pax_global_header00006660000000000000000000000064151502313230014505gustar00rootroot0000000000000052 comment=3e6de1df29d111c5fa5beb4c4294ef681978fd23 kalign-3.5.1/000077500000000000000000000000001515023132300127605ustar00rootroot00000000000000kalign-3.5.1/.claude/000077500000000000000000000000001515023132300142735ustar00rootroot00000000000000kalign-3.5.1/.claude/commands/000077500000000000000000000000001515023132300160745ustar00rootroot00000000000000kalign-3.5.1/.claude/commands/release.md000066400000000000000000000105541515023132300200430ustar00rootroot00000000000000Pre-release check and preparation for version $ARGUMENTS. Run ALL of the following checks in order. For each check, report PASS or FAIL. Fix issues automatically where possible, and ask before making changes that need judgment. ## 1. Validate version argument The user must provide a version in `X.Y.Z` format (e.g. `3.4.9`). If `$ARGUMENTS` is empty or not in the right format, stop and ask for the version number. ## 2. Check git state - Run `git status` — warn about uncommitted changes - Run `git tag -l "v$ARGUMENTS"` — verify the tag `v$ARGUMENTS` does not already exist - If the tag exists, warn and ask whether to continue ## 3. Check & fix version numbers All four files must contain the version `$ARGUMENTS`. Check each one and fix any that don't match: - **pyproject.toml**: `version = "$ARGUMENTS"` - **CMakeLists.txt**: `KALIGN_LIBRARY_VERSION_MAJOR`, `KALIGN_LIBRARY_VERSION_MINOR`, `KALIGN_LIBRARY_VERSION_PATCH` must match the three parts of `$ARGUMENTS` - **build.zig**: `kalignPackageVersion` string and the `KALIGN_PACKAGE_VERSION` in the cflags array must both be `"$ARGUMENTS"` - **CITATION.cff**: `version:` field must be `$ARGUMENTS` For any mismatches, fix them directly using the Edit tool and report what was changed. ## 4. Run linting (mirrors CI) Run these commands in sequence. If `black` or `isort` report formatting issues, auto-fix by running without `--check`: ``` uv run black --check python-kalign/ uv run isort --check-only python-kalign/ uv run flake8 python-kalign --select=E9,F63,F7,F82 ``` If black or isort fail the check, run the fix commands: ``` uv run black python-kalign/ uv run isort python-kalign/ ``` Then re-run the checks to confirm they pass. ## 5. Run Python tests ``` uv run pytest tests/python/ -v --no-header -q ``` Report the results. Note: there are some known pre-existing test failures in test_parameters.py and test_ecosystem_integration.py — flag any NEW failures beyond those. ## 6. Audit documentation — package name Search all files for bare `pip install kalign` that should be `pip install kalign-python`. Use grep to find: - Any `pip install kalign` NOT followed by `-python` - Specifically check: README files, python-docs/, python-examples/, python-kalign/ If any incorrect references are found, fix them. ## 7. Audit emails Extract the author email from `pyproject.toml` (the `authors` field). Then search all project files for email addresses and verify they are consistent. Check at minimum: - `python-kalign/__init__.py` (`__email__`) - `CITATION.cff` - `ChangeLog` (most recent entry) Report any mismatches. Do not hardcode any email — always extract the canonical email from pyproject.toml dynamically. ## 8. Check ChangeLog Read the `ChangeLog` file and check whether it contains an entry for `version $ARGUMENTS`. If an entry exists, report PASS. If NO entry exists: 1. Run `git log $(git describe --tags --abbrev=0)..HEAD --oneline` to get commits since the last tag 2. Read the existing ChangeLog to understand the format (date, author, email, version line, bullet points with changes) 3. Draft a new ChangeLog entry matching the existing format, using today's date and the author name and email from pyproject.toml 4. Present the draft to the user for approval or edits 5. Only after user approval, insert the entry at the top of the ChangeLog file ## 9. Build & verify Reinstall the package and verify the version: ``` uv pip install -e . uv run python -c "import kalign; print(kalign.__version__)" ``` Confirm the printed version matches `$ARGUMENTS`. If not, investigate and fix. ## 10. Summary Print a results table like this: ``` ## Release $ARGUMENTS — Pre-release Check Results | Check | Status | |------------------------|--------| | Git state | ... | | Version consistency | ... | | Linting (black) | ... | | Linting (isort) | ... | | Linting (flake8) | ... | | Python tests | ... | | Package name audit | ... | | Email consistency | ... | | ChangeLog | ... | | Build & version verify | ... | ``` Then, if all checks pass (or only known failures remain), ask the user: > All checks passed. Would you like me to: > 1. Commit all changes with message "Release vX.Y.Z" > 2. Create tag `vX.Y.Z` > 3. Push to remote > > Or pick individual steps? Wait for the user's response before taking any of those actions. kalign-3.5.1/.containerignore000066400000000000000000000001731515023132300161500ustar00rootroot00000000000000.git build benchmarks/data benchmarks/results __pycache__ *.pyc .venv *.egg-info .pytest_cache wheelhouse dist .mypy_cache kalign-3.5.1/.github/000077500000000000000000000000001515023132300143205ustar00rootroot00000000000000kalign-3.5.1/.github/workflows/000077500000000000000000000000001515023132300163555ustar00rootroot00000000000000kalign-3.5.1/.github/workflows/benchmark.yml000066400000000000000000000101721515023132300210330ustar00rootroot00000000000000name: Benchmark on: push: branches: [main] paths: - 'lib/**' - 'python-kalign/**' - 'benchmarks/**' - 'CMakeLists.txt' - '.github/workflows/benchmark.yml' pull_request: branches: [main] paths: - 'lib/**' - 'python-kalign/**' - 'benchmarks/**' - 'CMakeLists.txt' - '.github/workflows/benchmark.yml' workflow_dispatch: permissions: contents: write deployments: write jobs: benchmark: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install system dependencies run: | sudo apt-get update sudo apt-get install -y libomp-dev cmake - name: Build C binary run: | mkdir -p build cd build cmake .. make -j$(nproc) - name: Install Python package run: | python -m pip install --upgrade pip python -m pip install -e . - name: Cache BAliBASE dataset uses: actions/cache@v4 with: path: benchmarks/data/downloads key: benchmark-datasets-balibase-v1 - name: Run benchmarks run: | python -m benchmarks \ --dataset balibase \ --method python_api cli \ --binary build/src/kalign \ --output benchmarks/results/latest.json \ -v - name: Check if results were produced id: check_results run: | if [ -f benchmarks/results/latest.json ]; then echo "has_results=true" >> "$GITHUB_OUTPUT" else echo "::warning::No benchmark results produced (dataset download may have failed)" echo "has_results=false" >> "$GITHUB_OUTPUT" fi - name: Convert results for github-action-benchmark if: steps.check_results.outputs.has_results == 'true' run: | python -c " import json with open('benchmarks/results/latest.json') as f: data = json.load(f) entries = [] for method, stats in data.get('summary', {}).items(): entries.append({ 'name': f'SP Score Mean ({method})', 'unit': 'score', 'value': round(stats['sp_mean'], 2), 'range': f\"{stats['sp_min']:.1f}-{stats['sp_max']:.1f}\", }) entries.append({ 'name': f'Total Time ({method})', 'unit': 'seconds', 'value': round(stats['total_time'], 2), }) with open('benchmarks/results/benchmark_output.json', 'w') as f: json.dump(entries, f, indent=2) " - name: Store benchmark result if: github.ref == 'refs/heads/main' && steps.check_results.outputs.has_results == 'true' uses: benchmark-action/github-action-benchmark@v1 with: tool: 'customBiggerIsBetter' output-file-path: benchmarks/results/benchmark_output.json github-token: ${{ secrets.GITHUB_TOKEN }} gh-pages-branch: gh-pages benchmark-data-dir-path: dev/bench auto-push: true alert-threshold: '95%' comment-on-alert: true fail-on-alert: false - name: Compare with baseline (PRs only) if: github.event_name == 'pull_request' && steps.check_results.outputs.has_results == 'true' uses: benchmark-action/github-action-benchmark@v1 with: tool: 'customBiggerIsBetter' output-file-path: benchmarks/results/benchmark_output.json github-token: ${{ secrets.GITHUB_TOKEN }} gh-pages-branch: gh-pages benchmark-data-dir-path: dev/bench auto-push: false alert-threshold: '95%' comment-on-alert: true fail-on-alert: true - name: Upload results artifact if: steps.check_results.outputs.has_results == 'true' uses: actions/upload-artifact@v4 with: name: benchmark-results path: benchmarks/results/ kalign-3.5.1/.github/workflows/cmake.yml000066400000000000000000000050201515023132300201550ustar00rootroot00000000000000name: CMake on: push: branches: [ "main", "python" ] paths: - 'lib/**' - 'src/**' - 'tests/**' - 'CMakeLists.txt' - '.github/workflows/cmake.yml' pull_request: branches: [ "main" ] paths: - 'lib/**' - 'src/**' - 'tests/**' - 'CMakeLists.txt' - '.github/workflows/cmake.yml' jobs: build: name: Build C/C++ on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] build_type: [Release, Debug] steps: - uses: actions/checkout@v4 - name: Install dependencies (Ubuntu) if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y libomp-dev cmake - name: Install dependencies (macOS) if: runner.os == 'macOS' run: | brew install --formula libomp cmake - name: Configure CMake run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - name: Build run: cmake --build ${{github.workspace}}/build --config ${{ matrix.build_type }} --parallel 2 - name: Test working-directory: ${{github.workspace}}/build run: ctest -C ${{ matrix.build_type }} --output-on-failure - name: Test kalign executable run: | # Create test input echo ">seq1" > test.fasta echo "ATCGATCGATCG" >> test.fasta echo ">seq2" >> test.fasta echo "ATCGTCGATCG" >> test.fasta echo ">seq3" >> test.fasta echo "ATCGATCATCG" >> test.fasta # Test kalign executable ./build/src/kalign -i test.fasta -o test_output.fasta # Verify output exists and is not empty if [ -f test_output.fasta ] && [ -s test_output.fasta ]; then echo "✓ kalign executable test passed" else echo "✗ kalign executable test failed" exit 1 fi address-sanitizer: name: Address Sanitizer runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y libomp-dev cmake - name: Configure CMake with ASAN run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=ASAN - name: Build run: cmake --build ${{github.workspace}}/build --config ASAN --parallel 2 - name: Test with ASAN working-directory: ${{github.workspace}}/build run: ctest -C ASAN --output-on-failurekalign-3.5.1/.github/workflows/codeql-analysis.yml000066400000000000000000000037001515023132300221700ustar00rootroot00000000000000name: "CodeQL" on: push: branches: [main, python] pull_request: # The branches below must be a subset of the branches above branches: [main, python] schedule: - cron: '0 2 * * 4' jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: # Override automatic language detection by changing the below list # Supported options are ['c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'] language: ['c-cpp'] steps: - name: Checkout repository uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v3 # ℹï¸� Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # âœ�ï¸� If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # mkdir build && cd build # cmake .. # make - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" kalign-3.5.1/.github/workflows/python.yml000066400000000000000000000077211515023132300204300ustar00rootroot00000000000000name: Python on: push: branches: [ main, python ] paths: - 'python-kalign/**' - 'lib/**' - 'CMakeLists.txt' - 'pyproject.toml' - '.github/workflows/python.yml' pull_request: branches: [ main ] paths: - 'python-kalign/**' - 'lib/**' - 'CMakeLists.txt' - 'pyproject.toml' - '.github/workflows/python.yml' workflow_dispatch: jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: | python -m pip install --upgrade pip python -m pip install flake8 black isort mypy - name: Lint with flake8 run: | flake8 python-kalign --count --select=E9,F63,F7,F82 --show-source --statistics flake8 python-kalign --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Check formatting with black run: | black --check --diff python-kalign/ - name: Check import sorting with isort run: | isort --check-only --diff python-kalign/ test: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install system dependencies (Ubuntu) if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y libomp-dev cmake - name: Install system dependencies (macOS) if: runner.os == 'macOS' run: | brew install libomp cmake - name: Install Python dependencies run: | python -m pip install --upgrade pip python -m pip install pytest pytest-cov pytest-benchmark numpy - name: Build and install package run: | python -m pip install -e . - name: Test with pytest run: | pytest tests/python/ -v --cov=kalign --cov-report=xml --cov-report=term-missing - name: Upload coverage to Codecov if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' uses: codecov/codecov-action@v4 with: file: coverage.xml flags: python name: codecov-umbrella build-test: name: Build and test package runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install system dependencies (Ubuntu) if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y libomp-dev cmake - name: Install system dependencies (macOS) if: runner.os == 'macOS' run: | brew install libomp cmake - name: Install build dependencies run: | python -m pip install --upgrade pip python -m pip install build twine - name: Build package run: | python -m build - name: Check package run: | twine check dist/* - name: Test installation from wheel run: | python -m pip install dist/*.whl python -c "import kalign; print(f'kalign {kalign.__version__} installed successfully')" - name: Test basic functionality run: | python -c " import kalign sequences = ['ATCGATCG', 'ATCGTCG', 'ATCGATCG'] aligned = kalign.align(sequences, seq_type='dna') assert len(aligned) == 3 print('✓ Basic alignment test passed') "kalign-3.5.1/.github/workflows/wheels.yml000066400000000000000000000226031515023132300203720ustar00rootroot00000000000000name: Build Python Wheels on: push: branches: [ main, python ] tags: - 'v*' pull_request: branches: [ main ] paths: - 'python-kalign/**' - 'lib/**' - 'CMakeLists.txt' - 'pyproject.toml' - '.github/workflows/wheels.yml' workflow_dispatch: inputs: publish_target: description: "Publish target (manual runs only)" required: true default: "none" type: choice options: - none - testpypi jobs: build_wheels: name: Build wheels on ${{ matrix.os }} (${{ matrix.cibw_archs }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - os: ubuntu-latest cibw_archs: "x86_64" - os: macos-14 cibw_archs: "x86_64" - os: macos-14 cibw_archs: "arm64" steps: - uses: actions/checkout@v4 with: submodules: recursive - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: | python -m pip install --upgrade pip python -m pip install cibuildwheel build - name: Build wheels env: CIBW_BUILD: cp39-* cp310-* cp311-* cp312-* cp313-* CIBW_SKIP: "*-win32 *-manylinux_i686 *-musllinux*" CIBW_ARCHS: ${{ matrix.cibw_archs }} # Set minimum macOS version to match OpenMP requirements CIBW_ENVIRONMENT_MACOS: > CMAKE_BUILD_PARALLEL_LEVEL=2 OMP_NUM_THREADS=1 MACOSX_DEPLOYMENT_TARGET=14.0 CMAKE_OSX_DEPLOYMENT_TARGET=14.0 # Linux specific settings - handle different package managers CIBW_BEFORE_ALL_LINUX: > (yum install -y cmake3) || (apt-get update && apt-get install -y cmake) || (apk add --no-cache cmake) CIBW_REPAIR_WHEEL_COMMAND_LINUX: auditwheel repair -w {dest_dir} {wheel} # macOS specific settings CIBW_BEFORE_ALL_MACOS: | brew install --formula cmake libomp || echo "Dependencies may already be installed" CIBW_REPAIR_WHEEL_COMMAND_MACOS: > delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} # Environment variables for builds CIBW_ENVIRONMENT: > CMAKE_BUILD_PARALLEL_LEVEL=2 OMP_NUM_THREADS=1 # Skip testing during wheel build to avoid cross-compilation issues CIBW_TEST_SKIP: "*" run: | python -m cibuildwheel --output-dir wheelhouse - name: Upload wheels uses: actions/upload-artifact@v4 with: name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} path: wheelhouse/*.whl build_sdist: name: Build source distribution runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: recursive - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: | python -m pip install --upgrade pip python -m pip install build - name: Build sdist run: | python -m build --sdist --outdir dist/ - name: Upload sdist uses: actions/upload-artifact@v4 with: name: cibw-sdist path: dist/*.tar.gz test_install: name: Test wheel installation needs: [build_wheels] runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-14] python-version: ['3.9', '3.10', '3.11', '3.12'] steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Download wheels uses: actions/download-artifact@v4 with: pattern: cibw-wheels-* merge-multiple: true path: wheelhouse/ - name: Test installation and import run: | # Let pip find and install the appropriate wheel echo "=== Available wheels ===" ls -la wheelhouse/*.whl # Determine the distribution name from the wheel filenames (PEP 427) # e.g. kalign_test-3.4.5-...whl -> kalign-test DIST_NAME="$(ls wheelhouse/*.whl | head -n 1 | xargs basename | cut -d- -f1 | tr '_' '-')" echo "=== Detected dist name: ${DIST_NAME} ===" echo "=== Installing wheel ===" pip install --find-links wheelhouse/ "${DIST_NAME}" --force-reinstall # Check what got installed echo "=== Checking installed packages ===" pip list | grep -E 'kalign' || true # Check the kalign module structure echo "=== Checking kalign module ===" python -c " import sys print('Python version:', sys.version) print('Attempting to import kalign...') try: import kalign print('✓ kalign imported successfully') print('kalign location:', kalign.__file__) import os kalign_dir = os.path.dirname(kalign.__file__) print('kalign dir contents:', sorted(os.listdir(kalign_dir))) # Check for _core specifically core_files = [f for f in os.listdir(kalign_dir) if '_core' in f] print('_core files found:', core_files) except ImportError as e: print('✗ Import failed:', str(e)) import os import site print('Site packages:', site.getsitepackages()) for site_dir in site.getsitepackages(): kalign_path = os.path.join(site_dir, 'kalign') if os.path.exists(kalign_path): print(f'Found kalign at {kalign_path}') print('Contents:', sorted(os.listdir(kalign_path))) break sys.exit(1) " # Test the installation python -c " import kalign print('kalign version:', kalign.__version__) # Test basic functionality sequences = ['ATCGATCG', 'ATCGTCG', 'ATCGATCG'] aligned = kalign.align(sequences, seq_type='dna') print('Number of aligned sequences:', len(aligned)) print('Alignment lengths:', [len(seq) for seq in aligned]) assert len(aligned) == 3 assert all(len(seq) == len(aligned[0]) for seq in aligned) print('✓ Basic alignment test passed') # Test with different sequence types protein_seqs = ['MKTAYIAKQRQ', 'MKTAYIAKQ', 'MKTAYIAK'] aligned_proteins = kalign.align(protein_seqs, seq_type='protein') print('✓ Protein alignment test passed') print('All tests passed successfully!') " test_ecosystem: name: Test ecosystem integrations needs: [build_wheels] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.12' - uses: actions/download-artifact@v4 with: pattern: cibw-wheels-* merge-multiple: true path: wheelhouse/ - name: Install kalign with all extras run: | DIST_NAME="$(ls wheelhouse/*.whl | head -n 1 | xargs basename | cut -d- -f1 | tr '_' '-')" pip install --find-links wheelhouse/ "${DIST_NAME}[all]" --force-reinstall pip install pytest - name: Verify ecosystem packages are installed run: | python -c "import Bio; print(f'Biopython {Bio.__version__}')" python -c "import skbio; print(f'scikit-bio {skbio.__version__}')" python -c "import pandas; print(f'pandas {pandas.__version__}')" python -c "import matplotlib; print(f'matplotlib {matplotlib.__version__}')" - name: Run ecosystem tests (fail if any skipped) run: | pytest tests/python/test_ecosystem_real.py -v --tb=short 2>&1 | tee test_output.txt # Fail if any tests were skipped — all ecosystem deps should be present if grep -q "skipped" test_output.txt; then echo "ERROR: Some ecosystem tests were skipped — all deps should be installed" exit 1 fi upload_pypi: name: Upload to PyPI needs: [build_wheels, build_sdist, test_install, test_ecosystem] runs-on: ubuntu-latest if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') permissions: id-token: write environment: name: pypi steps: - name: Download all artifacts uses: actions/download-artifact@v4 with: pattern: cibw-* merge-multiple: true path: dist/ - name: Publish to PyPI (trusted publishing) uses: pypa/gh-action-pypi-publish@release/v1 with: packages_dir: dist/ upload_testpypi: name: Upload to TestPyPI needs: [build_wheels, build_sdist, test_install, test_ecosystem] runs-on: ubuntu-latest if: github.event_name == 'workflow_dispatch' && inputs.publish_target == 'testpypi' steps: - name: Download all artifacts uses: actions/download-artifact@v4 with: pattern: cibw-* merge-multiple: true path: dist/ - name: Publish to TestPyPI (API token) uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.TEST_PYPI_API_TOKEN }} packages_dir: dist/ repository-url: https://test.pypi.org/legacy/ verbose: true kalign-3.5.1/.gitignore000066400000000000000000000174051515023132300147570ustar00rootroot00000000000000# ============================================================================= # Mixed C/C++ and Python Project .gitignore # ============================================================================= # ----------------------------------------------------------------------------- # C/C++ Build Artifacts # ----------------------------------------------------------------------------- # Object files *.o *.obj *.elf # Shared libraries *.so *.so.* *.dylib *.dll # Static libraries *.a *.lib # Executables *.exe *.out *.app /kalign /kaligncpp kalign_*_test dssim # Debug symbols *.dSYM/ *.su *.idb *.pdb # Precompiled headers *.gch *.pch # Linker output *.ilk *.map *.exp # Build directories build/ build*/ build_*/ build_test_*/ .cache/ compile_commands.json # CMake CMakeCache.txt CMakeFiles/ CMakeScripts/ Testing/ Makefile cmake_install.cmake install_manifest.txt *.cmake !CMakeLists.txt CTestTestfile.cmake _deps/ # ----------------------------------------------------------------------------- # Zig Build System # ----------------------------------------------------------------------------- zig-out/ zig-cache/ .zig-cache/ # ----------------------------------------------------------------------------- # Python Development # ----------------------------------------------------------------------------- # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class *.pyc *.pyo *.pyd # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # 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/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # poetry # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. #pdm.lock # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it # in version control. # https://pdm.fming.dev/#use-with-ide .pdm.toml # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ # PyCharm # JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be added to the global gitignore or merged into this project gitignore. For a PyCharm # project, it is generally recommended to include this in version control. # https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this project gitignore. For a PyCharm # project, it is generally recommended to include this in version control. .idea/ # ----------------------------------------------------------------------------- # Python Package Building # ----------------------------------------------------------------------------- # scikit-build _skbuild/ # cibuildwheel wheelhouse/ # Build artifacts from setup.py build/ dist/ *.egg-info/ # ----------------------------------------------------------------------------- # Development Tools # ----------------------------------------------------------------------------- # Visual Studio Code .vscode/ *.code-workspace # Vim *.swp *.swo *~ # Emacs *~ \#*\# /.emacs.desktop /.emacs.desktop.lock *.elc auto-save-list tramp .\#* # Sublime Text *.sublime-workspace *.sublime-project # Xcode *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata/ *.moved-aside *.xccheckout *.xcscmblueprint # ----------------------------------------------------------------------------- # Operating System Files # ----------------------------------------------------------------------------- # macOS .DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear in the root of a volume .DocumentRevisions-V100 .fseventsd .Spotlight-V100 .TemporaryItems .Trashes .VolumeIcon.icns .com.apple.timemachine.donotpresent # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk # Windows Thumbs.db Thumbs.db:encryptable ehthumbs.db ehthumbs_vista.db # Dump file *.stackdump # Folder config file [Dd]esktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msix *.msm *.msp # Windows shortcuts *.lnk # Linux *~ # temporary files which can be created if a process still has a handle open of a deleted file .fuse_hidden* # KDE directory preferences .directory # Linux trash folder which might appear on any partition or disk .Trash-* # .nfs files are created when an open file is removed but is still being accessed .nfs* # ----------------------------------------------------------------------------- # Documentation and Archives (Keep Project Specific) # ----------------------------------------------------------------------------- # Keep project documentation but ignore generated docs !docs/ docs/_build/ docs/build/ # Archive directories (project specific - keep these) # doc/ # Commented out - this might be needed # dev/ # Commented out - this might be needed # old_src/ # Commented out - this might be needed # But ignore common archive patterns *.tar.gz *.tgz *.zip *.rar *.7z # ----------------------------------------------------------------------------- # Temporary and Cache Files # ----------------------------------------------------------------------------- # General temporary files *.tmp *.temp *.log *.bak *.backup # ----------------------------------------------------------------------------- # Project Specific # ----------------------------------------------------------------------------- # Test data outputs test_output/ *.out.fasta *.out.clustal *.out.msf # Benchmark results benchmark_results/ benchmarks/data/ benchmarks/results/ benchmarks/figures/ performance_*.txt # Profiling data *.prof gmon.out callgrind.out.* # Large test files (keep small test data) *.large.fasta test_data/large/ kalign-3.5.1/.gitmodules000066400000000000000000000000001515023132300151230ustar00rootroot00000000000000kalign-3.5.1/AUTHORS000066400000000000000000000000151515023132300140240ustar00rootroot00000000000000Timo Lassmannkalign-3.5.1/CITATION.cff000066400000000000000000000023271515023132300146560ustar00rootroot00000000000000cff-version: 1.2.0 message: "If you use this software, please cite it as below." type: software authors: - given-names: "Timo" family-names: "Lassmann" orcid: "https://orcid.org/0000-0002-0138-2691" title: "Kalign 3: multiple sequence alignment of large datasets" version: 3.5.1 date-released: 2026-02-27 url: "https://github.com/TimoLassmann/kalign" repository-code: "https://github.com/TimoLassmann/kalign" license: Apache-2.0 preferred-citation: type: article authors: - given-names: "Timo" family-names: "Lassmann" orcid: "https://orcid.org/0000-0002-0138-2691" title: "Kalign 3: multiple sequence alignment of large datasets" journal: "Bioinformatics" volume: 36 issue: 6 start: 1928 end: 1929 year: 2020 month: 3 day: 20 doi: "10.1093/bioinformatics/btz795" url: "https://academic.oup.com/bioinformatics/article/36/6/1928/5607735" publisher: name: "Oxford University Press" abstract: "Kalign is a fast multiple sequence alignment program for biological sequences (protein, DNA, RNA) with optimized algorithms and multi-threading support." keywords: - "multiple sequence alignment" - "bioinformatics" - "computational biology" - "sequence analysis" - "phylogenetics"kalign-3.5.1/CLAUDE.md000066400000000000000000000120631515023132300142410ustar00rootroot00000000000000# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Kalign is a fast multiple sequence alignment (MSA) program for biological sequences (protein, DNA, RNA) written in C. The project uses CMake as the primary build system with Zig as an alternative for cross-compilation. ## Build Commands ### CMake Build (Primary) ```bash mkdir build cd build cmake .. make make test make install ``` ### Debug Build ```bash mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Debug .. make ``` ### Address Sanitizer Build ```bash mkdir build cd build cmake -DCMAKE_BUILD_TYPE=ASAN .. make ``` ### Build Without OpenMP ```bash mkdir build cd build cmake -DUSE_OPENMP=OFF .. make ``` ### Zig Build (Alternative) ```bash zig build ``` ## Testing ### Run All Tests ```bash make test # or ctest ``` ### Run Specific Test ```bash ctest -R ``` ### Test Executables - `kalign_io_test` - I/O functionality tests - `kalign_lib_test` - Library API tests - `kalign_cmp_test` - Comparison tests - `kaligncpp` - C++ API tests - `dssim` - Distance similarity tests ## Code Architecture ### Directory Structure - `lib/` - Core library implementation - `src/` - Library source files (alignment algorithms, I/O, utilities) - `include/kalign/` - Public API headers - `src/` - Main executable (command-line interface) - `tests/` - Test suite with biological sequence data ### Key Components #### Alignment Engine (`lib/src/aln_*.c`) - `aln_seqseq.c` - Sequence-to-sequence alignment - `aln_seqprofile.c` - Sequence-to-profile alignment - `aln_profileprofile.c` - Profile-to-profile alignment - `aln_controller.c` - Alignment orchestration - `bpm.c` - Bit-parallel matching (Myers' algorithm) #### I/O System (`lib/src/msa_*.c`) - `msa_io.c` - Multi-format sequence reading/writing (FASTA, MSF, Clustal) - `msa_alloc.c` - Memory management for sequence data - `msa_op.c` - Sequence operations and manipulations #### Distance Calculations - `sequence_distance.c` - Sequence distance metrics - `euclidean_dist.c` - Euclidean distance calculations - `bisectingKmeans.c` - K-means clustering for guide tree construction #### Utilities - `tldevel.c` - Development utilities and debugging - `tlmisc.c` - Miscellaneous helper functions - `alphabet.c` - Sequence alphabet handling (DNA, RNA, protein) - `task.c` - Task scheduling and threading support ### Performance Features - **Multi-threading**: OpenMP parallelization - **SIMD**: SSE4.1, AVX, AVX2 optimizations (enabled by default) - **Bit-parallel algorithms**: Myers' algorithm for efficient alignment - **Memory optimization**: Custom allocation strategies ### API Usage The library provides a C API (`kalign.h`) with C++ compatibility. Key functions: - Reading sequences from files - Running alignments with different parameters - Writing results in various formats - Memory management helpers ### Build Configuration - C11 standard required - OpenMP support (can be disabled with `-DUSE_OPENMP=OFF`) - SIMD instruction support with runtime detection - Multiple build types: Release, Debug, ASAN (Address Sanitizer) - Cross-compilation support via Zig build system ### Testing Strategy - Unit tests for core components (BPM, distance calculations, I/O) - Integration tests using Balibase sequence datasets - C++ API compatibility tests - Performance benchmarks - Format conversion tests (FASTA, MSF, Clustal) ## Python Module The repository includes a Python package that provides Python bindings for the Kalign library. The Python package is configured at the root level using modern Python packaging standards. ### Python Development Commands #### Install in Development Mode (Recommended) ```bash uv pip install -e . ``` #### Build Python Package Locally ```bash uv run python -m build ``` #### Build with CMake (for debugging C extensions) ```bash mkdir build cd build cmake -DBUILD_PYTHON_MODULE=ON .. make ``` #### Test Python Package ```bash uv run python -c "import kalign; print(kalign.__version__); seqs=['ATCG','ATCGG']; print(kalign.align(seqs))" ``` #### Run Python Tests ```bash uv run pytest tests/python/ -v ``` #### Build Wheels for Distribution ```bash uv run python -m cibuildwheel --output-dir wheelhouse ``` ### Python Package Structure - `python-kalign/__init__.py` - High-level Python API - `python-kalign/_core.cpp` - pybind11 C++ bindings - `pyproject.toml` - Modern Python build configuration (at root level) - `README-python.md` - Python-specific documentation - `tests/python/` - Python test suite ### Python API Features - **Simple interface**: `kalign.align(sequences, seq_type="auto")` - **File support**: `kalign.align_from_file("file.fasta")` - **Parameter control**: Gap penalties, threading, sequence types - **Error handling**: Python exceptions for C library errors - **Memory safety**: Automatic memory management through pybind11 ### GitHub Actions Integration The `.github/workflows/wheels.yml` workflow: - Builds wheels for Linux, macOS, Windows - Tests multiple Python versions (3.9-3.13) - Uses cibuildwheel for cross-platform compatibility - Publishes to PyPI on tagged releaseskalign-3.5.1/CMakeLists.txt000066400000000000000000000253401515023132300155240ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.18) project(kalign LANGUAGES C CXX) set(NAMESPACE_NAME "kalign") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) option(BUILD_SHARED_LIBS "Build the shared library" ON) include(GNUInstallDirs) include(CMakePackageConfigHelpers) include(GenerateExportHeader) set(KALIGN_LIBRARY_VERSION_MAJOR 3) set(KALIGN_LIBRARY_VERSION_MINOR 5) set(KALIGN_LIBRARY_VERSION_PATCH 1) set(KALIGN_LIBRARY_VERSION_STRING ${KALIGN_LIBRARY_VERSION_MAJOR}.${KALIGN_LIBRARY_VERSION_MINOR}.${KALIGN_LIBRARY_VERSION_PATCH}) set (CMAKE_C_STANDARD 11) # SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg") # SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -pg") # SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") # SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg") # to compile without open mp: # cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DUSE_OPENMP=OFF .. # Compiler-specific flags if(MSVC) add_compile_options("$<$:/W3;/O2>") add_compile_options("$<$:/W3;/Od;/Zi>") else() add_compile_options("$<$:-W;-Wall;-O3;-pedantic>") add_compile_options("$<$:-W;-Wall;-O0;-g;-pedantic>") add_compile_options("$<$:-W;-Wall;-Wextra;-O0;-g;-DDEBUG;-pedantic;-ffunction-sections;-fdata-sections;-fstack-protector-strong;-fsanitize=address>") endif() if(CMAKE_BUILD_TYPE MATCHES ASAN AND NOT MSVC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") endif() if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) if (MSVC) # warning level 3 for Windows builds (level 4 too strict for wheel builds) add_compile_options(/W3) else() # lots of warnings and all warnings as errors add_compile_options(-Wall -Wextra -pedantic ) endif() endif() if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() include(GNUInstallDirs) include(CTest) include(CheckCSourceRuns) option(USE_OPENMP "Use OpenMP for parallelization" ON) option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON) option(ENABLE_AVX "Enable compile-time AVX support." ON) option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON) # Performance tuning parameters set(KALIGN_ALN_SERIAL_THRESHOLD "250" CACHE STRING "Alignment positions threshold below which to use serial instead of parallel processing") set(KALIGN_KMEANS_UPGMA_THRESHOLD "50" CACHE STRING "Number of sequences threshold below which to use UPGMA instead of parallel k-means") # option(ENABLE_FMA "Enable compile-time FMA support." ON) # option(ENABLE_AVX512 "Enable compile-time AVX512 support." ON) if(USE_OPENMP) # Configure OpenMP for macOS with Homebrew (only for arm64 native builds) if(APPLE AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm64" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") list(APPEND CMAKE_PREFIX_PATH /opt/homebrew) # Set OpenMP flags for Apple Clang + Homebrew libomp set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp -I/opt/homebrew/opt/libomp/include") set(OpenMP_C_LIB_NAMES "omp") set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I/opt/homebrew/opt/libomp/include") set(OpenMP_CXX_LIB_NAMES "omp") set(OpenMP_omp_LIBRARY /opt/homebrew/opt/libomp/lib/libomp.dylib) endif() find_package(OpenMP) if(OPENMP_FOUND OR OpenMP_FOUND) message(STATUS "OpenMP is enabled.") add_definitions (-DHAVE_OPENMP) else(OPENMP_FOUND OR OpenMP_FOUND) message(STATUS "OpenMP not supported") endif(OPENMP_FOUND OR OpenMP_FOUND) endif(USE_OPENMP) if (ENABLE_SSE) # # Check compiler for SSE4_1 intrinsics # if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) set(CMAKE_REQUIRED_FLAGS "-msse4.1") check_c_source_runs(" #include #include int main() { __m128i a = _mm_setzero_si128(); __m128i b = _mm_minpos_epu16(a); return 0; }" HAVE_SSE) endif() if (HAVE_SSE) message(STATUS "SSE4.1 is enabled - target CPU must support it") endif() if (ENABLE_AVX) # # Check compiler for AVX intrinsics # if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) set(CMAKE_REQUIRED_FLAGS "-mavx") check_c_source_runs(" #include int main() { __m256 a, b, c; const float src[8] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f }; float dst[8]; a = _mm256_loadu_ps( src ); b = _mm256_loadu_ps( src ); c = _mm256_add_ps( a, b ); _mm256_storeu_ps( dst, c ); int i = 0; for( i = 0; i < 8; i++ ){ if( ( src[i] + src[i] ) != dst[i] ){ return -1; } } return 0; }" HAVE_AVX) endif() if (HAVE_AVX) message(STATUS "AVX is enabled - target CPU must support it") endif() endif() if (ENABLE_AVX2) # # Check compiler for AVX intrinsics # if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) set(CMAKE_REQUIRED_FLAGS "-mavx2") check_c_source_runs(" #include int main() { __m256i a, b, c; const int src[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; int dst[8]; a = _mm256_loadu_si256( (__m256i*)src ); b = _mm256_loadu_si256( (__m256i*)src ); c = _mm256_add_epi32( a, b ); _mm256_storeu_si256( (__m256i*)dst, c ); int i = 0; for( i = 0; i < 8; i++ ){ if( ( src[i] + src[i] ) != dst[i] ){ return -1; } } return 0; }" HAVE_AVX2) endif() if (HAVE_AVX2) message(STATUS "AVX2 is enabled - target CPU must support it") endif() endif() endif() if (HAVE_AVX2) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx2 -DHAVE_AVX2") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx2 -DHAVE_AVX2") else(HAVE_AVX2) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOHAVE_AVX2") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNOHAVE_AVX2") endif(HAVE_AVX2) # Add performance tuning parameters as compile definitions add_definitions(-DKALIGN_ALN_SERIAL_THRESHOLD=${KALIGN_ALN_SERIAL_THRESHOLD}) add_definitions(-DKALIGN_KMEANS_UPGMA_THRESHOLD=${KALIGN_KMEANS_UPGMA_THRESHOLD}) add_subdirectory(lib) add_subdirectory(src) add_subdirectory(tests) # Python module build (optional) ########################################## option(BUILD_PYTHON_MODULE "Build Python extension module" OFF) if(BUILD_PYTHON_MODULE) # Find pybind11 - scikit-build-core will provide this find_package(pybind11 CONFIG) if(pybind11_FOUND) message(STATUS "Building Python extension module") # Create the Python extension module pybind11_add_module(_core python-kalign/_core.cpp tests/dssim.c ) # Link against the static kalign library target_link_libraries(_core PRIVATE kalign_static) # Link OpenMP if found if(OpenMP_CXX_FOUND) target_link_libraries(_core PRIVATE OpenMP::OpenMP_CXX) endif() # Add include directories for DSSim and lib headers target_include_directories(_core PRIVATE tests lib/src lib/include ) # Set properties for the Python module set_target_properties(_core PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF ) # Install only the Python module (no shared library needed with static linking) install(TARGETS _core LIBRARY DESTINATION kalign COMPONENT python) # Install Python source files install(DIRECTORY python-kalign/ DESTINATION kalign COMPONENT python FILES_MATCHING PATTERN "*.py" PATTERN "*.typed") message(STATUS "Python extension module configured") else() message(WARNING "pybind11 not found - Python module will not be built") endif() else() message(STATUS "Python module build disabled (use -DBUILD_PYTHON_MODULE=ON to enable)") endif() # Benchmark target ############################################################ # Runs BAliBASE benchmarks comparing the C binary and the Python API. # Requires: pip install -e . (to make the kalign Python package available) # # Usage: # make benchmark # full BAliBASE suite, both methods # make benchmark BENCH_MAX_CASES=5 # quick smoke test with 5 cases # find_package(Python3 COMPONENTS Interpreter QUIET) if(Python3_FOUND) set(BENCH_MAX_CASES "0" CACHE STRING "Max benchmark cases (0 = all)") add_custom_target(benchmark COMMAND ${CMAKE_COMMAND} -E echo "Running kalign benchmarks..." COMMAND ${Python3_EXECUTABLE} -m benchmarks --dataset balibase --method python_api cli --binary $ --max-cases ${BENCH_MAX_CASES} --output ${CMAKE_SOURCE_DIR}/benchmarks/results/latest.json -v DEPENDS kalign-bin WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Benchmarking kalign (C binary vs Python API)" VERBATIM ) endif() MESSAGE(STATUS "") MESSAGE(STATUS "Configuration:") MESSAGE(STATUS "--------------------------------------") MESSAGE(STATUS "Build type : " ${CMAKE_BUILD_TYPE}) MESSAGE(STATUS "Compiler flags : " ${CMAKE_C_COMPILE_FLAGS}) MESSAGE(STATUS "Compiler c debug flags : " ${CMAKE_C_FLAGS_DEBUG}) MESSAGE(STATUS "Compiler c release flags : " ${CMAKE_C_FLAGS_RELEASE}) MESSAGE(STATUS "Compiler c min size flags : " ${CMAKE_C_FLAGS_MINSIZEREL}) MESSAGE(STATUS "Compiler c flags : " ${CMAKE_C_FLAGS}) message(STATUS "OpenMP version : " ${OpenMP_C_VERSION}) message(STATUS "OpenMP flags : " ${OpenMP_C_FLAGS}) # Package Generator ####################################################### set(CPACK_PACKAGE_VENDOR "Timo Lassmann") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Kalign") set(CPACK_PACKAGE_VERSION_MAJOR ${KALIGN_LIBRARY_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${KALIGN_LIBRARY_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${KALIGN_LIBRARY_VERSION_PATCH}) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") # set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.org") set(CPACK_SOURCE_GENERATOR "TGZ;ZIP") set(CPACK_SOURCE_IGNORE_FILES /.cache /.git /GPATH /GTAGS /GRTAGS /.*build.* /.dir-locals.el /\\\\.DS_Store ) include (CPack) kalign-3.5.1/CONTRIBUTING.md000066400000000000000000000162251515023132300152170ustar00rootroot00000000000000# Contributing to Kalign First off, thank you for considering contributing to Kalign! It's people like you that make Kalign such a powerful multiple sequence alignment tool for the bioinformatics community. ## Table of Contents - [Code of Conduct](#code-of-conduct) - [How Can I Contribute?](#how-can-i-contribute) - [Getting Started](#getting-started) - [Development Environment Setup](#development-environment-setup) - [Pull Request Process](#pull-request-process) - [Issue Guidelines](#issue-guidelines) - [Coding Standards](#coding-standards) - [Testing](#testing) - [Community](#community) ## Code of Conduct This project and everyone participating in it is governed by our commitment to providing a welcoming and inclusive environment. By participating, you are expected to uphold high standards of respectful communication and collaboration. **Our Standards:** - Use welcoming and inclusive language - Be respectful of differing viewpoints and experiences - Gracefully accept constructive criticism - Focus on what is best for the community - Show empathy towards other community members ## How Can I Contribute? ### Types of Contributions Welcome We welcome many different types of contributions: - **Bug reports and fixes** - Help us identify and resolve issues - **Performance improvements** - Optimizations for speed and memory usage - **New features** - Alignment algorithms, output formats, or usability enhancements - **Documentation** - API docs, tutorials, examples, or README improvements - **Testing** - Writing tests, testing on different platforms, benchmarking - **Python bindings** - Improvements to the Python package - **Build system** - CMake, Zig, CI/CD improvements ### What We're NOT Looking For Please don't use the issue tracker for: - Support questions (use discussions instead) - Feature requests that fundamentally change Kalign's core purpose - Issues related to third-party tools or dependencies ## Getting Started ### Your First Contribution Unsure where to begin? You can start by looking through these issues: - **Good first issue** - Issues that are good for newcomers - **Help wanted** - Issues that need attention from the community Never made an open source contribution before? Here are some helpful resources: - [First Timers Only](https://www.firsttimersonly.com/) - [How to Contribute to an Open Source Project on GitHub](https://opensource.guide/how-to-contribute/) ### Before You Start For large changes, please open an issue first to discuss what you would like to change. This helps ensure your contribution aligns with the project's goals and avoids duplicate work. ## Development Environment Setup ### Prerequisites - **C compiler** - GCC, Clang, or MSVC - **CMake** (3.18 or higher) - **Git** - **OpenMP** (optional, for parallelization) ### Optional Dependencies - **Zig** (for alternative build system) - **Python** (3.9+ for Python bindings) - **pybind11** (for Python module development) ### Building from Source ```bash # Clone your fork git clone https://github.com/yourusername/kalign.git cd kalign # Create build directory mkdir build && cd build # Configure and build cmake .. make # Run tests make test ``` ### Python Development ```bash cd python pip install -e . python -c "import kalign; print(kalign.__version__)" ``` ## Pull Request Process 1. **Fork** the repository and create your branch from `main` 2. **Make your changes** following our coding standards 3. **Add tests** for any new functionality 4. **Update documentation** if you change APIs or add features 5. **Ensure tests pass** locally before submitting 6. **Submit a pull request** with a clear description ### Pull Request Guidelines - **One feature per PR** - Keep changes focused and atomic - **Clear commit messages** - Use descriptive commit messages - **Link related issues** - Reference any related issue numbers - **Update CHANGELOG** - Add a brief description of your changes - **Cross-platform compatibility** - Ensure changes work on Linux, macOS, and Windows ## Issue Guidelines ### Bug Reports When reporting bugs, please include: - **Kalign version** - Output of `kalign --version` - **Operating system** - Including version - **Build information** - How you installed/built Kalign - **Input data** - Sample sequences that trigger the bug (if possible) - **Expected behavior** - What you expected to happen - **Actual behavior** - What actually happened - **Error messages** - Complete error output - **Steps to reproduce** - Minimal steps to trigger the issue ### Feature Requests When suggesting features: - **Use case** - Describe the problem you're trying to solve - **Proposed solution** - How you envision the feature working - **Alternatives** - Other approaches you've considered - **Impact** - Who would benefit from this feature ### Performance Issues For performance problems: - **Input size** - Number and length of sequences - **System specs** - CPU, RAM, OS - **Timing data** - How long operations take - **Comparison** - Performance with other tools (if applicable) ## Coding Standards ### C Code Style - **Indentation** - Use spaces, not tabs (consistent with existing code) - **Naming** - Use descriptive variable and function names - **Comments** - Document complex algorithms and non-obvious code - **Memory management** - Always check malloc/free pairs - **Error handling** - Use consistent error checking patterns ### Python Code Style - **PEP 8** - Follow Python style guidelines - **Type hints** - Use type annotations for function signatures - **Docstrings** - Document all public functions and classes ### Commit Message Format ``` type(scope): brief description Detailed explanation if needed Fixes #issue_number ``` Examples: - `fix(alignment): handle empty sequences correctly` - `feat(python): add support for custom gap penalties` - `docs(readme): update installation instructions` ## Testing ### Running Tests ```bash # C/C++ tests cd build make test # Python tests cd python python -m pytest ``` ### Test Requirements - **All tests must pass** before submitting PRs - **Add tests** for new features and bug fixes - **Cross-platform testing** - Test on different operating systems when possible - **Performance tests** - Include benchmarks for performance-critical changes ### Test Data Use the provided test sequences in `tests/data/` or create minimal test cases. For large datasets, provide instructions for users to download test data separately. ## Community ### Getting Help - **GitHub Discussions** - For questions and general discussion - **Issues** - For bug reports and feature requests - **Email** - Contact the maintainer for security issues ### Recognition Contributors are recognized in: - **AUTHORS file** - All contributors are listed - **Release notes** - Significant contributions are highlighted - **Paper acknowledgments** - For substantial algorithmic contributions ## License By contributing to Kalign, you agree that your contributions will be licensed under the Apache License 2.0. ## Questions? Don't hesitate to ask! The worst thing that can happen is that you'll be politely asked to change something. We appreciate any sort of contribution and don't want a wall of rules to get in the way of that. Thank you for contributing to Kalign! 🧬kalign-3.5.1/COPYING000066400000000000000000000260321515023132300140160ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to the Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by the Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding any notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. Please also get an OpenSSF Best Practices badge (https://www.bestpractices.dev/) to show that the project follows best practices. Copyright 2006-2026 Timo Lassmann Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. kalign-3.5.1/ChangeLog000066400000000000000000000147321515023132300145410ustar00rootroot000000000000002026-02-27 Timo Lassmann * version 3.5.1 - Bugfix release - Fix memory leak in build_tree_from_pairwise (realign/ensemble) - Move seaborn from core to optional dependency - Fix benchmark workflow to handle unavailable datasets gracefully - Black formatting fixes * version 3.5.0 - Three modes Kalign now has three modes: default (best general-purpose), fast (same as v3.4), and precise (ensemble, highest accuracy, ~10x slower). - Ensemble alignment (--precise or --ensemble N) - Per-column confidence scores from ensemble mode - Ensemble consensus save/load (--save-poar, --load-poar) - Alignment refinement (--refine) - PFASUM substitution matrices (--type pfasum, pfasum43, pfasum60) - stdin via -i - convention (samtools/bcftools style) - Python align() now supports all parameters (mode, ensemble, etc.) - License changed from GPL-3.0-or-later to Apache-2.0 - Fixed crash in Python align() on Linux (uninitialized MSA fields) - Fixed selenocysteine (U) handling in reduced alphabet (Debian #1127766) 2026-02-10 Timo Lassmann * version 3.4.9 - Updated documentation to use kalign-python package name - Added claude code release command 2024-04-24 Timo Lassmann * version 3.4.1 - Fixed an issue when kalign is given hundreds of identical sequences. - added build.zig 2023-12-10 Timo Lassmann * version 3.4.0 - Added a simple sequence simulator for testing - Fixed an issue where alignments would be slighly different depending on the number of threads used. 2022-11-05 Timo Lassmann * version 3.3.5 - Added a check to find and remove sequences of length 0. 2022-10-28 Timo Lassmann * version 3.3.4 - Cmake and more - switched to cmake Added: 1) a Kalign library to make it easier to use Kalign from another projects 2) a block version of Gene Myers bit parallel string matching code (described here: Myers, Gene. "A fast bit-vector algorithm for approximate string matching based on dynamic programming." Journal of the ACM (JACM) 46.3 (1999): 395-415). This means Kalign will now run equivalently on processors with and without AVX2 instructions (e.g. Apple M1 / M2 and ARM chips). 3) alignment types giving users more control over alignment parameters. 4) multi-threading 2022-03-21 Timo Lassmann * version 3.3.2 - Bug Fix There was a bug in building a guide tree from highly similar sequences. The fix was involved distributing identical sequences equally among branches. This only happened when there were thousands of identical sequences. In addition Kalign now compiles on Apple's M1 chip and possibly on other ARM architectures as well (although I did not test the latter). 2021-04-16 Timo Lassmann * version 3.3.1 - Bug Fix The previous version kalign checked the top 50 sequences in inputs to determine whether the sequences are aligned or not. If the first 50 sequences are not aligned, but following sequences contain gaps (or other characters!) kalign can crash. In this version (3.3.1) kalign checks all sequences, thereby avoiding this issue. To alert users to the situation described above and to warn users about the presence of odd characters, kalign now produces a warning message like this: [Date Time] : LOG : Start io tests. [Date Time] : LOG : reading: dev/data/a2m.good.1 [Date Time] : LOG : Detected protein sequences. [Date Time] : WARNING : -------------------------------------------- (rwalign.c line 505) [Date Time] : WARNING : The input sequences contain gap characters: (rwalign.c line 506) [Date Time] : WARNING : "-" : 36 found (rwalign.c line 510) [Date Time] : WARNING : BUT the sequences do not seem to be aligned! (rwalign.c line 514) [Date Time] : WARNING : (rwalign.c line 515) [Date Time] : WARNING : Kalign will remove the gap characters and (rwalign.c line 516) [Date Time] : WARNING : align the sequences. (rwalign.c line 517) [Date Time] : WARNING : -------------------------------------------- (rwalign.c line 518) 2020-11-06 Timo Lassmann * version 3.3 - Threading and more - Kalign now runs pairwise distance estimation, guide tree building and alignments in parallel. - Memory optimisations. - Optimised bi-sectional K-means algorithm. - added -clean option to check for sequences with identical names but different sequences. - fixed minor bug in alignment I/O module 2020-09-24 Timo Lassmann * version 3.2.7 - Development version - dynamic programming in now more modular. - fixed rare bug in alignment input / output - added gap parameters (--gpo, --gpe, --tgpe) - for protein alignment I now use the CorBLOSUM66_13plus matrix from: Hess M, Keul F, Goesele M, Hamacher K. Addressing inaccuracies in BLOSUM computation improves homology search performance. BMC bioinformatics. 2016 Dec 1;17(1):189. with the empirically derived gap penalties. 2020-04-22 Timo Lassmann * version 3.2.5 - Bug fix: when given long output named the first lines in msf output could be truncated. 2020-04-01 Timo Lassmann * version 3.2.4 - Fixed issue relating to stdin input on clusters. - Added more sanity checks 2020-03-16 Timo Lassmann * version 3.2.3 - replaced timing code with code from the easel lib. 2020-02-23 Timo Lassmann * version 3.2.2 - Fixed minor bug in rwaln test routine. It assumed that input alignments were correctly formatted (which was not true for one test case). The kalign executable was never affected by this. - Added a script to test a few alignments. 2020-02-22 Timo lassmann * version 3.2.1 minor bug fix removed "-lrt" required for old glibc versions and replaced with a search in configure.ac: AC_SEARCH_LIBS([clock_gettime],[rt]) 2020-02-15 Timo Lassmann * version 3.2.0 Added support for reading sequences from standard input: cat file.fasta | kalign -f fasta | .... Added support for combining multiple input files into one alignment: kalign sequencesA.fa sequencesB.fa > msa.fa Also works in combination: cat file.fasta | kalign sequencesA.fa sequencesB.fa > msa.fa Minor: - added m4 macros to enable / disable compiler flags - added m4 macro for valgrind. Now there is a make target called check-valgrind that run all tests through valgrind. kalign-3.5.1/Containerfile000066400000000000000000000050421515023132300154660ustar00rootroot00000000000000# Kalign Benchmark Container # # Includes kalign, Clustal Omega, MAFFT, and MUSCLE v5 for comparative # benchmarking on BAliBASE, BRAliBASE, and BaliFam100 datasets. # # Build: # podman build -t kalign-benchmark . # # Run the interactive dashboard: # podman run -it -p 8050:8050 \ # -v ./benchmarks/data:/kalign/benchmarks/data \ # kalign-benchmark # # Run a CLI benchmark: # podman run -it \ # -v ./benchmarks/data:/kalign/benchmarks/data \ # kalign-benchmark \ # python -m benchmarks \ # --dataset balibase --method python_api clustalo mafft muscle -v # # View results in the dashboard after a CLI run: # podman run -it -p 8050:8050 \ # -v ./benchmarks/data:/kalign/benchmarks/data \ # -v ./benchmarks/results:/kalign/benchmarks/results \ # kalign-benchmark FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive # System dependencies + alignment tools (clustalo, mafft from apt) RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential cmake g++ git curl \ python3 python3-pip python3-venv python3-dev \ clustalo mafft \ pkg-config \ && rm -rf /var/lib/apt/lists/* # ---------- Build MUSCLE v5 from source ---------- # myutils.h checks __arm64__ (macOS) but not __aarch64__ (Linux); add it RUN cd /tmp && \ git clone --depth 1 https://github.com/rcedgar/muscle.git && \ cd muscle/src && \ sed -i 's/defined(__arm64__)/defined(__arm64__) || defined(__aarch64__)/' myutils.h && \ bash build_linux.bash && \ cp ../bin/muscle /usr/local/bin/ && \ rm -rf /tmp/muscle # ---------- Copy kalign source and build ---------- COPY . /kalign WORKDIR /kalign RUN mkdir -p build && cd build && \ cmake -DCMAKE_BUILD_TYPE=Release .. && \ make -j"$(nproc)" # ---------- Python environment ---------- RUN python3 -m venv /venv ENV PATH="/venv/bin:/kalign/build/src:$PATH" RUN pip install --no-cache-dir uv && \ uv pip install --no-cache -e ".[benchmark]" # ---------- Verify tools ---------- RUN which kalign && which clustalo && which mafft && which muscle # ---------- Data & results directories ---------- RUN mkdir -p /kalign/benchmarks/data/downloads /kalign/benchmarks/results # ---------- Hot-swap: cross-compiled kalign binary (last for fast rebuilds) ---------- COPY zig-out/kalign-linux-aarch64 /usr/local/bin/kalign RUN chmod +x /usr/local/bin/kalign # Rebuild Python module with latest source (uses cached venv layer) RUN uv pip install --no-cache -e ".[benchmark]" EXPOSE 8050 CMD ["python", "-m", "benchmarks.app", "--host", "0.0.0.0", "--port", "8050"] kalign-3.5.1/Containerfile.downstream000066400000000000000000000175451515023132300176630ustar00rootroot00000000000000# Kalign Downstream Benchmark Container # # Extends the base benchmark setup with tools for downstream application # benchmarks: positive selection (HyPhy), phylogenetics (IQ-TREE), # homology detection (HMMER), and confidence comparison (GUIDANCE2). # # Build: # podman build -f Containerfile.downstream -t kalign-downstream . # # Run all downstream benchmarks: # podman run -it \ # -v ./benchmarks/data:/kalign/benchmarks/data \ # -v ./benchmarks/results:/kalign/benchmarks/results \ # kalign-downstream \ # python -m benchmarks.downstream --all -j 4 # # Quick smoke test (5 cases per pipeline): # podman run -it \ # -v ./benchmarks/data:/kalign/benchmarks/data \ # -v ./benchmarks/results:/kalign/benchmarks/results \ # kalign-downstream \ # python -m benchmarks.downstream --all -j 4 --quick # # Generate figures from existing results: # podman run -it \ # -v ./benchmarks/results:/kalign/benchmarks/results \ # -v ./benchmarks/figures:/kalign/benchmarks/figures \ # kalign-downstream \ # python -m benchmarks.downstream --figures -o benchmarks/figures/ FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive # ── System dependencies ────────────────────────────────────────────── RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential cmake g++ git curl wget ca-certificates \ python3 python3-pip python3-venv python3-dev \ pkg-config zlib1g-dev libcurl4-openssl-dev libssl-dev libeigen3-dev libboost-dev \ clustalo mafft hmmer \ perl libwww-perl libbio-perl-perl cpanminus \ && rm -rf /var/lib/apt/lists/* # Bio::Perl convenience module (removed from BioPerl core in 1.7.x) RUN cpanm --notest Bio::Perl # ── MUSCLE v5 from source ─────────────────────────────────────────── # myutils.h checks __arm64__ (macOS) but not __aarch64__ (Linux); add it RUN cd /tmp && \ git clone --depth 1 https://github.com/rcedgar/muscle.git && \ cd muscle/src && \ sed -i 's/defined(__arm64__)/defined(__arm64__) || defined(__aarch64__)/' myutils.h && \ bash build_linux.bash && \ cp ../bin/muscle /usr/local/bin/ && \ rm -rf /tmp/muscle # ── INDELible v1.03 from source ───────────────────────────────────── RUN cd /tmp && \ git clone --depth 1 https://github.com/matsengrp/indelible.git && \ cd indelible/src && \ make && \ cp indelible /usr/local/bin/ && \ rm -rf /tmp/indelible # ── HyPhy from source ─────────────────────────────────────────────── RUN cd /tmp && \ git clone --depth 1 https://github.com/veg/hyphy.git && \ cd hyphy && \ cmake -DCMAKE_BUILD_TYPE=Release -DNOAVX=ON . && \ make -j"$(nproc)" hyphy && \ cp hyphy /usr/local/bin/hyphy && \ cp -r res /usr/local/lib/hyphy && \ rm -rf /tmp/hyphy ENV HYPHY_LIB=/usr/local/lib/hyphy ENV HYPHY_PATH=/usr/local/lib/hyphy # ── IQ-TREE 2 from source ─────────────────────────────────────────── RUN cd /tmp && \ git clone --depth 1 --recurse-submodules https://github.com/iqtree/iqtree2.git && \ cd iqtree2 && \ mkdir build && cd build && \ cmake -DCMAKE_BUILD_TYPE=Release .. && \ make -j"$(nproc)" && \ cp iqtree2 /usr/local/bin/ && \ rm -rf /tmp/iqtree2 # ── GUIDANCE2 from GitHub (original tar.gz URL is dead) ──────────── # guidance.pl uses FindBin-relative paths ($Bin, $Bin/../Selecton, etc.) # We install the full www/ tree under /opt/guidance-root/ so sibling # directories (Selecton, bioSequence_scripts_and_constants) resolve # correctly relative to the guidance.pl script location. RUN cd /tmp && \ git clone --depth 1 https://github.com/anzaika/guidance.git && \ cd guidance && make && \ mkdir -p /opt/guidance-root && \ cp -r www/Guidance /opt/guidance-root/Guidance && \ cp -r www/Selecton /opt/guidance-root/Selecton && \ cp -r www/bioSequence_scripts_and_constants /opt/guidance-root/bioSequence_scripts_and_constants && \ mkdir -p /opt/guidance-root/Guidance/exec && \ cp programs/msa_set_score/msa_set_score /opt/guidance-root/Guidance/exec/ && \ cp programs/removeTaxa/removeTaxa /opt/guidance-root/Guidance/exec/ && \ cp programs/isEqualTree/isEqualTree /opt/guidance-root/Guidance/exec/ && \ chmod +x /opt/guidance-root/Guidance/guidance.pl && \ mkdir -p /opt/programs/semphy /opt/programs/msa_set_score \ /opt/programs/removeTaxa /opt/programs/isEqualTree && \ cp programs/semphy/semphy /opt/programs/semphy/ && \ cp programs/msa_set_score/msa_set_score /opt/programs/msa_set_score/ && \ cp programs/removeTaxa/removeTaxa /opt/programs/removeTaxa/ && \ cp programs/isEqualTree/isEqualTree /opt/programs/isEqualTree/ && \ printf '#!/bin/sh\nexec perl /opt/guidance-root/Guidance/guidance.pl "$@"\n' \ > /usr/local/bin/guidance2 && \ chmod +x /usr/local/bin/guidance2 && \ rm -rf /tmp/guidance # ── Kalign C build ────────────────────────────────────────────────── COPY . /kalign WORKDIR /kalign RUN mkdir -p build && cd build && \ cmake -DCMAKE_BUILD_TYPE=Release .. && \ make -j"$(nproc)" # ── Record tool versions at build time ────────────────────────────── RUN echo "build_date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" > /tool_versions.txt && \ echo "kalign=$(build/src/kalign --version 2>&1 | head -1 || echo unknown)" >> /tool_versions.txt && \ echo "mafft=$(mafft --version 2>&1 | head -1 || echo unknown)" >> /tool_versions.txt && \ echo "muscle=$(muscle --version 2>&1 | head -1 || echo unknown)" >> /tool_versions.txt && \ echo "clustalo=$(clustalo --version 2>&1 | head -1 || echo unknown)" >> /tool_versions.txt && \ echo "hmmer=$(hmmbuild -h 2>&1 | grep '^# HMMER' | head -1 || echo unknown)" >> /tool_versions.txt && \ echo "iqtree=$(iqtree2 --version 2>&1 | grep 'IQ-TREE' | head -1 || echo unknown)" >> /tool_versions.txt && \ echo "indelible=1.03" >> /tool_versions.txt && \ echo "hyphy=$(hyphy --version 2>&1 | head -1 || echo unknown)" >> /tool_versions.txt # ── Python environment ────────────────────────────────────────────── RUN python3 -m venv /venv ENV PATH="/venv/bin:/kalign/build/src:$PATH" RUN pip install --no-cache-dir uv && \ uv pip install --no-cache -e ".[benchmark]" && \ uv pip install --no-cache \ dendropy biopython pandas matplotlib scipy seaborn numpy # ── Verify tools ──────────────────────────────────────────────────── RUN which kalign && which clustalo && which mafft && which muscle && \ which hmmbuild && which hmmsearch && which iqtree2 && \ which hyphy && which indelible && which guidance2 # ── Data & results directories ────────────────────────────────────── RUN mkdir -p benchmarks/data/downloads/pfam_seed \ benchmarks/data/downloads/swissprot \ benchmarks/data/downloads/selectome \ benchmarks/results/calibration \ benchmarks/results/positive_selection \ benchmarks/results/phylo_accuracy \ benchmarks/results/hmmer_detection \ benchmarks/figures EXPOSE 8050 CMD ["python", "-m", "benchmarks.downstream", "--help"] kalign-3.5.1/README-python.md000066400000000000000000000252361515023132300155660ustar00rootroot00000000000000# Kalign Python Package Python bindings for [Kalign](https://github.com/TimoLassmann/kalign), a fast multiple sequence alignment program for biological sequences (DNA, RNA, protein). ## Installation ```bash pip install kalign-python ``` Optional dependencies for ecosystem integration: ```bash pip install kalign-python[biopython] # Biopython integration (fmt="biopython", I/O helpers) pip install kalign-python[skbio] # scikit-bio integration (fmt="skbio") pip install kalign-python[io] # I/O helpers (requires Biopython) pip install kalign-python[analysis] # pandas + matplotlib for downstream analysis pip install kalign-python[all] # all of the above ``` ## Quick Start ```python import kalign sequences = [ "ATCGATCGATCG", "ATCGTCGATCG", "ATCGATCATCG" ] # Default mode — consistency anchors + VSM (best general-purpose) aligned = kalign.align(sequences) # Fast mode — no consistency, fastest aligned = kalign.align(sequences, mode="fast") # Precise mode — ensemble + realign, highest precision aligned = kalign.align(sequences, mode="precise") ``` ## Modes Kalign v3.5 provides three named modes that package the best configurations: | Mode | Python | CLI | Description | |------|--------|-----|-------------| | **default** | `mode="default"` or omit | `kalign` | Consistency anchors + VSM. Best general-purpose. | | **fast** | `mode="fast"` | `kalign --fast` | VSM only. Fastest, similar to kalign v3.4. | | **precise** | `mode="precise"` | `kalign --precise` | Ensemble(3) + VSM + realign. Highest precision. | Explicit parameters always override mode defaults: ```python # Fast base + 5 ensemble runs aligned = kalign.align(sequences, mode="fast", ensemble=5) # Precise base + custom gap penalty aligned = kalign.align(sequences, mode="precise", gap_open=8.0) ``` Mode constants are also available: `kalign.MODE_DEFAULT`, `kalign.MODE_FAST`, `kalign.MODE_PRECISE`. ## Core API ### `kalign.align()` ```python aligned = kalign.align( sequences, # list of str mode=None, # "default", "fast", "precise", or None (= default) seq_type="auto", # "auto", "dna", "rna", "protein", "divergent", "internal" gap_open=None, # positive float, or None for defaults gap_extend=None, # positive float, or None for defaults terminal_gap_extend=None, n_threads=None, # int, or None for global default refine="none", # refinement mode: "none", "all", "confident", "inline" ensemble=0, # number of ensemble runs (0 = off, try 3-5) min_support=0, # explicit consensus threshold (0 = auto) fmt="plain", # "plain", "biopython", "skbio" ids=None, # list of str (for biopython/skbio output) ) ``` Returns a list of aligned strings (default), a `Bio.Align.MultipleSeqAlignment` (`fmt="biopython"`), or a `skbio.TabularMSA` (`fmt="skbio"`). When `ensemble > 0` and `fmt="biopython"`, per-residue confidence is attached as HMMER-style PP `letter_annotations["posterior_probability"]`. ### `kalign.align_from_file()` Align sequences directly from a FASTA, MSF, or Clustal file: ```python result = kalign.align_from_file("sequences.fasta", seq_type="protein") for name, seq in zip(result.names, result.sequences): print(f"{name}: {seq}") ``` Returns an `AlignedSequences` object with `.names`, `.sequences`, and optional confidence fields (see below). Additional parameters for advanced use: ```python result = kalign.align_from_file( "input.fasta", mode="precise", # or "default", "fast" ensemble=5, # override: 5 runs instead of mode default (3) min_support=0, # consensus threshold (0 = auto) save_poar="consensus.poar", # save POAR table for re-thresholding # load_poar="consensus.poar", # OR load pre-computed POAR refine="none", # refinement mode ) ``` ### `kalign.compare()` Score a test alignment against a reference using the Sum-of-Pairs (SP) score: ```python score = kalign.compare("reference.msf", "test.fasta") print(f"SP score: {score:.1f}") # 0 (no match) to 100 (identical) ``` ### `kalign.compare_detailed()` Detailed alignment comparison returning POAR recall/precision/F1/TC: ```python scores = kalign.compare_detailed("reference.msf", "test.fasta") print(f"F1: {scores['f1']:.3f}, TC: {scores['tc']:.3f}") ``` ### `kalign.write_alignment()` Write aligned sequences to a file: ```python kalign.write_alignment(aligned, "output.fasta", format="fasta", ids=ids) ``` Supported formats: `fasta`, `clustal`, `stockholm`, `phylip` (non-FASTA formats require Biopython). ## Ensemble Alignment & Confidence Scores Ensemble mode runs multiple alignments with varied parameters and combines results via POAR (Pairs of Aligned Residues) consensus. The simplest way to use it is `mode="precise"` (ensemble=3 + realign). For more control, set `ensemble` directly. ```python import kalign # Precise mode: ensemble(3) + realign — highest precision result = kalign.align_from_file("proteins.fasta", mode="precise") # Or: explicit 5 ensemble runs result = kalign.align_from_file("proteins.fasta", ensemble=5) # Per-column confidence: average agreement across ensemble runs [0..1] print(result.column_confidence[:10]) # e.g. [0.93, 0.87, 1.0, ...] # Per-residue confidence: per-sequence, per-position agreement [0..1] print(result.residue_confidence[0][:10]) # e.g. [0.95, 0.90, 1.0, ...] ``` ### POAR Save/Load Save the POAR consensus table to avoid re-running the ensemble when experimenting with thresholds: ```python # First run: compute ensemble and save POAR kalign.align_file_to_file("input.fa", "output.fa", ensemble=5, save_poar="consensus.poar") # Later: instant re-threshold from saved POAR (no re-alignment) kalign.align_file_to_file("input.fa", "output2.fa", load_poar="consensus.poar", min_support=3) ``` ### Stockholm Output with Confidence Write confidence annotations in Stockholm format (`#=GR PP` per-residue, `#=GC PP_cons` per-column): ```python result = kalign.align_from_file("input.fasta", ensemble=5) kalign.write_alignment( result.sequences, "output.sto", format="stockholm", ids=result.names, column_confidence=result.column_confidence, residue_confidence=result.residue_confidence, ) ``` Confidence uses HMMER-style PP encoding: `*`=95%+, `9`=85-95%, ..., `0`=0-5%, `.`=gap. ### Biopython Per-Residue PP When using `fmt="biopython"` with ensemble, per-residue confidence is attached as `letter_annotations["posterior_probability"]`: ```python aln = kalign.align(seqs, ensemble=3, fmt="biopython", ids=ids) print(aln[0].letter_annotations["posterior_probability"]) # e.g. "998.76*9..." ``` ## Threading ```python import kalign kalign.set_num_threads(4) # set global default n = kalign.get_num_threads() # query current default # or override per call aligned = kalign.align(sequences, n_threads=8) ``` Thread settings are thread-local, so different threads can use different defaults. ## Utilities (`kalign.utils`) Requires only NumPy (installed automatically): ```python import kalign aligned = kalign.align(sequences) arr = kalign.utils.to_array(aligned) # numpy array stats = kalign.utils.alignment_stats(aligned) # dict with gap_fraction, conservation, identity consensus = kalign.utils.consensus_sequence(aligned, threshold=0.7) matrix = kalign.utils.pairwise_identity_matrix(aligned) # numpy array trimmed = kalign.utils.remove_gap_columns(aligned) region = kalign.utils.trim_alignment(aligned, start=2, end=10) ``` ## Biopython Integration Requires `pip install kalign-python[biopython]`. ```python import kalign # Return a Biopython MultipleSeqAlignment aln = kalign.align(sequences, fmt="biopython", ids=["s1", "s2", "s3"]) print(aln.get_alignment_length()) # Write in various formats via Biopython from Bio import AlignIO AlignIO.write(aln, "output.clustal", "clustal") ``` ### I/O helpers (`kalign.io`) ```python sequences = kalign.io.read_fasta("input.fasta") sequences, ids = kalign.io.read_sequences("input.fasta") aligned = kalign.align(sequences) kalign.io.write_fasta(aligned, "output.fasta", ids=ids) kalign.io.write_clustal(aligned, "output.aln", ids=ids) kalign.io.write_stockholm(aligned, "output.sto", ids=ids) kalign.io.write_phylip(aligned, "output.phy", ids=ids) ``` ## scikit-bio Integration Requires `pip install kalign-python[skbio]`. ```python import kalign # Returns a TabularMSA of DNA, RNA, or Protein depending on seq_type aln = kalign.align(sequences, seq_type="dna", fmt="skbio") print(type(aln)) # ``` ## Constants ### Sequence Types | String | Constant | Description | |--------|----------|-------------| | `"auto"` | `kalign.AUTO` | Auto-detect (default) | | `"dna"` | `kalign.DNA` | DNA sequences | | `"rna"` | `kalign.RNA` | RNA sequences | | `"protein"` | `kalign.PROTEIN` | Protein sequences | | `"divergent"` | `kalign.PROTEIN_DIVERGENT` | Divergent protein sequences | | `"internal"` | `kalign.DNA_INTERNAL` | DNA with internal gap preference | ### Refinement Modes | String | Constant | Description | |--------|----------|-------------| | `"none"` | `kalign.REFINE_NONE` | No refinement (default) | | `"all"` | `kalign.REFINE_ALL` | Refine all columns | | `"confident"` | `kalign.REFINE_CONFIDENT` | Refine only confident columns | | `"inline"` | `kalign.REFINE_INLINE` | Inline refinement (disables parallelism) | ## Command-line Interface ```bash # Modes kalign-py -i sequences.fasta -o aligned.fasta # default mode kalign-py --fast -i sequences.fasta -o aligned.fasta # fast mode kalign-py --precise -i sequences.fasta -o aligned.fasta # precise mode # I/O options kalign-py -i sequences.fasta -o - --format clustal # stdout cat input.fa | kalign-py -i - -o aligned.fasta # stdin kalign-py -i sequences.fasta -o aligned.fasta --type protein # explicit type # Ensemble with POAR save/load kalign-py -i input.fa -o output.fa --ensemble 5 --save-poar consensus.poar kalign-py -i input.fa -o output.fa --load-poar consensus.poar --min-support 3 kalign-py --version ``` ## Development ```bash git clone https://github.com/TimoLassmann/kalign.git cd kalign uv pip install -e . uv run pytest tests/python/ -v ``` Requirements: Python 3.9+, CMake 3.18+, C++11 compiler, NumPy. ## Citation If you use Kalign in your research, please cite: > Lassmann, T. (2020). Kalign 3: multiple sequence alignment of large data sets. > *Bioinformatics*, 36(6), 1928-1929. > [doi:10.1093/bioinformatics/btz795](https://doi.org/10.1093/bioinformatics/btz795) ## License Apache License, Version 2.0. See [COPYING](COPYING). kalign-3.5.1/README.md000066400000000000000000000064571515023132300142530ustar00rootroot00000000000000[![CMake](https://github.com/TimoLassmann/kalign/actions/workflows/cmake.yml/badge.svg)](https://github.com/TimoLassmann/kalign/actions/workflows/cmake.yml) [![Python](https://github.com/TimoLassmann/kalign/actions/workflows/python.yml/badge.svg)](https://github.com/TimoLassmann/kalign/actions/workflows/python.yml) [![Build Python Wheels](https://github.com/TimoLassmann/kalign/actions/workflows/wheels.yml/badge.svg)](https://github.com/TimoLassmann/kalign/actions/workflows/wheels.yml) ![CodeQL](https://github.com/TimoLassmann/kalign/workflows/CodeQL/badge.svg) # Kalign Kalign is a fast multiple sequence alignment program for biological sequences. It aligns protein, DNA, and RNA sequences using a progressive alignment approach with multi-threading support. ## Installation ### From source Prerequisites: C compiler (GCC or Clang), CMake 3.18+, optionally OpenMP. ```bash mkdir build && cd build cmake .. make make test make install ``` On macOS, `brew install libomp` for OpenMP support. ### Zig build (alternative) Requires zig version 0.12. ```bash zig build ``` ### Python ```bash pip install kalign-python ``` See [README-python.md](README-python.md) for the full Python documentation. ## Usage ``` kalign -i -o ``` Kalign v3.5 has three modes: | Mode | Flag | Description | |------|------|-------------| | default | (none) | Best general-purpose. | | fast | `--fast` | Fastest. Same as kalign v3.4. | | precise | `--precise` | Highest accuracy, ~10x slower. | ### Examples ```bash # Align sequences kalign -i sequences.fa -o aligned.fa # Fast mode kalign --fast -i sequences.fa -o aligned.fa # Precise mode (ensemble + realign) kalign --precise -i sequences.fa -o aligned.fa # Read from stdin cat input.fa | kalign -i - -o aligned.fa # Combine multiple input files kalign seqsA.fa seqsB.fa -o combined.fa # Save ensemble consensus for re-thresholding kalign --precise -i seqs.fa -o out.fa --save-poar consensus.poar kalign -i seqs.fa -o out2.fa --load-poar consensus.poar --min-support 3 ``` ### Options ``` --format Output format: fasta, msf, clu. [fasta] --type Sequence type: protein, dna, rna, divergent. [auto] --gpo Gap open penalty. [auto] --gpe Gap extension penalty. [auto] --tgpe Terminal gap extension penalty. [auto] --ensemble N Run N ensemble alignments. [off] --refine Refinement: none, all, confident. [none] -n Number of threads. [auto] ``` ### Output formats ```bash kalign -i input.fa -f msf -o output.msf kalign -i input.fa -f clu -o output.clu ``` ## C library Link Kalign into your C/C++ project: ```cmake find_package(kalign) target_link_libraries( kalign::kalign) ``` Or include directly: ```cmake add_subdirectory(/kalign EXCLUDE_FROM_ALL) target_link_libraries( kalign::kalign) ``` ## Benchmarks ### Balibase ![Balibase_scores](https://user-images.githubusercontent.com/8110320/198513840-0e08a634-bb41-4826-bd58-7fc66eae1054.jpeg) ### Bralibase ![Bralibase_scores](https://user-images.githubusercontent.com/8110320/198513850-00e5037f-355f-45ec-828f-ed8d47497272.jpeg) ## Citation Lassmann, Timo. "Kalign 3: multiple sequence alignment of large data sets." Bioinformatics (2019). [DOI](https://doi.org/10.1093/bioinformatics/btz795) ## License Apache License, Version 2.0. See [COPYING](COPYING). kalign-3.5.1/benchmarks/000077500000000000000000000000001515023132300150755ustar00rootroot00000000000000kalign-3.5.1/benchmarks/__init__.py000066400000000000000000000001071515023132300172040ustar00rootroot00000000000000"""Kalign benchmark suite for alignment quality regression testing.""" kalign-3.5.1/benchmarks/__main__.py000066400000000000000000000001201515023132300171600ustar00rootroot00000000000000"""Entry point for `python -m benchmarks`.""" from .runner import main main() kalign-3.5.1/benchmarks/analysis.py000066400000000000000000000533721515023132300173040ustar00rootroot00000000000000"""RV11 alignment structure analysis. Compares gap structure and alignment geometry between kalign, reference, and external tools (mafft, muscle, clustalo) to understand HOW alignments differ structurally — not just score differences. Usage: # Locally (kalign only, external tools skipped if not installed): uv run python -m benchmarks.analysis # Inside container (has mafft/muscle/clustalo): python -m benchmarks.analysis # Specific dataset: python -m benchmarks.analysis --dataset balibase_RV11 # Write CSV: python -m benchmarks.analysis --csv benchmarks/results/gap_analysis.csv """ import argparse import csv import json import re import statistics import sys import tempfile from dataclasses import dataclass, fields from pathlib import Path from typing import Dict, List, Optional, Tuple from .datasets import balibase_cases, balibase_is_available RESULTS_DIR = Path(__file__).parent / "results" # --------------------------------------------------------------------------- # MSF parser (reference alignments are in GCG MSF format) # --------------------------------------------------------------------------- def parse_msf(path: Path) -> Dict[str, str]: """Parse a GCG MSF file into {name: aligned_sequence}.""" text = path.read_text() # Split at "//" separator parts = text.split("//") if len(parts) < 2: raise ValueError(f"No // separator found in {path}") body = parts[1] seqs: Dict[str, List[str]] = {} for line in body.splitlines(): line = line.strip() if not line: continue tokens = line.split() if len(tokens) < 2: continue name = tokens[0] # Sequence characters (may contain dots for gaps) seq_parts = "".join(tokens[1:]) seqs.setdefault(name, []).append(seq_parts) # Join blocks and normalise: dots → dashes, remove whitespace result = {} for name, blocks in seqs.items(): seq = "".join(blocks).replace(".", "-").upper() result[name] = seq return result # --------------------------------------------------------------------------- # FASTA parser (kalign/tool outputs) # --------------------------------------------------------------------------- def parse_fasta(path: Path) -> Dict[str, str]: """Parse a FASTA file into {name: sequence}.""" seqs: Dict[str, str] = {} current = None parts: List[str] = [] for line in path.read_text().splitlines(): line = line.strip() if line.startswith(">"): if current is not None: seqs[current] = "".join(parts).upper() current = line[1:].split()[0] parts = [] elif current is not None: parts.append(line) if current is not None: seqs[current] = "".join(parts).upper() return seqs # --------------------------------------------------------------------------- # Gap structure metrics # --------------------------------------------------------------------------- @dataclass class GapStats: """Gap structure metrics for one alignment.""" n_seqs: int alignment_length: int mean_seq_length: float # unaligned (non-gap chars) expansion_factor: float # alignment_length / mean_seq_length total_gaps: int gap_fraction: float # total_gaps / (n_seqs * alignment_length) n_gap_blocks: int mean_gap_block_len: float mean_terminal_gap: float # average leading+trailing gap per sequence mean_internal_gap: float # average total internal gap chars per sequence n_gappy_columns: int # columns where >50% of sequences have a gap gappy_column_fraction: float def compute_gap_stats(seqs: Dict[str, str]) -> GapStats: """Compute gap structure metrics from aligned sequences.""" sequences = list(seqs.values()) n_seqs = len(sequences) if n_seqs == 0: return GapStats(0, 0, 0.0, 0.0, 0, 0.0, 0, 0.0, 0.0, 0.0, 0, 0.0) aln_len = len(sequences[0]) # Unaligned lengths (non-gap characters) ungapped_lens = [len(s.replace("-", "")) for s in sequences] mean_seq_len = statistics.mean(ungapped_lens) expansion = aln_len / mean_seq_len if mean_seq_len > 0 else 0.0 total_gaps = sum(s.count("-") for s in sequences) total_chars = n_seqs * aln_len gap_frac = total_gaps / total_chars if total_chars > 0 else 0.0 # Gap blocks and lengths all_block_lens: List[int] = [] terminal_gaps: List[int] = [] internal_gaps: List[int] = [] for seq in sequences: # Find all gap blocks blocks = [(m.start(), m.end()) for m in re.finditer(r"-+", seq)] all_block_lens.extend(m.end() - m.start() for m in re.finditer(r"-+", seq)) # Terminal: leading and trailing leading = len(seq) - len(seq.lstrip("-")) trailing = len(seq) - len(seq.rstrip("-")) terminal_gaps.append(leading + trailing) # Internal: everything that's not leading/trailing internal = sum(e - s for s, e in blocks) internal -= leading + trailing internal_gaps.append(max(0, internal)) n_gap_blocks = len(all_block_lens) mean_block_len = statistics.mean(all_block_lens) if all_block_lens else 0.0 mean_terminal = statistics.mean(terminal_gaps) mean_internal = statistics.mean(internal_gaps) # Gappy columns (>50% gaps) n_gappy = 0 for col in range(aln_len): gaps_in_col = sum(1 for s in sequences if s[col] == "-") if gaps_in_col > n_seqs / 2: n_gappy += 1 return GapStats( n_seqs=n_seqs, alignment_length=aln_len, mean_seq_length=mean_seq_len, expansion_factor=expansion, total_gaps=total_gaps, gap_fraction=gap_frac, n_gap_blocks=n_gap_blocks, mean_gap_block_len=mean_block_len, mean_terminal_gap=mean_terminal, mean_internal_gap=mean_internal, n_gappy_columns=n_gappy, gappy_column_fraction=n_gappy / aln_len if aln_len > 0 else 0.0, ) # --------------------------------------------------------------------------- # Alignment generation helpers # --------------------------------------------------------------------------- def _align_kalign(unaligned: Path, output: Path, seq_type: str) -> None: """Run kalign via Python API.""" import kalign kalign.align_file_to_file( str(unaligned), str(output), format="fasta", seq_type=seq_type, ) def _align_external(unaligned: Path, output: Path, tool: str) -> bool: """Run an external tool. Returns True if successful.""" import shutil import subprocess if shutil.which(tool) is None: return False try: if tool == "mafft": with open(output, "w") as f: subprocess.run( ["mafft", "--auto", str(unaligned)], stdout=f, stderr=subprocess.PIPE, check=True, ) elif tool == "clustalo": subprocess.run( ["clustalo", "-i", str(unaligned), "-o", str(output), "--outfmt=fasta", "--force"], capture_output=True, check=True, ) elif tool == "muscle": subprocess.run( ["muscle", "-align", str(unaligned), "-output", str(output)], capture_output=True, check=True, ) return True except (subprocess.CalledProcessError, FileNotFoundError): return False # --------------------------------------------------------------------------- # Per-case analysis row # --------------------------------------------------------------------------- @dataclass class CaseRow: family: str method: str # Scores from results JSON (NaN if not available) recall: float precision: float f1: float tc: float # Gap stats alignment_length: int expansion_factor: float gap_fraction: float n_gap_blocks: int mean_gap_block_len: float mean_terminal_gap: float mean_internal_gap: float n_gappy_columns: int gappy_column_fraction: float # --------------------------------------------------------------------------- # Load frozen scores from full_comparison.json # --------------------------------------------------------------------------- def load_scores(json_path: Path, dataset_filter: str = "balibase_RV11") -> Dict[Tuple[str, str], dict]: """Load {(family, method_key): scores} from results JSON. method_key is 'kalign' for python_api/refine=none, or the external tool name. """ with open(json_path) as f: data = json.load(f) scores: Dict[Tuple[str, str], dict] = {} for r in data["results"]: if dataset_filter and r["dataset"] != dataset_filter: continue if r["method"] == "python_api" and r["refine"] == "none": key = (r["family"], "kalign") elif r["method"] in ("clustalo", "mafft", "muscle"): key = (r["family"], r["method"]) else: continue scores[key] = { "recall": r.get("recall", float("nan")), "precision": r.get("precision", float("nan")), "f1": r.get("f1", float("nan")), "tc": r.get("tc", float("nan")), } return scores # --------------------------------------------------------------------------- # Main analysis # --------------------------------------------------------------------------- def analyse_rv11( dataset_filter: str = "balibase_RV11", external_tools: Optional[List[str]] = None, ) -> List[CaseRow]: """Run gap analysis on all RV11 cases. Returns list of CaseRow.""" if external_tools is None: external_tools = ["mafft", "muscle", "clustalo"] if not balibase_is_available(): print("BAliBASE not downloaded. Run: uv run python -m benchmarks --download-only") return [] cases = [c for c in balibase_cases() if c.dataset == dataset_filter] if not cases: print(f"No cases found for {dataset_filter}") return [] # Load frozen scores json_path = RESULTS_DIR / "full_comparison.json" scores = load_scores(json_path, dataset_filter) if json_path.exists() else {} rows: List[CaseRow] = [] for case in cases: print(f" {case.family} ...", end="", flush=True) # --- Reference alignment --- ref_seqs = parse_msf(case.reference) ref_stats = compute_gap_stats(ref_seqs) sc = scores.get((case.family, "reference"), {}) rows.append(CaseRow( family=case.family, method="reference", recall=1.0, precision=1.0, f1=1.0, tc=1.0, alignment_length=ref_stats.alignment_length, expansion_factor=ref_stats.expansion_factor, gap_fraction=ref_stats.gap_fraction, n_gap_blocks=ref_stats.n_gap_blocks, mean_gap_block_len=ref_stats.mean_gap_block_len, mean_terminal_gap=ref_stats.mean_terminal_gap, mean_internal_gap=ref_stats.mean_internal_gap, n_gappy_columns=ref_stats.n_gappy_columns, gappy_column_fraction=ref_stats.gappy_column_fraction, )) # --- Kalign --- with tempfile.TemporaryDirectory() as tmpdir: kalign_out = Path(tmpdir) / f"{case.family}_kalign.fa" _align_kalign(case.unaligned, kalign_out, case.seq_type) kalign_seqs = parse_fasta(kalign_out) kalign_stats = compute_gap_stats(kalign_seqs) sc = scores.get((case.family, "kalign"), {}) rows.append(CaseRow( family=case.family, method="kalign", recall=sc.get("recall", float("nan")), precision=sc.get("precision", float("nan")), f1=sc.get("f1", float("nan")), tc=sc.get("tc", float("nan")), alignment_length=kalign_stats.alignment_length, expansion_factor=kalign_stats.expansion_factor, gap_fraction=kalign_stats.gap_fraction, n_gap_blocks=kalign_stats.n_gap_blocks, mean_gap_block_len=kalign_stats.mean_gap_block_len, mean_terminal_gap=kalign_stats.mean_terminal_gap, mean_internal_gap=kalign_stats.mean_internal_gap, n_gappy_columns=kalign_stats.n_gappy_columns, gappy_column_fraction=kalign_stats.gappy_column_fraction, )) # --- External tools --- for tool in external_tools: with tempfile.TemporaryDirectory() as tmpdir: tool_out = Path(tmpdir) / f"{case.family}_{tool}.fa" ok = _align_external(case.unaligned, tool_out, tool) if not ok: continue tool_seqs = parse_fasta(tool_out) tool_stats = compute_gap_stats(tool_seqs) sc = scores.get((case.family, tool), {}) rows.append(CaseRow( family=case.family, method=tool, recall=sc.get("recall", float("nan")), precision=sc.get("precision", float("nan")), f1=sc.get("f1", float("nan")), tc=sc.get("tc", float("nan")), alignment_length=tool_stats.alignment_length, expansion_factor=tool_stats.expansion_factor, gap_fraction=tool_stats.gap_fraction, n_gap_blocks=tool_stats.n_gap_blocks, mean_gap_block_len=tool_stats.mean_gap_block_len, mean_terminal_gap=tool_stats.mean_terminal_gap, mean_internal_gap=tool_stats.mean_internal_gap, n_gappy_columns=tool_stats.n_gappy_columns, gappy_column_fraction=tool_stats.gappy_column_fraction, )) print(" done") return rows # --------------------------------------------------------------------------- # Output formatting # --------------------------------------------------------------------------- def print_table(rows: List[CaseRow]) -> None: """Print a summary table to stdout, grouped by family.""" if not rows: return families = sorted(set(r.family for r in rows)) methods = sorted(set(r.method for r in rows)) # Per-case comparison table hdr = f"{'Family':<10} {'Method':<10} {'Recall':>7} {'Prec':>7} {'F1':>7} {'AlnLen':>7} {'Expand':>7} {'GapFrac':>7} {'GapBlk':>7} {'MeanBL':>7} {'TermGap':>7} {'IntGap':>7} {'Gappy%':>7}" print("\n" + "=" * len(hdr)) print(hdr) print("-" * len(hdr)) for fam in families: fam_rows = sorted( [r for r in rows if r.family == fam], key=lambda r: (r.method != "reference", r.method != "kalign", r.method), ) for r in fam_rows: rec = f"{r.recall:.3f}" if r.recall == r.recall else " n/a" pre = f"{r.precision:.3f}" if r.precision == r.precision else " n/a" f1 = f"{r.f1:.3f}" if r.f1 == r.f1 else " n/a" print( f"{r.family:<10} {r.method:<10} {rec:>7} {pre:>7} {f1:>7} " f"{r.alignment_length:>7} {r.expansion_factor:>7.2f} " f"{r.gap_fraction:>7.3f} {r.n_gap_blocks:>7} " f"{r.mean_gap_block_len:>7.1f} {r.mean_terminal_gap:>7.1f} " f"{r.mean_internal_gap:>7.1f} {r.gappy_column_fraction:>7.3f}" ) print() # Aggregate summary by method print("=" * 80) print("AGGREGATE SUMMARY (means across all families)") print("-" * 80) fmt = "{:<10} {:>7} {:>7} {:>7} {:>8} {:>7} {:>7} {:>8} {:>8}" print(fmt.format("Method", "Recall", "Prec", "F1", "Expand", "GapFrac", "MeanBL", "TermGap", "IntGap")) print("-" * 80) for method in ["reference", "kalign"] + [m for m in methods if m not in ("reference", "kalign")]: method_rows = [r for r in rows if r.method == method] if not method_rows: continue def safe_mean(vals): clean = [v for v in vals if v == v] # filter NaN return statistics.mean(clean) if clean else float("nan") rec = safe_mean([r.recall for r in method_rows]) pre = safe_mean([r.precision for r in method_rows]) f1 = safe_mean([r.f1 for r in method_rows]) exp = statistics.mean([r.expansion_factor for r in method_rows]) gf = statistics.mean([r.gap_fraction for r in method_rows]) mbl = statistics.mean([r.mean_gap_block_len for r in method_rows]) tg = statistics.mean([r.mean_terminal_gap for r in method_rows]) ig = statistics.mean([r.mean_internal_gap for r in method_rows]) rec_s = f"{rec:.3f}" if rec == rec else " n/a" pre_s = f"{pre:.3f}" if pre == pre else " n/a" f1_s = f"{f1:.3f}" if f1 == f1 else " n/a" print(fmt.format(method, rec_s, pre_s, f1_s, f"{exp:.2f}", f"{gf:.3f}", f"{mbl:.1f}", f"{tg:.1f}", f"{ig:.1f}")) # Correlation analysis: precision vs expansion factor for kalign kalign_rows = [r for r in rows if r.method == "kalign" and r.precision == r.precision] if len(kalign_rows) >= 5: print("\n" + "=" * 80) print("CORRELATION: kalign precision vs gap metrics") print("-" * 80) # Simple Pearson correlation def pearson(xs, ys): n = len(xs) if n < 3: return float("nan") mx, my = statistics.mean(xs), statistics.mean(ys) num = sum((x - mx) * (y - my) for x, y in zip(xs, ys)) dx = sum((x - mx) ** 2 for x in xs) ** 0.5 dy = sum((y - my) ** 2 for y in ys) ** 0.5 return num / (dx * dy) if dx > 0 and dy > 0 else float("nan") prec = [r.precision for r in kalign_rows] metrics = [ ("expansion_factor", [r.expansion_factor for r in kalign_rows]), ("gap_fraction", [r.gap_fraction for r in kalign_rows]), ("mean_gap_block_len", [r.mean_gap_block_len for r in kalign_rows]), ("mean_terminal_gap", [r.mean_terminal_gap for r in kalign_rows]), ("mean_internal_gap", [r.mean_internal_gap for r in kalign_rows]), ("gappy_column_fraction", [r.gappy_column_fraction for r in kalign_rows]), ] for name, vals in metrics: r = pearson(prec, vals) print(f" precision vs {name:<25}: r = {r:+.3f}") # Also: kalign expansion vs reference expansion ref_rows = {r.family: r for r in rows if r.method == "reference"} kalign_dict = {r.family: r for r in kalign_rows} common = sorted(set(ref_rows) & set(kalign_dict)) if common: print(f"\n Expansion factor comparison (kalign vs reference, n={len(common)}):") over = [f for f in common if kalign_dict[f].expansion_factor > ref_rows[f].expansion_factor * 1.05] under = [f for f in common if kalign_dict[f].expansion_factor < ref_rows[f].expansion_factor * 0.95] same = [f for f in common if f not in over and f not in under] print(f" Over-expanded (>5%): {len(over)}") print(f" Under-expanded: {len(under)}") print(f" Similar (+/-5%): {len(same)}") # Relative expansion ratio correlated with precision ratios = [kalign_dict[f].expansion_factor / max(ref_rows[f].expansion_factor, 0.01) for f in common] precs = [kalign_dict[f].precision for f in common] r_ratio = pearson(ratios, precs) print(f" Correlation (expand_ratio vs precision): r = {r_ratio:+.3f}") if over: print(f"\n Worst over-expanded cases (kalign expand / ref expand):") ranked = sorted(over, key=lambda f: kalign_dict[f].expansion_factor / max(ref_rows[f].expansion_factor, 0.01), reverse=True) for f in ranked[:10]: ke = kalign_dict[f].expansion_factor re = ref_rows[f].expansion_factor kp = kalign_dict[f].precision print(f" {f}: kalign={ke:.2f} ref={re:.2f} ratio={ke/re:.2f} precision={kp:.3f}") if under: print(f"\n Worst under-expanded cases (kalign expand / ref expand):") ranked = sorted(under, key=lambda f: kalign_dict[f].expansion_factor / max(ref_rows[f].expansion_factor, 0.01)) for f in ranked[:10]: ke = kalign_dict[f].expansion_factor re = ref_rows[f].expansion_factor kp = kalign_dict[f].precision print(f" {f}: kalign={ke:.2f} ref={re:.2f} ratio={ke/re:.2f} precision={kp:.3f}") def write_csv(rows: List[CaseRow], path: str) -> None: """Write analysis results to CSV.""" fieldnames = [f.name for f in fields(CaseRow)] Path(path).parent.mkdir(parents=True, exist_ok=True) with open(path, "w", newline="") as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for row in rows: d = {fn: getattr(row, fn) for fn in fieldnames} writer.writerow(d) print(f"\nCSV written to {path}") # --------------------------------------------------------------------------- # CLI entry point # --------------------------------------------------------------------------- def main() -> None: parser = argparse.ArgumentParser( description="RV11 alignment structure analysis", prog="python -m benchmarks.analysis", ) parser.add_argument( "--dataset", default="balibase_RV11", help="Dataset filter (default: balibase_RV11)", ) parser.add_argument( "--csv", default="", help="Write results to CSV file", ) parser.add_argument( "--no-external", action="store_true", help="Skip external tools (mafft, muscle, clustalo)", ) args = parser.parse_args() external = [] if args.no_external else ["mafft", "muscle", "clustalo"] print(f"Analysing {args.dataset} alignment structure...") rows = analyse_rv11(dataset_filter=args.dataset, external_tools=external) if not rows: sys.exit(1) print_table(rows) if args.csv: write_csv(rows, args.csv) if __name__ == "__main__": main() kalign-3.5.1/benchmarks/app.py000066400000000000000000000562061515023132300162400ustar00rootroot00000000000000"""Dash app for running kalign benchmarks and viewing results. Usage: python -m benchmarks.app [--port 8050] """ import argparse import json import sys import threading from pathlib import Path try: import dash from dash import dcc, html, dash_table, callback_context from dash.dependencies import Input, Output, State import plotly.express as px import pandas as pd except ImportError: print("Dash visualization requires extra dependencies:") print(" pip install dash plotly pandas") sys.exit(1) from .datasets import DATASETS, get_cases, download_dataset from .scoring import run_case RESULTS_DIR = Path(__file__).parent / "results" RESULTS_DIR.mkdir(parents=True, exist_ok=True) # --------------------------------------------------------------------------- # Configuration presets — the 4 varieties of kalign # --------------------------------------------------------------------------- CONFIG_PRESETS = { "Kalign (default)": {"refine": "none", "ensemble": 0}, "Kalign + Refinement": {"refine": "confident", "ensemble": 0}, "Ensemble (8 runs)": {"refine": "none", "ensemble": 8}, "Ensemble (12 runs)": {"refine": "none", "ensemble": 12}, "Clustal Omega": {"method": "clustalo", "refine": "none", "ensemble": 0}, "MAFFT": {"method": "mafft", "refine": "none", "ensemble": 0}, "MUSCLE": {"method": "muscle", "refine": "none", "ensemble": 0}, } # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _available_datasets(): """Return list of (name, available, n_cases) tuples.""" info = [] for name, ds in DATASETS.items(): avail = ds["is_available"]() n = len(ds["cases"]()) if avail else 0 info.append((name, avail, n)) return info def _load_json(path): with open(path) as f: return json.load(f) _EXTERNAL_LABELS = { "clustalo": "Clustal Omega", "mafft": "MAFFT", "muscle": "MUSCLE", } def _config_label(row): """Build a human-readable configuration label from result fields.""" method = row.get("method", "python_api") if method in _EXTERNAL_LABELS: return _EXTERNAL_LABELS[method] ensemble = row.get("ensemble", 0) refine = row.get("refine", "none") if ensemble and ensemble > 0: label = f"Ensemble ({ensemble})" elif refine and refine != "none": label = f"Kalign + {refine}" else: label = "Kalign" return label def _results_to_df(results): """Convert list of AlignmentResult dicts to DataFrame.""" df = pd.DataFrame(results) if "error" in df.columns: df = df[df["error"].isna() | (df["error"] == "None") | (df["error"].isnull())] # Ensure columns exist (backward compat with old JSON files) if "ensemble" not in df.columns: df["ensemble"] = 0 df["ensemble"] = df["ensemble"].fillna(0).astype(int) for col in ("recall", "precision", "f1", "tc"): if col not in df.columns: df[col] = 0.0 df[col] = df[col].fillna(0.0) # Add config label for plotting df["config"] = df.apply(_config_label, axis=1) return df def _build_figures(df): """Build plotly figures from a results DataFrame.""" figs = [] if df.empty: return figs # Filter out errors clean = df[df["sp_score"] > 0].copy() if "sp_score" in df.columns else df if clean.empty: return figs # Ensure new columns exist (backward compat with old JSON files) for col in ("recall", "precision", "f1", "tc"): if col not in clean.columns: clean[col] = 0.0 # Determine color column: use 'config' if multiple configs, else 'method' configs = clean["config"].nunique() color_col = "config" if configs > 1 else "method" # bali_score-compatible metrics has_recall = clean["recall"].sum() > 0 if has_recall: # SP score (bali_score compatible) = recall fig_sp = px.box( clean, x="dataset", y="recall", color=color_col, title="SP Score by Dataset (bali_score compatible)", labels={"recall": "SP Score", "dataset": "Dataset", "config": "Configuration"}, ) fig_sp.update_layout(legend=dict(orientation="h", y=-0.2)) figs.append(("sp_box", fig_sp)) # TC score fig_tc = px.box( clean, x="dataset", y="tc", color=color_col, title="TC Score by Dataset", labels={"tc": "TC Score", "dataset": "Dataset", "config": "Configuration"}, ) fig_tc.update_layout(legend=dict(orientation="h", y=-0.2)) figs.append(("tc_box", fig_tc)) # Precision fig_prec = px.box( clean, x="dataset", y="precision", color=color_col, title="Precision by Dataset", labels={"precision": "Precision", "dataset": "Dataset", "config": "Configuration"}, ) fig_prec.update_layout(legend=dict(orientation="h", y=-0.2)) figs.append(("precision_box", fig_prec)) # F1 fig_f1 = px.box( clean, x="dataset", y="f1", color=color_col, title="F1 Score by Dataset", labels={"f1": "F1", "dataset": "Dataset", "config": "Configuration"}, ) fig_f1.update_layout(legend=dict(orientation="h", y=-0.2)) figs.append(("f1_box", fig_f1)) else: # Fallback: legacy SP score (not bali_score compatible) fig_box = px.box( clean, x="dataset", y="sp_score", color=color_col, title="SP Score Distribution by Dataset (legacy)", labels={"sp_score": "SP Score", "dataset": "Dataset", "config": "Configuration"}, ) fig_box.update_layout(legend=dict(orientation="h", y=-0.2)) figs.append(("sp_box", fig_box)) # Strip plot by family hover_cols = ["family", "wall_time", "refine", "ensemble"] if has_recall: hover_cols.extend(["recall", "precision", "f1", "tc"]) y_strip = "recall" if has_recall else "sp_score" fig_scatter = px.strip( clean, x="dataset", y=y_strip, color=color_col, hover_data=hover_cols, title="SP Score per Family", labels={"recall": "SP Score", "sp_score": "SP Score (legacy)", "config": "Configuration"}, ) fig_scatter.update_layout(legend=dict(orientation="h", y=-0.2)) figs.append(("scatter", fig_scatter)) # Timing fig_time = px.box( clean, x="dataset", y="wall_time", color=color_col, title="Alignment Time by Dataset", labels={"wall_time": "Wall Time (s)", "dataset": "Dataset", "config": "Configuration"}, ) fig_time.update_layout(legend=dict(orientation="h", y=-0.2)) figs.append(("timing", fig_time)) # Summary table by config x dataset if configs > 1: agg_dict = { "mean_sp": ("sp_score", "mean"), "median_sp": ("sp_score", "median"), "mean_time": ("wall_time", "mean"), "n_cases": ("sp_score", "count"), } if has_recall: agg_dict.update({ "mean_recall": ("recall", "mean"), "mean_precision": ("precision", "mean"), "mean_f1": ("f1", "mean"), "mean_tc": ("tc", "mean"), }) summary = clean.groupby(["config", "dataset"]).agg(**agg_dict).reset_index() summary = summary.round(3) y_col = "mean_recall" if has_recall else "mean_sp" y_label = "Mean SP Score" if has_recall else "Mean SP Score (legacy)" fig_summary = px.bar( summary, x="dataset", y=y_col, color="config", barmode="group", title=f"{y_label} by Dataset and Configuration", labels={y_col: y_label, "dataset": "Dataset", "config": "Configuration"}, ) fig_summary.update_layout(legend=dict(orientation="h", y=-0.2)) figs.append(("summary_bar", fig_summary)) return figs # --------------------------------------------------------------------------- # State shared between callbacks and the benchmark thread # --------------------------------------------------------------------------- _run_state = { "running": False, "progress": "", "results": [], "done": False, } def _run_in_thread(dataset, method, binary, max_cases, n_threads, configs): """Run benchmarks in a background thread so the UI stays responsive.""" global _run_state _run_state["running"] = True _run_state["done"] = False _run_state["results"] = [] _run_state["progress"] = f"Loading {dataset} cases..." try: cases = get_cases(dataset, max_cases=max_cases if max_cases > 0 else None) if not cases: _run_state["progress"] = f"No cases found for {dataset}. Try downloading first." _run_state["running"] = False _run_state["done"] = True return total = len(cases) * len(configs) done = 0 for cfg_name, cfg in configs: cfg_method = cfg.get("method", method) refine = cfg["refine"] ensemble = cfg["ensemble"] for case in cases: done += 1 _run_state["progress"] = ( f"[{done}/{total}] {cfg_name}: {case.family}..." ) result = run_case( case, method=cfg_method, binary=binary, n_threads=n_threads, refine=refine, ensemble=ensemble, ) _run_state["results"].append(result.to_dict()) # Auto-save import time as _time save_path = RESULTS_DIR / f"run_{_time.strftime('%Y%m%d_%H%M%S')}.json" data = { "timestamp": _time.strftime("%Y-%m-%dT%H:%M:%S"), "results": _run_state["results"], } with open(save_path, "w") as f: json.dump(data, f, indent=2) _run_state["progress"] = f"Done! {done} alignments scored. Saved to {save_path.name}" except Exception as e: _run_state["progress"] = f"Error: {e}" finally: _run_state["running"] = False _run_state["done"] = True # --------------------------------------------------------------------------- # App layout # --------------------------------------------------------------------------- def create_app(): app = dash.Dash(__name__) app.title = "Kalign Benchmarks" # Discover saved result files def _saved_files(): return sorted(RESULTS_DIR.glob("*.json"), reverse=True) ds_info = _available_datasets() app.layout = html.Div([ html.H1("Kalign Benchmark Dashboard"), # --- Run controls --- html.Div([ html.H3("Run Benchmark"), html.Div([ # Row 1: Dataset, method, binary html.Div([ html.Div([ html.Label("Dataset"), dcc.Dropdown( id="dataset-dropdown", options=[ {"label": f"{name} ({'available' if avail else 'needs download'}, {n} cases)", "value": name} for name, avail, n in ds_info ], value="balibase", ), ], style={"width": "30%", "display": "inline-block", "verticalAlign": "top", "marginRight": "2%"}), html.Div([ html.Label("Method"), dcc.RadioItems( id="method-radio", options=[ {"label": " Python API", "value": "python_api"}, {"label": " C binary", "value": "cli"}, ], value="python_api", ), ], style={"width": "12%", "display": "inline-block", "verticalAlign": "top", "marginRight": "2%"}), html.Div([ html.Label("C binary path"), dcc.Input(id="binary-input", type="text", value="build/src/kalign", style={"width": "160px"}), ], style={"width": "18%", "display": "inline-block", "verticalAlign": "top", "marginRight": "2%"}), html.Div([ html.Label("Max cases (0=all)"), dcc.Input(id="max-cases-input", type="number", value=0, min=0, style={"width": "80px"}), ], style={"width": "10%", "display": "inline-block", "verticalAlign": "top", "marginRight": "2%"}), html.Div([ html.Label("Threads"), dcc.Input(id="threads-input", type="number", value=1, min=1, style={"width": "60px"}), ], style={"width": "8%", "display": "inline-block", "verticalAlign": "top"}), ]), html.Hr(style={"margin": "10px 0"}), # Row 2: Configuration presets html.Div([ html.Div([ html.Label("Configurations to run"), dcc.Checklist( id="config-checklist", options=[{"label": f" {name}", "value": name} for name in CONFIG_PRESETS], value=["Kalign (default)"], style={"lineHeight": "2"}, ), ], style={"width": "35%", "display": "inline-block", "verticalAlign": "top", "marginRight": "2%"}), html.Div([ html.Label("Custom ensemble runs"), dcc.Input(id="custom-ensemble-input", type="number", value=8, min=2, max=32, style={"width": "80px"}), html.Br(), html.Label("Custom refine mode", style={"marginTop": "8px"}), dcc.Dropdown( id="custom-refine-dropdown", options=[ {"label": "none", "value": "none"}, {"label": "confident", "value": "confident"}, {"label": "all", "value": "all"}, ], value="none", style={"width": "140px"}, ), html.Button("+ Add custom config", id="add-custom-btn", n_clicks=0, style={"marginTop": "8px"}), ], style={"width": "25%", "display": "inline-block", "verticalAlign": "top", "marginRight": "2%"}), html.Div([ html.Br(), html.Button("Download Dataset", id="download-btn", n_clicks=0, style={"marginRight": "10px"}), html.Br(), html.Br(), html.Button("Run Benchmark", id="run-btn", n_clicks=0, style={"backgroundColor": "#4CAF50", "color": "white", "border": "none", "padding": "12px 24px", "cursor": "pointer", "fontSize": "14px"}), ], style={"width": "20%", "display": "inline-block", "verticalAlign": "top"}), ]), ]), html.Div(id="progress-text", style={"marginTop": "10px", "fontStyle": "italic"}), dcc.Interval(id="progress-interval", interval=1000, n_intervals=0, disabled=True), # Hidden store for custom configs dcc.Store(id="custom-configs-store", data=[]), ], style={"padding": "15px", "backgroundColor": "#f5f5f5", "borderRadius": "8px", "marginBottom": "20px"}), # --- Load saved results --- html.Div([ html.H3("View Results"), html.Div([ html.Div([ html.Label("Saved result files"), dcc.Dropdown(id="results-dropdown", multi=True), ], style={"width": "60%", "display": "inline-block", "verticalAlign": "top", "marginRight": "2%"}), html.Div([ html.Br(), html.Button("Refresh file list", id="refresh-btn", n_clicks=0, style={"marginRight": "10px"}), html.Button("Load & Plot", id="load-btn", n_clicks=0), ], style={"width": "30%", "display": "inline-block", "verticalAlign": "top"}), ]), ], style={"padding": "15px", "backgroundColor": "#f0f8ff", "borderRadius": "8px", "marginBottom": "20px"}), # --- Charts --- html.Div(id="charts-container"), # --- Table --- html.Div(id="table-container"), ], style={"maxWidth": "1200px", "margin": "0 auto", "padding": "20px", "fontFamily": "sans-serif"}) # --- Callbacks --- @app.callback( Output("results-dropdown", "options"), Input("refresh-btn", "n_clicks"), Input("progress-interval", "n_intervals"), ) def refresh_file_list(_n1, _n2): files = _saved_files() return [{"label": f.name, "value": str(f)} for f in files] @app.callback( Output("custom-configs-store", "data"), Output("config-checklist", "options"), Output("config-checklist", "value"), Input("add-custom-btn", "n_clicks"), State("custom-ensemble-input", "value"), State("custom-refine-dropdown", "value"), State("custom-configs-store", "data"), State("config-checklist", "options"), State("config-checklist", "value"), prevent_initial_call=True, ) def add_custom_config(_n, ensemble_n, refine, custom_cfgs, options, selected): """Add a custom configuration to the checklist.""" ensemble_n = ensemble_n or 0 refine = refine or "none" if ensemble_n > 0: name = f"Ensemble ({ensemble_n}) + {refine}" else: name = f"Custom (refine={refine})" cfg = {"refine": refine, "ensemble": ensemble_n} # Avoid duplicates for existing in custom_cfgs: if existing["name"] == name: return custom_cfgs, options, selected custom_cfgs.append({"name": name, **cfg}) options.append({"label": f" {name}", "value": name}) selected.append(name) return custom_cfgs, options, selected @app.callback( Output("progress-text", "children"), Output("progress-interval", "disabled"), Input("run-btn", "n_clicks"), Input("download-btn", "n_clicks"), Input("progress-interval", "n_intervals"), State("dataset-dropdown", "value"), State("method-radio", "value"), State("binary-input", "value"), State("max-cases-input", "value"), State("threads-input", "value"), State("config-checklist", "value"), State("custom-configs-store", "data"), prevent_initial_call=True, ) def handle_run_or_download(run_clicks, dl_clicks, _n_intervals, dataset, method, binary, max_cases, n_threads, selected_configs, custom_cfgs): triggered = callback_context.triggered_id if triggered == "download-btn" and not _run_state["running"]: try: download_dataset(dataset) return f"Downloaded {dataset}.", True except Exception as e: return f"Download error: {e}", True if triggered == "run-btn" and not _run_state["running"]: if not selected_configs: return "Select at least one configuration.", True # Build config list from presets + custom configs = [] custom_by_name = {c["name"]: c for c in (custom_cfgs or [])} for name in selected_configs: if name in CONFIG_PRESETS: configs.append((name, CONFIG_PRESETS[name])) elif name in custom_by_name: c = custom_by_name[name] configs.append((name, {"refine": c["refine"], "ensemble": c["ensemble"]})) if not configs: return "No valid configurations selected.", True t = threading.Thread( target=_run_in_thread, args=(dataset, method, binary or "build/src/kalign", max_cases or 0, n_threads or 1, configs), daemon=True, ) t.start() return f"Starting {len(configs)} configuration(s)...", False # Polling progress if _run_state["running"]: return _run_state["progress"], False if _run_state["done"]: return _run_state["progress"], True return dash.no_update, dash.no_update @app.callback( Output("charts-container", "children"), Output("table-container", "children"), Input("load-btn", "n_clicks"), Input("progress-interval", "n_intervals"), State("results-dropdown", "value"), prevent_initial_call=True, ) def update_charts(load_clicks, _n_intervals, selected_files): triggered = callback_context.triggered_id # If benchmark just finished, show those results immediately if triggered == "progress-interval" and _run_state["done"] and _run_state["results"]: df = _results_to_df(_run_state["results"]) elif triggered == "load-btn" and selected_files: all_results = [] for path in selected_files: data = _load_json(path) for r in data["results"]: r["source"] = Path(path).stem all_results.extend(data["results"]) df = _results_to_df(all_results) else: return dash.no_update, dash.no_update if df.empty: return html.P("No results to display."), "" charts = [] for fig_id, fig in _build_figures(df): charts.append(dcc.Graph(id=fig_id, figure=fig)) # Table display_cols = [c for c in df.columns if c not in ("error",)] table = dash_table.DataTable( data=df.to_dict("records"), columns=[{"name": c, "id": c} for c in display_cols], filter_action="native", sort_action="native", page_size=50, style_table={"overflowX": "auto"}, style_cell={"textAlign": "left", "padding": "5px"}, style_header={"fontWeight": "bold"}, ) return charts, html.Div([html.H3("Results Table"), table]) return app def main(): parser = argparse.ArgumentParser( description="Kalign benchmark dashboard", prog="python -m benchmarks.app", ) parser.add_argument("--host", default="127.0.0.1", help="Host to bind to (default: 127.0.0.1)") parser.add_argument("--port", type=int, default=8050, help="Port (default: 8050)") args = parser.parse_args() app = create_app() print(f"Starting dashboard at http://{args.host}:{args.port}") app.run(debug=False, host=args.host, port=args.port) if __name__ == "__main__": main() kalign-3.5.1/benchmarks/combined_improvements.py000066400000000000000000000224031515023132300220400ustar00rootroot00000000000000"""Measure cumulative/additive effect of kalign improvements on BAliBASE. Tests individual features and their combinations to determine additivity: Individual features (from baseline): 1. baseline: vsm_amax=0, no extras 2. +vsm: vsm_amax=2.0 only 3. +ref: refine=confident only (vsm=0) 4. +re1: realign=1 only (vsm=0) Stacking (additive): 5. +vsm+ref: vsm + refine 6. +vsm+re1: vsm + realign=1 (no refine) 7. +vsm+ref+re1: vsm + refine + realign=1 Ensemble path: 8. +ens3: ensemble=3 (uses vsm, internal post-refine) 9. +ens5: ensemble=5 10. +ens5+adapt: ensemble=5 + adaptive_budget Usage: uv run python -m benchmarks.combined_improvements -j 4 uv run python -m benchmarks.combined_improvements -j 4 --categories RV11 RV12 """ import argparse import json import statistics import tempfile import time from collections import defaultdict from concurrent.futures import ProcessPoolExecutor, as_completed from pathlib import Path import kalign from .datasets import get_cases from .scoring import parse_balibase_xml CONFIGS = [ # --- Individual features (from baseline) --- { "name": "baseline", "desc": "old defaults (vsm=0, no extras)", "vsm_amax": 0.0, "dist_scale": 0.0, "refine": "none", "ensemble": 0, "adaptive_budget": False, "realign": 0, }, { "name": "+vsm", "desc": "vsm_amax=2.0 only", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "none", "ensemble": 0, "adaptive_budget": False, "realign": 0, }, { "name": "+ref", "desc": "refine=confident only (vsm=0)", "vsm_amax": 0.0, "dist_scale": 0.0, "refine": "confident", "ensemble": 0, "adaptive_budget": False, "realign": 0, }, { "name": "+re1", "desc": "realign=1 only (vsm=0)", "vsm_amax": 0.0, "dist_scale": 0.0, "refine": "none", "ensemble": 0, "adaptive_budget": False, "realign": 1, }, # --- Stacking (additive combinations) --- { "name": "+vsm+ref", "desc": "vsm + refine", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "confident", "ensemble": 0, "adaptive_budget": False, "realign": 0, }, { "name": "+vsm+re1", "desc": "vsm + realign=1 (no refine)", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "none", "ensemble": 0, "adaptive_budget": False, "realign": 1, }, { "name": "+vsm+ref+re1", "desc": "vsm + refine + realign=1 (full stack)", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "confident", "ensemble": 0, "adaptive_budget": False, "realign": 1, }, # --- Ensemble path --- { "name": "+ens3", "desc": "ensemble=3 (uses vsm, internal post-refine)", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "confident", "ensemble": 3, "adaptive_budget": False, "realign": 0, }, { "name": "+ens5", "desc": "ensemble=5 (uses vsm, internal post-refine)", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "confident", "ensemble": 5, "adaptive_budget": False, "realign": 0, }, { "name": "+ens5+adapt", "desc": "ensemble=5 + adaptive_budget", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "confident", "ensemble": 5, "adaptive_budget": True, "realign": 0, }, # --- Ensemble + post-realign --- { "name": "+ens3+re1", "desc": "ensemble=3 + post-ensemble realign=1", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "confident", "ensemble": 3, "adaptive_budget": False, "realign": 1, }, { "name": "+ens5+re1", "desc": "ensemble=5 + post-ensemble realign=1", "vsm_amax": 2.0, "dist_scale": 0.0, "refine": "confident", "ensemble": 5, "adaptive_budget": False, "realign": 1, }, ] def _score_case(case, output_path): xml_path = case.reference.with_suffix(".xml") if xml_path.exists(): mask = parse_balibase_xml(xml_path) return kalign.compare_detailed(str(case.reference), str(output_path), column_mask=mask) return kalign.compare_detailed(str(case.reference), str(output_path)) def _run_one(args): case, config = args with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as tmp: tmp_path = tmp.name try: t0 = time.perf_counter() kalign.align_file_to_file( str(case.unaligned), tmp_path, format="fasta", seq_type=case.seq_type, vsm_amax=config["vsm_amax"], dist_scale=config["dist_scale"], refine=config["refine"], ensemble=config["ensemble"], adaptive_budget=config["adaptive_budget"], realign=config.get("realign", 0), ) wall_time = time.perf_counter() - t0 sp_score = kalign.compare(str(case.reference), tmp_path) scores = _score_case(case, tmp_path) return { "family": case.family, "dataset": case.dataset, "config": config["name"], "sp_score": sp_score, "recall": scores["recall"], "precision": scores["precision"], "f1": scores["f1"], "tc": scores["tc"], "wall_time": wall_time, } except Exception as e: return { "family": case.family, "dataset": case.dataset, "config": config["name"], "sp_score": 0, "recall": 0, "precision": 0, "f1": 0, "tc": 0, "wall_time": 0, "error": str(e), } finally: Path(tmp_path).unlink(missing_ok=True) def main(): parser = argparse.ArgumentParser(description="Combined improvements sweep on BAliBASE") parser.add_argument("-j", "--parallel", type=int, default=4) parser.add_argument("--max-cases", type=int, default=0) parser.add_argument("--categories", nargs="*", default=None, help="BAliBASE categories (e.g. RV11 RV12)") args = parser.parse_args() cases = get_cases("balibase", max_cases=args.max_cases if args.max_cases else None) if args.categories: cats = [c.upper() for c in args.categories] cases = [c for c in cases if any(cat in c.dataset.upper() for cat in cats)] print(f"{len(cases)} BAliBASE cases x {len(CONFIGS)} configs = {len(cases) * len(CONFIGS)} tasks") tasks = [(case, config) for case in cases for config in CONFIGS] t0 = time.perf_counter() results = [] done = 0 with ProcessPoolExecutor(max_workers=args.parallel) as pool: futures = {pool.submit(_run_one, t): t for t in tasks} for f in as_completed(futures): done += 1 r = f.result() results.append(r) if done % 100 == 0: print(f" {done}/{len(tasks)} ({time.perf_counter()-t0:.0f}s)") elapsed = time.perf_counter() - t0 print(f"All done in {elapsed:.0f}s\n") # Overall summary print("=" * 90) print("OVERALL") print("=" * 90) _print_config_table(results) # Per-category all_cats = sorted({r["dataset"] for r in results}) for cat in all_cats: cat_results = [r for r in results if r["dataset"] == cat] n_cases = len(cat_results) // len(CONFIGS) cat_label = cat.replace("balibase_", "") print(f"\n{'=' * 90}") print(f"{cat_label} ({n_cases} cases)") print(f"{'=' * 90}") _print_config_table(cat_results) # Save out = Path("benchmarks/results/combined_improvements.json") out.parent.mkdir(parents=True, exist_ok=True) with open(out, "w") as f: json.dump({"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S"), "results": results}, f, indent=2) print(f"\nSaved to {out}") def _print_config_table(results): config_names = [c["name"] for c in CONFIGS] groups = defaultdict(list) for r in results: if "error" not in r: groups[r["config"]].append(r) print(f"{'Config':<16} {'SP':>8} {'Recall':>8} {'Prec':>8} {'F1':>8} {'TC':>8} {'Time(s)':>9} {'dSP':>6} {'dF1':>6}") print("-" * 92) baseline_sp = None baseline_f1 = None for name in config_names: entries = groups.get(name, []) if not entries: continue sp = statistics.mean(r["sp_score"] for r in entries) rec = statistics.mean(r["recall"] for r in entries) prec = statistics.mean(r["precision"] for r in entries) f1 = statistics.mean(r["f1"] for r in entries) tc = statistics.mean(r["tc"] for r in entries) total_time = sum(r["wall_time"] for r in entries) if baseline_f1 is None: baseline_sp = sp baseline_f1 = f1 dsp = "" df1 = "" else: dsp = f"{sp - baseline_sp:+.1f}" df1 = f"{f1 - baseline_f1:+.3f}" print(f"{name:<16} {sp:>8.1f} {rec:>8.3f} {prec:>8.3f} {f1:>8.3f} {tc:>8.3f} {total_time:>9.1f} {dsp:>6} {df1:>6}") if __name__ == "__main__": main() kalign-3.5.1/benchmarks/datasets.py000066400000000000000000000233471515023132300172700ustar00rootroot00000000000000"""Dataset management for kalign benchmarks. Supports BAliBASE, BRAliBASE, and BaliFam100 benchmark datasets. """ import shutil import subprocess import tarfile import urllib.error import urllib.request from dataclasses import dataclass from pathlib import Path from typing import List, Optional BENCHMARKS_DIR = Path(__file__).parent DATA_DIR = BENCHMARKS_DIR / "data" DOWNLOADS_DIR = DATA_DIR / "downloads" @dataclass class BenchmarkCase: """A single benchmark test case (one MSA family).""" family: str dataset: str unaligned: Path reference: Path seq_type: str # "protein" | "rna" | "dna" # --------------------------------------------------------------------------- # BAliBASE # --------------------------------------------------------------------------- BALIBASE_URL = "http://www.lbgi.fr/balibase/BalibaseDownload/BAliBASE_R1-5.tar.gz" BALIBASE_DIR = DOWNLOADS_DIR / "bb3_release" def balibase_download() -> None: """Download and extract BAliBASE R1-5.""" DOWNLOADS_DIR.mkdir(parents=True, exist_ok=True) tarball = DOWNLOADS_DIR / "BAliBASE_R1-5.tar.gz" if BALIBASE_DIR.exists(): return print(f"Downloading BAliBASE from {BALIBASE_URL} ...") urllib.request.urlretrieve(BALIBASE_URL, tarball) print("Extracting ...") with tarfile.open(tarball) as tf: tf.extractall(DOWNLOADS_DIR) tarball.unlink() def balibase_is_available() -> bool: return BALIBASE_DIR.exists() def balibase_cases() -> List[BenchmarkCase]: """Discover BAliBASE test cases (*.tfa paired with *.msf).""" cases = [] for tfa in sorted(BALIBASE_DIR.rglob("*.tfa")): # Skip BBS (truncated) cases — only use full-length BB alignments if tfa.stem.startswith("BBS"): continue msf = tfa.with_suffix(".msf") if not msf.exists(): continue # Determine RV category from path parts = tfa.parts rv = "" for p in parts: if p.startswith("RV"): rv = p break family = tfa.stem cases.append( BenchmarkCase( family=family, dataset=f"balibase_{rv}" if rv else "balibase", unaligned=tfa, reference=msf, seq_type="protein", ) ) return cases # --------------------------------------------------------------------------- # BRAliBASE # --------------------------------------------------------------------------- BRALIBASE_URLS = [ ("data-set1", "https://web.archive.org/web/20160408045442id_/http://projects.binf.ku.dk/pgardner/bralibase/data-set1.tar.gz"), ("data-set2", "https://web.archive.org/web/20160408045453id_/http://projects.binf.ku.dk/pgardner/bralibase/data-set2.tar.gz"), ] def bralibase_download() -> None: """Download and extract BRAliBASE set1 + set2.""" DOWNLOADS_DIR.mkdir(parents=True, exist_ok=True) for name, url in BRALIBASE_URLS: target = DOWNLOADS_DIR / name if target.exists(): continue tarball = DOWNLOADS_DIR / f"{name}.tar.gz" print(f"Downloading BRAliBASE {name} from {url} ...") urllib.request.urlretrieve(url, tarball) print("Extracting ...") with tarfile.open(tarball) as tf: tf.extractall(DOWNLOADS_DIR) tarball.unlink() def bralibase_is_available() -> bool: return any((DOWNLOADS_DIR / name).exists() for name, _ in BRALIBASE_URLS) def bralibase_cases() -> List[BenchmarkCase]: """Discover BRAliBASE test cases. data-set1 structure: {family}/structural/*.fa paired with {family}/unaligned/*.fa families: g2intron, rRNA, SRP, tRNA, U5 data-set2 structure: structural/*.fasta paired with unaligned/*.fasta """ cases = [] for name, _ in BRALIBASE_URLS: base = DOWNLOADS_DIR / name if not base.exists(): continue # Glob for both .fa and .fasta reference files refs = sorted(list(base.rglob("structural/*.fa")) + list(base.rglob("structural/*.fasta"))) for ref in refs: # Corresponding unaligned file — try same extension first, then alternative unaligned_dir = ref.parent.parent / "unaligned" unaligned = unaligned_dir / ref.name if not unaligned.exists(): alt_ext = ".fasta" if ref.suffix == ".fa" else ".fa" unaligned = unaligned_dir / (ref.stem + alt_ext) if not unaligned.exists(): continue family = ref.stem # For data-set1, extract RNA family category from path # e.g. data-set1/tRNA/structural/aln1.fa -> category "tRNA" structural_parent = ref.parent.parent.name if structural_parent != name: # This is a subcategory (g2intron, rRNA, SRP, tRNA, U5) dataset = f"bralibase_{structural_parent}" else: dataset = f"bralibase_{name}" cases.append( BenchmarkCase( family=family, dataset=dataset, unaligned=unaligned, reference=ref, seq_type="rna", ) ) return cases # --------------------------------------------------------------------------- # BaliFam100 (CC0 - committed to repo) # --------------------------------------------------------------------------- BALIFAM_DIR = DATA_DIR / "balifam100" BALIFAM_REPO = "https://github.com/rcedgar/balifam.git" def balifam_download() -> None: """Clone BaliFam100 repo (CC0 license) into data/balifam100/.""" if BALIFAM_DIR.exists() and any(BALIFAM_DIR.iterdir()): return BALIFAM_DIR.mkdir(parents=True, exist_ok=True) print(f"Cloning BaliFam100 from {BALIFAM_REPO} ...") subprocess.run( ["git", "clone", "--depth", "1", BALIFAM_REPO, str(BALIFAM_DIR)], check=True, ) # Remove .git to keep it clean for committing git_dir = BALIFAM_DIR / ".git" if git_dir.exists(): shutil.rmtree(git_dir) def balifam_is_available() -> bool: return BALIFAM_DIR.exists() and ( any(BALIFAM_DIR.rglob("*.fa")) or any(BALIFAM_DIR.rglob("*.fasta")) ) def balifam_cases() -> List[BenchmarkCase]: """Discover BaliFam100 test cases.""" cases = [] # BaliFam100 has in/ (unaligned) and ref/ (reference) subdirectories in_dir = BALIFAM_DIR / "in" ref_dir = BALIFAM_DIR / "ref" if not in_dir.exists() or not ref_dir.exists(): # Try alternative structure for ref in sorted(BALIFAM_DIR.rglob("ref/*.fa")): in_file = ref.parent.parent / "in" / ref.name if not in_file.exists(): in_file = ref.parent.parent / "in" / ref.with_suffix(".fasta").name if not in_file.exists(): continue cases.append( BenchmarkCase( family=ref.stem, dataset="balifam100", unaligned=in_file, reference=ref, seq_type="protein", ) ) return cases for ref in sorted(ref_dir.glob("*")): if not ref.is_file(): continue in_file = in_dir / ref.name if not in_file.exists(): continue cases.append( BenchmarkCase( family=ref.stem, dataset="balifam100", unaligned=in_file, reference=ref, seq_type="protein", ) ) return cases # --------------------------------------------------------------------------- # Registry # --------------------------------------------------------------------------- DATASETS = { "balibase": { "download": balibase_download, "is_available": balibase_is_available, "cases": balibase_cases, }, "bralibase": { "download": bralibase_download, "is_available": bralibase_is_available, "cases": bralibase_cases, }, "balifam100": { "download": balifam_download, "is_available": balifam_is_available, "cases": balifam_cases, }, } def download_dataset(name: str) -> None: """Download a specific dataset by name, or 'all' for everything.""" if name == "all": for ds in DATASETS.values(): ds["download"]() elif name in DATASETS: DATASETS[name]["download"]() else: raise ValueError(f"Unknown dataset: {name}. Choose from: {list(DATASETS.keys())} or 'all'") def get_cases(name: str, max_cases: Optional[int] = None) -> List[BenchmarkCase]: """Get benchmark cases for a dataset. Downloads if not available.""" if name == "all": all_cases = [] for ds_name, ds in DATASETS.items(): if not ds["is_available"](): try: ds["download"]() except (urllib.error.URLError, OSError) as e: print(f"WARNING: Could not download {ds_name} dataset: {e}") continue if ds["is_available"](): all_cases.extend(ds["cases"]()) if max_cases: all_cases = all_cases[:max_cases] return all_cases if name not in DATASETS: raise ValueError(f"Unknown dataset: {name}. Choose from: {list(DATASETS.keys())}") ds = DATASETS[name] if not ds["is_available"](): try: ds["download"]() except (urllib.error.URLError, OSError) as e: print(f"WARNING: Could not download {name} dataset: {e}") print("Skipping benchmark — dataset unavailable.") return [] cases = ds["cases"]() if max_cases: cases = cases[:max_cases] return cases kalign-3.5.1/benchmarks/downstream/000077500000000000000000000000001515023132300172605ustar00rootroot00000000000000kalign-3.5.1/benchmarks/downstream/__init__.py000066400000000000000000000001101515023132300213610ustar00rootroot00000000000000"""Downstream application benchmarks for kalign ensemble confidence.""" kalign-3.5.1/benchmarks/downstream/__main__.py000066400000000000000000000142321515023132300213540ustar00rootroot00000000000000"""Unified CLI entry point for downstream benchmarks. Usage:: python -m benchmarks.downstream --all -j 4 python -m benchmarks.downstream --all -j 4 --quick python -m benchmarks.downstream calibration -j 4 python -m benchmarks.downstream positive_selection --quick python -m benchmarks.downstream --figures -o benchmarks/figures/ """ from __future__ import annotations import argparse import logging import os import sys import time from pathlib import Path logger = logging.getLogger("benchmarks.downstream") PIPELINES = ["alignment_accuracy", "calibration", "positive_selection", "phylo_accuracy", "hmmer_detection"] def _run_pipeline(name: str, params: dict) -> None: """Import and run a single pipeline by name.""" if name == "alignment_accuracy": from .alignment_accuracy import run_pipeline elif name == "calibration": from .calibration import run_pipeline elif name == "positive_selection": from .positive_selection import run_pipeline elif name == "phylo_accuracy": from .phylo_accuracy import run_pipeline elif name == "hmmer_detection": from .hmmer_detection import run_pipeline else: raise ValueError(f"Unknown pipeline: {name!r}") logger.info("Starting pipeline: %s", name) start = time.perf_counter() run_pipeline(params) elapsed = time.perf_counter() - start logger.info("Pipeline %s completed in %.1f s", name, elapsed) def _run_figures(results_dir: Path, output_dir: Path) -> None: """Generate all publication figures from saved results.""" from .figures import generate_all_figures generate_all_figures(str(results_dir), str(output_dir)) def main(argv: list[str] | None = None) -> int: """Parse arguments and dispatch to pipelines.""" parser = argparse.ArgumentParser( prog="python -m benchmarks.downstream", description="Kalign downstream application benchmarks", ) parser.add_argument( "pipelines", nargs="*", default=[], metavar="PIPELINE", help="Pipeline(s) to run: alignment_accuracy, calibration, " "positive_selection, phylo_accuracy, hmmer_detection, or 'all'.", ) parser.add_argument( "--all", action="store_true", help="Run all four pipelines.", ) parser.add_argument( "--figures", action="store_true", help="Generate publication figures from saved results.", ) _default_jobs = os.cpu_count() or 1 parser.add_argument( "-j", "--jobs", type=int, default=_default_jobs, help=f"Number of parallel jobs (default: {_default_jobs}, all cores). " "Use -j 1 for sequential execution with accurate timing.", ) parser.add_argument( "--quick", action="store_true", help="Quick smoke test (5 cases per pipeline).", ) parser.add_argument( "--data-dir", type=Path, default=Path("benchmarks/data"), help="Data directory (default: benchmarks/data).", ) parser.add_argument( "--results-dir", type=Path, default=Path("benchmarks/results"), help="Results directory (default: benchmarks/results).", ) parser.add_argument( "-o", "--output-dir", type=Path, default=Path("benchmarks/figures"), help="Figure output directory (default: benchmarks/figures).", ) parser.add_argument( "--methods", nargs="+", default=None, help="Override method list (default: pipeline-specific defaults).", ) parser.add_argument( "--no-cache", action="store_true", help="Ignore cached results and recompute everything.", ) parser.add_argument( "--full", action="store_true", help="Use full simulation grids and all methods (for publication).", ) parser.add_argument( "-v", "--verbose", action="store_true", help="Enable debug logging.", ) parser.add_argument( "--depths", nargs="+", type=float, default=None, help="Filter simulations to specific tree depths (e.g., --depths 4.0).", ) args = parser.parse_args(argv) # Configure logging level = logging.DEBUG if args.verbose else logging.INFO logging.basicConfig( level=level, format="%(asctime)s %(name)s %(levelname)s %(message)s", datefmt="%H:%M:%S", ) # Validate pipeline names valid = set(PIPELINES + ["all"]) for p in args.pipelines: if p not in valid: parser.error(f"Unknown pipeline: {p!r}. Choose from: {', '.join(PIPELINES)}, all") # Determine which pipelines to run pipelines_to_run: list[str] = [] if args.all or "all" in args.pipelines: pipelines_to_run = list(PIPELINES) else: pipelines_to_run = list(args.pipelines) # Must specify at least one action if not pipelines_to_run and not args.figures: parser.print_help() return 1 # Build common params dict params = { "data_dir": str(args.data_dir), "results_dir": str(args.results_dir), "n_jobs": args.jobs, "quick": args.quick, "no_cache": args.no_cache, "full": args.full, } if args.methods: params["methods"] = args.methods if args.depths: params["depths"] = args.depths # Run pipelines failed: list[str] = [] for name in pipelines_to_run: try: _run_pipeline(name, params) except Exception: logger.exception("Pipeline %s failed", name) failed.append(name) # Generate figures if args.figures: try: _run_figures(args.results_dir, args.output_dir) except Exception: logger.exception("Figure generation failed") failed.append("figures") # Summary if failed: logger.error("Failed: %s", ", ".join(failed)) return 1 if pipelines_to_run: logger.info("All pipelines completed successfully.") if args.figures: logger.info("Figures saved to %s", args.output_dir) return 0 if __name__ == "__main__": sys.exit(main()) kalign-3.5.1/benchmarks/downstream/alignment_accuracy.py000066400000000000000000000303061515023132300234640ustar00rootroot00000000000000"""Pipeline: Alignment Accuracy (BAliBASE + BRAliBASE). Scores alignment quality for all 6 methods against reference alignments. BAliBASE cases use XML core-block masks; BRAliBASE uses all columns. Usage:: python -m benchmarks.downstream alignment_accuracy -j 8 python -m benchmarks.downstream alignment_accuracy --quick -j 4 """ from __future__ import annotations import json import logging from concurrent.futures import ProcessPoolExecutor, as_completed from dataclasses import asdict from pathlib import Path logger = logging.getLogger(__name__) # Default methods for alignment accuracy (all 6 + true reference) _DEFAULT_METHODS = [ "kalign", "kalign_cons", "kalign_ens3", "mafft", "muscle", "clustalo", ] # --------------------------------------------------------------------------- # Single-case runner # --------------------------------------------------------------------------- def _run_case( case_dict: dict, method_name: str, work_dir: str, fingerprint: str | None = None, ) -> dict: """Align one case with one method and score against reference. Parameters ---------- case_dict : dict Serialised BenchmarkCase with keys: family, dataset, unaligned, reference, seq_type. method_name : str Key into ``utils.METHODS``. work_dir : str Scratch directory. fingerprint : str or None Tool versions fingerprint for caching (None disables cache). Returns ------- dict Per-case result with scoring metrics, timing, and metadata. """ import kalign as _kalign from ..scoring import parse_balibase_xml from .utils import ( cache_load, cache_save, clean_work_dir, parse_fasta, run_method, write_fasta, ) wd = Path(work_dir) family = case_dict["family"] dataset = case_dict["dataset"] seq_type = case_dict["seq_type"] unaligned = Path(case_dict["unaligned"]) reference = Path(case_dict["reference"]) # Check cache if fingerprint: cached = cache_load(wd, fingerprint) if cached is not None: return cached clean_work_dir(wd) wd.mkdir(parents=True, exist_ok=True) try: # Align aln_result = run_method( method_name, unaligned, wd, seq_type=seq_type, ) # Write alignment for scoring aln_path = wd / "aligned.fasta" write_fasta(aln_result.names, aln_result.sequences, aln_path) # Score: BAliBASE uses XML core-block mask, BRAliBASE uses all columns xml_path = reference.with_suffix(".xml") if xml_path.exists(): mask = parse_balibase_xml(xml_path) scores = _kalign.compare_detailed( str(reference), str(aln_path), column_mask=mask ) else: # Check for gapless reference (conserved RNA) — skip ref_names, ref_seqs = parse_fasta(reference) if ref_seqs and all("-" not in s for s in ref_seqs): return { "family": family, "dataset": dataset, "benchmark": "bralibase" if "brali" in dataset else "balibase", "method": method_name, "skipped": True, "reason": "gapless_reference", } scores = _kalign.compare_detailed( str(reference), str(aln_path), max_gap_frac=-1.0 ) result = { "family": family, "dataset": dataset, "benchmark": "bralibase" if "brali" in dataset else "balibase", "method": method_name, "recall": scores.get("recall", -1.0), "precision": scores.get("precision", -1.0), "f1": scores.get("f1", -1.0), "tc": scores.get("tc", -1.0), "wall_time": aln_result.wall_time, "peak_memory_mb": aln_result.peak_memory_mb, } if fingerprint: cache_save(wd, fingerprint, result) return result except Exception as exc: logger.warning("Case %s/%s failed: %s", family, method_name, exc) return { "family": family, "dataset": dataset, "benchmark": "bralibase" if "brali" in dataset else "balibase", "method": method_name, "error": str(exc), } # --------------------------------------------------------------------------- # Pipeline entry point # --------------------------------------------------------------------------- def run_pipeline(params: dict) -> dict: """Run the alignment accuracy pipeline. Parameters ---------- params : dict Configuration with keys: - ``data_dir`` : str or Path -- base data directory - ``results_dir`` : str or Path -- results output directory - ``methods`` : list[str] -- method names to evaluate - ``n_jobs`` : int -- parallel workers - ``quick`` : bool -- if True, limit to 5 cases per dataset - ``no_cache`` : bool -- disable caching Returns ------- dict Result dict with provenance, cases, and summary. """ from ..datasets import get_cases from .provenance import collect_provenance, result_path, update_latest_symlink from .utils import METHODS, tool_versions_fingerprint data_dir = Path(params.get("data_dir", "benchmarks/data")) results_dir = Path(params.get("results_dir", "benchmarks/results")) methods = params.get("methods", _DEFAULT_METHODS) n_jobs = params.get("n_jobs", 1) quick = params.get("quick", False) # Validate methods for m in methods: if m not in METHODS: raise ValueError(f"Unknown method {m!r}. Available: {sorted(METHODS.keys())}") # Load BAliBASE + BRAliBASE cases balibase_cases = get_cases("balibase") bralibase_cases = get_cases("bralibase") all_cases = balibase_cases + bralibase_cases if quick: # Take first 5 from each dataset balibase_subset = balibase_cases[:5] bralibase_subset = bralibase_cases[:5] all_cases = balibase_subset + bralibase_subset logger.info( "Alignment accuracy: %d cases x %d methods = %d total", len(all_cases), len(methods), len(all_cases) * len(methods), ) # Compute fingerprint if params.get("no_cache"): fingerprint = None logger.info("Caching disabled (--no-cache)") else: fingerprint = tool_versions_fingerprint() logger.info("Tool versions fingerprint: %s", fingerprint) # Build work items work_items = [] for case in all_cases: for method_name in methods: case_dict = { "family": case.family, "dataset": case.dataset, "unaligned": str(case.unaligned), "reference": str(case.reference), "seq_type": case.seq_type, } work_dir = str( data_dir / "alignment_accuracy_work" / case.dataset / case.family / method_name ) work_items.append((case_dict, method_name, work_dir, fingerprint)) # Execute from tqdm import tqdm results: list[dict] = [] pbar = tqdm(total=len(work_items), desc="Alignment accuracy", unit="case") if n_jobs <= 1: for case_dict, method_name, work_dir, fp in work_items: r = _run_case(case_dict, method_name, work_dir, fp) results.append(r) pbar.update(1) else: with ProcessPoolExecutor(max_workers=n_jobs) as pool: futures = { pool.submit(_run_case, cd, mn, wd, fp): (cd, mn) for cd, mn, wd, fp in work_items } for fut in as_completed(futures): try: results.append(fut.result()) except Exception as exc: cd, mn = futures[fut] logger.error("Worker failed: %s/%s: %s", cd["family"], mn, exc) results.append({ "family": cd["family"], "dataset": cd["dataset"], "method": mn, "error": str(exc), }) pbar.update(1) pbar.close() # Filter errors and skipped successful = [r for r in results if "error" not in r and not r.get("skipped")] skipped = [r for r in results if r.get("skipped")] errors = [r for r in results if "error" in r] logger.info( "%d successful, %d skipped, %d errors", len(successful), len(skipped), len(errors), ) # Aggregate summary summary = _aggregate_summary(successful, methods) # Provenance provenance = collect_provenance(params) output = { "provenance": asdict(provenance), "cases": results, "summary": summary, } # Save out_path = result_path(results_dir, "alignment_accuracy") with open(out_path, "w") as fh: json.dump(output, fh, indent=2, default=str) update_latest_symlink(out_path) logger.info("Results saved to %s", out_path) # Print summary _print_summary(summary, methods) return output # --------------------------------------------------------------------------- # Aggregation # --------------------------------------------------------------------------- def _aggregate_summary(cases: list[dict], methods: list[str]) -> dict: """Compute per-method and per-category aggregated metrics.""" from collections import defaultdict import numpy as np summary: dict = {} for method in methods: mc = [c for c in cases if c.get("method") == method] if not mc: summary[method] = {"n_cases": 0} continue recall_vals = [c["recall"] for c in mc if c.get("recall", -1) >= 0] prec_vals = [c["precision"] for c in mc if c.get("precision", -1) >= 0] f1_vals = [c["f1"] for c in mc if c.get("f1", -1) >= 0] tc_vals = [c["tc"] for c in mc if c.get("tc", -1) >= 0] time_vals = [c["wall_time"] for c in mc if "wall_time" in c] summary[method] = { "n_cases": len(mc), "mean_recall": float(np.mean(recall_vals)) if recall_vals else None, "mean_precision": float(np.mean(prec_vals)) if prec_vals else None, "mean_f1": float(np.mean(f1_vals)) if f1_vals else None, "mean_tc": float(np.mean(tc_vals)) if tc_vals else None, "mean_wall_time": float(np.mean(time_vals)) if time_vals else None, } # Per-category breakdown by_dataset: dict[str, list[dict]] = defaultdict(list) for c in mc: by_dataset[c["dataset"]].append(c) categories = {} for ds, ds_cases in sorted(by_dataset.items()): ds_recall = [c["recall"] for c in ds_cases if c.get("recall", -1) >= 0] ds_f1 = [c["f1"] for c in ds_cases if c.get("f1", -1) >= 0] ds_tc = [c["tc"] for c in ds_cases if c.get("tc", -1) >= 0] categories[ds] = { "n_cases": len(ds_cases), "mean_recall": float(np.mean(ds_recall)) if ds_recall else None, "mean_f1": float(np.mean(ds_f1)) if ds_f1 else None, "mean_tc": float(np.mean(ds_tc)) if ds_tc else None, } summary[method]["categories"] = categories return summary def _print_summary(summary: dict, methods: list[str]) -> None: """Print a summary table to the logger.""" logger.info("=" * 80) logger.info("Alignment Accuracy Summary") logger.info("=" * 80) logger.info( "%-18s %5s %8s %8s %8s %8s %8s", "Method", "N", "Recall", "Prec", "F1", "TC", "Time", ) logger.info("-" * 80) for m in methods: s = summary.get(m, {}) n = s.get("n_cases", 0) if n == 0: logger.info("%-18s %5d %8s", m, 0, "no data") continue logger.info( "%-18s %5d %8.3f %8.3f %8.3f %8.3f %7.2fs", m, n, s.get("mean_recall") or 0, s.get("mean_precision") or 0, s.get("mean_f1") or 0, s.get("mean_tc") or 0, s.get("mean_wall_time") or 0, ) logger.info("=" * 80) kalign-3.5.1/benchmarks/downstream/calibration.py000066400000000000000000000613341515023132300221300ustar00rootroot00000000000000"""Pipeline 0: Confidence Calibration. Validates that kalign ensemble confidence scores are meaningful by comparing predicted per-column confidence to actual column correctness against known true alignments from INDELible simulations. Usage:: python -m benchmarks.downstream.calibration -j 4 python -m benchmarks.downstream.calibration -j 4 --quick """ from __future__ import annotations import json import logging import tempfile from concurrent.futures import ProcessPoolExecutor, as_completed from dataclasses import asdict, dataclass, field from pathlib import Path from typing import List, Optional logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- # Per-case result # --------------------------------------------------------------------------- @dataclass class CaseResult: """Result from a single simulation x method calibration case.""" sim_id: str method: str predicted_confidence: list[float] # per-column confidence actual_correct: list[int] # 1 if column matches true alignment, 0 otherwise sp_score: float tc_score: float wall_time: float peak_memory_mb: float # --------------------------------------------------------------------------- # Aggregated calibration result # --------------------------------------------------------------------------- @dataclass class CalibrationResult: """Aggregated calibration result across all cases and methods.""" provenance: dict cases: list[dict] # serialised CaseResults summary: dict # aggregated metrics per method # --------------------------------------------------------------------------- # Column correctness # --------------------------------------------------------------------------- def _column_correctness( test_seqs: list[str], true_seqs: list[str], test_names: list[str], true_names: list[str], ) -> list[int]: """Check per-column correctness of *test* alignment vs *true* alignment. For each column in the test alignment, determine whether the set of residue pairs in that column matches the corresponding column in the true alignment. A column is correct (1) if every pair of non-gap characters in the test column appears at the same aligned positions in the true alignment; otherwise it is incorrect (0). Sequences are matched by name between test and true alignments. Parameters ---------- test_seqs, true_seqs : list[str] Aligned sequences (all same length within each list). test_names, true_names : list[str] Corresponding sequence names. Returns ------- list[int] One entry per column in the test alignment: 1 = correct, 0 = incorrect. """ if not test_seqs: return [] # Build name -> index mapping for the true alignment true_idx = {name: i for i, name in enumerate(true_names)} # Reorder true sequences to match test sequence order order = [] for name in test_names: if name not in true_idx: raise ValueError( f"Sequence {name!r} in test alignment not found in true alignment" ) order.append(true_idx[name]) reordered_true = [true_seqs[i] for i in order] # Build a mapping: for each sequence, residue position -> true column index # "residue position" = count of non-gap characters seen so far n_seqs = len(test_seqs) true_ncols = len(reordered_true[0]) if reordered_true else 0 # For each sequence, build: residue_index -> true_column true_res_to_col: list[dict[int, int]] = [] for s in range(n_seqs): mapping: dict[int, int] = {} res_idx = 0 for col in range(true_ncols): c = reordered_true[s][col] if c != "-" and c != ".": mapping[res_idx] = col res_idx += 1 true_res_to_col.append(mapping) # For the test alignment, do the same: track residue positions test_ncols = len(test_seqs[0]) test_res_counters = [0] * n_seqs result = [] for col in range(test_ncols): # Collect the true column index for each non-gap character in this test column true_cols_for_residues: list[int] = [] residue_indices_this_col: list[tuple[int, int]] = [] # (seq_idx, res_idx) for s in range(n_seqs): c = test_seqs[s][col] if c != "-" and c != ".": res_idx = test_res_counters[s] true_col = true_res_to_col[s].get(res_idx) if true_col is not None: true_cols_for_residues.append(true_col) residue_indices_this_col.append((s, res_idx)) test_res_counters[s] += 1 # A column is correct if all non-gap residues in this column # are aligned to the same column in the true alignment if len(true_cols_for_residues) <= 1: # 0 or 1 non-gap characters: trivially correct result.append(1) elif all(tc == true_cols_for_residues[0] for tc in true_cols_for_residues): result.append(1) else: result.append(0) return result # --------------------------------------------------------------------------- # Calibration metrics # --------------------------------------------------------------------------- def brier_score(predicted: list[float], actual: list[int]) -> float: """Brier score: mean squared error between predicted confidence and binary correctness. Parameters ---------- predicted : list[float] Predicted confidence values in [0, 1]. actual : list[int] Binary correctness values (0 or 1). Returns ------- float Brier score (lower is better). Returns 0.0 for empty inputs. """ n = len(predicted) if n == 0: return 0.0 total = 0.0 for p, o in zip(predicted, actual): total += (p - o) ** 2 return total / n def expected_calibration_error( predicted: list[float], actual: list[int], n_bins: int = 10, ) -> float: """Expected Calibration Error (ECE). Bins predictions into *n_bins* equal-width bins over [0, 1], computes |avg_confidence - fraction_correct| per bin, weighted by the fraction of samples in each bin. Parameters ---------- predicted : list[float] Predicted confidence values in [0, 1]. actual : list[int] Binary correctness values (0 or 1). n_bins : int Number of equal-width bins. Returns ------- float ECE value (lower is better). Returns 0.0 for empty inputs. """ n = len(predicted) if n == 0: return 0.0 bin_sums_conf = [0.0] * n_bins bin_sums_correct = [0.0] * n_bins bin_counts = [0] * n_bins for p, o in zip(predicted, actual): # Determine bin index b = int(p * n_bins) if b >= n_bins: b = n_bins - 1 bin_sums_conf[b] += p bin_sums_correct[b] += o bin_counts[b] += 1 ece = 0.0 for b in range(n_bins): if bin_counts[b] > 0: avg_conf = bin_sums_conf[b] / bin_counts[b] frac_correct = bin_sums_correct[b] / bin_counts[b] ece += (bin_counts[b] / n) * abs(avg_conf - frac_correct) return ece def calibration_curve( predicted: list[float], actual: list[int], n_bins: int = 10, ) -> tuple[list[float], list[float], list[int]]: """Compute calibration curve data for plotting. Parameters ---------- predicted : list[float] Predicted confidence values in [0, 1]. actual : list[int] Binary correctness values (0 or 1). n_bins : int Number of equal-width bins over [0, 1]. Returns ------- bin_centers : list[float] Midpoint of each bin. fraction_correct : list[float] Fraction of correct predictions in each bin (NaN for empty bins). bin_counts : list[int] Number of samples in each bin. """ bin_width = 1.0 / n_bins bin_centers = [(b + 0.5) * bin_width for b in range(n_bins)] bin_sums_correct = [0.0] * n_bins bin_counts = [0] * n_bins for p, o in zip(predicted, actual): b = int(p * n_bins) if b >= n_bins: b = n_bins - 1 bin_sums_correct[b] += o bin_counts[b] += 1 fraction_correct = [] for b in range(n_bins): if bin_counts[b] > 0: fraction_correct.append(bin_sums_correct[b] / bin_counts[b]) else: fraction_correct.append(float("nan")) return bin_centers, fraction_correct, bin_counts # --------------------------------------------------------------------------- # Single-case runner # --------------------------------------------------------------------------- def run_calibration_case( sim_dataset, method_name: str, work_dir: Path, seq_type: str = "protein", ) -> CaseResult: """Run one calibration case: align with *method_name*, evaluate column correctness. Parameters ---------- sim_dataset : SimulatedDataset A simulated dataset with known true alignment. method_name : str Key into ``utils.METHODS``. work_dir : Path Scratch directory for alignment output files. seq_type : str Sequence type hint for the aligner. Returns ------- CaseResult """ from .utils import alignment_accuracy, parse_fasta, run_method work_dir = Path(work_dir) work_dir.mkdir(parents=True, exist_ok=True) sim_id = sim_dataset.params.get("sim_id", "unknown") if hasattr(sim_dataset, "params") and isinstance(sim_dataset.params, dict): sim_id = sim_dataset.params.get("sim_id", sim_id) # "true" method: use the true alignment directly as a performance ceiling if method_name == "true": true_names, true_seqs = parse_fasta(sim_dataset.true_alignment) aln_len = len(true_seqs[0]) if true_seqs else 0 return CaseResult( sim_id=sim_id, method="true", predicted_confidence=[1.0] * aln_len, actual_correct=[1] * aln_len, sp_score=1.0, tc_score=1.0, wall_time=0.0, peak_memory_mb=0.0, ) # Run the alignment method aln_result = run_method(method_name, sim_dataset.unaligned, work_dir, seq_type=seq_type) # Load the true alignment true_names, true_seqs = parse_fasta(sim_dataset.true_alignment) # Compute alignment accuracy (SP, TC) acc = alignment_accuracy( aln_result.sequences, true_seqs, aln_result.names, true_names, ) # Compute per-column correctness correctness = _column_correctness( aln_result.sequences, true_seqs, aln_result.names, true_names, ) # Extract confidence: use column_confidence if available, else uniform 1.0 if aln_result.column_confidence is not None: confidence = list(aln_result.column_confidence) # After masking, the confidence list may be longer than the alignment; # truncate or pad to match the alignment length aln_len = len(aln_result.sequences[0]) if aln_result.sequences else 0 if len(confidence) > aln_len: confidence = confidence[:aln_len] elif len(confidence) < aln_len: confidence.extend([1.0] * (aln_len - len(confidence))) else: # Methods without confidence get uniform 1.0 aln_len = len(aln_result.sequences[0]) if aln_result.sequences else 0 confidence = [1.0] * aln_len return CaseResult( sim_id=sim_id, method=method_name, predicted_confidence=confidence, actual_correct=correctness, sp_score=acc["sp_score"], tc_score=acc["tc_score"], wall_time=aln_result.wall_time, peak_memory_mb=aln_result.peak_memory_mb, ) def _run_one_calibration(sim_dataset, method_name, work_dir, fingerprint=None): """Worker for parallel calibration cases. Returns a dict.""" from dataclasses import asdict as _asdict from .utils import cache_load, cache_save, clean_work_dir work_dir = Path(work_dir) if fingerprint: cached = cache_load(work_dir, fingerprint) if cached is not None: return cached # Remove stale output files from previous runs clean_work_dir(work_dir) case = run_calibration_case(sim_dataset, method_name, work_dir, seq_type="protein") result_dict = _asdict(case) if fingerprint: cache_save(work_dir, fingerprint, result_dict) return result_dict # --------------------------------------------------------------------------- # Pipeline entry point # --------------------------------------------------------------------------- def run_pipeline(params: dict) -> CalibrationResult: """Run the full confidence calibration pipeline. Parameters ---------- params : dict Configuration with keys: - ``data_dir`` : str or Path -- base directory for simulation data - ``results_dir`` : str or Path -- base directory for result JSON files - ``methods`` : list[str] -- method names to evaluate (keys in METHODS) - ``n_simulations`` : int -- override number of simulation cases (default: use PROTEIN_GRID) - ``n_jobs`` : int -- parallelism level (default 1) - ``quick`` : bool -- if True, only 5 cases for smoke testing Returns ------- CalibrationResult """ from dataclasses import asdict as _asdict from .provenance import collect_provenance, result_path, update_latest_symlink from .simulation import ( PROTEIN_GRID, PROTEIN_GRID_FULL, generate_indelible_dataset, iter_simulation_params, random_birth_death_tree, ) from .utils import METHODS, cache_load, cache_save, clean_work_dir, tool_versions_fingerprint data_dir = Path(params.get("data_dir", "benchmarks/data/downstream/calibration")) results_dir = Path(params.get("results_dir", "benchmarks/results")) # Calibration evaluates raw confidence scores → masked methods are excluded _default_methods = ["kalign", "kalign_cons", "kalign_ens3", "true"] methods = params.get("methods", _default_methods) quick = params.get("quick", False) n_jobs = params.get("n_jobs", 1) data_dir.mkdir(parents=True, exist_ok=True) # Validate method names for m in methods: if m not in METHODS: raise ValueError(f"Unknown method {m!r}. Available: {sorted(METHODS.keys())}") # Generate simulation parameter sets grid = PROTEIN_GRID_FULL if params.get("full") else PROTEIN_GRID sim_params_list = list(iter_simulation_params(grid, "WAG")) # Allow override of the number of simulations n_simulations = params.get("n_simulations") if n_simulations is not None: sim_params_list = sim_params_list[:n_simulations] if quick: sim_params_list = sim_params_list[:5] logger.info( "Running calibration pipeline: %d simulations x %d methods = %d cases", len(sim_params_list), len(methods), len(sim_params_list) * len(methods), ) # Step 1: Generate simulated datasets (sequential -- INDELible is fast) from tqdm import tqdm sim_datasets = [] for sp in tqdm(sim_params_list, desc="Generating simulations", unit="sim"): sim_id = sp["sim_id"] sim_dir = data_dir / sim_id tree = random_birth_death_tree( n_taxa=sp["n_taxa"], target_depth=sp["target_depth"], seed=sp.get("seed", 42), ) sim_dataset = generate_indelible_dataset( tree=tree, model=sp["model"], seq_length=sp["seq_length"], indel_rate=sp["indel_rate"], indel_length_mean=sp.get("indel_length_mean", 2.0), output_dir=sim_dir, seed=sp.get("seed", 42), ) sim_dataset.params["sim_id"] = sim_id sim_datasets.append(sim_dataset) # Step 2: Build work items for alignment + scoring work_items = [] for sim_dataset in sim_datasets: sim_id = sim_dataset.params["sim_id"] sim_dir = data_dir / sim_id for method_name in methods: work_dir = sim_dir / f"work_{method_name}" work_items.append((sim_dataset, method_name, work_dir)) # Compute fingerprint once for all workers (None disables caching) if params.get("no_cache"): fingerprint = None logger.info("Caching disabled (--no-cache)") else: fingerprint = tool_versions_fingerprint() logger.info("Tool versions fingerprint: %s", fingerprint) # Step 3: Run alignment cases (parallel when n_jobs > 1) all_cases: list[dict] = [] n_cached = 0 pbar = tqdm(total=len(work_items), desc="Calibration", unit="case") if n_jobs <= 1: for sim_dataset, method_name, work_dir in work_items: try: cached = cache_load(work_dir, fingerprint) if fingerprint else None if cached is not None: all_cases.append(cached) n_cached += 1 else: clean_work_dir(work_dir) case = run_calibration_case( sim_dataset, method_name, work_dir, seq_type="protein", ) result_dict = _asdict(case) if fingerprint: cache_save(work_dir, fingerprint, result_dict) all_cases.append(result_dict) except Exception as exc: logger.error("Failed: %s / %s: %s", sim_dataset.params["sim_id"], method_name, exc) all_cases.append({ "sim_id": sim_dataset.params["sim_id"], "method": method_name, "error": str(exc), }) pbar.update(1) pbar.set_postfix(cached=n_cached, computed=pbar.n - n_cached) else: with ProcessPoolExecutor(max_workers=n_jobs) as pool: futures = {} for sim_dataset, method_name, work_dir in work_items: fut = pool.submit( _run_one_calibration, sim_dataset, method_name, work_dir, fingerprint=fingerprint, ) futures[fut] = (sim_dataset.params["sim_id"], method_name) for fut in as_completed(futures): sim_id, method_name = futures[fut] try: result_dict = fut.result() all_cases.append(result_dict) except Exception as exc: logger.error("Failed: %s / %s: %s", sim_id, method_name, exc) all_cases.append({ "sim_id": sim_id, "method": method_name, "error": str(exc), }) pbar.update(1) pbar.close() # Aggregate results per method summary = _aggregate_summary(all_cases) # Collect provenance provenance = collect_provenance(params) result = CalibrationResult( provenance=_asdict(provenance), cases=all_cases, summary=summary, ) # Save results out_path = result_path(results_dir, "calibration") with open(out_path, "w") as fh: json.dump( { "provenance": result.provenance, "cases": result.cases, "summary": result.summary, }, fh, indent=2, default=str, ) update_latest_symlink(out_path) logger.info("Results saved to %s", out_path) return result def _aggregate_summary(cases: list[dict]) -> dict: """Compute per-method summary statistics from case result dicts. Returns a dict keyed by method name with aggregated metrics. """ from collections import defaultdict method_preds: dict[str, list[float]] = defaultdict(list) method_actuals: dict[str, list[int]] = defaultdict(list) method_sp: dict[str, list[float]] = defaultdict(list) method_tc: dict[str, list[float]] = defaultdict(list) method_time: dict[str, list[float]] = defaultdict(list) method_mem: dict[str, list[float]] = defaultdict(list) for case in cases: if "error" in case: continue m = case["method"] method_preds[m].extend(case.get("predicted_confidence", [])) method_actuals[m].extend(case.get("actual_correct", [])) if case.get("sp_score", -1.0) >= 0: method_sp[m].append(case["sp_score"]) if case.get("tc_score", -1.0) >= 0: method_tc[m].append(case["tc_score"]) method_time[m].append(case.get("wall_time", 0.0)) method_mem[m].append(case.get("peak_memory_mb", 0.0)) summary: dict[str, dict] = {} for m in sorted(method_preds.keys()): preds = method_preds[m] actuals = method_actuals[m] bs = brier_score(preds, actuals) ece = expected_calibration_error(preds, actuals) bin_centers, frac_correct, bin_counts = calibration_curve(preds, actuals) sp_vals = method_sp[m] tc_vals = method_tc[m] time_vals = method_time[m] mem_vals = method_mem[m] summary[m] = { "brier_score": bs, "ece": ece, "calibration_curve": { "bin_centers": bin_centers, "fraction_correct": frac_correct, "bin_counts": bin_counts, }, "n_columns_total": len(preds), "mean_sp": sum(sp_vals) / len(sp_vals) if sp_vals else None, "mean_tc": sum(tc_vals) / len(tc_vals) if tc_vals else None, "mean_time": sum(time_vals) / len(time_vals) if time_vals else None, "mean_peak_memory_mb": sum(mem_vals) / len(mem_vals) if mem_vals else None, "n_cases": len(time_vals), } return summary # --------------------------------------------------------------------------- # Result loading # --------------------------------------------------------------------------- def load_results(results_dir: Path | str) -> CalibrationResult: """Load calibration results from the latest.json symlink. Parameters ---------- results_dir : Path or str Base results directory (the ``calibration/`` subdirectory is appended automatically). Returns ------- CalibrationResult """ results_dir = Path(results_dir) cal_dir = results_dir / "calibration" latest = cal_dir / "latest.json" with open(latest) as fh: data = json.load(fh) return CalibrationResult( provenance=data.get("provenance", {}), cases=data.get("cases", []), summary=data.get("summary", {}), ) # --------------------------------------------------------------------------- # CLI entry point # --------------------------------------------------------------------------- if __name__ == "__main__": import argparse import sys logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s", ) parser = argparse.ArgumentParser( description="Pipeline 0: Confidence calibration benchmarks" ) parser.add_argument( "-j", "--parallel", type=int, default=1, help="Number of parallel jobs" ) parser.add_argument( "--quick", action="store_true", help="Quick mode: 5 cases only" ) parser.add_argument( "--max-sims", type=int, default=None, help="Limit number of simulations" ) parser.add_argument( "--data-dir", type=str, default="benchmarks/data/downstream/calibration", help="Data directory for simulations", ) parser.add_argument( "--results-dir", type=str, default="benchmarks/results", help="Results output directory", ) parser.add_argument( "--methods", nargs="+", default=None, help="Methods to run (default: all)", ) parser.add_argument( "--no-cache", action="store_true", help="Ignore cached results and recompute everything.", ) args = parser.parse_args() params = { "data_dir": args.data_dir, "results_dir": args.results_dir, "n_jobs": args.parallel, "quick": args.quick, "no_cache": args.no_cache, } if args.max_sims is not None: params["n_simulations"] = args.max_sims if args.methods is not None: params["methods"] = args.methods result = run_pipeline(params) # Print summary print("\n=== Calibration Summary ===\n") for method, stats in result.summary.items(): print(f" {method:25s} Brier={stats['brier_score']:.4f} " f"ECE={stats['ece']:.4f} " f"SP={stats.get('mean_sp', 'N/A')!s:>6s} " f"TC={stats.get('mean_tc', 'N/A')!s:>6s} " f"n={stats['n_cases']}") print() kalign-3.5.1/benchmarks/downstream/figures.py000066400000000000000000001242301515023132300213000ustar00rootroot00000000000000"""Publication-quality figure generation for kalign downstream benchmarks. Each public function produces a PDF figure suitable for inclusion in a journal manuscript. All figures read from pipeline result JSON files via ``_load_latest_json()``. All figures use: - matplotlib with a clean, Nature-style aesthetic - METHOD_COLORS from utils for consistent per-method colouring - PDF output for vector graphics - 10 pt base font, 1.5 pt minimum line width - Single-column width = 3.5 in, double-column = 7 in """ from __future__ import annotations import json import logging from collections import defaultdict from pathlib import Path from typing import Any from .utils import METHOD_COLORS logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- # Method ordering (consistent across all figures) # --------------------------------------------------------------------------- METHOD_ORDER = ["kalign", "kalign_cons", "kalign_ens3", "mafft", "muscle", "clustalo"] # --------------------------------------------------------------------------- # Style helpers # --------------------------------------------------------------------------- def _setup_figure_style() -> None: """Configure matplotlib rcParams for publication-quality output.""" import matplotlib as mpl mpl.use("Agg") import matplotlib.pyplot as plt plt.rcParams.update( { # Font "font.family": "sans-serif", "font.sans-serif": ["Arial", "Helvetica", "DejaVu Sans"], "font.size": 10, "axes.titlesize": 11, "axes.labelsize": 10, "xtick.labelsize": 9, "ytick.labelsize": 9, "legend.fontsize": 8, # Lines "lines.linewidth": 1.5, "lines.markersize": 5, # Axes "axes.linewidth": 1.0, "axes.spines.top": False, "axes.spines.right": False, "xtick.major.width": 0.8, "ytick.major.width": 0.8, "xtick.major.size": 4, "ytick.major.size": 4, # Grid "axes.grid": False, # Figure "figure.dpi": 150, "savefig.dpi": 300, "savefig.bbox": "tight", "savefig.pad_inches": 0.05, # Legend "legend.frameon": False, "legend.borderaxespad": 0.5, } ) def _add_panel_label(ax: Any, label: str) -> None: """Add a bold panel label (e.g. 'A', 'B') in the upper-left corner.""" ax.text( -0.12, 1.08, label, transform=ax.transAxes, fontsize=13, fontweight="bold", va="top", ha="left", ) def _method_color(method: str) -> str: """Return the colour for *method*, falling back to dark grey.""" return METHOD_COLORS.get(method, "#333333") def _method_label(method: str) -> str: """Return a human-friendly label for a method key.""" labels = { "kalign": "Kalign", "kalign_cons": "Kalign+cons", "kalign_ens3": "Kalign ens3", "mafft": "MAFFT", "muscle": "MUSCLE", "clustalo": "Clustal Omega", "true": "True alignment", } return labels.get(method, method) def _savefig(fig: Any, output_path: Path) -> None: """Save figure as PDF and close it.""" output_path = Path(output_path) output_path.parent.mkdir(parents=True, exist_ok=True) fig.savefig(str(output_path), format="pdf") import matplotlib.pyplot as plt plt.close(fig) logger.info("Saved figure: %s", output_path) def _bootstrap_ci_vec( values: list[float], n_bootstrap: int = 5000, alpha: float = 0.05 ) -> tuple[float, float, float]: """Return (mean, ci_lo, ci_hi) via bootstrap resampling.""" import numpy as np arr = np.array(values, dtype=float) n = len(arr) if n < 2: mu = float(arr.mean()) return mu, mu, mu rng = np.random.default_rng(42) boot_means = np.array( [float(rng.choice(arr, size=n, replace=True).mean()) for _ in range(n_bootstrap)] ) lo = float(np.percentile(boot_means, 100 * alpha / 2)) hi = float(np.percentile(boot_means, 100 * (1 - alpha / 2))) return float(arr.mean()), lo, hi def _shared_legend(fig: Any, methods: list[str], ncol: int = 6) -> None: """Add a shared legend below all panels.""" from matplotlib.patches import Patch handles = [ Patch(facecolor=_method_color(m), alpha=0.7, label=_method_label(m)) for m in methods ] fig.legend( handles=handles, loc="lower center", ncol=ncol, fontsize=8, frameon=False, bbox_to_anchor=(0.5, -0.02), ) def _ordered_methods(available: set[str]) -> list[str]: """Return methods in canonical order, filtered to those in *available*.""" return [m for m in METHOD_ORDER if m in available] def _grouped_boxplot( ax: Any, data: dict[str, dict[str, list[float]]], categories: list[str], methods: list[str], ylabel: str, cat_labels: dict[str, str] | None = None, ) -> None: """Draw grouped box plots on *ax*. Parameters ---------- data : dict[method -> dict[category -> list[float]]] categories : list of category keys methods : list of method keys (in order) """ n_methods = len(methods) n_cats = len(categories) if n_methods == 0 or n_cats == 0: return width = 0.8 / n_methods for j, method in enumerate(methods): positions = [] box_data = [] color = _method_color(method) for i, cat in enumerate(categories): vals = data.get(method, {}).get(cat, []) box_data.append(vals if vals else [0]) positions.append(i + j * width - (n_methods - 1) * width / 2) bp = ax.boxplot( box_data, positions=positions, widths=width * 0.85, patch_artist=True, medianprops={"color": "black", "linewidth": 1.2}, whiskerprops={"linewidth": 0.8}, capprops={"linewidth": 0.8}, flierprops={"marker": ".", "markersize": 3, "alpha": 0.5}, manage_ticks=False, ) for patch in bp["boxes"]: patch.set_facecolor(color) patch.set_alpha(0.7) tick_labels = [] for cat in categories: label = (cat_labels or {}).get(cat, cat) # Count cases from first method with data n = 0 for m in methods: n = len(data.get(m, {}).get(cat, [])) if n > 0: break tick_labels.append(f"{label}\n(n={n})" if n > 0 else label) ax.set_xticks(range(n_cats)) ax.set_xticklabels(tick_labels, fontsize=8) ax.set_ylabel(ylabel) ax.set_ylim(-0.02, 1.05) ax.set_xlim(-0.5, n_cats - 0.5) # --------------------------------------------------------------------------- # Result loading helpers # --------------------------------------------------------------------------- def _load_latest_json(results_dir: Path) -> Any: """Load the ``latest.json`` symlink (or most recent run file).""" results_dir = Path(results_dir) if not results_dir.is_dir(): return None latest = results_dir / "latest.json" if latest.exists(): with open(latest) as fh: return json.load(fh) json_files = sorted(results_dir.glob("run_*.json")) if not json_files: return None with open(json_files[-1]) as fh: return json.load(fh) def _extract_cases(data: Any) -> list[dict]: """Extract the cases list from a pipeline result dict or list.""" if isinstance(data, list): return data if isinstance(data, dict): return data.get("cases", []) return [] # --------------------------------------------------------------------------- # Figure 1: BAliBASE SP/TC by category # --------------------------------------------------------------------------- _BALIBASE_CATEGORIES = ["RV11", "RV12", "RV20", "RV30", "RV40", "RV50"] def figure_balibase(cases: list[dict], output_path: Path) -> None: """BAliBASE alignment accuracy: SP, Precision, F1, and TC box plots. Panel A: SP (recall) per BAliBASE category, grouped by method. Panel B: Precision per BAliBASE category, grouped by method. Panel C: F1 per BAliBASE category, grouped by method. Panel D: TC per BAliBASE category, grouped by method. """ import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt _setup_figure_style() fig, ((ax_sp, ax_prec), (ax_f1, ax_tc)) = plt.subplots(2, 2, figsize=(14, 10)) # Filter to balibase cases only bb_cases = [c for c in cases if c.get("benchmark") == "balibase" and "error" not in c and not c.get("skipped")] if not bb_cases: _savefig(fig, output_path) return available = {c["method"] for c in bb_cases} methods = _ordered_methods(available) # Build data[method][category] -> list of values def _build(metric: str) -> dict[str, dict[str, list[float]]]: out: dict[str, dict[str, list[float]]] = defaultdict(lambda: defaultdict(list)) for c in bb_cases: m = c["method"] ds = c.get("dataset", "") val = c.get(metric) if val is None or val < 0: continue for cat in _BALIBASE_CATEGORIES: if cat in ds: out[m][cat].append(val) break return out sp_data = _build("recall") prec_data = _build("precision") f1_data = _build("f1") tc_data = _build("tc") _grouped_boxplot(ax_sp, sp_data, _BALIBASE_CATEGORIES, methods, "SP (recall)") ax_sp.set_title("Sum-of-pairs score by category", fontsize=10) _add_panel_label(ax_sp, "A") _grouped_boxplot(ax_prec, prec_data, _BALIBASE_CATEGORIES, methods, "Precision") ax_prec.set_title("Precision by category", fontsize=10) _add_panel_label(ax_prec, "B") _grouped_boxplot(ax_f1, f1_data, _BALIBASE_CATEGORIES, methods, "F1") ax_f1.set_title("F1 score by category", fontsize=10) _add_panel_label(ax_f1, "C") _grouped_boxplot(ax_tc, tc_data, _BALIBASE_CATEGORIES, methods, "TC") ax_tc.set_title("Total column score by category", fontsize=10) _add_panel_label(ax_tc, "D") _shared_legend(fig, methods) fig.tight_layout(rect=[0, 0.04, 1, 1]) _savefig(fig, output_path) # --------------------------------------------------------------------------- # Figure 2: BRAliBASE SP by RNA family # --------------------------------------------------------------------------- _RNA_FAMILIES = ["SRP", "tRNA", "rRNA", "g2intron", "U5"] _RNA_LABELS = { "SRP": "SRP", "tRNA": "tRNA", "rRNA": "rRNA", "g2intron": "Group II\nintron", "U5": "U5", } def figure_bralibase(cases: list[dict], output_path: Path) -> None: """BRAliBASE RNA alignment accuracy. Panel A: SP (recall) per RNA family, grouped by method. Panel B: F1 per RNA family, grouped by method. Panel C: Wall time box plots per method (log scale). """ import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np _setup_figure_style() fig, (ax_sp, ax_f1, ax_time) = plt.subplots(1, 3, figsize=(18, 5)) br_cases = [c for c in cases if c.get("benchmark") == "bralibase" and "error" not in c and not c.get("skipped")] if not br_cases: _savefig(fig, output_path) return available = {c["method"] for c in br_cases} methods = _ordered_methods(available) # Build data per family def _build_family(metric: str) -> dict[str, dict[str, list[float]]]: out: dict[str, dict[str, list[float]]] = defaultdict(lambda: defaultdict(list)) for c in br_cases: m = c["method"] ds = c.get("dataset", "") val = c.get(metric) if val is None or val < 0: continue for fam in _RNA_FAMILIES: if fam.lower() in ds.lower() or fam in ds: out[m][fam].append(val) break return out sp_data = _build_family("recall") f1_data = _build_family("f1") _grouped_boxplot(ax_sp, sp_data, _RNA_FAMILIES, methods, "SP (recall)", _RNA_LABELS) ax_sp.set_title("Sum-of-pairs score by RNA family", fontsize=10) _add_panel_label(ax_sp, "A") _grouped_boxplot(ax_f1, f1_data, _RNA_FAMILIES, methods, "F1", _RNA_LABELS) ax_f1.set_title("F1 score by RNA family", fontsize=10) _add_panel_label(ax_f1, "B") # Panel C: Wall time time_data = [] time_colors = [] time_labels = [] for m in methods: times = [c["wall_time"] for c in br_cases if c.get("method") == m and c.get("wall_time", 0) > 0] if times: time_data.append(times) time_colors.append(_method_color(m)) time_labels.append(_method_label(m)) if time_data: bp = ax_time.boxplot( time_data, patch_artist=True, widths=0.6, medianprops={"color": "black", "linewidth": 1.2}, ) for patch, c in zip(bp["boxes"], time_colors): patch.set_facecolor(c) patch.set_alpha(0.7) ax_time.set_yscale("log") ax_time.set_xticks(range(1, len(time_labels) + 1)) ax_time.set_xticklabels(time_labels, fontsize=8, rotation=45, ha="right") ax_time.set_ylabel("Wall time (s)") ax_time.set_title("Alignment time", fontsize=10) else: ax_time.text(0.5, 0.5, "No timing data", ha="center", va="center", transform=ax_time.transAxes, fontsize=10, color="#999999") _add_panel_label(ax_time, "C") _shared_legend(fig, methods) fig.tight_layout(rect=[0, 0.05, 1, 1]) _savefig(fig, output_path) # --------------------------------------------------------------------------- # Figure 3: Phylogenetic tree accuracy # --------------------------------------------------------------------------- def figure_phylo_accuracy(cases: list[dict], output_path: Path) -> None: """Phylogenetic tree accuracy. Panel A: nRF box plots per method. Panel B: nRF vs tree depth with CI bands. Panel C: Branch score distance box plots. """ import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np _setup_figure_style() fig, (ax_nrf, ax_depth, ax_bsd) = plt.subplots(1, 3, figsize=(14, 5)) valid = [c for c in cases if "error" not in c] available = {c["method"] for c in valid} methods = _ordered_methods(available | ({"true"} & available)) # Panel A: nRF box plots if methods: box_data = [] colors = [] labels = [] for m in methods: vals = [c["nrf"] for c in valid if c.get("method") == m] box_data.append(vals if vals else [0]) colors.append(_method_color(m)) labels.append(_method_label(m)) bp = ax_nrf.boxplot( box_data, patch_artist=True, widths=0.6, medianprops={"color": "black", "linewidth": 1.5}, ) for patch, c in zip(bp["boxes"], colors): patch.set_facecolor(c) patch.set_alpha(0.7) ax_nrf.set_xticks(range(1, len(methods) + 1)) ax_nrf.set_xticklabels(labels, rotation=45, ha="right", fontsize=7) ax_nrf.set_ylabel("nRF distance") _add_panel_label(ax_nrf, "A") # Panel B: nRF vs tree depth import re as _re for m in methods: depth_nrf: dict[float, list[float]] = defaultdict(list) for c in valid: if c.get("method") != m: continue d = c.get("tree_depth") if d is None: dm = _re.search(r"_d([\d.]+)_", c.get("sim_id", "")) if dm: d = float(dm.group(1)) nrf = c.get("nrf") if d is not None and nrf is not None: depth_nrf[d].append(nrf) if depth_nrf: depths = sorted(depth_nrf.keys()) means = [float(np.mean(depth_nrf[d])) for d in depths] stds = [float(np.std(depth_nrf[d])) for d in depths] lo = [max(0, mu - s) for mu, s in zip(means, stds)] hi = [mu + s for mu, s in zip(means, stds)] color = _method_color(m) ax_depth.plot(depths, means, marker="o", color=color, label=_method_label(m), markersize=4) ax_depth.fill_between(depths, lo, hi, color=color, alpha=0.07) ax_depth.set_xlabel("Tree depth (subs/site)") ax_depth.set_ylabel("Mean nRF distance") handles, labels = ax_depth.get_legend_handles_labels() if handles: ax_depth.legend(fontsize=6, ncol=2, loc="upper left") _add_panel_label(ax_depth, "B") # Panel C: Branch score distance if methods: bsd_data = [] colors = [] labels = [] for m in methods: vals = [c["branch_score_dist"] for c in valid if c.get("method") == m and "branch_score_dist" in c] bsd_data.append(vals if vals else [0]) colors.append(_method_color(m)) labels.append(_method_label(m)) bp = ax_bsd.boxplot( bsd_data, patch_artist=True, widths=0.6, medianprops={"color": "black", "linewidth": 1.5}, ) for patch, c in zip(bp["boxes"], colors): patch.set_facecolor(c) patch.set_alpha(0.7) ax_bsd.set_xticks(range(1, len(methods) + 1)) ax_bsd.set_xticklabels(labels, rotation=45, ha="right", fontsize=7) ax_bsd.set_ylabel("Branch score distance") _add_panel_label(ax_bsd, "C") fig.tight_layout() _savefig(fig, output_path) # --------------------------------------------------------------------------- # Figure 4: Positive selection detection # --------------------------------------------------------------------------- def figure_positive_selection(cases: list[dict], output_path: Path) -> None: """Positive selection detection. Panel A: Precision/Recall/F1 bars per method. Panel B: F1 vs tree depth. Panel C: F1 vs indel rate. """ import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np import re as _re _setup_figure_style() fig, (ax_bar, ax_depth, ax_indel) = plt.subplots(1, 3, figsize=(14, 5)) valid = [c for c in cases if "error" not in c] by_method: dict[str, list[dict]] = defaultdict(list) for c in valid: by_method[c.get("method", "")].append(c) available = set(by_method.keys()) methods = _ordered_methods(available | ({"true"} & available)) # Panel A: bar chart if methods: n_methods = len(methods) x_pos = np.arange(n_methods) width = 0.25 prec_means = [np.mean([c.get("precision", 0) for c in by_method[m]]) for m in methods] rec_means = [np.mean([c.get("recall", c.get("tpr", 0)) for c in by_method[m]]) for m in methods] f1_means = [np.mean([c.get("f1", 0) for c in by_method[m]]) for m in methods] colors_prec = [_method_color(m) for m in methods] ax_bar.bar(x_pos - width, prec_means, width, label="Precision", color=colors_prec, alpha=0.8) ax_bar.bar(x_pos, rec_means, width, label="Recall", color=colors_prec, alpha=0.55) ax_bar.bar(x_pos + width, f1_means, width, label="F1", color=colors_prec, alpha=0.3) ax_bar.set_xticks(x_pos) ax_bar.set_xticklabels( [_method_label(m) for m in methods], rotation=45, ha="right", fontsize=7 ) ax_bar.set_ylabel("Score") all_vals = list(prec_means) + list(rec_means) + list(f1_means) if all_vals: ax_bar.set_ylim(0, max(all_vals) * 1.15) ax_bar.legend(fontsize=7) _add_panel_label(ax_bar, "A") # Panel B: F1 vs tree depth for m in methods: depth_f1: dict[float, list[float]] = defaultdict(list) for c in by_method[m]: d = c.get("tree_depth") if d is None: dm = _re.search(r"_d([\d.]+)_", c.get("sim_id", "")) if dm: d = float(dm.group(1)) f1 = c.get("f1") if d is not None and f1 is not None: depth_f1[d].append(f1) if depth_f1: depths_sorted = sorted(depth_f1.keys()) means = [np.mean(depth_f1[d]) for d in depths_sorted] ax_depth.plot(depths_sorted, means, marker="o", color=_method_color(m), label=_method_label(m)) ax_depth.set_xlabel("Tree depth (subs/site)") ax_depth.set_ylabel("F1 score") handles, _ = ax_depth.get_legend_handles_labels() if handles: ax_depth.legend(fontsize=6, ncol=2, loc="best") _add_panel_label(ax_depth, "B") # Panel C: F1 vs indel rate for m in methods: indel_f1: dict[float, list[float]] = defaultdict(list) for c in by_method[m]: ir = c.get("indel_rate") if ir is None: irm = _re.search(r"_ir([\d.]+)_", c.get("sim_id", "")) if irm: ir = float(irm.group(1)) f1 = c.get("f1") if ir is not None and f1 is not None: indel_f1[ir].append(f1) if indel_f1: rates_sorted = sorted(indel_f1.keys()) means = [np.mean(indel_f1[r]) for r in rates_sorted] ax_indel.plot(rates_sorted, means, marker="o", color=_method_color(m), label=_method_label(m)) ax_indel.set_xlabel("Indel rate") ax_indel.set_ylabel("F1 score") handles, _ = ax_indel.get_legend_handles_labels() if handles: ax_indel.legend(fontsize=6, ncol=2, loc="best") _add_panel_label(ax_indel, "C") fig.tight_layout() _savefig(fig, output_path) # --------------------------------------------------------------------------- # Figure 5: HMMER homology detection # --------------------------------------------------------------------------- def figure_hmmer_detection(cases: list[dict], output_path: Path) -> None: """HMMER homology detection — single bar chart with bootstrap CIs.""" import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np _setup_figure_style() fig, ax = plt.subplots(1, 1, figsize=(5, 4)) valid = [c for c in cases if "error" not in c] by_method: dict[str, list[dict]] = defaultdict(list) for c in valid: by_method[c.get("method", "")].append(c) available = set(by_method.keys()) methods = _ordered_methods(available) def _sens(case: dict) -> float: if "sensitivity" in case: return case["sensitivity"] h = case.get("hits_at_1e3", {}) return h.get("sens", 0.0) if isinstance(h, dict) else 0.0 if methods: means = [] ci_lo = [] ci_hi = [] colors = [] for m in methods: sens_vals = [_sens(c) for c in by_method[m]] mu = float(np.mean(sens_vals)) if sens_vals else 0.0 means.append(mu) if len(sens_vals) >= 2: _, lo, hi = _bootstrap_ci_vec(sens_vals, n_bootstrap=2000) ci_lo.append(mu - lo) ci_hi.append(hi - mu) else: ci_lo.append(0) ci_hi.append(0) colors.append(_method_color(m)) x = np.arange(len(methods)) ax.bar( x, means, color=colors, alpha=0.8, yerr=[ci_lo, ci_hi], capsize=3, ecolor="#333333", ) ax.set_xticks(x) ax.set_xticklabels( [_method_label(m) for m in methods], rotation=45, ha="right", fontsize=8 ) ax.set_ylabel("Mean sensitivity (E < 1e-5)") if means and max(means) > 0: ymin_bar = max(0, min(means) - 0.05) ymax = min(1.0, max(mu + h for mu, h in zip(means, ci_hi)) * 1.02) ax.set_ylim(ymin_bar, ymax) ax.set_title("HMMER homology detection (50 Pfam families)", fontsize=10) fig.tight_layout() _savefig(fig, output_path) # --------------------------------------------------------------------------- # Figure 6: Speed comparison (aggregated across all pipelines) # --------------------------------------------------------------------------- def figure_speed_comparison(all_timed: list[dict], output_path: Path) -> None: """Speed and memory comparison aggregated across all pipelines. Panel A: Wall time box plots (log scale) per method. Panel B: Peak memory box plots per method. """ import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np _setup_figure_style() fig, (ax_time, ax_mem) = plt.subplots(1, 2, figsize=(10, 5)) by_method: dict[str, list[dict]] = defaultdict(list) for r in all_timed: m = r.get("method") if m: by_method[m].append(r) available = set(by_method.keys()) methods = _ordered_methods(available) # Panel A: Wall time if methods: time_data = [] colors = [] labels = [] for m in methods: # Try multiple time field names times = [] for c in by_method[m]: t = c.get("wall_time_align") or c.get("wall_time") if t and t > 0: times.append(t) time_data.append(times if times else [0.001]) colors.append(_method_color(m)) labels.append(_method_label(m)) bp = ax_time.boxplot( time_data, patch_artist=True, widths=0.6, medianprops={"color": "black", "linewidth": 1.5}, ) for patch, c in zip(bp["boxes"], colors): patch.set_facecolor(c) patch.set_alpha(0.7) ax_time.set_yscale("log") ax_time.set_xticks(range(1, len(methods) + 1)) ax_time.set_xticklabels(labels, rotation=45, ha="right", fontsize=7) ax_time.set_ylabel("Wall time (s)") _add_panel_label(ax_time, "A") # Panel B: Peak memory if methods: mem_data = [] colors = [] labels = [] for m in methods: mems = [c.get("peak_memory_mb", 0) for c in by_method[m] if c.get("peak_memory_mb", 0) > 0] mem_data.append(mems if mems else [0]) colors.append(_method_color(m)) labels.append(_method_label(m)) bp = ax_mem.boxplot( mem_data, patch_artist=True, widths=0.6, medianprops={"color": "black", "linewidth": 1.5}, ) for patch, c in zip(bp["boxes"], colors): patch.set_facecolor(c) patch.set_alpha(0.7) ax_mem.set_xticks(range(1, len(methods) + 1)) ax_mem.set_xticklabels(labels, rotation=45, ha="right", fontsize=7) ax_mem.set_ylabel("Peak memory (MB)") _add_panel_label(ax_mem, "B") fig.tight_layout() _savefig(fig, output_path) # --------------------------------------------------------------------------- # Figure 7: Summary heatmap # --------------------------------------------------------------------------- def figure_summary_heatmap(all_results: dict, output_path: Path) -> None: """Summary heatmap across all pipelines. Rows = methods, columns = key metrics per pipeline. Colour-coded: green=best, red=worst. Annotated with raw values. Parameters ---------- all_results : dict Mapping with optional keys for each pipeline. Each value is a dict mapping method names to metric values (float). """ import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np _setup_figure_style() # Columns: (label, data_dict, higher_is_better) columns_spec: list[tuple[str, dict[str, float], bool]] = [] # Alignment accuracy F1 aln = all_results.get("alignment_accuracy") if aln: columns_spec.append(("Aln F1", aln, True)) # Calibration ECE cal = all_results.get("calibration") if cal: columns_spec.append(("ECE", cal, False)) # Positive selection F1 psel = all_results.get("positive_selection") if psel: columns_spec.append(("Sel. F1", psel, True)) # Phylo nRF phylo = all_results.get("phylo_accuracy") if phylo: columns_spec.append(("nRF", phylo, False)) # HMMER sensitivity hmmer = all_results.get("hmmer_detection") if hmmer: columns_spec.append(("HMMER sens.", hmmer, True)) # Speed speed = all_results.get("speed") if speed: columns_spec.append(("Speed (s)", speed, False)) if not columns_spec: logger.warning("figure_summary_heatmap: no data, skipping.") return # Collect union of methods all_methods: set[str] = set() for _, mdict, _ in columns_spec: all_methods.update(mdict.keys()) methods = _ordered_methods(all_methods) if not methods: methods = sorted(all_methods) n_methods = len(methods) n_cols = len(columns_spec) raw = np.full((n_methods, n_cols), np.nan) for j, (_, mdict, _) in enumerate(columns_spec): for i, m in enumerate(methods): if m in mdict: raw[i, j] = mdict[m] # Normalise each column to [0, 1] (1 = best) normed = np.full_like(raw, np.nan) for j, (_, _, higher_better) in enumerate(columns_spec): col = raw[:, j] valid_mask = ~np.isnan(col) if valid_mask.sum() < 2: normed[valid_mask, j] = 0.5 continue vmin = np.nanmin(col) vmax = np.nanmax(col) if vmax - vmin < 1e-12: normed[valid_mask, j] = 0.5 else: scaled = (col[valid_mask] - vmin) / (vmax - vmin) if not higher_better: scaled = 1.0 - scaled normed[valid_mask, j] = scaled fig, ax = plt.subplots(figsize=(max(5, 1.7 * n_cols + 2), 0.65 * n_methods + 1.5)) cmap = plt.get_cmap("RdYlGn") display = np.where(np.isnan(normed), 0.5, normed) im = ax.imshow(display, cmap=cmap, aspect="auto", vmin=0, vmax=1) for i in range(n_methods): for j in range(n_cols): val = raw[i, j] if np.isnan(val): text = "-" elif abs(val) < 0.01 or abs(val) >= 1000: text = f"{val:.2e}" else: text = f"{val:.3f}" ax.text( j, i, text, ha="center", va="center", fontsize=7, color="black" if 0.3 < display[i, j] < 0.7 else "white", ) ax.set_xticks(range(n_cols)) ax.set_xticklabels([name for name, _, _ in columns_spec], fontsize=9) ax.set_yticks(range(n_methods)) ax.set_yticklabels([_method_label(m) for m in methods], fontsize=8) cbar = fig.colorbar(im, ax=ax, fraction=0.03, pad=0.04) cbar.set_label("Normalised score (1 = best)", fontsize=8) cbar.ax.tick_params(labelsize=7) fig.tight_layout() _savefig(fig, output_path) # --------------------------------------------------------------------------- # Calibration figure (for calibration pipeline) # --------------------------------------------------------------------------- def figure_calibration(results: dict, output_path: Path) -> None: """Confidence calibration reliability diagram. Panel A: Calibration curve (predicted confidence vs fraction correct). Panel B: Histogram of confidence values. """ import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np _setup_figure_style() fig, (ax_cal, ax_hist) = plt.subplots(1, 2, figsize=(10, 5)) ax_cal.plot([0, 1], [0, 1], ls="--", color="#aaaaaa", lw=1.0, label="Perfect") for method, data in results.items(): bins = data.get("bins") if not bins: continue midpoints = np.array([(b["bin_low"] + b["bin_high"]) / 2 for b in bins]) accuracies = np.array([b.get("accuracy", 0.0) for b in bins]) ece = data.get("ece") brier = data.get("brier_score") label_parts = [_method_label(method)] if ece is not None: label_parts.append(f"ECE={ece:.3f}") if brier is not None: label_parts.append(f"Brier={brier:.3f}") ax_cal.plot( midpoints, accuracies, marker="o", color=_method_color(method), label=" ".join(label_parts), ) ax_cal.set_xlabel("Predicted confidence") ax_cal.set_ylabel("Observed accuracy") ax_cal.set_xlim(0, 1) ax_cal.set_ylim(0, 1) ax_cal.set_aspect("equal") ax_cal.legend(loc="lower right", fontsize=7) _add_panel_label(ax_cal, "A") for method, data in results.items(): bins = data.get("bins") if not bins: continue midpoints = np.array([(b["bin_low"] + b["bin_high"]) / 2 for b in bins]) counts = np.array([b.get("n_pairs", 0) for b in bins], dtype=float) total = counts.sum() if total > 0: counts = counts / total widths = np.array([b["bin_high"] - b["bin_low"] for b in bins]) ax_hist.bar( midpoints, counts, width=widths * 0.85, alpha=0.5, color=_method_color(method), label=_method_label(method), ) ax_hist.set_xlabel("Confidence score") ax_hist.set_ylabel("Fraction of residue pairs") ax_hist.set_xlim(0, 1) ax_hist.legend(loc="upper left", fontsize=7) _add_panel_label(ax_hist, "B") fig.tight_layout() _savefig(fig, output_path) # --------------------------------------------------------------------------- # Aggregation helpers for heatmap # --------------------------------------------------------------------------- def _aggregate_for_heatmap( pipeline_results: list[dict], method_key: str, metric_key: str, ) -> dict[str, float]: """Compute mean of *metric_key* per method from a list of per-case dicts.""" import numpy as np by_method: dict[str, list[float]] = defaultdict(list) parts = metric_key.split(".") for case in pipeline_results: m = case.get(method_key) if m is None: continue val = case for p in parts: if isinstance(val, dict): val = val.get(p) else: val = None break if val is not None: try: by_method[m].append(float(val)) except (TypeError, ValueError): pass return {m: float(np.mean(vs)) for m, vs in by_method.items() if vs} def _adapt_calibration_summary(cal_methods: dict) -> dict: """Convert calibration summary format to the bins format expected by figure_calibration.""" import math adapted: dict = {} for method, data in cal_methods.items(): if not isinstance(data, dict): continue cc = data.get("calibration_curve") if not isinstance(cc, dict): adapted[method] = data continue centers = cc.get("bin_centers", []) counts = cc.get("bin_counts", []) fracs = cc.get("fraction_correct", []) if not centers: adapted[method] = data continue bins = [] for i, center in enumerate(centers): if len(centers) > 1: width = centers[1] - centers[0] if i == 0 else centers[i] - centers[i - 1] else: width = 0.1 acc = fracs[i] if i < len(fracs) else 0.0 if isinstance(acc, float) and math.isnan(acc): acc = 0.0 bins.append({ "bin_low": center - width / 2, "bin_high": center + width / 2, "n_pairs": counts[i] if i < len(counts) else 0, "accuracy": acc, }) adapted[method] = { "ece": data.get("ece"), "brier_score": data.get("brier_score"), "bins": bins, } return adapted # --------------------------------------------------------------------------- # Top-level entry point # --------------------------------------------------------------------------- def generate_all_figures( results_dir: str | Path, output_dir: str | Path, ) -> None: """Generate all publication figures from saved results. Reads ``latest.json`` from each pipeline's results sub-directory and calls the corresponding figure function. Skips pipelines whose results are not available. """ results_dir = Path(results_dir) output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) generated: list[str] = [] # --- Fig 1 & 2: Alignment accuracy (BAliBASE + BRAliBASE) ---------------- aln_data = _load_latest_json(results_dir / "alignment_accuracy") aln_cases = _extract_cases(aln_data) if aln_data else [] aln_valid = [c for c in aln_cases if "error" not in c and not c.get("skipped")] if aln_valid: path = output_dir / "fig1_balibase_accuracy.pdf" try: figure_balibase(aln_valid, path) generated.append(str(path)) except Exception as exc: logger.error("Failed to generate BAliBASE figure: %s", exc) path = output_dir / "fig2_bralibase_rna.pdf" try: figure_bralibase(aln_valid, path) generated.append(str(path)) except Exception as exc: logger.error("Failed to generate BRAliBASE figure: %s", exc) # --- Fig 3: Phylo accuracy ----------------------------------------------- phylo_data = _load_latest_json(results_dir / "phylo_accuracy") phylo_cases = _extract_cases(phylo_data) if phylo_cases: path = output_dir / "fig3_phylo_accuracy.pdf" try: figure_phylo_accuracy(phylo_cases, path) generated.append(str(path)) except Exception as exc: logger.error("Failed to generate phylo accuracy figure: %s", exc) # --- Fig 4: Positive selection ------------------------------------------- psel_data = _load_latest_json(results_dir / "positive_selection") psel_cases = _extract_cases(psel_data) if psel_cases: path = output_dir / "fig4_positive_selection.pdf" try: figure_positive_selection(psel_cases, path) generated.append(str(path)) except Exception as exc: logger.error("Failed to generate positive selection figure: %s", exc) # --- Fig 5: HMMER detection ---------------------------------------------- hmmer_data = _load_latest_json(results_dir / "hmmer_detection") hmmer_cases = _extract_cases(hmmer_data) if hmmer_cases: path = output_dir / "fig5_hmmer_detection.pdf" try: figure_hmmer_detection(hmmer_cases, path) generated.append(str(path)) except Exception as exc: logger.error("Failed to generate HMMER detection figure: %s", exc) # --- Fig 6: Speed comparison (aggregated) -------------------------------- all_timed: list[dict] = [] # Collect timing data from alignment_accuracy + downstream pipelines for c in aln_valid: if "wall_time" in c: all_timed.append(c) for subdir in ("positive_selection", "phylo_accuracy"): sub_data = _load_latest_json(results_dir / subdir) sub_cases = _extract_cases(sub_data) all_timed.extend(c for c in sub_cases if "wall_time_align" in c or "wall_time" in c) if all_timed: path = output_dir / "fig6_speed_comparison.pdf" try: figure_speed_comparison(all_timed, path) generated.append(str(path)) except Exception as exc: logger.error("Failed to generate speed comparison figure: %s", exc) # --- Fig 7: Summary heatmap ---------------------------------------------- heatmap_data: dict[str, dict[str, float]] = {} # Alignment accuracy F1 if aln_valid: agg = _aggregate_for_heatmap(aln_valid, "method", "f1") if agg: heatmap_data["alignment_accuracy"] = agg # Calibration ECE cal_data = _load_latest_json(results_dir / "calibration") if cal_data is not None: cal_src = None if isinstance(cal_data, dict): cal_src = cal_data.get("methods") or cal_data.get("summary") or cal_data if isinstance(cal_src, dict): ece_map = {} for m, v in cal_src.items(): if isinstance(v, dict) and "ece" in v: ece_map[m] = v["ece"] if ece_map: heatmap_data["calibration"] = ece_map # Calibration figure (standalone) if cal_data is not None: cal_methods = None if isinstance(cal_data, dict): cal_methods = cal_data.get("methods") or cal_data.get("summary") if cal_methods is None: cal_methods = cal_data if isinstance(cal_methods, dict): cal_methods = _adapt_calibration_summary(cal_methods) if cal_methods: path = output_dir / "fig_calibration.pdf" try: figure_calibration(cal_methods, path) generated.append(str(path)) except Exception as exc: logger.error("Failed to generate calibration figure: %s", exc) # Positive selection F1 if psel_cases: agg = _aggregate_for_heatmap(psel_cases, "method", "f1") if agg: heatmap_data["positive_selection"] = agg # Phylo nRF if phylo_cases: agg = _aggregate_for_heatmap(phylo_cases, "method", "nrf") if agg: heatmap_data["phylo_accuracy"] = agg # HMMER sensitivity if hmmer_cases: agg = _aggregate_for_heatmap(hmmer_cases, "method", "sensitivity") if agg: heatmap_data["hmmer_detection"] = agg # Speed (mean wall time) if all_timed: # Normalise field name for c in all_timed: if "wall_time_align" in c and "wall_time" not in c: c["wall_time"] = c["wall_time_align"] agg = _aggregate_for_heatmap(all_timed, "method", "wall_time") if agg: heatmap_data["speed"] = agg if heatmap_data: path = output_dir / "fig7_summary_heatmap.pdf" try: figure_summary_heatmap(heatmap_data, path) generated.append(str(path)) except Exception as exc: logger.error("Failed to generate summary heatmap: %s", exc) # --- Summary -------------------------------------------------------------- if generated: print(f"Generated {len(generated)} figures:") for p in generated: print(f" {p}") else: print("No figures generated (no result data found).") kalign-3.5.1/benchmarks/downstream/hmmer_detection.py000066400000000000000000001143531515023132300230070ustar00rootroot00000000000000"""Pipeline 3: HMMER Homology Detection benchmark. Measures how alignment quality affects profile HMM sensitivity. For each Pfam seed family the pipeline strips gaps from the curated seed alignment, re-aligns using each method, builds a profile HMM with ``hmmbuild``, and searches a combined database with ``hmmsearch``. True/false positive rates are computed against known family memberships. """ from __future__ import annotations import json import logging import os import random import shutil import subprocess import tempfile import time from concurrent.futures import ProcessPoolExecutor, as_completed from dataclasses import asdict, dataclass, field from pathlib import Path from typing import Dict, List, Optional logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- # Pfam family list (hardcoded, well-known families) # --------------------------------------------------------------------------- PFAM_FAMILIES = [ "PF00001", # 7tm_1 (GPCR) "PF00002", # 7tm_2 "PF00003", # 7tm_3 "PF00004", # AAA (ATPase) "PF00005", # ABC_tran "PF00009", # GTP_EFTU "PF00010", # HLH "PF00012", # HSP70 "PF00013", # KH domain "PF00014", # Kunitz_BPTI "PF00018", # SH3 "PF00022", # Actin "PF00023", # Ank "PF00027", # cNMP_binding "PF00028", # Cadherin "PF00036", # EF-hand "PF00041", # Fibronectin_3 "PF00042", # Globin "PF00043", # GST_C "PF00046", # Homeodomain "PF00047", # Ig "PF00048", # IL8 "PF00050", # Kazal "PF00056", # LDLA "PF00069", # Pkinase "PF00071", # Ras "PF00072", # Response_reg "PF00076", # RRM "PF00078", # RVT "PF00079", # Serpin "PF00081", # Sod_Fe_N "PF00082", # Subtilisin "PF00083", # Sugar_tr "PF00084", # Sushi "PF00085", # Thioredoxin "PF00089", # Trypsin "PF00096", # Zinc_finger_C2H2 "PF00100", # Zona_pellucida "PF00102", # Y_phosphatase "PF00104", # Hormone_recep "PF00106", # adh_short "PF00107", # ADH_zinc_N "PF00109", # ketoacyl-synt "PF00111", # Fer2 "PF00112", # Pepsin "PF00115", # COX1 "PF00118", # Cpn60_TCP1 "PF00119", # ATP-synt_A "PF00120", # Glu_synthase "PF00121", # TIM ] # --------------------------------------------------------------------------- # Result dataclasses # --------------------------------------------------------------------------- @dataclass class HmmerCaseResult: """Result for a single family x method evaluation.""" family_id: str method: str true_positives: int false_positives: int false_negatives: int sensitivity: float # TP / (TP + FN) specificity: float # precision = TP / (TP + FP) e_value_threshold: float hmm_length: int # number of match states in the profile wall_time_align: float wall_time_hmmbuild: float wall_time_hmmsearch: float peak_memory_mb: float @dataclass class HmmerResult: """Aggregated result for the full HMMER detection pipeline.""" provenance: dict cases: List[dict] summary: dict # per-method aggregated metrics # --------------------------------------------------------------------------- # Pfam seed download / cache # --------------------------------------------------------------------------- _PFAM_SEED_URL_TEMPLATE = ( "https://www.ebi.ac.uk/interpro/api/entry/pfam/{accession}" "?annotation=alignment:seed" ) def _download_pfam_seeds( data_dir: Path, n_families: int = 50, ) -> List[dict]: """Download (or load from cache) Pfam seed alignments for benchmarking. Attempts to download seed alignments from the InterPro API for each family in :data:`PFAM_FAMILIES`. Successfully downloaded alignments are cached as FASTA files under ``data_dir/pfam_seed/``. If a download fails the cached version is used if available. Parameters ---------- data_dir : Path Base data directory. Seed files are stored in ``data_dir/pfam_seed/.fasta``. n_families : int Maximum number of families to return. Returns ------- list[dict] Each dict has keys ``family_id``, ``seed_fasta_path``, ``n_members``. """ import urllib.request import urllib.error seed_dir = Path(data_dir) / "pfam_seed" seed_dir.mkdir(parents=True, exist_ok=True) families_to_fetch = PFAM_FAMILIES[:n_families] results: List[dict] = [] for accession in families_to_fetch: fasta_path = seed_dir / f"{accession}.fasta" # Try to use cache first if fasta_path.exists() and fasta_path.stat().st_size > 0: names, _seqs = _parse_fasta_simple(fasta_path) if names: results.append( { "family_id": accession, "seed_fasta_path": str(fasta_path), "n_members": len(names), } ) logger.debug("Using cached seed for %s (%d seqs)", accession, len(names)) continue # Download from InterPro url = _PFAM_SEED_URL_TEMPLATE.format(accession=accession) logger.info("Downloading seed alignment for %s", accession) try: req = urllib.request.Request(url) with urllib.request.urlopen(req, timeout=30) as resp: raw = resp.read() # The InterPro API returns gzip-compressed Stockholm; # decompress if needed. import gzip as _gzip try: content = _gzip.decompress(raw) except (OSError, _gzip.BadGzipFile): content = raw # The API may return Stockholm or raw alignment text. # Convert to FASTA for uniform handling. text = content.decode("utf-8", errors="replace") names, seqs = _stockholm_or_text_to_fasta(text) if not names: logger.warning("No sequences parsed for %s", accession) continue # Strip gaps to get raw sequences, then write aligned FASTA # (we keep the aligned version since hmmbuild can use it) _write_fasta_simple(fasta_path, names, seqs) results.append( { "family_id": accession, "seed_fasta_path": str(fasta_path), "n_members": len(names), } ) logger.info("Downloaded seed for %s (%d seqs)", accession, len(names)) except (urllib.error.URLError, OSError, ValueError) as exc: logger.warning("Failed to download %s: %s", accession, exc) # If there is no cache either, skip this family continue logger.info( "Loaded %d / %d Pfam seed families", len(results), len(families_to_fetch), ) return results # --------------------------------------------------------------------------- # Stockholm / text parsing helpers # --------------------------------------------------------------------------- def _stockholm_or_text_to_fasta(text: str) -> tuple[list[str], list[str]]: """Parse Stockholm or aligned-text format into (names, sequences). Handles: - Stockholm format (lines with ``#=...`` annotations, ``//`` terminator) - Plain aligned FASTA - Clustal-like blocks """ lines = text.splitlines() # Detect Stockholm if any(line.strip().startswith("# STOCKHOLM") for line in lines[:5]): return _parse_stockholm_text(lines) # Detect FASTA if any(line.strip().startswith(">") for line in lines[:10]): return _parse_fasta_lines(lines) # Fallback: treat as space-separated name+sequence blocks names: list[str] = [] seqs: list[str] = [] seq_dict: dict[str, list[str]] = {} name_order: list[str] = [] for line in lines: line = line.strip() if not line or line.startswith("#") or line.startswith("//"): continue parts = line.split(None, 1) if len(parts) == 2: name, seq_part = parts if name not in seq_dict: seq_dict[name] = [] name_order.append(name) seq_dict[name].append(seq_part.replace(" ", "")) for name in name_order: names.append(name) seqs.append("".join(seq_dict[name])) return names, seqs def _parse_stockholm_text(lines: list[str]) -> tuple[list[str], list[str]]: """Parse Stockholm format lines into (names, sequences).""" seq_dict: dict[str, list[str]] = {} name_order: list[str] = [] for line in lines: line = line.rstrip() if not line or line.startswith("#") or line.startswith("//"): continue parts = line.split(None, 1) if len(parts) == 2: name, seq_part = parts if name not in seq_dict: seq_dict[name] = [] name_order.append(name) seq_dict[name].append(seq_part.replace(" ", "")) names = [] seqs = [] for name in name_order: names.append(name) seqs.append("".join(seq_dict[name])) return names, seqs def _parse_fasta_lines(lines: list[str]) -> tuple[list[str], list[str]]: """Parse FASTA from a list of lines.""" names: list[str] = [] seqs: list[str] = [] current: list[str] = [] for line in lines: line = line.rstrip() if line.startswith(">"): if current: seqs.append("".join(current)) current = [] name = line[1:].split()[0] if line[1:].strip() else "" names.append(name) else: current.append(line.strip()) if current: seqs.append("".join(current)) return names, seqs def _parse_fasta_simple(path: Path) -> tuple[list[str], list[str]]: """Parse a FASTA file from disk. Returns (names, sequences).""" names: list[str] = [] seqs: list[str] = [] current: list[str] = [] with open(path) as fh: for line in fh: line = line.rstrip("\n\r") if line.startswith(">"): if current: seqs.append("".join(current)) current = [] names.append(line[1:].split()[0] if line[1:].strip() else "") else: current.append(line.strip()) if current: seqs.append("".join(current)) return names, seqs def _write_fasta_simple( path: Path, names: list[str], sequences: list[str] ) -> None: """Write sequences in FASTA format.""" with open(path, "w") as fh: for name, seq in zip(names, sequences): fh.write(f">{name}\n") for i in range(0, len(seq), 80): fh.write(seq[i : i + 80] + "\n") def _strip_gaps(sequences: list[str]) -> list[str]: """Remove gap characters from sequences.""" return [s.replace("-", "").replace(".", "") for s in sequences] # --------------------------------------------------------------------------- # hmmbuild wrapper # --------------------------------------------------------------------------- def _run_hmmbuild(alignment_path: Path, hmm_path: Path) -> dict: """Run ``hmmbuild`` to construct a profile HMM from an alignment. Parameters ---------- alignment_path : Path Input alignment (FASTA or Stockholm). hmm_path : Path Output HMM file path. Returns ------- dict ``hmm_path``, ``hmm_length``, ``nseq``, ``wall_time``. Raises ------ RuntimeError If ``hmmbuild`` is not found or exits with an error. """ hmmbuild_bin = shutil.which("hmmbuild") if hmmbuild_bin is None: raise RuntimeError( "hmmbuild is not installed or not on PATH. " "Install HMMER3 (http://hmmer.org/)." ) start = time.perf_counter() proc = subprocess.run( [hmmbuild_bin, "--amino", str(hmm_path), str(alignment_path)], capture_output=True, text=True, ) wall = time.perf_counter() - start if proc.returncode != 0: raise RuntimeError( f"hmmbuild failed (exit {proc.returncode}): {proc.stderr}" ) # Parse hmmbuild output for HMM length and nseq hmm_length = 0 nseq = 0 for line in proc.stdout.splitlines(): # Example: "Number of sequences: 42" if "umber of sequences" in line: parts = line.split() for part in reversed(parts): try: nseq = int(part) break except ValueError: continue # Example: "Model length: 285" # Also appears in HMM header: "LENG 285" if "odel length" in line or line.strip().startswith("LENG"): parts = line.split() for part in reversed(parts): try: hmm_length = int(part) break except ValueError: continue # Fallback: parse the HMM file header for LENG if hmm_length == 0 and Path(hmm_path).exists(): with open(hmm_path) as fh: for hline in fh: if hline.startswith("LENG"): parts = hline.split() if len(parts) >= 2: try: hmm_length = int(parts[1]) except ValueError: pass break return { "hmm_path": str(hmm_path), "hmm_length": hmm_length, "nseq": nseq, "wall_time": wall, } # --------------------------------------------------------------------------- # hmmsearch wrapper # --------------------------------------------------------------------------- def _run_hmmsearch( hmm_path: Path, target_db: Path, output_path: Path, e_value: float = 1e-5, ) -> dict: """Run ``hmmsearch`` to search a profile HMM against a sequence database. Parameters ---------- hmm_path : Path Profile HMM file. target_db : Path FASTA database to search. output_path : Path Path for the ``--tblout`` tabular output. e_value : float E-value threshold for reporting hits. Returns ------- dict ``hits`` (list of dicts with name, e_value, score), ``n_hits``, ``wall_time``. """ hmmsearch_bin = shutil.which("hmmsearch") if hmmsearch_bin is None: raise RuntimeError( "hmmsearch is not installed or not on PATH. " "Install HMMER3 (http://hmmer.org/)." ) start = time.perf_counter() proc = subprocess.run( [ hmmsearch_bin, "--tblout", str(output_path), "--noali", "-E", str(e_value), str(hmm_path), str(target_db), ], capture_output=True, text=True, ) wall = time.perf_counter() - start if proc.returncode != 0: raise RuntimeError( f"hmmsearch failed (exit {proc.returncode}): {proc.stderr}" ) # Parse tblout hits = _parse_tblout(output_path) return { "hits": hits, "n_hits": len(hits), "wall_time": wall, } def _parse_tblout(path: Path) -> List[dict]: """Parse HMMER3 ``--tblout`` tabular output. Columns (space-separated, first 6): target_name accession query_name accession E-value score bias ... Comment lines start with ``#``. Returns a list of dicts, each with ``name``, ``e_value``, ``score``. """ hits: list[dict] = [] if not Path(path).exists(): return hits with open(path) as fh: for line in fh: if line.startswith("#"): continue parts = line.split() if len(parts) < 6: continue try: hit = { "name": parts[0], "e_value": float(parts[4]), "score": float(parts[5]), } hits.append(hit) except (ValueError, IndexError): continue return hits # --------------------------------------------------------------------------- # Search database preparation # --------------------------------------------------------------------------- def _prepare_search_db( families: List[dict], data_dir: Path, ) -> Path: """Create a combined FASTA search database from family seed sequences. Pools seed sequences from all loaded families. Each sequence is labelled ``__`` so that true positives can be identified by family membership. Negative sequences are drawn from other families -- i.e. for any given query family, members of the remaining families act as negatives. Parameters ---------- families : list[dict] Output of :func:`_download_pfam_seeds`. data_dir : Path Directory for writing the search DB. Returns ------- Path Path to the combined FASTA database. """ db_path = Path(data_dir) / "search_db.fasta" # If already exists and non-empty, check it covers all current families if db_path.exists() and db_path.stat().st_size > 0: needed = {f["family_id"] for f in families} present: set[str] = set() with open(db_path) as fh: for line in fh: if line.startswith(">"): fam_id = line[1:].split("__")[0] present.add(fam_id) if needed <= present: logger.info("Reusing existing search DB: %s (%d families)", db_path, len(present)) return db_path logger.info( "Search DB has %d families but %d needed — rebuilding", len(present & needed), len(needed), ) logger.info("Building combined search database from %d families", len(families)) all_names: list[str] = [] all_seqs: list[str] = [] for fam in families: family_id = fam["family_id"] fasta_path = Path(fam["seed_fasta_path"]) if not fasta_path.exists(): continue names, seqs = _parse_fasta_simple(fasta_path) # Strip gaps to get unaligned sequences seqs = _strip_gaps(seqs) for name, seq in zip(names, seqs): # Label with family for ground truth tracking labelled_name = f"{family_id}__{name}" all_names.append(labelled_name) all_seqs.append(seq) if not all_names: raise RuntimeError("No sequences available to build search database") _write_fasta_simple(db_path, all_names, all_seqs) logger.info( "Search database written: %s (%d sequences)", db_path, len(all_names), ) return db_path def _get_family_members(search_db: Path, family_id: str) -> set[str]: """Return the set of sequence names in the search DB that belong to the given family (identified by the ``__`` prefix). """ members: set[str] = set() with open(search_db) as fh: for line in fh: if line.startswith(">"): name = line[1:].split()[0] if name.startswith(f"{family_id}__"): members.add(name) return members # --------------------------------------------------------------------------- # Per-case pipeline # --------------------------------------------------------------------------- def run_hmmer_case( family: dict, method_name: str, search_db: Path, work_dir: Path, e_value_threshold: float = 1e-5, align_timeout: int | None = None, ) -> HmmerCaseResult: """Run the full HMMER pipeline for one family with one alignment method. Steps: 1. Read Pfam seed sequences for the family 2. Strip gaps to get unaligned sequences 3. Re-align using the named method via ``utils.run_method()`` 4. Build profile HMM from the new alignment 5. Search against the combined database 6. Score: family members detected = TP, non-members detected = FP Parameters ---------- family : dict Dict with ``family_id``, ``seed_fasta_path``, ``n_members``. method_name : str Alignment method name (key in ``METHODS``). search_db : Path Path to the combined search database FASTA. work_dir : Path Scratch directory for intermediate files. e_value_threshold : float E-value cutoff for hmmsearch. Returns ------- HmmerCaseResult """ from .utils import run_method, parse_fasta, write_fasta family_id = family["family_id"] seed_path = Path(family["seed_fasta_path"]) work_dir = Path(work_dir) work_dir.mkdir(parents=True, exist_ok=True) # 1. Read seed alignment and strip gaps to get unaligned sequences names, seqs = _parse_fasta_simple(seed_path) unaligned_seqs = _strip_gaps(seqs) # Write unaligned FASTA for the aligner unaln_path = work_dir / f"{family_id}_{method_name}_unaligned.fasta" write_fasta(names, unaligned_seqs, unaln_path) # 2. Align (with timeout protection for slow external tools) try: aln_result = run_method( method_name=method_name, input_fasta=unaln_path, work_dir=work_dir, seq_type="protein", timeout=align_timeout, ) except subprocess.TimeoutExpired: logger.warning( "Alignment timed out for %s/%s after %ss", family_id, method_name, align_timeout, ) return HmmerCaseResult( family_id=family_id, method=method_name, true_positives=0, false_positives=0, false_negatives=family.get("n_members", 0), sensitivity=0.0, specificity=0.0, e_value_threshold=e_value_threshold, hmm_length=0, wall_time_align=float(align_timeout or 0), wall_time_hmmbuild=0.0, wall_time_hmmsearch=0.0, peak_memory_mb=0.0, ) wall_time_align = aln_result.wall_time peak_memory_mb = aln_result.peak_memory_mb # Write alignment to FASTA for hmmbuild aln_path = work_dir / f"{family_id}_{method_name}_aligned.fasta" write_fasta(aln_result.names, aln_result.sequences, aln_path) # 3. Build HMM hmm_path = work_dir / f"{family_id}_{method_name}.hmm" try: hmm_info = _run_hmmbuild(aln_path, hmm_path) except RuntimeError as exc: logger.error("hmmbuild failed for %s/%s: %s", family_id, method_name, exc) return HmmerCaseResult( family_id=family_id, method=method_name, true_positives=0, false_positives=0, false_negatives=family.get("n_members", 0), sensitivity=0.0, specificity=0.0, e_value_threshold=e_value_threshold, hmm_length=0, wall_time_align=wall_time_align, wall_time_hmmbuild=0.0, wall_time_hmmsearch=0.0, peak_memory_mb=peak_memory_mb, ) wall_time_hmmbuild = hmm_info["wall_time"] hmm_length = hmm_info["hmm_length"] # 4. Search tblout_path = work_dir / f"{family_id}_{method_name}_hits.tbl" try: search_info = _run_hmmsearch( hmm_path, search_db, tblout_path, e_value=e_value_threshold ) except RuntimeError as exc: logger.error("hmmsearch failed for %s/%s: %s", family_id, method_name, exc) return HmmerCaseResult( family_id=family_id, method=method_name, true_positives=0, false_positives=0, false_negatives=family.get("n_members", 0), sensitivity=0.0, specificity=0.0, e_value_threshold=e_value_threshold, hmm_length=hmm_length, wall_time_align=wall_time_align, wall_time_hmmbuild=wall_time_hmmbuild, wall_time_hmmsearch=0.0, peak_memory_mb=peak_memory_mb, ) wall_time_hmmsearch = search_info["wall_time"] # 5. Score against ground truth true_members = _get_family_members(search_db, family_id) detected_names = {hit["name"] for hit in search_info["hits"]} tp = len(detected_names & true_members) fp = len(detected_names - true_members) fn = len(true_members - detected_names) sensitivity = tp / (tp + fn) if (tp + fn) > 0 else 0.0 precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0 return HmmerCaseResult( family_id=family_id, method=method_name, true_positives=tp, false_positives=fp, false_negatives=fn, sensitivity=sensitivity, specificity=precision, # using precision as the specificity metric e_value_threshold=e_value_threshold, hmm_length=hmm_length, wall_time_align=wall_time_align, wall_time_hmmbuild=wall_time_hmmbuild, wall_time_hmmsearch=wall_time_hmmsearch, peak_memory_mb=peak_memory_mb, ) # --------------------------------------------------------------------------- # Worker function for parallel execution # --------------------------------------------------------------------------- def _run_one(args: dict) -> dict: """Worker function for a single family x method evaluation. Parameters ---------- args : dict Must contain ``family``, ``method_name``, ``search_db``, ``work_dir``, ``e_value_threshold``. Returns ------- dict Serialisable case result, or ``{"error": str}`` on failure. """ from .utils import cache_load, cache_save, clean_work_dir fingerprint = args.get("fingerprint") work_dir = Path(args["work_dir"]) if fingerprint: cached = cache_load(work_dir, fingerprint) if cached is not None: return cached # Remove stale output files from previous runs clean_work_dir(work_dir) try: result = run_hmmer_case( family=args["family"], method_name=args["method_name"], search_db=Path(args["search_db"]), work_dir=work_dir, e_value_threshold=args.get("e_value_threshold", 1e-5), align_timeout=args.get("align_timeout"), ) result_dict = asdict(result) if fingerprint: cache_save(work_dir, fingerprint, result_dict) return result_dict except Exception as exc: logger.error( "Error in %s / %s: %s", args.get("family", {}).get("family_id", "?"), args.get("method_name", "?"), exc, ) return { "error": str(exc), "family_id": args.get("family", {}).get("family_id", "unknown"), "method": args.get("method_name", "unknown"), } # --------------------------------------------------------------------------- # Aggregation # --------------------------------------------------------------------------- def _compute_summary(cases: List[dict], methods: List[str]) -> dict: """Compute per-method aggregated metrics from case results. Parameters ---------- cases : list[dict] List of per-case result dicts (may include error entries). methods : list[str] Method names to summarise. Returns ------- dict Keyed by method name, each value is a dict of aggregated metrics. """ from .utils import bootstrap_ci, wilcoxon_paired, holm_bonferroni summary: dict = {} for method in methods: method_cases = [ c for c in cases if c.get("method") == method and "error" not in c ] if not method_cases: summary[method] = {"n_cases": 0} continue sensitivities = [c["sensitivity"] for c in method_cases] specificities = [c["specificity"] for c in method_cases] n = len(method_cases) mean_sens = sum(sensitivities) / n if n > 0 else 0.0 mean_spec = sum(specificities) / n if n > 0 else 0.0 # Bootstrap CIs (only if we have enough data) sens_ci = bootstrap_ci(sensitivities) if n >= 3 else (mean_sens, mean_sens) spec_ci = bootstrap_ci(specificities) if n >= 3 else (mean_spec, mean_spec) total_tp = sum(c["true_positives"] for c in method_cases) total_fp = sum(c["false_positives"] for c in method_cases) total_fn = sum(c["false_negatives"] for c in method_cases) mean_align_time = ( sum(c["wall_time_align"] for c in method_cases) / n if n > 0 else 0.0 ) mean_hmmbuild_time = ( sum(c["wall_time_hmmbuild"] for c in method_cases) / n if n > 0 else 0.0 ) mean_hmmsearch_time = ( sum(c["wall_time_hmmsearch"] for c in method_cases) / n if n > 0 else 0.0 ) summary[method] = { "n_cases": n, "mean_sensitivity": mean_sens, "sensitivity_ci_95": list(sens_ci), "mean_specificity": mean_spec, "specificity_ci_95": list(spec_ci), "total_tp": total_tp, "total_fp": total_fp, "total_fn": total_fn, "mean_wall_time_align": mean_align_time, "mean_wall_time_hmmbuild": mean_hmmbuild_time, "mean_wall_time_hmmsearch": mean_hmmsearch_time, } # Pairwise statistical tests: compare each method to "kalign" baseline = "kalign" baseline_cases = { c["family_id"]: c for c in cases if c.get("method") == baseline and "error" not in c } if baseline_cases: p_values = [] comparisons = [] for method in methods: if method == baseline: continue method_cases_map = { c["family_id"]: c for c in cases if c.get("method") == method and "error" not in c } # Find paired families shared_families = sorted( set(baseline_cases.keys()) & set(method_cases_map.keys()) ) if len(shared_families) >= 5: a_vals = [baseline_cases[f]["sensitivity"] for f in shared_families] b_vals = [method_cases_map[f]["sensitivity"] for f in shared_families] try: test = wilcoxon_paired(a_vals, b_vals) p_values.append(test["p_value"]) comparisons.append( { "comparison": f"{baseline}_vs_{method}", "statistic": test["statistic"], "p_value": test["p_value"], "cliffs_delta": test["cliffs_delta"], "n_paired": len(shared_families), } ) except Exception: pass if p_values: adjusted = holm_bonferroni(p_values) for comp, adj_p in zip(comparisons, adjusted): comp["p_value_adjusted"] = adj_p summary["_statistical_tests"] = comparisons return summary # --------------------------------------------------------------------------- # Main pipeline entry point # --------------------------------------------------------------------------- def run_pipeline(params: dict) -> HmmerResult: """Run the full HMMER homology detection benchmark. Parameters ---------- params : dict Configuration with keys: - ``data_dir`` : str or Path -- base data directory - ``results_dir`` : str or Path -- where to save JSON output - ``methods`` : list[str] -- alignment methods to test - ``n_families`` : int (default 50) -- number of Pfam families - ``n_jobs`` : int (default 1) -- parallel workers - ``quick`` : bool (default False) -- use only 5 families - ``e_value_threshold`` : float (default 1e-5) Returns ------- HmmerResult """ from .provenance import collect_provenance, result_path, update_latest_symlink from .utils import tool_versions_fingerprint data_dir = Path(params.get("data_dir", "benchmarks/data/downloads")) results_dir = Path(params.get("results_dir", "benchmarks/results")) methods = params.get("methods", ["kalign", "kalign_cons", "kalign_ens3", "mafft", "muscle", "clustalo"]) n_families = params.get("n_families", 50) n_jobs = params.get("n_jobs", 1) quick = params.get("quick", False) e_value_threshold = params.get("e_value_threshold", 1e-5) align_timeout = params.get("align_timeout", 300) # 5 min per alignment if quick: n_families = min(n_families, 5) logger.info("Quick mode: using %d families", n_families) # Collect provenance provenance = collect_provenance(params) # Download / load Pfam seeds families = _download_pfam_seeds(data_dir, n_families=n_families) if not families: raise RuntimeError( "No Pfam seed families available. " "Check network connectivity or populate the cache manually." ) # Prepare search database search_db = _prepare_search_db(families, data_dir) # Compute fingerprint once for all workers (None disables caching) if params.get("no_cache"): fingerprint = None logger.info("Caching disabled (--no-cache)") else: fingerprint = tool_versions_fingerprint() logger.info("Tool versions fingerprint: %s", fingerprint) # Build work items work_items: list[dict] = [] for family in families: for method_name in methods: case_work_dir = ( Path(data_dir) / "hmmer_work" / family["family_id"] / method_name ) work_items.append( { "family": family, "method_name": method_name, "search_db": str(search_db), "work_dir": str(case_work_dir), "e_value_threshold": e_value_threshold, "fingerprint": fingerprint, "align_timeout": align_timeout, } ) logger.info( "Running %d cases (%d families x %d methods) with %d workers", len(work_items), len(families), len(methods), n_jobs, ) # Execute from tqdm import tqdm all_cases: list[dict] = [] pbar = tqdm(total=len(work_items), desc="HMMER detection", unit="case") if n_jobs <= 1: for item in work_items: result = _run_one(item) all_cases.append(result) pbar.update(1) else: with ProcessPoolExecutor(max_workers=n_jobs) as executor: futures = { executor.submit(_run_one, item): item for item in work_items } for future in as_completed(futures): all_cases.append(future.result()) pbar.update(1) pbar.close() # Aggregate summary = _compute_summary(all_cases, methods) # Log summary table logger.info("=== HMMER Detection Summary ===") for method in methods: s = summary.get(method, {}) if s.get("n_cases", 0) > 0: logger.info( " %-20s sens=%.3f prec=%.3f (n=%d)", method, s["mean_sensitivity"], s["mean_specificity"], s["n_cases"], ) # Save results provenance_dict = asdict(provenance) hmmer_result = HmmerResult( provenance=provenance_dict, cases=all_cases, summary=summary, ) out_path = result_path(results_dir, "hmmer_detection") with open(out_path, "w") as fh: json.dump(asdict(hmmer_result), fh, indent=2, default=str) update_latest_symlink(out_path) logger.info("Results saved to %s", out_path) return hmmer_result # --------------------------------------------------------------------------- # Load results # --------------------------------------------------------------------------- def load_results(results_dir: Path) -> HmmerResult: """Load HMMER detection results from the latest result file. Parameters ---------- results_dir : Path Base results directory (the ``hmmer_detection/`` subdirectory is appended automatically). Returns ------- HmmerResult """ from .provenance import load_latest_results data = load_latest_results(Path(results_dir) / "hmmer_detection") return HmmerResult( provenance=data.get("provenance", {}), cases=data.get("cases", []), summary=data.get("summary", {}), ) # --------------------------------------------------------------------------- # CLI entry point # --------------------------------------------------------------------------- if __name__ == "__main__": import argparse logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", ) parser = argparse.ArgumentParser( description="Pipeline 3: HMMER Homology Detection Benchmark" ) parser.add_argument( "-j", "--parallel", type=int, default=1, help="Number of parallel workers (default: 1)", ) parser.add_argument( "--max-families", type=int, default=50, help="Maximum number of Pfam families to test (default: 50)", ) parser.add_argument( "--data-dir", type=str, default="benchmarks/data/downloads", help="Data directory for downloads and caches", ) parser.add_argument( "--results-dir", type=str, default="benchmarks/results", help="Results output directory", ) parser.add_argument( "--quick", action="store_true", help="Quick mode: only 5 families", ) parser.add_argument( "-v", "--verbose", action="store_true", help="Enable debug logging", ) parser.add_argument( "--methods", nargs="+", default=None, help="Alignment methods to test (default: all)", ) args = parser.parse_args() if args.verbose: logging.getLogger().setLevel(logging.DEBUG) from .utils import METHODS methods = args.methods or list(METHODS.keys()) run_pipeline( { "data_dir": args.data_dir, "results_dir": args.results_dir, "methods": methods, "n_families": args.max_families, "n_jobs": args.parallel, "quick": args.quick, } ) kalign-3.5.1/benchmarks/downstream/phylo_accuracy.py000066400000000000000000000575251515023132300226550ustar00rootroot00000000000000"""Pipeline 2: Phylogenetic Tree Accuracy. Evaluates how alignment quality affects phylogenetic tree inference. Simulates protein evolution with INDELible (WAG+Gamma), aligns with multiple methods, infers ML trees with IQ-TREE 2, and compares inferred trees to the true (simulated) tree using Robinson-Foulds distances. Methods that produce per-column confidence scores can pass them to IQ-TREE as site weights (``--site-weight`` flag) for continuous confidence weighting, or mask low-confidence columns before tree inference. """ from __future__ import annotations import json import logging import os import re import shutil import subprocess import time from dataclasses import asdict, dataclass, field from pathlib import Path from typing import Optional logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- # Result dataclasses # --------------------------------------------------------------------------- @dataclass class PhyloCaseResult: """Result of a single simulation x method phylogenetic analysis.""" sim_id: str method: str nrf: float # normalized Robinson-Foulds (0=perfect, 1=completely wrong) branch_score_dist: float # weighted RF sp_score: float # alignment SP vs true alignment n_columns_retained: int # after masking (if applicable) n_columns_total: int wall_time_align: float wall_time_iqtree: float peak_memory_mb: float @dataclass class PhyloResult: """Aggregated result for the full phylo accuracy pipeline.""" provenance: dict cases: list[dict] summary: dict # per-method aggregated metrics # --------------------------------------------------------------------------- # IQ-TREE runner # --------------------------------------------------------------------------- def _run_iqtree( alignment_path: Path, model: str, work_dir: Path, site_weights_path: Optional[Path] = None, n_threads: int = 1, timeout: int = 600, ) -> dict: """Run IQ-TREE 2 on an alignment and return the inferred tree. Parameters ---------- alignment_path : Path FASTA alignment file. model : str Substitution model string (e.g. ``"WAG+G4"``). work_dir : Path Working directory for IQ-TREE output files. site_weights_path : Path or None If given, passed to IQ-TREE via ``--site-weight`` for per-site weighting. n_threads : int Number of threads for IQ-TREE (default 1). timeout : int Maximum seconds before killing IQ-TREE (default 600). Returns ------- dict ``{"tree": str, "log_likelihood": float, "wall_time": float}`` Raises ------ RuntimeError If ``iqtree2`` is not found on ``$PATH`` or exits with an error. """ iqtree_bin = shutil.which("iqtree2") if iqtree_bin is None: raise RuntimeError( "iqtree2 is not installed or not on PATH. " "Please install IQ-TREE 2 (http://www.iqtree.org/) " "and ensure the 'iqtree2' binary is accessible." ) work_dir = Path(work_dir) work_dir.mkdir(parents=True, exist_ok=True) prefix = work_dir / "iqtree" cmd = [ iqtree_bin, "-s", str(alignment_path), "-m", model, "--prefix", str(prefix), "-nt", str(n_threads), "--fast", "-redo", ] # Note: IQ-TREE 2 does not support per-site weights. # The site_weights_path parameter is accepted but ignored. # Weighted methods (kalign_ens3_wt, guidance2_wt) run IQ-TREE # on the full unmasked alignment, providing a baseline comparison. if site_weights_path is not None: logger.debug("Site weights file ignored (IQ-TREE has no weighting support)") start = time.perf_counter() try: proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) except subprocess.TimeoutExpired: wall = time.perf_counter() - start raise RuntimeError( f"iqtree2 timed out after {timeout}s ({wall:.0f}s elapsed) " f"in {work_dir}" ) wall = time.perf_counter() - start if proc.returncode != 0: raise RuntimeError( f"iqtree2 failed (exit {proc.returncode}):\n" f"stdout:\n{proc.stdout}\n" f"stderr:\n{proc.stderr}" ) # Parse the treefile treefile = Path(str(prefix) + ".treefile") if not treefile.exists(): raise FileNotFoundError( f"IQ-TREE treefile not found at {treefile}. " f"Contents of {work_dir}: {list(work_dir.iterdir())}" ) tree_str = treefile.read_text().strip() # Parse log-likelihood from the .iqtree summary file log_likelihood = float("nan") iqtree_log = Path(str(prefix) + ".iqtree") if iqtree_log.exists(): log_text = iqtree_log.read_text() # Look for "Log-likelihood of the tree: -12345.6789 (..." m = re.search(r"Log-likelihood of the tree:\s+([-\d.]+)", log_text) if m: try: log_likelihood = float(m.group(1)) except ValueError: pass return { "tree": tree_str, "log_likelihood": log_likelihood, "wall_time": wall, } # --------------------------------------------------------------------------- # Single-case runner # --------------------------------------------------------------------------- def run_phylo_case( sim_dataset, method_name: str, work_dir: Path, model: str = "WAG+G4", n_threads: int = 1, iqtree_timeout: int = 600, ) -> PhyloCaseResult: """Run the full phylo pipeline for one simulation x method combination. Steps: 1. Align unaligned sequences with the specified method. 2. Write site weights if the method produces them. 3. Run IQ-TREE on the (possibly masked/weighted) alignment. 4. Compare the inferred tree against the true tree. Parameters ---------- sim_dataset : SimulatedDataset Simulation output (unaligned seqs, true alignment, true tree). method_name : str Key into ``utils.METHODS``. work_dir : Path Scratch directory for this case. model : str IQ-TREE substitution model (default ``"WAG+G4"``). Returns ------- PhyloCaseResult """ from .utils import ( alignment_accuracy, compare_trees, parse_fasta, run_method, write_fasta, METHODS, ) work_dir = Path(work_dir) work_dir.mkdir(parents=True, exist_ok=True) sim_id = sim_dataset.params.get("sim_id", str(sim_dataset.unaligned)) # -- "true" method: use true alignment directly as performance ceiling -- if method_name == "true": true_names, true_seqs = parse_fasta(sim_dataset.true_alignment) aln_fasta = work_dir / "true_aln.fasta" write_fasta(true_names, true_seqs, aln_fasta) n_columns_total = len(true_seqs[0]) if true_seqs else 0 iqtree_dir = work_dir / "true_iqtree" iqtree_result = _run_iqtree( aln_fasta, model, iqtree_dir, n_threads=n_threads, timeout=iqtree_timeout, ) true_tree_str = sim_dataset.true_tree.read_text().strip() tree_cmp = compare_trees(true_tree_str, iqtree_result["tree"]) return PhyloCaseResult( sim_id=sim_id, method="true", nrf=tree_cmp["nrf"], branch_score_dist=tree_cmp["branch_score_dist"], sp_score=1.0, n_columns_retained=n_columns_total, n_columns_total=n_columns_total, wall_time_align=0.0, wall_time_iqtree=iqtree_result["wall_time"], peak_memory_mb=0.0, ) # -- Step 1: Align ------------------------------------------------------- # For guided methods, pass the true alignment as input so that # kalign can compute pairwise distances from it and build a tree. input_fasta = sim_dataset.unaligned aln_result = run_method( method_name, input_fasta, work_dir, seq_type="protein", ) # Determine alignment dimensions n_columns_total = len(aln_result.sequences[0]) if aln_result.sequences else 0 n_columns_retained = n_columns_total # masking already applied by run_method # -- Step 2: Write alignment to FASTA for IQ-TREE ----------------------- aln_fasta = work_dir / f"{method_name}_aln.fasta" write_fasta(aln_result.names, aln_result.sequences, aln_fasta) # -- Step 3: Check for site weights file -------------------------------- cfg = METHODS.get(method_name, {}) site_weights_path = None if cfg.get("weights") and aln_result.column_confidence is not None: wt_path = work_dir / f"{method_name}_site_weights.txt" if wt_path.exists(): site_weights_path = wt_path # -- Step 4: Pre-check for all-gap sequences ---------------------------- for name, seq in zip(aln_result.names, aln_result.sequences): if all(c == "-" for c in seq): raise RuntimeError( f"Sequence '{name}' is all gaps after alignment/masking — " f"IQ-TREE would reject this. Method={method_name}" ) # -- Step 5: Run IQ-TREE ------------------------------------------------ iqtree_dir = work_dir / f"{method_name}_iqtree" iqtree_result = _run_iqtree( aln_fasta, model, iqtree_dir, site_weights_path=site_weights_path, n_threads=n_threads, timeout=iqtree_timeout, ) # -- Step 6: Compare inferred vs true tree ------------------------------ true_tree_str = sim_dataset.true_tree.read_text().strip() tree_cmp = compare_trees(true_tree_str, iqtree_result["tree"]) # -- Step 7: Alignment accuracy vs true alignment ----------------------- true_names, true_seqs = parse_fasta(sim_dataset.true_alignment) acc = alignment_accuracy( aln_result.sequences, true_seqs, aln_result.names, true_names, ) return PhyloCaseResult( sim_id=sim_id, method=method_name, nrf=tree_cmp["nrf"], branch_score_dist=tree_cmp["branch_score_dist"], sp_score=acc["sp_score"], n_columns_retained=n_columns_retained, n_columns_total=n_columns_total, wall_time_align=aln_result.wall_time, wall_time_iqtree=iqtree_result["wall_time"], peak_memory_mb=aln_result.peak_memory_mb, ) # --------------------------------------------------------------------------- # Pipeline entry point # --------------------------------------------------------------------------- def _phylo_worker(sim_ds, mname, data_dir, fingerprint=None, n_threads=1, iqtree_timeout=600): """Worker function for a single sim x method case (module-level for pickling).""" from .utils import cache_load, cache_save, clean_work_dir sim_id = sim_ds.params.get("sim_id", "unknown") case_dir = Path(data_dir) / "phylo_work" / sim_id / mname case_dir.mkdir(parents=True, exist_ok=True) if fingerprint: cached = cache_load(case_dir, fingerprint) if cached is not None: return cached # Remove stale output files (e.g. IQ-TREE checkpoints) from previous runs clean_work_dir(case_dir) try: result = run_phylo_case( sim_ds, mname, case_dir, n_threads=n_threads, iqtree_timeout=iqtree_timeout, ) result_dict = asdict(result) if fingerprint: cache_save(case_dir, fingerprint, result_dict) return result_dict except Exception as exc: logger.warning("Phylo case %s/%s failed: %s", sim_id, mname, exc) return {"sim_id": sim_id, "method": mname, "error": str(exc)} def run_pipeline(params: dict) -> PhyloResult: """Run the full phylo accuracy pipeline. Parameters ---------- params : dict Configuration with keys: - ``data_dir`` : str or Path -- base directory for simulation data - ``results_dir`` : str or Path -- where to write result JSON - ``methods`` : list[str] -- method names (keys into METHODS) - ``n_jobs`` : int -- max parallel workers - ``quick`` : bool -- if True, limit to 5 simulation cases Returns ------- PhyloResult """ from concurrent.futures import ProcessPoolExecutor, as_completed from .provenance import ( collect_provenance, result_path, update_latest_symlink, ) from .simulation import ( PROTEIN_GRID, PROTEIN_GRID_FULL, generate_indelible_dataset, iter_simulation_params, random_birth_death_tree, ) from .utils import ( tool_versions_fingerprint, METHODS, ) data_dir = Path(params.get("data_dir", "benchmarks/data/downloads")) results_dir = Path(params.get("results_dir", "benchmarks/results")) full = params.get("full", False) _default_methods = ["kalign", "kalign_cons", "kalign_ens3", "mafft", "muscle", "clustalo", "true"] methods = params.get("methods", list(METHODS.keys()) if full else _default_methods) n_jobs = params.get("n_jobs", 1) quick = params.get("quick", False) depth_filter = params.get("depths", None) logger.info("Phylo accuracy pipeline starting (quick=%s, n_jobs=%d)", quick, n_jobs) # -- Generate simulations ----------------------------------------------- grid = PROTEIN_GRID_FULL if full else PROTEIN_GRID sim_params_list = list(iter_simulation_params(grid, "WAG")) if quick: sim_params_list = sim_params_list[:5] if depth_filter: depth_set = set(float(d) for d in depth_filter) sim_params_list = [sp for sp in sim_params_list if sp["target_depth"] in depth_set] logger.info("Filtered to depths %s: %d simulations", depth_set, len(sim_params_list)) from tqdm import tqdm sim_dir = data_dir / "phylo_sims" sim_dir.mkdir(parents=True, exist_ok=True) simulations = [] for sp in tqdm(sim_params_list, desc="Generating simulations", unit="sim"): sim_out = sim_dir / sp["sim_id"] tree = random_birth_death_tree( n_taxa=sp["n_taxa"], target_depth=sp["target_depth"], seed=sp["seed"], ) try: ds = generate_indelible_dataset( tree=tree, model=sp["model"], seq_length=sp["seq_length"], indel_rate=sp["indel_rate"], indel_length_mean=sp["indel_length_mean"], output_dir=sim_out, seed=sp["seed"], ) # Attach sim_id into params for later reference ds.params["sim_id"] = sp["sim_id"] simulations.append(ds) except Exception as exc: logger.warning("Simulation %s failed: %s", sp["sim_id"], exc) logger.info("Generated %d simulations successfully.", len(simulations)) # Compute fingerprint once for all workers (None disables caching) if params.get("no_cache"): fingerprint = None logger.info("Caching disabled (--no-cache)") else: fingerprint = tool_versions_fingerprint() logger.info("Tool versions fingerprint: %s", fingerprint) # -- Run alignment + tree inference for each sim x method ---------------- # Allocate IQ-TREE threads: divide available cores among parallel workers cpu_count = os.cpu_count() or 1 iq_threads = max(1, cpu_count // max(n_jobs, 1)) iq_timeout = 600 # 10 minutes per IQ-TREE run logger.info( "IQ-TREE will use %d threads per job (%d cores / %d jobs)", iq_threads, cpu_count, n_jobs, ) cases: list[dict] = [] # Build work items work_items = [ (sim_ds, mname) for sim_ds in simulations for mname in methods if mname in METHODS ] pbar = tqdm(total=len(work_items), desc="Phylo accuracy", unit="case") if n_jobs <= 1: # Sequential execution for sim_ds, mname in work_items: cases.append(_phylo_worker( sim_ds, mname, data_dir, fingerprint, n_threads=iq_threads, iqtree_timeout=iq_timeout, )) pbar.update(1) else: with ProcessPoolExecutor(max_workers=n_jobs) as pool: futures = { pool.submit( _phylo_worker, sim_ds, mname, data_dir, fingerprint, n_threads=iq_threads, iqtree_timeout=iq_timeout, ): (sim_ds, mname) for sim_ds, mname in work_items } for future in as_completed(futures): try: cases.append(future.result()) except Exception as exc: sim_ds, mname = futures[future] sim_id = sim_ds.params.get("sim_id", "unknown") logger.warning( "Future for %s/%s raised: %s", sim_id, mname, exc, ) cases.append({ "sim_id": sim_id, "method": mname, "error": str(exc), }) pbar.update(1) pbar.close() logger.info("Completed %d cases.", len(cases)) # -- Aggregate: per-method summary -------------------------------------- summary = _aggregate_summary(cases, methods) # -- Statistical tests: pairwise Wilcoxon on nRF ----------------------- _add_statistical_tests(summary, cases, methods) # -- Provenance --------------------------------------------------------- provenance = collect_provenance(params) result = PhyloResult( provenance=asdict(provenance), cases=cases, summary=summary, ) # -- Save to disk ------------------------------------------------------- out_path = result_path(results_dir, "phylo_accuracy") with open(out_path, "w") as fh: json.dump(asdict(result) if hasattr(result, "__dataclass_fields__") else { "provenance": result.provenance, "cases": result.cases, "summary": result.summary, }, fh, indent=2, default=str) update_latest_symlink(out_path) logger.info("Results saved to %s", out_path) # -- Console summary --------------------------------------------------- _print_summary(summary) return result # --------------------------------------------------------------------------- # Internal aggregation helpers # --------------------------------------------------------------------------- def _aggregate_summary(cases: list[dict], methods: list[str]) -> dict: """Compute per-method aggregated metrics from case results.""" import numpy as np from .utils import bootstrap_ci summary: dict = {} for mname in methods: method_cases = [ c for c in cases if c.get("method") == mname and "error" not in c ] if not method_cases: summary[mname] = {"n_cases": 0} continue nrf_vals = [c["nrf"] for c in method_cases] bsd_vals = [c["branch_score_dist"] for c in method_cases] sp_vals = [c["sp_score"] for c in method_cases if c.get("sp_score", -1) >= 0] nrf_arr = np.asarray(nrf_vals, dtype=float) bsd_arr = np.asarray(bsd_vals, dtype=float) entry = { "n_cases": len(method_cases), "mean_nrf": float(nrf_arr.mean()), "std_nrf": float(nrf_arr.std()), "mean_branch_score_dist": float(bsd_arr.mean()), "std_branch_score_dist": float(bsd_arr.std()), } if len(nrf_vals) >= 5: ci_lo, ci_hi = bootstrap_ci(nrf_vals) entry["nrf_ci_95"] = [ci_lo, ci_hi] if sp_vals: sp_arr = np.asarray(sp_vals, dtype=float) entry["mean_sp_score"] = float(sp_arr.mean()) entry["std_sp_score"] = float(sp_arr.std()) # Mean timings align_times = [c.get("wall_time_align", 0) for c in method_cases] iqtree_times = [c.get("wall_time_iqtree", 0) for c in method_cases] entry["mean_wall_time_align"] = float(np.mean(align_times)) entry["mean_wall_time_iqtree"] = float(np.mean(iqtree_times)) summary[mname] = entry return summary def _add_statistical_tests( summary: dict, cases: list[dict], methods: list[str], ) -> None: """Add pairwise Wilcoxon tests on nRF to the summary.""" from .utils import holm_bonferroni, wilcoxon_paired # Build per-sim_id lookup for each method method_nrf: dict[str, dict[str, float]] = {} for c in cases: if "error" in c: continue mname = c["method"] sim_id = c["sim_id"] method_nrf.setdefault(mname, {})[sim_id] = c["nrf"] # All pairwise tests active_methods = [m for m in methods if m in method_nrf and len(method_nrf[m]) >= 5] pairwise_tests = [] p_values = [] for i, m1 in enumerate(active_methods): for m2 in active_methods[i + 1:]: # Find common sim_ids common = sorted(set(method_nrf[m1].keys()) & set(method_nrf[m2].keys())) if len(common) < 5: continue a = [method_nrf[m1][sid] for sid in common] b = [method_nrf[m2][sid] for sid in common] try: test = wilcoxon_paired(a, b) pairwise_tests.append({ "method_a": m1, "method_b": m2, "n_pairs": len(common), **test, }) p_values.append(test["p_value"]) except Exception as exc: logger.debug("Wilcoxon test %s vs %s failed: %s", m1, m2, exc) # Apply Holm-Bonferroni correction if p_values: adjusted = holm_bonferroni(p_values) for t, adj_p in zip(pairwise_tests, adjusted): t["p_value_adjusted"] = adj_p summary["_pairwise_tests"] = pairwise_tests def _print_summary(summary: dict) -> None: """Print a concise summary table to the console.""" print("\n--- Phylo Accuracy Summary ---") print(f"{'Method':<25s} {'N':>5s} {'nRF':>8s} {'BSD':>8s} {'SP':>8s} {'t_aln':>8s} {'t_iq':>8s}") print("-" * 75) for mname, stats in sorted(summary.items()): if mname.startswith("_"): continue n = stats.get("n_cases", 0) if n == 0: print(f"{mname:<25s} {n:>5d} {'N/A':>6s} {'N/A':>6s} {'N/A':>6s}") continue nrf = stats.get("mean_nrf", float("nan")) bsd = stats.get("mean_branch_score_dist", float("nan")) sp = stats.get("mean_sp_score", float("nan")) t_aln = stats.get("mean_wall_time_align", float("nan")) t_iq = stats.get("mean_wall_time_iqtree", float("nan")) print(f"{mname:<25s} {n:>5d} {nrf:>8.4f} {bsd:>8.4f} {sp:>8.4f} {t_aln:>7.2f}s {t_iq:>7.2f}s") # Print pairwise tests tests = summary.get("_pairwise_tests", []) if tests: print(f"\nPairwise Wilcoxon signed-rank tests (nRF, Holm-Bonferroni corrected):") print(f"{'A vs B':<45s} {'delta':>8s} {'p_adj':>10s}") print("-" * 65) for t in tests: label = f"{t['method_a']} vs {t['method_b']}" delta = t.get("cliffs_delta", float("nan")) p_adj = t.get("p_value_adjusted", t.get("p_value", float("nan"))) print(f"{label:<45s} {delta:>8.3f} {p_adj:>10.4g}") print() # --------------------------------------------------------------------------- # Load results # --------------------------------------------------------------------------- def load_results(results_dir) -> PhyloResult: """Load the latest phylo accuracy results from disk. Parameters ---------- results_dir : str or Path Base results directory (expects a ``phylo_accuracy/`` subdirectory with a ``latest.json`` symlink). Returns ------- PhyloResult """ from .provenance import load_latest_results data = load_latest_results(Path(results_dir) / "phylo_accuracy") return PhyloResult( provenance=data.get("provenance", {}), cases=data.get("cases", []), summary=data.get("summary", {}), ) kalign-3.5.1/benchmarks/downstream/positive_selection.py000066400000000000000000001000101515023132300235310ustar00rootroot00000000000000"""Pipeline 1: Positive Selection Analysis. Measures how alignment quality affects false-positive and false-negative rates in dN/dS site-model tests. Simulates codon evolution under M7/M8 models with INDELible, aligns with multiple methods, runs HyPhy FUBAR, and compares detected positively-selected sites against ground truth. """ from __future__ import annotations import json import logging import os import shutil import subprocess import time from concurrent.futures import ProcessPoolExecutor, as_completed from dataclasses import asdict, dataclass, field from pathlib import Path from typing import Any, Dict, List, Optional logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- # Codon translation / back-translation helpers # --------------------------------------------------------------------------- # Standard genetic code (NCBI translation table 1) _CODON_TABLE = { "TTT": "F", "TTC": "F", "TTA": "L", "TTG": "L", "CTT": "L", "CTC": "L", "CTA": "L", "CTG": "L", "ATT": "I", "ATC": "I", "ATA": "I", "ATG": "M", "GTT": "V", "GTC": "V", "GTA": "V", "GTG": "V", "TCT": "S", "TCC": "S", "TCA": "S", "TCG": "S", "CCT": "P", "CCC": "P", "CCA": "P", "CCG": "P", "ACT": "T", "ACC": "T", "ACA": "T", "ACG": "T", "GCT": "A", "GCC": "A", "GCA": "A", "GCG": "A", "TAT": "Y", "TAC": "Y", "TAA": "*", "TAG": "*", "CAT": "H", "CAC": "H", "CAA": "Q", "CAG": "Q", "AAT": "N", "AAC": "N", "AAA": "K", "AAG": "K", "GAT": "D", "GAC": "D", "GAA": "E", "GAG": "E", "TGT": "C", "TGC": "C", "TGA": "*", "TGG": "W", "CGT": "R", "CGC": "R", "CGA": "R", "CGG": "R", "AGT": "S", "AGC": "S", "AGA": "R", "AGG": "R", "GGT": "G", "GGC": "G", "GGA": "G", "GGG": "G", } def _translate_dna(dna_seq: str) -> str: """Translate a DNA sequence to protein using the standard genetic code. Stop codons are omitted from the output. The DNA sequence length must be a multiple of 3. """ dna_seq = dna_seq.upper() if len(dna_seq) % 3 != 0: raise ValueError( f"DNA sequence length {len(dna_seq)} is not a multiple of 3" ) protein = [] for i in range(0, len(dna_seq), 3): codon = dna_seq[i : i + 3] aa = _CODON_TABLE.get(codon, "X") if aa != "*": protein.append(aa) return "".join(protein) def _backtranslate( protein_aln: str, original_dna: str, ) -> str: """Back-translate an aligned protein sequence to a codon alignment. Each non-gap character in *protein_aln* is replaced by the corresponding original DNA codon (3 nucleotides). Each gap character (``-``) is replaced by ``---``. Parameters ---------- protein_aln : str Aligned protein sequence (may contain ``-`` gap characters). original_dna : str Original unaligned DNA sequence (ungapped, length must be a multiple of 3). Returns ------- str Codon-aligned DNA sequence where every position is exactly 3 characters (either a codon or ``---``). """ original_dna = original_dna.upper() # Build list of codons from original DNA (excluding stop codons) codons: list[str] = [] for i in range(0, len(original_dna), 3): codon = original_dna[i : i + 3] aa = _CODON_TABLE.get(codon, "X") if aa != "*": codons.append(codon) codon_idx = 0 result: list[str] = [] for ch in protein_aln: if ch == "-": result.append("---") else: if codon_idx >= len(codons): raise ValueError( f"Protein alignment has more residues than available " f"codons ({len(codons)})" ) result.append(codons[codon_idx]) codon_idx += 1 if codon_idx != len(codons): raise ValueError( f"Protein alignment used {codon_idx} residues but original DNA " f"has {len(codons)} non-stop codons" ) return "".join(result) # --------------------------------------------------------------------------- # Result dataclasses # --------------------------------------------------------------------------- @dataclass class SelectionCaseResult: """Result of a single (simulation x method) case.""" sim_id: str method: str true_positives: int false_positives: int false_negatives: int true_negatives: int precision: float recall: float f1: float sp_score: float wall_time_align: float wall_time_hyphy: float peak_memory_mb: float n_sites_tested: int @dataclass class SelectionResult: """Aggregate result for the full positive-selection pipeline.""" provenance: dict cases: list[dict] summary: dict # per-method aggregated metrics # --------------------------------------------------------------------------- # HyPhy FUBAR runner # --------------------------------------------------------------------------- def _run_hyphy_fubar( alignment_path: Path, tree_path: Path, work_dir: Path, ) -> dict: """Run HyPhy FUBAR on a codon alignment. Parameters ---------- alignment_path : Path Path to aligned codon sequences in FASTA format. tree_path : Path Path to Newick tree file. work_dir : Path Working directory for HyPhy output files. Returns ------- dict ``{"site_posteriors": list[float], "n_sites": int}`` where each element of *site_posteriors* is the posterior probability of positive selection (``Prob[alpha < beta]``) at each codon site. Raises ------ RuntimeError If HyPhy is not found or exits with an error. """ hyphy_bin = shutil.which("hyphy") or shutil.which("HYPHYMP") if hyphy_bin is None: raise RuntimeError( "HyPhy is not installed or not on PATH. " "Please install HyPhy (https://www.hyphy.org/) " "and ensure the 'hyphy' binary is accessible." ) alignment_path = Path(alignment_path).resolve() tree_path = Path(tree_path).resolve() work_dir = Path(work_dir).resolve() work_dir.mkdir(parents=True, exist_ok=True) # HyPhy FUBAR outputs a JSON file next to the alignment # with the suffix .FUBAR.json output_json = work_dir / (alignment_path.name + ".FUBAR.json") cmd = [ hyphy_bin, "fubar", "--alignment", str(alignment_path), "--tree", str(tree_path), "--output", str(output_json), ] # Build environment with HYPHY_PATH so HyPhy can find its batch files. # HYPHY_LIB (set in Containerfile) is not the variable HyPhy checks; # it needs HYPHY_PATH. env = dict(os.environ) hyphy_lib = env.get("HYPHY_LIB") or env.get("HYPHY_PATH") if hyphy_lib: env["HYPHY_PATH"] = hyphy_lib logger.debug("Running HyPhy FUBAR: %s", " ".join(cmd)) proc = subprocess.run( cmd, capture_output=True, text=True, cwd=str(work_dir), env=env, ) if proc.returncode != 0: raise RuntimeError( f"HyPhy FUBAR failed (exit {proc.returncode}).\n" f"stdout:\n{proc.stdout}\n" f"stderr:\n{proc.stderr}" ) # Parse results JSON if not output_json.exists(): # HyPhy may place the JSON in the same directory as the alignment alt_json = alignment_path.parent / (alignment_path.name + ".FUBAR.json") if alt_json.exists(): output_json = alt_json else: raise RuntimeError( f"HyPhy FUBAR output JSON not found at {output_json} " f"or {alt_json}" ) with open(output_json) as fh: fubar_data = json.load(fh) # FUBAR JSON structure: # "MLE" -> "content" -> { # "0" -> {"headers": [...], "0": [row0], "1": [row1], ...} # } # Headers typically include: # "alpha", "beta", "Prob[alpha>beta]", "Prob[alpha prob_col_idx: site_posteriors.append(float(row[prob_col_idx])) else: site_posteriors.append(0.0) return { "site_posteriors": site_posteriors, "n_sites": len(site_posteriors), } # --------------------------------------------------------------------------- # Site classification # --------------------------------------------------------------------------- def _classify_sites( posteriors: list[float], true_classes: list[int], threshold: float = 0.9, ) -> dict: """Classify sites as positively selected and compute confusion metrics. Parameters ---------- posteriors : list[float] FUBAR posterior probability of positive selection per site. true_classes : list[int] Ground-truth site classes: 1 = positive selection, 0 = neutral. threshold : float A site is predicted positive if posterior >= threshold. Returns ------- dict ``{"true_positives", "false_positives", "false_negatives", "true_negatives", "precision", "recall", "f1", "n_sites_tested"}`` """ n = min(len(posteriors), len(true_classes)) tp = fp = fn = tn = 0 for i in range(n): predicted_positive = posteriors[i] >= threshold actual_positive = true_classes[i] == 1 if predicted_positive and actual_positive: tp += 1 elif predicted_positive and not actual_positive: fp += 1 elif not predicted_positive and actual_positive: fn += 1 else: tn += 1 precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0 recall = tp / (tp + fn) if (tp + fn) > 0 else 0.0 f1 = ( 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0.0 ) return { "true_positives": tp, "false_positives": fp, "false_negatives": fn, "true_negatives": tn, "precision": precision, "recall": recall, "f1": f1, "n_sites_tested": n, } # --------------------------------------------------------------------------- # Single-case runner # --------------------------------------------------------------------------- def run_selection_case( sim_dataset, method_name: str, work_dir: Path, threshold: float = 0.9, ) -> SelectionCaseResult: """Run the full positive-selection pipeline for one (sim x method) case. Parameters ---------- sim_dataset : SimulatedDataset A simulated dataset (from :mod:`.simulation`). method_name : str Key into ``utils.METHODS``. work_dir : Path Scratch directory for this case. threshold : float FUBAR posterior threshold for calling positive selection. Returns ------- SelectionCaseResult """ from .utils import ( alignment_accuracy, mask_alignment_by_confidence, METHODS, parse_fasta, run_method, write_fasta, ) work_dir = Path(work_dir) work_dir.mkdir(parents=True, exist_ok=True) sim_id = sim_dataset.params.get("sim_id", "unknown") if hasattr(sim_dataset, "params") and isinstance(sim_dataset.params, dict): sim_id = sim_dataset.params.get("sim_id", sim_id) # "true" method: use the true codon alignment directly as performance ceiling if method_name == "true": true_names, true_seqs = parse_fasta(sim_dataset.true_alignment) aln_path = work_dir / "aligned.fasta" write_fasta(true_names, true_seqs, aln_path) t0_hyphy = time.perf_counter() fubar_result = _run_hyphy_fubar( alignment_path=aln_path, tree_path=sim_dataset.true_tree, work_dir=work_dir, ) wall_time_hyphy = time.perf_counter() - t0_hyphy metrics = _classify_sites( posteriors=fubar_result["site_posteriors"], true_classes=sim_dataset.site_classes, threshold=threshold, ) return SelectionCaseResult( sim_id=sim_id, method="true", true_positives=metrics["true_positives"], false_positives=metrics["false_positives"], false_negatives=metrics["false_negatives"], true_negatives=metrics["true_negatives"], precision=metrics["precision"], recall=metrics["recall"], f1=metrics["f1"], sp_score=1.0, wall_time_align=0.0, wall_time_hyphy=wall_time_hyphy, peak_memory_mb=0.0, n_sites_tested=metrics["n_sites_tested"], ) # 1. Translate-align-backtranslate to preserve codon reading frame # Standard DNA alignment can insert 1- or 2-nt gaps that break # the codon frame, causing HyPhy FUBAR to fail. # Masking is deferred to the codon level (skip_masking=True) # so that backtranslation has the full protein alignment. # 1a. Read unaligned DNA sequences dna_names, dna_seqs = parse_fasta(sim_dataset.unaligned) # 1b. Translate DNA to protein protein_seqs = [_translate_dna(s) for s in dna_seqs] # 1c. Write temporary protein FASTA prot_fasta = work_dir / "protein_input.fasta" write_fasta(dna_names, protein_seqs, prot_fasta) # 1d. Align proteins (skip masking so we get the full alignment) aln_result = run_method( method_name, prot_fasta, work_dir, seq_type="protein", skip_masking=True, ) # 1e. Back-translate protein alignment to codon alignment # Map aligned protein names back to original DNA sequences dna_by_name = dict(zip(dna_names, dna_seqs)) codon_seqs: list[str] = [] for name, prot_aln_seq in zip(aln_result.names, aln_result.sequences): orig_dna = dna_by_name[name] codon_seqs.append(_backtranslate(prot_aln_seq, orig_dna)) # Sanity check: all codon-aligned sequences must be the same length if codon_seqs: expected_len = len(codon_seqs[0]) for i, cs in enumerate(codon_seqs): if len(cs) != expected_len: raise ValueError( f"Codon alignment length mismatch: seq {i} has " f"{len(cs)} nt, expected {expected_len}" ) # 1f. Apply confidence masking at the codon level if configured # Each protein column maps to one codon column (3 nt). mask_threshold = METHODS.get(method_name, {}).get("mask") if mask_threshold is not None and aln_result.column_confidence is not None: # Expand protein column_confidence to codon columns (3x) codon_confidence = [c for c in aln_result.column_confidence for _ in range(3)] codon_seqs, _ = mask_alignment_by_confidence( codon_seqs, codon_confidence, mask_threshold ) # 2. Write codon-aligned output to work_dir aln_path = work_dir / "aligned.fasta" # Check if masking removed all columns (empty alignment) aln_len = len(codon_seqs[0]) if codon_seqs else 0 if aln_len == 0: raise RuntimeError( f"Masking removed all columns for {method_name} — " "cannot run FUBAR on an empty alignment" ) write_fasta(aln_result.names, codon_seqs, aln_path) # 3. Compute alignment accuracy vs true alignment (codon level) true_names, true_seqs = parse_fasta(sim_dataset.true_alignment) acc = alignment_accuracy( test_sequences=codon_seqs, true_sequences=true_seqs, test_names=aln_result.names, true_names=true_names, ) sp_score = acc.get("sp_score", -1.0) # 4. Run HyPhy FUBAR t0_hyphy = time.perf_counter() fubar_result = _run_hyphy_fubar( alignment_path=aln_path, tree_path=sim_dataset.true_tree, work_dir=work_dir, ) wall_time_hyphy = time.perf_counter() - t0_hyphy # 5. Classify sites vs true labels metrics = _classify_sites( posteriors=fubar_result["site_posteriors"], true_classes=sim_dataset.site_classes, threshold=threshold, ) return SelectionCaseResult( sim_id=sim_id, method=method_name, true_positives=metrics["true_positives"], false_positives=metrics["false_positives"], false_negatives=metrics["false_negatives"], true_negatives=metrics["true_negatives"], precision=metrics["precision"], recall=metrics["recall"], f1=metrics["f1"], sp_score=sp_score, wall_time_align=aln_result.wall_time, wall_time_hyphy=wall_time_hyphy, peak_memory_mb=aln_result.peak_memory_mb, n_sites_tested=metrics["n_sites_tested"], ) # --------------------------------------------------------------------------- # Worker function for parallel execution # --------------------------------------------------------------------------- def _run_one(args: dict) -> dict: """Worker: align + score one (simulation x method) case. Simulations must already be generated before calling this. Returns a dict (serialisable result or error). """ from .utils import cache_load, cache_save, clean_work_dir sim_dataset = args["sim_dataset"] method_name = args["method_name"] work_dir = Path(args["work_dir"]) threshold = args.get("threshold", 0.9) fingerprint = args.get("fingerprint") sim_id = sim_dataset.params.get("sim_id", "unknown") # Check cache if fingerprint: cached = cache_load(work_dir, fingerprint) if cached is not None: return cached # Remove stale output files from previous runs clean_work_dir(work_dir) try: result = run_selection_case( sim_dataset=sim_dataset, method_name=method_name, work_dir=work_dir, threshold=threshold, ) result_dict = asdict(result) if fingerprint: cache_save(work_dir, fingerprint, result_dict) return result_dict except Exception as exc: logger.error( "Error in %s / %s: %s", sim_id, method_name, exc, exc_info=True ) return { "sim_id": sim_id, "method": method_name, "error": str(exc), } # --------------------------------------------------------------------------- # Aggregation helpers # --------------------------------------------------------------------------- def _aggregate_summary( cases: list[dict], methods: list[str], ) -> dict: """Compute per-method aggregated metrics from case results. Returns a dict keyed by method name, each with mean precision, recall, F1, SP score, and timing. """ from .utils import bootstrap_ci summary: dict[str, dict] = {} for method in methods: method_cases = [c for c in cases if c.get("method") == method and "error" not in c] n = len(method_cases) if n == 0: summary[method] = { "n_cases": 0, "mean_precision": 0.0, "mean_recall": 0.0, "mean_f1": 0.0, "mean_sp_score": 0.0, "mean_wall_time_align": 0.0, "mean_wall_time_hyphy": 0.0, } continue precisions = [c["precision"] for c in method_cases] recalls = [c["recall"] for c in method_cases] f1s = [c["f1"] for c in method_cases] sp_scores = [c["sp_score"] for c in method_cases] align_times = [c["wall_time_align"] for c in method_cases] hyphy_times = [c["wall_time_hyphy"] for c in method_cases] mean_f1 = sum(f1s) / n mean_precision = sum(precisions) / n mean_recall = sum(recalls) / n mean_sp = sum(sp_scores) / n entry: dict[str, Any] = { "n_cases": n, "mean_precision": mean_precision, "mean_recall": mean_recall, "mean_f1": mean_f1, "mean_sp_score": mean_sp, "mean_wall_time_align": sum(align_times) / n, "mean_wall_time_hyphy": sum(hyphy_times) / n, } # Bootstrap CIs on F1 if we have enough cases if n >= 5: try: ci_low, ci_high = bootstrap_ci(f1s) entry["f1_ci_lower"] = ci_low entry["f1_ci_upper"] = ci_high except Exception: pass summary[method] = entry return summary # --------------------------------------------------------------------------- # Main pipeline # --------------------------------------------------------------------------- # Default methods for positive-selection pipeline (subset of all methods) _DEFAULT_METHODS = [ "kalign", "kalign_cons", "kalign_ens3", "mafft", "muscle", "clustalo", "true", ] _FULL_METHODS = [ "kalign", "kalign_cons", "kalign_ens3", "mafft", "muscle", "clustalo", "true", ] def run_pipeline(params: dict) -> SelectionResult: """Run the positive-selection analysis pipeline. Parameters ---------- params : dict Configuration with keys: - ``data_dir`` : str or Path -- directory for simulation data / scratch - ``results_dir`` : str or Path -- directory for output JSONs - ``methods`` : list[str] -- alignment methods to test - ``n_jobs`` : int -- parallel workers (default 1) - ``quick`` : bool -- if True, run only 5 simulations (default False) - ``threshold`` : float -- FUBAR posterior threshold (default 0.9) - ``max_sims`` : int or None -- max simulations to run Returns ------- SelectionResult """ from .provenance import collect_provenance, result_path, update_latest_symlink from .simulation import ( CODON_GRID, CODON_GRID_FULL, SimulationGrid, generate_indelible_dataset, iter_simulation_params, random_birth_death_tree, ) from .utils import tool_versions_fingerprint data_dir = Path(params.get("data_dir", "benchmarks/data")) results_dir = Path(params.get("results_dir", "benchmarks/results")) full = params.get("full", False) methods = params.get("methods", _FULL_METHODS if full else _DEFAULT_METHODS) n_jobs = params.get("n_jobs", 1) quick = params.get("quick", False) threshold = params.get("threshold", 0.9) max_sims = params.get("max_sims", None) data_dir.mkdir(parents=True, exist_ok=True) logger.info("Positive selection pipeline starting") logger.info("Methods: %s", methods) logger.info("Quick mode: %s", quick) # Build the simulation parameter grid if quick: # Minimal grid for smoke-testing: fewer taxa, depths, reps grid = SimulationGrid( n_taxa=[8], tree_depths=[0.7], indel_rates=[0.05], psel_fractions=[0.0, 0.10], replicates=3, n_codons=200, ) else: grid = CODON_GRID_FULL if full else CODON_GRID # Collect simulation parameter sets sim_params_list = list(iter_simulation_params(grid, model="M8")) if max_sims is not None: sim_params_list = sim_params_list[:max_sims] if quick and len(sim_params_list) > 5: sim_params_list = sim_params_list[:5] # Compute fingerprint once for all workers (None disables caching) if params.get("no_cache"): fingerprint = None logger.info("Caching disabled (--no-cache)") else: fingerprint = tool_versions_fingerprint() logger.info("Tool versions fingerprint: %s", fingerprint) # Step 1: Generate simulated datasets sequentially (avoids race conditions) from tqdm import tqdm sim_datasets = [] for sp in tqdm(sim_params_list, desc="Generating codon simulations", unit="sim"): sim_id = sp["sim_id"] sim_dir = data_dir / sim_id tree = random_birth_death_tree( n_taxa=sp["n_taxa"], target_depth=sp["target_depth"], seed=sp.get("seed", 42), ) sim_dataset = generate_indelible_dataset( tree=tree, model=sp["model"], seq_length=sp["seq_length"], indel_rate=sp["indel_rate"], indel_length_mean=sp.get("indel_length_mean", 2.0), output_dir=sim_dir, seed=sp.get("seed", 42), psel_fraction=sp.get("psel_fraction", 0.0), omega_positive=sp.get("omega_positive", 3.0), kappa=sp.get("kappa", 2.0), ) sim_dataset.params["sim_id"] = sim_id sim_datasets.append(sim_dataset) logger.info( "Running %d simulations x %d methods = %d total cases", len(sim_datasets), len(methods), len(sim_datasets) * len(methods), ) # Step 2: Build work items for alignment + scoring work_items = [] for sim_dataset in sim_datasets: sim_id = sim_dataset.params["sim_id"] sim_dir = data_dir / sim_id for method_name in methods: work_dir = sim_dir / f"work_{method_name}" work_items.append( { "sim_dataset": sim_dataset, "method_name": method_name, "work_dir": str(work_dir), "threshold": threshold, "fingerprint": fingerprint, } ) # Step 3: Execute (parallel or serial) cases: list[dict] = [] pbar = tqdm(total=len(work_items), desc="Positive selection", unit="case") if n_jobs > 1: with ProcessPoolExecutor(max_workers=n_jobs) as pool: futures = {pool.submit(_run_one, item): item for item in work_items} for future in as_completed(futures): try: result = future.result() cases.append(result) except Exception as exc: item = futures[future] logger.error("Worker failed: %s", exc) cases.append( { "sim_id": item["sim_dataset"].params.get("sim_id", "unknown"), "method": item["method_name"], "error": str(exc), } ) pbar.update(1) else: for item in work_items: result = _run_one(item) cases.append(result) pbar.update(1) pbar.close() # Filter out errors for summary successful = [c for c in cases if "error" not in c] error_count = len(cases) - len(successful) if error_count > 0: logger.warning("%d / %d cases had errors", error_count, len(cases)) # Aggregate summary summary = _aggregate_summary(cases, methods) # Statistical tests: wilcoxon between kalign_ens3 and each other method stats_tests = _compute_statistical_tests(cases, methods) if stats_tests: summary["statistical_tests"] = stats_tests # Collect provenance provenance = collect_provenance( parameters={ "pipeline": "positive_selection", "n_simulations": len(sim_datasets), "methods": methods, "n_jobs": n_jobs, "quick": quick, "threshold": threshold, "max_sims": max_sims, } ) # Build result sel_result = SelectionResult( provenance=asdict(provenance), cases=cases, summary=summary, ) # Save JSON out_path = result_path(results_dir, "positive_selection") with open(out_path, "w") as fh: json.dump(asdict(sel_result), fh, indent=2, default=str) update_latest_symlink(out_path) logger.info("Results saved to %s", out_path) # Print summary table _print_summary(summary, methods) return sel_result def _compute_statistical_tests( cases: list[dict], methods: list[str] ) -> dict: """Run Wilcoxon signed-rank tests comparing kalign_ens3 to other methods.""" from .utils import holm_bonferroni, wilcoxon_paired baseline = "kalign_ens3" if baseline not in methods: return {} # Group F1 scores by sim_id for paired comparisons baseline_f1: dict[str, float] = {} for c in cases: if c.get("method") == baseline and "error" not in c: baseline_f1[c["sim_id"]] = c["f1"] if len(baseline_f1) < 5: logger.warning( "Too few baseline cases (%d) for statistical tests", len(baseline_f1) ) return {} comparisons = [m for m in methods if m != baseline] test_results: dict[str, dict] = {} raw_p_values: list[float] = [] comp_names: list[str] = [] for method in comparisons: method_f1: dict[str, float] = {} for c in cases: if c.get("method") == method and "error" not in c: method_f1[c["sim_id"]] = c["f1"] # Paired comparison: only use sim_ids present in both common_ids = sorted(set(baseline_f1.keys()) & set(method_f1.keys())) if len(common_ids) < 5: continue a = [baseline_f1[sid] for sid in common_ids] b = [method_f1[sid] for sid in common_ids] try: result = wilcoxon_paired(a, b) test_results[method] = { "n_pairs": len(common_ids), **result, } raw_p_values.append(result["p_value"]) comp_names.append(method) except Exception as exc: logger.warning("Wilcoxon test failed for %s: %s", method, exc) # Apply Holm-Bonferroni correction if raw_p_values: adjusted = holm_bonferroni(raw_p_values) for name, adj_p in zip(comp_names, adjusted): test_results[name]["p_value_adjusted"] = adj_p return test_results def _print_summary(summary: dict, methods: list[str]) -> None: """Print a summary table to the logger.""" logger.info("=" * 72) logger.info("Positive Selection Pipeline — Summary") logger.info("=" * 72) logger.info( "%-22s %6s %8s %8s %8s %8s", "Method", "N", "Prec", "Recall", "F1", "SP", ) logger.info("-" * 72) for m in methods: s = summary.get(m, {}) if s.get("n_cases", 0) == 0: logger.info("%-22s %6d %8s", m, 0, "no data") continue logger.info( "%-22s %6d %8.3f %8.3f %8.3f %8.3f", m, s["n_cases"], s["mean_precision"], s["mean_recall"], s["mean_f1"], s["mean_sp_score"], ) logger.info("=" * 72) # --------------------------------------------------------------------------- # Load results # --------------------------------------------------------------------------- def load_results(results_dir: Path) -> SelectionResult: """Load the latest positive-selection results from disk. Parameters ---------- results_dir : Path Top-level results directory (e.g. ``benchmarks/results``). Returns ------- SelectionResult """ from .provenance import load_latest_results data = load_latest_results(Path(results_dir) / "positive_selection") return SelectionResult( provenance=data.get("provenance", {}), cases=data.get("cases", []), summary=data.get("summary", {}), ) kalign-3.5.1/benchmarks/downstream/provenance.py000066400000000000000000000221321515023132300217720ustar00rootroot00000000000000"""Version collection, hardware info, and result file naming for reproducible benchmarks. Captures full provenance metadata (tool versions, hardware specs, git state) and provides deterministic file naming for benchmark result files. """ import json import os import platform import re import subprocess from dataclasses import asdict, dataclass, field from datetime import datetime, timezone from pathlib import Path from typing import Dict, Optional @dataclass class Provenance: """Full provenance record for a benchmark run.""" timestamp: str kalign_version: str kalign_commit: str container_image: Optional[str] hostname: str cpu_model: str cpu_cores: int ram_gb: float os_version: str python_version: str tool_versions: Dict[str, str] parameters: Dict[str, object] # --------------------------------------------------------------------------- # Tool version collection # --------------------------------------------------------------------------- # Each entry: (binary, args, regex to extract version string) _TOOL_VERSION_COMMANDS = { "kalign": ("kalign", ["-v"], r"(\d+\.\d+\.\d+\S*)"), "mafft": ("mafft", ["--version"], r"v?([\d.]+\S*)"), "muscle": ("muscle", ["--version"], r"([\d.]+\S*)"), "clustalo": ("clustalo", ["--version"], r"([\d.]+\S*)"), "hmmer": ("hmmbuild", ["-h"], r"HMMER\s+([\d.]+\S*)"), "iqtree": ("iqtree2", ["--version"], r"version\s+([\d.]+\S*)"), "hyphy": ("hyphy", ["--version"], r"([\d.]+\S*)"), "indelible": ("indelible", ["--help"], r"INDELible\s+[Vv]?([\d.]+\S*)"), "guidance2": ("guidance.pl", ["--version"], r"([\d.]+\S*)"), } def _run_version_command(binary: str, args: list, pattern: str) -> str: """Run a single version command, return parsed version or 'not found'.""" try: result = subprocess.run( [binary] + args, capture_output=True, text=True, timeout=5, ) # Some tools print version on stderr (e.g. mafft) combined = result.stdout + "\n" + result.stderr match = re.search(pattern, combined) if match: return match.group(1) # Command ran but regex didn't match -- return raw first line first_line = combined.strip().split("\n")[0].strip() return first_line if first_line else "unknown" except FileNotFoundError: return "not found" except subprocess.TimeoutExpired: return "timeout" except OSError: return "not found" def collect_tool_versions() -> Dict[str, str]: """Collect version strings for all known external tools. Tools that are not installed are reported as ``"not found"`` rather than raising an error, so callers can always serialise the result. """ versions: Dict[str, str] = {} for name, (binary, args, pattern) in _TOOL_VERSION_COMMANDS.items(): versions[name] = _run_version_command(binary, args, pattern) return versions # --------------------------------------------------------------------------- # Hardware / environment helpers # --------------------------------------------------------------------------- def _get_cpu_model() -> str: """Return a human-readable CPU model string (macOS + Linux).""" system = platform.system() if system == "Darwin": try: result = subprocess.run( ["sysctl", "-n", "machdep.cpu.brand_string"], capture_output=True, text=True, timeout=5, ) model = result.stdout.strip() if model: return model except (FileNotFoundError, subprocess.TimeoutExpired, OSError): pass elif system == "Linux": try: with open("/proc/cpuinfo") as fh: for line in fh: if line.startswith("model name"): return line.split(":", 1)[1].strip() except OSError: pass return platform.processor() or "unknown" def _get_ram_gb() -> float: """Return total physical RAM in GiB, rounded to one decimal.""" system = platform.system() if system == "Darwin": try: result = subprocess.run( ["sysctl", "-n", "hw.memsize"], capture_output=True, text=True, timeout=5, ) return round(int(result.stdout.strip()) / (1024 ** 3), 1) except (FileNotFoundError, subprocess.TimeoutExpired, OSError, ValueError): pass elif system == "Linux": try: with open("/proc/meminfo") as fh: for line in fh: if line.startswith("MemTotal"): kb = int(line.split()[1]) return round(kb / (1024 ** 2), 1) except (OSError, ValueError): pass return 0.0 def _get_kalign_version() -> str: """Return the installed kalign Python package version.""" try: import kalign as _kalign return getattr(_kalign, "__version__", "unknown") except ImportError: return "not installed" def _get_kalign_commit() -> str: """Return the short git commit hash of the kalign repo.""" try: result = subprocess.run( ["git", "rev-parse", "--short", "HEAD"], capture_output=True, text=True, timeout=5, cwd=Path(__file__).resolve().parents[2], # repo root ) if result.returncode == 0: return result.stdout.strip() except (FileNotFoundError, subprocess.TimeoutExpired, OSError): pass return "unknown" def _get_container_image() -> Optional[str]: """Detect container image from environment if running inside one.""" # Common env vars set by container runtimes / Dockerfiles for var in ("CONTAINER_IMAGE", "IMAGE_NAME"): value = os.environ.get(var) if value: return value # Check cgroup for docker/podman hints try: with open("/proc/1/cgroup") as fh: text = fh.read() if "docker" in text or "podman" in text or "containerd" in text: return "unknown-container" except OSError: pass return None # --------------------------------------------------------------------------- # Main provenance collector # --------------------------------------------------------------------------- def collect_provenance(parameters: dict) -> Provenance: """Collect all provenance information for the current environment. Parameters ---------- parameters : dict Benchmark-specific parameters to record (e.g. dataset name, number of threads, alignment options). """ now = datetime.now(timezone.utc) return Provenance( timestamp=now.strftime("%Y-%m-%dT%H:%M:%S%z"), kalign_version=_get_kalign_version(), kalign_commit=_get_kalign_commit(), container_image=_get_container_image(), hostname=platform.node(), cpu_model=_get_cpu_model(), cpu_cores=os.cpu_count() or 0, ram_gb=_get_ram_gb(), os_version=f"{platform.system()} {platform.release()}", python_version=platform.python_version(), tool_versions=collect_tool_versions(), parameters=parameters, ) # --------------------------------------------------------------------------- # Result file naming and symlink management # --------------------------------------------------------------------------- def result_path(results_dir: Path, pipeline: str) -> Path: """Generate a unique result file path. Returns a path of the form:: results_dir//run_YYYYMMDD_HHMMSS_.json The directory is created if it does not exist. """ now = datetime.now(timezone.utc) stamp = now.strftime("%Y%m%d_%H%M%S") commit = _get_kalign_commit() name = f"run_{stamp}_{commit}.json" out_dir = Path(results_dir) / pipeline out_dir.mkdir(parents=True, exist_ok=True) return out_dir / name def update_latest_symlink(result_file: Path) -> None: """Create or update a ``latest.json`` symlink next to *result_file*. The symlink points to *result_file* using a relative target so that the whole results tree can be moved without breaking the link. """ result_file = Path(result_file).resolve() link_path = result_file.parent / "latest.json" # Relative target so the symlink is portable target = result_file.name # Atomic replace: unlink then symlink (no rename for symlinks) try: link_path.unlink() except FileNotFoundError: pass link_path.symlink_to(target) def load_latest_results(results_dir: Path) -> dict: """Load the JSON data from the ``latest.json`` symlink. Parameters ---------- results_dir : Path Directory that contains the ``latest.json`` symlink (typically a pipeline sub-directory under the main results directory). Returns ------- dict Parsed JSON contents of the latest result file. Raises ------ FileNotFoundError If no ``latest.json`` symlink exists in *results_dir*. """ link_path = Path(results_dir) / "latest.json" with open(link_path) as fh: return json.load(fh) kalign-3.5.1/benchmarks/downstream/simulation.py000066400000000000000000000533501515023132300220240ustar00rootroot00000000000000"""INDELible sequence simulation and tree generation via dendropy. Provides utilities for generating simulated multiple sequence alignments with known true alignments, for benchmarking alignment accuracy. """ from __future__ import annotations import itertools import os import shutil import subprocess import tempfile from dataclasses import dataclass, field from pathlib import Path from typing import Iterator, List, Optional @dataclass class SimulatedDataset: """Result of a single INDELible simulation run.""" true_alignment: Path # FASTA with gaps (true alignment) unaligned: Path # FASTA without gaps (input for aligners) true_tree: Path # Newick file site_classes: List[int] # Per-site class (0=neutral, 1=positive selection) params: dict = field(default_factory=dict) # All simulation parameters # --------------------------------------------------------------------------- # Tree generation # --------------------------------------------------------------------------- def random_birth_death_tree( n_taxa: int, target_depth: float, seed: int = 42, ) -> str: """Generate a random birth-death tree with dendropy, scale to target depth. Uses ``dendropy.simulate.treesim.birth_death_tree()`` with birth_rate=1.0, death_rate=0.5. Then scales all branch lengths so the maximum root-to-tip distance equals *target_depth*. Returns a Newick string. """ import random from dendropy.simulate import treesim tree = treesim.birth_death_tree( birth_rate=1.0, death_rate=0.5, num_extant_tips=n_taxa, rng=random.Random(seed), ) # Compute the maximum root-to-tip distance. max_dist = 0.0 for leaf in tree.leaf_node_iter(): dist = leaf.distance_from_root() if dist > max_dist: max_dist = dist if max_dist > 0.0: scale_factor = target_depth / max_dist for edge in tree.preorder_edge_iter(): if edge.length is not None: edge.length *= scale_factor nwk = tree.as_string(schema="newick").strip() # Strip dendropy annotations like [&R] that INDELible doesn't understand, # and remove the root branch length (e.g. "...):0.5;" → "...);") # which INDELible rejects. import re nwk = re.sub(r"\[&[^\]]*\]", "", nwk).strip() nwk = re.sub(r"\):[0-9eE.+-]+;$", ");", nwk) # INDELible cannot parse scientific notation (e.g. 1.23e-10) in branch # lengths. Reformat all `:NUMBER` tokens to fixed-point decimal. def _fix_brlen(m: re.Match) -> str: return f":{float(m.group(1)):.10f}" nwk = re.sub(r":([0-9eE.+-]+)", _fix_brlen, nwk) return nwk # --------------------------------------------------------------------------- # INDELible control-file writers # --------------------------------------------------------------------------- def _write_codon_control( output_dir: Path, tree: str, n_codons: int = 400, kappa: float = 2.0, indel_rate: float = 0.05, psel_fraction: float = 0.0, omega_positive: float = 3.0, seed: int = 42, ) -> Path: """Write INDELible control file for codon simulation. If *psel_fraction* > 0, uses M1a (two dN/dS categories: purifying + positive selection). Otherwise uses M0 (single omega, purifying only). INDELible ``[submodel]`` parameter counts determine the codon model: - 2 params → M0: ``kappa omega`` - 4 params → M1a: ``kappa p0 omega0 omega1`` Returns the path to the written ``control.txt``. """ output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) # Build the model block. # Max indel length (in codons). Without a bound, INDELible's power-law # sampler can hang when indel_rate is high. max_indel_codons = 10 if psel_fraction > 0.0: # M1a: two categories — purifying + positive selection p0 = 1.0 - psel_fraction # proportion in purifying class omega_purifying = 0.2 model_block = ( f"[MODEL] simmodel\n" f" [submodel] {kappa} {p0} {omega_purifying} {omega_positive}\n" f" [indelmodel] POW 1.7 {max_indel_codons}\n" f" [indelrate] {indel_rate}\n" ) else: # M0: single omega (purifying only) omega_purifying = 0.2 model_block = ( f"[MODEL] simmodel\n" f" [submodel] {kappa} {omega_purifying}\n" f" [indelmodel] POW 1.7 {max_indel_codons}\n" f" [indelrate] {indel_rate}\n" ) control = ( f"[TYPE] CODON 1\n" f"\n" f"[SETTINGS]\n" f" [randomseed] {seed}\n" f" [printrates] TRUE\n" f"\n" f"{model_block}\n" f"[TREE] t1 {tree}\n" f"\n" f"[PARTITIONS] p1\n" f" [t1 simmodel {n_codons}]\n" f"\n" f"[EVOLVE] p1 1 output\n" ) control_path = output_dir / "control.txt" control_path.write_text(control) return control_path def _write_protein_control( output_dir: Path, tree: str, seq_length: int = 300, indel_rate: float = 0.05, indel_length_mean: float = 2.0, seed: int = 42, ) -> Path: """Write INDELible control file for protein simulation (WAG+G4). Returns the path to the written ``control.txt``. """ output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) # Max indel length is set from the mean; INDELible uses a power-law # distribution with an upper bound. max_indel_length = int(round(indel_length_mean * 5)) if max_indel_length < 1: max_indel_length = 1 control = ( f"[TYPE] AMINOACID 1\n" f"\n" f"[SETTINGS]\n" f" [randomseed] {seed}\n" f"\n" f"[MODEL] simmodel\n" f" [submodel] WAG\n" f" [rates] 0 0.5 4\n" f" [indelmodel] POW 1.7 {max_indel_length}\n" f" [indelrate] {indel_rate}\n" f"\n" f"[TREE] t1 {tree}\n" f"\n" f"[PARTITIONS] p1\n" f" [t1 simmodel {seq_length}]\n" f"\n" f"[EVOLVE] p1 1 output\n" ) control_path = output_dir / "control.txt" control_path.write_text(control) return control_path # --------------------------------------------------------------------------- # INDELible execution and output parsing # --------------------------------------------------------------------------- def _run_indelible(control_dir: Path) -> None: """Run INDELible in the given directory. Raises ``RuntimeError`` if the executable is not found or if it exits with a non-zero return code. """ indelible_bin = shutil.which("indelible") or shutil.which("INDELible") if indelible_bin is None: raise RuntimeError( "INDELible is not installed or not on PATH. " "Please install INDELible (http://abacus.gene.ucl.ac.uk/software/indelible/) " "and ensure the 'indelible' binary is accessible." ) try: result = subprocess.run( [indelible_bin, "control.txt"], cwd=str(control_dir), capture_output=True, text=True, timeout=120, ) except subprocess.TimeoutExpired: raise RuntimeError( f"INDELible timed out after 120s in {control_dir}" ) if result.returncode != 0: raise RuntimeError( f"INDELible failed (exit code {result.returncode}).\n" f"stdout:\n{result.stdout}\n" f"stderr:\n{result.stderr}" ) def _parse_indelible_output( output_dir: Path, ) -> tuple[list[str], list[str], list[str], list[str]]: """Parse INDELible output files. Returns ``(true_names, true_sequences_with_gaps, unaligned_names, unaligned_sequences)``. INDELible produces (original v1.03 naming / matsengrp fork naming): - ``output_TRUE_1.phy`` or ``output_TRUE.phy`` — true alignment (relaxed PHYLIP) - ``output_1.fas`` or ``output.fas`` — unaligned sequences (FASTA) """ output_dir = Path(output_dir) # -- Parse the true alignment (relaxed PHYLIP) -------------------------- # Handle both original INDELible naming (_1 suffix) and matsengrp fork (no suffix) true_phy = output_dir / "output_TRUE_1.phy" if not true_phy.exists(): true_phy = output_dir / "output_TRUE.phy" if not true_phy.exists(): raise FileNotFoundError( f"Expected INDELible true-alignment file not found: {output_dir}/output_TRUE{{_1,}}.phy" ) true_names: list[str] = [] true_seqs: list[str] = [] with open(true_phy) as fh: header = fh.readline().strip().split() # First line: "n_seqs seq_length" _n_seqs = int(header[0]) for line in fh: line = line.strip() if not line: continue parts = line.split(None, 1) if len(parts) == 2: true_names.append(parts[0]) true_seqs.append(parts[1].replace(" ", "")) # -- Parse the unaligned FASTA ------------------------------------------ unaln_fas = output_dir / "output_1.fas" if not unaln_fas.exists(): unaln_fas = output_dir / "output.fas" if not unaln_fas.exists(): raise FileNotFoundError( f"Expected INDELible unaligned FASTA file not found: {output_dir}/output{{_1,}}.fas" ) unaln_names: list[str] = [] unaln_seqs: list[str] = [] current_name: Optional[str] = None current_seq_parts: list[str] = [] with open(unaln_fas) as fh: for line in fh: line = line.rstrip("\n") if line.startswith(">"): if current_name is not None: unaln_names.append(current_name) unaln_seqs.append("".join(current_seq_parts)) current_name = line[1:].strip() current_seq_parts = [] else: current_seq_parts.append(line.strip()) # Last sequence if current_name is not None: unaln_names.append(current_name) unaln_seqs.append("".join(current_seq_parts)) return true_names, true_seqs, unaln_names, unaln_seqs def _parse_site_classes(output_dir: Path, n_codons: int) -> List[int]: """Parse site class assignments from INDELible rates output. Returns a list of ints: 0 = neutral, 1 = positive selection. If no rates file is found, returns a list of zeros. INDELible writes per-site rate information to ``output_1_RATES.txt`` when ``[printrates] TRUE`` is set. The file has columns: Site, Class, Rate (tab- or space-separated, with a header line). For M8, class index equal to the last class is the positive-selection class. """ rates_file = output_dir / "output_1_RATES.txt" if not rates_file.exists(): rates_file = output_dir / "output_RATES.txt" if not rates_file.exists(): return [0] * n_codons classes: list[int] = [] max_class = 0 with open(rates_file) as fh: for line in fh: line = line.strip() if not line or line.startswith("Site") or line.startswith("#"): continue parts = line.split() if len(parts) >= 2: try: cls = int(parts[1]) except ValueError: continue classes.append(cls) if cls > max_class: max_class = cls # In M8, the highest class index is the positive-selection class. # Map: highest class -> 1 (positive selection), everything else -> 0. if max_class == 0: # All neutral (M7 or single class) return [0] * len(classes) if classes else [0] * n_codons site_classes = [1 if c == max_class else 0 for c in classes] # Pad or truncate to n_codons (rates file should match, but be safe). if len(site_classes) < n_codons: site_classes.extend([0] * (n_codons - len(site_classes))) elif len(site_classes) > n_codons: site_classes = site_classes[:n_codons] return site_classes # --------------------------------------------------------------------------- # Helper: strip gaps # --------------------------------------------------------------------------- def strip_gaps(sequences: list[str]) -> list[str]: """Remove all gap characters from sequences.""" return [s.replace("-", "").replace(".", "") for s in sequences] # --------------------------------------------------------------------------- # FASTA I/O helpers # --------------------------------------------------------------------------- def _write_fasta(path: Path, names: list[str], sequences: list[str]) -> None: """Write sequences in FASTA format.""" with open(path, "w") as fh: for name, seq in zip(names, sequences): fh.write(f">{name}\n{seq}\n") # --------------------------------------------------------------------------- # Main simulation function # --------------------------------------------------------------------------- def generate_indelible_dataset( tree: str, model: str, seq_length: int, indel_rate: float, indel_length_mean: float = 2.0, output_dir: Optional[Path] = None, seed: int = 42, psel_fraction: float = 0.0, omega_positive: float = 3.0, kappa: float = 2.0, ) -> SimulatedDataset: """Generate a simulated dataset using INDELible. Parameters ---------- tree : str Newick tree string. model : str Substitution model: ``"WAG"``, ``"M7"``, or ``"M8"``. seq_length : int Number of sites (amino acids) or codons depending on model. indel_rate : float Insertion/deletion rate. indel_length_mean : float Mean indel length (protein models only). output_dir : Path or None Directory for output files. If *None*, a temporary directory is used. seed : int Random seed for reproducibility. psel_fraction : float Fraction of sites under positive selection (codon models only). omega_positive : float Omega for the positive-selection class (codon models only). kappa : float Transition/transversion ratio (codon models only). Returns ------- SimulatedDataset Paths to output files and simulation metadata. """ use_temp = output_dir is None if use_temp: tmpdir = tempfile.mkdtemp(prefix="indelible_") output_dir = Path(tmpdir) else: output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) # Store all params for provenance. params = dict( model=model, seq_length=seq_length, indel_rate=indel_rate, indel_length_mean=indel_length_mean, seed=seed, psel_fraction=psel_fraction, omega_positive=omega_positive, kappa=kappa, ) tree_path = output_dir / "tree.nwk" true_aln_path = output_dir / "true_alignment.fasta" unaligned_path = output_dir / "unaligned.fasta" # Skip INDELible if output files already exist (deterministic given params) if ( not use_temp and tree_path.exists() and true_aln_path.exists() and unaligned_path.exists() and true_aln_path.stat().st_size > 0 ): model_upper = model.upper() if model_upper in ("M7", "M8"): site_classes = _parse_site_classes(output_dir, seq_length) else: site_classes = [0] * seq_length return SimulatedDataset( true_alignment=true_aln_path, unaligned=unaligned_path, true_tree=tree_path, site_classes=site_classes, params=params, ) # Write the tree to a file for reference. tree_path.write_text(tree + "\n") # Write control file. model_upper = model.upper() if model_upper in ("M7", "M8"): effective_psel = psel_fraction if model_upper == "M8" else 0.0 _write_codon_control( output_dir=output_dir, tree=tree, n_codons=seq_length, kappa=kappa, indel_rate=indel_rate, psel_fraction=effective_psel, omega_positive=omega_positive, seed=seed, ) n_codons = seq_length elif model_upper == "WAG": _write_protein_control( output_dir=output_dir, tree=tree, seq_length=seq_length, indel_rate=indel_rate, indel_length_mean=indel_length_mean, seed=seed, ) n_codons = 0 else: raise ValueError(f"Unknown model: {model!r}. Expected 'WAG', 'M7', or 'M8'.") # Run INDELible. _run_indelible(output_dir) # Parse output. true_names, true_seqs, unaln_names, unaln_seqs = _parse_indelible_output( output_dir ) # Parse site classes (codon models only). if model_upper in ("M7", "M8"): site_classes = _parse_site_classes(output_dir, n_codons) else: site_classes = [0] * seq_length # Write FASTA outputs. true_aln_path = output_dir / "true_alignment.fasta" unaligned_path = output_dir / "unaligned.fasta" _write_fasta(true_aln_path, true_names, true_seqs) _write_fasta(unaligned_path, unaln_names, unaln_seqs) return SimulatedDataset( true_alignment=true_aln_path, unaligned=unaligned_path, true_tree=tree_path, site_classes=site_classes, params=params, ) # --------------------------------------------------------------------------- # Batch simulation: parameter grids # --------------------------------------------------------------------------- @dataclass class SimulationGrid: """Full factorial simulation parameter grid.""" n_taxa: List[int] tree_depths: List[float] indel_rates: List[float] replicates: int = 10 # Codon-specific psel_fractions: List[float] = field(default_factory=lambda: [0.0]) omega_positive: float = 3.0 kappa: float = 2.0 n_codons: int = 400 # Protein-specific seq_length: int = 300 indel_length_means: List[float] = field(default_factory=lambda: [2.0]) # -- Full grids (for final publication runs with --full) -------------------- CODON_GRID_FULL = SimulationGrid( n_taxa=[32, 64, 128], tree_depths=[0.5, 1.0, 2.0], indel_rates=[0.01, 0.05, 0.10], psel_fractions=[0.10, 0.20, 0.30], replicates=10, n_codons=400, ) PROTEIN_GRID_FULL = SimulationGrid( n_taxa=[16, 32, 64], tree_depths=[0.5, 1.0, 2.0, 4.0], indel_rates=[0.02, 0.05, 0.10, 0.20], indel_length_means=[2.0, 5.0], replicates=20, ) # -- Slim grids (default — faster iteration, still publication quality) ----- # Protein: 2×4×4×2×3 = 192 sims # Codon: 3×3×3×3×3 = 243 sims # # Codon grid rationale: FUBAR is a Bayesian site-level test that needs # sufficient taxa for statistical power (≥32) and enough sites under # selection (psel ≥ 0.10) to produce meaningful F1 scores. Previous # grid (n_taxa=[16,32,64], psel=[0.05,0.10,0.20]) yielded F1 < 0.09 # for ALL methods including the true alignment, indicating the test was # underpowered rather than aligners being poor. PROTEIN_GRID = SimulationGrid( n_taxa=[16, 32], tree_depths=[0.5, 1.0, 2.0, 4.0], indel_rates=[0.02, 0.05, 0.10, 0.20], indel_length_means=[2.0, 5.0], replicates=3, ) CODON_GRID = SimulationGrid( n_taxa=[32, 64, 128], tree_depths=[0.5, 1.0, 2.0], indel_rates=[0.01, 0.05, 0.10], psel_fractions=[0.10, 0.20, 0.30], replicates=3, n_codons=400, ) def iter_simulation_params(grid: SimulationGrid, model: str) -> Iterator[dict]: """Yield parameter dicts for each simulation in the grid. Each dict has keys matching :func:`generate_indelible_dataset` kwargs plus a ``sim_id`` string that uniquely identifies the parameter combination and replicate number. """ model_upper = model.upper() if model_upper == "WAG": # Protein grid: iterate over n_taxa x tree_depths x indel_rates # x indel_length_means x replicates combos = itertools.product( grid.n_taxa, grid.tree_depths, grid.indel_rates, grid.indel_length_means, range(grid.replicates), ) for n_taxa, depth, indel_rate, indel_len, rep in combos: sim_id = ( f"{model_upper}_t{n_taxa}_d{depth}_ir{indel_rate}" f"_il{indel_len}_r{rep}" ) yield dict( sim_id=sim_id, model=model_upper, n_taxa=n_taxa, target_depth=depth, seq_length=grid.seq_length, indel_rate=indel_rate, indel_length_mean=indel_len, seed=42 + rep, psel_fraction=0.0, omega_positive=grid.omega_positive, kappa=grid.kappa, ) elif model_upper in ("M7", "M8"): # Codon grid: iterate over n_taxa x tree_depths x indel_rates # x psel_fractions x replicates combos = itertools.product( grid.n_taxa, grid.tree_depths, grid.indel_rates, grid.psel_fractions, range(grid.replicates), ) for n_taxa, depth, indel_rate, psel_frac, rep in combos: sim_id = ( f"{model_upper}_t{n_taxa}_d{depth}_ir{indel_rate}" f"_ps{psel_frac}_r{rep}" ) yield dict( sim_id=sim_id, model=model_upper, n_taxa=n_taxa, target_depth=depth, seq_length=grid.n_codons, indel_rate=indel_rate, indel_length_mean=2.0, seed=42 + rep, psel_fraction=psel_frac, omega_positive=grid.omega_positive, kappa=grid.kappa, ) else: raise ValueError(f"Unknown model: {model!r}. Expected 'WAG', 'M7', or 'M8'.") kalign-3.5.1/benchmarks/downstream/utils.py000066400000000000000000000673111515023132300210020ustar00rootroot00000000000000"""Shared utilities for downstream benchmark pipelines. Provides alignment runners, scoring helpers, statistical tests, tree comparison wrappers, and consistent figure styling for the kalign downstream benchmarks. """ from __future__ import annotations import hashlib import json as _json import logging import os import resource import subprocess import tempfile import time from pathlib import Path from typing import NamedTuple, Optional logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- # Per-case caching helpers # --------------------------------------------------------------------------- def tool_versions_fingerprint() -> str: """Return a short hex fingerprint of all external tool versions. Calls :func:`~.provenance.collect_tool_versions` once and hashes the sorted result. The fingerprint changes whenever any tool is upgraded (or removed / added), causing cached results to be recomputed. """ from .provenance import collect_tool_versions versions = collect_tool_versions() blob = _json.dumps(versions, sort_keys=True).encode() return hashlib.sha256(blob).hexdigest()[:16] def cache_load(work_dir: Path, fingerprint: str) -> Optional[dict]: """Load a cached result from *work_dir* if the fingerprint matches. Returns the cached result dict, or ``None`` on cache miss (file missing, fingerprint mismatch, or corrupt JSON). """ cache_file = Path(work_dir) / "_cache.json" if not cache_file.exists(): return None try: with open(cache_file) as fh: data = _json.load(fh) if data.get("fingerprint") == fingerprint: return data["result"] except (OSError, ValueError, KeyError): pass return None def cache_save(work_dir: Path, fingerprint: str, result: dict) -> None: """Write a result dict to *work_dir/_cache.json* with the given fingerprint.""" cache_file = Path(work_dir) / "_cache.json" Path(work_dir).mkdir(parents=True, exist_ok=True) with open(cache_file, "w") as fh: _json.dump({"fingerprint": fingerprint, "result": result}, fh) def clean_work_dir(work_dir: Path) -> None: """Remove stale output files from *work_dir*, preserving ``_cache.json``. Called before re-running a case to prevent leftover files (e.g. IQ-TREE checkpoints, partial FASTA files) from interfering with fresh runs. """ work_dir = Path(work_dir) if not work_dir.is_dir(): return for item in work_dir.iterdir(): if item.name == "_cache.json": continue if item.is_dir(): import shutil shutil.rmtree(item, ignore_errors=True) else: item.unlink(missing_ok=True) # --------------------------------------------------------------------------- # AlignResult # --------------------------------------------------------------------------- class AlignResult(NamedTuple): """Result returned by every alignment runner.""" sequences: list[str] names: list[str] column_confidence: Optional[list[float]] residue_confidence: Optional[list[list[float]]] wall_time: float peak_memory_mb: float # --------------------------------------------------------------------------- # FASTA parser / writer helpers # --------------------------------------------------------------------------- def parse_fasta(path: Path) -> tuple[list[str], list[str]]: """Parse a FASTA file. Returns ------- names : list[str] Sequence names (everything after '>' up to the first whitespace). sequences : list[str] Corresponding sequences with no whitespace. """ names: list[str] = [] sequences: list[str] = [] current_seq: list[str] = [] with open(path) as fh: for line in fh: line = line.rstrip("\n\r") if line.startswith(">"): if current_seq: sequences.append("".join(current_seq)) current_seq = [] # Name is the first whitespace-delimited token after '>' names.append(line[1:].split()[0] if line[1:].strip() else "") else: current_seq.append(line.strip()) if current_seq: sequences.append("".join(current_seq)) return names, sequences def write_fasta(names: list[str], sequences: list[str], path: Path) -> None: """Write sequences to a FASTA file.""" with open(path, "w") as fh: for name, seq in zip(names, sequences): fh.write(f">{name}\n") # Wrap at 80 characters for i in range(0, len(seq), 80): fh.write(seq[i : i + 80] + "\n") # --------------------------------------------------------------------------- # Confidence masking # --------------------------------------------------------------------------- def mask_alignment_by_confidence( sequences: list[str], column_confidence: list[float], threshold: float, ) -> tuple[list[str], int]: """Remove alignment columns where confidence is below *threshold*. Parameters ---------- sequences : list[str] Aligned sequences (all same length). column_confidence : list[float] Per-column confidence values in [0, 1]. threshold : float Columns with confidence < threshold are removed. Returns ------- masked_sequences : list[str] Sequences with low-confidence columns stripped. n_columns_retained : int Number of columns that survived the filter. """ if not sequences: return [], 0 ncols = len(sequences[0]) keep = [j for j in range(ncols) if column_confidence[j] >= threshold] masked = ["".join(seq[j] for j in keep) for seq in sequences] return masked, len(keep) # --------------------------------------------------------------------------- # IQ-TREE site weights # --------------------------------------------------------------------------- def write_site_weights( column_confidence: list[float], output_path: Path, ) -> None: """Write an IQ-TREE ``-a`` site-weight file. The file contains one weight per line. Values are clamped to [0, 1]. """ with open(output_path, "w") as fh: for w in column_confidence: fh.write(f"{max(0.0, min(1.0, w)):.6f}\n") # --------------------------------------------------------------------------- # Alignment accuracy via kalign.compare # --------------------------------------------------------------------------- def alignment_accuracy( test_sequences: list[str], true_sequences: list[str], test_names: list[str], true_names: list[str], ) -> dict: """Compute SP and TC scores of *test* alignment vs *true* alignment. Writes both alignments to temporary FASTA files and calls ``kalign.compare_detailed``. If ``kalign.compare_detailed`` is not available, falls back to ``kalign.compare`` for SP only. If neither is available, returns sentinel values of -1. Returns ------- dict ``{"sp_score": float, "tc_score": float}`` """ try: import kalign as _kalign except ImportError: return {"sp_score": -1.0, "tc_score": -1.0} # Quick validation: need at least 2 non-empty sequences if len(test_sequences) < 2 or len(true_sequences) < 2: return {"sp_score": -1.0, "tc_score": -1.0} if not test_sequences[0] or not true_sequences[0]: return {"sp_score": -1.0, "tc_score": -1.0} with tempfile.TemporaryDirectory() as tmpdir: ref_path = os.path.join(tmpdir, "ref.fasta") test_path = os.path.join(tmpdir, "test.fasta") write_fasta(true_names, true_sequences, Path(ref_path)) write_fasta(test_names, test_sequences, Path(test_path)) # Verify files were written (guard against race / disk issues) if os.path.getsize(ref_path) == 0 or os.path.getsize(test_path) == 0: logger.warning("alignment_accuracy: empty FASTA written, skipping") return {"sp_score": -1.0, "tc_score": -1.0} try: if hasattr(_kalign, "compare_detailed"): d = _kalign.compare_detailed(ref_path, test_path, max_gap_frac=-1.0) return {"sp_score": d.get("recall", -1.0), "tc_score": d.get("tc", -1.0)} elif hasattr(_kalign, "compare"): sp = _kalign.compare(ref_path, test_path) return {"sp_score": sp, "tc_score": -1.0} else: return {"sp_score": -1.0, "tc_score": -1.0} except Exception as exc: logger.warning("alignment_accuracy failed: %s", exc) return {"sp_score": -1.0, "tc_score": -1.0} # --------------------------------------------------------------------------- # Tree comparison (dendropy) # --------------------------------------------------------------------------- def compare_trees(true_tree: str, inferred_tree: str) -> dict: """Compare two Newick tree strings. Uses ``dendropy.calculate.treecompare`` (imported lazily). Returns ------- dict ``{"nrf": float, "quartet_dist": float, "branch_score_dist": float}`` """ import dendropy from dendropy.calculate import treecompare tns = dendropy.TaxonNamespace() t1 = dendropy.Tree.get(data=true_tree, schema="newick", taxon_namespace=tns) t2 = dendropy.Tree.get(data=inferred_tree, schema="newick", taxon_namespace=tns) # Ensure the same leaf set t1.encode_bipartitions() t2.encode_bipartitions() nrf = treecompare.symmetric_difference(t1, t2) / (2 * (len(tns) - 3)) quartet_dist = treecompare.euclidean_distance(t1, t2) bsd = treecompare.weighted_robinson_foulds_distance(t1, t2) return { "nrf": nrf, "quartet_dist": quartet_dist, "branch_score_dist": bsd, } # --------------------------------------------------------------------------- # Statistical helpers # --------------------------------------------------------------------------- def bootstrap_ci( values: list[float], n_bootstrap: int = 10000, alpha: float = 0.05, ) -> tuple[float, float]: """Compute a bootstrap confidence interval for the mean. Parameters ---------- values : list[float] Observed values. n_bootstrap : int Number of bootstrap resamples. alpha : float Significance level (default 0.05 for a 95 % CI). Returns ------- (lower, upper) : tuple[float, float] """ import numpy as np arr = np.asarray(values, dtype=float) n = len(arr) rng = np.random.default_rng(seed=42) boot_means = np.empty(n_bootstrap) for i in range(n_bootstrap): sample = rng.choice(arr, size=n, replace=True) boot_means[i] = sample.mean() lower = float(np.percentile(boot_means, 100 * alpha / 2)) upper = float(np.percentile(boot_means, 100 * (1 - alpha / 2))) return lower, upper def wilcoxon_paired(a: list[float], b: list[float]) -> dict: """Wilcoxon signed-rank test with Cliff's delta effect size. Parameters ---------- a, b : list[float] Paired observations (same length). Returns ------- dict ``{"statistic": float, "p_value": float, "cliffs_delta": float}`` """ from scipy.stats import wilcoxon as _wilcoxon stat, pval = _wilcoxon(a, b) # Cliff's delta (non-parametric effect size) n = len(a) count = 0 for ai, bi in zip(a, b): if ai > bi: count += 1 elif ai < bi: count -= 1 cliffs_d = count / n return { "statistic": float(stat), "p_value": float(pval), "cliffs_delta": cliffs_d, } def holm_bonferroni(p_values: list[float]) -> list[float]: """Apply Holm-Bonferroni correction to a list of p-values. Returns adjusted p-values in the same order as the input. """ m = len(p_values) if m == 0: return [] # Sort indices by p-value indexed = sorted(enumerate(p_values), key=lambda x: x[1]) adjusted = [0.0] * m cummax = 0.0 for rank, (orig_idx, p) in enumerate(indexed): corrected = p * (m - rank) # Enforce monotonicity: adjusted value must be >= previous cummax = max(cummax, corrected) adjusted[orig_idx] = min(cummax, 1.0) return adjusted # --------------------------------------------------------------------------- # Method colours (for consistent figure styling) # --------------------------------------------------------------------------- METHOD_COLORS = { "kalign": "#1f77b4", # blue "kalign_cons": "#2ca02c", # green "kalign_ens3": "#ff7f0e", # orange "mafft": "#d62728", # red "muscle": "#9467bd", # purple "clustalo": "#7f7f7f", # grey "true": "#000000", # black (reference) } # --------------------------------------------------------------------------- # Internal helpers for runners # --------------------------------------------------------------------------- def _peak_mem_children_mb() -> float: """Return peak RSS (in MB) of child processes via getrusage. On macOS ``ru_maxrss`` is in bytes; on Linux it is in kilobytes. """ ru = resource.getrusage(resource.RUSAGE_CHILDREN) maxrss = ru.ru_maxrss import sys if sys.platform == "darwin": return maxrss / (1024 * 1024) return maxrss / 1024 def _parse_fasta_string(text: str) -> tuple[list[str], list[str]]: """Parse FASTA from a string. Returns (names, sequences).""" names: list[str] = [] sequences: list[str] = [] current: list[str] = [] for line in text.splitlines(): if line.startswith(">"): if current: sequences.append("".join(current)) current = [] names.append(line[1:].split()[0] if line[1:].strip() else "") else: current.append(line.strip()) if current: sequences.append("".join(current)) return names, sequences # --------------------------------------------------------------------------- # Alignment runners # --------------------------------------------------------------------------- def run_kalign( input_fasta: Path, ensemble: int = 0, seq_type: str = "auto", tgpo: float | None = None, terminal_dist_scale: float | None = None, refine: str | None = None, vsm_amax: float | None = None, realign: int | None = None, consistency: int | None = None, consistency_weight: float | None = None, ) -> AlignResult: """Run kalign via the Python API. Parameters ---------- input_fasta : Path Path to unaligned FASTA. ensemble : int Number of ensemble runs (0 = off). seq_type : str Sequence type passed to ``kalign.align_from_file``. Returns ------- AlignResult """ import kalign as _kalign start = time.perf_counter() extra = {} if tgpo is not None: extra["tgpo"] = tgpo if terminal_dist_scale is not None: extra["terminal_dist_scale"] = terminal_dist_scale if refine is not None: extra["refine"] = refine if vsm_amax is not None: extra["vsm_amax"] = vsm_amax if realign is not None: extra["realign"] = realign if consistency is not None: extra["consistency"] = consistency if consistency_weight is not None: extra["consistency_weight"] = consistency_weight result = _kalign.align_from_file( str(input_fasta), seq_type=seq_type, ensemble=ensemble, **extra, ) wall = time.perf_counter() - start # AlignedSequences supports unpacking and has .column_confidence etc. names = list(result.names) sequences = list(result.sequences) col_conf = result.column_confidence # may be None res_conf = result.residue_confidence # may be None ru = resource.getrusage(resource.RUSAGE_SELF) import sys if sys.platform == "darwin": mem_mb = ru.ru_maxrss / (1024 * 1024) else: mem_mb = ru.ru_maxrss / 1024 return AlignResult( sequences=sequences, names=names, column_confidence=col_conf, residue_confidence=res_conf, wall_time=wall, peak_memory_mb=mem_mb, ) def run_mafft(input_fasta: Path, timeout: int | None = None) -> AlignResult: """Run MAFFT (``mafft --auto``) via subprocess.""" start = time.perf_counter() proc = subprocess.run( ["mafft", "--auto", str(input_fasta)], capture_output=True, text=True, timeout=timeout, ) wall = time.perf_counter() - start mem_mb = _peak_mem_children_mb() if proc.returncode != 0: raise RuntimeError(f"mafft failed (exit {proc.returncode}): {proc.stderr}") names, sequences = _parse_fasta_string(proc.stdout) return AlignResult( sequences=sequences, names=names, column_confidence=None, residue_confidence=None, wall_time=wall, peak_memory_mb=mem_mb, ) def run_muscle(input_fasta: Path, timeout: int | None = None) -> AlignResult: """Run MUSCLE v5 (``muscle -align ... -output ...``) via subprocess.""" with tempfile.NamedTemporaryFile(suffix=".fasta", delete=False) as tmp: out_path = tmp.name try: start = time.perf_counter() proc = subprocess.run( ["muscle", "-align", str(input_fasta), "-output", out_path], capture_output=True, text=True, timeout=timeout, ) wall = time.perf_counter() - start mem_mb = _peak_mem_children_mb() if proc.returncode != 0: raise RuntimeError( f"muscle failed (exit {proc.returncode}): {proc.stderr}" ) names, sequences = parse_fasta(Path(out_path)) finally: if os.path.exists(out_path): os.unlink(out_path) return AlignResult( sequences=sequences, names=names, column_confidence=None, residue_confidence=None, wall_time=wall, peak_memory_mb=mem_mb, ) def run_clustalo(input_fasta: Path, timeout: int | None = None) -> AlignResult: """Run Clustal Omega (``clustalo -i ... -o ...``) via subprocess.""" with tempfile.NamedTemporaryFile(suffix=".fasta", delete=False) as tmp: out_path = tmp.name try: start = time.perf_counter() proc = subprocess.run( [ "clustalo", "-i", str(input_fasta), "-o", out_path, "--outfmt=fasta", "--force", ], capture_output=True, text=True, timeout=timeout, ) wall = time.perf_counter() - start mem_mb = _peak_mem_children_mb() if proc.returncode != 0: raise RuntimeError( f"clustalo failed (exit {proc.returncode}): {proc.stderr}" ) names, sequences = parse_fasta(Path(out_path)) finally: if os.path.exists(out_path): os.unlink(out_path) return AlignResult( sequences=sequences, names=names, column_confidence=None, residue_confidence=None, wall_time=wall, peak_memory_mb=mem_mb, ) def run_guidance2( input_fasta: Path, output_dir: Path, seq_type: str = "aa", n_bootstrap: int = 100, ) -> AlignResult: """Run GUIDANCE2 via the perl script. Expects ``guidance.pl`` to be on ``$PATH`` or pointed to by the ``GUIDANCE2_PATH`` environment variable. Parameters ---------- input_fasta : Path Unaligned FASTA input. output_dir : Path Working / output directory for GUIDANCE2 files. seq_type : str ``"aa"`` for protein, ``"nuc"`` for nucleotide (DNA/RNA). n_bootstrap : int Number of bootstrap guide-tree perturbations. Returns ------- AlignResult """ import shutil as _shutil guidance_bin = os.environ.get( "GUIDANCE2_PATH", _shutil.which("guidance2") or _shutil.which("guidance.pl") or "guidance.pl", ) output_dir = Path(output_dir).resolve() # Clean any stale output from previous runs — GUIDANCE2 may skip steps # or produce inconsistent results if old output files are present. if output_dir.exists(): _shutil.rmtree(output_dir) output_dir.mkdir(parents=True, exist_ok=True) input_fasta = Path(input_fasta).resolve() # GUIDANCE2 type flags g2_type = "aa" if seq_type in ("aa", "protein") else "nuc" cmd = [ "perl", guidance_bin, "--seqFile", str(input_fasta), "--msaProgram", "MAFFT", "--seqType", g2_type, "--outDir", str(output_dir), "--bootstraps", str(n_bootstrap), ] start = time.perf_counter() proc = subprocess.run(cmd, capture_output=True, text=True) wall = time.perf_counter() - start mem_mb = _peak_mem_children_mb() if proc.returncode != 0: raise RuntimeError( f"GUIDANCE2 failed (exit {proc.returncode}): {proc.stderr}" ) # Parse the base MSA msa_path = output_dir / "MSA.MAFFT.aln.With_Names" if not msa_path.exists(): # Fallback to the filtered alignment msa_path = output_dir / "MSA.MAFFT.Without_low_SP_Col.With_Names" if not msa_path.exists(): raise FileNotFoundError( f"GUIDANCE2 output alignment not found in {output_dir}" ) names, sequences = parse_fasta(msa_path) # Parse column confidence scores col_conf: Optional[list[float]] = None col_scores_path = output_dir / "MSA.MAFFT.Guidance2_col_col.scr" if col_scores_path.exists(): col_conf = _parse_guidance2_col_scores(col_scores_path, len(sequences[0])) # Parse residue confidence scores res_conf: Optional[list[list[float]]] = None res_scores_path = output_dir / "MSA.MAFFT.Guidance2_res_pair_res.scr" if res_scores_path.exists(): res_conf = _parse_guidance2_res_scores( res_scores_path, len(names), len(sequences[0]) ) return AlignResult( sequences=sequences, names=names, column_confidence=col_conf, residue_confidence=res_conf, wall_time=wall, peak_memory_mb=mem_mb, ) def _parse_guidance2_col_scores( path: Path, ncols: int ) -> list[float]: """Parse GUIDANCE2 per-column confidence file. The file has lines `` `` (1-based). """ scores = [0.0] * ncols with open(path) as fh: for line in fh: line = line.strip() if not line or line.startswith("#"): continue parts = line.split() if len(parts) >= 2: try: col = int(parts[0]) - 1 # 1-based to 0-based val = float(parts[1]) if 0 <= col < ncols: scores[col] = val except ValueError: continue return scores def _parse_guidance2_res_scores( path: Path, nseqs: int, ncols: int ) -> list[list[float]]: """Parse GUIDANCE2 per-residue confidence file. The file has lines `` `` (1-based). """ scores = [[0.0] * ncols for _ in range(nseqs)] with open(path) as fh: for line in fh: line = line.strip() if not line or line.startswith("#"): continue parts = line.split() if len(parts) >= 3: try: seq_i = int(parts[0]) - 1 col_j = int(parts[1]) - 1 val = float(parts[2]) if 0 <= seq_i < nseqs and 0 <= col_j < ncols: scores[seq_i][col_j] = val except ValueError: continue return scores # --------------------------------------------------------------------------- # METHODS registry # --------------------------------------------------------------------------- METHODS: dict[str, dict] = { "kalign": { "fn": run_kalign, "ensemble": 0, "mask": None, "vsm_amax": 2.0, }, "kalign_cons": { "fn": run_kalign, "ensemble": 0, "mask": None, "vsm_amax": 2.0, "consistency": 5, "consistency_weight": 2.0, }, "kalign_ens3": { "fn": run_kalign, "ensemble": 3, "mask": None, "vsm_amax": 2.0, "realign": 1, }, "mafft": {"fn": run_mafft, "mask": None}, "muscle": {"fn": run_muscle, "mask": None}, "clustalo": {"fn": run_clustalo, "mask": None}, "true": {"fn": None}, } # --------------------------------------------------------------------------- # High-level method dispatcher # --------------------------------------------------------------------------- def run_method( method_name: str, input_fasta: Path, work_dir: Path, seq_type: str = "auto", skip_masking: bool = False, timeout: int | None = None, ) -> AlignResult: """Run an alignment method by name. Looks up *method_name* in :data:`METHODS`, dispatches to the appropriate runner, and applies confidence masking or site-weight output when the method entry requests it. Parameters ---------- method_name : str Key into :data:`METHODS`. input_fasta : Path Unaligned FASTA file. work_dir : Path Scratch / output directory (used by GUIDANCE2 and for weight files). seq_type : str Sequence type hint (``"auto"``, ``"protein"``, ``"dna"``, etc.). Returns ------- AlignResult """ if method_name not in METHODS: raise ValueError( f"Unknown method {method_name!r}. " f"Available: {sorted(METHODS.keys())}" ) cfg = METHODS[method_name] fn = cfg["fn"] if fn is None: raise ValueError( f"Method {method_name!r} has no runner function (fn=None). " f"It must be handled specially by each pipeline." ) # -- dispatch to runner ------------------------------------------------ if fn is run_kalign: result = fn( input_fasta, ensemble=cfg.get("ensemble", 0), seq_type=seq_type, tgpo=cfg.get("tgpo"), terminal_dist_scale=cfg.get("terminal_dist_scale"), refine=cfg.get("refine"), vsm_amax=cfg.get("vsm_amax"), realign=cfg.get("realign"), consistency=cfg.get("consistency"), consistency_weight=cfg.get("consistency_weight"), ) elif fn is run_guidance2: g2_type = "nuc" if seq_type in ("dna", "rna") else "aa" g2_dir = Path(work_dir) / f"guidance2_{method_name}" result = fn( input_fasta, output_dir=g2_dir, seq_type=g2_type, n_bootstrap=cfg.get("n_bootstrap", 100), ) else: # mafft, muscle, clustalo -- simple signature result = fn(input_fasta, timeout=timeout) # -- optional site-weight output --------------------------------------- if cfg.get("weights") and result.column_confidence is not None: wt_path = Path(work_dir) / f"{method_name}_site_weights.txt" write_site_weights(result.column_confidence, wt_path) # -- optional confidence masking --------------------------------------- mask_threshold = cfg.get("mask") if not skip_masking and mask_threshold is not None and result.column_confidence is not None: masked_seqs, _n_kept = mask_alignment_by_confidence( result.sequences, result.column_confidence, mask_threshold ) result = AlignResult( sequences=masked_seqs, names=result.names, column_confidence=result.column_confidence, residue_confidence=result.residue_confidence, wall_time=result.wall_time, peak_memory_mb=result.peak_memory_mb, ) return result kalign-3.5.1/benchmarks/external_balibase.py000066400000000000000000000131521515023132300211150ustar00rootroot00000000000000"""Run external tools (mafft, muscle, clustalo) on BAliBASE inside container. Scores against references using kalign's compare_detailed with XML masks. Usage (inside container): python -m benchmarks.external_balibase """ import json import shutil import statistics import subprocess import tempfile import time from collections import defaultdict from pathlib import Path import kalign from .datasets import get_cases from .scoring import parse_balibase_xml def _run_external(tool, unaligned, output): """Run an external alignment tool.""" try: if tool == "mafft": with open(output, "w") as f: subprocess.run( ["mafft", "--auto", str(unaligned)], stdout=f, stderr=subprocess.PIPE, check=True, ) elif tool == "clustalo": subprocess.run( ["clustalo", "-i", str(unaligned), "-o", str(output), "--outfmt=fasta", "--force"], capture_output=True, check=True, ) elif tool == "muscle": subprocess.run( ["muscle", "-align", str(unaligned), "-output", str(output)], capture_output=True, check=True, ) return True except (subprocess.CalledProcessError, FileNotFoundError): return False def _score_case(case, output_path): xml_path = case.reference.with_suffix(".xml") if xml_path.exists(): mask = parse_balibase_xml(xml_path) return kalign.compare_detailed(str(case.reference), str(output_path), column_mask=mask) return kalign.compare_detailed(str(case.reference), str(output_path)) def main(): tools = [] for t in ["mafft", "muscle", "clustalo"]: if shutil.which(t): tools.append(t) else: print(f" {t}: not found, skipping") if not tools: print("No external tools found. Run inside container.") return print(f"Tools: {tools}") cases = get_cases("balibase") print(f"{len(cases)} BAliBASE cases") results = [] n_tasks = len(tools) * len(cases) done = 0 t0 = time.perf_counter() for tool in tools: print(f"\n Tool: {tool}", flush=True) for case in cases: with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as tmp: tmp_path = tmp.name try: t1 = time.perf_counter() ok = _run_external(tool, case.unaligned, tmp_path) wall = time.perf_counter() - t1 if ok: scores = _score_case(case, tmp_path) results.append({ "family": case.family, "dataset": case.dataset, "method": tool, "recall": scores["recall"], "precision": scores["precision"], "f1": scores["f1"], "tc": scores["tc"], "wall_time": wall, }) else: results.append({ "family": case.family, "dataset": case.dataset, "method": tool, "recall": 0, "precision": 0, "f1": 0, "tc": 0, "wall_time": 0, "error": f"{tool} failed", }) finally: Path(tmp_path).unlink(missing_ok=True) done += 1 if done % 20 == 0: elapsed = time.perf_counter() - t0 eta = elapsed / done * (n_tasks - done) print(f" {done}/{n_tasks} ({elapsed:.0f}s, ETA {eta:.0f}s)", flush=True) elapsed = time.perf_counter() - t0 print(f"\nAll done in {elapsed:.0f}s") # Summary groups = defaultdict(list) for r in results: groups[r["method"]].append(r) print(f"\n{'Method':>12} {'Recall':>8} {'Prec':>8} {'F1':>8} {'TC':>8} {'Time':>7}") print("-" * 60) for tool in tools: entries = [r for r in groups[tool] if "error" not in r] if not entries: print(f"{tool:>12} (no results)") continue rec = statistics.mean(r["recall"] for r in entries) prec = statistics.mean(r["precision"] for r in entries) f1 = statistics.mean(r["f1"] for r in entries) tc = statistics.mean(r["tc"] for r in entries) wt = sum(r["wall_time"] for r in entries) print(f"{tool:>12} {rec:>8.3f} {prec:>8.3f} {f1:>8.3f} {tc:>8.3f} {wt:>6.1f}s") # Per-category all_cats = sorted({r["dataset"].replace("balibase_", "") for r in results}) for cat in all_cats: cat_results = [r for r in results if cat in r["dataset"]] cat_groups = defaultdict(list) for r in cat_results: cat_groups[r["method"]].append(r) n = len(cat_groups.get(tools[0], [])) print(f"\n=== {cat} ({n} cases) ===") print(f"{'Method':>12} {'Recall':>8} {'Prec':>8} {'F1':>8} {'TC':>8}") print("-" * 50) for tool in tools: entries = [r for r in cat_groups.get(tool, []) if "error" not in r] if not entries: continue rec = statistics.mean(r["recall"] for r in entries) prec = statistics.mean(r["precision"] for r in entries) f1 = statistics.mean(r["f1"] for r in entries) tc = statistics.mean(r["tc"] for r in entries) print(f"{tool:>12} {rec:>8.3f} {prec:>8.3f} {f1:>8.3f} {tc:>8.3f}") out = Path("benchmarks/data/external_balibase.json") out.parent.mkdir(parents=True, exist_ok=True) json.dump(results, open(out, "w"), indent=2) print(f"\nSaved to {out}") if __name__ == "__main__": main() kalign-3.5.1/benchmarks/full_comparison.py000066400000000000000000000154721515023132300206540ustar00rootroot00000000000000"""Full BAliBASE comparison: all kalign modes + external tools (cached). Shows ALL metrics: SP(=Recall), Precision, F1, TC, Time — overall and per-category. """ import json import statistics import tempfile import time from collections import defaultdict from concurrent.futures import ProcessPoolExecutor, as_completed from pathlib import Path import kalign from benchmarks.datasets import get_cases from benchmarks.scoring import parse_balibase_xml def _score_case(case, output_path): xml_path = case.reference.with_suffix(".xml") if xml_path.exists(): mask = parse_balibase_xml(xml_path) return kalign.compare_detailed( str(case.reference), str(output_path), column_mask=mask ) return kalign.compare_detailed(str(case.reference), str(output_path)) def _run_one(args): case, config_name, kwargs = args with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as tmp: tmp_path = tmp.name try: t0 = time.perf_counter() kalign.align_file_to_file( str(case.unaligned), tmp_path, format="fasta", seq_type=case.seq_type, **kwargs, ) wall_time = time.perf_counter() - t0 scores = _score_case(case, tmp_path) return { "family": case.family, "dataset": case.dataset, "config": config_name, **scores, "wall_time": wall_time, } except Exception as e: return { "family": case.family, "dataset": case.dataset, "config": config_name, "error": str(e), } finally: Path(tmp_path).unlink(missing_ok=True) def _print_table(title, display_order, summary_data, configs): """Print one table with ALL metrics: SP, Prec, F1, TC, Time.""" print(f"\n{'=' * 100}") print(f" {title}") print(f"{'=' * 100}") print( f"{'Method':<24} {'SP':>8} {'Prec':>8} {'F1':>8} {'TC':>8}" f" {'Time':>8} {'N':>4}" ) print("-" * 100) for name in display_order: if name not in summary_data: continue sp, prec, f1, tc, t, n = summary_data[name] marker = " " if name in configs else "*" t_str = f"{t:.0f}s" if t is not None else "—" print( f"{marker}{name:<23} {sp:>8.3f} {prec:>8.3f} {f1:>8.3f}" f" {tc:>8.3f} {t_str:>8} {n:>4}" ) print("-" * 100) print(" SP = Sum-of-Pairs recall (BAliBASE convention)") print(" * = external tool (cached results)") def main(): cases = get_cases("balibase") print(f"BAliBASE: {len(cases)} cases\n") # Kalign configurations to test configs = { "baseline(vsm=0)": {"vsm_amax": 0.0}, "+vsm": {"vsm_amax": 2.0}, "+vsm+ref": {"vsm_amax": 2.0, "refine": "confident"}, "+vsm+ref+sw": { "vsm_amax": 2.0, "refine": "confident", "seq_weights": 1.0, }, "+vsm+ref+sw+c5": { "vsm_amax": 2.0, "refine": "confident", "seq_weights": 1.0, "consistency": 5, "consistency_weight": 2.0, }, "ens3+vsm": { "vsm_amax": 2.0, "ensemble": 3, }, "ens3+vsm+ref": { "vsm_amax": 2.0, "ensemble": 3, "refine": "confident", }, "ens3+vsm+ref+ra1": { "vsm_amax": 2.0, "ensemble": 3, "refine": "confident", "realign": 1, }, "ens3+vsm+ref+ra1+c5": { "vsm_amax": 2.0, "ensemble": 3, "refine": "confident", "realign": 1, "consistency": 5, "consistency_weight": 2.0, }, } tasks = [(c, name, kw) for c in cases for name, kw in configs.items()] print(f"{len(configs)} configs x {len(cases)} cases = {len(tasks)} tasks\n") results = [] done = 0 t0 = time.perf_counter() with ProcessPoolExecutor(max_workers=12) as pool: futures = {pool.submit(_run_one, t): t for t in tasks} for f in as_completed(futures): done += 1 r = f.result() results.append(r) if done % 200 == 0: elapsed = time.perf_counter() - t0 print(f" {done}/{len(tasks)} ({elapsed:.0f}s)") elapsed = time.perf_counter() - t0 print(f"\nKalign runs done in {elapsed:.0f}s\n") # Load cached external results ext_path = Path("benchmarks/data/external_balibase.json") if ext_path.exists(): ext_data = json.load(open(ext_path)) for r in ext_data: r["config"] = r.pop("method") results.extend(ext_data) ext_methods = set(r["config"] for r in ext_data) print(f"Loaded {len(ext_data)} cached external results: {ext_methods}\n") # Group by config groups = defaultdict(list) for r in results: if "error" not in r: groups[r["config"]].append(r) # Display order: kalign configs first, then external sorted display_order = list(configs.keys()) + sorted( k for k in groups if k not in configs ) # Compute overall summary: (sp, prec, f1, tc, total_time, count) overall = {} for name in display_order: entries = groups.get(name, []) if not entries: continue sp = statistics.mean(r["recall"] for r in entries) prec = statistics.mean(r["precision"] for r in entries) f1 = statistics.mean(r["f1"] for r in entries) tc = statistics.mean(r["tc"] for r in entries) t = sum(r["wall_time"] for r in entries) overall[name] = (sp, prec, f1, tc, t, len(entries)) # Print overall table _print_table("OVERALL (218 cases)", display_order, overall, configs) # Group results by category categories = ["RV11", "RV12", "RV20", "RV30", "RV40", "RV50"] by_cat = defaultdict(lambda: defaultdict(list)) for r in results: if "error" not in r: cat = r["dataset"].replace("balibase_", "") by_cat[cat][r["config"]].append(r) # Per-category tables — each with ALL metrics for cat in categories: cat_summary = {} for name in display_order: entries = by_cat[cat].get(name, []) if not entries: continue sp = statistics.mean(r["recall"] for r in entries) prec = statistics.mean(r["precision"] for r in entries) f1 = statistics.mean(r["f1"] for r in entries) tc = statistics.mean(r["tc"] for r in entries) t = sum(r["wall_time"] for r in entries) cat_summary[name] = (sp, prec, f1, tc, t, len(entries)) _print_table(f"{cat} ({len(by_cat[cat].get(display_order[0], []))} cases)", display_order, cat_summary, configs) if __name__ == "__main__": main() kalign-3.5.1/benchmarks/make_summary_figure.py000066400000000000000000000203301515023132300215000ustar00rootroot00000000000000#!/usr/bin/env python3 """Generate a summary figure from downstream benchmark results. Produces a 2x2 grid of line plots showing method performance vs difficulty, with the "true" alignment as a dashed black ceiling line. - Panel A: Phylo accuracy (nRF) vs tree_depth - Panel B: Positive selection (F1) vs n_taxa - Panel C: Alignment accuracy (SP) vs tree_depth - Panel D: Alignment accuracy (SP) vs indel_rate """ import json import re from collections import defaultdict from pathlib import Path import matplotlib.pyplot as plt import numpy as np RESULTS_DIR = Path("benchmarks/results") # Method display order (true last — rendered as dashed black) METHOD_ORDER = [ "kalign", "kalign_ens3", "mafft", "muscle", "clustalo", "true", ] METHOD_LABELS = { "kalign": "Kalign", "kalign_ens3": "Kalign ens3", "mafft": "MAFFT", "muscle": "MUSCLE", "clustalo": "Clustal Omega", "true": "True alignment", } METHOD_COLORS = { "kalign": "#1f77b4", "kalign_ens3": "#2ca02c", "mafft": "#9467bd", "muscle": "#8c564b", "clustalo": "#7f7f7f", "true": "#000000", } def load_cases(pipeline: str) -> list[dict]: """Load per-case results from the latest.json for a pipeline.""" path = RESULTS_DIR / pipeline / "latest.json" with open(path) as f: data = json.load(f) return data.get("cases", []) def parse_sim_id(sim_id: str) -> dict: """Extract parameters from a sim_id string. Examples: WAG_t16_d2.0_ir0.10_il2.0_r0 -> {model:WAG, n_taxa:16, tree_depth:2.0, ...} M8_t16_d0.5_ir0.05_ps0.10_r0 -> {model:M8, n_taxa:16, tree_depth:0.5, ...} """ params = {} m = re.match(r"^(\w+)_t(\d+)_d([\d.]+)_ir([\d.]+)", sim_id) if m: params["model"] = m.group(1) params["n_taxa"] = int(m.group(2)) params["tree_depth"] = float(m.group(3)) params["indel_rate"] = float(m.group(4)) # Protein: _il{mean}_r{rep} m_il = re.search(r"_il([\d.]+)", sim_id) if m_il: params["indel_length_mean"] = float(m_il.group(1)) # Codon: _ps{frac}_r{rep} m_ps = re.search(r"_ps([\d.]+)", sim_id) if m_ps: params["psel_fraction"] = float(m_ps.group(1)) m_r = re.search(r"_r(\d+)$", sim_id) if m_r: params["replicate"] = int(m_r.group(1)) return params def group_by(cases: list[dict], param_key: str, metric_key: str): """Group per-case results by a sim_id parameter. Returns {method: {x_value: [metric_values]}}. """ grouped = defaultdict(lambda: defaultdict(list)) for c in cases: if "error" in c: continue sim_params = parse_sim_id(c.get("sim_id", "")) if param_key not in sim_params: continue x_val = sim_params[param_key] method = c["method"] val = c.get(metric_key) if val is not None and not (isinstance(val, float) and np.isnan(val)): grouped[method][x_val].append(val) return grouped def style_ax(ax, hint=""): """Apply clean Nature-style aesthetics.""" ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) ax.tick_params(labelsize=9) if hint: ax.annotate( hint, xy=(0.98, 0.95), xycoords="axes fraction", ha="right", va="top", fontsize=8, fontstyle="italic", color="gray", ) def plot_lines(ax, grouped, methods, xlabel, ylabel): """Plot lines with error ribbons for each method. Parameters ---------- grouped : dict {method: {x_value: [metric_values]}} methods : list[str] Method names in plot order. """ for method in methods: if method not in grouped: continue data = grouped[method] xs = sorted(data.keys()) means = [] ses = [] for x in xs: vals = np.asarray(data[x], dtype=float) means.append(vals.mean()) ses.append(vals.std() / max(1, np.sqrt(len(vals)))) means = np.asarray(means) ses = np.asarray(ses) color = METHOD_COLORS.get(method, "#333333") label = METHOD_LABELS.get(method, method) linestyle = "--" if method == "true" else "-" linewidth = 1.5 if method != "true" else 2.0 marker = "o" if method != "true" else "" ax.plot( xs, means, color=color, linestyle=linestyle, linewidth=linewidth, marker=marker, markersize=4, label=label, zorder=3 if method != "true" else 2, ) ax.fill_between( xs, means - ses, means + ses, color=color, alpha=0.12, zorder=1, ) ax.set_xlabel(xlabel, fontsize=10) ax.set_ylabel(ylabel, fontsize=10) def main(): fig, axes = plt.subplots(2, 2, figsize=(14, 10)) fig.suptitle( "Kalign 3.5 — Downstream Benchmarks by Difficulty", fontsize=16, fontweight="bold", y=0.98, ) # Determine which methods are present in results available = set() for pipeline in ("phylo_accuracy", "positive_selection", "calibration"): try: cases = load_cases(pipeline) for c in cases: if "error" not in c: available.add(c["method"]) except FileNotFoundError: pass methods = [m for m in METHOD_ORDER if m in available] # ── Panel A: Phylo accuracy (nRF) vs tree_depth ────────────────── ax = axes[0, 0] try: cases = load_cases("phylo_accuracy") grouped = group_by(cases, "tree_depth", "nrf") plot_lines(ax, grouped, methods, "Tree depth", "Normalized RF distance") style_ax(ax, "lower = better") ax.set_title("A) Phylogenetic tree accuracy", fontweight="bold", loc="left", fontsize=11) except FileNotFoundError: ax.text(0.5, 0.5, "No phylo_accuracy results", transform=ax.transAxes, ha="center") style_ax(ax) # ── Panel B: Positive selection (F1) vs n_taxa ─────────────────── ax = axes[0, 1] try: cases = load_cases("positive_selection") grouped = group_by(cases, "n_taxa", "f1") plot_lines(ax, grouped, methods, "Number of taxa", "F1 score") style_ax(ax, "higher = better") ax.set_title("B) Positive selection detection (FUBAR)", fontweight="bold", loc="left", fontsize=11) except FileNotFoundError: ax.text(0.5, 0.5, "No positive_selection results", transform=ax.transAxes, ha="center") style_ax(ax) # ── Panel C: Alignment accuracy (SP) vs tree_depth ─────────────── ax = axes[1, 0] try: cases = load_cases("phylo_accuracy") grouped = group_by(cases, "tree_depth", "sp_score") plot_lines(ax, grouped, methods, "Tree depth", "SP score vs true alignment") style_ax(ax, "higher = better") ax.set_title("C) Alignment accuracy vs tree depth", fontweight="bold", loc="left", fontsize=11) except FileNotFoundError: ax.text(0.5, 0.5, "No phylo_accuracy results", transform=ax.transAxes, ha="center") style_ax(ax) # ── Panel D: Alignment accuracy (SP) vs indel_rate ─────────────── ax = axes[1, 1] try: cases = load_cases("phylo_accuracy") grouped = group_by(cases, "indel_rate", "sp_score") plot_lines(ax, grouped, methods, "Indel rate", "SP score vs true alignment") style_ax(ax, "higher = better") ax.set_title("D) Alignment accuracy vs indel rate", fontweight="bold", loc="left", fontsize=11) except FileNotFoundError: ax.text(0.5, 0.5, "No phylo_accuracy results", transform=ax.transAxes, ha="center") style_ax(ax) # Add legend (shared across panels) handles, labels = axes[0, 0].get_legend_handles_labels() if handles: fig.legend( handles, labels, loc="lower center", ncol=min(len(handles), 7), fontsize=9, frameon=False, bbox_to_anchor=(0.5, 0.0), ) plt.tight_layout(rect=[0, 0.04, 1, 0.95]) out = Path("benchmarks/figures/downstream_summary.png") out.parent.mkdir(parents=True, exist_ok=True) fig.savefig(out, dpi=200, bbox_inches="tight", facecolor="white") print(f"Saved to {out}") plt.close() if __name__ == "__main__": main() kalign-3.5.1/benchmarks/mumsa_plots.py000066400000000000000000000166371515023132300200270ustar00rootroot00000000000000"""Generate publication figures for MUMSA consensus precision analysis. Reads results from benchmarks/results/mumsa_precision.json (produced by mumsa_precision.py) and generates two figures: Figure 1: Precision-recall tradeoff curve showing consensus support thresholds vs single-tool baselines. Figure 2: Per-category precision bar chart at selected thresholds alongside external tools. Usage: python -m benchmarks.mumsa_plots [--output-dir figures/] Only requires matplotlib + json (no kalign dependency). """ import argparse import json import statistics from collections import defaultdict from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt # Consistent colours COLORS = { "consensus": "#2166ac", "kalign_baseline": "#888888", "ensemble": "#4daf4a", "mafft": "#e41a1c", "muscle": "#ff7f00", "clustalo": "#984ea3", } TOOL_LABELS = { "kalign_baseline": "kalign", "ensemble": "kalign ensemble", "mafft": "MAFFT", "muscle": "MUSCLE", "clustalo": "Clustal Omega", } def load_results(json_path): data = json.load(open(json_path)) return data["results"], data.get("n_runs", 8) def aggregate(results, group_key="method"): """Group results by method, return {method: {metric: mean_value}}.""" groups = defaultdict(list) for r in results: groups[r[group_key]].append(r) agg = {} for method, entries in groups.items(): agg[method] = { "recall": statistics.mean(e["recall"] for e in entries), "precision": statistics.mean(e["precision"] for e in entries), "f1": statistics.mean(e["f1"] for e in entries), "tc": statistics.mean(e["tc"] for e in entries), "n": len(entries), } return agg def aggregate_by_category(results): """Group results by (category, method).""" groups = defaultdict(list) for r in results: cat = r["dataset"].replace("balibase_", "") groups[(cat, r["method"])].append(r) agg = {} for (cat, method), entries in groups.items(): agg[(cat, method)] = { "recall": statistics.mean(e["recall"] for e in entries), "precision": statistics.mean(e["precision"] for e in entries), "f1": statistics.mean(e["f1"] for e in entries), "tc": statistics.mean(e["tc"] for e in entries), "n": len(entries), } return agg def figure_precision_vs_support(results, n_runs, output_path): """Precision and recall as a function of consensus support threshold, with horizontal reference lines for external tools and kalign baseline.""" agg = aggregate(results) fig, ax = plt.subplots(figsize=(6, 4.5)) # Consensus curves consensus_methods = sorted( [m for m in agg if m.startswith("consensus_ms")], key=lambda m: int(m.replace("consensus_ms", "")) ) support_vals = [int(m.replace("consensus_ms", "")) for m in consensus_methods] prec = [agg[m]["precision"] for m in consensus_methods] rec = [agg[m]["recall"] for m in consensus_methods] ax.plot(support_vals, prec, "o-", color=COLORS["consensus"], linewidth=2.5, markersize=7, zorder=5, label="Consensus precision") ax.plot(support_vals, rec, "s--", color=COLORS["consensus"], linewidth=1.5, markersize=5, alpha=0.5, zorder=4, label="Consensus recall") # Reference lines for external tools and baselines (precision only) ref_methods = [ ("kalign_baseline", COLORS["kalign_baseline"], "kalign"), ("ensemble", COLORS["ensemble"], "kalign ensemble"), ("mafft", COLORS["mafft"], "MAFFT"), ("muscle", COLORS["muscle"], "MUSCLE"), ("clustalo", COLORS["clustalo"], "Clustal Omega"), ] for method, color, label in ref_methods: if method in agg: ax.axhline(agg[method]["precision"], color=color, linestyle=":", linewidth=1.5, alpha=0.8, label=f"{label} precision") ax.set_xlabel("Minimum support threshold (s)", fontsize=11) ax.set_ylabel("Score", fontsize=11) ax.set_title("Consensus precision increases with support threshold", fontsize=11) ax.set_xticks(support_vals) ax.legend(fontsize=7.5, loc="center left", bbox_to_anchor=(1.02, 0.5), framealpha=0.9) ax.set_ylim(0.35, 1.0) ax.grid(True, alpha=0.3) fig.tight_layout() fig.savefig(output_path, dpi=300, bbox_inches="tight") plt.close(fig) print(f"Saved {output_path}") def figure_precision_by_category(results, n_runs, output_path): """Per-category grouped bar chart of precision at selected thresholds.""" agg = aggregate_by_category(results) categories = sorted({r["dataset"].replace("balibase_", "") for r in results}) # Methods to show: baseline, ms=3, ms=n_runs, ensemble, mafft, muscle, clustalo mid = max(1, n_runs // 2) bar_methods = [ ("kalign_baseline", "kalign", COLORS["kalign_baseline"]), (f"consensus_ms{mid}", f"consensus s={mid}", "#6baed6"), (f"consensus_ms{n_runs}", f"consensus s={n_runs}", COLORS["consensus"]), ("ensemble", "ensemble", COLORS["ensemble"]), ("mafft", "MAFFT", COLORS["mafft"]), ("muscle", "MUSCLE", COLORS["muscle"]), ("clustalo", "Clustal\u03a9", COLORS["clustalo"]), ] n_cats = len(categories) n_bars = len(bar_methods) bar_width = 0.11 x = range(n_cats) fig, ax = plt.subplots(figsize=(9, 4.5)) for bi, (method, label, color) in enumerate(bar_methods): vals = [] for cat in categories: key = (cat, method) vals.append(agg[key]["precision"] if key in agg else 0) offsets = [xi + (bi - n_bars / 2 + 0.5) * bar_width for xi in x] ax.bar(offsets, vals, bar_width, label=label, color=color, edgecolor="white", linewidth=0.3) ax.set_xlabel("BAliBASE category", fontsize=11) ax.set_ylabel("Precision", fontsize=11) ax.set_title("Precision by category and method", fontsize=11) ax.set_xticks(list(x)) ax.set_xticklabels(categories, fontsize=10) ax.legend(fontsize=7.5, ncol=4, loc="upper center", bbox_to_anchor=(0.5, -0.12), framealpha=0.9) ax.set_ylim(0, 1.05) ax.grid(True, axis="y", alpha=0.3) fig.tight_layout() fig.savefig(output_path, dpi=300, bbox_inches="tight") plt.close(fig) print(f"Saved {output_path}") def main(): parser = argparse.ArgumentParser( description="Generate MUMSA precision figures from saved results." ) parser.add_argument( "--input", default="benchmarks/results/mumsa_precision.json", help="Path to results JSON (default: benchmarks/results/mumsa_precision.json)" ) parser.add_argument( "--output-dir", default="benchmarks/figures", help="Directory for output figures (default: benchmarks/figures/)" ) parser.add_argument( "--format", default="pdf", choices=["pdf", "png", "svg"], help="Output format (default: pdf)" ) args = parser.parse_args() results, n_runs = load_results(args.input) out_dir = Path(args.output_dir) out_dir.mkdir(parents=True, exist_ok=True) figure_precision_vs_support( results, n_runs, out_dir / f"mumsa_precision_vs_support.{args.format}", ) figure_precision_by_category( results, n_runs, out_dir / f"mumsa_precision_by_category.{args.format}", ) if __name__ == "__main__": main() kalign-3.5.1/benchmarks/mumsa_precision.py000066400000000000000000000256541515023132300206600ustar00rootroot00000000000000"""Verify MUMSA claim: consensus alignments at higher support thresholds have higher precision (fraction of aligned residue pairs that are correct). Runs kalign ensemble_consensus at min_support = 1..N for each BAliBASE case, scores against references, and compares precision with baseline/external tools. """ import argparse import json import statistics import tempfile import time from collections import defaultdict from concurrent.futures import ProcessPoolExecutor, as_completed from pathlib import Path import kalign from .datasets import get_cases from .scoring import parse_balibase_xml def score_case(case, output_path): """Score a test alignment against the BAliBASE reference. Returns dict with recall, precision, f1, tc.""" xml_path = case.reference.with_suffix(".xml") if xml_path.exists(): mask = parse_balibase_xml(xml_path) return kalign.compare_detailed( str(case.reference), str(output_path), column_mask=mask ) return kalign.compare_detailed(str(case.reference), str(output_path)) def _run_one_case(case, n_runs, max_support): """Process a single BAliBASE case: run all support thresholds + baseline + ensemble. Returns list of result dicts.""" results = [] for ms in range(1, max_support + 1): with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as tmp: tmp_path = tmp.name try: kalign.align_file_to_file( str(case.unaligned), tmp_path, format="fasta", seq_type=case.seq_type, ensemble=n_runs, min_support=ms, ) scores = score_case(case, tmp_path) results.append({ "family": case.family, "dataset": case.dataset, "method": f"consensus_ms{ms}", "min_support": ms, "n_runs": n_runs, "recall": scores["recall"], "precision": scores["precision"], "f1": scores["f1"], "tc": scores["tc"], }) except Exception as e: results.append({ "family": case.family, "dataset": case.dataset, "method": f"consensus_ms{ms}", "min_support": ms, "n_runs": n_runs, "recall": 0, "precision": 0, "f1": 0, "tc": 0, "error": str(e), }) finally: Path(tmp_path).unlink(missing_ok=True) # Normal ensemble (no consensus) with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as tmp: tmp_path = tmp.name try: kalign.align_file_to_file( str(case.unaligned), tmp_path, format="fasta", seq_type=case.seq_type, ensemble=n_runs, ) scores = score_case(case, tmp_path) results.append({ "family": case.family, "dataset": case.dataset, "method": "ensemble", "min_support": 0, "n_runs": n_runs, "recall": scores["recall"], "precision": scores["precision"], "f1": scores["f1"], "tc": scores["tc"], }) except Exception: pass finally: Path(tmp_path).unlink(missing_ok=True) # Baseline kalign with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as tmp: tmp_path = tmp.name try: kalign.align_file_to_file( str(case.unaligned), tmp_path, format="fasta", seq_type=case.seq_type, ) scores = score_case(case, tmp_path) results.append({ "family": case.family, "dataset": case.dataset, "method": "kalign_baseline", "min_support": 0, "n_runs": 0, "recall": scores["recall"], "precision": scores["precision"], "f1": scores["f1"], "tc": scores["tc"], }) except Exception: pass finally: Path(tmp_path).unlink(missing_ok=True) return results def _worker(args): """Picklable worker for ProcessPoolExecutor.""" case, n_runs, max_support = args return _run_one_case(case, n_runs, max_support) def run_consensus_sweep(cases, n_runs=8, max_support=None, categories=None, parallel=1): """Run ensemble consensus at each support threshold for each case.""" if max_support is None: max_support = n_runs # Filter cases filtered = [] for case in cases: if categories and not any(cat in case.dataset.upper() for cat in categories): continue filtered.append(case) all_results = [] if parallel > 1: tasks = [(case, n_runs, max_support) for case in filtered] done = 0 with ProcessPoolExecutor(max_workers=parallel) as pool: futures = {pool.submit(_worker, t): t[0].family for t in tasks} for future in as_completed(futures): done += 1 fam = futures[future] try: results = future.result() all_results.extend(results) print(f" [{done}/{len(filtered)}] {fam} done") except Exception as e: print(f" [{done}/{len(filtered)}] {fam} FAILED: {e}") else: for ci, case in enumerate(filtered): print(f" [{ci+1}/{len(filtered)}] {case.family} ({case.dataset})", end="", flush=True) results = _run_one_case(case, n_runs, max_support) all_results.extend(results) print(" done") return all_results def load_external_scores(json_path="benchmarks/results/full_comparison.json"): """Load external tool scores (mafft, muscle, clustalo) from saved results.""" p = Path(json_path) if not p.exists(): return {} data = json.load(open(p)) ext = {} for r in data["results"]: if r["method"] in ("mafft", "muscle", "clustalo"): key = (r["family"], r["method"]) ext[key] = { "recall": r.get("recall", 0), "precision": r.get("precision", 0), "f1": r.get("f1", 0), "tc": r.get("tc", 0), } return ext def summarize(results, external_scores=None): """Print summary table of precision across support thresholds.""" by_method = defaultdict(list) by_method_cat = defaultdict(lambda: defaultdict(list)) for r in results: by_method[r["method"]].append(r) cat = r["dataset"].replace("balibase_", "") by_method_cat[r["method"]][cat].append(r) if external_scores: families = {r["family"] for r in results} family_datasets = {r["family"]: r["dataset"] for r in results} for tool in ("mafft", "muscle", "clustalo"): for fam in families: key = (fam, tool) if key in external_scores: s = external_scores[key] ds = family_datasets.get(fam, "") cat = ds.replace("balibase_", "") entry = {"family": fam, "dataset": ds, **s} by_method[tool].append(entry) by_method_cat[tool][cat].append(entry) def method_sort_key(m): if m == "kalign_baseline": return (0, 0) if m.startswith("consensus_ms"): return (1, int(m.replace("consensus_ms", ""))) if m == "ensemble": return (2, 0) return (3, {"mafft": 0, "muscle": 1, "clustalo": 2}.get(m, 9)) methods = sorted(by_method.keys(), key=method_sort_key) print("\n=== Overall (all categories) ===") print(f"{'Method':<22} {'Recall':>8} {'Precision':>10} {'F1':>8} {'TC':>8} N") print("-" * 70) for m in methods: entries = by_method[m] n = len(entries) rec = statistics.mean(r["recall"] for r in entries) prec = statistics.mean(r["precision"] for r in entries) f1 = statistics.mean(r["f1"] for r in entries) tc = statistics.mean(r["tc"] for r in entries) print(f"{m:<22} {rec:>8.3f} {prec:>10.3f} {f1:>8.3f} {tc:>8.3f} {n}") all_cats = sorted({r["dataset"].replace("balibase_", "") for r in results}) for cat in all_cats: print(f"\n=== {cat} ===") print(f"{'Method':<22} {'Recall':>8} {'Precision':>10} {'F1':>8} {'TC':>8} N") print("-" * 70) for m in methods: entries = by_method_cat[m].get(cat, []) if not entries: continue n = len(entries) rec = statistics.mean(r["recall"] for r in entries) prec = statistics.mean(r["precision"] for r in entries) f1 = statistics.mean(r["f1"] for r in entries) tc = statistics.mean(r["tc"] for r in entries) print(f"{m:<22} {rec:>8.3f} {prec:>10.3f} {f1:>8.3f} {tc:>8.3f} {n}") def main(): parser = argparse.ArgumentParser(description="MUMSA precision verification") parser.add_argument("--n-runs", type=int, default=8, help="Number of ensemble runs (default: 8)") parser.add_argument("--max-support", type=int, default=None, help="Maximum min_support threshold (default: n_runs)") parser.add_argument("--categories", nargs="*", default=None, help="BAliBASE categories to test (e.g. RV11 RV12)") parser.add_argument("--max-cases", type=int, default=0, help="Limit number of cases (0 = all)") parser.add_argument("--parallel", "-j", type=int, default=4, help="Number of parallel workers (default: 4)") args = parser.parse_args() categories = [c.upper() for c in args.categories] if args.categories else None cases = get_cases("balibase", max_cases=args.max_cases if args.max_cases else None) print(f"Running MUMSA precision analysis on {len(cases)} BAliBASE cases") print(f"Ensemble runs: {args.n_runs}, max support: {args.max_support or args.n_runs}") print(f"Parallel workers: {args.parallel}") results = run_consensus_sweep( cases, n_runs=args.n_runs, max_support=args.max_support, categories=categories, parallel=args.parallel, ) external = load_external_scores() summarize(results, external) # Save results for plotting out_dir = Path("benchmarks/results") out_dir.mkdir(parents=True, exist_ok=True) out_path = out_dir / "mumsa_precision.json" # Merge external scores into a flat list alongside our results ext_list = [] if external: families = {r["family"] for r in results} family_datasets = {r["family"]: r["dataset"] for r in results} for tool in ("mafft", "muscle", "clustalo"): for fam in families: key = (fam, tool) if key in external: ext_list.append({ "family": fam, "dataset": family_datasets.get(fam, ""), "method": tool, "min_support": 0, "n_runs": 0, **external[key], }) json.dump({"results": results + ext_list, "n_runs": args.n_runs}, open(out_path, "w"), indent=2) print(f"\nResults saved to {out_path}") if __name__ == "__main__": main() kalign-3.5.1/benchmarks/runner.py000066400000000000000000000230441515023132300167630ustar00rootroot00000000000000"""Main benchmark orchestrator and CLI.""" import argparse import json import statistics import time from concurrent.futures import ProcessPoolExecutor, as_completed from pathlib import Path from typing import List, Optional from .datasets import download_dataset, get_cases, DATASETS from .scoring import AlignmentResult, EXTERNAL_TOOLS, run_case def _run_one(args): """Worker function for parallel execution.""" case, method, binary, n_threads, refine, adaptive_budget, ensemble = args return run_case(case, method=method, binary=binary, n_threads=n_threads, refine=refine, adaptive_budget=adaptive_budget, ensemble=ensemble) def _result_label(r) -> str: """Format a concise label showing method and config for verbose output.""" if r.method in EXTERNAL_TOOLS: return r.method parts = ["kalign"] if r.refine != "none": parts.append(f"refine={r.refine}") if r.ensemble: parts.append(f"ens={r.ensemble}") return " ".join(parts) def run_benchmark( dataset: str = "balibase", methods: Optional[List[str]] = None, refine_modes: Optional[List[str]] = None, max_cases: int = 0, binary: str = "kalign", n_threads: int = 1, verbose: bool = False, adaptive_budget: bool = False, ensemble: int = 0, parallel: int = 1, ) -> List[AlignmentResult]: """Run benchmark suite and return results.""" if methods is None: methods = ["python_api"] if refine_modes is None: refine_modes = ["none"] cases = get_cases(dataset, max_cases=max_cases if max_cases > 0 else None) if not cases: print(f"No benchmark cases found for dataset '{dataset}'.") print("Try running with --download-only first.") return [] print(f"Running {len(cases)} cases from '{dataset}' with methods: {methods}, refine: {refine_modes}") if parallel > 1: print(f"Using {parallel} parallel workers") print() # Build work items work = [] for case in cases: for method in methods: if method in EXTERNAL_TOOLS: # External tools don't support refine/ensemble — run once work.append((case, method, binary, n_threads, "none", False, 0)) else: for refine in refine_modes: work.append((case, method, binary, n_threads, refine, adaptive_budget, ensemble)) total = len(work) if parallel <= 1: # Sequential (original behavior) results = [] for i, item in enumerate(work): result = _run_one(item) results.append(result) if verbose: label = _result_label(result) if result.error: print(f"[{i+1}/{total}] {result.family:<12} {label:<25} ERROR: {result.error}") else: print(f"[{i+1}/{total}] {result.family:<12} {label:<25} SP={result.recall:.3f} TC={result.tc:.3f} F1={result.f1:.3f} {result.wall_time:.1f}s") else: # Parallel execution results = [None] * total done = 0 with ProcessPoolExecutor(max_workers=parallel) as pool: futures = {pool.submit(_run_one, item): i for i, item in enumerate(work)} for future in as_completed(futures): idx = futures[future] result = future.result() results[idx] = result done += 1 if verbose: label = _result_label(result) if result.error: print(f"[{done}/{total}] {result.family:<12} {label:<25} ERROR: {result.error}") else: print(f"[{done}/{total}] {result.family:<12} {label:<25} SP={result.recall:.3f} TC={result.tc:.3f} F1={result.f1:.3f} {result.wall_time:.1f}s") return results def print_summary(results: List[AlignmentResult]) -> None: """Print aggregate summary of benchmark results.""" by_group = {} for r in results: if r.error: continue ens = f" ensemble={r.ensemble}" if r.ensemble else "" key = f"{r.method} refine={r.refine}{ens}" by_group.setdefault(key, []).append(r) for group, group_results in sorted(by_group.items()): recalls = [r.recall for r in group_results] precisions = [r.precision for r in group_results] f1s = [r.f1 for r in group_results] tcs = [r.tc for r in group_results] times = [r.wall_time for r in group_results] print(f"\n--- {group} ({len(group_results)} cases) ---") print(f" SP: mean={statistics.mean(recalls):.3f} " f"median={statistics.median(recalls):.3f} " f"min={min(recalls):.3f} max={max(recalls):.3f}") print(f" TC: mean={statistics.mean(tcs):.3f} " f"median={statistics.median(tcs):.3f}") print(f" Precision: mean={statistics.mean(precisions):.3f} " f"median={statistics.median(precisions):.3f}") print(f" F1: mean={statistics.mean(f1s):.3f} " f"median={statistics.median(f1s):.3f}") print(f" Time (s): total={sum(times):.1f} " f"mean={statistics.mean(times):.2f} " f"max={max(times):.2f}") errors = [r for r in results if r.error] if errors: print(f"\n{len(errors)} error(s):") for r in errors: print(f" {r.family} ({r.method} refine={r.refine}): {r.error}") def save_results(results: List[AlignmentResult], path: str) -> None: """Save results as JSON.""" data = { "timestamp": time.strftime("%Y-%m-%dT%H:%M:%S"), "results": [r.to_dict() for r in results], "summary": {}, } by_group = {} for r in results: if r.error: continue ens = f"_ensemble={r.ensemble}" if r.ensemble else "" key = f"{r.method}_refine={r.refine}{ens}" by_group.setdefault(key, []).append(r) for group, group_results in by_group.items(): scores = [r.sp_score for r in group_results] recalls = [r.recall for r in group_results] precisions = [r.precision for r in group_results] f1s = [r.f1 for r in group_results] tcs = [r.tc for r in group_results] data["summary"][group] = { "n_cases": len(group_results), "sp_mean": statistics.mean(scores), "sp_median": statistics.median(scores), "sp_min": min(scores), "sp_max": max(scores), "recall_mean": statistics.mean(recalls), "precision_mean": statistics.mean(precisions), "f1_mean": statistics.mean(f1s), "tc_mean": statistics.mean(tcs), "total_time": sum(r.wall_time for r in group_results), } Path(path).parent.mkdir(parents=True, exist_ok=True) with open(path, "w") as f: json.dump(data, f, indent=2) print(f"\nResults saved to {path}") def main() -> None: parser = argparse.ArgumentParser( description="Kalign alignment benchmark suite", prog="python -m benchmarks", ) parser.add_argument( "--dataset", default="balibase", choices=list(DATASETS.keys()) + ["all"], help="Which dataset to benchmark (default: balibase)", ) parser.add_argument( "--method", nargs="+", default=["python_api"], choices=["python_api", "cli", "clustalo", "mafft", "muscle"], help="Alignment method(s) to test (default: python_api)", ) parser.add_argument( "--max-cases", type=int, default=0, help="Limit number of test cases (0 = all)", ) parser.add_argument( "--binary", default="build/src/kalign", help="Path to C-compiled kalign binary for CLI method (default: build/src/kalign)", ) parser.add_argument( "--refine", nargs="+", default=["none"], choices=["none", "all", "confident"], help="Refinement mode(s) to test (default: none)", ) parser.add_argument( "--threads", type=int, default=1, help="Number of threads per alignment (default: 1)", ) parser.add_argument( "--output", default="", help="Output JSON file for results", ) parser.add_argument( "--adaptive-budget", action="store_true", help="Scale trial count by uncertainty", ) parser.add_argument( "--ensemble", type=int, default=0, help="Number of ensemble runs (0 = off)", ) parser.add_argument( "-j", "--parallel", type=int, default=1, help="Number of parallel workers for benchmark cases (default: 1)", ) parser.add_argument( "--download-only", action="store_true", help="Only download datasets, don't run benchmarks", ) parser.add_argument( "-v", "--verbose", action="store_true", help="Verbose output", ) args = parser.parse_args() if args.download_only: download_dataset(args.dataset) print("Download complete.") return results = run_benchmark( dataset=args.dataset, methods=args.method, refine_modes=args.refine, max_cases=args.max_cases, binary=args.binary, n_threads=args.threads, verbose=args.verbose, adaptive_budget=args.adaptive_budget, ensemble=args.ensemble, parallel=args.parallel, ) if results: print_summary(results) if args.output: save_results(results, args.output) kalign-3.5.1/benchmarks/scoring.py000066400000000000000000000201311515023132300171100ustar00rootroot00000000000000"""Alignment + scoring wrappers for benchmark runs.""" import subprocess import tempfile import time import xml.etree.ElementTree as ET from dataclasses import asdict, dataclass from pathlib import Path from typing import List, Optional import kalign from .datasets import BenchmarkCase @dataclass class AlignmentResult: """Result of aligning and scoring one benchmark case.""" family: str dataset: str method: str sp_score: float wall_time: float seq_type: str refine: str = "none" ensemble: int = 0 recall: float = 0.0 precision: float = 0.0 f1: float = 0.0 tc: float = 0.0 error: Optional[str] = None def to_dict(self) -> dict: return asdict(self) def align_with_python_api( case: BenchmarkCase, output: Path, n_threads: int = 1, refine: str = "none", adaptive_budget: bool = False, ensemble: int = 0, ) -> float: """Align using kalign Python API. Returns wall time in seconds.""" start = time.perf_counter() kalign.align_file_to_file( str(case.unaligned), str(output), format="fasta", seq_type=case.seq_type, n_threads=n_threads, refine=refine, adaptive_budget=adaptive_budget, ensemble=ensemble, ) return time.perf_counter() - start def align_with_cli( case: BenchmarkCase, output: Path, binary: str = "kalign", n_threads: int = 1, refine: str = "none", adaptive_budget: bool = False, ensemble: int = 0, ) -> float: """Align using kalign C binary via subprocess. Returns wall time in seconds.""" cmd = [binary, "-i", str(case.unaligned), "-f", "fasta", "-o", str(output)] if n_threads > 1: cmd.extend(["--nthreads", str(n_threads)]) if refine != "none": cmd.extend(["--refine", refine]) if adaptive_budget: cmd.append("--adaptive-budget") if ensemble > 0: cmd.extend(["--ensemble", str(ensemble)]) start = time.perf_counter() result = subprocess.run(cmd, capture_output=True, text=True) elapsed = time.perf_counter() - start if result.returncode != 0: raise RuntimeError( f"kalign CLI failed (exit {result.returncode}): {result.stderr}" ) return elapsed EXTERNAL_TOOLS = {"clustalo", "mafft", "muscle"} def align_with_external( case: BenchmarkCase, output: Path, tool: str, n_threads: int = 1, ) -> float: """Align using an external MSA tool. Returns wall time in seconds.""" if tool == "clustalo": cmd = ["clustalo", "-i", str(case.unaligned), "-o", str(output), "--outfmt=fasta", "--force"] if n_threads > 1: cmd.extend(["--threads", str(n_threads)]) elif tool == "mafft": cmd = ["mafft", "--auto"] if n_threads > 1: cmd.extend(["--thread", str(n_threads)]) cmd.append(str(case.unaligned)) # MAFFT writes to stdout start = time.perf_counter() with open(output, "w") as f: result = subprocess.run(cmd, stdout=f, stderr=subprocess.PIPE, text=True) elapsed = time.perf_counter() - start if result.returncode != 0: raise RuntimeError( f"mafft failed (exit {result.returncode}): {result.stderr}" ) return elapsed elif tool == "muscle": cmd = ["muscle", "-align", str(case.unaligned), "-output", str(output)] if n_threads > 1: cmd.extend(["--threads", str(n_threads)]) else: raise ValueError(f"Unknown external tool: {tool}") start = time.perf_counter() result = subprocess.run(cmd, capture_output=True, text=True) elapsed = time.perf_counter() - start if result.returncode != 0: raise RuntimeError( f"{tool} failed (exit {result.returncode}): {result.stderr}" ) return elapsed def score_alignment(reference: Path, test_output: Path) -> float: """Score a test alignment against a reference. Returns SP score (0-100).""" return kalign.compare(str(reference), str(test_output)) def parse_balibase_xml(xml_path: Path) -> List[int]: """Parse BAliBASE XML annotation to extract core block column mask. The XML ``/`` element contains per-column integers: ``-1`` (flanking), ``0`` (non-core), ``1`` (core block). Returns a binary mask where only core columns (value == 1) are set. """ tree = ET.parse(xml_path) root = tree.getroot() colsco = root.find(".//column-score/colsco-data") if colsco is None or colsco.text is None: raise ValueError(f"No element found in {xml_path}") values = [int(v) for v in colsco.text.split()] return [1 if v == 1 else 0 for v in values] def _fasta_ref_has_gaps(reference: Path) -> bool: """Check if a FASTA reference alignment contains any gap characters.""" with open(reference) as f: for line in f: if not line.startswith('>') and '-' in line: return True return False def score_alignment_detailed(reference: Path, test_output: Path) -> dict: """Score a test alignment with POAR metrics. If a BAliBASE XML annotation file exists alongside the reference (same name with .xml extension), the XML core block mask is used. Otherwise scores all columns (max_gap_frac=-1.0), appropriate for BRAliBASE and other benchmarks with hand-curated references. Gapless FASTA reference alignments (e.g. conserved RNA with no indels) are skipped — the C comparison code requires alnlen > 0. """ xml_path = reference.with_suffix('.xml') if xml_path.exists(): mask = parse_balibase_xml(xml_path) return kalign.compare_detailed(str(reference), str(test_output), column_mask=mask) # For non-BAliBASE references (FASTA format), check for gapless edge case if reference.suffix in ('.fa', '.fasta') and not _fasta_ref_has_gaps(reference): raise RuntimeError("Reference alignment has no gaps — skipping (trivially aligned)") return kalign.compare_detailed(str(reference), str(test_output), max_gap_frac=-1.0) def run_case( case: BenchmarkCase, method: str = "python_api", binary: str = "kalign", n_threads: int = 1, refine: str = "none", adaptive_budget: bool = False, ensemble: int = 0, ) -> AlignmentResult: """Run alignment + scoring for a single benchmark case.""" with tempfile.TemporaryDirectory() as tmpdir: output = Path(tmpdir) / f"{case.family}_aln.fasta" try: if method == "python_api": wall_time = align_with_python_api(case, output, n_threads, refine, adaptive_budget, ensemble) elif method == "cli": wall_time = align_with_cli(case, output, binary, n_threads, refine, adaptive_budget, ensemble) elif method in EXTERNAL_TOOLS: wall_time = align_with_external(case, output, method, n_threads) else: raise ValueError(f"Unknown method: {method}") sp_score = score_alignment(case.reference, output) detailed = score_alignment_detailed(case.reference, output) is_external = method in EXTERNAL_TOOLS return AlignmentResult( family=case.family, dataset=case.dataset, method=method, sp_score=sp_score, wall_time=wall_time, seq_type=case.seq_type, refine="n/a" if is_external else refine, ensemble=0 if is_external else ensemble, recall=detailed["recall"], precision=detailed["precision"], f1=detailed["f1"], tc=detailed["tc"], ) except Exception as e: is_external = method in EXTERNAL_TOOLS return AlignmentResult( family=case.family, dataset=case.dataset, method=method, sp_score=0.0, wall_time=0.0, seq_type=case.seq_type, refine="n/a" if is_external else refine, ensemble=0 if is_external else ensemble, error=str(e), ) kalign-3.5.1/benchmarks/vsm_ensemble_experiment.py000066400000000000000000000227221515023132300223730ustar00rootroot00000000000000"""Comprehensive BAliBASE benchmark comparing all kalign modes. Modes: 1. baseline - no VSM, no refinement 2. +vsm - VSM only (vsm_amax=2.0) 3. +vsm+ref - VSM + refinement 4. ens3 - ensemble(3), no VSM, no refinement in runs 5. ens3+vsm - ensemble(3), VSM in each run 6. ens3+vsm+ref - ensemble(3), VSM + refinement in each run Usage: uv run python -m benchmarks.vsm_ensemble_experiment uv run python -m benchmarks.vsm_ensemble_experiment --max-cases 10 uv run python -m benchmarks.vsm_ensemble_experiment --categories RV11 """ import argparse import json import statistics import tempfile import time from collections import defaultdict from pathlib import Path import kalign from .datasets import get_cases from .scoring import parse_balibase_xml def _read_fasta_seqs(path): seqs = [] name = None buf = [] with open(path) as f: for line in f: line = line.strip() if not line: continue if line.startswith(">"): if name is not None: seqs.append((name, "".join(buf))) name = line[1:].split()[0] buf = [] else: buf.append(line) if name is not None: seqs.append((name, "".join(buf))) return seqs def _alignment_stats(path): seqs = _read_fasta_seqs(path) if not seqs: return {} alnlen = len(seqs[0][1]) nseq = len(seqs) total_chars = 0 total_gaps = 0 total_gap_opens = 0 for _, s in seqs: in_gap = False for ch in s: if ch == "-": total_gaps += 1 if not in_gap: total_gap_opens += 1 in_gap = True else: total_chars += 1 in_gap = False gap_frac = total_gaps / (nseq * alnlen) if alnlen > 0 else 0 mean_seqlen = total_chars / nseq if nseq > 0 else 0 alnlen_ratio = alnlen / mean_seqlen if mean_seqlen > 0 else 0 return { "alnlen": alnlen, "nseq": nseq, "gap_frac": gap_frac, "gap_opens_per_seq": total_gap_opens / nseq if nseq > 0 else 0, "alnlen_ratio": alnlen_ratio, "mean_seqlen": mean_seqlen, } def _score_case(case, output_path): xml_path = case.reference.with_suffix(".xml") if xml_path.exists(): mask = parse_balibase_xml(xml_path) return kalign.compare_detailed(str(case.reference), str(output_path), column_mask=mask) return kalign.compare_detailed(str(case.reference), str(output_path)) CONFIGS = [ { "label": "baseline", "refine": "none", "vsm_amax": 0.0, # explicitly disable VSM }, { "label": "+vsm", "refine": "none", "vsm_amax": 2.0, }, { "label": "+vsm+ref", "refine": "confident", "vsm_amax": 2.0, }, { "label": "+vsm+iref", "refine": "inline", "vsm_amax": 2.0, }, { "label": "ens3", "ensemble": 3, "refine": "none", "vsm_amax": 0.0, # no VSM in individual runs }, { "label": "ens3+vsm", "ensemble": 3, "refine": "none", "vsm_amax": 2.0, }, { "label": "ens3+vsm+ref", "ensemble": 3, "refine": "confident", "vsm_amax": 2.0, }, { "label": "ens3+vsm+ref+ra1", "ensemble": 3, "refine": "confident", "vsm_amax": 2.0, "realign": 1, }, { "label": "ens3+vsm+ref+ra2", "ensemble": 3, "refine": "confident", "vsm_amax": 2.0, "realign": 2, }, { "label": "ens3+vsm+iref", "ensemble": 3, "refine": "inline", "vsm_amax": 2.0, }, { "label": "ens3+vsm+iref+ra1", "ensemble": 3, "refine": "inline", "vsm_amax": 2.0, "realign": 1, }, ] def _run_one(case, config): label = config["label"] with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as tmp: tmp_path = tmp.name try: t0 = time.perf_counter() kwargs = dict(format="fasta", seq_type=case.seq_type) # Alignment mode if config.get("ensemble"): kwargs["ensemble"] = config["ensemble"] kwargs["refine"] = config.get("refine", "none") kwargs["vsm_amax"] = config.get("vsm_amax", -1.0) if config.get("realign"): kwargs["realign"] = config["realign"] else: # Standard kalign kwargs["refine"] = config.get("refine", "none") kwargs["vsm_amax"] = config.get("vsm_amax", -1.0) kalign.align_file_to_file(str(case.unaligned), tmp_path, **kwargs) wall = time.perf_counter() - t0 scores = _score_case(case, tmp_path) stats = _alignment_stats(tmp_path) return { "family": case.family, "dataset": case.dataset, "method": label, "recall": scores["recall"], "precision": scores["precision"], "f1": scores["f1"], "tc": scores["tc"], "wall_time": wall, **stats, } except Exception as e: return { "family": case.family, "dataset": case.dataset, "method": label, "recall": 0, "precision": 0, "f1": 0, "tc": 0, "wall_time": 0, "error": str(e), } finally: Path(tmp_path).unlink(missing_ok=True) def _print_summary(results, method_names): print(f"\n{'Method':>20} {'Recall':>8} {'Prec':>8} {'F1':>8} {'TC':>8}" f" {'GapFrac':>8} {'AlnRatio':>9} {'Time':>7}") print("-" * 90) groups = defaultdict(list) for r in results: groups[r["method"]].append(r) for method in method_names: entries = groups.get(method, []) valid = [r for r in entries if "error" not in r] errs = len(entries) - len(valid) if not valid: print(f"{method:>20} (no results)") continue rec = statistics.mean(r["recall"] for r in valid) prec = statistics.mean(r["precision"] for r in valid) f1 = statistics.mean(r["f1"] for r in valid) tc = statistics.mean(r["tc"] for r in valid) gf = statistics.mean(r.get("gap_frac", 0) for r in valid) ar = statistics.mean(r.get("alnlen_ratio", 0) for r in valid) wt = sum(r.get("wall_time", 0) for r in valid) suffix = f" ({errs} err)" if errs else "" print(f"{method:>20} {rec:>8.3f} {prec:>8.3f} {f1:>8.3f} {tc:>8.3f}" f" {gf:>8.3f} {ar:>9.2f} {wt:>6.1f}s{suffix}") def _print_per_category(results, method_names): all_cats = sorted({r["dataset"].replace("balibase_", "") for r in results}) for cat in all_cats: cat_results = [r for r in results if cat in r["dataset"]] cat_groups = defaultdict(list) for r in cat_results: cat_groups[r["method"]].append(r) n = len(cat_groups.get(method_names[0], [])) print(f"\n=== {cat} ({n} cases) ===") print(f"{'Method':>20} {'Recall':>8} {'Prec':>8} {'F1':>8} {'TC':>8}") print("-" * 55) for method in method_names: entries = [r for r in cat_groups.get(method, []) if "error" not in r] if not entries: continue rec = statistics.mean(r["recall"] for r in entries) prec = statistics.mean(r["precision"] for r in entries) f1 = statistics.mean(r["f1"] for r in entries) tc = statistics.mean(r["tc"] for r in entries) print(f"{method:>20} {rec:>8.3f} {prec:>8.3f} {f1:>8.3f} {tc:>8.3f}") def main(): parser = argparse.ArgumentParser(description="Comprehensive BAliBASE benchmark") parser.add_argument("--max-cases", type=int, default=0) parser.add_argument("--categories", nargs="*", default=None) parser.add_argument("--configs", nargs="*", default=None, help="Only run specific configs by label") args = parser.parse_args() cases = get_cases("balibase", max_cases=args.max_cases if args.max_cases else None) if args.categories: cats = [c.upper() for c in args.categories] cases = [c for c in cases if any(cat in c.dataset.upper() for cat in cats)] configs = CONFIGS if args.configs: configs = [c for c in CONFIGS if c["label"] in args.configs] print(f"{len(cases)} BAliBASE cases, {len(configs)} configs", flush=True) method_names = [c["label"] for c in configs] n_tasks = len(configs) * len(cases) print(f"{n_tasks} total tasks (sequential)", flush=True) t0 = time.perf_counter() results = [] done = 0 for cfg in configs: print(f"\n Config: {cfg['label']}", flush=True) for case in cases: r = _run_one(case, cfg) results.append(r) done += 1 if done % 20 == 0: elapsed = time.perf_counter() - t0 eta = elapsed / done * (n_tasks - done) print(f" {done}/{n_tasks} ({elapsed:.0f}s, ETA {eta:.0f}s)", flush=True) elapsed = time.perf_counter() - t0 print(f"\nAll done in {elapsed:.0f}s") _print_summary(results, method_names) _print_per_category(results, method_names) # Save out = Path("benchmarks/data/vsm_ensemble_experiment.json") out.parent.mkdir(parents=True, exist_ok=True) with open(out, "w") as f: json.dump(results, f, indent=2) print(f"\nSaved to {out}") if __name__ == "__main__": main() kalign-3.5.1/build.zig000066400000000000000000000073311515023132300145760ustar00rootroot00000000000000const std = @import("std"); const builtin = @import("builtin"); const ArrayList = std.ArrayList; const kalignPackageVersion = "3.5.1"; const targets: []const std.Target.Query = &.{ .{ .cpu_arch = .aarch64, .os_tag = .macos }, .{ .cpu_arch = .aarch64, .os_tag = .linux }, .{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .gnu }, .{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .musl }, // .{ .cpu_arch = .x86_64, .os_tag = .windows }, }; const cflags = [_][]const u8{ "-DKALIGN_PACKAGE_VERSION=\"3.5.0\"", "-DKALIGN_PACKAGE_NAME=\"kalign\"", "-DKALIGN_ALN_SERIAL_THRESHOLD=250", "-DKALIGN_KMEANS_UPGMA_THRESHOLD=50", }; pub fn build(b: *std.Build) !void { // const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); for (targets) |t| { const lib = b.addStaticLibrary(.{ .name = "tldevel", .target = b.resolveTargetQuery(t), .optimize = optimize, }); lib.linkLibC(); lib.addIncludePath(.{ .path = "./lib/src" }); lib.addCSourceFiles(.{ .files = &kalign_lib_sources, .flags = &cflags }); lib.addIncludePath(.{ .path = "./lib/include" }); b.installArtifact(lib); const kalign_bin = b.addExecutable(.{ .name = "kalign", .target = b.resolveTargetQuery(t), .optimize = optimize, }); lib.addCSourceFiles(.{ .files = &kalign_sources, .flags = &cflags }); kalign_bin.addIncludePath(.{ .path = "./lib/src" }); kalign_bin.addIncludePath(.{ .path = "./lib/include" }); kalign_bin.linkLibrary(lib); b.installArtifact(kalign_bin); const target_output = b.addInstallArtifact(kalign_bin, .{ .dest_dir = .{ .override = .{ .custom = try t.zigTriple(b.allocator), }, }, }); b.getInstallStep().dependOn(&target_output.step); } // const exe = b.addExecutable(.{ // .name = "zig_test", // .target = target, // .optimize = optimize, // }); // exe.addCSourceFile(.{ .file = .{ .path = "./tests/zig_test.c" }, .flags = &[_][]const u8{"-std=c99"} }); // // exe.addCSourceFiles(.{ .files = &kalign_lib_sources, .flags = &[_][]const u8{"-std=c99"} }); // // exe.addCSourceFile(&.{"./tests/zig_test.c"}, cflags.items); // // exe.addCSourceFile("./lib/src/strnlen_compat.c", cflags.items); // exe.addIncludePath(.{ .path = "./lib/src" }); // // exe.linkLibrary(lib); // exe.linkLibC(); // b.installArtifact(exe); } const kalign_lib_sources = [_][]const u8{ // "lib/src/strnlen_compat.c", "lib/src/test.c", "lib/src/tldevel.c", "lib/src/tlmisc.c", "lib/src/tlrng.c", "lib/src/esl_stopwatch.c", "lib/src/msa_alloc.c", "lib/src/msa_op.c", "lib/src/msa_io.c", "lib/src/msa_misc.c", "lib/src/msa_check.c", "lib/src/msa_cmp.c", "lib/src/msa_sort.c", "lib/src/alphabet.c", "lib/src/task.c", "lib/src/bisectingKmeans.c", "lib/src/sequence_distance.c", "lib/src/bpm.c", "lib/src/euclidean_dist.c", "lib/src/pick_anchor.c", "lib/src/aln_wrap.c", "lib/src/aln_apair_dist.c", "lib/src/aln_param.c", "lib/src/aln_run.c", "lib/src/aln_mem.c", "lib/src/aln_setup.c", "lib/src/aln_controller.c", "lib/src/aln_seqseq.c", "lib/src/aln_seqprofile.c", "lib/src/aln_profileprofile.c", "lib/src/aln_refine.c", "lib/src/sp_score.c", "lib/src/weave_alignment.c", "lib/src/poar.c", "lib/src/consensus_msa.c", "lib/src/anchor_consistency.c", "lib/src/ensemble.c", }; const kalign_sources = [_][]const u8{ "./src/run_kalign.c", "./src/parameters.c", }; kalign-3.5.1/doc/000077500000000000000000000000001515023132300135255ustar00rootroot00000000000000kalign-3.5.1/doc/images/000077500000000000000000000000001515023132300147725ustar00rootroot00000000000000kalign-3.5.1/doc/images/Balibase_scores.jpeg000066400000000000000000005200031515023132300207210ustar00rootroot00000000000000ÿØÿàJFIF,,ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ‰M"ÿÄ ÿĵ}!1AQa"q2�‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2�B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷ú(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ©¨jš~‘kö�JúÚÊßp_6æe�2z ±5n¼«öƒÿ’gÿoÑ& ×þ¿ÿÐסÿàÆþ*”xë pêÚÝíî ¬×°FÒ00­wv×0^[Gsk•ëþð…§ŠOŒõC|’‰MÅÅÖÈÕ‚àŽ•%÷Å¿iùó|Gk!­Õ¦Ïýð $ð÷Äïø#Æh72Ïlî©'Ú6™"V8,ƒï/®IèzúB¾Eø»ã}3Ç+´»Òb”[ZÛˆ|ÙWkHwȇÉ}×?Þ½ÿÑ¢½ãw‹uÏxwMºÐ¯¾É4×f9ÊI2» ÆHê+ÎþÉ}×?Þ½ÿÑ¢ºŸÚKþE-þ¿�þ‹jôÏj7Z¿�´]Fú_6îæÊ9e“h]ÌTpð¯•~xæo¶­5�§Úu+ØRÞÕ ’¡·g$O°Iõïù&žÿ°t?ú¯Ÿ¿gý Wâ ^\ uÓ­šxÁa!Tþ±ú�@¯áŽ:¼Úrê÷vò¸Þ-Vü@ßM‹…C�z‚~0ø‡Ãþ%ñÞö‹Ì¼÷kf= ÷“Ü󃜑Å}^ûIhP mÄ YÌ�g+÷Á“?L?ç@ù_9ëß|cã�I ø p̨ð…ó%QÁvváÓ§nyÅ{Ãûç×>h—Í$¶K�žX¨ØN}N3YºG†| ðºiïcºƒM’æ0Œ÷—œ²ƒœ(cëéé@[7‚>6YÄnã×ï.$Q»ÉMU˜ÿß,BšèþüTÕõír_ ø˜o¿Us æ1–O¼Ž£ dç¡Íuz�Ưiêßñ:ûLƒ¢[@îOÐãoë^1ðëX‹_ý¢!Õà…¡Šòâîd�º€a�Œã¿¯½}!âoZx[×ÚÕîL±îÚ½]‰Â¨÷$�ø×϶^ ø¯ñNêâãC¹’ÃO‰öÿ£Ëöxã=vïûÌqŒõú ×°|\Я|CðÛS³Ó£in—dÉŒ™0$SŒàw W�ü%ø¹¥ø;Eoë–“ÇÎÒ%Ì)»±�ë׌uôǯqñ{á—•©j­ÅÝ‘p¥å¸ûTDÿu·|ËŸ^>¹¯xð'‹¡ñ·„íu˜£ÈùŽxAÏ—"õôèG±A|Mà?ˆzdšAÕ,¯à¹ÛºÒI'|à v·•»áï èþÓÞÇD³–ÒJfhÄŒùr',Iè£ò Wâ�ÄÈ<¦E%ίt ·…ÏÊŠ:»ãœv¹úòë+ãO�m—V½Õ…¼Ã|@Ý}”2öÂ'8÷#ŸzÇñޝ¦j_´³xŠ/G²»HdÜŒàGýݪ !œñüF½¤|løvˆ?òJãÿ�Ж[|Cø‡ðÇ]†ÃÆ1Í}c'8˜‡f^í£©pIü3šú#LÔ­5�.ÛR±”Kks–'Ô�ÐûWˆüYø�à/xâÊÇVœ2$Ö‹öI”î  Ì€”·Jèÿg»ù/>´‹;éaO÷HWþnhÕ©-#}Óô Ž>xæo¶­5�§Úu+ØRÞÕ ’¡·g$O°IÞ?…þ8êðiË«ÝÛÊãxµ[ñ}6.}=ë öÐàÕ~ µåÂ]:Ù§Œ‘æOà ¨õM|íàŸŒ>!ðÿ‰G‡|w½¢ó/=šÙ�BÄ}ä÷<àç$q_D×�þÒZÛGñhs#YÊÀ}ðAdÏÓù×`ž'¹�öy]pHßk]#Ëçæó1åÏ®y ?Æ¿uýkÄÍá‡ñ3ÈÄn¢@ï+½³?* çæ>™È�/ƒ¾7YAý šåäÒ¨ÜmÓR.ß÷ÉùÐf¨|ñWƒ¼!©}¯j+m©Në@ÛË!“‚Š@ËŸìŠõÏø]¿?èaÿÉ+�þ7@ÇÂߌšÞ¯ÿÏŠ£Xµ\”†ãg–duꎽø=0L×Òüe¨]i^ Öõ )|««ke†M¡¶²¡ à‚>µó/ÄßhìüKáK±8 ó2Äñþýö`ÝT¯¤~!~ø�އMŸÿ@4ã~øÇâ½GÃ?Ù–Àë>-½½xí�…`„"Ä(U<–Æxà’p0_ªø;ãb[¶¨Þ#–y”6¶—ì­ë€€* ü*Ù¯I€�sXtu1ÛFÄrªrÍùü¿•{ýx¯ÁŸŠšŸ‰5|9â^$FK{�¡YÂýä`8Î9ŽkÕ¼E¯ØøcA»Ö5 [[&âÞcÐ(÷'}kçïÄ�þÓº„q�¨/o°¸s]í)ªË“¡é(ÄGq4“È}�Bÿègò züQø«¨Ü<šn›c÷R?@Òýælc }p*=JÿâïËPÔõ ¯¬ …fšoµDÇû¬O̹õãë^åðïE‡@ø¢ÙB�XÚ¤Ò‘üR8 Çó?�«â ÛÄ^¿Ñîò!¼…¢f%I0÷}(7À¾0´ñÇ…àÖ-“ÊrLsÀNLR£=Ç �b+çïë–þý¢ï5›¤y!´�$dO¼ßèë€>¤Š÷?‡¿ ø}g{km¨ÏyÔ‹&%@»8ǯ•x‡‰ô¨u¿Úa´û•×ÖþjŒ¢$bÔ PEö/Œaþ׃Q] Âa¾ÚÝnÜ”=Ø ú±íÅ`Aãψ_ üQ‡Šg¸½´b⹓Íó#Î7G'\õïõôð €+Àÿi„_'ÃRm÷\®}±{ÄÇsoð°h¥@èø# ×Îð|hñ“ãŸYßÌú”I=¶›b–è»¦ó‚Æ *† .îç?Z÷_ ÿÈ¡¢ׄú-k篇¶0^þÑz‹N�þÏ{{2ÓpvþÏÔPî£á��Úͳj²ëe��ë§Û^GP¸Q·ób}kŸµßÛjw‰!—R¹‰ Ú™Y`q²CÝzó÷¸Ç9ãéšù…4Ûk¿Ú…­e�Zí6˜©T2üxf€7&ðçÆÏZ�^Me´Ó ߌwmlÁz�µüçÖ¢øcñ3Äö>8�Â^,šk�,¦Û782Á0è7$cœõ_¡ëæ¯ƱþÓÚqA‚÷ö Øîqþ”ômýìn�stû-í¢i¥oEPI?�¯œdøƒñâv»=—„D–qó¶T(™Ài%<äú {Šú+UÓ-µ�&ëL¼ m®¢h¥ÅIR0FGJäô«/ü,¶¸µ‹Q´Ó¾ÒâIêìœãühɯ|+ñ¯ÃöϨ¦¹}x"Þ8µ˜€9?#ý߃Ÿ®üoou¦êëö¥š <è×hš2pIQÀ ã8ã‘Å]Õ~9xM…Ì:”—ó(8ŠÚù�ûÌþµå¿³Ä‰:´Á 4é_`蹚#ŠöOŠúö§á¯‡·Ú¦‘sökØž ’ùjø "ƒÃ:Ú¼•¾0x¯XðŽ�¢hm5÷Š.ÖV½¹†ÝKƾk…UU\°)-Ž;œ�Høéÿ$ŸSÿ®°èÕ¬/ÙÛC·µðuÞ²cSwyrÑù˜äF€aï¢Çòô xBÃÆ–? ücÿ “Þ´²YÊÖßk¹¾SîÆíçqY_³Güƒ¼Eÿ]`þO^»ãùuïû\趯˜~üG_ø[]ŽÖ;V¾’%µV\¢`6]½q‘�Üи|Sø§kà{cbR}vtýÜg•�Oñ¿ôþ•'ÂôñÝöž5�êò2NŸèöÖÈSünUÑsõô=ðf +Änn"xÆv6öÞ)ñ½Ýåû·Ú„K¼Zãˆàdd p1Œ×Ð_ ¸];ão�<)jº_ˆt#s<#bÉt� §Ówo®}úУø‡À_ ü+¥6§¬èöö¶�Õ7—™‰cФ“ß·jèü…ÿiðt"=.âf|…‘C¸Â“‰9þ~áqøÿãv¯j“Ù5Ž‘e[Ëd·ˆ­“Ì��OÐ_Gè-§‡4-ÅH¶´ˆF™êÞ¬}ÉÉ>æ€4i-!û§é@/þÎÚ¤6~<º±•‚›Û6X³üN¬÷ÈcøWÔ5ò†~øÖ[{Ý^ÇOÔ4ýOKx¥¶Žâ�¦ÎíÆ2À˵x=‰øûâý6°j^€jh6–•$ˆ–õ1õÏÐ�€6¿i=VÐôm83Ër×EAä*©POÔ¹ü�mÏ Ü/ìÔt݇Ï] \Ç äLF=k€ð¯€¼Sñ3Åëâ_Å4:pegóÐÆfQÈŽ4êßëÉ&¾”(��•J´©éŠùËàg…<%âÍT‹YÓ!»Ô-®ò:‘(¡nVüëÕÿáOøþ…È?ïìŸüUyˆ< âï…~-“ÄŠk�1‰*"C.Ä'&)PrT{؃Vö…ñ=Ôd³ðÕ²ê 6îcàúˆúþ¦€:Ý[Bø1¢x†-ÿN�59J�ܹŒ®@'Ž3ÜWuñB|6ñ¨Àdàß³^Uð¿á®½¨ø³þo$©8�Ï 7É/geþ½‡�ÀŸ[ñÕ´÷žñµ´2O<º|ÉQ)fv(@Iö 1ýšÿä[Öÿëí?ô öêñïÙûEÕt]X�UÓ/,d’éYꈰÛÔ"½†€>mð‡ü�£ÿ_—¿ú Ö¯í/c!‹ÃÚ‚¯îÕ¦…Ï¡;“~TÏ xw[·ý£/õIômB-=®ïnÞÕÖ"_iF0r1Ï5ëþ7ð•¯�|-u£\·–χ‚lgÊ�}ÖÇ~àû@ðN¥¯à}ú ²ÙEœv` 0üøVž©¨Á¤i7š•Ñ"ÞÒžB:íPIÇ¿óV�¯øÿàÄÓéwºAºÒË–Q"³BO÷£‘zg¸?�4º÷ÄüV´‘¡46“0óVÙY·€rÈpª¹Áí@Ûà/ˆúwÄ~Úu�åºÙyaÚä( _vÚO÷Oæ+È/äëWþ¿#ÿÒu¯_øgàuð'„ÓO‘Ò[éßλ‘: £Ø¿'½y•߇u¶ý¥×U]P:oÚ£o¶ Wòp �øÛŒñÖ€=þ¼ö˜ÿ�_ ¿sü£¯z¯ý¡t=_Z¶ðøÒ´«ëóÎd¶ï.̈ñ� ã8?•z§…äOÑ?ëÂýµà ¿äâ5¿úï}ÿ£ {ÿ†¢’ èðÍÇ,vP«£®H@ ô5â_<;­Ù|wÕõ½P·±’k—2ÚºFÁœ•Þ޴ô |Ùeÿ'Xßõû/þˆjúN¾³ðî¶¿´³j­£jMû\�ö³jþN ,ߌc|$´ñ¶’|Oâ[ë¹ÖæWÄ’a¤ÚpYÜäœ�x�kÙ¾#xQ¼gà›Ý"Tºm²Û³tóäìy�x/…~!x¯á4过¤–Õe.‘Oº&F=v¸2ž½^ {ž›ð«ÀÚK+ÛørÍ™9 qºn}~rkÇ>4oñO\xˆ1µŒÅ6ôÇŸ1Zòx¿â'Åh[JÐôOìM*q²æõË�ðG˜@ÏÑF × áíCVø5ñù.4‰oŽÉ-œÇçFX2ȇ®Ð{õ#­{ÇOù$úŸýuƒÿF­CðþIe§ý|Íÿ¡U¯‹v·ÚïÂk¨ì,.n.§û<‚ÚÚGûêHÀ8úv£à¦›}¥|6¶µÔl®lîâRa¸‰£p ppÀê|aÿ"N½ÿ`ë�ýÕàß³×…4½cRÔ5»ø|ùô׌[#òŠÍ¸ïÇr6ñé×®1ïž*†[�kpAË4–¢FŠY™Œlu$×–þÏz­¢Øk˪éw¶ ,°˜ÅÕ»Ä\ùÆà3ÔP-ñ§Âw^ñm¯�t=ÐEq8‘Ú1þ¦äsŸ£`Ÿ®ïQ^áàZøÓ¶šÅ¾Õw."ýT£ï/õÄUÿhV^%Ðo4}A7[]FQ±ÕOPÃÜô¯øceâï‡^?¹Ò/4MRãFº—ÈšâIAù&VçŸcÏ"€>‹¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªO<¢F¸öv³¥ÿZÿïwÚeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTPÓ#}—~~luüj¿Úeþÿè*cÿ?‡õª”/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚¬4Œ-wçæÀæ©U¶ÿ�ô΀!ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠºÒ0µÍ�ÍWûL¿ßýLÿñä>‚ªP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú °ò0¶Ì@æ©U¹?ãÍ~‚€!ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ»$Œ¶ÊàüÄj¿Úeþÿè*iãÑ>‚ªP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú ±,Œ¶êÀòqÍR«sǪ~Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP˜f‘æUfÈ>Õn¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEQEQEQEQEQEQE[?ñãøZ©VÏüxþÖªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVÛþ¿3sìq@�EGñ\ÛÇ<$ŠU޽�jJ+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEQEQEQEQEQEQE[?ñãøZ©VÏüxþÖªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVÛþÉ'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù H¼  ’F€ôÜØ§ ge ¥H<‚Zä|w#½¥˜fÎ$oå]—<ƒH²Ž ÿ Šå§‰rÄN�¾¿'­‹ßd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšêhÄßfòøÝŠƒì’³ùÔÅÛì›óóc¯ãU¾Ñ/÷Í?ì’³ùÒ5³ª–f@ d’xß´KýóTu©ä:ø-Á·ýÓŠ»±'É.Ƚ^p&)#p:•lÓþÉ'û?�r‘ÓMº Øý÷ôÖ}¢_°ä›‰Žñ#U«\Ù$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ éöI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:`‹2ybXËÿww?•h—ûæ¹K7aã9›{óøÞ�h¤ï²¹p‡2~G]öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù¬öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÖ1ñ¿ÛŸÙ¾W|y›½³Ó­ö‰¾jc%-�*R�;s-Õ× ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷ÍQ˜ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÓ$ˆC�2XÓ=763GÚ%þù®GÇr;Áe¸ç ÿÈW6.¿ÕèʪW°¤ì®vÙØ �y_²IþÏçTôéäe Ô§ògíÿ|Öñ|ÑLcþÉ'û?�Nbcmåñºªý¢_ïš²ÎÂÓ~~lj€‡ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@kvE,ÌŠ£’IÀØâó�1É�ÆU³YúôÒ6ƒ~ p`oåX¾•ÓI¸ ØyÿÐEj©Þ›ŸcŠx·TpöÝ7C­û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÖGhÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@‹sìÆ\niÿd“ýŸÎ¹=ØxÂwæß'?�uh—ûæ·¯GÙ4¯{«—R�!ÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÀ�ÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþuÌx·YÔ4õ´6·-òû°8Æ;{Öý­ÔÏi ´„³"’qÔâ¹áˆŒëJŠZÆßˆ¯­‹d“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšèi¢cl#ãÉ'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüêw‰šÜ ÆF*¯Ú%þù«.ì-U�ù°9 ~É'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçL'–%ˆ¿÷CsùQö‰¾k‘±v5™Áù·ÉÏàj'>V¼Îš=ª›½¹UÎÇì’³ùÑöI?ÙüéŸh—ûæ�´KýóVsû$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¨%Ô×1Çž›Ø þu'Ú%#!é]7`öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù¦©"f·TÈÅAöI?Ùüêi–ÙX˜�ÍVûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïšÎ×µ «Mêx&)*(*À9⹚Fuj*tåQì“q©öI?Ùüèû$Ÿìþu…ámRöûGó®nI<Öˆ8­¯´KýóNqq“‹&…h×¥±Ùê?ì’³ùÑöI?ÙüéŸh—ûæ�´KýóRl?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù¬]7^½»Õ§µ� �7`ªóÁÅi Rœ\—B£$Úèný’Oö:>É'û?�3íÿ|Ñö‰¾k2Gý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:žH™àTÈÅUûD¿ß5fWe·V㚇ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß446î’†8À«UN ¤i•Y² \ Š( Š( Š( Š( Š( Š( /ak› ˆ€ÒDÈ é’¬øvïÃ:}ì�I)�¤Ì,Jà�ê¥tÔP‹tÝcUÑÖßC¾Wbec)‘“*ÈÊ‚z‘ùV…•œƒB¶±Ô™neû2ÃrÄ–6ÐäòrsÖ¯Q@y‚üQáù&ƒÃìéò¹q ÚdÆO§ÊÙý+kÂ~þÀšçP½»kíZïýuà 3œÇ�é]MËø³Â â¶½´»k-VÐæ …ã9Áü™¬Iüâ¯4Vþ%× }>6 ÑZ& ˜õùWúý+Ðè íàŠÖÞ+xG JtUT”Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( Š( Š( Š( Š( SÇñéiÿ]ùWC¦È&Ïþ¸'þ‚+žñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šòè¿ÕôD/‰–¨¢Šõ -Ÿøñü?­T«gþ<ëU(ª:Ïü�/ÿëÝÿôWªŽ³ÿ Kÿú÷ýÕCâF8�àÏÑþF�äuÿ] ®ª¹_ÿÈ:ëþºÿA]Uk‰þ+8ò�÷*~Ÿ¨QE�éQ@rÖŸò8Iþûÿ#]MrÖŸò8Iþûÿ#]¸O†§øY½¥èu4QEqQ@Q@Q@Q@Q@Q@Q@™ÿ‘ßþÿ²WY\™ÿ‘ßþÿ²WYXÑû^§¡˜˯𠢊+cÏ (¢€ ä¼sþ¢ËýçþBºÚä¼sþ¢ËýçþB¼ü×ýÎ/Í?„é4ÿùÚÿ×þB¬Õm?þA¶¿õÅ?�«5ÛOà^… «mÿ#è?�T«mÿ#è?�X(¢ŠÏ×?ä}ÿ\[ùV?�¿äqÿ]Ïþ‚+c\ÿ�÷ýqoåXþÿ�UÇýw?ú®˜ÿ^§�[þF”ÿÂ΢Š(®cØ (¢€ (¢€9kù¦ÿ~Oë]MrÖò7MþüŸÖºšíÇ|qÿ 7¯ºô (¢¸ŒŠ( Š( Š( Š( Š) $9$ÐÑY‡Ä:P8ûWþCoð¤ÿ„‹JÿŸ¯ü†ßáQí!ÝýV¿ò?¹š•‚šµÓx”ØžFâ>ï?w=j×ü$ZWüýä6ÿ ç’þØx¤Þ™Ñ÷¿iþî:u¬êTZYõ;0˜Iµ?ið»]u;Z+/þ-+þ~¿ò…ð‘i_óõÿ�Ûü+Oièãú­äs5(¬Áâ,�ÐçÕJÓ#"©I=™¥RŸÇ½PQEÌÎCÇ_rÇêÿû-u6ñãoÿ\×ùW-㯹cõý–º›?øñ·ÿ®kü«ËÃÿ¿Vô�äBø™5Q^¡e·ÿ�!ôR­¿üy ª”Voˆ?ä{ÿ\�iVoˆ?ä{ÿ\�]?�zœø¯àOÑþF_�¿ä 7ý|ýk¦®gÀßò›þ¾þ‚µÓUâ?‹#Ÿ*ÿr§èQEbzEP\¶™ÿ#]Ïûò:êk–Ó?äk¹ÿ~Oç]¸O‚§¡½/†^‡SEW€QEQEQEQEQEQEQEÊÛÈçÆl›Ûn÷ã<}Ó]Urvßò:·ûïÿ šë+?SÐ̽ð¯Ô(¢ŠØóŠ( Š*Ž¡«Ùé~_Úä)ægnœãéõ¨œãN<ÓvA±zŠE`謽dRÕ€U¹?ãÍ~‚ªU¹?ãÍ~‚€*QESS¼:~›=Ð@æ%ÎÒqš¯¡j­¬X5ËD""B›Cg úÒx�þEëßúçýEgø'þ@r×vþK[¨/båÖç›:õa)û®-ÛÎçIEV¤QEQEW9¦^\Ëâˆd™Ú5/…'�ƒÅtu­j.””_©sƒƒ³ (¢² (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+“²ÿ‘Ê_÷äþFºÊäì¿är—ýù?‘¬koSÐÀüÂβŠ(­�<(¢Š(¢Šã-´ÉÄëÇøÔÊqŽìÚ–­kû5{ÏÿÂ[iÿ>ó~ŸãGü%¶Ÿóï7éþ5ÚŸsoìüOòÏüŽÿð?ý’ºÊáN©ü$Ú>[ù{³·ŒýÜV×ü%¶Ÿóï7éþ5•*�W»êvã0•çìùc{E# ¢¹ÿøKm?çÞoÓüh-´ÈÌ�ø�kí©÷8¿³ñ?ÈtR#Eu9Vµ©ÆÉxçýE—ûÏü…uµÉxçýE—ûÏü…yù¯ûœþ_š& Òiÿò µÿ®)ü…YªÚüƒmëŠ!Vk¶ŸÀ½ AVÛþ‡�ÿ ®•éqÿ|ñ¥oØj¶7�[™‚l:ã"¦f¤¹–—=*8ü-JŠšm”´ûmoT…¥¶º”ª¶Óºb9ëýjßö‰?çåÿð Ö—‚¿ä?ýv?ú®–ºñ¹Sªá«/#Ô©UÆM$Ž#ûÄŸóòÿøjðθ“‘•e9ˉ°Nzó]í’ÇÔ[%÷õ‰vGý‡âOùùü4aø“þ~_ÿ vôRúôÿ•}ÁíåÙuwý¯¤Ý—7Rnl0i`F{×c\÷Œÿä)iÿ\ÿöjèj±oš�9ÚÍÜu�ãQEpáEPEPEPEPEP'mÿ#«¾ÿú ®²¹;où[ý÷ÿÐMu•� Ÿ©èf??ð¯Ô(¢ŠØóŠ( ¸ï}뤟û-v5ÇxëïX}$ÿÙkÍÍÿÜçòüÑ3øN²Ûþ=bÿp*–¢¶ÿ�X¿ÜÊ¥¯B? (*ÜŸñæ¿AU*ÜŸñæ¿ATJ(¢€2üGÿ"õïýsþ¢³üÿ 9?ë»%­ÿȽ{ÿ\ÿ¨¬ÿÿÈOúîßÉk¦?îïÔñêÈÖà™ÒQEÌ{EPEP-¤ÈÏuõ“ÿB®¦¹m#þF{¯¬Ÿúu5ÛŽþ"ôFõþ%èQEqQ@Q@Q@Q@Q@Q@rv_ò9KþüŸÈ×Y\�—üŽRÿ¿'ò5�mãêz‚¯øYÖQE±ç…Q@Q@gŽ×YºÿÒ»¿Ô§û¢¸ÿÿ®²ÿuÿ¥v©O÷Eyx_÷ÚÿöïäBø˜ú(¢½BËrÿÇ¢}T«rÿÇ¢}T ²|Mÿ"åçû£ÿB­Y>&ÿ‘róýÑÿ¡ º_}NloûµOð¿È§à¿ùŸúìßÒº*ç|ÿ ÿ]›úWEU_ø’2Ë?Üéú ¢Š+#¸(¢Š+–Ñ?äcºú?þ„+©®[Dÿ‘Žëèÿú®Ü/ðªúÒøeèu4QEqQ@Q@Q@Q@Q@Q@Q@ž›ÿ#}ÇûòWY\ž›ÿ#}ÇûòWYXÐÙúž†cüHÿ…Q[xQEWã�øú³ÿq¿˜®Ö¸¯ÇÕŸû�üÅy™Çû¤¾_™øNÐt´ƒ ¥¯L°«sǪ~R­Íÿ©øPJ(¢€1üUÿ"ÝçÑô1Uüÿ"úÿ×F«*ÿ‘nóè¿úªþ ÿ‘}ë£WJÿw~¿¡ãËþFÑÿêtQEsÀQEQEËxþC×î?þ„+©®[Ãÿò»ÿqÿô!]Mvãÿ‹òFø�Œ(¢Šâ0 (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Šåf‘ÿá4 ½¶ï^3ÇÜŸ-¼ÎŒ=lä¯k&þ㪢Š*Îp¢Š(¢Š(”ñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šç¼qÿ–ŸõÑ¿•t:gü‚lÿë‚è"¼ºïõ} âeª(¢½BËgþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEP\µ§ü޾ÿÈ×S\µ§ü޾ÿÈ×ná©þoGizMQ\FEPEPEPEPEPW?ñë7û�ü«Á–6·‚÷í6ñM·fÝê3º·îãÖo÷ùV?€þíÿÖ?ýš°š½HßÌôpÒqÂUkËó:/ìM/þ�öß÷ìQý‰¥ÿÐ>ÛþýŠ¿EkËǶ©üÏï(biô¶ÿ¿b�ìM/þ�öß÷ìUú(å�`öÕ?™ýåìM/þ�öß÷ìW-ã+[5³û5¼Pî/»b�Ÿ»]Åqþ;û–Y?öZʼR¦ô;²ê³–&)·×òf½¯üyÃÿ\×ùTµÎ\ø¦×MhíZdt�7À*õ¨á7´ÿŸI¿1XK1ÂÁòÊz£Íœ—3:šä¼sþ¢ËýçþB¤ÿ„ÞÓþ}&üÅcx‡^‡YŽŠ�Ë$�ÄsœWc�ÃUÃJ•Û·æŒå$ÑÜéÿò µÿ®)ü…Y®FÛÆV°Zà µ˜˜ÑT�G8©á7´ÿŸI¿1]pÌðŠ)9þes£©®gâü‚ôïúèßÊ™ÿ ½§üúMùЧâ�Zc@°¸…]Îñ²·PBƒüˆ®ì7Zº…9]žnq$ð5-åù£·Ò-à:-�0ÆI·�$¨þè«¿fƒþxGÿ| ¯£ÿÈÃþ½£ÿÐE]­dß3;¨Æ>Î:tD_fƒþxGÿ| >Íüð�þø-®Í9cØ‹ìÐÏÿï�GÙ ÿžÿߥ¢‹°å�cÊÐñ^²r�u¾ ÿ�}Ïýuþ‚¹5ÿ‘³Zÿ·Ÿæk¬ðOüƒîë¯ôêÕÿw—ÈàÈÿÜê�þ‡OEW’z!EP\_�¿ãòÓþ¹Ÿç]¥q~6ÿ�ËOúæ�våÿÇ_3|?ñÐQEÄ`QEQEQEïüxÜ×&þU=A{ÿ7õÉ¿•'±Pø‘—àOõ7ßï'õ®¾¹©¾ÿy?­uõ�ᣳ2ÿzŸËòAEV§QEÆøó­‡ý´ÿÙk"ÇþJ Qÿ¢ë_Ç�l?í§þËY?òP`ú�ý^.aüXŽ'v+ýÒ�«üÏI¢Š+Ú8BŠ( ²ì>¥†ÿŸqû‘‹ÿ–…ÿ@èÿï¦ÿà,âH5í^—lq¤ê«è` õšò˜ädÖ¾—úuág)7wØóq”)RÅaÝ8¥ïtV;È.úìô]-rþ –8ôÉÃȪ|ãÁ8þ]Ú`ÿžÑÿßB³Æ'íä}eûÆKEEö˜?ç´÷Уí0Ïhÿï¡\ܯ±�™-Ú`ÿžÑÿßB�´Áÿ=£ÿ¾…¯°YœŒÿä)iÿ\ÿöjèkœñ„‰&§hQÕ‡—Øç½tuÙ‰þ/™µO‚!EW€QEQEQEQPÞ;GcpèpË}+�ÒôíWXId·¼ F@o2Vk)Ôåi%s³…Ua)Ê\©­ÍÂ-®ÿÏì÷ùÿÂ�øEµßùý�þÿ?øRö²þSO©ÑÿŸÈ‚ÛþGVÿ}ÿô]erÃÁúÀ“Ì ?½æ¶0¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( ¹9¿äwï¯þ€+¬®NoùÇûëÿ  Æ·Ùõ= »zŸá¡ÖQE±ç…Q@Q@§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€"¹ÿ�Y¿ÜoåXþû·ÿXÿöjعÿ�Y¿ÜoåXþû·ÿXÿöjÆÅ�Ìô(¹Õÿ·3±¢Š+cÏ (¢€ ãüw÷,>²ìµØW㿹aõ“ÿe¬kÿ �ÙoûÔ>“0bŠ9üsoѤ‘·–A÷C¨5èØšOý,¿ð?¸+_ùm~±ÿè¡^—^v]Nu\•ýöp5ïKÔ£ý‰¤ÿÐ2ËÿÓü(þÄÒèeÿ€éþzŠôý�?å_pY±4ŸúYà:…ØšOý,¿ð?¯QG±§ü«î #žñ“¦Ã ^ÉŸi‹*Ë ‚±Åyôßò*Aÿ_Òè ^›âOùïÿ뉯2›þEH?ëúOý+–„#ÖšŠ·ºÿSÊÎÜçéú£ÕtùX×´ú«µKGÿ�%‡ý{Gÿ Š»^„¾&z4…DQEI¨QEå‹ÿ#fµÿo?ÌÖ®�ât‹ib–$.û�R=+)älÖ¿íçùš›NÑ/5HžKeB¨ÛNæÇ5îÓ�9Sj¦Ú\<¢ðÕ9¶çgKÿ µ§üúMùŠ?á6´ÿŸI¿1Xßðˆê¿Ü‹þþ ?áÕ¹ýüÃßñ=®JÿgþkOùô›óÂmiÿ>“~b±¿áÕ¹ýüÂ#ªÿr/ûø(öÿˆrPïø›?ð›ZϤߘ¬X‹Xž"‰ã©RóRÿÂ#ªÿr/ûø+?PÒît¹#K� ¸ÈÚÙ­¨RÂÆw¦õõ.œi)^/S½¢Š+çÏ<(¢Š(¢Š(¢Š* ßøñ¸ÿ®Müªz‚÷þµ‡®)mn` ’Bp?ÜåæR•(ÆOV¤ŸàÎ<ÖtåB”©/vìõ/íí#þ‚vŸ÷ùÆ�íí#þ‚vŸ÷ùƼÈ›þy?ýòhò&ÿžOÿ|šÇûv·ò/Äñ}£=ƒû{Hÿ �§ýþ_ñ£û{Hÿ �§ýþ_ñ¯ò&ÿžOÿ|š<‰¿ç“ÿß&�íÚßÈ¿öŒöíí#þ‚vŸ÷ùƲüE¬i·½Šûi$h𪲂O#µyŸ‘7üòûäÒePKFàåMELê¬àààµVê'Q—îäV³ÿ¯¹ô¯WÒÿäeÿ\ÿAå?ò+Yÿ×Ü¿ú W«éò ²ÿ® ÿ Šúlü‹¨úfþF5½#ù袊ÐöBŠ( ¼¦ù5¯¥Çþ…^­^SüŒš×ÒãÿB®Ìïäy9‡ûÎüEz+µðl˦Nd‰‰±–P„WGö;où÷‡þøéVÌU9¸rì},ñ*2q±äôW¬}ŽÛþ}áÿ¾c¶ÿŸxï�YjÇù~¶»OEzÇØí¿çÞûàQö;où÷‡þøjÇùúÚìyJ¬_¨¯H®sÅñG§h#�Pä(Çzèë }Ok sïsy•'Ž�ur¨Ûo3Ðè®'û{Äÿô üz?·¼Oÿ@×ÿÀW¬¾«>ëï=í¼?òËî;I$H£i‚¢Œ’{ ÏþßÓ?çëÿ!·øW9iâÝJ+ûKÈãR°3|ªT‚?�jxoB²Ôôé&¹W.²”[`ë[C N0s¬Þ��[^Ž*�¶�í{ÿá Òÿçëÿ!·øQÿ —ÿ?_ù ¿Â¬ÿÂ#¥r_ûøhÿ„GJþä¿÷ðÔÛÞ_�Ój>g/§_[A®Ïs,›arû[i9ÉãŠßÿ„ƒKÿŸ¯ü†ßáVáÒ¿¹/ýü4Â#¥r_ûøkZµ0•_4¹¿§*Sww+ÂA¥ÿÏ×þCoð§G®i²È¨—#s £æ*øDt¯îKÿ szö›m¥ê¶Ñ[ Êî9çq©QÂÕ—,¯ò”ݕζŠ(¯8æ (¢€ (¢€ (¢€ «©È*óþ¸?þ‚jÕUÔ¿äyÿ\ÿA4¥³4¥üHú¢—�¿ãÆëþº�å]]ržÿ�¯úê?•uu�ᣧ0ÿyŸõÐ(¢ŠÔâ (¢€8ŸÇÕŸû�üÅ:ûÅ––�l`–F�†a€3Mñ×ü}Yÿ¸ßÌVeŒÜüAh§‰%��òŽ ƒòƼŒej´æ£IÙÊIØÆÖ…¼ÿ2çü&öŸóé7æ(ÿ„ÞÓþ}&üÅuߨzOý,ÿïÂÿ…ØzOý,ÿïÂÿ…_±Ì?çâû�:Òîy§ˆu¨µ—·h¢xü Àî#œãü+q“~bºïì='þ�–÷á±¼S¤éÖÞ¼– h¤P»]"PGÎ;�UV8útå7Qh›Û°ß2êiØêPêÚ4wPU'iV‚)k#Áÿò*¯ývj×®ü-IU¡ ËvŠNè+'Äßò.^º?ô!ZÕ“âoù/?Ýú®º_}N|oûµOð¿È§à¿ùŸúìßÒº*ç|ÿ ÿ]›úWEU_ø’2Ë?Üéú ªZ»´zMË#`�E]ª×ü�îÜþ´¨ÿ>¨ô!ñ#JÐ.µkCqÊ¢‡)†Îxüj÷ü!—¿óûþ=Z~ ÿ�+ÿ×vþBºïÄckB¬£¢ò:*VœdÒ8¿øC/çö/üz�x*ð‹ÈAúíh¬´+÷üúÅC‹ÿ„2÷þbÿǨÿ„2÷þbÿÇ«´¢�í ýÿúÄÏ8»°¸Ñµkh^ã{¶× „ôÝ�é]�sÞ,ÿ‘ŠÏþ¹§þ†ÕÐÕc$ç r{´:Ïš1l(¢Šà9Š( Š( Š( Š­¨Jðé×2Æpé>‡ËiÖÚî«Ëkw)Um§täsYN§+µ®vaðžÖnJ)w;*+™þÂñ7üü¿þš?°¼Mÿ?/ÿ�&—µ—ò³O©SÿŸ±!Óäo¸ÿ~Jë+“_ ë©1™,§$¸›çÞ¦þÂñ7üü¿þšÎœ¥×+:±TiV’j¬U’GMEs?Ø^&ÿŸ—ÿÀ“T/¿¶t‹˜–æî]Íó(óK3Þ­×kWa º3|°¨›;Z(¢·<À®+Çñõgþã1]­q^8ÿ�«?÷ùŠó3�÷I|¿2'ð� è)iAK^™aVæÿ�Tü*¥[›þ=Sð  ”QEcø«þE»Ï¢ÿèb«ø7þEõÿ®�VÕpòìÎÝÇ8ÍwßðˆèÿóÁÿïã�sž*Ñìô¥µ6‘²y…÷e‰Î1Ž¿Z™Ò©ݳl>7 R¢…8Ù¿$d\ß 7Åixc2„m´g÷kÞ·ÿábÇÿ@Çÿ¿Ãü+�¿²“Qñ0´„¨’UŒ)s�þ­kCþþ­ÿ=¬ÿï¶ÿâkÂ…LljÔXe§3è·>Rn\ò·sKþ,ô ûü?Â�øX±ÿÐ1ÿïðÿ Íÿ…«Ïk?ûí¿øš?á_êßóÚÏþûoþ&µöÙ·g÷!^f—ü,Xÿèÿ÷ø…ð±cÿ cÿßáþ›ÿ ÿVÿžÖ÷Ûñ4¿տ絟ýößüMÛ6ìþä™>§ã˜õ 2âÐX2P®ã.qúW?7üŠ�×ôŸúV�ï‚õ+ )®¥–ÔÇî`®ÄãÛå¬é¿äTƒþ¿¤ÿк²©âe™Cë;Ùžfo©Ô¿oÕVÞ=Ôím!·K{B‘"¢–VÉcŸš¥ÿ…‰ªÿϵ—ýðßüUY³ø|.ìmî´ÊùѬ›|Œã#8ûÕ?ü+eÿ ©ÿÀþʾ½Ë }SÆ…ë•r·oXÿ™Ÿÿ UÿŸk/ûá¿øª?ábj¿óíeÿ|7ÿZð­—þ‚§ÿÿû*?á[/ýOþÿöT¹°¿ÕÊö9ßw÷ÇüÌÿøXš¯üûYß ÿÅQÿ UÿŸk/ûá¿øªÐÿ…l¿ô?øÿÙQÿ Ùè*ðÿ²£› ý\=ŽwÝýñÿ3�Òî^óX¿º�(y¡šF Ð â»oÿÈ>çþºÿA\^Ÿkö-sQµß¿ÉŠx÷cÀ#8®ÓÁ?ò¹ÿ®¿ÐVÕíì%o#Ûáþo¨Ï›~gÀé袊òP(¢Š+‹ñ·ü~Z×3üë´®/Æßñùiÿ\Ïó®Ü¿øëæo‡þ": (¢¸ŒŠ( Š( Š(  ½ÿ��úäßʧ¨/ãÆãþ¹7ò¤ö*2ü þ¦ûýäþµ××!àOõ7ßï'õ®¾³¡ü4vf_ïSù~H(¢ŠÔá (¢€8ßu°ÿ¶Ÿû-dXÿÉAƒê?ô]køó­‡ý´ÿÙk"ÇþJ Qÿ¢ëÅÌ?‹ñÄîźQõ™é4QE{GQEVGŠ?äY¿ÿ®ÔV½dx£þE›ÿúçýEaŠþýä'±æ—?ò+Yÿ×Ü¿ú UEÕµ$P«¨]ª¨ÀfέÜÿÈ­gÿ_rÿè)^�aámm:ÖI,�áFc¹¹$zëʪƞ_K™_Cäq8ؼuEFV²�~ÞGšÿljŸô¼ÿ¿íþ4ljŸô¼ÿ¿íþ5ê_ð‰h_ô�þúoñ£þ- þ�ÑÿßMþ5Ûõº_ÊØ8ïùø¾÷þG–ÿljŸô¼ÿ¿íþ4ljŸô¼ÿ¿íþ5ê_ð‰h_ô�þúoñ£þ- þ�ÑÿßMþ4}n—ò‡ö;þ~/½ÿ‘å¿Û§ý¯?ïû�ZÐݤ¼¼wbÌÖÒÄä“Ç5éð‰h_ô�þúoñ®Î$ƒ^Õá‰vÇNª¾€6­iÖ…K¨« –_ˆÂc(:²½äº¿Ôí<ÿ ¹ÿë±ÿÐEtµÍx+þAsÿ×cÿ Šék‹üyk[øŒ(¢Šæ2 (¢€8¯ÿÈRÓþ¹ÿìÕÐ×=ã?ù Z×?ýšºíÄ—ÌÞ§Á¢Š+ˆÀ(¢Š(¢Š(¢Š¯ÿ ë¯úâÿÈÖw�ãÖóýõþF´oÿäuÿ\_ùÎð/üzÞ¾¿ÈÖ2þ,OB�û•OTu´QElyáEP\_Žÿ×XÿºÿÒ»JâüwþºÇý×þ•Ž#ølïË?Þ£óü™´'Š4@ò¢�£†`(ûU¿üüEÿ}Šág°:¿Œɦ1ù‡öîÆ=3í[ð®Wþ‚‡þüöUçlj¨åì©]&ÖélyÎM·doýªßþ~"ÿ¾År>6–9M�—"¾<Ìí9ÇÝ«ÿð®Wþ‚‡þüöT¹_ú ûñÿÙV8·ŽÄQt�+_û˽É|ÍZÆÝ½Õ¸¶ˆâûƒøÇ¥Iö«ùø‹þû�ÿ åè(ïÇÿeGü+•ÿ ¡ÿ¿ý•t,F9+{ü™òìoýªßþ~"ÿ¾Ås_Y^ÓJe ƒæ`ƒþíA«x iz\÷¿ÚO(³ÉÆy®ïzĽb|3¦‚IyÀöá+«.ÆV–24kC•Ù½îyyÔŸÔj'åù£Öl?äkÿ\Sù ±Uì?äkÿ\Sù ±]osÔ§ð/@¢Š)QEy=§ü‡5¯÷&ÿÐÅv¾ ÿ�<ßõðô®*ÓþCš×û“èb»_Èoúø?ú ×­_ýÞ^¨ó²?÷‰�Q^Iè…Q@q^/ÿ�ÝŸýs_ý×k\W‹ÿä7gÿ\×ÿB5Û—ÿäÍðÿÐÑEÄ`QEQEQEWRÿ�UçýpýÕª«©È*óþ¸?þ‚iKfiKø‘õG!¤ø‚ëGŠHíã…öãæ‘¡ÿ Æ£ÿ>ö¿÷ËñU[BðèÖ –_µy>[mÇ—»<}EjÿÂ?è"ïÏÿe\0U¹}Ý�¢¯<¨Õ_‹®Œ§ÿ Æ£ÿ>ö¿÷ËñTÂq¨ÿϽ¯ýòßüU\ÿ„ ÐDÿߟþÊ�ø@ÇýOýùÿ쪹k˜ûL³Ëîe?øN5ù÷µÿ¾[ÿŠ£þ�Gþ}íï–ÿâªçü cþ‚'þüÿöTÂ?è"ïÏÿeG-pö™g—ÜÎ{VÖn5‰"{„‰ `�å‚:ýI«ºWü”cþüŸú¨5ÝûXSíw˜¤çfÜcñ5>•ÿ%ÿ¿'þ€kÏÅs{J|ÛóÄäÍ]7N“¥ðëoÀôZ(¢½ÓÊ (¢€ Ãñ‡üŠ·¿DÿÐÖ·+Æò*ÞýÿCZçÆ»Ôÿ ü…-Žâúê×Ãlv÷D²M1o-ŠçqÓêkN? ø¢HÕ×Qá€#7OX—ÿò.é_õÒæ•ë–Ÿñçýs_å]8 Žž‹Kt|ìp±Åã«F¤�£Ëk;nŽþOÿÐGÿ&Ÿü)²xCÄÓFc–ù]Uk– þ¯G¢º>µ>Ëî:ÞI‡jÎRûÏ7‡Á¾$·M�Þ$iœíK†?€§ÿÂ)âŸúÿäÓÿ…z-}j}�,“•”¥÷žuÿ§Šè#ÿ“Oþ�¥ÝÞ³jv—72Ê©d;–ƒ¨ã?S^­^Maÿ!Mgþ¹Iÿ£º0õGï-­ùœòÁÇ �Ãû9=e­ÙÜx3þ@¯ÿ]Ûù èk‡ðÿˆlô­9­çI™Ì…òŠÆ©ö­oøM4ßùåuÿ|/ÿK†­*Ò”c¡õiMÍ´ŽŠŠçá4Óç•×ýð¿üUðši¿óÊëþø_þ*°ú¥åf~Ƨc¢¢¹ßøM4ßùåuÿ|/ÿGü&šoüòºÿ¾ÿŠ£ê•ÿ•‡±©ØÌñgüŒVõÍ?ô6®†¹ cTƒVÖmg·YUUpÎâ{zëël\\iÓŒ·³.²j1L(¢Šà0 (¢€ (¢€ (¢€)ê¿ò »ÿ®Müª·�¿äsÿ]¿ «:¯ü‚nÿë“*­àoù\ÿ×oè+…/÷)ú£©¢Š+cÏ (¢€ â¬ÿÜoæ+µ®+Çñõgþã1^fqþé/—æDþ´- è)kÓ,*ÜßñꟅT«sǪ~RŠ(  È·yô_ý UÿȾ¿õѪNJ¿ä[¼ú/þ†*¿ƒä__úèÕÒ¿Ý߯èxòÿ‘´Áú�Q\ǰgëŸò¹úæ)¾²µŸFß5´27šÃsÆ íëN×?ä sôÌT¾ÿ�ÿ®­ý+º ¬#·ó~†éÚ‹õ5³,?çÆÛþý/øQý™aÿ>6ß÷é­Q\žÒ}ÌyŸr¯öe‡üøÛߥÿ ?³,?çÆÛþý/øUª(ö“îϹWû2Ãþ|m¿ïÒÿ…qþ!‚+Z$1$k¶3µ�ÇÒ»ªâ|Oÿ#=§û‘ÿèF»02“¨îú3z ¹Q\8QEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@Q@Q@rsÈî?ß_ýWY\œßò;�÷×ÿ@�o³êzvõ?ÂÿC¬¢Š+cÏ (¢€ (¢€9OÇ¥§ýtoå]™ÿ ›?úàŸú®{Çñéiÿ]ùWC¦È&Ïþ¸'þ‚+Ë¡þÿWѾ&Z¢Š+Ô,¶ãÇðþµR­Ÿøñü?­T ¨ë?ò¿ÿ¯wÿÐM^ª:Ïü�/ÿëÝÿôU‰â?ƒ?Gù~ÿ�u×ýuþ‚ºªå| ÿ ë¯úëýuU®'ø¬ãÊ?Ü©ú~¡EV¤QEËZÈá'ûïü�u5ËZÈá'ûïü�vá>Ÿáfôv—¡ÔÑEÄ`QEQEQEQEQEEsÿ³¸ßʱü÷oþ±ÿìÕ±sÿ³¸ßʱü÷oþ±ÿìÕŒÿ‹™èPÿs«ÿnþgcEVÇžQEÇøïîX}dÿÙk°®?ÇrÃë'þËX×þ;²ß÷¨|ÿ&bZÿÈûkõ�ÿE ôºóK_ùm~±ÿè¡^—\9fõ¿ÆÎµ/P¢Š+ÔQE•âOùïÿ뉯2›þEH?ëúOý+Ó|Iÿ"Ýÿýq5æSÈ©ýIÿ %qRÿ‘µ?ð¿ÔòsŸ÷9ú~¨õ]þ@–õíþ‚*íRÑÿä aÿ^Ñÿè"®×|¾&z4…DQEI¨QEå‹ÿ#fµÿo?Ì×YàŸùÜÿ×_è+“_ù5¯ûyþfºÏÿÈ>çþºÿA^µ_÷y|�;#ÿt©þ7ú=Q^Iè…Q@q~6ÿ�ËOúæ�v•ÅøÛþ?-?ë™þuÛ—ÿ|ÍðÿÄGAEW€QEQEQET¿ñãqÿ\›ùTõïüxÜ×&þTžÅCâF_�?Ôß¼ŸÖºúä< þ¦ûýäþµ×Öt?†ŽÌËýê/ÉQZœ!EPãζöÓÿe¬‹ù(0}Gþ‹­u°ÿ¶Ÿû-dXÿÉAƒê?ô]x¹‡ñaþ8�د÷J>¯ó=&Š(¯há (¢€ ÈñGü‹7ÿõÏúŠ×¬�ȳÿ\ÿ¨¬1_ÀŸ£ü„ö<ÒçþEk?úû—ÿAJõ}/þA6_õÁ?ô^Qsÿ"µŸý}Ëÿ ¥z¾—ÿ ›/úàŸú«ÁȺ�¡ãá?äc[Ò?‘nŠ(­d(¢Š+Êaÿ‘“Zú\èUêÕå0ÿÈÉ­}.?ô*ìÁîþG“˜¼á¿Äv> ÿ�\ÿõØÿè"ºZæ¼ÿ ¹ÿë±ÿÐEtµÏãÈöë…Q\ÆAEPã?ù Z×?ýšºç¼gÿ!KOúçÿ³WC]¸�àRù›Ôø"QEqQ@Q@Q@ïÿäuÿ\_ùÎð/üzÞ¾¿ÈÖ�ÿüƒ®¿ë‹ÿ#YÞÿ�[Ï÷×ùÆ_ʼnèQÿr©ê޶Š(­�<(¢Š+‹ñßúë÷_úWi\_Žÿ×XÿºÿÒ±Ä �ùgûÔ~“34ßù(±ÿ¼ßú,ףלi¿òQcÿy¿ôY¯G®¯á«þ7útw~¡EW¨PQE�âÏùï¿Üú¯6¼ÿ‘gNÿ¯‰ÿ’W¤ø³þE{ï÷þ„+ͯ?äYÓ¿ëâä•ÇCþFðÿ ýO#;ÿsŸËóG­XÈ:×þ¸§òb«ØÈ:×þ¸§òb»^ç©Oà^�ER,(¢Šò{Oùk_îMÿ¡Ší|ÿ y¿ëàÿè+\U§ü‡5¯÷&ÿÐÅv¾ ÿ�<ßõðô¯Z¿û¼½Qçdî2ÿ::(¢¼“Ñ (¢€ â¼_ÿ!»?úæ¿ú®Ö¸¯ÿÈnÏþ¹¯þ„k·/þ7É›áþ3¡¢Š+ˆÀ(¢Š(¢Š(¢Š*®¥ÿ «Ïúàÿú «UWRÿ�UçýpýÒ–ÌÒ—ñ#êŠ^ÿ�¯úê?•uuÊxþ•À_ÿÈ»¥×IÿšT  êì¡—L» Œ‚!nJîË)B¦�3¶‡Èb1¸Œ.:«¡ß–ú7Ñv=+þ]þ�ýùð£þ]þ�ýùð¯6þÀÖ?èyÿ~[ü(þÀÖ?èyÿ~[ü+¯ê´›ñAý·˜ÿϵÿ€ËüÏIÿ„×@ÿŸãÿ~_ü(ÿ„×@ÿŸãÿ~_ü+Í¿°5�úÞß–ÿ ?°5�úÞß–ÿ >«Gù¿Ûy�üû_ø ¿ÌôŸøMtùþ?÷åÿ¸-2E–ÿW‘UàvÔ©ÿ`kô ¼ÿ¿-þ>†¬’ê*À†[VÇzVÔ©BŸÂï·æ<>;ŠÇPUãkKMüÍ;-PÔ`3ZÀ0Ûs½G?‰÷«ð‹kóè?ïê�t¾ ÿ�+ÿ×vþBº+æiÔpIiýw>î¦"Q“HóŸøEµ�ùô÷õ?Æ�øEµ�ùô÷õ?ƽŠÇûR·eøÿ™ZŸ‘ç?ð‹kóè?ïê�ð‹kóè?ïê�z5jVì¿ó­OÈòùtû�;P‚¨ö;`7ÆqÛé]åsÞ,ÿ‘ŠÏþ¹§þ†ÕÐÒÇTu!Noªb¯'%Š(¯<ç (¢€ (¢€ (¢€)ê¿ò »ÿ®Müª·�¿äsÿ]¿ «:¯ü‚nÿë“*­àoù\ÿ×oè+…/÷)ú£©¢Š+cÏ (¢€ â*ÿŸæÿÀ¦¨gðwˆnH3Ì’•èdœ¶?:ôš+©å$¬å/¼|ˆóÏøF|Uÿ?Íÿ�MGü#>*ÿŸæÿÀ¦¯C¢ŸöMæ—Þˆó-GHñ™c%ÝÅôžRc;nXžHÖº¯ ÝOyáx$¸‘¤�;.æ9$q“RøÏþE[ϪèkU<%ÿ"œ?õÕ¿�eBŠÃ㽜[k–ú¿1%iXÕ¢Š+Ù41üUÿ"ÝçÑô1Uüÿ"úÿ×F«*ÿ‘nóè¿úªþ ÿ‘}ë£WJÿw~¿¡ãËþFÑÿêtQEsÁŸ®Èçè?˜©|ÿ 3ÿ][úTZçü�n~ƒùŠ—Áßò?õÕ¿¥vÇýÍÿ‹ô7_Á~¦ýQ\FEP\O‰ÿäg´ÿr?ý×m\O‰ÿäg´ÿr?ý×nø¯Ñ›áþ/‘ÑQEÄ`QEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPEPEP\œßò;�÷×ÿ@ÖW'7üŽãýõÿÐc[ìúž†]½Oð¿Ðë(¢ŠØóŠ( Š( SÇñéiÿ]ùWC¦È&Ïþ¸'þ‚+žñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šòè¿ÕôD/‰–¨¢Šõ -Ÿøñü?­T«gþ<ëU(ª:Ïü�/ÿëÝÿôWªŽ³ÿ Kÿú÷ýÕCâF8�àÏÑþF�äuÿ] ®ª¹_ÿÈ:ëþºÿA]Uk‰þ+8ò�÷*~Ÿ¨QE�éQ@rÖŸò8Iþûÿ#]MrÖŸò8Iþûÿ#]¸O†§øY½¥èu4QEqQ@Q@Q@Q@Q@\ÿǬßî7ò¬ýÛÿ¬û5l\ÿǬßî7ò¬ýÛÿ¬û5c?âÇæz?ÜêÿÛ¿™ØÑE±ç…Q@qþ;û–Y?öZì+�ñßܰúÉÿ²Ö5ÿ†Îì·ýê?ɘ–¿ò>ÚýcÿÑB½.¼Ò×þGÛ_¬ú(W¥×Y½oñ³ƒíKÔ(¢ŠõQEex“þE»ÿúâkÍ%�ÛÂ8RUoŸq�”LW¥ø“þE»ÿúâkÀÿò-\ÿ×ÑÿÐR¼þ~LΜ¿ºÎÆåq~6ÿ�ËOúæ�lÂ[¤ÿÏY?ïÙ®kÄÚ¥®©snö¬ÌH9\w®¼ �¬œ¢Ò5¡ )¦ÑÖÑEæœÁEPEPEPQÜFe¶–1€] ŒûŠ’Š��Î:ÎÇÄ:võ´FŒ9ù¶ºs�©«[üYÿ=$ÿ¾’ºz+A-g£,ÊRw”"ß§ü˜ßâÏùé'ýô•Pj¾!7¿c2}£8Ùòúg¯Jì«“‹þGsþû袥>[Y½YцĪª|Ôã¢ob]þ,ÿž’ßIFÿÏI?冷žŠÓØÿyœ¿Úþ}Çîÿ‚q×zˆ5Œ]£I³;K:qž½µ6ÑJ|D‰OU`?òvuÃ\^ŧxñ®çÝåFùm£'îcú×™˜Â4•97öÖÿ3›‹•xÆ-$—cÓh®cþÍþžïßÿ^�øO4oúyÿ¿ýzíþÐÂÿÏÅ÷œÜ˹ÓÑ\Çü'š7ý<ÿß¿þ½ðžhßôóÿ~ÿúôhaçâûÙw:zÈñGü‹7ÿõÏúŠÏÿ„óFÿ§Ÿû÷ÿתߌ4»ýêÖ?Ì•0»“¯Ö²Äc°Ò£4¦¯gù’±ÉÜÿÈ­gÿ_rÿè)^¯¥ÿÈ&Ëþ¸'þ‚+Ê.äV³ÿ¯¹ô¯WÒÿäeÿ\ÿAÛ‚ÿ‘uCÈÂÈÆ·¤"ÝQZÈQEW”Ãÿ#&µô¸ÿЫի̴¨’jqH2ŽÓ©ú®¼,¹y›<ŒÅÛ†Þ7¼'¨ÙÙéÓ%ÍÌq1— 1ÆFoÿnióÿýõ\ÿü"Ö_óÚãþúáGü"¶_óÚãþúá[UxZ“srzùA7JR½ÙÐnióÿýõGöæ—ÿ?ðßUÏÿÂ+eÿ=®?ï¡þ‹i¦Ãq­ËdÎâ4g‚3ÁúQ >iµ' F�)&Óz×öæ—ÿ?ðßTnióÿýõ\ÿü"¶_óÚãþúáGü"¶_óÚãþúáYòa?™ýÄòÑîÊž*¼·¼Ôm^Úd•U0JœàæºzÅ�ÃI"·™;`ç†é[T±5)Ê…7µÅVQi(ô (¢¸ÌBŠ( Š( Š(  ÷ÿòºÿ®/ü�gxþ=o?ß_äkFÿþA×_õÅÿ‘¬ïÿÇ­çûëü�c/âÄô(ÿ¹TõG[EVÇžQEÅøïýu�û¯ý+´®/Çë¬ÝéXâ?†Îü³ýê??É™šoü”XÿÞoýkÑëÎ4ßù(±ÿ¼ßú,×£×WðÕÿý:;¿P¢Š+Ô((¢ŠÆñgüŠ÷ßîýW›^ȳ§×ÄÿÉ+Ò|Yÿ"½÷ûƒÿBæ×Ÿò,éßõñ?òJã¡ÿ#x…þ§‘�ÿ¹Ïåù£Ö¬?äkÿ\Sù ±Uì?äkÿ\Sù ±]¯sÔ§ð/@¢Š)QEy=§ü‡5¯÷&ÿÐÅv¾ ÿ�<ßõðô®*ÓþCš×û“èb»_Èoúø?ú ×­_ýÞ^¨ó²?÷‰�Q^Iè…Q@q^/ÿ�ÝŸýs_ý×k\W‹ÿä7gÿ\×ÿB5Û—ÿäÍðÿÐÑEÄ`QEQEQEWRÿ�UçýpýÕª«©È*óþ¸?þ‚iKfiKø‘õE/Ç�×ýuʺºå< ÿ7_õÔ*êë:ÃGNaþó?ë QE©ÄQEq>:ÿ�«?÷ùŠ¡¥ÉF?ïÉÿ ¿ã¯øú³ÿq¿˜®kQ½¸ÓüOsuk'—2Hv¶Ðq‘ƒÁã½xY•ENq›ÙI3·í…¡óüÏ[¢¼£þ-þÿò üMð™kÿóÿÿ�cÿâjÿ·pßË/¹™ç{Dz½åð™kÿóÿÿ�cÿâhÿ„Ë_ÿŸÿüƒÿGöîùe÷/óh�W¬?È«{ôOý k„ÿ„Ë_ÿŸÿüƒÿP^x›W¿µ{[›¿2ÆåòÐg=@ÏQX×ΰõ)J ;´×NÞ ê&ˆïÿä]Ò¿ë¤ÿÍ+×-?ãÎúæ¿Ê¼ŽÿþEÝ+þºOüÒ½rÓþ<àÿ®kü«ÝÂȾ‡¡å`¿ßñöïäMEUžÈQEW“XÈSYÿ®RèůY¯&°ÿ�¦³ÿ\¤ÿÑ‹]¸-ßËó<¬oûæüOô;�Èÿë»!] sÞ ÿ�+ÿ×vþBºËüyzžÍo�…Q\æaEPâÏù¬ÿëšèm] sÞ,ÿ‘ŠÏþ¹§þ†ÕÐ×n'øT½ êü (¢¸ŒŠ( Š( Š(  z¯ü‚nÿë“*­àoù\ÿ×oè*Ϋÿ ›¿úäßÊ«xþA—?õÛú Æ_ÅG¡KýÊ~¨êh¢ŠØóŠ( ¸�ÿÈBÏþ¹Ÿç]½q7ÿ�…Ÿýs?αÄ ž†Wþò¾‘KEÿ’‰/ûòÿ#^‰^w¢ÿÉD—ýù‘¯D®«øu?ÄÿĊP¢Š+Ô,(¢ŠÁñŸüŠ·ŸTÿÐÖªxKþE8ë«:·ã?ùo>©ÿ¡­szˆbÑ<+d�LóI!6úþ5樹fiG~OÔç­Z�êTvH먮?þÈÿèß÷÷ÿ­Gü'‘ÿÐ=¿ïïÿZ½ŸªÕìqÿm`ççàÿÈØñWü‹wŸEÿÐÅWðoü‹ëÿ]°µo&§¦Mf,Ú3&>c&q‚§µG¢ø¥4�8Z›F”†-¸>:þº¡SØòÛ[žl³<+Ìnw–׳Þþ‡ Ñ\ü'‘ÿÐ=¿ïïÿZ�øO#ÿ {ßßþµaõZ½�Kûkÿ??þGA®Èçè?˜©|ÿ 3ÿ][úW<|Gµ¦^Â-ÚHÃrÛ�€þµÐø;þ@gþº·ô®‡ CÔ¿›ô=\=zuðÞÒ“º¹¿EW‚Š( ¸ŸÿÈÏiþäú®Ú¸ŸÿÈÏiþäú®Üñ_£7Ãü_#¢¢Š+ˆÀ(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( ¹9¿äwï¯þ€+¬®NoùÇûëÿ  Æ·Ùõ= »zŸá¡ÖQE±ç…Q@Q@§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€"¹ÿ�Y¿Üoå\¯†uË]]}¥%o7nß,Ó=rG­uõ@èºi$›8¹ö¬ªBNJQèwaq¡Ntê¦Ô­·�Ÿð›iŸóÆëþø_þ*�øM´Ïùãuÿ|/ÿKý‰¦ÿÏœtbi¿óç+VîŠçÀÿ,¾ñ?á6Ó?ç�×ýð¿üUð›iŸóÆëþø_þ*¹Ãgoÿ gÙ|¥ò7cgo»šé?±4ßù󎢫+Ù­ ëSÁRå¼^ªû÷þm3þxÝß ÿÅV‰µË]am…²J¾QmÞ`®= ô®ƒûMÿŸ8è.š?c‹�jr…Y+6‰£ˆÁÑšœ#+£—µÿ‘ú×ëþŠéuæÄ—Zo‹Úú+rÛ ²eNÖùíWá:Õÿèýðÿã^FK :°©{¹>‡�ι�ûž…Eyïü'Z¿ýàÿ¾üiÇÚªc}�ºçÕXZëþØÂ÷ps£Ðè¯=;ÕÈÈÓà#ýÇÿ?á:ÕÿèýðÿãGö¾»û˜s£­ñ'ü‹wÿõÄÖ�ÿäZ¹ÿ¯£ÿ ¥c_ø¿T¿±šÒK•%]¤ª6Gë[¾ ‚X|5?›&û‚˸c# 3ùƒXRÄÃŽŒéÞÊ/ “¼´6h¢ŠöÍ ýsþ@WßõÅ¿•cøþAWõÜÿè"¶5Ïù_×þU�àoù\×sÿ Šé�ð%êxõ¿äiOü,ê(¢Šæ=�Ddp °Á¸¬ïì 3þ}ò#�iQW “‡ÂÚ)JQÙ™¿ð�éóëÿ‘ühÿ„KÿŸ_üˆßãZTUýb·ó¿½�ÚO»8ëKi|E-«Ç˜œÜ{tç­oÿÂ?¥ÿϯþDoñ¬‹ù¦ÿ~Oë]Muã+TŒ£Ë&´]M«NI«>†oü#ú_üúÿäFÿUÐtÄ`ÂÔdŒ»ëZ4W'Ö+;ûÙ�´ŸvQEb@QEQEQEQEQEW'üŽçýöÿÐ u•ÉÅÿ#¹ÿ}¿ôXÖû>§¡€Ú¯øYÖQE±ç…PºÑ´ëÙÌרò‚Ù ŸÊ¯ÑQ:pš´ÕטXÊÿ„oHÿŸ$ÿ¾›ühÿ„oHÿŸ$ÿ¾›ükVŠËê”?‘}ÈVG âÝ6ÏO[Ck‹y}Ø$çÇ_­oÛx{I{H]¬Ð³"’wN>µ•㯹cõý–º›?øñ·ÿ®kü«Î¡‡¤ñµ¢â¬¹z.Ä$¹™Cþ½#þ|“þúoñ£þ½#þ|“þúoñ­Z+Ñú¥ä_r.Èä|oioe¥i�ÛD±FÎÕõÀ®ßKÿ�M—ýpOýW?âíëWÓlÍ BбܬØÈ …`&ŸâøãTK¹U \ ù×¥BTcÒ±àÎ¥\6:­EJRRJÖ]‘éTW›ý‹Æ?óû7þõ꘼[im%Ä×ӈ㘋ŒñIaÓÓ�K5©wBvô=:ŠòÍ>_j�4Ö·ó²+l$ÏŽpõ«bñ�üþÍÿ�ýz'g$(fòœT¡Bm?#Ò+ÍtOùµ÷æÿÐéßbñ�üþÍÿ�ýz±áÝ Q³Õä½¾Ûó+dïÜY‰ÎjãÓ„½äîŒ*Ö­ŠÄQµ)EFWm£¬¢Š+Œú®[Lÿ‘®çýù?�u5ËiŸò5Üÿ¿'ó®Ü'ÁSÐÞ—Ã/C©¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š¯ÿ ë¯úâÿÈ× eª^éêëipÑ9`9ü뻿ÿ�u×ýqäkœðƇg«Ap÷>fc`ÆÇQ\µÔ¥4£¹ìåÕ)Ó¡9UWWEøIu�ùþûåÂ�øIu�ùþûåÂºßøC4¯úoÿ}ÿõ¨ÿ„3Jÿ¦ÿ÷ßÿZ£ÙVïø�^Àÿ'àŽKþ]cþŸþù_ð£þ]cþŸþù_ð®·þÍ+þ›ÿßýj?á Ò¿é¿ý÷ÿÖ£ÙVïø‡×°?Éø#’ÿ„—XÿŸçÿ¾Wü*¥î£w¨7s™Jgn@ÏÒ»�øC4¯úoÿ}ÿõ«œñ>�k¤Il¶Ûñ bÛÛ=1þ5§QFòzá±XJ•iÆÏÑ Óä¢Çþóè³^�^q¦ÿÉE�ýæÿÑf½³Êþ¿ã¡ò±Ýú…Q^¡AEP7‹?äW¾ÿpèB¼ÚóþE�;þ¾'þI^“âÏùï¿Üú¯6¼ÿ‘gNÿ¯‰ÿ’WùÃü/õ<ŒïýÎ/͵aÿ ë_úâŸÈUНaÿ ë_úâŸÈUŠí{ž¥?�zQH°¢Š(Éí?ä9­¹7þ†+µðWü�æÿ¯ƒÿ ­qVŸòÖ¿Ü›ÿCÚø+þ@ó×ÁÿÐV½jÿîòõG�‘ÿ¸ËüLè袊òOD(¢Š+Šñü†ìÿëšÿèF»Zâ¼_ÿ!»?úæ¿ú®Ü¿øß&o‡øÎ†Š(®#¢Š(¢Š(¢Š(ªº—ü‚¯?ëƒÿè&­U]KþAWŸõÁÿôJ[3J_Ä�ª)xþ3ÿ‘VóêŸú×�ê?òÒ~³èB½Æò*Þ}SÿCZó½Gþ@OÖoýW&þFñÿêÏ<ÿsŸËóGªÅ¦ØP›+oº?å’ÿ…?û2Ãþ|m¿ïÒÿ…OúˆÿÝÊŸ]¼Ï¹êF”,½ÔUþ̰ÿŸoûô¿áGöe‡üøÛߥÿ µE.gÜ~Êʾâ¯öe‡üøÛߥÿ ?³,?çÆÛþý/øUª(æ}ÃÙCùWÜy˜¸ÕÀ#€?ë¢×{àïùŸúêßÒ¸=7þ>u�úæôb×yàïùŸúêßÒ½\Gû»õ_‘őȻþÞfýQ^Iè…Q@q>'ÿ‘žÓýÈÿô#]µq>'ÿ‘žÓýÈÿô#]¸â¿Fo‡ø¾GEEW€QEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¤ò¨‘‡”§óWk:_õ¯þñ ùÉÿ:û–?WÿÙk©³ÿ�úæ¿Ê¼¼?ûõoHþD/‰—<äÿž+GœŸóÅj+Ô,¼Î°m€Œ*¿œŸóÅjWÿ�!ôR€&ó“þx­fx†U>¾%º<ÕÚÍñü€/ë‘«§ñ¯SŸü ú?ÈÎðŠº$àÆ­þ’ÜŸ÷VºŸ9?çŠ×'àoùÍÿ_ÿAZéªñőϕ¹Sô&ó“þx­rϨh¬O@›ÎOùâ´yÉÿx�¥ÅÿÂĶÿ |¿÷ð…ð±-¿è/ýüáGö¦ùÿþAÏoÅŸò+߸?ô!^myÿ"Î�ÿ_ÿ$®ƒXñ¬ž“qf¶rFÒ€Aþ•ÏÞȳ§×ÄÿÉ*p8ŠuóXJ›ºå©äçM<íåù£Ö¬?äkÿ\Sù ±Uì?äkÿ\Sù ±^›Üõiü Ð(¢ŠE…Q@Qfq®k|g1Íÿ¡Ší<ÿ y¿ëàÿè+\U§ü‡5¯÷&ÿÐÅZ±ÖïôØYB#6â Îïô¯mÑ•j.ßC‡‡àç‚’_ÌÏN¢¼ïþ½_þ~þý¯øQÿ ^¯ÿ? ÿ~×ü+—û2·uý|�_ê³=Šó¿øJõùø_ûö¿áGü%z¿üü/ýû_ð£û2·uý|ƒê³=¸¯ÈrÏþ¹¯þ„j‡ü%z¿üü/ýû_ðªw�Î¥{ ·NÔ…(gÚº0Ø*”jsÉ«R¡(Jìô/9?çŠÑç'üñZ†ŠñŽ"o9?çŠÑç'üñZ†Š›ÎOùâ´yÉÿ¬ÿÜoæ*Ž˜sñ �1óÉÇüÕïÇÕŸû�üÅPÒ¿ä£÷äÿÐ x¸ïãSÿNìgûµŸæz-Q^ÑÂQE‡ãùo~‰ÿ¡­nVŒ?äU½ú'þ†µÏŒÿw©þù [sÿ"î•ÿ]'þi^¹iÿp×5þUäwÿò.é_õÒæ•ë–Ÿñçýs_åZá?ä_CÐñð_ïø�ûwò&¢Š*Ïd(¢Š+É´ó�OZã9†OÃ÷‹^³^Maÿ!Mgþ¹Iÿ£»p[¿—æyXß÷Ì7øŸèw ÿ�+ÿ×vþBºç¼ÿ Wÿ®íü…t5–/øòõ=šß (¢¹ÌŠ( +Å|xŽÏþ¹§þ†ÕÓùÉÿ©ÿ¡­yÞ£ÿ 'ë7þ„+“ ÿ#xÿƒõg�ž¹Ïåù£×áÿQû£ùSé�ÿ¨�ýÑü©õÖ{ÙQ@Š( %Ó.5ž3˜�áûÅ®ïÁßò?õÕ¿¥pzoü|ëõÌÿèÅ®çÂ"è„3¨>kpOÒ½lGû»õ_‘çd_ò.ÿ·™ÑQLó¢ÿž‰ÿ} <è¿ç¢ßB¼«3Ѱú)žt_óÑ?ï¡G�üôOûèQf\O‰Ž©ÿ¡­yÞ£ÿ 'ë7þ„+ѺÏb; ¢Š(QEäšoü|ëõÌÿèŦSôßøùÖ?ë™ÿÑ‹]·„­mæÑKINÞk ²{W¼«ªÜÚ¾¿¡Åõ90þó8j+Õ¾Ãgÿ>°ß±GØlÿçÖûö+?íXÿ)í}mv<¦Šõo°ÙÿϬ÷ìQö?ùõƒþýŠ?µcü¡õµØòššÏþ?mÿë¢ÿ:õ°ÙÿϬ÷ìWâ8£‡Ä¶‹j‹¶3…xÖ”±Ê³pQ¶Œ¸WSv±ÒÑEàžxQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@Q@Q@rsÈî?ß_ýWY\œßò;�÷×ÿ@�o³êzvõ?ÂÿC¬¢Š+cÏ (¢€ (¢€9OÇ¥§ýtoå]™ÿ ›?úàŸú®{Çñéiÿ]ùWC¦È&Ïþ¸'þ‚+Ë¡þÿWѾ&Z¢Š+Ô,¶ãÇðþµR­Ÿøñü?­T ¨ë?ò¿ÿ¯wÿÐM^ª:Ïü�/ÿëÝÿôU‰â?ƒ?Gù~ÿ�u×ýuþ‚ºªå| ÿ ë¯úëýuU®'ø¬ãÊ?Ü©ú~¡EV¤QEËZÈá'ûïü�u5ËZÈá'ûïü�vá>Ÿáfôv—¡ÔÑEÄ`QEQEQEQEQEQEQErgþGøþÉ]ergþGøþÉ]ecGízž†aÿ.¿Â‚Š(­�<(¢Š+’ñÏú‹/÷Ÿù ëk’ñÏú‹/÷Ÿù óó_÷9ü¿4Lþ¤Óÿäkÿ\Sù ³U´ÿùÚÿ×þB¬×m?�z‚­·üx� þuR­·üx� þu`T¢Š(?\ÿ�÷ýqoåXþÿ�UÇýw?ú­�sþ@WßõÅ¿•cøþAWõÜÿè"ºcü zž=oùSÿ :Š(¢¹�`(¢Š(¢Šå¬?än›ýù?­u5ËXÈÝ7ûòZêk·ñÇü(Þ¾ëÐ(¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ äâÿ‘Üÿ¾ßú®²¹8¿äw?ï·þ€kßgÔô0Uÿ :Ê(¢¶<ð¢Š(¢Š(�ñ×ܱú¿þË]MŸüxÛÿ×5þUËxëîXý_ÿe®¦Ïþ+øô‘—àoùÍÿ_ÿAZé«™ð7ü�fÿ¯ƒÿ ­tÕx�âÈçʿܩúQXž€QEW-¦È×sþüŸÎºšå´Ïùîß“ù×nà©èoKá—¡ÔÑEÄ`QEQEQEQEQEW¿ÿ�u×ýqäk;À¿ñëyþúÿ#Z7ÿòºÿ®/ü�gxþ=o?ß_äk'¡Gýʧª:Ú(¢¶<ð¢Š(®/Çë¬Ýé]¥q~;ÿ]cþëÿJÇü6wåŸïQùþLÌÓä¢Çþóè³^�^q¦ÿÉE�ýæÿÑf½¸r¿†¯øßèyÑÝú…Q^¡AEP7‹?äW¾ÿpèB¼ÚóþE�;þ¾'þI^“âÏùï¿Üú¯6¼ÿ‘gNÿ¯‰ÿ’WùÃü/õ<ŒïýÎ/͵aÿ ë_úâŸÈUНaÿ ë_úâŸÈUŠí{ž¥?�zQH°¢Š(Éí?ä9­¹7þ†+µðWü�æÿ¯ƒÿ ­qVŸòÖ¿Ü›ÿCÚø+þ@ó×ÁÿÐV½jÿîòõG�‘ÿ¸ËüLè袊òOD(¢Š+Šñü†ìÿëšÿèF»Zâ¼_ÿ!»?úæ¿ú®Ü¿øß&o‡øÎ†Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(®NËþG)ß“ùë+“²ÿ‘Ê_÷äþF±­¼}OCðUÿ :Ê(¢¶<ð®sQðŒ7÷ÒÝ §ŒÈrW`<þuÑÑX×ÃÒ¯ZªèM'¹É üÿ¿ýûãGü ÑÏûÿß±þ5ÖÑ\¿ÙX?äü_ù‹’'›ëÚ"èϬæ_4ÊãÇøÖÒx"&Eo·?#?êÇøÔ^9ÿ]eþëÿJì"ÿRŸîŠàÃà0óÅU§(é[~¨•vr¿ðƒEÿ?ïÿ~ÇøÑÿ4_óþÿ÷ì�u´WöVù?þerDá|]¦G¤iºE¬nΚś¹;+Ò-?ãÎúæ¿Ê¸_ˆŸsJÿvOý’»«Oøóƒþ¹¯ò¯YÂ0ÃÓŒU’¹äàÿäaˆÿ·"j(¢±=€¢Š(¯&°ÿ�¦³ÿ\¤ÿÑ‹^³^Maÿ!Mgþ¹Iÿ£»p[¿—æyXß÷Ì7øŸèw ÿ�+ÿ×vþBºç¼ÿ Wÿ®íü…t5–/øòõ=šß (¢¹ÌŠ( +ÅŸò1Yÿ×4ÿÐÚºç¼Yÿ#ŸýsOý «¡®ÜOð©zÕø"QEqQ@Q@Q@õ_ùÝÿ×&þU[Àßò ¹ÿ®ßÐU�WþA7õÉ¿•Vð7üƒ.ë·ôŒ¿Š�B—û”ýQÔÑE±ç…Q@q7ÿ�…Ÿýs?λzâ·Ÿ÷ÊÿñUË/‚uÖPÂÚ<‘ûÕÿ_øAõßùö�þþ¯ø×Ñ{,7ÄòV;8·Àÿð¨ÿ…‰¥ÿÏ­çýò¿üUð±4¿ùõ¼ÿ¾WÿŠ®_þ}wþ}£ÿ¿«þ4®ÿÏ´÷õÆ�e†ïø�ëÙÇò?üê?ábióëyÿ|¯ÿGü,M/þ}o?ï•ÿâ«—ÿ„]ÿŸhÿïêÿ�ðƒë¿óíýý_ñ£Ùa»þ!õìãùþA¤¸–MV@ aŸy»ÿÈ ÿ×Vþ•çÚ*ÿ´Ñ¾òÁƒõÞµè>ÿ�ÿ®­ý+\Oð%ê¿#ÝÈoý›¯ó3~Š(¯$ô‚Š( ¸ŸÿÈÏiþäú®Ú¸ŸÿÈÏiþäú®Üñ_£7Ãü_#¢¢Š+ˆÀ(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( ¹9¿äwï¯þ€+¬®NoùÇûëÿ  Æ·Ùõ= »zŸá¡ÖQE±ç…Q@Q@§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€93ÿ#¿üÿd®²¹3ÿ#¿üÿd®²±£ö½OC0ÿ—_áAEVÇžQEÉxçýE—ûÏü…uµÉxçýE—ûÏü…yù¯ûœþ_š& Òiÿò µÿ®)ü…YªÚüƒmëŠ!Vk¶ŸÀ½ AVÛþ‚ªU·ÿ�!ôR€ Íñü€/ë‘­*Íñü€/ë‘«§ñ¯SŸü ú?ÈËð7ü�fÿ¯ƒÿ ­tÕÌøþ@³×ÁÿÐVºj¼Gñdså_îTýŠ(¬O@(¢Š+–Ó?äk¹ÿ~Oç]MrÚgü�w?ïÉüë· ðTô7¥ðËÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€!»�¥³ž4åž6Qõ"¹+¯ik"ZA"9o݆Î>µÙÑYΟ3Nö:ðø·F.©§Üæ?µ|SýÉ?ïÂÿ…Ú¾)þäŸ÷áºz*=‹þfkõèϨýÇ"XP3]¥n…ôrgæ•þìŸû%wVŸñçýs_å\—�ô›ÝFÛO’Ò(ˆ0pÈÈ\#YI}ãdEEó¨ÀT]?*ìäU)E&•®|ûÄK Ž­9S“R嵕öG¤Q^sý¡ã�Y?ïÌ_áQ\k2µ�¦žGHÓ–c |~•Voí/¼èyÌ»¥;‡þ étW™Zëž0¾‡Î¶™ä�8Ü!�¯åSÿhxãÖOûóøPðÍhä¾ñG:„—4iM¯ðÿÁ=¼šÃþBšÏýr“ÿF-iÿhxãÖOûóøUM?JÔm—R»½€Æ l|ÌYOAô5ч‚¦õ’Öß™‹Ä¼^2‡%9.Ykuc°ðgü�_þ»·òÐ×#á}VÆËJx®nR72–ÚsÓ¶ÿá!Òçú?×ü+,U*Ž´š‹ß±ôµa'7diÑYŸð�é?óýëþÂC¤ÿÏô¯øV¯ò¿¸Ï’]�:+3þ'þ£ýÂ�øHtŸùþ�õÿ =…_åprK±Îø³þF+?úæŸúWC\·ˆo-ïµÛI-¥Y")#×qÿêk§š¥M>ƵU£…Q\&EPEPEP=WþA7õÉ¿•Vð7üƒ.ë·ôgUÿ�MßýroåU¼ ÿ ËŸúíýc/â£Ð¥þå?Tu4QElyáEP\G�ÿä!gÿ\Ïó®Þ¸�ÿÈBÏþ¹ŸçXâ?†ÏC+ÿy_?Èç.ôùõO]ÚÛ2´®@c�Ç5kþmkþyÃÿE\Ñä¢Kþü¿È×¢W…„ËhâyçR÷æhò£÷<¿þmkþyÃÿEðƒk_óÎûú+Ô(®¿ì<7w÷ÿÀ+Ù£ËÿáÖ¿çœ?÷ôQÿ6µÿ<áÿ¿¢½BŠ?°ðÝßßÿ=š<—P𮩦YIwr‘ˆ“Џ'“�ëUõùi?Y¿ô!^‰ã?ùo>©ÿ¡­yÞ£ÿ 'ë7þ„+L³ 6h¡OnVõõ<|í[?—æ�_‡ýDî�åO¦Cþ¢?÷Gò§×¨{QÙQ@Š( %Ók�`Iò˜ÿäE­­Ä­¤Ù}˜Z‰~rÛ¼Ìuü*§„äb¿ÿqÿô1]§“üóOûäW©S^œãu£ÞÝ7 ©‚å’¾¬Æÿ„á¿è?ïïÿZ�øNþ�ãþþÿõ«gÉ‹þy§ýò(òbÿžiÿ|ŠÃÛa¿ç×âÏgž—òþ&7ü' ÿ@ñÿúÔÂpßô÷÷ÿ­TtV×nƒ( #ðGûBº&/ùæŸ÷È­«¼5òû;üÙu=œ¹þ†ÿ xÿ¿¿ýjÈ»ÔÛYÖígò|² &ÐÛº6}=ë°òbÿžiÿ|ŠQ)Ê¢ƒêD1Ta¬)Ùú’ªÂ:Æ?ˆê(¢¼óœ(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( ¹9¿äwï¯þ€+¬®NoùÇûëÿ  Æ·Ùõ= »zŸá¡ÖQE±ç…Q@Q@§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š¯~Jé÷$XÅ]¤zi]ؗ΋þz§ýô)<ø¿çªßB¹=ÃçY†Y>Óäùl7gõ©ÿ1ÿ €ÿ¿?ý•wÏ Bq•M} åJœ]œ¿cÏ‹þz§ýô+˜µu.‘‹ »ßœñÐÕÿøA�ýýùÿì¨ÿ„ÿÐ@ߟþÊ®—Õ©©/iº¶Ì¨{(ßÞßÈØóâÿž©ÿ} <ø¿çªßB±ÿá?ô÷çÿ²£þcÿAÿ~û*ÇØá¿ççàÈä¥üß�²&ˆœ “Ø0§×­hÇE–ûGšd‚n1øšì×î�¥F"„iÆ2„®�ÿjSQI§{‹EW)�QEQEQEQEQEÉŸùÿàû%u•ÉŸùÿàû%u•�µêz‡üºÿ (¢¶<ð¢Š(®KÇ?ê,¿Þä+­®KÇ?ê,¿Þä+ÏÍÜçòüÑ3øN“Oÿ�m¯ýqOä*ÍVÓÿäkÿ\Sù ³]´þèR ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÕ�RŠ( n­’òÖ[y •J¶Þ¸5_KÒmô‹w†Ý¤*í¼ï œãžÕzŠ®gn^†nŒEQ¯yu (¢¤Ð(¢Š(¢Šå¬?än›ýù?­u5ËXÈÝ7ûòZêk·ñÇü(Þ¾ëÐ(¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ äâÿ‘Üÿ¾ßú®²¹8¿äw?ï·þ€kßgÔô0Uÿ :Ê(¢¶<ð¢Š(¢Š(�ñ×ܱú¿þË]MŸüxÛÿ×5þUËxëîXý_ÿe®¦Ïþ+øô‘—àoùÍÿ_ÿAZé«™ð7ü�fÿ¯ƒÿ ­tÕx�âÈçʿܩúQXž€QEW-¦È×sþüŸÎºšå´Ïùîß“ù×nà©èoKá—¡ÔÑEÄ`QEQEQEQEQEQEQErvßò:·ûïÿ šë+“¶ÿ‘Õ¿ßý×YXÐÙúž†cñSÿ ýBŠ(­�<ã¬ä¤�úèßú,×¢×�XÿÉIõÑ¿ôY¯E¯/+Ú¯øßèD:…Q^¡aEP7‹?äW¾ÿpèB¼ÚóþE�;þ¾'þI^“âÏùï¿Üú¯6¼ÿ‘gNÿ¯‰ÿ’WùÃü/õ<ŒïýÎ/͵aÿ ë_úâŸÈUНaÿ ë_úâŸÈUŠí{ž¥?�zQH°¢Š(Éí?ä9­¹7þ†+µðWü�æÿ¯ƒÿ ­qVŸòÖ¿Ü›ÿCÚø+þ@ó×ÁÿÐV½jÿîòõG�‘ÿ¸ËüLè袊òOD(¢Š+Šñü†ìÿëšÿèF»Zâ¼_ÿ!»?úæ¿ú®Ü¿øß&o‡øÎ†Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(®NËþG)ß“ùë+“²ÿ‘Ê_÷äþF±­¼}OCðUÿ :Ê(¢¶<ð¢Š(¢Š(ŒñÏúë/÷_úWaú”ÿtWãŸõÖ_î¿ô®Â/õ)þè¯/ þû_þÝüˆ_EW¨Yn_øôO ª•n_øôO ª”VO‰¿ä\¼ÿtèBµ«'Äßò.^º?ô!WKã�©Í�ÿv©þùüÿ ÿ]›úWE\ï‚ÿäë³J誫ÿFYgû�?Dð%Ì ƒ(㤢³M§twlbÂ/aýùÿï¡þÂ/aýùÿï¡þ·EoõºÿÌÍ=´û˜Ÿð‹Ø~ûè…béºl7z´ö²¦ì<ðq]­rÚ'üŒw_GÿÐ…uáñeN£rÙS©76Ëßð‹Ø~ûè…ð‹Ø~ûè…mÑ\Ÿ[¯üÌÇÛO¹�†ìa™$f*A˜cùVÅVu*Φ³w&S”·aEVd…Q@Q@Q@õ_ùÝÿ×&þU[Àßò ¹ÿ®ßÐU�WþA7õÉ¿•Vð7üƒ.ë·ôŒ¿Š�B—û”ýQÔÑE±ç…Q@q7ÿ�…Ÿýs?λzâ©ÿ¡­yÞ£ÿ 'ë7þ„+ѺÏb; ¢Š(QEæžÿ‘ŠÿýÆÿÐÅvõÄxGþF+ÿ÷ÿCÛ×N+ø‡�‘ÿº|ßæQEsÁËxþC×î?þ„+©®[Ãÿò»ÿqÿô!]Mvãÿ‹òFø�Œ(¢Šâ0 (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¢Š(¢Š(®NoùÇûëÿ  ë+“›þGqþúÿè±­ö}OC.Þ§ø_èu”QElyáEPEP)ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAÏxãþ=-?ë£*ètÏùÙÿ×ÿÐEyt?ßêú"ÄËTQEz…–ÏüxþÖªU³ÿ?‡õª”Ugþ@—ÿõîÿú «ÕGYÿ�%ÿý{¿þ‚j¡ñ#Gðgèÿ#À¿òºÿ®¿ÐWU\¯�äuÿ] ®ªµÄÿœyGû•?OÔ*¾¡ÿ Û¯úâÿÈÕŠ¯¨È6ëþ¸¿ò5�?�zžœwE/Ç�×ýtʺšå¼ÿw_õÐ*êk|oûÄ�+ÿ…Q\¦AEPãøø³ÿu¿˜­åû£éX>7ÿ�‹?÷[ùŠÞ_º>•Û_ýÞ—Ïó7©ü8üÅ¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢ŠäÏüŽÿð?ý’ºÊäÏüŽÿð?ý’ºÊÆ�Úõ= Ãþ]…Q[xQEW%ãŸõ_ï?òÖ×'ãuf‚Ïh'ænƒØWŸšÿ¹Ïåù¢gð�Ÿÿ Û_úâŸÈUš¯§ñ¦Úÿ×þB¬Wm?�z‚­·üx� þuR­·üx� þu`T¢ŠŽâC´²(Ë"è(vWf6¯â›=.S£O8ûʧ~¦©ØøÚÒâaÕ»[†8»r�¯»´’3»f$’{šmz«O–ÏsáçÄ·Wš-(ö·ôÏd0AäKXžžIü?˜I(Y>€ñþ…m×™8òÉDZöxzʵ(Õ]RaET›Q@µ‡ü�Ó¿'õ®¦¹kù¦ÿ~Oë]Mvã¾8ÿ…×ÝzQ\FEPEPEPEPEPEP\œ_ò;Ÿ÷Ûÿ@5©®k?Ù¨±D\8ÈÏEµÈ‹û•¾ûh“÷ùÎìLt®Zõ"š]™íeØJŽŸI&‘èÔVN‰¬ N&Y,ñýà:ê+Zº#%%ty5iJ”Ü&µAEU…Q@‡Ž¾å�ÕÿöZêlÿãÆßþ¹¯ò®[Ç_rÇêÿû-u6ñãoÿ\×ùW—‡ÿ~­éÈ…ñ2j(¢½BËoÿCè*¥[øòAU(¬ßÈ÷þ¹Ò¬ßÈ÷þ¹ºõ9ñ_ÀŸ£üŒ¿Èoúø?ú ×M\Ï�¿ä 7ý|ýk¦«ÄG>UþåOÐ(¢ŠÄôŠ( ¹m3þF»Ÿ÷äþuÔÖE®�%¾±-é•J»1Ú#&º°õ#MIî�iÉ%+ö5袊å2 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9;où[ý÷ÿÐMu•ÉÛÈêßï¿þ‚k¬¬hlýOC1ø©ÿ…~¡EVÇžqÖ?òRGýtoýkÑkάä¤�úèßú,×¢×—•íWüoô"BŠ(¯P°¢Š(ÅŸò+߸?ô!^myÿ"Î�ÿ_ÿ$¯IñgüŠ÷ßîýW›^ȳ§×ÄÿÉ+އü�áþúžFwþç?—æ�Z°ÿ�u¯ýqOä*ÅW°ÿ�u¯ýqOä*Åv½ÏRŸÀ½Š(¤XQEäöŸòÖ¿Ü›ÿC½áÿÚé6A‘~U‡>ù_Þ{<Ô{1ŸðšéÿóÂëþù_þ*�øMtÿùáuÿ|¯ÿXe¬ø‚â"V‰KáHà`ñ]öFŸÿ>‘~UµhaiK•Å÷Ü©ªPviŒÿ„×Oÿž_÷ÊÿñU�­j°êú¥´Ð$Šª¡pÎìö'Öº/ì�?þ}"ü©É¥ØÆáÒÖ ÊrÞ•4ñjOšwÔ§t™nŠ(¯8æ (¢€ (¢€ (¢€ (¢€ (¢€ äì¿är—ýù?‘®²¹;/ù¥ÿ~OäkÛÇÔô0?_𳬢Š+cÏ (¢€ (¢€8Ïÿ®²ÿuÿ¥v©O÷Eqþ9ÿ]eþëÿJì"ÿRŸîŠòð¿ïµÿíßÈ…ñ1ôQEz…–åÿ�Dú ©Våÿ�Dú ©@dø›þEËÏ÷Gþ„+Z²|Mÿ"åçû£ÿBt¾8úœØß÷jŸá‘OÁò?õÙ¿¥tUÎø/þ@'þ»7ô®Šª¿ñ$e–¹ÓôAEVGpQEW-¢ÈÇuôýWS\¶‰ÿ#×Ñÿô!]¸_áUô7¥ðËÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€)ê¿ò »ÿ®Müª·�¿äsÿ]¿ «:¯ü‚nÿë“*Íð†£gea:\ÜÇ4¹Û„ÚUUÏJŒ\°SQWÕ•Ÿý»¥Ïü÷ÝÛºWüÿÁÿ}Ö¼ñîq{ ¿ÊþãBŠÏþÝÒ¿çþûî�íÝ+þàÿ¾èç�pö•ýÆ…q7ÿ�…Ÿýs?κíÝ+þàÿ¾ë‘ñuíµíõ«[N’ª¡¡ÎkòN3¿-¥8â”Zßò!Ñä¢Kþü¿È×¢W�è¿òQ%ÿ~_äkÑ+�*þOñ?Ðò!Ô(¢Šõ (¢€0|gÿ"­çÕ?ô5¯;Ôä¤ýfÿÐ…z'ŒÿäU¼ú§þ†µçz�ü€4Ÿ¬ßú®L7ü�ãþÕž6yþç?—æ�_‡ýDî�åO¦Cþ¢?÷Gò§×YìGdQE (¢€<ÓÂ?ò1_ÿ¸ßú®Þ¸�ÿÈÅþãèb»zéÅñò?÷O›üŠ(®cØ9oÿÈzïýÇÿÐ…u5ËxþC×î?þ„+©®Üñ~Hßñ…Q\FEPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š(¢Šå$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…WÔ?äuÿ\_ù±UõùÝ×þF³§ñ¯SÓŽè¥à�øóºÿ®ƒùWS\·‚?ãÎëþºå]Mo�ÿx‘¥â0¢Š+”È(¢ŠãƒùÕJ¶ßñâ>ƒùÐJ:ÑEyîµá[»K—’ÊžÙŽT Ë'¶:Õ+jw³û,�¦yyT¨ñëøW§Ñ]k5ø{ *¼é´»ì,ãÓìbµ‹îF¸Éî{ŸÎ¬QEr¶Û»=ØEB*1VH(¢ŠEQ@cÓm"»k¤‹±$¶ã߯ÅZ¢Š©JRø�ÆÛ{…QR ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(‡ñ)'Z�ÑTʲ+cÄÊWZrG ŠGå�éXõåÕøÙöX?÷xz#kÂä�c®3~=+µ®/ÂÊN®HÎJí+³ ðoþñòAEWAæQ@‡Ž¾å�ÕÿöZêlÿãÆßþ¹¯ò®[Ç_rÇêÿû-u6ñãoÿ\×ùW—‡ÿ~­éÈ…ñ2j(¢½BËoÿCè*¥[øòAU(¬ßÈ÷þ¹Ò¬ßÈ÷þ¹ºõ9ñ_ÀŸ£üŒ¿Èoúø?ú ×M\Ï�¿ä 7ý|ýk¦«ÄG>UþåOÐ(¢ŠÄôŠ(  ½_YM4E; …=õ5„¾&¿na/÷vÔþÿí©÷ûcé�Yµôl/dœ•ÛG¡JŒ9ÑßiºŒZ•·šƒkcW+•ð¦ÿµÜcîyc?\ñýkª¯#J4ª¸ÇcŽ´&Ò (¢¹ŒÂŠ( Š( Š( Š( Š( Š( NÛþGVÿ}ÿô]ervßò:·ûïÿ šë+?SÐÌ~*á_¨QE±çœu�ü”‘ÿ]ÿEšôZó«ù)#þº7þ‹5èµåå{Uÿý‡P¢Š+Ô,(¢ŠÆñgüŠ÷ßîýW›^ø¦tãÛíÿ$¯IñgüŠ÷ßîýV7„íà¹ð¡IáŽU @‘C àz×'ìóHKû¯óg? ñTeE;_üîW¶ø…k¬Q ‰D NñÎ*_øXÖŸô›þû«ý“¦ÿÐ>×þü¯øQý“¦ÿÐ>×þü¯øW±ÏCù‘a³$¬«/üÊÿ…�iÿ@ù¿ï±Gü,kOúÍÿ}Š“_Ó¬aЮäŠÊÝS!–%r;â¨x>ÆÒçFwžÖ _Îa¹ã q�ëZ%Eß—ñ9¥,Æ8•‡öªí^öE¿øXÖŸô›þûÂÆ´ÿ |ß÷Ø­_ì�7þ�ö¿÷åÂ�ì�7þ�ö¿÷å³ç¡ü¿‰Õõ|Ïþ/üä<)0¹ñMÜê¤ GÁí–»º† KkRM½¼Qnëå \þU5gZ¢©+£«/ÂK GÙÉÝÝ¿¼(¢ŠÈî9m#þF{¯¬Ÿúu5Ëiò3Ý}dÿЫ©®Üwñ¢7¯ñ/@¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+“²ÿ‘Ê_÷äþFºÊäì¿är—ýù?‘¬koSÐÀüÂβŠ(­�<(¢Š(¢Šã3ÿ‘VóêŸú×�ê?òÒ~³èB½Æò*Þ}SÿCZó½Gþ@OÖoýW&þFñÿêÏ<ÿsŸËóG¯Ãþ¢?÷Gò§Ó!ÿQû£ùSë¬ö#² (¢�…Q@iáù¯ÿÜoý Wo\G„äb¿ÿq¿ô1]½t⿈xùû§ÍþaEW1ì·‡ÿä=wþãÿèBºšå¼?ÿ!ë¿÷ÿBÔ×n?ø¿$oˆøÂŠ(®#¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ d¤¬.G)"ŸL›ýDŸîŸåCwG£è÷ãÎRà!�‹äç9ÿ Ôÿ„"÷þbü�KàO¿ô�ÿf®Î¹)QŒ ›=¬n:µò„ŠÝ<Žþ‹ßùý‹ò4Âyœý²ý wVŸW¦rjb{þáÿá½ÿŸØ¿#Gü!¿óûäk¸¢�«À?µ1=ÿy¦±¢\h« Ép¯æÌŒb»F/e1%ŒjI=Î+/Çê,¿Þä+NËþ<-ÿë’ÿ!J”TjI#LeYUÃSœ÷»'¢Š+ òÎSÇñéiÿ]ùWC¦È&Ïþ¸'þ‚+žñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šòè¿ÕôD/‰–¨¢Šõ -Ÿøñü?­T¬Ïk:F�nÖ¡7Ë&ÒÌ3€9®n=[Å“D’Gc+£€ÊËlH ô"·… N<×G›ˆÍ(Ъé4Û]•ÎÞ¨ë?ò¿ÿ¯wÿÐMs?Ú^/ÿ |ßø j+‹¿\ÛËštû$R�‹cÐŒUÇ$ÓºûÎj¹½)Ó”T%ªd¿à_ù]×_è+ª¯=ÓSĺTO®›pÛqÝnO5{ûKÅÿô›ÿM]jsrM}ç>2† S„®¼ŽÒ«êò ºÿ®/ü�rÚ^/ÿ |ßø i¶:þ¥uqwc|Š‘(+³k+50ÃI4î´;èç'V4ùdœ�•ÕŽ‡Áñçuÿ]ò®¦¹oÇ�×ýtʺšXß÷‰Íâ0¢Š+”È(¢Šã#"F«ý–Çõÿý�;þBÐ-¿ïÿÿc^ŸÕjö-gXðäwTW ÿ !?èß÷ÿÿ±£þBÐ-¿ïÿÿcGÕjööÖþ~~üŽêŠáád'ýÛþÿÿö4ÂÈOú·ýÿÿìhú­^Áýµ�ÿŸŸƒÿ#;Â?ò1_ÿ¸ßú®Þ¸o±—[¼—i£'é–»šx¯â‘ë„OÍþaEW1ì·‡ÿä=wþãÿèBºšå¼?ÿ!ë¿÷ÿBÔ×n?ø¿$oˆøÂŠ(®#¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQPÝÈÐÙO*ýä�˜}@ :—S×¼sâKí?EÔÛLÒ¬d—�žFÉy ãp9¤޽à?ØÚk:£jšEólY埤ÛZ]]½Üñ W�ó™©É'õ«µ� ë6þ Ñ­õ+PDs/*z£?CY~9×µxtßé–‰uqç*ynŒÃ98Rjék:_õ¯þñ¯ ÿ…»ã?ú­¿ðoþ*½wL&ûJ³¼¸ýÜÓÀ’ȃ€¬Ê <õ4”U¿³EýóùŠ>Í÷Ïæ(¥oìÑ|þb�³EýóùŠ©E[û4_ß?˜£ìÑ|þb€*S&ÿQ'û§ùUï³EýóùŠŽ{h…¼¿9û‡¸ô¡Ž;£™ð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�ªW>)�KòmE«JË ;öŽTCW|wþ¢ËýçþB°DHÞ6±FPèV †÷k^N>µJO÷NÍ´¾ó»ÚÁR·vZÿ„åèï÷ÿZ�øNWþ�çþÿõ«¹þϲÿŸ;ûô¿áGö}—üùÛÿߥÿ ¯«ã¿çòÿÀQçZ]Ï0×|@5˜aŒ[¼¶'%÷g?…hZøÍm­!ƒì%¼¸Õ3æã8ô®ÿû>Ëþ|íÿïÒÿ…Ùö_óçoÿ~—ü+(à1q¨êªªï}rÊ÷¹ÃÂr¿ô?÷ûÿ­Gü'+ÿ@óÿ¿úÕÜÿgÙÏ�¿ýú_ð¬ýzÆÑ4 ÷KX„ A€Gs£Ž„\½²Óû¨-.çâMb=kÃv“$MŽå‘”œó·=î´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú¯S VUpç=ÝÏ' ï™Uÿ 4(¢Š£Ù (¢€ òãÿ#–«ô¸ÿÐMz�yxPÞ3Õ²z-ÉÿÇZºð›ËÐòs/ãaÿÆŽŸÁñçuÿ]ò®¦¹oÇ�×ýtʺšXß÷‰Ýâ0¢Š+”È(¢ŠãÍ÷Ïæ(¥oìÑ|þb�³EýóùŠ©E[û4_ß?˜£ìÑ|þb€*QVþÍ÷Ïæ(û4_ß?˜  ”U¿³EýóùŠ>Í÷Ïæ(¥oìÑ|þb�³EýóùŠ©E[û4_ß?˜£ìÑ|þb€*U¶ÿ�ôÎ�³EýóùŠ”Æ¦™ù}h>Š·öh¿¾1GÙ¢þùüÅqzσÖöáîl¥H¤s—�ÇÊO¨#¥R±ð<ÞpkëˆÄ`ò±d–üH¯Aû4_ß?˜£ìÑ|þb·XšŠ<·<¹äØ9Õö®:þqF(’’(Ô* ª:)õoìÑ|þb�³EýóùŠÀôÒIY(«f‹ûçó}š/ïŸÌP2¥r>%½yo�¨b"ˆ �RFs]ÏÙ¢þùüÅq¾+Òž ¿¶Æ à ˆþsúWv]Ëí½ï—©¾ÜúœåtÞ½wó,Ü’ª»Ó=†pGê+™®¿ÂzK*I{>P8Û<:“ü«ÕÇòûÍò:ñäw6è«f‹ûçó}š/ïŸÌWÎiRŠ·öh¿¾1GÙ¢þùüÅT¢­ýš/ïŸÌQöh¿¾1@(«f‹ûçó}š/ïŸÌPJ*ßÙ¢þùüÅf‹ûçóRŠ·öh¿¾1GÙ¢þùüÅT¢­ýš/ïŸÌQöh¿¾1@(«f‹ûçó}š/ïŸÌPJ*ßÙ¢þùüÅf‹ûçóRŠ·öh¿¾1GÙ¢þùüÅT¢­ýš/ïŸÌQöh¿¾1@(«f‹ûçó}š/ïŸÌPJ*ßÙ¢þùüÅf‹ûçó?üy ª• cSB~_Z‹ìÑ|þb€*QVþÍ÷Ïæ(û4_ß?˜  ”U¿³EýóùŠ>Í÷Ïæ(¥oìÑ|þb�³EýóùŠ©E[û4_ß?˜£ìÑ|þb€8Ïir›ƒ{ FÌrïô®xÄ ' êŸf‹ûçóÑenpÀcÜc5éPÌeN W±Ó KŒlÑÍø{L’Î'žuÛ$€§ª�zÛ«f‹ûçó}š/ïŸÌW Z²«79u0œœÝÙRŠ·öh¿¾1GÙ¢þùüÅfIRŠ·öh¿¾1GÙ¢þùüÅT¢­ýš/ïŸÌQöh¿¾1@(«f‹ûçó}š/ïŸÌPJ*ßÙ¢þùüÅf‹ûçóRŠ·öh¿¾1GÙ¢þùüÅT¢­ýš/ïŸÌQöh¿¾1@E·üŽ­þûÿè&ºÊæ-cSã×Lü»ßŸø®ËìÑ|þb±¡³õ= Çâ§þú•(«f‹ûçó}š/ïŸÌVÇžpv?òRGýtoýkÑkÏmT/ÄÝ ä ÿEšô*òò½ªÿ�þ„C¨QEêQEcx³þE{ï÷þ„+/ÁŸò+7ýwoéZž,ÿ‘^ûýÁÿ¡ Îð:ðÑV8{!^dÿäcðþ¤}£ZŠ·öh¿¾1GÙ¢þùüÅze˜#ÿ‘z÷þ¹ÿQYþ ÿ�ŸõÝ¿’Öωà�|7|ÁÉ"?_qY¾…$Ð$,Ä´7e®˜ÿ»¿SÇ©ÿ#X�þfíoìÑ|þb�³EýóùŠæ=‚¥oìÑ|þb�³EýóùŠ©E[û4_ß?˜£ìÑ|þb€8½#þF{¯¬Ÿúu5Í豫x¶í À^àU×ýš/ïŸÌWn;ø‹Ñ×ø—¡RŠ·öh¿¾1GÙ¢þùüÅq(«f‹ûçó}š/ïŸÌPJ*ßÙ¢þùüÅf‹ûçóRŠ·öh¿¾1GÙ¢þùüÅT¢­ýš/ïŸÌQöh¿¾1@(«f‹ûçó}š/ïŸÌPJ*ßÙ¢þùüÅf‹ûçóR¹;/ù¥ÿ~Oäk·û4_ß?˜®6Â5>9™ ùwÉÏàkÛÇÔô0?_ð³§¢­ýš/ïŸÌQöh¿¾1[yRŠ·öh¿¾1GÙ¢þùüÅT¢­ýš/ïŸÌQöh¿¾1@Ž×YºÿÒ»¿Ô§û¢¹Oˆ¬sXmlå_ùŠí¡¶‹É�ç?tw•åáßkÿÛ¿‘ âez*ßÙ¢þùüÅf‹ûçóêÿÇ¢}T­�Z „áF9¨¾Í÷Ïæ(¥dø›þEËÏ÷Gþ„+¡û4_ß?˜¬oAxfùƒ’BŽÿí º_}NloûµOð¿ÈËð_ü€Oývoé]bx“Ãij|æïì+¦û4_ß?˜ª¯üIeŸîtýRŠ·öh¿¾1GÙ¢þùüÅdw(«f‹ûçó}š/ïŸÌPJå´Oùî¾�ÿ¡ í>Í÷Ïæ+�ðüjþ(¼Rp“Ÿø®Ü/ðªúÒøeèt”U¿³EýóùŠ>Í÷Ïæ+ˆÀ©E[û4_ß?˜£ìÑ|þb€*QVþÍ÷Ïæ(û4_ß?˜  ”U¿³EýóùŠ>Í÷Ïæ(¥oìÑ|þb�³EýóùŠ©E[û4_ß?˜£ìÑ|þb€*QVþÍ÷Ïæ(û4_ß?˜  ”U¿³EýóùŠ>Í÷Ïæ(ˆÓäo¸ÿ~Jë+˜ÒãSãk”'å/?�v_f‹ûçó� Ÿ©èf?Ä�øQRŠ·öh¿¾1GÙ¢þùüÅlyç ¢ÿÉD—ýù‘¯D¯=ÒT/ÄyÀ9I‘¯B¯/*þOñ?Јu (¢½BŠ(  ÿÈ«yõOý j�…¢Ž_Â$Ep%c†îj÷ŒÿäU¼ú§þ†µƒdð´!Ž˜ÿμÇÿ#%þÔ†“•™kìv¿óíýð(û¯üûCÿ| Òû4_ß?˜£ìÑ|þb½K°öpìŽ_ÄöÖñøví’Õ€\€¼*[Á.‚­$1»y�Ë(&µ<]iá{Ö I;ÿ¶µ_Á£øqY˜ƒæ¿zèMý]úžD¡íX«}�ÔÑû¯üûCÿ| >Çkÿ>Ðÿß´¾Í÷Ïæ(û4_ß?˜®{³×öpìŠ1Ã@ˆãD®Õ4ú·öh¿¾1GÙ¢þùüÅ"’KDT¢­ýš/ïŸÌQöh¿¾1@Î/Ãÿò»ÿqÿô!]Ms~�_ÄWŠÇ#óÿ×ýš/ïŸÌWn?ø¿$oˆøÊ”U¿³EýóùŠ>Í÷Ïæ+ˆÀ©E[û4_ß?˜£ìÑ|þb€*QVþÍ÷Ïæ(û4_ß?˜  ”U¿³EýóùŠ>Í÷Ïæ(¥oìÑ|þb�³EýóùІÛýzþ?ʯÔÁ8ebH÷©è¢Š(¢Š(¢Š(¢Š(¢Š(¦º,‘²0ʰ �juæŸ §Eæ³á›¶ÝArdEn ƒI‚©úwÅ;‘©¾“á«FY/..DŒŠrP`¨Ï ;‰ÿ€×OâèÞ$�n.â’+¥ï±ñïÁñžð>‹áˆ¹´ŽYn˜ö‹‡Þà¸àùPÔ“Úiv‘ý¢â+xPÕ¥p£§'éSÇ"MK«Æê]NCЃÜVW‰<9gâ�1l/dž8–Q(0° �îÕû 8ôí:ÖÆfŠÚ… œ± Ç~(€ñÂGñGIÐÏ6ºzý¦uì[°ƒþkÑëOð­Ž�â;ív9®d¼¼_Íe* �p {É=+r€9dñ¬øÊßÛ}�•sÃËòÍœ÷ê1W<]«Xé^¿{Éc_2Ž8ÉæFe ;õ©5ÿ é%‰R¶Þè0’¡Úëô>žÇŠÂ°øWá«¥�Òæì©ÈK™_ÈŸ¡ ü.±žËÁÔ©¸‘æE=”àÏük³¤U ¡TÀµ-�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò�üŽööÇÿEŠßñßú‹/÷Ÿù ÀƒþG{ûcÿ¢Åx¹—ÅñGõ;±?îT½Yé´QE{GQEVoˆä^Ô?ëƒÿ*Ò¬ßÿȽ¨×þU–#øRô�žÇ—Éÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¼¶Oùþ¿�þ€+Ô´/ùôßúõ�ÿAeÿò-¥ó,ÿÝoæ+y~èúWm÷z_?ÌÞ§ðãóŠ(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¤ 0 €Aê -UtÛ%“zÚB×`«TQU)J[±¶ÞáETˆ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢£¸¸ŠÖÝç™ÂFƒ,M&ÒW`IEqw^7›Í"ÒÖ1<I$þ]+SEñDZœ¢ÚxÄ7îàå[éèk†žg†©SÙÆZ’¦›±ÐQEÞQmÿãÈ}T«oÿCè*¥QP]^ÛY {™ã‰OMíŒý)¤ÞˆR’м�‘=R×S±¾b¶×QHÃøCsùUºkF(N3\Ðw^AER((¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šäí¿äuo÷ßÿA5ÖW'mÿ#«¾ÿú ®²±¡³õ= Çâ§þú…Q[yÄ%Ü?ææA)#nb ÆPŽßZìá-Ð¿è Ÿ÷Ã…fÞøkN¿º{™VA#ýí�€j¿ü!Ú_ý7ÿ¾ÿúÕãS£�¡)ªj-6Þ·êBR[_ð–è_ôOûá¿Â�øKt/ú'ýðßáX¿ð‡iôßþûÿëW?âm×I6¿fó?{»vöÏL�ŒN>…7Rq�—¯ù‰¹%sºÿ„·Bÿ ‚ß þÂ[¡ÐA?ï†ÿ ‡Âcß?, ŸŸÛéOÿ„;Kÿ¦ÿ÷ßÿZµSÌZ¿,ûÄÞ"ñ‘{ ]ÛÛÞ+Êê¨VäzŠ_ȬßõÝ¿¥Aÿv—ÿMÿï¿þµt6z}¾™¤¥½²•Lî99$žôP¡‰–%W®’²¶€“½Ø”QEz…™~#ÿ‘z÷þ¹ÿQYþ ÿ�ŸõÝ¿’Ö‡ˆÿä^½ÿ®ÔV‚ä'ýwoäµÓ÷wêxõ?äkð?Ìé(¢Šæ=€¢Š(¢Š(–Ò?ägºúÉÿ¡WS\¶‘ÿ#=×ÖOý ºšíÇz#zÿô (¢¸ŒŠ( Š( Š( Š( Š( Š( ¹;/ù¥ÿ~Oäk¬®NËþG)ß“ùƶñõ= ÁWü,ë(¢ŠØóŠ( Š( 3Ç?묿Ýé]„_êSýÑ\Ž×YºÿÒ»¿Ô§û¢¼¼/ûíûwò!|L}Q^¡e¹ãÑ>‚ªU¹ãÑ>‚ªPY>&ÿ‘róýÑÿ¡ Ö¬ŸȹyþèÿÐ…]/Ž>§67ýÚ§ø_äSð_ü€Oývoé]s¾ ÿ� ÿ®Íý+¢ª¯üIeŸîtýQE‘ÜQEËhŸò1Ý}ÿBÔ×-¢ÈÇuôýWnøU} é|2ô:š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( OMÿ‘¾ãýù+¬®OMÿ‘¾ãýù+¬¬hlýOC1þ$‚Š(­�<ãô_ù(’ÿ¿/ò5è•çz/ü”Iß—ùôJòò¯áÔÿý‡P¢Š+Ô,(¢ŠÁñŸüŠ·ŸTÿÐÖªxKþE8ë«:·ã?ùo>©ÿ¡­Tð—üŠpÿ×Vþuæ?ù/ð~¤}³VŠ(¯L³Å_ò-Þ}ÿC_Á¿ò/¯ýtj±â¯ùï>‹ÿ¡Š¯àßù×þº5t¯÷wëú<¿ämð~§AEW1ìQ@Q@·‡ÿä=wþãÿèBºšå¼?ÿ!ë¿÷ÿBÔ×n?ø¿$oˆøÂŠ(®#¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò�üŽööÇÿEŠßñßú‹/÷Ÿù ÀƒþG{ûcÿ¢Åx¹—ÅñGõ;±?îT½Yé´QE{GQEVoˆä^Ô?ëƒÿ*Ò¬ßÿȽ¨×þU–#øRô�žÇ—Éÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¼¶Oùþ¿�þ€+Ô´/ùôßúõ�ÿAeÿò-¥ó,ÿÝoæ+y~èúWm÷z_?ÌÞ§ðãóŠ(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¨®.a´ˆË<�w=êZã|Gròê�'d@Q’k§ CÛÔå{Ò§Ï+Kâm<É´ù x§ãZ±J“F²FáцCÁ¯8®‹Â·/çMlI(Wx‡ _Ò»qXS¦ç†Õpê1æ‰ÔQEäœ�EPEPEPEPEPEPEPEPEP\ç�×G�W;Z`ò&º:­c£e%¬ÃåqÔu±Ï‹¥*´%N;´)+«QRÛ;ÇuÅŸ1\Ç®x­{¯ ê�JV(„éž þµ´ Ëor—wûAŒîH�Ï>¤×ÈQ˱2ª¡Êןüs®¢Š+í΂ÛÿÇ�ú ©Vßþ<‡ÐUJdÒ¬I+}ÔRÇèkɯï§Ôoæv%˜ð;(ìµzÌÑ,ðI}×R§èF+ɯì'Ó¯Úu!”ð{0ìGµwà¹nûŸ/ľӖøu¿¯OøÈðȲFåNU”àƒ^§¡ß¶¥¤Arÿë*øõükË#�æ‘c� »*¨É&½OC°m7H‚ÙñæYñêNOøUãyyWs›†ý§¶�¾këÓõ4(¢ŠóO± (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9;où[ý÷ÿÐMu•ÉÛÈêßï¿þ‚k¬¬hlýOC1ø©ÿ…~¡EVÇžQEÇxëïX}$ÿÙk±®;Ç_zÃé'þË^noþç?—扟Âu–ßñëûƒùTµ·üzÅþàþU-zøQAVäÿ�5ú ©Väÿ�5ú  *QE—â?ù¯ëŸõŸàŸùÉÿ]Ûù-hx�þEëßúçýEgø'þ@r×vþK]1ÿw~§�SþF°ÿüÎ’Š(®cØ (¢€ (¢€9m#þF{¯¬Ÿúu5Ëiò3Ý}dÿЫ©®Üwñ¢7¯ñ/@¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+“²ÿ‘Ê_÷äþFºÊÁ¶Ò®¢ñ—¬«ä³1w<�JʪmÆÝÎìãÔRv¼Y½EV§QEQEƒâ meíÚ)c�Ê üóœ…n"íE_@:ŠÆ! ’¨·•¯òµ¸QE°ËrÿÇ¢}T«rÿÇ¢}T ²|Mÿ"åçû£ÿB­Y>&ÿ‘róýÑÿ¡ º_}NloûµOð¿È§à¿ùŸúìßÒº*ç|ÿ ÿ]›úWEU_ø’2Ë?Üéú ¢Š+#¸(¢Š+–Ñ?äcºú?þ„+©®[Dÿ‘Žëèÿú®Ü/ðªúÒøeèu4QEqQ@Q@Q@Q@Q@Q@Q@ž›ÿ#}ÇûòWY\ž›ÿ#}ÇûòWYXÐÙúž†cüHÿ…Q[yÁ&¥‘ã;‹ÉcwD‘ÁUëÈ"ºøXv?óçsù¯øÖ”Úm�ĆI¬à‘ÏVhÁ&™ý�¦Ð>Ûþý ò!ƒÅÑrTª$›onärÉlÊð°ìçÎçó_ñ£þ�üùÜþkþ5ûLÿ }·ýúÈøÂÒÚÒâÔ[ÁA‘‰ gšËd®oÿÂñÿŸ;ŸÍÆ�øXv?óçsù¯øÕá£é˜ñ/¶ÿ¿B—ûLÿ }·ýúÑìsùø¾áÚ]Î{^ñ�¦­£Ïe´ÈòmÃ600ÀÿJÙð—üŠpÿ×Wþf¬ciŸô¶ÿ¿BµZ(á°Ž8‘cE £~X|%xâ=½i&ím˜(»Ý•袊ô‹1üUÿ"ÝçÑô1Uüÿ"úÿ×F«*ÿ‘nóè¿úªþ ÿ‘}ë£WJÿw~¿¡ãËþFÑÿêtQEsÀQEQEËxþC×î?þ„+©®[Ãÿò»ÿqÿô!]Mvãÿ‹òFø�Œ(¢Šâ0 (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¦Mþ¢O÷Oò§Ó&ÿQ'û§ùPÇчàO¿ô�ÿf®Î¸Ï}ûÿ¤û5vuŽøhîÌÿÞ¥òü�QE±ÀQEr>;ÿQeþóÿ!XÈïaÿlôX­ÿÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,W‹™|QÿS»þåKÕž›EW´p…Q@fø‡þEíCþ¸?ò­*Íñü‹Ú‡ýpåYb?…/Gù ìy|Ÿò*'ýýW©h_ò/é¿õëþ‚+Ëdÿ‘Q?ëøÿè½KBÿ‘Mÿ¯XÿôF_ÿ"Ú_3ÆÂÿÈʯøQ¡EV§´QEåÇþG-Wéqÿ šõòãÿ#–«ô¸ÿÐMuá7—¡äæ_ÆÃÿ�G‚?ãÎëþºå]MrÞÿ�;¯úè?•u4±¿ï=ºÿÄaEW)�QEÆxßþ>,ÿÝoæ+y~èúV�ÿãâÏýÖþb·—î�¥v×ÿw¥óüÍê?1h¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÐJ(¤bK€I ¢¼ÇZ×îµK— #%¨8HÁÀ#Ôúš¥c¨ÝéÓ -¦d ò¹ù[ê;×jÁIÆíê|Üø’ŒjòÆ Ç½ÿOø'­ÑTô»õÔôØnÔmÞ>eô#‚*åq´Ó³>†�H©Çg¨QE‹ æ¼E¥K$ßl� ä"�ÈÇzéh­¨V•óĺsp•ÑæÁ›j©,xÀ×]áí.K8Þy×l² =T{ÖÖÑœàgÖ–º±„«C‘+#Z˜‡5d¬QEyç8QEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥Õ•µê¹‚9TtÞ¹ÇÒ§¢šmj…(©+I]-tË-mklˆ/?�[¢ŠoV(B0\°V^AER((¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šäí¿äuo÷ßÿA5ÖW'mÿ#«¾ÿú ®²±¡³õ= Çâ§þú…Q[xQEW㯽aô“ÿe®Æ¸ï}뤟û-y¹¿ûœþ_š& Ö[Ǭ_îåRÔVßñëûƒùTµèGáE[“þ<×è*¥[“þ<×è*€©EP_ˆÿä^½ÿ®ÔV‚ä'ýwo䵡â?ù¯ëŸõŸàŸùÉÿ]Ûù-tÇýÝúž=OùÃüó:J(¢¹�`(¢Š(¢Šå´�ùî¾²èUÔ×-¤ÈÏuõ“ÿB®¦»qßÄ^ˆÞ¿Ä½Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ü¿ñèŸAU*Ü¿ñèŸAU(¬ŸȹyþèÿÐ…kVO‰¿ä\¼ÿtèB®—ÇS›þíSü/ò)ø/þ@'þ»7ô®Š¹ßÿÈÿ×fþ•ÑUWþ$Œ²Ï÷:~ˆ(¢ŠÈî (¢€ å´Oùî¾�ÿ¡ êk–Ñ?äcºú?þ„+· ü*¾†ô¾zMQ\FEPEPEPEPEPEPEP'¦ÿÈßqþü•ÖW'¦ÿÈßqþü•ÖV46~§¡˜ÿ?áAEVÇžQEÅxãþ>¬ÿÜoæ+µ®+Çñõgþã1^fqþé/—æDþ´- è)kÓ,*ÜßñꟅT«sǪ~RŠ(  È·yô_ý UÿȾ¿õѪNJ¿ä[¼ú/þ†*¿ƒä__úèÕÒ¿Ý߯èxòÿ‘´Áú�Q\ǰQEQErÞÿ�õßû�ÿ¡ êk–ðÿü‡®ÿÜýWS]¸ÿâü‘¾#ã (¢¸ŒŠ( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š)“¨“ýÓü©ôÉ¿ÔIþéþT1Çtaøïßý#ÿÙ«³®3ÀŸ~ÿéþÍ]�c‡þ;³?÷©|¿$QElpQ@�ŽÿÔY¼ÿÈVò;ØÛý+Çê,¿Þä+ùì?í�þ‹âæ_ÅÔîÄÿ¹Rõg¦ÑEí!EPY¾!ÿ‘{Pÿ®ü«J³|Cÿ"ö¡ÿ\ùVX�áKÑþB{_'üЉÿ_Çÿ@êZü‹úoýzÇÿ ŠòÙ?äTOúþ?ú¯Rпä_ÓëÖ?ýQ—ÿȶ—Ìñ°¿ò2«þhQE©íQ@yqÿ‘ËUú\è&½F¼¸ÿÈåªý.?ô]xMåèy9—ñ°ÿãGQà�øóºÿ®ƒùWS\—ƒ&Š+K¡$¨„È1¹€í]?Û-¿çâûìSÆÅûyh{•ÓöŒšŠ‡í–ßóñýö(ûe·üüCÿ}Šåå—c+2j*¶[ÏÄ?÷Ø£í–ßóñýö(å—`³9/ÿÇÅŸû­üÅo/ÝJç¼i,rÏiåÈ�…lí`qÈ®…~èúW^#L=/ŸæmSøqù‹EW€QEQEQEQEQEQEQEQEV=߉ô»ILM3HÀàùk�?•Šï$³ÑXDJ´Î#Èì$ÿ,~5çuâfy¤ðÓT©­zÜÎs¶ˆõ; VËSRmfGÞSîהX^Ia{ÌD†Fɸî+Õë§-Ǽ\2³C„¹‚­·üx� þuR­·üx� þuéT¨/1öŒð<¶ÏåSÒ:«£# « íMnL•âÑãtVޝ¤\i7mˆÆ"w&8aþ>ÕNÚÚ{ÉÖxšI¢¨¯qI5̶?0��©ì¤½îÇ ø;ð�¦ ϘÙüë~¨èúöf— © ²Œ¹ØòjõxÕd¥6Ñú> œ©a¡ n’ (¢³:‚Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(“¶ÿ‘Õ¿ßý×Y\�·üŽ­þûÿè&ºÊƆÏÔô3ŠŸøWêQElyáEP\w޾õ‡ÒOý–»ã¼u÷¬>’ìµææÿîsù~h™ü'Ymÿ±¸?•KQ[Ǭ_îåRס…nOøó_ ª•nOøó_ ª¥Q@~#ÿ‘z÷þ¹ÿQYþ ÿ�ŸõÝ¿’Ö‡ˆÿä^½ÿ®ÔV‚ä'ýwoäµÓ÷wêxõ?äkð?Ìé(¢Šæ=€¢Š(¢Š(–Ò?ägºúÉÿ¡WS\¶‘ÿ#=×ÖOý ºšíÇz#zÿô (¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š¡q­é–²˜æ¼�\p@ç\t«V÷0]Ä%·•%CÝk8Õ§)rÆI¿Q]ÑE ËrÿÇ¢}T«rÿÇ¢}T ²|Mÿ"åçû£ÿB­QÍW´S"¼m÷•†Aªƒå’fXŠn­)S]S_z0|ÿ ÿ]›úWEPÛZÁg•oD™ÎÕ©©Ô—4Ü‘J.…RoT¬QEAÐQEËhŸò1Ý}ÿBÔ×-¢ÈÇuôýWnøU} é|2ô:š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( OMÿ‘¾ãýù+¬®OMÿ‘¾ãýù+¬¬hlýOC1þ$‚Š(­�<(¢Š+ŠñÇü}Yÿ¸ßÌWk\WŽ?ãêÏýÆþb¼ÌãýÒ_/̉ü'h: ZAÐRצXU¹¿ãÕ? ©Væÿ�Tü(¥Q@þ*ÿ‘nóè¿úªþ ÿ‘}ë£U�È·yô_ý UÿȾ¿õÑ«¥»¿_Ðñåÿ#hÿƒõ: (¢¹�`(¢Š(¢Šå¼?ÿ!ë¿÷ÿBÔ×-áÿù]ÿ¸ÿú®¦»qÿÅù#|GÆQEqQ@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQES&ÿQ'û§ùS铨“ýÓü¨cŽèÃð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,VÿŽÿÔY¼ÿÈVò;ØÛý+Å̾(ÿŠ?©Ý‰ÿr¥êÏM¢Š+Ú8BŠ( ³|Cÿ"ö¡ÿ\ùV•fø‡þEíCþ¸?ò¬±—£ü„ö<¾Oùþ¿�þ€+Ô´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú£/ÿ‘m/™ãaäeWü(ТŠ+SÚ (¢€ òãÿ#–«ô¸ÿÐMz�yqÿ‘ËUú\è&ºð›ËÐòs/ãaÿÆŠTWgà¸Ñí.‹¢·ïQžÕÓùÿÏ(ÿï‘^�lÁR¨áË{yŸK·äy-zJýÑô¬¢$ö{W*Ý;Šß_º>•Ž>¯µ§NvµîEysÆ2õŠ(¯0å (¢€ (¢€ (¢€ (¢€ ©¨j6úlläó¨êÇÚ­×â‰]õr�÷c@}y¬«O’7Gf±¹%¶åÏøKÛüy žžg?Ê·´ýF J6r8enªkÎëgúk ‹÷dF >œÿJç¥^NIHõ±™mÑs¦¬ÑÛQEÚ|èQEƒã+û¼ÌîóËÿ{ÿÕšóÚô_YI{¢·” <.$Ú:�ô?¥yÕ|ŽxŸÖSkKÔÜš×Ê�ùùò¼Åß�îçšõªò�>ÊMBú+h�%Ï'Ðw5êÕÝ�'É7m4ýGL*ÛLjúçU*ÛLjúç_@jT¢Š(®‹"•u §¨a‘MŠ`EFPŠIE*½ìQE (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( NÛþGVÿ}ÿô]ervßò:·ûïÿ šë+?SÐÌ~*á_¨QE±ç…Q@qÞ:ûÖI?öZìkŽñ×Þ°úIÿ²×››ÿ¹Ïåù¢gð�e·üzÅþàþU-Emÿ±¸?•K^„~PU¹?ãÍ~‚ªU¹?ãÍ~‚¨ ”QEeø�þEëßúçýEgø'þ@r×vþKZ#ÿ‘z÷þ¹ÿQYþ ÿ�ŸõÝ¿’×LÝß©ãÔÿ‘¬?Àÿ3¤¢Š+˜öŠ( Š( [Hÿ‘žëë'þ…]MrÚGüŒ÷_Y?ô*êk·üEè�ëüKÐ(¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Âñ^£%†–+$í³pê9Çùï[µ‰â�2MGKý–šÞª:°î?Ï¥rã½£ÃÏÙïaJöÐóªÓÐu4íRV>\ŒEìA?Ò³H �Fê jøL—QÔâ!O“‘û`s�©¯ŠÂªžÚ>Ïâ¹Î¯}J¢Š+ïÎ’Ü¿ñèŸAU*Ü¿ñèŸAU(¢Š(¢Š(¢Š(¢Š(®[Dÿ‘Žëèÿú®¦¹mþF;¯£ÿèB»p¿Â«èoKá—¡ÔÑEÄ`QEQEQEQEQEQEQErzoü�÷ïÉ]erzoü�÷ïÉ]ecCgêz�ñ#þQElyáEP\WŽ?ãêÏýÆþb»Zâ¼qÿVî7óægî’ù~dOá;AÐRÒ‚–½2­Íÿ©øUJ·7üz§á@(¢ŠÇñWü‹wŸEÿÐÅWðoü‹ëÿ]¬x«þE»Ï¢ÿèb«ø7þEõÿ®�]+ýÝúþ‡�/ùGü©ÐQEÌ{EPEP-áÿù]ÿ¸ÿú®¦±4­*æÏTžâ]›X žXé[u×�œgRñwÑÖiÊè(¢Šä2 (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¦Mþ¢O÷Oò§Ó&ÿQ'û§ùPÇчàO¿ô�ÿf®Î¸Ï}ûÿ¤û5vuŽøhîÌÿÞ¥òü�QE±ÀQEr>;ÿQeþóÿ!XÈïaÿlôX­ÿÿ¨²ÿyÿ�®/]ÿ�Ÿý±‹ÿ@Zð³iò%>ÒOðgn+ýÊ—«=‡rú�Î�Ëê?:ðÊ+õƒþ�þ?ð7Úyç¹}GçFåõ�xe¬ôïñÿ€ÓÈ÷=Ëê?:ÍñøGµGú‡þUãÔTTÏyàãì÷óÿ€§‘¥'üЉÿ_Çÿ@êZü‹úoýzÇÿ ŠòÙ?äTOúþ?ú©mü_­ÚÛEo Ú¬q DRœ0;WÓeTeW.¤£çùŸ;SK˜T•DõKc×h¯&ÿ„Û_ÿŸÅÿ¿)þÂm¯ÿÏâÿß”ÿ ëú•NèèÿXðŸË/¹™ë4W“Âm¯ÿÏâÿß”ÿ ?á6×ÿçñïÊ…R©ÝúÇ„þY}ËüÏY¯.?ò9j¿K�ýÕøMµÿùü_ûòŸáPéÝë776ée†fcŒd•5½¥w#š¦iG‰¡ié5½¿Ìí¼ÿw_õÐ*êk–ðGüyÝ×Aü«©®|oûÄ�­¯üFQEr™Q@g�ÿãâÏýÖþb·—î�¥`øßþ>,ÿÝoæ+y~èúWm÷z_?ÌÞ§ðãóŠ(®#¢Š(¢Š(¢Š(¢Š(¬MFmEVx1ç Û´œnã[tTÊ*JÌÖ�iÑšœ7GžejöýŠ|çêÎ?:ê4 ôðÓÜcÏq´(9Ú?ƶ謡B0w;19�Zðäµ�QE¹çQ@dÝxoK»”Êöû\œ“ÏáÒµ¨¬êR§UZ¤SõIîT±Ó,ôÔ+kÇž§©?RjÝUB‚劲U¶ÿ�ôΪU¶ÿ�ôΨ ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[øòAU*ÛÿÇ�ú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@�·üŽ­þûÿè&ºÊäí¿äuo÷ßÿA5ÖV46~§¡˜üTÿ¿P¢Š+cÏ (¢€ ã¼u÷¬>’ìµØ×㯽aô“ÿe¯77ÿsŸËóDÏá:Ëoøõ‹ýÁüªZŠÛþ=bÿp*–½ü( «rÇšýT«rÇšýP(¢ŠËñü‹×¿õÏúŠÏðOü€äÿ®íü–´dµ QV¹ãÑ>‚ªU¹ãÑ>‚ªPEPEPEPEP\¶‰ÿ#×Ñÿô!]MQ¶Ò­­.Þê=þcç9‹ÿ¡Š¯àßù×þº5t¯÷wëú<¿ämð~§AEW1ìQ@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQES&ÿQ'û§ùS铨“ýÓü¨cŽèÃð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�®z8Ò_ÙG"+£AV÷cµt>;ÿQeþóÿ!XÈïaÿlôX¯2ÖQÿS»þåKÕžƒý“§Ð>×þü¯øQý“§Ð>×þü¯øUÊ+ÖöPþTpX§ý“§Ð>×þü¯øQý“§Ð>×þü¯øUÊ(öPþT)ÿdéßôµÿ¿+þŸ®é¶h7Ï•²:ÀÄ2Ä ƒ�¥nVoˆä^Ô?ëƒÿ*ʽ8{)h¶�5¡åòȨŸõüô]^›àM.óK´º’{ÀóB’0W\@<|µÊIÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¶Ëg(eÔ¹_sçᆥˆÌ**±½’0¿á]éóñ{ÿ}§ÿGü+½#þ~/ï´ÿâk­¢º~±Wù�Gû+ÿ>ÑÉ»Ò?çâ÷þûOþ&�øWzGüü^ÿßiÿÄ×[EX«üÁý•‚ÿŸhä¿á]éóñ{ÿ}§ÿ\¥¥ªXø–þÖ"Æ8c�±ä€§­zÅyqÿ‘ËUú\è&ºpÕ'6Ô™çâðt(WúQI¹£¨ðGüyÝ×Aü«©®[Áñçuÿ]ò®¦²Æÿ¼HúZÿÄaEW)�QEÆxßþ>,ÿÝoæ+y~èúV�ÿãâÏýÖþb·—î�¥v×ÿw¥óüÍê?1h¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( Š*º·wØ·3ÿt8&šMì&¢Š)QEQEQEQEQEQEQEÉÛÈêßï¿þ‚k¬®NÛþGVÿ}ÿô]ecCgêz�ÅOü+õ (¢¶<ð¢Š(®;Ç_zÃé'þË]�qÞ:ûÖI?öZós÷9ü¿4Lþ¬¶ÿ�X¿ÜÊ¥¨­¿ãÖ/÷ò©kÐ�Š ·'üy¯ÐUJ·'üy¯ÐURŠ(  ¿ÿȽ{ÿ\ÿ¨¬ÿÿÈOúîßÉkCÄò/^ÿ×?ê+?Á?ò“þ»·òZé�û»õ™7ú‰?Ý?ʆ8îŽLÖ.ô“)µ)ûÌnܹéŸñ­øLµoX?ïßÿ^¢ð×Iž?+n6€sœÿ…nÿ kÿ?“ß"¸!®>îÇÓbk`£Qª«Þô1ÿá2Õ½`ÿ¿ýz?á2Õ½`ÿ¿ýzØÿ„×þ&ÿ¾EðƒZÿÏäß÷Ȫä¯ÜÇëwò¯¸Çÿ„ËVõƒþýÿõèÿ„ËVõƒþýÿõëcþk_ùü›þù kÿ?“ß"ŽJýÃëwò¯¸æ5=nóVXÖèLjÉ+µqÖ¥ƒþG{ûcÿ¢ÅXñ�� Ï'šH;€Æ?Æ«Áÿ#½‡ý±ÿÑb¼üj’äæßš?©ÉšJ”¨St¾³Óh¢Š÷O$(¢Š+7Ä?ò/jõÁÿ•iVoˆä^Ô?ëƒÿ*Ëü)z?ÈOcËäÿ‘Q?ëøÿè½KBÿ‘Mÿ¯Xÿô^['üЉÿ_Çÿ@êZü‹úoýzÇÿ Š2ÿùÒùž6þFUÂ� (¢µ= ¢Š(¯.?ò9j¿K�ýרחùµ_¥Çþ‚k¯ ¼½'2þ6ühê<ÿw_õÐ*êk–ðGüyÝ×Aü«©¥�ÿx‘í×þ# (¢¹L‚Š( 3Æÿññgþë1[Ë÷GÒ°|oÿî·ó¼¿t}+¶¿û½/ŸæoSøqù‹EW€QEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥Çë>2h.^ßODm‡ +ò öÖº«Íÿa¸ò³æym·¸â¼‚»0”£6ܺ=ŸcëaãRvæ¾§Uaãk´˜ ØÒH‰ä Ãèk¸ŠXç…%‰ƒFà2°î xízW„üÏøG-÷ç«mϦãW‹£ÅJ:d9…zÕ%F«æV½Íº(¢¸¨ (¢€9Oê25ѳ�ŠÆ€oÇñÏåX±â;G‡Rið|¹°A÷Ƭzúl"‚£SÓ¢—"±ÖøoQ’æ7¶™‹<`cÔŠÝ®oÂÖŽ¾mÛ†Ä÷çŸé]%xxÕ^J t”Ý‚Š(®S ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢é–izo\NýǸÇLâ­ÑE$’Ø©NRø�Š(¦HQEW㯽aô“ÿe®Æ¸ï}뤟û-y¹¿ûœþ_š& Ö[Ǭ_îåRÔVßñëûƒùTµèGáE[“þ<×è*¥[“þ<×è*€©EP_ˆÿä^½ÿ®ÔV‚ä'ýwo䵡â?ù¯ëŸõŸàŸùÉÿ]Ûù-tÇýÝúž=OùÃüó:J(¢¹�`(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+ŠñÇü}Yÿ¸ßÌWk\WŽ?ãêÏýÆþb¼ÌãýÒ_/̉ü'h: ZAÐRצXU¹¿ãÕ? ©Væÿ�Tü(¥Q@þ*ÿ‘nóè¿úªþ ÿ‘}ë£U�È·yô_ý UÿȾ¿õÑ«¥»¿_Ðñåÿ#hÿƒõ: (¢¹�`(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gÈŽerºžÕ¡T$–A#çšg–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*dÑ¿‘'Èßtöö©<é?¾:dóIäI󟺕 qÝû÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?òƒ#ÆöóÇÿEŠÞñßú‹/÷Ÿù Á„“ã‹ œñþ‹âæ_ÅÔîÄÿ¹Rõg¦QEí!EPY¾!ÿ‘{Pÿ®ü«J³|Cÿ"ö¡ÿ\ùVX�áKÑþB{_'üЉÿ_Çÿ@êZü‹úoýzÇÿ ŠòÙ?äTOúþ?ú¯Rпä_ÓëÖ?ýQ—ÿȶ—Ìñ°¿ò2«þhQE©íQ@yqøÏVÀíqÿ šõòâHñž­ƒÚãÿA5ׄÞ^‡“™þ4uÿ�;¯úè?•u5Ëx#þ<î¿ë þUÔÒÆÿ¼Höëÿ…Q\¦AEPãøø³ÿu¿˜®�c}£änž•Ïøßþ>,ÿÝoæ+¡Y¤Ú>sÒ»kÿ»Òùþfõ?‡˜yoýÆü¨òßû�ùRùÒ|þtyÒ|þuÄ`'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆüªÓ)û0s�ÇãU¼é?¾:´ÎßdÝ“»ŸÆ€*yoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@]OØÀÁÎWËî7åVÝØZÉÝ�ÍUó¤þùüè<·þã~UÇë> šk‡¸Ó°¡ÎZ'`ûé]��'÷ÏçG�'÷ÏçZS«*nñ9qx:8¸rU_ðÃÀ·ÒL éD!>f?ÐWq ·‘ CEcE ª@*O:OïŸÎ�:OïŸÎ�JÓ©ñƒËè`ÓT–¯«ÜO-ÿ¸ß•[ÿq¿*_:OïŸÎ�:OïŸÎ²;Dòßû�ùQå¿÷ò¥ó¤þùüèó¤þùüè9mDñ˜å‡z¡—5A|;`’o„ûÄ~U§çIýóùÑçIýóùÕÆ¬à­ÑJR[1« *…XÈ€ô¥òßû�ùRùÒ|þtyÒ|þu‰å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*ã|v¬­a�Guî×gçIýóù×ãÇgk ÌN�à5ææÿîsù~h™ü'Ymý–‘¾àííRùoýÆü©–ÓIöX~s÷ùTžtŸß?�zøQByoýÆüªÔŠM¢€p8ÅVó¤þùüêÓ» U`Np9ª§–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@u=µ >kS¹«�ÛsН¢èÍ£Ù5²»Ê —ÜS@Ò´¼é?¾:<é?¾:®wËËÐÅЦêªÍ{ÉZþByoýÆü¨òßû�ùRùÒ|þtyÒ|þu&ÂyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•Gs~¶�™gŸbäÖZøºÈÉ´É8Þ+ÇøÔÊqŽìÚž­ExE´lyoýÆü¨òßû�ùSb»óâY"›z0È`x4ÿ:OïŸÎ¨É¦�˜ž[ÿq¿*<·þã~T¾tŸß?�tŸß?�Ëî7åG–ÿÜoʗΓûçó£Î“ûçó òßû�ùQå¿÷ò¥ó¤þùüèó¤þùüè<·þã~TyoýÆü©|é?¾:<é?¾:³*“j œ*¯–ÿÜoÊ­Èì-U�9ÀæªùÒ|þtž[ÿq¿*<·þã~T¾tŸß?�fj^&³ÒßËžáš^¾\c$}})Æ.NÉÕ­N”yê4—™¥å¿÷ò£Ëî7åY:‹,u„1ÜI­÷VQŒýJ×ó¤þùüéÊ2‹´�¨×§Z<ÔäšòËî7åG–ÿÜoʗΓûçó£Î“ûçó©5Ëî7åG–ÿÜoʗΓûçó£Î“ûçó òßû�ùQå¿÷ò¥ó¤þùüé‹z¶­Â³zÓ³Þ[ÿq¿*<·þã~T¾tŸß?�tŸß?� Ëî7åG–ÿÜoʗΓûçó£Î“ûçó òßû�ùQå¿÷ò¥ó¤þùüèó¤þùüè<·þã~TyoýÆü©|é?¾:<é?¾:O-ÿ¸ß•[ÿq¿*_:OïŸÎ�:OïŸÎ€Ëî7åG–ÿÜoʗΓûçó£Î“ûçó òßû�ùQå¿÷ò¥ó¤þùüèó¤þùüè<·þã~TyoýÆü©|é?¾:<é?¾:O-ÿ¸ß•[ÿq¿*_:OïŸÎ�:OïŸÎ€Ëî7åG–ÿÜoʗΓûçó£Î“ûçó òßû�ùQå¿÷ò¥ó¤þùüèó¤þùüè<·þã~UÄøéJÝYäò7Qî+·ó¤þùüë‰ñÓ³ÝYî$ü�×ê+ÌÎ?Ý%òüÈŸÂv‚7Àùò¥òßû�ùR‰¤ÀùÍtŸß?�ze‰å¿÷ò«S)6Ê$ñÅVó¤þùüêÔ®ÂÙXÐO-ÿ¸ß•[ÿq¿*_:OïŸÎ�:OïŸÎ€1|TŒ<5xJ�0�¿Ûƒ�‡Ô…$y­ÐU�Êíá›ÀX‘„ÿÐÖ«ø.G_(V y­]+ýÝúþ‡�/ùGü©ÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þuÌ{yoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùÐyoýÆü¨òßû�ùRùÒ|þtyÒ|þtž[ÿq¿*<·þã~T¾tŸß?�tŸß?�'–ÿÜoÊ�-ÿ¸ß•/�'÷ÏçG�'÷Ïç@ å¿÷ò£Ëî7åKçIýóùÑçIýóùЖèÂu%HõÕv©Á+´Ê 9«”QEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š)“¨“ýÓü©ôÉ¿ÔIþéþT1Çtaøïßý#ÿÙ«³®3ÀŸ~ÿéþÍ]�c‡þ;³?÷©|¿$QElpQ@�ŽÿÔY¼ÿÈVò;ØÛý+Çê,¿Þä+ùì?í�þ‹âæ_ÅÔîÄÿ¹Rõg¦ÑEí!EPY¾!ÿ‘{Pÿ®ü«J³|Cÿ"ö¡ÿ\ùVX�áKÑþB{_'üЉÿ_Çÿ@êZü‹úoýzÇÿ ŠòÙ?äTOúþ?ú¯Rпä_ÓëÖ?ýQ—ÿȶ—Ìñ°¿ò2«þhQE©íQ@yqÿ‘ËUú\è&½F¼¸ÿÈåªý.?ô]xMåèy9—ñ°ÿãGQà�øóºÿ®ƒùWS\·‚?ãÎëþºå]M,oûÄ�n¿ñQEÊdQEqž7ÿ�‹?÷[ùŠÞ_º>•ƒãøø³ÿu¿˜­åû£é]µÿÝé|ÿ3zŸÃ�ÌZ(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®;Ç_zÃé'þË]�qÞ:ûÖI?öZós÷9ü¿4Lþ¬¶ÿ�X¿ÜÊ¥¨­¿ãÖ/÷ò©kÐ�Š ·'üy¯ÐUJ·'üy¯ÐURŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( +Ä÷/.ªÐvBÜŒ“úþ•‹]G‰4™e›í¶è_#*Žxï\ÀVfÚ–é€9¯6²jnç×`' aãÉÑkêt^¹qq5©$ÆSx„?¯é]e`øsJ’ÉæávË Â©ê«ï[ÕÛA5sçóÂx‰8QZœ!EPEPEP¹ãÑ>‚ªU¹ãÑ>‚ªP{ëƒk§Ü\“Là{�šòI$y¥idbÎä³1êM{Ñ$ðI ƒ)"•aìF+Ëu]ëI¹d•ÅŸ’P>Vãí]ø)E]u>[‰)U’„ׯòfx$ƒ‚+Õ4¹/´K[‰Nde!‰îA#?¥yµ†�u©N"¶‰œ“Ëcå_rkÔtû4Óì!µC‘ã>§¹üê±²�’êeÃtªª“©öm÷¿êåš(¢¼ã낊( OÄZœ²]5œlV(ølÿ ©èEiëö¯oªHä’�Ê�e×ÓácF<½�R’J ÇcáíJKÛwŠfÝ,Xù�V¶k�𵫤s\°!_ žøêk¢¯Ƽ”68+$¦ìQEsQ@Q@Q@Q@Q@Q@Q@Q@Q@q^8ÿ�«?÷ùŠíkŠñÇü}Yÿ¸ßÌW™œºKåù‘?„íAKH: ZôË ·7üz§áU*ÜßñꟅT¢Š(Å_ò-Þ}ÿC_Á¿ò/¯ýtj±â¯ùï>‹ÿ¡Š¯àßù×þº5t¯÷wëú<¿ämð~§AEW1ìQ@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQES&ÿQ'û§ùS铨“ýÓü¨cŽèÃð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,VÿŽÿÔY¼ÿÈVò;ØÛý+Å̾(ÿŠ?©Ý‰ÿr¥êÏM¢Š+Ú8BŠ( ³|Cÿ"ö¡ÿ\ùV•fø‡þEíCþ¸?ò¬±—£ü„ö<¾Oùþ¿�þ€+Ô´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú£/ÿ‘m/™ãaäeWü(ТŠ+SÚ (¢€ òãÿ#–«ô¸ÿÐMz�yqÿ‘ËUú\è&ºð›ËÐòs/ãaÿÆŽ£Áñçuÿ]ò®¦¹oÇ�×ýtʺšXß÷‰Ýâ0¢Š+”È(¢Šã‚ªPEPEPEPEP5â^X¦6vîS20<óÚ¹Õ–D“zÈÊýwÍix†ÝáÕ¤vd 2ŸÃ²«ép”á1åê�NŒb ¬vZ¨÷мSœÍ>oï Ø®c¶ïæÏpA ·`>§9ÿ?ZéëÄÆÂ0¬Ô68k$¦Ò (¢¹L‚Š( Š( Š( Š( Š( Š( Š( Š( Š( ¸ï}뤟û-v5ÇxëïX}$ÿÙkÍÍÿÜçòüÑ3øN²Ûþ=bÿp*–¢¶ÿ�X¿ÜÊ¥¯B? (*ÜŸñæ¿AU*ÜŸñæ¿ATJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ M«»v}qKEQEQEQGA“@‹qâ­*ÞSœÒÁ1®@üjýŽ¥i©F^Öep:Ž„}Ea MË’2MúŠè·EVã-Ëÿ‰ôR­Ëÿ‰ôR€ `ŒŠ(  a@ÐRÑEQEQEEqm ÔF9ãWCØÕðöœ’oòKzbEjQZF­H+FM§%¢b*…Pª`Ú–Š+2BŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¸¯ÇÕŸû�üÅvµÅxãþ>¬ÿÜoæ+ÌÎ?Ý%òüÈŸÂvƒ ¥¤-ze…[›þ=Sðª•noøõO€*QE�â¯ùï>‹ÿ¡Š¯àßù×þº5XñWü‹wŸEÿÐÅWðoü‹ëÿ]ºWû»õý_ò6�ø?S ¢Š+˜öŠ( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š)“¨“ýÓü©ôÉ¿ÔIþéþT1Çtaøïßý#ÿÙ«³®3ÀŸ~ÿéþÍ]�c‡þ;³?÷©|¿$QElpQ@�ŽÿÔY¼ÿÈVò;ØÛý+Çê,¿Þä+ùì?í�þ‹âæ_ÅÔîÄÿ¹Rõg¦ÑEí!EPY¾!ÿ‘{Pÿ®ü«J³|Cÿ"ö¡ÿ\ùVX�áKÑþB{_'üЉÿ_Çÿ@êZü‹úoýzÇÿ ŠòÙ?äTOúþ?ú¯Rпä_ÓëÖ?ýQ—ÿȶ—Ìñ°¿ò2«þhQE©íQ@yqÿ‘ËUú\è&½F¼¸ÿÈåªý.?ô]xMåèy9—ñ°ÿãGQà�øóºÿ®ƒùWS\·‚?ãÎëþºå]M,oûÄ�n¿ñQEÊdQEqž7ÿ�‹?÷[ùŠÞ_º>•ƒãøø³ÿu¿˜­åû£é]µÿÝé|ÿ3zŸÃ�ÌZ(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š( «8/aò§Œ:öõJÌ_ ج›‹ÌËýÒÃʶ¨­a^¥5hÊȸԔU“QÁÇES袲nú²Š( Š( Š( Š( Š( Š( Š( Š„]Û<±qî‡üªj/q¸µ¸QE(¢Š+Žñ×Þ°úIÿ²×c\w޾õ‡ÒOý–¼ÜßýÎ/Í?„ë-¿ãÖ/÷ò©j+oøõ‹ýÁüªZô#𢂭ÉÿkôR­Éÿkô@T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®wÆ’[iI d©�ö±Ý‘ü«¢¬Ÿimªé¦8±çFÛÓ=ý«—Ï8ÓÞ–ÚkW´{É,u[y£$áXz©<Š©,RA#G*2:ðU†­¯h³__Epñ•µ‰ƒ#†# µñxZu%Z1¦½ëœé;ž‡EWß%¹ãÑ>‚ªU¹ãÑ>‚ªPEPEPEPEP.µ­›û=¸ 62Äô_þ½a§ˆ5$“qœ8þë Áüª-i]u‹�ýKd}1ÅP¯¢Ãai*Jé;£Ñ§J‹C½ÒõÔ­|Å]N} ]®cÂjþeËs³ ?k§¯N4«8ÇcЬTfÒ (¢¹ÌŠ( Š( Š( Š( Š( Š( Š( Š( Š( ¸¯ÇÕŸû�üÅvµÅxãþ>¬ÿÜoæ+ÌÎ?Ý%òüÈŸÂvƒ ¥¤-ze…[›þ=Sðª•noøõO€*QE�â¯ùï>‹ÿ¡Š¯àßù×þº5XñH'Ãw`N�þø¨<¥t|Æë]+ýÝúþ‡‘/ùÇü©¿EW1ë…Q@aëZ᱓ìöà±–cÑúõ¹\°®º½È~¥ÉNߥw`(­O¡¾ RÔš?êI&ã8qÝYå]V™¨G©Z‰Tm`pëèk�®—ÂjùºoàùGãÍwcðÔ•'8«4o^œy.‘ÒÑEáœ!EPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEÉ¿ÔIþéþTúdßê$ÿtÿ*ãº0ü ÷ïþ‘ÿìÕÙ×àO¿ô�ÿf®Î±Ãÿ ÙŸûÔ¾_’ (¢¶8Š( GÇê,¿Þä+ùì?í�þ‹¿ã¿õ_ï?ò�üŽööÇÿEŠñs/Š?â�êwbÜ©z³Óh¢ŠöŽ¢Š(¬ßÿȽ¨×þU¥Y¾!ÿ‘{Pÿ®ü«,Gð¥èÿ!=�/“þEDÿ¯ãÿ  õ- þEý7þ½cÿÐEylŸò*'ýýW©h_ò/é¿õëþ‚(Ëÿä[KæxØ_ùUÿ 4(¢ŠÔö‚Š( ¼¸ÿÈåªý.?ô^£^\ärÕ~—ú ®¼&òô<œËøØñ£¨ðGüyÝ×Aü«©®[Áñçuÿ]ò®¦–7ýâG·_øŒ(¢Šå2 (¢€8ÏÿÇÅŸû­üÅo/ÝJÁñ¿ü|YÿºßÌVòýÑô®Úÿîô¾™½OáÇæ-Q\FEPEPEPEPEPEPEPEPEPEPVÛþû9˜¹EÜŒz㸮NºO Y¿Ÿ-ã# ±O©Ï?ʹh7ά{y”`ðòsùz�]Q^‰òaEP\w޾õ‡ÒOý–»ã¼u÷¬>’ìµææÿîsù~h™ü'Ymÿ±¸?•KQ[Ǭ_îåRס…nOøó_ ª•nOøó_ ª¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ x£�‚ñ£c¦åÎ)øÀÀ¢ŠV@QE0-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€3uM-ICnòæQ€àg#ÐÖ2xVàɉ." ê¹'ò®®Šê§Œ­N<±zƴ⬙^ÊÎe‚òŽI=Iõ5bŠ+šRrw{™¶Û» (¢�‚Š( Š( Š( Š( Š( Š( Š( Š( Š( ¸¯ÇÕŸû�üÅvµÅxãþ>¬ÿÜoæ+ÌÎ?Ý%òüÈŸÂvƒ ¥¤-ze…[›þ=Sðª•noøõO€*QEQEQEQEVf«£E©û¼¹”`>3‘èkNŠºu%N\ÑveFN.èåcð­Á“÷—õ\“]�¤V6ë# :“ÔŸSSÑZÖÅU¬­7¡S«)èŠ(®s0¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò�üŽööÇÿEŠßñßú‹/÷Ÿù ÀƒþG{ûcÿ¢Åx¹—ÅñGõ;±?îT½Yé´QE{GQEVoˆä^Ô?ëƒÿ*Ò¬ßÿȽ¨×þU–#øRô�žÇ—Éÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¼¶Oùþ¿�þ€+Ô´/ùôßúõ�ÿAeÿò-¥ó,ÿÝoæ+y~èúWm÷z_?ÌÞ§ðãóŠ(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š)’ÅјåEtnªÃ Óè iÛTe�i‚Mÿfü œ:ÒDXÐ"(U€)ÔT¨Ål‹�Z•>97êQEQ˜QEW㯽aô“ÿe®Æ¸ï}뤟û-y¹¿ûœþ_š& Ö[Ǭ_îåRÔVßñëûƒùTµèGáE[“þ<×è*¥[“þ<×è*€©EŒÁ³($ö´W›êþ'½¿¸u·™à¶ ¨v’=Iþ•^ÃÄ:�„ÊââIS?4r±`GãÒ»|·¾§Ïˈ°ê¯*‹qïÿõ * +¸ï¬âº‹îH»†{{TõÈÕ�™ïFJIJ;0¢Š)Q\ö½­Km/Ù-›k�—~ã=…kFŒ«O’%ÂnÈèh¯>MFõ$Þ·Sn÷rk­ÑuC¨Û°�4x Ž„v5шÀÎŒyïtiR„ ®jQEÄ`QEQEQEQEQEQEQEQEQEQEQEQE[—þ=è*¥[—þ=è*¥QEQEQEQEck:ßö{!PÓ‘’OEãX‰â=EdÜÒ£�î”ý9¨5 ãX¹ß×vGÓU ú>Ф®¯tz4èÕhwÚn£¥kæ ÚÀá×ÐÕÊæ<&̹?Á…ëÍtõãb©F•gìqUŠŒÚAEW9˜QEQEQEQEQEQEQEQEQEWã�øú³ÿq¿˜®Ö¸¯ÇÕŸû�üÅy™Çû¤¾_™øNÐt´ƒ ¥¯L°«sǪ~R­Íÿ©øPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEP\߉<}á H±kZ¼6ó°È…CI&=v¨$sZÚÖ 4� PÔ™w ;i. úìRØý+ç?…ß"ø™sªø›Ä÷WDnJm�ö´Ò�‹Ê.õíŽ@=³Ãß¼â{ųÓ5˜Úí¾ì2£DÍ컀Ü}†k®¯�~+|!Òü)áïøI<7%Í¿Ù%O:”¶`Ðõ1^ýóÆ9ö/‡:ôþ%ø}£j×GuÄЕ•¿¼èÅ ~%Iüh¨¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQES&ÿQ'û§ùS铨“ýÓü¨cŽèÃð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�¬{ßjWPßYJ‹º(È;ʲ� JØñßú‹/÷Ÿù Ó²ÿ� úä¿ÈW l41pŸ“;ë«à©z³“þÅñ?ýdÿÀ§£ûÄÿô“ÿž»:+ìš?Í/¼óy纜zö“os¨Ï‡$ — jÜ:W‰n ŽdÔeÙ"†\Ý?B3W‚ªU·ÿ�!ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ã¼u÷¬>’ìµØ×㯽aô“ÿe¯77ÿsŸËóDÏá:Ëoøõ‹ýÁüªZŠÛþ=bÿp*–½ü( «rÇšýT«rÇšýP* èZâÂæûÒDÈ>¤SÑM;;“(©EÅõ¬ÿÜoæ+µ®+Çñõgþã1^fqþé/—æDþ´- è)kÓ,*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEÏøïþIç‰ìuÿ¢š¸ÙãþI´¿ö—ÿAJôØÜjžÖôûDsu§Ï(H�£eQ“ÀäŠù÷Dð7ÆX› =¥±s!Ž;È1¸àÉöì?ä”kÿõÉ?ôbU‚_òHt/ûxÿÒ‰+Ë5? |nÖté´ýFIn-&IÞA†ƒëê&“àÿ�º™�¦<–ÖpîòâKÈ0¹%�SêIühéJ+çì_�óù?þÛÿ�}@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( ™7ú‰?Ý?ÊŸL›ýDŸîŸåCwF�>ýÿÒ?ýš»:ã< ÷ïþ‘ÿìÕÙÖ8᣻3ÿz—ËòAEVÇQEÈøïýE—ûÏü…iÙÇ…¿ýr_ä+3Çê,¿Þä+NËþ<-ÿë’ÿ!XCø²ù…o÷:^¬žŠ(­Ï<å¬ñèÈίøQ¡EW1ìQ@yv xÓTU“ö€ïÁ¯Q¯6±ÿ’‰wÿ]eþµÕ†væ~G‘™»Vÿï¢M_}c[u—Ì`Ù-Œ~•§ÿ Ä¿óâŸ÷ðÿ…nlOî¯åFÄþâþU¬ñT'.iS×Ô÷åVwqüL?øN%ÿŸÿ¿‡ü(ÿ„â_ùñOûø·6'÷ò®^ÑGü%ò o~?ZQxzŠOÙ쯻*œ¯îíæ\ÿ„â_ùñOûøÂ�øN%ÿŸÿ¿‡ü+sbq*6'÷ò¬}¾þ}~,�iOùŒÖu‡Ö¥„˜eP·g5Ú/ >”�…•:£^5#Æ6Hš•’IZÁEW)�QEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEKRÓ Ôà .U—”qÕkþüÌ}ª=ž»N/þ½u”Vr¥ ;´uÑÆ×£X= zv››oåB '–sÕ�\¢Š´’VG4ç)ÉÊNí…QL�¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢°µýiì6ÛÛàLÃ%ˆÎÑþ53š‚»5¡Fu¦¡ ÍÚ+Ï«¨ 7‹Éóîç—Jêôaµ(š9°'Œd‘üCÖ²§^3v;19mZç½Ñ±EVçœQEÇxëïX}$ÿÙk±®;Ç_zÃé'þË^noþç?—扟Âu–ßñëûƒùTµ·üzÅþàþU-zøQAVäÿ�5ú ©Väÿ�5ú  *QEQEQEQER3RÌ@©=©k�ñü“^µª±EŒ�üGÞº0Øw^|¨Ò�79Xé“Q²’M‰u nÀ8æ¬×š×Yá«ù.!’ÚV,b©=qé]X¬²‡<]ìkWÉdÍê(¢¼Ó˜(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢ŠãüE§Éë]*“ ¼’?„ûÖ-zI� ¨5XÚG&ôµ…_Ô ½Z9—$d¯c®žXÙ£/Ãz|–¶ï<ÊUåÆÕ=@¹EçVªêÍÎ]NiÉÎ\Ì(¢ŠÌ�¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®+Çñõgþã1]­q^8ÿ�«?÷ùŠó3�÷I|¿2'ð� è)iAK^™aVæÿ�Tü*¥[›þ=Sð  ”QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( ¹�üBð·„fX5�Z8nd@ŠÒI�Rª×oÆ:ïü#>Õu•ÉknÍ#‚ç…϶â+ƾü.Óüa¥Iâ oæ‘¢‰¥e †!�Ê�I,q�ß<{ô2¤ðG4g)"†SŽÄdW™øŸã¯…|;©Ë§D—Z•Ä,RV¶UòÑ�Á˜Œ‘ì÷­¿‰úáð§ÃMNæÑ¼©¼¥µ¶ÁåYð¹àdþÁ|øo£ÍáUñµ§[ÞÜÞ»}�.c±Æ§nBž2H'>˜Ç|€wž ø¥á¯Jm¬&–Þü)o²](W`:•Á!¿Ÿjík篌þ±ðMƑ㠚tËx±Éjy˜.¬p>ëŽ:çÞ´»äÕ4›-B1„º�'QèCç@袊‚êòÖÆ/6îæxúo•ÂÌÑk{i}›gu Ä}7à qùŠòýN‹â?ˆõ=_X2K¦ÛIäÚÛ‡*¸ü9é‚qÔµ"Òâøs®éºæ‹æÅa<žMÕ¹rÊG\sÏ#qèEz½€†ƒ�y¨ëw?bÐu¬ãɶ’Aø)4ü%>ÿ ö—ÿ�‘ÿ�Oi®ióùz¥•ÌØ'ˆá±ë€kÎ| à Yð�¶¡©Z<³ÌÎC Y~PÅGûWi£ø#AÐoÅî�hñN¦ã37¯ÐûºFŒò2ª(Éf8U[M[M¿‘£³Ô-.z¬3+‘ø\Ššoøþ×Âk4‘iÖè&»œ8ÝÏàTBÆ�øMÒ495¤ÖWÖL%fÜ£¯Rp@ÉãÒ€=.ŠÇð®°uÿ ØêN’Xñ 7©*ߨ5±@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( ™7ú‰?Ý?ÊŸL›ýDŸîŸåCwF�>ýÿÒ?ýš»:ã< ÷ïþ‘ÿìÕÙÖ8᣻3ÿz—ËòAEVÇQEÈøïýE—ûÏü…iÙÇ…¿ýr_ä+3Çê,¿Þä+NËþ<-ÿë’ÿ!XCø²ù…o÷:^¬žŠ(­Ï<å¬ñèÈίøQ¡EW1ìQ@yµ�ü”K¿úë/õ¯I¯6±ÿ’‰wÿ]eþµÓCáŸ¡ãæŸÅÃÿ�­Q\ǰËZÈá'ûïü�u5ËZÈá'ûïü�vá>Ÿáfôv—¡ÔÑEÄ`QEQEQEQEQEQEQEQEQEQEQEQEm¿ãÄ}óª•m¿ãÄ}ó  ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[øòAU*ÛÿÇ�ú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@q>'‰ÓXgaòȪTý?¥vÕVÿO·Ô`ò§SÇ*êŸjÊ´9ãdv`q+Wž[lyÕoøN'mFY@;<îHÇò5lxA<Ì›Æ)è#çóÍnÙÙAan!�6¨ä“ÔŸS\ô¨IJò=LneFt\)»¶X¢Š+´ùð¢Š(®;Ç_zÃé'þË]�qÞ:ûÖI?öZós÷9ü¿4Lþ¬¶ÿ�X¿ÜÊ¥¨­¿ãÖ/÷ò©kÐ�Š ·'üy¯ÐUJ·'üy¯ÐURŠ( Š( Š( Š( ¸ïY<ƒ\m&)¹Ð÷ØÓd�%B’"ºªÃ ×FèO˜Ò•Og+žo]O†,ž(云J‰T¸õ­4Ñôä“zÚG»ß$~F¯t®¼V=U‡$æÕq qåH(¢ŠóP¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ü¿ñèŸAU*Ü¿ñèŸAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®+Çñõgþã1]­q^8ÿ�«?÷ùŠó3�÷I|¿2'ð� è)iAK^™aVæÿ�Tü*¥[›þ=Sð  ”QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( 'âõ¤·¿ uø¡ºÂ²œu$WoÑMRø%©Ûj t¸ u2Y™ ™ð°rF~ªÊô ¡Žâ ™H¤RŽŒ2HÁ¼ Sø=ã? ë77žÖ,ç?ê>ÑåH£²¶~W±<ûw  ¿hÍkÏþÄðÅ«y“É!º’5<çîF?½{N�¥&‡áÝ;J�lí£‡#¹UŸÄó^;à_ƒšïü%ÑøŸÆ×«=Ä £„Ìey$u�º`q€ è:¾�ñSñ&•á´xVÌÝêFtO,BeÂrqøh…ý£µ(!ðv›¦i¸½ªw؈ÀŸÍÔ~5곓Nð–�c2•–ÚÆ\ ¬jò¯ð—ÂÿøŸÅ‘x£â¬D,;YY¤ åTªü¨€ó·¿§9¯z  ¾Ýö �¿{Êl}pjz(Ï>mÿ„Jï{íÏŸûá)ÿ6ÿÂî¿mM¿]¯ý3Y^Ôaøwâ=OEÖ Á§ÜÉçZ\m%qøzŒèV�jpüC×4Í E2Oe ¾uÝÀR�ýï©"€=/LÝý“g»ïy Ÿ®ÑTüO§]jÞ¾Óìš5¸¸�ËS!!y#9 Ù¤ñˆ,|/¦%íêJ`2€…A9 ‘Á#Ž*¶³w©ê�‡$hîå…. VE%”€Ûpr3ƒùÐ-§ü(Yt¸aÖµ‹Ù%�p‘ÛHQ ç09õíÖ Ñ®5Oøâß×wÒ^éwË›v�ä¡9œŒӜ֞‹ñGF}25Ö§’ÏQ‰vN�Ì8$mô8ÅfXÍ'�~!Újö¶òÇ£ék…šEǘà’1ï’8ôõ  ¼;ÿ%§Äþ÷ÙŽßÎ/é]¿‰6ÿÂ/«ïû¿b›?M†¸,¾ø…kâ¯*GÓn�CvÑŒí8ÛÏä¤zàÔž/ñ晩è2é: Ï}~<•H£aµO\ä£#ô¡ð£wü Ðç§Ÿ&>™ÿõÖ—Ž´ÍkWðáµÐnšÚ÷ÎVócÚ3‘¸séW<)£�Ã:sã͉3&?¾Ä³~¤ŠÙ  ÿ„â‡ý®?ði%zþ˜ ¶•gçï.¢�g?1g ž¼çšÓ¬éÖ¿ûÆ€,yÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß5òÛýž\ û‡ø}ª dßê$ÿtÿ*ãº0ü ÷ïþ‘ÿìÕÙ×àO¿ô�ÿf®Î±Ãÿ ÙŸûÔ¾_’ (¢¶8Š( GÇê,¿Þä+vÂX�j ùIŸ—ØVŽÿÔY¼ÿÈV�—üx[ÿ×%þB°‡ñeò= ßît½Y¥ç[ÿpß4yÖÿÜ÷ÍT¢·<óšñûÆöv{ÌlñŽÕÒi2À4kPgìñçåÿdW+ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_5|ëîûæ�:ßûƒþùª”W¨YÏ|C*ÚM‘Q�ç~UÒè_ò/é¿õëþ‚+—ñÿü�¬?ë©þFº� þEý7þ½cÿÐEtÏøõg�CþFuÂ� (¢¹�`(¢Š+Ît¶Uø‘v\dy³vú×£W›XÿÉD»ÿ®²ÿZé¡ðÏÐñóOâáÿÆ�@ó­ÿ¸?ïš<ëîûæªQ\ǰ[ó­ÿ¸?ïšä,ž1ãyX�“|œcý“]%rÖŸò8Iþûÿ#]¸O†§øY½¥èvžu¿÷ýóG�oýÁÿ|ÕJ+ˆÀ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß5)xü�Ä|ž˜¬ú¶ßñâ>ƒùÐç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(@ºCòzb¢ó­ÿ¸?ïšþ<‡ÐUJ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍTª÷—°XÀe¸}«Ðz“è)6–¬q‹“´UÙ§ç[ÿpß4yÖÿÜ÷ÍrƒÅ¶†Ly‚{ŒþUµmu ä 4qS‘–ÌÚ®µ%yÆÆ��oýÁÿ|Ñç[ÿpß5Rгß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß5Äü@xÝ´ÿ,cLñ�î×WU/tË=GgÚàìÎÜ’1ž½>•ÉŽÃËBT£»·æL•Õ�YmþÉP}Åþj—ηþàÿ¾jš¨E £ K]QVV(·ç[ÿpß5+†§®vœ]™›VÑ–üëîûæ�:ßûƒþùª”Roηþàÿ¾hó­ÿ¸?ïš©E[ó­ÿ¸?ïš<ëîûæªQ@üëîûæ�:ßûƒþùª”P¿:ßûƒþù£Î·þàÿ¾j¥oηþàÿ¾hó­ÿ¸?ïš©E[ó­ÿ¸?ïš<ëîûæªQ@üëîûæ�:ßûƒþùª”P¿:ßûƒþù£Î·þàÿ¾j¥oηþàÿ¾hó­ÿ¸?ïš©E[ó­ÿ¸?ïšå¼Y£ÜkÏf# �ÛŽÞ¦·¨¬1!ˆ¦éÏf&®¬[Ûà|ƒþù£Î·þàÿ¾j¥¸Ë~u¿÷ýóR» ˆ3 ¯aŠÏ«sǪ~yÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ·ç[ÿpß4yÖÿÜ÷ÍT¢€-ùÖÿÜ÷Íu¿÷ýóU(  ~u¿÷ýóG�oýÁÿ|ÕJ(ß�oýÁÿ|Ñç[ÿpß5RŠ»�³€Šv⧪ßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ º²µ¾‹Ê¼¶†â<çdч‘¢ÒÆÒÂ/*ÎÖ xó��Æ~B§¢€+ÞXÙêˆom ¹ˆ6à“FsëƒÞ¥Š(à…!†5Ž(Ô*" *�À‚ŸERºÑ´»é|Û½6ÎâOï˹üÈ«QE1¬qF±Æ£ ¨0ÐSè ÉKG"+£ 2°È#éUm4�6ÂC%ž�inç«C ¡?ˆrŠ(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEÉ¿ÔIþéþTúd ´.R¤ ãº0ü ÷ïþ‘ÿìÕÙ×™é½Ö†óˆíƒ™08#ÏøÖ§ü&·ÿóåþ=\”«F0IžÖ7ZµyN Gn¾GqEpÿðšßÿÏ”?øõ'ü&÷ÙÇØàϧÍþ5§Ö rÿeâ{/½ÍÃÿÂkÿ>PÿãÔÂkÿ>PÿãÔ}bþËÄv_z-xïýE—ûÏü…iÙÇ…¿ýr_ä+�Ö5«­iaIm•<²HØ9®ÆÑJYÀ¬a‚cŠT¤¥RMc)J–�9ïvMEWA圧Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEês~?ÿ�5‡ýu?È×Q¡È¿¦ÿ׬ú®_Çÿò°ÿ®§ùê4/ùôßúõ�ÿAÓ?àGÕž=ùÕÿ 4(¢Šæ=€¢Š(¯6±ÿ’‰wÿ]eþµé5æÖ?òQ.ÿ묿ֺh|3ô<|Óø¸ñ£µ¢Š+˜ö¹kOù$ÿ}ÿ‘®¦¹kOù$ÿ}ÿ‘®Ü'ÃSü,ÞŽÒô:š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®+Ä󼚱ˆ“²%GÔdŸóé]­sÞ"Ñ¥»awl»¤Q‡AÕ‡¨¬kÅʆYRë§3‘®ƒÂsºßKNÇ�qà�ñ¬Qgrdòż»ÿ»°æºïé`�=ÀiÿtW%ÉÍ4{Y�jk(·«ØÛ¢Š+Ñ>T(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢Šãu�I%Ãϧ:s“œ`ûJ­aà›§™ZúDŠ yT9cýwtWBÅTQµÏ"YU}£�Êú Š4†$Š5 ˆªŽÀS袹ÏY$•�QE (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢Šáu·wÖ.wöl¦8¬úëµ½¯_í6Øó±†SÆïþ½a&…¨¼›>ÌW݈WÑá±4�%ªVG¥N¬¦—…üË”þ )úk§ªVšºm®Ì]½O§Ò¯×‰‹©•œ£±ÃZJSmQ\æaEPEPEPEPEPEPEPEPEPEPEPVæÿ�Tü*¥[›þ=Sð  ”QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPEPEP\œßò;�÷×ÿ@ÖW'7üŽãýõÿÐc[ìúž†]½Oð¿Ðë(¢ŠØóŠ( Š( SÇñéiÿ]ùWC¦È&Ïþ¸'þ‚+žñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šòè¿ÕôD/‰–¨¢Šõ 9¿ÿÈÃþºŸäk¨Ð¿ä_ÓëÖ?ýW1ãñÿ[ÛÎ?ÈÔ:�m,´Û[V²™š’2Á† ëör�¨®§Ï¼U6eUÖ•“Hïh®/þ5ŸüøOÿ} ?ácYÿÏ„ÿ÷Ьþ­W±Ûý±�ÿŸ‹ñÿ#´¢¸¿øXÖóá?ýô(ÿ…�gÿ>ÿßB�«UìÛùø¿ò;Jókù(—õÖ_ëZ¿ð±¬ÿçÂûèV…t/ük%Ú!U”ÈáOP5­:S„fäºÌvZ„hÊíIíQ\gÑrÖŸò8Iþûÿ#]MrÖŸò8Iþûÿ#]¸O†§øY½¥èu4QEqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[oøñAüê¥[oøñAüè¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ßþ<‡ÐUJ¶ÿñä>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVäÿ�5ú ©Väÿ�5ú ©EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP¹ãÑ>‚ªU¹ãÑ>‚ªP\î«âë]>v·†#q*œ6j©ôÏ­ljR¼eÜÑýô…Ù~ òBI9<šëÂÐ�K¹w™UÂ(–�õ;Ý?ƶ·3,WPmÇ÷n_Ç�Šê+Æ«Ô<74“øzÍä$¶Ò¹>€�?AOB4Ò”LòLÒ¶*R¥[V•îjÑEÆ}QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU¹¿ãÕ? ©Væÿ�Tü(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQEQEQEW'7üŽãýõÿÐu•ÉÍÿ#¸ÿ}ôXÖû>§¡—oSü/ô:Ê(¢¶<ð¢Š(¢Š(”ñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šç¼qÿ–ŸõÑ¿•t:gü‚lÿë‚è"¼ºïõ} âeª(¢½BÉç·†çMòçŠ9SƒµÔ0ëèk/û#Lÿ u§ýø_ð­ƒÿ?‡õª”ÔšÙ‘*P“¼¢™Kû#Lÿ u§ýø_ðªz¶—§Ç£Þ¼vªë•e…A‘ÅlÕgþ@—ÿõîÿú «„å̵9ñ)*R÷Vϧ‘Íø2ÆÒêÂá®-`™„¸HÃ1ï]/öF™ÿ@ëOûð¿áX^ÿ�u×ýuþ‚ºªÓ)*®ÌäÊhÓ– ›q[vó)diŸô´ÿ¿ þ46–¬ZÞÖXŒaI…OEbå'Ôô•qwQ_pQE&�\µ§ü޾ÿÈ×S\µ§ü޾ÿÈ×ná©þoGizMQ\FEPEPEPEPEPEPEPEPEPEPEPEPVÛþ§¡—oSü/ô:Ê(¢¶<ð¢Š(¢Š(”ñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šç¼qÿ–ŸõÑ¿•t:gü‚lÿë‚è"¼ºïõ} âeª(¢½BËgþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEP\µ§ü޾ÿÈ×S\µ§ü޾ÿÈ×ná©þoGizMQ\FEPEPEPEPEPEPEPEPEPEPEPEPVÛþ‚ªU·ÿ�!ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·'üy¯ÐUJ·'üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅTªz´rK£Þ$Y.иwã¥\¢švw"¤9àâúž5Ewz¯ƒ"º�§²˜@ÌrѰÊçÛÒ£Ó¼�̲ßN²…9òÐp~¤×«õª|·¹ð¯"Æ*œŠ:w¾†×‡c’?Ù¬™Ý³<úHý1Z” Eyr|Òlûš4ý•8Óì’û‚Š(©4 (¬}c\{y0¨yÈÉÏE­)R•YrÁjTbäì�Š+��Ä·ë&ç1ºÿt®?•u}üZ�¨š>FSÕMm_ Vм¶.tevZ¢Š+”È(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( ¹9¿äwï¯þ€+¬®NoùÇûëÿ  Æ·Ùõ= »zŸá¡ÖQE±ç…Q@Q@§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­ÉÿkôR­ÉÿkôRŠ( Š( Š( Š( ªßjú|Açc“÷TrZ­W¯Lòêó<&G Åu`ðê½NW²5£OžVfÂxªÜɇ·‘SÔOå[�OÌ+,.¡ç5ÑøRgó.!ÏÉ€àzŸçé]ØÌ 8Ss†–7­B1�4NžŠ(¯ã (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(®X5{­ýwŸË·é]ådêú"j$Kç={×n¼hÔ¼öfô*(KS‹®“Â{ótƒåüùªÑø^õ¤Ã¼H½ØJé¬l¢Óí„gY�V>µÝŽÅÒ•'»¶o^¬\yQfŠ(¯á (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¢Š(¢Š(®NoùÇûëÿ  ë+“›þGqþúÿè±­ö}OC.Þ§ø_èu”QElyáEPEP)ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAÏxãþ=-?ë£*ètÏùÙÿ×ÿÐEyt?ßêú"ÄËTQEz…–ÏüxþÖªU³ÿ?‡õª”Ugþ@—ÿõîÿú «ÕGYÿ�%ÿý{¿þ‚j¡ñ#Gðgèÿ#À¿òºÿ®¿ÐWU\¯�äuÿ] ®ªµÄÿœyGû•?OÔ(¢ŠÀô‚Š( ¹kOù$ÿ}ÿ‘®¦¹kOù$ÿ}ÿ‘®Ü'ÃSü,ÞŽÒô:š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÇšýT«rÇšýT¢Š(¢Š(¢Š(¢Š(®w^Ñ¥¸›ív˽ˆÃ êqÜWEEkF´¨Ïž%ÂnèóÔ°¼’M‹k1oM†ºíK:u»0f“±Øv©Etâ1Ó­KYT¯)«Q\&EPEPEPEPEPEPEPEPEPEPEPEP¹ãÑ>‚ªU¹ãÑ>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVæÿ�Tü*¥[›þ=Sð  ”QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѪOdcæ É=MAEMösÿ=#üèû9ÿž‘þt 7ÙÏüô�ó£ìçþzGùÐ4Tßg?óÒ?Î�³Ÿùéç@ÑS}œÿÏHÿ:>Îç¤�CEMösÿ=#üèû9ÿž‘þt rsÈî?ß_ýWeösÿ=#üë�™?â» ¹~úóž>à¬k}ŸSÐË·©þúM7ÙÏüô�ó£ìçþzGùÖÇžCEMösÿ=#üèû9ÿž‘þt 7ÙÏüô�ó£ìçþzGùÐã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAƒã¸öYÙ�Ês#t>ÕÑiPgH²>b ÁöEyt?ßêú"Äɨ©¾Îç¤�g?óÒ?νBÉOüxþÖªUâŸè»7/N¹ã­Wû9ÿž‘þt QÖä ÿ^ïÿ šÔû9ÿž‘þuC[‡ùóâÞN‡ý“U‰â?ƒ?Gù÷�äuÿ] ®ª¹�G¿Mº;”~û¹öÖýœÿÏHÿ:×üVqåîTý?R*o³ŸùéçGÙÏüô�ó¬H†Š›ìçþzGùÑösÿ=#üèå­?äp“ý÷þFºÿ³Ÿùéç\•šgÆ’&åûïÎxèk· ðÔÿ 7£´½žŠ›ìçþzGùÑösÿ=#üëˆÀ†Š›ìçþzGùÑösÿ=#üè*o³ŸùéçGÙÏüô�ó h©¾Îç¤�g?óÒ?΀!¢¦û9ÿž‘þt}œÿÏHÿ:†Š›ìçþzGùÑösÿ=#üè*o³ŸùéçGÙÏüô�ó h©¾Îç¤�g?óÒ?΀!¢¦û9ÿž‘þt}œÿÏHÿ:†Š›ìçþzGùÑösÿ=#üè*o³ŸùéçGÙÏüô�ó h©¾Îç¤�g?óÒ?΀!¢¦û9ÿž‘þt}œÿÏHÿ:†­·üx� þuÙÏüô�ó« ™µÙ¹zuÏFŠ›ìçþzGùÑösÿ=#üè*o³ŸùéçGÙÏüô�ó h©¾Îç¤�g?óÒ?΀!¢¦û9ÿž‘þt}œÿÏHÿ:†Š›ìçþzGùÑösÿ=#üè*o³ŸùéçGÙÏüô�ó h©¾Îç¤�g?óÒ?΀!¢¦û9ÿž‘þt}œÿÏHÿ:†Š›ìçþzGùÑösÿ=#üè*o³ŸùéçGÙÏüô�ó h©¾Îç¤�g?óÒ?΀!¢¦û9ÿž‘þt}œÿÏHÿ:†Š›ìçþzGùÑösÿ=#üè*o³ŸùéçGÙÏüô�ó h©¾Îç¤�g?óÒ?΀!¢¦û9ÿž‘þt}œÿÏHÿ:†‘˜"–b�’O@*³Ÿùéç\ç�$’×ETG\M(FÚ{`ŸéXâ+*4¥QôvW!ºñ•„2”Š9gàºàÃ5¡¥ë¶Z¶Ve” ˜Ü`ãÔz×™U‹+‰-/¡ž"C£‚1ßÚ¾f–w_Ú';8ö2UÏX¢¦û9ÿž‘þt}œÿÏHÿ:úÃbWÿ�!ôR¯2fØ&åè9Ï_ìçþzGùÐ4Tßg?óÒ?Î�³Ÿùéç@ÑS}œÿÏHÿ:>Îç¤�CEMösÿ=#üèû9ÿž‘þt 7ÙÏüô�ó£ìçþzGùÐ4Tßg?óÒ?Î�³Ÿùéç@ÑS}œÿÏHÿ:>Îç¤�CEMösÿ=#üèû9ÿž‘þt 7ÙÏüô�ó£ìçþzGùÐ4Tßg?óÒ?Î�³Ÿùéç@ÑS}œÿÏHÿ:>Îç¤�CEMösÿ=#üèû9ÿž‘þt 7ÙÏüô�ó£ìçþzGùÐ4Tßg?óÒ?Î�³Ÿùéç@ÑS}œÿÏHÿ:>Îç¤�CEMösÿ=#üèû9ÿž‘þt 7ÙÏüô�ó£ìçþzGùÐ4Tßg?óÒ?Î�³Ÿùéç@ÑS}œÿÏHÿ:>Îç¤�CVäÿ�5ú ‹ìçþzGùÕ‡LÛÜ£�ÉÎç¤�CEMösÿ=#üèû9ÿž‘þt 7ÙÏüô�ó£ìçþzGùÐ4Tßg?óÒ?Î�³Ÿùéç@ÑS}œÿÏHÿ:>Îç¤�CEMösÿ=#üèû9ÿž‘þt 7ÙÏüô�ó£ìçþzGùÐ4Tßg?óÒ?Î�³Ÿùéç@ÑS}œÿÏHÿ:>Îç¤�%·úõü•_ª�öUmèqØ·@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( ¹9¿äwï¯þ€+¬®NoùÇûëÿ  Æ·Ùõ= »zŸá¡ÖQE±ç…Q@Q@§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€0¼A¬½€[{rÎ7ë´�rãR¾oû\û½|ÃZ>(…ÓVóùd@Tý8?çÞ±+έ99´}^IP‹J÷Üí4 aõh'ÇŸÎà1¸zÖÝqÞ…ÛRy@;2 ÷=ùô®ÆºèIÊg…˜Ò…*î0Ø(¢ŠØá ¡¬i«ªéÏlHWÎäcÙ‡ùÇãW訩N5"á-˜=O*ºÒïlå1Ím"�x!Iè{Ö¿‡ü;sswÅÔM¼d6`¹•ßQ^=,Ž”*s¹6—C5M\(¢ŠöÍ oÿCè*¥[øòAU(¢Šá5Ÿ\½Ëç0Š8ó0 ?¿=kJ”ª;DãÆãèàà¥W®ÉnÎîŠó«jVÓq'Ú"Ï̬?�è×1]ÛGq nŽE ¦�Z¥¹ž2£�OÙè×FKEV' QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnOøó_ ª•nOøó_   ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[—þ=è*¥[—þ=è*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnoøõOªU¹¿ãÕ? ©EPEPEPEPEPEPEPEPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š(¢Šå$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEW-iÿ#„Ÿï¿ò5Ô×-iÿ#„Ÿï¿ò5Û„øj…›ÑÚ^‡SEW€QEQEQEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEZöÆ ø<©Ó#¨#ªŸQXƒÂ0ù™7o³Ó`ÏçÿÖ®’ЉSŒ�Ú:)bëQ\°•‘^ÎÎ 0&Õê}Iõ5bŠ*’KDa)9;ÉÝ…QLAEPEPEP·ÿ�!ôR­¿üy ª” â<–S¤}£`¿\q^@A`ײ×3¬xB+û†¹µ”A+œº‘•'×Úºðµ£Mµ.§�žeÕqQŒéjãÐà+Òü(’GáÛ`ù,Ê¡cŠÈ°ð8Iƒß\« 9òãæú“]‚"ÆŠˆ¡UF«ÅWŒÒŒLr<²¶£­Y[K$-Q\'Ò…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[“þ<×è*¥[“þ<×è(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@åÿ�Dú ©Våÿ�Dú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[›þ=Sðª•noøõO€*QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@Q@Q@rsÈî?ß_ýWY\œßò;�÷×ÿ@�o³êzvõ?ÂÿC¬¢Š+cÏ (¢€ (¢€9OÇ¥§ýtoå]™ÿ ›?úàŸú®{Çñéiÿ]ùWC¦È&Ïþ¸'þ‚+Ë¡þÿWѾ&Z¢Š+Ô,¶ãÇðþµR­Ÿøñü?­T ¨ë?ò¿ÿ¯wÿÐM^ª:Ïü�/ÿëÝÿôU‰â?ƒ?Gù~ÿ�u×ýuþ‚ºªå| ÿ ë¯úëýuU®'ø¬ãÊ?Ü©ú~¡EV¤QEËZÈá'ûïü�u5ËZÈá'ûïü�vá>Ÿáfôv—¡ÔÑEÄ`QEQEQEQEQEQEQ\׉µYau²·r™]Ò2ž}…D桳|= W¨¡¢ó¢ó<¿17ÿwpÏåO¯0®«ÃZ¬³9²¸rø]ѳxê+x…)Y£¿•J�78ÊöÜéh¢Šé<�¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š(¢Š(¢Š+“›þGqþúÿèºÊäæÿ‘ܾ¿ú¬k}ŸSÐË·©þúeQ[xQEQEÊxãþ=-?ë£*ètÏùÙÿ×ÿÐEsÞ8ÿ�KOúèßʺ3þA6õÁ?ô^]÷ú¾ˆ…ñ2ÕQ^¡e³ÿ?‡õª•lÿÇ�áýj¥GYÿ�%ÿý{¿þ‚jõQÖä ÿ^ïÿ š¨|HÇüú?ÈÃð/üƒ®¿ë¯ôÕW+à_ù]×_è+ª­q?ÅgQþåOÓõ (¢°= ¢Š(®ZÓþG ?ßäk©®ZÓþG ?ßäk· ðÔÿ 7£´½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®7Å6¯¢.0Lr¨ô#Œ~X®Ê£žÞ+˜Z)£�Ôά9ãc«‰ú½U;]i[¾µyuq‚#‰O>¤ñ�çZÿð‹iÞfìÍŒýÍü,Ö¼ñZÂ"‚5D®zxy)^G©‹Í)Γ…5«$¢Š+°ðBŠ( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÇšýT«rÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ü¿ñèŸAU*Ü¿ñèŸAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«sǪ~R­Íÿ©øPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¢Š(¢Š(®NoùÇûëÿ  ë+“›þGqþúÿè±­ö}OC.Þ§ø_èu”QElyáEPEP)ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAÏxãþ=-?ë£*ètÏùÙÿ×ÿÐEyt?ßêú"ÄËTQEz…–ÏüxþÖªU³ÿ?‡õª”Ugþ@—ÿõîÿú «ÕGYÿ�%ÿý{¿þ‚j¡ñ#Gðgèÿ#À¿òºÿ®¿ÐWU\¯�äuÿ] ®ªµÄÿœyGû•?OÔ(¢ŠÀô‚Š( ¹kOù$ÿ}ÿ‘®¦¹kOù$ÿ}ÿ‘®Ü'ÃSü,ÞŽÒô:š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢¢žâXŒ³È¨ƒ¹¬õñœÒmóG÷ŠV�£Rjñ‹e(J[#VŠj:È�у)ƒN¬É (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·'üy¯ÐUJ·'üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ (¢€ (¢€ äæÿ‘ܾ¿ú®²¹9¿äwï¯þ€+ßgÔô2íê…þ‡YEVÇžQEQErž8ÿ�KOúèßʺ3þA6õÁ?ôT|A£I¬C G*FcbIaœÖ•¤&ÞÎ Ç¡#¾+‚•ÇR£Z4¬J^ódÔQEw”[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( 3ÄWO6¦ñ|¸@UøÉ5‘]ˆô¹~ÐoaBÈÀy€ºG¥sà@$ô¾› (:1åìztZpV:O Ý9i­X’€o_npk¥¬Oé’YÄóÎ¥d�õÞ¶ëÃÆÊ2¯'†»NnÁEW)�QEQEQEQEQEQEQEQEQEQEQEU¹?ãÍ~‚ªU¹?ãÍ~‚€*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEn_øôO ª•n_øôO ª”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU¹¿ãÕ? ©Væÿ�Tü(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQEQEQEW'7üŽãýõÿÐu•ÉÍÿ#¸ÿ}ôXÖû>§¡—oSü/ô:Ê(¢¶<ð¢Š(¢Š(¢Š(¢Š(Ùÿ�ÃúÕJ¶ãÇðþµR€ £¬ÿÈÿþ½ßÿA5z¨ë?ò¿ÿ¯wÿÐMT>$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEW-iÿ#„Ÿï¿ò5Ô×-iÿ#„Ÿï¿ò5Û„øj…›ÑÚ^‡SEW€QEQEQEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥QEQEQEQEÁjûÄhÔiôQp (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·'üy¯ÐUJ·'üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEW#âÛhú˜Ò¬¬.5MKh-ÇÝï‚@'8çMÇÖÚ¶©ý“§ÜiZ‰Hn?�ØÏÔP_EÙ$HbyeuHÑK31ÀP:“@¢¼þO‰ÆêæTм;ªÅÃM*? ¬¡ÿ}¿ÿ G¢©iÒêZMµäÖ¯k$È rICèrò«´Vt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š(¢Š(¢Š+“›þGqþúÿèºÊäæÿ‘ܾ¿ú¬k}ŸSÐË·©þúeQ[xQEQEQEQElÿÇ�áýj¥[?ñãøZ©@QÖä ÿ^ïÿ š½TuŸù_ÿ×»ÿè&ª1Ä~�ò0ü ÿ ë¯úëýuUÊøþA×_õ×ú ê«\OñYÇ”¹SôýBŠ(¬H(¢Š+–´ÿ‘ÂO÷ßùêk–´ÿ‘ÂO÷ßùíÂ|5?ÂÍèí/C©¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÛLjúçU*ÛLjúç@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š¶ÿñä>‚ªU·ÿ�!ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·'üy¯ÐUJ·'üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEÉdÂò7ÝE,~‚ŸQ\Äg´šÕÑ—ó ;øKÛ!Ö5Ùð×WWEÏQÀs�©qù wÅ»³ØiZÜ%Ý¥ØEp9Á‡äT~f�ðvP<9hÜK áfSÔŠê¦�ñ†`¾´·2Mx»W¹[?©�wöó ‹h¦^D?šÊñ^™y¬øf÷N°–8î. i…pÝ’<Œ�Æ´la6ú}´ ÷£‰Pþ ’yâµ·’yäXâ�K»±ÀP9$Ðg†4a xvËNÄ~dQ�5£èÎycžü×­ùW4�¦àÜÆƒímlÎï}œ~"¬Iâxây-¼0‡OÒ•ŠI¨ËÃ?û¾Ÿ‡=2Et¾ðvŸáx�¡/q{0ýõÔ¿yûàz ÿõÉ ?Åz½•�Å�2ãP›Ëµ°´,çŽâ€ï’µµiñ[ÃWWBk»`N³Ä~„‘øŠØþÅðÕÿ‰¥Ô ZÜêѼ·˜ð¦p1Çj‹ô‹[ÃWéw$rÌlªH öéùPÚ:ÈŠèÁ‘€*Êrõ[PÔìt›_´êqZÁ¸/™+=k•øWu=Ï‚!’Â^(ÉþèÁ–Hü+kÅ>µñf�ý™y4ÐÅæ,›¡ÆìŒúƒë@Âuá_ú4ïûþµyH¹Q<¼ŠQ½y §�Gá^ÿ /Aÿ ž¥ÿ}GÿÄ×f¿Ù¶6ö1|ÑÛF°«7R`ïÅ;É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~UÉL­ÿ È\Û×�ø®ËíoýÕ®>yIñà“;×�ø¬k}ŸSÐË·©þú_“'÷ò£É“û�ùT¿kî­kî­lyä^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ¥ì{pwc§ãU|™?¸ß•\2Ÿ³ù˜ô¨>ÖÿÝZ‹É“û�ùUj)‡~J}�û²kOíoýÕªÝÓ¶ƒ¨)UæÞAÿŽš¨|HÇüú?Èç|ŒÚmÑU'÷ݾ‚ºÏ&Oî7å\·€'h´Û 9˜uú ë¾ÖÿÝZ×üVqåîTý?R/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZÀôˆ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7å\¥¢1ñ”‹ƒ�ïÇàk°û[ÿuk‘³”�É&w¿ò5Û„øj…›ÑÚ^‡SäÉýÆü¨òdþã~U/Úßû«GÚßû«\F^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ­2·Ù6àîÀãñ¨¾ÖÿÝZœÊE¿™�ŸJ§äÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´+£@¸9Àâªù2q¿*¸Ò‘n$ÀÏÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò£É“û�ùT¿kî­kî­EäÉýÆü¨òdþã~U/Úßû«GÚßû«@y2q¿*<™?¸ß•Kö·þêÑö·þêÐ^LŸÜoÊ�&Oî7åRý­ÿº´}­ÿº´“'÷ò«2#UPp8¨þÖÿÝZ�å+“'OÉ“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuhYQ�ª¨œ*¯“'÷ò«�)XÀ8¨>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•Z•XÛ*€I㊋íoýթ䔤*à œP?&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ¼™?¸ß•LŸÜoÊ¥û[ÿuhû[ÿuh/&Oî7åG“'÷ò©~ÖÿÝZ>ÖÿÝZ‹É“û�ùQäÉýÆüª_µ¿÷V�µ¿÷V€"òdþã~Ty2q¿*—íoýÕ£íoýÕ ‚7Y”• sÚ®Õh®ZI�0jÍQEQEQEQEQEQEyýï†|Aáï]k>[{ˆoNë‹)›hÝœärRHäc'¨¤µð׈|IâMWÅkooodwAe nËg9<‘Ô òsŒq^ƒE`øµ¼@º:Ÿ (kï9rϹƒŸ¿Ç\VoЬ5ý[áìV0Áæê³Çº@蜀 ó�½Gc]…åÚ[üJÒ4Ë}>ÓÃÚzÁ\È™>ç÷½IäýkcIÔ~!Ë«[&©£XÃbÎÒ#©e_Q‰ò®æŠá|Cá-Z/ÿÂKወ£¾eÛ<ð²Œôç ã¦sš¡{eñÄð7P†ÃJ²“‰¤‰ƒ^ã†cøqõ¯I¢€(hºM¶…¤[é¶€ùP.=Xõ$û““W袀 Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@Q@Q@rsÈî?ß_ýWY\œßò;�÷×ÿ@�o³êzvõ?ÂÿC¬¢Š+cÏ (¢€ (¢€ (¢€ (¢€-Ÿøñü?­T«gþ<ëU(ª:Ïü�/ÿëÝÿôWªŽ³ÿ Kÿú÷ýÕCâF8�àÏÑþF�äuÿ] ®ª¹_ÿÈ:ëþºÿA]Uk‰þ+8ò�÷*~Ÿ¨QE�éQ@rÖŸò8Iþûÿ#]MrÖŸò8Iþûÿ#]¸O†§øY½¥èu4QEqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[oøñAüê¥[oøñAüè¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ßþ<‡ÐUJ¶ÿñä>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVäÿ�5ú ©Väÿ�5ú ©EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP¹ãÑ>‚ªU¹ãÑ>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVæÿ�Tü*¥[›þ=Sð  ”QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPEPEP\œßò;�÷×ÿ@ÖW'7üŽãýõÿÐc[ìúž†]½Oð¿Ðë(¢ŠØóŠ( ‘™QK1@É$ð-`xÂáàÐö¡Ç›*£}0Oô¬q•R¨ú!7er½ß�-!”¥½»ÎÆýÛAúpjþ“â;=Uü¥ øÈGïô=ëÍéðÊðL“FÛ]2ŸB+åéçX…Sšz®Ö2UÏ]¢š�¾5|cpêúíÍ‹gþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEP\µ§ü޾ÿÈ×SYèòE­µù•Jc·ò1]Xj‘„f¤÷LÖœ’R¿c^Š(®S ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š(¢Š(¢Š+“›þGqþúÿèºÊäæÿ‘ܾ¿ú¬k}ŸSÐË·©þúeQ[xQEV~µ¦ÿji’[‚Ÿz2{0ÿ8ükBŠŠ”ãRÙƒW<–æÖ{9Œ74n;0ÿ9­ DŸTºBceµS—�Œ=½zC"¸Ã(aî3N¼Jy#SšR¼{XÍSÔ(¢Š÷� gþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVÛþ§¡—oSü/ô:Ê(¢¶<ð¢Š(¢Š(¢Š(¢Š(Ùÿ�ÃúÕJ¶ãÇðþµR€ £¬ÿÈÿþ½ßÿA5z¨ë?ò¿ÿ¯wÿÐMT>$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEQEQEQEQEQEQEQEQEQEQEQEô‰äUÈúÓ¾Í/÷?QV-?Õ÷ªz¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ°Ñ±µÙ�›ŠžŠ¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè 66¡ù°8ªÿf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔU‡��°@>`=CìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@I5² 0Нöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEX–6kuP9â§¢€(}š_î~¢�³KýÏÔUú(‡Ù¥þçê(û4¿ÜýE_¢€(}š_î~¢�³KýÏÔUú(‡Ù¥þçê(û4¿ÜýE_¢€(}š_î~¢�³KýÏÔUú(‡Ù¥þçê(û4¿ÜýE_¢€(}š_î~¢�³KýÏÔUú(‡Ù¥þçê) €I^¸­ l¿êŸýÓ@´QEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPEPEP\œßò;�÷×ÿ@ÖW'7üŽãýõÿÐc[ìúž†]½Oð¿Ðë(¢ŠØóŠ( Š( Š( Š(  gþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEPEPEPEPEPEPEPEPEPEPEPEPÛOõGýêž ´ÿTީ袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢›½¼(óûÃó QMóûÃó£ÌOï΀E7ÌOïÎ�1?¼?:uß1?¼?:<ÄþðüèÔR ЃK@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@RPpH€Šo˜ŸÞ�bx~tê)¾bx~ty‰ýáùШ¦ù‰ýáùÑæ'÷‡ç@¢›æ'÷‡çJIÀ šZ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ('&›æ'÷‡ç@¢›æ'÷‡çG˜ŸÞ�:Šo˜ŸÞ�bx~tê)¾bx~ty‰ýáùШ¦ù‰ýáùÒ‚È9 ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢�°^¤ O1?¼?:uß1?¼?:<ÄþðüèÔS|ÄþðüèóûÃó QMóûÃó£ÌOï΀E7z“÷…:€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ l¿êŸýÓN¦Ëþ©ÿÝ4›EPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š(¢Š(¢Š(¢Š¶ãÇðþµR­Ÿøñü?­T ¨ë?ò¿ÿ¯wÿÐM^ª:Ïü�/ÿëÝÿôU‰â?ƒ?Gù~ÿ�u×ýuþ‚ºªå| ÿ ë¯úëýuU®'ø¬ãÊ?Ü©ú~¡EV¤QEQEQEQEQEQEQEQEQEQEQEQE]´ÿTÞ©ê OõGýꞀ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€)·Þ?ZJ§«jQév¦âDgËí ;Ÿò+þ8¿çÍÿï±þœªÂ.Í�4°•ªÇšº:z+˜ÿ„Î/ùóûì…ð™Åÿ>oÿ}�ð¥íé÷4þÎÅ'ä?Ãz¥ÝõåÒ\K½@Ü£åçµt•çÚ.®ºUÄÒ´&A"ããÖ×ü&qÏ›ÿßcü+*U¢£ï=N¼n¬«7JiØéè®cþ8¿çÍÿï±þø<_³ÇZº†`»·ŒÖ¾ÞŸs‘娔¯ÉùU¿ñ~=Aoü_…OZœAEPEPEË|Eñ%ç„| ¨ë–A%Õ±‹b\)(wH¨r£ôÔÑ\7Ÿê>:ðœÚ®§ ¬3¥ÛÀÙYWhT ᘜüǽw4QEQEQEQEbZø¿Ã×ÚÓèֺŬº’;£[+åÃ&w {`þT·EPEPE#)>‚¼á/ÅmwÇž$¼ÓµKM:a´3«ZÆêŃªàîvã hØh¢Š(¢Š(¢Š*´ßëMYª…ÂZC5Ì€”‰ �:œ M¤®ÀuÈÂ{üøIÿøQÿ ìóá'ýüá\Ú¸?çüùϯ®Sûb÷þ�°ùßèÙÙåàcîgóÍGÿ ìóá'ýüáXÛiÿ ?ö·�Ûwnò÷s÷qÖ¸±™•{?e=¤¯¾ÝI”Ö–=:Šä?á=ƒþ|$ÿ¿ƒü(ÿ„öùð“þþð®ßí\óþüŠç‰×Ô�ÿ­ÆÂ{üøIÿøW[§Ü%Ü0ÜFIP8®­èc(WmR•ì5$ö/ÑEÒ0¢ŠñÿüV×|?ñVÓÂÖ–šsØÍ-²4’Ææ@$ 6p;ñÅ{Q@Q@Q@Œp¤ú ñÿ„¿µßx’óNÕ-4èa†Ðέk««ƒ¹ÛŒ1 a¢¸‹^8ÔüáË=GK‚Òi¦»2Ý#2…(Í‘µ—œ¨­Ïë÷^(ðF™­^Ç w7HÌë�€‡eàOAë@Q@Q@Q@Q@“â/iÒŸQÖoÚÜ«žZFþê�É5äWÿ´®›ìº‡.®"‡žåb'ð ß΀=Ίò_ üðÖµw¦¥o>‘,‡ $ÌúÇÔŒ{׬‚C)�GzZ(¢€ÿêÛéU*Ûÿ«o¥s:ïˆáÐä†7�åyl)Àª1sv‰•zôèAԨ쑷Eqßð° ÿ |Ÿ÷ð…ð° ÿ |Ÿ÷ð…kõj½Žíœüüüù·s-ž‹wq m•*qœ¡á+û�GF2ÝHd‘edÜG$`ëX§ŒâÔ4ÉíÉÐÊ»C¥VðÿŠcÑtö¶{W”™ îPô­–~É«ks‚yµ®ÆJ§¹Êッ~Ç£Q\wü,?è'ýüáGü,?è'ýüáXýZ¯c¿ûgÿ??þGcVaÿWø×'£øº [P[1k$Nà•%� ×Yú¿Æ²œ%i#·‰¥ˆ‡='tIET›…Ïøã]ºðÏ‚õMfÊ8d¹´ˆ:,À”'p€Aïë\ÿÂOê~=ðõAi °]TZ£*•Ø­ÎænrMzQ@Q@Q@åß>$kÛFMµŒßmyŸjGllÙŒmeþùõí^�áûùu_ ézŒê‹5ݤSȨPÌ�ˆ'ŒšÑ¢¼w¿õÝsâÕÏ….m4ä°Šâê%’(ÜKˆ÷mÉ.F~Qž?*ö*(¢Š(¢Š(¢Š(¢Ž”Q^Qâ��žЯ$³Óà›Wž2UÞ >�Îsõ�zÁ²ý¥´ù' }Ộ"Ï/ ÒÊÃð*¿Î€=ÖŠÇðߊ4�éK¨è×kq;Xc u”ò lPEPx}*šãï¥rÏâèØ-¬Œ àÀfµ¥B¥[ò+ظÂSøQÑÑ\×ü&Ï›ÿßcü(ÿ„Â/ùóûì…mõGòþEû �‡ëš•Õ¦¯i 2mŒ€Ì¸ûÙb9ü«¢® TÕWPÔ!¹XŠÔ ¤ç8$ÿZØÿ„Â/ùóûì…tVÁÔtà£zìi:2å�‘ÒÑ\×ü&Ï›ÿßcü(ÿ„Â/ùóûì…sýGü¿‘Ÿ°©ØéÓï¯Ö­ÖN—|š�´w¥Al=ˆ5­\Ò‹‹q{£&švaETˆ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢²¼M©Í¢øWWÕ-–6žÎÊkˆÖ@J–D,Á¢€5h¯2øAñWø�®ú­µŒ&Í¢ý•s¿~s¹›û£Ò½6€ (¢€ (¢€ l¿êŸýÓN¦Ëþ©ÿÝ4›EPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š(¢Š(¢Š(¢Š¶ãÇðþµR­Ÿøñü?­T ¨ë?ò¿ÿ¯wÿÐM^ª:Ïü�/ÿëÝÿôU‰â?ƒ?Gù~ÿ�u×ýuþ‚ºªå| ÿ ë¯úëýuU®'ø¬ãÊ?Ü©ú~¡EV¤QEQEQEQEQEQEQEQEQEQEQEQE]´ÿTÞ©ê OõGýꞀ òOÚ'þIÅ·ý„¢ÿÐ$¯[¯$ý¢äœ[ØJ/ýJâ¼+ðÛÄžÓu—ñ °5äSµ =³¸f®ê³Î«¥[=ç‡|Nò^Æ7$M€±ެp}2?^…ðßÄš¯Ã� �kN†hícÉëÓÐ|gñoˆmu]'Â^’K{­H)’xŽî}ˆ¡¿‡�rzô÷ c¢¼)?gi¥„Owâû£©–•a,¡¾¥²~¼R|)×|E üFÔ<®_½ôP£ùNî_c( “ÎÒ§8íǾ@=ÚŠñŸ�Úþ« EáÉtÍJöÌ<ÓE­ÃEæ°€ÛHÏS×Ö›ÿ ãÄ?´õÖüUâ+«µ¨–×L¶\ÅmåCF[ÏSØ{Eò¾•¬øïÀž-Ô<¦^ý®æyÚßÍ%–&l2Ê€çoÈrGAœœâ» [à&¥.—6¥ÿ ]åæ¾¨dÌ€í‘ñ�¡‹n™ý(Þ(¯#øâÍKÄ^¿±Ôîdº—N•sJK9�ÁÀ$õÁVäúûW®PEP)ãù§ýwÉ«GA²´“B³wµ…˜§,Ñ‚O5�ãù§ýwɪ}]Ó-´kXf»D‘ ¤9úW=ÒªïØõg,yøžÆßöu—üùÛÿߥÿ ?³¬¿çÎßþý/øU?øI4ùþ�ò?áGü$š?üÿGùð­9¡ÝžËÚ_‰sû:Ëþ|íÿïÒÿ…ÙÖ_óçoÿ~—ü*Ÿü$š?üÿGùð£þMþ£ü�øQÍè=–'´¿çöu—üùÛÿߥÿ ã|U Pkök I”RB(;�¥tßð’hÿóýä¹Oß[_ë–’Ú̲"¢©#±Ük*Î.:¹|+*ךv³Þçsoü_…OP[ÿáS×Iä…PH’pAy{k§ZIw{s µ¼c/,Î{“À®9þ0ø;� øŽùÆVJÿßAqú׉x‡UÖ~4üI]M¸1é0ÈÂ~äq/ 3ÔžßP=ëÒbý�¼ ¶.µG¸Ç7e>Ë·öçë@¡¦jÚvµf·zeõ½å¹8A uϦGCí\WÆïù$ZßÖßÿGÇ^!ÿ‚ãƒíO5ƒ”wÛÂÜÛ1Ç+Ù†èG¡çÛ¾6�ß5¢ ýœ‚?ë¼t�û:ÿÉ8¹ÿ°”¿ú.:ô‹ïhZ]âYêÖ�ità‚âé#vःɯ7ý�äœ\ÿØJ_ýpä±iõímÿ£^€>š¨//mtëI.ïna¶¶Œeæž@ˆ£8å�§®#ãü’�þ¸§þŒZêôÝ_MÖ`iô½FÒúm�%¬Ë*†À8%IÁ{Ô÷7VöVÒ\ÝOF2òÊáUG©'�^Cû7ÿȇ©ØMÿôTuÄüdÖµO|N·ðe¬æ;Xf†Þ8Ë�4�NöõÆð=°}hØn>0øÖcž#€°8ÌpË"ÿßJ¤~µÑh~'ÐüK K£j–תŸ|Dùeú¯QøŠó‹ÙßÂPÙ,w—Z•ÍÆßže•Pgý•ÁÇãšòÿø?^øUñÖçÿm¼…n •"f%rCE&уÐçÔÒ€> Ôµ}3F�'Õ5K]¶,—S¬JÍŒà#œ_2ø/WÓ-h[íNãQ´‡Okëç[©'Uˆ«y›Hrqƒ‘ŽyÍ{ï‹|¥üEÐl­µ9o`�]nSìì¨ù*Få=˜×Í>ð>™¬ü`ºð•Ä×k§Åuu ɨ”¬[öä•#?(Ï•}k§jºv±lntËû[Ø2ÛL²(aÔeIä~u­­éz¯Úµ]BÚÊ à<òú õ>³<àý7Àššf›5Ì–Æf�šåÕ˜<ª��”v¯›t«SãgÄ˃{{$6Á^bHÝöx¨ƒ¦~`?3Í{ÉøËðüKåÿÂEï_³Í�Ïf+ªÑõý#ĦçHÔm¯b3A m§ÐŽ ûóƒû<ø,ÛyB]PI�õ¿h]ÙúmÇé^L,/þüd³³µ½ya2Ä coŸo!«™ëø€hëû�ô¯™fÿùu?û·þ�޾š¸ßJù—öoÿ‘çSÿ°kèØèéºçµßø_Ã2ù:Æ·km62a,^@=J.H…sŸ¼s7‚¼$¿`pš¥û˜mÛ¼` »�߀=ØW–ü5ø3ÿ –�ÿ ‰o.’Úå‹CmûÙùåÙ˜sîzäwö}/â—‚5‹…·³ñ¡•Žf ãè7�“í]}xg‹g�0é3\xbæê;蔲Û\8t›ÂR{GÓ­AðÇ—·2ø?V™ä1Fd²iOÌ¡~ô\óÀäz`�L{ÕQ@cx‹þ@×ÿõÁ¿•lÖ7ˆÿä ÿ\ùVUÿ…/Gù ìaøÎÚãI¹ií¡•„øÐ1hõ®«û/OÿŸoûò¿á\o‚õ�;MÓ."¼ºH�¦ÜÈÚ=+¥ÿ„«Cÿ „“…y¹}\:ÃAIÆöò&-X»ý—§ÿÏ�·ýù_ð£û/OÿŸoûò¿áT¿á*Ðÿè!äßáGü%Zý#ü›ü+³Ûaš?z*è»ý—§ÿÏ�·ýù_ð£û/OÿŸoûò¿áT¿á*Ðÿè!äßáGü%Zý#ü›ü(öØ_æ�Þ‚èÂñå�µ¾•lÐ[CðJ RFÓé[žÿ�5‡ýp_å\ß�5�?RÓm⳺I]fÜBƒÀÁõ®“ÿò°ÿ® ü«� (KQÁ«YlJø™³EW®XWÌ¿ÿäâ4ïúù±þk_MWÌ¿ÿäâ4ïúù±þk@MVv§â ExÓUÕì,@J «”ˆ°q¸ŒÖ�¼}¦ø D7wDMy(+kh +zŸEÏõÅx¿�ü¬|Xñž-ñl’/ʼ¯ŸƒÄq�áŒt${�ÎHú6ÊúÓR´K»¨.­¤ÎÉ �:68aÁæ Õµ½/BµûV«¨[YAœž@€ŸAž§ØU¨¡‚ÊÕ!†4†Þ ˆ‹…E€è¯”4«SãgÄ˃{{$6Á^bHÝöx¨ƒ¦~`?3Í{ÉøËðüKåÿÂEï_³Í�Ïf+ªÑõý#ĦçHÔm¯b3A m§ÐŽ ûóƒû<ø,ÛyB]PI�õ¿h]ÙúmÇé^L,/þüd³³µ½ya2Ä coŸo!«™ëø€hëû�ô¯™fÿùu?û·þ�޾š¸ßJù—öoÿ‘çSÿ°kèØèè'†_O‹þŸì¯±‰G—ý¤cù˜8Æþ7cwáš¹¢®”ºE¸ÐþÇýšò>ÆTÅŒœíÛÇ\ôï^YûGÿÈ…¦ÿØM?ôT•Õ|ÿ’Q ×'ÿÑ�@¬ÓEmÍ<©Q©gw`ª u$ž‚¸É~.ø ³lþ$¶2Œ¤r:ßaJþµäŸüMªøÛǰøDsöh§X°&Ÿø‹î§éµ�¥v:ìíáhtÕŠþóP¹¼+óÏ‹ý•ÁÀúæ€==¼A¢¦’š³êÖ)§>6ݵÂŽx98ëVloìõ;4¼°»‚îÖLìšÞA"6Gá_'|@ðö³ðÛí^­u ê…n gù‘‡n�Çã‚>˜÷�‚?òH´O­Çþ�’€:ùñ ÚÚéšõ´·p‘H&sè¡ÀÉöÕWËÿ~Yø*Âß[ÐçœÙ<Âa™·4LA*ÊÝǯ ã×�jøK¯Ýø�á¾™{}#Kt�à’F9/±ˆúœc'×4á߯/þ |e_Ã1[x.VÂ걜�1ÈõÎâ}”ÕïÞøwáoiÑÚZhÖ’2®{ˆ–Id=Ë1 ãÚ©Ù|,ðÕ‡Œ[Å0¥ÑÔÚâK’^l¦ù7nùqþÑÅv´áß~èÑøjãĺ-”V7V…Zâ($rÆHíÎGQœçŠÚøâ[�oÀòé÷r4’éscv9>S  ?O˜}¦üvñ•Ž‘àë�9•õ=H*yJrc‹ ³7¦q�ëŸcQ~ÏZÆ—à»­Nå Npñ)cA€ß‰-ø`÷ ^¢Š(¯þ­¾•ç;ÿ�¥—ýsÿÙ«Ñßý[}+ÎZ½™×íð_ͽ¿²ôÿùðµÿ¿+þeéÿóákÿ~Wü*�ü%šýcü›ü(ÿ„³Bÿ Œ“…µ{0öø/æ�Þ‹ßÙzüøZÿß•ÿ ?²ôÿùðµÿ¿+þGþÍ þ‚1þMþÂY¡ÐF?ɿŽZ½˜{|óGïGeEñ"T�d�Q€>C^‹ú¿Æ¼ãM¸Šëâ#χŠG�«ãa¯G‡ý_ãZb¾(ß²8òV�:�mÏ/Ð’Š(®cÙ8¿‹_òJüAÿ^ãÿCZãfïùõ_ûŸý•Ù|Zÿ’Wâú÷ú×û80OêÌÄ�$“ÀZP³3*#;°UQ’ÄàY6>+ðæ§v–– Ò®î_;a‚ò9°2p äñ^ñ+âF¡ã�]|à±$öó?•4Ðõº=ÔÑŽç¾=:úÃO†¶>Ò·6Ë�báGÚn±Óý„ôQúžO`;ºäõo‰¾ Ñ.ÞûÄ6‹22Eºb§Ð„¸ŸÚ ÅWú/‡¬4�>g…µ6“Ï’3†ò�.W=ƒöw¬?üÒu? Ùjþ!º»i¯"YÒÞ¬hÃ+¸�I8ÁíŒâ€=?Kø¥à�bá`³ñ¡•ŽfÝO ÞMuõó×Äo�ºF‡á{ÍoA»»W³O2K{†®™çAžsÒºÏÙÿÄ7šÇ‚.,¯ei›N¸ò¡w9"" ªçØçب—ý¦¾ÿ†>—_ûJ½›ÁŸò#xþÁ¶ßú)kÆi¯¿á�¥×þÒ¯fðgüˆÞÿ°m·þŠZ£¦Åà5ñ<�¦ÿoù’oíÚwóæd›=søæºšù—áÿüœ¦£ÿ_Ú‡ó’½Çâ‹WÁ^ ¼ÕÀV¹ŠÙ£Jßw>Ö>Êhî¿ã/x_hÖµ{kGa•�›t„z„\¶=ñUôˆñ=ÇÙô}nÚâã�Ñ»}À'ðàß>ÜüK’ëÄþ'Ô.¾Ë,ÄB<Û—x䂎œP1Šê¼[ðÎÃL}SÁ÷—ÐjvcÎŽ“w˜WŸ‘€_Ó¯­ý’šÆžÚ–JýŒ\¡› d�™ÝÓž�*Õíõ¦›g%ÝýÔ¶Ñã|ÓÈ',x�?ù[áv±w¯ütÒµKæVº¸išVQ€Ì-ÜgøÍ{§ÆŸù$zïû°ÿèøè¯µÖt»Ý=õ MJÎâÉ3ºæ)Õã\uË�Šåçø½à+k“o'‰-ËçŽ9ï¥R¿­xGÃ�Zø‰§Eá»{XH×WÒE÷¥g?*úòœÀÁ<ð+Õ¯?gÏͧ´­ms· sço9õ*FÐcð KÒõm;[²[Ý.ö ËfàK†ôã¡ö®ãwˆgðÿÃ{‘k!Ž{ùVÍ]N †›UR?ñÿ…7ZŸ‚þ1 Í.cši,î£Rv9PÅ\¨>„ú×Òzׇ´�ÚÇm¬XC{ oæ"J2`ŒþDÐ�|øm£^ømŒ Š( .>ðúWàø!žúèMH PqϽv7x}+‰ðµý­…åËÝL±« œóÍwáT�ª;èoJü’·‘ÚgÙÏ�¿ýúáGö}—üùÛÿß¡þWþ-'þcü�øQÿ “ÿ?±þGü+ŸÙ×ìÿ9jve¯ìû/ùó·ÿ¿Cü(þϲÿŸ;ûô?ªÿÂE¤ÿÏì‘ÿ ?á"Òçö?Èÿ…οgø‡-N̵ýŸeÿ>vÿ÷è…eøŽÎÖ-éã¶…Ã*GÌ*×ü$ZOüþÇùð¬Ý{ZÓ®´K˜ ºG‘‚íP?05­VUct÷]Ê„gÌ®˜xSþA)ÿ]MtµÍxSþA)ÿ]Mtµ–+øÒõ&¯ÆÂŠ(¬ ÌýO]Ò4AÕu[.|¿µ\$[ñŒãqÆGæ*=[Äš&‡§¥þ§ªZÚÚÈ3’H1'ù{·™¯ý¦Õxcýë¯ý¥G�þËñÆxÒîâH$ŒEce ìU…>POp8êIÍzn™ñSÁ½êÚYø†ØÎçj¬ªñ>€¸šéµNÇH²{ÝFò KdûÒÎá~&¾sø½ð‹L𖉻¡I:Û¬«żϿnìá”õë€AÏQUüá­oâð€x‹V¹þÁÑQmã Fé®ÐOc“�£Ü{4|%È�|Grq–†U_ûè®?Zìí®`¼¶ŽâÚhç‚E ’FÁ•‡¨#‚+Å ÑnÞ÷ÄV‚U8e„4ÅO¡Ø q´‹/´mÃF°™á:™�Ï"7–›~\ú1n}†;ÖO€þhº�†lum~êîYïaIÖw‘£ ¨'“‚3ÓÓÞ€=[Cøƒá?\-¾•®ÚÏpßv&7o¢¸þÒ×Ìßþ §„­-u É}s˜G%¹d‘6 ¥@8ãð$~×ðËYÔµÏé×ZÄS& �¡˜Ì…YÊ’{‘‚}ó@\²Ç/4Ò$q ,îìP:’OA\e×ÅßYܘ%ñ%³88ÌQÉ"ÿßJ¤~µä|Q«xóÇÉà} ØÚEp-ÌjØL>ó9¼ý6“ôí4ßÙ×ÂðéË£y¨\ÞùæŽE�Aÿepp>¤Ð§h¾!ÑüEln4}JÚö5Æã �Šgû꟭Qñïü“¿ÿØ.çÿE5|áâï êß¼kc¨h×ò½´Ù{i_‚à¾)àõ\ƒÁéô‰u8µ¯„¾©"+ÍiР4°}ù 2ý™ÿãÛÄ¿ïÛ)+ÞëÁ?føöñ/ûößÊJê~6xþãÂv—)‹TÔw•OÍ Cï0ô'8êzŠëµßøSÃS˜5mrÖÞq÷¡É"ýUA#ñ‹ñ'ÁÞ ¹[m7_µ’w8H¤Ý1ôÀ$ý+Ⱦü ‡[Ò!ÖüUut­x¾tV°°VÚy #NNs�øžÂÏŽ¾YÚhÓê^¸º7èdk9Ø?˜£“°€lv9ϵ{õã¼yâ +Ÿê³´÷v1‰mæs–xr†=Ê’¼ú7µ{=ÙÕ?û¦�M—ýSÿºh6Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š(¢Š(¢Š+“›þGqþúÿèºÊäæÿ‘ܾ¿ú¬k}ŸSÐË·©þúeQ[xQEQEQEQElÿÇ�áýj¥[?ñãøZ©@QÖä ÿ^ïÿ š½TuŸù_ÿ×»ÿè&ª1Ä~�ò0ü ÿ ë¯úëýuUÊøþA×_õ×ú ê«\OñYÇ”¹SôýBŠ(¬H(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š»iþ¨ÿ½SÔŸê�ûÕ=䟴Oü“‹oû Eÿ I^·^IûDÿÉ8¶ÿ°”_ú”Ïx7àW†‹§xL‹NҬ㵴‹îÇüÉ=I÷<ׇü^‚;¯Ž> ·•CG/ÙQÁî Ë^ÿ^ ñWþKß�¿ß³ÿÒ£@õ_?üçã_Œn§æà}§ê3p3ü€¯ +ç_½ßÂO�Rx˜ÚÉ.‹«3´�êEôÜn¸Ç¾>НŸï€´ý¬-šÛƒ.Ó _{béÍzÏÆ¯[éfõ5‘9Û•·ŽóXÿw ®½p ¬5üLÔþ!êæUgùè\®À ÷ úâ€N?ký«îžàüуím�úd×Ðà_¬¯¼ ñOLø‡glÓYHÈ·;{8_-”ún�¡õ»É>5ø4�·�\»lÜ-D/çýÜc÷Î=èÏ#Š8k�±cÙˆ¦È“ú“V¿i�øõð×û÷?Ê:æ< {¨êß´Uާ©[5µÅãMr!n©Û9Œßk§ý¦?ã×Ã_ïÜÿ(èÝm ŽÖÖ+x”,q D°¸ˆ?4¿I ‘¶—PÕg]éim“€Y°q“œ â»ÚùÏÆ·qxKö޵×õÈ]´·òå�ön|Ÿ/pʸÝ�Ïé@4~3øÃ®FKð]¥ŒOÑï2¬£×çuÿÐk“øo¬ÚþÑÅâãŸVò¥k™#?)fˆ  tí^±¨|að-…ƒ] v“·+ º³ÈÇÓãñÅxÇ…<[üy“Ä>"OìˆïØ €TF�òòOªíç§4Ô~ÓñãáÏúéqü£¯v‰U!DPª€ì+Á¿i9Rm3Ã2Äáãw�•�È ¬x5ïi÷é@ *†ý®" sÏýy÷ÊðI?äîbÿsÿl�{Ýx'ìÕ÷|Sþý·þÕ¯{¯ýš¾ïŠß¶ÿÚµïTQEÊxÇþAIÿ]Çòjf“á]:÷J·¹”ÍæH¹m®þTÿÈ%?ë¸þM[ÿ‘~Ëþ¹ÿZçåRªïØõYÒÁEÁÛÞeøBô¯ï\ßcü(ÿ„/JþõÇýö?º*+OeÇ/×qÎÎwþ½+û×÷Øÿ ?á Ò¿½qÿ}�𮊊=”;×qÎÎwþ½+û×÷Øÿ ç5Ý*ÛJÖm`·ÞQÕXï9çqÒ½¸ÿÈÃeÿ\ÓÿC5•jqŒn‘Û—âkT­Ë96¬ÎÆßø¿ ž ·þ/§®“È Âñ­ÛØø_ºˆ‘$Ztì„vo-°:ݬßé§XðÖ©¦†¼´–} !_ë@û4YÆ÷ž"¾ y±Ç*}-ÿ /å_B×Í?³Öµ‘âýSB¼>L·Ñ€Šü6"ß'× ß÷Í}-@:·…ôzhæÕ´{+éc]¨÷«•p +’øÖ‹ÁíeB¢ýœ(ÇXŸ~/j ñ ®‘£[XÝLÐy·hVb…�Ê£k yõ«ñ…î$ø%©=Ú*\´v¦eAÀ:=À{g4›û:ÿÉ8¹ÿ°”¿ú.:à>8ÿÉbÒÿëÚÛÿF½wÿ³¯ü“‹Ÿû Kÿ¢ã¯=øï*ÛüZÓ¦“!ÒÝÉö>héÚâ>0É(×ÿëŠèÅ®ÙY]C) ¤dr¯3øï­[éŸ .¬�À¸ÔdŽS<�;z¸üEdþÍÿò!ê_öýa|bøg¯Kâ“âÿ Ã5Ë?–óGoþº@äŒ*ôäÝý›ÿäCÔ¿ì&ÿú*:Ù‡ã&˜ÿO„fÓ.`œ^5˜¸ya`HSޏb>´çGí â$‹?è±]ÉÊî3o/Õ†ÏÐ ôÏ |kð�‰®"´iåÓ¯e;R+Å ¬Þ�Á+ùã5Úêz“­Eåêše�êc\B¯�¦Gó§Ç/‡Ú„“NÔ´HþÉö¹9-7–^;—<�B:r:PÓuó/�?äæ5ûj?ûR½¿á¥ýÖ§ðßA»½v{‡µ ÎÜ–ÚJ‚}IñÉÌjöÔö¥}5^}⿌¾ð¥ä–2O5ýôGl�Ù¨m�èÌHúŒ’=+Ǻ�Æ�à-sP´b·Ú9�ÇUb0ðÎ 𿀞 Ñ|KsªêšÍ´wÏfñ¬PMó -¸–eèÝ03ÇZÝŸö�žîC‹á)g�ýÓ%Ácÿ|*ÿZòÿj¾!Öþ#Xj>%²{+Ù倥»DcÙì.¹Ç^µöµ¥µ”" ˆtH�*�ÀWÌ?õ]Cãm¨µ™eû3[[ÊTä’>£8>ù ¨ßî7Ò¾eý›ÿäyÔÿìßú6:úiþã}+æ_Ù¿þG�OþÁ­ÿ£c  ÿi+—hö¤Ÿ.; ììþ€+è]Î=?@Ó¬¡EomJ¢¨Ò¼'ö”Òdz²ªLMÚ»vVr�Ç/ùW°|?ñ&ð>•¨Ã g0,S€yITÀþ#?B tµòݺ öœÙmò+jÌ0½„ äãæ¾ ¸¸†ÒÚ[‹‰(bBò;œP2I>˜¯—| ïãoÚë£}˜]M|N9H×!3ø”�}MEPX¾#ѯÿëƒ*Ú¬oÈÿþ¸7ò¬«ÿ ^�òØä¼)á»kOš{£0t—`ØÀ `OzÞÿ„ GþõÏýüáP|=ÿ�=×ý|좺úó0,<ðД ›h˜ÅXåÿáÑÿ½sÿøQÿ�ýëŸûø?ºŠ+³û? ÿ>ÐùQËÿ£ÿzçþþð£þ-û×?÷ð…uQýŸ…ÿŸh9Qç>+ðÝŽ‹a ö¦bï.ý�Á>žÕÖøw�Ãþ¸/ò¬Ÿˆ_òµÿ®ÿû)­oÿÈÃþ¸/ò®L-(RÇTŒ•�’´™³EW®XWÊÿ/Εñ±uŒHm~Ë8Bq»h ŒþõE|ÁñRÞÏ�Öv׉ š[(äCÑ”•~F€8ïÁâßÙëpHÖw“ù1JF@ä*¯dêîAêkê†^*²ño‚l®­cŠ mÐ[Ü[D¬N  :)#Øãµnk^Óõß\èWP(²ž("(Xt¨è �ú ù›ÁzÕ÷‰÷:N®Åld�[Þt§XæÃ9ú:ÐÕµçÞ+øËá? ^Ic$ó_ßDvÉ š†ØÞŒÄ€¨É#Ò·¼wªÍ¤ø[Ô¬ŸEfí Šs´‘€Ãéœ×†|ðf‹â[�WTÖm£¾{7�b‚o™mij/Fé�ž:Ðìÿ´l÷rt_ K<‡î™. ûáWú×—ø‹Uñ·ñÃQñ-“Ù^Ï,-Ú#È·ap­Î:õ¯°í­-¬¡ÚÛÅC¢D�T~¾aø·¨ÚêmE¬Ë/ÙšÚÞR§ 8|‘õÁ÷Í}Fÿq¾•ó/ìßÿ#Χÿ`Öÿѱ×ÓO÷é_2þÍÿò<êö oýw?´üˆZoý„ÓÿEI]WÁÿù%ýrýõÊþÑÿò!i¿öOý%u_ÿä”hõÉÿôcЋ|ƯñŠïQ¸ù¦\ݾ̟ÉÍ}C_,xeð'lj´ëóäÄÓÍb]øs˜ÏÐ�Ÿ�}O@5ûHZFþ ÒîÈlZˆ�Oû-“ú¢×IðGþI‰õ¸ÿÑòWûIk° ?GÐÃNÓÉTQB”\ýw?ýó]¿Áù$Z'ÖãÿGÉ@?ãËt»ý¥ ·”Ž]COG¸+5õ |Çã?ù: ?û éßú 5ôåy�ÇÏù%·?õóþ…KðþIe§ý|Íÿ¡R|{ÿ’[sÿ_0ÿèT¿ä–Z×Ìßúz%þ¡i¥ØÍ}sµ¬+ºIemª£ë^ âÿŽÚޱxtoYÌZS±nÌEæ�ÿÓ8û}NO°¬¯Šþ©ñâT> Òd"ÎÞçìê™Â¼Ãýd�ê =‚ŸZöß|>Ñ< §¬:|KÆP'½‘y)ïþêÿ²?SÍyO‚¾_êWã\ñÜò;»y†Ì˾IO¬¯Ûè}ÇJ÷袎RcXâ�B¢ ÀP8ŸEQE5ÿÕ·Ò¼ßÇŠ©gïýõ^�ÿêÛé^qã¿ù Y×?ýšºpŸÅG�žÿ¹KÕ~gAÿ�ýë¯ûø?Â�ø@4oï]ßÁþÔÑYûzŸÌtÿf`ÿçÚûŽ[þ û×_÷ð…ð€hßÞºÿ¿ƒü+©¢�oSùƒû3ÿ>×Ürßð€hßÞºÿ¿ƒü(ÿ„Fþõ×ýüá]M{zŸÌÙ˜?ùö¾ãÌt›8¬<öXwyq<Š»ŽN6ô¨Õþ5ç–¿òS&ÿ®²è½õ�iŠw”[ìŽ\’*4ªEl§/Ð’Š(®cÙ8¿‹_òJüAÿ^ãÿCZù›Âú¿‰5 ü áè˜�NèË;FpλUv“ü(6’O§_¦~-É+ñý{�ý k…ý›l­G†µ{ÿ"?µµç’fÇͰ"�¹ôÉ&€8ƒšâx#â=΋­ÚÇ·mö&–E ”7w÷Xð{}ÓÐWÔÕàŸ´� ¢xÇN‹çM±_ªŽ£¢Iøp§þèk·ø=ã±ã/ ¬7rîÕ´ð±\äó"ÿ Ÿˆ>àúŠìußi^ÓQÖ/c´µS�ÏÕ�¢�Ëa^S©~Ò˧h×÷`tyYaVú}ãúWñþþãQø�c£É1ŽÒÞÞ0€ýÐÒ1Üÿ–ü½ëÞðç…m"ƒLÒ­ÒD7�¥sê\óøtô€<+ż_ã? _ÙØxaì´·ˆ›«…G”¬c“ó�ô®Ÿöjÿ�»ÿ_Qÿè»Ï‹�®�ðË\7S,~}»[Ä åݸzž§è p³Wü€5ßúú�ÿ@4�ûM}ÿ }.¿ö•{7ƒ?äFðÿýƒm¿ôR׌þÓ_ÃK¯ý¥^ÍàÏù¼?ÿ`Ûoý´àÿäå5úþÔ?œ•ÒþÒ×nšW‡¬ÁýܳÍ+tUÿC5Í|?ÿ“”ÔëûPþrWeûGiÝxOLÕ#RËctRL ÈÉÿ�*�Æ€;φ6‘Ùü2ðìQ¬’S�WÏêÆºÊà> ë°k_ ôÄG{6“&yR§åü×i®âöòßO±žöîUŠÞÚIdnŠ dšùÀ–‘Ø~ÒfÒ Pj7ñ ”$À~•í_ä‘ë¿îÃÿ£ã¯ ø]¨�_ãÝ–¦À©¼º»¸ öß­ýkݾ4ÿÉ#×݇ÿGÇ@Çìßn‹à]NàæI©21õ dèGó¯d¯ ýœ¿ä�ߨVOýzý|Ê¿òt¿÷?ú.¾š¯™WþN—þâGÿE×}ñã\ñ‡4�QÐõ‹8ŒÒCpbÆ� g#ý—üèÔuM:ßXÒnôÛ°ÆÚî†P§« ÜòÝOöxð�Õ«®Ÿs¨Y\cäs ‘sî¤d�¡Ù|6ñü%Òµ¸óî„B–'æóS†Ï¹Æ]]|Óà/x�ÀÁzíÓÜØ•³1»À�ã'�§*qÓ¦kéjùOÅ× â�ÚWLa"�BÚ"¦=ŠíŸ@U¹ôõeQEAq÷‡Ò¸Oé6Ú­ÕÄw¢äl8ï]ÝÇÞJä¼ÿ÷õÌ:ïÂÉÆ�YE롽&Ô$ב©ÿv™ýë�ûì…ð‡iŸÞ¸ÿ¾ÇøWAEaõºÿÌÈö³îsÿð‡iŸÞ¸ÿ¾ÇøQÿv™ýë�ûì…tQõºÿÌÃÚϹÏÿ¦zãþûáT5Ÿ XXi3ÜÂfóÜÀŽXOzëë'Äßò.ÝýÿB­ MgV)Éî‹…Y¹$ÙŸá@’žòŸé]5s^ÿ�J×S]-eŠþ4½H«ñ°¢Š+œÌð/ÚgýW†?ÞºÿÚUë¾UO‡¾ ÙvÇÿ!-yí3þ«Ãï]í*õïÉ>ðßý‚­ôRÐ1ñÏþI6©ÿ] ÿÑ«Y߳ʪü5��‚Ú„¤û�¨?¥hüsÿ’Mªÿ×H?ôjÖì÷ÿ$Ñ¿ëþ_ä”éßü€uúõ—ÿA5à³Wü‡uïúö�ÿB5ïúßü€uúõ—ÿA5à³Wü‡uïúö�ÿB4ÓþÒ?ò%é_öú-ë²øKÿ$¯Ãÿõîô6®7ö‘ñEiG·öˆÿÑo]wÁùã¸øS ´l,N�ìDŒ â¾eø ÿ%_Uÿ¯)ÿôluô^·«[h:%î«xá-í!i\“Œàp¹8Ü×Íß³Ä�/Ä«éï>�+©’:õ?Œßo(^_ÜáæŽÊk€Çûìè¤þNß�}A_+ü/¹_|jŸIÔÊIm5�ø, Ä¢ÿßUõEgjÚ‘¯Gz¾™k|‘Ñ­ÄA“×éY2³¶Óþx‚ÒÎà·‡I¹Hâ�vªpa\çÅ¿‰·>‡M‡L†Òâúí™™.‘¯°<“ÇÐÕûíRÿ[ø¨êš”1Cww¡Ï3Ç!T4LW’zÞ€8ÙŸþ=¼Kþý·ò’¹/�w¦_Šj“)’SËÎ2¹.F}÷k­ý™ÿãÛÄ¿ïÛ)+ãýŒúOÄM/]D&)àFVíæDÜ�ȧç@ëûKlP«àì(j<ÿ~©ßðÓ ÿByÿÁ—ÿj¯pÑõk=wGµÕ,%ÚÝF$��ì{Bv"¥¿¿¶Òôû‹ûÉV+kxÚI]�  dÐË/w|c†Hb6ñ]¥È�ªT¸\÷ÆÑùWÕµç¾+ÃñWº²µÑn-c¶‡Íyä”0ûÀÀO'ð5è”SeÿTÿîšu6_õOþé  Ú(¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPTŸÈó"Lä竵�/ú×ÿxÐóoé'éFmý$ý*(lÛúIúQ›I?J†Š›6þ’~”fßÒOÒ¡¢€&Í¿¤Ÿ¥·ô“ô¨h  ³oé'éFmý$ý*(lÛúIúW!6ÏøN‡ÞÙ½~¿pWS\œßò;�÷×ÿ@�o³êzvõ?ÂÿC²Í¿¤Ÿ¥·ô“ô¨h­�<›6þ’~”fßÒOÒ¡¢€&Í¿¤Ÿ¥·ô“ô¨h  ³oé'éFmý$ý*(lÛúIúQ›I?J†Š¼v}—ø¶cñëUóoé'éRŸøñü?­T  ³oé'éT5¿#û ÿóöy1œtÕš£¬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘�à/+û6ë~ìùݾ‚ºÜÛúIúWà_ù]×_è+ª­q?ÅgQþåOÓõ&Í¿¤Ÿ¥·ô“ô¨h¬H›6þ’~”fßÒOÒ¡¢€&Í¿¤Ÿ¥·ô“ô¨h  ³oé'éFmý$ý*(lÛúIúQ›I?J†Š›6þ’~”fßÒOÒ¡¢€&Í¿¤Ÿ¥·ô“ô¨h  ³oé'éFmý$ý*(lÛúIúQ›I?J†Š›6þ’~”fßÒOÒ¡¢€&Í¿¤Ÿ¥·ô“ô¨h  ³oé'éFmý$ý*(lÛúIúQ›I?J†Š¿o³Ë;7c=êZ‚ÓýQÿz§ ªj:V�¬[ mNÂÖöÁÄW0¬Št8`Fy<ûÕº([[{Xím-â··‰vÇHz8¦¢Š*…Þ‡¤_ßÁy¥XÜ^ÛàÃq5º<‘àämb20yïWè ªêmŽ­döz�¤vÒ}è¦@êV¨ ?ƒþŠä\/‡ /œá¥‘—þù-·ô®ÎÞÚ Kxíí¡Ž#]©jTz8¥¢€<ÇÇ¢ð׋ì¼;®è°M ê1¯™w3n]¤�ÙM¤§�B*Ý¿‚¾él5Øìôt�z'’ë|C¾@f)ù êüGámÅšoØ5«º„ÈI!£oUaÈ5çéû¶YÐå^Vy¶ŸP� Zñ€<-â›èïu­«˜Ô(—{£:´Œ�®k¥¢€3o|;¢êVööú†‘cy ²í….­ÖQÀ.àqÀ•iQEPþÃÒ®5s¥XÿiŽ—ŸgO;îíûøÝ÷xëÓŠ¿ECLÐô�ÍþÊÒ¬l<ì>Ën‘oÆq� g=}jýPEP¹¦¶©d`I0pà‘ÇqýkxSQPÞÆì«°o¼~´•œ©FNìë£�­F�zz‡ü"Ú—üÿ'ýôÔÂ-©ÏòßM]}?W�¯öž#ºû‘çº]�Þ©4‘ÅrPÆ2K1­?øEµ/ùþOûéª_ ÚÏõÙ–@ܰÇ9®ª²¥F2�äuãqõ)Öq¦Õ´èrð‹j_óüŸ÷ÓS¢ð�ßÚb’k¸ÙU�=IÀ>õÖÑZý^#ÌñÝ}ÄÖÿÅøTõ¿ñ~=lyáEP‡üOø5¨ëOâo0Kç6kQ'–ÆAÏ™pÉŽyÏjæ×Å_m ön¦ò/Ê':`vÿ¾öí?S_JQ@ðûàö·wâTñG�Øù‰(�m¥�I$ÒCHF@ƒŽøÁÀëé¿ô=GÄuM+I·ûEìæ.-ê›¶ÊŒybàÖ»(Îþ xcX🂧Óõ»?²Ý5óÊ#óQò…•$u²þ2ü/»ñ¬vÚ¶�°ê–‘˜š`¢xòHžO^O5ëP̺7ˆ¾2øZÅ4ˆ´-Fæd^~œóyj:ëÔÙ&´?áYxãÆöº—ˆ<`ò=úÚ:éÖÕÈGË�TP{pIëïôUæ¿ü+­xGÂWÖ:å—Ù.e¾i‘<Ô“(cAœ¡#ªšæ~-ü ÔµÍi¼Ká�¯y Sqk¼#3(Àt'8##¦{׸Q@4Ûx¯ã~—²m/T¸(6¬’é†Vð0¼ýNh±øcñâ.»¡ã9ç´µ^î ‡ œ•Ž!Âþ üô¯¥¨  ö6úfŸmaiŠÚÚ%Š$ª0ä+æßøCÇ>ø§yâ_éW‹-Ü·6ó[Âg\K�ÊÊ9xŽ~¢¾š¢€8I®ø¿À×ÐxÛN6³Ý¼¶í’b>I@3ƒ“ݹö¯>ø‘ð»ÄÝxjïmŸåÚÆ%&rÅÉðãœú‚Šùò=SãwŒSì dú<|²Ü=¿Ùp=w6_þø®Æ¿µß .™{ ¥Þ®û3u$ ¹ÒpÄîTíÆ1ו9ê+ê:(‹øo¬x¯[ðìóø·Mû êͲ%04EÓhùŠ“×$ú}+Ïþ ü=ñO„|W}{®éd·–Å¢GûDRe÷¡Æ‰è {¥‹â¯ Xx¿Ã×:6¢§É˜ed_½ŽŒ¾ãüGzùî?|Røa©ÎÞYîí$<½š ’QÛtG$|} }=E|Ũ§ÆOˆQ 2÷O¾·³r<Èä€ZFyêŰXwÇ=:W±|2øomðÿI�<«sªÝ`ÜÜ(ù@3ÎÑúž}îè Š( ³µKo¶ÚÜ[nÛæÆSv3ŒŠÑªÓ­4¥$âú�À§‚µ(Á } �bÃúS¿á Õè#ýößá]Åæda{?½‘ÈŽþÝWþ‚1ÿßmþ‘ý�}ý»ý“ö³æîÛ¿{mû¹¯O®7ìw?ð°¼ß"O+výû~\lÆsõâ¸ñ™m*~ÏÙ§¬’z½…(¥kÿªÿÐF?ûí¿Â�øCu_úÇÿ}·øWqEvÿda»?½�‘+ø+R�÷а÷,¥vÚ]·Øímí·nò£ »ÎIRCþ´WFGÜ©­_˜ÔRسEWYA^ã�‡¾)Ö>3Ykö_�¥Ç=£¼ÿh‰p®ï”°n0{WºQ@yOƆ·2°¶Ôô[u“Yµ"3õO>"zeˆRr2zö¯V¢€<ïáæ�â)~Üx_ÆÚc©ZÇ!ž9<ØHÆQŽ ôÉí·ÐבŸüHø]â î¼5 ÷¶Ïò‰mc‰“9âäƒøqÎ }AE|ù©ñ»Æ)ö²} >Ynß츻›/ÿ| ×?ã_‚Úï†L½ÐRïW}™º’Üé8bw*vãëÊœõõÅü7Ö•çÿþø§Â>+¾½×t¿²[ËbÑ#ý¢)2ûÐãÄô½ÒŠó_�žÖ¼]á++Ëíw1_¬ÎžjG„¸Î\�Õ‡ç]Ã}ÿ@ø}¤izœEí¼l²Ç½[i.Är¤ƒÁ uTP”|[øLÞ3+¬èÆ8µ˜“c£�«r£ Ïf9ÏÖ¹ÿƒÕÿãÕë_´Ÿi:^¤ž2’ñîe0}ªô\�»yÁ Øçµz5QE×ÿVßJä|Káɵ¹ – Ò6�J�àà÷í]sÿ«o¥T«„Ü4L1zxŠn�E£8OøBõoú Gÿ}¿øQÿ^­ÿA(ÿï·ÿ îè­¾µPóÿ°ð�ŸÞÏ<¿ð¾§§ØÍw%ú2D»ˆWlš¯£è:޳f×0ßPå0îÙÈöú×s⤟@½Ž$.æ>FI¬ïA-¾„ÂhÚ2Ó3ÃŒŸÐÖ«/dåÖçŸ<ªŠÆÆ’O•ŽÞ÷îcÿ«ÐJ?ûíÿÂ�øBõoú Gÿ}¿øWwEeõª‡¡ý‡„ìþörz„îtÝY/n.£“`lÉ$‘Žsõ®Öõ�V«0ÿ«ük•%QÞGv K JKMÉ(¢Šƒ¤æ>"i7Úï€5�3MƒÏ¼¸„,QïUÜwÕˆ§s\ÏÁ/ ë~ðÆ¡g®Ù}’â[Ó*'š’ev(ÎP‘ÔôÚ( ËK}BÊ{;¸–[yãhå�‡ ¤`ƒøWϾøq㯇ßPдÆÔ4„”ÆX]B†{vÁ †pw;}åô¯¢h $øÉð¶ïÆbßYÑvRÞ/)àv çÇ’F à0$õàƒ×�\F—âŸ�Z%´zPЯ®„J#I.4ö�¨?x0Ô“_IQ@ÂßxüM©xëUh!qef~YùI òªçÆXãœVË_‰>ñö\>¹û ÝÔKxÓZ³ÆªÖ@@û¤ó’=«éš(Ǿ9ø#Ä^1mè:wÛ>Ê.<ïßGÝÞ^ß¾Ã9ÚzzW¦xfÎ}?š=•Ô~]ŽŒ1J™kªFG�zV­á~ø{â�/ã}爯t¿+J’îòD¸ûDM•“~ô1nr;W³êÚUž¹¤Ýiš„"kK˜Ìr!îqèGP{Wk�ø™¦kšŸ‚n—×—vÚ¤ ³ÅöYZ7”.w&Tää�Ü�@)sà/ˆ¿ õÙîü$×7¶Rœ¶A!uì²EÏ#Ôׂ3ZPhÿ¾'ËŸâ6ŸIÐ÷¸ßƒpãgÞs韔j†Ÿmt­-ôÜ_˜db—²†™ˆ'•~­�sŽqŠé¼KñûÂÖ:\ÇB–mJý”ˆG�ñƭرp >ÝhÍ~éÖöŸ´CZX!vWw©Îq¤ˆ¼÷ê+Ýþ'躇ˆ¾jÚV•oö‹Û�•õMØ•òÄÀ=My¯Àß%ÕïŒuHÝMÊ­Lƒ &âäú|š÷Šó�‚¾Ö|%àË» rÏì—R_¼ÊžjI”1ÆÊ:©ü«Ñ袀<,|=ñHøùÿ 7ö_üIþÛæý£í}ݘÎÝÛºûW®x£Ãv>,ðõÞ�¨)0μ:ýèØr¬=Áÿ Ø¢€>b_|Røg©Îþ3ÝZHßë,ÕeIGmÑ�qíÇcS]k?¼QißÙú•¬r�®VÌZîò0ü¯¥è &øQðƒþÙÿ¶µ™"ŸXd+Fr–àõÁîÄqžƒ�3œ×¬ÑEQEAq÷‡Ò¸ÓáKÄ‘ŒWq…'ƒÈ8÷®Êãï¥C[QÄN�ù:— ’†Ç'ÿÆ£ÿ?©ÿ}5ðŒj?óúŸ÷ÓWYEoõúÞ_q§Ö&p7öWz}äVÒ\–i « œV—ü#�üþ§ýôÕ'ˆmg›[³hâvRª¹#!�uÑ[R4á(µw¹¤ëIF-Ÿü#�üþ§ýôÔ�ámA†ò2bÍ]mÏý¡[Ëî3úÄÊz5�Ó¬ã·gÁ·:rkfª'ß_­[®IÉÎNOvbÛnì(¢Š‘CñÏÁ^!ñŒzÐtÿµ›S?�ûèãÛ»ËÛ÷Øgîžž•èþ²¸Ó|¢X]ÇåÜÛXA ɸ®±¨a‘Á䕯Eq´KÄ¿/ô½"Ûí7²¼E"Þ©�²)<± =ê—ÁÏ jþð;iÚÕ§ÙnÍÜ’y~b?ÊBàåI�z ST†K�"ö—t’@苜d• ò�þñ/ƒõmZ}wMû$w"D|øäÜC~ã~5íTP+ñÁ±øçÂSéU†à8šÚV "çö �~µàz-ŸÅ¯†“Ïg¦é³[;îh¢¶7P¹é¸mÎ z^•õ5óÄ>ø›ñVöpðçÂ_øÓÄ«®øòI¢·ÜD™‡�0*ð‹ùc°ï^éâ­6kÿkZfŸiçÓæ··‰HPXÆUTgr@ô­º(Èþø+ă\]{Oû!¹h ?¾ŽMÛCçî1ÇÞk¶ñׂ¬ø ÏÀ>6PÉçÞNÂK»œcÌlp죜r{×_ES_[g8ÁÎ)ÔÙÕ?û¦€)æßÒOÒŒÛúIúT4PÙ·ô“ô£6þ’~• 6mý$ý(Í¿¤Ÿ¥CEY‡ÉóWh}ݳVê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPEPEP\œßò;�÷×ÿ@ÖW'7üŽãýõÿÐc[ìúž†]½Oð¿Ðë(¢ŠØóŠ( ©êš‚iš|·N7mUþñ=\¬/[É>„Å>T‚FÓ‘ýkŸ9S¡9Ãt˜žˆâîõ�BöS$·R žª� ¥¡ø–êÒê8næimœ…%ÎJ{ƒé\õIsq ¼ŒG¹¯Š¥Š¯ªq“oó0MÜõÊ)mP3œ R×Þ�³ÿ?‡õª•lÿÇ�áýj¥GYÿ�%ÿý{¿þ‚jõQÖä ÿ^ïÿ š¨|HÇüú?ÈÃð/üƒ®¿ë¯ôÕW+à_ù]×_è+ª­q?ÅgQþåOÓõ (¢°= ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(í§ú£þõOPZª?ïTôQEQEQEQEQEQEQEQEQEQEQEQEQEÏ% éúÒy)éúÔ”P~Jz~´y)éúÔ”P~Jz~´y)éúÔ”P~Jz~´y)éúÔ”PU3Žôê( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ˜Ñ«‘Í>Š�ÉOOÖ�%=?Z’Š�ÉOOÖ�%=?Z’Š�ÉOOÖ�%=?Z’Š�ÉOOÖ•cU9š}QEQEQEQEQEQEQEZÿN²ÕlÞÏP´‚êÚO½ñ‡Søâäø/ðúIÌ­áä Np·3*þAñ]í—¢øsFð幃GÓ-¬£o½äÆo÷�SøÖ¥PEPEPEPEPEP�AïLòSÓõ©( ü”ôýhòSÓõ©( ü”ôýhòSÓõ©( ü”ôýhòSÓõ©( ü”ôýiê¡FJZ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(™×¾xKÄ×ãVÐí§¸o½2î‰ÛêÈA?�RÓ>øH�gµðí±‘NA�žl\9"»:(è-PEPEPEPEPEPYúÓ|”ôýjJ(?%=?Z<”ôýjJ(?%=?Z<”ôýjJ(?%=?Z<”ôýjJ(‚$:{Ó袀 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ l¿êŸýÓN¦Ëþ©ÿÝ4›EPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š) ¥Xô´P7wàÛ)æ2A,�rPT}=*ö•áë=)¼Ø÷I61æ?o íZÔW$08xOÚF âå[…Q]c-Ÿøñü?­T«gþ<ëU(ª:Ïü�/ÿëÝÿôWªŽ³ÿ Kÿú÷ýÕCâF8�àÏÑþF�äuÿ] ®ª¹_ÿÈ:ëþºÿA]Uk‰þ+8ò�÷*~Ÿ¨QE�éQ@GRÕ!Ób &ZFû¨:Ÿþµa�ÏædÛG³ÐŸÎºia+U�4V†°£9+¤uTU[ øu 6F8e=TÕªÂQq|²Üͦ�˜QE" (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€.Úª?ïTõB9Ú%Ú c9æŸö¹=ò  ”U?µÉè¿•k“Ñ*¹ESû\ž‹ùQö¹=ò  ”U?µÉè¿•Leamæ`f€&¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*•…¸“×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(¨^VXÀ8¨~×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò©¤•’pN(j*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¦Ëþ©ÿÝ5Wírz/åH×NÊT…Á (¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( ¹9¿äwï¯þ€+¬®NoùÇûëÿ  Æ·Ùõ= »zŸá¡ÖQE±ç…Q@Q@Q@Q@ÏüxþÖªU³ÿ?‡õª”Ugþ@—ÿõîÿú «ÕGYÿ�%ÿý{¿þ‚j¡ñ#Gðgèÿ#À¿òºÿ®¿ÐWU\¯�äuÿ] ®ªµÄÿœyGû•?OÔ(¢ŠÀô‚Š( +ÄR3ë2©< ULýk*ºOé’¼ßm… ‚�£ë›ÆN}6q•òôG§FIÁXÜ𴌺ŒˆÊÑ’G¸#ÿ¯]u`xsL’Ù^êu(î6ªž zŸÒ·ëÅÇÎ3®ÜN*í9èQEq˜…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[oøñAüê¥[oøñAüè¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ßþ<‡ÐUJ¶ÿñä>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVäÿ�5ú ©Väÿ�5ú ©EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP¹ãÑ>‚ªU¹ãÑ>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVæÿ�Tü*¥[›þ=Sð  ”QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPEPEP\œßò;�÷×ÿ@ÖW'7üŽãýõÿÐc[ìúž†]½Oð¿Ðë(¢ŠØóŠ( Š( Š( Š(  gþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEPLÄx�{hÍgêúºi¨ª|î2«ØSX倓q1ýÝœ�uÑÁÖ«hìm 3’º;**Ž—©Ç©À]FɇLôÿëUêæœ% 8ÉjŒ¥fQEH‚Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÇšýT«rÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ü¿ñèŸAU*Ü¿ñèŸAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«sǪ~R­Íÿ©øPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¢Š(¢Š(®NoùÇûëÿ  ë+“›þGqþúÿè±­ö}OC.Þ§ø_èu”QElyáEPEPEPEP³ÿ?‡õª•lÿÇ�áýj¥GYÿ�%ÿý{¿þ‚jõQÖä ÿ^ïÿ š¨|HÇüú?ÈÃð/üƒ®¿ë¯ôÕW+à_ù]×_è+ª­q?ÅgQþåOÓõ (¢°= ¢Š(Šñÿí™wtÚ»~˜ÿÖUw¶‘§�Û&OºøíèkxbüÉ´´!½¸ÿ…{ø\e/d”�š= U¡È“{ð¶ÿíq÷|£ŸÌbºÚ¥¦i±i¶åîvåÜ÷ÿëUÚòqu£V«”v9+MNwAEW1�QEQEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnOøó_ ª•nOøó_   ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[—þ=è*¥[—þ=è*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnoøõOªU¹¿ãÕ? ©EPEPEPEPEPEPEPEPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]eDmmÌþy‚#7üôØ7~u�Hs[É�8jê‹“kt×ÞKEV‡0QEQEQEQElÿÇ�áýj¥[?ñãøZ©@QÖä ÿ^ïÿ š½P_[›» ‹`ÁL±²#¦F*¢í$ÌëEÊœ¢·iœç�äuÿ] ®ª²4 ô[iby–Rï»!qŽ1Zõuä¥Q´rå´§G ušÿ0¢Š+#¸(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÛLjúçU*ÛLjúç@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š¶ÿñä>‚ªU·ÿ�!ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·'üy¯ÐUJ·'üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ÿøñü?­T«gþ<ëU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEEs)‚Öi‡TFoÈf€8=CÅ ×¼Gu¢øL[Ä–|\^Î2gŒät$àö¦ÙxŸÄ>ñ ¦‘âß³Í áÛìvqÎÉð1œô¦|„êmÌÓ^f=H ¤~¬iÿ`Vð½¥È–ÅÚÝÀ*Ùý@ü¨Ðê ˸l,§»¸}�À†Go@MS‹ iÛ¬‘+ŸÄ\·ÄùÚß82´hO¶ðOò  K-cÇ^0Y5 K=3NV:†i1îU¿>å[>ñeö¡©Ýè:íº[êöƒwÉÂʼsõä:ƒZþ·K_èñ¢€ ¤n@õe Rk�ñûÆ} â!´Ü@ñüDï^ ~T³ã^i—öz‰n—Åç*•�yäûð}€5‹}«xóÂ1¦¥¬Ée©éû€™aP­'B®=3È£FnøÝ¬K ÏÙ­�—ŸáÀ�xü ~uÚxªÝ.¼%«Âê6’‘ŸP¤ƒù�@ìo`Ôl ½¶}ðN‚D>Äf¬Wð²v›À–ªÇ>T’ ún'úÖ¿‹ÆßÞZгö6þð£ìmýá@¨«?coï >ÆßÞZгö6þð£ìmýá@¨«?coï >ÆßÞZгö6þð£ìmýá@¨«?coï >ÆßÞZгö6þð£ìmýá@¨«?coï >ÆßÞZгö6þð£ìmýá@¨«?coï >ÆßÞZгö6þð£ìmýá@¨«?coï >ÆßÞZгö6þð£ìmýá@¨«?coï >ÆßÞZгö6þð£ìmýá@¨«?coï >ÆßÞZгö6þð£ìmýá@ªÜßñꟅ7ìmýáSIxU  UŸ±·÷…coï ­EYûxQö6þð  ÔUŸ±·÷…coï ­EYûxQö6þð  ÔUŸ±·÷…coï ­EYûxQö6þð  ÔUŸ±·÷…coï ­EYûxQö6þð  ÔUŸ±·÷…coï ­EYûxQö6þð  ÔUŸ±·÷…coï ŽÛýzþ?ʯÕh­š9f€ (¢€ (¢€ (¢€ (¢€ (¢€ d±‰¡x›îº•?CO¢€<ßá$¦ÎßXÐçùn­n‹²ž¼€§BŸ¨§|\Ÿív•£AóÝÝ݆Dp_Ô¸ü«g^ð$¦«ý¯§êV¤F{~�õþ4š€àÓua«êZ�Æ­¨¨ÂMqÑ>ƒ'ŸÇŠê­áöÑ@§"4?Šæ¾"ؽÿ�µ‰K¿�QðV•$l Š�Æy Ÿ/?�?�r×äk?,cƒæM6ß3Èoæê+B_†ímw4šˆ/´˜g;ž²ËŸl0Çë[ž𕇅à—ìí$÷SœÍs1˹þ‚€98Ñ~7Üyß,z�¶"cÀ$…?úd~UÖxÚþ=;Áš¬Ò0íÚç«8Ú1ùçð¥ñ?„ìlg¯½zÙ¢þçêkÍaðN´Ÿω 1fù¬ûüÑ»"¿w¯Zôú‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?S^aaã jãã ž’唲ʂ)AÂÄÌ>lg¨ëÕ+Ì,<­[üa“Ä’CÓZY\8”nÃDÊ>^½MzWÙ¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P•é>0Ö¯>.\ør{”m.9fE‹ÊP@U$|ØÏQë^Ÿöh¿¹úšó]'Á:ÕŸÅËŸM CN’Y™\J a”�Ç^õéôÙ¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦¼ÃAñ†µ¨|W½ðõÍÊ>™ ³¢D"P@Líù€ÏoZõJó Á:ÖŸñ^ûÄÄ4ù¥�‘„ ¶8ãñ Jû4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Šò¿ øÃZÕ>)jZÝÊ>›o-ÊG‰A…ù€Ï½?ìÑsõ5æ¾ðNµ¦|RÔµë˜b[ å¹xØJ îJñô¯O ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ5æñ†µ¬üIÔô;딓O·k�b%R6>Õä ž+Õ+Ì<#à�kGø“©ëw�ĶW pce”w¾åãé@•öh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ã0e\ïRQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEŸw®é˜/5[y€Ç5Â#}‰ÍhW“ë:U–µñ¡,u|ëi-ÁdÜW8Œ‘È õè_ð”ø{þƒÚ_þGþ5¡muoy–Öâ)ã=' ?1\Áøeá1ý’G¸¹—ÿŠ®=tãà_Š:mž—4¦ÇP là1+ƒë‚2ÿ^€=NNÂæò[8/­¥º‹>d)*³¦TŽMZ¯/ñÿ„_â¶™¬�’×Q9�Až¿,£W¨P[½NÂÂH£¼½¶·yŽ#Y¥T.}�<õ�Z¯1¸ð“üeŠ/½i£Æ½7/?žöþ]o‰üIs V×D½Ô¤•X�³¡*˜ÇÞ uô  á4Fc‘  d¦á�=qO¯*øy¨ßjß5»ÍF&†êKš&R¾X  .<+ÔݶFÍ‚ÛA8MH‘F^GTEä³J¬®¡”‚¤dx"¼sÇ~4Õõ]ì—A¾Ó¬deóf¹��l…é�ÈëÕ4ù´Ïúô‹ÿ@¡EPEPEPEPEPEPEPEPEPEPEPEPEPEP}Þ»¤XN`¼Õlmæ×Œö'5ü%>ÿ ö—ÿ�‘ÿ�yî³¥Yk_ÇP‡Î¶’ÜMÅsˆÉ‚Q]Yøeá1ý’G¸¹—ÿŠ žÚêÞò!-­ÄSÆzÑðîO]ª™í‘–U�p>›²¿�v4W•è^ ŸÆÚp×¼Eª^™.Yš¡`«ƒ�Á8}jÿ„õ GÃþ1¸ð~§v÷p”ó,¦�üØÆìsÛú8 E¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(>ï]Ò,'0^j¶6ó Žk„Fûš‡þŸÐ{KÿÀÈÿƼ÷YÒ¬µ¯� c¨Cç[In &â¹ÄdŽA¨®¬ü2ð�þÉ#Ü\ËÿÅPOmuoy–Öâ)ã=' ?1QéØ\ÞKgõ´·QgÌ…%VtÁÁʃ‘ɯ,]8ø⎛g¥Í)±Ô‡…Û8 JàúàŒƒÿ׫¾"ð‹üVÓ5‘òZê G1è3Â7å”jõ «w©ØXIw—¶Öï1Äk4ª…ϰ'ž£ó«Uæ7þŒ±E÷­4xÃ7¦åçóÞÀÀhÓ¨¯5ñº‡‹¼zþ¶¾–ÏO´„KrÑ4œ~¿yF:u<ÕOøþ&]oÃúµü3ÚáÝd�ë�@=zƒ@«EsVþ*_øWéâKˆÀamæ2I÷p=oç\†…àÙüm§ {ÄZ¥é’å™ Š ±¨8qÓ€1ÇÖ€=RŠó¯ ê�‡ücqàýNíîá)æYM!ù±�Øç¶3ô*q^‹@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gÝëºE„æ ÍVÆÞ`1ÍpˆÀbsZäúΕe­|hKB:ÚKpY7Î#$r=Ezü%>ÿ ö—ÿ�‘ÿ�h[][ÞD%µ¸ŠxÏG‰ÃÌW0~x@Œd‘î.eÿâ«�]8ø⎛g¥Í)±Ô‡…Û8 JàúàŒƒÿ× S‡S°¹¼–Î ëin¢Ï™ J¬éƒƒ•#“V«ËüD?áø­¦k#äµÔ@ŽcÐg„oË(ÕêVïS°°’(ï/m­ÞcˆÖiU Ÿ`O=GçV«Ìnü$ÿb‹ïZhñ†oMËÏç½€ÿ€×¦;¤Q´’0TPY™Ž©4¬Ê¸ÜÀdàdõ¥¯×üCuâ?h·h®šB߬6yàHUÓ{ãßpþ^µëÚ¡ÞjR Ëo`¹ÆæèâH¡Ey^…àÙüm§ {ÄZ¥é’å™ Š ±¨8qÓ€1ÇÖ¯øOPÔ|?ã�êwow O2ÊiÍŒnÇ=±Ÿ¡SŠôZ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3îõÝ"Âsæ«co0˜æ¸D`±9¨á)ð÷ý´¿ü �ükÏu�*ËZøÐ–:„>u´–à²n+œFHäzŠêÏÃ/�ì’=ÅÌ¿üUtö×V÷‘ mn"ž3ÑâpÃó:�…Íä¶p_[Ku|ÈRUgL¨9šòÅÓ��~(é¶z\Ò›@(x]³€Ä®®È?ýz»â!ÿ¿Åm3Y%®¢sƒ<#~YF Pª·z�…„‘Gy{mnóF³J¨\ûyê?:µ^cp?á'øË_zÓGŒ3zn^=ìü€=:Šóˆ)âxA’GHÞ'v)Œ€s’3íOÿ kDÿ †¡ù§ÿ@�EaLöÞ ðk²³ËŸo„ÞF\ôPqêHÄh^ ŸÆÚp×¼Eª^™.Yš¡`«ƒ�Á8}hÕ(¯:𞡨øÆ7ÔîÞîže”қݎ{c?B§è´QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW�øŽ}Zßã“DµŠæü[�.)N�,ç?2öÏzõêó9ä¼Aÿ^ÇÿE°ÚÇÅ §þ)Í0{‡_þ=Yž”ê¾?ž×Ä)öïXÑ@þR$vç9'§«×™ø‰–ÛãV�(|ËuR}I2/õ³ñ;GþÔðtó"æk& Ž»G ú ½¡x–+ŸC®NÙ0Û3OÏ%Ðß™­tRÄ“ÂðÊ¡£‘J²ž„¯¸¼¼Ñ4ígÁ®òM~‹º“ÿ³b?ÌÐ}ð¦ÂC¥_ë·<ÜjW Û�uäþ,[òè5KHÓ£Ò4{=>,m·‰cÈî@äþ'&®Ð›øSþJωÿÜ?úפW›øSþJωÿÜ?úפPñcþDy?ëâ?æk¨Ðä^Ó?ëÒ/ýW/ñcþDy?ëâ?æk¨Ðä^Ó?ëÒ/ýP…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Câ9õkŒ"MÖ+›ñn<¸¥8R<³œüËÛ=ëiµ�ŠOüSš`÷¿üz«Ëÿ%âúö?ú(צP”x>SªøþyüPg_@¤[Û¼acEø}H‘Ûœäž�'ÄíûSÁÓÌ‹™¬˜\.:í7èIü+ÄL¶ß´ @Ûæ[ª“êI‘¨¯I–$ž†U ŠU”ô ðEsº‰b¹ð:äí“ ³4üò] ù‘úÖ› •®Üóq©\3n=Ô“ø±oÈWqyy¢iÚÏ‚]äšýu'ÿfÄ™¯rÒ4èô�ÏO‹mâXò;�9?‰É  µæþÿ’³â÷þ„µéæþÿ’³â÷þ„´èWV–×ÖíowoÄ �ÑÊ�”àäd:ÖV³â-Âv‹¹c�U1 ´*78Tt�£ÅÚáðï†o5PÓ"…ˆ…ØàgéœþÃxFßà zçˆu» Ífã÷¬.nˆsÐm'ïÓ Æ(Þƒe©øÇÆø«Q´k=>Õqe ýçëƒôÉ'?@3^“YVþ%ЮîÞÛX±–i4�K1ô5«@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@yˆçÕ­þ0‰4KX®oŸòâ”áHòÎsó/l÷¯^¯3—þKÄõìôQ  ¬|PÚâœÓ¸uÿãÕ™àùN«ãùçñA�|A‘onñ…�áõ Gns’zz½yŸˆ™m¾5h�·Ì·U'Ô“"ÿQ@?´íOO2.f²ap¸ë´pß¡'ð«Ú‰b¹ð:äí“ ³4üò] ù‘ú×E,I†|3ð…´Ðáäó#iÝz3ãÛ€? éô­[Áš%˜µÓµ=*Þ!Ô-Âe�©9É>æ�â[{ø/PƒL¸Šëzf&‰ÃèC‘ߌ~4{ª©á/O°ÂñÁ\gŠ?wñ‹Ãn‡çhUN=7H?©­ø³M“¶Öw×ÐZÞX¯“$s¸Œáxg¯ük3L•|_ñaµk\ɦépùi6>Wl1ÿf#ØP¦ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEä>#ŸV·øÂ$Ñ-b¹¿ãËŠS…#Ë9Ï̽³Þ¶›Xø¡´ÿÅ9¦pëÿǪ¼¿ò^ ÿ¯cÿ¢�zeyGƒå:¯�çŸÅuñ E½»Æ4P?‡Ô€I¹ÎIéÒ|NÑÿµ<<ȹšÉ…Âã®ÑÃ~„ŸÂ±¼DËmñ«@” ¾eº©>¤™úŠô™bIáxePÑÈ¥YOBP;¡x–+ŸC®NÙ0Û3OÏ%Ðß™­aü)°�éWúíÏ7•Ã6ãÝA9?‹ü…p7—š&�¬ø!ÞI¯Ña÷RölGùš÷-#N�HÑìôø±¶Þ%�#¹“øœš¶C §דxÂãÆÓi¬šåœPhÅ×í-§Í·=òÄúz Úÿ„®ï@ø‡{§k÷…4»„ßfî€"grqÔd÷{Æ2Ð`ðÅü1j6·sÜÛ¼1Å‚BK2qÐ çŸJÊñ|ú{ü �û‰ÓÏ’‘箌†÷ÈçÞ» ª§„t`½>à ÿÇqúW…ï.>ɦI-ÜèׯÃÛÔ{�ùÕßø³M“¶Öw×ÐZÞX¯“$s¸Œáxg¯üh?Å»øÅá·Có´*§›¤Ô×¥W™i’¯‹þ,6­k™4Ý.-&ÇÊí‚?àLÄ{ ôÚ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+È|G>­oñ„I¢ZÅs~-Ç—§ G–sŸ™{g½zõyœ¿ò^ ÿ¯cÿ¢�Xmcâ†Óÿæ˜=ïÿ¬ÏÊu_Ï?Š ëâ‹{wŒ,h ©’;sœ“ÓÕëÌüDËmñ«@” ¾eº©>¤™úŠÙø�£ÿjx:y‘s5“ …Ç]£†ý ?…^мKÏ€¡×'l˜m™§ç’èoÌ�Öº)bIáxePÑÈ¥YOBW�Ü^^hšv³à„Wy&¿E‡ÝIÿÙ±æh¾øSa!Ò¯õÛžn5+†mǺ‚r-ù “Åú…ψuˆ¼¤ÈTɇÔg_ùe÷~§�Ìæ» #N�HÑìôø±¶Þ%�#¹“øœšâî>^�cPÔ,|Swb׳¼®°FËÕ‰�ã8ÍPñÝ…¶—«xÆÒ1\”E›âýkwâ›2øè�,A¾›�þ‚¸OxcRÒµ� Ÿ^ß½Üå"–mÙ·;�n\¹çæŒ}Ñ]Íï„/ÿáÕ4‰õk�VêSçC,ùÜ í!X÷__â  ï ª§„t`½>à ÿÇqž(ý߯/ º�¡U8ôÝ þ¦´<âÍ6O ÛYß_Akyb¾L‘Îâ3…àž¼cñ¬Í2Uñņխs&›¥Ã夨ù]°@Çü ˜�a@›EPEPEPEPEPEPEPEPEPEPEPEPEPEP�øŽ}Zßã“DµŠæü[�.)N�,ç?2öÏzÚmcâ†Óÿæ˜=ïÿªòÿÉxƒþ½�þŠ5é”å”ê¾?ž×Ä)öïXÑ@þR$vç9'§Iñ;GþÔðtó"æk& Ž»G ú Æñ-·Æ­P6ù–ê¤ú’d_ê+Òe‰'…á•CG"•e=<@î…âX®|¹;dÃlÍ?<—@C~d~µ‡ð¦ÂC¥_ë·<ÜjW Û�uäþ,[òÀÜ^^hšv³à„Wy&¿E‡ÝIÿÙ±ækÜ´�:=#G³ÓâÆÛx–<ŽäOârh„ñ‡™�¨®×ª©á/O°ÂñÁ\n“á+¹>Üi’FVò䔈ðCWØ�£ó«þñf›'…m¬ï¯ µ¼±_&HçqÂðÏ^1øÐŠ?wñ‹Ãn‡çhUN=7H?©¯J¯2Ó%_üXmZ×2iº\>ZM�•Û À™ˆöé´QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEVaðþ–Úòëf×þ&*»ÞctÆ>îqÐúV�VF«á�[»·»Ô- ·ÿê¤Y] óŸá#½kÑ@cÜxWEº×#Ö§±WÔ#*Ë6ö¯C€pqô­Š(¢Š(6Ó@Ó,uk­RÚÛeíÐÄÒùŒwrBp:‚´¨¢€(êÚ=†¹blµ<ûrÁŠoeätåH5j#¶·ŠÞÛH9ÀsRQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@‡Ãú[kË­›_ø˜ªìy�Óû¹ÇCéZtQ@¯†4}nîÞïP´2Ü[ÿª‘et+΄Žõ¯E�qá]ë\�ZžÅ_PŒ«,ÛØr½ÁÇÒ¶(¢€ Í´Ð4ËZëT¶¶Ù{t14¾c܃Мƒ ­*(†¯£Xk¶_cÔ óí÷Ù½—‘Ó• Öü+?Ð#ÿ&eÿâ묢€9»øgM¾†öÓLòî!mÑ¿Ÿ!ÁúÅt”Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@fém¯.¶mâb«°Mæ7Lcîç¥iÑ@dj¾Ñõ»»{½BÐËqoþªE•Я9þ;Ö½V=Ç…t[­r=j{}B2¬³oaÊô8JØ¢€ 毼á�Fök˽3̸™‹Èÿh”dŸ`Ø®–ŠäÿáYøCþ�ù3/ÿ[ÚN�a¡Ø‹-6"Ü1`›Ù¹=ybM^¢€0u/øsW»7WºTRNÇ,êÌ…�©ÚFÔ°Ó¬ô«Eµ°¶ŽÞä$k�ŸSê}êÕQEQEQEQEQEQEQEQEQEQEQEQEQEQE˜|?¥¶¼ºÙµÿ‰Š®Á7˜Ý1�»œt>•§E‘ªøcGÖîíîõ C-Å¿ú©WB¼çøHïZôQ@÷ÑnµÈõ©ìUõʲͽ‡+Ðà}+bŠ(Ž©£iÚÕ¸ƒR³Šæ0r¡×•>Ǩü+2ÃÀÞÓnVâ×H„J§*Ò3Iƒê7Šèh °u/øsW»7WºTRNÇ,êÌ…�©ÚFÞ¢€*ØiÖzU¢ÚØ[Goò5ÀÏ©õ>õjŠ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬Ãáý-µåÖͯüLUv ¼ÆéŒ}Üã¡ô­:(¬�WÃ>·wow¨Zn-ÿÕH²ºç?ÂGz×¢€ Ǹð®‹u®G­Ob¯¨FU–mì9^‡àãé[PEPn§ išÅÍ�Íý·�-“ï·o1—cdàžTuÏJÒ¢ŠÁÔ¼áÍ^ìÝ^éQI;³«2>§iükRÃN³Ò­ÖÂÚ;x�‘®}O©÷«TPEPEPEPEPEPEPEPEPEPEPEPEPEPEPaðþ–Úòëf×þ&*»ÞctÆ>îqÐúV�PF«á�[»·»Ô- ·ÿê¤Y] óŸá#½kÑEcÜxWEº×#Ö§±WÔ#*Ë6ö¯C€pqô­Š(  Z–“§ëÿgÔl⹈�"çiõ¨ü+3Oð?†´»•¹´ÒaY”åYÙ¤Ú}Fâq]V¥à¿j÷fê÷JŠIØå�Y�±õ;HÏã[ÔP[ :ÏJ´[[ híà^BF¸õ>§Þ­QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿÙkalign-3.5.1/doc/images/Balibase_scores.png000066400000000000000000014651061515023132300205750ustar00rootroot00000000000000‰PNG  IHDRM‰éì§gAMA±� üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYs.#.#x¥?vtIMEã , À¡€IDATxÚìÝw¼œUµ7ðµ÷~žgúéé z4ô¤ÄK»AT¬z±ÐT®íµƒ×ËUAA¼\PT Š¡%�BI(é§Î™ö”½÷ûÇ:³™œä¤òû~üàdÎÌ3O�²ÖÞk k-Œ@rK¯À[„<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<Ç6*Š"cLã=aZk‡yеvÐS´ÖÖZ­u’$I’ úë–â¶BkíþKDqó?ùž0 Ý�ÖÚ(ŠÜ’$áÿºE…aØøØ‚p\6'¾ˆûyS¨V«D¤µæ·#ÞÛÖZ·ÛYǵZmK¯,ÀÖK Ú†w6­u¥R‘Rf³Y!Ä>ž3B!„1Æ£”ôDk­µVÊ-“BK’Äó¼$Iâ8Îd2DÔßߟÍf£( ‚@)EDqû¾_­V}ß÷<¯ñ¹µZ-‚ øž(Ьµ¾ïo©Í�õÂqÙÔªÕ*_>|Éó~Ã0•JméU{§‰ãØÓ¸c�1¼Ã+•J&“y3ïÌÛ8ä9¶Q<(Þ÷ýÆ;ã8æLÀº† ('IÂâ‰BˆAËÜÌ8ŸDZ‚.“Á·] ‘ÕjµZ­–Éd8ÎÈIÞ(÷D7#DkíR °E4P—MÇZ+„à½ÍÓ¶]M°±¸”R¹\&¢ ¤”ü>Ì;¼¯¯¯¹¹™?©‘óX/ä9¶]Q)¥”RÖÚjµêyžçyCå3\LYÔ­÷aÆ>£†Ê—lžíâ¨wÇZët:],›ššÂ04ÆpH‘ m¥ÓéÆ5�㘳Æ^ˆÛ’ 8<áÇe3àK^)eŒI’™¤MAkmŒáÜpc –“œm*•Jù|~K¯)ÀV yŽm”ÖšË7½É„„1f½é�J¥BDJ© Ü_Í™ØÌ*•ŠÖ:“Éc88kŒ ð±J•™nŒÑZ»ÑӃ棸¨:é’R"¤¾5ÀqÙÔ´Öår¹©©ÉÝS.—}ßG¶cãâL†ËÈQ©Tr¥óøÜæœkc"AžcåýýýýAø¾Ï�ɧ84Z7ŽÌ:÷OW*jËn—K±¸ÝÝÝmmmü×AÙ�r¹œË刨Z­¦ÓiÞ®‰†¡RÊå<m,l)µZ Çe3pÉ¿žžžL&3ÔÛlår™ß„{{{óù¼çyü.d­�¢È÷}NÓnÙ’€[3 ‚ÞFq{á0 ƒ H¥R<4>›ÍÊ!p}®`Ç1O} ¢b±Eñl ­u’$¼ð-BJ¹jÕ*"J’¤»»›ˆ8Ɇ¡ÖºV«¥Ói¥TÇD”ËåV¯^MD™L†‹ã‘çyB;QµZ­Õj¼±î1°¥à¸l¼KËårkkk:�®T*¼Ã·ôz½Óð|8—Ãhiiñ<¯³³3›Íò¹Í=“R©T†[ze¶^Èsl£x°¶”2•Jõôô|ö³ŸÍårbhܽƒ‡ÒA�ËåZZZÆŽ{ÜqÇ}ík_»ýöÛ»ººx±œ'ØRÛõ÷¿ÿ}üøñœ¼5jÔ 7Ü@DQ¥R)¥T.—ÓZ_yå•Bˆl6;yòäÙ³g‘ïûœž‘RZk¹ —b»í¶ûïÿþïÞÞ^"BÑž-ÇeóhjjzüñÇG�ŕܚšš~ó›ß`VÇF7¨Jõ÷÷{ì±ü.šN§O<ñÄb±¨”Êçó[0 °•CžcÅíÇ9ÛÑÜÜÜßßï’ܩۑRº82÷áH¥RƘ¾¾¾U«VÍ�;÷Š+®˜5kÖ®»îzÕUWQOO�"I"êëëã'j­yÚÇfØ..dïyž1†ÿÙ×Zçóùb±èy^µZ�¢¨££ƒˆxRKE|?7a–Rvvvj­[ZZ¬µ¨³Ù¸zzî7YÁqÙl²ÙlµZõ<�gh �"‡§Wƒ °Ö¦Óik-çbù<7ÆDQT(ˆÈZ‹&4CAÜsR8 b­å´�µ–Óar{�T*åû~ǹ\®§§çsŸûÜÁÜ××Ç]´ÖÍÍÍDT*•xžÇ�lŒá¬†kLBõ©•J¥T*ñVszãÖF ä9`0ÎFp³ "²ÖZk9À÷û¾/¥L’$ Ã8Ž�1årÙZÛÔÔôÈ#�|âŸX±b…RªZ­òSx8·÷ØRź‚ Èf³œ¿áQêJ©¦¦¦|>ŸJ¥¨žùØmÏÏÆ­´ë^�®®.÷H¾Çí^·Z­æÎ(wtúúúxŒ1¼2<�ŒêgšÛFwcÍš5î…ød µOKª_¼@‡ÿé."ÞŸZk·2nÉ�§ºµÖíÞA‹êííu{†§Í‘BkÍ'Ø–øã5áÍçÝҸ놺„ÞÁПÞžè@DŒãžäúô}¿T*år¹±cÇŽ=zõêÕD$„5jT­VBxžÇ �$Ix9™LfõêÕ¹\Î÷ý¾¾¾(ŠæÌ™sß}÷=ðÀ«V­ªV«ÕjµP(Œ?>—Ë�tÒI{ì±Ç¿ÿû¿ …jµšÉdjµZ:�ÞÐMà5÷<ÏZÛÕÕÕÑÑ‘ÏçyQA$I¢”RJYk{{{¹Ë‡qÇ�EQ6›å^#<ðÀÕW_ýÄOh­_}õU­õ�8iÒ¤ã�?þCú¿VSSSgg§Ë—¬Ë÷ýJ¥ÂñúÎÎÎr¹¼`Á‚»îºëŸÿüg___ggg__ŸµvìØ±ûì³Ï»Þõ®Oûìn»íV*•¦N�zÔQGpÀ‡rH­V+ Åb±©©©q �1I’A`Œá�ÓÛÛ›Ïç=Ïã°øõ×_ÿç?ÿ¹¿¿ÿÅ_\¹råN;í”Íf÷Ýwß8àsŸû\___sss*•âI’”Ëåæææt:í24ÚµeS—t:ÍeÖâ8æù=ÝÝݳgϾ÷Þ{/^¼téÒ8Ž=Ïëèè8ä�C;ì°O<1›Í.[¶lüøñJ©\.×ÕÕÕÞÞΛLDJ)­5ÏdâCfŒ Ã0“É”ËåT*ŧzµZýÁ~ðÄO,Y²ä_ÿúW.—›2eÊ„ N>ùäãŽ;.›ÍJ)yî””2•JñQvY:Þ�ýýýRÊ\.Çs§æÏŸÅW¼ôÒK¯½öÚŠ+vÚi§Q£FMš4é˜cŽ9òÈ#'L˜ÀWåk¯½6qâD>¯,¥Ê=Ï Ã�kÙA�J¥¤”þóŸo½õÖeË–=òÈ#år9›Íî¹çž'N<ðÀ?÷¹Ïe2™þþ~ÏóÒé´{ë`AXkùŒ²Ö¶··óš …8Ž91ð�üãÚk¯]²dɪU«V®\9mÚ´ñãÇŸ|òÉ'Ÿ|r___SSSss³;y‚ øÛßþö‹_übéÒ¥���Ë—/?~|ssó¿ÿû¿vØaÇw\___6›5jñ¥‘J¥øNßÖjµ|>o­íïïÿÝï~÷ôÓO?ù䓯¾újggg*•J¥R­­­“&MÚsÏ=O8á„3fP=«4jÔ(·çù%Ü…CD¥R)ŸÏW«U~Ÿ!¢––~îÿüÏÿ<øàƒ ,‚àôÓOÿÞ÷¾Çûг8CáS+ŽccŒ”2 CžxÇ;$I~[à·Ù }“©,l«Üàt­õG>òž¨ÁÿýéOÊc¨ù¯ƒžåþÄx4q­VûÈG>Â'‡ËgÏž]«ÕªÕjãs+•е–ÿk­}òÉ'ÿó?ÿ³ñ„ä ŠRŠ×Ä…êÚÚÚ®¼òJkmOOÏ05gÎ~ý¡‡j\UžÔÂ7¬µÅb‘w»{ÌÓO?ý©O}ŠÃµnµy%³Ù,ù¾ŸÉd¾öµ¯­X±‚ŸÂkÅ«êN!#?ÔÉ9è†A¿©� —_³Övuu}üã3fŒÛ]J©T*5(p饗6îŸþþþÆó­\.óæßsÏ=ÙlÖÕ…[¾|9ïá0 O9å^ç[ZZøa|ÔvÜqÇŸüä'�ǽ³³“ŸËÈ]€ü˜b±xùå—s.‡w ƒÞÜÜÜÔÔô©O}Š�,^ÿ—;ñp"ÊçóDtõÕWó†<ôÐCS§NuÇš[Ú4.üøñ?ÿùÏyW7^}î̬V«/¼ð‚‚¯n!Äš5køO³gÏÞu×]ù(7.“×aÏ=÷|衇x _Ë·ÜrË{ìÑxÜ�>xà�/½ô’µvÕªUn�5î.^ÏÞÞ^kíã�?þÁ~°1=àÞˆø çÌn&“™4iÒµ×^;èå3V«sæÌá˄ןP«Õî¸ãŽÆÎd2ŸùÌgܺrÈ!îÕ?üp^>ÿ—÷'ïI^ó0 ¿ýío»Eñ^qÅÖZ>�¶Èsl»6(ϱÞÐ0æ´Ösìèèh >õÔS�vQNkm©TÒZ_tÑE�±éææf—~p‘JwòýRÊ�|ä#8Êðy¾}ÓM7¹œ =ôÐC�Kð±XP:�þæ7¿i­ýÏÿüOMçåóùÆH(�…?öØckµG!‡ÑÝÝ}ÕUWñS83Ä2\ˆ–Ç›»4¿âG?úÑ%K–ØzÜßZëvˆÛÃÝÝÝ\p�[V(8äêv2Ç©9þ£ýÈZE¯ùzó|¸¿ó�ïì¹çžnÉ©TÊ�9nÏð ñœžxÀ­¡;.Ñ5ÌÉ9èFc¥ Mw\\�úÒK/mkks»HÑÔÔÔ›Îf³nÛƒ X¼x1ÇÊyG :4ÖÚ^xÁ�ϯ½öÚš5k^}õÕ¶¶6¥Oþpµ¡xÎAcfâä“OÖZGQÄIV­VK¥ßࣳlÙ²vØÁ%Ÿ²Ù¬ËF4NÖáëk—]v¹ùæ›ùéÅbÑ�0 µÖ‹/n �ßtÓMÕjõßøïLÞ�T*Å7ÜÂyCR©ÔÉ'Ÿìv&/9 C>šµZí¹çžã%ó«ÕjWW'ü˜ïû|òK)9gãÒKsæÌáÅ~ÿûßç3�æ7¿ q–ˆç”<ûì³nMxG¹ü«ÛêŸüä'®¶_#|Ü{š;(ü_!ć?üa>Äýýý.ÿÊÕ¨¬µÅbqÁ‚¼«yåùÿøÇ?xGe2žDD'œp¯LE;ï¼óPyw™ó?Ëåò7¿ùM·gÆŽ›Ï篹æ—2ØF ϱízkó9æº�Øÿú׿8ÈqÕéÓ§wuuÙzpÜÍäèììäž{î¹A¬·‚�‹6ºð¢ ä !Î=÷ÜaBÕCå9ø)}}}Zëk¯½Ö­ªRêþûïïééá?ñB¸b>p•R_ýêWüãŠK)ÝZqäwòäÉ\Sˆˆ¦N�Ú�^Www÷¥—^Êé.爧‚«ýð†»Pr&“Éf³žç�}öÙ�ŽØ6î“ýèG¼þ.Dëæs¸+žçq™÷¶çyW\qWüwËqËäþnÉ.¬œËåxÝ …J—àÛƽá†øpû„ë rºÑ8ŸcÓÍõ«_åø;oNss³›^À³\B"—ËqRA)uýõ×ÇqÌKhœ°ÒÛÛ»jÕªçŸÞMæ "Nrðby°?Ÿ“îŠÈçó<±‰³8DôË_þÒZ[*•¸fï®oÆGêÞ{ïÝ~ûí9C�N§9À/7hR‚Ë L˜0ᦛnjÜüÆY;n¿Ñ%—\¹^·ÆÒÞÞÞØÿ†�3æ¿þë¿OQ—™ÓZ?ùä“.iÔÞÞ¾jÕªsÏ=—×¶1WÚÒÒâV`ìØ±îE»»»]–Ôá¾1WÄWM&“Ùÿý×{½¸œÇ—¿üeޮѣG7&lœ\.ט…å¿ú¾Úi§¹IKœmr u¬µnN ³Ö>øàƒÔ�kt‰ÌO}êSÖÚJ¥EÑa‡6Tžcм¨üàîÌáýyÍ5×ðK¯^½Úl3П6€ÖÚEH¹aG!K¥Ò™gž™N§kµ‡†Ï8ã ‰†aÈåz|ß·Ör낇~ø×¿þ5Ïð}?Žcß÷§OŸ~È!‡¼ë]ïêèèÐZ¯^½zÕªU·Þzë£�>š$ÉØ±cW®\i­½øâ‹�;3gnКs웃×Üõ—ûçóy7*œ3ÖZn{�N§ã8¾óÎ;Ÿ~úé¶¶¶J¥’$ɨQ£Ž<òÈýöÛ/›Íú¾ÿÄOüæ7¿I’dÉ’%¼½­­­‹-:묳®¿þz_äá‡>ï¼ó¨Þ\Jéû~kkëW¾ò•±cÇvttXkW­ZõôÓO?ðÀO=õT:�v]…/¿üòO~ò“ûî»o±XävDT­V9cqï½÷þð‡?ô<�ËOI)ÛÚÚ¦N�z衇N�:µ££ã¥—^êîîþõ¯ýÜsϵ¶¶rWä$IÎ?ÿüN8�ÛpŸ^`¥Rá×\sÍ׿þõQ£Fõöörˆ$Ivß}÷ã�?~·Ývó<¯¹¹ùÚk¯]¾|ù<À·x|úi§�–Ïç�:ê¨öövîÑÂë·ÐgeSß÷¯¹æš /¼�OìjµA__ßAt衇qÄ…Bá¹çž›;wî¼yó–,YÂSšššŠÅâÙgŸ½óÎ;ïµ×^ÜÁ›ÃúApLÜõÏf³ÜªdÆŒZkÏóJ¥ÒW¾ò•ã�?~âĉRÊb±x×]wýîw¿{üñÇ]+":çœsŽ=öØí·ß¾¯¯¯P(p>¥}ß_±bÅÿûÿïå—_v—j­VÛyç�?ð�ì·ß~J©îîî§žzêöÛoá…R©T>ŸïêêZ¶lÙ¹çž{ÀŒ?ž/^%ª÷³ ‚€/“;î¸cÞ¼y½½½ét: ÃÓO?ýœsÎ5j”1fÑ¢E .¼üòË—.]šÉdŠÅ¢çy«V­úùÏþéOzüøñ|"I)¹ýŸíÕju„ Ë–-ëêêúéOzñÅó†|ðÁ_üâ�;+W>õÔSóæÍ»æšk^z饕+Wò¦µ¶¶î¿ÿþV*•|ßO’¤¹¹ùë_ÿúèÑ£'L˜ „xõÕWù wvvvuuõõõqºèOúÓ9çœÓÞÞn­u'3÷r礟¥RÉÓ××wÚi§ñ± ¢‰'¾öÚkD$„àT"çx{³—�”²T*]tÑEçŸ>ŸQ•J% Ão¼‘[ÑðåðúߌT[:Ñ[̆ÎçÐZ7ÎíÃ�ëûÿë_ÿ:á„øtâ1Å|°M<¨B�G>ꨣ¨ÞÚ!�N …Ù³góS´Ö®ÚOOOϪU«î½÷^ºànœøº†©[•$ ÿð‡?‘ïû¼±÷Ýw___%y«]cg~XcežOúÓ‹-j|EîêqÙe—år¹––÷x"úío;Ôz~àà=àf'Üzë­víilõêÕ>ø '�x5<Ï;çœs8ë3¨T†¼d·öÜsÏùóçsÓ×xƒ]}õÕü˜|>ÏS ~ùË_r ewÜHüÎÎNãºqîtÐÝwßݸª|>¼òÊ+?ûÙÏܤÞÉûì³×1 Ãе àšKC�œƒnð±ÛÔÇeñâÅ®è?xòäÉÏ=÷œÛÉnÓsÏ=wÉ%—´µµ5Î?;v¬küи[ŠÅâÂ… ©^Ñ‹ˆ>ö±�Q&“9òÈ#W­Zeës Ü&wuu�{î¹Ùl–çsø¾ŸN§/»ì2W Š÷6Ÿ3���®Ï�ÛØÿþïÿ¶ë4AéééùáÈG'ŸÏsVòë_ÿ:Ï ±õî)®nt!?²µµõˆ#ŽXºt©­· q+¼|ùòÿú¯ÿâup§+Oåq�á³Ô3¨(Ö±cÇþþ÷¿çÇó>á§¼ð ûî»oãéDDüž°÷Þ{ÏŸ?ß6ô‰ã8Žã»îº‹êSx¾÷½ï¹÷Û0Ϭñ’imm- ÙlöÖ[o Ã0Š"^šÛ9ÖÚ?üáííí<ÑŠWæÛßþv­V+—Ën ïÃ$IæÏŸïÎ ß÷?ÿùÏó«ðuô‰O|âæ›o~î¹çJ¥RWW—{ƒÝ{ï½ù)ë­[ÕÛÛ[©T\Oî�ÁÍ7ßìæÌY€m òÛ®·\·*Š¢+V<þøãsæÌù¾ÀÕäÝðÿ)S¦¼üò˶ޜ€ë<ÜØ-�#t öû,ïNÌp߈}öÙ‡'üxWóŠsqO�:Õ¥gÒéô?øAÛÐC›wxÇ�>úhãñ}ÿ¶Ûn³ -Ê9†Îÿ¬V«ßÿþ÷]�¬l6Ë•£8JΧG¥Rqó'œ\.wðÁóªršÍÖ;x»Kì´ÓNsuä”_úÒ—x±üÒ?>gßnºé&×ÀÃ�'¼Â×_½«ßåj£m·Ýv¯¾úª;Oû�k­Ï<óLÞiü¬ƒ>Ø6$“\ú§··—WØMS»ñÆíÚ½Uøò´!>èî)étz×]wôâž2oÞ<¾¾¸ �‚WæÔSOuiªAÙ¾$I¦OŸ>TžƒWû¼óÎãö3îâ½á†¸N`c³÷¡J¼ó ϱíZožƒC¥�E]\G‡a¸1þŸøÄ'^~ù寍ºmhùË¡:îäá‚•ùÈG¬µãÇ�w3-ø¹<üÜm>‡�]sc·‡M¯Y½zµËµp`Ú®“ Ãpþüùúçèüĉ9ô߸z|:¹þ•Jå·¿ý­‹�svÁÍAáý0Ìþ&ϱQŽËµ×^kÚwsæŸÿü'Oà¼È”)SÖ¬Y3|ßòÞÞÞ{׊[ƒŒ3¦¯¯Ï�èolwAk÷žiiiá9(ì?¯’[ù÷¾÷½�—ËsÌ1î”BðLžÄ㎣m˜R.—�=öX·2™Læ/ù‹ë¤Íž}öY—'à%···ód‚ƃÏóÏ?ߘ�8öØcíÚS(÷!w+àûþÙgŸ=Ì~®Õj{ï½775çÁæüqÕŸ|ßO¥R;ì°ƒ­g/8;È{æÉ'Ÿtsªˆèãÿ¸ËpðÂ0t€â8æ)ÜM$�N»eÚ†æÖÚ‡~Ø�±î]ô¼óγֺYM��ç‹h¯½öâ=#„xÏ{ÞÃX¹r%ßøÊW¾ÂEáܱ»úê«-À¶mpóXØÆqVÃÖ§\P½²ÙP�çðk__ýùϾüò˹Ç@¹\VJñÄ.è_«Õ„q¿üò˹\®R©Qss3W¤ñ<�ëÎs‡ê$I¤”AðSˆh¿ýös�ø¹›šëRÀÞÏ9çœÆôϺ2™Ì{ìqÊ)§¸4‰”òW¿úÕcë»L’dåÊ•ù|¾V«•J%"z÷»ßÍ{2ŽcŽsNÂó<ß÷ùž0 =ôPîpàû~gg'ñ¼ª×àò}áÂ…xõ<¯Z­~øáTÏ^c<Ïã¾\Ó‰ˆòùüÌ™3wÚi§t:=~üø8 R©ðfòæGQÁW\a­ÕZsóùË/¿Ü÷}wÈܙý[*•Š”2“É|à8î¸ãˆ¨\.ó¹-³;ÁÖm^½ÙŽËÿþïÿ&I’N§ù¹œæ¹ä’KÆŽE·Äøö·¿�ïûÜUb½š››wÙe—#Ž8"km’$kÖ¬™;w®¨ôx>™ù|øÄ'>±ÝvÛÑÚ½"7n·sçãÅ]Œ1ü¾ú-Zôâ‹/ò©Á®»îú¡}(I΢ñ‰¨R©ð=qg³ÙÓO?=Žc¾ÄªÕê‚ x¢ 'ø)AÔj5NØ!Î:ë¬T*åÎIÖx(S©TKKË Â_륵Îçóî„÷}Ÿ y %•Jí¾ûîÜ÷BJiŒ9è ƒ¦M›6Ôã……B¡££ƒÕðL ªg_xs¸ËÅóÏ?Ï]yxzÄ^{íÅ�q¨ÜäÎêñ¸Ë.»ðVpŒÞ(œJ¥¬µ{íµ×§?ýéþþþÖÖÖaÞWã8Îd2ÖÚææfž°5fÌž-tÑE¹÷�\.÷³ŸýìÓŸþ4lÛЇÖ‘M÷OŽj­‡ á…aÈÃüÃ0<õÔS¿õ­o½ï}ï›6mZ.—ëíímmm5Æpœ=�N'IâûþäÉ“¯ºêªjµÊ±¿Y³f%IR­V¹ò•kÀàâ³¼™L†c—ýýýÅbqSïnTη+•Ê>ð�=öØCk=|H½¹¹ùœsιîºë¨ÞÆùÞ{ïíïï/ œ0àÈò„ .»ì2kmKKKE‡~8'“‡·»eÆqÌýºyŠïNfQ.—sK¶ÖA�Ïç׬YCDù|ž[p÷õõ577ó‘åœGryÅn¿ývÞça–J%þSµZ匇Îó›ß!ÚÚÚúúúÆŒ3kÖ,Z'�ÍA[>øž\.wÌ1ÇÜvÛm®)úý÷ߨa‡ !xCÞpžÐ¦;.>ø`ww÷èÑ£yJ)«Õê-·ÜÂ]Ù}ߟ6mš‹¼»^—”râĉ§Ÿ~ú½÷ÞË÷xž÷ä“Oò.â ¾µÖ�èç½ÄGêÔSOÍårî¯ë5vìØÑ£G/_¾œCü�«Á-©“$¹çž{8ÏÁgˇ>ô¡ÝvÛ�c÷üB¼�œÒpGjÖ¬Y---½½½|y>þøã.cá¦õd2^ …Ï~ö³ƒúƯ»æ­­­­­­===Ã$‡Üªº…ì²Ë.tÐð�ße—]Â0ä–ÝÖÚ~ðƒnÙzù¾?~üøJ¥ÂiQÞuqsŠŽ·4‚ƒ>øª«®J§ÓZëžžž�|ä#üt¥§¸ÜÅhë忬µ…B!“Ép¾�Ͻa’DÄ9¶ÎÎÎË/¿|Ò¤Iüë·ëRJU«UÎV‹Eîwrþùç_xá…ù|žó£ÖÚk®¹†çl½…K à�yX ‡S9£P*•¸Ž ÅK¥R<\º­­­»»ûÛßþö…^xÞyç�rÊ)<¬[JEÇ9®7nܸ©S§rlÚEðy@=¿œC­”ªT*yçn©]Ű\.Çi ^óT*•J¥ªÕjÜ2A)•ÍfŸxâ ž^ÃÓ2N?ýôõg9ÒjŒ ‚ ÃT*eŒùà?xÎ9ç¸ÇÌ�;w+9.RÊ矾££ƒÏOÏó–,YÒßßOD£G�^½zõ!‡EQ¥R) Ã,¼X, …Y³fAÀ=0¢(ºýöÛ¿ùÍo®wñúÇq<~üxžÇ†á äÁ Ùl–/ ^‚›CÃW“çy÷Þ{/ÿU)¥µþøÇ?ND¼>Æß÷yúBã9Ã)®ï|ç;«V­âÜá„ ”RqóK!øº&"ß÷­µ“'Ož0aÂP+90=PJ¥ç/]‚d½83Ê/MD‡rÈðÇ=I~?ñ<�${ì±Ç0�ç|Fc"¤1Áçj’$ZëqãÆ}æ3ŸáÇó¹BçeùÝ�w,_•üÄgŸ}–s¼Éô&’vétºV«}ðƒä+qø“–W#‚R©ÄIŽüàç�wÏAáUºòÊ+O:é$·±° CžÖÂѺ£�>ú€àà;G‡ϾtéÒÙ³gó cvwwéK_zê©§®¼òÊeË–M˜0!zò¼n€Ì1>nÂáæpÐÚSˆ(›ÍöõõÝvÛm�=ößÃCï7õ~àø&'còùüŒ3Êå2· ï+!ÄQGõÊ+¯ð(rC»±êßô}ŸCÛ•J%•JqÞ‚wˆË[PCäÔZ{ã�7.Z´¨V«¹âBDÄmR©T©TÊçóMMM;ì°µ´´T*•(Šúûû÷Úk¯óÏ?Ÿ›‹Å Òé4—–âH.³êïïÏçóBÎpðºq€ûî»�S#¼E3gάÕj�ëéVÒ x/•Jœ­?~ü;ì°téR®5´hÑ"ŽÎ¿åáçë¸Ñ#�lÛ�瀵plôè£�þÌg>“J¥Þ0Ë‘Ö{î¹ç¿ÿû¿¹!3�}þ¿ÿû¿vØáÿý¿ÿçjæðrŽÀ–ËeÏóxù¸äØ¢‚‘Quww÷ööΛ7oöìÙwÝu-omm­Õj<«cSã i’$\WÊMƒŠËÖ̘1ãÒK/å:T¾ï»šB\?ŠÃÓÜ#Áó<Yò~Ã�c¦|O­V[´hÑ}÷Ý÷øã�ß|óͱ-‹™L†÷†[%7Û¦¥¥åë_ÿú�~ô#"Êd2Üxü[ßúÖÅ_·†¯Ä7s(�1x Ÿ.Ë;üS¢(2Æœþù?ýéOy£*• —ó<ïŒ3Θ7o^>Ÿoœ×°mBžã©#Ï“†ŠBrM›3fÜ|óÍŸúÔ§nºé&_&IòÍo~óÔSO5jÇòxÐ1‡�]¨‘cÐ¥RiÅŠË—/æ™gž~úéÅ‹/Y²dÙ²e<í€G=s],ðq›MÊÅ"‰hÇwìîînoofü¸‹kÇq¼Ûn»5–ùâ`ecwwθ½ÊAÿçŸ~ñâů¾úê‹/¾øøã�?ÿüóÝÝÝaº@-wSà×âÒ=œ4ªV«œ¥èìììèèøú׿~Çw<õÔS™L¦»»›[¾¿üòË/¿üòïÿ{)å^{íµûî»Ïš5ëÐC;v¬”Ò�ÓwƒÖ¹f×íY±b)ß÷׬Y³÷Þ{³ß8…À‘k"âÔ0# C+¿µ<ÇÆ:.Bž~ÁE«ˆhåÊ•RJžoÑÕÕ5sæLîáûþð%˜r¹Ü¨Q£–.]êÖÁZ˨1MèæI‘1†'‚ðíaZXó¤·Î|1º½çyÞ+¯¼âŠžOèa|§[+¥?׋jµÊÍÀyQ|¡Ù:>Eݶçóy^ ë5Ò¸’® =5tj¦EGãb­­ÕjoxQ»½JDaߣq¸lÖ ¬moo¯ïûÙl–W›ç™Q­V[ºté /¼ÐÙÙùØc�-^¼ø™gžyíµ×ø9;Ëç¯'kßðdVJq‰óL|܇y0_ø/¾øâüùó]aÀ¦¦&Îòö÷÷/X°à²Ë.;çœs�ä@žÖ’J¥xV�µÖ5æñ\uŠû‡ÿêW¿ú׿þµxñbß'Irþùç_y啎ç/säT*•[n¹åŸÿüçu×]·råÊÆÅºÙÆ˜ŽŽŽ®®®îînŽôñØêͰ+¸Sz’$¹\Žƒ°ÃŒçUå.ÜcÆŒá;�1•J%Žãr¹\(ZZZ8$íZH)o¿ýö›nºé®»îZ¹r%‡q¹4wP”R½½½\i*Žcn<ÀI7_¡££ƒˆÒéôßþö·O<ñÁÌd2ùäŸÿüçZ­vÄGœvÚi³fÍjkkãõç¹ Åb±µµ•+qI«R©†!§1¸íyãæ‹:×:‚çÌ\tžÇã_Þgókm¹\Žã˜÷^Ç]]]TïÙÀ'¶ë˜’Éd†:å„år¹\.S=vÏ× ÇÁÝcŸÒÜÜÜ××Ç×ÂzÐhÐÃ\<�¯Í :;;]u¦ xîTE©T*Š"Žã»k™;åpnƒoP}¾ˆ›û‹çßð†d³Ù8ŽÝX7ÏÁOi,³6èÆzq¶b±è¦5 “¯jL'¤Óéjµú†yÎ߸ýæN¹R©”Íf¥”ÍÍÍüžEÑœ9sn¸á†Ù³gsÍ7jÈÖð#Õ;Š7^¡™LÆ¥R†:±9Æ>îîÎk˜ãΫ´|ùrN‹vwwOžïyçR©Ô²eËx¾…[?å‘G9餓fÍšuõÕWwvvòNãæäœàוR†a¸÷Þ{ï±ÇµZÍÕ”xXw&“á—v5‘2™Ìرcxà�?þñ�£G�æÀ7ÅqÌ[N–pá {ï½÷ÔSOÝa‡¾ô¥/q_ ž¾ÀcÛy•úûûK¥DŽGQdׯî\ÍqóîînNÏp«sN™DQä&4âÍ\|ß_±b…Ë·ù¾Ïy×L›ê3-r¹GÕ×Ë�ÊÏf³ns’$Y½z5ïªÏˆr�OŠÅ¢«ÏFoÔŸ£±ò'«xö�+ø¶råJ­µ›&Õ˜øáS¨R©¸ KA¸F�s;xáTŸ.Ãy ès­$.g×8fÐJµþ�5¬g{ðíb±HõVÞ®%Æzq–”§¤ðy>̃™k€Ñ8“†ê­>ܶ¯X±"‚GyäÄOœ5kÖu×]×ÕÕʼn1Z_Φµµõ�CÙk¯½¸5Žûk­V&oÁŽë‹>|sÞ'œá¾ëJ©Q£F=üðÃ7Þx#Ï:"¢ –.]úå/Ù•ÏrËäÊc°ÍÀ Px[¸º�£(zÿûßÿå/™ˆ8œ½zõj"âH7��WJ-[¶lñâÅ3gÎÌd2étº§§‡»D¸e¶¶¶Nžûì_ÿú×ßþö·K—.-•JDT,¹Ä·‚ T*]wÝuwÞyç_ÿú×É“'§R)ž=Ãa\î¤ÂAskíÌ™3yJÇz÷Çý9JžËå¸Î÷èæ†çår™;'¿Íèoó¸(¥Æ�χƒÏ½ööv×SšˆN8áž‹S­VÛ³’N§{{{“$á>ð}}}I’DQ”Ëå8©@ M°ßL©¥7�§h¸™RDÄ8ø” zÅ)¾Á™ ^±Æî"Ã�_oÄõÜÚ¸�7sܸqW]uÕ¿øEž°Â.—ËåÊårSSÓ.»ì2eÊ”]vÙe·Ýv›>}ú.»ìrÊ)§<õÔS.»àz¤¿µ–3ëâcÊ"jooâ‰' …‚”ò¼óÎûâ¿ÈSaˆèá‡þãÿxÒI'õôô´¶¶r‹ß÷9Aò†]OÞ�瀷‹ã­|còäÉ\Úˆcma._¾|̘1®@PgggooïÌ™3‰HJÉ”R»ï¾ûÞ{ï}ôÑGϘ1cûí·ç‘Ñ®oÕj5îÌ º7Ϧñ0ó®®®7œyàŠÒÑ 6égwtkí]wÝuôÑGAÀÓ5¸£ÉêÕ«O=õÔ÷½ï}“'OÞm·Ý8Í3xèú²eˈˆ3Fœ^Šã˜+b¹½DDw%•§Mp’Òé,ªçBÞpªÄÈÅSaøÄæ¤×¼yó¾ûÝïº"Zq755555xà�G}ôÑGÍMé9æÒîÜã¾ïSwkCñÒ„…BaÔ¨QsçÎ- |Œ¾ð…/\y啜BN¥R/¿üòE]tÌ1Ǹ©<.ׂ$l;�瀷… Ú‘Ö:•Ji­G�õÚk¯Q=T÷òË/�?žÃĵZ­½½}Ö¬YDÄCû‰hÒ¤I_þò—?ýéOssr×m8Nrôôôp��‹ÃQ{{û¦Þ.ŽÑ+¥¢(z饗xņ©¿Ï�…9~úÚk¯i­¹§E:�æh~6›åy aþä'?á%su­õ/ùËÓN;mÝIF'¢0 ]I(k-$çVœCr�3¨Þbš� ¯pÛm·]kkë¬Y³2™LOOÏoûÛ;î¸ãÑG]³fMSSOAxôÑGÿçþç‚ .àW¯V«¹\nÒ¤I<¡Z­V«Õ¾¾¾|>?Ôü^+No4N,(‹¹\έwY؂Džˆ&NœèÖÐéªWjâ3÷°u¹Þ3MMM�}GÖíµ¾Ñó|uð¬W>kÑ¢Eœ§iŒws뾓O§¾¾¾ææf7ùƒ×�ÓŠÃlì;ïžèÀ 0¾üå/¯ZµŠê%û&NœøÙÏ~öK_ú}7 Ëó<—@*—Ë<ׇº»ÓFÍñÞÖÖ†á]wÝ5nÜ8"âæDô‹_üâˆ#Žàìf*•š?þÅ_üÝï~—àúÊ ?9l;ПÞØåîÙårÙ sæJ˜ãˆ›ïûO>ùäOWyÓvß}÷\.Ç›_«Õþô§?½úê«®òÏPÛ›Ïçƒ øÃþ°ë®»A0nܸ]wÝõ’K.ágq….—lØXMª©¡y䑼 Zë$I~ó›ß¸úfÔP;ËM×à%ôööÞpà ¼„r¹œ$ÉvÛmÇ1ý·�)ÜYǧ÷O<ÁH>Ÿ—Rîºë®DÔÑÑÁ�áË–�]ãœkí‹/¾ÈùZwgc3¡·¯R©ð twwóÑÌd2µZ�W;“Éd2™K.¹ÄÍ8‘RÞqÇ×_=W'së¹¥÷7Àf‚<¼-aòäƒ(Šâ8æªGþóùäU«VñŠQðqÎpÎÆó¼[o½õ¶ÛnK¥RÞyç�¹ÂREžçñýC�œëf\u �r\¾øÅ/&IÒÞÞÎguuu}ùË_vù'"úÎw¾ÃûmÝ–é.o!„¸óÎ;ï¾ûnªw,ßqÇwÛm7·Cxyò _Mœîr]X8G8ÌEê:Cp‘"·¸ƒ”òøã�Ÿ»\.[kG�ÝÓÓ†!Ðù:â+ý ë2ñ>á£ÀÕÀ8Ãë&¥äÂh®'Š«PÇ;g˜ztq»~énó‡Y>úüºî=Í­$gìR©TKK‹ëÐÇñ=÷ÜÃã©NnÍÃ0䳚ˆJ¥Ò§?ýi>"¼‡S©”»ù)®6WsiKwV»=À«êæÜpÅ9׈¨Z­ò{—kÁbxžwÕUWår9k-¿zOOÏùçŸÏo•›¡¸ÀÖyŽm7HPJ¥R©l6Ëݪ9v¦”âè¿ïû.9TÝ"êèè¸ùæ›gΜ9{öl" Ã0ŸÏÇqüáxÒ¤IHå°�RjêÔ©üêœ?¾ïû•J¥\.óLc ÇXù)ýýýŸüä'-ZDDåryôèÑžçU*þk¥RáØº €r@0•Jq¢…ƒ}©TŠƒ¤¥RÉE�y3]iîNÌ�ìïïÏårœ!X±bﱿýíoßÿþ÷�1ü0"Š¢(—Ëe³ÙåË—W«Õ… ~æ3Ÿáóž9è ƒvÜqG¾‡_(Žãƒ>˜wusss±X|ä‘GjµškZND™L†opRÄ÷ý³Î:ë¶Ûn ‚ ¯¯�cÇ���Ùl¶»»Û“ÍfS©TµZ�ãøˆ#ŽPJql½§§çÊ+¯äÊW¼[8ö­”Êd2ïB\qÅ/¿ür¹\îèè¨Õj‡rGºÓé4w./6~üxî¹ÝÜÜ\.—¿úÕ¯ºO_Œ£F�âTg¶x�ÖºX,~ñ‹_$¢B¡ÀÙ‚K/½ô¯ý+Õ3OBˆl6ËÛÞÖÖV©T®½öÚG}”_�»³üÛ¿ý[.—Bô÷÷·¶¶ºìÕ3ýýý�}tÖ«\.ód W8‹§.ñ–R=îÏ{>“ɸ Ã0Žãaê>ù¾ß××çû~:�Îd2œÂf¿e³Ù0 “$imm ‚€¯tÎÌñÕÁõô&Mšd­mjjÒZc-ZdŒ‰¢¨³³“Ï�0 9ET(Â0 Ãð»ßýîŸþô§b±È«$¥,—Ëù|ž·‚™L†·š«íñzÆqÌ»…7‡§vñ»%_A¼|N†ñ9É—¶ïû\¼Ž�Wüãôí¸qã¾úÕ¯òùÖÞÞÞÛÛ{饗>ýôÓ\pC/.€‘k£Õ‡‘Å �çAý�“*ˆèöÛoç®×ü'Ïó†* ôâ‹/ÞsÏ=ÝÝÝBˆjµª”joo_½zõ´iÓ¾öµ¯qÈÛUPñ}¿ýöã˜`OOýøÇ?ž6mÚÉ'Ÿì†Ì !ÜÀó§Ÿ~úG?ú§O·÷ÈçóÝÝÝííí\óŠŸÅÏݨvêίU©Txù¼>ƒæÀk:�nooç!ØRJN‡p(Ÿ—Ì¿y™ßûÞ÷ªÕêgœ±ÝvÛq…'ÁŒ?þúë¯?ýôÓ+•J[[[wwwµZÝqǯ¼òJðu!øÃ?œêc؉è'?ùÉN;ítÆgô÷÷ …8Ž9ÛÔÓÓÓÚÚºhÑ¢ÓN;�kv…a˜Íf+•JSSš0aWÄâôŒ”ò„N¸ñÆy0{.—ûÛßþvØa‡]ýõÛm·‡†9®Z.—ƒ ¨T*W\qÅW¿úU^looossó1ÇCDú¿ÿû¿|p†¼{yZIÇ×^{íÿûÿ/ŽãÎÎÎQ£F­Y³fÏ=÷<í´ÓxOºú[Èsl¬ãâæUðšóíB¡ðÛßþö¨£Žâ—hkk»ÿþû÷ßÿ믿þÝï~7qcj[/[¶ì¡‡:õÔSyÄêÕ«£(Úe—]Î=÷Ü0 ùps‚$I’æææI“&AÀÉ!žºÄËáY;C•Šâ"K<Û`Íš5cÇŽå¾Ù¼|NÚe³ÙÏ~ö³×]wÝ<À'ù²eË>øÁ^~ùåg�uV¥RáÂh|òW«Õo¼ñ«_ýj¥Rimmíééyå•WÎ9çž DkÏ¤á Ÿómo¦ÎX>Ÿç¾÷ü6ÂS»8'Ä+Ìs•¸K6_q|ƒ„[É¡v…K8I)9u7~ïªÕjü>£”ÒZó»Ïq/)¥›«ñÓŸþtòäÉgŸ}öèÑ£»ººÚÛÛÝœ'­õc�=öùÏžç<ñ9eR«ÕJ¥R>ŸçGÖj5>š|’óÅÅ/Ê™Œ8ŽóùU\=@>…”Ržç}á _¸ýöÛ}ôÑ®®®B¡Ðßßÿ…/|áþûïçy(]Ûä9¶Q½½½---ìBpj¿o­½ûî»ï¾ûî0 9œ—Éd\%–uq„ÝUFâTÄ7¿ùͽ÷Þ›¾¹\ŽGI§ÓéC=tûí·úé§yÉcÇŽ=õÔSÿûßîsŸÛe—]&MšÇñÒ¥K,X0{öì¹sçrT‘ˆÚÛÛ»ººxõJ¥Ò—¾ô¥Ÿýìg­­­Åb‘çxž†!‡Yy;·é®V«Ùl¶\.óPz�ǯÕj]]]ÖZ6-•JÙl–#†­­­}}}S¦Léìì\³fM*•úáø«_ýêýïÿ!‡R(8úyà 7¼úê«Ùl–ãÝÙlVk}Ægì´ÓN¼áA¸ÆS§N�9sæ¼yó:;;yÚÁ™gžyà 7œuÖY;ï¼ó^{í%„X¼xñܹsÿô§?Ý}÷Ý)æ /'08ÓpÞyç]pÁ\¾ŸˆxxûþûïÈ!‡Üu×]®4Ö?ÿùÏ}öÙgúôéGqÄôéÓ;::Ö¬YóÚk¯½øâ‹W_}u©Tâs€'ôäóùo}ë[´åvǼð\.÷Þ÷¾÷SŸúÔu×]GDÛo¿}ÿsÏ=7cÆŒ#Ž8bæÌ™“&Mš4iÒsÏ=W.—/ºè¢®®®$IxÜýš5k2™Ì…^HõìZ¥Ráˆó[°±Ž œO¥RŽã˜ÿyä‘G~ìc»í¶Û*•Jwww.—[´hÑôéÓ§OŸ~ä‘GvØaétú•W^yòÉ'çÎ�ûøã�óúÔjµŽŽŽb±xã�7òì%ε0~‰b±èê,q~ŽÃМ j‡‹EîBßßßï¦+ñùÀ³1x'Ñw¿ûÝSO=µ³³“ÙÚÚzöÙg_|ñŧ�vZSSÓÔ©S—-[öè£�>üðÃ/¾øboo¯RŠs&LøÆ7¾ÁÉ'.wÆçX6›u�Ì¥”P(º»»ƒ øÇ?þqÁ|ó›ßDž¶!¶mµZ-I’“O>¹ñ¬X·¡®54ràI“'O¾óÎ;¹¥G©TâW1ÆðíÕ«W¿ð \¾Æ÷}7!ƒ_”Ûe»ê.Îç>÷¹ë®»®P(pˆ�C±ù|~âĉ¿ýíoù%¸Ìý�wÞ™N§yù©Tê÷¿ÿ=w°Ör¢J¥rà 7¸—PJÍ›7¯q‡DQıW®lCD/¾øâ.»ìBõù­­­|¿‹Wú¾Ïõ”Ü2¿ð…/tww»eòÞà5´ÖÞ}÷݃âÚù|~ôèÑ�÷477s/öÿñ÷Þ{/ÕCä¼&£G�Þm·Ý~ñ‹_ð¤^ø-·Ü²ÓN;ñ³xŽ‚[Hãm7¢ÜîQ£F½ôÒK|˜¸‹¸[Ž·FQtÊ)§4®ä¸qãÜ’yN‰ûSãæüîw¿³Ör«sk-'ø¿CáGº]Ç7\'í�x\8nî^…óÇw?ÅezÒétcU%w�p€�Ô¯~õ+cLµZåEq/h÷B .t=‚üàœÃxÃ+ôÐCåÓ5“Éì·ß~î)Üm…×™�ÚŸþô§|>ÏëæÖœ_”WžÏhoo'¢í·ßþþûïïïïçE¹•·Ö®\¹’—ÀÏuÚðo&ÖÚ‰'º3á£ý(¯°;ùÙO<ÑÑÑÁõ—ššš¾ûÝï‹ÅáþË_þ²qÏ¿òÊ+n÷®W†‡~8ïºB¡0mÚ4žKá.s>è·ÝvÛäÉ“ùâ’hü*üD7ƒÇM¸Éd2§žzêm·Ý6è}r»í¶Û~ûíö³ŸEQäÖaþüù�×ËE]ä^}Ý®T*¼öÝw_wv͘1ƒ·…×–ÏÏ8Žy îx}øÃvïÙlvâĉO<ñÄ/€w ôçØvqG‡T*Å�¼ 8"ìr™L&“Éð_õ¨>½€ˆŠÅâ)§œòç?ÿùè£�æÊQÙl–K»p¥"5jÔĉ/¹ägÍòù<·v(—ËÜBƒÈU°.¼ðÂ+®¸âÄO,•JQ�?¾X,rçóÎÎNŽÆZk3™L’$étºV«q/‹ó(þ8Žy=3™Œ«ÓÅuù]Až;âû¾ë νÚÚÚ|ðÁ}öÙÇZ+„èééáÒR<Èš‹M•ËeÎŽ´··ë[ߺôÒK9ëã6ßÝ6Æ~øáW]uU¡PÈçóœ³I’dõêÕ.@ŸËåúúú¸…F{{ûÏ~ö³Ÿýìg{î¹'÷&™8q¢µ–ˆV¯^ýÜsÏYk9ÛßßEÑûÞ÷¾K/½”û‚p- ¦¦&×b�_n„ Õj•w:hÁ‚“'Oæî \ Ëuïêêâ>—]vÙW¾ò"’Rvttp“Œööv~iÞ“|4yZÏvÛm7gΜ�}ìcDT(8WávÝ[;o7Êqq\ïþ'ïØ?üá§Ÿ~ºËmpS.Œæ FQkk+Ï×ÑZßÿý§Ÿ~:ïR~Ål6Ë5‘l½ñx©TâýEÏB”J%³?”×^{-ŽãB¡Àõ�xŠ’µVJÉ=Æ=Ïã‹ëCúÐwÜÁý6x~Usss©Tj¬ç–Ïçƒ ˆ¢¨««kÔ¨Q?þñ�=ôÐ|>Ïqüt:í&�¬Y³†OEN™”J¥aJWqÃåQ¸*—ïûË–-ãkœ'(‘Öš'Wuvvr?íb±èy^¡P¦¥„µ–÷Oa!¢žžžuÓ±�onAðÄ‘\.×ßß¿téÒ \²Š;dXkgÍšõÍo~ÓÍ8á‰8Ü…�¯;ÄœB¸ð ¯¹æš™3gò›[cÞeÙ²eÙl–ß?“$áT çrÒét¡Pp‰F¥ODãV+îý–ÀÝwøN>axþY?;nÛS­VÝjÿêW¿jooç²r•JeÙ²eç�wÞPÅÞy�çØvq°Œˆ8HÍ u¹à ‡q«Õ*×Nq�—×ÕÞÞþ®w½ëÃþð•W^ùüóÏ_}õÕïz×»ˆ¨V«yžÇv8©àtvvžzê©‹/æ€lkk+�FçÀ(Õ‹Øì¼óÎÇüüùó¿ò•¯pé›ýèGD´|ùrn’E‘+‰ÃOñ<�£·TĻЪïûàæAÓî,•J£G�îëëㇹB=µZ-ŸÏséü(Šúûû;::}ôÑóÎ;/•Jq˜•›.pÓrÞ®|>¿ß~ûÍž=ûüóÏçŠ@]]]�¡a~"wfþèG?zûí·ï°ÃÅbQ)Å5ýù(p œCêŸüä'_xá…Ï~ö³Ùl¶©©éW¿ú½öÚkœâM¶Öº²?|cÖ¬Y<ðÀÇ?þñjµÊõ”8›ÅýˆhÙ²eÜ ¾Z­¶µµ}ë[ߺ馛¶ß~{®‘Å•¬\wåb±È»tùòåÍÍÍ^xá¼yóÞóž÷tvvJ)[ZZººº¨^݈Ÿ[«Õ‚ øò—¿üÈ#�ì½÷ÞÖZÞK®Ñ Ÿoá¤ÝXÇ…»yó*q’ÃZËi?>~õ«_Ýwß}S¦Lá+…Óš››9#Å]Ù?ÿùÏ?þøã‡z(Õ;ÜpÏ w•ñskµ'„øLà¹J)N µ½\Ë�á¼��­)øœ!¢U«VÑ!‡òÔSO}éK_?~¼”²¯¯�›d¸Î(œ®hnnþÏÿüϧŸ~úä“Ov«ê:]ó?‹ÅbSSS¹\îïïO§ÓÜ{¨õä>çZë×^{mܸqü¦Çñĉy“]2I)•ËåV¯^ÍSO2™ŒëÖΑ¡xžÇófâ8vgÝPxqÚ€$£G�æ}èÒ¨ToÕóñ�üŽ;îØo¿ýÊår&“±õ%œJá·&.ݶfÍš�|ä#|ö^|ñÅTŸ3DD“&MJ’¤Z­rfËuÑèèè0Æpž¬§§‡³G|™K)Ýœ*¾0µÖ¯¼òÊŽ;îèv…ïû/¿ü²;“©Þ§„:©T*•\.wñÅóTJYkçÎ�{×]w½…K `$¶¡ë,lSx˜9·aàjòTïí#Ûz…÷Æà`#×N9Žc7„‹ÃAÀ·9¼È 䇹åßvÛmÿûßï¿ÿþ%K–ðŸÆ�?}úôC=tæÌ™»ï¾»[^ÔÍ7ßüÃþpÅŠ���S§NÝyç�¿ô¥/pÀܵ›—�$ gk8Ôè^‹[¸±ÿ­­­<æš âóæ»žÏÜ>ÄÁ©Þ̼Z­þéOúË_þ²hÑ¢•+WÆq<~üøvØaÿý÷ÿøÇ?¾Ç{¬»ëø¥]÷cNü¸}5wîÜo¼qÁ‚Ï?ÿ<7®ð<ï�C9æ˜cŽ8âˆwÜÑ�ç–*·ß~û\ðÌ3Ï”Ëå½÷Þ{̘1ßûÞ÷Þýîw÷õõq"‡(ï®W^yåÖ[o}æ™gæÌ™Ó××ÇSZ[[›šš&L˜0cÆŒƒ>xÖ¬Yn«y%©9u}¡yýy5¸?s­V[µjÕ¯ýë»ï¾»\.¿üòË===cÇŽÍf³ï}ï{÷ÙgŸ“N:©¥¥¥±³4¯Ç|�…_—û«Û�œ‡àLÉF9.œÏãD·¢áƒÂ·¹Ï¹çy¯¾úê5×\sï½÷vuu­X±¢¯¯Ïó¼wÜqÆŒ{íµ×)§œÂawÞÀt:ͳ„œ»âeò¶sÀ�§qË>'ù…Ö»xµ¹‰/�'"¸]ÇÝ_Ï(Nþ­X±âöÛo衇{ì±Õ«W¯X±b„ A|ðÁ‡vرÇ;zôhÎÁH)ùrà—3Æø¾Ïç/œ/sî3Tªƒ7Ù5÷D×ë…[¡ðΡ†ôÝÝÝmmmI’‹ÅÆBmëâeòŠñþ¦;ïs)e*•r�f\f˪§sø)7ÝtÓ?þñ�yóæ½ôÒK|êŽ5j„ øÀþíßþ�‹¤ñ–òÿò—¿\tÑEK–,©V«cÆŒ™>}ú7¾ñ�iÓ¦ñ»¿o Û�ÉÇŽ_Ž·‘glð%ID¾ï»s’ìÎ4·¼LÞÿüBü&öÖ²‰#ò0Ra°'ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsl»¢(2Æ‘1FkÍ7¶ôJÁVÇZKDqÇqL8I¶bQñ ¾l`ëÁ_´ˆ(Žc\¡[3km†[z-`ýÜgh†ø<Ø:¹kÓ}N’dK¯lí¬µÆ˜·rDžcÛåyž”’ˆ„|ƒÿ à¸ô†”’O�(ŠðÛ`«R­Vù†{�¢Èå<`kà>:¥”B¤ò',l%¯Sw¾÷lUÜ%©”Âç)ÀÖÉýåÏS­5~ŸÂºt]’$I’c\àñíð¶ôvÁ–†a?)¥øk�ïû.× À|ß—RA ”âœ|EZk>y`k ¥ô<Ï¥®ù÷žÖºX,néU€Bˆ ÜujŒ©ÕjÖZŒnØz¸S¥i­kµ¾÷lU”RA ºN]� Øð—^NFQ’$aFQ„ß§ÐˆßÆ9cÍ1� |ß›‹Ežc¥”’Rj­yZŸX˜ø ƒÄqìyk½Kp¢•?®`kDZÖÚ}�4Æ$IÇ1¦èl=Ü,ìÆë4I\§[KÈ¿º‰HkÇq’$îØâܘ_?årÜø<Øzc8ºh­B¸§9B£Æ²ÛnLØÛ_,òÛ(N®rÒŒs.“¶¥W ¶"®4§ÁøôBl”wØ(â8æ\5ÕGC®S€­Œ"À¦np ®S€­‡Öºñ:u¹I\§[w�R½˜;>O¶6®úãÅu ëå’aü�ËÅ¥ß&œdÛ(øÀ y 0O@žù¾ï~ï¹à©¥¶žç¹ëÔ݉ë`«ÂßÚ ð 6\§[÷yJ W«R ×)ÀÖ£ñ{¯»Nñ½`«’ÉdÖý<•Râ:…F\'¿1¶Qfü ϱ�âÂgœ.ã Ú<÷yx3Þ~É<ØXÜ€S7 ‚ÿ‹ë`ë‘$Éz¿¸ã:Øzh­×½N…¸N¶®Þ€ûêK¸N¶2³æÜ÷Îá«×)4rß»¸À/7Vxû‹Ežcå:Úó÷>™Ð¼ q•OÍÞ(ï>°Q4Öªâ{ÐŒ`kÃ��²„>ä[�Æ>:�%ñ‘ °õà_£�Ý8ø:Åç)ÀÖCJé®SWÀ q$„¿nñÂ3hQ· Þ:îX˧'<Ü=[zÕ`+ÒxJ¸„΀­ ‡JS©b|ß7ÆA€>o[þÆÕ8hŸ§[WOœñÊí ·ôªÀëÓ�îãß{¶�u ©~�âÃáQ_ar(#IÏó\�ß· çŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÈsÀH…<ŒTÛbž£R©DQÔx�Ö: C¾E‘µÖ÷‡YN©TjügÇD”$ ÿ³X,ºÛÖZ"*—ËDdŒéíím| ¿V??RkÍ5Æ$IDZ[7¾†a­VãgQ­VÛÒ{`ËØæòQe³Ù ¨žÒàûS©”1¦T*A „àd?l(™L†ˆâ8®V«TOWH)ùFSS“çyår¹¯¯OE‘çyœ·hii!¢r¹ìû~EZëZ­V(ˆHQ©Tˆ¨V«…aèyžïû©TŠ×3•JñÓé´‚ïô}KïT€-ÃÛÒ+°¹AÀs&¢(2Æp&ópá—^z©P(uÔQDÇñðù÷€8Žy!œ„�RZkyâE*•Êårî)ü€8Žã86Æ(¥¨žJá´ÊŠ+Æ�W(jµZ:�ægÕj5!?·Z­ú¾¯”B!â8ößHOKIFXiÅÀùÆG…��°oã5ÞºaN ¹öÃäúî¤!®ˆMËí++ˆHZ¸î„5ÔpÁ +•Xŵ¯â-Éò{� iMý >+ÈÊ�ëWÞñúSØÀBDd%” Ü/"¾6DýO[Xãu',ñõ¨‡¼­°¡µÞ#7÷ioVͺÏSªK!A¼Ã·¢7€-ͽ?×Ó‘{«¬ÿT±$- 2ü½wD½…®û%yS½þ}»þq>ðå–„±kÅ–¤•F�d„¡Æß¶VA‰ød”!±¿OÖ~‘áu´æ¼™ƒ~´lk¶¹<­Zµê‚ .ð<¯R©pÙ(îïÍõ£¨ÞQ|øÉqó7ùcñâÅË—/O’¤P(œrÊ)cÇŽ Ã0•Jq+"ú�ÿø� „aX,o½õÖO|âZkά,Z´èé§ŸN¥RÖÚ¯|å+ÖZîpÎiŒ N;í´û¯¯¯³³ó¡‡:î¸ã¸t•k‡^­Vs¹\­VK§Ó¼†¼uC­¿Ö:•JEQÔÓÓÓÞÞ^.—›ššÖ¬YÃíF`dÚØHJ)e lÚje­• ™HO‡aHqJzi)|cc¡"ÏQ¬7è«$w áYPDDZR*Š¢õN!ÒD±g¤¡Œ%O“´R JI“èX'1%FªT*cŒÑ:$a„0RJk…µd� ’bà»›”i"²¤6ÝWIKR Ï)ÒÊ i�°Ò’°‚¬V¡HJ²Ö’6ÖZA©Ž-E…žQÖøÖÚ(cµ ªO‰ Hy†”%e¥°d8 ¸‰sË†ÈØ� d¬Â’RI)„VZÒV�N4‘§¤gŒåÏ T:E†Ïy"I$ÈÚa®\¥”µÖ}…aA†4ÕOX2q$Œ•~à§3FÈj!Rž¢$ôO“k±16-ƒ@ûVëÈ·[ÏÙ¯… •!!…ˆ„Žm‘'=¡‚Zœ2Vha­$-ÈJKd…© ´šD"¬$ò„I‘•$,‘%Y#¡‰ ‘g)EVq˜iCßOø«�µ–/LcL’$Ã>£1¿(_OC’Ôõà‹2äRÆ�•ZI#H�iÌ+ÔÇ@Èúr4 k…&"1ì»ÊÛ&- þød_od­•F’!C¤IeIZ©´2B6ŽŠØR„\˜G¿%IÂãÞøN€ÍBZ~ëš„¤…µÒ ²Vka¤�Ê“R*"eŒL¬!»U}VÃ�rß“%Yµ¡ŸG*i¼N=Ϣ丱ÂYa=KÂ� "eIZ«lBÂÄÒji´�D"H¬2žÒ’$Õ|›(+-y†²š<# ÉXÊXR"�Ú·:c´4¤…¿I¿Oò‡£4RX!¬ þU!Œ‘ÚÔÇa(k¥ñ”‘F�–©Øâ?7M�µv˜Ö° âóD)Ç1ßà(úÛ\ì6÷ ŸX677sÉ)¥T¡P¨V«ºN0Aà.à§žzªR©ø¾?yòdN6ðc¤”|1§R©éÓ§sµ«^xÁ­-X°À÷}­õ®»îÚÞÞ.„pñ)÷Ü©S§AEÑÂ… •RµZ�á±\.GõFÜ´cø>°,‘ò„•¡µÐ‰Ð‰M’$NBÒ‰'¤ï§|�õtBüpC_BÁg£»Á·‡x´1DF^ªêƒL� é{FPEq-¤D+!Uà{�Öâ$Òd„°V�!«Éja­°_j|!³2 㡌°††KKJHkE5 û+eî—#„à ¶,+ˆÏ,×ùâÄÁÁÍ3«CÉ�Õœ±b`Òà�•q¬Ã0Ž¢$‰ë3 „B¡ˆ¤Ö6 9ôiëÏ5õŸ‚Cr—çÀjÔ/Ø ]ÿ¦¦&þðÒQljÕV$d�„QÖLœ�0¼pµá ß b�$&±Ö�0’ŒÕqEµZ�êCí¬p`€u¹�1sy=òbçJ Œ«Ý ƒ.Ì7ø<Hr¢Á'­È4Ž?x÷@†ÈHk$‘ä$I²ž[g~öfÙ¥’ˆ$Ya¿�5|¼FŽ”¼Óñ…É·¿oéõ‚m‹°²a侕dø¿™LÊ÷}m¨ÆÕ0Œ“„�l¡¹ËoÇëƒ�Þn}ʷ݇é0שødä›nʦœòýó}`? +¥uß —V*#…•VÈD’‘Ò"2r³üD]gƒV”„±r­OX9òNxgjü–ûF_zaÛÕøîâ�o±Û\\[Jùîw¿û¼óÎknnæ´±X¼÷Þ{o¹å– ]'š„<ÒçŸÿü'O’Øk¯½x"Eãl" ‚àÐC�3gŽbÑ¢EµZ-ÎF<øàƒA”ËåýöÛ�ÃL<žˆÿËû=ïyÏ“O>™$É“O>ID•J…É/Q©T‚ à± < „“`C…¶}ßïîîÎårü<ï„ÿ»¥¼YVHA>Ya­ "Ï“BIeI&&Ò—"%È ‡P}"žZ´o<åh­µÖM$¼>’¤$eIJ)-I+­ )IJ’ü ÓJcI*!=EŠ´!Ïó|!•´–B2±Ñ‰µdÈ ) I²ÒTµ�üf%HŠM9ŸCJKDÒIFHKÖHKVP˜$$DJy¾(k£-9†[‚dIJk„’Fa¤D’|1ð_ "%…–ˆÄ¦=XÒâ“�l=Šç‰81JùBxBIAÆZRJJEÆVë‘�Ì´ÖÚZ­$÷H²’H _-g½£c¬µÃg»×‘‰¤ÕÚzÖz$%‰¬´ÖÊ”Â!¤1‚ˆdhl"­�Rn5ßW‘±�–H ÒR$B KÚ i%Ïë—$¬ ²¼@IB R4Püd“Îç�D$È“–„�«#H É™a¥PDf b#JÉÁVÊMÍØ,¤Ò’!-¿c ÉcøkILR©”ç‘GÂ’¶‘N¬�­Úо�ñ&¬sOÃÇ¥ z\¾þ°·]’Ÿy�”+å&7#ÓZ+%YOÿ`%Rz‚<©ˆùüÕQeI*’DZ��DФ”$¬g¥'¤”$…ÜÄó9 ñOê�âTÄ_n¥P$$ Cü…œgQò÷�­ë|à¦50Äàè÷ÆZì6—ç0ƤÓé]vÙÅÝÓÞÞþàƒ¾…EqÉ÷}km©TZµjß~×»Þå¢À�y"Úm·Ý<Ï3Æôôô¬^½zâĉJ©¾¾¾Õ«W·µµc¦M›FõïÓn>&ߘ>}:§"z{{{zz8�áÞ)8³Â¯Åó7“$±ÖSºÊó¼0 “$ñ}?“É„aˆëÈbI’ÖZ“£U,…Â’1ÒX-É))%IÏÚØrÑ7ÿuüÏáçZ#¬ø«±$¬Õ‚¬%k©V«RJI²ÆRb’jLQb2^ެ´6!+(1–¬°VIiÈ ²Z²di`¸¾°DÖnÐúoØþZXk„±”ðFg=¬"cH*a¤$ABXk��1ž‡9[Ž%�Ï kc!bÅ?Yˆ ).[<ð0Kœd7ñfMVZïb©^Æ*)<²Þ@`!H�1ÆØÈRlŒ±ÖX«”$!¤RÂò1¡´õåpg>ÿºãO ÷Ï �lõUËB_$­ Ò¼ÚÂLæà"‘›lZK\½Ïj!$"2ü�ÀZk%‘²ÂXkÌÀ»¥ØP€-Šv¹ëô ‚§›€°–¬&+YË“ÜÉò¸Å0®Ié ­…§„𬉠«HneoŸvˆ{‘˜‹=p'wmÚ°ÏSáÐA?W×}ie¬<ÐÀð:MÆ’d�ø2(-YÆ "«,Y"a¬àÒa? …!‘k­$cIX2õ„fSΩ±d…ÕÖZM®?¤±–d[²‚_ ÒVX"þÀÆ \\Î݃¢U°®Æ÷p>mÞþ2·¹<‡ûªZ.—y¦§ïûoT"y=¸¯÷ÃB¬X±"IžÛ1aª7ðt%çr¹\.ÇÅÓW­Z5iÒ$"Z¾|9· ‘RN˜0� [gÜ|‘öövcŒçy©TjñâÅp¿J<<0Š"¥Oä”Rzž7LÞ¢§§'›Íòk1~|•I„�BJ!I)kÉŠÐʪ%k“L:§cÏD¤µUÊú¾OÖ‹t,½ Keù¾ÏÉ6jè[ãûþzO-!H þ‡•yÐŒ‚HÏóåÛ0NŒ6R‰À“��¥ ù†”±JEÒWŠ”k«…BXA–GBF¼>WwãïOB«�×°\Mœ¿Àr�ˆ06:¶†¬òÈSJ^¢7i}sް¤Œ´DZ´ç‚iž!eM}¸™�1Ú<ÂiÓ¦r 7T[¸l‹P™ §›MÂH¥ŒÐ&©j¥SÊZ¥a�ÖZó›7‘0V 4£³êÿ[?~ëvW¥‚ê´òF�LùžçùÈÈÚZ"´B’R±¤ØÆ‰ÖB%=!ÉH)A±ÞŠJ%ãQBd”Ržô=deBÖ$¡P¾V�g…�FÖÕF Ti`þÀô©ú¬,"²B‚<²®¬7 \�ÂnÐ[Šçyîó”ˆøó”'þ®ûà�Ï>Rm.R+ä)ò4q\Åód,‰ˆ2^à%"‘Qb�È¥#�jDD$‰”ÉxƦt웘‡{¦„§¥ÔBjŽÕC¤%‘0ܧîͳÂ1PáTr%V2Ò’°žiJy;К,%[Š�Èsl)Ê’§¥*ŠiIÒ’¯)Ðäㆈii\W†M]¥^ü×ÕÉ–<²ž’Ê2DäYÏKˆ"¢”%Ï뉔5^ �()•”ÒZ#d@"Y»ùp3ú¹D•û ãët¨|äP´ íYÁµo¤õ¼T | H+ )"£É#òYÒ‰MOË­éwµ‘*#…P”&«8,l“JMG"åkR†"¡ŒTÖ(k‰Œáq{Dõ~ݪ~ínÖ]ïÒÁo'†øÎ�¸Ì×­â²¢Ì÷ýT*åûþzã2V�†ˆ<ózç!]� KÊriGÒBhÁo€R�öL¢(‘¤‰Œ!©…2ÂÓäÑ@çU+­ñMBDñ&¯kÁ™9�Ìà½g%YŸÈ³–kgÉ�DHdj‚linr<Õ1¢ª8lNÂJ_Kž€o¤ÑÂiŒ0’lÚ÷Èò—MIR2²ÚßÛª¾�ɵZX­Õ{£å ùK/_˜<ès¨>£‚Œo ÅÂ3B)@Â%Š4G$R‰*ž²‚Ò1 2¾Ô$AZYã"+é+)•’Z’²&ÐI6ÑÂR"•Þ´¥q‡ÚoÒýÕ Cb Õ•Ú”¿—Þ<¾Nù3”«Ñpã€-½^°uq“98Ìø‚óëÚæ~Qäóyªw#çÁto§wÈ0ÆT*¥TEAð§,‡†ù,ß¶Ör…(þgWW/$I’r¹Ì½:Ü !Noð”L~|†cÆŒéííBpãt7cƒO 7�#�N¯ZµêÁæ{yµZýØÇ>æ†R½ŸÇÛom›‘ ù^`ˆˆŒ¥RL�D}ŠT-ɼ¼J“Üœ`ϧOa}Ö[÷oø_IoÆ6ÔæÄ€‹ì[kS©Ô[+ÖÔx¡rCkíf‡¸ë™¹ãÇ_�—†a¡PàªS®@кïRÊZ­Æ‘,ž>Â÷»F üžçi­óùü𓸟O"qé ¼õŒ8Šˆn¤|óüÒGç?~‹—*&Úo/ìsʇÞe)"(/!J¾2oØQæÓÒÖØ€d˜05ÅI*¥Ž 2‚""¤þr^&v4ÙOùÞ1”OóðÕú˜$7ƒ£^)}3$„ )_�1IEDF’¥Å —½òB±TÖ^†ZÇGLÜÕUF‚-F2F‘”d‘ ™P"HJLê?c IS�n*kõP\ë*’,%DÕL?±èž—^›¯2}¦L›tüqïÝ•GiyžÏ¿ŸäëÙ=³öˆ¸!¹ª.mωð Û—DÊJ“æ d�h…¿›wÿ %…ÛÙ̹ǟ  M¼ì­ëÃ’òÅ¿æ-í^�ÔJ±—ò¶Û±}ï#Ç�á2ÅkïI¡ßÂÃñ˜Â€IDAT›!¼³m…Ú’e%‹DEC¡¥,‘/©¥Z��R~dI +ˆ‚ ]>v¡ú×6.U<Ìãmãg®‹gIF:‘QâSšiM±G5¢*‘%òˆŠ†FIR¤l\“~WË^¦Àgû멎͵GæFÖƒtŠç¨ðû Ïîˆ$ÅFûØ< `I’„뵺âÀ¨°››{;\÷KŠRK{¬ñR]Žt�*l?i×É“·þ¯3ÖjcŒ6qেذ ]àÀU™$ —i}£ˆ˜%7ÙÛ ÌŸ6!Å‚¼�Ÿ 5mÕM¥ˆ|¢ QQR­¥S "aÌ@§+"÷-6sxóz ^KI¢xà+‰•RJi6^q0€·¯q´þ )ÀPÞ~±Ðm.ϱù¾Ï?VyÊÿ7Š"÷7d�ÿÉ·“$áÍÜ Ä•Ïâ©DviN<ðrÒétoo/¿S4޲çrÏÛâìE©Tš0aÂ!‡’Éd†šÏ±×^{ !Â0ä¶"üê.Ñ#„!Ò¾Ÿ‰¨”˜ÞDv Õom*Jzªº?1¥Œ*DQQ�öI«¬6¨EŸ´©TÊ�îlY—¤ KÖ�2ÆH£ÅŠŒ e$‘çER™¼W&ªÝ+¨;%«Bz:馇L†„ŽjAd¸M°äqžÒÐ@eÕM[OÜðÀCi-È’d=›‰’5eCß‹ó)-„±6&]#©(2‘ÝÔ£ba‚L*ðÈjŠH%1 ’�—Y¥ÊQ$-I#‰ÈHŠ%ÅŠ„¥TB›°~±õ¸¸¼ MBKJܸ1C$¼8ñŠFôÑ­Õé÷�IWÃîj­ß“FPl’”ïgÂZâûžå(à@·לCÒ?]Œ1Ùl–›w¹ÞQš¿–R$­'cž§•×G²[éÕžX• ¤•ùš,jÆÂ c™MÂ$T6>ª}ñ’´W#ªfüHCžñl”çèoM×¥�Í�ñ¥Š�*$cSß‚ .�J“0Qd++zõV^$O+Ùš²»Œõnm“HÛÀ·Õ°¤¬ô=%v‰¹<]4ÆÄq,¥\o?FþôD2"O&QTóH ÊyYåÕ˜*ª½¦“g׬Ò6Èù¾*öÎØq¾œ‰ÈW^X«%R$Ò#+•%Ϙ@A”HI2Ò"OSJ a…)Q O¿øš6¡Š"’YÊ�%›Âµ°&П¶´8Žù‡žj­£(jü5°Xa„%e<"•©¥!gu(kÕ V+„¡JL"ljªÔ(ñ)’­è'¼Lb#¥Tž�’¤$!­RR)?Š«ÖYi¹Á¡•DJk¾3¿Yü½—êשµ6Š"¾±îƒßh-)”Ê™J¤´¤¥‰”Q¾oI�¶[\û·¿(Þ"N Ôj5N0d³YžÉEÏíàß®®3G ¢(ªV«<¥£­­�/òL&Ã%ªŒ1¥R©¥¥…ê\Q}l‘Rª»»[)Ç1·+'¢jµÊG*•J6›åÓ¢­­ícûØG>ò‘a’+V¬ˆã¸\.»_Ý•J…{ªoé] ož!k›�NT¬{�è5ª×R>6å(®&QY+‘„ýRè„R–Q¥TÁK5Ga[Sa‚´…¸ÖìûQT£ �KÏ R†”¥Hi7í¸AFYmIikµ�Z)BßÖt"uwü¯y¯Vû Z§L:Þá]m-;„"U Tvk“ Û­u&“áv‰T¿N”�ÍËXa‘Ò‘J„§¥!’®æk¡¬U ‘NiÉÄFU*q(ª¾·5å9H%¥L´Õ:Ž“šÖ1G¯8‰H¤¬Ö*ÎsX«…4ôyJDüã”?O“$áÏÓõ¯ IZ •Ö³±T–´4¡2ý~¢[+ê‚È'ä- ½ûžY¸°Ø)µÌÖ’ÆŒoÛwŸ¦R¥©˜$:$OP�ÖBãI+¥å¯åf“f8¨¾¿Œ0 ç9„V±õc/©P¹[ëXK�l6 š¥ÉÅ•¸’ñ�7-ØÒ‚ àé˳N’¤Z­¾‰ÙW°mqȩ޼�.½ÍÅâþÛâÀèÑ£Ã0äqårÙNo¸Ì•Ëe!D©T3f §ÚÚÚ’$I¥RQU*•––ž±áòîëuµZõ<¯R©l·Ýv\–ÄåQxPçK¢(â$XµZåû×5nܸ5kÖðƒ¹ÚOÐÞÐÐlQÆ’Õ–„Ð E‰(Q²ªdI©­ Ä’LŒÖZmkµÕvC¦×r[¾Íï>ÜÓe½)4+È�•–´5Â+(±F“%"‘-ÈÄ"²"Šýš2¡O¡R¡„Ö†BG†’Ä$I¢ãDkãI©i!,Ie­5DÆ‘¶v“æ9Èò.Õ±PÆZIZÛXk¢˜¬–J§¬ ¬NH[Q,#­´¸d¶¡ƒ´ò£Ht)ñÈZ_ØLG“Îxe›�ÂÈ@Ka­�d¬´‚´¶bÓ¥r­°œÛ „D¬H“ KÖk�ÖV[Y1²f„°2"¡­�­UÆH.~¨”2FV†¬+Ù¦‡úÈ%__kyê†M ¶k’V$&ŽH$Š’T[™(¯êD¢*lM SŤ“XGd•Ø ?ïÞ­5Å$RÆ'›†HS’PD‘V‘¦DS@F“DÆ ­ÉðÛç–^qØZ´Zú+}ùBVfra²&‘k_$IØW^é’ôR:Ž%…F[K*J¬Tzƒæóñpª˜òß$IÖûyªia…!“Ëd´¶±"Ï(%êch”¤”_$³´\¬yM™Øv„•Z:MBKIûäű6Jhk­�Æ’1ÄoƒFÛMšç [2 i-ÈXm…–VSB/Sí­E½yc)ì�MYfýB$b­õ›¬Ô°é J=cx">æ»Ãfd¬Ô ¡5©•�­¶J§´&�ÈD§t’Ñ$¤ŽMIÒRè­)gmBDBXFJRž'„ÂÆI•H’õÈ*k­5ÂÚ˜ˆ”Gšçh �ñ�Ó¡K¶A:‘I¡Œ5Z”²µ†Ôë�í” â@®ÖáâROJå3aEQSSSµZå7 ^[¼ïŒ(J ÏÍse…0Ò‹…"mCRÒ’²FYRÖ‘Gä‘VBŠ·ÜêÍLòóIw€æÿ·‚?Ð k…±¤I$’ŒçéY-¤‰=ëûV¥¬—¶2CÂ’±$�DÂ!¡„]»ÅôÆ&H(2†´àÕ—–È’ÕB*)ȳR%�g´‘Z� IÆ» W†'¨‹+Vö=¸Èë¬xZ˜ÖBóAÓõv¦�µ$T"|#<#b+#Oh²’6åW+aÉjF�&a„µ$„0ŠH "k�±>‘2ä’VPb)…ä"¿ÖÚ, !H¨�†È¢¾µ¯ÿw07Rf­ÕÙÀï‘\.NARKR[ÏHß(O¦Hø$Y+Œ”DB(­¬Âj!·š~ä’ˆ$y"QÖZMB‘à$†ÐBj!IXABYáY²‚|‘k9 @DÕJX*U„²±UjkŒèÖDÕ¤âgl�’žðlœH/ð¥¯t!ÔFˆpƒî:åÓAcõP)„²ÂHB�$+H(éI__ÇÖxʦ}[Èè¦|˜mÕZ¥û‰ò9ki,%‰¯mÏ MB Ë 3ÌÀçÖ&üôdOÌ´Â E’„UŠ„$å™,å3~›…ž¸Ë³¹Œ䥓xsŒŠÞ ÏS×þ¿�`3‚¬ áYa…H„ ©H(# +…–VKc‰|#R+Krë:E•RI%:‚”g¥Öê$á`–Â’°ÂL…°Ö!7èû˜«„ߤ<†`½_†ùáV #ÉH¡H(ž%K”�PJùJ¦|ò¤¯¥g6eªaÁ¤Z¨Õò9�MÒ2I¤ï§Ré$•’¬$KÂ’‰""¥Ì¦ý6,H Vj’B�¤yÒ’o³•î(©êÄFÆZßfrAŽÒIµVÄ÷[ØzðÊŸ§Ü“xK¯lE\ùAnY?ÔL÷ …<Ç[Ç�¯’$QJ …‰'.Y²DJùÿÙû·ÛòìªcÎïZkïˆ8·Ìʬ*Wa°ñÝ@QÝþý°…5ü@Ý`aµ„,xí? %Ä[?öO µ@ý„�¥n. M#èׯ†eƒ�]åK]\×¼œ[Dì½ÖúÎ9úá»ö>‘·Ê8EFž“yÖG'WFĉ³cÅÚë:Çœc|ñ‹_l:®Œb´þ‚/}éKM y饗^}õÕv1¾uëÖüÀ¼ùæ›fö¥/}éÇ~ìÇŽ^RWÿí¯þ꯶D�O|â/½ôÒñqüà(«ÔZ�³ ßã¦ÇÝ7›Ín·kÿ¤é1ÏÕMÒÊûa}w¢i"Hš`!j´™ ŠKf€T”&JOÓßqÔÛ®VdÞ˧X8ܵ&A Db1¡"YÜ«(ó`•æŽÎ•�ºÖ¥mT•�9F˜IDP¸ÒÐ.Üh»gH³ !’HCU" í #ƒÌb­t혥§š�Yù@‰[·O¦7}~¹ypч¥——J©§gßÀœ –ìªhrG]MBûÀiM‰tÌTH ’D·ÑKXÀnÙkšê§ÐògY7-;ú1ÙܼûÊ›Ùñy¯Ý(´¢ÌSý²!ÀH§¥uÆ’¶lä]º…eÂ̪[T?˜‘hû¼éµªR¥©�RJ‚Qjv=„¸¿+¬”~èOIöƒ ¤Ó‡‹!Jék°Ö˜2!!*¦tp–}ÿ:ÎÅïu=URJ&%A)!¥ƨè'íæ<ßãá ‡u¾(¼7K�÷÷ãéÚ�¥+f-8‹íÄH[¨nô~OBhé•Õ¦p‘9ʦέØ4äö�c*Êj³±òì9§ÇÞ¯vœ®u™•²R€DÈX¡€àmH¢ Ù,vÑ©ºáÐ1óœPŠÑÜBR˜‰ 3“ðÖ I%%JùTxWûA[Q¬=Ÿ¾ëq** 6R–“™u /}­¹‹Ý9óQß?B<èPœ[çƒÔý·vc™s”2/mIÙ¶¶$¤ ¤ÌÿBhWÒÕz Ò‘ØZíϺ³©îèyŠ “Bâ ˜¬¬\‹·•›#úê³r•v>oOC`­fÂý>‘Ô†9ŽÏ«ŸûÜçšTðŸþÓŠˆc²738™ù…/|¡Ý+ÿäOþäÉÉI3§Úl6Ÿÿüç[ðÝ/ÿò/Cž�Õä¦s|á _h:Äù#¤ëºã¬Æ0 íG43ÙöÁѳÒÞI}ßOÓÔ~n Ù[EŽ�2ª@½²H­™hþQ�L‹,B1ëÌz¨S~ÿÇû÷±o´�öÁq¸XF”Kë£t3‡Ê~f?k¨(‰®e»-eI„!hÉ›>_ °‚  yU°¶šS[¥cpøÔf²+$Ì‹óG9^»ñ•ä«3N.&¿Üï=¢H %Q] $,ù45Éïg}À NàÜRÄ©–®Qˆ”=µ5niƒX„.3� ïÕ¼`׿L_m8ý>nDT(¸YÛŠaÖ¶Z™Ý*K²hynš©‰ÏWó5Q‘.‰¹õíÑÚsõ ¶P÷¥tpðLXûiÖRó<·Ok­?öc?Ö#~û·»éo˪µþÚ¯ýZ)%"~äG~W®Ç?õS?õÏþÙ?;99ùµ_ûµišŽÆSG«ˆøÍßüͦIüø�ÿ8€–>MSß÷Íí®™µ)’Úß¾ëú7 äüü|Ç»wïÖZÛ“óñ7ZùH�™™Œªšb¨ù;˜@5†ÓÀ¶Ø,}¯´$>6¢¾—¿µ›=fˆÙî¥@+Á459Øšuu2•’AVö\µ…:]ûõÛþ¿WŸâßõ�äÓèÐÀ6}EÂ+Y�»$»®s:+™Ã€1žîœò¶§»ãŒö{|»`iÉZ-ÃO †Ô4M—Q­ß§…bÆ\й×Ò^3ÏÖ•„fE’4™'’0eÛb|ïSÊ‚` 3%P… %0X˜’Óneà­ ½æz<>cˆì2KjˆZ2Ln]7[±4âÒ=Ð.UzÊãëû@K+‰ñÉUõ]vW*ßÿÁüÜcÏÁÛÜ«žòeŒ21'¯`.X¨„-‡a2Ål8žË¾™Ä1‚èÐ@@­è0— õˉúyü>º˜È ’•0SzeH›¥jè(¸„˜T7:Oð´t¥ÐµŸv¯½ñ•¯}çW_¿ÿ5e;ýþW¥Ä­b]I ¹ôÔYiÇŽk·øÐ¤’*-?Ò °„Å~Î~žê)ZHH%ö%"D�‰Ì³ªÆT�˜ii�jgÂaË·ó› H¶ñ0Ò †š4mL–q1øêºy}D}¦´ûÕÃ¥³}å{ Ø<#Yê­—T=yhð�œÏ¯’ÇÄâï¯wöêl]°yøéÈg¶%Wþ»hó=Ç’ã5ÒñÂé­n{ì§kþN-Ž»†p%Òê(LÓm€ãñãÇ·nݺj*5Ïs×uŸûÜç~ø‡øk_ûÚ~¿ÿÿàü­¿õ·t]×^³ÖúK¿ôKo¾ùæýû÷äG~äñ¿ýíoêSŸr÷üÙ?ûgÿÅ¿ø¿ò+¿rvvöÿá?üÛûo·f½ö~ï÷ûñ/þE›½¸sçÎÏýÜϵé�–G  g´õi_i¿Eõø›‚äK/½´Ûíú¾'9ÏóÚ²ô‚röòÊ2¦[àÔbŽì‹×®ìd;ãRÊd‘%–Iáëÿˆ·Þ;¾ok­º9ˆLGX�#"y’›S£»g±=§è½Î˜ŠusWF›ª™ ]X¡�ZA¶؛ܢ^¹%à’«&<áÀ&­Dgчl¶ì†@ cÑbÖÔgƒ«Ø´±Ø†2‡Z•EgLTßøÉl»>G$;˜xÃy $àTG´”Žv¤Dä%\†Ndê~䛬b pƒ9²§uà>´Èì 8Ò{ìo’š Þ2›šÞuÝSÞ%ЬdcòŽieïõ²Xízw§‚eÌnœ¼ UÛì<·Eþ]2Ìk±([àijCQCVT�ì‰RÒ)ö`TS’&®-oïM.#J×Ó!(÷tÃG@]ÊÒƒ]5ËMNó£./O9FZ§gãþŽ«èú¯o§L‡CàhrÑ‚ ´$O,Ò×/Å’Í)¯²¨è*LD¢s–b]Iäœò®8Ì/f\°{¯ÍÛ:•ŽšÇ»D2Š!£D gGÂ61 z˜PzõuŒ�&mxºÕÉ›~8õ©Þ¦÷ÂË›N» ”œ•,¦ÒúOe5Ù<-ntÿ÷ )sd§1Q�”yµÍÔcîŠmé6�yžxI= âSˆ­|@ô©[Ì×ë×Ï¿öµ{’¯9?ó—þ7ߎìЧPmå)€­ËœxŠãëiSV�#P› ¢xP>$(;ì3‰fÄðm·¸O,מ*ïJÎÚE——ÃlœN…³¹pö¹úÔw*ì½^î–Û› �—Úô}Æô\ém&›œQ8ÔCnPr^‚3h�N€Ì«O·K]5Èkd}Ø&z`SËv.Þ×ÊZK�®²+ÅŸ§©# ÌÄâ±yø«_û¿ŽþµMw2=¾÷G.ÿø'o®ØvÞG) U1™âé®§8<™¾M•|�üHw¹+Oj®�9åa¶õ’ãe·¡¢Sá‰_bÃ;»“i¿Ý]žFÍ1X{/–€\ì’¨.±„Ç�¹ˆ€H²Kï‘¢ ¾Wé.�Íí³éq1tu ˜bªÃ%ëõôYAY—`ò6µ%Ó�CËÝÛà ãº~½7ï¶s.Âßpì'¨@| çó«Êí2Úüfžj¤£ÉEJÀ„¤0ºU[Ì?†š�@¤€Ù�<öE­|4hÏGó<ÃÐjòÃ0<í}×;yátަÌÛ§]×�žž¶Í­ ¶ùÇ�ãèîGáïÿý¿ÿ«¿ú«™÷ïþÝOúÓÇW¾sçÎ_ÿëýïý½¿÷õ¯ý _øÂüƒðOÿé?ýÉO~²…‡ÿËù/é—~IÒ½{÷~îç~.">õ©O5‹ª[·nø á/|õ«_�¦éßþÛûÊ+¯üÕ¿úWK)$Öç ‚µÑ`"W| `É,a‚HC@ÕR\ G«!̪gI Õ Ð?®–C~sˆ–0m Ń +AËCk!<[°jOYo"Ÿ!Æì,»Âk ªÊJx š=Á¤ÐW˜òCiô0¨ˆ a9"hq…ràŽTßB°08äPÙá ÒÁé¥Ý¨…AÉʵÿ•AFÁ%Bi–Õ,ÚóŒ´9bzv%‚7n%÷$P‰ÊbpŠ ´3O�œ¢'¬‹}Ázü=4ß¡÷]ÊÄÖò ƒL ÒӂДƒt+ò¤/pÌÁGÂ.š®ÿú –4•¥…Ët0‹KBΓ+ÜS?â'Øü‚‹àbóˆT¬íN‹ùyB6@<…­ÜÓBÀdD!ËÉAY_�i²zÂs(™Îì=á†.Õ'JÊUE¶¤g-ýniy£7í=¡%a€gº’¬‚%È‚t«i38Ëf¡ ‚iOšÇW>\(±V<ºŸßúÆ4î,˜·ÎæóÇÑŸ@fíÒ¹T=‹â~ãþÚ­…3ùž98¦åÿ¼Ý‹™à2ÐT8©N‘SÒÍça³ë»@LuL²ÖY°LÓ‡è%÷t,ӥͻÕ�¥�ëåÒ~aP s`íÿ1ÁÛü)P=�(%ܳ´`ë´JÏdÒd|^›®ÒwÑ+ÊwêÀ¨“|L^¹oçüåžùf7©+û˜“y5x–.!-å�\è¢ta"JæY¦ .XP1YÊd˜]Ê�yÃã4ËõTæË(‚sX¦Y=D¦�Ía“ÅÚ‡÷\ ¢)N"R ñöË™>„;{ǬÆ[Ö`‘:–áé|�o{–èŠáª q”I¢u?QËF^Åö•#/\}üèÃs´„jÚÆ8ŽÇ,�ÖÛ¤ãHÄåååÉÉÉü�ÿñ›ßüf×uwîÜi"ÇãÇ�·ÛmE>ÿùÏÿìÏþ,€¯ýëÿàüƒ_ú¥_º}ûv)åÑ£GßøÆ7^{íµŸüÉŸüÁüÁŸÿùŸoã ­ë¶©š?ó3?ó[¿õ[_üâù—ùý£ôOÿé?ýCèEÄW¿úÕDÄOþäOþÄOüÄ_þËÀ~¿o+¶Æø¬¬¬¬¬¬¬|°%aOóÄÀ0LW†ÁÓÕ…“ÈéþÃó¯ÿ¶Eõ)æÍí[?þÓÜœùTÅ=Y=zÔ4á¡ÕlñË;ü€ æ’ñ¼WVž;ÈÌÇÑ..,8ö�$wG}Fë#çÕnS&—jLóé9ÖFm°¼AÝñûYýy6g/Î,Ùkì6—6g*ÛàƒdµÂ!ëî'çòñoŸ¿6n‡.ã3——â|ªŸçB1 žÃ©À _†êdbR|2á{ž«b++++Ïñ­>Š-©- x’2÷äŸ|(gÒ·%�æ•Ñ ]ù"–3ÿótUm[/¸Ly‚é‚·Õ„™ß|‘®+^8�ã( 4Áƒd×uŸùÌgNNNNNNÌìõ×_å•Wš×9€¶Üï÷}ß_^^Þ»wï»ßýîùùù�þè�^\\œžž¶WkfvçÎ�_üÅ_ü¹Ÿû¹ÿïÿý¿þ×ÿúë_ÿúÝ»wôGôsŸûÜÏþìÏÞ½{÷•W^ éÍ7ß|饗4ÍÀ½{÷þüŸÿóòOþÉ/~ñ‹ÿüŸÿs3»¼¼,¥üÌÏüÌ_ø á‡~è‡ÚÏ:J/šcÕ¿ÙÊÊÊÊÊÊÊJãè„{M¦’{ϰt$”“§™Ò1îs¿»¼3WŸ±Û_’óœcÑàyÝç¨Ù1:ªg[¥6¢n‰T6C³¦sˆËƒ[{׳Þ�++"ŽÜ -'ûP§>ÜÃI€k1HPo³ÔH )"Ï!›Î*Ãç´Ì‰öÍyüßyíß}åë÷�/™ÿñÔúäK/E”ÌÎrŽçó9΀‚–ŠÄ&7³ÜæUEªαÏå{°²²²ò H` ‚„f–[mÉ�ðv5»rÊ7<£ùƒ¦[? o+áŸ3k_P=©t¥KEÙÖZDЂ) i‹kºž/ß­•g §s”Rš*pT2º®ûéŸþéòOþI³®:;;-<#3û¾¿¸¸Øl6gggçïü�–ŸÓDŽ–I.©E”GD 9ÿÔ§>õ×þÚ_ûãoe•ËËKwoúÄùùy ŸçÙÝ7›Í1�çÕW_}õÕW?ó™ÏüÂ/üB­µ™hxóÍ7ÛOlS&M™¦©}ð\Þ¯¬¬¬¬¬¬|T‘E*-`ï»læQhA‹$s²tCW9¸m渇aÌ@oÑK5 ë¼²‚2ᨋ,®5ÌXz»tÅ´êØ�ö¬·àÊÊGˆR œ"¦i¢¬ Ž—R> 8Ò§ƒzÛá›  ·;&-YŠW–ž‰¬^sðRúQß²×c¼¼_üUóW«ìäÔ.EMpD­nݳ^å«e‹uUS5TšðEèð.”·Ø¾¯¬¬¬¬4Dº!�$'GÂÚðq®¥‘èC™�Ì–¢wåzü€ËÝò[®­Ï™H ³´$Ôâf.X&€QÓÔÁ(³E¯yÎ~‹•�NçÐŽ«ãد¾ú*€f@’™] ÷nâÇ<Ï]×ÕZ3³Mr´¯»{DDDß÷í{®ÚIMÓD²ùM8Žq4 £)Myøðá�;w"âöíÛMizL×uíŸÜ¿ÿÞ½{íuZ¾ÈÕßbeeeeeee忟´Z[/÷5uYƒ×R0» ÀdÖ:­Í¬€ÚM1¥ÆÙÇ^û!ÃF®ùúº(CÏ.:̧'!fI ÅîYÔgWV>ª�­kŠ$A§ÛªžÍŒ¸â·¡£á‡„ `ÙÒ°Ÿ˜ž?ä 2¡¤º¡äé�ñöÝ>�¹Nw›¾·}‘F¸…¥1ù>ˆ «\lÙßgi@WÑ%;Ñ`I$èíoÎN<µ®t'E1xls!£Íi\ãõ]Ö%JZ›!Z¶yŽÃÇ&¤åÒ ®ç+”xeå9GÓTk5°˜›ŒdDLÓÔ£ùG-õ ¬nz’œoqoØ“¿lŽIrÀ´´©ÎÏz^Ù˜„mzaö`cÊýκ‹Ib²<ŽùÑå~ö»uÂi�ÎÏz¥¯@™G´ަ%‘ZÂ9ò0LSŽ=ÂD®²òÊÊÊ Wí2¶óbû89Â,,0…’ðDÒ‡š�‡޼ro|3˜‡ñÉ«ÓÏ×ý³iù“\ÒÛ @´{Y»%iƒ2«Ô±‚Sçh£MÉ8ŠÇpòöõ£¥CÞ&'´O�½NÇok¯st”:šJDÚ‹_­}p\“ã·‡BÞÖNÕ¾~üÛUäXYYYYYYùþ(¥ŒãØš6Ì,"¸3#-á ÌL–“IšÞeÉd zÂÓ é@&ÛmÍ© �φ©BA·®Ú]Fx×W{çÒ *aÍH#RF”°Lµ·û.«ž£ºçÊÊsif–Wä ' ´«©Ó^%;¯„£rYÊ�>ŽsWŠY i]ß�ã>sÓÌÚˆüÕqùcq{s�<õa?åË/�rÆÆ6—aH¿}rwqÛýdsúhÜÃÍþÜ&öæ=a˜¦(ƒ{§óéÍ;÷6ûi�6d'ŽYµë<ÇÊÊÊ ¸tZè»û@-0ïû.œéíŸ%­\Ùr;¸y]!ÀlV„Zðà}ß�û¹y̘Ù\ÇZ+i^ðüœÕ)`DzoÃ0„êTç~»=??‡qÓoê<ÏÓ¼ÙœZ�p³çeÕWž)/¢Î±²²²²²²²² …�5'ÌcYÐÌK ù%%p™ ×ñã·/­D)RBh¾U2ƒCî§q;Ï2ޤ±pªº¬}×·ÀÀ÷|Í+KÐ4ôqèn+ƒHI¾¼ˆ–ˆrhëlZÝTVV®Í{µ@^-À´NIÝ|·$¥V—YÜó–.Tsë·›Ab"¦vãNš·[×âb!ºÙž‰È�–Œj0ƒ¥ „u�>PÒ æ`Í¡=ÛPÚ3YÑ÷Úøi—÷Ço}õ�‹ý<Õy8>ñ·7·D ˜à@! øaì++++Ï?†>|ãw~'¿ó¨éesúÙè~ø³ Ø;d¸/¦ª›?ÿ¿åNøø£ÙîrŽ3Ï$c¿Ýl»ž—»‡Ïz+^%O‡!æZ#ê~ÜGNÎj¶?;1–(-“Ã\@&‘$±æ�¯¬:ÇÊÊÊÊÊÊÊÊ K3Él‘`’Ze0ˆ¾¹÷Š ��>~çrv\v™6Ì%kI4±ºtvkS·å|àÉ~—!•M×õ÷Nn�ï$8ßû5¯.'ÏG6Ç $n Ë D$±D”[6yjñë_YYù~xÛèFûÔ>Ìb<³¥§‚"J³Ëº¼·ÛmÍÉœ}ïf¨1m·Ûq7IÖÎ`ËP—Ô¼ˆŸÉ ³E’¹Ð†Š¡ÂêbÎ~õW¥nÚìé0ìý»¿wÿÑÅ4#ûÓrçöÙ½—O—`©C¹Àd³ÜZëJ++++ Ð)ßøÚW§¯¼¶©­û'§g?ú‡vùä(XCƇjŃc•†!³]*cÇɾ/þœUˆ#G*=h(“�l¾¥Ü•b,pÇ»³ÞÁ˜2#1›=_¿ßã ÿ¬Z1^ž¯�`eeeeeeeeåC£€‘Ì̈h‘`;+(iÀœ¬˜”t&`W—dÊkõ™˜™Qª›Ø¡ºðæƒ×yqr2³,¬��—¾œÞ êm¯ó^Kà3\’A¨šI&½ˆ0rÉ%ÆRÝd<1ë]YY¹6¶|?{š¦ÒâZ¡9¸Øöºc7íœYëX íîϼÕã6Ùã�bølç9 Ø&ÑÚ W¥+[¯iZm #Ìž«ÜWqË.ÏÙÕ“¡/uš:mOûÍùô˜}oZDÊqOYEŽ••• ²zÇ3án¿9ßÏ›úuD;w^¹Ä&¡%!ãÆ.2,Éuþ–ì:f­˜f(ï¸9Ì0�ÏÓ)�¹¯s'vr6£w—Åå÷û;óŽôÛÀOmïýø­;ƒ`)–ŒLÃÑ·²ê++++++++/*G‘£ÑÜ«Hz©R@„B"�¤ )ã!¥ðÉÒ™'‰ÄLN}Æ&Ü3‘$°¹wçâõ~wjç÷wEè¶wË0¼t÷ÖE�ªóm¯ó^Ë1PÊ�óU ó€[×^ÍH &Q2z¬:ÇÊÊÊÊÊÊÊÊ‹‹”Rº®àóxº»`ÌÈT.�]$A?}û‹4MÂv¦À숂¬ ÁæþÑã!*b�YÝ<ãþCl¶§®¿îR‰š ÁJéŽÞЗG—û,%ͳx,™å‚©5K¯¬¬\ ÁÔQßõ¾í¿¢Y>9š?Ú<‡€æ©N‰s¹~ÿÛ¿vkÇq~à¸w‚?z{{»”ÒæÒšÎñ¬L«”43†ôLCZŠ5Y²šfoiދΖñÜœ±LV*ºØ„6 ËpÌN¡/ƒPá"G•¸é~ä••••�Q‘3ç0Í6M9�˜gïJI¤A�03¨ É›îË)yãˆÀÚð"š"w‘;q†OPœ>?:˜ì”Š )êäý¼í¾®øFWª²Ö8/ÅNN=§˜4Û¼¯cañç©{`õ§z&¬:ÇÊÊÊÊÊÊÊÊ Jë}>Ä�€iš†ûoþ·ÿÇÿýÎî² y£}ÛäÇ»½Œ3a£#¶³—(Ò6ȽOÈGgõü¥Í Óýoü¾ðÆ4–.ìÚõÒ’ì/m°N]W�£[í;�žÄÉæÿ™?ƒ.k_ê€ê˜-gB’­·¸++ß/ϸB @™šÂŒJ17Û2ëܰ»Ø½ù…ÿåŸÉî�ñ öwþòŸý?nËl·ÛcÎ�™™Ù3©/´XTM̨†ÉQ­†)o²Â{݇<Û©Ó�=ëCàÊÊÊÊÊ ÑJÇO0ñ°”ŸêÛ÷èi.÷ ¤) J(—†êJk™�L kþ¤õ©~ÄóöÜ.¦`m­®®›ÞV’Ò’q÷T«/fh‰„ ÖRò–VÍ3­&! iÁ"ÄS•6D´ÆÏ’ ¬­v´Yj&W«j!iI&õT–ßlÎÌøò#ŸXj˜à \ýÄŸ`OÞFeUÆøøq¼ö�—.Ï_¾|ŒY5±7­˜Ñ¢¢=ÆŽ&Á¨R"„…¡važ©jVLµ) °¯†þd?Æ´ßLÕT¯¹Ž]b€]f7F5f+u{²;=Å8Á;cÀ¦(Hƒ§‰¦§)pŠ)e:C�³'Ÿ�D”«kÏ 3מžì»¡sÌ3öuÒÞ#’ªj'•§ºµZYYYù8c@)6@çÐÜΞ@ÌQ(wÕn½2¦›-ÒþÍÑÁÚÃ×áé»A*³ž_Þÿ�¯|ñ·¾ò?¿qÿ«²ÚéÕ_üùÿÓõoÇ>æÈÞ7ÖS¦˜w3¶///û[‘º?Ž�ö——S^N³§õÅÍŒ»g½ÆWð,6õÌÅLW6§�²1­‚­ßÞý\ ?XV�ceeeeå&°–¼TÌ CÒ ÇZ´òÜuK(ɲX–´n6�{‚•6–¬„åÔG€ ”f��C©ý:°«àçÉl·È&ã¡RÒì#´Ôõ¡K£™yíû¥ FÖ0u‘€y6»ØkXMÍâ,V± t•]eT{š÷+lv¡T/ Ë2›µž¦4t�(i‚OVÆâÕÒ0óúþ(BÉ$[~m—ÐÁ¸(“)D  ”@¥f÷‡kÝ�bŒýhÙu�¿õ�[üGãn½è/ÆýyžàÖ'/]phg‰ëmÀJ·Ÿ/·[¼öè¿'¼ÿON_™ö>Ü®÷çßúÄÝÐf¸˜ÄÁTÄŠôW…�  r³Æãaãp›&f Þu´9q.îîÏß~yø©D?M4!tJ›¥ö@Ö46™„Ê.ƒbXŸ†É@ñD&XM°´Eì†åTæZ|‚ÍžÕd˜1Ë’L¦§y’"³#Ôe9{´îÂdIm s¥—9ên»ñyž£ÚÙÉK»û{ýÉ£×ß{õô�û8»…iÄ�óÓæ$‚£óìLIDø|ýëË‹— J»^·+ NⳄµí÷¡\ƒ 2"€Ñ¨@ s·ÛµÎ»|ÝN.ró†:¥63Û§GPß÷}TB6ϳ¹õɨćb¯$"îòå6á}lzvö)·ÆÝx²½s1în�ø)ºOôÛïî¶=º^àÌÍàûmw9Y´'‘ç…R7oüúþwí÷çØV¯¹yü³é�Ù™]æCb»1Q[ÛdõçÍç„UçXYYYY¹ òXã2�H°4Ä fž°C�‰1håû÷]Ë`šdÞÚ“-Ûˆ€§• !�¯¯ÿúÏ!¶t‰×Ð’�´<¶…^)B]_§!`T«p¹€k¹Q$„Ã[ÀdL7Còú÷åMjØæodFŠ€dð4F´ú;ŸæõM ˆö¨ÐZ¥Ú:FCBVZMiºžôÎ\«Æôî²9Tx00-KÔ•fmhƒ5i™%“Î:e©YK©ggãÐ�5¦YªpaW¬ZR&0è"JÖãnyø±W{¨ß¹õìú›Ô�ŶsÁþìÔ&]~w¿³?ÙõäΦvç_ü½ÿôûû¯|g÷µœÆWôrì¦òú¥Ã¤ºý|~çnŽùí×ßüRèÜh°ú_ú÷_ÿæïœôŸœgW˜w…¨1FŸ·ÈÉì>X™[´?È9ï³TÈqbÞ¥í»»·7›ò‰?þSÛ—ú“Mª Í5´ïº69Q®ˆmi€)M®e¬¤ OU¢šDÁÒ�žtÈ“ 2dëÄo:eS5Œ©+##&KϺi€!+=A¨@…)”ÉPO Óy¾ñÕóßþÒï^ÞŸî¼ôÉïÞ¼ÙÞ›+²jS\óäJWH"¬)¯p‰:_z€yzzûþ7/‡aÛ Íó׿ôàüµ»¯¿ñÝn;¦Í×Þ£mUœw·ŒÝ¾ä¦úî–ö�¼Ô¦²šÍ Ù(âyêM|Þy˼ —?íþ¡ÙAÕ21]µ�6£§Ã¾ZÂÇ,;9`£lgСãQÿ¶+¹¢Í’Þ8™¤1™IqÑ�`mNÅd®'A©ÕvÓæìO¹öÌ꘽fC«˜Á €DuiC¥ùrm]YYYyáQßfÊÑN›V£õ¥û2¿.Dxº`¼q�»Mî¦P–'óvߨ„PÄåú×jç{zŠ›±£ÁÄ,Š>ç’p³š˜ %kr•’³……ÛósE¥Ê0ÝÚì«Å™{ g©�¬ÝO Y2�ù!u‘¼0¬:ÇÊÊÊÊÊ� «hc~¥nB`1uÆr·‡´f~"Ùj×X HPa V27ˆÊ¢d¢(»h&I¦`Š×~ý篨mÂÑ·j)Ò3“*,CÜ0[v¤åSÌ£8`�ŽðŠ4OzÏâéŒâb +°.sÍ™Îfu]ÂP’†¥…\b‚UÈ4„W¡¤Ï0s¢�©äuoý=á¨`g°G°‚ŽöE$8µ}/-e™lñÚïêŽõέ–cžçn¯¸!‚6ºïŠo¶ï~â3ôÇÆ»g”)z ¸Ý¶ø&�%ˆƒÓÑ�àQð˜3ïœðüâáÃÿ8Íç}w2c?å›u>ÿÕßøçßÅï=Œ¯ ·C§a_j<Åö¬:ÇÊÊÊÊÊÏ!�!EK¤ ÄGpãc“æðîm2¸ÎR@@ÉŒ6€�‹“Ï$Ñea‹ÉÉqâz¯5�à™c²«]¨yzH"¸L% ™-”Â\,À¯9¿B ËCVŠKP‚ EˆDsånÿKÏlFP×}}™Gñ«Ž[”˜ÉÚF.ÂL ªY8ZÀÂõ£ù˜°lÁX¼stHÀ•MÇ ¶ü=$ÍŸÜ¥kø-¿eýí9ò¹DË¥N6/ŸÿüÉ'îŽæ„„¾™Ì{Ó9œ‡m{CÔgØÁ΀Gçù«_žÇ±ëUµ¿˜Þ´ì¾ûæoĽ7Ëæ�¡+¸èà'覴lfJï»$J7°¯‘¨{wbžQGô› q>ÇDtg�M¥›`Sr¦=e1A#Ô¹ËË©Î5áìì�YeAî|ÞÇ7¿ý›ÓO¾Þu÷CáØ9¡ÅÕÀÛ–O@iùÈ6eÕN•ö$ʨ�p™ÑsÁ“%Ñ%\Ö>f¢;¤@I¹,[_!Ò@%Û¬�iJËÌyúâè|NC¡º<¯ßÞ:°ó gÜ)C`�ÄŒ‚ÎáMçJÀ䜈«ú¶�`žb(]Lu 9¼�èß=ÛLsˆ×Ík1„�–Ýô¸Îévº9¹]S�/~ë?ùŸ„ºÃØVŠ3lê‹#R®¬¬¬¬¬¬¬¬¬¼°¬:ÇÊÊÊÊÊM�híÁHQÒÛ  lÿɲU‘›Ëõ_Ý‚�aY FTC†$ž´-·øÜ¥8�§°¼|£A¹ü"MäHqqNtÅ•¨…Í¥Èê®3³¤Î²mÏpŒfûb£Ûd>™§l6›Õ²zíè²×õçc룔D MÒH" TZ�<]br„Cé@]û.EäÈ r€hé&Xh@:@¨_“U&™Ô¥¬Åê¶¹Ÿe ¤`P¦lup´|™°Hî‰ œÜ¹‹®G›Èiùî}û¾¦$¹â&[æYp8°¬»ŸOðÈ­ �w}²‹äNÄnW‡y ¹ …>ãpï%dó89áš½0,ÀDOh ›ÎúfÌ¢s•ÒK›dߎBp: ë8í“æ>˜Ÿ¸uÖY–‡îð3†ê£ñut#0&) ÷A O”¤4!épUÁÒ¬ n<¼3‚…!´Ç´Sß; ÷¬ýG�”‚‰´jH¦±ÙD@*L•2g£wUd…G±jÛz™%±ŸÔŸp¶:iŸØgL²¬ËéÝ„ T€tŒWòux\¥Š,Ý6#D ›Í4Íç»Ý.‹»þî3#çÙ§:ÀÉJ)ÆYÇýŒ4¨‡L°åWO‡Í·J++++++++++gV�ceeeeåƒç`¥Íl‚F³«Zº{íø 8”íÀEœ¸&bg3ªÁ„ÚŒ…`Í€^° -?VÖœêóÚÒÅó3Éñ®ëÖDŽÃÐŒ(RxÛÜAKª°6Uó½—®,)7$2˜“c6„=Q†’)¶ÜÞ¬:ÇÊÊÊÊÊM`¦¥Nœ‡br,¦U-uü˜œ ÁØ"ž"‚ËM4YЪÀdô„%,h³e6)EŽtÀâ©Í‡ž·Ò¶ –Ì£§V2[âzÉ츀§q™¢8Îy¼ÏÒ•]ª@3Ô$ ±ùØ dJéjC¨.B•b^ûõ“Øw  dÕÔ|«ZZ²›Ð‡—l!ËŒÎd=¯8J}¯eAssB« À‘­ŠZü©À4U1 #ÒP�²Äüe©ÃÇI,Bmû?ëàÃÃ}ÍmpãeW iH+æÉ&¨…@ºZ”â´{S+ÄY݈®N˜úþq·Ù 1!.K1ÖÜ]ÌÅOfÍtvxéO|þ÷黟ÛvŸ¨×¾Ë%¼`0˜s«ÕäØPÚ™ ˜„ %J ;@†p@‚ý x„oþúWþŸ_üÍóúã¯wÃf‡2alÓ7•# L�hZRdzÚD„g˰9fídRId‹äa›ÚQ«ÇlKŽ¥-•H¢ [,zs&!Jô¤&ÑŒ¦ Ni%ûÜaœ1—Ò•¨�íú�Pçþò¥Ÿødù4ÐÐéÀ•“å[αþ.ÛÚºE�nû‹èÞò ×!�“¹ÇåýîÁw.cfXŽûãàˆaQYm—]YYYYYYYYYYù¸³ê+++++<Z&GÀ\µ¤ò¥ÏhÖEûxÁtíR—üuñÃ%ˆj4µ6b°Ò’¨�™Ìpí†á%8äy’:Ú G±”Þ›ÈKôaLxh`S’\˜q­Dw29�D5ÌŽÉ[2ÛœGdˆ¥yÜ2Éë%ƃZV8‰°JJJEÏÞÓ<[7wáÊT6 l‰|x¿ekÜ7Tr Ü‘dÛåLp‰ ]€–öwf:– åå+KÖK›•i{D›zÖ{Á‡‡Gt‡JÔZ‹Ìz €ôm»|G‰y,&DÙ×ìˆ�R­]? ei»ÝÖî*qí\â ›mw�zïÁ‹“íi�.½ƒ"JÅ0©L{ánÅLèfœŠš-xÙÒHÒž¸AÙAø\¶Ž½û|OšqÖáx|ßeGxEldsZ¨¨-\Íw.ƒh3[/�H¹²²²²²²²²²òb²ê+++++7BDt]!•¬@²—†Èí\9UÔŠ s–"³Lh óúuÉX ÜÛn:M“ ÛÎ (qþ¸7ÀÇêµxBe˜·&€Ó÷nÎÌ6ºa¥ ëå>™·_äø=ÏPç @KÉ-L&ËLX§~|ø�û÷ååîöÄ®½²&ã„=y™uW§šVþSÞ»}¼púödû;ó¸éú‡ýIï[7ÌãS´ï'±9õóyØïÜ‚}âdóiÞö×ôµ_û½o|ùÍœ·{ßÖ®¤)µï4²[yÇÒMHâ}—ÁýÝG¯O'ãæ„˜‚�~ïáןïЦÜ2Ë�SÑι1q+˜c$ê;]û///•,¥”RjMIŸøÄ'^þƒÛOÿÑxQtÕP Ü2a [¬‡–Ñ�,-á!—*µß\)Y<©•Sy˜ðÔ�œñÒc@ ïðKz¿%® WÜ[>>Î]¿žÇ¯ã¨B>$‘àh;“©ÖiW1'Pû²JÝn¦fi .�)ØÄSh(á�Íæú˜u‰Þ;+¨@ö»çàã)î¿ù³^)Ý£ —=æÒaŠl¶›’6Tó�j9– –.Ü €™¥r3°Å~*ÖÉä¥Û(H Gµdh^¤ T ,�ÇzÈô¦7ä[1Þy.zûö¯ËæºÖ2šn "a�½õÝʃ ]9ZhÑ*u¬¬¬¬¬¬¬¬¬¬|¬YuŽ•••••ž$Èšæé„Â,{rS£Ÿ'>xŒÝŒÝ%ê }Ñ“rá5°¯xpßÇË^3c$~ÿ+xt‰Í-ð�{•‹¢M[¤ÁæCñëÝYŠ—f(›­Ý{ÅNzwÇyãèaõ!cB"]&Ú¥À’€yÑáø]àÿöÿÓÿü•/ŸÝè3¯xb*[;«Vw§—“MEìú[—ýwÇ>û”ŠóËÿËWÿÛöá#{¼Ÿv’tr²¹þ{–f绹ЦGŸ=Ùü©W?û?ýØŸþ£›í·ÞœNò^W7ŠS†)gV?µy3Ü~ýÒ*¶H¼ïRæÓd�oNOpj¨qç’ÝùÅ4‘ò[H 6Ät ·$FÃ|Eçhã)|yø�h¥çà4×Ì̧ÛÊ|Ñn™ *Pa:T Å`~0q!X ½I­ö­‹z¶ ¬@€ïÃGØó U–@,IRbv¥ž"ˆò4‘ Ë´H‚Þ~àä!‡Ë–ÁáÃã¯ÌãƒÊ±€/X2ÓªLU‰mŸ8¹Dwý7|œk-Û³„…`™ªq0ábI@˜ IôIÑ'»€œNx`¸z¢O¼b>pÝöìMÃk@·é´éìð�CE—0›�JÀ禽¡ÕP�É0;úYìïD¼Êm‚0²žp6Ê1~Íœ¡Xf&tœ™8ãÊÁõ®ïÄ•cX:läk¾_:¨‡ ¡vxVªí£‰æLGP¶Ì ­¬¬¬¬¬¬¬¬¬¬|¬yÑÚWVVVV>2]á³ ÒLƒÓXw¸8ÿÕÿ÷¿;¹ËÅÞç� æ"1-Í®í[„÷§›ØŸ<|}[`Œùâü»ÿí×wþ»91™²1|®–žåd<9{ˆõ�¯Vkš�t)3C)ýÃíö³ñ/Å0 à ižçg½=á :H5K•ÖŸn/2'Ø#à?~ã›ÿæw~ów§‹}+ïÞ�íºWyf—ÈÒÉgp‚Ä:—‹y†Û“73áÝæöw¶¥ïÌ—ºöNÂãnwûö­Ýƒoî=Ò7_ûá[o|öögß|0þ!¹SÙ[–¨Q/çÈý4x7ÜK3\iµÿKçº+¾­3Æ rge4ÌÅ·èÈ>Íi LpÃlí.h)U­1|´œçˆ$Ù—ÀþáüúùïÿØÿøCÏzøðhÑ/–VÒ< Õ ¼“u=ÒÝbéêÐêÕ×tú~—œ… °‹p¨†` Z2™àŠr,˜óºù.8ä�_ñ1³+òFVã(@-·œöä_ð�fO´ {D†EXi5pzûöc ßÀøŸ¿öÚ—_{ðúnw�ZY Ž2\Õ0Jv�—(IÍEe0c‹1ö–ègÞ}¿9ù5»øÊå9Î6ØÏ¿3=ú§¿ò_îr.9eIS¤‡až†ežIôµ¸²h+T‚ÝÄm¥mnw¬�oqúdâ'6¯ü™W´ß`ìØW8\-¬èÀ:ZÌUÐ ©e£áÉ4‡Þ9#sÈ=iîg×óÁ•ö¶H[µO¥ã Í!,fàXYYYYYYYYYy�XuŽ•••••ôTaeΚ XìÏãÁåòñv7ŸLÓéÌ”æˆ@8|qT¿Fݳš=ªµPgƒ£S¡îMy¾¿È˜;1dÚ>}N6�Cž6y {�#BMçZGšM³òüÍ7qv{†6ÀÑ&9žÉ0‹*ÈìIBἄöÀ}à·/|»È~ðm89”¸v¾³l7wä¹sû¢ô|òívû¨!”‚Ý#›OŒ�°©“ÏIñúeÄ‚(QÏ2n‰÷óå%ËKØ ÷¿y>¦ÛöΦ¿}'oqÏŒ½=ªvÝ­¼º÷ N±ïºÝ„¢®¿U#�Å19w— ³àŽñP =è* Õ'COø<‡YÝn·�wîx Wµ�<‡jÛÙKºÏsÁd‹dT¢8k1ßzbædW¶ç¹ X€ƒ™UGµæÂdÕ–²¹�a\ìÚè…ÞaJv üí#>O.·ÍjvI*°,Ñœ� (‘I[† PÓ§jªÞ]L6·âìßýÞWÿÝùη&|k»{w¦–í-ó„à f˜Ã.(x‘£•°,™á1)ÏÇó�솳KFŽßüÄŸý4xÛ^dþúÃû¼|T¼Î%÷Y»í)Uúj.&P]£CDìRE#˜�'ú™SÐÎßx°át/]î¿{û³÷ÎþÀ§»ÍùЕ©³u2�7‚ÏHÇ`�š‹žœ]�·½ï}@?‰¸¿–°yØíä¶mh¨{âöDhI|?»ÁÊÊÊÊÊÊÊÊÊÊÊG�UçXyÁ9V1–.iÊšå=€ä±õ0ù®Íˆ+++߃Ò� „N©NSžŸçãû>ÖíŒÎ|º©`²æ@¹®k¨/±˜rçÝYÖ$öfAgqeHÙ,KH·€¤@$”àÁ׿ÕA™t8d–®Ru:W�)¸ëMóÃǾŸìŒ‚CE0�t(*phÜVl)§.g R–Ld²¤FšqüòoMdO ‚ê!.V0WH¸�‹KU«!¶¾f$€ÝîÒNo�»R·~¶òøÛ¯�l^ÞÎ1D–L"Å«ùÀKÐBÓK É,+L—þ¸tq»s\̺|Ô�87ެ>äxþèå¤ßŽ5j¤ v}�£Z<˜çÂûè6·;K•Áfh¯¡?«[t·Î>ýÃxå‡8lï–ù.Ä5’9ŽË0l p LÀÆ&ôL yjº÷–u:ø/=ù¸Õ¯GØ-à_ù-|í·¿sÿþù¦ ±¯vò1À %a¹Ìm˜–-–(WvÒ›œãhƒÑŽD�D“Vª!¨ôC$†0Lص_ÿɯŽwù4ßùW‡]Æ$�VVˈÌðäÍ=��î1üæý‹_ß×é¥OìècjÛÂò ±�2$%O$9›’4g¶ÝTÍ;+Åûý<]Nçãeb{‚ýcdr³9Ÿ†Í&;^ÖQæz,ç êšbƒK‡!1#8%<îÜ™;<œûóÝkwwûצúrrÁ‚ –% …º@m›ÂñD�ÈwU8Þw—»¾ÈÑÌ®ŽoÄ!Áü­ïš-'[ ¬O—Hÿ\r8Ùa#T°·$—,¿~;±  LÌk,1{ K5Á›ñ) HC$3ÌfóцÊ-šKyü�ÖÙ¸•••••�«Î±ò"cOš=Y“ Àƒ•4Š•–i Ðef«ÁóÊÊõ0¨L5gŒCÂË0ù­ÓO¾¶ÿÚ�¢áüñ¶l¿ùàÁðG?÷;�ÚvˆÝùÝôþÚX•4h¿½w_K?Ø <äô@Š`�wͰaK­t+xÂHîæÝÜåOæ³¾ðŸ^¹sËlêc¯i|åôNŽ9×췷ƨ©PVg&Á„’è o¥J¶Às"- ˆ–Pš§œL±ù×Ï&XŒm³¶'@9´AvPÅRÕ:¸á¨O �e"YxšVSö´.cƒî`×Gæ Þêî¾zqþøŸþòÙýýv¿ïXÑñ’@¯ÎÓL–´j ¦gRá¨.x‚*‚-,�íM˜Yj‹×Ö9v¥»¸súþ¥©“nFýî¼»@Ý 'sb–™OÓ›Ÿþƒ/�üa`û¤ªìßÇ~w\#bà•dé·:�Ÿá²Ç¢gÌè ¿^z�”ô{¾P*7%fXu*uªºšµ¸])W í¸;;ÜÜÒ_f)Žb&á2* ÆNcŸ(A¤nMø ƒ]óõ¯ì ïÄÞñA“{¼ ÀÅóªÈ¥è¿ÌÆÖ³×øèež�=˜Î°½o'¯Ý³]_P¸½Ì8Û~÷;ß:=;»È@_.b’âT^0 éb %¡GûÂŽÊÙ ·lލçPq»Â´¡“R³¶è2Зð ”D'È2¬&AõÜh×å¥Ëf¯Íýy?øí—Ê{8—j'·Gܾ´!@&)OKíø8Uß#|üáðüBÀvà;g0€nÙ%ÊL €l¥ù�&b†e– ŠÁL­X™Dp™_iŽ^M² ›ü–È÷_ZmKÜIôQ.zŒŽ¹ŒµK¢D–jp ¨v‰ ÂR@ZÆâÒ&`µÃ6†ÈÅg «Ô±òñ€2OQ�ê•Hº€Áæ*¸Í†ÈzwÓ_¾þú§NÏpù`zý«±{\G˜:“Sèܽ+9ïÀ „1sÑHŒ"KرCæ(ç^<¾»KÇã:ºçÙtŽÿåß—O¼¬Z¯xyûDwbt`ö¦�½|·ûÃ?1Oš†[á‘›:¹2³#™¬«Ô±²²²²òQaÕ9V^pÞý©—­–G–HÃÒ�½Þâ­¬\™X h…cfq9$ˆÛζ=±>}çæýòfƒÛ'¸¼DÞ|R,s©�âwÄ(\’8ûæ}L;dõMqÌEsȯ><ŠHÊQ‰ è-�@�TÑ„L0 ¡5À沕`g˜�‡+åà ƕ`ÞV{·åµ sM•EµTt‚æY†¨?r÷îŸ>}os›öÒçHÀ6Oº�1Ùz½Ÿüìáð[À'\8/\sálðD0Y"‰H‡:d϶¡ì+о+ËhÂè¤FAA9ˆ©‹ ŠÉ,¿Íå£Ëñb'JL¸&ˆ&3“€';ýSõâË'&EÌC�Z,Q]Õ&„�è’€åÓ½þûð.æK»2 Oëi`õ0€fT¡\Ä|ó¿¤ÙÇyß÷[z¢#}d!cë3Çét3ù·?ý?þU€‰b¨T¶ú}9@®¬¬¬¬¬<3V�cå…Æ´<„ ‡Gv"…j²ZkXS0Ӳݮ¬¬\ æ¡ÉT`‚„–Jñå¸çîr¨^ïlûW^Á�»0à¥{W;«?xŽ"ŠHd›Kè¦8É2ãòâq)›ÇûG¹°)½MÆQ$²€íßW°B:¸ Ôƒ¡]:îp*((›¡‹ ’QÖ¼ *ü’ö¡-­§%­Òz,úÇ•šl)Û©‘à¡[V­aöJñ1›bÊØ]°N€°�Å¡çœWfúÿ¼¹3\n}ßK’Ža'7öóVVž'‚š €Z=€Úi>�çóÌ»‘ÿÛ?üÓÿûÿÌ'€˜€OfCnôøp@‡“b;5ÏÀ›À~ûË_ùýØo‡’šGîÇ®�.1'™8f-Ó*�+ŠÏ“•¾ÑÒØ‹Uw£–Á€P &"@ÐÞän JÐ)t©§¹eÍ.º>ܳCД{fÇì…"xe©–&Î¥-V¦Y "@yµ&‹Å·ªùù| ¤¦••k!I’™ Ã0_>þÆï~åôát·è©9°Sf­¹Ù õ8m–(À“›ºöå㨑.jG*"”9+ïÛ°–Œ§÷]&ÁÞ÷)¢÷Þk!s·o<è}žšéV@dJ«oóÊÊÊÊÊG†UçXyq¡à­#�ZsxÏVKd¢5°`ŠY™ºX,YWVV®AÄøƒ˜-˜·†Ò÷UšR}é`�õ}åM_å0à`0D t(@é.ÜeÝÜom»•8bIjMËï À3^a¨ .ðvèu%e€˜<&p˜‰Tyë™$¯6п£õØÿKp¢ ´æ¨þÎï98)ƒ‚¥z`4/æ f‡âÍó$A. ¦C°À�=ǶןçyŒ¨½?ÃD÷••gB°T`6ÌCN¡r{Žüæ7^ýñÏ|8 Ô]·x^Û/n6ÝwéC‰t\ü$p6�›~Þ€óta&v5ž`‹C"ÚÜð®)ßW“€®·ôôË "»� ,~q À¥Ã[@Ò’%à‰bTýÚCÈ®RÒJf$*L7YkîN+A« ]d‚ÕÚ5èø#à<Î6à8½J+sæyÎâV)37}oîç÷ÿ€ooÕ9Â'¹ºÞ†-¬„êÅå#�T9D¾™à¢uäàª^¸Ì‹ì#¢Öˆ0ÁÝû2Xévs͸îýsÔûd:ÕñüâÒmš ..ï{ d6I»5e¾`ºòÊÊÊÊÊG�UçXy‘Y|¥N9Ku²9Îp0£Ï`VÏV.\YY¹ë!.›‡¦aTúÁj w”,0 s°¿¹§© JŸÀ’˜ÊCÎx�! ÷Ae“ý NiæHr:’Z�µ<Ÿü­½m¹ Œ0¡�©Y‚8P R4á ‘4³òq‚¼…Ü"7Èy 9#(€<Œ�´ 醠]‚#R4Á²9ÑÛ•UY$�ï¶@x gôD‡L?Xô>ÕAÔA„ D ƒê�„òðÇtG€À²i¨ê–dV‡eƒjÿ¤‚3ä ÀŒv&ZrM–ÕËC±‡ *òÐÖÛ¾§úíŽêˆºÞ»v™7 /0ö–‰4óÅZ†pÇ¡ÌÙ6ÐñÓøO»Û id’’"B‚™­�Ï+/&`Ièa“c¶¼D>îâQ›°èê4عïϰݠÜÜ=º˜asÅè8j¢VØ®©¢†Y™YKéœ%öØ–žã’î~¥µW‡L%=ùúÃp3$Ü€`‰ÅœP®4Õ>¢¨–å�)�,I€SÚuß‹mÌÐlšÂçÙÇp�„öÛH$‚5UK@CToáS°Ö$äÉvi; 2B‡‰“à[}ÌVV>¼—ɧ™Õ:›äîœgE¶ ÜrïÎåÃûµçöî)>q}‡¨è·o‚JäaÞ× ö:Çñ x¥!מ‰Sârwl:ô› öýæÎÙí‹P *™aI!˜`®÷i+++++!V�cå…FÌ$’4?„¼9ª˜EóP3Ö;O j•9VVž¶aü·¸š\ŽÓŽò1.0¼LƒYf؇u9â±­ùm�µbšµÛãò2µË"Ë r€u€æZnB TÏ”À\’Æ™I3•&)0½u³R€8t ÖÁKÚ!²uÉ¢uyCE¤Úi‡ �4ÏèÐ Ij¬¤·~eå™!.@°£ç\¤ÍqÅø)i=WOQ8 ‹cv4°H´H'­ÔZ«PºA´qB?l1®£Ø•óÅ£ê�?d-m@47 šÐZs²¨1ŸÔYÑâ1€v0ÀêS̼ä„yßk1ÂF†æq`@ T(`8­k µ@¶ü–AXsiK69mÉÀ­ ®O�+®Vþ�χ’æqò©wÐÍ,÷H~1Ïœ:ôEÖ‡y—(�£¯)[|ÒáŽñøS€šÕÜ o~ħ:ÙJ0 “¡ïg’™™9M-d®�¦%@Å2‰ü¢�Э¬¬¬¬|„Yï8W^`˜i´Ù!À«S¹LvX½Õ•ßø—ÿú³å¬Œù âä�üÈö~ft�Õ¼jeåzè­�½GÇ“®ëbÜ­ôÐ@„yî7i¼¾Ë_i‘[¢ÈYQ€æÅÖí‚Vkwy‰Í½SÄ4W t7%¤EêhIÁiÙ¦ü% ²˜ˆæÖ%Ô¾·Ç»GÞYæÎ 6›Í4V%¢ªëOÎN|éÎK��'Û³iž "$µ°_RH™™®!ˆ È̼} 1‚xWä¥D¦ª=™ÐH3vË“ó¢p`®n“›¡í µÖn³©Éív›¹úV­¼(ö•] OôÐŒT m³œ[àÏ(Ä=žêØœ{3 ¿ú9`DÙ l½gzß•y·¼¯~ÚŸOó¶v‡H\@-Õ‡#$\‘qI�b �Œd0ÂÛ”`)ÅÝk­î^ëÇS5‘ÞO‘UÜžl§‹sÏùÞÙvúÎxü�bªÈ@MtÊãh�éÚ³5¦ÀîQ¿;ïºÏÏ{ñ¬ð«_Ä«¯`´f®˜ÖÌr*2�¹$Wé�õ€E»c(§˜úM1 ÛÍðê§f“Ÿ�Ìó:?ï··AUªBÁ È@Ñi­WVVVV>2¬:ÇÊ �¨6ÒÑÕLXÜû#´ß�ßþÎE¼±Ù1Ýø>ÝÍY‰ðg½Ò++Z©ÎÞÒÕ»ô~d:؉Ç'º¼©Ô]‚�àöÖõTÂ*,¬²*àôÖ퓳»rKKa db ¨÷ž:>„™°*.ÑFO@ asÙìËÐ×2É&a†yé7 Ô�ll.a˜bòe"uì0!! 21™L™–é&¢Â²NužNJé+ €:ç~š³oÙèKêpsiNW<èKZÉAÞ¸9ÍáF›ÓWVžsD –ô„ .8à&xfI/À &k­³K Ùڼ׿\f1ò0ÚÂmpö@< ÔæTç(ẗInæÅº®ûþÞ ç«f!TaFšc °»8ÿæ7¾þ+ÿßÍùãÓžQCèûì‡}�bþ4…ÉPÝ1ßžjÇdbüîëo>x0•NÙCÁ’i¨Eá™hùäò$ Á¸Üïè È ý¦³ï;½òÉWÿ‡?7G\¶%­:÷ÊGš·¹Wµy½8ŒË.³W‚ }ÀÂÚqà:z&·sýÕCA áW>Å»~ü–Ÿýä/¯±´¤{æÅ26Û}8Laí$¾LªXëãïÊÊÊÊÊG…UçXyÁIÑ’Ëýe&ƒ‰bâå¹íÌ/Ðo¶}�NÜ?ëÕ]Yùˆ!>©Éøö¢Æòw¹Äwd+¼ó.>Àe„ Í$I…Í\# ()‘bÉÑs.9–˜J½|ô`3ïöu_Ë,ƒ¼Â –BŸIk ÛP2ÓªZ‰úÌ !še8‡ï¬O–aŽc<çÝð%[ûp§ì ˜‘àÁXòlöz@Ð2E!ùè!ÉC<œk¤%¥CW´Žv °tŽ ��™L|\‡Ô¬ÍSsDubëE�î?øÚ×6ûÝ�ZOêlʤͪ³|Û•2ª\{c$Qanݦï: grÎy +?DeR,­z» Hšˆ`!˜ˆ¸u'3§ygÔüø9eÔç{þ©}œ’$W‘cåãÁ;íù¬MÝ6ßV…’`ÂÕz}š(A²)‡Û¯+YiOÒ×®ÍõÇqƒ¨0 ½Y±.Ý~h½Ga™D¬é"W •••••�«Î±ò"“WÇ‚);¶ÖˆIË­óvá¶x1v0P«ßôÊÊÓpð![,Odvè;ÊÍêÝ�ZáÝ„×û“º93°ëɳ{óäßDw*ïè[;ÝqزXÄþÊnK,o¿„iÊ´È2‘‘–�mÆùá ÃÝ´Y ·n ð¸�³bSsÑ×Õüu=ùúñ±úF”¦µ µòBÓn0[æÛ hç;Q�€/çK°ÃQqCçCVžÜÏF¾ôÖòÚ¿1BL±³+Å8Òè¤Åj¤Á dd7²¼²a!)3ñ±Ö9é¥dPY‘µ˜qž§·Á(!)弜ÆGu껓ÛQxmÛ°0p8©šÖ‰™Ì03yGïj´Ë2)èŠ ùáÚ�P³)‰d@¸xýMƒŠâÎéÆwû³í°Î;MSD˜Ÿø$®¾…+[Ž"Gc‘x¼/¶åÀZþºý€¨ž¶@ÃÃ�¸Wæk ËŠž„5± VÛÈIš½ÅFkeeeeeåygÕ9V^h\OR8Ÿdò3«˜`˜‰(3ª�׿‰\Yyá1Áry¤3S{j ;tþò­éµÞ.H7wŒÑFÀ`yx`,—Q|â©ê° ÜÚ½ñ•/ï.¼±ÿÆ£é ÙÜ÷=+(g.PY-\ÎØ0X)€î½ë÷û.Ëk÷Ï¿ˆ9GòþÃé¿üæ×ªqˆj}wR+ÌÌ ‘#K6¸0¨$ sDX­>9D–(Ï:¼ô?jeøqÚ˜ªæÅSL[ª—­…ptŒ‡2+òÉóµÁ²ö�/×sçÊ‹ ‘%™®4äâ!GN®±àØ…°�6bu£^oÊ¢ûè€f`f,ý¼FRéJLrw¦ø“ò:×¾ ËüÆÕµ�ñ/€7±Dä2ÓjåfæîîOo"‘µ#iRVγwR�a–ÒǪ²Ù”—_2hŒªáäþã±»¶Î!b_Ãʦœm:—IˆŒ9"͆­°Hb®J¤!¨4$€` ¢Ò“Œ@Ù 'ÆRçÍvûÚ÷O=(刔Ԇ9°šV­|Äy¯{UÐ2 ,¾U"f“#<Ý!oþ@ÂùDä˜/ä‡ñ^ ÃÛŽŸë ˺aé÷éEÈ6Yrpß"ài%�4ÂÀ§ú ++++++Ï’UçXyqiõÖö Ÿ²f¸ŸDÖyÔ˜s?Î6L6C‘ %×ZÝÊÊÓqH(…¬’ÏbûAªÅƒß�gÕbå8ZÛaÒ� )¤»ÌÓ’nÈ9Þœv_ýÏ¿ñÿº?}ã;¿{™÷QæÓ³mŽa‹Îa@Š«¹Ì{9rcrp>dŽTä\úÓýnn�ç7» ¦Zéßzý¿<¼ü½˜8Wu~ZFÓ-Å Re‚ÿÿÙû×I²-;[kïsÌÌÝ#"3ëuoßî¾ý¤º›$¨æ 9àŒÍPà@À@¤�>Hú® ¿!ú ohAC‰ÄpDqDršd÷ô»›·û>뙯˜�³÷Ö‡cîY™÷VfuyUf•-$NeEF„›››;g¯½ÖbH { î2U5 ï ©æ(›{«_ÚÞL¿þ÷~‘RÝ&‘�švªIÈl}’r°u`ËÉöþLŸÁ‚ßdH@#.á—¨„ƒz4?ôc”α4-©I/š?Þ>ŠW Â�ì¯;Âásþ9 a`ª k³©"2Ï› tyhu½g˜L^Á0þUGUÀ€]×ålbН³>À%ªº¸„±`×uÚõ½ Ú_ ¿ðsøíÿáæêâçðÙ/�yBì'‘u à†*p¢[7w°9�jfÇê‘!H (?NóS�9ž<Âv¿º¹q³ØÞ&˳aÕ3$G3°úªÏ킟?»-‡ÏΊA€î27Ì�úKôä[Ÿ#íŽjã[Ïןòwiä¥Wdoš�öbâP@ÂŽãâ\êH&â¤ÉÛ�,X°`Á‚/ ϱà ��ÛýYH´djÕˆp51²Ô¶ô²,Xð `KçŽS¨n+mÙŽ» Ë-1[x -ÿ‚G`P@ÁY,1çoà‚¤°Ôí«HHçÕò®ð£ü{7x�Øß˜ŒS¨Ó *;ƒpFÀ½‰À@`Í žb%ͧ�÷'[‰Eî°¾jê»\ÇíÞ>$òîv#¹«vµá¨w6�…H¨S\:#B¦"Þ\ó�ý~›¬”ßûƒôëïÂÇSU¯{ÉGƒ™‚�&Zá,£ €ó6»éIü!<˸`Á7 °yž›Â$¢¹ '÷lÞ·r@ 騨 ¦àWéŠQ6×ÚfÏ„” × 9Gü@à$ÝbkìÀŠ!_ XI’éÏ©ONÑ@çH!@PÆÈ‰˜Pk�}«³—–0¼Q Ð P0ïrÇfÈ“íÎDü…~ƒïþ2†« LñÒkÖ°)ˆ á�%€põÖëqŽž:Æ9QŽº€;<`�‹Ÿ|@^}îlµ M'ÓªÆs�‘¯ëG¶à›Þ‘q<ÿOŽ˜eÎpˆ! $¿k¢ìIaÇÔ´OiÓžÿͧUÕ±k§ý–— Ç×ud‡:LJ´|�CB’CLZ¤ˆ-«¸ ,Xð†`á9|“!Æ@ŽÓæîÂ:šW&°K‚–ÂÝ8VIiYç-Xð2˜«^!¢Í�‰ñ82³s‹8æ|ŽYCàT‡ò¶˜§ÄíÏq{ÄÍ_KÄÉ¢µÖëÃOìâ“n½×•ìoR=HÏ ¶šŽx´8sˆDu`f;ãömAfY(Q¢ŒÄþºÃ�U6QFÕ¡#DR–ž)©Ò|TÀ¥Ù±„€ÒÚ°.p�,²$9P÷þÊôÁþ£„Ô¤Yâ§Û·üÔ9,@Þ~Ã>¶}x0ZV�„´– J�“ï?íhýpN)H£¥dÎYäØh)œ¯M�¯UW†à›ÕvÌ Ta(Ü{¸E%òm¹y.‚ž 0‚³>[霆h©Ì�:Mâ„Ë8 .#ÛŸêç»~H\ óTÀ øÉü�pŒ‚IàŒvtÎhŽUÞ.- h»z�4 *æHØó€y,¢¥¸m-VžÒ;Ž×:Ç;·ïµʸ·§ƒnÂÓã4JŒ ‘P‚-È"‘yÆû×÷u9lV†ý‡6mmHÆ^˜frÝ)1ÏÀV†ƒo¶®LU§©X1v½æÕ`af÷/.³ùÞʘ¤ï:ôùú`Þé¦xô+| ½é  Š:²ÂÁ&÷ëûYl€ð€¡h:$9NÖ$Á9�šÖcÕmË´rä$²Ê¢PŠ€¼3‘ÞÍêøJÀçfõÖí8eEûñQ�——&P4Efƒ\?–¡½ÙÂI´ìç¹»_^å—?ð­9¿íÝj] §gÜËöûK¤dÈ5 ÌXLjŒÄHê´€ÚócâÚI öüYmÌÜ�÷Háw¾ˆãzò´¸mcÜù†Ù �ó ß¾œýVFW?fÓ�Äq» {þjxþV‘çÿé¥Ùâùgi�J˜„K¢CdD'®!‚ÐYL«ŒŒWPð²Õ¶¨)@Œ�ƼFvv+qʧ߮ßy‹§‹êî�—zÌw,#1ÚsÙb^:ÊIríŸJu:Ë%áǽË'Éñ‰^1ou´A¼—à|ÛÆ|ýœd48Š�Nš9f/�DÃÉjE™�­gc§<§9l26q¤¬^ê3;ØŽI¥á2º“bâ1ëÓ[Ž©ó _ ß$äôv8'‹òOÍNéåדFBkmâ­HNG$´óLDB€îÌë¦æQÜ@G›xçâSÝboêäùz"ž�œþ©»Í~ĬŠ~Å;Àƒ¬ ;㸺�ƒ­�q,�/ÌÙßâ™ßðY/ñf¯oÏ„…çXðÍ…Q=èÉÝX¦ÚW$ëˆõP§¡ˆÔz Lê«Ðuô»8sgÁ‚¯‚‚ˆäH7ñ 7­DÍQtȼcLçô¢Ÿ¡óÎá6†û¶úîÎHÉ«º©»xD·Æwt¼pÝûú .ê�ß·o­þ¦=Yu¼"`º5-A! –AwO+å»ÈÀôDúÈ8ØJîû„‹è±‰Úª ÄmÏÛVWŸZÓ€ÌY;THýNVß{Z>Þçk \¼óV öõò2×G»í½Á Âæµrëü}ÑgÔö9¼ã±p¾Í'ÄÉ`TÁýN·‡½®b$.3Ü&m¾ÔnxÕÅä+@àíRH!fpÃPB£pp  &ÐÑk’ÓÁ¿iYêÌý4Nc']—n(EµoÃ\œ ‡;`Ç[)Ÿq©Ý¬�Š!Ћ[eê8дO—)=µîº$° l¨5!Ÿñ섃Bá«94‚Ù6Y0H‚Q¸Kœ¢�çªÏM½ ŠSN¯NVP9gÖÄ1£ˆG)ƬƒFVJ+žP ŒÓ�"]öoýÎ?½qqŸ™KálþŸ„ œ0 Éôœ<‡„K/”=]ßÉߞ¦8„”ª(Š"¥ÐATAØ ¶Žo ƒ©¿¸·Ǥ¡Žn³æTónŸá¥cUë³q¹¾¨3�åÇ€ùÏ�ÙZRAZcÀ©Æ(Ïœ¸SÞ’žf÷4¤¢9!*6k|üÑÛýúò铼òLJ'QŠx$¡¤”̬º�˜§bÓí»>çz;èóõÒZ Z±Ïغía€Â}v–#ãUê\‚ƒF¿¨È¸kX Ó˜º(š‰™�áâ¯xqÖRÖý�B¦i CΉŠÅh@BâPc ‚1Ý©ž|Ƙ,u7xÀ·÷¶CWÒ“—¡ä0æ BpsÔ ÎPz'q·Nwd\HR«‹U÷ H¢(Œñ™*Þ›†ÖôÖÆßÃÃï}üàòíëýöPkîWã8®º•O 6}$=è­2Ìeniþfmf‡ˆçÝuéÊF ðôÁïþ“‘ƒ³÷p¶‡ûËŒ&fZ7ëËíÇcŸºR÷ßIzõô×ÿÞ·®í‰I5J{¬3 yéŠ qÑhqh.€Ã½U¢Å�Þh9"‘œ/»"K�)Û!['4fDãöÄÄ @[õEFTqsV@Zþ"ŽÌzÐ?}Š)­«¹¬/y9_ âdÝÇvsEðH9ÀeÎmIuÎ@À›(ûeAs1—âQ‚m‘ rN0569¬�”yI9n[sî°¼/l͘¿ü¦®oχ…çXðÍEc·‡Š€IDAT°W½µ[V�€,®`‚§ì `âF¨K2žµê°`Á× !L­„çCÍ“Û9ûÑ·íñÙ;;÷¹ÂÝ6T‚¹´áOâ­ ï QûN/ºµ^ËÄ;ßzçö÷þW¿yÿ?Yáà�›‚¶¡bF�ˆ;·g}ñN-€JEí1$ ÀfÂ�~ÿGÿ×úûÿÅOÆOjª.põ¤ž#›Û-�ø)çö6<øü n[‚µR¯„HÌ­xV*=œÞºË²v³WuÛÿŸÉ÷æ–ïRÞZ28¡]š—š]‚²"Æ”‡Ízõ�"¹%€±f‡‘É&žC0¬`ÿåé&k®â;×Ôveš&¨å�\&Û”R¶¶½§«3ž 0Ý­;S ÅÆtÜaÓÐ{—òf}ù{Àg ö¶oŠÙíçnðÝ,Ϲo9šÕ5È1’ühØNo{ÜcÁPµ$Èmfiõ;�‹/µÝEUZAéÔ¹|¦ã7dꨚÚC$Bª œ”cƒ-$t }“õ¸Mý–fçÒ8!„áÉ=¡jRO¬EÛ™7 ËKrиýßO_uÏ�6¹u>$dö=;^Æq íP$G¶ªá Õgß»Ø?…`“wÞvDŸó2+/'gžS¯sëˆù¶xéëÇ)FUC5Ô\� HŒF Ä„­zØJl¯Äëh–â"Be$1Ö Qƒá ¢ mÈY±Ó¸¬x‰Š$¨Õ‹ïGÛÕq7â½a�SºwÀÖÄL ·óƒ´®T¹-ÀÁ9«LÆi$ÌHš¨ÔND�¨e|ƒoÇ#C¬ú\· Âã–œ˜m ç;Ê�çdŽÌ‰[ÍXK¯‚ø«,4d¦²>k<ÞˆväÜ[KŒ‰®Ö=Sì¹3îIDtâ!1+»>kdHµšJUW‘Î+ECR'ªHЉ°P£÷d‚0æ»Ñ¥ý¶5bÓǬŎ@4™í˜ÈŽ9#§6�!ðSQðî�|Nxð$ù wq†A*„BF„•zØ—'ïçGa»ç~ÃÃ4„JÉ2M IíàóS5Ú%äA7™OŽÊ­;ct:ÂÝ ¡…Œœ' Åî0½üÑ›°p¬ÃdO:j®ÅßLSÿðâ~¾úõžQÚÅ,Î;²Ô7»¨ÚpäH3{öοp=Þ¹íÌG€/}¡˜$jr¤�L$‡FÕ°€1„!M:ã„ :å¶®M�Fõ=£ajÍÿ47Ñ%,ç‹Äiš¸Û©xTY‰³Q¤óÃNŽÛ›ýåòAu¶[�»|sÜògõO´D½Ûúx³ïÇ3aá9,X°`Á‚çáîU$’ VÜ<íI™˜qt€ÌÐ9$AäÀàгåx�н¢tÄÐá­ñ ?úÁÇònBk<ù§óNNìë 2À€ÓýH)m÷¯á“úÔ“Gˆ G…·øÛ/|œÝ–Ž–$J‘s*»EÙ•O¦Ãv÷[çÕW}þ¾¹¹JoUÇ41_Êä(¨ ˜–œ{ñÙÜO(ÁˆYÝÎȧÇên$,�Z�îH}~…R¸ø~ÚªõÃ}:í)µ;Œå^¬ÛKÍÜ9BàÍF÷�.­j8šîíL³kñ鼩7?¡¶ÀpçËRGk›t*—¥lj˜*c°ÂZÖuEèÞ5Ý&†™L ¸ŠÏ4a8àÂÀ32Çfï6_ۯƋ/ø™p ´õjÄlÛvGišæ‹?Ž =W /Ñ[ç�ZRëÍ{ÒÅS»Ø$$B8ûì) ÍB¹™˜1îò"ÇJÀë·¯�±ð ,X°`Á Pípo¦i'=Ö=bºðªðWÉç&¼NÑ zG&í�@n€"@u—T/.Öï½õàçÇ“[kW:è`EØKØ|©à±aª¡íßX ¸Ô¹帢S€Hélû(?r*Xj!í·äG �æÍfv4¢“x£…ú¯:ÀPëöÑÃÝïþÛÇÓ¸«–Wëž²%0«¼]ÃRT�c­¿ø;`’ôÔ˜®6»éÉÛ½v‡]N©DÉ)‰ˆJ¯2Ào| /…6éÜöyÎS47�'»öÖš­ƒÏâz`²‰X�¾êOõóCBÔ²¸46á$ŒhWN½�-ƒ`€!çË´q¸‹¸ Äèq²Ëæ[ܱe÷¥(°àE8yµhÚ†ë\¯Gr¨#þŠW³†+ÍÂHX•É &ÉhF7�Q‚Ç\¡W¬`hŠjÅ$ aQÍ‹ÁSn¢ å1å� ‚ˆ¢‰šÆçg�›Lwå‘GóÑwÕÆb›q·_uÙN†#’uaí\67C�ý~ï²*Ås†BP|)Ù|ÅÒÜeLGx°äUé.v±?ÄÂO¨ÙÇCA²”*å¥õLj%Éû2=Z¿Õ�Hž JpsíúQÕ>š6zÍ Í›cOx˃9–ÿšî¤ù%µYDv©»·(ÅHzûØ�;²1ºø¹š0>ãGD…¢š˜L•dD0q,Ø–§oåûÓôÔÒd�Jïûò˜õÙµ¿õ�àèø‚³­·G„G "}i“%ŽIV·"ùêpsÈLа H×2eÖFÆ:ç]\�$wÌND§RòQ½ê�×aë™PG0 ÓË'¦i}3-T‚á×ðµ-pq“êN/¬³†'€ðùGŽw“ÌÈ™Œ÷EÏñ…‚A¥cæ›� ·™R³kkˆh´Ä­ÿõg�3…æ=½±eÌÁE—�ÁÜBD�$Ç,éxv/<ÏØwÆÅÄìEXxŽ ,X°àyÄåz•Í«;H¨t}º\á°F$²x HsâßKtJ~Þ1=ÝêÅf0‘uì;Þ\ÜËófuƱñíuZϲ~ª ‡ß¦,Šxo¦¿°J ¦ ;SãqÃ1¾õöluDÙa¥xü>¢^¥4¸³Øøex{½FˆŠ A¬“vOVðÎ1Q½‰râh¸}…ƹ˜¾*µó¢ÅÓxÝy�2j³i*HyÝ)t̰êãØWç¼2ÑÉOµ"ÐòXqØB$cèV¥^÷¼¹Ý� ª§\Q�¾8檽®æïkß ¸mFûâ‚ ¹| ÀÙú⥹ |Š‘tB^§ÉpÁëiô˜s³4Ð*_zrä &CrÖÙßçúÙ®(.S•¢{£ûÁ¿ž`åƒTùÑOýÙOnþd[ÐAÖ‡·lÔ2DÑ—]¯žØÃØ•íùK%ïÿáþQÏ?édƒ¨‚GB¦ú <¦`%< ylg¾cíB'p”�Ëî­Ÿ{ç7¿{ÿïÚ«jH‘è9šänTÌWZ$ À[9kÎ$&§­î×_ýë|2­‘;íBh^TB¤=á(A˜8މ÷/f•H!Û+5¶£áUs¥ùÁa‹µ­¾÷[+„7 E ¡„µ5³Â5æ��7—ê`xŠ#s}´�26…ß\elk‰ÖÝa.5^zþt Edcµ MD)s6eR  ª˜JS·Ï‘9”÷D½GTo�Q±9ORŽ=Þç¯6—­vа‰u—7ÂÏš~6¼LŒå—Š–øÊcÁñ±ˆRª”´ÛM?ú3ÿäGÓxØnäršªgºœkÝÖ"g�$GÛA:Ó~;]®î׃O;YõÙ‹hߨ%d{¯—¬®]æa5tîžé6íh}ÈFølA.Rå’ù…�™þv'°*ÐdU(Ð�uܤT€í~Ügl`]Ï«+×bgôŠ*‚= Îû`óÈOS )­6÷šËÙ�ã©ç]äú&—€g� ¼åî="\b®)C±ÀÙlÌàDM#Ôà‰|—§lÀà³mºy‰ Þ,œ®œV6b`~,ÌÅ9zj“!Ò2^"×€¢dºÄ(<ÊX4 ) i ŠÀ£FrôxéßO¸�‡¤pINtYNâ7XËЂÂãHç'ŸS®_^Ò” v ÷{`ç(BÄãÕö{pE¿>u¯1ž ´oóDK* "÷0G8Eµi¬‡UŸ»ÍúQyhg{¾/øÙ˜ë¦·"AˆÓœÓ“ï=ü£ßýÑý�~gç?êµ»7}›èörSµ¼ÔÕMî HûítM¢y+ý›ßÿj¼«ì“àš!b]Ũ˜­?å=%ˆæræ!{ÊS‰´²Ÿûî»ÿþöú»oýê pÝAùTMð+îtVU ÜfFc´, ¯8hò·ßí¾ýàÛ–±:Ú¸å;ŸË±™~/DÅm<ž½ _ Ü|ø“~ÿÈ%'‰ž‘ÄWêAk&NMg€WÑ‹¼n Ž!c-ttzÏ^PÚ{4è "/ÏË:èªt£æœÒžžT×Tqh ʼnIÅD�1QÒ"Ž$pÊh9öc‰Sfçª@ðÄ'/óç:Â�A3mpÔ Ï²‰ 5×Ö`-XôÏ�50óúÁÓ–Ó€H�ÇÜ^„€ßΦwyÍ� qw|Æå†…çX°`Á‚ ^€Ýn·:†L•÷..îe G�NÁ§ÜŠÄØìlÎ0f@ÜQ'xŪU²Zm&LÏJ ä®ûõÁ�Cl9{Þ4¹_­»T¦ðíSl{I›4�’Îg5cDÑV:Fã@g€TºEYw‚”°êP€¾AጬIÇ‚Éý‚§CŸ%¦Ñw;•V E A ,1ü\W� b<øä]Nâ@1ÔМƒÐUoÄ¡N£`%¥L�?zø§årì¯Øï‚9Nàè °êãÃ!é&˃¬yW?’ôp¿Ÿ/–â/m{ð:¢Ý­!0…§bR]èÂÕ[ï60qD¢"çÚe˜Œ5m‘‚6…FŠ–ê37Ê=—Ù(, žÁÜ!î's�£óà13”€TI‘›EßËòUbJbá#ÜSXSïû•í¥ú¦Vî½ï»ØgxŽC�€ÎîxŽRº¡³@©èØ­°ÞXÿàÉŸÿñŸÁW•½G’::ÃñòzµÕe<˜½Ý¯è»©?üïøçåFW2ÕñtsñÖÓÃ……Q[»±Ï* úv»¼RßgŠå,ï½ûöƒï"ÿò…uO¿ê‹`�ßê[2�L¯òãOþøÉø—±º&Ó!Ežâ‹}û¾Ïa‚j‘+A\^ HpÇáéÃcÉ"<À)¾vŽ=x˜“Ì#ŸÜ´‚­Á¹?þïSÊ��ë‡ÕC|çç~ëÞú-Á……›™9Tî�·üW©çDÌñé³Ö¼ì‹µéz`´‚eÖAÞZÑ×ò?ÍØî§%‘½ÕÑ~ù%�°Ÿ®¯·¶Ž¾Àû@ZûyÌípÞäµLóÛ$�n„Îp�Ïš ÜfMÏš¿f扗]Ïz/y/}Õž©ßJÕÔõ’ 9�ÚÖ$q‡�ui܆†œxŽ&)pÒ PLÚñ,>E_šÖç6» €Í³ �,‡æH&p©�K )!çÔG Âg'†ÓçB8('$dÎìäq¤;p«@YðžcÁ‚ ,xüÖ{ßÖnØm»\|€×˜ÆZ"4Z ó\Ôã1€�s-þb&¢È=ØŽÝþz·¿q¯Ïl€ž‘ù¿^Tǧhî ¹¹Ù¥tލ ÷É9° Åä³÷Å9œ�¤5èÌeš9] ­û�‹�Ra#J�wõ«>_6˜;˜ÁÉ4US/“…צÝF4Ç`iµÀf4oz¾~$ÉbÖå Ì1í@bÕ³“ÑKaȪ¿¸B7é'ýè¿ù—ÿåÓG‡½”ªçûÔ*dDü²µš+dDJÙcð:¸ûTûן<úÊšÞäØÝ`˜¸¨ÔTk§´7-A¼íÆyTÖÝÄ‘¦{;��™K©r`«Ó[(*q,¼6ë*‹\ÁÛÃ[°Àmš+Ðx÷ckäL{Ïß#5ïµFXE}Î&ýÌ‘á2W©`‚<¹÷æ°è-rx{ÜÄÑÿ £Î_bt—ìÒMŽ©B%{•ÝåÇðp}x;âbäʘÔ@g¡Ž?‹ûgŽ'¬”ëû‘µä:á0öoKŽq}:As6�Å´€8©mQBx7ÃRãa»�º= C�ữúXà€ƒÇÐox@ª—Ýx=úc]—áQdڋ誙+çX§«J’l¤Óî©K ÐóAPæøÝð@Rô‚Á›  S@€Ñäî,@‚¯ ¸‡ÜGãp}˜Vì*D4%Uš�í½�2›ZÍú«*ºÏ/NRD ÒrD®.ßÞ��ƒ-MOÇ9¡.Ñͦüœ­õŽþ�§DâçÆ°Û¿3^ö“jc öm€bôƒAú~Ðt9 ·7{ÓƒIÌ\¯ÄmLׇ $è8Û¬î gxÓR´Ðé¦ökv…êúò«ˆ•Yû±f;fâ„«ûºVEˆD1FuV Ó@2¨ zzÍåtšlZœÖR�LÜžÓ°.ø«À!s$ˆù8Þ}Çtë�s@èyn”{‰±]H&æ°½á2!JPNÏåÖÿצ-Ò€–)$m};[Ŷ£å±EcþèK“pß(,'eÁ‚ ,x®¯÷÷mÝ÷ëOB„$‘Žs�ÅPP¨ $býW}ÕŸò¨!Ü!‚õ*÷ƒ˜�`=þ›÷Hé jöYu}9@3 SRŽ;¨ $˜œ‹ç˜xý¶I Ǫ��¸„’P͇,Ìg“*¼¦1I‘(2]2Weoê�h>3Ëìë2ï¬,çSO»ÈhjÒ[Éa~©kÒàaâû²eDZŽû*»Í;úxü¾eGž¨å\§‡ÇÖKŒèж3wI�ŒÔ1"cÿñÓ�tÞ'؛̔9½pŸúþñîý¿ýwA.7×SEµ–^’9«t?Ò½þ³ê2…щpé´[¾ÿ'Oýh;tW‘0J4"?9yˆ(ßyëÁøäÑ ŠÃÅ‘ZY‹iPÔô ­cVñôÉ}¸¡¦©lz^úˆÃu_×pƒ@ ¾V Q�|¸<£Âi'¹ï°ÛÉÐI­ ÐgL#./ž†Lú Û”œ ¤¡Çqš&͹'NrŽê8ñ­þ*­„>¡îìäæþúÃíu¿Â��.vWxÕøLŽ‘B/x ’f¦‰fõp8t]VÝ4V}-]¾r,<Ç‚ ,Xði0„sÀ% q§1÷‰0d2�«ÿL]þX¼:`+`xFÂÌ™êÀkGu|Jh=—H€ˆhŽÊÅ!Q®ìœ ž1a„�8uï2H@"”RÀ¶¾eÌ1Ë´ú&W©?¦êæRI£F§UE$’j¶f „ÖYV&trÔWë"|…~ÃT5W×*ƒŠ¥qÛ�áV¬¬³ˆºÑ-0¹ÞË#÷WÉÝýœ ƒ7 6ëÞ–œ3N#ÂDj`ÛwøWý�þÕà®.«¸ØtßúUàçð®$ 3Nв  BÎ/]  ÎVaO^Ü||0�Z�eŽKÀpj˜o-u¯×|¸àõ¶ÛíæêÊuЋ‹-°#¯WTª1õ*d4»ýa—ŸV‹§MlVpa)ª?<Ô�×覛)Gz’Öïîuý†qyÈù`{Ùµ@¤^$ÝãROGìŸ`·³í¡Ü×ìÁC ]Á FŸ¦½a_@“W¨Ë~ìÍ¿¥‚b&5€;F2Ë"›Å‡Ì©WsÍ…]?0Gêû›ézï—‘‹öªÞô ñk�êÇ“„�.’h6–2öýÍÿÁwÿóÿø+ÿ½Œô*Ÿ™ & s\@À€r‡«.ÄÔ^Tp1¢Ú!Àe@wÇ5�z|§@&ì+¾?Ž?˜ü/ 8ëìóÂvɵ#¼eÄLw¾òš ù%õÏFqH fF#pLBžÿ=p’u¼Ô8ß~/™'D€&œÂfÞ«ý¿³~?Š Þäû7€¢bF÷*ެ©sçõõõŸïOþû?ÈӔǒ" aU”¨òò×òxwÕ=ùþÞ2¹òáúæƒ?ÜÉß¼7X‰'„TAUkg&áÁÓ Ÿ•q¢2ª—‹Ë˃•Ã4õëþâòòÁ¯ýµük¿1ýTϲ¯Œý4�ÌÃ@j¸º¹I9ƒ®ð€#ÜçØp*(/™Ï!"«MJûiéîµÂNÍ©—È�ç„€ Íä%ƒÁ€óTF¯Æ€ºäœ{R§* ŽþFÉ� ϱ`Á‚ ¼œ£nW·³°•8–ÙäØë‘�;;’/|ެf=; XÀSr#fGã ¡Uœ_'ıdz‘s›X8ó¢dTVç”:w ©µ„Ç_ýuêÁ4qÞ¿µó•%3€†#Ðô �‘~58Á>OŠ ØÃóÅÕ¡ZñªMvŠº4ñ LÈ`òA[ÿþÆ€  º^3üp¸§L 9SèI  cŽˆ¨i„Pd Ïw œHÇtëÎÄDD%T$…Ò50j¼É×OÛýSÊ8õ[ï �1¾º“™0€g3QÏò| i sî¼ëº“N-ŒA~F–ë‚o2œwJ¤È}+ðøÃ}ý£?˜’"eÉ©S5DÔ¨ 8ñ©‘aZªyª£ë�Œß6ûog¬‘.®~Ô¥vÀáf÷m¦Ø×¼­&öüïùi£Fá¸w÷È|kuõsÒÿÊÈíß¹˜¶ÓÆMúöo©¬‘ CÉ.Ãðò>3.NqÒ¼à(�[žãSN@ "$d¶Ñ8>]¥¦½`÷»Ó#רåUbvÞûª?÷ŽV¶£Š @x¨Pûêe‹®Šà½ ~U�_¥‡¿UXÝÌ"¢Ÿ(2ÏÆ l! qƘyŽ T`œðp¬&éÝPÑùáÞ“›©_cn¯ž_�wÖÊÖÛ¤ºà[f>ï™g4Uh€}{bŠcš’;ŒÅÑ®æÕ3�‡hV<Ÿ9 ê|$�»{Φu»2?Lã ¦*�p£×bÙ¼^"áѣǿÿ'ÃûŸ\[�Ej…²š²¾âêŸðîZßšvWý *÷b¿¿ÙEìïíê}^dK©Š*Ö¡èEÄZGÞ®}ˆ‡iß×'¬E;èz�Aû_þÕmZxŽ/AÔpÍIÐEÐ=à)IÊ’­´[5ÚlsTɾ—㥺›af\÷W‰¸Þ«²Þ�ðè]"#à³e3И¡3§$²z ˜êXJ1O}Z|ÌžÇÂs,X°`Á‚ÏãnEl6cx6éköɨ éÌëþ»¦­ñlqÑ´†æ×íXMÜ�'Q P«Ø;o*½bt£æî¬§³°ú�µnå�˜‰ 'C¡Š¤ß¬E‡˜v1y¿ê¼õÎßþ÷°ZC{䮵g~±cCq>s/ápA<}òøÿ÷OíúÔC™Ø×¢5z¤I OÍû!ÆÃáXé8“{æóp'št2<êdSs¶à0ò¾âîVCê´¤@¤V)°E�…J‚„Ì�¡Å Ä+õÿ¾¤Å¡&à€)¦b½S¦.'ua5¼ N¦…2kXŠ—^ÿèO¿ÿÏÿòßýþÃ�Ãj_©kvDÍ|ÿ…¿3$*U£êµÇ!#톋ï—0s=ìçãëLJë‡�òàòwŽâ©{Tò¸J:í¶UíÝÍÅoßÿÅÿü·~ã2c[÷"¦ë›_øë÷6ï‚Xt¯Æ>2C<[:~ÖSåι»ûÜ¡9Û�PÃ÷ß—§í<8’{·àåWñi/¸‹°¿ÛíÖË”2W}•„ q_ñŽ@ùŠ¥ö&wnÚ…9ʘ¯†[Wò½Ëì A\±­a±ïÁœRàžTHBƒõp±³Áqhm 84(Φ±rÞy(À©?úõy"Ð!FîåÄsÈÈ£ÞE0 Äp¸`œèdNiwÇWXÏÜúç…Ö>'´FÉÌÿä§Œ÷׿|¾:Ý]ÃÄv¿ûñßÕî>š[à— QRzªŒ„¤ êÁa’´ëòZºaG6>‘UTi»¤ˆ €`³^?|¸Me¿bäU&||òèÉ_üÙú?üŸ|Õ§ðkÍIDÌ<&ÀRÇ.a� 1½(ÛçÖï¥î/)¸yø”•Š>ÇJäþþ!ò¤žÖɲÇñÞãêö™{z¶Æ3E‚z€Dá6evWWo]—ÇÆoœëÀgâ ßu-X°`Á‚çB“Jèà� ý±P/óúGç‡)ëY�«ÎnT3írŒŸq§ðJ ŧ46Ì…H™KKDµ±jåj’•9¦ý8A´—þ|éÁF8Û^¢¥ÌÍgOBLb•EC˨‘˜V‚ø¬x^+Й0Y©©.{ü�ßD¿‚fHwl�<5fX u€�mUI‡„ÃzMÓ Ñ3`¦R9Z=tÓT|]aÕƒV’´~쇧½–N$:$Šö¯â‹bOÛH •‡7Obÿà·~#7û›‹ÜS§}±þÞ½©�ï\Ä«¬9BâX'¥óÆï¼½ÕI9÷’7ɦÎêÓ‹ôr_gí_¿ûo`‹^�H­ lÖ}N€O^ 9tºYá-Á`¯6�Ç­_<ïJ“çµ+�t27c´Ül�謚nµ?QcŒÑ� ex|³? ˆ·,:mŽ[ÇçrD‹ì�ãw¤¥y¿V� îEn(„܇ÜE4ÁDÌÝ$Š}`l�ÖÇóö²÷° ørãíhÆYí³“p°‰cZgUH ?gCûÂj’BÜhÔHõ0íSW=e©IvÄSÔ1Ø9^!.Ði–•„0į�ÔF3ì^¬sÀ€ V!Lî0ŠŒˆÙ8À |¶þ™Nd�,ÆqW^Ã-Þ Ü 5©g¯ÞïÛÍ£ýÓOöJO€È­bBæ>ž8jÕ~æ(�ÝÇ‘}P¹J¦]þÞ¿u>1Nª—=¢²í™s´�›Í¨ç¹Ô¼t]2Ÿ(5gzL÷ïß»ü Ð3dá9>�…çX°`Á‚ žt ‚pÞ]ßà˜Ã3íÕ}Î*Œç’ñxv¼~ÍV~‡Nh[ki¾UŒê£tøöwß¾úÎÛP÷"‰(ãe¸çOÕŃ>'ª\gÄÿ�~2ú!&d‹°úªOá—FÜë3'ÜXÝï÷H A/¾C.² €8Õ,’θõ¢ì·ÛUêZmäÑav¡!YÕb0öU÷•�S1‚�ôÒNÖŸs|¾¹•lÞí ˆHX$bú2?Á/b†8Ä^ÊxÀ ˜ª!·»&f¯�YõÖ¾?pN o‚•LPƒŠ á5ž½_¯9pÁë9Ö÷æ¢< ©Ó®ÛÞ/ãÍze›rù ®ËÀä.¥@Dr¢;­†¾ Û¸ÂÜ¥>ç�S±RÇÝXõzÈÝe˜F�¾Ëª®A%ðÒhöÌÒ¥õÕÀ§ÛÇí‹ î­¯òA‚ùfUáÍg³^ƒ@Àô’>AÌCË«>šWñN«éÝÇó³êWŒ@�ÂF@`Sø˜RZcZ%tK�î+ƼˆýÔ²™åÄŽËÄrSêjŠõæsµzœž˜·rÌw.§–õË L@:ù5d‚W³.Í×›@Wù~ƾ �)�âÓb¥£²¹ýš8õV¿6`Ð�áòÌ"W‘�ï@ÀDŒÇ·ójzŽ—ó¬ºsfÝ-�âtS7ånu êP@b弑�€„«UzíHqo}©ë@N5òE�_øNúÖ;W�\d�”XB^éí@¢L�Ú a�Žæ<Ä%Ö°*‡l€¥"fçDy2ÔˆLbaÀ÷¿óþûV¬K÷®6o¿^×ó/µ(ÈÈ�¦ûòŸüøñþôÃéj==K$„òDßF+¡¿ãHØšÐÒ¥€ȸùä{{öc‰½›DTÆdNÏjÑNÎ{íï0+Ã*OeëqÈ�”²çÝéró‹úž.,ÇóXxŽ ,X°à…0ð¨ææ•ýL>äÙʳ]OPü¬KÏöú�c»G‡PD[Ýy]Þõ³z]p *¾[úl®èIy¨cê‡ooýРȀòŒŸ§�G¶À7¹Ýl·rô5Ða»ßoÄW.×.¾ê³øå!;äéõjɿРôIúÍFgo…�×úZíl×ÀåjS�Š«u¡‘áS)´!¢3ÉEuʪ�‘ën¥‰ûíáœ5äœÐ{ºŒÐ•6‘!„x¶š¦)•éfsq¶c9?è2ä�ÀGÙ¬:H¢u¾že3fµY»SÏÃ$’PQ븈U$dÎUº­I8!!|�|ü¼†hU×išP·ÀO¶»‡‚§Jl®?øø½Õj†RŠ™¥””RX^ÀæyäɈIÿd-ã½RÜäþ䣬c½Ìý:Õz8lÒx(6f ªyéKt”\¼ó“ë‡7±¿_c»?Ô=êS¬JÆ®ïÖO§k1¤ Q@îomû/3êÜOŠgÆ;Ë Þ†æVm!ºsnYsªŠ¹Ý©™â¬<�†>úi«i‚¾©5Ò¯n½PÒ]¶ƒáû'ã�²®ˆ®.yu•ßʪnxµÆ?e5Uwêƒ-vëN F#0ŽÉ̹h„ iH�Õ1X¾Ù�Oö¥¼:ëânyÜY¤C0¾Nó‘Å{›J\# ðtk"å€ôPŽèò ðWm28…Pܦaã[î¨7œÂ™yƒÓ$|ÁTÂj×IE50JŸw¥À\½ý׿õkX%é�Ücì^Á—5'(°]ºLi�‚ª8(\›ýÐ�¬(ó9î�Jn¯@8ÆPì8üó'?¹Ù�eå6•~Xôp_0 ) IÄ„òÄn>Ø?XGb¥¾ÏŒ;å&{¹®Â}Ú&h â’jãFEÄGå½r¾Ÿ.ÁœîÁS{{¯ÐveL�òz÷Èuq¾»”ô_€å¤,X°`Á‚³@Q¦Nº[M»tJE¸ ÀÉ�*ÁCƒyܽ7 ¸@²$ÃäNL*N­ÂŽU8 GÎ[›sç�„{¦f…r¾•ÀýÖõ³+q‡è�C$„QÀbpO (‚ìD$åqy2Ÿ¹óûÛ):—ëÖlW%ê¨cÛ xdNQ:“UºÙÏ=LÎÙÐ[žãÎ) L¨j“m«•ŽIÔå�’~e8=†�Œþ¦Tx`ªX%œò=çW tCØÙúûaGD-Ùá%'ÐÄ<a°0ÐC2WÝå½þ—×é~ÚôaHпðh§¡ÝŒÎ9,]�У¡ˆH Måp½ûd;}t°Ÿ4á»É#;(prŸò5Àˆ2CÛUoç½EqŒœ($Ð7¯ž$uQ£¸Š§äPÔ2Ž ·TÂæŒÖÞÍãÅp§×[š3\œ+E$Iw[Q)Â[_-Ã[«½ù_ÿ§ÿñߺÿ½î@‰¢T…8N“àí³êT,€Ãz. Ù£7hiÑÌûiï«u ê^1Ö÷)ðÿÙMÿ�ý¯?¼ù(å~½úfp“ð¬2°^೩^ëÄç«Ýe'’øDoÜ}ÞN%�9Ý_q<ó§…VB2è’b%ÑÓ¦ô +ҵ˻ÅÈ·Nƒ'*z:swfª3.8(·�'¦€¡n\]^ö»Mˆ¨vC>,>å€È«ðqT;Ï÷׬ýÐJO�ãÃÇÅáü÷�vtíg 2™uŠ®k‹Þµää@„„R�<îa–Í7€æ„Šõê @ЫB{3Ð+Õ˜è@¨V[í²‡óùQ“Úy¡»†žvHXí#Y‘NSªÊ�€AUrŠªÑÞPòè® T'"z ݽy\9/Š$÷Þ �‰¸ÓŠÑ>ï!øìMç=è3É¼ÂøjHó‹Òg ÊÖHN#(AASÉÒâõk¥zU¨ˆMÅ«±Ï’Ün’+7¨o_ô¸XaH[1ô}Ö—Ç¡è×ສW`BíUû•ÂEŒ �û>§SsÚI´'¶.#æ1ÐÍj5i-•oöÉ ‘�„b¯âàÖgl6ò®.Ô5X J � ´¨š °—]­ÒÓ*¦Ã^U˜zÔº×TÝÌl‡è�Tĉ–?·rz\z±)J?M“jîä2!P¢ŒÈglêzƒ±ð ,X°à‹‡ ªñ  Sv¸ z€‘ Wãö‰r�ýGˆ5ª£Û€z^ªƒwþÄ�u¤¥ÄÇŸl6›‡m.®±_çpê~“n Ökë˜ ¡À¨D‘æÐ¾sòùØ çDÐ÷žq‰Ø1„žŽ�­3¸”¡¹<1ÜWh…ì@å¶q´¡ˆÛ´sÕV#!€Ì”Fç*k§OëÍÎÞ–uÿäј¯62îV XÁûÖÇwFuÌí[ àŒþö£ëVp¢Ži­÷†šÆ2ñŒ6Z¯LdJ:Iò]Þ[! 6½™ ‘àÑ<–… rÎÏ §Ód`í1i-.ݘÅVýOÑ%ˆíqÝÅ·ÿ³¿÷¿ÿÕËÿБšÕ[´†þ/x‡8QýlE�j0�þ«ßû?ýË?ú¿�½)ˆô½9U'éê;ïý7%~)“€ FÀf2ö,,� €õøÇ�ø½Çx÷½ŸÿÁ?Ül6kIØw¸ßK „}Ÿ¨@€3áë !ü6¢öhusd�‹çhj­µÖuÒÃ4:¬µE6•C$ Ía#^±yÁd ½^š8”®nhe¥N]�í<)öÅÅCêécà�»@eЏd/×/:"ЧUÚÒ‚¢†Î€)Š«¤”Sê'È÷ž|(zùä0MÜäüdбÝþüÅÆæè/óÚ£0¤uÆ[øGN}¥1í’�G—=&‰RÅ÷ÕßÊk]ó׳i_b}}PÓÑ4µ›Ôw˜H¦»ppç¾úÃë%êæš¹Í3”Æ(°@„'F’8æxFäB·D}–Q~ÔC„v8™_€"’Íú]}Wôf·En-:DÓqúr th¯ !�ÑÉÉç•PÌ�&Š#·�¹éj”Hm‹Ú%D@ÄÖʺ•éÀ®š¯•>é C$ºN(ÝÆë´_m†íC[û{+öOv×qï£oÿµ?zücI"yiÎÑ ˆDŽ�B'êD q}‡Æ0Ð#€“@Ä->ëæ‰êã�ýƒ÷ò/þÙïÿ$Ûeèf_i¾k ½à߬EÆ‚ ,øÒÀÖ² !Æf'â öá@yòÿâŸÆv’×áâg–t8a2b3�ÙÐd?æÍv‡ñ£�“{©g.‡`lºtÏÒC)^«î÷ãS?¯'êQ[2§?¯’ûpì²O�"DZ¬7ÐÀdÄÇ×O XàžB7³ï�}Ú…â¼Øô뫸¹÷Óf•V›u—°Ç•nX‘NmŒ2Fr ©öŒ»T€ Ü�JÙ©þ—ÿò_þ›?üý®Ï»›m§>i'Qm¢¤ó͇Hî €^£Â(â½£{ðÖ·~üøñA´&c^ Ý�¦áàÔ»íÆ2³®ø\—zfBIw¾ñ o/‰ €á<;;rì1Ÿ7£Ë>ð«E§C•u°Gx€IbB¨¶PAH€Pº‚•2™m†!!^¬ÖÇTy\dU$E¡‹…*UIžæz;œpŠ&<„HpB4PISŒëŽâ"5“á0^»îk@G ¡Ò\æÆËäGKIAZĹ`ÀÅ„ÞB�BÂ#+Œ Ÿˆüˆì³äK“¯VW}fšŠ£ÊC[�ªTD�£Z��‚Öû JfM56á°Gê#¸š À †T ëäœéFÀ<=Ž{Gñ”™ˆêÕÈ�ó®ßçxϯô=G¹ÕI„ÚXm¢kqnÆã;䃗q¸²ðO°û/þèßþ“?ùäÃí¸w¯±÷>=•ðà[\¥âaûÜç"ÖrÆ­ú0ˆa³­î­˜À“TÁTË¡ÚÐõ�‡ùÃüÉÃG9¸¿¾ÁT×¹‡ùIWí³(Ùc¨5(Oójb�X¥˜6þ‘bDîŸìÇnsõ­NÿÁÏ¿ûñßVë!�‡öT:Þ;G¶ËU�Z8ø]_¯v´¯¨ÚüéébŸãÎk±¥Ê�oë wA%ò9}AÏ‹ÙAWH�p&—–‡áoV­³¢H"r8£JTÀ‹`L‚N,'ûη޷:útXw¾Ê9g•P«©ð|^U°Ë-î2BZŸ»Ð4YúwO?’Õà«þiõÕþ0­Yö¸™n.ùÎW}¼±ˆ¾\_Õ§÷CºZFô©Ɋ©OÍt 7“˜à–àN¼ƒíÅzç °ún´j“m’½Kñ@ØuØÎ}‡(Dx"$¢Zm¶9þ)I‡ñ Xûjì�"k”!OH]!]×uHÕÞàÎå¯ nnn¬ŒZ*#nvHÃ|MY‚ᇬΤ™�Ól¯I‚l5ä)I9ìŸbÿqÂÅÃ�ˆÖ[ü:‰á$d|²õz5VV¬þíOþìÏK}ºÊ5%Ñ5Vú�6cêÅ­VÏ:ÔQëÐ8§;ÖiW\zW„ LCf‡›,ïQìƒÃ!�9çaX�]ØíO?krª@ZÕ¤¤VªXí­îà çº{ÒqW÷�'Þÿ`úOÿÚ¿Ÿ�Kú+µªÖµiI¼±9�S×Èé � FÒñÒÌÅ+�€ÌÚ/ÂÅœ1³8 7ßÇpv.kßõU_ |¡AD넸+ü ŠnÕaó‘uð[¾ê<àÏ�;³Ax²ý¤·wD¬ë©=Þë…XxŽ ,XpŠF Vg.@r×±tªï¤õ“G7+JÖL³¡–äçzT·xF9õa5W“NÓX&D@¥SGRø"ÈÕ¤š†¨äº³®ñ—÷ðˆŠb€#™Â»YÞxSµÅQÓˆO\ž\>Ðý4¶Ü“Ó{EȘø�þø�?Ø^=îÍß¾¸˜n¶N†…;O͂¸õF?Ÿ¯K¥>øÎ¯üàéa¯'žcÁ‚ |ñÂ)”hm@æs¦º§œ‡Š#ë°Û÷y­‚iÚ§гñ�€K€”c¢€¬ŒÉÖ—š\•ÞUI.bEÔñ~¯!ÃMÞl;>ÝÚýÞŸÿß~üƒ†€õ"d²;Q@ 9ßñ'7Eˆt-ÈÔéz÷—ßÿð»÷2—eZ ¹„8‡ü+óÏEžÀTâ½ôõª– IÉäø!A4 ! ˜øùZB1~ÿ‡c ï;„prL‘êL‚I1´¶µ³&º/Xð`Nå zÀ�ˆ–!ái�Mbª"«0ËdV™è•çâ9"¥WŸmI\*hâ"!Ûë © \Á0#tÝ2-ù >/Xá: n*ÍÜK© dí$$\œ À¤5F¼B¦€Ó+ëá‚q0ŸB¡š(Î0$EÊC­µ”"áEÄ­‚ÐRíiG=‡ÄÑY N©Ø 2*œ@Bu¤`!J‹–ÓÒ/¹à¯‚ëëm§NUßty\…X€ +OÛ7G{=‰ÈÁ«d,¼ÊXWI_Õ‘>y'@ìû›H(€hH>p“׫`ä`·ÞŒÓjÒ´GþQÙ¼º\wåÁXßV};R)Ñ«2ì`†—‡ müMSd7ëª+Ÿ¢<õŠPåFIIN×S×åñZÅЉ zǬˆ ƒá`0œGÈ.¤v¨â¥ŸjvSÙ�Éó�ª ý.âÑÍÁ‰Èzáè=]gœššÇËáS~5çE€L͸5èN "Èh„á.ÒŸ.½.Xð¦£E"!>Õeç›�ì¥Ó\‘çÐ-f %Ø4¹3Œó8ˆ|<ž€V0c@×kÑÀª—³Ú<¿¹x­[ ,X°àëƒ`sm?FuÍÆ€Ghߨg” ÄýàbgØÓ��4܆ Ð@3v‡3¤W·ÖO‡‡w}î i2Œ“Ý�Éö<ù��Ða6†ªBGÔ„Q£ÎÚî$*C¸æœƒ©L\õªy¿¹Dá)E8-Ô˜ÆëØ{¬ïYà&�Є! ´�ßìmoå·ng¹¦Õ}!±  ZŸú•ô`“QÄ.RåN»íRQ]ðõB˱àì? Ò'«âQÝÜFsF*J�ZŽF÷_üN3СÐÉ–ŒPtý°- ÷ݦ7Zà€¨Kèå‚¿¦²óú„Ý>äšI%’döDaP< Ô‘H¡¸CqÚ#¢R‚œr0BXED{« sßåAˆ Jv�É)ïúßr×uE  AI&p×Ir=AIF8$Dî*&,x5à}‚tɃµäR²GD„°"‚rëSÒdDðù/-Øé‹…P UÔ“sÒ RÜÁœdP\ðZ8öÉÒåuAÔp#ªêõ‹ ¹¸—ºÕÅaü‡ç?øk——k)Ö©*05.4ÏÝÒw©Žööª{1s%s™I‡qrUŽLô‚$hYá˜w7s8Çü4G<�ì'hÀSUõ±3Ñ<˜¸ØÒ1¶àó¢[oê*×îa©��ɆA5¬L!èäð^Òû�¬IèNBÓò(Zðùa‚‰A%Y¤R{g¯`QU`dóeˆÔáDoón¿Ø196ÓËp/R\µ„7ŸsíE!¼9¦<½fýÂa£h¨ê5v“Âw7ÓXm{ø››{ÿÑ€w€¡Ó7‹T� ó9Õ!‚2o‘èÑ"òˆæpsŸy;J[ú�|MñìýEp³�&}Zj� Hnqñ5ÎF-8 ³O]ëÙ¦™H—T¤5†¡“C.eòiŠXV/ÆÂs,X°`Á‚³àdïûŒ ”ît=” D {:–KM¤bVœÁ«…(B'uª(S²º#¼ëS‡lÕÍÒîzÚXîºû«Õõ”>6ÂÕÐv?5¼ÄäÁÖóÔÚ¾Ó¹<;ªpÍ5E5°¶V¯x†ä8r9]¯aÓ¹ÓR¦°HK]kz#Ñ6zgƒØ8^c}’Š‹•C§]9ƾùéB™½ª;à_4k8u•�–7 ´.-SÖµF Ÿ" Œ:í°Ýʰ?—°S‚=F‘¨„I¸˜rs¸¶¡Óv,ëq2jî˜ò*–vöŸAý°ÞŒþÁõŸnëvò(¥fe•hj!õè�bR½eFq"o$ö=Cà”’¦}P7¦mýèâ²PŸ~ïßýãÝø8‚f�P³èòPkåÌs´µÈ‰ç(.`âÈŒÔyM1n.éݯ®J­ÕêV—"‚Ï'ÆRUJD©â`JO>Í=ý4ßQ‡:°HœEÍÐo¶YÎ(ðZ¢N5™0/i›ÜáèUè}}ˆ��;Ë«2€Ú­LŠœ.mè·û{iõ^‡®õÈEô¸—PQˆ[†ãvc„»[8D”Úò·ÍL™²…,§9à9þéøe�Zq’8t¨À=M´ŠËËUÒ\ö»‚¨X©$0Òƒ©k H g™_¢mbä| âg2•cÞÍÌÿ÷"JC?_•wÁ‚¯wÅóÝǸ¸ìvèõØÁ@)µ‘ gì œ_ wfA¸ÁQpH—²{¤4ô}L_õù{±ð ,X°à‹Çì~ë‚h¼NxADÖq·ë¯.�u«1Ñõ­{�ÍW±ä3éô�îâ ¨‹º0ÒÜÞI‘äÕk-–¨רc*^Kfº/ÜXéjÉÕiÒeжž³~ (DÓø‡"ô/|–ÑÐE÷ wq§|s‚£ ¨c h ÙÝ Ò‚Ç®=IŽäl;ß8›žÃBÊ0 VDJ9s"˜ÙBg,ø&@≮!�Ý'¯¨q1î¾»Þ|øþ‡›Ë‹Ãá†�Œe_æÕÈ3͇ Kè­jX³†Gˆ1à%«ÞË!?¸{¹ì€a¹Q|^8½Ûà#|ø�þÛÿËSÿ‹›r�”»¤ªYwÂ=1áèŒpÁJO`%GD‚]‰g°´'�C ½î|<¶âëðôÇ7ÿè'ðÿ½ã¯}R+¶q–q`þÒH¹ÉÇmµØ¤Í·§m D§1ö÷/~ý·sûsó'"^%w—˜l‰á]𹡎®ðAÊ1ÖPX`œ°ê1"wDÀ[d\kž7}EÔ³"%„£Sˆ„—N2çœÒ›Q’ˆ« })=¸ßÞàÁ}ìªÕÝU·š …=½9ÝГ4Ÿ®"P@y\GÓÁq„Ãñlß�=­Ïqšg¸ÀE(u«�‚vceëcQlÖ8ÄÞ(ýeÞÛSèìÊMÎLè0sód³EÖ‘´\—œsTx�.%t}JóqÄ­…&.“Ⴏ$žç-À4Á“»ûiY‘³¶ûQÏÙ·l,yw=C$…;­R�:�ñfLÜ_:–Ó²`Á‚ Έ9Skf;€殦©Ž75R½ÌÃöQÒгíëœnⲉzŸ ýÞ÷”«uŸˆëí6ê }J]Õ|_mïÒ„BD–p"¨ HÅ$„ΫÿOuŒ}A#I�2 I±ÖIu*×û èNÆã·¦ L0Æ1ÆŽÚeõjè»~o…ˆ€3ŽZxÞÖ€ÎÔ?Nø:õP½«OöOÅ6!LDcÅîvÓP‚S 5=Gò@5­þÎaú[ï~»~›C8ìR§“¦œr."gÒ·5gðäÞ›³õ�…ù�ò~¸üñﶇ=„æ8TÂSïÓbV±às"¤\O|"?þhûßïø½’J—/û{ï’,ÓGÂ-9ˆI˜Ž�ƒù’ã#‹Ž¨8ö8bŽÈ5qýì˶o�-�Ú�´pÀ �”)5•}ÙW„dÝÛðt÷“o¡ÔpÕ`)K>Í‚Ï l˜V”¹•$ V © ³p uÑ� ÚѽíóÑ…—à$JIIYC¢Úi1DÜ®Â^¯º¶’^z«\o­�\X ÜerIõh63÷]5œ&ƒO-3Ÿqdj·¼#ðSµ1|þ+*$� ‘&°fý/s,—Ó~* ¥áz ä"_9* ºÆ>8À;égZŸ “¼Lèó{™j)eûè‘¿‡M3>JÈÑÃjÁ‚¯fVáÙia¶n;Þºä)?㜷ÀùÓ õiž™âä¼ ñ‚€ÈÙ*'o:žcÁ‚ œ „KPàr§�½;Œk¢Bº÷¿õŸü�ñö·1©oå·sŠøÜåÓㆧEê[t‚'O?ùgÿìúƒPžÖƒÈ�ñãÐÓð¸ë�äN"*„Z™ó ÙÄïå\gÒ±ÒÕ4z­Þ™o€Œ‰SqÜYoùüGÜr…�Ó(¤‡Ý°PÔy™Æ:Â<ÜÚ6‡A?S€€Ó“G5À‹w©`bZåì§±ëÑlô®(eY¶-øÁ‰JÑ"Һѳ{Wê=Ãöãù¿ò6ÐãXñh?ržŠFm.  Éñ �=ðøà{úgÛ›]7\¤â(` 1 û¸àó‚ÅòC>HWï¯úƒãø8bØÝ”‹�éÜÎŽ%C¤ºÌ�ëyo϶ŸÏóo‹™ûöq²Çlöù3~Zb~ÀÞâµtn\óáj“Ÿ<Ùê£ëÝ'{À5'W:žcÁç<$Öb¹ë¢“‘2¬×ëC-& �h™L³ê™fÿ@Q/‡¬4õº# bQǃÀg’ƒ>g¢CxNÓ¤ÏuB[�¸wÐcÁÐh¨Åuœ†Öý ò6@[ž+e>÷ûè¶3Íé1Ýþ(-±[€º¡T³#Wäðu‰uÅ`ÕÜî_¬J®y­3û4Éaò<ô)÷p9i'”œVÄgZ°&€�ÚE•¡[m6|ðÖVÁtÛ5g‰¼^—Âg€à®�òÞ"~¾„µ0Óé–žggAÆlлܒ/ÄÂs,X°`Á‚/-ÅNNûŠ€ºˆ“!‰©úÑkÉ¿úkØ\Á3ò vΆa‰;<á (GìwÈÄ~»ûïþUôCÒ.| Ñš²!ã '”ƒèaÕKÀá!Âè%$y% rÚ9²E¡gµ·VÈžÃÝËSìûõÕpY>®OŽ‚Vt à?úñw¿õ-UQ³U�±NÐÝ®ù"ÄÌuH Àè!N—sŒ&ؼûí?þá�§iLªÚ©gìN'\➎ÁŽÁ…æXðµB@‚-ï´U p vî»ß¿ü�_¹¬w4Ç Âµ…Áž­t@ßþØ; ¿\LÓºÓÎÁý4«ÀÓÉ$°4�-øÜ¸Þ^_Ç'»éÑTÇ~‡_|ï»+&áV1jT@".nØÊ�¨`dg’�SÚ–´àÍpØ©QÑž7?ëiêÍ·��N©.¬–D'—!ùÇ?>Ü”ÍÜkÀFÓtëyµ`Á«"ˆáb›¶^»«‹Ò燻­ç¼+e¸¼4¹s4‹WÍaõ|…+#>ž®;Õ+í%JÊeÊÝp9dFáôàÜ2C¨¼f+2Š€â*DLá Wu&k†Qnp�;fÿ(»ÃÒÏÊåçðÜŒñŒžòyÄ3?@�ËÅ!pÙцÂ>d¨è+:‹âþð“'XñÞ¦G�}£VùjæNáæšvâlŒ×-Ï!€² 7ûjãN±ß]W0�v´çšý-�"“ ¾¶œÒiŽnwoù³&ßÞ\óCàÓ´J4opaØ—Á¸¼±XxŽ ,Xp˜ ­O“€:H.pJ˜o¦x[;hF%rFÎg\:óT`8iŽÞ£ƒ^v–u@êö¥®ÈJ•N/”ˆ\ Ê«Øè¯Ý»÷ÝíG7T‹ =#«%¢B¶`9S>"ï÷)i/  '˜ùÍþé�ož>éßC„â(‡qºÓ/§ýÿâW~õó·ûà ;6q;nÛSO q¦x@€GÀ¿þ�ûòç»ÑÊ•mÙüíõ½Mì]\º@gÇmçŸZvR ¾à¼Qq0^Ä«ø¤2…—ÆcíÔ„Ø´ÔóÔ5NÑÌÑêC� 逮•;ÆÃÕúÊ«év|\9î&Ñ¥§}ÁçEè;÷é“tò;äÇ«þâ[—¿ñ?ÿŸþÞ¯e”WÈ�û8nE@ ÛÉ›fRhA_œk ȱàPïhqç;Ÿ¿„pǾCrHÀG”Š÷ÿßÿúÿüáGÿöÉÍ�ÀLU…zÔÑöÒQ“ÿìæî ~Œø¸î…fï^}÷ïþ6þÆß¸wuM "!ˆæ�T›# p½õYúâá¿À@uì ð»Ûßù'å“�ëa§=á »œ|«äNÃÒëì™T*ÑÁ:¸%ë²I &’$Z‰€¦zZPþ´Âà¯XiÝ?wÝc_øýw�A Á–*ˆBrMCÑ•¤.¬3M TàÝËw­“M—q}< t\1Ÿ&¹óòg­fP€¶xûòÝ~|5$€ ÊÜGG=G¼näׂ_,ÄÙ´b·¦ÓZqÞ j̦ҟúê�¿³e…D{N,ë“`á9,X°`Á'0�¶§u#<ê𩔀0Ýép9@Îû<Š9ÙJ™÷ ³¬A’î݃ääJU-‡©N–'ZM^Y+xpñößú¥ð[ßùýÂå/(ØWx`Eô …¶À¹|«€tŽ˜b§ôÒþÑ�þëßùÓüý§§2Î'½ÙøçöKû·¯€X©õ³UG–™ã¹{v0Û�ž©®zA\ëRÓ4a”î£ÃÙ6q.á§|?¥,Xðµ@ЃzX• ‚F¯) †HÀ„Ò!�5äP�Aó­ (€C0VÇœdW¦�š:xÀ`:oñ,ø�Ýu½á´¿±Q²PÖøå¿”К±èá}N¶‹ôÏ“FÓ7#û Hc6^"ú¢ÍÿÑe€N#ž(ü“ÇýèÃõeDÉ@Ô¨QVÕÎød_ð�ÀE¿9Ô›�Ð×¹w}7¡ß† �ƒÌÊ8Ï 0hÀ*4m5ÕèV«‹dV'ÚŸ"ÇŽ¥×FC+“#9‘qëhƒ0OsÏQ ùÂÅïÝzáøLÐÏÝÆI�!Lsõß 6/º‘ A£Á>ÁD¥¦2Úû7�ÓÅΞlËu¿¦ÑX#«'ÀCŠs2A“ài®;ǸËÕúí |üýë˜Ìcw  �J»G,Ëó߀`3›}æv7~i÷Às»áfÔNa„3BÎʃ¾±XxŽ ,Xp˜=ì¸=jz \ô­%kALõj1ªÝy— q·+�0A 8xQ¯¼îU”‹aµ±2I •°U~ëçßû›ß½ü;.$ÜØÌsl®ÓùŽ_ €Þl¾‚ï®í/þìGòn’Ö8¿5‡¸ ,'åX?µ‚>î'÷™øÔÞîœÊøf¦^=íT!¤0­² öÓþê¢<îc–ä~j_µ`Á› ª†3ªx…;½%©ö•ë‘WÀ[@ÚB¬À†¹ÍýÂÇ�¾Ñ‰6ûduYª 7‹b/e§ìW²_áÂ7âãW}¼±`Ⱥ_¯±º·¹(º­¶9\3ªŒ}×k£¶]a  ©=9ÒìqŒE4ó(¦ã“MÚ÷0ä¹þÊùÂþ4NJQÀc<íØ ]¾wu9Åûæ“ù@D@""˶t†ázÔq²èd Dô@Ÿ)¤˜ÝF[ö¬Â pæ œ/Ÿ©ÀuuC¿)AuÀÃÆ s>G¸¸šš€ñ¢[髃cB@ª¨C#:0VY+óHZ4MPPî¥æZ%³>æÎsðnáòÓø)ï÷ÖUõî9q J@Fh&I£æƒæJ^çôx@^Sºto¯ÕíbûA݇û„û‡§‡•nè�º‚2ºŒ¦#±"�ëz�ªþÄö<¸]n Ôɵ¦´² €MÏq›‚òUþ œ/h-zÎ/j¾egÔ7óÖÏÀŸ;or1�Uà„�õ«>u¯)žcÁ‚ œ!G÷ætkPŒ ¼Ž;†$Šn@¿JrNǪ#æúÞq—"Ç]J/9 ‰ãa`Jf㸷�’’S?ô«IuÜÚãG»ÇGyp\¢艕F%ŸUÞ?Nû¾K}±DEB½·yûþ½{Oñ±ŸB#Cá�¼Ë`u[#rˆ`8)?@ÞzUÝž"žkÜ—}× �;+ûˆÈY•¥uÊÈiqÇfGrö+bÁ‚/„Kø3až¡ÕÐ8†©6öÕŽ¦gãî�8Ü“ˆ+ª£y‰H]o‚]×+?g|Ò‚¯;n¥L»Ý¡v“¤½h¹Lë G´›"ÍW˜¢Ïìí_P†8»;6Îã.ØX ÿôO�~a@HèZJ)e”N§‹)PRJ´„žÑAhÁ×zPDšgx•Á»åvO¡€ŸsÔ”##bM%1õÚAÓ4�jwî³ê7ˆÏJíþJNi€!NxÕ 1  ¢ *ÐCJ¤™©ásÅùÏ®Øûg¸±ÎsŽÏ'ûW‰¤³bÒ„E0&/ô’¼„âp˜.S7è0Ù”q™ú¸xº5éi´Ä¥£p»û qKæ~±£ˆ­ûcÙßLzO¨ÕMkâ 0„Ð<�D[ׯ4pï:J˜ËÑå¸ýtB‚ j ‡ÄquÏ A¶ ‡ç`µtºG|ŸXº®ñ‰R‚€GÓý@øB=€;þÇͺÝ>Á”CX<í8å5óYò¶S}~ž»�!bþ_ž_Üv:MϼN»ÿÄ_{ÒpDËRZVç/ÂÂs,X°`Á‚s@Ô܉-X€0jMé�Q±¿JÅÌ5¤Uw$|I!·~tûf ãÜ‘á@…$²ÛÛ0ºöRÔ#Ëdu?îëjº¼DÝNë~_!„*ŠjHÒT}MËc¾ûö½'u¼ÚhÙcè¥h>ì ¢Gô„Ì*�—*âW†HÕóÄpý°ðÇÁI�H V œD$D :eb…H!2?ËXAëV]°n÷ßÄßyïç>ød dfÓG^¿¤ï@•¾Ö(*½Õ®ÖéòB¶»§÷ºw'ì;üüõίÖÍâ;qOwRh^ 8qâfNó…$ >7!I@_Ä™~ñ3? �ˆ˜É#�ÃEgñŸÕ%âÿÏÞ¿üÈ–eé�Ø÷­µ÷9öp÷ûˆˆ|V«ŠE²ØÍnv»Ù 6Z€ú!ugš4С�FÒD#M¥�M$@Í�D´ ŠÑz€lÝj–XÅ*23«23^7îuw3;gïµ–û˜¹ßˆÈ »™áyýFî_zîðkî~ìØ±cçì½ßÇ*i–”Ø¥5¿„~…êt:�Î×�Ü£ZO>�¨ä,V¢,’d=F)~k¨8iv‡4±‹Äemb�D ƒÁ&"è8µ€Ðc°8 #¨ÒÁ½ð‡=¨„N0‘£4gãfܽ¼�‘º‰��ì@à†p ‘íåãh£ò+É`ëó†h@CÄÅ•R›ø�³Í_Át²Óù• €Ä]\´‰†Cb#*P�™ÐÊ-ä½#‘ a»v‰ جž½Ù;²‡†#”û•{�Î!pÀa˜@Ò�¨Ä’°¶"áIE¾ 5܇Ç�}îòËÜ&è€-wöÅb49l}U`£÷st~)\¼,iâ¥*8ˆû¦F(�z~þ—BÜõQAl‘Ay-¥÷ˆb‘'$H�ðvG2—ñ’¼šP–`!ãXÈó‹Ì'ÏNuÀA€V-‹i7¥CË”2 `à„uäj“�p$CÞŽ NÑ kK‹€‚�Óéñ�èj�ˆ$ w”R|™²k µ%�€ "?ìu~6!5=ÓŸ~ü‡ôÿó“�ÿ‹›ý�«MÕ²™­¶­U"ydD ô:´u@F¢‹ O‡›4HÎ^ýPëÎ9¯Wiçÿíÿþ1ž©{†3D„&òÆæ­GÍùöpؽwñý¿ô»ÿö¿÷ÿýíæ`:Ô�»†Ä£òûùR¸Ø`à~CÛ¯0Xq¼ò¶…,ÉÐõhÄ�@i�ÿh¾%zž£Óét:�N§Óét:�N§ó¨q" Œ” C˜$—VB490¸"ZÍùbíó€»³„%•€ ÄÜ,Í4�B a¨s�äÕ*m}Pt?cöˆ™uš7Y4¼¶ì/ NAxö‰x(þ ìK©±žæ½¤'93’Ó°^}™΃ztÎ@veþÃ?ùÉö‡?ø;»ùO5OÃ8¼²�Ö‘ DBd BnB É 0$ lzV� o.ÍÅ„–¥Ž¬0°/ŸiZƳû9�2Ì.«"U�üSŽøó�˜þúïÿ;ßÚŒ�4Í7y¸JJëŽ�‡§ç9:�N§Óét:�N§Óét:�'Bˆ3d¬¢&ê‚�›:Ý‚„ØÑ²!¢U úùxÝèÖ:0 qö€‹2¤J…g$fÇ éö¶„'–(u¤d¤< ÜA.]nt6'A¡§äøy~!¿Ähâ—O6Æ�’Â Š•j¨/¶ wº��· çÂ�næ?qùéÕó¢)5ª•ârÔ!VG{×< î4 Ah…«£ºª7K͹¢lƲüNà+GÀó Ž:ÍSx ·ÕÕÅn·ÛnóÕåÓÝË�?}õ“÷7Д†‘ÛÃÞ¤ŸI�‡§ç9:�N§Óét:�N§Óét:�˜#ÈÄ�LÇJuÖ›ð…3T›�Ä�ѲÀÊÛá)�1  pfCÖ1YB™²«*Œ(Ðí:yÅÁ1d)‚HØW½¢J4™<1ÂÈV€ož5òÃdi`œ§éE nõâúæf;Ìé�+ £òO}ûu‘@TÄ‹¶T+s¿þÅííD¥d›v"‘8ËÍÁ}ö"åé—Â(2v¯†Qˆ8öspñÞKµª‡œ©#ô¦£iYmHä§ÃöÕ«ŸÎ>3A³HNÎæ°(¼kæè¥øoC¸Á‚pà»ßù—ÿÚ_úo_­~ë°¯g@B� ÷!Õ�ÅÚª¹ ßDU�°@5›ÌKD¥„pPY-¿LÿÊ1èf–WRmŸÆ´ßUwŸ½úqJ9�:ä¼F`œw‡A°^]»·};ß|zž£Óét:�N§Óét:�N§óx!œ Ó{T‘CÎ%ý_üÝÿã÷ž¬ÊîZëz¬ûò~Ma¼ÖEyfÜöMÇÓÆn]lŸ´pP“û·IO~÷cÆ1ˆ¨– (‡Í“-\ü¥xJè ±B:fHޝóuPC˜€P±ß½?¿ÌÅÍ"¦iº*<扂`Ou¼]¨¼¹¹ðj>å§å÷~ãߊ¿HŒ„f‚8Pwähyœò …÷ë&h¶ô…œéD^—“t ”Û÷ngüyŠÿÓ<}¸/‡«o%];ÄÌÍŠõJ'ëÍ�§ç9:�N§Óét:�N§Óét:�— ‚R—´@ˆC iJÈ|û“Ñ_–‚1aµ‚M7ºÉ×I¡�÷a¨ ´9à^·Õ$pûé'ŽíU‚Ñ5VÞÄÂü8j:j{)öõvµ¹ªVÝï|8üau¿:o=)Ìn"v�]Óþp½ÁUÓ†ÂrâÔcÓF“Ë0 Ÿÿžˆ8=’Ö)-�ãÜq$Ü %Àj·¡7�ªÃeõpíœ&›†akÎ.€Öyhzž£Óét:�N§Óét:�N§ó¨ ¤:ÝáKexBéC%Y$…+jbIdM¨uñÎøúIžRÍB™ED Ad„W£9àå€bQ%#fE�-ÔË%ÇqZfcyœ0Ôx“ˆó/0íÙX�ˆ/??ÖÝ/VäG¡¢Î[ÆAgAAó|9%3.½‚PD‚ˆÅW¾ìûÓÈãã猄ð8�¹N�Âd*P‰JÈ´|F:�‡¤ç9:�N§Óét:�N§Óét:�š @3qG˜8Ô,L* ì¡0‘B‚I,ø`yc®CDš(Õ r�O D©s�* �S�3%$\ š`”VÈ(€‚'û„0‚Š¡¢Z-‡!-é\:;$C%\ G3$�ãÁï¼U$„!nQeQKÀç2QrÔ&«€8 Ž�LV~V²áM:ˆ(8¶ƒœ(h¹ ºˆŠH� Œ¡oûøu~-èyŽN§Óét:�N§Óét:�ΣFZ\5pT ¨C\’@,ÆŒˆÔ¤fyy¨úñP©"FZŽE„Ê©! ˜Æ’±Ÿ ¡ÍæBI#¼F¼˜>–× —öŠã‹\„£âaF)`°èS…0íkáøî¼mBY<3[Î ’tŽÉŒ â¾³½Çö& €³"§wVŽïu,©‘¯—lx49?îmrd` ¬á¯Ƀݠ£óÐô 4dpÏ€E�ƒ`jeXwsYÞÍj?·‚j3ߣ]?vÒ ^¯Ì9 ÉA'*Ã0$ºÔ تÛ `éÕ?Ïï�G·ïK¯~‹˜­r9&„ÓÉùnwêŸ  Ä逜V«mq"!Ë%P©B *µŽQaŽÈ  š‚³3D�¥&1t¨-G5¡9¾•u9¨'ÿÃ7Óa�ã³L0cHå�*­|-4*�VxX!NOøµ�äçö}‘%>>ê kÙÚ>¶È€9N„p„ÜER舄P@鉀¶ÿ¢Ù}úЄ'ôøî·†£µé}ðÓ18}ó¹ŸÒ¿j·ïA9^‰€‚pJAiß‚PF�ÆëKúN§ÓùµE+hÇûµ0†f:ÝÜ/Ž¿vâA¯Ÿ÷J¼O÷Q�|ïþùÚLÌ(0 ¸_TÿŸü'ÿÉ¿ºÂwn#àèÂü $`˜ï=KŸÿ«ñÃOvåvw›•ƒ&( �âà°Ü³OˆåîÉÅ&Á{¨¹ÌR믭è>=¢Y‰f‚¢Œ–N:þz¼ÛóáwŸöÉ­AaR]Ì`Š &@:ž‰Çsé5¾°ú%ár2y´©®.ðeŽÏ ´99ƒ§LmÝ÷óGÔ$Í£Æ)¾ô§ô ‚ætñ^E`glyYu.³WAÈ2ƒ Â�8®_[ô~‘5pçWNÏst:�N§óè h8\ ÄPgøA‡"¹–½2IrÅ|aÀTH[ÏeTà%±!¬bLR&‡»)ÚqAÓ’÷Ÿ 86'xÀ —ù²¤Ö“ü&k©¶ZÝ•ÈO¶òãõ6°Å®F€¨&Å—½©.ê€.I<ÄÈÅ:¯ß—ÎîeYàš¸FFäw½ÍZ\Ú²¦-1‚¾-" A¡L³!)•‡Ù‡f©ìýõ€Ÿ€&°@õ. ï8pAÍPÃú˜G (+ø4¤Š¨€C4˜ˆ´¼çâÁt =`÷JBw5­¯6S„dú�ç Dœ>ìØ,©”Š Èi�Ø>=*(@êQ1@ äëYL~½„ðx2€2 KX…} ‘>$‡ÂbSZëˆ[ÀÚ:ÚµÉjœ’Âáv̇bIŠÜe2–R¿Ó>œR�-RuîÎSÍ Æ•Šønw£«UÔ£Õ(ŠÌHâz„[_šv:�Î)R'{謈L_Ñ,žÆ`ˆx ò¢3ÃxÈ<ÇëâM‹i*À;ï.2JCÀÝ]¼]ðƒbZ`U_¼ü ß}rñt,ŽÞjo¡@â˜çh÷û ŒÀw.×ûëÛá2WCµbÆ\õ°ÔôàèRz Ê53ðz´Ä !ã8W ª¶ÿ†Àá±bä\ŠAG° 1 ¼Çyß&tp Z rˆmV0 \!ð ðœl?úb¶_ËÔ´ù•ûòÜŒ0�ŠåCW�%,‰¾•JqÌ&~æù©.+—2 ‡jâ…«Ê!èKEà„é4F¢¯Nž»}G«ŒaK÷j@‚€Fï„ã­oEúGàñÓó�N§Óé¼;kO0*"=¹¸˜&V¡CJ™¦CFDªV� P €”@G�Z°‘Ëš5¾°ü»_;&€An  -ÏÞJu€3Æ¹í³³Îu•Ç÷²n5à Ìêê¨Òjˈ0ÒB`“{ýºGÀŽ~z|ÑÈkëøÖ…Àr¬|‡9©<·W¼Kxh‹p ŽiTÍá6¤Ak"œ5®_à�þ)ž>…UŒ+~”ú]ŽWLQF¤R6¯æ4å¨Cɘž FäÑb"Vo%ŒÃê6�I7ã¡Èù–í”=\ƒ·86ÅB’™Õ0 £¸I[bÅXÁÚú (gžŸ¿ÀÈ¥r­�N÷í"‡Èò1zdyŽ»žŒÖ½ñÚOb97HÏM°Âe̤„ÊÑ  Œ-+¢8Æ¦Ž‰ èT‰{Y1Œ`µ%3&¤Rä.ÙÂ8W^Ý”f&"y™³{ ªsé\;潓£Óét€Óõx¹dW´6ßÖž�¸ßÐ+¯—|?P¤½Í:}i8µ.·’/¹zK àX tdiU¼n€5\}IPþ ‚]Þîx‰­G Ðê…¦ÁgÂ%œp†­iÉbÜiùóÛâXŒtšdèŒËe©ThÏcà,¨€2ä^³ªßkæèwÕ·…t‡ŽŸŸ¥Q:ŽÝÏ2‚€£êçC¾_[’£í�Ãã^�øk0‚Þ|Ê‚Èk»Î,]ä?wl+¶Y}H"ŽÄF ?NSôXš/äüíË)Oó…ý�6™¼Kr´îg>¶}çKéyŽN§Óét=„ ”Ë °•~ †ä�êu_=ÜÁÛ˜ö¬Ó˜0[½\l¶@œ&‹^Ës$`èR—Žz\ûb™Ý%ÿ0·)-±'æ³wÿ ðl¸x¹«Ã#Bnk(Ö2&£‡ÔõSœôè[‚ùõ�`ëÝÊ Œ�F ŽŠY¹W$Å@NßÔÚa ª�PÕˆ(V3ãã2ʦ”úç?˜_}²3Y*W«@Ðp h ™ä:ºÔ϶¯ªNÉ}¬ÃzÞÐÖ;„äRSÕˆ�ÇKäƒc ѳ£Ï&عgÌÏåöýaX½Ú�«‹¹êå�“CL¬&(‚kǶÆUŨ°Ä8sûoޤéƒG­Ý 2‚î‹Ä6Ó£Kr4î*ÔüË” Ð$¼ʉï¥"DÕ-C3 0I ò)ß©AŰ‚0•DðM‰€j¥ÀI*…’5H “èWŽ$£MÅ™T=|>ì‰,ѲxÕÅ"f‡IÀßH«Óét¾á|ÎØ@9EÞôE¡è•¥£â!Æ–ç¸%"�8Åo�¦Æý2Þé<:8C¤‰IAÉ—š*apÂ\̤˜(<[ý,ˆBTñ ÕÀ`’+ÓD#Wªd¥(‚�ãúñìíƒ 7qaËy¸ _�uÁzåt¾Nzž£Óét:�ÇNû'’ÖÚø%9C¹ÞÕy-B1'CâñCÊßûìU¦ØtØä1¦iÔ¥ŒÚªç–À_Ð�ÐÀº@Í‹Â)¶¿.uC„K@Ù%›qȨrteøªqÒñf¸x¯‰VYj8¥•‚‹.BËâü¨šúpõø@ºWÅÖÚð+álrCÅLA%êùùwˆÓ&YÍ,Hb*¥Î³ªNóíåt+Í×奉û“”Í¥.Åž„«/Î1ê’+‹ºLµ¦šÜÇÂÕ\Åçg9û4ÏŸ|8°h¸×ÏÞ«i�Z[qÖ9ú¹Ud…ÈÙòþf¾‰mÚ¸ÛáPJIƒ…š‹A £ûÊ"ÔC}8¥‡;ÙªÀ2�Žcù©¼ÖÀÑ´Î×ÊèX�KçÃÏ“i>V´ÕbUËaI¸ h½÷Çáíqq‡<à÷ÚûÃáÄ"{Ñ®M4ƒñFÙ @ªKVV&©“'5¨ÀkSáT£7Á„`u¶PÚ£L8u:�ί˜À±ÑP€¦‚ߢª3bqk�à | §¶�8™¨ G9´’ëojÑI§ó.B@qR3†ÍòîlÉ[ß·Kq)&pƒ%•®^̳,+YD0ØZõM|’ˆˆ|ZBžAÁ Â@‚ñ`똑 /U2_T?è ûåÙævÀKÖœ õ^ÉL,r? ?¤s$'Åç£Ñã"”ìÅÑÜRB4„!�+Nýõaf¢©º'‰A5Ì©²}öÌ/®Q‚*šÍB„Ã0*’•= k‹ ¶\Òì6‰O5Â�ô`„ºÕýa³Ò�W—p¬on¦ðÃîfaø™i)RÖ›mÀXM·»¼'“:d^^Äz]r*@e€#ÂHq'Íý>öŸ‹¶• ^§…Úç¦ð¸àiæ‚3è!K’cH50‹Ì§—¨A�Ü‘›†W@#e¤8uúßmð®�ìsÇð�>_ô£z…ø(¶÷*†a`@"N˜ÀœîbÇ+U§ÓétŽDB´X�ˆµ–Ž€!€‡T.º-rìºøzÇ{ÍK£aÓޑ徲Т�÷e”:�Σ€Ñ4E¨C¿:[&Ã!SHÔfzqA ±„F8iÄ,iR+”âæ˜ ª[rƒ�8éï}5ÐpÀzìr®Ns:!N­¥£u:wÞzž£Óét:�w‡×æ[ ¥$iu3*ö+øh7;<¿ù[ê6ä€qu�Ç„ðRUæ Ðb�wò£mEiLVE4$ •2%”æÃÀTg Z©g÷6½ú$?ÝTL×7…¡V3êH+!Ÿ³¸\Ô™›€ÖÅ©uy"œ _;ªˆá#|D¼ó�v”w-µÖ!e’"’4ê°Zéo|ïÇÿ⃛aNêþvï†\­”ùƒ§Ï—X6Ð}Éc=%¿]eÓi¬¨–ê¼N®ûý­Q¯Ë3qãn«ÕíàuÎ×w6¦�_Þ¦‚µjŸçÕ¤êÏ/êÓ§õꢌi’†ˆIÌŠCB²#5�Á¯}\à½ãÊãi³÷›ãK X–åÓcã5ôÏ¿§G[Ó¥ˆ,‘tÌ€CSÂ|\H|®Ò-^?<÷žP_{ö{¿tz¾s|à[´3Vi\�VÅÝ#‚qT8‰f="ÁÚšKpöõªÓét¾©0ÐÔìï¹ë¶_µU1Š`¾¨™¶›v›x Ñïõsœ„Sµ]Ëï~3¨ˆú¶�b§Ó9h»°$�  Øœ½á QOÀæû}†@Ð]`A?ªÀF©¤‘MGWà¬Áã%å¼íƒÎ‰HáÁˆÖ,°£e[ãnì¼ ô­a"–¦ 0@‡ØI„øÒH1 �2jTÑ å^[ä2×U°Æá8YÍÀp|¤Óé<âÞZî!iØàȆ �Ü5LC²#–O{|åh¡¯ÙÕ",Z­�ÃI $<»�áá³ê–C4¾zËmdDv„ ’!E¨C÷fÅD¼³µë¼ô÷ÐrÀ.æ�¹‡àKÑ�D=è!æTÙ†M¬¦Ýþ'ÿ´¾ÜXx˜0€”€„HM"™�q‘iÒÆÑÎ75eˆº2€ ›˜I51°ª‹ÀüêÑÄ#s*óå¸.{�éI2HjSœ‰$�  éV�oJÙét:¿„ Òq.P‚5±¸…K ±}ÈýHÀ˜ BQ�fBÞæ*ÍØÉ— HdÄÙ½íc×ét^#·7À 8Ô™‚ƒ‰ˆcGÄɯî¼þ]ásÕ�Àƒpºß•þyëç �µå¢vîö[ƒ‰SC4(N�EšMø –Wç„ö‰ä»CÏst:�N§óØ!�ühÊQ!S’I‰Qo· Ø¢þ6ÿƒý¯ý7þµ¿bcëò·Ÿc OçmÔ‘- r‹Cš€à¿Øïÿ×ï?›}åÕ¾»—ÿñøßúƒ›=ÒÆK�4F„œ£1³(ͪ(†Á±šë·+6ŸàƒCyZ}šjÚè|°õ N´æŽô�E3GËó¥HGဓMé&5G;f8à qý&(²~1ª-)777"ÂÃzC|ǧòL tÆ}¦=xŠ J¢¹¶„ ˆ-2˜Ä¤ª¹ѬC¦ë‹—ûƒ‡˜AÀ›CÅÕó©¦ÐL×3÷¼ˆL:ú“ü!_êå“�¸Ú¼²Zò:r¾Ý#8 bÜ®vŸ.V#P‰‚ôçh æzLcèkÒg‘äa äœ.Üç¾Ö·Æ’(‘’Zøn¾ qºŸ¤­M¸Ÿí^Bå[ЪÍ£´? a�Ñdઆ»X°šx{L"eS)ùp[ž]­‹ãz¾ÍëNÃ0°& 93ÏQµ¸î+v‡¹®W›Hã~š1º³F³Á eœLZ2Àú€ŸèæUÁ+„¿Ó-¶�Î7ŠÖ}…»QÚÁ¼NÓ¼›ƒBæ=tgužì*­% !NÿÊp›f$Ÿ‹çU e!VT9Lƒ¦5U5‰&æ&‹YêÁdH&_½å6y˜�pwXá(5»ªägOáT—“+c[ vñªw€žçèt:�NçÑ@xWRç�*tJÂ!á„4â %€IDATåj¹ævWŸ„¸Ës,%Í÷¼ÔNÚ£Œ1‹Y ­ )ŠÀL$èÉ}eS‹ú±w2X›âÓWŽ "nc¸L¡ ¬RÖA1úêò²ÜìÊà«QáÈ¡ÑÔo2*¬ðV9¨_,Íñ6ÀQmïqK¨‰Š\Þí<ÇûQî‡}O?õÅüÓE v4?¨4¹³pÒ–uŒ8 !cµGÌRˆF"�ýûÑoW¾O1`sÒYÎ TH0;V^( §kÄP[�ä1Æ!ÖS;š�‡9ùv-²^ÊùÂà¡' rA„‚‚›KÍùýõeüäÕ~ð-ø®_Ñ;�Çò`kéÒö%áÛõ0Íœ,"möHåÉs—Áx9§ …ñÕ#b%N‰邞mÂeM«©TØÊCŠSè&ç”}%¬¡J=cË «JzªS²Û”b’V»Ãìž�&é�X’=Ãñ®Ðó�N§Óé¼ë¸¶Š{¯0¬k ý ”ƒÉ-¢ßÙ �í¿� ¢YV„Hp0ŒUƪÉT|ð�⃠µ©ž@àL�™ ›Î•1¬âP?dÙeÉÛ¤¦˜CT(~^ èkF˜Dƒ¤Ë¢)»Ø­Ë"e 2 *!•õ8ž¼íwùWA›iÀz¥õ`îM¨êÔ  ` :Ã5 K ÅC,¢" 9%L9&šÓƒ5ä\ßiE!fàáÍ&iœbV'ø¸þŽg8Ø�ù|]µ7 ‡"pÇžp& Î>�XC ®o§W·ûWú òæoú.ßňäèÞdÛš¼–רÂJ�ŠƒÛg¿¹ý�ïoy´o}`q¯ |Íf¼½eN… œ�@. ò5þÉø¾ïQP³â;¿wyù}èùMV$ Ä %tsA1ŒklžàzžC àb!qÊñ2Øc�N§ÀqÊRûù $é0Ïõ »Í6˜¦_ü‘ÍÓöýëÐù�v…b¤6‘Ð(ˆ,õÈ®¾ØZÊ.F¸ÔWÓáâÒˆºÛǯÓ鼯iÁæ@%*hN˜ÀWã-Ò àÓüRœä“!ç³�.40 @ܸs�næøQ€ï?_×:»%Æ‹‹Õ?S|’uÍÕ“’BÓœq¾ÿ_Ü”ÙWc\¤ìÈï_òÆcžýbP 9r™JöLÇ»AÏst:�N§óè! wÍ d"$ �™vÐ@„H±ANÅÖ÷zŠõ~t .“¶]ŠP9 hduËz=•Õt™Ê¥ÄÏ.ØËf0W¿œÖCÕ3ó‡l¯Æƒª­=Ï%0$Ü®ðÙ*£&æL”:šÆê@ýN>×W`€c Ýê¦Rîfoû øUp*©'<™k„�æ_rŒ�ËIóê” :X¨.@ ÂM|Ѷe­î‘"hõÌ<‡„$ ñäv’WˆD™¼î%9W¬V~]>¾ÅO׸äÁÜ9ï/6Î ôšøUÎÅò°½Ý¹êY¿øÁGïÅͧùÁ4´~iqw=p@As¯!á1WƒéärãR) @Š–r Ÿ2¬GCk#jš]ÌéðìØÂ$­A™SŽœy¬i5 Áô6dÏ8눔ҕÕZpc¤ ¤€ó@¹%÷ˆÄP�DÂÛ´Óét:­àôÖÕ{ìçDÜÞî§©¬VÙl�‡øðã�n‡�Ò\Ðîõ_û@�„�lªƒ5X!©¾Úæ‚y¾Y/fógÛ‹Õxƒ‡ÒÐêt:oH È’8m——êÝÀ1¾€pýwÿ«ü�?¹þ0ázÐXoìì9™„ØLO6Ç”bd.ŸaA¦ŸÖ›w·NÃÌ‹�e—ºªvvuZrv;Ùí._Ô?ÍyÿÞ÷~ÿ½ïïë �ˆ„´õï±ô®-©{ªã±Óó�N§Óé¾Ý Ñ� T]"p—¢QƒŽHôÈ"I"Ñgñ‘¶V¹[Á×ë8ûäàÔI×NqÂÔ†´H� Ý…¾DF™Qýæ�øÊá1Ù�¯«öF#BÅ×tC0A¯ß ps¬WOow¹Ü<�oñƒ¼~ôšIÇËBDDÄ"L4 aQÌÌᾨº%„PЗ/ 5�1H8sˆÃ‹³8\¼†'ú@”9…$¦É µÒPŠ#rn˜×–¦Â]�ˆ(¢•,2›ïÝ[ëh £;�N§ƒc?Ç)Ôº:lÈ«2Û<Ïu¨‡ÀÓKŒÏðd{ùÙí.œDàëÓ 4BxkÜÄK‡m”=Þ××Èj±«S½™÷¸ì1ÆNçQ§6Üi!H#œùšöQ½ù/_|ô#Yíß^Æõ|;Kœýa*f„”b8X®öd�71{ÕAÌÂñM@¾ÁzÅdQ<Îí瘈ù½Ì‹U-;ìöß¾½~%xeˆ‚Vž´ø�; NéáÎc§ç9:�N§ó *êSk±ø H ™¡Ž_=u#¼!¢Bhkp`qhºùÇxîÑäÐïÄO1âö¸„':Ì�pˆº &5Úœ�t‘puª,Ep"�.舣ñƒ€ÃUpRm3\HñEv@Œpˆ ‚a÷öè^µþýxŸ/ïP ãÝÎUP¥E· —&þbÉ�\7©ýœq0CÅ¡® G h”4Ϋ4Ê”ÜÊ|غò)4]òìz™ œUBÔ…ÇÓÀÄ�!Ò´�š’Jº¸H,ôæ«\K™÷V}”9eñ1)K�·ÿ�p²ÍèƒMªÈ[“[õ%“ç8ú�KÐ)G¤£ÙI�® a$„rùÑRCç�91Š!�5"¨H#I13›¶)¿X ƼÌn{^…ìÎíX�€†×X.$ciü �žÅ+= š'w¨…eÑÕv5Ù<Ï»iš  #h€=EŒ‹Á‹‹¢Õ®Ÿ>XOþ°¸û ®µåøè±+îÿkù«û*O¯±(�AÔ¢ÑäJû¼%‘-BìÀD²y¬·|+)‹Ã‡‚D ıõL\h¹¥&*%d  ÖÊ2Å̽: Ñ’TBH~åø¾ìtDÂk5ÃAhíx:’PâÒ úâlÃûÇ #1‚G©h a‚:ƒW²¸ ?ŒfÛ2:ŽƒíÌäéô‚�U|JhXoûøu:�;¼7¿òvådH†¦”d�}õ€ÛybÎÄCõs¸TÂÐ.Z±ì ¦×7Øl±ßÃÒ.IXoÐû9:¿ Kwz[-`é|§S޾ƒÜéyþªç÷n— 4=XF« râÑv0š‰EZ"Ìħ/1lŠS§Õf?lotÀîpQ±²*.h•CXú¤Ûì"ðúãMº÷r¨u¥ØÒT¶:½º9„èà2EÙÃ̳0 lžæ�³ó*/og¢«ííì׈Ƞ€„N˜Ü_K �ö-èܧç9:�N§óÐÁ)yŒ5e•54²W ¿ÄZªSÂç >+ªIš+çžgù+P#á5È ½•"cNVáÚ¤sLtEYæ$¡-~ÙZOGƘY ª™cÊ7:Bé*‘éƒX©�(Ä,�±.Î-Ⳍñ€wU!* !¹¹@[ 3¹„'5&Cd5¬KVG,õz þs PB$Ä $Õ'†O‚Y1‹r¶”¬JÕé 2¨�©R—+‹þW�PªÆ®ØjÜd�ßÔÞ‹}ýÉu]ËZ2p+¸œmМÍäüš™Ó•åH|LÈ ±vi“Õ’Mé!�uÞrcr?J@ 9�)�<@E‚þé«rµÍëçÛóÅd?_|-§�ãA÷£žÐhQü;$@z@I´Xò-?È–u 0Š,ç¡äºp"r´È|ûͯ5˜cN!ÄО}‰ËÐe�Ë¿ðü?øg?øÅ?Z]­VI�JßzŒg+PA™y®Ãœ>ÍŸí*̰Rļ¾¾ÿÙ'?ÍŠ'O×·7{ †5ãô ¾ZŽ) €û›’UóJz)—VÒO?Žß|ÿ¯þþïþÍ=ʸ‘ŠèZBÀÖ¾ï@q)�D$óšÒ:$â ‹%ä?zPðÎ@åô.8I‘`@‚¨ežQJS¸ m¿�ÇgOo½æÛA%ãz%å€Ðã;âKÿÝ—�_rÖ,híÓÚº¾4†:kM±^á°òV9rZW�¥êQ DÀ¿r\óáu) ¬º9±�¥õDƒ~<“ßíf†¤š£JR­.s:Ä‹xÞ®vŸ~âëÕÅzÀí+\<Åt‹Œ¤}2ýëÅ Ór†²|Á�Ù8ìq™>|uø ­<É7éúÙé¼ÓÄ‘­é !QGä°Ac¥áµÜlW`ųÕ÷§$ùŒz�X<©¾æÑ¡ËB ‰¥KPßz l2¬lT§R�úŤóKàt'!Nº“ÒªXÚŠ×\ÔË—²}Jì�ͧO÷*ð@©D�LÎÙ¥¶ÏDüüݯ¶ ‰k`-!¸XÓjzêò¢ì÷SZaŽmÅ¿u±ú‹Ûuf.û]FR†× Â!Aw.ÂÕ%ˆ"¨’ƒ["’C�ˆ @ËŽd“%$›¶éüCt“Ó?™ÿÕ�j«§’¯9l8¥’…y™r/~o�êèw~&=ÏÑét:�‡À —€¸2ÔÄBÂÂ?ì¦u€Ã�‡„:ÁæÐ„ôevÐ?�EÃÉšõök¨Ýµ•GE–.�–h, >´w`ÜzdS¤e’ÄPñ$pYf7\B‡§È0îÿëÁާ@â@¡~Ôa .uèЖhI–”a‹×Æñ üü $DZ-„1"΀RŠæ*ž"«ïúWäŒînR1hL}\\Éoü…‹?|ùǰ‘¾VËô!$›V F‹�ŸG°Î¾�Ãð4¾µL¨ëýµ|fë‘RÑp‰ð@rnBî ûbøÓÝ�¦ªã8êEHDº¸Èï»é¯EKǽCÞÌ'¾pþ8ÐâìË?©i[™@Qp6ã—@Ð�.ð /åÞÔ{ _1È8íAd± G çñƒg¿óû¿ó\¬¾w½ûõ¶Ø«ýþ6¯®‚<Óçu äÈOúã�ëßu·1c$„ñ;Oþúó|“¤®7ÃnÜ«œÇiºýÌí;†¿ôýï}çé_ù½þ†áúÃÁZ�¡÷MÀ�=÷¬iNù]ÿÂ#w~=K—Æ¢! w¥ˆ¾4µ±å­üôL±d‡ÛÒ-20CÔF"‹9}PoN*'ëÅå­ÿÒóç$ƒæt H$u¸xŒnR�ÉHEB ˆ¹-ÚM*­ý¡Ÿ9.gBÈë 9ææî�¥ß‰/¹î÷û0Ã<ï?ùxó§‚'ï£ ‹ÚþÃ-Æ¥B ly�ë¢{ŽApýøè§iž×ÊTÜËü`^K�NçàxÛ!@ 8¢™È””3¢L˜Ð}Ú¦—ß~_°¨ˆ‡ƒ@(b$<‘?¼|a¨¢«i†ôÁzU ÿD0¿íã×y— zP‚G}KÇÙ¯D³<”“›à¯¢|ÿ8£{­Y·íR+u¡�ÚN>&üÔ|Üú|AåâL® Í“»Q* Oë:ÿÿÖßú}  dà¤S`÷ªzÚ�–9í®±?þgÿßôÃq<ÈàÅ=æpˆM´ \am6Õ¾zÉÆ»CÏst:�Nçë‡"N6Ô°ˆY�Qf)bE°@—�ýÄ7(’P ¡EÆîëx\Ú,â^˜öË(±¤J¤É´ æ«õ­Rö:-h„“‹Áw(0 rÛ"ïœÈ„ã�ŠÌ õ„œ©F3Z ïÔ�œÐ„ø C3Ý}\“1zh­b¤`D�ØÇœ®ô[ãê{¿óo¨‘õÓÛJj¢`çm>üÑ?üäöO_^ï´L7ßý­Ëùo~€«L`Uî"ÇF˜²úÒCD¢V�³pGÎ� ¼8¼|Ûñ×Î`ZËäP—›ûÕæÙï|ÿ¾÷ÁïZܤl’Ê\‘Ós�ñÜO�D÷‡*ówÿäÿò�^½¼ý‡»éƒû_úïþkùߨ%gî¦Yd#Tçzaó|ýÞö;ký‹?Aòý–v¡±A�Ķ­‘H‘ÃÛ'8½ž½¸3‹½w@€¥GcÉä~—@¬¥:x/Ó è骕¢rSQ6H6¦ºV:ÝápF¢{y¿5‚p“*¢Æ»{žÃJó¼/õúŸÿèG?ýx_‘gZ‹Ðàà„Q[vPZ?Ç1–=ìo®VÖ_|ô�PRþ¶ ÷I.×VK¸J$J´m1�ë°/:Ÿ©ï¬¶Ú®/xYÓzX¯¦Ãu¾Z�ßB³Õ<¹ Š“•ë*b:9ë·6hšj‰jSRzLµÐƒ¥¤wziñގ1š"�.ËŸ p„gá&a#˜S0c’›“7G–¯l/¶³í×é[϶Ûo¥>Y 5ží_ œŸåq¨6#4³0ÐÏܾ \ OÖé[¨ëš°Ÿ¸•aƒ}8KêF"„ÇËÍ©MlÉמÄÔïur4x¯î¸²¦µÀ£ƒÂñoH\z3êÒè�Ô®Ôi¿4ƒre.ÔB‹å×;o3q•–zGP¢.˜m ¦�ýT¦yŽâëš.R¥h<\žCŽ á’Ž¦ ‚Qn+׬ I7¢ŠjÆò¶�_§Óù§Ú"?Úì%̪™™E^ã½Ëßøwÿ�ÿh‹ß]áY HØïß`"€9èr(²¬Ô0¨ƒ…-º¢D ¨ƒk¢«ÇªæfòV*Üp{}%¸-‡y¿»�›•|74‡Þ„BR@f IŽ2. æ£ÜÏùqð&hªgÿ~³Av@LÀr Ù…°BnûÀ.tz ¶pðã‰Ë •¥ÌR@¥×(>ƒîŒ¦°ÓÚœ%À#*Yή‡JÀtŸ|¶Oe½ZmÂò ŸŠ´ÿp|²Í‹b6¢È®r0è—nm²ZÂIˆ0§Yá€8Ï–Ñê<Ç ûbá­·#§U“—÷AUIzÌã¨.vfž ðW/_\ßÞT0Ö·ÓüQöãŠ1åqœò0© Æ¬™3 Q«Š‚áñút¯I¤²Tx@’à R“±šRLêU°7ì2nâWîÄÙ¹GЃnÆ0q=JŠ Ef—9q5æPŽ5Cõp˜ìá´-Â[ô=ZÖíX»y¶Q_“´ð2§jžl~©X ¬½¤Óéür°Ü‘Yš¼}™Ý'”ax¿£ø †M`x°§oÅŒ€™ÇïûŒxF dEº}¡×/êåÅÛ>b�w™vó ,“´¦>Ф‚°%É�쮑õ�ë<š¬è)´~7g[Ê¿¤‡„óór�ïêÁÃAYÉ€R„,¨P‡ŠrTÅt¸9Îü`Œ¤µÎµV÷LR„íè~¾¦@ç1Òó�N§Óy‚pÊIdCP—Õz}åÀt¸ùñÇ7ÿ»ÿÃK¤é nX¯¨gnœhzW@+ƒ8\pPÜbDvdÃhPÔ'Åœ"€æ`&!âb¿�¢q5ŽÂùãO6³=Û¤ÍÓÕ5‹ËÜì—›¿Ùk�ÎÇòjމݟ4Eω̟f©g+ßÂVgªKmnÌÁp¶j#'ÌYCâh ûXðª#"‚YTÝÝ ^Å$`pðT§.q b@sTÿù£„¾ÿœߺýdØäPÔ˜óZ®†®m�0º³¸ÁÚñùâÖ*H"X¤:ýèCÑy[1"š§ÄI´M1‹ t5®rZ©JÌkõ— '„gŒŸ=yšR’Qm”¤5áp˜Óäädõv®fÅ,ÔŒ�Z‹+m-VçlŸ  ãh¶*£úm5£ù¼W›ç‰ –àGa‘ˆ£©F3áhö<í¢ 8ê,/äµ61œœÉï§:–ç«€ßKrâ2SžKž˜ÓR&Ñþ�·…ÓƒîâN�wy¯¬PP+…vpsìÃjä‹M能ct 'œ�V†J:‰"xñéKdeÊJ{T%o‡Ç”tït:rï.á‹` 1{̪ªÈp¿½qàBp\ òƒ¨V-7©öm:¦ð—òvÇZh��2Vpn·[`zÛ°ó®óz¶àžµ˜€ƒîXº˜t©¤{�O�ÏŽ{ŽkÀÉõúµ}>þÖ» = ³PèPiN{KÕ_›V·®–“Á uðá.?ˆ’"ÒÊÙÌ`fµúÃ¥v;¿zž£Óét:‚S@š¸®áÙ�ûW·Qƒ‘/‚òb?pȱ²Ú«—à¹Þ‚ÞœÁà£yöPè&²O\›8%¹dóÁz¯³@r& ýo¡ã0Í)ûHQ“N1½Ü¿e"²#Á5btŒÀˆHÀÑÖ‘Ð\)gç-üž>Í9#�tœÿ ØŒÓ%Úƒ1 F´ÝCÍôGC$«’d%ô(& ÝÌT��Yžú“)�ì‰g¿�Õõ'(‡5}“³lÆo› /_b¿Ù^‚-ˆ GAìË­üHRÀݽz„KDDðMìW:_31°®ÛwÀk&تt÷pG”2ÇÁÌ,<æÕz‰Ÿ5‚ןÝÎf^÷äÞcÒTÍ0±0$98Ò�Vû}ˆ¬GU· Œ3·OƳÀ–¤Šî×â9ã@–ž7÷¶Æå©aÿèîØŒˆŽ’ÌËBøôk€ @ø½î0o¥ˆ~gV$Â{"{ޤË2dÉ¡(öÀ˜ò¾¤=ÜÉY±WTÁtχ¼ó6X ®3àq4l J©uX4g�”y ¢8WöpyŽ{P€+"Ö›-‡T-ju A ”���Ì7µÓéܧMÀÌm2+"È:"å¨kà²Æ*1;Òùør³,·™;C)a«e‚aŒ(V_­Æ˜‹÷ÃÎ/ c™¾ÝgÑ„\~£ÝsÝP�‡;÷—îÌ6g‹cÖqÙàTÙÓ´œ�Íñ qb–˜ ©u§:àáýÜÓò­õÃì¿\yÌs¸»¹/™�~‘y§éyŽN§Óé<­™ ©S:4Báz;í«©"“�j1ßÖ¨:Î!åÜ "D4|(U,Dd ×°P¸„»{î¨�È•´$‡z›YI"õ°ßÕ0*‡q�œœ6 cÄÊc¾ *|1BOùÑþ ("ÅR€"g�Ç æ9c eb™t‹Ùc@dølà[à2°�øèò¨² ¦9­@Ÿ¦išjJ""îÑ`,}Ê8êü’;£JˆÓ¿r¤UÁ�D‹G­Aã8|Bœñ¶`fs†þòíÃÀ, -^ԉɅ5â�^Z¼Û„À×˲�TÀÚ*Ô¬D´‚, ¯ ‡QsÞÖr@d`écøù£I‡Õ¨SËë,¹µ`$÷·‡ýnÖtIÏÅÒᶨÆ�ˆzæö LÕ6 Õƒ–5rBÕ8`¥"1šâèÀº…´Ñ„¡—ñÔ2v’½kßs®'!<‰å-_í¯„P]þʱv¸A*0(2/�k`Ÿ ,_Û´²²2d·ŠÔW|o—ÂåxRùQU*pX£ìkÑÐ�§&é—— É�£yÔ/ʨû¢5Jñ¨1æ5 ˜l¬‰ýêÙé<"Z#òýæH€.)¸xC ‚^°†�Ðt Ç>Ôxÿîvê;t‡¤Ö†™˜j}•WûwZ·§ó¸qB gD“Ò]r .p‡K[EjUX_ÿ(8¦øéÜ?öóÞW†4 ¼ÓE')‚H… Ôhîêr’·ä23GÀ °‡ô:]N"¢-(RJà ÑÛÆÞezž£Óét:‚H¢f5+TÄwÿÚ¿ôÇÿõæ®îá)(ެÅLG­gÆý�˜cV/EÙÛ|3ޝ4æ,ŽœM’CQ�j¢ &ÉDâ”–l€81Mà *“•빸Z­ËÅåw¾ÿW?;ì˼ÉOÞ·0Ê¥êÖ!Š_�6-�€$Ž"2ÇQ‹E T_«áI‘EpKÎE‘T¾8"è�DDÀà¤R©T}Ê\®_Ìòþ„q…!uS"™op¢Ç¼09/=1ʧ-‹ÀŽ*£ C„þ•#¹Òþéz|5ïkÝ­×Ooã (S¸Fk„�MñlÚ—lM$¢¸‹ˆS$Äá¨ïôÒâ§50é²,\²V2N6Ðź£Tc(�ÏÝ|H¸ZÀ!uVD†)aˆ!É嘞)/ÍTe³Däüžë¯#!u¿KÛgR°ÀýþýÍæE-‡Ã!¿÷ü�@J,À'€O�ágä9pŒK5 ñöjI‘°ãËž PŽ~ã-5"ÇÇ%e».€���l/2B¾�·›W•ùj³¹vÌo`'Ôù:iŧھÚM¥@Ògø 6‡éÕj™Kžl}7…�+ù à�@Fd g@cé²r §Tj�T!Qî²íqÉNç‘rob‘’Ìó+Ìs}¾¾ IV¼WeþµÓä´¶ÙzŠP�€[b·Ó8Ú4ïî¢À�Î/„Äç£À0 ¡z+‚RP*ÓQ¬í� º­ëNºjñ¶Âf«÷ ¥Êì�hi÷æ8QŽ4Z�‚PMGù¼åBsoÅ% y¸ég’jD¸»ˆ¤Dfæ]¬õ§ç9:�N§óõC@§’«&¶YE]ó÷þÍ?XßÜÆa/@¨PZ!‡Ïâ&çöù=ÈxùÒÿä_ܾºÅ.ŸlûûëgO']9Æ¡& 5¤8‹ÀsÕäÒl®›×E3šYAÖ0 �s¾\oÆo÷âêÓa\ïë§×‡›dyòW�Û�dGuHFˆV„˜d‡8ðû#�À x%f‹XL‚ÅI?¿…øï�d¤¼t+ ªc ¼šìf.7Iëåå9ä„a©Éð2ëcŠÉ3\è§ó!–nq‚±�/Â&ÇÅ ÄcÓnUìCnA%÷ U@8UàŒÅI…X䪜‚À™ÛO˜ÎÛ!ÀzÒÖ+è`}=øÿ: Äù‹ÁÖ Å&VÀ;µöä6yºÓ‡ÊOšgb2@†Eš ÔýímÖ›¿÷OÿŸ|úê[iÀ«ëÁPùh£ÙÞL«Ñœ0e±Çt 9Ì’ÀIª’@£Ž?ÄM§¨3ã Q„EˆzR§’#y Ô1:’ÀMÊœæW«øìéúÏ>ùÏ¿Sn'Ÿ¸áêÉ8²¥j;o !ÐÜGΠÀA7Ad­ÁÛ¼Jºƒ;b¶r±Ù<Ü[Pè:ˆÐ»p€ ]é08óì£: ûõ³ÓyLœº’›Æiº×Vá`«Í9:@¯ûy|Íð¨×x¼B´Û�Üý‹ T.N¶ì~§ó‹"ËýHÚ²dé6¤ßÜܨ€Ã9#¥Å8æd "±ˆf- £ "€A„*’Ô‹•2ßîÏUx~Ä4ñå¥^'‚r”íº/�z:Nwm^`Ï¡Ä#S@è|=ô/>}ú-ÿð£ŸnÒþÕ'‚�Ç>ëz½¹�p³X‰<X5 i±èº/ºa ‹�|sQA΃ãɈîç�sà$( …Â5lé­–Å)Æ\˜qÆ–cI@¹Àø˜úc~½`%nŽ‹žSÅÛñíXb1ÇTÄb]8/‘sE¬AB&p‚ìÐÎÊØƒ%d Ä]ÆñS{ÎÝ~§qÇ<{ m®êõ«yò“§?zyûjÃýÁwÓVò<Ê�gPõýÂUZŠKù^Sµj!’D“YæJê°Ê‡²Û¬Æ<×dE§²Õ`ÔØ ³°*BOLŽdH yÀQÛá2ÝOÅöõ€Ëç«çߵ݇µÌ”M¬.no¯-?`œ«óÕ„HHkìcÖ¨´’S†íw¾óÁwŸMWr±ßO3Ã,¯Ðt#4@]ÂXr0OD`åˆëÛOÿô‡ÛÃ0­4IMv:�Šö�l�’M|uQ¯:éöÜåJàÃÏ'¡ž£½\œLÇŠ ŒÈýJÒy Æq¤Õ¢míóÕ§� ‘Ξí½9§É+–Õâñ“Æ€Øuï^Iˆˆ‘ä»]2 Ál2$´žëpƒ6ÁyM Uï›ññþáëßñÃÙù™<šH§Óét¾‰ø=]£îU\J�ì ŠPa,´œq)>œ¹Ùäu°9V¯ª‰ëʹr°õeÚ<±ôÄc�k$XB ä`Œ*jŸ[§…(¥P…¤!ÌÝ¢:h1{Uü†r0¹±˜_íþìÿõ�ÿÓ?Êÿ¨ÜÎÌ©˜‘ÕÓº³ògÅ•š¿ÙýïI�'Z„Ȥ€ Ü⋱v² C|.Q-t•8ì?¹ù'?þð‡—— î¦ò™`ήÁ=˜Qž­ ¯¶4C‚"ÑZ^ÐVÚ8…KªCŒ”3ë¡TNÎ%Dð˜Ó„6iûV)ÄVE]r*<·ÞЉ‡[æt¾?f+ï#÷2rדi½ïA?³¢Ë¡Ò2càqç>(Á–#k1 ©!›˜Æ™ÛŸ‡á†K~æÙj=Ì3j9¤Á%&¯Ž¢›y{ãÕy€êO‹¥%ǶØe¶oóvS=\”yU#0WHÚoW(iÚnñòz�.ñêz›„Œƒ—›˜ŽÝHíÂ" ³:¼2E°µ°Ð=j‰9�†qör¨+#À’ÒNÁ^îö–YÞ86«åŠfÕÍ…±Ú\~ï7ø¯ÿ+¸z¹k`5<à{F‡ØÉ) .wqÉiB8ö{þÙŸÛGÕù µÜ×â(êt:oÆ}Ä„HÀ°xþ¶ŸÒ@;*&ø•ä)÷ªîRÇ¢¢!0"2Bß ˆ¡ÓùÎ×ThOëÔ!åR'› <¨ #73i+ÿÚGAeÂA!)ñ&<ì9A†‹Õ:T0$Tõ�î¯e@ È@:þ÷ÜæZ-"ïË´wë�úiÞöé<�)Òét:�o ±x¦…ÓƒÞbÍ­)÷Æé‚$ÅÁp‚¢Ãõsç)"<²‡2†¨è4Üë �°J€Ui4¸Ä¤, —¥7 HN§ê£äx²YW��b1ë>üì¿þÉõ?ÝŒCЦ<�X%Ëc Tuÿ²©'É–Ûð#$E@ôp,š7G脞¾¿?f aª®¥JܤaíHŸ<{ÀzØgu¢fGµòBð³�æ¯娯!„ƒ¯Í/›O›Ò¶%®¼�6jpí€aÍX*!€Çˆp_Ž}<1€'ÈÙöq_4·ó+‡ŽÖv€S?P ­ê='Õö›‹\U`ˆ»ÉWŒEŒk`ôƒˆ€Ç¾qߺ¬#¤eZH7bIÊž³ý"2)(�€ß}rù;ãJv·»—/¸Ýa‰ê3åàþç„f®œ£�­ãé˜S‘W/?�€«rXaÈ ä n_ÔçïÑJ­.>3êóËõ¬¨Â LÆDfwÂ6Ó†C�àáúf>ÔÕ+¼oñÛÏ®6ƒ”ÕTjí o‰&Š"Â5Q%œ§ÎîsÆgß°�¯‘NÍ…CT`wìYTHZ>•áX�°’±yy;V^„Fd‰~öt:�„“è"ŠÐż)Ž�4 ‚2óRsóðû$ØüïQÑàýi`2| *zÝIç—ã‹uiÒÚÉÍë\°ß£Ì`ÆÎ�]gå±Zêk�3KD(¨<®V(¨¨¨5¦É¦CLSʺÏ­|¬„†kS·Æ}ïõe\Þ™8~ÔѬ[UÔ»œ7êü,zž£Óét:B•»y¤F‹ÓˆSLU(N®pDõ¦E†Ä™ºUq"lŸ8ͼÆ`‘ÃÂ<`Ag”.Ñ ™¹¤Žr¨t†-sÉ£•Hkº0�«:¯Â6‡(Xo°ªLâ³é$i6ÜYGJœR õ‹ûzب’¡.ÜY‰aæt%cñ*FXDVýâk°›,%ˆ¬#åRtÞI“fv˜^Íïm¿=�X‡ƒ>Œãx˜U¶DŒŽh³wÃ2�¿¿Ò8u°ÀÈÙçƒDójVa"ÔXŒÍÎD€Ó5"ØrQUF…×3·ß^ÂÛ>†¿æ$DÒ—ôp,u6qãtÒ…;c”ã©(ުɢ­°’#ŠHÁ"è.! =oËÇÑ˶ ÿÞo|o´ò£››Qz¸�œj­yÆ{5øé8êåFÖž ×�c3!¼_EöÁ™âã0“?yùòO_|<#¡*Êô7¿óÝ‹‹'—ÕWQ„¾«‡*(‚ 0$³‰†AöF)¸0ŒNѨ£ïS”Ëï~w3g¬ß[]üîÕåo]ŒÛ·Ãù¦î� ÈXún�ÃŽp �ˆ”jSåȲEIb|Ƚ‘É€ŠÈ¯-'§ 0�åPëµwºþ´ÓùÆqß#�÷ݧbéçX\� PÁT‹ âõªœÌ´TDZÈDN–oûèuÞeâ‹Sú¥w ”’5]¬ #$�ÀjJA­_¬?ûzF8–:€V&pÁ 0$(£¤•¤„ðZÃTìÃø«ÁÅ´–`ê¢!uZʱÂìÞbñ!Æ~=ù¦Òó�N§Óùú  \Z'‡«A]Ô% 4S3öU+m ËK×üWÇ�“syo|%©R§"áã®;ãžM5@KÕ´ ɱª`¨9LP‰€7Kj©~ #’ ƒªxv1þ•ï}ðoÔÃô²ü`_ܧ4Ú�…Qh5>„ ¬Y#,™¿X-’†µ¨&Us·ZÃÝ¡i¿Ÿ))‰Reñ|ôpD1~‰?k*©À*醫•°(c†õÿêïýG6‹é‚†dߥ“¯Z ydDºíjE÷85JD{d)çñÁÁø\ŽágŽb`ÒU(´�pÂt2©` ¸Ó„SNg¤ÁÁ�3·¿¬´»ŠëÛ"" FDøú2µ)lT ¿1‡£ãܪ·%¿É X€ê‹ïaj4ÏszH€È çëÂ)êE�Þ/+Ö„´ú7üÖ÷~ó3«ŸÕÙ¶ëL Oõ[“fÇgC­ë|˜ —ðì ‚€Nña¸qU‹¯V;à¿üã?þû?úá�\V­ñßûþoþ¦óÉ++«D‹jUP]’K6Ì®¯ªHáEÁ: äØç0x”³¥õ¸Yid¿YÏ/½ìT®úªámÑŠ�K½)†#œp (AG‚®ÀÜ*³˃í�‹‰ãŽ�À8$˜#%ŒÙPÓ R­ÚámÂN§sŸû2ø²´tD,7ÃfÑA€(@ ð!µ <íÐ^°@Ž`>F9µÕ^¿íC×ùfÂÀþvwµ^ ˆÛnnñt\Ê­j ÑÖj0¶v÷»¦óã>¹Ã eBÄ6gÕ´Ÿûëémª_Š Wñž u([žãÔ¨Õ|,�v9 }°ýI�w=oÔùRúŠ¥Óét:_?~¬ªæ}¯í&Ä€„5 Fœ´0ŠŸï›ê¨Å‹Â,fQhBx óRŠe7Ôà!ˆB L.Žð*$tñÅØ‚D ‡H «q¶xòÁoýõ¿ô¯~ÿ'¯þ´L·²_otDÌ!eNS£Ú8˜2ÜÒ.XyÍ­:D Ýq;}zsøá~~afáão|ç¯f\ä´Íy%LØï¯¨OKýôÕO·O.Å1ìë·,©c}=íÅe(Œ¨P‡xp(U/Ö“ÄÎ<�ã�ð§¥òÓϰɨ¾~ñê/8O°-³îoWYšçP aPÉÈ¡ *XYBxŠ¢QK)ø-a¨›&·ÛaôHù‘Éàý:\œc|©h†¸$Â*|‘¸.�LHº~(4�pÔõ_ü!ƒDÌ–³˜—C=8Ý �ÖØèâ9P…2"À¥Ek|¾ÒòÁ&Úó¶—‹ïIsxºË'-÷¦Ç׌‹ÞGÓ2,·O ¼g‹lÓ þü|£•’,®Ñ-bΩ9ì2¤W ¼mx¬—6°rÉp¤EÆj©4‡Àò®²úá.ç�JPÅÒð  »C,¢]G´ó Bx[�Z¸„áL Êv»]Ÿ¼øäÃÿçÿãÏþá>¥•Ö,%/|°óß…âÍÿb¤ÖQ‹ž]¬ðѧ}úíõz=n.6à;~òp�  5à@p‡œo 'øEŽçC(hŽéÏ2’c;¡Ë­³=»˜  銲?‹žçø5ežg)%fÖ¾WU÷G7•+´ã "9ç4a3Ã#kmkï�ˆˆH3h6fæîK41"ZŽÈ›Þ£Ý]UÛfqÜÚéÁóQÕꦚ•êî!ÑZ«»‹¤ˆ0 s™¦IW�ë Ÿ…™…™8©ª9çyîú°?äxAi® F„:¢9“W<Àãü"˜œoH‹,¾a]¥áó¤Î‹´¦­•'.[0šD…3Ùš@%ªÇö×Ú¬„EawAðæcMÄôÉ‹›ßzúo}?ýµøn!\<ÿÔƒ-+Óbå"ØÌÃ#tZ�›ÿÎßÿŸ¾ºùq‡r«yúîßþ�ÿGu·óóZAp …�K¶ƒ³`לѩø€7‹‘ÍúÉï w¬.×»}á^¯"BDÝá$SJd533cIUmŸ}3+¥ Û\èÀ—— ñó!$tŒçªJiERhD°$È(BM`ÒWpJiµñ0ÂåÜí÷fŽ_˜Ó}*¥$L"‚wo�سñfï� yH`1ÚqzS½¨ƒÙ#¢õ\4ù3Æ&³ç@N¢W6�F& ß‘{ÅwÒ³J$¡™ypþö’B2/3Ü¡‚1×ýaE¾¿Zù\$ ‚k%3ÅâÖSƒeVˆk®"AŒRl¦ÔQ)û[ÏëW«õG—O_^m?�¦ß/$a¾ÙoÊ>i)µFÊA¡'Ú”¬8 i”vŽÝ 2Œ5*èa&pÕÁ¬©‡|=åtª¨µ*@²”)áÁú¾!.R #Ì Æȉ9ʼ]�´ (°)ck­xXïøÐS ¶/’h÷s:.ÖøÔŸ�OôÕ'²V]�žæb0V�µc.¸Uª2! �`>f¾qÔí~ ¤]ÒS“7D8R rz¼Õ6Ÿx„Uäšjæƒy¤!#e„È=!_š€<+MÎ6£úÅàé?Ñt‡P("µ=qîƒeddbø¦¤”*ÐÖ]mu†ðv|<"TpOî�p„‚káØ2ý §„5cõÀŸÇ–Pi5+#(@òñÓwÌ€ \:8ß‘Ð^3ä#Ù–ºªÁ# ¶8ÐN]àþ„ÿ›)jFªlýˆÊ¬E‡ƒÑ(‡†|øø'ï�b”Uavñ‡Œÿ˜`R‘\Ô¡áH'BYÂñ™gÊxµÚWWc­ͧÈL‹üð]º¢ Ciº„0!D€ÒŒèäX°ö°· ,\DËç4%¨jÄÏ\öÅÙ+Ç_`Ä)µ —SO—C±ä9¦æxV=gY§&NðÓ®�ªz PÏó< ¿¬MÏsüš2 Ãz½nq‡q¤”ÚÍømïÚ¯Ž  pÁìĬ ‘6³hrÂK‘ù°Ÿ ²ºØn·úÞ{9aÖÇr)a@"Ížc˜i•Rj— wWãjµåb¥W¥ºWå›}äO©¯6GWÕ‹‹‹Ótí ,ó6 1ʤBøº€¨•fôÄ�‘hz£Xã8º;-Ÿ´ZábÈ’¯ò&±äØÌ @Nb‚ì.þ°qƦK#@Z ‚³&¡.ëժälª¢’RZ­�ÖëÕê^Ñ_çW‹†+ˆ—;"•rQSÚ¦Íó˧ßYévR šÔLe`¨ZTô�«2×ÀÕ™¿t@è t� 8}IŸjTþñ WdD˜{ló·/å·jº\¥÷-VÈ=XHBÛ‹Ç]¸wVÄø¥ç›»2È¢6ÉXÉH½j™ìs‰T Ç�a†IW«4 C›ê-ŸÓ1]ØÅjÌó<¦ôˆ¬ðRd‡ULgÊ2®²+Èv5桹¬Õ)p—:%ºzz×K¢í~ät—Ùê ‘2ZHä¼ÝÞ’ó<«€Ãˆíöù³gu©ž~UéÕáº�ÒvL›ÉG�ƒ‡m/òÅÅz뢚óa’ÝÌ$Ò•>”R˜W"„D‡5âgOº$"AîCʤ`¤õ¼¡s‚»VæˆÐ¸˜Ø^NÛË�$$ÊŠkâéåú½3<ÂŒHôÜ·ÓªÎ$äá–FMNÉ’†»ÔŒIë �aZ %1 ðÙ@ÖÛÔ®Ø�ŸAÐÇÑ׫Í4�¢§=�Ça-ANÔEOÿ®wíá|È�šƒl…†ŽcAñx_@&—d‚p'†Õ�B•B£¹ì„£,�Zuv» Û±¨ûÁK‹ˆ& Ÿ¢ÈãÏj{”…Ì­èSªdq6§¢ã{Äå>ð’¿�r úñÑ"ׯwRÒ3"m®�ÖçN®P7g-ê&¡®â’«†ªŠ)ëÄ€Ù8ŽØ?*é6!pt#¯KÃb!6)­D$as�Þ{s_V`KmTyª0iM–v÷‘ôw¨•CD"¢Zu÷”RNÐG{û²‹ÞpÅa¼ó`Œ@fˆº°Õ�<²ÔP�¹Y«™5|Ãz;Žk¹�űªUÃÚÙÎH.•j-öþ‘m£À“KrOîºÔìÕs;КV…‚1åœ[@¦E~ÞöA}3$[g«j#q¼:% püéƒÝ”‘¥ž5˜R2Tõ+‹üÁF ´:àÔF°@³†Š”’›«4Œïîý´ÕY6 Soáè¯%Éúh¯µ�G�¬V«vz™Ù75uÿ¥gIr\&:AhBÎ$ÝÝ$5g¤„A†G“çhk˜1FÓ¨H§–Žön&¤œ³r)ÇÀœIÞØGtùóˆ–hM)µ+Ñ—q¼Ë†è²ô%ɨ*¡È�" h;ÜÊT5'$ÇŠ+Qš€Añÿgïßž$ɶô>ìûÖÚÛ="2ëÖݧσ@€ # ƒdF3]Œ2‰2þzÕ‹þÉø¤ÿCOz’d’™hšô"ÉHHŠ�£€˜ fæœîÓÝU•î{¯µô°Ý#£º«Ogõ©èʪ޿éÙ'+2ÓÓÃïëÛëû ȺÎé¹äæ<Œ´+«­{9gY" "P¤œ}h->?"Âa~:NÑ*†)!眭µC;ÀUå¥w¡u>eI–óÅ.BD�_9NsÎ )%M͇Td¼‹…Ðu])à ë۹Ϛ´û·ª¯_{¨yÖ9ªzjk· †!%Ùˆ<¤[f¨ªŸu¶a@Ç6¯4q©Å‰ ƒxÀUÓƒ¯e½?PJ¨&¬p¨Šõyl™N‘3sÎ+MT‚FVh›Ø…€»Ã�%gddÍ9EÅDD‘ßhýOóNÚÆ0 ¿arIkćeŠ<“„c¤¸Ís‡@^/¦!¤ªÀ yX> h �ª�Ê´>DÊ›¶|½Á›]N  biŠU¦æŒ¢ª§³“*$c¡!à’N#�Äf3@¦úf'ùwJÊ9•¶£.·”kçÆZ—os�ÅEkÀj›ÀND ®?õLo#"!üÞìEàÍlBPói›.=1ô`‹»àÊ,%˜¥¿'a1­Zu¯å¿Œ b„oá@Æo?[óÒÌáI(ƒ¸!T•! ¨Uª¨ÈŠ÷éá:çÓƒÞr¨ö^Öß‚Ó�ZWë…»ìÞ±då À C Èô®ýþâ"k …„ `Ê,”V IŒä�œt¨¬Ê1ý­�"èÙ áiÍ.lö~-£<è”§.Žœ—û(¿»ž¾ë­úÓôHw��vœ~§ÎñƒÇß”¯ HäòT¾´òÞïëéy ÚÝO²ÇoÉC*Rt~XæynÎ$µÖVÀªµ¾Ùüß÷œoôs"é¬^°ŽÇVˆ Á!b>‡ý>"?¨~˜”8Ä0ÏÃlf§nÓRÊì3¦#t®ÕOý&o&ø·n6›”w©iššàñºM?‡µ =щ–�‚y‹RŠn"afsÁl8̇ÌTÄÌ¡³˜’˜Àße?‡Ž¥³lfa¨µzmž#z?Ç;CõT�X,øÍûþövÞäIE`gý�ïÙÏñ¼®ŸƒA¸»‰Ïß•vœ¶[“yžgÌeš`G+’"G°ˆ ´µ°BNΊÀ·íoM‡k�R$›¯Ôêɪ ™a‡H~`=æGÓ4Íó¬ã5#Ðìª4MÓDäR&Õ7ÖM/Gª£VÔZÍÌ]j­µæ\§iJŽP/¢. ³»~ëýo‹oôs"9t4×ù`ëq*L�ãqº½eÎù“¨ŒZ,\9�óâ5ˆÈ4MS�4¦2©;ÜkëçHô7zÒ©µ¶öÙvCÓ4µ‡«×ý¸DdÂÉiíç0™•.3ݵ"M!žªó<—R˜6Qk�€Cà02ܽ" {ý¦uLµV˜ ÍÜJq›eJаÞÏñ°¨µ:7:Ï3%vóó\Jy@gáo'€Å£’páÀz™ Ö MÝÎw³8ßö¸È‹°‰&0œl«Ö¢ž"á ›·~t2šk†p�»© :`h!Ò»Þ—Ð×íú Ë­{ËäX{e&Lúþ¦é~k?‡Î ÕcŠ™óF¡Ç#g«õý9³™µ2Öàh‚àû]×~g´-)"03³ ÈÃò0ûÖu^¾˜Øä“1þaôs(eJžÜ!‰få*€i¶¹d[æ<2¨‡Ð†¯\bÌp$\ã¤óÓNÂH¡;‚ 0$¬œ§­2ú�ú½i÷ü"B§™ÀÌÞå%ÿîc<¿œú«_{„¹Ws`„÷÷zŠišÚäû6uµ¨û¢ô�¨¨Ý9ÇÝK)µVicJÉÌÞ£©a¿=¯õ­Š9kÔ9n>:ÍŒ$ w?�rssôáê´Z0·¸ íQJñã±ÆM)&Ia‚ù�þDk³Ýlš£‡o×Ã^£sxQM¼DUÌp�C.[m'²X÷Æi¡Ôý´ÏH3krĜ޽o•bÞÍó\ëÐæLÔZ�G/iïþ€|W~lh¸Ìe<Û‰+ÂÝ=‡ãÍÍÑò¤IPN:G©ïFç° ÌÌ5jtªµž{J)ó<ÏÓäåPç6Ûë\çˆåͲúVÕ×îo±ÝnO µÖãñx8Þl a$D®…Vn\í(ép�J±e~¬Çiàp8¸•y>>0�£îêU; ¶Y9ó\Ê~{ã/Ë„æâêIQ¬ûV]€oñ­ÊÕênº™Öë颯�7"2ŒçüyÒ9"Ñ0ÕZC£Uy‡Ãñx”8Î)ÅÜ«QkU”7*}’DZ)1Ïóápø‘€DŒD=÷­ò9èb‰SèÁÝxv¥”v´ˆRÊ>ps³§›�a¡å!ùVñjj­â]Î*ûýxð›î[õHÌsµÓ4i"ë¼-õ½q« ·S™<*‚êZ_gý×ô㻸–uÖðÛ‰X›œÄᨂJÔ€µÔq¶T€h­io>>]ÍÓÌkE™Qªo ñJi¤mæi14»9^ÑQJ+òÔ³ä�óô¤p¼Å>nßõFüÞ,:Gù†Î‘Š ¥½Ø„©*b¿¿*òÞ§ŽÇynJ?DÀEI{x2ß{B»4gÉQJ91<Ø4ªWÏíæ¤Þbª·S>~H¾UA˜&­Å“ Â21”ÊêÒÜÛBð4IÊ©§)|ûc“)€õÜÝ ).ndƒ D!„ß§‹5,÷Òî÷b9Ns÷RÊñˆRJúŽ'Ä‹&t4ÎÖ€ŽðóƒÎÝ£Va)ûÛz¬ïïõtÙþ'cü6wó·_l?~¤œLÐÚ 2Ö|éoäþ ¶ÿ÷€9a ‚f‚0*[ ™™-ªÍ’~8ÙgŒÖïx²¸£�,ÜÝ£¹ .î\æo6�äd©qj¹mÿü–H½“oUÄ›�° "ÂÜà7w%ÒÒ$¾‚ÓW£ÃŒŒaq�Dç€îŒˆG+ž¶¶'®¡ô¥@{£è;#\ÙnÛNn®Šµ›ÁÀ€�cÙc�#èÍS­õs„,màç,¿µš«F´ÈÓöEÐluå´ 9 a¯Ýßj­çýªm ¼q„W!k­æI°F¶5_ŽM³Ö0áÞf‰>¸ž«—>ÞUò)¥XsÎ1ƒ0 3zÐáì:ÇÛ¢=‚9ÝÃ,N›4y£íáf†0WÇz=}8çO”ÑvñSM*ß¼¼žŽVs{#—ð¶Ö6sKûÑ·è‘a„‘a0hfôp‡;Ì݉¥?ìd1íbÚ‚pIV³é²L¸¦–»>^ì–¯é á€‘hwQëvX¼Ë+æy¦²Ù÷w^ ׋�™a}|�&'•2Õ:»;›é‚¤h¦kPÄêËÿŠ�ÛâS}‘:Â’ÑÍÐ*ôŒ]àkZ°<)<Ä�Ì%(ÀÝ«Ám²ÓYnóR5 YpÒ¥Þöh„Ûö-D]cV2d\cB&PÁ–�\-�ûMˆæ[enN3x{XñöÈäV›aß§<ç6 rMÏ~;æ!?fîI3«ºº/½²ž¯ÞèÍ2b6¨Ë±¿FÜÝ)4§Õ9ÕjÍö}Y=Y6fÃOçö³cýÉà­Âó3ÿé°ÃërKí:‚tþ$uìî©‘äšwõõ³ÿ+‡ä}9�¦ÚðTåÿ–Ýðn®'’W.=m­wÛö4!Cäîøm ÁÙ%ôn!Ë·.¶Ay~B¼‹ùi§œ�ôT±X ÷#òÛYÂÌZs¿À{�æ‰k18á'4”HŠÍ>²ºT ¤©º¼x¡ù’K˜qB;J�Ö¿x*<èZdÄ¢³’í¤0©ÏÒ"^—wdÈ%b$„ô Œ'7°*¨ÀÄó G�D!¡`¦< ç©7‡w7|ß|>QEBR¶vØxøuí§‚ÀÝóoK»ë|/¸¶\­!—Xœ~Ýáøõ§Þõ¡|-¡¼Ÿ QU¨Š<"œ€H¨ï“ÞæT$ÍÔѰ­¢áh�o}\VÊwgï.É+á¨VP ”«I¯ÞT/Ö„u×zðœ¦Þ¶{þvSú~þÒ»þzÁøÆ ^,¯´ûçX €ÎíùÃÂo¿´®süHi³Oð÷¢ûŽ8@µI8§Û¤=%çt¯Ý>_¶4%‰ïýñºû©"Ó^¹ ’}óu ‰ kÁ0§:Ë©”ú®·âkx¥HÁÓæ!®ì�ˆóãm/mÇéÃ;L›tѾ>=4œ˜Bî  yÓIM«>­íÄþ=|-OÅÇ“FÒ¦óÕ¶‡‡y�žÖ-"ÂC–Iõ½�töapšt¦úŠÎ ypêyTør†ÿ–‹]Ä÷i/üZÏåÉ‹ö�ÒÎK= ËÆ<ÝÔED{æi'†‡ä/÷ÍMÑ„™”¼›Vý&Λ`Zíö>ùþ'ͪ™‹xΈ ”çÏ¡ëeð<÷[.0®áØ‹yHSY^ý`iìx�3—׿¶óD0hÛžBW4£yK…òΞr�qݘLÍ�v‘‹BáÚ$%F‹+wð[&¨~´Kƒˆ(µíëï×qª9· S ¢Žˆµ¨Ýù>ÈBÙtŽœ‘I>lxØ·ú¿=Ò\I%£© fÇZŠ"ŽIn³<Ó$yH:TÉî 8Z¯/Œ¦s,—œ ( ÍÉm>(`ANëqÚuŽ·ÀÙq U†üùð:$ÎŽÊUSWÕ÷þ]J9ŸÈõ¶4›®süH9¯‹ÕZk­o>ù÷Cgµ§p¿+ÿ½ëuú:$Ããä³qªÅçœO-`§vwyóð©wõ·Ùf&Yj©^m›7íÂÜLuܽÍNdZ{™¬_´“– ŒÅ! ²bLÈ$#eäËvsØRæ@i�l:‡WTy9ä½fuLð"¼h^i焬Å?®‰™"\›Ñyùòf8©Àb”¸¦‰Á-ÜÐpk�^Ð-}³t:�N§Óét:�Nç"”ɘ•¤hËI±/øu +�D p ;\îá�Ux”<9¦€f…áP0í�·ÜÜý”D€þ E,F[çé€q2p¼)ð_ãP>¯²¯†Z•q….×ÑÁ`0@wVY<³À†fnsŒ_~v´ýf��ÛÍ÷|Ï�N§óV�@déƒXZ÷\`‚YY�3R†dÈàå®ÄbHD‡´Îmßð#*Æ2ìŠ\Íò8Àéö}ˆÜuœ„%@\rûÇÉÖŽë$‚ijœ$D!’D¤…¦ÔU¯×ÓuŽN§Óét:�N§Óé\&­µÖ8zªÃæø´Åã„C@@@ð€#y¹§Ô¹à–¨†yÀUE*øµŽ%mÅPϦʲY•0.èYòýH ù"2xËPX�æ"ƒ–ô«?š^î¿¢V-ux´!‹;Ê[—B¡8õ<�£NÕë~“%e Qa�°·=;�Î� Ð[,�‰»:v@œ$U¤*9!ãâÎm¾®¸þ#ˆŒÂ²Ë`2VlGó÷ưò='V3·ÓÇï¶ìZà"cûSA¬…zÁ`õ»ó–+¤Š$½[™Î+t�£Óét:�N§Óét:avÙÌ\¼úüòð§ÿøŸü§×ùŸÎ7U‚ �Œqp&�à|©µ‰„È£îhÆÇUž¸~ùÙ‹?tÙ{hÐ-ª-öáB—0]`-‹ÕH�ÇÛg¹êÏMÁ­‰–}ÂÁxû#Ú&z¥ªÀŸ^É¡ÆD†u†Y÷¬êt:ðõ¿EØ×€8"ZM™:´uêţ΅ ™YÊfX§.pÂ=Œã¢Ö0ÚT#@‹BñXš<.Ó§±%±­“-È€;Ü`¬(a¥àÍ“=t�£Óét:�N§Óét:—@¼¸KH m ‡iúÿÝ埦ÈDL {Ó9è`¡Ü‚A0Þþ™ÓUÝ{àùÍÓd8ŽÚ]ÖÄ)ö!"=_7A€žDbÆ(Zöˆ2”IJ•p\mGÐ.ä[µ†…ÜÕh|©ÔÈôÓaŠQ…‘³‹JhÞõ\ëN§ó®°&o¬A­ˆ¬îMB`.ˆ$H¾›/{ÆÊÖÈéEµÆúW¹j.t°Þyu.�EDõN‰Ò$À«‘Wo{äIÆ:õ–žÌÍ·*¥¬.QÐû¾ð-t�£Óét:�N§Óét:ÁªGbÀ4Al‡Û?“xäÁL@3JFËùä4>±!�PÊ‘š&»v>n°?Âyª(#öû9|iæh�´ÍuÅne>̇Db— @J˜ p͈ ¶tTƒ‚PN¸¾Æ&oRÆ\nÁÙc2NS¹Ÿ¼ëMØét~Œ8á@ëÙp®mq‹ Ü‘]à—†/±à¼Hâôi4ÂÎÔ Ù&V§;ÍiAk�€œ1‹˜˜A·¨Õ(ªrÉŸæ’uêñ‰3‘íà ¸€ ¢’Ußõfz¨t�£Óét:�N§Óét:a·‰›ðùøó—Ÿ# j£Â'ùøæ`Øm0UË‹¼É9m�GäŒ� û%F«²ÓrMÖ’�ø¸á4Ù~?'¹b$x•ÁøðúcÞ'ë¥.ð�€Q%D\£&·]øà…I\Í€ ¼Âް"qÄ10 (.ËNC‡!ˆzІµê…„"b©~††¶ýEÞ@êˆÖ4)ÚñFÃq(ãðøqq„¹XU²›12WDå<".9Ÿ]£•¤–‰ÌuÙ…†žLÑD2p±ðžÎ‡Î¾äKÊ4–$ ©"U§‰cö΋Þ=k-ò†q¹¾ §žÌÆa¬:-Ë,aïûô�AßÒGЛ´„„«+¬>’áöOŸÿ¿þ�¿OÕTA”–Ûu©~Ó2�pD‚ïÖŠ} ÌŒ¬ñ“]<Ó@‰Ð¡V)í·zÿ(]çèt:�N§Óét:�Πo6I ̬7 ¢p¯)ƒ¾ƒ;3¥P  qÁ)«Å!Ší2¢*JA6 C#”mÊ<‹I¡ Ç$ÿ»øŸýl·»·Q*jUUÓ•¸º™íxûÕã_¤Œãì%ªCµ ¸¤Î±8,Á‘['no~µÛÅæ©ç´Çf† Àh3c"Ú+Ù–ÄY§É)qÚÌmïBˆ„ï_‘ ¢Íß¡Üõ°‰ÝÙâ&ÇcEQ˜@%$A JèÅ�¢į̂šŒ”�soú Øò­÷Üô¬Óé<,hàÉuDdDR`ô€ad4ÕW;?¬.‚ow´ŒÖ8Ê@(\Z³dD ªS‡²#’w³×ÓuŽN§Óét:�N§Óé\z‰½ù R²»âp@–t{ã�6׌$®ˆÁC�Eã%0IÈçl{ÎúQ-¡´:ïI½ºÊ™Ç1ã8Ýð® +mB=˜Ž’Žf]$ ’ 2A# è­DK‡†kÃ�¼”Ï›4æ±ã´¹¯µ’R"cx仟lÿÁÿd‡gOîf _ú‰Ÿëx¡+@ú·àÀŒÿö?ÅgŠb˜ëÄø¾ð ]–æ¨ï_“4€WóƒÙìhФçînñ¢ú'†-óa¶)Õ$C³;K@ êˆu+JZÌÐÖW¯/]uÁÅͪå¬Ý ÷_ƒÄ©lB=ÄìiS7©ª›DÐcꌞqÑRÚiÿi™Ì§éÉw¹q§p,Á$—\ŸN§ó#Â� úYOB,\9 K£Ä…{Ê`ºûð%“EšÍ_Ä!±¤¶ô·×ÒuŽN§Óét:�N§Óé\σH ŠÕŠJL·øÉÏþR®ô b ¡ˆD¨JAÚÁÈ—zx—ÈW6×Í.éôr¹�ܾü£ 7›#œKº RËFHÂ$ƒÃE *iká�Eçˆ@ â²:‡:öÕÌF«^‚È@“ݾx>[ Ûã'¿‹+,©ÖÀåzcxæœq>Û>€~uûò夛q¼ºÚ=ùèÑ…×æ²,9±€F‹_ÇYžvCw^TÌk×Rav•óÕ¯‡úÚ¸@Tm>QpÀ/o} Q ˆ£é¶tf¸÷Ý’û†@Êü8쥻Y­thòÅ*ËA÷õmòÒ¦(ç;üóœÞÌÑétÞ6¬ Ý¥ÏšˆàÑôÕl‹•ЬºÂEuÖ8ke[}±¬ ¸ô�¹]>:¯£ë�N§Óét:�N§Ó¹B*Bõ éj³û{ç?Jõã«ü$Yfˆ„8Ĥ†îƒ m.÷”Ê�„|Üž>»z>}Ur1}þÿý'ÿðË/þE±ç•«&Ðæã‡Ä\!*B½Îs© ¡‰ÕÉ}©MX8�V{¸Èh˜$†q·"p�R¦Ÿ>ûÙäÇù+l€ˆÃdƒˆæí%?ÞÓd|V@૳|«�¸lC·¬‡©�ï{?±4l¬EùxíÏAØ ÆQe>Üàö)# J*-„â‹Ôp·m×@ж‘mím‘Pæ@,jß9z`_±ŽÍŒ¯W%$"j­­')c«÷­Ÿo\f|u³ýÆ ß'.w:�·Žð3Âå« ‚qòúk4pAñ7Î:ûÎGqpB¸i ~ݱê7ÑuŽN§Óét:�N§Óé\€+ÉmìàWôÍ6ÿüoþô?¼Æ_JØ)’.?'wL8vÀp¡ÕxB™ýv�T0oð'ÿ2ÿ£?»-ilEz_~\J«*p �-òÛiD¸ˆ¯? –É•íÅûÔœ¿Ïцœ "âQªR~ýÙ¯täWÓ0@+hšÝÁºVi.ÁÉј�d@…¨€›‰ÊµqÒ<Öƒ—bîBýÁ r±6ûæ·HPQ‡¼üò1ÝoJýg’žò?Ì\kU!aÒ m.ÑZ4$ FqÒ$OŽdŽ6óX$Tn3ƒÍ$\Bœß=Š 6áåK\;~ùÇ�^V•±FÆ\Ã`HîQ¥EÜFЈ›AÛ[åLÀàëÄŒS?ЬÒc§Óé¼-Nç–kÓžN˜Î&F2jõD|$ø©àZ�á‚â b\Koß÷IP�R÷:\_Át…’p"ˆ*KÕ ùVÀw÷ 5³UBÜ…Åœ§c�\¹ær_jî;[ÝÔ‚¬Væz<ø„ÌüôúI™d¸Ê{½j"QE)HuCñ lɳê³:|M”€À¦p ”:^—2ÃC‚IÒf¸hwÉ@ëÖñµ¶tòYº3 Ò!FI” ®W/çßþ ~ýÙÍtÔ4’D�ÀMÜÄ�DŠš ê) N©"UœðÁlôº)€#$oÆäÄl5ù}÷ FÊÕÍ‹—O>Î(·r(xúDtk¼EˆÆâÇÕ¦07�G(ê…öŸ@œi²?Ëv<ù·œ ‘Ú¿N§ÓyK‚Ñ4׸ëÔ�)L5M´J@£€.�Ë\I—K =ƒÎ €`!'ÄQBÃw¡!2D,Ò¸~ß·ýaÓuŽN§Óét:�N§Óé\„ˆ Yê$Ê Ø��§@¦c•‚2Ê+ŽòÖG"!Òn»�3ËuÅK⥦”¬Y²Ì¬„€üv¼R;L£fqØ4o6Ã~žrŒKLƒ@ƒNHà"#†Rfdxl_~öìêÑF0݇£«�õØeTÀSÒ�a¨¼ÌÆ\óKD @zµèˆØ<~ŠvÃx0j¨VúdŒ÷¿ñJWÁ¢päœ�Çý6§Nsyüô£ãŸýÒE¦°º¿MY,ܦÃÕKÚJfÂán°&·¥u#R ÏêU4Þ¾ÜäŒýiÃ(z;]}ü¤�£U½w>åêjë^󸕔÷sy.Óôx¨$I¥ˆ $<"–¤‘ó®‹·>žðkÕ™C½BÅ�%3Ù²N§Óy ÄÝÅ 'Í5Ä�¼9~†§û¿þ·~÷æÅ´ÉÉâp‘¡ýÄEú9è ÖÅ´0F„€¹µí=Ú|2Øî¿úÏ?{¶ûI�³“úŸÞKÞÿ›ŒN§Óét:�N§Óé—ívœÊŒ¤&z«"3 ±ÔJ.7Ûó ã—±ýgöK·ê5ÏÄ(C-ûä ñ¼6kV‘Öª¼^`8œ§y÷í¥ 8"!uÕº(?œÜÔÅ8ý¬ƒÇaR%"Í^Q‹ŽãÇñwoŽÏEm×£­‡³Çi?7ñ€.›1¹:F$ñlL³°$#üÑã<0'Œ@2wÛƒÛq �{K "’éA€Ž€í6öø'»O7ØmBSuó5 �ÖÍ$Hë.²ÿœíë—V¡" I2@D”©Ú»þì;�·C›Ö�Õ)kÜ– c~|µyöoíþêßÔ-F žÝµŸ]²góNÿ=¿\?BÀ~…áŸj�×2‹ºI�-z=]çèt:�N§Óét:�Î`s—>@oÈ=#{àLàv™,¾¸â¬ìKÂó…Ö‹–²¨, Œ¸ë08Mê"ðdªÿ«¿ûwÿß}úÈ€ k ´�i4Ä�ƒÄåj ŸÿûÛù�>ûÕËy?&‘£Ó1f9”š"‘W-' @6­ãbOýÔWÏ�Ö—2¼6�ƒ! ÑXÒSå=Ÿ�ßTŠWc`D„pQ*Kàvš7›Í§ý¯ÿ›¿¶:ŸÿîRÂr?mB¬Ò›‹Íi"0–Q-sQL©(¦Ã¼ÿê«/S9>&M7ã¶~ôÑK¡4Iâ >2uºÒ#ÌÍ"mÆg?K?{üReŽp„Ò(Ã�Øvé¸\*Æ+ЦÝR\&47ªÏ!^ëì©«�Nçíí.äÔ¸!õævoÛ—O8`s œ}ór“0NœV'Î’É7@…áC©¥˜8U )Øû9^C×9:�N§Óét:�N§óöa@ gà~ `‹g'  ¤@Æ©Œp1_°BÒb­édÊÍ¥k‚ˆV¶÷ÑlüóÏ~çÓO 2�ê [FÂXÚÂe�š—¬ƒ¨à¯^ R Ã6Iá“$Á[Z4ÅOrQü 3=ÏšrZYfuJ@jŠ‹¸0€`Ó9Þwš¼Ñ"Ä—®X>t'jx"=É‘sºúù/þöÿìްµbõ�Ïäk{‹ÔHL#|2–Šâ€/ÿüø/~’ÿn Õa¼úùÏ7ÿ½¿»+2¿ÉÚÃ|†„*A�™¹bó„�Ó¿9þ~UUp¸W�`MY¸˜vç2µÆpÂ3b�ÄUòtŠ– Á<¿ë= Óé|0´Nà$r´æMö3ŽË¤†°[ÐC¶Þ.m—9J80Å`DF»—ÊæpTHP„T³H½£ãut�£Óét:�N§Óét:—@Ãba´xýg%A`p‡¢�Å£ÿB#'ˆ#†`kßÎ8‹9o.qhQAÅ1Ê"r µJÒRÇO¥ ¬óÐ/SImKÜJÒlfÅà‚ª¬�¸ø+³A±®Ìåà:~]à‘öºó.ßÕ/)ý0Ðö“&rœ|«¸hf(V¡IÇ�YæqJ ú¹.Àjºk a�XM�É1Ķ26LD’í´Ÿ}ÿåÁsšwO?ݤkn#ÔïFëbS.Å' ä”2‹%ÛÏÈcJ¥˜¡L~°}EÍ€¨_2w׈ ˜@% ÐH)GHÔZePÒ�©ÚÍa¾Q½ðþÜét~4¬FUñJiHJœD � À @s´¼dù’ ¬·"Ž,ÍÊO` 5l6ö“áëè:G§Óét:�N§Óét.@1Ò·ô¼ßK¹þŠ×“¬5äKB¦ Rç+¶@[£V¿†0p&i’AñÉeÔöc'ÿ«WJ÷­f"¸ØÛH©«Œ�aÔ–3žÄ .^$–Ú �@^¼(¼È*«ùX, .'¹%x×î8ÞÿÂÌIäXòá›ÝRU<ÂÂsN¤Oµ†ÐR ºÆÒ ˆ¥ù†K‡‡5 .!0Ñ<’”M�Z‰t€lw;¤< ÃŽêA’P1rµ{û’ C.GóRŠASªHUGˆd1 X$8!£(3nå‚Q·îÀfÁ´ØåGÍYÏ*Ì0A&¯÷–t:�Nç;¡ƒÕáw�˜A€ûãñ¨S©grƒ4ዽž¿õQ¸‚ ô€·+(ƒ„C¤ýÙR fS£&M­ù®ó ºÎÑét:�N§Óét:�K�à;ø5üù98 6�ѱ]EŽ x@£ŸÚ(è€\dÄL%�z @ú©=ˆÂ¨@ É7�jØ�%€Xò¾W"žµ8¼õ‹MÞs­T‰„(âTw5× m:Ç kÈÂe ¬€ l[Ô¶²‚~ÚDÁ0 Òã¢+óƒðªLã0@­¡c‹j‘’RŬdT†·e±ø QÃë>Ó¬½Ü~ÈUÏê^ÅR uËyò#SQ‘˜­FëѧIh÷ÖÕßMç,E„jžšd Ãf‘Ù¤zÎàˆŠx�[»ýå'W$Ž—Ûœ-ç\ÀØ*ytЪï“dC)¨s=jÚkò';Ùßôº^§Óy[ÔvpöŠ80ä]•mÒ;W( U€]§\`ÑÚ7‡SC&©E™[&˜›Ñ#‰ )%¾ç ’£ë�N§Óét:�N§Ó¹ A¤€:“ Ä@$ÅLÌXg$ê�hà$@ÀS¿A«Ñ·¸Žt‡µÂG«h{ 6T<¯(�;c.¿ûÆÛH*›qTLµ:TDa�h­'�SImÝqšïyŸ ÞMG�W¾g«íÎeþEÃK~0NRÇy/�™ ²AD)%`¤†P•Õ�¯ÙzHÍÑ‹D á@AͺÃL@¥DŠÀ\ ­¤Ö"^‘†Ü¡î¹æ2O%G†mÒáaµVŸ�IÔI%vÂÛÙê¯oÿèÿó/ÿ¯¿üÃc⑜îï­&p„8§-M4ÐÖz¼ñv¤ÄÐýEüë?ùןü ¨'°8IÔåx[>•“ËV§óáq·cK¡Ò&û·£ïó@mòaœ¿ö¶içüv� ®!ÞH„,GZÔ\™‰™ˆoTèúÍ«ê]�ÅÅò0–�)Œº�¡>sš ‘@…¤p_Nþ~‘1g�­92†A WÃ6ÇF<ÜýXêÕÅ>Ü÷š®st:�N§Óét:�Nç¸â9˜–9Oq«¨œ!„Š!Q4FD›ÚxJÈxëãd"W@a@Ì“ŕ‰Ž!•G¸ÈÀÐR¢U«Âà­T¢§|iÂè…Ý·h(‡†œã0»C “Kx$`€äˆj³ŒºØöÀÕˆ¬‹C–jþ2C–árWÍù&ã×�ÿ¬ì¸Í¦"ÀHJ)FÀÌï*igÛM¢Õ[5«ÉláœÃ<4±mRc$@R¥†[óájØÕiÚ c©÷U(ä½­À":˜Ët· lr²ty*d­M7·›ÇGÈóÿìÿo²ìÄ#ôžº—ÀhsJC�a2w<ÌS”4æ¤8DÜ*&b€}d®!UëÏÞ":A¤óx™fwöß~6=ùÙÎ}Þr+²óz3â0 ‡R_ª\» àJHÎ"ß?i­Ói8‰Ð |T•˜[[£€³æB .xÖ]®ÔÁð€Âã*"4GŽØà™‚ˆzu�*kßß«êǹȱÖýßîH"§±MÆ«]JåöË2aÔ#k$¼IW»�e­BP(¼˜ŒKBRóÇBâz_A* ``1šÃ£$`HÁùbî{L×9:�N§Óét:�N§óö8h‚bt7�HáÉœ¡�‡+MçˆSôÅeÆFsån>9ÍkŽÁ‘�°6Óœ€„´9ûÒ ù¶Ì™µÓOl®Ïàë*·KеC]Öª�ºšƒ]v{®¦Äùÿ`ý|?D¾Ù˜Ò´†³Oÿ#”¯�¯&–¶u ŠË ºze$ UO«Ø w³}¡NQÈ&žˆ­ºS4ÅO 4äüdÈ?ŸæC�¾’ôeÞ„êÞç=b¸ç¢= ê.©Úàjs®Hîs2*xTTÅKF ‘Žž,¬´ßµ{ý�ñËÏê³GW cÀ­T0DÞeº·¹í½Ÿ£óáÃHt%ütôøu³jíÑÎTU—› ÒV ŽPD –h¡M¡€ÛYÏ«Ðìô �[Æ.A–m>DSRãí�˜…½ª©H‚‚*ƒí?àî¢ë€^òÜrJêXúH×3™Joâ/êð5ç©óZºÎÑét:�N§Óét:�N§ó¡Ã*.wb@("KìoþñÕ_©óTö9†²7™Þ¨ ‡‘`c`WÉ¥L·:P)€ÖIȤ4�1Ê5‘‰qŒ0Ü?ç¼WùãO?úÛ?ýkŠ�½n‘w䀨¯jݺªóat§ƒçþ„-Þam¨‚y•œÍ†ñb«p ¶ Ä,,Žº´@Àø�ÚÁ45 •Ž „(�@ây(w¬_ÎË„~$OC6ŠE¡*A¸;>—Å']çèt:�N§Óét:�N§ÓùÀYS1,–þâ>Òâ£Ç¿û—~±¿Ú<šüsæcðXêMʼ^‹ÙˆæC��øòO~ýßÐjÔ bóó�þú6mMaŸŸ�Ùó 8y”û/_mó“¿ø—ÿâïü½Ÿþüï~†O�…[7­¥W%;?Nz?õÊÉ¢Yʪv8PÀÓ�C _p�B–,+Q±D^ñ$©b±4Œ4Ëð™Èƒà„€Áu5Ü:·•ZR».¹5¿ö"Õi¦Š¤%‚ë•ÓÉ*)uíô}¡ë�N§Óét:�N§Óét:6ksÆù{2ËO®Ÿ{/Nv>(è!Õy&s,bÆi?? CŠž€ æxƒ@B; -w€8%3µõÔ½nÿw$€�ÍìQÒºöç Gûú¢:ÇWÀŸî÷sX�O^]I…!²ŠßËG¯ó@é:G§Óét:�N§Óét:�Î�‚N‰ ‘�?ûãÏSBÊJy¦QýD!ä)b@Œ{ŒåÙðóñcþÌ8ù”Dä„Ýôòj7~Êá™—�•­$�´3³Oá›û/ÿñö§ží±=á‰TSÕW3ON–\ÒsÈ; gaî\:9I‘¤å_P�B¾¶m�‹KDy/«#…z èæ×š!iÿ9êø¿ý?ýŸŸ Y,"b“²™Y©Ã0¸Ùݲ[!�7 z3&•òìÉþpˆq˜Kq• ‚PUØb›uÚzúÉä}¡ë�N§Óét:�N§Óét:6ò�²áR�|úèãˆU�ˆZ«»„BîÓÉÑFÞ¾8d®Õk9?Ë×/D‹àQ‚ úhÔ�« *ºÒ8'H¹ÿò½°5ªê^­Ñs'öŽÎÍi?g˽ò*i$ ­_;èÐ{‡ß|ŸIkóE“B�Pq�€–&+ÞYlÕO~rÌÅÜ}“r­Õ«m†±Öe=›Òpâ¢:GÐmšB‰œBèÊJT÷syèœ.s¼/t�£Óét:�N§Óét:�Nçƒç›€B Ì5‚9 BjUÅ�ÆTËK§IˆÓï1b;<4ŽöU’Í{RPom.‘Õ1øè€€8-UTžâFÎÞKôiØ� !UDH L®‡à¸8Ð5åòÎÚJ–Øï»¸ò·7laânˆÂd¤AÝ=Öñ&£"–~è€0À,@-<Ö³Ð)œcy·±,ä¾ >o4J”b$C5 P"DÂNðý\òÑuŽN§Óét:�N§Óét:�ž¯ë«®‚GÈ:�Y·8(÷#Á Áü 16_DBŒˆ 0.ü‘à[°8'A½ïòi `g°€m]aù�ïµÓyŸ QMBÒ|¦dÍsàå � 7€TPÖÃA�|±r‘‰(.ègì!ör_†'qjé0@ Bà� €´@�ôn©g‡­-oüL¶|{£F”ÃQCjV ˆE ^_{æèRÇûB×9:�N§Óét:�N§Óét>x¾V¬k…Ht@_'Sßip~÷:XBˆ3wûkÐ HˆAˆXj˜÷Yò2.Ž[¾VEcÕfZ‡ ]„ö’dçD™‰ˆjÇ,êú²à×cà€£ Òz€$ _²ê;+f`RºC©âùî‰Ö NïÚ2ᘎ…9< Ñð@­=uZ¼rð~³=ëí�žÂ! x$���ó¼ì"ÇûD×9:�N§Óét:�N§Óét>lÖÂãYÅ. wÿ\ÜcZy¯ŠH@rHÀ¿s*ôZÀ <€‡5&ùréH$ IIô ÷]~TW,\AÀ­´%ˆX¿ÙL®ô’IÆ�ΊUZ QTxèþùþ�ÿÙ/ÿ¬m7�Á –õXÐ¥—‚þÛþÉßDL‡—„ÌÅõãÑÿô¶|ÚN4 A„8R±Q„ »kø@e xäõÀ�XrÍq&34�óí�æ<9'±HJè!±øeuÞSºÎÑét:�N§Óét:�N§óÁÓò~_Í^ÝücMçpºÄ_L—÷ ²‚ ’¯†ûÍi‚ÚJ±ð>K^–/\|xb@$„ ñª9 c×9: ©ÅÌ<¥h_<ÿÃÿò¿ù‡·/ôööÖi�XB-°)ãÉ£+¯‘8'5yª›ÛûÏ7×áô šÎÉ�n­üÍÝÓŸ¦!k²RÈš$PJQ½ó­j½ ë[¾àö<¦ô'³ý›ýq*¦¥„!Ü•òŠ<´®Œ¿â®Õy¸t�£Óét:�N§Óét:�Nçæ…pàËtïH-Ø�Ȩ¶â¨KxH½çÒ@Œ° €°g°gÀÐìþØý±ûup‡¨p‚ ž! (o¸ütWlŒŒÈAø+¥­e.y«ðö‰Ù�‡”†À=PöË/~ÿåsÿèã§!ä´Xš9pÂ.ÚÒñ¢ÎV|ÀfšG“O†dÛGØ>ÂÍw‡^[™H�çÃÿúüüM ÄÚ™u®œ2ÔÛJË%Ý¢>þ“òÏ~y,u.$’a.¢°ËJ,�‹ÒuŽN§Óét:�N§Óy¸,ÁtÛ3¿Q¦$áÉHu9•ˆS�Oî7žj p.e…Ô^½›S¹þð×�uÖ7Žp„LÊcJƒ PŒÒr„%€€:¢ý- b1â^œeÚJuìNçƒíðeÓ 0=Îùû×I! ¢ 1 Ô##r@�„Hk!3�¢Aî¿ü œX‚&@ãîÞJ¥Nw(Ø*§h4�¤�X¾V»äÝkþÚ¢j|ý‡Ï_[ηËëîªQu$‡ˆœE•8àA[ °Ì[÷»³èëT™ËdœÞÍ݉=–­!N  "…ԵݧvÍè]#yÜÙªÌ�q‡a‡A,Ä ~˜o^Qw¿—TúÉ �Ó­§Y±3/oA €�d3€±âúðò§yܦA3Ï"B˜…ñƒk’N|²É™›“H"a¨!.c*S°@ ƒÆrŠx#ÝèuÍd¯œU!m‚€ÀAƒQYzîütWf¦%ôAwIï�3ºÎÑét:�N§Óét:‘ kNVê±wÛÍ᫯†aÀò0mwótœÍÕÃ60]�à½uŽHPá{…o0j¤0x³��U‚HlÖ÷¬1-Ë�³ÜŽâÇÝæås|¬W{L3“©*SrT‡x^áy-;j,ÏòA@»ÌÑé\9+±-2Ãéˆ[‚ÄñJíŒoXG P!r€B-¤ÛXƒµ��ˆ*¨‚úýÿDH±´ÒˆÍWƒOŠR!SÂmÂ3`ªb;Bl.ãl®xÜé­sÅÖ×òé'ïþê«q&ÄÚ”Ä`-+½Â'Ô 99¶En ÄbÞÅ V“já&Ñ*šÁˆYgµß‰Ê�µ«æM´ëû�lïg©ŸJЗøh$#Œƒµ õl†}/­¾3Ž·“û òdЯJ9¨à‹/Ÿ_?V[|ª€Áv<·�ïRfKØÛ›éÆ*æ¹lv7‡Ãü“�õâ3à#d‚¾€~!|ãÐÍiÀQÅ«AU¹˜æµÃnÝ3qz?—Z`³å4=ºÙ= ‰Ã”,mn™Ç ¾<ØGi€ s…% €¾¡ÎñÊû¸;±¬ YÄÚvœy†y“~XN•¢‘a€×8ØsIÃÀG_}U’�ûpßkºÎÑét:�N§Óét:”R�dá5‚ˆ0?LÇ�á:ç�_¾’t ˜½ÁÒ#£š9ä=øYXTSR¤€3`�o èJ¨ SÖÂhÀû[XàË/ m·y:Œ{É "Ž$`x.ÓÏjˆ?€OE§ó£ç›Eê¥âöê„êïSËf´¥a`Y²@X]*è.¶þ9XßÔƉ€ˆ‹ €ÐöW%�©Íg_~4ÁAýÆ åÕ¿xöÍEo¸{õkºÈz²Àá­ÜÉHàRúù ‰€IDAT$Z5R PuÔH£O‚’ °uM¸Ü­N«Ñ%¬m(²v»½õñÕMàšÔ±¬ZhP ôEÜ¡÷ùãï� Æ]NYŠYq£#e¤)û4·� 8±ì»t .Õ&à´/t [@‘72Uµ&ŽÅ°Dæ°¶6&İ3=ˆ³–Ò¯uu�k�—¼!˜êT½À+"· Då’TždiåÈvwàÜ·_ökÛëìëõ»”»†�"ðXO €¢5ì6�£Â’U™†tµÝnw;X¿]z]çèt:�N§Óét:�‡‰Ôê�«ÔHót-é‘› þà_ዯ�ÏÍófD½Õ¸¯ß="G5¡æŽ[ Ï’=µ:²K5=Eà ¡o% Q],€*0[æ�úGWW¶¿½’„››ë?þ“Ñk>lv:aáÍK† ÉþdÞét¾¡°Çާœ�×3¯áô�€yk¦ ôSຠÁÓ)gÉ*ˆóêÚ0�ÅŠjÕÈʼnkairÃ"r8"¡&IT%$+€ÈŽT™œVD+‘0DlijZV‹V» ‘ZMµ©K�n�Žæ¸uQˆ`8=^ÉrðEh‰eõÒOÞ)ÕñÒä¹ó…æMØŒ$QÖÏE%2àˆyiZºX>µ,ýOf°ã\J½}ytk5þá[ø5ì1ì1œ—k.ùP=rˆP°Š@Ô«G䨧9ã8‚ÁÈÓ,Œv�ÞOIäÉöÓWõT¾¾ç_SšsàÝ+~§¶ú O²/ûÉ0MåËýÓG— _yé:G§Óét:�N§Óé\ï¦/?C=\‡m$«àÉn¸F2Êñ ˜øwކ¹&7èrnnb(9ïŒ.1K«…)¨!„!j›ØÛžÏ[ðé³§�à5«xÄ ¡ÕL;l†«!¡ "€Eçˆ>!¸Óé¼92Öœ ZçC³ñƒ ˆÏê3�é¡V‘« I!>¾.K|Õ9¼åh•ÛX«‘ÍÄë.‹‚�Åg/€h¿â  ¡r•I¢…»C\Ìe6)!°äȆd•a5ŠÆ¼®Ï I¼›ý=­}( ".9e›ÖšHœ¶`k�D`ëö¹Kè¼;D\Ô'iSðh÷;ŽÂy KŒ–™B&À\ê)éú-�‘Å!v3â@ýɸMŸùÅv„j;ZâtÐ5 ¨¥Ã$q ¯'K¼øu¶ýþ«Ïÿð¹xJ�$#�ŠôÖmt6·©6äìcDˆ“ˆ†CÀ N²œ$0ŽÃ°¨/>Ÿ”ÜŽY\qõ~H¾†®st:�N§Óét:�ÎC„€€ ¬æ2édeÒæŸ>ßéZ½N·áÓ\ªÏõp80CNŽˆ”tÈûéXÍ6OÇÿ’g¹Ñèç�Nç�qK H-Uã 8x€°`TÐ�›T€‚4øI$8?ãœWj¹~·}Aˆ¬Þ:Ñz+Ößµõw[ÛzV#�Ö êMý]/ÜNá¤#RóñÐD[$ÈCâ²>—š�ϵ}K칯½#­ÅÄA—·o¹Nrú…Î;@„• "…§zDLW~&ø±„˜‰”@‹~´HŒËôsàt ŒÄM†opë³NuÒ°¬ÇP x'ÿú<‰wŒB”B"¦BU¤Gs<9¼8ÌÛtUpCÕ'Õô0aö‚Â� çH‡òX�.šI )¦sМ5$t ¢}@”@ršÎ¨AñELBEµ˜÷ñ‚ÛÇS|Å«¼y´yü»¸‘ù·Þ ]çèt:�N§Óét:� ]Ô>lòlÕ> /¼BUeÔ§ŸÌá€`Ô#’G–ë]µÅ0á>dóühó|æñY¯+ðùËòÉïüeƒ"mÕªeVG¤�[º–dN¨ƒ ´i¿@{H‡ ,è3L³«LÓ!„±@D”Ên}ÒétÞÜ`~:â–åsØx=ú´wräðKCRTj…$ÙWXšdÍn…|®-­3Ã''ii P‚$(±¸ä­‘ÁÖàG  $²À‰=Ò8b4Œ·ûy7æáêYÍxa,9© ;—ÃÒ-"(ŽbȹIŒ€;wéæç9ÆosÈb�Ug–|3í7�´L3^/E? é+,¥l·Ûyþ2¥Çn <ž€`V]Î�H!ŽÒ9ÛˆÖ&õ˜Ì†£àQ)1ŒƒqZWX�èv`{cÈHvt¡Z_Dù«ÿîÓ�þò§¿þà !F„,É�AŒ@–§ç¨õúðgøÃþB†¨<ìùÿðo›âXŽ®5¤Þ<¬–ã1�BÐS�ˆÁÑh†5ž@«Û¼IÛ]~>–³íܹ£ë�N§Óét:�N§ó@±6Ï–î„#aL€8Y‘� b@(cÀen®ÏA|çxöÙ $£ ‚„Ȥ ¡„¤*˜%…e¨W�84 ]íM‚â@@ð%f³8»¤ÑétÞFÔ$q„È‘º��¡ÿì§_$ &$À ¶kêqœ™V� ¬PB‰ºÃê9súyã¦,¯zX�8µ}�Hy‘ ¾¾ÒíøÉ/†c¡Ï_=ÿüX±ÝlƧ›rfÇã|ƒò„9ªƒ§rðXš-îã�óýF`íÎ(]’d‘rî4xêû à«Pý£ÃUJ&ñ,`mí-4ânþ€¯û«(—ªï%t2ØÒÖ!Á�0B”@´¦§á#|±AâaÕŸ ˆC�ítVçTó±Œüä¯=aˆiCMƒ˜ÕM€H@¾W7G0Íøãç° =›©…Äð °ƒÆ�·CHqVÀƒ€!N@àˆ@(¶Ö¯ÙÂh8"Ԙ뤇*ÐÙzsì7yXûY§Óét:�N§Óét˜xœ¬›5´9¹K8êI=ÓUbª%8k«L}÷Rˆy´²±âЬ&….Zd®©#b5c�‡ £…ö D–ɉÀCLê™CK§Óé|Œr¾¾‚Ï�/ޏÞ@†/Uþ“ÿÃÿåS‘!o|f-9ÈØL¢µp•'N1T5"()¥ Öê$½FÖD‰œ¤G­fA8= &-Ì\‚HŽMu ©Ìð1ÕmŠª|1¥øjûøWÈE³æëiú*F@°}ÄÙöysh Œj¡q"ÀX@1´¥Ý3÷ø�Ç�—ʪ„–©*”!Œ×™}uÁú�CÎäAxkºGä€ 6Û´  �´ìõÞ:„.³:[¦DÌ@˜À[ú6b€oà�ÝÞ-wæa• .a$„ÁJšæV5DL'æDÑ£j€÷<†„ o­,$R’Œ¼�ªìë!b ˜Ó×ÃL„•<†P !‘‚�4f!²„ ,`¨5ªU™4z—Õ×yX;Y§Óét:�N§ÓétN8ámþmˆ:ƒÂÅH]š=¶’CM¸<¨GHm“t¿sT˜¹�%…e¯ÉAÄLksЇ˜³:zÐÙ¦³: mn¯8K*¢ùJ b1�îåÞétÞ²»~@FÚ›™ZÕ6YwWÿ¬L“$ß ¬›9ÌÏC*Sn³Ý±NDoE|s�AxªP�d‘Ü0Oˆ’R’€ÕY³4Û+k2. ¼nk0Éè1¦:ަ;Ï ÝZ½zòÑKÃÕÇ:nåˆÛ燫4ŸKÙÃ+75tvI"@®–Z§�¦7ã"cè"_TÐS�L)n ‰Xd�Xe"é!ä‚6§ NàTÀÉ ÁD0�#�ã³ËÁÖvä@!¬5J Üàl·±�oá;ø¬ˆŒV”'ZOL8á�0AhÓ93çR‹èU ~�9 w3EA*<\89 X„ëáäbf×îîî‚LRç ÂÖÀK#à8o½êœè:G§Óét:�N§Óéå©W†‹ål5ÉFzÏô¬.BQTQ0’Ú¨.æ\‚Æ�æâ.ù´±È²„£¢°k�Nçm@ø³ë!G…OŸÈð¿ø{÷ßýå‹/^Ú¡ÎÃP<ûmNáéz6ÊË™Ó>e£¨Kr$Gö6Q³ÙŸ…5Kòóùð¯þôOÿà—¿ý«y#ö8í×YSq 0¢ L"ˆlx|¤Q¾ÚŒ/†< lbÈQÔs©”Ãïíÿ³Hûñ£±¼€û¯ä�~¿¾ý2m“¦q[ǼÕp�•Í÷Í!�H;å}™ë*Ky”N ©ÎHoð€*{ã/ǬÛð—ÏË.?fŽâ3 ¨§ä­*Ý.ŽåŒÝïÿßÎX#¾‘­ÉSNŸ71Ê2É`1[¿á—唡�8 ð4NUpN€>P{¥ )!³„kóÚB1ŸðhÇ!JØìs‹{÷s¤@Ú"ms¯â!³¡ðó°`´w@8ÍAxÓ9$‡*’ S0´T´ï%£oÒuŽN§óž@_ôÿ�‚`“‚ôX|àPŠhy\,`·êÖ1è@»®Û%$²WD*²­ÌENU]` d×Ñ`dh•žäþ·‘)\ÍX­"‹1(H3óª !ª n"PôëVçB£>Êéps«ã°¯é¥ 2 ’LæÃG;qÎóþ×EŠm6ÇóÓ} îÇQç>­«Óét.O³…w.vëË.!bâ~w.nÝlÕ¨û.½jÔ{9ÖÇV¢áˆ6AÄMP’»ÔäP‡K©°:O)|�ç+­¸Ì Y¾o™Ík«ý÷-ê†<ÐBH§Óy¤†#×O‘�§VöÓB„Å1Œd@)t‹,Ž.QG«„WI�$–ƒâ~Ðzx–ÝÇã~[®ŸþÉÁýôÓ)ët˜ü¦þÙ\í×1E9Œžr%=Ô³ZHM^5z5ïÇ*«DÑ€bFäb®ùe²Y¾Ü>ÿüêÑæã\6ã•N·¶“�1yÌr rîÊÆAÂRL*a8CÓ‹–´ÅX'h‚§41áÚ-ŠMB¿w0³×¼FP¯¯­Úá‹ã¯¯?’›ãóOã£Á”Ьե ¬rŸçôΠA_ˆÜ5®sÈä¨( Ñ&PŽª0­w—ü¼ø�ðqá£ÀȉáŒq%戇õôÈ’“næô¼ÔýÈ< GÙ�4³ӉJ *#3 È÷¿OQ„UšMᒨŠ@A PC0ƒÆˆ|½7’Å·NÙ¶jû › WO»^,z]çèt:ïí¢¢@{°–%² Xž—ˆÕ—2D1j0ˆÅH!Ô!Š´þšUic+$0¹$‡0y ôLhe�K=Ð1�åVýzC­ ¿ÿtÁ8®–\$H' "ëJ´„·ÅÅâ„öëVç‡ÄK Rv’¶îzœaÏ_>ž§_Çm’ނļ»ºÚÇlSŸ‚Ûét:? ß´`n}úúÖ�û>‡3B"€Z4fuõåw¹üQ˜8ШŽl‚³ÄÑóåÜ}½–1–fÙº¶±úú­S%Oñ÷ðËÚ‰w:�÷™€E©�H™×­Høutq¥©›j Ï‚JQCÐn>ïªGD¶á+äÃË<ÎIE-97W¥^E-^F„Z’peSmÃG *Ý £ùhE€¦3$"”2š"dÔ<§œŸ^mþÂ<ýéç�Gç+IÜ�õ¾vbÕ¨â8†ˆ‹ƒÕ�˜G)�€"•iþò8ß솟€Ã½·¦$n#8׃ÉÃ<ìêõOvÏ~ríb}P 8—lô&¼w«`'Ð�ÌiZèEZ'4 : —-ùú"ÓÊ/�¨  (á‚ 6Ùc@ÌrïfÓñ Àe 9j$ 2ŽøÒ®*b‚lÃþ}ÿù4‚D €2¨ ©ù‘:œôÕ-D^wÿóš-Öå�ßL×9:�Î{É7)ÖvŽf]M8•åRD—SW ‹ƒ¬*…ƒT¸DjÂèb¡œ$R,yl¢lb.P6ô«°~{˜ßdzD0£„'7BE$Òr*6Ð~R>:� L"“Jdbœ­Ü–_@ÿþÏþ¿¹}±y´‘aÐûÅùâf0øqN={×kÝét:�N§Óé¼;Bøêcéé_XDä�O?zÄߓώ¿NVî¹lu$ÃòÐ*BqÀ5b0„ÇûÏŽÁ ÜáñG£]_Kµòòþb±x¿h¶ó†9<%®¢&7©.p‘ 8r ‚w†�N§ó0é:G§Óy9×Ò ãN ` äb- ¶¤ FB("ÅrO ÄC FHUCøнUw&O.ÈA½Æ˜F»÷�ž‰VË�¤`R’ Üæ po\ B„Ž×ëù�ÎE`N2'‰€xl#rÈßzòÑGûß×�éÈýíÍϯ®žÂ·ió”,‡iï+G®Óét:�N§Óy¼êºGG�ˆ»sQ¯®Çáük¿÷¹÷tpu¨‹oª@r þÏq8戀nvòó¿’®~ñ‘ågÛÍ—¼Óé�ïü�prΕj‚ 3DB”DÖ¶sˆS� ÓäGˆÞù€»�J�Ráƒ:°–²Ø?ãΨJºcU§Óyðt�£Ó鼯ãkeV „!&Ûüê_}EW0‚Þ:%î˜6o+¹˜V°2€(Æâ§UQ’¥§ùiù<ô0dŽ(†Ì޽•ŠÙ¤™•Æw�HW€#«ÓÇaÐÍÒ#ÏÏ65O`HÍtë]oÝÎ� ¦,9¦ã±ÇéÓé&Àƒ0º Ll=T€:Zð ´F¨€¬÷st:�N§Óét~Ô´vÀ’lÁo¶z89/?Ì{ŒDBG@]ÔU\Ô¡6†�$é u‰+¿ßòB_Õ9¼ýáå_¬_Þ^¸]êèt:™®st:�÷†6ëDBŒ„¯SKZcpÊÄä!e¶ëGÛzÄ\�ÁxmÓüòåñù‹ª’²7aÐÀe¹}$BàgÉKzy;a2¬D :�Þ¤ã‚ÓÞ”v�ëˆÁçGYÒÕ±ùÑÞ\kO zôÖàΈ4€5OaÀI§…ËÓ ÑÚ×[7UW8:�N§Óét:?j¼ÍºóU^n’}Q –&Ü!F8ß9"š™²J¸/¯;ƒâêwóã¨à,¿‰'‘CÎÕ.Sœp×ùáÁ®pt:�‡N×9:�Î{�¬Ò€W‡2I ¥$þêøgZ¯ÆÇñWþæÓßý;À³-øs$ÀÖ–�ó s®ÿaýξuNœ}qÿjo»W,Àñ¯ðÿžŽRq³¿ ŽÁhK•’{„ûÿŸ½?ù‘e»Ò{Áo­µ·™¹{4§½çö—¼¼l2™Ìd6zêR¤Â«§B Õ@Ð@% $Aƒ4(è  ¦‚&¤P�$M„šTI%dÖ˧¨ô˜ÒË|J*Éd’¼$oßœ&Zw7³½×Z5ØæqÎmN\òÄ=ÝþÝ 1އ‡‡‡…»™íõ­õ}dµ_¦ò9AvÆ'�±™Ä/‘5›FYȱÙ$4V*•J¥R©T*O1deÁfw-ܘd�3ÁàS;Ñyxú6sw¦<-b?rîdNP�ÕÈ>C9¹�JNå½)˜›u.3`Ð’B^m•+•Ê#NÕ9*•ÊãÃGºÈ�J³‰0 ;'ËP� (ðl§WIc¢Å%ì <ÃÔ� ¼©á–ˆ·ÒÞBÈ›¤5v°”clüYýIÉ€ öÆý^ç³EÓÄVNVÊÌä @àn®¾@•Ï28oÞ,ÆFÓ„7(j£8\U*•J¥R©T*•»96N¦:`3ÒAçÎÏ(ßèe dƒÈ�ÉÉmó¡ æ¤œÝÅÏýøœ2À81ü£M| ‚Â@¤“ró°wm¥R©|*Uç¨T*�=fÆDÂÂÜaæP‚¹{Np� €@$f�–¼ñÒŸR:ÖA¥‘e£]LE\&0fp@A 0ðÏèÜÃÐé€ Ý>^óþ ™éZ¯Kå™råâå*åؽæO 2”¡"‡;‡¢ºÙ¤p€L Êæ4MàS]êT*•J¥R©TžVJjÝYC'òéÂÙ'ó)†ˆ pi:u³úÔ-àFÌ)'F#u ÆÙ9;Ãdt†Jr2÷Î<žûñ4‚œ pÆG:ùŒN̸ õâ¿R©<ÚT�£R©<&8Ÿn0‚1`xÈÐH€°‹©¹AEGo‚” ð5È|jV €x@Çt«»p8M7“9Œ €;ØQ\¦üãz^>#8a°Ü$Q’BÙi;#9Ȩ†‘W~&NDˆó ^�ÅP&ÖK,!ŒÀeŒƒ¦){£éëÆ“Í³ÃÀNÓÛ“a›)óòÎÁ¦QG@žTœ`È ¹åøÌ¼›‘�Œa //Kvœõ\(/€�ìnχ*§=¶x€o,¿§YL†#8±�áäd(c’0'«‡‡JåœxiÑ!`ãWã€#XiʆlŒXï>|ž¯{üÌ…íIXÃ7™Äå«”§ÛO²ŠK¬1% ¹ØÛX(_%dB"x ‹õj ò$±‰Y<{acg¤‚)LÜîZ4ò¹ß�æp�QÊb›r±�urgùæJÛù³<þt�˜V½°2Ì].à�ÎD�llJtߟþ.æÅÏ�¬ˆ:ÆÆÄ8ÿjÿ§ã®G¿[ar“±0[€û™ºA¥RùDªÎQ©TœØ!F.èK˜9‘wNi†´–�Õ=ÿòàL M?ÃÊvóÛN~�5g/7îþ£¡ÈÀѦdoyp|4ÔOþ�0¸‰CŒÄ„2G5ò‹{:•ÊBÕ9*•Êcƒ"Ù¢Ì ÀIÁîìÄFf¬fNdePƒ]`2]BÐt‘b@Y¥ îîM»§Ë÷|‰ïºý§À7±çƒ�µäÜ7¿KñVM 6šex€Q-íU>/Ò8ŠHhw÷ìÃ0Àà+Wž†õ²ïa9F‰mcf) Ì̬Á™YFf!Oð”-bšÿ0r#À±É®òäb›�»Ž“FæT^6¥¼8ãLÖåÙNº²-Ž' iš>öïWù,Üýç2†(ØôvŸýÒia¨.Ý+•ósâÚz¡Ø÷PÃ:¬0 �àò͘òý·›" % Q1zõpFÉÀXî�›ÊœLywTËi’@`àH�”)g£õø°÷\¥ò ù¸K”{Wp½ �c[2Ìy2•5#vš¦¨Ë*1lƒ8Ô9ƒxʘ<ßã÷œ|ËÕ�NØã.l|,'2šæãÀ~×<ÛI‡ Ÿ8?œ;Så3lOžÏÙWLÈ#)Ø•Ý Jàiz¾^,U*÷¡ê•J¥R©sm–ÔµÓò8@“K †6½çÙž¸óÛtP†BÎG)e>S¦TŒ{(‚"p÷PHTxå}+Y±ÆŒj�®R©<Ê…(¶ic„o.8 Ñ”fqÚ´*^�ÎQ<²% qZ,1@0RF†ä$yÓLc0庤ªTîCÕ9*•J¥RyùLEaqDˆFâÜ´cÓ¬€ýq8Z-.ï˜[f w‡<ôÞM`qƒZðä…EÈp8ÆN¥U¿úî?ñPÉ®'d�L‡¢pÃeãð> sQ€9‰ƒ�OÚ�¦ÎàÓ|Žú*zœ0�9` vÛT=3�A Ã:…g9‘óIdk¥R¹/“ŸŒO:9ÊAW0î¯SøZB .¦"]ÿY¡2¼ Éo¡›÷1¼ðfR-7ßxº-eÁ0`@i’¶;™Íêû½R©&S2…Ÿ¦§$†)™úaïŽÊCÎÁX‰¦dÆfà †Mß1œ|’�È0rÁìP9 À^b96K¸3ѹ•Ç'ÜB±";ûUrßDÖƒœÉ"»˜›Ww»J圜†h�—�ÙÌÖ«qxoõ¿üΘ±7Xo6w4YÓg(�¹8Z ”@ðˆ’�L#Ñ0 ™Y[Dƒs.x^œ Áp>>\m/vfa¦½åe»ÜH³»¨"G¥RyH�± OŽ©g»¾ø®?�›ðɧ�q*3<°-—9æÉ‹C±Ò:iaÀИ�Š`ƒø“—R©üã;?iü½™ÿ¹+×Ùd›C+J–È��|rÙŸ†9ÊÏR6¬öã?ÑˆŠ v2e#3vw±ÒzŒÓF_7v§Môt‘Á¸l|²d)_-ë>cSâ*w<¶©‹N\ËÎÀp�<à.û›J¥ò©�g'v°�•HÙ�ÁAÚÙNœíôGy4ãp�iŠ™¸žûÑ¥Dˆ;o [€3‰Ê4Nå�ë¤à54;àÍ!Ÿ¾4Gäà£ÎÍ*¯b’±_YØãÃÞƒ•Jå)El°³"•þ 8!3À &—¸"ø4µèo'ÍÚ¸ 7KI´™—Ù¼�8:jwvò°ŽMk1am–Í…B+Ó,PD‚œ †:ªÿ81y>„Éë%š…PÏLîì™t4Ïpã¾~ØÏ¸Ry<0À‰Góì1† 2Œâñ_}y~ð£}κ7®•€6g@[2SåC`}N�ƒ¬ érXgí¥…´Zím]š¥¼&…Ò›"Ÿ¼ª 2[©Tî¥ê•J¥R©\ !�pw8Ü>¿fÆrâ"%"^ ÀALh¥úÇo½óÞ²_y`—! „D¨ÁK&^ˆæÁÁF ÜÊ«ß{ý‡_ý¹_Ú?^.‚0Ã\™7i§¥¨é¬d¥ÞQ笟lX‚’k².·˜¶BÓ�ŽÃ}¬–X÷Tzæœ%gao±˜;yŸÇcS ¡ë:�£¶Äà2Ï+›2P¢+�0<8ŠuYÉh�DHÃ2Dc�زj™ê0G¥rn8Hˆ3–&¹÷ªhùòsó�|-_cÒYb(O†qf�ì�‘ʈÆ}·¢3ÝÇ{oŽý¸­ïæ|õù�[íb'yí²prHfèFÑœ&ï°±Aª`†Ì/›�;»‹�gøHV{V*•§&:­�x3ÝnÙ³»&0H¡kã8‚fÏ8�æ‚��Ëç@"°5)!eʽ[¢0k: ºm§^/U*÷£ê•J¥R©\ f#U53UUU8¹*:SÛÛ$[<0ØOG:NDœÙ&ÛW� FØ?>~ãí›G �A²:„fpƒ� ÁÑE Á!æ~ïG¯ÿõ¯üÒ<çEdbUUò,¦±kgr  v/”Ê“J&”Lg¦»L1xÿpõÖû·ßzcžVLJÝ,Àl½¿ÊßþãïÏ^ü¹Ÿ‹Wvg;;. 7ƒ‚ 5`£:mêe€U©ãñƒ7j—Ìy"KÆ™ûdI-3ëˆ�^[÷¡a¯+÷Jåœèh®n±qÕ>åÁÖ¼vž7Ù&¶4 +co&ˆ‘”«‚ûnCÆø^ÿð0¯UòÐÐs/\yöBƒí¤sL!è r`>Ø{ö #@Þ´D²*˪o%¥ô°wa¥RyJ9¹Ú(™@±Ó‘›(#„Ü 0 ám5H8Õ9´¬Ô"H&8�š°tmÈLGÖ_¯Ãñ•Êý¨:G¥R©T*ˆªÂhš (0;óGE÷,v°£t-�ˆˆÈJ™É .<äôîÞÞž£og¡m Áe!vÏc Œ`d†"d¶çÞ¾ýöÑÞ‹[Û©ßçœC#£fáÀ8˜¼Ä*¸Q-R?É8aÐD»À…xtäoÝ<ú“÷Þù`XÅÆºFæó– mÎÃí׊7�/¿øÒ•¯~y~ã{ýZClÛ™JÄìxÓ\Wt�ì8ûç+qÎÌãܱítÐØç`±…©Õ‘¯Jå<0`š©�JÖ�5yôwßÛûoß|§ìÒåhHø Ùg„Ö´ ÝþÛï­ÉôrüùÙõ+KÓe2jZv0Œ7(â€M)‘•Ç r¸NnÎ2H�µ�Ñ�vWw�h¤~q5`ždÆ~\s‰+•ó²h¥‹‰¡kÚ‚c�lmp2ac%�2À†v´èhá ²ûnh ¤m” �j9³1ODjÄ6õ0æÉ�N+�§—4!P&˜ ”L‘]ÀÔª€]©T F”KÂ7•Ùƒ›¸Ew¶Ü%˜�2�¤Ïˆ. .NZ0¸ONÄFÌÎxD,ÏìæPfiÛx�.Z•Ê“BÕ9*•J¥R¹X|ƒ™åœÁä9ÓGä�8ÏQÆ8°q¬â»o/“%NȪƒ -‡Þ¹…2Ü'× ÊÎJ!;»”Ø`3ˆVóÔ´·VËDpKÑM˜IÄ7ñ¢ìÕ¨ê)‚Û(î–ú£Þ_½ëí�%mÏwVLj圀,Cœ�d˜‰ ‡Ì®7?\¤Ôæ< I/' ­J¥òIT�£R©T*•ŒØÙÉ6²@ÔaÙÝ_¼ï„&R¸$z™­óbrMVÆ�Ýir†š\_À@ððÓ•yOªÃN°É—–ŠÓ¬©zÊcرÕ^H… ²6FÊ`‚Äi¼ÃàHNXŽËzõÌ3×ûÕ�Åv°p´fÜw W�„À1Q0 ÝbÄÒ8j/'3ñ9Ó"#8±Q“ȧ@®À­™™ƒÀ�‡¨)¯sOMí}¨T* R#)@âVá”8‰t"ãr)ò÷¾3®!¬¡wq=§N¬ŒÌ X£YÜ�`D‰ƒƒÉ‰½,Ì 0rˆ‚1 0gæ‘…�&³RƒýõÑåíy·Zï.W�Ðr˜‡X�ž•Ê}©:G¥R©T*:‰‘ƒ9ئÏ1ËLìýü×áÿ^;�¬aÝò±…G8 »æ!„æDÛð�ò`SùiêzÅRvc11m ‰Øür3·åàÏýâ/þßßø…í«,†c‚ dN2óa@l˜áš`9 ã°½:úÒ¢Û^ÄíÅly¸Ž6Ÿ�yF’@°C �6€%¾@[¸ØˆQ¥çÛó«óÃ~ïòîuºž‡V�ÈÊ �”i7©¥ÒEb�ÙúÇïmÝì·›�Ü/9¸ï€|a–¨•-Œ@Ê»1¥,ëñjÓ~ðãwøÕ/ËÕ«MÓª(Y&1ªs<^(ñØtcÒàÒQÛ‘ÉÝ�54³¤�2·´Z Þ1tY“±Sdɦ9¹:™‰ ŸV�3H‹—N}ÿV~JP àÃv-€qŒLCòfì´¢îîÙƒzè„ÐcPÃvhݳˆhÎÂ2©Hž Sq�Š'À`€1`7'IÇ[Mó¹®–f¤ã”`W©T>…ªsT*•J¥ò9*îú'`d­ŒÏ}úw�©œ­ü¬W´g†Iìp”̃2fј¿tm÷vÖëÕ|ûrعº}쳯G@Ð�æì%€ƒ--�¯öë¯ßxåJÌᙄã,nQ‰TÙ2g#ˆ…`˜’=Èô"KÍ ‹KÍqº³Ÿoõ¾:Na=^iÚ˜�ØÝNæì';¶öC=X#FŠ«¡íµI`”d¦�±3Ø-¨˜Âˆ²„ AÇuY¾\Ù˜<! 4M”`ôª•G‡”-¶ó@�®4�ºhº®i™1Žž´™‚˜Û¸µÚuÌ)I0ŒI F"¡ PB±¿ó4Yv‘riå)Á¹'2†ÁDäp2¦b–'€8•É2–q½F ßfÏ@¶¼�ލ YÊt°C}’:¦94)Láw¸—Ó¹Ã4)$¥œf?gNxAÃl‰1{vÎQ¨å( Nc–lb0'�8”yó3Ï{!¡d0†Ô*°‰Ú*à ™€"(!34”YÉé`­÷<â™S æ¨T*Ìî °ˆóíí^9Þ»ƒ ]Î�š@1�€cÆé›ýþÛÑáÜÀ´Ñâ%'9Ôñ¨÷�¸ 2(kP†Šg�’á7*‡ˆ¨»©Ž£šzÛlooo=¿�¨ê•Ê}¨:G¥R©T*O'q DäîÁì¿ÿæ¯.¿ÿý?úáëý�âUKѱ(B:qÕ£Ãþè°ÚñÅÙÖŸzùÕg%6«ÜæÌ Y–ýŠ2‚mJ8Jà‹¯k8«9¾ò Ï|=>³ØAy i)�§‰ƒ3j?ÔÅÝ5ë0 9g ÄÀX1gÿØû«ª�0³9çq)g—ÏáÅR¹pˆ°àÚ™†Î¤ÍŒA—ëõí½Õ8 «>æD!ÊbÆÛ;Ú.¼[,ÚÖ‰FÍÇÙÆ8aÙH~—ìV|*?+ø]Ë`%(BhÖC™‰AÌÄ)FED.E| ˆD'*‚�l�§Çt €˜aLvN„2ѱùw¶8;¸ùi[–Ýj=¤ž, e! œ’�¼Äq•v(U“ÆJ¥R9!�fufŽ&�Chk癯|åÿå„Z°HdJæžñg:„n/æãr¹‡EÄ€&w[¼{ͳ¬!88€Feã6µ€ A?Vff3#""Ê93³^¹ÒÜØµP�ç•Ê}¨:G¥R©T*O <'¢Æýk[W~õÒ5ßÙû �}êÍò@FloãÖm¬×:Ÿït]³è¸_Ï×Ë?õ…WùÆ�­Íz˜ÃiÀQ-�öã�PøÝ.´€Mé8ÅíHD‰D†¾_¯)PbT"O'3tž¬Ãë:áAÂ̪)¥dfÌL`¿_1Ú7œ½åaÿ•;:æ< ¾n·0ïi¾{ëÃî¯4�ÍÐÏ’ršÏx±•›y~ö•[Ï̺ݙ‘¨!»¹[ÖPÞ­TzÞ¹ôÎŒ‰«ØQùéqÀH62J¬ÄžCð®’alc þÒ•·Ás€�$„ÅëC;‰î8ɢәɕ ,wß_7䳜�noðE‹v@ÎhpÏÌÉ‹E%“ã$æ†D5á¨R©TÎäÌÞ¸E#¨ä¥bÑÎw^þ⟾ñ<Ôáy:H³� èg9‚ªaïèÀX>|¬Ì¾ýò·¿ü‹×Ãí.È@=dœ‘Z€ —aX.‰)0#g7£Ù Wi�ß~Ø;±RyÔ©:G¥R©T*O;³l_Ö/ï®ÆÿòæO~tûvžµ´³H‘u8@c�fá÷nµCzéÒ¥_~þ…?ûüË/ãáq§yGšQ³'„ÀºIöÒk ºpIÁ(/.s ¼^¯û”"Í,¦&òÖÎÖÑÑ€RD"gÿxg°ÊÏŠˆ¸»™`f83ÒnffWÏ9“»ˆÄý´èXy¼!X0Ç`m­#í὿÷ÖÞòpÙv�IÞb ×Uê�Ö}Lýñ�gW×o¼Ò´[�Év²Þ|$W g»æë0VågÅ'#'— òé´ÅHì9¸Â‰ ®ÀØþoÞ~׸ ‘ÍÅ@jQ‚¥,\^–Ó)Ï0�ø;¢!ÄÀ^  ØÉÊÄá(–#ƒ�[E8÷i-ñGý°´Le"sÌ)Q§ €È!6ùRV*•Jå,°e6¥ÌÈ—fbwéª kv‡Èœ�Ŕݧo9ïã7ÉÐ]Âw¿¿2rÇšäÊÖ%¼ø Ú]$xpIY à8Î@”Bú$__wŸ®¥UuwÃjäZ­TîC}“T*•J¥ò1õÑéxuŠvÄ|«»üò—Içï½ñVî æ]wc·ÈÚ�éÙÙâ×^ù⯿úÚ+}–£1¬×]a�ÂFÛfDR‚œ>?wç|óÎÍù¢•BÃ’i½^¯ï,›¦=uüp¦»üý«ÔñÀ`æ2\ÏÌ€–—™ˆÀ>þE@eØgó93—áüÚxüd cšÑ¢EÓßÁûß_¿ûúm]…�æjαó-’PÒ `ð5ç�nZÞgæÒKhwÊ®Æ3àfTêÒ¼™ê¨oÞÊÏŠ”q B ¡0Ü�`â ë`3Ë9'…ë­÷¾ýÞíÀ sV�!°#�I6ê¬oò„Ê'YŒÜZ卯ä|râqÈ�,32Û@ŽFYÊ+çÚÎf³õúbb)(gnÈyúMøL•×cj¥R©œ�€È¢î)»³heŽ&1Ê4'±Ìœ ß’æüAq‹°£^}T�t”sÔ¼íȪh;%¨P–˜$!JËÆI¢sþèCÅsÎÅ –™9¶înœ´æsT*÷£ê•J¥R©¦UÓ…Á²B‹Ëù矼{m×|4³¤ C Û»[Laò=er¼‘_D"7WUa|B‘ÍÌ„%Ä`̪šR‚*©5¹'rvEä6­ðö�ŽÞÿÑ‘·óp¹ñ9Fr2•(fÀgÌÞYX¾ŸÞ“‰»;-„‚²°3J9ÙTâ=Õ,Q¥ŽÊOÀæð4P±³ÙH0†èŽê•”GôK§qwû0;Å5ÏÚÆÆÍràN}ýÔ+ÊØ,ZÑúCbvâ‘I‰•Áqcw§¬l™¡„Uärïól˶\ÎMm5Î]w�ç ¦¼9Äavv˜ò”;"õ½R©T*×bc)«+‡ÀÌÉòR³´­ +‡Me$�¸ ½žÞnÌg3ž5²µ˜ÏbïÍf˜w™ÚÁ�‰38!g€'q‚ú1Ò…ª»³{ÜŒJ×pŽJåÛ ±qtCn5ÏŽ‡¨¹#?JëùÕKi½:^¯w»CŸ×c¦YSª—ä“SÃÉqѺBÊ>¨FPH9�1­û>œÎwÛôœAµês�˜™ªÂ ò‰ë1wgaŽ̪ã0 ’3Úæa?÷ʃ�½!4‡ûé�·ïôû|}ëÙ¼{=ëfîp…L F�`¼èfrkytôþêèêÖöu¡H 7QžÚå͉QªÉ5n ò³³‰•%°\b-؜ͣc†|%Ùµõ�“:–ýqXЙŽCj�¡0ËâÑÈ\¶Îf`F¦ÑÐ&Oîq^‡0ˆ�cž³˜5ª„œÅ”à`›d<»ï¶Õ|.ăÎ-_±°CÒ1 YÄa0ÈŠè¢ Çç:^Y©T*�,ä€)ÃAæ9K‰h=i*†p(A É¡8Dâùk¦‘ãò¸_ÇqˆÁ—Ú7iØÊyE#·3 �ÅÁ`ä-d xº—qÛ¶�1º{I¿C9ÍÔF­Jå~T�£R©T*•§ˆ³ŽUØØX¹ë�ŽY0ç�òH+‹Â»By´ç¥ãÁ¹ïõÆ,XŽ �f¶Ùîbu2Úêµ÷†‰%*%•òÁþy”WA�™¥˜$Ih 3‘4îÀid±¡ÄúC˜8y²†áòb±\.¯Îfº¿bfœRjññ©fffÃjeÍvæ‹Åbdv¯–'çØÌÓ*üèõ·=Ïwª¼NhÚÙ4Lŧ‰Íæ ji)[a[9¾þ�Ÿ\}åKÛ—085¡Uë7j'Q͵`[ù™ M>8NÄ3,Æm;ËÊaL[ÐÿÓ_þïÿýï½þãwÞ`~¸odܯ#gô§ªƒ“ØÉPÔb Çè”- j“5Ï?ÿÝ£­åùb+-�ÃÁò^x)}psFˆÇÇDZéœSçã€8æt½k¾ðìsþ…/<ßÎyôY׎ÚÃá>å�8A‰� ú°÷y¥R©< 4¯˜¸kDut ˜‰ÝKoV1l'QzÞî(2´i™ŒGæÈ€7Q²)¢æÐè€SÌ*Î /Š÷Ð�欧Ò<tþ°�Jå©¥ê•J¥R©<í(ÛŒ¼xÃpk�4#åÉ×ÃÄMÜ &fÊ– º1¬e/~“š°Q8xZ08Œ/ØOßendÀ±ùqŽ3ÓV~™ò¬ö^¢`f¸3³™•¼�’ØñI5érgw"w/z3£ÖãžØ”òè}µèԹ Ec-mæ%´™ J™œÅ…k` ÇwòâFfi“GœÊu‰_ù™!8—S) `rÇúàˆŒÃ8Ì‘¿®\þsWúü§ÚËVŽM÷Èö¾yIû]ÿÌÉÖ Ë‚‚ð>p ø¾ñÇtëƒwnßšƒ¾úܵÿãŸþµgݯIœ'í ‚ó%s`� |lXª·®×�w³åÕz9,cÙA0ßD†œœåü;§R©Tžd¦ž'ßäÄAœKo–l>Ø™ÝÈadì|ž-Èàh‘¥Æn ÌnƒÁ%Ã� ì¹±Hew¶iÖü<Û:�W©Ü�ªsT*•J¥ò´c„ãØ39Ù�ƒƒìD pÀ@æ°,Åõ›­8ÉL8é¶>9dã[eçÏïûéax$—RåSL€|êŸîXŒþO¾«ò€`fd‘œsG$, {‡‡ÎR´g7¢2ÛQĪÎñ$Àf¼Z¦Õ2G BÑîóIáÀ€R&R10C€1khÂÍ›·ŸýÊ –˜lo\æNËâÀs×¹Rù,ÀP@¼9· çÅl.¹màò% �ÈVк/:ÇI#­mŽmgŽ‚rF0Ï)¨Òl§w>žñpçàæ{ï†Y Wb÷Ei^æ£IrßGà¼ù™E›ù6CA¢˜çq¦hÍb>æáÌïY«g0Ìêˤò33�E¹0py’»ˆæ›!]Ö¸t½<¸´˜ËÝ/¼³§“{Ïn†Ž£Úˆ5™ZŠAgxvqõÆöòÃþ(¯ú¬kɈ=âÁªóLÈí¢)�Åç™çPçÃÃÃF˜™&)3\YŒ¹œ¦qF2!*)Y•J¥R9ÁOš&ÎÜh œLªÓúFÙ”À0;ßî 凜ñé1` ›f˜ÝŒØÈ”°¹&ºÿ¶R©Ü—ªsT*•J¥R)œ�6�ª§³�D(_*516�A“�PÌgĹÄr(ºH.q¯zmNFvæ©zéØš~ œ:Ý0üÌ畇»«j×u‡9xSsÿÄz?•É�*u<1ˆ±ØYŒ¥„ô80ÒÍ+"8�<íFèHKHèId0õH¸ËwÎëû·òÓSºw‰&oßhëa@L ÈùR;—ý±ÌüžCÙ'«‚ѸÆ]êÍ*á°�ïÙps˜Ï4R+ÍVÂeÅ6mmEH‡úu’óÎs€ìúÖ ž)›¹¹˜™�>Ž"|ò ÂÁ`V>3|R©T*O7S‡9^• h£ —[ʒǨLwLþ„çØ2œÄ˜ŒÉ™Ýà �P6�+ÃØØ,‰• %#.=açØr ²«TîKÕ9*•J¥RyÚaç&Oµ�)�ÃOJ#Všš°)–Ð&u£H'ñx%�CNE§þàrÁRQ‚ç•ÎØOlr*E‘(‹ÅáÔŠêS037'¢BŒÑ˜«ÎñdÀ€0ÏB˜7mÌ E˜Ä g2%ƒ PªË€ÇR2v8‘º§ÝÝ]"˜�88òæ�{—æJÅ ®Rùi¡ÓX×b]ÅNhg £i�>¦~<æ!'×!ΜPRÇɧí= á'·qnà ÄÁÂì!„¶íbÀ*†¡GŸu�¢ušZ}ï»eäþèP,‰�™YÈ…œ‹`câ gv˜p¶.V'+•J'ËŸ,|”@0Š©•”ͦõΛϱñþ%8³1Hœ`#(XÉœ¡ e0[ñàœrAçØz�é¨TîOÕ9*•J¥RyÚaCt>1˜*ßhE3(6×ÙåR~þpb09�d�#�ÌpB@™/.•ܹ̠óTÀâÍóÀ]õPÀI2y­ûp% Žwv†SSG4có$ÈŒu(ÕIˆC   ^¹h„GXØʃK2_15p+þìgS¿*O N–%²`”GáQlÕ$�ùØj„‡Ä!5dœ¢ €âSësröÀBw �›=b+;â5†(º°p£1C³…†�°�G]‡–š¶¡<(©5–ÁžÙ{Ë$!rG�sfV2Dµíâ¶È|�ûßxÒ6¦žzݰÃ@w9”³£è:•gUžïàê^{íí|ïR»¸D†õвÞˆÐ( axDOhÂØµGMØ~õe<{]æ‹å�ƒyJû»‰Ce(8ÚÖµ0Hl";ù¯ÿÂÿyÿø]BŠaþü³_Ë+ä˜DØ| vÕ×Χa„UZÏâö+_»þúúýåÞÁ ×·âL]`bPb–9�j0ˆ{îŸýÒ‹Ú‚´$Ë~¿�/dX T®<(¦ÓAk0‚ –„L&V•ŽvÑ�f;]ÞSò`žŠ§‰cr2±3:GÑt ˜e‡Hrf) ezçP¦¸“¤M:ÚZ/Ƕ[ æ~=²ŒîrÁúô­´­ÂVå}ÁR@=ný�¿›9O�D{�W*•Ê£€�$‚‰C¼{Á(eXб!o<¬ÎÍŒ0 ‚xé!3›\|™QÄÆ0œ¹T+Èlóƒî·µÇzõR¼NtŽâ › '‹µÏ«&VÊY¥Ü$gÚò”&µ85v.ãÈ�N½®òIT�£òHãw™2›–K™¦ 7�QœŽ�o~ûf~péˆC\ ]̱™sh“uý¤Òd¥rcò)ÜòcÝ#ÇìŠ<Ù³¤yr ƒg?_BØ—È ?^9w9GÕ¬quë–^»Ô]Ùõ¦ÍðQÕݱ€ò#V—ŸwŸÎÀp"gv†»mÎ>b'»ˆ-³9¸è ŒÜ‚Q£DÊ ¥g\Ø�M{/È�Ý<³[ts2e8CÉJ�—8Wؘ­!‹Jl�@dìV\t B$ØD‡ÕŠÈ“ 9 ÙÕ‚2{C¤JHœ©5'7VQ‚!8'7 O­ÎñIœÝW®=sç`/'iç™Ã~¿¨iºf逿VdçÒÖv·µƒÃ½ÕÞÑÕÝ� Ìœ8܉E瀓E š‰a¸8ת‚(àô„1]„žL —ÿØ»ü‰%„æp‹ù�oüÃo~ç�Æõú Û;ÃÞí–�®E`À5¥1kšuWî,ûå¥xõk¯Í¿úe�¼¿^wó¹éäoFÎäÆ`Ý,J/S283Ïš�®~ã¹Ë?ÇL!r5H"/ƒ—î˜f +ŸˆyˆêÞìàòóm^é`oiÚ4[pÀƒó4-Æ®B‚ˆ�Ö=V—®¶Ï~qgû ûuò£ù"xN '/Ö{Cw*•Ÿ'/½:„äÈì'1NBÞ‚Ã@yÊ,'žVÍ%ÃvJ²ÝŒ žÙ*¡˜³3™#;»ypˆQ4Rv�Š`àr™Z–$÷hŸ¾=óv€Ø=¿Ýô‰V…£R©Tîb#˜êÚgÍlÏÆ€Mœÿ*ÔÉAÐ�Ö,|òž”±â~9”NÔ—ólwNþ·9Ùíô‘ÛÏéíõY·£LŸXÈ”'¢w7É=�§‚ªsTK˜™ÜÜÝ7ß9g]®h=n#4Í‘›eÊÓ�· Èã,•d30(S¦3ݽe`Åqžgˆ+,+—X¿M€á§l3Inymºb„Ø€Y”ÄŠäÖ·ž´[4jlfD�»‚©ƒ'Ãób®5�u‚¶ÈrZG:"ëÈŠH.'ÏŒ­ôl3råâ îv±oG&åO,Ó/xWqGüÞZUC�‡Ô0Ž©žÝ¸~õ襃ß=~?Ý„n]¾´ú¡_¥ã#c’6ÆÙe�õ;—ñüË[מC˜ãèxm¾Íî�Ëtæ©ó½R©T*•J¥ò8Á^¦ûO®ìïv†ÂÇ)¶åZ+zB©:Gå1¦èL$"j–‡ÁÌJÖÓ˜²Î¶V at7¢„8(Ñt„µ’øIÿ�AN+ÿ¢Ï�¥�€µ;Ú¶^»ZGLdm$ÌcÛ'…¹ˆ0û˜„ø°wê=ãnHìF›ézL¾_e�ÞÉ™¡ìp€œÅ `�bòšpœø\Mƒ¢¤(n•¬Äæe‚„cû©CEdgƒ(‰ ¹³�˜<ˆ©›ˆ‰ƒ‚n†9N!+O"i¹–!çljPCNHkÅriVî`“¥>œxªz?ÅRǧ“‰mq•.o¿™ÒÿôƒïýÿÞûuOï@ǺhÃòûï-¿ýî;¯-vþÜk_û³¯½Ø6³VR4ña-™B`�jâ ³±›Æ–KÿëEëvv^Ç@|’¡œ„ö�–GÏtãV Ö´ÝhÊãÐ\½ú¥_ýµýýàΛo­<·óYÜš ³%ØhHŽaÞ>ûÚ—v¾ö\»|˜Æ15­ÚtÐ.=SålÂg¹‹#Ƙ3™™ª@6µ¤ª]×€³;¹;œ7 ê{�?Â80 ‰4m”­ëŒa æwÞúýuˆ RƒáÀŽNg—èÚ/]i®ný°jç.Þ®†ãNZsfœm“Ä:µq®T*•J¥R©<(O�xee¦!øI~b™\°¹ÈãbuO’ÆÚÞ÷:²ÔÁ´Ê!�Uç¨<–˜™»»ÃÜ`fgVøèX‘ñã.}ý+Ô5m3#µf=‚¬iT1s4*ù##ËÇäk¸–0);9FâóëbÜj£9ɤ?\~ïûÇwÄÝØi‰j–2³„È·áÑ J&Xð$îDa“ÅåœÙˆ¨ `N®æåþŽÆ‚Q„•(‚‹ €³fhfIÁ•`!®…–‘£¢Q�¡MÔft‰T13“+Vq­t(ÊÈgVV%Ïä ud€ƒ™ÀØ ÁLÝæ.0”k!êÉ¥Ô@…bœ/¤›wqh: Ô©$�:¡´›G–“]´b—¶Øãþá�~û»ôÝaÙ߸š¯_As f¸dYiÌË[{oîÝ~ûõ?ùñòàøÒ—;Ž;M”Ñ,’AÌŒáG†¦dIJ<ÆEÊŽÎ@`“ÍèŠmRÓy9бP>óàó@10 ǶCVã¶¶›Ý�gv¶|{ñî�~Ä9‘š©  £yá«_ÛùÊ—ðì3ëœ5Ñlb«½‰9Q1•ˆÀ%ý÷‚§(Æ1‘Tæ,™æFîdf„H6:G-²"FðàIÆ^Sí>Óîn=³wï½9îÝDê‘€Bn:ZlÍf—ã³_Ùn¯Ïp¤£®›Y2Kêeu{jFõ�[©T*•J¥òØa„Ì6nÂÚ ÅãKJGñÉÝÎ]\èj>mr8ì#þT§âJå1¤ê•Ç3@Dnæ"bf"â<ŠÆàÍB¾ñóW®_A7‡9† Øn�AÊp¡ §Y}÷R,¤¦?Ýžeh‡u�…bïÃíãý£µhŒ¡IDH9­{SGÓ€@D$�”Ì ’@@-˜LDÎj¬Dd“M¤Ù$x€P†s&qb%q±›LìÎlÁ³ëdÌ]<Ĉ�K¢ <ÀAîd šZ7ɧAñ’ç1*ÃäLÈÁSãÙÔƒ¹zf$CdGðôYbÃ*�Îí|�f_uì׫¬GÂ7BÛͶóP2e Á&óëÉR¿r/åýÛ‡ðºâßÿèÇÿùG?¾=ÛÚ~þ¹$œ{ÅX†Ç!4»—ú°úö¸Þ{ã'7¶·ÛÝ+ÛíVZ²+„!p†˜&³,`d‰/¸8I/á?ÓŸyû$tª¯ó~ vÝ:§¨©½rùÆ¥_½ñÍ_öÃýÛwމhgçÒΕk¸¼ƒY“X—Ã0ˆ ÛÊ$>²7~OZ½�>�ÌE3fØ,›«ˆˆÄœsi­ 0ñÉ0G-µ:&‘ ãzÃHóØÐU\Èš­–ÇXC± »»áÙg°¸Ü€ÞWmÇéǵ‘5³¹%goTߌ÷Ôó{¥R©T*•ÊcGéi5›f¶(9šÅ.ýt‹ Þ–h÷’ÆqRÔ¦ÀÝ%rrÅotšR^yÄ©:G屄ˆ„Y„ÌÜLOd�”4�zŒtÈãÕÅ‹9¤�b %#Æp6aŸ!­ÈÎ}OÀ9Â1a>_AV)7Æ£fVBR²MüxN§ðh9 F4;Ð8Q‰áPŒ³l*çÉüËØ�¯B(g#72'rÒbcÅð`h,uš¢qkÚ˜G´ÉϪhONÐMãu4c·hI @0CfçÖ¬ÕÜAUÇàœ]™³uÑ×\ë O.Ê8J=Öó@Íbˆ¹o°6ŒÃ)–v~€ÙaÎäô:Ýåtê§Û{²ìÊ›dä=<üÖá�ï­–´Ø uÈP`>£ùÌÇ5Ò€QÇÐðnìÓ�ŽŽÿÇý`û‹_¹ñìÖÕ&"QfÛü@›¢öÜ@^|ç.¸ ۜҩtAvÆéètTΜ‹âà33Ò•Ÿv0(÷cf JºÊ:“¸½³�×kéæ—¯?wÙq½HgÍ^¼ÌY$:Iª-9X(ßwÑR‡H$"€ÜÕ�Ü)›iv!àDR‚:ÌÌÌ­8­G 2‚™Ydn¤W¦‡8þ‡·ñþ[Ã0pêáî1èrßW{aþ¡^ëïôÍ¥ÀÜDNˆ€9•¤´“à%#ØSxH¯T*•J¥Ry|aX0‹0`Ê»3·Hæ0�md±b== Z|4(þÁl#¸Wä &ËtàGªXWùªÎQy,af!K'�– ¹ËMävIíÒ($9:Ž2L� fLuOû´x"÷Óω66?¯ëBpf b£AZÖÀNÂâ(MËÌÌã�á."�X‡¨32@vH’Ù%ÈÆ¸¹—Ñ R@™<0rÙÅJ¦lÂîä eäàhŒZ[’Kð��Œ4 2›¸™16cÆÈ‰¬Q™˜™á„“$y+…Äa³¨1)»Õ~Ï'Æ@×^zöµ¿ðg›+WüàÎûóçžß7OÅè†Ì ìÎ17£zu`òÖÃæíQ>ÿÓw¾ý'»v•8öF!0Âx8@&0ƒ¹5‚Ø®Úôû¼óµgn|/ÍBˆJr´²©9³CÜäDú¸ðasî�Nó„œN“Æus`fLî7váy!Ot!*BÖ1¹…ÛöRÊãÍÕ Ì\$NdLîÙpgÿ‹v>ßQÃ0(u¡™qD7D+‰N¥Cáb¥"rw3cæ˜(03æär;‘(w©/ O„Ý’d4�—·dûø–ýè»ï|ðãeZ5‹îªxlm‚aì×û®î쿳çK¿üü�Ýíu¿àÝî"­VÇ�™£‡�2Á|꯫RG¥R©T*•ÊcC)•¾'à 3ÍL']Dò¹øV•?+rL·ûæIz]0>–T�£òXbf"¼^¯»ØpC9çNÄ ‹Þv² ÛÌ#�Xbj� d!HÀfÒbZ6_ä"™m/€ct]ŸU‰™ƒ'7U„ )‡®Öýl6KiP3ºPÿúÏ䡉hö‡uÛ^Îû#mͯ «Ôr÷ ØÑÑa¶´{i¡>g�+*ŒÖlãl>_íowÛc^w‹Yƒ1èz.都[M·Xë‘Í/.×–»]c€22»’� 0qóŒÎ:²#2b0+!‘)tóÚ€v.&ºÌ7ZáfV‹ O0ÊH·4_õE$ÛÖ^94(;î -ãAÁÀÎÆO]ÿþÙžçrÅf@JiçÒîÁÑ¡M×&Ólzkoÿí[··.)ÃQ¤Šrµj¸Ò €Žôì3ÿóO¾ÿ—^ûùmàúö´?ŽÚ.ædb Ž`E’|�ïÄœ³ˆˆÈY!'ëÓŠ‚ÅzÈÝÕàF‘æ#‡Kʵܵô =ì?Ñ“ƒ�™À‘ÄÉMÑ›‚F2@næ\b«ˆ¸tå·Ív|3�’äðQlZT8A7ŸDT^TVzÈ€4{q–t‡j‰N„ˆÔϧ@@ Üt>÷õ£7ÿëÞp'Ìü™­YëjNмÊdMD+˜©ÍVËá�~ÿ­Û‡ù+¿ô,·‹ã££v;ºòwpÀ¨˜Ñ(a#XV*•J¥R©T5˜Ù�˜Y1_af¦@Ä�,]A¼¹®›¦íÏVê.x+Ü�CXDŽ!­S±Ä³\~òÓ.ºÊãBÕ9*OìhÈ€‚í$µR¦zI1è'ƒñiS÷g­ž|¦û”à€ ±ï¿�}<uW%I9„y×¶[+`nÉâm˜µ–€AÅá+³ìyß™±“g²Ð(•ZÕô˜ø(´¹�-›féÈ즿|µ�­ÍçC×Ý ü.!ͺó*6ÙT ™©¸í32¹w™¹�Ç£†û@bÇ:Ú_Ì¢‘;„<4YJóøth4Æþñånk\û�àÖîüÛÖ­ãŽÏgo3}ëöòæøÞn¶&¥àd€2³‘û,qc[“YV™ÁÆmÆöÈÁ�̳Р�^›_ÿævûlÇbJa©<‰Á‰’ðqä‘A#ÒMŒ¥ ÆSå”k]òI)‘š£4&tóÎížáa“¼‚+Œà p¸nV"7€LœÉ×1¾uû®\Ë£*Ì'R'gAq–cŠ{Õƒò +®A¥3(„ R†žq¸w,Áƒ4]œK”ì¦ÙG‰ÎNìNpsæÀD`h}I<@Œrv¸XÆÁ6ýO›w%±¶ÁÒ1õlòc&‘ccZõ9v$ø~w¨|äTZ›¿óÞòÃ7ùø™H�gP‚0�²—=é ¤ˆ¼›{=úp|qôÒövs•V Äß2¸Ù4âYå�J¥R©T*•Gš2sÏÌ\ZOÝaéŠ7|1‰·O(��¬/t–‚uH £ îB`™ € • ¢ê•'+ò† ’N€À€£ô™–Ãlº;‡è"`@9!›~Mku'ÌJçcÚE>‘gî’ðÝ%þíýÃ?xó­4›�Y‹ÅB"í/2eé˜בŠñ}`—65äp²!ØÐº�ÆãñêlK{;„^ß]e†· æ õß~÷öv³K c²lш•ÙÈØ� âÙ ƒ„!` @£˜'Þ([Œ)Hð2}=~Ø|éW¾ñ æÍ.Ö¡æE=©”¾o'Ê ‹16¡D³œúÕÃéi”:Š‹ý=©ež3kÒÀd†ƒåj@9LÉÔTc*—¤vúh°L ‡ š†ÂjÕ·±ôÚ`£+ÓÔÈ_Ò¤ÅÓaðÁø†õ}OD!fÞ¸ ™+ï´—U5õ©_:‘†š¶ mÆ#v¸¹“™3„ë¡á�S<…˜6 ~ìft¶$í§Á04½…Ù§ ¡“q°mÆ8Ne‡Ïã¯uVäøØbº}än•�‡�oaˆwÞ»½>Ы²E¤ˆ5va€Ë!Úi:*Ì)8v—냽Ž®¿²½¸ R‹­˜�›—V‘F6]xu˜£R©T*•Jå‘DDJ�‹ˆ&�ƒhlãÞ ï”®cÙøÐ]—Ôå’ÿôjû"�o7×k¢pQ30s” žJwt]0>ŽT�£òä`„A0D †U"z`,ù¨ 8t“Fk@Ñ? ¹°çC€œ¡ b Lò†O:Ç& ¸¾�/6eõ³ãª&œ=ðæññwî|ð&�6[äù¼Ï©iÐÎâ0ÛZç•´ÛkÚ+4´)–Ãu)#4wž,̘èȱl·ñÜR ‘;ŒëÁ³‡Hj@h•H‰�Œàâ9XNÁ�K�A Ž1C00y8†B6ï6;8zkïÎêÚs•ߟ`h3”Áà gØM¦Q`dDì�8<…RÇ |&KÍÝ�ÀL 28˜8sñ4v1e®ˆJXA)Fz†ƒ N d�Ðf„ì�‹ŽáV*ÔqÞLû–÷âƒÙùDTò9Ü=¥”s&¢à±¡KìDh µœVãàÛÆÙA07EV8\ëˆÏÇè^3Fú8}â$ͯ¨¸ÛôÖÉ” ¼ñ¿"ÆæLJ~¡/;m5ø´€ësÞí©ÇCàùú@îÜ<Ìf�{€"tpƒ#*-ë^ÄÑy«Ò­Žî,ÖWÒÌ57�ÇQAy³Ê,ý€âª;¿R©T*•Jå‘„™Ëþ´5ƒûaþ¯¿ýEšr#ÁÍÊ''ßh'KÎ W!¸9j¶³ÛÉÏG "šÓÃÞ…•ŸžªsTž(|Ó:P”e±—)”¯øævÂÔ¶yžíéã�ïÙœ”Ѭ”þJO¢Mó0²3F.�bÑÍ$k+#c ìc¹GKßmh'Z¦èíp|<ôG‹Yl4ëUœÍØ .ŽÀ*œ1(Crn7ã˜hÈ’%ºúí^f :æà¨™uŒ¦ÂðÀÄ¢Cv ¥hÊnì™]%Y—ÍGdv†µj]†¤�IRÇ9'4‘¯-T‡c[¦tÚÓÔ‘^yc±’TÌp'rˆ àÅÓßÉÊ‹3ª·æ)äÎÌÙIª \½zu¶×ïksÀ0™¡ ‘›™ŸxÅ”ù³²M.d7®^šäm¤Á!Ì%ÔÀ&çm.ÀQ®$�ëª2bBh}k} QA ƒ94™�I‚Qt#s3÷LìpþgÁÊÏ€“Ù‰1#�œ�PF2ü®w_y…16õ%›{*•÷ïtoòÏ!™ãô—d› òÍôÙ™‘‚“¯U>ÖæðH×ÇÚÆ–ëó58 æpòÒÂg@,ÆTó®]¦ñxÏÓL(»Ѹ™úàÉ€ ·Gð’©R©T*•J¥ÀÌTµø €*ŒW1¼åà 0ÓÀ‘H�Œ2£_8�ÿ¾à¥™ùÑ¡±S”HJÉÌœJkß”ÏqÒ)Xy\¨:GåÉ�ÁÐ(ÜÐ�Ñ%Ã�b{àØF øôð)n÷þ[|65ÂyúV6¸±—o¾ýÌ<Ç£‰rÛ1ÏÓ Mêã‘Ê24³±ßn/ù«ßè‹þÖ�gº-Òîh´¹´™³²Ã=¨Ï’—Ã<Í&ó Ý�]ì!ï°J“g[ÕœÀäªp#Õ \Idẫ»˜ˆu®<�`" G ¯ž½òŸÞþ–Z»PÑŒCa,:Ç õ(÷¤"Ž`€ó(ì 1œ÷³æþÐR”|„ßnŸ'ªbk9‘YŒ±Ï‰¢¼|ã…ë?¼Ý§&›Žž3´LÇød³ 'ßd*Œ]¶\¾týùfÄ\)›2ÀƶyëìîŠï–ˆÄÍl†þØìÖ•áN¾½w{¹:�†¯\ß¾þÂÕKWâñ¨ÒZ±¸¸‘+¼B�øzP8™Ýu®ètÖûdy`§z†)rl(áUNØ�O“âãâDwÁgLßô4œm!³O¾såS`M0P‘õ�Ú-ºåÊ•P0”A‰‰�3l=̯p0Œ«C¦çº–r^�dð€2ßãÀ@©J•J¥R©T*� Eá‘¶iÛ¶…Œ€“k³Î ²ÂLCÔœ�Ť-aÓ÷žé¸P»q�¥¶�È�f³YŒ1XRï¹ç#æºR¹µXyÂ0‚EPÀ�ÝÚèÀT¤à�S³~šºIï¿ÅgÛàòI U x2³r&x„3<’gL­¯çŸ/arb‡Sb¬IÜÅP¾SP&9“gw£Ó#ô=ÒøÙbÁT×4ÂÚG…Ö‚y”Ø4]hºõjøâÕ�¿óͯ `à*�˜œÁÐnvCÀ À�›Ó0ÍiŠ # ›oÑ»Çnh€0ñhó'=þШ¿÷á;0\×ÈÐÌ8Ö"È“Ly9‹A©4Ÿ†ÜЙPŠ“€ã§Pæ¸çšlR}Üfrg‡° :‘gw¶/;–¦kÕµæ5ap–©‘š6¦_^F¬0ÓtƒüeØ®‘ìØÕ˜ˆAb웟 %Žè§ãd €á�¼ÌA�äÚHÚŒ¼u¸ÿöÁêÍ›Q rž'ö·o¯Þúþ¤ÿïþÂ/rV�£…A�²3ÕëÕŒNã¨6;÷n[[cg;Ô0'v‚9ÀV´�³sW|jiõùÉé^‘ãïæŸÇá„2Ê’oJk'À�7‡8c2¬±|yìŸ[5)vÄ×úå֘˛“$o0˜fÜØÙ.>Ì "ˆmk=­×¤�maÿ�L¡ALfð’Xf—0fÛæ6 ¹å.PŠAÍ!p>u­LÞx�`žY¥R©T*•ÊÓ�1>ÙLÊ3D„¦ š/¸§±_­å&3±{Ι�ºªZέˆ©úÝ ‡²((I~â%é–ûŽbìCHÌ·ÒØªFË„S#‡ó?yvkržG»½Z?äùÚm(*yöM¶.ûi§óEÇûVO£ÎQf‘Ú¶UÕãããÝÝÝ“/½óÎ;/¼ð€ÃÃí­­)0çX.—‹Å¢ï{wŸÍf)¥ã'Ýy†¶mÏÞ²¿¿éÒ¥ò%fŽ1~øá‡Ï<󌪊È'=ÎÉWO~\°zØ;õ‘À ™al“R89Ržì{Úá:olXlºå<ÛÏ497ý„Ï0°‰X¬ ê�;,•B+¾0×™„®ù(´¾©ðßÄ„Œq+oÍtE‡÷f¬–Hd¤(žÂ°<Þ¿º}}èûyŒ«´ä|2â8Q 6ÇëÓ„Ïâ΄E³¿:¾4ïz`>îŒGír{bÃÇw^^®lDˆpØÙ¤¨“±obQNRÙ¸øÙ�öÍí~F–:™ ¡Í–ÇÔ³t` àù;«ùÒl–s»e VixpO $)VtVJ¥&z&‚ËçwÇ0D‰n„ƒáµÜ4%å0 J‚ØŽŽ¿ñâ³ÿ»WþÚ(ÌŽNµûNÌ�B6L>��N�ìÌ›}~qÏ?–‰Zñ[wöž¿t=0Þ|—¶� vçœ=«@a�qùÙÙí£ãQìúöÎj¹ŠAÉØ):ƒx"‚±óÿ •J¥R©T*•sàp»2á�èЬ©þû+ÿû?xý'{‡F´&$f|$Ãïžná“I©!DK9©ÇÙáåkÿ�?úoýbŽù–üòö¥?}íZÓØêpÞD'a=÷’!˜unÈ_{áÙ�K_¾t}{<öœ—ãjÑ6¥ËÈÊ …Êðú#mÇR9ái,Qáàà@U¿ýíoÿ«õ¯Þxã�œó7¿ùÍ?ógþÌ×¾öµo|ã;;;GGGÛÛÛŸô ëõºè]×ø�ÿñ?þ³öÏ?Iê3Çq6›•íl6ûçÿüŸïìì”Çyûí·ÿÑ?úGªº^¯‰èìÜÖYš¦ù›óoþÆoüÆÎÎN¹¥x”ŠÄòô`c3Lqß'7cò/©•–Á¥æ¾éÈü,ëäó+"t¦¾O¥“ÙIœØÝLàH)¯RN)ÏIVMð!%6•üûlÙ9­Žú±ƒn ;€IDATïl€Xidæ2‹² mFSòàC×}ÏÐ>�a r ð3î"pP>ý¼øÔ8œT�Ž2Æ�ƒ[4ä]ÊÁm nsà2pÙ€ˆèdP䈖ÎwTYüTáÍsdLç”/;£v™M' FÐs>•Êã‰Ó‰âupö²æîØS¤pœÙwýó£—eä=Ò1Où/>ÿìáñ±Ý¾ýÁj‹Î.ïÜGìˆKW@ BØ¥ÐFëõîÑþÿáµ/}mktyœ�¥é"“pì¤Íc*âRé=w:£Y~v]Á F†)ì@è×ã,nóˆÛïÜúñ*ßîfëkXs!»Ï°É()@vÈóá»ë¶¯Ò|öÌö`¹Ïº™�å3?�ʧpß“i3NïöÑýÿ±¯�ÏkEqž‹�ϳ°~êK¼Q+OçÕNžIã¹òÇ~¿ã��®�I€„4›‡´Û6ò¤ s¦ê–Ü"ƒ¸cÈ0E^,ºùv'BDB'÷²âs5‚Œ)½ÏñoQ©T*•J¥Rùx¦ùÿoçÔ›¥®; mPwy7oÏ(6�,‘Ï›�ÛÍ�<ûÚÛ×ÛÅ¿ûÍï ©ÙVÓüüåkù•—®áz�ê–Àç|ñÜÀÙ”€–Ã,6ÁÉ"…®q€üôêù¤q°òXðÔ•SJÃ0lmmýÎïüοþ×ÿúÖ­[/½ôÒõë×›¦ùÖ·¾õÆoÌçó_üÅ_ü;çï\½z5çÂÇï¢Ùl`½^ÃpéÒ¥a?Ei۶̎ܺukww÷àà ïû¦i†aH)mmm‰È0 1Æù|~tt´X||˜ˆ®]»VD޽½½cùÞ‡½_+Ÿ‚À#`€ÀÙÉA2bÛ¥=¢8XZöN„S#³ä³ó>° íœMÚ ºµê·FÔøÚöö:c&BmDˆ2›Q×ÌÚÖœ „»Òä8õËb¸À  õl1€8®ôÃQʽȂ$bÎñññ{ï½wxx¸³³sùòå³OæaïÚÊÇÃ`x€ç“ÞC#Ý?¾}™�²7vVÐ%n÷�ŒfŦü¾[·m—ôðP÷�ÓÛè†f—=y€Í®¦ckô6s¿¬ Cãä ærrb*ýÑnN(–68˜ÀNL. Á–{mEÔЂ .‘¡á©L:¨Tždõíãå¯\»òÌå�ÝÝ­ÿï�ðݽ[ýú€f�´Ýº“m‘Òe÷/.öÅ—õ‹/]â^‡Q‡4‹Í¬imHIMSþ”ðŸÏŠSù Ó@°(Mtܼ¥‡7=­bLHÄ©{êÉh�ƒmhã*øöÑ~þFhÛ”ziêej¥raP^§ÕµË[Ͼ¸óöë7öÞ¿6{e¾t„�Lwá0�î°ÒåH˸hºË�ÌHó˜-‘J šoGv®oàJ¥R©T*•G„»ã^!îA@ŽF³LœB&ØÉŠCñ§n£�bi ç(í¬™5�ܵód�;p¬­_ƒD²|†Ç÷Ñ E`NjjBhBДÊQyxêtUýÁ~ð­o}k¹\nooÿæoþæoüÆo|ýë_w÷ÃÃÃñ/þÅoÿöo7MóÇüÇÿæßü›¿ñ7þÆ'=NÑTµïû®ë~é—~éŸþÓºµµµ^¯?é[RJÇÇÇ¿û»¿kf?üáÿÞßû{ÛÛÛfÆÌªúæ›o¶mBøóþÏÿõ¿þ×?)¤išçž{NDÎÆxT‘ã‘…¦a‰ÏNl%�—óö¥s}óÝ?üÑ~rëÖG‡hZå<,®l+�{ŠÏ¥Á,å5w+ŠÇ{«·úC0(`ïýï�¿ÿ#[·i;Þ¶$dPÍÔªqf‡Øù®Ç$»ëvgò8ãË×/ážþ«u¾�®‹îÞcõ‹¨Tž0Y<¡Çó[‹ÿáç¿úÅ—ŸÿöûïçÃw?8:¾uë}OéŠ4_¾~ý›ß|íçnÜxakûJ×{Çê9ºØ°ÃÌÈAþÀª�'y"@m\û]³5®ñáÛ«þh6—…"† ‰�ØJä¡„À¡ºp…}¸sûøÃ·Ç«¯5™¤D W*•‹Áb›‡ÝkñåW¯¾oý¸Ú']Dj¨¤ö‘°îÈŠ‘Ð÷ûag¸ruvùÅy»Åƒ­¸!Cž‚ºhê¡cÈÓiEX©T*•J¥òXà¬@€yhr›ÏPt6²ûn°5›ç<ÈhªjD�#:¢¹7j!k4ká hÎBÂÈŽÏðø»Náp'‹0Hhе¬-5�/O�ÎÑ4Í?þÇÿøÎ�;/½ôÒsÏ=÷·þÖßzá…ŽŽŽDdww÷üƒpùòåù/ÿåw¾ó�½½½ßüÍß¼'<ü3s÷cŒq½^Ïf³/ùËÃ04Mó±÷/Q᯿þúïÿþï/—Ëo~ó›ûoÿíò8%/ä'?ù 3¯×ë_|ñµ×^û¤|wgæœóIöø§˜kU.S¤ªcŠÐÞ¤Jl5,±¾ý÷þ·×¾?¦ÜW‹E#”öÆ×�ÓyßD¼Í9ë8„Ö¸I‹m˜@"úkkÉ=5²ÃÞÙHæ‰ií<œyŒ�m¼¶rP'�¿{qgïÝÛ7¯~cȳäƒDâé7Ö£¥ò„`Äùøø(÷—¯\ûïvv_ÛÙý‹/¾¼J¶»»è“q¶›v7p€êòèਿÔvHÆLÁI‡QSnB!hÊN`@ö'ålSŠ’22Á™æã ·Þt9ßm/¯Ž’ë¦×Û§Ä:PpÎë¤m�õÍÛ?ùð¹×^ܯsi•ÊÅ`d±ÃÁÑ-_yõçn´aõãïÞÜÛ;ÚivD$3³A²Šš¸K é0ðÒ3—^úò�Ëϱ·ýr<ÈæÝv?(ÜN§µŠÁæôI¥R©T*•Jå‘à¤2DuÀ  Ðr`d׬¦â¦`Øý· ô‡�ÙÈ€³Zu½Ç>¥œ2�“˜EvÉYÕ|Ì�€s>¾Ã( L-+1³es3‹RK¬�1OÝï»ßýîjµ*i÷ïþÝ^xa†’«Q‚Çÿê_ý«¿û»¿;Žcß÷¿ó;¿ó×þÚ_ûØÇÉ9ŸŒ\ë*MÓÐ'¸“—È�ßú­ß2³ÕjõOþÉ? ! Ãж­»Ñûï¿_áÙgŸÇñ“ô’3—TBÈöN­|´9Øß˜é‰ Äö�ß½uôc w€5l×r/]rÏûðÎl¹ aÈž³ Å!§ì�BV`( œV,DÚÈ™Çû?>m¬ííhûZ›×¾{K—~³Ï—SÜ5Æèô1õ®E‡Jå±E³K[:rîÍÈŽ¯!¼çÝlöá;ND Ó°1ŒžÂ,^¾²ˆks#!bó4¤@B(ý/*êÃ@A�qÙ¸_w!@,²kJ=S·Q.ÊüÁÛiª# ]¸´óÃà 9Ükš\¥r!8ù€<äÞ¸Û¹´uí ó¤Wï¼{4¯†Q�£pP¥æÜ´ÍV³Ð—®\yîË»—žc™¹IrwsWÏF¹Á¥ôŽPEŽJ¥R©T*•G!Ü ™dEÖ”’tM&Ú”œîóဦ ‘"–ÀMfÜ…ØÌ³ÏÚ¦‰!"‹Pt$v‹d„s>> 4à’Wª¬äp÷œ3jðøcËS§sü‡ÿðRJ×®]kšæ+_ùŠª–ɉ¾ï‹‹Ô�7¾øÅ/~ç;ß¹uëÖüÁ|’ÎQtˆõzc<§ OŽ`ÝÞÞþ·ÿöß~ï{ß#¢¿ÿ÷ÿþÕ«WW«Õ|>°\.·¶¶nß¾}ûöíÝÝÝ×^{íSDŽò#ÊHGÓÛñaïÔÊ'CwMÛ'øŽã8AòÀ@œ<å%OŽä1@‚ƒ<Iò$@�À>Áù`ÙÇ9þ’HŠ/’Ù–dJ”L‰w²ÙÝuÙ—µÖœsŒó0×Þµ»›—n²‹]¬ž?47«ví˪]ë2çü�ñÿã–F§â#Q(¼oaÓ½ëW‰ÙAœ‘'WÃaÙÆýùããi›BŒ BÁ×­Z×u}ÛyT"œ#†9çK×uùª´>ðݲ˜! ”Rˆµ‡ î"[qHnõF¤€‚@0ãm„%ŒG;W/ ÑȬä  ÇG‚UÛ#¶sÙž<ù¦{—§Ï|ý¹«¯^W©D\ŠÔ³y?rS×ìÈ÷}æ‚ÛBŸºY»?šR5ªRˆËå‚ÝÈG4¯Fwí¤R( …B¡P¸ë˜jHjIEàYD<\ê5%V¶¤„·½0�Xíc¿´eÏS[RíbX´ír¹\¢mb¨\å½[jÌ·ùú8OLDjH!®muÞbi·pò9å:Ǻ1býÅ—¾ô¥sçνþúëÿïÿýBJ©iÙŸŠ™çóù_ý«õ«_ýêd2ùò—¿¼V#°rˆÚ¼gÝɱ&7gdùÄ9cìû~<¿òÊ+ÿò_þKïýO<ñ·þÖßÊ�ÌO™N§¾ùÍo^¸p¡iš���Üç1ŸÏ«ªòÞceo•RRUï}J©ïû¬¯„ò¹OEDò6ØÌð¸•ýýý³gÏ2sŽ13U}‹ÇŸ(T•ÍÌ,¥Df"BIC¸]ǧ÷”õ2/½™¬B=]´K©¸Omßö“­éöÇÛ½§ñm¿r"Z «ÍjX¥ pGè@ÊhMZ“Ög@A0P€™*‰±'ŽÉfÍØºþà÷¿ò[tfæªä�-°t7+Ûµ£½å·»§Ð÷}>4, fÄëwýÊï 1š™ñPÚ3ÃPq¯·¬ð~ Ÿö×'ü|½ëºîŽÎçl¼…Š"+|³=£æEj•0 ê¢ŽÉÆÈ¯lpòµC-h`æã®|©ë: ëº¦9#œË“£ð&>YÌè{8‡ãx<>8@u¦‚×.Üc­Bá6ÉcBïýz„à}4îº# ED�â‚¡Ÿ§jtŸ>ÿh»x´]ôóù2†äëf:�§p#tŒ-\p÷ÖYŒDÄù 3d’) ü©ã.㜛õ="Š1¹”Ò]¬¥""ç\aN (ÔNÞ('Æè�SÕÜ£B….ÝiQYUUÄISÂjÆÇÌÎ9ñžB˜˜Ù,Äw=Ê&É,ÒǨªÅ$ùD@«iš<ü;afîbçÇÞÌÌÌ9Äh"c‘Ø ®}ßWõ$_ ï”|õ$""zÇ‹Î9@Í)ÑpœF¦º®U5§©OÞ{‹'g»•çeçÜíúBŽ‘¾ïwªJÓ’=·m»å}Œñn­¼2çe0 ËT’Ãɪ߲U±¯™�¥‰!°‘ÆDfÌ¢ˆÞþ@ŸbCÁ¬°ñÖxÖÍyk«ªj‹½«¥×Üwáœëc€01ßæë“�AÍ`Ãø’†ñå­óÙwבÇT¾ò}ìcŒ"X†ÀŸ¸«þ="O‹œs}ßc5]z÷CŽ“uQ¼‹äµþµ —¯|³Ùl¹\QUU�>úhN×È ¢‚÷¾ªªË—/籸ˆ\½zu4­M¢¼uÿÍf³étBÈ!çÜÁÁÁ¿úWÿÊ9×4Í?øÿ ‹ù5ó›~ï{ß;þ|Œñµ×^Ë&Z1Æœ.¾\.Û¶ÝÝÝÍ¿E~e­%¥´ÖZÆãq¾Hg9+uäͶskk«m[çåu1ï½Ý½Ù»��»ÎV ÀyÓ tGßÞë-~3l¨FÌê‚rè�UM)‰³­éÖ�}ê3úßÏࣄ3·ù¢Œž0ÔP5Pë`‰ßÐy‚*€'4€7xP Ùž ˆÂ18¢ĈCÅìÅ«ßzöÛÏâ+Æ�Yʵ“JÐ Ç*ÅÊ ÿ¨ÄòžuÙ DÄü~á7öß�zØóß7¿Eá^qÓÙãm#F>9†%"'&%1J‚‰QNúf%Ä›$ Œ@€b8wço)‹'w:_ƒî'#¸>†Zê�³“å«]—j ' Cއ0Λ’±}BUCjtÚŽ·b„Ôw³YÕŒËáUxϸi|Å|Ô ¯7íî£L —ò|–Ы‰$cWËxKê4ˆ„™M‰–Põ­QEPÊÇ»’ 6ÈÈ ÆÙYTÒÈïë�ÇúÛ�¡ÈƫРóÛyƒüÿÁnW€Á'p„C7®#¯% ºÃ XÛ¶,jÚQŒˆ1…ú¾O�ô}‚ňcDêC/fõIò¿in•¿4SU%'XUó‡°úloúkÜð "fÆÉ»Ž°ÙöŸ'gfG‹3ù7üaÞÑþÖq/V‹?o¸AtÃ)ìhŸíº.ÆN(šY´˜�Ó®ë:¦>Æ@!F‹1JŒj‰¢z©†ÓßÑYqu,ßþ¿>çÒÆ¯²ñä=�s½\V€È•ãñ^ñ¦Ç©±®é�]èh¦sûo°a_?,œ¤[ÿ$7hd "!Œȓ̷¹Ú¾'�ĨĽ¥ ©O±M!ö±ocè4v-ÆŽû‚TÕí¿>r4úVsX»KèæÈj5ìßüK6Nï´:ùßWô}Ÿ?�¼‚�RZ×ñ¿NРêî’Uýõ*.w}íµ×B¹&åøÀúÁùº˜ëÁ�s—.]rÎåÇ /¼ðÀTUµ^B½ÍÝ9·\.óƒ¿øÅ/þîïþnUU?õS?õØc�ÈZV»þÕ«Ws+ÆO<1›Í¾ô¥/}ñ‹_¼råÊË/¿<�>ñ‰O|æ3Ÿyê©§~øáÍö¬ÆßY®ÈUÖâÍ[påÊ• .¼úê«Y7Ë:ÇZF;!�K½Ö#¤áϵ±¨�É'ú“%Ò è°Ú‡U4®)ánâ\ef¡ ¾žŽ«·ðˆa‡uçv?  P ‚Ö0O�܈€pf󆊌@”�îó0Wó€Gº 0jôÕ~®˜�’å¾ÍUÞ`#躎rs�yEŽ�]‚ˆEDäý¤si4«/Öß•¨÷ÂÛ’= 7R"²noºMÌhøGœÙÁ(`ƒ(Ìà�H‰s…ÙMoÀ¸!žãh¤›¿¸Ã}ÙŒ3$P‚™�aÞL¼÷Þ°{±Ù{ùµ‘¿ÈJM5‰}Ú8âŒs¶‡úp0Š]Ü¿ôàY?†›Ž`!�Äbâ©%—•¬¿ÍE£¹Èæ^oÚÝnjԜ)d”,Ç:‘Á‹ ‚1³æùLŠ1Od´ª1ˆGMÂ0Ì·É�Ï (×Ç»…™á–ëD¼óÖc’ü¨ÕøÄ6Nð·õúyo73UË‘'s*¿.Ï—‡\÷Æ@ÐxGû›÷žEa&"_×’¯Ô bfï¹®Ð4MmQYÙ9;IýfC» ‹�ˆˆH°õ¼lcܺ´Þë ?5n˜ ØÑN¬N½Ø|;3c>’‹„E‹åx¼g˜D†ëˆYž”Áû ~o8š‡“é�_O×¥Ïë%Á{|=]m;š¥‚¤Æ‘ÒP“ÂÌÞ{Qêb²¡6îín#£ñ•s,BÄœPy©j8—˜ÁÎùºª«šÇ^ƒs$ÜîëêÆïa€Ýâ©1Œ[†ùï�í´ªÎ;ƒ88çȹ.š­Ïö7è÷UUeh½Ø~WúGO¿Î±îdTÕ+W®xï‹…ˆìîîf{(l„^¬Ÿ¾µµõúë¯Ç_}õÕ|Ïz—{ë¦Èãt:�Ïç“É$;e]½zõóŸÿ¼÷þÒ¥K?ÿó?õêÕsçέ'Yyî¹ç¾ûÝïŽÇã���úOÿéW¾ò•º®³ÿUÛ¶¿ÿû¿ÿ;¿ó;úЇ~æg~æÇ~ìÇΞ=‹•‰VÞ ÖõÞûÂÁÁÁøÿáóŸÿür¹ÌM!·òéOúþÃ8�¶··±j+™Íf¹qä„`„ flàaÁL!˜:çCl+q Ĉiwww~¯·ù-QÊ-¤MÕ ®›ª®”ûˆØé†�]áéí¿ °Ü n[ªAeY5[@ �0HÖ3´�úʹªfKÎ"ÃØ@)L ÎŽÞë ÿÏ­$÷Œu½S¾ˆ:÷6­W'гg)žÝ–¦‘c€°rV£R¯Zx;RJ›ëSÌœuëÛѼ×��0çÎ-$F"”Àe1Ȱ© ŒéÍÇŽ™Í±à�vû8Ûëi.ñØÀ©æ^°ÀùÝw¿5c™:n¼“åB+'ÃÉØàæßŒÐj×§C…‡›VSðVU»];AËJ…ÓOa=5ÀÌu]›Y®z9e$Bäaü‘¯bl�Õ,ÑŒÌÌH‰È˜4GìÍê¿ážÕÑŽÚF‹oÕ]DRÀb–MÕòò 3£ªšªi&“ÄèܵB”ÔjÂAo÷O`ÜÍ-å©,Ö+ '•Í5(çS ÏÓª¹£þ¡˜ŒEa½ˆD_-<š¦ñÞCÄ9W±“I³E�^Ø9O'hÈ*AÂÃj©19ßÐÈ�Fã€:’˜ÁzW‰Hìö‡ÂÛÁ02‚rT”É+A ]K†ƒkM]�›ÆKõîßõnA�='æZòQ¿m�={öìÖY× aæ;ïÇjzC�Ìm�MÕ°ZçÍžÞû7œú!‹EH•%R%‰Œ€m*JDA§c‡º®ÝÒ ÌÕu="LFuí�%!¤šF0£$è P§ÄP…·c«ö3‚‚ê°ÜòÈ µzýU­§3y߸äG#×ÜC‹…û‰{y�.‹y"‚ªj¸nüX •Ža‚D­  ;ºžŠ,q=ïí›^÷ú÷>šå jÁ€Ë•È$ìëŠT`ñ*&övnsSç É;B5\]‰ˆ°¸Êû¦ž0¦õ¸›HÛÎI àv_�G¾úåƒî†CèëÒI+ØÔ½Pa4imci”$Ï´…ÀÈvìþÏ'�ÍuŒ#ið]sjuŽõa�•Daf¹%kþmÛæI&ųTN ØÝݽzõjJi6›­—ŠÖŸø[ûAae»œOp¿ýÛ¿ýÌ3ÏøÙŸýÙ‹/æŸN&“ÃÃÃétšÿ�³ÙìÑGM)}ë[ßÚÛÛ»|ùr¶�1¦”ªª !<û쳿ök¿6ŸÏñ±iš®ëœsy㛦QÕ¬|d3®ýýýW^y…™÷ööÞp;«ªšL&›ý.&“ɉ*�_y$ŸÿW-pBÄï<ƒ €Ì|M®�ö‚ ”HÍ ĈB¨�T<ªh‹1Õì¸6ƒzë[pöªÆÆ™÷õ™ò¹x½æ¸Ú”Õ ]aCÞ&cvÀˆ"æ+éÁ9MÄà .;Si~â€nH,÷lç¡ÁU`p–sÎyÿ~Ò9ààܰùÜ}Ê€Nà^]8Y¬¯Mkß¶¬²ß)ë“‚õž·êÇÏn1ýÃÿø-ÎO«—z7ˆ4xâ“£¼(:ÁCÄ^uW÷Ë–õ‚‘€” l.a¨W„ºúêåC8³ýà ±ð ºàN;›bdFžÊdŽá—Ýýd+;&€²]sö @Ê6ÈC£÷B@|ÔšO%¼1ÿ_ÏÿèÔ~z÷E]g�#K¼oF#$C € D<èW„ÛŸ¤¡&—`¯�:îõ¯|[xçEðü¾X€|©¼uUEŒÙ™�'€å$�v.Px�ÁD"%#s¨1nÆ@²‰ ùB*¸³Ï§ð6 . �¯<@ió8Eö«ªºªïaKýnK’Àå1Ýáõ´F��,^-ÂÜûþôßßY™u°<ó,ä‘×�`Xý¾·q˨Y1IîQŠQ¥”4ó àÅ䜭ëünãõéèXáÕ�”V3\¬~Hx§“[Ù8NS"8 !ö ë¤4e�^î'6gC-ïöS8µ:Çf÷zé'gfˆHÎ_ ·ÞæLŽìµ–L6›'Þâ}Uu{{;;)µmû›¿ù›"rþüùŸüÉŸÌöPù]rÀFŒ±ªª§Ÿ~zoo¯ªªº®ÿÆßø?ð?ð£?ú£ùjýÝï~÷ _øÂý¯ÿõ¹çž»zõêù/ÿåÁüéŸþé¬Ðd!¤išÜª™“9²¢“RÊî[o¸�[[[ùõC³Ù,wŸä’{ý§;bÝÏ�[ú9"LÄ…À⢄¤ñ„™?Ø _1 œìÈœc@ch£Í‰3UÔj¾£Åùu›#ßø~vÉøÈòqÝ�wƒ< ºõ�Ù�e–”lRk`3oÀšBlx0¥#üžªÖV’lÞOm„a¦#˜”}¯,ý…·å¦ÕÒõêÎ|«‰X l SÈ”¶aT‚eÛºÕa¾>ÚuŒqëñÿÎÛV0 ÆQIalRˆB à žøèÅïü¯×æ{óýÙx§žÂV¾"¢¯1ögÔ,·vå‰�œƒj˜ ÂDÓ»Û¼Báx3UãD�»îLY� HFP§¤,^Ø`°dÑ�s°¬P®# W�6d› 瘴²¤+Ç»†¤t“ð°ò ’!¹¤4ôs¸;ïçHƒGùðâï�c˜¿MéÎú6•‹u©m^›¾É¦‡™í„�$ Öõ§ª¬ç& 9 2÷s$’I"Bé縛¬û9 P#£¡ŸcC/ߜ木ý‡ ,Ä" é&7¼‚BcŠdÌÌ!†ªªÒ�ÆÖñË7Ýó†ŸCßÂ’K ¤jH$Hd80m–$¬Ù >6Ggƒ”r±w’”tèçàcô­"(؆~ŽJ Kp’hÈaùs^§)ߪ{…¤t“¿ÜѼLƒhÊã�DuwÞÏ‘°áCsTÂrÈ‘­‡Íthì€Ðj\w'ý[ª�i¡Yçc?È0x�ÎVrã-Ô4�Xó²ËMídCÆ$­š¶n}Ì[ IxبÕyeuœjJë~PŒ²ÞÉú3;rÃx‰ÖŸÕ»,Y>µ:G^²¿éScæ¾ïs36NCC�;ªªjÛ6ÇxäÝ1ƘO"·ó¡w]7�˜y6›ýú¯ÿú+¯¼²µµõó?ÿógΜÉùιÃÃÜ7žß±ïûÜÀñC?ôC¿ôK¿tþüy‡‡‡ÞûÇ{ì±Çûä'?ùë¿þë_øÂ®\¹òùÏþ#ùÈåË—SJë^“ca<ç_dkkk<¼YUoß÷‡‡‡¹Ç3{Uea殸¡Ý-Þ²ŸT®bn˜»;1iyO�õÙŠHl�°(”Èz3hlSÐc$E{Ý”Õk"E Ð`%0ó›R‡q:ƒ@ÂÊfŠ@>ªV”-_BŽ1÷�‰Ëk æQ°Ý°°‰U¸z†ïá gŒf³×Áîòd úߪà+�hèç`Êõ¥Ÿ£ðö¤”nŠr»ç /‚¼H,ë`Þ�ŠŠÓø¹Ý3Ý2�šr¨jJ,|Wú9"4×féêi'ÁgãV˜™q´2›,AAqwÖ¯ �¥�8ݬpN4’’­–zRJ,îd�t•±¾CÃzf]ú9Ž�7ëçh£ªJ–ÇòrDŒ1Åå[RˆÉs.aÖU\vUU ^÷säe a¹ÓsA6±Ø÷æÜÚ7<ŽÞ¢Ÿ#1E‡4¬4ä3ç«bU:¨PԔş¨~ެœb½’n P/®ôsÜ3L‘º”’™ÉF›QzñÍ]éçH°£ªýõï¥Î‘ËQVZŸ®”€uÐÅZƃÌß™²™• D…€Ä`C{GQL² �©‚)Yãn (\¼Úțֳx•@»ÙÏ‘›‘o9’]VÊd–}”Å—~¬ëuÃæ‰ýÝp‚µï:9–cým¶ȳʔÒ|>ÏjÄúì“/™Y<8<<Ìßæ…ò•øÍÚ#Ö¤”F£Q~n×uÿé?ý§Édbf?÷s?·Þž¾ï·¶¶ÖëP!„_ù•_aæ®ë²Â‘ÉBHnùÔ§>uõêÕÿù?ÿç¥K—þø�ÿøÙgŸ½|ùrÞï}¾¯3É›¦ùþïÿþ³gÏö}ÿf’Ì™3g¶¶¶ö÷÷ëºîû~:�^»vm{{{±XÜë¿ÛFHpÄô¦~ŽDïúnéY\4’˜f‡‡÷z“߆9@q±XìFõ�¨1]z«EÈ­«æ‹·¿*iÈ_ëD°ÕÑM‘0ô¼¬Î›²º� 4‹ ¦–ˆà£õ½.…1¿Áï2Ü®ò›îé'{୪ȡôï'�£=DôQjÀ:ƒ1EG@,•~ŽÂÛ²Ïßæ¦û”R×uwô:6ŒÜV*&)ÝPCÈ“ÀÕ Áˆßlï<²¬y§~¦ÈØHA�KІ “1®]½~f<âQóÐS[Ó3¸rðú¢MUjYI‘ÞÌk–xy¹ý ÿÀǧÓK€Çl¯µ‘ÕgFËy Ž¥Ÿãþã­÷Y¾�ǼíK½1yÔ¾Xæ–Ü<|ÃÇç~…ìNI9qö–®m$op¶Á�m½{¯‡Oëç)áX-€É˜MH”@1§…å³€3«Z25"çÅ{꺎`°s«òÜ›”"C•V¿_Y¾¹ÛÔ)HßÇs-× s¤Ô÷=ENŒÎw �bîçñ ]ÝÆAk�QS Ä`Y#`:ÈW¦«Ó ƒt~£}6W6­ÌøÆÝоÁÁKJfŸ›VA9�"q"Dp"À)Š©YBê»;;äI Á´óÞ[äà|–yrürJ)}o‘´‹»„“”Cî¸Z­ŸæìtU  Õ¶w Eq–Äz#ô\%b1-ýw†‰‘)÷ë|Q©4!…”ÒZçP3ÄØ÷}°x¯·ù204!y_ êæêø;<<G³©sòqšÚ Å·êž1Ž!äUˆ£•Æ;5�^ µvb!ù#Ó]OeauÈ.5æWý{»4~o®P�¦1*¬‡&fyo{ À{3î‹ÇV;�)CÉÌ’ö ´iì¬kÛÞ,òí¾>CÅ”ì†fŽ!G}5‡}7ýM7Χ¥\sŸ�Së5h›�”L”Thyßæslö䌉»¢vœZ�c­R¬Õ…ÃÃÃ���¼ôüóÏg‘#†ç§ä‡5MsåÊ•”ÒöööÞÞÞÎ΀Ñh”RZ7a¬ÉÎTÙä*ß³Åð[¿õ[1FïýOþäOÖ+W ¬Š6;.ó»äén~…B>ÖÒÈOüÄOüçÿüŸ_yå"úÚ×¾ö¹Ï}n³„¡ªª¼È•-¹~îç~îm?¢k×®åAŒñêÕ«"²¿¿²ò9Þ\çˆ0ñ.ômã«Ð'VkìíU¨{Cîî'…Ö°Ô+�©ÂõY×-[´µw³ÃŽÄú ¸Ãúý|¾Íå�›%Ó›R0žàs‘‡‚ ¬¼\ͯ”“hP!l›)&¤åJê¸Ê$N °2Ök«¤_@ º±Iï)xïã¢kÆS�Çãþ>î(„ùÞÒ÷è–KŠ ë|Š„`æ Eç(¼-f6�«ªÊµ–DtýúõlÞøî^øíW{ßl(vWõƒ¼Œ€Ö’¡ïEE¯.ö\ë«ÑÈ.ñ‡fÔîÙ _ÛkhÛ6¤(®j¶êé™Éhê?ú‰ó‰1Óƒ.HÒW—€.Ð�ãT³)Z¬væ73;2&sO¹ùaF cJ&¤„tGëzf¶³³³^’È7¹ë LyYlLÆ¢,ÊdD+RŒLY�4z�Ș•ň ¢œ×›È—!~5UF"NÇ}LGzÃÇ>LáÖ¦Òè[€”‹¼°±ºÍ <ùnËÂÍ1‘RØ Ýb±pÎ¡ï² .ö÷ç£ÄIoÑ9ìNuŽÄš®ï-ªZàmz¸‡ v€0 æ?nò ¾6jÃÚËÀÚ'5—€¬»ö à¡yh /*l$ÉÝ\�“L$Þ’g� ï1s>õiQW)v{â;E/ðdãƒýåkÝÁR²±¨i×÷}ìŒυòÔo8ü½ �-˜å$]Œ\àö É¥�ÙB£maûÝr´ì„q³Î‹Îq·yc�#j§Eß÷Þ €ªö}�Åb‚Ð ZÒÉ×c;èÛ¶ef"Ô5…Ôý$ÆàÐEç±-Û}f~ƒ±Ü½‘+ÜÚ¶].—kûâ›Xëz¤sDIÉÚ¥”,jf}’9íæ‚W ]`Þá°=4ëB\Ôì$º£s$ ÕbÁ9ž$«2‹Cô×çýxɉÊåòžÃx¶È–-cïæ}ïSŠ×¯wÍV‹!Ý sØ;Ð9‚® ꉆë5À÷ö/¾ª¶Y[¤ç†EÇ’«\´\¶ýl&•O¦‰”�õön£ÈaÛíT“Å|Þ5‹«n*ÞKŒÊÌ]œ]Ÿ/½ºfÑ*§˜º»D|›¯ŸÇ™Ãgûv³ÚwP·§]µ\3÷)‘PŒ±Ûƒít‹vf\�9 ‰9Ƙëï™ùüùóïÞþ]ï.›ù™º®Ïž=›­«Î�;wpp°³³3™Lr[™s®ïû”Òx<¾páÂÞÞ^‘¦ÓiM‘#_¶«ªÊ1!9,? ïû/|á 9!ãsŸûÜ›m'3/—Kï}J)«]×]¸p!? _¿çóùîîî“O>ù /ììì<ÿüóØð2;QfS…[XŸó�Âý�þ�çc”“À9[ZÝ�…t»¼mÉÆæX[iÉð5²ýL"˜ÂÁj¥¹’Š¡>ä&‹ª[Šì …ÂiãíÏEï‰N°®gA0 »`%ßÃÃùn<’�ï>�–ûSŠìÈ5\M¼«°¤ò‘Œ£ gZ}¯6¾p’8Z÷Üô�|Snmî 3»å ëFΣöJccͮǹ²Œ ºîî?Ú|EYlüÆJCµÚñqc~ÆÆÉdå®wÃw†›*þ^kÓä²jóþ† ¢j½4 i•B»ØjF<,Wí,�ˆ•‹ŒÑà†A¶¶sX{`ˆa«¨º£]:%k«Œ›60U©4ÁÊH0"ç],�йŸã¤Ù� …B¡pyÃÕù£þþÕ´‹ j* boËH³�@®Ùµ£¼YV`¹ß×à”CîX¾�Wη›kYo;1¼ßˆ÷5§v}<‡Úgu(‹œUU]¼x1û#×u�l¤÷Ôu�[‰Eäµ×^;þ|Ó4ûØÇœs!ï}Û¶XùD5M³V™Ì,Wޝ›Hªªúò—¿ü­o}kgg硇úä'?ùfÛ™RšL&¹{Àb±ØÞÞ^ÿhݶ“ïÌï2�¯_¿®ª›D÷úó. …Bá="÷;æú5f®ëš¥ª*æ1T]‚Ëñ’`#QhX™ç¤!Í8¯ÀÚ©¼AqÜZ$ Ê npe<ªþæÍoWqÚƒ‘zk{«»Ùjivey¼R&Ž–þYnû0A½fDaPbäø`B<Ò rÔáðlEê+¼WPŠinhA�•ˆÛ È7#3eOê,XÐ9p‡Ám<*Ó�¥#f­:»JXKoÄ›Í�œ¸](„‘µí@ã~ÙômÝÁêÕÕ!‚(oÞ V( …B¡P8Iœæõñu¨ýº�q{{û�‘®ëž~úi"ºvíZrB83§”þàþ wiŒF£ .¬Uï}]×Ù+‹ªã|>ÏÈ/’#.~ý×}gg'¥ô£?ú£o±‘"’Õç\Û¶ãñx>ŸgSõM¦Üºqpp "óùüâÅ‹›ÚF~ßB¡P(N=¹Y3_cŒƒ)3Ro!2Ô™º¤.$´AçËp`Ò)üÖ#(1Uî7ÆG·ùž7v¬ÚìBP‚QÔƒúãÞHQÅÚÍ&±&¶È‘­‹¢A4±&V#…SU‚²)È”-ŠEF/D{ADFäìXuš§…“FU¹ªª®k±¿p8Ÿ]i_i17hn2j¨$�Ø€”ƒ��õƒ.Á%H‚$¸”»’ßæŸ®oèc @¡"4�'[ÓÉ.Ì“VR… Èé2Å”©P( …BáýÁi.fÌÍùëuJÇÿðÿÇÿø'“ÉW¿úÕ_üÅ_œN§rAhNðöÞÿ·ÿößxà�«W¯>þøãÃÇäÉ=¦Ói¶D¬ª*7|ä&ÙÛÛûƒ?øƒ‹/üØ�ýXv¾zÃ�TÕóoþÍw¾ó�ù|¾½½ýÏÿù?Ï¥©ùô} ªªýýýÙl–RÚßßÿô§?�UÃGþ¢XW …Bá~ ›†çë{vžŒ1¡®œæÄXR@Ê0b5 ò V?‚1î, ©ð¾ãM‹"Ç×·zË3WJ€­K¹•låûoƒMÔ1múxh¬ÄLPÊãš}º�¤+c¨Üœd  JªÄ‰X ¶ò­¢u ¢/žÂ{‹q×ÂÒi[°Çn2©ÏºŠ=(¡ËíF‰<¯ãç}ã)ê[èsYéx tu¤3Ù‡Žnìˆ{®Í{óƒñˆ‚ñÐûDE/ …B¡Px?q-ާ”>ûÙÏþÛûowvv¾ñ�o¼üòË—.]Z›M­sË¿ñ�oìïï«ê�üÈ�¬õ‰µð`m-Õu�÷>?¦ëºº®»®kšæü�ÿѶíÁÁÁåË—xà�·ÈÇfæO}êS¿ú«¿º³³³X,ž{î¹G}t6›e&ŒçGþÙŸýÙw¾ó�ÂîîîÇ?þñüÓ¬sߪB¡P(Ü'd�?—2lÆN†87#³dfÆFD, ìû3ädß!žp³mQáÔsY±vú¿Qð8"gzçl€ ©‡àc¨â�W7‚ aª°#ïµ!`<‹"F–J¬N¤›"gyC!–íJºVá=%ÄeÒ\¹å½s“‘.úïí4C6¬�‘rž^Í�`7æµl(sùÈÈwðê°LŒH« 6 »«{ìÆLžÞÐ 7V¸ˆýÏs³Ø9Ó„~–EŽ#<¬ŠÚQ( …B¡ð>àÔê›!äëf3{ì±Ç>ûÙÏ~÷»ß=<<ü�ßø�_ø…_È)œsËåò·û·¯_¿~xxøñ�üsŸû\~�õ+ìííÕu=�öööÎ�;Ç̳Ùl-{`¡ñ…/|a2™´mû©O} o©C„~ø‡xww7ÛUýëý¯ù—yxž• fþ£?ú£ÏþóW®\ÙÞÞþñÿñ‡~+ã¬õ› …B¡pêÉÉ뮎|)43x% " lX;Ú`æN‘ãôsƒ”uÓ_œÞp°¾ ÃzŸa@yH°—!û8Û"”øHP!ÕÍt RVðjûÈ@ÐD0ÎÝPR[5©d…C ¬ð §ƒ~Ó9¤ÒÖQxo ~2ѺY*fQg];»¾ÿÚÿç¿ÿ?›ê‚!€9˜‡Ž€ç °ê·³¬ê­d?†±Á²Ï•æ R¢0”r#XéèkS%0L lPŠóÅžsµÅiÝLHúf+~û»_RÌ={0æ!„ÜÁ<P(RG¡P( …ÂÉçÔêX© y5$«¶¶¶~ññŸý³V×õç?ÿyù¥_ú¥¶m½÷!„ßù�ßùÿâ_loo_¸páðÏŸ?ŸŸ%"ªÚuݯþê¯~ë[ßbfùå_þå���u%i^j‘ÙlöôÓOg«'Ÿ|ùäo¸‘Dôwÿîßýwÿîß-—˯}íkÿøÿã¿ówþÎSO=5�N½÷W®\ùÃ?üÃ_ûµ_{úé§/_¾ìœûñÿñº®±j@É}$÷úÃ. …Bá½ _‘s£äº¦ÁÌÀ¦¤ë¤i3ƒ­W­7V´‹¼q_ 7æߨpl2„ÒµO­Ÿ¢8§ ojcvì¹ÄFYá"Äm‡NPÄT dƒ(Œ80V ä‡1 l¼)r䯕Wµî…Â{YLm­Eócr•-׿ÝwÏ�K ¬¤(xÚ Ê‘ãš÷dàHàSRãdAJF’jÒµïÕúPÝÜÅW¦s!Ñ»&…Æf® ýöN=_î�Ù®,›'ó€ÌÁX*Qä…B¡P( 'ŸS«s eœ­Û²0ðÄOüõ¿þ×ó7ó¥—^ú�ßø�?üÃ?tÎ�Çãï}ï{1ÆÑh´X,~ögö¯ýµ¿–ËEóë033ÿÉŸüÉK/½”C8r#ÈZÀX‡p|õ«_],DcüÁüA¼e?Çr¹œN§?õS?õâ‹/~þóŸ_.—Ï>ûì/ÿò/Ÿ={6{އbŒÌ|áÂUý'ÿäŸ\ºt)?7o^9 …B¡pÿ�µ�uù“’XoYºe�ëñrP�•EÞû‘£jqdU5$3"fqdl}ßö!xïF£Ñ|>gð¸×¾ia~0sä·w·–ýâøê»� Æ Ø�É‘[7”€”R#¾bÏÉ4Fhô`r’BÏNDDÁª5™©™9 Fî@¼ò¿*Þ Ø(F‡8ûK¯_»:šÄí­Iˆ®ëæŽ �DE¥Á^*9hÍH HHlÀM3 }J ­o$Q0 #´“éxoÁŒ¦‡>9W¥´¹“¯’6H�d’¢uàT7Ì}×oOÆÄñî¢m„¦ /�¶íˆXD‚v÷úS, …B¡P(¼=§Vçx .]ºô ¿ð Þûÿóÿü?Ÿþùù|~áÂ…+W®<÷ÜsUU}àøÄ'>ñ3?ó3“É@J)„�åï½™- çܵk×rb3/—ËÑh”SÊSJÏ<óÌîîîr¹|à�B›Á·2�N—Ë¥÷þïý½¿÷áøßÿûÿ�ï|çâÅ‹‹Å¢ëºªªr&¹™}ö³ŸýÙŸýÙ‹/æ �-­°H^( …Â}J^0(¥÷¸µ�C‹ É}ÀM!¹SC‰ ",0K€æeÿdÚÆÎbj&U³#•Y×ÏûýíÝm ivxõú^šÖ»>ø@ìôÚõëõäx‡Ð+MXïʵ«4Ä>DUâ;�©_Æñh4¦�bꌄ½cr.w>) <¼J¶rá=Ūis~wòÄù­OµËÛëó¤0¦T ;åx´³Sõ0§z†Õ"GŽ¢xv5*yöª,ËÅ�‰¹ìÐÏiä¶E‘ã8¶•êÊ· ª¤lP2†*EÂÒÒ¬šM<º­ gyðÜ#†sŽ©’¾íP¦Y…B¡P( ïî;�#k[[[ûoÿíú¡úò—¿üÅ/~ñë_ÿúÖÖÖ÷}ß÷ýÅ¿øäG~ä#ùHÖ^|ñÅË—/çÒ?óù|{{{ww7¥ôè£�ö}ŸŒüàÑh@D¾öµ¯½ð !„ŸþéŸ^‡¼)¥üÄ®ëþÒ_úKŸøÄ'¾ò•¯|éK_zå•WSJ/^üèG?ú©O}êÃþðîîîæ×m"Eç( …Â}ÓjY›7tŽÕ�íPþiYì½ïÈ�ÄÉ,% f‘%Ûáô®,ª|xÐÏû~gõ¨¹røÂÖøìhwê„Ø.ú$/îx»�rG†�9žßÒ™D fV>1‹°WÕ`޼g_3@šÌÌTƒ�‘Æš‰Ù� à¤d‘ÞÌ#ž97ýþ?*çv>¼ì¯€za‘år™�¦Vçi%58@ ‘‘(ëæñ$0ß-Ãëß{åk }UÓÂÓôìÎÇ/í>¶"qå¨jûÐø±bx*A�” F¹W*€–ʑՒUp2†ùQµ{ùâ“O=ñCŒIRH]XÖR  …B¡P(ÞÜw:Çh4ÊIÞûÇüñÇÿ›óoÞô˜”R۶ι˗/çnŒlN5™L~åW~e4…®]»6™L²ÀÀ̪BpΉÈ?úGÿèܹsù¥bŒûûûãñ8‹·2›Í²’ƒUwwwÿÊ_ù+?öc? ª*3kÛVD²#ÖZÏÈÖ䛞Z÷ús- …BážAßrç­‹Ñ9œ™aZ î?VYÆÀ’†”zâ¸o¶ÂþòÊÕ«/¿rå¹—^ûÞþìªI�FÓæÌ¹3—»üчÎ?�Nö_ER³µµÛ¯óí�Ÿ,r°�ŒûØ;WIãCJ}T#WÕM=  #Sæœ�®)¥d‘*—ãFkƉ §·´» Ç„¹ÅaÉùÇ/æÑGžT�)µÙ˜©†9…¬NÎÙÆ*«RÞa#™²1™(D%¯‘¯~çÚþµ~>KÚÂêü�¿úø?#"“®MM3…‘iÙ 2 Eãu®ø �³1Ìw-.ž}¸Â0ŠQSJøêØóx …B¡P( w…ûNçȾÞYuèû~¹\2sÓ4¹="†WU•M¨¬-§f³Ùt:mšÆ9—%Ëår<`æõ#Ï�;§ªÌœRrέ5�7$'™¯CD‹Åh4ÊªÆæ¦îííÕu�%ÉÖäYäPš9 …B¡pŸC·,ÚÒÆ:îê+̨,ñÞÇ�š”Ì’ó&Ž@)Øá³/}ýÏ_øêw¾÷ôþüU“V©]öó¾ïw·/س£o?ûÁ�=ñ—ž|ä3“�¤×Cc;öQt’—�I0´f=sWUÁ�¤aºÛÄÞR×R Þ´œ6LŒ¡j9 €ÁôK¡p|"´'±J*ªÎ0ÕѺ¤ÁT´˜g­�¬%(*!‘Ô 9Ppãœ�&wÐ6}\z llL®ŸYÚ9WÁÄÔYŸŒ¦f0[ïëè�y†Öƒ"`ùj  ˜»†Âû1À"1P¯ë± ]¯?ÅB¡P( …ÂÛsßéD”RŠ1z﫪ʊVzFn¡¸é)]׉Èt:ņ¢0›Í&“Éd2É™äX5U´mÛ4ÍþþþîînŒ‘ˆÖo±I}ß›Y]×Y5¹zõjK–ËeÞÈ3gΨjÛ¶9$? †ïkÁ£P( …û“ìôÃÆJšoWÂÃ�o¡Ôçžznù«“jŠ)qdQ_1‹Íf¯ÏžÿÝ?þ�«óo,^ãªíÀ5i‚¨ªËÅ‹JÍK¯ïͯìïòû~øüÖÂÒ`ÛǸÝv”¥Á€äî#ƒ‹ómŠ�&kF<®X°ØïúcOÎÆÞoÉÈ�TÛ%ºàLÙ”bTAV¤ŽÂ{JU;ÕØwd�13ˆÍœ*7ÕÒTE �ÔÀ‘j3z‚Š�À`ðüp.!ZíÙê¶ 8"!LÞõ<2e#ÑF¶SÜèÛËÍYJ1M ‚ FdÎÈ¥.E×0œ÷pR‰tóù|UÊVºç …B¡P(N:÷�ÎÑ÷}n×È_«ªˆxïg³YîÕÈB6$ 3˾UXi"2™L²º°ÖÚ¶M)5M Ëu]ç­Õ”[1³ãúy3Î�;·¿¿¿³³3�NcŒëÀóì‹uÓ+‘£P( ÷9d`(šoaÀ¦mI¡�«R(©E¢¢¶]¼øÒ÷žyáËWþ\ëצç–&‹yèÚ=�G]¡£ÞR�¹ÃëÏ=ýÌï!ØÇ?/œ}2væ�o;ݲ r´F25ïÕ¹ÛÞ|qµm¯.æ×B÷RÈžÏúú¡éÖ#Í䢯w Ã%¸Õbo~%UB"X?Þ#˜Ô‘ )`žÌ±xbsh‰•1”mÅ,u$’g 1X ¬B&0ùm¥E2_ûª®RE ©£ØV§‰a>%ŠV‡>åy“‚p¹_du•PP¾_&%9nÆuÅœeEQ4¥…î»)s¡P( …Âû‘ûnЖUM)­ÕUÍ홵°‘m¬²tc\,ÛÛÛëg-—K9<#UåG†êºÎÏ�1.—Ë­­­7ÛžµcUJÉÌòf¤”rhGv¾Ê)Ì¼Þøαi]U( …Â)娊ֆý,^(0ئ™æúô|Y¤ìð³~€­KûɃÿϽþµ ǯÃ8�­Ô.Sb ™�…N—{í‹Ï¾ö•?ýóÿ6:wÐé^ê®A=‚§lä�>¢o;¯×ªñÅnþúw_þÆÎö™sç&Çú �1ÄÐ(ÃÞ‰g} Ýél$ÏÎïÏ¿ýõçž»v0ë„ã–_„Vúp¶jž¼xáã—þØÅ?3=·7w ² œEÉ~@…Â{A×uÌÞ±gq QkM“)Õ®�e 8%Ê'pç B^áØ$'‰³1© ¤f¬IØyÅ’¤7 ¥TûQíF"µ’êD¨Ý©_EÚJÏÀp+È—Y…6y˜ëûÀm]Mjç�s)żp0‚Ȇ[‹²(D´ÏœÀN#>Öa4øˆ&%5ˆÂJ€‘Ù ÜþBá$C€2:±ÎàÅH@„U`¯­þ±'‚ÐÍN½Fë™ÔM×µÕÉäÎú}o:~—@êòìL’ÁŒT‰•ãÒR_8nî;�#“£ï6¿Ýüéº{cýEþz{û�‚M+ªµ�•V~®sî-DŽM65Ö_ç/ˆ(+(o¸ñ…B¡P(œFVW:c[‰ú xᔂZ¨'35$‰¦šHjÂ,ÌDlŽ)¥@JÂì¨&åIUÁd%Zöôb”^õú(ÎÂxg·§küÙ3_xfÿ·øü =&Ï46íRHÈSƼß1ÈRÄ|²}æpþòמýòãúÄ”ÏßîCÆÔ9ï˜æa‰Æ¡ñóYK®šGJ•ü×—^ÿOò•o†Þ¦ãºš:“ÞBë4t¥öOïÏ~ûðŸNËÿã‰ÿ•­eo²Õ,f‡1.·w϶1¥”´È…÷õ•j–u!ªHî@5 @R™" „ C'Ƥ d43:d‚i•,�+ V$‚¶ ah…b92y'ïÿ›â‡A*D…s¨G„hÌ�ôD.%N-ËÁ1J åUM”]â*±S"8Q�92�¨uC®”‚ÆnRK;;� ¦‹£šDž$´l{‰PÁT¢F …Û%Œš*ê•zd„…VðA²*ñ1 C¼¬\¬ûwWúÿ€®² p¹ìN 5&®„%F´×û]¸ÚL¡@¿8ô•zCèbç›&ö�Êå´püܧ:G¡P( …“Î�U~yßÅÀ a!�YDRb°È²mÙWÞ×Î�`4…4ö&YÔ@!)›×Ì.•uÞÓ‹U° »�’dXT3JJ±ï¯ïu/-ù¹è_u´QôfÀ*Á‚1O ]Ûê•ćKÓ¯üñ“;Ö…aCÏš<� )™¸èÓ­ÿþçÏýúwÿüY£Ùî®*#êf©©Žž[ÏJ¼ßÍþ¯—_\\?xøÑO~f2¶ÔS]ã`1¯FãeßVŽKDGá=ä¨ýÀZ6ȇêÆíêœO1»]�”-‚ ‡“0( /h2ÜO –_�r )G±y�ÇÜ�[²±…C `9˜ >ˆCez¡ðA9Hi£åô ÷?#èÐ(q²V �°X,¤�,’K¤†“šÙ)& QRA*Si±-n…hòªAT#©Ó$«*Àʬ´úǃ¶±>«h¾>Bɲsc~Ú;: Ù{5˜+¤iÆ„% Pop€38C‚9ƒ‘E”:³Â1StŽB¡P( ' ÎV«é½aU¤)2³�S�™TDDÌíÔ;]Hý2ÎÃ’Hœ÷Íhì›íƒÃk"$ì�ÌÈÀ f²TÙ§�ÂÆFCâ…ª:瀤šËÃý½×SßS pÖýþd�¼ÊŒÚfäÉb ¯Ëˆ£\}î•/>ùàOßÖ³Á3'³9+œ¯@ÔjÃõ!×ߘïÿÿ¾ûÌW_z1�½0 |"˜:ŽÌH Jð ̺ùá7_}áwmúà“Ù5=ë«<›Ô“ÑQ=_¡P(NdÄ01�‚ ´.ºf�‚(Ù"kdMƒ'I·Öº®ª1GÛnÛ­Iõ@J�$eÞõ£ØU;§ñJE[äF  =:¦H»:{´‚Ð'Tv”õ–K,ß*�å|g…D‘ë n¿L†`N¹&=F1n-÷¯NƤ³Ðm`B¨ajR@J�YáØ):G¡P( …“G®î#[EÅ8ÏdHÉ NÌàÔIpa®ž§#ç¸AÚÔ-‚ÅŠ+&�Â�ˆR¯½Â1BccS RJ1¼—ì÷æí|¶¯Ö×)?R‡ùÌÁ`¥Ô{MW)ayuïYÐñÎÓq²ÔYj|Ím²ž\=:úù?ý“?ëgvn—šQš÷MåÛqƒ~®°Ø£®ªÑ–TÎÿþKÏàìî_¾ð@PsàQÝô}_55b™g … … dÌÐì¾@IAH¤�5J¾µÈªU݉2~JÚuú r¸úyŸz�#'!2SP$"S3gˆïþM …ûcñ•‘7ñÑÈ{hÕ/ñZ1´ŒDP@ˆ·f@T€_U·ä–�¬‹®çVÂp€D‘ ­!Ъ ò­oï09P$E0›L&©­sêÙ`KC’–ÉÂ{@Ñ9 …B¡P(œLxðmÇ#ï\êaÑØ|-c'bi½³Ü‰M0 ¼Ï⸒ƾO-±Š7E 1T®¾×¿]áXQIÀ:_ÑÌÄIˆ=I‚†¾]�Óüp`ÕÏT  `LÆPŽƒï!E,Cw¼ÛN9hÆ’)³s,�šççû_~íå&•lí"9;˜{¢^ x"².Âb°Šà—Ô<÷¾øÚ‹ßÿȺyëBÜ™Lž»~åìùÝPtŽB¡P8ñ¬5Ô UÖ(Y•5±Ù°tx‚Ò¼b„*5²û¡Ç~¨—wÎÔ¼M�œ¾ÃÃÕÙy3-ý…Âí`#f‰É³”ÜÞõö™?}ùó•œ÷uOrt(dƈ’{ñìÖ®›ž‰DŒú˜"µä˜< ‰™Ò Z(ÜUh¥�Áç¶ ¹«#š:¤>´äLD4&v¢á(žFƒ¹?%�‚Ìy¨"õ Cì;Lª-Ø1–Ï*ÐCáEzøÄˆà;Áw®];�–´‰lÕMRÕ®C%ˆ̵«|[D‚tâu{úÕýׯ›^$‰}p[Ó» Eä( …ŠåêçUD ޤSRz;ŒMÅô®J%¤êh:š|à/|òãÑû˜âXÛBΠ6ôs0LÎpÌ¥…©�RB<`IH0Z^Ùûöïÿ¯ÿw þ`ö2¨€¡ ÈÀsB’äÉæØxթ솳‹1Žr;¤FI)'åò²·¾%àÌd `îúdTûf±øÊh¡ÈHŒt3µÙ;Œ)î„¢s …B¡P8™lôsP$3�¦$ŒÊóÈ©‹‡8ÜÃõWºÙõöÕg_g"3v,x}ïðõ!éñ�<~ö?>‡‘L["¢V&F¸×¿\á8Éi…åú5äºW"c?fiêÚûš¹‰iAäŒ�;9@¥œØ¡ç ŠÐø‘…�Ï]x V߯+£×Јԑ›e)þ@ð̵«]U£ô°d�´]¢íQU05�ªÞK¸ ‰Œ­¦ùHž»òêóû™ì²qêúÉdBð%Ÿ£P(NFPcÛ°ë$¶ ê&#˜ÔÔ«ú¤§êþ íºeJÆTIå&õ#Ä3⨮i1%cX"ØŒˆ¤¤� · ™z¯Ì‘(„¡^¿ö;×í]î”@иeDV—O¤Œ>g�¡ ,k܃‚Q p̦ÞÞ¹Š�Â÷b„Ú‚­Šy4ƨA\ÂŒFˆ„аDÀ**½P8FŠÎQ( …Bád¢Ã8ÚŽÒ:,%祡€ù^¾{ù{W÷_]óÙÿÛ#ÿ"p@åšù¾Š¨Å{ýAN9Eç( …B¡pâÈ#r…tX”5bãØ©£Ñ|¯>Ø&§¢ãØBÀd`8“ (�Ì3Ùìð€Ä½ôÝÖJ›¦éâÂS�nh•=¾^AQ� ³A‰ˆÔMÆg>pù£¯]yæÏž}iû�‘JH‘H�àêW¯¦Š1n¦±ÚÝzðâ¹mMD<ƾ{<˜“EFb1KÑ›\˜LϺîµÃô�Y-tÎÀŒ¾±«¼#o� ðÆà“m³{èüy(@:�_:¼î«ªè|…B¡p2Éý dl@ V£ØÇ9ÔzC0Dö&|â”k^5j̳2Htµ6ʃç�¤0ÂÉjG)N.dÕvuÎ\èÓkÆ3+|2’²00¬6ä~ŽdAšÝ[9×�™@D³åµjŸ}ùOþìÛ_T÷z’ëâ§¿ðSÿ/33åÊ"""U½u{Œ’q§…ÕˆgfšƒÌaréüG'xÔÔµ}ßw‰ÙWUݧþ^Š…ÓO™ä …B¡P8™XN†0,X›×$�Œ^{eñò÷®Ø‚kž¸ÈA«Õlóªä&Âbí"y{éÙ×·/^š\ïš>̩Ԟj(—¯ «-ÀHAj¦DTUMTÒ¾¹tî©§ÿKW¯½|¸øŽùÖ ±�IÓ²G×b±Àö<#µñ`VááG/üƒ—?sfòx¸~Œ¾O¬Á#¡sÚ6¨ÚÄ)l§úɳçšç^†2"!:l9)&Ù�€‰ƒCì"Cän1 í£R=²³­‹ ¤TWóëó³“ –J1]¡P(œ8²È‘«¥7`ƒ…˜Ô×ÔŒ ;'£)àB"ÈIÒ Œ�D0EV6L0"˜R¶»©ïê½ …û R9¼Ú{wöì¸a÷xÄÒ,© ˜ˆL× ¢9#4q4JJÊP‚’@ÙÊÅfãk®Y¾zåJXÖ �ÔÀ…êâö'êþ±¬sdm#ëoØ ¬àÈÎHA&”¶aL<õ��qp �C¬4ömÛõìNÒùªpJ):G¡P( …“ ¾±"‡&0ç¨aŵ+ó½vêp±¢µCÌ�%°� d scLÓ¾_öóöÚË{»—ÎBƒ§c W(œ Œa´2tR@�B©F£-ëmvýp|fòÁ‡>Bû…?úi_G¢ÔÔËÚ/Œ”šZô3ótæ~âÃOüð;×v Vߦ3P�û�#ˆ:o–ú:ታg§O/FÓZF Å®•ºá¦Öå ÂPêb°. Օ U}˜|ò¡ËÛjˆ=; ¡öR, …Bá¤B ¯K0#$BRÄÊÆAҚ̙•6ÇK'�ql s`èå0Ðj¬ $�¢¨…ÂmÃVIm A¡�IDL)xñª ‰³Ô‘ÃÀUØ ä�´ÅN8ŒI�c'*õsOý„™±²>} �ÃÌ'Œ”^˜Ób¹h©Ú¥J@v©jÒrÑ…Þj_òá ÇNÑ9 …B¡P(œ4²9µnL‰æH½ Ž-®¿~ˆä¶&;‹¹¢Ç¨AŒ¡!ÊP¯R‡ñ¨ 1Õ<~ý¥kû‹g÷—~,Q‹QÂéÅ06Q8 ‹šÿ±£˜bJÆ4Ò8Š‹4Ýzä‰GHmôâ•§_|ùÛ×_Y‰È««:_a6Kžêó[zü¡Ï>ùèO\8óI çg2ªü1®+‹1›‰gÕ]2o¢í#“úx(ì]»rmÏš-«8xÓ#˜i„2<¡vÞ§0²ö)©?wñò¸m†÷î`>ÛžNCHôî7²P( w¶ap"1Ë]‰ D\y›Ž•{}ÖUä¦À澩£µ÷z«oø †v Ê ²M 6¤«fŽl)Y4÷BᎠÔL`)©ÂTœÔ\UÌ "M¤Ä0üáHi"§¬ G¦b€1™P‹ ÊQt"•#¦eåk¯ãµÎ1¼-½ñ°Ñ¬‚N•À$ ÕˆˆXP; i§vÒ‚=�ª‘&½Ww…û‡¢s …B¡P8y�ʦ:T3:6ó¹¾¾�GcG.µ g•%#1Ä47‚°å¸ÄMQ_®îÍ9¢�/·ÆMñƒ>ݰÑjµ…W‚„Z7~1�í2Ôõd{|Ѩí—3gÿÂÇþ÷ ¯}pgüôkWŸ;œ¿²×BÚ³e|òáK[͹Kžzø�OžižB>öÛ�Y¬%¨Ñ@Mb¡W!«4ÑrÛO~ºþû_ù/½¨g�L·ç!b¹DÝp 05Ïä�"õË%Âáörù—?ð‘¸ðÐDûÚ BŠ“fr8Ÿ{9Æ|‘B¡P(¼3Ö±l& 6(8'F2?paë#9£·Qæ�n2šy°ØÉi‰Xëù*Éç�R8ŠÎŠ …•%©Bá6Ñ>ÌUaÊD$ì’¥º ÉS¥Ãê®®TF!Á)AašVÊýUf¤ÄÎ4¨!Äa6�Q9€³·œaÕÏñ&›cUPLÜ)V�ÑP£!g € žàQâ ÇO¹¨ …B¡P8�èQ½¼­ƒ\èsÀ´'•¾�¤4nÐFX #%Óˆ!›dpŒØÃ;— ï%°±#îË8û43xßx§–R¬ë:.9´6�’ú¾�ðÓnÙíŒýØ“—>ò! ©ïúEˆK@G£QÓŒ¿-¶–#ÄÊÃ;/ñ8s•TEx¢Üv]ªEîúŽÕ}t²ýS�=yùÓÐ^÷ &tÔ˜'Ò@™ˆ ]‹~^O«§Î�û¡|ð2¸"F ]ì]U™R©¤+ … [vàÙÐ a„Èh»^<;¸ ZW©zm:ž[ÚR:Y �)�ˆŒAHa<ØX�Aj¤ #+õÝ…ÂmaöÆJ0O$@4XR$Uç áßJç °À!!Ÿ(„ÍÃ(A½h%©â‘�÷ܸêÀ�§0gp–?LA0€Þ$Õ�@Ä=(€[†Âš! ÒÍûX›«Ç;ŽF‹H}„÷T¹ ÇMÑ9 …B¡P(ð0ùòȘ�aPVMGnlPBäÁŒ€ NA–ïWå#OŸw1ýf%5Ê­ª¤UCíP×uˆ¾�"~<Æü:Ð@9�i"&bÀçM®Ì\CóvÑl5”0r�£š­-Þ=§˜a�E¶'Ë]> P» gvÎôêæ³3@JpÓÑ…½å«";uÕ0ISÏÁ±¯GU×.*×P¢¾K‚¦ñ�˜Í›Ññî=‰ˆ+ã D¤O­©ŸíÿØ “ñüO¾òÍë×m2®UÜ|ÖiO©«Uµ·vѰ~úÒåÿã‰?ÕÕþÊõñVµœ/5öÛ»gÛk;AÅ¿…B¡P¸ʱFª¤ ­ªÆ‰ïÛ®"B”CCõìУîþŽ6\oi™5`³ø ¨…Â;CCŠOH03K ¸ªª¸ÖD´î”:’%؆ž*G¤¬&À¨j ƒ‹QÛv0$avÌœ}«˜y�Ïñ†=d S�æ‡Ã P·³3q�GBŒ€ˆ&Á0£+³¯Â±StŽB¡P(î{ŒIk6"‰�}“‡ÉªÑ`7`pÙ‚@ ‘�ÀNá|”±d�’²�“r®Ý»ýÍ!¨9#5‚’‚�0ãѸꮢªi¿�o�p•{õLÎà-(†@Ë5Ma„aø)ãaàå¹íf~˜v.î^GÍ%úò“kE�0̧HaÔµ¯—óp͈�%`äl±h=M †Žð`aÏÆºÔÚFh�Ü‹qãfDǺó){VKQµ–Z{µ>î ŠA5*ué§/�ûÀôs¿÷�oý¹ç®Ì:á¸å±•E8[5O^¼ðñËìâƒ�'Ùší7b˜/'Äðc�µ!¢ è|…B¡p1R5€8˜X¡ŒàP냢Þé,l$Ò-b¯'j0³*30ø� ]Ö£/%ãun¡P¸ ˜)7L$ 0MДõƒu+<‚<Ÿe€Ì© Ã/A€w`,ºÞ�«äæ~¤}‚ç±™Ár2‡YnÀè�bÈWz¦©&E®¤ Á«‰�$¥„ºöj¥Ÿ¾pì�£P( …”¡Æ„Ê+Ã:Ì; €¬ù¦ÄX–�_bÊÑ߯56ÒDH §@nþÈqз ¯tÌXÉ`•]L}3©¶ÏLö›¬¾Aj#X¨b!_„!Ä„.€$�:mMêéNC燜$—‡Â1qCk[Ë­uKë+ÝëϼPxcV> @ `ÐÐߤ)ö‹°ô}ßµ½jâ„§Ó&ö–º–â‚L0›[ÊFU¼Ò9¬+M…B¡P( …BáTQtŽB¡P(îwœÅ*�*X‰I"Î=Èd ¨W°Å*Y6Iଇ0œAU™�û<”„´êß ãÜÒwè”CFFë–Ž¤FQ¼K„­süè÷=ð]¿òÜ~Û-yÀSí ¨‡òÚ®I<\îѨ=i|îò¶ßÂÜ–½µ¨ØHßy£I¡ðž�L0Ì”ŒM“'iˆª”\ÕÈUuÃ>\o9w\±0LSŒÉ"*—H#ÿË •dŽB¡P( …B¡pê(:G¡P( ÷;lpH9ùÒˆXQ$甡bL(�lp¦UG`ÊnUȱáF0b6�A°½“ÐãܶµÈ:m-ŽG[ç–¾ß:\ì^=8Œ4Õó@#Bâ�L»¸ìµUíævýâÅÝG?üà™G(ø´èçæc3nR[rð ï²±²@Z»*Æh}$`ÛUÌ,€vK�Ȉa �&3"¸ÀQ@)»ÉÝëߪP( …B¡P(î*Eç( …Bá~G ‘@+“Š×е†ù?ndF1Iê¥7JÊQL›0xU‰e)ÂÍǹŸƒÀYá`åwݼŠè Ë¥èJ"]Z²ºÚ�¶/úGìüõWg‹+1îÏS(' önÉ ügÏïž{äÌÎ%âA»B^$ŽÂIfåRµv{ËY‘ RR$˜ ˆ,H"�)¤èGã`1¥RL0vŽÉ‰* eê4¼x$·ÒÕQ( …B¡P(NEç( …B¡Q$Á÷® ÔôT÷LJ¹ƒ@•žÄ¢·Ó*åRñ!®ÜÈŒ D«råa)upˆºµ#'�` R#Œ§£nú~©¦õÎø±Ý�‹—v^úókןápÞÅ�LR5â­³“­sÍcO�7�ÖÂl¹„Oõ¸JHm»lPßë�¼PxS²Û›mdu�€Eìç«J8Y 1iôÌUåæi'âÅQÍfQS0³KNÊÛÐØ‘�CQû …B¡P( …Âi¢è…B¡P(ÜGˆHŒ1¥ÄÌÌLD¼Uãè}ZŒêÃí�ga¿÷Ò‹_~ñ…çZMa¾Ø%þÔ¥Ëù�=µ{öœÕ±]$[ž�Ž—û‡#ï*¦.ô£­ñÕý=ÕʱÙGßaÙøfvù*¢X´ "_‘Æ  U/S÷èÇÎ>öÄ€@É9’š¤²Žz夤ÂfD±OFZ‘£p‚!ç& LH%‡4 @bdj†¨ž•­G4�2Àƒ¸�sä¸d÷*›ÂS¸B¡P( …B¡P85�£P( …ûU "YáPU3Kàƒ^ǸJö;ßþöÿ÷Åï}úÚÈíOJØÙ½®ôúáë_ýÝžoÿè÷=õƒ|dÒ»±—åá¡Õ$)ÄvÙùºŠ48ã†dŽœ)þN¶•líX)¯�vŒbb,AAÁDªÔ@5™%FŒ e�l€))0¸ô°a:r¯ÿ…›’•¡¥‰YÂ)”�” DAWg�ÐÀ ¬«»CþB¡ +¦U…B¡P( …BáÔQtŽB¡P(î#Ö�f–E3›9ºzéìËÿè¹ïýÎ7Ÿþúl¿={¶�a Bw@é€ñ‚vÏ/¯¿tåùoq÷¿=rÙ‹À×½bB^Ç®«·&Q{ਙ@¢a‰öNØ!xý™nÜ£J`ÖdlZ™+™ÔR23KAVLÀóðEÞž"uN(¼ÚÕ0Ë·H¬Ü”U1ˆdåJA %†�sÿ‡�sdŽ˜YÅ…Ï6«B¡P( …B¡P8�£P( …û3ËvUYá ""ê|õZå~ý™g~÷k_¿–Ô?øP[Uš®1Œ�³ÕöÙeèþh~ð½?}ñ¬·Éƒ—œL¼�J">jGD‘ �CÆ Ñw„’æøå [®L¿iqV•À¤‰4P«lŽ˜H5KJFÄùUƒLÂlPªM¤P8‰( ‡6õ @m8(V=j&##QÊJȪž`l¤JÈ_2åÕáùΚ¬ …B¡P( …BádRtŽB¡P(î#Ö™)%3fNÞý¯×¯õÕ«/†èwvÔ�–0àÜy„ã\ ÞÇ]„ÊÒ7_úÖ7ðõÙ��µm?ªGªˆQ³ ‘C�sŠx"AìĬú-Œq£ÄA›?…‚Ô –L `2 óàžõF/[š9 '£|à(ÍÊà, dÄJY½X²i>F` 0ƒ"H‰Aƒ±• ¦X…B¡P( …B¡pš(:G¡P( ÷ëfQÕeŠ¿÷ígž‹a1ž�‘ÅUvHrH1�ŒÀžî[¯|÷Ow_øØ…‡'¾‹°UUŽR ƒ”V‰`dJ�;]W¥µÁ·Œ{ŽR”*’dœ-1‘ To¬[”˜ÒÌQ8ÁhÊýK«® Q^ïñ–uJb#èªY*1l�:X‰aÄös2âÜü„ìÚŠuU¡P( …B¡P8=�£P( …û3Ã*�¼ïû«]÷çׯ]5V9˜²H3kBß_UAbDUÕ£ÆÌRè–ÝÒ×Õ·^}ååýƒKÓ3ÉX�6;ÒrÁ¸®–bïPêPË:Ç�ذ¼KÆ9œ`6]ûùprÎÌ@f¤`"10åÜu�Ë»¤:¬ó–!Pá„’�¬„ˆ,²��±’)„U©C•9p¶ºb2f#‹æ8òÕ3Vaæ#e'«B¡P( …B¡P8-”I~¡P8½�y1ǰ¹¨3T±Òp'a#ÜØV÷ßÝÛ7Þ›~Pªkß¿ð*×WW»S^‘Çj¿"#[­¶çÈ`Îú·¼Ô­~Jü&÷¿=ë®,o I³AÂ&.2ÏR¼úkÝÂ&5¶Æ ÑÚƒ(³÷ˆ� ð@ÝbMA3vÕù—®¼öúla;g@c4N ³Ül$fØàXeP¾k>Qºþ}”rÅ:“!Ec#°0�MIÍ F«Ãú�^§q…÷¶ºUÒ,u€4kÃ!`P†kCªõî­´º ÑêµØC¹B¡P(î2æŒ@ÐáâCJ¶¾Íéh¼þú=aðx$c68S±˜€Èj ³Š¨°!±FQeÊî‘¢egH#$V3%U§ #c—GÓïÀ•µP( ÇGÑ9 …Âi%¯&'Ö�óŠÏ°ð<˜ûÛzù8 O²�5Ñ»{‹ÕçÑ0½Åš/­þ•ü€÷ VxzJ¹øÚ$ó®r®Jˆ KCLè4ÅÊ�M¡ 13ÀfI5‰CÎ0ŒÁ͉·µI«'(&ÍR R!%�Z˜9é'£oó{R9À‚"� ‰3LÀ”«¿  a©ñ€\UM¯íÍ·u·ª˜z³ä…SJY…ˆœW]¹NʆÀwdÅ«gu�®'’Ùujx˜±Äk¹2g‚€7(ë$>z‹BáDBÆ«N ¤*k#­¦&T^óuN=ƒ œò£‡'Ò‘œŸóÉïõoY( …Ó¼lª¤ S(SþzÐæ•À`ò@�Žw¾“Û#50‰A”½©×®´l½@­õ>Ž8¡m}2¢DX £È#å(ið&ŠqÏ>±$IÌ�“ÄfÐ2e+ …“CÑ9 …©å�ª„høã ‹²Äqôse ”Õ¥SIöYÊýC þÐdØoÅD¡¢ìIœˆ�¤Þ &š˜ˆÌÄ,½›î�áÕ†Ýp,8b"KæÀ�h©g—œª×2”×˪¤š{"Ö‹DËd(‘˜Q4 zíD, ¬àÄ€ª(Ä�xc�ö¶ÿè~ý¹vò`9 'ÚÐ!rÒø[·_d÷6ë=}hÜòÄçB¡P(î"VRPR((* €²Â8+ôYnWZ�5�m[ ™™ä٘ؔ`%‚™ƒyVaƒ‘G° î‘Vˆ ])‘ÉÀJQ´rŠ\ФmÜ…B¡P8 �£P(œV`˜Àd�4À)ŒA´¹Ði¼Öýwûö†âô©ƒ"Q‡£H‰Üt Æ4[ f_“¹*ªumÛ÷]ã�Ej'^¸6£#’ÙQÐ�Áït*x«àÇÌ2"MI•TâD'R œ ½YE°u02GSe!_‘#M–’ªÂÙ)J±ú FHeX( …B¡pʉ žÉV¢ûz(›‡Çºš ­~JüŽÇ·ï[î™^ p³±±‘i® ÊΫ„DŒÈ””²%”©2Gæaù ›ª± ¡�ÖUJ€ ÙöÛnÔÎfLh².…hÊ"¾ªª”²« EÜÐ ÏweGMYê#‚ þX^¤r5³9…‚`¤7¬ ­NÌšƒŽBbGÞ¤®¤ieÖ3œS0{1¿#«h: …B¡P(N9„dW l©¾&�‘�W_ß­æ·Û$£õŒK‰Í`+a%$ú–�ªS‹Ù芡<¶z¤ØpØ"k/P6J�÷Pª) …Â[StŽB¡pjQb¾qiØè(´@6¹òç€�”¼»y{ã;½5vslzá}€ }ëêÈ<´X)�z£95m]Gs©�a±\¦–*©Æ£‘£ )ÅκÞL«¦ž4Õ)Á�ƒÊ Š£š¸w+rä]*¥ x!" ±#æÜüæ~¤ Yîìc6ˆ²Ì9’¤,ÊP¦ü2 b3Š¡MjèççâØV( …B¡pú!c2†1Læ&#dmc¥pd?(P8V©c£¦, šÛ22‰•LÊo©Nªœ‡®šš=W•`Ãøv$ÏÝi™´ …ÂÉ¡è…Bá4cëEb¾_�vmã¾ÍUd£c¹¥[•‹¾]·o—åà÷)D*CkX ó€%ðRêù,¼<Ÿ½ºèö®ïï½~moÙFáæÜôüÎôܹ³—¶¦çÇgw,ŶíÌÁ)Üd¯öŠw«|å2´Œ™™© Ȉ¡–’%r‰ÜÐÉÁ+‘ºjEvËì\¥3 šúúˆdPB骨mÝ2e¤Ê +sÀB¡P( …SÎÐ¥aL ˜#0LŒ¬&¬üT‰«ò²ãŘ lŒ<é£ì ‰ÔXA¨“61*ÇJ•` (Y~0ç¨;zŠ2Œ ¤HeâV( 'ˆ¢s …SŒ‚ kJË×£QÛŒÐ8nÞ0 öÍ6»xü¼ß u †9èV)ظ7Žêp¯=ÿòï?ý�/¾øúwf‹yTŒÆ;;Ó Ï>›¶Æ¸øð£ä¡?4m”~Ô-;æm˜ç£P%0 wªlN�†P "2è©Acìº.2L²¬²~Ú:$oŒ&f‚ZL±1"é°yfPð CÞì´ê”* …B¡P(œr†¤:¾Ùsu�9wC¿ò{1ë¡UðÀ‰ ¤y°›HÁR241m…İQHURÉíÍ€((qb[½ŽPAW9êEê( …“BÑ9 …Â)F�xËè9cnºõÁÇÊÛŽ€u5ú/cå÷'æH½™d ¤<7Ùû¿þ篾²ÿG׿ߔf¹½íû�ºvïêìÕñøÌ«‡/¾týk/¾ö�'?ø™=öÎm=1žž mGÊ0š9À0~gjÐMµÃÀ̪ÃÞNDd¦1u]�ÜzŸËÕpt;²5½<ݪš"¢#2Rµ¡u£Ô¸ …B¡P(Ü7¸��U5ô=¨±ÄØ/»eS{##"# ˆPðñt€s`#Ø@€åI EeŠÏˆÓ…��þð'úÀ{öUÔÇ]}nÔpŒHê@bÄšċ—dS§0*u<…B¡p²(:G¡P8µ„¶³[ícŸL‘ p£¦0xÈéwýv@a 1 Æú® Ëåm{q¯zß¡â•ý"q/>»ÚöWþô[¿½·üOŒ£ÑJäXÝš<’ÂW‡Ððòõ§Gß;sáÜc¦» 4BîC"…9P|ÛtëäË™*3à)�ªú¡éhô'ËñÈ¥dýla$£ºñb¾¬šQJi9”À &{ÙßêòcoM}€¤À¬ª=ûJõ†}·”¹ …B¡P(ܘ\{½¯ê±“†ÐÅØ+¬òÕööVн f(i¤ÁΔދ`B2ÎV®Fä•ɘMñ̦ÃrY¹ê±í3Î_P†ô˜¶ý$…Zçˆ('Ž › %cA²Á�«P( '…¢s …Ó ×¾�9õ‹Ê¹¼òÊä<ªAÕXÇë²ÇÚ4�ßN@ï!"ÌðÞs]¯¶8G#…ã}‰º\íú¸HÔÕÛí·¾ùÕýîy¸“¥”V"‡ê@±`�¡ ߤùáüÚÁ‹W®~÷ü·�(’Õ jÏî¼Ö�mHæX?W b`æƒ{‘ô!2¹sÍè/\~�¯ì7®’Q@Ë�T|òä“@26“˜¶úp^ñ‘sgωðbæ4+ à`A�r_?XYEÉŽùà* …B¡P(œêfLÂD1“DkµO©O•s °¹dLÉyGžXÍAǧsð "б‘ZERÇ ïRTÓˆ¥VfÔ D­™&)rßA#;‚ZÛGu.ÑZç€˜Šæx�{ý‰ …BaƒrV. §2Gê9ú£è»€X£hdlücFÐ×­µ@ ª!„Í5õ7£«…÷æÚ–«êLú´y|ã[¿W�[Ô�q7ˆÙöI…ÌÁܲ1À Äi4ö!Ο}þÛ Š@:êá¸{Ó?#¨ª™133“AC„j“ôÿþÉODÜÎõƒŒv]Õαëü™]8AU¡ª…Ý(Ò´í·æý™YûéK—>öÀƒgL]·hÈ„ABÉR¢l¼Úö•M@¡P( …BácdÕ˜‚-çý5ãÅäŒî^¬FÛ*Ml–Ð)©�•ªWˆí˜Ko�°^õ �6FHˆÉRt"Må¦uµÃr&êv×íÄ4!Ô 5F ëbˆÌ‘Ñ õBJ0b€È¨4. …‰¢ôs …Ó wmôÑ“¸Aç@¨Ä¡´úwÓ�ÇpKÕjËDd†£õýÆ6mã}‹9�ž±ìõñzD÷ÜKß9÷°ih³%ð�“ E6•20!D°ª÷Czé¥ç@ ˆC@ tÕÎÿn}r3U%""`fd°¤Òõ��›ŸxøñjÖ~íõׯϗÕÎn�Âbˆ Å”Ë:†]¡�ÿ¡=õÁ3gÆ{ËÚÐ0Z ì(¦äÈ`€FÆd`(•y`¡P( …Â)†ÚE<°º÷�F´Wz횊›ñØâ¦™i']o!ø Z¹cŸþ¬Þ€Œ``#0òUo©OIÈêŠXLR¤1 «²†d!AÁD"â]OˆD«ˆ#…š•Kép¡P(œ ŠÎQ(N+4©·œ€ë-a 0Z­Û†¦°Yj~|K±H^ý…š¦™:„vÒW³{ýAîV;u-.$>Üï®»ÊwqŸ8™6 BZb$yï».:1a„DpÎ…Eg¤ÊI‡~Óá‹�z´wƒª 1bŒJ""Jìº8ZüåÚ®ýÚŸþÑá!šÑ¼áð£1ˆ`†˜Æ‰oøÜ…ïÛøâÅ�,—SÇ,˜÷=ÕUBRb%%ºaS‹ÈQ( …B¡pÊá…Œ^\èkóÙµ+×^~å•ïî\­+·µ}æì΃ÓéÅsÛ��GIu–h”ÈSbÐ{×ô««·"ƒIfФPÄ`ÉÈ5Žcì“õ&ÉX“3SUŨ�``Lj`S©Q+ …FÑ9 …©¥O1wص¯¾P%�ƒ¨*Kr‰2e yt ¨H_ŠEç©ýÿ³÷§[’$ÇžØùÿ‹ª™¹{,¹VÖ‚B(÷}·¾=½ñvó4ûÌç�üÂ'à“ÌCÌKÌ>Àžvs8=ÃÛ=—½Ü;ª°Ôž[,înf*"ü æžK*«Ò332净Wdd¤‡¹‡™»ªŠŠÈpÎ$ËOÒýOÆÙâVÑ~{#œp€x+&HBÇ+Uë§nù7Ö<BGòi}\ èæ ™ò.þµÔœqãæË4ÔrI^EêΫ}Ê}�<›!Ý;³×ߺ·¾×¶#Gn›Á`›?äm#«Ofm·´Þ�®Ëy>§5°§Ñ hNÿ ù¶y¼t8/ú�‘S6µRÔ©é ðQç]·,ã½vóèŸýó7ÞûÅÿôÓŸô÷0¿õúí³û­¤Ã2®Ç·’üÁµ+ÿìûßûã«­Œ#—ËquÆÃsÇ1q‘ÅëoÀ £×¢U±Ï-„Bárp©£kº�@�ÓéàŽ�•µŸ~zöŸþö—ÿæg?ý«åpq�SÂúlè³Ö’߸õ�ï~ëOÞyëO®¿kßlò�d íË3hä]Ç¥Ékswb9Œž<ç IbBŠ ¼Í��ŽD¶mqÆÁÊZ ”FƒmʱZ�¾…Âã¹8 L†d€#;áwÖö™F€îaŸÖ¦ÆqŽÂËÉ©CZç|ØÉñÇ¿ÆG¿-F€@ö"nâî„JÖtbØ_‰Õºjïô1­Å›[³ë,–SA2$Mæ­˜GA¡§çý,>;kÔLÐ'Œ p4†¦Hc0`?Ï2ÕÍÕ\š”×¶v2³$sº»º¼›%w`jìÕGŸ¥yÛ¶kí÷ê�•{™µ¹/§Ýl~,¯ûê@t&¶JÜiÂí¥Ò¬ô]ƒYƒaÙwÒÍ›E¿<�åסW¡×k´Ç¥˜{ÍçpØuó®–u¸ä¨ÿ­ñ³Q€4BÒuEC!µS¿2èßkò;¿ÿîõÍ[¿úì³�ïÝ»»Òœpõ`ñ�wo¾sãµ›‹ƒÖ�÷îÙ´9:8usE3;²56âpÂ`›àJ­Xƒ¶B!„ËEOtŒP�Á €°uË9ÍO–wÛ…ï\;ÿ÷÷?þëÿí(íglÎ¥ë×5#yƦKÒû¹û‹ßüè'ÿîüÑó§ï¿.g‹Òç,û"Òʼn’Ì€Z"‹À(&mc4ÜÑ’"μGã†3‡4yÀ!f–µ2„�‚߆>•TtƦP”M!@©ilxÝ¥I§›@àuÓg¼ª|]ç!¼¬ ²v™9`ÈÙºäÈnÉ�îNSŠ’Êì¬c_ãÓ¿ '¤ékÄÍ}Êä0€€Qà@_µ|Ô, w#Œ« Èäè^L‹¹äÔJJkÎOºY¢q$:ÝQ ŒëeÍѤYnsn“5ãXöþ‰�ÆØ­ˆæ@�%$´véH}?Bõæk×al/FK&>…á䉂»­å§Ö”ÁŸ`VœÅò`9§Ã¶¹•ówo^Ž›ï~GU“¡kÚ &5z€IDATƒ¦Ë0‹jÉðš)R¦US ÎæGLQ–ØêB!„piÕ¡¢ÀE`Ӟ㺋…éþ½Óƒ« éúµŸþègÿßÿô£åùž§—5dÓôÛÜQºcœžÜ?l—ðþ'¿øó£ù›oßøg³îØÆ¯Û‚îËP°�ajmÝ8íšþøðv¨‹£¢#5À³å¯ØL-„ðDœµv pÂiF�u÷bL‘÷(â!„—-¡ÏX+éÈHÖ7š:H5B’; uïyí™üôo1õæ€{ÔCx op±Ûݦ¾Ó,ãf/þ+Ä7S)@)J�p””S'b¥³ƒÜ.(5ÌÆÑð$"l2_™YƒÁ¼ØˆÜ¤6ÛÈu?æn¯O¦ÀÝMH¸� ¼ûî÷>¸ûÿY™]L‚üÁ�AUhòlyVféà»ßýîÎn ì?äEG㬹³eá–š|Ô´Þ¶)%+ªÃè¦eµTss3v;�*„B!}˜O��šNX+ì�}¾µ 2U©ÚÄ9@kh'`â¾ÉðöÚl¿*êï tá@£Cš¤ªp]˜ÍÀfÝãî©vûý¿úÖ÷ê”Þà)wmšw˜·ßüÁwgo¾†[×�%™ùPM‚œ|¿ùåuF|' ç‘ߣ7€À ,œŽÆˆ.îtWwkƒÇú„Ô�išgîó¬°aL)5MÎLB6f*p!ÍE¤�H"‹Èàþ:Ù„B!„†M3$ Fݲòâ«î0ŸöŸ,õö{üeÏOæGãØ¯kÿŠ‰Ã‘ö}98ƈa´áèµÙòìßýæßþþ÷ÿ¤‘kIŸ÷C !„§Ï@%Æäp¨€‰›ÃÄëÄ^¦M®¾ù$|mç!¼¤<‹uT©+Ï.S0à0�@ „qJõ˜víáÖ^ßâÄ6Á•5åU~o3ˆ¬¿SŠÍš4¬ÖÐþP$øìöÝÿüÎ/~ž–÷æGÈð ‡õ}é×Ép~rüÍ7n~ï»xó�£Ùâ„T€9AË~�ß@šªÂŠúøÁÇ¿ê‡spwê¶ Z�pºyÉZ¬ï{³²î—ïÿêç¿÷æ¾s4ðšÁZPC {“R¢ÃÆ¢pw—$Y2’ôý 5 ã03¨s'Ð¥½>Ÿ!„Báùcí=~‘íDÓåeŽÖûrÚëݳþã"wOV«”°Mä˜ò¼� QÚY·\÷Ëæ×úÂ;Ÿžþüþò·W�~ð¼^!ì…ÀdSá£v… ]àâ�ÚÉõ“ ¿º AOWÄ9B/+š·µV�£˜‰‚F‡Š$#=×À†nzC¥½¾³–F“AÅ¡�³©µ—&SõF«û¤.vñ¿R|S� ¤ H‡1æNØÈÀO>½ý“ŸÝýåûvÿöÕÐH+¦e0`§ýÙÉzUúá¦yþæ7gÝA•Ï ÔHº›ÐAýÅ/:Œç2/Îm骚ޑઈhñœru—¹I:?ûùßýÞ[XÀZZíYôf¬R¢«™›¹9áf6*”m“POQ!E$Iý• ¯XaµB!„W a�ø¼fS Zʺ™ù§ÿv”³’V¤© ðö»<‘Úv5ô H‹ÞΔ`îîœþú�ãýîC !„çÆ�Ä’PÜèI<¹e'Ó6OÐáæ|ÅÖö&â!„—•;Mš ©/ͪä( '#]Ä2�NQÂh€ˆËûàq€ôF5 ¸Ð|=•:¨=§ ð)ÈOy iÇ+à ¯ñ�M})ƒ¨ØºŽ›Ôæ„åíû¿üÅó7Ýrõöµ£¬çRFÍmK™©±”›ÙG'÷OÞ/³ãã«W¯7yž²?ƒ< DHÑܰ¸}òÉæCÓpÜÎôXSþ롘î–%™«v³¶øxûÎÇ  X€ –MË–ý>†ÑT$éRÃ$ê>j)¦M“UU‹ Iq¨;Ò«u~†B!¼blÓ¢Ã6'´”ÔRáíAûɧŽº”³#”ÕÿÞ§lfPx~ŽÃc´Ê.h[Ü=ù߈-Ì!„—’’ykháo7E˳‹Ð€‹]¼ÌÂ6«@ák‰'1„ðrrZ»°²,K»óîo}ëïuKG!Ì<�â MkO 'ˆ"¾¿-ê‹lYÒàþøÑÿ|g–®›�]+ez‡›š1Ô‚W¯Ð~yãÅ^±š×©„ Ä Y8ïýíß}ôw?~£ë3é—àÚhºt‡BlÌŠk9�¨~ú‹_|6Œßû/ÿ«4Œš±çfVŽçw{ïêQÓ¯ÏÏÎï_}óøÞðÚ�VäSÃ˹9_Zâr±8X�ëþüp¾(§#``eê ¿Úã<Ð “)�¢¦îZÓP˜R1Á&¡¶·™ŽƒÑ'-„BáÕ$"EGˆ,—K3»råÚYùÕ8 L€R[˜‹/êG‹ÅªïI¨‚@Û �MÈC/)—¶µ&çVŸÝ9ëæ8]™Ì[·ÙT³ æ ôgWËá%qŽÂËÊúÒ“Ænœ]A~Ç-ÐnZ�ûæƒ;ž±¿¥[(€Ã´ ‡ªöý0®þ@AF§QäëF^;s �ê0hFK‰¾Vœ-íþiÛ÷³œ[×ìª4£CL\Ä�›V(™»µqÝ÷÷Ïpï~Ó-ضc]»ß+º^­Óáá¢Næ‹™ª®V+èbA›Nêº/)D?œ“9¥lfªÛ~6Å9\6§å~=εÛ#ŸÈÎ7¼J1¸B!„Wnu=p: >Œeqe.˜ßzí¿ø`\ÇØîs$RJL8;;;>jÀñü>ç ¶^Ú+¯Å¢^á¥äÄùë¢�€ æ‹Cdˆg¯…Ê/æøµRý,ú_>ç!¼¬Ä‘ÉFr#-0Z ²‰pÔå[R@Öì±ã@í¸‘g@k´DM_€mÝ*`3—xU8M ºˆƒ@2:§™RJ eÔO>=¿s7e&lÄAŒ¥¢5¼AË:µñÊð&ëÕpïîò£�ò›o§ÅLú5�ò ‰p½^Î?¾ûɵÃn>;ì×Ú·Åw;Y8X€ f3@1èRJ’­HÛÎáù�”UÜ7)!{œ :Ívâ�ž|»17¸¿"o!„BáàœŠOmÑáD’ì… ]±îí[ïf;BŸ[�ª’n„;ÌaVD4KZ�c›æëaÌÄA{trš²¿~ã]F�–ÂKŠ�Ë… Á^`>š+H›©½Ú+¨¿bây !¼¬„ÖÀS޵ß�C�¥PM|ÓðÛw¨C·ûÙ÷q ìáˆÁ0ê ª€·A{Ûùxå^œ�u�ÝK†äž Sçw=¹ýÙxrÚy�Ï›Y©¡,§88Öâcbƒ˜¶Âì>.Ïïúq²‘ZȘك¶mÝ]‹›¹[ó֛߂w]s|‘<´E€HM "H©z¸µoÜú¼ƒwðžv†;Ï:èÅG>B!„Â+ª&sÐ@#ФvÞôçfc{<óí[?˜7o`8tmÁ,„ 0·¢C)cÛæåÙªô¸v4kxÍú£›Gß}íêwàQº*„ðrMko—K»Úßy~º‚r�d›¶•Œ ÇSOeá%å´�>Ú%lÒ)DRMœ¨{ÿ�†X³í÷ìå#h2$lÔÓ:ê‡ÔH>ì•*WµUÂ&°ì–ܦjT£Š¡?[b(ó&Ó n¥qI–à©F;Œ5xh�Ž™ÞŠSÇåÉIrG)û>~’"¹ïËÑá Óæ;ßþ{‰ÇËsŸz�øÃ¡Š¦�Ì�¤±Ò¬—ìš«ï¼ýCØ6‡uð�§AÏž›�Wâ_ö#„B!¼"¶C¿i袣ÍÛ£ñÜ[¿Òáú¿ûO®´ßZÞMeèÊÈÚ¢CD@Œnìkt€(0ÌN>Õë‹ïüñ÷ÿ )7Ä"ÎBx ™Œk~&gÍÑ2­o°$g»–VÁ±®ùÐOð ä©KkøÚ"I0„ðr"�SC+ž6MžjCgó͆$ß|ë&åbjñàOÿn"²í…MŸ 3D$uÄiµî-Œp§êà+µ‰ÞhõÙ0°"+mÎ6– o›„²V/Ä( ( ÀáF«íWTKrda ‡5Ú¤:JÚïС’*�Žo,Ëú�[ß¹qí¿úìƒÙ•9lb±¸¨ž5ô �ÈedÛݺù­7n}6‡Í�Px Ðg°Å£^_攋0G!„Â+@¶Ã>’O;oÐÁ›ÜˆÏZv½óõ~ãæîŸ~D;Qc"$#%˜Å¡:Ÿ5^¸:U=k¿÷Gú‡¿÷/úûÝLÚçýCáéso¼Ù¶MCM�²8Ÿ–!­�s@àyÚë)矢x*C/+mÓ˜ÜMÎ�àWµe�6r6‰;-:.z@mš“?ý[†R“GFE±Æ ‘Ô],Ój†7hpùê¬(ͧ” !¸mKÑ´ tJ#,¥xBJIL’'$a½µ4äìý/dÛ$qWÌ÷ZL¨9‘ÆîíÁüúýÁ?>ÿËÏ˯¦ÞbÓ´)P…Ú”¬ˆ[~ãõo}÷Ý¿wåø œÍátÀˆšvÄò ‚ ɱM$šš�ìüÌÚºÃ/þ(p쳯{!„BxΜd³9lê, 1�«rÐÙ "³ùìÆ~ÿK·|ÿÎXº¥Wõ” ‚Lê8èáâpèõêâæßøGßÿö?¸Ò¼ýѰFù!„—Ë�·fW®æ„´�¼�v[©dãh¦©· ¸mÏùŠöxº"ξ 8‚#PsoàbÐÁ­¾Æy¤ý·e¨ÛÉëçlZ^C€äpÀ]ÖD_W„ézIZ`E¤–lªÃ„�îÙyZÝ×ëòtÔ>í*âôÿ)Za€S]ŠJqÖƒHãØ»�Ž‘T$AbbÄÝ¬åæøkÖÀ¾Ÿþ¦ié€"¦(c=5F`nxw£SÊ«YT��ü1Y-8–ÑÉØÊФteÇ$"îp:Ý2ºe78�³öPÈ ,MF"ºtiû]”—¦éÊrMiÎOVœ1ÏŽÿà{ÿÙÇw~õ·?=7ë�zçŽÓãt`@ƒnÞ\ë‡zå›×øÎë:K·Ëâwà ²ïúY.S3´‡n§#ÙߥB!„çD\è'”p�èHnFܧ×aU”²|…ÐÌ!Sgr¶³öì´?:˜Ý?_¦.yßþþ·ÿìðÚÑý?_s}ìåÓb§¢ž²¨:GEqÊ5[•o~ïþÃ?úoó÷—çÌr@g¬ë}: €ÑlÓH&É(†Æ„n k�I£î$ãª|N „p™º¾�•VNaL]‡T�uzï$àpñZ_"¼¼Œ¶.+—ä2+ªLÃ`K&É2+µ’Çô­Ñœã©Š8Gû4 2è=-Á;„Þ@Š¥S‡²ùÜ|îè²×÷:™) PAAÝ” àž�ô†{ wH¯QåqHÃã27½´&·Ö¬­qŽm¨A¶ý¿@hrÑä`³7_˜ ¤aÈ«œ­$+DA§)Ã9 �žàõ è€A BaÚÙ�Nì=´P�\§OsÒÜÀ &½I�0tît8hŽìø+4ú7u˜>ÅjðÍ×ZŽ¿ÿîíóÓ�Þûõk©“â°Áæ:&3)–µæÍ$­»zóyߥ½qóõßû¡Ÿ�åÅÁz¯Ï¥Ë8 §h’ZÇhãb�ÜÂKŒ�âÌ Û4<\�ë<“U¹ßÌøñÉ�þ0ýñógßþðÓ÷~ùþßþ惟ŸÜùT}�’´™óÙáÛ7ßýýüÇ·n¾›ySׇƒ²ë:èð¼â‹‹>å[� c‚QèìŒÙ8/è `°„"6 J2M%[Ô{nŒrZpõ‡rïÊÍ�ûåìð`|ã�ÓµµY”Z#U QÀ)ðm¢x99d $SýÌgpº9Pœ$@j9k>pÄùðDœ#„}šÖ% ,uáÞÔ¶É€yêÍ—º¨í¨ýöy8Ô¡€Ô[úE馌‘Rö®˜$ɦcòúp`¨+ö pC2xªk£ûŒȶ‹P¦§—rñ4×™,™eC² %�ô‹ÆÔjÜvÛ[Ž$|½ZZBC¤œ@ƒæ0Ü}‘ÎÜïª]éŽ^WŽÏN—h»½¿L—‡€'±™•ëÉ›úþ»[¿úîßýâ/>¼ý“““GMÝ‚óëúýæõwß~ëûo¿õƒ›×Þ]ÌÞL¸†ÅbuîÀÔ)峋uù&¼ñånC!„ð²©ëªtqŠÒLh›|Žº ¹R‚AÝáë2¯‚é·|1«b­µ»ù{oà }v|ðZ{ë�׎~øïÞY÷÷‹�QŠˆ´Íl>;^Ìod»êeîÚ²›¿ZÝŸ�ÉÍ#Œ2Š%É�¬6„‡ÁŒ0yÅæ�/$£Ì�¯^ïŽßyGDÚYÇ”×±&“©…ÔØ°Ñ0Õ /-‡(Ž›/ÈnÓ#D„c?"ÎÂ3V ñl*ñm±E�žÁ[=�S= A‡×JPŠÑÐQi™Ò 3$9ĺŠñ5°º&kÀI.{Ì“%ÂÁ”ÿPŸ>�²¡UÌGΊ,ÌŠ0Jë\*þH¨©ö�WÕâh�¯½ù�³ÏNʽ3]«ÈÑ|.Å{UK�h[4�«®$õYGÇWßzWŽ!ì­4ÜgœƒŽ�À[˜À[ ³•~ãÆá7þ´ðüäü“Oîüö|y7¹ó�Þ¼º¸q|t+ËÑØÏÎîl�D’Ì6wjÓ2f.!„BxVÄ ˆ¸ –±rqw(/&/NX OÂC\îÜ>i;9œ]9Z½®¶¢˜ˆ�ƒ�}Ö�ôœÑ‚Ù=Ρßͦ\j¯•åv׬nb¤ƒ.b±¾÷<9apiRƒäd�—2Œ¥Ó&íw¿]a+^Cا©¿lJF=d»¦€#0Ê^—å/*>΋&:Ìá@­RC�%AsI‚dÈ@6$·£ÃÊ”U‡9$×JVØ_o 0ƒÉNïðMœC’#ÛíȆdä¸||ªù{ñºÌæ‹Ó³å¢è­oû°øÝ¿úÑG«»W»Že°b,æäPwÂ,ûÐÍ>{=¼þÖïýÞÕwßÝ—çëæ`áû=!Ì.úœ <Ñ“æóõjí2kfiÞúÁÑ÷¯ÍÏIŸ·ì¤Ø0ŽÖ¥!f]» Ïà­7Ë}ê!„Bx&¦Z¯uÛiÝÃ4mAeÝÎÏM¹•Ú¾+„IZ8ÊÐ3L‰Ú<;1-´"Â&§,’Ýhf‘Ïñ6{�Ø)-»á¼5Ò‘,éÅVÀð|°ÉP+¥ e4wÉmÓ6ó¡Œö`•¿ø=…°'çá™ðÝ ßúþ¶ÍY3 €=ÐlŸ¡þ:2 î Ãµpڼ皀‚DÏ´ ˆ˜ˆIZE£hˆV¼5K@šŠ@Y‚B˜R„{Šq@k ôi¼gSzÉNYŸºÝlø—OMÖÁT±¨�im;;ë{:gW¯¼óÎù½³»ý°>;?öÔ`Ö-òl60ôëe)ƒðÔÊxpxü�7�Þy›W®,‹­h³î`\�ûíËWs/ëRêÆA‡q”©ü›?áˆY`!„öMêÆpx­ý*èBb'muÛ9,vc„ÈññõR†R³$ÒJ:Ü‹—q6mÓžUÕÔ«½_̦2GÓ…I¹.º‹9 b0Ïâ‘"óü°û6å4kç슛™9Pì� z´5 a�"ÎÂþù´ªþaSˆf' O…¬€0"ím¶à›R€¬}6©õ¿蛲ZBiÀÆ0ÕäM€Zõ–h�Z ´@ˆ!_tå(Û¤‘§~[{ˆ×CÔ©éîÀ˜NNݽˆ"(»$.Cm½MÀmg�‹œŸ¯RnIï Ýõë·þþÏ®Ÿ¼÷k»swu¶<ØÚ‰æ³™.æÇW^ÿæÛ×¾õ¯^ëAë@ÎÖã³Éöö6Š¸Øˆ–Í|Ñä Œ#V«õ½Óóホ©CJÙ̆¾”²43’"µ¶=Rà.ÎèB!ìUÝq‚Ý­!R÷�â0^¤Ý>ôm!X¯†¢ƒ™‰¤$3˜«j)%¥N(D6…YqgJ)¥Ætüú?ô%ç›ÊnL bN÷M¬1™ÀÄbÏßóㄹõVêÖ½bffîîîmû@øu„°?çaŸ.*ðLí¯§|ŽiN ›®Ô#dåXFÙßЄJnK=ÕŠSSî¹CÌU}ÌÔšÁÞ8€“˜@­ ÕÑ)fÀ h  ,A Yɲ·gSPº$±$pʸqˆA”CBŸ1dk¬€. ã¶š€6kÛ\ˆ3*»¶}ãÖñÁâèµ×OòóþöÝåÙiq31Í2¿revýÚëßùV¾ùŽŽŠùRup1fÓ‘½6øº8×hu‡#=ƒ£*Üu 4äœæ3ŸwMžL©jj*ƒƒEÛåóóÓïxûN[&C!„°_.0¡º],¡Ö:åY µ‰® Bán%K’Ü ³ˆ±Üx)Å ww‡‰@!¢Òðsnb�€ì\k*®i€ ÎÆ¨èÇîežµùÑa)¥”¢ª$§”’ˆ”òð"I¼r†°'çaÏ.Ztl³76orž/¾"KàÎ)~Jîé@ 0ÇfŸ8ÈIÌN7”6àn°Nï¯øQ›{%”Û<�)Pâ­õ¡°fÓ+Càîm˹fhžJsÚM¶-ZÏâ"Nq‰Mï/£m’²åèèhկץ´MºWF]õ3I×Þyûøµ×q~ö³Œ=X,�órÝ÷ggèf#Ù�E²�ggÏæØ�š�!˜f–3%Á¬˜)¨t3ïºîziVRbÓ¶î¶îÏNÏúÙ¼vúúL¯"B!„Bاá2*Fs5)lJŸæ2¾3©µkcÁ.l‘žR&ÅÔ†a$I“Rn›Ö¡f¥î½sŒªë±XN]¤,4©9ULÌ9šŒšFˆi*6U2ˆ�çìôüÌ€D¦œRJî^TušK¯!<#q±…ð pZ¬ôº�ÜÍ 6õi†~˜Íþüßþëÿí/þÜ÷\Os³dš›ë!‰O)&ö&=¤×¼ª# >3@ë^Á@é>ú3à>à‚Ü¢(Z$ kƒÒìëè·3,b$úM#вeoMöYÁÂp hG7Û$„ŸÀ�”2@ÀT·YPǘ¤"IàÑÍþs9aS�#„ntæ,ÞèÉxï`6[®–í‹¡¡‹Pãr|~œ�œI°n,URrÞ–ߪŸGõªžºˆs„ðllªjîÎÙ÷¸¿Æ*° cÀQS9šm¤S˜ s¼Ò5j§ÁX>!„Â3eR¸Ð7ß½–xåìlžçó+�â¤kd,È›ÁIÌl·bÄ€;Lx±Ô¾iH Ù„4 0¸oZÙ{Ò~ Ûy�À�ų+rë�k‹öæj]Дö8±sOºçòáwÛ†7äq_ !ì[Ä9BØŸí ow Öóy X kH‹Ë~²!ÜF]ÜmеlJãØb-Ã+^׋§ýçJAonÝúÑù)χVÒz=ަskoŸ�æ,Æ}m�×ÖgÌÕ 4Q9†¬ƒ¿ÿËÓÕÇ€‚�8Ä,²9.—�¨¿3»Ú1!¡2}‡SÊ#Q€Z©êá¯ÀxÑ�æYªÑMq$@èÛV±ãè(ÀàÁ, y0±� Z$s„Ba¯œÚæw~øzf·^uíócœ­‡³Ãr‘§îUWÂÚ$v\´¯«êùc±§çË ¶~i`1±ùÕƒ·¿÷úñÁÕQ1×±f}Ø)#ž5:„�ùbáYŠ8G{UWdÓ&¥›ŒÝíª«€*è�‚m¿}Üîì¿ÚmÔa^«]²âGrÀ¬Ž@“Cêò+3ºÙ½þ ÒtÝ¢÷”~q œ—Üîñ¹4…ÎH)*z6t`gYÐXÓœbæýp«/o­yý÷αØ]viÐQûç`ÛL„ê¹*>Åê’ ­� “Ú c“·±Ù[Xk×r'�c“A±×q?/ RmêÂM×øæG“ð �,PÅ8ÂxÂÎ¥1+Å‘܃¿Í툱JØJ®à>š´±ùc]Ž�ÕÞ/²½²ŒÓήê°uYJ{pVÌ\Ü‹–sË£$¯¹âáyáf‘Åâ•1„ç$â!ì•ý޽*Û$@Úëºü6ˆR;xÄhtÕ�4U šþŠºÖ·ê$G6@EÀDkg6+½’0(l�ì÷tøÂ–Ò)’"ˆÃlm e9Œk�ùêYc÷³�µ°ãNÏ-v˜]"âÀiî¨ýÆf@öi»`�Ò9@"Qt“Æ�M„c[´jÛœpŸš|Èž³†e“«Q/âMÙ:ã”Âå„ùt Ob-çðÍý؃ÍÉ#=„B{äToÆA–Š3æÅh=RßÍ3¨¾‡7c’Ø6&˜R´w'µ»õc·§�4:¢uö—FwlŠN«hʳ~½4ϹAÁÀT˜hÅS$�?'ÛM«µ€Õn«8ÅCxf"ÎÂ^=¸¹Ž€×"›µN¿Áè-K¡Ï¡]zàŸ<]6õ!÷f“iŽ̨`ÁÔÛ¬1QÈ*y¨qSw«r� FM@¶±ô¥�/Rž ź. ûm‰QWŠ7;öëÂ1 D^ÌØ `DÏrîvfМ”Ó¯Kd»O ›êj„ˆ×:j—Ý :¬Î”6媦»Ù~ƒF<ÛÍ4„ËN†�.0ƒÕF# í\{è$5l®.xìv !\.NÐw y¨ƒ€Xá…!¤¸{ÊÖ6>Œ 7a»ZŸæÔmwhÉ4^ÙîíaKìb?»Õ<æ:È7ˆL~1°îoŠîÚÎbüâBóÂÔ8£¤’SÊ�”Áµø8ú<žÐ@}¥ôâ„ð§]žÌŽn.W¥þí~Xòžf®/p‡B ´dÒ©AoÅÒÁñkGøô¬tQöòòpBaºù�Éf‡`]3ÂDðhÈb§¦“>< €ƒž.¾¸/¶3­˜¶­Õ��@’ÇÔž’MãýÜ;¬Ç|òˆ°]ár¨u²{»]ù¢ˆO�ímx›@¬„ð" ¥„c8Á¢å4dSz4¼«mL¦ÝÊŒ¸ˆv„Ω¤æâSwJØEf³í|Žxñÿb^[ý]þôö¯ 0ÒP”(0Ï]{èð¼‹Õùœ‡)—Ót·Ülçêòøý›_ûVÙFÀŠ—1©²aQ$îܾí‡-®BVgwOÇ«·šÔÆ(ïrÙòÁÅýÍÿIë�=ãSà1ÁŒÍÑ/ýOžû£!„§cw§·ÕPåâspåuQ !|B«��jB–ÙäEáÐX¡�·»Ÿýq·†Xü}2;ךO‹x›-µR/’ÇâÞóguÏ]¼†ðŒã išÌé�p>Ÿ_ͯŽˆn?·62¨q Pã9M² Ëðó“öý_Ü›]I. ­M94ûÐØhº.¼ã­+YR;a¹êv ä~°åàÜcœCŒ ±’ŠÉ13<ýàßüÉÙýú±À� ³2vŠ9X<ÖNB!„çàá탥§oñmu“X- !„B!|-çaψÍäþbÉ}G¸çœ»Ô‰hß÷'''ç>ñ˜8Ø©Yý”o}* ѶÉçèÐ’H-+Ñš„áÚñ·_/x_Å6¹Å%»v:²äþà÷ÿû?ýão3`€î¢P×¾žÈ*@ øðÿ·uûÞÌ< ¶M—PÆáyÿîC!„ð Ú¦�ÑN¾GìJ!„B!|=çá9˜Íf†¡¬u`C2uÝü€ÇеùÚwÿùÔÞpc Èfå BýàÅ0›Í‡u*£Xçèb”l¥óÒ”þÓ¿ûÉÕ?ýã[À`$ Òž{%×=Ÿ5ÈQ<Я8¿o³Æ¼uŒ…X�ëy,œ„BÏ^-Ö·ÛšèâsÃc ²G�¾B!„Â×qŽž‰»‹ÜÍLDrNe’Óžr9.BB`m^¿è¸@º�M_I Ä)¾y ¥S¹Ñ¤7�kÀ1�€ȵ]²û”²‡[à℺Ùú™€°°:ë1oÇeYzÑè²/Ÿ÷ï=„B“�PÇç74 !„B!„¯ â!<›É<tøT·ªiš.u)y_|½z¬ç艼·(‡ £Sݪ€ùJ@ƒ­HcèÁžRœt$‡(’ÎÚâÌçÄ!ÐÁgæè²:@{tí¦N—=õÛ€æ@‚æ R€­—yÆ¢[�¾jS¿ÀÐæf æ„BáÙ™vV<�T¹ íF8|÷ÛC!„Bá+‹8GφíNìE¤»—ѨEUÛ¶íÐ…@l·Djîˆ ($h„À8–^²ŒZVf\Œ4&…ŒÌJq#VçKfà)ÕM™täÍNL7p/·>åwØ&Ï„$`x–~Ð¥›Öt…8íÇ9qŽBáAŽB!„ÂSqŽöÍ*Zµ!î ""b ¯�ŒûëC.`¼È“Àf¥Öæì`A!¬i“ô ˆ{khŠ4Û!IÇ”ºÙ8à€º§Z Šƒ$xê· (Üaµ Èny (Y‘Õ�¤3MZ0oަGB!„gê±e©¬iÛZÝ� ï×!„B!„¯%â!<3�­F½«Nò¹çÛ¼é^�g`@8!´,’áži ’ I‘•R„Ås1aí�¡’I¶Ÿ€©™ÇS¿uÀ7O ¬75S  �ô”L²¦¶ k—‡ªf„Bá9‘Õª'™RJ©É™Ü€™}Ýû!„B!¼Ú"ÎÂ^Ù&sâ‹WÛ @ACtû;‡Ô~á5÷µk8™ƒp �è`sZ'ž“s¤Ä(J)¤2+rM ² ɘMÚ"]áb”ËQRÄ8B!„gŽuxñ@V¥ nJ­¸AëWܰÔäßµ$„B!„¾HÄ9BxÆšÆïV` yW¥oÜnÒD„˜ñÏÉ‘ ’ 0«aƒÆ‹{¢×?ŠàKt¾BL7n°‡P .É%›7E:EW«\íýÙ !„—!óù�©×¢Uî$)IHWŒÏûØB!„B—[Ä9BxfYrwnºonú[LÉû2ý´mÏŽÏùûÍŒn žÜdê2b  L H@Ì·áûœ»}J¼æq`JCqÛ>T\ÅŒFGrk ÉÌ"ÎB!<6 +v6%œ�ž“I$‹$"bê Bäsš™…B!„—qŽögS´ê‹§îϲWöÝ: �‹¯°ÐÝÑ€  ‚B)®„ ”Pq#,¹Õ GÜ� çƒ?bŸÏi¦¦0ˆ ÀŒÉ†¤cRºèæ†Bá{lr�³mg)5I‘°Œ>Ž£ZÉ{¬ÙB!„Bx%Dœ#„„°Ù|þÔo j]i=pì(�X"�“+Á@P0 7É$›e RM¦¨q1‡ÙÞâެ5ŒB¤ÍO)ÀXËÆÖMѦ¬ö¹ô FqÒv"0!„BxFd7¿sóyÎ�ªýh:""MnÛ.�vú¼�7„B!„p¹Eœ#¼\\Tà E7¨�’¨í± @B¹(Eq€‡=õ[€£öÚt¯«î5 Í!qˆiÚ¹�[ßÙb¹é¤Áí73�ætw:aRs8ê“Hè¶¼–ï·'ǃŒ›^&¾9hÛýážáÙéJŒ –¡ÁÓ³9¸Bá© #9œÐš.éBÔ·à‹Íâ¥!àÉ 4ƒÔà>â7ê[ý+‡0ñM«ðýpª�â’´£5´V\àøÛ¿þùj=œ�-ÇAgíìúõ›¯Ý|óøštW<­�ªR\ÔY6#¡ËN'3D»ò§®¶=£Ë�Òy3Ç*g8Z5¸Â‘ &`«ÿ}ÞÇB!„£"Î^*m;[­WC‡~F˜¡ïÑ6€‚™Së%  pèê öÔo …,WhçÇVÚ¥ªRS– ŽÄªS”R˜MS ;Lóù§먅!òε¾Ô`�žÁlÈÊäBÅ¥�dÍbY%÷)¯³¬¦DŽ 1¤v#ß›C"0 4È3à`�ƒ¾[æY3]\0æUË«û<œBáéKŽ®À‰óFFA2Ɇl°|Ð�žž&ãáÁ5xóééê$cv´8dÖg+wiÛ¦k“:û‘ƒ5°2¬%gæ¼RX“ÙÎÇ~5#’ï+`à4d;;9ýðÛºlì”͈ŸÿÝêãîxé ]ÆQÅóɯө߷Ôÿþÿáõkߜ͎°â86gš ’v]7¬T 4¡§º¬]Æ"ÚñÔ$–ëVš_Žz|t|¶î›Å!LCÑ´&Šââ%” ±}—) !„Bá‰Eœ#¼<Ä…ƒ7žÐ4ó”°îÁ o‘Zh÷Mí¦híN‘˜°Y@º·pƒ)ÜPÃØ »¶Mìͧý˜^³:¦8}ïAAíháµz¶Ž´éµA€ÂÓfB )H2ÐÅ)FEl7ÎÁ‹¤b‘›vqºS=*�' ZC¶”µMVêß:5v}†B¸Œ0‡qzïG2íl¹lãZsï^ÓÏÞº*õ˜�ƒÌ;43±Ae¯I~íhîg§-SJ M*êk·¢CÝ’¿×ãÏ9âE8ðì#œ|€;ï—o•R¦DRz¦'1ÑT~ý7'ëõâÚ7s{£Yœct½�làØôþªÏ @{V‰¤¯'0;�ù|½8ìÛ|n¶h2Ì’˜¹ ,™Ä(.uƒ«B!„ð"Š8Gxyˆ¡ìhÀ@+Ë%þòDZ8„´hZ€o",pÀÚ=¶C²óåÙlq”–ýòÓÛGdõZ†‚b›�É=m×ñC!„𪪫¦¢U°äHº(s¡¬@–ÃôéZûÉíŸ�ýIé—·?j…‡Ç×߸ùÚëÇ׎Ú–ãp¾|Mr–ÔŸ%/ãJËЦ¶Çñ]t°ƒöªh¾ýÙøáû§÷?û\?: ›OmÃv°|üÁí’Wšo´‹Ã£6K;X¢‘;M¶œ8Ø#ž%1ËGß÷ÏÞy+¿ñÖýúü¯Ý<»};5�r*SE y!„BáEqŽðòGöc3š.—Ã_ýåg«µæN‘×ë5€Úv4@�VëB¤½Å9Š˜_]Üz™-ŽÙt·OfèçäPœâ.Ûî‹Y{!„ðŠ3 T bu7)”¡åi–Uη×ãß|ôÁŸ¿÷Þ�û³¡kŽ»nuÿtX¿wmvð½[oüÁ›oÿÉÍ×Þ½qeu¾ž¹ÚpÞ8R›-©v]öa¯¡Y��¯_y}¼�ÞûäÓ× ¿ye±° !l¼à” êrÐ\ÏËgœp^šã9h¶Â´S!Ów)Æ@îoŸÊ+¦ÎÇÂ&©ÌŽ1Íë&I¿:-ãÁbn§ÔTÖßÙþó�B!„Bø "Î^F”D4 YX—'\¯ÛÔéJÓЧžÛN¨Ð�’ÛÖ긧ãg§w­ŒÃº§t ÕYJ‚D&eRR)uš˜ÜÄKz°áE!„^M*¶Éç§Ö쓜µí�Vþú£ÿßý·?ùìöýÃÅgG³Óq i::jæþÁj|ïýßþì³ûw¾ýíÕÛßøÃ£y“á÷–6öóÌ™˜YÉ(Ø_œƒž;f üä7gw>:“rØ6‡-“öÐM%®MŒc:†+óëëñüô³OÓÂŽoÍçm–9\Ý�.SKŽ)“#JV=eJI7®ÃzµZ�C¯æ>›u‹ÙQ×ö}@˜v >…8<;B!„ &âáåáD:݉nÖ¸�‡Y6ÚjUãµO 9Kñ½•nâú¬Yät×EJ�7@/©1ˆRR«7žÜ,J‡B¯8'l»Ž\‡."Yæf9ïþâW¿úWû·wûöIÛõ‡§G?]—ö ÌŽŽŒýéòW§çÿú—ï½÷«_þ÷ÿâŸ7³£ƒ#»_Hfˆ˜A÷\÷Éye~åü6~ýó�K/W7Ê}sM]·š»*Û�­�éü^¿>oIÓŽãê¢JY¹€§çý[zy¨à··ïH+9gËYr*¥|zrêf‹nF •ê//‚!„BáÅqŽðòpbLXÁ sË:QD‹õãA“á¨�Ç‹`ˆ39|_³�ËÓEÓ*ZSÍl`jTNqˆqÚ•H‡ÄƸB!L£‚ú‰âDôINÚü·wïÿ/¿øå¸}×®¿Ö\½ñÙú «W¯â�ë8éqÿüÔÉÃÁe=öËÿ×Ï~ÖýàûߟÍÚe§ž…鲿´q±¥ÇùɈ¡›-f§EQ tˆA“ðÁo=šYÓúḼ{v¸ºÖ”²"Á·û? 0£; ¦Q·ê)q98¾b‰®¶êûFØ4-™ݬ_­…PÛª8A7Ä€5„B!¼�"Î^".t13:Ú6Se–3àFŒ ¨ “ÀDL̉²ÏÃÙ­�ÒÜ¥W§ª£«ª;Ä(‡ÂèˆbÇ!„B�L –J3¢VYÎÚô?ÿ§½?–ÓƒÃ3–=ò M‹Þ°<‡'Ì Å–X Ìžgÿê—?þÞ7ß¼uãÆQjFHk€6Ü{2„œœŒ‹¦éÒü´/š1oRN°!” oKrM·ÌZ?¼ßß;;Y ËÃÃér3Ž}Mxp3HŒ—ž²a=J×d6âcbvcß� ©†”|ê ‘zB!„^Tç/ʲšÊz¤ª–ZàZ6µ„ �   S„}p Ôz”^qÐ,@OÅŒŽ)ÊQk*9B!„W�^tÖuçÃ9»$m£L}›Þ?;ù¿}ÿãþèØeO0�£ÁêG Bä\蟔¡=>üüõüƒù:<º:œ­hÒvYà~wå4w~å˳ÕÑáͱW]¥›·ðáèÓ7ìþpqdÁò\ðàðàäî'oçìçã9A-0º;LŠLާI\: Àuζv‹;Ìsh}Î¥O«›/†B!„ð‚‰8Gx©d SŠÁ�R¡Q›œ’Àº)²”¢„øçi%2ÉšÙE ÔœRFݽè›i£KT­ !„BÕHc¦8Ù�ë±éN qû“ó&Ÿ6Í�[ A:|4À“�†"2æŒÈ4IŸý`]>9®› ’Zñ ì7£µÞ³©wÏMT—Ë:üv<ˆƒ¦Aú0ôÝõn,ŠqtW>¦¼–ì܆§€@«ØÆžv{oÔÑ©o>7ÜüÖB!„BxÁDœ#¼<Xê¸ÒaíÝÛ+‡½¹�L ÍÐé„ ”S2G6Ù_¨ƒ^’/™°BÛ5í½å0GµaL$ŒS­* N)‰Y{!„ðªsIÒŒ:¦,žd(d^Ü~óÉG}Ê}H‚‹8[uÐ’kƘ 4Œ’OæIV"·ûåíóeßPZÓqtøÞ[,$´ó$-ÆÕŠÙ]Êr�š€¨i¬â1u#OpÀEûrvëÆ÷±èšYQ—Ýk‹µéÉyÞ¿�—Ù@÷mTÃĦOßä=Û&ìa„ B!„Bá…qŽð¡u� !»æÆþ!ºÎSc"^WFó©•"ÍØcJGAY"ž0`õ£Ÿ§“{èûÅb^Ü’aâf¤R”TÍC!„W�’£9“4)�ÎÜæÖÒÙéÒ§€²Ù¼aâ*ˆ 9Í%Y²Ú¾›Hmcf:ŒÌž’ xA¡{æÇF3·ƒ«råúüþ¯WŠ>ÏDmƒagÍm“�‘¡Å]zG¹ùÚ•f.%Ìv«$Éä`4!šjuWÙtà!nÆÏ­ìŽB!„ðbŠ8GxyÐS“�+iíp�?ùC\¿Áf–$ƒ8„uƒšÁÍäç?e /pN×üðvvªZè.™Bà`¡(D ûî B!„™ Jï$%É!j­Kk–ôšáNS)À`Ô‘–\:Àê† ›B �z«Ö©5j™E0˜ŒHÌØçr5}mgW�ޝ½~tï£OVå¬ëŽ9 Lk ƒÀa‚Ë”úÅ¢=¾¶hfeÐѼ€}“öA©a”çý+z© b¾9ŒS‡]Ä9¦¨wkB!„BxÁDœ#¼T|(ºVEû¦E;G;Cî�ZES«#@@§8G–=æs¸A§â@w·(ʘƒTÅ æ5¥#”¢`ó¼ŸÀB!<_é“(Ç:Kª¾ÄýÚü°½w7ùÔ&bj�Å2`0GªKÓ.0ƒ!¯Æ…áPdæ…£#óà9™JÚÛøÇiƒÆã«¯]?÷;ƒÙè­!0£F‡ ÑáÄh¦X-æéÆ[×ScÆ•ˆ‹ìæÝNëìêxjœPšÖ˜ ¨MQ~†wO—(ZB!„^@ç/�l¸Ñt‡ÍA“óËàC‚´%5ã´c4žÅê¶BSF¡ˆ4– ªíbqxÜÚ}™w63üZ ™0�R!„Â+O‰ʶÑaÙ¨Ï$ÙXæ©ùÖk·šÛw“atƒ’™cAVä“•åvL¡Á0ÌÕotó×óc.+OyôäмÏ�ù&�-Ëòê�Å·Þ}ë3[¯?ͼÉ�»aJ«­|óŸ’g¸þÚÑ[ßm•+ñÁlhšÖÕ6ßÌi熩cG„:ž§)ͧߋc§�\mbQ�B!„p)Dœ#¼Dhg'§³2´Íkº† ¤©M/¶F�¤7¨†½Ž.É€Þ ŠsíûÞ ¸õhLÃ$Â!„B �6¶¨‰s–gƒsÞvßzíÖá_ýÕñ0¬s3­=‹@2�a –Á<$\[�¹ÑuWŽ›u¯ ºf§ªËžG]›Çåòè`ñæ;Ýúîpzホœ4e=n¿ÇiôœP4�Ãì>«ƒ7¯|wï�ôIMÓ Z6ñj߈o<}NëÆŠOM슄íF;ö·Iè%à„±$ QIÞŒHE0&ŒbH£Q�SÑ\�Ñ7Ÿ†pá"¾(Ž©ÊßæÖj3�ÍV¹ú�ŸŒŒKÀ£AñíÓR/¿í“7]�S¡ÐM\À)ô{ñ$oÞ†¶ágò(6•÷m!¼Ò"ÎñŠr÷z;Ž£™¥”DÄÌÜ_ ¥vj jwwÇæÐܰ~Ñýâ«®p›“CjеN4ÀAB �À7-¾ëvµÚƒ{˜@ Á`z”d8½}ÑžjI�d.$÷ÆÆŒ²Ï°ËËŒõPUÕ͹�êdþbÛ#õí¹^Ïðz„ð…ÈÇÌb-êׇð"©oIÛ«•äîæa¦MVƹHRô¦…Ù¤¼q|üÞzƒËóåýÛg³Ž‘:Èžq6ÐèYÐ9PPÎa}Çâç§ÿÙÿñ¿d‹;çCÓusOÍêlÖ6£Om>ö�ŽLÉ™ëa™ºÙ;xttsþÛ÷oúá¯SÓŠ7 YÐ’X)ÙKsÿµ?‘+ß8:ºé÷ûå˜û¾/M»×â–áâp@­w^“9âÝñ©qŠóqãaÖsd�?ðOö|DÓ$ÀëȨ~î?gÑv÷-ÏÝÍ|;Ó™æ¸i}ÁÏ5³‡Þ=ëäˆ|‚Õb‡y£ÉåpÌES>8þxiëy:ãÉÑêÙYßdÐ}\®ÇíùêLØE¨#l�ØD/’ƒN€R[‘ª°î�«'krû¼ÐõÅãÁ¸È¥¶{=Šˆˆà‹Æ½Fh�LL‘#Â@'Œp@ë3I8át€4ÒEœÉ)Æä¬�±8度88 .Ž´ÿÀ òKÝÆzBظx ôÍšÚæ½uú†�úîç;êH›+îI—VHîz뽕Ržðýã0,¥”RD¥´mý¤Þ!Éúö-"eZB —Éî‰@UsþZ¡Šˆs¼¢HÊÆîkÖ½îìÿ(A°þ—›(Häôr¹º°$S1©}/D�7šÈt¬l"ukÆÞñæ‡ pKPB“;P{oÒ!& ‰.°˜â|5ˆÈÅÙ°Ï_ë>lÏgìÜŠ݉KõHÂs²ˆlºÅ^®k „—]½HëšiJi»"óØK5�›8§@@1’�ù?úöw>ú«¿úͽ{o¾UºîöùëÝá¢;êÏÏõüÅ0'3®y­Ç?ÿîïÿðê!�ÌâlYœDÚßÛ ieXÑéÉs—ç‹6-rwíõ7¾{ó×?ÿ°_ë³ó±/]3»zõê�kíÍ×ÛoÝk®�>[Ã=k"s}ºjGŽúNwŽÿžNûóÏ逸ñ×Ù@ý¯»¹;7C¾” I�Òv¸ù‡Ûa!6Óˆíƒù¢‡Ô4ÍCSë”Ò…$ÇÄ•ª ÑÔ¡+�´Xd™‹¯úå�Ë�¤ äœo(qÖ65!€; Àè&N1w�p�&î$ £�íâ�„›|¬zB¥íš÷ÎéÙOµíû¦ª’Üîrûœ¡/Y£D¬% "9  ‹‰ÕçÊPß§ '=ÁEñ”€ä)9¯O' 0£Ée Díõæ7î/¼å¾&\*ÛÕ4`zWÝ,­ù´6­ ¦”œšÝ>ðOvþsÙOµº²9= � çs–ˆâ¢>4¸4S^K Sù¸ÍXº¦uøî—Ð '�ÉÖ"Š$çžŸÔšÑø¥¿÷Òÿ†ÃSóeò9êJ ÍT]T·Ëƒ»!ŠÏ¯~¾‡²@¶ Ù¥”':þ£©YËwlßñ·k˜S.fšQäs\"Û÷ZšåiÝmÄ9^Q|ÄöëÏûÐv�ò ò9¦-_—ÄÅ¢öE=­ðµøÃ.SÝžGó9D„f›- !üõÕoðØ½ !¼ ¶›æðÈÕú�äÈ6uÓº°"úÌ�üƒ7Þ’‘8ÿ뿼s{9 é`Öë�¯Ì�ç8=ÏÏÏûwg‡ÿâ�wÿÙëßüãfñÚ)ÒÉÚkgÞ‹�™©idô=–.!Snjj½®×e¤6 MjšÜµYdŽ”�ÍÔ­œ•2®G.XJ©3œíúmp(¼r>'Ÿ#¥ÄäÛ3¸ªÌÀ‡R|¿|>ÇvEf÷Ü«§â“;=5X+:K9¦ÿ~;¿{íõu'G”oõ\˜ Ü fæzèÏûI/3]¦:Ì!.»×]ÙRKP°Éáp¯å�>XŸê%:¿¶×vÎyûNñõåèÍCu½ê÷ÕjT$']Òfæh›�Ûû2Òé΄ZðŠi*ƒØžK�Õ{ÿòý9^¢_vøš>?ŸC$¹Àvvᘡ†7v·Øå|ŽÕØþÃú6ú¤u k)oø›„v Um ïOq‚ù—I=1vNBPK�}�»�8Ç+j÷å`ûr†m]ì ëV½Xÿ…¶Uƒ·ûøÍö»µòåæ�‹s\"�­[µ“zÂÙ&ìïîn{ÑòóBxÅÕíf»_©oý)=¦^�8:C2#\œâ̪óaì�þì�7ß¹zí/>øí¿ûõ/Þ_�_?èF”“³®ÖoÍÿø;ïþÃ×ßþG׿ñƒº�õp,MSè#¬dzfVä½mprtB“@èBiœBIÞ÷§f¦: ¨‰HsR²¢^d¬×ê^9çK´e!¶Ô ]RçSN\”@ôM°È@P\HÖfP.^ã۾ʚC#N8—�ÊÂF(¹ï·*ÛÝšÿ…—ü·ž®/ŠsˆÑj4"¥$)e”ìù±;¡¿Zݪ‡þXGÂOV’ˆ0·º8""L)IÊ9§”Ó–à"ZCJ\—Ë£u«¾þ"FÄ9^QÃ0 ÃPWÇjj6€­È‰sJÑt7ÙlcM %^J)/&æÅñDIpÏ—ˆ`çýc {Dœã«òG’"EžÂëã3S J)¤¹j�K‘¢îp�ÖôáwÚ¦o×Lë¢Ì%zI áU°»m»íñש¡!P Å­H­·.É„ëÒµó£yw|evuñÝï}ãÖûç'Ÿ�Ëï’¯Ý<8þÎõ×¾}xõ–¥kç}ùh\ôŽbHŽ,½ kjÃÐ/ŠìïíÅi…pažvKÌTáͼ¨˜››¤IÁá|„ç:ûUÕq4Mó¢ Móá4@hͽ€N«½™ÍÌM’ú8¬q�ڌԥÀ<•‚”¦YP@»Xþû±v}ëÜVKÛÇx¢÷S3¨Ù˜}€™¹Œg‚î­Y{uql)�,Þ”ñôÄÆââ¥hJ©h¹ì­¡ÃÓc¤%À6�Õ�©”³x�X8ÄM p!1&Û ]؃M±§úK/Qœ£F·;Í·o¬�½NéÒhr£9a›"q5O#É…°ä5ndeª 6Å6js|*~Eº@S–=·þ~Ò;¿4Sà°oS�;N¥ªÄx 0¸¨z©�Cnö‰–RÒf ݶ!ùöBûòêV•ínží]=YÝ*Âh4Ödw7·RJIÅwâ%uIsð�^Š´—ÀåQsò~W›¥'qŽWÔ¶rB-p¹mHþØ}…Ï‹‚ =ç‚ðÔd¸æœ“›˜gÇ%*âœsFÎ9ç„$âÛýfÏû¸.+>fJ©>ÁÏû¸¾¬¦�åÌln¹" ˜Ý=C"Î~§ºë;qŽœsÎ9ÖCxq�Ì9×G}Ãjš¦hzô›“"’„ˆÕ/&¢?_uÂñtб¿~´xíÆÑn}¶\^ùö·3‘)Éá«>õˤ£ã9ÏW£"7©ˆ­�èò¬M¥”i�ù�,ÉA¯[^]¦ÅbÕ~D˜²PšâVÊz\öVVW®»N›së–.Û�]áU³‰sdÐ’;è´¦Æ9TL)BÁNݪú®—Sãšá^�NñiÃöEœã‹‡ÛZä5'ò«åQ0朅‰VØjß­Ç<òüthrRx釮íÚÜŠ2§lŒ} a’ÙŒS�èT%©þ¥ #9’�‚d¢bH(;¯”ò`Å*Ùd�`SÕè%ˆsÔ·†í‘¶m?oý4™d:�0Š HS�ÑŒp$­9›Dc*©8Sm¿á5£@§¸ˆ‰8“‰x uФ¾díOÄ9ÂW´�s$<‹5‘€îÙ…¾©[efª¨‘þly›\û•ëVm‡puÜ+"]×5MS7²|ùãW¨¸4l²eO©F\TU©õØrÎ %5M# LMÄ9.‘íËxÓ4Û²fQ·*|EMÓ¹{Ó4õ4J) ÃðBÍ'�ÐÇÅ9¦|Ž”Æ±�5­Œs˜ßyÞÇü%¥”�Ò&ë`ª+qޝl7Î!â)Õ'ø Ú}±ÃctÇlï²$)œ�Ž ‹8Gø�TµFy·cÐ:޼D—@/½që%¹í¦Ó¶-ð¹[4èY €ÀèV½¯^ÅX~mqÔ'ês⻋ÅPzLs׿ƒtP-ws/Š$€·žæ³™B ¥3Ù_œ@0…D@ÖþÐ0lkÇ+é.šABdèG3«¯]ÛYq䥽šŒs Û8é*6˜Ã]ו¦nöäñññ•+W’Ì\[b6Þu¹\>ÇM~‡a¨—dÝ=Ðu]�"=Ñ>V¥´ª9çN˜AÌ` ÕCd™µžòùº?˜utØÚHZò=¯“†K#9Xjâ‘ÔÂJ�©nRµmN¾-SÔ%36Ëá»ß‰Íš·ØÅç—=Ô1ŽãnѪœs×u»�vÑ‘4ÍÅ”P±=²©Y»@jÎ,ÃüÁ¾ß¬á"0ôœL’IrÐBÅ"Î^L�Ä9ÔM4XK�2ŸÏÛ¶õœ‹�$��ŽÛîxç¨÷ó⥔ÝÊWMÓ�ìºî‰ö 81Ú(.;4´ƒ4GÓ¶m“¥¤”º®›çæ £=>èR†eÄ9.“º¡¤”Ò¶íz½®Û4¿~VGÄ9^]Û hÛ4´mßÜv–\jŠ.�ijÖA©Åz§QàåéÏ‘RBÎ)%M}êžTP.MBJxºê2�.p�ˆâH”ˆ~…ßi›º´ŒÖ)ß%kSÂKm·§q]ÁoÛöóÖO•¨»Ý2$[-_B³Z@@âF:©ŽÁ²Û,:0%4ÃA´¹þìsŸ 37YöÚ€4dLóŒ©4çNcH €c:6‡×ÀOµÛ¥ã9ýÆÂóä$ µ„8=�& '²É^KœM z$[i¢µ�}€¦¡ƒ@¹çø¢3j÷ý´.¡ÖÚßOô~šÀFÄ8mÆOI)sd Äc7Ë d‡d�¤v[4"ítžFÍêvj š6%üH˜È)Õï)®f–Ræ6αs~¥Kçxhíu›ÿ÷Øë”^s$§¬–´}` 7¸LÏM}æŒì}Z%«í3KšâõFˆÐ)ÎÚö�€ Q|¿«ŸÓ_}óCwK¾H=WB€é$õÍ�kzHõ%&  È5Fè¨ûQ­Æ/O…ŠZ“ú‘ºU#jœÃ•AÅÜÍW«Õó>ä/kç0»h;÷¿²Ý8‡ª©jíì}Y^àV+ ݪÆ9ÔIFrt�ºUáËDZ!Ü&ä ÃPJy¡âÖ!¼â̬뺶m·[ä†aø¼&:CÂbG°7qŽ"Ö;†„Ú’¹+@�(FGŸ­¼î>-r±æR{¸¨­SéÓ[ËþÖeˆ’0*N#€©¹OÑŽÚö�“Ò°kç°�8‡;¡:z†§<ð�ËgµZ­×k·¢cÖ’‡ÞjœÃj·Õâ_4¬ª-Çk+ªÚ÷=6};¾$:«q¨Ô†SÐÏjK>—Æ*®0ºiLÀ!êt(HÖJî xžåa\ŸÞ_•R@kÛv6›ÍÚfu邏–I”>ª:Q’ˆˆúÔÛ /]œãÑë´ÎýN+bN·ä– É-’ÃÖÚ8“‹­ÆuG3IM×ugwΚ(óF:döe½^®ûåb1 §(Å@'àÏ,âá8Ç8ªÈ$@ÌŠÜõµ, ûö`œÃÄ(HPÌÄE5÷ã8ªjHˆÈz½¶~ýhޝ0¯¬åñëuZJY¯×O„s¢x±d¥ÏXK?.§wäM£Ž¾ïW:Ë«•É’^4u1¤¼DÊÉaje³¯_dè²,†§¬&Ž™™ªÖðF]#~±Z7sZú'xQí€$ánÛuí)Ðü9ƒ›“×´ÀKvÔ/.>XÄÌÌžlRú|ÕÓÛSZXÿ@‰®-áwÛžêÛ1A=‘^¨:„!¼âÍý¯Ó³ÇŽ»Ò62@@ƒ19M%™Ô"ã«%Ã�Fï›4$l:©r“N 6J€ä¬_t`ìïí… a Ò…„¸kB Aà�\¬ 9�óÒp�Sç5Ôöu›ÿ¦”L\7uù§ÈÅã˜ÙÔünšF`sÆówýdâÁëtÛóË;@: !œn¤“j-œHN�S¦×ÿ*M^ÃËÉHKI�t%,Õ€01årÝ%¹:Ÿ¥LÅÆRVX­Òè)7L$(‰JØ8Ž› ¸¸¶³ëKmÛŸczÒÌÌì±uIZ¢b¤1ÙS‚%ëµ@”¢BogHÙr³6Gs(|Ðóõòü|ݸ͚æêÑ +ƒÑbÓ+R äOU¬öúpÀk««‹ÛÅ|n^La^àÉIÅÝõëþÀðÒàÎU�Ý÷DŠˆ‹Û¦Çx]•òÖvתžô]êÑE®zoO6?%à›åu«]ÞjOV^ת¯Nß, ]ò¸WÌ´FÖ5�§2z‘µÃ3”s‘z>mº7K=Þ÷¡]pbz-Û´ßš’dè&ÂK´¨·íCÎ�©“#"_ѶùŽç}LO¢V] À!â‚Z¼ÒÌL#Ÿ#üNÛ�2Ûµ˜z ¼P¯ç!¼â[’¸ŽÄýfwÔݘT˜cÍi§jp‡(è0Çè+¢Ô‰£1Ч=¼Øi`Ê:Øÿ~^‚bõg9vz´P7À^ÔÑòú�Ïá×^Põ„©ùt�fNäœ f˜&/¾ ×Õë‹".""¤‹ ­} ¾t>Ƕ•q}?Ý–¼Ò|Ž‡àƒ²ö¤u#¹xÝUkÃôu‰ T*P”B$ÓÖ|´æ�)…¥wøˆ.¤ÎóR£æ½H“èpUÛ�× Ð/E>Ç6“c{�Ö„Ç^§æ°q4ÂÄæFˤÙlP_Bt¾àQ·&>=³ÏîŸ6m7ËÍA›Ž¯ø‹®†åº¬3�NWPéFNiXnûŒsl_ü¡Û¾ õ•�Rˆ$ÀÕôÉ[—‡—Óöz§n¸xO4‘Çœ¶Ûì�Gó9>/ù‹~úN¨£ÞgJé‰îlj”’P¸©tZc1xd5¼öÓ ˜ÅÛé%R+Rìn.y*wqŽWÚvX°MF{±B_�ϱ9þéQ<½KâÙ¨Õ4E„›Ra5‚þ¼�ë{4Îñb�Ì¿KÝAñÀ7[Ÿ÷¡…K ž0¥”ZÝò…{1!ØlYªÓ¼/Ø×–�F €C\ @¹(q‰ìI\jÜ$�„ ÉŽlH†m©O£9°:Å­… êŽò=owk©þ\À�ÀNœCàÅ£Þlž�ýwaÇçäs¨ªº)¸ÙÔ }�x4KúIó9¶Ù�uÁôb¢ñDÛghZw•:D\¨Km‡œ�™8ŒV’� N4êÉâ];S2Ÿ%h› EîGœ�a¹Zßþt8;¹wçöjy"�\½z|ãµërío| i.æ(ª°F$焦õ)æ àâ" .}>Çö�´^§µñç]§$2’{Ênâ �.&¢”s'®�]þ`=þäƒyçî'gç'¥œ­ÇNò­ƒÅ»7oüþÍ×¾±˜¦Y³²¹{¶"`„�¨Í5§¼Ž}¹è%ÿPÝ*wˆ ¥¦ÆzTÇa(ªcÛ¥Ëý OÑççsŒãˆd Ý6ôƃ¹ŒÝ>é6Òšc±�D^,n<Ùû)ÌëN˜MÒ 6µÊ]§4ŽM$fç!Äù™ìá¶Ã°¯¹m9⯨í‹v^nžx¿o_T·Êº.W¨mZ bEû)yèx¡Nä/qð<Šíùu«Â×ñb½ž‡ðj{lþ>>ç:MŽ®´A¼O("* K2´ q4*&Tˆ!Cs•F·û@ „ TXDœ4BÙà†<•5¶=¾½xv4›¥™šˆbt¯[»al:”K¼`… Ÿç0s³šå1�BuJüh���ëë âMŽ\7ù²œ4Ù˜Œ³Ë@q09²{g¬�…³;ÑØeËD{“X™ÁgŽ…:Ï–øìÞêƒÇÛw>þÅO[ÕL=†Kr~ôÉÝŸâ´[üÑŸµßøöÑõ« “ƒp$ÒSR7>縸.óéöD×i"`@vKÂL ”>¥{ðõWËõ_üö×ÿëû¿øéɽejÆ®ãìp\Ÿå_ÿêê/õ{‡Wþé;ïü³wßýÃëWÎO—3•lž Ä·Ï*wßÔž6N¡ŽGêV59›-n^à"IrJm›ÍÇËý OÑçÇ9ðÈд¾ånßCw{r|år»é¶<Ñ¿ª¦”ê�<†¹È5Ù~{]?‰óÿ©mýU~MçxEí¾~mÓ|…|´=$¡›ó‹Íî4%�vv’µ°íó>Þ'0µ�Ø ž#ú� ¶³—g3Ë}ÞÇôõÔhžjÔ­ ¿Û6[p£n‚(¥<ïC !LR-VIÖâµìfm“öè7Ó`j4©ê®ºÃ  Ôf*RÄ �ÍèTn„JG�©»JÝ™w˜Á¼ævìóÍÅéȆڙÃeZ¦qt‚µ�:ja �þÅ 4þ Ï�ÓjÛÐà :Mœhšì€96‹&€c»nòè\@U}°nÕ—l×™Q}W­­tžèàÕ p*a.îZËÌ‘æ0óÑL`ê¦4W7PŒJab‰Þ8ZSökܽ»úõ¯ïüøgg|ø�+WR­?cæ:šõþË?ÿÿ½ñGçW~ðƒöêUÐÖ:–јoJ½p3�vãž_ÿ÷o{¥™ëÔ!FPÜÌѪ¢‚eâpíøÿçãÿñg?ú÷}x—Y®ßSs^ †Q®\9xíúÝû§ÿáî�;¿úåÝdwÞ~ç÷»ÅUM3+­YÝ1P+bq çï‰:GZ¦ubm²–>5ßzÿýß Ã0ôêÎyÛ_½z8?bïk•ÞÅŒê´�_·pÓ¯k3 ¨Éd/­‹:u8ÝÐúÑ4 aÊ;Å]n&·ÍÆÀ“¯¦”¶3Sl®Ö‡–¿¾Ìño–w¦EË„©~}m12Uà÷‹íÿªUR.‘Ý@u­löõ“9qŽWV}ÑÙÖ²¬aÒ§rJ=ENÔ¦”µƒLq8Qy &.S�"’0«+D0ÖÆÙá«òMMÆ”Rí7m¼$¶Gºé«9�ÕÂØß~·Zg÷+uÑç½$†ðÒ«c­mëÔ/Îßwb¬•‘‰LˆÃmZ×Hš€ZŽƒ¨íÊ=cL¾{B4DÂÅò‹�é~¸ïu ……îÂé'>n»ëƒÕ«BØØ¤øq�'T Ûr»fµlK‘RJ’,"ªZÇ„ã8H@°Yì¦Þ0_`7Ç}ûöú„ï§"µ¬–À)ueH¶µÅ¥.2‰Am®�(Œwì ËAמúéñÑçgïýûÛÿæ×7”׎r3œ¡.\Ò@Ò!à¡ßèûÙ{?þõGïóŸü“öÛßN)ÿöôlvõŠY�̶—’‰v¸/«�ÎÉ^J©sêÇ®Ÿ:a_úù¢k̺%}ÐâÌW�þvÝÿ?ÿéÿôÉG8:‚pÀAßÜ”ƒAÇá §3CÓðÚMu»{ûã¿ùèƒÿë¿ü¿\¬NïΚ|`©_­Ç„ÐÙ 3_ùÉÉx¿=Ìí¬[ž¯2=‹%B3*8`êø/@/'ßÄ÷Å�@TÕ]�'DNÿð‘ºU_a^¹{ouûݶÜÜ—?þ.wãz<ìŽÎ‡%öÖ·mkf`]IUUÕ\›i©Ij<ÎçËÃÝ›¦)¥t]`†ÝèÚWqŽB!„^Î�†ŽìnMsb³DeÓßÖ-ä�ÌèHÏg1ËPë•óÒH á+ØnšÞɱíWvöÄJ¾Ü«Ía/J?4Öýg?ýi^�Úêìhv çç)uFx}Yu¯õÛ²—kc±»ŸêÑÑý÷~~åÆ �Ï»YSJ¹3‹e#àô}¶Ì~Ñ‘Ü2QP\­qKÍ Èw‡ò¿üòÇ?>=ÃâGWQf>ަÐâ ’9�À“ž  ÉÚ¢ÿî—ï57^»µ˜ ý0öc—„m÷�‰Eïf©ŒCéÑ,qú[|ø3œÖÏüzÇ$³ÄC-b½ækY­V?û÷'‹7xó[Gó«ÇÚèˆu_z¯áW@Ä(µMü5„^&é !„B!„Bx®h½öm—qròÛÿ´9ëçź$fEÅŒ¨=¯k©ƒH›ådýZWëß{o¸ýŠ´31Ý�hØ”m{©Ð!¥tL0ï­œ�Ãbv>oyrï?þì§÷Ζ�9ÐbT}‹“dç-ÖÉaŽ"P¢pèõd(ÿæ§?úñÉm],zb¥ á<% }�áJ:©©áÌ|ö1~õ ýèן�ž®¼$z‚ѬV5"õ}v¶üù�~óÛ÷>»ûÙÛ4G¡cJ 4ºOM³¶-Ž.OýƒBø’"ÎB!„B!„ðœ9}Ö6÷~óîžÌÖã5i1”Ü6%Ù˜ÌéâàNÚ�Hš3É8–Õê“ß|Њ´@®µivêâ|åBH±"æ ®Ïgí�&ÿõGÞ30Ï%ÍÑÎ{˜Ù¬Ñ…¬³ÑÚÏ–aÙ<-!?9½÷£{w×@É�%ªªŽÅÇ=7Ãs)+¶~8žá7¿¸ÿñ¯og.Žç×lDòÆMj.§d4¥ÉÉ”ùêž|ö«Ó;­mMW±â‰.n`êíÔÍ+„^>ç!„B!„Bxž`& Ÿ½÷Þk©=\•ÒpvÖv¹ŠL™ÉHŸ>‡–¦IYõ07Ÿþú7uµjq“�TƒM¿ìW¬p€QwQ&izI§‰Ÿˆÿ§�?æ t Z¬£"‹wD;¢Q$‡z.i�;H×çöî¼ûÑéí»p“”»nTuÕ¼çÞ:t™§+ë{þéoÎï~|n}š7‹.ÍhMB—и¨-»rÎi~ܽŽõѧ,?ùí©Í¢9LH,*X@Üj�—Wîd!¼"ÎB!„B!„ð\Ñ\\KÿãO®I“Åè>ôFÅŠô©±0”‚R÷EjÎïÞ…YY.Å4ÙTÞj»˜ý æs\´ÆQ˹uIçŽSÊû§÷OÀs5-ž¤An˜Da=‡˜˜g²Aj‘»1wç‹öWgg«AE%·3˜x;ëöÜd'_9¸r÷ãóßþâS ù¨»¡k¬ÎÐʼ‘ŽÈ¤˜¡ ŠQ‹™HYÈp°¼ë§ŸõÓ¬9ÈH¦JÝ¥>'›“AbI0„𒉵B!„B!„çÉæ4Žc«H}A!Ö}×uã8š@pó1-U'A¿n³è8¥(fÉ�°‡ºtØ+ç€gQz)¥a#.Z¼dYÂÏ/„¤”%Ñ^ @"À¤îjJ‡—44í¹Z‡œÐÜ…Ö`ÝkèHœ>¢?ÕqéÙç�€#|€€¦$!„0‡ÌÌMt��Œ‹Õ}]�ªNc–Dø@sŽBx)Eœ#„B!„Bá9K)™Ù|6+ý€”PGGEÕ€‹˜…€ÑŒ@×ú04M3 Ãl6ƒZÛ¶‰ ÊÄ›T@3d°QiþwöþäI²l9K)DÄMµ*åY§E³©–”3ˆ�ôÓ[O ª ÌÜu�åÂ̤–RÖ]<ÞpÎ]lžs8çœsÎ9çœsÎ�³¾ËÒÌšëW‡½éCäe¨‚² —õ3¨Ó¢Z6›<ÔrTr8Øß»y#ìì&P"*ÌF¼]Ô&Œ[ù_° Q2«.ØJ�‡kŒ_{ù•öøx¯ähŠÕ¢ôËF$BòÉB * © ‹Å – X©`ÓÕò¥¢ùú̓@H«˜™4U_ò³íûD ”vV™”!ÍC„R�Ëx¥õ4úÍõQu–2hÇ‘c ,›*X‰aù眻hüçœsÎ9çœsÎ9w¾ØT2˜ööøÆÕÓYs_J%¶¡ ºJÖ'+EQ(P˜4²³{J|JÄûû“k×0�ôf�j!V¬§/Œ‹>üBÎb cP°�2çÕnÁw/_ùÖtz¹ëëùÉŒé`6©D4e*9@5i‘À!†©Úd¹˜œý¥Ë×~ñÊ•Xµ+²’ÂÆÏ´-˜‘…š¦»MÕp¶A"Œ3  �\_¥F&$[Ö ïìOc…1‡±�Ø`2‹{^ä¶fι ÉsçœsÎ9çœsιse\ÇI2Æ¥½½o¿ß|y>kO`}ÑÚB]8°�ŠÁJ%“ÝïVC;™½|ëÒ«¯ðîîÒlij!b#|ÈÖØðBEbB&Ža5)@ËWÿßõ/}3TíáÑ�Ù,J·\–¾ßÙßKYS)¡©/ïí^MŽŽºå7&íÿåµ×^Ž’ó²„ê@Y©Ï5É3n¦�ÒLy²$ZVÍãD ÀŒ6í«¶?T*±Á¼ÏÙæû—'³Ý l¥âc`,æ`_tÎ]`á¼ï€sÎ9çœsÎ9çÜ �VY¥¾n'õk¯L†ãÅpÒxçðäô:·” ÆlI»¾O«Ì§¤û/¿yã~9¼özªê“aBÕ4u†³Kð -4®‡ë½w_?d¨JĹG") V'»˜þÊå«GßúNÿɽ»ÇŽâÞ®Nš“Å¢ UÎ9YZžtáááNê¿õêõÿñÍ׿{åê¤ë 9H±ÌDÔ¥&²ò,€*†ØÈþ•Y:JÃá*¤Z¸de¥ Û>d›¤C-”U4Ù ×nîK�.u ˜@°ŒiÇú ØÔ3çÜã9‡sÎ9çœsÎ9çܹ2.ņ¤«(¡­Ãµ«WË[¼3~ò^ušEŠÙÄT×5MÚÝ«·ößü&½ú2êz©9±»¢B¤5À¦ &¼p�«ÄÐ(•é¢ôtB$ó¾íÃTñW^~¥´ÓòßþÛÛ'§ewö0òðàžî_3hÎr~i²û­ýÝÿþú�ëWûAOÄ© Ål¹¬CL™&ϲžCEâŠ¯ÞØ¥…}xº,Cª¢íÁ¶�¬È¶A‡fíb[n¾zõú­&«¦Ô×ML% ¦¤ƒÆ/Vi�sî…á9‡sÎ9çœsîé0R¥€-r‰l�Tİi.ãJÛØœaÊI9)g#SÒG�86Èëå¹h²sîED*,Ä<@ÙÛß?ØÃ­×lvåôí÷—Ç‹´ìŒ´TDÓýö`6¹´?ýÎ/a÷2buºêVª½i1>YÌgM3Þ¤6ƒ:”ŒŸ}ÔÁãªûú’” F ûÈÇÛÉ϶žÀˆ˜À²F!‰J½ ïXè—«¿ríÒë×ÿú½ûÁøóÿFwO®MÛáÎíÀÒ´Õ›—þê­WùÖõKÓ¾ ]ê—‹ÙåkËå²ïV—ö§’•Š}å¡’ö*ҜJ ®§Ýr aÌŒ@@!§¡: ûùò×Ûë8\uÆ¥iš´Lÿ%Ø8ÛXÿ,¼˜Ã9wÑxÎáœsÎ9çœ{:” ï óÓ®µ+ íI‡IxçÇÝÉáòäh8=V-ÒTqV_»Öîݨ&ת°�UNº#i$4œs63²qV*¤0#el’眻pTK×4 h*¬açÔ´Ú�ÄÿîÊî¯}J]ŸR* ©BÕÔ\Å�¥gâÒÖ‘X‡�ÁûUU†A7;÷¿’´˜ ¢`†ê˜dLº¾$e@ ÛK¬3ïguH/¤}„¡HÒ}žPÑÁª6ÄÊ¥2ì,ô‡o]>øŸÿÏ¿¾Ì%kY-ºcÓT;U3%ŽÃ «,9±bº·¿:¡ÙÝ[j^<ëç3Rƒ»·ðó“+÷ßK·r÷áÓË× bÅrrV!kÓõ_j.½Ú+ùÄR’%1ú>Žfè™_ž <Û!êÎ9w.<çpÎ9çœsÎ=%¤«¡K©Ÿ²D ;ÆÉ},ïwwß?Ô‡®�]#C‡n®÷»ÃÛËý·âô¥ªÚ•IÜÑXRîsÎUUi6dd6”±µüØzÃWgœsåñ¿ÎÄ™Ð3„tª9çR  !0sÎù±¯6ÈãaÆWÛ«j¬0…X_ÒÙ� €næÏøÎ!“Ãf7ò¸Ö¯¥.Öh&"3SÕRŠªƒ­È0pÎD@UÍŒ˜m ”¯î)U1ÎÊ�„ºfÚg¡vÿÆôÞ�cKKUh”8‰ÓÉlo/„ƒËÍ+Ã¥”ªEÎP @Î*"�~@Î9wqyÎáœsÎ9çœ{JŒ+ª”9XKNîãƒÞ]<œ§eŽa†Ç €b†~u”O�ïg½2ì^{åòìzE‡.•R˜×ëb ŒõÙy?:çœ;Ûxƒ™Œ«óã'Ÿ' î™nÍŸpµ1Î)´3ŒíÇÛ'6„0Æ#3#¢³Wþ*©J‚™Ã&!Ö{mœLJG7Þl‡¾ ]2£ªª¦;ÍÎdŠE5±º+¥äœ™YDJ)¥”MÎáœsœçÎ9çœs駃�DÛ*F>­îÝÆÝwŽNîwÜó4î*HD ˆR‘´1Úáƒ+Мë¸×J”:—f]/�‘êuŒT�sî3FÛ5÷q À¸:ÿ¼gŸS!S“±“ÑæãídýÊæs|šíó6>�DÄÌDTJÙæØÄ!ç•s€Ô8•’ ”(UhB]QŒa*W®Ö9¥”ÆÇ}1í))©–2Ö¦Œaž·$Î9÷,yÎáœsÎ9çœ{:ÈB^æ ÏNõ½>8|w%}¨eÚP�Š™JÉ0B jj ÒQ¾kóPUíîn=i³ôšÀ@›­Áë'>œÃ9÷â !`³(�Ç�ó¾kgLë)JB€@F@ cŒÙ� j¤›ƒüWmÌÆçólÑÆ6O:› ŒW8‡§(¦Êj3ôÐd‰A`îÔLбŠ�JÈ9C6ÒVP�*clÀ‹9œs/Ï9œsÎ9çœsOÓˆêÕa:½7PßLe7¨–• ‹�@3ˆ‘+»õµ“´X<¼ÿàƒù¥[»{5EI;Y—n0 ›îUÎ9÷"ÚîÍßÖàë >ã~ŽQ´ Ùr,h;õšÆ»˜��έõÖÙ h›yŒU£ma‡™�WT`#’ ` ãbF¦RS-TT”ŨÑÚb^�ˆŒ÷6ç|¶*Å9ç^žs8çœsÎ9çž6®e¢§8¹»L§<“K-ÇÜg+9D ÈD€±&Ž,�îÚwÇéôA×ì6hHx\—Gtðæc�:œs/¢í¼ñ³9žÇ%l‚ ÀÃèÌA{[´a Ðm絛޶2†™ÏHŸØÏj{å¯\ „‰9Œ÷IÇ»JPUXu(ªHfŒ@C„alZ5F5ãCx¾ê~œsî™ñœÃ9çœsÎ9÷´PÍõái:üð´?µýI¤„Ü£ŽLM¡Š”`†Â�ê²B¬Ñð®Ç«yêºXGpjåÌ4ò�Ã9÷ÂÚ.X�ÁÆXjp^ý”>Ÿ±Ï€3÷�l“pè&ùàs9¶o“€mǪ1ÌØ>Ù6³“�sÉ È˜ŒÍÄ” ŒwR• ªëX �ÕrÒLdBåípŽq¸ºçιŠçÎ9çœs駃 %iîs·ì¯]yU–89ÂË7½û9¶¬EɸڼQ!¶5îbÿ•ú/žì®BS H <.ìð™[f:�>îÎ9wÞÆÕöm{%œÑq.>­�VÉ9ÆØ0¬Ì,Æ(A %笚aBQˆ,¥”R aç\¦.m³��×j|¤'Øù&b´}~ çœû*yÎáœsÎ9çœ{jr„‚~HQC�M`¡›&T}��3š¦Y.—Ì—–C’ `|lŸ¯ò¦É»sιóò)ÃBH-D˜«†…l%w«~5›NA5¬ 9-—½šU1ÖÍ´äó~$Ï120Œ,dc§Çñ¨�~;Ž-ÂÆ/»Bzªáœ{qyÎáœsÎ9çœ{:ŒL‘cS[×u{í$Tè3DÈF¦ã�­·¥ÂPuƒ”­iªœç!@“ˆÀ”ðøn_ŸÒáœsçìlYÉ£KÄ*LT) ]Ö,\BE¦ ‹e/!ŽLM ¦&PÖÄ@ñuùOE™  H F›_ÄØŽ|Ñ&öP;—Úçœ{ŽxÎáœsÎ9çœ{Z”ljTM˜[o©P¡F��²�`ÛDPJ�ršNTa’1„ØØ<„×�Þ�sÎ�·�Ur€¡¨‰HŒ"Á"›°hÊCN©/$Mv˜š2 ë–uÍgæ0¹�3ÐXó ²É96ö°b20›VjjÏíÄçœ{ö<çpÎ9çœsÎ=J ÉÜh»Oî–®@VÔ5¬d¥¢Ä0À`P V˜wKPŸmµõVŸÑìÄ£¥É¦Å8l¬‘zÒáœsω�ÌQ¤L½TDƒ¤œæ]^XÊ Úß=@BZÅœóªOD[%qfX¼wÕgQ°”`€Ñfx;d�EDdç3ÔÝ9çžžs8çœsÎ9çžÒÌ)„öàÚþé�Õjn�X¡TŒÔ(�[P•À$�G±É¬:¸|xòáüôÞr8 ŒX×{ÓË»{7.ï¾^ï\G )™„ š½˜ãSØÆþ�ƒ�¾Ödë:[@�t,ò8ï;îœsçÆsçœsÎ9çÜÓa¤Š�*½öÒtywrôcÈ Y‰*)ÀF ÂvœxA_7ĵÝxãÖl½`5d’hPÄ6Ì�sÎ=˜y›s؆Òüýûÿñý‡ÿõ½wôà胾?*HQ¸jZKñààÕWoþò­¿tiç­8½‚¼Ì)2‘gןÊB±ˆ±žj…‚f ñ0”˜ÂxœUï[åœ{�yÎáœsÎ9çœ{zÄyÿö®ÓñÝ&Q‘óÀ €a4NO5 YúO1ë0µ›oj+œöËzÂZHaªã�Ò߯ú�#mñxW÷�Kv&šrν Ö‡ãÍáa}d ""�AIy^hYâ{ÿþ?þ«‡‹?[,VµMöƒrI)Í“7§¾çþ_¾ÿƒoÿÜ_ùÆw£\OCÝÒ,ž÷£|NiᤶÄxó«P°1Aa аÑÁFëš%ðú¸Íd¼9†ogx¨ÿ2u_ ã?Øñðx9þÃ>§¾Œmmñúõ86–Á[ã6RØv ‘ª¤Øta]¿N±î8ÇP?Ñúò<çpÎ9çœsÎ=5«U§=Üú€ðáÛ÷N VdB;BµpMÄ0ä’{ËK{°lîÝzëàµ7ou˜ödeÒ²jÏ(€‚ή¿à›Ÿ.&c1 ¶^?0`»#xÓ^Ç>cX·€wÎ]|FÐõ"³™�0ŽÓXœöׯݺ{ïA;…ÊQ{0ÿóýÛÿ_þ_ üÄâÃê`aIÉ @`è ºz/üøÃÿðî‡?þŸþÚÿöí×ÿMï[õéŠô¹]_ël¯¾KèçK1�L&ý`Z‚šˆ@˜†\¤¼ qRr.Á¤Ž*–r"ã"ˆñXñ@¡Fj4.ªú!Ý=§Îžî�MÜD!aˆ>¶÷¾’²_21Œ�H�epŠÁºå +Oë])Ò¯0�ÍBß#•bÅB�º!btâæ¡Á*¯ m­R¶¢X‚B¼|ùKóœÃ9çœsÎ9÷ÔTM=”Aõ~œÎnüÜd:«î¾srúa�Tò°ê†e)&BU§{u³;9xéòÁ«m}…‰‡’†’™•Lã¤rÀ÷œ>[Fcww`ã>_;³ýÀØåìÖ`çÜ‹`s°qoò£cB]שdÌbÿö»ôãÛÿqY~dõ²ð^oeV¢ }y¨ULCóÎÚÄ/_þ-*çý Ÿg}Y5“:v±;îĦÕ® X|¸ŒÕ¤Ï: Äh™îìNê�\ŒE%U-(cé†jáÍÒ�¹öÙ#¼sÏ­�ü3%ÃØøt¬^:—ê#ÄÊø™”úIS#Ѱì£5»Õ�ö8z“ �%uè4-Y›Všé´­Û„ 2i.0-€`L!ÝÓà9‡sÎ9çœsîé00ÅjH)k– ÓË4icÝ^>9îÝ~0¬Ê°êòP¨Ù™¶{,ûáÒ7^®¨ª0¤qåeÝêýÌ;>>S_Àžy<]›¶ zöÿÈûm�7œ{­']�o>3~bìû‹J0‹ù{ñ_ß~ïÏ ­:F¦�vb Ä!‚‡!ƒàüãŸ|ÃåW®þ<¨œ÷£|~‘I&•Më¼k)JB™c~d÷îv?}ç§¥´¥´Å$V¶©º~Cö¤Þ ÜZ]7½ö¤+bŠ2”�Ï,òf’‡ÿ>uîóÚT¸ŽA˜Æm"*(Â…Œ(ÕÝ'÷†{wNï¼w—(˜3­"íL®ÜØÛ¿'νpÈ‹ºÆ~GP ç*¡n˜?<}wÞÝ‘z%u¶aSŸ±^\¯`5À]—$V¦CJU TÙj¸s÷á�_Û{ý¼ßó‹±²¶ÊèàÞÛzçí‡Ýqdry÷FΜ* TE§ºœËûïãdè)HU„'fª60Ô` RŒ?ÇG¿[ý¨îÜç¤Û‰e0€�È¢XŒˆ4ÔÇò‡oŸÜþñIB ï\j®Ia"(£”¡h—ݰZÝÖ“ÜQäÝz¿UÒTæ�LAúÈy¯û"<çpÎ9çœsÎ=%Æ,ã^ß"�›¨XŸOºÕÃÉd26¤*cg*RcX³À0fbU53zÔ:‰ÿÀ×ežûçóød+ÁŸ^çÜlŒmÈŒõ #2pÎeõÁ�Ÿ ¶à* ¹€ÖY©Ô`€!u5 2`Ô…)ßøÓ×öóy?Äç‹Ò¤ŠÃ!~ú½ã»q$©Ù­t@wØ ¹-™$ ªPG@êLW�îÞeZÅÐ^•ªB,3Ìl¬ç((0ÀJ�q*¹sî èØó��ÈX4P¢™å6Õ€IDAT¶jNOðã?»}÷Ç'Qw/Õ—0TÝC£(B@¬ª*V ÝLÝÑ2­bÕ\•*ìT…¤hG 2ïúxÎáœsÎ9çœ{:Pc¨‚L`%R ¨YÖ“7Š‘@BDDĶ3ÎL€Ž67†Ç>x|8¶{jHϾµ¦qå‹¶où6Cç^ ã|Î6�ÛRUuH6¨ Í4�ÞõK¯X7Cúè°2¢¢Y$@­’Ér8yÎñéH›ó¢¿»¿÷Á�aA—Û�&ÔË4L¦mÎ4 Èš�2@E)Mdqñ¡œVÓƒKSĦ6툋�•ÄØüÂÈg8÷¤”lŒY2&•Š«þ÷ß_=¼ÝåÓjwz¹Å¤K¸4CN(T�9Á ™«JŽî/ÑœTÓƒƒI䳑Zñ³¬§ÂŸDçœsÎ9çÜSb¬ƒ2¤¢hªýjÙuKÛ9˜ %e+Æà@,QÁ©XŸ²‘š% jfcÈÁü±�Ã=+ºi^¥d S@ýIwÎ}2R!„œs)eÚ´9g‰!!h;²<[ €Uu03 ¨€ –Y2±!ÿLƱjïß~ÿžå0›ìªÔ%R;=9ú†ˆ€uĤi÷&3]ÔGw—‹ÃŒAdc3ì›?ι'ftöÿ¤dÆÆl¡<¼Wî¿?—<ÙooÄ2éOQV8=ÁÐÁ ÂF`Ä€ºâi»;,åðnwr¢)ÔH‹=þ-Üäg°Î9çœs駃€ŠCT⬢\qŒRY¶nÞ‹˜hŽ%‡’ƒiE6eš 6�ªf³Â¼ 9ø£ïV¼˜ãi#ƒæ¬%1t|.D X3�GWÛþqνØМ‡ªªêªyxtråò�¦ÇG… 9C!B¹(‹˜p^œÎg;Õ|�ù³Y0C× ÓfzÞ�å9Ç‹“A­=<ì a·ë)•À¡‘ŒsV$ƒÀÈèRêû9öÚýi<¸óÎýa‰<(s`ÚVç)6»Ñ�{þåœÍŒˆD„™iÓÏtüÀ6ÆOžÙóLѦÀMi}vD‹S ÈÃ{s*M[íôK´‚&"D ÂFëÈW %# hš}CûÓw¤‚P)ùúüÓá}«œsÎ9çœsO �K(ÄÁ³‰“ɦ\Ã@ $lúÀolWeôc¸§† ýbÉd˜ P-Z4Á* œMž6Keþƒpî…`5fŒÇf� ¤Ìœ“‘`ºsp°óòÎäå‡'WJw¬¶P¬ß…!¬ ,’Û¶îû>'B*õ$ì]9øV®Ãây?Êç˜399F×µ3¾”3´@"õCE#]/œÚØ ¬f°˜ ª©ë».WFQ€‰ÕíNtÿÅê¾V¶uÌ,"¤DDÌÌ̤´½Î³¿#Ìëf(€Ü{ÀÆ Îê` cN …2ÁÂøj5´PêK×!˜CÖþ¼Ÿæ ÂsçœsÎ9çÜÓ²!N6.‹oGžò¸‰”×ÿ;n… öÑu–�µ«¯0nA5öÖ»Oi$0XHDd,àÈŠqPŠÇνà6GêñhP€ d$,MkdžÔׯ|óáá�OVÍ^PZÍã’c!2Ä`%YF`9äÕtòæ­Ë)à¬:ï‡øŸíQÎiRÅÁ…SbU›AãøE �!'Õ3cà­AŸÏ9œsÎ9çœsO‡t]Ô?.¥ð£¿XÿmÞ¾™ÓuüñÙíH×ë14V‡xÔñt°¡©ä®´(ADB¬‚H²±=ÍæŠÞLÁ¹ÒøÚ×qó2P�‘ªVÒ�ݼÄpåµ[¿²XÞÞ]’+ÂR)©!gdÍ`tš&¶qÚ÷Aó•û¿üúµ¿º×~#Ÿž÷Ã{®)€(ˆLlüMùñC±=úý©” ³q #¨™1m+óhÝR±ÞïK‚îù¥ªˆh;�#眔-ˆ�1^‡™ŸqLÀg6î¤u«U* %bŒ@¦¥˜G”¡L`0d�’e€Ø‚Ì fSÅ…˜ŠéÏjßê>?¨9çœsÎ9çž#P6Æz•F�@ÈcnAPÎd!ŸQɱ�êïŸ&2ˆA˜êº1B1+¦%—!eqüù=Ó†×ιçÙzËÿz„õz’.ˆsR‘ÖJÌ«>îìܸò�”-ÿìÇ b! ¶u9ˆÒdR +=>í"®½~ëW~ñ›ÿ׫{¿ÐŸLĊ׌}:e¶Ý]~8–…!c¯G!€2…Âzø6ê šÌRÕJÕF…jÉÆdD È™Y40TséÜs‡™ÇSʱ\#çœsNDÆU)eü_µ¸�UžŸù=:{>4nÓQ£l.]Ú?é͆Â"EUëxêj €L7UqS"6ÍQ86í¬¡d˜z…ÕSà9‡sÎ9çœsîiQ#T‰7…j¼+(…‘A ”ƒ¬}|-¯·³ÑÇ¿ÖÅϺ1Á‹¥¤Dªfƒ@üÙ_¿ýöÔùÄ:¥Ç\C fT °©,Â`‰ªêàÆå7Cµêòƒ§?<]¾_úÌ£(™Q% ¸p³óÊõï~÷­ÿñå+¿XV—»SL§=È»Ò Jàùå«|'­‡,WH`†£AY 5×3 [AϳÙt6CN¦ÌdÙz•uû»•ìYïwîKÙÎ!X‰H]דДØTC!03ÊWwh¬…?ØÆQäfÀ�W–‹"�ûÒM«Æ†� &È” �Ä©”Xa2�ìMб¦’BÐtÞOøÅà9‡sÎ9çœsîiÒGká ðzUe|C8ŽÙ0®›ÓØ�˜+æøÈ»ñº·•w¬ú\›™ádg¥0R#(©˜VÅ¢j›€’O~ò“£ã‡wž.æ"qÿÒ¥›×nî^>àÝ]^î…3I¡Àöñáðι ïìë]Àˆ™­dP&MÚÍ5VWn]ùŽ¿ºóƒ·ÿßÿáŸÞAÎLf-´:Åõk/óÍï~ó­ÿÓ~õ�ùa•æÝÁÁî0xÈñéH…ólgR·eNG&-…JM@D&¬“ÍoF0T¹PUÔ–¨†f'S, “R@ëJ2W�÷Ãsîg`" LÍ„y�ø-¡È”¨ì®¦D ¨}Åÿ¤Ç6­Ljœ3cç2(¤ !¤>sË[´` ²�Aª‚l…TM*LA0E!ò—äÓá9‡sÎ9çœsîiaË7pfM|»eÔÆÙÔlºZ=Ö±êãkè¼¹Ác·ì>N j´î&Æl œä®šUÕ´¶ÕiÝuu_ðg?yï?ý§†RD¹"|ÀDÊüÁ�þOþìÆK¿ðm¼|µýÖ[!VïžžÖ“Ë{“Ýùñ<È'•Ú8ç.2ðzåMi]KG†ÀŒÀ‰hN`†€´‡RU¥ýå׿ùÝ×ÿד“£û÷ïÎ'±išW_}�H„£ “ÔMj®«i?¤‡¾²÷YŒs‘YS¿òs×Oß}øáû×§¯ðéjBd ˆ`€Ũ`UâbžïìÍ~î;/Ç –)/9QÞüÂe@Ô+áìÎçž+dФ�¥×�#ð{ºüü÷u¢Qu–ú¦‚"š ±g|~H¦ ³õëˆ�T¹½ ž^ªÞúùëÿû~çþ�îêÎ+ X®°¿U”‚R „À9Q×ÅåÁõúæ·wKDB”#óºO ûr<çpÎ9çœsÎ=Eë‚Oü«3—Ov›çý ¾Nì£?lg:9íO«†=8ù³5?úàÖ�Y—FÚ g&²À†X „ÅÿÜæ÷« ñ�׮̦hµê}¿¡s/”Ç�%üøŒ\=Û VCcÄD²ä v®©¡©ª:¬–= ˜Ë8'¢À€€à‡÷ÏÐ }Ó`ïZûú·o¾Žç‡‡}Þ‹Ó¦d à TVpf1�épõáÁ+ík߸¹s€¬0ä:HXY×YÚº†’aÂe5?¨»çÕ¶uü¸ÉÚäÅ'^Ó_á‘„ÇH•òI÷�ª»Wðú·nÜ–y²DÞiw1_AfP€1èUÓ°èp|íµÙËßÚŸ^ÆJµGáB~$|:<çpÎ9çœsι â#‹V6‚¢$Ý€Õòè'ï>üþwï½Ü´ã^^¶õ‚‚”µÞ¿—rÇÁ®Wíî›ß$Õy·¨êÖÌ;H;ç>YŒ±”TT‰¤i"³"¢DF$03�ÙøÇ<9ý J Šê›Y}ó­�¢òΟß;~¸ªy·mvÄ‚01©!eë“ ‰ç³Ýæå7nÞ|­¥ ‹T8H¨«RºM%Ç£Û†?õÎ}FëWÙ¦ÊBä‚U3k_~«b›½óý{'LJMØ™ìÌÆ†ŸJT)3g¡no'¼üÖþ­W1,‡¹ÕY„†Ô4çýð.Ï9œsÎ9çœsî1" J` íN–×÷f6Ïw~ðã“ý¸ê–m”bY6;²ÐMÏ+%mëš‹Îßûðaó£—v.7; 0G΃·uwÎ}2"6£RŠj§c«Z)¹m'€ñ8`33ƒM>ƒ‘Ê$ÎWó.çédzí�‰ñµûïõóþt>·*¤”C�ÐPUs]ÓÏýü[{×""CN•ë—¬Æ�éåæõ½öê­öøazxÿhXËe—R_MªýKûW¯^ÞÙ§Ý}d`U4ñ`¢C FRà ëC·)lÛìÏ¿sŸŸžé¿Ê€)’™ �*Ó+³7÷v®¾Oô÷?˜çÄÃÀFhÚ°³7Ù»´ÓÎâÞ5 Àª¬2w¬”³ªj©Úó~pιçT)&ÂÌP%ÀT$ŠPÎã";�—´¹pŸ-—R·YèûeÉyg“k�Y¼úêÕœ‘³fS‰U b…ÓeJR…*„¡ }ê`Ò´mŸº3·:F�GÎ}~ ÊF�Á@ 6B7ôuUKàaX¨¦iÛîÝ v¯¹òÊdƒ8"FıìVƒõˆhëØké†�#O';Ãb8ï‡xxÎáœsÎ9çœs`cÅzQ±0…q:O÷î×'‹=FP;-=(‚ Æl�z˜†˜RÉ´ìw3CUâdn\1±3û�sî1DdFª03U˜iΉÈb¬Ç¿7³õ1ŠP3¯û,"a2ç! E»Adâ'R…HT­KýáÐçÅCŽQD"ˆ ‚0s.Š1ù^×p(`€Âç;÷t¶à‚1žˆ‰„�YËЧÓ2,…˜bl&5€˜YFJ¿Ò¤«l¤&F� 2b—?¹z*<çpÎ9çœs鋃lìFªÈJJ ÄR°\TM…&¶¨T À 0lÜÙ»­©m©Ë°8A8�/±\B]×ÈçýðœsÏ+‘8FÌA„ˆ*UUU¶ž Áˆd¼4óÊgaH¿ìÉ+©b3”@Òn¥Z–¦ ‰Ä8©&;uÎÈ}îSV‰mÛN‹ÚjµŠ1l=† é&Ø–ó~ˆÎ}]èú’˜+# )CsŒU¬ë¢9¥Lè»î!²(„ˆ *&“*¦”ú¡³DꪚdE7bðœã)ðœÃ9çœsÎ9ç. € š v÷îÞùp:E ÇïýÅÞë×ûÅœ9€‘1›Yd€dU3ŸÏª¸\œÊÄ›V9ç>Õ¶>ÃÖsÆ€ˆÆ¨ã#WóbŽÏF˜Ô,€RÑŒLP†j1!#20`j©/™©*‘)V0êSã#ùÈwç¾<*›r( cQTÊĈ`Õ¢„„L@AU¨‘®¿–ÔH‘K¬` Z˜M8Pà3:¾4Ï9œsÎ9çœsîBÙ.މBX-5pY¬+ôAÉ65`¢ †œR% £Î2W5 )%hã«eÎ9÷•`6ÀhÝ`Š” cç6躅tÝ ÌTY×­ÇÁã�Û¶Çð€1 º®úsÎ}.JÊö¨uçX8« u]¬Á dýS è¸sDÇ�€AÌJëyæ&“°Ç[c¹/ÂsçœsÎ9眻 h³p¥ÚäABÀbv§v)‡�‰¦ 㺗Œ”Œ‰b(¥ i•p”ì^GÛ˜‘€}¶sÎ}ÈÀc³/[¯‡Òº¡aÓ™P ž™íLß� {´,;^m 9Îûñ9÷õ£tf#Éø"]fó‚ d¬»|*Ö¯ÓñÕÌ›ë�"°1@„G%"îËóC›sÎ9çœsÎ](º]Ð2Ž QbfÔa÷µ—V“êné1iæqŸðzË!ˆ¢*…+©Â<ØI°xý2vg¡ào!�sŸNu±ÿ¼—î3غ‹ @ÆFl0Ùþac€i3–‰Œ�@ÆX7´R2e‚Ò£ Æv†X÷5tÎ}>ư³Õ R2_\ô‘šñãÅ´~Ùj„EX؆—dJë—ªŸ¯çpÎ9çœsι ‚ ÛMÀ0f¨(Ä�McÛN_½•Þž=8=Ü “äDÐ:aÂøF;†¥æ“(‹¦º|ý*&¢_štÎ}&O8žÅXË(��ÏaœyÇÝåc—*“m“ªÍ×�oºå¬ç'Ãçžx{ì__0¬?CLÆ@ÙÔe0P06š3f@Ád0ÚÖslPÀV¨©yUÇ—æ9‡sÎ9çœsÎ]UCˆrP8•ÔTb{³ö•''G§Ë¡QTë7ì¶©ç`±í»x9í»|õR<Ø«®_*�­°&%fó-‡Î¹Oö¤Å¾Úþ©Œ ”À؈ËúÓd@ÈlÎñ(4Z×v𸵜¡ã¤Åv¢Àöƒ�ä%ιŸ‰×ùÄ8fcÌ0ÆWènÆW+&Û\ ãù+1Ù:ˆ$�/qS†© öCâ—ç9‡sÎ9çœsÎ]Lbˆ  ó<' ¸òÍ7ªU×ÿÙ��b´n9Æñ:¾“çUIÓWÛW_ª®]^ÌD‹Rå» �sŸîóç æ+zŸM�Š`:®Ý)ñvÀØrÆ ŒqëNVDÊdã*êúæÖ»ÑǪÙÖŠœ÷ÃtîëÁ ›£P†�iÖ¥ma�À°ñE¦€�ƒv6§PºþC(›Ò«è9Ç—ç9‡sÎ9çœsÎ]ë’ R £ÈXêú´ïÀ|íå·ä0½ýö�6¥k0í¬yÜiX `„À…�šf®ý¥›7Û×^‹{{'‹^$›ù¬ÌÏ66ï&Ý „l qìYa`%Àd¼iÉ­g–7¶ùÏ|ẃ }Ù¥áÍDâGË/gïçÏÜL:öÆ9{Ǿê'Ø} Œ�鿥ûLFZ$+)kE ³ €õëÔh39(3`‚” Ð8§|³‚G¯ý±>ÄC羸1`d;Ëm>»=¾=úÉë‰åPó|ln`d€‡O…çÎ9çœsÎ9wA(=zŸ\HMPh½z¤%µ~λ¯üü7ÿoWÞû³ïßùþ÷¿d:tZPH;’B©âP…pyï­ŸûõöÍWò´9^œRŒ…rf ¾ôRûư`݉Œµè“$V¢‚P Æ ¦ž¡Jl›®Þ¢Œ„Á¦ C¡JPãI£ŽíFo>c°m×WÔH16ÍHÃǦ�W4l:’3è¸ZªÆu¸36ŸçÒ}¦Â6„>A+‹EdA¶ÀT×M.(+0¡"Z2wÄIV}Ÿ©Ä6"ÈPŠÑ@Æ¢2æàJc¥ˆŠÿ œû|”(m§‹?Š%L:î/1Š™9A‹j—‡(²siŸ.í6×'èm×9)K˜´a¶ƒ¶5Õ¤S[f3©"703üÍøg SAPH3k!†‘Ž›:Ù@–E9Ë¢¬¤…Udºž’`"l�¥ãº$onáÉ~ëJŽG_¥›ïÂ�úƒo»k�çf*Æcã,˜xÔzÃ9÷Ô‘!j Å$“µÎ1?ì<89<¹·XØüÄҠ턯]Ÿ¾t«Ú¿´«™cU8LV¥CIã±aÎX F�¦"ƒüP€<çpÎ9çœsι‹cÜkvš ¦JÌE“æ4d¡Ä¢²;É;±˜ªÂÆÁ™ˆ¬ÏE ƒq¤bD+…2SôÕ±OGjÈ C e2‚®»ôcO*S�…`'�Z×mljÊcGl†ÑŠOÈEÖ­´Öó9Hm}Óg¶©~|”´ñXW2î<-�ò.ïïïÜ3!F-ªá4­öêºá§?:ºÿÁ‡%óýÃ¥ê:ÄÒë½ÓÕñOï#.¾ùKoí\�´ûU%¡Ø6‡]7É!l¤�©ï"wÎ]0žs8çœsÎ9çÜñi«á9geŽ"$ŠXQSí]-)TDÄ`¡…*5uÍU VÔrB) ›:÷ ”4K¿É+8j€Ó¦-Å8rƒ D¦¤Ø„”il/C(´.›(ë)ŒM›‹M|õ¤Oþ£uÌÍ×*€í@Ž3ÿb˜LדQMÏüÕ¸<:vë‰é@>>IÕ9÷´�±¤µmr›Oq÷'éƒï=˜/›zgfW˜w9ì0ŠÒ ºxÐÃÞûÞÉ•¥\GöÚJÐ+ƒ0Á”7px÷0çÜEå9‡sÎ9çœsÎ]tfŠ¥>^Õc43UU¨“³�È|RT�"!fAˆÌ…JšK)…�(UŒ±èpÞ�ò¹Æ0¥Ì` #ÒÀÈÆ ãèoB†1CÔ €Ù:BG”*„°AdÌ›]ÙOul�o¿dl/n�õ›2Ú *6Æ ]�ë+­³25Èz ª´"âœ{êØ˜zÚ«¯”½ýçÇw~øÀVa‡¯Y%LSWu=JF 4Mµ;¹)íÕÛï½ke%Ü\¡*ìµ™2, �•cã ž 46²c%ÀsJçÜEâ9‡sÎ9çœsÎ]4ëåíÍf} ª¥”R"‚…+õL ÆffDÄÌÌLDËåRµlÀŒˆ¸xÌñéØ \XA† VbF�Ýð3¡2Ä ›A*lëáädJ�*Áh=/Ü"#|±�äF (1�Ït©¿áXhB°@Ƴ‘”    *@VV�©ŽÓV×·ŠmfŸIîÜ3@*Šèèè.îþôdqû“ƒihVË�¨•À“4#'Ìä^OëÙ¥“—$§ÕôòÞ!F-ÎëNtFcr ŒÊy?Jçœ{š<çpÎ9çœsι‹ã옇m“©¾ïC!fN)SfŠ"¼ÌŒ1Ä€™eKYKV�N𢠀„‰(iJ†U ÞêäS‰¡.HâØsµ mÏubN<?„J­Ò>×…+%ÌÂf °²±™²Á€¼KÎëmØ exÿhµŒínšƒuÓ AÀØ@„¢@Rï6—z;yïí;×^94btE¼�Í#çý¨œsîòœÃ9çœsÎ9ç.#¨ýìUçíðèÂZxÝ É6›ôíñ  U€ÌÚ¬’ûº6ÌlÖ=¼B"¢ª…˜÷®e<àðéÿÿöÿá½ÿ`~º¬dÑ6¬ö Þœíüåë7õæK?·pu'-º¡ïƒ–ZB‚jV³:Ƭ P`¬_¤_ÕÚ6&1ÂfÀ‡’1KèN».åÝfWÚ¦;Åûïæ»·çwßY•ÌV¨T73™î„8¥[¯\áLã^JeµèK[[�qÎ=}lŠÅýÀL­*TÁTa¤ 6 j`‚!‘ BVz:P"�}‘*0Vl1ñãŠsÎ=§<çpÎ9çœsι bŒ:Fgãþ¤i³™Qª¼¾‚�mj´®€†B^ÑÌœs6³#3«ªªö!VÕâïÝ¿÷~òö=¼{›p¿–ÔõØßGŽ‹T9ðþOþäèÁ_zý�_{å•·v:ÌÒ‰±&ÒA)ŠS#.›A›„é L ÞîãV¬ÇqF ŒšÃ1î¾³¸÷þáÑýÊçXJ,‹®VVN ÕÊ’t:»‚IØíÒ1bd͉=÷rîY0‚ŽNÝ�¦¡Î �`ÈJ¡ˆ ±ÆN�Á´©pêÒr™%#bT°=|øÜ9wqyÎáœsÎ9çœsĸ4F²1šx„µÇºZ)iÝnêlF&иS 0c7%ß¾? !˜­‡·«jÎÀ0�¾ÝðÝ;üÏoÿà�ÞùéaÃÍÕÎ$•(ªXXN‡áðÁýŸÜýà6ãžÿË߸ZÅVBVësS+Ý@dJc>5ަ/8ñÛèñ]ÛÆdœ“í6—j«�?Ä{?<úেyÉ vÚx@@!¨U-]ÎÝ btÇóãÅ+ߺvù¥À<ì´dhÉ"ñ¼Î]dËÕIΙ›Á "ÐAe}XL@ Ì@ªºîK5”< 9gf0ˆ?’t P{òy?Î9÷œóœÃ9çœsÎ9ç.Û”c0Á¬�:>áK€ÂF¶þ26ˆPðzy|Ì8˜‰ÔCŽ Ue^?µ9çqDG7©þ÷2ü?ßûá÷ïÝž¼|cgºsûð§ \ºV«e˜¶ÕÁåy;ÿ“Ü�þäíךɯï_žì4Ýq§ý°B©VAØÈlL8 lÓbÿ‰l~´ãšæúØD¦“º?Âoðöa: íMâNw¼$b¶È$B"AuÖ8œ.>\ž† “Ùåör�ó*q'65?ι§NA¸0e‚‘ˆ`V6í§DÛº;2�ÚJ…$ão3&èúuºéYÈÀ—é‡çœsÏ)Ï9œsÎ9çœsî‚Ë5 @"ÐãcIÇöjl:¶¥"Z÷­ȘmýµÛ¤DÇ~'ƾ4`†#•R„˜yYòÿçÏÿÛŸ.Nºi­M€@•Dš¾!1EQÉ}Éw‡á�~ô×¾!Ó©‰HBI«l¦†b›Y)ãsNøB­«ñ��ŒÉ8p�{Ü¿ÝÝy÷ºf¿¾L©. Ô,D& "@%Î4i«Éa7Üÿàdçr{³ž 6ŽuLÙ›à8÷L”(íì6“¦”®Ö�ƒÇ¡ SV¦u§AAR€´j¤™4$EmX Ë£TRiݪÐ9ç.Ï9œsÎ9çœsîâøÄ,z¼cÕHŒ› …� aëžWFëå0c³²nÛÏ9ÀÌÆzŽRŠˆTUµZ­îÞ½ÿç?|;_¹ÂÓÝÅɼlv÷šØäœç÷î¢nš¦±EúTëºÞ¯ëŸÜ¾ýÓK—_>¸|=D©3h. bÛô­z”QèX—´OŽF8JÕëƒ;GË£a‡.×T§œk2)Lƒi(€ʈ»ÍåãžwoïÚ­YÓ˜u¤›éι§Ï„ô`r·í—óž©e†f3Ä`h @0(ÒdÚÌvP"'S L=è8Åü¼£sÎ=Mžs8÷ ) `P �5@0˜¢4€W�#à~Atã»…Ïs‰G� Î~Ïõ'Ùl¿+À`ÀŠ`%$àÐYa)§ÊE ʳí[‚’�ŸfÚö@ 3+�sνˆØ¶}q(“PzÔåÌ7Ë×#àÑr*lýëŒÆŠ›ßmö± éι϶}Ý�¯#50>rŒ8X!Q£#˜û#ñvhµ�Aãͼp�«ÈÆàºî F:VºD QB)¦F$UªëóùÛ¢™fe¨òdÆÌ)÷ýje¥ì\ÞWUK¹”2‹uŒ±$=<9.ŠŸtÃ/wå•&61¤´ì´S.�™ÄÂ…X …ÀXÏJyÂû?¾sPcÛçLõªÃr®:DåРÇt‚Q$bÀT�@éìj³ÈÍüð4uVǪO:ôÅú¼DÎ]XJ:Û™„ÉaÆÜÂ.Œ‹�)ÀtŒ:¶×´±oa….÷9¤ª Õ] R˜ŒÖ=­6“~ìE;”;ç^ O?ç° �s!èûžˆªª:ï‡ìÜWÊ"€³q`V2béÄéŽÚ‡{—â|øÓ;ø÷Þ0L?wΡÙU�R3¨Rˆ\“ Úײє® °Õ°¬+(ö6DÚ3TãVZo½ß·!J–ÍlÆ{Šþ'¾ÍUÝ•%‡#AUrŽbÓ ÷‹¥”øhœ!%0 `yÂ÷]Î9ç.%‚9°1#§••®‰¡mªa5Œ-rÌ Èˆ ”‰Ä¬VeR¢Í€@l`HÕ`¤FP�¿iœs? Ùzíö1.~�y�mad„̜ϜÁéãžY SúÈ߿Ș�uÜ"άd*† h(X7¤‚Pµ‹ŽS±—^úÿÇÿ´Ü¹T¢€¢ƒåÐzûtc3“†Á`\¦Ó+û/‡Çÿ3*=YíïÇ÷ïÞ§k­&KjSE3ó2jæ"6ÀÆŸäœrÆ7 d+B¬6«‡‹9 Ø 2EF;A*ècPš‰©°’ª)C�‚ý)߻۵W.-æÃ*¯zB,Š=yôâœû<ŒPˆ'3zå7NŽÞ¹{ïÝ;¯ a~?Ï&µ*„†*’‚T£oìtXÌöÃËß¾R†œŠ•�¶J9³é˜Ú*ÁH +¶àçWι‹ä©å'''»»»ØäcÈ1 Ã6بëÀr¹$¢¶mÏû�;÷Óu f) 6 ¦UB.W'þó·ïߘ âç¯ç¨ê�r®BKDC×K°ºÒaXi)©çÈWM«Tr¬ȃ¢=ñ®Ù'Ü~‰UUr^®VA¤iÛ’óñâƒý«m? dNÙ,Õ̰:ó£74ã{1‡ãœs/$%pU›Y)KK]#:iëXR9:l¸ê‹ùáq·œl2©ö÷¦ØÙC¬3[§¶*1ÔõÄŒÒ*�ƒ�1¼1H(m‹�sŸË'.Z}ÆÖÝò¹võê™Ë ÈÌFZD�2¦LÀ´4d–AhÌ9 Ì�s11�i6%A Zß%Ρ¹;_åN9e²ÔXÆ\Lj©„al±Ò/ÖP]�²þ)o+}BÉÈ B¤æm&c¨&V¨Q!R¶ @Ih›¦¤\W³“yƒ'½ªÄ˜²7®rî™PBŸûPµ³krë·q|<ÿ á ÝorÝ îɦ…&x°ºÓ^­®½q0¹‹ˆD¢œR¿�º4¶"4Öõ/ñ:ç.–§–sŒ!Çr¹¬ªj,àØv»É9ÃÀÌMÓL&<ž8÷8Óù xR·Ä“ÝöêŠ�¤Ê¬©;‡ŽB=�d¶uWåŸq Π¤Å´"²Á–TRÉ)©îÎ&Cî;‰³^Q8fêK%þø­u‹¥†& mÒ”WYÚª¾:#¥h)Ör@h„(åœaf¤úØ;]ò(çœ{�©a©Xª5ï‰ÒPpïÞò½Û·ß~—º”—ƒv�Xî£tM•Úöú¯ÿ\ºÔN¦$4#Õ bÁØ1çl[œqQÏ7:çÎ˸ýy´î5~ &L&‚T¤B Ü© ÌH!4¶Šˆb„ZID`Ý©ol÷ÇdZÅPKÖ‰ËÐ7±ž§Bl›HÃŒ” d_æ8xf‡)  l¬€,‘Dfd…,ë½K›qô› õ G¹È´].zÔšŠ9Y>ï‘s“‘–@�uÍ^óÒ·ö‰õ½ïß[œv�ËFXDbB)=$[�b³zé�ƒWß”°ƒÁ’…^‚¥Ôbë¶Ñ¨­§˜;çÜóÔrŽårÙ¶ícèº.Æ8†!„1ù(¥”R¶ŸwîE²é†i c-Áz‹²·<nê‰Ø Ðû„þsç  f­j!V’¾®P)Ì–U³“úȸ2“�JŸxkm#¦ƒ�§uD-Ã0¬–ÇenŠ&;—¯ÜlÃAgç2°¨|üz‡Oçœ{aå´Œb“`;LX.pûöÿøñéûÔ§}«ÜRÕP ¬†rº<–“wþó6¯¿~ó­7§W¯VL'Ë…r¨êIΙÁØd¢;çž/l #lvõ‰ˆ¥ÄfÀ}Þ«c•- 𠯦#ÀbggvÓ™a˜ÕU«\Ò*ÔŒ<�#ûò=ô¼Ѳ©“#(¨ÄP.Ú‘†ñXkR  †Š}t+“ ´H¨J†4í�V¾ÛɹgGjîòÒPÚƒÉK?·Cœüx9ŸPœ±N€C*´Ì6W]|çW^½òÚlv€EéWé(B bÅú„Š^Ï=[<ípÎ](O-çˆ1Ž;TNNNDd:�(¥Ñjµªë:„06³êû¾išó~àÎ} PèºK²1lÜKeL5Uû¯¿ü‹ét¾’!ضnÉâsß8„²†ÐŠÂ†e_Pay‚«—ZÍ�É®Pk½0¦ PÐ'œÊL&“Õj•º4Æ’¢Ú 8TI£T7^éW[\%°&¢åÑùa oÈSçœ{Q1”1ˆZÆ¡Ãûï}ø§²z÷ýz9ìR²Å¼d-P©�]ªÂñ{wŽº®Êùs¼|9–”‹JSg@IÙ€Íìqòž ιçoRX6‘™1 Z*Ø ´¼¼wirçÎP7«d¡+š�@f¬'§(LÉLLÙ´Ò»þÖd6jXJ§¤$…XhüFJªô(H°'=&x–`ú°eM—®Üèª�fÑÏc”'¹CιÏËH³XA²Ü†öÒôõúÊ•=;ý�¼Ÿ'åðøHuhwìêÍÉËo^»ò2t­r²^i)±SÒlL̦¦ÆÛQäãH`¸ž÷uι§æiæ9g"Xõ}÷îÝa¾ÿýï¿ùæ›×¯_WU":88ð�ý0Î42^'뜣dBÜÿå_üë³W®®ºÛyd˜Qœ$p¿Þ[ñ³.�4“ 9Ň|øÎû|çþŸe{HD¯¿òê¯üâÿÔ/ö+\nê�Åüd2�jøÆôñ[+Ùˆ� ãÇES uÕÔËn:xó•¿a¸®ù¸”± h}¤>Ý·q9çÜ‹‹L›È�¦°ZêÝôÃå{ï¶‹îjÝŠ È@¶ý‰ &A^ª›w=Lß«£ì Ívw�(¥F¬c»*�:œsçͺ>)ÆõA6ÀÌ9å*Tp(ÚÞ¼q½¹{›ú¥•ÌR“\,¨Úq6À@Š’T,ÕÝâ›7_«Í¨R£‚ºŽPaHm½EIÇžú0|‘oc£1$aÂXÒQ@˜Îdw¯>^䬫@.l+9@<¾‘³$d•Ü̪ýË( çb1²¯“:÷,(i*)T�˜º~%$;;»íë¸z ¯ÞÉ i‚) #eÄCYôe‰ÆšJ)Å`ŒbÁÄ0€_¾^Ì9çž3O-ç06§úÁ~ð¯þÕ¿ú—ÿò_þèG? !0sÎYUoÞ¼ù÷þÞßû‡ÿðÞºuëèèhÿ¼»s_�è¦c•lÞátÞÙa×ì\¾vùÛu|­¤!䲦[¿ !û™—Ê)N0”NDŽï>|pªÃý°ت7¯üÙ{‰t¿Óy½ØÝ›¥”x]”þÑ[ÓbuSU±V+iÈjE‹ê¦/¡@&xã!‚&‘圔üÍŒsι5BÁ”…VýýŸ¾súþûM*ûuhZ13I´Š�T-—2”�fM{ öàôøè'? ³Ù´�L&“‡)#ާ¦�VÍÆõ 3îœ;gsÖñL~ÄÌ©$3#¢È$)µ�_¿yýÚ‡{÷‡a¹:ž™q¯ª¥ÂÀ4V¥T,ݘ´ù­7hÉC`I–Z®W)“±˜t}Îþ…ï?�éW3f$¤€i±»7½zs/�—“Ž˜U&¶�>BX@�´°fRªKÁêÚË×ÚV‚œûÇê¼�sO‹�TDX‚öa1G>ÆpŒ{?ÕÅI™Ÿ¬Jé›)_¹1{õµzr ýÉ�ëÌ!TK6‚3¶�öö ÀPý2Gçœ{.=Íœc±XüÞïýÞïüÎï¼ýöÛf³Ù|>ÿŠ™ïÞ½ûOþÉ?ùÿâ_üöoÿöoÿöoŸ÷wî«1¶¼ 0Âv‘fß4ô«Ðå&bEµLE§ÁEWw~æeáÔ+·Õ¤Ö‰íZáF¤^ιâuõ²;Áê “¨Ú'æã�ßZÍœ—:†!禪궅é²?\Ø Hf;³H‚TUUõ]*¶}×çÍÓ�sîÅÆµ5ú¼¼XN–;¡j@éè0N&ÅÐra…€¤nŒÓÑá~=áXžœœ~xgrëFœN0V  1ß#ìœ;w Â8¹—�¥õè SÒÒãY¾”ÒßšÍÞºzå޽‰š(Œ—uq›)P€Lši’Ó;—¾{ý =ÊÐbÈ&µTËå°þö%ëÛ¾è9·>šÞœÁkŸ–»ûÓƒ«“Ã;''ËeÊTâ¤dș㮱*™Q.¬Võ$–áôòͪÜë*¶dÃyÿˆœ» Ø´ŽUJ ¹nhOLÞÅû?¸wÿ½ÓSRHƒåòÁ;÷?|ßxÒ÷¯¿ZW3ŽìÛÁ>¸Gé†xxR>¼·ùï¿õíÿáÛß¾Ttš’X6²qÆùXøpaÅúD¥/VåFÛeMÁ�QBl%IÀôj¸ÒÍ’–û‹óå~¼«ªª©¹/iQNúañæ/ÜØ¿1Ù¹ŒÐ"‡Ðz+"/ïvîY cQªiÒ?ĽŸ`þA¨†k�¶R,pOFR4´¬5´)Ü?xg¨ªþÊku3ÙK4èÐ3…M@ª € ¤›#ƒ¿x�sÊé[5fD ¥T×u×u¿õ[¿•R:88¸wï^áõ×_ÿ�ßø�_ø…_¸uëÖáááý¯ÿõ÷~ï÷ÞyçU�L&)¥þÏÿùoüÆo´mcìû¾®kÏ9ÜÅ£ë³~¶( T€2Î'­Xk*õú= 'PþœsÈAJ¶‹À8ßµŒ9 Œ�E�Eîd ¨ Ÿóö‰”�Eh= VAôIKNc:âœsîE¤‹tCZt}IL¤$ÎD@A2.BŤÉ@*¨Ö{\rÎÃ0 e­ Âdlgò %ÀÃçÜ9"=»H2Ï} a< †��äôôÕë—^ó¯Zø÷¼ÿŽè�ùòîj ‚½bá©Þºþêwv÷í¥7~oÖÍmÉbf¤l›) ›º ]ÏúÛ„Oul¯¼iZEa¬PIeæ“j·¹úzSMëvÿäôÁ0¿÷p•¥¬RA–ˆØrµO“¦}ã—®USÄ]P5(:XO(ëc´sî`ã u�Ù�†ŸþÙawog†Ie@¦ 5Qe"@#P£À,TùêÑíryØNn^~+T«4°ð¦" ›/õ֠ι é‹äÌ<†ãÇÌü‡ø‡ßûÞ÷vvvëºþõ_ÿõßýÝß½~ýºªŠÈjµú»÷ïþãü�ó7ó�ÿø�>|à¿ü—ÿòðóoþM¥¬7‚«ª§î²” 4™˜À[(P†ÔÖA~æåؘT˜¢jwxÑxâbZÃ*V)ÆëkÚf3×ç»}€È@FëQ„ëM²}@�Ÿ­ƒšó~–�sÎ�1T•ˆ„9ƒB(…ŒEÁÆd+ ŒQŒ(›ªš�–lÛЃƽÒÛ�ð_1ι¯ÞÙ&Qd�.�1äxôWãIx0ìhÁý“[Óö7¿ñóßyùÕÿvÿÞ_Õ}!Ò®¿"á[×n|÷êõ—ÛÙ,—ðp)‰e 1Æc™Ú£Æù €Ö3B �ß«Ÿ�20¾7B `F9[ÎeÙ#µ’ëýÙ•M¯îõ'8þÃRËÓ>±æ½Ë³K×êé> Ð� j+£�Ȉ›ÑÎ=dÜòDñøÎáé½®ÍWê ˆ (3EpVÀX¡)&T¯Òn÷ ;ùÐöoPœ`0"¡`ì€÷èèÁ�½·wι á‰sŽíXU0v�ú7ÿæßÔuÝ÷=€¾ïÿÝ¿ûwã•Ç¿mÛÀÑÑÑ¿þ×ÿú•W^iÛVUû¾ÿÝßýÝ¿õ·þÖöj¶ñ‰sŠ=Z aP¥±ÏÓ6HXŸsoãõû…'¦„Àˆa¬ë·ÿ  jHË`%X(ŒCvƒL°{Z¸”=ˆÀ$B*Ì»•Ò`èH‹1Xª±vݼi•sψI@sx¿?ºwŒg­Ð€a@ÝŒoÃ#,0°Æ6Ù4`/\:Í÷�î^~xi§E d¬† ŒebÛÑ¡ãÙ•v8ç.”'Î9¶QĶöBUÿ÷À0 "ò{¿÷{«ÕŠ™K)MÓ0óáá!ݸqÀ?ý§ÿô·û·OOOëºþ·ÿößn‡sœí…åÜÅòø©?eP&J@æ±öb½7lŒ žô}‚”¡…ÈŒ¼îˆ…MdB *„D�Æg<Á·`;sÞCylå¹½»g<þFÏ9çÜ &õÃ¬Š³iÛÖ®(“Â:%¶�aÄZ¸wÀÈf«RrŒUÝVÍD%öÅ íÉ2öDá3Ë‹Î9÷ãõæ¤õj 9 më™ ¶ýõò�K3«DóS¾BRKÈ 12±® §Ý¢×�©£„.‰aàqg“=Jv•R6�Ž÷!l›Y}Þ»Nº©ç`3ŠœÓ¡db¶bCQ5íÉ¢HLÌ…HˆÉ”zM©ôºÊ±‚¡7׌m¬V÷óçž 6¶ŒwO—§ËºÚi +PwI²ZmT”`¤ †aX ÙÅ2ÉéÃãùq3»>‘ªÎf‰LAaœùcDŠSóÞsι‹å‰sŽíøñ³E?ýéOû¾¯ª*¥ôk¿ökcGJi Bööö˜y†ªªþößþÛÿàüƒc)åÞ½{ãHóm^âM«Ü…CgJh½]‚ �ÇY<¾K!%3�*�o >çMgp'�z¢x IP€zpõ H´3,�Š’=Éí�½E”ÖiíS'•Ñ6ñQfÎ9÷Âa §ž¦Óƒƒ�®­t‘• àÜGéƒÀ A94Œ  áÁ4QઞìíÈÞ®TÍ")3)x\ƒ3ÖÍ&Ðáœ{>�§Å (©¶ó3 ÈR×OfS‘°\­9Q†Eb”‰Bউ­TªZºUT5 J‚1S‹CX?ÞŸŠì ¸�»� ê0¤ý0„Ê,(‘Y.F™¤ †’ÍTMMˆ10#0Šö€‘ŒabØÆÑKÅ÷ƒ;÷LkÁjž­¨ˆ¥²TŽ¡‰öhzY0ÀÈ %#�F(G@LµdÒ¢yHXH›i3-”× ƒüõ뜻P¾È|U5³1çÈ9‡†aжmÎù•W^#�‚™åœcŒ)¥ªªNOOg³Ùõë×ïß¿_J™N§ãDdÞÚÓ]8|f:·r%@É@ŒñÃmg�'Gë¢�ê�‹’®CÊ �� jŒ�‹±=yNVÀ()ÀÐ (ŠôصŒ7oÞiÈÁ�&»?n³¬;g�{î”3+FcFSf!lšweP€3ûæÎ̾ýÈs½ýVüÅ—ÛXÁ Œc-’ ©b<ãT#UR³iÐñ߈sÎ=ÿTQÐVØßÑiÓŸ†>ÄH”•@P±q“²*¡0ŽY5IäÉŒ÷ö±· Š¥ôÀúú€™A�Â_¬U‹sØB}âr9ŸùÛ³³ª?bü+{ìLõ:A!{ìÙ;»ó™ïkëV{ÔÖõÐõŠ^™â¤2&b\ƒL‹åRJÒ¢Pb5ñcÏ*HdzÙõÈ¢íwyò­×dd´>Ãåu*£mšœ@ÉL�AZ˜ RJ9ŽEŠRÌrIÂãÛÓÂdÄ BÂÙzûBodœsŸM‰ PcŠô]ª¨i&жy«dJÙX’*rÈ8Jh‚hI¹tT“ÁÆxcla Rò�Ã9w±|‘œãlÆØrêôôÀñññßøCU«ªÂ¦ÃÕ8Ìcüx2™0ów¾ó�ßÿýß'¢Åb1†¥”m™ˆs‘1uôà¹qof¢6�6 eP À0«:>ÿí³RÕ …K!*¨Ù*µŠÍØXcÑc.�B…ðD½áXAÇÒXÎ1›ÁlX_e¬õ°ˆ1Py¦ï{Ç'¶ù¾Û7Þ€)¥1[eдn�ÁЭëç2îSúŒ �l½“ÅÎ~—ñRõ-¥�u/5~âÚÖ‚„e`K�˜VÃɥÉýù±–—©¥¡PrMÔ¨ª!™/$vÎ=÷” ‘†åau°sãWéƒ?Î?þÑ/Ý<¸Â'ÇmZ7NT˜‘$Lõ|¹ZŠ\¾ùÒþ/þBß/–¡F[™¢©)2³™*ùœLçžÀX¼Kë0C1Nz'4X!Æ¡@ 2ë6P¤3qÖçD¤…ÇYÌ@´;÷‚8;“c{*Èl|y{µõ&k1 À›Zn%Ûœ\‚ &c�ŽEylcÌàõ e€uû<³n.ž(T c¶zs PZoW!V3*¥˜*ÔŒ –ƒB5!ŒÝ«l¤Q&Sæ@ÊLJ Ëú…VœsŸ‡T¡+�^öê½�0t›×Ü3’fİ�ˆTu¹¤~@‘P7uSχ^ÁàÀë|=Q"À,¾PÇsçÜ…çg%Î=;ÛbŽqöøÊ0Q¬‚Ûºgî¸dNOÔ˜ƒ ëÁãÈÆj`ƒ˜UX·ÊÕñ}¬†Á˜ŒžxÍÜ F0¨�S0,nÆ—�w"¯›üžÓéѶ— ©ª–”ú~•3¥ \sˆ±Ïß ¨+…ôa=gÝÎÔƒlÛÂÛ|r[^1†ö¤5¾¬FlŒ@¦°ªª`cVÄ ßVösNçÜׂEh ¾ti÷�·4ååwn?8Ù!®�Š"ÌHj½YRtË•Îv.½þÊþk¯òþÎP…^U­D"2f(ézáµÀë9œ{Ûâ 9óÂaC9³G„6g;¢l¤ãi¡GEé�´™KacY€Ã'O ³�O¸Ž|âAÌÆëóö}s}}ü×§ƒgS–'`©ÉÛW53(P$! 33«bK$fµ*k1dca¦PÖ›�¦›»¤êg«Î=3ãñ¼žVílÚ'êÄ¡@Æ·‰¤d ,’ «]îb%í´­kêyÙI”ŒŒ H@!$dòùûZ;çÜóÏsçÜ×Þæí¡Y¶\J@Aæ'Ë®·*Òé —�ˆ jíT´Mb±™CòѼéìžÆ/s¨ˆZ!Ú;èÒ€£H0(x01À$Ä_ /�sÎ� #™¤Ò¯ŠÎ¦{»¯¿9áp�âüöíIÓ.SwÚ 9e%æäA¬».ï½þÚÁw¾‰Wn¤IÛÁ ±G©Ær|¤iŒsîg²Í†ý3kñ @±>»(3a¡—±¡Ü£œƒ«Òe@•xì·j`ßüû5³.P>“‘ÐØØvÌ5H„…€j)¹XHÌÅŒKA*dfBET�˜Á† Ì4nçòñIÎ=KdZU˜M¹mt@§eb šd|iUfX_ÔÔ ^Mf¡™UÒ²e3ã±\LÈ@Æôè­¯sÎ](žs8ç¾öPUU¥@1F©fž4{-"Õò@ƒy*(=Z5#{cƒ‚F6và±;€�Ùj÷¨Ÿõºóçº@2 ZbþªÔ‚•IDa¶ñ†ƒfUS�Ï…sÎ} ‡Ø¦l]ék©âîAxU®‡fçÊõ·ÿôOj©š½‰H„Q¯¥òªÏßøK¿<}ù&n]·º:6ëƒG2¶ôØ»n6ýH|çÜ“ú„ ›ÿEa$Ñqìm®Ïg¢Žm—ªq,Á£Ç¯“³ÃWÖØ™‘J©(‘Â@�E�ÈDBˆDd–”SQQw1ˆÀ ›’çpî!­L¦Ü¶vÌKp[Õmô X×Þ 4†㡾Á`Ëu²ßHCJÎöxÏecP`ó’,çÜEã9‡sîkDAgÇ€3°iû®šJ6"¢¬È½ÒýR¥i¯ý»W÷V¶\¦ci(cÝ+Œ °@Flƛْʙ‚t]ìo¶½Åy¬ú7�Ë?û’‡PeVšØAèk]"r0 ©j¦qo¤D© Fæï�s_9›r¡¥• (Îöùµfvãæw¿ýóùáƒ?¸sôð!Œ÷/_yåú-¹²‡IÄn›‚<ÌyÉ P3ÇÒ—`ÜNß$ìܤ¤ØôJà Œ¯)â±ï¦Ñºs§” ¬� 'è&Þ Ûxyv ¶ŸŸ|]=¥®Š@`V@ÙÌ TU�PJÉ9§DÂ1‚YRÉ}ÊU])0#èØÑÖÔ b¾-ܹgƒJJ«vW®Þ˜­ŽÓüÎéb&¼#6Åcc&•1ïç<›Ï®Õ—nîðÄ2z#µuÜ­€ð:ºf6/ÎsÎ]@žs8ç¾&>i|É™Q!cé})¥ ¹Ï ³²×îÌòd((KPiPä dcãi64Vïl�MºÝl€3‘qhƶ›  ¥GÓ&ñ9.�±îgÍH] ޳唿Z¥ÍþIeC+3AÌŠÏÝuÎ}]¬–}UU!6¹ ‹œk²ªm¥i0ôaÿ¥·¾ñ1À(€XK‹.`aº ”+ V( R6öÉñ=ãÎ}c1žÄ|â ÖvS¿Ž»÷MƒªÒz$ÇÙ¡€1L�XÇÝ!ý>îëáÌýÌ'Í DȈ"ؘ ¤ƒ†hQ"ØZ¦`%“‰q*‹žaTÌ@ªâ±´sÏ€‘ž®Ž¦Wn½¾Ÿ:yûôÞñûÊi·ÝÓAmýº#C‹9Tp:ÜߟÑåW®ìßj¹Öžƒå”!mzð8nÓd=éÒO·œsˆçι¯µõyD„ˆ²¦¤9ÔØ¿²³¸û ÐuUJæÈÂh*ªºn5~UØ Ca¤±CÕ:íXw«RV±Ò²*›Ð‚`a0*J¬c�Çç¨é(’ö/í*Ôd²Rúa>ÈiœfÀi¬Ma­ÇB:çÜ×LdLªT˜ £· +dœ.n aeÑAs*:H È!DË̪µÄq>ÇxTBáõدípîIŒ!ÁÖ{íEdÛq,ûÐ��¡ãÿ�˹PÁ™9(ÖSÈ}Æ×ËG2c#@ÆÂŒÌÅìÿ`ïσ&É®ò~ü9çÞ\ªêÝúíu¦gŸ‘Fƒ6¤‘F4²$V± �Cà°M°�°ÿ2^Âñ5ƒCÛ!#ÖH„`´"B‹¥ÑÆÌ¨gé}y—Z3ï½çüþ¸UÙïô,šîéÖôr>jÕÔ[••[UfÞ¼Ï=ÏãPUT© �¤v ö)ø�T[ÒªGU½º˜†"¹"¹À1‘ÌS͉ç †a\TPŽÑµÅ²_¿qy:K§¥Ñt,ÉŽ�#:XQ¨€oýtÏu½µ‹½7 ŠLe¨ aR¨,îfAÊP30 ãªÃtÃ0®,¬EI¾ ‹»y瘬ƒeÔ×­n<||æ|Œ±‰©¨J%ׄvFŽ{ uÊŠ\·Áˆ  $ŠR@J ŠN£ïã€Â R™e u)ÛÂMdè3×9X7F#WT>²£Òœü¤\ÑÝ7ö£Op-!’ª\×Íg†qùC@å�ƒBR!Gì¹mÛT÷KmTÕ‰'"GL!Í„Õ{çœQ4EG®_Ô2kI’DHÏxžëm4Œ+—®EÁ %€TXÅ©°¢”4h…5�æf‰("s"N¤:¯áüÈ5Ÿ¢+ e�(ˆ;_®|‚hCä ï -fº}zöàgfõ"ˆ1ÑÒR÷¾]+»—®»¹HÎGÏÑ3  ˜(rœa—„¢_�ÓÌE_­•7ܹVõzG�ØÿüDD˜9„ÀÌ"R–%€¦iªª�Rʯ?ér™­ýdƹîU Àù$“bÛ¶«½¬Ã n{ÞÚ`O/wŽ X1÷§:Ûœ›‡ŠÏgœA‚*É\ç^\_ªû?zjë©”®LÅ ÞýÕ{£Ñ\Âóšß§}0“£œÀœ—�RÐo¢›Š&aæ¼zÄgÓG Ã0.s Dñ !‰’„„j×h�”“ŽY…ÌžU$@ƒTàœ@BëÕlÙÿ=»‚ù¢Æ3†»G¡³~SÌH¢NƒcPJBÉ´Æx I`b&0ƒƒ¥ÂD$9OÎ%bbfï0³öÉÌ¢oÔC¸àBà8òt„#_Ü|ä‹G∠ÙãRHEJ ÝŒ'·†'<}æðê/Ú»¼ŸG¡�1INœ¹üÆ¥@ ZQS‹¶p®Zs×÷ªµ}7N·ãÃ}±�…élœ¢ÖýÁú®={öïìÂÒ>ÄBÆ¡Q×”ƒB™Û¶Å¼¾æãð Ã0®RÎ[çÈ"GÓ4ùOçÜòòrY–)¥”Ò¡C‡Þþö·�Çã~¿Ÿ'˜N§eY6Mã½!¬­­9rd0ŒF£ãÛÞö¶¬m0sY–D”Ò“·›è‡~è¹ÞW†a<ç<¥…¨R6V�&aDܾ&qˆÁ ŸÇ­0æÅõ §oj~’œF%p ^Ôs$Ȳ<‹Û.Eq¥j¿�+HÅÈœø™�auˆÔsB®CQuÊEÛb¬@1W“æ²k‚†qe@*n~ÖšŸ»ÆÜÎóXbaÍãÁsÜÑN»e%Re…°äÓ¤�äÑå¤fŠbÏ”€¦YoC}ýõõʲ‚)³ZûäŠ�²¨L"�y±`R^®—ãÇ™{äŒLü®rŸ—¾NÙ¥ù§¨ËFRŸ”— nfíã“SkeµºDý»Êq!v’6ŒK† e-C4Ää\á™›y×™«2ˆ "ÑîæÝ-°“E ‚ìºl‚µaW)’CÞiÔu� ;²>1�wN“RʱÙ‘N Ðé�–aÆS ‹±'E§”Mà•”Kð“E\ì0s8;+B[êD)‘TÌERÚ³ZÅG)Û¶|L á*J™b-òM#Ï»ížöQ I‰9Ë0,äUÕÁ“24îhnRÖi¿ž†a—/ (�(["€ÿÜé;_SBâ³£ Bb‘¹Ú¤Ìv&4Œó„tž^FʺðèÀ�¦™9�E ØÞ?úh8|xu<ÙÝ«k¦Ô†4›Iˆ”Ô;®‹:•¦axèá¶m÷÷êš|¡¢ÑÃdŽ+ B.¹ƒt)w V_:l�qæØöö™é’ì]©×d‚0»òXVš$\¸°‚¥OÌUá[Wª"9�7­s­«’Hóñq_ò‘U|"bq¬äVUBî�ÈLR!I @8Ášž†a\þ(AÀ˜Ÿ°ÖyÆü‘ ”O†"('Îj4 �f…CÑ�ƒNá+A�¤g±††qM‘Má÷ÏöY—¥÷HíöæÖ±£³3gÖ•jP˜Žª•²•0mg>Æ:Q_¹²p!îò^RÜ>vÔíZÛ½¶«WÖÓÙ eií“+^ø˜åñ4œ»>•% ™Ä0S— ¯5ÐÀWhâTH@ Q†š»H•£8miÖh�œ—J6.Ç0. ¤(¬Š‰„(²¾AŽØ‘c"8.”# Z@H €I‰³S(æ6†Â*Bùö“•„Lê0 ãêâB|«rÝFêˆ1ŽÇãµµ5eYf=c6›•e©ª9À£(Š,fd�#ÆÈÌYð˜N§½^@J©(ŠñxÜï÷Ÿë}bÆeËÜåÉà®2P¢’e‘Cò°–¹R2?¬€.ŒßU•‚–P"¢\[ÆÊ^¸ˆŒHURrˆ`¡DG Í»¾ä# 3‹Wæ;%¢ª �Ëâ`@Î#àÜ0 ã¹'û$ÌÿÈã… ’ó/• ´3²hî¡¢QÂBïÍäàñ³¦)6lÜ0ΓܙE R�rÀr¯?;sjzüD9 }Wöc@J…÷ˆTùº¨Áª ‚`6kCìZo˜OllŒNœØ}û­X¨Ö2Ù�yå°8ýBsò°ÎãÅ™Ñ4a2šjªêÚUqf') À“ À½7ŒTDš§³Ê—¨ë>$>×›hW-EQH IP%"U¨Æ^9$ 1…Y#88¯ÎÑ“ˆÙt~ÒžÇ�«i†a\¥\ˆÎ‘ ¦ºç«««DÄ9@UƒA~«iš¬shš&¿žÅ�\íQ…ˆ03M&“~¿ODmÛ:çòÜv>¿(äʼnHÛ¶D”óEv’_Ïë|qÙY³’wWN1ÉŠ‘ªæ} Æ("EQä˜w,Ê\ÌÔ˸¶™ß”å?æ €P8Ö¢„H Bd¤y¥.)@¤ ³a’ùÀãsËÄ…$�¦�õQB��‚O­Óšk|EÑÈé3n#’C‚fzÕþõ G—Ü+Á`NÀŽdrÃ0ŒËR0 7Ñù:9ð<öVvšùç[k§O­»ÐråîÜ—ê�S‚ Ãx:”8²¢Žð $EhG“åµ=‡>óÇË›ã]®ÀdÚè¬ê-ÁkäÄ)‘€"�œ'R”U_Bë%¬ÔÕtó¦£fKWÖv�Z±ñ¿W J³ 6e²/ „Ð4Ó^¯ÒPooN–©¿\ak”Px…Äá¬Åël¦4 ï]ˈÚ&ô m“Ê™o•a\”R1|�EZfÖ¶JLŒ¢ä\™IHs×¢ ÑÕ°ÄTÏö­í¼¹6 ø:¸�ãIaæc×S¯ªEQìTºç¹¯?O–%“Üן;ñ»~ÿ¬‘äç�BðìÉ!ê]AI&'¥çeåG"Ò4M.7¹(t"GÛ¶yo0s'áˆH~—ˆ:q(›€åÝÅlW Ã8ç(�ǽ¥ (@ eæŽU;»Òò(µ\½{.Ùw…F$e§”)¿EFT&H…ÒùêéUå)°òaÃ0®8vš–,*0$a‘{ôäÓ?ɉÎ=^üÐlµ`Æ3FH”$×Tñ"q68 w­Tâʨ¥2·¹‘#Lä¡HœuFQQ§à‰¼TÄÃÉ*¤B X¿ö•ÄÎ8ú\AÇ %x°6qÊâ{•ç„á=’‚ÔeÇ�ÎGˆKL%<±¦ÐjŠ…£¢p¬Éj—�E›ê‰UØy;¹h†�{³üø¢X;Z øú¹hgºÙl末ªÊ{ï½Ï½ù¹ !„�;ë;bŒª:�N»W²ÈqæÌ™.Ÿ#=äÞÿ‹X]ÑÍ*¥”…™\<‘óÒsšH^Ûs´�gˆ<Óé4„�·´Ó6bŒÝš8ç¼÷¹´¥ÓŠreÉÎÂÃ0 Ã0 Ã0Œ'…•I™…… Cò¨&´­:n%`çG.Î9FA(=×ÞUŽ<Ø�,œÃ0 Ã0ŒË„‹Vϱ3`¼®ë\ѶmY–Ù'Ê9§ª1ÆìUå½ï’9&“ÉÒÒåœ�¬‹tÃx<®ëúbYW¥”ˆ(«)ι¬¯ìtâbæNk¹Ÿ¨§$vÖ…äEQ^“l¥Õ½›ß:géY ‰1fï/Ã0 Ã0 Ã0Œ'Â:Ï…V°2å¢U€=š)WE›¤u¨@Î"’8%ÒÄ¢³¾173q® $Ä>È ®`_ƒ.šŸ°ñea>⛑E,@™TsjÝ®Ý+«ëÃÓ[£@Sç‹äQ .�³¿æ¿%&T…”@am¹¿¾¶Z0BŒ¤OV%m†a†ñ\pÑtŽŒsNDF£3÷ûý²,shyîÇï:î‹¢PÕápØëõŠ¢XZZúË¿üË¿ú«¿ºîºë<øÒ—¾´×ë…Bý~0tÂÃEYÃ�fñ W�0s.Fy61çT®ì\îl6ËN\�”’õ•¼7²à‘e˜Nw‘,{ä�’'¦‰†a†a†atPÖ7€D¬!$‚à9Iê- ¶¦1!Ií™HÇÄPÊeBŠ<~`((D)û0'fr^Ìü䊂æÞ5Â*B$BqÖÆå]~Ïõk›Ç†£é&1SQ)9ÁŒ¹É•QÐdº%½éúî={ö8&LšÆU,VÏa†aÆåÁÅÔ9Æã13géb8~âŸØÚÚºñÆo»í¶N9H)E‘ÿ\YYùüç?ÿ�þÑ?zßûÞ—+rå€ïüÎïüWÿê_½ìe/�•’‹»Ù]ÍD6ž8Á95Ïœ§¯;éÂ?BYbYYYÉë“­«º Ι[N)‘s&0 Ã0 Ã0 ÃÈÐ| >+BdJ¤Je%QG+{÷Ž�„шƒ”äš]Œòg�ŠS�2@Ò7JiýàMàb–TJ÷ÔcÆe iB@”„ ³0ôVÖ÷víl™Îâ–wuUIKù68ÇÍ'�$N³v¢Ål°âvííÕÌ´�©­]!Ñré Ã0 ø,¸h-’Éd2 z½Þ>ð�ïýÞï½þúë_ö²—½þõ¯ÿÌg> ç^`GÚ6€·¾õ­÷ÜsÏûÞ÷¾¬Ž(Ë2—,üöoÿö×ý×ÿãü�Çã±÷þÑG½Xë)"!„¼BMÓd§¬�9"ªúÄX‘gIvâ !L&“²,ûýþÊÊJ^Dö°êT�3gÎH)Íf³¼ßr‘ÇÅ2ï2 Ã0 Ã0 ãj„Y™””ˆ!-nø _ô®;PíZÕ^5#É+˜Ná…Š8aR†r ä´®¢÷7ÜqêªQUçløþ•ÆBá Íá+€('ò:�:XÃÍÏ;¸z ¯Õ4–ãTL¢o#z‰.¶>´¾iý¬-Æ¡®ßPßtç�åÝ$„VgÄAŸë­3 Ã0 ØsÑê$úýþ‰'~åW~å?ý§ÿtìØ1ƒÁ`<=z;B/rñýÏÿù?í×~-ÆØëõ¦ÓiötšÍfÝÜNž<ù_þË™L&ÿößþÛo¼ñb­'3çB 9tèÐ_þå_~ìc;räÈl6;xðàÝwß}Ï=÷Ü~ûíEQ\˜¨ð­ßú­Oúz6žšÍfÃáðæ›oþÎïüÎ׿þõKKKy·d�#OùÐCÝÿýïyÏ{¶¶¶š¦Ù¿ÿÝwßýÊW¾òöÛo¿€\tÃ0 Ã0 Ã0®²ë€DH!(!‹"‰œÇúš[[ ãq�z®ð¤,‰•!ežs8%�‹¾@o)z*o¼ ý~hgì �Á¢§¯8P€³Ü¤îUÍhÔï/ï¿…‡ÃåÑd(md/mã� a…ƒrÀ Ù{Ûõ×ÝêR…‰NM…%iy¨Õs†a†ñÜs!:Çx< “É$'FtOßó=ßsß}÷åþúº®s¥ÂÊÊÊx<îõz¹—¿( þð‡ßúÖ·æçÓ逈ìÚµëÆowúôé_ú¥_zë[ßú?ð)%f>'«£mÛ㡪mÛVU•-°òNxà�bŒ«««ù³1Ʋ,ó»Ãá0 [[[ªº´´ Oã½Ïkò«¿ú«¿÷{¿GDgΜٻwoJ顇zä‘G~ï÷~ﵯ}í?ù'ÿ¤ QO)yïó>ÉyïÏõoÉ0 Ã0 Ã0Œç˜y9#1„ €S�"…”ˆ\Q¸ûå[î“�mn†éìàÚŠ‹‡&…˜D’ªcï\©¾ IO6M±^¼èU¯D]g³Æ)©°ó+Zq@)«X‰š¸àQÛÔ\Ýz×êúÞ•‡:|üÑ�‚)EŸ=“‰Õ{ø (ã×¾þyÉaZHâ&ú)¼2sÂ<òÃ0 Ã0 ã9çBF^䚌~¿ïœ !äP�û±»ï¾ûªªÊÚÃl6›Íf/yÉK®¿þú�AâιÉdò ¿ð ËËËYBX^^¾ûî»?ò‘�<ôÐCüà766þ×ÿú_·Ýv[ž~<¿ýío¿ÿþû±£$?f™ä|É‘?ó3?óÎw¾³«±8xðà®]»Š¢˜L&kkk¿û»¿ûþÃèê9r#¯[ÿnò“ΉKU777Uu{{Û{¿ººš“ØË²Ì‘$EQ0sÎ]ÏžTmÛ:ç:AèçþçÿäOþd6›�8qbmmÍ9cL)9çF£Ñç?ÿùŸþéŸÞÜÜÌ‹Î~VyÇšÈa†a†a�ë9€’ A¨ªªMÒ63Tõêí·_÷âñÞ½G&“SãÙ(j,kî/ó`-½Í¤Ç&ÓMÇ«·ÜrãK_ŒûÁÔ0QQ&ëÒ¾!Êäêžüߤm¤©mR�Á^zÞ‹o¸ço¿xÏmƒ•›ÊúªýºzSï¦_ÿ⯹õÕßð¼¦DS…PŒb1N®I• d•†a†a\.\H=ÇÎàî¶m‹¢x÷»ßý‹¿ø‹bŒMÓÜu×]?ó3?óõ_ÿõNŸ>�§Œ1feâsŸûÜ;ÞñŽ\âP–åm·Ýöá8 Æãñ›ßüæïÿþï¿ûî»?ùÉO¦”öíÛ÷c?öcögÖ•>tŸíâÄŸ9ªúàƒþéŸþéd2©ëúÞ{ïý†oø†»îº+ÆxôèÑw¼ãýèGÏœ9ó¡}èå/ùßøFéDÎ9É+�«X:ã©<‡ªªœs÷Þ{ïWõW/--Å«ªÊU Ì윛N§)¥n¸!›P¥”r$ÉÇ?þñ÷¾÷½£ÑÈ9÷¦7½éïü�¿³ÿþªª:ôÞ÷¾÷7ó7|ðÁGyä#ùÈ7~ã7vÛb‰†a†a†a,@b%Qb§â^à=v�&W뽕½3_|�Bh›vÚ†"\Qù¥Õ¢ªhyeÏ îÄ­·¢òcI(‹¢(c›ìöã C´#;^I¬BŽ™I£´qľ¬Ö‹¥ë×ï‰mƒ¡ òð´@¦êfê‚RH, (1+[¹a†a— ç­sd‹$Uͺ…÷>¥ô³?û³“Éd×®]Ãáð«¾ê«>üáŸüðÃ7ß|sD$×4ˆÈùvô3óÏüÌÏäÜ‹—¾ô¥ÿàüƒµµ5EQÜvÛm?ôC?ôÎw¾óøÀÆÆÆÛßþö¯ùš¯©ë:/¨ÓTrýÊÎ'ùyJéÈ‘#Óé4ÆxóÍ7¿ô¥/ÍBH^áîùÎ=™— @Uîç~®ªªº®o¾ùæþáΆ`Dtë­·¾éMojšæ=ïy�÷þ�þè�^ö²—8pÀ{Ÿ£Ë/@ì1 Ã0 Ã0 㪄T@P!ÎÔ^Ä R“Ê¢ŠµŸJ,UÊÝë»î*V÷î=óðÃq8no·Ó/-¯–»w÷WVú7Äîݨ‹i3G¾¨SœÎJÑ"�/Ês÷*BþI�TA‘ — Ó&LgÉ¡JIØ×å’¯=TÐFŒB“QÕ'p£@0)#9˜Îa†aÆeÃy7R»~ùN`øìg?ûþ÷¿yyysssiiéþàäl‰ÕÕÕó™O~ò“Ø)œ<©Žb†a†aÆ5Í;²•æ±äNá1”µåh5¥Õ¢ìÛÃkk{n¼QÄU¡(Q(Ceã„T�I$\9owWOþ� DäI© ïYUEb“Ú¤ ™LgÈ;P©uωN@”beh-"¤¬�†a†a<·œw3µ ¥Èë³Ùì}ï{Ÿˆ ‡CUýoÿí¿åxmι¦if³€\àôéÓŸþô§s9€üÁÌyÝι£G�ªêñãÇxï———ÿþßÿû9»¢ßï¿ï}ïëd,Ü¢. sÿýïV\®¿þúÛo¿=rÔu]UU¯×‹1^wÝu7ÝtSaïÞ½ï~÷»wšVíô°ÊUD´³hãØ±cgΜ !¬­­…ž(ÆtÓ7M3™Lò§–––þäOþdÏž=mÛƒ¾ð…!„S§Nå ŸL&)¥½{÷¾ð…/\YY!¢�üã1Æœ²sž†a†a†a\Ó�¢$J ¬p§(ØÅ(ã6ŒIfe1ªŠ!ó¶Ê´î5Ëý¸kMÖ×em­íc–ÍØœŽíq ã’iЃ/Ú&jˆƒ¢"}öki|Ù`ÖÎ]ŠiGùEŽ� ‚´‰ A!TƵ½½•]eo…‹Z¸ˆà¨. EuB,HÁR°”+ŠÔnE Ã0 ø,¸�FIÛ¶]CŒñCúeª7¼á eYžò‘�d…cmm­(Š—¼ä%½^o{{Àu×]GDû÷ïϳ°oß¾w1™L>ñ‰O0s׳Á¹<ðÀh4ÚØØøº¯ûºªªúý>€cÇŽ>|¸ªª,K|Û·}ÛéÓ§Ïœ9sêÔ©áp˜µ–¬ÇìÔ9°#�<¯óÉ“'³ÈqË-·E‘W²mÛ¶mSJYöÈ‹è=�sùÈGD¤ßï¿æ5¯É»kÏž=Ýló|¾ê«¾êرc«««ûØÇbŒæUe†a†aÆ“@ Ò<Êž NÁÏ…$´ª©,B]Nˆ¶RÚ¶úÕéº:V¸£$GINyÞ¨‹Q¿Þr˜”¾­|dV p®PÒКÎqu@ŽÉ1B)HÛ¦&È, =~â‘Ó›G'Ó­$ ¼ÂÑÈ*DêY<Dzˆ•K©Ý–†a†qYpÞÖO"’ —š¦)ËriiéÑG !œ>}úÖ[o ¹"ÆØ…gˆHŒ1ê½ï}/çÜæææ[Þò–llU×õl6«ë:—‰äËË˹(d0=z€ªîÌ¿yä‘Á` ªÏþóOž<¹wïÞétzàÀ�në¦ÓéË_þò\�1�NG£QQÙHj§´°³ $»W…†Ã!3÷z½¢(¦Ó©s®,Ëη*˜çÄrç\~quuu8nmmÍf³²,_ýêW‡Š¢H)©ª÷>×ÇŒÇãW½êUëëëEQ|þóŸ�1æó\V’R²@rÃ0 Ã0 øÖQV*NÎŽ³�,à8:PÁÞSPi¢ΗËõ($eò…weé@€AUëþ©†¦�µm�«^UiF£Q5¨/ñ&xJyUÀ(,`(�‚’P@ :W]H šGQš_çÅdç}™»ñóròc×±ÿ¸· ¬Êÿ$—PP^®ò㥀\sƒÎîI ²X1>»”³fP¤Lšß|ÜëÏy‚ ÁÊBÒL[çÈ9GäIU&•zeMD$±Šh ÊÎĬàùÎV7ß�¤8Ï•1 ã<éÎL Ýq£'LóD²t>uÌ'Vpwäšn}�@ ‚Ê O€B@$óß43Bã*à¼ufΚDUUMÓTUuäÈ‘\èpÇwˆHv…ÊRD!÷ògÝBUÿ÷?goxÃÞ�»éE¤®ë,o„ʲ̒€÷þàÁƒGŽ�Ç]¹÷~<<^xx"YÉ‹È9Ÿþô§s.HUUû÷ïÏBÖ0òê1s¿ßÏ¢EŽøþÌg>ó†7¼!k]A ç\®kñÞg�á�(Ë2¥ô¼ç=o2™üÙŸýÙ'>ñ‰ÍÍÍ/|á KKK·ß~ûóŸÿüoû¶o[YY)Š"˜O§Óº®}ôÑ”R)ÉJå#yY9§½m[fÞÞÞ¾ùæ›ÿâ/þâk¿ök‹¢ÈiðÝ&ç2šªªÆãñöööêêj®Œy"mÛ®­­�:u*KPgΜɦX—•–ÒüBÎ:ÿ%H n‘Ô€sŽEŸjc/CBàlƒ+eY:çZ‘—ùöíBŠÂ‰|¤0e`3�Nóó”’÷3BŠDÄt^ß/{Wº‚ê…\1ƺºìÂ' Èfnó} ÔuícДžùþÌSòüö’¬ee°sŽˆÚ¶­  ªƒ%טY-zÑx®É×ÙnlA¡®ëÂeu>7Œkç\J©«o&¢ÜhÌEÆq!È; Tq‚Ä¢^fN%q)(•9&F’J ¥`Þe€((€ZKçJRH“Hyi°’Xη«ý™“óD0AHD-)«,�Ùya&aœr‘’„¢(T’…& 1³;Ûî%ÁÜÅ+óä×Gç\¾zv·�eY†Sߦ ƒ±È>Qr'QAqŠDª}¿93Š•ÞŠ´<Ü3Ü®•]�‡ª©?¨˜uÜ ‰t0èGI“¶�J.Íbí‹^éChÔAHqÂ,pÊYºÀý¿h3&öÞ²Ø+Ý>¤lqÅp @A�2¡œ÷�2ƒEb%k_.v¶os7TînjÛö¹^µK�(¤PR‰WÊýŒùÙ^æ:éüH¥Å[i·³'.@I”¸;‡°ŠIW+JX ¬‘Th~¦®Àó4Œú«…Â×1IíÖq膕g«ü�6Ïœ.�‹qá;_1ŒLþmTU•»2r7û³ÿ©\HewiÉO677s÷â¾}ûr‘€¼r¹#Þ{Ÿ‘Ï}îsãñx:�¨ëúî»ïÎL]×]°yW'‘ß yúÜw™ÉÊDNËxš:†.J¤+ž˜N§ùB˜ µÎùl×I`mmm{{;‡“ïÜäîï$,ÂÆ�?îœËjÊOþäO>ú裧OŸÞ½{wþæ>ÿùÏÿÍßüÍoýÖoýè�þèßøÆét: z½žªfÕ'/½ßïŸs*éÄ•üîd2ÉE';Ñ™y:�öz½,2‰È/ÿò/ÿæoþæææfvÇz"¯|å+ú§úÀ�ùû–[névþ僀Ë"Ç\çP%4)z_„Ø+�wQAŒ$kkk£çz�Ÿ!ËËËX[[ïMA³^¼ãÂã쨴/ )ꡈ\�±•O"’VVVÖŠ5^_w²NÄDˆ’qt^‡<…ä@ˆXˆ—yÏõþ{òê±£’ʺ®ûžƒ9w^:GãÇ’ý‘à hŒº®½÷¡_èa‰–ʲg:‡ñœ“Eý;REd§ nÆsKn+vÇinC>};Ö0. RZ´™!¬I�výÙ 0ƒÌ‹!6òdí%^T0Ìß욨çÓ^=_tÑoç €°0(‚&€CZR‡…¢ö®œ©¦Na×®]k+k€eO½•©"r�Û&�€\Ûñäíá\"߉‘ùn±&�s\v›Wp@ ‰TónÎûJ�6izp÷ n* >÷×–8xÀïZÉ×f–Ú^Éê=í‹$.˜V@"±jLœç<‰ß±ôËë®Í0¾lt¶Þ]W’s®ªª<öªC@¢P€N1w²4aq‚–\Æsó¬l`10/8ƒ.ªÛœ�N®^”¿k—Ç (  uÀ苲ۨˊ©Z–YJ¡Y_^/û»ž½Î±3\Ù{Ÿ;Š/·qÕÆsNNdÈŠuîÓ8'âú¸�Yt·dEQ¨êx<î‚+²‡3;çòZîT/þìÏþ,�¸¯ªêàÁƒ_ñ_¡ª¹€£išº®wú/å�ä­ÅBÛÈïvnQOsxŽÎ¡ª£Ñ¨ü˲ì×®¬$7mSJûöíÛØØðÞ�F£n¹]úzNÚè>Þ4�sîÑGÍ â¶m?ûÙÏîÙ³gmm-oÚp8lš†ˆ†ÃáþÏÿù�ø¡ú!³Ù¬ªªÑh”ZÅÒÒR¾ÎsÞÙ{åœ[^^>s挈ŒF£nWäýÐëõ²ô’'>vìØöövÒû¤;çôéÓëëëy¶Ý—•¿…gÿ«ºˆÌ/Ç;Ï«DD(|¡@á Á ñ•ÕYÀLÞ$� ›¯<áü®" bfp�"ÿzóA§ªòð´¸�8vÎïU–YmÊë{Yë1Æ”’È\ùóy�s~<_ š·Ïþ—ò_ò^�QÅ©SPVÕìRøèœsÝÌ…†ÏõJ†ñ8:Ý1ß4bÇ‘k:Û«E 9�€ùOÎåwÀPî¤ ÞÙöÄ>áÉ%mÿ,ºãó- ÀuëO �$·qç#]À¹m  ðÅ|b=g¦ÝŒŸ|廫g¾Í×S] “&Ú±rܼºÁ�Š «ˆH-ãððÅÉöééxccc½¿|Ã`ù–ÁÊó=ï*]¥hF¡žÅ�s·#�! fy/¾Ì/Çþ7ŒË™|=;ÙZãÂúa¯ÜüÜ£Œ…÷²ÞªçœÉæex˜ë°‹§tî™�Òâ”z¾ÝÆ•Åâ¢áºCï AI¨-³¬y=Ý+xÔ]õÙü2:£‘Üèµ›SãI¹Dã2/$ŸãœRÁÁ`�‹ ¾ð…/`Qx’&òÄÙ– ÀüÁtÂà«_ýj9Æ;¡Üçž_ !?~3ç|ò®G�WŸf=»>Y™ÍfùSEQ<ñHë¦L)­®®æ2¤“LºyîQòØ�ìuòäÉÕÕÕ¿øÅßñßñªW½Ê{?™LŽ?þ×ý×÷Ýwßp8<|øðþáÞrË-ßð ß�#IvÖsœ³Â]§U~¥×ëeE$W™d…£Ñ�•’NÉZÎSù!ä±ÿ�X^\.¬¹¿³ C»“ñ|üÔüåÅP*J’˜IJ%éÊñ­jÛ)A„„Ä ‰Ñ•Šó©çH”$Â?în'‡Ü$¤<èKªI Þñy~¿ç L Õí2ú‘dd‘�@´ÛÎóÙàn¼ ©B‹A{ª ùE"¢;Ï:ªÏüû2ŒKÄ9íÈ�þs½j†aœKnÝÙqj\:r#yQŸ¡<ϹÈÍ𷍕æ•‹ÓüÃóÙñ§€8üÕ.åB/áxÌ<€"aQ¾œoÒŽ*ZV…€Ž8IóF¯xF’ä8÷„.¦ž·^³9×S6ew˜Ý±I@.�ÉŸì>ëbŸæu†Ê¼�¬ŒVq,à Múóc‡>ôØ¡¦[“Ò‘c�¶ƒIs“ïý­}7¾æ–çåu+ëK…(’Hò¹w))R@å J4�ê0A¡]CÜNƵK¢zö ]´„Ÿëõº[ª;ηùàß‘ ´ƒîT®ÙOOÒ""ˆÎ�º RØùäjeGI�JªóÞ �ªD…zngŽÂ²„•†ZÏ»Øíèqíê9Î÷øÊiî8ÝÙm{U§ÆóD--=KëªóÖ9ÎQËSJ·Þzë'?ùɪªî¿ÿ~]ßzg­• Nž<ùá8÷Å·mûíßþíynÙŠ«KõÀ¢(Ä{¿µµuìØ±^¯7�N<¸SÉjÊsø}äUÍÃt:�1?~<Æøüç?ÿž{îyë[ßš5ƒ¦i¼÷·Þzë­·ÞzàÀ�ßø�ßÈ¡ ¿ök¿ö†7¼á"Öm�cQ’T¶··ŸJË{¯ªª”RÓ4Oeou™CDó! D¸¢Æqpv xöšñK˜;V%¤¤‰¹Ì¦Å´cG]ªHqrv>—ånfÀ{ïTÉ1IDyw/¢y´žsEéÄÍ¡óË;1ŒKB×½NÃ0ì¨Ðí �íNϸt¤…ç\¶P�2 �…Jñ$¶žrîóîÃÌûÎæ¡Ó] ö%�tÑŸ·È Wq.~V€s:1��"ˆ� ÙrŠŸýÕ°+b~";÷)ºxq%Î+×:L€“Àÿ}xû?ùWŸØ:±µÒß^Ìâ U…ž+]5œ¶�}ñ��;þµ/zéŸwÃó�5O¾qhžç…ŹŽD�šrvd¶�=Œk—ÎÆ½u¾Ó~üªc§ �™ûS=q*œ}c1 ->ÑÝ´*�æiC‹¿Œ«}ÜÏcqMg".¨Š¨ ¬.÷nˆhf±.Šý”Ó;ò´ Ç [ò9WÒÜ[e…ÆNvîïBž}+îBtŽÎ剙cŒ÷ÜsÏÇ?þñ}|ÿý÷¿ð…/ì* ²“»Ú?ò‘�ŒF#ï}–+þößþÛ9Ü@¶Kê’Æ;O®¿ø‹¿Àâ¸úНøŠÙl–½óš<½BpNˆH~R×u^óÂ9 Þ;§tÎmmmu†�;£2º'“ɤÓ²§ÖOüÄOôûýœ^×õöööÒÒRUUmÛæx’¯þꯎ1þôOÿtùä'?ù‚¼`0äb—ì@uÎRò¾êÆýuù"�‹—ªæ}ÕÅxL§Ó~¿ÿu_÷u_ù•_Bx*‹¡,·ŒF£œ2™LÆãq7çË%$xNeG¹$DÆŒ—€IDATB„ú²h›ié¼ RsL¹2æŠ Æˆ¦iœÎ* LiÊ}øFšgž+H �”¨Ašj’MáˆD1ÆMl'K]u8GOî¾ü”0´ ×ZtÊ\Þ¥­¹„¹mÛ™b:ƒùò9¼)+ŠDH¬N\=uMÓ¤Ty…*bŒµ#ï+Ëç0žsò… (Š®â°mÛ£ùŸÆåC�Ò5bSJ!„ìõú\¯šqµ¡„�ïUHáTp²ˆ—ÈvU¹_>"@ ±«áÈÁÚPÎ!Û* %Õ·�œjÊtIK:H„À*³”€€(‹xrˆn2ÓF¢²óD‘´œMÃtÖDD«’›&:NDNÎVoœÍ!—§iŠ¢èîó cJ‰Ü㦢—}nm X â>ìð�Ƕ?ø™ÿ÷éÍ3[½A¬„ºHÞ‡~Ovg6>º±yôÁÏ~qëÔ?xÉK^Tr¤ñ´×ëaÚN ­Dc;¡Ë&Å3oÜÆÕ‡ˆôz½®/,g—^­Ã}H™sšB–~IH$J�£ËÜ�(ŸØ!$] H.Ž#Ï_˜+Dz�=æ'|\Ž®ÔÆ³GÁ€)‘s²:€¬¹p«Ë׿ðÎ×DzÁTN­ö®›Î4¦i>¾º¾Ä®gò™“;u;U#„Ð4M¡k nFùžø»tígÃ…ˆiY…Ë�žÞû7¼á ¿ø‹¿˜û÷ßö¶·½ímoÛ©Xä•ÞÚÚúÕ_ýÕn3¾æk¾f×®]Ý4]UÔÎëÓÆÆÆý¯ÿ5+ DôÆ7¾1vt«‘-›žFÌ3ìú}˜yii)®mÛ¶mÛ¥YäÇn5œs'NœÈRMÖ²CÔN!$‹ù65çs¬¬¬ä‰3� ²³âæÞ{ï}Ç;ÞqôèQUý£?ú£W¼âªº´´”šR�F;´ºUÊˇy´ÂÒÒR^¥ügÞÒ¶m»®W¾ò•xÚ¢0":zôèp8Ü·o_ž�ˆ”e™óH.¾¤ÎÚYËÎG-ˆË$“Éä¹^ågJ³ÙHÚi«œ¦‘Ë4aIt¾:‰keB!†4É>Î9Uš0 SŒFŽÈ1#©éùê…ïû’Ýâ¨%½ ‹ô¬oå£r6k¦ÓiR½(:Å¥¶mSò"ˆš´mãã4v.˜Îa<ç8çröxY–ªÚ¶ít:mÛöª¼ß3Œ+”ܪÌNâyÀÍl6{ª5Ãx6(å¼Q°Â)XÀ€“yœxn·$b¥÷ÍJBH]?é\çe�C,ô8ß*§|)skeÞ&…:NHÁc(ǘ‰úQã§’¸  ªõtÜN&3h+B¡¥¶ La¡s,x}y9{2ßiçq3¹_†ÈÍGGá¬þ ±‡ó>OÄÂ8ÖÇÿïÌäþæs�9Úß»»¿¶v|8L3,/£`2Öíá§pŒÝ«ÛžgÛ'¯ÿì§ŠÛŸ×Ò4¢I5l…q�!ç³"˜›“:Œk—Üîõó FšL&“Éäúa¯:QYEž×º æg¤ÜG 8Ÿ£äð¥|¢Îî<¯Ãë¼9ÏAMç¸z9«s �"kB¾¢€£09”µôöݱ²R â4œ^®w�OÅBÆ;û!±0¡:¯Eg=#ÇçÄg³YÓ4¹£æ¹Þ+ÆeÄ9uY–u]?KÓ*<�£«¾ùË_^–e۶ι_ú¥_ú±û±o¼1O )ýìg?û®w½ ‹¢Â{ï½7 mÛÖuÝi݆:ôðƒÁ gH¼öµ¯í\ávº1> OÔ9r¾…ˆÄó0º�2ÉNÕhss3ß‘æú†®²+­èŒ³êºÎ1ùã¹tcccc§�“ælÏuûí·ñ‹_Ìß_Ó4ù õ“É$‹%;CA:�c2™tõy•v>æ‘ìÙ.,ë`O¬Y9‡›o¾y<oll¬¯¯÷ûýñx|YÕ‘)ÍoƲÈÑ$*�Tvˆ~pÄtÕ«–e çæ™b99œç›óÌï[HÑï 8HtÓÄœÉü3¨ªÊ{Ÿˆ0ßEùvLèü¤QUbœM9¾<}6pÎyUöäÕóbo0ÑyéX´þHYÁJPV^$\fI–‰eaË̦sÏ9Ýð‡îùNñÞ0ŒË�nŒ_ÈoÇ©qÑ™·g9¼›NÑýâHÄBY¡ì0(�ùòâÅÄ;#¸çsÖ³ž'—pH"a8&(È+£òu�‰J§5¥¾ RS:®¹t#_³�8;zœµý\#xJò5ôçUu.‹C‹6 )s7DZ9+`JŒYY¾ÿÁ�=âÂdmyB“‰úŠ *d8Eo€Á2¤"HSj¾8ÚþУ£—<¸w­ç Y„5ŠÒ9f�_Jâ‘‹jÎã~Á0®2ò8ñ.Ù´‹¸Z¯§]RP>ö¡ Ýc~FšŸ’ ,`xQ¸6/åX¨;μ812Ï¥Žçz#�K3X²îELPR°’—¾¨«¢¨(Êl»Ñ©«P퉞çraƒçºËh×qw9ÆÕMNpQÕ|2ÏÂØ³Ÿí…\ ªª !d]Àž={Þüæ7È•¯}ík?øÁÈ9äιÏ}îsozÓ›ˆhee@]×oyË[v^‡r¹ªfŸ%yøá‡ßð†7tó|ýë_Ÿeƒügglõô�ò]5I7å‹^ô¢”R¶ÕšN§[[[;§Ïj=öØc»wï!„n¾ùæÉdREÖE:Û+YNhÛ6/k<caÒ•ë-:Û¨|g›%Íååå•••áp8�NóÜ}ûö1óæææÒÒÒææ&€¼+òZåºeYnmm ƒÇ{ì®»îê,¿°$X×ug–Ÿ<½ÈQUÕÖÖ3///·mB¸‚t‚�fbªšBWÐú«*Ú€÷¾Ë³‰çŸ£žÝiòÕbg qV×T5LËzÛ\Tòg �ìS×­ðe….lÜdá’ÏQkþù@.Š"F!"ï}Ó$+º4.òµ)>�G\V¢µa¹ñ¹óJ½3�Ü0."¤`ˆSÉFUúíoû�ÿø�ç.Ú'N,//ÿüÏÿüÅÚ�7ÜpÃ#�<2›Íþê¯þ꛾雦Ói¯×�Ç"²¼¼<�TukkëÑGí÷û»víºí¶Ûº.ήÌ*ëιÙl–�ÕñxÜuzŠHvÄêz�r—SÞÆ3gÎÑÍ7ß|êÔ©¼ù»wïÞ»woJi{{ûÓŸþô-·ÜR–eWª“«=f³ÙûÞ÷¾ÕÕÕ”Ò 7ܰk×®ÜþΞWv¾0 Ã0 Ã0  “Ü¿°£‚ȹq3‹”¸ð½^/Bgí´mg»–W MÔ�³ƒ" ‘ #!‡¾_†ì'`\¾ò•Æà¸¾~ßó[,3zS^Z[Ú_•=‚K"ªP!⋘'ÇÝÐ@!Yì^P:/Q½g"nCjHÛ6úè£xë[ßší­bŒ_ù•_ùÁ~ðèÑ£øÀ¾ã;¾#W'”e™‡ägo«O|âιápøÊW¾²×ëeC°œ_²3ÒÃ0 Ã0 Ã0ŒkÚa©)@v+ÑlrÂ$ª$OÎQÒ½†‚U†[%9çœç‚H%¦Ô†µªzp9" ª ˆ2±B/iiïÎð�¼)ª$ �Ç’Dƒ¥=_ýªo¨–cíªNöÖE Õ³æÆª9‚�70èºö.�çæ¬pÌ1µÙ•®I"¥o˜;~";—( ¹ƒ¡ Í�ðâ²›¾‚À#r�G[M¸¾(R;#J¢ qö­J@t®—†q Ñ4³Á`àê¥é°‘À*W†Ì  (D•ˆJr`‡V¦’‚FG®(­d¯E¿ö\ª&¹:}¾ŒÇCùz§g¯†;¯"‹«-1\VÓs±Çs½Ö†ñ¬¸@�£išœþÔeBüÈ�üÈt:ý—ÿò_樦ir_|.€ÈéÖ)¥ÿþßÿûóž÷¼BQ]o¾ªþ�ÿñ?ÞùÎwfßžÎiª(Š{î¹ç§~ê§.bXͽ÷ÞûḮëÇ?ôÐC·ÝvÛt:ÍÚÌ™3gÖ××Üwß} !¼îu¯ë2LDïyÏ{Þô¦7Ýzë­;} ò§öíÛ÷¹Ï}î _øÂž={š¦¹ãŽ;²>á½Å+^ñž÷¼gß¾}‡:|øðÁƒóG:Me:�:tèäÉ“Þû{Ú|)ó.Ã0 Ã0 Ã0®M:‘CIB’ºðÄ.¶MšÅÂÑÀ»Ê•UJMRmHìP”¨ýl<%¯É+ˆDEˆÈ‘ÿrÔ‘/úßΦk$Ìð®nS Ób×ÒM\¶i¶Än—”%““bò�×óEq³É±%ó¼_Êé²p”‚ÆäˆóM±«*0mL&i×’2ΖnÌãL„•çÞSÚ�ªåÄšÊÞxk”µ«X†ªçR›«7ˆ4§ªˆ )„®Z—Ã0Ρp)q*z\e¯P„- 7u2lR›Ú¶_ùþRoy¥¬ûX]í5©nÂl.PWKAš¦™ºb‘¸I€4‡–[8ÇÕÍ¿ñIÜ&ó[u¤ GJºì,Ê ã|¹@·K×X^^ ")¥ñ/þÅŸÿùŸ¿èE/‘½{÷N§ÓÂêê*€¾}û~ë·~ëïþÝ¿[EQ“ÉÄ9—EŽwnQ:ï•@ààÊÂq9›Pj—‡§Ëá©z¼Qj¬RTäbw"‰z¶èd‡1˳N‘Çw ’‚”VâDœˆ#Sd1hì^P&x™‚!æ©ç™£DpetUD•P œdc+Î}O NŒÈˆŒÄYk1 ãꇔ—ªA¥á©&¾˜�ÄcŸ™ýÍ_{ä›bó±On=òÿ6ýÄ©ÇþßéÇ>¹õȧ¶¶Ž‚# Š%ŸZõTV¾’,m”TçQC²n�«J8›ÏÁ;�" ‰�Ñ*9Œ«ƒó.ÈÕý~¿‹…èFʨê ^ð‚O}êSýèGù—ùøñãÃáPUï¼óÎ{î¹çû¿ÿûUu2™ôûý¶m»Þÿ<â&‡¼9皦é÷û/|á üÇü»¾ë»L§Óº®/–ÅjJé~àþõ¿þ×›››ŸúÔ§~ÿ÷ÿ›¾é›úý~!Æøÿïÿ}×»ÞED[[[o~󛻕̺Âp8üÙŸýÙÓ§Ogµã~áF£QVzöîÝûÍßüÍ>ø ˆüŸÿóŽ;öíßþí/yÉKr�ÈC=ôÙÏ~öw~çw:`ß¾}ßõ]ßµ¾¾Þ¶m.éX[[{ó›ßü¶·½­išûî»ouuõ-oyËêê*M§Óûî»ï·~ë·f³YJéÞ{ï=pà@—±œwWg#f†a†aÆ5‹Î]* „D�œ›M Ç@Ò6=‘¾w˜¶ÍÑc§z >ìf³¦mÛ”Àå°îŸ P÷o~ÑW`i ++eU%B‚¶Ò*1à.x´Ü3 �*¥y¦Ð‰·íLRåyÀÔëùuŠ}¿t°ðåx¼ D rÌèªêŸnÏ®7GIA`�Û§“wMˆMAƒ¥êòÊ•�ù i9k“ëBæBÀ)híëžx?MEDtà(1ç$y%BLR$K6ŒkR´£¶�ªè-Ç1=4;þÐöèD’¦ P8!§ê‘¨‰ÍTâéi*F›Ã7ÞµÿúVúeo46‘**«ž œ�©Šâȯ $Ю㷫’Œ.V0à P“:Œ+ŸóÖ9vÖÿæñü¢ª¶m»k×./yÉK~á~@ö§Ê‘ã�>úè�7ÞØï÷SJ9d;×pÔu-"wÜqÇk_ûÚ•••oüÆo¼å–[ÞøÆ76M3�˲ÌþWË�)„ðªW½ê[¾å[>ð� ‡Ãßø�ßøð‡?|ë­·ŠÈ¡C‡Æãñ#�œí¤êº®ëz:�EÁÌ×]wÝOþäO8p@Nþ˜ÍfY !üäOþdÎ)!¢ÉdòÀŒF£”Ò`0¸ãŽ;^ô¢}ï÷~ïúúúl6Ë[Ñï÷˲lš&ï(ƒ,ÌùîîlY:]y½€à»ª=è¼ãüd1ìK>ày”b"€Åð4" ¤°Â+q¢ù]�a†a†a<ÎñV˜ DzΊÇûÄ'&'N^W×{ê§€„ƒ£ÈÌ•÷WúÔ'Ön¾©r¨ªÂûÝuéA®YºÅæE)¹�†Å ¡`׆–*xÏÞõªÒ/õ0Á9Êc“³I€ˆ8—ï+Ÿ0.u~p!ãU BÈ)â %‰ûQMµç>Ä{¾mÏÞúðÑ*¥D”‘YÁ Ꜭ ]$,@R„x�¦çõʵÒvT�Ó¶-*&…�€UHB ( Á]ÂbÃ0.'HVz™…�ÇÚC÷›�ÔÝõþR–›aªœERh®|cï]¿&IXßxl›Òñªì¯îwMðM˜•ÅÙ’²ºV~ÆåŽr.<÷»V^Dq°P¾®Ë¥¬Ô4Œ/¢sÔuýTou‚„s®×ëaà‘;âsùBþx~—ˆ–––°#�#?Ù³gÏçy±È+ðƒ?øƒ¯{ÝëþüÏÿücûØÑ£GÛ¶½óÎ;_ñŠW|ÕW}ÕwÜQE®Ò(Ërsss0EqäÈ‘<úè£UUE±±±±ÿþ¼-¹>Ú{ÿMßôM/ùË?þñ�üãÿâ¿8�–––ʲ|Å+^q÷Ýw¿üå/Ïsº¤“¼s~à~àÕ¯~õ_ÿõ_ðƒ�ÇÞû½{÷¾ä%/yÅ+^qç�wæ]‘×??ÏòÒÅÝ?W.¤ðŽà”kÕõîh<ÀÌm õ<ïròôº£�þéØÍ � ° „*(�áHKA‘PE€øó–] Ã0 Ã0 c'BÊL€äNvÀ ‰©„'OÜÿ¡¬¥°¿ruj%D(e«'°¨†¶Lí]»V‡[››Ÿ½º±±ï5÷+û¦۾׋”.¥«»ìì�!Ê�’H]û¶¼×ÐDïxÒ És’°°à@9à "Ç®°’äL†ø„-QX¢HÞAuª¤‰’‚|gFÅRÕ\´Á‡Ét¶�Ú)¸ïÉqÛnŽÝ)Óz®xšª�³¯Ï Ö×h\\s:Gã#2o{ïs!E÷dçdX²]U.O°{÷n³Ù,‰wIQvŠ™ÕÕÕîyvý�-§ò²²È‘'X__WÕ�3ɺK·VÆ“¢„ÈhZ eÀ£ZÀ–J@Ïy¬Wʯƒû‹ ¢gôèé|Îþg•±‚”rÁàÙ¡¬gÿìÒb†a†a<+²‰ÓÎN¬ÜÔ„¨#ÄÍÍGú∃ &¤_(qîOàT Â*ˆ©*‹ãööÖñc�í¿þ:ñ=õtqs/®2ª¿öÆ›ÇMë7¶��7Çhbá±T¡'2|uÉ{ª~H´µ]Œf{Šúβw÷óž¿Ú罹E_ÎF¶†@ ‘•Ó§¶‡[e¡ë1z%RÛ#� |>“Îí ìPÍšÉlk2¡êÁ‡Ðú€‚¶†��‘aÆÕÅ5§sd:µ`6›Å™9Û¹zï³+uÅ)%fÎ6S!„¶m³KÕÒÒÒÊÊ ]4öwFedsX,”’étZUUNûèV£,ËœYBDYähÛVDv*y&&oº½µ¾gO;šôÇᆲ÷â›n{ɾ^¸ïºzÕl´™¤ñI+_²"¥D «š1 `´‘BdqpÅ:W«�ä-ñ"€²,ó³¼AD"¢ªYöÈŸÊ%X”ƒd[-µöîÓ /@B‘P$ �’s!ßãÑüy™ë5󨆮epQe‡AÍu±x!ÿ#V^´9„-œÃ0 Ã0 Ãxvt9¢]Ãr>¶Fmœl�öø’ÃQ�’¹>ƒ%w¢Qz#HЏWq6KÒFm£pIþ©ý¾¯u ‘âæÔ©}½òµo¸ýúý_Ø<ýÈh{¤ics»¿²ïÆå•çïÚwk½º+j= tb£W¤-вçKM)‰:¢¬v(!ß*†qM""¨ªÂ¹ITÂH¦|r�³= ¢ä¯ °ó(=;U%MΑ¨(IwêV°€@:wÏ6 øZ¸æt޶mwºBe9!¥ôÄè‹\E‘£Â™9ÇotªªÊ‘"B�Fkkk�ÕUJ @·¬BV2:Q$ª(Š\ÿÑ-7¥Ô¶m¯×ËúG7Ÿ.)ÄxXÍž€Î „ÎÞðA ãªDâãhè„é´rÜJ‰`æÂ#FWø‰¤ªªfÓIááœKvûb†a†a< Xe!uäq¾ €««´½Õ[^™­¬œ9uzïÒ2Fô{�D !Vr † BDUÁ¹íñäàí·4M¨}5k‚×êY¬ÝUNëKŸ(² 9GìœÀ‹ÖÊMJˆ°*É”DKÑÊ“)Î`ÀW)²Èa#­ ãšG—Vêñ±�¥%n·“ÙéA±ì”SJÍtæŠ�óYŒFÇÌ  1”q}ïJT]¸Öùɤ©çÃpgK¡t~~†a—?Ö™n\©¨ªÈÙ¸xU *mA3—„9 µÐèŽ�ñ.a†:Î=…° ’—qö•¬pÐù”×#À%âÐRA©�Q" ’H›ì W8_°ª()Ù-�a†a†ñlÈ�<ºËB"¹A¿·º²Õë§jAC ѱ¨‘wĆhLB ¼´„$Ó¥î v­÷WV[Wº�¬þøiP %f'äF1N)”„¡‰D�DPB×õxv”§vpt7–çg×JÒ†Ùžý»ÒhðàÆÑÉpÜëU…÷ÓYXY[O‰cÈÉ(˜Øõ•B£a«9Þ_åënÚ»º[ÃQë‡+k+M;%”w˜ÂTÃ0®>Lç0®Hrx -žQI)9G¾àž²�ÃÖ6 ‡þB„2 (A$HŒ”+ïð“/àÉ|^Qð˜µh,+¶¶ªÔö _¹B|5!�wê8DQUïœgjš)œ’†a†aÆ#9nîC5Ïê`!ž†Ðï÷—ö¨ŽÝÞØÜ˜M•\]׎“:fa&8bÀ;apUM&Ó-çüúÚÒ¾ý¬1Õ$S2[ݧÆ) ^rÞÉŽAÓ�Å�Â+œÙCWÏ5¤bzr‹*Ûï†q�ÁÃélWÙ[ÛW­Ø{z¼ÝHbr®ªfAۀЄÒIfúåv÷Áõ]×ÃÐgQû>š@g“Í*B HLì0 ãjÂ:U�+"Re€™U5ǥĦ•YK©�Il>ñ©Íª(‹š’“$ã2%F¹"ån¨Ô™ÍfOúzÕ«Ïc%…!>¥X,õÃé‘#i:I\vJ@Uø^囨DP%Q$±rÃ0 Ã0 ã‚! ]Œú€…øÛ^åimmõúF'Om�‚°oue:Ù ”RJ1°hbòÌ ¦ÛqAXY¼žöì…¯Bˆ³îö§�UÎ/QÆÂfñe©ÀóRÉ/çÂŽ|c’EWÕaƵ‰�På‡)ùÚ]wÛÀK}âÑÓÓI]öIØq&�‡¢0‘b|ðy»®»c-˜5MµTx×Û�<3†2A”ˆÏõö†a\|Lç0®TT”M«TU‰¨t¾çÝŠ+«äWš8ü܃'CãÕ•‚~ˆ •) aŸˆ”�¢ŠóBòsè9ÇÌ]°JÖQ’J�ó^ŒäcYO�¤*nãQIBH"q–QQÇðNRR…:f�%;†a†aA¡ Ìç P"P÷¶Û¦O´rð ÌfGD¶ÏlpŒƒÒ¢,¾€ƒúDœˆÖ­ÔÒÚêòÍ7÷n¿kë­RÙS ˆEb?‹û  „DH,‹‚p&+HÅ)œ‚‰1óˆ,ª=žøóª2Œka)z.µÉ³ë9ìQ×¢wúØh8›øbXJi�"$&¦©/†®šì½±ýí+Ëû0 ÓYöªš�Ÿl�|Ùƒ2Ef  Pë4 ãªÂNjÆIˆ˜‰�¤ªÌ\UÑI•÷ãIÓ—X3ꤻ¨Å%Òè´P8G¤äÞpP gp-µi•‰Aà|«¨$š ®,Ÿ¹%±�›%©IdzQSCKÏ”¬ðn–Â4¶ ,DHI…óÍs½c Ã0 Ã0Œ+R€¤ ›U"ƒP÷êñæ,İguuí®» çöó'·Úö4VÌÀ<Õ4×í¯î[½íŽâÀþè“H¢Þ>Ê d:Ç—‚r8JÞQ,$ QÌ£ JÀJ�…c?^ä0 ãÚDH6š“½zÅñº zûqÛòòêQ>røøh4I!´1Àq¨—°k�–×–öÞ°î—¤%á~òLMœHR_UvÊ ÷»¬U§Ås«Ñ3 ãêÁtãŠ$»Tåz �g.û=í•ÃatíȃªË¢Ï¾ ¢Ó1()"¢ aR`Æ�Ç׉çÇbÉ'MšDr¡9“#&ÇMš<ó•tâz©WŽTÛØ² ©Š‚<í>°Ç•nÚÄ¥sNTUˆœ³rÃ0 Ã0 ã‚!€!P@!ó®vä>ôV”ªJ äûýÁm·ßÌnûp=;ñÚq˜Q‘ÕqéŠþJ=¨vÅóxÿºÛ³w\•MÒHŽ©4'÷§'¦æir…�°æ¬Ò‹å‚YL) ߪŽ��g?bÆ5€Rš`+¢Mœ¼ï—Kƒþ Ê•þ`ßÞÑ8ÅX‡P&¥ªÀòŠ®îJõ€7“¨‘+çMf3€{UmV¾wè$gË; Ã0®Lç0.kžÂ70ˆ™Y)@E5yŸz½ëï~Uûð›cá^p@Q4AšY³ºkH±�Ģ¢ åDƒT$"H˜!c·“r2ã¶M`”E¨©*“£D }Fÿ+„ÓƒÁ€Ý*…±�F¹ª·kÏòM·éò ¦­ Ï-‘¨&‘Ëj,©°&‚ÊD¥HH¬R&”Èa" J p7nðñµ1ó˜›0ÌŸP¾‡äè¼öV�ª+ï7 Ã0 ãšåœ弊`2­®ô[Û›uJƒå•ê…/Ü{Ã~ŒïÀpcvrk:l<ŠÁêïÛ‹ÝkXª0èM¼iCðÎIŒ‰-Oî©É^Uÿ-�ë6$Ï«Ã)Ët¶q»ãñ‰³0 ã‚ØYÁ%™ Ê@™s¬‘b~ŒPÎ…VÚuF�h÷˜ùQ/qqÛžÕ]ÛÓqˆ“º®b˜lLÚÒÓî[VV…B‹¦�*œ‡s"4¥»~*¢:M"Z¸RUE„Ï�Š`ÍYNÏõ÷c†qQ1�ø|!“ ÷qÓÙ�NT8§Q£*û2æÂËþruÇK·½‰ºžy>†M�Ö´£¿\" k¡eGÊEôP�›b¶ýØÿúµõ„ 2f·ï…¯ð/x<‹+ é—|„ÎK�"�(‹£‰óÍ$Ö\*gSW°ªèeeÀ¯SV'è·@ëcôÁaZE´è%pBB¥Ýmô%{TÀ”_¢S8‰ð.€‚Sò½ŠS!ÍÊ‹a†aƵ‚‚sPpî¹s ‡T8³i„¸ºN‚¡&Ðê.¿¼Ì´¼ƒjÀ$âÈŒ˜8 1|U0T3r0Óª§�<ïW}*‘‚»š×½òÔsÛ‰UrÆyÂP@9W0¤ì eIDQ+.{eÏÅfMAp½ºÝÜv¾”¢HŽ"³’$¤(-yR!(1IÁêY V‡K'u8qiËX#8‰mÐÈ5¤�°˜Ñó$Q à�( €$ eîñ›'Ž‹æG•§“S øª0�ø¬ÙÙ¸?§eß½•_O@r¾qçñ“VÔÂh…Ð:õý¶pÅa-5 v*I�à&¾Z*ú£’[wÑš.+ ùuyáTN@ˆÌ‰±Ò|/„UU÷)¹4�ºpõò@w¨�$pþ�Îÿ X‰¡6@Å0 Ã0Œk =·ßJÎif&âä°èÞòØÑŠ{*hî¶d Ç—&ô~Š7Ÿ^1 ã"ÓÝ$‚§óPŠÂU®,y8 ñU1 Msæô�}×…§AZ;ïIƒKšÂs[¹.wg.'_¢•'eŸÎž.”$ÑÎ[dçä{î<·ð“ÕjÈ“Mi†qõ`:‡aO‰À‘ùD‘È'ò‘¹uÔ:@ ô�H@7rðR¶˜� 9ý©ÓG†�\Úhg+{÷¢�MCa4>ù™Ï<°|äž›o~ùõûVŠŠ”PHtФE%É¥çg†aœ/¦s†ñ”è¢v‚Vq*¬‰”‚¹À N�yq‡Ã¼©wi+(A�òò5¿î (œ + (&N‰ÕÉ%¬/1 Ã0 Ã0 Ã0.[XAó[GD&�Ÿ¹bXT'ô±“ï{èÁOœ:v‰,-¹Õ~¯wÃö‰Ãð½¶_7£pôÄ™CÇÏŒ¢¢»÷ïÔ5š«C�c9̲Ê0 ã2ÃtÃ0žRPt(à4zMNÅ!»’æ˜ ™ç_D€Ÿ3:r³ïâ?QèbÔŒ‹P†8§ÄšE¡h*‡a†a†aƵ AX¤JÁ�ó#ï·*ÿÈ,¼ÿoþæ#Gåë¬ìY;¶y§¶°g ë0mf�ÝÒJ¯X�&=}âÈÆ‰›¿ó[œ•´N™¬BR,,œ Ã0ŒËÓ9 Ãx H˜Y$PÃK䜒‡V@‹ìOê�Ã:<”1½dM=)±0¥@)K À;fhá¨��ÛÖ÷}¡i3;Z=×ûÑ0 Ã0 Ã0 Ãø²BŠ‚8i0ÓTÔõ©YÃ{ÖmÏ~íýï;VÖîàÁ3„ÙÆ®�þEÐxÑ‚Ë~…vúK÷Ý÷#¯{Ý’V•H_©m›²ß·�Ýo†a\V˜ÎaÆSBœˆ\Îç($zMÊ`Õ‚oà+Ž”\nà À—°�Ç â\HÀÔS ˆ’®K_:&I­%‘†a†a†a\“��Œ¨"¬¡*ÆÀCãÍS¬§�nyš‘D1å"Á!¸rRHëÃíðãgŽ-ÕË¢*‰#Žjæ†a—Ö hÆS!D̈œ�¡D�À�ÀÔ²Ÿ# @9…/ ï x�O—0÷[¦Äð"¸G` 4@¨ëfk;¤ÔsìB*‹sÃ0 Ã0 Ã0 ã‚%"€¢‚@©.¶$~îÈ‘S7¡c"8e(¢´]¬p¢Î�;<}ü‹½ì®¯ÔÂK¼smˆ˜;8†a— ¦s†ñ”(§_€ XÙóÊò)`ˆ`;@É\ÊsJ&‹-�4À1`è}ÃE£I"§Tû‚Âs½ Ã0 Ã0 Ã0Œ/?ÊUï+"ˆ]1Mé¡#GÕ HAÈVÈ$Ê*ì¨(!‚Á Ç€�eñÈÉãî%¥'Ñ4fB›¢z¶ŠÃ0ŒË Ó9 Ãx*àYß…ÂG*¢«ŽM&8³uÜ®d$õëÝ“-fªœk€téVH ¤`%!D'PŒìg´th4ž”U„ ÄÒŠ‹¤jņa†a†a×$LÒ‚¼c8Šêá(¦áÆ&­®æwÁ@“Ƥ D�:ƒ‚óåxk³s§,•™]!z ý Ã0ŒóÅtÃ0žDIÙ!×sp!T¶\´ì›(ïûìçuã¤ÉLµ¿´{¼UÕý噕"é\�¸¸�Œì‹Å¤¬$Ñ¡èÎ÷öÙnfƒu&õ„ª(8±4Â…�°1 Ã0 Ã0 ø!"q ’�$-¢VÊ.iöÄ )æU’(�ˆ ˜@óTH”5$—m’iS€Û¹çųÆçz Ã0Œ˜ÎaÆS"‰s¾…àR¸ˆT‚½ß³ÿ¸6-È÷ê± >x®–úMÓ€+„pÑx!R HtÙN•œðl8¿„ª'³©pQ½Úõ¼NEyîre†a†a†a\3(AÀQ”á W†×j¿*VŠzSÉçp R°Î ¬”Ô%UHŠP† T @5q­ê ´.ÊédÈEÝhòi†q9a:‡aOGR0'€�%‘õ¶ñhÔú‚@2-£¬® Ñ@>Äi%�geˆ�YÊ"y`Œ2)GâiAð,ìHŠ”¤“Q%ƒ�˜±!kž9)1H½:G4(½+|�0Þ:3(°¼Òóu%uOÅØ†a†a†a\‹¨£ ¢„‚IK’J*{•S´ÂÊ€pPïQÄÔòB T!‘S¬«ƒ>>zF¿lgªL©‰@ù\o¢a†qÓ9 Ãxr”0KÑe<ð²]K?øò½û£=>ûª@Iäh™�ljG•©8e(EfR”"€¯£ÉpeeÍ«—±žŒQïºåáSÇqàD±=ÜMî–që·7QÓT%)WÑ)¸ñœˆ½À @²X;Q’þùûJyF[ fÎõN´âÖ‰È Ò‚¡©¦ãb6¹ýE/•Ú_uÏÆÅÊ †ÐcööÔ0 ø 0�Ã0Œ§Bœó#€¸Ø{Ûm/»nŸëõ'"‘9�ØÙ´S(E P @ÊD#Ä@Op’ñ)à¿|ì£'†#x¿>Xþ–ÛŸÿ�k{÷Iô}?AÛ‚¸' ÅÈA�së*¥¼ Ìë„Úi íhT³_«{Ô„éx2ðvŠ3 Ã0 Ã0 øæ`¢œ´ öì½@Ev÷êÛì_;ô¹3aŠ© ç€M›´7è/om‡x ú5˜ Íjò{¥¾uO} ·Tªª$*H•- Ò0 ãrÂ: ÃxrH1pÄ@™$�JGX›G¡JIAB �x° „èT|òJÜ21´JHëd�µ(Ðl‡]eoïN„ÿ÷¹¥ƒ75“æzâHùÒ+§a˜f�™”û­üÄ»D(s=�…aU@IÀ©ô˲æ‚Ë �‡-'Mâ%‰Z>‡a†a†aÆ5 ‚:¤ž‰“FížAñ‚]û_¶÷àlóÔ¦-jA™MÇ3Fïyû¦Ã3˜l"%° �qÓTMzõ‹_zguo rûB¥C$°3¥Ã0 ãòÁtÃ0žšÉ¸_—¤=Ïì• Òj6ÕÖ«ZˆY•4‘žÕ9„"ER·L íEq+N|¯ìS9œ5+mU|½Çm½¥I6GSŠÑon•Õ²nkÑ\t½)÷ƒ�¦‰8a)çÃ1²_P%’8m#&ö Ž1”ä|¯ªDÓ9 Ã0 Ã0 Ã0®=jWø¤…”8EN±‡joYÜ{Ç�á‹~tøÐ‰� ]A*{pL§g6[TÞõzu;+Çé º;ûƒWì½á–¢¿zâVW´×bÈ ¥T\ÏF8½¹7¤¯¹éޝ{þ]wøÞþ„rÖ Mž‰•gCê Ã0./Lç0 ãÉ‚ë•\zxFHÐÑñh{æ\é<)‰#°°�à’²ƒ9�‚ JÒ_ªfãY›¦EEK¾7qˆ:m¥™q”Ê1³”Ühp¡IÓF“RU@@B@`GJÙ‹I™” ‘€Èæð´ÄèHûeU–ž‹BRh”ìg†a†a†qÍ¡„X“œ`WÁiˆÍæä•ëûö VnXÛýÑ#�>2›œ™M'1î^Y‹Ã!NŸÞÅÅÁºÿÂë÷|ÍM·½tW¿¿‘úI¤ Qçg”¦É—H 3®2 øl°N@Ã0ž6šérµÔgBUæy©ÑIhIáò?�SÐ’Ž!‘àÉD Ò¶Û2+K�RáS[øÈn\éé4‹ž¶I·\šÖ\­ö¸ò‘›ql=A)ByN„‚Ä)ƒ\^1”ÎX•K¥£Љ¦™FRRlSYØ)Î0 Ã0 Ã0 ãš#&ˆ®vŽ1�Ñ ç¨ªgãåªÜ=¸õ/XÝý¹S'm ›frz³"·{yýÎo~ñÍ7ßÒï ¤ãR¡Pu"Ž› Ȉ¤*ÉÏàMç0 øl°N@Ã0ž%¦¢lÙ &6…/\ �c%Ï ( ‚e%a…'Gpp vä ³ØÖý^¯7oLÇÓIC=WƒAŒ©mÛqÓLC\&QHêœsçÊÎÇ$óœ7¢¬süÿÙû“Y²ì<ôýÖÚÛw�îÄi³Ï¬¾JõXEªXä¥Hñ^QE@¼wj¤)g4 ™æ‚þ  â@€(—OªÇ ñò>BT‘ÉbUeµ™UÙœ>:w7³½×ºƒíî'N6dåi2âD|?œŒŒðp·0ów7·ÏÖZ")%©*GúÁÌÚº‰M#<ñü"""""¢‹hpC]»b°”òÐH£ž.�F÷öò<·9¹råÆO]»¶Ë‚8ØFÝ4 K‹¾=ì&î�Âú.‡hrP�Úeëa*ÁÖUDDgs"úp¡NƒJê8�qHI$*�¢‰C ƒ«ÀªÔL]4˜¨Ì ɵr ù ksØ £Å �©M“Tˆ¨°¶š�*馌ºù´ ÑÔ¢¡´´ÀÊ‚*C1uÔs(ÙD4ÐRKâÀÃi߃DDDDDDt ÚX¥”{�Ǩ•fC—­íS·YÅM×ܧî`:Šz)¡M†Ìçå¶ ·à¦pTèÐàâ½ Úh‹ä`ÎADt–0ç ¢áZeH0@°hnRöç\æƒB Žh¨2ÔÕ¡P3 1bð,bê&1¢©ºÓ ƒ‰ZTH4 �l u@…*3q…—¡âêbu1&ëIãæòP‡s·“ˆˆˆˆˆèâ ͆> + jjÉ!°hP·Ê58BÒÚÐ&Pg‡ ²ÂÄp1ˆ™”·Ã Ørᥓ3�Ì9ˆèƒ©#šT®14I4kî€éÉ뫺‰C-šHÉt•L wqYŽw…Gqˆ¸ˆk0 ³�UMâ `9{ÜML]­Š—RÏQZW¹PÔaËxÃN|$"""""¢‹"8ª¤TC°>¬û `u’œĕ®Þ½.ßPº–F†òÔ—çö…´ŒC“"¢³ƒ9}0u÷h¶L DsdÀabu_î)P7²BäÒ`ª„@dD² ‹$U˜";².¯ãË©0�  ‹š 'Bˆ•dU±QÖqýsKì! 9ˆˆˆˆˆˆ.qƒ–ˆ*Ž– ²h,«•âŒõ{JW¼3ʼnë<#š·˜µÔˆ$ýH+EDDOs"úbbÍ�²¯ÁÍÝàR"w`•s¸ÀÊ /0TÊB\¬ ð€ Xô:x¯>ë£õÁ—¤Þë£÷ðîbYá@`ÐR5¬ºÜƒ´UUÇÒò§?ør¹+ªŽàl˜JDDDDDtá”�ŽVŠ02Ä Iáb&Hª†€`®(…’ÔV­’—ƒn']ÚœöÑØsÑ3À4eu¨- HrIQ‡É²�cYÜëX ÌXu‘’åb\ÌDLÜEL¬$".ÙËqI ÊGƒ”" ÌE!梾œ7”0åÄÞgiT%XÖ€û›DDDDDD›]Xö›ZÖvˆª#+’"‹™(`®Üx,˜ŠC€`0AiQU8�T³œì"@DDgs"ú`.ÖE룵a(»véC6ÏòA€•>VewjTf¦=»CÍ͵2 bÁ5šEÏn-GKµyåæf.‚h9:ÜM õe¢ï2JYÉrµ×€}«ˆˆˆˆˆˆ. ¤ ÚdDC�¡‘ÿ)¬ß-–0\Á \ËSd)ó)—ï…ƒAa³숈ΠæDôÁÊœ ‘2�ÀïM9°.¿€ræK‰"V£È 0¸CÍT ¾üV0˜#”S«Dq¨<ø|µL[¶J]ýЇw(€–‚‡ey~ Ñä˪ Ë¢A,‹ ¥¼CjêË7§&.¨}ð´ -›WgÔ-O­SÔ<­Žèc!ïké t5wyð8ü°C@Ì#/æDôÁÄ5˜„*‡<ÀÝåý¯ b€h–å@¶h¥LXaZe³Õœ 5Q@ÄÕ!åZY5»f•¬e¢¸,˜‡\â”û�žaø²_]DÁÑd @™ip”FÊ ¨ÁVM˜QUAˆ—ÎË7Ÿvb�Áa'Þiòà)ÑÓS:“K9ÖU|uBíê XS8ÔÖѣ؇zÿ©´ày±çs"úPâ*®}0Ÿ 臆 ®¾ø†,*0‡š˜¸Hi}º>õeùÊT–¦.j¢w ÜD&R ¸/*чG\æÀ—çäÙú»ÂòºzòB¬€æ÷-ðÄMˆè)r�Á\T 8Ö½D\J�rìÈ¥œ–û äX>Z?¢ Ð�¾ô,bÎADDDDDDDDDDgBV”D#êHZ£«=èUe~¢VcYƒåÐÕÇÄ3hÏ1æDDDDDDDDDDt&¨›‰AWŠe¡•­¯–Õª«¾se(¬ž¨ê`°qq0ç """""""""¢Ó'n•›{éOe&ëÎçË!äê&0uwq,ÛÓAONà8ù±8xp¾Î¹ÄœƒˆˆˆˆˆˆˆˆˆˆNŸ•y)ÅÈ‚’s8`‚à ˜âA™OîY–…ëx£t¯�_$Ì9ˆˆˆˆˆˆˆˆˆˆèô©#šwƒDhͪ5)sÆ58´üƒ‰»‹˜BN2J÷*¬˜¯q,ù9ÆœƒˆˆˆˆˆˆˆˆˆˆNŸAK}†C]Ô âˆ@˜KÉ¥{Õ²i•hÉ3J†±®êp�âA©‡¯’�2ÀƒÎæDDDDDDDDDDô±Ê97M ï{3‹1ŠHï¹oª. ­ëÖ-t]oкªô©ê*DÏyp¤ZC’ YU³y†¦iêX- UeǪ‹ƒ9}¬T5¥T>‰1†ÌL!]FŽã>„£XwU8WwïÞ»=ï—¶6¯moo7ÕX ‹KM£Á5˜›™™%Ë"ˈC� à}=¬èœaÎADDDDDDDDDD«’s¸{UUªZ"Š`aäm;jßÎþõwßþï÷Þúöüà�az{v´¹³-?šoÍóç7.ý¯/~úç^xõŸÓ,{ŸÕ³çJTª�²I΃gFs""""""""""úX©j©ºp÷”R©íðº™Æö�Yú³{ïþ_oÿàïßü‘ ¾]ãÊî}›ã£èó£éÍ?ùú_|ÿ�¿ýù/ÿ§®C Ç�²h+R²6Æd–q\Ì9ˆˆˆˆˆˆˆˆˆˆècefªev8RJeDÇѤþŸ þ¿ß{óë¯ënßå�ÝK£¦«‚Uu7ô@mDÙwn½¹ÿÎ÷ß©°™~e{ãEÔƒw9å6¶*šR7äÌÙ s""""""""""úX¥”ªª‘œózDDZø×ÞøîïÞzû­~Ûq]µÇÇ9 =j«F£áþáAfW¶6®_ŸoMþd˜ÿÅþK_~ak»·‹éÌU\ÄàÙM!zâÇ)k;Î5æDDDDDDDDDDô±r÷RÏ‘s!Ôu=ŸÏß�ÿÿÿäÏÞmÛjûRÝlšWÖwq´9žlÎûn|í•P#¥nïø>Ò€&NÝþü;¯æ _ØÝÜ6E﹆ "ðÓÞBúéã/‚ˆˆˆˆˆˆˆˆˆˆèý‚©¸p)ÿ 0À‚hu—Þ¼ qVW7Óðú½{ó¦µñ¤õtÈó!…X‹„Ùñqš÷6X7]ÌŽ ±Þ½Ç[ïÏÿÇ?þî|Ñ{¥C�Î$YŽŽZ!&ŽÊ.0@äQò�å:CÒúŸ &ªDtõïá/=¾÷ßCW£'ƒõDDDDDDDDDDôä‰k480d±¬¦°`PG4„d ŠºÙWmÚÑÝk»ÿé~os»G€ª˜˜:ÔM�ªõ³ ^W•6MY=M¶¿·ÑüÿŽŽ?¹Y"^µãý¸!ÁÛÐ:#¸Ž. +šdøGÌJ0#ð©†P¨‰ª«ËôÂXþ®.ëo¹¸©, bøèëCˆ9=yêÀòÈ¿æ‚ quT±ÊCJ¢2j:·ûžß^Ì£t!@‡«%ƒP‡¸—€ÁŘÐ^ã;îß;šÌ­Îê){‹Ü ]Ëõ1,C‡�HV3>ìAÉÆ{KCôÁú‰ôbùóÎ!O s""""""""""zòLJÈ_º "ÃлÆ:DI}w<ëŽ�ƒC�!p`•o°‡>p ƒܹ[}9M�ÞLü=³9€<êrñu›)`¶Ü uz¡Ëµ“ b.€$¸±U¼¡«þW^¢šGI[èC0ç """""""""¢§ÂJ9Åê ¾”/æ@UiBÔPí‡hwH† D!¶ŒÄà«�0Àáf›!ʬok˜@+Í9»;²`®è‰|cYoñé‰â ;ù‰ Ä×›¶®5Y]GÖ×Ogªå8(ý bÎADDDDDDDDDDO…Ë2êx3«ª*íó °ÍñxS£.ú&›&sQǪäáäÍ}ùQÀ*ó1p¹nƒÃ=k ¹Ïº,YNÕpy´x£Pñ2]£ŒRëÕGIZ_NÚXŽî0Y§©¬«žX_÷°Z.ü´=çs""""""""""zò\JñL̤ô€`&"Aƒ‰ ,7ŽÍªÚ®›:£63¬šAA}5�°åÇU©DpkúîÕë/§Îs€ÚÝ«²;\šKêà*y´ñ«�Ðu Æ*;1_&Ö©…—2”rƒe"ËÞVºÔQ‚0êx"˜sÑSa“}«Ö³»EdÈ !F 1 6 »mû¹—_ù‹{÷ÅQù‰¾N®%çp�‰­‚¸ ¸M\¿øÒ«2$ âê"]–CAdYÒ!03ü'&®n«„Dñp…ŠËbqArDµ¸C’”’ŽR[²žèáp”ÐÆ§Ö„`ÎADDDDDDDDDDOž‹™À×õæU˜ †aH[Å:IÒåÍÉç_y¹¾s·Î01‡:�¦Ë%”°Ä¥B`ÑìZh>{íZµß… TÔU$'`¢±å¨ŽGcË€DÈ€9trXÙ*ñ²EY âÖ8–ÓE’ yYÕá0Q‡Êj…LXÏñ$0ç """""""""¢§¦4qrX…ê.±©:›Í¢Š[ŸzþÅO=wëh:=\tq2éc\Ï¡‚Í ÔŽgD�æó ¾iúÿù[¿¢‡ÇÑ4V:[‹ˆ÷©ŠqÝð* €u{(ýè+Ÿƒ(\QÚg wWqñ 7Qx ã¾oT¢ˆ©! ÞC²û*5O˜{ož}�PUUXNñ Ç܃ˆˆˆˆˆˆˆˆˆˆž®’4(T`ê«â  FDSã”þÞ¿l¯ûëßúöÑÁQuýj»³±‡$îCÚº1�³ÅúêîÕŸ¹rå†ÇX£eùæââ"æ.(#Á]n U_&.ÅzðFvÍËÎS¢ê¨ªzèû¡Ë•Æ6N‚Fφ®EÍ }/iîЈJ!U 7—AÄ5xS*Érß÷µ†�¸Jô˜sÑSbÄ¡€øºËÓ‰ï Ä1luùç6GñÅO?7÷oÜyçͽý»GûWhj´�ä<êãY·9�¿ØŽÿz»óóW^|ÁuGb­&æYmÕâ x0½|ù£‘øjòyù²L·“huô6Hƒ‹Ãaz0¿õî±Á,µñ¤ÙÞžì\jF›èB�Á»Á"êèy‘ûÌ9žæDDDDDDDDDDô´œ 9Ž8–U ˜[pL†„}ûÅíöÓ_þ©?y÷êï¿ùÝoÜ»?ëÌáó}Éä¥Ñä³/^ÿÂå+_¸ñÒ§6ÓÈL‘“'ˆ <¸.‡ƒ?~^¦k< ƒ,'‹ˆ­³�ö‹¡ÖQÓlH�n‡÷ÓÝwöî͆YLrß™§ª–ñøhc³©Çúꧯ5ÛhFMNÞ/æ&æÁc,3K>z7-zs""""""""""zŠJȱž¹í² 9üÄLoqDªÙaÌ“Kmµ{õÊ'·&oÏ�ߚݙM‹Åh+Ü�?såÚ§vv®Åfc0½»ArÉŽ$‹$¨C–uþ ã#*c9l97\–µ)€xò¦UŽén¿ÙÝ{wzxoèŽtws׳š÷)%†Å<÷û½Ç>øøÚË—žÇ¨i-ç~X¨¤9ŸãÉ`ÎADDDDDDDDDDOÞº€£|¢«œ£Ì/iÄÔ!‚§J!]v 7ªfwkë¯]ÚÚï¯Ìæu]×U؈:´}/Ç{˜/�¬n&RȦY`"."nŽRÏᥘ㣎åXS@á¶ÎcVÛ¥uhÅÂì7ÔÝüáÑü¾kÚ£îîY�ãf$Æ” Y»7^¿½è{mvwn`ÔL܆ÁzQVr<Ì9ˆˆˆˆˆˆˆˆˆˆèi9Ñ·ª ‡8\ 81\L ®žÚlpx¬lG‹ÖâåЄf’³apëCše›‡ˆê’NÂ{&&¦f"P7˜Ã—‹‹ëÊ‘�Ì €—1äV²‹ªuSÜ{§»ýャ{Þä�‘4ÐñÒ6 è�€!+²U÷Þ=®ÆŠzg|!ÆÁáÈÂCôOïD""""""¢óÇ–GŽ\Wç¢*°lWîbsq)}| NôN×'®®/Ñ?‚ˆˆè£(/;&ø°¡àH­ýbá)µ±iôÔK?h+ #gX¨LšÊBž‹ãýÃkñ D "‚àÜ-CÕápƒ)Êkœã‘G‘p-óÒ!7Šjv„Ã;Ýìþ‡ñ¸jªŒ¾ƒ*ÜˤrQÕtc4jö�ïÜ~ë°ÙnnlŒ0¢.n[¾Óc`ÎADDDDDDtîˆ :@ �Ž ] HM_XZdä ·Ê,¹ª"ˆ®ÜÝÜ9ˆˆººŠ‹—v ˆ€¹‚Qý•JRnYì=ßRèƒë°Î*KTzË� XM±0@,¹gi0’Ñha.ž3Ä}™ŸDaù“K�,ÃG¯ëð²Î’ &0µ V‡‘`7Iý�Ðgš¶ut.&pHÖàf îXž¨JDDtA”Þ�ZN&‘{wîˆz!u6ÖÆ�€( Hr"Æ0ƒ†èŽù¼›ÏQoH@L9�öF�Ì9ˆˆˆˆˆˆˆÎW º@\X�C`£Ñž,¹äª‘6„Þh‡0T–aw¨¢©šIÝh…ù°0Q—…HvuH5¸¸Ë‰YDDDD™€•DëÃÃ=ÁfaH¦ r‚‡ IáÓU݉; p“¾ï»•‰J° ¾˜>Ì9ˆˆˆˆˆˆˆÎ!G0@EË8rÀÔI–=õIs…ѨÞ€ã#`~Ý1ŽgÓ>U£Û—7v¯…ÉZm-6.uÖYF—­‡BTa�sS‰ˆèÜ+Ý®V-¯–' @L¢Y–ß ËÖVŠu“u+.(·K\.ÍU\ñèÝ´èæDDDDDDDç�‹[–\¤Òܼ a­PGi£m¤CÞÇÍ·§7gó»âƒfL²FßgöîDB“>ÿå뉄�6„ÐÉz÷Ay<�ˆˆ..3Él]ÚœÎs–Bm(Ì uÈrЈÀµÌÊrAr x3jêAÕ8‚üÉá~ ѹã 9Ù±Ê8b[oÄ4šïãþ;ÝíÝ¿½Ždl—ÅJ$º!uóãÙôhaÓQÜÛ¾>ºüB[ïT w˜„àì(NDDÀrƆÐR™ajj Š«7vŽnÞʾhš�Ô¡‰è;h€x€–éX.ÈdÏR¡Ý¨'pEö,�sÈŸ æDDDDDDD瑇l@ ’ƒûΚ*zÂ|Ïn¿yx÷íYÈãËÍíRóÞ$k6âÎ¸Ýøá7oݘíVM»ÓíÚkt â›VÑÅ ë 5Ap¸¸)6/µ9 À\:­+ä¾ô¨Òu|áå\�$é†z„¦E§É,I8˜u<>î”�? èj~†­ç�‹‹%ŒêêþÍᇯ¿»ws†Éf¼’g‚ÁÐ#mÆ¡®½ )ê¼Þˆ—û£êþ÷ï÷G¨Uƒ�S_©4<¤@DD€�9Ä¡%Ãp ÉPµòÂkWsœß�¾[m"WXd8� )ÃRAkx@VTô>‹#{íÓ—c ­ ’cÔÕÌz,Ü)!"""""":Ÿ¤ äxк êÚÆq7ÃÁ�ùìÐ4µ•�BMP‡”~‚Æ,1W!7½„E+ýäæ�à ¤Elâ$wœšJDD„-'Œ»Âƒ#˜¨©uiÞl†k/î\~aâÍüÞìæÌÒè¬Ft]ÞŸûÑ€^aµÝ9º3ÚÅ�WvF[Èdñ®›ŸöÖ�ì[EDDDDDDtÞˆ— bæÄa hSMŽîøíwö‡Þz­ƒ$ ‚—öã0…0×`ýšwß¼wãÕË…ºÍŽ+ž‚JDD€À8ˆå…Ò�,p¤µ�áùîò0ܾs:l¶Û0©4Šì!:O�Í“,ts~ãµç^úL¬60K ©ú¥ë=°áI`ÎADDDDDDt`p¨à(µa:?ö{뚪n‘+8BI6 ¨[ë¡®p`@…()Ìgû÷péex6·ÄC DDt¬?ªC!R&‹-vµÙ¹ÑˆÞh7÷î¾==>œMçU'!F¨'OIªuÿÉ/¼øü+ÕÆeÌ’-úàcl5cÐñp§„ˆˆˆˆˆˆè7ˆ/Д §®ð0ôè; …JÚ(uʈ*’À^®ìXOP¨7 ½Ö±9Ø;|îS[]?�<œ@DD€ ‡—�& šCÄl~l¾1Ù¾òrSµ;õ¦w»Å~¶aÚ C²*ÝÚï^ÛÞ¼Ô^y¾ÑsŸ"fwAk3G>Ü1!"""""":o–}«Ü3/#:T]€8ô€Å(­†Fâ"€(²Â¥ôå0ñÒ‰rF*­$¤¡_„¸•†YÁÜ8õ“ˆˆ.�«k..¬·ÞcvϽU’Ú+á¥�KòZÝí'ëÑ¥!{’(ãífc»j6‘<ÏûÃ~˜‡Jë2|È� _LŸæDDDDDDDç�¸C ðå /礂ŠHeY �îÈ‚,¨\ ËDEߣm«ãþ^ÝÔžC5Xç¡"":çäd®ïÀM`–ëZ¹¦]^4Õ¨m6j ©¡..�‡A’tƒÌç‹ÐxŽ�]5£\³A£pÞÕãcÎADDDDDDtþ˜‹JI7€…Vh€£RÎØ* Á�8ÔUp-]ª³>5[˜MÆí�! a²%qø#­Ñ3ÄEábåõT2 €©C ª"n±¬i–�§ÝÑÆxœRÎW×(DÅÇ…7u³ƒëa{c·½ùÖááí> ÙSo6Ä ÕXFc�ãpí•ñå0ÌGa,^Iê=Æù´·�ˆˆˆs""""""¢sI¬T] Àóù1*©™§ÙqßOv¶/?×îÞhçû:t² u#›[qëâözcztxÜîî\J‚!c<¥<œö&Ì9ˆˆˆˆˆˆˆÎ'±Ÿ» ri`¥1×Ež b³²Íº £z\i‰F ÄMÓB_$móÁbŠÍxÞw.¨ëq×åpÚÛGDDDT0ç """""":‡lÕ¸jE-ÓÈ] È.–=Šd@ÝHeà�dH21ˆ¹¸.âP ÂWqˆ—BDDDtʘs�Gâ<È;´Tu¸p A×íÄÍÅ `3P‡®Cà� �Ì9ˆˆˆˆˆˆˆÎŸ÷ç �•z ˆCÜH‡Ép↶¼‚‹ àpV3?Ê@s9í-$"""*˜s�K¢ñ-¬\!廿R‚ sN^gU²¼>D\O\h%ê """: ˜s�GeùûÓ héh奶C|`”Éâ8_\± KÔ P“UQÑicÎADDDDDDt91Á:êX͇˜¬Ã‡ à¯ßr¬+BÊPÓå�SÀ|y)ÑébÎADDDDçL9x÷W È]µp1,OIV@Wç2+`€C 0A°üÒÕÖÃx‰ˆÎº‡Š9`êÆs8bpºlDåå…؉gTY6±óõ€s>ÑÙÀœƒˆˆˆˆÎ]Ô,Ûͯ�¡ëÛ¶�Z¥”Ì5šÙ0 Uc£ Iƒô½ºÑ *!¤”ŽE†*¤ n¾7—:ûÈyh�ˆž ŠeUN¦¿¶¬ÎXeeÂ8’� ¬y(0v°e³*Q€ÅDDDtV0ç """¢sÌVµm[wéûÞ QTDªª ÑES—ºÔ'Ѧm…sÆ0ôCž7MZå! Ã5ˆD3…ðÀ=£–¹Åûò }è râãû0Û ""¢3ˆ9�[²lÍ¢B¬ú>¥l!¨fälƒ¨»™¹ dhŸp°è­fÃÐon�L|Ñ÷©ó¦šŒêOÕüxÇ€¤ÓÞ2""""""ZbÎADDDDçɺ׊=<¢C‡![FÐªŠ•Àúaf–$ø`ó¦©FãZ¤ïÒ~îgÕØ7Ûº_ìeÄšªK®�JŠ¡Ú�1ç """"":;˜sѹ§€ZUUUC^d4¦ØXÓúb¸{wz8�Ý»ðÎñü~¬òd£ Zmn\»vé“[/ÏŽÒáÝiôfg‹ÄáDDDDDDgs"""":§Jsù2–ÜU5„Üs?,Ì»Pçªv�ó™Ýzóæ·øÆ·îîÿøx~û¸¿—í8D\»ú\­ÛW·?ó‰þ¹K?=¹ü|žçãNC´Ç[-""""""z’˜sѹ²œ‘+@ˆ‰E¸˜‹Æ˜�dCˆ[ïÒþÞý|ó�ÿó­»q÷ÞÛæÍ(µãy–Yˆþöýw=é�ÞýæÛ·¾ÿSŸ½ÿ¹×þfS§ƒ{ýD'«±DDDDDDtú˜sÑ9%G ;äÁ¼‘(qäZ÷‡‡ïüà�?ùö›¿?Oo¡ÚÍ q>ïûlˆ¯qùš¢Þ¹õ§ýŸ% ùS¯~uc÷ŠÏ>:ím#"""""¢%6¾ Ü€™ Ã�s1c†¥rÿ¨jŒ1ÆXyŸÍûÇÝÍÌÌÜ]VRJ†aèû^UE$çBø¨ _orYìúÇ}Ô唿®c]×)¥œsРƸ¾·äœsΧ}�~ðýPîÞT"âîgsUé‘òUã9ç¦i‹Åi¯Ñ)3Áz¹8Ô¨ˆv]ßõó¥ˬ¿÷g¯ÿ÷o¼þ'¹ÆGatÜÛÁ|è¡\Pµ˜éx¸&ÓÞøÓïþÎw~ô_ÛÑ!tþ‘Væäk4U}´×S"ú”ÇéúUõ´W‡ˆRö{Ëðú½ði¯=¤ÚC>„°~Yr÷òe '>ì ëõ*w샔¤¬Œ»»¹åœSJ9ûÉ4EU¡.â«ßÖ Yÿ„§u‡Êú^]þùÇQ6<çlý Ð`V.žö:ýÕÖA¬ª–'�õóÕi¯Ñép¨¯žÂ!P ¢LBÓ—+_®öh¿ß“gž–E­øQ­W`}®W²¬üúÂÓ¾G?ô~8y¯®Ï ':uë?N<üø:íõ":# °å4ò嫘‹¸†¼îÿøÝoÝ?~ÓÂÔ5;àóˆ\»Õž£[PÔ¹‡%TU£!ß~÷îwÞ¾õ]ÈG~Ÿö�ÕÓ¾sˆè�“»¦'O$:íõ"¢Ö¯žëw‘àã”èŒ9yøˆ�Sú0'ß ­f>þbyÙUþ†Êyôë<í$—òŸ9² 2.9+<»$˜-ßíø²íR†,šqVž�Å!’?ðÕ¢œÞò`KÝ”Š„�ô#̬ªªå�)KN)}È¡™ÕOtÏâ.°œ!ÈÉr â¢"ª*TQNtu³ìY 9 €,žjæ¶š+ût¸ÀÄLÜšÙ†u{7 AÂòžI)¹«Ÿ™¿º°N>N×—ðdºÈn€‹dAvàn>¤^“ Z÷@ß§ƒ·owžïÔã”%0xt¸€[JEa6÷44èúÃ[·ôÉK=>ÊKêú ñõ (§Dgкumù2¥4 K¯ˆÎŽõyâ';6—ZÉÓ^5"ZZ÷ýÆê8Ré^ÎSEé¤Ò«ª|^žÏŸHÆ�¶‹«b¯ÏWŠ1^´�À#` 7�‡�•WÁÅc…NË1ˆ”— ab]W•x8+OÍâPŽ(,¬£XTUb¬P‹÷ܪ*¤þ£åë3OOãD½ðÖ9GpUQ *° HŒUB¨Äcð*Æ X¾Ú•LADT%J4‰ÍU¢¡ò EUEe¦KΡ@4WG¥UbŽËŽ@à‚{¡®k3qVÅÑPþ>K“b_ý}^´§t¢5‡Â2爋ºŠGeá•x•=/îü¸÷{mìà'_u™sJÓX¬ëº¶j'“‘ˆß¾s«úb¬úÉWiý-ÇbÊã´\rÚ÷-�œW^CËû#–^�)åÍc9fªªu]ŸöÑCÖ»¸«C=ZÞœr¿—N*ï�ÖQGù y´ÑÂ'1縠TµmÛu¤”Ö[êygUÏÅ`‚�6Ä ècŒÞõîˆ1nll`ggRÉø,åÈ’P£"&mÛ–‘é¸OÂ$lnVØQw3xPÁø£½O[O§_wÊ›L&þ¤³÷ª.Ò h2€ŒàSD˜"c¬h�º®UU]ªªjÛv<Ɔè`›R!Á"P¥ ‰’� þ±åjW@\�Á &“IcçîîUU�6e´µ WætêÖÇ_Êã´<_�F#ž/C–C pA@+WX.uRíq0íòalè1¬ìÿ”�ƒ”‡�b•†œ²e•šœº££ƒ�ñNí|„UZ�¯ä«×‘�� ¾ß#:S†aX�ÒP×uUUOêìB"z"ʱ å¼�¦iêºæã”èLYï÷–jæÑhÔ4 ÷{é=Jαnº®Õ{ÌÅ2縸ÖÙÆÉ?£ w¾ÒºÜr õ‰©Òëa U]ç8{]ïËxnщ^¦G”ß0Ôîîðå€íGYþƒúý¿´Ÿ¸œ¼‘¬½C€åZ”XIuyÕ’s¬'‰HIþaËY(²š_~;OBÊj�ü_pò7bꉜÜP¢3áän[ÿÓ·|’ÆêYZ|ùlî)u®j@†ªÍYtz„g ¯—¢ C‚"Ö€tý0D´í¨øGzˆ�Ruò…•�S¢³cýx|Ï9=|œ�'Ïü-Ÿœì�CDgÁÉ÷¤8ñ.•�S:é=‡,žÔišÌ9.¨œó|>/Çm»®+mrÎïiò~¾�è[Õ› Ç}<%9ܘõ}offèû~zt´±¿¿hc–ê9rï†0¶®™-‹¾ï]d™Ó©MÃl½1CÎCv«ë(þÑV¾ä«[[[¥ª#„pxxXþZ>ðêåÁ5‹vA6 H�õƒ§€*jSÉxVÅùÄçóùÐ C–®ë‹ÅLë©y—<šUˆ†qÌ£æSê[•Y=X¨¦ñðð°ï·Ìj˜t]·8j?ë9èÔ¥”Ú¶mšf}ÖLyL]¨çs:}!æ€ A,¸ÇŒàˆÀ` 1\,+²ÀMÄ¡&eÌуçRY�éUžó]ºð'£Ž¸ÈB0h©çðÞ¤µÊ)v:dȽ«…”�À˾ÁCËÊ.hkˆÕ‹Ù uµ½uù°›†îð'_¡¾ï·¶¶Ê‰lª: Ã|>_w.þ€»S`_¢@yÏ]áå31uˆC\×Õ(Ë+ȃ/UØG¼?‰.„œóöövé¶!"]×M§ÓœsÛ¶§½jD´df›››ë®8}ß—ÇiÓ4§½jD´¤ª£Ñh½—»X,¦Ó)v™£“NÎ!ÄËl…Ç <˜s\P!„”RJ©®ë2zÁÌ̬ïûÓ^µ�� àv"ç0¸ÅÞƒ' fX€™YJ}og*çˆR÷ÃÐÏûÝz~†™ÔU�RÊ}I)™*J ¥øh}îÞ“Ãc5µþä�óÊ9ú  )KU°ÁýBªºwF(Oa.*ÒÃÐ÷9‹›YN)¹™!ö 7Í ÿs[æþ ç@TÕ‚Æ(ay(y÷ÌœƒNÝz&Géec¼ÿ~áB=ŸÓiӪ͎§YÒ¸E�”fÓv°j,2f ÎÐ/PeÙ¬â¥IO†!&Ó±³ˆ¹„ª®c3t}yÙ…˜¦fêú“š‡z„$ArÌD$Ùñ|QoTAÆ»£çgG³ÑFî}š n‰nÕ`B¨ëpëöѧ>qéèèho?]¿¼S×9uq<¹Ò÷9|”‡Ø{†»{™Çø�9‡ ²XÖuÆ£‚i0U‡:Äx�^¤àY{‹†h¦%ªq «fAÒuž@V£¢ðž T•¯§DgM9_³LÓ,[>N‰ÎŽr^ìºeë0 ådY>Né¤rúWJ©išÅb¡ªW®\yüæfÌ9ˆˆˆˆè1¸ÇX±Ü/Ú˜ÆUÀÁ�½{÷æ7¿SÍ_ô}ú*Ûب‡ñèå/|utùzØÞ6Èñ0,Ì-åù0�Jâ Wˆá½Å?)�©[åõu�Ã0ÄP7q4 íç?ý×ÿäw¼·Ã~ª Fm±í;Ë9¹' úü Íl~xt”›JݪÙtØï¾òüçàOwÚ€‰«8Ô–…PGe«B ²À/ß‚¥DÆðàñå©l@DDDDDçs""""z be h„Äìõl¾¸ïðo¼ñvØŸÙà!»"WC¶”Ó|–«ãïO¿~íSŸ½þÚ«:Þ¨D ±ƒ9{ÓáÆ#”W¸ë�£°òÏÌbS ·êóŸþÒëßûú,?cçxØúœò´j 5ÌáÈ]�Ô#FLFuîr�ñsW>qe÷%¤§[ÌjªŽ*#Ú²W•‹•⌤ôAαà%Ê"9 |QBŽà ÁÊbá‚�wÑ9œƒˆˆˆˆKÓVóé4æÅ$xº·óÏÿâà�Õ‹aS›Z¥ˆ˜Á‡óìXt¯‘#<}m4ÙÛ;8üÁFU¼4yTˆIˆ@(QÇ:Øx´1.0 @pW¢Ž”“´Í¨Kyèm¼}i:?þé/üo¢é�^+´íæ(híÉf}F ¨k ŠZ`‹z8j7«—?÷ê/}âÅ_�áŠæ§8ïTºÈñea«¡¦0�Á °˜—å¥Ï—)² k¹> ¦+C9&y0™œˆˆˆˆˆèÜ`ÎADDDD�% óëÛÛr˜öÞxcÿÛßÙœõÛ±ÖE'*.Èp5�æ• Ü£Ë$Ti:=ìæÇã¶ÝÚhâ Íxl‚ sQ8 ˉ�GÑáe!ê@M ^ ;4çŒ A¼Íýä•k/Í>1Ó˜oÞÿö­{o¥Ã£zÚªËCß/�3¦3´ºùòõŸúÌ+ÿÛç>ñ‹}åpšc|Šõd5w=‹åd-M«ÌdÙ~ªL�¹LïP/US”;ðdû/¸" 4€=Új�UÌ9ˆˆˆˆèÑ lTE�ãè¨{ç¦ß¹·tÂâø(ŒÛAÜ ®ˆfÈ3dÇÁÁ®#§|üî;agëÆîn»µ¹0ø²MÔQñòÕG�:Ð÷–,ˆÒ´Íl¾¨ªª­·fÓ£6^ëss}û‹›_¸ô½¼œgÿóàðfú€¾ËÓ¡ë¶'Û»[[×.}ú3¯þ/¯=ÿs­¾Ð´šL‚<Õ°@.èYÔÔJ‰Ví§êŒh¨³Vš¢Y‘J>¨[0p1`9À# r0dApTIãMx'""""":“˜sÑc©Äû;·Ò[oûÑt 2N9·î)õ“¡CdCî6vv¢ø�Žgó½ûèyèÐŒ] ŽRµ@]3|„VKe4…:JàaXM膷m½¿wØ4͸™Ü»wïÊÕK·oÞÝÚ¾:Fý¥Ï>÷…OþÒ½ƒ›o¿ûý»{o‹¦Éd²µµ{ãÊ«Û/U¸äÝ¥£™¨Õ[“n8€<Ŝà.Hj}XÎ /�ª¢k(ÅM :¨@‘E» I×s×Kÿ*ˆip3Y–ƒ”à$+CÎCþøÿLˆˆˆˆˆˆžæDDDDôèÔÑj¬G÷î-îïÝhÇéÖÛÕÕËè:‡%±Aƒ÷*0ôúNÝ6Çõ­»wûÙqÓwmÝÌK£*�¸>fÁ„IµýÐrŽ��6·&î>=š]ÚÚÍ6š«Ö%•ʬ‹réÚÖs×¶ÿši^ÞÊ£z%©Ñ<ÅØÀ«¾[<Ôê)(…C@R”#f Ž±Ôš, Cgfmå£ÑBýÈÒPÅdâµÆÚ,iì>Å|1 aH} �J;ë;6Fcô¬æ """"¢s…9=:qäÜ×UÝ/ºQ}6¯Æ,æ3�C³˜‹ ¨à@PÄí ¤a¼±5=:hDrÎP¸b9c�’vˆÁ¾•+”ƒ àe7Xá$ªW€™dˆé²VCáA\Õ¢x�Tà{zA� VêWPCbÖ:ÆÜõÙ«6\Ýœµøqgoïߺa.9çQ W76¯·“­:.¦Ýl¶ØE…ìq€ghÔ¤Áò|Žåh `UÒñàKƒC`Ë Åc‰q¬²�ix,9Pæ^$È 2zÀ›§ºm“ÒŸÊPÓ*«¸˜½´sXËëÇÓßûþ�þÇí·¿ßNÅ$A†< á…��Oï^ùüåë_Ú¹öéííÅ�¡u—<ÔC®*T!¸éOÞŒˆˆˆˆˆèYÀœƒˆˆˆˆ‹‹À]Ûöxè6£4&®AŽ`*¢â�•DCS#wŸ§~«#6Xdq…è‰cð¶L,–Ã6~B«Š Y—n¬¾#¶¬öX7·õbËê0\—!‡WÄ…AzÈxý4ïLd1Ñʼqˆ.ƒÆE+ùÆááÿñÝ¿øýÛo¿q´Ù@•†FB禇ßÝÛÿþí;G¯|*ßxõµ¦šuN˜'$kE²éЛs 9�/Ì9ˆˆˆˆèѹ@côù|råÒí×m·©‹iÕD¸+$fi\MT]Ô hZ`{2K}aÖ;»—!â@—Çűš=þ¥®©ü€@Wa†ÁKÔ‘à*0ˆÃ‡$ˆ¯Òêu­�“I¡nÁÑ$m2ຈ:«ÂÑåæwßxë·_ÿÆŸîln¤ÝÄ )#KŽ1Dí»Å݃ýáxÚÿ{7oÞþÿÔÏ6MØñVR§îÑ<8Ü‘™DDDDDtŽ0ç """¢Ç¡ta¶sýZÜžÌgGpÛi[ä¬&µC�«j|ȹª'G‹ÞÛv¼¹77±t•H<à�uPj4NëîUpH^Å%N‘YdÕ« ¡tµ‚G Ãk c¹è§Å&&@0Dƒf5•.è^«>›þï~ÿ÷nMw.éæ%ÛïÐum gø¼@«ØÜšÕÝ›óEwçÝ×î¼]_þM¬›hyha¶\þÓ[}"""""¢SÀœƒˆˆˆˆ�ƒ›‘Ë»×_~éþ_üÙxT{ÎÈ€f­s©¨x�7ä“çDšêµO 1¦¾«ªvpbËþQ«Ãñº,ðøÉ×h5Hê"(½§–Uë© Ip@"¼Z�ñp�U˜áÕ*䈀ÂPAŸfÒ�¬€¯zj)º€ýFoOâ¿ÿúÿý‡ýþôÆ6v.[á(ŽÐ\k®uÁîwG}žÁÁ�xÒ<ü·~k£ ãÏïŒcÛ§sÑyóqWâÑyâ‚–« ãÉÖ‹/ï›ÛÆæ\ã Õ²±ì e€ÃDóxcšÚFãO}ªÉQ·� LÌð»*Ùû¦˜ËC­¨ÄT�¸ÂE]áA]±ìZ•˪ÕSÎqbM"ËbCðE…©Èwîß›¶#´cìaïHÚvõλ?º{x§f€ªôj=Ž%LÇí×o¾õúñÞ=±Y”$!A$‹ò-�3|“CDDDD�Î�úyš‡Ñ«¯|ñ—åÝoÏÛØîµ2·ì©³4wïÜS'rÚwí7/¿òÓ_ÅÆ궇Ís—4å�SÈY-«9T]ÕU>Ú� /ÿ 0� ò*ÏP¸:‚{åu¨‹AÈ 0q¯Ô*±J]& sèÜua:˜d{ÊŠ!Žª�Á|ÐŒÖSmÓÅñ7^}8–á0 Ÿ ÙÁ¨qÕ{ݵ.íbk&º-úÍ©MºiÓ_»þýàû‡îõ¨Ýh'•u­«öTÿ^ˆˆˆˆˆˆž<ö­""""¢Gg@¨›ä¾H©–°ñâ˯ éèû?¼yûÖöhÔ$‹ðÒuÊEMÐÅxØ6;¯¼rýÕWpõÌ–s&î08€xù÷h'åèÃ+øaßZ‘ôà»®%Å`'¦zà#´Îz â%ZrU1`Ža¨�L÷g3ÑF¥ 4 ¡‡f„×T¹ŽY»$MÇU¼;Ÿî-æ ßL‹T«¨&öøkIDDDDDt–0ç """¢Ç¡žµŠäEŸ»z{wëó“ÍfòNo¿ýv¯%Ä  šÝŽ�K¯¾|åSŸlž»•ENCUiÝtn¦%á‚• à,“� Ã"àCÄp<ÌûXÐ[Gû}@V@ˆÂ4ÁÅsˆp©RT—¤Ú…r÷©†0ë‹Ù¡µ¾Ó”«J‡¡__'""""":/˜sÑ£SÇ|6lN&±Ö¡Ï‹!µM+¯¾òÂÖæ _Z,îïßz÷æ½ý}‘péòî ϽP_ÛíDZº´í±:š/’„fiF&°nèûE¥a£™GšwÂzDv™ÉQ>¿hå^äÁa^KUõgyu²sš]ó{Þ÷ªPA‡¹¸y†b`ò°ÙåBüÜö•š Ù4z6›ç!ñtÚ[HDDDDDôD]ؾÇDDDDôˆ[`©K¹«‚dz”RŸ‘!¦0�.�k-¨€Æ$vzk=lÇñDíL»Tknê&¾ 9² ‹ôâ !_Þ¥Ý0¨*6‹ÅÉ.€IDATGGÃÕÿûÏÿ�OÔ�¾ûΤ›o´ _ £qÙm †C„T5-��Ž/íýì•çÿÚ¥Ëñ8_µ‹Å,ïîõýE»?‰ˆˆˆˆèÜc==IX¶˜2)Ÿ¬¦ˆ‹#Ô-:Ä5˜9´\X&�‹Caj€˜Ÿ¨á(Ÿ˜@qÑW= u¨nŽôÅÝíw®^½}ÿÎ÷ïÏbn6Ú®ª ½¿}ÐLj$9˜VÇÇ/×õç¯Þø…—_y­�Œsö¡7xrË ‰•¥N{Óˆˆˆˆˆˆž æDDDDôÄà&€: ®\J8!âˆfêÍÄ .S‡ˆ«Á ˜À[%j‚àvÚùñÞ£å>q ®ê(­¦ê\ÿâ«/Õmü?ßøþ_Üë’Ú:G�lOÔQç,ó¹_•ø•K—ÿ—_þòå«W‡¤ó0©5…�²å&""""":/˜sÑãs@J°q²Cu]_ÍÛP)×pàbs±Ò¢ÊW#: ½`ÅâÐÕæ›¨*&ÐÊÒ|ïÞK—/µŸ|u< —~üÆw�öo[>ž÷Ú÷i6‹v«ñ+—.ÿµkÏýÌó/|þòÖæq§ÝÜRªkq­“{J&¾µDDDDDtÞ0ç """¢Çà%×0@Õ? LÀ Ps_–)¨C–ñ³’p\°r¨Ã\ƒ+`m¹Ú2ŠÈ%+JÔ’†Ã{[mýÕkW_½²ûÆôè�ƒÃ{Ó£ÙüØ7†­8~éòµÏ\}îÅÉdG0ž ˜yîRP­ªìH½—ª ¸`õ1DDDDDtî1ç """¢GçsU¬ª\eU�áë+T`bpU ô°rA 9²8–7)·0q¼\ \œ>KâË–,Zî"ˆ‰›ÀÚq1lŸSÕW6¶?;Þõ:¸[PŒ¤žl8ª>;ÆâxÔˆ«ºúÂRNpÓ‘4µÔ 8ŠœˆˆˆˆˆÎæDDDDôX\ÔJ qâ"˜¸&†Š;4¸ Àª’ÃM «£Œ£P‡øƒ#þöp'«s/8 ‘,ž,zÖl“ QÕf3tYL®Ž·ÇmÜߟ†(1%O9ô¹Ú ±®³) ‡÷iÄ6Ô�WÒ»Šf¹(¹]Ì9ˆˆèLXuíÇ{Ô,Ï _}wý±O-G?}u®·xið²¼­­Î(wA9=œˆž’C%þ ÀD]Ìë®C™ä¸H¡Æ°åw_\ŽK©ëêºUO.Åv‘†ãw�wª ¦ ˆAà–‡~H!£�©ŠH]U�VXØb±Àè´·�ˆˆˆˆˆè‰bÎADD§oÙ›‚•ƒ¡pA.ߨ˜.¯ô¦ª©‚ÍŠìæ9K¶V58‚Á&šIa£¢§Ç xÏ�uè|ùÇ2t\Õ}¸†¼Ì#�°¾¡®JC\Ì–·º@Å.È0 ÉËç?2Ä$hƒ&8ÒÜ U+€ÌˆPGB „£‹z¶�µÜ¹‹4PŒü:ˆˆˆˆˆˆÎæDDt˜‚ÒÌæAÅFàdË×u�þv26³ÁÓ�Óà�€¦©+QŸ/VËÔr[»è§†}<>àÐùú±ÖÈ{'ŠkøKgŒ_¨„ãÄVcY£vò®ƒ– (?ô”fßê=ßUøCu6Y/âýIDDDDDçs"":Ê©ß×rÆ·‰Úªë” ‡@ËŠ½n ÔB�{žw©³Ü„˜*%äP“‡Ò"""""""":g˜sÑ釮£1¸º7Ë�CY u,{ßÉ0C !ƨ!vÙ²ªCPq“€ 8s"""""""¢ó‡9�%ÃXΆ:Ô&ËÑ‚#¸©CÌæóã Ò¸4£˜˜¥E?b]¹#˲c•B d8íí#"""""""¢'�9� â¾ú.ËÙã)“uÅ—!G4«Í«°Ü&G24"˜§aB_ÚV²|¥óG\-"""""""":Û˜sÑYQm”`ñeÈáÁ-zª²5–«d@Æ0 {÷ïݼ3»¿Wgloo·×¯ãòΨ®b ó*w°ŒÚÊb…«ˆˆˆˆˆˆˆˆÎ'æDDtæ¬C u 9MFÍ0=””7¶·0ïúw~”ö÷¾ýGÿ½ÉC� 0»-TQ_ù™/m¼üJõÜst¿[Ì“x¨58£"""""""¢sˆ9�-uQ‡B€xÎóùHu£îß?zó‡w¾÷†ïÝ¿2ïÚºûÆ÷î¿ùýjvtE}Ë Éa€ÀI‘Ô\LÍ7$lAÇG‹ÙߺÿÝ`zT‡ÐuóÓÞ>""""""""z*˜sÑY p…kyar(JqLÌ¢ f³ÙÝ»a>Û‚5}'ÇÇp@Š>`ÑEd…¼[`6ì jÃñÍÛ~¼ÕMÎÃio =Ì9ˆˆèLXÖsüÄÄpqÔ*Èi¶w·?:Ø©âfX,‚é5.¢Î£Ì#†€,*ˆXôQëÝz£;˜Þß „pÚÛGDDDDDDDDOs"":c\ÅQþ©CÌóôøî­ÛLJGUŒâ†¡GÛBÄBìƒ$�I5‹æ’‘´-†âUÐãƒý½[·Óô0¤$°ÓÞ0""""""""zò˜sÑ¡¥{•Gp¨c1›‡çž»wïž6UÌó€I›†¹…ØkÌáLƒ‰¸šÞY«�áØæ“�º?¼ch‡œ£È‰ˆˆˆˆˆˆˆÎ!æDDtú\`xoÁ…:ÔQÇûG"!VU  Ö÷*Á.PG´å¿àP7’ä…÷¡�fÉ-a:mT”1ÑyÄœƒˆˆÎL`mÛ¦ƒÃ�ɦ÷©õ8²¨T«˜­²Te«Ì›lMö:[4ˆ¡Öà)Çsö¦y7T±9ím""""""""¢§‚9�-^f’/Ó•Ýý¹ç^®©Ï,@*¸EOµå:§Ú¬Î¨2ÔT­†ä¦a÷Æ ©[ÑD݈ˆˆˆˆˆˆˆè¬aÎADDg‘˲¤#[ŠmÛ\»^·£ùlဠó"E·*{e&d 9²‡£ù"´ã­ç_ÄhcaœÎADDDDDDDt>1ç "¢Ó'^¦�/Ù:äṖuÄd²{ýy«šÔ=,GyH²¸ ¸BÙó�¬ª6¯ßÀÎ%�qaf—<"""""""¢s(žö €ºÁXN/!ˆÚA[K×?û™[Ó£îþ¡ui«RG†ÀÄ�h®ã~Êáê¥f2¹úÉO iŽ<§ÙµŠˆˆˆˆˆˆˆè\bÎADD§OÁ˜ ̵Ìç(%c‡ì}½öbsóæt¦‹yhkï�P âPÕ,U{pt|i{§¹|©~ù%�á8å8j|‘…½«ˆˆˆˆˆˆˆˆÎæDDt&w@ͬZWIÐA%7UÌyçK_ظº{óÛ¯ÿ�^n¢f‘*uI)¹‹‡zo>Ûyõ•­O½^~1y¶¶^d«¡á´·‘ˆˆˆˆˆˆˆˆž8æDDtúÊèŒRo!Y}îÐÁÝ¢˜„€°YWð+–Ãöäþß—Á%KÔ‚@Tªú…Ï~¾¾|9<ÿ¶vÒ¨É!˜ÂE]¬ç """"""":w˜sÑé3 Ôp¬“uˆC˜†$èÄc­M¼2iÇ7®n=wuz÷î½Ûw�§ê2™L._»º¹{µ¹~m‹Ñ†7õ"†q¦DDDDDDDDçs"":}^¦Ž¯Ê8Ôá‚àðeUG€ø»*õdT7Íd÷òdÑ]7ƒpGP4 ]:÷>٠ꔫѹ܃ˆˆNŸ ’¥i•CÁ–_f î9%s‡9²;^Tªª®ê@êº> iÞUãItp3‡Šf©ÜÍ\#s"""""""¢sˆ9�>²Â1#pK F6�ºš­!ðœ]Ù¾úüÐõ‹aXX€f77Ú¦ž.º$nî"AÔ.ðS;í %"""""""¢'Œ9�>$… h†`YÏ€ š3à ‘UuúîÞ¡Hhªºi+‹~ÑÍiÞ5-D€«&†h ƒ{fEѹ܃ˆˆNŸøCŸ8à²ü<ŠŠ »#‹ˆAÄÜts{kѧaHÃ(æ` {?W TeâÜ|±¨¤\– À e9} Ô½Z>»•Záhù\ÌÎ9ʨƒˆˆˆˆˆs"":}â˱EI5>¬þbu"ðCÊ–Ÿ—å<|eÖq}œ%Y.Å®0ˆi¹D_æÎe7A"""""z"˜sÑ“’Dúup-ÄÖÕ t]®Wæ-±˜ƒˆˆˆˆˆs"""""z2¦JIÇrWZâñò…žöÊÑ9Áœƒˆˆˆˆˆž�•@Ã\ÔaP¸*.%íp( âêÀNP"""""¢Çœƒˆˆˆˆˆž…GÀÊ(rƒÂ®€Âuy À)C:uÑ£cÎADDDDDOˆ«£1Ǫn£ WwÅzjÇòr@ €"s 9=æDDDDDôd¸¨ù²b€ àê²űÊ6–½ª\Lààr"""""z<Ì9ˆˆˆˆˆè‰ÉpS‡»»»9 QU÷ ÀE3`¸8‚Tž€ªŠHÎ9çlf1ò­ ýDøæ�ˆˆˆˆˆž 3É ¸ `""âÈæžƒ%ƒ$×à*qè³[X/ADªªŠ1ö}Ú[CDDDDDÏæDDDDDô¤$×Þ$"Ô®�£®‚{ÀÝáîà·&k¥’ÃÝÍ,ç|ÚBDDDDDÏ æDDDDDôIJø`ñè¢Ôb (T*qS÷è¦fåZ‚U–sÎÃ0TUuÚ›BDDDDDÏæDDDDDôd bLU”¶ÂHP‰©ZDF2² ªCÜ>¾=øàîbŒUU•)§½)DDDDDôÌ`ÎADDDDDOˆkðZQ©Úè#bž£_àø`æ¹›õÞ§*Ô›[[¨¶1ÞÚNÍ<çÜ÷}Î9Æ("¥°ƒˆˆˆˆˆè'Áœƒˆˆˆˆˆž qÕÔª…€VÐØGûØ¿½8ÚîÝ<ð.ä…Ù€ZÓ¨Áx<ÆÖÑ�Ÿ³æêÐ4 €”+9ˆˆˆˆˆè£bÎAô $uË€˜š¨#ºÀEM â&’¢8ÄrÚkLDDDçœZ†Z%Ö ¡ÛÃþ[ùíîß½uxyójð6Æ6 {˜OÓÑÞ¹þ™öù·bÛð uь压ËÚì´·‘ˆˆˆˆˆÎæDÏ,1ˆ‰ ¯ ÁpI:èÂ¥ƒ¨@Å+À ÑÓ#I¢yŠã û·ñÆÿ\ì½{„A_Ùz±ï“ºÁ²y‡ kS›n^½½?«î§O}ychš£þN½)î@S‡â%ßWgÔADDDDDaß[¢g˜:à'ÏpT˜ÀÄ |\]Wœ�w"""zêú¡«B<>ÀÍÙì¾µy»± æ^gUSqÇjWÅ‚ÕÕü’ìï¿«ûo!Ï¥Ö&§dž ö „j|çBDDDDD‚Y®ð^Á�0À�Xkàœ•[DDDô±põê0¾'ýè‡oÏŽº*Ôuhs*u¥úž7 b"Y=…½»oÿø~?OUåE€ëê&¾ÜÑ „ÅDDDDDôæDÏ.…Wðzù@–¤Ò ²ÂÔU¬¯Äk± àÍADDD­µÃý›‡‡{³JZ„ µXTדå¦e÷$*¢´CçwnïϧC�J,ÔÕP<¨FuHv1H:í $""""¢3‡9ѳKÍ+GUÎsT �A1 ®@\Ös  Y�IDDDôÔ¨kdzCܽu½·£ÔÁDÔ€®O¼p¬ZRAƒ£r­ec>͇{³Ü‹ µËkK©á0Hráþ ½s¢g–Ÿhþ ’ƒ ‰›¸ŠõˆeÏ0ä ""¢�‡ >>ìŽmܨý f°µè*ÞXG CÐT#뱿7˽Kž\ýd=‡A$Còio�9Ì9ˆži'2  âW/#ÊeÙB²KruÑS&žÑϳ'mêq�´5RÊúPùÃ7ÒM¬±›õp‰±zǃ÷*åt�uq*÷gˆˆˆˆˆè!Ì9ˆžiËwû/Ô!.€®Z=$ ­R ""¢§NDcŒ!„œ!‚¶…Ù{wBÖƒ:B@Î!3‹uݘىbŽ5îÉÑ`ÎAôÌ� D“#O§Ó4x­ãn䘳Q·az¸7j¢y_Õ2äî´×˜ˆˆˆÎ¿®ï5êhÒÞß»§ŠñÞy×66ª”’»«BÃ7!ªH»×poÿ°OýöîÎ0@îÀ–-:ùž…ˆˆˆˆˆþ2ñ´W€ˆ™Í‡CÓ4mÞjª�¦º$:LªË2«ÕµmÛ`’²õÙDDN{…‰ˆˆèœ3ñ­Kã|<„¡UDä²F�P1ÀÔ!€Ã�fVÇL6«z$ƒnI+5_V|ˆŸæADDDDDô>|«@ôì2Ç¢ÇЊ�ób´8ͪã}�§Þ+•*ŠYŸó�“‡À\“ˆˆˆž6ë1o·âÆn›tq´è- ÖX YƒCrÎ(-¬D¡ª¢&uN²H:m7ÃÆvä0@³‹�ˆ7T]ÄUœåDDDDDô^|“@ôÌ Á䤩o%_­õ…V^P¿²9ºÞ-lr!€´ú >×DDDDOŒ‹íÝn·åÆ+»íf<öläFiP%€¸— ÙÌB¨N{…‰ˆˆˆˆèÙÆœƒˆˆˆˆˆžº‚»çœKß*U-åÎDDDDDôx˜sÑSgfÊøñõ… 9ˆˆˆˆˆèñqî=«XÏADDDDDO�}ÄëóÔ+"""""z,|SADDDDDDDDDDDÏ*æDDDDDDDDDDDô¬bÎADDDDDDDDDDDÏ*Îç """"¢'J~âÎ󮈈ˆˆˆèqñ}=i%ÀøI>=ÖsѤðŸø#Ñcã[ """""z²ô'þHDDDDDô¸øî‚ˆˆˆˆˆˆˆˆˆˆˆžUÌ9ˆˆˆˆˆˆˆˆˆˆˆèYÅœƒˆˆˆˆˆˆˆˆˆˆˆžUÌ9ˆˆˆˆˆˆˆˆˆˆˆèYÅœƒˆˆˆˆˆˆˆˆˆˆˆžUÌ9ˆˆˆˆˆˆˆˆˆˆˆèYusŽaÏf3)¥r¹»÷}ŸR²wÿK–Ó÷ý{®°þr†®ëÊ:yùú§›Y×u'/ù ™Ùû7g½(""""""""""¢ %žö œ‚ªªL&“òeÎ9„°···»»[×õO¸w/Wv÷aT5Æ("Ã0TUU~Dù®ˆ”ËÍlý-Umšf>Ÿ�F£rÉáááæææl6«ªê/Y Uu÷ÅbafMÓ¬7‡ˆˆˆˆˆˆˆˆˆˆèºp9G×uMÓ”w/y€ÝÝ]‹Å"„P’ƒœól6ÛÜÜüÀ夔ÊÕú¾¯ëZDÊåëÔÁÌRJîc,Ëìû^UË:L§ÓÝÝÝÑh4 ƒˆäœ«ª‘“éËþܲÀÑhtr‹ªª*K&""""""""""ºP.\ÎQUU‰ ”:Œ”RùÒÌÚ¶-W›ÍfMÓ|XÈ „€Uëªr¸{ι”wˆÈh4Z—eäœçóùÆÆ€étÚ¶íåË—ܹsçòåË¥Àáááh4*Ë9™dœ´nrÕu�ˆÔu]r""""""""""¢ èÂ媺··wéÒ¥œó�;wþüÏÿü·~ë·îß¿ॗ^úò—¿üÕ¯~õsŸûÜx<PúJ}ØrÊÇQäœsÎ%Ø0³ï|ç;ôGô?þÇÿxóÍ7CÛÛÛ»»»¿üË¿ü•¯|å¹çž‹1›ÙÕ«WSJ¥«Õþþþoþæo–&Zøð¡!„ßø�ßø;çïììì”kþåëIDDDDDDDDDDtŽ]¸œãøøøÒ¥KþÝ¿ûwÿá?ü‡2ŠüÆ�óùü­·Þúæ7¿ùÛ¿ýÛ¿ök¿ö¿ñÛÛÛënTïçîfVBŽÒ�ª„¯¿þúý¯ÿõw~çwîܹ³»»»³³“s¾ÿþÍ›7¿õ­o]¿~ý×~í×þá?ü‡“Éd†ue‰ˆTU5 CŒ±Œßø°* ÙÝÝ-å ‹ÅBDš¦aÈADDDDDDDDDDÓ…Ë9JÀð[¿õ[ÿù?ÿçû÷ï_¾|yggç[ßúÖ•+W&“ÉÖÖÖþþþïýÞïM&“¿ûwÿîµk×þ’E¥”JEÅ:®øÞ÷¾÷/þÅ¿˜Ïç1Æ×^{-„Ð÷}iBµµµÕuÝÞÞÞ¿ù7ÿæõ×_ÿ'ÿäŸ\ºtéàà`{{Àb±øö·¿­ª‡‡‡mÛŽF£¾ï?ð‡Öu½··wxx¸µµÕ¶­™™‡sÑÅtárßøÆ7~ë·~ËÝ_xá…íííöÏþÙË/¿ àÛßþö×¾öµßû½ßûÞ÷¾÷Û¿ýÛ¿þë¿þa 9YêQf†ïííýûÿïͬŒÙøÊW¾ò÷ÿþßÿÜç>`>Ÿÿñÿñ¿þ×ÿú�wÞÙÚÚúæ7¿ù;¿ó;ÿèý£ííí£££ÍÍÍÍÍÍ·Þzk<»û¯üʯü½¿÷÷Jpò~Ã0<÷ÜsëÁ!ªjf§}��Žs›sô}_I­'^˜™ˆˆÈ¿úWÿj†ñxü™Ï|æŸÿó^r3ûÜç>÷¹Ï}®išÿôŸþÓ½{÷þãü�ëoý­­­­›~áîeùx<žÏç·nÝúƒ?øƒº®Íì7ó7ù—¹”Y¸ûh4úão|õ«_ý§ÿôŸ~ç;ß¹råÊ¿ý·ÿöüƒ°±±±¹¹Y 2Þ}÷ÝÃÃæi^zé¥Ï~ö³ëéèë„Õ¨óõxs)%3«ëz†ªªrÎeÃ×£;Ê ?påCÃ0”!e‚ºˆ|ØõÏ¥rŸîËÿùò¾vWU„BæËOUuý»¸ Tµü¯ƒ½ò ú�;ay¡¯îÊÕ ;\V7Dz훗¿º”RJ©\¯<Cƒç²ˆåÒ|õñin¬¯ÿ-örÖ+" ˆ˜YÎYDžòJýÕbŒïyœ–ç«”Òi¯-‰ˆª®¤e�‚%¹DgÊz¯¯Ÿãßø™Ÿù™òUÕ7ß|³*Ï?ÿüÉù%ÛXn.†a(QM™çQþ „Ö‘L™ÿq29IDº®+ÇjcŒ)¥¾ï/Ö~¼”ÿD ËÿÊþÄÝa–—�s.¼²;uÚëýñ)ïî°J JýP¹>ì ËÝÎÕ ‰1BE‚˜‹ª† 1.Ϊú:4³lêÖ¿¬$²þ O‡@–"Ëÿc½eõN‰Î õŒ²»»~—ÊÇ)ÑÙQc®OÝ.�S>Hé=Ê_Ha}ìâ‰ü‘œÛœ£û8qþxùäw÷wSJu]_¿~ýK_úR¹r !JÚñÚk¯}ö³Ÿýú׿žRúÚ×¾ö«¿ú«'ë*ÊsÎ[[[å†ûûû1Æííí?üÃ?¼zõêáááÏÿüÏ—ï–_UI,Ì,„ð•¯|åÅ_üÓ?ýÓÍÍÍ?üÃ?üéŸþé’F”:Œííí§?ý麮E$¥Ôu]Œ±,!¥t||\æy”Ò�õÆ–ŽétZUUÚ1 C)A8yµ÷Ü?)¥Æ”x£Ôv|X¿¬sé/©çxp�‡ë7.Z=ÇÉg™÷Ü-tõ­ç0s˜X†eÉ’MàþP†Q’éºîgögëº.ÀíÛ·777˽¿®Ž\Ç'ëÉ?üá···oݺõÉO~ò…^(70ŸÏcŒ%) \,UUݽ{÷‹_üâz%oÞ¼yëÖ-w饗J-€aDäÿaï½ã-­ªûÿÏÚû)§Ý2w3‘ŽÔ ш¢ÁòE¿¶¬?Œ%Ö¨Q¿&–“5‰%�ß•—1_ VDEAD¥+ `˜>·žú”½×ï�uΞÃ03ÞÁ;Ü;3ëý÷ž{Îsö󜽟½÷ú¬E‘…E!jMQ¢dì®B1ä-ò<ßS|†œ‚\9/cLš¦yž/ö÷öàÁ°``@0Æ€û‰”Jï1�:È÷£ ¼÷ÆD‡T*í°¿ó¢1{ïw›Ì-`Ø0c F.- Á†vY’EѰ„!3y“3WŒ1l`ƒA•�ýƒ\>ˆØ0 ذÁÎl]d ™��7Æ0¡þ ,MîŸX#¨û‹Ý4EQú„JTÃyÿÃJRQ”¥@H²ÿÏgÝ«(Ê¢vd’bzOùºEYtÂ8=¤òÇ(óÁ ܈Å|± =ä ïd2ù‰bÇŽDÔív¬Y³¦ÑhH€LQÄÊ/±+W®”2›7o>öØcÇ£#C©sc̱Çû©O}*Š¢_ýêW«W¯Æ OúýkNnܸÑ{¿yóæÓN;M2SÕëõÉÉIçÜØØØI'�455uíµ×ÞrË-·ß~ûúõë­µ'žxâã÷¸Ç=îqkÖ¬‘CIéfÉL%�ïv»•JEÊ’‡0‘½OöË—/Ÿ™™Éó\R]cÚíö!eÄg’ÿ<Ãy‚�É9v&êG¿:ç¼ß™OÐ9ç¥J4U˜Àà‚3yvDÎGìÆ{öû]çðä=13Œ#8æ¡Óböž¼1C)ì4o•²è„4œUúçb7MQ”>AØ?Ë„¨ãTQ–!@hÖqª(KŠa+X˜U÷¼?Ueu„á‹Ý4e !Fòa7h)�¦y«öȰñT·oßîœK’$ÏóZ­&Ùä•Að�Âà###Û¶m‹¢hÇŽ!—†BCÂ{´ÛmÉe­=å”SdY&‰­B9qÓÓÓW\q…h-GuÔ#ùHõzÀÖ­[“$i·ÛwÝu×ßÿýß_wÝu’öJb;n¹å–uëÖ]yå•øÃŸóœçŒ��W«Õ`y—JŒBD¢mÜqÇwÜqÇÊ•+÷”ÿ®Ûí>þñ�—êöišŠÜÒl6)?&€#ÀÀ`#p” ¶lLêQv¤c8Çram­–{IAq±€1&I’]Êà Ñ,G†­!ø„@0%9“XXÑIm¢È Rv�1&Žã$1•¨BQ•#_Zy$ˆ¸È8ƒØ{ó èˆ¼'6ŒØœaëmÅDq÷ˆd®6Æ$‰5ÕjQx�çP�(ŠäÖ�dœjþSEY:„Zˆ –_uœ*Ê’BB7Â^/MSI†¼ØíR¥�¤ žšQU*Íû¯(KŠ(ŠBòÉRS©T¤(òb7MYBÈžH¬Žýt)ÌòÃos؃YçØ¥D•ä­Ê²låÊ•³³³q÷z½J¥233#e9¼÷!‡•”÷Þ·Ûíá£ÉÄÓëõªÕêÀD›t»Ý8Ž%$¢Z­+òúuëÖýû¿ÿ»s®V«ýÞïýÞÄÄ„üµÛíÞu×]iš¶Ûí©©©-[¶T«Õ#Ž8¢Õju:©CžeÙ­·Þzç�w6�?øƒ?X¹r¥1F$ ¹}Hp‰,Ê;�Η¿üå /¼°V«íi¾?ãŒ3õ¨G�ŽŽÊ)QµZ §ˆôeBÉ@Ž@êN` òV�ÁdŸƒZ­šÚꡤs;cYdI—ÛCʼø`@È1\�5 oÀ±¨#ª×ëR«CQ¥‚:!åQ©Ï‘‹$ˆâý[ ƒÑ×9ˆ½$4Á,¤iÚ�¢‚Hæé¸‚¸Z­Ö"¨Î¡,=Ò4­T*šÿTQ–a=ªéìu>Ueù{i°Þ“ÇÅn—¢(;§‚¿éb·KQ”�=CæSɺ¯I •]�YhEQ$Òõo؃vÝ&�(¢DZTËèv»Gy¤äk  7€^¯W«Õ¤~Ʋe˶lÙ’eY§Ó ÑÃ/P…DcˆGž|õz½(Š$!jGY–Ÿýìg¿÷½ïèt:§Ÿ~úË_þridQÕjuË–-’¸™™O8á„ç?ÿù{ØÃFGGggg³,»îºë>÷¹ÏíØ±£Ñh|ö³Ÿ;ûì³Eÿ(ËRŽ�$‰È6¢£ÌÌÌÄq¼—ú–ò®,ËdYP­V¥âú!Us�· fƒKê"’Dqè×�`ï½u|hU ‘L2?‰uOW´ÿ.fõc/€Ô±f`4›M»¬n¢˜óÂ{ŸXÀKÈ”aôÅI b€Á´ŸSDqøòY>ŸXžd�™e¸ccïûì™5o•²è„bT! O¦ªCêf¥(Kœà|#«y ‹ >Š¢,d•ܪɱKmLEQ�à~*%KÃó:NeéÒáˆ%6xöè8U†ö&ã¹÷þ·¯ãrÐêÂ.^rQ‰¥r¸vEXÑÊ4)Å*ʲÌó|8/˜1&¨rX9äÅI’”e)yBä8›7o–rW^yåç>÷¹{ï½W÷þð‡¿â¯ß±cÇŠ+$¤×ëI²¬3Ï<óÜsÏ=þøã”eÙh4Ò4ýƒ?øƒÃ?ü³Ÿýìu×]—¦éOúÓG=êQË—/—"-Òz½žÜ2Ä—¡^¯ÇqœeÙž\¦¦¦˜9MSYÊGQ422‚…(m€Ñ?]"€ä—på²’‡�µlxMè7œ> ½$¿ËD¢x�<ˆ ™%qyxyCÿ¡ÿ�ú‡Ù¯'ØoïÎÿS¿ý°ž(ŠLd­uýsퟨ¢,&÷•‡òmJQ–8²l³Ö©c±[¤(Ê}¸ •ŽSEY:ˆ}Æ \:Neé—uœ*ûÄýïí€CBçcIRÂèt:òŒd”w‘ªÕ*µÛmyFL±÷œ¡¹¼ ƒt®QMNN._¾|Íš5ëÖ­ûä'?yï½÷æy^­Vï½÷Þ—¾ô¥¯yÍkʲìv»+V¬`f Âøó?ÿóJ¥’eÙÄÄ„µVž %@¬µ�|ä#Ï9çœõë×çy~õÕW?íiO[¾|¹$Î’³�&¢šH•r©ó¼Û+sÌ1Lj<ã½ïõz�FC*´§Û:èa‚¤'2ðžàɦ_ŠÚÞµyg<‡'(Ý™ï‹ jßîèÿÉ0<o@ýç¼gçÈ[±!À^꽇a‰V“ŒeéLLý q¼1žàùAªÏÀz`<Á�‡)wV(éGq8xçhP±CQ‘û �¡Ü±¢(KYtíòŒnöeI\‡°tœ*Ê’Â97¼E•˜{¨ýTQ–ÁˆÂ8¤€ñb·KYZð rÉüö"b�£ï!>¸F’{jdd$I’PMÎ{Ÿe™A´�9;;+U+�Æ.[SIÝâ°†?Tª”/_¾|vvöÒK/ýô§?EQµZuέ^½úƒüàG!RŠˆòW«V­ÂPL†ä×’´Rö¼(Šßÿýß¿øâ‹ï¾ûîÙÙÙ_ýêW�{ÜãBnJÑKä-qW«Õ?ù“?yÞóž·—:´Ýn7Ïó,ËäÔ¦§§¥<û!Uh¨yî ¹�À‘ÏcË¥I{I¯’‰9çò<¯v»½’òC©>‡Ô� U¤$J†Éî^~Ÿ:ä™5ï Ê’\ gÄªÍØvjȲŒ*"ï}Q�.:�l.®EŠÈ£–GºK y-Kó::*•šA°Y½zu–eË–-“¼[éäÑ""9£€²§ûˆt‰V‘ð”8޹›Î úI™¢¾(*�³hWvP|[.õ!’5õ/Q?…×îo=ƒj'•M¤~YkKçdŒ!/¤í/O—3Ä`YkKøÁ7‚p AÕŒýÆ ¦ Ê‹õ;Gˆ¤#chà�ë½'²û¹MŠò›¹ü¢D¡ý–õ»EY@vÎ#C)UwY©*вè WgÄÐÞ{±Û¥(JŸ0$µŽŽ¢,evYñB×½Êý×gùyÓnüF�páŒ1ãããkÖ¬Ù¸q#Ýxã�§œrмF¬Bá²Þxã�bÌ]¹råêÕ«Å»‹Î±ËªWDŽË.»ìSŸú”ðˆ#ŽxûÛß¾råJcLš¦ÒŒv»-ÒE»Ý°|ùryûÜÜ\½^/Š"TÁ@Æßyf®T*ºÑívO<ñD ùŠê%ï’$Ï’÷^Š¥ßŸ,˼÷µZ­ÕjÅqÇq¸J‹ý�=x Õç0 cÐ�ß0† 6}éfˆÅnøƒx‰²jxf>Yó &cŒ!À Y6ÆCÜ/MŒ°a‰ÈZkØ™¡*sl`ƒýÏô?ˆØ0 ذA¨H/zËЙ£ñÊRàþ;½Cíf¥(Kœ=¹Jè8U”%Åð `§Š²”ÙEžTei"ÞÃ‹Ý e !Õ \ý:øuŽa5ÂZ{ôÑGÏÌÌt»Ý_ÿú×�N§V«íR!ÀÍ7ß,Ãï°Ã ¸¯¾Ò ‡�É»ï¾ûÓŸþôÌÌŒµöì³Ï~ík_+™ ¤ ˆ r´^¯'òƒs.˲K.¹ä¢‹.=á„^ÿú×[k;�N’$ÕjUŠy˜››«T*·ÜrKµZ�››;úè£ÃÙa�\QGÜíC¨Ên/Kš¦òéÞûjµšçyžçAË9D`XJbê�³÷Þ{ŠúûÎ9çv†5xï©:äÒÏCÇðuØÝËûOÃ<�à½Á“T{ïÉ{Çp¾&…!ýÖØ{ßÿ8ïåòx°ê�{ï‰ÁÒ+À€Ò—B™Ù#üî½×‰ZYtD2”¹L"90¨JµØMSe'Ã.22ƒ@ýOe)±Ëx”qº‹Ç�¢(‹N؜װÕu¯¢,†óëHöï`?Yì¦)Kˆ–nã ²â:˜uoQ/¤¾Exò‰O|âÜÜ\µZ½öÚk%rbzzZþÔëõä‡k¯½Ö{ÇñcûX ÒF1³h ÃÎ’]‚9¾ð…/”e966vì±Ç¾îu¯«ÕjRÜ#¥ä-Î9©"5ÆkµZµZ�™™Ù±cÇ׿þõ;v`P\ @¥R‘�½ì²Ë¶oß.ßú™gž @)¢H8åP&$<³[$IR–eµZm6›Rd±¿±%„X´wzñ™$)$—bÇ2-%I²ç"ä{£( nEQXkågYrk“!Çqš¦2p–Ã=!ü¬~CÊ¡( ²Qš¦Y–iÿT”%Eˆç ¬~û䳊¢,,aw-?„ŠŒŠ¢,)†Sº‡ªW‹Ý(EQv2ì" ƒT={”ûc­•*hbrtÎ¥iúÛK‡œä±�}ìÚµk›ÍfY–üà˲”ÊEQÈBöÓŸþôÖ­[%•Ó³žõ,$ÄŠd­•  ü$!€™™™»ï¾{ãÆ�sssÏþóEŸc®”4—wE!º…ÌÍι²,Ÿö´§cfggÓ4ýÀ> ¡ò‘h·ÞzëÏ~ö³;vLNN>å)OY½z5KðP½\QEQEQEQEQEQ59•¢(^úÒ—~èCZ¹råe—]¶fÍš—½ìeâ8.Šâ»ßýîw¾ó�z½>66öÄ'>ƒxq9/Šâ#ùÈwÜ!îüà%3€_þò—333GydµZ=õÔS7oÞ,J”$­JÓ´ÓéT«U©±\…TÿóÞ·ÛíW½êU_üâ[­ÖwÜñö·¿ýOþäON=õÔ²,‹¢h6›?ùÉO¾üå/ßsÏ=kÖ¬©×ëÏ~ö³%‚ÄZ+A!‹}QEQEQEQEQEQeq8ät޲,Ï:묛nºé¿ÿû¿×®]û½ï}ï¿þë¿ýèGEqûí·Kð;vüñ/~ñ‹Ûív(^­Vã8Þ´iÓ¶mÛŒ1EQH ˆ°uëÖÉÉÉ8Žo»í¶×¼æ5;vìX±bE³ÙÌó|åÊ•“““ãããι^¯×ív˲\±bųžõ¬?þã?vÎÕëõ3Ïçœs¤Z¸äSBBžç�N‡™¥¢8‰Ñ'''+•J½^?âˆ#î¼óÎ4M{½ž“Ö€÷~ff†ˆ*•ÊÄÄÄììl³Ùl·ÛRºC^ð¦7½éè£�þèG?Çq­V‹¢èöÛo÷Þ¯]»–ˆ¶nÝúˆG<âå/ù)§œ‚A•¼P8D£:EQEQEQEQEQ”C“CNçȲ¬^¯gYöÜç>÷�xÄu×]wýõ×ßzë­Ì|üñÇ?úÑ�~ÌcsÌ1ÇDQT–e–e¢CHž¨^¯·råÊ­[·v:�²,·mÛ¶jÕª8ŽË²ìv»vìØÑív%!ÕæÍ›—/_nŒ™œœ”ôVív{nn®Ñh4�Z­Öh4¤I½^¯Ñh0ó3ŸùÌóÎ;ïk_ûÚµ×^»aÆÑÑѹ¹¹,Ë~÷w÷mo{ÛÃþp .)ËRT–V«522BDyžW«Õž´Š¢(Š¢(Š¢(Š¢(Š¢(Šò`sÈéiš¶Ûíz½`Ù²e/zÑ‹Î9çœ+VHHÄöíÛÇÇÇ£(Êóy×ÖÉ;'§ïíe³Æ˜ÃV¹fõ G¬~øXõhxçËfÔ;6’“ŠöZ„œÍo~ÍÁ‰”|w@ 0ȃY¾ * ˆÙ†ØXoJ6¼o¢‘¢(Š¢(Š¢(Š¢(Š¢( �êвÔྑ}çÆZkMÊÎEæ¹¥>®2Çí{&ÿgý†›îºçW­ÞVŠZ.ê°í:à6ß¹yò–;ïºyõÄÉ]sÆÚÕ�ˆe xÞ­¸¹òƒ&xò^Ä f3|þÌAð`ClÈðe0Š‚�¢(Š¢(Š¢(Š¢(Š¢,!TçP”%‹]� OL€ÙȦ%Ïl"$5ÊÜÜÌô7ÿÏ%÷îøÕöÉ ŽšqZ0ÁÆ RÃl{nëŽM6­ŸkÍxÛ[³üxªŒs9N>pßR��¥ê·Ý°[îWƒ¿lÀG È_+EQEQEQEQEYdTçP”%ÉÎ*ÐëdT«0G¥‰ o:SÓ÷ܾñ7ßþSowTF8©¥¥/Ú]Dj5ÌLc|Y²l|¼5ݹsÃÏ=gîa͇všo¥À|B:±²6€"0€œÑàj0à™@Äy°=¤â]EQEQEQEQei¢:‡¢,)Œ™~•Þ�$ eyFäêcñlwêÆuWß³õ6)("ßél(Š@·ƒÈRáâv§%�´ŠÛîþE¯˜Y³zm„±ˆÆò<'¢jµêœËó<Šô>ˆ€c0€° 6ž§Ñ¶NsåÈòéVË”Þ$ÈJg:EQEQEQEQe‘9T½¶eéÁtŸH<ˆ @d1E.s­3æº3LyÛa“1åLÞÃzD‘ç¦â‡¢ä–·s&�nÿ³þÞ_˜ÄYKÖZÞ{ï=cv{0‡Üý� ˜ÀØ2¬ç˜† ŽÁÆ™ØSìlBQjÁÄÃA7Š¢(Š¢(Š¢(Š¢(Š¢,‡˜SQ–:!>@D޾ðADÌÞØÈgåì½[ÖM¶î*hšm“mΦô¦3À²9FÇÓÅ“¶²£™ß~ëW€2ca ï} x"" jvþãCöæ@€" [Oðäó2˸]P»•Oõü\�N·„·ž5œCQEQEQEQEQÍW£(K ©}M÷�`v`K†É–9·6n»½™m²Õ9Ø/Õ"ˆà<çlby<5MŠ"öwv{³‘q÷Õ6À¼— „CKíØål=y&0yŽ‹¨ê’fî�œ©'=äˆr”ÞjD‡¢(Š¢(Š¢(Š¢(Š¢,*ªs(Ê’ÅöÏd˜™È{8²%SwºµÁÑ\œt=àðȼƒG%pÎÃDˆ¾Û›kÎ$•,Žcc1�:X²WíäÐ�ä@?Œ öL�óÆWë<±ºV+j �wKЄ§JæãBZ-v›EQEQEQEQå�FuEY:ìÉbî ð Ç\ .ºÅ¬�{dðî‹Dx�Ø€ÞÁqckÝNæb'U͉H"9˜y8¼c'l@‡P´Á3$<ƃ8&φ�’ÉÕ'ìêÊòĤ¹C»Š^¼­ðC•C-äEQEQEQEQEQ–ªs(ÊRã¾vsò€!"2`ç\Ù£Jé|×VËÂÃ8 ŽAäÑÏ[¬�+™ÈÚÈ•ìJcMì‹1pb YkCrÀK‘óûÙëéP,²M(Á0 d<•†ŠÒçQLÉ$@žøß,M–R¬wQEQEQEQEQEY\ÔYQ– Ä0 Ëð RŠ�3"°eŠÉ$ÌÞùÂäÉ ñ9¤n¹a6ÄŽ ¶Ö$¾„÷Dˆ‰¬÷¾,Ë¢(¬µÖFÆö$RÇ.µ: ŠŸz" I«˜ÀÀ{Ë †µ1 &Ë\§ëK‡®�¯ØD“V)Š¢(Š¢(Š¢(Š¢(Ê¢£žÈв„0 À¹È žˆ‘±ó†`aL𦽬I—wz“#uäè–\²¢È€£¢tEáÎ�)=Údû¶ûJµ}ø«M7ÊzÅ †D¡ùP•Ž¡"å€]ì«òàAlø¾l 9Š]éÉFm*a^ìv*Š¢(Š¢(Š¢(Š¢(ŠhÞ*EYr°äŸä%®Ãùl˜-»ä¤O«DËóVR�&|^m7)ëk¢4µ€ïvš¾ÌóNé‹$6+Q®Ìš«S<ü赿®,öé)Š¢(Š¢(Š¢(Š¢(Š¢,$ªs(ÊRBDîGQP?�•'öQٲlj­WW®]}2Üx­0¾îò˜�‰,%±û¬Ç0e‘`Ó¨¬ŒyeÖkØ“yâÙÆUû EQEQEQEQEQÕ9eé ù‘B<‡‘`�s®H’„»Ò4Òy»úˆ¿våÉ�9Òzm$IL^Ý.Ûã¨7P¸hϵ¹¨6qÒ‘kNŸ=œ,ö9*Š¢(Š¢(Š¢(Š¢(Š¢,$ZŸCQ– LòŸ„tø~i òÄž™á¼�‰lÕ’AÞ8æðÓgf¦;¿œéakÞ�*À°ˆ€z �uyv¦½vù §=â‰Ç<ätß«ÖªŠ¢(Š¢(Š¢(Š¢(Š¢T¨Î¡(K ò0 –â|œ$½^'MÓ8íÌÍU¢äìC?6Û2¹îÞÍ·Îv(²K=Wd½ e�F¥1V?|íèÑÇù¸ãrÚxýÈö @v±ÏNQEQEQEQEQe!Q�CQ–Æ0@®ÿ;_MÓVsºR©¤QeÇÖm+×LLï˜È)'Õ×Ì%+¦:ÙL/kæy¾víêFcŒqgܺ†A…`˜{ r±ÏQQEQEQEQEQeÁP�CQ–Ä`üb€ä�°a€`�·YÛ�M�å$Z‘ÄkkQák¹÷žs2ˆ U5Ãò)|vΡ(Š¢(Š¢(Š¢(Š¢(ÊA†êвtð@"o0ú¥ÈÙ�ü *±›)3o¨LƒÈ`â¢,"2Ö�¸0È`^ì“TEQEQEQEQEY@TçP”%…ï‹@?{Õ}žïw0ŸÄÖÃ3×Þ1y±a ±)� <ÁJ‚ƒA4¦CQEQEQEQEQ”ƒÕ9eéàÌý opŸÒžsr‘¡†ÉFDl®ybOp†J dr†­ßÍaEQEQEQEQEQ`TçP”%…$hÃì,ÔA äÁÒQàØÃ$y®ˆà½'&�'–g%UYXOv±ÏNQEQEQEQEQe�Q�CQ–Lq$ °ï‡`ˆà'?2@ˆ˜ÄÌ\�3û4N°gW,11Œ!‡´¯�REQEQEQEQEYº¨Î¡(KŠû'•ò ö†ÉS¿d“LYz&KDÖDd &ÀÎ33I1s†Y"&ê|(Š¢(Š¢(Š¢(Š¢(Š¢¨Î¡(K$%I­7ø“Œ'p�)`C ìáàÝ}F`ržû¿•¸/¢(Ê| ¢ð±ØíÚM;£(òÞKƒ‹¢0Æäyn­¦ªS”¥‚÷Þ{/7"¾«,vÓEé#ã4üFè𓊢,.a`†™TÖÀ:Ÿ*ÊÒ¡,Ëá!)ãt—IVÙ‘1FŒ²afÙ€,vÓ TçP”%Åp<Ç®sK¹�ðû}îQ»Ÿ0ø�¸�)Ê~Á¹¾v( ‚°V‹¢¥5u…#´Ðc­]jíT”C™²,e¿!ã4l6T�T”¥ƒsΩmןOezÕùTQ–Þ{§�Oe©aŒ ãT´ ±¼ï2x•ýGp« לˆ‚}ãàFmŠ¢(в¢(öCcåy¾ØMÛµ�¸ŸQ†ˆŠ¢Xì¦)ŠÒÇZ»[*§Š²tˆ¢èþ㔙˲\ì¦)ŠÒ'莻x‹ë|ª(K‡jµ‚ ä™�x`±›v¨0ìY…Áõ?Dô`Õ9EQe7„ ‰]$„$I»i÷¡(Š¿ždæ¥ÖNE9”;éð •à}§Š²tpÎ ÏøâéœÓqª(K‡0NƒñNÖê:NeI1la—qªëÞ“á|¹!¤Cã9EQåÐEüMvÒ±ØM»»$Ü òŒúŸ*ÊÒa8Ÿ8[> ôEQ–!³œ Ï�ÃJÇ©¢,)†õÈ�RÇ©¢,ˆHRÌÉŠ7ÔŠÐqúà ×_²[cBQÀC$o˜êŠ¢(в{B"Ñá²]Km}DZ¤ÄµÃ#™7 E9 )‰‡Ç©µv©ÝOåP&Š¢`�tÿqc´nª¢,¬µÃóiEI’xïuÝ«(K‡ l„2Wq‘®{h@Ø€xï˲‡r°ì�»^ÄÞ.§°‹ÅGQ– »ôR¼÷Qt`›>VýF9¸Ù“w`M%VkåçÀžìEQEQAʲÜíóÊNÌ9l¦Æ˜¥ÙŠòpÎ9çÄFyÀõv1Kã­µÖÚÅn‘¢üîŸiÍ{ï½—ú.eYcŒ1ÃÃðÀºŸ(‡2a6”Ùd8i2ªÌæ‹Ý4EQv�ꊢ(Š¢(½<@÷ñã4€wŽ€ �ŸvyÅ<‰yoÁ”òQ¶ÿ‰Æ÷?ÂXž<æ�|„ìíÝ1*€÷¾,‹¢(¼÷Œ1ÆD{Ò)w Ì˜Ä Øò³ÉAàA°ÀPòL¦ü!¢(ò¾ -�ãØÀÒ�a›R]dš¢Á/Ä€gï}¯—ÏuÄýi‹÷Q) 6Lp¦|ä�aã3Œ#Cð;ÃÞ“g‚#`0å=`Â{‰ÈFd¬"c ˆ@¿Ý¡åA�ö(�÷Î9ç¼÷Ì®¿D•Õ#ËÔ#�û°žÀdëA<ˆ¡$ï Lž©@‚—±Âû8EZƒ¹y,¹'‰(­T°sé«+XEYB¨Î¡(Š¢(Šr Á€�Ó¢(Ø9#[.ç6† 1à ÷-JZQÅy.�O#_/»ðŽllx_¤G€™˜|ˆR"6bï@0 f†gv ;0+Ê’„�Ž@†<Dd,�Á2`Dl H”û¢o �Ä&µiÎe儲–*+ˆªe ŠÑmbm®Ó›Îf’Ñ*jµf³9jã}1ÃÒ&1L0Ôà ¬�ÞÁy°EÄ Ò1©,UÞÃ"‡+<‘Ã1È‚Îaú]Ÿx VÎçàd*ñÜt«fÒÑ´ÁÈEN0©)�s¦y‚7\Zf€<¢}‘:ˆ�‡Ïã;ï’$JÒðƒ…3 @Ð+EYtTçPEQE9àð}'nXb0`Ø6Ì^üÖˆ=oÀ[oæïô™:�NVܵÁ9Ç�Jã˜5õ±Ñˆ»ðYì}ä�ˆá`D¾äáÌNã-c×�Þ°ÔašQ\9Ø 2=öÅ(IÞ›ýhªÈ "€òJ‘å{foÚ´éãÒ#W=ìèU§å=›¼/áA 8À`‡?zðÈÖ°™·õIQ#¢À}Ÿ1LìÉ@æ#òêÁä 0ÿ„V† åDÄyä(ò\­”iåžî�.îœÜ^ñþ÷[yäh%‰kòlM<ˆ ™/;]ÄEod˜�G�qMèÛTåÀÀÆŽelzbCäv³XìÇ,zbÃ4�Gƒ¬Ç•dlY’ô¦±õŽÍ>s�±Ñ•G�f d<å–Žˆ=Ø€,`æyüû¶�ˆ ¡çï7#²KEY|TçPEQE9� ÀÀx@žú{+¶ 0,yÏ;Ów$%,Ï×Îb —ßpÓæ_ÝÒju’•ËÖ–§ÖqB¥Èº½¼‘Ž ã#è�:vL»æÒ�?šA.¬\÷�ÊAN°ƒø~¦)–1J€!&ð|ucr¦¨ ¶äc2Ø‚³Ývo³K¶^õ‹/oÜ|»qé‘«1òø:«’hœ|2ß–R †<! ‡Œ_‚ÀðòIÅ£cWYÊú`™Š€~×õ,q‡ÌžD $�ôïy�Gëy‚5ðÜeL%fܦ¶^~×=·OO®ˆâ©ä!O_uÂhn㬈 ª—YÌ_w�vÞ©p€ ,± †#pDä-f6Æh€•²„ñ/‹ÑÈ;fG0ž˜x0èX”u‘7"°Gæ§r3PÂ!ǦۻwÞ4•uËÃÖFÕÚhº‘£ÈplØ{0 ¦ÈÏûøÞ8PæMA �Á³ I3˜ KkÒrвTP�CQEQåÀÂÓÎ,©d™.Ø ÜLJyvŸv_¾œºûNžÚš:æ9dSSõV;­$I½aòPÀ€$¦ÄƒØ'p?´ÙÛ—ô<Šrðaé8ÌÀ{`‘œŸ�…ijÞxG†�aÞÇq<Ûž¹ûÞ›9ž¶ˆÖoÌ[�ɉÚáà}9>"ÀP2"B˜�Å v�ÔYUYÚ0ÈßWŽ#H© huÞôÓédx_f*g€¢Œ"“R”»Ì³iÝÑmýd놩Ô,+ºÇLo},Ž­xŽŠÒZ›X[Ð>D0zºO½Éi 3ˆQë°! ÄÒ!©,q˜†åÒ³c²âŽCl¤Ø‰¸ õ¥ú7æñHLõ”²&º96ݵ­3ã]ng¶u·oÄC–¡´0ÌžÊ~y+oÁFR×Í󸀕 O(™ ˜ØÓ lCæwÚ)u(вP�CQEQåÀƒ˜‰ÀKpCèç²`C Ãý=—#“EpóÞ€�8_ä3Õ8G¥šÅ(}.|R£¤ÚåÂøÈä…Á3yË(̾•vô^× ÊÁÄp°Ô.Á þ�ÃJÀ?ŸGf[Vc\•¼íGZ�%äKâZÉE½æ ç�¼Í¨U‚òy}g[OÞÀ`g}æ`WeÔt%5å(K?dp$€$´Câ9<Á�†/Ì>”"÷ÞåUT*L†“ªOÛÖ6L=�êÕF…ºÝV³›š¸j¹bòÔ¶ÔcWλøTîÞ)ŒžDŠ‘ü“fg2Œfòýd«4�:°ËCÜ´&¹¢,t�©(Š¢(Šr€A}÷pb" Ü?ÝÀbiÅÓ¬ŸLßp„ÒøA–ðßôH¹<-ºEá=1yVvº­zTg2%g|a¼åþ‡z§¼þŒäê!6R]žgò€‘Ú!Šrh0ésâ~9Ãóy$ŽÉU Ó@S!°ív<ÈØ8ov·!I&îv‹z%5ìçy|À�7˜`vÍn'žã¨¦Z…\Yâðàß@�0Àfôͬ0ýäl^̬óšáãŒ/*D ƒ())îqL°¹‰(vÞ8Dí¬$€¬áÈô¨Ì‹’1¹Ìoþ…·l {°aÂÎ`MB?iåð™JÃç-¢(ʃ KЃüâ@²4õ ò"¸¯8P*çïØëÍ��m¥Î¥�¨á¼õE›,õ92P£/W0›ùŸÉ3f&"ø~â;êŸ úQrª~(RgIEYLTçPEQE9°0`޹~FoÆ Ñ!†%cÄFR{[�ÁÖë7=:ŒS…-™ ›²ˆë#QÍ»°Þ’±–½•:ä!K¸¤Öéÿì%£¸è.Ôûày Q”¿$Õ‚Ù€‡RÌpBCZàÞÙ”  (>Þ9ˆA*jõ´Ùí%µÌ3@ˆÓ¶£N¥VAiI¬Kó8>@’�àAN*qˆ$)þ¶ýjÍZ‚\9à�*ƒ {b¦ûÄÏHÄ”¹óµ{{Ì-ºËâ\œçUG¦,]î]»ë3—ÇH�É\YMYT"¶EVŽ�IÜ|�Oð‘ƒ�÷-ªÁBLD��¹36L ªÊÒ†ØA8#Øx)ÍÁž™$x)DWx ‰0lÁ6 ÿ ¾,Jò ²vdÊQ—orø ø,«VCœ:T‰­çŒç}|†9OL÷ßQ¬;#§†¢Â£¢,2ªs(Š¢(Š¢pD³˜>À`0yG †#©t ö†¨]Ï;½[çñÈÔkµ«yfLÄYÖëdI§‡¸QDÞư—!£y?“f(³ñ ϲñÔ—[†ìKj›Qü}óVíò ~r†!Ð|ïûAä˜JPx›Ø›v´;³É8`ОžšœÙ¶v,æÒÏÿøŒˆ8b€ÀL}M€‡!˜Aùt¦�a:~•¥Kˆ~ AçŒX:="ùSß/ýêÁC‚Èox”`Êœ S–‰‰âÔ›8©ÄÕ bÄÕÈä¥w ÇqdŒíy)«3Ÿã†�—X“�¯;‹ÚÑ×É åÊIës(K–lT(��óžˆ6†õ‹Óy`(o÷†j’«ü¨(‹�Ž@EQEQ”ŒÈk’n'¯VëÞ™$©dY×/Mî ƒÒ 0(, gîS»|ïÿ`àm”“[BšFÕ*DÆ8 ÿLÿÃÎô�Ï€õ‡žÅ1jö:Ý"w‘)à,Ïð,Ëʲ°mÛ6ív;üÉ{//Xì6. r:xP7·×ë=ÈŸ{ÿ6äy>==  Óéì=óؙØÁ9fö ʳÒPâÏLÆäe±P§Û톟™Ù9·Ø_×îyý3œÚÜÜ\x,ŠbøOSSS‹}f y‰Š¢�ûä0Ì\–%3Ë¥ ­,K¹ïàœ+ŠÂ9'oy€­¡�:G?˜ƒa¾—£[$°IT�³àˆâšƒe&òóý9¶­|¢LÆQ¡^áÛ�ž+:¦œåêqÇç¹/c .¹šó25r²nŽÏL…cG±eæ(²‘AÖkÅÆ[p ä½qÞúùWÙåûòÞ‡ï+|ÍfS~•~._ǃß�öNhR«ÕÚåO2½÷r3qÎåy.’‰[^°OêÀö~­ä« ×A.NQyžË{‡� v·cùBá_T8g¼'ï�/}œ{0Èë�u@ÉìxpYÑ3`¤Õ$N)/™ ç%�Ì2Û:Çì°o‡fffò……�-R8ªV«‘¥é™I"w½ü¬|�†ÀÜÜœ Ÿ°Ô£ivvV^¶dW/‡,Ï¡(Š¢(Šr€Q:x&"[æe™‘¥Š1•ˆ¨_Ñ€ñ–°3—”Ÿþq$‘©í¤ðÜ!‘¯Á\”%jiŰ5Æ“5ˆ-�c‚eˆ‰$W²õƒ¼É�næÉ“,WëŠÈX2ÈËÂÛ¦,Ë(ŠÒ4•_GGGÔëõn·[­Vcò<—ÌÎÎŽ��-v“+Œ1½^/Š"ï}’$yžW*•Åj 3÷z=cL’$Ë–-“æ9ç±I{oïýŸ*KDâ86Þ—Þ— òìMT6†è7>’a&o˜ˆ"6ä–fçf;½’©aÍ$<*�^6ÛœIÆ Ï÷ø#•C¼1%(7T‚ “)³ÒP ÀK”@Ü`Ù-”¿jµZͲ,Š"k-Ykt:�Z­¶Øßæ<¾ï½öO¹?dY&6ÄÑÑÑ¢(â8öÞW«UIö.· y~±Ïæ·"Ïó$IŒÙÙ%ʲìõz•J…ˆ¢¨op "¹á”™¹Ûícâ8–oßZ+?]dø°ó¥_¾ ’Gb5ˆÑhŒív‘³/ËVYæ‘AÄÑxE~¾ÖI"“æ¥%kÙÚ´f’‘*!mW£´‚²pŒ(ŠXŠ�/}eÏïÓ-Ëä–{`¸’á«ð‘�’4�¢¨(2‚70€c°{#²0û$vì©Ë9ç�†| sssãããÃ_ÇÒAÆ‘1FúÆÌÌÌøø¸œ3ÏÌÌÄq\¯×ÈDÖl6�†<#§DZsn žÚ‚ æyYœ8ç从¢(Ë2ká:8ç¼÷áÞ+ï vaý‘舜D ÁxPd+ÆÄ„ØûÒ•=.=Œƒ§$N©_Ôj^«Ö¢×BY&ˆ™³¢hyÏ•4®×`c¤1ÇÖ¦àÈRl‘ÃÙxPêf>Ç7ì#föe^”=kÉJâþ€cÚeæ7ªs4Xk;�Nš¦²ò�çyžç###eYʨ k~"�ª[Z¨Î¡(Š¢(Šr€Qz0!‰br.e®²¯’1Lysè;±†hcÁƒÉ¿á±Þku,e…A/¦FjP1q5ª'È禉MiPXŸ—ŽØG¥·Ž"c˜@l=LL§qìà™3 ‚%ç]æzì}r€ä/– ·ÛͲltt´R©lذáÈ#�#æöíÛW®\Ùét’$p ‹‚÷>˜9Ä()FÌýú¡Ã[Äð³X„åç^¯×ét&&&šÍæÈÈÈb_¤ùÂÌÙˆ™]QfƺJµâ™²néÉ€¥òÅoxd.½ÉAÞ¢´Ì„Œá™ã‚02Ú¨#Q´,˶êU¢Õzmt¼‘7Ë’ç{|PÉÈ@%L¦KÈ@ˆÀq’ŽXS)JÏÔ÷µ'DÉ‚åÓ4ít:ÖÚ4M�s­Vk Ž£}ퟳ³³µZ�ˆÒ4MÓ´Õj5 k­÷¾ÛíÖëõN§CDbÜ?ÐEI’”eY–¥XQEÛ‹¹8Ô…CN6ŽãN§ã½o4Ú–¯Ã¯¢õ ÏŸ¡`hÈòh¼3lcJ+®‚<±.A tš¾RÎ7v„‰"$®DËçdPw˜ö˜i¶š3³(E1Å`m%NSQÄ•¼ØWß,B6b{ç¹õÖE\Z²Y»SMbê×0ð€g�Þû¤;‘inn®^¯Çq,Ê�»§¦¦&&&D9�¯/˜ù–�NG:ÏÌÌŒô4ÓÓÓ¢8ö¯d–1sÇ###Y–¥iZEš¦ív»^¯—eypè÷D$ñU÷œ»Drcv’«Iô•µvÕG}Å@b| l [WX昑á™ÄPÅXÇpó­/E~¤6[A†Z…¸Ýdv†Rø ÷P s¾pÆÎÂeĆ)g3ßãÇIDì ¶’—=—»8¥86ŸB? �$éRˆ¨V«Ea­m·ÛI’ŒŒŒÈ¨‘iK¦{qwXXuPùíÑïCQEQå@‚OLÌqbRâJl�gè´0“'õ*ز3À ~žbÀ<¯Gw2vHŒaÓiarºµ–Lì%S8œä?fx@ªo0ÃËÐwrkµ`Þ±%X“»²Ùdt¼ÕÉ¥£ÕjÕëõjµ*Í�7ž~úé;vì�¿>þñ�¿ì²ËÄÈÒn·�sKдO0³ìß$�ų`É+ö½%âg @Œ§gœqÆ%—\²Tƒ9vOÞ—¥ËÊ2OR“Ʀٛ6�¦˜oròD%úõNQNsÅ5¹×u›)*ËÌùZâ{Åæ–»½Ò¨æ[‡œ $8(º„€A ®zgÒ(¥Ì—®Gç ¦…3äˆ û-oyË'?ùÉF£ÑjµjµÚW¿úÕ§>õ©‹ýÕýæ–壘TS–e·Û½æškžúÔ§:çÄôÉO~òW¿úÕ`™m·ÛÞûHºÛQCO–eD$6Ö]ʲó oH†cŒ¼ŒˆÄJ‹!—ób�îg¬ò^*G€éµ»S\«»:¦slu® k�ÃFL:O/9YÀ=n0» a[ ×Y¶jÍf”idáÌÔ#Š"8‹8²˜÷ñ3`à²v<‰3øNF+õ²9í‰$Nkè<HdÕÌÌÌÈȈµv||ÀÔÔÔ[ßúÖÏ}îsÎ9¹þ?úÑ�N?ýô4M+•ÊÒ¼åÊÚ¾}ûI'�$ù߬µ�~ô£¿ò•¯Ôëõ(ФƒIã×­[wòÉ'›��}ÚÓžvñÅþ×{:…™™™$Iä H¦\„�Ñ­‰xï³,³Ö]D²Z-”Ãpýbò–]Z‹Ó¢‹¢bÄ‘‰l‚"!6ƒ ‰ù=3@ލƒ5ö1³±…iOvÈÖ*”&´RFÖPÐS¼ÇZÛaT'Pµ çæÀˆŒ…¡×}ˆŸ>‚••y’ç¹Ä‡yïo¹å–G>ò‘Qåyn­=ùä“ò“Ÿ,AÏ ªs(Š¢(Š¢p�å¼ìVÈœû­›Z[¶fÓS®Û2Ìbûð$‘Æ0bË0 O¿ù±âŠesyœ›ÄÆsY¯øŸ{ºYÙ2lÇ�Âzã Jƒnì £R‚¥1 Xît5ܯfl­µI\x禚”àÑeã8þ¤JRÏ'f1¦H*Þ$I&&&Dä¨×ëívûî»ï¶ÖÊ_Å}{±ÛûÛrp‰Â!É=öw0Ç.Èe”j �FÃ{Ÿçy–eëׯµI4˜Å¾Tó<ð\ÞX'QæZwÜû³[7~ÇÅÛç™7ƒa=×ÁÖ¢°\Ø0W£ë··Ý�¶šYF§¸ç¦;¾òëõ—3·AÅ|órpÊn8‚É™A ru¸Ñ‡ŸpÖCÖœJ¶ÎÎ[›€áÙZ0#N§Ó©×ëâÂ/n’�Nçˆ#ŽXì¯m¯_é<úgQ®Q­V�;î¸`jÌó\‚ʲ”Œ:I’ñaHŠ�¼ÜCDÒ¸öÚk¿ÿýï_}õÕwÞyçôô´ÔEX»víÚµk÷¸Ç=õ©O=ýôÓCXŒ ×v8{Õ¾é ‘ ¼ªÌ„’ÈתÝ÷¶ùg›6Ü275•ÚnÔ¿ÃÏs~4Þ¦YDÆõl3B9êÒ–�®ÏÜævc#sÞÿºÓþò­¿®•9ØÆ––zeÏÏóøE&N‰’^vx½¾Ê˜£G§­YKQ-ö>B X±ÙÒu yCÂ5*•ÊØØ˜µVnõÌ\ÅÊ•+eî ø._ТSEEÓÓÓÖÚéééZ­Öétœs›6m¾{ˆZ6777::EQY–³³³qgY&£o±Ïc!ß/çÜ/ùËüà?þñ�×­[×l6¥\ÇÈÈÈCúÐÇ>ö±O~ò“O;í´åË—ËW\3ËMÉÏ;“Ûo$Ì7Äl†�u i{f¶anGI%¥�óÒµ½çoµRkáºíÿóëé»Öç““#ÖF\GÆ˰%ˆïãU·—ÇÜùjÖ‹ �Õ,Ï·ooí¹<�­É-yx‚7ð1<'G�ˆÂâùÛY§I·ÌK°©$Ý2/&&VY�øˆ¢r·””¬ßBN• |`È>{˜,Ó4•úR¢€$Ûy )ò÷… …5â//efåytÎ-ÕÍ$Ýÿ fö¾´Qlœ'�Û±cÛ 7ýôžÞ�]²qžÇe¤ìG2èYÎ-9TÙ‚ [õ…ëTR(ºÅƭו™£8Í»Ð.WÙ�3,Q��0ù¾aŠåy^ÖkcËêÇ&ŽO–™=¼¡…‰Æ’R7bû–*ÁÖÚ%X�{_û§tQqù›ñ˜–_÷Ùv¿´‘óít:yž‹�õÞ{ï½øâ‹ÿáþarrrff€¤Ê‘;êÌÌ̆ ®¾úê¿þë¿>餓ÞñŽwœwÞyÕjU÷|øšï[kÈKP#‘$¯&ï>‰|OyܰyÓÖÝòËöÌÔHÚI¬'ây['#¥YlŒïUÚÙX�˜ªÛ£*5”„Òmìô.»ãƒ<‡o²AG1Í?k?±)»E „™Ù#*ÕÕ¥û�Ã׬]¹f”£Ä°u2×Z,˜ahg®}C2Œ‰4%3Zp៚š’l-ƘPžjé }ibbBFSÈ'óÔ.V£ÑX¿~½Hq¢AJâ&ÉdµØ§²À„T“Ì|ùå—ÿÝßýÝå—_.¥€d ÍfsãÆ�?ùÉO>úÑ�ŽŽŽ¾ýío?÷ÜsO>ùä8ާ§§�sÕjuý6¨_1§´ì™{2.¶%ÖÝ45µ¹˜Ý^$>­Ä|æ\Û3’t9Xdþ��Þpi3ÀÔKc»Õˆ�%P�ö”›kåY\”Ö3Áxo½�\)‚â|Ž<8~YÆsé8��>q ;O‘3ðŒÒ[Sû©«¼¦®:8�¹¬Ýn×jµPïGêNõz=IZB3µùRciîEQEQ”=á‰Jç{q\�ËÑm7·l(·m©õºãIûÒ2ЯÒa<†ÅQt^ƒ½sì#.céaöYâºUŽª%SZXؤÄÛKˆä0Üßè5bkj{çÀ6â©^ÍI´fÀF©F±T£›dª‰¢HüµÅ˜"¶Ùüë¿þëÈÈH¥RÉó|llì¹Ï}îƒV�|Ø )vdñ2®T*ÖZ©ý¸Ø—gßψ¼± Ã…+Ès·×ܼí^Ø_çs8gÛ ’ÐvÔ7¿0gL–lÙ0ʰd;”x¦}_lºÞvA…!f3ÈÔcذéæÂý¾�Ž( ë\bmdÉxï0éœT¾•/:MÓP�z ²¯ý“™Ûí¶dÉ'¢<Ï£( 9ñƒ±Ûí.5ùvqjµš¤Ê¹øâ‹?ñ‰O|ó›ß{ÐðÕ“´H!0.MÓuëÖ½ìe/ûßÿûÿýßÿýÊ•+GGGåÖÒ‚=�þàû“РFM_òÏAc¦ÀúæÌ¯Û3÷ZnÕbGd¸ùùJ¥µ>©”–;U6s%—Ô11’:ÒÞUM%ÏZ¨Ô3kzlLš”í¶™·ZSZòËlGl¢£˜ž=<÷eD6JÊ'\’'øbCûV„ƒ@‡áœò’gLº¨ÈQrýEQXØ®òÛ#z!3ÏÎÎJ˜”d’Ëó¼(Šz½*Ø‹¤±zõêééi�F£R©XužæI¸Ayï_ùÊW^xá…r¾­VkfffÙ²esssÃî ¬399ùÖ·¾õë_ÿúßøÆóÎ;O œˆÊµ _}p p {o"gQ¢µ£psI­mDÕ2µ•&6yæ=ažñž¼‰€)P�¬é""‚)òÄF¬·Ž`½±ÞDÞZß/Š>ß㛨tùìö™æd>±:‰“¨[ BH¸úØav>*8’ØMÖöR¥OÒÁu:###R½C P šR–ªs(Š¢(Š¢`&ø4yùNwÔ»•µ² 0%YGFŠfxò ox~lɾmœ–YÞH’ù,1&N¼sLfá r„’ ™Ï‰á(4 ÖK…FxB·ÈÓ’ó¼—FqØėe¯í:m»¯.º‹D°?;½ŠûyµZuÎõz=q# Ÿh¦¦¦Þõ®wI*kíi§�öÜç>wó³cœsÝnƒË.–â¥gzÛ]Vn†1ð e᳌+5²iޏÅfŽ‘ƒSøœÒ΄û€aãi�…Ÿ<` ,È�¬á‚˜ÀsÕÀÂÂ’a_�óİYD\xß/Pë»Î-†D‚§kà-:­jRTS4ÆÐêŽä¨óÕP‰A>Ï�³ä£ÈÔ9bçÓ<÷Ôiµš)јsE§sYä¹K¢¤â}<ï,@¹Å,òx¤ÑI«MgÍî¤sÀ9xòLÀƒ˜ø�”Ë‘´„÷ E§¥Œ<±•J%MS±›Kg^€.²pˆô^–åªU«z½žˆˆRfÜ<¯C}—Ã?|ëÖ­jµZ«ÕʲlddäÖ}9xô£}Ï=÷0Æôz=Q5¦§§ƒÎ*·#zÞûjµzÅWÜu×]EQ¼ð…/dæ<ÏÊuch8’aS’7ä™@ŒrÎE½$B55p@¯èzi¹}ùZ¼�7ÞS²÷&ÎòNim¥^1y¯0Ìl`x2 ãdîbÓO85ð `™nAÎ0ˆ ql\ÄHGê+ón«è•ð‰1Ʋg¢þ xhŠ<³Ô–'ÊBÖüI’”e™$IµZíõz�NGæôf³¹bÅ ™Á8œCÕ9EQe?|eKyòÉ'¯[·N¶îà #±ìˆQ@\ £(zÔ£•$ɉ'žxÁ<îq�#"I4,îŸb"YìóS_–QRkš8ñåHcŒ¼§Äv³¶çdõªÚQ'Nf®(¸QK�w¬-]á÷Içp€eô¤Æ�É× †Á 7±S,1"6€/9ã È—…õÎúN‘­M«›n¾%êqÕ{r‘µûÙN½[éà¢({{cLÈn1œÂBX‹ ¶˜Ô½÷â÷*éËe“ÓívÅÀ{Ÿ¦©S)æWFb—4ô‚#³8ÕbîŸgC¬ï'ͽxb#, ÀþA>]{�sÁL  Ó釵ðóp“Ĉ9Ë‘÷^¬Ë‹Ã…nóðM2|eQíÝ8µÛkÞívÅ¢Ž,?,`�Õ`Ê‘z@¨̆ŒwðœDQÕS³ë·q²™âÉZ3[ò‡Ÿx¦q+ŠŽIbë]A$:GìaÀ6%Ø€cÀÊþq™<)!>œgçåã}Ð! <¡°·‹nÔÈÊhË/oûÅòqÙÎlì;�NQE-7”zoÀ 5|åú‹wdˆxÁ`�—šY†F¨#ãN:Fè�Ò¥«J: ¹uÔëuy3KîûÐ`"’v†Aˆá¼Â'†´Ì,í‘vÊE�|Yò–á¡*�œ™³,«T*á¹DÃãB^,ù†Ç‘sNnzrSÚÓE“ë¼~ýúW¾ò•’y,T9P«Õ¤ÀªU«6mÚ´nݺ+¯¼R ?È¥¨×ëÍfóì³ÏþÁ~p 'ý$IöÙM,ˆL N`Î-Â;�²Z‹J_t"ã*57ã�i¬:­n—eÝy€!6Îxg*€�#GÖ‘ëmì=�¤¢ô»º`ÙÏ?žÒP½röí×µ}k¼1²|Åt™-Æ{]ŽˆM錋 €‚AŒˆ�è8¤(¿†©m¸“ˆã8ôÉÆ4|¨p#•n3Üýv=5çB$€,ËŒ1räá?Ý^Ûù¸(Šæææ$¦Šˆ²,“a+FÎHŽÓl6å�roÙ% åýzÎ9™1EÚí�O”w…A$óŽGnD’â_beÂYËÅ�ºÛã3s¯× µ¤1rqd­"C/¬yžûÜç®[·NîµZmnnndd¤ÙlþÎïüÎñÇÄG$Irã�7^uÕUSSSòåÊbfÆ ögvøá‡ŸuÖYR�l¡¤`}D>.M×ÙÂ!«Ø4á8�êž0ÙlUÖø•'V³^alžzã÷eŠé¯<†ó˜a¸tÔJˆ­höÒ™°ž" G€'*˜JãÉ‚ª&20EÙëÆ”¬¨6~ù³¬QKóŽ«§ v"Û+Ù¦5 XÄ•}…ûîÃ##¨ÝnËý÷]YµÛm ”a¸§ bø¦í½—¾4üï½ø„‘~ájö`h™7üAeY2sØ{:犢ؓ+Lx£ü ]tï ã°úÅ`žË8 §¶÷ù¨ÿ%3KºÈ]&59‹áK!©ÌéyžKÞ6™¯Ã„+R½LërÛ n7󙡆oqr¨]¼vBö¹)»CuEQEYÄ DŒ‰bO”5�d¸nµZ¿øÅ/¬[·î?þã?ö°‡}âŸxüã?55511!‹QÕ9Mˆ¼±žâ’ �“eOðñØHí¸cñØß_Y…�sˆd÷ouDÉÂC¦ŸÖˆ¶DQ`¦9>Û6;¦J_äp]W$ûÙßM6üY–‰ù@FД֔ÝQØ}Iš‹‘‘‘°Á“çyþÀ¶»ˆY–9çöd÷[L؉ɓaÿ&›OIÐ!¶ò)£š¦iضµÛí8Ž“$ â�ì£Â¯²y#¢jµDZì«ÅÂ"g-Åz½^žç¶²lÙ2±’Ôëuk­œB»Ý¶ÖÊå•6È‘kµš\«ám›£å4ƒk­lC¥âáÜ)¿=Qõz=)™¦©|®´vØZÚívår-ȇŠYCB¨/< ‡h§žÚÞflÛí6ŒÅXíèG?ìiG�=6ÆxCp"~'@ DÈ Dûoüš�îÂòUÄB Ä™¬£(šg­¸v»-¹¤Â9FQ”e™Ü[Â-ëäN§#«\i€œ¸Äp/Hÿ—C…5†8 È$+“»,Ôå|åâ/Èçâ¨Î¡(Š¢(‹€8x;®Š5¶Óé0³XCêõz–eâyË-·œ}öÙïxÇ;þú¯ÿ𙧦¦V¯^½$ó·(ûFì�:8ãû»5G¦0fGÖ�S›Œ×�$ƒðùð\’Û�]…AžÉ3˜±“Šäð¦4‘AlÐ¥E'î¶"æèAÉÓ"û Ƀ�ÛcØH„È ±ˆ?uDz ì{ \Ù¢ôz½,ËÆÆÆ0psÞâÀvb²—m£^¯ûQµZ )³êõúð1˲ìv»!Õx85ÙGaàDj#èt:rIÅ.FcÌèèèè訸ôJ=Ò,ËD¶ Þ…aË-9»*•ŠYL¥òA"ÖÊóa£(ލÁØ*ï îü •ÚX6ÕÃÞ…áÞd�f×Wß=¾:’®¤¢‚üèFrJ‚“£€)97(‰Nyò ”ýpÀl"N`­A‘¢Ú¨ÜC~9È5j:ñÀÄIˆ�ő؃�TÜ<%ýŽ$—Óa¥R Æq1j,Jÿš››;æ˜c$ÙŪU«$¨"X4ÆÆÆ¤7Ê3EQ0³”ÿ¶Ñ``ý”þ,ƒ14^n;Rr ÝnU‘šÍ¦”T•?‰º9ìT.m›©HrcÄ<œëå5cccŸøÄ'nºé¦ðd«Õ:âˆ#>ùÉO>ýéO0==-©ÿåz–eùÆ7¾ñ9ÏyÎïüÎïÌÍÍ…J’Àê¼óÎ …£•hÈ’€IDATPÝ-»0¾_?c_È–ÕGØoã¬Ë¾ì«Õ†¸_W½×"lxôé~»|b%”2ÕjU|œ÷ÒU‚¥~—ã‘Cýð‰ u– Wk×®5Æìرc||õ)Ù>,[¶lzzzÅŠ_þò—Ï8ãŒpc”q�çùÔÔÔK_úÒ3Î8ã¯xÅÕW_Ýëõ¤ðÀW\qÍ5לp ˜¯r¨¿†'ÈÕz�3Ê _ØNI£ýY%"ÀîO�ƒ°sF%r "®ôÛIU� E7Ú1Óáñtt¿Ž0"êt:"KK"``0ItŽlúB¿îBa‘ÄȰ= ÁÍAannN%R„È Ì<œ9P–L¬µsss�FC¤÷0 îgð�‡>ô¡çŸþêÕ«±$ó&+ xŸ8”Þ›�ñ“ ¥1¨ÆE%1•Ö´ K\t«iФâ÷g<£ô`À‘lQÙÃ:äUCH«‘‰�GÄ0%ûNöBû÷‰�ñ_vhbÐÇ@_ö¶–vÙÒ‘Ø#d$>QŽL„�NG\áö´ŒãXv¤bÁ >_ÝoŒ¯4 Rf oídÇE‘£ ¿]œõÄ«}XÞ µ‚‡·Áb[™��Û¶m›X?ƒÁE^ ¾ç’'Gl”rkÂ`ÓĹªÃ¶* ÞFQ$Ÿ2ì,—k¡¾÷�å Ýn{ïÅ‹_Ìpò…ç:X<‘تä]ãÛ>k[ªŽz—zKq ŒA ˜ (U/É9ö‹o+EœÁ—(mŠ(ëµãvÓGU®Äá;ò d@~�ƒÄïßø°=^8ƒAH DOéN¡úEp‘–W>øýS ¾â;11b,0¶blqB>Wþ:üéeY�rØú)Hb™`Ž£Øèè¨]‰!U>ND333ãããb*µÖ¶Z­põBË1H±%„G{ñ«�ûÉ{Þ󞉉 ñ̰ÖNLLüüç??ì°Ãä:/[¶LNGÌ©r#zØÃvõÕWŸsÎ9[·n3Ö‡?üáóÎ;O.ÑÞó -–}ÙÏäóì- 37›wÚ¨Ô¬µ–³3`’,=Ô¯;Ò¯â³ÿ.0àï/8…Ž¢’cgO&È�´M~ûcš¦â⃡X�’µ Óp–eÊ 6Ç=½>Ø‚1˜Leú�Ó ñ”»Ü‚� ÌáùWÌÇeY†»P�EÔ yÃdÝ.µŒúp5DÌ©r$X$hW_}õ-·Ü"ol6›ÕjõŸøÄžðSSS�FCrÁÉ�—�yòÉ'ó›ß<ùä“wìØ!59Úíö¿üË¿\xá…{·_ï+ƒhˆ~vTHh ‘—\–¦ð¦Ÿö ˆ<“ÛãÌÃŒ51à� p òàÂÅl¨"[�5ˆ9JÍþs2Ôjµ�ÖI„¨`d—Aî±¢‚H¨ŸŒøÅ­GÌú¡ëZ­Vä†ãž//�a(ë%IÙ$½N:ž¤c ¯Çàž¿‹¸ 2Ý wxqÙÙÓГufÈÕn·e⹪¬µÁ§g/Ç‘?IZH©.Ï‹Óð”'§)7·ppàÕju_ýœöB¸HŒfµZ‘#Ä8mIæÜìZ‡,ªs(Š¢(Ê"`­}ÙË^öêW¿zttTö*ÙjÄwÛó±�}ì¯þê¯Úív³Ù\µjÕ¶mÛ.¸à‚?üÃ?\³fMpÆTE‘‡g)5ÃýŒüiZ56Œ[DéH?_ÀþlŽ–`ƃÉ2E( Î�r•¶â©ÌåfoC²&Y²á 1ÃÑýa'?;;+?Ù�ˆ9`_Má•J¥ÝnKFqa»¿ïê.„ÔÛ²·+áÄÄ„ØVdß%�_Áã[̦bþ�O ¹2ä˜Á"3ŒÈ²�” 9r•D®�]V­V‘-ôøøxžçÕNd,mn4r³ vX’|FR�‹ ò¡Þû±±±,Ë‚°$›ùÜÔ…4ñ’Ï:\�]е´Z-"ZÀ¼ûˆ+ý¬Œ]nãж6‰,ƒ%÷uÀÁ&ÛQȾ³?`��%x‚Clí@pyB”ƒ À %èZ´ B±ò ‹y2~§¦¦d°HJ(ñnI´üþâNäWi§Lô♲êË+CW öç\»Ý“Óp2:‰·HÓTzu¸Ãt:�ÙÙÙ5kÖHûw1†T$AtiµZ�%/èá!TÃa¡èþÄqüÿþßÿÛ¾}»­Ñh´Z­÷½ï}bÊi6›yž/_¾\Ԛй>§œrÊk^óš÷¾÷½³³³r»¾âŠ+n¾ùæã�?^NauÐÝbXæÇÒ0Ü$ŠE&Ó�¸Øú/†Kq�§ ÃYt¹#‰~)¢æ¦M›V¬X‘$‰”|Îã²Þ³uõ–+/‘r!ŠÈp|ª¼¬Óé|éK_ ©Y–=õ©O}îsŸÛl6“$™˜˜�W†«dŒ8ŽÏ?ÿüþç²^¯å+_¹ð *¯#vÓ7 ÀQ8o­‰*†*Ö$‘‘Reiœ1ûIKd‚7%`¬ƒaC–É8DÆÂ€ jFÒP°ÜHmŒAm¤ý„câÜùå‹‘>tÂJ¥2z8üÊá~+È+C|† ¿ÌkÒ!1ˆº$fffFGGC*H nÂÒCD*Â^Æ‘ˆeYJì‚ÌAÝnw/]KNYÂ. »äO"Ãì"ÏïB¨ytñÑ‘d�2¸Bù=Ñrœs³³³•J¥V«Éd½€ß¯ä “Æ„“’O^…†�MÕ9„ÅÖVEQ”Cž²,'&&dOü%eõ)¡Ä’`÷MozÓ/ù˽èE¶mÛ&‹¿ /¼°Ûí.NÆeÉ0ìhd–aY«—·:è�0€àc˜Øÿ*@¦“Â$0†ÈÙ^VÀ9ôòN§—e…/˘ -œ“àž�êâÒ%ÏT*90äÈïœËó<˜8GGGCHûð{÷‰`ÁL’D<ÂöRW9”ê•-€‰‰‰‰‰‰�O ÿý,b�‘Ôòþ–œÎÁ®ºËGH¬î·bcƒãÜܜ؅ÅhU«ÕšÍ¦d�ñ¿kµZívƒ¼ao&¦[‰J¯´z½ªG† (ªÒNqƒ•*b³–dý ‚X�‚mznnN²yfjjJD1v/Ôçî„2²Ýjµ¨Õ}çY¯7×év²¼ òbè!C…�'"‚ìþxàsôºèe(¢ØUk&IÙØ”� P EGÄávq¶0ÓO«Õš˜˜µ(ÂËŠ¢X¬þ)#QÌ%ÍfS¢.ä%½�´°Õj‰mt¸úz–eâ~+Ë1ëô{‘ØJÂÍ¡ÓéˆUTj�¬Y³÷ TjµZâ)/wŒáÛZ½^—á;vì�ø§^¯'.çív[ gbî©×ëÕjunnn/çûË_þRœ‘ÃÁ/¸àÉÃ922|W¥ŒÇ¶mÛ䬭µÓÓÓo|ãån)aßÿþ÷å[­Öþ^ꛈÙXDKá1ª@D`ËÞ³s®`òQ{ ñRñ˜ögB»û^%"™Ë‚¡S¾e\òõ…ñ¸§ƒÈx”wÉ„"OJ7sÎMOOw»]ÉØ6\}¡NaÙ²e2AH ©½¼²ÙlJˆCÈ9#‰ƒÂZ=”ö©×ëb½�e™¤�’zRö&¸1‰5yíÚµÒ·åh"`„Rê²¶�ÈEm4›(ÆY  ³›1æŠ+®•Éêõú³žõ¬^¯722’¦©ˆ &''¥å�NGFk£ÑxîsŸbJÚív–e›6mZøxÇ~¨¢ gã Î{&ÏŠnÑ,2ø¬‹²EH,’ýó[$%d‹Ø"²Qd“ØF© X ;à€ Üó>óÄû÷ ·ÈØqBîÛc!Ÿ$³_÷Éó\Æ‹ôgéĈ¢¨R©H<„SÞH###’Í�l||\:˜ÔÿpÎ%I"Á"H³C2´=ᜓw…MÂ:üþH µ$ªš™™‘ÛB–eòC�7$àx/ë79AEQÌÎΆZVâ$ € I‰‰ ú/lç¯V«»BGÒl6åWYoÈ7«þ‹ …Æs(Š¢(Ê" ‘æ²5 ɯåÉàã&þ2«W¯þà?ø½ï}/˲f³iŒùÌg>óÖ·¾U69û;uµ²D!8O;=å #r¨²i ›£Æ€2�¨D ,•ûƒ.`ÍN¿98“V�õŠ©”µÊ\Þu\Œø2ÝÏáÁ*ä.ŠbffæsŸûÜ­·ÞzÝu×­_¿¾Û펎ŽwÜqÇsÌýÑ=üáÈC"n_xXIþb333’Axûöí«V­ú�ísÞÈȈìZÅĹqãÆÃ?¼Ûí†,X¡œ²˜Mƒ·õW\qýõ׋ôÖ­[˲\¶lÙŠ+N:é¤G?úÑO~ò“O;í4Ù>‰uCj-†ÄòAõz]²ÇÌÍÍyïåú`�6¡ÙlŠ×ápºù¡Ûí–e)V˜›o¾ùꫯþÊW¾2==½yóæ©©)f?ì°ÃÆÇÇO;í´³Ï>ûñ�üð^w·”!%ÑöíÛ¯¸âŠï}ï{×^{í–-[¦¦¦–-[6::ºråÊ3Î8ãÜsÏ=õÔSCåÉ*K_D¶ “ƒr ¨U"ƒ„`Ø—€G€xž–09rÕßò3÷Ž©¢b|Œ^�Šf)j’m–9Ef¨XR-8Òýí<¾wB�Ö©©©åË—‡8ƒÍ›7uÔQeYÎÍ͉U%x¼>øý3Ü@Ä.#*B0*¿o¹WHÒª�š<<ßétn»í¶ÿøÇßøÆ7~þóŸ‹Kì©§žzÒI'½éMoZ»vm½^¯T*rزe‹$¢¹÷Þ{�8âˆ�5K%žàÛ¶m[µjU’$bñ” ™ÆÉäsç�w~å+_ùÁ~°iÓ¦{î¹GB»Ž=öØ?üÃ?<ï¼óŽ:꨽¸ê·Ûí 6È�J ˜?ó™ÏŒãX.£4Æ#æ¼¢(V­Z%Pz½žíøÃ?üÃo|ã¤îõ×_’æíïERλÿñÅ´1 �‹¼È2Ÿ¦0 "2Æ0±ÆÃXø¾ÎÁû=žc8ÙT¸gŠû³¤¿ˬäkÚÓq’$™››ûÕ¯~õ³Ÿýìšk®¹õÖ[7oÞÜn·%£ÎøøøqÇ÷»¿û»gžyæ©§ž*ÙYй¹9q·…½Ä'W÷;ï¼ó /üö·¿}Ï=÷LMM�ŽŽsÌ1ððìg?ûŒ3ÎÀ N²$‹“’`2SÇEu»]Qƒî¸ãŽc�=6DkIm0±�¶ÛíÛn»íšk®¹ä’K~ñ‹_lÙ²¥R©<ô¡=ú裟ñŒg<ö±�=å”S†K …ìš2º™Y*ŠË_˲ü_ÿë¥i*·¹çLMMÉ`o·Û2îÄÅþ„Nb0€Z­¶~ýú5kÖ,ÜÔdrI£Z–%…·Þ“O*Q\Lä\tû“à~€È3yÀÀ%`€z X I`ûÕ;|¿¬øˆ%cÁ¼oCâk’¦©¬¾$Ã17[·n]½zuE6l¸á†¾øÅ/þêW¿…cùòå§�vÚ“Ÿüä§<å)ÇsL¸Ó†¬hwß}÷¦M›þùŸÿùž{î¹ë®»fgg«Õê1Çó˜Ç<æ”SN9ÿüóGFFB-+©!í!¢v»-Û·o_¹r¥$Ou\TÑáö’ÏPâ)åçM›6­]»¶ÛíE±§©$Žã;vÜtÓMW^yåÕW_}Ûm·MMMI®Ôz½~Ì1ÇœuÖYçœsÎi§�öƒü‚€ä‡Ðívׯ_ÿóŸÿü?øÁµ×^»qãFïýòåËW¯^}üñÇ?ïyÏ;묳ä|³,“ˆç…ú~eå à–[n¹ä’K.½ôÒuëÖ5›MI.wøá‡ÿîïþô¤Ç>ö±GyäÆQâ¨qDQEQq Å?ÅQN¼GÃÒ0XCÖ¬Y#qå’$Y·n�,|û$”E‚Bià$;÷`óH ËÞJ­RÈÞ Æ€ý~Ô9ØïŒ.á�ÿ/�Îø")zElâz•­/çc»¿í¤¡è´ìî¼óÎøÃÿøÇEðÀÀ»yûöíÛ·o¿öÚk/¼ð±±±?ú£?zç;ßyÔQG‰[åøøø¾æç•ýÛ¥—^ú¾pÇŽ’>â¯xÅg>ó™Ý_9f±wÈNlÛ¶mögvá…#àúõë�>úhâå*‘øR½\,#ÿþïÿþñ�|ýúõÁ…\r\LMMMMM­_¿þßøÆ{Þóž§<å)¯yÍkžùÌggº—�ÜUW]õ„'‡))® ŸªqásW#Q–À�ºS†˜úrŒ+áJp\™•…³Ñþ5=‹2!e!Ž;î8 ´ðþÏÿyÛÛÞ¶zõjïý?þã?þÕ_ý•ÈI’ȼà½ÿò—¿üå/ùÔSO}ñ‹_ü–·¼%Üö§§§¿õ­o}⟸ꪫdý&ýjvvöú믿þúë«ÕêG?úÑw¿ûÝ/|á e %²eÙ,Fÿþð‡gŸ}vÈ–ö–·¼Eš„A楽èçž{î÷¿ÿý°4½çž{FFFörKÿЇ>ô¥/}éç?ÿ9†îæR©T6oÞ|饗¾÷½ï=óÌ3_ÿú׿à/Øû%•ë#¹æî¸ãŽ¿þ뿾袋šÍ¦ÌËÖÚ²,[­ÖÝwßýóŸÿü /¬Õj/|á ßûÞ÷yä‘$É\�ï·^¯_rÉ%ùÈGdBÛ“8Že¡~Ûm·ýßÿûkµÚ\𖷼娣ŽÚ¯ýíAS^(Š¢(Ê"0œGµ×ëíRQ"j1È@Ç¢(jµZÕjuóæÍ!Í…¼@6ŠòŒlWÚíö 7ÜðÊW¾ríÚµ«V­z÷»ß-$ëã³ßëõ¾öµ¯½êU¯ú½ßû=Éþ±|ùòÓO?ý�o|ã—¾ô¥ééiy™” Øm¤°Ø/LNNþã?þã3žñŒ£�>ºZ­®^½ú9ÏyŽmƒ½X²è`(ð_¬3Òà]2üÌÎÎ^{íµ/~ñ‹W¯^]¯×ßÿþ÷Ëósss!?Æôôô½÷ÞûÉO~ò�ÿø�O<ñÄ5kÖ¬\¹Rü^_øÂ¾ímo»üòˇ›>nË–-{úvŠ¢èv»ýèGŸõ¬guÔQcccÇwܳŸýìË.»LÏÌrœÙÙÙ /¼ðÜsÏ=þøãGFFÆÆÆžüä'¿ò•¯¼üòËwìØ1|ÅŠ¢ØmZ¡Ô{K¥¥ÒÂ.‰Ø�³¢€!Hö›¾�§‡s`0›ýô¾/u0ɽ–Qž�ØÄH“Ò»fÖíºÂGâs¢ß“6H>ùÉOžqÆÿöoÿ&™²%:ALœâm-ßi§ÓùÌg>óèG?ú _ø€ñññ�D%|–|ƒ{ßÿ‹{øŽ;Œ1¡·ìñ›˜!¤Ÿ¬X±"ø$áR(¼!)°Ä<*q÷ëׯ?çœsÞô¦7Ýyç�’xJª8†œ3ÃMýþ÷¿ÿ¢½èÕ¯~u°íÊf/ÏóF£Q…ìi‰(Xu%ù²ü,'.΀rpIÅ#ÙrÖ¯_ÿä'?ùÙÏ~ö5×\#Ÿ˜ç¹Øyw)ž,|ëÖ­o~ó›õ¨GÝu×]I’„!9Bödyo8Âw¾ó�“N:écû˜$èv»bú‘ô#qÏÍ͉ïðºuëÞóž÷uÔQ7Þxãðw·—¤+¢ð-„º�ÌìJ”Ø“5 aP÷»»†ì4`@RHí·ð}Œ¡(Š’¬Çì 8[pŽÿþãûQ/ÂÒiåÛ¼øâ‹_÷º×mܸ1\Õ“O>ù«_ýêQG%™ýó<ëábõO¹·H—“ùQòÒ„T$"rH! * I¢ÿZ­ö™Ï|æQ�zÔå—_.y~D¹”¢Íò^_üâÏ<óÌ›o¾9¤¾‘êbÌ ÍÀ ¸D^nSSSišEñ�ï|ç÷ÿ÷¿ñ�oHZ�n·Ûh4ÄÁ<Žcqgæþç~üã¿qãFé¥aýæñ 6` ’§u ¥ �¤’Šxéh·ÛÕjU¾¯$IäÈrÑK·€!}« ×Jú€Mãàˆ—ÄcäYK‘íözòÍV�žwvvÙµEˈØ%ÅJ¨@.™d<^uÕUgŸ}vžç�NG ‘�}ìc¿õ­o=ä! ï ¦…t˜Ç<æ1/zÑ‹Dhî!Íwò‰‰‰_ýêWû·{ÔQGÝ{ï½ò';!ÛÕ>!ùÙ0”P.üIšVžò2"ú¾ð¤'=é»ßý®ôL}òzimš¦^xáóž÷¼;î¸C71È)4\÷+ÔÃíDüÙeiÑl6eöÿæ7¿yî¹ç~ùË_–Ê%òâ�–J>nrròŸøÄÙgŸ½iÓ&ñ»—2Ô"«8çÖ¯_ IYj}ôÑá\ä’b¨ ˆõ©°S–¯f±’¬Ð,¾WŽ¢(Š¢‚ˆAMÞeå'K™f³911Á̳³³ãããâù8::ºlÙ2I¿#Y†sy§iê½?묳®»î:kíYg�õ£ýhÛ¶mßùÎw^þò—‡%Úí·ß.)�e#T­V'''o½õÖç<ç9333ÁÉ]rs‹¿Ï§?ýéãŽ;îÍo~ó‹^ô¢‰‰ ß™™“(û²æþà?ø™Ï|æž{î‘âŠišNOO_tÑE_ûÚ×>ô¡}ç;ßY¾|ù_üÅ_üË¿ü‹ì“Cúo±«NNN>ûÙϾâŠ+â8~Ò“žôÍo~3Žã¯}ík/ùË峌1W]u•dÞ¨×ëÁ÷oþæo¾üå/oÛ¶-,úDQôë_ÿúæ›o6Æ|üã?ãŒ3þáþáä“O•Ô®D$Y>&''ŸóœçüøÇ?ð„'<á[ßúV£Ñ¸è¢‹^ò’—”eY¯×ee<77wÏ=÷\tÑEOúÓ/ºè"Y•þô§?ýÿþ¿ÿoݺuò¡b�ºôÒKüû¿ÿûóž÷¼÷¿ÿýÇw€ééiÙ-/Xÿ‘<Ý”m4pX˜ZìSc¬‡9ˆ,ˆab"6 ¿ð�¦bâ |,÷‹Ÿ‚³q•(v W” åj³ËÆ#ìF˜úÀ>ð±�}lrrRrÇ˾E¾¬PŠC,‰RߢÛí¾ô¥/•œá+“�\È/·ˆ[Žn·+fún¸áùÏþí·ßŽ!;Qh˜D†ÉNÉZ»bÅŠ­[·öz½Ï|æ3Ìü™Ï|Æ9òõ‹;ž™"àI(ɰÍ4MSñòcEtpÝu×½á o¸òÊ+ÈR^)ýa¥ì-×®]»iÓ&6lxþóŸÿíoû„¦‰åWR9;ò§>õ©×¾öµ�F#�jí­VKœÇ1ä$¸|ùòÉÉÉ 6œuÖY_üâŸüä'˶¶Ñh„P•ýÃØ¸Šªd[úÒ:³1y/¹¯€0Áƒ÷�w«|Œ£^á£ZÌH Õ-5"S�£:û 8Ç€ˆ.2ׄì.¿(!VŸøÄ'^ÿú×KW¯×ëÝn÷ÄOüú׿.nÎrCçÓ<ÏÓ4]”þ¹¯ˆV¦Âù—yßûÞ7:::;;¢UDuë'€F£Ñét6oÞ|î¹ç^vÙe³³³2�÷Øå˜CT9e±{~þóŸ¿à‚ $XDÆÅøø¸ˆIR7~øá×_ýóŸÿü‹.ºhåÊ•²€ ùU¤ä jišuÔQ{‰ƒ‘u‹Ürå^-æ­<ÏÇÆÆ‚¸²à™Êû_:÷<éJ ÄBžým(�”@iám%)QVúÒ‰#:à÷™ô†A~kÄö�e™TŒ�ï4Ìz¡.ñ·¾õ­—¿üå2¤iÚn·O9å”ýèG­V+øwËë¥{lܸñ‰O|âÆ�C‰cI#Y«Õäî-1F�FcffÆ{?55%á¶mÛžò”§\~ùå###2ïÈ"v¡J¶„>¼àåÆò•¯|å¥/}©|Ðôôt¥R‘¤²2?JÄÃôô4MNN>êQ�ºòÊ+ÇÆÆB•�f³¹÷®+�|ÕªUÖÚ�}ìco~ó›Cº!ïredÉÑívE’ÌóüöÛoúÓŸþ£ýHˆ4IÚÒI'ýÅ_üÅa‡&"îòåËCÂL¹1v»Ýz½.ƒ®R©È·#_Ð5×\#Á þ¤“NZ˜.Õg(N‘<`Ol»ÝnR¤ f&—�s��€qÄÃo\ÐGbXDÖ’hü†É€à#ãá=À°”[À’yPJàÜŸ$IfffÎ;ï¼›nº©V«É„(IÒ¤“H…§N§Óét�Æ?øÁ“O>ù¯xųžõ¬+®¸"Èê"0­Nj½È’¯Z­þŸÿóÎ:묵k×b(Nw¿"iQCU’Ûo¿ý Ox‚L@¢ªJ•ý¯„v:Qý—/_¾eË–±±±�üãÖÚøÃr‘�­¸1É§È úЇ>ôÎw¾ÓZ+o•êd>• 2;;;::*ëÆn·ûÌg>ó _øÂsžóÙÈëå†6Ô»¥Óé,_¾¼Ùl&IR©TDhyúÓŸ.Ë�•+Wnß¾ýðÃß¾}»,N¤ì¼sNvÍè¸ozÓ›î¾ûî¿ú«¿Â LTyÍS½OèÅREQ”E@’ÿŠÏ—„ÃK™‰‰ YhŽ��OOO'IÞe÷8¼JÎÿ»eË–z½>66&^0ÿýßÿýú׿^¶.bPèt:ÃÙ®ò<ÿÏÿüÏ·¼å-dÛ)˾aw¹n·{óÍ7¿õ­oýõ¯ý®w½K>k||Ü9'©0*•ŠDÐøÃþÀ> –DÙ•e)V’z½~ã�7ž~úé×_ý²e˲,“,ÉÓÓÓccc²­’Ÿ¥`�sNL0ó7ó—ù—–-[Ön·ó<÷Þ¯ZµjnnnttÔZ{ã�7¾ò•¯”gRïT–ŒáÓe=}à 7<ëYϺ袋Ž=öØU«VI€v¯×«V«rÁÅM^êI¾á oøèG?*Çû‘”`•Kô£ýèœsÎùêW¿z饗¾ô¥/•MéòåËE+’5±˜‰¿ùÍoæy~ÑEÉ)xïÛí¶¤éX(˜ÀD!�¼!ßµ®…|ÔyTtKªD£ÁÂY0ƒÉ,ü£¨p䈀ÄÃz�ሼ%ÇÈ|Ò-ÓÌ7"ÊJP¯Xpð]/ÄYòóŸÿü?üÃ?ÌÌÌH®ùSš¦'Ÿ|òYg�µbÅŠÛn»íç?ÿù½÷Þ+©0Øf¼üå/¿øâ‹Ÿö´§‰¥#æ/N9‡!d 6›Í÷¼ç="rÈîN2Q¬\¹òØc�=ñÄëõúwÜqã�7nÛ¶mvvvëÖ­?üð�7~ö³Ÿ}ñ‹_üÄ'>QT¹-yä‘[·n5ƈMYÆŽìÓÄ×Ln5«W¯ž��ùGŠ^Zk/¸à‚믿^¶�FC¬¢’iýa{˜¸þmܸñ—¿üåí·ßÞívň,åͯ½öÚ÷¿ÿýüà€A3”Q‘j“Ÿýìgßýîw‡ô ι+VìØ±£V«½â¯�˜•­[·^vÙebV›œœm·ÛÍfó�ÿø�/½ôÒ#Ž8bõêÕ½^oÿïó£vÛcã2±QˆS!c 8€Èö­x 3ð,µ ³¿2å�£š& ä–——Y£“E¥µ5_‡¯ƒSp4Èï1È`¾?ãi½^•Ê’~ê?ÿó?ßóž÷È÷KDµZ-ŽãŸþô§’S[Œ¡2NÓ4-Ër±úç¾"ÅW/¹ä’w¿ûÝbpñÀa‡öèG?ú‘�|$€n¸áú믗 `nnîÏxÆë_ÿz¹¿íÉþ+ñ"Ãñ�Nç?øÁ›Þô&9Ùf³ùˆG<âÍo~³µvùòåwß}÷/~ñ‹¯~õ«!ðEŒb?ýéO?ÿùÏ¿á obgˆ�yÙË^&õ¥;�N’$Ë–-®8rÿïWnÅ"¸ÎÎÎÞqÇò§ÙÙY){.G5e¡.²÷ž©oÉOd&b¸ˆ±Tf#”%¢Pœµ`r¥ó@L†=ˆ`àIŒ³Ä »€âcèrÃu ™eʲüáøÌg>Sž”…ÖñÇÿ³Ÿý¬( ©ý077—¦i¥R‘UkE¯ýëÿçþGŽEÑÜÜܲe˪ÕêÚµkO?ýôZ­V«Õn¼ñÆ­[·fY&†øÑÑÑÉÉÉ,ËÖ­[÷—ù—ÿöoÿ†A8‚H r¾Á]åæÿÍo~ó/xÁÈȈ„TŠ»@¯×;÷Üs�<òÈJ¥²~ýú«®ºj8¾ä/ÿò/úÐ‡Š‚(¶Ô½/$2rË–-?ýéOßóž÷H)�,ËñˆG<ÿùÏ?ñÄ·oß¾eË–n¸á²Ë.“ÚÞ{1ÅÞpà _øÂ^÷º×Éj9è‹ãããoxÃV¬X1\»KCÑø¢(¤‚†FV³Ù”¤sòš,Ëö°‡IŒÎ½ûâ <I¥>Š(¢t¬šÖˆ&Øj ,Pìóî¾ô¡j!0ˆãaX¦¶Ôd0Qd¬!0P«Ã¥Þ‹’§Ùl>ýéO¿óÎ;e©vì±Ç¾êU¯:þøã‹¢¸õÖ[¯¹æšoûÛEQLLL4›Mù¾Þô¦7]tÑE—_~y¨–tæ™g¾à/8òÈ#ï¹çžÛo¿ý»ßýî-·Ü255uÄGÜ{ï½Ì¼mÛ¶üÇüô§?í½pŠ`‹3‹ÏÁ_üÅ_lÞ¼@¥R‘¥fY–'œp‚ø´=ò‘�üÅ/~‘$É7¾ñ�¢(¶lÙ"ÊGÇùÈGž÷¼ç=þñ�—ÃÊ,Š¢×ëI¢¹Ï}îsû·+TË—/—‰uddäáø©§ž*±ž·ÝvÛöíÛ%þ^Ô 8ŽÏ?ÿü¯ýëçž{nhó|œœjµÚääd(ºEѹçž+^tõz}ûöíµZmãÆ�ÖÚ¾ð…�F£Ñhlß¾ýú믿å–[˜Y„‘$?þñ�GQô¾÷½OöÚ{™L•=¡:‡¢(Š¢,ÍfS6Q–^ž—­…˜ÝƒgŠd4‘#MSqÔ‡kI2°|ùòM›6µÛí'=éIW^yå[ßúVAäDZØtÄkìýï¿HÝnW+W®|ÌcsÒI'mÚ´é²Ë.»çž{ÄÓdjjêïÿþïã8ï %�/Ñú§ABr4çyþä'?ù¸ãŽóÞßvÛmW]u•÷~óæÍ矾øˆ¥i*²AØŒIi;Ñ't:�n¸áïþîïd_rgÉöL¬�­Vë/xÁm·Ý&ÏH9Ó£�>ú¸ãŽ£Ø-·Ürë­·NNNŠy7ŽãW½êU7Ýt“\CñCÄÀOçÿgï»ã¤ªÎ÷Ÿsî½Óg;]@,,XbÁccï±`Å.v�ņQc5– ö‚DE 4h@Å "m�e—­ÓçÞ{Îï�gç8"¬€»â÷ç¾ÙÏdfïÜrÊ[ž÷yx-555×_ýÝwßM±ÖSN9¥G�sçÎ�={ö»ï¾  %‰éÓ§ÿãÿ¸þúëyù}úôÙo¿ý¸|ùòéÓ§ÿïÿc´œJ¥&NœøñÇo²É&¬¦´[‘CËÖ@ü ` „%lp ŽEú(!-Ñ�ò’)"_BJÀ’³0ZƒîÊ×¾ë Kk @ûòü¸©\QSSsþùç+¥***˜¤«¬¬<óÌ3GŒAqÌ<Ï›5kÖØ±c'Mš [·nì :çœs¾þúk&ò˜8 ˜«£nâZ›ëº¯¼òÊ+¯¼Âu¶Ûn»“O>ùÄOŒD"Lʰ>úÍ7ߌ;ö‘GéÖ­y~***Î9çœO>ù„E‚x<¾ï¾ûΙ3SKUUU¾ïóà»ì² ‘h4â¬Q`ü0yòäÏ>ûÌ äš››ûôésÞyç�zê©%%%Ä qšär¹æææxàÑG]¼x1;0¤”?üð�7Þ¸®!œ!@ ~áÂ…W_}5#UòrtëÖ- ~öÙgÌ�“ñãÇ�5ª¶¶–˜ežöi§�6kÖ,#æÜ±¦¥ãÄ}m+p=©!SnÆ‚eI, @  ý ÔÆàûíÿ*4´‡d&gG-í(ÏSÊAÇŽÀu ­V ²á ç ­2Ì�(°„G"‘§žzê‚ .`·A(¢ ù×_]QQÁÒ»‘ïf?S.—{÷Ýw7Èø\Wã¾ÜÐÐpÌ1ÇðTÃáp.—cÞjäȑݻwç>Î Á“O>9räÈT*•J¥ª««ÇŒÃ2ÆšŽÏóg€çyŸ~úéìÙ³ÉÒfYÖ‡~¸ãŽ;’BФ[---]tÑ\ðᇾþòòò±cÇŽ1‚Ë‹i#‹F£T?â‚™ÍfÉ­·Æ µbùòå=zôÐZ/^¼øƒ>0ÊdétzŸ}öágÚÁZ¬0Á2­’² |ókaóV°5�•"­•ÖÚÕZ) [ZžÖl—lJBKˆö«;š,½#v B_ôµ×^;öØcùN«~ýú}ñÅlDÀ4Ñ6l�š:uêK/½Ô³gÏ+Väóù|>_VV6jÔ¨³Ï>»´´Ôl©LäÍ�;w„ ÷Ýw_]]i+**Æ�w÷ÝwS¤¬¬¬‡;¹ðòYíK¥RL›VVVŽ5jÔ¨Ql×àTJ&“<ðÀèÑ£éN¿òÊ+ôxÙIFÏÖè¬ö{3™Lssó¡‡Êæ•>}ú<ôÐC»ï¾»�ËÐ>þøã›nºéÅ_4ïôìÙó–[n9î¸ãÊËËÍ`æc"Ù”™†žçñP¹\Ž`öP(T__ÏÖ¢ ˆ“7n?@Ö� /¼?¥ÓþóLZjø®—Ϻž–®ïy‰\knRŠéÑ¿¨‹jü°HØÀÓp–¯|/Œ 4ò^.—TqÙnbëdÿú׿(Ó`üøñÇw\*•â¼8âˆ#<óÌ3—^zéâÅ‹9“Édyyù¤I“øìÇyíµ×†Ê ‘Í|W\qÅ£�>z饗VWWs­.))yøá‡ï¹çÖ~�ëâ°lnnŽÅb�=öسÏ>Û½{÷ššnaýúõ=zôA”ËåJKKM‹É¼yóþú׿¾ûî»555†ÖrÔ¨Qï¿ÿ>×N"Þøù‘#Gš2cû’K.éÑ£ Õî\.7wîÜk®¹æÃ?¤I@ÀE]´çž{Æãñâv|VÛ¨v˜O*¥nºé¦©S§Ò—N¥R•••ŽãÜsÏ=GqD,cÕ–Nõ¼yóÎ?ÿ|JqŸmhhøÛßþ¶ÓN;pÀtEÚÐAé´ÕZg�£Ó:­Ó:­Ó:m˜eY3 ˜ €‘åäûô}߯««{öÙg™:w§¢¢¢gÏžd~àщ1qétºººú¸ãŽ#ÚÚ¶í½÷Þ{�=öèÞ½{ii)y{Ãáð”)S®ºê*^¤”=zô˜0aÂ.»ìbÛ¶9ìøñ㯺êªÅ‹———766Þ~ûí;î¸ã�È6téz ?Ì‘GIWžX&“ùòË/GŒñÉ'Ÿ¼õÖ[_|ñE4¥¯FèŸáG!O ‰ÄQGE¸\8þÓŸþ´Ùf›m³Í6UUUŒ33™Ì³Ï>ûÍ7ß”••1×söÙg{챿ÿýïd³Y6)×ÕÕ]wÝu�=öýûÏ?ÿ|âĉÇ7… ãÓ³KzÅŠ×^{m Øc�=Æ�gè¹Lž<ù€H¥R¬åŒ=šï_tÑE]t�fÚĉ9ä¢ülÛ~ì±Çîºë.‹Ú} © KÃVÊö•ŸHêD¹¼Z¾'¤Òù”…á瀎JÕiíi‘Õð4¤@+Vé³|ØB†/`¥„çÚˆEœvǃÿ8¸à‚ øÜ-Ë’R>òÈ#ÇO§ÓìR/))av`èС&L8å”SÆ�O�Ð@ 0þü§žzê¸ãŽc:Œøq£»ØAwrm,™L>øàƒ„`p]wÛm·%/?`:÷}ßß|óÍ|ðÁL&3aÂÑhtåÊ•d¼éÝ»7iý�J*€ÊÊJ^,é’É$‰HÖÁ" ×t:ýè£�R9™H´Þ½{Oœ8‘¥ÃͼO8¶m{ôèу :ꨣL‚&�NOŸ>ýøÃ:Ý“Áñ}?“É\wÝuK—.e'ׇ=÷Üó¡‡2ßâyW¶l6{ 'üùÏ>î¸ã^yå湂ÁàìÙ³/½ôÒ[o½•Õ¯~†–íÄ-¡¢Ò j 䔄ï#@µ ÜX h­!Â�†ÒТý_¥PVÐ�²Zh-–“„”ò´cKd5 !àð¯ B·æZ;ÒˆO§Ól7œ8qâÙgŸm6…L&Ó³gÏ™3gšH9(*ÃÔF0ÜPãs]�$l>ãöJ µ÷Þ{oË-·äŽlô-‰Aǯ­­Íd2dü`þ«�o1<]J©/¿ü’M!ûî»ï¿ÿýo–é$’h•””l½õÖS§N0`@uu5} C+DV±@ @òw#öNޏP(Ô6U#œ�¡Pè±Ç3xf…N8á^ ‡A{¥¶Y碵B#¥„”Z puðg¾},/�ü`зm´V!5¤Ò–€ª@££”Z@ÊvÛNM©ŒM<¦ˆOyÒ¤I'œp§ÙS‡úÊ+¯xžGgI)E?‡¸lÊHÜ~ûíZZZø@ûöíûæ›oöïßݦbí8NÿþýG�½ë®»qĬh2ó8eÊ”<�ýʫȇüL#U×u£Ñèm·Ý6þ|z¤ˆ|ê©§vß}wNÇq–,YB™âQ£F}ôуfþôÛo¿åbBâÍ×ô¥ä§zæ™g¨UÞ»wï÷ß¿k×®ô=X bâf›mö / 6ìã�?& iÅŠ¾ïWWW³RK†»6뵆ãŽçLJ²T‘Ï @ccc$ ƒŸ~úéˆ#–,Ybë¢Ñè©§žZÌOûóM£XÒIC@Àp,h  8ˆ}€;Ÿ ¡¡E‡¼j@h²C áûÂ×pl‰  ZX>  Ú®öÅòøÒé´Ö: ½òÊ+ûî»/ç£Ñl“Rr«:öØcYéÀ¢H&“ÙrË-?ùäŽj¨ S©TUUÕ%—\²lÙ²;ï¼Ó(Íx÷Ýw÷ßÿD"юϽ ËçóÀ7ÝtS  7ëyÞ�!CÈS€AY·nݨg³ùæ›ß{ï½gŸ}öo¼ÑÔÔT^^ …þûßÿVWWo¼ñÆ,Ï£8çr¹‹.º(�NªP(4cÆŒ-¶Ø‚` Ïó¸g�ÁƒOš4éÏþóË/¿,„ˆF£Éd²ººúõ×_?òÈ#‹ëŽ�@ �MÖħJ©¯¾úê¶Ûn#6Žl¨“'OÞd“M$ B JKK3™ÌÆoüÚk¯ÝsÏ= [ uä•W^¹ÿþû§Ói¶—µAÙi?¶_ r¡Ó:­Ó:­Ó:í7ehX–eø²9€ü6lll¼òÊ+ …àºîI'�D ¥™IƒÁ`uu5s@}ôÑ¢E‹ì»ï¾Ë—/þùç/½ôÒOúè]wÝ•b­Á`ð_ÿúW÷îÝÉuôÑGßqÇ,r˜0/�n¼ñÆ�>ú(/œDÆ}ô‘ ÿx½$­�Íf—.]ªµ>óÌ3Ÿ}öY™”tÎd2ûì³ÏE]DÀÆ’’’믿þÆoìÑ£GCCáEù|~ðàÁgžyf(¢P35B˜¬1*‚ídRjÖàø:è눧{ÇË¢ÒFN!㋬BV‹<�É!—A>ÝA?2Ÿv<7¤ü°ï;ž�¬BN!¯�hlASKP‰H0` ©D»BÆŠ™ÖÍ;Ï>ûì›o¾Iˆ7SãÇ�g‘ƒùzÙÌdtçñÇ4hçÚ¸qã˜å!w“.X»>Äu¶H$BžX(ºõÖ[™¼Èd2+W®4ê$·,ëþûïgÜÈ4J:�þßÿþ‡M3¯‘ÙR® &Pt'‹1QÂå…Ç)--}öÙg744X–uóÍ7o¾ùæ¦|ÈR¨â½=ðÀÿüç?“@@(*nYû›Àüu4­®®~ì±Ç"‘¥t2™Ì‘GùÔSOÅb1ƱMMM„¯òz,X‹Åž}öÙm¶Ù†\F \yä‘ÚÚZfÕ;ô *áf½e5úresv~K–i,SX ,“X&°XÔHÔ+€@5ÄR!—vÌk5°PŠj :‹ÉÜ%W +•÷!²yK¶‚?KXΉF"5ß÷§L™rÜqÇ555qpº®û»ßýîã�?îÞ½;0¸ÝPÇÛäÄ…j|®«…B¡êêêÛo¿�Y�ÊÊÊt:}Çw <˜ìêÙl6ŸÏs»/))illÜ~ûí_{í5nFÁ`Ðh¬ÖLÍÀ8\%*++xàj{ÄãqâЙb{(€7ÞxƒI(²�WVVΘ1ƒ@ “çDC�³E°ÖÕ+¶mÿûßÿ¾óÎ;Y¤!!ûÙgŸmôœÍsiM^0­SZ×Ëį姨R¾'‚Am_kKÂS%,�}GAù’Jív8\×å¶È�&ŸÏÿ÷¿ÿ=ì°Ã8lØë°ë®»>ôÐCd bÂ�æ¦ÃÇ÷Ÿÿü' 1ý‹ÅÎ:ë¬þýûs�P%˜_�Ç©K`Ÿ}öÙ}÷Ý©ŠÁúæ›o2™Œ‚\©í5ŠÕ€•Ruuu£G�¦¬7Çqn¿ýö}÷ݗÕëÝ»7µ\×íÚµëŒ3‚Á {YXAÁ‹n|�Ëå8s—.]Ú¯_¿Ù³gWTT�£Ÿš<¾‚Ë×=÷ÜÃÁÝJAö#1m•èýòrÈsk0O¬ÇÎK/½tØa‡ýáøøã�Yä°m»¢¢bÊ”)¹\®¬¬¬�þ°õ0%Ì/ŠÝHœPÀЬh li ¤€ àÁÊCæ;êÕ.üŽ�È;–ëØ.¬ì,Ðl#á 4#î–•Ê Kmh8×Õn¸a�=öhhh 1c2™d˜ãû~KKËG±Í6Û°¦ˆ¿œeY'Nd¬ÔÐÐ`©nó<ï‚ . l…ÒâRÊšš [~�K£\:�þî»ï¨;À¶íüã|€ïûdZv‡¨¨¨¸ãŽ;ˆhll\¾|¹eYÜ ÍÂ¥”RJ=ÿüóÓ¦MK§ÓìM wß}7åY�ˆD"Fá†rAÏ?ÿü^{í ™L’ óž{î¡“ €á[ÛMNŽã466†Ãáp8|ýõ×§R)®ÉdrÈ�!³gÏÞd“M–.]êy^<ç—ÉdlÛæÓ1bÄ�wÞIŠf¥¥¥Ÿ|òÉSO=ÅÚg‘c]­³Ÿ£Ó:­Ó:­Ó:mÃXss3³®„F2ÿÎì±T]ºt;vìÍ7ßÜÒÒb˜7úöí;räHú²üsÆ–±XŒÑ&ÝÁC9䥗^"„ês” Íf³_~ùåôéÓ™ñ<ïé§ŸŽD""d'úÍwß}÷®»îJgñƒ>˜>}ú{ìÁÌ¶í¯¾úê•W^!T¶ÿþÿøÇ?0QÂã“5Àøñã÷ÜsOú---t¬‰°&Ï 5x�tò¶ß~û)S¦ ÀqÁk1¸ÑúúúššR~]sÍ5¦^Â0¸¥¥Å¶m~’D«(Ðj1FÍårtX£Ñ¨öaJøa&“‰Çã¼í¤‹9rä]wÝ…uu ¸ä’KÒétiii(bR,ôíÛ÷ä“O~à�ø”‰D:�…B---¼íb$`) … �ˆ äàV×§r_ÛM2)ƒZÉXÐQ™zÇÖZûºÃ:ž•�ž°4¤ÒRz¶Ôð…ÈÛÚ.‰ª\: [Ô6•hËõe>çÛ®ê8êJõ¾ð ¬ÿqD}ôÑüã%’<‹™°ÁuÝæææŠŠŠ &lµÕVì @:¢û9)6x‘ƒ• ---ìß ƒ{ï½7!Ïœ_ß?¥Ë•””ôéÓgîܹ¦V1wî܆††òòrà Ã?\¸paEEsR¡Pˆë Ã<à Àä`.—#v›ùÆÆ‡v˜”’Å)%ÓRÅçÃÜÙ°aÞ}öY£°~üÔe-))yúé§QPfö}¿{÷î×_= èõl6ËTQuuu¯^½�@¿~ýd³ÙG}t»í¶ã˜‘RƒÁgŸ}öœsÎéð§(3"˜pâ‰ÆdÝ󟛿`†ÊÛAGær-9ÐAètPCBx€áBø„o•Z„àHikÇÉˆÆ ¦Ý%‘TÎ…Û™…ÌB!HŸ¥:\� '€L&3sæÌc�=6ŸÏ›oÛö»ï¾Ë ˆIîsä(mjj2úój|®“Y–uß}÷ !¨=žJ¥vÞyçSN9… ]ƒ'5 åååË–-4hÐÑGÍî.¦~ ›Ç��5N³‚åóùx<>zôhÂKƒÁ !m‹Çã¹\Žºîµµµ½{÷Þf›m¾ùæV=Ï[²d‰ÔçóybÉÙ–j2ã( ˆ×t>¡P¨¡¡aéÒ¥Ç<3S„*—””\~ùå •••Lx™"J{™Ò`•”O¼Þ7~>?âµ/ aýÍ‚Wq66å…ËÖ`ÿ”ÖRR+ºUi@íÖÝ@ð  3‰Dâ�wÞ9ûì³�8œÖz×]w½ãŽ;¶ÙfJ©|>Ï¥­Iˆäy^cc#¡Ó$MJ$gžy& >ž�³‹Žð¾ï³SÄü•ëºD@£T²x½Žã<úè£è$8p ÏÖ÷ýp8ÜÜÜlÛv4Íçó¼ ‘H¤ÿþ'�tÒÃ?Œ‚ÐL¡®éT‰¬§GzñÅIpÖ?<Ï3î¢ïûÙlvàÀ�ݺukjj")_>Ÿ_¼x1o²ÑçB¦,Ê  ^EUƒãŽ;.�N/\¸°¾¾ž]ª\)v-„¨¬¬¼çž{†jY–i.oS€õC†U%�d¢%� +m¥ÜüÒ…2íÙùL:hI+ß âé Þ*€%Y{‘i_ (X¾„£v:]o ? ‚!·45_Ú :²a”È3™LUUeËËË9P©¡€õ ‡rȬY³þ°ByÒI'õíÛ—ƒ�I)EŠ$V”ûöí»õÖ[Ϙ1Ãtø7Wu´Ñ)ÕZñÅœ¬Á;޳Ûn»Èår\UèÄ*¥ÊË˹JôèÑc—]v™9s&Õ«W¯%K–7•;»RjêÔ©Fö& 2dĈ«œFq/¢Q£FQ«&‘H!Þÿ}†(Pÿd'E(ëêê^ýu³°¸ÿþûù·Ý»w§<$w@òæ}ôÑÏ=÷ÜG}”ÏçYô½óÎ;ÉWÖ”ÿ[g�£Ó:­Ó:­Ó:mÃØ“O>ùú믓hžS0&ûí· ,Ð�Åb™LæüóÏg«»‰C(µ  yE0dž�\Þ&ýÁ”Á½÷Þ+„ Èëøã�0`€)róK)#‘ÈïÿûÃ?üÅ_ô¤•í +o%-y…¨ •u•ð¿—ÒÑB HÝñFxó�wÞ9餓ةÃqÒ£G�3fn1b¨‰¿æî‰‚¤Ç¢E‹6Ôø\WÓZ?ÿüó¾ï›~ˆ1cÆpV`¹Ž•xf'…䮼æšk}ôQÒ\ݬÛF‹{(YÑ9çœsª««7Úh£|>Ï"�æÂ¤”TÛ~ûí?ÿüs­µã8ÍÍÍ}ûöEAǘ+o�ïûÉd²´´”Åæ6Rf|¸Ó¦M;ýôÓÙRÉe*—Ë]vÙe%%%¥¥¥---lÉjGÞ*Ó’ÇÕR)¥•Hi=mYµ¥ó?ÿøíb!ß-Ë´$,±î€`÷”-à@*( ¥µutû5r´÷DæãXähjjZ¸páI'�Äí†IóÁƒßu×]C† ¡¿Ç ´˜V…ã–(iÏózôèAºÈ¡C‡rxp+).rp>òÓéô¶ÛnKt6O£¾¾žC±}űM‘€ûà}:ÏŠE~UÖ£Ñèˆ#.½ôRRÎ’'§�:ͺš\í¯­CÅ’@2#šê-Y7Ѹ2$%²ÌR» -…r$DÂõ%4ìd&YRKe[$òŽ –Û¥"…x ZŠçY1bèó¯ýir(§ÁH>R:{lÏf³±X¬¥¥eË-·D�΀mÛW^y%É{)|Ȩ�‹*·Îd2¹õÖ[¿ÿþûB·lÙ²p8üËè]s¸r-æŒ&¶¦W¯^í “ÆóÀÍ…C=•J]}õÕß}÷=ÒeË–í¿ÿþtóÌtX²d á/†­ô¡‡BA]…®ÓÊÏ¿r]÷€èׯߒ%K\×�Çã©Tª¥¥Ek]YYII0Fµkj)ãV o½õVNFžÇsÌ Aƒ‚Á Ñx–e�G'œ±<#ͪªªë®»nÏ=÷ä#‘ÈÇÌݹ#Jþÿ[g�£Ó:­Ó:­Ó:mÃØgŸ}f¨�™“`�§(Ð5¢‰`0xÁœrÊ)(ÊÖ`ö�Ž#óÏ>›XWÓ8ÏÓIúàƒÊ*¥.¹äsœb Š o²ÙìE]ô /ð}êÔ©Å”÷¯½öÝP­õyç�GL™‰uùít@|ðÁo¾ù&S-ZkÖ`Lj‰Ÿ¬®®æ x�š"($_è Çãq˲fΜÉ㯖¬ƒ9V>ˆ§ OÆôøS,„ý.üÃí¶ÛÎ\}q‚v!DŸ>}ª««ùÉwÜÑD¼FéŽáe8&@]]]×®] ¾ù7´´< %!…†„'¡-%,/—“ª%Ѩ­ˆ#¼|ÄðµTBè¥Ô÷´€‚´4‚J °lXe±€J4t)�.ܬ¯r©t"Ú~_lc°Mgüøñ õ™ž0`À;ìÀ'XüŠcx„6l댈¾üò˲²2¶ ™Ï·­CØ¡–ÉdXædÖ À²eË.\HºsSä0ìmˆ’Ûk¯½vÛm7Bt‹Rœ0žÍf™a¦ÆŒ|3¶‹I�È\!ïU±à —‚’?“ÉD"‘L&Cv‚Êɧ±NƹoÛö´iÓr¹S·”/:í´Ó¨ËÔ•Y ø‡«ôþŸsÎ9Ï?ÿ¼Q^™5kV*•jw}­µRZ)Õ #÷4 TuEsS“�x8Ô:á]_ç)„«aR ™1Ê©¥CÛv4„„çç3É\I9RYH–²µ²µÔ~@HGH pÚ7�Ãff³LÊ¿õÖ[¤«2y�¾}û~øá‡¬rQBœtØœ«d¶Þzë 5>×Õ¾øâ‹êêjÃuÓ­[·ßÿþ÷fVs`>lê:¶mwëÖmß}÷}ë­· “Éš¾‚}ó†ŸtÒI6Úh#­ü¢bg@)Å;‰Bzˆ¥PVŽyWM…•éQƒ9 çÎø{SSÓ 7ÜÀþH¶éƒÇüI'�TZZJz.Ž�ö•"×Z{žâ.ï8Ž'tÖsµ- ~-lÞ¾g[nÀ Å)�tà*áû–x¾@ ­¤ÖP>Ÿ*dûîëtÀLÍlêÔ©g�uVss3=F!D¯^½^ýu“w3+jñÒJn¥@ лwïb´éA¡ö†“뺡PˆÍñxœ"É(”ø;û’Ûñb‹û¥fÏž½lÙ2Î#¥TŸ>}vÙeæIù¥œžF¤ÊôA†Ãa‚xèðÖµ�2frY)uÊ)§ð8uaÖ(¶ò÷’’’ªª*£�ÌF±³Í/âšùBïÚu]öX›oç2ËR�H$²ÝvÛ™êÛ@Û³oFC¶æä÷´k®ç§ÓùH(² hkN™ƒ¼ˆR�Ÿû¥k2¡H ¡hˆ€¥¤/¬X(ÔÒ” ÇÊ|•õ]4å½`ÄnÉ C+¤ÓY –ËåœP0Ÿ÷� ¬Öq-[uE ¾W9o';úè£ÙúÃ'eŠô–e‘S´¤¤¤_¿~ d8t»uëF¨Ÿ G/‡:y ù·›l² ™ÍH)¹žûŽºù PD3 0z,[¶lÑ¢EÛl³M6›e'—£bB$ùÃþ`Î�ÍUœk¡Pˆ'?yòd"œ8M† ²å–[×íŠ'&ÿŠ[2™Üwß}Ù×E¹wß}—%{I ©Ôš®‹+ÆË/¿ÌJò+Œ5Š?òßòÃÅ’T(ê 6¬_¿~ÕÕÕlY0kÖ¬�vÚ©³È±®ÖYçè´Në´Në´NÛÆp…Þªqžè–`€âB¡Pß¾}ÿú׿{ì±|ŸùzÒ[‘à H) ´¦ï­­­]ºt) �Ãm´QÛ`ÉP(Ô§OŸÒÒRr£¯X±¢©©‰•†D"Azñx¼¢¢¢ ç8 n¼ñÆä72àmÜŸAƒ1ÛÈs3¡ Q½ñxܸ¶ŽãŒaª¦—?ŸÏ744¼ýöÛRJF˦†±¦ïíÙ³§©…ðK�$ƒQ.åÑâñø/Óâݶi¾„/`K  #A'î)ÇÍ«´ö|¡„#,Ëé ú¬E+;�° 4<‰œ�&7t옅–LªÌ )G¢Ñ`»ö_<£‰>þøc“òËd2;î¸c1çÒjbüo¸á†‘#G ·U,c)‹Q?Üv>±C��F¥¥¥ù|>“É0(Ýo¿ýfΜI¸k±°$i ¸¼¤Ói^HûRfn‚Æ\.W,~“Ëå˜Ia˜ÊóollüüóÏM‰WkM éz˜Rа>óÎÖ[o]^^^œ i;hïß¿·nÝX ÐÒÒòõ×_<¸Xy²}MØe%�ŒÊk7tbÒ�@ ­´�¾P!@ ,@ ¸ÐBA…AõÔx•Z•/µÙŽÒ�´† "*Ïdmh!º�sÁLØÉÕ…ÊǧŸ~zÊ)§455Q@4}ç�wø|™M@øçšŽ¿aÇçÚÛ§Ÿ~ʽ‰}–ƒ j{®E|ë­·Ðæ¾ÆY° ”�¤CíbæÈÅ0‚ñ©åC’p8ÜÐÐðæ›oþõ¯]¸p!;MÓét8®¬¬ìÑ£Çßþö·ÊÊÊL&CR : †@é盹F¢Y–�ó,üZú9l¥„Ò‰LH"î@ZmI@ €}›­½™€¥¤%Ú-µJ·‡å=ï¿ÿþÈ‘#ëêêXhìÒ¥ €wÞy§ªªÊôN­þl»˜•=Ç,–3½NÜ@ñ€Ìd2žS jîܹ‘H„Â0gf\ù¾?þ|n%¼  0ë‡ Ëç«=ÎöÛoÿÆo;¦}jµÆ©¡µf/2O }7zÚ¡PˆWÁÎ6ÁÀYÉ®¯¯?óÌ3-˺÷Þ{O8áCDÖn÷…!*%` ­bñ(²¶Öp]•Ïç´§ò¹´«Ò±° ÝaýÇBJiX~Z ‘…ð5¤––By9Wæ¤t¥å„-[$ô‘W”ö��0‚(?œs²#¦)}ÄŽpŒõÚø<'==¿Ž®X¬÷uQ°pÛm·¥Ò†"�·´´wÜq¯½öZïÞ½Q(ŠS¡ …º�YRØíTÁ»Q*äÐÊ®%ù_‹>‡kÁ©*ý¨®qNZÂ’Á€­2YׇÚB Q¨;B �³˜ä¡‰DÞ|óÍÃ?œÞ…yIè´`Á‚Í7ßÜ€rV{r+±/�Ô©¦¯·¸«’„QôµLµ’nãÇ�ïè" óˆ5‰�?þ˜ƒ�g¸ÓN;ß–¶á°aÃÆŒC·Ü�Gµ�—dÎzûí·7Z&í[ç0ÝLwéÒåÊ+¯dî5—Ë-^¼ø“O>™;w.»¯xÒéô‰'žøÜsÏM˜0�"víå'í BºUˆÜ‚’¾ÖÒ ¡¬k¤¢WPçÃ*�Ëjt˜¶Ð€– %ážÒ¶3Ê ûžp}ÇKÖ4†²i;WB)/¤°LuÔ ‹D"F=kW´ƒ•••øu×9ˆ"b'în»íÆF¶}õÕWÛm·Ý¨Q£.½ôÒl6K66Þ�bÍv;Q …)l½§OŸnHÓéô�ø“§Ä®2˲úõëGŽSc&`äbeê.«=€÷Þ{�ˆ npûí·Ÿ©<7·µñhþüç?¿øâ‹øÙgŸ±1ë ûÿÉ:ë�Öi�Öi�ÖiÀ,Ë3fÌÈ‘#‹1SÍÍÍñx¼�ìy6›-.�D"ã*1%�>±0«5ÒÝÐ$÷O’B�©à›o¾aü¶bÅŠßýîw˜ýaq¥OŸ>øam`ÓZ÷êÕËôÝã§²�¼Ã&dÒT�ÉdB¡�‘jü÷¿ÿ=wîÜ�>úè‹/¾X¾|y*•â·0]�Çóùˆ€G"¬(< È °;Ný[À·‘Ï#-àxhZ¨g¼9íéD²ÚQe~§ŒZë4,òµ[‰—¤‹fNår¹iÓ¦Ýÿýd�hii)--¥$’Rꢋ.ÚsÏ=ù€ h;·¡ÆçºÚW_} mÍ%«m~|Þ1˲¶ß~{.ƒmÔ9~ü¾ëºÜµÛ˸Q²ÜÂFU~i>ŸƒK—.¥”?LRÁ®]»ÖÖÖn±Å÷ÜsϰaÃHÓ�FM‹^±ÚP{�¤Â*¨(¥„°ãBœ?t`·vüšŸgI`�Ž­ør~�/”­”ò´–£„RBi@ ()ŒÒËŸeYï½÷Þ¥—^JÀ •� SâÈ‘#¿øâ V>Ötºm\–�œ[*•⡊Û+‰Ñ^¾|yKKËŒ3¦N�úÍ7ß|ñÅ™L&�’õå0˲>ùäþÂbÏ Aƒ˜X$õ ÚÔÛà¾c,ß¶]· þ`ã�7îO²xé ëQYY5¨ƒÂ§ÐÜÜ_¶C1WHz1۶ɶÑö¼¨¯¯'ŽqÃ'ÂÍŠ1ŰÂA#ôò ƒ:ÿüózè¡+VðÍ`0˜J¥¦N�úî»ï²Åª_¿~þóŸÿøÇ?²•ŠEŽt:Ú«©´´ÔÃòæóù§žzjéÒ¥ß}÷ÝgŸ}6oÞ¼ÆÆFÆ�$à†B!æ°\×]�<²É‘-[¶Œ>î�7ÞEs?‰ÃÕZ÷íÛ·x:×ÕÕuPv@Á܃™hÊRYÙªlT Ä`#HÀ 8\ xZç�ð%ri@„ltm¬Ëç]_¨t ŽB © Š\¡Ý諸õpº1ƒ�Ëåî»ï¾êêjvr 9u8æÍ›wã�7Ž3†\…ƆÈñǶ¡ÆçºZmm­!H¤Æx$9Æøy®om“éqy4Í‘$•ZÓM[3ˆöPž Éo»í¶«¯¾:—Ëñ‘år9jkkO9å”ë®»®²²’gh2JÍâƒkG\¹™ÚÜÍù]a�r k{Ý‹Ÿm! Ä”�t о–¶@ÀV"¯!$ $$ çe;ííT¾‘RžuÖYâñx"‘à~Ê»WYYùí·ß^{íµ7ÝtS±ÎÓ��D¬ü�’òœGÙlvéÒ¥ ,øúë¯?ýôÓÏ>ûlñâÅÌë‘q”óެJ}«‹Û4.\@JÉ<æÆo̼ÿÚt‘4²ø°m» F*‰ðÛC¡Pþðº s8%KKKM(aÖ[z×¥¥¥^xáÑG}ä‘G~øá‡¼ÉdrÚ´iS¦LÙgŸ}Ú±ÔQ ®jÝgµ°ì€²àKOX®£ ;t»+.iêæð�  Å7²ËsnÈa‹ã„â"º½U8Ö`Å­ÃkÙFlZÌ mÇqÕ^fÖ ãÍ>òÈ#,NÄb1²"g2™7ß|ó¹çž»úê«KKK‡:|øð}öÙ‡5Rá±óÏ4IPŸ�•|8cfBœÚÖ'XåV×3ÌÙþ¤¿Ûá¦! ¤VΩ…ô¤mEˆDà8pl­, K†‚úí• Y͹´†‡ N±%•­¡¬òHg½ˆøÚñtV{áàøDÌÀËf³„>ñM¥”Qkhûy™"UIY a.Ì“]×%^Œhͺ™m›RбÜ5×\Ó¿Ê ! îÕ�TWW3aq饗öïߟ}ö9úè£)fø“Tuëd±X,“É,X°à�7Þ7nÜ×_Íx’,@æc¿Æ5*•JƒAòƒ³øº®÷��ÕPü1»Ú¥KŒÒšŽÓ­[·b �†††¶%‹~މBCG$„¶Ü”e DB 5„ÔTëü�Â�t üpÀ8×z\@ªŒ’¾F^4—•áH\úA™áiøji�Z«öJò˜~,¥ž«««�µfĈ³fÍúì³Ï¸Wf³Ù›nºé�CÙa‡˜þVJµ�¯ß ãs]�kš2™ZÞ3®Ú¦n/Î|™¿ëyFËÊu]£�`úôé7ÜpÔ)Sèo1ä@ 0pàÀ[o½uï½÷æ;ÉdR�Fy¦}Q $l¯ó䦠a™;¦~ˆ`×°�y°B€�Í8nÞ-KX–åYßõ-ø,�B h(ÙîˆòòòòåË—sðsXžqÆo½õÖÂ… }ß'UéÝwß}üñÇoµÕVk:H6›%S(Ós%%%ÉdráÂ…?üðœ9sfΜÉu›ô¬ˆär¹l6kº*£Ñè/0ïŠ�McÆ*** CÎOÎr™`…ÏÔ,×d¤¾ù~jm ÛË袞<‰tØžÂU—ÓʶíÞ½{Ožàùí•�1íMæ777ó©qîàØÚ€¡‰‡´Ø( ?ª °È�‚Šx6›­¬¬<ûì³ÿýïŸtÒI±XŒ±SéÔZ766–””¸®ûõ×_?òÈ#»ì²Ëž{î9mÚ´vÄ…µ´´äóù±cÇnµÕV]t3Ô,Æp9"/¿‘´ñ}ë­·Þk¯½ØƒÂƒ´¡#½&3Ú$9N ?F·‘?bQ¹ø¦àѾöƒåB( írðÓ6”†¶`ÛHØ6Z‡mÀ,Á)$,@Rš¼^- ø°uX ¦–"¬]˱Zk!5Dñh—Z£ýÚ9¾ïÇB�ØÁpn�C=ô¡‡ºð =ÏëÞ½;Ùº…cÆŒAQŸ_ÇßPãs]�ƒ–éN£µ–KÉî6H«hçK@ûVòx¶ÔYá;ß~ûíã�?¾ûóÎ;ZëL&ä69Ä|ðÁiÓ¦í½÷Þ$“Ìd2\ÄH]…Bû&þa{�'óM¾þù‰ÖZÞ¯äÇB@\Ș-BHh-”?ç{JH-$ ek²¸�™sXäèÕ«'W$1bÄßÿþ÷ÇÜôg¡rÔQGµqœP(Äî(þImmí˜1c†z÷Ýw¿ýöÛLer0¤ÓiöîðS©T8Þf›m¶ß~û_„κ7UF3*x&IÚvé"‹q32ÕÄ6ü& #_Ûñz9ÇM»!Î#NRsQ,--½úê«eP8aÞ¼y ,h×›-´ Mi: ïiåK%àÃ÷-·°íåai-¬úQ°…[M^»˜÷ƒ÷™ìá¨\A(-”ÅÀjfš<ÏÓAÕ ŸSà¸~>(t«|F»¿dõZ[ù…†“0B@*ß—ZÚ�aËÒÐÚW¢ý²3|4ÆÁ`0 @JÁ@ó1òbr•U,�NG"‘âÐEØ+Nû 4F£Qs©Tj¯½öÚk¯½–/_>yòä)S¦¼ùæ›õõõœ&ŒÜ+ú¾Ï$ò»ï¾{Úi§�~úé_|q»œO.—Ûwß}gΜ IyQü¯\*++·Øb‹Áƒo²É&ŒN§L™2uêÔ–––dÖ£´`ž‚)ëb1ÃJgrmOR×uM‘ŒO¼ãš9ø*…Ÿ÷Ò‘�´- :, -tkÙR|?;4 \­á]héè€W(  ÙaDz¥”®› ÂBC4®lßP›Ó–;™µù,¤”‡zè„ |ß?þøãß~ûíG}”ýRʉ'>úè£ùË_PÔÙ³ZÛPãs]­¸›ÄügÛ|M&SÏ$ÓFm uÓQŒ‡h¯ÕŒë°9Û… Þ~ûí÷ß?ë‘BÒ‘'çâ‹/ŽÅbœk–e1'nø$9û’Éd8&Se;Þgú0Jý@¤WkmµóS;˜ ‚ kX¾rs9ËÏ*­…c9Á@^hRËÚ„(ÂÁ<�mÛ‡�F£;ì°Ã 'œðÄO�81›ÍΟ?ÿñÇç\­Q@À´iÓ®¾úêéÓ§ó}fñ”Rétš›”mÛUUUƒîÝ»÷V[mµë®»0àÍ7ßœ>}ú/@]ÅmÂ ŠŒÛ�ÍfÍÚò“Ó„ŽA�a²�/5DÿÜÐÛq2`_8O€K«9I>2×ί|>?bĈk®¹&“É$“ÉP(ÔÜܼÊjù³n2Õá4 mA;B;ÐP¾¥a hH¡…‚¤‚ö[}ßüÑίºu“ºµËC h À£ÇL�øð=©mêû’•Ö¿\¥Ã@¬Lp‡Bö|µŸçC7É}æå�}t¶É9IøN·nÝÆ�wÏ=÷<öØcS§N}ï½÷jkkÙ[Æëb˜¬µ®¯¯onnÞi§�zè¡#�<2 qC!š CEãÔá‡=.«Xñ4÷–ß�F9�<Ï‹D"œ8kº(êKŠÄ�Q*Ãvî>¬yÐS]Ósdã%èÙE‡_k_ίÙ:ë�Öi�Öi�ÖiÆ(*NÅõÆþX(•f\"“Ë`ª‚q }Y&åÛH ôéÓ‡9PÇq¾ùæ’�K¢­"�ÆÊ'Ÿ|B_3÷èу ßM6Ù„ŸI§Ót=‹ÅBV[ËårË–-ãêŠΚ\7ã�š«6œW¹\îºë®3ìíGuÔSO=µJ†ùÛUî0ñ¦C‰T¾c¾—ÿjþªødVé"o#©TÜcnÞiÏÑ£”‚Vö÷¤ÿBháÀ–¾@ bi¸>lP"` È+ !:à€† Ø|þš× @øðe$Œ–¼´TÞÍÄ™óS€WP3þ¹Æ>ŸÏ³v•L&·Øb &GØðÞÜÜÌ"3 k:N$1}î̽²��,ÀÔ `òOV¶˜4á AÞ*€çl6[QQÁ!GéOŠò*Hþ ›ÍöèÑãˆ#Ž8ùä““ÉäÌ™3'Ožüþûïùå—ÅD†î|ÅŠ£F�êÛ·ïá‡NžØÚ4©d2&%ùŸMMM»îºëâÅ‹9Á»víšÉd˜î<ôÐC¸Ûn»m³Í6ä8fåɶíT*Å#˜ðu=¦†YaªªªHëÌX´±±qÀ€¼ÛÉd²¤¤¤8YÌ”+ 3šÑuKKK1gHÏž=î lÓ8œ2Ù¤eÉT*U‡‚²a ÐÐVkÉ.�àCtXÔ&#Ç*à¥RM¶£rù„åH•óáûZûsQ…k;ñ“›•™›iñ@ pÔQG‘Òš õرc�„5«çœsÎ!‡R^^ÎtªIap`�à±±±qC�Ïuµx<ÞÐÐ`Ðå&AÙÆŸ°Ãb@SSSYYYd¸µÐ�"H$䄸¾ò}ýP�GeI×L½oIÛóRR::�PI(çe1±3§ø ŒáAZ…ò‘)øl6Ë‚)X×çaõšu²R@™%BîR©T(2ñ£!e`e<.ú__ÙÅÅÒ`0<ãŒ3N;í4ÏóÞ~ûí?üðÕW_ýøã�¹ï‡ÃavA)¥¸>œþù±XìÐCu§¡¡¡¢¢"‰ðœ űᚶTã%&‰x‚eðô`,Û}÷Ýo½õÖéÓ§Ï™3ç?ÿùÏyç�·ùæ›`,  ¹¹Ù¶ín¸aÙ²eÁ`�ÝcDŸµGñŠÂá°)Šh­xà�úúz² I)kkk·ÜrË;ï¼³¹¹ù‘G¹ì²ËöØc�òòrf¯„¶m'“Éh4Z[[‹"Àïz¤29Í}ß7tD©ýõ×JJJXÈä:FpŸ�"æE‹±¥ÀPµ´çÐ\£ hKh ÚHíåì­pþx…Õ‘?笄/à ä|_j%´*4s€h­™¶‹ë“8Þqœ£�>úÁäÓillÔZWVVŽ7Ž{G:�&ü–[n1$ä©cY…éðàƒn¨ñ¹®FÝQC-µxñbîSkú<—2îÅí¶#øzý,‘H”••577~øáß}÷]6›�F£RÊX,&¥¼÷Þ{_xáÊ ýêp©¬Þiù+ù¡¬¸¥ Z§'ô÷ú4U‰ö©8Ò¸CY–uî¹çžyæ™L�³E2�_sÍ5J)ö3 xà 7˜?4)Ëbvǻロuhî†,ËÝxã�ÍÍÍÏ=÷Ü¡‡ºãŽ;–••%“Iã$ òYý€y×u�´†a†a±©©‰‹I<燹­Cý$¥¤Žú*]¤¿€ô†ïûwÜqÇØ±co»í¶Gyäºë®£3ÌÔ0ïm|Gt? ÀCqëœ;wn;Ÿ®´”­?RÓå�€¥…IK¶!:è§•­‘E€› §—,t|´þ(X¢ãû6~m¶ÚÆer šQdÔ58©¤Ói†{¤njj2L°œ$dú´x#÷ÍQêy^:�{ï½÷èÑ£ß~ûmÏó^~ùå /¼�;ˆÖºk×®<�¦¦¦+®¸‚>^EE…çy›m¶;éf§ÓinŽm@”è {žG±L®]Ä6ñwƒØ#B÷ @,£Ã @)•J¥èZ$“I)e$áæHÂ.˜ÓcW:[· ìÃúË¿që¬stZ§uZ§uZ§ý†,›Íþþ÷¿—RÆãq!Ä3Ï<#„ ®¼8 21g ¸ï¾û gŸ}öA‘¿xÀÐ÷Íd2�<òH  Q8’qÑ9 ‡Ã¾ï¿úê«(jÄ^?œ1tß}÷]ïÞ½‰µg—|îÆóÎçó†Jµ¦¦†À¥T<'dž)]f´ �FÛs¿"€ÐZh¦?P¦Y–‚,d/-Áÿ„‚P°:ò§AjÑ,š- `«œ­s¶Î8^Úñóv»ÅŽ&‘Ƙ¿k×®ü…8ýE‹­ >šLñ(pwÈår õM`ÃAÛFþÑu($DXG$“;ÖWa´Èf³B¡ÿ©®®®mþe£åcDkxª¹\Î�[–Õ»wï!C†ÜrË-ŸþùO<±ñƳw„÷áÓO?ýßÿþ‡‚`,¯¨ ’6ŠßI&“÷Ýw_}}= ê#�<ò­·Þ9r$‹CŒ3]×-N ñ¹D"ƒæû9¹\n³Í6+¦�ûòË/McÓsÔ_5m+ü.Ìù±Ï>ûÌÔ¢„½{÷îpý-¡è T* „¡m ì@¯2´$Z9ËíB¦c~$³¥.�‡ð! ••ï‹3šF@>š`0xÌ1Ç„Ãav#±”ओNÚ|óÍ9q¸nÿýï÷ÝwM�ƒ1ÔäMMM÷ÜsφŸko=zôà/<�¯¾úªíâJñRFÒÈâDɱx<îûþ…^8cÆ ¶Z2׳å–[Î�;÷´ÓNÓZ—––²†ô+3©Q”ÜÜÐ?ßãZ@ @ &ˆ-%e+°@£•ê§ýnD¡ ÷È#�ìׯ1Ñfw¸è¢‹¶ß~{.�‘H$�N�7î­·Þ2°né1yw×]wGB/k¿ýöûúë¯/¹ä’+VèÑ£·³p8lF/G~ÛÍíeÅ-›l²Iñ Z¸p!wXÎ5Çqˆ›1»¿™ƒ¾ïÏ�;÷Çýš¿ÀºAÏ$›Íf³Ùk®¹æ²Ë.»ä’KÎ;ï¼üã\úL³TÛ¤²¬ôÌ87ÄvlYh�_?4–:øÓZäƒò:îGÀ³àZß×ë] äBBA¸ôi%r®ì þ©_±É c¾³Š"«ÅŒmfŇìÿ¡ô1G0ÇäkY–ÑÜ&»‘ \ âñx>Ÿßo¿ýn¿ýö%K–Lš4©gÏžµµµr4wîÜ矞ñ&×QðÕçÏŸü„eq ¾é7 Öžç¥R)’%üd_E¿~ýÌÕX¼x±R*‹Qù…0Á (87‹Û­¸ŠÒ½7mzDüß³Î:G§uZ§uZ§uÚoÈ,Ë:ñĉ1‘R¾üòËÿùÏÂá0Ó¬®ë¶´´0^àyÞôéÓŸzê)Ó‰|úé§›”±Rêä“Of£±eYãÆ�«­­¥³øãDá”)SÞ~ûmÓ)‚¢ôÖ:�BK–,‰F£tèÐ| ‹¹qÖtW«ÈB¬’42é<”Á²‘j©¡¡¡�ëåWkÆÚ�`0‡ƒÁ`>Ÿ7pïP(N8á„×_½¤¤¤¡¡ÁqVV¦OŸNâ`dèjc �S…ì•mÛsçÎ]²d‰!û.//¿å–[zöì™Édr# ‰Éb“&kÙ²e¦-ŒáÜzäƒx��@`×]w%ìY³Hô€p9 3˜‡’L&Mw€|>?þüâkßa‡:>_,¡mh[Âv4œfQLùÁ  ÔŽùÑLã(OBK ©!µ óïÆU—Ÿo¦±Æ< �7Þ˜ÈJ>G£b}ÿý÷ƒAr‘Åb1ÏóF�…B¥?¬úꫯ–.]º¡ÆçºÚÀ�Q05È5}ž÷Š`¢¿HßÉšŒÉ 'žxâÑGez(¸®»ûî»OŸ>½OŸ>™LF‘Ífɶ¡Îsµ¦ü_Q;|BÉ_¥B+š4ƒÔ€f²UB½½æ£Á\C@˜ëä–zï½÷’‰i×u¯¸â l„ò<¯ªª  Ì·ß~Ëz7ÐòòòñãÇóøÝºu«««kjj"ç Qnii)îôê8ãšJ¥|ßßm·ÝXÆà²ðÁ �©4+€É6’)ˆ d–e}øá‡¦VÚQT¥«3Þ¥P(TUU�Ç ôñ<¯±±qÑ¢El¤æzØö¤ãüýú믹rKíÚµk;žªj¨ªÐ?Áa«ˆÑ‘€ÐÇQSúÍïÈU¨#*À+¼é‚_.\¿uN _¶ÏêÿiãÐâl5AGŽ´‘©Õ÷} OÖÕÕ¡Ð…l¸[ù“m[,�<þ[4Ð…Ãaºs‰Db¯½öúôÓO7Úh#˜lÛ®¨¨˜8q" ._SSÓvÛmÇ*W›©S§¢Mývþ¡eY5553gÎ6lXEEEUUU×®]O;í´•+WF"Æ›¹\® ?™÷aðàÁÅà›9sæH)ÍWà‡MÄh.5ìa͆ï°ÚÑiëd�uŽNë´Në´Në´ß–í°Ã½{÷¦3šH$FŽ9oÞ<ÒXI)KJJÈ ÚÔÔ”J¥Î;ï<:÷wÜqÇ�wÞ™\À¤”»ï¾û€Òét×®]W¬XqÍ5×ð}BÃ3g³Ùººº›nº‰œ$tþ Ÿìºž¼eY©TªÿþW?ù䓌º‹Áòžç-Z´èºë®›5kÓ.lˆŽÅb†m¶Øõü?ÓÌÑjZˆÕöE´F’ðGZ Bk@AvÐ� Ñš-R…T¨$l K0žÕZhHÕÕ¶�²5#± ÷ÜsÏd2ɘßqœ‰'òcmô+0Ì…Bï¼ó΢E‹V®\™L&.\¸xñbCUOŽˆµ/Î1'ÂêBëc2;´ææfÅ7Þxƒ4VmœçÍ7ß|óÍ7ßpà ·ÜrËÍ7ßÜØØHL:õ´ÉVa¨œ‰Ûö·Øb j�“Lܶíÿýï,„�ØÇÚ0#a`ÆŒ$"5óï~÷»�7Þ¸¹¹Yk,XqýÉÈ•——/Y²„Ì'ÅÔ[ëd¦ÚºÃ;ðJyðÿýï‹-âgB¡¡ÄÅ¡);ºPÐfûí· ¯:ÿd›m¶ù¥pñ?Bbÿ _i±R¨sؘX¥i²–‹BÆÚ¬Â9ÚÄÚ›'§˜jÜU³ÿ‰J¤Ëg"rĈL†rÌš5ëŽ;î`Ò„“Ë´5Ìž=›´ud|®«í±Ç(º~ðÁétº�º…Y÷¼ð &ÔÑç¹&cçÎ;ïŒÇã™L†)ªýöÛï½÷Þã=äͤ Á¬Ç¬Ö”P�¿–¦]µ�ªÀNÉIÚÚµ©`iu®”T¾hO´9S‡ä{1"Õl0tèÐQ£F™ œã8üñwÜAüu1©‹mÛÔ7ô•’Œ€IDATY¼vØAkÍBˆëº]ºt)++cÓáÞ,.*¥¢ÑèâÅ‹�FKG9ëvÚi§â›ðÞ{ïqSf‰EÚf¢pmYÖ”)S˜þ…{ª<ÏkiiáÛl³Í8ÅxÏg̘axíðSEÐ\.—Ïç Æ‚t=eeeíuž­n!¨Ù¹ßäe+Ûª²”,x�¿€�l­îú�é3ª Bq'TBµ#Oãÿ9C�{Šƒ�²4Œã°9§—<“'Oæ 2“¢¸Hoü�;vì�7Þxûí·ßtÓMuuuF:‘=ú‘HÄ¶íÆÆÆh4šJ¥âñx(*--=æ˜cL —L&¹"E"‘L&S^^~ÐA¡ Ñ`Ò¤I,^®é2Má¡{÷îï¿ÿþ§Ÿ~ÚØØØÜÜ\__ßµk×’’^TKK ½‘6n€Í6Û¬K—.\Ö�À·ß~›Ëå²Ùlcc#ãSÞ«T*U ¤0-/ù|þšk®9õÔSÏ=÷ÜO<ñä“O^¸p¡AvÚÚ[g�£Ó:­Ó:­Ó:í7dÔj{ýõ×Mfð›o¾9ꨣ>üðÃX,fYÖÒ¥K‰„mÛï¾ûî–[nùÉ'ŸPæ´²²òºë®c¬KØ€@ pÓM7¨©©ðøã�sÌ1_ý5&ª|ðÁûï¿ÿ´iÓ*++M—žâúåe‚Á Ë-dÀ¸öÚkß}÷]³“Ã÷ý^xáœsÎyê©§ØÉ‘Íf]×­¯¯§—ÉŒ-ï€IýÚò/k4ݪþ-t+›p¡‡CC(C3¬$< %T+÷~G¾ ›KÀæL}é(ÛVÒömK K‰ïª?ÏŠK¦w~÷Ýw7ÿ©”úè£�HÞ¾’áY>ŸŸ0a€H$‡óùüž{îiâ:Jb0Yã“)0J  ŒÒ5†W�Å6óa~> q(>ùä“mO )åßþö·+®¸âæ›o¾üò˯¹æš�>úˆÍXlé(ÎÞ’¨-‰pvtéÒŶíîÝ»çóyÏóLÕ‡ÁÛÚÜíbr°yóæqó>S°´´´4‰$ Þ(ÖŠË ”Oûí·©œQ|ÓÖÉÌTíÑ£GÏž=�Üe.—»ÿþûC¡§3Å9ŒZ¬A㲩Ëqœ|�19ßßzë­ {Ç™ ÂSÂÓÂ×B^Ñ„ð± zÔÚtì9�«†€-”%´ØÐ´ÝšSTž€vkp`Qœ™8“gR€:œföñ�+®¸¢OŸ>(‚'�=zÁ‚(B s$,Z´È´ð‹�Ïuµm¶Ù¦{÷–e-X°`Ú´imÔ;™ÖqgéÒ¥³gÏ67°£ÏsMfÛö‹/¾øÙgŸ™s())¡o�F9ïØ|¹|ùòN=ÕŸ4 *ä°9R¶²SêCd¡ŸCÃó…jG€‡YþL“'ÿ³¡¡aìØ±†fÍuÝX,ö׿þõ»ï¾ã;Æ~͈Zèß¿?WWVÂPŠ¥öl¡ ¢ùì³ÏÚ¾LCW;nÜ8²ÕE"¥éû„Ãá’’³š­Öx£âñøÎ;ïl®:•J�3†é < /¯ÑïX˜üâ‹/nºé¦ñãÇ?øàƒãÇ�饗zöìÙÙϱÖYçè´Në´Në´NûmY,0`À�7Þ˜Ë刧›={öî»ïÞ¿ÿÓN;íá‡>÷Üsû÷ïøá‡/_¾œo0<ï¼óöÛo?ÂsPÄazðÁ_qÅ _s¹Üĉ‡ ¶çž{žsÎ9gžyæöÛo¿ÿþûÏž=Ûqœ+¯¼ÒøytïÖƒ·Š4Yg�uñ¶ååå+W®ÜsÏ=‡~Ýu×=õÔS÷ßÿ©§žºí¶Ûžx≯¾új Ø}÷ÝÙC `úôé×]wÝ{ï½7gÎdt5þ÷ÿ¥–Ý–}ßÏ!T+Ó…l¥ív%< /჈9iéŽy…,Vw$€ð`ûú\ ×¹vصC®rmÇo7ºcÓAßzW´°å–[n»í¶ì(bÓÒý÷ßßÔÔÔß4ý·ß~»lÙ2MMM”R<ðÀ)ôÂ#·¡@Øú„`ú£˜ºê»ï¾3Çè HœœÌoŸ|òÉ{gŸ‡Ý»wg‰ŽÚ‰“'O6«\N  ø…„Žïû555œ€$ÖZ›,�±UNIk�F)øáº®É�$“Iß÷ãñ¸mÛ–eY–ÅbÑÜ”VþôÓO™?*¾ëúÜ�ª|$9á„0_æ8ÎO<1wî\¦¢�ex&Œ{ å×[o½õÖ[o¡Ëpê©§®B?Ý1¦ \ÈLër RkáˆÂ]2À‘¬_„ˆ;è‡_ (p ƒÐÌ ¥ŽB—˜ð êèíÓ:`@ †x�ï‡B!>#¡�F£ÑhÏž=ï»ï>~ÀDþW]u‡.KÚ|3 nÀñ¹®VUUuà�òwÎqãÆqè®Ö˜]Êçówß}w±"BGŸçšÌó¼þóŸ¼Ã]»v•Rž|òÉÛn»mKK *ƒÁ Yòzöìi¥_‰I­l ÷WòÃ*�Ð�döQ�$%Ê[I5 5´‚ÒíǪc* Ùl–d†Å_]]žÆŽ˦@óáóÏ?@sss<7œ6$—Cad®\¹ÒeÂá0¥¡ˆ•FQaÀ¶íÙ³gðÁ¿•hñv\YYyì±Ç¢(!;nܸ¥K—š[C×1‘HÜwß}ÉdÒTÂmdjåSØwß}™'¥_ýÁL™2ŤPÑfKG&“¹çž{Ph¾ñïûþYg�õ׿þ•ðpMMM†xÇ÷ýo¼ñOú3G™L¦±±ñ£�>zà�|ðAÒå[–µÿþû_pÁÆ©ý9ç`Çw¼êª«B¡Pcc#ù=^{íµÑ£G{ì±gŸ}ö£�>:gÎÒ¾>üµ×^2d“¹ù|þæ›oÞk¯½¦L™ÒÔÔ„辘Øýÿ€ ( ž„¥a+(%à ©…°yÙ 2™H&Êç"¹´í¦�Ë —Bv-_3Èexd ÿÉŸL™2)dSÈ¥�K"—äŠlÆÎå¬LYYi™4²¸¹ Ÿ”­ìÿíh¤]`ºKKK™ûfœ`YÖ=÷ÜóñÇ·q�P(”Ï篻+WÔÊÊÊ>}ú°—ܨ’O|MÇaLȸ E¡Ëœ9s ®˜¿Û´=µ´´Œ;–3« î‹l6{ÀƒÁ––&Vž|òIÒpÿcK­uII ó¼¶m?öØc<=’ôíÛ—ùå`0Hä6 c&´cîÉ÷ý�7ÞØ÷}2]„B¡7Þx{ÂLË”I“±²â8ŽëºgœqÛkXªÄ�ôKÖÒŒVêQGÅ ›6šššF�Åw2™LUU•,1….ÇqêêꮼòJB\Í"pòÉ's[§3�€”hå–)ê·"áŒmI ˆœ„+5„ (8Z@Ym¯ôQí‹….úXäa‘‡jK<,öEµ'Wø¢Þ+\,v±ØÅRË},õ±ØÇB }T»Xîb…Ûú~µÂR…¥>ª×áG,E`쥞\è£ÚÔi+ÙZh‰;” �hUh7ícêÛk­¹5pHpÌp²dXy衇¸§“où¤“N"cW×N[{ëìý�›µ¹|0ÅÕä—é²üõ›”²`úû_7ôyýÒF°ŠP6l.^�PÊ÷}Û -²Ùlζ”rØ`¨ßä|µÆ f"‘09Jòr¬‰}Åd‘"‘ÈùçŸÿ»ßýîþûï÷Ýw‹¯ÎÌJ)åàÁƒ/»ì²£�>@:�&S*ÅëÃO<1hÐ ºžÉd’¤X™LFk]VV6|øð‡~¸¦¦fÙ²eÁ`0—ËQ6�33E¥Y6×§Óé66#Ò›J)¯½öÚ^½z]{íµuuuÆÁåuÑ�Üm·ÝN8á„#F1bÄå—_€7YJ¹råʲ²2ú �@€~­eYÅq?>�ÆÆFzÕ? êa¸È ]2™l_¦i2i!k똗h–Ìû*o�W•V_ÏGM=B!X–¥,­m(-”Ðr­^BúÚñ´ÈZÚ“°’v0íI¥ ´/‘³•*  4iÉ9…ÕÚe"¥ mÇÖ-I?SgEÐ’ÏfT.ãåÃíçn”bñl=û쳯¹æ>kBS�<òÈI“&ýþ÷¿_íA”R·Ür˳Ï>kž¾ï�9Ò诒džÔ+̇RºœÉV¶p577o´ÑF¬ˆP²5›Ížyæ™TJ¬««ëÒ¥ €††bcç\}õÕÏ<ó 9fM}ÅôÐöÛo¿xíÄd2yÒI'=þøãÉžÏçÍö�Ëå˜Ý5jÔÌ™3KJJ ˜zĈæÖp.ã[s¨g`bKCv—ÉdŠïd.—[¼xñc�=vÒI'¥kR`æÌÉn¼ï¾û~ùå—Dö±Âjú'¸úqaáiócûAAoƒ‹ùR¸ 2ä�üãË/¿Lÿ$—ËMž<ùôÓO¿þúë»uëF9G> Þ"Û¶W¬XqÚi§}ôÑG*++}ß¿à‚ ØóÑF»&F”�!жmE|·9—[ fƒ2¨s!_”‹P.W¯¿ÿÏxø•€i]m„pBI¡…Z*é)™lé•He[ÈBf!rJåÇœ@™VBYÈH­-È\.ç[Ðb]\)¡”pµHæTC*»4PÖ”K»ÊBgí ”È¦³" dT2ÃÚnÓ·5àoii!›ö�ù‹¿R*‰\wÝu“&Mª¬¬dCJ9räÈ÷ßßuÝh4Ê;iˆ#6Èø¤¸ˆ°)N‘gœûµÙDÇÞn»íÞ~ûmNüp8|ÜqÇ}ðÁ[mµ•éÞ`2ˆS²¶¶v¯½öb³ ×%úQp`<Ïã9›<2ÏÄqœ¶I�X2ä÷š¿—ýjÌgqu ‡ÃÄáf³Ynºi04²ê«4Ä´ÑC`/¿ÚH@ÓÉY—!](ohx 4P9Í(2T¢éä"âk/sÝ7‹Ëò9¡×ê¶/ã~(ígêB-:è•úxtXYÁœe»¾Òy?—E·�Ö‘X<᥯‹‡rgË-·Ü}÷݉CçO>ùäW_}u‡vàrJ)kjjºwï¾lÙ²?ÿùÏÜRMUƒ ò"ò}³ïp>ø¶©�8ŽSLŸ¸ZcÔÌ‹åÂRüì8+O?ýôQ£FÑåˆÅb/½ôÒˆ#n»í¶®]»rU1�}–,Y2cÆŒ³Î:‹Î ?Э[·ã�?¾ýòª²à™¹Z(ÛXØn ~Hz®ï¥¤Ô%u_À[ÇAÞ×xZxô!òUÁÊx¶KÄ‚ðÒ9ÏÍ…£‘´§=áxõ[ÁÒp|@À·<-44‹ª°WJ-,­µ„'4´/ÝŒ zBTÎÉ\>¬„„v½€ ßO)¥--¤0š",>®ãd4^%@F1�@  q<›ð�ƒ–Â&êá¸*^Ò³Ù¬¡%Cc&ýø³qð«)‰�Ç¡G�œ5”¸p]÷�Cùꫯ8\YàX2�çÅ_üæ›or’0�žU0t'•JzÕáÇOœ8‘3Ŷí \}õÕW\qE·nÝÌ ð¶˜¦Š¦¦¦»ï¾»±±‘�Œ<çcŽ9Æøº¼Q#GŽü׿þµxñbv?g³ÙáÇ¿ûî»›o¾9¶ÙýyßB¡Ðí·ßþÔSO !b±X"‘ÐZ3~$Æì}¦Œ‚Àç¦q×y{/¼ðÂo¼‘³Õó¼ÿýï'œpÂÕW_=hÐ \c‹ù“-Ëš0aÂßþö7ê©Ñh´K—.‡z¨y^ë‘…`­Úd3x’¿6H‡\  *‹Ô^mÔe×Ò:ë¿Q3€DÎ=ü°gê7bš  KX–mY–ei�u]ø~ÁÔZëÖ~ö`Ȳ~CÕŽ|>¿J´Éû°†¥§Õ²´„�–%„¥  ´JJ)mKÊ`رC¶mD«hÌ­(¥àk+hY¢u4Z–„„%„l7:÷Në´µ2údñ6ñözƒÓé4�ªl6�ǧM›F5c“é@�{‡Ø�u=>µx<þÑG¤LÛ‹93#s;âˆ#†Z]]ýøã�Ï›7﫯¾ª¯¯�ÅbŒ÷† rÈ!‡Ð…e{oÏœÞmcc#…7Î;ï¼3Î8ãþûïõÕW?ûì³T*µÕV[ýñ�<ðÀ)²J¢žCUUU<O$ÌÚ°ÀðñdzԆ‘€”rĈpÀ¿ÿýïI“&}ñÅÙlV)Õµk×vØá€ØgŸ}ºvíJÏûøã�÷<ïÅ_üè£��ÀN;í´Ë.»xž—J¥JKK'Mš‹Å Îj�>±¡pu]·íÌ‹É&777Çb16�´£þ‡cG<Çsò>ò>´¶œ g+Kz‰º¦ˆ�tV6()rÚÏ ([ Kjßúä=µ6„¥¤²„ç +µ²„ËMfZè¼¥ÒŽÒA_YJ*ØZf{Ù®Áß3¹l8¶åe3�HDdØ ‡c±ŽÖ°mû_ÿú×i§�¶råJŽ´ÆÆÆ½÷ÞûÚk¯=à€Œ"yÕD"qñÅOž<™Q µR=Ï»ä’K°2gú9P\;ŽcøŽLr–\p™LfÈ�!Ó§Og¸XYYùÉ'ŸœwÞy×^{í�!C˜e(++ãÚR[[{Ê)§¼þúë(DD(ô—�=ìùÓŸþÄб´´4™L¦Óé‰'>ü”SN9âˆ#Š‘œ¡/¾øâ}÷ÝGl8‡eUUÕ^{íUÌJÁΰ{ž×»wï%K–Ì›7/•Jñd"‘ƒ=ñx|ã�7Þl³Íêêêš››yÚ§�vZ8>ꨣÌ9ó~²Þsß}÷]ýõFÐÕÜX|ð $rŒä:#Æ™f…4A>£èÆÆÆ[o½õ‹/¾˜7o/ÇuÝGydΜ9£G�Þÿý™9%ÿ{KKËk¯½vÓM7}öÙgŒÞëëëì¶Ûn·Ýv[â6gK�U\€Â‘ZK­ ”°,+±Ci‹ #£žp|¤sÞJ7Ó˜ÌÍ×Êó=å›ÜKñ«’¾k塎[.}ÛÈDV ‘s£–Ëär¾)K«ˆ]ê¹AáK¬öh«}õaIGÙN"£•¯Fx†yO/{}F3€;©ÙîQ¤„¼Z#¤½thÜà–––’’¢à�<òȧŸ~úã�?®ªªbÿè›o¾ùÇ?þñüóÏ?á„ à†è ×u?ûì³»ï¾ûñÇgñ@eee}}ý 7ÜPYY¹~yÕÕšD+÷š!}Kh  %×ìˆ@ ±•È%°¢YYÂÒËú¹µ‡<ú–¡Rσt³a¡ì|Ú³‚*ãû9+à Ç´´• (PžÐ*oû«ÅȯĠä|(+%ƒœöàÛ>¤/lß–JÃS°$¤¦Ç+­ ¨‡u¸ufäзáVèºnEEEyy9êâþ‰bZTÕ­Ù÷À©Í¿â8aÈf|úB¦“€+<»š¸!ÂÿìÞ½ûþûïÿ /TTT444”––.^¼xذa7ß|ó.»ìÂ=%—Ëq¦Ï�;÷â‹/þÏþƒ•(án„¹®ÛØØh¢<¥Ô_þò— /¼°¹¹¹k×®µµµÿøÇ?fΜyË-·ì¶ÛnL:™žŒd29}úôÇü…^àÄá)tÐA}úôá=$¬�Ü?üð~ûíg:«r¹ÜN;ítíµ×žþùltf�5 577ŸsÎ9ÿüç?Y—M$¡Pè²Ë.ã"‰DB¡5Ï#‘H*•*&³2µ^õB®¸âŠ×_}úôé\Zóùü‹/¾8þüN8áÔSOåœ5óñÓO?ý׿þõè£�644�ª«¶¶¶¥¥åå—_6zïë7Í:ϧO:ß_[¾—–Áxµ×²#6 dY§m@s]—,u¬£€2øMIÃihPy%�·lh;’w,íi;K5.}øŸ]ònÞGs¤¤l×=£¦‘ÿ-Õ9Xþ�Åb&ÓÒÒ²fV«Ç`ié ™³¤€ »ð|©\íYp$áÛú¼DŒznŠŠy}³¹‘;ïz@¤¤—FÞoѶÊÁµ"y@Æ–¾„£”T�uŽNûEÍ$)¨ñ‹õ­sÐédr„È8¦$ªîÍO2gº®_áº.>ú‚Éd’�í¶©!ØÀWìëpS0Âhìùc²†| t—�ÜÜ܇�@.—#§A$inn¦sl.ÊuÝt:‡…K—.ýÝï~—Ëå,Ë:è ƒ^zé¥â«`À�IxŠÍ<z–ü�®!ë1ÄÏòÏMÖÒ`C´ÖétÚT˜˜¾1奶!u|”¬¦D"‘¶“DR©”¢ø€íµÏjÀU:—HD<ÏJ§áû‹'½Š•+Es¢k,€P®ö³¾ÊAkÇ H+”wíµ&™PÊËÛ´ ‰Œ�´¥sBÙ *h+åKä-•µ¡‚,%}!µ�¢¨ÂÁç§/Z2“ËZ–•ÎçtÝiGìºG*' *‹1ÀkGç›�þ˜cŽyúé§ ŽcD ¢¢bРA (--]±bÅÇüÅ_p1Èá„�6mÚvÛmÇê;B8Òºuë‡Óé´eYo¼1)n=34Ï<ó ÁãüÏ=z,_¾<�rÈ!¤Þõ'Ÿ|2yòä7Þx# •••-[¶¬W¯^çŸþõ×_o¨„ËÊÊø{.—Ëd2eee<ðÀYg�Õú° é˲ºuë¶ÕV[ <¸¢¢béÒ¥sçÎ�7oÞÂ… 9K0·;cÆŒbÀ;ŠæÈ¦›nJQYNÛ½÷ÞûÐCíÝ»w}}½”òOú�ŸápøÎ;ï¼øâ‹03)�ÇC¡Ði§�¶Ùf›•””0ãùæ›oNŸ>=™Lš~РAß~ûm*•ŠÅb•••‹-ºôÒK?üð.]ºôíÛׄaü€9Ã�6ÚhÉ’%«L13—Ç�ÖYgñĈue}±[·n{î¹gß¾}-ËúöÛoß}÷ÝL&Ãå‹-e”6ùßÿþ×§O6Þ­²6®Õ„ü>³Au ¤g”Nk-’J4H'Y½üó—Þ¸Ï�~‘ÔK -a¡5�âéÖßWÉ{ú¾4l/`ù–9!”–PÂv0”Îg"a7�˜eås"ç{¾üéŒjë+¾ CÚŽ“"«áÇôÃÒ¯´¼žïzïnÛ!_âè(´ G,AŽŽŸmžçåóùãŽ;îµ×^ãØ~øá�!CÚø«T*eYÖ&›l’N§ ¹Š”òƒ>èß¿?!çBˆ;î¸ã¢‹.Ú ãÓ€dÇ©­­íÖ­›ùØî»ïþÞ{ï1ƒÃ$Kë ÒZñøã�ŸtÒIݺu«¯¯7;{—.]xùå—×ÕÕqábo4 Û�©Å !ºuëV[[krškŸøûßÿ>jÔ(εT*õÀœqÆVà°Ã{ÿý÷kkk‹…š±îø9£}ÕUW]uÕUÜÓ‹×Õµ5¥!„/”‚¯ øÊÏg¼\^0Ú¯}>ï•/?¯ZÍeQ�&ÍÀÚÎÀ¶|G…e6ž„NÇZ¼�ëx²Ì ÄR™,�|*l+åÀ |åÀ~.+ ÖúøÒB0 -ÇÖa7i¨ß:»x¿ºçU™ömíê œ@Ïñ4„)!Öy>’•”IÿSO=• +´�>úhûí·çmÛ¶m¯\¹rûí·¯¯¯O&“áp˜}„sæÌéß¿?ws¥Ô¸qãÎ:ë¬ÒÒR3O+**6ÞxãÁƒï½÷Þ}ûö]±b[ ¦L™B ·ªÁƒóÍ7ÜïH1:jÔ¨sÏ=×÷ý~ýú™Öç–––ªª*¦kƒÁ`$Y±b…–¬7pöîÝ›@xC‡�1cF.—ãcr�û£ã8wÝu×%—\Â¥ ¤¤Ä²,6òzè¡}úô ‡Ãß~ûíûï¿Ï]’‹Æ¿þõ¯‹/¾˜ºìAaM”Å“ƒ–R–••¥R)ƒf0²á$}]S+¡ëº=ôÐÈ‘#Í;<ðÀé§ŸÎrT±WùÊ+¯œyæ™”Öã%p!²m{¿ýö‹D"m´Q8ž7oÞ|@"¦PÍÔ»ð o¿ývÓ°µ®ƒêÇÆUFÜ\.©ò9[…,/.sÖ[çz©¨Ìǃ2,µò²i¡sŽ„ˆêµFc+�¼Ô¾ëÙ®ç(D´ض«½´öt$@ª:Ž‚­”ã� Ž¿ºPK(…B+­àÕû–jvt(5pûÞ}6—~8£ìÏöbѸFPÁ‘�Ð…:‡àî¿þûcIII±’c.>âUbFfÀ}ߟ7oÞÀ�M·îAôÊ+¯pÙÌçó· [)g —î»îºë /4Ðþ{ï½÷ì³ÏþÁ�-|Ý /¼pøá‡s´3h*++‹ÅbC† :t覛n‹Åjjj&OžüꫯHÇÊßÿüsª”ŽÀùÒ¥K—Ç{l�=öà®gö †ºæõèу’~ÆØ±ÍÁó<ÞyFÅ�x‡v0` T,X0{ölnÊæ“�@ଳκóÎ;b3î^�ádª•Œ¶PP)[¿ÁÙA&Š ;ù~~°üJjwZ±9ŽSZZjÊX;Çÿ÷ö½t+< äa‡g9Ð9n¾)e$Aii4hEKuõ屃8‰;»«|¶õÿµ„@@€Ô¸Rih ZB¡ÌB¼À¼LôP(ŠFÕ긶TÚlß²àŽJtZ§ý‚Æ„—qô×o�$Ž#™LVTTÐMaæ=‘H�Äßô¡¯_’×t p¶F£Ñ\.×F‘ƒ!«q ˜1ôè(²é„ýÎÆ«c‰‚_G åìÙ³©ðü§?ýÉô¹@ÍóM­õ믿Îþl6ËÖ]²«Œ Q`mnãV³\ÄâÑ|Ñh”>šÑá �*óÝLàf³YÓŒBŸ��|žm(j£ÈÁûPÜIý“7‘H+�ùX;6 »®ëk¥- Û�í„»wmÉg}ß­�Ú—PžV9!|! ¬€�a-íµÆÇ9 %Ò†Òð5”‚m!ÐR¸¾nÎh[K_Á•Èh@˰‚TðdÑöÃ~Û¶²ùœeY®BB‘X•]×#)³NÆñüÔSO…B¡Ç{Ì9JKKÞyç6[0?"„ˆÇã™LÆ7ÜpÃn»í†:Ì–libéÎä/ —1?FH×ðáÃ>øàgŸ}–Z¬Ë—/�J¥ž|òÉâó$çU:�fjþ±ÇB$‰ÒÒR­uKK ‘hoÔO§ÓgœqÆ;ï¼Ãt'£)´Ë—/¯©©1ZŽì ÒZwïÞ½¦¦†ï¸®;qâD9B3�aZ@*++kjj„Œ»&Mšôæ›o²1eàÀ�ûï¿¿‘€>÷ÜsŸ|òÉO>ù„V–?‰Ä�wÞiÊE<f x-çŸþ�wÞ‰DøPxÏÇŽ{ë­·ƒÁwÞygç�w&ǤiÈ£Åééºn.—‹F£¾ï  D"qüñÇ766^uÕUÌD£Q¹±±q„ ˜ó5¹]6§òÃóæÍ«ªªb=‰_Ÿ1WÀÚ~ûÁ×Z(eûÐŽëÙcÓêæ¥¶çJH)I:¨Õï2Z(_ºB[¢–´„p!\-<-�Êåµ­<"äóPNØÏ;ÑPHð¥?ùªðý8´„Ê(��η Ã¶ªèÑe«€,÷s¶T–/¤)ÚÕc”K4·SY­MÉ4~üø½÷ÞÛüS0¼âŠ+¦N�J$A0<묳Æ�¿AÆ'ë¹\Ž[ d hllä�+¦ùnjjŠF£Žãär¹¿üå/555dY$h€¤[ÕÕÕ¯¼òйXv@&‰«¯¾úÄO<óÌ3¹Ù«Ëwo¸æLÍ•(‡¶ñã«”¸8Zþgq6ùã�?æ f¦˜mÛåååuuuë:$***ZZZŠ)•ֹȡ‰eƒ%¤€ÖÐ, ©•­…S¢W8Ü;L%¹\¦¥¶¶[E©Z{Z}­Ý¼ëCûªE¹éHNFl')E"—CI Ú·“M¥–•ln’GX�|Æ­ …­µ®*YJØy�¼—w“QKôrì�Ý{”ÚÉœmI К«,`ý:# %6�T*ÅIGÖ5&Âè’q†¢0˜Ù„Ä1VUUuÿý÷xà�(ô`ù¾ñÅOš4‰µ@)åñÇÿÜsϽýöÛL>RÒ©¥¥å›o¾1e:Š$¯ollÌår^xá¹çžûûßÿÞ²¬¦¦&.Ýÿûßo»í6³gÏ4hq$øàÅ‹_qŤ £sˤðk¯½Vœoeÿ+%¼¨H$rôÑGß~ûí¬ë´cÿ1×YÎK- …VBii•÷(©Y”hljÛñx8„P^©´/r¾§ �µå­¾ϲeÀ 딂 ²r9e‡C /åZyÏòekXZ´„¶|Ôz5YP)¥†öµ¯•ª5ñªt^„½p™ —H„t\ðûŒŽqii)§[4mhhxæ™g¸>°(bÆ?'¾mÛÿûßYäàáÎêêêJJJž~úi×u_|ñEú¡ sùàƒfÍšeöDŹ\ŽÄÈ‘HäÊ+¯üãÿˆþ€·�®¯”0 °_Ÿ÷¹K—.---†ÌöÛo¿6lØâÅ‹ðq$“É–––éӧϘ1£´´”žy$!‹N:�>ûì³ÇŽ €�Ã06¯Ó *ÖY1ÙŒH$òkõ¯¹h¯¤ô¯ë";í—4}SÛü Ö9:í—4 ÝÚ�ÑJ›ÛÙLÖi¿  Bš››™J#‡ÿµ>¼BdqeŒÇìOKKKñ£Ó8bê+¦·o•Š‹ ØL»= ü§™Læßÿþ÷�7ÞHz¦‡LW s4„¬²jÂô+‘eGy$Q�¦Í‚<ËIJñeµçoz� ƒ–Öš1j:�¦gϬ��Çyz,r°èÂûl*L,r$“IÃíþc3ESì¡§ÛÆs1Á-Ãioü|S€ X¾¶=i)©¶ŒØ\•„E&“K&´€° -Oh%-í*í‹,×M;?’Ëi¡r¶ãVăÝ*­HÄ×pRž¥¤¶`IØ6„†ãAj!µøA'ùp�@>�†B-…eÛ‘X[lêuöØcǰß~ûMœ8‘Änݺ±`cÛv:�æ�1ÅKfjPÐ#1•]ºÁ`�Yžl6{î¹çVTTÜ}÷Ýÿýïùaù·J©²²2¶¥’ÖC1xðàqãÆuíÚ•µáõ,r¬ºf|?¶}–E÷Ç–Ò‘V¬{·¾Cío}öDÊ/P¤rA[cË ÐJxRK饶|@i!}éÉr•EmSó[ÙàgÑ¥j�@iw×u[•Ã×"OH­l!„�y�Ÿ¿ÿþûY5£@II‰ïû©TŠ{åÈ‘#/¸à�7Ðó<¦ÆÌŸg›ÜîF§Ý-VkLëp޳’ÊB7Vv‘gʳëº\ÊØ.ÆÌi]]Ýzôs�o‡t(®ë¨þº ¬Âf'aA*ZIKÁ–­|V[v©Jo¾Eßt¢Þ ©¤í+k­÷G©E¼,îI¯Y†Ý@¦,q�ø—ÕÜÔâ ',u÷œõû^}½D4àXpBi'c+½öLJ%â•ežçes©²�Ý=ºñ&]„--¥-­”–6ˆV&[×ÅØ©O nf3ËËËɱÖz –E?Ê´ð²nahQ™ñ<à€Ž9æ˜gŸ}�±ÿûß?üðˆ#2™ wœW_}uç�wþì³ÏŠåLCIcÈîX__ߥK—¿ýíogžy&€?üá�>ú(�Ì ‘­¦ŠÕ>Ž.‹/6%:Ӆɽ»õÙI™Ëå � óžl†æ/\ ®¿þú^½z]vÙėB¡êêjþ¹Q§#Büꫯ¾êª«´Ö·Üå�H×+’kñd***êêêØ¡B3ÙRÓzµÚyÁs.Vô¡'Ï^Uµ#Ÿ~úéƒ1bÄ·ß~K߀Z€\:øçf�ârCœ0aÂÿøÇ%K–ôîÝ›÷¹K¼Vh© } H–Ó`÷X¼¬¾&éˆ`$àø^VAÚVÀÍ@p¤P?ùª%<­BN8ì…ê¾KfÓ®‚Ì+¿¼4-qò�¤gå´ÌK%ß¶}GhËrÍ\oÖú>GìK,- •ˆXø6„TJ@i©`‹UêB–µNSRk]Œc¡Ždƒ( a˜ÊgûŽ™›Ædˆ²m›£—Ylº4F­�Á�iågJݲ,3$âñ8ÇÇ«õ¬(Äãñ«®ºÊó¼W^y¥¥¥¥K—.ìZ`›_Êò!Ûñ=Ïûç?ÿ¹ÿþû¿ñƬÉQtÄL^£ ˜kܸq®ëNž<™Óܬ<Ÿt:m¨,É@‰Äþýûß}÷Ýûí·wœâ¹“J¥ºtéB]�^xaÔ¨QO<ñD]]]&“¡Óëº.#PnX p …B�<ò5)9éxɼE,³¯… !hÁè{k­yç!öë×ï™gž9ûì³çÍ›—L&s¹Ÿ§žY|ÈCÀV¶t:}Ûm·�9’ Çæcÿ§jœl—‹í¬süF-›Í&“I®¡Æ·6ÿF¬ Þ*+”‹¥Óôc,€ P´¹¹Yø¿)Þ*J·‘¶žï¤Óiƒñù‘­‘·JYÚƒOÞ*K‡;Q&R©"åì£Ìf³)Hiäý„¶UÊËtòVuÚ7òœþ|Þªâì¹áŸA¡l@  ß¡Fâºßp4E£Q¡¶-qaâ¶q'AŠ?Faó¦†ùO¼÷í½÷Þýë_É4úᇒUœÎ1ú|üÆ×^{mæÌ™|ß8pà€Œ¨)+=L!Åãñ¶w"ÓJO/“I&AˆˆáÇ ‘zw|Žæä|’„Ê<ߟ¬01J7%¢¶ÅQy&žç555UUUQÉÓ(!ÿLÓ„ôl;ßõóå�P¨OOEl–8Pµh(>„€^ëDK.׸bI@øžç«’ht“ÞÖï6GU|@¡„„X¤Ð’Ъ5Ó¢Íù^ƒ�X&ƒXÊG6 h¥|”Ä\·ÃKÝ ¢Üpà GuÔ­·Þ:~üxr0ÑÉä8Ëˡ v×]w…Ãa)%‡( ír,_¾<‰´´´H)Ãáp÷îÝ™d§Eð)§9uJ'Mšt÷ÝwS�!œQ 6ÈÐx<¾ÑF=þøãC† ÑZ×ÔÔÄb±ÆÆFÛ¶»té²råJªš“)�^½z�?þàƒ¾é¦›æÌ™Ãk¡G§µ6Ìd-`87zôèsÏ=—1°ëâD$— 3Ïÿ“ÊÌkÌ?ìYj­çAjøž+µyÑ' õßt „p�JÙ8¾6ÝO€ü „…¤å»ðÂVp¹ÆË‹›ççÖ¹ù°ØÏóV®\YYYyÝu×}ôÑGŸþ9»Ÿ³ÙìÊ•+ “*Ï¿±±‘ÛwÕ~ýú566öèÑEžeYË—/'꜉Ëh4jøL×/3�±XŒ;Å™gž9hРK/½ô£�>bY‚i\îμK—_~ùyç�çû~&“á ðr6Úh#N.££`�h4JÒ9Ö–H gÔzVk|4fùb…˜!3G(“ �À®»î:iÒ¤qãÆ=øàƒæÌ “•y²<±H$rÈ!‡ÜrË-lëìÙ³' ’íXçЀ‚ÔBj¥©„ôã]­MKB›ý.d®‹|.dÛeÁ0´Wø›µ›3ž‚ ©F»%ïi;hIÑe#ôÜZ¨`<ïĵ„¥`ù°üÖ„^Ýq”iAp®šP”DÖƒ !AÒÍ //©„°T,YÏŽm–Ü”R���Ô]c�¬_¿~¦Y‡a—i(7Œ»RJBèØ²‡#‘HSSe*ØóaÊz@‰ÒVVV2wÏ�1 šp•š4›m¶Ù˜1c¶ÝvÛË.»¬¾¾Þ²,98­H.G¯lË-·|ê©§¶Øb âÏŒpw&“Y±bEÏž=‰+â€g�‰Dxà�I“&Ý|óÍ‹-¢îZ6›5Ð!DyyùÊ•+-n¹å–‡zèÅ_\^^nzþ¸_°0Ã;‹Å-ZÔ·oßÛn»í°Ã»æšk¦N�ÊÂ/ʬxÔÐJ¥RçŸþE]Ô»woôuéÒÅ„oÔê Ó2¿¢ººšŸ7Bñ<¥–––ŠŠ ­õN;í4kÖ¬¿ÿýï÷ÜsÏÂ… Q¨¼²ø$¥äò¯;üðÃÇŒ³é¦›‹÷¬÷44LP(`¤Ói.ƒ¿c€còLŒ™±õ¶N}Žß¨ÑÉf™�w´ý¬�:G^7Uf[ª}¼»¯ržn Åb;íýÝ€l$ð›ªs�¦°8gZ__¿f|G[ú¾P¶m ?°Â±¿*³/ùÙ¥%]r®Þ(•>kÇ]ö•öT^Þo�£•ƒÎ:G§mp£ÃT©‘U\?ˆINƒÁ ÙÅ›7“’lç_O²€²ÆÅ¹9“l]íɬÖu0WÇúÇj•BøEä•2ªÅÛo¿ýœ9sø�#�<òÉ'Ÿ´m;•Ji­�ÆÚìÙ³ÿò—¿|þùçÂáðµ×^{ÞyçÑ•)Ve`wöOÞäL&C"ÿ3—Ë‘·‡Ç¡ ^1�D|ˆ¬­Òõg2…x^# »&¿ŠŸ4ü¥�<‘ñ·vìö€?Ÿó=["ÕÜ *¢‘DSc<Ö¾Z %´`+@)(0Ù´¶1X$›Yüè#‘¦æ¬ë£²¼dÈV%C¶FeE:¯lW -”�y)ó$ÉK©•g)_«Ø«<­òù|iY™«ü¼ç‚ÁœçZ–㥕m:NŸÃäÈèЈZ__?~üø™3g~òÉ'9Ø|óÍ·ÝvÛ½÷Þ{Ï=÷d„ ¾¾>0›`(°9æ©VÊGlR*(šATž§[ÅA˜H$žyæ™·ß~û‹/¾¨©©©­­u§k×®ù|þøÃgœ1tèPð8lL¶tÅŠdöçå0B#¶zþüù›nº)€•+WÖÖÖN˜0áÓO?%¡y&“iii ݺu2dH×®]�=öØ]vÙEHyÓËËÛÎáÍQÊ×ÿûß÷Þ{ï²eË/^�Ç»wïöØc�1cÆ  8ÌÆ|ÎÄæææ—_~ù�wÞyÿý÷o“U`»í¶;üðÃ÷ÝwßX,ÆuÉ.¼ðÂï¾ûnöìÙŽã :tðàÁ'Ÿ|r¯^½Œàmñ�0?Å0™)ãSfZ–écþžÏç_~ùåW^yeÞ¼yË—/¯«« ƒ]ºtÙgŸ}Ž:ê¨Þ½{Ó½I$Ì ™/Z�¾º"æ � ädèÖ>„@"¡•Î ™Ï¹MÁ|׳ˆe9ÔÖÚÂZm×…ÐJB -„†¥¥ÖŽ��oee$9å”ç߸ҕ5B#à÷=bß;6é>ÌÍæ×O*´ÒZ[žR®ïûJi¥ƒ‰¨¥Cùœ¥�bñÕp~†ñ‘OŸêêê�6Úè'§6[ L7ÿ‰E fšššÊËËÍ£üåÇ'fE,_¾Ü,´ârkl2ãçM«Ç´iÓž~úéiÓ¦-X°@)Õ³gÏm·Ýöàƒ>âˆ#HziYÖâÅ‹ûöíkŽ|ä‘G>óÌ3LL›=Žÿdºgèrüä gö'‰ïeî$¯®¥nN˜«%’õãÙ K{1¤ø¯ÝQ… @»ù\&kih%’Y׉G[”nö½Py,•ób¾´ÕÚêsXJF-826òPKÎÆ}Wÿ¯9³Ü’x™¯~Ÿvo=x�h×!;•Í;°ÅZëøyKÚAh‰(�Ȥ˃A?‘ŒZ¶T>„²lÛ ‡ %àiXr]ç¤ñd¸?¦\.×ÐÐÀáJ¹rnôšP1æ†H_ËlXfØÄãñUÆ|:�öŸ�—”ä ó?L…0A`b³¦¦¦x<^Œñ7mæFüÓŒ:#ÖjŠg¦Ð…¢¶ º^fLš ËzL0ä9˜Œ')ƒY�3#ÊTÝ’Édeee1™þ*_G3ŠÄœï&Ô4œ$|Dz›O¢P45÷„k‚ïû¤øà÷*¥ZZZÊÊʉ9Øïe–8fÊGÍ"× Mö­øw2ÅNs¥D ã‡Zü�hFæÅk¯y‚æÿ-ÿi=É:¾¯s(ÀoM²jéºpl47{¶-ƒad²Í–ÍFº ¯-¡„–Zj©„Òžö´çHG ÅwÌ+g®€²´RK¥ƒZ=ÛuÃ5Kš§¾òîvt…ÐÂOö¾Û?z•ï*= �k«{,”ò\iÁ–R ’Iie ßC8‚¬ _åJJ‚¾v¢Ýp¾«°¢Í- X‰å6¡hu5ÏÚdg6ÈøDaå/΢²oЦÂ�Bv?ÒÆXeCgúÃ,2¶mO›6íÀ$øÚuÝóÎ;ïÿø‡9ˆ™û†nÈ -LbèÇf6hƒ6 €O�|>ÿãíúˆ‡(h†ñh«<¦µµ¢:‡*47úžçfÒÂS–”ÙL>V^þÿØ»óhK¯²Nüß½÷;œñŽ5&E&’@%!’0$òƒ(ÈBD¥¡A”v¤eµ‹^íjí[íeKk;´AE"2C�LÀÌ!©ÊPU·ªîx¦wØûùýñœûÖÉ­T¥’TrÏ­ú~VÖÍ­{Ï}Ï{†}Þ÷ÝÏ~ž§çý 713Õíeµ`œ#VÌ# 9âØÒ+‚$éÔÝ1®¾îCÿvso²Õìöž?ßýÓ7¼¢µ”»¼M·½Qœà8·/€I¢Až÷ó^«Õì÷:ÓíîÒb»ÕðÅð#:­5 ¢cx5Íä¸U¯lõ6Öå :¦Ÿóš01ú'ú^­~¥#wô}«o­Ñ¾nUaUŒL£�R=²Tíg«ŸèîèÐÓw‚|ui VCwÕá #‡m1¥+`ª�‚*Ì {XÊGÿª:F�‹õaê`ÔUÉÁ¢(¾ð…/¼â¯¨ÈÏÿüÏÿßÿûµ$ŽŽ£*{R‡Oõ¤UÔüΣ�U¯×èt§Þ^wO³Iô…ÓŒ´ÑóÑÆrkº‹k°*ÏsýŒª>m{6Õà Ç*Î1È;¾È�1#Þ:[³’„)½u&Šàà ϺIj`Ž÷|Õ |™5ì,×nOgÚH&{/|îŽ3ž…¼ÞÏÓ¹àú�Èú4.[&Db‹`¦4EµÀKßc:Ëom­ÛCZkYç—» ­ÉFš¦KË�©ÉYvV­Úú8âª:À�v—©Š �®À8òx‡‘C§žŽjÒùèu‡n¿Úަà7 ÝÈèeNuB[}àW§RzÕšo£ëÞFwìȪ†+ªŸTQÉ*Œ­µ›ªl ¬w4˜Zm§zgVE’«™5�ê´¿:› UË�êÓcâÑàšÅ4º·zËjc¤ò’¶²«î¥úóê¹Ò‚�Õ’¾Ñ�b½DÕr‚UŠçè»ÇöŽZ3äçççO`«ÈBß*:¡ v»ýø“ÉX·êUµ®Ò…{zuq¢âö'�Båð·�¶þéFWå›W ?« 3�j;!ãlQ¡4õ¤;«§úá^}ø:ç<¬剫ˆ@ôØé%ÊhՅǰ8#5^°:‰3Zee”6C~lÛÇÈôʱ‹®T§Z*ªúù‘Ùz¤¨Î®F¾þP§w_ô¢ýŸÿó~í×~MÏïºë®w¾ó�{×yž¿üå/×ßV“­ºÿZ"ïÈ;:Æþ㈚Ý›0QmíaÈš›㼪jg¢ÏùñœtV/Mu¹x¢úsÁ´Äe^ø^oÊFFL±Ø�NÚVJãÀ¼…×Ò°&ÇÿÉíóz†¤WLÛZ'·R 7ÀTÒ6¹"�ÈÀÀÀ$NÄ xÀ¬�G¼tøè"¸ê�T%EUcJ¿=rU7®¾ÑW¹�k.œŽ|ë6«w”îC5FßiÕ�ê]h[róÝnwzzú]ïz×k^óš­[·já)mŠ£A k­–ß¹ÿþûó7S‹wk,äÇüÇ«n%UUîÇVrsC ÃÂNÀá VM"íuc$ [°Ú^ç8æ<ƒÎmÖáL)¾(|)‘+`Œu"VÐLKŸe!/�P”±‹ÃÀ7âš”åño?˜ Nl8A€±2\%` œ.$×öWºÒœƒñ±Òx¡÷¾ÛíNMMýôOÿô¿øEm´3==ýÞ÷¾÷'~â'6mÚT–eu²ª]¬’$™››k4Ífó×~í×h5æ<Ïâ'~'¦þáÉà èïbÃHÃáð†ž�Úa„ÞÈñv"‡ ! ‚(AÚ¨û�±X”ZªJ€PÇð8±!´bãño¿zÐ,“*Ðh0ú?¬.bà2¢õÇ8=jZø»*¥­«Û¤iª×{Ú#®ªµÚét�F5í2Ú�Ž-1È¢�!”.c œ\µ²§Àj"€hØEC£"áx¾ú‰ÆR©ðÒMŒ�MË}”ýÈJ6Xo‘;.X ‘'Èm ŒXƒX+au>×+fuGë�ûS®å�üª9‘áÐÓ ‡‡)�ã´99L€ÉaŠãÞ¬­TÊ`¼~'bÅ•¹¸$)r;9½Å –W$‰�/{ÎÕÍø2"5ÀA"��©ŠË £+1ÆDÆÃ<ú¾ÇtlµZí…/|a»Ý^^^‘¥¥¥,Ë~ù—ù�þè�fgg«.�£EÏïºë®Ÿû¹ŸûÎw¾Çq–e6mÚôÆ7¾q´Ç©Þ~ ëq?Á‚ -,`ŒˆÀ‰ñ`a‚E)«É`l0z||ä¯@a`|ÄFÖÔSgIméJÛl®,vÊÔ@Ô¬Ã{ô‹Ø¤cK{¼Ûo…à,Œ‡–ˆþcÄ:Xx -!Ç£èãP¯×¤�+¯¼²Õju:+++sss?û³?ûWõW­Vkÿþý[·nÕ4eýíŽ;æææ^ýêWík_°iÓ¦¹¹¹³Î:ë'ò'qJ�.Tg£F`ÚtÊʰ’Í +º ÄꢀGü*ˆDL?G3À:_šLHk®Ñ€Õz�b�Dé4º?¦°È�F:éëêƒpΘ ‚‘a »ÃŒf@®÷“MDxl$""¢Ç V«i„c0E‘$I£Ñh4!mSY]@èv»­VËZ›çy·Ûk­ˆ,//¯÷ãØ�ôª1¬æk蔣“áQÐK»à$8)�+!˜ p|_a±‚rÞ=P z±ÉS—ôá‘DÞÀ[xoƒ·!ØÒ[_:lÞ†`LðVo0òó�Ÿ�à‡_µòøc"AÿÞX¶õÁ”@HâBZf�ƒûü¡}y™§�$Iª Çq5é@LðÖ‹)aDŒ ذڙCït¾•N¤²,wìØñ»¿û»š¨B(Ëò¯ÿú¯/»ì²ŸÿùŸÿÜç>·oß¾B¯×»õÖ[¯¹æš·½ím—^zé¿øÅ•••¢(tîõšk®9í´Ót–vÔ©ç€vÜp‘Í~ˆ¬&>ˆÎµZo¬7Ãò3ÃäqcŒ�Lœ¸(r06+¢îÀ­ôÃüB¹¸ÔNk%|š¦€�ù"¬®R?®¯ÁØÒÚÂFÞD‚hu‘xX+‘D~B…hW�Sðõ=14C‡LY–›7o¾úꫛͦµ¶ßï×jµk®¹æÌ3Ïüõ_ÿõÛn»mnnNËÁÝ}÷Ý»vízó›ß|æ™g~ûÛßÖ«¹¹¹‰‰‰w½ë][·ní÷ûQi²¨+¬E´F¬ÆíŒè?�g$1 £&çפžäyYxÀõr?×<(²àb��10Vƒ( ƒÜ 4ÃZª�üÀÈNZ+ÖˆµÚ(kxˆ÷ÇVyˆ$ZoÌç ""¢G­Z­–$IQeYcŠ¢¨ÕjzƒÑµl�F£ÓéXk�†fxèíuv†- Ä!„"¯—ŒÁø`ÅZ ­t 3,y ‚µ¥V ¨ò,Žþ5 ˜:m«ô–‚wé–­Ó›6Ù$ƒÈ9À‹ïH0(aýÜïûÞßtRžsîåδc7Q^ ŸGUS›‰-ƒ‰†ÍÒ‡q’0œ�ÂÖ É=tÑÀOüÄO\sÍ5Ÿÿüçó<�ã8MÓ{ï½÷ýïÿûßÿ~ÍØÐª�Þû‚Ö§š˜˜èõzËËË¿û»¿{á…h6›º’@S*õûõ~|O6ƒà Dà‚#0ðFK/Z+ð6¸€È[ƒãÍ·ð¥‹BdLÈL^˜<ŸE²3š¸bê´»$KZée;Ή{™�ã²,“Z³Èó.:î홆/´ñ†±V``]€»úqÜcŸàœ ­V @žç�Fã oxÃG>ò‘/}éKEQh/ñùùù?þã?þÿã0ƈˆsN;âÔëõ^¯ V«%Iò¦7½éÇüDZÚyŽ¥«*NßÉÃàAü€ Œ5ÁÆj…¹ã!&ÄièÛnÒœÞrZTQÖÉZñô¬ÀØÜ˜¾1™–Wµ¶€˜kä¸K;еbEŒ�±bDŒÕ¬ÑA¨ûéVw`®#Ñ`œƒhŒTÅF˜aI½<Ö_'7œ‰2™X?¬¥nò`»)Ùq&êͲ׃)Ü0H ‚[mµQ…1ôÞÍa #°AàV›€�Ì×í¶@8ÜÜh”Bs#9æ8,ïf†ñA3ì¡ +ÆBPfe;Ùú²½é¦ïžS>ëÂÚþæ<�ª¹… FL¹Z<]Gi8<¤Å%L“²hÕÄóÉO~ò-oyË_þå_v»]ý¡F8°zxÍó\o9 fgg:Ôh4þìÏþì­o}«ˆt:�V«¥¥«4·òŒsÀÂ>Ìšj£ó’0lõÛÕab׬Å>úW¯Íá�…Eáá0ÕN^Ð8½9=ùÝ…¹42?øÔ³Ûý�ϳ�•iÛ V²f½eµiÈqlß@C2A`ƒ V×+X�«:�WŸ(«Ëãé1(˲Ùlèv»Ú“ÜZûÉO~òç~îçÞóž÷¤išeY­V[XX�¦©¶½‘z½žeY¿ßךrƒÁàÏþìÏ^õªWéf'''uƒëýøÆÊ1Þ§võ8³æ6Çy| e6ð¡oZÓgœ¿¥?Óï,õ›ÍúÄÓlȃØZìQ#QÂDÍñáðY«ˆHÐJ’#ûIDã…q¢q!Á1Ag¢lˆ�¶qE!(“¸îË$ëGÆÔêM”˜[êJjuy÷2haùÞ…¥ËÐ�¢Ä¡¾ã´§M4Ÿâ)B¥…ĵ$)ò>CDt¢mµÚhèB§fFEQ4Zdœ›² €5NB/Έ‡× ÓáþÆ [‡a¸ûxˆlÔ¬]|yM¬·XW Êš«Á›x=:91V¢€ b«÷½vz©š¾Ñ•nκ²,«uÇQéÉ#ß0DÃÚñµÚÿ8ÀÀ@Š(¬c †ëX�óëH£S@†}È€ñ!1M μü¼�ÅVšå£Ûs ÆG#Mb«û´°""!ˆqÎ#Áˆ;þ�:>Ƙ‚ö:þ£?ú£W¼âW_}õç?ÿy�i­n¦«È5z „ð–·¼åg~ægž÷¼çaµ>$ͪÔðÆ©äX‹ackŒ®´.|é­Ú†\`†W ïuùÀ0¶w¬¯$(Œ³I½‚ïv&]üü‰ôÒé3�Pëg©±“&ƒ¼Ÿ6ÒR+Ûçö%$¥ˆ ÉM°V‚ &H$AB0‘õ1œã" Hàr‘Ǧ:Õ˜D5X®¾úêüÁüã?þãk¯½v0è¹n–eƃzöàôÓOö³Ÿ}õÕW·Z­ÑÕ<�Fc½Üø°D$1Î:ˆf¤ ¼3ÒëI¯i<Šã£ˆ/B£Ñêv;nÖMN·&1`à³yo¼-þ¼`uÅÀ£XnBÙØXS†2H0VÄ1ÖÀV™P…C8‰Ö'ˆÆˆÁ *´*Æêõ±ue–÷œiÇQ-Ë‘ç>jùFTL4“ïÍÝzëM߸î¶NÿþÌÏcZÍM­;·Î4Ï9ëôg=õŒç4Ig¹Ûé÷“(â*Z"¢“ƒÆ“duݪNuÈÚy‡Õ<úã¿ò ÖõíÚxÃpÀ ×–Àÿ�þä‘wxt·VSt9äè#":Yh*Fìœ1ÖNt«ÊXÏ×5㫚‚�±’À'ýý£=ÕÓÉà‡Ì×(g±ÀZëœ3F8‹óDðÞ—e™$I»Ý~õ«_}å•W>ðÀW_}õ]wÝuÛm·íÛ·O'X'''gggà~àòË/¿êª«Î=÷\EQÄq\M³4@'FŒU¬ãGGÓÈÿ‡ß×x9˜:x@j’× à!V�‹æx·¼º}a5óјŒÕ¯‘µÖk¬]]7XŽÇ'À«_ýêüÁüæ7¿ùÏÿüÏ_úÒ—îºë®ªXëÄÄÄgœ±sçÎË/¿üû¿ÿû/¾øâ~¿¯Y„DDWo¬÷ƒÖ¬µ"0Æ'"9î<$öpüÇG£ N€Ò¯½ë‡ÝS])k­v½Ó³l#AŒ;2“ƒc‘h<ðó—h<�t¥ƒµ&¹�}c�g^z‘] ØÿõÛ¾¶çÁÛsßݽ|)i„¤%°}ï‹ÅÁ�åî÷ÜËÜ¡;ÅÁ³O¿´m‰ìBÂj¡DDž®Ø‘�¾ÖÚñÎ9Æ9è$¦oïj ¾ª&ÅÆÜè>cF£’tbÅq\u°uëÖ­[·þùŸÿ¹ˆôz=}òõ3I�W­²ßªnü­¬92j”n£Œ»£ÑZdkÆ _ôNC­V몫®ºêª«ˆHQóóó�F#MS‰UN³fb)-ÇÊÏÉ#UO‹~”és¸Þ;u\tEŽÄ5ÞE_b¢qÆ8ÑZS§ÒZA ‘ (l4°é Ÿï½wß7®»áÃ¥�·IÔnG&6…ï{ßç“Ú-3X™¿ïÀ®þ·—:Ý…óÏzÞöÙ ó¥`œƒˆhÃ; .±ôZ—s4tÒ«ÂU`r£Œß†9(§O(�WÕà!„¢(tUxEº0¼j‚¥ï�WÍó\Dâ8Öé²,¹„\þ×8ÇF~F�žO­#§cÐE‘1&I’mÛ¶yã~¿¯ãQ?Þn<³Jÿ¹A[iƒ¾ÄDcncì‰N2F¬•0,D"0@„Ê8ŽEQv¢¤pÉÊûoùö­Ÿ ÉkQÀ¹8‹(Å CÒèGM4Jtúß»ãÞ(ŽÝÌÄfcNê�{7‰ˆhýé”GÕõ]¯»t^rü=ìÂp^:ÒIF×_Woìa­9íx±A¬ rTsyë½_'•ÑgØZ[E5ÖЉWkmQQ­ÉNØè“ø'Üè³jŒqÎm q÷°ªq·qó87„²,ã8®ží,ËBš¤õåªEýI’Ôëõê#�!áG4z4Ü(ãqtÜ©51"7<"3ba¼­’9$Ö—H’$ÏC)Ý$ +ƒûï¹ÿÆ={¿=¹#ôK\$qêÒºµÎÛ(Ä5,wa�ÉI„¸œ;xWó�©³v\¸)Þ²Þ�ˆˆNŒ5“§G~ODã`ÍòÏ�;H9»úY« ¼ ÍóXÓT\#Y–i¹ª(Šœs÷}õD8òÙ8™žŸ“鱌!-HÕï÷�1µZ­Š;jÜz4¹*Ïó8Ž�œøÖt†�mý�õ%æq�hüñ×h¼ÀVGOÑë[–!I’ ¥±%l¶wÿí÷íý×(”%‚Æ@BÔ/Ê¢ lÞ _" /`LL9¿rÿÝ»¿;sþ%£&Ÿ5Šîº«KätÏ7âþÍšrU•�ò>M«ö|£ìü’ç¹[5ú󪓮(�¢Hg`;�N«ÕÒùV ZÀj½ǸX“�Tý„o]:Y–i¢ÍÞ¨B‰úOý`mŠ3ZŽic'|¬9‚<ì÷ÈÝm¢S ãDã¬Á œ₇À#˜Á¾C÷\¾gbS²”g&B’8Ø$Ï|Q†(¶õ†Û÷`15�4Æ [æ�‰f)‡n»ãúËŸöï×ûQÑ p´iÓ ´ÐìÈy^=ÒIithµr½wêx÷|to9BŸ £¨Ê²PMªjo€*¤á½!´Z-EQhÛ‰jB–ëÇ�4úîÝ(ãî�…�Æ'Áhá¸(ŠªaeŒ�&jTÒ{_½( r<¬�>G_ÖÑš¯2ÑØâÉÑ8k `ô6­5»Ý^’Ö \‚Ý÷Ý11™ô²,²IQ™#˜ ŽŒôe½Ž•%Ô“ƵÂç^:Îåý|nyåÐtrz’$yž{ïã86ÆèeÒz?r""zŽ6Ó±g@x ¢“ކλÚX{»Ñ�Æ*ÖÄ-´ÉD•ó±&�ƒAއ5z|Ùèïä�¾ÿ'¥Ñ,F¡ÖF?Ç{Ø"x|¡‰ÆχˆÆ‡6ä¨B€à\¬­¼—2Ëòr�£ã- )$�ÉaŒ‡ñú—ÆXgƒ[–^$¸XŒ)Ŭ„Pxïu-ØšÖµDDDDDDDDDDÑÆ®�dŒ�Ñ ‡ñX-d%ÁHp—¥µÎ{.ÛF82X¯�kàlˆc HéscÅE€…H¦Ô8GU }MoL"""""""""¢�…q¢1#Fƒå0¥Ãˆ÷⃵6v65H[Íc“(²0Þ 7È-ÄFSA Hâ`lc`¡„1q§š:ªiG6Æ$"""""""""ÚXç #FìjnE°‹ÒÂ!ã bHl�ÌLou¶–g¦Û…-aD7ñ0°±�Bn¥4­úiµ´E‘6-Ô€GUÀŠˆˆˆˆˆˆˆˆˆh#bœƒhlˆöç0`(� ¹ƹHLToÞ|z·³ Öˆ1–ºØAZü pR÷E³fvœyÚ3S×:2Ÿƒq"""""""""Ú¸ç ;V`eµñkmE\Vˆ‹;N?gvf[’T•ªq5„Bbƒ1"¡…lz¢vÞùç|B-„°&‡ƒý9ˆˆˆˆˆˆˆˆˆhãŠÖ{ˆh• �#0Vl€µ`##eâ­Öù[ÛÏ\^ÚßÍï4΋b‚nc�€àa¥feEÒHÎ8cÛù‚ Þ°Öjbç¡Ïâ0, �0è,ôVzÆ.Ž‚¤ÓõÍÓ[ÎÚ6ó´§l»xóÔS­Ÿè÷B1ÎqTF´’—}hŪ€a`ES7†Q Œ×ÛY„``¡*W%Uz {½=1ç Ú´—†ˆˆˆ÷Þ{ïœsHjñéO;óÅgžöœCK>8wï¡Å½. ív»³’�¾ýœ§l¿ ‘n•bÂwëe™º`L˜r½Íø2r8Èa©ªT,’¢‚͚í0¦ÕÆL•"ÚÙ#<Š� """"""""¢Gƒq¢ ÀZB!Œfu„¦œkOƧOn;wÇæKzùJé3êõ–5©ñÍЋQ6"iSƒ ÀÊz?”qf�X->ÀJ& ûÀ¿Îó ˆ1bˆ°b4÷ín³¬¢#Lê """""""":áç ÚŒ1Þ{ι(ŠV«W™"CFPglÒ®¹–D@jëEŠ�ŸÄ&µ.±1–iÇ&ŒF%4ÈQZsJƒ~ß0Ö ‚�˜&, B€æÝ ›wð€]-`õ�H �ŒsmÆcŒˆÐ €(Šbga LYY‘çbMÇQdç–“¤VK›®‡"”e'c-`ýz?”qd˜x€¼TùÁXÀãFûs„Õþp¢›0Xí^ Œ60׸�pŒsmÖZk­öç(Š¢,K-`U–¹ˆxç\³Þ²E–õ:ÙTkª Áç™D¥s.2&xB0òG'AL0Ã~ãA0a˜�1ìO®q +°‚b-GB0¬gu¸ëøj,°bÃê ˆˆˆˆˆˆˆˆˆèDa¢ À{oŒÑnäÖÚ$I¢(ò¾0Ö[ç#_ƒ|00"iœˆ÷>²É}Ù ²Û³.còc !òQ#2‰é—YQdq'q£ ÖÙÄIi‹Ü”…•9›$qC¼E°IlˆŒ1išÊ°JUÅ®þGIQU½8h\ï�zxòPë½;D´VÃBY–úOý†ˆÆ‡ŽÓ²,ó<ý ��#£zºNDãCG¥÷¾( ý �§O&�? ":•QÅ©ópq7ц&0Aó ¬`X. €­Ê%YY-ıö1çÐí®A£ÑpÁôº™ Ò¨Mö{ƒØÖëQ=Jb/¦ðå Ÿ—e–&5˜Òk#ç$vÞû^¯ãœƒÕ¾ã€+æT9®œ44¸¨%ã´vœÆÇ�îÞzï½Ø°Öž:D…Lµžþ„KˆÆ�ŽS=E_ï}!¢‡§ÃÓ9W�SOŸLÕ¬Eõü;çâ8>E¢ÂŒsm`£%•Ķª’Ä”€FA‚6Á~D!ˆ¡´ˆ�8‹8 Îù4*3I«,PtÐ/!€�£vE�F^xk}áˬÈ%¶qê‚ e1pQ ÀÚ¨’X0Ô±¡DQä½×bqQ骱1„ Œ»º:C—l`µjžç£D´¾¼÷eYFQT­kãÅѸÉó\ h®UY–:)ÀüH¢ñ¡ýót�ê±õ”ª;O´!è8Õ«Q§yž�áuôÉJŸê‚NTÝFO‘çŸq¢�JŒv~zí`-üšt� °â°&VÈ8ºÄ¦¾ã#ƒ¦­÷{xàŽÞþ{W²%‰ÃTŒÄÚÈ�/}Y„^™»Þ÷²——'w”›§6£ž¤¹„¼˜¨°¦ `a†Ÿ± ÌxÕ;¢c+ËR#úUפŒa�=e©– Ž®E]ï]#¢¡jœê„iU‡ó§DãCÇé‘«x<%+Uô±:'ç %+ÕIoµXPÈ¡ú䨦F¯;FÛ��Üç Ú¸LXí¡Œ‘|ýÆ0‘àx±q€ˆ³¥ëtÂÁ{ûï^è05L5ã†) Þ&r6‰laÓhy%Ûß¡°er›‰"WˆøP'ÃV`V[Ä–u«6�5KªéÈq‹sh`c´ÛX5…ºÞ»FDC:0GÃ�§DchÍq_‡-Ç)Ñø�*­Ž­Zr½w�ˆ«fØ+¬ù¤Y³¬J§5N� ãD'c‚EÕo<XÑ�26!?ÁûÉæT±”ìÙ½²ç¶E¿”N$Ó5=8ƒØ ‰a,<¬‘ÞM7O?Ðy`î¾åv»ÙœjÙVäL$p‚²zÂe5ÒL`�cc©f$«ºUúUÛ`Œ�Ѥ“ÑŸœ:§2D㯧£“ùDcEôÕ?y0%CGRÅ¡J4VFOz™zõ$óÞc$Ρá¥jrã¤7^“5DtüŒ gGªRTs¸¹˜ê–°&ŒÞ’† Þú»¼ˆ{ïX¶ýMÓõzÙC°I!A`€DÒ�âr«Í{Þ³XŸŒ·��c㤖‡>†•ÄV‹Š™’Ïþ†£kôûj ¶6'_ï][»ŸºcZ5Žã<Ï«vD4ª…TÕ7ÖZï=Ç)Ñø-†S-ç %7£‹”uæŽÇS¢q3zÍ<æ'Ùh<ãa ržÜ¸ˆŒh3bͰ÷øð?�ýï¡·ä4û#3FŠÂw—½u[ÔCŽP�`3ï2q™·¥¶EP"‘&ò¤Ì¢åƒ=)!Þ:8#`!6h@Ä„`<Ä0ŸƒˆˆˆˆˆˆˆˆècœƒˆhÈÚ¸”‹—¤_@ÇÀÖKïú›Qݸr?FªTÙabs;ˆˆˆˆˆˆˆˆˆžœw#"1I�õ騽¹¢A'Ÿ÷.K›‘X+Ã|ŽÕ8G0¾9�öÂR&+qS¶ì˜IZÖÆÁ£‚Læ�È0›ÃÈcÜ7""""""""":Æ9ˆˆ@L.ϤS›2[Ïœj̺¾_ZɊЃfrTÉÖZkÑ-zåBÒ [Ïœ™ÝåÒë�´ã?²mæs=Q8ïFD¤Ba½°ìêØ²#Úºc¶9�•�Þr0… 3Læp€…3QXêLÚØrÆôYçn²5 Š•n¶’Öc±A VKWÙ*„ˆˆˆˆˆˆˆˆˆN¸h½w€ˆh,#ÆI^ j.¯5’-Û‘†Ó÷®,èzï^$‚Àk-œÝ|Úìôé�-§5“èe¹Km‰r؇ÜâV·m¡¡ŽÃÁ""""""""":1ç " Ä.ïË<ËBR›Âém´§ÛþîbîÁq}q œ5ë£8óqoç%g7· ú‚Î`erK3ô‹^¯—$ ó?¢``™ ?0il¼ç�>³miª×t—zýþJäÐnÕf§§j›}ZlÂÀú¸uzkl=N ¦€X±%‚ã$$X¾Šˆˆˆˆˆˆˆˆè„cœƒˆHY#€X+Á»LL\dŶ¾ÝÕ|<šFêÖˆs&Ž\Þ+zb±š»at#!‚ €ÀĈóìÒADDDDDDDDôD`œƒˆhH˜1‚Ä6/ú‘AGÎBD|Yæ_Hak‰@³40»ú¡š@ª>°Vã """"""""zB0ÎADt˜¬¶ ÍÉ0@”)á ï� ÁÀ®ö`£ßDFìá~ãÆBØœƒˆˆˆˆˆˆˆˆè‰Â8Ñ�£ÃK0¢?OÒ4”Þ{/ApÎ9yçiØá&à,œF?˜pxó,\EDDDDDDDDtÂ1ÎAD¬9±UNF¯—¬1°âáC†·‡¦€ˆ,àXhƒ€sxƒDDDDDDDDDt¢0ÎADt˜à!IøpÖFÖDÆ8+bÊ�·RðĈŰ-9 6X á0(XÀŠˆˆˆˆˆˆˆˆècœƒˆh k%ÀX3,4e�X)ED¼ +0"ã¬oM€fm�&‚íÛLp@ øjãëý興ˆˆˆˆˆˆˆN*Œs YkKïXÙ`CYŠ.²±Àˆˆ�81€±¡Ì:͉ºGÙé/ÙÈ´&&ÜÒb'Žš Œ@J䀔=ɉˆˆˆˆˆˆˆˆN,Æ9ˆˆ†BIÛåý\ʲæÒÔÕ#ã|ÀIæiÀÁÀ j4ú½¥2”µ¨P¬,͸8©!”0`� &£ùvµ79�0Œs€¬x8GHê¨KÝ ºË½……¥•nÏZÛžœžÝ<Õž@mi9él;(L·ô™µ>v(Ä3oƒˆˆˆˆˆˆˆˆèÉÁ8Ñ�36¶ŒñDͺböäX˜Û;o‚ ÄZ:ûöß½d¢pîÓÏÜ´Í6¦êƒB ú­F38éç™1uAXý€µ Xó8wŽˆˆˆˆˆˆˆˆˆãDD«Dà%2I—-áÁ»û{ïY,”ÒkE¦Ç©sÎ)$+Ë¢@~ç�ûûOÝ´ý¬8™¨Eµ:|B.>¸A,DCÉpÛ&¬÷Ã#"""""""": 1ÎADF Þ7âfŒZIöÜ>ÿí‡üJÒr›7O5Ë>² y^”.ŽilS3·xè¾ÛBÙ:ëÂF£9ÙÌ•Ö7[ÍAn;üO�Àˆe1+""""""""¢Žq"¢!ñ¡VO}ìÙ{ÿ÷e+IÃL&h.îEl‘Fh$LT”(–}?íÖ¦••¥¹û:­)·­%µ:,"#°pA"ÀA‚6$˜ÏADDDDDDDDtâqq1‘²‚ÄHš/›Åº~ÞlŽ·lЧ}u¤JA?G–Aj‘›®¥5 fêýÅü¾»÷zp%ví4j//õ»Ó0b ÖÈz?>""""""""¢“ãDD pQ<ÕYÄÊœ,Þ“o·g´{n€÷(,Š$5)J H3µ¤5²¥rï}+ÆÛ~?Jk3'bK˜ &ƒ)r‹’¡""""""""¢Žq""eEbˇò84]Y³¹‹<´}¸wEá²2ʼ Úeñ�äbƒµH³¾Ï3X“o, €‡ñ0¥A9,ZÅVäDDDDDDDDD'ãDDC!Xì;0‡8.aJ@< fõ¦„ñ00py¬DVlo¥—õá B@€ ‡£Rõ$çG.Ñ ÆI7"¢!1ƒCK‹p¶„±ð‚Vc¦„)`!(K�8ˆ e¬Bi!«�ǃn6@“<ˆˆˆˆˆˆˆˆˆè‹Ö{ˆˆÆˆ†:‚ ¥…Xxo�‘ÈŠŒ˜01Hø*WÃ¥†6X�%WÖ­""""""""":Á¸¾˜ˆH/ÀätÛ‹‡óÆÁcø1iŒÄÎ'N¬ ° àQMÔ¨Õ“$µ!xk�A°ŒV¯[Õ­Ã�\""""""""¢Œ“nDDJœ lÝ:YHWl/0€ °Qi]ˆ�O]ˆmpVP¸bB0¡ÕjÔjRZ ÀÈC·mFº|Ñ Ã8'ÞJ1=]è#˜È‹…±0à¢Î["+Q¼À¤ð®(ãFìR„PX Yä """"""""¢' ãDD* L4£é©dÇ3KÝ)ÌZØh¥IDAT}�ü "`¬fuŒÀ®…•<ËÑimª?å¬mˆ�Ô“n¿sx“2òËàÑ€q"¢!‘�H¿9�yÎÖ­O™ô®Û)… ÖÁZ1ÈY(º¾× sÑDØ~æt{³”E/ï¶Z�ÕíY ‹U1ÈADDDDDDDDôĈÖ{ˆˆÆƒ @èö—Öl:­^ fú½}+sóFL5<'Ö(m¡,M/�zµÙ~Öäì.™ÄJ‘R$Ö‰ VF¶<ü>¬÷ƒ$"""""""":Ù0ÎAD4”ÖÓîJ¿,–§µÍg6²ró¾úb¶Ü e�ÒÞ†X±&2HòƤl;{Óö§4lÝr`±Ætû=›Äª„9#Á"bÙŒœˆˆˆˆˆˆˆˆèÄbœƒˆhUE�Z(MÏöÒÉæ–§µÓ©tå`vÿÝ{ÃÀfƒ²ð…1ˆÒ¤Þ¬¹ºÊÎmÓÛêI ?ÈdÅY‹à�……ØÕæ&@€a[""""""""":qç "�]îõÓz-ªEý~Þ+ŠZ­1ñ”¤5›l?«íû ¤( ‰�Ö“Zq&Bî;+eaSX²2ƒD�V3x`­#€ ^ä """"""""z0ÎADb�‰1>wyïm™FõÈE®Ù†uE(‚›ä’š2˜"Ï;^ŠÈ8¸#€Á4¤aaJ@`´3G`¨ƒˆˆˆˆˆˆˆˆèÄbœƒN]F1¡4Ю .˜`` ÞØP¸EéÄEðœ >&#vØ…VVgóƒ VàDŸs X#Öˆ @0ðÁˆÀ þ­«O» p<¡ý-šÍfîË"/œ3iZ3‚<ëåÞÔ]ÍÕ�«;kàJã SŠ/²A§ÝnÅÖv»+ph·' æ[Í)X�AÀÀ¬>!|�`ŒsЩË,ÊÒ„,‚ii�@€ÂÁG>‹‹,.|QÖ3?ð>ØP8a¨ã,{+°™³……À tp@ì!¥ElÎûÈ‚ … ¹ … ÁIi‚ƒÒ”. ñÖ rÊ',ÎaRä1ààà àŒ1±-%/a­  ``êµfY€4n �uKÀN6& €èm`°„q""""""""¢�q:¥¹o!FŒDÞ &xÄ#&¡DOd&ÁÉÁë Ä@Œ1"V @°"VÄl0Æ 4«Ãš€‘, àl�‡ÄÀk ŒÀi´ä‰¤y$GÜI ø‡y¬Æ-ÄñË0z3y¢Ÿz""""""""¢Sãt검щõcàN‚ ƒ8ÀX± #ÖÄ¥í8: r rNŸ7þVŒxk O¾±.ØÈ[ŒX±Ö=ôIÁ¿Þ�ŽˆˆˆˆˆˆˆˆˆÆãtJÓ†o†Açëá­qÁvuŒX'ÖX–:º‹*ëeØ B ÆXˆÑp…‘`‚ÀjÀ°6ˆvó°€kÅÆ�'Yo­¦S„a€d½$�ÎÚÒ©n˜Ò!b$8`.X,$öpÞDÞhJgÙ�7ðZ£É ¬À‰µ7,Û4ŒXx¼…˜`¬b!& ƒ0#08ܼ[·Lx,ûDDDDDDDDDD'5æsЩM, V€`Å XHäMT8  Åë½§ãO Â0iÐ(…ÀðÃöݼÍêÐþ䚥á-¼±ÞÀZX6Àˆ-íj¨Ã<´åç SšX1V F‚ ^‚Àâ—[׋Lˆ¥ÛÄ0ù鑬hÛp1.Xhí)¬6çЬ�*‰ ÁØÒBÿË�È!’aFˆœ {ƒ=,Æ9èÔ ¼1bl0|°°°€ c’�K:(s²Ø5�ñƲÔÛ1h>‡˜ÀŠÕ|`øuØ�`œÀÀÄx +… …šd†é «y6«Ù6|þ‰ˆˆˆˆˆˆˆˆè!8iH§.1Z+Éx oPºPÚPØPZ$�öþååöé;”å> Ø4SÔj™;t<‚Õf5¼ ”Alùê�´×Y¶E‘I|0¾ˆl(Cž‡<$fïâ!4ÓÜ¢´VŒ…X+ÖŠÖ°zH»""""""""""Å|:…‰Xí›-&x H°€|Àì¶Ó·OÖñÜËà®îÓ©A [a‡*deØ«ÃFÎ[ˆ5qì&uÔêiY¤E9ålߢ#�Q‹l­‹CnB k1Ã�èW°"""""""""¢#1ÎA§41¶ ]h‹lq‚¥•^Ýù¨^·­:$À›Ì›^QØÄ­÷.�/Í·&h†FŒõÆ–ð¾ÈQæ¡ô \RzÓë6²Ü8h“8VV099ãá|0ÖÂ�lœÙgDDDDDDDDDôpç S�k m—ŒM’Z²˜õ¬ €€¨—ÆI­ Åzïï8 ÃP4Èa� €Hd}ðP”rgCˆ‹â¬Ö”x&jÕ¢©ÒÛnÏåyp%Ę`´¥‡ šé """"""""¢#0ÎA§4#ƉµA @ÐÆ±�ái€‰½ '>X8é˜a„cøM0Úìݚؘ`’š±ÆûZœli´¯<ÿ‚ËÓvîLl‹óg§6ÁÄÁ»šˆˆˆˆˆˆˆˆˆˆˆ6*Æ9ˆˆˆˆˆˆˆˆˆˆˆh£bœƒˆˆˆˆˆˆˆˆˆˆˆ6*Æ9ˆˆˆˆˆˆˆˆˆˆˆh£bœƒˆˆˆˆˆˆˆˆˆˆˆ6*Æ9ˆˆˆˆˆˆˆˆˆˆˆh£bœƒˆˆˆˆˆˆˆˆˆˆˆ6*Æ9ˆˆˆˆˆˆˆˆˆˆˆh£bœƒˆˆˆˆˆˆˆˆˆˆˆ6*Æ9ˆˆˆˆˆˆˆˆˆˆˆh£bœƒˆˆˆˆˆˆˆˆˆˆˆ6*Æ9ˆˆˆˆˆˆˆˆˆˆˆh£bœƒˆˆˆˆˆˆˆˆˆˆˆ6*Æ9ˆˆˆˆˆˆˆˆˆˆˆh£:ã!„‚~¿²² Ë2ï}žç¼÷ƒ9Æv²,ÓoôOÖÜ…Þ@Dz½^u_EQ¬ùÛÑÛ‡¼÷eY†ʲ¬v#ÏóN§SÝL÷sô¯Ž½ŸDDDDDDDDDDD'«S1Îa­µÖÎÏÏçyÞn·ï»ï¾4M�sEQ”eiŒ !8çÖ„"Žäœ«¾ !h #Ïón·k­Í²,MSï}£ÑÐëõÚívÇÝn@š¦‡ÂjlC#"ÖZcLEÖÚ(Šôf’$iµZ! ™ˆˆF8¬µúÕ³ÞO*Ñ:ˆÖ{ÖA§Ó ›6mêt:ûØÇnºé¦ûï¿ÿþûï¿êª«Î=÷ÜË.»lçÎ�¨8Fü@D¢(òÞk´CD¼÷Q%I’$ɽ÷ÞûÕ¯~õk_ûÚÒÒR!Š¢«®ºêŠ+®¸à‚ šÍæ¡C‡�Æìì,kíòòòÄÄD¯×+ŠbrrrÏž=_þò—ÿßÿû‡𙙉ãøÒK/}Å+^1;;Ûjµ8çòòw÷w½^ojjjeeerrò¾ûî;ýôÓ—––^ùÊW¾õ­oլޣý¹F8Š¢°Öj>‡1Æ#"ûØÇ>ö±�%IrèСZ­Öív7oÞœeÙæÍ›Ï?ÿüŸýÙŸm6›EQhnG³ÙP–¥sÎóñ�üoÿöo“$°wïÞ™™é÷û­VëŠ+®xûÛß®¡—<Ï�sz¿�9Ú1??_–e’$eYŠˆsÎ{ÏÔeŒqÎMMMé…1faaAÓžÖ{׈hHD�F³Ù¬BïsssιSöøN4†Ddrr2ŽcÆ-IÊó.¢q355E‘ˆcƒA·ÛåÁ”hÜLOO뉮ˆ ƒ^¯§ó0ë½_D4EQ»Ý®…w:�~¿EQÕA€€–5*Ë2MÓ<Ï­µ›6mÒs°Ç³ÙS.!@{i|ô£ýÈG>rß}÷Õj5-å½o·ÛËËËEQüÓ?ýÓoÿöo;ç´=ÆÃZ3>µxT¿ßÏ{ÞóÙÏ~¶(ŠÝ»w·Ûm;vìèv»ý~ÿÖ[oýô§?ý�|@ÇY–i¤À�Œ1ŸûÜçÞóž÷¬¬¬ìÙ³§(Š-[¶hI+ç\·Û½ñÆÿçÿüŸ ’$Ñ� }8<¨ѩ锫[UÅ-·ÜòÞ÷¾wÛ¶mI’<ïyÏ{ùË_¾sçÎ^¯×ívßóž÷ÜrË-Þû¯}ík×]wÝ•W^y´íh|I£OÕoºé¦Ï|æ3û÷ïß²eË�üÈ�üðÿð\à–[nùüç?íµ×c¾øÅ/ÎÎξöµ¯‘Z­–eYaûöí_ûÚ×þàþ (Ч?ýé[¶lyõ«_}ñŸí¶Û¾ô¥/}å+_Ù½{÷ÜÜÜå—_þ⿸ºÓªù1ROˆˆˆˆˆˆˆˆˆˆˆNV§\>G­V{ÿûߟ¦éîÝ»Ï9çœw¼ãg�u–ý˜˜˜ø¯ÿõ¿^rÉ%Ú?ã—ù—�‘,£q-W¥Á†C‡}úÓŸŽ¢¨Õj=ãÏøÏÿù??íiOëv»KKK\pÁOýÔO½øÅ/Îó|~~þ³Ÿý¬÷¾V«åyž¦©µVDÞÿþ÷ONN6›Myç;ßyñů¬¬xúÓŸþ“?ù“/zÑ‹œs[·nýÌg>³gÏž5Ù$Lþ""""""""""¢SÓ)ç¸ñÆï¾ûîz½Þn·ßö¶·¨Š#çyàg~ægêõºµöÜsÏýøÇ?~´íèŸh€A¿?tèЮ]»á"²¸¸øàƒêâôK.¹DUÅ9ª[>ûÙÏÖ ÁÁƒ8°æ¨Y]šjxCíÂÂÂ�Š¢ˆãø™Ï|fu�X}µª-ë?8077§?\\\ܽ{wÇyž?ïyÏÓ:Z£«ôMõ!¬¬¬ìß¿ß{ÿ°w1 DDß.X½–>’s.MSÍPqΕe9 ø¹Ckè¼ÌèCDxI4VtœŽþ„ã”hܬ§£åO‰hL¬É†g<’h ­§ºô“ã”hüñ¼—Ö¨âÕÌö Ùl´Þ�ë ¤Ç¼Ñl©ùùy­%U–¥¶÷ÞGQT%@hl`ff&Š"}Æ÷íÛ·cÇŽjýVŸú5“¿sssËËËι^¯wÖYgeYV«ÕÖd:‹ÈÄÄ„ÞQÇóóóyž'I²´´ I’………M›6åyDZQxïµÉöíÛõÞƒÁ�Î>ûìÑ«!¬Æ]ªû=Ú!?˲f³¹´´”e™s®Ñh ƒ,˪û%Âêû'„P]éiˆ•¥«ˆÆÇÃŽS–˜#CÕ8Õå,§Dc¨§xèŠT"kÎ{1²Z|½w�ˆ«*ÐTs§§´F5µXeü¹Òú18i'µ« ÈX]ÙªY(Ërrr² 'VObU»Içý“$9xðàš¼ŠÑ˜V´‹‹‹"’$I¯×›™™é÷û8"Ð „Ðh4ºÝîÄÄÄÁƒõ%!­VK³:´á‘ªr�«ÆqÌK>¢±rä8MÓtô'D´îŒ1Õ9žÎÎ$IÂÅ%DãFG¥®3³Öêñ”KP‰Æ‡O±:NµL…. ]ï]#¢¡Ñ)J-õ¯ç½¼>¥QI’TߟÀÕ'ùõÕhF…µ¶Óéäy®ÃlM+M­¨~899yðàAÑ,�j G»£n·›¦©1¦V«éµ+-3¥QÑ0Æôôô¾}û²,›ŸŸ×›-..†z½ÞÄĄ.ʲ¬Žâúq0==Ýét¬µGÁjÔKDFÛ�¬¬¬|á _øÂ¾°¼¼¬*Gzá _øüç?ff@¯×sεZ-œ¸D!:9¬y?DQ4šÕDDcbtHê.IŽS¢ñ1:õìŽ{D㦪x¬Pqëhåü)ÑX­ýX54å8%Õ<¤ŽV�,Õ£êzï�‘*㧪[Å8DZTÕ¥0Rcªßïkä£ÑhT©ŽU"E•Í Yšß�eÙšmbuí@µ‚ ,Ë<ÏkµZ¯×ÓÞæ£ ô¬µ£%#ëõzš¦½^¯( ý•Ö#³ÖjŒ@Y–qkSôê¯ô«vïȲl´~Yµ‘$IÒ4MÓTD´÷ÆÑò3xà�êáhŒ„IdtÑLL½÷,ËtƒzÍGÑ;Õýét:ÓÓÓÞûc„Lã8^\\œžžÖÈJõp85F£ô§*xZ•Sãz¢ñ1ZgCÚ_ŠKfˆÆ‡¦êb¤uª®_áñ”h|”e©ÉúÕê±Ñ^ÇD4²,«×ëkʸsƒh¬èÂn¥ÿ,ËR—’¯÷®Ñí0ª½¨µ”Ñãt2Ç9ª!¤Ï�1FÛn/..NLLEÑl6Ôëõ,Ë4©€÷~rr²ßïƒB½^×L«*ßJ·Y W­=U¯×ó<�ãxnnN�¸ÍfSkLéfhm«ÅÅEm0ÞjµôWQÍÌÌ,,,$I¢!Õöu®Jc-I’ÌÍÍé6h€DÛŠèY¸VЊ¢¨ÕjýüÏÿü«_ýêíÛ·­?ÇÁƒ[­Öƒ>("ÓÓÓ½^«¡õ~ÝhŒhËñv»­qø(Šz½NDcÅ“$I½^×iSkm·Û-ºHDë.„011Q­†)ŠBë‹ò�J4>ªy™²,­µ:N­µ\-N4>´î…ŽSm³: ¸h€h¬h$RçQ ƒÁ`À~W´FÕ¢V«åy®SëÕâ°ÇìdžÔ>2αyóf WdY–çyÕå[ÃZèt:“““ÝnWOpggg±šY­îY£º™n5Á«”U‡ ½¯^¯§[ÓNÚí¶1&„EQ§ÓÑM)}É­µº‡Ýn×㜛œœÔ½­âºqÍA©×ë­VKs>ަÝnw»ÝÁ`099é½_^^Ž¢(I�&#RÕ©Êžjî!O%‰Æ‡°Ú�@�æDcEK¡j÷5½ðÓª§ë½_Dt˜æ1ëÙ¯1F‹úrR†h¬è1«×§"’ç¹Î¥¬÷®Ñ�áíÒ‘ç¹N±®÷®Ññ«tq‰¾=ÿ›äd>T§ªšra­Ý¼y³÷~vvvqqñСCSSS4±CÿD+Gi5§8Ž·oß>Ú’n´V#(QÍÎÎ6 �^Ü{ï½\p�ffT}ŵ©øÒÒ’µ6Žã,˶oß^…ˆœyæ™ý~zzzqqq~~~vvV_é*ÅDC,‡ÒòA"²cǽkýøÐŸ8Ž�1þÒÉòòòôôôÃ>9ý~¿ÛíNMM5�••ÍÑ]]ï×�ÆK•?¤ÿÔ3KŸˆÆGU·J¯÷°Ú΋ñH¢ñQU:ÕêÁ”ã”hÜŒ64®®«Ã+­»ê`Z]¥V³=ë½kD4¤ågFÿÉy$:’Îxk„cM ûñ8™ãzÀÓkHMCž˜˜˜˜˜EÑ7¿ùÍW¿úÕªô M™©Õj_ûÚׄ’$Ù¶mFVË®–Õ P¯×·lÙ²{÷îZ­và 7hœ#MSíÉ@Ó,n¾ùf�‘4›Í³Ï>[× %I255Õëõ¬µ7Þxãyç�§»¤9úý~£Ñ¸ñÆEDËm�vÚiz-u•¦©vûÐâœÓ…H333G{r�F§Ó)˲ÓédYÖl6ã8Ö|‘õ~Ýh¼hZ’®9ÕÎ4lqL4Vt�8Fg¬'N4nªÞãU¡Qï=‡*ѸÑQ©g¿eYê˜å8%Zè?Š"­1 §:ó³Þ»FDCZÄ9WÍ&qœÒ‘ôý çZUºO5þ˜�ÌqŽ*Q�­cžùÌg~ýë_�ãøÚk¯ý±û1ÚÄ»ê´ àßø†fÍ<å)O©ªK�=ÙÕH†1æüóÏÿÞ÷¾7 ¾ûÝïЀ V[—ëëtà 7xïó+Ïs-�¥‡y½x‘ÑÚYûäE¡µªtŽlee…Ÿ;´FSÍaªÊ,Ñ88rI8Ç)Ѹ©Ž§xhOŽS¢ñ±f�êÁ”×GDc¥º8­¦aÙG‡hÜhÅ~ý^3ëYÏ:ãŒ3î¹ççÜ®]»Î9çœ~¿?55U½À×_ý<`Œ™™™¹ôÒK±Ú™C£, ¨ ƒ(Š¢(Ò5Gû‰¢¨Ñhxïçææ¢(ÒnälµGk™ªB¨"D44Ó#kôŸ<�$ºRiôè©ÇSΟ��ªfõž÷�]!^-èÑÒkްD´¾ªqZý“õZéHUâìh™ÇÞåÞùÎw®÷C{BŒ­ÒoªU®QÝyç�»wï^YYÉó|Ó¦MívÛÓét>õ©OýíßþíÁƒ§¦¦~äG~ä²Ë.˲L Li á7~ã7>úÑ�~îsŸû‡ø‡ýÑÕßjËñ$I¦§§o¸á†N§³ÿþÂgœQ¯×5ò±�}쓟üäý÷ß¿eË–×¼æ5çŸ~š¦Õ°_ZZÚ²eË]wÝuàÀ�¹¹¹ÅÅÅg=ëYºô/„ð�ÿø�úЇ<¸iÓ¦Ÿù™ŸÙ¶m›ö -Å^=Þªùù#.æ eY6 cŒnŠë•h }Û×jµ*µh0Œ±ˆh$I’$IuîØívy±G4nÒ4­ÎÐ4•'"5›ˆNk­^»é¹nY–ZQa½÷‹ˆ‘Z­¦ãTDʲÔ6ë½_Dt˜žÑó^Éó\‹ös]5­QXÒå_:Aý8O½NÚ|Žc¸üòËççç?ñ‰OÜyç�KKK»víj4µZíþûï_^^žŸŸo6›/}éKø‡¸êr�Õ Q�ahK¬öÞHÓT3'žÿüçß|óÍÿò/ÿrË-·¼ï}ïûêW¿Ún·ûýþ`0˜ŸŸ¿ï¾û&''_ð‚|ß÷}ŸvïÐ�fÇ“““—\r‰Æ9î¸ãŽÁ`ð�ï|'I’¢(<¸°°�$ÉÎ�;gffžùÌgNMM�îÑ)ëTŒsÌÎξä%/)ËòË_þòþýûï¹çÍvÔN§�vÚ‹^ô¢—½ìeŠÐX‚Æ{½Þ`0èt:iš...˜˜˜¨cäyBxÝë^·yóæ$Iî¿ÿþ½{÷.,,EÑï÷{½Þ\pÕUW½ô¥/ݲe V“0œs,iµZ¯|å+£(úêW¿º{÷î{î¹ÇZÛl6­µ¹âŠ+Þô¦7�ö�¯RU˜üEDDDDDDDDDD§¦S.α¼¼Üjµ6oÞüÆ7¾ñòË/ÿêW¿ú�ï|çàÁƒY–�{î¹g�uÖ¥—^úÜç>@·Û­Õjÿ¨×ëÒ4ݶmÛž={ºÝîi§�Öív�†6î®ú�§iúŠW¼â™Ï|æ®]»víÚõàƒ6›ÍÓO?ý™Ï|楗^zñÅW-=ªœhMé÷ûÓÓÓ¯}ík/»ì²o|ã»víêt:ÝnwjjêÇüǯºêª³Ï>[ÿDÓyªŽ[UA¡õ~j‰ˆˆˆˆˆˆˆˆˆˆžlæ¬�B(ËRãz½^£ÑÐoŒ1ÛPyž{ïëõúââb£ÑH’¤Óéh“ ým¯×«ÕjqkiH-Y«ÕôZ*]ÿ™ç9V»ˆW=쬬´Z­ªi¹µVŒ�~$Mõˆ¢è1Ä9æççõyÐöãUA´õ~}hŒhDmjjª §-,,”eÉ÷ Ñø‘F£Ñl6«ž]sssιSðøN4¶DdrrR—¶cò<ït:<ï"7SSSZ@\›Òu»]L‰ÆÍôô´žèŠÈ`0ÐÙU¢ñEQ»ÝÖ+Sét:ý~?Š"]óM¤´DY–išæyn­Ý´iÓãï|Êåsh*íת“û!„••k­9¤iª2˲B½^O’DœÚ£,ËV«Õï÷h·ºªgÆÂÂÂää¤F/Š¢°Ö:çšÍ&ï½f‡è-CµZ-„ 3Sív« ?4Ä¢¯®~ßív˲l6›£u«B�9ÈADDDDDDDDDDt8åâÀP…þÓZ;99YÝ`aaazzÀ`0¨2DDƒKºOƒ qk0CC !„ƒjï ý§µÖ£á m"_¥eôz=ç\š¦ÖÚ¢(Š¢Ðûª¢X½^O„ôû}cL)©–Òë6«6éDDDDDDDDDDD§ S.Ρµ4ÆÀ{Ÿç¹F,[­–94ð ± í4^…(4#DÿVfhŠF¿ßß²e‹n\Ã'ÿДŽj4P¡¹#U- W,--iMcÌÄÄ„fœh>‡Ö§�jhE¿×,�õ~j‰ˆˆˆˆˆˆˆˆˆˆžlv½w`$IRœsõz]ãZ�U®môDZ~£ªÛh6FU‡JS.F7nŒ9²¢TEÕ Fÿ€¦•T2 qέIÝÝòcrE¡»šç¹æ…cF&Ñ7v·ÛÕ¡¦(­÷~Ñaúy®•h=C?%+qk&®1F©EQ°î(ÑXÑÖ‰´ya!˲*¿ŸˆÆ�ÆÐo¬µY–•eÉ*DcE‹k©�GÒZ8ë½_4^´ú‘µVûXGQtBš³_Ó)ª×ëE‘ç¹6~Ñì΋ÑÆí£±´^¯W¯×çççùV!UÀ^¯ñtœîß¿4•�ˆÖWš¦EQLOOWkJò33ó®w½K«#ј(Šâ£ýèç>÷9]Úv饗þüÏÿ¼vb#¢1±¼¼üÞ÷¾÷Æoìõziš¾ä%/yýë_Ï|¢±Òét~é—~©^¯w»Ý,Ë^÷º×ýè�þhžç�jŒˆN”ï~÷»ï~÷»—––LLLüûÿïŸûÜçb¤:VÛN!T-¨ÿ¤4ßd§´5o 9h�¿ýÛ¿ ƒ¢(öíÛ·Þ{DDkyï÷ìÙó�ï|geeebbbÿþý r�›<Ïï¾ûîoûÛZõtÓ¦M­Vk½wŠˆ"Š¢›nºéÖ[ouΉÈÅ_Ì ѸiµZßýîw­µ+++yž¿ìe/À ÑXi6›ÿò/ÿ’eYajjê ox#t¤Ñž'ð·Ú)ªj±Põ3gÝ*:’sÎÓét´dÞòò²Æa‹¢ñ¡—vý~?„�çy·ÛP[.��f³)"EQDQ4 t„òxJ4>�Æ`0Ð…½^oyy€ÖRXï]#¢!cL¿ßo·ÛÍf³Ýn§iº²²’$ gQ‰Æ‡žînÙ²%˲ååå••yž³®2�2«ˆHuºõ8ç1x08EùùbŒá‡­B0ÆÔjµF£Q¯×ót½C¯×ë÷ûÚ¼ @³Ùä8%šYÅÜÜ\u™§GÕõÞ5"Š¢hbbbïÞ½ŒãxeeE/¶9N‰Æ‡µ6I’¢(Ò4-Šbee¥( ï=ó9ˆÆ‡–ÐöãÓÓÓq‹Èòòr»Ý^ï]£1²&D­3ÒìÏA�ÑèûI×ì3ÎAGòÞ‹H’$ú5Žã¢(ð¸óȈèÄJ’¤V«Yk½÷zÉë=¢qcŒÑêU�F#MÓÁ` “5ë½_D4¤íètù×ÔÔT«ÕâõѸ ! ƒ‚fuXkkµZ�×§Dã£( mDWE¿ß_ZZ2ÆLNN®÷~ÑØ©ÊU�V¯zœ)z<¬µU—¢Qι<Ïõ=¡LÓt½wŠˆÖÒ˼^¯ÇqY–Æ9ˆÆM»ÝÖüýÁ`ÐívkµƒDc¥V«cÒ4uÎu:]Ü£gÂD4&¼÷­VK³$«´H9ˆÆŠµ6„ H]/ËNWô°Œ1ÕŒ´~ÿøëòx@DG¥+ÚBÎ9-W5ÚˆˆÆ„µVDÒ45Æh™Ë,ËÖ{§ˆè°n·»²²bŒ™˜˜hµZZ_®ßï¯÷~Ña"¢‘H=Ö¬ûO4V¬µÝnW§Ã´6Îzï­¥eåt*©×ëéQu½wŠN<*ÑQé¢6­y*"eY:çxˆ"7ÚGÇS–¥®kcsc¢±Òl65Ý*˲N§£ã´êrLDã@gNuÝ@ÇçЬ"ι,Ëêõz­VEQ¡,ËõÞ/":LÃ�õz]ÏuõÊ”ù‘ôä`] ":*íWŸ$‰†7ʲäÅѸ !èP­×ëU9Kæ]�Ѽl­*ÎbâDc¨^¯E¡s¦º²GçR‰h|è‘TKA:çôغÞ;ED‡é2Yï½6Ö8ëµÒ“ƒÇ":* oXkçççµà‹á�¡$IŒ1 KKKzíÇ:DcEKTct Õ9×ív×{§ˆè!ºÝnURDB,.G4n¼÷õz]»‘;ç˜ÌA4†VVVZ­VQY–U'½\‡GOæsѱ<å)Oyå+_¹´´T¯×�s³³³ë½GDôÖÚ‹.ºè5¯yM–eÖÚF£ÁEmDã¦^¯_yå•ívÛ{_ÅùçŸÏEmDcèE/zÑSŸúTç\E;wîôÞ—e©¬ˆh„~ø‡¸Ñh ƒZ­vÁcúý>KA��ÙÙÙ×½îuyž[kã8>ýôÓ ŽSz†Ôˆèhƒ�æêÚð,ËÒ4íõz�Fc½w�ˆ†úý~EQi… ½êët:­Vk½w�ˆÓ&:zTÕ™S­ë½_Dt˜f\¥i꽯¬D4V<8333 Ò4e3ÑxÊó<˲Z­fŒárz21ÎAD�LçLµ˜¸ˆðª�h|TCRc�EQ° 9ѸñÞWs1!íÕ�ÕD4Ö@CEQ¤iºÞûED‡UKòõDÇí¤§D'™ñ§DÄqJ4þÆœêš9ýþ/<‰NJã?N‰N Æ9ˆ6€Á` ‡¥ªjðñZôL®Z´‚ÕòýÕ z½€²,'&&v ý~ßZ›$IžçÕè1ªÿ?lëŽcôóðÞëãª~¢çÜè))цp²ŽS¢“ÉF§D§2ŽS¢ñ·AÇ©Nñ¤—Ntœ=Œsmö±�]sÍ5Y–Õjµ¢(Ò4=Z¾áÖ­[Ï;ï¼Ë.»ì‚ .زeËè�íW~åWn½õÖÁ`pÎ9çüÎïüÎäää1îTCîËËËüoÿí¿ÍÏÏ7�û±{ýë_´? wß}÷�wÞÙn·/¹ä’™™™Gì7U5èõzwß}÷=÷Üsúé§ŸsÎ9ÓÓÓ)ã8 jµÚz¿DÇr�S¢“ÆF§D§2ŽS¢ñ·!Æéh•ªåååÅÅÅ8Ž'''G› �Ä6Ä8%:�8©A´1´Ûí<ϳ,K’$I-­¨¿Òó¶ÑlÜ}ûöÍÍÍíÚµ«Ñh¼õ­o½êª«´ßT–e¯zÕ«¾ó�ïc8pÇw\|ñÅUc¨#i€abbâŸøDY–qEñò—¿<˲8Ž«Ã^Y–í/Š¢V«½ûÝï¾ï¾û.ºè¢ø�¨¢Þ{k­1¦:׬Zncôf�Fãÿð;�ÎÓžö´ßø�ß "qkƒ4þ6ô8Ͳ,MSýªR…f~xïï¿ÿþú§ºû,{à�&&&Î8ãŒ3Ï<ó oxÃÄÄD¯×3ÆÔëõN§ÓjµÖûu :–±§yžƒv»mŒÑpþM7Ýtýõ×ßpà ÖÚÝ»woÛ¶mË–-O}êSÿÝ¿ûwSSSƒ�ˆh)-G�eY¿ßŸššºýöÛ¯¿þú»îºëÆol4Û·oß¹sç _øÂ�;wVµöïß¿uëÖõ~ˆÁX�S¬NÙhIÕ………o}ë[×^{íþýû{½^ÇÍfsÇŽ/~ñ‹¯¸â ½åââ¢Xï}–e�F#„°¼¼ÌqJ'“q§ºJ}ôšQÏ~çççggg¼÷½ïýÌg>sæ™gþâ/þⳞõ,)ŠB�޾¢(ºÝ.Ç)�LÆjœêðÑ3ÞW¿úÕ+++ív{0­Ž–ˆ¼ýío¿âŠ+šÍfõCž÷Ò±1ÎA´èRë4MÛív¿ßïv»ív»( ³JDôÒ«j³fŒYXXhµZð�çùK_úRišžsÎ9›6mšŸŸ »víºì²ËôÐuìøÖ·¾5 B—^ziš¦zHÓSCUb’$·ÝvÛÞ½{5¤À9§Í¬Fï%„àœóÞÇq¬û¬¼ï¾û–––ªŒH¢�e£�S½½ÆED$ÏsýIžç¿õ[¿õ/ÿò/›7oîv»½^oóæÍyžï{ß{à�>ð�üÂ/üÂßøF½^�Asã6NõšS›4îÛ·ïãÿøç>÷¹ÉÉÉ(м÷�FãŽ;îX\\¼ýöÛ?úÑ�¾þõ¯Õ«^5==]–¥¦BêU_’$iš~øÃþøÇ?>99¹{÷î�;wÞ~ûíý~ÿÀ�Ÿþô§_ùÊW¾éMoZ^^n4[·nÕ»[ï—‚è¨Æmœzï“$9tèÐìììõ×_ÿñ÷Þ{ïöíÛçççã8^\\,Š¢×ë}þóŸ¿è¢‹Þö¶·]xá…SSS ÓÓÓι4MC¦¦¦8Né¤1nã4„ Ž‚%£(ÒdåÙÙÙÂg?ûÙÏ}îs›7o¾ýöÛ7mÚÀ“$‰Þ—v…Œã˜ã”N&ã6NõJÓ{¿oß¾(Š&&&ôÞ�ÖêC ÍUAŽ~¿Ÿ®â8¥£aœƒhЦÜKKK—~Æ3žñö·¿}vv6ÏscŒNVzïµ=”÷þ›ßüæµ×^{ç�wÎÍÍc>ð�¼èE/Š¢È9·yóæóÏ?ÿ[ßúVQ×_ýÏýÜÏãà¤s ¼ýöÛkµZžçW\qE­V˲L·VÍœŠH¯×k6›×^{íââb³ÙÔ�I’ÄZ›çyµÍªVž̪н{÷^sÍ5ËËË£±z¢ d£�S½MÕ)Gÿyï½÷¾ãï¨ÕjšÝßl6�Æôôô=÷Ü£�¨^¯üãß·oß/ýÒ/±�¿q§"²¸¸8==½gÏž?ýÓ?½ûî»óð�v»½wïÞÍ›7÷z=- ßï·Z­z½®W©§t2·qª¿ÕUw‹‹‹úýÔÔÔÑZ†èê:ïý`0h6›Ú§tLŒsm URa·Û=tèÐÄÄFhÐ(©~éK_úÌg>óOþäOî¼óÎ^¯×ï÷?õ©O½êU¯ÒPöóŸÿüý×µÖ¡Ó1SSSº{z§U H=õÔïEDìÙ³çÛßþöW¾ò•ÂhP„hcÙèãT÷Ð{oŒIÓ´ßïÿÕ_ýU­V[XXèv»W\qÅk_ûÚsÏ=À`0øÖ·¾õ7ó7ý~ÿÁüô§?}á…¾üå/¯JÕ�­±§eYêÕ×ÕW_ý�o|cóæÍÛ¶m{á _øªW½ªÑhè¾}ñ‹_üЇ>´¼¼ àSŸúÔ¶mÛ^óš×èµ¥NÓ|ûÛß¾æšköîÝÛn·_üâ¿å-o™ššrÎÝqÇ_üâ?ûÙÏzïÿéŸþééOúK^ò^ìц0VãT'Oxà�¿üË¿Ôt«�;w¾ò•¯|Æ3žÑn·­µ+++÷w÷•¯|åî»ïžžž~ßûÞwÉ%—h‚c¿ß×Ãâ�7ÞÈqJ'™±§zÞ[•JÆê!R¯7?úÑ�öz=kíììlQÞûjí�N›êÚvŽS:ùŒÕ8ÕKÅ8Ž8P«ÕÒ4}Îsžó¾P+ËiyyùôÓOwÎé�Xwûºë®ã8¥c°�DôDÓ\¿4M'&&fff�FÕô¢¢ñ*ÏómÛ¶½á o°Öv:ïý­·Þª½.<÷¹ÏmµZ"’$ɧ>õ©cܯnó+_ùJ³Ùì÷ûO{ÚÓvìØ¡÷«."7ß|óßÿýßÿ÷ÿþßßüæ7õ«_õÞoÛ¶­ßïEBÐNFrèÆ®¿þúO~ò“¿ÿû¿ÿ+¿ò+ï{ßûî½÷Þ™™6C¦ ê$§�4Æè8½ù替öµ¯ô¡ƒȲl½_¢c·q  ×ëýÝßý]«ÕÒz8ÿå¿ü—ïû¾ï›œœ´Ö8p Ýn¿ùÍoþÉŸüÉ4MkµÚý÷ßã�7b5“#Š¢<Ï?ô¡qœÒÉdÜÆ©ž»ŠˆÆ-Š¢ÐÅsõzýCúÐM7Ýä½_^^ž˜˜˜››k·ÛÕ5i½^×^t½^O¶8Né¤1nã4Š"-°ÿ~½J½à‚ žóœç<õ(.¹ä’-[¶Ð[ºçÿ÷ÏqJÇÀ8ÑP«Õ¬µ!„¹¹¹ùùùÅÅE­žïV�6�P–eY–OúÓ�F»Ý^XXÈó\[ ‹H³Ù<ÿüóó<ŸœœüÎw¾Óï÷�v¿Þû•••{î¹§(Š~¿ÿ‚¼ ZëmŒÉóü[ßúÖþá¾ûÝïþ×ý×8Žô¬qee¥Ûíj]Ôjßtq�žzv:�ýû÷¿ãïøó?ÿóo|ãKKKOyÊSÒ4eÚ N‚qª�<ªæ]»véYãþà~ÿ÷¿f4GQ¤‹ã:�ιçžû–·¼ÅZ»´´477wë­·®÷‹@ôÆmœX^^þ§ú§f³911qÚi§½ñ�oœ˜˜Ø»w¯v݈¢h0LNNþôOÿt³Ùl6›÷Þ{ï]wÝUMèìÞ½ûŽ;îˆã¸ßï¿îu¯›ššZYYÁêÊÖf³ùö·¿½,ËÉÉÉN§óÍo~sß¾}ÇèI4Æmœ.--5�›o¾ùþûï·Öþâ/þâæÍ›±zÐÜ´i“÷¾(Šç=ïyÏyÎsæçç£(úÖ·¾Õï÷«)×›o¾ùÎ;ïä8¥“ɸ�Szš ˲ª]ÇÍ7ßü‰O|âàÁƒ;wîœ��½ÿþû7mÚTõaÖFÚ<òî»ï¾ùæ›9Néd2nãTÃ!„ûî»O¯µZ­�Gʲ,ÏóN§£ß‹Èí·ßÎó^:6Æ9ˆ6€Á`�çy½^O’dvvvffFÛ¦U7¨’sµ‘T£Ñ!ôz½óÎ;¯(ŠmÛ¶---%I¢ ·¼ìe/`­ív»ßþö·�v¿ÖÚë®»Î{ŸeÙÖ­[Ÿóœç`µØ]³¦Ç]ÝÖh4úýþþýû[­V«ÕÒ§Þc•¬œsQmÞ¼YT’$Y–-..>øàƒ,ñOÔI0N«lª²,�1ßùÎwÒ4m6›Ï{Þó�†–À [[­V§Ó¹à‚ žúÔ§jÍÖn¸atAÑ·qªkK¿÷½ïíß¿óæÍ/zÑ‹ô¢qûöíöïßßh4¢(Z\\¼à‚ tÐ¥izÛm·éŸgY¦kå–——·oß~þùç뼪ÿN§£õŽ/ºè¢©©©<ϯ¿þúmÛ¶­÷‹@ôÆmœNNNÞrË-ܺuë`0xá _¨;©MÈ5 ree¥^¯?å)O‰ã8ÏóDQ¤ `˲üêW¿Z«Õ8Néd2nãTÛ�ëm¼÷:³ùÀ\}õÕÖÚV«õ¶·½­×ë¥iDZÞcžç‰Ôà]»vEQÄqJ'“q§X½J]XXˆã¸Ýn?ãψã8Eš¦I’hÈZ­fŒùÌg>SÇ)ãD@’$q'IÒëõƒA–ešôP4OBWaë±*I’F£qÇwLOOgY655ÀZ›$IY–ÏzÖ³â8îv»Þûë®»îh÷ëœûêW¿š$‰1æÜsÏÝ´iS·ÛÕË6�^yÆ3žñÛ¿ýÛŸùÌgþîïþîÿïÿ}õÕW¿ò•¯œššÒk9MÖ5§zY–¥ ëõúæÍ›ÿâ/þâ÷~ï÷þàþàÃþðýѽþõ¯oµZU'¢�e£�ÓÑEpZÝøÀ�Ýn×9×l6ã8Ö¾åƒÁ`Ë–-ºe=éܺu«s®ßïw:�ªŸ9Ñx·q:11Ñív[­Ö}÷Ýw饗Ž"­¡\–¥Þé\B˜��½å–[ƒ�1¦V«]wÝuyžOOO_yå•KKKÆíÓ˜çy«ÕÒÕ¬?ú£?º{÷nßþö·³,«f‚ˆÆÓ¸�Ó^¯7==­S3q:t@š¦ÕØ !heón·«CX‚îsE7ÝtS–e§t2·qª÷¥·Ñe7½^ïŸÿùŸwïÞ]Å[Þò–ÓN;ÍZ«QIžšÆ@W]wÝuµZ�ã”N&ã6NµCdÇKKK �NgbbB/<––œÒìÝòõ×_?11ÁqJÇÀù¢ @�CÝn·V«EQ¤�˜ôÎ{_–åh/µÊÁƒ÷ïß¿²²EÑYg�¥?Ô¬ÃN§óÓ?ýÓ�NG3ëC+++Õt1©V)ýÖ·¾¥‡]¼Öl6uVTÛxÆ3ž‘¦i£Ñ8çœs¶lÙÒjµ²,˲¬^¯ëdÕù @µ´ ÀäääÌÌÌŽ;¶mÛ699yÆgÄq¬¹õ~¾‰‹�>N­µúWEQ¤izÿý÷7 眵vÓ¦Múó²,õ‚ÐS%ôû}ç\§Ó™œœ\ï�èŒá8�›››žž!DQT¯×«eX]aªËît u0lß¾½V«õûý••Ýçùùù—¾ô¥µZM× héd¬6Ýyö³Ÿ]­ÑûÞ÷¾Ç>X4æÆmœ6�V«õ§ú§ò'òîw¿»Ýnc¤—U¯×‘z½Þï÷ó<!4 �ÂjýœÅÅÅ,Ë8Néd2nãTDtpyïõD÷_ÿõ_?ýéOÏÍͽüå/ÉK^’$‰N›ÖëuÍÿ¨Õjºú[Ó+9Néä3nãÔ9ç½ß½{·°Úºuk5 ,..ê7º‡EQèYç\½^×1xàÀž÷Ò±ñõ&Úô:Jãá�N§Óé,//ëeÕBMé¹�~Ê¿÷½ïÕ#™÷þMoz“~èëœf£Ñ8÷Üs'&&z½^·ÛýêW¿zå•WVKZœsšø�o|#„ ëI/¼ðÂ<Ï“$Ys�D¤6ú8­N5QcÇŽÿëý¯3Ïøàòòòôôô9çœS–%O%iœ�á8=ûì³ï÷~offFƒ…zq¨÷«w¡“2!„={öè>è5g½^ß½{÷¡C‡êõº†u9Þ‘�W Íé#Z\\ !pI�³1§õz]‡˜îÑ&XÕ^}ýë_¿é¦›´žÕK^òÝÃZ­vÛm·eYÖn·ƒÇ)�4Æpœb5ƒêÀ��Fãýï·Û½òÊ+Ÿýìgëšq=žjã+†Uá�ååe½¯8Ž9Né¤1†ãÔ9·wï^-Üzúé§///ïÚµk×®]{öìÑî ç�wÞsŸûܳÏ>{çÎ�Ú‡C˃Ûn»mff&Ë2ŽS:¾ØD†®k6›gœq†ž„­¹�ž½õûýù—ù…_ø…Ï~ö³|ç;ß @(ËÒZûÔ§>õì³ÏÖ¶T_úÒ—4¼¯Û‰ãX«óñ‹_¬Õj"rî¹çnݺuôt�ˆÖƧÚ1Àìì¬þDë™êœ©©©B¿ßïõzš  ÕjýÕ_ýÕ¡C‡¦¦¦¬µ;wîd�ƒ6„ñ§Z yóæÍιÉÉI­§=9ƒA·ÛP¯×ó<¿ùæ›xà�N§333óÜç>W>:Ôëõâ8®ÕjZs|Íõ^µÂnffF+:tˆõ!iC«qª‹IÓ4­J™E¡7qå+_ù£?ú£~ðƒ‡Ú´iÓË^ö²óÎ;OË�˜››Ó[rœÒÉg|Æ©1Æ{¯GÏÍ›7ÿÎïüÎ<EÑ«^õª /¼P7b­ÕL�ôÔ ˆþùÜÜœÎÕrœÒÉg|Æ)­ý¨7¶Öþê¯þêŸþéŸÞzë­óóóEQ,,,|ó›ß|ßûÞ÷®w½ë#ùˆ6©I>øàƒišZk9Né8A´1xï�1šÿ•¯|åúë¯_ZZÒâøZpÆ£í×¼÷eYNOOŸvÚi¿õ[¿uæ™gæy>11¡ŸûY–EQEÑå—_~ë­·jùÅ¥¥¥ÉÉI]‹­Õ‡———o¿ýöz½¾¼¼üÒ—¾€FÑ«)N"ZcC�SÍâ×�W�ߊ¢¨×ëƒÁ@±jýq!„¥¥¥ýû÷ÿõ_ÿµ÷~rròŠ+®¨òš‰ÆÙX�Ó¢(Œ1ºZM/;u%ÝüüüÌÌ ÝÚ®]»Þ÷¾÷é^=ç9Ï9óÌ3˲ÔZšê‘$‰©;òÁFQdŒ™ššZZZÒsŒGÒø«qŠ#:µjÕ/ýÒ/Ýu×]ÞûÂŽ;Î>ûì«®ºêu¯{€ê–zxÕMqœÒÉd¬Æ©÷^{o´Ûík¯½öÚk¯m6›¯xÅ+ž÷¼çé�Uέ¬¬hA¬öçÐqªs¯ÖÚ8Ž9Néd2VãÀììì?øAí}õÙÏ~vûöíÚþªÝnïÙ³gjjªÕjíÙ³§Ûí~ò“Ÿìv»o}ë[uHFQÔjµµ99Ç) ó9ˆ6†Â`0ÐFÁív{jjjjjJƒØB�¢Hëï7›Ín·Ûï÷C¿ø‹¿¸}ûv=nÐu.Õ–ç>÷¹šÃ¸´´týõ×c5®ÿñ�oäyžçùäääå—_®apfüÃF§Æ˜ªQ›®¸Ñ‰Wí_‡ÕÜ+++ŸùÌg~ý×½(Љ‰‰ÉÉÉŸú©Ÿ2ÆTeU‰ÆÖX�ÓªY±VÒHÓ4„ཟ™™Ù¿?€ÉÉÉ÷½ï}¿ÿû¿?77g­}Á ^ð?ð¢(*Š"˲F£Q…sn4‹«ª«S•Ð ¥¶÷X³ö�h �Õ8­†Œ~£­Œ­µ ÿ{÷#WYÿqü™™3gÎÜ·³»Ý-…ni…m¹Ô‚¥´~RÃ¥4ADBÂÅ„€¢„h˜¡/£kä–x©+·%^°ºµʵ-µ¥´Û²»ÝíÜÏœËÌùýñÍžŒ¥;¢víœéûõG³,3gζùì9çù>Ï÷9x0�Ê®WÒÁ#—Ë�yæ™j2}�I²}+9E‡i«œF"×uÓéô›o¾¹nÝ:Ã0æÎ�{ÅWÄb1ÏóÇ‘ª†ÄMŽégP)eš¦?圜¢“´UN•R¥RI6ÞðÚ_»åTFHÕäÞãþ`ͪU«Ö¬Y³xñâ\.�Çs¹Üßÿþ÷»ï¾{ݺu–e©É®8ããã2œDNÑIÚ-§J)ÉÝC=T©TÂáð�7Þ(½Xe•† õJ:iãÓ\È”ts=E‡i·œÊnU»wïŽF£™L¦¯¯ïsŸûÜŠ+’ÉäÄÄ„R*�N¯Y³æ«_ýê’%K&&&,ËúÑ�~dš¦¤õÀ�ÙlVn}å$§x?Öï �D]×­ÕjÙlvñâÅk×®õ[+Ê£—¼LnÎ^ýõ‡~ø—¿üåé§Ÿþ‹_ü"—Ë­^½zÆŒ~‰[MÞÒ�þù[·n�Åb[·nÝ¿ÿœ9s”Rº®ïÛ·oûöí®ëÆb±�}ìcÍ{7±�pXAÏi4•»C釓H$”R²¨YšŸêº¾eË–_ýêWúÓŸdÖ4ÍÕ«W_~ùå]]]ccc}}}´¶C›k·œÊJÐäÏz½^«Õ8ððÃÿñ�ŒD"ýýýápxppðÆo”fVÒa< IéÑ�­šÌ¾ßc'K+�jµ*/`ñ>Ú_»åÔÿ³ù›žç]wÝuþ¨ÊðððÆ�þóŸ���oܸ±¯¯ïâ‹/ö»jÈÉ):I»åÔuÝh4úýï×®]™Læâ‹/^¼x±�•—5�xʨ?>k†,”$§è$í–SyïÚµk�F4M§ÓJ)I–ÜKèæÎ�»|ùò;vX–õî»ï¾òÊ+çœsŽR*‘HHI’œ¢+�Ð4M.Ò6ѶmÃ0d9¼LE2Å, �uÖY÷ßÿêÕ«=Ï{ï½÷^|ñEÿ®N®OþÊÜåË—ËÕbtttÏž=ŽãHY~Ïž=ù|Þ²¬žžž ø Û¶ýË!€f�Sÿü.UŽãÔëu]׫Õêc�=öàƒnÙ²E~´3fÜu×]7ÜpƒLíéíí- 9ÐæÚ-§r>š¦ 9òÈÈÈsÏ=wóÍ7oÞ¼¹««Kª ·ÜrËwÜ‘Ëå,˲,K6öP“ã2ÒL@ŽìOjSÿÜCÀŸ»ÊºL´¿vË©¬ÆPMóCåÓ¥È!Í4fÏž}à 7¬^½:›ÍF"‘Ç\¦¦º®ÛÓÓ㺮ü,ä£ÝrªëúöíÛŸþùjµÚÝÝý™Ï|fbbBÎA)%/Ð4­R©Ôjµd2yÈ\o™u.C½ä£ s*KLr¹\:�–»ÙH$bY–4xôw5_¶lYµZÍårùË_êõºã8'œpÂØØ÷½h�: ²"/�Û¶-Ó®åštH·AMÓdœ1‘H\vÙeù|>‘H¼ýöÛ²µšLiQJÅãq¹b%“É%K–Hé{ãÆ�ÑhÔ0ŒF£±iÓ&©„ŸqÆ2M:3ÊÆSGû/hSAÏ©¿ �ü§ î„B¡Ý»wßrË-O?ý´Rª\.÷ôôÜ|óÍßüæ7—,Y¢”2 Cn+³Ù,uP´¿¶Ê©?Î";oÛ¶í�X·n]8¶,+›Í~éK_úîw¿û‘�|D¥‡²´•“s+‹ñx<8p@)�Få�V66¯ÕjñxÜuÝb±˜ÉdlÛ–ér@›k«œ*¥¤i†Ì!UJ•J%¥T(ò<Ï0Œb±(ÓT/¿ürÇq4MËçóÛ·o—s˜1c†´þ §è0í–Óx P(ô÷÷ßtÓM‘HD–&K3+™R‰Dd2¸eYrýõo˜gÍšU*•²Ù,9E‡i«œÊ69²š¤R©Èžçù;�—J%™=�H$zzz�FµZ-‹ò.MÓ¤õ9E ŒW�)‹õôô躇mÛ–«…”î¥N./3 cùòå¿ùÍoR©ÔÎ�;÷ïßßÛÛ[«ÕÞ|óMÃ0B¡ÐÙgŸ-¯”Ë›8GP»åT ²a£iš²Ýßþö·Ûo¿}þüùÒ×øÚk¯½æškÊ岮벉\4õoRij‡Î3­9­T*©TÊqÃ0~ýë_ÿøÇ?N$Ñhôæ›o¾øâ‹“ɤ<.F£Q—ñ7WTJ Äb±|>/Ï«~syº“ØJ¥"{~¼÷Þ{ÝÝÝ .<Ú£À‘7­9õ<¯Z­îÛ·/�&“Éîîn™…‰Ddnl&“QJÙ¶=kÖ¬ÞÞÞƒ¦R©|>/½çÎ�›N§GGGeê9Å1kZsê8ŽÜ�ŽŽŽÞ{ヲiJ¦ÒéôÄÄ„çy²C€a±Xì¶Ûn«×ëÉd2�N¯]»¶¯¯¯¿¿?‰”J%×uÉ)ŽeÓšÓp8\(²Ù¬R*�W«ÕP($_hš¦ëºt²’ã���T*%…Ér¹œJ¥N8áÙõJV3“Sã@Çêïï—…Š¶mû e•ŸRÊßqÉ’%===š¦MLLÈžQo¿ýöÞ½{e9áòåËýÅ€þmßÑþÉ€ÎÑV9•Ï …Bþ }ûÛßž;wîÄÄÄÒ¥K×®]{å•WªÉ�"‘ˆaRä��æ÷:Òôå4•J�ŽŽ†ñ‡?üᡇzõÕWu]¼ï¾ûÖ¬Y“L&-Ë’•j²g±T;\×�˜˜Èf³Ç¼L {íµ×Êå²|„¤R¦œëºþúë¯ËÞæ±XlÞ¼y²¢è0Ó—ÓP(ôÈ#�\ýõ·ÞzësÏ=' …B²å†šœ0.­6Êår±X”7ú»zôõõÅb1r L_N£Ñ¨l �Ëå …‚išr³:22¢ëúÀÀ€R*›Í–Ëå®®®b±(Û2ïØ±C†\3™ÌñÇON5ÍϧÙlvÿþýŽã„Ãáx<. š‰„®ë…B¡ù4vîÜ)-”eY¤RÊ0ŒÞÞ^i!@N1ê@’_÷étÚ¿´T*¥T½^…BR„—]L�F<ÿ¿ÿû?™Rúâ‹/*¥†††âñ¸iš§�všRJ.BjrË)–tGDæÔßÃMNlÇŽO=õÔØØØØØØgœqÏ=÷,Z´H^922"ƒ;r†ŽãÈ(¿Ða¦;§¶mÏœ9sß¾}÷ß¿®ë§�vÚŠ+¾øÅ/Ο?_ª±XÌ0 Ó4-Ë’åVº®ËG'“I¥ÔÉ'Ÿ,™}á…t]÷» 4�L&“Ïç£ÑèæÍ›=ÏËår3gÎdÑ:ÏÿàzªiZ6›µ,ë�wÞ‘fß2AÕoˆ!×ÄZ­&Ó]�FWW—´Í)—Ë ,�w‘S³¦;§µZmæÌ™ÝÝݹ\®»»»¿¿¿««KÓ´ÁÁÁD"1::Úßß?>>nÆž={Ž;î8]×ûúúN:é$9Çq>ô¡ÿùÏß{。P¨P(„B¡jµ*Ÿ«”’þZ®ë:Žãy^­V›?¾,e®×ë§žzª4¹"§˜ ÿä@ÇjLÒ4­X,†Ãa£'¿I¢|±råÊz½®iÚž={^yå•—^z)�NÛ¶}þùç+¥¤�£t§QŒcGT[åTî¥b¡”zæ™g¶mÛ–Íf-Ztë­·ªÉ5˦iöõõùûÚÉ™X,&9Žöß(päM_NeøO<‘J¥äAñÆoìîî.—Ëòz9iF,Ïœòà§&»téRÏó4M–þÅJ)˲¤mqWW—çyo¼ñF¥RÑ4í£ý¨RŠ-Ñ‘¦/§årùì³ÏÎårJ©7ß|sÿþýJ©J¥"HÛ¶ý­S7mÚÔh4 ÃÈf³³gÏ–K$gŸ}¶išä˜¾œ†ñå/yݺuëÖ­{üñÇüñï}ï{6lx衇֯_ÿä“Oþð‡?Ìårr1½çž{~ò“Ÿ<úè£>ø d-_tÑEsæÌ!§ÀôåtæÌ™R�8pàÀï~÷»ááa™C�H$lÛ‡Ãõz]î~7mÚôòË/‡Ãát:½páB©gèº~Î9çŒ��‘S´@�èL�FC®(òè%¿÷ývŠòHægîܹóæÍ“†¤O>ù䨨X­V›={ö™gžiÛ¶¼†v4À×V9õ·—–8ÕjuË–-2%çÊ+¯ìéé±m[Öÿú�ª„®ëò�F£111q´ÿR�#lZs*sↆ†¤1ñ•W^ÙÕÕ¥”J¥Ržç•ËåB¡ Í”R²x_vÄq]W6–<묳,X …ÆÇÇŸxâ‰|>¯”ŠÅb3gΔºÈc�=6>>nšf,[¹råÑþë¦Å´æ4•J�~úé²�qbbâ¹çž“ÎþÉdR–XÉâª�;w>ýôÓ¦iŽŽŽžtÒI~?�Å‹’Sã¦û¾wöìÙ‘HD†V•R–eÉü9lµZw]·\.G£Q™O�J¥d"y$™5k–LÙ!§8–MkNÇÇÇW¬X!E”���ï|ç;µZM&îÈË"‘ˆçyûöíÛ¼ys$©T*þð‡åFW.]:þ|rЍs(4)“ÉÈõ`ddD5Þ£ÑhóõFÓ´•+W6�z½þÚk¯E£ÑR©´jÕ*Õ4™4‹Iß_Ãà¿Ñn9õ—bÈœ—­[· …x<žL&ûúúvîÜY(FGGK¥R>Ÿß½{÷;ï¼óÎ;ïìÛ·o|||ÿþýÃÃÖeÉtW cLwNC¡Ðïÿ{©^8Žs '”J¥mÛ¶I¦LÓÔu½R©ìÙ³çÝwß-•J{÷îÝ·o_±XÔ4Mê±Xì /ÌårÕjuãÆ�Ï?ÿü»ï¾+4::úì³ÏnܸQ¶¸à‚ 2™Œ_Ñ:ÆtçÔ²¬L&sÙe— 6�GyäßøÆ¦M›FFFLÓTJ���ýìg?ûú׿þÆoèº~ÜqÇ]pÁ±XL6Ô‘¡¢O}êSäDzÿÁ}¯mÛ²�€,MöçåÈŒoik“H$r¹œeY~Ó9é㯔êîî¾îºëÈ)ŽeÓ�Óîîî®®®«¯¾Ú4Í]»v½üòËwÜqÇ–-[ÆÆÆ Ã��Û°aÃ}÷Ý÷ì³Ï*¥,Xpá…ª¦VÉš¦]uÕUä-hGûL 醑J¥¤Z.…n¥”eYš¦ÉxŠRʶmé¾téÒ 6 …D"‘H$Êåòyç�'‹=ϳm;‹Isð£ý“�£­r*�¶mK�cïÞ½š¦U«Õd2yýõ×Ïœ9sdd$•J9ŽcÛ¶lgY–¼«P(¤R©Ë.»ìꫯöçû�aZsZ.—u]7MÓó¼þþþ›nº©V«õööZ–U¯×]×m4ápØ£‰F£ápøãÿø 7Ü Û +¥V­ZõÖ[o9ŽS(6lØðÔSO-\¸p||¼ÑhìܹÓuÝ3f ^{íµŠÕ™èPÓšSB½æškn»í¶t:�Éd^xá…¿þõ¯þõÎ4Íz½^«ÕN<ñÄ‘‘‘«®ºjÅŠRÞ�iªJ©åË—¿òÊ+äDzé¾ï­×ëñx\ZöËLÿeõz]JæóyÙAGMvj�Çã…B!›Í:޳lÙ²-[¶�S˦;§µZí¢‹.2Mó[ßúÖŒ3vïÞ}×]wɆá[·n•½è<Ï›1cF&“¹âŠ+Î<óÌȆçÅb1�žwÞy\OÑë9€�{5¹'“å´~ý©”ËåH$rê©§:ŽS­VwìØ±iÓ&¥”¬¬W“3\¤l®iZÿ)§œ"w~X¸páܹse`% ÉCšL{iÑ_žè\×�F£¶mËŽR-^/×?iÅ(§$ �mÛnž�.—ÒZ­v´ÿ€V‚žS±°Rʶí÷Þ{ϲ¬d2iYV</•J‰D¢ÑhD"‘x<îy^µZu]7kšæo.G‘m®ÝršJ¥¶l٢뺌³D£ÑL&#�5<Ï‹D"ÑhTÞ«” ‡ÃÒL ›ÍJk¹>*¥n¹å–5kÖ¤R©B¡`YÖK/½´cÇŽááa9ÏsÏ=÷ _øB(r]—‹)Ú_»åT.mº®ß}÷Ý—^zi8–ýÆÇ)‹•J%W*×ugÏž}ç�w~ò“ŸTM]>„¦iä�¤Ýrª”’�Š•RápØŸ–.c¦~Ó›x<>>>.ïŠÅbr�l6+Ÿ …È):IæTÞxÉ%—Ü~ûí±XìàÁƒ©T*‰lß¾]ZAæóùr¹¼råÊ;ï¼S6Øèéé‘�Îd2ò9E ŒG‡e]¼Ü®†á8Ž\!¦‹Å�FOOÏÀÀÀÄÄÄÞ½{7nÜ(׉ÃJ$§œrÊ®]»jµZOOÏÉ'Ÿüœ§\A�†mÛr£é�ÎV½^�D"2yÜ4M)o …9sæ”Ëe¹(êº.Š­^ਠzNeÛ7ùºV«ÕëõP(”Ïç‰Äa�ÓÛÛ[©TǑęLFšû}€6Ôn9Íçó�FC–tÈÙl6�NOµÊ¾T*%“IÇqLÓŒÇãò¨éº®®ë—^zéâÅ‹_}õÕ?ÿùÏÿøÇ? Ø5kÖ©§žzÎ9ç,Z´Èó¼J¥�ÇýGD mµ[N5M“�’\.wíµ×ž{î¹CCCÛ¶mÛµk—mÛÑhtΜ9^xáààààà`___‹C‘StŒvËéTŠÅb&“ …Bš¦åóy¹ƒmñrŠŽÑ†9-•JJ©t:}É%—,[¶lóæÍo½õÖ믿.ó{.\xÊ)§,X° »»»ÅqÈ)¦¢Õ>Ðþjµš\�,Ë’ù›‰DÂo/sØ×‡Ãaù¿Õj5‰Ôëõ©+•R¥R)�N+¥êõºã8¡PH×õóÁ§"³¤>!ç\­Vc±ØTÕ™_Ð|­•é6ccc½½½þËŠÅb*•’¥‘GûŸ˜RäTf§JñC­¶h�%7͆aÈZÓ4 Ãh]ÚŽº6ÌiµZ ‡Ã͸jµÚâ#äB韞¦iþÄU¥”ã8~ÁR)%½8äk)�¨ÉE]GûŸ˜Ræ´™ã8�FCÞ¥”r]W:rLuz>?¼ä ÍsÚLvN–n<º®·9E'iÛœ6ofî‡Î¶m˲ Ã�'P™{Ø·“S´@�8V8ŽÓbÈRÆ4¥ �ßJø?&�|2çôƒl SËÕäzaicå_Øä Ò£ühÿ-Óë¨ç´^¯KõQM¶’›êVõýßw]×u]ê‘èxG0§2ørÈd‹›s)+:ŽãyžTj2�SÝ'’kÙØƒEÁhsí–S¿!€¿6_Žß"wþÑdìU–íËÏåyž<”úgxسeý>Ú\»åô�s“ɰ¡PHfÈJôÔ¨÷“St’vÎé!ä¦W6ê8d×â©~.rŠÎж9m^cÑh4¤Ç”\LýšÊ¿Ü‡œœâ°¨s€ ¢- *ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚Š:*ê ¨¨s€ ¢Î‚êÿ:ÒtÏ®Såþ%tEXtdate:create2019-10-12T07:39:39+00:00²àÁÊ%tEXtdate:modify2019-10-12T07:39:39+00:00ýyvIEND®B`‚kalign-3.5.1/doc/images/Bralibase_scores.jpeg000066400000000000000000005433421515023132300211160ustar00rootroot00000000000000ÿØÿàJFIF,,ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ‰M"ÿÄ ÿĵ}!1AQa"q2�‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2�B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷ú(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ©¨jš~‘kö�JúÚÊßp_6æe�2z ±5n¼«öƒÿ’gÿoÑ& ×þ¿ÿÐסÿàÆþ*”xë p]A +Z%Ò4 ¯ÞÎFxâ´«æïÉÏê_õù{üž€>‘¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¯*ý ÿä™ÿÛô_É«ÕkÊ¿h?ù&öýòjŸàü’Ûoúú›ÿB¯L’HâBò:¢Žìp+äÿüÔ|má¸õ›mZÖÚ7‘ãÉ6œv®‹þ¯Yÿ ý‡ýúz_�^%°ñ>¯£xC‘u «w0ÛüãÌ}¡cR:žqê=ëÝ<£É x;HÒ¦ Íkkr`ñ¿6?×Î2h~+ø®A¬Ég§j³(O³zúí @hØŒôàû⾎ð—‰ì¼aá»]jÃrÇ0!ãcóFã†Sô?˜Áï@E¬üVÕü;ñªûNÔµB<7i¼µ¨‚<·ú1ePÛwd¾1ÏJ·Ö~-xûY‡XÓaÔ­t“2˜ã·”A�w©+æqÔóŸÒ³<[¤E¯þÑòésŒÁqÊ=SËBÃò¾¦Ž4†$Š$T�*¢Œ Ò€8_ŠÇÃý màIõ+Öd¶I>âís¶:�•ã¾Ey6™añ›Çvi«Ã¬]YÚOóBßjû*ºúª§8ô$sï^Ùâÿø{Æom6»¯öEaIÌaAÁ$ãè?*†ãâ�¼?n–oâ-=Ýk2y¥Œ„Éí@#â‹ om¦Ö¯&¼²•°>Ó(¸Š\rWÞSøƒÇq_Dxk]·ñ7†ì5«U)ÜB@„ä¡èËøGá^ñ“⟇�3^ŸðWþI…ôŸÿGÉ@UñþK¶…þíŸþ�5î~8Ô®ôkZ�„¾Mݵ£É›Cm`88 ƒøŠðÏ‹ÿò]´/÷lÿôi¯iø—ÿ$ÏÄõã'ò sà—‹5¿xgP¼×o~×Ì¥Ù#ço÷�•š¾:ø•ð¿\†×Äí=í«œùwn%¯s£'#ëÆyôÜQG) (±Å…DQ€ p•Ã|bР×>j¦DkþÙ ã”)Ë~k¸~4ÖhZÕ—ˆ´;=_O“}­ÔaО£±Üƒî+Éþ,üZÔô m|/ᘇö™ çNSÌdgTEèX‚H=@Å/ìã©IqàýOOv,¶—›£Éûªê8úeIüMvwþð…§ŠOŒõC|’‰MÅÅÖÈÕ‚àŽ•y:x+ãn¡¼—_»·‘†ï%µFCÿ|§Ê>•‡¾'x×Á0ƒ@ñ¹–{guI>ѴɱÀ‘dy}rOCÐ×­ß|[ð&ŸŸ7Äv²ÚÝZlÿߊùëâï�ôÏx®ÒïIŠQmkn!óe]­!Ü[ vñŸzúè�IÀ¯�5߉þ3ñ犥Ð|T,HB‰%Ppdgo¸¾˜ÇQÔœWÐ×Pý¦Òh7ócdÜ;dc5ò€üO?ÂêÚî—+_³Ü*$L6C¦p¨È æ€:+ÿ |jð휚¯öåíÒ¦I#�PiŠ�É;ƒôסüø›qã›;« Uc­š‡2F6‰ãžgÞsÓ8ÏÐV‡í)ªÊnô=Xˆ–9.�sÃ1;Tþ7ýôk±ðßÅ?†žðÞŸ¤[kª‘ÚÀ±œY\rØù˜þï©9'ë@y¨Þü_øc³PÔoæ¿ÓÃï4ßjˆû1?:ç×�­{w€|oeãÏ&§jžLèÞ]͹91>={ƒÔê sÚŸÅφz¶—u§^k¢Kk˜š)Ù\r¤`ÿË:ó_ÙÂùáñ†±¦«î†k/;=2c‘@8úHhéJ(¢€>[ñÖµ‡hË­báH¬æ‚VDêØ·NÔÖÄR|aø“jú}ÔšN™!&Ý#¸û2•ÿd��¿Þâ¹?ŒZçÃMTÈ€ÍcÛ!|r…9oÍwƹOÙÇR’ãÁúžžìYm/7G“÷UÔqôÊ“øšÒø±ñe¼"hº,qÏ­L¡™œn[u=8îǰüNráàð·ÆívÜjRëW–lãzÀ÷æ?ðá~‡ÍøsÄšß/|Iâ«¿*Ò;‰§ˆ¼O ÞØ— ùFÿtW¸ÿÂíøyÿCþI\ñºó_üXño‚Í,gÉe;¹eïïë^µðŠþMKáV�<§.�´„nÈ?EåÖ_5�Ç>'‡[½kÛ Cs…’ÔL5Ü«Ÿ»»$“À=N*Ýχþ5ø²©É«¦Ž²|ÑØÇtÖì«Ô ?øógÖ¹i0jß´MâÜ x­µË�¤pY¶þMƒøWÔ”óo„~'xÃÁþ5‹Ã~3–kˆe‚arCIlaÃ�¼¼ƒÉ$貨ý”{ˆï‰_ìµYt…úåÌ,VW„@¤uc?£òï|WñWŒ¼Nþø}¬!Š‹ˆ”y“Á}ÍÄièx=9çRûÃß<3jú°Ö¯.Ö!æIw¦à¨vü º¯ÙÏE†ÛÂWúÉAö›»£~â4þúfü…{=y�ÂOŠ-ã»iôýJ8âÖ-;øYãÎ7؃ŒŽœŒz'ö˜ÿ�¯ ¹süã¯@ðçÂM?Ã9ŸÄÖ:ŒãÍiOÙ<µ«!'h=p1ô¯?ý¦?ãëÃ_î\ÿ8èX¼EñâLkkà¿ø”èvˆ°ÙËi\(Ï͂߂Žç­súô¿þM¡¨kw7vŒá|Ö¹k˜Kuƒò¹úc_Ax/JƒDðV�§Û TŠÒ=ØyÊ‚Íõ,IükŸøÐŠÿ uÝÊ&ÇÎJÙð'Šãñ§„,õ¥ˆC$€¤Ñ�’)ÃíÜ{^kñ?âF»áŠMŒ“A¢­æ»…mãrÈe`ø%Kr«Ž l~Ï_òMþ¿åÿÐR¼óã­²^|^ÒmdÎÉ­-ãlz\ç@ ²üXø— jš5ÊxE“&Ò#9…åN͹T±Ï¯ÓÖ¹�7â/Ž~ø¼i^-¸¹¾µR<ønÍcé$ny?LàòO§"Š8!HbEHãP¨Š0ó—í)hr�󵣩> ?ÌЗö�Å/Š�.¡áë� è!ÊÛ˜Âdã;”cëŒ.xìk™|FøYâ˜m>èúÍ„2Em&§f‰æ‚².H¸ü±@V];Gi3¡Ã*1ßóo†~:x‚Û@Ö¤Õ離»A™�o3{Š2�R&¾�½ÿ��úäßʾbýžô;}OÇW÷1¬ƒN¶ó" 3‰‚†üïÇÙü2·ø¡uãXu_¶¨ºT±HdK™B b¿/îr1Ïû5Ïø;þNRÿ¯Ëßäõô�|©‰lü#ñï]Ö¯ÕÚ{«Ü$c,ìwQé’G4ô_Œ|c¥ø'B“SÔäÿfüó?e_ê{W™ü8×þ#|@Ö¥Õî5Oìß ¤¤ˆ£µˆù˜?êÑ™ ;±?Nzy4þ&=ø�§ÞxÒy`Ò¦˜'—Ú�ÄOg¢ç›¯S__YYÛiöPÚYÃРH£ŒaUG@OEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^UûAÿÉ3ÿ·è¿“Wª×šürÒõ _áçÙ´Û›Û�¶DÞU´-#àÉ‚q@üÿ’[mÿ_SèUéÕò¿†5ÏŠþÑSIÒ¼3©-ª;8hò±ËžvÖÇü,?�?ô._à’Oð Iøé5¬_ 5$¸+æK$)=KùŠxÿ€†ü3Xÿ³šL¿ïZ@DO©9�=ÿw'é‘úóé<ñG↫nÞ!ŽæÒÒ3þ²ò1 pƒÔ¬CŸÃžæ¾‹ð߇ì¼/áû=OR-í“h-ÕÉå˜û’IühÀnäê×þ¿SÿD úN¾~¸ðî¶ß´°ÕF�¨;íˆßk¯äãÉ;ñŒg޵ô |ïñÏÄz®­ã+éó´VÎ" b¢id8PØê ãÔ“é]žƒðÂu´Úiqª\�ó´’´iŸeB8ú“\ïÆÿkWZ寋ü?·Ĉ·À»¤��ådQÔŽ€ã¦õÅÚ]XVÊë‹s©´´Rºnoúç´ŸÃ4«ñ§Â¾ðÏÃoø”éVSK{ #Œonãqäð=k²ø)ÿ$‹BúOÿ£ä¯&ño†¾#øÿAºñ>¹jmb²@ÖZLq�ì¤�Ä&rå¾cŽ1]'ÀÝOkm๴–T´I¤[Ðä –ÚË·®XóŸÂ€9ÿ‹ÿò]´/÷lÿôi¯iø—ÿ$ÏÄõã'ò¯)ø§áÝoPøÏ£_ÙhÚ…Íœb×}Ä6®ñ®%$å€ÀÀä×­üBµ¸½ø{¯[ZA,÷ÙH±Åg$trMyïìÝÿ"f«ÿaÿ¢Ò¸_jqhß´¹Ô'`°A{fÒ±þò¢ I¯Gø£êz7„µ8uM:îÆW¾.©uD̾ZŒ€Àdpk…ñïÃíwÅ¿u8 Óïa²ºTòõ¶snm”Œ¾1‚Ë·9ã>¼PÒ€‚29ÆüVÕaÒ>k²ÌàíšÖ0O,Ò|˜�'è y�Åü8´]ÄZ º[aåÃ5Àe;G UÔv?­e^?�¾7jöÑ=‘µÒ¢|©²[Cرc÷Û‡>€dÐ{û7éòCá=VýÔ…¹¼¦GPŠ9úeˆü pR&§ñ£âÕÆ�q¨I›nÒ´j9À�·å^›˜‘“ï诤|5áû? øvËE±ȵ�hcÕÛ«1÷$“ø×Îþ#ð÷Š~|DŸÄº%“Üé²É#Ç Œ¼{壓®;3€Gq@³¦|ð&œ‹¿J{Ùü´º�ØŸÀ¿¥yǽ/IÑ|M£Xi6V¶q­žöŠÞ0ƒ™ã©àò}+¤‡ãç‰u´zƒ<Ëöà2Èó¨>»B�Ô× ñÀ¾3±·¶ñOˆÝîï/ݾÔ"]â×جG# c�Œf€>¯¾½·Ótû›ë¹<«khši_íE'ž5Ê[Ýx╽Äq¥ž²¶›VFx^-ÙÆ€a�§¡íU¼âóñ3·çPÒ ’me_0²Ì>b¹“Ç?Zñ%Ó|sðSÅ766Ow§Éò¼¦’ ãÎWv߸Ãêç¨<€zF·û;xbõô›ËÝ6c÷T·�üæÿÇ«ŠøG«ë^ø¥'‚nîL¶rK4D²$ˆ¬ÁÓ=3·ñž•j_ÚÄÚ”&×IðÔ xÃheß1Ô ŸÎ¶~|7× ñ,¾4ñRI ãù�S­i$Èi†:óÛ ¿´¥Œ‰®hz†ßÝËlðgÝwþÏ^“¤ü/øu«èöZ�¿‡íÞ¨da4œ†ÿz¶~!ø*ßÇ~—K‘Ä7(ÂkYÈÈŽ@çØ‚AúçµxV�â߈ô}OF{�5˜Òub‹žIŽUã®9úšöK�„ßím¥¸ŸÃöÑÑÚi0ªI?7¥Søt¿ .µ[«¯Û¨¼‚“H±Î¸F=?yÇ%Jò½kâ'Žþ(Ú� DÐÞ K�–aj¬ÅÇ£Èp}z{œq^Éð»À)à/ ›i�%Ô®˜Kw"tÎ8AêŸÄ“Þ€;Š(¢€>^ñ¦§�ûK�Bv ¶m+áO* Çðšú„FG"¾kñïÃíwÅ¿u8 Óïa²ºTòõ¶snm”Œ¾1‚Ë·9ã>¼Sì~(x÷áÅ¢è~"ÐMÒÛ.®)Ú8H2®£±ýh×þ+j°é µÙfp öÍk'–i>LÀ“ô¸�Ù¿O’ ê·î¤-Íà�2:„QÏÓ,Gàk‚¼|nÕí¢{#k¥DùR#d¶‡±bÇï¶;}ɯ¤|5áû? øvËE±ȵ�hcÕÛ«1÷$“øÐÌßü;¢Ïñ‹Pðï‰l㸌µÌG#2�5_ ‚þl}kÝ¿áOøþ…È?ïìŸüUpÿ~ê·šÚøÃŠí¨)W¸‚‰7§Ý’?S€2<3“Xß¼Y¤Û‹cñK~ƒi’ExŸVLuúcé@׉¼!ð�ÁÖÐO®éVö©på"æw,@ÉáI8¾â»¿ Ûè–þ±‡ÊÒdO6Ý@qò±-œ?ÍÉ9çÖ¾~²ðÏ�¾2ø¢ OÄPKc¤EÆöŒÆ‰rV%nI?ÞçÜð}-km �¤6¶ñˆà…8Ñz*�€à(ç†_òqßýw¾ÿц¾“¯Ÿ¾xw[²øï«ê7z6¡oc$×….eµt�ƒ9+†#=½kèù·ö„ÿ’‰¡ךèׯUøÏc%ÿÂ�ib]ÏÇ6=–E-ÿŽäמ|sðî·«øïF¸ÓtmBöí^[kW‘Tù¬pJ‚ÁÍ{ÝÍ´7–³ZÜF$‚dhäFèÊF?� &ý�õ(n|sbyö—­¹{íp ŸÄ†…zõ|ɨx_ÆŸüU>­áÈ%¾Ò$ÈÜ#2#Gœì™W�G÷¸ö<‘Vï><ø»\µ};EðòA}*ìó!WšE'º®8?\Щéß4mWÇïá [;×»I¥…®0žVc Xçvqò‘Ò¼ãö˜ÿ�¯ ¹sü㮇à·Ã+ï <þ"×ã1êW1˜á�ŽZ$',ÍþÑÀã°Îzàg~к³­\ø|éZMýø‰'—fLxÎÐqœÊ€=ŸGÿ�%‡ý{Gÿ Šä~2ÿÉ%׿܋ÿG%vR4z=’:•u·Œ2°Áhà×/ñbÆïRøa­ZXÚÏus"F#.í‰Pœ(äð  oözÿ’jÿõÿ/þ‚•Áüjÿ’Õ¡× _ýõèÿô½CHø|öÚ�…Õ•ÇÛdo*æ�°Bàá€8ⸯ‹¾Öõ/‹º5í†�¨]ZG °yàµw�H•‰Ë�€A  kç/ÚWþCºý{Iÿ¡ ú6¼ö‚ðöµ­k:,šV�¨_¤vòk[g”),8%AÅ{½¯üzCÿ\×ùW‡~Òÿò ðïývŸÿAJ÷`VÖA ¥xçí ¢jÚÖŸ¡.•¥Þß´RÌd¶ï)@Bã;AÇJôO Ý¥‡Ã=ò@Lvú<2°‹'ùWÏ^Ð5�~5Ô/õýJd¶·Ig%C¶8ÁáGœvîNkè¿ Øð‘§^Âñ“¥Ãñ:•eýÐVR õó­´>0øâ˹ãÓšóM˜yfRŒa¸�9S¸}LJ¦OPµiß<§*ãC[—Çs3ÉŸÃ;JòZXX~ÑÚ-ž�oµ¼¶ äÀ�ä8À㸮‚?�~2ñb}‡Âž)w Ûç—iÖ<÷åUWêÇÀø«ÂÞ'øyâ­#Ä:¡:�ËËü—3Gç«î1³w<xëÇJúÎ÷þxóþOaßK»SÓ*–<ËEor¼)ÿ€ú׫� ŒƒÔù¯Ä~ ñïŠ0ë~Ñï¯tö>8í-ÞEU' m®=ˆî(éZ*½…Ø¿ÓíîÄ3À&�_Êž2’&FpÊyzUŠ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*“Ï(‘€n=…]¬éÖ¿ûÆ€ö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿôtÈßeߟ›¯ö™¿ú ˜ÿÇ�áýj¥Kö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ « # ]ùù°9ªUm¿ãÄ}ó ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€.´Œ-Cƒó`sUþÓ/÷ÿAS?üy ª”/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚¬<Œ-ƒƒó9ªUnOøó_  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€.É#-²¸?1š¯ö™¿ú š_øôO ª”/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚¬K#-º°<œsTªÜßñꟅCö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿôf¤y•Y²µ[ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÏüxþÖªU³ÿ?‡õª”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnOøó_ ª•nOøó_   ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[—þ=è*¥[—þ=è*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnoøõOªU¹¿ãÕ? ©EPEPEPEPEPEPEPEPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬½_Ä:V‡k,××°ÆQIoØúêMeø _¼ñ'‡žþûg›ö‡@p€0?Zê(¢™4ÑÛÃ$Ó8H£RÎÌpI4ú+ΓÇ&צš_ hOaó®[ñéó/åÍnxKÆ+â.lníÇUµÿ]nǨÎ23Ï^£ÜPSEs-ñ‚xpÛZ[Zµî©vq²Ÿ|d÷ëÐwæ°$ñ¿Š4!ŸÄþŠ>V f¶l”ϯÌÜûP£QQÁ/»K/êóHØe‘ÿi†ÕýH  Ÿ†7OuàK ä“ �‰¡ð­ŸøŽÇÂÚWöŽ %0y‹î”1ÉéÆG¥c|0µ{_Y—3;˃èX�úk¢Õ´m?]²û§l·ûƒìb@Èèx"€8ø]~þæ£ÿ~ÿŠ®ÒÔ�FÒØ?Õ\F²¦îÖü bÿ²ðoýáÿ¿�ÿÅVÔ`YÄ–¶ÿ$0¨Ž4£€?!@ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ™å'–e‹÷wsùQö‰¾k‘™Ûþ ùù·¯?ðQ9òÛÌéÃPöÎJö²oî;²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷ÍYÌ?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|Ð$^PI#@znlS…³²†R¤A­r>;‘ÞÒÌ3g7ò®‡KžA¤YÇÿÐErÓĹb'Fß _ˆ“ÖÅï²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Íu ´bo³y|nÅAöI?ÙüêbíöMùù±×ñªßh—ûæ€öI?ÙüéÙÕK3 P2I< oÚ%þùª:Ôò üàÛ¿þ‚iÅ]ØŠ“䃗d^Ž/8‘¸J¶iÿd“ýŸÎ¹Hé¦Ýl~ûú ë>Ñ/÷ÍUXrMÄLjxŠªÕ®?ì’³ùÑöI?ÙüéŸh—ûæ�´KýóPt�û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�0E™<±,eÿ»»ŸÊ�´Kýó\¥›°ñœŽͽùü oF�´RwÙ\¸C™?#®û$Ÿìþt}’Oö:gÚ%þù£íÿ|Öû$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïšÎÕ¼Bº:DÓ‰\HHíõ¨©R4âç7d�»Ÿd“ýŸÎ�²IþÏçPÃy$ðG*± êy§ý¢_Ù$ÿgó©ÌLm¼¾7U_´KýóVYØZoÏÍ�Í0!û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ«]ê-gi-Ë–)–!@É«i:òëï4DT}„8ÎíõªåvæèdëSU&ýç­�/²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷ÍI¨ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$ŸìþtÏ(yž_›ÿîîçò£íÿ|×#·ü'Eóóonà¢så·™Ó‡¡í”õ·*oî;²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷ÍYÌ?ì’³ùÑöI?ÙüéŸh—ûæ°õ[é×�jë;ºcq@023ÜÖU«Ó£jŽÈM¥¹¿öI?Ùüèû$ŸìþuËÂ}mÿ¶ÿž7?’ÿ�sia?� �4‘ˆqæËg¦æÆiÂÕÈ ÷Íyω|A¸¶Â4•|’ÙÞ|z}+jßÇVÐÛE†ã(�x Ø}kfÔYE´’µŸqs«�oÙ$ÿgó£ì’³ù×-ÿ õ·üñ¹ü—ühÿ„úÛþxÜþKþ5·ö–ùÐùÑØ4Lm„|gŠƒì’³ù×?}ãXaÑmï-`yY2®ví+‚s×Ô~u�ÿ ëþ|—þþõ«Ò£JU ªSÕ3‚¾k„ÃÏÙÔ•Ÿ£;�²IþÏçHÖìŠY™GRN®#þ×üù/ýüÿëU]CÆ÷†Ÿ=£Zª¬ªT¶üãô­V­õG<óÜ‹q•ߣÿ#¿Ž5wG$nÆU³Oû$ŸìþuæzЦÐìžÚ;u�<†L—ÇP§µjÂúÿŸ%ÿ¿ŸýjrÂTOE¡4sì$ �GgÕY¿Ðî>É'û?�d“ýŸÎ¸øXw_óä¿÷óÿ­VmÑ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïš@Éå‰b/ýÝÜþTÿ²IþÏç\u³°ñþ~mïÏü×]ö‰¾j)ÏšçN&‡±qW½Òxÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷ÍYÌ?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù®GÆ÷—1µ�—<‰Ÿ3;®~ï¥sâ± EÕjöÿ; »+��Ù$ÿgó£ì’³ùÔ÷›h²çîåR}¢_ïšÝ;«ŒÙ$ÿgó©Þ&kpƒª¿h—û欻°µVæÀæ˜ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçY>!¹�t ÆYYX'NäUÝÜI¢9’gsç·.rz/­h©Þg$±J8¥‡¶ê÷:_²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Ífu�û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4,[œ¢ËaÕCsOû$ŸìþuÈèîËâ›¶’dçþ]_Ú%þù­ñ}””o}.iRŽÃþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß5�˜ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$ŸìþtÁ2ybX‹ÿt7?•h—ûæ¹aãYœ›|œþ¢såkÌé¡CÚ©»Û•\ì~É'û?�d“ýŸÎ™ö‰¾hûD¿ß5g0ÿ²IþÏçGÙ$ÿgó¦}¢_ïšä5ë)¬Íee¾ÆÚª#,Ç“ÅsbqTðÑRŸ]4i—Ù$ÿgó£ì’³ù×ÿ ‹?çÂ_üj?á"ñgüøKÿ€­\ŸÚÔ–_q<è줌C�6X“=7>3R}–OUüë͵i5ýe¢k½>à˜� ¶Ý‡_ÃÚ´—Ä+U ,%Àÿ�V¨Žo6¥nš9Ûý’Oö:>É'û?�q?ð‘x³þ|%ÿÀV¦KâA–kVŽ5êÏlÀÄÕ¼ÚŠÕÆ_ps£Ð$‰šÝPc#Ù$ÿgó®:óÆšŒZ„ñÇžg‘]¶’>\tïŸÒ«�øµ€"ÂB ‹V¯^…7^”jÃg±ç×ͨQ¨é4Û]•÷;Ÿ²IþÏçM{v�K;"¨êIÀÄÂGâïùð—ÿ«ßjÞ(Ôl¥´ŸO˜Å Ãmµ`zæ¶XY_VŒ'�ÑQn0•ýþ8L«º9#ué•lŠwÙ$ÿgó¯9ÒïüK¤Z}š×OœG¸·ÍlÄäÕßøHü]ÿ>ÿà#SxY_F…O;¤âœá$ýçì’³ùÑöI?Ùüë†ÿ„�Åßóá/þ5XѼa¨ÜKv—¨‡ÉˆÈ®Ó�@Áüê^} èæÔ*Õ�$šrÚèì~É'û?�d“ýŸÎ¹_øLîçÝï¿þµð™ÜÿϺÿßýj×û?ü¿Š=¯«Ôìu_d“ýŸÎ˜±or‹,lè “\Çü&w?óî¿÷ßÿZ²luy,u)oV0Í&ì®qŒœÕÃ.ªÓæÑô)a§gsÐ>É'û?�d“ýŸÎ¹_øLîçÝï¿þµð™ÜÿϺÿßýj�ìüGòþ(Ÿ«Ôìu_d“ýŸÎ�²IþÏç\Ì0žIãG€f�ÜŒþÑý¢_ïšÂµ ”ZSV¹§(|CþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß5‰þÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÑöI?ÙüéŸh—ûæ�´Kýó@û$Ÿìþt}’Oö:gÚ%þù£íÿ|ÐþÉ'û?�d“ýŸÎ™ö‰¾hûD¿ß4ÿ²IþÏçGÙ$ÿgó¦}¢_ïš>Ñ/÷Í?ì’³ùÔòDÏ ÆF*¯Ú%þù«2»-º°8'Ð?d“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù ý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÖ>�â ¯µ ­L{`�Û³œ==ëWíÿ|ÕÔ§*o–[•(¸»1ÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïš‚Gý’Oö:>É'û?�3íÿ|Ñö‰¾hÿd“ýŸÎ�²IþÏçLûD¿ß4}¢_ïšÙ$ÿgó£ì’³ùÓ>Ñ/÷Íh—ûæ€öI?Ùüèû$ŸìþtÏ´KýóGÚ%þù  ¡·t”1ÆZªpM#LªÍ�jåQEQEQEQEQEQEA{ \Ø\@„’&@OL�E`x÷~ðùÓïd‚ILí&abWP=+¦¢€0|[¦ë®Ž¶úð²»+LŒ™PFTÔ�Ê´,¬äµŽ¤Ës/Ù––$°‘¶€Ç'““žµzŠóÈ|â�É4×`�O•ˈnÓ&2}>VÏé[^ðö×:…íÛ_j×ë®`œà~8ü‡Jêh _Åž_½µí¥ÛYj¶‡0\(ÏÎãüÍbOàÏx�¢·ñ.½éñ°fŠÑ0dǯʿ×é^‡EGoV¶ñ[À‚8bPˆƒ¢¨¤¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š(¢Šå$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEW-iÿ#„Ÿï¿ò5Ô×-iÿ#„Ÿï¿ò5Û„øj…›ÑÚ^‡SEW€QEQEQEQEQEQEQEQYÿÛÿÚŸÙûeó³ŒàméŸZФ¤žÅΜ¡nekêQE2Š( ¹/ÿ¨²ÿyÿ�®¶¹/ÿ¨²ÿyÿ�¯?5ÿsŸËóDÏá:M?þA¶¿õÅ?�«5[Oÿ�m¯ýqOä*ÍvÓø¡H*ÛLjúçU*ÛLjúçVJ(¢€3õÏù_×þU�àoù\×sÿ ŠØ×?ä}ÿ\[ùV?�¿äqÿ]Ïþ‚+¦?À—©ãÖÿ‘¥?𳨢Š+˜öŠ( Š( Šæ¬§™¼U4fW(þRÇ•tµµj.“I½ÕËœ9‚Š(¬H (¢€ (¢€ (¢€ (¢€ lޱFÒ7ÝPXý: ½ÿ��úäßʓب«É#øºñhøÿ|Qÿ |_óèÿ÷Øÿ “ÁV¶÷^àŠ]¬˜Þ�±×Öº¯ìËùò¶ÿ¿KþÏk8ós®#êt*:n›vó9øKâÿŸGÿ¾ÇøV:ꪺ÷ö�”vî'fyû¸ë^�ý™aÿ>Vß÷éÂ�ìËùò¶ÿ¿KþåJ¤­yO…§~ZoUg¯C‘ÿ„¾/ùôûì…ð—Åÿ>�ÿ}�ð®»û2Ãþ|­¿ïÒÿ…Ù–óåmÿ~—ü)òÕþc/m‚ÿŸoï9!âèr3hàw!�¬ÅŠψ+Ѭ�Èã*à �/5§ãkh-Í�‘qnó3±çîúVm�ü”>£ÿE×™�rnœ'¯¿ÔŒm:>Ê�ZQ·3~{¿ü#Ú?ým¿ïØ£þíþ�¶ß÷ìV•ê}^—ò¯¹6Foü#Ú?ým¿ïØ£þíþ�¶ß÷ìV•}^—ò¯¹‘›ÿö�ÿ@Ûoûö+/ÄZ.™máûÉ¡°·ŽDL«*G"ºjÈñGü‹7ÿõÏúŠÇB’£6¢¶}<„Ò±æ—?ò+Yÿ×Ü¿ú Wªé‘Ft›2c_õ Ûý‘^Usÿ"µŸý}Ëÿ ¥z¾—ÿ ›/úàŸú®Œü‹¨ú>_0­éȱäÇÿ<Óþùy1ÿÏ4ÿ¾E>ŠÒç³d3É�þy§ýò(òcÿžiÿ|Š}\,†y1ÿÏ4ÿ¾Eyd$Ö€é‹�ý ½Z¼¦ù5¯¥Çþ…]¸=ßÈò±é,NüGcà¯ùÏÿ]�þ‚+¥®kÁ_ò Ÿþ»ýWKYã?�#Û­üFQEsQ@WŒÿä)iÿ\ÿöjèkžñŸü…-?ëŸþÍ] vâ?�KæoSàˆQEÄ`QEQEQEQEQErvßò:·ûïÿ šë+“¶ÿ‘Õ¿ßý×YXÐÙúž†cñSÿ ýBŠ(­�<(¢Š+Žñ×Þ°úIÿ²×c\w޾õ‡ÒOý–¼ÜßýÎ/Í?„ë-¿ãÖ/÷ò©j+oøõ‹ýÁüªZô#𢂭ÉÿkôR­Éÿkô@T¢Š(/Äò/^ÿ×?ê+?Á?ò“þ»·òZÐñü‹×¿õÏúŠÏðOü€äÿ®íü–ºcþîýO§ü�aþù�%Q\ǰQEQErÚGüŒ÷_Y?ô*êk–Ò?ägºúÉÿ¡WS]¸ïâ/Do_â^�EW€QEQEQEQEQEQEW'eÿ#”¿ïÉü�u•ÉÙÈå/ûò#XÖÞ>§¡�ø*ÿ…�eQ[xW¥ÿÉH?ïÉÿ ì+ÏçÔŽ‘ã)ïDBS�òÆr¸ëø×“šÎ0öS–ÊH‰ô=RŠà¿ábÉÿ@Äÿ¿Çü(ÿ…‹'ýþÿð­?µðÏø?òx�íÁÂÅ“þ�‰ÿ�øQÿ Oú'ýþ?áGö¾ùÿþAϽ¬?È«{ôOý kžÿ…‹'ýþÿðªZ¿�_UÒæ²6+—8—8Á¦=« Ni…�Æ2Õ§Ñöô5cÿþEÝ+þºOüÒ½rÓþ<àÿ®kü«Èïÿä]Ò¿ë¤ÿÍ+¿·ñŽ‚–Ñ#_á•#É“®?ݯc KG•_CÄÃ×¥K_ÚIFü»»t::+þOÿÐCÿ ÉÿÄÑÿ §‡ÿè!ÿ�dÿâk_eSù_Üz_ÂÿÏØÿàKüÍê+þOÿÐCÿ ÉÿÄÑÿ §‡ÿè!ÿ�dÿâhöU?•ýÁõü/üý�þ¿ÌÞ¯&°ÿ�¦³ÿ\¤ÿÑ‹]ßü&žÿ ‡þA“ÿ‰®L‘e¿ÕäC”x”úƒ"×^‹|ÊÛ~gŸ‰ÄQ«�Ã{9©Z]gsàäVÑ\•ùÍÔ{ è|¸ÿ¸¿•`x3þ@¯ÿ]Ûù èk[ýü½O ­ñ±¾\Ü_Ê�.?î/åN¢¹î̆ùqÿq*<¸ÿ¸¿•:Š.Àâ|T¡|Cfû´éþù®Š¹ïÈÅgÿ\ÓÿCjèk³ü*^†õ~…Q\FEPEPEPEPEPEPEPEPX!×§Ñæ�"†9ŠIßž1[õÅxãþ>¬ÿÜoæ+ƒ3«:XiNÏOÌ™»#µŠ)AK]å[›þ=Sðª•noøõO€*QESS¾]7O–í�ºÇŒ¨8ÎHÖ™¤jk«X‹¤ŒÆ ÚNzU_È·yô_ý UÿȾ¿õÑ«eìyºÜ󥈨³Bþï-þw: (¢±=¢Š(¢Š(–ðÿü‡®ÿÜýWS\·‡ÿä=wþãÿèBºšíÇÿä�ñQEÄ`QEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPA ž¢™7ú‰?Ý?Ê�¥wc,ø—L�5Î;„4Ÿð“i¿óÒOûàÖg„ô«-M®Åä>g–oÌF3œô>ÕÓÂ)¢ÿÏ™ÿ¿¯þ5Í UšæV=Zô°T*:ræºô3?á&Ó礟÷Á¬5vñ0¾ ÞFå9Ç<(+±ÿ„SEÿŸ3ÿ_ühÿ„SEÿŸ3ÿ_üh”*Ê×°Q¯‚¥w-UºŸð“i¿óÒOûàÑÿ 6›ÿ=$ÿ¾ iÿÂ)¢ÿÏ™ÿ¿¯þ4Â)¢ÿÏ™ÿ¿¯þ5¾ò1¾´¿4x›L'ýc�ø¬�c_Ô£Ö~ǧía…Ø7$ýjoé:dV­i–]˜7ÎNq�SYÐÈïaÿlôX¯70«UF0R³rJëÎæxÊ4cFhÞÒoro·x»þ|§ÿÀoþµnñwüùOÿ€ßýjôz+OìúŸóú_yÁÊûžY¨CâMQ.¬.!Êâ?¥Y†çÅ�C)e8DPª>ÍØ zW¥QR²¶¤æªÊï¨ryžqöïÏ”ÿø ÿ֦˩ø®šYmeHÐe™­ðü«Òk7Ä?ò/jõÁÿ•*˜�ƒ’­-pq}Î5ü[¨� ¬£ÊóÍÉ‹~ßá §¯5^=OųD’Çk3Æà2²ÛdzÅdÉÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"½lº§û :“Wo¹áJ±8ÙÒUe’Ùœ7Ûücÿ>Sÿà7ÿZ£žãÅ·6òA-Œæ9£mŽ•é´WWÖ#üˆÝåU³¯?¼ò�:/éqSÿà7ÿZ½&Šo›»Š2yÓŠŒ+É%æy·Ûücÿ>Sÿà7ÿZ�¥x�TmB{kÕRÑÄìU“iVQœ~•èõåÇþG-Wéqÿ šÒ”¡VéÅU¡[ ^�ï¥%)$Óf�¾«®]†khÚP§dYÅMöŸÿϬß÷ãÿ­Z>ÿ�;¯úè?•u5®"¼)TpTÖ‡ÕÔœc'Tp¿iñ/üúÍÿ~?úÕM-u¸ï�âÙOçI>QÇ>ÕèÔVqÇ(ÞÔÖ¤ªöÚ(á~Óâ_ùõ›þüõ¨ûO‰çÖoûñÿ֮ꊟ­Ãþ}Ä^Ù*<úmcZ²tûTf<òH±ººÀr¬ÿÇÅŸû­üÅo/ÝJx®WJŒR½ö ¶qŒ’µÅ¢Š+„À(¢Š(¢Š(¢Š(¢Š(¢ŠäÏüŽÿð?ý’ºÊäÏüŽÿð?ý’ºÊÆ�Úõ= Ãþ]…Q[xQEW%ãŸõ_ï?òÖ×%ãŸõ_ï?òçæ¿îsù~h™ü'I§ÿÈ6×þ¸§òf«iÿò µÿ®)ü…Y®Úô)[oøñAüê¥[oøñAüêÀ©EP~¹ÿ +ïúâßʱü ÿ «�úîô[çü€¯¿ë‹*Çð7ü‚®?ë¹ÿÐEtÇøõ¯ó=‚ŠñoíMCþ®ïó�Úš‡üÿ\ÿßæÿ�íø#ûÏ;ÚÓEx·ö¦¡ÿ?×?÷ù¿Æ�íMCþ®ïó�ÛðþG÷‡´=¦²©_ùX{�ŒÏÿÈRÓþ¹ÿìÕÐ×!¯êÖúµõ¼¶ë"ª.Ó¼Î}‰®¾¶ÅÅÂ�8Ë}M*¦¡Š(®œ(¢Š(¢Š(¢Š(¢Š(¢Šäí¿äuo÷ßÿA5ÖW'mÿ#«¾ÿú ®²±¡³õ= Çâ§þú…Q[xQ\f¥«ë2x†[ >C�v¤j«ÎO'ñ§lñ§üó›þùŽ¼ÇšC™Æ0“³¶‹þ çc\w޾õ‡ÒOý–�ž4ÿžsß1Õ;í#ŎϵÚË/—�¹Ø1ž½>•ÇŽÆgÿ€ÿÁ:ÿȽ{ÿ\ÿ¨¬ÿÿÈOúîßÉk*âÓÆ7vïðÌñ8Ã.#¨ì´ßéðmmåŽ2ۈ¥j©%IÙoÜáž:OG²�”mðêw´W³ÆÿóÎoûæ:6xßþyÍÿ|ÇY}[ûËï;¿¶üùŸþÿí(®GÃ:Î¥s«Og.ðˆÄ‚ `@í]?Û-çæûø+9Ò”%˹߃ÅGOÚA4¶ÔžŠƒí–¿óóýü}²×þ~aÿ¿‚£’]Ž®VsºGüŒ÷_Y?ô*êk“Ò¦�‚½Ô?çòÛÿÿ ?á^êóùmÿ�…z-ÿ±°�ŸÞ‘<ëþî¡ÿ?–ßø÷øQÿ ÷PÿŸËoü{ü+Ñh£û ÙýáÉοá^êóùmÿ�…TÔüy¥éÒÞËs¤XÊ®rr@ô÷¯P¬?È«{ôOý kFS……Î)Ý&÷ò‚±ç7ÿò.é_õÒæ•è:»(eÓ.È# ˆ[ŸÒ§¿ÿ‘wJÿ®“ÿ4¯\´ÿ�8?ëšÿ*÷òêΖ�–èù‰å°Çc«)I«rþ(ñßì cþ�wŸ÷å¿Â�ì cþ�wŸ÷å¿Â½¢Šéú컫T�þ‹ÿ`kô ¼ÿ¿-þ`kô ¼ÿ¿-þíQõÙvõj�ó¿Àñì cþ�wŸ÷å¿Â§ÐÕ’]EXËjÀƒØïJöòkù k?õÊOýµ½ î«ÕvüÌá•Ã�øɻÈí|,i£8gU>spN; è<øç¬÷Я%¢ºjåʤÜù·ò>âxni7sÖ¼øç¬÷УχþzÇÿ} òZ+?ì¥üÿ‡ü~©æzןüõ�þúyðÿÏXÿï¡^KEÙKùÿø!õO3§ñK«ø†Ð£ZrŒ×G^umÿPÿ¾¿Î½°ÇÓöq„;&gˆ�*Š (¢¼Ó˜(¢Š(¢Š(¢Š(¢Š(¢ŠÀ³Õn¦ñ ÖnÊaVpÞxéÍo×'¦ÿÈßqþü•ÖVT[iß¹Ý�„a8¨«{¨(¢ŠÔá (¢€ â¼qÿVî7óÚ×ã�øú³ÿq¿˜¯38ÿt—Ëó" Ú‚–�tµé–noøõOªU¹¿ãÕ? ©EP?Š¿ä[¼ú/þ†*¿ƒä__úèÕcÅ_ò-Þ}ÿC_Á¿ò/¯ýtjé_îï×ô£ÿE׉˜¤êA?ç‰ÝŠÿs£êÿ3±ÿ„WCÿ |›�ðŠèô�óoñ­Š+Ôú­ä_r8,ŒøEt?úÇù·øÑÿ®‡ÿ@øÿ6ÿØ¢�ªÐþE÷ ²1ÿáÐÿèæßãY¾ ðî“i ÞO’$¨™Vðr=몬�ȳÿ\ÿ¨¬q8j*ŒÚ‚Ùô]„Ò±æ—?ò+Yÿ×Ü¿ú W iþÑeÓmd“O��áFc“É {ןÜÿÈ­gÿ_rÿè)^¯¥ÿÈ&Ëþ¸'þ‚+«'¾�ŸCÄ¡F�L·´ŠzGu~…øDô/úGù·øÑÿž…ÿ@èÿ6ÿÙ¢¶ö“îÏSêxoù÷¹ßð‰è_ô�óoñ£þ= þ�Ñþmþ5³EÒ}Ø}O ÿ>ã÷#þ= þ�Ñþmþ5ÀZD�kú¼Q¨XÑ'UQØÀëå0ÿÈÉ­}.?ô*ëÂÊRnï±æã(R§ŠÃ:qKÞè¬Oc£_ê14¶°ùˆ­´�ê9üMYÿ„[XÿŸAÿSük¡ðWü‚çÿ®ÇÿAÒ×N#0«N«‚JËúî}=LD£&‘ç?ð‹kóè?ïê�ð‹kóè?ïê�z5�ö¥nËñÿ2>µ?#ÎáÖ?çÐßÔÿ?áÖ?çÐßÔÿôj(þÔ­Ù~?æZŸ‘å·zuÖ›qwQùlß0�ã>ÕßW=ã?ù Z×?ýšº1µJtæ÷w òrŒ[ (¢¼ã˜(¢Š(¢Š(¢Š(¢Š(¢Šäí¿äuo÷ßÿA5ÖW'mÿ#«¾ÿú ®²±¡³õ= Çâ§þú…Q[yÇXÿÉIõÑ¿ôY¯E¯:±ÿ’’?ë£è³^‹^^Wµ_ñ¿Ðˆu (¢½BŠ(  oȯ}þàÿÐ…yµçü‹:wý|Oü’½'ÅŸò+߸?ô!^myÿ"Î�ÿ_ÿ$®:ò7‡ø_êyßûœþ_š=jÃþAÖ¿õÅ?�«^ÃþAÖ¿õÅ?�«Ú÷=Jô (¢‘aEP”Z5ÝkÜ›ÿC±¡øq5{'¸k–ˆ¬…0=�õ÷¬kOùk_îMÿ¡Ší|ÿ y¿ëàÿè+^ÌêJ�(;= †N8)5üÌ­ÿ<_óüÿ÷ì�ðƒÅÿ?Ïÿ~Çø×YEpý{üß‘êûz�ÎOþx¿çùÿïØÿ?á‹þŸþý�ñ®²Š>½ˆþoÈ=½Nç'ÿ<_óüÿ÷ì�bêºHÑõ;xRc&àq\cœJôjâ¼_ÿ!»?úæ¿ú®¬*­Jœ³wVf´jÎR³gCEW”rQ@Q@Q@Q@Q@rv_ò9KþüŸÈ×Y\�—üŽRÿ¿'ò5�mãêz‚¯øYÖQE±ç…qú_ü”ƒþüŸú®Â¸ý/þJAÿ~Oý×™˜üTƈŸCÑ(¢ŠôË (¢€ Ãñ‡üŠ·¿DÿÐÖ·+Æò*ÞýÿCZçÆ»Ôÿ ü…-�9¿ÿ‘wJÿ®“ÿ4¯\´ÿ�8?ëšÿ*ò;ÿùt¯úé?óJõËOøóƒþ¹¯ò­pŸò/¡èxø/÷üGý»ùQEg²QEäÖòÖ딟ú1kÖkɬ?ä)¬ÿ×)?ôb×n wòüÏ+þù†ÿýÓÂC.Ží$Q¹ó˜e”·þÇmÿ>ðÿß±<ÿ Wÿ®íü…t5¹?o-zžÕfùÙØí¿çÞûàQö;où÷‡þø5ÏÍ.æwd?c¶ÿŸxï�GØí¿çÞûàTÔQÍ.ávpþ(Ž8¼Ah±¢ òÐáF?Œ×I\÷‹?äb³ÿ®iÿ¡µt5׊þ/Cj¿BŠ(®#¢Š(¢Š(¢Š(¢Š(¢Š(“Óäo¸ÿ~Jë+“Óäo¸ÿ~Jë+?SÐ̉𠢊+cÏ (¢€ â¼qÿVî7óÚ×ã�øú³ÿq¿˜¯38ÿt—Ëó" Ú‚–�tµé–noøõOªU¹¿ãÕ? ©EP?Š¿ä[¼ú/þ†*¿ƒä__úèÕcÅ_ò-Þ}ÿC_Á¿ò/¯ýtjé_îï×ô-³Ïú‰ÿ!þ5¯ÿ ë¯úâÿÈÖ7ƒ¬-/-®šæÚ9Jº€]sŽ+’—2ŒOC J‹£:µSv¶Ã¿á-³ÿžþCühÿ„¶ÏþxOùñ®�ûJÿ }¿ýð(þÃÒ¿èoÿ| 9j÷Aí0?Èþó�‹TŠ?@£ùe˜íã<ŒVßü%¶óÂÈ�tØzWýíÿï�Gö•ÿ@ûûàTÆ�HìÍjâ°•ZrƒÑ[sœÿ„¶ÏþxOùñ¡|YdX àzàqú×Gý‡¥Ð>ßþøÉøÆÊÖÊ[AmqVݱqž”¦êÂ<Í•‡†½EME«ù•¬?TŽ…ÛÿEšôZó�7þJ,ï7þ‹5èõÉ•íWüoôvŒžT�ë^Vg%FRÙI>‡§Q\×ü'Z/÷çÿ¿tÂu¢ÿ~û÷]__ÂÿÏÅ÷�™w:Z+šÿ„ëEþüÿ÷î�øN´_ïÏÿ~èúþþ~/¼9—s¥¬?È«{ôOý j·ü'Z/÷çÿ¿u™âiz–…sinÒ™d ·r`pÀÿJÃ�Ãʄ⦮ÓëäJÇ+ÿ"î•ÿ]'þi^¹iÿp×5þUäwÿò.é_õÒæ•ë–Ÿñçýs_å]øOùÐô<Œûþ#þÝü‰¨¢Š³Ù (¢€ òkù k?õÊOýµë5äÖòÖ딟ú1k·»ù~g•�ÿ|Éþ‡qàÏù¿ýwoä+¡®{ÁŸòúîßÈWCYbÿ�/SÙ­ñ°¢Š+œÌ(¢Šâ¼Yÿ#ŸýsOý «¡®{ÅŸò1Yÿ×4ÿÐÚºíÄÿ —¡½_‚!EW€QEQEQEQEQEÉé¿ò7Ü¿%u•Éé¿ò7Ü¿%u•� Ÿ©èf?Ä�øPQE±ç…Q@q^8ÿ�«?÷ùŠíkŠñÇü}Yÿ¸ßÌW™œºKåù‘?„íAKH: ZôË ·7üz§áU*ÜßñꟅT¢Š(Å_ò-Þ}ÿC_Á¿ò/¯ýtj±â¯ùï>‹ÿ¡Š¯àßù×þº5t¯÷wëú<¿ämð~§AEW1ìQ@Q@·‡ÿä=wþãÿèBºšå¼?ÿ!ë¿÷ÿBÔ×n?ø¿$oˆøÂŠ(®#¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò�üŽööÇÿEŠßñßú‹/÷Ÿù ÀƒþG{ûcÿ¢Åx¹—ÅñGõ;±?îT½Yé´QE{GQEVoˆä^Ô?ëƒÿ*Ò¬ßÿȽ¨×þU–#øRô�žÇ—Éÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¼¶Oùþ¿�þ€+Ô´/ùôßúõ�ÿAeÿò-¥ó,ÿÝoæ+y~èúWm÷z_?ÌÞ§ðãóŠ(®#¢Š(¢Š(¢Š(¢Š(¢Š(“?ò;ÿÀÿöJë+“?ò;ÿÀÿöJë+?kÔô3ùuþQElyáEP\—ŽÔY¼ÿÈW[\—ŽÔY¼ÿÈWŸšÿ¹Ïåù¢gð�&Ÿÿ Û_úâŸÈUš­§ÿÈ6×þ¸§òf»iü Фm¿ãÄ}óª•m¿ãÄ}ó«¥Q@úçü€¯¿ë‹*Çð7ü‚®?ë¹ÿÐElkŸò¾ÿ®-ü«Àßò ¸ÿ®çÿAÓàKÔñëÈÒŸøYÔQEÌ{EPEP-aÿ#tßïÉýk©®ZÃþFé¿ß“ú×S]¸ïŽ?áFõ÷^�EW€QEQEQEQET¿ñãqÿ\›ùTõïüxÜ×&þTžÅCâF_�?Ôß¼ŸÖºúä< þ¦ûýäþµ×Öt?†ŽÌËýê/ÉQZœ!EPãζöÓÿe¬‹ù(0}Gþ‹­u°ÿ¶Ÿû-dXÿÉAƒê?ô]x¹‡ñaþ8�د÷J>¯ó=&Š(¯há (¢€ ÈñGü‹7ÿõÏúŠ×¬�ȳÿ\ÿ¨¬1_ÀŸ£ü„ö<ÒçþEk?úû—ÿAJõ}/þA6_õÁ?ô^Qsÿ"µŸý}Ëÿ ¥z¾—ÿ ›/úàŸú«ÁȺ�¡ãá?äc[Ò?‘nŠ(­d(¢Š+Êaÿ‘“Zú\èUêÕå0ÿÈÉ­}.?ô*ìÁîþG“˜¼á¿Äv> ÿ�\ÿõØÿè"ºZæ¼ÿ ¹ÿë±ÿÐEtµÏãÈöë…Q\ÆAEPã?ù Z×?ýšºç¼gÿ!KOúçÿ³WC]¸�àRù›Ôø"QEqQ@Q@Q@ïÿäuÿ\_ùÎð/üzÞ¾¿ÈÖ�ÿüƒ®¿ë‹ÿ#YÞÿ�[Ï÷×ùÆ_ʼnèQÿr©ê޶Š(­�<(¢Š+‹ñßúë÷_úWi\_Žÿ×XÿºÿÒ±Ä �ùgûÔ~“34ßù(±ÿ¼ßú,ףלi¿òQcÿy¿ôY¯G®¯á«þ7útw~¡EW¨PQE�âÏùï¿Üú¯6¼ÿ‘gNÿ¯‰ÿ’W¤ø³þE{ï÷þ„+ͯ?äYÓ¿ëâä•ÇCþFðÿ ýO#;ÿsŸËóG­XÈ:×þ¸§òb«ØÈ:×þ¸§òb»^ç©Oà^�ER,(¢Šò{Oùk_îMÿ¡Ší|ÿ y¿ëàÿè+\U§ü‡5¯÷&ÿÐÅv¾ ÿ�<ßõðô¯Z¿û¼½Qçdî2ÿ::(¢¼“Ñ (¢€ â¼_ÿ!»?úæ¿ú®Ö¸¯ÿÈnÏþ¹¯þ„k·/þ7É›áþ3¡¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š+“²ÿ‘Ê_÷äþFºÊäì¿är—ýù?‘¬koSÐÀüÂβŠ(­�<+:çBÓ/'içµV‘º¶â3ùÑ¢¢táQZi5湓ÿÎ�ÿ>Cþûoñ£þ�þ|‡ýößãZÔV_TÃÿϵ÷!r®ÇâÍ6ÓN’ÔZB#¶œã¦ºXü5£´jM˜ÉýöÿÄñÏúë/÷_úWaú”ÿtW�†ÃÑxºÑpV\¶Ñv!%ÌÌÏøFtùò÷Û�ðŒèÿóä?ï¶ÿÖ¢½ªaÿçÚû‘|«±ÆøêÒ +M" h–8•d!G¾Úô Oøóƒþ¹¯ò®â'ÜÒ¿Ý“ÿd®êÓþ<àÿ®kü«ÐšQ¡¶Ôò0Ÿò1ÄÛ¿‘5Q\ç°QEäÖòÖ딟ú1kÖkɬ?ä)¬ÿ×)?ôb×n wòüÏ+þù†ÿýãÁŸòúîßÈWC\÷ƒ?ä ÿõÝ¿�®†²Åÿ^§³[ãaEW9˜QEÅx³þF+?úæŸúWC\÷‹?äb³ÿ®iÿ¡µt5Û‰þ/Cz¿BŠ(®#¢Š(¢Š(¢Š(¢Š(¢Š(“Óäo¸ÿ~Jë+“Óäo¸ÿ~Jë+?SÐ̉𠢊+cÏ8ýCÄÚšjóÙÙÛÆâ6*ª³u<�ûÄô?ø ÿãRh¿òQ%ÿ~_äkÑ+ÃÃS¯‰çŸµjÒhÍ&úžoý¿â?úüñ¬ÝQõ�Yã{�>`c �0ë^µEkS,©V<³¬Úƒ}O7þßñý�þ=Ûþ#ÿ qÿÀgÿôŠ*þ¡_þÈ9_sÍ%ñ.¿ fIl–4Yà`ãšèí|Olþµ»ÔeŽ $f@»iÆ@äúU¯ÿÈ«yõOý kÎõùi?Y¿ô!U�§V8õ‡�G$ãÄáÌ1SÂP•XêÕ·õ±ÛÂU¢ÿÏèÿ¿oþÂU¢ÿÏèÿ¿oþ,~Ñ$cÙ* ýé§ ¡ÿÏ9¿ïé¯nØ~ïð0SÍ_H~&/ˆ™7ú‰?Ý?ʆ8îŒ?}ûÿ¤û5vuÆxïßý#ÿÙ«³¬pÿÃGvgþõ/—䂊(­Ž¢Š(‘ñßú‹/÷Ÿù å®ï³¼Kç—æy) lÎ3ò/zê|wþ¢ËýçþB¹Kû7Ô,ÿÝoæ+y~èúV�ÿãâÏýÖþb·—î�¥v×ÿw¥óüÍê?1h¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€93ÿ#¿üÿd®²¹3ÿ#¿üÿd®²±£ö½OC0ÿ—_áAEVÇžQEÉxçýE—ûÏü…uµÉxçýE—ûÏü…yù¯ûœþ_š& Òiÿò µÿ®)ü…YªÚüƒmëŠ!Vk¶ŸÀ½ AVÛþ$eøýM÷ûÉýk¯¯,Óu«Í%d[V@$ ¶åÏOÿ]_ÿ„ÃWÿž‘ß±\”«Æ0IžÞ3-­Z´ªFÖäz%çð˜jÿóÒ/ûö(ÿ„ÃWÿž‘ß±Z}f7öF#Ëïÿ€z%çð˜jÿóÒ/ûö(ÿ„ÃWÿž‘ß±GÖ`Ù�/¿þ¥ãζöÓÿe¬‹ù(0}Gþ‹ªš–±w«y_jd>^ví\uÆ•[±ÿ’ƒÔèºòñ²Rœþx‹1£*8zTåºlôš(¢½ÃÌ (¢€ ÈñGü‹7ÿõÏúŠ×¬�ȳÿ\ÿ¨¬1_ÀŸ£ü„ö<ÒçþEk?úû—ÿAJõ}/þA6_õÁ?ô^Qsÿ"µŸý}Ëÿ ¥z¾—ÿ ›/úàŸú«ÁȺ�¡ãá?äc[Ò?‘nŠ(­d(¢Š+Êaÿ‘“Zú\èUêÕå0ÿÈÉ­}.?ô*ìÁîþG“˜¼á¿Äv> ÿ�\ÿõØÿè"ºZä|%ii§L—1DÆ\€ì#ºí�3þíÿïà£Nn¼šL÷+E¹½ ÔUí�3þíÿïà£ûgLÿŸûûø+ŸÙOùYŸ,»¨ª?Û:güÿÛÿßÁGöΙÿ?öÿ÷ðQì§ü¬9eØæ§SÈ?Ö,'g÷Á#´ÿ�æµþäßú®×Á_ò›þ¾þ‚µÁèÒ´÷šŒÏ�ò[ÈÍ�RÀ×yà¯ùÍÿ_ÿAZëÄ+aä¼ÑÙ�ÉK/“_ÌÎŽŠ(¯$ô‚Š( ¸¯ÿÈnÏþ¹¯þ„kµ®+Åÿò³ÿ®kÿ¡íËÿ�òføŒèh¢Šâ0 (¢€ (¢€ (¢€ ¯¨;G¦Ý:¬°¹v85bªê_ò ¼ÿ®ÿ šRÙ—Kã^§)¤h—šÌRKÒ FÚw±æ´á Ô¿çúͿ®øþ¯jb;¯¸ó-[M¼Ðæ„IrœS1]Èè+�ñ×ü}Yÿ¸ßÌWB: TRŒä—‘xꎥ S–îÿ ´QEtaÆxçýu—û¯ý+°‹ýJº+�ñÏúë/÷_úWaú”ÿtW—…ÿ}¯ÿnþD/‰�¢Š+Ô,äþ"}Í+ýÙ?öJííe�ìp~ñ?Õ¯jÄñ7‡ÿ·--n<—€er`?¹Ÿø@åÿŸôÿ¿Gük­{9ÓŒe+5sÂ’Åáñ•jҥΥn©l�Gó£ÿž‰ÿ} <èÿç¢ßB¼ãþ9çý?ïÑÿ«©xBM;OšìÞ+ˆÀ;DxÏ8õ÷©Ti7e?À¹æèEÎX}¿=GÎ�þz'ýô(ó£ÿž‰ÿ} ò�Âï«Øý¥n–!¼®Ò™éøÖ‡ü rÿÏúߣþ4åF”]œÿSÌqµ`§ =Óþò=Î�þz'ýô+Ê4þu=gþ¹Iÿ£´?á—þÓþýñ©âðÑѬo®äJÍÀ`¸_a[Pöp•”¯vºyŠ+‰ÅÑ•J\ª.û¦t^ ÿ�+ÿ×vþBºç¼ÿ Wÿ®íü…t5Ï‹þ<½O ­ñ°¢Š+œÌ(¢Šâ¼Yÿ#ŸýsOý «¡®{ÅŸò1Yÿ×4ÿÐÚºíÄÿ —¡½_‚!EW€QEQEQEQEQEÉé¿ò7Ü¿%u•Éé¿ò7Ü¿%u•� Ÿ©èf?Ä�øPQE±çœ~‹ÿ%_÷åþF½¼ïEÿ’‰/ûòÿ#^‰^^Uü:Ÿâ¡êQEz……Q@>3ÿ‘VóêŸú×�ê?òÒ~³èB½Æò*Þ}SÿCZó½Gþ@OÖoýW&þFñÿêÏ<ÿsŸËóG¯Ãþ¢?÷Gò§Ó!ÿQû£ùSë¬ö#² (¢�…Q@W Ü›=ST¸U R6À>»À­hüCªÊ»£³�צV6#ùÖ›ÿ:Çýs?ú1k¼ðwü€Ïýuoé^½Og n¤£wt¿ÏÈ9V™«ûÌÃþÜÖ?çÁïËÿ�ÛšÇüø/ýùñ®îŠåúÍ/ùô�_ÚÃùO5³—Q²»’æ;7/ †‰±ÉÏô«ÿÛšÇüø/ýùñ®îŠ©ã!7ySLn´dîâpŸÛšÇüø/ýùñ¢ߋȡ¸¶�°me8'ä×w\O‰ÿäg´ÿr?ýÖ”'F´œ=šZ2©¸M۔訢ŠóP¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò�üŽööÇÿEŠßñßú‹/÷Ÿù ÀƒþG{ûcÿ¢Åx¹—ÅñGõ;±?îT½Yé´QE{GQEVoˆä^Ô?ëƒÿ*Ò¬ßÿȽ¨×þU–#øRô�žÇ—Éÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¼¶Oùþ¿�þ€+Ô´/ùôßúõ�ÿAeÿò-¥ó©_ùX{)ö3tc ŒŽõ'ög�½dÿ¿Ñÿ�w:?ü�,?ëÚ?ýUÚÑâvå_qÍO)Œ ¤êÏUüßð6—Gñœð¼R‰7e3GÈüê+Oø¶Æ6ŽÖ&‰î!f�“ù×§QKëRµ¹WÜ$¤åÌêNýïÿóŸìÏzÉÿ£ÿ?³Áý¡‰þsÎ|G¡Ã¢›o&Y$ówg~8Æ=>´Ëù(0}Gþ‹­u°ÿ¶Ÿû-d_húÀÖ>ß§Çœª²H® �”Ôד�„“‹§ùee©®:¤êahÎZ»¿Ìôš+οâ´ÿž’ÿßÈÿÆ�ø­?礿÷ò?ñ®�í)Ï™ýÇ—Íäz-å÷ÚŸŠ4Ñ»º–?3;~d9Ç^ŸZ´�ã9]e”«Aó#éùÔ,Õ98ªRºé`çò=²×ây™¶ÔõH’±Ã*zœ0Úx>æt™VYãF3“†p6­qöŸòÖ¿Ü›ÿC {£í鸷m�8vš– Qþó=[íÖóõýü}ºÏþ~ ÿ¿‚¼¦ŠÏû*?Ì{T]ÏVûuŸüýAÿn³ÿŸ¨?ïà¯)¢�ì¨ÿ0}Qw=[íÖóõýüÇøªh¦Ö­)ÀE«üF¹š’õñÿ¼?�kG¨Ë�J傃½ÏF¢Š+À<ð¢Š(¢Š(¢Š(ªº—ü‚¯?ëƒÿè&­U]KþAWŸõÁÿôJ[3J_Ä�ª)xþ3ÿ‘VóêŸú×�ê?òÒ~³èB½Æò*Þ}SÿCZó½Gþ@OÖoýW&þFñÿêÏ<ÿsŸËóG¯Ãþ¢?÷Gò§Ó!ÿQû£ùSë¬ö#² (¢�…Q@I¦ÿÇαÿ\ÏþŒZï<ÿ 3ÿ][úW¦ÿÇαÿ\ÏþŒZï<ÿ 3ÿ][úW­ˆÿw~«ò<ì‹þEßöó7袊òOD(¢Š+‰ñ?üŒöŸîGÿ¡í«‰ñ?üŒöŸîGÿ¡íÀú3|?Åò:*(¢¸ŒŠ( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5Ià&F>dc$õ47�ç¤÷ÕAÿž‘ÿßT 7�ç¤÷ÕAÿž‘ÿßT 7�ç¤÷ÕAÿž‘ÿßT 2oõº•Yòüô�þú¨ç€ýžOÞG÷Oñ{PÇÑÏxïßý#ÿÙ«³®3ÀŸ~ÿéþÍ]�c‡þ;³?÷©|¿$QElpQ@�ŽÿÔY¼ÿÈVò;ØÛý+Çê,¿Þä+·Ç ñOúæ+Å̾(ÿŠ?©Ý‰ÿr¥êÏL¢Š+Ú8BŠ( ³|Cÿ"ö¡ÿ\ùV•fø‡þEíCþ¸?ò¬±—£ü„ö<¾Oùþ¿�þ€+Ô´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú£/ÿ‘m/™ãaäeWü(ТŠ+SÚ (¢€ òãÿ#–«ô¸ÿÐMz�yv3ã=[�8¸<ÿºk¯ ¼½'2þ6ühK=.÷PF{X Ч Añ5gþ½_þ|›þû_ñ®ƒÁñçuÿ]ò®¦»±…JU\ZGS(ÉÅmÿÞ¯ÿ>Mÿ}¯øÑÿÞ¯ÿ>Mÿ}¯ø×¤ÑXjUì¿ó3úÔûmÿÞ¯ÿ>Mÿ}¯øÑÿÞ¯ÿ>Mÿ}¯ø×¤ÑGö¥^Ëñÿ0úÔûWy§]éì‹u Œ¸%rAÏå]úýÑô¬ÿÇÅŸû­üÅtkØ?yOïRÆÕuiS›ëp­'(FOÌŽŠ›È?óÒ?ûê� ÿÏHÿïªóŽb*o ÿÏHÿïª<ƒÿ=#ÿ¾¨*o ÿÏHÿïª<ƒÿ=#ÿ¾¨*o ÿÏHÿïª<ƒÿ=#ÿ¾¨*o ÿÏHÿïª<ƒÿ=#ÿ¾¨*o ÿÏHÿïª<ƒÿ=#ÿ¾¨�?ò;ÿÀÿöJë+–)ÿÖÍË÷úç�¹]�ç¤÷ÕcGízž†aÿ.¿Âˆh©¼ƒÿ=#ÿ¾¨òüô�þú­�<¥5í¥»ìžê›Úò?­Gý«§Ïý¯ýþ_ñ®CT°]CÇOe$…VFE,¼ãäŠÜÿ…ygÿ?Óÿß"¼˜ã1U'5Jšj-­ûÌÞÈÓþÕÓ¿çþ×þÿ/ø×/ã+»k˜mJU›>[†ÇOJÕÿ…ygÿ?Óÿß"�øW–óý?ýò+,JÇb):NšWóæjÖ-Øêv §Û+_[( ʹÞ¬jéßóÿkÿ—ük3þåŸüÿOÿ|Š?á^YÿÏôÿ÷È­£W—²_xï.ÆŸö®�ÿ?ö¿÷ùư|w4Sèút�È’!‘°ÈÀŽž¢“UðE®Ÿ¥ÜÝ¥äÎÑ!`¥F s“ø¤àÿ¯é?ô®œ.»ÆF�h%tÞ÷<ÌâOêUì¿4z¦�ÿ Kúö�ÿAv©hÿò°ÿ¯hÿôWkº_=?Â�¢ (¢¤Ô(¢Šóm/þJÿýuŸÿB5Úפ.ÿˆWã ~ö~Iÿh×uäùéýõ]8Ÿ‰z#ÇɃ?ñH†Š›È?óÒ?ûê� ÿÏHÿïªæ=ƒ�°ÿ‘ºo÷äþµÔ×1§¦|c:î_¿'$ñÞºß ÿÏHÿïªíÇ|qÿ 7¯ºô!¢¦òüô�þú£È?óÒ?û긌h©¼ƒÿ=#ÿ¾¨òüô�þú h©¼ƒÿ=#ÿ¾¨òüô�þú h©¼ƒÿ=#ÿ¾¨òüô�þú h©¼ƒÿ=#ÿ¾¨òüô�þú j ßøñ¸ÿ®Müªï�ç¤÷ÕW½€‹ ƒæGþ©»ûOb¡ñ#ÀŸêo¿ÞOë]}rÿS}þòZëë:ÃGfeþõ?—䂊(­N¢Š(�ñç[ûiÿ²ÖÔñïûƒùV/�:ØÛOý–·íà&Ú/ÞG÷ñ{V0þ,¾G¡ˆÿt£ÿo~bQSyþzGÿ}Qäùéýõ[yÅxëîXý_ÿe®¦Ïþ.¹]Ê0òòOk· ðTô7¥ðËÐé詼ƒÿ=#ÿ¾¨òüô�þú®#*o ÿÏHÿïª<ƒÿ=#ÿ¾¨*o ÿÏHÿïª<ƒÿ=#ÿ¾¨*o ÿÏHÿïª<ƒÿ=#ÿ¾¨*o ÿÏHÿïª<ƒÿ=#ÿ¾¨*o ÿÏHÿïª<ƒÿ=#ÿ¾¨�ÿüƒ®¿ë‹ÿ#YÞÿ�[Ï÷×ùÖÔ #Lº>d|Býý�døþ=o?ß_äk'¡Gýʧª:Ú(¢¶<ð¢Š(®/Çë¬Ýé]¥q~;ÿ]cþëÿJÇü6wåŸïQùþLÌÓä¢Çþóè³^�^s§�¿�d™º×3^�\9_ÃWüoô<èîýBŠ(¯P ¢Š(ÅŸò+߸?ô!^myÿ"Î�ÿ_ÿ$¯IñgüŠ÷ßîýW›^ȳ§×ÄÿÉ+އü�áþúžFwþç?—æ�Z°ÿ�u¯ýqOä*ÅW°ÿ�u¯ýqOä*Åv½ÏRŸÀ½Š(¤XQEäöŸòÖ¿Ü›ÿCÙø24m"bȤùç¨ÿek�³×5¾@ÄsßÚx+þ@ó×ÁÿÐV½jÿîòõG�‘¸ËüLè<˜¿çšß"�&/ùæŸ÷ȧÑ^UÙèÜg“üóOûäQäÅÿ<Óþùú(» Œòbÿžiÿ|Šã3¹]Ê>yy'Žõ×ùþzGÿ}V46~§¡˜ÿ?áD4TÞAÿž‘ÿßTyþzGÿ}VÇžq:/ü”Iß—ùôJóÍmø‹0È8yz} zyyWðê‰þ„C¨QEêQE`øÏþE[Ϫèk^w¨ÿÈIúÍÿ¡ ôOÿÈ«yõOý kÎõùi?Y¿ô!\˜oùÇü«•ƒãøø³ÿu¿˜­åû£é]µÿÝé|ÿ3zŸÃ�ÌZ(¢¸ŒŠ( Š( Š( Š( Š( LÿÈïÿÿÙ+¬®LÿÈïÿÿÙ+¬¬hý¯SÐÌ?å×øPQE±çœwüÔ˜ÿë¢ÿè±^‹^uÿ5&?úè¿ú,W¢×—–üU¿ÆÈ�P¢Š+Ô,(¢ŠÊñ'ü‹wÿõÄ×™Mÿ"¤õý'þ€•é¾$ÿ‘nÿþ¸šó)¿äTƒþ¿¤ÿи©ÈÚŸø_êy9Ïûœý?Tz®�ÿ Kúö�ÿAv©hÿò°ÿ¯hÿôWk¾_=?Â�¢ (¢¤Ô(¢Šóm/þJÿýuŸÿB5Ú× k1·ñ®«01µÃ{àšÐ‹[Önh-¼Å¤%€ü«Ñžu]ã²Hòò*R� µüìêè®cûO_ÿŸ?ð¨þÓ×ÿçÆOüjÏê;¯¼öý„»¡¶ò7MþüŸÖºšâ¢]Zö½[üÖ$œÀØæ¯iëÿóã'þµtâp²©$âÖ‰-Í*ÒrjÏ¡ÓÑ\Çöž¿ÿ>2à;To¯j¶Ò ¹·;^2¤ŠçX ¯f¾ó?«ËÈê袊á0 (¢€ (¢€ (¢€ ‚÷þ¨¥àoøñºÿ®£ùWW\§�¿ãÆëþº�å]]gCøhéÌ?Þgýt (¢µ8‚Š( 'Ç_ñõgþã1]è+žñ×ü}Yÿ¸ßÌWB: ÆŸñ%ò= Oû­û{óŠ(­�<ã¼p¬ÓYmR~Wè>•×Eþ¥?Ýú+––ÙÖ�[üVü•�Š(®¡–åÿ�Dú ©Våÿ�Dú ©@dø›þEËÏ÷Gþ„+Z²|Mÿ"åçû£ÿBt¾8úœØß÷jŸá‘OÁò?õÙ¿¥tUÎø/þ@'þ»7ô®Šª¿ñ$e–¹ÓôAT5¯ùÜÿ¹ýjýPÖ¿äsþçõ¢�ñcê�BàÏù¿ýwoä+¡®{ÁŸòúîßÈWCW‹þ<½J­ñ°¢Š+œÌ(¢Šâ¼Yÿ#ŸýsOý «¡®{ÅŸò1Yÿ×4ÿÐÚºíÄÿ —¡½_‚!EW€QEQEQEQEQEÉé¿ò7Ü¿%u•Éé¿ò7Ü¿%u•� Ÿ©èf?Ä�øPQE±çœ~‹ÿ%_÷åþF½¼ïEÿ’‰/ûòÿ#^‰^^Uü:Ÿâ¡êQEz……Q@>3ÿ‘VóêŸú×�ê?òÒ~³èB½Æò*Þ}SÿCZó½Gþ@OÖoýW&þFñÿêÏ<ÿsŸËóG¯Ãþ¢?÷Gò§Ó!ÿQû£ùSë¬ö#² (¢�…Q@I¦ÿÇαÿ\ÏþŒZï<ÿ 3ÿ][úW¦ÿÇαÿ\ÏþŒZï<ÿ 3ÿ][úW­ˆÿw~«ò<ì‹þEßöó7袊òOD(¢Š+‰ñ?üŒöŸîGÿ¡í«‰ñ?üŒöŸîGÿ¡íÀú3|?Åò:*(¢¸ŒŠ( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š)“¨“ýÓü©ôÉ¿ÔIþéþT1Çtaøïßý#ÿÙ«³®3ÀŸ~ÿéþÍ]�c‡þ;³?÷©|¿$QElpQ@�ŽÿÔY¼ÿÈVò;ØÛý+Çê,¿Þä+ùì?í�þ‹âæ_ÅÔîÄÿ¹Rõg¦ÑEí!EPY¾!ÿ‘{Pÿ®ü«J³|Cÿ"ö¡ÿ\ùVX�áKÑþB{_'üЉÿ_Çÿ@êZü‹úoýzÇÿ ŠòÙ?äTOúþ?ú¯Rпä_ÓëÖ?ýQ—ÿȶ—Ìñ°¿ò2«þhQE©íQ@yqÿ‘ËUú\è&½F¼¸ÿÈåªý.?ô]xMåèy9—ñ°ÿãGQà�øóºÿ®ƒùWS\·‚?ãÎëþºå]M,oûÄ�n¿ñQEÊdQEqž7ÿ�‹?÷[ùŠÞ_º>•ƒãøø³ÿu¿˜­åû£é]µÿÝé|ÿ3zŸÃ�ÌZ(¢¸ŒŠ( Š( Š( Š( Š( LÿÈïÿÿÙ+¬®LÿÈïÿÿÙ+¬¬hý¯SÐÌ?å×øPQE±çœwüÔ˜ÿë¢ÿè±^‹^uÿ5&?úè¿ú,W¢×—–üU¿ÆÈ�P¢Š+Ô,(¢ŠÊñ'ü‹wÿõÄ×™Mÿ"¤õý'þ€•é¾$ÿ‘nÿþ¸šó)¿äTƒþ¿¤ÿи©ÈÚŸø_êy9Ïûœý?Tz®�ÿ Kúö�ÿAv©hÿò°ÿ¯hÿôWk¾_=?Â�¢ (¢¤Ô(¢ŠòÅÿ‘³Zÿ·Ÿæk¬ðOüƒîë¯ôɯü�š×ý¼ÿ3]g‚äsÿ] ¯Z¯û¼¾G�‘ÿºTÿýžŠ(¯$ôBŠ( ¸¿Çå§ýs?λJâümÿ–ŸõÌÿ:íËÿ޾føâ# ¢Š+ˆÀ(¢Š(¢Š(¢Š* ßøñ¸ÿ®Müªz‚÷þ‚ªPY¾ ÿ�ïýr5¥Y¾ ÿ�ïýr5tþ5êsâ¿�?Gù~ÿ�,ßõðô®š¹ŸÈoúø?ú ×MWˆþ,Ž|«ýÊŸ QE‰èQ@rÚgü�w?ïÉüë©®[Lÿ‘®çýù?�vá> ž†ô¾zMQ\FEPEPEPEPEP{ÿù]×þF³¼ ÿ·Ÿï¯ò5£ÿ ë¯úâÿÈÖw�ãÖóýõþF±—ñbzܪz£­¢Š+cÏ (¢€ âüwþºÇý×þ•ÚWã¿õÖ?î¿ô¬qÃg~YþõŸäÌÍ7þJ,ï7þ‹5èõæV÷PYxð\\È#‰îcÛ1‘ýkµÿ„«Cÿ „“…y¹ujpUTä—¾÷~‡šš»õ6(¬øJ´?úGù7øQÿ V‡ÿAÿ&ÿ ô~µCù×ÞŠº6(¬øJ´?úGù7øQÿ V‡ÿAÿ&ÿ >µCù×Þ‚èOȯ}þàÿÐ…yµçü‹:wý|Oü’»oø‡I¼Ð.ííïRI]@UóójƒÂ–¶÷~)qs(¸bŠÖ¹(ׇö¤gt¢öõ8±øgŠ£*1v¿ùÜŽÛâ Œ°Älî DU$ì1ëRÿÂŰÿŸ+ŸÍÆ´?±t¿úÚÿߥ£ûKÿ }¯ýúZöùè+93Jʬ~ã?þ-‡üù\þkþ4ÂŰÿŸ+ŸÍÆ“^Ò´ø4;¹b²·I2cŽEQð†�eu£¼—�Êâf�8À«J‹‡=™Í)æK°þÑ]«ÞÅÿøX¶óåsù¯øÑÿ Ãþ|®5ÿÐþÅÒÿèkÿ~–�ì]/þ�ö¿÷éj9¨+:½†gÿ?c÷.™0¹ÔµYÔ²C+€{À×sà¯ùÍÿ_ÿAZ†þÆÒÓI»6ÖÐÂZ>Lh?•Mà¯ùÍÿ_ÿAZé�ES &»£ÑËp’ÂàÝ9»»ßï::(¢¼Óp¢Š(®+Åÿò³ÿ®kÿ¡íkŠñü†ìÿëšÿèF»rÿã|™¾ã:(¢¸ŒŠ( Š( Š( ªê_ò ¼ÿ®ÿ šµUu/ù^×ÿÐM)lÍ)>¨¥àoøñºÿ®£ùWW\§�¿ãÆëþº�å]]gCøhéÌ?Þgýt (¢µ8‚Š( 'Ç_ñõgþã1]è+žñ×ü}Yÿ¸ßÌWB: ÆŸñ%ò= Oû­û{óŠ(­�<(ªw®Ÿk'—5ä(㪖ä}jÌ3Eq’D="¡T„Ÿ*jáqôQEXåÿ�Dú ©Våÿ�Dú ©@dø›þEËÏ÷Gþ„+Z²|Mÿ"åçû£ÿBt¾8úœØß÷jŸá‘OÁò?õÙ¿¥tUÎø/þ@'þ»7ô®Šª¿ñ$e–¹ÓôAT5¯ùÜÿ¹ýjýPÖ¿äsþçõ¢�ñcê�BàÏù¿ýwoä+¡®{ÁŸòúîßÈWCW‹þ<½J­ñ°¢Š+œÌ(¢Šâ¼Yÿ#ŸýsOý «¡®{ÅŸò1Yÿ×4ÿÐÚºíÄÿ —¡½_‚!EW€QEQEQEQH̨¥˜€ d“Ð ¡ý¹¦ÏÚ~Gü)9%».ç?…6hQYÿÛºgüý§äÂ�íÝ3þ~Óò?áKž=Ëú½oäs0ôßùî?ß’ºÊã,omâñ4×/(³9Øç¥tÛºgüý§ä±£(¤îú�ù…’œybߺºVöî™ÿ?iùð¥MkN‘Â-Ún'9·<{œW­ü�îg=¢ÿÉD—ýù‘¯D¯;Ñä¢Kþü¿È×¢W›•§øŸèsC¨QEêQE`øÏþE[Ϫèk^w¨ÿÈIúÍÿ¡ ôOÿÈ«yõOý kÎõùi?Y¿ô!\˜oùÇü«;ÿQeþóÿ!XÈïaÿlôX­ÿÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,W‹™|QÿS»þåKÕž›EW´p…Q@fø‡þEíCþ¸?ò­*Íñü‹Ú‡ýpåYb?…/Gù ìy|Ÿò*'ýýW©h_ò/é¿õëþ‚+Ëdÿ‘Q?ëøÿè½KBÿ‘Mÿ¯XÿôF_ÿ"Ú_3ÆÂÿÈʯøQ¡EV§´QEåÇþG-Wéqÿ šõòãÿ#–«ô¸ÿÐMuá7—¡äæ_ÆÃÿ�G‚?ãÎëþºå]MrÞÿ�;¯úè?•u4±¿ï=ºÿÄaEW)�QEÆxßþ>,ÿÝoæ+y~èúV�ÿãâÏýÖþb·—î�¥v×ÿw¥óüÍê?1h¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€93ÿ#¿üÿd®²¹3ÿ#¿üÿd®²±£ö½OC0ÿ—_áAEVÇžqßóRcÿ®‹ÿ¢Åz-y×üÔ˜ÿë¢ÿè±^‹^^[ñVÿ"=BŠ(¯P°¢Š(+ÄŸò-ßÿ×^e7üŠ�×ôŸúW¦ø“þE»ÿúâk̦ÿ‘Rúþ“ÿ@Jâ¥ÿ#já©äç?îsôýQêº?ü�,?ëÚ?ýUÚ¥£ÿÈÃþ½£ÿÐE]®ù|Lôhÿ >ˆ(¢Š“P¢Š(ËþFÍkþÞ™®³Á?ò¹ÿ®¿ÐW&¿ò6k_öóüÍuž ÿ�}Ïýuþ‚½j¿îòùvGþéSüoô:z(¢¼“Ñ (¢€ âümÿ–ŸõÌÿ:í+‹ñ·ü~Z×3üë·/þ:ù›áÿˆŽ‚Š(®#¢Š(¢Š(¢Š(¨/ãÆãþ¹7ò©ê ßøñ¸ÿ®Mü©=Š‡ÄŒ¿©¾ÿy?­uõÈxýM÷ûÉýk¯¬è ™—ûÔþ_’ (¢µ8BŠ( 7Ç�l?í§þË[PǼ_îåX¾<ëaÿm?öZÚƒþ=âÿp*ÆÅ—Èô1î”íïÌ’Š(­�<ä)ÿøQÿ Ä¿óâŸ÷ðÿ…nlOî/åFÄþâþU^ßÿ>¿W´§ü¿‰‡ÿ Ä¿óâŸ÷ðÿ…ðœKÿ>)ÿøU=!Añ5Ð c2qÿ®£bq*Ú»ÃÒ’�³¾—Ý—QÓƒ·/âaÿÂq/üø§ýü?áY:ŽªúÖ¥o/�#eÂSœóŸë]–ÄþâþT¡…ý*!‹£MóB�Ÿ©1«ê£ø‹EWžs…Q@Q@Q@UÔ¿äyÿ\ÿA5jªê_ò ¼ÿ®ÿ šRÙšRþ$}QÊh¾!“F‚X’Ýe6ì–Æ8­?øN¦ÿŸÿïáÿ ÊѼ=6³ ’G:F#m¤0'5§ÿ5×üþCÿ|šá‡¶å÷v>ŠºÀ{Gí~.»Žÿ„êoùñ�þþð£þ©¿çÆ?ûø›ÿ5×üþCÿ|š?áºÿŸÈï“Uûó+ež_ˆïøN¦ÿŸÿïáÿ ?á:›þ|cÿ¿‡ü)¿ðƒ]Ïä?÷É£þk¯ùü‡þù4~ü-–y~&N·­>µ,Nð¬^X#³œ×r: á5�MH’IRC $mcÝŽ‚´¡ÍÍ.mô9³?gìé{/‡[~ÖŠu)4ý,¬³6ÀêŽäžõ¹\§Ž�µ›�ò`O¹ÈÖy�ISÂÎQÞÇ‹'dqD’rNMj蜺v§ù20I±ŒýEeT¶ÈÒ]Dˆ2ìà(÷Í|]’§QN;¦`ž§­ÑEú Ò[—þ=è*¥[—þ=è*¥“âoù/?Ýú­jÉñ7ü‹—Ÿî�ýUÒøãêscݪ…þE?ÿÈÿ×fþ•ÑW;à¿ùŸúìßÒº*ªÿÄ‘–YþçOÑW¿·7v3@¬�p éš±Eg8´×C½;;œ¬Z±l†èF¹Îf?•?û']ÿŸöÿ¿í]=Øñõ^é}ÆßX—‘Ìdë¿óþß÷ýª�¯ö­Ýä–±ßKæ&sºfÇÚ×-¢ÈÇuôýWM Tç É¥¢ìi ®Q“}dë¿óþß÷ý¨þÉ×çý¿ïûWOEs}~§e÷ûyyºh”—qKspކYœ±À9ã"ºŠ(¬+b'ZÜÝ çQÏp¢Š+Š( Š( Š(  z¯ü‚nÿë“*ÂðÖ�g«ÙÍ-ËJ$Ú60`JÝÕäwÿ\›ùUoÈ2çþ»A\óŠ•T™éáêJžrƒ³º&ÿ„+KþýÏýö?Â�øB´¿ïÜÿßcü+£¢´öPìs}{üìç?á Òÿ¿sÿ}�ð£þ­/û÷?÷Øÿ èè£ÙC°}{üìç?á Òÿ¿sÿ}�ð®sÄzE¶‘wo±�«®ã¼ç¿Ò½¸�ÿÈBÏþ¹ŸçYV§ÂéÙ~*µJê3“kS=N=#Æ—’£º$’©Œò®‹þŸÿ>w?øïø×'y§Üj~(»µ¶PÒ´®@'Žj×ü úßüñ‹þþŠùÊUñ´å5‡�×3é}O9-Ž‹þŸÿ>w?øïøÑÿ OÿŸ;Ÿüwük�ÿ„[ÿž1ßÑGü úßüñ‹þþŠ×ëy§ò¿ü|Ó:/øXZüùÜÿã¿ãGü,-?þ|îñßñ®wþ}oþxÅÿEðƒëóÆ/ûú(úÞiü¯ÿiš÷Œlõm{(­§G“nñ�†×Ú¹íGþ@OÖoýU‹ÿ jšm“ÝÜlj1¸‰<œZ¯¨ÿÈIúÍÿ¡ íÉjW©™'ˆV|¯¥´<œé·ƒ�ü¿4zü?ê#ÿt*}y2øÓ^U /`~å?Â�øMµÿùü_ûòŸá_Mõ*�Ñ’â<"_ ¾åþg¬Ñ^Mÿ ¶¿ÿ?‹ÿ~Sü(ÿ„Û_ÿŸÅÿ¿)þ¾¥SºúÇ„þY}ËüÏY¢¼›þmþþü§øQÿ ¶¿ÿ?‹ÿ~Sü(ú•Nè?Ö<'òËî_æ7Mÿ��cþ¹ŸýµÞx;þ@gþº·ô¯>Ñ]¤þÓv9fƒ$ûïZôÈ ÿ×Vþ•׉þ½Wävä.ùmÿ¼Íú(¢¼“Ò (¢€ â|Oÿ#=§û‘ÿèF»jâ|Oÿ#=§û‘ÿèF»pÅ~Œßñ|ŽŠŠ(®#¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò�üŽööÇÿEŠßñßú‹/÷Ÿù ÀƒþG{ûcÿ¢Åx¹—ÅñGõ;±?îT½Yé´QE{GQEVoˆä^Ô?ëƒÿ*Ò¬ßÿȽ¨×þU–#øRô�žÇ—Éÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¼¶Oùþ¿�þ€+Ô´/ùôßúõ�ÿAeÿò-¥ó,ÿÝoæ+y~èúWm÷z_?ÌÞ§ðãóŠ(®#¢Š(¢Š(¢Š(¢Š(¢Š(“?ò;ÿÀÿöJë+“?ò;ÿÀÿöJë+?kÔô3ùuþQElyçÿ5&?úè¿ú,W¢×�ÍI�þº/þ‹èµåå¿oñ²#Ô(¢Šõ (¢€2¼Iÿ"Ýÿýq5æSÈ©ýIÿ %zo‰?ä[¿ÿ®&¼Êoù ÿ¯é?ô®*_ò6§þúžNsþç?OÕ«£ÿÈÃþ½£ÿÐE]ªZ?ü�,?ëÚ?ýUÚï—ÄÏF�ð£è‚Š(©5 (¢€<±älÖ¿íçùšë<ÿ ûŸúëýrkÿ#fµÿo?Ì×YàŸùÜÿ×_è+Ö«þï/‘çdî•?ÆÿC§¢Š+É=¢Š(®/Æßñùiÿ\Ïó®Ò¸¿Çå§ýs?λrÿ㯙¾øˆè(¢Šâ0 (¢€ (¢€ (¢€ ‚÷þÒ-wÞÿ�ÿ®­ý+ƒÓãçXÿ®gÿF-wžÿ�ÿ®­ý+ÐÄÿ»¿Uù "VË¿íæoÑE䞈QEWâùí?Ü�ÿB5ÛWâùí?Ü�ÿB5Û€þ+ôfø‹ätTQEqQ@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQES&ÿQ'û§ùS铨“ýÓü¨cŽèÃð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,VÿŽÿÔY¼ÿÈVò;ØÛý+Å̾(ÿŠ?©Ý‰ÿr¥êÏM¢Š+Ú8BŠ( ³|Cÿ"ö¡ÿ\ùV•fø‡þEíCþ¸?ò¬±—£ü„ö<¾Oùþ¿�þ€+Ô´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú£/ÿ‘m/™ãaäeWü(ТŠ+SÚ (¢€ òãÿ#–«ô¸ÿÐMz�yqÿ‘ËUú\è&ºð›ËÐòs/ãaÿÆŽ£Áñçuÿ]ò®¦¹oÇ�×ýtʺšXß÷‰Ýâ0¢Š+”È(¢ŠãçþºÿA^µ_÷y|�;#ÿt©þ7ú=Q^Iè…Q@q~6ÿ�ËOúæ�v•ÅøÛþ?-?ë™þuÛ—ÿ|ÍðÿÄGAEW€QEQEQET¿ñãqÿ\›ùTõïüxÜ×&þTžÅCâF_�?Ôß¼ŸÖºúâ<}ig๸ŠÌ»w°ë]GöÞ—ÿA oûø+2JšÔïÌiNX™4ŸOÉèªÛz_ý-¿ïà£ûoKÿ …·ýü¯4{œ^Ƨò¿¸¿EPþÛÒÿè!mÿÛz_ý-¿ïࣚ=ÃØÔþW÷ç�:ØÛOý–¶ ÿ�x¿ÜʹïÞÚÞ/³\G6Ýû¶08ÎÚè`ÿ�x¿Üʲƒ½I[Èíħ%$ÿ½ù’QE¹ç‡Ž¾å�ÕÿöZêlÿãÆßþ¹¯ò®[Ç_rÇêÿû-u6ñãoÿ\×ùW—‡ÿ~­éÈ…ñ2j(¢½BËoÿCè*¥[øòAU(¬ßÈ÷þ¹Ò¬ßÈ÷þ¹ºõ9ñ_ÀŸ£üŒ¿Èoúø?ú ×M\Ï�¿ä 7ý|ýk¦«ÄG>UþåOÐ(¢ŠÄôŠ( ¹m3þF»Ÿ÷äþuÔ×-¦È×sþüŸÎ»pŸOCz_ ½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(½ÿüƒ®¿ë‹ÿ#X^Õ¬të{•»œD]�PTœñì+vÿþA×_õÅÿ‘¯?‚Êêèom4Áx&8Ëcò®ZòqšhörêP«Bp›²º=þ�þGýðßáGü%7üþ�ûá¿Â¼ÿû#Rÿ ußýùoð£û#Rÿ ußýùoð¨úÅNÇGö^ùßÞ¿ÈôøJ4oùý÷Ã…ð”hßóú?ï†ÿ óÿì�Kþ�×÷å¿Â�ì�Kþ�×÷å¿Â�¬TìÙx_çzÿ#Ð?á(Ñ¿çôß þËø·S³Ô¤µ6“ B …#Ǩ¬ì�Kþ�×÷å¿Â¡žÒæÔ¨¸·–Ý<Ä+ŸÎ¢u§(Ù£l6J¢œ%v¼ÑèñÿªO÷E:›ú¤ÿtS«Ð>eîÇxëïX}$ÿÙk±®;Ç_zÃé'þË^noþç?—戟Âu–ßñëûƒùTµ·üzÅþàþU-zøQAVäÿ�5ú ©Väÿ�5ú  *QE—â?ù¯ëŸõŸàŸùÉÿ]Ûù-hx�þEëßúçýEgø'þ@r×vþK]1ÿw~§�SþF°ÿüÎ’Š(®cØ (¢€ (¢€9m#þF{¯¬Ÿúu5Ëiò3Ý}dÿЫ©®Üwñ¢7¯ñ/@¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š*®¥ÿ «Ïúàÿú «UWRÿ�UçýpýÒ–ÌÒ—ñ#êŠ^ÿ�¯úê?•uuÊxþ§œÕÕ�!«z]¼—z¥´1‚XÈ€9'ò®ÆãÁvÊ^)e…Oð >™­=/D³ÒTý� ‘†G9cíí_7C%¯íW´²Š2TÝõ4h¢Šú³bÜ¿ñèŸAU*Ü¿ñèŸAU(¬ŸȹyþèÿÐ…kVO‰¿ä\¼ÿtèB®—ÇS›þíSü/ò)ø/þ@'þ»7ô®Š¹ßÿÈÿ×fþ•ÑUWþ$Œ²Ï÷:~ˆ(¢ŠÈî (¢€ å´Oùî¾�ÿ¡ êk–Ñ?äcºú?þ„+· ü*¾†ô¾zMQ\FEPEPEPEPEP=WþA7õÉ¿•Vð7üƒ.ë·ôgUÿ�MßýroåU¼ ÿ ËŸúíýc/â£Ð¥þå?Tu4QElyáEP\G�ÿä!gÿ\Ïó®Þ¸�ÿÈBÏþ¹ŸçXâ?†ÏC+ÿy_?È¥¢ÿÉD—ýù‘¯D¯;Ñä¢Kþü¿È×¢WUü:Ÿâ¡æC¨QEêQE`øÏþE[Ϫèk^w¨ÿÈIúÍÿ¡ ôOÿÈ«yõOý kÎõùi?Y¿ô!\˜oùÇü«•ƒãøø³ÿu¿˜­åû£é]µÿÝé|ÿ3zŸÃ�ÌZ(¢¸ŒŠ( Š( Š( ŠF`ŠYŽ&±Šì#˸>áGøÔÊqŽìÖ• •oìã{”Vü%vóÊãþùãGü%vóÊãþùãSí¡ÜÛê8Ÿäeÿ#¿üÿd®²¸c©Áÿ ö†Ù<�ÙÆï»�ZÜÿ„®Ãþy\ß#ükU"¯wÔíÆákOÙòÅ»E#vŠÂÿ„®Ãþy\ß#üiGŠì ˸åGøÖÞÚÎ/¨â‘™_óRcÿ®‹ÿ¢Åz-yʰˆñ2œ©t ÿÛ1^�^~[½oñ³Š=BŠ(¯P ¢Š(+ÄŸò-ßÿ×^e7üŠ�×ôŸúW¦ø“þE»ÿúâk̦ÿ‘Rúþ“ÿ@Jâ¥ÿ#já©äç?îsôýQêº?ü�,?ëÚ?ýUÚ¥£ÿÈÃþ½£ÿÐE]®ù|Lôhÿ >ˆ(¢Š“P¢Š(ËþFÍkþÞ™®³Á?ò¹ÿ®¿ÐW&¿ò6k_öóüÍuž ÿ�}Ïýuþ‚½j¿îòùvGþéSüoô:z(¢¼“Ñ (¢€ âümÿ–ŸõÌÿ:í+‹ñ·ü~Z×3üë·/þ:ù›áÿˆŽ‚Š(®#¢Š(¢Š(¢Š(¦º,‘²0ʰ �juÇ>|%iž.'ðÿ ?á´ÿŸ‰¿Oð®‚ŠËØÓìvhbœçÿá´ÿŸ‰¿Oð¬TÒâogy�åî#wû¹®ê¹8¿äw?ï·þ€k*´à¹lº�¸<]yªœÒ½¢Ùsþ+Oùø›ôÿ ?á´ÿŸ‰¿Oð®‚Š×ØÓìqhbœçÇ„¬ÁÏ9œ…oª…P£€-q„c²1«ˆ«ZÞÑÞÁEUœ‡Ž¾å�ÕÿöZêlÿãÆßþ¹¯ò®[Ç_rÇêÿû-u6ñãoÿ\×ùW—‡ÿ~­éÈ…ñ2j(¢½BËoÿCè*¥[øòAU(¬ßÈ÷þ¹Ò¬ßÈ÷þ¹ºõ9ñ_ÀŸ£üŒ¿Èoúø?ú ×M\Ï�¿ä 7ý|ýk¦«ÄG>UþåOÐ(¢ŠÄôŠ( ¹m3þF»Ÿ÷äþuÔ×-¦È×sþüŸÎ»pŸOCz_ ½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(½ÿüƒ®¿ë‹ÿ#YÞÿ�[Ï÷×ùÑ¿ÿ�u×ýqäk;À¿ñëyþúÿ#XËø±= ?îU=QÖÑE±ç…Q@q~;ÿ]cþëÿJí+‹ñßúë÷_úV8�᳿,ÿz�Ïòfôê“ýÑN¦Çþ©?ÝêØá{…qÞ:ûÖI?öZìkŽñ×Þ°úIÿ²×››ÿ¹Ïåù¢'ð�e·üzÅþàþU-Emÿ±¸?•K^„~PU¹?ãÍ~‚ªU¹?ãÍ~‚¨ ”QEeø�þEëßúçýEgø'þ@r×vþKZ#ÿ‘z÷þ¹ÿQYþ ÿ�ŸõÝ¿’×LÝß©ãÔÿ‘¬?Àÿ3¤¢Š+˜öŠ( Š( [Hÿ‘žëë'þ…]MrÚGüŒ÷_Y?ô*êk·üEè�ëüKÐ(¢Šâ0 (¢€ (¢€ (¢€ (¢€ «©È*óþ¸?þ‚jÕUÔ¿äyÿ\ÿA4¥³4¥üHú¢—�¿ãÆëþº�å]]ržÿ�¯úê?•uu�ᣧ0ÿyŸõÐ(¢ŠÔâ (¢€8ŸÇÕŸû�üÅt# ®{Ç_ñõgþã1]è+Ä—Èô1?î´íïÌZ(¬?êRiúX1Yfm�‡UÈÿ=é×­4ÝIl�9»+š¶Ÿk'—5ä(㪖ä}jÌ3Eq’D="¼ˆ’NO&µt N];S‹ |™$‹Øƒßê+£ž¹UQœmøªšž—EWÑ–åÿ�Dú ©Våÿ�Dú ©@dø›þEËÏ÷Gþ„+Z°üUuZÄ2,²(Ø„òÜŽÕ¥%z‹ÔäÇIG Q·ö_äCà¿ùŸúìßÒº*åüuöY¶ó“Ïó¼²yÆ8®¢ªºýã2Êäž�Ÿ@¢Š+Ð (¢€ å´Oùî¾�ÿ¡ êk–Ñ?äcºú?þ„+· ü*¾†ô¾zMQ\FEPEPEPEPEP=WþA7õÉ¿•Vð7üƒ.ë·ôgUÿ�MßýroåU¼ ÿ ËŸúíýc/â£Ð¥þå?Tu4QElyáEP\G�ÿä!gÿ\Ïó®Þ¸�ÿÈBÏþ¹ŸçXâ?†ÏC+ÿy_?È¥¢ÿÉD—ýù‘¯D¯;Ñä¢Kþü¿È×¢WUü:Ÿâ¡æC¨QEêQE`øÏþE[Ϫèk^w¨ÿÈIúÍÿ¡ ôOÿÈ«yõOý kÎõùi?Y¿ô!\˜oùÇü«u�úæôb×yàïùŸúêßÒ½ßoì)9Úúþ‡TäÀ_ûÌá~Í?üñ“þù4}šùã'ýòkÖh¬?µ_òþ'±õ·Øòo³OÿýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,VÿŽÿÔY¼ÿÈVò;ØÛý+Å̾(ÿŠ?©Ý‰ÿr¥êÏM¢Š+Ú8BŠ( ³|Cÿ"ö¡ÿ\ùV•fø‡þEíCþ¸?ò¬±—£ü„ö<¾Oùþ¿�þ€+Ô´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú£/ÿ‘m/™ãaäeWü(ТŠ+SÚ (¢€ òãÿ#–«ô¸ÿÐMz�yqÿ‘ËUú\è&ºð›ËÐòs/ãaÿÆŽ£Áñçuÿ]ò®¦¹oÇ�×ýtʺšXß÷‰Ýâ0¢Š+”È(¢Šã’ìµææÿîsù~h‰ü'Ymÿ±¸?•KQ[Ǭ_îåRס…nOøó_ ª•nOøó_ ª¥Q@~#ÿ‘z÷þ¹ÿQYþ ÿ�ŸõÝ¿’Ö–¿Ë Þ$hÎå8U'‘T|¶ú3¤ÑQmiTM.‹øjîZ¢Š+éÍKrÿÇ¢}T«rÿÇ¢}T nî­œ÷dE>=p3^Mus5åËÜNåäs’MzÕÌ sk,÷eB‡èF+Ê/ì'Ó®ÞÞá ²žf£Ú»ð\º÷>W‰UKAý�~ÿëbäx¤Y#b®§*Ààƒ^«£^¶£¤[]?ßuù¾ àþ¢¼¶ÞÞk¹Ò#i$s€ WªiV_ÙÚ]½¦A1¯ÌGry?©5XÞ[.æ\4ª{I¿³oÇþåÊ(¢¼ãëŠ( ¹mþF;¯£ÿèBºšå´Oùî¾�ÿ¡ íÂÿ ¯¡½/†^‡SEW€QEQEQEQEQEOUÿ�MßýroåU¼ ÿ ËŸúíýYÕäwÿ\›ùUoÈ2çþ»AXËø¨ô)¹OÕMQ[xQEWãùYÿ×3üë·®#Æÿò³ÿ®gùÖ8�á³ÐÊÿÞWÏò)h¿òQ%ÿ~_äkÑ+Îô_ù(’ÿ¿/ò5è•Õ§øŸèy�êQEz……Q@>3ÿ‘VóêŸú×�ê?òÒ~³èB½Æò*Þ}SÿCZó½Gþ@OÖoýW&þFñÿêÏ<ÿsŸËóG¯Ãþ¢?÷Gò§Ó!ÿQû£ùSë¬ö#² (¢�…Q@I¦ÿÇαÿ\ÏþŒZï<ÿ 3ÿ][úW¦ÿÇαÿ\ÏþŒZï<ÿ 3ÿ][úW­ˆÿw~«ò<ì‹þEßöó7袊òOD(¢Š+‰ñ?üŒöŸîGÿ¡í«‰ñ?üŒöŸîGÿ¡íÀú3|?Åò:*(¢¸ŒŠ( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQ^WW_|E¨ù×÷Ú ‹ùqÅcÍ98>™ã9 ã R]ÛÝ|0×tùm¯î.4+Çòæ†vÏ–xÉôÎAt ЪÑEex‡B·ñ&�&›s,±Dì¬Z,nàç¸4«EyÇü)­þ‚‡æŸüM`hÞ ²“â"[éÙi2$·W• ʧ!w?CéȳQ^cñÅýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,VÿŽÿÔY¼ÿÈVò;ØÛý+Å̾(ÿŠ?©Ý‰ÿr¥êÏM¢Š+Ú8BŠ( ³|Cÿ"ö¡ÿ\ùV•fø‡þEíCþ¸?ò¬±—£ü„ö<¾Oùþ¿�þ€+Ô´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú£/ÿ‘m/™ãaäeWü(ТŠ+SÚ (¢€ òãÿ#–«ô¸ÿÐMz�yqÿ‘ËUú\è&ºð›ËÐòs/ãaÿÆŽ£Áñçuÿ]ò®¦¹oÇ�×ýtʺšXß÷‰Ýâ0¢Š+”È(¢Šã‚ªU·ÿ�!ôR€ Íñü€/ë‘­*£¬Á%Î�u (^GŒ…QÜÕCâF”Ý ¥ÙþF?�¿ä 7ý|ýk¦¬ ØÜéú\±]Dbs1` �«éô­êºí:�£ ²2†œd¬ìQEdwQ@S‡Kµ‚õîÑXLä’KqÏZ¹ETg(¦“Üiµ°QE" (¢€ (¢€ (¢€ (¢€ (¢€+ßÿÈ:ëþ¸¿ò5�à_øõ¼ÿ}‘­ÿù]×þF³¼ ÿ·Ÿï¯ò5Œ¿‹УþåSÕmQ[xQEWã¿õÖ?î¿ô®Ò¸¿ÿ®±ÿuÿ¥cˆþ;òÏ÷¨üÿ&oGþ©?Ýêlê“ýÑN­Ž¸W㯽aô“ÿe®Æ¸ï}뤟û-y¹¿ûœþ_š" Ö[Ǭ_îåRÔVßñëûƒùTµèGáE[“þ<×è*¥[“þ<×è*€©EPEPEPEPEP-¤ÈÏuõ“ÿB®¦¹m#þF{¯¬Ÿúu5ÛŽþ"ôFõþ%èQEqQ@Q@Q@Q@EuÚ-&€yˆÉŸLŒT´Põm;£‘‹ÃÚ½¸+ ÒF çd¬3úTŸØÚïüÿŸûþÕÕQX}^' ó:ÏV—Ür¿ØÚïüÿŸûþÕŸê²êMb·²ùÊH$ÌØâ»ªäì¿är—ýù?‘¬êRQjÝYÕ†ÆN¤j9%¢¾Ã¿±µßùÿ?÷ý¨þÆ×çüÿßö®ªŠ×ØGÌäþÓ­Ù}Ç"þÕ.~ÑrŽiˆÙ×tQW jb1U+ÛŸ VŠõ,4°°±Y'm›‡P1Î?ÏzÝ®OÇ ‹k4ÇWcŸ ã\¹ŒÜ0³”]�ŽIlqu§ ê2iÚ¤,¬|¹$‹Ø‚¥fT¶í²æ'Æv¸8õæ¾*ŒÝ:Šqvi˜-ëtQE~„t–åÿ�Dú ©Våÿ�Dú ©@E=­½Òl¸‚9WÑÔçRÑBvŠ’³ ·²µ´[[Åzì@3SÑE6ÛÜQŠŠ´U�QEŠ (¢€ å´Oùî¾�ÿ¡ êk–Ñ?äcºú?þ„+· ü*¾†ô¾zMQ\FEPEPEPEPEP=WþA7õÉ¿•Vð7üƒ.ë·ôgUÿ�MßýroåU¼ ÿ ËŸúíýc/â£Ð¥þå?Tu4QElyáEP\G�ÿä!gÿ\Ïó®Þ¸�ÿÈBÏþ¹ŸçXâ?†ÏC+ÿy_?Èɺ¶Ötÿ\_YZÈÌ]Š:ǸjÏöï‹ÿçÞOüÿëWaEpf8¶áVI7{#Ìäó8ÿíßÿϼŸø ÿÖª÷+ñ%¡Qsû¢Ü€ðŸÒ»Šâ¼qÿVî7óËŽÃÕÃÐucZNÖê)&•îKý»âÿù÷“ÿ¿úÔnø¿þ}äÿÀoþµuã ¥®¿ìúŸóú_xù_s†¿¿ñF¥fö—6²´O�À[ã¡Ï§µQÖìç±Ñtˆ®c1ÈD­´õ°Åz=V×´MjÚÝ®Uh¾ëF@àõƒé]X "ÃâUyÍÉÚÚœ9–xŒ4©ÓÝÛóLš/èÂR¶(þ1Oÿ„“Eÿ �·ýö+˜ÿ„MÿŸ‹¯ûéøš?áÓçâëþú_þ&½>ZÙ‚«š%ü8ýçOÿ &‹ÿA;oûìQÿ &‹ÿA;oûìW­xRËMÒg»Šk†xöà;.9`==ê=Ãz®–.§–uråp„ÇÔU{*<¼÷v0xìÁWöÎ<Ö¾ý6;¯øI4_ú Ûßb�øI4_ú Ûßb¹�øA´ßùøºÿ¾—ÿ‰£þm7þ~.¿ï¥ÿâjyhwfþ×4ÿŸqûÎ{K`Óêì§ ÄH#¿ï»ßÈ ÿ×Vþ•‰7‡¬ô}*öXWw@¤ÈAÀÜ=­¿È ÿ×Vþ•ÕVjxfãÝ~GvU†©‡Àû:›Ý³~Š(¯0ê (¢€ â|Oÿ#=§û‘ÿèF»jâ|Oÿ#=§û‘ÿèF»pÅ~Œßñ|ŽŠŠ(®#¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEë2XÜ:}剈ú⧤`J‘�F =ø8ª<'vÃïæþøJÆSàè ê·¨Gýòõ�àKè<#­êþÕ§Kaçy¶ÒLv«Ž�O€¤~4¾?Ô`ñf¥¤øcH�.™î<ÙÞcc9p øP£i¬Ï¥Y»ýæ� Ï®ÑV«?RÕtïØ$÷÷ mlD¬TžqÀà­Û\Ãyi Õ»ï†dY#p1¹HÈ?‘ {Ç^!oxrI 'í·'ȶ®óßðýqV|! /‡<;›`Ü·ïn®é^{ã§á\¦¨ßð‘|_°Ó›æµÒ"óÝ{oÀlþf1øW¤P›øƒÃž'Ô~" GLÙi@!K×*ÛS» œçæ#§øÔZ¶ƒã/ ZK«Øø¢ãQ2h'S‚£®fôâ¶.¼o6‹ãY4�r(m´éu­ØVé÷ŽHÇP};T¾*ñ¶…gáûŇQµ»¸šŽ( �HIa�œgœó@þדжԕn଱ƒ÷\pGÓ¸ö5OÇZ†¹¦xtÜxzÙî/¼å]‰ ”í9ÉÚ? ƒáÆ‘q£ø6Þ;¤)4îÓ²7U Œøë(Ãá2ø­ÿ@[¿ü·øW¯é„ÜiVs^ü—r@�:Ÿ”«•†;sž+N³¥ÿZÿï±å[ÿ|ßTyVÿß÷ÕT¢€-ùVÿß÷ÕU¿÷ÇýõU(  ~U¿÷ÇýõG•oýñÿ}UJ(ß•oýñÿ}TsÅoöypÃîâö¨)“¨“ýÓü¨cŽèàtÝ^ïJ2VUó1»rç¦qüëCþ _þzÇÿ~Å7Ú:Ó\‰¥’?+n6cœç×é[ßðƒYÿÏÜÿ�ÿ óá ®7‹ÐúlE|j5U{Þ†ü&¿üõ�þýŠ?á0Õÿç¬÷ìVçü Öó÷?ä?Â�øA¬ÿçîÈ…_%~ÿ‰�Örïå_q‡ÿ †¯ÿ=cÿ¿b�øL5ùëýû¹ÿ5ŸüýÏùð£þk?ùûŸòáG%~ÿˆ}g.þU÷®¥¬Þj«Ý:°Œ’»Tµb0Žl6ôÄú-jh0hÑÛ´SI!��wãŒcüj´ò;ØÛý+ÏÆ©.E-ù£úœ™¤©J…7I{·g¦ÑEîžHQEVoˆä^Ô?ëƒÿ*Ò¬ßÿȽ¨×þU–#øRô�žÇ—Éÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¼¶Oùþ¿�þ€+Ô´/ùôßúõ�ÿAeÿò-¥ó3Õ·vçÿAjõ òãÿ#–«ô¸ÿÐMuá7—¡äæ_ÆÃÿ�G‚?ãÎëþºå]MrÞÿ�;¯úè?•u4±¿ï=ºÿÄaEW)�QEÆxßþ>,ÿÝoæ+©H­ö/Î:z¹oÿÇÅŸû­üÅo/ÝJí¯þïKçù›Ôþ~eÏ*ßûãþú£Ê·þøÿ¾ª¥Ä`[ò­ÿ¾?ïª<«ï�ûêªQ@ü«ï�ûê�*ßûãþúª”P¿*ßûãþú£Ê·þøÿ¾ª¥5ÜVÿcŸ 3å·ñ{W9à?»õ�ÿf­‹Ÿøõ›ýÆþU�à?»õ�ÿf¬güXüÏB‡û�_ûwó;(¢¶<ð¢Š(®?ÇrÃë'þË]…qþ;û–Y?öZÆ¿ðÙÝ–ÿ½Cçù3Ä P½?uÿ¢…zMy¥¯ü�¶¿XÿôP¯K®³zßãgÚ—¨QEê (¢ŠÊñ'ü‹wÿõÄ×™Mÿ"¤õý'þ€•é¾$ÿ‘nÿþ¸šó)¿äTƒþ¿¤ÿи©ÈÚŸø_êy9Ïûœý?Tz&—¯é1iQɨÛ+¤¬¦A�BŒŠ·ÿ �ÿA;_ûø+Ç…­ÃD�y!¥û%ÏüûËÿ|÷Þ Þç‰ ÄF**šÓÔöøH´oú ÚÿßÁGü$Z7ýíïà¯û%ÏüûËÿ|>Ésÿ>òÿß—Ôáܯõ‹ÿ>×â{ü$Z7ýíïà£þ-þ‚v¿÷ðW�ý’çþ}åÿ¾ d¹ÿŸyïƒGÔáÜ?Ö,Oüû_‰¿m$SøŸX•Z7K–F‚9Æ+­ðOüƒîë¯ôÁè*VöåXE´ ƒÛŠÖÓµ»Í.'ŽØ WmÇrçšëteR”¡#ÝáÅ*¸)¾®Oô=6ŠóÿøKõ_ïCÿ~èÿ„¿Uþô?÷î¸ÿ³+y×Õ¦zçÿð—ê¿Þ‡þýÑÿ ~«ýèïÝÙ•¼ƒêÓ=¸¿Çå§ýs?ΩÿÂ_ªÿzû÷YÚŽ«sªIÜ•%ÕÅtá0UiUS•¬kJ„¡;³Ò<«ï�ûê�*ßûãþúª”WŒqü«ï�ûê�*ßûãþúª”P¿*ßûãþú£Ê·þøÿ¾ª¥oÊ·þøÿ¾¨ò­ÿ¾?睊E[ò­ÿ¾?ïª<«ï�ûêªQ@ü«ï�ûê�*ßûãþúª”P¿*ßûãþú®6%�þâ¹ù7·9ÿ`×O\œ_ò;Ÿ÷Ûÿ@5�o³êz ªÿ…�¿•oýñÿ}Qå[ÿ|ßURŠØóË~U¿÷ÇýõG•oýñÿ}UJ(ß•oýñÿ}Qå[ÿ|ßURŠ}Þ—¦_ûTq˳;w™©Ö T@ªÀ*Œ» ª´T¨Å7$µ`[ò­ÿ¾?ïª<«ï�ûêªQT�XÌ!I=sQyVÿß÷ÕÿCè*¥[ò­ÿ¾?ïª<«ï�ûêªQ@ü«ï�ûê�*ßûãþúª”P¿*ßûãþú£Ê·þøÿ¾ª¥oÊ·þøÿ¾¨ò­ÿ¾?睊E[ò­ÿ¾?ïª<«ï�ûêªQ@ü«ï�ûê�*ßûãþúª”P¿*ßûãþú£Ê·þøÿ¾ª¥oÊ·þøÿ¾¨ò­ÿ¾?睊E[ò­ÿ¾?ïª<«ï�ûêªQ@ü«ï�ûê�*ßûãþúª”P¿*ßûãþú£Ê·þøÿ¾ª¥íF;q¥Ý�Ã>Kãæÿd×+á]fËK‚å.äd.À®žÞÕÓ²«©V© ÷–|9¥“ÿçþþ7øÖ5!'%(ô;ðÕèÆ”©U½�¶.ÿÂ]£ÿÏwÿ¿mþÂ]£ÿÏwÿ¿mþGþ½/þx7ýüoñ£þ½/þx7ýüoñ£÷ÞCÿ`þ÷à^ÿ„»Gÿžïÿ~Ûü(ÿ„»Gÿžïÿ~Ûü+’‡O¶µ“!ò0Û¸öRzÖÿü#z_üðoûøßãQÕ•ícjÔpTZRæÕ_¡{þíþ{¿ýûoð®gÅZµ¦©%©´�¸Œ0l©qëô­�øFô¿ùàß÷ñ¿Æ•|;¥«örqØ»�…Y«; ø*U!ÍuèoE¿”Ÿ0û£ø©ÞU¿÷ÇýõU(®“Ée¿*ßûãþú®'â Æ­§ùd$Ï9þíuuÇxëïX}$ÿÙkÍÍÿÜçòüÑ3øNÞÖ+²C–q‹Ú¥ò­ÿ¾?ïªÏ¶ÿ�X¿ÜÊ¥¯B? (·å[ÿ|ßU+,f ¤�ž¹¬ú·'üy¯ÐUyVÿß÷ÕU¿÷ÇýõU(  ~U¿÷ÇýõG•oýñÿ}UJ(ß•oýñÿ}Qå[ÿ|ßURŠ·å[ÿ|ßTyVÿß÷ÕT¢€-ùVÿß÷ÕU¿÷ÇýõU( oDXÏ‹n×2àçýªëü«ï�û긽#þF{¯¬Ÿúu5ÛŽþ"ôFõþ%è[ò­ÿ¾?ïª<«ï�ûêªQ\F¿*ßûãþú£Ê·þøÿ¾ª¥oÊ·þøÿ¾¨ò­ÿ¾?睊E[ò­ÿ¾?ïª<«ï�ûêªQ@ü«ï�ûê�*ßûãþúª”P¿*ßûãþú£Ê·þøÿ¾ª¥oÊ·þøÿ¾¨ò­ÿ¾?睊E[ò­ÿ¾?ïªãl3ã™”‘³|œçØ×O\�—üŽRÿ¿'ò5�mãêz‚¯øYÛùVÿß÷ÕU¿÷ÇýõU(­�<·å[ÿ|ßTyVÿß÷ÕT¢€-ùVÿß÷Õs8°éÜA†0I—çå#üñ[”„R¬`ƒÞ°ÄÐUéJ“ê&®¬y^ÑìÞÿW¶·QÁ�>ŠIü«³¸ð†—<¥×·=V6ýA­-;I³ÒЭ¬XfûÎÇ,ùÚ%oj½£\«ñ2TÝõ6<«ï�ûê�*ßûãþúª”WÔ› ±˜‚±ù8ÁÍEå[ÿ|ßTKÿ‰ôR€-ùVÿß÷Õq:×� —·ÒáI¤$‚}€íï[ú³´z=ë¡Ã,AôùMy5va(Æw”��Ïs Ø~Zt�¯«ge¦xá¾Ð©©Û¡‰Ž ‘d÷#'5Þ¢ÚÈŠé"²°È!ºŠñ ôß »IáË2Ç$_À1«F0JQ3ȳÕç*5]쮟õêt~U¿÷ÇýõG•oýñÿ}UJ+„úbß•oýñÿ}Qå[ÿ|ßURŠ·å[ÿ|ßUÈx}c>(¼ p¸“ÿ´+¤®[Dÿ‘Žëèÿú®Ü/ðªúÒøeèvžU¿÷ÇýõG•oýñÿ}UJ+ˆÀ·å[ÿ|ßTyVÿß÷ÕT¢€-ùVÿß÷ÕU¿÷ÇýõU(  ~U¿÷ÇýõG•oýñÿ}UJ(ß•oýñÿ}Qå[ÿ|ßURŠ·å[ÿ|ßTyVÿß÷ÕT¢€¬GѯJ°Ï’Øù½«3Àßò ¹ÿ®ßÐU�WþA7õÉ¿•Vð7üƒ.ë·ôŒ¿Š�B—û”ýQÔÑE±ç…Q@q7ÿ�…Ÿýs?λzâk÷£Å_ò-Þ}ÿC_Á¿ò/¯ýtjé_îï×ô•ƒãøø³ÿu¿˜­åû£é]µÿÝé|ÿ3zŸÃ�ÌZ(¢¸ŒŠ( Š( Š( ®ãÖo÷ùV?€þíÿÖ?ýš¶.ãÖo÷ùV?€þíÿÖ?ýš±Ÿñcó= îuíßÌìh¢ŠØóŠ( ¸ÿýˬŸû-vÇøïîX}dÿÙkÿÃgv[þõŸäÌK_ùm~±ÿè¡^—^ikÿ#í¯Ö?ý+Òë‡,Þ·øÙÁö¥êQEzƒ (¢€2¼Iÿ"Ýÿýq5æSÈ©ýIÿ %zo‰?ä[¿ÿ®&¼Êoù ÿ¯é?ô®*_ò6§þúžNsþç?OÕ«£ÿÈÃþ½£ÿÐE]ªZ?ü�,?ëÚ?ýUÚï—ÄÏF�ð£è‚Š(©5 (¢€<±älÖ¿íçùšÕÐf÷'µvaùŸ.ÇÏçñÃ:qu›RéoÇädiúMæ§2Ço '™¯ÔרXÚ%…Œ6±ò±.Üúžçó¯?ÓüW©ZL¦iMÄ9ù‘úãØ×¢[ÏÕ¼sÄÛ£‘C)ö4ñަœÛðüp©IÓmÏ­ôÓËrJ(¢¸�¤ (¢€ å´Oùî¾�ÿ¡ êk–Ñ?äcºú?þ„+· ü*¾†ô¾zMQ\FEPEPEPEPEP=WþA7õÉ¿•Vð7üƒ.ë·ôgUÿ�Mßýroå\ž‘â� !†(�]·ùôÇc\õ$£Q6zØJ3­„œ!½Ñé”W ÿ Åÿüû[~Mþ4Âqÿ>Öß“�?¬S3þÊÄö_yÝÑ\'ü'ÿóímù7øÑÿ Åÿüû[~Mþ4}b˜eb{/¼îëˆñ¿ü„,ÿë™þuü'ÿóímù7øÖN«¬M¬\E$ÑÆ†1´ϯ½gV´%#¯€­F²œÖš�íQ]g„Åxãþ>¬ÿÜoæ+µ®+Çñõgþã1^fqþé/—æDþ´- è)kÓ,*ÜßñꟅT«sǪ~RŠ(  È·yô_ý UÿȾ¿õѪNJ¿ä[¼ú/þ†*¿ƒä__úèÕÒ¿Ý߯èxòÿ‘´Áú�Q\ǰgëŸò¹úæ*_È ÿ×Vþ•¹ÿ [Ÿ þb¥ðwü€Ïýuoé]±ÿsâý ×ð_©¿EW€QEWâùí?Ü�ÿB5ÛWâùí?Ü�ÿB5Û€þ+ôfø‹ätTQEqQ@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQES&ÿQ'û§ùS铨“ýÓü¨cŽèÃð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,VÿŽÿÔY¼ÿÈVò;ØÛý+Å̾(ÿŠ?©Ý‰ÿr¥êÏM¢Š+Ú8BŠ( ³|Cÿ"ö¡ÿ\ùV•fø‡þEíCþ¸?ò¬±—£ü„ö<¾Oùþ¿�þ€+Ô´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú£/ÿ‘m/™ãaäeWü(ТŠ+SÚ (¢€ òãÿ#–«ô¸ÿÐMz�yqÿ‘ËUú\è&ºð›ËÐòs/ãaÿÆŽ£Áñçuÿ]ò®¦¹oÇ�×ýtʺšXß÷‰Ýâ0¢Š+”È(¢ŠãÚýcÿÑB½.¼Ò×þGÛ_¬ú(W¥×Y½oñ³ƒíKÔ(¢ŠõQEex“þE»ÿúâk̦ÿ‘Rúþ“ÿ@JôßÈ·ÿ\My”ßò*Aÿ_Òè \T¿ämOü/õ<œçýÎ~Ÿª=WGÿ�%‡ý{Gÿ Š»T´ùX×´ú«µß/‰ž�áGÑQRjQEybÿÈÙ­ÛÏó5Öx'þA÷?õ×ú ä×þFÍkþÞ™®³Á?ò¹ÿ®¿ÐW­WýÞ_#ÎÈÿÝ*�þ‡OEW’z!EP\_�¿ãòÓþ¹Ÿç]¥q~6ÿ�ËOúæ�våÿÇ_3|?ñÐQEÄ`QEQEQEQEQEÉÅÿ#¹ÿ}¿ô]erqÈîßoýÖ5¾Ï©è`6«þu”QElyáEPEPEPEP·ÿ�!ôR­¿üy ª”QEQEQEQEQEQEQEQEQEQEQEQEQEÉÛÈêßï¿þ‚k¬®NÛþGVÿ}ÿô]ecCgêz�ÅOü+õ (¢¶<ð¢Š(®;Ç_zÃé'þË]�qÞ:ûÖI?öZós÷9ü¿4Lþ¬¶ÿ�X¿ÜÊ¥¨­¿ãÖ/÷ò©kÐ�Š ·'üy¯ÐUJ·'üy¯ÐURŠ( Š( Š( Š( Š( [Hÿ‘žëë'þ…]MrÚGüŒ÷_Y?ô*êk·üEè�ëüKÐ(¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ äì¿är—ýù?‘®²¹;/ù¥ÿ~OäkÛÇÔô0?_𳬢Š+cÏ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€*êQ¼Ú]ÜQçÌx]W¤òJöZæµoÛßN×ÒýžG9eÛ•'×Úºðµ£NêG��åµqJ5(ê×CÏëÔ<5�øzÍ$6ÒÜúHý¬�;Á0A2Ëy?žäF«…?_ZêÀ` UН¥™ä™el4åV¶�«X(¢Šâ>Œ(¢Š+–Ñ?äcºú?þ„+©®[Dÿ‘Žëèÿú®Ü/ðªúÒøeèu4QEqQ@Q@Q@Q@Q@õ_ùÝÿ×&þUÌè~:Õ´“}«ÉØûqåîÏõÓj¿ò »ÿ®Müª·�¿äsÿ]¿ ®z‘R¨“=\-iÑÂNpvwEoø@ÏýGýùÿì¨ÿ„ ÿÐDߟþÊ»**½…>Æ?Úx¯æüùoü gþ‚#þüÿöTÂè"?ïÏÿe]•{ }ƒûOüß‚ÿ#�ÿ„ ÿÐDߟþʱ5­ûæ¼ÿ;Ì]ÙÙ·ýMzmq7ÿ�…Ÿýs?β­J…Ò;0êõk¨NWZôGGEWYâq^8ÿ�«?÷ùŠíkŠñÇü}Yÿ¸ßÌW™œºKåù‘?„íAKH: ZôË ·7üz§áU*ÜßñꟅT¢Š(Å_ò-Þ}ÿC_Á¿ò/¯ýtj±â¯ùï>‹ÿ¡Š¯àßù×þº5t¯÷wëú<¿ämð~§AEW1ìúçü�n~ƒùŠ—Áßò?õÕ¿¥G­#>�r¨¥ŽÐp>¢°4¯\éVfŽÙwËg<×£B”ªá\a½ÿC¦s¤ÒîzÅÂiyÿ>q~´Âiyÿ>q~µŸö}~߉?W¨v´Wÿ ­ÙýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,VÿŽÿÔY¼ÿÈVò;ØÛý+Å̾(ÿŠ?©Ý‰ÿr¥êÏM¢Š+Ú8BŠ( ³|Cÿ"ö¡ÿ\ùV•fø‡þEíCþ¸?ò¬±—£ü„ö<¾Oùþ¿�þ€+Ô´/ùôßúõ�ÿAå²ȨŸõüô^¥¡È¿¦ÿ׬ú£/ÿ‘m/™ãaäeWü(ТŠ+SÚ (¢€ òãÿ#–«ô¸ÿÐMz�yqÿ‘ËUú\è&ºð›ËÐòs/ãaÿÆŽ£Áñçuÿ]ò®¦¹oÇ�×ýtʺšXß÷‰Ýâ0¢Š+”È(¢ŠãçþºÿA^µ_÷y|�;#ÿt©þ7ú=Q^Iè…Q@q~6ÿ�ËOúæ�v•ÅøÛþ?-?ë™þuÛ—ÿ|ÍðÿÄGAEW€QEQEQEQEQEW'üŽçýöÿÐ u•ÉÅÿ#¹ÿ}¿ôXÖû>§¡€Ú¯øYÖQE±ç…Q@Q@Q@Q@ßþ<‡ÐUJ¶ÿñä>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPEP'mÿ#«¾ÿú ®²¹;où[ý÷ÿÐMu•� Ÿ©èf??ð¯Ô(¢ŠØóŠ( ¸ï}뤟û-v5ÇxëïX}$ÿÙkÍÍÿÜçòüÑ3øN²Ûþ=bÿp*–¢¶ÿ�X¿ÜÊ¥¯B? (*ÜŸñæ¿AU*ÜŸñæ¿ATJ(¢€ (¢€ (¢€ (¢€ (¢€9m#þF{¯¬Ÿúu5Ëiò3Ý}dÿЫ©®Üwñ¢7¯ñ/@¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+“²ÿ‘Ê_÷äþFºÊäì¿är—ýù?‘¬koSÐÀüÂβŠ(­�<(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ+•Õ¼e¥Ã[ÙB³24Œ~\ûc­t›¼zUãÅŸ1ar¸õÁ¯$®Ì-ÎîGÏç™�\7-:Z7Ôítÿ‰&XïíÖ4c�22p¿Pk¯V ¡”‚È#½xÝz†^I<;fdÎí¤ ú ~˜§Š¡%(™äy•lDåF³½•Ó5¨¢Šâ>�(¢Š+–Ñ?äcºú?þ„+©®[Dÿ‘Žëèÿú®Ü/ðªúÒøeèu4QEqQ@Q@Q@Q@Q@õ_ùÝÿ×&þU[Àßò ¹ÿ®ßÐU�WþA7õÉ¿•Vð7üƒ.ë·ôŒ¿Š�B—û”ýQÔÑE±ç…Q@q7ÿ�…Ÿýs?λzâ²ìµ�á³»-ÿz‡Ïòf½¯üyÃÿ\×ùTµ¯üyÃÿ\×ùTµªØãŸÄ¹/ÿ¨²ÿyÿ�®¶¹/ÿ¨²ÿyÿ�® ×ýÎ/ÍÏá:M?þA¶¿õÅ?�«5[Oÿ�m¯ýqOä*ÍvÓø¡H+™ø�ÿ ½;þº7ò®š¹¿£"ÁÂ’«!ã�‘]Xoâ£ÌÎ?Üj|¿4uz?ü�,?ëÚ?ýUÚó‹OˆÚYAl4ôakï4Œàc=*øYÐ6?ûú®XZ­·c YÞ 0ŠsÙväzçÿð²&ÿ l÷ôÿ…ð²&ÿ l÷ôÿ…OÕjö/ûsüÿƒÿ#Ð(¯?ÿ…‘7ýcÿ¿§ü(ÿ…‘7ýcÿ¿§ü(ú­^Áý¹�þÁÿ‘˜¿ò6k_öóüÍuž ÿ�}Ïýuþ‚¸½2w¿Öu+Ï/o› Ò0…Ýžÿ�vž ÿ�}Ïýuþ‚»«+aä½ r¥‚©%³›ýžŠ(¯$ô‚Š( ¸¿Çå§ýs?λJâümÿ–ŸõÌÿ:íËÿ޾føâ# ¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š+“‹þGsþûèºÊäâÿ‘Üÿ¾ßú¬k}ŸSÐÀmWü,ë(¢ŠØóŠ( ‘™Q 3U$œ)kžñ�Ä�èʈHÊ�¶ Çè+EeF”ª>‚nÊã.¼gc ¥!†IÀ8.0 ý+CJ׬õl¤%’`2c~=½kÌê{+‰-/až"C£‚1ßÚ¾f–w]TNvqìdª;ž³EWÖßþ<‡ÐUJ¶ÿñä>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPEP'mÿ#«¾ÿú ®²¹;où[ý÷ÿÐMu•� Ÿ©èf??ð¯Ô(¢ŠØóŠ( ¸ï}뤟û-v5‘­èK­ \¼­Ý9Î=ý«‹1£:ØiS¦®Ý¿4L•Õ�+oøõ‹ýÁüªZliåĉœíf�]‘VInOøó_ ª•nOøó_ ¦J(¢€ (¢€ (¢€ (¢€ (¢€9í6Æê~ây!e‰‹á�C“Åt4QZÖ¬êË™ú9¹»°¢Š+"Š( Š( Š( Š( Š( Š( ¹;/ù¥ÿ~Oäk¬®NËþG)ß“ùƶñõ= ÁWü,ë(¢ŠØóŠ( Š( Š( Š(  rÿÇ¢}T«rÿÇ¢}T  š¦ñ¤ÞyÈ}¿]¦¼–½—­yN´–Qê“-ƒ„7qÀ=Àõß‚–ñ>W‰i;B­û«+Ó¼1¼ørÏ]§MǦ+Î,–Ù¯"nén[ç(2@¯Z�bKxÖ¢  &ޘǪÆËE.¤ý¤êߥ­øþ„”QEyÇ×…Q@rÚ'üŒw_GÿÐ…u5ËhŸò1Ý}ÿBÛ…þ_Cz_ ½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(ž«ÿ ›¿úäßÊ«xþA—?õÛú ³ªÿÈ&ïþ¹7òªÞÿ�eÏývþ‚±—ñQèRÿrŸª:š(¢¶<ð¢Š(®#Æÿò³ÿ®gù×o\G�ÿä!gÿ\Ïó¬qÃg¡•ÿ¼¯ŸättQElyá\WŽ?ãêÏýÆþb»Zâ¼qÿVî7óægî’ù~dOá;AÐRÒ‚–½2­Íÿ©øUJ·7üz§á@(¢ŠÇñWü‹wŸEÿÐÅWðoü‹ëÿ]¬x«þE»Ï¢ÿèb«ø7þEõÿ®�]+ýÝúþ‡�/ùGü©ÐQEÌ{EPEP-áÿù]ÿ¸ÿú®¦¹oÿÈzïýÇÿÐ…u5Û�þ/Éâ>0¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( ™7ú‰?Ý?ÊŸL›ýDŸîŸåCwF�>ýÿÒ?ýš»:ã< ÷ïþ‘ÿìÕÙÖ8᣻3ÿz—ËòAEVÇQEÈøïýE—ûÏü…`Aÿ#½‡ý±ÿÑb·üwþ¢ËýçþB° ÿ‘ÞÃþØÿè±^.eñGüQýNìOû•/VzmQ^ÑÂQE›âùµúàÿÊ´«7Ä?ò/jõÁÿ•eˆþ½ä'±åòȨŸõüô^¥¡È¿¦ÿ׬ú¯-“þEDÿ¯ãÿ  õ- þEý7þ½cÿÐEü‹i|Ï ÿ#*¿áF…QZžÐQEW—ùµ_¥Çþ‚kÔkË�üŽZ¯ÒãÿA5ׄÞ^‡“™þ4uÿ�;¯úè?•u5Ëx#þ<î¿ë þUÔÒÆÿ¼Höëÿ…Q\¦AEPãøø³ÿu¿˜­åû£éX>7ÿ�‹?÷[ùŠÞ_º>•Û_ýÞ—Ïó7©ü8üÅ¢Š+ˆÀ(¢Š(¢Š(¢ŠŠçþ=fÿq¿•cøîßýcÿÙ«bçþ=fÿq¿•cøîßýcÿÙ«ÿ?3СþçWþÝüÎÆŠ(­�<(¢Š+�ñßܰúÉÿ²×a\Žþå‡ÖOý–±¯ü6we¿ïPùþL×µÿ�8ëšÿ*–¢µÿ�8ëšÿ*–µ[sø˜W%ãŸõ_ï?òÖ×%ãŸõ_ï?òÁšÿ¹Ïåù£9ü'I§ÿÈ6×þ¸§òf«iÿò µÿ®)ü…Y®Úô)[p ŽÈÀëõª•m¿ãÄ}ó«—•÷ò£Ê�û‹ùS¨¢â²3uÈÐhWÄ"ƒä·ojÇð:+iW”ßž£ý‘[Zçü€¯¿ë‹*Çð7ü‚®?ë¹ÿÐEtÇøõ<ŠÉiÓÿ :o*?î/åG•÷ò§Q\×={" ›:ÎxP*™¨8îEspi:墕·œÄ¤ä„›šê變8™ÒN*Í>氨଎gì~#ÿŸÙð Ñö?ÿÏì¿øk¦¢µúôÿ•}ÅûyvGƵ-óY¥ôþr’óŽ8ëW~Çâ?ùý—ÿ 2ÃþFé¿ß“ú×S]8œK¥$£ªOcJµ\Z²[ÏØüGÿ?²ÿàA¨eÑu‹ÉÝMæc�Ï.ì ë(®u�¨µI}ÆX’Ù ¢Š+„À(¢Š(¢Š(¢Š(¢Š(¢Š+“‹þGsþûèºÊäâÿ‘Üÿ¾ßú¬k}ŸSÐÀmWü,ë(¢ŠØóŠ( ¨kjêºsÛµ¾ò1ìçù÷«ôTT„jEÂ[0zžYu¤ßÙÊcšÖPsÁU$¡¯áÿ\ÏwÍÜM¼d6×.GA�Jï(¯"–IF9Ü›K¡š¦®QE{F…·ÿ�!ôR­¿üy ª”QEQEQEQEQEQEQEQEQEQEQEQEQEÉÛÈêßï¿þ‚k¬®NÛþGVÿ}ÿô]ecCgêz�ÅOü+õ (¢¶<ð¢Š(¢Š(¢Š(«rÇšýT«rÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®NËþG)ß“ùë+“²ÿ‘Ê_÷äþF±­¼}OCðUÿ :Ê(¢¶<ð¢Š(¢Šd²¤14²¸DA–cÐ ¶¬Ñ\µÇ�í£”¬�*÷™¶çè0kSI×­5|¤{£™FLo×£Ö¹)ãðÕgìá4Ù*Iš´QEu”[—þ=è*¥[—þ=è*¥UÔÙ×J¼h³æ\®=všòJõÍBf¶Ón§Q–Ž&`¨¼Ž½Ìù&·´§è½?Ã-#xvÌÉœí gÓqÇéŠó õ ÌÓøzÍØ`„)ÿ|’?¥V7à^¦\7o¬Ëü?ª5h¢Šó´ (¢€ å´Oùî¾�ÿ¡ êk–Ñ?äcºú?þ„+· ü*¾†ô¾zMQ\FEPEPEPEPEP=WþA7õÉ¿•Vð7üƒ.ë·ôgUÿ�MßýroåU¼ ÿ ËŸúíýc/â£Ð¥þå?Tu4QElyáEP\G�ÿä!gÿ\Ïó®Þ¸�ÿÈBÏþ¹ŸçXâ?†ÏC+ÿy_?Èè袊Øó¸¯ÇÕŸû�üÅvµÅxãþ>¬ÿÜoæ+ÌÎ?Ý%òüÈŸÂvƒ ¥¤-ze…[›þ=Sðª•noøõO€*QE�â¯ùï>‹ÿ¡Š¯àßù×þº5XñWü‹wŸEÿÐÅWðoü‹ëÿ]ºWû»õý_ò6�ø?S ¢Š+˜öŠ( Š( [Ãÿò»ÿqÿô!]MrÞÿ�õßû�ÿ¡ êk·ü_’7Ä|aEW€QEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@2oõº•>™7ú‰?Ý?ʆ8îŒ?}ûÿ¤û5vuÆxïßý#ÿÙ«³¬pÿÃGvgþõ/—䂊(­Ž¢Š(‘ñßú‹/÷Ÿù ÀƒþG{ûcÿ¢ÅoøïýE—ûÏü…`Aÿ#½‡ý±ÿÑb¼\Ëâ�ø£ú�ØŸ÷*^¬ôÚ(¢½£„(¢Š+7Ä?ò/jõÁÿ•iVoˆä^Ô?ëƒÿ*Ëü)z?ÈOcËäÿ‘Q?ëøÿè½KBÿ‘Mÿ¯Xÿô^['üЉÿ_Çÿ@êZü‹úoýzÇÿ Š2ÿùÒùž6þFUÂ� (¢µ= ¢Š(¯.?ò9j¿K�ýרחùµ_¥Çþ‚k¯ ¼½'2þ6ühê<ÿw_õÐ*êk–ðGüyÝ×Aü«©¥�ÿx‘í×þ# (¢¹L‚Š( 3Æÿññgþë1[Ë÷GÒ°|oÿî·ó¼¿t}+¶¿û½/ŸæoSøqù‹EW€QEQEQEÏüzÍþã*áô­nëGý™b>n7oRzgßÞ»‹Ÿøõ›ýÆþUÈxAMh\o�¢ò¶ã œç?á\µÔœ£Ë¹ìå²¥5_‡BÇü&º§÷-¿ïƒþ4ÂkªrÛþø?ãZð‚Ãÿ?Òß±þ4 üÿIÿ~ÇøÔr×7öÙoe÷33þ]Sû–ß÷Áÿ?á5Õ?¹mÿ|ñ­?øAaÿŸé?ïØÿ?á‡þ¤ÿ¿cühå®Û-ì¾æfÂkªrÛþø?ãYÚ®·u¬…ÊÄ<¬íؤuÇ¿µtŸð‚Ãÿ?Òß±þ5‹â 4U·);Kæ–ÎWÆ?Ʀqª£ïlo‡«�•D©/{Ñ�u¯üyÃÿ\×ùTµ¯üyÃÿ\×ùTµÜ¶>j ä¼sþ¢ËýçþBºÚä¼sþ¢ËýçþB¸3_÷9ü¿4g?„é4ÿùÚÿ×þB¬Õm?þA¶¿õÅ?�«5ÛOà^… «mÿ#è?�T«mÿ#è?�X(¢ŠÏ×?ä}ÿ\[ùV?�¿äqÿ]Ïþ‚+c\ÿ�÷ýqoåXþÿ�UÇýw?ú®˜ÿ^§�[þF”ÿÂ΢Š(®cØ (¢€ (¢€9kù¦ÿ~Oë]MrÖò7MþüŸÖºšíÇ|qÿ 7¯ºô (¢¸ŒŠ( Š( Š( Š( Š( Š( ¹8¿äw?ï·þ€k¬®N/ùÏûíÿ Æ·Ùõ= ÕÂβŠ(­�<(¢Š(¢Š(¢Š(¢Š¶ÿñä>‚ªU·ÿ�!ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9;où[ý÷ÿÐMu•ÉÛÈêßï¿þ‚k¬¬hlýOC1ø©ÿ…~¡EVÇžQEQEQEnOøó_ ª•nOøó_   ”QP^Lm¬n'Q“Là}i¥waJJ)Éô3õOXiRyR3I0ëc$}}* é×Ó,'Ì�Øá|À0OÔW�I#Ë#I#v$±=I¦×¦°på³Üø©q'ÚóE.^ßðOe¢²¼9u%æƒk,¤—ÁRO|?¥j×›(òɧÐû*5UZq¨¶i?¼(¢Š“@¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®NËþG)ß“ùë+“²ÿ‘Ê_÷äþF±­¼}OCðUÿ :Ê(¢¶<ð¢Š(®gƳ¼zd1)!d“æ÷Àéþ}+¦®cÆÑ»iÖò(%_›Û#Šá̯õIÛ±3øN­i³½¶§m,d†Y§~yV¬éñ¼Ú�´q‚]¥\~uñT¯Ïos¹êôQE~†t–åÿ�Dú ©Våÿ�Dú ©@ ’5–'�ÆQÁV ×šjÞ½Ó.lO-¾~IQsÇ¿¡¯M''¥pú·Œç7 ›µ"S�5—%½À<]XWQI¨yO *QuÛO¥·óÐÃÓô;ýJeH uLüÒ:�ª>µé¶V±ØÙCkÜ�B‚{û×§øÒö)”_ž~b+qŽ+»ŠTš$–6 Ž¡•‡pj±n¥Ò’ÐÏ!§„Q”¨É¹u¾ŽÞŸðGÑEÆ}QEW-¢ÈÇuôýWS\¶‰ÿ#×Ñÿô!]¸_áUô7¥ðËÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€)ê¿ò »ÿ®Müª·�¿äsÿ]¿ «:¯ü‚nÿë“*­àoù\ÿ×oè+…/÷)ú£©¢Š+cÏ (¢€ â¬ÿÜoæ+µ®[Åš]î¡qlÖ°4¡† �Ž}ëÎÍa)áe«½?2g±Ô‚–�ÐQ^‰AVæÿ�Tü*¥[›þ=Sð  ”QEcø«þE»Ï¢ÿèb«ø7þEõÿ®�V‚ªU¹ãÑ>‚ªP]L;iW‹|Ã…Ç®Ó^I^Ë\Ž­àÏ>á§ÓåH÷œ˜Ÿ ìGò®Ì%hÂêGÏg¹}lO-JJöèqéþYöbLçi#>›Ž?LVŸà‰Êú„É僟."IobxÅvŠªˆ¨€*¨À XºÑšQ‰žE—VÃÎUª«]Y!h¢Šá>”(¢Š+–Ñ?äcºú?þ„+©®[Dÿ‘Žëèÿú®Ü/ðªúÒøeèu4QEqQ@Q@Q@Q@Q@u5gÒî•A,blߊå4oK£[É [¤�ßq,HǮ֊Êtܤ¤�ŽÜ>*©ºs‡2~v9ÏøN®çÊ/ûìÑÿ ÕÏüùEÿ}šèè¥ìê7à_Ö°ßóçñäsŸð�\ÿÏ”_÷Ù£þ«Ÿùò‹þû5[Mÿ‘¾ãýù+¬¬àªM_˜éÄË FJ>Ê÷IîÎsþ«Ÿùò‹þû5‘ªêòë—p1€#(Ø 9ɮꊩQœ•œ¿*xê¥Í V~¿ðŠ(®ƒË (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(Å_ò-Þ}ÿC_Á¿ò/¯ýtj±â¯ùï>‹ÿ¡Š¯àßù×þº5t¯÷wëú<¿ämð~§AEW1ìQ@Q@·‡ÿä=wþãÿèBºšå¼?ÿ!ë¿÷ÿBÔ×n?ø¿$oˆøÂŠ(®#¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�Rv‡ÌlÆIÉÏ46ø?ç™üèßüó?�CEM¾ùæ:7Áÿ<Ïç@ÑSoƒþyŸÎ�ðÏ3ùÐ4É¿ÔIþéþUg|óÌþuíÙäýÙû§¿µ qÝ÷�>ýÿÒ?ýš»:ã< ÷ïþ‘ÿìÕÙÖ8᣻3ÿz—ËòAEVÇQEÈøïýE—ûÏü…`Aÿ#½‡ý±ÿÑb·üwþ¢ËýçþB°aÁñņ!ÿÑb¼\Ëâ�ø£ú�ØŸ÷*^¬ôÊ(¢½£„(¢Š+7Ä?ò/jõÁÿ•iVoˆä^Ô?ëƒÿ*Ëü)z?ÈOcËäÿ‘Q?ëøÿè½KBÿ‘Mÿ¯Xÿô^['üЉÿ_Çÿ@êZü‹úoýzÇÿ Š2ÿùÒùž6þFUÂ� (¢µ= ¢Š(¯.?ò9j¿K�ýרחp,ÿÝoæ+£Wƒ`ýÙéë]µÿÝé|ÿ3zŸÃ�ÌŽŠ›|óÌþtoƒþyŸÎ¸Œh©·Áÿ<ÏçFø?ç™üè*mðÏ3ùѾùæ:†Š›|óÌþtoƒþyŸÎ€*\ÿǬßî7ò¬ýÛÿ¬û5nÝ4?d›ŸõmßÚ°¼÷oþ±ÿìÕŒÿ‹™èPÿs«ÿnþgcEVÇžQEÇøïîX}dÿÙk°®?ÇrÃë'þËX×þ;²ß÷¨|ÿ&kÚÿÇœ?õÍ•KE£Cö83Ï–½ýªmðÏ3ùÖ«cŽ!®KÇ?ê,¿Þä+³ßüó?�qþ<1˜,¶)_™ó“ì+ƒ5ÿsŸËóFsøN‡Oÿ�m¯ýqOä*Í3Nh³-3Ï’�ÿÙg|óÌþuÛOà^…"¶ßñâ>ƒùÔ[àÿžgó« Sì¹*vã¦jÀ£EM¾ùæ:7Áÿ<Ïç@:çü€¯¿ë‹*Çð7ü‚®?ë¹ÿÐEnëÍ Ð/ñÈlûV/€Ú1¤\oBOžzöEtÇøõ¬†Š›|óÌþtoƒþyŸÎ€!¢¦ßüó?�àÿžgó h©·Áÿ<ÏçFø?ç™üè*mðÏ3ùѾùæ:†Š›|óÌþtoƒþyŸÎ€!¢¦ßüó?�àÿžgó h©·Áÿ<ÏçFø?ç™üè*mðÏ3ùѾùæ:†Š›|óÌþtoƒþyŸÎ€!¢¦ßüó?�àÿžgó 6ÛþGVÿ}ÿô]erÖ¥?á9rTíÞügý“]~ø?ç™üë?SÐÌ~*á_© 6ø?ç™üèßüó?�lyä4TÛàÿžgó£|óÌþt 6ø?ç™üèßüó?�CEM¾ùæ:7Áÿ<Ïç@Õ¹?ãÍ~‚¢ßüó?�XrŸf©+Ç  4TÛàÿžgó£|óÌþt 6ø?ç™üèßüó?�CEM¾ùæ:7Áÿ<Ïç@ÑSoƒþyŸÎ�ðÏ3ùÐ4TÛàÿžgó£|óÌþt 6ø?ç™üèßüó?�CEM¾ùæ:7Áÿ<Ïç@ÑSoƒþyŸÎ�ðÏ3ùÐ4TÛàÿžgó£|óÌþt 6ø?ç™üèßüó?�CEM¾ùæ:7Áÿ<Ïç@ÑSoƒþyŸÎ�ðÏ3ùÐ4TÛàÿžgó£|óÌþt rv_ò9KþüŸÈ×e¾ùæ:ä,JÂm1*vûƶñõ= ÁWü,êh©·Áÿ<ÏçFø?ç™üëcÏ!¢¦ßüó?�àÿžgó k/^Òÿµ´Ó &C¾2zgÓñ­­ðÏ3ùѾùæ:έ8Õƒ„¶bjç�ÜZ\ZJb¸…ãqÆœÖç‡4 ‹›Ø®®"híâ`ãpÁr:í^‰¾ùæ:7Áÿ<Ïç^=Ž�:Šr•ÒèB¦“!¢¦ßüó?�àÿžgó¯pЖ_øôO ª•zB‚ÝIRW5_|óÌþt T½Ôì´ð ÝÊDO@NIü5jîê [)î Dˆ£gÆî¸¯!ººšòæK‰Ü¼ŽrI®œ=kvö<|Û4ú’Q‚¼ŸÜz�–±§ê ²Öé$îòäy«Õã‘ÈñH²FÅ]NU�Á½kEÔ#Ô4{k©#>c®«ƒúŠxŒ?²ÕlFS›2*mðÏ3ùѾùæ:â0!¢¦ßüó?�àÿžgó h©·Áÿ<ÏçFø?ç™üè*mðÏ3ùѾùæ:†Š›|óÌþtoƒþyŸÎ€Ûýzþ?ʯÕHZ#*…B®jÝQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò�üŽööÇÿEŠßñßú‹/÷Ÿù ÀƒþG{ûcÿ¢Åx¹—ÅñGõ;±?îT½Yé´QE{GQEVoˆä^Ô?ëƒÿ*Ò¬ßÿȽ¨×þU–#øRô�žÇ—Éÿ"¢×ñÿÐz–…ÿ"þ›ÿ^±ÿè"¼¶Oùþ¿�þ€+Ô´/ùôßúõ�ÿAeÿò-¥ó,ÿÝoæ+y~èúWm÷z_?ÌÞ§ðãóŠ(®#¢Š(¢Š(¢Š(+Ÿøõ›ýÆþU�à?»õ�ÿf­‹Ÿøõ›ýÆþU�à?»õ�ÿf¬güXüÏB‡û�_ûwó;(¢¶<ð¢Š(®?ÇrÃë'þË]…qþ;û–Y?öZÆ¿ðÙÝ–ÿ½Cçù3^×þ<áÿ®küªZŠ×þ<áÿ®küªZÕlqÏâa\—ŽÔY¼ÿÈW[\—ŽÔY¼ÿÈWkþç?—æŒçð�&Ÿÿ Û_úâŸÈUš­§ÿÈ6×þ¸§òf»iü Фm¿ãÄ}óª•m¿ãÄ}ó«¥Q@úçü€¯¿ë‹*Çð7ü‚®?ë¹ÿÐElkŸò¾ÿ®-ü«Àßò ¸ÿ®çÿAÓàKÔñëÈÒŸøYÔQEÌ{EPEP-aÿ#tßïÉýk©®ZÃþFé¿ß“ú×S]¸ïŽ?áFõ÷^�EW€QEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥QEQEQEQEQEQEQEQEQEQEQEQEQErvßò:·ûïÿ šë+“¶ÿ‘Õ¿ßý×YXÐÙúž†cñSÿ ýBŠ(­�<(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+“²ÿ‘Ê_÷äþFºÊäì¿är—ýù?‘¬koSÐÀüÂβŠ(­�<(¢Š(¢°¼W¨Éa¥……ŠÉ3lÜ:�Žqþ{ÖUëF�7R[!7eríÆ·¦ZÊbšò5qÁœ}qVíî`»ˆKo*J‡º×’Vž…¨É§j�²±òä`’/b þ•àÑÏe*©TŠQ�š©©é´QE}©n_øôO ª•n_øôO ª”KWÏö-öOÙäãþkÉëÙC)V‚0Aï\­á Ë{†{óíÉÈP~eöÇzîÁÕŒo3Ä:Õ¹jÓW¶ŽÇ5^›á\� Údc†ÿÐÍr:„µ¹—íhsó3ã8öèVðGmo.ØãPª=…ƒùÕJ¶ßñâ>ƒùÕ�RŠ(  ýsþ@WßõÅ¿•cøþAWõÜÿè"¶5Ïù_×þU�àoù\×sÿ Šé�ð%êxõ¿äiOü,ê(¢Šæ=€¢Š(¢Š(–°ÿ‘ºo÷äþµÔ×-aÿ#tßïÉýk©®ÜwÇð£zû¯@¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š¶ÿñä>‚ªU·ÿ�!ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9;où[ý÷ÿÐMu•ÉÛÈêßï¿þ‚k¬¬hlýOC1ø©ÿ…~¡EVÇžQEQEQEnOøó_ ª•nOøó_   ”QEQEQEQEQEQEQEQEQEQEQEQEQEÉÙÈå/ûò#]erv_ò9KþüŸÈÖ5·�©è`~ ¿ágYEVÇžQEËxÜ�°ÚŒsæœN+©¬ÍwKþÖÓš!eS¾2zgÐ×&:”ªáçnÑ2WG™TöD ûrà J¹¼ÒÜX]ÚJcžÞD`qÊõúõ¹áÏÜOyÝÌMÀ8Ár:qé_‡ÃU©YB1Öÿw©ŠM³¼¢Š+ïN‚Ü¿ñèŸAU*Ü¿ñèŸAU(¢ŠÈÔüG§éryR»I0ëc$}{ ¨ÅÉÚ(ʵjtcÏRV^f½‰§ø«MÔ&†xdc…€b mÑ(JÒB£ˆ¥^<Ô¤š (¢¤Ø(¢ŠkÈ‘!yUGVc€*ªj¶I±n¢-îq\ψo¤¸ÔÄEÀ_SÜÖ=zÔrÕ8)Mêθa¯¶zUƒá›é'‚Ki±‹ ôô­êó«Rt¦àúÓƒ„¹XQE‘!EPEPEPEPEPEP'¦ÿÈßqþü•ÖW'¦ÿÈßqþü•ÖV46~§¡˜ÿ?áAEVÇžQEQEQEnoøõOªU¹¿ãÕ? ©EP$Š9£1Ëȇª°È?…Cºl†$�:íE~”ú(¿Ar«ó[P¢Š(QEQEËxþC×î?þ„+©®[Ãÿò»ÿqÿô!]Mvãÿ‹òFø�Œ(¢Šâ0 (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¦Mþ¢O÷Oò§Ó&ÿQ'û§ùPÇчàO¿ô�ÿf®Î¸Ï}ûÿ¤û5vuŽøhîÌÿÞ¥òü�QE±ÀQEr>;ÿQeþóÿ!XÈïaÿlôX­ÿÿ¨²ÿyÿ�¬?äw°ÿ¶?ú,W‹™|QÿS»þåKÕž›EW´p…Q@fø‡þEíCþ¸?ò­*Íñü‹Ú‡ýpåYb?…/Gù ìy|Ÿò*'ýýW©h_ò/é¿õëþ‚+Ëdÿ‘Q?ëøÿè½KBÿ‘Mÿ¯XÿôF_ÿ"Ú_3ÆÂÿÈʯøQ¡EV§´QEåÇþG-Wéqÿ šõòãÿ#–«ô¸ÿÐMuá7—¡äæ_ÆÃÿ�G‚?ãÎëþºå]MrÞÿ�;¯úè?•u4±¿ï=ºÿÄaEW)�QEÆxßþ>,ÿÝoæ+y~èúV�ÿãâÏýÖþb·—î�¥v×ÿw¥óüÍê?1h¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€93ÿ#¿üÿd®²¹3ÿ#¿üÿd®²±£ö½OC0ÿ—_áAEVÇžQEÉxçýE—ûÏü…uµÉxçýE—ûÏü…yù¯ûœþ_š& Òiÿò µÿ®)ü…YªÚüƒmëŠ!Vk¶ŸÀ½ AVÛþ›¨Ç©[y¨6°8t=�p5ÐøP?Ú.Hû›F~¹ãú×~7 IRsгGEzQPºV:š(¢¼3„(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+“²ÿ‘Ê_÷äþFºÊäì¿är—ýù?‘¬koSÐÀüÂβŠ(­�<(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ¯;Zé÷7 2ÑDÎ> f¼‘ݤ‘�س±É'©5ìƳBñ8Ê:•aê yŽ­¡]éW ­<ù%Q�G¿¡®ü¢®žçËñ%²PœUâ¯ò2ëÔô ©/t+Yå$¹R¤žø$gô¯9Óô›ÍNeŽÞ*O2…_©¯P±´K mcåb]¹õõ?�V6Q²�S.£UNu÷moWÿ±EWœ}hQEÁë WWºûäÕ»«’u{¬ÿÏCT«êèÿ>ˆõ¡ð£¡ð ?h¹lpÖºšå¼(Ònûù×S^aþðþ_‘Áˆþ# (¢¸ŒŠ( Š( Š( Š( Š( Š( OMÿ‘¾ãýù+¬®OMÿ‘¾ãýù+¬¬hlýOC1þ$‚Š(­�<(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( [Ãÿò»ÿqÿô!]MrÞÿ�õßû�ÿ¡ êk·ü_’7Ä|aEW€QEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@2oõº•>™7ú‰?Ý?ʆ8îŒ?}ûÿ¤û5vuÆxïßý#ÿÙ«³¬pÿÃGvgþõ/—䂊(­Ž¢Š(‘ñßú‹/÷Ÿù ÀƒþG{ûcÿ¢ÅoøïýE—ûÏü…`Aÿ#½‡ý±ÿÑb¼\Ëâ�ø£ú�ØŸ÷*^¬ôÚ(¢½£„(¢Š+7Ä?ò/jõÁÿ•iVoˆä^Ô?ëƒÿ*Ëü)z?ÈOcËäÿ‘Q?ëøÿè½KBÿ‘Mÿ¯Xÿô^['üЉÿ_Çÿ@êZü‹úoýzÇÿ Š2ÿùÒùž6þFUÂ� (¢µ= ¢Š(¯.?ò9j¿K�ýרחùµ_¥Çþ‚k¯ ¼½'2þ6ühê<ÿw_õÐ*êk–ðGüyÝ×Aü«©¥�ÿx‘í×þ# (¢¹L‚Š( 3Æÿññgþë1[Ë÷GÒ°|oÿî·ó¼¿t}+¶¿û½/ŸæoSøqù‹EW€QEQEQEQEQEÉŸùÿàû%u•ÉŸùÿàû%u•�µêz‡üºÿ (¢¶<ð¢Š(®KÇ?ê,¿Þä+­®KÇ?ê,¿Þä+ÏÍÜçòüÑ3øN“Oÿ�m¯ýqOä*ÍVÓÿäkÿ\Sù ³]´þèR ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÕ�RŠ( Š( Š( Š( Š( ZÃþFé¿ß“ú×S\µ‡ü�Ó¿'õ®¦»qßÂ�ë(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šäí¿äuo÷ßÿA5ÖW'mÿ#«¾ÿú ®²±¡³õ= Çâ§þú…Q[xQEQEQEU¹?ãÍ~‚ªU¹?ãÍ~‚€*QEQEQEQEV^­£G©êÞ\ê0èkRŠºu%N\Ñz•8»£�O Þ™0òB«ýàIý1].Ÿa�l!‹$õf=XÕª+jغµ•¤ô.u¥5fQEsQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@åÿ�Dú ©Våÿ�Dú ©@Vf¥¯éú[ùsÊL½|¸ÆHúúSŒ\�’3«Z�(óÔi/3NŠÇÓüM¦j3c•£•¾êÊ1Ÿ§jا(Ê.ÒB£^�hóS’kÈ(¢Š“P¢Š(“ñ™*]5äHZ'åñü'ü+Ì‚IèzM1a‰rÆŠÞ¡@5éÑÌœ £(ÞÇT1.1³FO‡´Ù,­ÞY—l²ãå=T Ù¢Šà«VUfç-ÙÏ99;°¢Š+2BŠ( Š( Š( Š( Š( Š( OMÿ‘¾ãýù+¬®OMÿ‘¾ãýù+¬¬hlýOC1þ$‚Š(­�<(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( [Ãÿò»ÿqÿô!]MrÞÿ�õßû�ÿ¡ êk·ü_’7Ä|aEW€QEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@2oõº•>™7ú‰?Ý?ʆ8îŒ?}ûÿ¤û5vuÆxïßý#ÿÙ«³¬pÿÃGvgþõ/—䂊(­Ž¢Š(‘ñßú‹/÷Ÿù æoÚîÃ^·¾†ÝŸlq:eIVÂÚºoÿ¨²ÿyÿ�­;/øð·ÿ®Kü…yØœ/ÖdãÍk4îwâðT½YÌÂs­Ð>ûöÿãGü':×ýàÿ¿oþ5×QQõ,Oüÿqæò¾çþ=Õ㽕²çûÈãúӇ޵’|„FÿãOñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šå§K,Dèûg»‰'{\æÿá9Ö¿èýûñ¨/|]«ßYMk%„J’¡F+äø×kEt¼"Jλû‡Êûžu&Ÿyÿ‚?Ù¥ÛöÂßpôØ~™â¯ZxËY³²‚Õ4øJCÆ¥£|�9æ½ÿÇ�áýj¥zØN\>4æQ<ÊÙmIWu©Uqm%·c�ÿ„ï[ÿ t÷íÿÆ�øóZPIÓíÀI�ÿÆ»£¬ÿÈÿþ½ßÿA5Ó´Û·!•L.rúÃÑvG4ž?Ö$Kfû¨çúÓÿá;Öÿèýûñ©¼ ÿ ë¯úëýuUU'Nqä1ÁáñxЬñ _Éü'zßý ÿ¿oþ5›¥-æ¡®^]½³«K¬ØR,§�Ÿs^…EJÄF? ltÇ,ªêÂ¥ZÎ\®ö±ÇiZ½ö�‘Ãj¬²|Än?*¿ÿ v«ÿ>Pÿß þ5ÑQZÏNošTÕýO u¢ÝÜNwþíWþ|¡ÿ¾üi£ÆZ‘m¢Ößw¦ÖÏó®’¹kOù$ÿ}ÿ‘­hÎ�E'ìÖŠåBP’~îÄÿð—j¿óåýðßãGü%Ú¯üùCÿ|7ø×EEaõš?óé}ä{X)Åêš…öµ,>m®ÖL…¡ç?ZìÔa@ö¥¢³¯ˆUTb£d‰©S™$•¬QEsQ@Q@Q@Q@Q@™ÿ‘ßþÿ²WY\™ÿ‘ßþÿ²WYXÑû^§¡˜˯𠢊+cÏ (¢€ ä¼sþ¢ËýçþBºÚä¼sþ¢ËýçþB¼ü×ýÎ/Í?„é4ÿùÚÿ×þB¬Õm?þA¶¿õÅ?�«5ÛOà^… «mÿ#è?�T«mÿ#è?�X(¢Š(¢Š(¢Š(¢Š(¢Šå¬?än›ýù?­u5ËXÈÝ7ûòZêk·ñÇü(Þ¾ëÐ(¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( NÛþGVÿ}ÿô]ervßò:·ûïÿ šë+?SÐÌ~*á_¨QE±ç…Q@õ=B-2ÆK©Fvðª?ˆöÁÜøŸU¸”¸¹1.xHÀ�t~5�ÛJ…×%Q»Û àÿŸZá+åóœ]hÖöQm$ºu1œ�ìvŠ&šé,ïØ?˜v¤¸ÁÏ`k°¯&²�å¾·Ž<ïi.=s^³]ù6&­jrUíÔºmµ¨U¹?ãÍ~‚ªU¹?ãÍ~‚½’Ê”QEQEQEQEQEQEQEQEQEQEQEQEQEU[ëû}>6áð £’ÇÚ±—ÅÐ0Ö²õ üª%R1vl襄­V<Ð�ÑÑÑPÚÝCy͆CúCSU§}Q„¢âì÷ (¢�U cSM'O{–›;Q¼Æ¢¤ãN.rz zè¯1¸×µK™L�{*z,lTÀV߇¼Mp÷qÙß?˜²©!ê`}kÊ£�P©QBÍ_© ¢lì袊ö -Ëÿ‰ôR­Ëÿ‰ôR€+ß\]>âà ˜¢gÜ ×’Ë#Í+K#w$³¤×¯ÍO�È2’)VÄb¼·UÑî´›–IQŒYù%åaþ>Õß‚”U×S帒•Y(M|*ÿ&g‚A^© Ý½ö‰kq)ÌŒ¤1=È$gô¯5°Ó®µ+� ´Läž[*û“Ú½KO³M>ÂT9®3ê{ŸÎ«(Ù.¦\7Jª©:ŸfÖùÿW,ÑEç\QEV¼¾·°‹Ì�öç “ô˜ž(²i6´s"ÿx€­ak— q«M¸�±�Š=1ÿ׬êöèeÔÝ4ç»;©á¢ãy�©4K$ndÞŸ\×…n™íÉÊ€G§cý+¥¯+GØÔp9*C’N!EV$Q@Q@Q@Q@Q@Q@ž›ÿ#}ÇûòWY\ž›ÿ#}ÇûòWYXÐÙúž†cüHÿ…Q[xQEQEQEU¹¿ãÕ? ©Væÿ�Tü(¥Q@Q@Q@Q@Q@·‡ÿä=wþãÿèBºšå¼?ÿ!ë¿÷ÿBÔ×n?ø¿$oˆøÂŠ(®#¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò§eÿÿõÉ�¬Ïÿ¨²ÿyÿ�­;/øð·ÿ®Kü…aâËäz¿Üéz²z(¢·<ó”ñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šç¼qÿ–ŸõÑ¿•t:gü‚lÿë‚è"¼ºïõ} âeª(¢½BËgþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEP\µ§ü޾ÿÈ×S\µ§ü޾ÿÈ×ná©þoGizMQ\FEPEPEPEPEPEPEP&äwÿ�ÿì•ÖW&äwÿ�ÿì•ÖV4~שèfòëü((¢ŠØóŠ( ¹/ÿ¨²ÿyÿ�®¶¹/ÿ¨²ÿyÿ�¯?5ÿsŸËóDÏá:M?þA¶¿õÅ?�«5[Oÿ�m¯ýqOä*ÍvÓø¡H*ÛLjúçU*ÛLjúçVJ(¢€ (¢€ (¢€ (¢€ (¢€9kù¦ÿ~Oë]MrÖò7MþüŸÖºšíÇ|qÿ 7¯ºô (¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(“¶ÿ‘Õ¿ßý×Y\�·üŽ­þûÿè&ºÊƆÏÔô3ŠŸøWêQElyáEPsÁÌ È7e=ë‹¿ð­­¼øMVTôIد5Ðø“S}3K/ ÄÒ6Ä?Ýõ5æîí#—v,Ää’rM|þqˆ ¤©ÊÒ_+M­�Bм=i§t&3òÈ>èú�nךè´ºn¡Þ~Ï#‘3Ç=þ¢½*»rªôjѵ(òÛtTk@«rÇšýT«rÇšýze•(¢™4«Lÿv5,~€f�6’»iá·MóJ‘'÷�‚�Ö›ݵÐ&Þâ)@ëå¸l~Uåš–¥qª]µÄîNOʹá ¨-îf´�f‚FŽE9 ¦»Ö ÝÕê|¼¸•*¶Œ=ß]O`¢©i7ßÚZ\x�~`;pQWk…¦�™ôÔç�SŽÏP¢Š)QEQEQEQEQEQEQEQEQEq%™äÖdF'ljª£ê3ýkºÿh²^0º¶¥ŸÞ£Þ¹•Ó¯ZO,ZO»Óa¯:´$¦Ï¬À×¥*I¥e©±á)œ^ÍNÆ�qà�ýk®¬}Hm:’lyòuøG¥lWe¸Á&x…XTÄ9C`¢Š+Sˆ+™ñ¬.úl¨%#“æöÈàÿŸZé©“Cð¼R xÜa”ô"¹ñT=½S½®&®¬yZÓa{�NÚ(ÁÞÒ.1ÛžµÕÜx"”µ½ãF‡ø]7cñÈ­]#ÃöºA2!2ÎF �Ø{ÕóT2lCª•EdºÜÉAßSZŠ(¯­6-Ëÿ‰ôR­Ëÿ‰ôR€ B##Þ–ŠEP£ €RÑEQEQEq~ ²{}EæÚ|©ŽàÞýÅdÖ·ˆ/ãRx‰>\'j¯¿sY5õnocmìz”¯È®u^²x¡’êEÇ™€™ôõ®‚¹ÿ Þ<°Ëlä‘3ØÕÐWƒ�æöòæ8+ßÚ;…Q\¦AEPEPEPEPEPEP'¦ÿÈßqþü•ÖW'¦ÿÈßqþü•ÖV46~§¡˜ÿ?áAEVÇžQEQEQEnoøõOªU¹¿ãÕ? ©EPEPEPEPEP-áÿù]ÿ¸ÿú®¦¹oÿÈzïýÇÿÐ…u5Û�þ/Éâ>0¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@s~$ñ÷…ü%"Å­jðÛÎÃ" $˜õÚ �=ÍkkZ€Ò4-CReÜ,í¤¸+ë±Kcô¯œþ|<‹âeΫâoÝ\M¹)¶7ÚÓJ@f,{( ¸×¶9öÏ|Nð‰ïÏLÖck¶û°Ê�7²îqö®º¾uø­ð‡K𧇿á$ðÜ—6ÿd•<è^RØ€WCÔÅ{÷ÏçØ¾ëÓø—áö�«]×BVVþó£-ø•'ñ ¢Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPL›ýDŸîŸåO¦Mþ¢O÷Oò¡Ž;£ÀŸ~ÿéþÍ]�qžû÷ÿHÿöjìë?ðÑÝ™ÿ½Kåù ¢Š+c€(¢Šä|wþ¢ËýçþB´ì¿ãÂßþ¹/ò™ã¿õ_ï?ò§eÿÿõÉ�¬!üY|�B·û�/VOEVçžrž8ÿ�KOúèßʺ3þA6õÁ?ô\÷Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW—Cýþ¯¢!|LµEW¨YlÿÇ�áýj¥[?ñãøZ©@QÖä ÿ^ïÿ š½TuŸù_ÿ×»ÿè&ª1Ä~�ò0ü ÿ ë¯úëýuUÊøþA×_õ×ú ê«\OñYÇ”¹SôýBŠ(¬H(¢Š+–´ÿ‘ÂO÷ßùêk–´ÿ‘ÂO÷ßùíÂ|5?ÂÍèí/C©¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠäÏüŽÿð?ý’ºÊäÏüŽÿð?ý’ºÊÆ�Úõ= Ãþ]…Q[xQEVV·¢.²�«Nbò‰<.sŸÇÚµh¬êÒ…X8M]15r;x¼‹h¡Î|´ Ÿ\ T”QV’JÈaVÛþkEÙèšÎUafΪ8*õ£ÍèuTUkø5 q4ã¡SÕO¡«5i¦®ŽyEÁ¸ÉY ¢Š)’QXþ$ÕLÓ7Bq4­±÷}MgZ¬hÓu%²vW4¥»¶�‚ÍqlzpëR«+¨e`Êzr y»HåÝ‹3–'$Ö¿‡uy´ýB(‹“m+t'�žâ¼J9ê�EÆÉõ¹ ¦§£ÑEïšåÿ�Dú ©Våÿ�Dú ©@PH$àPE `Ã*A¢–€ (¢€ (¢€9iòAx×J¤Ã/$�ájÄ­oÞ=Æ¢ðäùP�¡}ûšÉ¯§Âó{óïcÔ¥~Es¯ðæŸ%­»Ï2•yq…=BÖÝsþ¼ya–ÚBH� ìjè+ÁÆsûysîpV¿;¸QEÌdQEQEQEQEQEQErzoü�÷ïÉ]erzoü�÷ïÉ]ecCgêz�ñ#þQElyáEPEPEPVæÿ�Tü*¥[›þ=Sð  ”QEQEQEQEQEQ´Ò­¬®¤¸ˆ¾÷Ç#“ŸéW¨¢ªs”Ýäî7&õaETˆ(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@ÿŽÿäžx—þÁW_ú)«‡ýž?ä›Kÿa ô¯Añ]�Æ©àíoO´@÷7Z|ðB„�¹Ú6U<H¯ŸtO|gð剱ÒÚ[2㼃Ž<Ÿa@Ãñ‡þIF¿ÿ\“ÿF%Wø%ÿ$‡Bÿ·�ý(’¼³Sð—ÆígN›OÔd–âÒ`‘=ä`>¾ Ri>øÛ¡é�éÚcÉmgï.$¼ƒ ’Xõ>¤ŸÆ€>”¢¾wþÅø÷ÿ?“ÿà]¿ø×ÑQE5ÝcFv8U“í@ÿˆ¼m¢øfE†ög{–„.çÔòüM'‡¼q¢x–cog4‘Ü�Ÿ"uÚä{rAü rß -—Y¿Öz§ýú�ÿ‹­o|DÒÎÞö9Š3î™.Ñ�sþ ñ†¼?àËu;ëxîe/#&Ã# ¹!AÇu®÷JÔt­Z´ésÛ΃‚Ñc+ìGQøÐu½{Mðõ—Úõ+�dáF2Î}kžÓ>(xsS½K_2âÕÜáæ0ªÇê ÇãŠÄ»‰†€™7ú‰?Ý?ʤÁô5Àùp~éþT1Çtaøïßý#ÿÙ«³®3ÀŸ~ÿéþÍ]�c‡þ;³?÷©|¿$QElpQ@�ŽÿÔY¼ÿÈV�—üx[ÿ×%þB³†€Š\CF¡ ¢—Ðуèh(¥Áô4`úJ)p} >†€Š\CF¡ HÿÈïÿÿÙ+¬®L�ø­ÿàû%u¸>†±£ö½OC0ÿ—_áBQKƒèhÁô5±ç‰E.¡£ÐÐQKƒèhÁô4”Ràú0} %[oøñAüꮡ«L?ЇÐ:©E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} ZøòAU*Û�ô!ôWÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4É[Èêßï¿þ‚k¬®NØÅlÿï¿þ‚k­Áô5� Ÿ©èf??ð¯ÔJ)p} >†¶<ñ(¥Áô4`úJ)p} >†€Š\CF¡ «rÇšýUÁô5jAþ†¿A@(¥Áô4ɤC$¯�ˆ¥˜ûšÚJì$‘"Bò:¢Žìp)±OêZ)R@;£^Yªj·:­ÛM;�¹ù#Ï=Wµ»žÊág·•£‘{ƒ×ØúŠîX'Ë«Ôù‰q,[(^=ï¯ÜzýSJ½–™Ø\y‹Èˆàþ¢®`úâi§f}4'‘SŽÏQ(¥Áô4`úE E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐ âWvÖ¥VÎT/ÓþdÖEvºî†ÚŽ'ƒu ð�sk ê�&ϲ8>¤Œ~uçÕ§.w¡õX,]B+™&‘ÂNãPš1�†,Ÿ¨#Ì×_Yš.�ý™!§“ïÐ{ ÔÁô5×F.0³<}hU®å „¢—ÐуèkSŒJçü]c%Þ”²Ä¥šÞ@þî9þ•Ðàú0} cˆ¢«Ò•9uWV†ŒC_JjZ—þ=è*¥[”¢'ÐU\C@Í*A“Hp‘©f>Àf¼·UÖ.µk–y]„Yù"åQþ>õé×ÖÍu§Ü[Ž ±2îF+É%‰á•â‘Jº¬§¨5ß‚Œ]ßS帒­X¨A|.ÿ6X°Ô®´ÙĶҲ�y\ü­ìEzŽŸxš…„7H0$\ãÐ÷�yœ’kÕ49,tK[yT‰I`{IÇëU�ŒlŸS.«UÔ�?³o¹ÿW4h¥Áô4`úó�®Š\CF¡ #Ä0¤Z¼…Xà1Ý?çŸÆ²êþ¶®ºÅÈ|ä¶F}1ÅP¯©Ãÿ >ˆõiüê<) g›p.X.ßAÿ×þ•ÑW1á5s%ËvaAúó]F¡¯ þñ/ë¡Á_øŒJ)p} >†¸ÌD¢—Ðуèh(¥Áô4`úJ)p} >†€Š\CF¡ ¢—Ðуèh(¥Áô4`ú·G¶ƒQ{äi<×,H$cž½«B—Ðуèi(¥±s©)»ÉÜJ)p} >†™QKƒèhÁô4”Ràú0} %¸>†ŒC@ Væÿ�Tü*®¡«SôTü(¥¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4”Ràú0} %¸>†ŒC@ E.¡£ÐÐQKƒèhÁô4%·úõü•_ªàùëǯò«ôQEQEW1â_ˆ^ðŒË³«G à ˆZI1êUAÀúâ­øÇ]ÿ„gÁú®² -mÙ£p\ð¹öÜEx׿…ÚŒ4©<]âÓ6¡-üÒ4Q4¬¡°Ä3¹R %�ÀÎ0;ç€~†TžæŒå$PÊqØŒŠó?üuð¯‡u9tè’ëR¸…ŠJÖʾZ08#s’=�õ·ñ?\>øi©ÜÚ7•7”¶¶Ø<«>#Ü ŸÂ¸/‚ ôy¼*¾"Ö´ë{Û›×o³¥ÌaÖ8ÔíÈSÆIçÓï�óÁ¼5ã‰Mµ„ÒÛß…-öK¥ ìR¸$7àsí]­|õñŸÁÖ> ¸Ò™é^’ÆÇ—U©ñòáºÞÖÑšåï×îÿ‚Yðäm¥è6¶²'ï~zIÇáœV§Û÷?Z«EyÒ““mŸ[JœiS�8앾â×Û÷?Z>Ø?¹úÕZ)¾Ø?¹úÑöÁýÏÖªÕ-GTƒMŒrÎßu©ª„%7Ëv4›vF¿Û÷?Z>Ø?¹ú×"ž,gÏi„ÿeòGé[Ö·PÞ@³BÛ�þ`úÖ®­%y«:r‡Ä�¶î~´}°sõª´V¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@¾Ø?¹úÑöÁýÏÖªÑ@.ØD˜ÎqÅCöÁýÏÖ–_øôO ª”kíƒûŸ­djº.—¬IæÜÛ›§›mcõì»E8ÉÅÝ3:´iÕ�%EuæféžÒ4¹Äñ[<³/*ó>í¿AŒVçÛ÷?Z«E9JRw“èÇ–œR^E¯¶î~´}°sõª´T𖾨?¹úÑöÁýÏÖªÑ@ç‹®m&–%µ¨åÃpÐú×1Wµ’N¯u““¾¨×ÓáaÉF(õ)G– ÷‡/,Æ”©k R§÷�›'w©­o¶î~µÆøLŸ>äg�«Çâk¨¯ JòGhòÍ¢×Û÷?Z>Ø?¹úÕZ+”ȵöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ¦yvDÎ8¬ú·7üz§á@ öÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVеöÁýÏÖ�¶î~µVŠ»Ï™ ]¸Ï½OT-¿×¯ãüªýQEQEq?­%½øS¯Å%Ö”ãû©"»~Šj—Á-NÛPø[¥Å©’ÌÉÈ?…ƒ’3õVSø× M wIȲE"”ta�ÊF5àZŸÁïøWY¹¼ð°Ég9ÿQö�*E•³ò¸‰çÛ½MûFk^ö'†-[ÌžI Ô‘©ç?r1øåëÚt )4?éÚTxÛgm9ʨþ'šñßü×á.�Äþ6½Yî �M&c+É û¬íÓŒOAÐuôˆšŸ‰4¯ ý£Â¶fïR3¢yb.ƒ“�Às@/í©Aƒ´Ý0¸ûMÅè•S¾ÄFþn£ñ¯P𽜚w„´k”¬¶Ö0BàõcP•xß„¾ø§Äþ,‹Ååb!`ñÚÈÊÍ!*¥WåD�½ý9Í{ÕQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò§eÿÿõÉ�¬Ïÿ¨²ÿyÿ�­;/øð·ÿ®Kü…aâËäz¿Üéz²z(¢·<ó”ñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šç¼qÿ–ŸõÑ¿•t:gü‚lÿë‚è"¼ºïõ} âeª(¢½BËgþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEP\µ§ü޾ÿÈ×S\µ§ü޾ÿÈ×ná©þoGizMQ\FEPEPEPEPEPEPEP&äwÿ�ÿì•ÖW&äwÿ�ÿì•ÖV4~שèfòëü((¢ŠØóŠ( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(“¶ÿ‘Õ¿ßý×Y\�·üŽ­þûÿè&ºÊƆÏÔô3ŠŸøWêQElyáEPE2YRšYX"(Ë1èr÷>7�%+ohÒ ?}Ÿn çÄbèáííek‰É-ήŠÈÒ•ÁשjÚjjº{Û9ÚOÌ�ýÖ yýÎ�ªZÊQ¬å~xh”¸?•|¶s†ªëûD®šûŒj'{•lf{{ûyc'zÈÇÖ½b¸¯øfãíqÝßGåGܱ·ÞcÛ#°®Ö»ò\=JT¤ê+_dU4Ò ·'üy¯ÐUJ·'üy¯ÐW´hT¢ŠF`ŠYŽ ’{PÑ^s«ø¦öúáÖÚg·¶ á˜z“×ðªÖ#Ô¬fVûD“GŸš9X°#ñé]k7õ< qUäIµÜôú* ;¨ïl⹈ü’.ážÞÕ=rµgf{Ñ’’RŽÌ(¢ŠC (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€!º€]ZMnÇTd'Ó#ä÷–“XÝ=½Â‘¿¸ö¯^ª÷v—ÊêÞ9@é¹yC]zþÉ»ìy®WõÔœ]¤�%Š)'•b‰ Èç ª9&½WH²:v“ojÄEù±êNOêiÖše�‰&ÖÖ8˜õ`9üúÕºxŒGµÑ-ʲŸ©79»Ééò (¢¹�h(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š)“¨“ýÓü©ôÉ¿ÔIþéþT1Çtaøïßý#ÿÙ«³®3ÀŸ~ÿéþÍ]�c‡þ;³?÷©|¿$QElpQ@�ŽÿÔY¼ÿÈV�—üx[ÿ×%þB³ƒùÕJ¶ßñâ>ƒùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¸ŸÊòk Œ~XÕB�¨Ïõ®Ú°|A¢½ñ[›` Ê0ËœnãX׋”4= ¶¬)W¼Î:·ü'+®¡,@��H÷cùšËeù“`³Ÿwû†º½Gm:&–lyò ?„zW-K�3ÙÌq• F÷ocfŠ(¯@ù`¢Š(¢Š(¢Š(«rÇšýT«rÇšýT¨/¢iôû˜SïÉ*ýH"§¦É"ÅÈç €±>€S[“4œZ{:ÊUа ƒ‚jJ·©Þ�CQšèF±‰!T?z¯žTÉ&Õm¬k ƒìE{©»]Ÿ—Î1Sj.êûž™á˜$·ðõªHb `ö’?CZÕWN¼MCO‚ê1…‘s�CÐ�έW‡6Ü›géxhÆ4!;¤•ŸÈ(¢Š“p¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢°uýmìX[[&#,äghÿæ—VÔMâòlû¹#òéXO»–,«Z÷I=�C¢²4-\êP²Jž?½ŽŒ=k^µŒ”•ÑÃV”©MÂ{ ¢Š*ŒÂŠ( Š( Š(  rÿÇ¢}T«rÿÇ¢}T Š( Š( Š( Š( k_ÖeŠsglå6��Ç\ú ÀK˘äÞ—†õ jÞ» C«Ï»£�àúƒYÕô¸jTãEYn�N”" ¬vÚ&¦Ú�³ qçG€Øî;Ô®kÂ�¶n'?s„ç¯øWK^2…iF;5¢£6�QEÌdQEQEQEQEQEQEQEQEQEQEQEnoøõOªU¹¿ãÕ? ©EPEPEPEPEPEPEPEPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEÉ¿ÔIþéþTúdßê$ÿtÿ*ãº0ü ÷ïþ‘ÿìÕÙ×àO¿ô�ÿf®Î±Ãÿ ÙŸûÔ¾_’ (¢¶8Š( GÇê,¿Þä+NËþ<-ÿë’ÿ!Yž;ÿQeþóÿ!Zv_ñáoÿ\—ù ÂÅ—Èô+¹ÒõdôQEnyç)ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAÏxãþ=-?ë£*ètÏùÙÿ×ÿÐEyt?ßêú"ÄËTQEz…–ÏüxþÖªU³ÿ?‡õª”Ugþ@—ÿõîÿú «ÕGYÿ�%ÿý{¿þ‚j¡ñ#Gðgèÿ#À¿òºÿ®¿ÐWU\¯�äuÿ] ®ªµÄÿœyGû•?OÔ(¢ŠÀô‚Š( ¹kOù$ÿ}ÿ‘®¦¹kOù$ÿ}ÿ‘®Ü'ÃSü,ÞŽÒô:š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( LÿÈïÿÿÙ+¬®LÿÈïÿÿÙ+¬¬hý¯SÐÌ?å×øPQE±ç…Q@Q@Q@[oøñAüê¥[oøñAüè¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ßþ<‡ÐUJ¶ÿñä>‚ªPEPEPEPEPEPEPEPEPEPEPEPEPE‰¯kM§í‚ß{ –<íãS)(«³Z4gZjÜÛ¢¼økˆ“Û%Ï»qùt®«CÖ¥$  ã뎌=k:uã7c¯–Õ¡vî�z(¢¶<ð¢Š(¢Š(¢Š(«rÇšýT«rÇšýT¨o!76Wƒ,l€údb¦¢„í¨¥$Óêxì±<2¼R)WBU”ö4ÊõOÃÚ~ªþdñ²ËÓÌŒàŸ¯cPØx[LÓæ*<Ò)Ê™H8?@¯McaËvµ>2\9ˆö¼±’åïÿ›ÃÖ’YhVÐÊ“˜Ù$ãõ­J(¯:Ræm³ì(ÒT©ÆœvI/¸(¢Š“@¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(…ñ²ë“–0R=ÆÐ?¥eW{«é0jP†wIâNÀzjåSHG¸òÿ´¬±ž¢CþçÕ¥%;÷>£Œ§*)=U‹~V:œ¬Ê" Ÿ©á]�RÓtØtÛo.#¹›—sÕ�]®ºPp�™ác«Æ½g8ìQEjrQ@Q@Q@åÿ�Dú ©Våÿ�Dú ©@Q@Q@Q@Q@&´ÎÚÅÎþ¡°>˜â¨W_­hfùþÑn@›e=ÿ¯XiáýIäÚ`;³0À¯¢Ãb©:Jí+#ѧV‹SCÂlþeÊó³ k§ª:^œšm¯–çc—oSþz¼\]HÔ¬åŽ*²R›h(¢Šç3 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò§eÿÿõÉ�¬Ïÿ¨²ÿyÿ�­;/øð·ÿ®Kü…aâËäz¿Üéz²z(¢·<ó”ñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šç¼qÿ–ŸõÑ¿•t:gü‚lÿë‚è"¼ºïõ} âeª(¢½BËgþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEP\µ§ü޾ÿÈ×S\µ§ü޾ÿÈ×ná©þoGizMQ\FEPEPEPEPEPEPEP&äwÿ�ÿì•ÖW6ln¿á-ûO�þFìïÇwÒV4S\×îw㤥ììþÊ (¢¶8Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®'ÄѺkí�®ŠWòÇô®Úªju¾¥—09«Ž«YVƒœlŽÌ%aësËm�;­ÿ Æí¨Ë "ÆA>äŒ*²Ohùþu½ecŸn!�p:’z±õ5ÏJ„”¯#ÕÇf4eE›»eš(¢»Ož (¢€ (¢€ (¢€ ·'üy¯ÐUJ·'üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ d’Ç fI]QVc�O®7ÄW�>¢ÐdùPð©îk£ ‡uçÊiJŸ´•Ž�5­9äØ.“>à�ù‘о##‘^k]O…ïHåµv$F&{â»1XJð{Uèǚ'CEW–r…Q@Q@Q@Q@Q@Q@‡Š/ä{ϱ+`ø‰çü+Ÿ­ÿXIïÛIŠ@Ù€ÇøVy•¯Îî}~“êñäíøõ:Ÿ ßÉ'™e#»ãÏaÐ�ÔWM\Ï…l$C%ìŠUYv&{ŒäŸÐWM]´/È®|öcÉõ™rL(¢ŠØá (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ dßê$ÿtÿ*}2oõº• qÝ~û÷ÿHÿöjìëŒð'ß¿úGÿ³WgXáÿ†ŽìÏýê_/ÉQ[EP#ã¿õ_ï?ò§eÿÿõÉ�¬Ïÿ¨²ÿyÿ�­;/øð·ÿ®Kü…aâËäz¿Üéz²z(¢·<ó”ñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šç¼qÿ–ŸõÑ¿•t:gü‚lÿë‚è"¼ºïõ} âeª(¢½BËgþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEP\µ§ü޾ÿÈ×S\µ§ü޾ÿÈ×ná©þoGizMQ\FEPEPEPEPEPEPEPEPEPEPEPEPVÛþýÿÒ?ýš»:ã< ÷ïþ‘ÿìÕÙÖ8᣻3ÿz—ËòAEVÇQEÈøïýE—ûÏü…iÙÇ…¿ýr_ä+3Çê,¿Þä+NËþ<-ÿë’ÿ!XCø²ù…o÷:^¬žŠ(­Ï<å$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEW-iÿ#„Ÿï¿ò5Ô×-iÿ#„Ÿï¿ò5Û„øj…›ÑÚ^‡SEW€QEQEQEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQÕµ$Ò´÷¹q¸�•ûÌz óû�T¹”È×’§<,LPʺŸÄï¤Å"ò±Ê7~ ŒÿŸZá+峜MU_Ù§d—ÞcQ»Øêü?âkƒw¥ôžjHv¬�÷”öϨ®Ö¼šÊ'žþÞ(þûÈ ~uë5ß’â*U¥%7{lʦÛAVäÿ�5ú ©Väÿ�5ú ö� ”QEQEQEQEKPÓ-õÂÊuû®½E]¢ª”4]˜ÓiÝâxM‚÷ŒW¸àþy­Û[XlàX`M¨?Sêjj+Z¸ŠµU¦îTêJ (¢° (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEV|ŠÞkü§ïÕ¡TdšA#çš�ctþTloîŸÊ�çËýóGŸ/÷Í7ctþTloîŸÊ�çËýóGŸ/÷Í7ctþTloîŸÊ�çËýóGŸ/÷Í7ctþUÈÞDŸ)û§·µMçËýóLžy|‰>s÷Oò¡Ž;£Ÿð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�­K$o°[|§ýRöö—ã¿õ_ï?ò¯c<ƒO¶Î<¥þB°‡ñeò= ßît½Y.Æþéü¨ØßÝ?•;Ï—ûæ�>_ïšÜóÎGÇ*E¥¦A¼oå]–­ý“eòŸõ Ûý‘X:‘ÞÒÏsg÷�ü«¡Òæ�i@9À�?ô^]÷ú¾ˆ…ñ2ÎÆþéü¨ØßÝ?•;Ï—ûæ�>_ïšõ ,~ÅŒã§ãUv7÷OåVË·Ù7çæÇ_Æ«yòÿ|Ðv7÷OåTu¥a¡ßü§þ=ß·û&´<ù¾j޵4‡C¿Ž »ÿè&ª1Ä~�ò0<¤é×Xþûú êö7÷Oå\¯€ätÓn‚¶?}ýuž|¿ß5®'ø¬ãÊ?Ü©ú~£v7÷OåFÆþéü©Þ|¿ß4yòÿ|Ö¤7ctþTloîŸÊ�çËýóGŸ/÷Í7ctþUÊZÿ Œƒ;ß�À×[çËýó\¥›°ñœŽͽùü vá>Ÿáfôv—¡ÔìoîŸÊ��ýÓùS¼ù¾hóåþù®#»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò«Lرƒœ?¯çËýóVYØZoÏÍ�Ïã@67÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Їì``犫±¿º*¶ÎÂÔ8?65[Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—û怱¿º*67÷OåNóåþù£Ï—ûæ€9o WJƒ„3 Ü{W ^·¨[®§e%¥Á-�ÄÄW sàíJ)HƒËš<ðÁ‚ŸÄùœßZu½¬ÓíÐÊqw¹‹fdÖæ,ùžbíÇ®x¯[ØßÝ?•rÚ…ÚÂå//Zdæ4^BŸR}k«óåþù®ìŸ R…9:š7Ш&–£v7÷OåV¤ìŠ0s�Uüù¾jË» U`~lkØ,©±¿º*67÷OåNóåþù£Ï—û怱¿º*67÷Oå\¦¯ã™-®ÞÁVB‡ +ýÜû×ëUì<uç*_ÆžY8/ ¯¾s] QǚǕ,ë¾ÍËçÓï;=�ýÓùQ±¿º*é¤�]%ÜŒR:Nóåþù®sÕNãv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü©Þ|¿ß4yòÿ|Ðv7÷OåFÆþéü«'[ñºhXa!®gžŠ=kœ_kMÿk'ý’‹�åXμbìÏB†[Z´9Õ’ó;��ýÓùQ±¿º*ÏÑõ×Õ-Ø“²dûê:}Eiyòÿ|Ö±’’º8ªS•98MY¡»û§ò£ctþTï>_ïš<ù¾i�7ctþTloîŸÊ�çËýóGŸ/÷Í7ctþTloîŸÊ�çËýóGŸ/÷Í7ctþTloîŸÊ�çËýóGŸ/÷ÍX”h£8WctþUnGal¬$j·Ÿ/÷Í7ctþTloîŸÊ�çËýóGŸ/÷Í7ctþTloîŸÊ�çËýóGŸ/÷Í7ctþTloîŸÊ�çËýóGŸ/÷Í7ctþTloîŸÊ�çËýóGŸ/÷ÍQ¿¿ƒNŒ=Á ·ÝP9jÊO[4˜x$Uþð þ•�¯ÜÉs¬NdbvŠ`+2½º}'M9êÙÝOÈôˆ$K˜VhNøØd0©67÷Oå\ׄ®æ_´@ù|8‡¡þŸ•tþ|¿ß5åb(ûŽ%HrIÄnÆþéü¨ØßÝ?•;Ï—ûæ�>_ïšÄ�»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò£ctþTï>_ïš<ù¾h»û§ò«SmPsÅWóåþù«2»-º°8'ÐM�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4Ý�ýÓùQ±¿º*wŸ/÷Í|¿ß4ëua:’¤uííWªœÈÓ(f$UÊ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEÉ¿ÔIþéþTúdßê$ÿtÿ*ãº0ü ÷ïþ‘ÿìÕÙ×àO¿ô�ÿf®Î±Ãÿ ÙŸûÔ¾_’ (¢¶8Š( GÇê,¿Þä+NËþ<-ÿë’ÿ!Yž;ÿQeþóÿ!Zv_ñáoÿ\—ù ÂÅ—Èô+¹ÒõdôQEnyç)ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAÏxãþ=-?ë£*ètÏùÙÿ×ÿÐEyt?ßêú"ÄËTQEz…–ÏüxþÖªU³ÿ?‡õª”Ugþ@—ÿõîÿú «ÕGYÿ�%ÿý{¿þ‚j¡ñ#Gðgèÿ#À¿òºÿ®¿ÐWU\¯�äuÿ] ®ªµÄÿœyGû•?OÔ(¢ŠÀô‚Š( ¹kOù$ÿ}ÿ‘®¦¹kOù$ÿ}ÿ‘®Ü'ÃSü,ÞŽÒô:š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÇšýT«rÇšýTªúƒ:é·M|Á •Ç®*ÅÓ³¹3�4Z›Ž+b™ 1ÛÂ�Ä¡cE  vŸ^DåÍ&ϾÃÓt¨Æ›w²KîAET›Q@Q@Q@Q@Q@Q@Q@Q@Q@7‰×[”¶pÊ¥~˜ùƒY5ßêšL:¤@9)"ýÙéì}Ea/„n|Ì5ÌA=@$þ_ýzá«B|Í£épy�EFnÍ+ ð’¹Ô&a�‚,©#È×_U4ý>6ßÊ„žY�V5nº©AÂ6g‹�®«ÖsŽÁEV‡ QEQEQEn_øôO ª•n_øôO ª”QEQEQEQEÍëÚ4³NníP¹aó ëŸQX)cw$›ÚRÞ› wwWpYÅæO Eíê~‚³“ĺ{É´™Py—�Ò½\6+©Ú0æHë§V§-’¹.‰¦:ټ̤Álvô§MGY:0ea�AÈ4êójNU&å-ÎiIÉÝ…QPHQEQEQEQEQEQEQEQEQEQEQEU¹¿ãÕ? ©Væÿ�Tü(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQES&ÿQ'û§ùS铨“ýÓü¨cŽèÃð'ß¿úGÿ³Wg\g�>ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�­;/øð·ÿ®Kü…fxïýE—ûÏü…iÙÇ…¿ýr_ä+_#ЭþçKÕ“ÑE¹çœ§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š+›ñ&¯-¼‚ÎÝÊ1\È㯰•š‚»7ÃЕzŠ:LóŠ+̃¸}áØ>s¸k®ðæ­%â½µÃn–1¹\õaïYSÄ)»5c·•΄=¢•ÒÜߢŠ+ òŠ( Š( Š( ­ÉÿkôR­ÉÿkôRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  rÿÇ¢}T«rÿÇ¢}T Š( Š( Š( Š( #^¹yõYU‰ÛØ£ÓÖ³+ ñ•(¹kÈPº?.d©õúV #ÈáK1èÉ5ôøYÂTcËÑ¥)'c¥ð­Ë²ÏlÄ•\2ûg­tu‘ i�alòL14¸Êÿt‚µëÁÆJ2­' Ž Í9¶‚Š(®c ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«sǪ~R­Íÿ©øPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¦Mþ¢O÷Oò§Ó&ÿQ'û§ùPÇчàO¿ô�ÿf®Î¸Ï}ûÿ¤û5vuŽøhîÌÿÞ¥òü�QE±ÀQEr>;ÿQeþóÿ!Zv_ñáoÿ\—ù Ìñßú‹/÷Ÿù Ó²ÿ� úä¿ÈVþ,¾G¡[ýΗ«'¢Š+sÏ9OÇ¥§ýtoå]™ÿ ›?úàŸú®{Çñéiÿ]ùWC¦È&Ïþ¸'þ‚+Ë¡þÿWѾ&Z¢Š+Ô,¶ãÇðþµR­Ÿøñü?­T ¨ë?ò¿ÿ¯wÿÐM^ª:Ïü�/ÿëÝÿôU‰â?ƒ?Gù~ÿ�u×ýuþ‚ºªå| ÿ ë¯úëýuU®'ø¬ãÊ?Ü©ú~¡EV¤QEËZÈá'ûïü�u5ËZÈá'ûïü�vá>Ÿáfôv—¡ÔÑEÄ`QEQEQEQEQEQEQEQEQEQEQEQEm¿ãÄ}óª•m¿ãÄ}ó  ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[øòAU*ÛÿÇ�ú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@p¾#ÿ�äÿEÿÐEwUÌø—J–YEì_åÄŠOë D[†‡¥•T�ýÿÒ?ýš»:Çü4wfïRù~H(¢ŠØà (¢€9ÿ¨²ÿyÿ�­;/øð·ÿ®Kü…fxïýE—ûÏü…iÙÇ…¿ýr_ä+_#ЭþçKÕ“ÑE¹çœ§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ùh~ÅÝëŽiÔQ@\(¢Š(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šá¼HîÚÜ¡³…U ôÀ?̚ɭ�KækR.òÕWëÆ­c×—WãgÙ`ÿÝá莃ÂNãP™v²~ Œ3]}r>—môñ`|ÑîÏÐÿõë®®Ü?ðÏžÍÞ_È(¢ŠÜó‚Š( Š( Š(  rÿÇ¢}T«rÿÇ¢}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­Íÿ©øUJ·7üz§á@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( ™7ú‰?Ý?ÊŸL›ýDŸîŸåCwF�>ýÿÒ?ýš»:ã< ÷ïþ‘ÿìÕÙÖ8᣻3ÿz—ËòAEVÇQEÈøïýE—ûÏü…iÙÇ…¿ýr_ä+3Çê,¿Þä+NËþ<-ÿë’ÿ!XCø²ù…o÷:^¬žŠ(­Ï<å$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEW-iÿ#„Ÿï¿ò5Ô×-iÿ#„Ÿï¿ò5Û„øj…›ÑÚ^‡SEW€QEQEQEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQET—pØZIs;b4>§ØWsã;ù%&Þ8¢�<7Ä×+G eQêúä–çyEsZŠF¡:ÚÝ¢Ç3}Æ_ºÇÓØ×KZáññç¦î†š{[“þ<×è*¥[“þ<×è+q•(¢Š(¢Š(¢Š(¢Š(¢°õ½m¬ŸìÖøó±–cÎßþ½iJ”ªË’;•9»#rŠáS\ÔRMÿjcìÀùWU¤êk©[ ,©Ã¨þbº+àªQ�3ÕT¡(+³BŠ(®3¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ŠñG•ý®v}ýƒÌúöý1Xµµâ{g‹UiÈ;&ƒîý?Zů2¯ÆÏ±Á[êð³èt~ò¾ÓqŸõ»ß÷sÏëŠë+”ð�³›‰®ˆ"0›õ$ƒý?Zêë·ü4|öio¬ÊϰQE±ç…Q@Q@Q@åÿ�Dú ©Våÿ�Dú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[›þ=Sðª•noøõO€*QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@2oõº•>™7ú‰?Ý?ʆ8îŒ?}ûÿ¤û5vuÆxïßý#ÿÙ«³¬pÿÃGvgþõ/—䂊(­Ž¢Š(‘ñßú‹/÷Ÿù Ó²ÿ� úä¿ÈVgŽÿÔY¼ÿÈV�—üx[ÿ×%þB°‡ñeò= ßît½Y=Q[žyÊxãþ=-?ë£*ètÏùÙÿ×ÿÐEsÞ8ÿ�KOúèßʺ3þA6õÁ?ô^]÷ú¾ˆ…ñ2ÕQ^¡e³ÿ?‡õª•lÿÇ�áýj¥GYÿ�%ÿý{¿þ‚jõQÖä ÿ^ïÿ š¨|HÇüú?ÈÃð/üƒ®¿ë¯ôÕW+à_ù]×_è+ª­q?ÅgQþåOÓõ (¢°= ¢Š(®ZÓþG ?ßäk©®ZÓþG ?ßäk· ðÔÿ 7£´½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šæ|m¿û* gg�ó~GÂ׬^ÙÃi%´ë”qÛ¨=ˆ®*çÁº„r‘E4yá·m?ˆ5óY¾´ë{ZjéþS‹½Ñ…g¿í¶þV|Ï1vã×{¥ÙþÊó]¥¤66ë +…IêO©®üf6”©8AݳzÕ¢ãËz(¢¼Sˆ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šå¼Q¨åÅ‚ÀÃHHÉÏ`=+™­DñëR»–@¬§Ô`éYæVmÍÜúü # ä�ð5××mÜÏŸÌ¡b$¢QElpQ@Q@Q@åÿ�Dú ©Våÿ�Dú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[›þ=Sðª•noøõO€*QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@2oõº•>™7ú‰?Ý?ʆ8îŒ?}ûÿ¤û5vuÆxïßý#ÿÙ«³¬pÿÃGvgþõ/—䂊(­Ž¢Š(‘ñßú‹/÷Ÿù Ó²ÿ� úä¿ÈVgŽÿÔY¼ÿÈV�—üx[ÿ×%þB°‡ñeò= ßît½Y=Q[žyÊxãþ=-?ë£*ètÏùÙÿ×ÿÐEsÞ8ÿ�KOúèßʺ3þA6õÁ?ô^]÷ú¾ˆ…ñ2ÕQ^¡e³ÿ?‡õª•lÿÇ�áýj¥GYÿ�%ÿý{¿þ‚jõQÖä ÿ^ïÿ š¨|HÇüú?ÈÃð/üƒ®¿ë¯ôÕW+à_ù]×_è+ª­q?ÅgQþåOÓõ (¢°= ¢Š(®ZÓþG ?ßäk©®ZÓþG ?ßäk· ðÔÿ 7£´½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢£¸™mí¥�¾ìh\ý͉´•ØË›Ëk4s¡v÷7YØôì£Ð{T1K$¬±;$Šr¬§ô ÝÕê|¤¸•û_vïâ{GF¾:–“otÀuÃcÔåW«‚IÅÙŸSN¤jAN;5p¢Š)QEQEQEQEQEQEQEQEQEq>&¸yuvˆŸ’%GÔŸéXÕ«â<ÿnO‘Ž÷Ȭªòêülû,K vGEá+‡S[çädß�BÖºÚã¼'Ÿí9xãÉ9?ˆ®Æ»pÿÃ>{5Ib]¼‚Š(­Ï8(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEG<¢ y%#!¶>ƒ4Åë^7¿:ôš†4ÅÔo¡¾‘ÛÆ{Ž£§BIñI£øßQ‹^‹DñF–º}Üÿê%�³“Ðu=zdÏGá>n‘ªjrü×7…]ÏS… üÜÓ¾/Á·@Óõò·×`#ŽªI?ª­z-Cwu �¤×W2à… »žÊM“}¦Î ñ�25|}Fj‡‰tfñ‡î´´¹û1¸ »7àñ‘×ëÞ€8ØeöÅjxcÇêz¼š³`tíY!2vÉ�“Œô8ç¾G9®�DÒÓDÑ,ôØÜ:Ûĸ]»�sŽÙ95çú„ðø‡ã—ý”ÂU°Œ}¦xùQ´±#=ú�õ8  Ïx¯WÑum3MÑ--®n¯“)'‚1Œ0Çñu¬Ïíô-iÿçþÚÖ‹5¸tÿ‹V3C5ÂÙZíXa]ÌîÁðÿ�ʵOÄù,®k>Ôtëw8Yœú¡4Úé_O¤ÛK©À�^²4IÑ[Ðr�]¨­n ½µŠêÚU– T::žÊñG‰lü'£ÿißE<°ù‹Ø-“ŸRjÚ¬éÖ¿ûƸ/ø^~ÿ ~«ÿ~ãÿâë»´oí+(/¡ùb¹�f@ý@a‘œwæ€бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐzdßê$ÿtÿ*·öI?¼µöŽ-ä9_º• qÝç�>ýÿÒ?ýš»:ã< ÷ïþ‘ÿìÕÙÖ8᣻3ÿz—ËòAEVÇQEÈøïýE—ûÏü…iÙÇ…¿ýr_ä+3Çê,¿Þä+jÂÕΟlr¼Ä¿ÈVþ,¾G¡[ýΗ« *ÇÙ$þòÑöI?¼µ¹çœgŽ?ãÒÓþº7ò®‡Lÿ�MŸýpOýV�ah¬ìËs#túWE¥Z»höDæÞ3ÿŽŠòè¿ÕôD/‰’QV>É'÷–�²Iýå¯P±çþ<ëU*ù‰¾Íåäf û$ŸÞZ¯TuŸù_ÿ×»ÿè&µ¾É'÷–¨kv®º Ä®¼‡ÿ5Pø‘Ž#ø3ô‘ÎxþA×_õ×ú ê«™ð .›tT�‰‡_ ®»ì’yk\OñYÇ”¹SôýJôU�²Iýå£ì’ykÒ+ÑV>É'÷–�²Iýå  õËZÈá'ûïü�v?d“ûË\�œL|k$yÞÿÈ×ná©þoGiz5cì’yhû$ŸÞZâ0+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+Õ¶ÿ�ôΙöI?¼µ9‰�¿—‘š¡EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yhïÿCè*¥_h˜Ûˆò3ÅAöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz*ÇÙ$þòÑöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz*ÇÙ$þòÑöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz*ÇÙ$þòÑöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz*ÇÙ$þòÑöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@êÜŸñæ¿ALû$ŸÞZ™âf·‚21@j;ˆVâÚXîÈ…ÐŒUϲIýå£ì’yhØM&¬Ï½²ŸO»{k„*è=GµEO4«h]ØáUFI5ìWZ4Èêe¦á’>†£´Ð-,Xµµ¼±þ 9üú× ±«—U©òrá©{_v~ïâTÑlN›¤[Ú·ßUËãÔœŸçWêÇÙ$þòÑöI?¼µÁ&äîϪ§N4à¡’±^бöI?¼´}’Oï-"ÊôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh€ñ4¾fµ"à-U~¼gúÖ=uþ&ðýÌ�öëdó1"''Žøï\šÅ#Iåª1|ãhþUæÖ‹Sw>»VÃÇ•ìµ7¼%.ÛéâÀù£ÝŸ¡ÿë×]Y>ðýÅœOspK ÀCÕWßë[ßd“ûË]”PIŸ?˜Ô…LCp+ÑV>É'÷–�²Iýå­Ž½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå Ëÿ‰ôR¯¼LÐ*21P}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz*ÇÙ$þòÑöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz*ÇÙ$þòÑöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz*ÇÙ$þòÑöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz*ÇÙ$þòÑöI?¼´^бöI?¼´}’Oï-W¢¬}’Oï-d“ûË@è«d“ûËGÙ$þòÐz·7üz§áLû$ŸÞZžH™áTdb€(QV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZ¯EXû$ŸÞZ>É'÷–€+ÑV>É'÷–�²Iýå  ôU�²Iýå£ì’yh½cì’yhû$ŸÞZe·úõü•_ªÑ[¼r†%p=*ÍQEQEQEQEQEñ í刜B¹úŒT”Pœ|—ÊÑõM6O–âÚð³¡í• üÐÓþ0OŸØX&Z{›ÀQV ¤Õ–®êþ Ôb×å×<1©¥…äã÷ñJ¹ŽCÜô=~‡žx¤Ò¼©\kÐë~)Ô㿹·ÿ�xa\F‡±è:ué×Ö€;+H~ÍeÏ•§ä1M¿¾·Ó,'½º�G]ÛØZÉñn›¬jº:ÛèwÂÊìL¬e22e@9POR?*£â/êÚÏ�môTº€ßl…n&šFÚå@Üs‚NXg‘@ô_ð‘üH (™´�–*¡?Ö\_åõÅw‡4Ï Ùý›N·d�ËÈ}Xÿ‘\E§†~$XÚCimâ 68!@‘ u@Àê«OIÒ> A«[K©ëÖ3Ù+ƒ4h>f_Aû±üÅnÚÝøvïÄ÷1[¥³kp/ï›ÈÄ¡xxŽF—Å0ZÜx[TŽð)ƒìÎÄ·b�~ �XÞ%ðCêz´zÞ�~Úv¬ƒ@2²``gðã¾GjÊ›Áž/×BÚø‡Ä‘5†AxíñØüª?<ý(÷†™¼—;ò³ýÜÿŽêêõ-*ÃX´û.£k̃yr ŒŽ†Ÿ§Ø[i–YZF#·…"ŽÃüjÍsð€xOþ€?÷î´� T[x?w Cb"ôU? Ò¬éÖ¿ûÆ€Γûæ�:OïšŽŠ“Î“ûæ�:OïšŽŠ“Î“ûæ�:OïšŽŠ“Î“û棞i<‰>s÷Oò¢™7ú‰?Ý?ʆ8îŒ?}ûÿ¤û5vuÆxïßý#ÿÙ«³¬pÿÃGvgþõ/—䂊(­Ž¢Š(‘ñßú‹/÷Ÿù Ö±šA§ÛçýRÿ!Y>;ÿQeþóÿ!Zv_ñáoÿ\—ù ÂÅ—Èô+¹Òõe¿:Oïš<é?¾j:+sÏ9o;=¥žæ'÷�ü«¢Òæ�i@9Ç�Ÿú®oÇñéiÿ]ùWC¦È&Ïþ¸'þ‚+Ë¡þÿWѾ&^ó¤þù£Î“û棢½BË¥Û웲wc¯ãU¼é?¾jsÿ?‡õª”'�'÷ÍPÖ¥�èwà¹Á·ýÕº£¬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‹à94Û ¬Gï¿ ®³Î“ûæ¹ÿÈ:ëþºÿA]Uk‰þ+8ò�÷*~Ÿ©'�'÷ÍtŸß5�éyÒ|ÑçIýóQÑ@yÒ|×'hì¥!¹û lV5¾?ˆžqôÅs•ËSË+${l«ÚÓSœ­sÓè®sÂú”“‰,æbÅr×þUÑÖðšœn�7BT*:rèQEYˆQEQEQEn_øôO ª•n_øôO ª”QEQEQEQE^òúÞÆ/2â@ ôIú ÌOX´›Y&EþñQ�ÐÖ»póêÓ'lgb�@+6½ªu7M9îÎÚxh¸ÞG¤G"MÉF :¹¿ Ü9Û’J.}½k¤¯/GØÔp9jC’N!EV$Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[›þ=Sðª•noøõO€*QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@6E-¨êT�N¢€NǦͬèí0¶³—2`6èKtÏøÕÿøH|Gÿ>�ÿ€í]5‚¢Ò²“=9朹§I6s?ð�ø�þ}ÿÚ¢>*×ÞI�¿ÜòNïʺºäæÿ‘ܾ¿ú¨©FÞóÕ›á«Q¬ä�$¬›û‰¿á!ñüú7þµð�ø�þ}ÿÚºj+Oe/æg/×iϘœ^¥s­jë\ÙˈÉ+¶k¯µFŽÒa†XÔŠp§Ê۽̱¯mÁEE.ÁEV§!Êxãþ=-?ë£*ètÏùÙÿ×ÿÐEsÞ8ÿ�KOúèßʺ3þA6õÁ?ô^]÷ú¾ˆ…ñ2ÕQ^¡e³ÿ?‡õª•lÿÇ�áýj¥GYÿ�%ÿý{¿þ‚jõQÖä ÿ^ïÿ š¨|HÇüú?ÈÃð/üƒ®¿ë¯ôÕW+à_ù]×_è+ª­q?ÅgQþåOÓõ (¢°= ¢Š(®ZÓþG ?ßäk©®ZÓþG ?ßäk· ðÔÿ 7£´½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šã|Qdñjj˜æŸFý+ »ý_P´²¶ÅÊ wð"Æwõ«“MBÁn<äÆW?wÍcÿÖý+‚´"§¹ôÙ~"¤¨$àÝ´OM~ö�? YH$–ñ�Wbg¿9?ʺš©§ÞÛßZ¬–Ü(à¦0WÛnºéEF)#ÂÆU�ZÎSV}‚Š(­`¢Š(¢Š(¢Š(Ü¿ñèŸAU*Ü¿ñèŸAU(¢Š(¢Š(¢Š(¢Š(˜ñ‘3\5åºVûê£�}k –I<´�Ùÿº&½Šôhæ3§F¯c¦—Ù£'BÓO¶f—t¸,?ºAZÔQ\5jJ¤Üå»0”œ�ØQE…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[›þ=Sðª•noøõO€*QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@Q@Q@rsÈî?ß_ýWY\œßò;�÷×ÿ@�o³êzvõ?ÂÿC¬¢Š+cÏ (¢€ (¢€9OÇ¥§ýtoå]™ÿ ›?úàŸú®{Çñéiÿ]ùWC¦È&Ïþ¸'þ‚+Ë¡þÿWѾ&Z¢Š+Ô,¶ãÇðþµR­Ÿøñü?­T ¨ë?ò¿ÿ¯wÿÐM^ª:Ïü�/ÿëÝÿôU‰â?ƒ?Gù~ÿ�u×ýuþ‚ºªå| ÿ ë¯úëýuU®'ø¬ãÊ?Ü©ú~¡EV¤QEËZÈá'ûïü�u5ËZÈá'ûïü�vá>Ÿáfôv—¡ÔÑEÄ`QEQEQEQEQEQEQEQEQEQEQEQEm¿ãÄ}óª•m¿ãÄ}ó  ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[øòAU*ÛÿÇ�ú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[“þ<×è*¥[“þ<×è(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@7‰]ßZ•[8EP¿Lgù“Y5Úëº!ÔvÏu ð�sk¡jm&ϲ0>¤Œ~uçÕ§.w¡õX,]B)É&‘ÂNãPš1�†,Ÿ¨#Ì×_Yz.�4¸»žO¼GAì+RºèÅÆgƒ�­ µÜ¡°QE©ÆQEQEQE[—þ=è*¥[—þ=è*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnoøõOªU¹¿ãÕ? ©EPEPEPEPEPEPEPEPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š(¢Šå$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEW-iÿ#„Ÿï¿ò5Ô×-iÿ#„Ÿï¿ò5Û„øj…›ÑÚ^‡SEW€QEQEQEQEQEQEQEQEQEQEQEQEU¶ÿ�ôΪU¶ÿ�ô΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEmÿãÈ}T«oÿCè*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnOøó_ ª•nOøó_   ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[—þ=è*¥[—þ=è*¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnoøõOªU¹¿ãÕ? ©EPEPEPEPEPEPEPEPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š(¢Šå$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEW-iÿ#„Ÿï¿ò5Ô×-iÿ#„Ÿï¿ò5Û„øj…›ÑÚ^‡SEW€QEQEQEQEQEQEQEQEQEô‰äUÈúÓ¾Í/÷?QV-?Õ÷ªz¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ°Ñ±µÙ�›ŠžŠ¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè  f—ûŸ¨£ìÒÿsõ~Š¡öi¹úŠ>Í/÷?QWè 66¡ù°8ªÿf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔU‡��°@>`=CìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@>Í/÷?QGÙ¥þçê*ýCìÒÿsõ}š_î~¢¯Ñ@I5² 0Нöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEf—ûŸ¨«ôP³KýÏÔQöi¹úŠ¿EPû4¿ÜýEX–6kuP9â§¢€(}š_î~¢�³KýÏÔUú(‡Ù¥þçê(û4¿ÜýE_¢€(}š_î~¢�³KýÏÔUú(‡Ù¥þçê(û4¿ÜýE_¢€(}š_î~¢�³KýÏÔUú(‡Ù¥þçê(û4¿ÜýE_¢€(}š_î~¢�³KýÏÔUú(‡Ù¥þçê) €I^¸­ l¿êŸýÓ@´QEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ³¥ÿZÿïѬéÖ¿ûÆ€EPEPEPEPEP\œßò;�÷×ÿ@ÖW'7üŽãýõÿÐc[ìúž†]½Oð¿Ðë(¢ŠØóŠ( Š( SÇñéiÿ]ùWC¦È&Ïþ¸'þ‚+žñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šòè¿ÕôD/‰–¨¢Šõ -Ÿøñü?­T«gþ<ëU(ª:Ïü�/ÿëÝÿôWªŽ³ÿ Kÿú÷ýÕCâF8�àÏÑþF�äuÿ] ®ª¹_ÿÈ:ëþºÿA]Uk‰þ+8ò�÷*~Ÿ¨QE�éQ@rÖŸò8Iþûÿ#]MrÖŸò8Iþûÿ#]¸O†§øY½¥èu4QEqQ@Q@Q@Q@Q@Q@Q@Q@Q@m?Õ÷ªz‚ÓýQÿz§ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Šnõþð£ÌOï΀E7ÌOïÎ�1?¼?:uß1?¼?:<ÄþðüèÔS|ÄþðüèóûÃó QH7B -QEQEQEQEQEQEQEQEQEQEQEQEQEQEQH]AÁ Z)¾bx~ty‰ýáùШ¦ù‰ýáùÑæ'÷‡ç@¢›æ'÷‡çG˜ŸÞ�:Šo˜ŸÞ�(u'‚hh¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š( œ šo˜ŸÞ�:Šo˜ŸÞ�bx~tê)¾bx~ty‰ýáùШ¦ù‰ýáùÑæ'÷‡ç@¢›æ'÷‡çJ# 怊( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ŠBÁz�)<ÄþðüèÔS|ÄþðüèóûÃó QMóûÃó£ÌOï΀E7ÌOïÎ�1?¼?:uÝêOÞê(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š)²ÿª÷M:›/ú§ÿtÐmQ@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬éÖ¿ûÆ´k:_õ¯þñ QEQEQEQEQEW'7üŽãýõÿÐu•ÉÍÿ#¸ÿ}ôXÖû>§¡—oSü/ô:Ê(¢¶<ð¢Š(¢Š(”ñÇüzZ×FþUÐéŸò ³ÿ® ÿ Šç¼qÿ–ŸõÑ¿•t:gü‚lÿë‚è"¼ºïõ} âeª(¢½BËgþ<ëU*Ùÿ�ÃúÕJ*޳ÿ Kÿú÷ýÕ꣬ÿÈÿþ½ßÿA5Pø‘Ž#ø3ô‘‡à_ù]×_è+ª®WÀ¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êQE`zAEP\µ§ü޾ÿÈ×S\µ§ü޾ÿÈ×ná©þoGizMQ\FEPEPEPEPEPEPEPEPEPÛOõGýêž ´ÿTީ袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(›}ãõ¤ªz¶¥—jn$F|¾Ð£¹ÿ"±?á3‹þ|ßþûáYʬ"ìÙÓK Z¬y¡£§¢¹�øLâÿŸ7ÿ¾ÇøQÿ œ_óæÿ÷Øÿ ^ÞŸsOììWò~Cü7ª]ß^]%Ä»Ô Ê0>^{WI^}¢êë¥\M+Bd.01ÍmÂgüù¿ýö?²¥Z*>óÔëÆà*ʳt¡¦�ŽžŠæ?á3‹þ|ßþûáOƒÅðK�k¬ZË©#º5²¾\2gpǶå@tQEQER1“è+ÇþüV×|yâKÍ;T´Ó¡†C:µ¬n¬X:®çn0Æ€=†Š( Š( Š( «Mþ´Õš¡¨\%¤3\È H�¹©À¤ÚJìQ\‡ü'°Ï„Ÿ÷ð…ðžÁÿ>ßÁþÁý«ƒþÁÿ‘<ñ:úå?¶/á8û�þ��ž^>æ<ÔðžÁÿ>ßÁþ�ý¶Ÿð“ÿky ·vï/w?wk‹™Q—³öSÚJûíÔ™MicÓ¨®CþØ?çÂOûø?Â�øO`ÿŸ ?ïàÿ íþÕÁÿ?àÿÈ®x�}IúÑ\gü'°Ï„Ÿ÷ð…uº}Â]à Ä`„•€zàŠÞ†2…vÕ)^ÃRObýQ]# (¯ñÅmwÃÿm<-ii§=ŒÒÛ#I,ndB`‡¿P°QEQEQEQHÇ O ¯øKñ[]ñç‰/4íRÓN†m êÖ±º±`ê¸;�¸Ãö+€øµã�OÀ~³Ôt¸-&šk±-Ò3(RŒÙYyÊŠÜð¿uâ�išÕìpÇstŒÎ°)v^$ô´ÑÑEQEQEQEQY>"ñ6‘áM)õfñ-­ÁÚ¹å¤o^EûJé±N˧ørêâ xyîV"­üèÜè¯%ðÏÇÿ kWqÚjVóéÈp²LÁáÏ¡qŒ}HǽzÈ!”2�Aw ¢Š(¯þ­¾•R­¿ú¶úW3®øŽHcxW�œ*£7h™W¯N„JŽÉtWÿ úÉÿøQÿ úÉÿøV¿V«ØàþÙÀÿÏÏÁÿ‘Ñkw2Ùè·w¶ÙQ2§Áª¿¹Ôtc-Ô†IVMÄrFþµ�ªxÎ-CLžÑl� «´1pqúUoø¦=OkgµyI�¾ààuJÙaçìš¶·8'›Púìdª{œ®ûÚ÷ìz5ÇÂÀƒþ�òßÁþÂÀƒþ�òßÁþ�Õªö;ÿ¶p?óóðäv5fõ�rz?‹ Õµ³²Dî RXÀÍu�ÿ«ük)ÂPv’;pøšXˆsÒwD”QEI¸Q\ÿŽ5Û¯ ø/TÖl£†K›Hƒ¢Ì BwÈþµÏü$ñΧãß^ê¤�ËÑ…Eª2©]ŠÜîfç$РQEQEQEQ^]ñƒâF±ðý´a¤ÛXÍöÑ7™ö¤vÆÍ˜ÆÖ_ïŸ^Õè¿—UðÞ—¨Î¨³]ÚE<Š€… È�’xÉ  +Ç|+ñ_]×>-\øRæÓNK®.¢Y"�ĸ�vÜ’ägåãò¯b Š( Š( Š( Š(é@å(øùá­ òK=> µyã%]á`�ƒèç?P÷¬/Ú[O’p·Þ¹‚,òðÝ,¬?«üèÝh¬ ø£Hñn”ºŽ�v·µ†0Ñ·÷YO ÖÅQEAq÷‡Ò¡©®>ðúW,þ.�]‚ÚÈÊÜkZT*U¿"½‹Œ%?…ÍÂaüù¿ýö?Â�øL"ÿŸ7ÿ¾ÇøVßQÄ/ä_°©Ø~¹©]Zjö�Ã&ØÈ Ë�½–#ŸÊº*àµMUu B•ˆ �@ÚNs‚Oõ­�øL"ÿŸ7ÿ¾ÇøWElGN 1׮Ɠ£.XÙ-ÍÂaüù¿ýö?Â�øL"ÿŸ7ÿ¾ÇøW?ÔqËùû �Ž�>úýjÝdéwɨÛGpŠTÁS؃ZÕÍ(¸·º2i§fQEH‚Š( Š( Š( Š( Š( Š( Š( Š( Š++ÄÚœÚ/…u}RÙciì즸�d©dBÀq‘ê(VŠó/„uˆêïªÛXÂlÚ!ÙQ×;÷ç;™¿º=+Óh¢Š(¢Š(¦Ëþ©ÿÝ4êl¿êŸýÓ@´QEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©<@ÈÇÍA’xÍ]¬éÖ¿ûÆ€ä¯üõOÎ�%çª~u 7’¿óÕ?:<•ÿž©ùÔ4PÞJÿÏTüèòWþz§çPÑ@y+ÿ=Só£É_ùêŸ�CEMä¯üõOÎ�%çª~u 7’¿óÕ?:ä&Aÿ Ð]ÃמßpWS\œßò;�÷×ÿ@�o³êzvõ?ÂÿC²òWþz§çG’¿óÕ?:†ŠØóɼ•ÿž©ùÑä¯üõOΡ¢€&òWþz§çG’¿óÕ?:†ŠåüwK;<:·ï§Òº-*t‹#æ Ì ÆÙÍxãþ=-?ë£*ètÏùÙÿ×ÿÐEyt?ßêú"ÄÍ%çª~ty+ÿ=Só¨h¯P²ñAö]»†1×·Z¯ä¯üõOÎ¥?ñãøZ©@y+ÿ=SóªÜ@hWçÍC‹y8ý“Vj޳ÿ Kÿú÷ýÕCâF8�àÏÑþF7€£¦Ý꿾ïôÖù+ÿ=Só®?À¿òºÿ®¿ÐWUZâŠÎ<£ýÊŸ§êMä¯üõOÎ�%çª~u �éy+ÿ=Só£É_ùêŸ�CEMä¯üõOι+4Æ’.á�ïÏn†ºzå­?äp“ý÷þF»pŸ Oð³z;KÐëü•ÿž©ùÑä¯üõOΡ¢¸Œ ¼•ÿž©ùÑä¯üõOΡ¢€&òWþz§çG’¿óÕ?:†Š›É_ùêŸ�JÿÏTüê(o%çª~ty+ÿ=Só¨h  ¼•ÿž©ùÑä¯üõOΡ¢€&òWþz§çG’¿óÕ?:†Š›É_ùêŸ�JÿÏTüê(o%çª~ty+ÿ=Só¨h  ¼•ÿž©ùÑä¯üõOΡ¢€/Û¨HÈ ž¢¥¨-?Õ÷ªz+É?hŸù'ßö‹ÿ@’½n¼“ö‰ÿ’qmÿa(¿ô (Šð¯À;ox[MÖ_Ä2À×� LBÔ0\öÎáš»¨~Ï:®•l÷žñ;É{Ü‘4FÄz:±ÁôÈüEzÃhV¿4.5­:£´PñÉtŠÊ}'"¶5ŸˆþÐìdº¹×ì$عÛβÈç° ¤ŸÇ§© à‡Ä-OÄF÷úô¯6¡džlSIþ±Ð¬¯êT•ç©Ï=+Øëç?€–—z¿ÄwÄÆ©ŽE$<ÉdzàúzÖ¯Æjžø�¡Om{z,¢´I¥²Šá’9È‘øe8ä(Ýè¯ ðÇÃ�ë>+Ó•ÓÂI£ÿÏô‘ÿ 噵q_¿ä‘k[ýx‡üMþ|O޵<ÖQßo slǯfo¡‡ŸnøÚC| Öˆ ƒörÿ®ñÐ7ìëÿ$âçþÂRÿè¸ëÒ/¼I¡iw‰g¨kZu¥Ó€V ‹¤�Ø€B’&¼ßöuÿ’qsÿa)ô\uÀ|qÿ’Å¥ÿ×µ·þ�zúj ¼½µÓ­$»½¹†ÚÚ1—šy"Œã–< ž¸�ŒòJ5ÿúâŸú1h«Óu}7Y�§ÒõKèQ¶4–³,ªà•$gqïSÜÝ[Ù[IsuQÚ¾mÒ¬uO�Ÿ. íì�Ûy‰#wÙà ¢™ù€üÏ4ï'ã/Ãñ/—ÿ {½~Ï6?=˜®«G×ô�Z›�#Q¶½ˆpÍ�¶ŸB:ƒìkÎìóà³må uA&?Öý¡wgé·¥y0°¿øGñ’ÎÎÖõå„Ë-�¾}¼„¬:g¯â ¬î7Ò¾eý›ÿäyÔÿìßú6:úiþã}+æ_Ù¿þG�OþÁ­ÿ£c ¦ëž×|sá ËäëÝ­´ØÉ„±yõ(¹ ~Î|bñÌÞ ð’ý�Âj—îa·nñ€2î|÷a^[ð×àÏü&Zwü$~%¼ºKk–- Q·ïgç—f`p Ϲë‘ÜÙô¿Š^Ö.ÞÏÄV†V8U˜4;� ÞOµuõáž-ýžtäÍqá‹›¨ï¢RËmpáÒl8IìyNµÀ?^Ü\ËàýZg�Å’É¥?2…ûÑsÏ‘é‚=0ïTQE�â/ù_ÿ×þU³XÞ#ÿ�5ÿýpoåYWþ½ä'±‡à;;k�&å§¶†Và@Ä £Öº¯ì½?þ|m¿ïÊÿ…q¾ Ötí7L¸Šòé"v›p #hô®—þ­þ‚þMþæåõpë 'ÛȘµbïö^Ÿÿ>6ß÷åÂ�ì½?þ|m¿ïÊÿ…Rÿ„«Cÿ „“…ð•hô�òoð®Ïm…þhýè«¢ïö^Ÿÿ>6ß÷åÂ�ì½?þ|m¿ïÊÿ…Rÿ„«Cÿ „“…ð•hô�òoð£Ûaš?z £ Ç–vÖúU³Am LgÁ(�IO¥nxwþ@ÖõÁ•s~4ÖtýKM·ŠÎé%u›q ÖºOÿÈÃþ¸/ò®<4¡,uG­e±+âfÍQ^¹a_2üKÿ“ˆÓ¿ëæÇù­}5_2üKÿ“ˆÓ¿ëæÇù­}5YÚŸˆ4]ãMWW°°i(.®R"ÀuÆâ3X~>ñö›à-ÝÝ5ä ­­ l4­ê}w?×âþðF±ñcÄrx·Å²Ht½ÿ*ò¾~Æ?†1Бî9 èÛ+ëMJÑ.ìn º¶“;&‚@èØ8ᇚƒVÖô½ ×íZ®¡mepy}zŸaV¢† +T†ÒxP*". ¾PÒ¬uO�Ÿ. íì�Ûy‰#wÙà ¢™ù€üÏ4ï'ã/Ãñ/—ÿ {½~Ï6?=˜®«G×ô�Z›�#Q¶½ˆpÍ�¶ŸB:ƒìkÎìóà³må uA&?Öý¡wgé·¥y0°¿øGñ’ÎÎÖõå„Ë-�¾}¼„¬:g¯â ¬î7Ò¾eý›ÿäyÔÿìßú6:úiþã}+æ_Ù¿þG�OþÁ­ÿ£c  /øJ²¾Æ%_ö‘ŒGæ`ãøÝ�߆j抺RéãCûöhÈûS2s·osÓ½ygíÿ"›ÿa4ÿÑRWUðþIF�ÿ\ŸÿF=v³M´4ò¤QF¥�Ý‚ª�Ô’z ã%ø»à(nͳø’ØÈ2‘Èéÿ}…+ú×’|[ñ6«ãoÃàMÏÙ¢�`tVÀšâ,ºŸ¦Ö>•Øéÿ³·…¡ÓV+ûÍBæð¯ÏÿÉ"Ñ>·ú>Jëäñ‰ª4©5�=5B‹F¹A1$d ™Ï ƒÒªëÞ2ðï†6�kW¶´vXݲäz„l{â¾qøŸ¬Ïáï�wºµ´k$ö­‘«ô-ä&3ø×¡xoà}®«mýµã‹»Ëífôy³D%("'øI–:€:Æh¾Ñ~$ø;Ä7kk¦kÖÒÜ9ÂE h™Ï¢‡'ØWU_/ü]øMgà« }oCžsdóe†fÜÑ1«+w¼ƒ�^=«á.¿wâ?†úeíô�-Ò‚I侯 êqŒŸ\Ї|J¼¿ø�ñ•|; Åmà¹[ªÆr<Ç#×;‰öP;W¿xáß…¼9§Gii£ZHʸyî"Y%�÷,Ä~ƒ�j§eð³ÃV1o—GSk‰.Iy²›äÝ»åÇûGÚЇ|iø_£Gá«�è¶QXÝZkˆ P‘Ë ´pg9Fsž+kà‰nu¿˧ÝÈÒK¥Ì!�ØäùL2€ý>aô›ñÛÆV:Gƒ®4æWÔõ ©å)ÉŽ,‚ÌޙƮ}�Eû=h_‚îµ;”(u9ÃĤu�~$·áƒÞ€=zŠ( ¿ú¶úWœxïþB–_õÏÿf¯Gõmô¯8ñÙT²ÉéñêéÂ>{þå/Uù�÷ö^Ÿÿ>¿÷åÂ�ì½?þ|-ïÊÿ…Qÿ„³Bÿ Œ“…ð–h_ô�òoð¬ùjög_·Á4~ô^þËÓÿçÂ×þü¯øQý—§ÿÏ…¯ýù_ðª?ð–h_ô�òoð£þÍ þ‚1þMþrÕìÃÛ࿚?z/eéÿóákÿ~Wü(þËÓÿçÂ×þü¯øUøK4/úÇù7øQÿ f…ÿAÿ&ÿ 9jöaíð_ͽ}”iĉR4TE’@Fù z,?êÿó�6â+¯ˆ�<)B¬;�†½õ�iŠø£~ÈãÉZtê5·<¿BJ(¢¹�dâþ-É+ñý{�ý k�ý›¿äKÕì"ôZWeñkþI_ˆ?ëÜèk\gìàÁ<«3j’Oyi@Į̀ŒîÁUFK€dØø¯Ãš�ÚZXxƒJ»¹|í† ÈävÀɃ“ÅxgቇŽuuðW‚Ä“ÛÌþTÓCÖè÷P{F;žøôëéÿ >Øø JÜÛ.5‹…iºÇOöÑGêy=€îë“Õ¾&ø/D¸k{ïÚ,ÈpÉ銟Bâh/_è¾°Ò4ùžÔÚO>HÎÊ@¹\ö \gØÞ°üðIÔü7e«ø†êí¦¼‰gKxF±£ ®âA$ã¶3Šôý/â—‚5‹…‚ÏÄV†V8U›t9>ƒx5××Ï_¾é…ï5½îí^Í<É-î:ºgœyÏJë?gÿÞk¸²½•¦m:ãÊ…Ü䈊‚«Ÿcœ{`v _öšûþú]í*öoÈ�áÿûÛ襯ý¦¾ÿ†>—_ûJ½›ÁŸò#xþÁ¶ßú)hŽ›€×Äò6˜|?ý¿æI¼[´?ißÏ™�>lõÏãšêkæ_‡ÿòrš�ýjÎJ÷ˆ~-_x2óWZäb+dn�+}ÜûXû)  ºÿŒ¼9á}£ZÕí­†V6mÒêrØ÷ÅWÐ> xSÄ÷gÑõ»k‹ŒdBwFíôWŸÀWƒ|8øcsñ.K¯øŸPºû,³ón\}ã’ :p=@Æ+ªñoÀ[; 1õOÞ_A©Ù�:8^MÞa^~FN¼ñÇZöñˆú·öJk{jY+ö1r†l�’6gwNzt«W·Öšmœ—w÷PZÛG�óO D\œ ±àr@ükåo…ÚÅÞ¿ñÓJÕ/™Zêá¦iYF0·qœ{ã5îŸä‘ë¿îÃÿ£ã ¾×YÒït÷Ô-5+;‹$Î똧W�q×,+—Ÿâ÷€­®M¼ž$·/œf8äuÿ¾•Jþµát}kâ&�„Ríì|=a#]_IÞ•œü«èOÊpóÀ¯V¼ýŸ<6žÐZµýµÎÜ-Ï�¼çÔ©?A�€=/KÕ´ínÉot»Ø/-›�,gÓŽ‡Ú¸_�Þ!ŸÃÿ îE¬†9ïå[5u8*l}UHükÇþÝj~ øÄ|74¹Ži¤³º�IØåCp> `úë_Ië^ÒõØÜ}áô®'Â×ö¶—/u2Ƭ€sÏ5ß…Rtj¨ï¡½+òJÞGiýŸeÿ>vÿ÷è…Ùö_óçoÿ~‡øU_øH´Ÿùý�ò?áGü$ZOüþÇùð®g_³üHå©Ù–¿³ì¿çÎßþýð£û>Ëþ|íÿïÐÿ «ÿ “ÿ?±þGü(ÿ„‹IÿŸØÿ#þ{:ýŸâµ;2×ö}—üùÛÿß¡þ—â;;X´ §ŽÚp ¨0«_ð‘i?óûä³uíkNºÑ.`‚éF µ@<üÀÖ´!YU�ÓÝw*Ÿ2ºaáOù§ýu5Ò×5áOù§ýu5ÒÖX¯ãKÔš¿ (¢°33õ=wHÑGUÕll¹òþÕp‘oÆ3�Äg˜¨õohšž—úž©kkk ÌrI ÄœgåîÜzf¼[ö™ÿUá�÷®¿ö•øk/Ä[ý»³†S×®=EWð†µ¿‹Ââ-ZçûEE·Œ)¤n»A‡`85Ä~Ð~,¾Ñ´ Âg„êfC<ˆpÞZmùsèŹöïY>ø ¢ê>±Õµû«¹g½…'XmÜ"FŒ2 œNÏOOzõmâ„üIp¶úV»k=Ã}ØX˜Ý¾ŠàøWK_3|Oø6ž´µÕü3%õÌFa–äy’DØ$:•ã�À‘ø{_Ã-gR×<§]kLš‚†c2g*H AîF ÷Íur˼ÓH‘Ä€³»°@êI=q—_|gr`—Ä–Ìàã1G$‹ÿ}*‘ú×�|UñF­ãÏ'�ô'ciÀ·1«`M0ûÌä óôÚOÓ´Óg_ ç,z�æ¡sxWçš95ý•ÁÀú“@�¢ø‡Gñ±¸Ñõ+kØ×Œ2)Ÿïª~µGÇ¿òNüKÿ`»ŸýÕ󇋼7«|ñ­Ž¡£_ÊöÓeí¥~ €Fø¤ƒÔ}r§Ð^%ÔâÖ¾jú¤ˆ¯49§@z€ÐÁ÷æ€<Ëögÿ�oÿ¿mü¤¯{¯ý™ÿãÛÄ¿ïÛ)+©øÙãû�hiÚ\¦-SQÜU?41¼ÃМà©ê(®×|áO N`ÕµË[yÇÞ„$‹õU�ÄT:/ÄŸx‚åm´Ý~ÖIÜá"“tLÇГô¯"øð&oH‡[ñUÕÒµâùÑZÂÁ[iä4ŒA99Îâ{ >:øgi£O©xZâèÜ[¡‘¬ç`þbŽNÂ!±Øç>ÔïÔWŒ|ñýçˆ,®|;ªÎÓÝØÆ%·™ÎYáÈR÷*JóèÞÕìôS\f6ÆAæ�M—ýSÿºhŸ’¿óÕ?:<•ÿž©ùÔ4PÞJÿÏTüèòWþz§çPÑ@y+ÿ=Só£É_ùêŸ�CEY† ²©!ö­Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( ¹9¿äwï¯þ€+¬®NoùÇûëÿ  Æ·Ùõ= »zŸá¡ÖQE±ç…Q@Q@§Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW=ã�øô´ÿ®�ü«¡Ó?ägÿ\ÿAåÐÿ«èˆ_-QEê[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯Ugþ@—ÿõîÿú ª‡ÄŒqÁŸ£üŒ?ÿÈ:ëþºÿA]Ur¾ÿ�u×ýuþ‚ºª×üVqåîTý?P¢Š+Ò (¢€ å­?äp“ý÷þFºšå­?äp“ý÷þF»pŸ Oð³z;KÐêh¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€.Úª?ïTõ§ú£þõO@y'íÿ$âÛþÂQèW­×’~Ñ?òN-¿ì%þ�%sÞ øá�ø;JÕîïõt¸»·YdX¦ˆ 'ÐÉÇã] ³¯ƒa™]îõ‰Ôc’â0×l`þµ×|/ÿ’cáßúóJëh†�¢éÞÓ"Ó´«8ím"û±Æ?2OR}Ï5áÿ Žëã�ƒ-åPÑËöTp{ƒrÀ׿ׂüUÿ’÷ào÷ìÿô¨Ð½WÏÿÀ¹ø×ã©ù¸iÆzŒÜ ÿ +è ù×Äowð“ãTž&6²K¢êÌí#F:‡Á‘}7€î1«çûà-?k f¶àË´ÈÞØƒús^�sñ«À–úY½MdNvåmã…üÖ?ÝÁë�ï\Âk GÆ¿5?ˆz…¹†ÕYžz+°(=ÂÇÁ>¸ Ó�Úÿjû§¸?4EÄ`û[`~™5ôxÅ++ï|SÓ>!ÙÛ4ÖR2-ÎÞÎËe>›£è}A®òO�~M#íãW.Û7 Q ùÄÿwÆ}ó�zóÈâŽÚãlXÁvb©²$þ¤Õ¯Úcþ=|5þýÏò޹�^ê:·íc©êVÍmqxÓ\ˆ[ªFöÎc÷ÁZéÿi�øõð×û÷?Ê:÷[h#µµŠÞ% HìÀ®âÅM/À’Cdm¥Ô5Y×zZDÛp¤àldçx®ö¾sñ­Ü^ý£­uýrm-ü¹c}›€_'ËÜr®7`súPMŒþ0둆Òüicô{Ì«(õùÝôäþÛë6¿´Dñx†xçÕ¼©ZæHÏÊY¢Àè;W¬j| a`×C]†äíÊÃn¬ò1ôÆ8üq^1áOÆ¿dñˆ“û";Ävà£D<¼“ê»yéÍu´Çüxøsþº\(ëÝ¢UHQª ; ðoÚNT›Lð̱8xÝçe`r+ {Ú}ÅúP‚J¡¿kˆƒFÜóÿ^F½ò¼Où;˜¿ÜÿÛ#^÷@ û5}ßÿ¿mÿµkÞëÁf¯»âŸ÷í¿ö­{ÕQErž1ÿ�R×qü𙤸WN½Ò­îe3y’.[k€?•?Æò Oúî?“VLJ¿ä_²ÿ®Ö¹ùTª»ö=EVt°Qpv÷™Cþ½+û×÷Øÿ ?á Ò¿½qÿ}�𮊊ÓÙC±ËõÜGó³�ÿ„/JþõÇýö?Â�øBô¯ï\ßcü+¢¢�eÁõÜGó³�ÿ„/JþõÇýö?¹ÍwJ¶Òµ›X-÷”uV;ÎyÜGô¯E®Åÿò0Ù×4ÿÐÍeZœc¤våøšÕ+rÎM«3±·þ/§¨-ÿ‹ð©ë¤ò°¼kvö>×î¢$I�;!›Ëlηk7Ä:iÖ<5ªi€á¯-%€BÈWúІ~Íq½çˆ¯ˆlqÁ Ÿ@ÅËè ùWеóOìõ­G¤x¿TЯ“-ô`"¿͈·ÉõÃ7ýó_KPN­á}^š9µmÊúX×j=Ä*åG\GJä¾5¢Çð{YDP¨¿g @ñÖ'Å_‹Ú‡‚|Ck¤hÖÖ7S4mÇÚ˜¡cò¨ÚÞ}Ejüa{‰> jOvŠ—-©™PpÎ�pÙÍfþοòN.ì%/þ‹Ž¸Ž?òX´¿úö¶ÿѯ]ÿìëÿ$âçþÂRÿè¸ëÏ~;ʶÿ´é¤ÈD´·r}„�šúv¸�ŒòJ5ÿúâŸú1k¶VWPÊC)‚+Ìþ;ëVúgÃK«'p.5#‚Ï$Ç€.?@?³üˆz—ý„ßÿEGX_¾ëÒø¤ø¿ÃpÍrÏå¼ÑÛÿ®†DP9# ½9·fÿùõ/û ¿þŠŽ¶aøÉ¦?Äá´Ë˜'�f.EØXã®��­yÆ‘ûBø‡I"ÏÄz,WrEò»ŒÛËõa‚3ô½3Âßü#âkˆ­ytëÙNÔŠñB«7 pJþxÍvºž…¤ëQyz¦™gz˜À«ãé‘Å|éñËáö�á$Óµ-?²}®GŽKMå—€åÏ#ÐŽœŽ”ôÝ|ËàOù9�CþÂ�þÔ¯oøiu©ü7Ðnï]žáíB³·%¶’ ŸR@¼CÀŸòs‡ý„5ý©@MWŸx¯ã/„ü)y%Œ“Í}Û$6jcz3>£$�Jßñî§q£x \Ô-­Ä6ŽcqÕXŒü3ŸÂ¼/à'ƒ4_Ü꺦³móÙ¼k|È n%™z7L ñÖ€7gý£g»�âøJYä?tÉpXÿß ¿Ö¼¿ÄZ¯ˆu¿ˆÖ�‰lžÊöy`)nÑöE» …nq×­}‡mime†ÖÞ("$ £ðóŽF×PøÛj-fY~ÌÖÖò•9Ãä�¨Î¾hê7û�ô¯™fÿùu?û·þ�޾š¸ßJù—öoÿ‘çSÿ°kèØèÚJåßÅš=©'ËŽÄÈ»;ÿ  úC³�OÐ4ë(@[ÛG�èªô¯ ý¥4™Þ‡¬ª“Fö®Ý•�Ü£ñËþUìüA‰¼¥j0ÈÌ àRU0?ˆÏЃ@-|·nƒEý§6[|ŠÚ³ /a(9øù¯¨..!´¶–ââEŠ�¼ŽçT ’O¦+åß»øÛö€:Ä(ßfS_ŽR5ÈLþ%ã@SQEV/ˆÆtkÿúàßʶ«Ä_ò¿ÿ® ü«*ÿ—£ü„ö9/ xnÇZÓæžèÌ%Ø60ÓÞ·¿áÑÿ½sÿøTäuÿ_û(®¾¼Ì <4%(&Ú&1V9ø@´ï\ÿßÁþ£ÿzçþþ𮢊ìþÏÂÿÏ´>Trÿð�hÿÞ¹ÿ¿ƒü(ÿ„ GþõÏýüá]EgáçÚTyÏŠü7c¢ØC=©˜»Ë°ï`F0O§µu¾ãF°ÿ® ü«'âü‚-ë¿þÊk[ÿò°ÿ® ü«“ J±Õ#ed$­&lÑEë–ò¿ÆKó¥|l]Ec_²ÎœnÚc?…}Q_0|T·†óãõ�µÄbH&–Ê9ôe%A‘ ;Åpx·Ä6CÇ:Ü5�äþLR‘…P9 «Ù:€{�zšúƒá—Ь¼[à›+«Xâ‚[t÷Ñ«¨ŠFö8í[š×‡ôýw×:Ô ,§‡ÊŠ–Ý*:¤>‚¾fð^µ}ðƒâ}Γ«±[$÷ŸÝ)Ö9‡°Î~„Ž´õmy÷Šþ2øO—’XÉ<×÷ѲCf¡¶7£1 ê2Hô­ïê³i>Öõ+'ÄÑY»C"œí$`0úg5áŸ<¢ø–çUÕ5›hïžÍãX ›æ@[q,ËѺ`gŽ´»?í=܆ÂRÏ!û¦K‚ÇþøUþµåþ"Õ|C­üF°Ô|KdöW³ËKvˆÇ²-Ø\+s޽kì;kKk(D6¶ñAè‘ U€¯˜~-ê6º‡ÆÛQk2Ëöf¶·”©È$}Fp}ó@Q¿Üo¥|Ëû7ÿÈó©ÿØ5¿ôluôÓýÆúWÌ¿³ü�:Ÿýƒ[ÿFÇ@Ïíÿ"›ÿa4ÿÑRWUðþIF�ÿ\ŸÿF=r¿´üˆZoý„ÓÿEI]WÁÿù%ýrýôâß1«üb»Ôn>i„7@Ÿï³'òs_P×Ë™| ñâm:üù14óX—~æ3ô$'ç_SÐ�~Ò‘¿‚t»²›¢#SþËFäþ¨µÒ|ÿ’E¢}n?ô|•Ä~ÒZìOÑôpÓ´ÆòU”P¥?]Ïÿ|×oðGþI‰õ¸ÿÑòP�øòÝ.ÿih-壗PÓÑÁî Ä }C_1øÏþN‚ÏþÂzwþƒ }9@cñóþImÏý|Ãÿ¡Rüÿ’Yiÿ_3èTŸÿä–Üÿ×Ì?ú/À_ù%–Ÿõó7þ…@‰¨Ziv3__ÜÅmk î’Y[j¨úׂø¿ã¶£¬^À–s”ì[³y¤?ôÎ>ßS“ì++↿ª|Cø•‚ô™³·¹û:¦p¯0ÿY#z…Ã`§Ö½·Á´Oé럒ñ” ïd_ÞJ{ÿº¿ì�Ôó@Sà¯�—ú•ø×¢€;wÄW†tÇÔu‹Øí-Tãsõcè rÇØW”ê_´†�²éÚ5ýØVXU¾Ÿxþ•Æ|¿¸Ô~#XèòLc´··Œ ?t4Œw?å�ÿ¯zðç�¼9á[H Ó4«t‘Íài\ú—<þ=  ñ_ÅoøÏÃöv{--â&êáQå+äüäý+§ýš¿ä®ÿ×Ôú®óâÆ£k§|2× ÔËŸnÖñywn§©ú\ìÕÿ wþ¾£ÿÐ g~Ó_ÃK¯ý¥^ÍàÏù¼?ÿ`Ûoýµã?´×ßðÇÒëÿiW³x3þDoÿØ6ÛÿE-xÃÿù9MGþ¿µç%t¿´µÛ¦•áë0w,óJÃÝ@ÿÐÍs_ÿäå5úþÔ?œ•Ù~ÑÚD·^Ó5HÔ²ØÝ“²2àJ£ñ óá�¤v ¼;@k$”ãÕÆóú±®²¸ƒ:ì×Ã=1ÁžÅM¤ÉžT©ù5Úk¸½¼·Óìg½»•b·‚6’Y¢¨&€>_ð%¤v´™´ˆ�ühe 0¥{WÆŸù$zïû°ÿèøëÂ~j'Wø÷e©°*o.®î=·Å+Z÷o�?òHõß÷aÿÑñÐ1û7Û¢øS¸y’jLŒ}BÇúüëÙ+È?g/ù'wßö“ÿEE^¿@2¯ü�/ýÄ�þ‹¯¦«æUÿ“¥ÿ¸‘ÿÑuß|x×çjéZ?ÿä“j¿õÒýµŸû=ÿÉ4oúÿ—ù%zF·ÿ Gþ½eÿÐMxìÕÿ!Ý{þ½£ÿÐ�{þ·ÿ Gþ½eÿÐMxìÕÿ!Ý{þ½£ÿÐ�tÿ´�ü‰zWý„Gþ‹zì¾ÿÉ+ðÿý{Ÿý «�ý¤GüQZQíý¢?ô[×]ð~xî>è- £{#(¸¯™~ÉWÕëÊý}­êÖÚ‰{ªÞ8K{HZW$ã8îN÷5ówìñ#Kñ*úFûϧJÇêdŽ€=Oã7ÃÛÏè–—VÖÔ´ör�³ó‘±¹A<•g޵äúÅoü9·‡CÖt–šÖ²(o£h¥E¯Ý}2lq^Åãÿ‹^Ö-´û½*êèÏn'Y"uï2ãžü~µÚ§Ø5ý" ¤‚«;¨–UYP:²°ÈàñÐЗè?´7†5'Xµ[[½*Fþ6tCþ¿7þ;^­õµÝ‚_ZÏöΞbKW\g ޵ä>xRjZå…Œ:eíœ~jµ¿Éœ�´§Ýç8çJƒöp¾º¸ð¶­c33Û[\©„7!w©Ü·ãÜúÐð?íOŠ—÷8y£²šà1þû:)?“·ç_PWÊÿ îWÀŸ§Òuò’F›Mg~K‡ñ(¿÷Õ}Q@Ú¶�¤kÑů¦Zß$D´kqp¤õÆzVGŒ¬í´ÿ† ´³‚8-áÒnR8£]ª€DÜØW9ñoâmÏ€!ÓaÓ!´¸¾»ffK€Ä$kÆp¬$ñô5~ûT¿Öþê:¦¥ PÝÝèsÌñÄU À$ž„w ögÿ�oÿ¿mü¤®KãÝé—⚤Êd†ÖÖòóŒ®K‘Ÿ}Çšëføöñ/ûößÊJÃøÿc>“ñK×Q Šx•»y‘7#ò)ùкþÒÛ*ø; �ߪwü4ÃОðeÿÚ«Ü4}ZÏ]ÑíuK D¶·Q‰#`{ÇЃÁˆ©oïí´½>âþòUŠÚÞ6’Wc¨4òßÁKÝßá’�¼Wir@ä*•.=ñ´~UõmyßÃïŠðü@Õt[‹Xí¡ó^y% >ðpSÉü z%ÙÕ?û¦�M—ýSÿºh6Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š(¢Š(¢Š+“›þGqþúÿèºÊäæÿ‘ܾ¿ú¬k}ŸSÐË·©þúeQ[xQEQEÊxãþ=-?ë£*ètÏùÙÿ×ÿÐEsÞ8ÿ�KOúèßʺ3þA6õÁ?ô^]÷ú¾ˆ…ñ2ÕQ^¡e³ÿ?‡õª•lÿÇ�áýj¥GYÿ�%ÿý{¿þ‚jõQÖä ÿ^ïÿ š¨|HÇüú?ÈÃð/üƒ®¿ë¯ôÕW+à_ù]×_è+ª­q?ÅgQþåOÓõ (¢°= ¢Š(®ZÓþG ?ßäk©®ZÓþG ?ßäk· ðÔÿ 7£´½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(í§ú£þõOPZª?ïTôUMGJÓµ‹am©ØZÞÀ8Šæ‘C‡ Ï'Ÿz·ECkkock­¥¼Vöñ.Øâ‰"@TÔQ@P»Ðô‹ûø/ï4«‹Û|n&·G’<�¬FF#êýU]CM±Õ¬žÏQ´‚îÚO½ÈOàjÕÃÇðÀ1\‹…ðäóœ4²2ÿß%¶þ•ÙÛÛAio½´1Ãkµ#�Bª�@T´P˜øïâ4^ñ}—‡uÝ ´F5ó.æmË´’)´ƒ´à‘èE[·ðWÂÝ-†»žŽ‘¯ïDò]oˆwÈ Å?!]_ˆü-£x³Mûµb—Pƒ¹ $4mê¬9¼ý?g�¥ÇšÓjÎ™Ï”× ·éÂúÐ5ðùÇ�~=ë~-µF:uª°ŽR¤%Iô%C7á^Ý©èzF´"®•c~"ÉŒ][¤»3Œãp8ÎåLÐô +ÃZbiÚ=”v–ªs±:±õ$òO¹­*+3[ðö‘âK1i¬éÐ^ÀUe\•>ªzƒî+NŠä4¯…¾ ÑoîÇÃÖË:«ÊÏ6Óê’«^ ð…¼S}îµ£Ãus…ïtb@v‘‘õÍt´Pmï‡t]JÞÞßPÒ,o!¶]°¥ÕºÊ#åÜ8ò­*(  ØzAÕÆ®t«í1Òóìéç}Ý¿¾ïzqW袀(iš‘¢ù¿ÙZU�‡�ƒ'ÙmÒ-øÎ3´ ã'¯­_¢Š(¢ŠÂ×4ÖÕ,Œ F8î?­` j*[ØÀƒ5v ÷�Ö’³•(ÉÝ�tqµ¨Ã’OC�ÿ„[RÿŸäÿ¾š�øEµ/ùþOû髯¢§êð5þÓÄw_r<÷K±»Õ&’8®JÆIf5§ÿ¶¥ÿ?Éÿ}5Ká[Yྻ2ÂèÛ–ç5ÕVT¨ÆQ¼Ž¼n>¥:Î4Ú¶�CþmKþ“þújt^»ûLRMw*°'©8ÞºÚ+_«Àäyž"Û¯¸šßø¿ ž ·þ/§­�<(¢Šðÿ‰ÿ¯õiüMá |ïæÍj$òØÈ9ó#nby ‘Ï9í\Úø«ã�´OþÍÔÞEùDçLß÷ÞݧêkéJ(À~|ÖîüJž(ñ»1%­´² $šAÈiÈpqß8}7➇¨ø�áΩ¥i6ÿh½œÃåŽSvÙQ�,@z×cEyßÁ� kðTú~·gö[¦¾yD~j>P¢r¤Ž Ö_Æ_…÷~5ŽÛVѶRÒ3BìOIÀ`IëÁÉæ½bŠù—FñÆ_ X¦‘…¨ÜÁì‹ÏÓžo-G@z�Û$Ö‡ü+/xÞ×RñŒG¿[G]:Àº£ùr Šn =}þŠ¢€<×àŸ…u¯øJúÇ\²û%Ì·Í2'š’e h3”$uS\ÏÅ¿„–¹­7‰|3µï$ n-w„fe„àgddtÏz÷ (æ›oüoÒàM¥ê—Õ’]0ÊÃþŸ©Í? ~ |E×bÔÕâçÀÿ>x‚{¯ C=í³ü¢[XÄ¢dÎ@x¹ þsƒ_PQ@>Gª|nñŠ}�,ŸG‚O–[‡·û.®æËÿß5Ïø×à¶»á…Ó/t»Õßfn¤�7:N�ʃ�¸Æ:ò§=E}GEq õ�ë~žé¿a½Y¶D¦ˆºm1RzäŸO¥yÿÁ?‡¾)ð�Šï¯uÝ/ì–òØ´HÿhŠL¾ô8Â1=¯t¢€1|Uá‹øzçFÔTù3 ¬‹÷¢qї܈ï_=ÇàÏŠ_ 59Ûë=ݤ‡—³A2J;nˆäƒï�¡¯§¨ ˜µøÉñ !¦^é÷ÖönG™� HÏ=X¶ øç§Jö/†_ í¾é2•nu[¬›…(¢&yÚ?SÏ ÝQEVv©möÛ[‹mÛ|ØÊnÆq‘Z5Zoõ¦”¢¤œ_P8ðV¥!/¡QìXJwü!º¯ýcÿ¾Ûü+¸¢¼ÏìŒ/g÷²9ÃÿªÿÐF?ûí¿Â²?³¯¿·²~Ö|ÝÛwïm¿w5éõÆýŽçþ›äIånß¿oË�˜Î~¼W3-¥OÙû4õ’OW°¥­bøCu_úÇÿ}·øQÿn«ÿAÿï¶ÿ î(®ßìŒ7g÷±ò#…jRúå�ô®ÛK¶û­½¶íÞTa7cÀ©*HÖŠèÃ`háÛ•5«óŠ[h¢Šë(+Âüqð÷Å:ÇÆk-~ÃKó´¸ç´wŸí.Ýò– Æj÷J(¯)øÏðÖãÆVÚž‹n²k6¤FcÞ©çÄOL±*NFOBÞÕêÔP�ü<ÑüE/Ãû� øÛLxU"kXä3Ç'›)Ê1Á^™=¶úò3à‰ ¼A=׆¡žöÙþQ-¬bQ2g <\�9Á¯¨( Ÿ#Õ>7xÅ>À–O£Á'Ë-ÃÛý—×seÿï�šçükð[]ðÂé—º ]êï³7R@›�' NåAÎÜcySž¢¾£¢€8¿†úÇŠõ¿Ï?‹tß°Þ¬Û"SD]6�˜©=rO§Ò¼ÿàŸÃßøGÅw׺î—öKylZ$´E&_zaž€×ºQ@kñ³Âº×‹¼%ec¡Ù}®æ+õ™ÓÍHð‚7Ë�:°üë øo£ßè´�/SƒÈ½·�–X÷«m%ØŽT�x#¡®ªŠò�‹ ›Æeu�dzltsµnTtìà'Œpq�\ Ž¿ñÃK…t„ÓµY–“Mb%+ÛýiOÔ“W<{®ø¿á×Å8õYu Jï@ž>w¹s ©2x¯Lм7e?Øàcå™ €Ò¾3µ@ϹÅ}%¡é0èZ †“nsœ œ}í£üzþ4ã^&øyâ�CãÅ·‰mt¿3HKë)šãí $b=çimÜm=»q^ëEÂü]ðö©â�Ϧhö¿i¼iâq˜©�O,@ýi~ø{TðÇ€môÍb×ì׉4®ÑùŠø²9RGë]ÍòxøWñJj]ZÏJ¸µ¼yA<Œ1¸-œá„™ÉüëCþÏŽ_óõ®àõøõ}AE|¿ÿgÇ/ùú×?ðz¿üz½ká“ã-'KÔ“ÆR^=Ã̦µ^‹“·o8!›ö¯F¢€ (¢€ÿêÛé\�‰|96·4Á:FÑ©Rý«®õmôª•p›ƒæ‰†#OMÓ¨´g ÿ^­ÿA(ÿï·ÿ ?á Õ¿è%ýöÿá]Ý·Öªö³ûÙç—þÔôû®ä¿FH—q í“Uô}QÖlÚæàŠ¦Û9ßZî|A“è±Ä…ÜǨÉ5�à¨%·Ð˜MFZf``‘€3úÕb%윺Üóç•QXØÒIò¸·»ÞýÌøBõoú Gÿ}¿øQÿ^­ÿA(ÿï·ÿ î謾µPô?°ð�ŸÞÎOCð�Λ«%íÅÔrl €¹$’1Î~µÚÃþ¯ñªÕfõ�cR¤ª;ÈîÂá)aaÉIi¹%QPtœÇÄM&û]ð±¦i°y÷—…Š=껎àz±tîk™ø%á=oÂ>Ô,õÛ/²\KzeDóRL®ÅÊ:ƒ^›EAyio¨YOgwËoÝøÌ[ë:.ê[Åå<Á|øòHÁ<ž¼zð+ˆÒüSñ«D¶�JõЉDi%ÆžÒ§ïú’ké*(À£ø[ã�‰µ/j­¤.,¬Ã/Ë!)!~U\ã8ËsŠÃøqkñ'ÀÞ#þˇ÷?a»º‰okVxÕC`ºÈtžrGµ}3Ex÷Ç?x‹Æ- �NûgÙEÇ�ûèãÛ»ËÛ÷Øg;OOJôÏ ÙϧøSG²º�˸·±†)S íu@ÈàòJÕ¢€Â?öÖ³$Së …bHÎRܸ=ØŽ3Ðrsšõš( Š( .>ðúW|)x’1Šî0¤ðyõÙ\}áô¨kj8‰Ñ¿'RáRPØäÿáÔçõ?念þ�GþSþújë(­þ¿[Ëî4úÄÎþÊïO¼ŠÚK’Í c�“ŠÒÿ„cQÿŸÔÿ¾š¤ñ ¬ókvmNÊUW dd1®¢º+c*Fœ%®÷4�i(Å£“ÿ„cQÿŸÔÿ¾š‘¼-¨0Ã^FAìY«­¢¹ÿ´+y}ÆX™OF°:uœvìáØ6âGNMlÕDûëõ«uÉ99ÉÉîÌ[mÝ…QR#È~9ø+Ä>1�BŸö³jgó¿}{wy{~û ýÓÓÒ½–WoƒôK ¸ü»›k!™7µÖ5 28<ƒÒµè /ⶃ©x—áåþ—¤[}¦öWˆ¤[Õ2E'– t½Rø9á­_¾m;Z´û-Ù»’O/ÌGùH\©#±¯A¢€*j�És¤^Áî’HsŒ’¤^Að?À~%ð~­«O®é¿dŽâH�Ÿ›ˆbOÜc�ƽªŠå~!ø6?øJ} ʰÜ[JÃ!$\ã>ÄÖ¼E³øµðÒyìôÝ"ökg}ÍVÆê=7 ¹Á CëÒ¾¦¢€>x‡Ãß~*ÞÁмí'B�ÃËEänÇ÷PüÌÞ…¸¡ØøYðç_ð—ÄÍVþïK6Ú;A<6²ˆß*eBƒ‹}Õî>µíôPžüWøqÿ ö�ZK:­‘cnÒ}×S�ÈÄtè=�Ö¼‡J—ã/€àþÌ´Ó5m#$$BÔ]ƿ�ì=«ê (æ;ÍâÿÄ·ŽÏW‚æÚÄ0%nPZľåp±ô5îÞðe§�|1“m!šBÆ[‰ÈÁ–CŒœvè+¦¢€<“âÏÂñ„ÿÛzG°¨X¤;VäœöqÓ'‚1ÓÁÛxƒã~ƒl4ÏìíNàF6$�`. �úè õ$×ÒôPÎøKâßx•ußI4VûƒH“0ó¦¢^,vë݇é_NÑ@‡Ã¿YøÃæÊ<ûÉØIwsŒy�Ž”s�îOzë袀 l¿êŸýÓN¦Ëþ©ÿÝ4›EPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+:_õ¯þñ­Ηýkÿ¼h”QEQEQEQEQEÉÍÿ#¸ÿ}ô]ersÈî?ß_ýV5¾Ï©èeÛÔÿ ý²Š(­�<(¢Š(¢Šå$cˆþ ýäaøþA×_õ×ú ê«•ð/üƒ®¿ë¯ôÕV¸Ÿâ³�(ÿr§éú…QX�QEW-iÿ#„Ÿï¿ò5Ô×-iÿ#„Ÿï¿ò5Û„øj…›ÑÚ^‡SEW€QEQEQEQEQEQEQEQEQEvÓýQÿz§¨-?Õ÷ªz(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šg’„ôýi<”ôýjJ(?%=?Z<”ôýjJ(?%=?Z<”ôýjJ(?%=?Z<”ôýjJ(ªŠ™ÇzuPEPEPEPEPEPEPEPEPEPEPEPEPEPEPLhÕŽHæŸEGä§§ëG’žŸ­IEGä§§ëG’žŸ­IEGä§§ëG’žŸ­IEGä§§ëJ±ªœ�Í>Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š­§Yj¶og¨ZAum'ÞŠxéü qr|ø}$æVðò'8[™• ø®öŠËÑ|9£xrÜÁ£é–ÖQ·Þòc·ûÇ©ükRŠ(¢Š(¢Š(¢Š(¢Š(¢Š(È ÷¦y)éúÔ”P~Jz~´y)éúÔ”P~Jz~´y)éúÔ”P~Jz~´y)éúÔ”P~Jz~´õP£¥-QEQEQEQEQEQEQEÌëß<%âkƒq«hvÓÜ7Þ™wDíõd ŸÆ©iŸ ü ¤N³ÚøvØÈ§ ÎÏ6®‘]�€t–Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬Šýi¾Jz~µ%’žŸ­Jz~µ%’žŸ­Jz~µ%’žŸ­Jz~µ%Á=éôQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@6_õOþé§SeÿTÿîšÍ¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ (¢€ (¢€ äæÿ‘ܾ¿ú®²¹9¿äwï¯þ€+ßgÔô2íê…þ‡YEVÇžQEQErž8ÿ�KOúèßʺ3þA6õÁ?ô\÷Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW—Cýþ¯¢!|LµEW¨YlÿÇ�áýj¥[?ñãøZ©@QÖä ÿ^ïÿ š½TuŸù_ÿ×»ÿè&ª1Ä~�ò0ü ÿ ë¯úëýuUÊøþA×_õ×ú ê«\OñYÇ”¹SôýBŠ(¬H(¢Š+–´ÿ‘ÂO÷ßùêk–´ÿ‘ÂO÷ßùíÂ|5?ÂÍèí/C©¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š»iþ¨ÿ½SÕçh—j�ŒçšÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þU1•…·™�ššŠ§ö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(¨ZVâL ñPý®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åGÚäô_Ê€.QTþ×'¢þT}®OEü¨åOírz/åS<¬¶â@N(j*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢¡yY`Wdâ¡û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_Ê�µÉè¿•\¢©ý®OEü¨û\ž‹ùPÊ*ŸÚäô_ʦ’VHUÀ8  ¨ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTrЧö¹=ò£írz/å@(ªk“Ñ*>×'¢þTr›/ú§ÿtÕ_µÉè¿•#];)Rb€ ¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ (¢€ (¢€ äæÿ‘ܾ¿ú®²¹9¿äwï¯þ€+ßgÔô2íê…þ‡YEVÇžQEQErž8ÿ�KOúèßʺ3þA6õÁ?ô\÷Ž?ãÒÓþº7ò®‡Lÿ�MŸýpOýW—Cýþ¯¢!|LµEW¨YlÿÇ�áýj¥[?ñãøZ©@QÖä ÿ^ïÿ š½TuŸù_ÿ×»ÿè&ª1Ä~�ò0ü ÿ ë¯úëýuUÊøþA×_õ×ú ê«\OñYÇ”¹SôýBŠ(¬H(¢Š+–´ÿ‘ÂO÷ßùêk–´ÿ‘ÂO÷ßùíÂ|5?ÂÍèí/C©¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÛLjúçU*ÛLjúç@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š¶ÿñä>‚ªU·ÿ�!ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·'üy¯ÐUJ·'üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÖ�gKþµÿÞ4Ê(¢€ (¢€ (¢€ (¢€ (¢€ äæÿ‘ܾ¿ú®²¹9¿äwï¯þ€+ßgÔô2íê…þ‡YEVÇžQEQErž8ÿ�KOúèßʺ3þA6õÁ?ôTõÝë0ßÉòØœìÝœþ"´maû5¤0nÝ審»Î+‚•ÇR£Z4¬J^ód´QEw”[?ñãøZ©VÏüxþÖªPTuŸù_ÿ×»ÿè&¯T¶ÿk±žÛvÏ66MØÎ21š¨»I3:Ñr§(­Úg9à_ù]×_è+ª¬�F:-´±üíï»;6ãŒzšÖ«­%*�£—-£:8XS¨¬ÐQE‘ÜQEËZÈá'ûïü�u5ËZÈá'ûïü�vá>Ÿáfôv—¡ÔÑEÄ`QEQEQEQEQEQEQEQEQEQEQEQEm¿ãÄ}óª•m¿ãÄ}ó  ”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[øòAU*ÛÿÇ�ú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[“þ<×è*¥[“þ<×è(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@åÿ�Dú ©Våÿ�Dú ©@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[›þ=Sðª•noøõO€*QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Ηýkÿ¼kF³¥ÿZÿïeQ@Q@Q@Q@Q@rsÈî?ß_ýWY\œßò;�÷×ÿ@�o³êzvõ?ÂÿC¬¢Š+cÏ (¢€ (¢€ (¢€ (¢€-Ÿøñü?­T«gþ<ëU(¢Š(¢Š(¢Š(¢Š(®ZÓþG ?ßäk©®ZÓþG ?ßäk· ðÔÿ 7£´½¦Š(®#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«mÿ#è?�T«mÿ#è?�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÛÿÇ�ú ©Vßþ<‡ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜŸñæ¿AU*ÜŸñæ¿A@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·/üz'ÐUJ·/üz'ÐUJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÜßñꟅT«sǪ~RŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEAzÌ–7Ÿybb>¸ 2‚+¯‰¾"Ô|ëû‹mÅü¸â�±æœœLñœ�q�).íî¾kº|¶×÷ãùsC;gË•fï÷š'>»ErßÙ—Àw@tib ôÜôÏh^ ŸÆÚp×¼Eª^™.Yš¡`«ƒ�Á8}jÿ„õ GÃþ1¸ð~§v÷p”ó,¦�üØÆìsÛú8®»Âª©á/O°ÂñÁ\gŠ?wñ‹Ãn‡çhUN=7H?©  ¼a©j:ß‹m<¥Ý½¢2ù—“Æ~`1œqÛoæXV~¹à™¼¦¶»áÝVøOjCÍÎH¹ç€Ôƒž*ׇ¿yñ«_g?2Û¹úÄ?•vÞ$U jêÿtÙLýðhÞÕÓ]Ðlõ4P¾|yeÂÆ�´«‰øRÌÞ„‹<�~™Ïõ5£ã«�~׿O #¾¡ç(ÂF®vsž#Ò€:ZΗýkÿ¼kÇ¿¶þ0Ï­ßþEÿÄׯ陓J³{þ/3ƒÁ¸9Í%oe·¨üèÙmê?:©E[Ùmê?:6[z�΀*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©\œßò;�÷×ÿ@Ûì¶õ�bI £ø„jBé{�òðsÂã­eV.V·s·VÜùݯ¾f…oe·¨üèÙmê?:Ôâ*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©E[Ùmê?:6[z�΀ÿ?‡õª•¡ˆüœË?­E²ÛÔ~tRŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@(«{-½GçFËoQùÐJ*ÞËoQùѲÛÔ~tR¹kOù$ÿ}ÿ‘®Óe·¨üë "×›P7Hc,ÇËÁÏ#k« R0ŒÔžé£ZrIJý‹ÔU½–Þ£ó£e·¨üë”È©E[Ùmê?:6[z�΀*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©E[Ùmê?:6[z�΀*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©E[Ùmê?:6[z�΀*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©VÛþŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@(«{-½GçFËoQùÐJ*ÞËoQùѲÛÔ~tRŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@(«{-½GçFËoQùÐJ*ÞËoQùѲÛÔ~tRŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@(«{-½GçFËoQùÐJ*ÞËoQùѲÛÔ~tRŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@(«{-½GçFËoQùÐJ*ÞËoQùѲÛÔ~tRŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@(«{-½GçFËoQùÐ/üz'ÐUJÐaˆûœcš‹e·¨üè¥oe·¨üèÙmê?:©E[Ùmê?:6[z�΀*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©E[Ùmê?:6[z�΀*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©E[Ùmê?:6[z�΀*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©E[Ùmê?:6[z�΀*QVö[z�Î�–Þ£ó  ”U½–Þ£ó£e·¨üè¥oe·¨üèÙmê?:©E[Ùmê?:6[z�΀*U¹¿ãÕ? 6[z�Î¥qˆû�¹  ú*ÞËoQùѲÛÔ~tRŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@(«{-½GçFËoQùÐJ*ÞËoQùѲÛÔ~tRŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@(«{-½GçFËoQùÐJ*ÞËoQùѲÛÔ~tRŠ·²ÛÔ~tl¶õ�T¢­ì¶õ�-½Gç@Û¯_ÇùUú‚5€8(FîÜÔôQEQEQEQEQER0 ¥HÈ#RÑ@]àKè<#­êþÕ§Kaçy¶ÒLv«Ž�O€¤~4¾?Ô`ñf¥¤øcH�.™î<ÙÞcc9p øWy«øwHוF§aÁNŽCè`ãñ£Hðæ� †þ̰ŠÜ¸Ã8Ë1›ŽN(MKUÓ¼?`“ßÜ-µ°a±RyÇ€{ ÍñEŠø£ÁQY7›ö˜kr7ã¸Ï®ükKXÑ4ízÈZjvþ|Ä�7²üÀTƒÜÕ«[Xl¬à´·M�AÇä�ª£dóÐPài²xVÚÎúú [ËòdŽwœ/Œõã�fi’¯‹þ,6­k™4Ý.-&ÇÊí‚?àLÄ{ ëõ/øsW»7WºTRNÇ,êÌ…�©ÚFÔ°Ó¬ô«Eµ°¶ŽÞä$k�ŸSê}èÏ5™„¾+A­\å4ÝJ/*IqÂ6ÐCô&µ¼uâí. ÝÛYßÛÜÝÞÆ`Š8$‚N: ø×]§Ùê–�k}mÄ Õ$\�¯±÷¬�;Á^ÒnÖêÏJ…'S•vfr§Ôn'… Ò$Ðü#ae:íœ!’Pz†b[éœ~¿EVt¿ë_ýãZ5�/ú×ÿxÐ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š¶ãÇðþµR­Ÿøñü?­T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­·üx� þuR­·üx� þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  oÿCè*¥[øòAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÇšýT«rÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ü¿ñèŸAU*Ü¿ñèŸAU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«sǪ~R­Íÿ©øPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPYÒÿ­÷�hÖt¿ë_ýã@ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ùÿ�ÃúÕJ¶ãÇðþµR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶ßñâ>ƒùÕJ¶ßñâ>ƒùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-¿üy ª•mÿãÈ}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­ÉÿkôR­ÉÿkôRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  rÿÇ¢}T«rÿÇ¢}T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­Íÿ©øUJ·7üz§á@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@gKþµÿÞ5£YÒÿ­÷�2Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  gþ<ëU*Ùÿ�ÃúÕJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÛLjúçU*ÛLjúç@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š¶ÿñä>‚ªU·ÿ�!ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·'üy¯ÐUJ·'üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Ëÿ‰ôR­Ëÿ‰ôR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·7üz§áU*ÜßñꟅT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQE‚"I+É÷5%Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P•Ãã iþ1Ÿ 5Ê+Ídò|¥ÎE‡ÍŒõ÷¯Oû4_ÜýMy¬> Ö“ãñ!†/ìß5Ÿš7`ÄWîõë^Ÿ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêkÌ,€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔטh>0ÖµŠ÷¾¹¹GÓ!–tH„J �¿0íë^©^a ø'ZÓþ+ßx‚↟4³²0”Ãç~4é_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@WáŸkZ§Å-K@»¹GÓmå¹Hâ( #�¿0àW§ýš/î~¦¼×Ã> Ö´ÏŠZ–½s Ka<·/ AbÉ^>•éôÙ¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦¼ÃÂ0ÖµŸ‰:ž‡}r’iöíp#ŒDªFÇÚ¼�“Åz¥y‡„|­hÿu=nò–Êá® l²‚N÷ܼ}(Ò¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€#XcF «‚=êJ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š)®é3Èꈣ%˜à@ªöz…–£Icwos¶Öh$ô$¼Ôvº¾™)ŠÏQ´¸�uHgW#ð¸ƒßò-êõüßúP¢QU/5];O ^ßÚÛÐM2¦3RÛ]Û^ÅæÚÜEvqåý¡7géœÕú(ª·š•ŽžÞÞÛ[èf•S?™©mî­ï![Oñ�†ñ-ÀxßÅm¦ëÚ­†­Jn¶_¢È‡jîO¿Ÿ»ÁoNõ§ã/ǤøBMKJ¹‚wšADâD s“‘ÁÀñ ²ŠóK…ëªiñÞ뺾¡&¥2‰ Y#'œ|À“�¤ðv£ªhž0»ð†©vב¢y–³9$ããžÅONÄq@�EPEPEPEPEPEPEPEPEPEPEPER:Æ–·d:•˜¹Î<“:ïÏ¦Üæ¥ŽúÎk¹m"»�îbÉ È  ÷^£¨  W—Þ�GÇÞ6¿ÑÒþk=M;%œú’AÆxtÍCâOà�=µßj·ˆmŠ™¡™ÃR@ÏÉäü¨Óîïm4ø<ûÛ¨m¡Î<ɤ¹ôÉ©‘ÖDWF ¬2‚=k“½m#Ƴ¹ÖnE�¥ÀI¼åŒ+ŒŒnn:æºsc¥é±<×pÃhˆ¨³M*ª‘Œ˜ñÍ\¢¨ÝkzU‹¢]êvví Ü‚YÕKQ“Ò¬Çs¶ÿhŽxÞ óÁ\ùé@Ñ^yiã8ÛâUý´Úå¯ö"Û 3F"ß„èýÎKqŸZîŸP²Šây/-ÒyÆb‰¥PÒöFr ³EV�P²šòK8®à{˜Æç…dÔz‘Ôu¦Þjš~Ÿ·í·ÖÖÛºyÓ*gó4nŠŠÞêÞò5´ñOèñ8`L–úÎ ¨­fº‚;‰¿ÕDòïþè<ŸÂ€,QYͯèËrÖÍ«X‰ÔàÄn0>˜ÎkF€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (ªÿo³7ÆËíp}¬.ÿ#Ìfß]½qï@;¬hÎìÌÇSYð”ø{þƒÚ_þGþ4_êwº>ª–·pNÐÛÈ$Ha*x8èx5ç?< ëÞ’óS°óç/9×å ¤ +ÜФÅâM yqkZtŽz*]!'ðÍi×}ð¯Ã’Gmi%¤ÅNÉRgm§· H"¨|#Ôîî´kë ™E²•V&cœ)åÐúÐsmªé×—2[ZßÚÏ)Ö|E`7¦�¨¸Oï$ŽãŸo—R+ÝôÝFÛVÓmïí| u?Ðûކ€ûFÈ_ý‡í–ÿl#wÙüÕó1×;sœUšó‡ÿ’éýyÿ솽âxím¥¸™‚Åv=€&€+>±¥Ç~,_R³[ÂB‹v�D™=Ü眊»_=\Úê……÷ŽU™]5%(?º:çð%~5ïZ]üz®•iú»ˆ–@=2:~(ÝQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@G=Ä6Ñn&Ž(ÇW‘‚�øš’¼—O°é'¾Hæ€=.Û[Òo%Zê–SÈx Â1ü�«õÄßü+ðÕÍ«%¥¼¶Sãä–9�°{d1 Š—áåÞ¶úMÅŽ¹or“Yɲ9§FS*÷?{<ú@óø‹Dµ�à¸Ötø¦C‡ŽK¤VSèA›¨ >[œà6à3îzúP­ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEQEyö­ãƒâ>•iµlºI…¾Õ‰PÆyœ3v[ÖÆ�¬«ÿë”϶1ϳڽ€+Zj6WæAgyopb;dòeWØ}¬×œ|)ÿ]â/úüû5t~<Ö?±|}p­¶iWÈ‹×sq‘ô?…kÙkf£#Gc©YÝH£s,«�=H®×‡xzÒøŸÃ—— D:­¾%ÏwžŸ†c'ñ¯q Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Ë,pÄòÊëh¥�Øà(I=…Ei{kžÎæ˜I#̆@ëŸLŠ¥â_ùµúò›ÿ@5Íü'ÿ‘?úø“ùŠî*µž¥c¨ •í½ÈŒáü™UöŸCƒÅY¯3øAþ§\ÿ¯•ÿÙ¨Ó(¯‹ÃÞ8ø�âV»¸ž(íeT2HÊc�¸kzÛá�ku Â_ß–‰ÕÀ%0H9þízQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@y�ŠÅÏ‹¾ AáE¸xtûhÄ·!,p?‘P=2Mzuy†»sÿ�ÅhµËµa§jˆ¤” „!BŸËjŸ¡  MOá¦�šÓè‘Íe©Û©’ Òf$¸ä’G>ت_L�á-DÄWÍ7o·wMÞZc5Ðêþ;Ðtý*K›}JÚêr§É‚ »¿a�ÓŸZã¼-í—ÃoËh¬/"–Rƒ«×·¨  öÑìþÑwã;ëk½By —’é‘@üJ’zûtÅdé‡GÒ>*éðxbó}�Ìe.#ŽRé» À=ú)êjiþ ¼Ð×QÖnm.57f7&úãNN8cÈÆyþ•V}W@oŠ$šJÛ[iÖàÄÓ$b(™þlàðP3@tm9dò ]ÿà''>À~“ðãR±—Æ^!xö[%Ó†¶…ð„®æÀ ô#�ë@œÞ:ðÌI º¼ $lU”†àƒ‚:VĽRâoÅw¤LÍiq*‰e‹<ÄAü�8§zêßÃ: ²4’hšk»ÌÍi$ž¤œVW‹uäðv�jði1ÍbÒy‹‘Æc¯P5§ø_áÞ±¤¬Q§� #ܲÌJ޽±Šèô¸o¼à{¯í+¤¼{$’HŠçî�•^yë‘ôÅcßéß 5[&¼yôØ.íöóˆœÀëìV³¼o¨kÞ×ôÓ,²Ú’ÑX<Ç“ÆqÏA�¿Lš§á�;ÃZí»ë~.Öm.5 §cäMz#ò” €ÀŽœ˜ÇÛ¹t¯ø«M½ðÆ« öR®í"¹…<zFzלT¾ �Á—H±×-,­õkfd›ígË/ÉÁÉ g¶:ñW¥oËâ{Cðý–¥$�™§‰ÎÈÎFC`dþC½3â.�§'‰¼9"ÚFúô­ÉÇúѺ1ÏàOç]úx{FM:=?û2Õìãré ‘Ucž@9ç“ù×ñ2D‡\ð”Ò°HÒô³»£$“Z¾<ñ`Ѽ-ö�.â)'º“ȆXØ0N fôÈÆ>¤PÿøÏHðÊyw2ù·d|–°òçÓ?Ý_Ã5ƒàÝTÔ£p-ìµK;‰ˆ$GÊÍ�×€hFŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¸¿‰zåÖ“áø­¬]’îþQºœ^ø>½ã]¥p_4Û›�ÓRµBï§O溎ÈzŸÀ�øf€$µøUáÄÒÖ ˜e–ì§Ïr&`Û»�3޾¢°¾ÛÜÚxï^µ¼�§ž¼“+– ÁAü€®ÎÛÇ^¸Ò–ýµ[X”¦æ‰äbœr»z“ô×ðêõµ?x‚ù¢xÄéæ*8Á \ÏáŠôao¥èëu|!´³óÜNcÝÔå�~Iëë^}â/\xë‡<1m$¶ò2‹«×R¨ªxô}N0Q¼Ôl|eã;È5ÍZ+=N}‘[¼Â?=�#<žzž `qœ×yeâéÖ©meªéP@Ÿu#�þtÍ|AÓbÑþ[éÐ’Éo$HÿÉüNMKñ þIt?KéR|P¹‚óÀh¶™&†Iã)$lXdô"£ø…ÿ$º¥¿ô x{áþ“{£A¨k‘=þ¡yË$’JÃ``PÀÀÿëUY�Ç^"ðÜr<šrÅæ,nsŒíþ�ƒë�]þ‹ÿ ;þ½cÿÐEqZü–_ÿתÿí*ʱðÞ�'ÅÍKK}>c˜t€ƒµ[l|þ§ó«àxãÃPXKäNêaŽ@3åîm»‡Ðþ4–Ö?uY.î"�ÉT4®¶3ŒŸ¡üª_�ßü&A�Gš€6FÑü ¡ê¶Ÿj~Õ³n–YšSÛvN9lt¹Ïx&ËÄZ_öÿˆüÛë«ÖgPò²…PHt�Cì+ºñ>›&¯á�FÂ/õ³@Â1êÃ�?0+’ø{âÝ2E¤êWpÙ^Ù‰’åÄy$c8éÓx  ÍKN|a¥]éRHº^ þLöìå€ä×Ù²;䯥ø“ ÍÏŒ¼;mg1‚yÃD²¯TÜÁIü‰¦x«R·ñ§‹´]G�\Åm/›q<| Áï€=2@­ÉJð—ûÿû0  ·_ ü44i`ŠÕÖàFvÜ™X¾ìu#8ü1Š>ÞÏyàµYägû<ï 9!@Ãuvwñí/û‡ùW ðþDÙ¿ëõÿô þŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¼§^´ŸQø¾4ønÝ.­sÉ "ÚY€=‰ÛŒû׫W�?ü—(ÿëËÿe4Ò/‡t¯x{S‹Kµ,¶îdùÙ‹§É>¦¼ÛÀ—þ4¶Ð?éWv~{$ÎoÂä¬^1ŽÕëºÇü�/ÿëÚOý×ðƒþDÙëñÿô  �s\ø••;ÜiÖ�„>dÖ ;¢÷?}±Ç|q]7Ëm E&�òH²¹3¼£d@éŽ0o­uŽ‹$lŒ2¬ ÷æÿ¥ÿ‰£nz¥Ðb=2 ì´Ï‡¶ÐÞk^6¶¸ŒI ·!¡¦QáK™¼âÙü'!67MæXJÝ2zÇÿx{Ôß ?äeñ�ý~/þ‡-nx÷ÃÄZûa�FЙm™x$÷\ûã�p( ÿäºGÿ^û!­ŠZÇög„$¶FÄ×Î!ë·«Ècþ\oƒu¹õÿ‰–W—I¶äZ4Rÿ´Ê„øõ­_Äž1ø«g¢¸2Xiñ–�A8‡kãÛ!Oã@›EPEPEPEPEPEPEPEPEPEPEPEPEPEPEP_‰äVÕÿëÊoý×7ðŸþDxÿëâOæ+®Ô­>ߥÞYîÛöˆ,únR?­y¯ÃïÙxrÖçÚëý‚ê Ø«J0§8ÈÏn™Éà‚(Õ+Ìþ©×?ëåöjèõ�ˆÒ¬dš=FÞî`§Ë†ÝÖnÀ‘Àæ²>é7¶»½™sßÈd‰dî�ò’= 'ðÅdh~ ñƒÞjŽ÷í¢Cw9•Ù6É,‡$Œ<¸÷{Óïî¼SðîîÖê÷U“YÑæ�G!—;Ôþ$�qœrAÇ5¹á¯ˆ0ÞKuaâ6¶Òõ+yJ”s士¹ÏLVGÄ]~ËĶžÑ&ŽþöâáXùz¨þ!ÇÀšôÈ¥IáIc`Ѻ†R;ƒÈ§Õ{ o±iÖÖ¡·y,yõÚþ•b€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ­}§Ùêv­k}mÄ Õ$\Œúý}êÍ�§x'ÃzUâÝÙéQ$êr®ÌÏ´ú�Äàý+CJÑtý)¢Óíü”šS4ƒ{6\ã'æ'ÐUú(œ¸ð…î®�̺<a;ŽÆdRÝÒ¬êÐuKk{k½2†Û"LÆ m#�jÚ¢€35i:¾Ÿ�õ’Mm<µ$‚˜ äqïNµÐt»- éPÙGöœÀùu999ÝœóZ4P9mà/ Ú] ˜tx<Ðr7³8ýÖ$~•nO h’ëi¬½‚h) & ÑÀ8þ±EÍ´–ïos sC ÃÇ"†VàÔ´P0>xPMæÿcE»Ð»íü³Šèà‚X x’(�aR5 ª=€©(  MW·?Ÿ¨i�Ë7y(ÇêT‚µ¥h:V‡&›c °o¼P|Íõ'“Z4P~¯¡éºíªÛjv‰q¶å H*}ˆ ŠÏŸÁ¸Ó-ôétìÚ[³èè;V�‹«øGA×n–çRÓ£žuCîe${í#?�Osáý.óP²¿ž×}Í�Å»ùŒ6~àþ9­:(¬=WÁþÖ® Åþ™ ³²)dfú•#?�nQ@ÚN…¥èq4zeŒVÊßx ù›êO&‹Ý MÔ5+MFêÛÌ»´9‚Mì6sž€àþ5£E#(e*à Œ¡£èšv�fÖše¿‘9�¦öo˜€ Ë{ Т€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ Î:šuÑ­oø˜òÄÛÛîãÛœ~•£E2hRâ !•wG"”aœdƒT´}NÐl�¦™oä@\ÈS{7Ì@å‰=…hQ@di^ÑôKË‹½:ÐÁ5ÇúÒ%rœýÒHëíZôPn™ iš=ÍåÅ…·“-뇸o1›{dœòN9cÓkJŠ(Ûš%ž¶úŽŠÇ~å‹J²> n¿.vóô©tÿiZ^¥u¨YÚùwwD™¥23ÉÉêN9ô­J(¬­[ÃzN¹=´ú�§�-±&:äá#=ZÕ¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¡ªhšfµ�R±†åWú£ð«ôP1ÃÏ [Ê$M"ÀçHî?&b+¤Š(á‰b‰8ÐaQ€Sè  ËOév½Î«mk²öè4¾cÙ ô'�: Ó¢ŠÈ¸ðÆ�s®G­KhN£6̲ºž:pŽ9Š’÷Ãú^£ªÚêwV¾eå¦<™<Æpr8ŸQZtPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPYZφ´yÚ–)pbÎÆ,ÊÃÛ*AǵjÑ@W~Ò/tX´{‹@ömÙ‘†6ôäþµ£oo¥´VÐ.È¢A.IÂ�€2}ªJ(µý…¶§c5•äB[y—k¡$d}G5N×ÃzU–‹6�³.Ÿ0`ð™]¸n r?Z´PM3L³Ñôø¬,!òmbÎÄÜ[$žI'©5=ż7vÒÛÜF²C*”tnŒÁ%‹§øKDÒì/,l¬Œ6÷‹¶t9Þ0GRÙÓsIÑ´ý Çìzm¸‚ßq}�‹rzœ’M^¢€ Ê�ÃzL:óëqÚmÔdy„�Ïû¹ÛÐÞõ«EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE—«xsG×0u->†Øa€ôÜ0ZÔ¢€9Û/xcOœMo£Áæ)È2“èÄ×EE‘«x[D×\I©iÐÏ ó9WǦå ÒéÑt"ͦéðÀì0\e˜�MÇ'­EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿÙkalign-3.5.1/doc/images/Homfam_scores.jpeg000066400000000000000000005126101515023132300204330ustar00rootroot00000000000000ÿØÿàJFIF,,ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ‰M"ÿÄ ÿĵ}!1AQa"q2�‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2�B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷ú(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€*ßêV:U©ºÔom¬íÁËq*Æ€žƒ,@¤ÓõM?W¶ûN›}m{o¸¯›m2ȹFT‘šóÏ�òKnëæý  ýŸ?䙟úþ—ù-z­2Yc‚ši8£RÎîpª$’z }dø§þE kþ¼'ÿÑm@iž Ñu§‘4­cO¿xÀ.¶·))Pz´œV•|çû5Èo^ÿ¯h¿ô#_FPEPEPEPEPYz—‰tåmõMoM±��8Šêí"b¤‘œ1ŸjÔ¯—¿hÏù(–_ö �ÿFË@@ÿÂwàÿúô?üÃÿÅQÿ ߃ÿèkÐÿðcÿ^\¿³f�Êü$ÜŒÿ©J_øf½#þ† ïûò”ë6>+ðæ©v–š~¿¥]ܾJÃoyŽØ8PIãÿ�Õ]KàÇÄ.òîçÄ–RA,ˆ/® eU$ŒÁàPßÙ«þCz÷ý{Eÿ¡ö¯xÂÇÁ›W½BŽá¦�ôQéÐ’{kÅf¯ù ëßõíþ„i?iFiüC¡èêO—³\m‚ÎåGþ�úš§§êÿþ(Í5æ“y-†ž®T4ýš?Ý >f?ž=¨Ô5‹Ÿ ¦†óV¼–ûOg Zy~Ó Ÿî–?2ŸË>õô?‡ôkx~ÃHµ@°ÚB±Œ¤[êNI÷4xƒF·ñ‡¯ô‹¥ Ü-ÈèHá¾ à�q@Þñ…��ü5¯d¦6$Ç< ra�uR{õàŠóÿŽ^9ñƒ®45Ðu² •˜Ì<ˆäÝ´¦>úœu=+–ý›µ¡ñ¹£±;$¶[�¤ð)ÿÐÿAV?i�øúð×û—?Î:Ҹ׾#|Pšy<"èÞ‰ŒqÝÌþSÜÔî°ú(t$šãn¼Uñ/áW‰-á×u ï “çòîg3Åp™çkžT�ÀŽ2ëôg…,`Ó|#£ÙÛ H¢³‰@©9?�y?í)èr‘ó­ÔŠ )ÏòV|@ø­}<~ £èp†îWòÙÛåÀ$dè'‘\¦µ«|Sø[«Z˪ë7pÌIFšá®`›Wæäuö>•îÿ ì`°øeáøà@«%šLØîÎ71üÍrŸ´WÖ€=Ãì>&ðÎ�­@…ò&Âs±º2ç¾#ð¯�?hÏù(–_ö �ÿFË^ËðcþI&ƒþìßú9ëÆ¿hÏù(–_ö �ÿFË@O§úµú u|Þ¿þ#•xžÇÏýÇÿ¥ÿ…ñþ†{ü¸ÿãtô}x¿ÅŸ‹Zž�­¯…ü3þÓ!<éÊyŒŒã*ˆ½ Aɨ®¿áw„µÏèvZö¡ íÄ·FTx¦yMª1—õ¥¿ð'„-Qô¨ü=ñ;ƾñ„�̳Û;ªIö�¦H•Ž‹ ûËë’z†½nûâß�4üù¾#µ�ŽÖêÓgþøWÏ_|o¦xãÅv—zLR‹k[q›*íiâÙ°çŒûÐ×Uóœ¥ROm¦Ø¥º.é¼à±‚Ê¡ˆ »¹ÏÖ¾Œ¯˜þØÁ{ûEê-:û=íìÈMÁØøg?Q@º�†>7k6ͪ˭ý–B7®Ÿmx`eBáFß͉õ¬_ |v×|?m¨iÞ$†]Jæ$+jddY�ÆÉuëÏÞãç�¦kæÓm®ÿjµ–5h´Úb¤pYPÈ?ñášÜ›ÃŸÐ`“È�§™÷œôÎ3ô¡ûJj²›½GV"%ŽK§\ðÌNÕ?€ ÿ}ì|7ñOᧇ|7§éÚê¤v°,gW¶>f?»êNIúОj7¿þìÔ5ù¯ôðÀ;Í7Ú¢>ÌOιõãë^ÝàÙxóɩڧ“:7—snNLO�^àõúƒ\ö§ñsáž­¥Ýiךè’Úæ&ŠE6W©?òμ×öp¾x|a¬iªû¡šËÎÏL˜äP>’ì~9xçÄ~¸Ð×AÔ~È.Vc0ò#“vÒ˜ûêqÔôªš‡Š¼yñ'P¹µð]?C¶)õ9Ï=Ç\6 Ð(Î:‘œVOí1ÿ^ÿrçùÇ^Éà}& Àú-…ºXí#-�÷�”3ʼn4àüÿ¾Ï¡¨k—v²I´J׿nNҕȰö5ï~ñd~5ð�ž´‘e“)<@ä$ŠpÀ{wÄV?Æx’_„ÚîõjÄÃØ‰R°ÿg�ù&ÓØB_ý(ßÅ�Š‹à[x´ý:8çÖ®Sz‰9H¦æÉ9Àö$ú<µðïÆßZ®¬ÚÍå§š7¤O{ör÷îÓ~„ §¦D¾5ý¥n ðómíï¥;�VB zeW�s_NPÎÞø¯â¿x¥<;ãÕy .¨óLK<Ü8tõ<ŸCÆ+Ù>!ü8ñ!?³gÿÐ d|Bø[§|A¸±¸¹½šÎ{Ttß.¤‚Ï¡ï¿ãKceðŸ[´2´¦ "XÌŒ0_lDdýq@>|6ñ®µ¢è7^ðµƒ]kú�Þ蘨+ ¶úð1“]N¥à¯�pÛ¶¥ÿ $÷¼ÚÚê.èÐ~kökÒ 0ëšÃ 7£¶�ˆåW˜©ÛùW¾Ð‹|ø¥ªø�RŸÃž!a-ìq™ ¹(ÛiÃ#�Üg9Çcší¾+kº—†¾ê®‘sökØZ ’ìWÆéO èOjñÿ"ÇûMꈀ*ý²û�ÿ¯Nøåÿ$—Vÿ~ý”Àh_|{ã] ÇBðØkaõ-RX‘26À6�—o8$öÖ?Š-~.ü?DÖo¼Essm¼–+¶š$cÐ28Óîãô¯Dýžì`·ør÷H€Muy#HÝÎÜ(Aƒùšê>*Æ’ü.ñ ¸È¥¿A¨åñ|`ñwŽ,l4/ i‚-vHɾºlŒ�É»!A$·LàdàÖ?‰´_Œ ±mrëÄ—w6ñek{ç‘bÉêÈÀ döWUû6XÀžÖo´Ix!fïµP?75ê¾/�&ðV»ƒ(Ú}À#þÙµrÿ¼{q㯠K& ¨5+)S² WÇbyz�Â¥ø§ñ |?С–ÞŸR½fKd“î.Ð7;c¨^;äWŸþÌßñïâo÷­¿”µê~/ð‡¼föÓk±JÿdV”œÆN>ƒò Ó,>3xîÍ5xu‹«;Iþh[í_eW_UT焎}ê½ÿˆ~,|-½¶›Z¼šòÊVÀûL¢â)qÉ]ÿyOâÅ{uÇÄ/x~Ý,ßÄZz%ºÖ8dóJ “Ú¼‡ã'Å?x¯ÃQhº#MtÿiYšá¢(Š0ãvN}:f€=ãÃZí¿‰¼7a­Z©H®â'%F_À‚? ò�ˆßuÏ üZѴȵak¡¸¶’ò3l6H�î*X|£±úW]ðWþI…ôŸÿGÉ^=ñêÙ¯~+ØÚ¡ÃOg`ú‘Çõ  Z§‹~&|JÔçŸÂ6ú•¦�”ƒìÎ! Ží!#,{Œà~¦ÿí—QøgÁ©zXݬr ÷6Ný‘nÉïÎkÞô½6×FÒ­tÛ„V¶Ñˆã@:?Ÿs^#ûLÇ—†ÿë¥ÇòŽ€=Âò$^ Ñd‘Õ4虎5É&¼Ä_üKâ¿Aá߇µŠµÙ…Kêß:�±�\dþB¸¯|SºÖü1§øgEóbÓ-láŽò`iÜ"‚¾ÈçÚ½‡àn™áëA£�÷—-ü²c̯TöQœ�èAêh¾Ñ-5 "Þ WRmJùW÷×-F»áT§zТŠ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šó�òKnëæý  ýŸ?䙟úþ—ù-hülÓoµ_†÷ºu•ÍåÁ¸ˆˆ­âi€Üœ(&¡ø¥êGÃÓm©XÜÙ\}²Vò®ahÛ.ŠôªÉñOüŠ×ýxOÿ¢Úµ«/Ä‘I?…µxa�¤–K)•Y‰Bu4àÿ³Wü†õïúö‹ÿB5ík-·Œ4MP/É%Ÿ”§ý¨ä,ô`­ÙóÃúÖ‹¬koªèú…‚IoFº¶xƒÇ n5é_| �<.ÖE†úó­&nŠøÆû$pÎ(§Ó55m*ÓQ¶`Ð]B“FGu`þtjz„N•w¨Ý0X-ai¤'²¨ÉþUóN‡ãoü$‰´M[Dyì#bbK…`©Üùr®AS×þÑ®x×Ç¿â]IÑ >FT·VÚýÇ™+`qÇãÅ^ýœme¹ñ†·ªù#³ò˜ÿµ$�‡þ‹5{ö˜ÿ�¯ ¹süã¯Tømàh|áu°ókٛͻ™z3ãì�ÀüO¯;ý¡t gZ¹ðùÒ´›ûñN$6¶Ï.̘ñ� ã8?•{.‡ÿ 7þ½bÿÐEyí'ÿ"΋ÿ_�ÿ ö -Â9‘ÖÚ5ea‚Q�Eygí£jš×‡´ˆ´­6òúHîÙ�-`iJ��HPp(»øyÿ$ãÃö ƒÿ@ÆþпòMSþ¿âÿÐ^»o[OgàÛ\Ã$Åa IªU‘‚ ‚ ûW)ñÓKÔ5‡Ém¦X]^Ü}¶6ò­¡i6NŽhCàÇü’MýÙ¿ôs×�~ÑŸòQ,¿ìþ�–½³á%�Þ›ð¿E´¾µžÖæ5—|3ÆQ×2¹SÈàƒø×“ü{ðÖ½¬xòÒãKÑ5+èM� ¶¶�*†Hq•gqï@E§úµú u58Eú uò̉©ühøµq§\jA¦Û´­ŽD0#mùW¦æ$dûú+êjù‹Ä~ñOÂ�ˆ“ø—D²{�6Y$xä—�cœ´rc•ÇcÆpî(ÖtςӑwéO{ ÿ–—S»øô¯"ø÷¥é:/‰´k &ÊÖÎ5³ÞÑ[Æs!œu<O¥t�ü|ñ.¶‚ÏAðg™~ÜYu×hQúšá~"xÆv6öÞ)ñ½Ýåû·Ú„K¼Zãˆàdd p1ŒÐÖõógÃ/ù8�oþ»ßèÃ^½ðÓÇsøóCšöãK6@ëùË,§nK.@Àöçë^gðóúݗÇ}_Q»Ñµ {&¼)s-«¤lÉ\19íë@@×Í–_òu�ÿ_²ÿ膯¤ëçû?ëkûK6ªÚ6 4ßµÈßk6¯äàÂÀøÆ3ÇZú¾lñ·üœæ—ÿ_¶û%}'_?x¿ÃºÝÏí¦êvú6¡.ž—vL×QÚ»D¡vn%ÀÀ<ñ@@ÑEãÿ´ü“í?þ±ÿè©k঩¥ð·KHØ-7ÛJ£øX1#ÿ*Ìøû¤êZÏ�¬mô½>îúuÔ‘Ú;XZV åJ2B‚q’9÷æºV�ãÿ„QÚë:mŒ·šf¡k·Vò@ÄDåAe‘ÌŒ¤�§¯¥}=_2X̾+ý§>ÕhD�G|_Ì�°G�ßBPcê)ú¿Æ�x¾Ñôm DkYg9ÑY°z…8ù~¸Èõè_þÏàËIµmaTkiåˆ�ìñç;r8,HãÐ{ÐûJXȚ懨mýܶÏ}Ñ·ìõé:OÂÿ‡Z¾�e¨Ûø~Ýáº�&FIÈ`÷«gâ‚­üwáit¹CrŒ&µœŒˆäŽ}ˆ$®{W…hÞ-ø�ð�_GÔôg¸ÓQ‰�'V(¹ä˜å^0z㟠9 d¸øMðîÖÚ[‰ü?m1!y¦“  d“ózU?‡KðÒëUººðMº‹È! 4‹ë„cÓ÷œrWô¯+Ö¾"xïâ�©Ð´M à´¸ùfªÌ\z<‡W×§¹ÇìŸ ¼žðɶ™Ò]Jé„·r'Lã„¡yüI=èÌÿi�øúð×û—?Î:÷]þ@oýzÅÿ Šñ¯Ú@Öu«Ÿ�+I¿¿$âCklòìÉ�Ú3ƒùW³èèñh–ÈŒŽ¶Ñ«+ BŒ‚(“øÇÿ$›_ÿ®qÿèÔ®öxÿ’m7ý„eÿÐRºŠÖWz�ÃnÒÆÖk«™#Œ$0F]Û÷ˆxQÉàÃø¥ê:GÃùmµ; «)ÍüŽ"¹…£m¥S Ç€<ËÂ2/‡?iKËk²#YﮡRxÿY¹£üò£ñ¯¦ëÆ~1ü.¿×ï"ñ?†Ô¶« ¨žm¯(_ºè¾:c¸Žy[O�>/ÐíWNÖü<“_Æ6y“«ÀìÚ\r~˜ _ñçÄ}'áüv'R‚æáï ˆÒÜ) .2NHãæx³QM_àþ¯©G‘Gw£I:Ç&7(h‹qßšñ]3ÂÞ0øÅãu¯ÛIe¤¦ÐÌÑ´h">\@òsÏÍîNz ÷ŸYI7ÃÍvÊÊÝ䑴领P³1Ø@UQÉôÀ 5ý›?äWÖ¿ëõô^Ù^Aû?hÚ¦‹áÍZ-WM¼±’KµdK¨"Ã`ä"½~€>nð_üœî©ÿ_—ßÉëÓ>9É%տ߃ÿG%p¾ðî·mûEj:¤ú>¡ž÷WŒ·rZºÄÁƒm!ÈÆxçšô?Œš}î©ðÃS´Óìî.î]á+ ¼fGlJ¤á@$ð3@Ÿ¿ä—[ÿ×Ôßút?ä˜x‹þ¼ÛúVGÁ-6ÿIøq®£esgp.ecÄM€O ­ßˆö—7ßµÛ[Kyn.%´eŽ(P»¹ôrMp_³ü‰§ý„›ÿEÇ^�â¯ùõ¿úðŸÿEµy÷À#SѼ¨Áªi×v3=ùuŽê‰™|´€ã óí^‰âX¤ŸÂºÄ0ÆòK%”ʈ‹–bP€Mx¿ìÍþ£Äßï[)jŸÇ?꺷Œ¬|§ÎÑ[8ˆH�Љ¥�áCcª€W�RO¥n~Ï:¯¢ÃâªéWÖV·òþÕnñoÀ“8Üq‘ùÕO�þÖ®µË_ø~ n%‰n#�wI!ÊÈ£©ÇL뀋Aøá :Ú?í4¸Õ.@ùÚIZ4ϲ¡}I¬O�>ð߆~ħH²²š[Ø�Ic{pÇ�'�ëYV´>º°­•×…çRih¥tÜßõÏi?†k7žø�ãýëÄú婵ŠÉYi1ÆC²’7™È s–ùŽ8ÅzÏÁOù$ZÒý%yWÆOù.ýs´ÿÑÍ]ÀÝOkm๴–T´I¤[Ðä –ÚË·®XóŸÂ¨üXðî·¨übѯ¬tmBêÒ8íCÜAjïâV',4ô x7í1ÿ^ÿ®—Ê:÷šñ_ÚCÕõ«Mt­.úüÅ$æAknòìÈLgh8Îå@'ƒþxy>&’m· ^Î9nç` Œì¡�¶Ò~QÛç>Gàn÷á/ÄË¿ëo³O¸”A;ùg0öÁçØžâ¾�ðÄ2[øOF†hÞ9c±�He`€AèEy×LJ²xŸE�ZÒ­žmZÄmh¢RÏ<$ýÐ$©9ݽ¨ÖºÑ^wðX×o<(ºgˆ´­FÎ÷N$–òÙãÅü$,1ƒô½z%QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQERyå0 À'°¦ý¦_ïþ‚›/ú×ÿxÓ(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(Ä3Èòª³djuÄÒ$¸VÀÇ¥Eoþ½i×_ë¿ oÚeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú �M'ÙËnùƒc8ªÕ0ÿ�Vÿz€í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýI ò<ª¬ÙÚ«T¶ÿëÖ€%¸šD— Øô¨¾Ó/÷ÿAKuþ»ð¨h_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýI Ò;0fΞ•Z¦·ûíþé ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿôadcj_?65J­¯üy¡þtÚeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚¤Ži9 n@㊭SEþª_  ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐTöÒ<›·ãª�Z³êÿ…F׆ 7AIö™¿ú �þû}i(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßý]BLjORfÖ”_ê“ýÑ@¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(:_õ¯þñ¦SåÿZÿïeQEQEQEQEKoþ½i×_ë¿ m¿úõ§]®ü( (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ˜Ç«½PÔÃþ=[ýꆊ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¥·ÿ^µKoþ½hn¿×~ Muþ»ð¨h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©­þûºjšßï·û¦€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«kÿGè�T«kÿGè�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š¯u}kd»®&TÏ@zŸÂ“ijÊŒ\�¢®ËV ž+²S„Šg÷ÀùÒÅâ»8xæ�ܨ#ô5ÚΟ¨âm~FnÑP[^[Þ&ûy–Aß‘õªz´ï±Ë(¸»5fQE1Q@Q@Mú©~‚¡©¢ÿU/ÐP4QEQEQEQEQEQEQEQEQEQEQEQEQEQEjÏ«þV­Yõ€+?ßo­%+ýöúÒPEPEPZQªO÷EfÖ”_ê“ýÑ@¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(:_õ¯þñ¦SåÿZÿïeQEQEQEQEKoþ½i×_ë¿ m¿úõ§]®ü( (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ˜Ç«½PÔÃþ=[ýꆊ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¥·ÿ^µKoþ½hn¿×~ Muþ»ð¨h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©­þûºjšßï·û¦€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«kÿGè�T«kÿGè�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š‚öålìå¸nˆ¹Ç©ì?:MÙ\q‹“Q[³/\×€û=¾ ÃOdã\t²É4†I]�Û«1É4M+Ï3Ë#nw9'Þ™^mJŽlúü&xYoÕ…QY�d�Ï-´¢XddqЩ®ÓDÖ—R�Ê— r£�:0õÃÔ¶×ZÜÇE¦�˜QE(¢Š*h¿ÕKô Mú©~‚€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«V}_ðªµjÏ«þYþû}i)_ï·Ö’€ (¢€ (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@$‰Ì®B62{S|©?¸ß•:I\Jà;c'½7Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐ�Fë2’¤¥-ÌnÒåT‘ŽÂ’ ¦PX‘õ¥¹‘Ö\+1ØÐ^TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆüªQý™†Ó�Ý1Qy²}¿:”Hÿfc¸çw\Ð^TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆüªH#u™IRÒ£ódþû~u$;L ±#ë@ s´¹ HÇaQyRq¿*–æGYp�ŽÆ¢ódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*–ÝY²¤|§µEæÉýöüêX$vfËòžô•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*²ªßd+ƒœ*·›'÷Ûó«*ÍöBÙ9Áæ€+yRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò£Ê“û�ùQæÉýöüèódþû~tyRq¿*<©?¸ß•lŸßoÎ�6Oï·ç@•'÷ò¬/—‹HU*@yBœý þ•»æÉýöüëÅJóhû‹#‘XäýGõ¬êü êÁ[ë¿sˆ¢Š+Ì>Ä(¢Š(¢Šê´�nÒËGŠ;‰˜¥€E8ÎjSâÛ<ñäzà�rVË4’G�,²„¤ç+Ý�Í¿‰4éØ)‘¢'þz.æ8­tV‘ ,¤dÈ5åõ£¥ëWz\ƒÊ‘Œ$üÑÁúzÖ—xäÄdñµè½{3Ð|©?¸ß•TŸÜoÊ ´Ôí²O ¬Q½ùÐÔþlŸßoκӾ¨ðeg¸yRq¿*–8ÜE(*r@Ç›'÷Ûó©c‘ÌR’Ç sLD^TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoÊ�*Oî7åG›'÷Ûó£Í“ûíùÐåIýÆü¨ò¤þã~Ty²}¿:<Ù?¾ß�TŸÜoʬZ£.ýÊGNµ_Í“ûíùÕ‹Wfß¹‰éÖ€ h¤,~FëéIåIýÆü©ZY�ºúÒy²}¿:<©?¸ß•TŸÜoÊ�6Oï·çG›'÷Ûó Ê“û�ùQåIýÆü¨ódþû~ty²}¿:<©?¸ß•_Œ×¨y²}¿:¿&$'®:Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  éÖ¿ûÆ™O—ýkÿ¼i”QEQEQEQE-¿úõ§]®ü)¶ÿëÖ�uþ»ð (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*aÿ­þõCSøõo÷¨(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ –ßýzÔU-¿úõ ºÿ]øT55×úï¡ Š( Š( Š( Š( Š( Š( ¦·ûíþé¨jk¾ßŠ( Š( Š( Š( Š( Š( Š( ­¯üy¡þuR­¯üy¡þtRŠ( Š( Š( Š( Š( Š( Š( ¢¹�.m¤�þë©SRÑFãM§tyµÕ´–—2A(áÇ×Þ¡®ïXÑãÔâ K…+úûjâî¬î,¥òî"d=‰è~†¼Ú´œ‘õ˜)vcŠ…_ùêÃ$ýøÖ·÷sœËs+}\â¹å‰ŠÑjz´ršÓW›åüÏG¢¼Ú;˘Žc¸•³‘[6(¹…‚]�:?ï†ãJ8˜½ô\¢¬Uàïø…½ÌWp,Ð8tn„TµÒ�Ï)¦�˜QE*ÚÿÇ‘úçU*ÚÿÇ‘úç@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š)’EÈRTWSÕXdSè iÛTeÉáí2CŸ³í?ì±±xLˆä[n?í±?¥iÑQìáØÛëUínw÷³…ñºÛêî#*²…cÒ²«®ñ]¢½œwy¢m§'¨?ýë\�pVƒŒÙôÙ}uV‚×U£ (¢²;‚ŠŠy„KêÇ ª/+¹Ë1>Õß…ËêW\ײ>_:â¬.Y?cnyõKKz¿ø½¼F{ˆ¢]Â�Ä×¥×�C<¶ò¬°ÈÈêrN®ëÃ~&:ƒ‹;Ü Œ|Ž8í�ZíþÏ•Úw>{ýj£™Ô�9C‘ôÖéßÎËò:zš/õRýCSEþª_ ¬Žâ(¢€ (¢€ (¢€ (¢€ ÍÖuEÓ-wgáÿ3íZUÂx‚äÜk ü±~íG¦:þ¹¬kO’:Ù~W­ilµ3çž[™šYœ»·Rj:(¯8úÄ’VA[º¸ö²­µË–·c€IûŸýj¢ªqwFU¨Â´&�O¢³´;“u¤@ìrÊ6ôãùb´kÔ‹º¹ñµ éÍÁô (¢™EPEPEPEPEPV¬ú¿áUjÕŸWü(³ýöúÒR¿ßo­%QEQE¥ú¤ÿtVmiEþ©?Ýê(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3¥ÿZÿïe>_õ¯þñ¦PEPEPEPEP¶ÿëÖ�uþ»ð¦Ûÿ¯Zu×úï€ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©‡üz·ûÕ L?ãÕ¿Þ h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*[õëQT¶ÿëÖ€ëýwáPÔ×_ë¿ †€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ šßï·û¦¡©­þûºh(¢€ (¢€ ã¼Iª5Åɳ‰± G�âoþµuws}žÎi¿çšü…y»ÌXœ’rMrâfÒå]Og(éÍÕ—M½D¢Š+ˆú ¢Š(ODÕN¼˜ù8ô÷®ó­y…wúÁ¸ÑíÝŽX.ÃøWfoXžq‡JÕ—£4(ª’êv0²]Äu²i±êú|§ y}Ûκy£Üñ½�F¯Êíè]«kÿGè�S0AèE\_øò?CüêŒÊ”QEQEQEQEQEQEQEQEQPÜ][ÚGæ\L‘'«¶(Jû RQWnÈšŠÁ—ÆDM…–I=Ò3ýqK‹ô‰[ 4‘gûè¦k_cS~Vqÿhá/ËíÞŒO_3ÝAd§å�|Æÿxôü‡ó®~ �À,‡×Ö¬ø–â;­~æX¤Y#;v²œ‚6ŠÉ®Ùa)Ö¢¡#æ©çØœcR½tÝšèÒÑÀfµ˜“HŸuŽ=*OµËþÏå^TòšÉû­4}¶Žð�ëBQ&¾ûþˆmË�½¸¨©Y‹±cÔÒW½F”ãÈüÈúÎ*¥küRoïaRA3ÛÏÑœ¯øPgûíõ¤¥¾ßZJ(¢Š(¢Š+J/õIþè¬ÚÒ‹ýRº(ÔQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEgKþµÿÞ4Ê|¿ë_ýãL Š( Š( Š( Š(  mÿ×­:ëýwáM·ÿ^´ë¯õß…AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPSøõo÷ª˜Ç«½@ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQET¶ÿëÖ¢©mÿ×­-×úï¡©®¿×~ QEQEQEQEQEQE5¿ßo÷MCS[ýöÿtÐ4QEQESÕ”¶“v_)�é^y^œÊeX`Šó›ÛW²¼–Ýú£`QØ×*;3Þɪ+JŸ]ÊôQErèQEU�¶Ü Qj%e„vƒŒç×Ö«ÑBm⥺ (¢‚‹–:�ÖžàÁ)ÛÝ* ï´�^ SMmŸ,È>xÉä{ûŠóZ³§ÞɧÞ%ÄDñÃï/q[R¬àìö<ünâÜU¥ýnz5ȤY¢IPåCìiõèŸ(Õ´aEPEPE1åŽ?¾ê¿ïR¤‰ Ê:°ö9¢ã³µÇQE(¢«ÞÞÃalÓÎØQФú M¤®Ç¹5îX¦³¢œ3¨>æ¸{ý~òõˆG0ÅÙàþ'½eIÉ95Í,ROD{4²iÉ^¤­øžŸœŒŠ+Ííï.mt˜Îk”ø›­ÝéúM¦™§»%æ§/”¬§(Æ@=‰,£ñ4ÕøQáïì²²Jo6`Þy�»®ÜíÆ{cüh»¢¸O†ZÍåÞŸ}£ê.Ïw¥Ëåc“·�=ðT�¦+» »¤hÏ#*¢Œ–c€U´Õ´Ûù;=BÒáתÃ2¹€5Àx©¦ño�í|&³I�n‚k±Ác�Üþ@ô,hño€4Ý#C“WðúMe}`Á’VmÊ:õ' ž=(Òê�Þ«§X:¥æ¡klÍ÷Vi• úd×;Œ økÿ !Uóž ã�7vΞ›¹úV„< §ëz"ë^!I¯o¯ó.^V]ªOÉ#ŸÄP¥G"KÉ«£ †S�GÖ‡t�äeTQ’Ìp¯5ð×�àÿˆSx[Î’M2ò35¨�ä¡Á?û+ë�K⦛ž?µðšÍ$Zuº ®ÄgŽ7søб þÓVÓoähìõ K‡^« Êä~ÕÊóOøMÒ495¤ÖWÖL%fÜ£¯Rp@ÉãÒ»? ë_ðÍŽ¤à %�Óz’­úƒ@QEgKþµÿÞ4Ê|¿ë_ýãL Š( Š( Š( Š(  mÿ×­:ëýwáM·ÿ^´ë¯õß…AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPSøõo÷ª˜Ç«½@ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQET¶ÿëÖ¢©mÿ×­-×úï¡©®¿×~ QEQEQEQEQEQE5¿ßo÷MCS[ýöÿtÐ4QEQE‘®hãRˆKÂ3üCҵ詔T•™¥*²¥58n�3’'†FŽD(êpTŒL¯D¼Óm/×#£~5‹/„c'0ݲ�GLþ¼W°Ò[j}ÚŒ—ï4g+Eu1øAAýåá#ÑcÇõ«í¡ÙÚé÷ [¥h˜~[8ý? K>¥Ï5æ”]ÿ¯3‡¢Š+Ò (¢€ (¢€;¯JeÑa’„¯ëZµ“á¸Ìz,Dÿ3~¸þ•­^¥?�‹··�»°¤$($�êM) “€+‰Öõ§¾• …ŠÛ)ÇÇî}©T¨ ®ÊÂa'‰Ÿ,vêÍËÏY[±H·NÃûœ/çXWÞ#½»ÊÆ~Ï¢OÔÖ=Ã:ó‘ôTr굵ߘ¬Å‰,I'©4¨íF*á›Edw[¡»§x–æÙ‚]<^§ïÇ¿ã]tÇs Í ‡�†Aæ•»á­E­ï«·î¦8ÍÛóéùWUÍ>Y>a—ÂPui+5ø�•pÞ ¿kÍEÐÝBJ(÷îk¸cµ ô¯2$³NIäÕâ¤ÒHæÉ©)NS}?Q(¢Šâ>ˆ* ³ˆqêqSÕ{±˜sèk§o¬Býψy¿²ëòïÊþî¿�FŠ(¯­? (¢€ (¢€,¦Ÿy%°¹ŽÚG‡$oEÈzã¥W ©ÁC^‘áL^„‘�1™ÿ\JÜÀÎq\2ÆrÉÆÇÓQáåZŒ*)Úé=¯ú£É­t«ûÖÞÒWø¶á3Åuú/ƒãµu¸Ô Ë åb¨úúÿ/­uTV1sš²Ðô𙄔æùŸžßpQEÊ{�SEþª_ ¨jh¿ÕKô Q@Q@Q@bxžé ÓHpfm§éÔÿJÛ¬BÏa dG&°"³­~Gc¯¢ñRîqôQEy‡Øtºd¾’ØŸ’EÈãÿ­šçëoÂð´š·˜ËO׊Ò�ùÕŽLr‹ÃÏ›±ÚQEéŸQEQEQEQEQEQEQEjÏ«þV­Yõ€+?ßo­%+ýöúÒPEPEPZQªO÷EfÖ”_ê“ýÑ@¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¦«ÿ {ßú÷“ÿA5Ç|"ÿ‘-¿ëîO䵨ê¿ò½ÿ¯y?ô\wÂ/ùÛþ¾äþK@~ Èûá ÿêþÒ¿ú5?úÕéUÂüNÑnï´«=SOF{½2_4*Œ�§�;ટ¦iëñOÇG�;‹�™6›~ÿîçüs@žÿ’�âÝŸsÎ|ý|ÃÿׯJ®á–�yma¬ê(ÉuªMæíaƒ·$ƒí’Äý1[ºo‹´íSÄWšº\ »@æBè¬àçÔŽÔÉøwþKOˆ7ýﳿœ_Ò»mÿ„_Wß÷~Å6~› pþ(Y|%ñ ×Å^T�¦Ý †í£Úq·ŸÉHõÁ©<_ãÍ3SÐeÒtžúþüy*‘FÃjž¹ÈFF=è›Mÿð¢äþïÛ?MãúתxWoü":6ÞŸa‡ÿ@�ƒØ|3ÿ„p•ûA·É9ãÎÝ¿¯¦î>•‹àïéºF„š>¿3ØßXf&Ycc¹Aã ãÔž)ÿ’ÃὟÉ\ý7IÿףÿòZ|A¿ï}˜íüâþ”žó¦"V‚;7–Ê%Ý#¢V8ªÿÚz>qöÛlÿ×A^e,ÒÎåå‘��v94Êæx§Ñ¼rXÛÞŸàzÂKe*î�ÑǪóNͯ·äkÊ"šXwôƒÚµ¥IÍù8Ül0ñi?{¢4 ŠÎÞÞ8ScP£ƒÚ¤Í¯·äj¥é&Ûnì¡â›Èm´fHqæLÂ0FxÿÃñ¯?®§Åùòí=2ßÒ¹jóñó±õTpÉ®·ÿ ¢Š+Ò (¢€ r9ŽEu8e �­6•T³Q’N OÌõxäµ’%|™AèkÌ5 cg¨OoÙ…÷�å^‰yq"u@¬_hæùŸýú þøÿï¯MÊ7[£æ2ÜLhÕq–ÏúGE+)V*À‚=©+€úp¦º‡B§¸§V–“¤K©N8+n§çè=ê¡Í̹w2Ä:~ÊJ¯ÂÕŸ¡Ì:”b¬0E%z&½á¨µu{P±\D»W°e�ø×�××P¬ªFýzŸƒfx `ë8ý—³òÿ5Ô(¢ŠØó‚¬ØYɨ_EkÞ‘±ŸAÜþZºMåëá0?{/õþ•$ã$t`éFµxSžÍ¤zU´6V¶±[ÆÈÐ àô¥Í¯·äj¥áî~˜’JÈ·›_oÈÑ›_oÈÕJ(o6¾ß‘£6¾ß‘ª”P¼Úû~Fž¦ ­·ÇÍÖ¨ÔѪ—è(\Úû~FŒÚû~FªQ@ókíù3kíù©E[ͯ·ähͯ·äj¥o6¾ß‘¨®!±º·’ @(ëƒÁ¨h i´îŽTÒ'Ó'e`^ü’�Áþ†³ëÓ™UÔ«Êz‚2 RmNfÜlâϰÀ®9au÷YîQÎmU޾G mk5ÜÂ(#gséÛëé^…¢i–ºUˆ�˜<ÏóHø=}°§Ã6é²’5ôE¤­iQPÕîqãs b"V‰o6¾ß‘£6¾ß‘ª”Vçœ[ͯ·ähͯ·äj¥o6¾ß‘£6¾ß‘ª”P¼Úû~FŒÚû~FªQ@ókíù3kíù©E[ͯ·ähͯ·äj¥o6¾ß‘£6¾ß‘ª”P¼Úû~FŒÚû~FªQ@ókíù’#Ï—øÕ µgÕÿ q6Ù9Æ~†“6¾ß‘ª¯÷ÛëI@ókíù3kíù©E[ͯ·ähͯ·äj¥o6¾ß‘« �£oLqY•¥ú¤ÿtP¨¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠGE‘C+ # �J‚ÎÆÓO‡É²µ‚Ú,îÙ a>¸bŠ*‰Ñ4£uö£¦Y}£9ó~λóëœf¯Q@sZv’ßðšÞêë§%”"ÜÛÚ¡®\¾æ�ííÀäòk¥¢€$i,mˆ®Œ0Êà �¥U´Ò4Û –zu¥»ž­ *„þ UÊ(ªwzN›"Éy§Ú\ºôi¡W#ñ"®Q@ Ž4†5Ž$TEUQ€°¢HÒXÚ9]a•†AJuNÓHÓl$2YéÖ–îz´0ªø�W(¢€ (¢€3¥ÿZÿïe>_õ¯þñ¦PEPEPEPEP¶ÿëÖ�uþ»ð¦Ûÿ¯Zu×úï€ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©‡üz·ûÕ L?ãÕ¿Þ h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*[õëQT¶ÿëÖ€ëýwáPÔ×_ë¿ †€ (¨®fö²ÌzF…¿!CÐi6ìŽcÄÚ¡’Sc aýaϧá\å9ݤ‘�ÎY‰$úšmys›œ®Ï³ÃÐ� j (¢ Ü(¢Šé<3ª2J,&l£s=�¥uuæQÈÑH²!Ã) ¡é6ò‰í¢™zH�‡â+» ;®WÐù¼Û¡QT�ÚüÉ(¢Šé<€©­þûºjšßï·û¦€!¢Š(¢Š(¢Š(¢Š(¢Š(¤e ¥XPih  ét-6c–µ@Ø%•6?鑜‹`Çý¦'úÖ�Î�þ³Y+s¿½ŒŽ(á@‘¢¢ŽŠ£¯/üy¡þuR­¯üy¡þuf ßVT¢Š(ÄÖ¦}/ÌQ–…·~ùö®*½9”:•` ‘‚q\.³¤I¦ÎYAkf?#z{ãÄÓwæG¿”bcËìe¿C.Š(®CÜ (¢€ Ùðæž×wë;ÜÀwê݇õ¦iÚÕë‘L0÷fŸ ®ÎÖÖ+;u‚Ú‹úûšé£E·Ìö<ŒÃAÓ¦ï'øQEÜ|ÙF÷H²¿;¦‹}8oþ¿ãY/áK|—n¡@jýö¿ifÆ5&iGUNƒêk)¼W9?%´`zMmº¥UÍËúÔ+b¡BM/ë¹zÛÂö0°iZIˆìÇò´‘¤H5 Š0F®zßÅHÌ͹Qýä9ý+zÞæ¨„°HqS<$è|Q±–"uæïU¶K^CynÖ—³[¸Á�ÊþF½z¹Oø}îÏö…šn” KêÀwõ¾ª„¬úŸ3Ÿ`爢§M]Çò{œ-AÁàÑ^¡ðá]‚íš]oÎÇË d“îxÌþU…mm5äë¼m$ŒxU¯LÐtuÑìD†™ÎéXw>ƒØW6*ªŒz³ÙÉ0S¯ˆ�K{±Öþ}©EW’}àQEQETѪ—è*š/õRýCEPEPEPEPEPEPEPEPEPEPEPEPEŒÁT±8dš¡ªêÐéq Ã|­÷#¯¹ôÉÜøƒQ¸bDæ%ì±ñ�Ç­T¾»{ëÉ.ø�Ðv^¼ê•¥'¦ÇÕa2út œÕähC®jP0"éÛÙþ`:ì<9¯Å¨;A(\‘�½ŸŸá^OŠW†T–6*èC+Æ”+J,¼N•hÙ+>禿ßo­%AgsöË8®q�1rG¡ïúÔõè§usäåâúQLAEPZQªO÷EfÖ”_ê“ýÑ@¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(:_õ¯þñ¦SåÿZÿïeQEQEQEQEKoþ½i×_ë¿ m¿úõ§]®ü( (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ˜Ç«½PÔÃþ=[ýꆊ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¥·ÿ^µKoþ½hn¿×~ Muþ»ð¨hªÙ#EºÇ÷?­_¨/ ûM”ðwt*>¸©’¼Z4£%‘“èÑæôR�T�FàŠJò�· (¢€ (¢€ ô“£ZçþyŠóõRÌFI8½"Ò³ÚCüó@¿�®¬*Õ³ÅΤ¹#2j(¢»Ož šßï·û¦¡©­þûºh(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶¿ñä~‡ùÕJ¶¿ñä~‡ùÐJ(¢€ l‘¤±´r(ta‚¬2 :Š;õç… •‹ZÊa'øXnãYçÂwÙâkr=w7øWcEbèAô;á™â`­ÍS™¶ð� ÕÎG÷cÔÿ…nÛéö–Šñ¡Å·ŸÏ­I%ͼGOFp)c¸†cˆ¦�ÿÝ`kHÑPWHʶ*½o�èIEU¡\÷ˆufƒýÑ™uÒºp3^us;\ÝK3uv-^†]AT¨å-‘ц‚”®úQEU½?P—N¹Ær§ï§fRŠ™EM8Ëa4š³= ’âš3”q�jJÂð¼æK !'>[ñô?ý|Öã2¢–f  d’p|½z^Σ‡cËœydâg_è:n¢Åç¶aêèv“õÇ_Ƴ×ÁZR¶I¸aýÒã ©.üOLRÚ#1ÄNÑT×Åsîù­£#Ð+ªž˦Ÿ3žyM¯žTÕý‚ËN´ÓãÙkn‘Ô�Éúž¦­V]†½k|Â3˜¥=�èkR¹*Âp•ª-MU%Ir%dQEfEPEPSEþª_ ¨jh¿ÕKô Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Et…í&EûÌŒ×-1§gsÌ(­}Kk¶™ýS�GðŸJȯ*QqvgÚÑ«°SŽÌ(¢´4}*mZõaŒæGì£üi$Û²*sŒ"å'¢:Ý4K`ÝpOàXšÒ¤XÖ% Â ڣРZõb¬’>.¬ùêJ}ÛaES3 (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Òÿ­÷�2Ÿ/ú×ÿxÓ(¢Š(¢Š(¢Š(¢Š([õëNºÿ]øSmÿ×­:ëýwá@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQETÃþ=[ýꆦñêßïP4QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE-¿úõ¨ª[õë@ uþ»ð¨jk¯õß…C@Q@g‰4Ãkvn£_ÜÌrqü-ßóëXuésCÄ-¨`ƒ\~§áÛ‹Fi-ƒM^Ì¿Qßë\5è´ù£±ôY~aER¨ì×âbQGJ+˜öBŠÉÀ­½/×l²\††¸<3~ª£'deZ½:1æ›°ï i†æè]È¿¹ˆü¹þ&ÿëWeL†íáX¢@ˆ£ÔúôiÓP��“Åâ^"§;Û QE¡Ê5¿ßo÷MCS[ýöÿtÐ4QEQEQEQEQEQEQEmãÈýóª•mãÈýó  ”QEQEAww •»M3aGAÜŸA\…þ»wxÅUÌ1vD<Ÿ©¦ëz�¾¿`§÷1’¨?™¬Ú÷°x(Â*sW‘ßFŠŠ¼· PH9w¤¢½¤×ÓüAshÁ'c4=Ø} uÖ÷]@³BÁ‘ºóªÙðî m¯E»ŸÝLq�Fì¥y˜ÜeR Í~'-z)®hîv 7)£æî¥‘† œôšã¼C§µµé¸Aû©ŽsèÝÇõ®|²¢ŒÜS<,’“]Ìj(¢½³¸(¢Šé|(ñ�´¡qæ6Ò¹?ãUüE©´×Î6ÄQŸŸÄßýjņi-æIbb®‡ ŠIÉ#;}æ$Ÿ­r,*úìõÿ3K÷œìmQ]fÁ]—‡õ&½¶0ÊÙš.çø—Ö¸ÚÖðã”ÖGGVòÏô®Lu%R‹ou©�x)Aù¥Q_6y¡EPEPSEþª_ ¨jh¿ÕKô Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ ’4š6ŽDŒ0U†A¬+� ZHÅ –Hsü?x�oÑS(F[£j8Š´‡+ì>·Vk™$Š¡ƺm*ÖHš(#TAŽzŽ­Yõ”iÆ;!ÖÅV­üI\¬ÿ}¾´”¯÷ÛëIV`QEQE¥ú¤ÿtVmiEþ©?Ýê(¢€ (¢€ (¢€ (¢€2/¼WáÍ.íí5 J´¹L†âò8Ýr22¤‚89ªßð�ø?þ†½ÿ0ÿñUàÞ9Ñ-|GûH"øÈ-®ž�ÄØly x8>•è?ðÏ ÿžÚ·þ/ÿ@•§ë:^®¬Ún¥gz©¶�dÇýòM^¯™~!ü.›áœÞ'ðαx"†eFó b'£PRx#Ç\ñîÞñ#ø·Á^µ*ªÏqó(9úÐÚ*½åýž�žúî XGY'�"þf©Ùx—AÔ¥XkzmÔ„à$H䟠4©EPEfIâ= ï°Ë­iÉy�¿gk¤gÓnsW®. ´�繚8aA–’F ª=Éé@ÑY¶!ÑuYLZv±§ÞH:¥½ÊHGà¤Ö•QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEgKþµÿÞ4Ê|¿ë_ýãL Š( Š( Š( Š(  mÿ×­:ëýwáM·ÿ^´ë¯õß…AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPSøõo÷ª˜Ç«½@ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQET¶ÿëÖ¢©mÿ×­-×úï¡©®¿×~ QEQEV¸Ó¬îŽg¶�ÛûØçóªŸðŽéyÏÙ¿1¿Æµ(©p‹ÝÇV Ñ“_6V·ÓìíN`¶�ûÁyüêÍSI-ˆ”¥'y;…QL�¢Š(©­þûºjšßï·û¦€!¢Š(¢Š(¢Š(¢ª_ê6út>díÉû¨:·Ò¹›Ÿ^HÄ[¢B½²7ðý+9ÕŒ7:ðø*ÕÕà´îÎÆŠá“Äš¢¶LêãÐÆ¿ÐVƟ∦qâ˜ô‘~ïãéQD$ìmW+ÄS\Ö¿¡ÐÑ@ Œƒ�h­Ï8(¢Š*ÚÿÇ‘úçU*ÚÿÇ‘úç@(¢Š* ÙL6«õÅOP^Äf±¸ˆuhØ®*¡neqÇusÏ(¢ŠúÓ× (¢€ UbŒN9’Žý@÷4="7ó#Wþð›<ÜÂÑL�‘†5¥Ý¤È±ÛÝC)U oåVkä�ã-3RÖ,á5}=tÛß%º²‡�’1úU é|UlqtêØúwÖ¹ªú\%WRŠ“zž¥óÂïp¢Š+ Ô)ÈÍ-#+Bû]H8ÐŒ�Ò¸±X¥‡©?…Ý?]-ú›R§íKqh£9¢»”•ÖÆM5£ Ôðë­B=C#YD�[^·iu'¸#å‰:ûž?–kÊ̱°„}Œ]äÿÔ©Rý̧-’üNÆŠ(¯ñŠ( Š( ¦‹ýT¿APÔѪ—è((¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ µgÕÿ «V¬ú¿á@Ÿï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEQEóg‹u;=öš�QÔ'ZA$ ,¬ <…ãšõ¿ø\>ÿ¡Žûó/ÿ^Gã &Ë\ý¦LÔaóìî–=컇�§ª�GNƽSþ—ÃÏú¿òvãÿŽPšü^ø­£ø¯CO ølÍ{çÎ�,þS*œT€Ä–ÇnÝóÇ®|1ðõφ>i:eâí»TifOî3±}¿Q�? ›Aøsá ]‹­'C·†å~ìÎZW_÷K’Gá]E|‹à;Ä,—Sð~�r,ìï&:…ÑÏ&@\¹-Ó¿5î'†4ï‚þ ×µ5½šøybf¨@Π…QŽ™f½qŸ³|joü[!rµºƒìLÙþB»Žžgü*}Ofvù�oúy«ýq@mào^üZžëž0Ô®šÙå1ÁL¾:íÈ!PtNzc›~>ø@¾ Óм¨_A6žD’ÆÒe•sË#ÁÎF~‡Òþy_ð©ô'|¹3�ïy¯Ÿ×5¿âÿ+þ­{ÏÇ•ý�q¿>ž[f€1¼ãxüMðò/ß2Ç%¼n·ÅG ÑŒ³~# ŽÙÅy†t ïŽ~'Ôuÿ^\Á¢ÚIå[ÛÂÃ#<„\ä 8É$~ ðÙ§|q³;s>?ïÊîý+µýž<¿øVÓlûßÚ2ïúìOéŠç¼eðÈü9ÒæñOƒo®Ð@†;ÛIßzË |­Ð �œ�sê"¶¿gù'Ú‡ý…dÿÑQW}ãï/þ߉<ß¹ý™qùùm�×ÀþÎòOµû Éÿ¢¢ 5ݯÝü^ñf�áÙ7zÅäöÒ\#ɈHYÎGN3×°äŠöo‡? í~^Ï|š¤×·7y2nˆ"AÈ'·­pß £Wý£ÉdŽ“ØqÐçð©Ó⟎|u«\ÚøD�,`l5ÝбؒÄ*çû¸&ªø·Â?/¼%ªÞxŸÅ¶¢ÆÞÙç{;EÇ™´nÚÛQF8îOã@÷Á­~ûÄ?,î5š{˜${s+œ³…?)'¹Á=ñ^?ai­jÿ¼S¡è÷Í`5©ã»ºAóÇɹ¶óÁ$ø×¥þÏ¿òL‡ý~Ëÿ²×1ðàÆFxÇýË¿ýXñ·À¯éÞ ¿Ô4yo#¾±·k�ÓK¼L`F:�1Žk�øoá½[â¶›^$Ö/Ãú6 †ß ,‡žO?t2rp@æ½çÆŸò"ø‡þÁ—?ú)«Ï?gù'—ÿö“ÿEE@/Å�†ÖáÓ ÿ‘ÿö ¶ÿÑK@´QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEgKþµÿÞ4ÊšH¤21pI¦ù2pÐtTžLŸÜ4y2pÐtTžLŸÜ4y2pÐtTžLŸÜ4y2pÐtTžLŸÜ4y2pÐÛÿ¯Zu×úïˆ"u™IR:â7irªHÅV¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#©‡üz·ûÔß&Oî�FÿfeÚs»¥W¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#¢¤òdþá£É“û†€#©mÿ×­'“'÷ >�fRT�@ uþ»ð¨j=GS±¶œ‰n¢V•Ý’?T—^Ó°.×>êGó.qZ\ÕP«%uoFhÑI [˜÷ÀË*yúT¾LŸÜ5Fm4ìÈè©<™?¸hòdþá Dtב"Bò0TQ’Ìp:oôxi~HÐe˜öÁjÚ¼ÚœÄd¤ ~Hÿ©÷¬ªÕT×™ÙƒÁÏ-4Kvo^xªÚ&+mLGñµƳÅwäü±À£ýÒ­aQ\R¯7Ôú yn Ü·õ:|[r§÷Öñ8ÿ`•?Ö·,5»=@„G1Êå›ðOÓÖ¸* ä¨â&·ÔŠÙ] ‹Ý\¯Èôú+�ðö´÷L¶W-º_ùfçø½�½tÞLŸÜ5Û ©«£ç1'B|“#©­þûºi¾LŸÜ5$º³eHùMY‰^Гɓû†�&O“É“û†�&O¸�-­äžC„E,jÇ“'÷ aø«Ì‡FÁR’*ŸÔÿJ™Ë–-›aéûZ±‡vr·’ßÝ<òž[ ì£ÐUz(¯)»»³ìã£�QEu>ÔÙóc+g1éÜWM^y¤ÈÑêÖŒ½Lª¿™Çõ¯Gòdþá®ü<œ£gÐù|ÖŠ§[š=Hè©<™?¸hòdþᮃÌ#«kÿGè�AäÉýÃVUZÁ݃ÅR¢¤òdþá¬ûýRÓM;n$ÄŸóÍyoË·ãI´•Ùp„¦ù`®Ë•Vúþ >2vë÷Tuo¥c?‹¡ òZHG©`+ž½¿’þå§”òzÊ=+\,¨T©iÎÈì†]_yÆÈmĉ-Ì’F›˜°\çe½Ë›ƒ"žœ¥]†î9 ÚÞ†¾š#±åàsü&&¤©_•§e~«ºÿ"z(£¥j{¡U¯&ÙÁ÷›ùQ5âFC¹½ºV{»;c’k•VGÉçÙí*t¥‡ÃÊòz6¶K¯ÏòY‘ƒ)!‡ ƒÈ®ËÃ>&–YÒÂý÷–â)O\ú_­q”ªÅ2’‚;W ZQ©3âpxʘJŠp~«¹è¾*¼òlRÙ~ôÇ'Øž+’VσZþ!•î?³î`Kj²©æ±k£˜UÂVij»µà°°«„„ã£zÜ–Š‹ñ?�^~µê<ú—.�wù_�kVúµý|‡3g�ù×Oqcý½¥A{Ú®Öã·ùõ®Z»_ G#é.B’<ã�ÈW�Sž—K¶{e�›—8ª«áëmÂÁsï“Yª5#¤%¡œszM^pÔ᬴û�Ba“ýæ?u~¦»­:Â=:Ñ`�“Õ›ûÇÖ®%©‰GÅŒOòdþá­)QPשçã1óÄû¶´{ÑRy2pÑäÉýÃ[tTžLŸÜ4y2pÐtTžLŸÜ4y2pÐu4_ê¥ú o“'÷ In#�9#НEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GEIäÉýÃG“'÷ GV¬ú¿áPù2pÕ‹TdݹHÎ(£ýöúÒT­ …�ÈzÒy2pÐtTžLŸÜ4y2pÐtTžLŸÜ4y2pÐu¥ú¤ÿtU&Oî½"5¨€EPEPEPEPÎú×ü�m§ývƒÿIÅ}EQE࿳wü}x»ýûoç5{Š4|Oá�GE�¶%Ü&0øÎÆê­ø0ð­z(çøþóá,÷^ñ†�t¶ÑÊd‚H”1LõÆH ‡¨ ðs×<\ñïÅåñ¶˜|+àÝ>úyµ#–V� ËžUyîN03õñ¥éú¬"FÆÚò râ�Á�¦iÚ&“¤f™edï kt�?] P3àOEῇIáËà²Iu†ûiášA†û.>Ù¯#ð¿ˆo¾ø›Qðÿˆ¬î'Ñî¤ó`¸…zã�"‚@ ŒÈ ~?FN%6òVb§c0È Ž3íšño |SµÔïµ/üN¶Ó­n`—¬ö¿ºÈÈemÛ€==?L€QñÇÄÿøO¼= øBÊí¡ïq¨ÞΛ(#ØO]¸çƒ9ãsöqR>ß“ßT“÷ê*©ñ âƒ4¯j…d°–ëQŒÀ°éÑ«pÌÅF:d×$Wcð�ÃwøwaiyŠòr×3Fà ž÷ >ù >øgÿ'ãO÷.ÿô¦:öéÒkÕ´È\$·–s[£€ºõ­:(æ¿…_,~Ûê~ñE•ݤ¢ìͽbÜU¶ª•a×øAg95ÐxÇâuÇ�t-G@ð>‘{v�5íä‘íXâ,g©àö“Dzj:�«²¶§¤Ø^²ð¦æÙ$#鸳gei§Û‹{+Xm¡^‘ÃE€â€<[ö|ñn—ý…ÿ³<‹ªyòΩ°ídÂó»§àj¯Ãù8Ïÿ¹wÿ£ã¯j´Ðtk Ǽ³Òl-îŸ;ç†ÙÛ=rÀdÖ…aøÓþD_ÿØ2çÿE5yçìãÿ$òÿþ²訫×è !ý£?ä�ÙØR?ý-z‚¿äCðïýƒ-¿ôRÖíQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEŸ#¸•Àvê{Ó|Çþû~t²ÿ­÷�2€æ?÷Ûó£Ìï·çM¢€æ?÷Ûó£Ìï·çM¢€æ?÷Ûó£Ìï·çM¢€æ?÷Ûó£Ìï·çM¢€&�ØÌ ±#ëN¹và1�2ßýzÓ®¿×~˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ�1ÿ¾ß�6Šw˜ÿßoÎ¥ßfc¸çw\Ô0ÿ�Vÿz€#óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Ñ@óûíùÑæ?÷Ûó¦Õ;ýNÛN‹|íóº‹Õ©6’»*”åËv^óûíùÑæ?÷Ûó®.ëÅ7²±*B½¸Ü^?J¦5ÝLý­³ôáXý]dQEsž±5µÔör‰mæxœwSŠê´ï,¡c½-ôóùO×Ò¸ú+HT”69qJX…ï­{õ=AfgPË!*FA Á¥óûíù× ë-e2ÛÌÙ¶sŽ€úý+µ®úuÕÑó¼,°Óå{tg5âÍBM±Ø«¶o�g¯ ÿ>ÕÊÖ–¿!“[¹'øHQøYµÁV\ÓgÓ`i*xx¥Õ_ï (¢³:Š( #´r+£u9u½N¿kën7œ²üÃ=CúלWaá9 i²¡þN?+§ +JÇ“›ÒR¢§Õ?Ìè|Çþû~u,ÅÛ,OÊ{Öf¡©[é°ï™¾c÷Pujån¼M;0…þ·Œ'\}ºjVŒ4g�†ÀÖÄkeÝ�ǘÿßoÎ�1ÿ¾ß�y£^\¹Ë\LÇÔ¹©àÕ¯íÈ1ÝI�F;‡äk%Š]Žç’ÎÚI\ôO1ÿ¾ß�cÿ}¿:ç4ÏG;,Wб9àH>éúúWC]œf®�.¾¥ rÔVæ?÷Ûó¬�Ä÷4œ–1°“ôàþ„Ö­#(u*À#â‰Gš-F£§R3]æ4Vž±¤É¦Ükv?#ú{z̯.QqvgÙÓ©±SƒÑ…Rª–`ª bpïH²þ‰O¬[þO¦9¯AóûíùÖ&�¤�>4Ãý"AÈþèô­šôhAÆ:Ÿ+™b#Z·»²Ðw˜ÿßoÎ�1ÿ¾ß�6ŠØóÇy�ýöüêÒ±û99Áç5N­¯üy¡þtÎëúÜš|B$?h�g9ûƒÖ¸‡v‘Ë»f9$œ’jÞ«pnµK‰IÈÞBý©×›V£œ�®Àá£B’î÷ d§9ö4úk®äeõ¨¦ÒšlÛJ„ã Úvõ±—E(¯´?�¶—î±CH]›ï1?SIE;—í'ËËw`¢Š)ø¢y¥H£RÎì@îM:ÞÚ{¹„Vñ<²áA“]χ<0t÷—»MÆ>D„÷ÏsYU­jïs»—ÕÅÔJ+ÝêûÁ$×ôÆ=©L±³@‡ýÜý+“¯N 0 €AàƒÞ¹MWÃ2#´Ö#zLYå~ž¢¾kIÉó£ö,« pT&ì–ßäs”Sä†X[l±ºFR*K{+›¦ ùî�rYÞǼ繛Є̓À½z‘lú~™ ˆ`7>sɬÍÃâÍÅÅÑWœ}Õ„ÿ[ÕÛ‡¤ãï3ç3_õ¯þñ¦PEPEPEPEP¶ÿëÖ�uþ»ð¦Ûÿ¯Zu×úï€ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©‡üz·ûÕ L?ãÕ¿Þ h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š­x–r\?;GÔöç÷W2Þ\<ó6çcù{ è<]pwÛÛÆ „~ƒú×3\‰·.^ÇÒåXu ^Ñîÿ ¢Š+œõ‚Š( Š( Š( »Ý èÝ鳺|Œ~ŸýlW]‡„óý›7§œ�®Œ3´ìyY¼¡ÍÙ˜^ ŒÅ­\g£Ãñ³+«ñU‰x£½A’Ÿ#ý;Ïù×)YÖ�,ÙÓ€ªªaâ×M>ࢊ+3°(¢Š+ªÐ&K âî_»¼�=x~µËÇK"ƃ,Ä(¤Öþ¾¢ÇO²Ó�ð »ûŸÿY5µ'Ëyö81©Up¡üÏðF-åÜ··/<Í–nÝ€ôV-ßVvÆ**Ë`¢Š((+«ðΪÒ°ÎÙeˆŸOJå*[YÚÖê)׬l®œÜ%s›‡Ué8=úzž•GJ@C(#¡Ìø—V`MŒ ��Þ°þUê="äöGÉС*Õ8ŒÖü@²´´èxyd þµÍQEys››»>»‡…r@)ñK$2 "vG^Œ§S(¨6jú3¬Ñ¼EçºÛ^�$<,�Cï]³Eeå‘Qv8¯3«2ÝOtTÏ+HT`n=z¹rúÅOe7cÂÇeÑOÚSÑuG_/‰4øÎ¤“ýÅÿScñ=ƒœ0™=ÙÀšã¨¯¡þÍ£kjq}Z¢[ÝÛݦè%Y|GÔVŠÿÇ‘úç^[ ÒA(’'dqЩ®ãB×SQ³{i°·(¹öqê?¸1X R\ÑÕõpî ëc…ºCÜÈÝUØΡ­_,CY˜ÅßÿÞÇ5•_9Vœ©Ë–HúÜ=ER”fº ¢Š+3b�ÔE_x)ý W­b¡†È5V[9ˆäzúl®µJÔškáê~WÄü3R�w‰Á«©jâ·O­»§ýhS¢žÐʧ˜Ûò¥JÝ#oʽ3⾫_›—‘ßÑ‘ÑRýžlãËoʧ†Å‰Ì¼AT¡'ÐéÃe8ÌDù!Múµd¾fç‚£#Tyˆ�ùŠïk�ð¬`ê>@ Ð=ÉÿëW_^.*¤gU¸ì´?B¥€Ž”pëtµõz…Q\å…Q@Q@Q@Q@Q@"ÖÑE­»m•ÆY‡UÞõÇ’I$œ“Þ¯ënϬÝê€â¨W›VnRw>¿B4¨ÆÛ½XVÿ‡õ‰ �-'rÐ9Ú„ÿíøV�ATBn.èÚ½Öƒ„�O©¢ÿU/ÐUhX¼1³ueþUf/õRýz§Åµgb(¢�Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@`ëºëX·Ù­±çã,Ç�ŸýzÞ¯<Õ‹^ï_5¿,ñúV‰¸ÇCÒË0ð­Uóê�WP/¿í“çýó�Ê·ô=~K‰–Òð‚í÷$é“èk”©mK ¸J}ðë·¹®8T”e{žî# J­7’=*­Yõªի>¯øW¦|�Yþû}i)_ï·Ö’€ (¢€ (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@Pzo˜ŸÞy‰ýáU(  ~bxQæ'÷…T¢€-ù‰ýáG˜ŸÞRŠ·æ'÷…bxUJ(à`Ýij(>éúÔ´QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÓ)òÿ­÷�2€ (¢€ (¢€ (¢€ (¢€%·ÿ^´ë¯õß…6ßýzÓ®¿×~Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@L?ãÕ¿Þ¨jaÿ­þõCEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPUou]>=×'¢ŽXýGªê)¦Ù™H #|±¯©ÿ à®.%º™¦™Ë»u&°­[“E¹é`r÷ˆ÷ç¤2¦§z³G"ª�'’súÖuW¤äîϦ§N4à¡�QE‹ (¢€ )H*H`AA¤ Š( »Ý ÔÚi0« ;üì>¿ýlW; èÍ{2ÜN¸¶C‘Ÿã>ŸJí+³ M¯yžo‰Œ­F=7è²ÆÑº†F ÷Äk$ºt†HÁ{bxoîûñ®æ²üC1‡EŸoðŸ™çôÍkZ Q»èqeøŠ”«(Çi;%Q^qõ�EPÐÕ«Ûé/¼–”åã�a?ÞäóúÕZ)ÝÚĸ&Ôžè(¢ŠEQ@S£(%C %7 ØëŽô žˆ’}ŸLYþYÂþ¼öyYžG9f9'Ü×a>±g¥\¤m“ÊoݸÁéú×ßz½z©<”™~Lð²ºr…is«1´QEy¼QEäëM§'Zí˯õ¨[¹†"ÞÊWEWÜžT�O%´é4G‡ ÔtRi5f—™î%•º»üÍ@SÒŸGJäÄàhâb”ÖÛ>¦´«J�ñ uS†`¡5ÜDƒïdú ¡#™˜õ&›^*Ê))k'câñ<{‰|Ñ¡N+³w†…ƒy&ýË€=)ï|ç08äc½T¢½ZQT¡É òÓÏ3¹9Uw—ŸåÛÑhHóË' ç�*X¯dA†ÇëU¨«S’w¹…,ËJ§µ…GÍæï÷ßsZ)Ä©»iZvKp)U \t§VÂâëIªµ-ËüÏØðÕ*1ç\Ó¶­÷ôÊT�Gq]6‡®<’­¥Ûn-ÂHzçÐ×3J VÈ"»*aiÊ—³µ’ÛÈÆ¬}­ù·=&ŠŠÖS=¤2ž®Šß˜©kæš³³<–¬QE (¢€ (¢€ (¢€ (¢€8ߨ´7ÿjUýÔØÉôaXUésÁÌ- Ȩ5Í]xI·“ip»OðËÛñá\U¨JüÑ>ƒ™STÕ:®ÍÍ[Ó,ŸP¾ŽnrçÑ{Ö´>¹f}ÄH¿ìe�ô®ŽÃN·Ó¡òà^OÞcÕ¾µ4ðòoÞØÛ™Ò„¤ï"Ø*h¿ÕKô Mú©~‚»Ï™!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®w_Ðäº�ÝÚ®éùÓ×ÜWEEDবͰõçB|ð<ØÚ\‡Ømåý݇5ÐhZ ©:]ݦÀœ¤g©>§Òºš+(a£vÎúùµJ°pŠµÂ­Yõªի>¯øWAåŸï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEPz(= R¢Š(¢Šd³EšD�ñ;`P4›Ñ¢«ÁgrÛ`¹ŠFþê¸'ò«“O`”\]¤¬QE1 û§ëRÔP}Óõ©h¢Š(¢Š(¢¸/†ž7Ô¼dÚðÔ`´‹û>óìñ}�w/<¶æ<ñÛÞÐEPE^þö 7N¹¿ºb¶öÑ<Ò°!TN^X¢³¥mgI´Ôeýôx|q"ðÃük™ŸÂW Çȸ�×ý°TÿZìî¿×~�®êOÓÉŒâYÄöõ5ÑVœæ’<œ&'*tÞýÅ]ÚµœæxÙ×ïl9ǵAA$œ“’h¯9ùWÒ×rÌZ�ìòî¦P: ç•ni¾)pâ;ðOjŒõá\Õq©(½…l%ÊÒ�ùžœŽ®�у+ ‚W1â�J6QaÜÁƒ;z{T°mm® ”åQH³ê;ŸzÁ‘ÚYG$³I=ÍtU¯Í—SÌÁåΞ!¹í¼ÆÑEÈ{�EPZ:²Ýj±Dëº2pöÚk:ºÏ X¢{Ù ƒjgû½Ïùô­(ÇšixêÊ• >¯D`êšdºeÉFÆ~ãö#üj�zTöñ]Bbž0èzƒ\õÏ„Ý�”ëŒgd¿â+Z˜v�âqá3XJ<µ´}ú3–¢´n4-BÚ'–H–ƒ%ƒ¯Oγ«�ÅÇtz�© ŠðiúQHÐ)ì22)”ä=«ÑËêS|Øz®ÑŸ^ϡ͈Œ´©ÐÚ)Ì„éM®lN®|µù3ZucQ^!EW>å…=FLö7ÛÇq,L±É÷IïQ×ÒäøíêoÑf/®H;…Q_BpTrÎ�Œ±ç°¥%vgV­:0s©$’êÇnÃÚœFF*‡ÛF~áüêżÂy4ûÌpׇG^‹“ÄAò¶Ý÷µÿBifyf2j–²rÚÎêþ—Jÿ#1”«=AÅ%u"ðר-Mì30¥q€{çòË×\g«ÁÝ’æ7„ÄJ“Û§šèQEQÄz‰áÝ%ìm¯ -3H�¿zrïÇNµ¸šuŒm¹,íÕ½V%Ò Ñ¡6z¤rü¥c³Æ çúÕµ¹�ÛjÏ@à׉R£rzŸ¤àð”áF-A'e}:Øào-ÚÒòXcc=ÇoÒ ®³Ä¶–Íl.^AËÂÿ·í\˜ ô¯ ‹§Z)_Þì}&ç{:4idXÐe˜€îi¹Åt~´µ‘šäÈtàGýÏz¼F.�«×¢ÛŒí¡ÑÛÅä[Eþ ù T”Q_4ÝÝÙäQHŠ( Š( Š( Š( Š( Š( ¦‹ýT¿APÔѪ—è((¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ µgÕÿ «V¬ú¿á@Ÿï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEPz(= R¢Š(¯7Õµ)u+ו˜ù`‘öQ^‘^i©XI§^É© Q¿¼½�râ¯eØörei+ïÓõ*«20eb¬AW¡h7ï¨éi$‡2¡(çÔŽÿ‘ç€p95è>±{ )RQ¶IÈÊ{g�¬ð׿ò:ó…b›Þú´QEw6XƒîŸ­KQA÷OÖ¥ ©jÚ­ž‡¤Ýjš„Â+KhÌ’9ì§©=îM]¯+ý ¥ž?†Eb'd—±,¸þîóÿ @-~#üFñDm¨øOÁvͤn"9/eåã#çAù;d×Uðÿâ*xÆKÝ6ûO}3\ÓÎ.lÜçŒãrçƒÁ¦G\×Iá˜-í¼+¤Ch[¥œ"=£�» U·²ð´2ºº·6 âI¡Äá&{G…ûÉœãyÇa@yðïøÃþ‡ÿf®—á��µ/[k2jPZDl¯M¼fF\®:�Ìyü«šø÷üaÿaCÿ³Rüÿ�ØQ¿•tŸ‹S:{˜î.î¤Û`H |Ê1�qódààV—ÁXþinìU® $ðšõ‹£xçU×.ïÇÃ�X =f+6£pËLþ¥TO9êNÎ3@é¿üO¤ø§Mмuᨴó©H"¶ºµ“(X�ñ0#%sódg¥Vøõ÷<%ÿaAý+™ø‰ŒÏ‰üqâÉô��©(·¶Óƒâ?ž=Å‹rONæºo�_sÂ_öÒ€=ŠŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š*­Ö¥ge=´7 ·/åÂŒyvô�Z¢Š(¢šî‘£<ŒªŠ2YŽVÓVÓoähìõ K‡^« Êä~ÐÊ(ªwz®�`ê—š…­³7ÝY¦T'é“@(¦Ç"KÉ«£ †S�GÖ‡t�äeTQ’Ìp QTí5m6þFŽÏP´¸uê°Ì®Gà \ Š(  éÖ¿ûÆ™O—ýkÿ¼i”QEQEQEQE-¿úõ§]®ü)¶ÿëÖ�uþ»ð (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*aÿ­þõCSøõo÷¨(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9Úùw‘\Ž’®Ôõˆü«Ÿ®¯ÅêL­Ø3Ð…r•æ×V¨Ï­Ëdå†�ÿ­BŠ(¬Žà¢Š(®óÂ3™´è”œ˜�“úÿZàë¶ðZ‘fÌzŽ?ï‘]gïž^l“ÃÝ÷Fý×úï¸ÏHMݼ}–2ß™ÿëWguþ»ð®GÅÖçýà9BQýk§ü6ycKùþG1EWœ}XQE àñIW´›/·ê ÎÌÇÐcüqUg…í§xdt8"��®fªEÍîätQE#@¢ŠUVv  –'æ�z‡öü\ÎqnŽ®GòÙ*„PªP0íU´Û_±iðÛ÷Uù¾§“úÕªô©SP�™ò8ÜL«Ôm½ÁS[ýöÿtÔ55¿ßo÷Mjq™Ú¤fm.é’cl¼î½>¸=oLm:ñНî$9Œú{~ÉŠ‹ÒG¹“ÖŠr¤úêŒÊ(¢¸Ï|*[hÌ×QD½]Â�ÄÔUÑxcLgŸíÒ®#N#Ïñ_®œ\¤’9ñ5£F“›þ™µ¡Ú_ø1J�;ýGzě·jw,2rA®ºŠ÷aŠ©ò=Wg©òPÄT‡ÂÎ>? Þ1ùÚïý+^ÇÖ–Œ_ßÈ:nQøVÍ2iV$•þê)cô5³ KÑ$U\eYGÞ–‡)âýoÉM·Ú\á¥b3·¸Þ¹¨oA‡;[ߥR¹¸{«™n$9y±üj*ö0éÑ�*> EŠ¥‰•X;Åý—µ¿ÌÛ#Š+3/Ýb>†”»·Vcõ5Õíü�eqŒ9u£¯¯üN[¨âw7 ¬Çv‘Ë1É4Ú+Ôr>s4Îkæ )é²_¯p§G#Ã*It!”ŽÄSh¨<”ÚwGªi÷ëZ$rL�–d+"öÏCú׫xVöÂV{hÚâß9 ƒ,>£ú×YáHZ[ï.YÀö'ŠÚ¯%Utj5�½ž†œ«i+-~G�-�ӾĶ™Ÿû¡ 5¡žútÉ-äcÎe�¹Ç¡oðüýý*æu¶¶–vé–úâ¼æižâwšC—s’k,^a5X«6vd|'‡u½µwÌ£Óe1÷7—ro¸™ä>ç�ôª (¯»î~‹¨«% ÷–IUäf †9ÇÒ™E $¶ ±cy%�äw“•<�ïâ«ÑM;;¡J*IÅìÏMGY]NU€ ûSª½‚²iÖªßxD€þB¬WªµGÄMZM ¢Š)’QEQEQEQEQEQE4_ê¥ú †¦‹ýT¿A@ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEU«>¯øUZµgÕÿ ¬ÿ}¾´”¯÷ÛëI@Q@Q@iEþ©?Ý›ZQªO÷E:Š( Š( Š( ƒÐÑAèh•Q@CsiowˈREìtúTÔPÕÆ›‹º)[i}¤žd6¨®:1ä�¦zUÚ(¤’[s”ÝäîQE2K}Óõ©j(>éúÔ´VG‰ü;gâ¿^è·Ù\¦7¯T`r¬=ÁÖ½âÚ]‡Æ/X¦‡¦Yi:ÞŸÙmq4�Y°Át8œã¦p+¢øuà-[FÖu/x¢ò;¯jK±„\¤)�vç×åQÇ(5èôP›|%ð®µá†ñ!Ö,¾ÍöËÿ:Þ£ïO›Ÿ”œukœ‡Â_~ø“Wºð…¥Ž¯¤j2™�¼òhÎI–^FHÈ'#g§¶Q@=x�Á?|m-Ž»­YÀ·]"A¦A,j°ÃÉy /Œä ÆKöWñ;ÀZ¯‰.ô�{×q[kzSîˆKÂÈ2ÁäÐðrs^�ExõÔ¿õ« t™´�OIÐÅ%òÊ ÚF ;c�ö~˜®«Ãß“ÿ îü)Ð’{»yÖ[‚¸S,ˆTœzá]½å? t_x~ÇþmF³�CŠ9¶Ý¤êÎå›8ÀnŸ3uµdh^ø™ðØÞi^°Óu½YÌмò„t$ÎYyÀ#Ò½¶Šð¯xâGˆWNñåÕ�Þ±er²A¥[��À€†á˜�ÌYW9=SÅn|@ðß‹|_¡øNS¤D5+kÁ=ô\ XG 7=;^³EQEQEQEQEQEQEQEQEQEQEgëW:�¦—$ÚUŠÞÞBÎy9>‚¼žîëÄ—ü>þ"µ[Sç¯Ùá��U]Üž ç¦sé^Ñ^oãOù)žÿ|ètéQEy§Ššoøþ×Âk4‘iÖè&»œ8ÝÏàTBÆ�øMÒ495¤ÖWÖL%fÜ£¯Rp@ÉãҗÿòZ|A¿ï}˜íüâþ•Ûø“oü"ú¾ÿ»ö)³ôØh?ð×þB«ç‹|Çní�=7sô¬xOÖôEÖ¼B“^ß_æ\¼¬»Tž:’G?ˆ¬ßÿ .Oîý³ôÞ?­z§…vÿÂ#£méöô@W†¼ïüB›ÂÞt’i—‘™­D‡% ÿÙX\ _4Þ-ñý¯„Öi"Ó­ÐMv#8,q»ŸÀ¨…�/Šä°øogßòW?MÒõèðïü–Ÿoûßf;8¿¥'‹|¦éš¿‡Òk+ë& ’³nQש8 dñé]Ÿ…uƒ¯øfÇRp’ljé½IVýA©|I·þ}_ÝûÙúl5Íü(Ýÿ49éçÉ�¦ýtÛÑ\׎­uûϘ¼7#ǨyÊw$¢3³œòOÒ¼Ëþÿ‹ßóûwÿ�éÿÅP°ËþµÿÞ4Ê]31iVqßü׉,äüÄÈnç¿9«[í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TRŠ·¾ÛÐ~To¶ô•T¢­ï¶ô•í½å@Ûÿ¯Zu×úï¦� .»·²4!ñ ¾”FŠ·¾ÛÐ~To¶ô•T¢­ï¶ô•í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TRŠ·¾ÛÐ~To¶ô•T¢­ï¶ô•í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TRŠ·¾ÛÐ~To¶ô•T¢­ï¶ô•í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TRŠ·¾ÛÐ~To¶ô•T¢­ï¶ô•í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TRŠ·¾ÛÐ~To¶ô•T¢­ï¶ô•í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TRŠ·¾ÛÐ~To¶ô•T©‡üz·ûÕ.ûoAùSÃAå�³<ñÞ€(ÑV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨¥o}· ü¨ßmè?*©E[ßmè?*7ÛzÊ€*QV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨¥o}· ü¨ßmè?*©E[ßmè?*7ÛzÊ€*QV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨¥o}· ü¨ßmè?*©E[ßmè?*7ÛzÊ€*QV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨¥o}· ü¨ßmè?*©E[ßmè?*7ÛzÊ€*QV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨^³7šTŠ£/ï}:þ™®½k}· ü«†ñ&ˆ-gk»1›g9eýYÿ äÄÓoÞG·”â”oF]vÿ#ž¢Š+Œú¢Š(“�ɯGÐm •¥´ >p o©äÖ†4Ui–þõqód}ãê}«´� .»·Û†¦×¼Ï�ͱQ›T¡ÓR ¯õß…Q½´ŽúÒKy:0àúƵ¤hCáÀÝô¦o¶ô•tµufxñ“‹R[£Ëo,¦°¸hg\0è{0õ^½Jî×N¾‡Ê¸…]{pACڹ˟Û&Öù”vDÏê?¸§†’~î§ÑáójR�ªèÿ�¥Ug`ª¥˜œ&º˜¼ ~ûPP¿ìDIýkNÒ4­0f$//y$oÃÒ¦8y·®†•³Z^ãæfvƒ¥:ؼ }¢_½þÈô¦ëz ÔW· r£ôqè}ë¤ßmè?*7ÛzÊ»=œyyzÖêûolž¿Ö‡”϶Ҙæ�£qÙ…G^­4v ²hc‘}3Tމ¡Ýö4Ïտƹžôg¯O9…½ø»ùqo+„�ÜôU&ºÝ@6Œ.®À3uÙî}륂 :ÕqÆ;íLf¦ßmè?*ÖžEÝêrbóIÖ�$—âT¢­ï¶ô•í½å]”T©`8g'¦ÓNžêÊÚšRdœWŸêúìúœ¬©˜m¿†5î?Úõ¬ªUTÖ§f‡®²zkU's¥»ð›î-g:•=NüGZ¤<3©ÁHÀõ.(ѵé´ÙU%kSÃ!䯺ÿ…wñ\YOKVGµP§J¦«CF'„÷dÓ]ŽRDZÆÁï$ÿ,Ó…üOzè•U*€ª�W7ÛzʹßøŽ&ÜAhª×’Ž F=~¾•ÙF޼°G…�ÌZƒ­ˆ–‹úÑ5fÇK_ô™€r2#^XþÎÏãµ E½‰+ë$˜ýþµÇK,“JÒJìîÇ,ÌrI§%´² „8õW¦ªßŠEVçÎ…Q@Q@_Ñ´æÕ5Hm€; Ý!”uÿÆ«Gm,‡„ zž+ ðìË¥jp¹ù‘ÎÉsÜðëNTæàÜOw*É1ªŠs� ·¿_%êw¨‹jˆ¡U@Â�V÷ÛzÊ�öÞƒò¯Ÿ>á+zî±n±×hþb¸ôýV[EÒnË(#ÊaŒwÇæƒ\˜ªr²ŸM�¡É¦½œ£æQEqžÐQE\Ó-¡¼Ô"‚wd�ÎÒËÔqúÕÓ§*’å‚»"¥HÓ‹œ¶E:ÔÑ4§Ô.Õ™OÙã9v=µtÖþÒbpÒË<Øþp?AŸÖ·b[(cXâ�€ª¸º)á�ï#ÆÅfÐäq£»êW¢­ï¶ô•í½å]‡€T¢­ï¶ô•í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TRŠ·¾ÛÐ~To¶ô•T¢­ï¶ô•í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TR¦‹ýT¿ARï¶ô•=Z­´ wâ€(ÑV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨¥o}· ü¨ßmè?*©E[ßmè?*7ÛzÊ€*QV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨¥o}· ü¨ßmè?*©E[ßmè?*7ÛzÊ€*QV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨¥o}· ü¨ßmè?*©E[ßmè?*7ÛzÊ€*QV÷ÛzÊ�öÞƒò  ”U½öÞƒò£}· ü¨¥Z³êÿ….ûoAùT‘4G>XüPûíõ¤«…í²r~”›í½å@(«{í½åFûoAùPJ*ÞûoAùQ¾ÛÐ~TR´¢ÿTŸîŠƒ}· üªÂà¨ÛÓPÑEQEQEPz(  TTø‡Ûó£û~t>!öüèÄ>ß�AEOˆ}¿:1·ç@QSâoÎŒCíùÐÁ÷OÖ¥¦ @Δê(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+Íüiÿ%3Âï�ý½"«O§Y\ÜÅs=�¼·ÿª–H•™?Ý$d~f°tßiÚ§ˆ¯4;t¸v�Ì…Ð;X)ÁÏ©«z¹­;IoøMouuÓ’ÊnmƒmP×._sHvöàry4Ìø¡eð—Ä+_yR>›t‚¶ŒgiÆÞ%#פñ�4ÍOA—IÐf{ëûñäªE ªzç u÷¯E’4–6ŽDWFea�GÒªÚim„†K=:ÒÝÏV†B(œ�Áì>ÿÂ8Jý Ûäœñçnß×ÓwJÅðwŽtÝ#BM_™ìo¬3,±±Ü ñŒÐq�jôš§w¤é·ò,—š}¥Ë¯Fšr?(€ðç™ãˆ“x�b‘4Ë(ü›V�cyÁßL}²(ñBËá/ˆV¾*ò¤}6é7mÎÓ�¼þJG® zLq¤1¬q"¢(ªŒ=…F’ÆÑÈŠèà ¬2úP�x¿Çšf§ Ë¤è3=õýøòU"�†Õ=s�:ŒŒ{×]áMè±ÓŸlI™1ýö%›õ$UÛM#M°�Ég§Z[¹êШOâ\ Š(  éÖ¿ûÆ™O—ýkÿ¼i”QEQEQEQE-¿úõ§]®ü)¶ÿëÖ�uþ»ð (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*aÿ­þõCSøõo÷¨(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ *).­á8’x�ú3�KÄ3ªš7ÿu�¥tW,­{P@ ‚2j(¦I…}á‹[†/nÆ=€Êþ]«"O j~C�PØþuÚQXÊ„%©ßK2ÄSV½ýN2/ _¹ùÚ(Ç»gùV͇†í-I)3È:nQøVÕF„#­…W1ÄUVnËÈ(Ú°–yV8ÇVc�U¯¯b°´{‰zîǰ®ÿP¸Ô'2ÌÜ ŽŠ=¨«YCN£Á`e‰wzEu÷‹4ñ1òD³ïÀýyªñø²Í› È=Fõ®>ŠåúÌÏee8kZÏï=ÒþÖù7[Ì¯Ž£¡…Y¯3Ši •e‰Ùy vú&®58 É�qù€î=EtR®§£Üòñ¹s ¹àïÈÕ¢Š+ òŠ( Š( Š©6©cnÛdºˆ0êd�ʈ5;† ÔLÇ Ý‚SÍÚæžÆ¥¹¹]½ tQEQ™Ëø²ìƒ šœ<Ç÷ì?­sµâ€F±ÏCãõ¬Zók;ÍŸ_—ÁG uÔ(¢ŠÉ+莰®¯ÂweâšÑŽv|éô=ϽrÁ=jî™|úeÉ�9*T†=²ô¯[–bî§Ëeæy¸ê”ªÑtÓ»èwÎëm#œ*‚Iô¼—P¼}Bþk© Ì��=aùWkyâ8.´{ÈÊ434,êG­pö©æ\(=&½l&p“SVgæyý:µqp‹NoÕÛð-ÚÚ„Üe�@{Uª(¯f1QVGØà°Tpt•*JËóóaMtYk ŠuΙÂ3‹Œ•Ó2® 0>:©èjÕº@öížÃ5­¤xjÛXÐ’mí Àf]ã�Ã=Åyø‰F‹»Øüç5ÈåOéa¶k™/�šÿ#”¢º)üªÄÇËòfо?ž)‘x;W‘°ÑÅõyôÍeíéÚüÈñÞ[ŒO—Ù¿¸À«v–åØHÃå=êÓéMgpÑ\ƒæ)ävÿëÔÕÙJ�ýæ}NMÃsŒÕ|_MTwûÿÈ)Ñ©yWï¦Ö߇tÖ¸ºR/îb9\ÿõ«ZÕU(9³íg%Ý�}Q_(y% iKh÷ u۟ȃ\\ýkÒdE–6�ÆU�R=�yýõ¤–7oƒîž¨ìkÔÀÆ�jr¡Q_©ß‚ªàýשL‚;RT´VSÈ"åîÎËÒÿª=•�vÖ#“W´´-ªZÿžª#š©]†lç7®0ˆ §¹ï]�ÁÑÀÑ”–­­ÙÅŠÅJqn[UQ^!âQ@Q@Q@Q@Q@Q@Q@Q@Mú©~‚¡©¢ÿU/ÐP4QEQEQEQEQEQEQEQEQEQEQEQEQEQEjÏ«þV­Yõ€+?ßo­%+ýöúÒPEPEPZQªO÷EfÖ”_ê“ýÑ@¢Š(¢Š(¢Š( ô4Pz¥EPEPEPEPˆ>éúÔµtýjZ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÎ—ýkÿ¼i”ùÖ¿ûÆ™@Q@Q@Q@Q@Ûÿ¯Zu×úï›oþ½i×_ë¿ ‚Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦ñêßïT50ÿ�Vÿz€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(½íì6Í<í…:±ôÆjõåóW0ÃÙãó=é5ÍE¯ïÛ û˜ÉXÇó?�fWjÎNËcé°|)EN¢¼Ÿà • © Ž„RQ\çªmé¾#¹µ`—$Ï¿ÞCßñ®Â ã¹…f…ÃÆÃ ŠóJÞð΢Ð^}‘Û÷S}Üöoþ¿øWM Í>Y6c€„ êÓVk3±¢Š+¸ùТŠ(�ñUÙ’ù-�ù"\‘þÑÿëb°+G^ÏöÝÖzîÈVuyu]æÏ²ÁÁB„ì¿¢Š*�«š]Ù²Ôa˜(l7û§­S¢švwDN qq{3Ó訚d·µóg`ª‹–&¹KÄ—7,RÔ˜!õxþ=¿ ô§V0ZŸ#†ÁÔÄJÐÙu;‘ﺯÔâ•Y\eXê y“;;v,Ç©'&�²Bûâ‘‘‡u85‡Ö¼�OûO�_Oø'¥³RÌ@P2Ií\^±¯M{#EnͰ㎠ý}½ª)5ûÉ´é-%!÷`y�žõ•QZ¿2´Mð9o²“�]_Oó (¢¹�\{M+ãtŽØé–&¬Úê—¶l W�ü,r§ðªtSRkTD©ÂK–JèÙÕ.“X´Žílð ³ þéèÃÛ?αªÅ•ÇÙ®ã�Œ¦pêz2ž£ò­}OÃSÂí-Š™¡ë°rÊ?¨«jS\ÈæŒéᚤݓÛüŒ zŒzB¥_k<ƒO¯s#ÃFR•itÑ㪴”P¢Š+é�0k®øÙ}F*…�»H­Í™¼›âÀt þ••]‘ó9ú� Ø|l¶Œ¬ý¿…™¥E"°e § ÒÖ§ÒÆJJë`¢Š(ÉŽ �Ÿîšè|}æZOdÝbmëô=_ç\µô¡SË–ëô­/¹]x�Ñ¡`Cý+ÎÇ¥(5ØøÜÏ¿¶)SƒÙYüú|´=Š(¯öŠ—ºu¶ ›gL°è㆔þ &?6+Ñ·Ñ£çóÍtmãÈýó®ŠXª´• ô4�YÇDÎZ×Âöñ0k‰ZlEn",h*¨À` ukÔªï7qJrŸÄŠ(¬ˆ §¨é°jPì”aÇÝqÔUÊ*¡9AóEÙ�6�ÑÅ]x~þÝŽÈüäìÉþjªéwìØsçÝ®þŠôcšUJÍ&t,T­ª9[ Êìõ‚'÷äŸÇµuÆ�ƱơQF©ÔW|EJÎófS©)îQE`fQEQEQEQEQEQEQEQE4_ê¥ú †¦‹ýT¿A@ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEU«>¯øUZµgÕÿ ¬ÿ}¾´”¯÷ÛëI@Q@Q@iEþ©?Ý›ZQªO÷E:Š( Š( Š( ƒÐÑAèh•Q@G4ðÛFdžT‰ñ;?Z’¼§ZÕeÕµ %w>P$D�•Ƹ3 rÂA;]½‰”¹OL·Ô¬nße½Ü2¿÷UÁ?•Z¯GhÜ:1VS�AÁ½?Ãz›êš:K)ÌÈÆ7>¤cŸÈŠçËóO­IÓš³g} z(¢½rË}Óõ©j(>éúÔ´W5ñÄ7~ð6§­ØÇ—6ª…u%éN@ ôcÞºZàþ3ÿÉ$׿܋ÿG%t¾Õg×<'¤j·)Oyiò,@… Ê N9õ­zóí#Åz_ƒ~h®«6Ø×M�c�~üÏåŒ*Žçùu5áþµâÏØI«kö:u”ÿ5•´q¿œPžض1ŽŸ(Ï^2ÙQ^O¨üPñ&±âKýÀ>‹S:{˜î.î¤Û`H |Ê1�qódààRi¿üO¤ø§Mмuᨴó©H"¶ºµ“(X�ñ0#%sódg¥n|Mñ¾¥àÅÐÎ�¤¿o¼òý¡°¼r»XsÏ|Õßk¾&ÑGÒP7>]Ù6òKåGÇÍòާ“‘\oǯ¹á/û é]/įj^ miÐZKý¡z-åûB3m^9]¬9ç¾h½¢¹�xÞÃÀšö…Üm<Ò?—ml‡ 3úg°Ïõ W > üMÓ­ÿ¶uŸÀ4Ed‹˜ž8û±ÉàsÊŽœâ€=†Šóÿ†?»ñé×fšxí­.„v†$efŒî ¾Xüئ+‘°øÅâ�^ïQÑt�ÛP×RòHàH•’(àC�ò–~¤ñÕGè·Q^<Ÿ|_á�O°ñï‡---/œGÝ“’ªrOÌÀã## ãšö(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÎ—ýkÿ¼i”ùÖ¿ûÆ™@Q@Q@Q@Q@Ûÿ¯Zu×úï›oþ½i×_ë¿ ‚Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦ñêßïT50ÿ�Vÿz€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÊ×5oìÛp±àÜI÷Ùµ2’Š»4¥JUf¡ ÙfûT´ÓÇïå�D^Xþ‹'‹Ð6"³b=Yñúb¹‰$ydi$bÎÇ%‰É4Úâ–&mé¡ôTrš1_¼÷™ÕÃâ虀šÕÐz£ný8­ËKëkè÷ÛÊ£¡Q^qRÛÜËi:Í”uèE8bdŸ½¨«å4¤¿u£üJ¢¨éZ’jvbPȼ:úð«ÕÚšjèùÙÂTäá-ÐUmBS�s"ðËõÅYª÷ñôûˆ—ï4l×KfíίµÏ8¢Š+É>à(¢Š)ñHa™%_¼Œ~Ê|1§Ž%êì~&„)ZÎû˜Fh  Q^¹ð¡EP!â«Cê]òJ»Iÿhõ¿•sõè÷¶q_Z½¼£ån„uÔW ¨i·tÅ&\©û®:5pb)µ.e±ô¹f.3¦©IûËñE:(¢¹ÏX*î•hou(b+»sÿº:Õh-幕b†6w=®ãFÒWL·%ˆißï°íì+Z4Üåäpcñq¡M¤ýç·ù˜¾)¿i.VÉÉ þìúßιڵ©¹“Tºc×ÍaúÕZš’r“fØJJ•Åv (¢ é (¢��®+ô (¢�Š( ± “ÀÞ6¿a§-¤3Hi óõé\*®9ïN¯¥Ëò–£Ï[Kôÿ3ÄÇÊä—Do_x‚È$‹ì#,¤f_~•ƒEîR¡ *ÐV9cdQEjPVuòâpݘV�A©BÑÄ¡Æðz€sŠÊ­¹lx\GF5pMêµ_-ÿ ”­îZ)éWÒæ'8ÇŠÉ¢°�WŒË¸ƒ‚‡³ø£ÙôôfÉ‘Éu�VšõÌÞ½«>ЧY½ŽÌWâªÃ–”T<÷/øaY‹±f9&º/¡:Ù|p#a\è˜2OJî<bb3NGEÙŸRy?ÈW-áI³—!ÂO‰uå´uo»{™ÖQEâl—ªø–;¾Én‚YùÜOÝOñ5vösmc<ê!#ëÚ¼õ˜³bI'$žõèà0±ªÜ§²:pô”õf™ñ¦[>xÐ"ãùV®™âA<‹ âª3p$^™÷ô®ZŠõ*`èÎ6å·¡Õ*0’µ�JéYÓëšt U®0쀷ê8®^ïX¸º²†ÛqUUÃ�ysïYÕÅG,ëUýÆÂÿ3;»}fÂé‚Gp¡�@À®:¿^k]/‡ugy•ÃnÈýÛ¿JÏ—û8óÓw±5püªñ:Z(¢¼³”(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*h¿ÕKô Mú©~‚€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«V}_ðªµjÏ«þYþû}i)_ï·Ö’€ (¢€ (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@¡¢ƒÐÐ*(¢€ òm[M—KÔ%·‘HPI�¿¼½�zÍAuem}—uJ½ƒ ãéé^~c�X¸$�šØ™G˜ñð ’{W¦ø_N“MÑ‘&R²ÊÆFSü9Àò­Zèze”¢[{8ÖAÑŽX�¦zV…seÙ[ÃMÔ›»òamBŠ(¯d²ÄtýjZŠº~µ-Áügÿ’I¯¹þŽJï+’ø›¢ê!øw«iZ]¿Ú/n1[Õ7bDcËõ4àw~ñzø'AñÝûCwi¥ˆ®šé½RÕ@Úì:|Ä ÷ÁÏÀúKþ#°ñ/†íuË)¶ž=ä1æ2>ò·¸ ƒôªÞÒ$´ð“£j¶ËæG§Çmsã;²œdÔq\7�<â/ø³XÐÅ“]ø6ü³Ãqç¦a%{©mÝ>C�É }h Ç:®¹w~>x"Àië1Yµ†Xgõ* yÏRpFqšåþ"Eã3â\x²}$#êJ-í´àø�ç�qbܓӹ­½ Ã>Í+Ön·£Ë9šžPŽ„€9Ë/8 dzUxâGˆWNñåÕ�Þ±er²A¥[��À€†á˜�ÌYW9=SÅiüzûžÿ° þ”¿þÿƒÿì(?öZ±ñÃ~-ñ~‡á9N‘Ô­¯÷ÐEp�at,ÜôìMh|Yð¶µâfðÙÑìþÓö;ñ4ÿ½DØœsóž�³@ñqñ›À6·c6BPÊ­÷K™š¥{3¢É#¨d`C+ ‚= pŸ|%câÍ6Æ/íK}7[·—ÌÓ'–@…Ÿ#)êA;zr>‡žŽ/ŒšÕ¹Ñ5Hô�.Ñ×˸ÕbeiY:1PáˆÏð¯^ÔKöxH£·ñJ@s Þ Œÿ³†ÇéR| ·ˆk6¹Ø<Ó¨÷c�¡¤8üÏè)¿³½²C¤øŽH 5©¿Ääç!W×躅ּ5uâ‡Õì¾Ì·×þu¹óQ÷¦[Ÿ”œuq@ÿ´8ðŠh‡#TAŸø×°×›üeð¶³â¿ivº%ŸÚ¦ƒPY¤_5jaœ±©éQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÓ)òÿ­÷�2€ (¢€ (¢€ (¢€ (¢€%·ÿ^´ë¯õß…6ßýzÓ®¿×~Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@L?ãÕ¿Þ¨jaÿ­þõCEPEPEPEPEPEPEPEPEPEPEP^¬Ý½Zw'*­±~ƒ�þ½w·°Ø[4ó¶pêÇÐW�HÛägþñ&¹1RÑD÷2jOšUòEWï…Q@>º0j¢,ü“)R=Ç#üû×m^¢‚ÚͨßÍzwaŸ¸|Öq«¦º ¢Š+¤òN]ÓšÂý™W÷2’È}=Eeפ]ÚC{nÐN»�þ`úŠãõ^Y±h”ÏfAÈúŠà­E§xì}.0…H(Tv’üLz)H*H ‚;TG‘‚¢³1èd×9êߨÚè<1§4×_l‘w žíÿ֦龸¸a%Ø0Å×oñ7øW]QÁÅE ;WU .üÒ#½-’7#Ø+29¥µ¹ó ‘£‘åe8"¤¿¼{û£s W~:3úW“MUç”®~g˜g51TÔf­8¿“ÝH®F¯½%(ôëRIo$H†ý+{7±âÆ�J‘”áÔwò"¢—ã󧯖œ¶\ú �''«IwÕßÉô}>kË•¦Y¸ù>ÕéV6‰ch�GÈQÉõ=ÍsÞ �ÚÖêéÈðE°þ¿ÒºšóqµÜŸ³[#ô,²4éàá IÛ}w~>žAEW ÜAyÚl¦„ut }{Wž²²1V08 ö5é5›ªøn-Bµ@â+Œ|Ù+ý} z8 Th·ìÎŒ=U ÃÑZÇÚˆlyhG÷ƒŒV¦Ÿáå´?h»e‘Ðn¿t}}kÔ©�£ßšþ‡\«A-ÎVŠ@sÍ-oNq©8ìÍ¥føex'IPáу™E[WVb=Þe¸¶Žeû®¡‡ãRU-!=&Ù[®À>jí|�D£6‘äIY´‚Š(¨QEQEQEQEQEQEQEQEQETѪ—è*š/õRýCEPEPEPEPEPEPEPEPEPEPEPEPEPEPV¬ú¿áUjÕŸWü(³ýöúÒR¿ßo­%QEQE¥ú¤ÿtVmiEþ©?Ýê(¢€ (¢€ (¢€ CE¡  TQEQEQEQEXƒîŸ­KQA÷OÖ¥ Š( Š( Š( Š( OÇÞ¶ñΓ u%•õ¤¾u¥Üc&'úddàð rWøµ©Z6—}ã-.;Ë–x-ÿ|Èx?À9Ç£­zÍ…á Øx7Öú6Ÿ¹£�,ò¿Þ•ÏV?瀭Ú( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  éÖ¿ûÆ™O—ýkÿ¼i”QEQEQEQE-¿úõ§]®ü)¶ÿëÖ�uþ»ð (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*aÿ­þõCSøõo÷¨(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¡ªj‘i�ošFûˆ_þµ^$($œÉ5çš•ë_ßI;´œ ô^Õ�jœ‘ÓsÐËð‹SÞøVâ_j:„¾eÃçuG~‚ªÑEyí¶îÏ©Œ#ËdQE"‚Š+KLÑ®u)Ž ó!ËÖœbäìŒêT…8óMÙü+ddº{Æ$cjŸV?ýoç]uEmm¥ºA íE-zT¡É%ŒÄ}b«ŸNž�EV‡(QEÇŠ9>ühßï(4©F0ˆª=†)ÔQaÝÚÁE„€ 'u E-OTƒL„<Ÿ3·ÜŒu?ýjäî¼E¨\1Û/’�–1�×­TÔo^þúIØœ…‹ØUZóê×”ž›SƒË©Ò‚sW‘~=kQ‰·-ä§ýã¸~µÐi>$[© µXå<+�ºÇÓØ×!ED*Ê/sjø5£g>èôú–ßýzÖ>ƒz×Úb4‡2Fv1õÇCùVÅ¿úõ¯J2RWGÊU¦éÍÂ[¡n¿×~ Muþ»ð¨i™…Q@gê5¦£óJ…eÿž‰Áü}kBŠN*J̺u'N\ÐvgŸ_Ù­…ì–Ë'˜61Ôf«Uýh¬\çûßÒ¨WÔáaQŒcµ‘ê©ÊkšNí…Q[€QESŠ�_pù˜�½Æ1þ4Ú«q1Šæ2~î9¬ê%u'ÑœxÜlptÕIìÚOæ÷ù¨ @#�h­Äïª (¢€ B@ž‚–ªÞÌ?,™ºý)J\ªç&; &U§Ñ}ï¢3ÉËêhRädzRQ\ãͶîËV*†bXüÃîŠÐuWR¬2 c)*Àƒ‚+b7ß·¨ÍtÑi®Sï8WJ®xWu«óO¿åéb“Ø6~Fô4±ØæFôzŠ¿eÜô× åʧ´äù]ØÐÑoŽŸz˜8…ð®;c×ð®ê¼Ö½Ü–¶‰›©@Oå^ViM'®§~& 6h’Š(¯$å ¶¿ñä~‡ùÕJ¶¿ñä~‡ùÐJB†�ênáŸLÒМ^[½•ì°0åÜv?•F5ÜjÚ4ZšÏ—:Œ+㯱®V}R�ˆ6Ìã³GóF[ì—4;EN½ \3å™J®iVnÔc‡@w?²�óŠ’ÛÃú�Ãa1/v�ã‡Zë4Í.2 ‘üÎß}ÏSÿÖ®ùæÓª­N<¾oô9±2¥F-)^^_©xÀQEp0QEQEQEQEQEQEQEQEQEQETѪ—è*š/õRýCEPEPEPEPEPEPEPEPEPEPEPEPEPEPV¬ú¿áUjÕŸWü(³ýöúÒR¿ßo­%QEQE¥ú¤ÿtVmiEþ©?Ýê(¢€ (¢€ (¢€ ( ô4!öüèÄ>ß�AEOˆ}¿:1·çPQ@âoÎŒCíùÔPø‡Ûó£û~umvt§TP}Óõ©h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Œ�Èdbà“Mò%þá¢Fo5þc÷�zföþñüèþD¿Ü4yÿpÓ7·÷�çFöþñüèþD¿Ü4yÿpÓ7·÷�çFöþñüèþD¿Ü4yÿpÓ7·÷�çFöþñüèþD¿Ü4yÿpÓ7·÷�çFöþñüèxa‘fRT€)n"w—*¤ŒS f3®IüénX‰¸$q@ ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá£È—û†™½¿¼:7·÷�ç@ò%þá©DOöv]§;³Š¯½¿¼:˜1û+œîõ yÿpÑäKýÃLÞßÞ?�ÛûÇó ùÿpÑäKýÃLÞßÞ?�ÛûÇó ùÿpÑäKýÃLÞßÞ?�ÛûÇó ùÿpÑäKýÃLÞßÞ?�ÛûÇó ùÿpÖUö¹c`æ7“Ì�uHþb>½«Äô­#ÙZÈʋĎ$újæk–®"ÎÑ=¬UÏ:Ú_¡ÕŸEŸ–ÑÈõ.Z¶ñ=„ìMð“Ýǘ®*ŠÅb&ŽùeXf¬“_3ÔR6•ãã †R4ï"_îóý'YŸL”ÌÖäüñçõõÝÅ8ž$–9 #Œ‚Q]tªªˆð±˜9᥮©ìÉ|‰¸hò%þá¦ooïÎ�íýãùÖ§ÿ"_î<‰¸i›ÛûÇó£{xþtÿ"_î<‰¸i›ÛûÇó£{xþt_UŽXô›· F!n ózôË„7ÒÂXâD*yõ¯5‘97e$èk‹µLú –K–qê6Š(®SÛ (¢€%¶·’îæ;x—t’0P+Òá³x`Ž%Cµ(ú æ|'d9/Y~bvF}|žÕÓooïλððå�3ê|Îmˆö•}šÚ?˜ÿ"_î<‰¸i›ÛûÇó£{xþuÐyCü‰¸hò%þá¦ooïÎ�íýãùÐü‰¸hò%þᦗ ¤šÈºñ=�³YfóÏ‘ùÔÊJ;³JtjUv‚¹µäKýÃG‘/÷ skã |ÐN¨`kRËXµ¿â þî7 J5!-5©„¯M^qv4<‰¸jËy�”áPçËl~Týíýãùѹ¿¼:¶sÅÙ¦y}¡¬ií§ßºmýÓ�ÑŸoO³ëÉ’qvgÛÓ©‘SŽÌ(¢•U� ,ÌpîiuÞŠGµ¹eRWxŽ?ýUÔC‹2’¤YZ=“iÚtp“‡?3àÿÿ8ü*=cXm2å¶n!çõëá¨ÊJ4ÖçÈb¥íñpêË:Ö­k§K‰t„qòJæ§ñEÛ“äÅkïóÄ’G–F’F,ìrXœ’iµô4rúP^ò»6†ZêhI­êRžn™Ý!OƒÄ” ˜J¿Ý�çÖ³(§W/¡QmoMˆò¥nTסÝi:¬Z²•EÙ:Œ´dþ£ÔV§‘/÷ y¤Ékp“ÂÅdC�kÐín¾ÕkèÇ(lg§µxUðó¡>IëÙ÷8±T# NžÏ§frÞ)²{}Ag*B̽}ÇË…]ö©d5+&…�Î>d'±® ÐÇ##pÊJŸ¨¯s/®ªRQê�0õ£ËÕ ¢Š+¸è (¢€ «¨ÐÆ@û„äýqþ­Z«6©{v¶²}Ƀ)#·ð85�kr6úvk„úÞt–öÓÕjŒK{£Êܧò­‘$FV}õŒÚuä–Ó®^Äv#Ú«‚AÈ$jÂ�f—t|>]Ä8œö£Í¥ž�y_ô6¨¬‘q0ÿ–�ùÓZYï;©­=ºì{3ã >í7Uÿò/Íx‘‚ ß ¬æbìYŽI¤¢±œÜ·>W2ͱ„¯SH­’Ûþ (§fè¤ýAæÆ2“´UÆÖ¼*RSÔ «mfC”c¯WU5«>ÿ†2º¸e,Eeg-ëo0¢Š|14Ó$K�ÎÁFzdÖÍÛV}i>�e%ýôVñ©;�͎ù¯DòC�YzN——Ãn™ÇÎÿÐ{VŽöþñüëçqØ•Z~îÈó«Ôç–›!þD¿Ü4yÿpÓ7·÷�çFöþñüëˆÀ‘/÷ qºÏ‰.. ZZHc·RAe8/øúWIªÍ$zUÓ+6DgûW�W.&mZ(ö²œ4'z“W¶ÀI'$äÖ¶—®ÜXÊ«+´¶ç‚¬rG¸¬š+’2qwG¹V”*Ç–jèôì�³}§#ÉÙ¿~xÛŒæ¸íKÄ·3ÈÉhÆGFy¿Â�5ä£Âñn8y „°+¢µfì‘åà2øEÊSW³i|‹K©_+n“çÞBk Ñ¼DóL–׸ÜÇ /N} r´V0«(»¦w×ÁÒ­V¾g©ùÿpÑäKýÃT´Ë©.tËyY‰fA“ž§¥ZÞßÞ?�zIÝ\ù ÅÂN/ ÿ"_î<‰¸i›ÛûÇó£{xþtÉäKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃRLjäNHâ«ïoïΦ‰‰Š^OAÞ€äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀äKýÃG‘/÷ 3{xþtooï΀rËgnÓÜ0Š%êÌp+–»ñ´åmmZP?�Ûh?‡5‡â=fMRý‘\›h‰X×<V¬ZùŒnsS�†‰uîe)¾‡eޏEWûѾOäGõ®¿F¾¶Ô-Ú{iC§úƒèGjñê¿£êÓèú‚\ÂI$LðëÜVxLê¬f•mWK>§«4'aëIäKýÃQGp."Y¢rc�SžÆ�½¿¼:ú¤ÓWFÃü‰¸hò%þá¦ooïÎ�íýãùÓþD¿Ü4yÿpÓ7·÷�çFöþñüèþD¿Ü5z0DjPgooïδcÿTŸîŠuQ@Q@Q@¡¢ƒÐÐ*(¢€ (¨ç¸†Ú3$ò¤H:³°õ M¤®É(ª–Ú��ãì¶¼‚Wþê¸'ò«tÚkqFqš¼]ÐQEŠ,A÷OÖ¥¨ û§ëRÐEÍ|@ñ ß…< ©ëv1Á%ͪ¡D�ICºES�=÷ –ŠÈð®«>¹á=#U¹HÒ{ËH§‘b(fPH’qÏ­kÐEPEp_|o©x1t3§Ai/Û_hFl/®Öóß5wÇZGÑLJt…ÔÍÏ—vM¼’ùQñó|„c©ääPaEPEPE“âOižÑ&Õµiü«hð,ìz*Žäÿõú Ö¢¼wþŽ¡%±Ômþë2èãæûnæ ·×„+ÿ�cÞ½Â1ÒÇhl8àÊFGà?­Iâ�E¡…lâl4ƒs‘ýßOÇúW%[׬Óå‰çeÙ|gkU_²,ͨ^NÙ–êVöÜqùQ¡yf;©WþqùUj+“™ïsÛöPµ¬¬ugŠ uŠü ª1ùŠé� yW˜×WámE¤F±•²PnŒŸNâºèVmòÈñs¾1�µ¤­mÑÒW1â=™ÚúÙsŸõª?ô/ñ®žŠèœÕ™äá±ÃÔç‰æWq}áÛ+Æ2(0Èz”è~¢²ÛÂ3ùnÐ�R¤W°óOMO£§šaæ¯'fsusMÓfÔ®DqŒ ûïÙEtÞ…5ÍÃH?ºƒhüëz xmbA¢ÀUSÃ6ï#Ÿ›SŒmGWß ¶ðGmn�D0ˆ0IEݱóͶîŠ( AE›®Ü›mvS†a°~?ýlÒ“åM—J¤ÔSœ×5§½™ �ˆ¶SŽ?Œúý+Š+Ë”œ�ÙöthÂŒ ´ UfF ¤«�AÁ”Tš¦�¬øÌŸô„Ï÷ǯֶëδë“i¨A08Úã?N‡ô¯E¯CQÊ:ô>_3ÃF�[ÇfAwgôÓržž úŠæ.¼'pŒM´É"vÁÿ 먫�(ÏsŸŒ­CH=;\~Ô°æ$¥³ü«KЭôâ$'ÍŸûätú Õ¢”(Â.èÒ¾a^´yd켊®¤ºm®ü•¸E=ϯҸ‰ç–æf–g.íÔš¿¯Ý�VEÏÉÈ£é×õ¬Êú|R¦¤÷eЦ£õaEWi¸QEWiáÉ7èñ¯÷—õÏõ®.ºß çû:_O4ãòçæQN�û3 OðÃÅ:»išw— bâ|ª‘ÕGsþ}k€´™’P„ü¬z{Ö¯Œ.Lúü‘çå…Uå“üë¡Íc„�³‚kv~oŽÍ*Ã1ö°zAÙ|·ûͺ*y„Ñçø‡QSWªšjèý'^ž"”jÓwL(¢ŠfÁZþ€Ë«+㈔±ü±ýk"º¿ *}Šw÷žnÒ}°þf¹1Õ9(?= 1P‡®†�#fÕD�–5‡5ÌWâ»=ÞUÖÜ®<·þcú×=£ÆI@YQXP\Ôc(Ÿ Ÿe%/­ÐWOâK£]} ÔQEQòAEZ‚Íœ†�_Næ´N“V+|K ÒlEìp95çìi:²Ùþ†ñ¸µ[•I¥®öïc:+LŒÈHöq>E ½WÌOˆ”¹”šô?Z˲<_Z0׫z·óÿ-†Í:¢©G"¾‹)ÇÏ ŸüPbè*mJ;0«Zlf]NÙ¯˜§ð&ª×QáÍ-¢ÿM™pHÄ`úz×¡Šª©Rmž}Y¨Å³¢¢Š+æ,(¢ŠŽx–x$…þë©Sø×�ÞZKerðL¸e<Qê+Ò(¼Ó-5<-ÌAŠƒµ‡ ¼ö5�j\ëMÏC�ú´š’¼Yæø¢yåX¢RÎÇõÕÛoȹ”/¡?�jXi6špÌ —<c–5Í4›ÔõªæÔcÃVfjºQ‹ÃqCÌöøvÇ~»¿ž äkÓú×5©x\I#Kbê™äÄÝ?ZV¢Þ±9rüÂ1¼+=Ýïêr´ª¬îA,Çæµ—ÃZ›6 H£ûÅÆ+{Iðüz{‰æa,ã¦Ê¿JÆ''µ�B¾cBœn¥wÙV6ÿd°‚ÕõïV(¢½¬¬|¤¤äÜŸP¢Š)ˆ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*h¿ÕKô Mú©~‚€!¢Š(¢Š(¢Š(¢Š(¢ŠÎÖµxô‹/5€i[ˆÓÔÿ…EJ‘§9»$ ع=Ä6±™'•"AüNØ”þ*ÑѶý¤·ºÆØþUÀÞß\ê™®e.ǧ öµW¯›­ŸTrýÔU¼Ì�GÐõMoM¾`�]¡sÑ[*OàzÕúñúê¼9âY#•,¯¤/±ÈÇ•>„úWN:U$¡YZýVÃ�KîvÔQE{Æ�EPEPEPEPP^3%�Ã/ÞXØ�®*zkíØÛñ·ç¦)I]4�ÑV/`KkÙ¡ŽE‘ˆWVÛš¯_�Ê.-§Ðå (©mí庸ŽÞ/,ŒTw4’mÙè¾fÚ놀bkTV‹ce ªœˆ”.}OsS×è8x8RŒ%ºKò:VÁEV£ (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@¡¢ƒÐÐ*(¢€ ò]oV›WÔd™Üù@‘vUÿõªò_M—JÔe¶‘HPI�»2ö5Û‚åæwÜù¾$u=”9~»þŸ©M£utb¬§!�Á½KÃ:›êº2M1Ìѱ�Ï©çò"¼¬HdžÕê>ÓdÓ4DI”¬²±•”õ\àù[cyy÷<þu>±%†Úþ†ÝQ^aö…ˆ>éúÔµtýjZ+ƒøÏÿ$“^ÿr/ý•ÞWñŸþI&½þä_ú9(-#Åz_ƒ~h®«6Ø×M�c�~üÏåŒ*Žçùu5áþµâÏØI«kö:u”ÿ5•´q¿œPžض1ŽŸ(Ï^3á~ñzø'AñÝûCwi¥ˆ®šé½RÕ@Úì:|Ä ÷ÁÏÀúKþ#°ñ/†íuË)¶ž=ä1æ2>ò·¸ ƒô >Ô~(x“Xñ%þ‹àE©�=ÌwwRmŒ0$>eÈ8ù²pp)4߉þ'Ò|S¦è^:ðÔZyÔ¤[]ZÉ”,Hø˜’¹ù²3ҠѼsªë—wãáÇ‚,ž³›Q¸e�&Rª'œõ'g®_â$^3>'ðeÇ‹'ÒB>¤¢ÞÛNˆþx÷-É=;šé¾=}Ï ØPJé~%xÛRðkh#N‚Ò_í Ño/Ú›jñÊíaÏ=ó\×ǯ¹á/û éKñßïø?þƒÿe ëÇ^7°ð&ƒý¡wO4�åÛ[!ÃLþ™ìsýHÂ�ˆ?tëí�gÀ° G™"Á&'Ž>ìArxò£§8¨>'âãã7€mnÆl„¡•[î—2?5JögE’6GPÈÀ†Vzà~xþïǧ]šhmã¶´ºÚ‘•š3¸‚ùcó`˜®FÃãŠ5{½GEÒ4 mC]KÉ#�"VH£�7ÊYú“ÇU /ýž(íüR�·¨#?ìá±úTŸ­âÇ�®v4ê=Øä(i?3ú ™>(ø¿ÃþŸaãßZZZ_8Ž;»'%Tä Ÿ™�ÆFFAÇ5¿ñ7ÀšŸŽnü= ¼ö©¦YÜ™o¢šFS"’£åH'hqÉz°?hp?áÑF¨ƒ?ð¯EñgŠôÏèRêÚ¬„D§lq ËÊ碨õàþDÐÈX­à G k€ª�ú+ľ ,RüFñ½ÖŽ1¡4ÛbØ0„ùŒWo¶7cØŠ•t¿|\A>«pÞð¬¿2YÅÌ× Ø·¨>­�Ð…=kÕ|9á½/š4Z^‘l ¶�“ÎYØõf=Éÿët  j(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3¥ÿZÿïe>_õ¯þñ¦PEPEPEPEP¶ÿëÖ�uþ»ð¦Ûÿ¯Zu×úï€ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©‡üz·ûÕ L?ãÕ¿Þ h¢Š(¢Š(¢Š*ޱjo4©âQ—ÆåúŽjõšº³.œÜ$¦·G˜Q]¿¢<2½å²f&åÔ õúW=^\ààìϱ¡^à§¢Š*Mº¿ Ú”†k¦|„_ ëþ}«KÒ¦ÔçAXAùäì>žõÞC vð$1.ÔA€+«M·ÌÏ6ÅECØÅê÷8}~C&·qžŠB�À Ì­o@aÖdl|²€ãòÇó“XTøÝÏG Ó¡ vAETZ†=jØŽí´þ#ŸZž€Ï¬Â@â<¹üøâ®ŸÆ¬a‰iQ�û3»¢Š+Ô>,(¢Š(¢Š(¢Š(¢Š+Äè_Fb?…ÔŸåýkb±üIv-´¶�´Ç`Ó¹¬êÛ‘ÜéÁßëåîqQEy‡ÙQ@‰ “$kÕ˜ø×¦Wá­9®oEÓ¯î¡9Õ»~]k³®ì4Z‹}ÏœÎ*©TŒOÔ( �IÀRMRÂ#†»‹>�³ü«®0”¾sÈI½‹tUXõ;Žê"}7b­Q(Ê?°4Öç�Ýo''¯˜ÙüêÐ֭Ͷ­:ãåvÞ¿CÏóÍg×ÕR’”]�V.ñL(¢Š²‚Š( »�&ÓôxÌÄ'G'Œgÿ­ŠâаaÔŽ*õö±wh¶ò²í,Tcw¦kÎÌ¡Vt¿v¯b%KÚÊ1nË©‰­N—:ÍÔÑ’Qß*HÇB¬Þ&$ ØŠ­Xá§ÏF2ò?(ΰ¯ ˜V¤úIÛÑê¿\Óþûý*ýeÚH#œg£pkR½*/Ý>Û…«Bx¼[¿ÏP¢Š+Sé·•ÃW ^”¹%s®5a%tÄ®Ž×à =´3 µD �™ÆGÖ¹õ^æ»Ý=Ö×D�ç`бIì+ÔÂáëá!ívrÒÞG�™ân”i²½—‡¬íX;æg7ô…k×5s⢋kpT‡¯à)Öž)Wp·PìøÐ亪aqU<ÕÏ&TªËVttR#« t`Êà Žâ–¸p¢Š(«kÿGè�T«kÿGè�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©¢ÿU/ÐT54_ê¥ú †Š( Š( Š( Š( ¼çÅ7�u­Ê™ù ýÚ�çú×£W–ëHS[½ ×Îcø‘^{6¨F+fÌêlQ¢Š+åLBŠ( NÐ/ûE·™ÎdcR8ÍiVƒÐ®‚¤ôi�§Oé[Õ÷¸9¹áá)odtÇ`¢Š+¤aEPEPEP\Šõyn/žÆ7+' ûíß?Jï+Ìuøß\»Wæ�¸÷ Ïõ¯;©8ÐJ;7©�G¡›NDiQFYŽ÷¦Õ�>ºÔmáŒÏ vç“_)óIEu14 ð¶­;€mÄCûÒ0Zíü3áÛ}$¼ÌD·DcÌ#…€ZЫV}_ð¯²Âåx|<¹Ö¯ÌèPH¬ÿ}¾´”¯÷ÛëI^‘AEPEPZQªO÷EfÖ”_ê“ýÑ@¢Š(¢Š(¢Š( ô4Pz¥EPUîì­o¢òî IS°qœ}=*ÅÓkT)EIrÉ]Öš—c(–ÞÊ4�tc–#éž•£E99jÙ4éBšå‚IyhQE"Ë}Óõ©j(>éúÔ´W%ñ7EÔµë4P‰h^ø™ðØÞi^°Óu½YÌмò„t$ÎYyÀ#Ò«ø»À,ø[Zñ3xlèöiûøšÞ¢lN9ùˆÏNÙ¯I¢€8/Š>±ñf›cö¥¾›­ÛËæi“Ë BÏ‘”õ �½9CÏGÆMjÜ蚤zN—hëåÜj±2´¬�¨pÄgøW¯jì¼}à[oé0@×RY_ZKçZ]Æ2b¦FAÀî×%qá‹Z•£iwÞ2Ò㱑<¹g‚ß÷̇ƒüœz0úÐìïl�é>#’ÍjoÄq99ÈUõú0®ƒáG…u¯ ]x¡õ{/³-õÿ�n|Ô}é–çå'G\WYá Øx7Öú6Ÿ¹£�,ò¿Þ•ÏV?瀭ÚóŒ¾Ö|Wáí.×D³ûTÐj 4‹æ¢m@Œ3– u"²>1ø[ž$×4 t"=BÓOÌϳF±´…‡ÊÊΤŒ(ü ¯_¢€}ªö Ä~bººÁñM£Mc ˜[æÿtÿ‘YWMÓv;²é¨âbÙÇQEæŸZQEv>$é’ƒÐLqù ¿©ê°é±ß<­÷P¾çÚ«éq�'AL0peqîz¯A\•ÕÌ——/<§,Çò•ôYnÚ¤ç²>R¬#[9-®Ky©]_¹3JvöEáGáU(¢¾Š1ŒU¢¬�ÒIYXŠúî ̨£¢‡8üª½ÜT´hOrÍÍõÅâ ¸på>ëÇ¥V¢Š#d�$´AEj îX#žÛdñÈ»�VÁÄõJæÒ{9\FQˆÈƒÅDjÓ“²z‰N-Ù2 (¢´((¢ŠŠx„±‘YD$ÕµPÜ@³Fxù€à×Õyg)ÅïÓÏþ óÜC”}~ ­=*EàK¢õZÛî2ÕK0P2MjG½c Í’;Õk4ûÎG=*Õ|öa�©ºTÝ’ÜêàÜ–4pß]«ñOeÑ+öêßä.O­(ZmÅCˆ£.hÉú=�´©BœÕš*ÜÞn#éݪOøúOÇùRÜDzRGCÍIad2€`}kéðبâ­8;þžGãõ©cjçq¥‰ÖQ—ÊÉÞëÊËüÍpr:צX¿›ÈF7G»Q^oF{ˆ¡GÔâ½.Ô%@À@–j׺ºê}®)®dˆ¨¢ŠòSƒ×íZÛW˜‘òÊ|Å>¹ëúæ³ÁÍmxŠìÝjMwʣ߹ÿ>•ŽTÔUËñ4š«M^úéº>« ‰„è¨ÔÑØp ÒÓŸ¥lx}â]Ibš$‘dÔ§¨Å}ˆ•':´íeé‘ljŒ)ÝÁÜ4�[é–I­°9,‹ØUÿÜ2˜-W„Æò~Ãú×MÒ¹¿Ú3n”eTloOë\Ôq>ß=º\*ûJ©Èæh¢ŠöÎã¬ðµËIi, r"`WèsÇéúÖõaøbÑ¡³’w3´Aßõ5¹_3Œåöòå<ÊÖöŽÁEW1�Uµÿ�#ô?ΪUµÿ�#ô?΀*QEQEQEQEQEQEQEQEQP]ÞAclÓÜH5î{ŸAï\V¥ã »†)f>ÏfÆ\ÿ‡á\x¼}*÷Þ½–ä¹$w”W’Ëys;n–âY«94°ÞÝ[¶a¹–3þË‘^Wöüoðiëÿ�hzÍÃiž1¹…–;õó£þúŒ0þ†»Kk˜nàYà�mà 4„tö‚ºpyelD—2´{ÿ‘QƒeûD±±†Õ9¨õ=ÏçV(¢¾Î1QJ+dnQE0 (¢€ (¢€ (¢€ ËÖt;}b!¼˜æA„� ãØúŠÔ¢³«Jbá5tÄÕÎø'Pó0'¶)ýâ[ùbº-ÃÐi”·›pF ‘€ ³ErPË0Ô'ϯ˜” µgÕÿ «V¬ú¿á]åŸï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEPz(  TTø‡Ûó£û~t>!öüèÄ>ß�AEOˆ}¿:1·ç@QSâoÎŒCíùÐÁ÷OÖ¥¦ @Δê(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÎ—ýkÿ¼i”ùÖ¿ûÆ™@Q@Q@Q@Q@Ûÿ¯Zu×úï›oþ½i×_ë¿ ‚Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦ñêßïT50ÿ�Vÿz€!¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÍÖ5tÒà縿ÔûR””UÙtéʬ” ®Ù î‘©guUØàUq©ØÛöÛ|ÿ×A\ ÕåÅì¦K‰YÏlžÐv¨+‘âµÑÜ2Uo~Zùœ¬®¡”‚B -yÕ–¡sa&ø$ wSÊŸ¨®ãKÔ¢Ôí|Ô]xtþéÿ Ú•e=:œ̾xz÷�ríQ[EPEPEPEPEPEPHÊ®¥X¤`ƒÜRÑ@f¯áémç¶K~¤wOñ‡]Oе]–1¶ òc¿ þ¿•rÕæÖQS´O®ÀN¬è)Uþ�TÖ“­µÔsóN‡ƒp¯O·ûíþé¯;ð•ƒ]ë zÀù0g÷cÀ—?•z%¿ßo÷M}f2«©%}ìyØJÒÄN¥gð·hú-/ó×þ†Š(®3´àuhÚ-Zé[©�·àyþµN»sG7ê'ƒz cûãük‘–)!r’£#¡† }.¼jÓVÝ�ŠqC+CD�¥Ö-Âÿ n?@*œ0Ëq ŽÙÜöQšì4M#û>3,¸70qü#Ò–2¼iSiîÅZ¢ŒZêkW5â»ÇE†Ñ Æ÷÷‡ó®–¹oÛ7™Ð\ydú£ú×ËWmA´g–¨¼LyŽl?¨ ¹¦ÑY¼ÏáÉÎíøýûŸMõjW¿)Ùx^ñî,^$˜Ÿîžƒô5»\÷„íš;Y®`JÀ/¸çõý+¡­h¶à®|¾=Ebf£·õÄ(¢ŠÐã ¶¿ñä~‡ùÕJ¶¿ñä~‡ùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ F`ªYˆ ’{RÖ7Šn�®ƒ6Ó†”ˆÁúõý¬«UT©Ê£è®&ì®qºî®úµó0$[¡ÄKíëõ5•EðUjÊ¬Üæõg;w (¢³Vχu–ÒïBHÇ천8þéþõcQZQ­:3U!ºvÔí¯|ko³·i¿Ûs´~]•fŸê;² µÓk�stWeL×7~kzæÎ¾×ÆçpvƒÚ&þ‡ük¦±Ô­5(¼ËYƒ�ÕzúŠòªšÖî{+…žÞB’/B?‘®œ6uZœ­WÞ_ˆÕGÔõª+7EÕ£Õì„ •x‘=øÒ¯ª§R5 §tÍ“¸TѪ—è*š/õRýXÑEQEQEQEQEQEQEQEQEQEQEQEQEQEU«>¯øUZµgÕÿ ¬ÿ}¾´”¯÷ÛëI@Q@Q@iEþ©?Ý›ZQªO÷E:Š( Š( Š( ƒÐÑAèh•Q@Q@Q@Q@ û§ëRÔP}Óõ©h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ª©©Yɨ˧¥Â5äH$’~eSПÌVG‰õÙWÃúDWÌêÛÞIˆÏà‘žýûWðåõ)<®>¯‘¨?| rñÇ€=^©Ýêºuƒª^j¶Ìßuf™PŸ¦MUñ6¯ýƒá»íH^þ@z$*çñ"¸ŸxOÖôEÖ¼B“^ß_æ\¼¬»Tž:’G?ˆ JŽD–5’7WF § �­é3Èʨ£%˜à^ká¯;Áÿ¦ð·�$šeäfkQ!ÉC‚öV×—ÅM7‹|ká5šH´ët]ˆÎ nçð*¡c@ý¦­¦ßÈÑÙê—½V•Èü«•æž-ð›¤hrjþI¬¯¬˜2J͹G^¤à�“Ç¥v~Ö¿á›IÀK$¦õ%[õ€6(¢ŠÎ—ýkÿ¼i”ùÖ¿ûÆ™@Q@Q@Q@Q@Ûÿ¯Zu×úï›oþ½i×_ë¿ ‚Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦ñêßïT50ÿ�Vÿz€!¢Š(¢Š(¢Š(¢Š(¢Š(¯=Õ®šóSžRr¡Š¯° ô*óIÐÇ<ˆßyXƒù×.)»${Y,SœåÔŽŠ(®#èBµ|=tÖÚ´kŸ’_‘‡òýk*®iH_V´ ×ÍSùÕAµ$ÑŽ"*Td¥µ™ètQEz§ÅQ@Q@Q@Q@Q@Q@Q@ˆ¶¹sžÄÿ|ŠÌ­ÿZ4wËtÉ*àŸö‡ÿ[�^eTÔÝϱÁÍK» ¢Š+3¨z3N¤_º)kîð•<4"»_ï<*òr¨Û (¢ºÌBŠ( Š*�ÕÞAŽ>� ¨”Ôw8s ÂŽ�µªývAs/›1# àT4U»{`@wÏA^f' 1ç™ùÆ ŠÎ±’T÷z·Ñ/ëdUÍÑIú •êúŠÕéH@a‚õä¬áßXiê}”¼?�³÷kûßáÓó¹–¬Uƒ‚:V¼N$�\wŸqoåüË÷}=*Í�Ìz5{¸:ñª¹¡³<ÜŽŽ'-Ìg€Ä+]_ÉÛf¼š¿ë±jŠ(®óíLëüùãýÚ¬¬Êr¤ƒíZ7±o‹~@+YµÅZ>óO©ù~F¦1”Ó·6©ÿ^d†yHÆóQ’IÉ94T�A-ÌË 1´’1ÀU&±Œ!OX¤�*®'‰iUœ¥Úí¿ÌDé]“ ]ê1®†ÜòÒ°ê?Ùþ½+cBð˜µe¹Ô¼ƒ•‹ª©õ>¦ºªùJXnleL\ÖïEåÝúöûϿ˨ÔÃá•&ìÚ³ï®êý;wíb½•”}¢[[¦Ø×ó'ÔûÕë¾ß¦·ûíþé¯A¶ÝÙÙ¨EF*ÉÑEŠ kÆ’ :+ö†iÔQ{Ô�#DUŠ1N¢Š*9àŠæ†d jJ(m;£•¹ð”›Éµ¸B�„¹~#­>ÏÂdHòu*?‚<óøšéè¬}…;ÞÇsÌñ.<¼ßæ68Ò(Ö4P¨£Â�E±ÀÝŠ( ­¯üy¡þuR­¯üy¡þtRŠ( Š( Š( Š( Š( Š( Š( ¹¿‚txHè'ÿ¾ZºJÍ׬�þ�q ÈôãŸþ·ã\¸Ún¦q[ØRWG˜ÑEðg0QEQEQEQE±á›ö²Öbþîcå¸úôýq^‘^BŽc‘]z©W¯WÔd5\©Î›èÿ?øcjo@©¢ÿU/ÐT54_ê¥ú ÷�h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÕŸWü*­Z³êÿ…V¾ßZJWûíõ¤ Š( Š( ´¢ÿTŸîŠÍ­(¿Õ'û¢€EPEPEPAèh ô4JŠ( ™,Ñ@…å‘#QüLp)õ皦£&£xò3,#^ÀWV ëÉ«Ù#ZT½£;¸/­.[l71HÞŠÀš±^^¬ÈÁ•а9]ö…~ú†˜²Hs"Ž}HïùZâð^Â<ÑwEÖ¡È®�*(¢¸rÄtýjZŠº~µ-QX^2Ö®|;àíWX´HžâÒÜËÌ BG¨~4»Ex¶•ñ/â'‹ôè.|+ák£Š0.înIHÞle–0d^N§ßí'ãn©x·$Þ–O$þDv0±¹ÜÌOÜ ŽrOnq’=žŠñ¹~(øÏºîŸoã� YÚi÷ÒK‹9 ÙÈÉ'sŒò88é]‡Åê ðyÕôØm¥¸ûBE¶åY“ œð¬xõ ÒНa;ÝiÖ·yaG`½ +Šðç�µ-_⇈ü3q¢Ùi‘††HÑ„ŒI_¼K~ñèw´W•êÿõýGÅÞð'‡STŸOb—WW2m‰X9^àŒ–ç½&‡ñ;Äž/²ðÏŽ<=™w�mqm&èÙ�uläñ�Ü2;ЪÑ\O�þ"[ø--,íì¤Ôµ«ã¶ÖÊ#Ës�Çœg€É?‰�ßÄ_‰~·¯‰|hº@#ÌkYy'8vÇâ÷Ù|Oñmÿ‚¼&±¦Ãm-ÂÏanU™0Çžƒú×O¥]=ö‘ew(Q$ðG+è ('ÜוüdÖ,¼AðV-[O“Ì´ºž #$`õ9v äq]ÉñŸá‡¶šÆ§!Kk{IÚ2ÌJGrOÓQ^9mñâ~¿n5]ÀöŸÙ/óEö©y"ö#.¹Ï²‘éšë<ñÛÆ¿k²¸²“LÖ¬N.¬e<Žq¸dŒðAÄ€vôQEQEQEQEç¾,øÁáÿ Þ2Í&Öulí–_0VôfçØG¥w�ŠjšUæŸ$’ÅÔIaÔ2•%Ob3ÅfxkÁÚ„­¾�§EnHÃË�ÒIþóžOÓ¥ylšÏÆÏs§höú «}Ö•U\0–ÏÑEWÿ„ãT™™¼cn¯ý϶H?A+Ýê;‹ˆ- yîfŽPeä‘‚ª�RO€Ùx¡eð—Ä+_yR>›t‚¶ŒgiÆÞ%#×€;�mÿ„_Wß÷~Å6~› s 7 zyòcéŸÿ]gø¿Çšf§ Ë¤è3=õýøòU"�†Õ=s�:ŒŒ{×]áMè±ÓŸlI™1ýö%›õ$P?iúæ§áÓoáë—·¾ó•·¤Æ#´g#pü+Ì¿á ø­ÿA«¿ü7ø×¹Q@š`6úUœ7¿=Üp"NÇæ,á@cžüçšµæÛÿpß5^_õ¯þñ¦P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”PØä„¸ 7o––G…_ Ÿ¦jµ¿úõ§]®ü(O6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾iâH|¢v�¹éŽõF¦ñêßïP¾m¿÷ýóG›oýÁÿ|ÕJ(ß›oýÁÿ|ÑæÛÿpß5RŠ·æÛÿpß5VÿT°Ó­ŒÓ誖>‚’¸ gPmCPw÷HvÆ=½ʵNHù�¸'ÖjYì·,j>#½¾r‹x»$\Äõ5�ÌÌrÌIõ&’Šóå''vϪ§F�%h+-5[Û' Ã?…¾e?�®ÓEñ®¤3Ä‘\�ЕþŸá^NŽFŠE‘«©È#±«§VP~G6+J¼v³îzÇ›oýÁÿ|× â­8A~o _ÜLrØu»þ}:èôËÁ§ÅqÀb0ÃÐŽµbX’hš9P:0ÁSÐ×làªDùÜ=yá+]¯&�3¢º{ß ’Åì¦à“·ÐÕá�H¶<¸ÀõÞ+‰Ñš{G ~jüÉzèc×Uá 9Dͨ\/ÊX�Osý)l<*‘¸’öA&?åštüMtjªŠ@ �[Q Óæ‘æãó(J•-o».y¶ÿÜ÷Ím¿÷ýóU(®ÃÂ-ù¶ÿÜ÷Ím¿÷ýóU(  ~m¿÷ýóG›oýÁÿ|ÕJ(ß›oýÁÿ|ÑæÛÿpß5RŠ·æÛÿpß4y¶ÿÜ÷ÍT¢€-ù¶ÿÜ÷Ím¿÷ýóU(  ~m¿÷ýóG›oýÁÿ|ÕJ(ß›oýÁÿ|ÑæÛÿpß5RŠ}õ½�ý£ÛÌŸ+¡pTúŠó�JÁ´ë¶€Ê’Ñ”ö÷�tÚö°Öƒì¶í‰˜e˜ÿäÉ$’NIêMvRʾ±y»v=lj”UþËèC@©p=(¥ �ó{ÓÓÐõ?M""ð0ih¢¾†•5N e¡çÊ\Òr}BŠ(«$)ѧ™*&໘.Iàf›T/.~íÍDåÊ®yù–aOAÕžýwýnljßeþ׺†ÑvÅ =ÀŸÏ5ÏL¥&u=�:š)wõÏ_zžíª'�‘Ð× (A^qøºùŸ!�ÇK7ËWóÒmµý×ÕziB¬kºE_SZ•—m‘[ÐÖ§Zðó‹óG±ôéûÉ|WWô¶Ÿ�Š(¯ýk¨t*{ŠÎŽG‰·)Áþu§‚xk>éBÎUzé^þL¤¡9tºþ¿#ó¾;¦áìqTÝ¥«õ×U÷Yýå•Ô2}©PùPçÜÕ+Ûö³>Añ.cËËÏó²¿äI,ï1ù�ƒ¥jxoLµÕµ -nžD"Èñ‘�À�^Ýk HdšÙÒm.ssß4¡PÎ3ÿê¬å ÔO—s<· ˆÌqjsNjþó×ÜtIà+!&_R™“Ñbþy?Ê·¬¬ôE„ °æIN]¿ÏµrƒÄ:žOïÁöØ¿áYÒK$Ò$vw=KšÉ`kOJ³ÓÈû¬6I†¡.hE'÷þg£G­èò¶Ô¸‡>ãήy¶ßÝ÷ÍyUlèºÄ–“,9kv8äýÏ¥g_-å�57s¶xk+Å�ç›oýÁÿ|Óã’'b€qϪ�Mo÷ÛýÓ^IÈKæÛÿpß4y¶ÿÜ÷ÍT¢€-ù¶ÿÜ÷Ím¿÷ýóU(  ~m¿÷ýóG›oýÁÿ|ÕJ(ß›oýÁÿ|ÑæÛÿpß5RŠ·æÛÿpß4y¶ÿÜ÷ÍT¢€-ù¶ÿÜ÷Ím¿÷ýóU(  ~m¿÷ýóG›oýÁÿ|ÕJ(ß›oýÁÿ|Ô¡£òw6zb³êÚÿÇ‘úç@›oýÁÿ|ÑæÛÿpß5RŠ·æÛÿpß4y¶ÿÜ÷ÍT¢€-ù¶ÿÜ÷Ím¿÷ýóU(  ~m¿÷ýóG›oýÁÿ|ÕJ(ß›oýÁÿ|ÑæÛÿpß5RŠ·æÛÿpß4y¶ÿÜ÷ÍT¢€-ù¶ÿÜ÷Ím¿÷ýóU(  ~m¿÷ýóG›oýÁÿ|ÕJ(ˆñn‚-n^þÉI¶�åÔõmþ¹jõò5Íê^µ¹c%›ý�Ï;1”?á_9�Éå):˜~½?ÈÊPꎊݗ´m„Ž)GªHóÅ,>Õdl:Eõgùf¼¨boofþâ9_cŠë§ð_•¦ÈÑÎÒݨܠ )õZäˆ �Fê F# WÒª­q4ÖâQEÎ ¢Š(Ö›oö½NÚ d<ŠÓ<þ•ì>m¿÷ýó\/ƒ´–Ru)—aõoéù×__[’áÝ*rÞ_—CzjÈ·æÛÿpß4õ’¬UF^*�Mú©~‚½’É|Ûîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ�6ßûƒþùª”P¿6ßûƒþù£Í·þàÿ¾j¥oÍ·þàÿ¾jXž6Ï–õãŸV¬ú¿á@2ÛäåFݤómÿ¸?ÿ}¾´”oÍ·þàÿ¾hómÿ¸?ïš©E[ómÿ¸?ïš<ÛîûæªQ@üÛîûæ¬)A1ÅfV”_ê“ýÑ@¢Š(¢Š(¢Š( ô4Pz¥EP^s¨ØÉ§ÞÉ©À9CýåìkѪ‹X.ãÙqH½ƒ•ׄÅ{ ;«¦mF¯³gšIÀä×{áû'±ÒÕe’F.Ê{g·ä*{}&ÂÖO2dWòGÓ5vµÆcUhòEYZ¿:² (¢¼óœ±Ý?Z–¢ƒîŸ­K@r?ä˜x‹þ¼ÛúW]\ï�t»ÍkÀšÎ›§Ãç]ÜÛ4qG¸.æ=²Hñ4—ð†4�áN€Bƒ 1Ç©‘‰5Èx6Ïíã'(7%¯ÊqÓ&,×}ðïI¾Ð¼£éš”Eå¼%e�z¶Ó¸žªH={ç|3á]kOøÑâ]Yyz]í¸KyüÔ;ÏîøÚá÷OP:P/íü!zIÇ#SQŸûg%_ý ¿ä™úý‹ÿf«|+­x·Âú}ž‡eö»ˆ¯ÖgO5#Âqœ¹©Ð|Bð�ü&޺ђu‚v+,8ùC©ÈÎ;Gã@š7ü€ôÿúö�ÿAå>u“ãÿŽ �@ˆ=C ?¨¨-nþ6iE¾‡…¦\�A eF* `1ÀÈÊýA5oáÃÿxGÇzÕî¯þ‘Õªÿ§yŠ|阫¿ÝÃn gï@Ç€¼]á�êÚ÷€µK  Ô¥3\é÷ƒ‚Ù-€GP 69RÇ4'Ä�KK×´Û/ˆž ŠÂI¥ m¨Ã¶XÑò9{àœ6GUQà¿øÄÚ­÷‚ÃQÒõLÍgtÁJ’%zn ÜŽ¢¤›Á~<ø…­i·7~™¥XJ%V�¹¤·Oõ2Éüœ)aËŸÍ«¤ñ¯Ã»Äø;ká ÛµäÖÒÆÀ3¤eÎâÎıd’qžõÒkþ ƒÅŸ-ü=¨“éoÉÃ2.3è{ƒê  v+ÏŒÐÄ‘E¡øM#E ª­ €~ò³ü+á?¯ÅÃâÍ~×JµÛ´W)c1Ã|€)ÚI=UsÏjKø]^´M"?GÕ¡…|¸¯å”n 8Ë©8«Ÿ\×Að÷À:އªê&ñ-ò_x‹Qdhþä)ÁÚ8€qÀ  C¢Š(¢Š(¢Š(¢Š(ªš¥üzV‘{¨Ì ŠÒ�ÀîKåVë?^ÓŽ¯áíOL ÞZKn í½ ÿZð¯†:?‰>!x±*kþ:¸�ÒÙ7$¿…Ÿ «žåc?Q@9øw'Â?ìÏøcU»&ác•n ä þ2‡Gq_DéwñêšE–£ÄwP$è`Ê:ðŸŽ>Òõû|%¡É%åïÛ‡Ú<¸ØeʈÆGÌňé‘Å{‡´÷Ò|3¥i²^ÒΨ�Oò  *(¢€ (¢€ (¢€ (¢€ ­�eow-Ü6vñÜËþ²d‰C¿Õ€É«4PTîô�6þE’óO´¹uèÓB®GâE\¢€i kH¨Š0ª£aD‘¤±´r"º0Ã+ ‚>”ê(�¦‘¦ØHd³Ó­-ÜõhaT'ñ®QEQEgKþµÿÞ4Ê|¿ë_ýãL Š( Š( Š( Š(  mÿ×­:ëýwáM·ÿ^´ë¯õß…AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPSøõo÷ª˜Ç«½@ÑEQE^ýÌzu˯U‰ˆü�yÅz\ñ ­äˆôu*Šói¢‘£q†RA„W)j�%k–k®ƒh¢Šä=À¢Š(®ð““e:‹&Gâ?úÕÐÖ'…íÌ:Y‘† ®X}ã[uéÑV‚¹ñøöž&mw (¢´9Š( Š( Š( Š( Š( Š( Š( Š( ›$‚(žFû¨¥�ÐSª¦©Ÿì«¬Ï&þUP\ÒHqWv8K‰žââIœå�‹ŽŠ+ëIY¾ÁES¤rB1@â– žé!ù~óz ™4–§6+KIÔ«.UßúÜ…u��àiÆý1Â1úÕH`iÛ ÀO¥_KHPr»�©¬`êI%–âsÌm>hI(ÿ3KðÓ_¸§-Ü’Œ}Õô^µ�´,0c_Ê©qfP�%GQÜTΜ÷zœ®I™kˆ«/inÛ¯—oB¥>9^3•=zŽÆ™Ed��™§Rtä§f» Ä�1ì*ͽÈQ±úv5VŠÂ½W‡,Îü»4Äeø�¬Pzõ]ìѪ# ‚=©{�ÜÖP$t8¥G)"¿ps^ZÉ×6³ÓÐûˆqúi)P³êù´û¬k1X�»•’ì]Ù�RsOšáç<ð£ {1„)AS¦¬‘ó¯øPgûíõ¤¥¾ßZJ(¢Š(¢Š+J/õIþè¬ÚÒ‹ýRº(ÔQEQEQE†ŠC@¨¢Š(¢Š(¢Š(¢Š±Ý?Z–¢ƒîŸ­K@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ïï­ôÍ:êþîO.ÚÖ'šgÁ;QA,p9<Ò£Òõm?Z±KÝ2ò »gû²Âá‡ÓØûU©#IchäEtpU•†A¨"¼»[øõã’x¯ã/…¾MWÃvúÔ ÇŸmöoÝ?ü/�¡òdøt.AæH?ñß/4ézOß èÚäÚÝ®–�©M+Ìn&v�«1$•ázž@Ít—WVöVÒ\ÝÏF7<²¸UQêIàWŠÇãï‹~$ýÞ‰àØôô?òÚê&\{†�ªŸÈÖž�ð“X×ø‰âK�P«otV}ñ�ø(S@�£ëZˆ4ÔÔt»•¹³‘™RU*ÅN3Û óWê ++]:Î+;+x­í¢]±ÅUÀTôQEQEQEQEQEQEQEQE�/ú×ÿxÓ)òÿ­÷�2€ (¢€ (¢€ (¢€ (¢€%·ÿ^´ë¯õß…6ßýzÓ®¿×~Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@L?ãÕ¿Þ¨jaÿ­þõCEPEP\¿‰4v.×Öë�Ö¨íþ×ø×NX(%ˆu& ûu™m¿jƒ>ž`¬êF2VgNµJ3点çWm{áÛ+Òd‹0¹ç)÷Oáþ˜ÞŸwËu¥H®)aæ¶Ôúy¦kWgæs•¡¥irêw!@+ ŸÞ? ôúÖí¯„àF s;KþÊ�¢·¡†+x–(QQ¢¨­)á�ï#››AEÆŽ¯¸èãX£XÑB¢€…:Š+´ùæï¨QEQEd뺩Óm‚Å�>Ný‘ëS)(«³JT¥VjÝ—.õ+Køø�U»/Sù Ï(Ó·c÷Àzìãù×îò»;±gc’IÉ4Úãx™_Cè)äôT}öÛ=ÖúÖõw[Ì¯Ž u‡Z±^gÒA ’'dqÑ”àÔ�yu#n{‰Y½KšµŠÓTa<—Þ÷g¡éW e¯_Y¸Ì¦hû¤‡?‘ê+²±½†þÙg„ðx õSèkju£=�?�©†ÖZ®åš(¢µ8‚Š*+›ˆímÞyNMA¤Û²$fTRÎÁTu$à  úÞš�´ÝÇŸl‘ùŠãµ-VãR˜´ŒV ~HÁà‰ª5Ç,V¾ê=Ú92q½YkäzM½Ý½ÐÌ$˜ëµ³Šš¼Î)d†E’'duä2œ]®…«ÿiBc—â1ócø‡­iJº›³ÜåÆe²¡x;¯ÈצK–'�¾ë©Sô4ú+¡;jygœÏ ÛÎð¸Ã#5uzþŽ×?évë™@ùÔõõÊt5õjñ­%¿SÔ§QN7 (¢·4 ºŸÉ� ÷›§µeòO©5bñ·\0ì¼T1ÿ¬\ôÈ®:’æ‘ù†yŒ–3é·îÅò¯É¿¼Ö†1Aãõ§ÑEv%mÒéR�(*pVKDQE†]ÔB)È" «š†7§®*�qTV“Gä™ÍQÇU§ ¯ùêQEAæ…Q@K ;`êj*î´O¿Ð¡¸hv\2²™�PHÎ3ŽÕ«vsØõ2|1X¥ Ÿ ÕôÓúÿ‡9èÑc@ª0:¯ßiv.wÆ^>Ò(ÈÿëU ô!8Î7ƒº?V¦¡(ÓÙlVžŸ¢]^¸% P÷vü‡zê�`ÖÉ[©T Ñ¿1\ÕñÔ©5ý�xÁØá*{K9ïg@››¹ì©®±|7§ÉIzâ´ ¶†Ö=�D±¯¢Šç«™Á/Ý­LåŠV÷QËGá{ÖoÞI /®I?Ê·ôÝ&ßMCååå# #uúAWè¯:¶2­UË'¡Í:Óš³ šßï·û¦¡©­þûºk”ȆŠ( Š( Š( Š( Š( Š( Š( ­¯üy¡þuR­¯üy¡þtRŠ( Š( Š( Š( Š( Š( Š*«êV1¶×½¶VôiTçS)F?°¨¨âž)×tR¤‹êŒ©)¦ž¨›$‰m$Œd³)ÕÂx³X{›Æ°‰ˆ‚‡Çñ7ÿZ¹q¸¸áis½_DL¥di_xÒÞ')g›ÆÇjþ©ý*‚øÞð7Ík_A��rôWÊÏ6ÅÊWæ·¡—<�DÒüQe¨ºÂàÛÎx ç!�±­Êñúïü+«¾¡hÖó¶éàæ=Y{¨ÿ ö2ÌÒUåì«oÑ÷.¾Œèh¢Š÷M;ÆìŸÙ°1Q€f#¾z/õ®B´µòÇ^½Ý×Ì?—jͯ…ÇÖ•lDœº;}Ç<�ØVׇ5‡ÓoÒ7söiX+©è÷«Šç£ZTj*�Ý ;j{Mú©~‚ªÛ–6ÑûÛ~¸«Qª—è+ôî®t�ÑEÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÕŸWü*­Z³êÿ…V¾ßZJWûíõ¤ Š( Š( ´¢ÿTŸîŠÍ­(¿Õ'û¢€EPEPEPEP<”ôýhòSÓõ§Ñ@ òSÓõ£ÉOOÖŸE3ÉOOÖ�%=?Z}Ï%=?Z<”ôýiôP*…´Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Òÿ­÷�2Ÿ/ú×ÿxÓ(¢Š(¢Š(¢Š(¢Š([õëNºÿ]øSmÿ×­:ëýwá@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEP¹ÖtûV+-Êî¿1ý)9%¹p§9»A\¿Søõo÷« ŒàP݆¢Þˆš¸oJdÖ¥Rx�UGåŸë]´sE0ÌR#�U`kŽñE³EªyØùfPsî8?Ò¹ñ:ÃCÔÊmE¥½™‰EWôÁEP[¾ºhµ#oŸ’e<{Ž–k ¶<3 I¬Æàq³ËÖ´¥~uc—¢ðóæìvôQA8=+Ó>8+�ñlÌ–�B9cøúéÚ‡‰R1Y¨‘‡Fû¿‡­s×—÷7ì¦æMûs´`3]k-­Z¯ÜïÁÁÓ«“Z"�&ÑéM+Ž•ÁˆÊqcͺò>Šž.œÝ¶Z$í±lÀýçØ}Áâ³ëGB·k�bÜÂ7˜ÇÐþ¾+Î…ù•�1ö2æÚÌ諸ŠõOŠ Í¾Ñ-/˜»)ŽSüiÆ~£½iU{‹ë[^'�úÏåZR•HÊô÷ò*.Iû§;'…'÷w1°ÿhþ5‘¨Z ¼–™$”}à�ñõ®µõý8Få.8RBía“éÒ¸i䑞BK±$“ÜÖ¸¬ÃJ)=/Ödz—R•i7Wdf\ÿÇÃç¹ÍEVï#Î$CU+· [ÛQR¾½}OÊx‡<eVZ6Úôz¯òùÖó ¢?0àÔµ��nCƒWRýùÔƒíÍzpªš³>§)âL=JJž*\³]^ÏÎýû–è$’pV7Ð�ÆãøUIîžo—TªÅ˜Þ"ÁaàÜ%Ï.‰~¯a·ùÓ:¥EEÈÝÝÏÍkÖ�z’«=Û» (¥’'Ò‘šMè„¢¬-”Ì2@_©¤{I�gnáíUÉ.Çsʱªî”­èÈ+Ô¼=jÖš ¤N0Û7‘þñÏõ¯3¶ˆÉ:ñœšè§|[wÛ'ϳ‘YUÂμl��¢á|¾sSĽËõýþ›±n ¹õÅrš‰.!p—g͈ÿ>aþ5Õ£¬±«£Vwå×ÃÔ í#ê*S•7¨ê(¢¹ÌŠ( Š( ¦·ûíþé¨jk¾ßŠ( Š( Š( Š( Š( ±uOÙiŒbÏ8êˆxSÚ©x§^k5û «âv‘ÇTƒÜ× Ö¼,Ç6tdéQß«ìg)ÛDtsøÓP‘�•/n ΛŒµ4l¸‚AèSÈ×=ExO1Å7~vgÌÎûMñ}�ÛîTÛHxœ¡ü{~5Ö¡ÍŽGLñJë¼'âG€�.í÷@üBÇøÓèkØËó‰NJ�~»?ó.3èÎÊŠ(¯¢5 (¢€ ÍÔuË /åž\Ëÿ<Ó–ÿë~5Ÿâm|éÈ-m˜}¥ÆKp�pLÌìYس’IÉ&¼LÃ6ööT•å×ÈÎS¶ˆëåñÉ݈lxõy? °øáKb{¬rgô#ú×Ex¿ÚØËߟð_äG<�RÓõ‹-MѦÀÉ�¸aøUêò(¥’ VX�‘Ôä2œ^…áÝpjÖæ9°.¢6?ˆxW¹—f«ý�Ei~ Ò3¾ŒÛªZ¦©•hg˜äžV>•v¼×Äz‹j¼¸lÅ1Æ=‡Søšé̱ŸU£Í‰è‡)YêZåö¦çÍ”¬]¢C…ãøÖmWÆT©:’æ›»0nä�Ï-¼‚HdxÜtd85Øè)7%¦ G˜Ü$½7Cïï\U¾W >h=;tcRhöÀ¯!’F–W‘ŽYرúšô�j ¨é¼‡2Æ|·>¤wü±\«fÖ�Å» rWÝO#ô¯_:—¶£J¬~ÆßðK©ªL§EWÏnøFFOD£££)úc?Ò°«§ð]›I¨KvGÉmý£ÿÖÍveñ”±PQîTw;š(¢¾èè8¿é.³�J%&6eÇð‘À?Jäë×ÙUÔ«ÊF# Šç¯<apåày-Éþå#þ5ó¹†Q:•Z=wFR…ÝÑÀÖ·‡ô—ÔõÊŸ³ÆCHݾŸ�tVþ ´G{©eøTÏó®ŽÚÖ 8x–8×¢­eƒÉjs©WÑ.�Â4ßRZš/õRýCSEþª_ ¯§5!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«V}_ðªµjÏ«þYþû}i)_ï·Ö’€ (¢€ (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@VGŠštð~¶Ö¹û@°œÅŽ»¼¶Çë@Câ‹*ñ?‰'Ð>Xù«!ï|µrøà°ßò"g¡n¼téRü1×!ð·�äÐüs§ˆ¬'¸amz!HˬHù]qŒ‘È÷é^ÙÖ¼‡öŠK#àGŸgÚ–ù¹þ.U·cÛŸ ¯Fð“NÞ ÐÚç?h:}¹—=wykŸÖ€6(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÎ—ýkÿ¼i”ùÖ¿ûÆ™@Q@Q@Q@Q@Ûÿ¯Zu×úï›oþ½i×_ë¿ ‚Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š+/ÄF×H”©ÃHD`ýzþ™¥)r¦Ù¥*n¤ÔS [פ¹‘­­\¬‚Êyþµ`ÑEys››»>Æ…Q‡$U‹KÛ‹„¶ò=Çfö#½W¢¥;j�%%i+¢Iæ{‰Þi]ر¨è¢�¤’² (¢�…Q@_ÑPɬڅê?—5B´`i4»_´¶âu",õTîß�AøÕC{¾†5îàâ·z#²»Õl¬NÙçPÿÝŸÈUXüG¦HÛ|æOvBpä–bÌI'’OzJÝâ¥}æÇ'¢£i7sÓQÒDŒO!”äVeE,Ä$žÂ¸MV“N¹Uf&ÝÎ}=Åt>'º0éb4<ÌÛIÝê¥oÉÁ˱æÕËçN¼i_IlÌm[Ä]ÈÑ[;En8ÈáŸÿ­íX”Q\2›“»>–�Q�,‡Å,�H$‰Ùte85ÑÙßG¯[>ø…¸ë u?ãüë™§Å#Ã*J‡„0>âœ&ãèF#ªëI-ŸbÍö—u§ÈDÑ��¤^Tþ5N½. EÅ´r�ĈQY:Ö†—± -‘tì�O­o<6—‰æáókÉB²·™ÅQO– �Ç*28ê¬0i•Ê{)¦®‚»­O[-=\�ßL>{z ÃÑtn%K‹¤)œ…a‚ÿýjìk³M¯yžk‹Rý̯ùsž%Ô™1cc#2‘éØWG^{1žþâSüR}3Å{yu:¼Ï¡åá ¥+¾…z(¢½óÐ (¢€ ¤×S­ãgsØv®×FÒWL·;ˆißï°íì+šÐf0ë`ðä¡üGøâ»ŠùŒnqQë©–3VQTžß˜QESÕ.�ž›4Êpàa~§ŠÆr’Šêy©]ÙúÞºÑÈÖ¶m‚8y¯ ®h’Ä–$“ÔšBrrzÑ_OB„(Ç–'©Nš‚² È¢ŠÖQRV’º4M­QZG¾ÉÊÝ·ãUfµe9�•ôî*õÄ~d ;�‘RørÞ-Fým.%*0Y@êØí^' ,$½¦n«¡óùœ°øšë™m%xM|Iõ‹î»|¯®¦&1ÖŠéüW©ÂÓ 6Ö„pa]öŒä=€®b»)ÉÊ*MXüëF+J�9s%ÖÖ%¶‰&¸Hä™aBy‘� ~UÔë1éºW‡¡ŠÄC4—hÀf }ânÃñ®F”FyPsŒÒ•>i'}X|J¥ Õ^Z_·õ÷’Ãm$ÜŽÔÕ‘§®9�çéV£ehÔ¯Ý#ŠuwÆ”l}ö †ð¤œ×;}níò·C:KQ”;‡§zµm…#ç=}ªz*£N)ݘ\‹…Ä{zK^‹t¼ÐQEg° P ž´´Q@’IYuž¹i,¥�Ž|¦{Ûó¹:ê¼+%¬ó‘�#=ñÿë®ÆÞÁßÈÇoftQE|ñçQ@Q@Mo÷ÛýÓPÔÖÿ}¿Ý4 Q@Q@QÐdÐEsZ§‹íí]¢²Aq à¹? ÿç&ñF¯3gí>Xþìjÿ^¼ºù¾‹å¿3ò!Í#Ò)’ȰÄò¿ ŠXýyÄ^%Õâl‹Æaèêô­3âöºÓnm®¡ $‘2¬‘ô$Žãµg ë4÷OÌ=¢9Ë«—»»–âC—‘‹†Š+ä›rwfER AÁ¢Šõ-ðßé6× rì˜o÷‡õz°|!ŸìÏO1±[Õ÷ØIº”!7»HéŽÁ\ïˆ _ø­|tú­í¸·’6Ógò€ œþìwÇ&»Ígö�Ѭ¯å·Òôk�F$b¢v˜B¯î£k}qYÿðÒ«ÿBŒŸøÿÚè=/áï�~"øŽ×Yø‚æÛN·9K#…,3�Šƒî�’ß1˜÷ÕPª@ ;WƒÃJ¯ý 2àÿk¯z Š( Š( Š( Š( Š( Š( Š( Š( Š(  éÖ¿ûÆ™SɦF!x$÷¦ýž_î~¢€"¢¥û<¿ÜýEg—ûŸ¨ ¨©~Ï/÷?QGÙåþçê(**_³ËýÏÔQöy¹úŠŠŠ—ìòÿsõ}ž_î~¢€ õëNºÿ]øRà ‹*³.÷§\C#Ë•\ŒzÐZ*_³ËýÏÔQöy¹úŠŠŠ—ìòÿsõ}ž_î~¢€"¢¥û<¿ÜýEg—ûŸ¨ ¨©~Ï/÷?QGÙåþçê(**_³ËýÏÔQöy¹úŠŠŠ—ìòÿsõ}ž_î~¢€"¢¥û<¿ÜýEg—ûŸ¨ ¨©~Ï/÷?QGÙåþçê(**_³ËýÏÔQöy¹úŠŠŠ—ìòÿsõ}ž_î~¢€"¢¥û<¿ÜýEg—ûŸ¨ ¨©~Ï/÷?QGÙåþçê(**_³ËýÏÔQöy¹úŠŠŠ—ìòÿsõ}ž_î~¢€"¢¥û<¿ÜýEg—ûŸ¨ ¨©~Ï/÷?QGÙåþçê(**_³ËýÏÔQöy¹úŠŠŠ—ìòÿsõ}ž_î~¢€"¢¥û<¿ÜýEg—ûŸ¨ «ÅŠN™Ã?‘®�ìòÿsõWQÒä¾°–Ü® ”äpG"¢¤y¢Ò7ÂÔTëFodÏ5¢Ÿ,O ¯ŠUЕe=A¦W–}šwÕQ@Š( а¶��¶“œôÄgšÔ±ð®§vÀÉ ‚>æNåÖ©BRÑ#•éSW”’3ôÝ6mNàÅ Ë9 Óÿ„J÷wúû}¾¹?á]eŽ�º}¸†ð:³2ÇÔÕŸ³ËýÏÔWd0Ñ·½¹à×ͪ¹¿e¢9Û [[8’áü÷…# ?õ�ârN°A豨Jë5Kø´˜CÜ}öû‘‚2ßýjáµ=Eõ;¯=ãTÂí}=ê+òF<±7Ëž"µomSUkÃ袌f¹T\�’=ÆÒÕ…tzÚ¼žÓflœ*‚~«ÿÖ¬£W•GØ„€ÍŒàz×u¶ÇW°k('��Pª7Ã5Ù %e 9E¯TyXÜL!Rœ–¶zþGEX¼²žÂåíùê=ª½q5mêFJJë`¢Š¹mlën×�€Rz;öþ§éM+„¤¢®Î·ûJ×HÓ­¢¸reX”yj2Ý?J |^›¸³b¾¦N•ròHóHÒHÅ�ŽI=éµ³ÄKìèyÐÊèïSVÎâ×UÓ5r"’5ó;G2ƒŸ¥_ŠÂÎݬ(Þ¡kÎ ‚®ïײêv,æšÎzŽÇüúVÔjó»IjpcðN„9é7ËÕ”T¿g—ûŸ¨£ìòÿsõÔxÄUç—‘˜ogŒõY~µè튥˜É$Ž+„×fµ¸ÔZKf-‘‡8à‘é^¦W&¦Õ´gV¾fŒÊ(¢½³¸(¢ŠÐÑ#2ëàvmÇð®ê°ü1¤M&õã Ê1»ëø×Cöy¹úŠùìª�k.šv"JSÓ¡cø”¤t.kwìòÿsõ™âÄ:ÓL0»xç©Ï¹ðîÕbüÌ£%)>‡E !€ äZú“ÕM5tQEô9¬Ë+—³½†å͆«·Rˆà>­À¬ÔF’EEf ï\¸†ž‡Áñf%XÝÏ®‹C…Óô«· *40÷f'è+±†íáHb]¨ƒUŸ³ËýÏÔQöy¹úŠàÄb§]ûÛT«*›‘QRýž_î~¢�³ËýÏÔW1‘/Ùåþçê(û<¿ÜýEEEKöy¹úŠ>Ï/÷?Q@TÖÿ}¿Ý4Ÿg—ûŸ¨©!†Df,¸Ê‘Ö€+QRýž_î~¢�³ËýÏÔPTT¿g—ûŸ¨£ìòÿsõqÞ-×9ÓmŸß0ïþÏø×atÖÒk‡O–$g<ö5ärÊóLòÈrîŘú“^&uŠ•*j”7—åÿΣ²°Ê(¢¾PÄ(¢Š(¢Š(¢Š(¢º ørMFq}Ï/÷?Q@QRýž_î~¢�³ËýÏÔPTT¿g—ûŸ¨£ìòÿsõ/Ùåþçê(û<¿ÜýEEEKöy¹úŠ>Ï/÷?Q@QRýž_î~¢�³ËýÏÔPTT¿g—ûŸ¨£ìòÿsõ/Ùåþçê(û<¿ÜýEEEKöy¹úŠ>Ï/÷?Q@QRýž_î~¢�³ËýÏÔPTT¿g—ûŸ¨£ìòÿsõ/Ùåþçê(û<¿ÜýEEEKöy¹úŠ>Ï/÷?Q@U«>¯øT_g—ûŸ¨©í£x÷nÎ(£ýöúÒTÍo)bv÷õŸg—ûŸ¨ ¨©~Ï/÷?QGÙåþçê(**_³ËýÏÔQöy¹úŠŠ´¢ÿTŸîŠ¥öy¹úŠ»"5¨€EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPY^'·¸»ðž³mh ¹–Æxá©sýqZµõä:}…ÍíÃm‚Þ&–FôUŸÐP‘þÏ6HðmÍäPÂu_µ¼w2bÕõ Ž~¹ô¯c¯“´‰ümâÏê¾"ð™.š³IûÑk"¤_ð2çk1êG©Î+¶òÿhOùíåcþïtW‚y´'üö�ò±ÿ ÷º(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÎ�Ÿ5ùþ#MÉõ4éÖ¿ûÆ™@ “êhÉõ4”Päúš2}M%¹>¦ŒŸSIE.O©£'ÔÒQ@Û“ç¯4ë¢|¶ÿëÖ�uþ»ð r}M>¦’Š\ŸSFO©¤¢€'ÔÑ“êi( Éõ4dúšJ(r}M>¦’Š\ŸSFO©¤¢€'ÔÑ“êi( Éõ4dúšJ(r}M>¦’Š\ŸSFO©¤¢€'ÔÑ“êi( Éõ4dúšJ(r}M>¦’Š\ŸSFO©¤¢€'ÔÑ“êi( Éõ4dúšJ(r}M>¦��O°ï|Oinå Cpé ùÔÊqŽ­šÒ¡R³µ5sw'ÔÑ“êk•O¶ïžÌmö“Ÿå[Z~¯i¨ŒBåd&6àÿõêcVvLÖ® ½%Í8èhdúš2}M%¡Ê.O©£'ÔÒQ@Æ…¥ûèØGpÞìß_ñ®FóNº°l\DT€Ã�ôZÆñ=¹›I.£&'~�?­sV£œ–ç­—ãªBq¥'x½=&Š(®éBŠ( ÷@™¦ÑmË•#�úVžO©¬ýÝ­´‹xØa¶î#êsýjýz°¿*¹ñX†�i¸íwù‹“êi¯ �Ù°ª2Oµ-TÕ3ý•w·¯’ßÊ›vW3„y¤£Üá/ïd¿¼’âB~cò�îŽÂ«QJN+ËŠ•I$·gÛ%q²Ñ!UsÉéO¢ŠûŒ žŠ×«ÛM°Žo™HÜ_»“Þ¼üUgù³Éʰ³Çb�j®öw~o¡ƒâ� Éw#_Ù&éHýìc«{�záÙY«¬#W²UK­2ÆøææÖ)ûÅyüú×%[‚å’¹ìf quh¾V÷]%­�Ã÷:´ÊÅZ;P~iHë쾦»¸¼?¤Àû’Æ�ï ßδ@ :WSuh#› ܳRÄJë²ÿ3›¿ð¸5� ÿTÇùÉ:.¤gØå'Øf»º–ßýzÑK1«g©ö4ëÊQ[#ŒµðÅëÈ>Ô Ôä‚ÇðÔZÛEgn°À»P~§ÔÕ˯õß…CX×ÅT¯ñmØŠ•e=ÅÉõ4dúšJ+˜Ì\ŸSFO©¤¢€'ÔÑ“êi( Éõ4dúšJ(r}M>¦’Š\ŸSFO©¤¢€'ÔÔ¶äïn„Ô4†òÚÈ3ÜÜG í8.ÀgéIÉE]€ìŸSFO©¬gñNŽ��µçééV-µÍ2í‚ÅycÐ1ÚOçŠÆ8ªvSWõBº4r}M>¦’ŠÜe oqÐï@'ýK*òêõÙ¢Yà’'û®¥OÐŒW“Ý[½¥Ô¶ò –6¦¬ZIlUÉõ4dúšJçu?ZY»El¿i�pH8Aø÷ª¯ˆ¥B<Õ�6–æÕý¢j3ZÊ~Yô=�ç^]wi5•Ô–ó®Ùàûû�jÛêlÙT·QèŸëUï5ÈõdUÔ-Ud^x8eúƒÔ{dWÍæ8œ.-'i.ëFe&¤bÑWN—rñyÖÉö˜¿Î>£¨ª�¡Ã#)ˆÅxÒ§(ÚURÌA$œ;ÒQP#¾ðþ�earÌÑ=ñäåÁÙ쯽ty>¦¼zµ´¿Þé’(4°w‰ÎF=½+èpy½ISpå]Ö¿y¬f–‡¥äúš2}MV²¼†þÒ;˜(ãñÐÕŠúHÉI)Gfjex‡Vm+M/ýü‡d~Ç×ð¯5wi�س1É$ä“]G�åckð¬E‡ÔŸþµrÕñùÅyTĸt‰„ÝØQEåY±¾›N»K˜§§fÁö¯Q³»KÛ8®b'dŠ{{W’×àÙZM ©ẹ́逭{¹y*®‹Ù«üÍ)½ltY>¦ŒŸSIE}I°¹>¦ŒŸSIE.O©£'ÔÒQ@ “êhÉõ4”Päúš2}M%¹>¦¥ˆŸ*^{ †¦‹ýT¿A@dúš2}M%¹>¦ŒŸSIE.O©£'ÔÒQ@ “êhÉõ4”Päúš2}M%¹>¦ŒŸSIE.O©£'ÔÒQ@ “êhÉõ4”Päúš2}M%¹>¦ŒŸSIE.O©£'ÔÒQ@ “êhÉõ4”Päúš2}M%¹>¦ŒŸSIE.O©«6g;ÿ «V¬ú¿á@Ø�íÉëI“êh¾ßZJ\ŸSFO©¤¢€'ÔÑ“êi( Éõ5£ú¤ÿtVmiEþ©?Ýê(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ §«ié«h×Úl¬V;»y b;R§ùÕÊ(È~jVÞ²¼ðNºÑéúÍ¥ÓÈ©3l(ØÃ¡?{¡ü1ï�\„d0ÇÖ¼._Ùº)Ø4¾-¹��€^Ðýž™ÿ ÏkÿCLßø?øº÷�ëýáùÒ׃Ã3ÚÿÐÓ7þþ.½æ€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3¥ÿZÿïe>_õ¯þñ¦PEPEPEPEP¶ÿëÖ�uþ»ð¦Ûÿ¯Zu×úï€ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(˜ñF¦ÊÂÂ&À#2‘ßÐW/Wµ–fÖn‹uóü;Uó*ÉÊm³ìpT£J„Ríp§Å+Ã*Éu9v¦QY�-_Fz•|5>9ø÷\Ì*ís~cö{¥þêG×þªé+Ó¥'(&ÏŽÆRT«ÊØ(¢ŠÐæ GE‘¬0Aî)h WÑ&Óåi#RöÄðÃ�¾Æ²kÓÈ`ò*¤º™<-#Ù¦ýÝT•þUÉ<5Ýâ{˜|âÑ嬯æ�;­ýB’âT¹ºB°)Ê«_ÿ­]¾‘§Û0h­P0è[æ#ó¨5ëö°Ó‰ŒâYÄ>ž¦”h({ÓèU\ÊX†¨ÐVoK²-OÄ6öa�|é‡PýMc7ŠïËd$zm?ãXDääõ¢²•y·½ŽÚ9nœlÕß™ÖXøª9\GyˆŸãNWñ«¡!%ˆŽvèA¯2®«Âºƒ8{;FèóØwµí¾Y†] pö´´¶èçõ '°½’åO÷—±ªéÖ½PÓmõ(|¹— >뎫\µß†ï-ÊŒ’Ä ’AÁÇÒµÃRöx¨K¥Ñ½,Æ�j.3v•¾ó*Š(¯µ9Š( ·|*Äj2¯c?¨ÿ®“–çuÅÁ` ?©þ•Ë�iP•Ì«»SgM\_‰íZPÏ�’ep0Gòüë´¬}vëOÍotK¹åU>òŸ_jù‰P•eÉva€®èÖRµÖÌâ(§ìêhØ(þÆÅÚö_yôŸ\¥}ÇÚ[=ÝÜP ù�±ôÍzB€ªt¹Ï ®ž€ì�›¶‡ãÑk¤©§‡�©«3ÂÌñ*µE삲õ�]tØ‚ pãåSÐSZnÁ�ŽFI¯=¼¹{˹'~®r ì+ÒÀá•iÞ[#Ž…>yk²!$’Iêi(¢¾„ôBŠ( Hdšô;8M½”ž¨�O×ËøsO[«£q!` …õ=«¯¯3¬¥%Mt8qS»å]Š(¯,å å¼qt#Ó ¶À-,›¾�Gÿ\WS\GŽÕ¾ÑdßÂQ€úäVøez¨òó©¸`fãä¾ör4S‚R@Î:ÓkØ??qi&ÖáE  I=…I·d>ó&U÷æº�Ä‚Æáì¯\ýœ·îÜóåŸCíü«E´M#ýìsííYìرêNiÖ¤¥O–]O£œjezOj’|ÍvÖIÿ_‘ì`†‚<‚)kšðeûÝi’[HIkvIþéè?C]-xU á'}VMÖ�P¢Š*€©mÿ×­ERÛÿ¯Z[¯õß…CS]®ü*(¢Š(¢Š*ާ«ZéP︘ýØ×–jv©¨G¥ØIs'8áWûÍØW™^^Ot÷ZF?€ƒÚ¼¬Ë1XUÉ dÿ'+Þ.Ô.Xˆ ÛGØ/-ø“ý1Y/¨ÞÈÙ{ˆ>ò­E|­\Uj®ó“f-¶^ƒYÔ­˜ïfì͸~GŠèô¿å–-F0ãÎŒtú�ðü«Ž¢´¡�ÄPwŒ¾Oa©4zôr$±¬‘¸ta�Êr§WŸøg\m>åmg|ÚÈqÏð1ïôõ®³Ä‘Ó4§•ïœì�Øžÿ€¯«Ãæ4êÐuž–Ý_�²’jæoˆ¦±(­ã‰«NŠ~ëݬQE` ¢Š(¬ðMã ‹‹2~F_1G¡ù�Ê»Já< >­,¸ùR" ÷$cùîëì²iIáû³xlr7´b-®ÔeFccéÜZã«Öo-"¾´’Úa˜ä>ÞõæÚ®�s¤ÎRU-?$ pßà}«ÉÎpr�W^+Ý{ù2*G[™ôQExfa^�ákFµÐ¡Þ0Ò“)^Ÿ Ìxòê%ÅÊ´Sžx2{ozô€: úL“(·^jÝùšÓ�P¢Š+è�BŠ( Š( Š( Š( ¦‹ýT¿APÔѪ—è((¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ µgÕÿ «V¬ú¿á@Ÿï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEC\:€ðþ¤t€§öY~ÈßõÛϽÇÞÇ^=k”ølÞ?huøNÑVMÑý“o“Óæßþ«þÖºÞÜiÞ ×o­$1\Ûi÷E íu�Šœ8 W)ð_Äz·Š<%þ³x×wBöHÄŒŠ¿(U a@Íq[ÿh?ùçþI�ÿh?ùçþI�{ÍàÛÿh?ùçþI�{ÍPEPEPEPEPEPEPEPEPEPt¿ë_ýãL§ËþµÿÞ4Ê(¢Š(¢Š(¢Š(¢Š–ßýzÓ®¿×~ÛõëNºÿ]øPQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEqÞ(±ho…Ò�ÝÍÔú0ÿ?ΰkÒî-⺅¡™ÆÝA®V÷·¹kGYS²±Ãèkе~hŸC€Ìiû5N«³G=Ej'‡uFlm¾å×ηt¯ Çi"ÏtË,«Ê¨ûª}}ë(ÑœžÇml} Q¿5ßdZÐ,ZËLQ Ä’ìoAùV¥W¡¨«#åjÔufç-ØQEV½¿·°‡Ì¸“h=ä·ÐSm%vLc)>X«²ÍÊÏâé ³Û ^ÆBI?€¦ÃâéÃ~þÚ6_ö Súæ²úÅ;îweâm~_ÅeL?ãÕ¿Þ¬Û NÛQŒ´ó¼�à ÒñêßïV©¦®ŽÂP—,•™ s>/m™þ¾~¼WMYÚÖžu=£Oõ¨w§×Ò¢¬\ Ò:0UcKËoé ¬¥«{RW˜}€V·†�:ÜXè³ôÅd×[á}5¡‰¯%\4ƒl`ÿw×ñ­hÅÊjÇaV4ðò¿]>ó¢ €Ad(¯HùˆÖt·ÓîK(&ÝÎQ½=�fW£ËsÄÑÊ�Ѹ Šç¯<,‹ZLrNß�{xlÂ.<µt}ÎêX…kLæh­cáÍH�û‡fßÂ×ÀÜL‘¯¢üÆ»%‹¡w$lëAu1­me¼¸Xa]Ìß�¦»Ë+D±´ŽÞ>BŽO©îi,¬-ì"Ùc=Xò[êjÍxØÌ[®ùc𣊵n}Ænµ©gZ|˜ó¤á=½Mq.í#—v,ÌrI<šÔñæm]Ó?,@(ü²�d׫�¢©ÒO«Ôë¡_¸QEØl*³#RU�È#¨®×DÔÿ´-JÈ î;âkSÃó˜ux†~YCý?P+�AT¤ßU©�x)CÐë52F—tG_)¿•yýz<±‰¡x›îº•?�yÜÑ<¼N0ÈÅMråR\²�S,#Ñ¡”QUî®<•Ú¿|þ•êɨ«²ñxªxZ2­Uè‡Ëq<1ÉôYµŸ–1øš¤I'$äÑ\²­'±ùî/‰ñµ¤ý“ä�–¯æßéc ÑYTzú�cZµåJ..Ìû*5aZš©t±ìÌFl$/÷Á½ë·Xíß䯅÷°ø¥ÞéÛõüˆînLÇjðƒõªõ¢,#Ç,ÄÒ&š¯qyÛ#f™‡Ýµ”á?‰ž;%Í«Íת¹›ìÖŸ×‘ÓøÝ–Þòà�•ÙQ “üÅuÕ^ÊÒ8­­Æ#A�ïïV+çêÏžnGÒ`0ßVÃÆ‹Ý~{…QY�aRÛÿ¯ZŠ¥·ÿ^´·_ë¿ †¦ºÿ]øT4QEQEÃxÒô˨GhÉ î#ý£ÿÖÇç\Åjx‰‹x‚ðž»ñùYuðxꎦ&r}ßá¡Ï'vQEr’QE­«joa§#¶Z(Èsœgòó¬šyB!WìX�ËãZB¤£El÷ûÇq”QEf ¢Š(§#´n®§ § ûÓh’&„®Ã'›rãPߘ®[Æš{IWñ®|¿’O§cùçó®¢Þ3´Qž¨�!K,I4OŠa”÷÷˜œ?Ö(:rÝþgKWV<ŠŠµ¨Åo¡o¬OnŸækN=E¢ŠÍ×µ¦éN‡Ÿ’?©ïør ú*•#NrÙ·bŽ·âˆt×6öê&¹{'åO¯©ö®f_kR ͉ýÔEùf±‰,Ř’IÉ'½%|f'3ÄV•Ôš]‘ÎæØ¬Å˜±9$äÒQEyä…Q@sLÓ¦Õ/Þ×–nÊ=M^ñ„úMÆøƒ5£ýÖë´úÞ8j²¤ë%î¡ÙÚæ-QX*Ha–âe†g‘ÎTrj>§»ß è�a ]ܦۉFOT_ñ5Ù‚ÂKW‘mÕ•Ý—ô$i66ÁžCºF¾Ÿ…jQE}µ*Q¥l�Ò°Sd�%Œ¤ˆ®‡‚¬2 :ŠÑ«î3o i1o³'ûŽ@üª[oéVŒ;Efä%¿Ÿ©Es¬&K™A_Ñ •Q] (¢€ (¢€ (¢€ (¢€ (¢€ š/õRýCSEþª_  h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÕŸWü*­Z³êÿ…V¾ßZJWûíõ¤ Š( Š( ´¢ÿTŸîŠÍ­(¿Õ'û¢€EPEPEPEP^sâ¯�>ð�ˆ'Ñomµ+‹˜™Ö(Ù`g8#µwº�ô^™u¨]6Û{hšiÑTA_)èž¼ø‡¤øßÅ×*Ææ Ó[€x2îóG®mý±@Vi÷Ðjzm­ý«ï·¹‰f‰½U€#ô5ËøçâF•ಭ–£2]†òäµ�A\dθ<Šæþx‹û_À?Ù²¾ë�*S çËl²ý à5¥ñ§ÃŸð�ü8½xÓuΜEäXáAÞ?ï‚Çêw¶—PÞÙÁwnáàž5’7XdÈÔÕæ_¼Eý·ðê I_uÆ—!µlžv}ä?L¿ðô¹$Hbyd`‘¢–f=Mqz×Å Dñ­¯…$µÔ.u+†‰GÙ£FEi‰pG'ކ»««{+Yn®¦Ž x”¼’ÈÁUu$ž‚¾zøO øããµã …& fybÝü,ùH×ð@ß�«Ÿu­GÅ~6Ó¾èîUK¡¹Áá¤a¸nÇð¢üß�°  ½sö‰ðí…ÓA¤é×z¦Ó�7p†6ÿt�XþB¨Ù~ÒZ{\ˆõ? ÝÚ&yhnR?«^•àÿè> ÓãƒN³�®BþöòDYOrOaì8±«hš^»döz­…½ä0Rd �pzƒî9 <;âm#ÅzZê:5â\Û“µ±Ã#u”ò M®ëþЯu{´•íìâ2ȱ\�è ?�x§…üâ?‡_Z*ÆöçÃ7l#’`¥”FÃ*Xú£¾™õ¯Pø™ÿ$ÏÄ_õã'ò   ñ¦�ã­]WK†ê#�­ÊÝ"«n ¬N˜c ;×G^Eû9ÿÉ:¼ÿ°¤Ÿú.*õÚ+È[öŒð‚;)ӵ̃�õñÚõêù³ö~ÒôíS^ñê·j‘FP\B²;›¦AÅvðÑÞÿ n¹ÿ~!ÿãµgNý |)©êv–éúÒËs2B…áˆ(f`q'Nk¿ÿ„KÃô/i?øøS£ð·‡¡•%‹AÒÒD`Êëg*GB84'ˆ5»o è7šÅâJöö‘ù’, #8àZÀð?ĽÇÍw”.¡žØxnÑUÊŸâY²3Ç·¢�Š¿òK¼Cÿ^§ùŠù§Ã‹¬ø"ÏDñþŸ™-æKiÓ àò�ìËÐö#ØPØõËxßǺ_€lmnõ[{É£¹”ĂՈ g�̼VÖ‰¬YxƒE´Õ´ù|Ë[¨Äˆ{�P}9zŠòÚOþE�þ¿ÿ@4ìÖWqߨ[ÞDGoF.’©ÕQEw8fj:®¢K°1Íÿ=¿Ôw¬fðŒû¾[¨Êú• ×YEe*0“»Ge,~"”yc- ; ZÛ8’v3¸ä0£ðï[”QWF*ȵz•Ÿ5Gp¢Š*Œ‚Š( Š( Š( ]BšÍÆ{�Ãñ³«©ñ5ƒI^F2Pm�NƹjúlERŒZé¡éÑ’”QEÒjEC&±lfÝù Õ éü1`ÈöA�ÃlyôîkŸQS£&ý ëIF �`ëÚ3]¥[.fçQüCÛÞ·¨¯�£VT§ÏÍ„ÜÑæÄ$AA¬‹‡ß;Ÿ| õ;Í*Îøîš!¿ûëÁÿë×–\Æa»š#œ£²óìkÙŽ.5ãd¬ÑóüW‰s£N k¶þKOÍ‘QEψ (¢€7ü!vÖÚêEŸ’u(ÃßËõ¯F¯-ðêñ�^¾f!šõ*ó1©)§ä}¯NO (½“ýQEÆ}T�}¦ÊhGWBÖ§¢šm;¡§gsÍ™J1V08 ö¤®³YÐMӵͮ§ï!à7¸÷®L‚Áôø|D+Fñß©éÓ¨¦®‚Š(­Í¿ÃWmqbйËB@ý“ÓúÖÝs¾‰„73ò³*�Ã9þuÑWÍcRUä¢y•’U‚Š(®S ©mÿ×­EPÏ©Zi›f»™c^p:“ôêe(ÁsIÙrëýwáP×-㸞cöK6eèVÇè3üêšxâà7Ïe�ȯ>Y¾;s~ Žx�­ƒaâÍ>ñ„rî¶�ôó>éüǼ##‘]”kÒ¬¹©Êå&žÁEVÃ<ïÅ–æ zGÇË2«�Ëõ‡^…â�)µ Ä,63´w5ëÉv±$òUBA⽌§ CŸ>Ö·ßÔÒ¹ä”WYâ :H÷––�¹x”r§ÔOjäúóñ8j˜yòMÁ!¦· (¢¹Ä±á­9µ ^2W0ÂDŽ~�â­TÓ´»­Rq¼d�âs÷WêkÑ´½2*Ímáäõw=Xú×­•à%^¢©%î¯ÇȸFîåÚÊñãYh“º;�ŸLÿõ³ZµÏxÍKhŠGE™Iú`�ë_M�›†rŽöfÒØà(¢Šø3˜(¢ŠÙðÅãZk�®~I¿vÃ×=?\W£×•é*_X²Uëç§óê•õY Û£(½“6§°W5ãUc¤BGA8Ïýòk¥ªz¥ŠêZlÖ¤€\|§Ñ‡"½¤ÔòÅÑ´r¢º0ÁV¼ÂÓYÔ,œ47rcû¬Û”þ»½ ]�X€†;”:v#Ô{W­�ÌpõÿuÊût.2OC>÷Áv“9{YÞ ÿ —ðïT“ÀÒ–ùï�/´dŸç]¥¤ò¬$¥Ìáù�’&>™á« 5Ä¡LÓ�'o í[Q]´¨Ó£ZjÈi%°QE ÂŠ( Š( Š( Š( Š( Š( Š( Š( ¦‹ýT¿APÔѪ—è((¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ µgÕÿ «V¬ú¿á@Ÿï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEQEåüGý‘à5Òâ}·¬¢,Ï”¸g?žÑÿ®›á‡†‡†~é–ÆÄÑý¢äÕääƒô_ø xßħø›ñ¾ ÙÜùVöjm|í»ÄeAy_ƒòõÚ+£ÿ†Õè Þà#ñêÂ🇿5 JJY^»[ÆLÞB~¸ÂýX×ѲF“DñÈ¡‘ÁVR2=E|§ñáΩðÞM+]MvMMÚãw„ÆÐȘdêíœàú}ÚúsÃúÄ> ðöŸ«Ûã˼�&?t‘ÊýAÈü(Áþ;øã^¯áØ­µáh¢Üz•ýäL~¨Húµz_Æ_Â?ð×Q(ûn/±eü;¿ñÀõÀü{Ó'ÐüI xÖÁvË‹Œ:y‘�ñ“õ‡ÑjŸÅ-]~"øËÂÒä&Úæ(î¯ðùØ9>ëÏâhÐ~xwû áŭĉ¶ãScvùí< úmÿÀ�pÅïí3¯M8Ì�KyåîëÁØ?ñÒkè;x"µ¶ŠÞ HtU~Uó—‰f?hxµ»€WM¾q3?o.EÙ!ÿ€¶[ÃÖ€>‘¯ñGÇ«_ øšÿEÍpÖryfQt7çN:ׯG"MK«ÆêYNCЃéN ±ý£m/µ kAá©ÐÏ*Ä݃�Ä ýßzô_‰ŸòLüEÿ^2*ñ¯Œúõ¶§ñ[AÓm¤Y?³^4™”ä @Jþ/âqÚ½—âgü“?׌ŸÊ€8ßÙÏþIÕçý…$ÿÑqW®×‘~ÎòN¯?ì)'þ‹Š½v€ ùá·‰üMá�WU—ÃZêòLª³"[É/–“¦yë__WÎÿ³‡üŒ#ÿ®1ÿèm@?ðµ¾)ÿÑ;Ÿÿ×U«áŸˆÿ5_éö:§�æ²±ž`“\„¯®[�ø×±Q@wÅ_ù%Þ!ÿ¯SüÅqßt+/ü—GÔ#ßmu<èÞªr0ÃÜô®Çâ¯ü’ïÿשþb°>ÿÉ.ƒþ¾æþb€8ß…ºíïÿÞ|?ñ›mç›ýVáD‡î‘þ̃C�SZ¿´Ÿü‹:/ý~7þ€kgão€›ÄºÖôØÏö¾–¥ÆÏ½,#’¿Q÷‡â;×’øãÇ«ão†ÝH­cvb»«ü‡lŸð,sîµ}7áÏù4Ÿúò‡ÿ@§Yžÿ‘cIÿ¯(ôZtQEQEQEQEQEŸ¯iŸÛ~ÔôŸ;Éûu¤¶ÞnÝÛ7¡]ØÈÎ3œdVÿxiôs¨}»uÃÏæù>_Þ 1�Çû¾µÖÑ@Q@Q@Q@Q@Q@Q@Q@T—–Ú}¤—ws$0F2ò9À¥OE2cž扃Ç"†V# Ò»¤hÏ#*¢Œ–c€:Чi«i·ò4vz…¥Ã¯U†er?jåQEgKþµÿÞ4Ê|¿ë_ýãL Š( Š( Š( Š(  mÿ×­:ëýwáM·ÿ^´ë¯õß…AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP=VÔÞi“À£,Ë•úŽGò¯< ƒƒÁ¯O®o[ðóO#]Y�½¹xúdúŠæÄRr÷‘ìexÈÒnœÝ“9J)òE$.RTdaÔ0Á¤Di*)f=&¸O¢ºµÆ× øzÑ­<<¡ÆGóúôý1XZ?‡$2-ÅòíAÊÄzŸ¯·µv#þ=ýêíÃÒkÞgÏæ¸ÈÔJ”û�ÑEÔx¡EPEPE ]Û)Ã\D¡qM&ö \šŠEeuܬzƒšZ@QEQE!�æu/ 6æ–ÇLDôúéè­¨â'EÞ ¸T”ÑçrÚÜ@Ø– ÿ´¤REk<툡‘Ïû*Mz-èjÊß¾§GÖßc—Ó|4ìË-÷Ê£Ÿ(OÔ×NªB¨@Àµ-ç×ÄN³¼ÙÏ:’›» ŠââHyäXãA’Æ¥¯9ñN°ÚŽ Öñ·ú4 U@èÍÜÿ…i:²±æfXøà¨óîÞȽ©xÚwrš|b4ÿž’ ±ü:Ö¹i¦’âwšVÝ#±f8ÆI¨è¯V¡… ‰Æ×Å;Õ•üº}ÁEV‡(QEnhÞ»Õd‘Z^¦F,?Ù×¥Lç+É›PÃÔ¯5 JìÑðNœÏu& ëòF F}Xõü‡ó®â¢¶¶ŠÒÚ;x$h0 TµãÖ©í'Ì~…—àÖ‚¥×¯¨QE‘ÚQEÍëZ É+]Y®âܼ}óê+¤¢¶¡^teÍá7tyÃÃ,mµãuoFR ^±Ñnï\~í£‹¼Ž1ùz×sEwO4›�£3wŠvÑÚÛGil�D0ˆ??zš™4Ñ[ÆdšD�VvÀ¬©|Q¤DHûVò?¸„þ¸ÅxõqàïRI?6r¹ufÅÇ^xÝ·²µìÓ¿€ÿ¢xïÕv7Œ®‚¹ør0’ê6…cÀ-,g€}Ç¿µuõ‡âÙ z ªŸÏ?Ò£1¥Nxy:ŠöM¯P’VÔóº(¢¾ç (¢€ í|©4°É§ÈÙ1�ñçû½Ççü늭� Ècñ ¶:6å?÷ɮ춳¥‰ƒ]]¾ò¢ìÏHªWÓu7v¸·fÒw¡ÚÙü:þ5v¦·ûíþ鯵©N,Õ×™ÐÕÎIüd[乸ÐàÿJ±màý2 –r;;`~˜­ú+–9v.êžT2b·ŒG kŠ£S袻IYWR²]CNžÕŽ<ÅÀ>‡¨?�Z¬kM¦[,0\Ì8?Ü__ð¬qU)Ó£)Uøl&ÒZœÐÉo3Ã*•‘ V±¦R³3±f%˜œ’O&’¾ÚúÁER§ðvšÓ^›ç_ÝC�„÷cþúWs\…5—µ»[›6òœ&��ô5ÞWØäΟՒ†ý}MákQ^©fn©¡ÙêË™”¬ aeNÿçäð ÞÃ$7�2¶ ŸÓ5ÙUµÿ�#ô?θ±v¼¹§~â\S8{/¢¸kÛ�àcüMuC �°Ž$XâŒpª:T´Ž¡Ñ”ô#´¡„£‡OÙFÌj)ly5ÝËÞ]Ëq!ËHÅ�CR\@ö×2A ÃÆÅOáQ×ÂO›™ónshh—mg¬[J¤€\+{©àÖ}^ÑíšïWµ…Fs 'ØOè*ès{Xòït5¹êTQE~‚t…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Mú©~‚¡©¢ÿU/ÐP4QEQEQEQEQEQEQEQEQEQEQEQEQEQEjÏ«þV­Yõ€+?ßo­%+ýöúÒPEPEPZQªO÷EfÖ”_ê“ýÑ@¢Š(¢Š(¢Š(ªú„·0i×2ÙÛý¢é"f†Á|Çí\’ÉÀÉ5bŠñ¿ƒ_uïkzƽâ‹O#P¹\Y•$-¹·HÄ¡ d…ýkÙ(¢€9/‰~“ÅþÔt»xÃÞmZ‚@̪rO#+“ýêÈø9£ø“þ“FñžmZÚvkSçG hÛ’>F8Ãn<ÿz½Šå¾"øa¼]à]KI‰]2y¶Ù ~õyQ“ÀÎ6çКó/ƒ_ µÿø®}kĶf0[ùv�§ŽBY¸$lcŒ(#ŸïW»Q@rž>ð�ãÝ ì7la¹ˆ—µºQ–‰±éÝOøÕÑ@:éñ|aøf?³¬ì?¶t¸ÉªÆncý�¤H£Øà{V¯ü$Ÿ<\Ÿa³Ð"У“‡º’…�§2ï•Í{­óîµð>ûJOÝin©©%\4�wÊÀ€Ç Ãz“»>ÃØ¼s¦ÝëÖ´ë|ë»›GŽ(÷ÜÄp2Hñ5ÐQ@6øcÿü¦>�¢éqCló™ZkG;Èœ—ôQ[hý ¿çÊÎÏÿНw¢€8χRxÞM6ðøâ$ŽìL>ÎÅÊcŸõd޾µâÞðOÅÿÞ^\hZBB×XY Ïjù’>óñÖ¾œ¢€<#í´üùAùÙÿñT}£ö‚ÿŸ(?;?þ*½ÞŠæ|}¥_k~ÕôË|ëÛ‹}‘ǹWsdq’@�dü!ðî«áŦë6¿f¼[‰Çæ+ðO*Hýk¼¢€ ù³â'Á uüY=ß„ôÕ¹Ó®¿|cÇ�äüʰã<ŒtÎ;WÒtPÞ[MN¶�vM ´qºä0PÈ÷«ÔQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ rË]Ì zšñ¿ê^3¼ÑŠêšTzv™æ.ñªÅÛ<!‰#>ÕìÕÃüXÿ‘Oúø�ùšê4ù´Ïúô‹ÿ@Âx©¦ño�í|&³I�n‚k±Ác�Üþ@ô,k»Ðä^Ó?ëÒ/ýW áßù-> ß÷¾ÌvþqJOøMÒ495¤ÖWÖL%fÜ£¯Rp@ÉãÒ»? ë_ðÍŽ¤à %�Óz’­úƒRø“oü"ú¾ÿ»ö)³ôØk›øQ»þhsÓÏ“Lÿúè·¢¹¯iƵáÓi¡Ý}šóÎVó<æ�åÈÊó^eÿ ëâOýÏþ eÿ öÖ¿ûÆ™K¦i¥YÛ]þòæ(9Ÿïnp 1ÉëÎy«^|ÜÿÇET¢­ùðsÿyðsÿRŠ·çÁýÏütQçÁýÏütPJ*ߟ÷?ñÑGŸ÷?ñÑ@(«~|ÜÿÇE|ÜÿÇECoþ½i×_ë¿ š9bgWéK$±#á×'é@h«~|ÜÿÇE|ÜÿÇET¢­ùðsÿyðsÿRŠ·çÁýÏütQçÁýÏütPJ*ߟ÷?ñÑGŸ÷?ñÑ@(«~|ÜÿÇE|ÜÿÇET¢­ùðsÿyðsÿRŠ·çÁýÏütQçÁýÏütPJ*ߟ÷?ñÑGŸ÷?ñÑ@(«~|ÜÿÇE|ÜÿÇET¢­ùðsÿyðsÿRŠ·çÁýÏütQçÁýÏütPJ*ߟ÷?ñÑGŸ÷?ñÑ@(«~|ÜÿÇE|ÜÿÇET¢­ùðsÿyðsÿRŠ·çÁýÏütQçÁýÏütPJ*ߟ÷?ñÑGŸ÷?ñÑ@(«~|ÜÿÇE|ÜÿÇET¢­ùðsÿyðsÿRŠ·çÁýÏütQçÁýÏütPJ*ߟ÷?ñÑGŸ÷?ñÑ@ž4�aÑXz0Í"E_êãDÿtb¯yðsÿyðsÿXwv±R¦ñêßïT¾|ÜÿÇEg<"¬µÌð’Ÿøè¯8ÕïΣ©K?Hó¶1裧ø×f íç®ÈÚ�>yk°—º­Ýó6R´kÂ�ñªTQ_CF ÑVG¢’JÈ– ™­Ÿ|2´mꦺ=+ÄfY С›…”p3ï\½†# ñ³ß¹2§üHôª*PŽïH�ä\Ê£cœu#ŒþX5£çÁýÏütWÍÎ.q{£Ë’åm(«~|ÜÿÇE|ÜÿÇEHŠ• Íݽ”&[™’$Øãÿ×OÕõ«='O{™#ÜÝ0æì+Ê5JëU»k‹©71装Qèj顇uu{Fg›CîE^o§oSµŸÆÚllV(ç›ý  Ôçô¢i²0Ybž/öŠ‚?Cšóð2p)þT˜Ï–ØúWoÔéØùøç˜ù¾h«¯CÖío-¯¡óm¦ISÕOO¯¥O^Ia¨\é—kqk!GAä0ô#¸¯VѵËM_OK„Œ+�–DÀ;[ü+оÒÕl{ùfm g¹%i¯ÇÓüˆµ)Ͷ™u:ýèâf\q^I^ɪˆ®´‹È>y!u_—¾+Æë£nVyMÍí)ö³þ¿ ¢Š+¸ù�¢Š(®¢×Æ“ÚÙÁn-„Hs9ÉÀÅsqA$Çäzž•diçÈöJ‡µZ«žÎ[„ÌÚu0‘v}tWûÎËOñ¥�ˈî¢kf<ÎåüOjéA ¡”‚È#½y–R ÈÃnµ×x]Ù)Òî¾d ´Œ•#’¿NõÁ‰Áò.hžæ0ÅR®°ØøÙ½�¿¤þG_E[óàþçþ:(óàþçþ:+Ï>€©E[óàþçþ:(óàþçþ:(¥oσûŸøè£ÏƒûŸøè  •‹¯x‚-&?.0$ºa•NÊ=OøVæ¡©Ûiú|÷ODk�1Ôö�yÕÌ·—R\LÛ¤‘·1¯#5Ǽ4T)üOðDNVØ}åõÍüÆ[™šFí“ÀúÕ^Š+äe''Í'v`QE (¢€ (¢€ (¢€ ôÏ^›í æE[ŸqÿÖÅy�w>Õ,´Ý v½•Q~ÐvädŸ•z¦½|š·³®ÓvMj]7ftõ�â{sq \hñ'äyý3QÍãÝ-ÙÏ õ*ª?�sÞ!ñSêñ­½´FÞÛq‘—>øíí^Æ32º3‚•ÛVÐÒRV9Ê(¢¾@À(¢Š+wÂVæmz7ÇË ³ŸËÖ°€$€I¯K𞙓§¸Oô©ðÎû£°¯K*Ãʶ"/¤u¡pWf­sz·ŒÂG‚Åi€*Ò7ÝSíêjçŒ5¥²Ó½°Û=ÆWv9Uî~½¿:ózõ³\ÊTeìioÕ—9ÛDiO¯ê³±f¾•}£;éKˆ5[voeoið:Ì¢¾wë5¯ÍÎïêÌ®Î÷Eñ\Wò-½Ú¬3· Àü¬¡®Ž¼~·`ñ~±"yѺ¨o‰I?SÖ½¼wË\F¾kõ4�Nç¡×›xžvŸ_¹ÉáE€ñÍtÚ_Žà•Äz•ªDOüµˆey­sÞ,‰W^–xˆ0Ü*Ë„ƒúƒWšâ©âpªT�ÒzýÌ&ÓZtQE|Ù�QEªÅX2œr zݼžu´R®�¿1^QmÝ\Åc/#�{$ooI§ ¡GÊ;WÑä _¼}4ýMi•¨«~|ÜÿÇE|ÜÿÇE}©R­¯üy¡þtyðsÿKTñ�¤@¦á‰wXPe�áØ}j*T…8óMÙvEs ñ ?3åÒAOS0Ïþƒ[šWŠ4½Tùh¦)ñþ©Ôdýz奘aªË’×îüÉRLç¼_¤Âa:š8ŽQ…u?ÇØ~5Å× xöUm*Ùc\/Ÿ–ãÂqýkÏëæ³ˆÆ8§Ê­ßÔÊ{…_Ñõ7Òµ¸U §åuÇU=qT(¯:�IS’œ^¨”ìzôn²Æ²!Ê0 ¤w�U¼9:Â;b$\°ˆ�»~•©çÁýÏütWßÒŸ=8ϺLè[(«~|ÜÿÇE|ÜÿÇEh2¥oσûŸøè£ÏƒûŸøè  ”U¿>îã¢�>î㢀*QVüø?¹ÿŽŠ<ø?¹ÿŽŠ©E[óàþçþ:(óàþçþ:(¥oσûŸøè£ÏƒûŸøè  ”U¿>îã¢�>î㢀*QVüø?¹ÿŽŠ<ø?¹ÿŽŠ©E[óàþçþ:(óàþçþ:(¥oσûŸøè£ÏƒûŸøè  •4_ê¥ú —σûŸøè§¬±b�׊£E[óàþçþ:(óàþçþ:(¥oσûŸøè£ÏƒûŸøè  ”U¿>îã¢�>î㢀*QVüø?¹ÿŽŠ<ø?¹ÿŽŠ©E[óàþçþ:(óàþçþ:(¥oσûŸøè£ÏƒûŸøè  ”U¿>îã¢�>î㢀*QVüø?¹ÿŽŠ<ø?¹ÿŽŠ©E[óàþçþ:(óàþçþ:(¥oσûŸøè£ÏƒûŸøè  ”U¿>îã¢�>î㢀*QVüø?¹ÿŽŠ<ø?¹ÿŽŠ©E[óàþçþ:(óàþçþ:(¥oσûŸøè£ÏƒûŸøè  •jÏ«þ¾|ÜÿÇEI‘¾v.1׌Pûíõ¤«†h §?îÒyðsÿRŠ·çÁýÏütQçÁýÏütPJ*ߟ÷?ñÑGŸ÷?ñÑ@+J/õIþè¨<ø?¹ÿŽŠ°¤t#ŠZ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ áþ,È�'ý|GüÍwÝ•­ü Ëhna$.hî}ph¶ƒÿ"ö™ÿ^‘è¸O,¾ø…kâ¯*GÓn�CvÑŒí8ÛÏä¤zàפÇEÇ*"ªª0IKG"+£ 2°È#é@uâÿišžƒ.“ Ì÷×÷ãÉTŠ6TõÎ@ê21ï]w…4s xbÇN|y±&dÇ÷Ø–oÔ‘Wm4�6ÂC%ž�inç«C ¡?ˆr€ (¢€3¥ÿZÿïe>_õ¯þñ¦PEPEPEPEP¶ÿëÖ�uþ»ð¦Ûÿ¯Zu×úï€ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š:PErš¯‰diZ ƒƒ.2[éíXfþñ›q»Ÿw¯˜kžX˜§e©êÑÊjÎ<Òv=¦ñêßïW §x’æÞEK¦3Bz“÷‡ãÞ»hdIl<ÈØ21ÜV”êFkC“„©‡vžÝÆQE¡ÊQEW¿bšuË¢&#ò5çµèòÆ%‰ãnŽ¥Oã^w4MÏŒ21S^ÎU%i.§nèÐÊ(¢½c¬(¢Šê¼(ÄÚ\/`àþŸýjè+#Ã–Æ ,; X¿áÐ*n»«›@Gžã$ÿp�|íh:Ø™FÏ:qsªÔM ›û[?õó¢N§òHx�NÝ�1ÀõØk�wi»±f'$“’iµß ®š^óm›¬,m«&ñv¤/õÒ-o|§�$ÿ!øV0™¤Ú8Ï¥k2†R¬±¨á…a ¹Ítà ¡h­�šÄpÔ«cÕiÊôÛ»î»/Nƒ£…"Eü{Ó袺’¶ÇÕÒ¥ QP¦¬—D1¢�ÎYŸqVlî¦Óܵ«ùE¾ðP0~¢¡¢¥Â2Vh^—77*¿{~‘¯-ëˆ.IÏÝ#£�®GÄú;iº‹J‹þ�9,„tSÝhV(Á”�ÀäÚ»¸–cH�í1«¤¨7)õï�NkÉÄÓXYª�ø^èñ3¬®8ªVZ>ž¿äÏ(¢º�KÁWP¹{ÇÙ€ÃúÛHÔmÃlnW’ÞYÀüzV�« ­ùí|&ƒ´àÿO¼¥RA�(NÝOÒ’4V�+ȱŽìr@ü«u­´È,á67?h•‰ó\‚¤tÀÁè:Ö±iÍG¹Õ“à3M®^ºêíÑ-ÈUB(U–Š+¼ý^1QJ1VH)ÖõË£&u �BqM«zaÆ«iÆz¿Î²¯*oÐäÇa!Š¥Ë-Ö©öhï袊ùSŒ(¢Š(¢Šæ�§]j–RËÒb` 7qëR¶•~�´ÙÍŸd'ùWTkÓz_Sõ¬&6–*ŒkCgܧZþ³k�Ie#÷püÄûöçÒ‹?ÞÜ82¯‘rÝ]e¥¤66ë +…IêO©®,f2ƒ„Û*µh¨òÇrz(¢¼#€(¢Š(¢ŠÆñLp¾ƒ7œáJ�ѓݽ?�yÅtÞ3¾iu³SòB¹aþÑÿëcó®f¾77­¸–¢¶ÐÂnì(¢ŠòÈ (¢€ é|1á·Ôn¢¸»B¶€äÖOo¥^ð߆•Uooã HÌq7 {Ÿð®šãT³Ò¶Ëw0�yÂõ'è+ßÀåqQUñ.Ë{?×ü�c¬ƒ^Ð,µIs"yr…Iñõ®FçÁwñ±ò%†eí“´þ_ýzÒ¾ñäo16¶LW³Jø?�Ïóªñxå÷~öÅJÿ±&?¥o‰©•וæõî“ÿ!·g'„5flâAêÒé[:‚ቄ—ÓyÄË4áÔþ•«aâ-6ýNÙÄ.JLB‘øô5^çźU»W’b?çšñùœUÓÂe´’¨äšó (ÅjpÚœbVî0¡BÌà0ÉÅU­ fòÞÿS’êÙ$E�Êàž‡¡¬úùªÊ*¤¹]ÕÙ“Ü(¢ŠÌAEPEPEP‹B¦Q ­¶)HV?ÝôoÃüio¬.4ë–‚å °è{0õ«W­ }BØC{Ê<¾Œ9Aê+ÒÀྐྵ E;8Úß;è\cÌy-ÝOà›'ba¸š0{0�¬øZm:=»µÄ@~óåÁ_¥Ml¯J.N:.ÀàÑÏQEç�oL¶kÍNÚß ÏÓ©ý*¥9ãpÈ̬:8"ª )'-†zõqž7µ>Úì ¡S>‡9ÌþTÍÅG:ZßÈd‰ŽÕ•º©÷=ÅvV°ÞÛ=½Â�Ư°”éæXYF›³ü™¶“ZKEu7~ ¹I ´ž9#ì$ùXCO±ðT¦@×Ó ŒuH²Iü{WÎ,¯çËÉþ_y—#-x&Õã´¹¹a…•‚¯¾Üäþ¿¥uTÈaŽÞ†$  *ŽÂŸ__„¡õz1¥ØÝ++Q] ãµï\)kí9<Èœ–xWï!öõØÕµÿ�#ô?ιqxJx¨rOïŠgŒ›[…}�¡ÿºPæ·4 ]^L²ÞFÐ[ƒ’†lvú×Ey´r:PŸ4åÌ»lB¦„UTEE*Œ; Z(¯pÐ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*h¿ÕKô Mú©~‚€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«V}_ðªµjÏ«þYþû}i)_ï·Ö’€ (¢€ (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@¡¢ƒÐÐ*(¢€˜*–b$žÕçš÷Æ¿hs½º]M¨Ì‡ ,P:ƒþù!OàMy×Æßˆ·7zœÞÒçhìíÎÛ×Cƒ4�Ó?Ýîsé^-@LÙ~Ð~¸˜Gsg©Ú©?ë%u]­ŸÈô�]ÒüC`·ºMô7vç�ñ·CèGP}�5ðíoxGźŸƒu¸µ-6R M?$ÉÝX#Ú€>Ô¢³ô=b×Äž­dÅ­î¢&z�P}ÁÈ>â´(ÄtýjZŠº~µ-QH̨Œì@U$ö´WŒüKøÑ£Úøzk ê¿hÕ¦*«=º�°.r[q$��ŒõÍzŸ‡n%ºðÆ“q;™&–ΑÏVb€“ùÐ�ç?~ j:&­§x_ÑÞx‹Q圬)ÏÌGðÇ“€“\Ω¯üVø{ Z׈æÓu½z­Ê[ V„Ž¡ñŸ˜gë@ÙEe'ˆ´ÇðÀñ¸Ù†×í~i#Û»§¯·¯ågˆ¾)üDIµ K¦èš2ÈÉn.�3MƒêQ³èHgŽphÛ(¯7øyãýSVÖõ øªÒ;OØ ÄÇÂNœr¯ ñÁ#¯H Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  éÖ¿ûÆ™O—ýkÿ¼i”QEQEQEQE-¿úõ§]®ü)¶ÿëÖ�uþ»ð (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠF]ÈWÔb¼ÒXÚ^'db¤{ŠôÊçõͯÝZ�羇�ÞãÞ¹ñÜ•×CÔÊñP£7è™ÈQSKkq í– ½H«VZ-íó€±4q÷‘ÆÿáQmÙ#èåZœcÍ&¬jøF3\Ï�”(O©ëý+ªªÖ6QXZ%¼]$ž¬}jÍzT¡É�‘ÆWUë9­‚Š(­`¢Š(–Õ|4æFžÀ­É‹8ÇÒ±™~i³¸Ïýs5è”W<°ÑnëCÔ£›V§Y+œv�ᛉ¤x<˜‡ðçæoð®Ö$X¬|´P¨¤aQÔÃþ=[ýêÒ�8Áhrbqu1óûˆj…Þ³edÅ$—sލƒ$V^¿¬¼Nlí›kËGG°®b½Œ._í#ÏSD:X~eygü%V›¿ÔO�\ñ«özÅ•ëŠ\9þ?ýzá(é]sËhµîÝ<4ÐôªLŒã#>•ÀË©ÞÍÅ%Ì…cÆ~¾µS'9ï\ÑÊ¥ö¥ø,#êÏJ¢¸{nòÉÇï ±wG9ü�jì,¯"¾¶Yá<=Aô5LjÂN†¯UÜÆ¥SßbÅbê)Ó,Æd3J:¬C8úž•�â�¼³>ŸdåbS¶Yòç¸ßι:ÒŽ™sLù<Ç>tæéaÕí»ÿ#µo&ï—Ob¾¦låY:޳g¨]}¡"x]‡Î­‚3ê¬ +¶•(Ò—4æQâu)ós'äÒý,mdAî)k* †…½Tõ¨¬C)È=+фԑ÷yFoK1¦ì­%ºýW�´äÕ_K<*¦yª1þSM¬ËÆÍË@M{8Yõ2âdð¸&á¼�½?¤ˆÄò‡/æ6æ9$œäÔŸm›GåUè®e&¶gç4±øª1å§RIy6<Í!påÎáÒ´íæGŸâY55´þC’A Ž•tçg©êd™¼ð¸«Ö›ä–÷×Ñÿ] ZÔðÅÔC\0–h˜)ô<~@×5-ó¸Â ƒ×½ixF6“Äp0èŠìßM¤2*qu©I.ÇÐb¸Ž«SÃá5M«¿+ô=&¸_x~X®¤Ô-c/ ‡tŠ£”nçèkº¢¼*U]9]XìÇ�U‹+�Bá`¶‰�ϧAîOa^¡.�¦Îûå±·f=NÁ“V ·‚Ù6A q'¢(ô®¹c•´ZŸ=O†¥ÏûÉû¾[•´�54�:;U;˜|ÎßÞcÔÿŸJ½EÁ&äîϪ§N4à¡d‚Š(¤XQEQEQPKykm–æÏ£¸è®mçÿSi/ÓÔÓŒ\šŠÝ�ßͪ®•á»[‰éL(ñ6Ñ^ww=íÃOq!y©=½‡µmxºç~¨–‰ÄVÑ…ÜŒÿ,~UÏ×§šb¥R§²¿»>}Yswv (¢¼²Š( Š( ŠÒÐVÞMbn¢Y"””!»Óõ¯A·Ò4ëV œ*ãmɉ¯K–OxÉ$�‹Œ.y³é÷1Y ¹c1ÄÌ pXûOz«]·Ž}ŽÐÿ˜sõÇÿ®¸šÃ‡Ž³¥maIYØ(¢Šä$(¢Š½£Û}¯X´„Œ©�Óú õ‹¾ßîšã|!£¼*u× ë¶ };ŸÆ»+¾ßîšúü›éPæ’ÖZüºÓVD4QEzåœ�Šl´{H¼Ã K©>êÂÛsîGL:ãkSÄWMu®Ý3#s�@¼<þu—_ ˜U�JòpI%¦Ÿ™Ï'vQEqêZ4Íq£ZJç,b>¤q^c\Î�Ä¥¤sµ@¯U³¶vP[©È‰ç×­}AsÎ]-øšÓ'¢Š+é�BŠ( Š( ­¯üy¡þuR­¯üy¡þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦‹ýT¿APÔѪ—è((¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ µgÕÿ «V¬ú¿á@Ÿï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEPz(= R¦JþTO!Ú¥±ô§Ð@#‘@ ÝÜË{y=Üíºiäi�vc’3PÖ׋´¼3â½GH• ‹y˜FOñFyFüTŠÅ Š( ¦¿gÛÙn<so!%m¯�#öRªØüËƽb¼ûàÆ�.ƒðê×íR{éñ”Ž@`ÿ㪧ñ¯A  }Óõ©j(>éúÔ´R2«©V« zKEx·ÆÏ xwGøu-Þ™¡iÖw"æ%ÛÛ"6 9½K¿ò'èŸõáþ‹Zá¾?É/›þ¾áþf»Ÿ ÿÈŸ¢ׄú-hÊü8©ûNøŠâa¸ÙY€�qø3~f½+Ç–qßü?ñ ¼Š6Ÿ;{0Bʯ4´aá¯Ú~ð\þînÏlÇ’¨V‰‡â+Ð>&êÐèß õ뉘)’ÑíãÁ/ ظü[?� ‹Uœ~Ê’Ää]}”ó´Î®>•í¬ã±øqáÈcP éðÈ@þó¨výX×–Cá{£û-É”ßid:ˆL—~ïØÍzG­Zcáž…,L ‚ÕmdåZ1³òèEpÞ-Lý¥<+w níBK�â'ÍN ¿•{Ux¦ªÃÄŸ´Þ— ¯Ï‹f Ã)ÈVÛÿB‘ë^×@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Òÿ­÷�2Ÿ/ú×ÿxÓ(¢Š(¢Š(¢Š(¢Š([õëNºÿ]øSmÿ×­:ëýwá@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQECwr––²Nÿu8õ=…4›vCJîȯ¨ê–úl`ÈwH~ìkÔÿ€®jãÄ—ó1òÙa_E?™¬Û›‰.®i[.Ç'ü**ú >�8ûÊìô)ÐŒVº³E5ÍI"é�³¥lYx¬¸€nªéПB+–¢µ©„£5g¸¹Q„º’F–F‘ÎY‰$ûÓh¢ºv4 (¢€ (¢€ ³oªË¥ÛܘÉýäeG³v?…Vª×ßñïÿ�h©A¦pf•<YÇt™›EWùQEUû 2Œ‡·"¨U«õíþïõ­);IÏÕ•<ÆŸ/]Í5�|…gÝÙ…hô¦Ý-±Ò¼ó*»´¢0ŠyNäšÚ³J:ŸmÄtéUÁ8ÎI5ªõ_ðæ5#ÂÈ3Œ©èÃ¥G\ÍXüÎ¥)Ò—,Õ˜Ríù7{⥊Ùå9ÆÕîÆ’wRÁ#û‹À÷÷§Ë¥ÙÓõIB‹¯UY=#æûú%×½‘«;„E,Ìp$×¢x_Cm.Õ¦¸\\ÌG÷Óük�еA¥jI3Ư|¯•�êjõeu ¤# Žâ¼üeI/w£=ÎÂÑ›u›¼—NÞbÑEgêz´:lcpß+}ØÁýO ®BS—,UÙõÑ‹“²4(®:O_»e|´�süêÕ—ŠÀ�G|AãÌ^1õÓWR”yåo¼ÖT'vtôT0ÝÛ\¨¸Š_÷åSWi«£¢Š)€QEWPÔ-ôÛV¸¸l(àÕ� ® Sñ-ö¢ì«!‚ÑÆq‘î{Ó|Cª6§©¾ÖÌ‘ŽÞçñÿ ȯ‘̳9Õ›§MÚ+ñ1”ï¢ Ub¬It"’ŠñÌÍ1¬MqhlïÙ§‡ª¹åã> ÷ú¡4/ Ü« «Œ=EG[¾ž ®³ocYmç? oàP{g§å]4„å®É¿ÉÿZµ0¨®ÞãÁÎÄÛÝIôuþ~@Ù–ýŠú,Xýrk©äø´íËø¡òHã•YØ*‚ÌN$×yá�´ô7wK‹—UþàÿÑÓ´; 3æ‚,Éÿ=å¿úß…iW±—å>Â^Ö«¼ºvEÆÕžiâU+â°{°?øè¬ªëŽ›U/vÍ!$–§[¯éÇSÒe…e_ž?¨íøŒŠó2 ’ Ž5Üé~0‚êE†ö1žƒ”'ßÒ¤Öü/¢ísjËÁå�û¯þÞº1ØxcãíðÎín‡%ͪ8+J}U·b­e+{Æ7�Ò–ßÃú­Ë¶R§¼ƒ`�x?V­ÍËÈïèÌìÌÕVw ³1À©5Üi‚ßd÷ÇΗùxùTûúÕ�Ã1iŒ..MsÛåO§©÷­úú,»)P^Ó®ú.Ʊ‡V*k¾ß¦·ûíþé¯xІŠ( 5ñ%£Zk—,­æ©õ¯ëšÉ¯PÕôˆ5{o._–Eå$•?á\M×…u[w!!§f�‡?�æ¾C0ËjÓªçN7‹×CA§¡‹Wô�&m^ìà »™Èà »iáMRåÀ’!wi!ÍvÚV•o¤Úù0Œ“Ë¹êÆŒWR´Ó«£ç¥Å7¹_Hðý®�7©2ÎF ¬:}jÖ¢ŠúºT¡J<”Õ‘²VØ(¢ŠÐaEPEPV×þ<�Ðÿ:©V×þ<�Ðÿ:©EPEPEPEPEPEPEPEPEPEPEPEPEPEPSEþª_ ¨jh¿ÕKô Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Z³êÿ…U«V}_ð  Ï÷ÛëIJÿ}¾´”QEQEV”_ê“ýÑYµ¥ú¤ÿtP¨¢Š(¢Š(¢Š(= †€)QEÀ|Løgkã»$¸·t¶Ö-×l3°ùd^»ã=lšù£^ðˆ<3pÑjÚUŸS�.ÍÑ·ÑÇ󯵨 …-,nõ ÄV³\ÌÝ#†2ì^Íðçà�ä×�êÞ+ƒÈµŒ‡ŽÁŽ^SÛÌþêûu=ñßèEEA…P£Øb–€€: (¢€,A÷OÖ¥¨ û§ëRÐEP/ãÿÿÂsáwÑ~ßö-Ò¤¾w“æcom»‡ó­Ý*Çû3G²°ó<ϲÛÇý»wmP3ŽÙÅ[¢€9OøJñÍœ zÒÛ^[6ëkÈ$ˆÿQÀãÛŒW)Áy/ïm¤ñWŒ5M~ÒÙ·Gi6Q ÿk.Ù÷ƽzµÁ B�Avö�»qŒcÓå³ü{+û™¼)âíOÃö×Mº[X2éŸöpË�lä�ZõZ(“ðGÃý+ÀÖ×dy®¯®Žë›Ûƒ™$=qì2IÇæMu”Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Òÿ­÷�2Ÿ/ú×ÿxÓ(¢Š(¢Š(¢Š(¢Š([õëNºÿ]øSmÿ×­:ëýwá@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEV'Š$+¦"�ã”ù[u“â( úK2Œ˜˜?áÐÿ:è´«E¾æ”¾5s‹¢š_Ò€þ¢½yf˜HÏ‘Ïü¾óÜXZ­^袊ïM5tsìUý"È_j ‚c³ãÓÿ׊½yዘ؛VY“°' ?¥cz²r~a^¡á©ZoÙ³uWð�ü«Ì¢�æ•"�K;�ª£¹5ëm§Ø4Û{\䯀;žÿ­pãZåH÷øjöÓŸK[çrÕyæ£xn.渑¸,qì; ô:òÝUL7ó[gˆœ¯Ö¼Ú™”rü<ëZòvQõ>ÚU(¹uèW–åä8jú †Š+àq8ºØªŽ¥i9?ëî8ç9MÞLPJ�T�GB+¡ÑüWsfëë4öý7]õÎÑSCR„¹©»›[»±ÏK‡�ÆU‡B)õÆø/Ro2M:FÊ‘¾,ö=Çõü벯¶ÁâV&Ѝ¾~§D]Õªjs4«¹Tá–#ëŽ*ÝUÔ¡7]Ô+Ë6‘¾\wô¦*ãëÓÌóZ”ê:4t¶ì©Í§duQxâä?ï­"eôF*\×O¥ëš´E­Ø‡_½pËÿÖ¯.«6²é÷±ÜÂpÈyÞÁ®<.q^œ×µ|Ñ›[ž¯S[ýöÿtÕheYàŽd9GPÊ}ˆÍY·ûíþ鯭M5tlCES¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«kÿGè�T«kÿGè�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©¢ÿU/ÐT54_ê¥ú †Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­Yõªի>¯øPgûíõ¤¥¾ßZJ(¢Š(¢Š+J/õIþè¬ÚÒ‹ýRº(ÔQEQEQE†Š(•cÏ_îš<õþé  ôU�=ºhó×û¦€+ÑV<õþé£Ï_EXó×û¦�=ºhƒîŸ­KMG ê(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š¤öò4ŒBðI=i>Í/÷Zd¿ë_ýãL  ¾Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  ¾Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  0Á"J¬GÞ–x]äÊŒŒzÔVÿëÖ�uþ»ð û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýhû4¿Ýýj(o³KýßÖ±¼NÒÚhÎGkòc’AZuŸ­Y5þ™$H3"áÐz‘ÛùÔTMÅØß â«EÏkœ¤b¬#‚jJòÏ´‡¨§SPqšu}¶WÇ ?étO‰jJôéôÕ…Q]çËQ@'‡ü(uÛ¹[¿/d… ìÏ`sÔzÖN¯¦I¤jsYË“°å[yOC]_�û Ùþ0cë�ÿUix‡AMbÜ4d%ÔcäcÐ�C\OáYÆOCéVS F_´ciþ}4¢§º³¸±˜Ãs F㳿OZ‚»SOT|Ü¢âùd¬Â”c#'¬Øé×Z”â+XYÏsÙ~§µvðx>É4¦¶”î¸|1œTû{?ËÔ¯ {�ø,¶¾*ò‚ÑwÙùºtHeéQ½´,§(ÜqŠ–óÃ:µ„‡d2vx>lþjtM^íÂ-�ÇÖE*?3]_Z§(ÝØúš¹Û©eˆÂ^[[§ËBœv²Ov¶ÖÀÍ#œ(QÉ5«„5Éßh±dÚF ë]W‡ü6šOïçe’é†2: ôã[õæUÆZV‚ÐâÃpü*GÚW¼[ è»ksBðxÒ˜\M¶k¬pGÝO§ø×Aöi»úÔ4W ç)»Èú,>ž �%dMöi»ú×�^»I}pí÷šF'ó¯Y¯-ÖmMž±u aeúGó¯žÏâýœK²êlQ¢Š+æ BŠ(  O3/ˆl¶u2müÆ+Ô¾Í/÷ZóO [�v&ÇË27å�ú‘^‹_W‘E¬<›êÿDmObo³KýßÖšÐ:#;aUFI' ¨ëÅ o Ï´á¤Äyö'ŸÓ5ëV¨©S•GÑ\¶ì®yýóÃ-ýÄ–êV�”Ó5^Š+óùK™·Üæ (¢�u^ Ñ%»º:ƒ§îa8B‰¿úÕÌC³Î�̦á¸Ló^³ 1ÛÂ�Â�#A…QÚ½Œ›«Uö’Ú=<úB7w-}š_îþ´}š_îþµ•ªêöÚM¿™1,í÷#^¬ÃÞ¸«Ïjw.|¹Ý;,cŸÌ׿‹Ì¨aŸ,�ßdhä‘é_f—û¿­f—û¿­yl^#Õ¡mÂõÛÙÀaú×Q¢ø®;éÚñV)Û…a÷Xú{Ë›áëK“TüĦ™Õ}š_îþ´‡ý Zær(”³¶z*"p2kžñ>¥mý�<ÝBÒ¹U(® c<ñ]¸ŠÊ�)MôL¦ìŽO[Ö§Ö¯ši X�Äqç…ãY”Q_R¤ªIÎníœíÜ(¢Š� ¬Uƒ) ƒ�GjèõëIo´«-uS+$b9ˆìÀã?žGå\Ýz7†  á¨#™$�²¬2,kÓËh}a΃٫üÓÓó. úsEuú—ƒÈÒiò®ÓÏ•!éô?ãYCšÁl}•@þ÷˜¸þu�L»N\® új'ŒZ|sKï*GMà ´ã#Ò­jzdºUÂA;£HÈìè2O¥R®YFTäã-ÁÖŠ(¨QEmøB—SºYeB-å˜ÿû"µ£Fu¦¡vÆ•ÎûH³�4k%eä@™ôâ´a‚Df,:©j¯A�S[ýöÿt×ßÂ<‘Qìt‡Ù¥þïëGÙ¥þïëPÑTßf—û¿­f—û¿­CEMöi»úÑöi»úÔ4Pßf—û¿­f—û¿­CEMöi»úÑöi»úÔ4Pßf—û¿­f—û¿­CEMöi»úÑöi»úÔ4Pßf—û¿­XXØZ”Ç̓TjÚÿÇ‘úç@}š_îþ´}š_îþµ 7Ù¥þïëGÙ¥þïëPÑ@}š_îþ´}š_îþµ 7Ù¥þïëGÙ¥þïëPÑ@}š_îþ´}š_îþµ 7Ù¥þïëGÙ¥þïëPÑ@}š_îþ´}š_îþµ 7Ù¥þïëGÙ¥þïëPÑ@}š_îþ´}š_îþµ 7Ù¥þïëGÙ¥þïëPÑ@}š_îþ´}š_îþµ 7Ù¥þïëGÙ¥þïëPÑ@}š_îþ´}š_îþµ 7Ù¥þïëGÙ¥þïëPÑ@}š_îþµ$pH±ÈäŽ9ªµ4_ê¥ú >Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  ¾Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  ¾Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  ¾Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  ¾Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  ¾Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  ¾Í/÷Z>Í/÷Z†Š›ìÒÿwõ£ìÒÿwõ¨h  ¾Í/÷ZžÚ'�váŒâ©U«>¯øPmo)bv÷õ£ìÒÿwõ¨Ÿï·Ö’€&û4¿Ýýhû4¿Ýýj(o³KýßÖ�³KýßÖ¡¢€&û4¿Ýýjⱨ=@³kJ/õIþè QEQEQEPz(= R¢Š(¢¼{â?ƨt ™´¬WZ„d¬×/óG wP?‰‡ä=ùÂ5x‡^•¤Ôõ›Ë�ßÀÒ�ƒè£ ?@lQ_ Zê7Ö2‰m/n-䇆VB?kÓ|ñË^ÑgŽß]vÕtüá™ñçÆ=CѺúŠúrŠ£¤jöö•¥¦Ü-Ťë¹PGb:Ú¯Pˆ>éúÔµtýjZ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÎ—ýkÿ¼i”ùÖ¿ûÆ™@Q@Q@Q@Q@Ûÿ¯Zu×úï›oþ½i×_ë¿ ‚Š( Š( Š( Š( Š( f ¥˜€É'µrº—Š$24v *<Ö'è*ÿŠ.š 5bCƒ3`ý_é\erb*´ùb{™f�µ¨¯ÙÆ·©ÝöÉ3øcò­�/Äìò,7áFx�Œ}Gõ®^Šç�YÅÞç©WB¬y\Rô=>ŠÉðåÓ]i(å¢c}‡OÐÖµz1—2Lù:ÔÝ*Ž QEFaEPEPEPEPEPEPEPEPEPEPE ÕÜp™g�"ûõ?Ji9;!¥}V÷F±¿}òʼnWC‚~¾µ‡¬èözm’¼AÚGp¹vÎ «ø­C±#ûÎØýfêZÓêVéÀ¨U·Vö®ì>]5V3œ4ùôe‰�£ÌíêeÑEô@Ui/cC…ËŸn• åÁ,bSÀëïTëžu¬íâóŽ%�*ކÚo-õòÿ3§�Æ—PÙÇ[G¹.öbxúTiâ›é_æºd>˜þUÎQ\±§»ò£Â¡Ä8ÚSæ“R]š_¥ŽæÓIJ�Ýß*Ë 3‚ò5Æ]¶÷rÄŽ$Eo‘ÁÎáØÔeبRÄ�Ðf›O’ W‚°³ŒÚž?—’Ÿ-¼ûü‚Š(¦x�E¡I¬«W§F<õd’ó.�)Õ—,ߑ鞱6:*ß~_Þ·ãÓôÅlW¤x²; 2[ˆ$‘£È ¤tí[vž,Òî˜+Hð1ÿž«�ùŒŠùÉfXZ•UúFF!­d´6&‚„Ù/2êe�{g©úõ2’Šæ“²4I$Y¢¹yümhŒD6²È=X…ÿH|ojÌÖ²Æ=T†ÿ áþÓÂ^Üëñž•óù†i‡©MÒŠæü”¦š±Q_4dèãydXãRÎÇ@É&¯húbê·¿f7+ ‘•Éoa]î— ÙiCtH^l`ÊüŸÃÒ½[Sï-#ßþqƒd^Ñÿ²lyƒq.B;z¶(¢¾Æ�(Ñ‚§ ‘²VÐ+Ű™t HòÝ\ý3�ë[•ð¥ÄC ÊH¥X{œE/kJTû jêÇ‘ÑW5=:m.ùíå9FìËØÕ:øÂP“Œ•š9Š(©-´&âêTdÈáGâkÖ‰NêkÍü5-¼Zì p89{< ס_:}È_¼bl}pkéò8¨Ñ�E¿ùSØóM[P}OQ–á‰ÚNz(è*�WÍNrœœå»2 :QEH� ÝjþþâžvòÑBí^7{ŸSYôQW:“¨ù¦îÇ{…QP ¢Š(§opAÜÙ9éM¢€6´¯Þéò*Ë#\[÷G9 {Õè6×]ÛGq n�ÆT×’Woà‹–{;›rr"pËí»?áú׿“cj{Oa7töò5„�ìPñµ³-ý½Î>G�f}Áÿë×/^©©éÐê–Om7ò¬:«v5çz–�{¦HDñx•FTÿ…e›à§ ®´UâÿN:ÜÏ¢ŠÝѼ5u¨J²N� ¨9,ý€þµåQ¡R´¹)«²oc_Âú¤Úh»»¶Y$w%7çG:uÍujªŠT*�€À‘F�Ä‘F¡QU°êûŒ.zjZõ}΄¬‚¦·ûíþé¨jk¾ßîšé Q@Q@Q@Q@Q@Q@Q@[_øò?Cüê¥[_øò?Cüè¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Mú©~‚¡©¢ÿU/ÐP4QEQEQEQEQEQEQEQEQEQEQEQEQEQEjÏ«þV­Yõ€+?ßo­%+ýöúÒPEPEPZQªO÷EfÖ”_ê“ýÑ@¢Š(¢Š(¢Š( ô4Pz¥^}ñƒÆ2øOÁ¬¶rÔ/ØÛÀÀòƒwAÀô,+Ðkç?Ú.êGñ>�hIòâ³2¨÷g ÿ耴ño‡.´;é®!¶¹Ù½íØùX0Á Žª;P•é:çůˆ6ϬèSéz”ìÂÙg@Í(J9<Œg =+WÁ¿¼CmãCà¯ÚC¦ëºÖîÍÁ<ãƒ�Ç#f½M±Óü)á«kœEa§Û¬~uêáTcs7=Éâ¼x^Çñ3ã®™¨èhÒi cνÚB¹˜ìX€ cÒ€:ÿˆ¿5VÓ¼/á‹Hï•í¬ã±øqáÈcP éðÈ@þó¨výXÐ;ðóÇú¦­­êñU¤vž!°‰�„�8ä^Aã‚F1^‘^+âÐ4ÏÚS·p¦îÔ$¸þ"|ÔçðÛùWµPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPt¿ë_ýãL§ËþµÿÞ4Ê(¢Š(¢Š(¢Š(¢Š–ßýzÓ®¿×~ÛõëNºÿ]øPQEQEQEQEQEsÞ-…žÊ €È�È>ÙÿõW#^—qw0<2®QÆ®RÑ.¬$b¥ƒ´Š3ùúW"›¿2>‡*ÅCÙû;5±™E¯¥è77Ò+Ê�¿RÌ0[éþ5Ϲ;#Õ«V£Í7dnøZ‹I.Ãýd…‡Ó�ý mÓc�"�c�B¢€Â�^œ#Ë�ޝWÚÕ”û…QTdQEQEQEQEQEQEQEQEQEQE6I(žG8T‰öÁjòêM+’¢/÷Euž rš4Øþ"«ú×^ÎWIrº�}ŽÜ,œ‚¢{˜£8gôÕ;›¢ä¤g ÜŽõV»çZÎÑ>g2â¥J£§…Š•º½¾Kõ5ä$ýâ>¢¤2/”ΤKp¢Š(¢Š(¢ŠP2k:µcJœªKd¯÷N¤Ô#»Ðr¯sN¢Šü¯Ž«�¬êT~‹²>ÿ „§…¦¡êû…Q\GI³¡ëóéS*;4–„üÑÿwÜW¢E*MKG•‡q^E]Ç‚ïš[9¬ÜäÂC'û§·çüëè2\l”þ¯7£ØÖœºÆ©“bÓ¸ çå�?¼ßá^myy=õÃOq!wo^ƒØz Úñ…ÛO¬yù P÷<“ü¿*ç«—6ÆJµgM?v:|Éœ®ìQEy$ZÝÏep³ÛÈREèGò>Õé:.­¯b&,«òÈž‡ü y…oxFí­õ¥‡?$êP�qÈÿ>õêå8ÉQ¬©·îËOŸrá+;…^{â}]µ ö·�¿Ñ m ânæ»�Fsm¦ÝL¿y"f\q^Q^–{ˆ”c1ë«.£èQE|ÁˆQE$=¼ñÍaã`Ê}Åz½´ëskë÷d@ãñ¯$¯QÑU“D² ×ÉSúWÐd—<áÒ×5¦_¢Š+é�BŠ*½íäVr\Ìp‘Œû“ØR””S”¶@p~-¸iµéPŸ–T_Ë'õ5‡V/¯þúk©+HÙÀè*½|&§µ­)®­œÍÝ…QXˆ ä^©¥Þ-þ™áƒA¿›�μ®·¼)¨½žª–ìß¹¸;HônÇú~5êå8µB·,¶–Ÿä\%fS×4ÇÒõ)"Ú|–%¢oUôü:Vmzµþ�m©[.SrõuSê q÷ž ¼�ɵ–9“°cµ¿ÂµÇe5a7**ñz úͽ„5Y‘D=Z@–k~ÓÁöPÚH“±šif0è+–ŽWŠªþzè%Î Š»©iw:]ÁŠá3ò¸û¬=ª•p΄œd¬Ñ!ETˆ(¢¤†n%ÃH碨ɡ&Ý�Ñ] x;QK2˜ÌÇ“p@úôÍf�TWÚl.3ì„�κgƒÄBÜÐzù•”+ºð]£C§Mrà�=Æßp½ÿ2k3Jð…ÌÒ,—ÿ¹„rP³~]+·Ž4Š5Ž5 Š0ª:^ÖQ—Ô…OoUZÛB.÷c¨##Š+èÍH–Ú}ëjÞ¡5-RI-€(¢Š`5¿ßo÷MCS[ýöÿtÐ4QEQEQEQEQEQEQEmãÈýóª•mãÈýó  ”QEQEQEQEQEQEQEQEQEQEQEQEQEQE4_ê¥ú †¦‹ýT¿A@ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEU«>¯øUZµgÕÿ ¬ÿ}¾´”¯÷ÛëI@Q@Q@iEþ©?Ý›ZQªO÷E:Š( Š( Š( ƒÐÑAèh•x/í£É¿EÖ‘I�k+z¼ŸŸÏùW½V?Š|9gâ¿]è÷¼G:ü²“ŽU‡Ðþ}(âZ+_ľÔü)­M¥ê�æC•q÷e^̧¸?ýnµ‘@R€X€$ð  ÏhòkÞ3Ò4ØÔ°šå7ã²¹Ïà šûV¼‹à·Ã‰¼9júþ¯ �Rº�d0¸ù ˆòsèÍLJԊõÚ±Ý?Z–¢ƒîŸ­K@eø�^´ðLJ¯u›â~Ïiò«УܒãZ•ËøÿÂã� ¾ˆº�Ø’¤�/“æä)Î1¹{ã¿jó�ÂÞ ø¼°øƒÆ7ÒÙèÛì´›VÚsÃ1ô÷<žÛF+×ô}Mðþ�Ÿ¤ÙEikHâ\sêOR}Ï5äðüñ%´ÁÄýV(cP‰E"ª¨?V¯‡þø‹F×쵯ˆš¦¡¼¡ÞÖT�,£û§3úÅ´aá¯Ú~ð\þînÏlÇ’¨V‰‡â+Ð>&êÐèß õ뉘)’ÑíãÁ/ ظü[?�¥ñ¿€4¯ÙÀ—­-µå³n¶¼€âH�õ=¸År�ü’þöÚOxÃT×í-›tv“eŸö²íŸ|`ûÐ9…î�ì·$S}¥�ê!1ü]ùÿ¿c5é µhu�†z±0& Uµ�g•hÆÌÈ¡×bh" °G´mÛŒc˜¯-ŸàÃÙ_ÜÍáOj~¶ºmÒÚÁ—Lÿ³†\{g$zÐNªÃÄŸ´Þ— ¯Ï‹f Ã)ÈVÛÿB‘ë^×\Ÿ‚>é^¶¸û#Íu}tw\ÞÜÉ!ë�a’N?2k¬ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  éÖ¿ûÆ™O—ýkÿ¼i”QEQEQEQE-¿úõ§]®ü)¶ÿëÖ�uþ»ð (¢Š(¢Š(¢Š(¢Š(¢Š(¢Šo—mÛw®9§QEp¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢šî±£;°UQ’IÀÏ^x¥UŠÚDã“¡ü+j4*Vv‚.å?„èè®A|Qz-,=6‘ýkoM×mïØFG•1þx?CZÕÁV¦¹šÐ©PœUÚ5(¢Šä2)ê¶ÆïLž%b¹QêG?Ò¼îíÌv펧Šõ â¼a¤­¼BöäÓÐ�yé`1 Ó}v0Çb%KW—{?ò8ú(¢»OÌBŠ( Š’ÞE†â91"+ÈO =+~ ÏZF—I¹ò¤µ´ýWèGQQ9¨|[0Ó¯¥=eۯ˿æs”VÝÏ…¯ìÐÉs-¬Q�ãyp)¶6Ú$S¿¾i€?rØ)ú’ý){Xµu¯¡R­¨T\¿âi~f5ØIáí#X-&�|±·SÉð<Ь<¨îÁ¸µÛ빿¡b)õvõ7–SŠ¿¹eÝ4ÑÌT­ óÌR¥×xÓ±®ëLðm¥£¬·r}¥Ç!q„‡zÂñŒM¼Œ,‘)_Ã�é\9…O¬aªR§»‹ÿ†;hå•0|˜šú{ËNÞl¢Š+òóëŠ( º_“ý¯0íäÿßK\Õv~ ³e†âñ†‘}'ú~UèepsÅÂÝ5*˜>$R¾ ¼ Ý�üÀ¬ªë|i§0š-A*ÃË“�cý? ä«<“¥‰š}ï÷„•˜QEÆHV—‡Ô¶½f¯™ŸËšÍ®«Ášs=Ì—î¿$`¢V=!üë¯JUqŠï¸¨«³¬Ô¡7eÔ*2ÏõÇå5ìç>%Ò[NÔD_ôi‰d# =Ö½¼÷)F5—M¥EÔÅ¢Š+æLBŠ)ñE$ò¤Q!yáTu&„›v@ZÒ´ù5=B;di9v½Íz’ª¢Q…Q€=ghºDZM’Æ30Wõ>ŸAZUöyf ê´¯/‰ïþFð��QEé–ÉxÞå–+[P~V%Ûðà3]mqÞ8…·YΈCìx#ú×�›9,$íåù“?„ä(¢Šø£œ(¢Š*Þ”Œúµš§Þ3'óR¤‚ym§I¡r’!ʰíWM¨Í7µÆ�\¢³´MLjÚrN@¶E˜œÖ�~�N¤jAN;3¥;…QV%†)ã1ÍH‡ª¸È®SÄ~‰-…Î�oµ“&H×'#Ôjëª[õë\Øœ%—.«|� "0s#ÿuƽ.x-“l$kèŠ6ÒÎÞÆ ´Kÿ×Ö§¯{/ÀG u“ÝšÆ6 (¢½‚Š( Š( Š( Š( ¦·ûíþé¨jk¾ßŠ( Š( Š( Š( Š( Š( Š( ­¯üy¡þuR­¯üy¡þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦‹ýT¿APÔѪ—è((¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ µgÕÿ «V¬ú¿á@Ÿï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEPz(= R¢Š(Ä^ѼW§ý‹Y²KˆÇ(LJŒú«GùÍxö±û9æV}^ÛéäY#þ½ïš÷š(çk_ÙÏXy@¼×lb�»CÈ#·ùצx?á†ü#2^,o¨§+ssƒ°ú¢ô_¯'Þ»Ú(¢Š(ÄtýjZŠº~µ-QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEgKþµÿÞ4Ê|¿ë_ýãL Š( Š( Š( Š(  mÿ×­:ëýwáM·ÿ^´ë¯õß…AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP+âköyÅ’1€÷=«Ÿ«º¾µî·uó R¯¨ÃAB”Rìz”¢£�R©*Á”�AÈ#µ%¹¡ÝhׯÿOIþñNÇ÷#½hW;áLù?Ýܸü�tUó¨(V”VÇ—V*3iRÕ¬¥¦Ojp×å'³GëWh¬iÝT„jAÂ[=–'‚WŠU*èJ²žÆ™]·‰àÑnÜÈoâ†õF \°of ŸÎ¸¦X€Á‡¨ï^Õ*žÒ7µ�ÎqØOªÕpRMy5øöŠ(­0«7“i÷‘ÜÀØt9ö#¸>Õ^ŠMYŽ2p’”]š-j�ΧtÓÜÈY�AÙG VŠ)$’²ç)ÉÊNí�ŠY •e‰Ù$S•e8"½Úßöµ‹yÄ ˆx“°#³WšÔÐË$+ �ÙD‹µ€8ÈëƒùW™›âia°î¬÷éæÏg!«Z8žX|/ó;ÝGÅövŽc¶Crã© ù÷®WX×%ÖV5šSË$« ;¹íœÖ]ð3Î1r—4eËè}}XÆ´\&®Ÿ@¢ŠUÛ¸nÎÜóŽµæÊNRmîÂ)EY Eu1x5®"I Ô#x¤PÊÆ28>Ù«öž µ‰ƒ]\<øþø×£ §7ðÙwº4Pg/¤éµÐŽ0V y!(ÿjô»kh¬í£·…vÇÀØã¶°¶‚8!_¢�P�_M-´_Ûgþº¯ø×Ðà°t°Q÷¤¹Ÿõ¡¤b¢Yž®`xf@ñ¸Ã)ï\±á‹«i-Õ§¶ê Œ²ýGõ¯AVWPÈÁ”ô äZÛ�¥‹�½¿F9E3Çè¯WŸO²¹mÓÚA#z´`ŸÎˆtë+vÝ ¤·÷–0ç^7öïñ«zìÎHðÍÞ ë$êÐ[u,Ã ÃØZïííâ´·H @‘ Â�OwHмŒª£’Ìpf?‰4ˆßk^¡?ì«0üÀ¯W †Ã`V²I¾­Ø´”MZ†êÖÛv‚â0ñ·Pi¶·ö—ÊMµÄrã¨SÈúб]×…H÷L­ÎQðmÔ.^Å„ñöF 0þ†±ŸGÔ‘¶› œûDOò¯S¢¼Š¹ »Á¸™ºhó{O j·L3na^í)Û�ïé]†�áûm$y™ónÁ�ŽžÀv­Š­{Ÿe-Ô¿uAԞ·Ãå¸|'ï­u} –¤—0ZDe¸•"AÝŽ+ü]¤£`K#�UŒãõ®QÔ®5;£=ÓýÕì£ÐUJòëçµ­E+y’ê>‡¨Ùk:~ vÛÜ«?÷Êß‘ëWëÈаe$rí]ï…õ×Ôbk[–ÍÄc!�ñ¯øŠíËóo¬KÙÕV—NÌq�ôgETu}95M:Kf 1ù‘�ð°éW¨¯^p�H¸Kfi¹ä—6ÓZ\<¡IàƒQW©j:Ež©[˜òÃîȼ2þ5ÍÍàwÜ|‹Õ+èéÈüE|¦'&¯ ~ëÞ_‰‹¦ú�ØÛxCuxJÿv5Çê¹ýkI—I¾hÈ&9‰ýGøŠã­€ÄP‡´©"\ZWfuS‘GŠY˜à2I®2N¿ÀŶßáÊÇæ®¾²|;¥¶—¦�~þC¾OcØ~­_s—Ò•,4!=ÿÏS¢*È(¢Ší(*[õëQT¶ÿëÖ€ëýwáPÔ×_ë¿ †€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ šßï·û¦¡©­þûºh(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶¿ñä~‡ùÕJ¶¿ñä~‡ùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ š/õRýCSEþª_  h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÕŸWü*­Z³êÿ…V¾ßZJWûíõ¤ Š( Š( ´¢ÿTŸîŠÍ­(¿Õ'û¢€EPEPEPE†€"ó×û¦�=ºj½cÏ_îš<õþ鬽OUÓôk&¼Ô¯ ´·^²LáF}9ê}«ÍõO�¾±•£³ŠÿP#øâˆ"ÅÈ?¥zçž¿Ý4yëýÓ^+mûDøyä s¤jq!þ$Øøü7 ï|7ãï ø³ ¤ê‘IqŒ›y3£þzýFEu¾zÿtÑç¯÷MW¢€-£‡�ŠuEÝ?Z–€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (®{Äðx¦q xræÊÝJ·š÷–ÏÛÁ´~ vÆç^¹Ñ¢‘šòÚ1$£ocŸ^EiW“ü7¶½³ñö¹o¨Ì&¼HO� bÛ›z’rkÖ(¢Š(:_õ¯þñ¦SåÿZÿïeQEQEQEQEKoþ½i×_ë¿ m¿úõ§]®ü( (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9_X2N/QIG?±ìkŸ¯HtY‘Ô2°Ádç¯<,¬å­&ð?Aø×±ƒÇEAS©¥º�”k¤¹dsª¥˜*‚I8w­¥ð½él4�¨õÜOô­½7B·°a!>lÝ™‡è+ª®>ŒÓ»5ž"Z;’èö&ÃOHÜ~ñŽ÷úžÕ~Š+çç799KvyònNì+€ñ‰e¼™í,ä)j§k2ždÿëWUâ;¦³Ðn¤C‡+°÷Ž?‘5æPÇæÊ©ëÖ»pTT½æ|ÖyŠªç åú»$:y&û£ÔÕŸìþ?Ösþí\U ¡T`”µíÆŒRÔõðœ/‚§M*ëž]ui|­c.kY"¾òúŠ‚¶ë:{9C³E´~ª¤�íYU¦£ª< ÷!Ž*¾ü»5ÛþVнk£ê7Ž 9›?ÄWói;³"柪]é’‡¶”¨Ï(yVúŠôMV‡W³ó£d^$LýÓþåõµákÖ´ÖâLü“þí‡×§ëŠõ2¼tèÕTäý×§¡p•��F¨çš;h$šVÛ)f>¤®Æ34ZÕç þµ'ÉΜ%^´i½Š:‡‰µ Ù—!·‹øR.âzÕk}oR¶�:^JÞÒ6ðYôWšç&ïsêㆣò¨«z� ëðêÉå¼b;¥2Ž„zŠÖ–hÑðÊIúWšøzvƒ^³e?z@‡Ü?­z×úï»èTsާÍf8hЫhlõ$ûL?Ü?�£í0ÿpþBªQ[¿´ÃýÃù >Ó÷ä*¥oí0ÿpþB�´ÃýÃù ©E[ûL?Ü?�£í0ÿpþBªQ@þÓ÷ä(ûL?Ü?�ª”P¿´ÃýÃù >Ó÷ä*¥oí0ÿpþB�´ÃýÃù ©E[ûL?Ü?�£í0ÿpþBªQ@þÓ÷ä(ûL?Ü?�ª”P¿´ÃýÃù >Ó÷ä*¥oí0ÿpþB�´ÃýÃù ©E[ûL?Ü?�£í0ÿpþBªQ@þÓ÷ä(ûL?Ü?�ª”P¿´ÃýÃù >Ó÷ä*¥oí0ÿpþB�´ÃýÃù ©E[ûL?Ü?�£í0ÿpþBªQ@þÓ÷ä(ûL?Ü?�ª”P¿´ÃýÃù >Ó÷ä*¥oí0ÿpþB�´ÃýÃù ©Egx¸-׆®–4;“kôìÏéšó;"È÷½mÑdFG•†=Åy¦·£O¢_nPZÝ›1Iý½z8 ª/•Ÿ;šÓ• ],rWŒZ¿É�¢£ŠU™7)ú�J’½äïª>Ú•XU‚©MÝ=˜WaàÏÝÙÞHà”.ª8îÿ\kºÆ¥˜à î|-<øiZA =wú±^~e;Qåîrâ±4”• ûÏ[yßi‡û‡ò}¦îÈUJ+À9Ki‡û‡ò}¦îÈUJ(ßÚaþáü…yg‰4¿ìÝVO-H¶”—ˆúãðÿ ôŠ­}ao¨Úµ½ÊnCÈ#ªŸQ\† b©r¯‰lL£tyE¿¨øNþÑË[¯ÚbìSï¨ÿ Çk;¤m­m2·¡B+ãêá«R|³‹F 4ANDiQ³1À¹­?êw¬Zº)þ9FÐ?>¿…v:/†­ô²&‘¼ëŸïÂýõ®¼[W5Ì­ÿäTas_D·‹KÑíí è¹s�ËMyMÊî¥FûÊä¨5ëuÁø·I{[ã{æ ÎX�á~ÿŸ_νlë ûˆÊ HþEÔZÝQ_.bCRúí†q:1Ç  ŸåT+­ðv’ÆS©J¸UbÏsÜÿJëÀЕjñŒ{þE]�÷Úaþáü…bøªÝuhâCæÆDª1×Bjýöõ©*´Ý9lÑ»WV<~Šìõ¿ ¥{�;hfå¡'?ìŸé\Ëèú”oµ¬.sí#óñ8Œ zå”oæ¶0qh¥]G�í7jÍzêLp!ã«?–j¦ŸáMBíÁ�>Ív½øñ®îÆÊ >Ñ-­×j/¯R}O½z^]QÕUj+%¯«*w»4þÓ÷ä(ûL?Ü?�ª”WÕþÓ÷ä)²Ko,m‘nFYJŒU¨£p8-o³ÙÌòØ#Ïjy ]=±ßë\ë)V*À‚:ƒ^¿MdF9eR}ÅxUò:s—59rùZænšèy}†‘}¨¸ð1SÖFQø×¤èZmž‰e䢙%~d”¨Ëð«4W^ ,¥…|×¼»ÿ�ã‹i‡û‡ò}¦îÈUJ+Ò,·ö˜¸!GÚaþáü…T¢€-ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!GÚaþáü…T¢€-ý¦îÈS£ž7pª„íTª[õë@eš4|2’~”Ï´ÃýÃù ŠëýwáPп´ÃýÃù >Ó÷ä*¥oí0ÿpþB�´ÃýÃù ©E[ûL?Ü?�£í0ÿpþBªQ@þÓ÷ä(ûL?Ü?�ª”P¿´ÃýÃù >Ó÷ä*¥oí0ÿpþB�´ÃýÃù ©E[ûL?Ü?�§Ç4nHU#=*�Mo÷ÛýÓ@ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!GÚaþáü…T¢€-ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!R‰ÿ/¦+>­¯üy¡þt}¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!GÚaþáü…T¢€-ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!GÚaþáü…T¢€-ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!GÚaþáü…T¢€-ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…=f�•ˆRëÅQ©¢ÿU/ÐP¿i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!GÚaþáü…T¢€-ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!GÚaþáü…T¢€-ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!GÚaþáü…T¢€-ý¦îÈQö˜¸!U(  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!RE"I�‹Œ{U µgÕÿ q¸ˆ ÈR}¦îÈUWûíõ¤  i‡û‡ò}¦îÈUJ(ßÚaþáü…i‡û‡òRŠ·ö˜¸!V†PGB3Y•¥ú¤ÿtP¨¢Š(¢Š(¢Š(= †€2ï&6ö7¨ÉŽ6qø ׬ÌîÎÄ–c’Os_wÉËÆã*êT�Pká½[N—HÖ/téÁÚÎð¶}T‘ý(�Q@Q@}%û;ܼž Ô­Ø’±_–_mȼ~Ÿ­|Û_PüÒÞÃáẑH7×rL¹þàê­ùЬÁ÷OÖ¥¨ û§ëRÐYšþ�§xŸG›IÕai¬æ*]Ù3´†‚P+N¹oˆ,¸ðW…%ÖàÓÅðŠTI#2 ¬q»8=È�Tñ7‹tŸ†:6—gý—¨Ü[L6ég�F±ª�¼³8#žsƒ\ÃiÇ�þ*j>9’KkU‚&ÞÀL|m ½ÇaŒóê}«Øt-Z {A±Õm™LWp,£kgŒúƒ‘øWŽëqÛZþÓšèj‰q%¾u‡€IY n¾Í§ò=hª~Ó¾"¸˜n6VDCŸà Dœ~ ß™¯JñåœwÿüCo"† §ÎÀ̲ŸÀ€kÍ-xköŸ¼?»‡[³Û±À$ªÕ¢aøŠô‰º´:7Ã}zâf d´{xÆpKÈ6.?ÏàhÇbÕg²¤±9_e<í3‡Çë�¥{Gë8ì~xrÔ(:|2?¼ê¿V5å�ø^èþËrAå7ÚY¢À%ߟûö3^‘ð«V‡Xøg¡K`µ[YyVŒlÁü�ú@7‹@Ó?iO ÝÀ›»P’ãø‰óSŸÃoå^Õ^)ª°ñ'í7¥ÃkóÅ¢ÙƒpÊr€vÿФEú×µÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPt¿ë_ýãL§ËþµÿÞ4Ê(¢Š(¢Š+Å6M=¤w1Œ˜s¸îžÿ…oÐ@#dTÎ*QåfØzÎ�EQt<Šì¯|/kq!x$0Õ@Êþ]ª¼@àÏtÌ¿ÝEÇë\/Rö>’9¦ÆíÛÊÅ/ XµÎ³Ä~긟|p?¯á]Í×úï Óí¡´1ÃAØT÷_ë¿ ì¥O’6< n)âjóôèAEV‡ QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÙ$H£i$pˆ£,Ìp®OPñ¼q¹K¸ÿ–’dô•Uñ¦ªïr4ؘˆã¥Çñ1äÀ:ä«ÐÃábãÍ3äólê¤*º8wknüΙ„r?\Q Æœ”å²2ÆRupó§Úg•«2© ûTßlŸßú €Œ+Ý…KÅJF~yK‰Ã^ç(÷I´9äy]‰>õÕø7Y¶±K‹;—1ùέº çÓµrU"Œ ñ3ÜÁa(+k&ô^]OS$�Z˜¿lÝí{·ç¡ì4W+á ]î#m>vÜñ®è˜õ+éøWU\x\Dq•Hõ>Ý;«…Q] (¢€ (¢€ (¢€ †ì@m%ûPSÒ_wLTÕÎxÎé¡ÒR8ó¤Ã}?ÏÏŠª¨Ñ•F¯d&ì®qM]HmQ’ß"¹É¡¢Šø);»œÁ]Ÿ…üBÒ²i×dnÆ!~™Çðšã)Èí‹"¬¤Gb+£ Šž¢œ~~h¨»3ר®RñuåÐÚÿ£¦æxžüö†×—NÅšæbǹsšúÙíJЋ—àhê#Ò/uý6ÁÌs\ƒ êˆ7õÇJ­‹4™\)™ãÏwByÕÁ,ö»•ãb}£=z9XÄ‘ºº7!”äuy®‡­Ë¤Ý(,ZÙÏïú�zô•et ¤a�Gq^î \.´ktis EWqAEPEPEPEPEPEPEPEPEPRÛÿ¯ZŠ¥·ÿ^´·_ë¿ †¦ºÿ]øT4QEQEQEQEQEQETÖÿ}¿Ý5 Mo÷ÛýÓ@ÑEQEQEQEQEQEQEUµÿ�#ô?ΪUµÿ�#ô?΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQETѪ—è*š/õRýCEPEPEPEPEPEPEPEPEPEPEPEPEPEPV¬ú¿áUjÕŸWü(³ýöúÒR¿ßo­%QEQE¥ú¤ÿtVmiEþ©?Ýê(¢€ (¢€ (¢€ CE¡  Uó×Ç�Ëo¨ÂYa kiÂ¥èQþ­Ç ÿB0¸÷¯¡j;‹xní¤·¸‰%‚U)$n¹VSÁwð�íÞ9ø wòßøH‰íØ–6>?ÜcÃcÏÖ¼{QÑõ-s¥asg 8ÛÈó]_]×7·2HzãØd“�Ìšë(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3¥ÿZÿïe>_õ¯þñ¦PEPEPEPEP¶ÿëÖ�uþ»ð¦Ûÿ¯Zu×úï€ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š­{oa™;ã?uG%¾”ã'h­F“nÈó_nþß½Ý×Í?—jÍ­ícÉÕ5»Dh·€ÎrGþU™-‹(Ê6ïnõï”ÔÑñ8ìƒΪ…ÕÛѦíé¹RŠ)UK0U±8w¤|ýŽÛÀ›¾Ë{Ÿ»½qõÁÏô®º²|;¦6—¤¤R Lç̓؞߀ÅkW‹^JUGèùeQÂBÞßž¡\ï�&1hŠƒþZJª~˜'ù�]s¾4…¥Ðƒ¨ÈŠefö#ù‘Y{(Öýܶ{úcªJžs†é3Ï ÍQ^ôb¢”b¬‘ù¬¤äî÷˜Ç½:˜�éõù¦~­˜M'}¾Zl}ÆPµ·ü˺MèÓõH.›;Q¾`:�F j_ø¾þåȶ"Ú.ÛFXýIþ•ÏQ^u<]jtÝ8JÉë¡é©4¬^þÙÔ÷nþйÏýu8ü«SOñ}õ³…ºÅÌ]ò0ÃèƹÚ)ÓÆW§.hÍýà¤ÑØßxضÂß?íÍþük3þý[vwÅ�O,b°h­jfX©»¹µé ÜÙÚé¾3ŽWßÄ"'�13·ñEuJÊêX2‘�AÈ"¼‚ºÿê¬]´Ù[+‚Ñg·¨þ¿�z¹fk9ÍQ¬ï}™pŸFv4QE}¨W/ãhYôûy€ÈŽBâ?úÕÔT¶‘ßYËm(ù$\oC\غ>Þ„©®¨RWV<šŠ·¨é·eÓAp¸þëŒ=ET¯„œ% 8ÉY£œ(¢”‚:‚*D%Q@Q@zg‡$i|?fÍÔ!_Àò¯6Š7šTŠ5,îB¨Íz¦�h,tè-³“Hî{þµïd0—µ”úZÆ”÷,ÑEdëZõ¾�y“°ÊÆ8õ>‚¾’­XRƒœÝ’5nƵç²ø¿V‘÷$‘Ä?º±‚?\Ö†›ã9<Å�P�J<ØÆúŽÿ…yÐÎp³—-Úó{íÙQMGY]2°È ðE:½RŠ( Š( Š( Š( Š( Š( Š( ¥·ÿ^µKoþ½hn¿×~ Muþ»ð¨h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©­þûºjšßï·û¦€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«kÿGè�T«kÿGè�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©¢ÿU/ÐT54_ê¥ú †Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­Yõªի>¯øPgûíõ¤¥¾ßZJ(¢Š(¢Š+J/õIþè¬ÚÒ‹ýRº(ÔQEQEQE†Š(•cÏ_îš<õþé  ô×E‘Jº†SÔ�jמ¿Ý4yëýÓ@¢¶·€“ FO]ˆò©jÇž¿Ý4yëýÓ@è«zÿtÑç¯÷M}Óõ©i¨áÁ b�@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Òÿ­÷�2Ÿ/ú×ÿxÓ(¢Š(¢Š(¢Š(¢Š([õëNºÿ]øSmÿ×­:ëýwá@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW©^µõô“vç=µwÌ7!_QŠó‡F�Ùa”�G½zÙTbå)u:ð©]±´QE{'hëmm^å¾Ï$Qí¾òL êôo ÚéN&vóîGa€¿AýjŸ…#cqq/ð… ø“ÿÖ®¦¼}Y*® è|õ\¯ T«¨ûÏ_Ÿ QEç!Lšî!xePѺ•e=Á§Ò3RÌ@d“Ú�4š³<Ã[Ñ&Ò.Ê�ZÝ�îäõ‡Þ³šîµOÇp¯o ¼rÂx-(Èo ®aí!wÈÌ`ž‹ÈŸøÖÕég§û…ëñ~vûÏ&|/FRçIÛµÿ¯ÌΖŸ2åd�Œd})•ùÅiíeí~+ë}îvF𦹲AEVC (¢€ (¢€ ±cy%…ìWQ^3�CÆ*½ã'¤·@upøâà0óìâeÿaŠŸ×5ÓišÅž«kwùÇÞ�¸e¯.©­.¦²¹Kˆ¬ˆrô>Õë᳚ôåû×ÍÄÑM­ÏZ¢«i÷‰¨XCtœ 8ô=ÇçVkë#%(©GflCuio{ Šæ•f>ž•…7‚ôçlÇ$ñ�î†~¢º:+ØZ5µ©ÄÒ{˜vžÒí\;#ÎçšÙ�Àüë;ÆAxÒþÝ?Õ®ÉGEìð®¶‚# ÖUrú¢éF6¿a8«Xñú+ºÔ¼ms#Kg'ÙØòPŒ§áéYCÁ:†ìí¶úîo𯗩•b¡+(ßÍ83š­[oj·AY-J£ †rcù×U¥øNÖÆEšáþÑ*òP~�롯C ‘¹.lC·’)Sîah~‡J"yXMuŽ'ÓükvŠ+è(ЧB”Õ‘¢Ilå:•Ûßj3ܹÎ÷8ö‡å^­^S¨Ú=Ž¡=³Œlr¸ì*ñsþnH[k¿ø© ´QE|Á‰Þx2íçÓ$·sŸ!þ_e<ãóÍt•Íx2ÑáÓ%¸q�=þ_p;þy®–¾ç-æú¬9··ü7àtG`¢Š+´ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©mÿ×­ERÛÿ¯Z[¯õß…CS]®ü*(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*k¾ß¦·ûíþé h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÚÿÇ‘úçU*ÚÿÇ‘úç@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*h¿ÕKô Mú©~‚€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«V}_ðªµjÏ«þYþû}i)_ï·Ö’€ (¢€ (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@¡¢ƒÐÐ*BB‚II4µó¿Æ‰Ó^ÞÜx[Eœ¥œ$Ç{2f~ñƒýÑÐúž:@:ÿüuÑ´9¤²Ñ!­Ú­(m°!ÿ{«þ{×”j_$ÓcžÁ¸³{•' ø^!E}Á¡xƒKñ.˜š†‘yÕ»q•ê§Ñ�äcZUñwƒ¼c©ø/[MCO�”$ íØü“'¡÷ô=«ëý\²ñ&‡i«éòo¶¹MËžªz>àä¥mA÷OÖ¥¨ û§ëRÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPt¿ë_ýãL§ËþµÿÞ4Ê(¢Š(¢Š(¢Š(¢Š–ßýzÓ®¿×~ÛõëNºÿ]øPQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÎkš“J×v‹¹›—Œu'ÔWGEmF´¨Ëš%ÂnèófFF*êU‡PF Y³Óîo¤ dŽîxQø×|Ñ£ýäVúŒÓ€`t¯BY«·»N‡‹vÑtûôûE�9=Y¿¼jÕW—)97)nÎVÛwaETˆ+#Äs4ZK8ó!úuþ•¯Y^!6ÃI�\L±÷B{°ìiF¤)ÔS¨ì“Ôºm)&Î*Š@Aƒ�ikê“M]©RõF»ôª•bêPîNBÕzü“ˆ*Ò«˜Ô•-´ûÒIž.&JU[AEWŒs…*«;PK€ä×c¤øRÎëL·¹¹iÄ’.âªÀ ÇoLWAc£XiÇuµº«ÿ|òß™¯b†K^¢R“I?¼ÑSlóË�Q´�dšÒEFÈÇ×?¡^ÁQMmñI ÄŠTœs‚1]µ2ÿ˹ýëþn™ä”T×v²Y]Ëo(ÃÆÛO¿½C_7(¸»=Ì‚Š(êp)ßx1Ù´G¢ÎÀ}0õ®Š³4 Óôxaq‰ÎãОßÈV�}æ †–ö:c°QEÔ0¢Š(¢Š(¢Š(¢Š(¬�kAƒX@ż«„Yχڵ¨¬êÒ…X8M]15sÎåðŽ­íH£”yd~¸­ 7Á’™MBETùHrOÔöü+´¢¼Ød¸XK›Wäö'Ù¡¨‹jˆ¡QF�Àê(¯[bŠ( Š( Š( Š( Š( Š( Š( ¥·ÿ^µKoþ½hn¿×~ Muþ»ð¨h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©­þûºjšßï·û¦€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«kÿGè�T«kÿGè�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©¢ÿU/ÐT54_ê¥ú †Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­Yõªի>¯øPgûíõ¤¥¾ßZJ(¢Š(¢Š+J/õIþè¬ÚÒ‹ýRº(ÔQEQEQE†ŠC@WÄO7…¼ ©êq6Û‘•n}$s´Ã9ü+ãfbÌY‰$œ’{×Ò_´Eç‚ôØád¿½ñÿ�|Ù@Q@Q@{‡ìóâG�PÔ<73“©ö¨ìãÀú‚ü¼>»�„oñODe?}äŒ�Pca@aA÷OÖ¥¨ û§ëRÐEÄðÚÛKqq"Å H^Ià*�’IôÅ`xßÅÖž ðÌú­ÈKþ®Ú ó4§î¨þgØå~ ø«Yñw†µ+íjóí3¥ñ�ÅP‹±NÐdšÍðÌ3|RñÃxÂþ6Ò\Å£ÛÈ0&�e#êúà ¨?fïùµ_ûŸý”Ð|Eø�¨èš¶�á ZGyâ-G”r°§?1sÃNRMs:¦¿ñ[áì1k^#›MÖô}ê·)l�ZN:„\sÆ~aŸ­/‡Õ?iß\L7+"!Ïð"N?oÌ×¥xòÎ;ÿ‡þ!·‘CÓç`fYOà@4qÍ'û?�CEMöi?Ùüèû4Ÿìþt 7Ù¤ÿgó£ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ oþ½i×_ë¿ t0:J¬q�ïK<,òdcîh­7Ù¤ÿgó£ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ÑS}šOö:>Í'û?�CEMöi?Ùüèû4Ÿìþt 7Ù¤ÿgó£ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ÑS}šOö:>Í'û?�CEMöi?Ùüèû4Ÿìþt 7Ù¤ÿgó£ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ÑS}šOö:>Í'û?�CEMöi?Ùüèû4Ÿìþt 7Ù¤ÿgó£ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ÑS}šOö:>Í'û?�CEMöi?Ùüꆫm£[y×ržå˜û i6숩R4âç7d‹4W7Žæ/û‹$ þÛ’OåW´ß[\ʱ^EöbÇMÙOÇÒ¶xj©^Ç� ç9ò)þ #¨¢¥3(e*A´¿f“ýŸÎ°=B*o³IþÏçGÙ¤ÿgó  ÓJ�@óHpˆ¥˜ú^aªêsj·­<¤…è‰ÙWһ߬�xvà‚>bªp{+Í+æsÜD¹ãEmk™T}¤¯Ýb)Zy`±ÇµGEyÆâcOÙF¤”{]Ûî'ÚM+_@¢Šéü;áˆ5Í6[†žHåIvqŒ€>j(P�yòSÜ”¯±ÌV¶‰£>§q¾A²Ò>e�ð1è¯ò®ºÛÀ¶0¸i]çÇð³?Oñ¨|_'öf�œ ‘¬í·jq…Ÿæ+Ô†W*uñ;G§rù-«2µoÈXÛ阊ùD˜äýaX ©ß»îkÛ‚Þ¾k�U¢¼êØÊÕ¥Í)‘.M›ÚoŠïìÜ-Û˜{‡?0úñ®îÎòûT¸·mѸüG±÷¯&®§Án5 ,sòJ¥ÔÌ?úßʽL«1¨ªª5ÓÛÉ• ;Ù›Úç‡áÕÐH¬"¹Q…|pÃÐ×u¡jvnD–’0ÅÜ?1^«öi?ÙüëÄZ§ö%�•§”‘çó'ØW¥˜eøi§Zo–Û´\¢·<çì7\�ÑOñH6¯æx®›ÃºE„s¤÷7¶Ó\”…$iõ÷5ËÜÝOy1šâV’CÝ�ùÅC_7B½*59Ôy­ßúÿ3$Òg°Q\/†üE5½Ìvwr·r]Ï1žÜúW }šOö:û 2ž*ðù£xÊä4Tßf“ýŸÎ�³IþÏç]c!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè–ßýzÒýšOö:|0:J¬q�ï@ ºÿ]øT5jxYäÈÆ1ÜÔf“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüèšßï·û¦�³IþÏçRC £18åHë@h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè¶¿ñä~‡ùÔ_f“ýŸÎ¬,l-Jqœ£EMöi?Ùüèû4Ÿìþt 7Ù¤ÿgó£ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ÑS}šOö:>Í'û?�CEMöi?Ùüèû4Ÿìþt 7Ù¤ÿgó£ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ÑS}šOö:>Í'û?�CEMöi?Ùüèû4Ÿìþt 7Ù¤ÿgó£ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ÑS}šOö:>Í'û?�CEMöi?Ùüèû4Ÿìþt 7Ù¤ÿgó£ìÒ³ùÐ54_ê¥ú >Í'û?�I.±È2GÐZ*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!¢¦û4Ÿìþt}šOö:†Š›ìÒ³ùÑöi?Ùüè*o³IþÏçGÙ¤ÿgó h©¾Í'û?�f“ýŸÎ€!«V}_ð¨þÍ'û?�OmG»v9ÇC@ßï·Ö’§kw,OË×Ö“ìÒ³ùÐ4Tßf“ýŸÎ�³IþÏç@ÑS}šOö:>Í'û?�CZQªO÷ESû4ŸìþuqØÔ @¢Š(¢Š(¢Š( ô4Pzò�škÞü;[¤\›+Èåcè¤þlµòý}ɬiVúæ�y¥ÝŒÁw DøêÈ÷ ø»Ä:熵۽"ý6ÏlåIÇ;0ö#}h2Š( Š( ½à†š÷ÿ¬¦ ”²Š[‡úm(?WçUôçÀÏÉ xfMbö"—º¦ÖEaÊB>ïýõ’ßM´ëÐ}Óõ©j(>éúÔ´Wñ{Dñˆ|4¿ Æež{¤1‰V=Ð…bFXŽ7ãúf»Ú(ÅôËÏŒÚ>—m§Xø/ÃÐÚÛF#�QÀöñÉ÷ï\§ÀûÿÛÚy“as¡É©'Û®'p$ˆ�ö�1z'#å<úô¯¤ëŒøoàøWº%Ö�ý§öÿ>äÏæyVß•WÜÙû½sÞ€8kFý§ïÏîáÖìöÀìp *‡õh˜~"½ân­�ðß^¸™‚™-Þ1œò ‹�ųø_øJñÍœ zÒÛ^[6ëkÈ$ˆÿQÀãÛŒW)Áy/ïm¤ñWŒ5M~ÒÙ·Gi6Q ÿk.Ù÷ƽs�ø^èþËrAå7ÚY¢À%ߟûö3^‘ð«V‡Xøg¡K`µ[YyVŒlÁü�ú]p†!€F‚ »{FݸÆ1éŠòÙþ =•ýÌÞñv§áûk¦Ý-¬tÏû8eǶrG­dê¬�â髤C!àL ý}«�Nôúüó7ÄO ˜Ïؽ4mtÕj}ÖOVrÂAËúÔöAƒ�h¬ß5Ö‘åHrÖí°öz�ðü+~½ì=eZ”j.§´�ÕÌýrͯ´k˜eÊîQêAÎ?Jòúö ãüCá‰g¼ÓÓvîd„uϨÿ ò3œê¥Zš»Z?B'êŽ>Šs£FåJ°à†"�Ä ' òÖèb%zg…lÚÏÃ)¼aæ“Í#ê?@+›Ð|-4ò¥Íüf8TäDßyþ£°®õx´`?½_K“`gMºõ»™­8ÛVE\—ŽbcœÃî«2Ÿ©�äk­ªš•„z•„¶²ppØû§±¯_A×ÃÊšÝÿÚI]Xòª*Íõ…Æ�rÐ\!Vf¢«WÂJ.-ÆJÍÁ[¾‰¤×ãqÒ4f?–?­bGÍ"Ç3»Q’Mz'‡4c¥Y–˜´Ë‚ÿìŽÂ½« *؈ÉmYpWfÕyÿŒegÖöòÇ€>¼ÿZô âük`ââå\£/–çÐŽŸçÚ½üæ2–òôjæ•69:(¢¾8À+Õt¹Z}*ÒWåž$úœW—ÚÛIyu¼+™$m W«Û¶ÖÑ@Ÿv4>€b¾‡ Œ¹§.šÓ$¢Š+éMBŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¥·ÿ^µKoþ½hn¿×~ Muþ»ð¨h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©­þûºjšßï·û¦€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«kÿGè�T«kÿGè�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©¢ÿU/ÐT54_ê¥ú †Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­Yõªի>¯øPgûíõ¤¥¾ßZJ(¢Š(¢Š+J/õIþè¬ÚÒ‹ýRº(ÔQEQEQE†ŠC@«„ø“ðÚÏÇzzË%¶¯n¤ApG :ìö}û~`÷tPÄ_ j/a«ÙKk:ôÜ>Wªz0÷™_rêšF�­Ù›MNÆÞòÜóåÍ`¨ÏCî+Ï5/€ž ½�½·Ûì3ü0NñðÇõ —iUYÝQ³1Àd“_J[þÏŽ@Óê:¬Ê?„Iƒõù3]LJ|á 0“JÒaŽàËÄ™’OÁ›$~  øcð^âââoÅVæd!á°�|ÒÆAÙÙê{àuúŠ(ÄtýjZŠº~µ-QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEgKþµÿÞ4Ê|¿ë_ýãL Š( Š( Š( Š(  mÿ×­:ëýwáM·ÿ^´ë¯õß…AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP\‡‰¼3-ÄÍb›�¹–!ÔŸQþ×ÑZS©*ræ‰ËŒÁÓÅÓöu?á�xÞ')"28ê¬0E ×â­ï£[ËdÝupäc?~w^ŸðD–бec>¡t¶öèYÛ©ì£ÔûWÅNu+Ôr–²“üO §N0Š„’:ïÄÂÎêS÷Z@£ðýzꪮ›c›a¬|„·÷�sV«íðT] ¦÷G\U•‚Š(®¡�Íkoqþ¾¥ÿ}:HlímÎ`¶†#ê‘…þTùî!¶ˆË<©¬Ç²�Štu}¿k'ÜFØþUÏR¥ r½F“ó°›HÙ©‡üz·ûÕJÖöÚö=öÓ¤ª:í=>¾•tÇ«½[ÆJJñwC!¢Š)� Í¥½ì^UÌ)*z0éôô¬†ðŽ’Ï¸G*�î‰+vŠÂ®�Wz‘Oä&“)ÙiV:pÿE·TcÕº±üO5rŠ+XB0\±VC Žx"¹�á™Æã §½IE6“V`qwþ ™d/a2²à�à�ǽS‹ÁÚ¤�‡ƾ¬ùþUèW—<› )sY¯+‘ìÑ“£hÚB—SæÜ0ÃHF8ôµkQEz4©B”T)«"’°QE ÂŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¥·ÿ^µKoþ½hn¿×~ Muþ»ð¨h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©­þûºjšßï·û¦€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«kÿGè�T«kÿGè�T¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©¢ÿU/ÐT54_ê¥ú †Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­Yõªի>¯øPgûíõ¤¥¾ßZJ(¢Š(¢Š+J/õIþè¬ÚÒ‹ýRº(ÔQEQEQEQE”`zQE”`zQE”`zQE”`zQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEgKþµÿÞ4Ê|¿ë_ýãL Š( Š( Š( Š(  mÿ×­:ëýwáM·ÿ^´ë¯õß…AEPEPEPEPEPL–h MòȨ¾¬qQ_]¥�£Ü?!GÔöÂÝÞO}9–w,{Ê=vapr¯«vFÔ¨ºšô;1­é¥¶ý©3ô8üñWc’9PérOà?úõËWk¯Ù5æœLc2Dw€;ŽãüúW_A—I:]C Ó…‚Š(“€2k¼è:ÿ »6˜êz,¤ÈVÝgèÖfËMŽ7‘¾w„ÿõ±Zòø™)V“Ž×<ª­9¶‚Š(¬ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ §ªX�GMžÔ� ¯ÊOf�Ö®QS8)ÅÆ[0<Šhd·™á• H‡ §±¦W¦êš–¬7L…eTàþ>µ„| wüº‡Ëï?ξJ¾Kˆ„­Ms/—ê`龇 $ ' éÞÓLÐ6J14�½Ç§Ê«é~±ÓJM8èïü?AÚ·Çüz·ûÕêå™d°ïÚÕø¿"á jÈh¢Šö�Š( Š( »FsÑA&¼žîæK˹n%9y±ÿ õ—PèÈz0Á¯'¼µ’Êò[iF6#ëï_=Ÿórö¿y•B PH ƒ‚:IJªY‚¨$“€zù£#Ô´‹¦½Òm®—tù�©ÔUÚ¥¤Ú5Ž•mlßyæúžOêjí~ƒC›ÙGŸ{+ú�+`¢Š+Q…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Koþ½j*–ßýzÐÝ®ü*šëýwáPÐEPEPEPEPEPEPS[ýöÿtÔ55¿ßo÷MCEPEPEPEPEPEPEPV×þ<�Ðÿ:©V×þ<�Ðÿ:©EPEPEPEPEPEPEPEPEPEPEPEPEPEPSEþª_ ¨jh¿ÕKô Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Z³êÿ…U«V}_ð  Ï÷ÛëIJÿ}¾´”QEQEV”_ê“ýÑYµ¥ú¤ÿtP¨¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢«ß_Úi¶­u{q¼ Õäl§Ö€,QX:o�|9«]‹[-V�Ž2>ƒpü+z€ (¢€3¥ÿZÿïe>_õ¯þñ¦PEPEPEPEP¶ÿëÖ�uþ»ð¦Ûÿ¯Zu×úï€ ¢Š(¢Š(¢Š(¢Š(¢Š(¬MGðݹ–òd<‘Œ©ÿ Û¢´¥VtŸ4ŠŒåtr#Â×»°eƒ»�øV¾› AbâYΘt$`/ÐV½½Luj‘åoCIWœ•› (¢¹ BŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦ñêßïT50ÿ�Vÿz€!¢Š(¢Š(¢Š(¬­cA¶ÕÔ3“ê0²¨íèGqZ´VuiB¬\&®„Õμ~ qlSÔ–òÅmèþ·Ód?Ÿp>éÆ~ƒ×Þ·è®:9^”ùã|Ä �QEèQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE-¿úõ¨ª[õë@ uþ»ð¨jk¯õß…C@Q@Q@Q@Q@Q@Q@Mo÷ÛýÓPÔÖÿ}¿Ý4 Q@Q@Q@Q@Q@Q@Q@[_øò?Cüê¥[_øò?Cüè¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Mú©~‚¡©¢ÿU/ÐP4QEQEQEQEQEQEQEQEQEQEQEQEQEQEjÏ«þV­Yõ€+?ßo­%+ýöúÒPEPEPZQªO÷EfÖ”_ê“ýÑ@¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¯1×"ÿ„»â¤É-¦éÑy²ÄÎÐOêÊ¿L×§Wšø{÷¼@®>f¶%sõˆÿ*¿ãŸi/ák«½?O·´»²ŒÏ–ñˆÎ–xñ­Ïjòkž°½�·NP¤§¹e%IüqŸÆ®x‘•ÔŸÜ4RŠ·ö¤þá£íIýÃ@(«jOî>ÔŸÜ4RŠ·ö¤þá£íIýÃ@Ûÿ¯Zu×ú年áÂ… šYgXßiRMQ¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†¸_x¢i®O±sIòÊêp\÷ô®\^.Z|óù.â”¬Ž–mNÂÙ-äÝÕ¤Ššˆn|Ç*ú£?Jò:±g}s§Ü,ö³4ràõö#¸¯ûæ÷¡§®¦~ÐõŠ*¾‡âµm9f1…™~YTtÔ{ÓûRp×ÑS©�SƒÑš§r¥oíIýÃGÚ“û†¬ ”ŒÁT³$ö«ŸjOîçüe¨˜¼>é*fuŒŸnIþX¬«ÕTiJ£è„Ý•ÌmGÆž\­„*ê8ó$ÎÐ ¯iãk…� »hÚ>æ,‚?2s\­ñòÍqn|üß.†<ìõ«[¨o-’⌃Wüz·ûÕÇxù£7–¯–�E‡¡üøü«¹©ˆ¾Ó€qŠú¼#ë#S«6‹º¹FŠ·ö¤þá£íIýÃ]C*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*QVþÔŸÜ4}©?¸h¥oíIýÃGÚ“û†€*T¶ÿëÖ¦ûRpÓ£¸Gp¡H&€ ºÿ]øT5zYÖ7ÚT“LûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJšßï·û¦¥ûRpÓã�\�Œ Ð*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T«kÿGè�jOî”J >f8ô  ú*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJš/õRýKö¤þ᧬êÊÄ)ùzÐ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T¢­ý©?¸hûRpÐJµgÕÿ _µ'÷ I«.v®1@_ï·Ö’®¤�‡ŠOµ'÷ T¢­ý©?¸hûRpÐJ*ßÚ“û†�µ'÷ T­(¿Õ'û¢ ûRpÕ…;”Üf€Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¼ïÅÚuþ…ã Oi¶�wO.òÆ[ÛŸ¦1ô*+Ñ( .×ülÞ/ÒßBðæ›}%ÅÞW’0¢%Ï9 Ÿ¡Ï®ûÃÚBh:ž˜ŒÈ� Ãø˜òÇñ$Ö�QE�/ú×ÿxÓ)òÿ­÷�2€ (¢€ (¢€ (¢€ (¢€%·ÿ^´ë¯õß…6ßýzÓ®¿×~Q@Q@Q@Q@Q@V~£­Øic3~ðŒˆÔe�áÛñ§¹;"*U…(óÔv^f…Ë�ØoÁ¶¹ ë…ÏåšÚÓõ{-Q µ˜3¼‡†…\©N*òG=~¼¹iÍ6^¢Š+3¬(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šk’±±$@¯"f.Řå‰É>µëõæZî–ú^¥"m>K’Ñ7b=? ùüúœœ!5²¿ãc:ˆÌ¢Š+æLN«ÀîÂòê1÷ a�Ô?™®Ú¹ß ioeb÷3.Ù.0Bž¡GOÏ?ʺ*ûl®œ©áb¥¿ù�VAEW PVv¹§�OJ–Ý1æ :gûÃüâ´h¨©N5 á-˜5sÈd�â‘£‘Jºœ#mz•ö�a¨�×6êÏýñ�ߘ¨m<;¥ÙÈ$ŽÔ†r[�|̲ÜöRVü~ãfÊÒä²³’æu+$øÚ§¨Qþ9þUÔ�øõo÷ª˜Ç«½_G‡¡•8ì�R²± Q[ (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*[õëQT¶ÿëÖ€ëýwáPÔ×_ë¿ †€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ šßï·û¦¡©­þûºh(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¶¿ñä~‡ùÕJ¶¿ñä~‡ùÐJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ š/õRýCSEþª_  h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÕŸWü*­Z³êÿ…V¾ßZJWûíõ¤ Š( Š( ´¢ÿTŸîŠÍ­(¿Õ'û¢€EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPt¿ë_ýãL§ËþµÿÞ4Ê(¢Š(¢Š(¢Š(¢Š–ßýzÓ®¿×~ÛõëNºÿ]øPQEQEQEQEQEf뺟öN—%ÂàÊNÈÁþñÿ$×—Ë,“ÊÒÊìò9Ë3’k´ñÞï²Ùcîïlýp1ýkˆ¯S©óugÃñ"sÅ{'´møëp©m®f´¸Iàr’!È"¢¢ºÚ¹á¦âî·=cIÔSÓaºQ‚à ¾Œ:ÕÚæ|»ûlýß<ãþùZé«Ä«´�Òp5¥[ ’Ý ¢Š+3¬(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š* »;{è 71,ˆ{ÇÔÕ=¥%i+ 9Y¼lϘnåEôe þwOð®Ÿc •÷\H9N€ý?Æ·h®8eØXKž0W'•Q]¥Q@Q@Q@L?ãÕ¿Þ¨jaÿ­þõCEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPRÛÿ¯ZŠ¥·ÿ^´·_ë¿ †¦ºÿ]øT4QEQEQEQEQEQETÖÿ}¿Ý5 Mo÷ÛýÓ@ÑEQEQEQEQEQEQEUµÿ�#ô?ΪUµÿ�#ô?΀*QEQEQEQEQEQEQEQEQEQEQEQEQEQETѪ—è*š/õRýCEPEPEPEPEPEPEPEPEPEPEPEPEPEPV¬ú¿áUjÕŸWü(³ýöúÒR¿ßo­%QEQE¥ú¤ÿtVmiEþ©?Ýê(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3¥ÿZÿïe>_õ¯þñ¦PEPEPE ÝÔVVÏ<§ ¿™>‚šNNÈi_DMEq7šýíË�’c챜Ï­A¯†[©ÙÛpýkÑYeW¶®t,,­¹èVÿëÖ�uþ»ð¬­WMI° :}åõ«uþ»ð® ”åNN2Z˜J..Ì‚Š(¨$(¢Š(¢Š(¢Š(¢ŠË×ô³ªéOcÍS¾<ÿxvüFEy„‘¼R4r)WS†R0A¯c®{ÄVú€ú‹ys‘Á‹ýaOñ®ŠXÈaâý£´O7Ê^-ª´Ý¤»õ< ngHaBò9¨ïZ+‰æàÏåÿ×4Ïó®×Ãðh±Ä[L*òcçg?¼üsÐ}8«Žo…©îÒšlñpù"sµ[EzÝü‹º>ž4½2\‚Ê2äwcÖ¯QEr¶äîϵ§N4à¡–�ER,(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*aÿ­þõCSøõo÷¨(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ –ßýzÔU-¿úõ ºÿ]øT55×úï¡ Š( Š( Š( Š( Š( Š( ¦·ûíþé¨jk¾ßŠ( Š( Š( Š( Š( Š( Š( ­¯üy¡þuR­¯üy¡þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦‹ýT¿APÔѪ—è((¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ µgÕÿ «V¬ú¿á@Ÿï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE�/ú×ÿxÓ)òÿ­÷�2€ (¢€ (¢€ æ|W3fÚ~^XûžŸã]5axšÍ§µŽáL9Ü÷OzëÁJ1¯#Z *Šç%EWÒ™¥áùÚ vÑ—øœ!÷Šïî¿×~ÄøZÉ®uˆ¦#÷P�Äûã�ýk¶ºÿ]øWƒ™Ê.ªK{¦¹È(¢ŠóŽ`¢Š(¢Š(¢Š(¢Š(?ZÔ†•¦Ip2–0{±ÿ9ü+ÌæšK‰šiœ¼ŽrÌO&»û5˜w{gë��ë\]|–w^RÄ{>‘1¨õ°TÖ·SYÜ$ð9IäPÑ^:n.ës3Õ4»õÔ´èn”`¸ù—чQW+›ðQc¤LÝœß+]%}æ««B–í1wAEWHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦ñêßïT50ÿ�Vÿz€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©mÿ×­ERÛÿ¯Z[¯õß…CS]®ü*(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*k¾ß¦·ûíþé h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*ÚÿÇ‘úçU*ÚÿÇ‘úç@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*h¿ÕKô Mú©~‚€!¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«V}_ðªµjÏ«þYþû}i)_ï·Ö’€ (¢€ (¢€ Ò‹ýRº+6´¢ÿTŸîŠuQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Òÿ­÷�2Ÿ/ú×ÿxÓ(¢Š(¢Š( €FÈ4Q@wž¶�ËÁ!€ž«Œ¯åÚ ‡Âˆî‹/÷Qqú×GEu,muU#U^¢V¸iöñZ˜â… ì*{¯õß…6ßýzÓ®¿×~ÌÛnìÉ»�QE€(¢Š(¢Š(¢Š(¢ŠË×ôêio®C¾?r;~#5æŽ�²:•e8 Œk×ë/SðýލÛåB“ÏHÎ úú×�™å�ý¥?‹ó"p¾¨ó:|1I<ÉH^G8UI®Äx-ù7Ï·ÓËüó[zn‰e¥ Á2ƒ#œ·ÿ[ð¯*ŽKˆ”­SÝD*o¨ýOf™ ¶Ap2äwcÖ¯QE}]8FœT#²6ZQVEPEPEPEPEPEPEPEPEPEPEPEPSøõo÷ª˜Ç«½@ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQET¶ÿëÖ¢©mÿ×­-×úï¡©®¿×~ QEQEQEQEQEQE5¿ßo÷MCS[ýöÿtÐ4QEQEQEQEQEQEQEmãÈýóª•mãÈýó  ”QEQEQEQEQEQEQEQEQEQEQEQEQEQE4_ê¥ú †¦‹ýT¿A@ÑEQEQEQEQEQEQEQEQEQEQEQEQEQEU«>¯øUZµgÕÿ ¬ÿ}¾´”¯÷ÛëI@Q@Q@iEþ©?Ý›ZQªO÷E:Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  OîNIïIövþò~tÉÖ¿ûÆ™@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@a…–UbÊqèigˆ¼™ £Žæ¢·ÿ^´ë¯õß…'ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÔ‚äܹݜæªÔÃþ=[ýê>ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOÎ�³·÷“ó¨h  ¾ÎßÞOΟ ,²«S�CUª[õë@Ï y2GÍGövþò~t]®ü*›ìíýäüèû;y?:†Š›ìíýäüèû;y?:†Š›ìíýäüèû;y?:†Š›ìíýäüèû;y?:†Š›ìíýäüèû;y?:†Š›ìíýäüèû;y?:†Š›ìíýäüêHa*ÌK)Ê‘Áªµ5¿ßo÷Mgoï'çGÙÛûÉùÔ4Pßgoï'çGÙÛûÉùÔ4Pßgoï'çGÙÛûÉùÔ4Pßgoï'çGÙÛûÉùÔ4Pßgoï'çGÙÛûÉùÔ4Pßgoï'çGÙÛûÉùÔ4Pßgoï'çGÙÛûÉùÔ4Pßgoï'çV2-JdgœñTjÚÿÇ‘úç@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�goï'çPÑ@}�¿¼Ÿ�I%c�n^G­U©¢ÿU/ÐPövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~t}�¿¼Ÿ�CEMövþò~u=´f=Ù*sކ©U«>¯øPÝ‹¹:úÒ}�¿¼Ÿ�Dÿ}¾´”7ÙÛûÉùÑövþò~u 7ÙÛûÉùÑövþò~u 7ÙÛûÉùÕÄ�G ›ZQªO÷E:Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  éÖ¿ûÆ™O—ýkÿ¼i”QEQEQEQE-¿úõ§]®ü)¶ÿëÖ�uþ»ð (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*aÿ­þõCSøõo÷¨(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ –ßýzÔU-¿úõ ºÿ]øT55×úï¡ Š( Š( Š( Š( Š( Š( ¦·ûíþé¨jk¾ßŠ( Š( Š( Š( Š( Š( Š( ­¯üy¡þuR­¯üy¡þtRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¦‹ýT¿APÔѪ—è((¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ µgÕÿ «V¬ú¿á@Ÿï·Ö’•þû}i(¢Š(¢Š(­(¿Õ'û¢³kJ/õIþè QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE‚"I+É÷4Ÿf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h gÇ7÷ƒ5ONaÜ †7#v2ꎄÕ/†úÅ&ºŽ« šäÎé¼(N1ÀÀ­/ézïƒ52ÅU®gT¶ƒ‡RyúT¾ø~ÿÃ^]?RDK�;¾à c‘@OÙ¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš_&=…vü¤ç©( ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔ×;ã½Bã@ð^¡ªiÌ"»€!�È ŒÈªxÍ÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦•a� *¸ÈÇZ’Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔטj>0Ö­¾0EḮPiM,Haò”œ4a�ÍŒõ'½z¥y†£à�jçã^#ŽŽœ²ÄÅÌ£v0§Ž½EzWÙ¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦”C‚ðzóRQ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêkÎ~+x§VðŠi'F¸X É”Kº5|íÙ�¼>ñ¯K¯9ø­àý_ʼn¤�*(ä6Æ_3|�1»f:ÿºh¸Ó•nt»Iå’XQÜôÉ* «?f‹ûŸ©¨ôè^ÛK´‚@‘BˆÀòVh/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMHÐRÑ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V~µ©¾‘¥Éy•Åë!An»�²qÒ€.¼ÑDȲHˆ\áC0� õ§×ŒÝø�T×þ!x{íúdút\¯‘ÊÀœ°Ë@ÏAô¯f Šò¸"ºø›â-Gο¸¶Ðl_ËŽ(iÉÁôÏÉ’îÞëᆻ§Ëmqq¡^?—43¶|³ÆO¦pr¡€=VŠãþ!ø’ã@Ñ"‹O8¿½“Ê„ŽJŽì=ù}k|*-cö§×/ÿ· îóüÏ�?§MØ÷Ï¿µzMÇ|;ñÖ¹¤ÜZê$�BÂO*f=Xs‚}ø#ð®Æ€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ +“ø‡â�øa¦³m·W#|gfA%¿ X–ß ¹³K�SWÔdÕw<« ±íÈ$ãëϵz=çßu]J=_VðΧr×O§±1LÄ’T“Î9g§5è4Q\'Ä wPŠëMðæ�1†ûRpU81¡8=²sÏ¢šÍÔ~6“¦K©húΡý­K³ŒJ@É‘Ÿr}èÓh®cÂ^)]kÁãV»!d¶W[¢£€PdŸÄ`þ5Çèš5×Ä·ºÖ5«û¨l¦;kX1õq�3Œ“šõz+Ì´Ù/¼ãkMké®ô}Dnf91±8óÀ8ãæ´¾ kº„WZo‡4yŒ7Ú“€Ò©Á� ÀÁ퓞}ÐwEy–£ðÑ´�2]KGÖuíhÊ]œbRH Œû“ï]_‚¶·¥ÃªëZΠuK”«+ŒE‘�0Fxö#Ò´¼­êÚ—†5‰Œ÷š{Ìr^0qÉ<žªA=›Ú€;Ê+Ìõi¯¼qã‹�Û_Ki¤Ø)ûKBpda€Gæpã‚j¦¹¡]|7ÚÖ…¨]Kf% skpà†¿ �2 êôT6wQ_YAw ÌSƲ!õVΦ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( $($�ä“Ú’9#š1$N®�Ñ”äÆ¼ÇÆ¾6ÕÛNÔ4û?ßÛÂwÃ-ìѶЙÁ+Æ9óÞº¯‡¿ò!é?õÍ¿ô6 šŠá> kº„WZo‡4yŒ7Ú“€Ò©Á� ÀÁ퓞}Ön£ðÑ´�2]KGÖuíhÊ]œbRH Œû“ï@›EsñJë^µÙ %²ºÝƒ$þ#ñ®?DÑ®¾%½Ö±­_ÝC`%1ÛZÀà�¨#Œ�œdœÐ«Ñ^e¦É}à?Zh3_Mw£ê s1É�‰ÀžÇ05é´Q\ÿŒü@|5ᛋøÀ7ˆ  Ó{t?€Éü+‘Ó>¶·¥ÃªëZΠuK”«+ŒE‘�0Fxö#Ò€=:Šàü­êÚ—†5‰Œ÷š{Ìr^0qÉ<žªA=›Ú³õi¯¼qã‹�Û_Ki¤Ø)ûKBpda€Gæpã‚hÓ(¯(×4+¯†âÛZе ©lÄ¡.mnÀ÷àƒÓ¦A"»x©4�fÔ†{„O²îèYÆA?A“øPMEyŽ™ðݵ½.WZÖuª\ •Y\b,Œ�‚3DZ•¥à oPþÐÔ¼1¬Lg¼Óؘæc’ñƒŽIäõR ìÞÔÞQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEæþ4ÿ’™á?÷Çþ‡^ƒzÌ–7Ÿybb>¸¯>ñ§ü”Ï ÿ¾?ô:ôv”©`ŠóßƒŠ£Âwl>ñ¾`ï„§ü`U>€ž«z„ß/YÞ¾ƒÂ:Þ¯á­Zt¶w›m$Çj¸éÔñÈ GãKãýFjZO†4‰ÒéžãÍ�á!–03‘DZ?…Gâ÷iüMàE˜�¬Ñ1Ï©xóü…z¥yçÅ 6x´ý+Z²�siS*EÊ�~€¨üë£_xxèãS:¥¸‹fã˜<À»³®}¨•ð'ÉñÅÑ¡ù ÌÇëæ7øšôªóß…ÖW&­â¨Ê6§pZ0GUËG±-�ø zQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE5‘\aÔ0÷®gÅ0Šu_YÙMnbË<§÷�òx`1Œvªß5kGÒ-µ-&fHà˜}¥UAÊ™È8ükJÓÆÞ»°[±¬YÄ¥wå•Qר©ç4Ë|2’Ì_ê©v×#ÄnåïáBœg�¸í“ÏáÚ½"¼ÃÂ’ÿÂEñKUñ’0Ó£‹Ê•ǘvª�Ïi?Lf»Ãâ)uÑ¢ÅþÑ#" ­Ÿ»»®1Óž´Äj?¼øë¥+žÔíÏýs�ÿ:ô®µæÞ>I4?h^*Ím\Ú2š³~UÑë^7Ñl4 ï­õ;Y¥1"8ä ÌäqòõõÏJóï»GðßÅÑÆNÅÜèWô®ëᚪü?ÓJ÷óIúù�Yžð̉ðêêÒéLrê«#|ÕV]«ü³øÕo†Úý®™¥Üx{W¸ŠÊöÊw'`™RrpOSœþP|Tù5O ʧ÷‹tÛqþôà(Ôyñ×JW<%©ÛŸúç!þu³u�>$höZt‹qe¦>y“”ÎàHÏqò¨úšŸÇÉ&‡ã ÅA­¢" ‚£;FOóVoÊ€='­y¯ÁÓ·KÕ¢S˜Öèmÿ¾úºMkÆú-†�=õ¾§k4¦#äG�™œŽ>^£ž¹éT>èÓi>Y.¤×’ö°ä)/è3øÐkEPEPEPEPEPEPEPEPEP\ïŽÿäGÕÿë�þbº*ç|wÿ">¯ÿ\óÃßùôŸúæßúW7¨þóã®”®xKS·?õÎCüë¤ø{ÿ"“ÿ\ÛÿCjç<|’h~0мTšÚ" ¸*3´dÿ5fü¨Òzךü;t½Z%9�n†ßûçÿ¬+¤Ö¼o¢Øhß[êv³Jb>DqÈ™Èãåê9ëž•Cá~�6“á’á My!ŸkB�þƒ?�vµæ¿ yâÊç2¥Î}Þ\×o¤x‡J×ZuÓ/àÛ�%XmÎqÔCùW¦\Åàωڵ¾¢âÞÇUýô3? ¸¶á“ØÎ?*é¾$*·€5PÝÆG×Ì\WâÉþø]X�¥†`?Jèþ$x†ÓPÑ£Ð4«ˆ¯ooæE1ÀÁð ç’:Bþµ?�|/#|5¶±¶_2m1#“ 9}«µ±ø ï•B Uèyµ¯îþ;^„?ë-Fü×4ÿ]‡ük£_øvÞîçSµ‚dˆ „–@¬®<HÏOZçü ¯¯øã[ñVÆ�þ�nÌ1»î€QŸ÷¨>þóÄ>-•Îd7Kœû¼¹®ƒâB«xU Ð,d}|ÅÅs:eÌ^ ø�«[ê.-ìu_ßC3ð›‹n=€,ãò«_*|š§…åSûźm¸ÿz?ðéUåúÍÔ>4ø‘£ÙiÒ-Å–˜|ùæNS;�#=ÇÊ£êk½ÖV'iaŸÁXÒº?‰!´Ô4hô *â+ÛÛù‘Lp0|(9䎄�¿­Oã_ Èß m¬m—Ì›LHäÂŽ_jíl~ŸÂ€;åP¨z�^mkû¿Ž×¡úËQ¿õÍ?ÀWCáÿè×þ·»¹Ôí`™"á%�++�Ï’3ÓÖ¹ÿ+ëþ8ÖüU±…££Û³ nû ÁTgýêôš(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3ot 3QÔí5«o2îÐæ <Æ9Ï@pyõ¥E—«øwHוF§aÁNŽCè`ãñ£Hðæ� †þ̰ŠÜ¸Ã8Ë1›ŽN+RŠGE‘C+ # �JæÏÃÿ ›¯´cA¿9ÆæÙÿ|çoé]-ÔDŠ5Ž5TEUQ€ ê( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( º,ˆÈêa•†A†¹¹~øRiÌÍ£B9Â;ªÿß ãô®šŠ‚ÎÊ×O¶Kk;xà�>ìq¨P?*å®t‹k�‰6:…¥œÂâÙïnX8F=‘¨'å'œü¾œ×aEEqmÝ»ÛÜ“C ÃÇ"†VàÖ ·€¼/iv.bÑáóAÈÞÌêû¤‘úWGE�«øOB×fjZlSJ<ÀJ1åH&¶h  V‹¦è–æ 6Î+hØå¶Xû“ÉüjÕÅ´vïos M ƒŠX{ƒRÑ@å·€¼/iv.bÑáóAÈÞÌêû¤‘úWGEQEQEQEQEQEQEQEQEQEU{ûmNÆk+ÈüËy—l‰¸Œ�¨æ¬Q@tí>×J°ŠÆÊ/*Ú„MŰ3ž¤“Þ¥¸¶‚îÝíîaI¡�aã‘C+pjZ(œ¶ð…í.ÅÌZ<>h9Ù�Aÿt’?Jè袀8ÿéÖž·w§ÙÍk§\¼IÌ3” ¹°ÿ6 n3é]©£iÚÕ°·Ô¬â¹Œ¨qÊŸcÔ~zŠÅÒ|% èS´í6(f#a%ØbÄ‘øVÕP9uà? Þ]›™´xL¬rJ3 'ÝT�úVõµ´véom pÃÂG…UÀT´PSFÓµ«ao©YÅs9Pã•>Ǩü*ž“á-B˜Í§i±C1ó .À{$�¶¨ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ÷ö6Ú�ŒÖW‘ù–ó.ÙqQÍ7NÓít«¬l¢ò­¡DÜ[9êI=êÕÅ´vïos M ƒŠX{ƒX6Þð½¥Ø¹‹G‡Í#{3¨?î’Gé]V6¯á= ]˜M©i±M(ó(Ä{• šÙ¢€(iZ.›¢[˜4Û8­£c–Ø9cîO'ñ®{â‘m­i–ö†Îk�Eßm£ }±W{1({ð®ÂŠ;W9uà? Þ]›™´xL¬rJ3 'ÝT�úWGEEmm�º[ÛC0Æ0‘Æ¡UG°[TÑ´íjØ[êVq\ÆT8åO±ê? ½Ebé>Ðt)ŒÚv›3�0’ì±bHü+jŠ(œºð…ï.ÍÌÚ<&V9%�îª@ý+zÚÚ ;t·¶†8aŒa#�Bª�`*Z(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(•Öþ#øKÚÈÒ5m]moˆSå´t%‚•ŸÕƒÐ×Ëß´‹�{ãHÒì‚››‹h– Ç›a g߯Døã©5�!ü1ª».­¥®ØÄœ4�ƒŒ÷CòŸl{Ю×?¡øßþ$Ôï4Ý#QûMÝž|øü™fiå”Ï¡®‚¾øÿ%7ÅÿI?ôu}EP¹×4‹=J:ëT²‚úp VÒÜ"Ë&Ij““’àv«ôQT\ÒV]%µK!©0ȳ7 ç7}ÌîéÏN”ºŽµ¥hæ©êvV^q+ÚgXüÂ1�»ˆÏQÓÖ€/Q\÷ˆkÑgø»à+kÃk'‰-Œ€ã1¤ŽŸ÷Ú©_Ö€;Z*µ†¡eªÙGy§ÝCum ÊK †VüEM,±ÁË4‹h 3¹ÀP:’OJ}ÄÍñwÀV÷FÙüIldD‘ÓþûU+ú×W§jv½’^i·�]Û?Ý– ©öÈïí@èª:޵¥i©êvVFrV!s:ÇæŒ…ÜFzŽžµ™®xëÿ†ÇVÖ ·»˜€�á�ùà úœPCEPEdkÞ)м1 Ë­j–ÖJÿqdo™þŠ9?€¬}+â�‚u«µµ±ñ ³Nçj¤ªðî>ƒx4××ã?‰žð,±AªÍ<—r®õ¶¶Œ;íän9 �zšêîn`³¶’æêhà‚%/$²°UEI'€+çK½SÃÚŸí.o¯õ 2ãEDR—Ï[ä[ |Äí8Ö€=ïÃzý§ŠúÆÿ:ýTò?Z7—¶šu¤—w×PÚÛFy§�"/8å�’(z+&ïÄú ŽŽº½Æ±bšsýËŸ=J?^ƒó=+'Hø™àÍvù,´ý~ÚK—m©†Œ¹ô]àdý(¬¢ŠçüAã� øYÖ=kY¶µ”Œˆ‰/&=v('ø ‚Šçtx[Åy:6µms>3äò’ê€'ò®Š€ +œ×ü}á_ OäkÕµ´øÉ„fI÷U�ÄSôxgÅômfÚêP3åVLzí`? è(¢¹]oâOƒ¼;vÖºž½mÂtuºñ%˜Õõ«å^Ý]3æ0É ÈÀ=�ñ‹¯MañžïÀú5ýÍ­�ó¬Rs“nÈ&e>¸Žzãžµõz}ÅúW‚Éÿ'sûŸûdh·¾ø+à©ü?&�m¥,ùDEvŒªøá‰Ï<öéí\�ì×}<š>½§»±†Þx¤E'….6?ï�^å^ û5}ßÿ¿mÿµh�Ö4KïüzÖt++—¶[û§ŠæDíß?‚ôîp+Ú¿áIxû/ì?Ù »n>Óç¿›Ÿïg8϶1í\„æŠ/Ú\I /ž‘çûØVþJkè ùÓÀ2_ü2øÉ?ƒ..^m2ùö!n»¢�Ì~éÿë ÔøÃ«j^)ñΕðëK¸0Å1Fº ðÌß0Ýꪣv;“ì*·�¶Þ~Ò~†Û™aû'š¨"FsŸø�â½ÿXý¤î´û]^m"êça‚ú,†LZƒÆO8+×½zÅ—ÁOZi‹g&�ö–Û‡¸šgóúä�üÛK‚çàÿÆ›]ÞêYt-`Æ$oáv*¤öÜ®1žãÓ5Óÿ¡ñ¯ýmgþú›ÿ�U > j/â:÷Xø„÷×VÒÆñ%älî@|…]Ò’#µEûIJÐ'…¦LnŽiØg¦G–kK¿ìµ[x|Gâû»ËÝjø‹¹dØ‘–ù€8$qß VWí1ÿ¾ÿ~çùG^ò *… @ U5MB'I¼Ôn3äÚ@óÉ�?Ê­×3ñ)&øqâ4ˆßÙó@„ŸÒ€€Wžðë~ÐÒøPØ·ö2¦E¿œùÏÙ„Ÿ{;¾ñÏZÞýœÁ—Zñ]Ì@‹vòqÇ«HGéSEÿ'o7ýsúF(Ú´]ÃÃÚ=¾•¦Ba³·ErØ’y$“É5~Š(çO‰Ìž$øé¦xw\½k]!Ÿjü˸œžc…ϰ¯HÔ¾ øóG–ÎÛHKYŒdEs®]’w~9«;ømáßȆêcmªÂ›âöõÚÊ~ðäžÇÞ¼í¾üPðz—ð¿ŠMå¼\¥¿œS?öÍóë@·Áß x›ÁÚ=þ—¯4&ÛÍYm)·í$ãØp§¤× ã)/~)ücOÅtðèÚk?aêT~ññݲv ôüMv ¾%ßø¾ký]¶Xu›Üì‹·ÌPÛ[rÿ €~½«ÊôO j¾!øÓâ½?OñÖ…x³ÝÊn ÜEóÇËò²œ†ëÚ€=šO‚Þ}0Ù !Û�:Îþh?ÞÜO_ÃÕçß îµ|Y¿øwtÓéó–6û�¶yŠàvÜœ;ãÒ·áPø×þж³ÿ}MÿÇ©šÂ+½/Çöî£ã�íMBÕ÷4w“,ƒiÜÒÐút  /‰7:‡Ä_‹V~²¹htûVy�Ûw»‘ܪü ùõ¯A_‚^]/ìGHfm¸7&wósýìçöÆ=«€ð[­·í5â®x’cr±g¹%\cþ }@)Ùh·þøã¡xrîêK›}>ú5³wÿž.ÛÆ=>ñÈéœ×gûFÿÈCÁÿõÒãùÃPxÞh¥ý¦<8‘�^/²¤˜ìÛ™¿‘ZŸö�ÿ�‡ƒÿë¥Çó†€=æ¼âßü–ï×Koý)¯y¯øµ*7ÇOÄÎ�hXzfäãùPañ»Æ7>ðbA§ÊÐßêRU8hÐ »ØôÛ³Yþø'áÛ?ÚÜø†Àj¥ÌbY|×m‘nØ qÜœóšç?ixÜŸ Hsår¤�П+úÒ¶“á'ŒÝÓâ¾°U†A 6ÿ¿ÔÌüMðRü.Ô´ÏxBIlâ) ÞYQˆ$u9(À0 ŸçÇ¡üHÔãÖþßê°�±ÞY[ΫœíÜñœ~Årš¿Ám~öÈC­|N»¸µ.KÕ‘Ów8á¥Æz×Cã�#ûö{»Ò~Ô·bÖÎÄê»D€J˜ dö÷ Sá�­¼eáË]_ůl¬·Zé¶%ˆ‰»�$±#ŸNüb?�¿ ô ÃpëúšØOÂÅ,q±Õ³ƒŒðA§­wÿôR 3“ïûù*�Çïù%Óÿ×Ü?ÌÐãã;�à}¯Š.XKz4ØŠ—ç|Ì)>¿1þ5Â|(øeaâÍ.Oø¹dÔ®/åv†9d`‚í‚ $‚è÷âoÇ#þÌ:3 ;RF¦qüȯBøG$Rü+ðûC�¢§ÞÁ¿PhÏ>'ü"‡K¶´×¼ aw¡ë¾ÚÌ»ŸQ"rH �ÓŽ{cžÓÅ^6Ô¼=ðz-vê¶Öç·Š±í1Ü0ç¦0̰®ãTÕl4[¾Ôîâ´µŒ€ÒÊØPIÀýMyÇÛÛ}gá~—¨é· sdú’0–3•aåʹÏ׊­ð»á.“«x~/øªÔ¯µgDšVÚ¨O Ø9fn¼“Ôwª¿þéþÒÅÞé·£KR6,tÉÊ�Hàq�§2xká‹5? é7Ö_u[kk‹H¤ŠÞ3.ØT !%åéÐt«z�Á¿ÜØK§ñGP–ÍÀ¥ÏšÑ°Ïñ›œu ‚ëÆ÷úŸÀ;�Z7—¨µ‘Ghø) -ØzwaéÅqßþxCÄ~}[U…5=I§u–)%l@àrG99ë^—à¯ÙxkÀð�Þ_Ûêv2CÊP$r+“•Æãî:ת|ò/Qðg‰&ÓœœÇ³a}–T;±õûÐø§àÍî™â½/\ø}V†ó%†K‚]HÆÜäá� ŽŸ�{…|ísâωÿ o-á'tÕô™_`vq&ÿP²`0lr7Ý:×Ð6°êZuµõ³‚æ%š2F2¬¡  QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEx‰4bÚ;IÕ!Òo¤Ó�þí-ÜĸSœ¸�{…P�|`ðñ§…ÌöqnÕì’Û™Wø£üq‘î©®à‡õÝ'ĺÄú¾‘¨Ù,¶ ,—vÏvÞ Á`2kßè øßá�y•â�¡êçö¡�WU÷ö`No>ÎþOüy•ûøÛ÷¸ë׊öÊ(¯ýŸ4=_E_jéWÖsÛ˜þÕnñoÇ™œn8Èéë^×E|Ï®ø;Æw¼A®èZuä3XÌo-f’T¸ÁPU�¬H$ã<€Et2þÐzŒßc›ÁÓÇ­°Æò0]þ» îÿ€þµîôP‰ü'ð>»w⛯xº7Šú}ÆÚWkå† •þåQéô½ñƒÀ:¾§¨Xx¿ÂᎱ§íßxÞê§r²Žì c*ž/¦âxéÖ¾…¢€8�…¾>ðšÙÜ2>£rþ}Û' 60àÔšã#ÐõqûPK«�.÷û0Ç�yöwòãÐ/߽߯Ç^¼WµQ@Q@ñ@ñƒ>('�ô ¾µ“2"ØÛ6:¸…aÎîÄû Ø?´T·0,<#pú‹ ,frêè'éÅ{µã¿<­éú®­âÿÂÖ×ú˜`�8ÚøwÞìËü9`0<j¥ñ/Á¾!мmÄÀ׌»hÓsd.ÒvŽYYx r>ãÛè ?´EËÛýš/\X�¢#1*×w§ëZ? ¼®¿‰o¼wâØÞ-Fì7‘‹µ×wW+ü<|¡}3í^ÍExwÅ¿k¶ž*¶ñï„â’[ȶ5ÌP®ç ƒÂÿ*‘í܈-ÿhMF{Qfžž]h�¢8äb¥ývmÝÿýkÞ( ”ìtí~Ëãw†î¼M�ªêW^ËxÃ;(S逃ŽÃµz‡Ç¯jž$ÐôÝGI‚K™ôÇ�¼ »#…Ë(êH(8óíX^?ÿ“’ð—ýs¶ÿѲW¼Ð…i_´ ÒØÅeá[Û�iT!H¯ë·nW>˜5ÎßxcÆúŸÄ ø§ZÒ®škÝB¤‚ÞÝÝ,aIhr2Œœ˜Éç8ú^Šã~&ø xëÂ2iñ:G} ‰íúo�¤úHü�jòÍ âçˆü§EáÿxjîW´Q3îòØ àH*àt Luë_BÑ@8ß¿‹>:ë¶0ÿeˤønÙ÷´�’¼õmÄ ïŽŒýMz¿ÄÝ&Y~jšV•e4ΰEöñ—bªé€É8ô®ÞŠá¾X^iŸ ´‹;ûIí.£3ï†â3®fr2¤dd¥ñ»M¿Õ¾Ík¦Ù\Þ\˜˜EmHärp šôj(‡Ð<4º¿ÁÍ?ú´Û™ôÔ†T‘ ¼MŽÓЩà÷å‰|YðNK�\Ðå¿ÑŒ¥àž"B‚z”|ƒŒ•8 úsŸ£è ›|Eâ|l–ÓCÐô)¬´•”I4ÒË‘Ñ�ðvŒ’}x¯dÕ<a¨|5 WÛ v©3ÊȘ*ä¼2~¦ºê(ç?xçÅmÛþ%ðü÷zt.ßf�¨PI'kà«)<ã‚3øëþ'ñoÆ£o¡hZ¶A”<óÊISŽ…ß:í$ŽõôuÂxƒáäWŸ ›ÁÚs€ð[ ·‘øÝ*Ù>›ˆ9ôÝ^Sá?Š:ïÃ-)<5âO Ý4v®Â,beRI#�CŒ“‚OZúFŠù·ÄzçŠ~7Ïc¤i>–ÇI†a+ÜLK l¹Ÿp aFIÏzúJÓâÒ4{6LV–ñÛ¡=J¢…Ê®Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@.4M&ïR‡Q¹Ò즾‡UÌ–èÒǃ‘µˆÈÁ'¡ïW袀 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€?ÿÙkalign-3.5.1/doc/images/Quantest2_scores.jpeg000066400000000000000000003370121515023132300211130ustar00rootroot00000000000000ÿØÿàJFIF,,ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ‰a"ÿÄ ÿĵ}!1AQa"q2�‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2�B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷ú(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ d²ÇO,²,q¢–ws€ rI=…>²¼Oÿ"ž³ÿ^3ÿè€*Âwàÿúô?üÃÿÅQÿ ߃ÿèkÐÿðcÿ_/ü,ø{kñQÔ-®¯¦´[X–Eh�6ìœsšôóû5i8ãÄ7 û”ìz~µ¥jÁŽ›©ÙÞ…ëöiÖLß$ÕêùcÇ µŸ†ÖÑx�HÖ$¸·‚E 4ja–Ü“€x'#8ÏqÅ{oÂMã%åæßí Y ½ÉQ€ì!ñÛ �Ç4ÝQEQEQEKRÖ4Í›TÔlìbvدu:ĬÝp “V-n­ïmc¹´ž)íåPшG Ž¯ý¤äNÒì!ÿ´Ú»ß†òLü;ÿ^1ÿ*Ù³ñ‰¨ßIcc¬é÷W‘ç}¼Hò.TŒ ;S×´}ÊþÖÕ¬l<ìùj¸H·ãÆâ3Œ�ÌW›øáf«á_ˆº�ˆîﬥ¶ºYÂÇmã{†È õ®_öšûÞú]í÷èäIcY#uxÜVS�Àô Ó«;@ÿ‘sKÿ¯H¿ôZ4QEQEQEQEQEQEQEŸ©ëÚ>‰åkjÖ6v|¿µ\$[ñŒãqÆGæ*ôr$±¬‘º¼n+)È`zkÀi¯½á¥×þѯoÐ?ä\ÒÿëÒ/ýP�Q@Q@Q@Q@Q@Q@V¾Ô,´»G»Ô/-í-“¦¸�F‹“�–$ÉÅY¯:øåÿ$—Vÿ~ý”ÝØjV:­¨ºÓ¯m¯-Ø�&·•dBGQ•$Uªó/€¿òK-?ëæoý ½6€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ÍÔ4aƒåN=ù?B+˵¿ƒ~*ð,KâWÓõXlO�"÷í©hÜa”wÆHëÛ5ìß >%Åãý2hç�-u[0¾|QýÇSÑÓ<�ÆçsÍs¼sâ?]è© ê?d[”˜Ê<ˆäÜT¦>úœu=+œñO�|mãýzçMðW«¥Z6Ãsiò›ûÆC� öŸg~ÓñýáÏúåqüÒ½‹À:¿‡¼ ¤X[ƨE²I)ïÈʘþ'òÅféÚÅ÷ƒ>êx³Ï{ûb×"ID’;–©`H$’£9ï^9gâoŠßïndÐg{›ìÒ#‹¸O¼ÍŒgú úÄ~ÓüU¢Ë¤ê‰#ÙÊÊΨå ÚA�p+Â÷À¿ tÏìhõ{+ÑÚC ·!åÜz’2[ôí@9«i¼fú¼ºÕåÕ¬t®·ŸiT¬�ž=ñÅzןˆãïK5ÜI£g ŠàG÷[#*àvΠ֌¾6x3þÍJÇO»—R¹¸¶’HàeL²•ù™€ç¶k�ý™¾ç‰þ¶¿ûV€5¿iù´Ÿûí6®÷áŸü“?ÿ׌ʸ/ÚGþDí'þÂûM«½øgÿ$Ïÿõãò =øqãïkß5}SÔüý:ÝnLPù®Ý’_™T€{šÌý¦¾÷…þ—_ûF³¾Év×ÿݼÿÑËZ?´×Þð¿ÒëÿhÐ(¼_ñâ•¥x"9lt«c†K�Â2Ì ´‡‘Ó…^q×Û;W“ãÃ�š�þ©wud•î>Õ'£É\ôÏx9¯tøo¡Ááÿ‡Ú-œ(žÙ'˜�ËHà3ëÉÇÐ èoìmµM>âÂò%–Úâ6ŠTnŒ¤`Ð+ðÛÇöÞ?ðù»¬öì#»·!XŽÙ88Ï¡³U¾)üCô(e·�'Ô¯Y’Ù$û‹´ ÎØêWŽùä?^oü^Ô´#!dhç¶qØ´M�ß_•¿3^ãâÿø{Æom6»¯öEaIÌaAÁ$ãè?*ñ=2Ãã7ŽìÓW‡Xº³´Ÿæ…¾ÕöUuõUNqèHçÞ«ßø‡âÇÂÛÛiµ«É¯,¥l´Ê."—•ß÷”þ ñÜW·\|Bð7‡íÒÍüE§¢[ �c†O4 Q€0™=«È~2|SðçŠü5‹¢4×Oö•™®"ˆ¡C7`äçÓ¦hÞ<5®Ûø›ÃvÕª”Šî! BrPôeü#ð¯,ø±ñ_TÑ5Ä𯅣T`‚iÄ~c+>6¢)à±�zŽõÕ|ÿ’E¡}'ÿÑòWŽ|IMGÀßÄòY™ídž;«v» &{0ÁúphTx+ãuÌ?m}vò9HÝösª•o¦Ðv~µ£ðÓ⧈¢ñ‚ø?Æ[žw�ÁÒ Yb”tVÇ @zäŽH®ÏDøåà�]O&›;uŽò"?ï®WR+i|!àŸk‘ø®[[ëñ,s%ìLÃzciù[oGnÔÕÍ4VÐI<Ò,qF¥ÝØà*�’IôÅ|ñ­|RñŸ�üG&‰àe‚Ñs‰cP%ué½�¸�}1ƒïÎ+Ñ~8j²é µ…нä‘ÚîøXå‡âªGã\Á¿xÁ¾‘5=Umõ[¹ÚK�öYœ…"îT Œdõþ#@ï<7ñ³Ãvíª&µ{{å�ïw¦à¨ôÍøo »ï„ÿ?á7iZ´qÁ¬Â›Á�„¸AÔ�Ù‡qøŽàiÂíøyÿCþI\ñºñ}gH�ö…²Õ<38“N»Ô¢ËF?|È0ÀË¿júºŠ( Ÿÿi¯½á¥×þѪQx¿âÄ?+JðDrØéV0Ç —!„e˜(i#§ ¼ã¯µßÚkïx_éuÿ´kÕ¾èpxáö‹g g¶Iæ rÒ8 Äúòqô€Õ'£É\ôÏx9¯kømãûoø|ÝˆÖ ûvÝÛƒ�¬G ¿ìœgÐŽÙ®ªþÆÛTÓî,/"Ym®#h¥FèÊF |ÝðEæðÿÅíKB2FŽ{g‹DÙ õù[ó4íß|ueà/Bá<ë©O—klGÇEÏÓÔW‹éòübø’�ªYjiú{“å4s}–#ì»~vç?Z¯ñÛR�Qø§a¦_NÐéÖqB’0ìÛ�ð9ÎÒ½?º+Õí¾2|5²µ†ÖÛ\X …qƶ7*�€îý(Ën™I®‹á„øG¡;•a�“ì$zæ>+|\ºððÌk6°ûD³ló<’ßu‰ÎAç dpIã“_|o»·‹kW‘ÌÃp¶:–Æõû€ìJ¥ðRßþ¿‹:—ˆ5ó$…%¼]ÜâWpä±é�_MP„|9ø¹®'ŠSÂ^5Cö§—ÈŽâHÄr$½‘ÀÀ ô 䎹Èì¾9É%տ߃ÿG%/‹þiþ,ñe¿ˆ¿´g±»…cE�ì��Ç=ñ�ô“ã—ü’][ýø?ôrP’xÆ^)›Â6^ ðE™:¡yfº¼u\B…¸Án¹> kC\ð·ÆoYI¬7ˆî¯R2J–·òI±G$˜Ø@ö»?ÙãJ‚ÓÀSê*ƒí·m½ñÎÄ*ýÜõÂ)V‚0Aï@_ðkâMß�ôû»\!Õ,B±•(š3‘¸�À ŽqÇ"¦øÙâ½oÂ>°½Ð¯~Éq-ð‰ßÊI2»ãêyÇìè¡cˉ|ÔÎ ŽQÎG¡=ÆE{]ÿÅOi¥„þ%±b½D fÿЯ øÓñDñ¹Ó-4UšHìÚG{‰cØpQ…žÜäÔôý�Ü7ö6÷–íº ãYcoUa�#^¬üVÕü;ñªûNÔµB<7i¼µ¨‚<·ú1ePÛwd¾1ÏJõ¯ÿÈ�á¿ûÚÿ襯�|[¤E¯þÑòésŒÁqÊ=SËBÃò€4íõŸ‹^>ÖaÖ4Øu+]$̦8íåD#ÝêJùœu<çô©?h/ù(úýyÇÿ£ž¾�Ž4†$Š$T�*¢Œ Ò¾ný¡]cø‡¢Hç ¶HIôW ¢ï¯­tËﯧŽÞÖ/$²*�Þ¼&?ˆþ6ø‹ã“§xìÝ&.âKhäÂgýcïS‚{(ÿ8�Š/QŽˆ¾Ã'žäŸ ó?Úcþ?¼9ÿ\®?šW¼èÿò°ÿ¯hÿô^-ûBèε{ 6•¤_߈£œHmmž]™)ŒíÁü«Úô¤hô{$u*ëoea‚ÑÁ 9øéâëÿ x> }2f‚ëQ˜ÂfC†HÀËm=‰È÷5Ê|9ø£êÞ²×|G5ÅԷщÒÞ9 "£r7óFQ׿Zî~0øëÆÞHôÐQ²—φ2qæŒa“'€O{�zò |añ'€t¸|;¬øqî¨òáY‹[Ê«ÙNTäÜt \Ô¾ø+þÕ®í4 (ž)œM*™Y0‡�\’½p³/Üñ?Ö×ÿjÒ\]|DøËØOðë|ÒÉ"·ïqÈ8/Ï`õ=+”ø[â�WáÏŠotKÍi¥Ô&† cbcxYX€ßtä|çôæ€= ö‘ÿ‘;Iÿ°‡þÓjï~ÿÉ3ðïýxÇü«�øÿ£êzÏ…4Èt½:òúT¾ÞÉkJÊ»d…»o‡–·_4k¸%‚â+4Y"• ºt ò xŸÂù.Úÿû·Ÿú9kGöšûÞú]í_…žÖôÿŒúÝýî�¨[YÈ·[.&µt�³(# FG"¯þÐú±­·‡?²t›ëÿ$\ùŸe·yvgÊÆvƒŒàþF€=?Àš¤:Ï€ô;èX0{8Õ±ÙÕB°ü[ÓM¼M3¬qF¥ÝØà($šù¾ÞãÇ¿o.-"±:§‡å27hØÇÏ|¯ú¶ìAãŽýj–»ñ+Ç?­Žƒ£h¯´ÿ,Éh¬ìãÑä<*úô÷8  ÷xƒãV«®F¤BÕÙ$tó}~sùÐøçâ=WVñ•�‚tùÚ+g 1Q4²(luP ñêIô¯KøUðôx ÃΗ,’j·…dºtä.Ê€÷'žäŸjá~7øZº×-|_áø%¸–$E¸ŽÝ$l‡+"ޤt0®:-à„4ëhÿ´ÒãT¹çi%hÓ>Ê„qõ&±>4øWÃ~ømÿ�"ÊÊiobA$q�íÃn<ž­eX~Ðúê¶W^[�H ¥¢•Ós×=¤þ¬ßøkâ?�ô¯ë–¦Ö+$ e¤ÇÊHÜBg �Î[æ8àcë??ä‘h_Iÿô|• Þ.ðW‰u™|'5Õ­õï™$Oc=³0/w™väm=ûq^uðÇ7SÚÛx.m%•-iô9å¶²íë–<çð¬‰Þñ/‡¡ðªkˆ”•·¸†àŒs´�¿û=s¼à¯ø ­CG‚ëQ‚y!¸s#ƒ�Û— 0u—ò¯lÔ´ë][K¹Ó¯#ZÜÄÐÊžªÃé_5I¢xïைnnôx$¿Ò%82Œ‘Jƒ§˜«Ê0Ï^;à‘šöøSþÿ¡rûû'ÿ\í–™ð~ׯðè–VP�~Þàã�nd©ó}ï»Æ9çµqW¼]­Û¶Ÿ¡øy!¾�ló!W�ÔúªãƒõÍu>ê:ü¾)ñ*°Õ&VC#nx÷}çsýóÓ�9äðìôQE|ÿûM}ï ý.¿ö�zÿ�5HuŸèwа`öq«c³ª…aø0"¼Ãö‡Ðu�m¼9ý“¤ß_ù"çÌû-»Ë³>V3´gò5Î[Üx÷à�åŤV'Tðü¯æFíùï•ÿV݈úüçò5_]ø•㟉ÖÇAÑ´W‚Ú–d´Vvqèò}z{œW±ü*øz<áçK–I5[²]:rå@{�“ÏrOµxïÆk;{�VwzœAô땵š`s†�[cŽ9臧­{2ü!ø~è<;nÊà ‰¤ �ûê«üXøuÿ î…³d�V²,ÖÌü,€ýèÉíœ Ä{šòm⇎¾Ú.‡¯hoq°ÙÚÕ‘ÑG@² †QÛ¯×êÚ·ÃO†z•s©êZ´vɾY ’�£è$öÀ«Ÿ#ð$¶·×¾�RuŠåÕ%PÌ£ ~óÐ7oZñ}cÄ?>2¼:UŽ�ÖÚ^ðÎ#VX²?ŠIƒŽ Èš÷ßøJÛÁ>µÑ­ßÌt̓͌y²Ÿ¼Øôè°áÿ¿äµh_õÂ×ÿG=}'_?|]ðî·©|]ѯl4mBêÒ8mƒÏ«¼jD¬NX  }@MûDÉ7ƒþÂ1èVïÂ8„ß4H�G‚U?Œ�Y¿ô­GXð6Úe…Õìâþ71[BÒ0P¯“…ã‘ùÖç›+½;á–‰i}k5­Ìq¸xgŒ£¯ïò§‘Áã_³ýÀÒ>"jº5Þ#¸–Ùâ {ÉŒ¯å¸þô½x'Å/†zå�Šá5ðjJ÷A<ð[ŒË£«¢ÿnëÉÉ<xÍOÚÅÐ ;¯ [6¢£if&O¼}søŠõüWѼ ¬[éw¶w·W3Â&ÙT튀rÃ’AªÿN~j¤ŒðqÿmR¼ãÀ¾ñ7ŽÎâîåÞ°ÛÆdvĪNO4�ðþIe§ý|Íÿ¡W¦×ž|Óo´¯†ÖÖº�•Í�ÂÜJL74nn^‡@7~Îÿò=kŸõæôj×[ûHÈ�¦ØIôT•‰ð#úÞ�ã=f}OGÔ,¡’ÔªIsjñ«1N`8®Ÿãö‘©ë>Ó Òôë»é“PWhí`iYWËq’2G>ôÔü-ÿ’_áïúô_ækãßü’ÛŸúù‡ÿB®—á½¥Í�Ã� ÖòÞ[{ˆ­UdŠd(èrx ò b|lÓoµ_†÷ºu•ÍåÁ¸ˆˆ­âi€Üœ(&€àgü’]+þºOÿ£^¯|_ÿ’S¯ÿ×ÿÑ‹Q|Óït¿†:e¦¡gqir�1hn"1ºæV#*@#ŽjçÅ;+­Cáž·iem5ÍÌ‘(HaŒ»±Þ§…šäÿgOù'7ö—ÿEÇ\Ä=CVø‰ñ}<ãAa À·DÉÚ ®é$`>ñl};d×£üÒµÀW6Ú�…ÕŒçQ‘ÄW0´LT¤`0}«…ø¡àßøcâü'¶–â•n Š3!†@0ÁÔsµ¹çÜŽ8È i<¦Ä‚æÊ}F`9’ævŸ÷P�ø×ñ÷@м;¢è6ÚF›ibdžVaAYÀUäž§}jÅ¯í ®ÞÆ--<'ÔHÇî¥w¿ë˜Lþ«šñïƒ|¬h�ã?#=ǘ±�>ɶƒîÀÎÐ8äó“@DxþIÿ†ÿìkÿ¢–¼*çþN­ëõ?ô@®ÿ௎®�¯š¿hˆ„þ?Ñ¢'ìQsé™\WÒµà¼;­êþ>ÑntÝP½‚;TW–ÚÕäU>k €pA BÕ>hWdð�„ QæÁpÃ/ö€8‘�rzc�Ž+Ë> øºç¾(ºðN¹º眤K!ÿSr8+ôlcê­}!^ñËáÍíýå·Š|=eq=îåŽîXËHÄ}É^r1ƒ�ö} {¥Ë|=×5]wÂVÓkšm冩înêÝ¢20}C�FEu4QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEUk‰^9VÀÇ¥YªwëGû´Ï´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(í¼Œñ±c’ WûL¿ßýMkþ©þµR€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€-[Ìï&²1éM–yVPØÚ’ÓýwáLŸý{ýh~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ÒâRê pO ©nexÙvœdzUXÿÖ'ÔT÷Ÿy~”Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè(ûL¿ßýEEKö™¿ú >Ó/÷ÿAQQ@ý¦_ïþ‚�´ËýÿÐTTP¿i—ûÿ £í2ÿô/Úeþÿè*Ä’2Û+ƒó9ªUn_øó_  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  ~Ó/÷ÿAGÚeþÿè**(_´ËýÿÐQö™¿ú ŠŠ—í2ÿô}¦_ïþ‚¢¢€%ûL¿ßýi—ûÿ ¨¨  0Í#̪Í�}ªÝP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹U®"y$qŒc­T¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀!¢¦û4žƒó£ìÒz΀%µÿTÿZ©W �’6 Œ“UþÍ' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üè*o³Iè?:>Í' üèm?×~Éÿ׿֦·…ÒL¶1�ZI`v•˜ƒï@¨©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó h©¾Í' üèû4žƒó ãÿXŸQSÞ}åúSRÞ@êHÖ¥¹‰¤e+Ž=è�7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t 7Ù¤ô�f“Ð~t [—þ<×è*/³Iè?:±$lÖꃨ€(ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ÑS}šOAùÑöi=ç@ mþ½åWê¤0:J¬@À÷«tQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@íÕ?ÖªU»_õOõª”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE=§úï™?ú÷úÓí?×~Éÿ׿ր#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ñÿ¬O¨©ï>òý*ÿÖ'ÔT÷Ÿy~”ZŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­ËÿkôR­ËÿkôRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@íÕ?ÖªU«fU��` £Nœ¨ÉOdŽþŠ(¯PøÐ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š({Oõß…2õïõ§Ú®ü)“ÿ¯­GEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP]OþA7ŸõÁÿô\ï�?ãÊïþºå]§ÿ ›Ïúàÿú ®wÀŸñåwÿ]ò®˜_#ÇÄÈÊ�¤¿#¬¢Š+˜öŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­ËÿkôR­ËÿkôRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@#(u*À#Á¥¢€3—ÂzeÉi1,|ýÔ~?PjÅ��µ„^]¼aêz“õ5©kþ©þµR¥B)Ý#iâ*Î<²“h(¢Š£¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š({Oõß…2õïõ§Ú®ü)“ÿ¯­GEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP]OþA7ŸõÁÿô\ï�?ãÊïþºå]§ÿ ›Ïúàÿú ®wÀŸñåwÿ]ò®˜_#ÇÄÈÊ�¤¿#¬¢Š+˜öŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­ËÿkôR­ËÿkôRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@íÕ?ÖªU»_õOõª”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE�¬êòè¶"êÒG.œ`çÓéSéׯ©iðÞHª¯*äªôÖGŒ¿ä¿õÙ‘«Þÿ‘~ÏýÏêkÏ�Y¼t©ßÝå½¾dßÞ±§EW PQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWSÿ�Mçýpý×;àOøò»ÿ®ƒùWE©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü«¦À—Èññò2£é/Èë(¢Šæ=€¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÿÇšýT«rÿÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP»_õOõª•n×ýSýj¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEsÞ2ÿ�ÿ×eþF¯xwþEû?÷?©ª>2ÿ�ÿ×eþF¯xwþEû?÷?©¯.ò1—øR>ѧEW¨XQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWSÿ�Mçýpý×;àOøò»ÿ®ƒùWE©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü«¦À—Èññò2£é/Èë(¢Šæ=€¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÿÇšýT«rÿÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQP^JðXÜMî‘#fQê@È _ñö…áÛ“ks4“]½ ºneú䀶sOð÷ŽtOÎmìæ’;œdA:íb;ã’àkšøGgkq¦_k›R–长~YFü2I'×ð¤ø­¾™—¯Z‡TŠì*ºŒ\Ï®�z-ÕÔV²\ÜÊ‘Aîws€¢¸£ñkÃ"ëÊÍá�8óüŸ“ë×wéYßïäÔí¼=£Û¹DÕfW§Êl¾]âèºjèÿÙ"Î/°ìòü�¼þ>ýs@m.íïí"ºµ™&‚UÜ’!È"¦¯8ø]4¶Wz÷‡¤�ºX\Ÿ+?ï2·áòƒøšôfeE,Ä*�’IÀ€©Ýÿ­îÓ¶t¿ú YÿßõÿkÏ Ù[J“&1º6 3é‘@ÑK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùP«_õOõª•rÔdÍTØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•s¾2ÿ�ÿ×eþF¯xwþEû?÷?©ª^3R45È#÷Ëü�^ðâ±ðýžûžžæ¼¸ÈÆ_áýHûF•»û§ò£ctþUê%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@5?ùÞ×ÿÐMs¾ÿ�+¿úè?•tz¢·öMïÊÔ?oöMsžÙ^`ûÅþUÓàKäxø�ùQô—äu”RìoîŸÊ��ýÓùW1ì E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPU¹ãÍ~‚ªìoîŸÊ—ûBÒôHçV�8hÇQŽ´Ô[Ù &ÆÑK±¿º*67÷OåHBQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT”RìoîŸÊ��ýÓùPQK±¿º*67÷Oå@ E.Æþéü¨ØßÝ?•%»û§ò£ctþT%·úõü•_ª6êÂu$ý½ªõQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEyíÏ€µ�'UžûÂÂX¥ÁÌ–Ó.Pn#“ŒŽ=k–ñö�ªYh°ê:þ°u FK…†(ãc�v±b$…ì?ÞŠßÄžÖ/¾Á¥Ë¬h÷OæF‘1ßôà1œtÁÀéRÁ¥kÞ6ñž§®ØféV-¾G9y9ç¡ì2H É4SÆp¶Ÿâ?<¼$OlO@UãÏó¯S®cÇ^ohBvT½·6݉À'º“Û?Ì Á.ñ’Ø‹á+£©…Ùöž|­ßÞé�ü{€¿ñÅ× Ìbf\އ26?ô^…}möÝ>æÓ~Ï>&�v3·p#8ükžð/…äðΊétáïîŸÍ¸`sƒÙsßþ$×S@7ÿ ?èdoüÿí•Ýø?ÃÁ:+ibë훦i¼Ã—Œ€1ŒŸîú×STîÿÖ�÷hßlÿ¦­lÿ¦­U¢€-}³þ™þ´}³þ™þµVеöÏúgúÑöÏúgúÕZ(×Û?éŸëGÛ?éŸëUh  _lÿ¦­lÿ¦­U¢€-}³þ™þ´}³þ™þµVеöÏúgúÑöÏúgúÕZ(×Û?éŸëGÛ?éŸëUh  _lÿ¦­lÿ¦­U¢€-}³þ™þ´}³þ™þµVеöÏúgúÑöÏúgúÕZ(×Û?éŸëGÛ?éŸëUh  ¥óP¶ÜcÞ¡ûgý3ýimÕ?ÖªP¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P'Ž.<ÝWn?~§¯±«þ¹òü9d»3„<çÜÖWŒ¿ä¿õÙ‘«Þÿ‘~ÏýÏêkˇüŒeþÔ�´ný³þ™þ´}³þ™þµVŠõ -}³þ™þ´}³þ™þµVеöÏúgúÑöÏúgúÕZ(×Û?éŸëGÛ?éŸëUh  _lÿ¦­lÿ¦­U¢€-}³þ™þ´}³þ™þµVеöÏúgúÑöÏúgúÕZ(×Û?éŸëGÛ?éŸëUh  _lÿ¦­lÿ¦­U¢€-}³þ™þ´}³þ™þµVеöÏúgúÑöÏúgúÕZ(×Û?éŸëGÛ?éŸëUh  _lÿ¦­lÿ¦­U¢€-}³þ™þ´}³þ™þµVеöÏúgúÑöÏúgúÕZ(×Û?éŸëGÛ?éŸëUh  _lÿ¦­lÿ¦­U¢€-}³þ™þ´}³þ™þµVеöÏúgúÑöÏúgúÕZ(×Û?éŸëGÛ?éŸëUh ê×{´kåÙÖÞA×ý“\×Ã鼫+ß—9‘{ûVî§ÿ ›Ïúàÿú ®wÀŸñåwÿ]ò®˜_#ÇÄÈÊ�¤¿#¶ûgý3ýhûgý3ýj­Ì{¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ®GJ—oŒn¤ÇW”ã>õÒW/¦È×uþôŸÎ»pŸOCz_ ½ËíŸôÏõ£íŸôÏõª´W�kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«EZûgý3ýhûgý3ýj­kíŸôÏõ£íŸôÏõª´P¯¶Ó?Ö�¶Ó?ÖªÑ@¾ÙÿLÿZ>ÙÿLÿZ«E\ŽçÌ�.Ìg¾jÅP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@š�ˆ$Òn"� Y£$–Æ9Åi×)â�ù Ú»ÿ³WWYBMÎIô;q¡ 4¥«½ÂŠ(­N ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(žñ—ü€×þ»/ò5{ÿò/Ùÿ¹ýMQñ—ü€×þ»/ò5{ÿò/Ùÿ¹ýMypÿ‘Œ¿Ãú‘ö�:(¢½BŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ºŸü‚o?ëƒÿè&¹ßÇ•ßýtʺ-OþA7ŸõÁÿô\ï�?ãÊïþºå]0þ¾G�ˆÿ‘•I~GYEW1ìQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@rúgü�w_ïIü먮_Lÿ‘®ëýé?�vá> ž†ô¾zEQ\FEPEPEPEPEPEPEPEPEPEPEP¶ßë×ñþU~¨[¯_ÇùUú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*�ßúÑþí\ªwëGû´^Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( SÅò´ÿwÿf®®¹OÈNÓýßýšººÆŸÇ#ÐÅÿ»ÑôaEVÇžQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEsÞ2ÿ�ÿ×eþF¯xwþEû?÷?©ª>2ÿ�ÿ×eþF¯xwþEû?÷?©¯.ò1—øR>ѧEW¨XQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWSÿ�Mçýpý×;àOøò»ÿ®ƒùWE©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü«¦À—Èññò2£é/Èë(¢Šæ=€¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®_Lÿ‘®ëýé?�uËéŸò5ݽ'ó®Ü'ÁSÐÞ—Ã/C¨¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@S»ÿZ?Ý«•Nïýhÿv€+ÑEQEQEQEQEQEQEQEQEQEQEQEÊx£þBvŸîÿìÕÕ×)â�ù Ú»ÿ³WWXÓøäz¿÷z>Œ(¢ŠØóŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( {Æ_ò_úì¿ÈÕïÿÈ¿gþçõ5GÆ_ò_úì¿ÈÕïÿÈ¿gþçõ5åÃþF2ÿêGÚ4袊õ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€*êò ¼ÿ®ÿ šç| ÿWõÐ*èµ?ùÞ×ÿÐMs¾ÿ�+¿úè?•tÃøù>#þFT}%ùeQ\ǰQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEËéŸò5ݽ'󮢹}3þF»¯÷¤þuÛ„ø*zÒøeèuQEqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªwëGûµr©Ýÿ­îÐz(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9OÈNÓýßýšººå’ü޲Š(®cØ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ åôÏùî¿Þ“ù×Q\¾™ÿ#]×ûÒ:íÂ|= é|2ô:Š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEUk…ŒÈ7¹…YªwëGû´Ý°ÏFü¨ÛüôoÊ¡¢€&ÛüôoÊ�°ÏFüª(m°ÏFü¨ÛüôoÊ¡¢€&ÛüôoÊ�°ÏFüª(m°ÏFü¨ÛüôoÊ¡¢€&ÛüôoÊ�°ÏFüª(m°ÏFü¨ÛüôoÊ¡¢€&ÛüôoÊ�°ÏFüª(m°ÏFü¨ÛüôoÊ¡¢€&ÛüôoÊ�°ÏFüª(m°ÏFü¨ÛüôoÊ¡¢€&ÛüôoÊ�°ÏFüª(–ñXAªYìbFÎãýªëöÁÿ=ò®;Åò´ÿwÿf®®±§ñÈô1îô}6Ø?ç£~Tmƒþz7åPÑ[y6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@^5XÆ„»“ç/Qìj÷†Ö#áÛ-ÎAØxǹ¬ßÈ ë²ÿ#W¼;ÿ"ýŸûŸÔ×—ùËü?©hÙÛüôoÊ�°ÏFüª+Ô,›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h  ¶Áÿ=ò£lóÑ¿*†Š›lóÑ¿*6Áÿ=ò¨h uU‡û"÷|‰1Çû&¹¿„6W›Ø�Þ.0=« Ôÿäyÿ\ÿA5Îøþ<®ÿë þUÓàKäxø�ùQô—äv[`ÿž�ùQ¶ùèß•CEsÁ6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7å\ž–þë X…ß/8÷®š¹}3þF»¯÷¤þuÛ„ø*zÒøeèuÛ`ÿž�ùQ¶ùèß•CEqmƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U 6Ø?ç£~Tmƒþz7åPÑ@mƒþz7åFØ?ç£~U fˆJ»\“銷T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP)â�ù Ú»ÿ³WW\§Š?ä'iþïþÍ]]cOã‘èbÿÝèú0¢Š+cÏ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9ïÈ ë²ÿ#W¼;ÿ"ýŸûŸÔÕÈ ë²ÿ#W¼;ÿ"ýŸûŸÔ×—ùËü?©hÓ¢Š+Ô,(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š«©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü«¢Ôÿäyÿ\ÿA5Îøþ<®ÿë þUÓàKäxø�ùQô—äu”QEsÀQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW/¦È×uþôŸÎºŠåôÏùî¿Þ“ù×nà©èoKá—¡ÔQEÄ`QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Ýÿ­îÕʧwþ´»@袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šå’ü޲Š(®cØ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ åôÏùî¿Þ“ù×Q\¾™ÿ#]×ûÒ:íÂ|= é|2ô:Š(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@×u�w;_Rp*?µÛÏÄ_÷Ø¥t5öDÔT?k¶ÿŸˆ¿ï±GÚí¿çâ/ûìQt>Iv&¢¡û]·üüEÿ}Š>×mÿ?ßb‹ ä—bj*µÛÏÄ_÷Ø£ívßóñýö(ºIv&¢¡û]·üüEÿ}Š>×mÿ?ßb‹ ä—bj*µÛÏÄ_÷Ø£ívßóñýö(ºIv&¢¡û]·üüEÿ}Š>×mÿ?ßb‹ ä—bj*µÛÏÄ_÷Ø£ívßóñýö(ºIv9¯ÈNÓýßýšººä¼K,rj6¥$Vy*sŽk§û]·üüEÿ}ŠÆ›\ò= Teõz:tdÔT?k¶ÿŸˆ¿ï±GÚí¿çâ/ûìV×GŸÉ.ÄÔT?k¶ÿŸˆ¿ï±GÚí¿çâ/ûìQt’ìMECö»oùø‹þû}®Ûþ~"ÿ¾ÅAÉ.ÄÔT?k¶ÿŸˆ¿ï±GÚí¿çâ/ûìQt’ìMECö»oùø‹þû}®Ûþ~"ÿ¾ÅAÉ.ÄÔT?k¶ÿŸˆ¿ï±GÚí¿çâ/ûìQt’ìMECö»oùø‹þû}®Ûþ~"ÿ¾ÅAÉ.ÄÔTi<26Ô•ú+RSMnQE (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9ïÈ ë²ÿ#W¼;ÿ"ýŸûŸÔÕÈ ë²ÿ#W¼;ÿ"ýŸûŸÔ×—ùËü?©hÓ¢Š+Ô,(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š«©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü«¢Ôÿäyÿ\ÿA5Îøþ<®ÿë þUÓàKäxø�ùQô—äu”QEsÀQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW/¦È×uþôŸÎºŠåôÏùî¿Þ“ù×nà©èoKá—¡ÔQEÄ`QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Ýÿ­îÕʧwþ´»@袊(¢Š(¢Š(¢Šç¼ZOØ­Æxó?¥6ÏÁkwcÇÛŠù±«íò³ŒŒã­/‹¿ãÎßþºå]N�ÿ [ú÷�ÿAÌáÕ|Ǭ±(`àé»]³œÿ„è"ïÏÿ^�øAþ‚'þüÿõë°¢¯ØSìsÿib¿Ÿð_äqÿð‚/ýOýùÿëÑÿ"ÿÐDÿߟþ½vQì)öí,Wóþ üŽ?þEÿ ‰ÿ¿?ýz?á_úŸûóÿ׮Š=…>Áý¥ŠþÁ‘Çÿ¿ô?÷çÿ¯Gü ‹ÿAÿ~úõØQG°§Ø?´±_Ïø/ò8ÿøAþ‚'þüÿõèÿ„è"ïÏÿ^» (öûö–+ùÿþGÿ"ÿÐDÿߟþ½ð‚/ýOýùÿë×aEŸ`þÒÅ?à¿Èãÿá_úŸûóÿ×£þEÿ ‰ÿ¿?ýzì(£ØSìÚX¯çüùü ‹ÿAÿ~úô¿ô?÷çÿ¯]…{ }ƒûKüÿ‚ÿ#�ÿ„è"ïÏÿ^�øAþ‚'þüÿõë°¢�aO°ib¿Ÿð_äqÿð‚/ýOýùÿëÑÿ"ÿÐDÿߟþ½vQì)öí,Wóþ üŽ?þEÿ ‰ÿ¿?ýz?á_úŸûóÿ׮Š=…>Áý¥ŠþÁ‘Çÿ¿ô?÷çÿ¯Gü ‹ÿAÿ~úõØQG°§Ø?´±_Ïø/ò8ÿøAþ‚'þüÿõèÿ„è"ïÏÿ^» (öûö–+ùÿþGÿ"ÿÐDÿߟþ½ð‚/ýOýùÿë×aEŸ`þÒÅ?à¿Èãÿá_úŸûóÿ×£þEÿ ‰ÿ¿?ýzì(£ØSìÚX¯çüùq�ö_‹"´YLž[¯ÏŒg+žŸ�vuÌjò>ÿÀÓÿ@ÓÒ ­Ì—sLÆN~ÎRÝÅQ[žhQEQEQEQM’DŠ6’F Š2ÌN�ÿ “ÿ?Ñþ¿áYέ8|rKÕŠétVgü$ZOüÿGúÿ…ð‘i?óýëþZ¡üëïAtiÑYŸð‘i?óýëþÂE¤ÿÏô¯øQõªξôF�™ÿ “ÿ?Ñþ¿áGü$ZOüÿGúÿ…Z¡üëïAtiÑYŸð‘i?óýëþÂE¤ÿÏô¯øQõªξôF�™ÿ “ÿ?Ñþ¿áGü$ZOüÿGúÿ…Z¡üëïAtiÑYŸð‘i?óýëþÂE¤ÿÏô¯øQõªξôF�™ÿ “ÿ?Ñþ¿áGü$ZOüÿGúÿ…Z¡üëïAtQñ—ü€×þ»/ò5{ÿò/Ùÿ¹ýMbx£V°½ÒDV×)$žj�£=0jÞ‰­é¶Ú5¬3]¢H‹†Sž95æÂ½/¯Ê\Êܽüɺæ::+3þ-'þ£ýÂ�øH´Ÿùþ�õÿ ô¾µCù×ÞŠº4è¬ÏøH´Ÿùþ�õÿ ?á"Òçú?×ü(úÕç_z £NŠÌÿ„‹IÿŸèÿ_ð£þ-'þ£ýÂ�­Pþu÷ º4è¬ÏøH´Ÿùþ�õÿ ?á"Òçú?×ü(úÕç_z £NŠÌÿ„‹IÿŸèÿ_ð£þ-'þ£ýÂ�­Pþu÷ º4è¬ÏøH´Ÿùþ�õÿ ?á"Òçú?×ü(úÕç_z £NŠÌÿ„‹IÿŸèÿ_ð£þ-'þ£ýÂ�­Pþu÷ º4è¬Õñ’̾‹'Žr+J´…XTø~ƒ½ÂŠ(«¢Š(¢Š(¢Š(¬ü_¥A;ÄZf(J’©ÆEoW áM6ÏTñì7° cTf’0w�Ûë[Ñ„$¥)ô<¼Ç^”éÓ¡kͽ͟øM4¯úxÿ¿ýz?á4Ò¿éãþýÿõëoþ þ�Éÿ}·øÑÿ†ƒÿ@äÿ¾Ûüj¯‡ìÌù3_æ‡âbÂi¥ÓÇýûÿëÑÿ ¦•ÿO÷ïÿ¯[ðˆh?ôOûí¿Æ�øD4ú'ýößãEðý˜rf¿ÍÄÄÿ„ÓJÿ§�û÷ÿ×£þM+þž?ïßÿ^¶ÿáÐèŸ÷Û�ðˆh?ôOûí¿Æ‹áû0äÍš‰‰ÿ ¦•ÿO÷ïÿ¯Gü&šWý<ß¿þ½mÿÂ! ÿÐ9?ï¶ÿ?áÐèŸ÷Û�ÃöaÉšÿ4?þM+þž?ïßÿ^�øM4¯úxÿ¿ýzÛÿ„CAÿ rßmþ4Â! ÿÐ9?ï¶ÿ/‡ìÓ5þh~&'ü&šWý<ß¿þ½ðši_ôñÿ~ÿúõ·ÿ†ƒÿ@äÿ¾Ûühÿ„CAÿ rßmþ4_Ù‡&küÐüLOøM4¯úxÿ¿ýz?á4Ò¿éãþýÿõëoþ þ�Éÿ}·øÑÿ†ƒÿ@äÿ¾Ûüh¾³L×ù¡øœíï‹ôË‹ ˆSÏß$L‹”îAµ“á�vÏH·¸KŸ328#bçµwðˆh?ôOûí¿Æ�øD4ú'ýößãVªPQq³³9çƒÌ§Z5Ü¡xÞÛõùŸðši_ôñÿ~ÿúôÂi¥ÓÇýûÿëÖßü"ý“þûoñ£þ þ�Éÿ}·øÔ_Ù�™¯óCñ1?á4Ò¿éãþýÿõèÿ„ÓJÿ§�û÷ÿ×­¿øD4ú'ýößãGü"ý“þûoñ¢ø~Ì93_æ‡âbÂi¥ÓÇýûÿëÑÿ ¦•ÿO÷ïÿ¯[ðˆh?ôOûí¿Æ�øD4ú'ýößãEðý˜rf¿ÍÄÄÿ„ÓJÿ§�û÷ÿ×£þM+þž?ïßÿ^¶ÿáÐèŸ÷Û�ðˆh?ôOûí¿Æ‹áû0äÍš‰‰ÿ ¦•ÿO÷ïÿ¯Gü&šWý<ß¿þ½mÿÂ! ÿÐ9?ï¶ÿ?áÐèŸ÷Û�ÃöaÉšÿ4?þM+þž?ïßÿ^�øM4¯úxÿ¿ýzÛÿ„CAÿ rßmþ4Â! ÿÐ9?ï¶ÿ/‡ìÓ5þh~&'ü&šWý<ß¿þ½ðši_ôñÿ~ÿúõ·ÿ†ƒÿ@äÿ¾Ûühÿ„CAÿ rßmþ4_Ù‡&küÐüLOøM4¯úxÿ¿ýzÚ²½ƒP´K›v-ôÈÁ¬xwIÓü=qskf±Ì¥6°f8Ëzš„?ä]‡ý÷þf‰ÂŸ³ç…÷°aqµ‹ú¾!§îßK÷±»EW1ìQ@Q@Q@g^ëV–ù2—/Œ�«œV�r×ÑG?‹¡ŠUݼjÃÔq]XJP©6§²W5¥'©¡ÿ =‡¤ß÷Èÿ?á'°ô›þùã[?ðŽióäŸ÷Ó�ðŽióäŸ÷Ó�_6´¿¯G³1¿á'°ô›þùãGü$ö“ß#ükgþÍ#þ|“þúoñ£þÍ#þ|“þúoñ£›Ú_€^�fcÂOaé7ýò?Æ�øIì=&ÿ¾GøÖÏü#šGüù'ýôßãGü#šGüù'ýôßãG6´¿½ÌÆÿ„žÃÒoûä�ð“ØzMÿ|�ñ­ŸøG4�ùòOûé¿Æ�øG4�ùòOûé¿ÆŽli~z=™�ÿ =‡¤ß÷Èÿ?á'°ô›þùã[?ðŽióäŸ÷Ó�ðŽióäŸ÷Ó�Ø>Òüô{3þ{I¿ï‘þ4ÂOaé7ýò?ƶáÒ?çÉ?ï¦ÿ?áÒ?çÉ?ï¦ÿ9°}¥øèöf7ü$ö“ß#ühÿ„žÃÒoûä�lÿÂ9¤Ï’ßMþ4Â9¤Ï’ßMþ4s`ûKð ÑìÌoøIì=&ÿ¾GøÖ%–¥ä׎Êrä`sÉâ»OøG4�ùòOûé¿Æ�øG4�ùòOûé¿Æ´…|,I=tèTjRŠi'©�ÿ =‡¤ß÷Èÿ?á'°ô›þùã[?ðŽióäŸ÷Ó�ðŽióäŸ÷Ó�g̓í/À›ÑìÌoøIì=&ÿ¾GøÑÿ =‡¤ß÷ÈÿÙÿ„sHÿŸ$ÿ¾›ühÿ„sHÿŸ$ÿ¾›ühæÁö—à£Ù˜ßð“ØzMÿ|�ñ£þ{I¿ï‘þ5³ÿæ‘ÿ>Iÿ}7øÑÿæ‘ÿ>Iÿ}7øÑ̓í/À/G³1¿á'°ô›þùãGü$ö“ß#ükgþÍ#þ|“þúoñ£þÍ#þ|“þúoñ£›Ú_€^�fcÂOaé7ýò?Æ�øIì=&ÿ¾GøÖÏü#šGüù'ýôßãGü#šGüù'ýôßãG6´¿½ÌÆÿ„žÃÒoûä�ð“ØzMÿ|�ñ­ŸøG4�ùòOûé¿Æ�øG4�ùòOûé¿ÆŽli~z=™�ÿ =‡¤ß÷Èÿ?á'°ô›þùã[?ðŽióäŸ÷Ó�ðŽióäŸ÷Ó�Ø>Òüô{3þ{I¿ï‘þ5vÃS·ÔC˜ e1�Ú³'‡t‘‘d™ÿ�s~ÿYuô_ëU*t'FS¦�Õ·ó�7(ô:z(¢¸p¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEP;âïøó·ÿ®‡ùWS£ÿÈÇþ½ãÿÐErÞ.ÿ�;úè•u:?ü�lëÞ?ýV1þ+= ¿îTýYvŠ(­�<(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šá5ùàiÿ  éë˜Ô?ä}ÿ�§þ€+§¬hï/SÐÇü4¿Â‚Š(­�<(¢Š(¢Š(¢ŠÍ×ÿä{ÿ\Í`x[Ã:Ö—%ÍËή³6`{ƒë[úÿü€o뙨¾ÿÈoúùoýkÈÄÒ…\|#5uÊÿ2¼‡Â¤Ï[¿ûø¿üMð€ióÖïþþ/ÿ]MÕý�…þD>Trßð€ióÖïþþ/ÿGü Güõ»ÿ¿‹ÿÄ×SEÙØ_äAÊŽ[þ #þzÝÿßÅÿâhÿ„Hÿž·÷ñøšêh£û; üˆ9QˤÏ[¿ûø¿üMð€ióÖïþþ/ÿ]Mga‘*9oø@4�ùëwÿÿ‰£þ #þzÝÿßÅÿâk©¢�ìì/ò åG-ÿ‘ÿ=nÿïâÿñ4¤Ï[¿ûø¿üMu4Qý�…þD¨å¿áÒ?ç­ßýü_þ&�ø@4�ùëwÿÿ‰®¦Š?³°¿Èƒ•·ü Güõ»ÿ¿‹ÿÄÑÿ‘ÿ=nÿïâÿñ5ÔÑGövùr£–ÿ„Hÿž·÷ñøš?áÒ?ç­ßýü_þ&ºš(þÎÂÿ"Trßð€ióÖïþþ/ÿGü Güõ»ÿ¿‹ÿÄ×SEÙØ_äAÊŽ[þ #þzÝÿßÅÿâhÿ„Hÿž·÷ñøšêh£û; üˆ9QˤÏ[¿ûø¿üMð€ióÖïþþ/ÿ]Mga‘*9oø@4�ùëwÿÿ‰£þ #þzÝÿßÅÿâk©¢�ìì/ò åG-ÿ‘ÿ=nÿïâÿñ4¤Ï[¿ûø¿üMu4Qý�…þD¨å¿áÒ?ç­ßýü_þ&�ø@4�ùëwÿÿ‰®¦Š?³°¿Èƒ•aâÝÓC6‚Õ¥o;~ï1�é·ÀµÛ[ÿǬ_îå\ïÄo½¦ý%ÿÙk¢¶ÿ�X¿ÜʹpTãOZVK—òU¤Éh¢ŠõË (¢€ (¢€ (¢€ ãü ÿ#5ÿýrý Wa\�äf¿ÿ®Oÿ¡Šé£ü9ž>aþ÷†õ’=Š(®cØ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9ÿÈ©wþòèb³¼!ÿ"ì?ï¿ó5£ãoù.ÿÞOý Vw„?ä]‡ý÷þfºæçú;ÿ‘·ý¹ÿ·´QEsÀQEQEQEW3sÿ#¥·ýt�úWM\ÍÏüŽ–ßõÒ?é]¸Ž_áfô7~‡uEW€QEQEQEQEQEQEQEQEQEQEQEQEQEQEÉÔ¿û¦¸ ÿ¬ºú/õ®â_õ/þé®Âë.¾‹ýk¶‡ûµ_—æoáËätôQEqQ@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢¸-OÇZ�Ö¹>�á]%u í‰M+b5#‚:Žüd‘žÔšŽõKnßIñ^�–\�°Ïf2s�žHÆqÈ#}í7é/þË]·üzÅþàþUÎüFûÚoÒ_ý–º+oøõ‹ýÁü«ËÿWÿ·"ÄÉh¢Šõ (¢€ (¢€ (¢€ ãü ÿ#5ÿýrý Wa\�äf¿ÿ®Oÿ¡Šé£ü9ž>aþ÷†õ’=Š(®cØ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9ÿÈ©wþòèb³¼!ÿ"ì?ï¿ó5£ãoù.ÿÞOý Vw„?ä]‡ý÷þfºæçú;ÿ‘·ý¹ÿ·´QEsÀQEQEQEW3sÿ#¥·ýt�úWM\ÍÏüŽ–ßõÒ?é]¸Ž_áfô7~‡uEW€QEQEQEQEQEQEQEQEQEQEQEQEQEQEÉÔ¿û¦¸ ÿ¬ºú/õ®â_õ/þé®Âë.¾‹ýk¶‡ûµ_—æoáËätôQEqQ@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š‚òg·±¸ž4ÞñÆÎ«ê@Î(Ë´ J‡^#Õ´íu^8oMÒ.ðÊ c sßð9¤ñ&§Ä]oKÒ´yc¶�Í=Ó©@Šp3ÏøœU¯†ÚE�ˆ-/µíb8õ BK’„Üáð§Žÿ€§|IѬ4+ M{IŽ=;P†åUZÜ' ã<~YÍ?âoú~¿á}óä\\þñ}rȿȷç^’ tÅyo�gxïü¯Î›dG›�¸r��ý ò¯SÎF{Pšü7Ùþ+ñN‘E¼W£_î€ì?‘•z-ÍÂZZMs.|¸Q¤l œ“^uðãý?ž)Õ£æ . ÆßÞØÿ ?:ôiáŽæ •wG"”uõ`ŠàásøOû×ß÷ãÿ¯]‡¯Yx¶Àê:Y�Û«˜�š»Ná‚xüEQÿ…aàÏúÅÿdÿâ«SOÒ,<9mö-&ÜZÛ2V-ó 䓨Pß²ÉíùÑöY=¿:oÚ%þÿéGÚ%þÿé@û,žß�e“Ûó¦ý¢_ïþ”}¢_ïþ”ï²ÉíùÑöY=¿:oÚ%þÿéGÚ%þÿé@û,žß�e“Ûó¦ý¢_ïþ”}¢_ïþ”ÎxÆŽÊض9�ÿ*étùØÿ×¼ú®gÆ;Ù[†lþðÿ*é´ùØÿ×¼ú¬cüVzÜ©ú²íQ[xQEQEQEQEQEQEQEQEQEQEQEQEQEQEÂß)íK§þ€+­û,žß�rWä¯�òtÿÐuh—ûÿ¥cGyzž†?á¥þ;ì²{~t}–OoΛö‰¿úQö‰¿úVÇž;ì²{~t}–OoΛö‰¿úQö‰¿úP¾Ë'·çGÙdöüé¿h—ûÿ¥h—ûÿ¥;ì²{~t}–OoΛö‰¿úQö‰¿úPoˆ­äOÞ±Æg½Uøÿ ¿ëå¿ô«>!šFðýè-�c5[áÿü€&ÿ¯–ÿÐV¼ÊŸò1‡ø_æCøŽ®Š(¯L°¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(„ø�÷´ß¤¿û-u6Ö²XOq{ûW-ñïi¿IöZéí§”ZÃóÿöö¯/ þý_þÝüˆ_'û,žß�e“Ûó¦ý¢_ïþ”}¢_ïþ•ê;ì²{~t}–OoΛö‰¿úQö‰¿úP¾Ë'·çGÙdöüé¿h—ûÿ¥h—ûÿ¥;ì²{~t}–OoΛö‰¿úQö‰¿úP¾Ë'·ç\G�Faþ÷†õ’=Š(®cØ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9ÿÈ©wþòèb©ø6“Ãp2ãß¿ûF®xÛþEK¿÷“ÿCGÁÓHž„+`oý×OüÃüÿCÇò6ÿ·?öã¡û,žß�e“Ûó¦ý¢_ïþ”}¢_ïþ•Ì{¾Ë'·çGÙdöüé¿h—ûÿ¥h—ûÿ¥;ì²{~t}–OoΛö‰¿úQö‰¿úP¾Ë'·çGÙdöüé¿h—ûÿ¥h—ûÿ¥;ì²{~uÊ^!�ÆÖÊÝ|Èÿ¥u?h—ûÿ¥r·l_ƶŎO™ô®ÜÇ/ð³z¿C¹¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šd¿ê_ýÓ\Wƒâid»ÛŽÿZíeÿRÿîšâ|!#$—{N2ú×m÷j¿/ÌÞ×Èë>Ë'·çGÙdöüé¿h—ûÿ¥h—ûÿ¥qû,žß�e“Ûó¦ý¢_ïþ”}¢_ïþ”ï²ÉíùÑöY=¿:oÚ%þÿéGÚ%þÿé@û,žß�e“Ûó¦ý¢_ïþ”}¢_ïþ”,6î’«`{Õª§Ò4ʬÙ®PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPŸÜøUÒµIï¼#¬-€¸9’ÚeÌyöàŒrq‘Ç­$Õõ}J Ïë+|�¥¬+ˆÉ÷à zàsë^ƒEexƒ@´ñ�.�vFÃ#¯XØtaþz\xð§ŽVÇû%|Mký�·Ëó<³æìé�»žŸí~5è´PO‡Ó,-$�ÖG=XþŸ€­j( ©Ýÿ­îÕʧwþ´»@袊(¢Š(¢Š(¢Šç|]ÿvÿõÐÿ*êtùØÿ×¼ú®[Åßñçoÿ]ò­½/YÓbÒlã’úu�”¸È!G‚iUw=)ÂRÁSåWÕ›tVöæ•ÿA ûìQý¹¥ÐBßþû¯<{œ^Ưò¿¸Ð¢³ÿ·4¯ú[ÿßb�íÍ+þ‚ÿ÷Ø£ž=ÃØÕþW÷Vöæ•ÿA ûìQý¹¥ÐBßþûsǸ{¿ÊþãBŠÏþÜÒ¿è!oÿ}Š?·4¯ú[ÿßbŽx÷cWù_ÜhQYÿÛšWý-ÿï±Göæ•ÿA ûìQÏáìjÿ+û� +?ûsJÿ …¿ýö(þÜÒ¿è!oÿ}Š9ãÜ=�_åq¡Egÿni_ô·ÿ¾ÅÛšWý-ÿï±G<{‡±«ü¯î4(¬ÿíÍ+þ‚ÿ÷Ø£ûsJÿ …¿ýö(ç�pö5•ýÆ…Ÿý¹¥ÐBßþûni_ô·ÿ¾ÅñîƯò¿¸Ð¢³ÿ·4¯ú[ÿßb�íÍ+þ‚ÿ÷Ø£ž=ÃØÕþW÷Vöæ•ÿA ûìQý¹¥ÐBßþûsǸ{¿ÊþãBŠÏþÜÒ¿è!oÿ}Š?·4¯ú[ÿßbŽx÷cWù_ÜhQYÿÛšWý-ÿï±Göæ•ÿA ûìQÏáìjÿ+û� +?ûsJÿ …¿ýö(þÜÒ¿è!oÿ}Š9ãÜ=�_åq¡Egÿni_ô·ÿ¾ÅÛšWý-ÿï±G<{‡±«ü¯î9MCþGßøèºzå.§ŠçÇh$Y#gL2œƒò]]eGíz�™‚iROùPQE¹çQ@Q@Q@ºÿü€o뙨¾ÿÈoúùoýj]þ@7¿õÌÔ_ÿä7ý|·þ‚µæTÿ‘Œ?Âÿ2ÄutQEze…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@'Äo½¦ý%ÿÙk¢¶ÿ�X¿Üʹ߈ß{MúKÿ²×Emÿ±¸?•yxo÷êÿöïäBø™-Q^¡aEPEPEP\�äf¿ÿ®Oÿ¡Šì+�ð/üŒ×ÿõÉÿô1]4‡3ÇÌ?ÞðÞ¯òG¢QEÌ{EPEPEPEPEPEPEPEPEPEPEPEPEPEP?ãoù.ÿÞOý Vw„?ä]‡ý÷þf´|mÿ"¥ßûÉÿ¡ŠÎð‡ü‹°ÿ¾ÿÌ×OüÃüÿCÇò6ÿ·?öãvŠ(®cØ (¢€ (¢€ (¢€ ænät¶ÿ®‘ÿJé«™¹ÿ‘ÒÛþºGý+·ñËü,Þ†ïÐŠâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€/ú—ÿt×á?õ—_EþµÜKþ¥ÿÝ5ÃøOýe×Ñ­vÐÿv«òüÍáü9|ŽžŠ(®#¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEP;âïøó·ÿ®‡ùW,-æ`†B …5Ôø»þ<íÿë¡þUÔèÿò±ÿ¯xÿô\“§í*5sÜ¡‹xl$$•îÙåßfŸþxIÿ|>Í?üð“þø5ëÔQõUÜ?¶Ÿò~?ð!û4ÿóÂOûàÑöiÿ焟÷Á¯^¢�ª®áý´ÿ“ñÿ€yÙ§ÿžß�³Oÿ<$ÿ¾ zõ}Uwí§üŸ�üÈ~Í?üð“þø4}šùá'ýðkר£ê«¸m?äüàCöiÿ焟÷Á£ìÓÿÏ ?ïƒ^½EU]Ãûiÿ'ãÿò³Oÿ<$ÿ¾ fŸþxIÿ|õê(úªîÛOù?ø�ýšùá'ýðhû4ÿóÂOûàׯQGÕWpþÚÉøÿÀ<‡ìÓÿÏ ?ïƒGÙ§ÿžß½zŠ>ª»‡öÓþOÇþä?fŸþxIÿ|>Í?üð“þø5ëÔQõUÜ?¶Ÿò~?ð!û4ÿóÂOûàÑöiÿ焟÷Á¯^¢�ª®áý´ÿ“ñÿ€yÙ§ÿžß�³Oÿ<$ÿ¾ zõ}Uwí§üŸ�üÈ~Í?üð“þø4}šùá'ýðkר£ê«¸m?äüàCöiÿ焟÷Á£ìÓÿÏ ?ïƒ^½EU]Ãûiÿ'ãÿò³Oÿ<$ÿ¾ fŸþxIÿ|õê(úªîÛOù?ø�ýšùá'ýðhû4ÿóÂOûàׯQGÕWpþÚÉøÿÀ<³GVMnÕYJ°~„cµwõÌjò>ÿÀÓÿ@ÓÕáÕ“^g>i?i*sïŠ(®ƒË (¢€ (¢€ (¢€3uÿùÞÿ×3Q|?ÿ�ßõòßú Ôºÿü€o뙨¾ÿÈoúùoýkÌ©ÿ#…þd?ˆê袊ôË (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€8Oˆß{MúKÿ²×Emÿ±¸?•s¿¾ö›ô—ÿe®ŠÛþ=bÿp*òðßïÕÿíßÈ…ñ2Z(¢½BŠ( Š( Š( ¸ÿÿÈÍÿ\ŸÿCØWà_ù¯ÿë“ÿèbºhÿg�˜½á½_ä�D¢Š+˜öŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Æßò*]ÿ¼Ÿú¬ïÈ»ûïüÍhøÛþEK¿÷“ÿC�áùaÿ}ÿ™®Ÿù‡ùþ‡ŽÿämÿníÆíQ\ǰQEQEQEÌÜÿÈémÿ]#þ•ÓW!¬\5§‰ÂÍÆô8Ý—¦êI.Ì߯&¼�C¢¸øM¯çÚßõÿ?á6½ÿŸk×ühþίÛñ«T;Š+‡ÿ„Ú÷þ}­ÿ_ñ£þkßùö·ýÆ�ìêý¿úµC¸¢¸øM¯çÚßõÿ?á6½ÿŸk×ühþίÛñ«T;Š+‡ÿ„Ú÷þ}­ÿ_ñ£þkßùö·ýÆ�ìêý¿úµC¸¢¸øM¯çÚßõÿ?á6½ÿŸk×ühþίÛñ«T;Š+‡ÿ„Ú÷þ}­ÿ_ñ£þkßùö·ýÆ�ìêý¿úµC¸¢¸øM¯çÚßõÿ?á6½ÿŸk×ühþίÛñ«T;Š+‡ÿ„Ú÷þ}­ÿ_ñ£þkßùö·ýÆ�ìêý¿úµC¸¢¸øM¯çÚßõÿ?á6½ÿŸk×ühþίÛñ«T;Š+‡ÿ„Ú÷þ}­ÿ_ñ£þkßùö·ýÆ�ìêý¿úµC¸¢¸øM¯çÚßõÿ?á6½ÿŸk×ühþίÛñ«T;Š+‡ÿ„Ú÷þ}­ÿ_ñ£þkßùö·ýÆ�ìêý¿úµC¸¢¸øM¯çÚßõÿ?á6½ÿŸk×ühþίÛñ«T;Š+‡ÿ„Ú÷þ}­ÿ_ñ£þkßùö·ýÆ�ìêý¿úµC¸¢¸øM¯çÚßõÿ?á6½ÿŸk×ühþίÛñ«T;YÔ¿û¦¸ ÿ¬ºú/õ§7�/J›h9ïþ4ß ÿ¬ºú/õ­¾¯Rާ?[~eû9Bœ¹¼ŽžŠ(¯,å (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPTîÿÖ�÷jåS»ÿZ?Ý  ôQEQEQEQEs¾.ÿ�;úè•u:?ü�lëÞ?ýW-âïøó·ÿ®‡ùWS£ÿÈÇþ½ãÿÐEcâ³Ð«þåOÕ—h¢ŠØóŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Pÿ‘÷þŸú®ž¹�CþGßøèºzÆŽòõ= ÃKü((¢ŠØóŠ( Š( Š(  Ýþ@7¿õÌÔ_ÿä7ý|·þ‚µ.¿ÿ ßúækÍ⻹� Cq,jNpŽ@Ïá^aŠXld*5wõ3“´®{uâ¿ÚWßóûsÿ[ühþÒ¾ÿŸÛŸûúßãSý¿äx½¡íTWŠÿi_ÏíÏýýoñ£ûJûþnïë�ÛðþG÷‡´=ªŠñ_í+ïùý¹ÿ¿­þ4i_ÏíÏýýoñ£û~Èþðö‡µQ^+ý¥}ÿ?·?÷õ¿Æ�í+ïùý¹ÿ¿­þ4oÃùÞÐöª+Å´¯¿çöçþþ·øÑý¥}ÿ?·?÷õ¿Æ�íø#ûÃÚÕEx¯ö•÷üþÜÿßÖÿ?´¯¿çöçþþ·øÑý¿äx{CÚ¨¯þÒ¾ÿŸÛŸûúßãGö•÷üþÜÿßÖÿ?·áü�ïh{Uâ¿ÚWßóûsÿ[ühþÒ¾ÿŸÛŸûúßãGöü?‘ýáíj¢¼WûJûþnïë�ÚWßóûsÿ[ühþ߇ò?¼=¡íTWŠÿi_ÏíÏýýoñ£ûJûþnïë�ÛðþG÷‡´=ªŠñ_í+ïùý¹ÿ¿­þ4i_ÏíÏýýoñ£û~Èþðö‡µQ^+ý¥}ÿ?·?÷õ¿Æ�í+ïùý¹ÿ¿­þ4oÃùÞÐöª+Å´¯¿çöçþþ·øÑý¥}ÿ?·?÷õ¿Æ�íø#ûÃÚÕEx¯ö•÷üþÜÿßÖÿ?´¯¿çöçþþ·øÑý¿äx{CÚ¨¯þÒ¾ÿŸÛŸûúßãGö•÷üþÜÿßÖÿ?·áü�ïhuÿ¾ö›ô—ÿe®ŠÛþ=bÿp*ò™®g¸Ç�4’í齋có¯V¶ÿ�X¿ÜÊ´Ë1 ˆ«U+^ßä8;¶Éh¢Š÷ Š( Š( Š( ¸ÿÿÈÍÿ\ŸÿCØWà_ù¯ÿë“ÿèbºhÿg�˜½á½_ä�D¢Š+˜öŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Æßò*]ÿ¼Ÿú¬ïÈ»ûïüÍhøÛþEK¿÷“ÿC�áùaÿ}ÿ™®Ÿù‡ùþ‡ŽÿämÿníÆíQ\ǰQEQEQEÈêÖÆóÄËli”¢îÆq‘]us7?ò:[×Hÿ¥w`U$×fo‡v“~EŸøAäÿŸõÿ¿_ýz?á“þ×þýõë±¢§ûCüß‚Ö*w8ïøAäÿŸõÿ¿_ýz?á“þ×þýõë±¢�í Gó~>±S¹ÇÂ'üÿ¯ýúÿëÑÿ<Ÿóþ¿÷ëÿ¯]�hb?›ðAõŠ�Î;þy?çýï×ÿ^�øAäÿŸõÿ¿_ýzìh£ûCüß‚¬TîqßðƒÉÿ?ëÿ~¿úôÂ'üÿ¯ýúÿë×cEÚ�æü}b§sŽÿ„Oùÿ_ûõÿ×£þy?çýï×ÿ^»(þÐÄ7àƒë;œwü òÏúÿ߯þ½ðƒÉÿ?ëÿ~¿úõØÑGö†#ù¿X©Üã¿á“þ×þýõèÿ„Oùÿ_ûõÿ׮Ɗ?´1Íø úÅNçÿ<Ÿóþ¿÷ëÿ¯Gü òÏúÿ߯þ½v4Qý¡ˆþoÁÖ*w8ïøAäÿŸõÿ¿_ýz?á“þ×þýõë±¢�í Gó~>±S¹ÇÂ'üÿ¯ýúÿëÑÿ<Ÿóþ¿÷ëÿ¯]�hb?›ðAõŠ�Î;þy?çýï×ÿ^�øAäÿŸõÿ¿_ýzìh£ûCüß‚¬TîqßðƒÉÿ?ëÿ~¿úôÂ'üÿ¯ýúÿë×cEÚ�æü}b§sŽÿ„Oùÿ_ûõÿ×£þy?çýï×ÿ^»(þÐÄ7àƒë;œwü òÏúÿ߯þ½ðƒÉÿ?ëÿ~¿úõØÑGö†#ù¿X©ÜãÁ.¨ÍöõàgýWÿ^«øOýe×Ñ­wÿ©÷MpþÿYuô_ë[¬EJØzœîö·æhªJtåÍätôQEy‡(QEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ çüMãø8Ú�{QûÚ·ù?¹’MÛq»î)Æ7¾µÐVˆ¼áÿc®i©yömÞNçeÙ»¾év�Ê€9¿ø]¿?èaÿÉ+�þ7Gü.߇Ÿô0ÿä•Çÿ¬ß|*ðF�à­vúÓ@†+›}>yb�K!*ëynÄWð;À¾ñO…µ ½oJŽòx¯Lhí#®bœ|¤w&€=_Fø©à¿jÖúV—¬ý¢öà‘_e™7`ydpS]�pvžømá/ÙI Z^�¬g6©-éY[vPmF~s’:u®ò€ +?P×´}"h¡Ôµk )fÿT—7)?nŸÂ�w­iV¶öWš�•µÕÉ N¨ò’p©9nxã½^¢¹­â…<1qöm_[¶·¸ïÝ#¯ÕP?¿¡x›Dñ5³\hº�½ìk÷ü¦ù“ýå<�ÄPµW)¬üKðo‡ïÓR×í£¸C‡Š0Ò²FÖ€:º+Bñ^ƒâxšMU¶¼Ù÷Ö7ù×ê§‘øŠØ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Ýÿ­îÕʧwþ´»@袊(¢Š(¢Š(¢Šç|]ÿvÿõÐÿ*êtùØÿ×¼ú®[Åßñçoÿ]ò®§Gÿ�-�ý{Çÿ ŠÆ?Åg¡WýÊŸ«.ÑE±ç…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@&¡ÿ#ïü ?ô]=s‡ü�¿ð4ÿÐtõ�åêzÿ†—øPQE±ç…Q@Q@Q@ºÿü€o뙬ÏèÚv¡£K5ݤrÈ'e Þ›W�ÔÖž¿ÿ ßúæj/‡ÿò›þ¾[ÿAZò«B3Ì ¤®¹_æCø�_øF4_úCúÑÿÆ‹ÿ@èZÖ¢»¾­CùÜŠ²2áÑèëGü#/ý¡ýkZŠ>­CùÜ‚ÈÉÿ„cEÿ t?­ðŒh¿ô‡õ­j(úµä_r #'þ�þ�Ðþ´Â1¢ÿÐ:Öµ¨£êÔ?‘}È,ŒŸøF4_úCúÑÿÆ‹ÿ@èZÖ¢�«PþE÷ ²2áÑèëGü#/ý¡ýkZŠ>­CùÜ‚ÈÉÿ„cEÿ t?­ðŒh¿ô‡õ­j(úµä_r #'þ�þ�Ðþ´Â1¢ÿÐ:Öµ¨£êÔ?‘}È,ŒŸøF4_úCúÑÿÆ‹ÿ@èZÖ¢�«PþE÷ ²2áÑèëGü#/ý¡ýkZŠ>­CùÜ‚ÈÉÿ„cEÿ t?­ðŒh¿ô‡õ­j(úµä_r #'þ�þ�Ðþ´Â1¢ÿÐ:Öµ¨£êÔ?‘}È,ŒŸøF4_úCúÑÿÆ‹ÿ@èZÖ¢�«PþE÷ ²2áÑèëGü#/ý¡ýkZŠ>­CùÜ‚ÈÉÿ„cEÿ t?­ðŒh¿ô‡õ­j(úµä_r #Î|q¦Yi­cö;t‡Ìó7mï�¸þfºÛoøõ‹ýÁü«�ø�÷´ß¤¿û-tVßñëûƒùW1Ž6²Š²÷"cñ2Z(¢½RŠ( Š( Š( ¸ÿÿÈÍÿ\ŸÿCØWŸøoXµÑuÛË‹¿3c« ع9Üô®ª ¸M#ÄÍ*Fž'9»$ßä�T¢¹øO´_úyÿ¿cühÿ„ûEÿ§Ÿûö?Ʋö?”íþÓÁÿÏÅ÷�EËÿÂ}¢ÿÓÏýûãGü'Ú/ý<ÿß±þ4{ ŸÊÚx?ùø¾ó¨¢¹øO´_úyÿ¿cühÿ„ûEÿ§Ÿûö?Æ�aSùCûOÿ?ÞuW/ÿ ö‹ÿO?÷ì�ðŸh¿ôóÿ~ÇøÑì*(iàÿçâû΢Šåÿá>Ñéçþý�ñ£þíþžïØÿ=…Oåí<üü_yÔQ\¿ü'Ú/ý<ÿß±þ4Â}¢ÿÓÏýûãG°©ü¡ý§ƒÿŸ‹ï:Š+—ÿ„ûEÿ§Ÿûö?Æ�øO´_úyÿ¿cühö?”?´ðóñ}çQErÿðŸh¿ôóÿ~ÇøÑÿ ö‹ÿO?÷ì�§ò‡öžþ~/¼ê(®_þíþžïØÿ?á>Ñéçþý�ñ£ØTþPþÓÁÿÏÅ÷�EËÿÂ}¢ÿÓÏýûãGü'Ú/ý<ÿß±þ4{ ŸÊÚx?ùø¾ó¨¢¹øO´_úyÿ¿cühÿ„ûEÿ§Ÿûö?Æ�aSùCûOÿ?ÞuW/ÿ ö‹ÿO?÷ì�ðŸh¿ôóÿ~ÇøÑì*(iàÿçâû΢Šåÿá>Ñéçþý�ñ£þíþžïØÿ=…Oåí<üü_yÔQ\¿ü'Ú/ý<ÿß±þ4Â}¢ÿÓÏýûãG°©ü¡ý§ƒÿŸ‹ï:Š+—ÿ„ûEÿ§Ÿûö?Æ�øO´_úyÿ¿cühö?”?´ðóñ}å�È©wþòèb³¼!ÿ"ì?ï¿ó5KÄž.Ó5]{;o?Ír¤nL_j»áùaÿ}ÿ™­e F…¤ºþ‡*ôëfœÔ¥uÉÓÔÝ¢Š+”÷BŠ( Š( Š( ¹›Ÿù-¿ë¤Òºjænät¶ÿ®‘ÿJíÀürÿ 7¡»ô;ª(¢¸ŒŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Kþ¥ÿÝ5ÃøOýe×Ñ­wÿ©÷MpþÿYuô_ë]´?ݪü¿3x_#§¢Š+ˆÀ(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@Q@÷�ä�ø—þÁw?ú)«Î¿fïùõ_ûŸý•è¾=ÿ’wâ_ûÜÿ覯:ý›¿äKÕì"ôZP´F‰#èšW‰-r·}Ç”î½B¿*Qÿ}W©ø[[�Ä~Ó5ˆñ‹»t‘€þÇÌ?Èü)¾-ÐÓľÕ4g7VìˆO@ýPþ ü+žøìø{áO‰­î›mÖ†Yà�ýdáWõ×9ÿz€‡ü,OÚ?ë4Ý ¯qˆOäs+~"¡ý îîl»>È?Õ¼7óKðÿ#È?á×è'ýô¿ãGü"Zïý¤ÿ¾—ük×è£ë³ìƒý[Ã4¿ò<ƒþ-wþ�ÒßKþ4Â%®ÿÐ:Oûéƽ~Š>»>È?Õ¼7óKðÿ#È?á×è'ýô¿ãGü"Zïý¤ÿ¾—ük×è£ë³ìƒý[Ã4¿ò<ƒþ-wþ�ÒßKþ4Â%®ÿÐ:Oûéƽ~Š>»>È?Õ¼7óKðÿ#È?á×è'ýô¿ãGü"Zïý¤ÿ¾—ük×è£ë³ìƒý[Ã4¿ò<ƒþ-wþ�ÒßKþ4Â%®ÿÐ:Oûéƽ~Š>»>È?Õ¼7óKðÿ#È?á×è'ýô¿ãGü"Zïý¤ÿ¾—ük×è£ë³ìƒý[Ã4¿ò<ƒþ-wþ�ÒßKþ4Â%®ÿÐ:Oûéƽ~Š>»>È?Õ¼7óKðÿ#È?á×è'ýô¿ãGü"Zïý¤ÿ¾—ük×è£ë³ìƒý[Ã4¿ò<ƒþ-wþ�ÒßKþ4Â%®ÿÐ:Oûéƽ~Š>»>È?Õ¼7óKðÿ#È?á×è'ýô¿ãGü"Zïý¤ÿ¾—ük×è£ë³ìƒý[Ã4¿ò<ƒþ-wþ�ÒßKþ4Â%®ÿÐ:Oûéƽ~Š>»>È?Õ¼7óKðÿ#È?á×è'ýô¿ãGü"Zïý¤ÿ¾—ük×è£ë³ìƒý[Ã4¿ò�(¢Š(¢Š(¢Š+™¹ÿ‘ÒÛþºGý+¦®fçþGKoúéô®ÜÇ/ð³z¿Cº¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šd¿ê_ýÓ\?„ÿÖ]}ú×q/ú—ÿt×á?õ—_EþµÛCýÚ¯Ëó7‡ðåò:z(¢¸ŒŠ( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQEQE…ã[y®ü â {hdšytÛ„Ž(Ô³;Øä’{WðGÔôoêPêšuÝŒ¯~]Rꉙ|´€ÈÈ5ëTP_%üQðÍ݇śÝ#NÈ]nXåŠ%8en„×@Õôg�|{¤øÒÖçVŠîHî]‘>ÌŠÄ3ÎXW“ü7‚ïâ/ÅËÿÝÛݨ£±*¹cŽ„�Z÷JƒCÐìt«aû›H8ë´c'ÜõükÁ¿hK7Ô|má›ÙVK˜¼•fè H'ó¯¢+Á~5ÿÉQðWûñÿèá@ cñsÄž±MÅþ¹žêÑDQ]¬›DÊ8$ßïÏqœÖUž•â��ž4´Õu�>M?ö‡åV.Ìä¢öl ¶0Ð úBŠã>&x|qáÓ )í» ¬Ý¸Pà´ú ‘í^[¡|\ñ€4è¼?âï ]ÊöŠ"†}Þ[I\��鎽kèZ(ç÷ñgÇ]vÆì¹tŸ Û>ö‘òWž­¸�½ñÀqŸ©¯¢mm¡³´†ÖÝC kj?…@À�©h Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Ýÿ­îÕʧwþ´»@袊(¢Š(¢Š(¢Šç|]ÿvÿõÐÿ*êtùØÿ×¼ú®cňíc *’NH8ªö¾0ºµ´†Ýlãa*IçÌæ¡U¶zñÃξ ŸFÎòŠâ?á7¼ÿŸ¿3Gü&÷Ÿóãæjþ±LÃû/ÛñGoEqð›ÞÏŒ_™£þ{Ïùñ‹ó4}b˜eâ{~(íè®#þ{Ïùñ‹ó4Âoyÿ>1~f�¬Sì¼OoŽÄÂoyÿ>1~f�øMï?çÆ/ÌÑõŠaý—‰íø£·¢¸�øMï?çÆ/ÌÑÿ ½çüøÅùš>±L?²ñ=¿vôWÿ ½çüøÅùš?á7¼ÿŸ¿3GÖ)‡ö^'·âŽÞŠâ?á7¼ÿŸ¿3Gü&÷ŸóãæhúÅ0þËÄöüQÛÑ\9ñÅØëeÿ�_øMï?çÆ/ÌÑõŠ}Ãû/ÛñGoEqð›ÞÏŒ_™£þ{Ïùñ‹ó4}b˜eâ{~(íè®#þ{Ïùñ‹ó4Âoyÿ>1~f�¬Sì¼OoŽÄÂoyÿ>1~f�øMï?çÆ/ÌÑõŠaý—‰íø£·¢¸�øMï?çÆ/ÌÑÿ ½çüøÅùš>±L?²ñ=¿vôWÿ ½çüøÅùš?á7¼ÿŸ¿3GÖ)‡ö^'·âŽÞŠâ?á7¼ÿŸ¿3Gü&÷ŸóãæhúÅ0þËÄöüQÛÑ\Gü&÷Ÿóãæhÿ„Þóþ|büÍX¦ÙxžßŠ#Ô?ä}ÿ�§þ€+§®2ÚêmSÅ1^4;Y˜ œÒ»:TùŸ™YŒ\=œ^ê((¢ŠÜóBŠ( Š( Š(  Ýþ@7¿õÌÔ_ÿä7ý|·þ‚µ.¿ÿ ßúæj/‡ÿò›þ¾[ÿAZó*ÈÆá™â:º(¢½2Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( â7ÞÓ~’ÿìµÑ[Ǭ_îå\ïÄo½¦ý%ÿÙk¢¶ÿ�X¿Üʼ¼7ûõûwò!|L–Š(¯P°¢Š(¢Š(¢Š(®?À¿ò3_ÿ×'ÿÐÅvÇøþFkÿúäÿú®š?ÙãæïxoWù#Ñ(¢Šæ=€¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ÿñ·üŠ—ï'þ†+;Âò.Ãþûÿ3Z>6ÿ‘RïýäÿÐÅgxCþEØßæk§þaþ¡ã¿ùÛŸûq»EW1ìQ@Q@Q@s7?ò:[×Hÿ¥tÕÌÜÿÈémÿ]#þ•Û�øåþoCwèwTQEqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ —ýKÿºk‡ðŸú˯¢ÿZî%ÿRÿîšáü'þ²ëè¿Ö»h»Uù~fðþ¾GOEW€QEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€)êN�«Â°êZ}­ìJw*\²(> 0<ÔööÐYÛ¥½´1Á $q UQ쥢€ £{¢iZ�Ô77Úe•ÕÄÅ,öêï9ùIóÅ^¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ §wþ´»W*µÃªÈŒ7MT¢¦ó“þx­rÏ h©¼äÿž+GœŸóÅh*o9?çŠÑç'üñZ†Š›ÎOùâ´yÉÿ•ÛÛÿǬ_îå\¸*�©Œ­8;§Ëù .òd´QEzå…Q@Q@Q@qþÿ‘šÿþ¹?þ†+°®?À¿ò3_ÿ×'ÿÐÅtÑþÏ0ÿ{Ãz¿É‰EW1ìQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿ�¿äT»ÿy?ô1YÞÿ‘v÷ßùšÑñ·üŠ—ï'þ†+;Âò.Ãþûÿ3]?óóýÿÈÛþÜÿÛ�Ú(¢¹�`(¢Š(¢Š(¢Š+™¹ÿ‘ÒÛþºGý+¦®fçþGKoúéô®ÜÇ/ð³z¿Cº¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šd¿ê_ýÓ\?„ÿÖ]}ú×q/ú—ÿt×á?õ—_EþµÛCýÚ¯Ëó7‡ðåò:z(¢¸ŒŠ( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQETSýÑõ©j)þèúÐâkÈ5)­­í£a“�¡¨á'ÕçÆ?ûößãOÒ¿ä{—ýù?‘®æ¹ §;¾n§¯^t0ü±öiÝ'¹ÁÿÂOªÿÏŒ÷í¿Æ³õMFÿVXÖkM¢2HØ�ßë^™E7FMYÈÎúTä¥I?S€‡Äz¤0ÇÙ!¡A1·aõ§ÿÂOªÿÏŒ÷í¿Æ»Ê)û)ÿ1/A»º+ï8#â�TM”`þ[�lè:¼š´34±¢ðŸÄšôš(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ §wþ´»W*�ßúÑþíW¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(”ñGü„í?ÝÿÙ««®SÅò´ÿwÿf®®±§ñÈô1îô}QE±ç…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ tIchäPÈà ¤dYÿð�é?óãëZTVs¥NSõB±›ÿþ“ÿ>1~´Â?¤ÿÏŒ_­iQQõjȾäFoü#úOüøÅúÑÿþ“ÿ>1~µ¥EV¡ü‹îAdfÿÂ?¤ÿÏŒ_­ð�é?óãëZTQõjȾäFoü#úOüøÅúÑÿþ“ÿ>1~µ¥EV¡ü‹îAdfÿÂ?¤ÿÏŒ_­ð�é?óãëZTQõjȾäFoü#úOüøÅúÑÿþ“ÿ>1~µ¥EV¡ü‹îAdfÿÂ?¤ÿÏŒ_­ð�é?óãëZTQõjȾäG%â�*ÆËIÛ[$oæ¨Ü¾˜5oDÑtë�Öi­#yrÌ{òi|eÿ 5ÿ®Ëü�^ðïü‹öîS^t(RþДyU¹{y“eÌ/ü#úOüøÅúÑÿþ“ÿ>1~µ¥Ez?V¡ü‹îEY¿ð�é?óãëGü#úOüøÅúÖ•}Z‡ò/¹‘›ÿþ“ÿ>1~´Â?¤ÿÏŒ_­iQGÕ¨"û�Y¿ð�é?óãëGü#úOüøÅúÖ•}Z‡ò/¹‘›ÿþ“ÿ>1~´Â?¤ÿÏŒ_­iQGÕ¨"û�Y¿ð�é?óãëGü#úOüøÅúÖ•}Z‡ò/¹‘›ÿþ“ÿ>1~´Â?¤ÿÏŒ_­iQGÕ¨"û�Y£@Ò•�0äzŒÖ•V�§| /AØ(¢Š° (¢€ (¢€ (¢€ ó�?R½ðö³w4v›Ý·FVE< Ùíô¯G¢¶¥UBé«ÜóñØb\%ò¸ìís�ÿ„ÿTÿ l?“Qÿ þ©ÿ@Ø&®¾Š¿mOù?¨c?è%ÿà+üÎCþýSþ�°þMGü'ú§ýaüšºú(öÔÿ“ñ¨c?è%ÿà+üÎCþýSþ�°þMGü'ú§ýaüšºú(öÔÿ“ñ¨c?è%ÿà+üÎCþýSþ�°þMGü'ú§ýaüšºú(öÔÿ“ñ¨c?è%ÿà+üÎCþýSþ�°þMGü'ú§ýaüšºú(öÔÿ“ñ¨c?è%ÿà+üÎCþýSþ�°þMGü'ú§ýaüšºú(öÔÿ“ñ¨c?è%ÿà+üÎCþýSþ�°þMGü'ú§ýaüšºú(öÔÿ“ñ¨c?è%ÿà+üÎ@ü@ÕÉÓ¡èßãM_ˆZ“ýÝ>ún?Öº}OþA7ŸõÁÿô\ï�?ãÊïþºåZFTœù68ªSÆC ?·~ònö]ªÐ6ɨÿ„ÿTÿ l?“W_Egí©ÿ'âvýCÿA/ÿ_ærðŸêŸô ‡òj?á?Õ?èäÕ×ÑG¶§üŸˆ}CÿA/ÿ_ærðŸêŸô ‡òj?á?Õ?èäÕ×ÑG¶§üŸˆ}CÿA/ÿ_ærðŸêŸô ‡òj?á?Õ?èäÕ×ÑG¶§üŸˆ}CÿA/ÿ_ærðŸêŸô ‡òj?á?Õ?èäÕ×ÑG¶§üŸˆ}CÿA/ÿ_ærðŸêŸô ‡òj?á?Õ?èäÕ×ÑG¶§üŸˆ}CÿA/ÿ_ærðŸêŸô ‡òj?á?Õ?èäÕ×ÑG¶§üŸˆ}CÿA/ÿ_æpZ¿‹5 _M’Ê[D�‚YCd`ƒý+£ð¤REáèDd$±†2kjŠ™ÖR‡$cbð¹}JUý½ZœîÖÚÝnQE`z�EPEPEP\ÅÛ*xÊݘ…Q$d’pJéëRÐPºûGžcb#nz~5׃©Mó»&š5£%>c¥ûm§üýCÿm´ÿŸ¨ïà®;þ5ÿŸÃÿ~ÿúôÂ&¿óøïßÿ^«ÙaççàÊä¥üß�Øý¶Óþ~¡ÿ¿‚�¶ÚÏÔ?÷ðWÿšÿÏáÿ¿ýz?á_ùü?÷ïÿ¯G²ÂÿÏÏÁ‡%/æüÇí¶Ÿóõýü}¶Óþ~¡ÿ¿‚¸ïøD×þýûÿëÑÿšÿÏáÿ¿ýz=–þ~~ 9)7àv?m´ÿŸ¨ïà£í¶ŸóõýüÇÂ&¿óøïßÿ^�øD×þýûÿëÑì°¿óóðaÉKù¿±ûm§üýCÿm´ÿŸ¨ïà®;þ5ÿŸÃÿ~ÿúôÂ&¿óøïßÿ^�e…ÿŸŸƒJ_Íø�Ûm?çêûø(ûm§üýCÿqßð‰¯üþû÷ÿ×£þ5ÿŸÃÿ~ÿúô{,/üüürRþoÀì~Ûiÿ?PÿßÁGÛm?çêûø+Žÿ„Mçðÿß¿þ½ð‰¯üþû÷ÿ×£ÙaççàÃ’—ó~cöÛOùú‡þþ >Ûiÿ?PÿßÁ\wü"kÿ?‡þýÿõë*×K:´¶>vÐ…†ý¹Î¦kHapóMƦÞCT©»µ-�Fûm§üýCÿm´ÿŸ¨ïà®;þ5ÿŸÃÿ~ÿúôÂ&¿óøïßÿ^³öX_ùùø1rRþoÀì~Ûiÿ?PÿßÁGÛm?çêûø+Žÿ„Mçðÿß¿þ½ð‰¯üþû÷ÿ×£ÙaççàÃ’—ó~cöÛOùú‡þþ >Ûiÿ?PÿßÁ\wü"kÿ?‡þýÿõèÿ„Mçðÿß¿þ½Ë ÿ??”¿›ð;¶ÚÏÔ?÷ðQöÛOùú‡þþ ã¿á_ùü?÷ïÿ¯Gü"kÿ?‡þýÿõèöX_ùùø0ä¥üß�Øý¶Óþ~¡ÿ¿‚�¶ÚÏÔ?÷ðWÿšÿÏáÿ¿ýz?á_ùü?÷ïÿ¯G²ÂÿÏÏÁ‡%/æüÇí¶Ÿóõýü}¶Óþ~¡ÿ¿‚¸ïøD×þýûÿëÑÿšÿÏáÿ¿ýz=–þ~~ 9)7àv?m´ÿŸ¨ïà£í¶ŸóõýüÇÂ&¿óøïßÿ^�øD×þýûÿëÑì°¿óóðaÉKù¿®–öÔÄÿé0ýÓÿ-qÞÿYuô_ëOÿ„Mçðÿß¿þ½iiZBibB%24˜É#Çÿ®­Ê…:3„%víÐmÂ0j.÷4¨¢ŠóÎp¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEÿt}jZŠº>´ÀC¨C¦øºâê`æ5’@v žr+¡ÿ„ÛLÿžw_÷Àÿóµ‚óÆ“Ãq’2ò§èk«ÿ„wHÿŸÿ_ñ®Jj¦¼¯©íâå†NÕ6ùVÅøM´Ïùçuÿ|ñ£þm3þyÝßüjÿü#ºGüøÇúÿ�ðŽéóãëþ5¥«wG'>ùeø?á6Ó?ç�×ýð?Æ�øM´Ïùçuÿ|ñ«ÿðŽéóãëþ4Â;¤ÏŒ¯øÑjÝÐsà–_�•wã6{9âXîw*Юï<Í2Æ ÖÐyH6§ñ¸õ=I¬{Ÿx߯¾.ÕôO› >ÏI“Êžúìn,Ù+À!¸%[ié’FqQøâ+Ÿ�ž8’' ‚=™ªÈ§õ¦›Àpê^#ÔüCðëÆËa},¤ÞÁ ,Й $îñ““‚œãý'Å>?ðÇ�tÝÆ1Zêvz‹ŠþÊ,ylNpª1’2r st﯎ü2òë�¼7:‰R uÍ·D2Ç?%O9é[ÓøçÇŸµm:߯ðiÚŽ—{7’/¬þWSÆN0çF{“ã?üŽ?ì(ôdÔjzö¯ðÿáÌÚ—ˆnÓZÕabªñD"³6a@À¯�r–1ük×l"Ö!Õô]:;„ÅdðŒí##9�ˆãÕ³ëŠì¾$øèxñÞÅj.ïnf[BN±å±Î:¹ZŃEø¯«À$ÔÿÉuñçÐèB©ü´’Ãâ7Ž­&½’öXfT’æO½+ ,}ÉÍ\øÿ%×ÇŸAÿ¡ ›_ñ÷Š|AãK¯ x U’Ç"óQ¹ª08 g xèI à`f³õ|Løo%½ÿ‹ZÃ[Ñe”G4¶ˆâϦ0zõ™ï� ‘k^5µ¸ j+| ¡�Ì@iü›?˜®¿ã,¶Ñ|)ÖÅÉ\:F‘‚z¿˜»qøŒþ€;K+È5 {ÛY–÷¬±8èÊà þF§®GájMÃ,ùßö5#?Ý$•ÿÇH®º€ (¢€ (¢€ (¢€ (¢€ (¨çž+[yn&p‘D…Ý�EP2Oå@T_ZO1†¨$” ”IlzàWÎÑEâߎúÝì±ê ¥øfÚO-ä¨ôAßœœ öàUÿ…þOüxÖtîšé-tÎ&dÚ[w�ý2q÷±øPÐ4WÏ:ܾ/ø3âÕÕýõ jnÏNѸ–+´Ÿ‘ñ’àãžâ¾�·¸ŠîÚ+˜<2 ‘wR2å@ÑEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@§Š?ä'iþïþÍ]]rž(ÿ��§û¿û5uu�?ŽG¡‹ÿw£èŠ(­�<(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šç¼eÿ 5ÿ®Ëü�^ðïü‹öîST|eÿ 5ÿ®Ëü�^ðïü‹öîS^\?äc/ðþ¤}£NŠ(¯P°¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®§ÿ ›Ïúàÿú ®wÀŸñåwÿ]ò®‹Sÿ�Mçýpý×;àOøò»ÿ®ƒùWL?�/‘ãâ?äeGÒ_‘ÖQEÌ{EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP\¾™ÿ#]×ûÒ:ê+—Ó?äkºÿzOç]¸O‚§¡½/†^‡QEW€QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ Šº>µ-E?ÝZâ4ù¢ƒÆóI4‰“,ìè{šìµ4ÿùþµÿ¿Ëþ5Ï^øZ ËÉ.>Ñ"⸚¯ÿlóù'ýð+š*¤.’=j²ÂW唦ÓI-ާûSOÿŸë_ûü¿ãGö¦Ÿÿ?Ö¿÷ùƹoøC`ÿŸÉ?ï�Y:戚JBÉ3IæF1ŒS•J‘Wq&– Vj¨îüŽÿûSOÿŸë_ûü¿ãGö¦Ÿÿ?Ö¿÷ùƹ+Ã5´R›¹t �£ŒŠ“þØ?çòOûàSç«ü¤:4ìê?¸èoõ+Ó®Uom‹˜%\“ƒï\ïƒ?ÔÝÿ¼¿Ö—þØ?çòOûàV¾“¤E¤Å"G#Hd9fn(Jr𔕬T燧‡•:rm»tìnŽ‚ŠAEny�\GćPxÓìwÖ·ÒiºÝ�Í­ìc‘ÎB¶8Ï ƒÇ?Jíè »øwñ7Ä–ÃJñ'�lÎ�Äy¢Ö/ÞH ç™üIZèügðåµO†Vþðë[Û-»Æc7NÁp¤’IU'q$ž�I¯B¢€9mwÁpx—À á�Bo-…¼H'ˆnÙ"†ã##§µpø'âö›¦E¢Xx¿NþÍEò’R–8ú`#Ž˜l�Q^ÑEyï…מñv§~o¡º°¹µH£bÍç4Ÿ)vaŒX1cÁNÿág‰t_ßë^ñ,Zh¿s$ö·)”ÜI?Ý`FIÆW#=k×( '´ø]â-{]±Õ<âXõ4±q$V±íˆ·žc gåÉõ­¯‰ÞÔ|e�w£êYêZUÁšœ„�§’Áô5ßQ@y­xUñ§€"Ò•ê~²›Mð¦�cp15µŒ0ÉŸï*Q^uàŸ‚6š°šçˆ5Ö5D1å£ÿx’IvA8Ç¥zÕQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP)â�ù Ú»ÿ³WW\§Š?ä'iþïþÍ]]cOã‘èbÿÝèú0¢Š+cÏ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9ïÈ ë²ÿ#W¼;ÿ"ýŸûŸÔÕÈ ë²ÿ#W¼;ÿ"ýŸûŸÔ×—ùËü?©hÓ¢Š+Ô,(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š«©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü«¢Ôÿäyÿ\ÿA5Îøþ<®ÿë þUÓàKäxø�ùQô—äu”QEsÀQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW/¦È×uþôŸÎºŠåôÏùî¿Þ“ù×nà©èoKá—¡ÔQEÄ`QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( ¢Ÿî�­KMr  Ã#é@(«âþèü¨ß÷Gå@ëÄúuÍüÿf�Ì(Ç# uú×M¾/î�Ê�ñt~U3Š’³5¡ZTj*‘Ý­chm!‰±¹TãÔ –¬o‹û£ò£|_Ý•R3nîåz*Æø¿º?*7ÅýÑùP"QÐQEQEQEQEQEQEQEQEQEQEQEQEQEQEUMSO‹VÒ/tÙÉÝÀðHW¨WR§�«tPο ¼Ggð«Ä:Ÿ‡µûÛy4ëÇYmµWÄHÈÉÛ’21î烚öˆü}àé:ø«Eÿzþ%?‘l× ÿ íàÏùúÖ?ð!?øŠ‡þ€Ä¾Wöž¥ætÙö¸³ùl Aÿ„ïÁÿô5èø1‡ÿŠ®‚¼“þÛÁŸóõ¬àBñëtQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@§Š?ä'iþïþÍ]]rž(ÿ��§û¿û5uu�?ŽG¡‹ÿw£èŠ(­�<(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šç¼eÿ 5ÿ®Ëü�^ðïü‹öîST|eÿ 5ÿ®Ëü�^ðïü‹öîS^\?äc/ðþ¤}£NŠ(¯P°¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®§ÿ ›Ïúàÿú ®wÀŸñåwÿ]ò®‹Sÿ�Mçýpý×;àOøò»ÿ®ƒùWL?�/‘ãâ?äeGÒ_‘ÖQEÌ{EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP\¾™ÿ#]×ûÒ:ê+—Ó?äkºÿzOç]¸O‚§¡½/†^‡QEW€QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ Šº>µ-E?ÝZ¯EqÚ—‹¯­õYí-­bu‰Š�Á‹u<¯ÿ †³ÿ@ø¿ïÛÿ�y²Í°Ñ“�ÞžDs£¹®OÇ7Ckf±JèØ�§Àª_ð˜k?ô‹þý¿øÖf±ªj:ÒD³ÙìG—sŸ¯Ò¸ñÙ•¸yB�îü¼Å)¦´=ÅÚM>ÙÜ’Í’Os�V+‚ƒÅZÄñº|ecP ˜ß8µ'ü&Ïýâÿ¿oþ5Ó Û¢“¿ÜÇÎŽæŠá�Œ5€ :|@¤Æÿã[Þ×%Ö �¦‰â`>LàƒõúVÔ3ª*pnïÈjIèu ¢�ÐQ]åQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@G<ñÛ[É<Î(�»±è “RVWŠ-&Ô<%¬Ù[g¸±ž(Àë¹£`?S@ öŸüq×/WN¾}/Ãvï³Ц; ÌŽG8<n3¯ÿ Ñmäcþ‰¼ì}ï± ¹úoþµ¥û;ëz|ž»ÐüÄ�Q‚éæhIÃ:0Pø#ÓÖ½ž€>o>4ø®Y.¥zú§†®fLwÚ˜Üp8>ý¾Œ‚hî`Žx\µ-E?ÝZàtù(Ó×I‘¯C¯0‡SƒJñ½ÍäáÚ$–@B žr+¦ÿ„ÿHÿžW÷íøªðòü] QœjI'ÌÌã$·:š+–ÿ„ÿHÿžW÷íøª?á?Ò?ç•ßýû_þ*»ÿ´p¿ÎŠæGSErßðŸéóÊïþý¯ÿGü'úGüò»ÿ¿kÿÅQý£…þtÈßÔÿäyÿ\ÿA5Æx ýE÷ûÉü�]¼ñΕqcq GuºHÙQq’1ëT|G“|;îOë\rÄR­Ž¤éÊöOòÓ’±ß‚ŠAE{%…y¿ˆâô#¥zExÿŠÿäå<ÿ^ü§ `¢¼¯Å=Öu¿¯ƒþ¼mfûSdªƒÈäOcÁôôê_�kÇ[u:?ñ,ÊÈÿgæéýêã~ÿÉuñçÐèB¶|â�kUø©âíöóÍÓôò>Í”‹åüØûÀhÒh¯%×üqâ¿øÎóž[X›O½Ô®@*Œ Œ‚8øë]Öu½_Âþ)·…5�/æ2Â0$\àä;©pAéë¯á?‡ãÃ^/ñˆ¥ÔEäú¼¥Õ|�†.X®wÝTvû´ÇÜ|Rñ¿„n­äñׄ`·ÓgpŸi°}Ûýöàž¼3ƒŠõûK¸/ì໵•e·ž5’)£)~¼ãã–»¥Øü>¼ÒndI/õ ‰ml\�àïÇP>¸Óü<Ó.ô‡Ú…ðeºŠÕ|Än¨O;OÓ8ü(¦¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠŠææ+;I®§p�Â�$Œ{('òä¾5ø¯¬É®xgRþÉÔ]Ì�ÈŒ¹êÊËÊßü+žÿ…{ñŸoÙÿá0ýßO3ûN_ç·uRÓî<{ñ›\º½°ÔäÒ|?m6ÕA+"Ô.™'< öÈô=ÜæÎxl2ÆÉ»ÆF3@Mà¯�ÐéÌz/ímF7$c&0ã£37.Glãñ¯_¯›î¿á9ø!ªÙ\ÝjO«xzy|¶BìÈ{•Úßêß ƒƒŽø"¾‹µ¹ŠòÒ¨<3F²Fú‘�#@Ó%F’EbŒÊ@aØúÓè 8ÿ…}â�úµûî_þ9X#Ñ|I ÉemŒ5+ÛûÙ|¸m’Y‘݉Þp:�kØnn"´µ–æw H]ÜôU$× àˆ&ñ±}ãä?½c‚7ü³ˆ?—×w­]ñ7ˆ.<àÛ5i>Õª4inŽä¶ùüÎsÉ韩Ž<'ㆱþÑ>+œjE|ϱóåç®Þ»sÿÇó¤ø‰þ‘ã_Ú¿1�H=d@•zUrþñCøŸEg¹@—ÖÏå\(ölvÏóºŠó_~ãâ‹m“ˆÌÌØ$lèF½P¸{M6êæ5$0¼Š§¹�(ÍS»ÿZ?ݯÿ…ËâŸúí¿ïÔ¿ã^‡à�vóÅšj:•²ZN³´B4  ÍÏs@4U¿²ÇýóùÑöXÿ¾:©E[û,ß?�e�ûçó  ”U¿²ÇýóùÑöXÿ¾:©E[û,ß?�e�ûçó  ”U¿²ÇýóùÑöXÿ¾:©E[û,ß?�e�ûçó  ”U¿²ÇýóùÑöXÿ¾:©E[û,ß?�e�ûçó  ”U¿²ÇýóùÑöXÿ¾:©E[û,ß?�e�ûçó  ”U¿²ÇýóùÑöXÿ¾:©E[û,ß?�e�ûçó 'Åò´ÿwÿf®®¹ŸF±êÖaNFÁÿ¡WcöXÿ¾:ÆŸÇ#ÐÅÿ»ÑôeJ*ßÙcþùüèû,ß?�lyåJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�r~2ÿ�ÿ×eþF¯xwþEû?÷?©¨Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þt•©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü««Õ­£]ø‡9òüt×3ðú%’Ê÷sc/ò®˜_#ÇÄÈÊ�¤¿#§¢­ý–?ïŸÎ�²Çýóù×1ì(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtRŠ·öXÿ¾:>Ë÷Ïç@(«e�ûçó£ì±ÿ|þtR¹}3þF»¯÷¤þuÙý–?ïŸÎ¹ &5oÝ¡Ë÷Ïç\FJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�T¢­ý–?ïŸÎ�²ÇýóùÐJ*ßÙcþùüèû,ß?�Cmþ½åWêàDpÁ‰"§ Š( Š( Š( ¢Ÿî�­KQO÷GÖ€<îÆÎÞûÇ×÷1,‘4’’§¡à×eÿ¶‰ÿ@è¿3þ5Èi³Åoñy&•"A$¹g` p{šî¿µôÏúÚßõÿñrøPq›¨•ùžö3�º•?áÑ?èæÆ�øE´OúEùŸñ«Úúgým?ïúÿ�Úúgým?ïúÿ�wû<'hþZ%OøE´OúEùŸñ£þmþ�Ñ~güjßö¾™ÿAOûþ¿ãGö¾™ÿAOûþ¿ãG³Âv�à‰—á­-:êD°‰]!vR3ÁûÖ€¿Ô_¼ŸÈ×O¨êºsé—j·ö¬Æ ”’vŸzæ<þ¢ûýäþF¸§QÇRöilöôœÊÇz: (ìàŸ4ÝKXøÙáÍ;I½ûíΜc[œ�cRÓo#çnïñkÞëƒÖü©j_tC=¢Øiö­ ±»°•˜‰~è Œ|ã©èÏ4˜$ø!ñ&->ây%ðζˆ‚æ\|’/›¬yÿeÁí^›ñ'ÇcÀ~Žö+Qw{s0‚Úp¥ˆ'-ŽÃ\�­[ñ÷ƒ­¼qáK�&R©qþ²Öfê¥Ðò±5ËÍð×Vñ'Ã+_ ø§P¶•„€ÙßZ3H0£ ¼0Rx%OÐæ€‹ñ_W€I¨x§LÑ|Á–†ÊÈLÑç¶[¿ÐŸ­s¿-$°ø�ã«I¯d½–•$¹“ïJÂGËrsZöÞø¯V¥lèÞ[ã, ‘Õyá� 'Žø«á�rÑjž1ñÕµ©®RÞÊÞÝvC œ³•P$à àvëÆ;Šÿò@ìë�Ÿòé~�bð†‹l U°­s6ð^£â†6Þ±–Ú´KpZá™Pl<¨'·¥v=¤š~‰ae)V’ÞÞ8œ¡È%T�n(Êü%ÿ'#ã/úñOå^ñ�µÍCÅà¯[Ç.ª‹þ—'1Ú3í‘‘’s‚p=5ô?êZgŽÅsOhÖ�²ÅhìeR<¿¼ à�ô'µp–_ >(hºÞ­©h¾"Ñm$Ô§if%™Ù²ÌÃ;¡8ûÇ¥v>øI§hšˆ×5˹uÝ|°sutIXÛÕTç‘ØœôãèÕãð‹üpÿ¡ÓGÿ¾ûž½Göúµ¯‡ì ×.¢ºÕ<\OÝvÏQÂûv§EPEPEPEPEPYž"°—UðÆ­§Bq-ÕœÐ!Î0Ì…GêkNŠñ€>(Óm4[¯ ßJ–z¬7nëÇa”=X Ž¸Ç¾=¾¼×Ç?ô^I¨Ã,šf§'2M IO«'>à�|×ÿ ÄÀ}�|d¿eþî$øîì~´§û@x£M¸Ðí|-g*]ê³]¤�Gyˆ@’qŸlúç‡,%Òü/¤éóËke Î~e@§õÂøঅàûèõ;™äÕ5(Îc–T GûÊ™<û’}±^›@Q@ÅMJX4 }&Ûþ>59Ä@ê'õ*?]†•§Å¤é6š|?êíâXÁõÀäþ'šÏÕ|+c¬ëš~«u5Ï›`CE²ˆÉ »$ž wì+r€<çâ¤Ú¾‡¯Åq§Ü�3åYU#ñ®éu[Ò†¨.¢û—æùÛ¾]¾µ5Õ¬Ö²ÚÝD“A*ítq�¸ÃðŸÃž~í×ÂÛ¾Ïçþïùgõ  ? á’ú÷_ñ ‘”Kë“ågýæfÿЀü z=Aigoai­¤) .Ô�=Nïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP)â�ù Ú»ÿ³WW\§Š?ä'iþïþÍ]]cOã‘èbÿÝèú0¢Š+cÏ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€9ïÈ ë²ÿ#W¼;ÿ"ýŸûŸÔÕÈ ë²ÿ#W¼;ÿ"ýŸûŸÔ×—ùËü?©hÓ¢Š+Ô,(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š«©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü«¢Ôÿäyÿ\ÿA5Îøþ<®ÿë þUÓàKäxø�ùQô—äu”QEsÀQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW/¦È×uþôŸÎºŠåôÏùî¿Þ“ù×nà©èoKá—¡ÔQEÄ`QEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( ¢Ÿî�­KQO÷GÖ€9-CÁÖ××ÒÝ ©#2¶â»Aªßð�ÛÿÏô¿÷À®ºŠá–[…”œœ5~¤ò#‘ÿ„ßþ¥ÿ¾bx‡Ãñè‘ÀÉpÒù¤ƒ¹qŒcükÒk›ñ~—w©[Úý’/1£s¹AóŽyúW;,¡<�({Ý7îL ­¡Ÿkàˆ.-!˜ÞÈ ˆ¯�ƒŒŒÔßð�ÛÿÏô¿÷À®¢Î&‚Ê_’5S�P1SWD2¼/*¼5ùÿ˜ùÈÿÂoÿ?Òÿß¶´]9F‘�fn:t­J+z8 =sÓ�ŸÌj)l]‚Šë((¢Š(¢Š(¢Š(¢Šóÿü-·Õü@Þ!Ñu«ÝX‘vÍ=§+(ÿir9àwÁÇLóU´„‰»m¬ø›ÄZ‡ˆîíu²Ý|±FÙÎvå»àã8ö5é4PEPEPEPEPEPEPEPEPsÏ­¼·ȱÃwc€ªI?…xïįˆ5»›O‡öoo§[¶<à‰¹‡fw“å\õ 9úצü^»’ËáN¿,LC4)#û¯"¡ýÕ_‚š|? ´–…T=Ï™<¬¿ÄÅØsôGá@eþ¨š†&Õ56âÎ×Íœ‚2J®Häð>µó®œÿ>2jw—¶:£éúl/´/Ú^#îvœ‘øŒ�^�ûAk_ÙßWOFÄš•ÊFGû ó“ù…�tß ô1 |6Ñ­Jm–hE̾¥¤ù¹÷�øP•i^,ñ·Â�Ùé4¹{íí¶­ÃÊe ¹º9ù¾\Œ©íØdúFG"¼öŒ·ŽOXÎÀy‘j(÷ÁŽL�нÂ3Isའy³æË§[»ç®LjMlÑEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@§Š?ä'iþïþÍ]]rž(ÿ��§û¿û5uu�?ŽG¡‹ÿw£èŠ(­�<(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šç¼eÿ 5ÿ®Ëü�^ðïü‹öîST|eÿ 5ÿ®Ëü�^ðïü‹öîS^\?äc/ðþ¤}£NŠ(¯P°¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®§ÿ ›Ïúàÿú ®wÀŸñåwÿ]ò®‹Sÿ�Mçýpý×;àOøò»ÿ®ƒùWL?�/‘ãâ?äeGÒ_‘ÖQEÌ{EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP\¾™ÿ#]×ûÒ:ê+—Ó?äkºÿzOç]¸O‚§¡½/†^‡QEW€QEQEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ k•nJuE?ÝZ7ÅýÑùQ¾/î�Ê«Ñ@7ÅýÑùQ¾/î�Ê«×#㻉¡µ³X¥t ìNÖÆp?�]8sÉDæÆbV„«5{¶ø¿º?*7ÅýÑùV}ƒ´šu´ŽK3D„“Ü�*ÅKVv7Œ¹¢¥Ü±¾/î�Ê�ñt~U^ŠEh tPEPEPEPEPEPEPEPEPEPEPEPEPEP'‹ô!âojš6à¯wnÉ7@ã•'Ûpáÿ þ*Ãà: x¶Îò±™ÄN‘î1ää£.AêIg9¯¢ë ]ðg†üLë&³£ÚÝÊ£WL8›†=³@=x›^—ãWÄ­#KÒíçM.°o0BA–VàpöÍ}%ªëW‡4Ñw©ÝÁef„FC…°•A¡x[BðÌO‹¥ÛY >ûDŸ3}Xò:‡ÅžÓ|g£ +U3‹a*Ëû— ÙÇ8÷¸d ;tߎ¡Kž¹õ�ðÿýE÷ûÉü�ix:2ä]ŽETs?Xié+[ÐôÐQ@è(®#è¼Åòržÿ¯þS×°W‚|XÓu-cãg‡4í&÷ìW·:q�nrA�KM¼Œs�»¿Äu ŸÅ=Öu¿¯ƒþ¼mfûSdªƒÈäOcÁôô긮‡á‡Žu_ˬhþ ´†ßYÑåLaádÉaœdò ž‡#Z ⾯“PñN™¢ùƒ- •�™£Ïl·¡?Zç~ ZIañÇV“^É{,3*Is'Þ•„�–>俀.|?ÿ’ëãÏ ÿÐ…lø7Å:Ö«ñSÅÚ-íç›§éä}š)Ëù±÷€þ$Ö7Ãÿù.¾<úýRü<ÿ’áãï¨ÿШ}Ç+ñŒï<)൉´ñ‹ÝJä¨Àà¨È#ƒÇBI°Ísž1ñ¯ÄÿèÏi­Ïe<×d}�V³�NÆV‘•�/+ŸáÄöÕøÂ=SƖׂêÌï™Çþ…»ó«ÿ´<¶ëðæå+æ½ü~HÏ9 Ù?–:Ðøƒâ­kCøEk®i×¾F¥"[›ÊFÉp7|¬ óô¬=>ÿ⿎m#Ö´MCOÐô·\[Gs´—q½¾FÆN}=�êdø¯ÿ$Çþ¹Ùÿ!^—áhÖ/h± ÂP;ÐðÏÇZî³­êþñM¼)¬é1–�"ç qÝH#‚O]ÍÂ?�o|IâF½¹�ß–»»’pÊU.í´*ç1ã“À®;Â_òr>2ÿ¯þPWkái~:þÖµ·´ž&°“ȹ‚éWæÎG@NGÊG4æ|m¥|M°±ð�„V]Fúâí%óZ3q…'.ïéÓ5îU‘Ót{+'˜m­ã„¿÷¶¨ý+Ëþ4øGÃÖþ¼Ö­ì-lu+'‰à¸¶ŒDÌÆE]§n3Á'ØŒ×sà-BïUð‡}~Ì×SYÆÒ;us�¼~½訢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*�ßúÑþí\ªwëGû´^Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( SÅò´ÿwÿf®®¹OÈNÓýßýšººÆŸÇ#ÐÅÿ»ÑôaEVÇžQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEsÞ2ÿ�ÿ×eþF¯xwþEû?÷?©ª>2ÿ�ÿ×eþF¯xwþEû?÷?©¯.ò1—øR>ѧEW¨XQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWSÿ�Mçýpý×;àOøò»ÿ®ƒùWE©ÿÈ&óþ¸?þ‚k�ð'üy]ÿ×Aü«¦À—Èññò2£é/Èë(¢Šæ=€¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®_Lÿ‘®ëýé?�uËéŸò5ݽ'ó®Ü'ÁSÐÞ—Ã/C¨¢Š+ˆÀ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@E?ÝZ–¢Ÿî�­yÞ™<6ÿ.$žTŠ1$¹g` p{šï?¶4ÏúÙÿßõÿæ5Û_ßÍt.¥ŒÊÛ™B‚3U¿á·ÿŸùï�]“tjY¹[NÇÏáá˜ayá jIÉ»Ýu;í�3þ‚6÷ýÆ�í�3þ‚6÷ýƸÿø@-ÿçþ_ûàVˆü;‡»Çpòù¥�Ü cÿP£Fo•Kð.¾?B›©RŠIyž™ý±¦ÐFÏþÿ¯øÑý±¦ÐFÏþÿ¯ø×kàh.-!˜ÞÈ ‘«�q‘š›þ ùÿ—þø.�ö¿EŠÌ¤®¨¯üéµ-[M}.íWP´fh\&RIÚ}ë—øÿ÷ßï'ò4ïø@-ÿçþ_ûàVÞ‡¡Ã¡Á,qJò4Œ 3 téÅ9Jœi¸ÅÞäS¥Œ­Œ§Z´TSë}ÑÑ‚ŠAEržàW­ø'RÔ¾.è>,†{E°ÓíZcwa+1ýÐùÇR;×yEs>ðu·Ž<)s¤ÊU.?ÖZÌÃýT£¡úAö&¹y¾êÞ$øekáŸêÃR°�;ëFiaw† O©úœ×§Ñ@QmáŠóĺ~¡ã«8lØÓÚÁºå—ýâŠA÷ÝŸ­3Ã? uïxîKýX¶: ÉAu ÖZwQÉÛŒç'9zW­Q@…ü©hŸ|Kâ;™íÏTÈHÝŒ‹È?0*éØš<+à�KCø�âo\Ïhöš©BDìd^só Àšïh Ö|1·ã­GXøwâˆtß[+R¶to-Žq–Hê¼ðÀ�“Ç|UðƹaáHµOø„jÚÔ×)oeon»!…NYʨ ’pp;uã¥â_…¶ú¿ˆÄ:.µ{ k.Ù§´åeí.G<ø8éžj¶�ð‘#×mµŸx‹PñÝ£n¶[¯–(Û9ÎÜ·|gÆ€.xÛÁz�‰þÛxrÆ[hnÑ-Ák†eA° ò žÞ•Øhö’iú%…”¥ZK{xâr‡ •P=¸«´P¡ø'RÓ>-ëþ+š{F°Ôm–(£Gc*‘åýàW|‡¡=«#Ä_ 5h¼UqâëÃGÔ.²na•sŒy'¡êy ©çž+Ôè …~1ñeå¿ü'Þ,ŽïO�Ë;Ú®}ÎÔ¿8'ã¯^··ŠÖÚ+{xÖ8b@‘¢ŒP0ö¤¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ §wþ´»W*�ßúÑþíW¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(”ñGü„í?ÝÿÙ««®SÅò´ÿwÿf®®±§ñÈô1îô}QE±ç…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@÷Œ¿ä¿õÙ‘«Þÿ‘~ÏýÏêj�Œ¿ä¿õÙ‘«Þÿ‘~ÏýÏêkˇüŒeþÔ�´iÑEêQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEUÔÿäyÿ\ÿA5Îøþ<®ÿë þUÑjò ¼ÿ®ÿ šç| ÿWõÐ*é‡ð%ò<|GüŒ¨úKò:Ê(¢¹�`(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+—Ó?äkºÿzOç]Erúgü�w_ïIüë· ðTô7¥ðËÐê(¢Šâ0 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPQO÷GÖ¥¦¹Pá‘ô  ”U�ñt~To‹û£ò  õÍxÇJ¼Ôí­~ǚѹܠ€yÇ<ý+­ß÷GåFø¿º?*ºsp’’0Åa㉤éOfQ³‰ ±·…ñº8ÕN=@ÅMV7ÅýÑùQ¾/î�Ê¡»›E(¤‘^б¾/î�Ê�ñt~T ”tQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®UK¥c(À'åô  ÔS¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåFÆþéü¨´S¶7÷OåYºÖ¢t»/0.esµéŸZR’Š».�9Tš„waáïíyã¸ûW•å mò÷gœúŠÐ¯;“S¾–Bíw6sž€?[z¹;Ü¥�Ó™ðŽzƒè}kš åµ®zØœ¿)¹]G§õ¹ÔÑNØßÝ?•û§ò®£ÆE;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€E;ctþTloîŸÊ€9ÏÈ ë²ÿ#W¼;ÿ"ýŸûŸÔÕ/« rýòöö5{ÊÇÃöd)?'§¹¯.ò1—øR>Ñ¥E;ctþTloîŸÊ½BÆÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò ÑNØßÝ?•û§ò  zŸü‚o?ëƒÿè&¹ßÇ•ßýtʺ=Qi7¿)ÿPý¿Ù5Îx I²¼À'÷‹Óé]0þ¾G�ˆÿ‘•I~GYE;ctþTloîŸÊ¹�`mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mí�ýÓùQ±¿º*mrúgü�w_ïIüëªØßÝ?•rº`'Å—C;¤ãñ®Ü'ÁSÐÞ—Ã/C¨¢�±¿º*67÷Oå\Fh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPh§loîŸÊ��ýÓùPí¿×¯ãüªýQ·V©*G^ÞÕz€ (¢€ (¢€ (¢€ Šº>µ-E?ÝZ¯EsÞ$»ƒQšÚ xØFÅFA$ãèjøIuOùò�þý·ø×bÀVi=5ó6T&Õζ¹ßÍ,P[ädÉ;N3ŒbªÂKªÏ”÷í¿Æ¨êz…ö¨±¬Ö»Dd‘±¿Öº0Ø:�ª¥+XÒ•Fi³µ´f{(ŽY£RO©ÅM\|^!Ôá…"[4!(&6íøÓÿá%Õ?çÊ?ûößãXËU·k}ä<<îu´W$|Mª“gý†ÿ×Ðõi5He2ƨñ°/B gSVœyå±2£(«³£‚Šå2 (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ «s#¤€+1Vª�ßúÑþíGçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýó\׌Ymí¦$²F̧Û8ÿ èj ×·K9Zïo‘�˜7zŠ‘æ‹GF«¥Z3Jç›Õí'›Wµç+ rG`¥CrÖfv6Ñʱg€î3ü«¨ðÜšq�’Ù.qóù‡,G±ô® PR�®}62»§AÉEëøz�Ÿ/÷Í|¿ß5é"IçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGEIçËýóGŸ/÷ÍGE`øÒG} C1#Î_äjï†å‘|=f6SYþ2ÿ�ÿ×eþF¯xwþEû?÷?©¯.ò1—øR>ѯçËýóGŸ/÷ÍGEz…’yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@j“Ht‹Ð\àÀÿú ®sÀR2Y^mb3"ÿ*è5?ùÞ×ÿÐMs¾ÿ�+¿úè?•tÃøù>#þFT}%ù‡Ÿ/÷Í|¿ß5Ì{ž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß4yòÿ|ÔtPž|¿ß5ÊinÃÅ·L;Néë—Ó?äkºÿzOç]¸O‚§¡½/†^‡YçËýóGŸ/÷ÍGEqyòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@yòÿ|ÑçËýóQÑ@ •Úe‰r¨[¯_ÇùUú(¢Š(¢Š(¢Š*)þèúÔµÿt}hŽÒÿäx—ýù?‘®Ú¼þ+øtïOu0sÈàì=ÅoÂg¦ÿÏ;Ÿûà�zxº*8¸Æú#¦­9I¦—C¢¢¹ßøLôßùçsÿ|ñ£þ=7þyÜÿßük“ê•ÿ•™{ö:*+�ÿ„ÏMÿžw?÷Àÿ?á3Óç�Ïýð?Æ�ªWþVÆ}�­CþA·_õÅÿ‘®SÁÿênÿÞ_ëW.¼]§Mi4KÆç�”e2GÖ©ø<þêì´¿ÖºU)ÓÂÏ�[cU F”®ŽÌtP: +Î9‚Š+ɾ)xïÄñ—‡­t|ÏÜnÄF§íµâ HèEzÍâíÏÆ_ h²ø’óXÒ®-áijéñ§ÊRzg`$ ó†Ï¹ëW´ßüFø‘§¦£áa§èr(O:ìy�< |ûr¬6Æqý@ö+ËþøãÄ:§ˆõŸ ø®8N­¦¯˜&…B‡P@9�âRƒÒ§‹Å:Ó|zŸÃFó:BØ …¿”œ>Ðs»»žôé4W=ã­NóFð.µ©XMäÝÛZ¼‘I´6Ö þ"¹­7Ç×gÁ;oëÞÞy˜Tód2Qò€éœ€Ð£Q^3§IñŸÄºTõž§¢iö÷Q‰à²hÁ,„ey(ØÈÆ2ÝùÅuŸ þÜçv7u÷¯I¯où:5ÿ°_þÉ[;ø�«Ùø’ÛÁþ²Šó_�<Éd—î[¡ç�3Žyà ps@•Ex¾¥¨|aðU“kz¥Î“®ið�÷6ð V�;œ„Cǯ͎¤`W©xcÄ6~*ðåžµ`O‘r›¶·ÞF §ÜEkQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@s~.‘Ä6±Œìfb~£þfºJ£ªé˩٘‰ÚàîFô5�X¹A¤tàêÆ•xÎ{#Ϫæ“#Å«Z²u2ªþàþ•4š¨ŽTYÈø?yáùŠÙд mç[»°—îGœàúšá§NNKCé18º1¢ß2wGIEW¤|�QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÏxËþ@kÿ]—ù½áßùìÿÜþ¦¢ñ-…Ö¥¥ˆ-"2ËæÚ`úÕ­Úk="ÚÞá J‹†RsŽk΄%õùJÚrïó'í¨¢ŠôJ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€*êò ¼ÿ®ÿ šç| ÿWõÐ*èµ?ùÞ×ÿÐMs¾ÿ�+¿úè?•tÃøù>#þFT}%ùeQ\ǰQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEËéŸò5ݽ'󮢹}3þF»¯÷¤þuÛ„ø*zÒøeèuQEqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¨§û£ëRÔSýÑõ "ÎÖ¿Í ñ‰#/!*~†ºŸøG´Ÿùñ�õÿæl%ŽLòÈ‘ y2ÎÀ†ºÿí;ùþ¶ÿ¿«þ5ébåU8ò7k-Žš®I«v+Â=¤ÿÏŒ¯øÑÿö“ÿ>1þ¿ãV´ì?çúÛþþ¯øÑý§aÿ?Öß÷õƹ9ë÷‰—5O2·ü#ÚOüøÇúÿ�ð�i?óãëþ5gûNÃþ­¿ïêÿ�ÚvóýmÿWühç¯Ýþ!ÍSÌϼÐt¸ìn,ã ±±ž+Áÿê®ÿÞ_ë] ö£bÚ}Ê­í¹c«“Á÷®{ÁÿênÿÞ_ë]1sxYóߦæ‰ÉÒ•üŽÌtP: +Ï9¼sâHãOÃüŒþ÷ÿgìuÁx·Á–½ñ Âþ µžÑ-4§Ý:Jì¾`~Pƒø‘@Ÿ¿äšx�þ¼%ÿÐk;àâ…øM €\‡�úêõÐx»H¸×ü!«i6¯\^[<1´¤…Œ � ÇáU¼áû¿ x#LÑo¤†K›Tev�‰C—fà�B;Páoù9ŸÿØ9•½�?j;ŒžºXÇýðµÒè¾Ô´ïŒžÑ´ýBÐAhìeVWÞq�Ýž„öªž;øm¨ë~&³ñW†u…ÒõËdî‘IIÎ@8à�F#õØø©q·Âÿ<®ZÔ ÏvbÌŠæ¼/m _|Ò¬|Kw®™s–ÒË(�kyŒT†&ÓT|¸S·’¼ñÚ¸;ï…~!Ðuë½WáҒñ·Ïcr™ˆç�•†98xÏ­xwᆳ/‹-üQã�u5}FÓe†ÛDt=CÈG<ó@Íÿ'F¿ö ÿÙ+šM?Ä·Ÿ´ŠaÐõ¸4�HŸK< /™#¨`{m‡ÐRð·ÄöÒî×Qø‡¦­‰…ÅÁ—O‰TGƒ»'g溄º ~ðBYëÚj°5Ä’GshÛ£ à±¹{Ÿ‡/*ÒÚ1iœñêOrNI>¦€/QEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@íÕ?ÖªU»_õOõª”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE=§úï™?ú÷úÓí?×~Éÿ׿ր#¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®§ÿ ›Ïúàÿú ®wÀŸñåwÿ]ò®‹Sÿ�Mçýpý×;àOøò»ÿ®ƒùWL?�/‘ãâ?äeGÒ_‘ÖQEÌ{EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPVdŠ5¶W¡ˆ sUªÜ¿ñæ¿A@(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š–Ûýzþ?Ê¯Õ oõëøÿ*¿@Q@Q@Q@E?ÝZ–¢Ÿî�­sW¾‚îîK�´:⸚ƒþçîOûàWIEuG^*ÊFªµD­s›ÿ„Bùû“þø•­hÉ¥$,“4ža#‘Œb»šÃñ.Ÿs} ¿Ù£ÞQŽF@ëõ®Œ62«ª•Iiò4¥ZNk™èR·ð¤S[E)ºp]chã"¥ÿ„Bùû“þø¿mŠÖÛï"*œz�RÖ2ÇW»´¿"z—Üæÿá‡þ~äÿ¾jiZTZTN‘ÈÎ\ä–­ +:˜ªÕ#Ë)]*³’³eÑÐQ@è(®s0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªwëGûµr©Ýÿ­îÐz(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Úÿª­T«v¿êŸëU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š({Oõß…2õïõ§Ú®ü)“ÿ¯­GEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP�½Í�Äã|‘².}HÀ¬¯ è—š-¼ñÞ #†]�ž1[Ñÿ¬O¨©ï>òý*ÔÚ‹�FsÏ Ö�w¼oo™ZŠ(¨:Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­ËÿkôR­ËÿkôRŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  m¿×¯ãüªýP¶ÿ^¿�ò«ôQEQEQERP -݉ýÑùQ±?º?*u݉ýÑùQ±?º?*u݉ýÑùQ±?º?*u݉ýÑùQ±?º?*uQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU;¿õ£ýÚ¹TîÿÖ�÷h½Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@íÕ?ÖªU»_õOõª”QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE2YR^Y*"–b{I´•Ø­?×~Éÿ׿ָÏ_´ìl ÛÆ8RT3ïž*}/ÆW r±ê[]ãÍUÚWÜ�Æ+ÌŽq…u9.ýzήvtQEz……Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@�ýb}EOy÷—éPGþ±>¢§¼ûËô  ÔQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEn_øó_ ª•n_øó_   ”QEQEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Ýÿ­îÕʧwþ´»@袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·kþ©þµR­Úÿª­T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ²|L®Þ»ç8Rqé¸gô­jGE‘C+ zYÖ§í)ÊÓBjèò +°»ð<ÒÜ1Óç�açd¤‚¾Ùæ¦Ó<öK¡.¡*HPäGJ“îOò¯�ŽSŠu9~} y·OW]2ÕeϘ!@ÙõÀÍY¢Šû(Ç–)v7 (¢¨Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Gþ±>¢§¼ûËôªÞbDCÈêˆË1Àé/-n˜}žæ°9òÜ6?*v{’åìÞ£h¢ŠEQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[—þ<×è*¥[—þ<×è(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(+‹˜-!3\Í1¯#QøšŽÓP²Ô½•å½ÊަUÀü�y®™b¿¼O¨_êrHÚ5ŒžMµº9UsëǰÉïÈç®ê¾¸Ðõ[[Á°´rÇ&'¶3ü®ŸV=B3ÜŒP£U¬ébïì§R³9Ç“ç®üúc9®Sân·wa¤Ziš{2^jrùA”ႌdØ’Ê?M_…þÇû+$¦óf ç˜Û·úíÎÜg¶?Æ€;º+„øe¬Þ]é÷Ú>¢ì÷z\¾Qf9;yßHúb»º*�ßúÑþí\ªwëGû´^Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  v¿êŸëU*ݯú§úÕJ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢³õËDZѮn#8�( } gõ¨©5NrÙ+ƒÐYüG¦iw%.'Ì€`¤k¸�¯¥>×[ÓõY›ì³†~»moÈ×–X’I$òI§Ã4–ó$Ñ1YåHìkæcžÕö—q\¿�ÞcíÏ\¢¡´Ÿí6P\cljøôÈÍM_Q¤®�‚Š(¦EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPGAš) ¤„b€<»ZÕæÕ¯]ÙÏ�¤ˆ£ì¯Ö³ášKyVX]’E9 §Tú…Œºuô¶Ò©ûñV½Ø(ò¥�Ì+Ϋ­)T~õõõ=K@Ô›UÒc¸|y ”“Þÿ‘­:Æð½„š~ˆ‰2•’F22ž£8Çèl׋U%7˱ú6 Ô–¯Åep¢Š*�¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÿÇšýT«rÿÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEë2X\2ý剈úàÔô„�x"€÷š¿–yý+U¼!¨–>KC"÷‹cô­]A]9üùœI>06ô_¥qBŒùµGÐb3 “å•Û[TQEzËQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Ú®ü)“ÿ¯­>ÓýwáLŸý{ýh:(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€úÄúŠžóï/Ò �ýb}EOy÷—é@¨¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÎÕux´Änù˜eS8ãÔÖ?ü&¤x 1ŽÀ<Õ |¹ÖgÝÛ}0+6½ü6 —²NJíž…*åM£Ð,/áÔ-ıdc†SÕMZ®WÂ…þ×pÜØ úç�ë]Uyª*•WìqÕ‚„ÚAEW9˜QEQEQEQEQEQEQEQEQEQE-·úõü•_ªßë×ñþU~€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ §wþ´»W*�ßúÑþíW¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ݯú§úÕJ·kþ©þµR€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€'´ÿ]øS'ÿ^ÿZ}§úï™?ú÷úÐtQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE:?õ‰õ=çÞ_¥AúÄúŠžóï/Ò€+QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE‘¬è£Qı0IÔcžŒ=ëxcUÈ-ªã2 ~œ×eVåÿ�5ú 쥎«J<‹chWœU‘�¥é±é¶ÅÝ#rïëÿÖ«ÔQ\³œ§')n̤Ü�ØQE" (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPTîÿÖ�÷jåS»ÿZ?Ý  ôQEQEQEQEQEQEQEQEQEQEQEQE[µÿTÿZ©VíÕ?ÖªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPöŸë¿ dÿëßëO´ÿ]øS'ÿ^ÿZŽŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Gþ±>¢§¼ûËô¨#ÿXŸQSÞ}åúPj(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·/üy¯ÐUJ·/üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPTîÿÖ�÷jåS»ÿZ?Ý  ôQEQEQEQEQEQEQEQEQEQEQEQE[µÿTÿZ©VíÕ?ÖªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPöŸë¿ dÿëßëO´ÿ]øS'ÿ^ÿZŽŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Gþ±>¢§¼ûËô¨#ÿXŸQSÞ}åúPj(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·/üy¯ÐUJ·/üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPTîÿÖ�÷jåS»ÿZ?Ý  ôQEQEQEQEQEQEQEQEQEQEQEQE[µÿTÿZ©VíÕ?ÖªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPöŸë¿ dÿëßëO´ÿ]øS'ÿ^ÿZŽŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Gþ±>¢§¼ûËô¨#ÿXŸQSÞ}åúPj(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·/üy¯ÐUJ·/üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPTîÿÖ�÷jåS»ÿZ?Ý  ôQEQEQEQEQEQEQEQEQEQEQEQE[µÿTÿZ©VíÕ?ÖªPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPöŸë¿ dÿëßëO´ÿ]øS'ÿ^ÿZŽŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Gþ±>¢§¼ûËô¨#ÿXŸQSÞ}åúPj(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ·/üy¯ÐUJ·/üy¯ÐPJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€%¶ÿ^¿�ò«õBÛýzþ?ʯÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPU®"/ !”qÜÕš§wþ´»@ û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€&û;}?:>ÎßßOΡ¢€/@…#`H9=�Wû;}?:–×ýSýj¥Mövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEMövþú~t}�¿¾Ÿ�CEZ·ˆ¤™,§ŽÆ’XKJÇrŒúšm§úï™?ú÷úоÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  ¾ÎßßOÎ�³·÷Óó¨h  Ò§rp}j[ˆË²à¨Ç©ª±ÿ¬O¨©ï>òý(Ÿgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çGÙÛûéùÔ4Pßgoï§çV$BÖê¹sž*�[—þ<×è(/³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(o³·÷Óó£ìíýôüê(Ì0”•X²œz·T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP»_õOõª•n×ýSýj¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEOiþ»ð¦Oþ½þ´ûOõß…2õïõ 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Štëê*{ϼ¿J‚?õ‰õ=çÞ_¥V¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÿÇšýT«rÿÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP»_õOõª•n×ýSýj¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEOiþ»ð¦Oþ½þ´ûOõß…2õïõ 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Štëê*{ϼ¿J‚?õ‰õ=çÞ_¥V¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÿÇšýT«rÿÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP»_õOõª•n×ýSýj¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEOiþ»ð¦Oþ½þ´ûOõß…2õïõ 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Štëê*{ϼ¿J‚?õ‰õ=çÞ_¥V¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÿÇšýT«rÿÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP»_õOõª•n×ýSýj¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEOiþ»ð¦Oþ½þ´ûOõß…2õïõ 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Štëê*{ϼ¿J‚?õ‰õ=çÞ_¥V¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÿÇšýT«rÿÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQENïýhÿv®U;¿õ£ýÚ¯EPEPEPEPEPEPEPEPEPEPEPEP»_õOõª•n×ýSýj¥QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEOiþ»ð¦Oþ½þ´ûOõß…2õïõ 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Štëê*{ϼ¿J‚?õ‰õ=çÞ_¥V¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«rÿÇšýT«rÿÇšýT¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([oõëøÿ*¿T-¿×¯ãüªýQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW­|MÑt-^ãL¹·¿’h ÑF…I 2À÷ôª¶ßt ›¨­ÒÏR+„RÑÇŒ“Ž~z﨨®® ²µ’ææTŠ—s»œÅ‹^^Vo yÇŸäüŸ^»¿Jm.íïí"ºµ™&‚UÜ’!È"¦ ©Ýÿ­îÕʧwþ´»@袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·kþ©þµR­Úÿª­T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  í?×~Éÿ׿֟iþ»ð¦Oþ½þ´Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@�ýb}EOy÷—éPGþ±>¢§¼ûËô  ÔQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEn_øó_ ª•n_øó_   ”QEQEQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( )ðε¤Yø³Åz®­w(÷^T>g%€fèIà/Jî´�xw\�¦™ym4£Ÿ/nÇǨVÖv“ðçÃúeÌ×@×óJÛ·^…�/®ý+šø‘áË Î×Ä4)aw©òÅ9ÉŒ‚;uæ€.|T¸šèèš2…Ècت®}²Ùüvë¢é«£ÿd‹8¾Ã³ËòvðGøûõÍyߌîL¾$ð6©*„I^9=ç��ó¯S 8ø]4¶Wz÷‡¤�ºX\Ÿ+?ï2·áòƒøšôY$H£i$uD@Y™Ž©&¼ßÀ_¿øƒâë„æ13.GC™ú ¯C½¶[Û‹Vb«4MaÔ1ŸÖ€3á/ðÏý ZGþÇÿÅT±ßZj©ö�:ê ÈGÊd·�H ŽÙ\Œò+ÎÿáDéô¼ÿ¿k]—…¼;‚ô–Òí§{„iZmòH»@¾TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctP>TŸÜoÊ�*Oî7åS}±¿º(ûctPí•–6sÜUo*Oî7åW!”È…ˆÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€!ò¤þã~TyRq¿*›í�ýÑGÛû¢€ de—%Hî)“Fæf!ŒúTðÜ_iP8Í6K–I …_Ê“û�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Eloʓû�ùQåIýÆüªo¶7÷Elo#q"’�Ôv©®‘™—j“ÇaBÝ38G'$󈚩åIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆü¨ò¤þã~U7Ûû¢�¶7÷ECåIýÆüªÌŠÆÕ@œ1LûctTÏ)X˜8â€)ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ùRq¿*<©?¸ß•MöÆþè£í�ýÑ@ �L¤£Ï${UÚ­ËI R f¬ÐEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPM–4š'ŠA¹J°õ�Ey…„>)ø}qsim¥K­éHdˆÄÇÌOÈ8ÆF1Ç^Zx›âÝ­¾¡¥¾�¢Ã ’E”Ÿ2CÓ¸8Î8dõâ½>Šå¼máOøHü<–¶…bºµ`öÄð8ÛžÀ�Ô Ã.ñ’Ø‹á+£©…Ùöž|­ßÞé�ü{è´P-à_ Éá�ÒéÃßÝ?›pÀç²ç¾9üI®¦Š(ªwëGûµr©Ýÿ­îÐz(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Úÿª­T«v¿êŸëU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š({Oõß…2õïõ§Ú®ü)“ÿ¯­GEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP£ÿXŸQSÞ}åúTÿ¬O¨©ï>òý(µQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[—þ<×è*¥[—þ<×è(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªwëGûµr©Ýÿ­îÐz(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Úÿª­T«v¿êŸëU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š({Oõß…2õïõ§Ú®ü)“ÿ¯­GEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP£ÿXŸQSÞ}åúTÿ¬O¨©ï>òý(µQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[—þ<×è*¥[—þ<×è(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªwëGûµr©Ýÿ­îÐz(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Úÿª­T«v¿êŸëU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š({Oõß…2õïõ§Ú®ü)“ÿ¯­GEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP£ÿXŸQSÞ}åúTÿ¬O¨©ï>òý(µQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[—þ<×è*¥[—þ<×è(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªwëGûµr©Ýÿ­îÐz(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Úÿª­T«v¿êŸëU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š({Oõß…2õïõ§Ú®ü)“ÿ¯­GEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP£ÿXŸQSÞ}åúTÿ¬O¨©ï>òý(µQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@º®¯˜�vù“0ʦq�êk#þûã…x`1ŽÀ<Õ |¹ÖgÝÛú`Vm{øldœ•Û= TaÊ›G i÷ñj6ÂX²á”õSV«•ð¡µÜ÷6~¹ãú×U^F*’¥UÂ;u`¡6�QEÎfQEQEQEQEQEQEQEQEQEQEKmþ½åWê…·úõü•_ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Ýÿ­îÕʧwþ´»@袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š·kþ©þµR­Úÿª­T Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  í?×~Éÿ׿֟iþ»ð¦Oþ½þ´Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@�ýb}EOy÷—éPGþ±>¢§¼ûËô  ÔQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEdë(Ôq,LuÉèÃÞ±…õL‚Ñ"¡þ3 ÇéÍv5n_øó_ ®ÊX괣ȶ6…yÅYÚ^››lcS¹Û—SþzŠ+–s”äå-Ù“nNì(¢Š‘Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªwëGûµr©Ýÿ­îÐz(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€-Úÿª­T«v¿êŸëU(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š({Oõß…2õïõ§Ú®ü)“ÿ¯­GEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP£ÿXŸQSÞ}åúTÿ¬O¨©ï>òý(µQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@[—þ<×è*¥[—þ<×è(¥Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Û¯_ÇùUú¡mþ½åW袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªwëGûµr«\¼Á¼¶qÚ€*QSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@ÑSbßûÒQ‹ïI@Úÿª­T«ÐlòÛalgœÕ|[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ†Š›ÿÞ’Œ[ÿzJ[Oõß…2õïõ©àyŸ!lã½6QšÛ‹ç¾(µ6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô” 6-ÿ½%·þô”ëê*{ϼ¿Jj7® çÍ÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEy_įk^ñ›e¤Ü¤0\DE1+äï#©µzÙ¢þçêkÍ~%x'Zñ7ˆ´ÛÝ6žx‚È^P¤äô>ÕéôÙ¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ä|LÖ¯¼/ád¿ÒeXnMÊDX ”†$`äv©à»Ùµ¿麕û .®#-#�·'qª�Ä¿ê'ð²Xiˆ�8¹Iw 6€Àò~¢´ü¥ÝhžÓtÛÕU¹‚2®·w×ñ  Ÿ³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/³EýÏÔÑöh¿¹úš–Š‹ìÑsõ4}š/î~¦¥¢€"û4_ÜýMf‹ûŸ©©h ¾Í÷?SGÙ¢þçêjZ(/]caáýJòßåžÞÖYccÎP�p}Åqß üKªx³OÔfÖgYÞ Qc+¦ŸºvÚí¤·þÔ¬àÍ=¬±F À,È@çêkŽøYá=Wš~£«hóÊŒ›$ �¥wf‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©¯0ðߌ5­O➣áû»”}6 n8„JÄ/ÌzWªW˜xoÁ:Ö™ñOQ×îa‰l'–áÑ„ ±įé_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´P_f‹ûŸ©£ìÑsõ5-Ù¢þçêhû4_ÜýMKEEöh¿¹úš>Í÷?SRÑ@}š/î~¦�³EýÏÔÔ´Pk hÁ•pG½IEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE#2¢–f  d’p ¨.ïml 3Þ\Ãm y“Hsé“P[ë:]äþE¶¥g<ßóÎ)Õ›ò¹_‹ò#Éÿ_ÿ3@²:ÈŠèÁ‘†U”äê)Õ—g}i§øzÂ{Û¨m¢ò#dÒ\ídÖš²º†V ¬29PÑUâÔ,§»–Ò+»y.b’�Oªç"–êúÒÆ1%åÔèz4Ò™  èªö—Öwñ™,îà¸AÕ¡�8ˆ®#Æþ+m7^Эl5h"Su²ýD;Wr}üýÞ zw þІÖòÖú=�Ì7’@’§yUYµÝ"Þsú­ŒSƒÜ"·äMhUhu +‹©ma»·’âõ±$€º}@9�NŽ’"¼l®Œ2NAç¾ÿ’¥â¯ þb€=ŠŠâêÞÎ5ÌñAêò¸P?PÙêš~¡»ìWÖ×;zù3+ãò4nŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  öz…–£IewÊ+mf‚@àBAëV+Ï>ÿÈ»¨ÿ×óè ]ĺ¦ŸêYÍkÔ˜ÙÌ¡Û=0¤äк)“M¼M,ò¤Q¯Wv âj¥®µ¥^ËåZjvwr)ÕÏä ZžâX{‰£†y$`ª£Üž•ö…—Ø~Ýö˱íÝö�5|¼zîÎ1XÞ;ÿ‘Wÿ®ùŠÍÐ-,¯þYÚêSùrZâYw„Ú7uÉàPaÄ7P$öóG4.2’FÁ•‡¨#­IYú­•މim§N'³Ž=±J>áë‘Á§Üke¥À·¹Ôm!˜ôŽIÕXþæ€.ÑUÍý˜½[#wÚ™w¬`ÞWÔ.sŽ:ÐoìÅé²7p}¨&ó˜7íõÛœãÞ€,QYðkÚ=ÌþDµŒ³go–—ÍŸLQx—XþÁðåö¦3AQOBÄ…\ûdŠÕ¢¼³Bð$¾-Ó#Ö¼I«_I5Øó"Ž'"ž�AøRiê^ñÕ·‡n/¥½Ò¯×0NLdä zr0@àç4éôQEQEQEQEQEQEQEQEQEQEQEQEQEQEW]BÉïžÅnàkÄ]Ín$ErW9‘ùÕŠóÍ;þKŽ­ÿ^+ÿ Å]Õî£e§F²_^[ÚÆÇj´òª}2MY¢š’$±¬‘º¼l+)È#Ô¡ý¿£ ¼Ÿí{78Ùö”Ýùf€4jµ®¡eæ}ŽîÞãÊm²y2Ø}¬ƒ‘‘Ò¼ïá_Þñý�wvš…•ø�ÙÞ[Üymµü™Cí>‡ƒVkžð®•¢ék~4kát%Ÿ|ø�dØþŸ/O¡­‹ÍBËO@÷·–öÊÜšU@3@hªo«i±[Åq&¡h�JÛ#•¦P®Þ€çÔ—WÖv^_Úî ·ó[d~l�7· ÏSí@(ªæ‘irm®uK(gb’á¿"sWDˆbóC©Œ�Á�È#Ö€Ey6‹¥ÜüMº¾Õu]Fê2)ŒVö°6àù äã'=±I©XÝü3×t¹ôíFæ}*î_.[iÛ8äg¦prâ€=jŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Нu}geåý®ê 5¶GæÈ{z õ>Õ^m{G·º6³j¶1\ƒÜ"°?Bs@T7–¶py÷W0Áüô–@«ùš-/­/â2ÙÝAq8ß �Çæ(z*¼º…”qZMwoÌßêáywú)95;2¢–b@É$à@ EAi}i¨AçÙ]Asvù�Èsé‘Q]júmŒ‚;½FÒÞCÑf™PþDÐÊ)‘Kñ,°È’FÃ*èÀƒô"™suog šêâ("^W ?3@Uiµ +{¨­g»·ŠâoõQ<�]ÿÝäþYê6:‚–²¼·¹Uêa•\È× âÿù)þúŸý €=ŠB@’IªPëzUÅÇÙáÔ줟8òÒáKgèhõQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@y·‹žãÅ:³ð’\<6 šïaÁ~7còÆ=Î{W¤×™x†oøE~)Úk×jÃN½‡É’P2íÚsôŸ¦}(CXø]¢¾“'ö=»Úê1®è%¹ÜÃ�IúŒb¨xÙ58þÁ³´ß¤±¬¬­»v€sêF3ï]&·ã½LÑf¼¶Ô¬î§Ø|ˆb”9wí�@ÏZæ™ ¡­KáÜÃ#êüªÏ„¿ä©x«è?˜¬ÿ‡•Œ¾2ñ DzÙ.œ5´/„%w6_¡ZÐð—ü•/}ó›¦éÃâ7‹õK½VIKÓßÉ‚Ý\¨<�:{.O|‘ØTÞ2ðM—‡t¿íÿy¶7VL®Á%f ¤�üDú�b3QøSR·ð_‹µ½X�[Eq/�o<‡FN9éÈ#ŸPEhüBñn™7‡eÒ4Û¸¯¯oJÆ©lâM£ œ‘žO@:ó@–�©ÿlè:‰P­q »Ð69žkF²|1¦É¤xcN°—ýl0¨�z1ä�ÌšÖ Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ð¿�`ð¯„5¢Q.¥=ã˜b=mQ½½½»×uà/@¶‹âK»¡¨j—ëæ5ÁäFð¯¡ì~˜éX_ ô=:ÿEÕ纵Ie–g¶fnO—´§_åéRøBîø®ãÂ:Œ„ÚNÞe„­Ð“Ð~8ÇûÃÞ€6|Oá9üCâk�Rþ(ô tæÜJQ™ùäñ�Øg9À®SÆš7�ôíYt‹›xu8Š˜VÞèÈÌw ‚7q“ž:U�LXêßîì|UrcÓàˆHd”Ç.9ã®Xû‘ŽØ©ŒÄŒþ'ð¥ð÷ÃmçB·ºÖ!–òþî14²´Î –çzõ9ç5ZëHŸYø+e ªžRuAÕ¶“�=ðMnx_ÆÚ׆ìÚçRµ¶¸†Žh¦”#Q‚@=AëÇ­r>ÒåÑ~/.˜÷O µ»­»HrDEK*þˆ©P˜®1øÒ蚺kŸMü âÙ u…™HÞŠ˜ÝÏbA­Yä¹Cÿ^'ÿA4ž+øyáëO ^ÜØÚ5½Í¬&T”JÌNÞH9'9­ï2ëÞÓN©wbHöºÎ¡Ãíb õ?(5wÆò&ë?õç/þ‚k•ѵÃá߃VºŠ(i’7X�è]¥`3ôÎ êuŸh¾°Œ]Ë ©ˆm¡Q¸�À £ ü…r: –§ãCâ­FѬôûUÅ”/÷Ÿ®Ó$œýÍTð�¿†8õÏëvšÍÇïX\Ü)ç ÚOÞ§AŒWoâ] îá-íµ‹f�á#IÔ³@3@´QEQEQEQEQEQEQEQEQEQEQEQEQEQEyMî»gáß‹zÞ¡|ÄF¶*ª«÷�ŠÅ…õ7„íÇ�õ‰üC­L’Çg&Ë}8¬]Áaßú�sÓøôëMGã…ø»…eX-’hÕ¹ÂFÇ|dÔzìR|?ñ´Zýª7ö>¢Û.ãQÂ1äñÿ�ø ·Æš&©â "=?N¼ŠÖ7“7,ìAdþèÀ?äW;yá?‡6 ÕÍ´r*àÊoI—>»Cc>ØÇµEñ2øÏqáûynÞ- òM×BxuÊõ#¶ÒHüùÅh4?´ !p±éSmE ·9í€I$Ð_ï&¸ðÅÌJÒGotR"Ç¢•Läþ5¿½âúþÿƒáÜÙú�»H‘Ü5Ùq`Gn½�Oð¯ïx‡þ¿¿Æ€#øe2[Zx’y8H®ÙÛè&©xKÃðxîKßøˆ=È’cþc*¢Ž{`àgèsœÕ¿†öâóOñ=±8]àŒPŽ|/†u-,i²JšmÝÀclÎYRU dgÔ7ó®‹âóËŸ£¼‰–ó1‘Ù±ÇëXÿ¼Eg¬êºE¦›*ÜÃmp ³ÇÊob0 ô'ž=ksâÇüzèõü?•hZ|1ðúéþ]ü]ÞÈ35ÓLû™ÏR9Ç_o®k?á[Ín5Ýæi`°»ÙîÙ,þƒŸÄ×¢W›x%“TñªA'—3]��ýÖÝ.ç@Ö«öø4™ÛF‚Ýï†<¨æá ÈÎpGl÷¯,Ô®u3âÍ2oÂÖöQ¾m…²©‡~GÞ9' õ?…t ñ´:o‰õ·Õmæe&çla—Ó< ƒŸÒ³¾$ë–>!¶°Ð4i£¿½–é_÷z®Ü8ÏÍøs@§œŒŠ*+XM½¤0–Üc�P·®3RÐEPEPEPEPEPEPEPEPEPEPEPEPEPœ|]ó³ô%ŠËöÏ‘�ƹqðÇÃñè3ÄÐÉ%艘Þ4�¼ÉŒîÆq×¶?Æ«|Xÿ�]þ¿‡ò®úóþŒ/5Ù&¼‚Õ͵¥³ÈÁ#'ƒÏÞÇáôÅ�;L‡Âßmôí0¼vW¶¬íb@ùXãž¼¦ÔøCÿ"dŸõøÿú Ô:Ÿü—-þ¼[ÿA–€ÿÉWð¿û‡ùµw—ÿòºÿ®/ü�ycÒ¾ øgSºÊZ *Òc�Ï?–àk¡ñ'Œ´[ æHµk™å‰’ ”;;�ÀÏôÎü?’î…š„– Zív„“¿hÆsšÅð^Ÿà�WL/¯\¤š¼ŽÞp»¹hÏS�§ Œzœæ¶þ_M¦|1¼¾‚ßí2[Ë,‚-ØÝ€¤ŒàöÍOeà_iËyªÁ¦ZÞ¶|èä”E 9þ÷ÊXwÍjxGÂsxkS¾{]AfÑ®Fè`ÜX£d`ç§LŒ÷â¹�#NOˆþ(Õ5]ä“L²“ɶ¶W*_Oa“ޤú oƒL_îtÿ]Íq¡ù%¥‹"¶:ƒßæÀëÖ¤ðf¥màßë:±*Ú+ÍæÛÍ)ÚŒ9Ç=FàE_ÕþÉ¥_Yj¾ O³]Å'ïaiŽÇO«ô#ßÚ“ÅÜüNð¦F§ü ¯xŸÇÑY=¥—‡d´Ôµ+™BÔùˆª}Jž¹ÇZ¡âÝßð³<'¼‚ÝñÓ9 ¾ jÚ>'Óü-&¢š~Ÿ"ùד´��¤ž:/ì=)·žøs6žÐZêÖ÷!~K�¨«0nÄ‚Ø?�ü*YZiÞ>Óu�^Óí=Ä~LùRB°s�L©÷Á­K¸~ZiíxSJ‘îTŠ@ÎÞÁAÎhÇà vëWÐg¶½›ÏžÆ_(K»vô#åÉïÐŒúb»Šå<ök� ïí´8ô”¹–4rÞbŽŒr©®®€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¯{ck¨Ú½µí¼w?ÞŽE X¢€9ËOx^Êè\C£Ãæ)ÈÞÌà£?JÕÕ´{ rÄÙj0yöåƒÞËÈéÊ�jõµ€Y‹Cµ¸O/Ëq¸Æ0s×�Zæäøqá9'%Tƒ’«+…?†q]U›g iz~¥6¡ih°ÜÍÄì¬Ø* çGAÚ Õ¼)¡k“yÚŽ› Òãg*Ä{• šÙ¢€24Ÿ èš™4í6$#f 6?Þ95>¯¡éºíªÛjv‰q¶å H*}ˆ ŠÐ¢€3­t.ËH:T6Qý€ç0>]NNNwg<Öm·€¼/it.aÑàóAÈÞÌà÷X‘úWGEcÉám]m5—°Oí!„Á˜r8àŸÂ§´Ð´ÛVëS¶¶ÙywþºMìwþà~´h  í[AÒõÈ–=NÆ+�¿t°Ã/ÐŽETÒ¼áýàO§é�Å0é#v_¡bqøVåQEQEQEQEQEQEQEQEQEQEQEQEQEQE�£èZn�o%¾™mäE$†G]ìÙlŸ˜ŸAQêþÒuç·“R´ó¤·$ÄâFFSÇu ö«EejþÑõÕA©ØEpPa]²MÀƒ�Æ£±ð¦ƒ¦ÚÏmi¥À‘N…%.§±c“�ƶh  K_hVZeÞ›o`#´»ÿ_‘þÇ9�«_Ø:oöö/Ù¿â]³Ëòw·ÝÎq»9ýkFŠÈ»†]Ã2E¡Y¬�kî-Ù™�äŒç$ã8ç­pVº§Ã½b$Ôµ›Kk]O­Ä%$Q¿¹Ú¼6ë^©Tn4]*îo:çL²š^»å�Y¿2(„ðtÛþ;Ô»"@£ò5�¦èZn‘qy=�·•%äždí½›{dœòN:ž•£EcjÞеÉ|ÝGM†iq�3”b=ÙH&Ÿ¤xcEИ¾›§C‘ƒ',øôÜrqZÔPEPEPEPEPEPEPEPEPEPEPEPEPEPEPv­¡iºâÀº�·ž 2?�—kzü¤f¯º,ˆÈÃ*À‚=©ÔP EÓô#g¦[ù.S{7Ìq“–$öÙt-6mrjKlê§—ÛÛ…ÁÛœíÞ´h  šŽ—c«Ú]BÖ+ˆIÎÙp}G¡÷‹aà é·ë{m¦*̇(^Gp§Ô$gùWKEPÒ4m?B²û›oä[î/³{7'©Ë{V]߀¼/{pÓÍ£Ãæ1ÜLlÈ ú)º:(–›¤éú=¿‘§YÃmäˆ×�©=OãQjÚ“®Æ©©ØÅrî³ 2ýr?:Ò¢€1´� èZ¦m;MŠHǘIvر$U‹Í M¿Õ-5+›o2îÓýD›ØlüÁüEhÑ@ÝÚ[_[=µÜÏŒ4r(`Xx¶÷xôhKƒœ;3¯ýòI¥t´P*…PªP0KEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÃß|`ð&›¨\Ø]ë¾]Í´­ ÉöIÎ×RC „Áä•_þoÃÏúòJãÿ�ÕëÏ…>Ô/®/n´e¹¸‘¥–C,€³±É<7rMx§Ç�èmhzrYý¤\yÛ]›~ß/oÞ'¦ãùЮÿÂíøyÿCþI\ñºéü7â½ÅÖ2ÞèW¿k·ŠO)ßÊxðØpB+šµøCà'´…ÛðhÔ“çK×ïVǃm¼§ÚÜÙxBãNxD‚Yã³»mb0 |ÄŒ…ý(¦¢ŠÏ±×´}NîkM?V°»¹‡>l6÷)#ǃƒ¹A$sÇ4¡EgZøƒE¾[¶´Õì.Ïþ>LW(â¿åû§¯¡ô®sþ×€Å÷Øÿá%´ós�Û_Ëÿ¾ñ·õ ÒŠd3Es M©,R(dt`ÊÀô Ž¢£¼½µÓ­$»½¹ŠÚÚ!—–gª=Éâ€'¢¸•ø½àºû8ñ%¾üã&9ßEvþµØÛ][ÞÛGsk x ôÃd4P‡në;ù ÿ{q= {WŸ|3ºÔ<ñfÿáýÝÓO§ÎXÛî<Ùæ+�Ûrp@ï�JÝÿ…Cã_ú*ÚÏýõ7ÿ¦h®ô¿Økº�Ž?µ5 WÜÑÜFL² ¤csHOCéÒ€=šŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¼;ö†Ðu�mü9ý“¤ß_ùBçÌû-»Ë³>V3´gò5î4P6ŠVÊ`A¨ öâ°üw ¯‰¼«é8I­Ù¢ÏiæOüx è«Æ>'|cÓìlu¿ i¶×¿Û5¡‘‘Di‘†`CN Çh…ø¡Ë®xßûVè´–Ú5¿î÷…wÈEú\ý@¯¨kϾ øJ_ ø¼„Å|ææta†L€OÑ@ã±&½€>Dð¤'¶ñ–µâ Aö«�*åškP 3DîÀ�£ï:zÒ½ÿö‚Õ.­ZÃJð�ÄZË�€HæO-½B�±Å/ÀOùãÛè ?´EËÛýš/\X�¢#1*×w§ëZ? ¼®¿‰o¼wâØÞ-Fì7‘‹µ×wW+ü<|¡}3í^ÍEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEžt ê_ÚGI°7ùÏÚ�²y¹ÿýkBŠ(¢Š£c¢iZ\ÓM§é–V’Ï̯on±´�þbÏSÖ¯QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿÙkalign-3.5.1/doc/paper/000077500000000000000000000000001515023132300146345ustar00rootroot00000000000000kalign-3.5.1/doc/paper/kalign3.bib000066400000000000000000000133361515023132300166500ustar00rootroot00000000000000@article{lassmann2005kalign, title={Kalign--an accurate and fast multiple sequence alignment algorithm}, author={Lassmann, Timo and Sonnhammer, Erik LL}, journal={BMC bioinformatics}, volume={6}, number={1}, pages={298}, year={2005}, publisher={BioMed Central} } @article{lassmann2008kalign2, title={Kalign2: high-performance multiple alignment of protein and nucleotide sequences allowing external features}, author={Lassmann, Timo and Frings, Oliver and Sonnhammer, Erik LL}, journal={Nucleic acids research}, volume={37}, number={3}, pages={858--865}, year={2008}, publisher={Oxford University Press} } @article{sievers2011fast, title={Fast, scalable generation of high-quality protein multiple sequence alignments using Clustal Omega}, author={Sievers, Fabian and Wilm, Andreas and Dineen, David and Gibson, Toby J and Karplus, Kevin and Li, Weizhong and Lopez, Rodrigo and McWilliam, Hamish and Remmert, Michael and S{\"o}ding, Johannes and others}, journal={Molecular systems biology}, volume={7}, number={1}, year={2011}, publisher={John Wiley \& Sons, Ltd} } @article{edgar2004muscle, title={MUSCLE: multiple sequence alignment with high accuracy and high throughput}, author={Edgar, Robert C}, journal={Nucleic acids research}, volume={32}, number={5}, pages={1792--1797}, year={2004}, publisher={Oxford University Press} } @article{deorowicz2016famsa, title={FAMSA: Fast and accurate multiple sequence alignment of huge protein families}, author={Deorowicz, Sebastian and Debudaj-Grabysz, Agnieszka and Gudy{\'s}, Adam}, journal={Scientific reports}, volume={6}, pages={33964}, year={2016}, publisher={Nature Publishing Group} } @article{katoh2006parttree, title={PartTree: an algorithm to build an approximate tree from a large number of unaligned sequences}, author={Katoh, Kazutaka and Toh, Hiroyuki}, journal={Bioinformatics}, volume={23}, number={3}, pages={372--374}, year={2006}, publisher={Oxford University Press} } @article{blackshields2010sequence, title={Sequence embedding for fast construction of guide trees for multiple sequence alignment}, author={Blackshields, Gordon and Sievers, Fabian and Shi, Weifeng and Wilm, Andreas and Higgins, Desmond G}, journal={Algorithms for Molecular Biology}, volume={5}, number={1}, pages={21}, year={2010}, publisher={BioMed Central} } @inproceedings{muth1996approximate, title={Approximate multiple string search}, author={Muth, Robert and Manber, Udi}, booktitle={Annual Symposium on Combinatorial Pattern Matching}, pages={75--86}, year={1996}, organization={Springer} } @article{myers1999fast, title={A fast bit-vector algorithm for approximate string matching based on dynamic programming}, author={Myers, Gene}, journal={Journal of the ACM (JACM)}, volume={46}, number={3}, pages={395--415}, year={1999}, publisher={ACM} } @article{steinegger2018clustering, title={Clustering huge protein sequence sets in linear time}, author={Steinegger, Martin and S{\"o}ding, Johannes}, journal={Nature communications}, volume={9}, number={1}, pages={2542}, year={2018}, publisher={Nature Publishing Group} } @article{sievers2011fast, title={Fast, scalable generation of high-quality protein multiple sequence alignments using Clustal Omega}, author={Sievers, Fabian and Wilm, Andreas and Dineen, David and Gibson, Toby J and Karplus, Kevin and Li, Weizhong and Lopez, Rodrigo and McWilliam, Hamish and Remmert, Michael and S{\"o}ding, Johannes and others}, journal={Molecular systems biology}, volume={7}, number={1}, pages={539}, year={2011}, publisher={EMBO Press} } @article{lassmann2005kalign, title={Kalign--an accurate and fast multiple sequence alignment algorithm}, author={Lassmann, Timo and Sonnhammer, Erik LL}, journal={BMC bioinformatics}, volume={6}, number={1}, pages={298}, year={2005}, publisher={BioMed Central} } @incollection{deorowicz2014kalign, title={Kalign-LCS—A more accurate and faster variant of kalign2 algorithm for the multiple sequence alignment problem}, author={Deorowicz, Sebastian and Debudaj-Grabysz, Agnieszka and Gudy{\'s}, Adam}, booktitle={Man-Machine Interactions 3}, pages={495--502}, year={2014}, publisher={Springer} } @article{shu2011kalignp, title={KalignP: Improved multiple sequence alignments using position specific gap penalties in Kalign2}, author={Shu, Nanjiang and Elofsson, Arne}, journal={Bioinformatics}, volume={27}, number={12}, pages={1702--1703}, year={2011}, publisher={Oxford University Press} } @inproceedings{yang2009improving, title={Improving Kalign via Reconstruction of Phylogenetic Tree and Iteration}, author={Yang, Fan and Zhu, QingXin and Zhao, MingYuan}, booktitle={2009 WRI World Congress on Computer Science and Information Engineering}, volume={1}, pages={625--629}, year={2009}, organization={IEEE} } @article{gardner2005benchmark, title={A benchmark of multiple sequence alignment programs upon structural RNAs}, author={Gardner, Paul P and Wilm, Andreas and Washietl, Stefan}, journal={Nucleic acids research}, volume={33}, number={8}, pages={2433--2439}, year={2005}, publisher={Oxford University Press} } @article{thompson1999balibase, title={BAliBASE: a benchmark alignment database for the evaluation of multiple alignment programs.}, author={Thompson, Julie D. and Plewniak, Fr{\'e}d{\'e}ric and Poch, Olivier}, journal={Bioinformatics (Oxford, England)}, volume={15}, number={1}, pages={87--88}, year={1999} } @article{sievers2019quantest2, title={QuanTest2: Benchmarking Multiple Sequence Alignments using Secondary Structure Prediction}, author={Sievers, Fabian and Higgins, Desmond G}, journal={Bioinformatics}, year={2019} } kalign-3.5.1/doc/paper/kalign3.org000066400000000000000000000213541515023132300167020ustar00rootroot00000000000000#+Options: toc:nil ^:nil title:nil author:nil #+BIND: org-latex-title-command "" #+LATEX_CMD: pdflatex #+Latex_Class: bioinfo #+LaTeX_CLASS_OPTIONS: [nocrop] # Nice code-blocks #+BEGIN_SRC elisp :noweb no-export :exports none :results none (setq org-ref-default-citation-link "citep") (setq org-latex-hyperref-template "") (setq org-latex-minted-options '(("bgcolor" "mintedbg") ("frame" "single") ("framesep" "6pt") ("mathescape" "true") ("fontsize" "\\footnotesize"))) #+END_SRC #+BEGIN_SRC latex \abstract{\textbf{Motivation:} Kalign is an efficient multiple sequence alignment (MSA) program capable of aligning thousands of protein or nucleotide sequences. However, current alignment problems involving large number of sequences are exceeding Kalign's original design specifications. Here we present a completely re-written and updated version to meet current and future alignment challenges.\\ \textbf{Results:} Kalign now uses a SIMD accelerated version of the bit-parallel Gene Myers algorithm to estimate pariwise distances, adopts a sequence embedding strategy and the bi-sectiong K-means algorithm to rapidly construct guide trees for thousands of sequences. The new version maintains high alignment accuracy on both protein and nucleotide alignments and scales better than other MSA tools.\\ \textbf{Availability:} The source code of Kalign and code to reproduce the results are found here: https://github.com/timolassmann/kalign\\ \textbf{Contact:} \href{timolassmann@icloud.com}{timolassmann@icloud.com} %\textbf{Supplementary information:} Supplementary data are available at \textit{Bioinformatics}online. } #+END_SRC #+TOC: headlines 2 #+Latex: \subtitle{Sequence Analysis} #+Latex: \title[short Title]{Kalign 3: multiple sequence alignment of large data sets.} #+Latex: \author[Sample \textit{et~al}.]{Timo Lassmann$^{\text{\sfb 1,}*}$} #+Latex: \address{$^{\text{\sf 1}}$Telethon Kids Institute, University of Western Australia, Nedlands, WA, Australia.} #+Latex: \corresp{$^\ast$To whom correspondence should be addressed.} #+Latex: \history{Received on XXXXX; revised on XXXXX; accepted on XXXXX} #+Latex: \editor{Associate Editor: XXXXXXX} #+Latex: \firstpage{1} #+Latex: \maketitle * Introduction Multiple sequence alignment (MSA) remains an important task in biological sequence analysis. MSA programs can be divided into consistency and progressive methods. The latter estimate pairwise sequence distances, construct a guide tree and align sequences following the order of the guide tree. Consistency based methods tend to be more accurate than compared to progressive methods but are orders of magnitude slower and therefore not practical when aligning thousands of sequences. Kalign citep:lassmann2005kalign,lassmann2008kalign2 is progressive alignment method striking a good balance between accuracy and speed compared to other alignment programs on a range of popular benchmark data sets (see for example cite:sievers2011fast). Despite having aged well Kalign was not designed to handle the tens of thousands of sequences frequently encountered today. In particular, the original Kalign program uses the unweighted pair group method with arithmetic mean (UPGMA) algorithm to construct a guide tree resulting in quadratic time complexity. More recent alignment programs have overcome this hurdle by implementing heuristics to construct guide trees citep:katoh2006parttree,blackshields2010sequence. Here we present a new version of Kalign, introducing a SIMD (single instruction, multiple data) accelerated version of Gene Myers bit-parallel algorithm to estimate pairwise sequence distances and adopting the sequence embedding strategy introduced by cite:blackshields2010sequence to speed up the construction of guide trees. * Methods We replaced the fast string matching algorithm used in Kalign2 citep:muth1996approximate with a new implementation of Gene Myers approximate string matching algorithm citep:myers1999fast. The algorithm calculates the exact edit distance between two strings using bit-parallel instructions. In the standard implementation the maximum length of a query is equivalent to the size of a computer word (64 characters on 64 bit architectures). However the algorithm lends itself to further parallelisation using SIMD (single instruction, multiple data) instructions including the AVX and AVX2 instructions available on all modern computers. Using these instructions it becomes possible to compare sequences of length 256. While the implementation of the Gene Myers algorithm is fairly straight forward using AVX instructions some operations are absent from the AVX instruction set and had to be implemented separately. A stand alone implementation of the algorithm is distributed together with Kalign to facilitate downstream adoption and development. To estimate pairwise sequences distances Kalign scans the first 256 characters of the shorter sequence across the longer sequence. The distance is defined as the number of edits required to turn one sequence into an exact match in the longer sequence. For distantly related protein sequences the sequence similarity is too low for the algorithm to detect meaningful distances. Therefore, following the method by cite:steinegger2018clustering, Kalign converts all protein sequences into a reduced alphabet by merging (L, M), (I, V), (K, R), (E, Q), (A, S, T), (N, D), and (F, Y) for the purpose of the distance calculation. #+BEGIN_SRC latex \begin{figure}[!tpb]%figure1 \centerline{\includegraphics[scale = 0.45]{Paper_figure.jpeg}} \caption{Benchmark results. a) Sum of pairs scores (SP) of all tested alignment programs on Balibase protein alignment data sets. b) SP scores of RNA bralibase alignments. c) Computational performance assessed on the BaliFam data set.}\label{fig:01} \end{figure} #+END_SRC Kalign 3 adopts the guide tree construction methods used in clustal omega citep:sievers2011fast. A number of seed sequences are selected and all sequences are compared against those forming for each sequence a vector of distances to all seeds. The bi-secting kmeans algorithm is used to cluster sequences based on the euclidean distance between these vectors until clusters containing fewer than 100 sequences are found. Here Kalign again uses AVX/ AVX2 instructions to accelerate the distance calculation. Finally, the UPGMA method is used to cluster the remaining sequences. Since the bi-section kmeans algorithm is not guaranteed to discover the optional split of sequence into two clusters Kalign runs the algorithm ten times using randomly selected sequences to seed the calculation. * Results We compared the performance of Kalign against two other popular progressive alignment methods muscle citep:edgar2004muscle and clustal omega citep:sievers2011fast. We used the Balibase citep:thompson1999balibase, Quantest2 citep:sievers2019quantest2, Bralibase citep:gardner2005benchmark and BaliFam benchmark data sets (Fig. \ref{fig:01}). Clustal omega and Muscle were run with parameters recommended for large alignments on the BaliFam data set (Clustal:--threads=8 --MAC-RAM=48000 --iterations=2; Muscle: -maxiters 2), but otherwise default parameters were used. Kalign's performance on all 6 Balibase categories is statistically indistinguishable from the other two programs (twosample t-test, corrected p < 0.05). Likewise there is no statistical difference in alignment accuracy on the Quantest2 benchmark data set (results not shown). Kalign's mean performance is significantly better compared to the other two programs in 2 out of the 6 Bralibase alignment categories. However, we note that the performance of all algorithms can vary dramatically depending on the specific alignment case (see Fig. \ref{fig:01} box plot error bars and outliers). Therefore, we do not assume that good performance on a MSA benchmark sets generalises and recommend users to manual inspect their alignments and compare the results of different alignment programs. Kalign compares favourably to the other two programs in terms of running times and scalability on the Balifam data set (Fig. \ref{fig:01}c). In all alignment cases Kalign is one to two orders of magnitude quicker and compared to clustal omega only uses a single CPU core. * Conclusion We present a new version of Kalign that outperforms other programs in terms of running times while sacrificing little in terms of accuracy. This combinations makes Kalign especially attractive in large alignment problems. * Acknowledgements :PROPERTIES: :UNNUMBERED: t :END: I would like to thank Max Burroughs for providing feedback on Kalign. * Funding :PROPERTIES: :UNNUMBERED: t :END: T.L. is supported by a fellowship from the Feilman Foundation. #+BEGIN_SRC latex \bibliographystyle{plainnat} \bibliography{kalign3} #+END_SRC kalign-3.5.1/doc/paper/revision/000077500000000000000000000000001515023132300164725ustar00rootroot00000000000000kalign-3.5.1/doc/paper/revision/main.tex000066400000000000000000000257771515023132300201620ustar00rootroot00000000000000\documentclass[nocrop]{bioinfo} \copyrightyear{2019} \pubyear{2019} \begin{document} \firstpage{1} \subtitle{Sequence Analysis} \title[short Title]{Kalign 3: multiple sequence alignment of large data sets.} \author[Sample \textit{et~al}.]{Timo Lassmann$^{\text{\sfb 1,}*}$} \corresp{$^\ast$To whom correspondence should be addressed.} \address{$^{\text{\sf 1}}$Telethon Kids Institute, University of Western Australia, Nedlands, WA, Australia.} \corresp{$^\ast$To whom correspondence should be addressed.} \history{Received on XXXXX; revised on XXXXX; accepted on XXXXX} \editor{Associate Editor: XXXXXXX} \abstract{\textbf{Motivation:} Kalign is an efficient multiple sequence alignment (MSA) program capable of aligning thousands of protein or nucleotide sequences. However, current alignment problems involving large number{\color{red} s} of sequences are exceeding Kalign's original design specifications. Here we present a completely re-written and updated version to meet current and future alignment challenges.\\ \textbf{Results:} Kalign now uses a SIMD accelerated version of the bit-parallel Gene Myers algorithm to estimate pariwise distances, adopts a sequence embedding strategy and the bi-secting K-means algorithm to rapidly construct guide trees for thousands of sequences. The new version maintains high alignment accuracy on both protein and nucleotide alignments and scales better than other MSA tools.\\ \textbf{Availability:} The source code of Kalign and code to reproduce the results are found here: https://github.com/timolassmann/kalign\\ \textbf{Contact:} \href{timolassmann@icloud.com}{timolassmann@icloud.com} %\textbf{Supplementary information:} Supplementary data are available at \textit{Bioinformatics}online. } \maketitle \section{Introduction} Multiple sequence alignment (MSA) remains an important task in biological sequence analysis. MSA programs can be divided into consistency and progressive methods. The latter estimate pairwise sequence distances, construct a guide tree and align sequences following the order of the guide tree. Consistency based methods tend to be more accurate than compared to progressive methods but are orders of magnitude slower and therefore not practical when aligning thousands of sequences. Kalign \citep{lassmann2008kalign2} is {\color{red} a} progressive alignment method striking a good balance between accuracy and speed compared to other alignment programs on a range of popular benchmark data sets (see for example \cite{sievers2011fast}). Despite having aged well Kalign was not designed to handle the tens of thousands of sequences frequently encountered today. In particular, the original Kalign program uses the unweighted pair group method with arithmetic mean (UPGMA) algorithm to construct a guide tree resulting in quadratic time complexity. More recent alignment programs have overcome this hurdle by implementing heuristics to construct guide trees \citep{katoh2006parttree,blackshields2010sequence}. Here we present a new version of Kalign, introducing a SIMD (single instruction, multiple data) accelerated version of Gene Myers{\color{red} '} bit-parallel algorithm \citep{myers1999fast} to estimate pairwise sequence distances and adopting the sequence embedding strategy introduced by \cite{blackshields2010sequence} to speed up the construction of guide trees. \section{Methods} We replaced the fast string matching algorithm used in Kalign2 \citep{muth1996approximate} with a new implementation of Gene Myers{\color{red} '} approximate string matching algorithm. The algorithm calculates the exact edit distance between two strings using bit-parallel instructions. In the standard implementation the maximum length of a query is equivalent to the size of a computer word (64 characters on 64 bit architectures). However the algorithm lends itself to further parallelisation using SIMD (single instruction, multiple data) instructions including the AVX and AVX2 instructions available on all modern computers. Using these instructions it becomes possible to compare sequences of length 256. While the implementation of the Gene Myers algorithm is fairly straight forward using AVX instructions some operations are absent from the AVX instruction set and had to be implemented separately. A stand alone implementation of the algorithm is distributed together with Kalign to facilitate downstream adoption and development. To estimate pairwise sequence distances Kalign scans the first 256 characters of the shorter sequence across the longer sequence. The distance is defined as the number of edits required to turn one sequence into an exact match in the longer sequence. For distantly related protein sequences the sequence similarity is too low for the algorithm to detect meaningful distances. Therefore, following the method by \cite{steinegger2018clustering}, Kalign converts all protein sequences into a reduced alphabet by merging (L, M), (I, V), (K, R), (E, Q), (A, S, T), (N, D), and (F, Y) for the purpose of the distance calculation. \begin{figure}[!tpb]%figure1 \centerline{\includegraphics[scale = 0.45]{Paper_figure.jpeg}} \caption{Benchmark results. a) Sum of pairs scores (SP) of all tested alignment programs on Balibase protein alignment data sets. b) SP scores of RNA bralibase alignments. c) Computational performance assessed on the {\color{red}Hom}Fam data set.}\label{fig:01} \end{figure} Kalign adopts the guide tree construction methods used in clustal omega \citep{sievers2011fast}. A number of seed sequences are selected and all sequences are compared against those forming for each sequence a vector of distances to all seeds. The bi-secting kmeans algorithm is used to cluster sequences based on the euclidean distance between these vectors until clusters containing fewer than 100 sequences are found. Here Kalign again uses AVX instructions to accelerate the distance calculation. Finally, the UPGMA method is used to cluster the remaining sequences. Since the bi-secting kmeans algorithm is not guaranteed to discover the opti{\color{red} mal} split of sequence{\color{red}s} into two clusters Kalign runs the algorithm {\color{red}fifty} times using randomly selected sequences to seed the calculation. \section{Results} We compared the performance of Kalign against two other popular progressive alignment methods muscle \citep{edgar2004muscle} and clustal omega \citep{sievers2011fast}. We used the Balibase \citep{thompson1999balibase}, Quantest2 \citep{sievers2019quantest2}, Bralibase \citep{gardner2005benchmark} and {\color{red}Hom}Fam benchmark data sets (Fig. \ref{fig:01}). Clustal omega and Muscle were run with parameters recommended for large alignments on the BaliFam data set (Clustal:--threads=8 --MAC-RAM=48000 --iterations=2; Muscle: -maxiters 2), but otherwise default parameters were used. Kalign's performance on all 6 Balibase categories is statistically indistinguishable from the other two programs (two sample t-test, corrected p < 0.05). Likewise there is no statistical difference in alignment accuracy on the Quantest2 benchmark data set (results not shown). Kalign's mean performance is significantly better compared to the other two programs in 2 out of the 6 Bralibase alignment categories. However, we note that the performance of all algorithms can vary dramatically depending on the specific alignment case (see Fig. \ref{fig:01} box plot error bars and outliers). Therefore, we do not assume that good performance on a{\color{red} n} MSA benchmark sets generalises and recommend users to manual{\color{red} ly} inspect their alignments and compare the results of different alignment programs. Kalign compares favourably to the other two programs in terms of running times and scalability on the Balifam data set (Fig. \ref{fig:01}c). In all alignment cases Kalign is one to two orders of magnitude quicker and compared to clustal omega only uses a single CPU core. \section{Conclusion} We present a new version of Kalign that outperforms other programs in terms of running times while sacrificing little in terms of accuracy. This combination makes Kalign especially attractive in large alignment problems. \section*{Acknowledgements} I would like to thank Max Burroughs for providing feedback on Kalign. \section*{Funding} T.L. is supported by a fellowship from the Feilman Foundation. %\bibliographystyle{natbib} %\bibliographystyle{achemnat} %\bibliographystyle{plainnat} %\bibliographystyle{abbrv} %\bibliographystyle{bioinformatics} % \bibliographystyle{plainnat} % %\bibliography{Document} \begin{thebibliography}{} \bibitem[Blackshields et~al.(2010)Blackshields, Sievers, Shi, Wilm, and Higgins]{blackshields2010sequence} Blackshields, G et al. (2010) Sequence embedding for fast construction of guide trees for multiple sequence alignment. {\it Algorithms for Molecular Biology}, {\bf 5}(1): 21. \bibitem[Edgar(2004)]{edgar2004muscle} Edgar, R.C. (2004) Muscle: multiple sequence alignment with high accuracy and high throughput. {\it Nucleic acids research}, }{\bf32} (5):1792--1797. \bibitem[Gardner et~al.(2005)Gardner, Wilm, and Washietl]{gardner2005benchmark} Gardner, P. et. al. (2005) A benchmark of multiple sequence alignment programs upon structural rnas. {\it Nucleic acids research}, {\bf 33} (8):2433--2439. \bibitem[Katoh and Toh(2006)]{katoh2006parttree} Katoh, K. and Toh, H (2006) Parttree: an algorithm to build an approximate tree from a large number of unaligned sequences. {\it Bioinformatics}, {\bf 23} (3):372--374. \bibitem[Lassmann et~al.(2008)Lassmann, Frings, and Sonnhammer]{lassmann2008kalign2} Lassmann, T. et al. (2008) Kalign2: high-performance multiple alignment of protein and nucleotide sequences allowing external features. {\it Nucleic acids research}, {\bf 37} (3):858--865. \bibitem[Muth and Manber(1996)]{muth1996approximate} Robert Muth, R. and Manber, U. (1996) Approximate multiple string search. {\it Annual Symposium on Combinatorial Pattern Matching}, 75--86. \bibitem[Myers(1999)]{myers1999fast} Myers, G. (1999) A fast bit-vector algorithm for approximate string matching based on dynamic programming. {\it Journal of the ACM (JACM)}, {\bf 46} (3): 395--415. \bibitem[Sievers and Higgins(2019)]{sievers2019quantest2} Sievers, F. and Higgins, D.G. (2019) Quantest2: Benchmarking multiple sequence alignments using secondary structure prediction. {\it Bioinformatics}. \bibitem[Sievers et~al.(2011)Sievers, Wilm, Dineen, Gibson, Karplus, Li, Lopz, McWilliam, Remmert, S{\"o}ding, et~al.]{sievers2011fast} Sievers, F. et al. (2011) Fast, scalable generation of high-quality protein multiple sequence alignments using clustal omega. {\it Molecular systems biology}, {\bf 7} (1). \bibitem[Steinegger and S{\"o}ding(2018)]{steinegger2018clustering} Steinegger, M. and S{\"o}ding, J. (2018) Clustering huge protein sequence sets in linear time. {\it Nature communications}, {\bf 9} (1):2542. \bibitem[Thompson et~al.(1999)Thompson, Plewniak, and Poch]{thompson1999balibase} Thompson, J.D. et al. (1999) Balibase: a benchmark alignment database for the evaluation of multiple alignment programs. {\it Bioinformatics}, {\bf 15} (1): 87--88. \end{thebibliography} \end{document} kalign-3.5.1/lib/000077500000000000000000000000001515023132300135265ustar00rootroot00000000000000kalign-3.5.1/lib/CMakeLists.txt000066400000000000000000000144711515023132300162750ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.18) if(NOT KALIGN_PACKAGE_NAME) set(KALIGN_PACKAGE_NAME ${CMAKE_PROJECT_NAME}) endif() if(NOT KALIGN_PACKAGE_VERSION) set(KALIGN_PACKAGE_VERSION ${KALIGN_LIBRARY_VERSION_STRING}) endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in" "version.h") set(source_files src/test.c src/tldevel.c src/tlmisc.c src/tlrng.c src/esl_stopwatch.c src/msa_alloc.c src/msa_op.c src/msa_io.c src/msa_misc.c src/msa_check.c src/msa_cmp.c src/msa_sort.c src/alphabet.c src/task.c src/bisectingKmeans.c src/sequence_distance.c src/bpm.c src/euclidean_dist.c src/pick_anchor.c src/aln_wrap.c src/aln_apair_dist.c src/aln_param.c src/aln_run.c src/aln_mem.c src/aln_setup.c src/aln_controller.c src/aln_seqseq.c src/aln_seqprofile.c src/aln_profileprofile.c src/aln_refine.c src/sp_score.c src/weave_alignment.c src/poar.c src/consensus_msa.c src/anchor_consistency.c src/ensemble.c # src/coretralign.c # src/test.h ) add_library(${PROJECT_NAME}_OBJ OBJECT ${source_files}) if(OpenMP_C_FOUND) target_link_libraries(${PROJECT_NAME}_OBJ PRIVATE OpenMP::OpenMP_C) endif(OpenMP_C_FOUND) target_include_directories(${PROJECT_NAME}_OBJ PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_compile_definitions(${PROJECT_NAME}_OBJ PRIVATE KALIGN_PACKAGE_VERSION=\"${KALIGN_PACKAGE_VERSION}\") add_library(${PROJECT_NAME}) add_library(${NAMESPACE_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) generate_export_header(${PROJECT_NAME} EXPORT_FILE_NAME ${PROJECT_NAME}/${PROJECT_NAME}_export.h ) set(public_header_files ${CMAKE_SOURCE_DIR}/lib/include/kalign/kalign.h ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_export.h #${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_export.h ) set_target_properties(${PROJECT_NAME} PROPERTIES LANGUAGES C CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF VERSION ${KALIGN_LIBRARY_VERSION_STRING} SOVERSION ${KALIGN_LIBRARY_VERSION_MAJOR} PUBLIC_HEADER "${public_header_files}" CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1 ) target_sources(${PROJECT_NAME} PRIVATE ${public_header_files} $ ) # Define headers for this library. PUBLIC headers are used for # compiling the library, and will be added to consumers' build # paths. target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ ) target_include_directories(${PROJECT_NAME} PRIVATE src ) target_link_libraries(${PROJECT_NAME} PRIVATE m) if(OpenMP_C_FOUND) target_link_libraries(${PROJECT_NAME} PRIVATE OpenMP::OpenMP_C) endif() add_library(${PROJECT_NAME}_static STATIC ${public_header_files} $ ) set_target_properties(${PROJECT_NAME}_static PROPERTIES LANGUAGES C CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF VERSION ${KALIGN_LIBRARY_VERSION_STRING} SOVERSION ${KALIGN_LIBRARY_VERSION_MAJOR} PUBLIC_HEADER "${public_header_files}" CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1 ) target_include_directories(${PROJECT_NAME}_static PUBLIC $ $ $ ) target_include_directories(${PROJECT_NAME}_static PRIVATE src ) target_link_libraries(${PROJECT_NAME}_static PRIVATE m) if(OpenMP_C_FOUND) target_link_libraries(${PROJECT_NAME}_static PRIVATE OpenMP::OpenMP_C) endif() add_library(tldevel STATIC src/tldevel.c src/tlmisc.c src/tlrng.c src/esl_stopwatch.c ) target_include_directories(tldevel PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) target_link_libraries(tldevel PRIVATE m) # adjust this path depending where cmake searches for the target files set(ConfigPackageLocation "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") # 'make install' to the correct locations (provided by GNUInstallDirs). install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Library ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Library RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Library # This is for Windows PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT Development INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install(EXPORT ${PROJECT_NAME}Targets FILE ${PROJECT_NAME}Targets.cmake NAMESPACE ${NAMESPACE_NAME}:: DESTINATION ${ConfigPackageLocation} COMPONENT Development ) configure_package_config_file( ${PROJECT_NAME}Config.cmake.in ${PROJECT_NAME}Config.cmake INSTALL_DESTINATION "${ConfigPackageLocation}" PATH_VARS CMAKE_INSTALL_PREFIX ) write_basic_package_version_file( ${PROJECT_NAME}ConfigVersion.cmake VERSION ${KALIGN_LIBRARY_VERSION_STRING} COMPATIBILITY AnyNewerVersion ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" DESTINATION ${ConfigPackageLocation} COMPONENT Development ) add_executable(bpm_utest src/tldevel.c src/tlrng.c src/esl_stopwatch.c src/alphabet.c src/bpm.c src/bpm_test.c ) target_link_libraries(bpm_utest PRIVATE m) add_test( NAME bpm_utest COMMAND bpm_utest ) add_executable(alphabet_utest src/tldevel.c src/alphabet.c ) set_target_properties(alphabet_utest PROPERTIES COMPILE_FLAGS "-DUTEST_ALPHABET") add_test( NAME alphabet_utest COMMAND alphabet_utest ) add_executable(edist_utest src/tldevel.c src/tlrng.c src/esl_stopwatch.c src/euclidean_dist.c ) target_link_libraries(edist_utest PRIVATE m) set_target_properties(edist_utest PROPERTIES COMPILE_FLAGS "-DUTEST_EDIST") add_test( NAME edist_utest COMMAND edist_utest ) add_executable(task_utest src/tldevel.c src/tlrng.c src/task.c ) target_link_libraries(task_utest PRIVATE m) set_target_properties(task_utest PROPERTIES COMPILE_FLAGS "-DTASKWRITETEST") add_test( NAME task_utest COMMAND task_utest )kalign-3.5.1/lib/include/000077500000000000000000000000001515023132300151515ustar00rootroot00000000000000kalign-3.5.1/lib/include/kalign/000077500000000000000000000000001515023132300164165ustar00rootroot00000000000000kalign-3.5.1/lib/include/kalign/kalign.h000066400000000000000000000106271515023132300200420ustar00rootroot00000000000000#ifndef KALIGN_H #define KALIGN_H #include #ifdef KALIGN_IMPORT #define EXTERN #else #ifndef EXTERN #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif #endif #define KALIGN_TYPE_DNA 0 #define KALIGN_TYPE_DNA_INTERNAL 1 #define KALIGN_TYPE_RNA 2 #define KALIGN_TYPE_PROTEIN 3 #define KALIGN_TYPE_PROTEIN_DIVERGENT 4 #define KALIGN_TYPE_PROTEIN_PFASUM43 5 #define KALIGN_TYPE_PROTEIN_PFASUM60 6 #define KALIGN_TYPE_PROTEIN_PFASUM_AUTO 7 #define KALIGN_TYPE_UNDEFINED 8 #define KALIGN_REFINE_NONE 0 #define KALIGN_REFINE_ALL 1 #define KALIGN_REFINE_CONFIDENT 2 #define KALIGN_REFINE_INLINE 3 struct msa; /* input output routines */ EXTERN int kalign_read_input(char* infile, struct msa** msa,int quiet); EXTERN int kalign_write_msa(struct msa *msa, char *outfile, char *format); /* EXTERN int kalign_msa_to_arr(struct msa *msa, char ***aligned, int *out_aln_len); */ /* Used to convert sequences read by non-kalign code into the msa struct.. */ /* EXTERN int kalign_arr_to_msa(char **input_sequences, int *len, int numseq, struct msa **multiple_aln); */ EXTERN int kalign(char **seq, int *len, int numseq, int n_threads, int type, float gpo, float gpe, float tgpe, char ***aligned, int *out_aln_len); EXTERN int kalign_run(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget); EXTERN int kalign_run_seeded(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, uint64_t tree_seed, float tree_noise, float dist_scale, float vsm_amax, float use_seq_weights, int consistency_anchors, float consistency_weight); EXTERN int kalign_run_dist_scale(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, float dist_scale, float vsm_amax, float use_seq_weights); EXTERN int kalign_run_realign(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, float dist_scale, float vsm_amax, int realign_iterations, float use_seq_weights, int consistency_anchors, float consistency_weight); EXTERN int kalign_post_realign(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, float dist_scale, float vsm_amax, int realign_iterations, float use_seq_weights); EXTERN int kalign_ensemble(struct msa* msa, int n_threads, int type, int n_runs, float gpo, float gpe, float tgpe, uint64_t seed, int min_support, const char* save_poar_path, int refine, float dist_scale, float vsm_amax, int realign, float use_seq_weights, int consistency_anchors, float consistency_weight); EXTERN int kalign_consensus_from_poar(struct msa* msa, const char* poar_path, int min_support); /* Memory */ EXTERN void kalign_free_msa(struct msa* msa); /* Auxillary... */ EXTERN int reformat_settings_msa(struct msa *msa, int rename, int unalign); EXTERN int kalign_check_msa(struct msa* msa, int exit_on_error); EXTERN int kalign_msa_compare(struct msa *r, struct msa *t, float *score); struct poar_score; EXTERN int kalign_msa_compare_detailed(struct msa *r, struct msa *t, float max_gap_frac, struct poar_score *out); EXTERN int kalign_msa_compare_with_mask(struct msa *r, struct msa *t, int *scored_cols, int n_cols, struct poar_score *out); #undef KALIGN_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/kalignConfig.cmake.in000066400000000000000000000001761515023132300175340ustar00rootroot00000000000000@PACKAGE_INIT@ include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") check_required_components("@PROJECT_NAME@") kalign-3.5.1/lib/src/000077500000000000000000000000001515023132300143155ustar00rootroot00000000000000kalign-3.5.1/lib/src/aln_apair_dist.c000066400000000000000000000041331515023132300174330ustar00rootroot00000000000000#include "tldevel.h" #include "msa_struct.h" #define ALN_APAIR_DIST_IMPORT #include "aln_apair_dist.h" static float pairwise_identity_dist(const char* a, const char* b, int alnlen); int compute_aln_pairwise_dist(struct msa* msa, float*** dm_ptr) { float** dm = NULL; int n; int i, j; ASSERT(msa != NULL, "No MSA"); ASSERT(msa->aligned == ALN_STATUS_FINAL, "MSA must be finalized"); n = msa->numseq; MMALLOC(dm, sizeof(float*) * n); for(i = 0; i < n; i++){ dm[i] = NULL; } for(i = 0; i < n; i++){ MMALLOC(dm[i], sizeof(float) * n); dm[i][i] = 0.0f; } for(i = 0; i < n - 1; i++){ const char* seq_i = msa->sequences[i]->seq; for(j = i + 1; j < n; j++){ float d = pairwise_identity_dist(seq_i, msa->sequences[j]->seq, msa->alnlen); dm[i][j] = d; dm[j][i] = d; } } *dm_ptr = dm; return OK; ERROR: if(dm){ for(i = 0; i < n; i++){ if(dm[i]) MFREE(dm[i]); } MFREE(dm); } return FAIL; } void free_aln_dm(float** dm, int n) { int i; if(dm == NULL) return; for(i = 0; i < n; i++){ if(dm[i]) MFREE(dm[i]); } MFREE(dm); } /* Distance = 1.0 - identity. Only counts columns where both sequences have a residue (no gap). */ float pairwise_identity_dist(const char* a, const char* b, int alnlen) { int matches = 0; int aligned = 0; int i; for(i = 0; i < alnlen; i++){ if(a[i] != '-' && b[i] != '-'){ aligned++; if(a[i] == b[i]){ matches++; } } } if(aligned == 0){ return 1.0f; } return 1.0f - (float)matches / (float)aligned; } kalign-3.5.1/lib/src/aln_apair_dist.h000066400000000000000000000012721515023132300174410ustar00rootroot00000000000000#ifndef ALN_APAIR_DIST_H #define ALN_APAIR_DIST_H #ifdef ALN_APAIR_DIST_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; /* Compute NxN pairwise identity distances from an aligned MSA. Distance = 1.0 - (matches / aligned_positions) for each pair. The MSA must be finalized (sequences contain gap characters). Caller must free the returned matrix with free_dm(). */ EXTERN int compute_aln_pairwise_dist(struct msa* msa, float*** dm_ptr); /* Free an NxN distance matrix allocated by compute_aln_pairwise_dist. */ EXTERN void free_aln_dm(float** dm, int n); #undef ALN_APAIR_DIST_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_controller.c000066400000000000000000000312701515023132300175010ustar00rootroot00000000000000#include #include "tldevel.h" #include "aln_param.h" #include "aln_struct.h" /* The dynamic programming modules */ #include "aln_seqseq.h" #include "aln_seqprofile.h" #include "aln_profileprofile.h" #define ALN_CONTROLLER_IMPORT #include "aln_controller.h" static int aln_continue(struct aln_mem* m,float input_states[],int old_cor[],int meet,int transition, uint8_t serial); int aln_runner(struct aln_mem* m) { float input_states[6]; int old_cor[5]; float score; int mid; int meet; int transition; /* switch to serial if too little work. */ if(m->enda - m->starta < KALIGN_ALN_SERIAL_THRESHOLD){ return aln_runner_serial(m); } if(m->starta >= m->enda){ return OK;//hirsch_path; } if(m->startb >= m->endb){ return OK;///hirsch_path; } input_states[0] = m->f[0].a; input_states[1] = m->f[0].ga; input_states[2] = m->f[0].gb; input_states[3] = m->b[0].a; input_states[4] = m->b[0].ga; input_states[5] = m->b[0].gb; mid = ((m->enda - m->starta) / 2)+ m->starta; old_cor[0] = m->starta; old_cor[1] = m->enda; old_cor[2] = m->startb; old_cor[3] = m->endb; old_cor[4] = mid; /* fprintf(stderr,"Forward:%d-%d %d-%d\n",m->starta,m->enda,m->startb,m->endb); */ m->enda = mid; m->starta_2 = mid; m->enda_2 = old_cor[1]; /* fprintf(stderr,"Forward:%d-%d %d-%d\n",m->starta,m->enda,m->startb,m->endb); */ #ifdef HAVE_OPENMP #pragma omp parallel #pragma omp single nowait { #endif if(m->seq1){ #ifdef HAVE_OPENMP #pragma omp task shared(m) if(m->run_parallel) #endif aln_seqseq_foward(m); #ifdef HAVE_OPENMP #pragma omp task shared(m) if(m->run_parallel) #endif aln_seqseq_backward(m); #ifdef HAVE_OPENMP #pragma omp taskwait #endif aln_seqseq_meetup(m,old_cor,&meet,&transition,&score); }else if(m->prof2){ #ifdef HAVE_OPENMP #pragma omp task shared(m) if(m->run_parallel) #endif aln_profileprofile_foward(m); #ifdef HAVE_OPENMP #pragma omp task shared(m) if(m->run_parallel) #endif aln_profileprofile_backward(m); #ifdef HAVE_OPENMP #pragma omp taskwait #endif aln_profileprofile_meetup(m,old_cor,&meet,&transition,&score); }else{ #ifdef HAVE_OPENMP #pragma omp task shared(m) if(m->run_parallel) #endif aln_seqprofile_foward(m); #ifdef HAVE_OPENMP #pragma omp task shared(m) if(m->run_parallel) #endif aln_seqprofile_backward(m); #ifdef HAVE_OPENMP #pragma omp taskwait #endif aln_seqprofile_meetup(m,old_cor,&meet,&transition,&score); } #ifdef HAVE_OPENMP } #endif if(m->mode == ALN_MODE_SCORE_ONLY){ m->score = score; }else{ aln_continue(m, input_states,old_cor, meet, transition,0); } return OK; } int aln_runner_serial(struct aln_mem* m) { float input_states[6]; int old_cor[5]; float score; int mid; int meet; int transition; if(m->starta >= m->enda){ return OK;//hirsch_path; } if(m->startb >= m->endb){ return OK;///hirsch_path; } input_states[0] = m->f[0].a; input_states[1] = m->f[0].ga; input_states[2] = m->f[0].gb; input_states[3] = m->b[0].a; input_states[4] = m->b[0].ga; input_states[5] = m->b[0].gb; mid = ((m->enda - m->starta) / 2)+ m->starta; old_cor[0] = m->starta; old_cor[1] = m->enda; old_cor[2] = m->startb; old_cor[3] = m->endb; old_cor[4] = mid; /* fprintf(stderr,"Forward:%d-%d %d-%d\n",m->starta,m->enda,m->startb,m->endb); */ m->enda = mid; m->starta_2 = mid; m->enda_2 = old_cor[1]; if(m->seq1){ aln_seqseq_foward(m); aln_seqseq_backward(m); aln_seqseq_meetup(m,old_cor,&meet,&transition,&score); }else if(m->prof2){ aln_profileprofile_foward(m); aln_profileprofile_backward(m); aln_profileprofile_meetup(m,old_cor,&meet,&transition,&score); }else{ aln_seqprofile_foward(m); aln_seqprofile_backward(m); aln_seqprofile_meetup(m,old_cor,&meet,&transition,&score); } /* CRITICAL */ //m->starta = mid; //m->enda = old_cor[1]; //fprintf(stderr,"Backward:%d-%d %d-%d\n",m->starta,m->enda,m->startb,m->endb); /* if(m->seq1){ */ /* }else if(m->prof2){ */ /* }else{ */ /* } */ if(m->mode == ALN_MODE_SCORE_ONLY){ m->score = score; }else{ aln_continue(m, input_states,old_cor, meet, transition,1); } return OK; } int aln_continue(struct aln_mem* m,float input_states[],int old_cor[],int meet,int transition, uint8_t serial) { int* path = m->path; switch(transition){ case 1: //a -> a = 1 path[old_cor[4]] = meet; path[old_cor[4]+1] = meet+1; //foward: m->f[0].a = input_states[0]; m->f[0].ga = input_states[1]; m->f[0].gb = input_states[2]; m->b[0].a = 0.0F; m->b[0].ga = -FLT_MAX; m->b[0].gb = -FLT_MAX; m->starta = old_cor[0]; m->enda = old_cor[4]-1; m->startb = old_cor[2]; m->endb = meet-1; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } //backward: m->starta = old_cor[4]+1; m->enda = old_cor[1]; m->startb = meet+1; m->endb = old_cor[3]; m->f[0].a = 0.0F; m->f[0].ga = -FLT_MAX; m->f[0].gb = -FLT_MAX; m->b[0].a = input_states[3]; m->b[0].ga = input_states[4]; m->b[0].gb = input_states[5]; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } break; case 2:// a -> ga = 2 path[old_cor[4]] = meet; //foward: m->f[0].a = input_states[0]; m->f[0].ga = input_states[1]; m->f[0].gb = input_states[2]; m->b[0].a = 0.0F; m->b[0].ga = -FLT_MAX; m->b[0].gb = -FLT_MAX; m->starta = old_cor[0]; m->enda = old_cor[4]-1; m->startb = old_cor[2]; m->endb = meet-1; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } //backward: m->starta = old_cor[4]; m->enda = old_cor[1]; m->startb = meet+1; m->endb = old_cor[3]; m->f[0].a = -FLT_MAX; m->f[0].ga = 0.0F; m->f[0].gb = -FLT_MAX; m->b[0].a = input_states[3]; m->b[0].ga = input_states[4]; m->b[0].gb = input_states[5]; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } break; case 3:// a -> gb = 3 path[old_cor[4]] = meet; //foward: m->f[0].a = input_states[0]; m->f[0].ga = input_states[1]; m->f[0].gb = input_states[2]; m->b[0].a = 0.0F; m->b[0].ga = -FLT_MAX; m->b[0].gb = -FLT_MAX; m->starta = old_cor[0]; m->enda = old_cor[4]-1; m->startb = old_cor[2]; m->endb = meet-1; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } //backward: m->starta = old_cor[4]+1; m->enda = old_cor[1]; m->startb = meet; m->endb = old_cor[3]; m->f[0].a = -FLT_MAX; m->f[0].ga = -FLT_MAX; m->f[0].gb = 0.0; m->b[0].a = input_states[3]; m->b[0].ga = input_states[4]; m->b[0].gb = input_states[5]; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } break; case 5://ga -> a = 5 path[old_cor[4]+1] = meet+1; //foward: m->f[0].a = input_states[0]; m->f[0].ga = input_states[1]; m->f[0].gb = input_states[2]; m->b[0].a = -FLT_MAX; m->b[0].ga = 0.0F; m->b[0].gb = -FLT_MAX; m->starta = old_cor[0]; m->enda = old_cor[4]; m->startb = old_cor[2]; m->endb = meet-1; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } //backward: m->starta = old_cor[4]+1; m->enda = old_cor[1]; m->startb = meet+1; m->endb = old_cor[3]; m->f[0].a = 0.0F; m->f[0].ga = -FLT_MAX; m->f[0].gb = -FLT_MAX; m->b[0].a = input_states[3]; m->b[0].ga = input_states[4]; m->b[0].gb = input_states[5]; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } break; case 6://gb->gb = 6; //foward: m->f[0].a = input_states[0]; m->f[0].ga = input_states[1]; m->f[0].gb = input_states[2]; m->b[0].a = -FLT_MAX; m->b[0].ga = -FLT_MAX; m->b[0].gb = 0.0F; m->starta = old_cor[0]; m->enda = old_cor[4]-1; m->startb = old_cor[2]; m->endb = meet; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } //backward: m->starta = old_cor[4]+1; m->enda = old_cor[1]; m->startb = meet; m->endb = old_cor[3]; m->f[0].a = -FLT_MAX; m->f[0].ga = -FLT_MAX; m->f[0].gb = 0.0F; m->b[0].a = input_states[3]; m->b[0].ga = input_states[4]; m->b[0].gb = input_states[5]; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } break; case 7://gb->a = 7; path[old_cor[4]+1] = meet+1; //foward: m->f[0].a = input_states[0]; m->f[0].ga = input_states[1]; m->f[0].gb = input_states[2]; m->b[0].a = -FLT_MAX; m->b[0].ga = -FLT_MAX; m->b[0].gb = 0.0F; m->starta = old_cor[0]; m->enda = old_cor[4]-1; m->startb = old_cor[2]; m->endb = meet; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } //backward: m->starta = old_cor[4]+1; m->enda = old_cor[1]; m->startb = meet+1; m->endb = old_cor[3]; m->f[0].a = 0.0F; m->f[0].ga = -FLT_MAX; m->f[0].gb = -FLT_MAX; m->b[0].a = input_states[3]; m->b[0].ga = input_states[4]; m->b[0].gb = input_states[5]; if(serial){ aln_runner_serial(m); }else{ aln_runner(m); } break; default: break; } return OK; } kalign-3.5.1/lib/src/aln_controller.h000066400000000000000000000005601515023132300175040ustar00rootroot00000000000000#ifndef ALN_CONTROLLER_H #define ALN_CONTROLLER_H #include #ifdef ALN_CONTROLLER_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct aln_mem; EXTERN int aln_runner(struct aln_mem* m); EXTERN int aln_runner_serial(struct aln_mem* m); #undef ALN_CONTROLLER_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_mem.c000066400000000000000000000056161515023132300161010ustar00rootroot00000000000000#include "tldevel.h" #include "aln_struct.h" #define ALN_MEM_IMPORT #include "aln_mem.h" int alloc_aln_mem(struct aln_mem** mem, int x) { struct aln_mem* m = NULL; ASSERT(x>=1, "Given size %d is too small",x); // a=((typeof(a))(((int)(((void *)malloc(c+15))+15))&-16)). MMALLOC(m,sizeof(struct aln_mem)); m->seq1 = NULL; m->seq2 = NULL; m->prof1 = NULL; m->prof2 = NULL; m->sip = 0; m->mode = ALN_MODE_FULL; m->score = 0.0F; m->margin_sum = 0.0F; m->margin_count = 0; m->flip_threshold = 0.0F; m->flip_trial = 0; m->flip_stride = 1; m->flip_counter = 0; m->flip_mask = 0; m->flip_margins = NULL; m->flip_margin_alloc = 0; m->flip_bit_map = NULL; m->flip_n_targets = 0; m->flip_n_uncertain = 0; m->ap = NULL; m->consistency = NULL; m->consistency_stride = 0; m->starta = 0; m->startb = 0; m->enda = 0; m->endb = 0; m->size = x; m->len_a = 0; m->len_b = 0; m->f = NULL; m->b = NULL; m->path = NULL; m->tmp_path = NULL; m->alloc_path_len = x; MMALLOC(m->f,sizeof(struct states)* m->size); MMALLOC(m->b,sizeof(struct states)* m->size); MMALLOC(m->path, sizeof(int) * m->alloc_path_len); MMALLOC(m->tmp_path, sizeof(int) * m->alloc_path_len); *mem = m; return OK; ERROR: free_aln_mem(m); return FAIL; } int resize_aln_mem(struct aln_mem* m) { int g; /* For dynamic programming I only need a slice of the dyn. prog. matrix. To be precise, a slide of the shorter sequence */ g = MACRO_MAX(m->len_a, m->len_b) + 2; if(g > m->size){ while(m->size < g){ m->size = m->size + m->size / 2; } MREALLOC(m->f,sizeof(struct states)* m->size); MREALLOC(m->b,sizeof(struct states)* m->size); } /* For the alignment path I need at most: */ g = m->len_a+ m->len_b + 2; /* memory */ if(g > m->alloc_path_len){ while(m->alloc_path_len < g){ m->alloc_path_len = m->alloc_path_len + m->alloc_path_len / 2; } MREALLOC(m->path, sizeof(int) * m->alloc_path_len); MREALLOC(m->tmp_path, sizeof(int) * m->alloc_path_len); } return OK; ERROR: free_aln_mem(m); return FAIL; } void free_aln_mem(struct aln_mem* m) { if(m){ if(m->flip_bit_map) MFREE(m->flip_bit_map); if(m->flip_margins) MFREE(m->flip_margins); MFREE(m->tmp_path); MFREE(m->path); MFREE(m->f); MFREE(m->b); MFREE(m); } } kalign-3.5.1/lib/src/aln_mem.h000066400000000000000000000005671515023132300161060ustar00rootroot00000000000000#ifndef ALN_MEM_H #define ALN_MEM_H #ifdef ALN_MEM_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct aln_mem; EXTERN int alloc_aln_mem(struct aln_mem** mem, int x); EXTERN int resize_aln_mem(struct aln_mem* m); EXTERN void free_aln_mem(struct aln_mem* m); #undef ALN_MEM_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_param.c000066400000000000000000000461551515023132300164260ustar00rootroot00000000000000#include "tldevel.h" #include "kalign/kalign.h" #include "msa_struct.h" #define ALN_PARAM_IMPORT #include "aln_param.h" static int set_subm_gaps_CorBLOSUM66_13plus(struct aln_param *ap); static int set_subm_gaps_gon250(struct aln_param* ap); static int set_subm_gaps_PFASUM43(struct aln_param *ap); static int set_subm_gaps_PFASUM60(struct aln_param *ap); static int set_subm_gaps_DNA(struct aln_param *ap); static int set_subm_gaps_DNA_internal(struct aln_param *ap); static int set_subm_gaps_RNA(struct aln_param *ap); int aln_param_init(struct aln_param **aln_param,int biotype , int n_threads, int type, float gpo, float gpe, float tgpe) { struct aln_param* ap = NULL; /* Allocate */ MMALLOC(ap, sizeof(struct aln_param)); ap->subm = NULL; ap->nthreads = n_threads; MMALLOC(ap->subm,sizeof (float*) * 23); for (int i = 23;i--;){ ap->subm[i] = NULL; MMALLOC(ap->subm[i],sizeof(float) * 23); for (int j = 23;j--;){ ap->subm[i][j] = 0.0f; } } if(biotype == ALN_BIOTYPE_DNA){ /* include/kalign/ */ switch (type) { case KALIGN_TYPE_DNA: set_subm_gaps_DNA(ap); break; case KALIGN_TYPE_DNA_INTERNAL: set_subm_gaps_DNA_internal(ap); break; case KALIGN_TYPE_RNA: set_subm_gaps_RNA(ap); break; case KALIGN_TYPE_PROTEIN: ERROR_MSG("Detected DNA sequences but --type protein option was selected."); break; default: set_subm_gaps_RNA(ap); break; } }else if(biotype == ALN_BIOTYPE_PROTEIN){ switch (type) { case KALIGN_TYPE_PROTEIN: set_subm_gaps_PFASUM43(ap); break; case KALIGN_TYPE_PROTEIN_DIVERGENT: set_subm_gaps_gon250(ap); break; case KALIGN_TYPE_PROTEIN_PFASUM43: set_subm_gaps_PFASUM43(ap); break; case KALIGN_TYPE_PROTEIN_PFASUM60: set_subm_gaps_PFASUM60(ap); break; case KALIGN_TYPE_DNA: ERROR_MSG("Detected protein sequences but --type dna option was selected."); break; case KALIGN_TYPE_DNA_INTERNAL: ERROR_MSG("Detected protein sequences but --type internal option was selected."); break; case KALIGN_TYPE_RNA: ERROR_MSG("Detected protein sequences but --type rna option was selected."); break; default: set_subm_gaps_PFASUM43(ap); break; } }else{ ERROR_MSG("Unable to determine what alphabet to use."); } if(gpo >= 0.0){ ap->gpo = gpo; } if(gpe >= 0.0){ ap->gpe = gpe; } if(tgpe >= 0.0){ ap->tgpe = tgpe; } ap->dist_scale = 0.0f; ap->vsm_amax = (biotype == ALN_BIOTYPE_PROTEIN) ? 2.0f : 0.0f; ap->subm_offset = 0.0f; ap->adaptive_budget = 0; ap->use_seq_weights = 0.0f; ap->consistency_anchors = 0; ap->consistency_weight = 2.0f; *aln_param = ap; return OK; ERROR: aln_param_free(ap); return FAIL; } int set_subm_gaps_gon250(struct aln_param* ap) { //A,R,N,D,C,Q,E,G,H,I,L,K,M,F,P,S,T,W,Y,V,B,Z,X, int gon250mt[23][23] = { // A, R, N, D, C, Q, E, G, H, I, L, K, M, F, P, S, T, W, Y, V, B, Z, X, { 24, -6, -3, -3, 5, -2, 0, 5, -8, -8, -12, -4, -7, -23, 3, 11, 6, -36, -22, 1, 0, 0, 0},// A { -6, 47, 3, -3, -22, 15, 4, -10, 6, -24, -22, 27, -17, -32, -9, -2, -2, -16, -18, -20, 0, 0, 0},// R { -3, 3, 38, 22, -18, 7, 9, 4, 12, -28, -30, 8, -22, -31, -9, 9, 5, -36, -14, -22, 0, 0, 0},// N { -3, -3, 22, 47, -32, 9, 27, 1, 4, -38, -40, 5, -30, -45, -7, 5, 0, -52, -28, -29, 0, 0, 0},// D { 5, -22, -18, -32, 115, -24, -30, -20, -13, -11, -15, -28, -9, -8, -31, 1, -5, -10, -5, 0, 0, 0, 0},// C { -2, 15, 7, 9, -24, 27, 17, -10, 12, -19, -16, 15, -10, -26, -2, 2, 0, -27, -17, -15, 0, 0, 0},// Q { 0, 4, 9, 27, -30, 17, 36, -8, 4, -27, -28, 12, -20, -39, -5, 2, -1, -43, -27, -19, 0, 0, 0},// E { 5, -10, 4, 1, -20, -10, -8, 66, -14, -45, -44, -11, -35, -52, -16, 4, -11, -40, -40, -33, 0, 0, 0},// G { -8, 6, 12, 4, -13, 12, 4, -14, 60, -22, -19, 6, -13, -1, -11, -2, -3, -8, 22, -20, 0, 0, 0},// H { -8, -24, -28, -38, -11, -19, -27, -45, -22, 40, 28, -21, 25, 10, -26, -18, -6, -18, -7, 31, 0, 0, 0},// I { -12, -22, -30, -40, -15, -16, -28, -44, -19, 28, 40, -21, 28, 20, -23, -21, -13, -7, 0, 18, 0, 0, 0},// L { -4, 27, 8, 5, -28, 15, 12, -11, 6, -21, -21, 32, -14, -33, -6, 1, 1, -35, -21, -17, 0, 0, 0},// K { -7, -17, -22, -30, -9, -10, -20, -35, -13, 25, 28, -14, 43, 16, -24, -14, -6, -10, -2, 16, 0, 0, 0},// M { -23, -32, -31, -45, -8, -26, -39, -52, -1, 10, 20, -33, 16, 70, -38, -28, -22, 36, 51, 1, 0, 0, 0},// F { 3, -9, -9, -7, -31, -2, -5, -16, -11, -26, -23, -6, -24, -38, 76, 4, 1, -50, -31, -18, 0, 0, 0},// P { 11, -2, 9, 5, 1, 2, 2, 4, -2, -18, -21, 1, -14, -28, 4, 22, 15, -33, -19, -10, 0, 0, 0},// S { 6, -2, 5, 0, -5, 0, -1, -11, -3, -6, -13, 1, -6, -22, 1, 15, 25, -35, -19, 0, 0, 0, 0},// T { -36, -16, -36, -52, -10, -27, -43, -40, -8, -18, -7, -35, -10, 36, -50, -33, -35, 142, 41, -26, 0, 0, 0},// W { -22, -18, -14, -28, -5, -17, -27, -40, 22, -7, 0, -21, -2, 51, -31, -19, -19, 41, 78, -11, 0, 0, 0},// Y { 1, -20, -22, -29, 0, -15, -19, -33, -20, 31, 18, -17, 16, 1, -18, -10, 0, -26, -11, 34, 0, 0, 0},// V { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},// B { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},// Z { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},// X }; for(int i = 0; i < 23;i++){ for(int j = 0; j < 23;j++){ ap->subm[i][j] = (float)(gon250mt[i][j]);// *2.0F; } } ap->gpo = 55; ap->gpe = 8; ap->tgpe = 4; return OK; } int set_subm_gaps_CorBLOSUM66_13plus(struct aln_param* ap) { int i; int j; //char aacode[20] = "ACDEFGHIKLMNPQRSTVWY"; //char aa_order[23] = "ARNDCQEGHILKMFPSTWYVBZX"; //int num_aa = 23; int CorBLOSUM66_13plus[23][23] = { /*A R N D C Q E G H I L K M F P S T W Y V B Z X*/ {5,-1,-1,-2,-2,-1,-1,0,-2,-1,-1,-1,0,-2,-1,1,0,-2,-2,0,-2,-1,0}, {-1,6,0,-1,-3,1,1,-2,0,-2,-2,3,-1,-3,-1,-1,-1,-1,-1,-2,0,1,-1}, {-1,0,6,2,-3,1,0,0,0,-3,-3,0,-2,-2,-1,1,0,-2,-1,-2,4,0,-1}, {-2,-1,2,7,-3,1,2,-1,-1,-3,-3,0,-3,-3,-1,0,-1,-3,-2,-3,5,2,-1}, {-2,-3,-3,-3,12,-3,-4,-3,-2,-2,-3,-3,-2,-1,-3,-2,-2,-3,-2,-2,-3,-3,-2}, {-1,1,1,1,-3,5,2,-2,0,-2,-2,1,0,-2,-1,0,0,-1,-1,-2,1,3,0}, {-1,1,0,2,-4,2,6,-2,-1,-3,-3,1,-2,-3,0,0,-1,-2,-2,-2,1,4,-1}, {0,-2,0,-1,-3,-2,-2,7,-2,-4,-4,-2,-3,-3,-2,0,-2,-3,-3,-3,-1,-2,-1}, {-2,0,0,-1,-2,0,-1,-2,10,-3,-3,0,-2,-2,-2,-1,-1,-2,1,-3,0,0,-1}, {-1,-2,-3,-3,-2,-2,-3,-4,-3,5,2,-2,2,0,-3,-2,-1,-1,-1,3,-3,-2,-1}, {-1,-2,-3,-3,-3,-2,-3,-4,-3,2,5,-2,3,1,-3,-3,-2,0,-1,1,-3,-2,-1}, {-1,3,0,0,-3,1,1,-2,0,-2,-2,5,-1,-3,-1,0,0,-2,-2,-2,0,1,-1}, {0,-1,-2,-3,-2,0,-2,-3,-2,2,3,-1,6,1,-2,-1,-1,0,-1,1,-2,-1,0}, {-2,-3,-2,-3,-1,-2,-3,-3,-2,0,1,-3,1,7,-3,-2,-2,2,3,0,-3,-3,-1}, {-1,-1,-1,-1,-3,-1,0,-2,-2,-3,-3,-1,-2,-3,9,0,-1,-2,-2,-2,-1,-1,-1}, {1,-1,1,0,-2,0,0,0,-1,-2,-3,0,-1,-2,0,4,2,-2,-2,-1,0,0,0}, {0,-1,0,-1,-2,0,-1,-2,-1,-1,-2,0,-1,-2,-1,2,5,-1,-1,0,0,0,0}, {-2,-1,-2,-3,-3,-1,-2,-3,-2,-1,0,-2,0,2,-2,-2,-1,13,3,-2,-2,-2,-1}, {-2,-1,-1,-2,-2,-1,-2,-3,1,-1,-1,-2,-1,3,-2,-2,-1,3,9,-1,-2,-2,-1}, {0,-2,-2,-3,-2,-2,-2,-3,-3,3,1,-2,1,0,-2,-1,0,-2,-1,4,-3,-2,-1}, {-2,0,4,5,-3,1,1,-1,0,-3,-3,0,-2,-3,-1,0,0,-2,-2,-3,4,1,-1}, {-1,1,0,2,-3,3,4,-2,0,-2,-2,1,-1,-3,-1,0,0,-2,-2,-2,1,4,-1}, {0,-1,-1,-1,-2,0,-1,-1,-1,-1,-1,-1,0,-1,-1,0,0,-1,-1,-1,-1,-1,-1}, }; for(i = 0; i < 23;i++){ for(j = 0; j < 23;j++){ ap->subm[i][j] = (float)(CorBLOSUM66_13plus[i][j]);// *2.0F; } } ap->gpo = 5.5F; ap->gpe = 2.0F; ap->tgpe = 1.0F; return OK; } /* PFASUM43 matrix (H = 0.3354 bit) from Keul, Hess, Goesele, Hamacher (2017) * BMC Bioinformatics 18:293. Derived from Pfam seed alignments (v29.0) with * 43% clustering threshold. 1/3 bit units — same scale as CorBLOSUM66. */ int set_subm_gaps_PFASUM43(struct aln_param *ap) { /* A,R,N,D,C,Q,E,G,H,I,L,K,M,F,P,S,T,W,Y,V,B,Z,X */ int PFASUM43[23][23] = { /* A R N D C Q E G H I L K M F P S T W Y V B Z X */ { 4, -1, -1, -1, 0, 0, -1, 0, -2, -1, -1, -1, 0, -2, -1, 1, 0, -2, -2, 0, 0, 0, 0}, /* A */ { -1, 6, 0, 0, -3, 2, 1, -2, 1, -3, -3, 3, -2, -3, -1, 0, 0, -2, -2, -3, 0, 0, 0}, /* R */ { -1, 0, 6, 2, -2, 1, 1, 0, 1, -4, -4, 1, -2, -3, -1, 1, 0, -3, -2, -3, 0, 0, 0}, /* N */ { -1, 0, 2, 6, -4, 1, 3, 0, 0, -5, -5, 0, -4, -5, 0, 0, 0, -4, -3, -4, 0, 0, 0}, /* D */ { 0, -3, -2, -4, 13, -3, -4, -2, -2, -1, -1, -4, 0, -1, -3, 0, -1, -2, -1, 0, 0, 0, 0}, /* C */ { 0, 2, 1, 1, -3, 5, 2, -1, 1, -3, -3, 2, -1, -3, -1, 0, 0, -3, -2, -2, 0, 0, 0}, /* Q */ { -1, 1, 1, 3, -4, 2, 5, -1, 0, -4, -4, 2, -3, -4, -1, 0, 0, -4, -3, -3, 0, 0, 0}, /* E */ { 0, -2, 0, 0, -2, -1, -1, 7, -2, -4, -4, -1, -3, -4, -1, 0, -1, -3, -3, -3, 0, 0, 0}, /* G */ { -2, 1, 1, 0, -2, 1, 0, -2, 9, -3, -3, 0, -2, -1, -1, 0, -1, -1, 2, -3, 0, 0, 0}, /* H */ { -1, -3, -4, -5, -1, -3, -4, -4, -3, 5, 2, -3, 2, 1, -3, -3, -1, -1, -1, 3, 0, 0, 0}, /* I */ { -1, -3, -4, -5, -1, -3, -4, -4, -3, 2, 4, -3, 2, 2, -3, -3, -2, 0, 0, 2, 0, 0, 0}, /* L */ { -1, 3, 1, 0, -4, 2, 2, -1, 0, -3, -3, 5, -2, -4, -1, 0, 0, -3, -2, -3, 0, 0, 0}, /* K */ { 0, -2, -2, -4, 0, -1, -3, -3, -2, 2, 2, -2, 6, 1, -3, -2, -1, 0, 0, 1, 0, 0, 0}, /* M */ { -2, -3, -3, -5, -1, -3, -4, -4, -1, 1, 2, -4, 1, 7, -3, -3, -2, 3, 4, 0, 0, 0, 0}, /* F */ { -1, -1, -1, 0, -3, -1, -1, -1, -1, -3, -3, -1, -3, -3, 9, 0, -1, -3, -3, -2, 0, 0, 0}, /* P */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, -3, -3, 0, -2, -3, 0, 4, 2, -3, -2, -2, 0, 0, 0}, /* S */ { 0, 0, 0, 0, -1, 0, 0, -1, -1, -1, -2, 0, -1, -2, -1, 2, 4, -3, -2, 0, 0, 0, 0}, /* T */ { -2, -2, -3, -4, -2, -3, -4, -3, -1, -1, 0, -3, 0, 3, -3, -3, -3, 13, 3, -2, 0, 0, 0}, /* W */ { -2, -2, -2, -3, -1, -2, -3, -3, 2, -1, 0, -2, 0, 4, -3, -2, -2, 3, 8, -1, 0, 0, 0}, /* Y */ { 0, -3, -3, -4, 0, -2, -3, -3, -3, 3, 2, -3, 1, 0, -2, -2, 0, -2, -1, 4, 0, 0, 0}, /* V */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* B */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* Z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* X */ }; for(int i = 0; i < 23; i++){ for(int j = 0; j < 23; j++){ ap->subm[i][j] = (float)(PFASUM43[i][j]); } } /* PFASUM43 is in 1/3 bit units (same scale as CorBLOSUM66). Jointly tuned with seq_weights=2.0 and vsm_amax=2.0 on BAliBASE to balance SP, TC, and F1. */ ap->gpo = 7.0F; ap->gpe = 1.25F; ap->tgpe = 1.0F; return OK; } /* PFASUM60 matrix (H = 0.4941 bit) from Keul, Hess, Goesele, Hamacher (2017) * BMC Bioinformatics 18:293. Derived from Pfam seed alignments (v29.0) with * 60% clustering threshold. 1/3 bit units — same scale as CorBLOSUM66. * Recommended as general-purpose matrix by the authors. */ int set_subm_gaps_PFASUM60(struct aln_param *ap) { /* A,R,N,D,C,Q,E,G,H,I,L,K,M,F,P,S,T,W,Y,V,B,Z,X */ int PFASUM60[23][23] = { /* A R N D C Q E G H I L K M F P S T W Y V B Z X */ { 5, -1, -2, -2, 0, -1, -1, 0, -2, -1, -1, -1, -1, -2, -1, 1, 0, -3, -3, 0, 0, 0, 0}, /* A */ { -1, 7, 0, -1, -4, 2, 0, -2, 1, -4, -3, 3, -2, -4, -2, -1, -1, -3, -2, -3, 0, 0, 0}, /* R */ { -2, 0, 7, 2, -3, 1, 0, 0, 1, -5, -4, 1, -3, -4, -1, 1, 0, -4, -2, -4, 0, 0, 0}, /* N */ { -2, -1, 2, 7, -5, 1, 3, -1, 0, -6, -6, 0, -4, -6, -1, 0, -1, -5, -4, -5, 0, 0, 0}, /* D */ { 0, -4, -3, -5, 14, -4, -5, -2, -2, -1, -1, -4, -1, -1, -4, 0, -1, -2, -1, 0, 0, 0, 0}, /* C */ { -1, 2, 1, 1, -4, 6, 2, -2, 1, -4, -3, 2, -1, -4, -1, 0, 0, -3, -2, -3, 0, 0, 0}, /* Q */ { -1, 0, 0, 3, -5, 2, 6, -2, 0, -5, -4, 1, -3, -5, -1, 0, -1, -5, -3, -4, 0, 0, 0}, /* E */ { 0, -2, 0, -1, -2, -2, -2, 8, -2, -5, -5, -2, -4, -5, -2, 0, -2, -4, -4, -4, 0, 0, 0}, /* G */ { -2, 1, 1, 0, -2, 1, 0, -2, 10, -4, -3, 0, -2, -1, -2, -1, -1, -1, 2, -3, 0, 0, 0}, /* H */ { -1, -4, -5, -6, -1, -4, -5, -5, -4, 6, 3, -4, 2, 1, -4, -3, -1, -2, -2, 4, 0, 0, 0}, /* I */ { -1, -3, -4, -6, -1, -3, -4, -5, -3, 3, 5, -4, 3, 2, -4, -4, -2, -1, -1, 1, 0, 0, 0}, /* L */ { -1, 3, 1, 0, -4, 2, 1, -2, 0, -4, -4, 6, -2, -5, -1, 0, 0, -4, -3, -3, 0, 0, 0}, /* K */ { -1, -2, -3, -4, -1, -1, -3, -4, -2, 2, 3, -2, 8, 1, -4, -2, -1, -1, -1, 1, 0, 0, 0}, /* M */ { -2, -4, -4, -6, -1, -4, -5, -5, -1, 1, 2, -5, 1, 8, -4, -3, -3, 3, 4, 0, 0, 0, 0}, /* F */ { -1, -2, -1, -1, -4, -1, -1, -2, -2, -4, -4, -1, -4, -4, 10, 0, -1, -4, -4, -3, 0, 0, 0}, /* P */ { 1, -1, 1, 0, 0, 0, 0, 0, -1, -3, -4, 0, -2, -3, 0, 5, 2, -4, -3, -2, 0, 0, 0}, /* S */ { 0, -1, 0, -1, -1, 0, -1, -2, -1, -1, -2, 0, -1, -3, -1, 2, 6, -3, -2, 0, 0, 0, 0}, /* T */ { -3, -3, -4, -5, -2, -3, -5, -4, -1, -2, -1, -4, -1, 3, -4, -4, -3, 14, 3, -2, 0, 0, 0}, /* W */ { -3, -2, -2, -4, -1, -2, -3, -4, 2, -2, -1, -3, -1, 4, -4, -3, -2, 3, 9, -2, 0, 0, 0}, /* Y */ { 0, -3, -4, -5, 0, -3, -4, -4, -3, 4, 1, -3, 1, 0, -3, -2, 0, -2, -2, 5, 0, 0, 0}, /* V */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* B */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* Z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* X */ }; for(int i = 0; i < 23; i++){ for(int j = 0; j < 23; j++){ ap->subm[i][j] = (float)(PFASUM60[i][j]); } } /* PFASUM60 is in 1/3 bit units (same scale as CorBLOSUM66). Tuned with seq_weights=2.0 and vsm_amax=2.0 on BAliBASE. */ ap->gpo = 7.0F; ap->gpe = 1.25F; ap->tgpe = 1.0F; return OK; } int set_subm_gaps_DNA(struct aln_param *ap) { int i,j; for(i = 0; i < 5; i++){ for(j =0; j < 5;j++){ ap->subm[i][j] = -4; if(i == j){ ap->subm[i][j] = 5; } } } ap->gpo = 8; ap->gpe = 6; ap->tgpe = 0; return OK; } int set_subm_gaps_DNA_internal(struct aln_param *ap) { int i,j; for(i = 0; i < 5; i++){ for(j =0; j < 5;j++){ ap->subm[i][j] = -4; if(i == j){ ap->subm[i][j] = 5; } } } ap->gpo = 8; ap->gpe = 6; ap->tgpe = 8; return OK; } int set_subm_gaps_RNA(struct aln_param* ap) { int i,j; for(i = 0; i < 5; i++){ for(j =0; j < 5;j++){ ap->subm[i][j] = 283.0; } } // A 91 -114 -31 -123 0 -43 ap->subm[0][0] += 91.0; ap->subm[0][1] += -114.0; ap->subm[0][2] += -31.0; ap->subm[0][3] += -123.0; // C -114 100 -125 -31 0 -43 ap->subm[1][0] += -114.0; ap->subm[1][1] += 100.0; ap->subm[1][2] += -125.0; ap->subm[1][3] += -31.0; // G -31 -125 100 -114 0 -43 ap->subm[2][0] += -31.0; ap->subm[2][1] += -125.0; ap->subm[2][2] += 100.0; ap->subm[2][3] += -114.0; // T -123 -31 -114 91 0 -43 ap->subm[3][0] += -123.0; ap->subm[3][1] += -31.0; ap->subm[3][2] += -114.0; ap->subm[3][3] += 91.0; ap->gpo = 217.0; ap->gpe = 39.4; ap->tgpe = 292.6; return OK; } void aln_param_free(struct aln_param *ap) { if(ap){ if(ap->subm){ for (int i = 23;i--;){ MFREE(ap->subm[i]); } MFREE(ap->subm); } MFREE(ap); } } kalign-3.5.1/lib/src/aln_param.h000066400000000000000000000025721515023132300164260ustar00rootroot00000000000000#ifndef ALN_PARAM_H #define ALN_PARAM_H #ifdef ALN_PARAM_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif /* #define KALIGN_DNA 0 */ /* #define KALIGN_DNA_INTERNAL 1 */ /* #define KALIGN_RNA 2 */ /* #define KALIGN_PROTEIN 3 */ struct aln_param{ int nthreads; /* actual parameters */ float** subm; float gpo; float gpe; float tgpe; float score; float dist_scale; /* distance-dependent gap scaling: 0=off, >0 scales gap penalties down for divergent pairs */ float vsm_amax; /* variable scoring matrix: 0=off, >0 subtracts a(d)=max(0,amax-d) from subm scores */ float subm_offset; /* computed per alignment step: amount to subtract from substitution scores */ int adaptive_budget; /* 0=off, 1=scale trial count by uncertainty */ float use_seq_weights; /* 0=off, >0=pseudocount for profile rebalancing */ int consistency_anchors; /* 0=off, >0=number of anchor sequences K for consistency */ float consistency_weight; /* bonus scale for consistency (default: 2.0) */ }; EXTERN int aln_param_init(struct aln_param **aln_param,int biotype , int n_threads, int type, float gpo, float gpe, float tgpe); EXTERN void aln_param_free(struct aln_param* ap); #undef ALN_PARAM_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_profileprofile.c000066400000000000000000000366711515023132300203510ustar00rootroot00000000000000#include #include #include "tldevel.h" #include "aln_param.h" #include "aln_struct.h" #define ALN_PROFILEPROFILE_IMPORT #include "aln_profileprofile.h" #define MAX(a, b) (a > b ? a : b) #define MAX3(a,b,c) MAX(MAX(a,b),c) int aln_profileprofile_foward(struct aln_mem* m) { unsigned int freq[24]; const float* restrict prof1 = m->prof1; const float* restrict prof2 = m->prof2; struct states* restrict s = m->f; register float pa = 0; register float pga = 0; register float pgb = 0; register float ca = 0; register float xa = 0; register float xga = 0; register int i = 0; register int j = 0; register int c = 0; register int f = 0; prof1 += (m->starta) << 6; prof2 += (m->startb) << 6; s[m->startb].a = s[0].a; s[m->startb].ga = s[0].ga; s[m->startb].gb = s[0].gb; if(m->startb){ for (j = m->startb+1; j < m->endb;j++){ prof2+=64; s[j].a = -FLT_MAX; s[j].ga = MAX(s[j-1].ga+prof2[28],s[j-1].a+prof2[27]); s[j].gb = -FLT_MAX; } prof2+=64; }else{ for (j = m->startb+1; j < m->endb;j++){ prof2+=64; s[j].a = -FLT_MAX; s[j].ga = MAX(s[j-1].ga,s[j-1].a)+prof2[29]; s[j].gb = -FLT_MAX; } prof2+=64; } prof2 -= (m->endb-m->startb) << 6; s[m->endb].a = -FLT_MAX; s[m->endb].ga = -FLT_MAX; s[m->endb].gb = -FLT_MAX; for (i = m->starta;i < m->enda;i++){ prof1 += 64; //c = 1; f = 0; for (j = 0;j < 23; j++){ if(prof1[j]){ freq[f] = j; f++; } } f--; //freq[0] = c; pa = s[m->startb].a; pga = s[m->startb].ga; pgb = s[m->startb].gb; s[m->startb].a = -FLT_MAX; s[m->startb].ga = -FLT_MAX; xa = s[m->startb].a; xga = s[m->startb].ga; if(m->startb){ s[m->startb].gb = MAX(pgb+prof1[28],pa+prof1[27]); }else{ s[m->startb].gb = MAX(pgb,pa)+ prof1[29]; } for (j = m->startb+1; j < m->endb;j++){ prof2 += 64; ca = s[j].a; pa = MAX3(pa,pga + prof2[-37],pgb + prof1[-37]); prof2 += 32; for (c = f;c >= 0;c--){ //for (c = 0;c < f;c++){ //for (c = 1;c < freq[0];c++){ pa += prof1[freq[c]]*prof2[freq[c]]; } prof2 -= 32; if(m->consistency){ pa += m->consistency[i * m->consistency_stride + j]; } s[j].a = pa; pga = s[j].ga; //s[j].ga = MAX(s[j-1].ga+prof2[28],s[j-1].a+prof2[27]); s[j].ga = MAX(xga+prof2[28],xa+prof2[27]); pgb = s[j].gb; s[j].gb = MAX(pgb+prof1[28] ,ca+prof1[27]); pa = ca; xa = s[j].a; xga = s[j].ga; } prof2 += 64; ca = s[j].a; pa = MAX3(pa,pga + prof2[-37],pgb + prof1[-37]); prof2 += 32; for (c = f;c >= 0;c--){ pa += prof1[freq[c]]*prof2[freq[c]]; } prof2 -= 32; if(m->consistency){ pa += m->consistency[i * m->consistency_stride + j]; } s[j].a = pa; s[j].ga = -FLT_MAX; if (m->endb != m->len_b){ s[j].gb = MAX(s[j].gb+prof1[28] ,ca+prof1[27]); }else{ s[j].gb = MAX(s[j].gb,ca)+ prof1[29]; } prof2 -= (m->endb-m->startb) << 6; } //prof1 -= (m->enda) << 6; return OK; } int aln_profileprofile_backward(struct aln_mem* m) { unsigned int freq[24]; struct states* restrict s = m->b; const float* restrict prof1 = m->prof1; const float* restrict prof2 = m->prof2; register float pa = 0; register float pga = 0; register float pgb = 0; register float ca = 0; register float xa = 0; register float xga = 0; register int i = 0; register int j = 0; register int c = 0; register int f = 0; prof1 += (m->enda_2 +1) << 6; prof2 += (m->endb+1) << 6; s[m->endb].a = s[0].a; s[m->endb].ga = s[0].ga; s[m->endb].gb = s[0].gb; if(m->endb != m->len_b){ for(j = m->endb-1;j > m->startb;j--){ prof2 -= 64; s[j].a = -FLT_MAX; s[j].ga = MAX(s[j+1].ga+prof2[28],s[j+1].a+prof2[27]); s[j].gb = -FLT_MAX; } prof2 -= 64; }else{ for(j = m->endb-1;j > m->startb;j--){ prof2 -= 64; s[j].a = -FLT_MAX; s[j].ga = MAX(s[j+1].ga,s[j+1].a)+prof2[29]; s[j].gb = -FLT_MAX; } prof2 -= 64; } s[m->startb].a = -FLT_MAX; s[m->startb].ga = -FLT_MAX; s[m->startb].gb = -FLT_MAX; i = m->enda_2-m->starta_2; while(i--){ prof1 -= 64; f = 0; for (j = 0;j < 23; j++){ if(prof1[j]){ freq[f] = j; f++; } } f--; //freq[0] = c; pa = s[m->endb].a; pga = s[m->endb].ga; pgb = s[m->endb].gb; s[m->endb].a = -FLT_MAX; s[m->endb].ga = -FLT_MAX; xa = s[m->endb].a; xga = s[m->endb].ga; if(m->endb != m->len_b){ s[m->endb].gb = MAX(pgb+prof1[28] ,pa+prof1[27]); }else{ s[m->endb].gb = MAX(pgb,pa)+prof1[29]; } prof2 += (m->endb-m->startb) << 6; for(j = m->endb-1;j > m->startb;j--){ prof2 -= 64; ca = s[j].a; pa = MAX3(pa,pga + prof2[91],pgb + prof1[91]); prof2 += 32; for (c = f;c >= 0;c--){ //for (c = 0;c < f;c++){ //for (c = 1;c < freq[0];c++){ pa += prof1[freq[c]]*prof2[freq[c]]; } prof2 -= 32; if(m->consistency){ pa += m->consistency[(m->starta_2 + i) * m->consistency_stride + j]; } s[j].a = pa; pga = s[j].ga; //s[j].ga = MAX(s[j+1].ga+prof2[28], s[j+1].a+prof2[27]); s[j].ga = MAX(xga+prof2[28], xa+prof2[27]); pgb = s[j].gb; s[j].gb = MAX(pgb+prof1[28], ca+prof1[27]); pa = ca; xa = s[j].a; xga = s[j].ga; } prof2 -= 64; ca = s[j].a; pa = MAX3(pa,pga + prof2[91],pgb + prof1[91]); prof2 += 32; for (c = f;c >= 0;c--){ //for (c = 0;c < f;c++){ pa += prof1[freq[c]]*prof2[freq[c]]; } prof2 -= 32; if(m->consistency){ pa += m->consistency[(m->starta_2 + i) * m->consistency_stride + j]; } s[j].a = pa; //pga = s[j].ga; s[j].ga = -FLT_MAX;//MAX(s[j+1].ga+prof2[28], s[j+1].a+prof2[27]); //pgb = s[j].gb; if(m->startb){ s[j].gb = MAX(s[j].gb+prof1[28], ca+prof1[27]); }else{ s[j].gb = MAX(s[j].gb,ca)+prof1[29]; } //pa = ca; } return OK; } int aln_profileprofile_meetup(struct aln_mem* m,int old_cor[], int* meet,int* t,float* score) { struct states* f = m->f; struct states* b = m->b; int i; int c; int c2 = -1; int transition = -1; int transition2 = -1; float s_tmp; const float* prof1 = m->prof1; const float* prof2 = m->prof2; //code: // a -> a = 1 // a -> ga = 2 // a -> gb = 3 // ga ->ga = 4 // ga -> a = 5 //gb->gb = 6; //gb->a = 7; //int max = -FLT_MAX; float max = -FLT_MAX; float max2 = -FLT_MAX; //float middle = (m->endb - m->startb)/2 + m->startb; float middle = (float) (old_cor[3] - old_cor[2])/2.0F + (float) old_cor[2]; float sub = 0.0F; prof1+= ((old_cor[4]+1) << 6); //prof2 += 64 * (m->startb); //i = m->startb; prof2 += old_cor[2] << 6; c = -1; //for(i = m->startb; i < m->endb;i++){ for(i = old_cor[2]; i < old_cor[3];i++){ sub = fabsf(middle - (float)i); sub /= 1000.0F; prof2 += 64; s_tmp = f[i].a+b[i].a-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 1; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 1; } s_tmp = f[i].a+b[i].ga+prof2[27]-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 2; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 2; } s_tmp = f[i].a+b[i].gb+prof1[27]-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 3; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 3; } s_tmp = f[i].ga+b[i].a+prof2[-37]-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 5; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 5; } if(m->startb == 0){ s_tmp = f[i].gb+b[i].gb+prof1[29]-sub; }else{ s_tmp = f[i].gb+b[i].gb+prof1[28]-sub; } if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 6; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 6; } s_tmp = f[i].gb+b[i].a+prof1[-37]-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 7; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 7; } } //i = m->endb; i = old_cor[3]; sub = fabsf(middle - (float)i); sub /= 1000.0F; s_tmp = f[i].a+b[i].gb+prof1[27]-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 3; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 3; } if(m->endb == m->len_b){ s_tmp = f[i].gb+b[i].gb+prof1[29]-sub; }else{ s_tmp = f[i].gb+b[i].gb+prof1[28]-sub; } if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 6; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 6; } /* Accumulate confidence margin and record per-meetup margins */ if(max2 > -FLT_MAX){ float _margin = max - max2; if(m->flip_margins != NULL && m->margin_count < m->flip_margin_alloc){ m->flip_margins[m->margin_count] = _margin; } m->margin_sum += _margin; m->margin_count++; } /* Perturbation: flip uncertain midpoints to second-best choice. Three modes: individual targeting (MCTS), stride bitmask, or round-robin. */ if(m->flip_threshold > 0.0F && c2 >= 0 && max2 > -FLT_MAX){ float margin = max - max2; if(margin < m->flip_threshold){ if(m->flip_bit_map != NULL){ /* Individual midpoint targeting (MCTS) */ if(m->flip_counter < m->flip_n_uncertain){ int bit = m->flip_bit_map[m->flip_counter]; if(bit >= 0 && ((1U << bit) & m->flip_mask)){ c = c2; transition = transition2; } } }else if(m->flip_mask != 0){ /* Stride-based bitmask mode */ if((1U << (m->flip_counter % m->flip_stride)) & m->flip_mask){ c = c2; transition = transition2; } }else if(m->flip_trial > 0){ /* Round-robin mode */ if(m->flip_counter % m->flip_stride == m->flip_trial - 1){ c = c2; transition = transition2; } } m->flip_counter++; } } *meet = c; *t = transition; *score = max; return OK; } kalign-3.5.1/lib/src/aln_profileprofile.h000066400000000000000000000007531515023132300203460ustar00rootroot00000000000000#ifndef ALN_PROFILEPROFILE_H #define ALN_PROFILEPROFILE_H #ifdef ALN_PROFILEPROFILE_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct aln_mem; EXTERN int aln_profileprofile_foward(struct aln_mem* m); EXTERN int aln_profileprofile_backward(struct aln_mem* m); EXTERN int aln_profileprofile_meetup(struct aln_mem* m,int old_cor[], int* meet,int* t,float* score); #undef ALN_PROFILEPROFILE_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_refine.c000066400000000000000000000641521515023132300165730ustar00rootroot00000000000000#include "tldevel.h" #include #include "msa_struct.h" #include "task.h" #include "aln_param.h" #include "aln_struct.h" #include "aln_mem.h" #include "aln_setup.h" #include "aln_controller.h" #include "weave_alignment.h" #include "sp_score.h" #include "aln_run.h" #include "anchor_consistency.h" #define ALN_REFINE_IMPORT #include "aln_refine.h" #define REFINE_N_TRIALS 5 static int refine_edge(struct msa* msa, struct aln_param* ap, struct aln_tasks* t, int task_id); static int replay_edge(struct msa* msa, struct aln_param* ap, struct aln_tasks* t, int task_id); static int dispatch_alignment(struct msa* msa, struct aln_mem* ml, float* prof_a, float* prof_b, int a, int b, int len_a, int len_b); static int convert_raw_path(struct aln_mem* m); static int compute_confidence_threshold(struct aln_tasks* t, float* threshold); /* Leaf weight for make_profile_n — always 1.0 since sequence weighting is handled via balanced freq-count merging in update_n. */ static float leaf_weight(struct msa* msa, int node) { (void)msa; (void)node; return 1.0f; } int refine_alignment(struct msa* msa, struct aln_param* ap, struct aln_tasks* t, int refine_mode) { int i; float threshold = 0.0F; if(refine_mode == KALIGN_REFINE_NONE){ return OK; } RUN(sort_tasks(t, TASK_ORDER_TREE)); if(refine_mode == KALIGN_REFINE_CONFIDENT){ RUN(compute_confidence_threshold(t, &threshold)); } /* Reset alignment state: zero all gaps and restore leaf sip/nsip */ RUN(clean_aln(msa)); /* Clear stale profiles from the initial alignment */ for(i = 0; i < msa->num_profiles; i++){ if(t->profile[i]){ MFREE(t->profile[i]); t->profile[i] = NULL; } } /* Process all edges bottom-up using progressive profile building. Each edge builds profiles from its children (identical to original progressive alignment), then refined edges run multi-trial DP. */ for(i = 0; i < t->n_tasks; i++){ int should_refine = 0; if(refine_mode == KALIGN_REFINE_ALL){ should_refine = 1; }else if(refine_mode == KALIGN_REFINE_CONFIDENT){ should_refine = (t->list[i]->confidence <= threshold); } if(should_refine){ RUN(refine_edge(msa, ap, t, i)); }else{ RUN(replay_edge(msa, ap, t, i)); } } return OK; ERROR: return FAIL; } /* Process an edge with multi-trial DP: builds progressive profiles (identical to do_align), runs K alignment trials (one deterministic baseline plus threshold-based alternatives), keeps the best by SP score. */ int refine_edge(struct msa* msa, struct aln_param* ap, struct aln_tasks* t, int task_id) { struct aln_mem* ml = NULL; float* tmp = NULL; int* best_path = NULL; int a, b, c; int len_a, len_b; int k, j, g; float best_sp = -FLT_MAX; float best_margin_sum = 0.0F; int best_margin_count = 0; float avg_margin = 0.0F; int n_trials = REFINE_N_TRIALS; a = t->list[task_id]->a; b = t->list[task_id]->b; c = t->list[task_id]->c; /* Distance-dependent parameter scaling (must match do_align) */ struct aln_param* orig_ap = ap; struct aln_param scaled_ap; float gap_scale = compute_gap_scale(msa, ap, a, b); float subm_off = compute_subm_offset(msa, ap, a, b); if(gap_scale < 1.0f || subm_off > 0.0f){ scaled_ap = *ap; scaled_ap.gpo *= gap_scale; scaled_ap.gpe *= gap_scale; scaled_ap.tgpe *= gap_scale; scaled_ap.subm_offset = subm_off; ap = &scaled_ap; } /* Build profiles progressively (same as do_align) */ if(msa->nsip[a] == 1){ len_a = msa->sequences[a]->len; RUN(make_profile_n(ap, msa->sequences[a]->s, len_a, leaf_weight(msa,a), &t->profile[a])); }else{ len_a = msa->plen[a]; RUN(set_gap_penalties_n(t->profile[a], len_a, msa->nsip[b])); } if(msa->nsip[b] == 1){ len_b = msa->sequences[b]->len; RUN(make_profile_n(ap, msa->sequences[b]->s, len_b, leaf_weight(msa,b), &t->profile[b])); }else{ len_b = msa->plen[b]; RUN(set_gap_penalties_n(t->profile[b], len_b, msa->nsip[a])); } /* Allocate alignment memory */ RUN(alloc_aln_mem(&ml, 256)); ml->ap = ap; ml->mode = ALN_MODE_FULL; ml->len_a = len_a; ml->len_b = len_b; ml->margin_sum = 0.0F; ml->margin_count = 0; RUN(init_alnmem(ml)); /* Allocate best_path buffer */ MMALLOC(best_path, sizeof(int) * ml->alloc_path_len); /* Compute consistency bonus for all merge types */ ml->consistency = NULL; ml->consistency_stride = 0; { struct consistency_table* ct = (struct consistency_table*)msa->consistency_table; if(ct != NULL){ int dp_row_node, dp_col_node, dp_rows, dp_cols; if(msa->nsip[a] == 1 && msa->nsip[b] == 1){ if(len_a < len_b){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; } }else if(msa->nsip[a] == 1){ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; }else if(msa->nsip[b] == 1){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ if(len_a < len_b){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; } } RUN(anchor_consistency_get_bonus_profile(ct, msa, dp_row_node, dp_rows, dp_col_node, dp_cols, &ml->consistency)); ml->consistency_stride = dp_cols; } } /* If adaptive budget, allocate flip_margins for baseline trial to record per-meetup margins for uncertainty analysis */ if(ap->adaptive_budget){ int est = MACRO_MIN(len_a, len_b) + 1; if(est < 64) est = 64; MMALLOC(ml->flip_margins, sizeof(float) * est); ml->flip_margin_alloc = est; } /* Multi-trial alignment: trial 0 is deterministic (baseline), trials 1..n_trials-1 use increasing flip thresholds. */ for(k = 0; k < n_trials; k++){ float sp = 0.0F; /* Re-initialize DP state before each trial. The Hirschberg recursion only writes matched positions to the path array; unmatched positions must be -1. After convert_raw_path swaps path/tmp_path, the buffer contains stale 0/1/2 values. */ { int _g = MACRO_MAX(len_a, len_b) + 2; int _i; for(_i = 0; _i < _g; _i++){ ml->path[_i] = -1; } } ml->starta = 0; ml->startb = 0; ml->enda = len_a; ml->endb = len_b; ml->len_a = len_a; ml->len_b = len_b; ml->f[0].a = 0.0F; ml->f[0].ga = -FLT_MAX; ml->f[0].gb = -FLT_MAX; ml->b[0].a = 0.0F; ml->b[0].ga = -FLT_MAX; ml->b[0].gb = -FLT_MAX; ml->margin_sum = 0.0F; ml->margin_count = 0; if(k == 0){ ml->flip_threshold = 0.0F; ml->flip_trial = 0; }else{ ml->flip_threshold = avg_margin; ml->flip_trial = k; ml->flip_stride = n_trials - 1; ml->flip_counter = 0; } RUN(dispatch_alignment(msa, ml, t->profile[a], t->profile[b], a, b, len_a, len_b)); /* Convert raw DP path to 0/1/2 format with gap info */ RUN(convert_raw_path(ml)); /* Score this candidate with sum-of-pairs */ RUN(compute_sp_score(msa, ap, ml->path, msa->sip[a], msa->nsip[a], msa->sip[b], msa->nsip[b], &sp)); if(sp > best_sp){ best_sp = sp; best_margin_sum = ml->margin_sum; best_margin_count = ml->margin_count; memcpy(best_path, ml->path, sizeof(int) * (ml->path[0] + 2)); } /* After baseline trial, compute avg_margin and adaptive budget */ if(k == 0){ if(ml->margin_count > 0){ avg_margin = ml->margin_sum / (float)ml->margin_count; } /* Adaptive budget: count very uncertain meetups */ if(ap->adaptive_budget && ml->flip_margins && ml->margin_count > 0){ int n_very_uncertain = 0; int m_i; float vu_threshold = avg_margin * 0.25F; for(m_i = 0; m_i < ml->margin_count; m_i++){ if(ml->flip_margins[m_i] < vu_threshold){ n_very_uncertain++; } } { float frac = (float)n_very_uncertain / (float)ml->margin_count; n_trials = 1 + (int)(7.0F * frac + 0.5F); } } /* Free flip_margins after extracting stats */ if(ml->flip_margins){ MFREE(ml->flip_margins); ml->flip_margins = NULL; } } } /* Restore best path into ml */ memcpy(ml->path, best_path, sizeof(int) * (best_path[0] + 2)); /* Free consistency bonus */ if(ml->consistency){ MFREE(ml->consistency); ml->consistency = NULL; ml->consistency_stride = 0; } /* Update confidence from best trial */ if(best_margin_count > 0){ t->list[task_id]->confidence = best_margin_sum / (float)best_margin_count; }else{ t->list[task_id]->confidence = 0.0F; } /* Restore original aln_param for profile update (unscaled base penalties) */ ap = orig_ap; /* Merge profiles for downstream edges */ MMALLOC(tmp, sizeof(float) * 64 * (ml->path[0] + 2)); if(task_id != t->n_tasks - 1){ update_n(t->profile[a], t->profile[b], tmp, ap, ml->path, msa->nsip[a], msa->nsip[b]); } t->profile[c] = tmp; /* Update gap arrays for all member sequences */ RUN(make_seq(msa, a, b, ml->path)); msa->plen[c] = ml->path[0]; msa->nsip[c] = msa->nsip[a] + msa->nsip[b]; MREALLOC(msa->sip[c], sizeof(int) * (msa->nsip[a] + msa->nsip[b])); g = 0; for(j = msa->nsip[a]; j--;){ msa->sip[c][g] = msa->sip[a][j]; g++; } for(j = msa->nsip[b]; j--;){ msa->sip[c][g] = msa->sip[b][j]; g++; } /* Free child profiles */ MFREE(t->profile[a]); t->profile[a] = NULL; MFREE(t->profile[b]); t->profile[b] = NULL; /* Cleanup */ MFREE(best_path); free_aln_mem(ml); return OK; ERROR: if(best_path){ MFREE(best_path); } free_aln_mem(ml); return FAIL; } /* Process an edge using standard progressive profiles (identical to the original do_align in aln_run.c). Used for high-confidence edges in REFINE_CONFIDENT mode and as the default replay path. */ int replay_edge(struct msa* msa, struct aln_param* ap, struct aln_tasks* t, int task_id) { struct aln_mem* ml = NULL; float* tmp = NULL; int a, b, c; int len_a, len_b; int j, g; a = t->list[task_id]->a; b = t->list[task_id]->b; c = t->list[task_id]->c; /* Distance-dependent parameter scaling (must match do_align) */ struct aln_param* orig_ap = ap; struct aln_param scaled_ap; float gap_scale = compute_gap_scale(msa, ap, a, b); float subm_off = compute_subm_offset(msa, ap, a, b); if(gap_scale < 1.0f || subm_off > 0.0f){ scaled_ap = *ap; scaled_ap.gpo *= gap_scale; scaled_ap.gpe *= gap_scale; scaled_ap.tgpe *= gap_scale; scaled_ap.subm_offset = subm_off; ap = &scaled_ap; } /* Build profiles (standard progressive approach) */ if(msa->nsip[a] == 1){ len_a = msa->sequences[a]->len; RUN(make_profile_n(ap, msa->sequences[a]->s, len_a, leaf_weight(msa,a), &t->profile[a])); }else{ len_a = msa->plen[a]; RUN(set_gap_penalties_n(t->profile[a], len_a, msa->nsip[b])); } if(msa->nsip[b] == 1){ len_b = msa->sequences[b]->len; RUN(make_profile_n(ap, msa->sequences[b]->s, len_b, leaf_weight(msa,b), &t->profile[b])); }else{ len_b = msa->plen[b]; RUN(set_gap_penalties_n(t->profile[b], len_b, msa->nsip[a])); } /* Allocate alignment memory and run alignment */ RUN(alloc_aln_mem(&ml, 256)); ml->ap = ap; ml->mode = ALN_MODE_FULL; ml->len_a = len_a; ml->len_b = len_b; ml->margin_sum = 0.0F; ml->margin_count = 0; RUN(init_alnmem(ml)); /* Compute consistency bonus for all merge types */ ml->consistency = NULL; ml->consistency_stride = 0; { struct consistency_table* ct = (struct consistency_table*)msa->consistency_table; if(ct != NULL){ int dp_row_node, dp_col_node, dp_rows, dp_cols; if(msa->nsip[a] == 1 && msa->nsip[b] == 1){ if(len_a < len_b){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; } }else if(msa->nsip[a] == 1){ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; }else if(msa->nsip[b] == 1){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ if(len_a < len_b){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; } } RUN(anchor_consistency_get_bonus_profile(ct, msa, dp_row_node, dp_rows, dp_col_node, dp_cols, &ml->consistency)); ml->consistency_stride = dp_cols; } } RUN(dispatch_alignment(msa, ml, t->profile[a], t->profile[b], a, b, len_a, len_b)); /* Free consistency bonus */ if(ml->consistency){ MFREE(ml->consistency); ml->consistency = NULL; ml->consistency_stride = 0; } /* Store alignment confidence */ if(ml->margin_count > 0){ t->list[task_id]->confidence = ml->margin_sum / (float)ml->margin_count; }else{ t->list[task_id]->confidence = 0.0F; } RUN(convert_raw_path(ml)); /* Restore original aln_param for profile update (unscaled base penalties) */ ap = orig_ap; /* Merge profiles for downstream edges */ MMALLOC(tmp, sizeof(float) * 64 * (ml->path[0] + 2)); if(task_id != t->n_tasks - 1){ update_n(t->profile[a], t->profile[b], tmp, ap, ml->path, msa->nsip[a], msa->nsip[b]); } t->profile[c] = tmp; /* Update gap arrays for all member sequences */ RUN(make_seq(msa, a, b, ml->path)); msa->plen[c] = ml->path[0]; msa->nsip[c] = msa->nsip[a] + msa->nsip[b]; MREALLOC(msa->sip[c], sizeof(int) * (msa->nsip[a] + msa->nsip[b])); g = 0; for(j = msa->nsip[a]; j--;){ msa->sip[c][g] = msa->sip[a][j]; g++; } for(j = msa->nsip[b]; j--;){ msa->sip[c][g] = msa->sip[b][j]; g++; } /* Free consumed profiles */ MFREE(t->profile[a]); t->profile[a] = NULL; MFREE(t->profile[b]); t->profile[b] = NULL; free_aln_mem(ml); return OK; ERROR: free_aln_mem(ml); return FAIL; } /* Dispatch alignment based on group types (seq-seq, seq-profile, profile-profile). Handles the shorter-first convention and path mirroring. */ int dispatch_alignment(struct msa* msa, struct aln_mem* ml, float* prof_a, float* prof_b, int a, int b, int len_a, int len_b) { if(msa->nsip[a] == 1){ if(msa->nsip[b] == 1){ /* seq vs seq */ if(len_a < len_b){ ml->seq1 = msa->sequences[a]->s; ml->seq2 = msa->sequences[b]->s; ml->prof1 = NULL; ml->prof2 = NULL; aln_runner(ml); }else{ ml->enda = len_b; ml->endb = len_a; ml->len_a = len_b; ml->len_b = len_a; ml->seq1 = msa->sequences[b]->s; ml->seq2 = msa->sequences[a]->s; ml->prof1 = NULL; ml->prof2 = NULL; aln_runner(ml); RUN(mirror_path_n(ml, len_a, len_b)); ml->len_a = len_a; ml->len_b = len_b; } }else{ /* seq a vs profile b: profile must be prof1 */ ml->enda = len_b; ml->endb = len_a; ml->len_a = len_b; ml->len_b = len_a; ml->seq1 = NULL; ml->seq2 = msa->sequences[a]->s; ml->prof1 = prof_b; ml->prof2 = NULL; ml->sip = msa->nsip[b]; aln_runner(ml); RUN(mirror_path_n(ml, len_a, len_b)); ml->len_a = len_a; ml->len_b = len_b; } }else{ if(msa->nsip[b] == 1){ /* profile a vs seq b */ ml->seq1 = NULL; ml->seq2 = msa->sequences[b]->s; ml->prof1 = prof_a; ml->prof2 = NULL; ml->sip = msa->nsip[a]; aln_runner(ml); }else{ /* profile vs profile */ if(len_a < len_b){ ml->seq1 = NULL; ml->seq2 = NULL; ml->prof1 = prof_a; ml->prof2 = prof_b; aln_runner(ml); }else{ ml->enda = len_b; ml->endb = len_a; ml->len_a = len_b; ml->len_b = len_a; ml->seq1 = NULL; ml->seq2 = NULL; ml->prof1 = prof_b; ml->prof2 = prof_a; aln_runner(ml); RUN(mirror_path_n(ml, len_a, len_b)); ml->len_a = len_a; ml->len_b = len_b; } } } return OK; ERROR: return FAIL; } /* Convert raw Hirschberg path (path[i] = B position or -1) to the 0/1/2 format with gap info bits that update_n and make_seq expect. This replaces add_gap_info_to_path_n for refinement trials. The original has a latent bug: it tracks the last B position via `b = path[i]`, which resets b to -1 on gap-in-B entries. When a later match skips B positions, the gap-in-A fill is skipped because `b == -1`. Stochastic Hirschberg sampling triggers this by producing interleaved gap patterns. This function tracks b_last correctly: only updated on actual matches (path[i] != -1). */ int convert_raw_path(struct aln_mem* m) { int* path = NULL; int* o_path = NULL; int* tmp_path = NULL; int i, j, a; int b_last; int len_a; int len_b; len_a = m->len_a; len_b = m->len_b; path = m->path; o_path = m->tmp_path; for(i = 0; i < len_a + len_b + 2; i++){ o_path[i] = 0; } j = 1; b_last = 0; /* last consumed B position (1-indexed), 0 = none */ for(i = 1; i <= len_a; i++){ if(path[i] == -1){ o_path[j] = 2; j++; }else{ /* Fill gap-in-A for B positions b_last+1..path[i]-1 */ for(a = b_last + 1; a < path[i]; a++){ o_path[j] = 1; j++; } o_path[j] = 0; j++; b_last = path[i]; } } /* Trailing gap-in-A for remaining B positions */ for(a = b_last + 1; a <= len_b; a++){ o_path[j] = 1; j++; } o_path[0] = j - 1; o_path[j] = 3; /* Add gap info bits */ i = 2; while(o_path[i] != 3){ if ((o_path[i-1] & 3) && !(o_path[i] & 3)){ if(o_path[i-1] & 8){ o_path[i-1] += 8; }else{ o_path[i-1] |= 16; } }else if (!(o_path[i-1] & 3) && (o_path[i] & 3)){ o_path[i] |= 4; }else if ((o_path[i-1] & 1) && (o_path[i] & 1)){ o_path[i] |= 8; }else if ((o_path[i-1] & 2) && (o_path[i] & 2)){ o_path[i] |= 8; } i++; } /* Add terminal gap flags */ i = 1; while(o_path[i] != 0){ o_path[i] |= 32; i++; } i = o_path[0]; while(o_path[i] != 0){ o_path[i] |= 32; i--; } tmp_path = m->path; m->path = m->tmp_path; m->tmp_path = tmp_path; return OK; } int compute_confidence_threshold(struct aln_tasks* t, float* threshold) { float* confidences = NULL; int n, i, j; float tmp; n = t->n_tasks; ASSERT(n > 0, "No tasks"); MMALLOC(confidences, sizeof(float) * n); for(i = 0; i < n; i++){ confidences[i] = t->list[i]->confidence; } /* Insertion sort for median */ for(i = 1; i < n; i++){ tmp = confidences[i]; j = i - 1; while(j >= 0 && confidences[j] > tmp){ confidences[j + 1] = confidences[j]; j--; } confidences[j + 1] = tmp; } if(n % 2 == 0){ *threshold = (confidences[n / 2 - 1] + confidences[n / 2]) / 2.0F; }else{ *threshold = confidences[n / 2]; } MFREE(confidences); return OK; ERROR: if(confidences){ MFREE(confidences); } return FAIL; } kalign-3.5.1/lib/src/aln_refine.h000066400000000000000000000007671515023132300166020ustar00rootroot00000000000000#ifndef ALN_REFINE_H #define ALN_REFINE_H #ifdef ALN_REFINE_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif #define KALIGN_REFINE_NONE 0 #define KALIGN_REFINE_ALL 1 #define KALIGN_REFINE_CONFIDENT 2 #define KALIGN_REFINE_INLINE 3 struct msa; struct aln_param; struct aln_tasks; EXTERN int refine_alignment(struct msa* msa, struct aln_param* ap, struct aln_tasks* t, int refine_mode); #undef ALN_REFINE_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_run.c000066400000000000000000000703501515023132300161240ustar00rootroot00000000000000#include "tldevel.h" #include "tlrng.h" #include "msa_struct.h" #ifdef HAVE_OPENMP #include #endif #include "task.h" #include "aln_param.h" #include "aln_struct.h" #include "aln_mem.h" #include "aln_setup.h" #include "aln_controller.h" #include "weave_alignment.h" /* #include "weave_alignment.h" */ #include "sp_score.h" #include "anchor_consistency.h" #include #include #define ALN_RUN_IMPORT #include "aln_run.h" static void recursive_aln(struct msa* msa, struct aln_tasks*t, struct aln_param* ap, uint8_t* active, int c); /* static void recursive_aln_openMP(struct msa* msa, struct aln_tasks*t, struct aln_param* ap, uint8_t* active, int c); */ /* static void recursive_aln_serial(struct msa* msa, struct aln_tasks*t, struct aln_param* ap, uint8_t* active, int c); */ static int do_align(struct msa* msa,struct aln_tasks* t,struct aln_mem* m, int task_id); static int do_align_inline_refine(struct msa* msa, struct aln_tasks* t, struct aln_mem* m, int task_id, int n_trials); static void recursive_aln_inline(struct msa* msa, struct aln_tasks*t, struct aln_param* ap, uint8_t* active, int c, int n_trials); /* static int do_align_serial(struct msa* msa,struct aln_tasks* t,struct aln_mem* m, int task_id); */ /* static int do_score(struct msa* msa,struct aln_tasks* t,struct aln_mem* m, int task_id); */ /* static int SampleWithoutReplacement(struct rng_state* rng, int N, int n,int* samples); */ /* static int int_cmp(const void *a, const void *b); */ int create_msa_tree(struct msa* msa, struct aln_param* ap,struct aln_tasks* t) { int i; uint8_t* active = NULL; RUN(sort_tasks(t, TASK_ORDER_TREE)); MMALLOC(active, sizeof(uint8_t)* msa->num_profiles); for(i = 0; i < msa->numseq;i++){ active[i] = 1; } for(i = msa->numseq; i < msa->num_profiles;i++){ active[i] = 0; } /* LOG_MSG("Setting threads to 1 for debugging!"); */ /* ap->nthreads = 1; */ msa->run_parallel = 1; if(ap->nthreads == 1){ msa->run_parallel = 0; } #ifdef HAVE_OPENMP #pragma omp parallel #pragma omp single nowait #endif recursive_aln(msa, t, ap, active, t->n_tasks-1); MFREE(active); return OK; ERROR: if(active){ MFREE(active); } return FAIL; } void recursive_aln(struct msa* msa, struct aln_tasks*t, struct aln_param* ap, uint8_t* active, int c) { struct task* local_t = NULL; /* Follow left and right branch until I arrive at sequences / profiles ready to align. */ int a; int b; local_t = t->list[c]; a = local_t->a - msa->numseq; b = local_t->b - msa->numseq; if(!active[local_t->a] && local_t->a >= msa->numseq){ #ifdef HAVE_OPENMP #pragma omp task shared(msa,t,ap,active) firstprivate(a) #endif recursive_aln(msa, t, ap, active, a); } if(!active[local_t->b] && local_t->b >= msa->numseq){ #ifdef HAVE_OPENMP #pragma omp task shared(msa,t,ap,active) firstprivate(b) #endif recursive_aln(msa, t, ap, active, b); } #ifdef HAVE_OPENMP #pragma omp taskwait #endif struct aln_mem* ml = NULL; alloc_aln_mem(&ml, 256); ml->ap = ap; ml->mode = ALN_MODE_FULL; do_align(msa,t,ml,c); active[local_t->a] = 0; active[local_t->b] = 0; active[local_t->c] = 1; /* LOG_MSG("Local: %d %d %d p:%d", local_t->a, local_t->b, local_t->c, local_t->p); */ free_aln_mem(ml); } float compute_gap_scale(struct msa* msa, struct aln_param* ap, int a, int b) { float ds = ap->dist_scale; if(ds <= 0.0f || msa->seq_distances == NULL){ return 1.0f; } /* Compute mean normalized distance for all sequences in both clusters */ float sum = 0.0f; int count = 0; int i; for(i = 0; i < msa->nsip[a]; i++){ int si = msa->sip[a][i]; if(si < msa->numseq){ sum += msa->seq_distances[si]; count++; } } for(i = 0; i < msa->nsip[b]; i++){ int si = msa->sip[b][i]; if(si < msa->numseq){ sum += msa->seq_distances[si]; count++; } } if(count == 0){ return 1.0f; } float avg_div = sum / (float)count; /* Scale: 1.0 for similar sequences, decreasing for divergent. scale = max(0.3, 1.0 - dist_scale * avg_div) With dist_scale=0.5 and avg_div=1.0 (fully divergent): scale=0.5 With dist_scale=0.5 and avg_div=0.0 (identical): scale=1.0 */ float scale = 1.0f - ds * avg_div; if(scale < 0.3f) scale = 0.3f; if(scale > 1.0f) scale = 1.0f; return scale; } float compute_subm_offset(struct msa* msa, struct aln_param* ap, int a, int b) { float amax = ap->vsm_amax; if(amax <= 0.0f || msa->seq_distances == NULL){ return 0.0f; } /* Compute mean normalized distance for all sequences in both clusters */ float sum = 0.0f; int count = 0; int i; for(i = 0; i < msa->nsip[a]; i++){ int si = msa->sip[a][i]; if(si < msa->numseq){ sum += msa->seq_distances[si]; count++; } } for(i = 0; i < msa->nsip[b]; i++){ int si = msa->sip[b][i]; if(si < msa->numseq){ sum += msa->seq_distances[si]; count++; } } if(count == 0){ return 0.0f; } float avg_div = sum / (float)count; /* MAFFT VSM: a(d) = max(0, amax - d) Close sequences (small d) -> large offset -> more stringent scoring Distant sequences (large d) -> small/zero offset -> original scoring */ float offset = amax - avg_div; if(offset < 0.0f) offset = 0.0f; return offset; } /* Leaf weight for make_profile_n — always 1.0 since sequence weighting is handled via balanced freq-count merging in update_n. */ static float leaf_weight(struct msa* msa, int node) { (void)msa; (void)node; return 1.0f; } int do_align(struct msa* msa,struct aln_tasks* t,struct aln_mem* m, int task_id) { float* tmp = NULL; int a,b,c; int len_a; int len_b; int j,g; a = t->list[task_id]->a; b = t->list[task_id]->b; c = t->list[task_id]->c; /* Distance-dependent parameter scaling */ struct aln_param* orig_ap = m->ap; struct aln_param scaled_ap; float gap_scale = compute_gap_scale(msa, m->ap, a, b); float subm_off = compute_subm_offset(msa, m->ap, a, b); if(gap_scale < 1.0f || subm_off > 0.0f){ scaled_ap = *m->ap; /* shallow copy — shares subm pointer */ scaled_ap.gpo *= gap_scale; scaled_ap.gpe *= gap_scale; scaled_ap.tgpe *= gap_scale; scaled_ap.subm_offset = subm_off; m->ap = &scaled_ap; } if(msa->nsip[a] == 1){ m->len_a = msa->sequences[a]->len;// aln->sl[a]; RUN(make_profile_n(m->ap, msa->sequences[a]->s,m->len_a,leaf_weight(msa,a),&t->profile[a])); }else{ m->len_a = msa->plen[a]; RUN(set_gap_penalties_n(t->profile[a],m->len_a,msa->nsip[b])); } if(msa->nsip[b] == 1){ m->len_b = msa->sequences[b]->len;// aln->sl[b]; RUN(make_profile_n(m->ap, msa->sequences[b]->s,m->len_b,leaf_weight(msa,b),&t->profile[b])); }else{ m->len_b = msa->plen[b]; RUN(set_gap_penalties_n(t->profile[b],m->len_b,msa->nsip[a])); } RUN(init_alnmem(m)); m->margin_sum = 0.0F; m->margin_count = 0; m->consistency = NULL; m->consistency_stride = 0; /* Compute consistency bonus for all merge types */ { struct consistency_table* ct = (struct consistency_table*)msa->consistency_table; if(ct != NULL){ int dp_row_node, dp_col_node, dp_rows, dp_cols; if(msa->nsip[a] == 1 && msa->nsip[b] == 1){ if(m->len_a < m->len_b){ dp_row_node = a; dp_rows = m->len_a; dp_col_node = b; dp_cols = m->len_b; }else{ dp_row_node = b; dp_rows = m->len_b; dp_col_node = a; dp_cols = m->len_a; } }else if(msa->nsip[a] == 1){ dp_row_node = b; dp_rows = m->len_b; dp_col_node = a; dp_cols = m->len_a; }else if(msa->nsip[b] == 1){ dp_row_node = a; dp_rows = m->len_a; dp_col_node = b; dp_cols = m->len_b; }else{ if(m->len_a < m->len_b){ dp_row_node = a; dp_rows = m->len_a; dp_col_node = b; dp_cols = m->len_b; }else{ dp_row_node = b; dp_rows = m->len_b; dp_col_node = a; dp_cols = m->len_a; } } RUN(anchor_consistency_get_bonus_profile(ct, msa, dp_row_node, dp_rows, dp_col_node, dp_cols, &m->consistency)); m->consistency_stride = dp_cols; } } m->mode = ALN_MODE_FULL; if(msa->nsip[a] == 1){ if(msa->nsip[b] == 1){ if(m->len_a < m->len_b){ m->seq1 = msa->sequences[a]->s; m->seq2 = msa->sequences[b]->s; /* LOG_MSG("%d %d", m->len_a, m->len_b); */ m->prof1 = NULL; m->prof2 = NULL; aln_runner(m); }else{ len_b = m->len_b; len_a = m->len_a; m->enda = len_b; m->endb = len_a; m->len_a = len_b; m->len_b = len_a; m->seq1 = msa->sequences[b]->s; m->seq2 = msa->sequences[a]->s; m->prof1 = NULL; m->prof2 = NULL; aln_runner(m); RUN(mirror_path_n(m,len_a,len_b)); m->len_a = len_a; m->len_b = len_b; } /* m->seq1 = msa->sequences[a]->s; */ /* m->seq2 = msa->sequences[b]->s; */ /* m->prof1 = NULL; */ /* m->prof2 = NULL; */ /* aln_runner(m); */ }else{ len_b = m->len_b; len_a = m->len_a; m->enda = len_b; m->endb = len_a; m->len_a = len_b; m->len_b = len_a; m->seq1 = NULL; m->seq2 = msa->sequences[a]->s; m->prof1 = t->profile[b]; m->prof2 = NULL; m->sip = msa->nsip[b]; aln_runner(m); RUN(mirror_path_n(m, len_a,len_b)); m->len_a = len_a; m->len_b = len_b; } }else{ if(msa->nsip[b] == 1){ m->seq1 = NULL; m->seq2 = msa->sequences[b]->s; m->prof1 = t->profile[a]; m->prof2 = NULL; m->sip = msa->nsip[a]; aln_runner(m); }else{ if(m->len_a < m->len_b){ m->seq1 = NULL; m->seq2 = NULL; m->prof1 = t->profile[a]; m->prof2 = t->profile[b]; aln_runner(m); }else{ len_b = m->len_b; len_a = m->len_a; m->enda = len_b; m->endb = len_a; m->len_a = len_b; m->len_b = len_a; m->seq1 = NULL; m->seq2 = NULL; m->prof1 = t->profile[b]; m->prof2 = t->profile[a]; aln_runner(m); RUN(mirror_path_n(m,len_a,len_b)); m->len_a = len_a; m->len_b = len_b; } } } /* Store alignment confidence (average meetup margin) */ if(m->margin_count > 0){ t->list[task_id]->confidence = m->margin_sum / (float)m->margin_count; }else{ t->list[task_id]->confidence = 0.0F; } RUN(add_gap_info_to_path_n(m)) ; /* LOG_MSG("Aligned %d and %d (len %d %d) -> path is of length: %d",a,b, m->len_a,m->len_b, 64*(m->path[0]+2)); */ /* Free consistency bonus if allocated */ if(m->consistency){ MFREE(m->consistency); m->consistency = NULL; m->consistency_stride = 0; } /* Restore original aln_param for profile update (unscaled base penalties) */ m->ap = orig_ap; MMALLOC(tmp,sizeof(float)*64*(m->path[0]+2)); if(task_id != t->n_tasks-1){ update_n(t->profile[a],t->profile[b],tmp,m->ap,m->path,msa->nsip[a],msa->nsip[b]); } MFREE(t->profile[a]); MFREE(t->profile[b]); t->profile[c] = tmp; RUN(make_seq(msa,a,b,m->path)); msa->plen[c] = m->path[0]; msa->nsip[c] = msa->nsip[a] + msa->nsip[b]; MREALLOC(msa->sip[c],sizeof(int)*(msa->nsip[a] + msa->nsip[b])); g = 0; for (j = msa->nsip[a];j--;){ msa->sip[c][g] = msa->sip[a][j]; g++; } for (j = msa->nsip[b];j--;){ msa->sip[c][g] = msa->sip[b][j]; g++; } return OK; ERROR: return FAIL; } /* --------------------------------------------------------------------------- * Inline refinement: run N trials at each progressive merge, keep the best * by SP score. Single pass — no second replay pass needed. * ------------------------------------------------------------------------- */ int create_msa_tree_inline_refine(struct msa* msa, struct aln_param* ap, struct aln_tasks* t, int n_trials) { int i; uint8_t* active = NULL; RUN(sort_tasks(t, TASK_ORDER_TREE)); MMALLOC(active, sizeof(uint8_t) * msa->num_profiles); for(i = 0; i < msa->numseq; i++){ active[i] = 1; } for(i = msa->numseq; i < msa->num_profiles; i++){ active[i] = 0; } /* Inline refine is sequential — multi-trial per edge isn't thread-safe */ msa->run_parallel = 0; recursive_aln_inline(msa, t, ap, active, t->n_tasks - 1, n_trials); MFREE(active); return OK; ERROR: if(active){ MFREE(active); } return FAIL; } void recursive_aln_inline(struct msa* msa, struct aln_tasks* t, struct aln_param* ap, uint8_t* active, int c, int n_trials) { struct task* local_t = NULL; int a, b; local_t = t->list[c]; a = local_t->a - msa->numseq; b = local_t->b - msa->numseq; if(!active[local_t->a] && local_t->a >= msa->numseq){ recursive_aln_inline(msa, t, ap, active, a, n_trials); } if(!active[local_t->b] && local_t->b >= msa->numseq){ recursive_aln_inline(msa, t, ap, active, b, n_trials); } struct aln_mem* ml = NULL; alloc_aln_mem(&ml, 256); ml->ap = ap; ml->mode = ALN_MODE_FULL; do_align_inline_refine(msa, t, ml, c, n_trials); active[local_t->a] = 0; active[local_t->b] = 0; active[local_t->c] = 1; free_aln_mem(ml); } /* Run n_trials alignments for one edge, keep the best by SP score. Trial 0 is the deterministic baseline. Trials 1..n-1 use flip_threshold to explore alternative Hirschberg paths at uncertain meetup points. */ int do_align_inline_refine(struct msa* msa, struct aln_tasks* t, struct aln_mem* m, int task_id, int n_trials) { float* tmp = NULL; int* best_path = NULL; int a, b, c; int len_a, len_b; int j, g, k; float best_sp = -FLT_MAX; float avg_margin = 0.0F; a = t->list[task_id]->a; b = t->list[task_id]->b; c = t->list[task_id]->c; /* Distance-dependent parameter scaling */ struct aln_param* orig_ap = m->ap; struct aln_param scaled_ap; float gap_scale = compute_gap_scale(msa, m->ap, a, b); float subm_off = compute_subm_offset(msa, m->ap, a, b); if(gap_scale < 1.0f || subm_off > 0.0f){ scaled_ap = *m->ap; scaled_ap.gpo *= gap_scale; scaled_ap.gpe *= gap_scale; scaled_ap.tgpe *= gap_scale; scaled_ap.subm_offset = subm_off; m->ap = &scaled_ap; } /* Build profiles (same as do_align) */ if(msa->nsip[a] == 1){ m->len_a = msa->sequences[a]->len; RUN(make_profile_n(m->ap, msa->sequences[a]->s, m->len_a, leaf_weight(msa,a), &t->profile[a])); }else{ m->len_a = msa->plen[a]; RUN(set_gap_penalties_n(t->profile[a], m->len_a, msa->nsip[b])); } if(msa->nsip[b] == 1){ m->len_b = msa->sequences[b]->len; RUN(make_profile_n(m->ap, msa->sequences[b]->s, m->len_b, leaf_weight(msa,b), &t->profile[b])); }else{ m->len_b = msa->plen[b]; RUN(set_gap_penalties_n(t->profile[b], m->len_b, msa->nsip[a])); } len_a = m->len_a; len_b = m->len_b; RUN(init_alnmem(m)); /* Compute consistency bonus for all merge types */ m->consistency = NULL; m->consistency_stride = 0; { struct consistency_table* ct = (struct consistency_table*)msa->consistency_table; if(ct != NULL){ int dp_row_node, dp_col_node, dp_rows, dp_cols; if(msa->nsip[a] == 1 && msa->nsip[b] == 1){ if(len_a < len_b){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; } }else if(msa->nsip[a] == 1){ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; }else if(msa->nsip[b] == 1){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ if(len_a < len_b){ dp_row_node = a; dp_rows = len_a; dp_col_node = b; dp_cols = len_b; }else{ dp_row_node = b; dp_rows = len_b; dp_col_node = a; dp_cols = len_a; } } RUN(anchor_consistency_get_bonus_profile(ct, msa, dp_row_node, dp_rows, dp_col_node, dp_cols, &m->consistency)); m->consistency_stride = dp_cols; } } /* Allocate best_path buffer */ MMALLOC(best_path, sizeof(int) * m->alloc_path_len); /* Multi-trial alignment */ for(k = 0; k < n_trials; k++){ float sp = 0.0F; /* Re-initialize DP state */ { int _g = MACRO_MAX(len_a, len_b) + 2; int _i; for(_i = 0; _i < _g; _i++){ m->path[_i] = -1; } } m->starta = 0; m->startb = 0; m->enda = len_a; m->endb = len_b; m->len_a = len_a; m->len_b = len_b; m->f[0].a = 0.0F; m->f[0].ga = -FLT_MAX; m->f[0].gb = -FLT_MAX; m->b[0].a = 0.0F; m->b[0].ga = -FLT_MAX; m->b[0].gb = -FLT_MAX; m->margin_sum = 0.0F; m->margin_count = 0; if(k == 0){ m->flip_threshold = 0.0F; m->flip_trial = 0; }else{ m->flip_threshold = avg_margin; m->flip_trial = k; m->flip_stride = n_trials - 1; m->flip_counter = 0; } /* Dispatch alignment (handle seq/profile combinations + mirroring) */ if(msa->nsip[a] == 1){ if(msa->nsip[b] == 1){ if(len_a < len_b){ m->seq1 = msa->sequences[a]->s; m->seq2 = msa->sequences[b]->s; m->prof1 = NULL; m->prof2 = NULL; aln_runner(m); }else{ m->enda = len_b; m->endb = len_a; m->len_a = len_b; m->len_b = len_a; m->seq1 = msa->sequences[b]->s; m->seq2 = msa->sequences[a]->s; m->prof1 = NULL; m->prof2 = NULL; aln_runner(m); RUN(mirror_path_n(m, len_a, len_b)); m->len_a = len_a; m->len_b = len_b; } }else{ m->enda = len_b; m->endb = len_a; m->len_a = len_b; m->len_b = len_a; m->seq1 = NULL; m->seq2 = msa->sequences[a]->s; m->prof1 = t->profile[b]; m->prof2 = NULL; m->sip = msa->nsip[b]; aln_runner(m); RUN(mirror_path_n(m, len_a, len_b)); m->len_a = len_a; m->len_b = len_b; } }else{ if(msa->nsip[b] == 1){ m->seq1 = NULL; m->seq2 = msa->sequences[b]->s; m->prof1 = t->profile[a]; m->prof2 = NULL; m->sip = msa->nsip[a]; aln_runner(m); }else{ if(len_a < len_b){ m->seq1 = NULL; m->seq2 = NULL; m->prof1 = t->profile[a]; m->prof2 = t->profile[b]; aln_runner(m); }else{ m->enda = len_b; m->endb = len_a; m->len_a = len_b; m->len_b = len_a; m->seq1 = NULL; m->seq2 = NULL; m->prof1 = t->profile[b]; m->prof2 = t->profile[a]; aln_runner(m); RUN(mirror_path_n(m, len_a, len_b)); m->len_a = len_a; m->len_b = len_b; } } } /* Convert raw Hirschberg path to 0/1/2 format with gap info */ RUN(add_gap_info_to_path_n(m)); /* Score this trial */ RUN(compute_sp_score(msa, m->ap, m->path, msa->sip[a], msa->nsip[a], msa->sip[b], msa->nsip[b], &sp)); if(sp > best_sp){ best_sp = sp; memcpy(best_path, m->path, sizeof(int) * (m->path[0] + 2)); } /* After baseline, compute avg_margin for flip threshold */ if(k == 0 && m->margin_count > 0){ avg_margin = m->margin_sum / (float)m->margin_count; } } /* Install best path */ memcpy(m->path, best_path, sizeof(int) * (best_path[0] + 2)); /* Free consistency bonus if allocated */ if(m->consistency){ MFREE(m->consistency); m->consistency = NULL; m->consistency_stride = 0; } /* Store confidence */ t->list[task_id]->confidence = best_sp; /* Restore original aln_param for profile update */ m->ap = orig_ap; /* Merge profiles */ MMALLOC(tmp, sizeof(float) * 64 * (m->path[0] + 2)); if(task_id != t->n_tasks - 1){ update_n(t->profile[a], t->profile[b], tmp, m->ap, m->path, msa->nsip[a], msa->nsip[b]); } MFREE(t->profile[a]); MFREE(t->profile[b]); t->profile[a] = NULL; t->profile[b] = NULL; t->profile[c] = tmp; RUN(make_seq(msa, a, b, m->path)); msa->plen[c] = m->path[0]; msa->nsip[c] = msa->nsip[a] + msa->nsip[b]; MREALLOC(msa->sip[c], sizeof(int) * (msa->nsip[a] + msa->nsip[b])); g = 0; for(j = msa->nsip[a]; j--;){ msa->sip[c][g] = msa->sip[a][j]; g++; } for(j = msa->nsip[b]; j--;){ msa->sip[c][g] = msa->sip[b][j]; g++; } MFREE(best_path); return OK; ERROR: if(best_path){ MFREE(best_path); } return FAIL; } kalign-3.5.1/lib/src/aln_run.h000066400000000000000000000021701515023132300161240ustar00rootroot00000000000000#ifndef ALN_RUN_H #define ALN_RUN_H #ifdef ALN_RUN_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct aln_param; struct aln_tasks; struct msa; /* EXTERN int create_msa(struct msa* msa, struct aln_param* ap,struct aln_tasks* t); */ EXTERN int create_msa_tree(struct msa* msa, struct aln_param* ap,struct aln_tasks* t); EXTERN int create_msa_tree_inline_refine(struct msa* msa, struct aln_param* ap, struct aln_tasks* t, int n_trials); EXTERN float compute_gap_scale(struct msa* msa, struct aln_param* ap, int a, int b); EXTERN float compute_subm_offset(struct msa* msa, struct aln_param* ap, int a, int b); EXTERN int create_chaos_msa_serial(struct msa* msa, struct aln_param* ap,struct aln_tasks* t); EXTERN int create_msa_serial(struct msa* msa, struct aln_param* ap,struct aln_tasks* t); /* EXTERN int create_msa_openMP(struct msa* msa, struct aln_param* ap,struct aln_tasks* t); */ EXTERN int create_chaos_msa_openMP(struct msa* msa, struct aln_param* ap,struct aln_tasks* t); #undef ALN_RUN_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_seqprofile.c000066400000000000000000000323741515023132300174750ustar00rootroot00000000000000#include #include #include "tldevel.h" #include "aln_param.h" #include "aln_struct.h" #define ALN_SEQPROFILE_IMPORT #include "aln_seqprofile.h" #define MAX(a, b) (a > b ? a : b) #define MAX3(a,b,c) MAX(MAX(a,b),c) int aln_seqprofile_foward(struct aln_mem* m) { struct states* s = m->f; const float* prof1 = m->prof1; const uint8_t* seq2 = m->seq2; const int sip = m->sip; register float pa = 0; register float pga = 0; register float pgb = 0; register float ca = 0; register float xa = 0; register float xga = 0; register int i = 0; register int j = 0; const float open = m->ap->gpo * sip; const float ext = m->ap->gpe * sip; const float text = m->ap->tgpe * sip; prof1 += (m->starta)<< 6; s[m->startb].a = s[0].a; s[m->startb].ga = s[0].ga; s[m->startb].gb = s[0].gb; if(m->startb){ for (j = m->startb +1; j < m->endb;j++){ s[j].a = -FLT_MAX; s[j].ga = MAX(s[j-1].ga-ext,s[j-1].a-open); s[j].gb = -FLT_MAX; } }else{ for (j = m->startb+1; j < m->endb;j++){ s[j].a = -FLT_MAX; s[j].ga = MAX(s[j-1].ga,s[j-1].a) - text; s[j].gb = -FLT_MAX; } } s[m->endb].a = -FLT_MAX; s[m->endb].ga = -FLT_MAX; s[m->endb].gb = -FLT_MAX; seq2--; for (i = m->starta;i < m->enda;i++){ prof1 += 64; pa = s[m->startb].a; pga = s[m->startb].ga; pgb = s[m->startb].gb; s[m->startb].a = -FLT_MAX; s[m->startb].ga = -FLT_MAX; xa = s[m->startb].a; xga = s[m->startb].ga; if(m->startb){ s[m->startb].gb = MAX(pgb+prof1[28],pa+prof1[27]); }else{ s[m->startb].gb = MAX(pgb,pa)+prof1[29]; } for (j = m->startb+1; j < m->endb;j++){ ca = s[j].a; pa = MAX3(pa,pga -open,pgb + prof1[-37]); pa += prof1[32 + seq2[j]]; if(m->consistency){ pa += m->consistency[i * m->consistency_stride + j]; } s[j].a = pa; pga = s[j].ga; //s[j].ga = MAX(s[j-1].ga-ext,s[j-1].a-open); s[j].ga = MAX(xga-ext,xa-open); pgb = s[j].gb; s[j].gb = MAX(pgb+prof1[28],ca+prof1[27]); pa = ca; xa = s[j].a; xga = s[j].ga; } ca = s[j].a; pa = MAX3(pa,pga -open,pgb + prof1[-37]); pa += prof1[32 + seq2[j]]; if(m->consistency){ pa += m->consistency[i * m->consistency_stride + j]; } s[j].a = pa; s[j].ga = -FLT_MAX;//MAX(s[j-1].ga-ext,s[j-1].a-open); if (m->endb != m->len_b){ s[j].gb = MAX(s[j].gb+prof1[28] ,ca+prof1[27]); }else{ s[j].gb = MAX(s[j].gb,ca)+ prof1[29]; } } //prof1 -= m->enda << 6; return OK; } int aln_seqprofile_backward(struct aln_mem* m) { struct states* s = m->b; const float* prof1 = m->prof1; const uint8_t* seq2 = m->seq2; const int sip = m->sip; register float pa = 0; register float pga = 0; register float pgb = 0; register float ca = 0; register float xa = 0; register float xga = 0; register int i = 0; register int j = 0; const float open = m->ap->gpo * sip; const float ext = m->ap->gpe * sip; const float text = m->ap->tgpe * sip; prof1 += (m->enda_2 +1) << 6; s[m->endb].a = s[0].a; s[m->endb].ga = s[0].ga; s[m->endb].gb = s[0].gb; if(m->endb != m->len_b){ for(j = m->endb-1;j > m->startb ;j--){ s[j].a = -FLT_MAX; s[j].ga = MAX(s[j+1].ga-ext,s[j+1].a-open); s[j].gb = -FLT_MAX; } }else{ for(j = m->endb-1;j > m->startb;j--){ s[j].a = -FLT_MAX; s[j].ga = MAX(s[j+1].ga,s[j+1].a)-text; s[j].gb = -FLT_MAX; } } s[m->startb].a = -FLT_MAX; s[m->startb].ga = -FLT_MAX; s[m->startb].gb = -FLT_MAX; i = m->enda_2 -m->starta_2; while(i--){ prof1 -= 64; pa = s[m->endb].a; pga = s[m->endb].ga; pgb = s[m->endb].gb; s[m->endb].a = -FLT_MAX; s[m->endb].ga = -FLT_MAX; xa = s[m->endb].a; xga = s[m->endb].ga; if(m->endb != m->len_b){ s[m->endb].gb = MAX(pgb+prof1[28],pa+prof1[27]); }else{ s[m->endb].gb = MAX(pgb,pa) +prof1[29]; } for(j = m->endb-1;j > m->startb;j--){ ca = s[j].a; pa = MAX3(pa,pga - open,pgb +prof1[91]); pa += prof1[32 + seq2[j]]; if(m->consistency){ pa += m->consistency[(m->starta_2 + i) * m->consistency_stride + j]; } s[j].a = pa; pga = s[j].ga; //s[j].ga = MAX(s[j+1].ga-ext,s[j+1].a-open); s[j].ga = MAX(xga-ext,xa-open); pgb = s[j].gb; s[j].gb = MAX(pgb+prof1[28],ca+prof1[27]); pa = ca; xa = s[j].a; xga = s[j].ga; } ca = s[j].a; pa = MAX3(pa,pga - open,pgb +prof1[91]); pa += prof1[32 + seq2[j]]; if(m->consistency){ pa += m->consistency[(m->starta_2 + i) * m->consistency_stride + j]; } s[j].a = pa; s[j].ga = -FLT_MAX;//MAX(s[j+1].ga-ext,s[j+1].a-open); if(m->startb){ s[j].gb = MAX(s[j].gb+prof1[28], ca+prof1[27]); }else{ s[j].gb = MAX(s[j].gb,ca)+prof1[29]; } } return OK; } int aln_seqprofile_meetup(struct aln_mem* m,int old_cor[],int* meet,int* t,float* score) { struct states* f = m->f; struct states* b = m->b; const float* prof1 = m->prof1; float sip = m->sip; int i; int c; int c2 = -1; int transition = -1; int transition2 = -1; float s_tmp; const float open = m->ap->gpo * sip; //code: // a -> a = 1 // a -> ga = 2 // a -> gb = 3 // ga ->ga = 4 // ga -> a = 5 //gb->gb = 6; //gb->a = 7; //int max = -FLT_MAX; float max = -FLT_MAX; float max2 = -FLT_MAX; //float middle = (m->endb - m->startb)/2 + m->startb; float middle = (float)(old_cor[3] - old_cor[2])/2.0F + (float)old_cor[2]; float sub = 0.0F; prof1+= ((old_cor[4]+1)<<6); //i = m->startb; c = -1; //for(i = m->startb; i < m->endb;i++){ for(i = old_cor[2]; i < old_cor[3];i++){ sub = fabsf(middle - (float)i); sub /= 1000.0F; s_tmp = f[i].a+b[i].a-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 1; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 1; } s_tmp = f[i].a+b[i].ga-open-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 2; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 2; } s_tmp = f[i].a+b[i].gb+prof1[27]-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 3; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 3; } s_tmp = f[i].ga+b[i].a-open-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 5; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 5; } if(m->startb == 0){ s_tmp = f[i].gb+b[i].gb+prof1[29]-sub; }else{ s_tmp = f[i].gb+b[i].gb+prof1[28]-sub; } if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 6; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 6; } s_tmp = f[i].gb+b[i].a+prof1[-37]-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 7; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 7; } } //i = m->endb; i = old_cor[3]; sub = fabsf(middle - (float)i); sub /= 1000.0F; s_tmp = f[i].a+b[i].gb+prof1[27]-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 3; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 3; } if(m->endb == m->len_b){ s_tmp = f[i].gb+b[i].gb+prof1[29]-sub; }else{ s_tmp = f[i].gb+b[i].gb+prof1[28]-sub; } if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 6; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 6; } /* Accumulate confidence margin and record per-meetup margins */ if(max2 > -FLT_MAX){ float _margin = max - max2; if(m->flip_margins != NULL && m->margin_count < m->flip_margin_alloc){ m->flip_margins[m->margin_count] = _margin; } m->margin_sum += _margin; m->margin_count++; } /* Perturbation: flip uncertain midpoints to second-best choice. Three modes: individual targeting (MCTS), stride bitmask, or round-robin. */ if(m->flip_threshold > 0.0F && c2 >= 0 && max2 > -FLT_MAX){ float margin = max - max2; if(margin < m->flip_threshold){ if(m->flip_bit_map != NULL){ /* Individual midpoint targeting (MCTS) */ if(m->flip_counter < m->flip_n_uncertain){ int bit = m->flip_bit_map[m->flip_counter]; if(bit >= 0 && ((1U << bit) & m->flip_mask)){ c = c2; transition = transition2; } } }else if(m->flip_mask != 0){ /* Stride-based bitmask mode */ if((1U << (m->flip_counter % m->flip_stride)) & m->flip_mask){ c = c2; transition = transition2; } }else if(m->flip_trial > 0){ /* Round-robin mode */ if(m->flip_counter % m->flip_stride == m->flip_trial - 1){ c = c2; transition = transition2; } } m->flip_counter++; } } *meet = c; *t = transition; *score = max; return OK; } kalign-3.5.1/lib/src/aln_seqprofile.h000066400000000000000000000007141515023132300174730ustar00rootroot00000000000000#ifndef ALN_SEQPROF_H #define ALN_SEQPROF_H #ifdef ALN_SEQPROFILE_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct aln_mem; EXTERN int aln_seqprofile_foward(struct aln_mem* m); EXTERN int aln_seqprofile_backward(struct aln_mem* m); EXTERN int aln_seqprofile_meetup(struct aln_mem* m,int old_cor[],int* meet,int* t,float* score); #undef ALN_SEQPROFILE_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_seqseq.c000066400000000000000000000323741515023132300166250ustar00rootroot00000000000000#include #include #include "tldevel.h" #include "aln_param.h" #include "aln_struct.h" #define ALN_SEQSEQ_IMPORT #include "aln_seqseq.h" #define MAX(a, b) (a > b ? a : b) #define MAX3(a,b,c) MAX(MAX(a,b),c) int aln_seqseq_foward(struct aln_mem* m) { struct states* s = m->f; const uint8_t* seq1 = m->seq1; const uint8_t* seq2 = m->seq2; float *subp = NULL; const int starta = m->starta; const int enda = m->enda; const int startb =m->startb; const int endb = m->endb; register float pa = 0; register float pga = 0; register float pgb = 0; register float ca = 0; register float xa = 0; register float xga = 0; register int i = 0; register int j = 0; const float gpo = m->ap->gpo; const float gpe = m->ap->gpe; const float tgpe = m->ap->tgpe; float** subm = m->ap->subm; const float soff = m->ap->subm_offset; s[startb].a = s[0].a; s[startb].ga = s[0].ga; s[startb].gb = s[0].gb; if(startb){ for (j = startb+1; j < endb;j++){ s[j].a = -FLT_MAX; s[j].ga = MAX(s[j-1].ga - gpe,s[j-1].a-gpo); s[j].gb = -FLT_MAX; } }else{ for (j = startb+1; j < endb;j++){ s[j].a = -FLT_MAX; s[j].ga = MAX(s[j-1].ga,s[j-1].a)-tgpe; s[j].gb = -FLT_MAX; } } s[endb].a = -FLT_MAX; s[endb].ga = -FLT_MAX; s[endb].gb = -FLT_MAX; seq2--; for (i = starta;i < enda;i++){ subp = subm[seq1[i]]; pa = s[startb].a; pga = s[startb].ga; pgb = s[startb].gb; s[startb].a = -FLT_MAX; s[startb].ga = -FLT_MAX; xa = s[startb].a; xga = s[startb].ga; if(startb){ s[startb].gb = MAX(pgb - gpe,pa - gpo); }else{ s[startb].gb = MAX(pgb,pa) - tgpe; } for (j = startb+1; j < endb;j++){ ca = s[j].a; pa = MAX3(pa,pga-gpo,pgb-gpo); pa += subp[seq2[j]] - soff; if(m->consistency){ pa += m->consistency[i * m->consistency_stride + j]; } s[j].a = pa; pga = s[j].ga; //s[j].ga = MAX(s[j-1].ga-gpe,s[j-1].a-gpo); s[j].ga = MAX(xga-gpe,xa-gpo); pgb = s[j].gb; s[j].gb = MAX(pgb-gpe ,ca-gpo); pa = ca; xa = s[j].a; xga = s[j].ga; } ca = s[j].a; pa = MAX3(pa,pga-gpo,pgb-gpo); pa += subp[seq2[j]] - soff; if(m->consistency){ pa += m->consistency[i * m->consistency_stride + j]; } s[j].a = pa; s[j].ga = -FLT_MAX;//MAX(s[j-1].ga-gpe,s[j-1].a-gpo); if (endb != m->len_b){ s[j].gb = MAX(s[j].gb-gpe ,ca-gpo); }else{ s[j].gb = MAX(s[j].gb,ca)-tgpe; } } return OK; } int aln_seqseq_backward(struct aln_mem* m) { struct states* s = m->b; const uint8_t* seq1 = m->seq1; const uint8_t* seq2 = m->seq2; float *subp = NULL; const int starta = m->starta_2; const int enda = m->enda_2; const int startb =m->startb; const int endb = m->endb; register float pa = 0; register float pga = 0; register float pgb = 0; register float ca = 0; register float xa = 0; register float xga = 0; register int i = 0; register int j = 0; const float gpo = m->ap->gpo; const float gpe = m->ap->gpe; const float tgpe = m->ap->tgpe; float** subm = m->ap->subm; const float soff = m->ap->subm_offset; s[endb].a = s[0].a ; s[endb].ga = s[0].ga; s[endb].gb = s[0].gb; //init of first row; //j = endb-startb; if(endb != m->len_b){ for(j = endb-1;j > startb;j--){ s[j].a = -FLT_MAX; s[j].ga = MAX(s[j+1].ga-gpe,s[j+1].a-gpo); s[j].gb = -FLT_MAX; } }else{ for(j = endb-1;j > startb;j--){ s[j].a = -FLT_MAX; s[j].ga = MAX(s[j+1].ga,s[j+1].a)-tgpe; s[j].gb = -FLT_MAX; } } s[startb].a = -FLT_MAX; s[startb].ga = -FLT_MAX; s[startb].gb = -FLT_MAX; i = enda-starta; seq1+= starta; while(i--){ subp = subm[seq1[i]]; pa = s[endb].a; pga = s[endb].ga; pgb = s[endb].gb; s[endb].a = -FLT_MAX; s[endb].ga = -FLT_MAX; xa = s[endb].a; xga = s[endb].ga; if(endb != m->len_b){ s[endb].gb = MAX(pgb-gpe,pa-gpo); }else{ s[endb].gb = MAX(pgb,pa)-tgpe; } for(j = endb-1;j > startb;j--){ ca = s[j].a; pa = MAX3(pa,pga - gpo,pgb-gpo); pa += subp[seq2[j]] - soff; if(m->consistency){ pa += m->consistency[(starta + i) * m->consistency_stride + j]; } s[j].a = pa; pga = s[j].ga; //s[j].ga = MAX(s[j+1].ga-gpe,s[j+1].a-gpo); s[j].ga = MAX(xga-gpe,xa-gpo); pgb = s[j].gb; s[j].gb = MAX(pgb-gpe,ca-gpo); pa = ca; xa = s[j].a; xga = s[j].ga; } ca = s[j].a; pa = MAX3(pa,pga - gpo,pgb-gpo); pa += subp[seq2[j]] - soff; if(m->consistency){ pa += m->consistency[(starta + i) * m->consistency_stride + j]; } s[j].a = pa; s[j].ga = -FLT_MAX;//MAX(s[j+1].ga-gpe,s[j+1].a-gpo); if(startb){ s[j].gb = MAX(s[j].gb-gpe,ca-gpo); }else{ s[j].gb = MAX(s[j].gb,ca)-tgpe; } } return OK; } int aln_seqseq_meetup(struct aln_mem* m,int old_cor[],int* meet,int* t,float* score) { struct states* f = m->f; struct states* b = m->b; const float gpo = m->ap->gpo; const float gpe = m->ap->gpe; const float tgpe = m->ap->tgpe; int i; int c; int c2 = -1; int transition = -1; int transition2 = -1; float s_tmp; //code: // a -> a = 1 // a -> ga = 2 // a -> gb = 3 // ga ->ga = 4 // ga -> a = 5 //gb->gb = 6; //gb->a = 7; //int max = -FLT_MAX; float max = -FLT_MAX; float max2 = -FLT_MAX; //float middle = (hm->endb - hm->startb)/2 + hm->startb; float middle = (float)(old_cor[3] - old_cor[2])/2.0F + (float)old_cor[2]; float sub = 0.0F; //i = hm->startb; c = -1; //for(i = hm->startb; i < hm->endb;i++){ for(i = old_cor[2]; i < old_cor[3];i++){ sub = fabsf(middle - (float)i); sub /= 1000.0F; s_tmp = f[i].a+b[i].a-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 1; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 1; } s_tmp = f[i].a+b[i].ga-gpo-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 2; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 2; } s_tmp = f[i].a+b[i].gb-gpo-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 3; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 3; } s_tmp = f[i].ga+b[i].a-gpo-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 5; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 5; } if(m->startb == 0){ s_tmp = f[i].gb+b[i].gb-tgpe-sub; }else{ s_tmp = f[i].gb+b[i].gb-gpe-sub; } if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 6; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 6; } s_tmp = f[i].gb+b[i].a-gpo-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 7; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 7; } } //i = hm->endb; i = old_cor[3]; sub = fabsf(middle - (float)i); sub /= 1000.0F; s_tmp = f[i].a+b[i].gb-gpo-sub; if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 3; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 3; } if(m->endb == m->len_b){ s_tmp = f[i].gb+b[i].gb-tgpe-sub; }else{ s_tmp = f[i].gb+b[i].gb-gpe-sub; } if(s_tmp > max){ max2 = max; c2 = c; transition2 = transition; max = s_tmp; transition = 6; c = i; }else if(s_tmp > max2){ max2 = s_tmp; c2 = i; transition2 = 6; } /* Accumulate confidence margin and record per-meetup margins */ if(max2 > -FLT_MAX){ float _margin = max - max2; if(m->flip_margins != NULL && m->margin_count < m->flip_margin_alloc){ m->flip_margins[m->margin_count] = _margin; } m->margin_sum += _margin; m->margin_count++; } /* Perturbation: flip uncertain midpoints to second-best choice. Three modes: individual targeting (MCTS), stride bitmask, or round-robin. */ if(m->flip_threshold > 0.0F && c2 >= 0 && max2 > -FLT_MAX){ float margin = max - max2; if(margin < m->flip_threshold){ if(m->flip_bit_map != NULL){ /* Individual midpoint targeting (MCTS) */ if(m->flip_counter < m->flip_n_uncertain){ int bit = m->flip_bit_map[m->flip_counter]; if(bit >= 0 && ((1U << bit) & m->flip_mask)){ c = c2; transition = transition2; } } }else if(m->flip_mask != 0){ /* Stride-based bitmask mode */ if((1U << (m->flip_counter % m->flip_stride)) & m->flip_mask){ c = c2; transition = transition2; } }else if(m->flip_trial > 0){ /* Round-robin mode */ if(m->flip_counter % m->flip_stride == m->flip_trial - 1){ c = c2; transition = transition2; } } m->flip_counter++; } } *meet = c; *t = transition; *score = max; return OK; } kalign-3.5.1/lib/src/aln_seqseq.h000066400000000000000000000006451515023132300166260ustar00rootroot00000000000000#ifndef ALN_SEQSEQ_H #define ALN_SEQSEQ_H #ifdef ALN_SEQSEQ_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif EXTERN int aln_seqseq_foward(struct aln_mem* m); EXTERN int aln_seqseq_backward(struct aln_mem* m); EXTERN int aln_seqseq_meetup(struct aln_mem* m,int old_cor[],int* meet,int* t,float* score); #undef ALN_SEQSEQ_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_setup.c000066400000000000000000000400331515023132300164530ustar00rootroot00000000000000#include "tldevel.h" #include #include "aln_struct.h" #include "aln_param.h" #include "aln_mem.h" #define ALN_SETUP_IMPORT #include "aln_setup.h" int init_alnmem(struct aln_mem* m) { int i; int g; m->starta = 0; m->startb = 0; m->enda = m->len_a; m->endb = m->len_b; m->f[0].a = 0.0F; m->f[0].ga = -FLT_MAX; m->f[0].gb = -FLT_MAX; m->b[0].a = 0.0F; m->b[0].ga = -FLT_MAX; m->b[0].gb = -FLT_MAX; RUN(resize_aln_mem(m)); g = MACRO_MAX(m->len_a, m->len_b) + 2; for(i = 0 ;i < g ;i++){ m->path[i] = -1; } return OK; ERROR: return FAIL; } int make_profile_n(struct aln_param* ap,const uint8_t* seq,const int len, float weight, float** p) { float** subm = NULL; float* prof = NULL; float gpo; float gpe; float tgpe; int i; int j; int c; gpo = ap->gpo; gpe = ap->gpe; tgpe = ap->tgpe; subm = ap->subm; float soff = ap->subm_offset; MMALLOC(prof,sizeof(float)*(len+2)*64); prof += (64 *(len+1)); for (i = 0;i < 64;i++){ prof[i] = 0; } prof[23+32] = -gpo; prof[24+32] = -gpe; prof[25+32] = -tgpe; i = len; while(i--){ prof -= 64; for (j = 0;j < 64;j++){ prof[j] = 0; } c = seq[i]; prof[c] += weight; prof += 32; for(j = 23;j--;){ prof[j] = subm[c][j] - soff; } prof[23] = -gpo; prof[24] = -gpe; prof[25] = -tgpe; prof -= 32; } prof -= 64; for (i = 0;i < 64;i++){ prof[i] = 0; } prof[23+32] = -gpo; prof[24+32] = -gpe; prof[25+32] = -tgpe; *p = prof; return OK; ERROR: return FAIL; } int set_gap_penalties_n(float* prof,int len,int nsip) { int i; prof += (64 *(len+1)); prof[27] = prof[55] * (float)nsip;//gap open or close 23 prof[28] = prof[56] * (float)nsip;//gap extention 24 prof[29] = prof[57] * (float)nsip;//gap open or close 25 i = len+1; while(i--){ prof -= 64; prof[27] = prof[55] * (float)nsip;//gap open or close prof[28] = prof[56] * (float)nsip;//gap extention prof[29] = prof[57] * (float)nsip;//gap open or close } return OK; } int add_gap_info_to_path_n(struct aln_mem* m) { int* path = NULL; int* o_path = NULL; int* tmp_path = NULL; int i,j; int a = 0; int b = 0; int len_a; int len_b; len_a = m->len_a; len_b = m->len_b; path = m->path; o_path = m->tmp_path; for(i = 0; i < len_a+len_b+2;i++){ o_path[i] = 0; } j = 1; b = -1; if(path[1] == -1){ o_path[j] = 2; j++; }else{ if(path[1] != 1){ for ( a = 0;a < path[1] -1;a++){ o_path[j] = 1; j++; } o_path[j] = 0; j++; }else{ o_path[j] = 0; j++; } } b = path[1]; for(i = 2; i <= len_a;i++){ if(path[i] == -1){ o_path[j] = 2; j++; }else{ if(path[i]-1 != b && b != -1){ for ( a = 0;a < path[i] - b-1;a++){ o_path[j] = 1; j++; } o_path[j] = 0; j++; }else{ o_path[j] = 0; j++; } } b = path[i]; } if(path[len_a] < len_b && path[len_a] != -1){ // fprintf(stderr,"WARNING:%d %d\n",path[len_a],len_b); for ( a = 0;a < len_b - path[len_a];a++){ o_path[j] = 1; j++; } } o_path[0] = j-1; o_path[j] = 3; //add gap info.. i = 2; while(o_path[j] != 3){ if ((o_path[i-1] &3) && !(o_path[i] & 3)){ if(o_path[i-1] & 8){ o_path[i-1] += 8; }else{ o_path[i-1] |= 16; } }else if (!(o_path[i-1] & 3) &&(o_path[i] &3)){ o_path[i] |= 4; }else if ((o_path[i-1] & 1) && (o_path[i] & 1)){ o_path[i] |= 8; }else if ((o_path[i-1] & 2) && (o_path[i] & 2)){ o_path[i] |= 8; } i++; } //add terminal gap... i = 1; while(o_path[i] != 0){ o_path[i] |= 32; i++; } /* j = i; */ i = o_path[0]; while(o_path[i] != 0){ o_path[i] |= 32; i--; } tmp_path = m->path; m->path = m->tmp_path; m->tmp_path = tmp_path; return OK; } int update_n(const float* profa, const float* profb,float* newp, struct aln_param*ap, int* path,int sipa,int sipb) { float gp; int i; int j; int c; /* Balanced profile merging: when use_seq_weights is on, rescale positions 0-22 (amino acid frequencies) at match columns so each side contributes 50%, keeping the total = sipa + sipb. Then recompute substitution scores (32-54) from the balanced freqs via a delta correction that preserves gap penalty adjustments already embedded in those positions from earlier merge steps. delta[j] = sum_aa((freqA*(scaleA-1) + freqB*(scaleB-1)) * subm[aa][j]) This gives: newp[32+j] = balanced_subst[j] - soff_sum + gap_adj, exactly rebalancing the substitution component while keeping gap penalties (which scale with nsip, not weights) intact. */ float scaleA = 1.0f; float scaleB = 1.0f; int do_rebalance = 0; if(ap->use_seq_weights > 0.0f && sipa > 0 && sipb > 0){ float pseudo = ap->use_seq_weights; float total = (float)(sipa + sipb); float denom = total + 2.0f * pseudo; scaleA = total * ((float)sipa + pseudo) / (denom * (float)sipa); scaleB = total * ((float)sipb + pseudo) / (denom * (float)sipb); do_rebalance = 1; } /* First boundary row (freq counts are zero — no rebalancing needed) */ if(do_rebalance){ for (i = 0; i < 23; i++){ newp[i] = profa[i] * scaleA + profb[i] * scaleB; } for (i = 23; i < 64; i++){ newp[i] = profa[i] + profb[i]; } }else{ for (i = 64; i--;){ newp[i] = profa[i] + profb[i]; } } profa += 64; profb += 64; newp += 64; c = 1; while(path[c] != 3){ if (!path[c]){ /* Match column */ if(do_rebalance){ for (i = 0; i < 23; i++){ newp[i] = profa[i] * scaleA + profb[i] * scaleB; } for (i = 23; i < 64; i++){ newp[i] = profa[i] + profb[i]; } /* Correct subst scores (32-54) for rebalanced freqs */ { float** subm = ap->subm; float dA = scaleA - 1.0f; float dB = scaleB - 1.0f; for(j = 0; j < 23; j++){ float delta = 0.0f; int aa; for(aa = 0; aa < 23; aa++){ delta += (profa[aa]*dA + profb[aa]*dB) * subm[aa][j]; } newp[32 + j] += delta; } } }else{ for (i = 64; i--;){ newp[i] = profa[i] + profb[i]; } } profa += 64; profb += 64; } if (path[c] & 1){ //fprintf(stderr,"Gap_A:%d\n",c); //printf("open:%d ext:%d %d %d\n",si->nsip[a] * gpo,si->nsip[a] * gpe,si->nsip[a] * profb[41],si->nsip[a] * profb[46]); for (i = 64; i--;){ newp[i] = profb[i]; } profb += 64; if(!(path[c] & 20)){ if(path[c] & 32){ newp[25] += (float)sipa;//1; gp = ap->tgpe*(float)sipa; }else{ newp[24] += (float)sipa;//1; gp = ap->gpe*(float)sipa; } for (j = 32; j < 55;j++){ newp[j] -= gp; } }else{ if (path[c] & 16){ // fprintf(stderr,"close_open"); if(path[c] & 32){ newp[25] += (float)sipa;//1; gp = ap->tgpe*(float)sipa; newp[23] += (float)sipa;//1; gp += ap->gpo*(float)sipa; }else{ newp[23] += (float)sipa;//1; gp = ap->gpo*(float)sipa; } for (j = 32; j < 55;j++){ newp[j] -= gp; } } if (path[c] & 4){ // fprintf(stderr,"Gap_open"); if(path[c] & 32){ newp[25] += (float)sipa;//1; gp = ap->tgpe*(float)sipa; newp[23] += (float)sipa;//1; gp += ap->gpo*(float)sipa; }else{ newp[23] += (float)sipa;//1; gp = ap->gpo*(float)sipa; } for (j = 32; j < 55;j++){ newp[j] -= gp; } } } } if (path[c] & 2){ //fprintf(stderr,"Gap_B:%d\n",c); //printf("open:%d ext:%d %d %d\n",si->nsip[b] * gpo,si->nsip[b] * gpe,profa[26],profa[27]); for (i = 64; i--;){ newp[i] = profa[i]; } profa+=64; if(!(path[c] & 20)){ if(path[c] & 32){ newp[25] += (float)sipb;//1; gp = ap->tgpe*(float)sipb; }else{ newp[24] += (float)sipb;//1; gp = ap->gpe*(float)sipb; } for (j = 32; j < 55;j++){ newp[j] -= gp; } }else{ if (path[c] & 16){ // fprintf(stderr,"close_open"); if(path[c] & 32){ newp[25] += (float)sipb;//1; gp = ap->tgpe*(float)sipb; newp[23] += (float)sipb;//1; gp += ap->gpo*(float)sipb; }else{ newp[23] += (float)sipb;//1; gp = ap->gpo*(float)sipb; } for (j = 32; j < 55;j++){ newp[j] -= gp; } } if (path[c] & 4){ // fprintf(stderr,"Gap_open"); if(path[c] & 32){ newp[25] += (float)sipb;//1; gp = ap->tgpe*(float)sipb; newp[23] += (float)sipb;//1; gp += ap->gpo*(float)sipb; }else{ newp[23] += (float)sipb;//1; gp = ap->gpo*(float)sipb; } for (j = 32; j < 55;j++){ newp[j] -= gp; } } } } newp += 64; c++; } /* Last boundary row (freq counts are zero — no subst correction needed) */ if(do_rebalance){ for (i = 0; i < 23; i++){ newp[i] = profa[i] * scaleA + profb[i] * scaleB; } for (i = 23; i < 64; i++){ newp[i] = profa[i] + profb[i]; } }else{ for (i = 64; i--;){ newp[i] = profa[i] + profb[i]; } } return OK; } int mirror_path_n(struct aln_mem* m,int len_a,int len_b) { int* apath = NULL; int* opath = NULL; int* tmppath = NULL; int i; apath = m->path; opath = m->tmp_path; for(i =0; i < len_a+2;i++){ opath[i] = -1; } for(i = 1; i <= len_b;i++){ if(apath[i] != -1){ opath[apath[i]] = i; } } tmppath = m->path; m->path = m->tmp_path; m->tmp_path = tmppath; return OK; } kalign-3.5.1/lib/src/aln_setup.h000066400000000000000000000013361515023132300164630ustar00rootroot00000000000000#ifndef ALN_SETUP_H #define ALN_SETUP_H #include #ifdef ALN_SETUP_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct aln_mem; struct aln_param; EXTERN int init_alnmem(struct aln_mem* m); EXTERN int make_profile_n(struct aln_param* ap,const uint8_t* seq,const int len, float weight, float** p); EXTERN int set_gap_penalties_n(float* prof,int len,int nsip); EXTERN int add_gap_info_to_path_n(struct aln_mem* m); EXTERN int update_n(const float* profa, const float* profb,float* newp, struct aln_param*ap, int* path,int sipa,int sipb); EXTERN int mirror_path_n(struct aln_mem *m, int len_a, int len_b); #undef ALN_SETUP_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/aln_struct.h000066400000000000000000000035621515023132300166520ustar00rootroot00000000000000#ifndef ALN_STRUCT_H #define ALN_STRUCT_H #include #define ALN_MODE_SCORE_ONLY 2 #define ALN_MODE_FULL 1 struct states{ float a; float ga; float gb; // float x; }; struct aln_mem{ const float* prof1; const float* prof2; const uint8_t* seq1; const uint8_t* seq2; struct aln_param* ap; struct states* f; struct states* b; int* path; int* tmp_path; uint8_t run_parallel; int alloc_path_len; float score; float margin_sum; /* accumulated meetup margins */ int margin_count; /* number of meetup calls */ float flip_threshold; /* midpoints with margin < this are flip candidates; 0 = no flips */ int flip_trial; /* round-robin: current trial (1..K-1, 0 = baseline) */ int flip_stride; /* round-robin: number of flip slots */ int flip_counter; /* running count of flip candidates encountered */ uint32_t flip_mask; /* bitmask of which slots to flip (0 = no flips) */ float* flip_margins; /* per-meetup margins recorded during baseline */ int flip_margin_alloc; /* allocated size of flip_margins */ int* flip_bit_map; /* maps flip_counter → bit index (-1 = not targeted) */ int flip_n_targets; /* number of individually targeted midpoints */ int flip_n_uncertain; /* total uncertain midpoints (margin < threshold) */ int starta; int starta_2; int startb; int enda; int enda_2; int endb; int size; int len_a; int len_b; int sip; int mode; float* consistency; /* bonus matrix [i * consistency_stride + j], NULL if disabled */ int consistency_stride; /* = len_b (stride for j dimension) */ }; #endif kalign-3.5.1/lib/src/aln_wrap.c000066400000000000000000000553121515023132300162720ustar00rootroot00000000000000#include "tldevel.h" #include "tlmisc.h" #include "esl_stopwatch.h" #include "task.h" #include "msa_struct.h" #include "msa_op.h" #include "msa_alloc.h" #include "msa_check.h" #include "msa_sort.h" #include "msa_io.h" #include "alphabet.h" #include "bisectingKmeans.h" #include "aln_param.h" #include "aln_run.h" #include "aln_refine.h" #include "aln_apair_dist.h" #include "anchor_consistency.h" #include "kalign/kalign.h" #ifdef HAVE_OPENMP #include #endif #define ALN_WRAP_IMPORT #include "aln_wrap.h" /* Resolve PFASUM_AUTO: pick PFASUM43 for divergent, PFASUM60 for closer. Must be called after build_tree_kmeans which fills msa->seq_distances[]. */ static int resolve_pfasum_auto(struct msa *msa, int *type) { int i; int min_len, max_len; float len_ratio; if(*type != KALIGN_TYPE_PROTEIN_PFASUM_AUTO){ return OK; } if(msa->biotype != ALN_BIOTYPE_PROTEIN){ *type = KALIGN_TYPE_PROTEIN_PFASUM43; return OK; } /* Use sequence length ratio (max/min) to select matrix. Similar-length sequences (ratio < 1.5) prefer PFASUM43; high length variation (insertions/extensions) prefers PFASUM60. */ min_len = msa->sequences[0]->len; max_len = msa->sequences[0]->len; for(i = 1; i < msa->numseq; i++){ int l = msa->sequences[i]->len; if(l < min_len) min_len = l; if(l > max_len) max_len = l; } len_ratio = (min_len > 0) ? (float)max_len / (float)min_len : 1.0f; if(len_ratio < 1.5f){ *type = KALIGN_TYPE_PROTEIN_PFASUM43; }else{ *type = KALIGN_TYPE_PROTEIN_PFASUM60; } if(!msa->quiet){ LOG_MSG("Auto matrix: len_ratio=%.2f -> %s", len_ratio, *type == KALIGN_TYPE_PROTEIN_PFASUM60 ? "PFASUM60" : "PFASUM43"); } return OK; } static int compute_tree_weights(struct msa* msa, struct aln_tasks* tasks) { float* nw = NULL; int i; MMALLOC(nw, sizeof(float) * msa->num_profiles); for(i = 0; i < msa->num_profiles; i++){ nw[i] = 0.0f; } /* Root gets total weight = numseq */ nw[tasks->list[tasks->n_tasks - 1]->c] = (float)msa->numseq; /* Walk root → leaves: at each split, distribute parent's weight to children in proportion to the OTHER child's size */ for(i = tasks->n_tasks - 1; i >= 0; i--){ int a = tasks->list[i]->a; int b = tasks->list[i]->b; int c = tasks->list[i]->c; float total = (float)(msa->nsip[a] + msa->nsip[b]); nw[a] = nw[c] * (float)msa->nsip[b] / total; nw[b] = nw[c] * (float)msa->nsip[a] / total; } /* Copy leaf weights to seq_weights */ if(msa->seq_weights){ MFREE(msa->seq_weights); } MMALLOC(msa->seq_weights, sizeof(float) * msa->numseq); for(i = 0; i < msa->numseq; i++){ msa->seq_weights[i] = nw[i]; } MFREE(nw); return OK; ERROR: if(nw) MFREE(nw); return FAIL; } int kalign(char **seq, int *len, int numseq,int n_threads, int type, float gpo, float gpe, float tgpe, char ***aligned, int *out_aln_len) { struct msa *msa = NULL; RUN(kalign_arr_to_msa(seq, len,numseq, &msa)); msa->quiet = 1; if(n_threads < 1){ n_threads = 1; } RUN(kalign_run(msa,n_threads, type, gpo, gpe, tgpe, KALIGN_REFINE_NONE, 0)); RUN(kalign_msa_to_arr(msa, aligned, out_aln_len)); kalign_free_msa(msa); return OK; ERROR: if(msa){ kalign_free_msa(msa); } return FAIL; } int kalign_run_seeded(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, uint64_t tree_seed, float tree_noise, float dist_scale, float vsm_amax, float use_seq_weights, int consistency_anchors, float consistency_weight) { struct aln_tasks* tasks = NULL; struct aln_param* ap = NULL; /* This also adds the ranks of the sequences ! */ RUN(kalign_essential_input_check(msa, 0)); /* If already aligned unalign ! */ if(msa->aligned != ALN_STATUS_UNALIGNED){ RUN(dealign_msa(msa)); } /* Make sure sequences are in order */ RUN(msa_sort_len_name(msa)); /* Convert into internal representation */ if(msa->biotype == ALN_BIOTYPE_DNA){ msa->L = ALPHA_defDNA; RUN(convert_msa_to_internal(msa, ALPHA_defDNA)); }else if(msa->biotype == ALN_BIOTYPE_PROTEIN){ msa->L = ALPHA_redPROTEIN; RUN(convert_msa_to_internal(msa, ALPHA_redPROTEIN)); }else{ ERROR_MSG("Unable to determine what alphabet to use."); } RUN(alloc_tasks(&tasks, msa->numseq)); #ifdef HAVE_OPENMP omp_set_num_threads(n_threads); #endif /* Build guide tree - noisy variant if seed != 0 */ if(tree_seed != 0 && tree_noise > 0.0f){ RUN(build_tree_kmeans_noisy(msa, &tasks, tree_seed, tree_noise)); }else{ RUN(build_tree_kmeans(msa, &tasks)); } /* Convert to full alphabet after having converted to reduced alphabet for tree building above */ if(msa->biotype == ALN_BIOTYPE_PROTEIN){ RUN(convert_msa_to_internal(msa, ALPHA_ambigiousPROTEIN)); } /* Resolve auto matrix selection using BPM distances */ RUN(resolve_pfasum_auto(msa, &type)); /* align */ RUN(aln_param_init(&ap, msa->biotype, n_threads, type, gpo, gpe, tgpe)); ap->adaptive_budget = adaptive_budget; if(use_seq_weights >= 0.0f){ ap->use_seq_weights = use_seq_weights; } if(dist_scale > 0.0f){ ap->dist_scale = dist_scale; } if(vsm_amax >= 0.0f){ ap->vsm_amax = vsm_amax; } if(ap->use_seq_weights > 0.0f){ RUN(compute_tree_weights(msa, tasks)); } /* Build anchor consistency table if requested */ if(consistency_anchors > 0){ ap->consistency_anchors = consistency_anchors; ap->consistency_weight = consistency_weight; RUN(anchor_consistency_build(msa, ap, consistency_anchors, consistency_weight, (struct consistency_table**)&msa->consistency_table)); } DECLARE_TIMER(t1); if(!msa->quiet){ LOG_MSG("Aligning"); } START_TIMER(t1); if(refine == KALIGN_REFINE_INLINE){ RUN(create_msa_tree_inline_refine(msa, ap, tasks, 3)); }else{ RUN(create_msa_tree(msa, ap, tasks)); } msa->aligned = ALN_STATUS_ALIGNED; /* Optional iterative refinement (two-pass approach) */ if(refine != KALIGN_REFINE_NONE && refine != KALIGN_REFINE_INLINE){ RUN(refine_alignment(msa, ap, tasks, refine)); } /* Free consistency table AFTER refinement */ if(msa->consistency_table){ anchor_consistency_free((struct consistency_table*)msa->consistency_table); msa->consistency_table = NULL; } RUN(finalise_alignment(msa)); RUN(msa_sort_rank(msa)); STOP_TIMER(t1); if(!msa->quiet){ GET_TIMING(t1); } DESTROY_TIMER(t1); aln_param_free(ap); free_tasks(tasks); return OK; ERROR: if(msa->consistency_table){ anchor_consistency_free((struct consistency_table*)msa->consistency_table); msa->consistency_table = NULL; } aln_param_free(ap); free_tasks(tasks); return FAIL; } int kalign_run(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget) { return kalign_run_seeded(msa, n_threads, type, gpo, gpe, tgpe, refine, adaptive_budget, 0, 0.0f, 0.0f, -1.0f, -1.0f, 0, 2.0f); } int kalign_run_dist_scale(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, float dist_scale, float vsm_amax, float use_seq_weights) { struct aln_tasks* tasks = NULL; struct aln_param* ap = NULL; RUN(kalign_essential_input_check(msa, 0)); if(msa->aligned != ALN_STATUS_UNALIGNED){ RUN(dealign_msa(msa)); } RUN(msa_sort_len_name(msa)); if(msa->biotype == ALN_BIOTYPE_DNA){ msa->L = ALPHA_defDNA; RUN(convert_msa_to_internal(msa, ALPHA_defDNA)); }else if(msa->biotype == ALN_BIOTYPE_PROTEIN){ msa->L = ALPHA_redPROTEIN; RUN(convert_msa_to_internal(msa, ALPHA_redPROTEIN)); }else{ ERROR_MSG("Unable to determine what alphabet to use."); } RUN(alloc_tasks(&tasks, msa->numseq)); #ifdef HAVE_OPENMP omp_set_num_threads(n_threads); #endif RUN(build_tree_kmeans(msa, &tasks)); if(msa->biotype == ALN_BIOTYPE_PROTEIN){ RUN(convert_msa_to_internal(msa, ALPHA_ambigiousPROTEIN)); } RUN(resolve_pfasum_auto(msa, &type)); RUN(aln_param_init(&ap, msa->biotype, n_threads, type, gpo, gpe, tgpe)); ap->adaptive_budget = adaptive_budget; if(use_seq_weights >= 0.0f){ ap->use_seq_weights = use_seq_weights; } ap->dist_scale = dist_scale; if(vsm_amax >= 0.0f){ ap->vsm_amax = vsm_amax; } if(ap->use_seq_weights > 0.0f){ RUN(compute_tree_weights(msa, tasks)); } DECLARE_TIMER(t1); if(!msa->quiet){ LOG_MSG("Aligning (dist_scale=%.2f, vsm_amax=%.2f)", dist_scale, vsm_amax); } START_TIMER(t1); if(refine == KALIGN_REFINE_INLINE){ RUN(create_msa_tree_inline_refine(msa, ap, tasks, 3)); }else{ RUN(create_msa_tree(msa, ap, tasks)); } msa->aligned = ALN_STATUS_ALIGNED; if(refine != KALIGN_REFINE_NONE && refine != KALIGN_REFINE_INLINE){ RUN(refine_alignment(msa, ap, tasks, refine)); } RUN(finalise_alignment(msa)); RUN(msa_sort_rank(msa)); STOP_TIMER(t1); if(!msa->quiet){ GET_TIMING(t1); } DESTROY_TIMER(t1); aln_param_free(ap); free_tasks(tasks); return OK; ERROR: aln_param_free(ap); free_tasks(tasks); return FAIL; } int kalign_run_realign(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, float dist_scale, float vsm_amax, int realign_iterations, float use_seq_weights, int consistency_anchors, float consistency_weight) { struct aln_tasks* tasks = NULL; struct aln_param* ap = NULL; int iter; RUN(kalign_essential_input_check(msa, 0)); if(msa->aligned != ALN_STATUS_UNALIGNED){ RUN(dealign_msa(msa)); } RUN(msa_sort_len_name(msa)); if(msa->biotype == ALN_BIOTYPE_DNA){ msa->L = ALPHA_defDNA; RUN(convert_msa_to_internal(msa, ALPHA_defDNA)); }else if(msa->biotype == ALN_BIOTYPE_PROTEIN){ msa->L = ALPHA_redPROTEIN; RUN(convert_msa_to_internal(msa, ALPHA_redPROTEIN)); }else{ ERROR_MSG("Unable to determine what alphabet to use."); } RUN(alloc_tasks(&tasks, msa->numseq)); #ifdef HAVE_OPENMP omp_set_num_threads(n_threads); #endif /* Initial guide tree from BPM anchor distances */ RUN(build_tree_kmeans(msa, &tasks)); if(msa->biotype == ALN_BIOTYPE_PROTEIN){ RUN(convert_msa_to_internal(msa, ALPHA_ambigiousPROTEIN)); } RUN(resolve_pfasum_auto(msa, &type)); RUN(aln_param_init(&ap, msa->biotype, n_threads, type, gpo, gpe, tgpe)); ap->adaptive_budget = adaptive_budget; if(use_seq_weights >= 0.0f){ ap->use_seq_weights = use_seq_weights; } ap->dist_scale = dist_scale; if(vsm_amax >= 0.0f){ ap->vsm_amax = vsm_amax; } if(ap->use_seq_weights > 0.0f){ RUN(compute_tree_weights(msa, tasks)); } /* Build anchor consistency table if requested */ if(consistency_anchors > 0){ ap->consistency_anchors = consistency_anchors; ap->consistency_weight = consistency_weight; RUN(anchor_consistency_build(msa, ap, consistency_anchors, consistency_weight, (struct consistency_table**)&msa->consistency_table)); } DECLARE_TIMER(t1); if(!msa->quiet){ LOG_MSG("Aligning (realign=%d, dist_scale=%.2f, vsm_amax=%.2f)", realign_iterations, dist_scale, vsm_amax); } START_TIMER(t1); /* First alignment with BPM-based guide tree */ if(refine == KALIGN_REFINE_INLINE){ RUN(create_msa_tree_inline_refine(msa, ap, tasks, 3)); }else{ RUN(create_msa_tree(msa, ap, tasks)); } msa->aligned = ALN_STATUS_ALIGNED; /* Iterative realignment: align -> compute distances -> new tree -> re-align */ for(iter = 0; iter < realign_iterations; iter++){ float** dm = NULL; int si; /* Finalize to get character sequences with gap characters */ RUN(finalise_alignment(msa)); /* Compute NxN pairwise identity distances from alignment */ RUN(compute_aln_pairwise_dist(msa, &dm)); /* Remove gaps, reset alignment status. dealign_msa zeroes the gaps[] array but does NOT strip '-' from seq->seq (which was linearized by finalise_alignment). We must rebuild seq->seq without gap characters. */ RUN(dealign_msa(msa)); for(si = 0; si < msa->numseq; si++){ struct msa_seq* seq = msa->sequences[si]; int r, w = 0; for(r = 0; seq->seq[r] != '\0'; r++){ if(seq->seq[r] != '-'){ seq->seq[w++] = seq->seq[r]; } } seq->seq[w] = '\0'; seq->len = w; } /* Re-encode internal representation for alignment */ if(msa->biotype == ALN_BIOTYPE_DNA){ RUN(convert_msa_to_internal(msa, ALPHA_defDNA)); }else if(msa->biotype == ALN_BIOTYPE_PROTEIN){ RUN(convert_msa_to_internal(msa, ALPHA_ambigiousPROTEIN)); } /* Reset profile tracking */ RUN(set_sip_nsip(msa)); /* Rebuild guide tree from alignment-derived distances */ free_tasks(tasks); tasks = NULL; RUN(alloc_tasks(&tasks, msa->numseq)); RUN(build_tree_from_pairwise(msa, &tasks, dm)); free_aln_dm(dm, msa->numseq); if(ap->use_seq_weights > 0.0f){ RUN(compute_tree_weights(msa, tasks)); } /* Re-align with new tree */ if(refine == KALIGN_REFINE_INLINE){ RUN(create_msa_tree_inline_refine(msa, ap, tasks, 3)); }else{ RUN(create_msa_tree(msa, ap, tasks)); } msa->aligned = ALN_STATUS_ALIGNED; } /* Refinement after all realign iterations (two-pass, skip for inline) */ if(refine != KALIGN_REFINE_NONE && refine != KALIGN_REFINE_INLINE){ RUN(refine_alignment(msa, ap, tasks, refine)); } /* Free consistency table AFTER refinement */ if(msa->consistency_table){ anchor_consistency_free((struct consistency_table*)msa->consistency_table); msa->consistency_table = NULL; } RUN(finalise_alignment(msa)); RUN(msa_sort_rank(msa)); STOP_TIMER(t1); if(!msa->quiet){ GET_TIMING(t1); } DESTROY_TIMER(t1); aln_param_free(ap); free_tasks(tasks); return OK; ERROR: if(msa->consistency_table){ anchor_consistency_free((struct consistency_table*)msa->consistency_table); msa->consistency_table = NULL; } aln_param_free(ap); free_tasks(tasks); return FAIL; } int kalign_post_realign(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, float dist_scale, float vsm_amax, int realign_iterations, float use_seq_weights) { struct aln_tasks* tasks = NULL; struct aln_param* ap = NULL; int iter; ASSERT(msa != NULL, "No MSA"); ASSERT(realign_iterations > 0, "Need at least 1 realign iteration"); /* Detect biotype if not set */ if(msa->biotype == ALN_BIOTYPE_UNDEF){ RUN(detect_alphabet(msa)); } /* seq_distances available from prior alignment */ RUN(resolve_pfasum_auto(msa, &type)); RUN(aln_param_init(&ap, msa->biotype, n_threads, type, gpo, gpe, tgpe)); ap->adaptive_budget = adaptive_budget; if(use_seq_weights >= 0.0f){ ap->use_seq_weights = use_seq_weights; } ap->dist_scale = dist_scale; if(vsm_amax >= 0.0f){ ap->vsm_amax = vsm_amax; } #ifdef HAVE_OPENMP omp_set_num_threads(n_threads); #endif DECLARE_TIMER(t1); if(!msa->quiet){ LOG_MSG("Post-realign (%d iterations, vsm_amax=%.2f)", realign_iterations, ap->vsm_amax); } START_TIMER(t1); for(iter = 0; iter < realign_iterations; iter++){ float** dm = NULL; int si; /* Finalize if not already (first iter may already be FINAL from ensemble) */ if(msa->aligned != ALN_STATUS_FINAL){ RUN(finalise_alignment(msa)); } /* Compute NxN pairwise identity distances from alignment */ RUN(compute_aln_pairwise_dist(msa, &dm)); /* Strip gap characters from seq->seq and fix seq->len. Consensus alignment may have set len to alignment length, so we recompute from the ungapped sequence. We also zero gaps[] and reset alignment status manually (rather than calling dealign_msa which uses the possibly wrong len to bound the gaps[] loop). */ for(si = 0; si < msa->numseq; si++){ struct msa_seq* seq = msa->sequences[si]; int r, w = 0; for(r = 0; seq->seq[r] != '\0'; r++){ if(seq->seq[r] != '-'){ seq->seq[w++] = seq->seq[r]; } } seq->seq[w] = '\0'; seq->len = w; /* Zero gaps array (len+1 entries) */ for(r = 0; r <= w; r++){ seq->gaps[r] = 0; } } msa->aligned = ALN_STATUS_UNALIGNED; /* Re-encode to internal representation */ if(msa->biotype == ALN_BIOTYPE_DNA){ RUN(convert_msa_to_internal(msa, ALPHA_defDNA)); }else if(msa->biotype == ALN_BIOTYPE_PROTEIN){ RUN(convert_msa_to_internal(msa, ALPHA_ambigiousPROTEIN)); } /* Reset profile tracking */ RUN(set_sip_nsip(msa)); /* Build UPGMA tree from alignment-derived distances */ if(tasks){ free_tasks(tasks); tasks = NULL; } RUN(alloc_tasks(&tasks, msa->numseq)); RUN(build_tree_from_pairwise(msa, &tasks, dm)); free_aln_dm(dm, msa->numseq); if(ap->use_seq_weights > 0.0f){ RUN(compute_tree_weights(msa, tasks)); } /* Re-align with new tree */ if(refine == KALIGN_REFINE_INLINE){ RUN(create_msa_tree_inline_refine(msa, ap, tasks, 3)); }else{ RUN(create_msa_tree(msa, ap, tasks)); } msa->aligned = ALN_STATUS_ALIGNED; } /* Refinement after all realign iterations (two-pass, skip for inline) */ if(refine != KALIGN_REFINE_NONE && refine != KALIGN_REFINE_INLINE){ RUN(refine_alignment(msa, ap, tasks, refine)); } RUN(finalise_alignment(msa)); RUN(msa_sort_rank(msa)); STOP_TIMER(t1); if(!msa->quiet){ GET_TIMING(t1); } DESTROY_TIMER(t1); aln_param_free(ap); free_tasks(tasks); return OK; ERROR: aln_param_free(ap); if(tasks) free_tasks(tasks); return FAIL; } kalign-3.5.1/lib/src/aln_wrap.h000066400000000000000000000033141515023132300162720ustar00rootroot00000000000000#ifndef ALN_WRAP_H #define ALN_WRAP_H #include #ifdef ALN_WRAP_IMPORT #define EXTERN #else #ifndef EXTERN #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif #endif struct msa; EXTERN int kalign_run(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget); EXTERN int kalign_run_seeded(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, uint64_t tree_seed, float tree_noise, float dist_scale, float vsm_amax, float use_seq_weights, int consistency_anchors, float consistency_weight); EXTERN int kalign_run_realign(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, float dist_scale, float vsm_amax, int realign_iterations, float use_seq_weights, int consistency_anchors, float consistency_weight); EXTERN int kalign_post_realign(struct msa *msa, int n_threads, int type, float gpo, float gpe, float tgpe, int refine, int adaptive_budget, float dist_scale, float vsm_amax, int realign_iterations, float use_seq_weights); #undef ALN_WRAP_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/alphabet.c000066400000000000000000000242311515023132300162430ustar00rootroot00000000000000#include "tldevel.h" #include #define ALPHABET_IMPORT #include "alphabet.h" int create_default_protein(struct alphabet* a); int create_protein_BZX(struct alphabet* a); int create_default_DNA(struct alphabet* a); int create_reduced_protein(struct alphabet *a); int create_reduced_protein2(struct alphabet* a); int clean_and_set_to_extern(struct alphabet* a); static int merge_multiple(struct alphabet*a,char* p,int n); static int merge_codes(struct alphabet*a,const int X, const int Y); #ifdef UTEST_ALPHABET int print_alphabet(struct alphabet* a); int main(void) { struct alphabet* a = NULL; RUNP(a = create_alphabet(ALPHA_defPROTEIN)); print_alphabet(a); MFREE(a); a = NULL; RUNP(a = create_alphabet(ALPHA_redPROTEIN)); print_alphabet(a); MFREE(a); RUNP(a = create_alphabet(ALPHA_defDNA)); print_alphabet(a); MFREE(a); RUNP(a = create_alphabet(ALPHA_redPROTEIN2)); print_alphabet(a); MFREE(a); return EXIT_SUCCESS; ERROR: return EXIT_FAILURE; } int print_alphabet(struct alphabet* a) { fprintf(stdout,"LEN: %d\n",a->L); int i; for(i = 64;i < 96;i++){ fprintf(stdout,"%c\t%d\n", (char)i, a->to_internal[i]); } return OK; } #endif struct alphabet* create_alphabet(int type) { struct alphabet* a = NULL; int i; MMALLOC(a, sizeof(struct alphabet)); for(i = 0; i < 128;i++){ a->to_internal[i] = -1; } for(i = 0; i < 32;i++){ a->to_external[i] = -1; } switch (type) { case ALPHA_defPROTEIN : { create_default_protein(a); break; } case ALPHA_ambigiousPROTEIN :{ create_protein_BZX(a); break; } case ALPHA_defDNA : { create_default_DNA(a); break; } case ALPHA_redPROTEIN : { create_reduced_protein(a); break; } case ALPHA_redPROTEIN2 : { create_reduced_protein2(a); break; } default: break; } RUN(clean_and_set_to_extern(a)); return a; ERROR: if(a){ MFREE(a); } return NULL; } int switch_alphabet(struct alphabet* a, int type) { int i; for(i = 0; i < 128;i++){ a->to_internal[i] = -1; } for(i = 0; i < 32;i++){ a->to_external[i] = -1; } switch (type) { case ALPHA_defPROTEIN : { create_default_protein(a); break; } case ALPHA_redPROTEIN : { create_reduced_protein(a); break; } default: break; } RUN(clean_and_set_to_extern(a)); return OK; ERROR: return FAIL; } int create_default_protein(struct alphabet* a) { char aacode[20] = "ACDEFGHIKLMNPQRSTVWY"; /* char aacode[20] = "ARNDCQEGHILKMFPSTWYV";//BZX"; */ int code; int i; code = 0; for(i = 0; i < 20;i++){ //fprintf(stdout,"%c %d CODE: %d\n", aacode[i], (int) aacode[i], code); a->to_internal[(int) aacode[i]] = code; code++; } /* ambiguity codes */ /* BZX */ a->to_internal[(int) 'B'] = code; a->to_internal[(int) 'Z'] = code; a->to_internal[(int) 'X'] = code; /* Some protein sequences contain 'U' - a non-IUPAC code I will treat these as an ambiguous aa e.g: >Q74EN2_GEOSL/108-206 TRELEALVAKGTEEGGYLLIDSRPAGKYNEAHIPTAVSIPFAELEKNPALLTASKDRLLVFYCGGVTUVLSPKSAGLAKKSGYEKVRVYLDGEPEWKKA */ a->to_internal[(int) 'U'] = code; code++; return OK; } int create_protein_BZX(struct alphabet* a) { char aacode[23] = "ARNDCQEGHILKMFPSTWYVBZX"; int code; int i; code = 0; for(i = 0; i < 23;i++){ //fprintf(stdout,"%c %d CODE: %d\n", aacode[i], (int) aacode[i], code); a->to_internal[(int) aacode[i]] = code; code++; } /* ambiguity codes */ /* Some protein sequences contain 'U' - a non-IUPAC code I will treat these as an ambiguous aa e.g: >Q74EN2_GEOSL/108-206 TRELEALVAKGTEEGGYLLIDSRPAGKYNEAHIPTAVSIPFAELEKNPALLTASKDRLLVFYCGGVTUVLSPKSAGLAKKSGYEKVRVYLDGEPEWKKA */ a->to_internal[(int) 'U'] = code-1; //code++; return OK; } int create_default_DNA(struct alphabet* a) { char dnacode[16] = "ACGTUNRYSWKMBDHV"; int code; int i; code = 0; for(i = 0; i < 16;i++){ //fprintf(stdout,"%c %d CODE: %d\n", aacode[i], (int) aacode[i], code); a->to_internal[(int) dnacode[i]] = code; code++; } merge_codes(a,'U','T'); /* R.................A or G */ /* Y.................C or T */ /* S.................G or C */ /* W.................A or T */ /* K.................G or T */ /* M.................A or C */ /* B.................C or G or T */ /* D.................A or G or T */ /* H.................A or C or T */ /* V.................A or C or G */ merge_codes(a,'N','R'); merge_codes(a,'N','Y'); merge_codes(a,'N','S'); merge_codes(a,'N','W'); merge_codes(a,'N','K'); merge_codes(a,'N','M'); merge_codes(a,'N','B'); merge_codes(a,'N','D'); merge_codes(a,'N','H'); merge_codes(a,'N','V'); return OK; } int create_reduced_protein(struct alphabet* a) { char aacode[20] = "ACDEFGHIKLMNPQRSTVWY"; int code; int i; code = 0; for(i = 0; i < 20;i++){ a->to_internal[(int) aacode[i]] = code; code++; } /* ambiguity codes */ /* BZX */ a->to_internal[(int) 'B'] = code; code++; a->to_internal[(int) 'Z'] = code; code++; a->to_internal[(int) 'X'] = code; code++; /* From Clustering huge protein sequence sets in linear time Martin Steinegger 1, 2, 3 and Johannes Söding 1 */ /* The default alphabet with A = 13 merges (L,M), (I,V), (K,R), (E, Q), (A,S,T), (N, D) and (F,Y).*/ /* reduced codes */ merge_codes(a,'L','M'); merge_codes(a,'I','V'); merge_codes(a,'K','R'); merge_codes(a,'E','Q'); merge_codes(a,'A','S'); merge_codes(a,'A','T'); merge_codes(a,'S','T'); merge_codes(a,'N','D'); merge_codes(a,'F','Y'); /* merge ambiguity codes */ merge_codes(a,'B','N'); merge_codes(a,'B','D'); merge_codes(a,'Z','E'); merge_codes(a,'Z','Q'); /* Selenocysteine (U) - map to cysteine (C) as it is structurally nearly identical (Se replaces S) */ a->to_internal[(int) 'U'] = a->to_internal[(int) 'C']; return OK; } int create_reduced_protein2(struct alphabet* a) { char aacode[20] = "ACDEFGHIKLMNPQRSTVWY"; int code; int i; code = 0; for(i = 0; i < 20;i++){ a->to_internal[(int) aacode[i]] = code; code++; } /* ambiguity codes */ /* BZX */ a->to_internal[(int) 'B'] = code; code++; a->to_internal[(int) 'Z'] = code; code++; a->to_internal[(int) 'X'] = code; code++; /* From Clustering huge protein sequence sets in linear time Martin Steinegger 1, 2, 3 and Johannes Söding 1 */ /* The default alphabet with A = 13 merges (L,M), (I,V), (K,R), (E, Q), (A,S,T), (N, D) and (F,Y).*/ /* AM DEKNQRT CFIV GHTS WLY */ /* reduced codes */ merge_codes(a,'A','M'); /* DEKNQRP */ merge_multiple(a,"DEKNQRP",7); /*CFIV*/ merge_multiple(a,"CFIV",4); /*GHTS*/ merge_multiple(a,"GHTS",4); /* WLY */ merge_multiple(a,"WLY",3); merge_multiple(a,"BZX",3); /* Selenocysteine (U) - map to cysteine (C) as it is structurally nearly identical (Se replaces S) */ a->to_internal[(int) 'U'] = a->to_internal[(int) 'C']; return OK; } int merge_multiple(struct alphabet*a,char* p,int n) { // Declaring pointer to the // argument list int min = INT32_MAX; for(int i = 0; i < n;i++){ min = MACRO_MIN(min,a->to_internal[(int)p[i]]); } for(int i = 0; i < n;i++){ a->to_internal[(int)p[i]] = min; } return OK; } int merge_codes(struct alphabet*a,const int X, const int Y) { int min; min = MACRO_MIN(a->to_internal[X],a->to_internal[Y]); ASSERT(min != -1, "code not set!"); a->to_internal[X] = min; a->to_internal[Y] = min; return OK; ERROR: return FAIL; } int clean_and_set_to_extern(struct alphabet* a) { int i; int code = 0; int8_t trans[32]; for(i = 0; i < 32;i++){ trans[i] = -1; } for(i = 64; i < 96;i++){ if(a->to_internal[i] != -1){ trans[a->to_internal[i]] = 1; } } code = 0; for(i = 0; i < 32;i++){ if(trans[i] == 1){ trans[i] = code; code++; } } a->L = code; for(i = 64; i < 96;i++){ if(a->to_internal[i] != -1){ a->to_internal[i] = trans[a->to_internal[i]];//a->to_internal[i]]; a->to_internal[i+32] = a->to_internal[i]; } } for(i = 64;i < 96;i++){ if(a->to_internal[i] != -1){ a->to_external[a->to_internal[i]] = i; } } return OK; } kalign-3.5.1/lib/src/alphabet.h000066400000000000000000000013341515023132300162470ustar00rootroot00000000000000#ifndef ALPHABET_H #define ALPHABET_H #include #ifdef ALPHABET_IMPORT #define EXTERN #else #ifndef EXTERN #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif #endif #define ALPHA_defPROTEIN 21 #define ALPHA_ambigiousPROTEIN 23 #define ALPHA_redPROTEIN 13 #define ALPHA_redPROTEIN2 8 #define ALPHA_defDNA 5 #define ALPHA_UNKNOWN 255 #define ALPHA_UNDEFINED -1 struct alphabet{ int8_t to_internal[128]; int8_t to_external[32]; int type; int L; }; EXTERN struct alphabet* create_alphabet(int type); EXTERN int switch_alphabet(struct alphabet* a, int type); #undef ALPHABET_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/anchor_consistency.c000066400000000000000000000503601515023132300203600ustar00rootroot00000000000000#include #include #include "tldevel.h" #include "msa_struct.h" #include "aln_param.h" #include "aln_struct.h" #include "aln_mem.h" #include "aln_setup.h" #include "aln_controller.h" #define ANCHOR_CONSISTENCY_IMPORT #include "anchor_consistency.h" /* Run a pairwise seq-seq alignment and extract position map. Returns map[0..len_i-1] where map[p] = position in seq_j that aligns to position p of seq_i, or -1 if gapped. */ static int pairwise_align_map(struct aln_param* ap, const uint8_t* s_i, int len_i, const uint8_t* s_j, int len_j, int** map_out) { struct aln_mem* m = NULL; int* posmap = NULL; int c, pos_a, pos_b; int swapped = 0; MMALLOC(posmap, sizeof(int) * len_i); for(c = 0; c < len_i; c++){ posmap[c] = -1; } RUN(alloc_aln_mem(&m, 256)); m->ap = ap; m->mode = ALN_MODE_FULL; m->run_parallel = 0; m->flip_threshold = 0.0F; m->flip_trial = 0; m->flip_stride = 1; m->flip_counter = 0; m->flip_mask = 0; m->margin_sum = 0.0F; m->margin_count = 0; /* Kalign requires seq1 = shorter, seq2 = longer */ if(len_i <= len_j){ m->len_a = len_i; m->len_b = len_j; m->enda = len_i; m->endb = len_j; m->seq1 = s_i; m->seq2 = s_j; swapped = 0; }else{ m->len_a = len_j; m->len_b = len_i; m->enda = len_j; m->endb = len_i; m->seq1 = s_j; m->seq2 = s_i; swapped = 1; } m->prof1 = NULL; m->prof2 = NULL; m->f[0].a = 0.0F; m->f[0].ga = -FLT_MAX; m->f[0].gb = -FLT_MAX; m->b[0].a = 0.0F; m->b[0].ga = -FLT_MAX; m->b[0].gb = -FLT_MAX; RUN(init_alnmem(m)); aln_runner(m); if(swapped){ RUN(mirror_path_n(m, len_i, len_j)); m->len_a = len_i; m->len_b = len_j; } RUN(add_gap_info_to_path_n(m)); /* Extract position map from alignment path. After add_gap_info_to_path_n: path[0] = alignment length path[c]: 0=match (both advance), 1=gap in a (b advances), 2=gap in b (a advances), 3=end */ pos_a = 0; pos_b = 0; c = 1; while(m->path[c] != 3){ if(m->path[c] == 0){ /* match: a[pos_a] aligns to b[pos_b] */ if(pos_a < len_i){ posmap[pos_a] = pos_b; } pos_a++; pos_b++; }else if(m->path[c] & 1){ /* gap in a: only b advances */ pos_b++; }else if(m->path[c] & 2){ /* gap in b: only a advances (no partner) */ if(pos_a < len_i){ posmap[pos_a] = -1; } pos_a++; } c++; } free_aln_mem(m); *map_out = posmap; return OK; ERROR: if(posmap) MFREE(posmap); if(m) free_aln_mem(m); return FAIL; } /* Select K diverse anchor sequences using farthest-first traversal on msa->seq_distances[] (per-sequence mean distance). */ static int select_anchors(struct msa* msa, int K, int* anchor_ids) { int i, k; float* min_dist = NULL; /* min distance to any selected anchor */ int N = msa->numseq; if(K > N) K = N; MMALLOC(min_dist, sizeof(float) * N); /* Pick first anchor: sequence with median seq_distances[] value. Use a simple approach: pick the one closest to the mean. */ { float sum = 0.0f; float best_diff = FLT_MAX; int best_idx = 0; for(i = 0; i < N; i++){ sum += msa->seq_distances[i]; } float mean = sum / (float)N; for(i = 0; i < N; i++){ float diff = msa->seq_distances[i] - mean; if(diff < 0) diff = -diff; if(diff < best_diff){ best_diff = diff; best_idx = i; } } anchor_ids[0] = best_idx; } /* Initialize min_dist: distance from each seq to first anchor. We use |seq_distances[i] - seq_distances[anchor]| as a proxy since we only have per-sequence mean distances, not pairwise. */ for(i = 0; i < N; i++){ float d = msa->seq_distances[i] - msa->seq_distances[anchor_ids[0]]; if(d < 0) d = -d; min_dist[i] = d; } /* Farthest-first: pick remaining K-1 anchors */ for(k = 1; k < K; k++){ float best_min = -1.0f; int best_idx = 0; for(i = 0; i < N; i++){ /* Skip already-selected anchors */ int skip = 0; for(int j = 0; j < k; j++){ if(anchor_ids[j] == i){ skip = 1; break; } } if(skip) continue; if(min_dist[i] > best_min){ best_min = min_dist[i]; best_idx = i; } } anchor_ids[k] = best_idx; /* Update min_dist with new anchor */ for(i = 0; i < N; i++){ float d = msa->seq_distances[i] - msa->seq_distances[best_idx]; if(d < 0) d = -d; if(d < min_dist[i]){ min_dist[i] = d; } } } MFREE(min_dist); return OK; ERROR: if(min_dist) MFREE(min_dist); return FAIL; } int anchor_consistency_build(struct msa* msa, struct aln_param* ap, int n_anchors, float weight, struct consistency_table** ct_out) { struct consistency_table* ct = NULL; int N = msa->numseq; int K = n_anchors; int i, k; if(K <= 0 || N < 3){ *ct_out = NULL; return OK; } if(K > N) K = N; /* Check that seq_distances are available */ if(msa->seq_distances == NULL){ *ct_out = NULL; return OK; } MMALLOC(ct, sizeof(struct consistency_table)); ct->pos_maps = NULL; ct->map_lengths = NULL; ct->anchor_ids = NULL; ct->n_anchors = K; ct->numseq = N; ct->weight = weight; MMALLOC(ct->anchor_ids, sizeof(int) * K); MMALLOC(ct->pos_maps, sizeof(int*) * N * K); MMALLOC(ct->map_lengths, sizeof(int) * N * K); for(i = 0; i < N * K; i++){ ct->pos_maps[i] = NULL; ct->map_lengths[i] = 0; } /* Select diverse anchors */ RUN(select_anchors(msa, K, ct->anchor_ids)); if(!msa->quiet){ LOG_MSG("Anchor consistency: K=%d, weight=%.1f", K, weight); } /* Build position maps: for each sequence i, for each anchor k */ for(i = 0; i < N; i++){ int len_i = msa->sequences[i]->len; for(k = 0; k < K; k++){ int ak = ct->anchor_ids[k]; ct->map_lengths[i * K + k] = len_i; if(i == ak){ /* Identity map for anchor itself */ int p; MMALLOC(ct->pos_maps[i * K + k], sizeof(int) * len_i); for(p = 0; p < len_i; p++){ ct->pos_maps[i * K + k][p] = p; } }else{ /* Pairwise alignment: seq_i vs anchor_k */ RUN(pairwise_align_map(ap, msa->sequences[i]->s, len_i, msa->sequences[ak]->s, msa->sequences[ak]->len, &ct->pos_maps[i * K + k])); } } } *ct_out = ct; return OK; ERROR: anchor_consistency_free(ct); *ct_out = NULL; return FAIL; } int anchor_consistency_get_bonus(struct consistency_table* ct, int seq_a, int len_a, int seq_b, int len_b, float** bonus_out) { float* bonus = NULL; int* inv_b = NULL; int K = ct->n_anchors; int k, i; float per_anchor_weight = ct->weight / (float)K; MMALLOC(bonus, sizeof(float) * len_a * len_b); memset(bonus, 0, sizeof(float) * len_a * len_b); /* For each anchor, build inverse map for seq_b (anchor_pos → seq_b_pos), then scan seq_a's map to accumulate bonus. O(K * (La + Lb + max_anchor_len)) */ for(k = 0; k < K; k++){ int* map_a = ct->pos_maps[seq_a * K + k]; int* map_b = ct->pos_maps[seq_b * K + k]; int anchor_len = 0; int j; if(map_a == NULL || map_b == NULL) continue; /* Determine anchor length for inverse map */ /* Find max mapped position to size the inverse map */ anchor_len = 0; for(i = 0; i < len_a; i++){ if(map_a[i] >= anchor_len) anchor_len = map_a[i] + 1; } for(j = 0; j < len_b; j++){ if(map_b[j] >= anchor_len) anchor_len = map_b[j] + 1; } if(anchor_len == 0) continue; /* Build inverse map: anchor_pos → seq_b_pos */ MMALLOC(inv_b, sizeof(int) * anchor_len); for(j = 0; j < anchor_len; j++){ inv_b[j] = -1; } for(j = 0; j < len_b; j++){ if(map_b[j] >= 0 && map_b[j] < anchor_len){ inv_b[map_b[j]] = j; } } /* Accumulate bonus */ for(i = 0; i < len_a; i++){ int ak_pos = map_a[i]; if(ak_pos >= 0 && ak_pos < anchor_len){ int bj = inv_b[ak_pos]; if(bj >= 0){ bonus[i * len_b + bj] += per_anchor_weight; } } } MFREE(inv_b); inv_b = NULL; } *bonus_out = bonus; return OK; ERROR: if(bonus) MFREE(bonus); if(inv_b) MFREE(inv_b); *bonus_out = NULL; return FAIL; } /* Compute consensus anchor positions for a profile node. For a leaf (nsip==1), positions come directly from pos_maps. For a profile (nsip>1), positions are derived by majority vote across member sequences, using gaps[] to map profile columns to ungapped positions. */ static int get_node_anchor_positions(struct consistency_table* ct, struct msa* msa, int node, int dp_len, int anchor_k, int* positions, float* confidence) { int K = ct->n_anchors; int i, c, p; if(msa->nsip[node] == 1){ /* Leaf: direct lookup from pos_maps */ int* map = ct->pos_maps[node * K + anchor_k]; int seq_len = msa->sequences[node]->len; if(map == NULL){ for(i = 0; i < dp_len; i++){ positions[i] = -1; confidence[i] = 0.0f; } return OK; } for(i = 0; i < dp_len && i < seq_len; i++){ positions[i] = map[i]; confidence[i] = (map[i] >= 0) ? 1.0f : 0.0f; } for(; i < dp_len; i++){ positions[i] = -1; confidence[i] = 0.0f; } }else{ /* Profile: consensus from member sequences */ int n_members = msa->nsip[node]; int* members = msa->sip[node]; int* col_to_ungapped = NULL; int* best_pos = NULL; int* agree_count = NULL; int* total_count = NULL; int mi, col; MMALLOC(col_to_ungapped, sizeof(int) * (dp_len + 1)); MMALLOC(best_pos, sizeof(int) * dp_len); MMALLOC(agree_count, sizeof(int) * dp_len); MMALLOC(total_count, sizeof(int) * dp_len); for(c = 0; c < dp_len; c++){ best_pos[c] = -1; agree_count[c] = 0; total_count[c] = 0; } for(mi = 0; mi < n_members; mi++){ int si = members[mi]; int* map; int seq_len; int* gaps; int apos; if(si >= ct->numseq) continue; map = ct->pos_maps[si * K + anchor_k]; if(map == NULL) continue; seq_len = msa->sequences[si]->len; gaps = msa->sequences[si]->gaps; /* Build col_to_ungapped from gaps[] */ col = 0; for(p = 0; p <= seq_len && col < dp_len; p++){ int g; for(g = 0; g < gaps[p] && col < dp_len; g++){ col_to_ungapped[col] = -1; col++; } if(p < seq_len && col < dp_len){ col_to_ungapped[col] = p; col++; } } while(col < dp_len){ col_to_ungapped[col] = -1; col++; } /* Accumulate votes for each profile column */ for(c = 0; c < dp_len; c++){ int ugp = col_to_ungapped[c]; if(ugp < 0 || ugp >= seq_len) continue; apos = map[ugp]; if(apos < 0) continue; total_count[c]++; if(best_pos[c] < 0){ best_pos[c] = apos; agree_count[c] = 1; }else if(apos == best_pos[c]){ agree_count[c]++; } } } for(c = 0; c < dp_len; c++){ if(total_count[c] > 0 && agree_count[c] > 0){ positions[c] = best_pos[c]; confidence[c] = (float)agree_count[c] / (float)total_count[c]; }else{ positions[c] = -1; confidence[c] = 0.0f; } } MFREE(col_to_ungapped); MFREE(best_pos); MFREE(agree_count); MFREE(total_count); } return OK; ERROR: return FAIL; } int anchor_consistency_get_bonus_profile(struct consistency_table* ct, struct msa* msa, int node_a, int len_a, int node_b, int len_b, float** bonus_out) { float* bonus = NULL; int* apos_a = NULL; float* conf_a = NULL; int* apos_b = NULL; float* conf_b = NULL; int* inv_b = NULL; float* inv_conf_b = NULL; int K = ct->n_anchors; int k, i, j; float per_anchor_weight = ct->weight / (float)K; MMALLOC(bonus, sizeof(float) * len_a * len_b); memset(bonus, 0, sizeof(float) * len_a * len_b); MMALLOC(apos_a, sizeof(int) * len_a); MMALLOC(conf_a, sizeof(float) * len_a); MMALLOC(apos_b, sizeof(int) * len_b); MMALLOC(conf_b, sizeof(float) * len_b); for(k = 0; k < K; k++){ int anchor_len; RUN(get_node_anchor_positions(ct, msa, node_a, len_a, k, apos_a, conf_a)); RUN(get_node_anchor_positions(ct, msa, node_b, len_b, k, apos_b, conf_b)); /* Find max anchor position to size the inverse map */ anchor_len = 0; for(i = 0; i < len_a; i++){ if(apos_a[i] >= anchor_len) anchor_len = apos_a[i] + 1; } for(j = 0; j < len_b; j++){ if(apos_b[j] >= anchor_len) anchor_len = apos_b[j] + 1; } if(anchor_len == 0) continue; /* Build inverse map: anchor_pos -> node_b DP col */ MMALLOC(inv_b, sizeof(int) * anchor_len); MMALLOC(inv_conf_b, sizeof(float) * anchor_len); for(j = 0; j < anchor_len; j++){ inv_b[j] = -1; inv_conf_b[j] = 0.0f; } for(j = 0; j < len_b; j++){ if(apos_b[j] >= 0 && apos_b[j] < anchor_len){ inv_b[apos_b[j]] = j; inv_conf_b[apos_b[j]] = conf_b[j]; } } /* Accumulate bonus */ for(i = 0; i < len_a; i++){ int ak_pos = apos_a[i]; if(ak_pos >= 0 && ak_pos < anchor_len){ int bj = inv_b[ak_pos]; if(bj >= 0){ bonus[i * len_b + bj] += per_anchor_weight * conf_a[i] * inv_conf_b[ak_pos]; } } } MFREE(inv_b); inv_b = NULL; MFREE(inv_conf_b); inv_conf_b = NULL; } MFREE(apos_a); MFREE(conf_a); MFREE(apos_b); MFREE(conf_b); *bonus_out = bonus; return OK; ERROR: if(bonus) MFREE(bonus); if(apos_a) MFREE(apos_a); if(conf_a) MFREE(conf_a); if(apos_b) MFREE(apos_b); if(conf_b) MFREE(conf_b); if(inv_b) MFREE(inv_b); if(inv_conf_b) MFREE(inv_conf_b); *bonus_out = NULL; return FAIL; } void anchor_consistency_free(struct consistency_table* ct) { if(ct){ if(ct->pos_maps){ int total = ct->numseq * ct->n_anchors; for(int i = 0; i < total; i++){ if(ct->pos_maps[i]){ MFREE(ct->pos_maps[i]); } } MFREE(ct->pos_maps); } if(ct->map_lengths) MFREE(ct->map_lengths); if(ct->anchor_ids) MFREE(ct->anchor_ids); MFREE(ct); } } kalign-3.5.1/lib/src/anchor_consistency.h000066400000000000000000000030541515023132300203630ustar00rootroot00000000000000#ifndef ANCHOR_CONSISTENCY_H #define ANCHOR_CONSISTENCY_H #ifdef ANCHOR_CONSISTENCY_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; struct aln_param; struct consistency_table { int** pos_maps; /* [seq_idx * K + anchor_slot][pos] = anchor_pos or -1 */ int* map_lengths; /* [seq_idx * K + anchor_slot] = length of seq_idx */ int* anchor_ids; /* [0..K-1] = sequence indices of anchors */ int n_anchors; /* K */ int numseq; /* N */ float weight; /* scaling factor for bonus */ }; EXTERN int anchor_consistency_build(struct msa* msa, struct aln_param* ap, int n_anchors, float weight, struct consistency_table** ct_out); EXTERN int anchor_consistency_get_bonus(struct consistency_table* ct, int seq_a, int len_a, int seq_b, int len_b, float** bonus_out); EXTERN int anchor_consistency_get_bonus_profile(struct consistency_table* ct, struct msa* msa, int node_a, int len_a, int node_b, int len_b, float** bonus_out); EXTERN void anchor_consistency_free(struct consistency_table* ct); #undef ANCHOR_CONSISTENCY_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/bisectingKmeans.c000066400000000000000000001057301515023132300175750ustar00rootroot00000000000000#include "tldevel.h" #ifdef HAVE_OPENMP #include #endif #ifdef HAVE_AVX2 #include #include #endif #include "tlrng.h" #include "bisectingKmeans.h" #include "msa_struct.h" /* #include "global.h" */ #include "task.h" #include "sequence_distance.h" #include "euclidean_dist.h" /* #include "alignment.h" */ #include "pick_anchor.h" #include "esl_stopwatch.h" struct node{ struct node* left; struct node* right; int id; }; struct kmeans_result{ int* sl; int* sr; int nl; int nr; float score; }; static struct kmeans_result* alloc_kmeans_result(int num_samples); static void free_kmeans_results(struct kmeans_result* k); struct node* upgma(float **dm,int* samples, int numseq); static struct node* alloc_node(void); static int label_internal(struct node *n, int label); static void create_tasks(struct node*n, struct aln_tasks* t); /* static void create_tasks(struct node*n, struct aln_tasks* t); */ /* static int bisecting_kmeans_serial(struct msa *msa, struct node **ret_n, float **dm, int *samples, int num_samples); */ static int bisecting_kmeans(struct msa* msa, struct node** ret_n, const float * const * dm, int* samples, int num_samples); /* static int bisecting_kmeans_parallel(struct msa* msa, struct node** ret_n, float** dm,int* samples, int num_samples); */ static int split(const float * const * dm, int *samples, int num_anchors, int num_samples, int seed_pick, struct kmeans_result **ret); static int split2(const float * const * dm,const int* samples, const int num_anchors,const int num_samples,const int seed_pick,struct kmeans_result** ret); static inline int cmp_floats(const float a, const float b); inline int cmp_floats(const float a, const float b) { const float epsilon = 1e-6; // Set a small epsilon value for tolerance if (fabsf(a - b) < epsilon) { return 0; // Numbers are equal } else if (a > b) { return 1; // First number is bigger } else { return -1; // Second number is bigger } } int build_tree_kmeans_noisy(struct msa* msa, struct aln_tasks** tasks, uint64_t seed, float noise_sigma) { struct aln_tasks* t = NULL; struct node* root = NULL; float** dm = NULL; int* samples = NULL; int* anchors = NULL; int num_anchors; int numseq; int i; ASSERT(msa != NULL, "No alignment."); t = *tasks; if(!t){ RUN(alloc_tasks(&t, msa->numseq)); } numseq = msa->numseq; DECLARE_TIMER(timer); if(!msa->quiet){ LOG_MSG("Calculating pairwise distances (noisy, seed=%lu)", (unsigned long)seed); } START_TIMER(timer); RUNP(anchors = pick_anchor(msa, &num_anchors)); RUNP(dm = d_estimation(msa, anchors, num_anchors, 0)); /* Add multiplicative Gaussian noise to distance matrix */ if(seed != 0 && noise_sigma > 0.0f){ struct rng_state* rng = NULL; rng = init_rng(seed); for(i = 0; i < numseq; i++){ for(int j = 0; j < num_anchors; j++){ double noise = tl_random_gaussian(rng, 1.0, (double)noise_sigma); if(noise < 0.1) noise = 0.1; dm[i][j] *= (float)noise; } } free_rng(rng); } STOP_TIMER(timer); if(!msa->quiet){ GET_TIMING(timer); } MFREE(anchors); MMALLOC(samples, sizeof(int) * numseq); for(i = 0; i < numseq; i++){ samples[i] = i; } START_TIMER(timer); if(!msa->quiet){ LOG_MSG("Building guide tree."); } #ifdef HAVE_OPENMP #pragma omp parallel #pragma omp single nowait #endif bisecting_kmeans(msa, &root, (const float * const *)dm, samples, numseq); STOP_TIMER(timer); if(!msa->quiet){ GET_TIMING(timer); } label_internal(root, numseq); create_tasks(root, t); /* Compute per-sequence normalized mean distance (noisy variant). */ if(msa->seq_distances == NULL){ MMALLOC(msa->seq_distances, sizeof(float) * numseq); } for(i = 0; i < numseq; i++){ float sum = 0.0f; int j; for(j = 0; j < num_anchors; j++){ sum += dm[i][j]; } float mean_dist = sum / (float)num_anchors; float seq_len = (float)msa->sequences[i]->len; msa->seq_distances[i] = (seq_len > 0.0f) ? mean_dist / seq_len : 0.0f; } MFREE(root); for(i = 0; i < numseq; i++){ #ifdef HAVE_AVX2 _mm_free(dm[i]); #else MFREE(dm[i]); #endif } MFREE(dm); DESTROY_TIMER(timer); return OK; ERROR: return FAIL; } int build_tree_kmeans(struct msa* msa, struct aln_tasks** tasks) { struct aln_tasks* t = NULL; struct node* root = NULL; float** dm = NULL; int* samples = NULL; int* anchors = NULL; int num_anchors; int numseq; int i; ASSERT(msa != NULL, "No alignment."); t = *tasks; if(!t){ RUN(alloc_tasks(&t, msa->numseq)); } numseq = msa->numseq; DECLARE_TIMER(timer); /* pick anchors . */ if(!msa->quiet){ LOG_MSG("Calculating pairwise distances"); } START_TIMER(timer); RUNP(anchors = pick_anchor(msa, &num_anchors)); RUNP(dm = d_estimation(msa, anchors, num_anchors,0));//les,int pair) STOP_TIMER(timer); if(!msa->quiet){ GET_TIMING(timer); } MFREE(anchors); MMALLOC(samples, sizeof(int)* numseq); for(i = 0; i < numseq;i++){ samples[i] = i; } START_TIMER(timer); if(!msa->quiet){ LOG_MSG("Building guide tree."); } /* if(n_threads == 1){ */ /* RUN(bisecting_kmeans_serial(msa,&root, dm, samples, numseq)); */ /* }else{ */ #ifdef HAVE_OPENMP #pragma omp parallel #pragma omp single nowait #endif bisecting_kmeans(msa,&root, (const float * const *)dm, samples, numseq); /* } */ STOP_TIMER(timer); if(!msa->quiet){ GET_TIMING(timer); } label_internal(root, numseq); create_tasks(root, t); /* Compute per-sequence normalized mean distance to anchors. Used for distance-dependent gap penalty scaling. */ if(msa->seq_distances == NULL){ MMALLOC(msa->seq_distances, sizeof(float) * numseq); } for(i = 0; i < numseq; i++){ float sum = 0.0f; int j; for(j = 0; j < num_anchors; j++){ sum += dm[i][j]; } float mean_dist = sum / (float)num_anchors; float seq_len = (float)msa->sequences[i]->len; msa->seq_distances[i] = (seq_len > 0.0f) ? mean_dist / seq_len : 0.0f; } MFREE(root); for(i = 0; i < numseq; i++){ #ifdef HAVE_AVX2 _mm_free(dm[i]); #else MFREE(dm[i]); #endif } MFREE(dm); DESTROY_TIMER(timer); return OK; ERROR: return FAIL; } int bisecting_kmeans(struct msa* msa, struct node** ret_n, const float * const * dm,int* samples, int num_samples) { struct kmeans_result* res_tmp = NULL; struct kmeans_result* best = NULL; /* struct kmeans_result** res = NULL; */ struct node* n = NULL; int num_anchors = 0; int i,j; int tries = 40; /* int t_iter; */ /* int r; */ int* sl = NULL; int* sr = NULL; int num_l,num_r; /* LOG_MSG("num_samples: %d", num_samples); */ num_anchors = MACRO_MIN(32, msa->numseq); if(num_samples < KALIGN_KMEANS_UPGMA_THRESHOLD){ float** dm = NULL; RUNP(dm = d_estimation(msa, samples, num_samples,1));// anchors, num_anchors,1)); n = upgma(dm,samples, num_samples); *ret_n = n; gfree(dm); MFREE(samples); return OK; //return n; } /* else if(num_samples < 1000){ */ /* RUN(bisecting_kmeans_serial(msa, &n, dm, samples, num_samples)); */ /* *ret_n = n; */ /* return OK; */ /* } */ best = NULL; res_tmp = NULL; struct kmeans_result* res[4]; /* MMALLOC(res, sizeof(struct kmeans_result*) * 4); */ for(i = 0; i < 4;i++){ res[i] = NULL; } tries = MACRO_MIN(tries, num_samples); int step = num_samples / tries; int change = 0; for(i = 0;i < tries;i += 4){ change = 0; #ifdef HAVE_OPENMP #pragma omp task shared(dm,samples,num_anchors, num_samples,i,step,res) #endif split2(dm,samples,num_anchors, num_samples, (i)*step, &res[0]); #ifdef HAVE_OPENMP #pragma omp task shared(dm,samples,num_anchors, num_samples,i,step,res) #endif split2(dm,samples,num_anchors, num_samples, (i+ 1)*step, &res[1]); #ifdef HAVE_OPENMP #pragma omp task shared(dm,samples,num_anchors, num_samples,i,step,res) #endif split2(dm,samples,num_anchors, num_samples, (i+ 2)*step, &res[2]); #ifdef HAVE_OPENMP #pragma omp task shared(dm,samples,num_anchors, num_samples,i,step,res) #endif split2(dm,samples,num_anchors, num_samples, (i+ 3)*step, &res[3]); #ifdef HAVE_OPENMP #pragma omp taskwait #endif for(j = 0; j < 4;j++){ if(!best){ change++; best = res[j]; res[j] = NULL; }else{ if(best->score > res[j]->score){ res_tmp = best; best = res[j]; res[j] = res_tmp; /* LOG_MSG("Better!!! %f %f", res_tmp->score,best->score); */ change++; } } } if(!change){ break; } } sl = best->sl; sr = best->sr; num_l = best->nl; num_r = best->nr; /* free_kmeans_results(res[0]); */ /* free_kmeans_results(res[1]); */ /* free_kmeans_results(res[2]); */ /* free_kmeans_results(res[3]); */ for(i = 0; i < 4;i++){ free_kmeans_results(res[i]); } /* MFREE(res); */ MFREE(best); MFREE(samples); n = alloc_node(); /* #ifdef HAVE_OPENMP */ /* #pragma omp parallel //num_threads(2) */ /* #pragma omp single nowait */ #ifdef HAVE_OPENMP #pragma omp task shared(msa,n,dm) #endif bisecting_kmeans(msa,&n->left, dm, sl, num_l); #ifdef HAVE_OPENMP #pragma omp task shared(msa,n,dm,num_anchors) #endif bisecting_kmeans(msa,&n->right, dm, sr, num_r); #ifdef HAVE_OPENMP #pragma omp taskwait #endif *ret_n =n; return OK; ERROR: return FAIL; } /* int bisecting_kmeans_serial(struct msa* msa, struct node** ret_n, float** dm,int* samples, int num_samples) */ /* { */ /* struct kmeans_result* res_tmp = NULL; */ /* struct kmeans_result* best = NULL; */ /* struct kmeans_result** res_ptr = NULL; */ /* int num_anchors = 0; */ /* struct node* n = NULL; */ /* int i,j; */ /* int tries = 40; */ /* /\* int t_iter; *\/ */ /* /\* int r; *\/ */ /* int* sl = NULL; */ /* int* sr = NULL; */ /* int num_l,num_r; */ /* num_anchors = MACRO_MIN(32, msa->numseq); */ /* if(num_samples < KALIGN_KMEANS_UPGMA_THRESHOLD){ */ /* float** dm = NULL; */ /* RUNP(dm = d_estimation(msa, samples, num_samples,1));// anchors, num_anchors,1)); */ /* n = upgma(dm,samples, num_samples); */ /* *ret_n = n; */ /* gfree(dm); */ /* MFREE(samples); */ /* return OK; */ /* } */ /* best = NULL; */ /* res_tmp = NULL; */ /* MMALLOC(res_ptr, sizeof(struct kmeans_result*) * 4); */ /* for(i = 0; i < 4;i++){ */ /* res_ptr[i] = NULL; */ /* } */ /* tries = MACRO_MIN(tries, num_samples); */ /* int step = num_samples / tries; */ /* int change = 0; */ /* for(i = 0;i < tries;i += 4){ */ /* change = 0; */ /* for(j = 0; j < 4;j++){ */ /* split(dm,samples,num_anchors, num_samples, (i+ j)*step, &res_ptr[j]); */ /* } */ /* for(j = 0; j < 4;j++){ */ /* if(!best){ */ /* change++; */ /* best = res_ptr[j]; */ /* res_ptr[j] = NULL; */ /* }else{ */ /* if(best->score > res_ptr[j]->score){ */ /* res_tmp = best; */ /* best = res_ptr[j]; */ /* res_ptr[j] = res_tmp; */ /* /\* LOG_MSG("Better!!! %f %f", res_tmp->score,best->score); *\/ */ /* change++; */ /* } */ /* } */ /* } */ /* if(!change){ */ /* break; */ /* } */ /* } */ /* sl = best->sl; */ /* sr = best->sr; */ /* num_l = best->nl; */ /* num_r = best->nr; */ /* for(i = 0; i < 4;i++){ */ /* free_kmeans_results(res_ptr[i]); */ /* } */ /* MFREE(res_ptr); */ /* MFREE(best); */ /* MFREE(samples); */ /* n = alloc_node(); */ /* bisecting_kmeans_serial(msa,&n->left , dm, sl, num_l); */ /* bisecting_kmeans_serial(msa,&n->right, dm, sr, num_r); */ /* *ret_n = n; */ /* return OK; */ /* ERROR: */ /* return FAIL; */ /* } */ int split(const float * const * dm,int* samples, int num_anchors,int num_samples,int seed_pick,struct kmeans_result** ret) { struct kmeans_result* res = NULL; int* sl = NULL; int* sr = NULL; int num_l,num_r; float* w = NULL; float* wl = NULL; float* wr = NULL; float* cl = NULL; float* cr = NULL; float dl = 0.0F; float dr = 0.0F; float score; int num_var; int i; int s; int j; int stop = 0; num_var = num_anchors / 8; if( num_anchors%8){ num_var++; } num_var = num_var << 3; #ifdef HAVE_AVX2 wr = _mm_malloc(sizeof(float) * num_var,32); wl = _mm_malloc(sizeof(float) * num_var,32); cr = _mm_malloc(sizeof(float) * num_var,32); cl = _mm_malloc(sizeof(float) * num_var,32); w = _mm_malloc(sizeof(float) * num_var,32); #else MMALLOC(wr,sizeof(float) * num_var); MMALLOC(wl,sizeof(float) * num_var); MMALLOC(cr,sizeof(float) * num_var); MMALLOC(cl,sizeof(float) * num_var); MMALLOC(w,sizeof(float) * num_var); #endif if(*ret){ res = *ret; }else{ RUNP(res = alloc_kmeans_result(num_samples)); } res->score = FLT_MAX; sl = res->sl; sr = res->sr; for(i = 0; i < num_var;i++){ w[i] = 0.0F; wr[i] = 0.0F; wl[i] = 0.0F; cr[i] = 0.0F; cl[i] = 0.0F; } for(i = 0; i < num_samples;i++){ s = samples[i]; for(j = 0; j < num_anchors;j++){ w[j] += dm[s][j]; } } for(j = 0; j < num_anchors;j++){ w[j] /= (float)num_samples; } //r = tl_random_int(rng , num_samples); //r = sel[t_iter]; s = samples[seed_pick]; /* LOG_MSG("Selected %d\n",s); */ for(j = 0; j < num_anchors;j++){ cl[j] = dm[s][j]; } for(j = 0; j < num_anchors;j++){ cr[j] = w[j] - (cl[j] - w[j]); fprintf(stdout,"BEGIN: %e %e diff::: %f %f\n", cl[j],cr[j], cl[j]-cr[j],w[j]); } #ifdef HAVE_AVX2 _mm_free(w); #else MFREE(w); #endif /* check if cr == cl - we have identical sequences */ s = 0; for(j = 0; j < num_anchors;j++){ int res = cmp_floats(cl[j],cr[j]); /* if(fabsf(cl[j]-cr[j]) > 1.0E-6){ */ /* s = 1; */ /* break; */ /* } */ if(res != 0){ s++; } } fprintf(stdout,"S: %d\n",s); s = 0; for(j = 0; j < num_anchors;j++){ /* int res = cmp_floats(dr,dl); */ if(fabsf(cl[j]-cr[j]) > 1.0E-6){ s++; //break; } /* if(res != 0){ */ /* s++; */ /* } */ } fprintf(stdout,"S: %d\n",s); #ifdef HAVE_AVX2 edist_256(cl,cr, num_anchors, &dr); #else edist_serial(cl, cr, num_anchors, &dr); #endif fprintf(stdout,"R/L Dist: %e %e %d\n",dr,1e-6, dr < 1e-6); cmp_floats(cl[j],cr[j]); if(!s){ score = 0.0F; num_l = 0; num_r = 0; /* The code below caused sequence sets of size 1 to be passed to clustering... */ /* sl[num_l] = samples[0]; */ /* num_l++; */ /* for(i =1 ; i nl = num_l; res->nr = num_r; res->score = score; *ret = res; return OK; ERROR: return FAIL; } int split2(const float * const * dm,const int* samples, const int num_anchors,const int num_samples,const int seed_pick,struct kmeans_result** ret) { struct kmeans_result* res = NULL; int* sl = NULL; int* sr = NULL; int num_l,num_r; float* w = NULL; float* wl = NULL; float* wr = NULL; float* cl = NULL; float* cr = NULL; float dl = 0.0F; float dr = 0.0F; float score; int num_var; int i; int s; int j; num_var = num_anchors / 8; if( num_anchors%8){ num_var++; } num_var = num_var << 3; #ifdef HAVE_AVX2 wr = _mm_malloc(sizeof(float) * num_var,32); wl = _mm_malloc(sizeof(float) * num_var,32); cr = _mm_malloc(sizeof(float) * num_var,32); cl = _mm_malloc(sizeof(float) * num_var,32); w = _mm_malloc(sizeof(float) * num_var,32); #else MMALLOC(wr,sizeof(float) * num_var); MMALLOC(wl,sizeof(float) * num_var); MMALLOC(cr,sizeof(float) * num_var); MMALLOC(cl,sizeof(float) * num_var); MMALLOC(w,sizeof(float) * num_var); #endif if(*ret){ res = *ret; }else{ RUNP(res = alloc_kmeans_result(num_samples)); } res->score = FLT_MAX; sl = res->sl; sr = res->sr; for(i = 0; i < num_var;i++){ w[i] = 0.0F; wr[i] = 0.0F; wl[i] = 0.0F; cr[i] = 0.0F; cl[i] = 0.0F; } for(i = 0; i < num_samples;i++){ s = samples[i]; for(j = 0; j < num_anchors;j++){ w[j] += dm[s][j]; } } for(j = 0; j < num_anchors;j++){ w[j] /= (float)num_samples; } //r = tl_random_int(rng , num_samples); //r = sel[t_iter]; s = samples[seed_pick]; /* LOG_MSG("Selected %d\n",s); */ for(j = 0; j < num_anchors;j++){ cl[j] = dm[s][j]; } for(j = 0; j < num_anchors;j++){ cr[j] = w[j] - (cl[j] - w[j]); } #ifdef HAVE_AVX2 _mm_free(w); #else MFREE(w); #endif w = NULL; for(int stop = 0; stop < 500; stop++){ num_l = 0; num_r = 0; for(i = 0; i < num_anchors;i++){ wr[i] = 0.0F; wl[i] = 0.0F; } score = 0.0f; for(i = 0; i < num_samples;i++){ s = samples[i]; #ifdef HAVE_AVX2 edist_256(dm[s], cl, num_anchors, &dl); edist_256(dm[s], cr, num_anchors, &dr); #else edist_serial(dm[s], cl, num_anchors, &dl); edist_serial(dm[s], cr, num_anchors, &dr); #endif score += MACRO_MIN(dl,dr); int res = cmp_floats(dr,dl); if(res == -1){ w = wr; sr[num_r] = s; num_r++; }else if (res == 1){ w = wl; sl[num_l] = s; num_l++; }else{ if(i & 1){ w = wr; sr[num_r] = s; num_r++; }else{ w = wl; sl[num_l] = s; num_l++; } } for(j = 0; j < num_anchors;j++){ w[j] += dm[s][j]; } } if(num_l == 0 || num_r == 0){ score = 0.0F; num_l = 0; num_r = 0; for(i = 0; i < num_samples/2;i++){ sl[num_l] = samples[i]; num_l++; } for(i = num_samples/2; i < num_samples;i++){ sr[num_r] = samples[i]; num_r++; } break; } for(j = 0; j < num_anchors;j++){ wl[j] /= (float)num_l; wr[j] /= (float)num_r; } s = 0; for(j = 0; j < num_anchors;j++){ int res = cmp_floats(wl[j],cl[j]); if(res != 0){ s = 1; break; } res = cmp_floats(wr[j],cr[j]); if(res != 0){ s = 1; break; } } if(s){ w = cl; cl = wl; wl = w; w = cr; cr = wr; wr = w; }else{ break; } } #ifdef HAVE_AVX2 _mm_free(wr); _mm_free(wl); _mm_free(cr); _mm_free(cl); #else MFREE(wr); MFREE(wl); MFREE(cr); MFREE(cl); #endif res->nl = num_l; res->nr = num_r; res->score = score; *ret = res; return OK; ERROR: return FAIL; } struct node* upgma(float **dm,int* samples, int numseq) { struct node** tree = NULL; struct node* tmp = NULL; int i,j; int *as = NULL; float max; int node_a = 0; int node_b = 0; int cnode = numseq; int numprofiles; numprofiles = (numseq << 1) - 1; MMALLOC(as,sizeof(int)*numseq); for (i = numseq; i--;){ as[i] = i+1; } MMALLOC(tree,sizeof(struct node*)*numseq); for (i = 0;i < numseq;i++){ tree[i] = NULL; tree[i] = alloc_node(); tree[i]->id = samples[i]; } while (cnode != numprofiles){ max = FLT_MAX; for (i = 0;i < numseq-1; i++){ if (as[i]){ for ( j = i + 1;j < numseq;j++){ if (as[j]){ if (dm[i][j] < max){ max = dm[i][j]; node_a = i; node_b = j; } } } } } tmp = NULL; tmp = alloc_node(); tmp->left = tree[node_a]; tmp->right = tree[node_b]; tree[node_a] = tmp; tree[node_b] = NULL; /*deactivate sequences to be joined*/ as[node_a] = cnode+1; as[node_b] = 0; cnode++; /*calculate new distances*/ for (j = numseq;j--;){ if (j != node_b){ dm[node_a][j] = (dm[node_a][j] + dm[node_b][j])*0.5F + 0.001F; } //fprintf(stdout,"\n"); } dm[node_a][node_a] = 0.0F; for (j = numseq;j--;){ dm[j][node_a] = dm[node_a][j]; } } tmp = tree[node_a]; MFREE(tree); MFREE(as); return tmp; ERROR: return NULL; } struct node* alloc_node(void) { struct node* n = NULL; MMALLOC(n, sizeof(struct node)); n->left = NULL; n->right = NULL; n->id = -1; return n; ERROR: return NULL; } int label_internal(struct node*n, int label) { //n->d = d; if(n->left){ label = label_internal(n->left, label); } if(n->right){ label = label_internal(n->right, label); } if(n->id == -1){ n->id = label; label++; } return label; } void create_tasks(struct node*n, struct aln_tasks* t) { if(n->left && n->right){ struct task* task; task = t->list[t->n_tasks]; task->a = n->left->id; task->b = n->right->id; task->c = n->id; /* task->p = depth; */ /* task->p = n->d; */ /* task->n = n->n; */ /* fprintf(stdout,"Node %d depends on %d %d\n", n->id , n->left->id, n->right->id); */ t->n_tasks++; } if(n->left){ create_tasks(n->left,t); } if(n->right){ create_tasks(n->right,t); } if(n->left){ if(n->right){ MFREE(n->left); MFREE(n->right); } } } struct kmeans_result* alloc_kmeans_result(int num_samples) { struct kmeans_result* k = NULL; ASSERT(num_samples != 0, "No samples???"); MMALLOC(k, sizeof(struct kmeans_result)); k->nl = 0; k->nr = 0; k->sl = NULL; k->sr = NULL; MMALLOC(k->sl, sizeof(int) * num_samples); MMALLOC(k->sr, sizeof(int) * num_samples); k->score = FLT_MAX; return k; ERROR: free_kmeans_results(k); return NULL; } void free_kmeans_results(struct kmeans_result* k) { if(k){ if(k->sl){ MFREE(k->sl); } if(k->sr){ MFREE(k->sr); } MFREE(k); } } int build_tree_from_pairwise(struct msa* msa, struct aln_tasks** tasks, float** dm) { struct aln_tasks* t = NULL; struct node* root = NULL; int* samples = NULL; int numseq; int i, j; ASSERT(msa != NULL, "No alignment."); ASSERT(dm != NULL, "No distance matrix."); t = *tasks; if(!t){ RUN(alloc_tasks(&t, msa->numseq)); } numseq = msa->numseq; /* Compute per-sequence mean pairwise distance (for gap/VSM scaling). Must be done BEFORE upgma() which modifies dm in place. */ if(msa->seq_distances == NULL){ MMALLOC(msa->seq_distances, sizeof(float) * numseq); } for(i = 0; i < numseq; i++){ float sum = 0.0f; for(j = 0; j < numseq; j++){ if(j != i) sum += dm[i][j]; } msa->seq_distances[i] = (numseq > 1) ? sum / (float)(numseq - 1) : 0.0f; } MMALLOC(samples, sizeof(int) * numseq); for(i = 0; i < numseq; i++){ samples[i] = i; } /* Build UPGMA tree from pairwise distances. Note: upgma() modifies dm in-place. */ root = upgma(dm, samples, numseq); ASSERT(root != NULL, "UPGMA tree construction failed."); label_internal(root, numseq); create_tasks(root, t); MFREE(samples); MFREE(root); *tasks = t; return OK; ERROR: if(samples) MFREE(samples); return FAIL; } kalign-3.5.1/lib/src/bisectingKmeans.h000066400000000000000000000013541515023132300175770ustar00rootroot00000000000000#ifndef BISECTINGKMEANS_H #define BISECTINGKMEANS_H #include #ifdef BISECTINGKMEANS_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct aln_tasks; struct msa; /* int build_tree_kmeans(struct msa* msa, struct aln_param* ap,struct aln_tasks** task_list); */ EXTERN int build_tree_kmeans(struct msa* msa, struct aln_tasks** tasks); EXTERN int build_tree_kmeans_noisy(struct msa* msa, struct aln_tasks** tasks, uint64_t seed, float noise_sigma); EXTERN int build_tree_from_pairwise(struct msa* msa, struct aln_tasks** tasks, float** dm); #undef BISECTINGKMEANS_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/bpm.c000066400000000000000000000464611515023132300152520ustar00rootroot00000000000000#include #include #include #include "tldevel.h" #define BPM_IMPORT #include "bpm.h" #include #include #define SIGMA 13 #define DIV_CEIL(a,b) (a == 0 ? 1 : a/b+(a%b == 0 ? 0 : 1)) #ifdef HAVE_AVX2 #include __m256i BROADCAST_MASK[16]; void bitShiftLeft256ymm (__m256i *data, int count); __m256i bitShiftRight256ymm (__m256i *data, int count); /* taken from Alexander Yee: http://www.numberworld.org/y-cruncher/internals/addition.html#ks_add */ __m256i add256(uint32_t carry, __m256i A, __m256i B); #endif uint8_t dyn_256(const uint8_t* t,const uint8_t* p,int n,int m) { uint8_t* prev = NULL; uint8_t* cur = NULL; uint8_t* tmp = NULL; int i,j,c; if(m > 255){ m = 255; } MMALLOC(prev, sizeof(uint8_t)* 257); MMALLOC(cur, sizeof(uint8_t)* 257); cur[0] = 0; //fprintf(stdout,"%d ", cur[0]); for(j = 1; j <= m;j++){ cur[j] = cur[j-1] +1; //fprintf(stdout,"%d ", cur[j]); } //fprintf(stdout,"\n"); tmp = cur; cur = prev; prev = tmp; for(i = 1; i <= n;i++){ cur[0] = prev[0] ; //fprintf(stdout,"%d ", cur[0]); for(j = 1; j < m;j++){ c = 1; if(t[i-1] == p[j-1]){ c = 0; } cur[j] = prev[j-1] +c ; cur[j] = MACRO_MIN(cur[j], prev[j]+1); cur[j] = MACRO_MIN(cur[j], cur[j-1]+1); } j = m; c = 1; if(t[i-1] == p[j-1]){ c = 0; } cur[j] = prev[j-1] +c ; cur[j] = MACRO_MIN(cur[j], prev[j]); cur[j] = MACRO_MIN(cur[j], cur[j-1]+1); //fprintf(stdout,"\n"); tmp = cur; cur = prev; prev = tmp; } c = prev[m]; MFREE(prev); MFREE(cur); return c; ERROR: return 255; } uint8_t bpm(const uint8_t* t,const uint8_t* p,int n,int m) { register uint64_t VP,VN,D0,HN,HP,X; register uint64_t i;//,c; uint64_t MASK = 0; int64_t diff; uint64_t B[13]; int8_t k; if(m > 63){ m = 63; } diff = m; k = m; for(i = 0; i < 13;i++){ B[i] = 0; } for(i = 0; i < (uint64_t)m;i++){ B[p[i]] |= (1ul << i); } VP = (1ul << (m))-1 ; VN = 0ul; m--; MASK = 1ul << (m); //fprintf(stdout,"BEGINNING\t%lu %lu\n",VN,VP); for(i = 0; i < (uint64_t) n;i++){ // fprintf(stdout,"%lu:\t",i); X = (B[t[i]] | VN); //fprintf(stdout,"%lu ", X); D0 = ((VP+(X&VP)) ^ VP) | X ; //fprintf(stdout,"%lu ", D0); HN = VP & D0; //fprintf(stdout,"%lu ", HN); HP = VN | (~(VP | D0)); //fprintf(stdout,"%lu ", HP); X = HP << 1ul; //fprintf(stdout,"%lu ", X); VN = X & D0; //fprintf(stdout,"%lu ", VN); VP = (HN << 1ul) | (~(X | D0)); //fprintf(stdout,"%lu ", VP); diff += (HP & MASK)? 1 : 0;// >> m; diff -= (HN & MASK)? 1 : 0;// >> m; if(diff < k){ k = diff; } //fprintf(stdout,"%lu ", diff); //fprintf(stdout,"\n"); } return k; } #ifdef HAVE_AVX2 uint8_t bpm_256(const uint8_t* t,const uint8_t* p,int n,int m) { __m256i VP,VN,D0,HN,HP,X,NOTONE; __m256i xmm1,xmm2; __m256i MASK; __m256i B[13]; int i,j, k,diff; alignas(32) uint32_t f[13][8]; //int ALIGNED_(64) f[8]; if(m > 255){ m = 255; } for(i = 0; i < 13;i++){ for(j = 0;j < 8;j++){ f[i][j] =0u; } } for(i = 0; i < m;i++){ f[p[i]][i/32] |= (1 << (i % 32)); } /* for(i = 0; i < 13;i++){ */ /* B[i] = _mm256_load_si256((__m256i const*) &f[i]); */ /* } */ B[0] = _mm256_load_si256((__m256i const*) &f[0]); B[1] = _mm256_load_si256((__m256i const*) &f[1]); B[2] = _mm256_load_si256((__m256i const*) &f[2]); B[3] = _mm256_load_si256((__m256i const*) &f[3]); B[4] = _mm256_load_si256((__m256i const*) &f[4]); B[5] = _mm256_load_si256((__m256i const*) &f[5]); B[6] = _mm256_load_si256((__m256i const*) &f[6]); B[7] = _mm256_load_si256((__m256i const*) &f[7]); B[8] = _mm256_load_si256((__m256i const*) &f[8]); B[9] = _mm256_load_si256((__m256i const*) &f[9]); B[10] = _mm256_load_si256((__m256i const*) &f[10]); B[11] = _mm256_load_si256((__m256i const*) &f[11]); B[12] = _mm256_load_si256((__m256i const*) &f[12]); diff = m; k = m; VP = _mm256_set1_epi64x(0xFFFFFFFFFFFFFFFFul); VN = _mm256_setzero_si256(); NOTONE = _mm256_set1_epi64x(0xFFFFFFFFFFFFFFFFul); MASK = _mm256_set_epi64x (0ul,0ul,0ul,1); m--; i = m / 64; while(i){ bitShiftLeft256ymm(&MASK,64); i--; } bitShiftLeft256ymm(&MASK,m%64); for(i = 0; i < n ;i++){ //X = (B[(int) *t] | VN); X = _mm256_or_si256(B[t[i]], VN); //fprintf(stdout,"%lu ", X); //D0 = ((VP+(X&VP)) ^ VP) | X ; //print_256(X); xmm1 = _mm256_and_si256(X, VP); xmm2 = add256(0, VP, xmm1); //xmm2 = _mm256_add_epi64(VP, xmm1); xmm1 = _mm256_xor_si256(xmm2, VP); D0 = _mm256_or_si256(xmm1, X); //print_256(D0); //HN = VP & D0; HN =_mm256_and_si256(VP, D0); //print_256(HN); //HP = VN | ~(VP | D0); xmm1 = _mm256_or_si256(VP, D0); xmm2 = _mm256_andnot_si256(xmm1, NOTONE); HP = _mm256_or_si256(VN, xmm2); //print_256(HP); //X = HP << 1ul; X = HP; bitShiftLeft256ymm(&X, 1); //print_256(X); //VN = X & D0; VN= _mm256_and_si256(X, D0); //print_256(VN); //VP = (HN << 1ul) | ~(X | D0); xmm1 = HN; bitShiftLeft256ymm(&xmm1, 1); xmm2 = _mm256_or_si256(X, D0); xmm2 = _mm256_andnot_si256(xmm2, NOTONE); //xmm2 = _mm_andnot_si128 (xmm2,NOTONE); VP = _mm256_or_si256(xmm1, xmm2); //print_256(VP); //diff += (HP & MASK) >> m; diff += 1- _mm256_testz_si256(HP, MASK); ///diff -= (HN & MASK) >> m; diff -= 1- _mm256_testz_si256(HN,MASK); //fprintf(stdout,"%d ",diff); //xmm1 = _mm256_cmpgt_epi64(K, diff); k = MACRO_MIN(k, diff); } return k; } /* Must be called before BPM_256 is!!! */ void set_broadcast_mask(void) { BROADCAST_MASK[0] = _mm256_set_epi64x(0x8000000000000000, 0x8000000000000000, 0x8000000000000000, 0x8000000000000000); BROADCAST_MASK[1] = _mm256_set_epi64x(0x8000000000000000, 0x8000000000000000, 0x8000000000000000, 0x8000000000000001); BROADCAST_MASK[2] = _mm256_set_epi64x(0x8000000000000000, 0x8000000000000000, 0x8000000000000001, 0x8000000000000000); BROADCAST_MASK[3] = _mm256_set_epi64x(0x8000000000000000, 0x8000000000000000, 0x8000000000000001, 0x8000000000000001); BROADCAST_MASK[4] = _mm256_set_epi64x(0x8000000000000000, 0x8000000000000001, 0x8000000000000000, 0x8000000000000000); BROADCAST_MASK[5] = _mm256_set_epi64x(0x8000000000000000, 0x8000000000000001, 0x8000000000000000, 0x8000000000000001); BROADCAST_MASK[6] = _mm256_set_epi64x(0x8000000000000000, 0x8000000000000001, 0x8000000000000001, 0x8000000000000000); BROADCAST_MASK[7] = _mm256_set_epi64x(0x8000000000000000, 0x8000000000000001, 0x8000000000000001, 0x8000000000000001); BROADCAST_MASK[8] = _mm256_set_epi64x(0x8000000000000001, 0x8000000000000000, 0x8000000000000000, 0x8000000000000000); BROADCAST_MASK[9] = _mm256_set_epi64x(0x8000000000000001, 0x8000000000000000, 0x8000000000000000, 0x8000000000000001); BROADCAST_MASK[10] = _mm256_set_epi64x(0x8000000000000001, 0x8000000000000000, 0x8000000000000001, 0x8000000000000000); BROADCAST_MASK[11] = _mm256_set_epi64x(0x8000000000000001, 0x8000000000000000, 0x8000000000000001, 0x8000000000000001); BROADCAST_MASK[12] = _mm256_set_epi64x(0x8000000000000001, 0x8000000000000001, 0x8000000000000000, 0x8000000000000000); BROADCAST_MASK[13] = _mm256_set_epi64x(0x8000000000000001, 0x8000000000000001, 0x8000000000000000, 0x8000000000000001); BROADCAST_MASK[14] = _mm256_set_epi64x(0x8000000000000001, 0x8000000000000001, 0x8000000000000001, 0x8000000000000000); BROADCAST_MASK[15] = _mm256_set_epi64x(0x8000000000000001, 0x8000000000000001, 0x8000000000000001, 0x8000000000000001); } __m256i add256(uint32_t carry, __m256i A, __m256i B) { A = _mm256_xor_si256(A, _mm256_set1_epi64x(0x8000000000000000)); __m256i s = _mm256_add_epi64(A, B); __m256i cv = _mm256_cmpgt_epi64(A, s); __m256i mv = _mm256_cmpeq_epi64(s, _mm256_set1_epi64x(0x7fffffffffffffff)); uint32_t c = _mm256_movemask_pd(_mm256_castsi256_pd(cv)); uint32_t m = _mm256_movemask_pd(_mm256_castsi256_pd(mv)); { c = m + 2*c; // lea carry += c; m ^= carry; carry >>= 4; m &= 0x0f; } return _mm256_add_epi64(s, BROADCAST_MASK[m]); } //---------------------------------------------------------------------------- // bit shift left a 256-bit value using ymm registers // __m256i *data - data to shift // int count - number of bits to shift // return: __m256i - carry out bit(s) void bitShiftLeft256ymm (__m256i *data, int count) { __m256i innerCarry, rotate; innerCarry = _mm256_srli_epi64 (*data, 64 - count); // carry outs in bit 0 of each qword rotate = _mm256_permute4x64_epi64 (innerCarry, 0x93); // rotate ymm left 64 bits innerCarry = _mm256_blend_epi32 (_mm256_setzero_si256 (), rotate, 0xFC); // clear lower qword *data = _mm256_slli_epi64 (*data, count); // shift all qwords left *data = _mm256_or_si256 (*data, innerCarry); // propagate carrys from low qwords //carryOut = _mm256_xor_si256 (innerCarry, rotate); // clear all except lower qword //return carryOut; } __m256i bitShiftRight256ymm (__m256i *data, int count) { __m256i innerCarry, carryOut, rotate; innerCarry = _mm256_slli_epi64(*data, 64 - count); rotate = _mm256_permute4x64_epi64 (innerCarry, 0x39); innerCarry = _mm256_blend_epi32 (_mm256_setzero_si256 (), rotate, 0x3F); *data = _mm256_srli_epi64(*data, count); *data = _mm256_or_si256(*data, innerCarry); carryOut = _mm256_xor_si256 (innerCarry, rotate); //FIXME: not sure if this is correct!!! return carryOut; } #endif int bpm_block(const uint8_t *t, const uint8_t *p, int n, int m) { int32_t w; int32_t w_bytes; int32_t b_max; int32_t maxd; int32_t k; int32_t W; uint64_t HIGH_BIT; uint64_t ONE = 1; if(m > 1024){ m = 1024; } w_bytes = sizeof(uint64_t); w = w_bytes * 8; b_max = DIV_CEIL(m,w); HIGH_BIT = ONE << (w - 1); W = w * b_max - m; k = m; maxd = m; /* Precompute */ uint64_t Peq[13][16] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; uint64_t P[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint64_t M[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int32_t score[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* m = 1024; *- > 16 */ /* w_bytes = sizeof(uint64_t); */ /* w = w_bytes * 8; */ /* b_max = DIV_CEIL(m,w); */ /* LOG_MSG("%d -> %d",m,b_max); */ /* W = w * b_max - m; */ HIGH_BIT = ONE << (w - 1); /* MMALLOC(score,b_max * sizeof(int32_t)); */ /* MMALLOC(P ,b_max * w_bytes); */ /* MMALLOC(M ,b_max * w_bytes); */ /* MMALLOC(Peq,SIGMA * sizeof(uint64_t *)); */ for (int c = 0; c < SIGMA; c++) { /* Peq[c] = NULL; */ /* MMALLOC(Peq[c], b_max*w_bytes); */ /* Peq[c] = (uint64_t *) malloc(b_max*w_bytes); */ /* memset(Peq[c], 0, b_max*w_bytes); */ for (int32_t block = 0; block < b_max; block++) { uint64_t bitPos = (uint64_t) 1; for (int32_t i = block * w; i < (block + 1) * w; ++i) { // fill the remainder after the last block with 1 (>m matches anything) if (i >= m || p[i] == c) { Peq[c][block] |= bitPos; } /* if (i >= m ){ */ /* LOG_MSG("Am filling %d",i); */ /* } */ bitPos <<= 1; } } } int y = DIV_CEIL(maxd, w) - 1; /* 256 is max edit distance */ /* init blocks */ for (int b = 0; b <= y; b++) { /* bpm_init_block(s,b); */ P[b] = (uint64_t) -1;//Ones M[b] = 0; score[b] = (uint32_t)(b + 1) * w; } for (int i = 0; i < n+W; i++) { /* LOG_MSG(" (%d)",i); */ uint8_t c = 0; if(i >= n){ /* seq padding */ c = 0; }else{ c = (uint8_t)t[i]; } /* LOG_MSG(" c: %d (%d)", c,i); */ int carry = 0; for (int b = 0; b <= y; b++) { /* LOG_MSG("y: %d c: %d b: %d n: %d m:%d",y, c,b,n,m); */ uint64_t Pv = P[b]; uint64_t Mv = M[b]; uint64_t Eq = Peq[c][b]; uint64_t Xv, Xh; uint64_t Ph, Mh; int hIn = carry; int h_out = 0; Xv = Eq | Mv; if (hIn < 0) { Eq |= ONE; } Xh = (((Eq & Pv) + Pv) ^ Pv) | Eq; Ph = Mv | (~(Xh | Pv)); Mh = Pv & Xh; if (Ph & HIGH_BIT) { h_out += 1; } if (Mh & HIGH_BIT) { h_out -= 1; } Ph <<= 1; Mh <<= 1; if (hIn < 0) { Mh |= ONE; } else if (hIn > 0) { Ph |= ONE; } Pv = Mh | (~(Xv | Ph)); Mv = Ph & Xv; P[b] = Pv; M[b] = Mv; carry = h_out; score[b] += carry; } if ((score[y] - carry <= maxd) && (y < (b_max - 1)) && ((Peq[c][y + 1] & ONE) || (carry < 0))) { y += 1; /* bpm_init_block(s,y); */ P[y] = (uint64_t) -1;//Ones M[y] = 0; int b = y; uint64_t Pv = P[b]; uint64_t Mv = M[b]; uint64_t Eq = Peq[c][b]; uint64_t Xv, Xh; uint64_t Ph, Mh; int hIn = carry; int h_out = 0; Xv = Eq | Mv; if (hIn < 0) { Eq |= ONE; } Xh = (((Eq & Pv) + Pv) ^ Pv) | Eq; Ph = Mv | (~(Xh | Pv)); Mh = Pv & Xh; if (Ph & HIGH_BIT) { h_out += 1; } if (Mh & HIGH_BIT) { h_out -= 1; } Ph <<= 1; Mh <<= 1; if (hIn < 0) { Mh |= ONE; } else if (hIn > 0) { Ph |= ONE; } Pv = Mh | (~(Xv | Ph)); Mv = Ph & Xv; P[b] = Pv; M[b] = Mv; /* carry = h_out; */ score[y] = score[y - 1] + w - carry + h_out;//advanceBlock(s,y, c, carry); } else { while (score[y] >= (maxd + w)) { if (y == 0) break; y -= 1; /* LOG_MSG("y in loop: %d", y); */ } } if(score[y] < k){ /* LOG_MSG("%d", s->score[y]); */ k = score[y]; } /* if (y == (b_max - 1) && s->score[y] <= maxd) { */ /* assert(i - s->W >= 0); */ /* /\* result->push_front(SearchResult(score[y], (uint32_t)(i - W))); *\/ */ /* } */ } return k; } kalign-3.5.1/lib/src/bpm.h000066400000000000000000000015641515023132300152520ustar00rootroot00000000000000#ifndef BPM_H #define BPM_H #include #ifdef BPM_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif /* #ifdef HAVE_AVX2 */ /* #define BPM(a,b,len_a,len_b) bpm_256(a,b,len_a,len_b) */ /* #else */ #define BPM(a,b,len_a,len_b) bpm_block(a,b,len_a,len_b) /* #endif */ /* #define LOG_MSG(...) do { \ */ /* log_message( __VA_ARGS__ ); \ */ /* }while (0) */ /* Must be called before bpm_256!!!! */ EXTERN void set_broadcast_mask(void); EXTERN uint8_t bpm_256(const uint8_t* t,const uint8_t* p,int n,int m); EXTERN uint8_t bpm(const uint8_t* t,const uint8_t* p,int n,int m); EXTERN int bpm_block(const uint8_t *t, const uint8_t *p, int n, int m); EXTERN uint8_t dyn_256(const uint8_t* t,const uint8_t* p,int n,int m); #undef BPM_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/bpm_test.c000066400000000000000000000417021515023132300163020ustar00rootroot00000000000000#include "tldevel.h" #include "tlrng.h" #define BPM_IMPORT #include "bpm.h" #include #include #include #include "alphabet.h" #include "esl_stopwatch.h" /* Functions needed for the unit test*/ uint8_t dyn_256_print(const uint8_t* t,const uint8_t* p,int n,int m); int mutate_seq(uint8_t* s, int len,int k,int L, struct rng_state* rng); #ifdef HAVE_AVX2 #include /* For debugging */ void print_256(__m256i X); void print_256_all(__m256i X); #endif #define SIGMA 13 #define DIV_CEIL(a,b) (a == 0 ? 1 : a/b+(a%b == 0 ? 0 : 1)) struct bpm_struct { uint64_t** Peq; uint64_t* P; uint64_t* M; uint64_t HIGH_BIT; uint64_t ONE; int32_t W; int32_t* score; int k; }; static int bpm_block2(const uint8_t *t, const uint8_t *p, int n, int m, int maxd); static int bpm_precompute(const uint8_t *p, int m, struct bpm_struct **out); static int bpm_init_block(struct bpm_struct *s, int b); static inline int advanceBlock(struct bpm_struct *s, int b, uint8_t c, int hIn); int bpm_block2(const uint8_t *t, const uint8_t *p, int n, int m, int maxd) { struct bpm_struct* s = NULL; int w; int32_t w_bytes; int32_t b_max; uint64_t ONE; w_bytes = sizeof(uint64_t); w = w_bytes * 8; b_max = DIV_CEIL(m,w); bpm_precompute(p, m, &s); ONE = s->ONE; w_bytes = sizeof(uint64_t); w = w_bytes * 8; int y = DIV_CEIL(maxd, w) - 1; /* 256 is max edit distance */ for (int b = 0; b <= y; b++) { bpm_init_block(s,b); s->score[b] = (uint32_t)(b + 1) * w; } for (int i = 0; i < n+s->W; i++) { uint8_t c = (uint8_t)t[i]; int carry = 0; for (int b = 0; b <= y; b++) { carry = advanceBlock(s,b, c, carry); s->score[b] += carry; } if ((s->score[y] - carry <= maxd) && (y < (b_max - 1)) && ((s->Peq[c][y + 1] & ONE) || (carry < 0))) { y += 1; bpm_init_block(s,y); s->score[y] = s->score[y - 1] + w - carry + advanceBlock(s,y, c, carry); } else { while (s->score[y] >= (maxd + w)) { if (y == 0) break; y -= 1; } } if(s->score[y] < s->k){ /* LOG_MSG("%d", s->score[y]); */ s->k = s->score[y]; } /* if (y == (b_max - 1) && s->score[y] <= maxd) { */ /* assert(i - s->W >= 0); */ /* /\* result->push_front(SearchResult(score[y], (uint32_t)(i - W))); *\/ */ /* } */ } int k = s->k; for (int c = 0; c < SIGMA; c++) { MFREE(s->Peq[c]); } MFREE(s->Peq); MFREE(s->score); MFREE(s->P); MFREE(s->M); MFREE(s); return k; } inline int advanceBlock(struct bpm_struct *s, int b, uint8_t c, int hIn) { uint64_t Pv = s->P[b]; uint64_t Mv = s->M[b]; uint64_t Eq = s->Peq[c][b]; uint64_t ONE = s->ONE; uint64_t HIGH_BIT = s->HIGH_BIT; uint64_t Xv, Xh; uint64_t Ph, Mh; int h_out = 0; Xv = Eq | Mv; if (hIn < 0) { Eq |= ONE; } Xh = (((Eq & Pv) + Pv) ^ Pv) | Eq; Ph = Mv | (~(Xh | Pv)); Mh = Pv & Xh; if (Ph & HIGH_BIT) { h_out += 1; } if (Mh & HIGH_BIT) { h_out -= 1; } Ph <<= 1; Mh <<= 1; if (hIn < 0) { Mh |= ONE; } else if (hIn > 0) { Ph |= ONE; } Pv = Mh | (~(Xv | Ph)); Mv = Ph & Xv; s->P[b] = Pv; s->M[b] = Mv; return h_out; } int bpm_init_block(struct bpm_struct *s, int b) { int w; int32_t w_bytes; w_bytes = sizeof(uint64_t); w = w_bytes * 8; s->P[b] = (uint64_t) -1;//Ones s->M[b] = 0; s->score[b] = (uint32_t)(b + 1) * w; return OK; } int bpm_precompute(const uint8_t *p, int m, struct bpm_struct **out) { struct bpm_struct* s = NULL; uint64_t** Peq = NULL; uint64_t* P = NULL; uint64_t* M = NULL; int32_t *score = NULL; int32_t w_bytes; int32_t b_max; uint64_t W; int w; uint64_t HIGH_BIT; uint64_t ONE = 1; /* m = 1024; *- > 16 */ w_bytes = sizeof(uint64_t); w = w_bytes * 8; b_max = DIV_CEIL(m,w); /* LOG_MSG("%d -> %d",m,b_max); */ W = w * b_max - m; HIGH_BIT = ONE << (w - 1); MMALLOC(score,b_max * sizeof(int32_t)); MMALLOC(P ,b_max * w_bytes); MMALLOC(M ,b_max * w_bytes); MMALLOC(Peq,SIGMA * sizeof(uint64_t *)); for (int c = 0; c < SIGMA; c++) { Peq[c] = NULL; MMALLOC(Peq[c], b_max*w_bytes); /* Peq[c] = (uint64_t *) malloc(b_max*w_bytes); */ memset(Peq[c], 0, b_max*w_bytes); for (int32_t block = 0; block < b_max; block++) { uint64_t bitPos = (uint64_t) 1; for (int32_t i = block * w; i < (block + 1) * w; ++i) { // fill the remainder after the last block with 1 (>m matches anything) if (i >= m || p[i] == c) { Peq[c][block] |= bitPos; } bitPos <<= 1; } } } MMALLOC(s ,sizeof(struct bpm_struct)); s->M = M; s->P = P; s->Peq = Peq; s->W = W; s->ONE = ONE; s->HIGH_BIT = HIGH_BIT; s->score = score; s->k = m; *out = s; return OK; ERROR: return FAIL; } /* The actual test. */ int bpm_test(void); int main(void) { /* Important set_broadcast_mask has to be called before using bpm_256!!! */ #ifdef HAVE_AVX2 set_broadcast_mask(); #endif RUN(bpm_test()); return EXIT_SUCCESS; ERROR: return EXIT_FAILURE; } int bpm_test(void) { /* idea: start with identical sequences add errors run bpm */ struct alphabet* alphabet = NULL; struct rng_state* rng; //long int r; int len = 0; int i,j,c; uint8_t* a = NULL; uint8_t* b = NULL; int test_iter = 100; int dyn_score; int bpm_score; int bb_score; int bb_score2; int diff[4][4] = { {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0} }; RUNP(rng = init_rng(0)); RUNP(alphabet = create_alphabet(ALPHA_redPROTEIN)); char seq[] = "MLLRNSFISQDENDDQLSPTQLGRAAIASSLPPEASLAIFEDLNSASRAIALDTELHMLYLVYFYKNSRAQIIQKIFKIYSIFILKKFKNLEPKFKKKISENITVHITNSIRKKQHFWHVTPINVSVWQECDWHHLFSIFSKLPSDHKRIAKLVGVSEKFILDQLQGRRNDKLLQIHIRFFSALALFDLISEMSIYEVSHKYRIPRGCLQTLQSQSATYAAMIVAFCLRLGWTYLKALLDGFATRLLFGVRSELSELVAIEGIDGQRARILHERGVTCLSHLSACDSSKLAHFLTLAVPYSSSNSNDGLGEWLFGEPRMRVDVAARTLKERARKVLIRRVQELGISVELPKFEENEENIQESCDSGLPDSCEGMEDELEEKENIVKMEEMTKSVTEMSLTDNTISFKSEDDLFKKEIKVEEDEVFIKKEIDEDEEEIVEETVIECLETSLLKLKASTDEVFLRRLSQTFSPIGRSRSILNNSLLEDSFDRPVPRSSIPILNFITPKRESPTPYFEDSFDRPIPGSLPISSSRRKSVLTNIANLDSSRRESINSNASDNNSFDVFVTPPTKSAKEEKRRIAVKHPRVGNIIYSPLTSSPVIKHPKLEINHFYLKDVCHDHNAWNLWTKSSTSTSSCSIRVSDDYTGIAIRTDAGNTFIPLLETFGGENSVPQFFKNISNFYVLKMPLKIFWKQPSPASKYFESFSKCIIPLNTRLEFLKTLAVTVEMYISSMEDAFLIFEKFGIKIFRLKVVRIAAYLNNVIDVEQEENSNFLPILMDRYSILDPEIRKTCSSSLHKAAVEVYSLKPIFEKMCCSGASLQLEMESCQTVLNIFYSGIVFDQALCNSFIYKIRKQIENLEENIWRLAYGKFNIHSSNEVANVLFYRLGLIYPETSGCKPKLRHLPTNKLILEQMNTQHPIVGKILEYRQIQHTLTQCLMPLAKFIGRIHCWFEMCTSTGRILTSVPNLQNVPKRISSDGMSARQLFIANSENLLIGADYKQLELRVLAHLSNDSNLVNLITSDRDLFEELSIQWNFPRDAVKQLCYGLIYGMGAKSLSELTRMSIEDAEKMLKAFFAMFPGVRSYINETKEKVCKEEPISTIIGRRTIIKASGIGEERARIERVAVNYTIQGSASEIFKTAIVDIESKIKEFGAQIVLTIHDEVLVECPEIHVAAASESIENCMQNALSHLLRVPMRVSMKTGRSWADLK"; len = strlen(seq); if(len > 256){ len = 256; } MMALLOC(a , sizeof(uint8_t) * len) ; MMALLOC(b , sizeof(uint8_t) * len) ; for(i = 0;i < len;i++){ a[i] = alphabet->to_internal[(int)seq[i]]; b[i] =a[i]; /* fprintf(stdout,"%d %d\n", a[i],b[i]); */ } fprintf(stdout,"LEN: %d\n", len); LOG_MSG("Testing correctness of serial bpm."); // len = 63; len = 63; //could fix; for(i = 0; i < len;i++){ for (j =0 ; j < test_iter; j++){ RUN(mutate_seq(b,len,i,alphabet->L,rng)); dyn_score = dyn_256(a,b,len,len); bpm_score = bpm(a,b,len,len); bb_score = bpm_block2(a,b,len,len, len); bb_score2 = bpm_block(a,b,len,len); /* if(j == 0){ */ /* LOG_MSG("k:%d %d %d %d %d",i,dyn_score,bpm_score, bb_score , bb_score2); */ /* } */ if(dyn_score != bpm_score){ diff[0][1]++; } if(dyn_score != bb_score){ diff[0][2]++; } if(dyn_score != bb_score2){ diff[0][3]++; } if(bpm_score != bb_score){ diff[1][2]++; } if(bpm_score != bb_score2){ diff[1][3]++; } if(bb_score != bb_score2){ diff[2][3]++; } /* restore sequence b */ for(c = 0;c < len;c++){ b[c] = a[c]; } } } for(int i = 0; i < 4;i++){ for(int j = 0; j < 4;j++){ fprintf(stdout,"%3d ",diff[i][j]); } fprintf(stdout, "\n"); } fprintf(stdout, "\n"); LOG_MSG("Testing correctness of AVX bpm."); len = strlen(seq); if(len > 255){ len = 255; } for(int i = 0; i < 4;i++){ for(int j = 0; j < 4;j++){ diff[i][j] = 0; } } for(i = 0; i < len;i++){ for (j =0 ; j < test_iter; j++){ RUN(mutate_seq(b,len,i,alphabet->L,rng)); dyn_score = dyn_256(a,b,len,len); #ifdef HAVE_AVX2 bpm_score = bpm_256(a,b,len,len); #else bpm_score = dyn_score; #endif bb_score = bpm_block2(a,b,len,len, len); bb_score2 = bpm_block(a,b,len,len); /* if(j == 0){ */ /* LOG_MSG("k:%d %d %d %d %d",i,dyn_score,bpm_score, bb_score , bb_score2); */ /* } */ if(dyn_score != bpm_score){ diff[0][1]++; } if(dyn_score != bb_score){ diff[0][2]++; } if(dyn_score != bb_score2){ diff[0][3]++; } if(bpm_score != bb_score){ diff[1][2]++; } if(bpm_score != bb_score2){ diff[1][3]++; } if(bb_score != bb_score2){ diff[2][3]++; } /* restore sequence b */ for(c = 0;c < len;c++){ b[c] = a[c]; } } } for(int i = 0; i < 4;i++){ for(int j = 0; j < 4;j++){ fprintf(stdout,"%3d ",diff[i][j]); } fprintf(stdout, "\n"); } fprintf(stdout, "\n"); len = strlen(seq); if(len > 255){ len = 255; } double dyn_timing = 0.0; double bpm_timing = 0.0; double block_timing = 0.0; double block2_timing = 0.0; int timing_iter = 10000; fprintf(stdout,"Dyn\tAVX\tDYN/AVX\n"); LOG_MSG("Timing DYN 256"); DECLARE_TIMER(t); for(i = 0; i < 1;i++){ RUN(mutate_seq(b,len,i,alphabet->L,rng)); START_TIMER(t); for(j = 0; j < timing_iter;j++){ dyn_score = dyn_256(a,b,len,len); } STOP_TIMER(t); /* GET_TIMING(t); */ dyn_timing += GET_USERTIME(t); #ifdef HAVE_AVX2 START_TIMER(t); for(j = 0; j < timing_iter;j++){ bpm_score = bpm_256(a,b,len,len); } STOP_TIMER(t); /* GET_TIMING(t); */ bpm_timing +=GET_USERTIME(t); #endif START_TIMER(t); for(j = 0; j < timing_iter;j++){ bpm_score = bpm_block(a,b,len,len); } STOP_TIMER(t); /* GET_TIMING(t); */ block2_timing +=GET_USERTIME(t); START_TIMER(t); for(j = 0; j < timing_iter;j++){ bpm_score = bpm_block2(a,b,len,len,len); } STOP_TIMER(t); /* GET_TIMING(t); */ block_timing +=GET_USERTIME(t); for(j = 0;j < len;j++){ b[j] = a[j]; } //dyn_timing = GET_TIMING(t); } LOG_MSG("%f - dyn ", dyn_timing); LOG_MSG("%f - bpm ", bpm_timing); LOG_MSG("%f - bpm_block2 ", block2_timing); LOG_MSG("%f - bpm_block ", block_timing); DESTROY_TIMER(t); MFREE(alphabet); MFREE(a); MFREE(b); MFREE(rng); return OK; ERROR: return FAIL; } int mutate_seq(uint8_t* s, int len,int k,int L, struct rng_state* rng) { int i,j; int r; for(i = 0; i < k;i++){ r = tl_random_int(rng,len); j = r; r = tl_random_int(rng,L); s[j] = r; } return OK; } uint8_t dyn_256_print(const uint8_t* t,const uint8_t* p,int n,int m) { uint8_t* prev = NULL; uint8_t* cur = NULL; uint8_t* tmp = NULL; int i,j,c; MMALLOC(prev, sizeof(uint8_t)* 257); MMALLOC(cur, sizeof(uint8_t)* 257); cur[0] = 0; fprintf(stdout,"%d ", cur[0]); for(j = 1; j <= m;j++){ cur[j] = cur[j-1] +1; fprintf(stdout,"%d ", cur[j]); } fprintf(stdout,"\n"); tmp = cur; cur = prev; prev = tmp; for(i = 1; i <= n;i++){ cur[0] = prev[0]; fprintf(stdout,"%d ", cur[0]); for(j = 1; j < m;j++){ c = 1; if(t[i-1] == p[j-1]){ c = 0; } cur[j] = prev[j-1] +c ; cur[j] = MACRO_MIN(cur[j], prev[j]+1); cur[j] = MACRO_MIN(cur[j], cur[j-1]+1); fprintf(stdout,"%d ", cur[j]); } j =m; c = 1; if(t[i-1] == p[j-1]){ c = 0; } cur[j] = prev[j-1] +c ; cur[j] = MACRO_MIN(cur[j], prev[j]); cur[j] = MACRO_MIN(cur[j], cur[j-1]+1); fprintf(stdout,"%d ", cur[j]); fprintf(stdout,"\n"); tmp = cur; cur = prev; prev = tmp; } c = prev[m]; MFREE(prev); MFREE(cur); return c; ERROR: return 255; } #ifdef HAVE_AVX2 void print_256(__m256i X) { alignas(32) uint64_t debug[4]; _mm256_store_si256( (__m256i*)& debug,X); fprintf(stdout,"%lu ", debug[0]); } void print_256_all(__m256i X) { alignas(32) uint64_t debug[4]; _mm256_store_si256( (__m256i*)& debug,X); int i; for(i = 0; i < 4;i++){ fprintf(stdout,"%lu ", debug[i]); } fprintf(stdout,"\n"); } #endif kalign-3.5.1/lib/src/consensus_msa.c000066400000000000000000000714411515023132300173500ustar00rootroot00000000000000#include "tldevel.h" #include #include "msa_struct.h" #include "msa_alloc.h" #include "poar.h" #define CONSENSUS_MSA_IMPORT #include "consensus_msa.h" /* Union-find data structure with per-set sequence membership tracking and element linked lists for efficient set enumeration. */ struct uf_set { int* parent; int* rank; int* elem_seq; /* element -> sequence index */ uint64_t** seq_mask; /* per-root: bitmask of sequences in set */ int* set_head; /* root -> first element in set (-1 if none) */ int* next_in_set; /* element -> next element in same set (-1 if last) */ int n_elements; int numseq; int mask_words; /* number of uint64_t words per bitmask */ }; static int uf_alloc(struct uf_set** uf, int n, int* seq_offsets, int* seq_lengths, int numseq) { struct uf_set* u = NULL; int mw = (numseq + 63) / 64; MMALLOC(u, sizeof(struct uf_set)); u->parent = NULL; u->rank = NULL; u->elem_seq = NULL; u->seq_mask = NULL; u->set_head = NULL; u->next_in_set = NULL; u->n_elements = n; u->numseq = numseq; u->mask_words = mw; MMALLOC(u->parent, sizeof(int) * n); MMALLOC(u->rank, sizeof(int) * n); MMALLOC(u->elem_seq, sizeof(int) * n); MMALLOC(u->set_head, sizeof(int) * n); MMALLOC(u->next_in_set, sizeof(int) * n); MMALLOC(u->seq_mask, sizeof(uint64_t*) * n); for(int i = 0; i < n; i++){ u->parent[i] = i; u->rank[i] = 0; u->set_head[i] = i; u->next_in_set[i] = -1; u->seq_mask[i] = NULL; MMALLOC(u->seq_mask[i], sizeof(uint64_t) * mw); memset(u->seq_mask[i], 0, sizeof(uint64_t) * mw); } /* Fill elem_seq and initialize per-element bitmasks */ for(int s = 0; s < numseq; s++){ for(int p = 0; p < seq_lengths[s]; p++){ int elem = seq_offsets[s] + p; u->elem_seq[elem] = s; u->seq_mask[elem][s / 64] |= (1ULL << (s % 64)); } } *uf = u; return OK; ERROR: return FAIL; } static void uf_free(struct uf_set* u) { if(u){ if(u->seq_mask){ for(int i = 0; i < u->n_elements; i++){ if(u->seq_mask[i]) MFREE(u->seq_mask[i]); } MFREE(u->seq_mask); } if(u->next_in_set) MFREE(u->next_in_set); if(u->set_head) MFREE(u->set_head); if(u->elem_seq) MFREE(u->elem_seq); if(u->parent) MFREE(u->parent); if(u->rank) MFREE(u->rank); MFREE(u); } } static int uf_find(struct uf_set* u, int x) { while(u->parent[x] != x){ u->parent[x] = u->parent[u->parent[x]]; /* path halving */ x = u->parent[x]; } return x; } /* Check if root 'target' is reachable from root 'start' via the implicit column ordering DAG. A directed edge col_A -> col_B exists when some sequence has consecutive residues in cols A and B. If target is reachable from start, merging them would create a cycle. */ static int dag_reachable(struct uf_set* u, int start, int target, int* seq_offsets, int* seq_lengths, int* visited, int visit_id) { /* BFS using the element linked lists for efficient enumeration */ /* We use a simple queue built from a scratch array */ int queue[4096]; /* bounded queue; for very large problems this needs malloc */ int head = 0, tail = 0; if(start == target) return 1; queue[tail++] = start; visited[start] = visit_id; while(head < tail){ int cur = queue[head++]; /* Enumerate outgoing edges: for each element in cur's set, check its successor (same seq, pos+1) */ int elem = u->set_head[cur]; while(elem >= 0){ int s = u->elem_seq[elem]; int pos = elem - seq_offsets[s]; if(pos + 1 < seq_lengths[s]){ int succ_elem = seq_offsets[s] + pos + 1; int succ_root = uf_find(u, succ_elem); if(succ_root == target) return 1; if(succ_root != cur && visited[succ_root] != visit_id){ visited[succ_root] = visit_id; if(tail < 4096){ queue[tail++] = succ_root; } } } elem = u->next_in_set[elem]; } } return 0; } /* Merge two sets. Returns 1 if merge succeeded, 0 if blocked by: - same-sequence conflict (two residues from same seq in one column) - ordering cycle (merging would create a cycle in the column DAG) When seq_offsets/seq_lengths are NULL, skip cycle check. */ static int uf_union_safe(struct uf_set* u, int a, int b, int* seq_offsets, int* seq_lengths, int* visited, int* visit_counter) { int ra = uf_find(u, a); int rb = uf_find(u, b); if(ra == rb) return 1; /* Check for conflict: do the two sets share any sequence? */ for(int w = 0; w < u->mask_words; w++){ if(u->seq_mask[ra][w] & u->seq_mask[rb][w]){ return 0; /* conflict: same sequence in both sets */ } } /* Check for ordering cycle: would merging create a cycle? A cycle exists if ra can reach rb (meaning ra < rb in the partial order, but merging makes them equal). */ if(seq_offsets != NULL){ (*visit_counter)++; if(dag_reachable(u, ra, rb, seq_offsets, seq_lengths, visited, *visit_counter)){ return 0; /* would create cycle */ } (*visit_counter)++; if(dag_reachable(u, rb, ra, seq_offsets, seq_lengths, visited, *visit_counter)){ return 0; /* would create cycle */ } } /* Safe to merge */ int new_root; int old_root; if(u->rank[ra] < u->rank[rb]){ u->parent[ra] = rb; new_root = rb; old_root = ra; }else if(u->rank[ra] > u->rank[rb]){ u->parent[rb] = ra; new_root = ra; old_root = rb; }else{ u->parent[rb] = ra; u->rank[ra]++; new_root = ra; old_root = rb; } /* Merge sequence bitmasks into new root */ for(int w = 0; w < u->mask_words; w++){ u->seq_mask[new_root][w] |= u->seq_mask[old_root][w]; } /* Concatenate element linked lists: append old_root's list to new_root's */ if(u->set_head[old_root] >= 0){ /* Find tail of new_root's list */ int tail = u->set_head[new_root]; if(tail < 0){ u->set_head[new_root] = u->set_head[old_root]; }else{ while(u->next_in_set[tail] >= 0){ tail = u->next_in_set[tail]; } u->next_in_set[tail] = u->set_head[old_root]; } } u->set_head[old_root] = -1; return 1; } static inline int popcount32(uint32_t x) { #ifdef __GNUC__ return __builtin_popcount(x); #else x = x - ((x >> 1) & 0x55555555u); x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u); return (int)(((x + (x >> 4)) & 0x0F0F0F0Fu) * 0x01010101u >> 24); #endif } static inline int pair_index(int i, int j, int numseq) { return i * numseq - (i * (i + 1)) / 2 + (j - i - 1); } struct merge_candidate { int elem_i; int elem_j; int support; }; /* DFS-based topological sort that gracefully handles cycles by skipping back edges. This produces a valid ordering that respects as many sequence constraints as possible. */ static int topo_sort(int* col_id, /* [total_residues]: element -> column id */ int* seq_offsets, /* [numseq]: start offset for each seq */ int* seq_lengths, /* [numseq] */ int numseq, int n_cols, int** sorted_cols, /* output: sorted column indices */ int* n_sorted) { int* out = NULL; int** adj_list = NULL; int* adj_count = NULL; int* adj_alloc = NULL; int* state = NULL; /* 0=unvisited, 1=in-progress, 2=done */ int* dfs_stack = NULL; /* pairs of (node, edge_index) */ int i, s, pos; int out_idx; int sp; MMALLOC(adj_count, sizeof(int) * n_cols); MMALLOC(adj_alloc, sizeof(int) * n_cols); MMALLOC(adj_list, sizeof(int*) * n_cols); MMALLOC(out, sizeof(int) * n_cols); MMALLOC(state, sizeof(int) * n_cols); MMALLOC(dfs_stack, sizeof(int) * n_cols * 2); for(i = 0; i < n_cols; i++){ adj_count[i] = 0; adj_alloc[i] = 4; adj_list[i] = NULL; MMALLOC(adj_list[i], sizeof(int) * adj_alloc[i]); state[i] = 0; } /* Build adjacency list (deduplicated) */ for(s = 0; s < numseq; s++){ for(pos = 0; pos < seq_lengths[s] - 1; pos++){ int elem_a = seq_offsets[s] + pos; int elem_b = seq_offsets[s] + pos + 1; int ca = col_id[elem_a]; int cb = col_id[elem_b]; if(ca != cb){ int dup = 0; for(int k = 0; k < adj_count[ca]; k++){ if(adj_list[ca][k] == cb){ dup = 1; break; } } if(!dup){ if(adj_count[ca] >= adj_alloc[ca]){ adj_alloc[ca] *= 2; MREALLOC(adj_list[ca], sizeof(int) * adj_alloc[ca]); } adj_list[ca][adj_count[ca]++] = cb; } } } } /* DFS topological sort — back edges (cycles) are silently skipped */ out_idx = n_cols - 1; for(int start = 0; start < n_cols; start++){ if(state[start] != 0) continue; sp = 0; dfs_stack[sp++] = start; dfs_stack[sp++] = 0; state[start] = 1; while(sp > 0){ int edge_idx = dfs_stack[--sp]; int node = dfs_stack[--sp]; int pushed = 0; for(int e = edge_idx; e < adj_count[node]; e++){ int next = adj_list[node][e]; if(state[next] == 0){ /* Push current with updated edge index */ dfs_stack[sp++] = node; dfs_stack[sp++] = e + 1; /* Push next */ dfs_stack[sp++] = next; dfs_stack[sp++] = 0; state[next] = 1; pushed = 1; break; } /* state[next]==1: back edge (cycle) — skip */ /* state[next]==2: cross/forward edge — skip */ } if(!pushed){ state[node] = 2; out[out_idx--] = node; } } } for(i = 0; i < n_cols; i++){ if(adj_list[i]) MFREE(adj_list[i]); } MFREE(adj_list); MFREE(adj_count); MFREE(adj_alloc); MFREE(state); MFREE(dfs_stack); *sorted_cols = out; *n_sorted = n_cols; return OK; ERROR: if(adj_list){ for(i = 0; i < n_cols; i++){ if(adj_list[i]) MFREE(adj_list[i]); } MFREE(adj_list); } if(adj_count) MFREE(adj_count); if(adj_alloc) MFREE(adj_alloc); if(state) MFREE(state); if(dfs_stack) MFREE(dfs_stack); if(out) MFREE(out); return FAIL; } int build_consensus(struct poar_table* table, int* seq_lengths, int numseq, int min_support, struct msa* out_msa) { struct uf_set* uf = NULL; int* seq_offsets = NULL; int* col_id = NULL; /* element -> column */ int* root_to_col = NULL; /* uf root -> column index */ int* sorted_cols = NULL; int* visited = NULL; /* for cycle detection BFS */ int visit_counter = 0; int n_sorted = 0; int total_residues = 0; int n_cols = 0; int i, j, s, pos; char** out_seqs = NULL; ASSERT(table != NULL, "No POAR table"); ASSERT(out_msa != NULL, "No output MSA"); /* Compute offsets */ MMALLOC(seq_offsets, sizeof(int) * numseq); for(s = 0; s < numseq; s++){ seq_offsets[s] = total_residues; total_residues += seq_lengths[s]; } /* Initialize union-find with sequence membership tracking */ RUN(uf_alloc(&uf, total_residues, seq_offsets, seq_lengths, numseq)); /* Allocate visited array for cycle detection (use visit_counter to avoid clearing between checks) */ MMALLOC(visited, sizeof(int) * total_residues); memset(visited, 0, sizeof(int) * total_residues); /* Collect all POAR entries above min_support, then process in descending support order so higher-confidence pairs merge first */ { int n_candidates = 0; int alloc_candidates = 1024; struct merge_candidate *candidates = NULL; MMALLOC(candidates, sizeof(*candidates) * alloc_candidates); for(i = 0; i < numseq - 1; i++){ for(j = i + 1; j < numseq; j++){ int pidx = pair_index(i, j, numseq); struct poar_pair* pp = table->pairs[pidx]; for(int e = 0; e < pp->n_entries; e++){ int support = popcount32(pp->entries[e].support); if(support >= min_support){ if(n_candidates >= alloc_candidates){ alloc_candidates *= 2; MREALLOC(candidates, sizeof(*candidates) * alloc_candidates); } uint32_t key = pp->entries[e].key; candidates[n_candidates].elem_i = seq_offsets[i] + (int)(key >> 20); candidates[n_candidates].elem_j = seq_offsets[j] + (int)(key & 0xFFFFF); candidates[n_candidates].support = support; n_candidates++; } } } } /* Counting sort by descending support (values bounded 1..32) */ { int counts[33] = {0}; for(int a = 0; a < n_candidates; a++){ counts[candidates[a].support]++; } int offsets[33]; offsets[32] = 0; for(int v = 31; v >= 0; v--){ offsets[v] = offsets[v+1] + counts[v+1]; } int tmp_alloc = n_candidates > 0 ? n_candidates : 1; struct merge_candidate *sorted = NULL; MMALLOC(sorted, sizeof(*sorted) * tmp_alloc); for(int a = 0; a < n_candidates; a++){ int s_val = candidates[a].support; sorted[offsets[s_val]++] = candidates[a]; } memcpy(candidates, sorted, sizeof(*candidates) * n_candidates); MFREE(sorted); } /* Merge in priority order, skipping conflicts AND cycles */ for(int c = 0; c < n_candidates; c++){ uf_union_safe(uf, candidates[c].elem_i, candidates[c].elem_j, seq_offsets, seq_lengths, visited, &visit_counter); } MFREE(candidates); } MFREE(visited); /* Map UF roots to column IDs */ MMALLOC(root_to_col, sizeof(int) * total_residues); MMALLOC(col_id, sizeof(int) * total_residues); for(i = 0; i < total_residues; i++){ root_to_col[i] = -1; } n_cols = 0; for(i = 0; i < total_residues; i++){ int root = uf_find(uf, i); if(root_to_col[root] == -1){ root_to_col[root] = n_cols++; } col_id[i] = root_to_col[root]; } MFREE(root_to_col); /* Topological sort (DFS-based, cycle-safe) */ RUN(topo_sort(col_id, seq_offsets, seq_lengths, numseq, n_cols, &sorted_cols, &n_sorted)); /* Build column order lookup: sorted position -> column */ int* col_order = NULL; /* column -> position in sorted output */ MMALLOC(col_order, sizeof(int) * n_cols); for(i = 0; i < n_sorted; i++){ col_order[sorted_cols[i]] = i; } /* Build output alignment */ MMALLOC(out_seqs, sizeof(char*) * numseq); for(s = 0; s < numseq; s++){ out_seqs[s] = NULL; MMALLOC(out_seqs[s], sizeof(char) * (n_sorted + 1)); memset(out_seqs[s], '-', n_sorted); out_seqs[s][n_sorted] = '\0'; } /* Place residues */ for(s = 0; s < numseq; s++){ for(pos = 0; pos < seq_lengths[s]; pos++){ int elem = seq_offsets[s] + pos; int col = col_id[elem]; int sorted_pos = col_order[col]; /* Use original residue character from the MSA */ out_seqs[s][sorted_pos] = out_msa->sequences[s]->seq[pos]; } } /* Write back into MSA: replace seq pointers */ for(s = 0; s < numseq; s++){ MFREE(out_msa->sequences[s]->seq); out_msa->sequences[s]->seq = out_seqs[s]; out_msa->sequences[s]->len = n_sorted; out_seqs[s] = NULL; } out_msa->alnlen = n_sorted; out_msa->aligned = ALN_STATUS_FINAL; MFREE(out_seqs); MFREE(col_order); MFREE(sorted_cols); MFREE(col_id); MFREE(seq_offsets); uf_free(uf); return OK; ERROR: if(out_seqs){ for(s = 0; s < numseq; s++){ if(out_seqs[s]) MFREE(out_seqs[s]); } MFREE(out_seqs); } if(col_order) MFREE(col_order); if(sorted_cols) MFREE(sorted_cols); if(col_id) MFREE(col_id); if(root_to_col) MFREE(root_to_col); if(visited) MFREE(visited); if(seq_offsets) MFREE(seq_offsets); uf_free(uf); return FAIL; } /* Compute per-residue and per-column confidence from POAR table. For each residue at alignment position pos in sequence i: - Count residue-residue pairs with other sequences j that also have a residue (not gap) at the same column. - For each such pair, look up POAR support (popcount). - confidence = sum(supports) / (n_residue_pairs * n_alignments) Gaps get confidence 0.0. Column confidence = mean of residue confidences in that column. */ int compute_residue_confidence(struct poar_table* table, struct msa* aligned_msa) { struct pos_matrix* pm = NULL; int numseq = aligned_msa->numseq; int alnlen = aligned_msa->alnlen; int n_alignments = table->n_alignments; int i, j, col; char** seqs = NULL; ASSERT(table != NULL, "No POAR table"); ASSERT(aligned_msa != NULL, "No aligned MSA"); ASSERT(alnlen > 0, "Alignment length is 0"); /* Build position matrix from aligned MSA */ MMALLOC(seqs, sizeof(char*) * numseq); for(i = 0; i < numseq; i++){ seqs[i] = aligned_msa->sequences[i]->seq; } RUN(pos_matrix_from_msa(&pm, seqs, numseq, alnlen)); /* Allocate per-residue confidence arrays */ for(i = 0; i < numseq; i++){ if(aligned_msa->sequences[i]->confidence){ MFREE(aligned_msa->sequences[i]->confidence); } aligned_msa->sequences[i]->confidence = NULL; MMALLOC(aligned_msa->sequences[i]->confidence, sizeof(float) * alnlen); for(col = 0; col < alnlen; col++){ aligned_msa->sequences[i]->confidence[col] = 0.0f; } } /* Allocate per-column confidence */ if(aligned_msa->col_confidence){ MFREE(aligned_msa->col_confidence); } aligned_msa->col_confidence = NULL; MMALLOC(aligned_msa->col_confidence, sizeof(float) * alnlen); /* Compute per-residue confidence */ for(i = 0; i < numseq; i++){ for(col = 0; col < alnlen; col++){ int ri = pm->col_to_res[i][col]; if(ri < 0){ /* gap position */ aligned_msa->sequences[i]->confidence[col] = 0.0f; continue; } double sum_support = 0.0; int n_pairs = 0; for(j = 0; j < numseq; j++){ if(j == i) continue; int rj = pm->col_to_res[j][col]; if(rj < 0) continue; /* skip gaps */ /* Look up POAR support for this pair */ int si = i < j ? i : j; int sj = i < j ? j : i; int pidx = pair_index(si, sj, numseq); struct poar_pair* pp = table->pairs[pidx]; int orig_i = i < j ? ri : rj; int orig_j = i < j ? rj : ri; uint32_t key = ((uint32_t)orig_i << 20) | (uint32_t)orig_j; /* Binary search */ int lo = 0; int hi = pp->n_entries; int support = 0; while(lo < hi){ int mid = lo + (hi - lo) / 2; if(pp->entries[mid].key < key){ lo = mid + 1; }else if(pp->entries[mid].key == key){ support = popcount32(pp->entries[mid].support); break; }else{ hi = mid; } } sum_support += (double)support; n_pairs++; } if(n_pairs > 0 && n_alignments > 0){ aligned_msa->sequences[i]->confidence[col] = (float)(sum_support / ((double)n_pairs * (double)n_alignments)); }else{ aligned_msa->sequences[i]->confidence[col] = 0.0f; } } } /* Compute per-column confidence: mean over non-gap residues */ for(col = 0; col < alnlen; col++){ double sum = 0.0; int count = 0; for(i = 0; i < numseq; i++){ if(pm->col_to_res[i][col] >= 0){ sum += aligned_msa->sequences[i]->confidence[col]; count++; } } if(count > 0){ aligned_msa->col_confidence[col] = (float)(sum / count); }else{ aligned_msa->col_confidence[col] = 0.0f; } } pos_matrix_free(pm); MFREE(seqs); return OK; ERROR: if(pm) pos_matrix_free(pm); if(seqs) MFREE(seqs); return FAIL; } /* Score one alignment against the POAR table. Returns expected number of correct pairs: for each aligned pair, (support - 1) / (m - 1) gives the fraction of OTHER alignments agreeing. Summing these gives expected correct pairs. This rewards both high recall (many pairs) and high precision (pairs with broad agreement). */ int score_alignment_poar(struct poar_table* table, struct pos_matrix* pm, int numseq, int n_alignments, double* out_score) { double total_score = 0.0; int i, j, col; int alnlen = pm->alnlen; double denom = (n_alignments > 1) ? (double)(n_alignments - 1) : 1.0; for(i = 0; i < numseq - 1; i++){ for(j = i + 1; j < numseq; j++){ int pidx = pair_index(i, j, numseq); struct poar_pair* pp = table->pairs[pidx]; for(col = 0; col < alnlen; col++){ int ri = pm->col_to_res[i][col]; int rj = pm->col_to_res[j][col]; if(ri >= 0 && rj >= 0){ uint32_t key = ((uint32_t)ri << 20) | (uint32_t)rj; /* Binary search in sorted entries */ int lo = 0; int hi = pp->n_entries; int support = 0; while(lo < hi){ int mid = lo + (hi - lo) / 2; if(pp->entries[mid].key < key){ lo = mid + 1; }else if(pp->entries[mid].key == key){ support = popcount32(pp->entries[mid].support); break; }else{ hi = mid; } } /* support includes self; subtract 1 for other-agreement */ total_score += (double)(support - 1) / denom; } } } } *out_score = total_score; return OK; } kalign-3.5.1/lib/src/consensus_msa.h000066400000000000000000000015601515023132300173500ustar00rootroot00000000000000#ifndef CONSENSUS_MSA_H #define CONSENSUS_MSA_H #ifdef CONSENSUS_MSA_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct poar_table; struct pos_matrix; struct msa; EXTERN int build_consensus(struct poar_table* table, int* seq_lengths, int numseq, int min_support, struct msa* out_msa); EXTERN int score_alignment_poar(struct poar_table* table, struct pos_matrix* pm, int numseq, int n_alignments, double* out_score); EXTERN int compute_residue_confidence(struct poar_table* table, struct msa* aligned_msa); #undef CONSENSUS_MSA_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/core.h000066400000000000000000000012321515023132300154140ustar00rootroot00000000000000#ifndef CORE_H #define CORE_H #ifdef CORE_IMPORT #define EXTERN #else #define EXTERN extern #endif /* idea: use a shared struct holding dm & msa & empty root Process: put root on task list if (node is ready to align - do so ) }else{ while # tries < x take task, run split , update L / R arrays if better than previous split then add left and right node contine. } if(nseq at node == 1){ send possible align signal up; if(align counter ==2 ){ add parent node to queue } } if (number of left == 1 && number of right ==1){ send possible align to } */ #undef CORE_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/coretralign.c000066400000000000000000000126421515023132300167770ustar00rootroot00000000000000#include "tldevel.h" #define CORETRALIGN_IMPORT #include "coretralign.h" int aln_scheduler_get_tid(aln_scheduler *s) { int i; int64_t tid = (int64_t) pthread_self(); int ID = -1; aln_scheduler_lock(s); for(i = 0; i < s->thread_id_idx;i++){ if(s->thread_id_map[i] == tid){ ID = i; break; } } if(ID == -1){ ID = s->thread_id_idx; s->thread_id_map[s->thread_id_idx] = tid; s->thread_id_idx++; } aln_scheduler_unlock(s); return ID; } int aln_scheduler_lock(aln_scheduler* s) { ASSERT(s != NULL, "No thread controll"); /* pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); */ if(pthread_mutex_lock(&s->lock) != 0){ ERROR_MSG("Can't get lock"); } return OK; ERROR: return FAIL; } int aln_scheduler_trylock(aln_scheduler* s) { return pthread_mutex_trylock(&s->lock); } int aln_scheduler_unlock(aln_scheduler* s) { ASSERT(s != NULL, "No thread controll"); if(pthread_mutex_unlock(&s->lock) != 0){ ERROR_MSG("Can't get lock"); } /* pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); */ /* pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); */ /* pthread_testcancel(); */ return OK; ERROR: return FAIL; } int aln_scheduler_alloc(aln_scheduler **scheduler, int n_threads) { aln_scheduler* n = NULL; MMALLOC(n, sizeof(aln_scheduler)); n->task_alloc = NULL; n->task_queue = NULL; n->root = NULL; n->threads = NULL; n->thread_id_map = NULL; n->thread_id_idx = 0; pthread_mutex_init(&n->lock, NULL); n->n_threads = n_threads; MMALLOC(n->threads, sizeof(pthread_t) * n->n_threads); MMALLOC(n->thread_id_map, sizeof(int64_t) * n->n_threads); queue_alloc(&n->task_alloc, 1); queue_alloc(&n->task_queue, 0); *scheduler = n; return OK; ERROR: return FAIL; } void aln_scheduler_free(aln_scheduler *n) { if(n){ if(n->task_alloc){ queue_free(n->task_alloc); } if(n->task_queue){ queue_free(n->task_queue); } if(n->threads){ MFREE(n->threads); } if(n->thread_id_map){ MFREE(n->thread_id_map); } MFREE(n); } } static int aln_elem_alloc(aln_elem **node); static int aln_elem_free(aln_elem *n); int queue_push(aln_elem_queue *q, aln_elem *n) { if(q->head == NULL){ q->head = n; q->tail = q->head; q->head->p = NULL; }else{ n->p = q->head; q->head = n; } q->n++; return OK; } int queue_pop(aln_elem_queue *q, aln_elem **node) { aln_elem * tmp = NULL; if(q->head == NULL){ if(q->is_allocator){ /* RUN(eq_add_mem(q)); */ }else{ *node = NULL; return FAIL; } } *node = q->head; tmp = q->head; q->head = tmp->p; if(q->head == NULL){ q->tail = NULL; } q->n--; return OK; } int queue_append(aln_elem_queue *q, aln_elem* n) { if(q->head == NULL){ q->head = n; q->tail = q->head; }else{ q->tail->p = n; q->tail = q->tail->p; } q->tail->p = NULL; q->n++; return OK; } int queue_add_mem(aln_elem_queue *q) { ASSERT(q->alloc_block_size != 0,"This queue is not an allocator!"); for(int i = 0; i < q->alloc_block_size;i++){ /* Alloc e_node */ aln_elem* n = NULL; aln_elem_alloc(&n); /* Add to queue */ queue_append(q, n); } return OK; ERROR: return FAIL; } int queue_alloc(aln_elem_queue **queue, uint8_t is_allocator) { aln_elem_queue* l = NULL; MMALLOC(l, sizeof(aln_elem_queue)); l->head = NULL; l->tail = 0; l->n = 0; l->alloc_block_size = 0; l->is_allocator = is_allocator; if(is_allocator){ l->alloc_block_size = 4096; RUN(queue_add_mem(l)); /* RUN(eq_add_mem(l)); */ } *queue = l; return OK; ERROR: queue_free(l); return FAIL; } void queue_free(aln_elem_queue *l) { if(l){ aln_elem* n = NULL; while(l->n){ n = NULL; queue_pop(l, &n); aln_elem_free(n); } MFREE(l); } } int aln_elem_alloc(aln_elem **node) { aln_elem* n = NULL; MMALLOC(n, sizeof(aln_elem)); n->l = NULL; n->r = NULL; n->p = NULL; n->wait = 0; n->type = AE_TYPE_UNDEF; n->aln_mem = NULL; *node = n; return OK; ERROR: aln_elem_free(n); return FAIL; } int aln_elem_free(aln_elem *n) { if(n){ MFREE(n); } } kalign-3.5.1/lib/src/coretralign.h000066400000000000000000000033131515023132300167770ustar00rootroot00000000000000#ifndef CORETRALIGN_H #define CORETRALIGN_H #include #include #include "aln_mem.h" #ifdef CORETRALIGN_IMPORT #define EXTERN #else #define EXTERN extern #endif /* Idea: construct hirschberg alignment via trees -> only because this would make threading easier to control */ typedef enum { AE_TYPE_UNDEF, AE_TYPE_ALN_BACK, AE_TYPE_ALN_FORWARD, AE_TYPE_SPLIT /* tree stuff here */ }aln_elem_type; typedef struct aln_elem aln_elem; typedef struct aln_elem { aln_elem* l; /* left OR backward in dyn*/ aln_elem* r; /* right OR backward in dyn*/ aln_elem* p; /* parent */ uint8_t wait; aln_elem_type type; struct aln_mem* aln_mem; } aln_elem; typedef struct aln_elem_queue { aln_elem* head; aln_elem* tail; int alloc_block_size; int n; uint8_t is_allocator; } aln_elem_queue; typedef struct aln_scheduler { aln_elem_queue* task_alloc; aln_elem_queue* task_queue; aln_elem* root; pthread_t* threads; int64_t* thread_id_map; int thread_id_idx; pthread_mutex_t lock; int n_threads; double** dm; struct msa* msa; } aln_scheduler; EXTERN int aln_scheduler_lock(aln_scheduler* s); EXTERN int aln_scheduler_trylock(aln_scheduler* s); EXTERN int aln_scheduler_unlock(aln_scheduler* s); EXTERN int aln_scheduler_alloc(aln_scheduler **scheduler, int n_threads); EXTERN void aln_scheduler_free(aln_scheduler *n); EXTERN int queue_alloc(aln_elem_queue **queue, uint8_t is_allocator); EXTERN void queue_free(aln_elem_queue *l); #undef CORETRALIGN_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/ensemble.c000066400000000000000000000505521515023132300162620ustar00rootroot00000000000000#include "tldevel.h" #include "esl_stopwatch.h" #include "msa_struct.h" #include "msa_op.h" #include "msa_alloc.h" #include "msa_sort.h" #include "msa_check.h" #include "aln_param.h" #include "aln_wrap.h" #include "poar.h" #include "consensus_msa.h" #include "kalign/kalign.h" #define ENSEMBLE_IMPORT #include "ensemble.h" /* Each ensemble run varies gap-open and gap-extend independently, with optional iterative refinement on select runs. This explores "few long gaps" vs "many short gaps" rather than just uniformly scaling all penalties together. Entry 0 is unused (run 0 always uses defaults). */ struct ensemble_params { float gpo_scale; /* gap open multiplier */ float gpe_scale; /* gap extend multiplier */ float tgpe_scale; /* terminal gap extend multiplier */ float noise; /* tree noise sigma */ }; static struct ensemble_params run_params[] = { {1.0f, 1.0f, 1.0f, 0.0f}, /* 0: default (unused, handled specially) */ {0.5f, 1.5f, 0.8f, 0.20f}, /* 1: fewer gap-opens, longer extensions */ {1.5f, 0.5f, 1.2f, 0.20f}, /* 2: more gap-opens, shorter extensions */ {0.7f, 0.7f, 0.5f, 0.25f}, /* 3: globally relaxed gaps */ {1.4f, 1.4f, 1.5f, 0.25f}, /* 4: globally strict gaps */ {0.8f, 1.2f, 1.0f, 0.30f}, /* 5: slight open-relax, extend-strict */ {1.3f, 0.8f, 0.7f, 0.30f}, /* 6: strict open, relaxed extend+terminal */ {0.6f, 1.0f, 1.3f, 0.15f}, /* 7: relaxed open only */ {1.0f, 0.6f, 0.6f, 0.15f}, /* 8: relaxed extend only */ {1.8f, 1.0f, 1.0f, 0.35f}, /* 9: very strict open, big tree perturbation */ {1.0f, 1.8f, 1.8f, 0.35f}, /* 10: very strict extend */ {0.4f, 0.4f, 0.3f, 0.20f}, /* 11: very relaxed all */ }; #define N_RUN_PARAMS 12 /* --------------------------------------------------------------------------- * Helper: resolve_run_params * * Given base gap penalties and a run index, compute the run-specific * gap-open, gap-extend, terminal-gap-extend, seed, and noise values. * Run 0 always uses defaults (deterministic, no noise). * ------------------------------------------------------------------------- */ static void resolve_run_params(float base_gpo, float base_gpe, float base_tgpe, int k, uint64_t seed, float* out_gpo, float* out_gpe, float* out_tgpe, uint64_t* out_seed, float* out_noise) { if(k == 0){ /* Run 0: default params, deterministic */ *out_gpo = base_gpo; *out_gpe = base_gpe; *out_tgpe = base_tgpe; *out_seed = 0; *out_noise = 0.0f; }else{ /* Subsequent runs: independent per-penalty scaling + tree noise */ struct ensemble_params ep = run_params[k % N_RUN_PARAMS]; *out_gpo = base_gpo * ep.gpo_scale; *out_gpe = base_gpe * ep.gpe_scale; *out_tgpe = base_tgpe * ep.tgpe_scale; *out_seed = seed + (uint64_t)k; *out_noise = ep.noise; } } /* --------------------------------------------------------------------------- * Helper: score_alignments * * Score all N alignments against the POAR table. Returns the scores * array (caller must MFREE) and the index of the best run (best_k). * Run 0 is preferred unless another run exceeds its score by >5%. * ------------------------------------------------------------------------- */ static int score_alignments(struct msa** alignments, struct poar_table* poar, int numseq, int n_runs, int quiet, double** out_scores, int* out_best_k) { struct pos_matrix* pm = NULL; double* scores = NULL; int k; MMALLOC(scores, sizeof(double) * n_runs); for(k = 0; k < n_runs; k++){ char** aln_seqs = NULL; MMALLOC(aln_seqs, sizeof(char*) * numseq); for(int i = 0; i < numseq; i++){ aln_seqs[i] = alignments[k]->sequences[i]->seq; } RUN(pos_matrix_from_msa(&pm, aln_seqs, numseq, alignments[k]->alnlen)); RUN(score_alignment_poar(poar, pm, numseq, n_runs, &scores[k])); if(!quiet){ LOG_MSG(" Run %d score: %.1f", k + 1, scores[k]); } pos_matrix_free(pm); pm = NULL; MFREE(aln_seqs); } /* Select: prefer run 0 (default params) unless another run has a meaningfully higher score (>5% improvement). */ int best_k = 0; double baseline = scores[0]; for(k = 1; k < n_runs; k++){ if(scores[k] > scores[best_k] && scores[k] > baseline * 1.05){ best_k = k; } } *out_scores = scores; *out_best_k = best_k; return OK; ERROR: if(pm) pos_matrix_free(pm); if(scores) MFREE(scores); return FAIL; } /* --------------------------------------------------------------------------- * Helper: build_consensus_from_poar * * Build a consensus MSA from a POAR table at the given min_support * threshold. Allocates and returns consensus_msa via *out_consensus. * The source MSA is used as the template (deep-copied internally). * ------------------------------------------------------------------------- */ static int build_consensus_from_poar(struct poar_table* poar, struct msa* msa, int numseq, int min_support, struct msa** out_consensus) { struct msa* consensus_msa = NULL; int* seq_lens = NULL; RUN(msa_cpy(&consensus_msa, msa)); MMALLOC(seq_lens, sizeof(int) * numseq); for(int i = 0; i < numseq; i++){ seq_lens[i] = msa->sequences[i]->len; } RUN(build_consensus(poar, seq_lens, numseq, min_support, consensus_msa)); MFREE(seq_lens); *out_consensus = consensus_msa; return OK; ERROR: if(seq_lens) MFREE(seq_lens); if(consensus_msa) kalign_free_msa(consensus_msa); return FAIL; } /* --------------------------------------------------------------------------- * Helper: copy_alignment_to_msa * * Move alignment sequences from src into dst, transferring ownership. * After this call, src's seq pointers are replaced with empty strings * so it can be safely freed. * ------------------------------------------------------------------------- */ static int copy_alignment_to_msa(struct msa* dst, struct msa* src, int numseq) { for(int i = 0; i < numseq; i++){ MFREE(dst->sequences[i]->seq); dst->sequences[i]->seq = src->sequences[i]->seq; dst->sequences[i]->len = src->sequences[i]->len; src->sequences[i]->seq = NULL; MMALLOC(src->sequences[i]->seq, 1); src->sequences[i]->seq[0] = '\0'; } dst->alnlen = src->alnlen; dst->aligned = src->aligned; return OK; ERROR: return FAIL; } /* --------------------------------------------------------------------------- * Helper: score_single_msa * * Score a single MSA against a POAR table. Returns the score via * out_score. This avoids repeating the aln_seqs + pos_matrix pattern. * ------------------------------------------------------------------------- */ static int score_single_msa(struct msa* aln, struct poar_table* poar, int numseq, int n_runs, double* out_score) { struct pos_matrix* pm = NULL; char** aln_seqs = NULL; MMALLOC(aln_seqs, sizeof(char*) * numseq); for(int i = 0; i < numseq; i++){ aln_seqs[i] = aln->sequences[i]->seq; } RUN(pos_matrix_from_msa(&pm, aln_seqs, numseq, aln->alnlen)); RUN(score_alignment_poar(poar, pm, numseq, n_runs, out_score)); pos_matrix_free(pm); MFREE(aln_seqs); return OK; ERROR: if(pm) pos_matrix_free(pm); if(aln_seqs) MFREE(aln_seqs); return FAIL; } /* ======================================================================== */ int kalign_ensemble(struct msa* msa, int n_threads, int type, int n_runs, float gpo, float gpe, float tgpe, uint64_t seed, int min_support, const char* save_poar_path, int refine, float dist_scale, float vsm_amax, int realign, float use_seq_weights, int consistency_anchors, float consistency_weight) { struct msa* copy = NULL; struct msa* consensus_msa = NULL; struct msa** alignments = NULL; struct poar_table* poar = NULL; struct pos_matrix* pm = NULL; struct aln_param* ap = NULL; double* scores = NULL; int numseq; int k; int best_k = 0; int use_consensus = 0; float base_gpo, base_gpe, base_tgpe; ASSERT(msa != NULL, "No MSA"); ASSERT(n_runs >= 1, "n_runs must be >= 1"); /* Seq_weights hurts ensemble performance (POAR consensus already handles profile imbalance). Default to OFF in ensemble mode. */ if(use_seq_weights < 0.0f){ use_seq_weights = 0.0f; } /* Essential input check + detect alphabet */ RUN(kalign_essential_input_check(msa, 0)); numseq = msa->numseq; DECLARE_TIMER(t_ensemble); if(!msa->quiet){ LOG_MSG("Ensemble alignment with %d runs", n_runs); } START_TIMER(t_ensemble); /* Resolve default gap penalties using aln_param_init. We need to detect biotype first. */ if(msa->biotype == ALN_BIOTYPE_UNDEF){ RUN(detect_alphabet(msa)); } /* Use aln_param_init to resolve defaults */ RUN(aln_param_init(&ap, msa->biotype, n_threads, type, gpo, gpe, tgpe)); base_gpo = ap->gpo; base_gpe = ap->gpe; base_tgpe = ap->tgpe; aln_param_free(ap); ap = NULL; /* Allocate POAR table and array to store completed alignments */ RUN(poar_table_alloc(&poar, numseq)); MMALLOC(alignments, sizeof(struct msa*) * n_runs); for(k = 0; k < n_runs; k++){ alignments[k] = NULL; } /* Run N alignments, extract POARs, and keep each alignment */ for(k = 0; k < n_runs; k++){ float run_gpo, run_gpe, run_tgpe, run_noise; uint64_t run_seed; resolve_run_params(base_gpo, base_gpe, base_tgpe, k, seed, &run_gpo, &run_gpe, &run_tgpe, &run_seed, &run_noise); /* Deep-copy MSA */ copy = NULL; RUN(msa_cpy(©, msa)); copy->quiet = 1; if(!msa->quiet){ LOG_MSG(" Run %d/%d (gpo=%.1f gpe=%.1f tgpe=%.1f noise=%.2f)", k + 1, n_runs, run_gpo, run_gpe, run_tgpe, run_noise); } /* Run alignment */ if(realign > 0){ RUN(kalign_run_realign(copy, n_threads, type, run_gpo, run_gpe, run_tgpe, refine, 0, dist_scale, vsm_amax, realign, use_seq_weights, consistency_anchors, consistency_weight)); }else{ RUN(kalign_run_seeded(copy, n_threads, type, run_gpo, run_gpe, run_tgpe, refine, 0, run_seed, run_noise, dist_scale, vsm_amax, use_seq_weights, consistency_anchors, consistency_weight)); } /* Extract POARs from the finalized alignment */ char** aln_seqs = NULL; MMALLOC(aln_seqs, sizeof(char*) * numseq); for(int i = 0; i < numseq; i++){ aln_seqs[i] = copy->sequences[i]->seq; } RUN(pos_matrix_from_msa(&pm, aln_seqs, numseq, copy->alnlen)); RUN(extract_poars(poar, pm, k)); pos_matrix_free(pm); pm = NULL; MFREE(aln_seqs); /* Keep this alignment for scoring later */ alignments[k] = copy; copy = NULL; } /* Score all alignments and select the best */ RUN(score_alignments(alignments, poar, numseq, n_runs, msa->quiet, &scores, &best_k)); if(!msa->quiet){ LOG_MSG(" Selected run %d (score=%.1f)", best_k + 1, scores[best_k]); } /* Save POAR table if requested */ if(save_poar_path != NULL){ RUN(poar_table_write(poar, save_poar_path)); if(!msa->quiet){ LOG_MSG(" Saved POAR table to %s", save_poar_path); } } /* When min_support > 0: explicit consensus threshold, skip selection. When min_support == 0: auto behavior (selection vs consensus). */ if(min_support > 0){ /* Explicit consensus: force consensus path */ RUN(build_consensus_from_poar(poar, msa, numseq, min_support, &consensus_msa)); use_consensus = 1; if(!msa->quiet){ LOG_MSG(" Using consensus alignment (min_support=%d)", min_support); } }else{ /* Try consensus approach: build a new alignment from POAR table. This can combine correct pairs from multiple runs, potentially outperforming any single run. */ double consensus_score = 0.0; int min_sup = (n_runs + 2) / 3; if(min_sup < 2) min_sup = 2; RUN(build_consensus_from_poar(poar, msa, numseq, min_sup, &consensus_msa)); /* Score consensus against POAR table */ RUN(score_single_msa(consensus_msa, poar, numseq, n_runs, &consensus_score)); if(!msa->quiet){ LOG_MSG(" Consensus score: %.1f (selection: %.1f)", consensus_score, scores[best_k]); } if(consensus_score > scores[best_k]){ use_consensus = 1; if(!msa->quiet){ LOG_MSG(" Using consensus alignment"); } }else{ kalign_free_msa(consensus_msa); consensus_msa = NULL; if(!msa->quiet){ LOG_MSG(" Keeping selection winner"); } } } /* Post-selection refinement: only when using selection (not consensus), re-run the winner with REFINE_CONFIDENT and keep if it scores higher. */ if(!use_consensus){ float ref_gpo, ref_gpe, ref_tgpe, ref_noise; uint64_t ref_seed; resolve_run_params(base_gpo, base_gpe, base_tgpe, best_k, seed, &ref_gpo, &ref_gpe, &ref_tgpe, &ref_seed, &ref_noise); copy = NULL; RUN(msa_cpy(©, msa)); copy->quiet = 1; if(!msa->quiet){ LOG_MSG(" Refining run %d...", best_k + 1); } RUN(kalign_run_seeded(copy, n_threads, type, ref_gpo, ref_gpe, ref_tgpe, KALIGN_REFINE_CONFIDENT, 0, ref_seed, ref_noise, dist_scale, vsm_amax, use_seq_weights, consistency_anchors, consistency_weight)); /* Score the refined alignment against the same POAR table */ double refined_score = 0.0; RUN(score_single_msa(copy, poar, numseq, n_runs, &refined_score)); if(!msa->quiet){ LOG_MSG(" Refined score: %.1f (was %.1f)", refined_score, scores[best_k]); } if(refined_score > scores[best_k]){ kalign_free_msa(alignments[best_k]); alignments[best_k] = copy; copy = NULL; if(!msa->quiet){ LOG_MSG(" Using refined alignment"); } }else{ kalign_free_msa(copy); copy = NULL; if(!msa->quiet){ LOG_MSG(" Keeping original alignment"); } } } MFREE(scores); scores = NULL; /* Copy the winning alignment back into the original MSA */ if(use_consensus){ RUN(copy_alignment_to_msa(msa, consensus_msa, numseq)); kalign_free_msa(consensus_msa); consensus_msa = NULL; }else{ RUN(copy_alignment_to_msa(msa, alignments[best_k], numseq)); } /* Compute per-residue and per-column confidence from POAR table */ RUN(compute_residue_confidence(poar, msa)); /* Sort back to original rank order */ RUN(msa_sort_rank(msa)); STOP_TIMER(t_ensemble); if(!msa->quiet){ GET_TIMING(t_ensemble); } DESTROY_TIMER(t_ensemble); /* Free all alignments */ for(k = 0; k < n_runs; k++){ if(alignments[k]) kalign_free_msa(alignments[k]); } MFREE(alignments); poar_table_free(poar); return OK; ERROR: if(copy) kalign_free_msa(copy); if(consensus_msa) kalign_free_msa(consensus_msa); if(pm) pos_matrix_free(pm); if(alignments){ for(k = 0; k < n_runs; k++){ if(alignments[k]) kalign_free_msa(alignments[k]); } MFREE(alignments); } poar_table_free(poar); if(scores) MFREE(scores); if(ap) aln_param_free(ap); return FAIL; } int kalign_consensus_from_poar(struct msa* msa, const char* poar_path, int min_support) { struct msa* consensus_msa = NULL; struct poar_table* poar = NULL; int numseq; ASSERT(msa != NULL, "No MSA"); ASSERT(poar_path != NULL, "No POAR file path"); ASSERT(min_support >= 1, "min_support must be >= 1"); RUN(kalign_essential_input_check(msa, 0)); numseq = msa->numseq; /* Read POAR table from file */ RUN(poar_table_read(&poar, poar_path)); if(poar->numseq != numseq){ ERROR_MSG("POAR file has %d sequences, input has %d", poar->numseq, numseq); } /* Build consensus at given min_support threshold */ RUN(build_consensus_from_poar(poar, msa, numseq, min_support, &consensus_msa)); /* Copy consensus alignment back into original MSA */ RUN(copy_alignment_to_msa(msa, consensus_msa, numseq)); kalign_free_msa(consensus_msa); consensus_msa = NULL; /* Compute per-residue and per-column confidence */ RUN(compute_residue_confidence(poar, msa)); RUN(msa_sort_rank(msa)); poar_table_free(poar); return OK; ERROR: if(consensus_msa) kalign_free_msa(consensus_msa); if(poar) poar_table_free(poar); return FAIL; } kalign-3.5.1/lib/src/ensemble.h000066400000000000000000000015771515023132300162720ustar00rootroot00000000000000#ifndef ENSEMBLE_H #define ENSEMBLE_H #include #ifdef ENSEMBLE_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; EXTERN int kalign_ensemble(struct msa* msa, int n_threads, int type, int n_runs, float gpo, float gpe, float tgpe, uint64_t seed, int min_support, const char* save_poar_path, int refine, float dist_scale, float vsm_amax, int realign, float use_seq_weights, int consistency_anchors, float consistency_weight); EXTERN int kalign_consensus_from_poar(struct msa* msa, const char* poar_path, int min_support); #undef ENSEMBLE_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/esl_stopwatch.c000066400000000000000000000350501515023132300173430ustar00rootroot00000000000000/* Tracking cpu/system/elapsed time used by a process. * * Credits: * - Thanks to Warren Gish for assistance. * - Includes portable high-resolution timer code * (C) 2012 David Robert Nadeau, http://NadeauSoftware.com/ * Creative Commons Attribution 3.0 Unported License * http://creativecommons.org/licenses/by/3.0/deed.en_US */ //#include "esl_config.h" //#include "easel.h" #include "tldevel.h" #define ESL_STOPWATCH_IMPORT #include "esl_stopwatch.h" #define TRUE 1 double stopwatch_getRealTime(void); /***************************************************************** * ESL_STOPWATCH object maintenance *****************************************************************/ /* Function: esl_stopwatch_Create() * * Purpose: Creates a new stopwatch. * * Returns: ptr to a new object; caller is * responsible for free'ing it with * . * * Throws: NULL on allocation failure. */ ESL_STOPWATCH * esl_stopwatch_Create(void) { ESL_STOPWATCH *w = NULL; MMALLOC(w, sizeof(ESL_STOPWATCH)); //ESL_ALLOC(w, sizeof(ESL_STOPWATCH)); w->elapsed = 0.; w->user = 0.; w->sys = 0.; return w; ERROR: esl_stopwatch_Destroy(w); return NULL; } /* Function: esl_stopwatch_Destroy() * * Purpose: Frees an . */ void esl_stopwatch_Destroy(ESL_STOPWATCH *w) { if (w){ free(w); } } /* Function: esl_stopwatch_Start() * * Purpose: Start a stopwatch. This sets the base * for elapsed, cpu, and system time difference * calculations by subsequent calls to * . * * Returns: on success. */ int esl_stopwatch_Start(ESL_STOPWATCH *w) { #if defined HAVE_TIMES && defined eslSTOPWATCH_HIGHRES /* System-dependent highest resolution */ times(&(w->cpu0)); w->t0 = stopwatch_getRealTime(); #elif HAVE_TIMES /* ... else fall back to POSIX... */ w->t0 = times(&(w->cpu0)); #else /* ... else fallback to ANSI C */ w->t0 = time(NULL); w->cpu0 = clock(); #endif w->elapsed = 0.; w->user = 0.; w->sys = 0.; return OK; } /* Function: esl_stopwatch_Stop() * * Purpose: Stop a stopwatch. Record and store elapsed, * cpu, and system time difference relative to the * last call to . * * Returns: on success. */ int esl_stopwatch_Stop(ESL_STOPWATCH *w) { #if defined eslSTOPWATCH_HIGHRES && defined HAVE_TIMES double t1; struct tms cpu1; double clk_tck; #elif defined HAVE_TIMES clock_t t1; struct tms cpu1; double clk_tck; #else time_t t1; clock_t cpu1; #endif #if defined eslSTOPWATCH_HIGHRES && defined HAVE_TIMES t1 = stopwatch_getRealTime(); w->elapsed = t1 - w->t0; clk_tck = (double) sysconf(_SC_CLK_TCK); times(&cpu1); w->user = (double) (cpu1.tms_utime + cpu1.tms_cutime - w->cpu0.tms_utime - w->cpu0.tms_cutime) / clk_tck; w->sys = (double) (cpu1.tms_stime + cpu1.tms_cstime - w->cpu0.tms_stime - w->cpu0.tms_cstime) / clk_tck; #elif defined HAVE_TIMES /* POSIX */ t1 = times(&cpu1); clk_tck = (double) sysconf(_SC_CLK_TCK); w->elapsed = (double) (t1 - w->t0) / clk_tck; w->user = (double) (cpu1.tms_utime + cpu1.tms_cutime - w->cpu0.tms_utime - w->cpu0.tms_cutime) / clk_tck; w->sys = (double) (cpu1.tms_stime + cpu1.tms_cstime - w->cpu0.tms_stime - w->cpu0.tms_cstime) / clk_tck; #else /* fallback to ANSI C */ t1 = time(NULL); cpu1 = clock(); w->elapsed = difftime(t1, w->t0); w->user = (double) (cpu1- w->cpu0) / (double) CLOCKS_PER_SEC; w->sys = 0.; /* no way to portably get system time in ANSI C */ #endif return OK; } /* format_time_string() * Date: SRE, Fri Nov 26 15:06:28 1999 [St. Louis] * * Purpose: Given a number of seconds, format into * hh:mm:ss.xx in a provided buffer. * * Args: buf - allocated space (128 is plenty!) * sec - number of seconds * do_frac - TRUE (1) to include hundredths of a sec */ static void format_time_string(char *buf, double sec, int do_frac) { int h, m, s, hs; h = (int) (sec / 3600.); m = (int) (sec / 60.) - h * 60; s = (int) (sec) - h * 3600 - m * 60; if (do_frac) { hs = (int) (sec * 100.) - h * 360000 - m * 6000 - s * 100; sprintf(buf, "%02d:%02d:%02d.%02d", h,m,s,hs); } else { sprintf(buf, "%02d:%02d:%02d", h,m,s); } } /* Function: esl_stopwatch_Display() * * Purpose: Output a usage summary line from a stopped * stopwatch, showing elapsed, cpu, and system time * between the last calls to * and . * * The string will be prepended to the output * line. Use <""> to prepend nothing. If is NULL, * a default <"CPU Time: "> prefix is used. * * For = <"CPU Time: "> an example output line is:\\ * * * Args: fp - output stream * w - stopped stopwatch * prefix - output line prefix ("" for nothing) * * Returns: on success. * * Throws: on any system write error, such as filled disk. */ int esl_stopwatch_Display(FILE *fp, ESL_STOPWATCH *w, char *prefix) { char buf[128]; /* (safely holds up to 10^14 years; I'll be dead by then) */ if (prefix == NULL) { if (fputs("CPU Time: ", fp) < 0){ ERROR_MSG( "stopwatch display write failed"); } }else{ if (fputs(prefix, fp) < 0){ ERROR_MSG( "stopwatch display write failed"); } } format_time_string(buf, w->user+w->sys, TRUE); #ifdef HAVE_TIMES if (fprintf(fp, "%.2fu %.2fs %s ", w->user, w->sys, buf) < 0){ ERROR_MSG( "stopwatch display write failed"); } #else if (fprintf(fp, "%.2fu %s ", w->user, buf) < 0){ ERROR_MSG( "stopwatch display write failed"); } #endif format_time_string(buf, w->elapsed, TRUE); if (fprintf(fp, "Elapsed: %s\n", buf) < 0){ ERROR_MSG( "stopwatch display write failed"); } return OK; ERROR: return FAIL; } int tl_stopwatch_Display(ESL_STOPWATCH *w) { char buf[128]; /* (safely holds up to 10^14 years; even I'll be dead by then) */ char buf2[128]; /* (safely holds up to 10^14 years; even I'll be dead by then) */ format_time_string(buf, w->user+w->sys, TRUE); format_time_string(buf2, w->elapsed, TRUE); #ifdef HAVE_TIMES LOG_MSG("CPU Time: %.2fu %.2fs %s Elapsed: %s", w->user, w->sys, buf,buf2); #else LOG_MSG("CPU Time: %.2fu %s Elapsed: %s", w->user, buf,buf2); #endif return OK; } /* Function: esl_stopwatch_GetElapsed() * Synopsis: Return the elapsed time in seconds * Incept: SRE, Fri Jan 8 10:10:37 2016 * * Purpose: After watch is Stop()'ed, calling * returns the elapsed time * in seconds. * * The resolution is system-dependent. */ double esl_stopwatch_GetElapsed(ESL_STOPWATCH *w) { return w->elapsed; } double tl_stopwatch_utime(ESL_STOPWATCH *w) { return w->user; } /* Function: esl_stopwatch_Include() * * Purpose: Merge the cpu and system times from a slave into * a master stopwatch. Both watches must be * stopped, and should not be stopped again unless * You Know What You're Doing. * * Elapsed time is not merged. Master is assumed * to be keeping track of the wall clock (real) time, * and the slave/worker watch is ignored. * * Useful in at least two cases. One is in * PVM, where we merge in the stopwatch(es) from separate * process(es) in a cluster. A second is in * threads, for broken pthreads/times() implementations * that lose track of cpu times used by spawned * threads. * * Args: master - stopwatch that's aggregating times * w - watch to add to the master. * * Returns: on success. */ int esl_stopwatch_Include(ESL_STOPWATCH *master, ESL_STOPWATCH *w) { master->user += w->user; master->sys += w->sys; return OK; } /***************************************************************** * Portable high resolution timing *****************************************************************/ #ifdef eslSTOPWATCH_HIGHRES /* The following code is * (C) 2012 David Robert Nadeau, http://NadeauSoftware.com * Creative Commons Attribution 3.0 Unported License * http://creativecommons.org/licenses/by/3.0/deed.en_US * * Reference: http://nadeausoftware.com/articles/2012/04/c_c_tip_how_measure_elapsed_real_time_benchmarking * * On resolution: * I believe that on Mac OS/X, the high performance timer has a resolution in units * of nanoseconds (at least on some platforms, including my laptop). However, calling * the esl_stopwatch_* functions themselves have overhead. The example driver is * a reasonable test of the minimal resolution, including call overhead; that gives * me about 0.1 microseconds (12 Jan 2016). */ #if defined(_WIN32) #include #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) #include /* POSIX flags */ #include /* clock_gettime(), time() */ #include /* gethrtime(), gettimeofday() */ #if defined(__MACH__) && defined(__APPLE__) #include #include #endif #else #error "Unable to define getRealTime( ) for an unknown OS." #endif /** * Returns the real time, in seconds, or -1.0 if an error occurred. * * Time is measured since an arbitrary and OS-dependent start time. * The returned real time is only useful for computing an elapsed time * between two calls to this function. */ static double stopwatch_getRealTime(void) { #if defined(_WIN32) FILETIME tm; ULONGLONG t; #if defined(NTDDI_WIN8) && NTDDI_VERSION >= NTDDI_WIN8 /* Windows 8, Windows Server 2012 and later. ---------------- */ GetSystemTimePreciseAsFileTime( &tm ); #else /* Windows 2000 and later. ---------------------------------- */ GetSystemTimeAsFileTime( &tm ); #endif t = ((ULONGLONG)tm.dwHighDateTime << 32) | (ULONGLONG)tm.dwLowDateTime; return (double)t / 10000000.0; #elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__))) /* HP-UX, Solaris. ------------------------------------------ */ return (double)gethrtime( ) / 1000000000.0; #elif defined(__MACH__) && defined(__APPLE__) /* OSX. ----------------------------------------------------- */ static double timeConvert = 0.0; if ( timeConvert == 0.0 ) { mach_timebase_info_data_t timeBase; (void)mach_timebase_info( &timeBase ); timeConvert = (double)timeBase.numer / (double)timeBase.denom / 1000000000.0; } return (double)mach_absolute_time( ) * timeConvert; #elif defined(_POSIX_VERSION) /* POSIX. --------------------------------------------------- */ #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) { struct timespec ts; #if defined(CLOCK_MONOTONIC_PRECISE) /* BSD. --------------------------------------------- */ const clockid_t id = CLOCK_MONOTONIC_PRECISE; #elif defined(CLOCK_MONOTONIC_RAW) /* Linux. ------------------------------------------- */ const clockid_t id = CLOCK_MONOTONIC_RAW; #elif defined(CLOCK_HIGHRES) /* Solaris. ----------------------------------------- */ const clockid_t id = CLOCK_HIGHRES; #elif defined(CLOCK_MONOTONIC) /* AIX, BSD, Linux, POSIX, Solaris. ----------------- */ const clockid_t id = CLOCK_MONOTONIC; #elif defined(CLOCK_REALTIME) /* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */ const clockid_t id = CLOCK_REALTIME; #else const clockid_t id = (clockid_t)-1; /* Unknown. */ #endif /* CLOCK_* */ if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 ) return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0; /* Fall thru. */ } #endif /* _POSIX_TIMERS */ /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */ struct timeval tm; gettimeofday( &tm, NULL ); return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0; #else return -1.0; /* Failed. */ #endif } #endif /*eslSTOPWATCH_HIGHRES*/ /***************************************************************** * Example of using the stopwatch module *****************************************************************/ #ifdef eslSTOPWATCH_EXAMPLE /*::cexcerpt::stopwatch_example::begin::*/ /* compile: gcc -g -Wall -I. -o example -DeslSTOPWATCH_EXAMPLE esl_stopwatch.c easel.c -lm * run: ./example */ #include "easel.h" #include "esl_stopwatch.h" int main(void) { ESL_STOPWATCH *w; double t = 0.; w = esl_stopwatch_Create(); /* This tests the minimum *practical* resolution of the clock, * inclusive of overhead of calling the stopwatch functions. * It gives me ~0.1 usec (12 Jan 2016). */ esl_stopwatch_Start(w); while (t == 0.) { esl_stopwatch_Stop(w); t = esl_stopwatch_GetElapsed(w); } printf("Elapsed time clock has practical resolution of around: %g sec\n", t); esl_stopwatch_Display(stdout, w, "CPU Time: "); esl_stopwatch_Destroy(w); return 0; } /*::cexcerpt::stopwatch_example::end::*/ #endif /*ESL_STOPWATCH_EXAMPLE*/ kalign-3.5.1/lib/src/esl_stopwatch.h000066400000000000000000000047371515023132300173600ustar00rootroot00000000000000/* Tracking cpu/system/elapsed time used by a process. * * SRE, Wed Feb 22 19:30:36 2006 [St. Louis] [moved to Easel] * SRE, Thu Aug 3 08:00:35 2000 [St. Louis] [moved to SQUID] * SRE, Fri Nov 26 14:54:21 1999 [St. Louis] [HMMER] */ #ifndef eslSTOPWATCH_INCLUDED #define eslSTOPWATCH_INCLUDED #include #ifdef ESL_STOPWATCH_IMPORT #define EXTERN #else #ifndef EXTERN #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif #endif #include #ifdef HAVE_TIMES #include #endif #ifdef HAVE_UNISTD_H #include /* need for sysconf() */ #endif typedef struct { #ifdef eslSTOPWATCH_HIGHRES double t0; /* baseline wall time from Nadeau routine */ #elif HAVE_TIMES clock_t t0; /* baseline wall time, POSIX times() */ #else time_t t0; /* baseline wall time from ANSI time() */ #endif #ifdef HAVE_TIMES struct tms cpu0; /* baseline CPU/system time, POSIX times() */ #else clock_t cpu0; /* baseline CPU time, fallback to ANSI clock() */ #endif /* elapsed/user/sys are t-t0 results for the last time the * watch was Stop()'ed. */ double elapsed; /* elapsed wall time, seconds */ double user; /* CPU time, seconds */ double sys; /* system time, seconds */ } ESL_STOPWATCH; EXTERN ESL_STOPWATCH *esl_stopwatch_Create(void); EXTERN void esl_stopwatch_Destroy(ESL_STOPWATCH *w); EXTERN int esl_stopwatch_Start(ESL_STOPWATCH *w); EXTERN int esl_stopwatch_Stop(ESL_STOPWATCH *w); EXTERN int esl_stopwatch_Display(FILE *fp, ESL_STOPWATCH *w, char *prefix); EXTERN int tl_stopwatch_Display(ESL_STOPWATCH *w); EXTERN double esl_stopwatch_GetElapsed(ESL_STOPWATCH *w); EXTERN double tl_stopwatch_utime(ESL_STOPWATCH *w); EXTERN int esl_stopwatch_Include(ESL_STOPWATCH *master, ESL_STOPWATCH *w); #define DECLARE_TIMER(n) ESL_STOPWATCH* timer_##n = esl_stopwatch_Create(); #define START_TIMER(n) esl_stopwatch_Start(timer_##n); #define STOP_TIMER(n) esl_stopwatch_Stop(timer_##n); #define GET_TIMING(n) tl_stopwatch_Display(timer_##n); #define GET_ELAPSED(n) esl_stopwatch_GetElapsed(timer_##n); #define GET_USERTIME(n) tl_stopwatch_utime(timer_##n); #define DESTROY_TIMER(n) esl_stopwatch_Destroy(timer_##n); #undef ESL_STOPWATCH_IMPORT #undef EXTERN #endif /*eslSTOPWATCH_INCLUDED*/ kalign-3.5.1/lib/src/euclidean_dist.c000066400000000000000000000115231515023132300174370ustar00rootroot00000000000000#ifdef HAVE_AVX2 #include #include #include #endif #include "float.h" #include "tldevel.h" #include "tlrng.h" #include "esl_stopwatch.h" #define EUCLIDEAN_DIST_IMPORT #include "euclidean_dist.h" /* These functions were taken from: */ /* https://stackoverflow.com/questions/6996764/fastest-way-to-do-horizontal-float-vector-sum-on-x86 */ #ifdef HAVE_AVX2 float hsum256_ps_avx(__m256 v); float hsum_ps_sse3(__m128 v); #endif #ifdef UTEST_EDIST int main(void) { struct rng_state* rng; float** mat = NULL; double r; float d1; float d2; int i,j,c; int max_iter = 10; int num_element = 128; // mat = galloc(mat,1000,8,0.0); //void* _mm_malloc (size_t size, size_t align) MMALLOC(mat, sizeof(float*)* 100); for(i = 0; i < 100;i++){ mat[i] = NULL; #ifdef HAVE_AVX2 mat[i] = _mm_malloc(sizeof(float)*num_element, 32); #else MMALLOC(mat[i],sizeof(float)*num_element); #endif } RUNP( rng =init_rng(0)); //srand48_r(time(NULL), &randBuffer); for(i =0; i < 100;i++){ for(j = 0; j 10e-6){ ERROR_MSG("DIFFER: %d\t%d\t%f\t%f (%e %e)\n", i,j,d1,d2, fabsf(d1-d2), FLT_EPSILON); } } } #endif DECLARE_TIMER(t); LOG_MSG("Timing serial"); START_TIMER(t); for(c = 0; c < max_iter;c++){ for(i = 0; i < 100;i++){ for(j = 0; j <= i;j++){ edist_serial(mat[i], mat[j], num_element, &d1); } } } STOP_TIMER(t); GET_TIMING(t); //LOG_MSG("%f\tsec.",GET_TIMING(t)); #ifdef HAVE_AVX2 LOG_MSG("Timing AVX"); START_TIMER(t); for(c = 0; c < max_iter; c++){ for(i = 0; i < 100;i++){ for(j = 0; j <= i;j++){ edist_256(mat[i], mat[j], num_element, &d2); } } } STOP_TIMER(t); GET_TIMING(t); //LOG_MSG("%f\tsec.",GET_TIMING(t)); #endif for(i = 0; i < 100;i++){ #ifdef HAVE_AVX2 _mm_free(mat[i]); #else MFREE(mat[i]); #endif } MFREE(mat); MFREE(rng); DESTROY_TIMER(t); return EXIT_SUCCESS; ERROR: return EXIT_FAILURE; } #endif int edist_serial(const float* a,const float* b,const int len, float* ret) { int i; float d = 0.0f; float t; for(i = 0; i < len;i++){ t = (a[i] - b[i]); d += t *t; } *ret = sqrtf(d); return OK; } int edist_serial_d(const double* a,const double* b,const int len, double* ret) { int i; double d = 0.0f; double t; for(i = 0; i < len;i++){ t = (a[i] - b[i]); d += t *t; } *ret = sqrt(d); return OK; } #ifdef HAVE_AVX2 int edist_256(const float* a,const float* b, const int len, float* ret) { float d = 0.0f; register int i; __m256 xmm1;// = _mm256_load_ps(a); __m256 xmm2;// = _mm256_load_ps(b); __m256 r = _mm256_set1_ps(0.0f); for(i = 0;i < len;i+=8){ xmm1 = _mm256_load_ps(a); xmm2 = _mm256_load_ps(b); xmm1 = _mm256_sub_ps(xmm1, xmm2); xmm1 = _mm256_mul_ps(xmm1, xmm1); r = _mm256_add_ps(r, xmm1); a+=8; b+=8; } d = hsum256_ps_avx(r); *ret = sqrtf(d); return OK; } float hsum256_ps_avx(__m256 v) { __m128 vlow = _mm256_castps256_ps128(v); __m128 vhigh = _mm256_extractf128_ps(v, 1); // high 128 vlow = _mm_add_ps(vlow, vhigh); // add the low 128 return hsum_ps_sse3(vlow); // and inline the sse3 version, which is optimal for AVX // (no wasted instructions, and all of them are the 4B minimum) } float hsum_ps_sse3(__m128 v) { __m128 shuf = _mm_movehdup_ps(v); // broadcast elements 3,1 to 2,0 __m128 sums = _mm_add_ps(v, shuf); shuf = _mm_movehl_ps(shuf, sums); // high half -> low half sums = _mm_add_ss(sums, shuf); return _mm_cvtss_f32(sums); } #endif kalign-3.5.1/lib/src/euclidean_dist.h000066400000000000000000000007531515023132300174470ustar00rootroot00000000000000#ifndef EUCLIDIAN_DIST_H #define EUCLIDIAN_DIST_H #ifdef EUCLIDEAN_DIST_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif EXTERN int edist_256(const float* a,const float* b, const int len, float* ret); EXTERN int edist_serial(const float* a,const float* b,const int len, float* ret); EXTERN int edist_serial_d(const double* a,const double* b,const int len, double* ret); #undef EUCLIDEAN_DIST_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/io.h000066400000000000000000000002131515023132300150710ustar00rootroot00000000000000#ifndef IO_H #define IO_H #ifdef IO_IMPORT #define EXTERN #else #define EXTERN extern #endif #undef IO_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/mod_tldevel.h000066400000000000000000000002151515023132300167620ustar00rootroot00000000000000#ifndef MOD_TLDEVEL_H #define MOD_TLDEVEL_H #include "tldevel.h" #include "tlrng.h" #include "tlmisc.h" #include "esl_stopwatch.h" #endif kalign-3.5.1/lib/src/msa_alloc.c000066400000000000000000000103741515023132300164200ustar00rootroot00000000000000#include "tldevel.h" #include "msa_struct.h" #include "alphabet.h" #define MSA_ALLOC_IMPORT #include "msa_alloc.h" int alloc_msa(struct msa** msa, int numseq) { struct msa* m = NULL; int i; MMALLOC(m, sizeof(struct msa)); m->sequences = NULL; m->alloc_numseq = numseq; m->numseq = 0; m->num_profiles = 0; m->L = ALPHA_UNDEFINED; m->biotype = ALN_BIOTYPE_UNDEF; m->aligned = 0; m->alnlen = 0; m->quiet = 0; m->seq_distances = NULL; m->col_confidence = NULL; m->seq_weights = NULL; m->plen = NULL; m->sip = NULL; m->nsip = NULL; m->consistency_table = NULL; MMALLOC(m->sequences, sizeof(struct msa_seq*) * m->alloc_numseq); for(i = 0; i < m->alloc_numseq;i++){ m->sequences[i] = NULL; RUN(alloc_msa_seq(&m->sequences[i])); } for(i = 0; i < 128; i++){ m->letter_freq[i] = 0; } *msa = m; return OK; ERROR: kalign_free_msa(m); return FAIL; } int resize_msa(struct msa* msa) { int i; int old_size; old_size = msa->alloc_numseq; msa->alloc_numseq = msa->alloc_numseq + 512; MREALLOC(msa->sequences, sizeof(struct msa_seq*) * msa->alloc_numseq); for(i = old_size; i < msa->alloc_numseq;i++){ msa->sequences[i] = NULL; RUN(alloc_msa_seq(&msa->sequences[i])); } return OK; ERROR: return FAIL; } void kalign_free_msa(struct msa* msa) { int i; if(msa){ for(i = 0; i < msa->alloc_numseq;i++){ if(msa->sequences[i]){ free_msa_seq(msa->sequences[i]); } } if(msa->seq_distances){ MFREE(msa->seq_distances); } if(msa->col_confidence){ MFREE(msa->col_confidence); } if(msa->seq_weights){ MFREE(msa->seq_weights); } for (i = msa->num_profiles;i--;){ if(msa->sip[i]){ MFREE(msa->sip[i]); } } if(msa->plen){ MFREE(msa->plen); } if(msa->sip){ MFREE(msa->sip); } if(msa->nsip){ MFREE(msa->nsip); } MFREE(msa->sequences); MFREE(msa); } } int alloc_msa_seq(struct msa_seq** s) { struct msa_seq* seq = NULL; int i; MMALLOC(seq, sizeof(struct msa_seq)); seq->name = NULL; seq->seq = NULL; seq->s = NULL; seq->gaps = NULL; seq->confidence = NULL; seq->len = 0; seq->rank = 0; /* seq->name_len = 128; */ seq->alloc_len = 512; MMALLOC(seq->name, sizeof(char)* MSA_NAME_LEN); MMALLOC(seq->seq, sizeof(char) * seq->alloc_len); MMALLOC(seq->s, sizeof(uint8_t) * seq->alloc_len); MMALLOC(seq->gaps, sizeof(int) * (seq->alloc_len+1)); for(i =0;i < seq->alloc_len+1;i++){ seq->gaps[i] = 0; } *s = seq; return OK; ERROR: free_msa_seq(seq); return FAIL; } int resize_msa_seq(struct msa_seq* seq) { int old_len; int i; old_len = seq->alloc_len; seq->alloc_len = seq->alloc_len + 512; MREALLOC(seq->seq, sizeof(char) * seq->alloc_len); MREALLOC(seq->s, sizeof(uint8_t) * seq->alloc_len); MREALLOC(seq->gaps, sizeof(int) * (seq->alloc_len+1)); for(i = old_len+1;i < seq->alloc_len+1;i++){ seq->gaps[i] = 0; } return OK; ERROR: return FAIL; } void free_msa_seq(struct msa_seq* seq) { if(seq){ MFREE(seq->name); MFREE(seq->seq); MFREE(seq->s); MFREE(seq->gaps); if(seq->confidence){ MFREE(seq->confidence); } MFREE(seq); } } kalign-3.5.1/lib/src/msa_alloc.h000066400000000000000000000007331515023132300164230ustar00rootroot00000000000000#ifndef MSA_ALLOC_H #define MSA_ALLOC_H #ifdef MSA_ALLOC_IMPORT #define EXTERN #else #define EXTERN extern #endif struct msa; struct msa_seq; EXTERN int alloc_msa(struct msa** msa, int numseq); EXTERN int resize_msa(struct msa* msa); EXTERN void kalign_free_msa(struct msa* msa); EXTERN int alloc_msa_seq(struct msa_seq** s); EXTERN int resize_msa_seq(struct msa_seq* seq); EXTERN void free_msa_seq(struct msa_seq* seq); #undef MSA_ALLOC_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/msa_check.c000066400000000000000000000250311515023132300163770ustar00rootroot00000000000000#include "tldevel.h" #include #include /* #include "strnlen_compat.h" */ #include "msa_struct.h" #define MSA_CHECK_IMPORT #include "msa_check.h" struct sort_struct_name_chksum{ struct msa_seq* seq; char** name; int chksum; int action; }; static int GCGchecksum(char *seq, int len); static int sort_by_name(const void *a, const void *b); static int sort_by_chksum(const void *a, const void *b); static int sort_by_both(const void *a, const void *b); int sort_seq_by_len(const void *a, const void *b); int kalign_sort_msa(struct msa *msa) { struct sort_struct_name_chksum** a = NULL; MMALLOC(a, sizeof(struct sort_struct_name_chksum *) * msa->numseq); for(int i = 0; i < msa->numseq;i++){ a[i] = NULL; MMALLOC(a[i], sizeof(struct sort_struct_name_chksum)); a[i]->seq = msa->sequences[i]; a[i]->name = &msa->sequences[i]->name; a[i]->chksum = GCGchecksum(msa->sequences[i]->seq, msa->sequences[i]->len); a[i]->action = 0; } qsort(a, msa->numseq, sizeof(struct sort_struct*),sort_by_both); for(int i = 0; i < msa->numseq;i++){ msa->sequences[i] = a[i]->seq; } for(int i = 0; i < msa->numseq;i++){ MFREE(a[i]); } MFREE(a); return OK; ERROR: if(a){ for(int i = 0; i < msa->numseq;i++){ MFREE(a[i]); } MFREE(a); } return FAIL; } int kalign_essential_input_check(struct msa *msa, int exit_on_error) { int problem_len0 = 0; ASSERT(msa != NULL, "No alignment"); ASSERT(msa->numseq > 1,"only %d sequences found.", msa->numseq); for(int i = 0; i < msa->numseq;i++){ if(msa->sequences[i]->len == 0){ if(!msa->quiet){ WARNING_MSG("No sequence found for sequence %s ",msa->sequences[i]->name); } problem_len0++; } msa->sequences[i]->rank = i; } if(!exit_on_error){ /* Here we attempt to fix the zero length problem */ if(problem_len0){ if(problem_len0 == 1){ if(!msa->quiet){ LOG_MSG("Removing %d sequence with a length of 0.", problem_len0); } }else{ if(!msa->quiet){ LOG_MSG("Removing %d sequences with a length of 0.",problem_len0); } } struct msa_seq** tmp = NULL; MMALLOC(tmp, sizeof(struct msa_seq* ) * msa->alloc_numseq); int c = 0; int e = msa->numseq-1; for(int i = 0 ; i < msa->numseq;i++){ if(msa->sequences[i]->len){ tmp[c] = msa->sequences[i]; c++; }else{ tmp[e] = msa->sequences[i]; e--; } } for(int i = msa->numseq; i < msa->alloc_numseq;i++){ tmp[i] = NULL; } MFREE(msa->sequences); msa->sequences = tmp; /* for(int i = msa->numseq-500; i < msa->numseq;i++){ */ /* LOG_MSG("%d\t%s", msa->sequences[i]->len,msa->sequences[i]->name); */ /* } */ /* LOG_MSG("%d %d %d ", msa->numseq, msa->numseq -c , problem_len0); */ /* qsort(msa->sequences, msa->numseq, sizeof(struct msa_seq*),sort_seq_by_len); */ /* int c = 0; */ /* for(int i = msa->numseq-1;i >= 0;i--){ */ /* if(msa->sequences[i]->len != 0){ */ /* c = i; */ /* break; */ /* } */ /* } */ /* c++; */ msa->numseq = c; ASSERT(msa->numseq > 1,"only %d sequences found.", msa->numseq); /* exit(0); */ } }else{ ERROR_MSG("%d sequences found with length 0.", problem_len0); } return OK; ERROR: return FAIL; } int kalign_check_msa(struct msa* msa, int exit_on_error) { char* tmp_name = NULL; /* char* tmp_ptr; */ struct sort_struct_name_chksum** a = NULL; int i; /* int j; */ int c; int l; MMALLOC(a, sizeof(struct sort_struct_name_chksum *) * msa->numseq); for(i = 0; i < msa->numseq;i++){ a[i] = NULL; MMALLOC(a[i], sizeof(struct sort_struct_name_chksum)); a[i]->seq = msa->sequences[i]; a[i]->name = &msa->sequences[i]->name; a[i]->chksum = GCGchecksum(msa->sequences[i]->seq, msa->sequences[i]->len); a[i]->action = 0; } qsort(a, msa->numseq, sizeof(struct sort_struct*),sort_by_name); for(i = 1; i < msa->numseq;i++){ if(strncmp(*a[i-1]->name, *a[i]->name,MSA_NAME_LEN) == 0){ /* WARNING_MSG("Name: %s is duplicated", a[i]->name); */ if(a[i-1]->chksum == a[i]->chksum){ if(!msa->quiet){ LOG_MSG("Found duplicated sequence:\n%s checksum: %d\n%s checksum: %d\n", *a[i-1]->name, a[i-1]->chksum, *a[i]->name, a[i]->chksum); } a[i-1]->action = 1; a[i]->action = 1; if(exit_on_error){ ERROR_MSG("Same seq with same name!"); } }else{ if(!msa->quiet){ WARNING_MSG("Found sequence pair with same name but different sequence:\n%s checksum: %d\n%s checksum: %d\n", *a[i-1]->name, a[i-1]->chksum, *a[i]->name, a[i]->chksum); } a[i-1]->action = 1; a[i]->action = 1; if(exit_on_error){ ERROR_MSG("This is a problem if we want to compare alignments down the track. Will append \"_X\" to the sequence name."); }else{ WARNING_MSG("This is a problem if we want to compare alignments down the track. Will append \"_X\" to the sequence name."); } } } } c = 1; for(i = 0; i < msa->numseq;i++){ if(a[i]->action){ tmp_name = NULL; l = strnlen(*a[i]->name, MSA_NAME_LEN)+ 16; MMALLOC(tmp_name, sizeof(char) * l); snprintf(tmp_name, l, "%s_%d",*a[i]->name,c); MFREE(*a[i]->name); *a[i]->name = tmp_name; c++; } } qsort(a, msa->numseq, sizeof(struct sort_struct*),sort_by_chksum); for(i = 1; i < msa->numseq;i++){ if(a[i-1]->chksum == a[i]->chksum){ if(!msa->quiet){ WARNING_MSG("Found identical sequences:\n%s checksum: %d\n%s checksum: %d\n", *a[i-1]->name, a[i-1]->chksum, *a[i]->name, a[i]->chksum); } } } for(i = 0; i < msa->numseq;i++){ MFREE(a[i]); } MFREE(a); return OK; ERROR: if(a){ for(i = 0; i < msa->numseq;i++){ MFREE(a[i]); } MFREE(a); } return FAIL; } int sort_by_both(const void *a, const void *b) { struct sort_struct_name_chksum* const *one = a; struct sort_struct_name_chksum* const *two = b; if(strncmp(*(*one)->name, *(*two)->name,MSA_NAME_LEN) < 0){ return -1; }else if(strncmp(*(*one)->name, *(*two)->name,MSA_NAME_LEN) == 0 ){ if((*one)->chksum > (*two)->chksum){ return -1; }else{ return 1; } }else{ return 1; } } int sort_by_name(const void *a, const void *b) { struct sort_struct_name_chksum* const *one = a; struct sort_struct_name_chksum* const *two = b; if(strncmp(*(*one)->name, *(*two)->name,MSA_NAME_LEN) < 0){ return -1; }else{ return 1; } } int sort_by_chksum(const void *a, const void *b) { struct sort_struct_name_chksum* const *one = a; struct sort_struct_name_chksum* const *two = b; if((*one)->chksum > (*two)->chksum){ return -1; }else{ return 1; } } int sort_seq_by_len(const void *a, const void *b) { struct msa_seq* const *one = a; struct msa_seq* const *two = b; if((*one)->len > (*two)->len){ return -1; }else{ return 1; } } /* Taken from squid library by Sean Eddy */ int GCGchecksum(char *seq, int len) { int i; /* position in sequence */ int chk = 0; /* calculated checksum */ for (i = 0; i < len; i++){ chk = (chk + (i % 57 + 1) * (toupper((int) seq[i]))) % 10000; } return chk; } kalign-3.5.1/lib/src/msa_check.h000066400000000000000000000006451515023132300164100ustar00rootroot00000000000000#ifndef MSA_CHECK_H #define MSA_CHECK_H #ifdef MSA_CHECK_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; EXTERN int kalign_essential_input_check(struct msa *msa, int exit_on_error); EXTERN int kalign_check_msa(struct msa* msa, int exit_on_error); EXTERN int kalign_sort_msa(struct msa *msa); #undef MSA_CHECK_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/msa_cmp.c000066400000000000000000000506211515023132300161040ustar00rootroot00000000000000#include "tldevel.h" #include #include "msa_struct.h" #include "msa_check.h" #include "msa_op.h" #define MSA_CMP_IMPORT #include "msa_cmp.h" struct cmp_stats { uint64_t ref_total_aligned_pairs; uint64_t ref_total_gap_pairs; uint64_t identical_aligned; uint64_t identical_gaps; uint64_t test_total_aligned_pairs; uint64_t test_total_gap_pairs; }; struct detailed_pair_stats { int64_t ref_scored_pairs; int64_t test_pairs; int64_t common_scored; /* matches in scored columns → for recall */ int64_t common_all; /* all matches → for precision */ }; static int compare_pair(char *seq1A, char *seq2A, char *seq1B, char *seq2B, int len_a, int len_b, struct cmp_stats *stat); static int compare_pair_detailed(char *seq1A, char *seq2A, char *seq1B, char *seq2B, int len_a, int len_b, int *scored_cols, struct detailed_pair_stats *stat); int kalign_msa_compare(struct msa *r, struct msa *t, float *score) { struct cmp_stats* stat = NULL; ASSERT(r != NULL, "No reference alignment"); ASSERT(t != NULL, "No test alignment"); if(r->aligned == ALN_STATUS_ALIGNED){ finalise_alignment(r); } if(t->aligned == ALN_STATUS_ALIGNED){ finalise_alignment(t); } RUN(kalign_check_msa(r,1)); RUN(kalign_check_msa(t,1)); kalign_sort_msa(r); kalign_sort_msa(t); MMALLOC(stat, sizeof(struct cmp_stats)); stat->identical_gaps = 0; stat->identical_aligned = 0; stat->ref_total_gap_pairs = 0; stat->ref_total_aligned_pairs = 0; stat->test_total_gap_pairs = 0; stat->test_total_aligned_pairs = 0; /* float s = 0.0; */ /* float c = 0.0; */ for(int i = 0; i < r->numseq;i++){ for(int j = i + 1; j < r->numseq;j++){ compare_pair(r->sequences[i]->seq, r->sequences[j]->seq, t->sequences[i]->seq, t->sequences[j]->seq, r->alnlen, t->alnlen, stat ); } } /* LOG_MSG("%ld %ld %ld %ld %ld %ld", */ /* stat->ref_total_aligned_pairs, */ /* stat->ref_total_gap_pairs, */ /* stat->test_total_aligned_pairs, */ /* stat->test_total_gap_pairs, */ /* stat->identical_aligned, */ /* stat->identical_gaps); */ double a; double b; /* Pairs of aligned (and unaligned) residues in common with reference divided by number of pairs in reference */ a = (double) (stat->identical_aligned+ stat->identical_gaps ); b = (double) (stat->ref_total_aligned_pairs + stat->ref_total_gap_pairs); /* LOG_MSG("Score: %f (%f / %f)", 100.0 * a / b, a,b); */ /* Pairs of aligned residues in common with reference divided by number of pairs in reference */ a = (double) (stat->identical_aligned); b = (double) (stat->ref_total_aligned_pairs); /* LOG_MSG("Score: %f (%f / %f)", 100.0 * a / b, a,b); */ /* Pairs of aligned (and unaligned) residues in common with reference , divided by average number if pairs */ a = (double) (stat->identical_aligned+ stat->identical_gaps ); b = (double)(stat->ref_total_aligned_pairs + stat->ref_total_gap_pairs + stat->test_total_aligned_pairs + stat->test_total_gap_pairs)/ 2.0; /* LOG_MSG("Score: %f (%f / %f)", 100.0 * a / b, a,b); */ /* Pairs of aligned residues in common with reference , divided by average number if pairs */ a = (double) (stat->identical_aligned ); b = (double)(stat->ref_total_aligned_pairs + stat->test_total_aligned_pairs) / 2.0; /* LOG_MSG("Score: %f (%f / %f)", 100.0 * a / b, a,b); */ /* LOG_MSG("ORG Score: %f", s); */ a = (double) (stat->identical_aligned+ stat->identical_gaps ); b = (double) (stat->ref_total_aligned_pairs + stat->ref_total_gap_pairs); *score = 100.0 * a / b; /* exit(0); */ MFREE(stat); return OK; ERROR: return FAIL; } int compare_pair(char* seq1A, char* seq2A, char* seq1B, char* seq2B, int len_a, int len_b,struct cmp_stats* stat) { int* codes1_A = NULL; int* codes2_A = NULL; int* codes1_B = NULL; int* codes2_B = NULL; int p1; int p2; int g1; int g2; if(len_a == 0 || len_b == 0){ return OK; } MMALLOC(codes1_A, sizeof(int) * len_a); MMALLOC(codes2_A, sizeof(int) * len_a); MMALLOC(codes1_B, sizeof(int) * len_b); MMALLOC(codes2_B, sizeof(int) * len_b); /* process aln A */ p1 = -1; p2 = -1; for(int i = 0; i < len_a;i++){ g1 = 0; g2 = 0; if(isalpha((int) seq1A[i])){ p1++; }else{ g1 = 1; } if(isalpha((int) seq2A[i])){ p2++; }else{ g2 = 1; } if(!g1 && ! g2){ stat->ref_total_aligned_pairs++; codes1_A[p1] = p2; stat->ref_total_aligned_pairs++; codes2_A[p2] = p1; }else if(!g1 && g2){ stat->ref_total_gap_pairs++; codes1_A[p1] = -1; }else if(g1 && !g2){ stat->ref_total_gap_pairs++; codes2_A[p2] = -1; } } /* process aln B */ p1 = -1; p2 = -1; for(int i = 0; i < len_b;i++){ g1 = 0; g2 = 0; if(isalpha((int) seq1B[i])){ p1++; }else{ g1 = 1; } if(isalpha((int) seq2B[i])){ p2++; }else{ g2 = 1; } if(!g1 && ! g2){ stat->test_total_aligned_pairs++; codes1_B[p1] = p2; stat->test_total_aligned_pairs++; codes2_B[p2] = p1; }else if(!g1 && g2){ stat->test_total_gap_pairs++; codes1_B[p1] = -1; }else if(g1 && !g2){ stat->test_total_gap_pairs++; codes2_B[p2] = -1; } } /* LOG_MSG("P1: %d P2: %d len b: %d", p1, p2,len_b); */ /* fprintf(stdout,"%s\n%s\n",seq1A,seq2A); */ /* fprintf(stdout,"%s\n%s\n",seq1B, seq2B); */ /* fprintf(stdout,"\n"); */ for(int i = 0; i <= p1;i++){ if(codes1_A[i] != -1){ if(codes1_A[i] == codes1_B[i]){ stat->identical_aligned++; } }else{ if(codes1_A[i] == codes1_B[i]){ stat->identical_gaps++; } } /* if(codes1_A[i] != codes1_B[i]){ */ /* d += 1.0; */ /* /\* LOG_MSG("%d %d %d", i, codes1_A[i], codes1_B[i]); *\/ */ /* } */ } for(int i = 0; i <= p2;i++){ if(codes2_A[i] != -1){ if(codes2_A[i] == codes2_B[i]){ stat->identical_aligned++; } }else{ if(codes2_A[i] == codes2_B[i]){ stat->identical_gaps++; } } /* if(codes2_A[i] != codes2_B[i]){ */ /* d += 1.0; */ /* /\* LOG_MSG("%d %d %d (second seq)", i, codes1_A[i], codes1_B[i]); *\/ */ /* } */ } /* s = d /(float)( p1 + p2); */ /* LOG_MSG("score: %f", s); */ /* *score = s; */ MFREE(codes1_A); MFREE(codes1_B); MFREE(codes2_A); MFREE(codes2_B); return OK; ERROR: MFREE(codes1_A); MFREE(codes1_B); MFREE(codes2_A); MFREE(codes2_B); return FAIL; } /* Shared helper: compute POAR + TC scores given a pre-built column mask. */ static int compare_with_mask_helper(struct msa *r, struct msa *t, int *scored_cols, struct poar_score *out) { struct detailed_pair_stats dstat; int tc_correct = 0; int tc_total = 0; /* Accumulate POAR stats over all sequence pairs */ dstat.ref_scored_pairs = 0; dstat.test_pairs = 0; dstat.common_scored = 0; dstat.common_all = 0; for(int i = 0; i < r->numseq; i++){ for(int j = i + 1; j < r->numseq; j++){ compare_pair_detailed( r->sequences[i]->seq, r->sequences[j]->seq, t->sequences[i]->seq, t->sequences[j]->seq, r->alnlen, t->alnlen, scored_cols, &dstat ); } } /* TC score: for each scored column in reference, check if all non-gap residues map to the same column in the test alignment. Build residue-to-test-column map for each sequence. */ { int** res_to_tcol = NULL; MMALLOC(res_to_tcol, sizeof(int*) * t->numseq); for(int s = 0; s < t->numseq; s++){ res_to_tcol[s] = NULL; MMALLOC(res_to_tcol[s], sizeof(int) * (t->sequences[s]->len + 1)); } /* Fill residue→test_column map */ for(int s = 0; s < t->numseq; s++){ int p = 0; for(int c = 0; c < t->alnlen; c++){ if(isalpha((int)t->sequences[s]->seq[c])){ res_to_tcol[s][p] = c; p++; } } } /* Check each scored reference column */ for(int c = 0; c < r->alnlen; c++){ if(!scored_cols[c]){ continue; } int first_tcol = -1; int all_same = 1; int nres = 0; /* Count non-gap residues at this column */ for(int s = 0; s < r->numseq; s++){ if(isalpha((int)r->sequences[s]->seq[c])){ nres++; } } if(nres < 2){ /* Need at least 2 residues for a "pair" column */ continue; } tc_total++; /* Check if all residues map to same test column */ { int pos[r->numseq]; for(int s = 0; s < r->numseq; s++){ pos[s] = 0; } for(int cc = 0; cc < c; cc++){ for(int s = 0; s < r->numseq; s++){ if(isalpha((int)r->sequences[s]->seq[cc])){ pos[s]++; } } } for(int s = 0; s < r->numseq; s++){ if(isalpha((int)r->sequences[s]->seq[c])){ int tcol = res_to_tcol[s][pos[s]]; if(first_tcol < 0){ first_tcol = tcol; }else if(tcol != first_tcol){ all_same = 0; break; } } } } if(all_same){ tc_correct++; } } for(int s = 0; s < t->numseq; s++){ MFREE(res_to_tcol[s]); } MFREE(res_to_tcol); } /* Fill output */ out->ref_pairs = dstat.ref_scored_pairs; out->test_pairs = dstat.test_pairs; out->common = dstat.common_scored; if(dstat.ref_scored_pairs > 0){ out->recall = (double)dstat.common_scored / (double)dstat.ref_scored_pairs; }else{ out->recall = 0.0; } if(dstat.test_pairs > 0){ out->precision = (double)dstat.common_all / (double)dstat.test_pairs; }else{ out->precision = 0.0; } if(out->recall + out->precision > 0.0){ out->f1 = 2.0 * out->recall * out->precision / (out->recall + out->precision); }else{ out->f1 = 0.0; } if(tc_total > 0){ out->tc = (double)tc_correct / (double)tc_total; }else{ out->tc = 0.0; } return OK; ERROR: return FAIL; } int kalign_msa_compare_detailed(struct msa *r, struct msa *t, float max_gap_frac, struct poar_score *out) { int* scored_cols = NULL; ASSERT(r != NULL, "No reference alignment"); ASSERT(t != NULL, "No test alignment"); ASSERT(out != NULL, "No output struct"); if(r->aligned == ALN_STATUS_ALIGNED){ finalise_alignment(r); } if(t->aligned == ALN_STATUS_ALIGNED){ finalise_alignment(t); } RUN(kalign_check_msa(r, 1)); RUN(kalign_check_msa(t, 1)); kalign_sort_msa(r); kalign_sort_msa(t); /* Build scored column mask from reference alignment */ MMALLOC(scored_cols, sizeof(int) * r->alnlen); for(int c = 0; c < r->alnlen; c++){ if(max_gap_frac < 0.0f){ scored_cols[c] = 1; }else{ int ngaps = 0; for(int s = 0; s < r->numseq; s++){ if(!isalpha((int)r->sequences[s]->seq[c])){ ngaps++; } } float gf = (float)ngaps / (float)r->numseq; scored_cols[c] = (gf <= max_gap_frac) ? 1 : 0; } } RUN(compare_with_mask_helper(r, t, scored_cols, out)); MFREE(scored_cols); return OK; ERROR: MFREE(scored_cols); return FAIL; } int kalign_msa_compare_with_mask(struct msa *r, struct msa *t, int *scored_cols, int n_cols, struct poar_score *out) { ASSERT(r != NULL, "No reference alignment"); ASSERT(t != NULL, "No test alignment"); ASSERT(scored_cols != NULL, "No column mask"); ASSERT(out != NULL, "No output struct"); if(r->aligned == ALN_STATUS_ALIGNED){ finalise_alignment(r); } if(t->aligned == ALN_STATUS_ALIGNED){ finalise_alignment(t); } RUN(kalign_check_msa(r, 1)); RUN(kalign_check_msa(t, 1)); kalign_sort_msa(r); kalign_sort_msa(t); ASSERT(n_cols == r->alnlen, "Mask length (%d) != reference alignment length (%d)", n_cols, r->alnlen); RUN(compare_with_mask_helper(r, t, scored_cols, out)); return OK; ERROR: return FAIL; } int compare_pair_detailed(char* seq1A, char* seq2A, char* seq1B, char* seq2B, int len_a, int len_b, int* scored_cols, struct detailed_pair_stats* stat) { int* codes1_A = NULL; int* codes2_A = NULL; int* codes1_B = NULL; int* codes2_B = NULL; int* in_scored1 = NULL; int* in_scored2 = NULL; int p1, p2, g1, g2; if(len_a == 0 || len_b == 0){ return OK; } MMALLOC(codes1_A, sizeof(int) * len_a); MMALLOC(codes2_A, sizeof(int) * len_a); MMALLOC(codes1_B, sizeof(int) * len_b); MMALLOC(codes2_B, sizeof(int) * len_b); MMALLOC(in_scored1, sizeof(int) * len_a); MMALLOC(in_scored2, sizeof(int) * len_a); /* Process reference alignment */ p1 = -1; p2 = -1; for(int i = 0; i < len_a; i++){ g1 = 0; g2 = 0; if(isalpha((int)seq1A[i])){ p1++; in_scored1[p1] = 0; }else{ g1 = 1; } if(isalpha((int)seq2A[i])){ p2++; in_scored2[p2] = 0; }else{ g2 = 1; } if(!g1 && !g2){ /* Both residues aligned */ codes1_A[p1] = p2; codes2_A[p2] = p1; if(scored_cols[i]){ stat->ref_scored_pairs += 2; /* both directions */ in_scored1[p1] = 1; in_scored2[p2] = 1; } }else if(!g1 && g2){ codes1_A[p1] = -1; }else if(g1 && !g2){ codes2_A[p2] = -1; } } /* Process test alignment */ p1 = -1; p2 = -1; for(int i = 0; i < len_b; i++){ g1 = 0; g2 = 0; if(isalpha((int)seq1B[i])){ p1++; }else{ g1 = 1; } if(isalpha((int)seq2B[i])){ p2++; }else{ g2 = 1; } if(!g1 && !g2){ stat->test_pairs += 2; /* both directions */ codes1_B[p1] = p2; codes2_B[p2] = p1; }else if(!g1 && g2){ codes1_B[p1] = -1; }else if(g1 && !g2){ codes2_B[p2] = -1; } } /* Compare: count scored matches (for recall) and all matches (for precision) */ for(int i = 0; i <= p1; i++){ if(codes1_A[i] >= 0 && codes1_A[i] == codes1_B[i]){ stat->common_all++; if(in_scored1[i]){ stat->common_scored++; } } } for(int i = 0; i <= p2; i++){ if(codes2_A[i] >= 0 && codes2_A[i] == codes2_B[i]){ stat->common_all++; if(in_scored2[i]){ stat->common_scored++; } } } MFREE(codes1_A); MFREE(codes1_B); MFREE(codes2_A); MFREE(codes2_B); MFREE(in_scored1); MFREE(in_scored2); return OK; ERROR: MFREE(codes1_A); MFREE(codes1_B); MFREE(codes2_A); MFREE(codes2_B); MFREE(in_scored1); MFREE(in_scored2); return FAIL; } kalign-3.5.1/lib/src/msa_cmp.h000066400000000000000000000023751515023132300161140ustar00rootroot00000000000000#ifndef MSA_CMP_H #define MSA_CMP_H #include #ifdef MSA_CMP_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; struct poar_score { double recall; /* |common| / |ref_scored_pairs| — bali_score SP equivalent */ double precision; /* |common| / |test_pairs| — fraction of test POARs correct */ double f1; /* 2*recall*precision / (recall+precision) */ double tc; /* fraction of scored columns that are completely correct */ int64_t ref_pairs; /* total scored reference POARs */ int64_t test_pairs; /* total test POARs */ int64_t common; /* POARs in both ref and test */ }; EXTERN int kalign_msa_compare(struct msa *r, struct msa *t, float *score); EXTERN int kalign_msa_compare_detailed(struct msa *r, struct msa *t, float max_gap_frac, struct poar_score *out); EXTERN int kalign_msa_compare_with_mask(struct msa *r, struct msa *t, int *scored_cols, int n_cols, struct poar_score *out); #undef MSA_CMP_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/msa_io.c000066400000000000000000001217261515023132300157410ustar00rootroot00000000000000 #include #include #include #include /* #include "strnlen_compat.h" */ #include "tldevel.h" #include "tlmisc.h" #include "esl_stopwatch.h" /* #include "version.h" */ #include "msa_struct.h" #include "msa_alloc.h" #include "msa_misc.h" /* NEED TO REMOVE */ #include "msa_op.h" #include "alphabet.h" #define MSA_IO_IMPORT #include "msa_io.h" struct in_line{ char* line; int len; }; struct in_buffer{ struct in_line** l; int n_lines; int alloc_lines; }; /* only local; */ struct line_buffer{ struct out_line** lines; int max_line_len; int alloc_num_lines; int num_line; }; struct out_line{ char* line; int block; int seq_id; }; static int check_for_sequences(struct msa* msa); static int read_fasta(struct in_buffer* b, struct msa** msa); static int read_msf(struct in_buffer* b, struct msa** msa); static int read_clu(struct in_buffer* b, struct msa** msa); static int write_msa_fasta(struct msa* msa,char* outfile); static int write_msa_clu(struct msa* msa,char* outfile); static int write_msa_msf(struct msa* msa,char* outfile); static struct line_buffer* alloc_line_buffer(int max_line_len); static int resize_line_buffer(struct line_buffer* lb); static void free_line_buffer(struct line_buffer* lb); static int read_file_stdin(struct in_buffer** buffer,char* infile); static int alloc_in_buffer(struct in_buffer** buffer, int n); static int resize_in_buffer(struct in_buffer* b); static void free_in_buffer(struct in_buffer* b); static int detect_alignment_format(struct in_buffer* b,int* type); static int null_terminate_sequences(struct msa* msa); static int sort_out_lines(const void *a, const void *b); static int parse_format_argument(char* format, int* type); int kalign_read_input(char* infile, struct msa** msa, int quiet) { struct in_buffer* b = NULL; struct msa* m = NULL; int type; int i,j; //ASSERT(infile != NULL,"No input file"); /* sanity checks */ if(infile){ if(!my_file_exists(infile)){ ERROR_MSG("File: %s does not exist.",infile); } } DECLARE_TIMER(timer); START_TIMER(timer); /* read everything into a in_buffer */ RUN(read_file_stdin(&b,infile)); /* Check if any input was read */ /* Logic: sum length of lines 1.. up to 5 */ //LOG_MSG("%s lines: %d", infile, b->n_lines); j = 0; for(i = 0; i < MACRO_MIN(1, b->n_lines);i++){ j += b->l[i]->len -1; /* exclude '0' at the end of strings */ //fprintf(stdout,"%d %s\n", i, b->l[i]->line); } //LOG_MSG("Len: %d",j); if(j == 0){ DESTROY_TIMER(timer); free_in_buffer(b); *msa = NULL; return OK; } RUN(detect_alignment_format(b, &type)); //LOG_MSG("FORMAT: %d", type); if(type == FORMAT_FA){ //RUNP(msa = read_msf(infile,msa)); //RUNP(msa = read_clu(infile,msa)); /* LOG_MSG("reading fasta"); */ RUN(read_fasta(b,&m)); }else if(type == FORMAT_MSF){ RUN(read_msf(b,&m)); }else if(type == FORMAT_CLU){ RUN(read_clu(b,&m)); }else if(type == FORMAT_DETECT_FAIL){ if(infile){ WARNING_MSG("Could not detect input in file: %s", infile); }else{ WARNING_MSG("Could not detect input in standard input"); } /* clean up allocated structures */ free_in_buffer(b); DESTROY_TIMER(timer); *msa = NULL; return FAIL; /* Return FAIL instead of OK when no valid format detected */ } m->quiet = quiet; RUN(detect_alphabet(m)); RUN(detect_aligned(m)); RUN(set_sip_nsip(m)); free_in_buffer(b); STOP_TIMER(timer); if(!quiet){ if(infile){ LOG_MSG("Read %d sequences from %s.", m->numseq, infile); }else{ LOG_MSG("Read %d sequences from standard input.",m->numseq); } GET_TIMING(timer); } DESTROY_TIMER(timer); if(*msa != NULL){ RUN(merge_msa(msa, m)); kalign_free_msa(m); }else{ *msa = m; } /* LOG_MSG("%d " , (*msa)->aligned); */ RUN(check_for_sequences(*msa)); return OK; ERROR: if(m){ kalign_free_msa(m); } return FAIL; } int check_for_sequences(struct msa* msa) { if(!msa){ ERROR_MSG("No sequences were found in the input files or standard input."); } if(msa->numseq < 2){ if(msa->numseq == 0){ ERROR_MSG("No sequences were found in the input files or standard input."); }else if (msa->numseq == 1){ ERROR_MSG("Only 1 sequence was found in the input files or standard input"); } } return OK; ERROR: return FAIL; } int kalign_write_msa(struct msa* msa, char* outfile, char* format) { int type = FORMAT_FA; ASSERT(msa!= NULL, "No alignment"); if(msa->aligned != ALN_STATUS_FINAL){ ERROR_MSG("Cannot produce msa output: Sequences are not aligned."); } RUN(parse_format_argument(format, &type)); /* LOG_MSG("Aligned? %d", msa->aligned); */ if(type == FORMAT_FA){ RUN(write_msa_fasta(msa, outfile)); }else if(type == FORMAT_MSF){ /* if(msa->aligned == ALN_STATUS_UNALIGNED || msa->aligned == ALN_STATUS_UNKNOWN){ */ /* ERROR_MSG("Cannot produce msa output: Sequences are not aligned."); */ /* } */ RUN(write_msa_msf(msa, outfile)); }else if(type == FORMAT_CLU){ /* if(msa->aligned == ALN_STATUS_UNALIGNED || msa->aligned == ALN_STATUS_UNKNOWN){ */ /* ERROR_MSG("Cannot produce clu output: Sequences are not aligned."); */ /* } */ RUN(write_msa_clu(msa, outfile)); }else{ ERROR_MSG("Output format not recognized."); } return OK; ERROR: return FAIL; } int parse_format_argument(char* format, int* type) { int out_format = -1; if(format){ if(strstr(format,"msf")){ out_format = FORMAT_MSF; }else if(strstr(format,"clu")){ out_format = FORMAT_CLU; }else if(strstr(format,"fasta")){ out_format = FORMAT_FA; }else if(strstr(format,"fa")){ out_format = FORMAT_FA; }else{ ERROR_MSG("Format %s not recognized.",format); } }else{ out_format = FORMAT_FA; } *type = out_format; return OK; ERROR: return FAIL; } /* detect alignment format */ int detect_alignment_format(struct in_buffer*b,int* type) { //FILE* f_ptr = NULL; char* line = NULL; //size_t b_len = 0; //ssize_t nread; //char line[BUFFER_LEN]; int hints[3]; int line_len; int line_number; int set; int i; ASSERT(b != NULL,"No input file"); /* sanity checks */ //if(!my_file_exists(infile)){ //ERROR_MSG("File: %s does not exist.",infile); //} line_number = 0; for(i = 0; i < 3; i++){ hints[i] =0; } for(i = 0; i < MACRO_MIN(b->n_lines, 100);i++){ line = b->l[i]->line; line_len = b->l[i]->len; //} //RUNP(f_ptr = fopen(infile, "r")); /* scan through first line header */ //while ((nread = getline(&line, &b_len, f_ptr)) != -1){ //while(fgets(line, BUFFER_LEN, f_ptr)){ //line_len = nread;//strnlen(line, BUFFER_LEN); //line[line_len-1] = 0; line_len--; if(line[0] == '>'){ hints[0]++; /* fasta */ } if(strstr(line, "multiple sequence alignment")){ hints[2]++; /* clustal format */ } if(strstr(line, "CLUSTAL W")){ hints[2]++; /* clustal format */ } if(strstr(line, "CLUSTAL O")){ hints[2]++; /* clustal format */ } if(strstr(line, "!!AA_MULTIPLE_ALIGNMENT")){ hints[1]++; } if(strstr(line, "!!NA_MULTIPLE_ALIGNMENT")){ hints[1]++; } if(strstr(line, "MSF:")){ hints[1]++; } line_number++; if(line_number == 100){ break; } } //fclose(f_ptr); //MFREE(line); set = 0; for(i = 0; i < 3;i++){ if(hints[i]){ set++; } } if(set == 0){ *type = FORMAT_DETECT_FAIL; //ERROR_MSG("Input alignment format could not be detected."); } if(set > 1){ *type = FORMAT_DETECT_FAIL; //ERROR_MSG("Input format could not be unambiguously detected"); } if(hints[0]){ *type = FORMAT_FA; } if(hints[1]){ *type = FORMAT_MSF; } if(hints[2]){ *type = FORMAT_CLU; } //fprintf(stdout,"fa: %d msf:%d clu:%d", hints[0],hints[1],hints[2]); return OK; ERROR: return FAIL; } int read_file_stdin(struct in_buffer** buffer,char* infile) { struct in_buffer* b = NULL; FILE* f_ptr = NULL; char* line = NULL; char* tmp = NULL; size_t b_len = 0; size_t nread; int i; //char line[BUFFER_LEN]; int line_len; b = *buffer; if(!b){ RUN(alloc_in_buffer(&b, 1024)); } if(infile){ if(!my_file_exists(infile)){ ERROR_MSG("File: %s does not exist.",infile); } RUNP(f_ptr = fopen(infile, "r")); }else{ f_ptr = stdin; } b->n_lines = 0; while ((nread = getline(&line, &b_len, f_ptr)) != -1){ //LOG_MSG("Read %d ", nread); //while(fgets(line, BUFFER_LEN, f_ptr)){ line_len = nread; //tmp = b->l[b->n_lines]->line; tmp= NULL; MMALLOC(tmp, sizeof(char) * (line_len+1)); for(i = 0; i < line_len;i++){ if(iscntrl((int) line[i])){ break; } tmp[i] = line[i]; } tmp[i] = 0; //memcpy(tmp, line, line_len); //tmp[line_len-1] = 0; b->l[b->n_lines]->line = tmp; b->l[b->n_lines]->len = i; b->n_lines++; if(b->n_lines == b->alloc_lines){ RUN(resize_in_buffer(b)); } } if(f_ptr != stdin){ fclose(f_ptr); } MFREE(line); *buffer = b; return OK; ERROR: return FAIL; } int read_fasta( struct in_buffer* b,struct msa** m) { struct msa* msa = NULL; struct msa_seq* seq_ptr = NULL; char* line = NULL; int line_len; int i; int nl; if(msa == NULL){ RUN(alloc_msa(&msa,512)); /* msa = alloc_msa(); */ } for(nl = 0; nl < b->n_lines;nl++){ line = b->l[nl]->line; line_len = b->l[nl]->len; if(line[0] == '>'){ /* alloc seq if buffer is full */ if(msa->alloc_numseq == msa->numseq){ RUN(resize_msa(msa)); } /* line[line_len-1] = 0; */ /*for(i = 0; i < line_len;i++){ if(isspace(line[i])){ line[i] = 0; } }*/ seq_ptr = msa->sequences[msa->numseq]; MFREE(seq_ptr->name); MMALLOC(seq_ptr->name, sizeof(char) * line_len); memcpy(seq_ptr->name, line+1, line_len); /* seq_ptr->name_len = line_len; */ /* snprintf(seq_ptr->name ,MSA_NAME_LEN ,"%s",line+1); */ //LOG_MSG("Name %d: len %d name : %s ",msa->numseq, line_len, seq_ptr->name); //fprintf(stdout,"%s\n%s\n", line, seq_ptr->name); msa->numseq++; }else{ for(i = 0;i < line_len;i++){ msa->letter_freq[(int)line[i]]++; if(isalpha((int)line[i])){ if(!seq_ptr){ ERROR_MSG("Encountered a sequence before encountering it's name"); } seq_ptr->seq[seq_ptr->len] = line[i]; seq_ptr->len++; if(seq_ptr->alloc_len == seq_ptr->len){ resize_msa_seq(seq_ptr); } }else if(ispunct((int)line[i])){ seq_ptr->gaps[seq_ptr->len]++; } } } } RUN(null_terminate_sequences(msa)); *m = msa; return OK; ERROR: kalign_free_msa(msa); return FAIL; } int read_clu(struct in_buffer* b , struct msa** m) { struct msa* msa = NULL; struct msa_seq* seq_ptr = NULL; char* line = NULL; int i,j; char* p; int active_seq = 0; int line_len; int nl,ni; if(msa == NULL){ RUN(alloc_msa(&msa,512)); /* msa = alloc_msa(); */ } ni =0; for(nl = 0; nl < b->n_lines;nl++){ line = b->l[nl]->line; line_len = b->l[nl]->len; ni++; break; } active_seq =0; for(nl = ni; nl < b->n_lines;nl++){ line = b->l[nl]->line; line_len = b->l[nl]->len; if(!line_len){ active_seq = 0; }else{ if(!isspace(line[0])){ if(msa->alloc_numseq == active_seq){ RUN(resize_msa(msa)); } seq_ptr = msa->sequences[active_seq]; p = line; j = 0; for(i = 0;i < line_len;i++){ if(i == MSA_NAME_LEN-1){ seq_ptr->name[i] = 0; j = i; break; } if(isspace((int)p[i])){ j = i; break; } seq_ptr->name[i] = p[i]; } seq_ptr->name[j] = 0; for(i = j;i < line_len;i++){ msa->letter_freq[(int)p[i]]++; if(isalpha((int)p[i])){ seq_ptr->seq[seq_ptr->len] = p[i]; seq_ptr->len++; if(seq_ptr->alloc_len == seq_ptr->len){ resize_msa_seq(seq_ptr); } }else if(ispunct((int)p[i])){ seq_ptr->gaps[seq_ptr->len]++; } } active_seq++; msa->numseq = MACRO_MAX(msa->numseq, active_seq); } } } RUN(null_terminate_sequences(msa)); *m = msa; return OK; ERROR: kalign_free_msa(msa); return FAIL; } int read_msf(struct in_buffer* b,struct msa** m) { struct msa* msa = NULL; struct msa_seq* seq_ptr = NULL; char* line = NULL; int line_len; int i,j,nl,li; char* p; int active_seq = 0; if(msa == NULL){ RUN(alloc_msa(&msa,512)); /* msa = alloc_msa(); */ } li = 0; for(nl = 0; nl < b->n_lines;nl++){ line = b->l[nl]->line; line_len = b->l[nl]->len; li++; /* line_len--; /\* last character is newline *\/ */ //fprintf(stdout,"%d \"%s\"\n",line_len,line); if(strstr(line, "//")){ // LOG_MSG("Header done"); break; } /* look for name */ p = strstr(line,"Name:"); if(p && strstr(line,"Len:")){ if(msa->alloc_numseq == msa->numseq){ RUN(resize_msa(msa)); } p += 5; /* length of name: */ while( isspace((int)*p)){ p++; } /* LOG_MSG("Found name: %s len %d", p, strlen(p)); */ seq_ptr = msa->sequences[active_seq]; for(i = 0;i < line_len;i++){ if(i == MSA_NAME_LEN-1){ seq_ptr->name[i] = 0; break; } if(isspace((int)p[i])){ seq_ptr->name[i] = 0; break; } seq_ptr->name[i] = p[i]; } seq_ptr->seq[0] = 0; msa->numseq++; active_seq++; //LOG_MSG("Got a name %s",p); } } active_seq = 0; for(nl = li; nl < b->n_lines;nl++){ line = b->l[nl]->line; line_len = b->l[nl]->len; /* line_len--; /\* last character is newline *\/ */ if(!line_len){ active_seq = 0; }else{ if(!isspace(line[0])){ seq_ptr = msa->sequences[active_seq]; //p = strstr(line,seq_ptr->name); //if(p){ //LOG_MSG("Found bitsof seq %s", seq_ptr->name); p = line; j = strnlen(seq_ptr->name, MSA_NAME_LEN); p += j; for(i = 0;i < line_len-j;i++){ msa->letter_freq[(int)p[i]]++; if(isalpha((int)p[i])){ seq_ptr->seq[seq_ptr->len] = p[i]; seq_ptr->len++; if(seq_ptr->alloc_len == seq_ptr->len){ resize_msa_seq(seq_ptr); } }else if(ispunct((int)p[i])){ seq_ptr->gaps[seq_ptr->len]++; } } //} active_seq++; } } //fprintf(stdout,"%d \"%s\"\n",line_len,line); } RUN(null_terminate_sequences(msa)); *m = msa; //fclose(f_ptr); //MFREE(line); return OK; ERROR: kalign_free_msa(msa); return FAIL; } int write_msa_fasta(struct msa* msa,char* outfile) { FILE* f_ptr = NULL; int i,j,f; if(!outfile){ f_ptr = stdout; }else{ RUNP(f_ptr = fopen(outfile, "w")); } for(i = 0; i < msa->numseq;i++){ fprintf(f_ptr,">%s\n", msa->sequences[i]->name); f = 0; for(j = 0;j < msa->alnlen;j++){ /*for(c = 0;c < msa->sequences[i]->gaps[j];c++){ fprintf(f_ptr,"-"); f++; if(f == 60){ fprintf(f_ptr, "\n"); f = 0; } }*/ fprintf(f_ptr,"%c", msa->sequences[i]->seq[j]); f++; if(f == 60){ fprintf(f_ptr, "\n"); f = 0; } } /* for(c = 0;c < msa->sequences[i]->gaps[ msa->sequences[i]->len];c++){ */ /* fprintf(f_ptr,"-"); */ /* f++; */ /* if(f == 60){ */ /* fprintf(f_ptr, "\n"); */ /* f = 0; */ /* } */ /* } */ if(f){ fprintf(f_ptr,"\n"); } } if(outfile){ fclose(f_ptr); } return OK; ERROR: return FAIL; } int write_msa_clu(struct msa* msa,char* outfile) { struct line_buffer* lb = NULL; struct out_line* ol= NULL; struct msa_seq* seq = NULL; char* linear_seq = NULL; char* ptr; FILE* f_ptr = NULL; int aln_len; int i,j,c,f; int block; int max_name_len = 0; int line_length; if(!msa->aligned){ ERROR_MSG("Sequences appear to be unaligned!"); } if(!outfile){ f_ptr = stdout; }else{ RUNP(f_ptr = fopen(outfile, "w")); } for(i = 0; i < msa->numseq;i++){ max_name_len = MACRO_MAX(max_name_len, (int)strnlen( msa->sequences[i]->name,MSA_NAME_LEN)); } /* aln_len = 0; */ /* for (j = 0; j <= msa->sequences[0]->len;j++){ */ /* aln_len += msa->sequences[0]->gaps[j]; */ /* } */ /* aln_len += msa->sequences[0]->len; */ /* MMALLOC(linear_seq, sizeof(char)* (aln_len+1)); */ /* length of write line buffer should be: max_name_len + 5 + 60 (for sequences) + 1 for newline character */ line_length = max_name_len +5 + 60 + 2; line_length = MACRO_MAX(256, line_length ); RUNP(lb = alloc_line_buffer(line_length)); /* print header line here I will use seq index -1 to make sure this ends up on top. */ ol = lb->lines[lb->num_line]; snprintf(ol->line, line_length,"Kalign (%s) multiple sequence alignment", KALIGN_PACKAGE_VERSION); ol->block = -1; ol->seq_id = -2; lb->num_line++; ol = lb->lines[lb->num_line]; ol->line[0] = 0; ol->block = -1; ol->seq_id = -1; lb->num_line++; aln_len = msa->alnlen; /* now the actual sequence lines */ for(i = 0; i < msa->numseq;i++){ block = 0; seq = msa->sequences[i]; /* RUN(make_linear_sequence(seq,linear_seq)); */ linear_seq = seq->seq;// msa->sequences[i]->seq; /* aln_len = seq->len;//msa->sequences[i]->len; */ f = 0; while(1){ if(lb->alloc_num_lines == lb->num_line){ resize_line_buffer(lb); } ol = lb->lines[lb->num_line]; c = (int) strnlen(seq->name, MSA_NAME_LEN); for(j = 0;j < c;j++){ ol->line[j] = seq->name[j]; } for(j = c;j < max_name_len+5;j++){ ol->line[j] = ' '; } ptr = ol->line + max_name_len+5; for(j = 0;j < 60;j++){ if(f == aln_len){ ptr[j] = 0; break; } ptr[j] = linear_seq[f]; f++; } ptr[j] = 0; ol->block = block; ol->seq_id = i; lb->num_line++; if(i == 0){ if(lb->alloc_num_lines == lb->num_line){ resize_line_buffer(lb); } ol = lb->lines[lb->num_line]; ol->block = block; ol->seq_id = msa->numseq; ol->line[0] = '\n'; ol->line[1] = 0; lb->num_line++; } block++; if(f == aln_len){ break; } } } qsort(lb->lines , lb->num_line, sizeof(struct out_line *), sort_out_lines); for(i = 0; i < lb->num_line;i++){ ol = lb->lines[i]; fprintf(f_ptr, "%s\n", ol->line); //fprintf(stdout,"%d %d %s\n",ol->seq_id,ol->block,ol->line); } if(outfile){ fclose(f_ptr); } free_line_buffer(lb); /* MFREE(linear_seq); */ return OK; ERROR: return FAIL; } int write_msa_msf(struct msa* msa,char* outfile) { struct line_buffer* lb = NULL; struct out_line* ol= NULL; struct msa_seq* seq = NULL; time_t now; /* current time as a time_t */ struct tm local_time; char date[64]; /* today's date in GCG's format "October 3, 1996 15:57" */ char* linear_seq = NULL; char* ptr; char* basename = NULL; FILE* f_ptr = NULL; int aln_len; int i,j,c,f; int block; int max_name_len = 0; int line_length; int header_index; int written; if(!msa->aligned){ ERROR_MSG("Sequences appear to be unaligned!"); } if(!outfile){ f_ptr = stdout; }else{ RUNP(f_ptr = fopen(outfile, "w")); } for(i = 0; i < msa->numseq;i++){ max_name_len = MACRO_MAX(max_name_len, (int)strnlen( msa->sequences[i]->name,MSA_NAME_LEN)); } aln_len = msa->sequences[0]->len; /* for (j = 0; j <= msa->sequences[0]->len;j++){ */ /* aln_len+= msa->sequences[0]->gaps[j]; */ /* } */ /* aln_len += msa->sequences[0]->len; */ /* MMALLOC(linear_seq, sizeof(char)* (aln_len+1)); */ /* length of write line buffer should be: max_name_len + 5 + 60 (for sequences) + 1 for newline character + 6 for spaces every 10 letters */ /* BUG: the header lines might be longer!! */ line_length = max_name_len +5 + 60 + 2+6 ; line_length = MACRO_MAX(256, line_length); RUNP(lb = alloc_line_buffer(line_length)); /* print header line here I will use seq index -1 to make sure this ends up on top. */ /* !!AA_MULTIPLE_ALIGNMENT 1.0 stdout MSF: 131 Type: P 16/01/02 CompCheck: 3003 .. Name: IXI_234 Len: 131 Check: 6808 Weight: 1.00 Name: IXI_235 Len: 131 Check: 4032 Weight: 1.00 Name: IXI_236 Len: 131 Check: 2744 Weight: 1.00 Name: IXI_237 Len: 131 Check: 9419 Weight: 1.00 // */ header_index = -1 * (msa->numseq+10); ol = lb->lines[lb->num_line]; //LOG_MSG("Alphabet : %d", msa->L); if(msa->L == ALPHA_defPROTEIN){ snprintf(ol->line, line_length,"!!AA_MULTIPLE_ALIGNMENT 1.0"); }else if(msa->L == ALPHA_redPROTEIN){ snprintf(ol->line, line_length,"!!AA_MULTIPLE_ALIGNMENT 1.0"); }else if(msa->L == ALPHA_defDNA){ snprintf(ol->line, line_length,"!!NA_MULTIPLE_ALIGNMENT 1.0"); }else{ snprintf(ol->line, line_length,"!!NA_MULTIPLE_ALIGNMENT 1.0"); } ol->block = -1; ol->seq_id = header_index; header_index++; lb->num_line++; /* a space */ ol = lb->lines[lb->num_line]; ol->line[0] = 0; ol->block = -1; ol->seq_id = header_index; header_index++; lb->num_line++; /* The msf line*/ now = time(NULL); if((localtime_r(&now,&local_time)) == NULL){ ERROR_MSG("could not get local time"); } if (strftime(date, 64, "%B %d, %Y %H:%M", &local_time) == 0){ ERROR_MSG("time failed???"); } ol = lb->lines[lb->num_line]; if(outfile){ RUN(tlfilename(outfile, &basename)); } written = snprintf(ol->line, line_length," %s MSF: %d Type: %c %s Check: %d ..", outfile == NULL ? "stdout" : basename,aln_len, msa->L == ALPHA_defPROTEIN ? 'P' : 'N', date, GCGMultchecksum(msa)); if(written >= line_length){ MREALLOC(lb->lines[lb->num_line]->line,sizeof(char) * (written+1)); ol = lb->lines[lb->num_line]; written = snprintf(ol->line, written+1," %s MSF: %d Type: %c %s Check: %d ..", outfile == NULL ? "stdout" : basename,aln_len, msa->L == ALPHA_defPROTEIN ? 'P' : 'N', date, GCGMultchecksum(msa)); } if(basename){ MFREE(basename); } ol->block = -1; ol->seq_id = header_index; header_index++; lb->num_line++; /* another space */ ol = lb->lines[lb->num_line]; ol->line[0] = 0; ol->block = -1; ol->seq_id = header_index; header_index++; lb->num_line++; //Name: IXI_234 Len: 131 Check: 6808 Weight: 1.00 for(i = 0; i < msa->numseq;i++){ if(lb->alloc_num_lines == lb->num_line){ resize_line_buffer(lb); } ol = lb->lines[lb->num_line]; written = snprintf(ol->line, line_length," Name: %-*.*s Len: %5d Check: %4d Weight: %.2f", max_name_len,max_name_len, msa->sequences[i]->name , aln_len, GCGchecksum(msa->sequences[i]->seq, msa->sequences[i]->len), 1.0); if(written >= line_length){ MREALLOC(lb->lines[lb->num_line]->line,sizeof(char) * (written+1)); ol = lb->lines[lb->num_line]; written = snprintf(ol->line, written+1," Name: %-*.*s Len: %5d Check: %4d Weight: %.2f", max_name_len,max_name_len, msa->sequences[i]->name , aln_len, GCGchecksum(msa->sequences[i]->seq, msa->sequences[i]->len), 1.0); } ol->block = -1; ol->seq_id = header_index; header_index++; lb->num_line++; } /* another space */ if(lb->alloc_num_lines == lb->num_line){ resize_line_buffer(lb); } ol = lb->lines[lb->num_line]; ol->line[0] = 0; ol->block = -1; ol->seq_id = header_index; header_index++; lb->num_line++; /* header section finished */ if(lb->alloc_num_lines == lb->num_line){ resize_line_buffer(lb); } ol = lb->lines[lb->num_line]; snprintf(ol->line, line_length,"//"); ol->block = -1; ol->seq_id = header_index; header_index++; lb->num_line++; /* another space */ if(lb->alloc_num_lines == lb->num_line){ resize_line_buffer(lb); } ol = lb->lines[lb->num_line]; ol->line[0] = 0; ol->block = -1; ol->seq_id = header_index; header_index++; lb->num_line++; aln_len = msa->alnlen; /* now the actual sequence lines */ for(i = 0; i < msa->numseq;i++){ block = 0; seq = msa->sequences[i]; //RUN(make_linear_sequence(seq,linear_seq)); linear_seq = seq->seq; /* aln_len = seq->len; */ f = 0; while(1){ if(lb->alloc_num_lines == lb->num_line){ resize_line_buffer(lb); } ol = lb->lines[lb->num_line]; c = strnlen(seq->name, MSA_NAME_LEN); for(j = 0;j < c;j++){ ol->line[j] = seq->name[j]; } for(j = c;j < max_name_len+5;j++){ ol->line[j] = ' '; } ptr = ol->line + max_name_len+5; for(j = 0;j < 60;j++){ if(f == aln_len){ ptr[j] = 0; break; } ptr[j] = linear_seq[f]; f++; } ptr[j] = 0; ol->block = block; ol->seq_id = i; lb->num_line++; if(i == 0){ if(lb->alloc_num_lines == lb->num_line){ resize_line_buffer(lb); } ol = lb->lines[lb->num_line]; ol->block = block; ol->seq_id = msa->numseq; ol->line[0] = '\n'; ol->line[1] = 0; lb->num_line++; } block++; if(f == aln_len){ break; } } } qsort(lb->lines , lb->num_line, sizeof(struct out_line *), sort_out_lines); for(i = 0; i < lb->num_line;i++){ ol = lb->lines[i]; //fprintf(stdout,"%d %d %s\n",ol->seq_id,ol->block,ol->line); fprintf(f_ptr, "%s\n", ol->line); } if(outfile){ fclose(f_ptr); } free_line_buffer(lb); /* MFREE(linear_seq); */ return OK; ERROR: if(linear_seq){ MFREE(linear_seq); } if(basename){ MFREE(basename); } return FAIL; } int null_terminate_sequences(struct msa* msa) { int i; struct msa_seq* seq_ptr = NULL; /* 0 terminate sequences */ for(i = 0; i < msa->numseq;i++){ seq_ptr = msa->sequences[i]; if(seq_ptr->alloc_len == seq_ptr->len){ resize_msa_seq(seq_ptr); } seq_ptr->seq[seq_ptr->len] = 0; } return OK; } struct line_buffer* alloc_line_buffer(int max_line_len) { struct line_buffer* lb = NULL; int i; ASSERT(max_line_len > 60, "max_line_len:%d too small", max_line_len); MMALLOC(lb, sizeof(struct line_buffer)); lb->alloc_num_lines = 1024; lb->num_line = 0; lb->lines = NULL; lb->max_line_len = max_line_len; MMALLOC(lb->lines, sizeof(struct out_line*) * lb->alloc_num_lines); for(i = 0; i < lb->alloc_num_lines;i++){ lb->lines[i] = NULL; MMALLOC(lb->lines[i], sizeof(struct out_line)); lb->lines[i]->block = 0; lb->lines[i]->seq_id =0; lb->lines[i]->line = NULL; MMALLOC(lb->lines[i]->line,sizeof(char) * lb->max_line_len); } return lb; ERROR: return NULL; } int resize_line_buffer(struct line_buffer* lb) { int old_len = 0; int i; old_len = lb->alloc_num_lines; lb->alloc_num_lines = lb->alloc_num_lines + 1024; MREALLOC(lb->lines, sizeof(struct out_line*) * lb->alloc_num_lines); for(i = old_len; i < lb->alloc_num_lines;i++){ lb->lines[i] = NULL; MMALLOC(lb->lines[i], sizeof(struct out_line)); lb->lines[i]->block = 0; lb->lines[i]->seq_id =0; lb->lines[i]->line = NULL; MMALLOC(lb->lines[i]->line,sizeof(char) * lb->max_line_len); } return OK; ERROR: return FAIL; } void free_line_buffer(struct line_buffer* lb) { int i; if(lb){ for(i = 0; i < lb->alloc_num_lines;i++){ MFREE(lb->lines[i]->line); MFREE(lb->lines[i]); } MFREE(lb->lines); MFREE(lb); } } int alloc_in_buffer(struct in_buffer** buffer, int n) { struct in_buffer* b = NULL; int i; MMALLOC(b, sizeof(struct in_buffer)); b->alloc_lines = n; b->l = NULL; b->n_lines = 0; MMALLOC(b->l, sizeof(struct in_line*) * b->alloc_lines); for(i = 0; i < b->alloc_lines;i++){ b->l[i] = NULL; MMALLOC(b->l[i], sizeof(struct in_line)); b->l[i]->line = NULL; b->l[i]->len =0; } *buffer = b; return OK; ERROR: return FAIL; } int resize_in_buffer(struct in_buffer* b) { int i,o; o = b->alloc_lines; b->alloc_lines = b->alloc_lines + b->alloc_lines / 2; MREALLOC(b->l, sizeof(struct in_line*) * b->alloc_lines); for(i = o; i < b->alloc_lines;i++){ b->l[i] = NULL; MMALLOC(b->l[i], sizeof(struct in_line)); b->l[i]->line = NULL; b->l[i]->len =0; } return OK; ERROR: return FAIL; } void free_in_buffer(struct in_buffer* b) { int i; if(b){ for(i = 0; i < b->n_lines ;i++){ MFREE(b->l[i]->line); } for(i = 0; i < b->alloc_lines;i++){ MFREE(b->l[i]); } MFREE(b->l); MFREE(b); } } int sort_out_lines(const void *a, const void *b) { struct out_line* const *one = a; struct out_line* const *two = b; if((*one)->block > (*two)->block){ return 1; }else if((*one)->block == (*two)->block){ if((*one)->seq_id > (*two)->seq_id){ return 1; }else if((*one)->seq_id == (*two)->seq_id){ return 0; }else{ return -1; } }else{ return -1; } } kalign-3.5.1/lib/src/msa_io.h000066400000000000000000000006301515023132300157340ustar00rootroot00000000000000#ifndef MSA_IO_H #define MSA_IO_H #ifdef MSA_IO_IMPORT #define EXTERN #else #define EXTERN extern #endif #define FORMAT_DETECT_FAIL -1 #define FORMAT_FA 1 #define FORMAT_MSF 2 #define FORMAT_CLU 3 struct msa; EXTERN int kalign_read_input(char* infile, struct msa** msa,int quiet); EXTERN int kalign_write_msa(struct msa* msa, char* outfile, char* format); #undef MSA_IO_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/msa_misc.c000066400000000000000000000013041515023132300162520ustar00rootroot00000000000000#include #include "msa_struct.h" #define MSA_MISC_IMPORT #include "msa_misc.h" /* alignment checksum */ int GCGMultchecksum(struct msa* msa) { int chk = 0; int idx; for (idx = 0; idx < msa->numseq; idx++){ chk = (chk + GCGchecksum(msa->sequences[idx]->seq, msa->sequences[idx]->len)) % 10000; } return chk; } /* Taken from squid library by Sean Eddy */ int GCGchecksum(char *seq, int len) { int i; /* position in sequence */ int chk = 0; /* calculated checksum */ for (i = 0; i < len; i++){ chk = (chk + (i % 57 + 1) * (toupper((int) seq[i]))) % 10000; } return chk; } kalign-3.5.1/lib/src/msa_misc.h000066400000000000000000000004051515023132300162600ustar00rootroot00000000000000#ifndef MSA_MISC_H #define MSA_MISC_H #ifdef MSA_MISC_IMPORT #define EXTERN #else #define EXTERN extern #endif struct msa; EXTERN int GCGMultchecksum(struct msa* msa); EXTERN int GCGchecksum(char *seq, int len); #undef MSA_MISC_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/msa_op.c000066400000000000000000000447741515023132300157570ustar00rootroot00000000000000#include "tldevel.h" #include "msa_struct.h" #include "alphabet.h" #include #include "msa_alloc.h" #define MSA_OP_IMPORT #include "msa_op.h" static int aln_unknown_warning_message_gaps_but_len_diff(struct msa *msa); static int aln_unknown_warning_message_same_len_no_gaps(void); int msa_cpy(struct msa** dest, struct msa* src) { int i; struct msa* d = NULL; d = *dest; if(d == NULL){ RUN(alloc_msa(&d,src->alloc_numseq)); /* d = alloc_msa(); */ } if(d->biotype != ALN_BIOTYPE_UNDEF){ /* if(d->L != ALPHA_UNDEFINED){ */ if(d->biotype != src->biotype){ ERROR_MSG("Input alignments have different alphabets"); } } if(d->aligned != 0 && d->aligned != ALN_STATUS_UNKNOWN){ if(d->aligned != src->aligned){ d->aligned = ALN_STATUS_UNKNOWN; } } for(i = 0; i < 128;i++){ d->letter_freq[i] += src->letter_freq[i]; } d->numseq = 0; for(i = 0; i < src->numseq;i++){ msa_seq_cpy(d->sequences[i], src->sequences[i]); } d->numseq = src->numseq; d->quiet = src->quiet; RUN(detect_alphabet(d)); RUN(detect_aligned(d)); RUN(set_sip_nsip(d)); *dest = d; return OK; ERROR: return FAIL; } int msa_seq_cpy(struct msa_seq *d, struct msa_seq *src) { ASSERT(d != NULL,"No sequence"); ASSERT(src != NULL,"No sequence"); while(src->alloc_len > d->alloc_len){ resize_msa_seq(d); } snprintf(d->name, MSA_NAME_LEN, "%s", src->name); for(int j = 0; j < src->len;j++){ d->seq[j] = src->seq[j]; d->s[j] = src->s[j]; d->gaps[j] = src->gaps[j]; } d->gaps[src->alloc_len] = src->gaps[src->alloc_len]; d->seq[src->len] = 0; d->len = src->len; d->rank = src->rank; return OK; ERROR: return FAIL; } int merge_msa(struct msa** dest, struct msa* src) { int i; struct msa* d = NULL; d = *dest; if(d == NULL){ RUN(alloc_msa(&d,src->alloc_numseq)); /* d = alloc_msa(); */ } if(d->biotype != ALN_BIOTYPE_UNDEF){ /* if(d->L != ALPHA_UNDEFINED){ */ if(d->biotype != src->biotype){ ERROR_MSG("Input alignments have different alphabets"); } } if(d->aligned != 0 && d->aligned != ALN_STATUS_UNKNOWN){ if(d->aligned != src->aligned){ d->aligned = ALN_STATUS_UNKNOWN; } } for(i = 0; i < 128;i++){ d->letter_freq[i] += src->letter_freq[i]; } for(i = 0; i < src->numseq;i++){ free_msa_seq(d->sequences[d->numseq]); d->sequences[d->numseq] = src->sequences[i]; src->sequences[i] = NULL; d->numseq++; if(d->alloc_numseq == d->numseq){ RUN(resize_msa(d)); } } RUN(detect_alphabet(d)); RUN(detect_aligned(d)); RUN(set_sip_nsip(d)); *dest = d; return OK; ERROR: return FAIL; } int dealign_msa(struct msa* msa) { struct msa_seq* seq = NULL; int i; int j; for(i = 0; i < msa->numseq;i++){ seq = msa->sequences[i]; for(j = 0; j <= seq->len;j++){ seq->gaps[j] = 0; } } msa->aligned = ALN_STATUS_UNALIGNED; return OK; } int detect_alphabet(struct msa* msa) { int i; double DNA[128]; double protein[128]; char DNA_letters[12]= "acgtunACGTUN"; char protein_letters[40] = "acdefghiklmnpqrstvwyACDEFGHIKLMNPQRSTVWY"; double dna_prob; double prot_prob; ASSERT(msa != NULL, "No alignment"); for(i = 0; i < 128;i++){ DNA[i] = log(0.0001 * 1.0 / 116.0); protein[i] = log(0.0001 * 1.0 / 88.0); } for(i = 0 ; i < 12;i++){ DNA[(int) DNA_letters[i]] = log(0.9999 * 1.0 / 12.0); } for(i = 0 ; i < 40;i++){ protein[(int) protein_letters[i]] = log(0.9999 * 1.0 / 40.0); } /* dna_prob = 0.0; */ /* prot_prob = 0.0; */ /* for(i = 0; i <128;i++){ */ /* dna_prob += exp(DNA[i]); */ /* prot_prob += exp(protein[i]); */ /* } */ /* LOG_MSG("DNA: %f PROT: %f",dna_prob,prot_prob); */ dna_prob = 0.0; prot_prob = 0.0; for(i = 0; i < 128;i++){ if(msa->letter_freq[i]){ dna_prob += DNA[i] * (double) msa->letter_freq[i]; prot_prob += protein[i]* (double) msa->letter_freq[i]; } } /* LOG_MSG("DNA: %f PROT: %f",dna_prob,prot_prob); */ /* exit(0); */ if( dna_prob == prot_prob){ WARNING_MSG("Could not determine whether we have a DNA or Protein alignment"); msa->L = ALPHA_UNKNOWN; }else{ if(dna_prob > prot_prob){ if(!msa->quiet){ LOG_MSG("Detected DNA sequences."); } msa->biotype = ALN_BIOTYPE_DNA; /* msa->L = ALPHA_defDNA; */ /* RUN(convert_msa_to_internal(msa, ALPHA_defDNA)); */ }else if(prot_prob > dna_prob){ if(!msa->quiet){ LOG_MSG("Detected protein sequences."); } msa->biotype = ALN_BIOTYPE_PROTEIN; /* msa->L = ALPHA_redPROTEIN; */ /* RUN(convert_msa_to_internal(msa, ALPHA_redPROTEIN)); */ }else{ ERROR_MSG("Alphabet not recognized."); } } return OK; ERROR: return FAIL; } int detect_aligned(struct msa* msa) { int min_len; int max_len; int l; int i; int j; int n; int gaps = 0; /* assume that sequences are not aligned */ msa->aligned = 0; /* Improved logic: Lets sum up the number of gaps plus sequence length of the first X sequences. if min == max it is aligned. */ min_len = INT32_MAX; max_len = 0; gaps = 0; /* n = MACRO_MIN(50, msa->numseq); */ n = msa->numseq; for(i = 0; i < n;i++){ l = 0; for (j = 0; j <= msa->sequences[i]->len;j++){ l += msa->sequences[i]->gaps[j]; } gaps += l; l += msa->sequences[i]->len; min_len = MACRO_MIN(min_len, l); max_len = MACRO_MAX(max_len, l); } /* LOG_MSG("%d %d", max_len, min_len); */ /* exit(0); */ if(gaps){ if(min_len == max_len){ /* sequences have gaps and total length is identical - clearly aligned */ msa->aligned = ALN_STATUS_ALIGNED; }else{ /* odd there are gaps but total length differs - unknown status */ if(!msa->quiet){ aln_unknown_warning_message_gaps_but_len_diff(msa); } msa->aligned = ALN_STATUS_UNKNOWN; } }else{ if(min_len == max_len){ /* no gaps and sequences have same length. Can' tell if they are aligned */ if(!msa->quiet){ aln_unknown_warning_message_same_len_no_gaps(); } msa->aligned = ALN_STATUS_UNKNOWN; }else{ /* No gaps and sequences have different lengths - unaligned */ msa->aligned = ALN_STATUS_UNALIGNED; } } /* LOG_MSG("Aligned: %d gaps: %d",msa->aligned,gaps); */ return OK; } int set_sip_nsip(struct msa* msa) { int i; ASSERT(msa!= NULL, "No msa"); if(msa->seq_weights){ MFREE(msa->seq_weights); msa->seq_weights = NULL; } if(msa->plen){ for (i = msa->num_profiles;i--;){ if(msa->sip[i]){ MFREE(msa->sip[i]); } } if(msa->plen){ MFREE(msa->plen); } if(msa->sip){ MFREE(msa->sip); } if(msa->nsip){ MFREE(msa->nsip); } msa->plen = NULL; msa->sip = NULL; msa->nsip = NULL; } msa->num_profiles = (msa->numseq << 1 )-1; MMALLOC(msa->sip,sizeof(int*)* msa->num_profiles); MMALLOC(msa->nsip,sizeof(int)* msa->num_profiles); MMALLOC(msa->plen,sizeof(int)* msa->num_profiles); for (i =0;i < msa->num_profiles;i++){ msa->sip[i] = NULL; msa->nsip[i] = 0; } for(i = 0;i < msa->numseq;i++){ MMALLOC(msa->sip[i],sizeof(int)); msa->nsip[i] = 1; msa->sip[i][0] = i; msa->plen[i] = 0; } return OK; ERROR: return FAIL; } int reformat_settings_msa(struct msa *msa, int rename, int unalign) { for (int i = 0 ;i < msa->numseq;i++){ msa->nsip[i] = i; } if(rename){ for (int i = 0 ;i < msa->numseq;i++){ snprintf(msa->sequences[i]->name, 128, "SEQ%d", i+1); } } if(unalign){ RUN(dealign_msa(msa)); } return OK; ERROR: return FAIL; } int convert_msa_to_internal(struct msa* msa, int type) { struct alphabet* a = NULL; struct msa_seq* seq = NULL; int8_t* t = NULL; int i,j; RUNP(a = create_alphabet(type)); t = a->to_internal; msa->L = a->L; for(i = 0; i < msa->numseq;i++){ seq = msa->sequences[i]; for(j =0 ; j < seq->len;j++){ if(t[(int) seq->seq[j]] == -1){ WARNING_MSG("there should be no character not matching the alphabet"); WARNING_MSG("offending character: >>>%c<<<", seq->seq[j]); seq->s[j] = 0; }else{ seq->s[j] = t[(int) seq->seq[j]]; } } } MFREE(a); return OK; ERROR: if(a){ MFREE(a); } return FAIL; } int kalign_msa_to_arr(struct msa* msa, char ***aligned, int *out_aln_len) { ASSERT(msa != NULL,"No MSA!"); ASSERT(msa->aligned == ALN_STATUS_FINAL,"Sequences are not finalized"); char** out = NULL; int numseq = msa->numseq; int aln_len = msa->alnlen; MMALLOC(out, sizeof(char*) * numseq); for(int i = 0 ; i < numseq;i++){ out[i] = NULL; MMALLOC(out[i], sizeof(char) * (aln_len +1)); } /* galloc(&out, numseq,aln_len+1); */ for(int i = 0 ; i < numseq;i++){ for(int j = 0; j < aln_len;j++){ out[i][j] = msa->sequences[i]->seq[j]; } out[i][aln_len] = 0; /* fprintf(stdout,"IN msa to ALIGNED: %s %d\n", out[i], msa->alnlen); */ } /* /\* msa->alnlen = aln_len; *\/ */ /* /\* msa->aligned = ALN_STATUS_FINAL; *\/ */ /* /\* int aln_len = 0; *\/ */ /* for (int j = 0; j <= msa->sequences[0]->len;j++){ */ /* aln_len += msa->sequences[0]->gaps[j]; */ /* } */ /* aln_len += msa->sequences[0]->len; */ /* aln_len += 1; */ /* MMALLOC(out, sizeof(char*) * numseq); */ /* for(int i = 0; i < numseq; i++){ */ /* out[i] = 0; */ /* MMALLOC(out[i], sizeof(char) * (uint64_t)aln_len); */ /* int pos = 0; */ /* for(int j = 0;j < msa->sequences[i]->len;j++){ */ /* for(int c = 0;c < msa->sequences[i]->gaps[j];c++){ */ /* out[i][pos] = '-'; */ /* pos++; */ /* } */ /* out[i][pos] = msa->sequences[i]->seq[j]; */ /* pos++; */ /* } */ /* for(int c = 0;c < msa->sequences[i]->gaps[ msa->sequences[i]->len];c++){ */ /* out[i][pos] = '-'; */ /* pos++; */ /* } */ /* out[i][pos] = 0; */ /* } */ *aligned = out; *out_aln_len = aln_len; return OK; ERROR: return FAIL; } int kalign_arr_to_msa(char** input_sequences, int* len, int numseq,struct msa** multiple_aln) { struct msa* msa = NULL; MMALLOC(msa, sizeof(struct msa)); msa->sequences = NULL; msa->alloc_numseq = numseq; msa->numseq = numseq; msa->num_profiles = 0; msa->L = ALPHA_UNDEFINED; msa->biotype = ALN_BIOTYPE_UNDEF; msa->aligned = 0; msa->alnlen = 0; msa->plen = NULL; msa->sip = NULL; msa->nsip = NULL; msa->seq_distances = NULL; msa->col_confidence = NULL; msa->seq_weights = NULL; msa->run_parallel = 0; msa->consistency_table = NULL; msa->quiet = 1; MMALLOC(msa->sequences, sizeof(struct msa_seq*) * msa->alloc_numseq); for(int i = 0; i < 128; i++){ msa->letter_freq[i] = 0; } for(int i = 0; i < msa->alloc_numseq;i++){ msa->sequences[i] = NULL; struct msa_seq* seq = NULL; MMALLOC(seq, sizeof(struct msa_seq)); seq->name = NULL; seq->seq = NULL; seq->s = NULL; seq->gaps = NULL; seq->confidence = NULL; seq->rank = 0; seq->len = len[i]; seq->alloc_len = len[i]+1; MMALLOC(seq->name, sizeof(char)* MSA_NAME_LEN); MMALLOC(seq->seq, sizeof(char) * seq->alloc_len); MMALLOC(seq->s, sizeof(uint8_t) * seq->alloc_len); MMALLOC(seq->gaps, sizeof(int) * (seq->alloc_len+1)); for(int j = 0;j < seq->alloc_len+1;j++){ seq->gaps[j] = 0; } for(int j = 0; j < len[i];j++){ msa->letter_freq[(int)input_sequences[i][j]]++; seq->seq[j] = input_sequences[i][j]; } seq->seq[len[i]] = 0; msa->sequences[i] = seq; /* LOG_MSG("%s",msa->sequences[i]->seq); */ } RUN(detect_alphabet(msa)); RUN(detect_aligned(msa)); RUN(set_sip_nsip(msa)); *multiple_aln = msa; return OK; ERROR: kalign_free_msa(msa); return FAIL; } static int aln_unknown_warning_message_gaps_but_len_diff(struct msa* msa) { int i; WARNING_MSG("--------------------------------------------"); WARNING_MSG("The input sequences contain gap characters: "); for(i = 0; i < 128;i++){ if(msa->letter_freq[i] && ispunct(i)){ WARNING_MSG("\"%c\" : %4d found ", (char)i,msa->letter_freq[i] ); } } WARNING_MSG("BUT the presumably aligned sequences do not "); WARNING_MSG("have the same length. "); WARNING_MSG(" "); WARNING_MSG("Kalign will remove the gap characters and "); WARNING_MSG("align the sequences. "); WARNING_MSG("--------------------------------------------"); return OK; } static int aln_unknown_warning_message_same_len_no_gaps(void) { /* int i; */ WARNING_MSG("--------------------------------------------"); WARNING_MSG("All input sequences have the same length. "); WARNING_MSG("BUT there are no gap characters. "); WARNING_MSG(" "); WARNING_MSG("Unable to determine whether the sequences "); WARNING_MSG("are already aligned. "); WARNING_MSG("Kalign will align the sequences. "); WARNING_MSG("--------------------------------------------"); return OK; } int finalise_alignment(struct msa* msa) { ASSERT(msa->aligned == ALN_STATUS_ALIGNED, "Sequences are not aligned"); struct msa_seq* seq = NULL; char* linear_seq = NULL; int aln_len = 0; for(int i = 0; i <= msa->sequences[0]->len;i++){ aln_len += msa->sequences[0]->gaps[i]; } aln_len += msa->sequences[0]->len; for(int i = 0; i < msa->numseq;i++){ MMALLOC(linear_seq, sizeof(char)* (aln_len+1)); seq = msa->sequences[i]; RUN(make_linear_sequence(seq,linear_seq)); MFREE(seq->seq); seq->seq = linear_seq; /* seq->len = aln_len; */ linear_seq = NULL; } msa->alnlen = aln_len; msa->aligned = ALN_STATUS_FINAL; return OK; ERROR: return FAIL; } int make_linear_sequence(struct msa_seq* seq, char* linear_seq) { int c,j,f; f = 0; for(j = 0;j < seq->len;j++){ //LOG_MSG("%d %d",j,seq->gaps[j]); for(c = 0;c < seq->gaps[j];c++){ linear_seq[f] = '-'; f++; } //LOG_MSG("%d %d %d",j,f,seq->gaps[j]); linear_seq[f] = seq->seq[j]; f++; } for(c = 0;c < seq->gaps[ seq->len];c++){ //LOG_MSG("%d %d",j,seq->gaps[seq->len]); linear_seq[f] = '-'; f++; } linear_seq[f] = 0; ///fprintf(stdout,"LINEAR:%s\n",linear_seq); return OK; } kalign-3.5.1/lib/src/msa_op.h000066400000000000000000000021321515023132300157420ustar00rootroot00000000000000#ifndef MSA_OP_H #define MSA_OP_H #ifdef MSA_OP_IMPORT #define EXTERN #else #define EXTERN extern #endif struct msa; struct msa_seq; EXTERN int msa_seq_cpy(struct msa_seq *d, struct msa_seq *src); EXTERN int msa_cpy(struct msa** dest, struct msa* src); EXTERN int merge_msa(struct msa** dest, struct msa* src); EXTERN int dealign_msa(struct msa *msa); EXTERN int detect_alphabet(struct msa *msa); EXTERN int detect_aligned(struct msa *msa); EXTERN int set_sip_nsip(struct msa *msa); EXTERN int reformat_settings_msa(struct msa *msa, int rename, int unalign); EXTERN int convert_msa_to_internal(struct msa* msa, int type); /* convert alinged msa sequences to character array */ EXTERN int kalign_msa_to_arr(struct msa *msa, char ***aligned, int *out_aln_len); /* Used to convert sequences read by non-kalign code into the msa struct.. */ EXTERN int kalign_arr_to_msa(char **input_sequences, int *len, int numseq, struct msa **multiple_aln); EXTERN int finalise_alignment(struct msa* msa); EXTERN int make_linear_sequence(struct msa_seq *seq, char *linear_seq); #undef MSA_OP_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/msa_sort.c000066400000000000000000000045051515023132300163140ustar00rootroot00000000000000#include "tldevel.h" #include "tlrng.h" #include "msa_struct.h" #include #define MSA_SORT_IMPORT #include "msa_sort.h" static int sort_by_len_name(const void *a, const void *b); static int sort_by_rank(const void *a, const void *b); int msa_sort_len_name(struct msa *m) { ASSERT(m != NULL, "No alignment"); qsort(m->sequences, m->numseq, sizeof(struct msa_seq*),sort_by_len_name); return OK; ERROR: return FAIL; } int msa_sort_rank(struct msa *m) { ASSERT(m != NULL, "No alignment"); /* for(int i = 0; i < m->numseq;i++){ */ /* fprintf(stdout,"%d %s\n", */ /* m->sequences[i]->rank, */ /* m->sequences[i]->name */ /* ); */ /* } */ qsort(m->sequences, m->numseq, sizeof(struct msa_seq*),sort_by_rank); /* for(int i = 0; i < m->numseq;i++){ */ /* fprintf(stdout,"%d %s - sorted\n", */ /* m->sequences[i]->rank, */ /* m->sequences[i]->name */ /* ); */ /* } */ return OK; ERROR: return FAIL; } int msa_shuffle_seq(struct msa *m, struct rng_state* rng) { int r; int i,j; struct msa_seq* tmp; int n = m->numseq; for (i = 0; i < n - 1; i++) { r = tl_random_int(rng,n); j = i + r % (n-i); tmp = m->sequences[j]; m->sequences[j] = m->sequences[i]; m->sequences[i] = tmp; } return OK; } int sort_by_len_name(const void *a, const void *b) { struct msa_seq* const *one = a; struct msa_seq* const *two = b; if((*one)->len > (*two)->len){ return -1; }else if((*one)->len == (*two)->len){ int c = strncmp((*one)->name, (*two)->name, MSA_NAME_LEN); if(c < 0){ return -1; }else{ return 1; } }else{ return 1; } } int sort_by_rank(const void *a, const void *b) { struct msa_seq* const *one = a; struct msa_seq* const *two = b; if((*one)->rank > (*two)->rank){ return 1; }else{ return -1; } } kalign-3.5.1/lib/src/msa_sort.h000066400000000000000000000005261515023132300163200ustar00rootroot00000000000000#ifndef MSA_SORT_H #define MSA_SORT_H struct msa; struct rng_state; #ifdef MSA_SORT_IMPORT #define EXTERN #else #define EXTERN extern #endif EXTERN int msa_sort_len_name(struct msa *m); EXTERN int msa_sort_rank(struct msa *m); EXTERN int msa_shuffle_seq(struct msa *m, struct rng_state* rng); #undef MSA_SORT_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/msa_struct.h000066400000000000000000000031421515023132300166520ustar00rootroot00000000000000#ifndef MSA_STRUCT_H #define MSA_STRUCT_H #include #ifdef MSA_STRUCT_IMPORT #define EXTERN #else #define EXTERN extern #endif #define MSA_NAME_LEN 256 #define ALN_STATUS_UNALIGNED 1 /* no gaps sequences may or may not have equal lengths */ #define ALN_STATUS_ALIGNED 2 /* sequences have equal lengths and may or may not contain gaps*/ #define ALN_STATUS_FINAL 3 /* sequences have equal lengths and may or may not contain gaps*/ #define ALN_STATUS_UNKNOWN 3 /* sequences have un-equal length and contain gaps */ #define ALN_BIOTYPE_PROTEIN 0 #define ALN_BIOTYPE_DNA 1 #define ALN_BIOTYPE_UNDEF 2 struct msa_seq{ char* name; char* seq; uint8_t* s; int* gaps; float* confidence; /* per-position confidence [0..1], NULL if not computed */ int rank; int len; int alloc_len; }; struct msa{ struct msa_seq** sequences; float* seq_distances; /* per-sequence mean distance (normalized), set during tree building */ float* col_confidence; /* per-column confidence [0..1], NULL if not computed */ float* seq_weights; /* per-sequence tree-based weight, NULL when not computed */ int** sip; int* nsip; int* plen; uint8_t run_parallel; int numseq; int num_profiles; int alloc_numseq; int aligned; int alnlen; int letter_freq[128]; uint8_t L; uint8_t biotype; int quiet; void* consistency_table; /* struct consistency_table*, NULL when disabled */ }; #undef MSA_STRUCT_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/pick_anchor.c000066400000000000000000000044511515023132300167450ustar00rootroot00000000000000#include "tldevel.h" #include "msa_struct.h" #define PICK_ANCHOR_IMPORT #include "pick_anchor.h" struct sort_struct{ int len; int id; }; int sort_by_len(const void *a, const void *b); int* select_seqs(struct msa* msa, int num_anchor); int* pick_anchor(struct msa* msa, int* n) { int* anchors = NULL; int num_anchor = 0; ASSERT(msa != NULL, "No alignment."); /* num_anchor = MACRO_MAX(MACRO_MIN(32, msa->numseq), (int) pow(log2((double) msa->numseq), 2.0)); */ num_anchor = MACRO_MIN(32, msa->numseq); RUNP(anchors = select_seqs(msa, num_anchor)); *n = num_anchor; return anchors; ERROR: return NULL; } int* select_seqs(struct msa* msa, int num_anchor) { struct sort_struct** seq_sort = NULL; int* anchors = NULL; int i,stride; MMALLOC(seq_sort, sizeof(struct sort_struct*) * msa->numseq); for(i = 0; i < msa->numseq;i++){ seq_sort[i] = NULL; MMALLOC(seq_sort[i], sizeof(struct sort_struct)); seq_sort[i]->id = i; seq_sort[i]->len = msa->sequences[i]->len;// aln->sl[i]; } qsort(seq_sort, msa->numseq, sizeof(struct sort_struct*),sort_by_len); /* for(i = 0; i < msa->numseq;i++){ */ /* fprintf(stdout,"%d\t%d id: %d \n", seq_sort[i]->id,seq_sort[i]->len,seq_sort[i]->id); */ /* } */ //fprintf(stdout,"%d\t seeds\n", num_anchor); MMALLOC(anchors, sizeof(int) * num_anchor); stride = msa->numseq / num_anchor; // fprintf(stdout,"%d\tstride\n", stride); //c = 0; for(i = 0; i < num_anchor;i++){ anchors[i] = seq_sort[i*stride]->id; /* LOG_MSG("Anchor: %d",anchors[i] ); */ } ASSERT(i == num_anchor,"Cound not select all anchors\tnum_anchor:%d\t numseq:%d",num_anchor,msa->numseq); for(i = 0; i < msa->numseq;i++){ MFREE(seq_sort[i]); } MFREE(seq_sort); return anchors; ERROR: return NULL; } int sort_by_len(const void *a, const void *b) { struct sort_struct* const *one = a; struct sort_struct* const *two = b; if((*one)->len > (*two)->len){ return -1; }else{ return 1; } } kalign-3.5.1/lib/src/pick_anchor.h000066400000000000000000000004451515023132300167510ustar00rootroot00000000000000#ifndef PICK_ANCHOR_H #define PICK_ANCHOR_H #ifdef PICK_ANCHOR_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; EXTERN int* pick_anchor(struct msa* msa, int* n); #undef PICK_ANCHOR_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/poar.c000066400000000000000000000226531515023132300154320ustar00rootroot00000000000000#include "tldevel.h" #include #include #include #define POAR_IMPORT #include "poar.h" static inline int pair_index(int i, int j, int numseq) { /* Flat index for pair (i,j) where i < j */ return i * numseq - (i * (i + 1)) / 2 + (j - i - 1); } static inline uint32_t pack_key(int pos_i, int pos_j) { return ((uint32_t)pos_i << 20) | (uint32_t)pos_j; } static int poar_pair_alloc(struct poar_pair** pp) { struct poar_pair* p = NULL; MMALLOC(p, sizeof(struct poar_pair)); p->entries = NULL; p->n_entries = 0; p->alloc_entries = 64; MMALLOC(p->entries, sizeof(struct poar_entry) * p->alloc_entries); *pp = p; return OK; ERROR: return FAIL; } static void poar_pair_free(struct poar_pair* p) { if(p){ if(p->entries){ MFREE(p->entries); } MFREE(p); } } /* Insert key into sorted array, or update support if already present. */ static int poar_pair_insert(struct poar_pair* p, uint32_t key, int aln_idx) { /* Find insertion point */ int lo = 0; int hi = p->n_entries; while(lo < hi){ int mid = lo + (hi - lo) / 2; if(p->entries[mid].key < key){ lo = mid + 1; }else if(p->entries[mid].key == key){ /* Already exists, set bit */ p->entries[mid].support |= (1u << aln_idx); return OK; }else{ hi = mid; } } /* Need to insert at position lo */ if(p->n_entries >= p->alloc_entries){ p->alloc_entries *= 2; MREALLOC(p->entries, sizeof(struct poar_entry) * p->alloc_entries); } /* Shift entries right */ if(lo < p->n_entries){ memmove(&p->entries[lo + 1], &p->entries[lo], sizeof(struct poar_entry) * (p->n_entries - lo)); } p->entries[lo].key = key; p->entries[lo].support = (1u << aln_idx); p->n_entries++; return OK; ERROR: return FAIL; } int poar_table_alloc(struct poar_table** table, int numseq) { struct poar_table* t = NULL; int n_pairs; int i; MMALLOC(t, sizeof(struct poar_table)); t->pairs = NULL; t->numseq = numseq; t->n_alignments = 0; n_pairs = numseq * (numseq - 1) / 2; t->n_pairs = n_pairs; MMALLOC(t->pairs, sizeof(struct poar_pair*) * n_pairs); for(i = 0; i < n_pairs; i++){ t->pairs[i] = NULL; RUN(poar_pair_alloc(&t->pairs[i])); } *table = t; return OK; ERROR: poar_table_free(t); return FAIL; } void poar_table_free(struct poar_table* table) { if(table){ if(table->pairs){ for(int i = 0; i < table->n_pairs; i++){ poar_pair_free(table->pairs[i]); } MFREE(table->pairs); } MFREE(table); } } int pos_matrix_from_msa(struct pos_matrix** pm, char** seqs, int numseq, int alnlen) { struct pos_matrix* m = NULL; int i, j; MMALLOC(m, sizeof(struct pos_matrix)); m->col_to_res = NULL; m->numseq = numseq; m->alnlen = alnlen; MMALLOC(m->col_to_res, sizeof(int*) * numseq); for(i = 0; i < numseq; i++){ m->col_to_res[i] = NULL; MMALLOC(m->col_to_res[i], sizeof(int) * alnlen); int res_pos = -1; for(j = 0; j < alnlen; j++){ if(isalpha((int)seqs[i][j])){ res_pos++; m->col_to_res[i][j] = res_pos; }else{ m->col_to_res[i][j] = -1; } } } *pm = m; return OK; ERROR: pos_matrix_free(m); return FAIL; } void pos_matrix_free(struct pos_matrix* pm) { if(pm){ if(pm->col_to_res){ for(int i = 0; i < pm->numseq; i++){ if(pm->col_to_res[i]){ MFREE(pm->col_to_res[i]); } } MFREE(pm->col_to_res); } MFREE(pm); } } int extract_poars(struct poar_table* table, struct pos_matrix* pm, int aln_idx) { int i, j, col; int numseq = pm->numseq; int alnlen = pm->alnlen; ASSERT(aln_idx < 32, "Maximum 32 alignments supported in ensemble"); for(i = 0; i < numseq - 1; i++){ for(j = i + 1; j < numseq; j++){ int pidx = pair_index(i, j, numseq); struct poar_pair* pp = table->pairs[pidx]; for(col = 0; col < alnlen; col++){ int ri = pm->col_to_res[i][col]; int rj = pm->col_to_res[j][col]; if(ri >= 0 && rj >= 0){ uint32_t key = pack_key(ri, rj); RUN(poar_pair_insert(pp, key, aln_idx)); } } } } if(aln_idx >= table->n_alignments){ table->n_alignments = aln_idx + 1; } return OK; ERROR: return FAIL; } /* Binary POAR file format: 4 bytes: "POAR" magic 4 bytes: version (1) 4 bytes: numseq 4 bytes: n_alignments For each pair (n_pairs = numseq*(numseq-1)/2): 4 bytes: n_entries n_entries * 8 bytes: (key, support) pairs */ #define POAR_MAGIC 0x524F4150 /* "POAR" in little-endian */ #define POAR_VERSION 1 int poar_table_write(struct poar_table* table, const char* path) { FILE* fp = NULL; uint32_t magic = POAR_MAGIC; uint32_t version = POAR_VERSION; uint32_t numseq = (uint32_t)table->numseq; uint32_t n_alignments = (uint32_t)table->n_alignments; int i; ASSERT(table != NULL, "No POAR table"); ASSERT(path != NULL, "No output path"); fp = fopen(path, "wb"); if(!fp){ ERROR_MSG("Cannot open %s for writing", path); } fwrite(&magic, 4, 1, fp); fwrite(&version, 4, 1, fp); fwrite(&numseq, 4, 1, fp); fwrite(&n_alignments, 4, 1, fp); for(i = 0; i < table->n_pairs; i++){ struct poar_pair* pp = table->pairs[i]; uint32_t n_entries = (uint32_t)pp->n_entries; fwrite(&n_entries, 4, 1, fp); if(n_entries > 0){ fwrite(pp->entries, sizeof(struct poar_entry), n_entries, fp); } } fclose(fp); return OK; ERROR: if(fp) fclose(fp); return FAIL; } int poar_table_read(struct poar_table** out_table, const char* path) { FILE* fp = NULL; struct poar_table* t = NULL; uint32_t magic, version, numseq, n_alignments; int i; ASSERT(path != NULL, "No input path"); fp = fopen(path, "rb"); if(!fp){ ERROR_MSG("Cannot open %s for reading", path); } if(fread(&magic, 4, 1, fp) != 1 || magic != POAR_MAGIC){ ERROR_MSG("Invalid POAR file magic in %s", path); } if(fread(&version, 4, 1, fp) != 1 || version != POAR_VERSION){ ERROR_MSG("Unsupported POAR file version %u in %s", version, path); } if(fread(&numseq, 4, 1, fp) != 1){ ERROR_MSG("Failed to read numseq from %s", path); } if(fread(&n_alignments, 4, 1, fp) != 1){ ERROR_MSG("Failed to read n_alignments from %s", path); } MMALLOC(t, sizeof(struct poar_table)); t->pairs = NULL; t->numseq = (int)numseq; t->n_alignments = (int)n_alignments; t->n_pairs = (int)(numseq * (numseq - 1) / 2); MMALLOC(t->pairs, sizeof(struct poar_pair*) * t->n_pairs); for(i = 0; i < t->n_pairs; i++){ t->pairs[i] = NULL; } for(i = 0; i < t->n_pairs; i++){ uint32_t n_entries; struct poar_pair* pp = NULL; if(fread(&n_entries, 4, 1, fp) != 1){ ERROR_MSG("Failed to read pair %d entries count", i); } MMALLOC(pp, sizeof(struct poar_pair)); pp->entries = NULL; pp->n_entries = (int)n_entries; pp->alloc_entries = n_entries > 0 ? (int)n_entries : 1; MMALLOC(pp->entries, sizeof(struct poar_entry) * pp->alloc_entries); if(n_entries > 0){ if(fread(pp->entries, sizeof(struct poar_entry), n_entries, fp) != n_entries){ MFREE(pp->entries); MFREE(pp); ERROR_MSG("Failed to read pair %d entries", i); } } t->pairs[i] = pp; } fclose(fp); *out_table = t; return OK; ERROR: if(fp) fclose(fp); if(t) poar_table_free(t); return FAIL; } kalign-3.5.1/lib/src/poar.h000066400000000000000000000030001515023132300154200ustar00rootroot00000000000000#ifndef POAR_H #define POAR_H #ifdef POAR_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif #include /* Position matrix: maps (seq, col) -> residue position or -1 (gap) */ struct pos_matrix { int** col_to_res; /* [seq][col] -> residue pos or -1 */ int numseq; int alnlen; }; /* POAR entry: packed (pos_i, pos_j) key + support bitmask */ struct poar_entry { uint32_t key; /* (pos_i << 20) | pos_j */ uint32_t support; /* bitmask: bit k set if alignment k has this POAR */ }; /* One sorted array per sequence pair */ struct poar_pair { struct poar_entry* entries; int n_entries; int alloc_entries; }; /* Table of all POAR pairs */ struct poar_table { struct poar_pair** pairs; /* indexed by flattened (i,j) pair */ int n_pairs; /* numseq*(numseq-1)/2 */ int numseq; int n_alignments; }; EXTERN int poar_table_alloc(struct poar_table** table, int numseq); EXTERN void poar_table_free(struct poar_table* table); EXTERN int pos_matrix_from_msa(struct pos_matrix** pm, char** seqs, int numseq, int alnlen); EXTERN void pos_matrix_free(struct pos_matrix* pm); EXTERN int extract_poars(struct poar_table* table, struct pos_matrix* pm, int aln_idx); EXTERN int poar_table_write(struct poar_table* table, const char* path); EXTERN int poar_table_read(struct poar_table** table, const char* path); #undef POAR_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/sequence_distance.c000066400000000000000000000315551515023132300201540ustar00rootroot00000000000000#include "tldevel.h" #include #ifdef HAVE_AVX2 #include #include #endif #include "msa_struct.h" #define SEQUENCE_DISTANCE_IMPORT #include "sequence_distance.h" /* #include "alphabet.h" */ /* #include "alignment.h" */ /* #include "align_io.h" */ /* #include "misc.h" */ #include "bpm.h" #define NODESIZE 16 /* small hash implementation */ struct bignode{ struct bignode *next; unsigned int pos[NODESIZE]; unsigned int num; }; struct bignode* big_insert_hash(struct bignode *n,const unsigned int pos); void big_remove_nodes(struct bignode *n); void big_print_nodes(struct bignode *n); float dna_distance_calculation(struct bignode* hash[],const uint8_t * p,const int seqlen,int diagonals,float mode); float protein_wu_distance_calculation(struct bignode* hash[],const uint8_t* seq,const int seqlen,const int diagonals,const float mode); float** d_estimation(struct msa* msa, int* samples, int num_samples,int pair) { float** dm = NULL; uint8_t* seq_a; uint8_t* seq_b; float dist; int len_a; int len_b; int i,j; #if HAVE_AVX2 set_broadcast_mask(); #endif if(pair){ RUN(galloc(&dm,num_samples,num_samples)); for(i = 0; i < num_samples;i++){ seq_a = msa->sequences[samples[i]]->s;// aln->s[samples[i]]; len_a = msa->sequences[samples[i]]->len;//aln->sl[samples[i]]; for(j = 0;j < num_samples;j++){ //fprintf(stdout, "Working on %d %d\n", i,j); seq_b = msa->sequences[samples[j]]->s; //aln->s[ samples[j]]; len_b = msa->sequences[samples[j]]->len;//aln->sl[selection[j]]; /*dm[i][j] = MACRO_MIN(len_a, len_b) - MACRO_MIN( bpm_256(seq_a, seq_b, len_a, len_b), bpm_256(seq_b, seq_a, len_b, len_a) );*/ dist = calc_distance(seq_a, seq_b, len_a, len_b); /* give shorter sequences a preference */ int s = (len_a + len_b) / 2; float add = MACRO_MIN(10000.0, s) / 10000.0; dist += add; /* fprintf(stdout,"%f\n", add * 1000.0); */ //dist = dist / (float) MACRO_MIN(len_a, len_b); dm[i][j] = dist;// + (float)( i * num_samples + j) / (float) ( num_samples * num_samples); dm[j][i] = dm[i][j]; } /* fprintf(stdout,"\n"); */ } /* fprintf(stdout,"\n"); */ }else{ int a; int numseq = msa->numseq; MMALLOC(dm, sizeof(float*)* numseq); //fprintf(stdout,"MASK: %lx\n", mask); a = num_samples / 8; if( num_samples%8){ a++; } a = a << 3; for(i = 0; i < numseq;i++){ dm[i] = NULL; #ifdef HAVE_AVX2 dm[i] = _mm_malloc(sizeof(float) * a,32); #else MMALLOC(dm[i], sizeof(float) *a); #endif for(j = 0; j < a;j++){ dm[i][j] = 0.0F; } } struct msa_seq** s = msa->sequences; #ifdef HAVE_OPENMP #pragma omp parallel for shared(dm, s) private(i, j) collapse(2) schedule(static) #endif for(i = 0; i < numseq;i++){ for(j = 0;j < num_samples;j++){ uint8_t* s1; uint8_t* s2; int l1; int l2; s1 = s[i]->s; l1 = s[i]->len; s2 = s[samples[j]]->s; l2 = s[samples[j]]->len; dm[i][j] = calc_distance(s1,s2,l1,l2); int s = (l1 + l2) / 2; float add = MACRO_MIN(10000.0, s) / 10000.0; dm[i][j] += add; /* fprintf(stdout,"%f ",dm[i][j]); */ /* dm[i][j] += (float)MACRO_MIN(l1, l2) / (float)MACRO_MAX(l1, l2); */ /* dm[i][j] = dm[i][j] / (float) MACRO_MIN(l1, l2); */ //dm[i][j] = dist; } /* fprintf(stdout,"\n"); */ } /* fprintf(stdout,"\n"); */ /* for(i = 0; i < numseq;i++){ */ /* seq_a = msa->sequences[i]->s;// aln->s[i]; */ /* len_a = msa->sequences[i]->len;// aln->sl[i]; */ /* for(j = 0;j < num_samples;j++){ */ /* seq_b = msa->sequences[samples[j]]->s;// aln->s[ seeds[j]]; */ /* len_b = msa->sequences[samples[j]]->len;// aln->sl[seeds[j]]; */ /* dist = calc_distance(seq_a, seq_b, len_a, len_b,msa->L); */ /* dm[i][j] = dist; */ /* } */ /* } */ } return dm; ERROR: return NULL; } float calc_distance(uint8_t* seq_a, uint8_t* seq_b, int len_a,int len_b) { uint32_t dist; if(len_a > len_b){ dist = BPM(seq_a, seq_b, len_a, len_b); }else{ dist = BPM(seq_b, seq_a, len_b, len_a); } return (float)dist; } float protein_wu_distance_calculation(struct bignode* hash[],const uint8_t* seq,const int seqlen,const int diagonals,const float mode) { struct bignode* node_p; unsigned int* d = NULL; unsigned int* tmp = NULL; float out = 0.0; register int i,j; register int c; register int num; register unsigned int hv; d = malloc(sizeof(unsigned int)*diagonals); if(d == NULL) return 0.0f; //for (i = diagonals;i--;){ for (i = 0;i < diagonals;i++){ d[i] = 0; } for (i = seqlen-2;i--;){ //for(i = 0; i < seqlen-2;i++){ /*hv = (seq[i+1] << 5) + seq[i+2]; node_p = hash[hv]; while(node_p){ tmp = node_p->pos; for(j = 0;j < node_p->num;j++){ d[tmp[j]]++; } node_p = node_p->next; }*/ hv = (seq[i] << 5) + seq[i+1]; //printf("3:%d\n",hv); node_p = hash[hv]; while(node_p){ tmp = node_p->pos; num = node_p->num; for(j = 0;j < num;j++){ c = tmp[j]; d[c]++; c++; d[c]++; } node_p = node_p->next; } hv = (seq[i] << 5) + seq[i+2]; node_p = hash[hv]; while(node_p){ tmp = node_p->pos; num = node_p->num; for(j = 0;j < num;j++){ c = tmp[j]; d[c]++; } node_p = node_p->next; } d++; } //exit(0); d -= (seqlen-2); //unsigned int max = 0.0; for (i = diagonals;i--;){ // if(d[i] > max){ // max = d[i]; //} //d[i] /= minlen; //fprintf(stderr,"%d ",d[i]); if(d[i] > mode){ out += d[i]; // printf("%f %d\n",d[i]/ minlen,d[i]); } } free(d); //return out; return out; } float dna_distance_calculation(struct bignode* hash[],const uint8_t * p,const int seqlen,int diagonals,float mode) { struct bignode* node_p; float out = 0.0; unsigned int* tmp = NULL; unsigned int* d = NULL; int i,j; unsigned int hv; d = malloc(sizeof(unsigned int)*diagonals); if(d == NULL) return 0.0f; for (i = 0;i < diagonals;i++){ d[i] = 0; } for (i = seqlen-5;i--;){ hv = ((p[i]&3)<<8) + ((p[i+1]&3)<<6) + ((p[i+2]&3)<<4) + ((p[i+3]&3)<<2) + (p[i+4]&3);//ABCDE if (hash[hv]){ node_p = hash[hv]; while(node_p){ tmp = node_p->pos; for(j = 0;j < (int) node_p->num;j++){ d[tmp[j]]++; } node_p = node_p->next; } } hv = ((p[i]&3)<<8) + ((p[i+1]&3)<<6) + ((p[i+2]&3)<<4) + ((p[i+3]&3)<<2) + (p[i+5]&3);//ABCDF if (hash[hv]){ node_p = hash[hv]; while(node_p){ tmp = node_p->pos; for(j = 0;j < (int)node_p->num;j++){ d[tmp[j]]++; } node_p = node_p->next; } } hv = ((p[i]&3)<<8) + ((p[i+1]&3)<<6) + ((p[i+2]&3)<<4) + ((p[i+4]&3)<<2) + (p[i+5]&3);//ABCEF if (hash[hv]){ node_p = hash[hv]; while(node_p){ tmp = node_p->pos; for(j = 0;j < (int)node_p->num;j++){ d[tmp[j]]++; } node_p = node_p->next; } } hv = ((p[i]&3)<<8) + ((p[i+1]&3)<<6) + ((p[i+3]&3)<<4) + ((p[i+4]&3)<<2) + (p[i+5]&3);//ABDEF if (hash[hv]){ node_p = hash[hv]; while(node_p){ tmp = node_p->pos; for(j = 0;j < (int)node_p->num;j++){ d[tmp[j]]++; } node_p = node_p->next; } } hv = ((p[i]&3)<<8) + ((p[i+2]&3)<<6) + ((p[i+3]&3)<<4) + ((p[i+4]&3)<<2) + (p[i+5]&3);//ACDEF if (hash[hv]){ node_p = hash[hv]; while(node_p){ tmp = node_p->pos; for(j = 0;j < (int)node_p->num;j++){ d[tmp[j]]++; } node_p = node_p->next; } } d++; } //exit(0); d -= (seqlen-5); for (i = diagonals;i--;){ //d[i] /= minlen; //printf("%d ",d[i]); if(d[i] > mode){ //fprintf(stderr,"%f %d\n",d[i]/ minlen,d[i]); out += d[i]; } } free(d); return out; } struct bignode* big_insert_hash(struct bignode *n,const unsigned int pos) { struct bignode* p = NULL; if(n){ if(n->num < NODESIZE){ n->pos[n->num] = pos; n->num++; return n; }else{ MMALLOC(p, sizeof(struct bignode)); p->pos[0] = pos; p->num = 1; p->next = n; } }else{ MMALLOC(p, sizeof(struct bignode)); p->pos[0] = pos; p->num = 1; p->next = n; } return p; ERROR: return NULL; } void big_remove_nodes(struct bignode *n) { struct bignode* p = NULL; while(n){ p = n; n = n->next; MFREE(p); } } void big_print_nodes(struct bignode *n) { int i; while(n){ for (i = 0; i < (int)n->num;i++){ fprintf(stderr,"%d ",n->pos[i]); } n = n->next; } } kalign-3.5.1/lib/src/sequence_distance.h000066400000000000000000000010161515023132300201460ustar00rootroot00000000000000#ifndef SEQUENCE_DISTANCE_H #define SEQUENCE_DISTANCE_H #include #ifdef SEQUENCE_DISTANCE_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; /* #include "alignment_parameters.h" */ EXTERN float** d_estimation(struct msa* msa, int* samples, int num_samples,int pair); EXTERN float calc_distance(uint8_t *seq_a, uint8_t *seq_b, int len_a, int len_b); #undef SEQUENCE_DISTANCE_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/sp_score.c000066400000000000000000000170141515023132300163010ustar00rootroot00000000000000#include "tldevel.h" #include #include #include "msa_struct.h" #include "aln_param.h" #define SP_SCORE_IMPORT #include "sp_score.h" #define SP_ALPHA 23 /* Build a frequency profile from a group of sequences. For each profile column, counts residues (0..SP_ALPHA-1) and gaps. freq: pre-allocated array of prof_len * SP_ALPHA ints (zeroed) n_gap: pre-allocated array of prof_len ints (zeroed) Sequences are expanded one at a time via gap arrays to avoid O(N * L) simultaneous memory allocation. */ static int build_profile(struct msa* msa, int* sip, int nsip, int prof_len, int* freq, int* n_gap) { int i, j, k, pos, si; int8_t* cols = NULL; for(i = 0; i < nsip; i++){ si = sip[i]; /* Expand gap array into column array */ MMALLOC(cols, sizeof(int8_t) * prof_len); pos = 0; for(j = 0; j < msa->sequences[si]->len; j++){ for(k = 0; k < msa->sequences[si]->gaps[j]; k++){ cols[pos++] = -1; } cols[pos++] = (int8_t)msa->sequences[si]->s[j]; } for(k = 0; k < msa->sequences[si]->gaps[msa->sequences[si]->len]; k++){ cols[pos++] = -1; } /* Accumulate into frequency profile */ for(j = 0; j < prof_len; j++){ if(cols[j] >= 0 && cols[j] < SP_ALPHA){ freq[j * SP_ALPHA + (int)cols[j]]++; }else{ n_gap[j]++; } } MFREE(cols); cols = NULL; } return OK; ERROR: if(cols) MFREE(cols); return FAIL; } /* Compute profile-based SP score for cross-group sequence pairs. Instead of iterating all O(|A|*|B|) pairs, builds residue frequency profiles for each group and computes the expected score analytically: substitution: sum_r sum_s freq_a[r] * freq_b[s] * subm[r][s] gap penalty: gpo at path-level gap opens, gpe/tgpe per gap-residue pair The substitution component is exact (cross-group pairs are independent). Gap-open penalties are tracked at the path level (gap-in-A/B runs) which captures the dominant inter-group gap structure. Internal gap opens within profiles are not tracked (would require O(N^2) per-pair state). Complexity: O((|A|+|B|) * L) for profile construction + O(SP_ALPHA^2 * path_len) for scoring. */ int compute_sp_score(struct msa* msa, struct aln_param* ap, int* path, int* sip_a, int nsip_a, int* sip_b, int nsip_b, float* score) { int* freq_a = NULL; int* freq_b = NULL; int* gap_a = NULL; int* gap_b = NULL; int path_len; int i, j, c, si; int pos_a, pos_b; float total = 0.0F; const float gpo = ap->gpo; const float gpe = ap->gpe; const float tgpe = ap->tgpe; float** subm = ap->subm; path_len = path[0]; /* Compute profile lengths from first sequence in each group */ si = sip_a[0]; int prof_a_len = msa->sequences[si]->len; for(i = 0; i <= msa->sequences[si]->len; i++){ prof_a_len += msa->sequences[si]->gaps[i]; } si = sip_b[0]; int prof_b_len = msa->sequences[si]->len; for(i = 0; i <= msa->sequences[si]->len; i++){ prof_b_len += msa->sequences[si]->gaps[i]; } /* Allocate and build frequency profiles */ MMALLOC(freq_a, sizeof(int) * prof_a_len * SP_ALPHA); MMALLOC(gap_a, sizeof(int) * prof_a_len); memset(freq_a, 0, sizeof(int) * prof_a_len * SP_ALPHA); memset(gap_a, 0, sizeof(int) * prof_a_len); RUN(build_profile(msa, sip_a, nsip_a, prof_a_len, freq_a, gap_a)); MMALLOC(freq_b, sizeof(int) * prof_b_len * SP_ALPHA); MMALLOC(gap_b, sizeof(int) * prof_b_len); memset(freq_b, 0, sizeof(int) * prof_b_len * SP_ALPHA); memset(gap_b, 0, sizeof(int) * prof_b_len); RUN(build_profile(msa, sip_b, nsip_b, prof_b_len, freq_b, gap_b)); /* Walk the path and score using profiles. Track path-level gap runs for gap-open penalties. */ pos_a = 0; pos_b = 0; int in_a_gap = 0; /* currently in a gap-in-A run */ int in_b_gap = 0; /* currently in a gap-in-B run */ for(c = 1; c <= path_len; c++){ int step = path[c] & 3; int is_terminal = path[c] & 32; float pen = is_terminal ? tgpe : gpe; if(step == 0){ /* Match: both profiles advance */ int* fa = freq_a + pos_a * SP_ALPHA; int* fb = freq_b + pos_b * SP_ALPHA; /* Substitution: exact cross-group sum */ for(i = 0; i < SP_ALPHA; i++){ if(fa[i] == 0) continue; for(j = 0; j < SP_ALPHA; j++){ if(fb[j] == 0) continue; total += (float)(fa[i] * fb[j]) * subm[i][j]; } } /* Gap penalty: residue-gap cross pairs (gpe only, internal gap opens not tracked) */ int n_res_a = nsip_a - gap_a[pos_a]; int n_gap_b = gap_b[pos_b]; int n_gap_a = gap_a[pos_a]; int n_res_b = nsip_b - gap_b[pos_b]; total -= (float)(n_res_a * n_gap_b + n_gap_a * n_res_b) * pen; in_a_gap = 0; in_b_gap = 0; pos_a++; pos_b++; }else if(step == 1){ /* Gap in A: only B advances. All A sequences are gapped at the path level. Only B sequences with residues contribute penalty. */ int n_res_b = nsip_b - gap_b[pos_b]; int n_pairs = nsip_a * n_res_b; if(!in_a_gap){ total -= (float)n_pairs * gpo; } total -= (float)n_pairs * pen; in_a_gap = 1; in_b_gap = 0; pos_b++; }else if(step == 2){ /* Gap in B: only A advances. All B sequences are gapped at the path level. Only A sequences with residues contribute penalty. */ int n_res_a = nsip_a - gap_a[pos_a]; int n_pairs = n_res_a * nsip_b; if(!in_b_gap){ total -= (float)n_pairs * gpo; } total -= (float)n_pairs * pen; in_a_gap = 0; in_b_gap = 1; pos_a++; } } *score = total; MFREE(freq_a); MFREE(gap_a); MFREE(freq_b); MFREE(gap_b); return OK; ERROR: if(freq_a) MFREE(freq_a); if(gap_a) MFREE(gap_a); if(freq_b) MFREE(freq_b); if(gap_b) MFREE(gap_b); return FAIL; } kalign-3.5.1/lib/src/sp_score.h000066400000000000000000000006751515023132300163130ustar00rootroot00000000000000#ifndef SP_SCORE_H #define SP_SCORE_H #ifdef SP_SCORE_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; struct aln_param; EXTERN int compute_sp_score(struct msa* msa, struct aln_param* ap, int* path, int* sip_a, int nsip_a, int* sip_b, int nsip_b, float* score); #undef SP_SCORE_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/task.c000066400000000000000000000117471515023132300154350ustar00rootroot00000000000000#include "tldevel.h" #define ALN_TASK_IMPORT #include "task.h" static int sort_tasks_by_priority(const void *a, const void *b); static int sort_tasks_by_c(const void *a, const void *b); #ifdef TASKWRITETEST #include "tlrng.h" int main(void) { struct rng_state* rng = NULL; struct aln_tasks *t = NULL; rng = init_rng(0); int n_tasks = 54; alloc_tasks(&t, n_tasks); for(int i = 0; i < n_tasks;i++){ t->list[i]->score = 0.0; t->list[i]->a = tl_random_int(rng, 1000); t->list[i]->b = tl_random_int(rng, 1000); t->list[i]->c = tl_random_int(rng, 1000); t->list[i]->p = tl_random_int(rng, 1000); t->list[i]->n = tl_random_int(rng, 1000); t->n_tasks++; } RUN(write_tasks(t, "task_write_test.txt")); free_tasks(t); t = 0; RUN(read_tasks(&t, "task_write_test.txt" )); for(int i = 0; i < t->n_tasks;i++){ struct task* a = t->list[i]; fprintf(stdout,"%d %d %d %d %d\n",a->a,a->b,a->c,a->p,a->n); } free_tasks(t); free_rng(rng); return EXIT_SUCCESS; ERROR: if(t){ free_tasks(t); } if(rng){ free_rng(rng); } return EXIT_FAILURE; } #endif int write_tasks(struct aln_tasks *t, char *filename) { FILE* f_ptr = NULL; RUNP(f_ptr = fopen(filename, "w")); fprintf(f_ptr,"%d\n", t->n_tasks); for(int i = 0; i < t->n_tasks;i++){ struct task* a = t->list[i]; fprintf(f_ptr,"%d,%d,%d,%d,%d\n",a->a,a->b,a->c,a->p,a->n); } fclose(f_ptr); return OK; ERROR: if(f_ptr){ fclose(f_ptr); } return FAIL; } int read_tasks(struct aln_tasks **tasks, char *filename) { struct aln_tasks *t = NULL; FILE* f_ptr = NULL; RUNP(f_ptr = fopen(filename, "r")); int n_tasks = 0; fscanf( f_ptr, "%d", &n_tasks); RUN(alloc_tasks(&t, n_tasks)); for(int i = 0; i < n_tasks;i++){ struct task* a = t->list[i]; fscanf(f_ptr,"%d,%d,%d,%d,%d\n",&a->a,&a->b,&a->c,&a->p,&a->n); t->n_tasks++; } fclose(f_ptr); *tasks = t; return OK; ERROR: if(f_ptr){ fclose(f_ptr); } return FAIL; } int sort_tasks(struct aln_tasks* t , int order) { ASSERT(t != NULL, "No tasks"); ASSERT(t->n_tasks != 0, "No tasks"); switch (order) { case TASK_ORDER_PRIORITY: { qsort(t->list, t->n_tasks, sizeof(struct task*), sort_tasks_by_priority); break; } case TASK_ORDER_TREE: { qsort(t->list, t->n_tasks, sizeof(struct task*), sort_tasks_by_c); break; } default: ERROR_MSG("Task ordering %d not recognised.", order); break; } return OK; ERROR: return FAIL; } int sort_tasks_by_priority(const void *a, const void *b) { struct task* const *one = a; struct task* const *two = b; if((*one)->p >= (*two)->p){ return 1; }else{ return -1; } } int sort_tasks_by_c(const void *a, const void *b) { struct task* const *one = a; struct task* const *two = b; if((*one)->c >= (*two)->c){ return 1; }else{ return -1; } } int alloc_tasks(struct aln_tasks** tasks,int numseq) { struct aln_tasks* t = NULL; int np; int i; MMALLOC(t, sizeof(struct aln_tasks)); t->n_tasks = 0; t->n_alloc_tasks = numseq; t->list = NULL; t->profile = NULL; np = (numseq << 1) - 1; MMALLOC(t->profile,sizeof(float*)*np); for(i = 0; i < np;i++){ t->profile[i] = NULL; } MMALLOC(t->list, sizeof(struct task*) * t->n_alloc_tasks); for(i = 0; i < t->n_alloc_tasks;i++){ t->list[i] = NULL; MMALLOC(t->list[i], sizeof(struct task)); t->list[i]->confidence = 0.0F; } *tasks = t; return OK; ERROR: free_tasks(t); return FAIL; } void free_tasks(struct aln_tasks* t) { if(t){ for(int i = 0; i < t->n_alloc_tasks;i++){ MFREE(t->list[i]); } if(t->profile){ int np = t->n_alloc_tasks; np = (np << 1) - 1; for(int i = 0; i < np;i++){ if(t->profile[i]){ MFREE(t->profile[i]); } } MFREE(t->profile); } MFREE(t->list); MFREE(t); } } kalign-3.5.1/lib/src/task.h000066400000000000000000000023431515023132300154320ustar00rootroot00000000000000#ifndef ALN_TASK_H #define ALN_TASK_H #ifdef TASK_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct task{ float score; /* score of output alignment */ float confidence; /* average meetup margin (alignment confidence) */ int a; /* input 1 */ int b; /* input 2 */ int c; /* output */ int p; /* priority */ int n; /* amount of work */ }; struct aln_tasks{ struct task** list; /* list of pairwise alignments and their priority */ float** profile; /* buffer to hold output profiles */ /* int** map; /\* traceback paths *\/ */ int n_tasks; int n_alloc_tasks; }; #define TASK_ORDER_PRIORITY 1 #define TASK_ORDER_TREE 2 EXTERN int sort_tasks(struct aln_tasks* t , int order); EXTERN int alloc_tasks(struct aln_tasks** tasks,int numseq); EXTERN void free_tasks(struct aln_tasks* tasks); EXTERN int write_tasks(struct aln_tasks *t, char *filename); EXTERN int read_tasks(struct aln_tasks **tasks,char* filename); #undef TASK_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/test.c000066400000000000000000000003501515023132300154360ustar00rootroot00000000000000 #include "stdio.h" #include "test.h" /* #include "version.h" */ int add(int a, int b) { return sub(a,b);//a + b; } int sub(int a, int b) { fprintf(stdout," %s\n", KALIGN_PACKAGE_VERSION); return a -b; } kalign-3.5.1/lib/src/test.h000066400000000000000000000000751515023132300154470ustar00rootroot00000000000000#ifndef TEST_H #define TEST_H int sub(int a, int b); #endif kalign-3.5.1/lib/src/tldevel.c000066400000000000000000000324421515023132300161250ustar00rootroot00000000000000#include #include #include #define TLDEVEL_IMPORT #include "tldevel.h" #define TYPE_MARGIN 8 static void verror(FILE* f_ptr, const char *location, const char *format, va_list argp); static void vwarning(FILE* f_ptr,const char *location, const char *format, va_list argp); static void vlog(FILE* f_ptr,const char *format, va_list argp); static int get_time(char* time_ptr, int size); typedef struct { int dim1; int dim2; } mem_i; const char* tldevel_version(void) { return TLDEVEL_VERSION; } #define UNUSED(expr) do { (void)(expr); } while (0) int galloc_unknown_type_error (void* p, ...) { UNUSED(p); error(AT, "galloc was called with pointer of unknown type"); return FAIL; } int galloc_too_few_arg_error (void* p) { UNUSED(p); error(AT,"galloc was called with only one argument"); return FAIL; } #undef UNUSED /* g memory stuff */ int get_dim1(void* ptr,int* d) { if(ptr){ *d = ((mem_i*)((void*) ((char*)ptr - sizeof(mem_i))))->dim1; return OK; } return FAIL; } int get_dim2(void* ptr,int* d) { if(ptr){ *d = ((mem_i*)((void*) ((char*)ptr - sizeof(mem_i))))->dim2; return OK; } return FAIL; } #define ALLOC_1D_ARRAY(type) \ int alloc_1D_array_size_ ##type (type **array, int dim1) { \ mem_i* h = NULL; \ void* tmp = NULL; \ ASSERT(dim1 >= 1,"DIM1 is too small: %d",dim1); \ if(*array == NULL){ \ MMALLOC(tmp,(dim1 * sizeof **array + sizeof(mem_i))); \ }else{ \ tmp = *array; \ tmp = (void*) ((char*)tmp - sizeof(mem_i)); \ h = (mem_i*)(tmp); \ if(h->dim1 < dim1){ \ MREALLOC(tmp,(dim1 * sizeof **array + sizeof(mem_i))); \ }else{ \ *array = (type*) ((char*)tmp + sizeof(mem_i)); \ return OK; \ } \ } \ h = (mem_i*)(tmp); \ h->dim1 = dim1; \ h->dim2 = 0; \ *array= (type*) ((char*)tmp + sizeof(mem_i)); \ return OK; \ ERROR: \ gfree(*array); \ return FAIL; \ } ALLOC_1D_ARRAY(char) ALLOC_1D_ARRAY(int8_t) ALLOC_1D_ARRAY(uint8_t) ALLOC_1D_ARRAY(int16_t) ALLOC_1D_ARRAY(uint16_t) ALLOC_1D_ARRAY(int32_t) ALLOC_1D_ARRAY(uint32_t) ALLOC_1D_ARRAY(int64_t) ALLOC_1D_ARRAY(uint64_t) ALLOC_1D_ARRAY(float) ALLOC_1D_ARRAY(double) #undef ALLOC_1D_ARRAY #define ALLOC_2D_ARRAY(type) \ int alloc_2D_array_size_ ##type (type ***array, int dim1,int dim2) { \ int i,j,c; \ mem_i* h = NULL; \ type** ptr_t = NULL; \ type* ptr_tt = NULL; \ void* tmp = NULL; \ int max1, max2; \ int o1, o2; \ ASSERT(dim1 >= 1,"DIM1 is too small: %d",dim1); \ ASSERT(dim2 >= 1,"DIM1 is too small: %d",dim2); \ if(*array == NULL){ \ MMALLOC(tmp,(dim1 * sizeof **array+ sizeof(mem_i))); \ MMALLOC(ptr_tt,((dim1 * dim2) * sizeof ***array)); \ h = (mem_i*)tmp; \ h->dim1 = dim1; \ h->dim2 = dim2; \ max1 = dim1; \ max2 = dim2; \ ptr_t =(type**) ((char*)tmp + sizeof(mem_i)); \ for(i = 0;i< dim1;i++){ \ ptr_t[i] = ptr_tt + i * dim2; \ } \ *array = ptr_t; \ }else{ \ ptr_tt = *array[0]; \ tmp = (void*)( (char*)*array -sizeof(mem_i)); \ h = (mem_i*)tmp; \ o1 = h->dim1; \ o2 = h->dim2; \ max1 = MACRO_MAX(dim1,o1); \ max2 = MACRO_MAX(dim2,o2); \ if(dim1 > o1){ \ MREALLOC(tmp,(dim1 * sizeof **array+ sizeof(mem_i))); \ MREALLOC(ptr_tt,((dim1* max2) * sizeof ***array )); \ }else if(dim2 > o2){ \ MREALLOC(ptr_tt,((max1 * dim2) * sizeof ***array )); \ }else{ \ return OK; \ } \ if(dim2 > o2){ \ for(i = o1-1; i >= 0;i-- ){ \ c = i* max2; \ for(j = o2-1;j >=0;j--){ \ *(ptr_tt + c + j) =*(ptr_tt + i*o2 + j); \ } \ } \ } \ h = (mem_i*)tmp; \ h->dim1 = max1; \ h->dim2 = max2; \ ptr_t = (type**) ((char*)tmp + sizeof(mem_i)); \ for(i = 0; i < max1;i++){ \ ptr_t[i] = ptr_tt + i * max2; \ } \ *array = ptr_t; \ } \ return OK; \ ERROR: \ gfree(*array); \ return FAIL; \ } ALLOC_2D_ARRAY(char) ALLOC_2D_ARRAY(int8_t) ALLOC_2D_ARRAY(uint8_t) ALLOC_2D_ARRAY(int16_t) ALLOC_2D_ARRAY(uint16_t) ALLOC_2D_ARRAY(int32_t) ALLOC_2D_ARRAY(uint32_t) ALLOC_2D_ARRAY(int64_t) ALLOC_2D_ARRAY(uint64_t) ALLOC_2D_ARRAY(float) ALLOC_2D_ARRAY(double) #define FREE_VOID(type) \ void gfree_void_ ##type(type *a){\ error(AT, "free was called on wrong type (%p)",(void*)a); \ } FREE_VOID(char) FREE_VOID(int8_t) FREE_VOID(uint8_t) FREE_VOID(int16_t) FREE_VOID(uint16_t) FREE_VOID(int32_t) FREE_VOID(uint32_t) FREE_VOID(int64_t) FREE_VOID(uint64_t) FREE_VOID(float) FREE_VOID(double) #undef FREE_VOID #define FREE_1D_ARRAY(type) \ void free_1d_array_ ##type(type **array){ \ if(*array){ \ void* ptr = (void*)((char*)*array - sizeof(mem_i)); \ MFREE(ptr); \ *array = NULL; \ } \ } FREE_1D_ARRAY(char) FREE_1D_ARRAY(int8_t) FREE_1D_ARRAY(uint8_t) FREE_1D_ARRAY(int16_t) FREE_1D_ARRAY(uint16_t) FREE_1D_ARRAY(int32_t) FREE_1D_ARRAY(uint32_t) FREE_1D_ARRAY(int64_t) FREE_1D_ARRAY(uint64_t) FREE_1D_ARRAY(float) FREE_1D_ARRAY(double) #undef FREE_1D_ARRAY #define FREE_2D_ARRAY(type) \ void free_2d_array_ ##type(type ***array){ \ if(*array){ \ if(*array[0]){ \ MFREE(*array[0]); \ } \ void* ptr = (void*)((char*)*array- sizeof(mem_i)); \ MFREE(ptr); \ *array = NULL; \ } \ } FREE_2D_ARRAY(char) FREE_2D_ARRAY(int8_t) FREE_2D_ARRAY(uint8_t) FREE_2D_ARRAY(int16_t) FREE_2D_ARRAY(uint16_t) FREE_2D_ARRAY(int32_t) FREE_2D_ARRAY(uint32_t) FREE_2D_ARRAY(int64_t) FREE_2D_ARRAY(uint64_t) FREE_2D_ARRAY(float) FREE_2D_ARRAY(double) #undef FREE_2D_ARRAY void error(const char *location, const char *format, ...) { va_list argp; va_start(argp, format); verror(stderr,location,format,argp); va_end(argp); } void warning(const char *location, const char *format, ...) { va_list argp; va_start(argp, format); vwarning(stderr,location, format, argp); va_end(argp); } void log_message( const char *format, ...) { va_list argp; va_start(argp, format); vlog(stderr,format, argp); va_end(argp); } int get_time(char* time_ptr, int size) { //struct tm *ptr; time_t current = time(NULL); struct tm local_time; if((localtime_r(¤t,&local_time)) == NULL){ ERROR_MSG("could not get local time"); } if(!strftime(time_ptr, size, "[%F %H:%M:%S] ", &local_time))ERROR_MSG("write failed"); return OK; ERROR: return FAIL; } void verror(FILE* f_ptr, const char *location, const char *format, va_list argp) { char time_string[200]; if(get_time(time_string, 200) != OK){ fprintf(stderr,"notime"); } fprintf(f_ptr,"%*s: ",MESSAGE_MARGIN,time_string); fprintf(f_ptr,"%*s: ",TYPE_MARGIN,"ERROR "); vfprintf(f_ptr, format, argp); fprintf(f_ptr," (%s)\n",location); fflush(f_ptr); } void vwarning(FILE* f_ptr,const char *location, const char *format, va_list argp) { char time_string[200]; if(get_time(time_string, 200) != OK){ fprintf(stderr,"notime"); } fprintf(f_ptr,"%*s: ",MESSAGE_MARGIN,time_string); fprintf(f_ptr,"%*s: ",TYPE_MARGIN,"WARNING "); vfprintf(f_ptr, format, argp); fprintf(f_ptr," (%s)\n",location); fflush(f_ptr); } void vlog(FILE* f_ptr,const char *format, va_list argp) { char time_string[200]; if(get_time(time_string, 200) != OK){ fprintf(stderr,"notime"); } fprintf(f_ptr,"%*s: ",MESSAGE_MARGIN,time_string); fprintf(f_ptr,"%*s: ",TYPE_MARGIN,"LOG "); vfprintf(f_ptr, format, argp); fprintf(f_ptr,"\n"); fflush(f_ptr); } int nearly_equal_float(float a, float b) { float absa = fabsf(a); float absb = fabsf(b); float d = fabsf(a-b); if(a == b){ return 1; }else if (a == 0.0f || b == 0 || (absa + absb < FLT_MIN)){ return d < (FLT_EPSILON * FLT_MIN); }else{ return d / MACRO_MIN((absa+absb), FLT_MIN) < FLT_EPSILON; } } int nearly_equal_double(double a, double b) { double absa = fabs(a); double absb = fabs(b); double d = fabs(a-b); if(a == b){ return 1; }else if (a == 0.0f || b == 0 || (absa + absb < DBL_MIN)){ return d < (DBL_EPSILON * DBL_MIN); }else{ return d / MACRO_MIN((absa+absb), DBL_MIN) < DBL_EPSILON; } } kalign-3.5.1/lib/src/tldevel.h000066400000000000000000000255411515023132300161340ustar00rootroot00000000000000#ifndef TLDEVEL_H #define TLDEVEL_H #include #include #include #include #include #include #include #ifdef TLDEVEL_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif #define TLDEVEL_VERSION "1.0" #define OK 0 #define FAIL 1 #define MESSAGE_MARGIN 22 #define MACRO_MIN(a,b) (((a)<(b))?(a):(b)) #define MACRO_MAX(a,b) (((a)>(b))?(a):(b)) #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) #define AT __FILE__ " line " TOSTRING(__LINE__) #define ERROR_MSG(...) do { \ error(AT, __VA_ARGS__ ); \ goto ERROR; \ }while (0) #define WARNING_MSG(...) do { \ warning(AT, __VA_ARGS__ ); \ }while (0) #define LOG_MSG(...) do { \ log_message( __VA_ARGS__ ); \ }while (0) #define ASSERT(TEST,...) if(!(TEST)) { \ error(AT,#TEST ); \ error(AT, __VA_ARGS__); \ goto ERROR; \ } #if (DEBUGLEVEL >= 1) #define DASSERT(TEST,...) if(!(TEST)) { \ error(AT,#TEST ); \ error(AT, __VA_ARGS__); \ goto ERROR; \ } #else #define DASSERT(TEST,...) #endif #define ADDFAILED(x) "Function \"" TOSTRING(x) "\" failed." #define RUN(EXP) do { \ if((EXP) != OK){ \ ERROR_MSG(ADDFAILED(EXP)); \ } \ }while (0) #define RUNP(EXP) do { \ if((EXP) == NULL){ \ ERROR_MSG(ADDFAILED(EXP)); \ } \ }while (0) EXTERN int nearly_equal_float(float a, float b); EXTERN int nearly_equal_double(double a, double b); #define TLSAFE_EQ(X,Y) _Generic((X), \ float: nearly_equal_float, \ double: nearly_equal_double \ )(X,Y) /* Functions to declare and use a timer */ /* #define DECLARE_TIMER(n) struct timespec ts1_##n; struct timespec ts2_##n; #define START_TIMER(n) clock_gettime(CLOCK_MONOTONIC_RAW, &ts1_##n); #define STOP_TIMER(n) clock_gettime(CLOCK_MONOTONIC_RAW, &ts2_##n); #define GET_TIMING(n) (double)(ts2_##n.tv_sec - ts1_##n.tv_sec) + ((double) ts2_##n.tv_nsec - ts1_##n.tv_nsec) / 1000000000.0 */ /* Memory functions */ #define MFREE(p) do { \ if(p){ \ free(p); \ p = NULL; \ }else{ \ WARNING_MSG("free on a null pointer"); \ } \ } while (0) #define MMALLOC(p,size) do { \ if (p != NULL){ \ ERROR_MSG( "malloc on a nun-null pointer"); \ goto ERROR; \ } \ if(size == 0){ \ ERROR_MSG("malloc of size %d failed", size); \ goto ERROR; \ } \ if (((p) = malloc(size)) == NULL) { \ ERROR_MSG("malloc of size %d failed", size); \ goto ERROR; \ } \ } while (0) #define MREALLOC(p, size) do { \ void *tmpp; \ if(size == 0){ \ ERROR_MSG("malloc of size %d failed", size); \ goto ERROR; \ } \ if ((p) == NULL) { \ tmpp = malloc(size); \ }else { \ tmpp = realloc((p), (size)); \ } \ if (tmpp != NULL){ \ p = tmpp; \ }else { \ ERROR_MSG("realloc for size %d failed", size); \ goto ERROR; \ }} while (0) /* g memory functions */ EXTERN int get_dim1(void* ptr, int* d); EXTERN int get_dim2(void* ptr, int* d); /* #define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5,4,3,2,1) #define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,N,...) N #define macro_dispatcher(func, ...) macro_dispatcher_(func, VA_NUM_ARGS(__VA_ARGS__)) #define macro_dispatcher_(func, nargs) macro_dispatcher__(func, nargs) #define macro_dispatcher__(func, nargs) func ## nargs */ #define FUNC_DEF(type) \ EXTERN int alloc_1D_array_size_ ##type (type **array, int dim1); \ EXTERN int alloc_2D_array_size_ ##type (type ***array, int dim1,int dim2); \ EXTERN void gfree_void_ ##type(type *a); \ EXTERN void free_1d_array_ ##type(type **array); \ EXTERN void free_2d_array_ ##type(type ***array); FUNC_DEF(char) FUNC_DEF(int8_t) FUNC_DEF(uint8_t) FUNC_DEF(int16_t) FUNC_DEF(uint16_t) FUNC_DEF(int32_t) FUNC_DEF(uint32_t) FUNC_DEF(int64_t) FUNC_DEF(uint64_t) FUNC_DEF(float) FUNC_DEF(double) #undef FUNC_DEF EXTERN int galloc_unknown_type_error (void* p, ...); EXTERN int galloc_too_few_arg_error (void* p); #define p1(X) _Generic((X), \ default: galloc_too_few_arg_error \ )(X) #define p2(X,Y) _Generic((X), \ char**: alloc_1D_array_size_char, \ int8_t**: alloc_1D_array_size_int8_t, \ uint8_t**: alloc_1D_array_size_uint8_t, \ int16_t**: alloc_1D_array_size_int16_t, \ uint16_t**: alloc_1D_array_size_uint16_t, \ int32_t**: alloc_1D_array_size_int32_t, \ uint32_t**: alloc_1D_array_size_uint32_t, \ int64_t**: alloc_1D_array_size_int64_t, \ uint64_t**: alloc_1D_array_size_uint64_t, \ float**: alloc_1D_array_size_float, \ double**: alloc_1D_array_size_double, \ default: galloc_unknown_type_error \ )(X,Y) #define p3(X,Y,Z) _Generic((X), \ char***: alloc_2D_array_size_char, \ int8_t***: alloc_2D_array_size_int8_t, \ uint8_t***: alloc_2D_array_size_uint8_t, \ int16_t***: alloc_2D_array_size_int16_t, \ uint16_t***: alloc_2D_array_size_uint16_t, \ int32_t***: alloc_2D_array_size_int32_t, \ uint32_t***: alloc_2D_array_size_uint32_t, \ int64_t***: alloc_2D_array_size_int64_t, \ uint64_t***: alloc_2D_array_size_uint64_t, \ float***: alloc_2D_array_size_float, \ double***: alloc_2D_array_size_double, \ default: galloc_unknown_type_error \ )(X,Y,Z) #define _ARG3(_0, _1, _2, _3, ...) _3 #define NARG3(...) _ARG3(__VA_ARGS__,3, 2, 1, 0) #define _GALLOC_ARGS_1( a) p1(a) #define _GALLOC_ARGS_2( a, b) p2(a,b) #define _GALLOC_ARGS_3( a, b, c ) p3(a,b,c) #define __GALLOC_ARGS( N, ...) _GALLOC_ARGS_ ## N ( __VA_ARGS__) #define _GALLOC_ARGS( N, ...) __GALLOC_ARGS( N, __VA_ARGS__) #define GALLOC_ARGS( ...) _GALLOC_ARGS( NARG3(__VA_ARGS__), __VA_ARGS__) #define galloc(...) GALLOC_ARGS( __VA_ARGS__) #define gfree(X) _Generic((&X), \ char*: gfree_void_char,\ int8_t*: gfree_void_int8_t,\ uint8_t*: gfree_void_uint8_t,\ int16_t*: gfree_void_int16_t,\ uint16_t*: gfree_void_uint16_t,\ int32_t*: gfree_void_int32_t,\ uint32_t*: gfree_void_uint32_t,\ int64_t*: gfree_void_int64_t,\ uint64_t*: gfree_void_uint64_t,\ float*: gfree_void_float,\ double*: gfree_void_double,\ char**: free_1d_array_char,\ int8_t**: free_1d_array_int8_t,\ uint8_t**: free_1d_array_uint8_t,\ int16_t**: free_1d_array_int16_t, \ uint16_t**: free_1d_array_uint16_t, \ int32_t**: free_1d_array_int32_t,\ uint32_t**: free_1d_array_uint32_t,\ int64_t**: free_1d_array_int64_t,\ uint64_t**: free_1d_array_uint64_t,\ float**: free_1d_array_float,\ double**: free_1d_array_double, \ char***: free_2d_array_char, \ int8_t***: free_2d_array_int8_t,\ uint8_t***: free_2d_array_uint8_t,\ int16_t***: free_2d_array_int16_t, \ uint16_t***: free_2d_array_uint16_t, \ int32_t***: free_2d_array_int32_t,\ uint32_t***: free_2d_array_uint32_t,\ int64_t***: free_2d_array_int64_t,\ uint64_t***: free_2d_array_uint64_t,\ float***: free_2d_array_float,\ double***: free_2d_array_double \ )(&X) /* functions */ EXTERN void error(const char *location, const char *format, ...); EXTERN void warning(const char *location, const char *format, ...); EXTERN void log_message( const char *format, ...); EXTERN const char* tldevel_version(void); #undef TLDEVEL_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/tlmisc.c000066400000000000000000000123751515023132300157640ustar00rootroot00000000000000 #include #include #include /* #include "strnlen_compat.h" */ #define TLMISC_IMPORT #include "tlmisc.h" #include "tldevel.h" #define MAX_CMD_LEN 16384 int my_str_cpy(char* target, char* source, int t_size,int s_size) { if(s_size > t_size){ ERROR_MSG("Target size is < than source size"); } int s_len = strnlen(source, s_size); int t_len = strnlen(target, t_size); if(s_len > t_size){ ERROR_MSG("Target len is < than source size"); } for(int i = 0; i < t_len;i++){ target[i] = source[i]; } target[t_len] = 0; return OK; ERROR: return FAIL; } int my_str_append(char* target, char* source, int t_size,int s_size) { if(s_size > t_size){ ERROR_MSG("Target size is < than source size"); } int s_len = strnlen(source, s_size); int t_len = strnlen(target, t_size); if(s_len > t_size){ ERROR_MSG("Target len is < than source size"); } if(t_size - t_len < s_len){ ERROR_MSG("Target has insufficient space."); } int c = t_len; for(int i = 0; i < t_len;i++){ target[c] = source[i]; c++; } target[c] = 0; return OK; ERROR: return FAIL; } char* basename(const char* name) { int i= 0; int c = 0; while(1){ if(name[i] == '/'){ c = i+1; } if(!name[i]){ break; } i++; } return (char*)(name +c); } int my_file_exists(const char* name) { struct stat buf; int ret,local_ret; ret = 0; local_ret= stat ( name, &buf ); /* File found */ if ( local_ret == 0 ) { ret++; } return ret; } /* I don't like that both libgen and string have functions to work with directory / filenames. The functions below copy the input path and alloc a new character array to store the output. Needs to be MFREE'd... */ int tlfilename(char* path, char** out) { char* tmp = NULL; int len; int i; int c; len = 0; len = (int) strlen(path); MMALLOC(tmp, sizeof(char) * (len+1)); c = 0; for(i = 0;i < len;i++){ tmp[c] = path[i]; c++; if(path[i] == '/'){ c = 0; } } tmp[c] = 0; if(c == 0){ ERROR_MSG("No filename found in: %s", path); } *out = tmp; return OK; ERROR: if(tmp){ MFREE(tmp); } return FAIL; } int tldirname(char* path, char** out) { char* tmp = NULL; int len; int i; int c; int e; len = 0; len = (int) strlen(path); MMALLOC(tmp, sizeof(char) * (len+1)); c = 0; e = 0; for(i = 0;i < len;i++){ tmp[c] = path[i]; if(path[i] == '/'){ e = c; } c++; } tmp[e] = 0; if(e == 0){ ERROR_MSG("No dirname found in: %s", path); } *out = tmp; return OK; ERROR: if(tmp){ MFREE(tmp); } return FAIL; } int make_cmd_line(char** command, const int argc,char* const argv[]) { char* cmd = NULL; int i,j,c,g; int alloc_len = 16; int old_len; RUN(galloc(&cmd,alloc_len)); for(i =0 ; i < alloc_len;i++){ cmd[i] = 0; } c = 0; for(i =0 ; i < argc;i++){ //fprintf(stdout,"%s\n", argv[i]); for(j = 0; j < (int) strlen(argv[i]);j++){ if(c == 16384-1){ break; } cmd[c] = argv[i][j]; c++; if(c == alloc_len){ old_len = alloc_len; alloc_len = alloc_len + alloc_len /2; RUN(galloc(&cmd,alloc_len)); for(g = old_len; g < alloc_len;g++){ cmd[g] = 0; } } } if(c >= MAX_CMD_LEN){ ERROR_MSG("Command line too long! Allocated: %d", alloc_len); } if(c == 16384-1){ break; } cmd[c] = ' '; c++; if(c == alloc_len){ old_len = alloc_len; alloc_len = alloc_len + alloc_len /2; RUN(galloc(&cmd,alloc_len)); for(g = old_len; g < alloc_len;g++){ cmd[g] = 0; } } } cmd[c] = 0; *command = cmd; return OK; ERROR: if(cmd){ gfree(cmd); } return FAIL; } kalign-3.5.1/lib/src/tlmisc.h000066400000000000000000000011511515023132300157570ustar00rootroot00000000000000#ifndef TLMISC_H #define TLMISC_H #ifdef TLMISC_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif EXTERN char* basename(const char* name); EXTERN int my_str_cpy(char* target, char* source, int t_size,int s_size); EXTERN int my_str_append(char* target, char* source, int t_size,int s_size); EXTERN int my_file_exists(const char* name); EXTERN int make_cmd_line(char** command, const int argc,char* const argv[]); EXTERN int tlfilename(char* path, char** out); EXTERN int tldirname(char* path, char** out); #undef TLMISC_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/tlrng.c000066400000000000000000000316231515023132300156140ustar00rootroot00000000000000 #include #include #include /* #include */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define M_2PI 2.0*M_PI #include "tldevel.h" #define TLRNG_IMPORT #include "tlrng.h" /* code here was adopted from: */ /* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) To the extent possible under law, the author has dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. See . */ /* http://vigna.di.unimi.it/xorshift/xoshiro256starstar.c */ /* http://xoshiro.di.unimi.it/splitmix64.c */ /* written by: */ /* Sebastiano Vigna (vigna@acm.org) */ /* David Blackman */ /* code for sampling from varius distributions was taken from */ /* Copyright 2005 Robert Kern (robert.kern@gmail.com) * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* And code bits from */ /* the easel library (by Sean Eddy) */ struct rng_state{ uint64_t s[4]; uint8_t gen; double z1; int has_gauss; /* !=0: gauss contains a gaussian deviate */ double gauss; }; static inline uint64_t rotl(const uint64_t x, int k); static uint64_t next(struct rng_state* s); static void jump(struct rng_state* s); void long_jump(struct rng_state* s); static uint64_t choose_arbitrary_seed(void); static uint32_t jenkins_mix3(uint32_t a, uint32_t b, uint32_t c); static double tl_standard_gamma(struct rng_state* rng, double shape); static double tl_standard_exponential(struct rng_state* rng); static double tl_gauss(struct rng_state* rng); double tl_random_double(struct rng_state* rng) { uint64_t x; double y; do{ x = next(rng); y = ((double) x / 18446744073709551616.0); }while (y == 0.0); return y; } int tl_random_int(struct rng_state* rng,int a) { return (int) (tl_random_double(rng) * a); } /* from: */ //https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform double tl_random_gaussian(struct rng_state* rng, double mu, double sigma) { rng->gen = !rng->gen; if (!rng->gen){ return rng->z1 * sigma + mu; } double u1, u2; do{ u1 = tl_random_double(rng);// rand() * (1.0 / RAND_MAX); u2 = tl_random_double(rng);//rand() * (1.0 / RAND_MAX); } while (u1 <= DBL_EPSILON); double z0; z0 = sqrt(-2.0 * log(u1)) * cos(M_2PI * u2); rng->z1 = sqrt(-2.0 * log(u1)) * sin(M_2PI * u2); return z0 * sigma + mu; } double tl_random_gamma(struct rng_state* rng, double shape, double scale) { return scale * tl_standard_gamma(rng, shape); } double tl_standard_gamma(struct rng_state* rng, double shape) { double b, c; double U, V, X, Y; if (shape == 1.0) { return tl_standard_exponential(rng); } else if (shape < 1.0) { for (;;) { U = tl_random_double(rng); V = tl_standard_exponential(rng); if (U <= 1.0 - shape) { X = pow(U, 1./shape); if (X <= V) { return X; } } else { Y = -log((1-U)/shape); X = pow(1.0 - shape + shape*Y, 1./shape); if (X <= (V + Y)) { return X; } } } } else { b = shape - 1./3.; c = 1./sqrt(9*b); for (;;) { do { X = tl_gauss(rng); V = 1.0 + c*X; } while (V <= 0.0); V = V*V*V; U = tl_random_double(rng); if (U < 1.0 - 0.0331*(X*X)*(X*X)) return (b*V); if (log(U) < 0.5*X*X + b*(1. - V + log(V))) return (b*V); } } } double tl_standard_exponential(struct rng_state* rng) { /* We use -log(1-U) since U is [0, 1) */ return -log(1.0 - tl_random_double(rng)); } double tl_gauss(struct rng_state* rng) { if (rng->has_gauss) { const double tmp = rng->gauss; rng->gauss = 0; rng->has_gauss = 0; return tmp; } else { double f, x1, x2, r2; do { x1 = 2.0*tl_random_double(rng) - 1.0; x2 = 2.0*tl_random_double(rng) - 1.0; r2 = x1*x1 + x2*x2; } while (r2 >= 1.0 || r2 == 0.0); /* Box-Muller transform */ f = sqrt(-2.0*log(r2)/r2); /* Keep for next call */ rng->gauss = f*x1; rng->has_gauss = 1; return f*x2; } } struct rng_state* init_rng(uint64_t seed) { struct rng_state* s = NULL; uint64_t z; uint64_t sanity; MMALLOC(s, sizeof(struct rng_state)); s->gen = 0; s->z1 = 0.0f; s->gauss = 0.0; s->has_gauss = 0; if(!seed){ seed = choose_arbitrary_seed(); } sanity = 0; while(!sanity){ sanity = 0; z = (seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s->s[0] = z ^ (z >> 31); if(s->s[0]){ sanity++; } z = (seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s->s[1] = z ^ (z >> 31); if(s->s[1]){ sanity++; } z = (seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s->s[2] = z ^ (z >> 31); if(s->s[2]){ sanity++; } z = (seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s->s[3] = z ^ (z >> 31); if(s->s[3]){ sanity++; } } return s; ERROR: return NULL; } struct rng_state* init_rng_from_rng(struct rng_state* rng) { struct rng_state* s = NULL; int i; MMALLOC(s, sizeof(struct rng_state)); for(i = 0; i < 4;i++){ s->s[i] = rng->s[i]; s->gen = 0; s->z1 = 0.0; s->gauss = rng->gauss; s->has_gauss = rng->has_gauss; } jump(rng); return s; ERROR: return NULL; } void free_rng(struct rng_state* rng) { if(rng){ MFREE(rng); } } /* Taken from easel library (by Sean Eddy) */ static uint64_t choose_arbitrary_seed(void) { uint32_t a = (uint32_t) time ((time_t *) NULL); uint32_t b = 87654321; // we'll use getpid() below, if we can uint32_t c = (uint32_t) clock(); // clock() gives time since process invocation, in msec at least, if not usec uint64_t seed; #ifdef HAVE_GETPID b = (uint32_t) getpid(); // preferable b choice, if we have POSIX getpid() #endif seed = jenkins_mix3(a,b,c); // try to decorrelate closely spaced choices of pid/times return (seed == 0) ? 42 : seed; /* 42 is entirely arbitrary, just to avoid seed==0. */ } /* jenkins_mix3() * * from Bob Jenkins: given a,b,c, generate a number that's distributed * reasonably uniformly on the interval 0..2^32-1 even for closely * spaced choices of a,b,c. */ static uint32_t jenkins_mix3(uint32_t a, uint32_t b, uint32_t c) { a -= b; a -= c; a ^= (c>>13); b -= c; b -= a; b ^= (a<<8); c -= a; c -= b; c ^= (b>>13); a -= b; a -= c; a ^= (c>>12); b -= c; b -= a; b ^= (a<<16); c -= a; c -= b; c ^= (b>>5); a -= b; a -= c; a ^= (c>>3); b -= c; b -= a; b ^= (a<<10); c -= a; c -= b; c ^= (b>>15); return c; } static inline uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } /* This is xoshiro256** 1.0, one of our all-purpose, rock-solid generators. It has excellent (sub-ns) speed, a state (256 bits) that is large enough for any parallel application, and it passes all tests we are aware of. For generating just floating-point numbers, xoshiro256+ is even faster. The state must be seeded so that it is not everywhere zero. If you have a 64-bit seed, we suggest to seed a splitmix64 generator and use its output to fill s. */ uint64_t next(struct rng_state* s) { const uint64_t result_starstar = rotl(s->s[1] * 5, 7) * 9; const uint64_t t = s->s[1] << 17; s->s[2] ^= s->s[0]; s->s[3] ^= s->s[1]; s->s[1] ^= s->s[2]; s->s[0] ^= s->s[3]; s->s[2] ^= t; s->s[3] = rotl(s->s[3], 45); return result_starstar; } /* This is the jump function for the generator. It is equivalent to 2^128 calls to next(); it can be used to generate 2^128 non-overlapping subsequences for parallel computations. */ void jump(struct rng_state* s) { static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c }; uint64_t s0 = 0; uint64_t s1 = 0; uint64_t s2 = 0; uint64_t s3 = 0; for(uint64_t i = 0; i < sizeof JUMP / sizeof *JUMP; i++) for(int b = 0; b < 64; b++) { if (JUMP[i] & UINT64_C(1) << b) { s0 ^= s->s[0]; s1 ^= s->s[1]; s2 ^= s->s[2]; s3 ^= s->s[3]; } next(s); } s->s[0] = s0; s->s[1] = s1; s->s[2] = s2; s->s[3] = s3; } /* This is the long-jump function for the generator. It is equivalent to 2^192 calls to next(); it can be used to generate 2^64 starting points, from each of which jump() will generate 2^64 non-overlapping subsequences for parallel distributed computations. */ void long_jump(struct rng_state* s) { static const uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 }; uint64_t s0 = 0; uint64_t s1 = 0; uint64_t s2 = 0; uint64_t s3 = 0; for(uint64_t i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++) for(int b = 0; b < 64; b++) { if (LONG_JUMP[i] & UINT64_C(1) << b) { s0 ^= s->s[0]; s1 ^= s->s[1]; s2 ^= s->s[2]; s3 ^= s->s[3]; } next(s); } s->s[0] = s0; s->s[1] = s1; s->s[2] = s2; s->s[3] = s3; } kalign-3.5.1/lib/src/tlrng.h000066400000000000000000000013001515023132300156060ustar00rootroot00000000000000#ifndef TLRNG_H #define TLRNG_H #include #ifdef TLRNG_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif typedef struct rng_state rng_state; EXTERN struct rng_state* init_rng(uint64_t seed); EXTERN struct rng_state* init_rng_from_rng(struct rng_state* rng); EXTERN void free_rng(struct rng_state* rng); EXTERN double tl_random_double(struct rng_state* rng); EXTERN double tl_random_gaussian(struct rng_state* rng, double mu, double sigma); EXTERN double tl_random_gamma(struct rng_state* rng, double shape, double scale); EXTERN int tl_random_int(struct rng_state* rng,int a); #undef TLRNG_IMPORT #undef EXTERN #endif kalign-3.5.1/lib/src/version.h.in000066400000000000000000000001761515023132300165640ustar00rootroot00000000000000#cmakedefine KALIGN_PACKAGE_NAME "@CMAKE_PROJECT_NAME@" #cmakedefine KALIGN_PACKAGE_VERSION "@KALIGN_LIBRARY_VERSION_STRING@" kalign-3.5.1/lib/src/weave_alignment.c000066400000000000000000000055071515023132300176350ustar00rootroot00000000000000#include "task.h" #include "tldevel.h" #include "msa_struct.h" #define WEAVE_ALIGNMENT_IMPORT #include "weave_alignment.h" int update_gaps(int old_len,int*gis,int *newgaps); int clean_aln(struct msa* msa) { int i,j; int* p = NULL; for (i = 0; i < msa->numseq;i++){ p = msa->sequences[i]->gaps;// aln->gaps[i]; for (j = 0; j <= msa->sequences[i]->len;j++){ p[j] = 0; } } for(i =0;i < msa->numseq;i++){ msa->nsip[i] = 1; msa->sip[i][0] = i; } for (i = msa->numseq;i < msa->num_profiles ;i++){ if(msa->sip[i]){ MFREE(msa->sip[i]); msa->sip[i] = NULL; } msa->nsip[i] =0; } return OK; } int make_seq(struct msa* msa,int a,int b,int* path) { int* gap_a = NULL; int* gap_b = NULL; int c; int i; int posa = 0; int posb = 0; MMALLOC(gap_a,(path[0]+1)*sizeof(int)); MMALLOC(gap_b,(path[0]+1)*sizeof(int)); for (i = path[0]+1;i--;){ gap_a[i] = 0; gap_b[i] = 0; } c = 1; while(path[c] != 3){ if (!path[c]){ posa++; posb++; }else if (path[c] & 1){ gap_a[posa] += 1; posb++; }else if (path[c] & 2){ gap_b[posb] += 1; posa++; } c++; } for (i = msa->nsip[a];i--;){ RUN(update_gaps(msa->sequences[msa->sip[a][i]]->len, msa->sequences[msa->sip[a][i]]->gaps,gap_a)); //RUN(update_gaps(aln->sl[aln->sip[a][i]],aln->gaps[aln->sip[a][i]],path[0],gap_a)); } for (i = msa->nsip[b];i--;){ RUN(update_gaps(msa->sequences[msa->sip[b][i]]->len,msa->sequences[msa->sip[b][i]]->gaps,gap_b)); //RUN(update_gaps(aln->sl[aln->sip[b][i]],aln->gaps[aln->sip[b][i]],path[0],gap_b)); } MFREE(gap_a); MFREE(gap_b); return OK; ERROR: if(gap_a){ MFREE(gap_a); } if(gap_b){ MFREE(gap_b); } return FAIL; } int update_gaps(int old_len,int*gis,int *newgaps) { int i,j; int add = 0; int rel_pos = 0; for (i = 0; i <= old_len;i++){ add = 0; for (j = rel_pos;j <= rel_pos + gis[i];j++){ if (newgaps[j] != 0){ add += newgaps[j]; } } rel_pos += gis[i]+1; gis[i] += add; } return OK; } kalign-3.5.1/lib/src/weave_alignment.h000066400000000000000000000005451515023132300176370ustar00rootroot00000000000000#ifndef WEAVE_ALIGNMENT_H #define WEAVE_ALIGNMENT_H #ifdef WEAVE_ALIGNMENT_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif struct msa; EXTERN int make_seq(struct msa* msa,int a,int b,int* path); EXTERN int clean_aln(struct msa* msa); #undef WEAVE_ALIGNMENT_IMPORT #undef EXTERN #endif kalign-3.5.1/pyproject.toml000066400000000000000000000132251515023132300156770ustar00rootroot00000000000000[build-system] requires = [ "scikit-build-core>=0.11.4", "pybind11>=2.12", "cmake>=3.18", ] build-backend = "scikit_build_core.build" [project] name = "kalign-python" version = "3.5.1" description = "Python wrapper for the Kalign multiple sequence alignment engine" readme = "README-python.md" license = "Apache-2.0" license-files = ["COPYING"] authors = [ {name = "Timo Lassmann", email = "timolassmann@icloud.com"} ] maintainers = [ {name = "Timo Lassmann", email = "timolassmann@icloud.com"} ] keywords = [ "bioinformatics", "sequence alignment", "multiple sequence alignment", "MSA", "computational biology", "genomics", "proteomics", "phylogenetic analysis", "evolutionary biology", "biopython", "scikit-bio", "DNA alignment", "protein alignment", "RNA alignment", "fast alignment", "parallel alignment", "SIMD optimization" ] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", "Operating System :: OS Independent", "Programming Language :: C", "Programming Language :: C++", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering :: Bio-Informatics", "Topic :: Software Development :: Libraries :: Python Modules" ] requires-python = ">=3.9" dependencies = [ "numpy>=1.19.0", ] [project.scripts] kalign-py = "kalign.cli:main" [project.optional-dependencies] # Bioinformatics ecosystem integrations biopython = ["biopython>=1.85"] skbio = ["scikit-bio>=0.6.3"] io = ["biopython>=1.85"] # For I/O helper functions analysis = ["pandas>=2.3.0", "matplotlib>=3.9.4", "seaborn>=0.13.2"] all = ["biopython>=1.85", "scikit-bio>=0.6.3", "pandas>=2.3.0", "matplotlib>=3.9.4", "seaborn>=0.13.2"] benchmark = ["dash>=2.14", "plotly>=5.18", "pandas>=2.0", "tqdm>=4.60"] # Development dependencies dev = [ "pytest>=6.0", "pytest-cov", "pytest-benchmark", "pytest-xdist", "rich", "black", "flake8", "mypy", "build", "twine", "biopython>=1.85", # For testing ecosystem features "scikit-bio>=0.6.3" ] test = [ "pytest>=6.0", "pytest-cov", "pytest-benchmark", "pytest-xdist", "rich" ] docs = [ "sphinx", "sphinx-rtd-theme", "myst-parser" ] [project.urls] Homepage = "https://github.com/TimoLassmann/kalign" Documentation = "https://github.com/TimoLassmann/kalign/blob/main/README.md" Repository = "https://github.com/TimoLassmann/kalign" "Bug Tracker" = "https://github.com/TimoLassmann/kalign/issues" Changelog = "https://github.com/TimoLassmann/kalign/blob/main/ChangeLog" [tool.scikit-build] # Wheel settings - removed py-api to build version-specific wheels # wheel.py-api = "cp39" # CMake settings cmake.build-type = "Release" cmake.source-dir = "." # CMakeLists.txt is now in the same directory as pyproject.toml cmake.args = [ "-DBUILD_PYTHON_MODULE=ON", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON" ] build.targets = ["_core"] # Install settings install.components = ["python"] # Source distribution settings # Now that all files are in the same directory tree, sdist should work correctly sdist.exclude = [ "build*/", ".venv/", "__pycache__/", "**/*.pyc", "wheelhouse/", "dist/" ] # Explicitly include critical directories that might be excluded by default sdist.include = [ "lib/include/" ] # Logging logging.level = "DEBUG" [tool.scikit-build.cmake.define] BUILD_PYTHON_MODULE = "ON" [tool.cibuildwheel] # Build wheels for Python 3.9+ build = "cp39-* cp310-* cp311-* cp312-* cp313-*" # Skip 32-bit builds (PyPy wheels are not built by default) skip = "*-win32 *-manylinux_i686" # Test command test-command = "python -c 'import kalign; print(kalign.__version__)'" # Linux settings [tool.cibuildwheel.linux] before-all = [ "yum install -y cmake3 || apt-get update && apt-get install -y cmake", ] repair-wheel-command = "auditwheel repair -w {dest_dir} {wheel}" # macOS settings [tool.cibuildwheel.macos] before-all = [ "brew install cmake || echo 'cmake already installed'", ] repair-wheel-command = "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}" # Windows settings [tool.cibuildwheel.windows] before-all = [ "choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' || echo 'cmake already installed'", ] # Test settings for all platforms [tool.cibuildwheel.environment] # Set OpenMP variables for better performance OMP_NUM_THREADS = "1" [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py", "*_test.py"] python_functions = ["test_*"] addopts = [ "--strict-markers", "--strict-config", "--cov=kalign", "--cov-report=term-missing", "--cov-report=html" ] [tool.black] line-length = 88 target-version = ["py39"] include = '\.pyi?$' extend-exclude = ''' /( # directories \.eggs | \.git | \.hg | \.mypy_cache | \.tox | \.venv | build | dist )/ ''' [tool.mypy] python_version = "3.9" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true disallow_incomplete_defs = true check_untyped_defs = true no_implicit_optional = true warn_redundant_casts = true warn_unused_ignores = true warn_no_return = true warn_unreachable = true strict_equality = true [[tool.mypy.overrides]] module = "kalign._core" ignore_missing_imports = true [dependency-groups] dev = [ "build>=1.2.2.post1", "pytest>=8.4.1", "pytest-benchmark>=5.1.0", ] kalign-3.5.1/python-kalign/000077500000000000000000000000001515023132300155445ustar00rootroot00000000000000kalign-3.5.1/python-kalign/__init__.py000066400000000000000000001077651515023132300176750ustar00rootroot00000000000000""" Kalign - Fast multiple sequence alignment This package provides Python bindings for the Kalign multiple sequence alignment program. Kalign is a fast and accurate multiple sequence alignment tool for biological sequences. """ import os import threading from importlib import import_module from typing import Any, List, Literal, Optional, Union class AlignedSequences: """Result of aligning sequences from a file, preserving sequence names. Supports unpacking as ``names, sequences = result`` for backward compatibility, while also exposing optional confidence attributes. """ __slots__ = ("names", "sequences", "column_confidence", "residue_confidence") def __init__( self, names: List[str], sequences: List[str], column_confidence: Optional[List[float]] = None, residue_confidence: Optional[List[List[float]]] = None, ): self.names = names self.sequences = sequences self.column_confidence = column_confidence self.residue_confidence = residue_confidence # Backward-compatible 2-tuple unpacking: names, sequences = result def __iter__(self): return iter((self.names, self.sequences)) def __len__(self): return 2 def __getitem__(self, index): return (self.names, self.sequences)[index] def __repr__(self): return ( f"AlignedSequences(names={self.names!r}, sequences={self.sequences!r}, " f"column_confidence={'[...]' if self.column_confidence else None}, " f"residue_confidence={'[...]' if self.residue_confidence else None})" ) from importlib.metadata import version from . import _core, io, utils __version__ = version("kalign-python") __author__ = "Timo Lassmann" __email__ = "timolassmann@icloud.com" # Re-export constants for convenience DNA = _core.DNA DNA_INTERNAL = _core.DNA_INTERNAL RNA = _core.RNA PROTEIN = _core.PROTEIN PROTEIN_PFASUM43 = _core.PROTEIN_PFASUM43 PROTEIN_PFASUM60 = _core.PROTEIN_PFASUM60 PROTEIN_PFASUM_AUTO = _core.PROTEIN_PFASUM_AUTO PROTEIN_DIVERGENT = _core.PROTEIN_DIVERGENT AUTO = _core.AUTO # Refinement mode constants REFINE_NONE = _core.REFINE_NONE REFINE_ALL = _core.REFINE_ALL REFINE_CONFIDENT = _core.REFINE_CONFIDENT REFINE_INLINE = _core.REFINE_INLINE # Mode constants MODE_DEFAULT = "default" MODE_FAST = "fast" MODE_PRECISE = "precise" # Mode preset definitions _MODE_PRESETS = { "default": {"vsm_amax": -1.0, "consistency": 5, "consistency_weight": 2.0}, "fast": {"vsm_amax": -1.0, "consistency": 0, "consistency_weight": 2.0}, "precise": { "vsm_amax": -1.0, "ensemble": 3, "realign": 1, "consistency": 0, "consistency_weight": 2.0, }, } # Global thread control _thread_local = threading.local() _default_threads = 1 def _conf_to_pp(conf: float) -> str: """Convert a confidence value [0..1] to HMMER-style PP character.""" if conf >= 0.95: return "*" return str(int(conf * 10)) def _confidence_to_pp_string(seq: str, confidences: list) -> str: """Convert per-residue confidence array to PP string. Gap positions get '.', residues get HMMER-style PP characters. """ pp = [] for ch, conf in zip(seq, confidences): if ch == "-" or ch == ".": pp.append(".") else: pp.append(_conf_to_pp(conf)) return "".join(pp) def align( sequences: List[str], seq_type: Union[str, int] = "auto", gap_open: Optional[float] = None, gap_extend: Optional[float] = None, terminal_gap_extend: Optional[float] = None, n_threads: Optional[int] = None, refine: Union[str, int] = "none", ensemble: int = 0, min_support: int = 0, seq_weights: float = 0.0, consistency: int = 5, consistency_weight: float = 2.0, vsm_amax: float = -1.0, realign: int = 0, ensemble_seed: int = 42, mode: Optional[str] = None, fmt: Literal["plain", "biopython", "skbio"] = "plain", ids: Optional[List[str]] = None, ) -> Union[List[str], Any]: """ Multiple sequence alignment via Kalign. Parameters ---------- sequences : list of str List of sequences to align. Sequences should be provided as strings containing the sequence characters (e.g., 'ATCG' for DNA, 'ACGU' for RNA, or amino acid codes for proteins). seq_type : str or int, optional Sequence type specification. Can be: - "auto" or AUTO: Auto-detect sequence type (default) - "dna" or DNA: DNA sequences - "rna" or RNA: RNA sequences - "protein" or PROTEIN: Protein sequences - "divergent" or PROTEIN_DIVERGENT: Divergent protein sequences - "internal" or DNA_INTERNAL: DNA with internal gap preference gap_open : float, optional Gap opening penalty (positive value, e.g. 5.5). If None, uses Kalign defaults. gap_extend : float, optional Gap extension penalty (positive value, e.g. 2.0). If None, uses Kalign defaults. terminal_gap_extend : float, optional Terminal gap extension penalty (positive value, e.g. 1.0). If None, uses Kalign defaults. n_threads : int, optional Number of threads to use for alignment. If None, uses global default. refine : str or int, optional Refinement mode: "none", "all", "confident", or "inline" (default: "none"). ensemble : int, optional Number of ensemble runs (default: 0 = off). Set to e.g. 3 for higher accuracy at the cost of ~10x runtime. vsm_amax : float, optional Variable scoring matrix amplitude (default: -1.0 = use kalign defaults: 2.0 for protein, 0.0 for DNA/RNA). Set to 0.0 to disable. realign : int, optional Number of alignment-guided tree rebuild iterations (default: 0 = off). ensemble_seed : int, optional RNG seed for ensemble runs (default: 42). mode : str, optional Preset mode: "default" (consistency+VSM), "fast" (VSM only), "precise" (ensemble+VSM+realign). Explicit parameters override mode defaults. None is treated as "default". fmt : {'plain', 'biopython', 'skbio'}, default 'plain' Choose return-object flavour: - 'plain': list of aligned sequences (fastest) - 'biopython': Bio.Align.MultipleSeqAlignment object - 'skbio': skbio.TabularMSA object ids : list of str, optional Sequence IDs (used only for Biopython / scikit-bio objects). If None, generates 'seq0', 'seq1', etc. Returns ------- list of str | Bio.Align.MultipleSeqAlignment | skbio.TabularMSA Aligned sequences. Return type depends on `fmt` parameter. Raises ------ ValueError If input sequences are empty or invalid RuntimeError If alignment fails ImportError If Biopython or scikit-bio are requested but not installed Examples -------- >>> import kalign >>> sequences = ["ATCGATCGATCG", "ATCGTCGATCG", "ATCGATCATCG"] # 1) Plain list (default) >>> aligned = kalign.align(sequences) >>> print(aligned) ['ATCGATCGATCG', 'ATCG-TCGATCG', 'ATCGATC-ATCG'] # 2) Biopython object >>> aln_bp = kalign.align(sequences, fmt="biopython", ids=["s1","s2","s3"]) >>> print(type(aln_bp)) # 3) scikit-bio object >>> aln_sk = kalign.align(sequences, fmt="skbio") >>> print(type(aln_sk)) """ # Input validation - replicate C CLI robustness if not sequences: raise ValueError("No sequences were found in the input") if len(sequences) == 1: raise ValueError( "Only 1 sequence was found in the input - at least 2 sequences are required for alignment" ) if not all(isinstance(seq, str) for seq in sequences): raise ValueError("All sequences must be strings") # Check for empty or whitespace-only sequences empty_sequences = [] for i, seq in enumerate(sequences): if not seq or not seq.strip(): empty_sequences.append(i) if empty_sequences: if len(empty_sequences) == 1: raise ValueError( f"Sequence at index {empty_sequences[0]} is empty or contains only whitespace" ) else: raise ValueError( f"Sequences at indices {empty_sequences} are empty or contain only whitespace" ) # Check for valid sequence characters (basic validation) for i, seq in enumerate(sequences): # Remove common whitespace and check if anything remains cleaned_seq = "".join(seq.split()) if len(cleaned_seq) == 0: raise ValueError( f"Sequence at index {i} contains only whitespace characters" ) # Check for obviously invalid characters (control characters, etc) if any(ord(char) < 32 for char in cleaned_seq if char not in "\t\n\r"): raise ValueError( f"Sequence at index {i} contains invalid control characters" ) # Check for digits and other problematic characters that cause platform-specific segfaults invalid_chars = set(char for char in cleaned_seq if char.isdigit()) if invalid_chars: raise ValueError( f"Sequence at index {i} contains invalid characters: {sorted(invalid_chars)}. " f"Sequences should only contain valid biological sequence characters." ) # Warn about very short sequences (like C CLI warnings) very_short_sequences = [ i for i, seq in enumerate(sequences) if len(seq.strip()) < 3 ] if very_short_sequences and len(very_short_sequences) > len(sequences) * 0.5: import warnings warnings.warn( f"Many sequences are very short (< 3 characters). This may affect alignment quality.", UserWarning, stacklevel=2, ) # Convert string sequence types to integers seq_type_map = { "auto": AUTO, "dna": DNA, "rna": RNA, "protein": PROTEIN, "pfasum43": PROTEIN_PFASUM43, "pfasum60": PROTEIN_PFASUM60, "pfasum": PROTEIN_PFASUM_AUTO, "divergent": PROTEIN_DIVERGENT, "internal": DNA_INTERNAL, } if isinstance(seq_type, str): seq_type_lower = seq_type.lower() if seq_type_lower not in seq_type_map: raise ValueError( f"Invalid seq_type: {seq_type}. Must be one of: {list(seq_type_map.keys())}" ) seq_type_int = seq_type_map[seq_type_lower] else: seq_type_int = seq_type # Parameter validation and defaults # The C core expects positive penalty values (e.g., gpo=5.5, gpe=2.0). # A value of -1.0 signals "use defaults". if gap_open is None: gap_open = -1.0 elif not isinstance(gap_open, (int, float)): raise ValueError("gap_open must be a number") elif gap_open < 0: raise ValueError("gap_open must be a positive number (penalty value)") if gap_extend is None: gap_extend = -1.0 elif not isinstance(gap_extend, (int, float)): raise ValueError("gap_extend must be a number") elif gap_extend < 0: raise ValueError("gap_extend must be a positive number (penalty value)") if terminal_gap_extend is None: terminal_gap_extend = -1.0 elif not isinstance(terminal_gap_extend, (int, float)): raise ValueError("terminal_gap_extend must be a number") elif terminal_gap_extend < 0: raise ValueError( "terminal_gap_extend must be a positive number (penalty value)" ) # Handle thread count if n_threads is None: n_threads = get_num_threads() elif not isinstance(n_threads, int): raise ValueError("n_threads must be an integer") elif n_threads < 1: raise ValueError("n_threads must be at least 1") elif n_threads > 1024: # reasonable upper limit import warnings warnings.warn( f"Very high thread count ({n_threads}) may not improve performance and could cause issues.", UserWarning, stacklevel=2, ) # Resolve mode presets — collect explicitly-set params _explicit = {} # We detect "explicit" by checking if the value differs from the function signature default. # For mode-relevant params, the signature defaults match the "default" mode preset. if ensemble != 0: _explicit["ensemble"] = ensemble if realign != 0: _explicit["realign"] = realign if consistency != 5: _explicit["consistency"] = consistency if consistency_weight != 2.0: _explicit["consistency_weight"] = consistency_weight if vsm_amax != -1.0: _explicit["vsm_amax"] = vsm_amax resolved = _resolve_mode(mode, _explicit) ensemble = resolved.get("ensemble", ensemble) realign = resolved.get("realign", realign) consistency = resolved.get("consistency", consistency) consistency_weight = resolved.get("consistency_weight", consistency_weight) vsm_amax = resolved.get("vsm_amax", vsm_amax) # Convert refine mode refine_int = _parse_refine_mode(refine) # Validate ensemble if not isinstance(ensemble, int) or ensemble < 0: raise ValueError("ensemble must be a non-negative integer") # Call the C++ binding for core alignment confidence_data = None try: result = _core.align( sequences, seq_type_int, gap_open, gap_extend, terminal_gap_extend, n_threads, refine_int, ensemble, min_support, float(seq_weights), consistency, consistency_weight, vsm_amax, realign, ensemble_seed, ) # When ensemble is used, result is (sequences, confidence_dict) if isinstance(result, tuple): aligned_seqs = result[0] confidence_data = result[1] else: aligned_seqs = result except Exception as e: raise RuntimeError(f"Alignment failed: {str(e)}") # Validate IDs if provided (applies to all formats) if ids is not None and len(ids) != len(aligned_seqs): raise ValueError( f"Number of IDs ({len(ids)}) must match number of sequences ({len(aligned_seqs)})" ) # Handle different return formats if fmt == "plain": return aligned_seqs # Generate IDs if not provided (only for ecosystem formats) if ids is None: ids = [f"seq{i}" for i in range(len(aligned_seqs))] if fmt == "biopython": try: MultipleSeqAlignment = import_module("Bio.Align").MultipleSeqAlignment SeqRecord = import_module("Bio.SeqRecord").SeqRecord Seq = import_module("Bio.Seq").Seq except ModuleNotFoundError as e: raise ImportError( "Biopython not installed. Run: pip install kalign-python[biopython]" ) from e records = [] for idx, (s, i) in enumerate(zip(aligned_seqs, ids)): rec = SeqRecord(Seq(s), id=i) # Attach per-residue confidence as letter_annotations if available if confidence_data is not None: res_conf = confidence_data["residue_confidence"] if idx < len(res_conf) and len(res_conf[idx]) == len(s): pp_str = _confidence_to_pp_string(s, res_conf[idx]) rec.letter_annotations["posterior_probability"] = pp_str records.append(rec) return MultipleSeqAlignment(records) if fmt == "skbio": try: skbio_mod = import_module("skbio") skbio_seq = import_module("skbio.sequence") TabularMSA = skbio_mod.TabularMSA except ModuleNotFoundError as e: raise ImportError( "scikit-bio not installed. Run: pip install kalign-python[skbio]" ) from e # Select the appropriate skbio sequence type skbio_type_map = { DNA: skbio_seq.DNA, DNA_INTERNAL: skbio_seq.DNA, RNA: skbio_seq.RNA, PROTEIN: skbio_seq.Protein, PROTEIN_DIVERGENT: skbio_seq.Protein, } if seq_type_int in skbio_type_map: SeqClass = skbio_type_map[seq_type_int] else: # AUTO or unknown: infer from sequence content SeqClass = _infer_skbio_type(sequences, skbio_seq) return TabularMSA( [SeqClass(s, metadata={"id": i}) for s, i in zip(aligned_seqs, ids)] ) raise ValueError(f"Unknown fmt='{fmt}' (expected 'plain', 'biopython', 'skbio')") def _parse_refine_mode(refine): """Convert string or int refine mode to integer constant.""" if isinstance(refine, int): return refine refine_map = { "none": REFINE_NONE, "all": REFINE_ALL, "confident": REFINE_CONFIDENT, "inline": REFINE_INLINE, } refine_lower = refine.lower() if refine_lower not in refine_map: raise ValueError( f"Invalid refine mode: {refine}. Must be one of: {list(refine_map.keys())}" ) return refine_map[refine_lower] def _infer_skbio_type(sequences, skbio_seq): """Infer the appropriate skbio sequence class from raw sequence content.""" chars = set() for seq in sequences: chars.update(seq.upper().replace("-", "").replace(".", "")) dna_chars = set("ACGTNRYSWKMBDHV") rna_chars = set("ACGUNRYSWKMBDHV") if "U" in chars and "T" not in chars and chars <= rna_chars: return skbio_seq.RNA if chars <= dna_chars: return skbio_seq.DNA return skbio_seq.Protein def _resolve_mode(mode, explicit_kwargs): """Resolve mode presets, letting explicit parameters override. Parameters ---------- mode : str or None One of "default", "fast", "precise", or None (treated as "default"). explicit_kwargs : dict Only keys that the caller *explicitly* passed (not sentinel/default). Returns ------- dict Merged parameter values: mode defaults + explicit overrides. """ if mode is None: mode = "default" mode_lower = mode.lower() if mode_lower not in _MODE_PRESETS: raise ValueError( f"Invalid mode: {mode!r}. Must be one of: 'default', 'fast', 'precise'" ) result = dict(_MODE_PRESETS[mode_lower]) result.update(explicit_kwargs) return result def set_num_threads(n: int) -> None: """ Set the default number of threads for alignment operations. This affects all future calls to align() that don't explicitly specify n_threads. The setting is thread-local, so different threads can have different defaults. Parameters ---------- n : int Number of threads to use. Must be at least 1. Raises ------ ValueError If n is less than 1 Examples -------- >>> import kalign >>> kalign.set_num_threads(4) >>> aligned = kalign.align(sequences) # Uses 4 threads """ global _default_threads if n < 1: raise ValueError("Number of threads must be at least 1") # Use thread-local storage for thread safety _thread_local.num_threads = n # Also update global default for new threads _default_threads = n def get_num_threads() -> int: """ Get the current default number of threads for alignment operations. Returns ------- int Current default number of threads Examples -------- >>> import kalign >>> kalign.get_num_threads() 1 >>> kalign.set_num_threads(8) >>> kalign.get_num_threads() 8 """ return getattr(_thread_local, "num_threads", _default_threads) def align_from_file( input_file: str, seq_type: Union[str, int] = "auto", gap_open: Optional[float] = None, gap_extend: Optional[float] = None, terminal_gap_extend: Optional[float] = None, n_threads: Optional[int] = None, refine: Union[str, int] = "none", adaptive_budget: bool = False, ensemble: int = 0, ensemble_seed: int = 42, dist_scale: float = 0.0, vsm_amax: float = -1.0, min_support: int = 0, realign: int = 0, save_poar: str = "", load_poar: str = "", seq_weights: float = 0.0, consistency: int = 5, consistency_weight: float = 2.0, mode: Optional[str] = None, ) -> AlignedSequences: """ Align sequences from a file using Kalign. Parameters ---------- input_file : str Path to input file containing sequences. Supported formats: FASTA, MSF, Clustal, aligned FASTA. seq_type : str or int, optional Sequence type specification (same as align function) gap_open : float, optional Gap opening penalty gap_extend : float, optional Gap extension penalty terminal_gap_extend : float, optional Terminal gap extension penalty n_threads : int, optional Number of threads to use for alignment vsm_amax : float, optional Variable scoring matrix a_max parameter (default: -1.0 = use kalign defaults: 2.0 for protein, 0.0 for DNA/RNA). Set to 0.0 to disable. When > 0, subtracts max(0, amax - d) from all substitution scores, where d is the estimated pairwise distance. Returns ------- AlignedSequences Named tuple with ``names`` and ``sequences`` fields. Raises ------ FileNotFoundError If input file doesn't exist RuntimeError If alignment fails """ if not os.path.exists(input_file): raise FileNotFoundError(f"Input file not found: {input_file}") # Convert string sequence types to integers seq_type_map = { "auto": AUTO, "dna": DNA, "rna": RNA, "protein": PROTEIN, "pfasum43": PROTEIN_PFASUM43, "pfasum60": PROTEIN_PFASUM60, "pfasum": PROTEIN_PFASUM_AUTO, "divergent": PROTEIN_DIVERGENT, "internal": DNA_INTERNAL, } if isinstance(seq_type, str): seq_type_lower = seq_type.lower() if seq_type_lower not in seq_type_map: raise ValueError( f"Invalid seq_type: {seq_type}. Must be one of: {list(seq_type_map.keys())}" ) seq_type_int = seq_type_map[seq_type_lower] else: seq_type_int = seq_type # Use defaults if not specified if gap_open is None: gap_open = -1.0 if gap_extend is None: gap_extend = -1.0 if terminal_gap_extend is None: terminal_gap_extend = -1.0 # Handle thread count if n_threads is None: n_threads = get_num_threads() if n_threads < 1: raise ValueError("n_threads must be at least 1") # Resolve mode presets _explicit = {} if ensemble != 0: _explicit["ensemble"] = ensemble if realign != 0: _explicit["realign"] = realign if consistency != 5: _explicit["consistency"] = consistency if consistency_weight != 2.0: _explicit["consistency_weight"] = consistency_weight if vsm_amax != -1.0: _explicit["vsm_amax"] = vsm_amax resolved = _resolve_mode(mode, _explicit) ensemble = resolved.get("ensemble", ensemble) realign = resolved.get("realign", realign) consistency = resolved.get("consistency", consistency) consistency_weight = resolved.get("consistency_weight", consistency_weight) vsm_amax = resolved.get("vsm_amax", vsm_amax) # Convert refine mode refine_int = _parse_refine_mode(refine) # Call the C++ binding — returns (names, sequences) or (names, sequences, confidence) try: result = _core.align_from_file( input_file, seq_type_int, gap_open, gap_extend, terminal_gap_extend, n_threads, refine_int, int(adaptive_budget), ensemble, ensemble_seed, dist_scale, vsm_amax, min_support, realign, save_poar, load_poar, float(seq_weights), consistency, consistency_weight, ) if len(result) == 3: names, sequences, conf = result col_conf = list(conf["column_confidence"]) res_conf = [list(row) for row in conf["residue_confidence"]] return AlignedSequences( names=names, sequences=sequences, column_confidence=col_conf, residue_confidence=res_conf, ) else: names, sequences = result return AlignedSequences(names=names, sequences=sequences) except Exception as e: raise RuntimeError(f"Alignment failed: {str(e)}") def write_alignment( sequences: List[str], output_file: str, format: str = "fasta", ids: Optional[List[str]] = None, column_confidence: Optional[List[float]] = None, residue_confidence: Optional[List[List[float]]] = None, ) -> None: """ Write aligned sequences to a file. Parameters ---------- sequences : list of str List of aligned sequences output_file : str Path to output file format : str, optional Output format: "fasta", "clustal", "stockholm", "phylip" (default: "fasta") ids : list of str, optional Sequence IDs. If None, generates seq0, seq1, etc. Raises ------ ValueError If invalid format or empty sequence list ImportError If Biopython is not installed for non-FASTA formats Examples -------- >>> aligned = kalign.align(sequences) >>> kalign.write_alignment(aligned, "output.fasta") >>> kalign.write_alignment(aligned, "output.aln", format="clustal", ids=["seq1", "seq2"]) """ if not sequences: raise ValueError("Empty sequence list provided") format_lower = format.lower() # Map format aliases format_map = { "fasta": "fasta", "fa": "fasta", "clustal": "clustal", "aln": "clustal", "stockholm": "stockholm", "sto": "stockholm", "phylip": "phylip", "phy": "phylip", } if format_lower not in format_map: raise ValueError( f"Invalid format: {format}. Must be one of: fasta, clustal, stockholm, phylip" ) mapped_format = format_map[format_lower] # Use appropriate writer from io module (lazy import to avoid circular imports) from . import io if mapped_format == "fasta": io.write_fasta(sequences, output_file, ids=ids) elif mapped_format == "clustal": io.write_clustal(sequences, output_file, ids=ids) elif mapped_format == "stockholm": io.write_stockholm( sequences, output_file, ids=ids, column_confidence=column_confidence, residue_confidence=residue_confidence, ) elif mapped_format == "phylip": io.write_phylip(sequences, output_file, ids=ids) def generate_test_sequences( n_seq: int, n_obs: int, dna: bool, length: int, seed: int = 42 ) -> List[str]: """ Generate test sequences using DSSim HMM-based simulator. This function uses the DSSim (Dynamic Sequence Simulator) from the Kalign test suite to generate realistic evolutionary sequence data for testing and benchmarking purposes. Parameters ---------- n_seq : int Number of sequences to generate n_obs : int Number of observed sequences for training the HMM (typically 20-50) dna : bool True to generate DNA sequences, False to generate protein sequences length : int Target sequence length seed : int, optional Random seed for reproducible results (default: 42) Returns ------- list of str List of generated sequences Raises ------ RuntimeError If sequence generation fails Examples -------- >>> import kalign >>> # Generate 100 DNA sequences of length 200 >>> dna_seqs = kalign.generate_test_sequences(100, 20, True, 200) >>> len(dna_seqs) 100 >>> len(dna_seqs[0]) 200 >>> # Generate 50 protein sequences of length 150 >>> protein_seqs = kalign.generate_test_sequences(50, 30, False, 150) >>> len(protein_seqs) 50 """ if n_seq < 1: raise ValueError("n_seq must be at least 1") if n_obs < 1: raise ValueError("n_obs must be at least 1") if length < 1: raise ValueError("length must be at least 1") try: sequences = _core.generate_test_sequences(n_seq, n_obs, dna, length, seed) return sequences except Exception as e: raise RuntimeError(f"Test sequence generation failed: {str(e)}") def compare(reference_file: str, test_file: str) -> float: """ Compare two multiple sequence alignments and return SP score. Computes the sum-of-pairs (SP) score between a reference alignment and a test alignment. Sequences are matched by name, so both files must contain the same sequences. Parameters ---------- reference_file : str Path to reference alignment file (FASTA, MSF, or Clustal format) test_file : str Path to test alignment file Returns ------- float SP score (0-100), where 100 means identical alignments Raises ------ FileNotFoundError If either file doesn't exist RuntimeError If comparison fails """ if not os.path.exists(reference_file): raise FileNotFoundError(f"Reference file not found: {reference_file}") if not os.path.exists(test_file): raise FileNotFoundError(f"Test file not found: {test_file}") return _core.compare(reference_file, test_file) def compare_detailed( reference_file: str, test_file: str, max_gap_frac: float = 0.2, column_mask: Optional[List[int]] = None, ) -> dict: """ Compare two multiple sequence alignments returning detailed POAR scores. Computes BAliBASE-compatible recall (SP), precision, F1, and TC scores. Only "core" columns (gap fraction <= max_gap_frac in reference) are scored for recall/TC. Gap-gap matches are NOT counted. Parameters ---------- reference_file : str Path to reference alignment file (FASTA, MSF, or Clustal format) test_file : str Path to test alignment file max_gap_frac : float, optional Maximum gap fraction for a reference column to be scored (default: 0.2). Use -1.0 to score all columns regardless of gap content. Ignored when column_mask is provided. column_mask : list of int, optional Explicit binary mask (0/1) for each column in the reference alignment. When provided, only columns with mask=1 are scored (overrides max_gap_frac). Typically parsed from BAliBASE XML core block annotations. Returns ------- dict Keys: recall, precision, f1, tc, ref_pairs, test_pairs, common_pairs Raises ------ FileNotFoundError If either file doesn't exist RuntimeError If comparison fails """ if not os.path.exists(reference_file): raise FileNotFoundError(f"Reference file not found: {reference_file}") if not os.path.exists(test_file): raise FileNotFoundError(f"Test file not found: {test_file}") if column_mask is not None: return _core.compare_detailed_with_mask(reference_file, test_file, column_mask) return _core.compare_detailed(reference_file, test_file, max_gap_frac) def align_file_to_file( input_file: str, output_file: str, format: str = "fasta", seq_type: Union[str, int] = "auto", gap_open: Optional[float] = None, gap_extend: Optional[float] = None, terminal_gap_extend: Optional[float] = None, n_threads: Optional[int] = None, refine: Union[str, int] = "none", adaptive_budget: bool = False, ensemble: int = 0, ensemble_seed: int = 42, dist_scale: float = 0.0, vsm_amax: float = -1.0, min_support: int = 0, realign: int = 0, save_poar: str = "", load_poar: str = "", seq_weights: float = 0.0, consistency: int = 5, consistency_weight: float = 2.0, mode: Optional[str] = None, ) -> None: """ Align sequences from input file and write result to output file. Unlike align_from_file(), this preserves all sequence metadata (names, descriptions), which is required for MSA comparison with compare(). Parameters ---------- input_file : str Path to input file containing unaligned sequences output_file : str Path to output alignment file format : str, optional Output format: "fasta", "msf", "clu" (default: "fasta") seq_type : str or int, optional Sequence type (default: "auto") gap_open : float, optional Gap opening penalty gap_extend : float, optional Gap extension penalty terminal_gap_extend : float, optional Terminal gap extension penalty n_threads : int, optional Number of threads (default: uses global setting) vsm_amax : float, optional Variable scoring matrix a_max parameter (default: -1.0 = use kalign defaults: 2.0 for protein, 0.0 for DNA/RNA). Set to 0.0 to disable. Raises ------ FileNotFoundError If input file doesn't exist RuntimeError If alignment or writing fails """ if not os.path.exists(input_file): raise FileNotFoundError(f"Input file not found: {input_file}") seq_type_map = { "auto": AUTO, "dna": DNA, "rna": RNA, "protein": PROTEIN, "pfasum43": PROTEIN_PFASUM43, "pfasum60": PROTEIN_PFASUM60, "pfasum": PROTEIN_PFASUM_AUTO, "divergent": PROTEIN_DIVERGENT, "internal": DNA_INTERNAL, } if isinstance(seq_type, str): seq_type_lower = seq_type.lower() if seq_type_lower not in seq_type_map: raise ValueError( f"Invalid seq_type: {seq_type}. Must be one of: {list(seq_type_map.keys())}" ) seq_type_int = seq_type_map[seq_type_lower] else: seq_type_int = seq_type if gap_open is None: gap_open = -1.0 if gap_extend is None: gap_extend = -1.0 if terminal_gap_extend is None: terminal_gap_extend = -1.0 if n_threads is None: n_threads = get_num_threads() # Resolve mode presets _explicit = {} if ensemble != 0: _explicit["ensemble"] = ensemble if realign != 0: _explicit["realign"] = realign if consistency != 5: _explicit["consistency"] = consistency if consistency_weight != 2.0: _explicit["consistency_weight"] = consistency_weight if vsm_amax != -1.0: _explicit["vsm_amax"] = vsm_amax resolved = _resolve_mode(mode, _explicit) ensemble = resolved.get("ensemble", ensemble) realign = resolved.get("realign", realign) consistency = resolved.get("consistency", consistency) consistency_weight = resolved.get("consistency_weight", consistency_weight) vsm_amax = resolved.get("vsm_amax", vsm_amax) refine_int = _parse_refine_mode(refine) _core.align_file_to_file( input_file, output_file, format, seq_type_int, gap_open, gap_extend, terminal_gap_extend, n_threads, refine_int, int(adaptive_budget), ensemble, ensemble_seed, dist_scale, vsm_amax, min_support, realign, save_poar, load_poar, float(seq_weights), consistency, consistency_weight, ) # Convenience aliases kalign = align # For backward compatibility or alternative naming __all__ = [ "align", "align_from_file", "align_file_to_file", "compare", "compare_detailed", "write_alignment", "generate_test_sequences", "set_num_threads", "get_num_threads", "kalign", "AlignedSequences", "DNA", "DNA_INTERNAL", "RNA", "PROTEIN", "PROTEIN_PFASUM43", "PROTEIN_PFASUM60", "PROTEIN_PFASUM_AUTO", "PROTEIN_DIVERGENT", "AUTO", "REFINE_NONE", "REFINE_ALL", "REFINE_CONFIDENT", "REFINE_INLINE", "MODE_DEFAULT", "MODE_FAST", "MODE_PRECISE", "__version__", "__author__", "__email__", "io", "utils", ] kalign-3.5.1/python-kalign/_core.cpp000066400000000000000000000644661515023132300173570ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include // Include DSSim for sequence simulation and MSA structures extern "C" { #include "msa_struct.h" #include "msa_alloc.h" #include "msa_op.h" #include "msa_cmp.h" #include "dssim.h" } namespace py = pybind11; // Helper function to convert C strings to Python strings and free memory std::vector c_strings_to_python(char** c_strings, int count, int length) { std::vector result; result.reserve(count); for (int i = 0; i < count; ++i) { if (c_strings[i]) { result.emplace_back(c_strings[i], length); free(c_strings[i]); } } free(c_strings); return result; } // Helper to extract confidence data from MSA before freeing static py::object extract_confidence(struct msa* msa_data, int numseq) { if (!msa_data->col_confidence) { return py::none(); } int alnlen = msa_data->alnlen; // Per-column confidence py::list col_conf; for (int c = 0; c < alnlen; c++) { col_conf.append(msa_data->col_confidence[c]); } // Per-residue confidence py::list res_conf; for (int i = 0; i < numseq; i++) { py::list row; if (msa_data->sequences[i]->confidence) { for (int c = 0; c < alnlen; c++) { row.append(msa_data->sequences[i]->confidence[c]); } } res_conf.append(row); } py::dict result; result["column_confidence"] = col_conf; result["residue_confidence"] = res_conf; return result; } // Shared alignment routing helper — selects the appropriate kalign function // based on the combination of parameters provided. static int run_alignment(struct msa* msa_data, int n_threads, int seq_type, float gap_open, float gap_extend, float terminal_gap_extend, int refine, int adaptive_budget, int ensemble, uint64_t ensemble_seed, float dist_scale, float vsm_amax, int min_support, int realign, const std::string& save_poar, const std::string& load_poar, float use_seq_weights = -1.0f, int consistency_anchors = 0, float consistency_weight = 2.0f) { if (!load_poar.empty()) { return kalign_consensus_from_poar(msa_data, load_poar.c_str(), min_support > 0 ? min_support : 2); } else if (ensemble > 0) { const char* save_path = save_poar.empty() ? nullptr : save_poar.c_str(); return kalign_ensemble(msa_data, n_threads, seq_type, ensemble, gap_open, gap_extend, terminal_gap_extend, ensemble_seed, min_support, save_path, refine, dist_scale, vsm_amax, realign, use_seq_weights, consistency_anchors, consistency_weight); } else if (realign > 0) { return kalign_run_realign(msa_data, n_threads, seq_type, gap_open, gap_extend, terminal_gap_extend, refine, adaptive_budget, dist_scale, vsm_amax, realign, use_seq_weights, consistency_anchors, consistency_weight); } else if (consistency_anchors > 0) { return kalign_run_seeded(msa_data, n_threads, seq_type, gap_open, gap_extend, terminal_gap_extend, refine, adaptive_budget, 0, 0.0f, dist_scale, vsm_amax, use_seq_weights, consistency_anchors, consistency_weight); } else if (dist_scale > 0.0f || vsm_amax >= 0.0f || use_seq_weights >= 0.0f) { return kalign_run_dist_scale(msa_data, n_threads, seq_type, gap_open, gap_extend, terminal_gap_extend, refine, adaptive_budget, dist_scale, vsm_amax, use_seq_weights); } else { return kalign_run(msa_data, n_threads, seq_type, gap_open, gap_extend, terminal_gap_extend, refine, adaptive_budget); } } // Main alignment function py::object align_sequences( const std::vector& sequences, int seq_type = KALIGN_TYPE_UNDEFINED, float gap_open = -1.0f, float gap_extend = -1.0f, float terminal_gap_extend = -1.0f, int n_threads = 1, int refine = KALIGN_REFINE_NONE, int ensemble = 0, int min_support = 0, float seq_weights = -1.0f, int consistency_anchors = 0, float consistency_weight = 2.0f, float vsm_amax = -1.0f, int realign = 0, uint64_t ensemble_seed = 42 ) { if (sequences.empty()) { throw std::invalid_argument("Empty sequence list provided"); } // Convert Python strings to C format std::vector seq_ptrs; std::vector seq_lengths; seq_ptrs.reserve(sequences.size()); seq_lengths.reserve(sequences.size()); for (const auto& seq : sequences) { seq_ptrs.push_back(const_cast(seq.c_str())); seq_lengths.push_back(static_cast(seq.length())); } if (n_threads < 1) { n_threads = 1; } // Build msa struct from input arrays struct msa* msa_data = nullptr; int result = kalign_arr_to_msa(seq_ptrs.data(), seq_lengths.data(), static_cast(sequences.size()), &msa_data); if (result != 0 || !msa_data) { throw std::runtime_error("Failed to create MSA from input sequences"); } msa_data->quiet = 1; // Route to appropriate alignment function result = run_alignment(msa_data, n_threads, seq_type, gap_open, gap_extend, terminal_gap_extend, refine, 0, ensemble, ensemble_seed, 0.0f, vsm_amax, min_support, realign, "", "", seq_weights, consistency_anchors, consistency_weight); if (result != 0) { kalign_free_msa(msa_data); throw std::runtime_error("Kalign alignment failed with error code: " + std::to_string(result)); } // Extract confidence data before converting to arrays (which frees the MSA) py::object confidence = extract_confidence(msa_data, static_cast(sequences.size())); // Extract aligned sequences char** aligned_seqs = nullptr; int alignment_length = 0; result = kalign_msa_to_arr(msa_data, &aligned_seqs, &alignment_length); kalign_free_msa(msa_data); if (result != 0 || !aligned_seqs) { throw std::runtime_error("Failed to extract aligned sequences"); } // Convert results back to Python auto seqs = c_strings_to_python(aligned_seqs, static_cast(sequences.size()), alignment_length); // If ensemble was used and confidence data exists, return tuple if (ensemble > 0 && !confidence.is_none()) { return py::make_tuple(seqs, confidence); } // Otherwise return just sequences (backward compat) return py::cast(seqs); } // File-based alignment function — returns (names, sequences) or (names, sequences, confidence) py::object align_from_file( const std::string& input_file, int seq_type = KALIGN_TYPE_UNDEFINED, float gap_open = -1.0f, float gap_extend = -1.0f, float terminal_gap_extend = -1.0f, int n_threads = 1, int refine = KALIGN_REFINE_NONE, int adaptive_budget = 0, int ensemble = 0, uint64_t ensemble_seed = 42, float dist_scale = 0.0f, float vsm_amax = -1.0f, int min_support = 0, int realign = 0, const std::string& save_poar = "", const std::string& load_poar = "", float seq_weights = -1.0f, int consistency_anchors = 0, float consistency_weight = 2.0f ) { struct msa* msa_data = nullptr; // Read input file int result = kalign_read_input(const_cast(input_file.c_str()), &msa_data, 1); if (result != 0) { throw std::runtime_error("Failed to read input file: " + input_file); } // Check if msa_data is NULL - this happens when the file format cannot be detected if (!msa_data) { throw std::runtime_error("Could not detect valid sequence format in file: " + input_file); } // Perform alignment result = run_alignment(msa_data, n_threads, seq_type, gap_open, gap_extend, terminal_gap_extend, refine, adaptive_budget, ensemble, ensemble_seed, dist_scale, vsm_amax, min_support, realign, save_poar, load_poar, seq_weights, consistency_anchors, consistency_weight); if (result != 0) { kalign_free_msa(msa_data); throw std::runtime_error("Kalign alignment failed with error code: " + std::to_string(result)); } // Extract confidence data before writing (which doesn't preserve it) py::object confidence = extract_confidence(msa_data, msa_data->numseq); // Write to a temporary file so kalign_write_msa handles gap insertion const char* tmpdir = std::getenv("TMPDIR"); if (!tmpdir) tmpdir = std::getenv("TMP"); if (!tmpdir) tmpdir = std::getenv("TEMP"); if (!tmpdir) tmpdir = "/tmp"; std::string temp_file = std::string(tmpdir) + "/kalign_output.fa"; result = kalign_write_msa(msa_data, const_cast(temp_file.c_str()), const_cast("fasta")); kalign_free_msa(msa_data); if (result != 0) { throw std::runtime_error("Failed to write alignment results"); } // Parse the FASTA file, capturing both headers (names) and sequences std::ifstream file(temp_file); std::vector names; std::vector aligned_sequences; std::string line, current_name, current_seq; while (std::getline(file, line)) { if (line.empty()) continue; if (line[0] == '>') { if (!current_seq.empty()) { names.push_back(current_name); aligned_sequences.push_back(current_seq); current_seq.clear(); } // Strip the '>' prefix; take everything up to the first whitespace as the name current_name = line.substr(1); auto ws = current_name.find_first_of(" \t"); if (ws != std::string::npos) { current_name = current_name.substr(0, ws); } } else { current_seq += line; } } if (!current_seq.empty()) { names.push_back(current_name); aligned_sequences.push_back(current_seq); } // Clean up temp file std::remove(temp_file.c_str()); // If confidence data exists, return 3-tuple if (!confidence.is_none()) { return py::make_tuple(names, aligned_sequences, confidence); } return py::make_tuple(names, aligned_sequences); } // Generate test sequences using DSSim std::vector generate_test_sequences( int n_seq, int n_obs, bool dna, int length, int seed = 42 ) { struct msa* msa_data = nullptr; // Call DSSim to generate sequences int result = dssim_get_fasta(&msa_data, n_seq, n_obs, dna ? 1 : 0, length, seed); if (result != 0) { throw std::runtime_error("DSSim sequence generation failed with error code: " + std::to_string(result)); } if (!msa_data) { throw std::runtime_error("DSSim returned null MSA data"); } // Convert MSA sequences to Python strings std::vector sequences; sequences.reserve(msa_data->numseq); for (int i = 0; i < msa_data->numseq; ++i) { if (msa_data->sequences[i] && msa_data->sequences[i]->seq) { sequences.emplace_back(msa_data->sequences[i]->seq, msa_data->sequences[i]->len); } } // Clean up kalign_free_msa(msa_data); return sequences; } // Compare two MSA files (reference vs test), returning SP score float compare_msa_files(const std::string& reference_file, const std::string& test_file) { struct msa* ref = nullptr; struct msa* test = nullptr; float score = 0.0f; int result = kalign_read_input(const_cast(reference_file.c_str()), &ref, 1); if (result != 0 || !ref) { throw std::runtime_error("Failed to read reference file: " + reference_file); } result = kalign_read_input(const_cast(test_file.c_str()), &test, 1); if (result != 0 || !test) { kalign_free_msa(ref); throw std::runtime_error("Failed to read test file: " + test_file); } result = kalign_msa_compare(ref, test, &score); kalign_free_msa(ref); kalign_free_msa(test); if (result != 0) { throw std::runtime_error("MSA comparison failed"); } return score; } // Compare two MSA files returning detailed POAR scores py::dict compare_detailed_files(const std::string& reference_file, const std::string& test_file, float max_gap_frac = 0.2f) { struct msa* ref = nullptr; struct msa* test = nullptr; struct poar_score score; int result = kalign_read_input(const_cast(reference_file.c_str()), &ref, 1); if (result != 0 || !ref) { throw std::runtime_error("Failed to read reference file: " + reference_file); } result = kalign_read_input(const_cast(test_file.c_str()), &test, 1); if (result != 0 || !test) { kalign_free_msa(ref); throw std::runtime_error("Failed to read test file: " + test_file); } result = kalign_msa_compare_detailed(ref, test, max_gap_frac, &score); kalign_free_msa(ref); kalign_free_msa(test); if (result != 0) { throw std::runtime_error("Detailed MSA comparison failed"); } py::dict d; d["recall"] = score.recall; d["precision"] = score.precision; d["f1"] = score.f1; d["tc"] = score.tc; d["ref_pairs"] = score.ref_pairs; d["test_pairs"] = score.test_pairs; d["common_pairs"] = score.common; return d; } // Compare two MSA files with an explicit column mask py::dict compare_detailed_with_mask_files(const std::string& reference_file, const std::string& test_file, py::list column_mask) { struct msa* ref = nullptr; struct msa* test = nullptr; struct poar_score score; int result = kalign_read_input(const_cast(reference_file.c_str()), &ref, 1); if (result != 0 || !ref) { throw std::runtime_error("Failed to read reference file: " + reference_file); } result = kalign_read_input(const_cast(test_file.c_str()), &test, 1); if (result != 0 || !test) { kalign_free_msa(ref); throw std::runtime_error("Failed to read test file: " + test_file); } // Convert py::list to int array int n_cols = static_cast(column_mask.size()); std::vector mask(n_cols); for (int i = 0; i < n_cols; i++) { mask[i] = column_mask[i].cast(); } result = kalign_msa_compare_with_mask(ref, test, mask.data(), n_cols, &score); kalign_free_msa(ref); kalign_free_msa(test); if (result != 0) { throw std::runtime_error("Detailed MSA comparison with mask failed"); } py::dict d; d["recall"] = score.recall; d["precision"] = score.precision; d["f1"] = score.f1; d["tc"] = score.tc; d["ref_pairs"] = score.ref_pairs; d["test_pairs"] = score.test_pairs; d["common_pairs"] = score.common; return d; } // Align sequences from input file and write result to output file, preserving all metadata void align_file_to_file( const std::string& input_file, const std::string& output_file, const std::string& format = "fasta", int seq_type = KALIGN_TYPE_UNDEFINED, float gap_open = -1.0f, float gap_extend = -1.0f, float terminal_gap_extend = -1.0f, int n_threads = 1, int refine = KALIGN_REFINE_NONE, int adaptive_budget = 0, int ensemble = 0, uint64_t ensemble_seed = 42, float dist_scale = 0.0f, float vsm_amax = -1.0f, int min_support = 0, int realign = 0, const std::string& save_poar = "", const std::string& load_poar = "", float seq_weights = -1.0f, int consistency_anchors = 0, float consistency_weight = 2.0f ) { struct msa* msa_data = nullptr; int result = kalign_read_input(const_cast(input_file.c_str()), &msa_data, 1); if (result != 0 || !msa_data) { throw std::runtime_error("Failed to read input file: " + input_file); } result = run_alignment(msa_data, n_threads, seq_type, gap_open, gap_extend, terminal_gap_extend, refine, adaptive_budget, ensemble, ensemble_seed, dist_scale, vsm_amax, min_support, realign, save_poar, load_poar, seq_weights, consistency_anchors, consistency_weight); if (result != 0) { kalign_free_msa(msa_data); throw std::runtime_error("Alignment failed with error code: " + std::to_string(result)); } result = kalign_write_msa(msa_data, const_cast(output_file.c_str()), const_cast(format.c_str())); kalign_free_msa(msa_data); if (result != 0) { throw std::runtime_error("Failed to write output file: " + output_file); } } PYBIND11_MODULE(_core, m) { m.doc() = "Python bindings for Kalign multiple sequence alignment"; // Main alignment function m.def("align", &align_sequences, py::arg("sequences"), py::arg("seq_type") = KALIGN_TYPE_UNDEFINED, py::arg("gap_open") = -1.0f, py::arg("gap_extend") = -1.0f, py::arg("terminal_gap_extend") = -1.0f, py::arg("n_threads") = 1, py::arg("refine") = KALIGN_REFINE_NONE, py::arg("ensemble") = 0, py::arg("min_support") = 0, py::arg("seq_weights") = -1.0f, py::arg("consistency_anchors") = 0, py::arg("consistency_weight") = 2.0f, py::arg("vsm_amax") = -1.0f, py::arg("realign") = 0, py::arg("ensemble_seed") = (uint64_t)42, R"pbdoc( Align a list of sequences using Kalign. Parameters ---------- sequences : list of str List of sequences to align seq_type : int, optional Sequence type (default: auto-detect) gap_open : float, optional Gap opening penalty (default: -1.0, uses Kalign defaults) gap_extend : float, optional Gap extension penalty (default: -1.0, uses Kalign defaults) terminal_gap_extend : float, optional Terminal gap extension penalty (default: -1.0, uses Kalign defaults) n_threads : int, optional Number of threads to use (default: 1) refine : int, optional Refinement mode (default: REFINE_NONE) ensemble : int, optional Number of ensemble runs (default: 0 = off) min_support : int, optional Explicit consensus threshold (default: 0 = auto) vsm_amax : float, optional Variable scoring matrix amplitude (default: -1.0, uses Kalign defaults) realign : int, optional Number of realignment iterations (default: 0 = off) ensemble_seed : int, optional RNG seed for ensemble (default: 42) Returns ------- list of str or tuple When ensemble > 0: (aligned_seqs, confidence_dict) Otherwise: aligned sequences )pbdoc"); // File-based alignment — returns (names, sequences) or (names, sequences, confidence) m.def("align_from_file", &align_from_file, py::arg("input_file"), py::arg("seq_type") = KALIGN_TYPE_UNDEFINED, py::arg("gap_open") = -1.0f, py::arg("gap_extend") = -1.0f, py::arg("terminal_gap_extend") = -1.0f, py::arg("n_threads") = 1, py::arg("refine") = KALIGN_REFINE_NONE, py::arg("adaptive_budget") = 0, py::arg("ensemble") = 0, py::arg("ensemble_seed") = (uint64_t)42, py::arg("dist_scale") = 0.0f, py::arg("vsm_amax") = -1.0f, py::arg("min_support") = 0, py::arg("realign") = 0, py::arg("save_poar") = "", py::arg("load_poar") = "", py::arg("seq_weights") = -1.0f, py::arg("consistency_anchors") = 0, py::arg("consistency_weight") = 2.0f, "Align sequences from a file. Returns (names, sequences) or (names, sequences, confidence) tuple."); // Generate test sequences using DSSim m.def("generate_test_sequences", &generate_test_sequences, py::arg("n_seq"), py::arg("n_obs"), py::arg("dna"), py::arg("length"), py::arg("seed") = 42, R"pbdoc( Generate test sequences using DSSim HMM-based simulator. Parameters ---------- n_seq : int Number of sequences to generate n_obs : int Number of observed sequences for training the HMM dna : bool True for DNA sequences, False for protein sequences length : int Target sequence length seed : int, optional Random seed for reproducible results (default: 42) Returns ------- list of str Generated sequences )pbdoc"); // Compare two MSA files m.def("compare", &compare_msa_files, py::arg("reference_file"), py::arg("test_file"), R"pbdoc( Compare two multiple sequence alignments and return SP score. Parameters ---------- reference_file : str Path to reference alignment file test_file : str Path to test alignment file Returns ------- float SP score (0-100) )pbdoc"); // Detailed MSA comparison (POAR recall/precision/F1/TC) m.def("compare_detailed", &compare_detailed_files, py::arg("reference_file"), py::arg("test_file"), py::arg("max_gap_frac") = 0.2f, R"pbdoc( Compare two MSAs returning detailed POAR scores. Parameters ---------- reference_file : str Path to reference alignment file test_file : str Path to test alignment file max_gap_frac : float, optional Max gap fraction for scored columns (default: 0.2 for bali_score compat). Use -1.0 to score all columns. Returns ------- dict Keys: recall, precision, f1, tc, ref_pairs, test_pairs, common_pairs )pbdoc"); // Detailed MSA comparison with explicit column mask m.def("compare_detailed_with_mask", &compare_detailed_with_mask_files, py::arg("reference_file"), py::arg("test_file"), py::arg("column_mask"), R"pbdoc( Compare two MSAs with an explicit column mask. Parameters ---------- reference_file : str Path to reference alignment file test_file : str Path to test alignment file column_mask : list of int Binary mask (0/1) for each column in the reference alignment. Only columns with mask=1 are scored for recall/TC. Returns ------- dict Keys: recall, precision, f1, tc, ref_pairs, test_pairs, common_pairs )pbdoc"); // Align file to file (preserves sequence names/metadata) m.def("align_file_to_file", &align_file_to_file, py::arg("input_file"), py::arg("output_file"), py::arg("format") = "fasta", py::arg("seq_type") = KALIGN_TYPE_UNDEFINED, py::arg("gap_open") = -1.0f, py::arg("gap_extend") = -1.0f, py::arg("terminal_gap_extend") = -1.0f, py::arg("n_threads") = 1, py::arg("refine") = KALIGN_REFINE_NONE, py::arg("adaptive_budget") = 0, py::arg("ensemble") = 0, py::arg("ensemble_seed") = (uint64_t)42, py::arg("dist_scale") = 0.0f, py::arg("vsm_amax") = -1.0f, py::arg("min_support") = 0, py::arg("realign") = 0, py::arg("save_poar") = "", py::arg("load_poar") = "", py::arg("seq_weights") = -1.0f, py::arg("consistency_anchors") = 0, py::arg("consistency_weight") = 2.0f, R"pbdoc( Align sequences from input file and write to output file. Unlike align_from_file, this preserves all sequence metadata (names, descriptions) which is required for MSA comparison. Parameters ---------- input_file : str Path to input sequence file output_file : str Path to output alignment file format : str, optional Output format: "fasta", "msf", "clu" (default: "fasta") seq_type : int, optional Sequence type (default: auto-detect) gap_open : float, optional Gap opening penalty gap_extend : float, optional Gap extension penalty terminal_gap_extend : float, optional Terminal gap extension penalty n_threads : int, optional Number of threads (default: 1) )pbdoc"); // Constants for sequence types m.attr("DNA") = KALIGN_TYPE_DNA; m.attr("DNA_INTERNAL") = KALIGN_TYPE_DNA_INTERNAL; m.attr("RNA") = KALIGN_TYPE_RNA; m.attr("PROTEIN") = KALIGN_TYPE_PROTEIN; m.attr("PROTEIN_PFASUM43") = KALIGN_TYPE_PROTEIN_PFASUM43; m.attr("PROTEIN_PFASUM60") = KALIGN_TYPE_PROTEIN_PFASUM60; m.attr("PROTEIN_PFASUM_AUTO") = KALIGN_TYPE_PROTEIN_PFASUM_AUTO; m.attr("PROTEIN_DIVERGENT") = KALIGN_TYPE_PROTEIN_DIVERGENT; m.attr("AUTO") = KALIGN_TYPE_UNDEFINED; // Constants for refinement modes m.attr("REFINE_NONE") = KALIGN_REFINE_NONE; m.attr("REFINE_ALL") = KALIGN_REFINE_ALL; m.attr("REFINE_CONFIDENT") = KALIGN_REFINE_CONFIDENT; m.attr("REFINE_INLINE") = KALIGN_REFINE_INLINE; }kalign-3.5.1/python-kalign/cli.py000066400000000000000000000170151515023132300166710ustar00rootroot00000000000000""" Command-line interface for the Python Kalign package. This CLI uses the compiled Python extension module shipped with the package instead of shelling out to a separately-installed `kalign` binary. Installed as ``kalign-py`` so it does not shadow the C binary on PATH. """ from __future__ import annotations import argparse import sys import tempfile from importlib.metadata import PackageNotFoundError from importlib.metadata import version as dist_version from pathlib import Path from typing import Optional def _resolve_version() -> str: # kalign-test is the name of the test distribution, which may be installed in test environments. If it's present, use its version; otherwise, fall back to the main kalign distribution. If neither is found, try to import __version__ from the package, and if that fails, return "unknown". for dist_name in ("kalign-python",): try: return dist_version(dist_name) except PackageNotFoundError: continue try: from . import __version__ return __version__ except Exception: return "unknown" def _build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( prog="kalign-py", description="Multiple sequence alignment via the Kalign Python package", ) parser.add_argument( "-i", "--input", required=True, help="Input sequence file path, or '-' to read from stdin.", ) parser.add_argument( "-o", "--output", default="-", help="Output file path, or '-' to write to stdout (default).", ) parser.add_argument( "--format", default="fasta", help="Output format: fasta, clustal, stockholm, phylip (default: fasta).", ) parser.add_argument( "--type", default="auto", dest="seq_type", help="Sequence type: auto, dna, rna, internal, protein, divergent (default: auto).", ) parser.add_argument( "--gpo", type=float, default=None, help="Gap open penalty (default: Kalign internal defaults).", ) parser.add_argument( "--gpe", type=float, default=None, help="Gap extension penalty (default: Kalign internal defaults).", ) parser.add_argument( "--tgpe", type=float, default=None, help="Terminal gap extension penalty (default: Kalign internal defaults).", ) parser.add_argument( "-n", "--nthreads", type=int, default=1, help="Number of threads to use (default: 1).", ) parser.add_argument( "--refine", default="confident", help="Refinement mode: none, all, confident (default: confident).", ) parser.add_argument( "--adaptive-budget", action="store_true", default=False, help="Scale refinement trial count by uncertainty.", ) ens = parser.add_argument_group( "ensemble options", "These options only take effect when --ensemble is used.", ) ens.add_argument( "--ensemble", type=int, default=0, help="Number of ensemble runs (default: 0 = off). Try 3-5 for better accuracy.", ) ens.add_argument( "--ensemble-seed", type=int, default=42, help="RNG seed for ensemble (default: 42).", ) ens.add_argument( "--min-support", type=int, default=0, help="Explicit consensus threshold (default: 0 = auto).", ) ens.add_argument( "--save-poar", default=None, help="Save POAR consensus table to file for later re-thresholding.", ) ens.add_argument( "--load-poar", default=None, help="Load POAR consensus table from file (skip alignment, just re-threshold).", ) adv = parser.add_argument_group("advanced options") adv.add_argument( "--dist-scale", type=float, default=0.0, help="Distance scaling parameter (default: 0.0).", ) adv.add_argument( "--vsm-amax", type=float, default=None, help="Variable Scoring Matrix a_max (default: Kalign internal defaults).", ) adv.add_argument( "--realign", type=int, default=0, help="Realignment iterations (default: 0 = off).", ) parser.add_argument( "-V", "--version", action="version", version=f"%(prog)s {_resolve_version()}", help="Print version and exit", ) return parser def _write_stdout(names: list[str], sequences: list[str], fmt: str) -> None: import kalign fmt_lower = fmt.lower() if fmt_lower in {"fasta", "fa"}: kalign.io.write_fasta(sequences, sys.stdout, ids=names) return if fmt_lower in {"clustal", "aln"}: kalign.io.write_clustal(sequences, sys.stdout, ids=names) return if fmt_lower in {"stockholm", "sto"}: kalign.io.write_stockholm(sequences, sys.stdout, ids=names) return if fmt_lower in {"phylip", "phy"}: kalign.io.write_phylip(sequences, sys.stdout, ids=names) return raise ValueError( f"Invalid format: {fmt}. Must be one of: fasta, clustal, stockholm, phylip" ) def main(argv: Optional[list[str]] = None) -> int: parser = _build_parser() args = parser.parse_args(argv) import kalign input_path = args.input tmp_path: Optional[Path] = None if input_path == "-": with tempfile.NamedTemporaryFile( prefix="kalign-", suffix=".fa", delete=False ) as tmp: tmp.write(sys.stdin.buffer.read()) tmp_path = Path(tmp.name) input_path = str(tmp_path) try: kwargs = dict( seq_type=args.seq_type, gap_open=args.gpo, gap_extend=args.gpe, terminal_gap_extend=args.tgpe, n_threads=args.nthreads, refine=args.refine, adaptive_budget=args.adaptive_budget, ensemble=args.ensemble, ensemble_seed=args.ensemble_seed, min_support=args.min_support, realign=args.realign, dist_scale=args.dist_scale, ) if args.vsm_amax is not None: kwargs["vsm_amax"] = args.vsm_amax if args.save_poar is not None: kwargs["save_poar"] = args.save_poar if args.load_poar is not None: kwargs["load_poar"] = args.load_poar result = kalign.align_from_file(input_path, **kwargs) # Pass confidence data to Stockholm writer when available write_kwargs = dict( format=args.format, ids=result.names, ) if result.column_confidence is not None: write_kwargs["column_confidence"] = result.column_confidence if result.residue_confidence is not None: write_kwargs["residue_confidence"] = result.residue_confidence if args.output == "-": _write_stdout(result.names, result.sequences, args.format) else: kalign.write_alignment( result.sequences, args.output, **write_kwargs, ) return 0 except KeyboardInterrupt: return 130 except Exception as exc: print(f"kalign-py: error: {exc}", file=sys.stderr) return 2 finally: if tmp_path is not None: try: tmp_path.unlink() except OSError: pass if __name__ == "__main__": raise SystemExit(main()) kalign-3.5.1/python-kalign/io.py000066400000000000000000000301531515023132300165270ustar00rootroot00000000000000""" I/O helper functions for reading and writing sequence alignments. This module provides convenient functions for reading sequences from files and writing alignments in various formats, with optional Biopython integration. """ import os from pathlib import Path from typing import List, Optional, TextIO, Tuple, Union def read_fasta(path: Union[str, Path]) -> List[str]: """ Read FASTA file and return sequences as list of strings. Parameters ---------- path : str or Path Path to FASTA file Returns ------- list of str List of sequences (without headers) Raises ------ ImportError If Biopython is not installed FileNotFoundError If file doesn't exist Examples -------- >>> sequences = kalign.io.read_fasta("sequences.fasta") >>> aligned = kalign.align(sequences) """ try: from Bio import SeqIO except ImportError as e: raise ImportError( "Biopython required for FASTA I/O. Run: pip install kalign-python[io]" ) from e path = Path(path) if not path.exists(): raise FileNotFoundError(f"File not found: {path}") with open(path, "r") as handle: return [str(record.seq) for record in SeqIO.parse(handle, "fasta")] def read_sequences( path: Union[str, Path], format: str = "auto" ) -> Tuple[List[str], List[str]]: """ Read sequences from file and return sequences with their IDs. Parameters ---------- path : str or Path Path to sequence file format : str, optional File format. Options: "auto", "fasta", "genbank", "embl", "swiss". Default "auto" attempts to detect format from file extension. Returns ------- sequences : list of str List of sequences ids : list of str List of sequence IDs Raises ------ ImportError If Biopython is not installed FileNotFoundError If file doesn't exist ValueError If format is unsupported or auto-detection fails Examples -------- >>> sequences, ids = kalign.io.read_sequences("data.fasta") >>> aligned = kalign.align(sequences, fmt="biopython", ids=ids) """ try: from Bio import SeqIO except ImportError as e: raise ImportError( "Biopython required for sequence I/O. Run: pip install kalign-python[io]" ) from e path = Path(path) if not path.exists(): raise FileNotFoundError(f"File not found: {path}") # Auto-detect format from extension if format == "auto": ext = path.suffix.lower() format_map = { ".fasta": "fasta", ".fa": "fasta", ".fas": "fasta", ".fna": "fasta", ".ffn": "fasta", ".faa": "fasta", ".gb": "genbank", ".gbk": "genbank", ".embl": "embl", ".swiss": "swiss-prot", } format = format_map.get(ext, "fasta") # Default to FASTA try: with open(path, "r") as handle: records = list(SeqIO.parse(handle, format)) sequences = [str(record.seq) for record in records] ids = [record.id for record in records] return sequences, ids except Exception as e: raise ValueError(f"Failed to parse file as {format}: {e}") def write_fasta( alignment: List[str], path: Union[str, Path, TextIO], ids: Optional[List[str]] = None, line_length: int = 80, ) -> None: """ Write aligned sequences to FASTA format. This function doesn't require Biopython and is used as the default writer for FASTA format. Parameters ---------- alignment : list of str List of aligned sequences path : str, Path, or file-like object Output path or file handle ids : list of str, optional Sequence IDs. If None, generates seq0, seq1, etc. line_length : int, optional Maximum line length for sequence lines (default: 80) Examples -------- >>> aligned = kalign.align(sequences) >>> kalign.io.write_fasta(aligned, "output.fasta", ids=["seq1", "seq2"]) """ if not alignment: raise ValueError("Empty alignment provided") if ids is None: ids = [f"seq{i}" for i in range(len(alignment))] elif len(ids) != len(alignment): raise ValueError( f"Number of IDs ({len(ids)}) must match alignment length ({len(alignment)})" ) def write_to_handle(handle): for seq_id, seq in zip(ids, alignment): handle.write(f">{seq_id}\n") # Write sequence with line wrapping for i in range(0, len(seq), line_length): handle.write(seq[i : i + line_length] + "\n") if hasattr(path, "write"): # File-like object write_to_handle(path) else: # File path with open(path, "w") as handle: write_to_handle(handle) def write_clustal( alignment: List[str], path: Union[str, Path, TextIO], ids: Optional[List[str]] = None, ) -> None: """ Write aligned sequences to Clustal format. Parameters ---------- alignment : list of str List of aligned sequences path : str, Path, or file-like object Output path or file handle ids : list of str, optional Sequence IDs. If None, generates seq0, seq1, etc. Examples -------- >>> aligned = kalign.align(sequences) >>> kalign.io.write_clustal(aligned, "output.aln") """ try: from Bio import AlignIO from Bio.Align import MultipleSeqAlignment from Bio.Seq import Seq from Bio.SeqRecord import SeqRecord except ImportError as e: raise ImportError( "Biopython required for Clustal I/O. Run: pip install kalign-python[io]" ) from e if not alignment: raise ValueError("Empty alignment provided") if ids is None: ids = [f"seq{i}" for i in range(len(alignment))] elif len(ids) != len(alignment): raise ValueError( f"Number of IDs ({len(ids)}) must match alignment length ({len(alignment)})" ) # Create Biopython alignment object records = [SeqRecord(Seq(seq), id=seq_id) for seq, seq_id in zip(alignment, ids)] msa = MultipleSeqAlignment(records) if hasattr(path, "write"): # File-like object AlignIO.write(msa, path, "clustal") else: # File path with open(path, "w") as handle: AlignIO.write(msa, handle, "clustal") def _conf_to_pp_char(conf: float) -> str: """Convert a confidence value [0..1] to HMMER-style PP character.""" if conf >= 0.95: return "*" return str(int(conf * 10)) def write_stockholm( alignment: List[str], path: Union[str, Path, TextIO], ids: Optional[List[str]] = None, column_confidence: Optional[List[float]] = None, residue_confidence: Optional[List[List[float]]] = None, ) -> None: """ Write aligned sequences to Stockholm format. When confidence data is provided (from ensemble alignment), emits ``#=GR PP`` lines (per-residue) and ``#=GC PP_cons`` line (per-column) using HMMER-style PP encoding. Parameters ---------- alignment : list of str List of aligned sequences path : str, Path, or file-like object Output path or file handle ids : list of str, optional Sequence IDs. If None, generates seq0, seq1, etc. column_confidence : list of float, optional Per-column confidence values [0..1]. Emitted as ``#=GC PP_cons``. residue_confidence : list of list of float, optional Per-residue confidence values [0..1]. Emitted as ``#=GR PP``. Examples -------- >>> aligned = kalign.align(sequences) >>> kalign.io.write_stockholm(aligned, "output.sto") """ if not alignment: raise ValueError("Empty alignment provided") if ids is None: ids = [f"seq{i}" for i in range(len(alignment))] elif len(ids) != len(alignment): raise ValueError( f"Number of IDs ({len(ids)}) must match alignment length ({len(alignment)})" ) has_confidence = residue_confidence is not None or column_confidence is not None if has_confidence: # Write Stockholm manually to include PP annotations def write_to_handle(handle): handle.write("# STOCKHOLM 1.0\n") # Find max ID length for padding max_id = max(len(i) for i in ids) pp_label_len = max(max_id, len("PP_cons")) for idx, (seq_id, seq) in enumerate(zip(ids, alignment)): handle.write(f"{seq_id:<{max_id}} {seq}\n") # Per-residue confidence if residue_confidence is not None and idx < len(residue_confidence): rc = residue_confidence[idx] pp = [] for ch, conf in zip(seq, rc): if ch == "-" or ch == ".": pp.append(".") else: pp.append(_conf_to_pp_char(conf)) pp_str = "".join(pp) handle.write(f"#=GR {seq_id:<{max_id}} PP {pp_str}\n") # Per-column confidence if column_confidence is not None: pp_cons = "".join(_conf_to_pp_char(c) for c in column_confidence) handle.write(f"#=GC {'PP_cons':<{pp_label_len}} {pp_cons}\n") handle.write("//\n") if hasattr(path, "write"): write_to_handle(path) else: with open(path, "w") as handle: write_to_handle(handle) else: # No confidence data: use Biopython for standard Stockholm output try: from Bio import AlignIO from Bio.Align import MultipleSeqAlignment from Bio.Seq import Seq from Bio.SeqRecord import SeqRecord except ImportError as e: raise ImportError( "Biopython required for Stockholm I/O. Run: pip install kalign-python[io]" ) from e records = [ SeqRecord(Seq(seq), id=seq_id) for seq, seq_id in zip(alignment, ids) ] msa = MultipleSeqAlignment(records) if hasattr(path, "write"): AlignIO.write(msa, path, "stockholm") else: with open(path, "w") as handle: AlignIO.write(msa, handle, "stockholm") def write_phylip( alignment: List[str], path: Union[str, Path, TextIO], ids: Optional[List[str]] = None, interleaved: bool = False, ) -> None: """ Write aligned sequences to PHYLIP format. Parameters ---------- alignment : list of str List of aligned sequences path : str, Path, or file-like object Output path or file handle ids : list of str, optional Sequence IDs. If None, generates seq0, seq1, etc. interleaved : bool, optional Whether to use interleaved format (default: False, sequential) Examples -------- >>> aligned = kalign.align(sequences) >>> kalign.io.write_phylip(aligned, "output.phy") """ try: from Bio import AlignIO from Bio.Align import MultipleSeqAlignment from Bio.Seq import Seq from Bio.SeqRecord import SeqRecord except ImportError as e: raise ImportError( "Biopython required for PHYLIP I/O. Run: pip install kalign-python[io]" ) from e if not alignment: raise ValueError("Empty alignment provided") if ids is None: ids = [f"seq{i}" for i in range(len(alignment))] elif len(ids) != len(alignment): raise ValueError( f"Number of IDs ({len(ids)}) must match alignment length ({len(alignment)})" ) # Create Biopython alignment object records = [SeqRecord(Seq(seq), id=seq_id) for seq, seq_id in zip(alignment, ids)] msa = MultipleSeqAlignment(records) format_name = "phylip" if interleaved else "phylip-sequential" if hasattr(path, "write"): # File-like object AlignIO.write(msa, path, format_name) else: # File path with open(path, "w") as handle: AlignIO.write(msa, handle, format_name) kalign-3.5.1/python-kalign/py.typed000066400000000000000000000000001515023132300172310ustar00rootroot00000000000000kalign-3.5.1/python-kalign/utils.py000066400000000000000000000220631515023132300172610ustar00rootroot00000000000000""" Utility functions for working with multiple sequence alignments. This module provides helpful utilities for analyzing and manipulating alignments produced by Kalign. """ from collections import Counter from typing import Dict, List, Optional, Tuple import numpy as np def to_array(alignment: List[str]) -> np.ndarray: """ Convert alignment to NumPy character array. Parameters ---------- alignment : list of str List of aligned sequences Returns ------- numpy.ndarray 2D character array with shape (n_sequences, alignment_length) Examples -------- >>> import kalign >>> aligned = kalign.align(["ATCG", "ATCG", "ATGG"]) >>> arr = kalign.utils.to_array(aligned) >>> print(arr.shape) (3, 4) """ if not alignment: raise ValueError("Empty alignment provided") # Verify all sequences have same length lengths = [len(seq) for seq in alignment] if len(set(lengths)) > 1: raise ValueError("All sequences in alignment must have the same length") # Convert to numpy array return np.array([list(seq) for seq in alignment], dtype="U1") def alignment_stats(alignment: List[str]) -> Dict[str, float]: """ Calculate basic statistics for a multiple sequence alignment. Parameters ---------- alignment : list of str List of aligned sequences Returns ------- dict Dictionary containing alignment statistics: - length: alignment length - n_sequences: number of sequences - gap_fraction: fraction of positions that are gaps - conservation: fraction of positions that are fully conserved - identity: average pairwise identity Examples -------- >>> import kalign >>> aligned = kalign.align(["ATCG", "ATCG", "ATGG"]) >>> stats = kalign.utils.alignment_stats(aligned) >>> print(f"Conservation: {stats['conservation']:.2f}") Conservation: 0.75 """ if not alignment: raise ValueError("Empty alignment provided") # Convert to array for easier analysis arr = to_array(alignment) n_sequences, length = arr.shape # Calculate gap fraction n_gaps = np.sum(arr == "-") gap_fraction = n_gaps / (n_sequences * length) # Calculate conservation (fully conserved positions) conserved_positions = 0 for col in range(length): column = arr[:, col] # Remove gaps for conservation calculation non_gap = column[column != "-"] if len(non_gap) > 0 and len(set(non_gap)) == 1: conserved_positions += 1 conservation = conserved_positions / length # Calculate average pairwise identity total_comparisons = 0 total_matches = 0 for i in range(n_sequences): for j in range(i + 1, n_sequences): seq1, seq2 = arr[i], arr[j] # Only compare non-gap positions valid_positions = (seq1 != "-") & (seq2 != "-") if np.sum(valid_positions) > 0: matches = np.sum(seq1[valid_positions] == seq2[valid_positions]) total_matches += matches total_comparisons += np.sum(valid_positions) identity = total_matches / total_comparisons if total_comparisons > 0 else 0.0 return { "length": length, "n_sequences": n_sequences, "gap_fraction": gap_fraction, "conservation": conservation, "identity": identity, } def consensus_sequence(alignment: List[str], threshold: float = 0.5) -> str: """ Generate consensus sequence from alignment. Parameters ---------- alignment : list of str List of aligned sequences threshold : float, optional Minimum fraction of sequences that must have the same character for it to be included in consensus (default: 0.5) Returns ------- str Consensus sequence. Positions where no character meets the threshold are represented as 'N' (nucleotides) or 'X' (amino acids). Examples -------- >>> import kalign >>> aligned = ["ATCG", "ATCG", "ATGG"] >>> consensus = kalign.utils.consensus_sequence(aligned) >>> print(consensus) ATCG """ if not alignment: raise ValueError("Empty alignment provided") if not 0 <= threshold <= 1: raise ValueError("Threshold must be between 0 and 1") arr = to_array(alignment) n_sequences, length = arr.shape consensus = [] # Detect sequence type (crude heuristic) all_chars = set("".join(alignment).upper().replace("-", "")) is_nucleotide = all_chars.issubset(set("ATCGUN")) ambiguous_char = "N" if is_nucleotide else "X" for col in range(length): column = arr[:, col] # Remove gaps for consensus calculation non_gap = column[column != "-"] if len(non_gap) == 0: consensus.append("-") continue # Count character frequencies char_counts = Counter(non_gap) most_common_char, count = char_counts.most_common(1)[0] # Check if most common character meets threshold if count / len(non_gap) >= threshold: consensus.append(most_common_char) else: consensus.append(ambiguous_char) return "".join(consensus) def remove_gap_columns(alignment: List[str], threshold: float = 1.0) -> List[str]: """ Remove columns with gaps from alignment. Parameters ---------- alignment : list of str List of aligned sequences threshold : float, optional Remove columns where fraction of gaps >= threshold (default: 1.0) Default removes only all-gap columns. Returns ------- list of str Alignment with gap columns removed Examples -------- >>> aligned = ["AT-G", "AT-G", "AT-G"] >>> nogaps = kalign.utils.remove_gap_columns(aligned) >>> print(nogaps) ['ATG', 'ATG', 'ATG'] """ if not alignment: raise ValueError("Empty alignment provided") if not 0 <= threshold <= 1: raise ValueError("Threshold must be between 0 and 1") arr = to_array(alignment) n_sequences, length = arr.shape # Identify columns to keep keep_columns = [] for col in range(length): column = arr[:, col] gap_fraction = np.sum(column == "-") / n_sequences if gap_fraction < threshold: keep_columns.append(col) # Extract kept columns if not keep_columns: return [""] * n_sequences # All columns removed filtered_arr = arr[:, keep_columns] return ["".join(seq) for seq in filtered_arr] def pairwise_identity_matrix(alignment: List[str]) -> np.ndarray: """ Calculate pairwise identity matrix for alignment. Parameters ---------- alignment : list of str List of aligned sequences Returns ------- numpy.ndarray Symmetric matrix of pairwise identities (shape: n_sequences x n_sequences) Examples -------- >>> aligned = kalign.align(["ATCG", "ATCG", "ATGG"]) >>> matrix = kalign.utils.pairwise_identity_matrix(aligned) >>> print(matrix[0, 1]) # Identity between first two sequences 1.0 """ if not alignment: raise ValueError("Empty alignment provided") arr = to_array(alignment) n_sequences = arr.shape[0] identity_matrix = np.zeros((n_sequences, n_sequences)) for i in range(n_sequences): identity_matrix[i, i] = 1.0 # Self-identity is always 1 for j in range(i + 1, n_sequences): seq1, seq2 = arr[i], arr[j] # Only compare non-gap positions in both sequences valid_positions = (seq1 != "-") & (seq2 != "-") if np.sum(valid_positions) > 0: matches = np.sum(seq1[valid_positions] == seq2[valid_positions]) identity = matches / np.sum(valid_positions) else: identity = 0.0 identity_matrix[i, j] = identity identity_matrix[j, i] = identity # Symmetric return identity_matrix def trim_alignment( alignment: List[str], start: Optional[int] = None, end: Optional[int] = None ) -> List[str]: """ Trim alignment to specified positions. Parameters ---------- alignment : list of str List of aligned sequences start : int, optional Start position (0-based, inclusive). If None, starts from beginning. end : int, optional End position (0-based, exclusive). If None, goes to end. Returns ------- list of str Trimmed alignment Examples -------- >>> aligned = ["ATCGATCG", "ATCGATCG"] >>> trimmed = kalign.utils.trim_alignment(aligned, start=2, end=6) >>> print(trimmed) ['CGAT', 'CGAT'] """ if not alignment: raise ValueError("Empty alignment provided") length = len(alignment[0]) if start is None: start = 0 if end is None: end = length if start < 0: start = max(0, length + start) if end < 0: end = max(0, length + end) if start >= end: raise ValueError("Start position must be less than end position") return [seq[start:end] for seq in alignment] kalign-3.5.1/scripts/000077500000000000000000000000001515023132300144475ustar00rootroot00000000000000kalign-3.5.1/scripts/balibase_test.org000066400000000000000000001366411515023132300177740ustar00rootroot00000000000000#+TITLE: Test kalign on BAliBASE #+AUTHOR: Timo Lassmann #+EMAIL: timolassmann@icloud.com #+DATE: 2019-04-23 #+LATEX_CLASS: report #+OPTIONS: toc:nil #+OPTIONS: H:4 #+LATEX_CMD: pdflatex * Introduction Let's run kalign on the core BAliBASE test alignments. * Method ** Step 1: install balibase #+BEGIN_SRC sh cd mkdir -p data cd data if [ ! -f BAliBASE_R1-5.tar.gz ]; then wget https://www.lbgi.fr/balibase/BalibaseDownload/BAliBASE_R1-5.tar.gz fi tar -zxvf BAliBASE_R1-5.tar.gz #+END_SRC #+RESULTS: BAliBASE comes with a C program to score alignments. Unfortunately, something is wrong with the bundled expat library. To fix this install expat system and remove the links to the bundled library by editing the makefile: #+BEGIN_EXAMPLE makefile CC = cc CFLAGS = -c -O #-I$(EXPAT_INC) LFLAGS = -O -lm -lexpat #-L$(EXPAT_LIB) -lexpat EXPAT_LIB = expat-1.95.2/lib EXPAT_INC = expat-1.95.2/include #+END_EXAMPLE Also, by default bali_score will use all columns for the TC score. In the original clustal omega paper only core blocks are used to calculate the TC scores supercite:sievers-2014-fast-scalab. To change this modify =bali_score.c= line 104 from: #+BEGIN_EXAMPLE C method='C' #+END_EXAMPLE to: #+BEGIN_EXAMPLE C method='B' #+END_EXAMPLE Then compile: #+BEGIN_SRC sh cd ~/data/bb3_release/bali_score_src make #+END_SRC #+RESULTS: | cc | -c | -O | readxml.c | | | | | | | | cc | -c | -O | init.c | | | | | | | | cc | -c | -O | util.c | | | | | | | | cc | -c | -O | bali_score.c | | | | | | | | cc | -o | bali_score | readxml.o | init.o | util.o | bali_score.o | -O | -lm | -lexpat | ** Step 2: run tests #+BEGIN_SRC sh :session onesh cd ~/data/bb3_release cd .. mkdir -p bb3_release_tmp_aln cd bb3_release_tmp_aln KALIGNOUTDIR=$PWD echo $KALIGNOUTDIR #+END_SRC #+RESULTS: | | | sh-4.4$ sh-4.4$ sh-4.4$ sh-4.4$ sh-4.4$ /home/user/data/bb3_release_tmp_aln | #+BEGIN_SRC sh :session onesh :results raw find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -alnp param_25.txt %s -o %s/%s_%skalign25.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_kalign.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -alnp param_50.txt %s -o %s/%s_%skalign50.msf\n", $1,outdir,a[n-2],a[n-1] }' >> run_kalign.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -alnp param_75.txt %s -o %s/%s_%skalign75.msf\n", $1,outdir,a[n-2],a[n-1] }' >> run_kalign.sh #+END_SRC #+BEGIN_SRC sh :session onesh :results raw find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -alnp testparam %s -o %s/%s_%skalign.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_kalign.sh find ~/data/bb3_release -name "*.tfa" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "clustalo --dealign -i %s --outfmt=msf -o %s/%s_%sclustalo.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_clustalo.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign %s -set 0 -o %s/%s_%skalign_1.msf\n", $1,outdir,a[n-2],a[n-1] ; printf "kalign %s -set 1 -o %s/%s_%skalign_2.msf\n", $1,outdir,a[n-2],a[n-1] ; printf "kalign %s -set 2 -o %s/%s_%skalign_3.msf\n", $1,outdir,a[n-2],a[n-1] ; printf "kalign %s -set 3 -o %s/%s_%skalign_4.msf\n", $1,outdir,a[n-2],a[n-1] ; }' > run_kalign_cmsa.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "cmsa -a %s/%s_%skalign_*.msf -out %s/%s_%skalign_cmsa.msf -f msf \n",outdir,a[n-2],a[n-1],outdir,a[n-2],a[n-1] ; }' > run_cmsa.sh chmod 755 run_kalign_cmsa.sh chmod 755 run_kalign.sh chmod 755 run_clustalo.sh #+END_SRC #+RESULTS: #+BEGIN_SRC sh :session onesh :results raw find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_1.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set1.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_2.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set2.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_3.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set3.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_4.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set4.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_5.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set5.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_cmsa.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_cmsa.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%sclustalo.msf\n", $1,outdir,a[n-2],a[n-1] }' >> alignment_scores.sh chmod 755 alignment_scores.sh #+END_SRC #+RESULTS: run the tests #+BEGIN_SRC sh :session onesh parallel --jobs 5 < ./run_kalign.sh parallel --jobs 5 < ./run_clustalo.sh ./alignment_scores.sh | grep auto > scores2.csv #+END_SRC ** Step 3: plot scores *** Check for dependencies Here I define the list of libraries I'll be using. #+NAME: liblist #+BEGIN_SRC R -n :exports code :results none libraries <- c("tidyverse","ggplot2","stringi","cowplot") #+END_SRC Script to test if libraries are present. #+BEGIN_SRC R -n :tangle test_for_libraries.R :shebang #!/usr/bin/env Rscript :noweb yes :exports code :results none <> Sys.info()["nodename"] for(library in libraries) { f = is.element(library, installed.packages()[,1]) print(paste("Library",library, "is installed?", f)) if(!f) { message("Missing library:",library ) quit(status=1) } } quit(status=0) #+END_SRC #+BEGIN_SRC sh -n :results output :exports both ./test_for_libraries.R #+END_SRC #+RESULTS: : nodename : "work" : [1] "Library tidyverse is installed? TRUE" : [1] "Library ggplot2 is installed? TRUE" : [1] "Library stringi is installed? TRUE" : [1] "Library cowplot is installed? TRUE" install.packages("tidyverse") Code block to load the libraries in R code. #+NAME: Rlibraries #+BEGIN_SRC R -n :exports code :results none :noweb yes <> lapply(libraries, FUN = function(X) { do.call("library", list(X)) }) #+END_SRC *** Plotting functions #+BEGIN_SRC R :session one :results none :export none :noweb yes <> readBaliscores <-function(file,name){ mat <- read.table(file); colnames(mat) <- c("Type","Name","SP","TC") mat$Type <- name mat$Name <- sub(".*/" ,"", mat$Name) mat$Name <- sub("[A-Z,_]*[.]{1}[A-Z]*$" ,"", mat$Name,ignore.case = TRUE) mat <- as.tibble(mat) x = str_split(mat$Name, "_", n = Inf, simplify = TRUE) mat$Group <- x[,1] return(mat) } #+END_SRC #+BEGIN_SRC R :session one :results output graphics :file BalibaseSP_scores.jpeg :exports both :width 160 :height 80 :noweb yes mat <- readBaliscores("scores_kalign_old.csv","kalign old"); mat <- rbind(mat,readBaliscores("scores_kalign_new.csv","kalign new")); mat <- rbind(mat,readBaliscores("scores_kalign_pbil2.csv","kalign pbil 2")); mat <- rbind(mat,readBaliscores("scores_kalign_16seed.csv","kalign 16 seed")); mat <- rbind(mat,readBaliscores("scores_kalign_test.csv","rel")) mat <- rbind(mat,readBaliscores("scores_kalign_optimized.csv","Opt")) ## mat <- rbind(mat,readBaliscores("scores_kalign_3.csv","kalign 3")); ## mata ## <- rbind(mat,readBaliscores("scores_kalign_bibpm.csv","bibpm")); ## mat ## <- rbind(mat,readBaliscores("scores_kalign_bibpm_zero.csv","bibpm_zero")); p1 <- ggplot(mat, aes(Group, SP)) p1 <- p1 + geom_boxplot(aes(colour = Type)) means <- aggregate(SP ~ Type, mat, median) means$SP <- round(means$SP,digits = 4) p2 <- ggplot(mat, aes(Type, SP)) p2 <- p2 + geom_boxplot(aes(colour = Type)) p2 <- p2 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p2 <- p2 + geom_text(data = means, aes(label = SP, y = SP + 0.08)) p3 <- ggplot(mat, aes(Group, TC)) p3 <- p3 + geom_boxplot(aes(colour = Type)) means <- aggregate(TC ~ Type, mat, median) means$TC <- round(means$TC,digits = 4) p4 <- ggplot(mat, aes(Type, TC)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p4 <- p4 + geom_text(data = means, aes(label = TC, y = TnC + 0.08)) p = plot_grid(p1,p2,p3,p4, labels=c("SP", "TC"), ncol = 2, nrow= 2) #+END_SRC #+RESULTS: [[file:BalibaseSP_scores.jpeg]] * Benchmarking Programs to test: #+NAME: Benchprograms | Name | Download | |--------------+------------------------------------------------------------------------------| | Muscle | https://www.drive5.com/muscle/downloads3.8.31/muscle3.8.31_i86linux32.tar.gz | | Clustalomega | http://clustal.org/omega/clustalo-1.2.4-Ubuntu-x86_64 | | q-score | https://www.drive5.com/qscore/qscore_src.tar.gz | | Kalign2 | http://msa.sbc.su.se/downloads/kalign/current.tar.gz | Since the clustal papers provide a great overview of alignment programs I think these two should suffice. Note I am not comparing kalign against consistency based methods as these are a) all more accurate and b) slower. Kalign is targeted at the accurate and fast niche. Benchmarks: #+NAME: Benchmarkdata | Name | Download | |---------------+-------------------------------------------------------------------| | Balibase1-5 | http://www.lbgi.fr/balibase/BalibaseDownload/BAliBASE_R1-5.tar.gz | | Balifam | http://clustal.org/omega/bali3fam-26.tar.gz | | Bralibaseset1 | http://projects.binf.ku.dk/pgardner/bralibase/data-set1.tar.gz | | Bralibaseset2 | http://projects.binf.ku.dk/pgardner/bralibase/data-set2.tar.gz | | HomFam | http://www.clustal.org/omega/homfam-20110613-25.tar.gz | | QuanTest2 | http://bioinf.ucd.ie/quantest2.tar | ** Step one: create test directory and download all data #+BEGIN_SRC bash :exports both :results none cd mkdir -p kalignbenchmark cd kalignbenchmark mkdir -p data mkdir -p programs mkdir -p scratch #+END_SRC *** Download benchmark datasets #+BEGIN_SRC bash -n :results raw :exports both :var tbl=Benchmarkdata :colnames yes cd cd ~/kalignbenchmark/data for idx in ${!tbl[*]}; do #echo ${tbl[$idx]} if [[ ${tbl[$idx]} =~ ^http* ]]; then echo "wget ${tbl[$idx]}" wget ${tbl[$idx]} fi done #+END_SRC inter all data sets #+BEGIN_SRC bash :results none :exports code cd cd ~/kalignbenchmark/data mkdir -p homfam mv homfam-20110613-25.tar.gz homfam cd homfam tar -zxvf homfam-20110613-25.tar.gz cd ~/kalignbenchmark/data for filename in *.tar.gz; do tar -zxvf $filename done tar -xvf quantest2.tar #+END_SRC *** Compile baliscore program and place in program directory #+BEGIN_SRC bash cd ~/kalignbenchmark/data/bb3_release/bali_score_src gcc *.c -lm -lexpat -o bali_score cp bali_score ~/kalignbenchmark/programs #+END_SRC #+RESULTS: *** Download programs #+BEGIN_SRC bash -n :results none :exports none :var tbl=Benchprograms :colnames yes cd cd ~/kalignbenchmark/programs for idx in ${!tbl[*]}; do #echo ${tbl[$idx]} if [[ ${tbl[$idx]} =~ ^http* ]]; then echo "wget ${tbl[$idx]}" wget ${tbl[$idx]} fi done chmod 755 clustalo-1.2.4-Ubuntu-x86_64 tar -zxvf muscle3.8.31_i86linux32.tar.gz tar -zxvf qscore_src.tar.gz mkdir -p kalign2_src cd kalign2_src mv ../current.tar.gz . tar -zxvf current.tar.gz ./configure make cp kalign ../kalign2 #+END_SRC *** Compile q-score NOTE: this is manual! Add: #+BEGIN_EXAMPLE C #include #+END_EXAMPLE to qscore header: =qscore.h= then: #+BEGIN_EXAMPLE bash make #+END_EXAMPLE ** Step 2: test if all programs run Let's make sure individual programs run on all the test sets. small code chunk to set path: #+NAME: path #+BEGIN_SRC bash :results none :exports code :noweb yes export PATH=~/kalignbenchmark/programs:$PATH #+END_SRC *** muscle Can I run muscle? #+BEGIN_SRC bash :results value :exports code :noweb yes <> muscle3.8.31_i86linux32 -version #+END_SRC #+RESULTS: : MUSCLE v3.8.31 by Robert C. Edgar Let's try on a balibase case: #+BEGIN_SRC bash :results raw :exports code :noweb yes <> IN=~/kalignbenchmark/data/bb3_release/RV11/BB11002.tfa REF=~/kalignbenchmark/data/bb3_release/RV11/BB11002.msf OUT=~/kalignbenchmark/scratch/BB11002_muscle.msf muscle3.8.31_i86linux32 -msf -in $IN -out $OUT bali_score $REF $OUT #+END_SRC Let's try on a balifam #+BEGIN_SRC bash :results raw :exports both :noweb yes <> IN=~/kalignbenchmark/data/BB20021-package.vie ADD=~/kalignbenchmark/data/bb3_release/RV20/BB20021.tfa REF=~/kalignbenchmark/data/bb3_release/RV20/BB20021.msf OUT=~/kalignbenchmark/scratch/BB20021_muscle.fa cd ~/kalignbenchmark/scratch cat $IN $ADD > test.fa time muscle3.8.31_i86linux32 -maxiters 2 -in test.fa -out $OUT kalign $REF -r -f fasta -o ref.fa qscore -test $OUT -ref ref.fa #+END_SRC #+RESULTS: [2019-06-11 20:55:42] : LOG : kalign -r -f fasta -o ref.fa /home/user/kalignbenchmark/data/bb3_release/RV20/BB20021.msf [2019-06-11 20:55:42] : LOG : Detected protein sequences. [2019-06-11 20:55:42] : LOG : Detected: 53 sequences. [2019-06-11 20:55:42] : LOG : Output in fasta format *** clustalo Can I run muscle? #+BEGIN_SRC bash :results value :exports code :noweb yes <> clustalo-1.2.4-Ubuntu-x86_64 --version #+END_SRC Let's try on a balibase case: #+BEGIN_SRC bash :results raw :exports code :noweb yes <> IN=~/kalignbenchmark/data/bb3_release/RV11/BB11002.tfa REF=~/kalignbenchmark/data/bb3_release/RV11/BB11002.msf OUT=~/kalignbenchmark/scratch/BB11002_clustalo.msf clustalo-1.2.4-Ubuntu-x86_64 --outfmt=msf --in $IN --out $OUT bali_score $REF $OUT #+END_SRC #+RESULTS: Using GCG format reference alignment Comparing test alignment in /home/user/kalignbenchmark/scratch/BB11002_clustalo.msf with reference alignment in /home/user/kalignbenchmark/data/bb3_release/RV11/BB11002.msf SP score= 0.483 TC score= 0.000 auto /home/user/kalignbenchmark/scratch/BB11002_clustalo.msf 0.483 0.000 ** Step 3: scripts to run benchmarks #+NAME: scratchdir #+BEGIN_SRC bash :results none :exports code :noweb yes SCRATCHDIR="~/kalignbenchmark/scratch" #+END_SRC *** Balibase #+BEGIN_SRC bash -n :tangle gen_run_balibase.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle gen_run_balibase.sh :noweb yes :exports code :results none :noweb yes DIR=`pwd` function usage() { printf "This script will generate scripts to run kalign, clustal omega and muscle on the balibase MSA benchmark data set.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done printf "Generating kalign run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.tfa" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -i %s -f msf -o %s/%s_%s_kalign.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_kalign.sh chmod 755 run_kalign.sh printf "Generating muscle run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.tfa" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "muscle3.8.31_i86linux32 -msf -in %s -out %s/%s_%s_muscle.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_muscle.sh chmod 755 run_muscle.sh printf "Generating clustalo run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.tfa" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "clustalo-1.2.4-Ubuntu-x86_64 --outfmt=msf --in %s --out %s/%s_%s_clustalo.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_clustalo.sh chmod 755 run_clustalo.sh printf "Generating kalign scoring run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.xml" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_kalign.msf | grep auto\n", $1,outdir,a[n-2],a[n-1] }' > score_bb3_kalign.sh chmod 755 score_bb3_kalign.sh printf "Generating muscle scoring run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.xml" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_muscle.msf | grep auto\n", $1,outdir,a[n-2],a[n-1] }' > score_bb3_muscle.sh chmod 755 score_bb3_muscle.sh printf "Generating clustalo scoring run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.xml" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_clustalo.msf | grep auto\n", $1,outdir,a[n-2],a[n-1] }' > score_bb3_clustalo.sh chmod 755 score_bb3_clustalo.sh #+END_SRC **** Kick off jobs #+BEGIN_SRC bash -n :tangle run_balibase.sh :noweb yes :exports code :results none :noweb yes :shebang #!/usr/bin/env bash <> ./run_muscle.sh ./run_kalign.sh ./run_clustalo.sh #+END_SRC **** score alignments #+BEGIN_SRC bash ./score_bb3_kalign.sh > scores_kalign.csv ./score_bb3_muscle.sh > scores_muscle.csv ./score_bb3_clustalo.sh > scores_clustalo.csv #+END_SRC #+RESULTS: **** Plot #+BEGIN_SRC R :session one :results none :export none :noweb yes <> readBaliscores <-function(file,name){ mat <- read.table(file); colnames(mat) <- c("Type","Name","SP","TC") mat$Type <- name mat$Name <- sub(".*/" ,"", mat$Name) mat$Name <- sub("[A-Z,_]*[.]{1}[A-Z]*$" ,"", mat$Name,ignore.case = TRUE) mat <- as.tibble(mat) x = str_split(mat$Name, "_", n = Inf, simplify = TRUE) mat$Group <- x[,1] return(mat) } #+END_SRC #+BEGIN_SRC R :session one :results output graphics :file Balibase_scores.jpeg :exports both :noweb yes mat <- readBaliscores("scores_kalign.csv","kalign"); mat <- rbind(mat,readBaliscores("scores_muscle.csv","muscle")); mat <- rbind(mat,readBaliscores("scores_clustalo.csv","clustalo")); ## mat <- rbind(mat,readBaliscores("scores_kalign_3.csv","kalign 3")); ## mata ## <- rbind(mat,readBaliscores("scores_kalign_bibpm.csv","bibpm")); ## mat ## <- rbind(mat,readBaliscores("scores_kalign_bibpm_zero.csv","bibpm_zero")); p1 <- ggplot(mat, aes(Group, SP)) p1 <- p1 + geom_boxplot(aes(colour = Type)) means <- aggregate(SP ~ Type, mat, median) means$SP <- round(means$SP,digits = 4) p2 <- ggplot(mat, aes(Type, SP)) p2 <- p2 + geom_boxplot(aes(colour = Type)) p2 <- p2 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p2 <- p2 + geom_text(data = means, aes(label = SP, y = SP + 0.08)) p3 <- ggplot(mat, aes(Group, TC)) p3 <- p3 + geom_boxplot(aes(colour = Type)) means <- aggregate(TC ~ Type, mat, median) means$TC <- round(means$TC,digits = 4) p4 <- ggplot(mat, aes(Type, TC)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p4 <- p4 + geom_text(data = means, aes(label = TC, y = TC + 0.08)) p1 <- p1 + theme(legend.position="none") p2 <- p2 + theme(legend.position="none") p3 <- p3 + theme(legend.position="none") p4 <- p4 + theme(legend.position="none") p = plot_grid(p1,p2,p3,p4, labels=c("SP", "TC"), ncol = 2, nrow= 2) ggsave("Balibase_scores.jpeg", p,width = 16, height = 12, dpi = 300, units = c( "cm")) p1 <- ggplot(mat, aes(Group, SP)) p1 <- p1 + geom_boxplot(aes(colour = Type)) p1 <- p1 + scale_color_discrete(name = "Program") p1 <- p1 + theme(legend.position = c(0.25, 0.15),legend.text=element_text(size=16), legend.direction = "horizontal") p1 <- p1 + xlab(label="") p1 <- p1 + theme(plot.margin = margin(t = 0, b = -0.4, unit = "cm"))# unit(c(1,2,3,4), "cm")) # t = 0, r = 0, b = 0, l = 0 ("left", "right", "bottom", "top") ggsave("Figure1.jpeg",p1,width = 16, height = 12, dpi = 300, units = c( "cm")) #+END_SRC #+RESULTS: [[file:Balibase_scores.jpeg]] *** Bralibase #+BEGIN_SRC bash -n :tangle gen_run_bralibase.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle gen_run_bralibase.sh :noweb yes :exports code :results none :noweb yes DIR=`pwd` function usage() { printf "This script will generate scripts to run kalign, clustal omega and muscle on the balibase MSA benchmark data set.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*_test.fa" -exec rm -rf {} \; printf "Generate commands to reformat the reference alignments\n\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.fa" -o -name '*.fasta' | grep structural | awk -v outdir="$SCRATCHDIR" '{printf "kalign %s --rename -reformat -f msf -o %s.msf\n", $1,$1 }' > run_kalign_reformat.sh find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.fa" -o -name '*.fasta' | grep unaligned | awk -v outdir="$SCRATCHDIR" '{printf "kalign %s --rename -reformat -f fasta -o %s_test.fa\n", $1,$1 }' >> run_kalign_reformat.sh chmod 755 run_kalign_reformat.sh ./run_kalign_reformat.sh printf "Generating kalign run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*_test.fa" | grep unaligned | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign %s -f msf -o %s/%s_%s_%s_kalign.msf\n", $1,outdir,a[n-4],a[n-3],a[n-2] }' > run_kalign_bralibase.sh chmod 755 run_kalign_bralibase.sh printf "Generating muscle run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*_test.fa" -o -name '*.fasta' | grep unaligned | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "muscle3.8.31_i86linux32 -msf -in %s -out %s/%s_%s_%s_muscle.msf\n", $1,outdir,a[n-4],a[n-3],a[n-2] }' > run_muscle_bralibase.sh chmod 755 run_muscle_bralibase.sh printf "Generating clustalo run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*_test.fa" -o -name '*.fasta' | grep unaligned | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "clustalo-1.2.4-Ubuntu-x86_64 --outfmt=msf --in %s --force --out %s/%s_%s_%s_clustalo.msf\n", $1,outdir,a[n-4],a[n-3],a[n-2] }' > run_clustalo_bralibase.sh chmod 755 run_clustalo_bralibase.sh printf "Generating kalign scoring run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.msf" | grep structural | awk -v outdir="$SCRATCHDIR" '{name=$1; gsub(/structural/, "unaligned"); n=split ($1,a,/[\/,.]/); printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_%s_kalign.msf | grep auto\n", name,outdir,a[n-4],a[n-3],a[n-2] }' > score_kalign_bralibase.sh chmod 755 score_kalign_bralibase.sh printf "Generating muscle scoring run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.msf" | grep structural | awk -v outdir="$SCRATCHDIR" '{name=$1; gsub(/structural/, "unaligned"); n=split ($1,a,/[\/,.]/); printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%s_%s_muscle.msf | grep auto\n", name,outdir,a[n-4],a[n-3],a[n-2] }' > score_muscle_bralibase.sh chmod 755 score_muscle_bralibase.sh printf "Generating clustalo scoring run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.msf" | grep structural | awk -v outdir="$SCRATCHDIR" '{name=$1; gsub(/structural/, "unaligned"); n=split ($1,a,/[\/,.]/); printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%s_%s_clustalo.msf | grep auto\n", name,outdir,a[n-4],a[n-3],a[n-2] }' > score_clustalo_bralibase.sh chmod 755 score_clustalo_bralibase.sh #+END_SRC **** Kick off jobs #+BEGIN_SRC bash -n :tangle run_bralibase.sh :noweb yes :exports code :results none :noweb yes :shebang #!/usr/bin/env bash <> ./run_kalign_bralibase.sh ./run_muscle_bralibase.sh ./run_clustalo_bralibase.sh #+END_SRC **** score alignments #+BEGIN_SRC bash ./score_kalign_bralibase.sh > scores_kalign_bralibase.csv ./score_muscle_bralibase.sh > scores_muscle_bralibase.csv ./score_clustalo_bralibase.sh > scores_clustalo_bralibase.csv #+END_SRC #+RESULTS: **** Plot #+BEGIN_SRC R :session one :results none :export none :noweb yes <> readBaliscores <-function(file,name){ mat <- read.table(file); colnames(mat) <- c("Type","Name","SP","TC") mat$Type <- name mat$Name <- sub(".*/" ,"", mat$Name) mat$Name <- sub("[A-Z,_]*[.]{1}[A-Z]*$" ,"", mat$Name,ignore.case = TRUE) mat <- as.tibble(mat) x = str_split(mat$Name, "_", n = Inf, simplify = TRUE) mat$Group <- x[,1] return(mat) } #+END_SRC #+BEGIN_SRC R :session one :results output graphics :file Bralibase_scores.jpeg :exports both :noweb yes mat <- readBaliscores("scores_kalign_bralibase.csv","kalign"); mat <- rbind(mat,readBaliscores("scores_muscle_bralibase.csv","muscle")); mat <- rbind(mat,readBaliscores("scores_clustalo_bralibase.csv","clustalo")); ## mat <- rbind(mat,readBaliscores("scores_kalign_3.csv","kalign 3")); ## mata ## <- rbind(mat,readBaliscores("scores_kalign_bibpm.csv","bibpm")); ## mat ## <- rbind(mat,readBaliscores("scores_kalign_bibpm_zero.csv","bibpm_zero")); p1 <- ggplot(mat, aes(Group, SP)) p1 <- p1 + geom_boxplot(aes(colour = Type)) means <- aggregate(SP ~ Type, mat, median) means$SP <- round(means$SP,digits = 4) p2 <- ggplot(mat, aes(Type, SP)) p2 <- p2 + geom_boxplot(aes(colour = Type)) p2 <- p2 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p2 <- p2 + geom_text(data = means, aes(label = SP, y = SP + 0.08)) p3 <- ggplot(mat, aes(Group, TC)) p3 <- p3 + geom_boxplot(aes(colour = Type)) means <- aggregate(TC ~ Type, mat, median) means$TC <- round(means$TC,digits = 4) p4 <- ggplot(mat, aes(Type, TC)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p4 <- p4 + geom_text(data = means, aes(label = TC, y = TC + 0.08)) p1 <- p1 + theme(legend.position="none") p2 <- p2 + theme(legend.position="none") p3 <- p3 + theme(legend.position="none") p4 <- p4 + theme(legend.position="none") p = plot_grid(p1,p2,p3,p4, labels=c("SP", "TC"), ncol = 2, nrow= 2) ggsave("Bralibase_scores.jpeg", p,width = 16, height = 12, dpi = 300, units = c( "cm")) p1 <- ggplot(mat, aes(Group, SP)) p1 <- p1 + geom_boxplot(aes(colour = Type)) p1 <- p1 + scale_color_discrete(name = "Program") p1 <- p1 + theme(legend.position = c(0.25, 0.15),legend.text=element_text(size=16), legend.direction = "horizontal") p1 <- p1 + xlab(label="") p1 <- p1 + theme(plot.margin = margin(t = 0, b = -0.4, unit = "cm"))# unit(c(1,2,3,4), "cm")) # t = 0, r = 0, b = 0, l = 0 ("left", "right", "bottom", "top") ggsave("Figure2.jpeg",p1,width = 16, height = 12, dpi = 300, units = c( "cm")) #+END_SRC #+RESULTS: [[file:Bralibase_scores.jpeg]] *** Homfam **** Create test alignments create script to merge =*_ref.vie= and =*_test-only.vie= alignments. #+BEGIN_SRC bash -n :tangle create_homfam_tests.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle create_homfam_tests.sh :noweb yes :exports code :results none :noweb yes DIR=`pwd` function usage() { printf "This script will merge *_ref.vie and *_test-only.vie alignments and convert them into msf format.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done find ~/kalignbenchmark/data/homfam -name "*_test-only.vie" | awk '{test_aln=$1;ref=$1 ;gsub("_test-only.vie", "_ref.vie", ref);gsub("_test-only.vie", "_testaln.fa", test_aln); printf "kalign %s %s --reformat --rename -f fasta -o %s\n",ref, $1, test_aln }' > homfam_reformat.sh find ~/kalignbenchmark/data/homfam -name "*_ref.vie" | awk '{ref=$1;gsub("_ref.vie", "_ref.msf", ref);printf "kalign %s --reformat --rename -f msf -o %s\n", $1,ref}' >> homfam_reformat.sh chmod 755 homfam_reformat.sh #+END_SRC **** Run alignment programs on Homfam #+BEGIN_SRC bash -n :tangle gen_run_homfam.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle gen_run_homfam.sh :noweb yes :exports code :results none :noweb yes DIR=`pwd` function usage() { printf "This script will generate scripts to run kalign, clustal omega and muscle on the balibase MSA benchmark data set.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done printf "Generating kalign run script\n" printf "export PATH=~/kalignbenchmark/programs:$PATH\n\n" > run_homfam.sh find ~/kalignbenchmark/data/homfam -name "*_testaln.fa" | awk -v outdir="$SCRATCHDIR" '{ ref_aln=$1;gsub("_testaln.fa", "_ref.msf",ref_aln); printf "timescorealn -test %s -ref %s -program kalign --scratch ~/kalignbenchmark/scratch -out scores_homfam.csv \n", $1,ref_aln; printf "timescorealn -test %s -ref %s -program muscle --scratch ~/kalignbenchmark/scratch -out scores_homfam.csv\n", $1,ref_aln; printf "timescorealn -test %s -ref %s -program clustalo --scratch ~/kalignbenchmark/scratch -out scores_homfam.csv\n", $1,ref_aln; }' >> run_homfam.sh chmod 755 run_homfam.sh #+END_SRC #+BEGIN_EXAMPLE bash -n :tangle run_homfam.sh :noweb yes :exports code :results none :noweb yes :shebang #!/usr/bin/env bash <> ./run_homfam.sh #+END_EXAMPLE /home/user/kalignbenchmark/data/homfam printf "Generating clustalo run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*_test.fa" -o -name '*.fasta' | grep unaligned | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "clustalo-1.2.4-Ubuntu-x86_64 --outfmt=msf --in %s --force --out %s/%s_%s_%s_clustalo.msf\n", $1,outdir,a[n-4],a[n-3],a[n-2] }' > run_clustalo_bralibase.sh chmod 755 run_clustalo_bralibase.sh **** plot scores #+BEGIN_SRC R :session one :results output graphics :file homfam_runtime.jpeg :exports both :noweb yes <> mat <- read.csv("scores_homfam.csv"); p <- ggplot(mat, aes(NUMSEQ,Time)) p <- p + geom_point(aes(colour = Program,size = AVGLEN)) p <- p + scale_x_continuous(trans = 'log10', breaks=c(100,3000,10000,100000) ,labels = scales::comma) p <- p + scale_y_continuous(trans = 'log10',breaks=c(0.01, 0.1, 1 , 10,100,1000,10000), labels=scales::comma ) ggsave("homfam_runtime.jpeg",p,width = 18, height = 12, dpi = 300, units = c( "cm")) #+END_SRC #+RESULTS: [[file:homfam_runtime.jpeg]] q[[file:homfam_runtime.jpeg]] #+BEGIN_SRC R :session one :results output graphics :file homfam_scores.jpeg :exports both :noweb yes p <- ggplot(mat, aes(Program, SP)) p <- p + geom_boxplot(aes(colour = Program)) ggsave("homfam_scores.jpeg",p,width = 16, height = 12, dpi = 300, units = c( "cm")) #+END_SRC #+RESULTS: [[file:homfam_scores.jpeg]] *** QuantTest 2 **** script to generate run and score commands #+BEGIN_SRC bash -n :tangle gen_run_quanttest2.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle gen_run_quanttest2.sh :noweb yes :exports code :results none :noweb yes DIR=`pwd` function usage() { printf "This script will generate scripts to run kalign, clustal omega and muscle on the quanttest2 MSA benchmark data set.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done printf "Generating kalign run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -i %s -o %s/%s_kalign.afa\n", $1,outdir,a[n-1] }' > run_kalign_quanttest.sh chmod 755 run_kalign_quanttest.sh printf "Generating muscle run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "muscle3.8.31_i86linux32 -in %s -out %s/%s_muscle.afa\n", $1,outdir,a[n-1] }' > run_muscle_quanttest.sh chmod 755 run_muscle_quanttest.sh printf "Generating clustalo run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); printf "clustalo-1.2.4-Ubuntu-x86_64 --threads 8 --outfmt=a2m --in %s --out %s/%s_clustalo.afa\n", $1,outdir,a[n-1] }' > run_clustalo_quanttest.sh chmod 755 run_clustalo_quanttest.sh printf "Generating kalign scoring run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/data/QuanTest2/quantest2.py test@test %s/%s_kalign.afa ~/kalignbenchmark/data/QuanTest2/SS/%s.ss | grep kalignbenchmark \n", outdir,a[n-1],a[n-1] }' > score_kalign_quanttest.sh chmod 755 score_kalign_quanttest.sh printf "Generating muscle scoring run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/data/QuanTest2/quantest2.py test@test %s/%s_muscle.afa ~/kalignbenchmark/data/QuanTest2/SS/%s.ss | grep kalignbenchmark \n", outdir,a[n-1],a[n-1] }' > score_muscle_quanttest.sh chmod 755 score_muscle_quanttest.sh printf "Generating clustalo scoring run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/data/QuanTest2/quantest2.py test@test %s/%s_clustalo.afa ~/kalignbenchmark/data/QuanTest2/SS/%s.ss | grep kalignbenchmark \n", outdir,a[n-1],a[n-1] }' > score_clustalo_quanttest.sh chmod 755 score_clustalo_quanttest.sh #+END_SRC **** Run jobs and score alignments #+BEGIN_SRC bash -n :tangle run_quanttest.sh :noweb yes :exports code :results none :noweb yes :shebang #!/usr/bin/env bash <> ./run_muscle_quanttest.sh ./run_kalign_quanttest.sh ./run_clustalo_quanttest.sh ./score_kalign_quanttest.sh > scores_quanttest_kalign.csv ./score_muscle_quanttest.sh > scores_quanttest_muscle.csv ./score_clustalo_quanttest.sh > scores_quanttest_clustalo.csv #+END_SRC **** Plot #+BEGIN_SRC R :session one :results none :export none :noweb yes <> readquanttestscores <-function(file,name){ mat <- read.table(file); colnames(mat) <- c("Name","Score") mat$Type <- name mat$Name <- sub(".*/" ,"", mat$Name) mat$Name <- sub("[_]{1}[A-Z]*[.]{1}[A-Z]*$" ,"", mat$Name,ignore.case = TRUE) mat <- as_tibble(mat) return(mat) } #+END_SRC #+BEGIN_SRC R :session one :results output graphics :file Quantest.jpeg :exports both :noweb yes mat <- readquanttestscores("scores_quanttest_clustalo.csv","clustalo") mat <- rbind(mat, readquanttestscores("scores_quanttest_kalign.csv","kalign")); mat <- rbind(mat, readquanttestscores("scores_quanttest_muscle.csv","muscle")); #mat <- mat %>% mutate(Score = as.dbl(Score)) p4 <- ggplot(mat, aes(Type, Score)) p4 <- p4 + geom_boxplot(aes(colour = Type)) means <- aggregate(Score ~ Type, mat, median) means$Score <- round(means$Score,digits = 4) p4 <- p4 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p4 <- p4 + geom_text(data = means, aes(label = Score, y = Score + 0.08)) ggsave("Quantest.jpeg",p4,width = 16, height = 12, dpi = 300, units = c( "cm")) t = t.test(filter(mat,Type == "kalign")$Score,filter(mat,Type == "muscle")$Score, paired = FALSE, alternative = "greater") t = t.test(filter(mat,Type == "kalign")$Score,filter(mat,Type == "clustalo")$Score, paired = FALSE, alternative = "greater") #+END_SRC #+RESULTS: [[file:Quantest.jpeg]] *** Rose :PROPERTIES: :ORDERED: t :END: #+BEGIN_SRC bash -n :tangle create_rose_tests.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes DIR=`pwd` function usage() { printf "This script will merge *_ref.vie and *_test-only.vie alignments and convert them into msf format.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done numseq=(100 1000 10000 100000 1000000 10000000) for item in ${numseq[*]} do printf "# kalignbenchmark sample 1\n" > rose.in; printf "\n" >> rose.in; printf "%%include protein-defaults\n" >> rose.in; printf "\n" >> rose.in; printf "StdOut= False\n" >> rose.in printf "OutputFilebase = \"rosetest%d\"\n" $item >> rose.in; printf "AlignmentFormat= \"FASTA\"\n" >> rose.in; printf "SequenceLen = 500\n" >> rose.in; printf "SequenceNum = %d\n" $item >> rose.in; printf "ChooseFromLeaves = False\n" >> rose.in; printf "TreeWithSequences = True\n" >> rose.in; rose rose.in done #+END_SRC # rose sample 1 %include protein-defaults OutputFilename = "TIMO" OutputFilebase = "timotest" AlignmentFormat= "FASTA" SequenceLen = 500 SequenceNum = 1000 ChooseFromLeaves = False TreeWithSequences = True * Paper figure #+BEGIN_SRC R :session one :results none :export none :noweb yes <> readBaliscores <-function(file,name){ mat <- read.table(file); colnames(mat) <- c("Type","Name","SP","TC") mat$Type <- name mat$Name <- sub(".*/" ,"", mat$Name) mat$Name <- sub("[A-Z,_]*[.]{1}[A-Z]*$" ,"", mat$Name,ignore.case = TRUE) mat <- as.tibble(mat) x = str_split(mat$Name, "_", n = Inf, simplify = TRUE) mat$Group <- x[,1] return(mat) } #+END_SRC #+BEGIN_SRC R :session one :results output graphics :file Paper_figure.jpeg :exports both :noweb yes library(ggplot2) library(ggsignif) my_comparisons = list( c("clustalo", "kalign"), c("kalign", "muscle"), c("clustalo", "muscle") ) mat <- readBaliscores("scores_kalign.csv","kalign"); mat <- rbind(mat,readBaliscores("scores_muscle.csv","muscle")); mat <- rbind(mat,readBaliscores("scores_clustalo.csv","clustalo")); p1 <- ggplot(mat, aes(Group, SP)) p1 <- p1 + geom_boxplot(aes(colour = Type)) p1 <- p1 + scale_color_discrete(name = "Program") p1 <- p1 + theme(legend.position = c(0.25, 0.15),legend.text=element_text(size=16), legend.direction = "horizontal") p1 <- p1 + xlab(label="") ## p1 <- p1 + geom_signif(comparisons = my_comparisons ,map_signif_level=TRUE) mat <- readBaliscores("scores_kalign_bralibase.csv","kalign"); mat <- rbind(mat,readBaliscores("scores_muscle_bralibase.csv","muscle")); mat <- rbind(mat,readBaliscores("scores_clustalo_bralibase.csv","clustalo")); ## mat <- rbind(mat,readBaliscores("scores_kalign_3.csv","kalign 3")); ## mata ## <- rbind(mat,readBaliscores("scores_kalign_bibpm.csv","bibpm")); ## mat ## <- rbind(mat,readBaliscores("scores_kalign_bibpm_zero.csv","bibpm_zero")); p2 <- ggplot(mat, aes(Group, SP)) p2 <- p2 + geom_boxplot(aes(colour = Type)) p2 <- p2 + scale_color_discrete(name = "Program") p2 <- p2 + theme(legend.position = c(0.25, 0.15),legend.text=element_text(size=16), legend.direction = "horizontal") p2 <- p2 + xlab(label="") # p2 <- p2 + theme(plot.margin = margin(t = 0, b = -0.2, unit = "cm"))# unit(c(1,2,3,4), "cm")) # t = 0, r mat <- read.csv("scores_homfam.csv"); p3 <- ggplot(mat, aes(NUMSEQ,Time)) p3 <- p3 + geom_point(aes(colour = Program,size = AVGLEN)) p3 <- p3 + scale_x_continuous(trans = 'log10', breaks=c(100,3000,10000,100000) ,labels = scales::comma) p3 <- p3 + scale_y_continuous(trans = 'log10',breaks=c(0.01, 0.1, 1 , 10,100,1000,10000),labels=scales::comma ) p3 <- p3 + xlab("Number of sequences") p3 <- p3 + ylab("Time (s)") p = plot_grid(p1, p2, p3, labels = c('A','B','C'), ncol = 1, nrow = 3, rel_heights = c(0.7,0.7,1.0)) ggsave("Paper_figure.jpeg",p,width = 18, height = 24, dpi = 300, units = c( "cm")) #+END_SRC #+RESULTS: [[file:Paper_figure.jpeg]] Test for statistical significant differences: #+BEGIN_SRC R :session one assess_diff_alignment_scores <-function(mat, groupname,tests){ f <- filter(mat, Group == groupname) %>% select(-TC,-Group) %>% spread(Type, SP) %>% column_to_rownames("Name") t = t.test(f$kalign,f$clustalo, paired = TRUE, alternative = "greater") if(t$p.value * tests <= 0.05){ message("sig diff: kalign, clustalo ", groupname," ", t$p.value); message("Clustalo ", mean(f$clustalo)); message("Kalign ", mean(f$kalign)); message("Muscle ", mean(f$muscle)); } t = t.test(f$kalign,f$muscle, paired = TRUE, alternative = "greater") if(t$p.value * tests <= 0.05){ message("sig diff: kalign, muscle ", groupname," ", t$p.value); message("Clustalo ", mean(f$clustalo)); message("Kalign ", mean(f$kalign)); message("Muscle ", mean(f$muscle)); } } mat <- readBaliscores("scores_kalign.csv","kalign"); mat <- rbind(mat,readBaliscores("scores_muscle.csv","muscle")); mat <- rbind(mat,readBaliscores("scores_clustalo.csv","clustalo")); g <- unique(mat$Group) tests = length(g) * length(unique(mat$Type)) for (i in g){ assess_diff_alignment_scores(mat,i,tests); } mat <- readBaliscores("scores_kalign_bralibase.csv","kalign"); mat <- rbind(mat,readBaliscores("scores_muscle_bralibase.csv","muscle")); mat <- rbind(mat,readBaliscores("scores_clustalo_bralibase.csv","clustalo")); g <- unique(mat$Group) tests = length(g) * length(unique(mat$Type)) for (i in g){ assess_diff_alignment_scores(mat,i,tests); } #+END_SRC #+RESULTS: * Slurm scripts #+BEGIN_SRC bash -n :tangle srun_kalign.sh :shebang #!/usr/bin/env bash :exports code :results none :noweb yes #SBATCH -N 1 # number of nodes #SBATCH -n 1 # number of cores #SBATCH -t 0-10:00 # time (D-HH:MM) #SBATCH -o slurm.%N.%j.out # STDOUT #SBATCH -e slurm.%N.%j.err # STDERR DIR=`pwd` OUTPUT= INPUT= function usage() { printf "Slurm script to run kalign.\n\n" ; printf "usage: $0 -i input -o output\n\n" ; exit 1; } while getopts i:o: opt do case ${opt} in i) INPUT=${OPTARG};; o) OUTPUT=${OPTARG};; ,*) usage;; esac done if [ "${INPUT}" == "" ]; then usage; fi if [ "${OUTPUT}" == "" ]; then usage; fi kalign -i $INPUT -f msf -o $OUTPUT #+END_SRC kalign-3.5.1/scripts/benchmark.org000066400000000000000000000677121515023132300171270ustar00rootroot00000000000000#+TITLE: Benchmark of MSA algorithms #+AUTHOR: Timo Lassmann #+EMAIL: timolassmann@icloud.com #+DATE: 2019-09-27 #+LATEX_CLASS: report #+OPTIONS: toc:nil #+OPTIONS: H:4 #+LATEX_CMD: pdflatex * Introduction This org mode document contains the code and scripts to generate the results presented in: #+begin_quote Kalign 3: multiple sequence alignment of large data sets. #+end_quote * Benchmark ** MSA programs Programs to test: #+NAME: Benchprograms | Name | Download | |--------------+------------------------------------------------------------------------------| | Muscle | https://www.drive5.com/muscle/downloads3.8.31/muscle3.8.31_i86linux32.tar.gz | | Clustalomega | http://clustal.org/omega/clustalo-1.2.4-Ubuntu-x86_64 | | q-score | https://www.drive5.com/qscore/qscore_src.tar.gz | | Kalign2 | http://msa.sbc.su.se/downloads/kalign/current.tar.gz | Since the clustal papers provide a great overview of alignment programs I think these two should suffice. Note I am not comparing kalign against consistency based methods as these are a) all more accurate and b) slower. Kalign is targeted at the accurate and fast niche. ** Alignment benchmark datasets #+NAME: Benchmarkdata | Name | Download | |---------------+-------------------------------------------------------------------| | Balibase1-5 | http://www.lbgi.fr/balibase/BalibaseDownload/BAliBASE_R1-5.tar.gz | | Balifam | http://clustal.org/omega/bali3fam-26.tar.gz | | Bralibaseset1 | http://projects.binf.ku.dk/pgardner/bralibase/data-set1.tar.gz | | Bralibaseset2 | http://projects.binf.ku.dk/pgardner/bralibase/data-set2.tar.gz | | HomFam | http://www.clustal.org/omega/homfam-20110613-25.tar.gz | | QuanTest2 | http://bioinf.ucd.ie/quantest2.tar | ** Installation *** Step one: create directory and download all data #+BEGIN_SRC bash :exports both :results none cd mkdir -p kalignbenchmark cd kalignbenchmark mkdir -p data mkdir -p programs mkdir -p scratch #+END_SRC *** Download data sets #+BEGIN_SRC bash -n :results raw :exports both :var tbl=Benchmarkdata :colnames yes cd cd ~/kalignbenchmark/data for idx in ${!tbl[*]}; do #echo ${tbl[$idx]} if [[ ${tbl[$idx]} =~ ^http* ]]; then echo "wget ${tbl[$idx]}" wget ${tbl[$idx]} fi done #+END_SRC #+RESULTS: wget http://www.clustal.org/omega/homfam-20110613-25.tar.gz wget http://clustal.org/omega/bali3fam-26.tar.gz wget http://www.lbgi.fr/balibase/BalibaseDownload/BAliBASE_R1-5.tar.gz wget http://projects.binf.ku.dk/pgardner/bralibase/data-set1.tar.gz wget http://projects.binf.ku.dk/pgardner/bralibase/data-set2.tar.gz wget http://bioinf.ucd.ie/quantest2.tar Unpack data sets: #+BEGIN_SRC bash :results none :exports code cd cd ~/kalignbenchmark/data mkdir -p homfam mv homfam-20110613-25.tar.gz homfam cd homfam tar -zxvf homfam-20110613-25.tar.gz cd ~/kalignbenchmark/data for filename in *.tar.gz; do tar -zxvf $filename done tar -xvf quantest2.tar #+END_SRC **** Compile baliscore program and place in program directory #+BEGIN_SRC bash cd ~/kalignbenchmark/data/bb3_release/bali_score_src gcc *.c -lm -lexpat -o bali_score cp bali_score ~/kalignbenchmark/programs #+END_SRC #+RESULTS: *** Download programs #+BEGIN_SRC bash -n :results none :exports none :var tbl=Benchprograms :colnames yes cd cd ~/kalignbenchmark/programs for idx in ${!tbl[*]}; do #echo ${tbl[$idx]} if [[ ${tbl[$idx]} =~ ^http* ]]; then echo "wget ${tbl[$idx]}" wget ${tbl[$idx]} fi done chmod 755 clustalo-1.2.4-Ubuntu-x86_64 tar -zxvf muscle3.8.31_i86linux32.tar.gz tar -zxvf qscore_src.tar.gz mkdir -p kalign2_src cd kalign2_src mv ../current.tar.gz . tar -zxvf current.tar.gz ./configure make cp kalign ../kalign2 #+END_SRC And kalign3! #+BEGIN_SRC bash -n :results none :exports none cd ~/kalignbenchmark/programs mkdir -p kalign3_src cd kalign3_src git clone https://github.com/TimoLassmann/kalign.git cd kalign ./autogen.sh ./configure --bindir=$HOME/kalignbenchmark/programs make make check make install #+END_SRC *** Compile q-score NOTE: this is manual! Add: #+BEGIN_EXAMPLE C #include #+END_EXAMPLE to qscore header: =qscore.h= then: #+BEGIN_EXAMPLE bash make #+END_EXAMPLE *** Reformat datasets #+BEGIN_SRC bash :exports both :results none export PATH=$HOME/kalignbenchmark/programs:$PATH find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*_test.fa" -exec rm -rf {} \; printf "Generate commands to reformat the reference alignments\n\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.fa" -o -name '*.fasta' | grep structural | awk -v outdir="$SCRATCHDIR" '{printf "kalign %s --changename -reformat msf -o %s.msf\n", $1,$1 }' > run_reformat.sh find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.fa" -o -name '*.fasta' | grep unaligned | awk -v outdir="$SCRATCHDIR" '{printf "kalign %s --changename -reformat fasta -o %s_test.fa\n", $1,$1 }' >> run_reformat.sh chmod 755 run_reformat.sh ./run_reformat.sh #+END_SRC *** Reformat homfam create script to merge =*_ref.vie= and =*_test-only.vie= alignments. #+BEGIN_SRC bash -n :tangle create_homfam_tests.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle create_homfam_tests.sh :noweb yes :exports code :results none :noweb yes export PATH=$HOME/kalignbenchmark/programs:$PATH DIR=`pwd` function usage() { printf "This script will merge *_ref.vie and *_test-only.vie alignments and convert them into msf format.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done find ~/kalignbenchmark/data/homfam -name "*_test-only.vie" | awk '{\ test_aln=$1;ref=$1 ;\ gsub("_test-only.vie", "_ref.vie", ref);\ gsub("_test-only.vie", "_testaln.fa", test_aln);\ printf "cat %s %s > tmp.vie\n" ,ref, $1;\ printf "kalign tmp.vie --reformat --rename -f fasta -o %s\n", test_aln }' > homfam_reformat.sh find ~/kalignbenchmark/data/homfam -name "*_ref.vie" | awk '{ref=$1;gsub("_ref.vie", "_ref.msf", ref);printf "kalign %s --reformat --rename -f msf -o %s\n", $1,ref}' >> homfam_reformat.sh chmod 755 homfam_reformat.sh ./homfam_reformat.sh #+END_SRC ** Scripts to run programs Alignment programs #+BEGIN_SRC sh :exports both :results none :noweb yes :tangle run_aln.sh :shebang #!/usr/bin/env bash export PATH=$HOME/kalignbenchmark/programs:$PATH CPU=1 MEM=8 FMT= IN= OUT= PROG= function usage() { printf "usage: $0 -p -i -o \n\n" ; printf "Options:\n-f \n-t \n-m \n\n"; printf "Valid options for include:\n kalign\n kalign2\n muscle\n clustal\n\n"; exit 1; } while getopts t:m:p:i:o:f: opt do case ${opt} in t) CPU=${OPTARG};; m) MEM=${OPTARG};; p) PROG=${OPTARG};; i) IN=${OPTARG};; o) OUT=${OPTARG};; f) FMT=${OPTARG};; ,*) usage;; esac done if [ "${PROG}" == "" ]; then usage; fi if [ "${IN}" == "" ]; then usage; fi if [ "${OUT}" == "" ]; then usage; fi SLURMMEM=$MEM"G" CMD= if [ "${PROG}" == "kalign2" ]; then if [ "${FMT}" == "msf" ]; then CMD="kalign2 -i $IN -f msf -o $OUT" else CMD="kalign2 -i $IN -o $OUT" fi fi if [ "${PROG}" == "kalign" ]; then if [ "${FMT}" == "msf" ]; then CMD="kalign -i $IN -f msf -o $OUT" else CMD="kalign -i $IN -o $OUT" fi fi if [ "${PROG}" == "muscle" ]; then if [ "${FMT}" == "msf" ]; then CMD="muscle3.8.31_i86linux32 -msf -in $IN -out $OUT" else CMD="muscle3.8.31_i86linux32 -in $IN -out $OUT" fi fi if [ "${PROG}" == "clustal" ]; then if [ "${FMT}" == "msf" ]; then CMD="clustalo-1.2.4-Ubuntu-x86_64 --outfmt=msf --in $IN --out $OUT" else CMD="clustalo-1.2.4-Ubuntu-x86_64 --outfmt=a2m --in $IN --out $OUT" fi fi HAS_SLURM=0 # printf "Running Sanity checks:\n"; if which sbatch >/dev/null; then HAS_SLURM=1 fi # echo $HAS_SLURM if [ $HAS_SLURM = 1 ]; then echo "YES" sbatch < -i -r \n\n" ; printf "Options:\n-f \n-t \n-m \n\n"; printf "Valid options for include:\n kalign\n kalign2\n muscle\n clustal\n\n"; exit 1; } while getopts t:m:p:i:r: opt do case ${opt} in t) CPU=${OPTARG};; m) MEM=${OPTARG};; p) PROG=${OPTARG};; i) IN=${OPTARG};; r) OUT=${OPTARG};; ,*) usage;; esac done if [ "${PROG}" == "" ]; then usage; fi if [ "${IN}" == "" ]; then usage; fi if [ "${OUT}" == "" ]; then usage; fi SLURMMEM=$MEM"G" CMD= CMD="timescorealn -test $IN -ref $OUT -program $PROG --scratch $HOME/kalignbenchmark/scratch -out scores_homfam.csv" HAS_SLURM=0 # printf "Running Sanity checks:\n"; if which sbatch >/dev/null; then HAS_SLURM=1 fi # echo $HAS_SLURM if [ $HAS_SLURM = 1 ]; then echo "YES" sbatch <> #+END_SRC #+BEGIN_SRC bash -n :tangle gen_cmd.sh :noweb yes :exports code :results none :noweb yes DIR=`pwd` function usage() { printf "This script will generate scripts to run kalign, clustal omega and muscle on the balibase MSA benchmark data set.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done printf "Generating balibase run commands\n"; find ~/kalignbenchmark/data/bb3_release -name "*.tfa" |\ awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/);\ printf "run_aln.sh -p kalign -i %s -f msf -o %s/%s_%s_kalign.msf\n", $1,outdir,a[n-2],a[n-1];\ printf "run_aln.sh -p kalign2 -i %s -f msf -o %s/%s_%s_kalign2.msf\n", $1,outdir,a[n-2],a[n-1];\ printf "run_aln.sh -p muscle -i %s -f msf -o %s/%s_%s_muscle.msf\n", $1,outdir,a[n-2],a[n-1];\ printf "run_aln.sh -p clustal -i %s -f msf -o %s/%s_%s_clustal.msf\n", $1,outdir,a[n-2],a[n-1];\ }' > run_benchmark.sh printf "Generating bralibase run commands\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*_test.fa" |\ grep unaligned |\ awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/);\ printf "run_aln.sh -p kalign -i %s -f msf -o %s/%s_%s_%s_kalign.msf\n", $1,outdir,a[n-4],a[n-3],a[n-2];\ printf "run_aln.sh -p kalign2 -i %s -f msf -o %s/%s_%s_%s_kalign2.msf\n", $1,outdir,a[n-4],a[n-3],a[n-2];\ printf "run_aln.sh -p muscle -i %s -f msf -o %s/%s_%s_%s_muscle.msf\n", $1,outdir,a[n-4],a[n-3],a[n-2];\ printf "run_aln.sh -p clustal -i %s -f msf -o %s/%s_%s_%s_clustal.msf\n", $1,outdir,a[n-4],a[n-3],a[n-2];\ }' >> run_benchmark.sh printf "Generating Quantest2 run commands\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" |\ awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/);\ printf "run_aln.sh -p kalign -i %s -o %s/%s_kalign.afa\n", $1,outdir,a[n-1];\ printf "run_aln.sh -p kalign2 -i %s -o %s/%s_kalign2.afa\n", $1,outdir,a[n-1];\ printf "run_aln.sh -p muscle -i %s -o %s/%s_muscle.afa\n", $1,outdir,a[n-1];\ printf "run_aln.sh -p clustal -i %s -o %s/%s_clustal.afa\n", $1,outdir,a[n-1];\ }' >> run_benchmark.sh chmod 755 run_benchmark.sh #+END_SRC Here is the script to run the homfam test: #+BEGIN_SRC bash -n :tangle gen_timecmd.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle gen_timecmd.sh :noweb yes :exports code :results none :noweb yes DIR=`pwd` function usage() { printf "This script will generate scripts to run kalign, clustal omega and muscle on the balibase MSA benchmark data set.\n\n" ; printf "usage: $0\n\n" ; exit 1; } while getopts h opt do case ${opt} in h) usage;; ,*) usage;; esac done printf "export PATH=~/kalignbenchmark/programs:$PATH\n\n" > run_homfam.sh find ~/kalignbenchmark/data/homfam -name "*_testaln.fa" | awk -v outdir="$SCRATCHDIR" '{ ref_aln=$1;gsub("_testaln.fa", "_ref.msf",ref_aln); printf "run_timealn.sh -p kalign -i %s -r %s\n", $1,ref_aln; printf "run_timealn.sh -p muscle -i %s -r %s\n", $1,ref_aln; printf "run_timealn.sh -p clustal -i %s -r %s\n", $1,ref_aln; }' >> run_homfam.sh #+END_SRC * Score alignments ** Balibase #+BEGIN_SRC bash -n :tangle score_balibase.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle score_balibase.sh :noweb yes :exports code :results none :noweb yes printf "Generating kalign scoring run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.xml" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_kalign.msf | grep auto\n", $1,outdir,a[n-2],a[n-1] }' > score_bb3_kalign.sh chmod 755 score_bb3_kalign.sh find ~/kalignbenchmark/data/bb3_release -name "*.xml" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_kalign2.msf | grep auto\n", $1,outdir,a[n-2],a[n-1] }' > score_bb3_kalign2.sh chmod 755 score_bb3_kalign2.sh printf "Generating muscle scoring run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.xml" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_muscle.msf | grep auto\n", $1,outdir,a[n-2],a[n-1] }' > score_bb3_muscle.sh chmod 755 score_bb3_muscle.sh printf "Generating clustal scoring run script\n"; find ~/kalignbenchmark/data/bb3_release -name "*.xml" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_clustal.msf | grep auto\n", $1,outdir,a[n-2],a[n-1] }' > score_bb3_clustal.sh chmod 755 score_bb3_clustal.sh ./score_bb3_kalign.sh > scores_balibase_kalign.csv ./score_bb3_kalign2.sh > scores_balibase_kalign2.csv ./score_bb3_muscle.sh > scores_balibase_muscle.csv ./score_bb3_clustal.sh > scores_balibase_clustal.csv #+END_SRC To plot the scores: #+NAME: Rplotheader #+BEGIN_SRC R :session one :results none :export none :noweb yes <> readBaliscores <-function(file,name){ mat <- read.table(file); colnames(mat) <- c("Type","Name","SP","TC") mat$Type <- name mat$Name <- sub(".*/" ,"", mat$Name) mat$Name <- sub("[A-Z,_]*[.]{1}[A-Z]*$" ,"", mat$Name,ignore.case = TRUE) mat <- as.tibble(mat) x = str_split(mat$Name, "_", n = Inf, simplify = TRUE) mat$Group <- x[,1] return(mat) } #+END_SRC The actual plotting: #+BEGIN_SRC R :session one :results output graphics :file Balibase_scores.jpeg :exports both :noweb yes library(ggplot2) mat <- readBaliscores("scores_balibase_kalign.csv","kalign3"); mat <- rbind(mat,readBaliscores("scores_balibase_kalign2.csv","kalign2")); mat <- rbind(mat,readBaliscores("scores_balibase_muscle.csv","muscle")); mat <- rbind(mat,readBaliscores("scores_balibase_clustal.csv","clustalo")); p <- ggplot(mat, aes(Group, SP)) p <- p + geom_boxplot(aes(colour = Type)) p <- p + scale_color_discrete(name = "Program") p <- p + theme(legend.position = c(0.6, 0.15),legend.text=element_text(size=14),legend.direction = "horizontal") p <- p + xlab(label="") p <- p + ggtitle("Balibase benchmark") p # ggsave("Balibase_scores.jpeg",p,width = 18, height = 12, dpi = 300, units = c( "cm")) ## p1 <- p1 + geom_signif(comparisons = my_comparisons ,map_signif_level=TRUE) #+END_SRC #+RESULTS: ** Bralibase #+BEGIN_SRC bash -n :tangle score_bralibase.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle score_bralibase.sh :noweb yes :exports code :results none :noweb yes printf "Generating kalign scoring run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.msf" | grep structural | awk -v outdir="$SCRATCHDIR" '{name=$1; gsub(/structural/, "unaligned"); n=split ($1,a,/[\/,.]/); printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_%s_kalign.msf | grep auto\n", name,outdir,a[n-4],a[n-3],a[n-2] }' > score_bralibase_kalign.sh chmod 755 score_bralibase_kalign.sh printf "Generating kalign2 scoring run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.msf" | grep structural | awk -v outdir="$SCRATCHDIR" '{name=$1; gsub(/structural/, "unaligned"); n=split ($1,a,/[\/,.]/); printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_%s_kalign2.msf | grep auto\n", name,outdir,a[n-4],a[n-3],a[n-2] }' > score_bralibase_kalign2.sh chmod 755 score_bralibase_kalign2.sh printf "Generating muscle scoring run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.msf" | grep structural | awk -v outdir="$SCRATCHDIR" '{name=$1; gsub(/structural/, "unaligned"); n=split ($1,a,/[\/,.]/); printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_%s_muscle.msf | grep auto\n", name,outdir,a[n-4],a[n-3],a[n-2] }' > score_bralibase_muscle.sh chmod 755 score_bralibase_muscle.sh printf "Generating clustalo scoring run script\n"; find ~/kalignbenchmark/data/data-set1 ~/kalignbenchmark/data/data-set2 -name "*.msf" | grep structural | awk -v outdir="$SCRATCHDIR" '{name=$1; gsub(/structural/, "unaligned"); n=split ($1,a,/[\/,.]/); printf "~/kalignbenchmark/programs/bali_score %s %s/%s_%s_%s_clustal.msf | grep auto\n", name,outdir,a[n-4],a[n-3],a[n-2] }' > score_bralibase_clustal.sh chmod 755 score_bralibase_clustal.sh ./score_bralibase_kalign.sh > scores_bralibase_kalign.csv ./score_bralibase_kalign2.sh > scores_bralibase_kalign2.csv ./score_bralibase_muscle.sh > scores_bralibase_muscle.csv ./score_bralibase_clustal.sh > scores_bralibase_clustal.csv #+END_SRC Plot scores #+BEGIN_SRC R :session one :results output graphics :file Bralibase_scores.jpeg :exports both :noweb yes <> library(ggplot2) mat <- readBaliscores("scores_bralibase_kalign.csv","kalign3"); mat <- rbind(mat,readBaliscores("scores_bralibase_kalign2.csv","kalign2")); mat <- rbind(mat,readBaliscores("scores_bralibase_muscle.csv","muscle")); mat <- rbind(mat,readBaliscores("scores_bralibase_clustal.csv","clustalo")); p <- ggplot(mat, aes(Group, SP)) p <- p + geom_boxplot(aes(colour = Type)) p <- p + scale_color_discrete(name = "Program") p <- p + theme(legend.position = c(0.6, 0.15),legend.text=element_text(size=14),legend.direction = "horizontal") p <- p + xlab(label="") p <- p + ggtitle("Bralibase benchmark") ggsave("Bralibase_scores.jpeg",p,width = 18, height = 12, dpi = 300, units = c( "cm")) #+END_SRC #+RESULTS: q[[file:Bralibase_scores.jpeg]] ** Quantest2 #+BEGIN_SRC bash -n :tangle score_quantest2.sh :shebang #!/usr/bin/env bash :noweb yes :exports code :results none :noweb yes <> #+END_SRC #+BEGIN_SRC bash -n :tangle score_quantest2.sh :noweb yes :exports code :results none :noweb yes printf "Generating kalign scoring run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/data/QuanTest2/quantest2.py test@test %s/%s_kalign.afa ~/kalignbenchmark/data/QuanTest2/SS/%s.ss | grep kalignbenchmark \n", outdir,a[n-1],a[n-1] }' > score_quantest2_kalign.sh chmod 755 score_quantest2_kalign.sh printf "Generating kalign scoring run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/data/QuanTest2/quantest2.py test@test %s/%s_kalign2.afa ~/kalignbenchmark/data/QuanTest2/SS/%s.ss | grep kalignbenchmark \n", outdir,a[n-1],a[n-1] }' > score_quantest2_kalign2.sh chmod 755 score_quantest2_kalign2.sh printf "Generating muscle scoring run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/data/QuanTest2/quantest2.py test@test %s/%s_muscle.afa ~/kalignbenchmark/data/QuanTest2/SS/%s.ss | grep kalignbenchmark \n", outdir,a[n-1],a[n-1] }' > score_quantest2_muscle.sh chmod 755 score_quantest2_muscle.sh printf "Generating clustalo scoring run script\n"; find ~/kalignbenchmark/data/QuanTest2/Test -name "*.vie" | awk -v outdir="$SCRATCHDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/kalignbenchmark/data/QuanTest2/quantest2.py test@test %s/%s_clustal.afa ~/kalignbenchmark/data/QuanTest2/SS/%s.ss | grep kalignbenchmark \n", outdir,a[n-1],a[n-1] }' > score_quantest2_clustal.sh chmod 755 score_quantest2_clustal.sh ./score_quantest2_kalign.sh > scores_quantest2_kalign.csv ./score_quantest2_kalign2.sh > scores_quantest2_kalign2.csv ./score_quantest2_muscle.sh > scores_quantest2_muscle.csv ./score_quantest2_clustal.sh > scores_quantest2_clustal.csv #+END_SRC *** Plot #+BEGIN_SRC R :session one :results output graphics :file Quantest2_scores.jpeg :exports both :noweb yes <> readquanttestscores <-function(file,name){ mat <- read.table(file); colnames(mat) <- c("Name","Score") mat$Type <- name mat$Name <- sub(".*/" ,"", mat$Name) mat$Name <- sub("[_]{1}[A-Z]*[.]{1}[A-Z]*$" ,"", mat$Name,ignore.case = TRUE) mat <- as_tibble(mat) return(mat) } library(ggplot2) mat <- readquanttestscores("scores_quanttest_clustalo.csv","clustalo") mat <- rbind(mat, readquanttestscores("scores_quanttest_kalign.csv","kalign3")); mat <- rbind(mat, readquanttestscores("scores_quantest2_kalign2.csv","kalign2")); mat <- rbind(mat, readquanttestscores("scores_quanttest_muscle.csv","muscle")); #mat <- mat %>% mutate(Score = as.dbl(Score)) p4 <- ggplot(mat, aes(Type, Score)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + ggtitle("Quantest2 benchmark") ggsave("Quantest2_scores.jpeg",p4,width = 16, height = 12, dpi = 300, units = c( "cm")) #+END_SRC #+RESULTS: [[file:Quantest2_scores.jpeg]] ** Homfam *** Plot: #+BEGIN_SRC R :session one :results output graphics :file Homfam_scores.jpeg :exports both :noweb yes <> library(ggplot2) mat <- read.csv("scores_homfam.csv"); p <- ggplot(mat, aes(NUMSEQ,Time)) p <- p + geom_point(aes(colour = Program,size = AVGLEN)) p <- p + scale_x_continuous(trans = 'log10', breaks=c(100,3000,10000,100000) ,labels = scales::comma) p <- p + scale_y_continuous(trans = 'log10',breaks=c(0.01, 0.1, 1 , 10,100,1000,10000),labels=scales::comma ) p <- p + xlab("Number of sequences") p <- p + ylab("Time (s)") p <- p + ggtitle("HomFam benchmark") p ggsave("Homfam_scores.jpeg",p,width = 18, height = 12, dpi = 300, units = c( "cm")) #+END_SRC *** Run tests * Check for dependencies #+NAME: liblist #+BEGIN_SRC R -n :exports code :results none libraries <- c("tidyverse","ggplot2","stringi","cowplot") #+END_SRC Script to test if libraries are present. #+BEGIN_SRC R -n :tangle test_for_libraries.R :shebang #!/usr/bin/env Rscript :noweb yes :exports code :results none <> Sys.info()["nodename"] for(library in libraries) { f = is.element(library, installed.packages()[,1]) print(paste("Library",library, "is installed?", f)) if(!f) { message("Missing library:",library ) quit(status=1) } } quit(status=0) #+END_SRC #+BEGIN_SRC sh -n :results output :exports both ./test_for_libraries.R #+END_SRC #+RESULTS: : nodename : "work" : [1] "Library tidyverse is installed? TRUE" : [1] "Library ggplot2 is installed? TRUE" : [1] "Library stringi is installed? TRUE" : [1] "Library cowplot is installed? TRUE" install.packages("tidyverse") Code block to load the libraries in R code. #+NAME: Rlibraries #+BEGIN_SRC R -n :exports code :results none :noweb yes <> lapply(libraries, FUN = function(X) { do.call("library", list(X)) }) #+END_SRC kalign-3.5.1/scripts/bralibase.org000066400000000000000000000214601515023132300171070ustar00rootroot00000000000000#+TITLE: Test kalign on BAliBASE #+AUTHOR: Timo Lassmann #+EMAIL: timolassmann@icloud.com #+DATE: 2019-04-23 #+LATEX_CLASS: report #+OPTIONS: toc:nil #+OPTIONS: H:4 #+LATEX_CMD: pdflatex * Introduction Let's run kalign on the Bralibase benchmark * Method ** script to run test :PROPERTIES: :ORDERED: t :END: The script has points to a bralibase directory containing =structural= and =unaligned= sub directory #+BEGIN_SRC bash -n :tangle run_bralibase_test.sh :shebang #!/usr/bin/env bash :noweb yes DIR=`pwd` INDIR= OUTPUT= function usage() { printf "This script runs kalign for a across the bralibase test sets.\n\n" ; printf "usage: $0 -i -o \n"; exit 1; } while getopts i:o: opt do case ${opt} in i) INDIR=${OPTARG};; o) OUTPUT=${OPTARG};; ,*) usage;; esac done if [ "${INDIR}" == "" ]; then usage; fi if [ "${OUTPUT}" == "" ]; then usage; fi if [ -f $OUTPUT ]; then printf "OUTPUT file exits - will overwrite.\n"; rm $OUTPUT fi function run_test() { dir=$1 name=$2 echo "$name" for file in "$dir"/unaligned/*.fa do ref="${file//unaligned/structural}" # printf "Working on %s\n" $file; kalign $file -o test.msf 2>&1 > /dev/null kalign $ref -r -o ref.msf 2>&1 > /dev/null bali_score ref.msf test.msf | grep auto | awk -v name="$name" '{printf "%s,%f,%f\n" , name, $3, $4}' >> $OUTPUT done } run_test $INDIR/data-set1/g2intron g2intron run_test $INDIR/data-set1/rRNA rRNA run_test $INDIR/data-set1/SRP SRP run_test $INDIR/data-set1/tRNA tRNA run_test $INDIR/data-set1/U5 U5 #+END_SRC #+BEGIN_SRC sh :session onesh cd ~/data/bb3_release cd .. mkdir -p bb3_release_tmp_aln cd bb3_release_tmp_aln KALIGNOUTDIR=$PWD echo $KALIGNOUTDIR #+END_SRC #+RESULTS: | | | sh-4.4$ sh-4.4$ sh-4.4$ sh-4.4$ sh-4.4$ /home/user/data/bb3_release_tmp_aln | #+BEGIN_SRC sh :session onesh :results raw find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -alnp param_25.txt %s -o %s/%s_%skalign25.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_kalign.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -alnp param_50.txt %s -o %s/%s_%skalign50.msf\n", $1,outdir,a[n-2],a[n-1] }' >> run_kalign.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign -alnp param_75.txt %s -o %s/%s_%skalign75.msf\n", $1,outdir,a[n-2],a[n-1] }' >> run_kalign.sh #+END_SRC #+BEGIN_SRC sh :session onesh :results raw find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign %s -o %s/%s_%skalign.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_kalign.sh find ~/data/bb3_release -name "*.tfa" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "clustalo --dealign -i %s --outfmt=msf -o %s/%s_%sclustalo.msf\n", $1,outdir,a[n-2],a[n-1] }' > run_clustalo.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "kalign %s -set 0 -o %s/%s_%skalign_1.msf\n", $1,outdir,a[n-2],a[n-1] ; printf "kalign %s -set 1 -o %s/%s_%skalign_2.msf\n", $1,outdir,a[n-2],a[n-1] ; printf "kalign %s -set 2 -o %s/%s_%skalign_3.msf\n", $1,outdir,a[n-2],a[n-1] ; printf "kalign %s -set 3 -o %s/%s_%skalign_4.msf\n", $1,outdir,a[n-2],a[n-1] ; }' > run_kalign_cmsa.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); printf "cmsa -a %s/%s_%skalign_*.msf -out %s/%s_%skalign_cmsa.msf -f msf \n",outdir,a[n-2],a[n-1],outdir,a[n-2],a[n-1] ; }' > run_cmsa.sh chmod 755 run_kalign_cmsa.sh chmod 755 run_kalign.sh chmod 755 run_clustalo.sh #+END_SRC #+RESULTS: #+BEGIN_SRC sh :session onesh :results raw find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_1.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set1.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_2.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set2.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_3.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set3.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_4.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set4.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_5.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_set5.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%skalign_cmsa.msf\n", $1,outdir,a[n-2],a[n-1] }' > alignment_scores_cmsa.sh find ~/data/bb3_release -name "*.xml" | awk -v outdir="$KALIGNOUTDIR" '{n=split ($1,a,/[\/,.]/); ;printf "~/data/bb3_release/bali_score_src/bali_score %s %s/%s_%sclustalo.msf\n", $1,outdir,a[n-2],a[n-1] }' >> alignment_scores.sh chmod 755 alignment_scores.sh #+END_SRC #+RESULTS: run the tests #+BEGIN_SRC sh :session onesh parallel --jobs 5 < ./run_kalign.sh parallel --jobs 5 < ./run_clustalo.sh ./alignment_scores.sh | grep auto > scores2.csv #+END_SRC ** Step 3: plot scores #+BEGIN_SRC R :session one :results none :export none library(tidyverse) library(ggplot2) library(stringi) library(cowplot) readBaliscores <-function(file,name){ mat <- read.table(file); colnames(mat) <- c("Type","Name","SP","TC") mat$Type <- name mat$Name <- sub(".*/" ,"", mat$Name) mat$Name <- sub("[A-Z,_]*[.]{1}[A-Z]*$" ,"", mat$Name,ignore.case = TRUE) mat <- as.tibble(mat) x = str_split(mat$Name, "_", n = Inf, simplify = TRUE) mat$Group <- x[,1] return(mat) } #+END_SRC #+BEGIN_SRC R :session one :results output graphics :file BalibaseSP_scores.jpeg :exports both :width 160 :height 80 mat <- readBaliscores("scores_kalign_old.csv","kalign old"); mat <- rbind(mat,readBaliscores("scores_kalign_newp.csv","kalign newp")); mat <- rbind(mat,readBaliscores("scores_kalign_digi.csv","kalign digi")); mat <- rbind(mat,readBaliscores("scores_kalign_digi2.csv","kalign digi 2")); mat <- rbind(mat,readBaliscores("scores_kalign_dist2.csv","kalign dist 2")); ## mat <- rbind(mat,readBaliscores("scores_kalign_3.csv","kalign 3")); ## mata ## <- rbind(mat,readBaliscores("scores_kalign_bibpm.csv","bibpm")); ## mat ## <- rbind(mat,readBaliscores("scores_kalign_bibpm_zero.csv","bibpm_zero")); p1 <- ggplot(mat, aes(Group, SP)) p1 <- p1 + geom_boxplot(aes(colour = Type)) means <- aggregate(SP ~ Type, mat, mean) means$SP <- round(means$SP,digits = 4) p2 <- ggplot(mat, aes(Type, SP)) p2 <- p2 + geom_boxplot(aes(colour = Type)) p2 <- p2 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p2 <- p2 + geom_text(data = means, aes(label = SP, y = SP + 0.08)) p3 <- ggplot(mat, aes(Group, TC)) p3 <- p3 + geom_boxplot(aes(colour = Type)) means <- aggregate(TC ~ Type, mat, mean) means$TC <- round(means$TC,digits = 4) p4 <- ggplot(mat, aes(Type, TC)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + geom_boxplot(aes(colour = Type)) p4 <- p4 + stat_summary(fun.y=mean, colour="darkred", geom="point", shape=18, size=3,show.legend = FALSE) p4 <- p4 + geom_text(data = means, aes(label = TC, y = TC + 0.08)) p = plot_grid(p1,p2,p3,p4, labels=c("SP", "TC"), ncol = 2, nrow= 2) #+END_SRC #+RESULTS: [[file:BalibaseSP_scores.jpeg]] kalign-3.5.1/src/000077500000000000000000000000001515023132300135475ustar00rootroot00000000000000kalign-3.5.1/src/CMakeLists.txt000066400000000000000000000024551515023132300163150ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.18) # Build library in sub-directories if (NOT TARGET kalign::kalign) add_subdirectory(${PROJECT_SOURCE_DIR}/lib build EXCLUDE_FROM_ALL) endif() # link to installed library # if (NOT TARGET kalign::kalign) # find_package(kalign) # endif() if(NOT KALIGN_PACKAGE_NAME) set(KALIGN_PACKAGE_NAME ${CMAKE_PROJECT_NAME}) endif() if(NOT KALIGN_PACKAGE_VERSION) set(KALIGN_PACKAGE_VERSION ${KALIGN_LIBRARY_VERSION_STRING}) endif() #configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/version.h.in" #"version.h" ) add_executable(kalign-bin run_kalign.c parameters.c ) # Link with static library.... target_link_libraries(kalign-bin PRIVATE tldevel ${PROJECT_NAME}_static ) if(OpenMP_C_FOUND) target_link_libraries(kalign-bin PRIVATE OpenMP::OpenMP_C) endif(OpenMP_C_FOUND) target_compile_definitions(kalign-bin PRIVATE KALIGN_PACKAGE_NAME=\"${KALIGN_PACKAGE_NAME}\" KALIGN_PACKAGE_VERSION=\"${KALIGN_PACKAGE_VERSION}\") set_target_properties(kalign-bin PROPERTIES OUTPUT_NAME kalign) add_executable(kalignfmt run_reformat.c parameters.c ) if(OpenMP_C_FOUND) target_link_libraries(kalignfmt PRIVATE OpenMP::OpenMP_C) endif(OpenMP_C_FOUND) install(TARGETS kalign-bin DESTINATION bin) target_link_libraries(kalignfmt PRIVATE tldevel kalign::kalign) kalign-3.5.1/src/parameters.c000066400000000000000000000060121515023132300160550ustar00rootroot00000000000000#include "tldevel.h" #include "kalign/kalign.h" #include #ifdef _WIN32 #include #else #include #endif #ifdef HAVE_OPENMP #include #endif #define PARAMETERS_IMPORT #include "parameters.h" static int get_default_thread_count(void) { int cores = 1; #ifdef HAVE_OPENMP cores = omp_get_num_procs(); #elif defined(_WIN32) SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); cores = sysinfo.dwNumberOfProcessors; #elif defined(_SC_NPROCESSORS_ONLN) cores = sysconf(_SC_NPROCESSORS_ONLN); if (cores <= 0) cores = 1; #endif if (cores > 1) cores = cores - 1; if (cores > 16) cores = 16; if (cores < 1) cores = 1; return cores; } struct parameters*init_param(void) { struct parameters* param = NULL; MMALLOC(param, sizeof(struct parameters)); param->dist_method = KALIGNDIST_BPM; param->aln_param_file = NULL; param->param_set = -1; param->infile = NULL; param->num_infiles = 0; param->input = NULL; param->outfile = NULL; param->format = NULL; param->reformat = 0; param->rename = 0; param->help_flag = 0; param->dump_internal = 0; param->type = -1; param->gpo = -1.0; param->gpe = -1.0; param->tgpe = -1.0; param->matadd = 0.0F; param->chaos = 0; param->nthreads = get_default_thread_count(); param->clean = 0; param->unalign = 0; param->refine = KALIGN_REFINE_NONE; param->adaptive_budget = 0; param->ensemble = 0; param->ensemble_seed = 42; param->min_support = 0; param->save_poar = NULL; param->load_poar = NULL; param->consistency_anchors = 5; param->consistency_weight = 2.0f; param->realign = 0; param->vsm_amax = -1.0f; /* sentinel: use C defaults */ param->mode = 0; /* 0=default, 1=fast, 2=precise */ param->quiet = 0; return param; ERROR: free_parameters(param); return NULL; } void free_parameters(struct parameters* param) { if(param){ if(param->num_infiles){ MFREE(param->infile); } MFREE(param); } } int check_msa_format_string(char* format) { int ok = 0; if(format){ if(strstr(format,"msf")){ ok = 1; }else if(strstr(format,"clu")){ ok = 1; }else if(strstr(format,"fasta")){ ok = 1; }else if(strstr(format,"fa")){ ok = 1; }else{ ok = 0; ERROR_MSG("Format %s not recognized.",format); } if(!ok){ ERROR_MSG("Format %s not recognized.",format); } } return OK; ERROR: return FAIL; } kalign-3.5.1/src/parameters.h000066400000000000000000000026211515023132300160640ustar00rootroot00000000000000#ifndef PARAMETERS_H #define PARAMETERS_H #include #ifdef PARAMETERS_IMPORT #define EXTERN #else #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN extern #endif #endif #define KALIGNDIST_ALN 0 #define KALIGNDIST_BPM 1 #define KALIGNDIST_WU 2 struct parameters{ char **infile; char *input; char *outfile; char* format; char* aln_param_file; int type; float gpo; float gpe; float tgpe; float matadd; int chaos; int out_format; int param_set; int dist_method; int num_infiles; int reformat; int rename; /* rename sequences - to make bali_score swallow the alignments */ int dump_internal; int nthreads; int clean; int unalign; int refine; int adaptive_budget; int ensemble; uint64_t ensemble_seed; int min_support; char* save_poar; char* load_poar; int consistency_anchors; float consistency_weight; int realign; float vsm_amax; int mode; /* 0=default, 1=fast, 2=precise */ int help_flag; int quiet; }; EXTERN struct parameters* init_param(void); EXTERN void free_parameters(struct parameters *param); EXTERN int check_msa_format_string(char* format); #undef PARAMETERS_IMPORT #undef EXTERN #endif kalign-3.5.1/src/run_kalign.c000066400000000000000000000511571515023132300160550ustar00rootroot00000000000000#include "tldevel.h" #include "tlmisc.h" #include "kalign/kalign.h" /* #include "version.h" */ #include "parameters.h" #include #include #include #include #define OPT_SET 1 #define OPT_SHOWW 5 #define OPT_GPO 6 #define OPT_GPE 7 #define OPT_TGPE 8 #define OPT_NTHREADS 10 #define OPT_ALN_TYPE 13 #define OPT_REFINE 14 #define OPT_ADAPTIVE_BUDGET 15 #define OPT_ENSEMBLE 16 #define OPT_ENSEMBLE_SEED 17 #define OPT_MIN_SUPPORT 18 #define OPT_SAVE_POAR 19 #define OPT_LOAD_POAR 20 #define OPT_CONSISTENCY 21 #define OPT_FAST 22 #define OPT_PRECISE 23 #define OPT_REALIGN 24 #define OPT_VSM_AMAX 25 #define OPT_CONSISTENCY_WEIGHT 26 static int set_aln_type(char* in, int* type ); static int set_refine_mode(char* in, int* refine); static int run_kalign(struct parameters* param); static int print_kalign_header(void); static int print_kalign_help(char * argv[]); static int print_kalign_warranty(void); int print_kalign_help(char * argv[]) { const char usage[] = " -i -o "; char* basename = NULL; RUN(tlfilename(argv[0], &basename)); fprintf(stdout,"\nUsage: %s %s\n\n",basename ,usage); fprintf(stdout,"Modes:\n\n"); fprintf(stdout,"%*s%-*s: %s\n",3,"",MESSAGE_MARGIN-3,"(default)","Consistency anchors + VSM (best general-purpose)"); fprintf(stdout,"%*s%-*s: %s\n",3,"",MESSAGE_MARGIN-3,"--fast","VSM only, no consistency (fastest)"); fprintf(stdout,"%*s%-*s: %s\n",3,"",MESSAGE_MARGIN-3,"--precise","Ensemble(3) + VSM + realign (highest precision)"); fprintf(stdout,"\nOptions:\n\n"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--format","Output format." ,"[Fasta]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--type","Alignment type (rna, dna, internal)." ,"[rna]" ); fprintf(stdout,"%*s%-*s %s %s\n",3,"",MESSAGE_MARGIN-3,"","Options: protein, divergent (protein)" ,"" ); fprintf(stdout,"%*s%-*s %s %s\n",3,"",MESSAGE_MARGIN-3,""," rna, dna, internal (nuc)." ,"" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--gpo","Gap open penalty." ,"[]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--gpe","Gap extension penalty." ,"[]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--tgpe","Terminal gap extension penalty." ,"[]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--refine","Refinement mode." ,"[none]"); fprintf(stdout,"%*s%-*s %s %s\n",3,"",MESSAGE_MARGIN-3,"","Options: none, all, confident" ,"" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"-n/--nthreads","Number of threads." ,"[auto: N-1, max 16]"); fprintf(stdout,"\nEnsemble options:\n\n"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--ensemble","Number of ensemble runs." ,"[off; 5 if no value given]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--ensemble-seed","RNG seed for ensemble." ,"[42]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--min-support","Explicit consensus threshold." ,"[auto]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--save-poar","Save POAR table to file." ,"[off]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--load-poar","Load POAR table for re-threshold." ,"[off]"); fprintf(stdout,"\nAdvanced (usually managed by modes):\n\n"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--consistency","Anchor consistency (K anchors)." ,"[5]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--consistency-weight","Consistency anchor weight." ,"[2.0]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--realign","Alignment-guided tree rebuild iters." ,"[0]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--vsm-amax","VSM amplitude (0 to disable)." ,"[auto]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--adaptive-budget","Scale refinement trials by uncertainty." ,"[off]"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--version (-V/-v)","Prints version." ,"[NA]" ); fprintf(stdout,"\nExamples:\n\n"); fprintf(stdout,"Passing sequences via stdin:\n\n cat input.fa | kalign -i - -f fasta > out.afa\n\n"); fprintf(stdout,"Combining multiple input files:\n\n kalign seqsA.fa seqsB.fa seqsC.fa -f fasta > combined.afa\n\n"); if(basename){ MFREE(basename); } return OK; ERROR: if(basename){ MFREE(basename); } return FAIL; } int print_kalign_warranty(void) { fprintf(stdout,"Disclaimer of Warranty (Apache License, Version 2.0, Section 7):\n"); fprintf(stdout,"\n"); fprintf(stdout,"Unless required by applicable law or agreed to in writing, Licensor\n"); fprintf(stdout,"provides the Work (and each Contributor provides its Contributions)\n"); fprintf(stdout,"on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\n"); fprintf(stdout,"either express or implied, including, without limitation, any\n"); fprintf(stdout,"warranties or conditions of TITLE, NON-INFRINGEMENT,\n"); fprintf(stdout,"MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.\n"); fprintf(stdout,"\n"); fprintf(stdout,"See the COPYING file for the full Apache License, Version 2.0.\n"); return OK; } int print_kalign_header(void) { fprintf(stderr,"\n"); fprintf(stderr,"Kalign (%s)\n", KALIGN_PACKAGE_VERSION); fprintf(stderr,"\n"); fprintf(stderr,"Copyright (C) 2006-2026 Timo Lassmann\n"); fprintf(stderr,"\n"); fprintf(stderr,"Licensed under the Apache License, Version 2.0.\n"); fprintf(stderr,"See the COPYING file or http://www.apache.org/licenses/LICENSE-2.0\n"); fprintf(stderr,"\n"); fprintf(stderr,"Please cite:\n"); fprintf(stderr," Lassmann, Timo.\n"); fprintf(stderr," \"Kalign 3: multiple sequence alignment of large data sets.\"\n"); fprintf(stderr," Bioinformatics (2019) \n"); fprintf(stderr," https://doi.org/10.1093/bioinformatics/btz795\n"); fprintf(stderr,"\n"); return OK; } int main(int argc, char *argv[]) { int version = 0; int c; int showw = 0; struct parameters* param = NULL; char* in = NULL; char* in_type = NULL; char* in_refine = NULL; RUNP(param = init_param()); param->num_infiles = 0; while (1){ static struct option long_options[] ={ {"showw", 0,0,OPT_SHOWW }, {"set", required_argument,0,OPT_SET}, {"format", required_argument, 0, 'f'}, {"type", required_argument, 0, OPT_ALN_TYPE}, {"gpo", required_argument, 0, OPT_GPO}, {"gpe", required_argument, 0, OPT_GPE}, {"tgpe", required_argument, 0, OPT_TGPE}, {"refine", required_argument, 0, OPT_REFINE}, {"adaptive-budget", no_argument, 0, OPT_ADAPTIVE_BUDGET}, {"ensemble", optional_argument, 0, OPT_ENSEMBLE}, {"ensemble-seed", required_argument, 0, OPT_ENSEMBLE_SEED}, {"min-support", required_argument, 0, OPT_MIN_SUPPORT}, {"save-poar", required_argument, 0, OPT_SAVE_POAR}, {"load-poar", required_argument, 0, OPT_LOAD_POAR}, {"consistency", required_argument, 0, OPT_CONSISTENCY}, {"consistency-weight", required_argument, 0, OPT_CONSISTENCY_WEIGHT}, {"fast", no_argument, 0, OPT_FAST}, {"precise", no_argument, 0, OPT_PRECISE}, {"realign", required_argument, 0, OPT_REALIGN}, {"vsm-amax", required_argument, 0, OPT_VSM_AMAX}, {"nthreads", required_argument, 0, 'n'}, {"input", required_argument, 0, 'i'}, {"infile", required_argument, 0, 'i'}, {"in", required_argument, 0, 'i'}, {"output", required_argument, 0, 'o'}, {"outfile", required_argument, 0, 'o'}, {"out", required_argument, 0, 'o'}, {"help", no_argument,0,'h'}, {"version", no_argument,0,'v'}, {"quiet", 0, 0, 'q'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long_only (argc, argv,"i:o:f:n:hqvV",long_options, &option_index); /* Detect the end of the options. */ if (c == -1){ break; } switch(c) { case OPT_ALN_TYPE: in_type = optarg; break; case OPT_SHOWW: showw = 1; break; case OPT_SET: param->param_set = atoi(optarg); break; case 'f': param->format = optarg; break; case 'n': param->nthreads = atoi(optarg); break; case 'q': param->quiet = 1; break; case OPT_GPO: param->gpo = atof(optarg); break; case OPT_GPE: param->gpe = atof(optarg); break; case OPT_TGPE: param->tgpe = atof(optarg); break; case OPT_REFINE: in_refine = optarg; break; case OPT_ADAPTIVE_BUDGET: param->adaptive_budget = 1; break; case OPT_ENSEMBLE: if(optarg){ param->ensemble = atoi(optarg); }else if(optind < argc && argv[optind][0] != '-'){ param->ensemble = atoi(argv[optind]); optind++; }else{ param->ensemble = 5; } break; case OPT_ENSEMBLE_SEED: param->ensemble_seed = (uint64_t)strtoull(optarg, NULL, 10); break; case OPT_MIN_SUPPORT: param->min_support = atoi(optarg); break; case OPT_SAVE_POAR: param->save_poar = optarg; break; case OPT_LOAD_POAR: param->load_poar = optarg; break; case OPT_CONSISTENCY: param->consistency_anchors = atoi(optarg); break; case OPT_CONSISTENCY_WEIGHT: param->consistency_weight = atof(optarg); break; case OPT_FAST: param->mode = 1; break; case OPT_PRECISE: param->mode = 2; break; case OPT_REALIGN: param->realign = atoi(optarg); break; case OPT_VSM_AMAX: param->vsm_amax = atof(optarg); break; case 'h': param->help_flag = 1; break; case 'v': case 'V': version = 1; break; case 'i': in = optarg; break; case 'o': param->outfile = optarg; break; case '?': free_parameters(param); exit(1); break; default: abort (); } } if(version){ fprintf(stdout,"%s %s\n",KALIGN_PACKAGE_NAME, KALIGN_PACKAGE_VERSION); free_parameters(param); return EXIT_SUCCESS; } if(!param->dump_internal){ if(!param->quiet){ print_kalign_header(); } } if(showw){ print_kalign_warranty(); free_parameters(param); return EXIT_SUCCESS; } if(param->help_flag){ RUN(print_kalign_help(argv)); free_parameters(param); return EXIT_SUCCESS; } if(param->nthreads < 1){ RUN(print_kalign_help(argv)); LOG_MSG("Number of threads has to be >= 1."); free_parameters(param); return EXIT_FAILURE; } param->num_infiles = 0; /* Use "-" to indicate stdin (like samtools/bcftools). * NULL in the infile array signals read_file_stdin() to use stdin. */ if(in){ param->num_infiles++; } if (optind < argc){ param->num_infiles += argc-optind; } if(param->num_infiles == 0){ RUN(print_kalign_help(argv)); LOG_MSG("No input files"); free_parameters(param); return EXIT_SUCCESS; } MMALLOC(param->infile, sizeof(char*) * param->num_infiles); c = 0; if(in){ param->infile[c] = (strcmp(in, "-") == 0) ? NULL : in; c++; } if (optind < argc){ while (optind < argc){ if(strcmp(argv[optind], "-") == 0){ param->infile[c] = NULL; /* stdin */ }else{ param->infile[c] = argv[optind]; } c++; optind++; } } RUN(check_msa_format_string(param->format)); RUN(set_aln_type(in_type, ¶m->type)); RUN(set_refine_mode(in_refine, ¶m->refine)); /* Apply mode presets. Explicit params (already set above) will have * overridden their init_param() defaults, so we only fill in mode * values for fields that are still at their init_param() defaults. */ if(param->mode == 1){ /* fast: no consistency anchors (unless user explicitly set --consistency) */ if(param->consistency_anchors == 5){ /* still at default */ param->consistency_anchors = 0; } }else if(param->mode == 2){ /* precise: ensemble + realign */ if(param->ensemble == 0){ param->ensemble = 3; } if(param->realign == 0){ param->realign = 1; } } /* if(param->chaos){ */ /* if(param->chaos == 1){ */ /* ERROR_MSG("Param chaos need to be bigger than 1 (currently %d)", param->chaos); */ /* } */ /* if(param->chaos > 10){ */ /* ERROR_MSG("Param chaos bigger than 10 (currently %d)",param->chaos); */ /* } */ /* } */ RUN(run_kalign(param)); /* if(devtest){ */ /* for(c = 0; c < param->num_infiles;c++){ */ /* MFREE(param->infile[c]); */ /* } */ /* } */ free_parameters(param); return EXIT_SUCCESS; ERROR: free_parameters(param); return EXIT_FAILURE; } int run_kalign(struct parameters* param) { struct msa* msa = NULL; if(param->num_infiles == 1){ RUN(kalign_read_input(param->infile[0], &msa,param->quiet)); }else{ for(int i = 0; i < param->num_infiles;i++){ RUN(kalign_read_input(param->infile[i], &msa,param->quiet)); } } if(param->load_poar != NULL){ RUN(kalign_consensus_from_poar(msa, param->load_poar, param->min_support > 0 ? param->min_support : 2)); }else if(param->ensemble > 0){ RUN(kalign_ensemble(msa, param->nthreads, param->type, param->ensemble, param->gpo, param->gpe, param->tgpe, param->ensemble_seed, param->min_support, param->save_poar, param->refine, 0.0f, param->vsm_amax, param->realign, -1.0f, param->consistency_anchors, param->consistency_weight)); }else if(param->realign > 0){ RUN(kalign_run_realign(msa, param->nthreads, param->type, param->gpo, param->gpe, param->tgpe, param->refine, param->adaptive_budget, 0.0f, param->vsm_amax, param->realign, -1.0f, param->consistency_anchors, param->consistency_weight)); }else{ RUN(kalign_run_seeded(msa, param->nthreads, param->type, param->gpo, param->gpe, param->tgpe, param->refine, param->adaptive_budget, 0, 0.0f, 0.0f, param->vsm_amax, -1.0f, param->consistency_anchors, param->consistency_weight)); } RUN(kalign_write_msa(msa, param->outfile, param->format)); kalign_free_msa(msa); return OK; ERROR: kalign_free_msa(msa); return FAIL; } int set_aln_type(char* in, int* type ) { int t = 0; if(in){ if(strstr(in,"rna")){ t = KALIGN_TYPE_RNA; }else if(strstr(in,"dna")){ t = KALIGN_TYPE_DNA; }else if(strstr(in,"internal")){ t = KALIGN_TYPE_DNA_INTERNAL; }else if(strstr(in,"protein")){ t = KALIGN_TYPE_PROTEIN; }else if(strstr(in,"divergent")){ t = KALIGN_TYPE_PROTEIN_DIVERGENT; }else if(strstr(in,"pfasum43")){ t = KALIGN_TYPE_PROTEIN_PFASUM43; }else if(strstr(in,"pfasum60")){ t = KALIGN_TYPE_PROTEIN_PFASUM60; }else if(strstr(in,"pfasum")){ t = KALIGN_TYPE_PROTEIN_PFASUM_AUTO; }else{ ERROR_MSG("In %s not recognized.",in); } }else{ t = KALIGN_TYPE_UNDEFINED; } *type = t; return OK; ERROR: return FAIL; } int set_refine_mode(char* in, int* refine) { if(in){ if(strstr(in,"all")){ *refine = KALIGN_REFINE_ALL; }else if(strstr(in,"confident")){ *refine = KALIGN_REFINE_CONFIDENT; }else if(strstr(in,"none")){ *refine = KALIGN_REFINE_NONE; }else{ ERROR_MSG("Refine mode '%s' not recognized. Use: none, all, confident.", in); } } /* When in is NULL, keep the default from init_param() */ return OK; ERROR: return FAIL; } kalign-3.5.1/src/run_reformat.c000066400000000000000000000255631515023132300164310ustar00rootroot00000000000000#include "tldevel.h" #include "tlmisc.h" #include "kalign/kalign.h" #include "version.h" #include "parameters.h" #include #include #include #include #define OPT_RENAME 3 #define OPT_REFORMAT 4 #define OPT_SHOWW 5 #define OPT_CLEAN 15 #define OPT_UNALIGN 16 static int run_reformat(struct parameters* param); static int print_kalign_header(void); static int print_kalign_help(char * argv[]); static int print_kalign_warranty(void); int print_kalign_help(char * argv[]) { const char usage[] = " -i -o "; char* basename = NULL; RUN(tlfilename(argv[0], &basename)); fprintf(stdout,"\nUsage: %s %s\n\n",basename ,usage); fprintf(stdout,"Options:\n\n"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--format","Output format." ,"[Fasta]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--reformat","Reformat existing alignment." ,"[NA]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--changename","Change sequence names to 1 .. N." ,"[NA]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--unalign","Remove gaps and write to fasta." ,"[NA]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--clean","Perform additional checks on alignment." ,"[NA]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"--version (-V/-v)","Prints version." ,"[NA]" ); fprintf(stdout,"\nExamples:\n\n"); fprintf(stdout,"Passing sequences via stdin:\n\n cat input.fa | kalign -f fasta > out.afa\n\n"); fprintf(stdout,"Combining multiple input files:\n\n kalign seqsA.fa seqsB.fa seqsC.fa -f fasta > combined.afa\n\n"); if(basename){ MFREE(basename); } return OK; ERROR: if(basename){ MFREE(basename); } return FAIL; } int print_kalign_warranty(void) { fprintf(stdout,"Disclaimer of Warranty (Apache License, Version 2.0, Section 7):\n"); fprintf(stdout,"\n"); fprintf(stdout,"Unless required by applicable law or agreed to in writing, Licensor\n"); fprintf(stdout,"provides the Work (and each Contributor provides its Contributions)\n"); fprintf(stdout,"on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\n"); fprintf(stdout,"either express or implied, including, without limitation, any\n"); fprintf(stdout,"warranties or conditions of TITLE, NON-INFRINGEMENT,\n"); fprintf(stdout,"MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.\n"); fprintf(stdout,"\n"); fprintf(stdout,"See the COPYING file for the full Apache License, Version 2.0.\n"); return OK; } int print_kalign_header(void) { fprintf(stdout,"\n"); fprintf(stdout,"Kalign (%s)\n", KALIGN_PACKAGE_VERSION); fprintf(stdout,"\n"); fprintf(stdout,"Copyright (C) 2006-2026 Timo Lassmann\n"); fprintf(stdout,"\n"); fprintf(stdout,"Licensed under the Apache License, Version 2.0.\n"); fprintf(stdout,"See the COPYING file or http://www.apache.org/licenses/LICENSE-2.0\n"); fprintf(stdout,"\n"); fprintf(stdout,"Please cite:\n"); /* fprintf(stdout," Kalign 3: multiple sequence alignment of large data sets Timo Lassmann Bioinformatics, btz795, https://doi.org/10.1093/bioinformatics/btz795 */ fprintf(stdout," Lassmann, Timo.\n"); fprintf(stdout," \"Kalign 3: multiple sequence alignment of large data sets.\"\n"); fprintf(stdout," Bioinformatics (2019) \n"); fprintf(stdout," https://doi.org/10.1093/bioinformatics/btz795\n"); fprintf(stdout,"\n"); /*fprintf(stdout," Lassmann, Timo, Oliver Frings, and Erik LL Sonnhammer.\n"); fprintf(stdout," \"Kalign2: high-performance multiple alignment of protein and\n"); fprintf(stdout," nucleotide sequences allowing external features.\"\n"); fprintf(stdout," Nucleic acids research 37.3 (2008): 858-865.\n"); fprintf(stdout,"\n"); fprintf(stdout," Lassmann, Timo, and Erik LL Sonnhammer. \"Kalign–an accurate and\n"); fprintf(stdout," fast multiple sequence alignment algorithm.\"\n BMC bioinformatics 6.1 (2005): 298.\n"); fprintf(stdout,"\n");*/ return OK; } int main(int argc, char *argv[]) { int version = 0; int c; int showw = 0; struct parameters* param = NULL; char* in = NULL; RUNP(param = init_param()); param->num_infiles = 0; while (1){ static struct option long_options[] ={ {"showw", 0,0,OPT_SHOWW }, {"format", required_argument, 0, 'f'}, {"reformat", required_argument, 0, OPT_REFORMAT}, {"changename", 0, 0, OPT_RENAME}, {"unalign", 0, 0, OPT_UNALIGN}, {"clean", 0, 0, OPT_CLEAN}, {"input", required_argument, 0, 'i'}, {"infile", required_argument, 0, 'i'}, {"in", required_argument, 0, 'i'}, {"output", required_argument, 0, 'o'}, {"outfile", required_argument, 0, 'o'}, {"out", required_argument, 0, 'o'}, {"help", no_argument,0,'h'}, {"version", no_argument,0,'v'}, {"quiet", 0, 0, 'q'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long_only (argc, argv,"i:o:f:n:hqvV",long_options, &option_index); /* Detect the end of the options. */ if (c == -1){ break; } switch(c) { case OPT_CLEAN: param->clean = 1; break; case OPT_UNALIGN: param->unalign = 1; break; case OPT_SHOWW: showw = 1; break; case OPT_RENAME: param->rename = 1; break; case 'f': param->format = optarg; break; case 'n': param->nthreads = atoi(optarg); break; case 'q': param->quiet = 1; break; case OPT_REFORMAT: param->format = optarg; param->reformat = 1; break; case 'h': param->help_flag = 1; break; case 'v': case 'V': version = 1; break; case 'i': in = optarg; break; case 'o': param->outfile = optarg; break; case '?': free_parameters(param); exit(1); break; default: abort (); } } if(version){ fprintf(stdout,"%s %s\n",KALIGN_PACKAGE_NAME, KALIGN_PACKAGE_VERSION); free_parameters(param); return EXIT_SUCCESS; } if(!param->dump_internal){ print_kalign_header(); } if(showw){ print_kalign_warranty(); free_parameters(param); return EXIT_SUCCESS; } if(param->help_flag){ RUN(print_kalign_help(argv)); free_parameters(param); return EXIT_SUCCESS; } param->num_infiles = 0; if (!isatty(fileno(stdin))){ param->num_infiles++; } if(in){ param->num_infiles++; } if (optind < argc){ param->num_infiles += argc-optind; } if(param->num_infiles == 0){ RUN(print_kalign_help(argv)); LOG_MSG("No input files"); free_parameters(param); return EXIT_SUCCESS; } //fprintf(stdout,"%d fgiles\n",param->num_infiles); MMALLOC(param->infile, sizeof(char*) * param->num_infiles); c = 0; if (!isatty(fileno(stdin))){ param->infile[c] = NULL; c++; } if(in){ param->infile[c] = in; c++; } if (optind < argc){ while (optind < argc){ param->infile[c] = argv[optind++]; c++; } } RUN(check_msa_format_string(param->format)); if(param->num_infiles == 0){ if (!isatty(fileno(stdin))){ LOG_MSG("Attempting stdin"); param->num_infiles =1; MMALLOC(param->infile, sizeof(char*)); param->infile[0] = NULL; }else{ LOG_MSG("No infiles"); free_parameters(param); return EXIT_SUCCESS; } } RUN(run_reformat(param)); free_parameters(param); return EXIT_SUCCESS; ERROR: free_parameters(param); return EXIT_FAILURE; } int run_reformat(struct parameters* param) { struct msa* msa = NULL; if(param->num_infiles == 1){ kalign_read_input(param->infile[0], &msa,1); }else{ for(int i = 0; i < param->num_infiles;i++){ kalign_read_input(param->infile[i], &msa,1); } } reformat_settings_msa(msa, param->rename, param->unalign); if(param->unalign){ param->format = NULL; } if(param->clean){ RUN(kalign_check_msa(msa,0)); } /* extra checks for input alignments */ /* if(param->clean){ */ /* RUN(run_extra_checks_on_msa(msa)); */ /* } */ /* if(!msa->quiet){ */ /* LOG_MSG("Detected: %d sequences.", msa->numseq); */ /* } */ /* If we just want to reformat end here */ /* if(param->out_format != FORMAT_FA && msa->aligned != ALN_STATUS_ALIGNED){ */ /* ERROR_MSG("Input sequences are not aligned - cannot write to MSA format: %s", param->format); */ /* } */ RUN(kalign_write_msa(msa, param->outfile, param->format)); kalign_free_msa(msa); return OK; ERROR: kalign_free_msa(msa); return FAIL; } kalign-3.5.1/src/version.h.in000066400000000000000000000001761515023132300160160ustar00rootroot00000000000000#cmakedefine KALIGN_PACKAGE_NAME "@CMAKE_PROJECT_NAME@" #cmakedefine KALIGN_PACKAGE_VERSION "@KALIGN_LIBRARY_VERSION_STRING@" kalign-3.5.1/tests/000077500000000000000000000000001515023132300141225ustar00rootroot00000000000000kalign-3.5.1/tests/CMakeLists.txt000066400000000000000000000056071515023132300166720ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.18) # Build library in sub-directories if (NOT TARGET kalign::kalign) add_subdirectory(${PROJECT_SOURCE_DIR}/lib build EXCLUDE_FROM_ALL) endif() # link to installed library if (NOT TARGET kalign::kalign) find_package(kalign) endif() add_executable(largebench large_benchmark.c ) target_link_libraries(largebench tldevel ${PROJECT_NAME}_static) add_executable(kalign_io_test kalign_io_test.c ) target_link_libraries(kalign_io_test kalign::kalign) add_executable(dssim dssim_test.c dssim.c ) target_link_libraries(dssim tldevel kalign::kalign) add_executable(kalign_lib_test kalign_lib_test.c ) target_link_libraries(kalign_lib_test kalign::kalign) add_executable(kalign_cmp_test kalign_cmp_test.c ) target_link_libraries(kalign_cmp_test kalign::kalign) add_executable(kaligncpp kalign_lib_testCXX.cpp) target_link_libraries(kaligncpp kalign::kalign) add_test( NAME C++Lib COMMAND kaligncpp WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) #BB11001.tfa add_test( NAME kalign_itest_BB11001.tfa COMMAND kalign-bin ${CMAKE_CURRENT_SOURCE_DIR}/data/BB11001.tfa WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) #BB11001_EOF.msf add_test( NAME kalign_itest_BB11001_EOF.msf COMMAND kalign-bin ${CMAKE_CURRENT_SOURCE_DIR}/data/BB11001_EOF.msf WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) #BB12006.msf add_test( NAME kalign_itest_BB12006.msf COMMAND kalign-bin ${CMAKE_CURRENT_SOURCE_DIR}/data/BB12006.msf WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) #BB12006.tfa add_test( NAME kalign_itest_BB12006.tfa COMMAND kalign-bin ${CMAKE_CURRENT_SOURCE_DIR}/data/BB12006.tfa WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) #BB30014.msf add_test( NAME kalign_itest_BB30014.msf COMMAND kalign-bin ${CMAKE_CURRENT_SOURCE_DIR}/data/BB30014.msf WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) #BB30014.tfa add_test( NAME kalign_itest_BB30014.tfa COMMAND kalign-bin ${CMAKE_CURRENT_SOURCE_DIR}/data/BB30014.tfa WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_executable(kalign_ensemble_test kalign_ensemble_test.c ) target_link_libraries(kalign_ensemble_test tldevel ${PROJECT_NAME}_static) add_test( NAME kalign_ensemble_test COMMAND kalign_ensemble_test ${CMAKE_CURRENT_SOURCE_DIR}/data/BB11001.tfa WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_executable(kalign_api_test kalign_api_test.c ) target_link_libraries(kalign_api_test tldevel ${PROJECT_NAME}_static) add_test( NAME kalign_api_test COMMAND kalign_api_test ${CMAKE_CURRENT_SOURCE_DIR}/data/BB11001.tfa WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_test( NAME kalign_api_test_large COMMAND kalign_api_test ${CMAKE_CURRENT_SOURCE_DIR}/data/BB30014.tfa WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_test( NAME DSSIM_takes_a_min COMMAND dssim WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) kalign-3.5.1/tests/data/000077500000000000000000000000001515023132300150335ustar00rootroot00000000000000kalign-3.5.1/tests/data/BB11001.msf000066400000000000000000000014601515023132300164110ustar00rootroot00000000000000PileUp MSF: 96 Type: P Check: 7038 .. Name: 1aab_ oo Len: 96 Check: 4681 Weight: 10.0 Name: 1j46_A oo Len: 96 Check: 1914 Weight: 10.0 Name: 1k99_A oo Len: 96 Check: 8221 Weight: 10.0 Name: 2lef_A oo Len: 96 Check: 2222 Weight: 10.0 // 1aab_ ...GKGDPKK PRGKMSSYAF FVQTSREEHK KKHPDASVNF SEFSKKCSER 1j46_A ......MQDR VKRPMNAFIV WSRDQRRKMA LENP..RMRN SEISKQLGYQ 1k99_A MKKLKKHPDF PKKPLTPYFR FFMEKRAKYA KLHP..EMSN LDLTKILSKK 2lef_A ........MH IKKPLNAFML YMKEMRANVV AEST..LKES AAINQILGRR 1aab_ WKTMSAKEKG KFEDMAKADK ARYEREMKTY IPPKGE.... ...... 1j46_A WKMLTEAEKW PFFQEAQKLQ AMHREKYPNY KYRPRRKAKM LPK... 1k99_A YKELPEKKKM KYIQDFQREK QEFERNLARF REDHPDLIQN AKK... 2lef_A WHALSREEQA KYYELARKER QLHMQLYPGW SARDNYGKKK KRKREK kalign-3.5.1/tests/data/BB11001.tfa000066400000000000000000000006001515023132300163710ustar00rootroot00000000000000>1aab_ GKGDPKKPRGKMSSYAFFVQTSREEHKKKHPDASVNFSEFSKKCSERWKT MSAKEKGKFEDMAKADKARYEREMKTYIPPKGE >1j46_A MQDRVKRPMNAFIVWSRDQRRKMALENPRMRNSEISKQLGYQWKMLTEAE KWPFFQEAQKLQAMHREKYPNYKYRPRRKAKMLPK >1k99_A MKKLKKHPDFPKKPLTPYFRFFMEKRAKYAKLHPEMSNLDLTKILSKKYK ELPEKKKMKYIQDFQREKQEFERNLARFREDHPDLIQNAKK >2lef_A MHIKKPLNAFMLYMKEMRANVVAESTLKESAAINQILGRRWHALSREEQA KYYELARKERQLHMQLYPGWSARDNYGKKKKRKREK kalign-3.5.1/tests/data/BB11001_EOF.msf000066400000000000000000000014511515023132300171020ustar00rootroot00000000000000PileUp MSF: 96 Type: P Check: 7038 .. Name: 1aab_ oo Len: 96 Check: 4681 Weight: 10.0 Name: 1j46_A oo Len: 96 Check: 1914 Weight: 10.0 Name: 1k99_A oo Len: 96 Check: 8221 Weight: 10.0 Name: 2lef_A oo Len: 96 Check: 2222 Weight: 10.0 // 1aab_ ...GKGDPKK PRGKMSSYAF FVQTSREEHK KKHPDASVNF SEFSKKCSER 1j46_A ......MQDR VKRPMNAFIV WSRDQRRKMA LENP..RMRN SEISKQLGYQ 1k99_A MKKLKKHPDF PKKPLTPYFR FFMEKRAKYA KLHP..EMSN LDLTKILSKK 2lef_A ........MH IKKPLNAFML YMKEMRANVV AEST..LKES AAINQILGRR 1aab_ WKTMSAKEKG KFEDMAKADK ARYEREMKTY IPPKGE.... ...... 1j46_A WKMLTEAEKW PFFQEAQKLQ AMHREKYPNY KYRPRRKAKM LPK... 1k99_A YKELPEKKKM KYIQDFQREK QEFERNLARF REDHPDLIQN AKK... 2lef_A WHALSREEQA KYYELARKER QLHMQLYPGW SARDNYGKKK KRKREKkalign-3.5.1/tests/data/BB12006.msf000066400000000000000000000031731515023132300164220ustar00rootroot00000000000000PileUp MSF: 245 Type: P Check: 59 .. Name: 1al2_ad oo Len: 245 Check: 2091 Weight: 10.0 Name: 1bbt_ac oo Len: 245 Check: 8510 Weight: 10.0 Name: 1bev_ac oo Len: 245 Check: 6172 Weight: 10.0 Name: 1mec_ac oo Len: 245 Check: 3286 Weight: 10.0 // 1al2_ad .GLPVMNTPG SNQYLTADNF QSPCALPEFD VTPPIDIPGE VKNMMELAEI 1bbt_ac GIFPVACSDG YGGLVTTDPK TADPVYGKVF NPPRNQLPGR FTNLLDVAEA 1bev_ac .GLPTKPGPG SYQFMTTDED CSPCILPDFQ PTPEIFIPGK VNNLLEIAQV 1mec_ac SPIPVTIREH AGTWYSTLPD STVPIYGKTP VAPANYMVGE YKDFLEIAQI 1al2_ad D.TMIPFDLS ATKKNTMEMY RVRLSDKPHT DDPILCLSLS PASDPRLSHT 1bbt_ac CPTFLR.... ......FEGG VPYVTTKTDS DRVLAQFDMS LAA.KHMSNT 1bev_ac E.SILEANN. REGVEGVERY VIPVSVQDAL DAQIYALRLE LGGSGPLSSS 1mec_ac P.TFIG.... .NKMPNAVPY IEASNTAVK. TQPLAVYQVT LSC.SCLANT 1al2_ad MLGEILNYYT HWAGSLKFTF LFCGSMMATG KLLVSYAPPG ADPPKKRKEA 1bbt_ac FLAGLAQYYT QYSGTINLHF MFTGPTDAKA RYMVAYAPPG MEPPKTPEAA 1bev_ac LLGTLAKHYT QWSGSVEITC MFTGTFMTTG KVLLAYTPPG GDMPRNREEA 1mec_ac FLAALSRNFA QYRGSLVYTF VFTGTAMMKG KFLIAYTPPG AGKPTSRDQA 1al2_ad MLGTHVIWDI GLQSSCTMVV PWISNTTYRQ TIDD.....S FTEGGYISVF 1bbt_ac AHCIHAEWDT GLNSKFTFSI PYLSAADYTY TASDVAE..T TNVQGWVCLF 1bev_ac MLGTHVIWDF GLQSSITLVI PWISASHFRG VSNDDVLNYQ YYAAGHVTIW 1mec_ac MQATYAIWDL GLNSSYSFTV PFISPTHFRM VGTDQAN..I TNVDGWVTVW 1al2_ad YQTRIVVPLS TPREMDILGF VSACNDFSVR LLRDTTHIEQ KA... 1bbt_ac QITHGK.... .ADGDALVVL ASAGKDFELR LPVDARAE.. ..... 1bev_ac YQTNMVIPPG FPNTAGIIMM IAAQPNFSFR IQKDREDMTQ TAILQ 1mec_ac QLTPLTYPPG CPTSAKILTM VSAGKDFSLK MPISPAPWSP Q.... kalign-3.5.1/tests/data/BB12006.tfa000066400000000000000000000017301515023132300164040ustar00rootroot00000000000000>1al2_ad GLPVMNTPGSNQYLTADNFQSPCALPEFDVTPPIDIPGEVKNMMELAEID TMIPFDLSATKKNTMEMYRVRLSDKPHTDDPILCLSLSPASDPRLSHTML GEILNYYTHWAGSLKFTFLFCGSMMATGKLLVSYAPPGADPPKKRKEAML GTHVIWDIGLQSSCTMVVPWISNTTYRQTIDDSFTEGGYISVFYQTRIVV PLSTPREMDILGFVSACNDFSVRLLRDTTHIEQKA >1bbt_ac GIFPVACSDGYGGLVTTDPKTADPVYGKVFNPPRNQLPGRFTNLLDVAEA CPTFLRFEGGVPYVTTKTDSDRVLAQFDMSLAAKHMSNTFLAGLAQYYTQ YSGTINLHFMFTGPTDAKARYMVAYAPPGMEPPKTPEAAAHCIHAEWDTG LNSKFTFSIPYLSAADYTYTASDVAETTNVQGWVCLFQITHGKADGDALV VLASAGKDFELRLPVDARAE >1bev_ac GLPTKPGPGSYQFMTTDEDCSPCILPDFQPTPEIFIPGKVNNLLEIAQVE SILEANNREGVEGVERYVIPVSVQDALDAQIYALRLELGGSGPLSSSLLG TLAKHYTQWSGSVEITCMFTGTFMTTGKVLLAYTPPGGDMPRNREEAMLG THVIWDFGLQSSITLVIPWISASHFRGVSNDDVLNYQYYAAGHVTIWYQT NMVIPPGFPNTAGIIMMIAAQPNFSFRIQKDREDMTQTAILQ >1mec_ac SPIPVTIREHAGTWYSTLPDSTVPIYGKTPVAPANYMVGEYKDFLEIAQI PTFIGNKMPNAVPYIEASNTAVKTQPLAVYQVTLSCSCLANTFLAALSRN FAQYRGSLVYTFVFTGTAMMKGKFLIAYTPPGAGKPTSRDQAMQATYAIW DLGLNSSYSFTVPFISPTHFRMVGTDQANITNVDGWVTVWQLTPLTYPPG CPTSAKILTMVSAGKDFSLKMPISPAPWSPQ kalign-3.5.1/tests/data/BB30014.msf000066400000000000000000000544151515023132300164260ustar00rootroot00000000000000PileUp MSF: 307 Type: P Check: 2883 .. Name: 1ags_A oo Len: 307 Check: 2542 Weight: 10.0 Name: GTA1_BOVIN oo Len: 307 Check: 1045 Weight: 10.0 Name: GTA1_MOUSE oo Len: 307 Check: 2301 Weight: 10.0 Name: GTC1_RAT oo Len: 307 Check: 6389 Weight: 10.0 Name: GTC_RABIT oo Len: 307 Check: 2138 Weight: 10.0 Name: GTA1_RABIT oo Len: 307 Check: 6143 Weight: 10.0 Name: GTA1_CAVPO oo Len: 307 Check: 2879 Weight: 10.0 Name: GTA3_RAT oo Len: 307 Check: 3064 Weight: 10.0 Name: GTA3_CHICK oo Len: 307 Check: 6404 Weight: 10.0 Name: GTA2_CHICK oo Len: 307 Check: 3444 Weight: 10.0 Name: GTA1_CHICK oo Len: 307 Check: 4246 Weight: 10.0 Name: GTA1_ANTST oo Len: 307 Check: 2040 Weight: 10.0 Name: GTA4_HUMAN oo Len: 307 Check: 7381 Weight: 10.0 Name: 1oe7_A oo Len: 307 Check: 3128 Weight: 10.0 Name: GTP1_BUFBU oo Len: 307 Check: 7779 Weight: 10.0 Name: GT28_SCHJA oo Len: 307 Check: 7618 Weight: 10.0 Name: GTS1_ASCSU oo Len: 307 Check: 6708 Weight: 10.0 Name: GTS9_CAEEL oo Len: 307 Check: 3425 Weight: 10.0 Name: GTS3_CAEEL oo Len: 307 Check: 9066 Weight: 10.0 Name: GTS5_CAEEL oo Len: 307 Check: 8451 Weight: 10.0 Name: GTS6_CAEEL oo Len: 307 Check: 245 Weight: 10.0 Name: GTS4_CAEEL oo Len: 307 Check: 1081 Weight: 10.0 Name: GTS2_CAEEL oo Len: 307 Check: 4110 Weight: 10.0 Name: GTS1_CAEEL oo Len: 307 Check: 1820 Weight: 10.0 Name: GTS_ANOGA oo Len: 307 Check: 660 Weight: 10.0 Name: GTS2_MANSE oo Len: 307 Check: 5117 Weight: 10.0 Name: GT1_ONCVO oo Len: 307 Check: 728 Weight: 10.0 Name: SC11_OMMSL oo Len: 307 Check: 7004 Weight: 10.0 Name: SC2_OCTDO oo Len: 307 Check: 9708 Weight: 10.0 Name: 1aw9_ oo Len: 307 Check: 4565 Weight: 10.0 Name: GTH3_ARATH oo Len: 307 Check: 2928 Weight: 10.0 Name: GTH7_ARATH oo Len: 307 Check: 2013 Weight: 10.0 Name: GTH6_ARATH oo Len: 307 Check: 8296 Weight: 10.0 Name: GTH_SILCU oo Len: 307 Check: 9759 Weight: 10.0 Name: GTH1_ARATH oo Len: 307 Check: 9980 Weight: 10.0 Name: GTH4_ARATH oo Len: 307 Check: 9350 Weight: 10.0 Name: GTH4_MAIZE oo Len: 307 Check: 3503 Weight: 10.0 Name: GTH1_MAIZE oo Len: 307 Check: 2572 Weight: 10.0 Name: GTH1_WHEAT oo Len: 307 Check: 9368 Weight: 10.0 Name: GTH5_ARATH oo Len: 307 Check: 9671 Weight: 10.0 Name: 1eem_A oo Len: 307 Check: 6005 Weight: 10.0 Name: GTO1_MOUSE oo Len: 307 Check: 911 Weight: 10.0 Name: GTO2_HUMAN oo Len: 307 Check: 9751 Weight: 10.0 Name: YKJ3_CAEEL oo Len: 307 Check: 7547 Weight: 10.0 // 1ags_A .......... .......... .......... ....AEKPKL H.YFNARGRM GTA1_BOVIN .......... .......... .......... ....AGKPTL H.YFNGRGRM GTA1_MOUSE .......... .......... .......... ....AGKPVL H.YFNARGRM GTC1_RAT .......... .......... .......... ....PGKPVL H.YFDGRGRM GTC_RABIT .......... .......... .......... ....AGKPKL H.YFNARGRM GTA1_RABIT .......... .......... .......... ...MARKPLL H.YFNGRGRM GTA1_CAVPO .......... .......... .......... ....SGKPVL H.YFNVQGRM GTA3_RAT .......... .......... .......... ...MEVKPKL Y.YFQGRGRM GTA3_CHICK .......... .......... .......... ....AAKPVL Y.YFNGRGKM GTA2_CHICK .......... .......... .......... ...MAGKPKL H.YTRGRGKM GTA1_CHICK .......... .......... .......... ...MSGKPVL H.YANTRGRM GTA1_ANTST .......... .......... .......... ...MAGEQNI K.YFNIKGRM GTA4_HUMAN .......... .......... .......... ...MAARPKL H.YPNGRGRM 1oe7_A .......... .......... .......... .....DHIKV I.YFNGRGRA GTP1_BUFBU .......... .......... .......... .....PEYTI I.YFNARGRC GT28_SCHJA .......... .......... .......... .......VKL I.YFNGRGRA GTS1_ASCSU .......... .......... .......... .....PQYKL T.YFDIRGLG GTS9_CAEEL .......... .......... .......... ....MVSYKL I.YFQSRGNG GTS3_CAEEL .......... .......... .......... ....MVHYKL T.YFNARGLA GTS5_CAEEL .......... .......... .......... ....MVSYKL T.YFNGRGAG GTS6_CAEEL .......... .......... .......... ....MVHYKL V.YFPLRARA GTS4_CAEEL .......... .......... .......... ....MPNYKL L.YFDARALA GTS2_CAEEL .......... .......... .......... ....MVHYKL M.CFDVRGLG GTS1_CAEEL .......... .......... .......... ....MPHFKF Y.YFDVRGRG GTS_ANOGA .......... .........L SSSSISRSSL KCNIMPDYKV Y.YFNVKALG GTS2_MANSE .......... .......... .......... ....MPKVVF H.YFGAKGWA GT1_ONCVO FITMNFVVEA ASSNANQAIT SENSIKPKGK LQPQMEKYTL T.YFNGRGRA SC11_OMMSL .......... .......... .......... ....MPSYTL Y.YFNGRGRA SC2_OCTDO .......... .......... .......... ....MPSYTL N.YFNHRGRA 1aw9_ .......... .......... .......... .....APLKL Y.GMPLSPNV GTH3_ARATH .......... .......... .......... ......VLTI Y..APLFASS GTH7_ARATH .......... .......... .......... .....MVVKV Y.GQIKAANP GTH6_ARATH .......... .......... .......... ....MASIKV H.GVPMSTAT GTH_SILCU .......... .......... .......... ......TIKV H.GNPRSTAT GTH1_ARATH .......... .......... .......... ....MAGIKV F.GHPASTAT GTH4_ARATH .......... .......... .......... .....AGIKV F.GHPASIAT GTH4_MAIZE .......... .......... .......... ...ATPAVKV Y.GWAISPFV GTH1_MAIZE .......... .......... .......... .....APMKL Y.GAVMSWNL GTH1_WHEAT .......... .......... .......... ....MSPVKV F.GHPMLTNV GTH5_ARATH .......... .......... .......... ....MVTVKL Y.GMAYSTCT 1eem_A .......... ........SA RSLGKGSAPP GPVPEGSIRI Y.SMRFCPFA GTO1_MOUSE .......... ....MSGESS RSLGKGSAPP GPVPEGQIRV Y.SMRFCPFA GTO2_HUMAN .......... ....MSGDAT RTLGKGSQPP GPVPEGLIRI Y.SMRFCPYS YKJ3_CAEEL .......... .......... MTVLAGVNSK IVKNGCWNHS YLQHAILPVA 1ags_A ESTRWLLAAA GVEFEEKFIK SAEDL...DK LRNDGYLMFQ QVPMVEIDG. GTA1_BOVIN ECIRWLLAAA GVEFEEKFIE KPEDL...DK LKNDGSLMFQ QVPMVEIDG. GTA1_MOUSE ECIRWLLAAA GVEFEEKFIQ SPEDL...EK LKKDGNLMFD QVPMVEIDG. GTC1_RAT EPIRWLLAAA GVEFEEQFLK TRDDL...AR LRNDGSLMFQ QVPMVEIDG. GTC_RABIT ESIRWLLTAA GVEFEEKCMK TREDL...EK LRKDGVLMFQ QVPMVEIDG. GTA1_RABIT ESIRWLLAAA GEEFDEKFME TAEDL...DK LRNDGSLMYQ QVPMVEIDG. GTA1_CAVPO ESIRWLLAAA GVEFEEKLIM CQEDL...DK LKNDGLLMFQ QVPMVEMDG. GTA3_RAT ESIRWLLATA GVEFEEEFLE TREQY...EK LQKDGCLLFG QVPLVEIDG. GTA3_CHICK ESIRWLLAAA GVEFEEVFLE TREQY...EK LLQSGILMFQ QVPMVEIDG. GTA2_CHICK ESIRWLLAAA GVEFEEEFIE KKEDL...EK LRNDGSLLFQ QVPMVEIDG. GTA1_CHICK ESVRWLLAAA GVEFEEKFLE KKEDL...QK LKSDGSLLFQ QVPMVEIDG. GTA1_ANTST EAIRWLLAVA GVEFEEKFFE TKEQL...QK LKET.VLLFQ QVPMVEIDG. GTA4_HUMAN ESVRWVLAAA GVEFDEEFLE TKEQL...YK LQDGNHLLFQ QVPMVEIDG. 1oe7_A ESIRMTLVAA GVNYEDERIS FQDW....PK IKP..TIPGG RLPAVKITDN GTP1_BUFBU EAMRMLMADQ GAQWKEEVVT SDDWQ..KGD LKK..AAVYG QLPGFKDGD. GT28_SCHJA EPIRMILVAA GVEFEDERIE FQDW....PK IKP..TIPGG RLPIVKITDK GTS1_ASCSU EGARLIFHQA GVKFEDNRLK REDW....PA LKP..KTPFG QLPLLEVDG. GTS9_CAEEL EIARQVFAFA GQEFIDERIS KEQW....AE IKN..MTPFG QVPVLEVDG. GTS3_CAEEL EISRQLFHMA GVEFEDERIN EEKF....SQ LKP..TFPSG QVPILCIDG. GTS5_CAEEL EVSRQIFAYA GQQYEDNRVT QEQW....PA LKETCAAPFG QLPFLEVDG. GTS6_CAEEL EIARQIFAYA GQDYSEENLS FEQW....PA RKN..NTPFG QLPILEVDG. GTS4_CAEEL EPIRIMFAML NVPYEDYRVS VEEW....SK LKP..TTPFG QLPILQVDG. GTS2_CAEEL EVIRQLFYLG DVSFEDFRVS REEF....KS LKS..NLPSG QLPVLEIDG. GTS1_CAEEL EAIRLLFHLA DEKFDDERFG MEQW....GV LKS..EMPLG QVPVLEIDG. GTS_ANOGA EPLRFLLSYG NLPFDDVRIT REEW....PA LKP..TMPMR QMPVLEVDG. GTS2_MANSE RP.TMLLAYG GQEFEDHRVE YEQW....PE FKP..NTPFG QMPVLEIDG. GT1_ONCVO EVIRLLFALA NVSYEDNRIT RDEW....KY LKP..RTPFG HVPMLNVSG. SC11_OMMSL EICRMLFAVA SVQYQDKRIE LAEW....TQ FKT..KMPCH MLPILEIDT. SC2_OCTDO EICRMLFAAA GVQYNDRRIE TSEW....SN MRS..KMPCS MMPMLDIDN. 1aw9_ VRVATVLNEK GLDFEIVPVD LTTGAHKQPD FLA..LNPFG QIPALVDGD. GTH3_ARATH KRAVVTLVEK GVSFETVNVD LMKGEQRQPE YLA..IQPFG KIPVLVDGD. GTH7_ARATH QRVLLCFLEK DIEFEVIHVD LDKLEQKKPQ HLL..RQPFG QVPAIEDGY. GTH6_ARATH MRVLATLYEK DLQFELIPVD MRAGAHKQEA HLA..LNPFG QIPALEDGD. GTH_SILCU QRVLVALYEK HLEFEFVPID MGAGGHKQPS YLA..LNPFG QVPALEDGE. GTH1_ARATH RRVLIALHEK NVDFEFVHVE LKDGEHKKEP FIL..RNPFG KVPAFEDGD. GTH4_ARATH RRVLIALHEK NLDFELVHVE LKDGEHKKEP FLS..RNPFG QVPAFEDGD. GTH4_MAIZE SRALLALEEA GVDYELVPMS RQDGDHRRPE HLA..RNPFG KVPVLEDGD. GTH1_MAIZE TRCATALEEA GSDYEIVPIN FATAEHKSPE HLV..RNPFG QVPALQDGD. GTH1_WHEAT ARVLLFLEEV GAEYELVPMD FVAGEHKRPQ HVQ..LNPFA KMPGFQDGD. GTH5_ARATH KRVYTTAKEI GVDVKIVPVD LMKGEHKEPA YLDN.YHPFG VIPVLEDEDG 1eem_A ERTRLVLKAK GIRHEVININ LKNK...PEW FFK..KNPFG LVPVLENSQG GTO1_MOUSE QRTLMVLKAK GIRHEVININ LKNK...PEW FFE..KNPLG LVPVLENSQG GTO2_HUMAN HRTRLVLKAK DIRHEVVNIN LRNK...PEW YYT..KHPFG HIPVLETSQC YKJ3_CAEEL QRALIYASVK NIPSDVINVH LQEKP...DW YFS..KHYKG QVPTLEHDEG 1ags_A ....MKLVQT RAILNYIASK YN.......L YRKDI...KE KALIDMYIEG GTA1_BOVIN ....MKLVQT RAILNYIATK YN.......L YGKDM...KE RALIDMYSEG GTA1_MOUSE ....MKLAQT RAILNYIATK YD.......L YGKDM...KE RALIDMYSEG GTC1_RAT ....MKLVQT RAILNYIATK YN.......L YGKDM...KE RALIDMYAEG GTC_RABIT ....MKLVQT RAIFNYIADK HN.......L YGKDI...KE RALIDMYTEG GTA1_RABIT ....MKLVQT RAILNYVANK HN.......L YGKDM...KE RALIDMYTEG GTA1_CAVPO ....MKMVQS RAILNYIATK YN.......L YGKDT...KE RLLIDMYTEG GTA3_RAT ....MLLTQT RAILSYLAAK YN.......L YGKDL...KE RVRIDMYADG GTA3_CHICK ....MKLVQT RAILNYIAGK YN.......L YGKDL...KE RALIDMYVGG GTA2_CHICK ....MKMVQS RAILCYIAGK YN.......L YGKDL...KE RAWIDMYVEG GTA1_CHICK ....MKMVQT RAILNYIAGK YN.......L YGKDL...KE RALIDMYVEG GTA1_ANTST ....MKLVQT RAILHYIAEK YN.......L LGKDM...KE HAQIIMYSEG GTA4_HUMAN ....MKLVQT RSILHYIADK HN.......L FGKNL...KE RTLIDMYVEG 1oe7_A HGHVKWMVES LAIARYMAKK HH.......M MGGTE...EE YYNVEKLIGQ GTP1_BUFBU ....FTLYQS NAMLRLLARN HD.......L YGKNP...RE ASLIDMVNDG GT28_SCHJA RGDVKTMSES LAIARFIARK HN.......M MGDTD...DE YYIIEKMIGQ GTS1_ASCSU ....EVLAQS AAIYRYLGRQ FG.......L AGKTP...ME EAQVDSIFDQ GTS9_CAEEL ....RQLAQS ITIVRYLSKQ FG.......I SGKSS...WE EAQVDALGDQ GTS3_CAEEL ....AQFSQS TAIARYLARK FG.......F VGQTA...EE ELQADEVVDT GTS5_CAEEL ....KKLAQS HAIARFLARE FK.......L NGKTA...WE EAQVNSLADQ GTS6_CAEEL ....KPLGQS YAIARYLARE FG.......I AGQND...TE AAEVDAIADQ GTS4_CAEEL ....EQFGQS MSITRYLARK FG.......L AGKTA...EE EAYADSIVDQ GTS2_CAEEL ....VMISQS ASIGRFLARQ YG.......Y SGKTP...TE EMQVDSIIDL GTS1_CAEEL ....VKISQT TAIARYLGHQ FH.......R AGTNA...VD CARLDMIAEV GTS_ANOGA ....KRVHQS LAMCRYVAKQ IN.......L AGDNP...LE ALQIDAIVDT GTS2_MANSE ....KKYAQS LAISRYLGRK YG.......L AGNDI...EE DFEIDQIVDF GT1_ONCVO ....NVLGES HAIELLLGGR FG.......L LGTND...WE EAKIMAVVLN SC11_OMMSL ...ETQVPQS MAISRYLARE FG.......F YGKNN...MD MFKVDCLCDS SC2_OCTDO ...RHQIPQT MAIARYLARE FG.......F HGKNN...ME MARVEYISDC 1aw9_ ....EVLFES RAINRYIASK YASEG..TDL LPATA...SA AKL.EVWLEV GTH3_ARATH ....YKIFES RAIMRYIAEK YRSQG..PDL LGKTI...EE RGQVEQWLDV GTH7_ARATH ....LKLFES RAIARYYATK YADQG..TDL LGKTL...EG RAIVDQWVEV GTH6_ARATH ....LTLFES RAITQYLAEE YSEKG..EKL ISQDCK..KV KATTNVWLQV GTH_SILCU ....IKLFES RAITKYLAYT HDHQNEGTSL IHKEK...HE MAAQLVWEEV GTH1_ARATH ....FKIFES RAITQYIAHE FSDKG..NNL LSTG....KD MAIIAMGIEI GTH4_ARATH ....LKLFES RAITQYIAHR YENQGT..NL LQTDSKNISQ YAIMAIGMQV GTH4_MAIZE ....LTLFES RAIARHVLRK HKP.....EL LGGGRL..EQ TAMVDVWLEV GTH1_MAIZE ....LYLFES RAICKYAARK NKP.....EL LREGNL..EE AAMVDVWIEV GTH1_WHEAT ....LVLFES RAIAKYILRK YGGTAG.LDL LGENSGI.EE LAMVDVWTEV GTH5_ARATH ....TKIYES RAISRYLVAK YGKGS...SL LPSPSDP.KA YGLFEQAASV 1eem_A ....QLIYES AITCEYLDEA YPGKK....L LPDDP...YE KACQKMILEL GTO1_MOUSE ....HLVTES VITCEYLDEA YPEK....KL FPDDP...YK KARQKMTLES GTO2_HUMAN ....QLIYES VIACEYLDDA YPGR....KL FPYDP...YE RARQKMLLEL YKJ3_CAEEL K...KHVIES AVIPEYLDDI YPET....RI LPTDP...YE KVQQKLLLDR 1ags_A .IADLGEMIL LLPFTQ.... ......PEEQ DAKLALIKEK IKNRYFPAFE GTA1_BOVIN .VADLGEMIM HFPLCP.... ......PAEK DAKLTLIREK TTNRYLPAFE GTA1_MOUSE .ILDLTEMIG QLVLCP.... ......PDQR EAKTALAKDR TKNRYLPAFE GTC1_RAT .VADLDEIVL HYPYIP.... ......PGEK EASLAKIKDK ARNRYFPAFE GTC_RABIT .IVDLNELIL TRPFLP.... ......PEEQ EAKLAQIKDK AKNRYFPAFE GTA1_RABIT .VADLYELVL LLPLCP.... ......PEQK DAKVDFIKEK IRTRYFPAFE GTA1_CAVPO .MTDLYELFF KVILAP.... ......PEEK DAAKSLIKDR AKNRFLPAFE GTA3_RAT .TQDLMMMII GAPFKA.... ......PQEK EESLALAVKR AKNRYFPVFE GTA3_CHICK .TDDLMGFLL SFPFLS.... ......AEDK VKQCAFVVEK ATSRYFPAYE GTA2_CHICK .TTDLMGMIM ALPFQA.... ......ADVK EKNIALITER ATTRYFPVYE GTA1_CHICK .LADLYELIM MNVVQP.... ......ADKK EEHLANALDK AANRYFPVFE GTA1_ANTST .TMDLMELIM IYPFLK.... ......GEEK KQRLVEIANK AKGRYFPAFE GTA4_HUMAN .TLDLLELLI MHPFLK.... ......PDDQ QKEVVNMAQK AIIRYFPVFE 1oe7_A .AEDLEHEYY KTLMKP.... ......EEEK QKIIKEILNG KVPVLLDIIC GTP1_BUFBU .VEDLRLKYL KMIYQN.... .......... YENGKDDYVK ALPTNLGHFE GT28_SCHJA .VEDVESEYH KTLIKP.... ......PEEK EKISKEILNG KVPILLQAIC GTS1_ASCSU .FKDFMAELR PCFRVLAGFE ......EGDK EKVLKEVAVP ARDKHLPLLE GTS9_CAEEL .FKDYRVEAR PFFRAKMGFS ......DGDV DQLYKDLFVP AFNKMYSIFT GTS3_CAEEL .FKDFIESFR KFVIAVLSGE S.....EEIL KNIREEVIKP AVKTYTAYLK GTS5_CAEEL .YKDYSSEAR PYFYAVMGFG ......PGDV ETLKKDIFLP AFEKFYGFLV GTS6_CAEEL .FKDYLNDVS PYLTVLAGFK ......PGDK DQLRTDVFVP AFKKNFEFFE GTS4_CAEEL .YRDFIFFFR QFTSSVFYGS D.....ADHI NKVRFEVVEP ARDDFLAIIN GTS2_CAEEL .FKDFMLTFR QFFFAVIHGY P.....EYEK ERMKRDIVKP AIKNYFIALN GTS1_CAEEL .IQEFMSSSG MGKFSRVLLG M....IQANK EQFFKENVLP DVEKYAPIVE GTS_ANOGA .INDFRLKIA IVAYEPDD.. .......MVK EKKMVTLNNE VIPFYLTKLN GTS2_MANSE .VNDIRASAA SVEYEQDAAN .........K EVKHEENMKN KYPFQLNKLS GT1_ONCVO .IDELFQKLI PWTHEKNTTK .........K AELFRNLSES DVMPFLGRYE SC11_OMMSL .LFELFNDYM AVYNEKDAA. .........K KTELQKRFQN TCLRVLPYME SC2_OCTDO .FYDILDDYL RMYQDDNCRM MFQRSGDRNG SSEKRTRYQE TLRRILPFME 1aw9_ ESHHFYPNAS PLVFQLLVRP LLG....GAP DAAVVDKHAE QLAKVLDVYE GTH3_ARATH EATSYHPPLL ALTLNIVFAP LMG....FPA DEKVIKESEE KLAEVLDVYE GTH7_ARATH ENNYFYAVAL PLVMNVVFKP KSG....KPC DVALVEELKV KFDKVLDVYE GTH6_ARATH EGQQFDPNAS KLAFERVFKG MFG....MTT DPAAVQELEG KLQKVLDVYE GTH_SILCU EAHQFDPVAS KLAWELVFKG IFG....MQT DTTVVEENEA KLAKVLDVYE GTH1_ARATH ESHEFDPVGS KLVWEQVLKP LYG....MTT DKTVVEEEEA KLAKVLDVYE GTH4_ARATH EDHQFDPVAS KLAFEQIFKS IYG....LTT DEAVVAEEEA KLAKVLDVYE GTH4_MAIZE EAHQLSPPAI AIVVECVFAP FLG....RER NQAVVDENVE KLKKVLEVYE GTH1_MAIZE EANQYTAALN PILFQVLISP MLG....GTT DQKVVDENLE KLKKVLEVYE GTH1_WHEAT EAQQYYPAIS PVVFECIIIP FIIPGGGAAP NQTVVDESLE RLRGVLGIYE GTH5_ARATH EYSSFDPPAS SLAYERVFAG MRG....LKT NEELAKKYVD TLNAKMDGYE 1eem_A F.SKVPSLVG SFIRS..... .........Q NKEDYAGLKE EFRKEFTKLE GTO1_MOUSE F.SKVPPLIA SFVRS..... .........K RKEDSPNLRE ALENEFKKLE GTO2_HUMAN F.CKVPHLTK ECLVA..... ........LR CGRECTNLKA ALRQEFSNLE YKJ3_CAEEL ISGQVSPAFY GVVQA..... ........VK NPDLREEKFA DIKKAYDNAE 1ags_A KVLKSHG..Q DYLVGNKL.S RADIHLVELL YYVEELDS.. .........S GTA1_BOVIN NVLKSHG..Q DYLVGNKL.S RADIHLVELL YYVEELDP.. .........S GTA1_MOUSE KVLKSHG..Q DYLVGNRL.T RVDIHLLEVL LYVEEFDA.. .........S GTC1_RAT KVLKSHG..Q DYLVGNRL.S RADVYLVQVL YHVEELDP.. .........S GTC_RABIT KVLKSHG..Q DYLVGNKL.S KADILLVELL YNVEELNP.. .........G GTA1_RABIT KVLKSHG..Q DYLVGNRL.S KADILLVELL YNVEELDP.. .........S GTA1_CAVPO KVLKSHG..Q GYLVGNKL.S KADILLTELL YMVEEFDA.. .........S GTA3_RAT KILKDHG..E AFLVGNQL.S WADIQLLEAI LMVEEVSA.. .........P GTA3_CHICK KVLKDHG..Q DFLVGNRL.S WADIHLLEAI LMVEEKKS.. .........D GTA2_CHICK KALKDHG..Q DYLVGNKL.S WADIHLLEAI LMTEELKS.. .........D GTA1_CHICK KVLKDHG..H DFLVGNKL.S RADVHLLETI LAVEESKP.. .........D GTA1_ANTST NVLKTHG..Q NFLVGNQL.S MADVQLFEAI LMVEEKVP.. .........D GTA4_HUMAN KILRGHG..Q SFLVGNQL.S LADVILLQTI LALEEKIP.. .........N 1oe7_A ESLKAST..G KLAVGDKV.T LADLVLIAVI DHVTDLDK.. ........EF GTP1_BUFBU RLLASNNEGK GFVVGAHI.S FADYNLVDLL HNHLVLAP.. .........D GT28_SCHJA ETLKEST..G NLTVGDKV.T LADVVLIASI DHITDLDK.. ........EF GTS1_ASCSU KFLAKSG..S EYMVGKSV.T WADLVITDSL ASWESLIP.. .........D GTS9_CAEEL ESLKSSG..S GFLVGDSL.T WMDLAIAQHS ADLLEADG.. .........K GTS3_CAEEL AILEKSS..S GYLVGNEL.T WADLVIADNL TTLINAEL.. .........L GTS5_CAEEL NFLKASG..S GFLVGDSL.T WIDLAIAQHS ADLIAKGG.. .......... GTS6_CAEEL NILASNHS.. GFFVGNSL.T WVDLLISQHV QDILDKDL.. .........A GTS4_CAEEL KFLAKSK..S GFLVGDSL.T WADIVIADNL TSLLKNGF.. .........L GTS2_CAEEL KILLRSK..S GFLVGDDL.T WADLQIADNL STLINIRL.. .......... GTS1_CAEEL KFLLENGN.N GLLLGDRE.T WVDVFAAESF SKLIDYGSP. .........D GTS_ANOGA VIAKENN... GHLVLGKP.T WADVYFAGIL DYLNYLTKT. .........N GTS2_MANSE EIITKNN... GFLALGRL.T WADFVFVGMF DYLKKMLR.. .......MPD GT1_ONCVO KFLKEST..T GHIVGNKV.S VADLTVFNML MTLDDEVK.. .......... SC11_OMMSL KTLEANKGGA GWFIGDQI.L LCDMMTHAAL ENPIQENAN. .......... SC2_OCTDO RTLEMYKSGG QFFMGDQM.T MADMMCYCAL ENPIMEES.. .........S 1aw9_ AHLARN.... KYLAGDEF.T LADANHASYL LYLSKTPK.. ........AG GTH3_ARATH AQLSKNE... .YLAGDFV.S LADLAHLPFT EYLVGPIG.. .......KAH GTH7_ARATH NRLATNR... .YLGGDEF.T LADLSHMPGM RYIMNETS.. .......LSG GTH6_ARATH ARLAKSE... .FLAGDSF.T LADLHHLPAI HYLLGTDS.. ........KV GTH_SILCU ARLTESEY.. .LGANDSF.T LVDLHHLPLL GYLMGTQV.. ........KK GTH1_ARATH HRLGESK... .YLASDHF.T LVDLHTIPVI QYLLGTPT.. ........KK GTH4_ARATH ARLKEFK... .YLAGETF.T LTDLHHIPAI QYLLGTPT.. ........KK GTH4_MAIZE ARLATCT... .YLAGDFL.S LADLSPFTIM HCLMATEY.. ........AA GTH1_MAIZE ARLTKCK... .YLAGDFL.S LADLNHVSVT LCLFATPY.. ........AS GTH1_WHEAT ARLEKSR... .YLAGDSI.T FADLNHIPFT FYFMTTPY.. ........AK GTH5_ARATH RILSKQK... .YLAGNDF.T LADLFHLPYG AMVAQLEP.. .........T 1eem_A EVLTNKK..T TFFGGNSI.S MIDYLIWPWF ERLEAMKLN. .........E GTO1_MOUSE EGMDNYK... SFLGGDSP.S MVDYLTWPWF QRLEALELK. .........E GTO2_HUMAN EILEYQN..T TFFGGTCI.S MIDYLLWPWF ERLDVYGIL. .........D YKJ3_CAEEL QLLTGD.... .FYSGTSKPG FVDYLLYPNI QRAYWAAHIV PDFPLEAESF 1ags_A LISSFPLLKA LKTRISN.LP TVKKFLQPGS PRKPPMDEKS LEEARKIFRF GTA1_BOVIN LLANFPLLKA LKARVSS.LP AVKKFLQPGS QRKPPTDEKK IEEARKVFKF GTA1_MOUSE LLTPFPLLKA FKSRISS.LP NVKKFLQPGS QRKPPMDAKQ IQEARKAFKI GTC1_RAT ALANFPLLKA LRTRVSN.LP TVKKFLQPGS QRKPLEDEKC VESAVKIFS. GTC_RABIT ATASFPLLQA LKTRISN.LP TVKKFLQPGS QRNPPDDEKC REEAKIIFH. GTA1_RABIT AIASFPLLKA LKTRISS.LP TVKKFLQPGS QRKPPMDEKN LEKAKKIFKI GTA1_CAVPO LLANFTLLQA LKTRVSN.LP NVKKFLQPGS QRKPFPTQEM FEEMRKF... GTA3_RAT VLSDFPLLQA FKTRISN.IP TIKKFLQPGS QRKPPPDGHY VDVVRTVLKF GTA3_CHICK ALSGFPLLQA FKKRISS.IP TIKKFLAPGS KRKPISDDKY VETVRRVLRM GTA2_CHICK ILSAFPLLQA FKGRMSN.VP TIKKFLQPGS QRKPPLDEKS IANVRKIFSF GTA1_CHICK ALAKFPLLQS FKARTSN.IP NIKKFLQPGS QRKPRLEEKD IPRLMAIFH. GTA1_ANTST ALSGFPLLQA FKTRISN.IP TVKTFLAPGS KRKPVPDAKY VEDIIKIFYF GTA4_HUMAN ILSAFPFLQE YTVKLSN.IP TIKRFLEPGS KKKPPPDEIY VRTVYNIFRP 1oe7_A LTGKYPEIHK HRENLLASSP RLAKYLSDRA .......... .......... GTP1_BUFBU CLSGFPLLCA YVKRISS.RP KLEAYLSSDA HKKRPINGNG KQQ....... GT28_SCHJA LTGKYPEIHK HRKHLLATSP KLAKYLSERH ATAF...... .......... GTS1_ASCSU FLSGHLQLKK YIEHVRE.LP NIKKWIAERP KTPY...... .......... GTS9_CAEEL ILDTFLEMKD HQKKIHS.IP NVKKWIEKRP VTSR...... .......... GTS3_CAEEL DIENDKLLKE FREKIIE.TP KLKEWLAKRP ETRF...... .......... GTS5_CAEEL DFSKFPELKA HAEKIQA.IP QIKKWIETRP VTPF...... .......... GTS6_CAEEL VVEEFKKVLA HRKKVQS.ID RIQKYIANRP DYPF...... .......... GTS4_CAEEL DFNKEKKLEE FYNKIHS.IP EIKNYVATRK DSIV...... .......... GTS2_CAEEL FAEKEPHLNV FIRKL..... .......... .......... .......... GTS1_CAEEL ALDAYPHILA LINRVFN.HP NIKKYVSQRK ATPA...... .......... GTS_ANOGA LLENFPNLQE VVQKVLD.NE NVKAYIAKRP ITEV...... .......... GTS2_MANSE LEEQYPIFKK PIETVLS.NP KLKAYLDSAP KKEF...... .......... GT1_ONCVO .LEEYPQLAS FVNKIGQ.MP GIKEWIKKRP KTYF...... .......... SC11_OMMSL LLKEYPKLAA LRTRVAA.HP KIAAYIKKRN NTAF...... .......... SC2_OCTDO LLNSYPKLQA LRTRVMS.HL KMSPYLKKRS STEF...... .......... 1aw9_ LVAARPHVKA WWEAIVA.RP AFQKTVAAIP LPPPP..... .......... GTH3_ARATH LIKDRKHVSA WWDKISS.RA AWKEVSAKYS LPV....... .......... GTH7_ARATH LVTSRENLNR WWNEISA.RP AWKKLMELAA Y......... .......... GTH6_ARATH LFDSRPKVSE WIKKISA.RP AWAKVIDLQK Q......... .......... GTH_SILCU LFEERAHVSA WCKKILA.RP SWEKTLALQK QA........ .......... GTH1_ARATH LFDERPHVSA WVADITS.RP SAQKVL.... .......... .......... GTH4_ARATH LFTERPRVNE WVAEITK.RP ASEKVQ.... .......... .......... GTH4_MAIZE LVHALPHVSA WWQGLAA.RP AANKVAQFMP VGAGAPKEQE .......... GTH1_MAIZE VLDAYPHVKA WWSGLME.RP SVQKVAALMK PSA....... .......... GTH1_WHEAT VFDDYPKVKA WWEMLMA.RP AVQRVCKHMP TEFKLGAQY. .......... GTH5_ARATH VLDSKPHVKA WWAASLRVIP GRLLRNSSKE FM........ .......... 1eem_A CVDHTPKLKL WMAAMKE.DP TVSALLTSEK DWQGFLELYL QNSPEACDYG GTO1_MOUSE CLAHTPKLKL WMAAMQQ.DP VASSHKIDAK TYREYLNLYL QDSPEACDYG GTO2_HUMAN CVSHTPALRL WISAMKW.DP TVCALLMDKS IFQGFLNLYF QNNPNAFDFG YKJ3_CAEEL PGPNYPRLSK WYKALESIPE VAAASQPTEN GVGFFKDYLG GSPNYDYGLT 1ags_A ....... GTA1_BOVIN ....... GTA1_MOUSE Q...... GTC1_RAT ....... GTC_RABIT ....... GTA1_RABIT P...... GTA1_CAVPO ....... GTA3_RAT ....... GTA3_CHICK YYDVKPH GTA2_CHICK ....... GTA1_CHICK ....... GTA1_ANTST ....... GTA4_HUMAN ....... 1oe7_A ....... GTP1_BUFBU ....... GT28_SCHJA ....... GTS1_ASCSU ....... GTS9_CAEEL ....... GTS3_CAEEL ....... GTS5_CAEEL ....... GTS6_CAEEL ....... GTS4_CAEEL ....... GTS2_CAEEL ....... GTS1_CAEEL ....... GTS_ANOGA ....... GTS2_MANSE ....... GT1_ONCVO ....... SC11_OMMSL ....... SC2_OCTDO ....... 1aw9_ ....... GTH3_ARATH ....... GTH7_ARATH ....... GTH6_ARATH ....... GTH_SILCU ....... GTH1_ARATH ....... GTH4_ARATH ....... GTH4_MAIZE ....... GTH1_MAIZE ....... GTH1_WHEAT ....... GTH5_ARATH ....... 1eem_A L...... GTO1_MOUSE L...... GTO2_HUMAN LC..... YKJ3_CAEEL KLSETI. kalign-3.5.1/tests/data/BB30014.tfa000066400000000000000000000240541515023132300164070ustar00rootroot00000000000000>1ags_A AEKPKLHYFNARGRMESTRWLLAAAGVEFEEKFIKSAEDLDKLRNDGYLM FQQVPMVEIDGMKLVQTRAILNYIASKYNLYRKDIKEKALIDMYIEGIAD LGEMILLLPFTQPEEQDAKLALIKEKIKNRYFPAFEKVLKSHGQDYLVGN KLSRADIHLVELLYYVEELDSSLISSFPLLKALKTRISNLPTVKKFLQPG SPRKPPMDEKSLEEARKIFRF >GTA1_BOVIN AGKPTLHYFNGRGRMECIRWLLAAAGVEFEEKFIEKPEDLDKLKNDGSLM FQQVPMVEIDGMKLVQTRAILNYIATKYNLYGKDMKERALIDMYSEGVAD LGEMIMHFPLCPPAEKDAKLTLIREKTTNRYLPAFENVLKSHGQDYLVGN KLSRADIHLVELLYYVEELDPSLLANFPLLKALKARVSSLPAVKKFLQPG SQRKPPTDEKKIEEARKVFKF >GTA1_MOUSE AGKPVLHYFNARGRMECIRWLLAAAGVEFEEKFIQSPEDLEKLKKDGNLM FDQVPMVEIDGMKLAQTRAILNYIATKYDLYGKDMKERALIDMYSEGILD LTEMIGQLVLCPPDQREAKTALAKDRTKNRYLPAFEKVLKSHGQDYLVGN RLTRVDIHLLEVLLYVEEFDASLLTPFPLLKAFKSRISSLPNVKKFLQPG SQRKPPMDAKQIQEARKAFKIQ >GTC1_RAT PGKPVLHYFDGRGRMEPIRWLLAAAGVEFEEQFLKTRDDLARLRNDGSLM FQQVPMVEIDGMKLVQTRAILNYIATKYNLYGKDMKERALIDMYAEGVAD LDEIVLHYPYIPPGEKEASLAKIKDKARNRYFPAFEKVLKSHGQDYLVGN RLSRADVYLVQVLYHVEELDPSALANFPLLKALRTRVSNLPTVKKFLQPG SQRKPLEDEKCVESAVKIFS >GTC_RABIT AGKPKLHYFNARGRMESIRWLLTAAGVEFEEKCMKTREDLEKLRKDGVLM FQQVPMVEIDGMKLVQTRAIFNYIADKHNLYGKDIKERALIDMYTEGIVD LNELILTRPFLPPEEQEAKLAQIKDKAKNRYFPAFEKVLKSHGQDYLVGN KLSKADILLVELLYNVEELNPGATASFPLLQALKTRISNLPTVKKFLQPG SQRNPPDDEKCREEAKIIFH >GTA1_RABIT MARKPLLHYFNGRGRMESIRWLLAAAGEEFDEKFMETAEDLDKLRNDGSL MYQQVPMVEIDGMKLVQTRAILNYVANKHNLYGKDMKERALIDMYTEGVA DLYELVLLLPLCPPEQKDAKVDFIKEKIRTRYFPAFEKVLKSHGQDYLVG NRLSKADILLVELLYNVEELDPSAIASFPLLKALKTRISSLPTVKKFLQP GSQRKPPMDEKNLEKAKKIFKIP >GTA1_CAVPO SGKPVLHYFNVQGRMESIRWLLAAAGVEFEEKLIMCQEDLDKLKNDGLLM FQQVPMVEMDGMKMVQSRAILNYIATKYNLYGKDTKERLLIDMYTEGMTD LYELFFKVILAPPEEKDAAKSLIKDRAKNRFLPAFEKVLKSHGQGYLVGN KLSKADILLTELLYMVEEFDASLLANFTLLQALKTRVSNLPNVKKFLQPG SQRKPFPTQEMFEEMRKF >GTA3_RAT MEVKPKLYYFQGRGRMESIRWLLATAGVEFEEEFLETREQYEKLQKDGCL LFGQVPLVEIDGMLLTQTRAILSYLAAKYNLYGKDLKERVRIDMYADGTQ DLMMMIIGAPFKAPQEKEESLALAVKRAKNRYFPVFEKILKDHGEAFLVG NQLSWADIQLLEAILMVEEVSAPVLSDFPLLQAFKTRISNIPTIKKFLQP GSQRKPPPDGHYVDVVRTVLKF >GTA3_CHICK AAKPVLYYFNGRGKMESIRWLLAAAGVEFEEVFLETREQYEKLLQSGILM FQQVPMVEIDGMKLVQTRAILNYIAGKYNLYGKDLKERALIDMYVGGTDD LMGFLLSFPFLSAEDKVKQCAFVVEKATSRYFPAYEKVLKDHGQDFLVGN RLSWADIHLLEAILMVEEKKSDALSGFPLLQAFKKRISSIPTIKKFLAPG SKRKPISDDKYVETVRRVLRMYYDVKPH >GTA2_CHICK MAGKPKLHYTRGRGKMESIRWLLAAAGVEFEEEFIEKKEDLEKLRNDGSL LFQQVPMVEIDGMKMVQSRAILCYIAGKYNLYGKDLKERAWIDMYVEGTT DLMGMIMALPFQAADVKEKNIALITERATTRYFPVYEKALKDHGQDYLVG NKLSWADIHLLEAILMTEELKSDILSAFPLLQAFKGRMSNVPTIKKFLQP GSQRKPPLDEKSIANVRKIFSF >GTA1_CHICK MSGKPVLHYANTRGRMESVRWLLAAAGVEFEEKFLEKKEDLQKLKSDGSL LFQQVPMVEIDGMKMVQTRAILNYIAGKYNLYGKDLKERALIDMYVEGLA DLYELIMMNVVQPADKKEEHLANALDKAANRYFPVFEKVLKDHGHDFLVG NKLSRADVHLLETILAVEESKPDALAKFPLLQSFKARTSNIPNIKKFLQP GSQRKPRLEEKDIPRLMAIFH >GTA1_ANTST MAGEQNIKYFNIKGRMEAIRWLLAVAGVEFEEKFFETKEQLQKLKETVLL FQQVPMVEIDGMKLVQTRAILHYIAEKYNLLGKDMKEHAQIIMYSEGTMD LMELIMIYPFLKGEEKKQRLVEIANKAKGRYFPAFENVLKTHGQNFLVGN QLSMADVQLFEAILMVEEKVPDALSGFPLLQAFKTRISNIPTVKTFLAPG SKRKPVPDAKYVEDIIKIFYF >GTA4_HUMAN MAARPKLHYPNGRGRMESVRWVLAAAGVEFDEEFLETKEQLYKLQDGNHL LFQQVPMVEIDGMKLVQTRSILHYIADKHNLFGKNLKERTLIDMYVEGTL DLLELLIMHPFLKPDDQQKEVVNMAQKAIIRYFPVFEKILRGHGQSFLVG NQLSLADVILLQTILALEEKIPNILSAFPFLQEYTVKLSNIPTIKRFLEP GSKKKPPPDEIYVRTVYNIFRP >1oe7_A DHIKVIYFNGRGRAESIRMTLVAAGVNYEDERISFQDWPKIKPTIPGGRL PAVKITDNHGHVKWMVESLAIARYMAKKHHMMGGTEEEYYNVEKLIGQAE DLEHEYYKTLMKPEEEKQKIIKEILNGKVPVLLDIICESLKASTGKLAVG DKVTLADLVLIAVIDHVTDLDKEFLTGKYPEIHKHRENLLASSPRLAKYL SDRA >GTP1_BUFBU PEYTIIYFNARGRCEAMRMLMADQGAQWKEEVVTSDDWQKGDLKKAAVYG QLPGFKDGDFTLYQSNAMLRLLARNHDLYGKNPREASLIDMVNDGVEDLR LKYLKMIYQNYENGKDDYVKALPTNLGHFERLLASNNEGKGFVVGAHISF ADYNLVDLLHNHLVLAPDCLSGFPLLCAYVKRISSRPKLEAYLSSDAHKK RPINGNGKQQ >GT28_SCHJA VKLIYFNGRGRAEPIRMILVAAGVEFEDERIEFQDWPKIKPTIPGGRLPI VKITDKRGDVKTMSESLAIARFIARKHNMMGDTDDEYYIIEKMIGQVEDV ESEYHKTLIKPPEEKEKISKEILNGKVPILLQAICETLKESTGNLTVGDK VTLADVVLIASIDHITDLDKEFLTGKYPEIHKHRKHLLATSPKLAKYLSE RHATAF >GTS1_ASCSU PQYKLTYFDIRGLGEGARLIFHQAGVKFEDNRLKREDWPALKPKTPFGQL PLLEVDGEVLAQSAAIYRYLGRQFGLAGKTPMEEAQVDSIFDQFKDFMAE LRPCFRVLAGFEEGDKEKVLKEVAVPARDKHLPLLEKFLAKSGSEYMVGK SVTWADLVITDSLASWESLIPDFLSGHLQLKKYIEHVRELPNIKKWIAER PKTPY >GTS9_CAEEL MVSYKLIYFQSRGNGEIARQVFAFAGQEFIDERISKEQWAEIKNMTPFGQ VPVLEVDGRQLAQSITIVRYLSKQFGISGKSSWEEAQVDALGDQFKDYRV EARPFFRAKMGFSDGDVDQLYKDLFVPAFNKMYSIFTESLKSSGSGFLVG DSLTWMDLAIAQHSADLLEADGKILDTFLEMKDHQKKIHSIPNVKKWIEK RPVTSR >GTS3_CAEEL MVHYKLTYFNARGLAEISRQLFHMAGVEFEDERINEEKFSQLKPTFPSGQ VPILCIDGAQFSQSTAIARYLARKFGFVGQTAEEELQADEVVDTFKDFIE SFRKFVIAVLSGESEEILKNIREEVIKPAVKTYTAYLKAILEKSSSGYLV GNELTWADLVIADNLTTLINAELLDIENDKLLKEFREKIIETPKLKEWLA KRPETRF >GTS5_CAEEL MVSYKLTYFNGRGAGEVSRQIFAYAGQQYEDNRVTQEQWPALKETCAAPF GQLPFLEVDGKKLAQSHAIARFLAREFKLNGKTAWEEAQVNSLADQYKDY SSEARPYFYAVMGFGPGDVETLKKDIFLPAFEKFYGFLVNFLKASGSGFL VGDSLTWIDLAIAQHSADLIAKGGDFSKFPELKAHAEKIQAIPQIKKWIE TRPVTPF >GTS6_CAEEL MVHYKLVYFPLRARAEIARQIFAYAGQDYSEENLSFEQWPARKNNTPFGQ LPILEVDGKPLGQSYAIARYLAREFGIAGQNDTEAAEVDAIADQFKDYLN DVSPYLTVLAGFKPGDKDQLRTDVFVPAFKKNFEFFENILASNHSGFFVG NSLTWVDLLISQHVQDILDKDLAVVEEFKKVLAHRKKVQSIDRIQKYIAN RPDYPF >GTS4_CAEEL MPNYKLLYFDARALAEPIRIMFAMLNVPYEDYRVSVEEWSKLKPTTPFGQ LPILQVDGEQFGQSMSITRYLARKFGLAGKTAEEEAYADSIVDQYRDFIF FFRQFTSSVFYGSDADHINKVRFEVVEPARDDFLAIINKFLAKSKSGFLV GDSLTWADIVIADNLTSLLKNGFLDFNKEKKLEEFYNKIHSIPEIKNYVA TRKDSIV >GTS2_CAEEL MVHYKLMCFDVRGLGEVIRQLFYLGDVSFEDFRVSREEFKSLKSNLPSGQ LPVLEIDGVMISQSASIGRFLARQYGYSGKTPTEEMQVDSIIDLFKDFML TFRQFFFAVIHGYPEYEKERMKRDIVKPAIKNYFIALNKILLRSKSGFLV GDDLTWADLQIADNLSTLINIRLFAEKEPHLNVFIRKL >GTS1_CAEEL MPHFKFYYFDVRGRGEAIRLLFHLADEKFDDERFGMEQWGVLKSEMPLGQ VPVLEIDGVKISQTTAIARYLGHQFHRAGTNAVDCARLDMIAEVIQEFMS SSGMGKFSRVLLGMIQANKEQFFKENVLPDVEKYAPIVEKFLLENGNNGL LLGDRETWVDVFAAESFSKLIDYGSPDALDAYPHILALINRVFNHPNIKK YVSQRKATPA >GTS_ANOGA LSSSSISRSSLKCNIMPDYKVYYFNVKALGEPLRFLLSYGNLPFDDVRIT REEWPALKPTMPMRQMPVLEVDGKRVHQSLAMCRYVAKQINLAGDNPLEA LQIDAIVDTINDFRLKIAIVAYEPDDMVKEKKMVTLNNEVIPFYLTKLNV IAKENNGHLVLGKPTWADVYFAGILDYLNYLTKTNLLENFPNLQEVVQKV LDNENVKAYIAKRPITEV >GTS2_MANSE MPKVVFHYFGAKGWARPTMLLAYGGQEFEDHRVEYEQWPEFKPNTPFGQM PVLEIDGKKYAQSLAISRYLGRKYGLAGNDIEEDFEIDQIVDFVNDIRAS AASVEYEQDAANKEVKHEENMKNKYPFQLNKLSEIITKNNGFLALGRLTW ADFVFVGMFDYLKKMLRMPDLEEQYPIFKKPIETVLSNPKLKAYLDSAPK KEF >GT1_ONCVO FITMNFVVEAASSNANQAITSENSIKPKGKLQPQMEKYTLTYFNGRGRAE VIRLLFALANVSYEDNRITRDEWKYLKPRTPFGHVPMLNVSGNVLGESHA IELLLGGRFGLLGTNDWEEAKIMAVVLNIDELFQKLIPWTHEKNTTKKAE LFRNLSESDVMPFLGRYEKFLKESTTGHIVGNKVSVADLTVFNMLMTLDD EVKLEEYPQLASFVNKIGQMPGIKEWIKKRPKTYF >SC11_OMMSL MPSYTLYYFNGRGRAEICRMLFAVASVQYQDKRIELAEWTQFKTKMPCHM LPILEIDTETQVPQSMAISRYLAREFGFYGKNNMDMFKVDCLCDSLFELF NDYMAVYNEKDAAKKTELQKRFQNTCLRVLPYMEKTLEANKGGAGWFIGD QILLCDMMTHAALENPIQENANLLKEYPKLAALRTRVAAHPKIAAYIKKR NNTAF >SC2_OCTDO MPSYTLNYFNHRGRAEICRMLFAAAGVQYNDRRIETSEWSNMRSKMPCSM MPMLDIDNRHQIPQTMAIARYLAREFGFHGKNNMEMARVEYISDCFYDIL DDYLRMYQDDNCRMMFQRSGDRNGSSEKRTRYQETLRRILPFMERTLEMY KSGGQFFMGDQMTMADMMCYCALENPIMEESSLLNSYPKLQALRTRVMSH LKMSPYLKKRSSTEF >1aw9_ APLKLYGMPLSPNVVRVATVLNEKGLDFEIVPVDLTTGAHKQPDFLALNP FGQIPALVDGDEVLFESRAINRYIASKYASEGTDLLPATASAAKLEVWLE VESHHFYPNASPLVFQLLVRPLLGGAPDAAVVDKHAEQLAKVLDVYEAHL ARNKYLAGDEFTLADANHASYLLYLSKTPKAGLVAARPHVKAWWEAIVAR PAFQKTVAAIPLPPPP >GTH3_ARATH VLTIYAPLFASSKRAVVTLVEKGVSFETVNVDLMKGEQRQPEYLAIQPFG KIPVLVDGDYKIFESRAIMRYIAEKYRSQGPDLLGKTIEERGQVEQWLDV EATSYHPPLLALTLNIVFAPLMGFPADEKVIKESEEKLAEVLDVYEAQLS KNEYLAGDFVSLADLAHLPFTEYLVGPIGKAHLIKDRKHVSAWWDKISSR AAWKEVSAKYSLPV >GTH7_ARATH MVVKVYGQIKAANPQRVLLCFLEKDIEFEVIHVDLDKLEQKKPQHLLRQP FGQVPAIEDGYLKLFESRAIARYYATKYADQGTDLLGKTLEGRAIVDQWV EVENNYFYAVALPLVMNVVFKPKSGKPCDVALVEELKVKFDKVLDVYENR LATNRYLGGDEFTLADLSHMPGMRYIMNETSLSGLVTSRENLNRWWNEIS ARPAWKKLMELAAY >GTH6_ARATH MASIKVHGVPMSTATMRVLATLYEKDLQFELIPVDMRAGAHKQEAHLALN PFGQIPALEDGDLTLFESRAITQYLAEEYSEKGEKLISQDCKKVKATTNV WLQVEGQQFDPNASKLAFERVFKGMFGMTTDPAAVQELEGKLQKVLDVYE ARLAKSEFLAGDSFTLADLHHLPAIHYLLGTDSKVLFDSRPKVSEWIKKI SARPAWAKVIDLQKQ >GTH_SILCU TIKVHGNPRSTATQRVLVALYEKHLEFEFVPIDMGAGGHKQPSYLALNPF GQVPALEDGEIKLFESRAITKYLAYTHDHQNEGTSLIHKEKHEMAAQLVW EEVEAHQFDPVASKLAWELVFKGIFGMQTDTTVVEENEAKLAKVLDVYEA RLTESEYLGANDSFTLVDLHHLPLLGYLMGTQVKKLFEERAHVSAWCKKI LARPSWEKTLALQKQA >GTH1_ARATH MAGIKVFGHPASTATRRVLIALHEKNVDFEFVHVELKDGEHKKEPFILRN PFGKVPAFEDGDFKIFESRAITQYIAHEFSDKGNNLLSTGKDMAIIAMGI EIESHEFDPVGSKLVWEQVLKPLYGMTTDKTVVEEEEAKLAKVLDVYEHR LGESKYLASDHFTLVDLHTIPVIQYLLGTPTKKLFDERPHVSAWVADITS RPSAQKVL >GTH4_ARATH AGIKVFGHPASIATRRVLIALHEKNLDFELVHVELKDGEHKKEPFLSRNP FGQVPAFEDGDLKLFESRAITQYIAHRYENQGTNLLQTDSKNISQYAIMA IGMQVEDHQFDPVASKLAFEQIFKSIYGLTTDEAVVAEEEAKLAKVLDVY EARLKEFKYLAGETFTLTDLHHIPAIQYLLGTPTKKLFTERPRVNEWVAE ITKRPASEKVQ >GTH4_MAIZE ATPAVKVYGWAISPFVSRALLALEEAGVDYELVPMSRQDGDHRRPEHLAR NPFGKVPVLEDGDLTLFESRAIARHVLRKHKPELLGGGRLEQTAMVDVWL EVEAHQLSPPAIAIVVECVFAPFLGRERNQAVVDENVEKLKKVLEVYEAR LATCTYLAGDFLSLADLSPFTIMHCLMATEYAALVHALPHVSAWWQGLAA RPAANKVAQFMPVGAGAPKEQE >GTH1_MAIZE APMKLYGAVMSWNLTRCATALEEAGSDYEIVPINFATAEHKSPEHLVRNP FGQVPALQDGDLYLFESRAICKYAARKNKPELLREGNLEEAAMVDVWIEV EANQYTAALNPILFQVLISPMLGGTTDQKVVDENLEKLKKVLEVYEARLT KCKYLAGDFLSLADLNHVSVTLCLFATPYASVLDAYPHVKAWWSGLMERP SVQKVAALMKPSA >GTH1_WHEAT MSPVKVFGHPMLTNVARVLLFLEEVGAEYELVPMDFVAGEHKRPQHVQLN PFAKMPGFQDGDLVLFESRAIAKYILRKYGGTAGLDLLGENSGIEELAMV DVWTEVEAQQYYPAISPVVFECIIIPFIIPGGGAAPNQTVVDESLERLRG VLGIYEARLEKSRYLAGDSITFADLNHIPFTFYFMTTPYAKVFDDYPKVK AWWEMLMARPAVQRVCKHMPTEFKLGAQY >GTH5_ARATH MVTVKLYGMAYSTCTKRVYTTAKEIGVDVKIVPVDLMKGEHKEPAYLDNY HPFGVIPVLEDEDGTKIYESRAISRYLVAKYGKGSSLLPSPSDPKAYGLF EQAASVEYSSFDPPASSLAYERVFAGMRGLKTNEELAKKYVDTLNAKMDG YERILSKQKYLAGNDFTLADLFHLPYGAMVAQLEPTVLDSKPHVKAWWAA SLRVIPGRLLRNSSKEFM >1eem_A SARSLGKGSAPPGPVPEGSIRIYSMRFCPFAERTRLVLKAKGIRHEVINI NLKNKPEWFFKKNPFGLVPVLENSQGQLIYESAITCEYLDEAYPGKKLLP DDPYEKACQKMILELFSKVPSLVGSFIRSQNKEDYAGLKEEFRKEFTKLE EVLTNKKTTFFGGNSISMIDYLIWPWFERLEAMKLNECVDHTPKLKLWMA AMKEDPTVSALLTSEKDWQGFLELYLQNSPEACDYGL >GTO1_MOUSE MSGESSRSLGKGSAPPGPVPEGQIRVYSMRFCPFAQRTLMVLKAKGIRHE VININLKNKPEWFFEKNPLGLVPVLENSQGHLVTESVITCEYLDEAYPEK KLFPDDPYKKARQKMTLESFSKVPPLIASFVRSKRKEDSPNLREALENEF KKLEEGMDNYKSFLGGDSPSMVDYLTWPWFQRLEALELKECLAHTPKLKL WMAAMQQDPVASSHKIDAKTYREYLNLYLQDSPEACDYGL >GTO2_HUMAN MSGDATRTLGKGSQPPGPVPEGLIRIYSMRFCPYSHRTRLVLKAKDIRHE VVNINLRNKPEWYYTKHPFGHIPVLETSQCQLIYESVIACEYLDDAYPGR KLFPYDPYERARQKMLLELFCKVPHLTKECLVALRCGRECTNLKAALRQE FSNLEEILEYQNTTFFGGTCISMIDYLLWPWFERLDVYGILDCVSHTPAL RLWISAMKWDPTVCALLMDKSIFQGFLNLYFQNNPNAFDFGLC >YKJ3_CAEEL MTVLAGVNSKIVKNGCWNHSYLQHAILPVAQRALIYASVKNIPSDVINVH LQEKPDWYFSKHYKGQVPTLEHDEGKKHVIESAVIPEYLDDIYPETRILP TDPYEKVQQKLLLDRISGQVSPAFYGVVQAVKNPDLREEKFADIKKAYDN AEQLLTGDFYSGTSKPGFVDYLLYPNIQRAYWAAHIVPDFPLEAESFPGP NYPRLSKWYKALESIPEVAAASQPTENGVGFFKDYLGGSPNYDYGLTKLS ETI kalign-3.5.1/tests/data/README000066400000000000000000000003121515023132300157070ustar00rootroot00000000000000This directory contains test alignments: - distributed together with Sean Eddy's easel library: https://github.com/EddyRivasLab/easel - from the balibase MSA benchmark: https://www.lbgi.fr/balibase/ kalign-3.5.1/tests/data/a2m.good.1000066400000000000000000000012521515023132300165230ustar00rootroot00000000000000>MYG_PHYCA VLSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRFKHLKTEAEMKASED LKKHGVTVLTALGAILKKKGHHEAELKPLAQSHATKHKIPIKYLEFISEAIIHVLHSRHP GDFGADAQGAMNKALELFRKDIAAKYKELGYQG >GLB5_PETMA pivdtgsvApLSAAEKTKIRSAWAPVYSTYETSGVDILVKFFTSTPAAQEFFPKFKGLTT ADQLKKSADVRWHAERIINAVNDAVASMDDtekMSMKLRDLSGKHAKSFQVDPQYFKVLA AVI---------ADTVAAGDAGFEKLMSMICILLRSAY------- >HBB_HUMAN VhLTPEEKSAVTALWGKV--NVDEVGGEALGRLLVVYPWTQRFFESFGDLSTPDAVMGNP KVKAHGKKVLGAFSDGLAHLDNLKGTFATLSELHCDKLHVDPENFRLLGNVLVCVLAHHF GKEFTPPVQAAYQKVVAGVANALAHKYH------ >HBA_HUMAN VLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHF------DLSHGSAQ VKGHGKKVADALTNAVAHVDDMPNALSALSDLHAHKLRVDPVNFKLLSHCLLVTLAAHLP AEFTPAVHASLDKFLASVSTVLTSKYR------ kalign-3.5.1/tests/data/a2m.good.2000066400000000000000000000006311515023132300165240ustar00rootroot00000000000000>tRNA2 UCCGAUAUAGUGUAACGGCUAUCACAUCACGCUUUCACCGUGGAGACCGGGGUUCGACUC CCCGUAUCGGAG >tRNA3 UCCGUGAUAGUUUAAUGGUCAGAAUGG-GCGCUUGUCGCGUGCcAGAUCGGGGUUCAAUU CCCCGUCGCGGAG >tRNA5 GGGCACAUGGCGCAGUUGGUAGCGCGCUUCCCUUGCAAGGAAGaGGUCAUCGGUUCGAUU CCGGUUGCGUCCA >tRNA1 GCGGAUUUAGCUCAGUUGGGAGAGCGCCAGACUGAAGAUCUGGaGGUCCUGUGUUCGAUC CACAGAAUUCGCA >tRNA4 GCUCGUAUGGCGCAGUGG-UAGCGCAGCAGAUUGCAAAUCUGUuGGUCCUUAGUUCGAUC CUGAGUGCGAGCU kalign-3.5.1/tests/data/afa.good.1000066400000000000000000000013151515023132300165730ustar00rootroot00000000000000>MYG_PHYCA --------V-LSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRFKHLKT EAEMKASEDLKKHGVTVLTALGAILKKKGH---HEAELKPLAQSHATKHKIPIKYLEFIS EAIIHVLHSRHPGDFGADAQGAMNKALELFRKDIAAKYKELGYQG >GLB5_PETMA PIVDTGSVAPLSAAEKTKIRSAWAPVYSTYETSGVDILVKFFTSTPAAQEFFPKFKGLTT ADQLKKSADVRWHAERIINAVNDAVASMDDTEKMSMKLRDLSGKHAKSFQVDPQYFKVLA AVI---------ADTVAAGDAGFEKLMSMICILLRSAY------- >HBB_HUMAN --------VHLTPEEKSAVTALWGKV--NVDEVGGEALGRLLVVYPWTQRFFESFGDLST PDAVMGNPKVKAHGKKVLGAFSDGLAHLDN---LKGTFATLSELHCDKLHVDPENFRLLG NVLVCVLAHHFGKEFTPPVQAAYQKVVAGVANALAHKYH------ >HBA_HUMAN --------V-LSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHF----- -DLSHGSAQVKGHGKKVADALTNAVAHVDD---MPNALSALSDLHAHKLRVDPVNFKLLS HCLLVTLAAHLPAEFTPAVHASLDKFLASVSTVLTSKYR------ kalign-3.5.1/tests/data/afa.good.2000066400000000000000000000006321515023132300165750ustar00rootroot00000000000000>tRNA2 UCCGAUAUAGUGUAACGGCUAUCACAUCACGCUUUCACCGUGG-AGACCGGGGUUCGACU CCCCGUAUCGGAG >tRNA3 UCCGUGAUAGUUUAAUGGUCAGAAUGG-GCGCUUGUCGCGUGCCAGAUCGGGGUUCAAUU CCCCGUCGCGGAG >tRNA5 GGGCACAUGGCGCAGUUGGUAGCGCGCUUCCCUUGCAAGGAAGAGGUCAUCGGUUCGAUU CCGGUUGCGUCCA >tRNA1 GCGGAUUUAGCUCAGUUGGGAGAGCGCCAGACUGAAGAUCUGGAGGUCCUGUGUUCGAUC CACAGAAUUCGCA >tRNA4 GCUCGUAUGGCGCAGUGG-UAGCGCAGCAGAUUGCAAAUCUGUUGGUCCUUAGUUCGAUC CUGAGUGCGAGCU kalign-3.5.1/tests/data/afa.good.3000066400000000000000000000016151515023132300166000ustar00rootroot00000000000000>7295730___KOG0003 mqifvktltgktitlevepsdtienvkakiqdkegippdqqrlifagkql edgrtlsdyniqkestlhlvlrlrggiiepslrilaqkyncdkmicrkcy arlhpratncrkkkcghtnnlrpkkklk >Hs4507761___KOG0003 mqifvktltgktitlevepsdtienvkakiqdkegippdqqrlifagkql edgrtlsdyniqkestlhlvlrlrggiiepslrqlaqkyncdkmicrkcy arlhpravncrkkkcghtnnlrpkkkvk >At3g52590___KOG0003 mqifvktltgktitlevessdtidnvkakiqdkegippdqqrlifagkql edgrtladyniqkestlhlvlrlrggiiepslmmlarkynqdkmicrkcy arlhpravncrkkkcghsnqlrpkkkik >CE15495___KOG0003 mqifvktltgktitleveasdtienvkakiqdkegippdqqrlifagkql edgrtlsdyniqkestlhlvlrlrggiiepslrqlaqkyncdkqicrkcy arlpprasncrkkkcghsselrikkklk >SPAC1805.12c___KOG0003 mqifvktltgktitlevessdtidnvkskiqdkegippdqqrlifagkql edgrtlsdyniqkestlhlvlrlrggiiepslkalaskyncekqicrkcy arlppratncrkkkcghtnqlrpkkklk >YIL148w___KOG0003 mqifvktltgktitlevessdtidnvkskiqdkegippdqqrlifagkql edgrtlsdyniqkestlhlvlrlrggiiepslkalaskyncdksvcrkcy arlppratncrkrkcghtnqlrpkkklk kalign-3.5.1/tests/data/clustal.good.1000066400000000000000000000021451515023132300175150ustar00rootroot00000000000000MUSCLE (3.7) multiple sequence alignment MYG_PHYCA --------V-LSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRFKHLKT GLB5_PETMA PIVDTGSVAPLSAAEKTKIRSAWAPVYSTYETSGVDILVKFFTSTPAAQEFFPKFKGLTT HBB_HUMAN --------VHLTPEEKSAVTALWGKV--NVDEVGGEALGRLLVVYPWTQRFFESFGDLST HBA_HUMAN --------V-LSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHF----- . *: :. : *. * * : * .:: * : * * MYG_PHYCA EAEMKASEDLKKHGVTVLTALGAILKKKGH---HEAELKPLAQSHATKHKIPIKYLEFIS GLB5_PETMA ADQLKKSADVRWHAERIINAVNDAVASMDDTEKMSMKLRDLSGKHAKSFQVDPQYFKVLA HBB_HUMAN PDAVMGNPKVKAHGKKVLGAFSDGLAHLDN---LKGTFATLSELHCDKLHVDPENFRLLG HBA_HUMAN -DLSHGSAQVKGHGKKVADALTNAVAHVDD---MPNALSALSDLHAHKLRVDPVNFKLLS . .:. *. : *. : . : *: *. . .: : .:. MYG_PHYCA EAIIHVLHSRHPGDFGADAQGAMNKALELFRKDIAAKYKELGYQG GLB5_PETMA AVI---------ADTVAAGDAGFEKLMSMICILLRSAY------- HBB_HUMAN NVLVCVLAHHFGKEFTPPVQAAYQKVVAGVANALAHKYH------ HBA_HUMAN HCLLVTLAAHLPAEFTPAVHASLDKFLASVSTVLTSKYR------ : : . .. :* : . : * kalign-3.5.1/tests/data/clustal.good.2000066400000000000000000000012611515023132300175140ustar00rootroot00000000000000CLUSTAL W (1.81) multiple sequence alignment tRNA2 UCCGAUAUAGUGUAACGGCUAUCACAUCACGCUUUCACCGUGG-AGACCGGGGUUCGACU tRNA3 UCCGUGAUAGUUUAAUGGUCAGAAUGG-GCGCUUGUCGCGUGCCAGAUCGGGGUUCAAUU tRNA5 GGGCACAUGGCGCAGUUGGUAGCGCGCUUCCCUUGCAAGGAAGAGGUCAUCGGUUCGAUU tRNA1 GCGGAUUUAGCUCAGUUGGGAGAGCGCCAGACUGAAGAUCUGGAGGUCCUGUGUUCGAUC tRNA4 GCUCGUAUGGCGCAGUGG-UAGCGCAGCAGAUUGCAAAUCUGUUGGUCCUUAGUUCGAUC * * * * * * * **** * tRNA2 CCCCGUAUCGGAG tRNA3 CCCCGUCGCGGAG tRNA5 CCGGUUGCGUCCA tRNA1 CACAGAAUUCGCA tRNA4 CUGAGUGCGAGCU * kalign-3.5.1/tests/data/small.fa000066400000000000000000000003561515023132300164570ustar00rootroot00000000000000>1 GGGGGAAGGGGG >2 GGGGAAGGGGG >3 GGGGAAGGGGG >4 GGGGAAGGGG >5 GGGGGAAGGGGGG >6 GGGGGAAGGGG >7 GGGGGAAGGGGGA >8 GGGGGAAGGGGGG >9 GGGGGAAGGGGGG >10 GGGGAAGTTG >11 A >12 GGGGGGAAGGGGG >13 GGGGGAAGGGGGG >14 GGGAGT >15 GGGGAAGGGGG >16 G >17 Tkalign-3.5.1/tests/data/tiny.fa000066400000000000000000000000261515023132300163240ustar00rootroot00000000000000>2 A >1 GGGGGAAGGGGGG kalign-3.5.1/tests/data/tiny_internal.fa000066400000000000000000000000231515023132300202150ustar00rootroot00000000000000>1 GATTACA >2 GATTAkalign-3.5.1/tests/dssim.c000066400000000000000000000427461515023132300154220ustar00rootroot00000000000000#include "tldevel.h" #include "tlrng.h" #include "msa_struct.h" #include "msa_alloc.h" #include "msa_op.h" #include "alphabet.h" #define DSSIM_IMPORT #include "dssim.h" typedef enum { TMM = 0, TMI = 1, TMD = 2, TII = 3, TIM = 4, TDD = 5, TDM = 6 } trans_type; typedef enum { HMM_MATCH, HMM_INSERT, HMM_DELETE } state_type; struct hmm_param { double match_err_p; double insert_err_p; double indel_p; int n_observed_seq; int n_sim_seq; int len; int seed; int dna; }; struct hmm { double** match_emit; double** insert_emit; double** transition; struct rng_state* rng; int L; int len; }; int hmm_emit_simple(struct hmm *hmm, char **out,int *len); int sample_pick(double *p, int len, struct rng_state* rng, int *pick); char emit_letter(int c); char emit_letter_dna(int c); /* int hmm_init(struct hmm **hmm, int len, int seed); */ int hmm_init(struct hmm **hmm, struct hmm_param *p); int get_prior_emit(double **prior); int get_prior_emit_dna(double** prior); int get_prior_trans(double** prior); int pick(double *p, int len, struct rng_state *rng, int *pick); int hmm_print(struct hmm *m); int hmm_alloc(struct hmm **hmm, int len, int seed, int dna); void hmm_free(struct hmm *n); int hmm_param_init(struct hmm_param **param); void hmm_param_free(struct hmm_param *p); int dssim_get_fasta(struct msa **msa, int n_seq, int n_obs, int dna,int len, int seed) { struct msa* m = NULL; struct hmm* hmm = NULL; struct hmm_param* p = NULL; char* tmp_seq = NULL; int r_len; /* RUN(alloc_msa(&m)); */ hmm_param_init(&p); p->n_sim_seq = n_seq; p->n_observed_seq = n_obs; p->len = len; p->seed = seed; p->dna = dna; if(n_seq > 100){ p->indel_p = 0.02; }else{ p->indel_p = 0.04; } RUN(hmm_init(&hmm, p)); /* hmm_print(hmm); */ MMALLOC(m, sizeof(struct msa)); m->sequences = NULL; m->alloc_numseq = n_seq; m->numseq = n_seq; m->num_profiles = 0; m->L = ALPHA_UNDEFINED; m->biotype = ALN_BIOTYPE_UNDEF; m->aligned = 0; m->alnlen = 0; m->plen = NULL; m->sip = NULL; m->nsip = NULL; m->seq_distances = NULL; m->col_confidence = NULL; m->seq_weights = NULL; m->run_parallel = 0; m->consistency_table = NULL; m->quiet = 1; MMALLOC(m->sequences, sizeof(struct msa_seq*) * m->alloc_numseq); for(int i = 0; i < 128; i++){ m->letter_freq[i] = 0; } m->numseq = 0; for(int i = 0; i < p->n_sim_seq;i++){ hmm_emit_simple(hmm, &tmp_seq, &r_len); /* LOG_MSG("%s", tmp_seq); */ m->sequences[i] = NULL; struct msa_seq* seq = NULL; MMALLOC(seq, sizeof(struct msa_seq)); seq->name = NULL; seq->seq = NULL; seq->s = NULL; seq->gaps = NULL; seq->confidence = NULL; seq->len = r_len; seq->alloc_len = r_len+1; seq->rank = i; MMALLOC(seq->name, sizeof(char)* MSA_NAME_LEN); snprintf(seq->name, MSA_NAME_LEN,"%d",i+1); MMALLOC(seq->seq, sizeof(char) * seq->alloc_len); MMALLOC(seq->s, sizeof(uint8_t) * seq->alloc_len); MMALLOC(seq->gaps, sizeof(int) * (seq->alloc_len+1)); for(int j = 0;j < seq->alloc_len+1;j++){ seq->gaps[j] = 0; } for(int j = 0; j < r_len;j++){ m->letter_freq[(int)tmp_seq[j]]++; seq->seq[j] = tmp_seq[j]; } MFREE(tmp_seq); seq->seq[r_len] = 0; m->sequences[i] = seq; m->numseq++; } /* tl_random_double(struct rng_state *rng) */ hmm_param_free(p); hmm_free(hmm); RUN(detect_alphabet(m)); /* LOG_MSG("%d biotype",m->biotype); */ RUN(detect_aligned(m)); /* LOG_MSG("%d aligned ",m->aligned); */ RUN(set_sip_nsip(m)); /* LOG_MSG("%d aligned ",m->aligned); */ *msa = m; return OK; ERROR: return FAIL; } /* int main(int argc, char *argv[]) */ /* { */ /* struct msa* m = NULL; */ /* dssim_get_fasta(&m, 20, 10, 250, 1); */ /* for(int i= 0; i < m->numseq;i++){ */ /* fprintf(stdout,">Seq_%d\n%s\n",i, m->sequences[i]->seq); */ /* } */ /* kalign_free_msa(m); */ /* return EXIT_SUCCESS; */ /* ERROR: */ /* kalign_free_msa(m); */ /* return EXIT_FAILURE; */ /* } */ int hmm_emit_simple(struct hmm *hmm, char **out,int *len) { char* seq = NULL; int n_alloc = 256; int n = 0; int pos = 0; int pick; state_type state = HMM_INSERT; double r; double sum; state = tl_random_int(hmm->rng, 3); MMALLOC(seq, sizeof(char) * n_alloc); seq[0] = 0; while(pos+1 < hmm->len){ /* transiation; */ switch (state) { case HMM_MATCH: r = tl_random_double(hmm->rng); sum = hmm->transition[pos][TMM]; if(r < sum){ state = HMM_MATCH; }else{ sum += hmm->transition[pos][TMI]; if(r < sum){ state = HMM_INSERT; }else{ sum += hmm->transition[pos][TMD]; if(r < sum){ state = HMM_DELETE; } } } pos++; break; case HMM_INSERT: r = tl_random_double(hmm->rng); sum = hmm->transition[pos][TII]; if(r < sum){ state = HMM_INSERT; }else{ state = HMM_MATCH; pos++; } break; case HMM_DELETE: r = tl_random_double(hmm->rng); sum = hmm->transition[pos][TDD]; if(r < sum){ state = HMM_DELETE; pos++; }else{ state = HMM_MATCH; pos++; } break; } /* Emit */ switch (state) { case HMM_MATCH: sample_pick(hmm->match_emit[pos], 20, hmm->rng,&pick); if(hmm->L == 20){ seq[n] = emit_letter(pick); }else{ seq[n] = emit_letter_dna(pick); } n++; if(n == n_alloc){ n_alloc = n_alloc + n_alloc / 2; MREALLOC(seq, sizeof(char) * n_alloc); } break; case HMM_INSERT: sample_pick(hmm->insert_emit[pos], 20, hmm->rng,&pick); if(hmm->L == 20){ seq[n] = emit_letter(pick); }else{ seq[n] = emit_letter_dna(pick); } n++; if(n == n_alloc){ n_alloc = n_alloc + n_alloc / 2; MREALLOC(seq, sizeof(char) * n_alloc); } break; case HMM_DELETE: break; } seq[n] = 0; /* n++; */ if(n == n_alloc){ n_alloc = n_alloc + n_alloc / 2; MREALLOC(seq, sizeof(char) * n_alloc); } /* LOG_MSG("%d %s n:%d state:%d",pos,seq,n ,state); */ } seq[n] = 0; *len = n; *out = seq; return OK; ERROR: return FAIL; } int sample_pick(double *p, int len, struct rng_state* rng, int *pick) { double sum = 0.0; double r = 0.0; int sel = -1; r =tl_random_double(rng); sum = 0.0; for(int i = 0; i < len;i++){ sum += p[i]; if(r < sum){ sel = i; break; } } /* LOG_MSG("Selected: %d (%d) r:%f %f", sel, len, r, sum); */ /* if(sel == -1){ */ /* } */ *pick = sel; return OK; } char emit_letter(int c) { char alphabet[20] = "ACDEFGHIKLMNPQRSTVWY"; return alphabet[c]; } char emit_letter_dna(int c) { char alphabet[4] = "ACGT"; return alphabet[c]; } int hmm_init(struct hmm **hmm, struct hmm_param* p) { struct hmm* n = NULL; double* prior_e = NULL; double* prior_t = NULL; double sum = 0.0; double r = 0.0; int pick; if(p->dna == 0){ RUN(get_prior_emit(&prior_e)); RUN(get_prior_trans(&prior_t)); }else{ RUN(get_prior_emit_dna(&prior_e)); RUN(get_prior_trans(&prior_t)); } prior_t[TMM] = 1.0 - p->indel_p; prior_t[TMI] = p->indel_p / 2.0; prior_t[TMD] = p->indel_p / 2.0; prior_t[TMM] = prior_t[TMM] / (prior_t[TMM] + prior_t[TMI] + prior_t[TMD]); prior_t[TMI] = prior_t[TMI] / (prior_t[TMM] + prior_t[TMI] + prior_t[TMD]); prior_t[TMD] = prior_t[TMD] / (prior_t[TMM] + prior_t[TMI] + prior_t[TMD]); RUN(hmm_alloc(&n, p->len,p->seed,p->dna)); /* Start state... */ /* n->transition[0][TMM] = 0.5; */ /* n->transition[0][TMI] = 0.5; */ /* n->transition[0][TMD] = 0.0; */ for(int i = 0; i < p->len;i++){ for(int j = 0; j < n->L;j++){ n->match_emit[i][j] = 0.0; n->insert_emit[i][j] = 0.0; } /* match */ /* pick =tl_random_int(n->rng, 20); */ sample_pick(prior_e, n->L, n->rng, &pick); for(int j = 0; j < p->n_observed_seq;j++){ r = tl_random_double(n->rng); if(r < p->match_err_p){ int c = tl_random_int(n->rng, n->L); n->match_emit[i][c] += 1.0; }else{ n->match_emit[i][pick] += 1.0; } } /* insert */ /* pick =tl_random_int(n->rng, 20); */ sample_pick(prior_e, n->L, n->rng, &pick); for(int j = 0; j < p->n_observed_seq;j++){ r = tl_random_double(n->rng); if(r < p->insert_err_p){ int c = tl_random_int(n->rng, n->L); n->insert_emit[i][c] += 1.0; }else{ n->insert_emit[i][pick] += 1.0; } } for(int j = 0; j < n->L;j++){ n->match_emit[i][j] += prior_e[j]; n->insert_emit[i][j] += prior_e[j]; } sum = 0.0; for(int j = 0; j < n->L;j++){ sum += n->match_emit[i][j]; } for(int j = 0; j < n->L;j++){ n->match_emit[i][j]/=sum; } sum = 0.0; for(int j = 0; j < n->L;j++){ sum += n->insert_emit[i][j]; } for(int j = 0; j < n->L;j++){ n->insert_emit[i][j]/=sum; } /* transitions */ for(int j = 0; j < 7;j++){ n->transition[i][j] = prior_t[j]; } } gfree(prior_e); gfree(prior_t); *hmm = n; return OK; ERROR: return FAIL; } int get_prior_emit(double** prior) { double* p = NULL; double sum = 0.0; RUN(galloc(&p , 20)); p[0] = 0.075520; /* A */ p[1] = 0.016973; /* C */ p[2] = 0.053029; /* D */ p[3] = 0.063204; /* E */ p[4] = 0.040762; /* F */ p[5] = 0.068448; /* G */ p[6] = 0.022406; /* H */ p[7] = 0.057284; /* I */ p[8] = 0.059398; /* K */ p[9] = 0.093399; /* L */ p[10] = 0.023569; /* M */ p[11] = 0.045293; /* N */ p[12] = 0.049262; /* P */ p[13] = 0.040231; /* Q */ p[14] = 0.051573; /* R */ p[15] = 0.072214; /* S */ p[16] = 0.057454; /* T */ p[17] = 0.065252; /* V */ p[18] = 0.012513; /* W */ p[19] = 0.031985; /* Y */ sum = 0.0; for(int i = 0; i < 20;i++){ sum += p[i]; } for(int i = 0; i < 20;i++){ p[i]/= sum; } *prior = p; return OK; ERROR: return FAIL; } int get_prior_emit_dna(double** prior) { double* p = NULL; double sum = 0.0; RUN(galloc(&p , 4)); p[0] = 0.2; /* A */ p[1] = 0.3; /* C */ p[2] = 0.3; /* G */ p[3] = 0.2; /* T */ sum = 0.0; for(int i = 0; i < 4;i++){ sum += p[i]; } for(int i = 0; i < 4;i++){ p[i]/= sum; } *prior = p; return OK; ERROR: return FAIL; } int get_prior_trans(double** prior) { double* p = NULL; RUN(galloc(&p , 7)); p[TMM] = 0.96; p[TMI] = 0.02; p[TMD] = 0.02; p[TII] = 0.50; p[TIM] = 0.50; p[TDD] = 0.50; p[TDM] = 0.50; *prior = p; return OK; ERROR: return FAIL; } int hmm_print(struct hmm *m) { ASSERT(m == NULL,"No hmm"); LOG_MSG("Emission: MATCH "); for(int i = 0; i < m->len;i++){ fprintf(stdout," %4d ", i); for(int j = 0; j < m->L;j++){ fprintf(stdout,"%0.2f ", m->match_emit[i][j]); } fprintf(stdout,"\n"); } fprintf(stdout,"\n"); LOG_MSG("Emission: Insert "); for(int i = 0; i < m->len;i++){ fprintf(stdout," %4d ", i); for(int j = 0; j < m->L;j++){ fprintf(stdout,"%0.2f ", m->insert_emit[i][j]); } fprintf(stdout,"\n"); } fprintf(stdout,"\n"); LOG_MSG("Transition:"); for(int i = 0; i < m->len;i++){ fprintf(stdout," %4d ", i); for(int j = 0; j < 7;j++){ fprintf(stdout,"%0.2f ", m->transition[i][j]); } fprintf(stdout,"\n"); } fprintf(stdout,"\n"); return OK; ERROR: return FAIL; } int hmm_alloc(struct hmm **hmm, int len, int seed, int dna) { struct hmm* n = NULL; ASSERT(len >0 ,"len has to be > 0"); MMALLOC(n, sizeof(struct hmm)); n->match_emit = NULL; n->insert_emit = NULL; n->transition = NULL; n->rng = init_rng(seed); if(!dna){ n->L = 20; }else{ n->L = 4; } n->len = len; galloc(&n->match_emit,n->len, n->L); galloc(&n->insert_emit,n->len, n->L); galloc(&n->transition, n->len, 7); *hmm = n; return OK; ERROR: return FAIL; } void hmm_free(struct hmm *n) { if(n){ gfree(n->match_emit); gfree(n->insert_emit); gfree(n->transition); free_rng(n->rng); MFREE(n); } } int hmm_param_init(struct hmm_param **param) { struct hmm_param* p = NULL; MMALLOC(p, sizeof(struct hmm_param)); p->insert_err_p = 0.25; p->match_err_p = 0.05; p->indel_p = 0.04; p->n_sim_seq = 20; p->n_observed_seq = 10; p->len = 250; p->seed = 42; p->dna = 0; *param = p; return OK; ERROR: return FAIL; } void hmm_param_free(struct hmm_param *p) { if(p){ MFREE(p); } } kalign-3.5.1/tests/dssim.h000066400000000000000000000005521515023132300154140ustar00rootroot00000000000000#ifndef DSSIM_H #define DSSIM_H #include "kalign/kalign.h" #ifdef DSSIM_IMPORT #define EXTERN #else #define EXTERN extern #endif EXTERN int dssim_get_fasta(struct msa **msa, int n_seq, int n_obs, int dna,int len, int seed); /* EXTERN int dssim_get_fasta(struct msa** msa, int n_seq, int n_obs,int len,int seed); */ #undef DSSIM_IMPORT #undef EXTERN #endif kalign-3.5.1/tests/dssim_test.c000066400000000000000000000075311515023132300164520ustar00rootroot00000000000000#include "tldevel.h" #include "tlrng.h" #include "kalign/kalign.h" #include "msa_struct.h" #include "msa_sort.h" #include "msa_op.h" #include "dssim.h" int msa_restore_ord_seq_order(struct msa* m); int msa_remove_gaps(struct msa *m); /* int test_consistency(int num_tests, int numseq, int seed); */ int test_consistency(int num_tests, int numseq,int dna,int seed); void progress_bar(int c, int t, int w); int main(void) { LOG_MSG("DSSim - a simplistic sequence simulator."); LOG_MSG("Protein alignments - 20 seq"); RUN(test_consistency(1000,20,0,42)); LOG_MSG("Protein alignments - 1000 seq"); RUN(test_consistency(10,1000,0,42)); LOG_MSG("Protein alignments - 10000 seq"); RUN(test_consistency(2,2000,0,42)); LOG_MSG("DNA alignments - 20 seq"); RUN(test_consistency(1000,20,1,42)); LOG_MSG("DNA alignments - 1000 seq"); RUN(test_consistency(10,1000,1,42)); LOG_MSG("DNA alignments - 10000 seq"); RUN(test_consistency(2,2000,1,42)); return EXIT_SUCCESS; ERROR: return EXIT_FAILURE; } int test_consistency(int num_tests, int numseq,int dna,int seed) { struct msa* m = NULL; struct msa* m2 = NULL; struct rng_state* rng = NULL; RUNP(rng = init_rng(seed)); for(int i = 0; i < num_tests;i++){ int local_seed = tl_random_int(rng, 1000000); int t1 = tl_random_int(rng, 8) + 1; int t2 = tl_random_int(rng, 8) + 1; while(t1 == t2){ t2 = tl_random_int(rng, 8) + 1; } float score = 0.0; dssim_get_fasta(&m, numseq, 10,dna, 45, local_seed); m->quiet = 1; msa_cpy(&m2, m); msa_shuffle_seq(m, rng); msa_shuffle_seq(m2, rng); kalign_run(m, t1, KALIGN_TYPE_UNDEFINED,0.0,0.0,0.0, 0, 0); kalign_run(m2, t2, KALIGN_TYPE_UNDEFINED,0.0,0.0,0.0, 0, 0); kalign_msa_compare(m, m2, &score); if(score != 100.0f){ LOG_MSG("Testing %d : %d %d %f", i , t1 ,t2,score); kalign_write_msa(m, NULL, "msf"); } kalign_free_msa(m); kalign_free_msa(m2); m = NULL; m2 = NULL; progress_bar(i, num_tests, 50); } progress_bar(num_tests, num_tests, 50); fprintf(stdout,"\n"); free_rng(rng); return OK; ERROR: return FAIL; } int msa_remove_gaps(struct msa *m) { int aln_len = m->alnlen; for(int i = 0; i < m->numseq;i++){ struct msa_seq* s = m->sequences[i]; int c = 0; for(int j = 0; j < aln_len;j++){ if(s->seq[j] != '-'){ s->seq[c] = s->seq[j]; c++; } } s->len = c; m->sequences[i]->rank = atoi(m->sequences[i]->name); } dealign_msa(m); return OK; } int msa_restore_ord_seq_order(struct msa* m) { for(int i = 0; i < m->numseq;i++){ m->sequences[i]->rank = atoi(m->sequences[i]->name); } RUN(msa_sort_rank(m)); return OK; ERROR: return FAIL; } void progress_bar(int c, int t, int w) { double progress = (double) c / (double) t; int l = (int)round(progress * (double) w); fprintf(stdout,"\r["); for(int i = 0; i < w;i++){ if(i < l){ fprintf(stdout,"="); }else{ fprintf(stdout," "); } } fprintf(stdout,"] %3d%%", (int)round(progress * 100.0)); fflush(stdout); } kalign-3.5.1/tests/kalign_api_test.c000066400000000000000000000552431515023132300174340ustar00rootroot00000000000000/* * kalign_api_test.c — comprehensive tests for the kalign public C API. * * Covers the functions not exercised by the existing test suite: * - kalign_run_seeded() (VSM, consistency, tree seed/noise) * - kalign_run_dist_scale() (VSM, seq_weights) * - kalign_run_realign() (realign iterations) * - kalign_post_realign() (post-align realign) * - kalign_run() with refine modes * - kalign_msa_compare_detailed() * - kalign_msa_compare_with_mask() * - kalign_check_msa() * - reformat_settings_msa() * - kalign_write_msa() round-trip fasta * * Each test: * 1. Reads input from the file passed as argv[1] * 2. Calls the API function * 3. Asserts structural correctness (alnlen>0, all seqs same length, * non-gap chars preserved, scores in range) * 4. Returns 0 on success, -1 on failure * * Exit code: EXIT_SUCCESS if all pass, EXIT_FAILURE otherwise. */ #include #include #include #include #include "kalign/kalign.h" #include "msa_struct.h" #include "msa_cmp.h" /* ------------------------------------------------------------------ */ /* helpers */ /* ------------------------------------------------------------------ */ /* Count non-gap characters in an aligned sequence string. */ static int count_residues(const char *seq) { int n = 0; for (int i = 0; seq[i]; i++) { if (seq[i] != '-') n++; } return n; } /* Record the ungapped lengths of all sequences before alignment. */ static int *snapshot_lengths(struct msa *m) { int *lens = malloc(sizeof(int) * m->numseq); if (!lens) return NULL; for (int i = 0; i < m->numseq; i++) { lens[i] = m->sequences[i]->len; } return lens; } /* Verify basic alignment invariants: * - alnlen > 0 * - every seq string has length == alnlen * - every seq preserves its original residue count * Returns 0 on success, -1 on failure. */ static int verify_alignment(struct msa *m, int *orig_lens, const char *label) { if (m->alnlen <= 0) { fprintf(stderr, " [%s] FAIL: alnlen=%d\n", label, m->alnlen); return -1; } for (int i = 0; i < m->numseq; i++) { if (m->sequences[i]->seq == NULL) { fprintf(stderr, " [%s] FAIL: seq %d is NULL\n", label, i); return -1; } int slen = (int)strlen(m->sequences[i]->seq); if (slen != m->alnlen) { fprintf(stderr, " [%s] FAIL: seq %d strlen=%d != alnlen=%d\n", label, i, slen, m->alnlen); return -1; } if (orig_lens) { int res = count_residues(m->sequences[i]->seq); if (res != orig_lens[i]) { fprintf(stderr, " [%s] FAIL: seq %d residues=%d != orig=%d\n", label, i, res, orig_lens[i]); return -1; } } } return 0; } /* Read input, returning a fresh MSA. Caller must free with kalign_free_msa. */ static struct msa *read_input(const char *path) { struct msa *m = NULL; if (kalign_read_input((char *)path, &m, 1) != 0 || m == NULL) { fprintf(stderr, " ERROR: cannot read %s\n", path); return NULL; } return m; } /* ------------------------------------------------------------------ */ /* individual test functions */ /* ------------------------------------------------------------------ */ static int test_run_with_refine(const char *input) { /* Test KALIGN_REFINE_ALL and KALIGN_REFINE_CONFIDENT */ int modes[] = {KALIGN_REFINE_ALL, KALIGN_REFINE_CONFIDENT}; const char *names[] = {"REFINE_ALL", "REFINE_CONFIDENT"}; for (int m = 0; m < 2; m++) { struct msa *msa = read_input(input); if (!msa) return -1; int *lens = snapshot_lengths(msa); int rv = kalign_run(msa, 1, -1, -1, -1, -1, modes[m], 0); if (rv != 0) { fprintf(stderr, " kalign_run(%s) returned %d\n", names[m], rv); free(lens); kalign_free_msa(msa); return -1; } if (verify_alignment(msa, lens, names[m]) != 0) { free(lens); kalign_free_msa(msa); return -1; } fprintf(stdout, " %s: OK (alnlen=%d)\n", names[m], msa->alnlen); free(lens); kalign_free_msa(msa); } return 0; } static int test_run_dist_scale(const char *input) { struct msa *msa = read_input(input); if (!msa) return -1; int *lens = snapshot_lengths(msa); /* vsm_amax=2.0, seq_weights=1.0 */ int rv = kalign_run_dist_scale(msa, 1, -1, -1, -1, -1, 0, 0, 0.0f, 2.0f, 1.0f); if (rv != 0) { fprintf(stderr, " kalign_run_dist_scale returned %d\n", rv); free(lens); kalign_free_msa(msa); return -1; } if (verify_alignment(msa, lens, "dist_scale") != 0) { free(lens); kalign_free_msa(msa); return -1; } fprintf(stdout, " vsm_amax=2.0, seq_weights=1.0: OK (alnlen=%d)\n", msa->alnlen); free(lens); kalign_free_msa(msa); return 0; } static int test_run_seeded(const char *input) { struct msa *msa = read_input(input); if (!msa) return -1; int *lens = snapshot_lengths(msa); /* tree_seed=42, tree_noise=0, vsm_amax=2.0, consistency_anchors=5 */ int rv = kalign_run_seeded(msa, 1, -1, -1, -1, -1, 0, 0, 42, 0.0f, 0.0f, 2.0f, 0.0f, 5, 2.0f); if (rv != 0) { fprintf(stderr, " kalign_run_seeded returned %d\n", rv); free(lens); kalign_free_msa(msa); return -1; } if (verify_alignment(msa, lens, "seeded") != 0) { free(lens); kalign_free_msa(msa); return -1; } fprintf(stdout, " seeded + consistency: OK (alnlen=%d)\n", msa->alnlen); free(lens); kalign_free_msa(msa); return 0; } static int test_run_realign(const char *input) { struct msa *msa = read_input(input); if (!msa) return -1; int *lens = snapshot_lengths(msa); /* realign_iterations=1, vsm_amax=2.0 */ int rv = kalign_run_realign(msa, 1, -1, -1, -1, -1, 0, 0, 0.0f, 2.0f, 1, 0.0f, 0, 2.0f); if (rv != 0) { fprintf(stderr, " kalign_run_realign returned %d\n", rv); free(lens); kalign_free_msa(msa); return -1; } if (verify_alignment(msa, lens, "realign") != 0) { free(lens); kalign_free_msa(msa); return -1; } fprintf(stdout, " realign=1, vsm=2.0: OK (alnlen=%d)\n", msa->alnlen); free(lens); kalign_free_msa(msa); return 0; } static int test_post_realign(const char *input) { /* First do a normal alignment, then post-realign the result */ struct msa *msa = read_input(input); if (!msa) return -1; int *lens = snapshot_lengths(msa); int rv = kalign_run(msa, 1, -1, -1, -1, -1, 0, 0); if (rv != 0) { fprintf(stderr, " initial kalign_run returned %d\n", rv); free(lens); kalign_free_msa(msa); return -1; } rv = kalign_post_realign(msa, 1, -1, -1, -1, -1, 0, 0, 0.0f, 0.0f, 1, 0.0f); if (rv != 0) { fprintf(stderr, " kalign_post_realign returned %d\n", rv); free(lens); kalign_free_msa(msa); return -1; } if (verify_alignment(msa, lens, "post_realign") != 0) { free(lens); kalign_free_msa(msa); return -1; } fprintf(stdout, " post_realign: OK (alnlen=%d)\n", msa->alnlen); free(lens); kalign_free_msa(msa); return 0; } static int test_ensemble_with_realign(const char *input) { struct msa *msa = read_input(input); if (!msa) return -1; int *lens = snapshot_lengths(msa); /* ensemble=3, vsm=2.0, realign=1, refine=CONFIDENT */ int rv = kalign_ensemble(msa, 1, -1, 3, -1.0f, -1.0f, -1.0f, 42, 0, NULL, KALIGN_REFINE_CONFIDENT, 0.0f, 2.0f, 1, 0.0f, 0, 2.0f); if (rv != 0) { fprintf(stderr, " kalign_ensemble+realign returned %d\n", rv); free(lens); kalign_free_msa(msa); return -1; } if (verify_alignment(msa, lens, "ens+realign") != 0) { free(lens); kalign_free_msa(msa); return -1; } /* Also check col_confidence */ if (msa->col_confidence == NULL) { fprintf(stderr, " [ens+realign] FAIL: col_confidence is NULL\n"); free(lens); kalign_free_msa(msa); return -1; } for (int i = 0; i < msa->alnlen; i++) { if (msa->col_confidence[i] < 0.0f || msa->col_confidence[i] > 1.0f) { fprintf(stderr, " [ens+realign] FAIL: col_confidence[%d]=%.3f\n", i, msa->col_confidence[i]); free(lens); kalign_free_msa(msa); return -1; } } fprintf(stdout, " ensemble+realign+refine: OK (alnlen=%d)\n", msa->alnlen); free(lens); kalign_free_msa(msa); return 0; } static int test_compare_detailed(const char *input) { /* Align, then compare to self — should get perfect scores */ struct msa *ref = read_input(input); struct msa *test_msa = read_input(input); if (!ref || !test_msa) return -1; kalign_run(ref, 1, -1, -1, -1, -1, 0, 0); kalign_run(test_msa, 1, -1, -1, -1, -1, 0, 0); struct poar_score out; memset(&out, 0, sizeof(out)); int rv = kalign_msa_compare_detailed(ref, test_msa, -1.0f, &out); if (rv != 0) { fprintf(stderr, " kalign_msa_compare_detailed returned %d\n", rv); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } /* Self-comparison: recall, precision, f1 should all be 1.0 */ if (fabs(out.recall - 1.0) > 0.001) { fprintf(stderr, " FAIL: recall=%.4f (expected 1.0)\n", out.recall); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } if (fabs(out.precision - 1.0) > 0.001) { fprintf(stderr, " FAIL: precision=%.4f (expected 1.0)\n", out.precision); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } if (fabs(out.f1 - 1.0) > 0.001) { fprintf(stderr, " FAIL: f1=%.4f (expected 1.0)\n", out.f1); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } if (fabs(out.tc - 1.0) > 0.001) { fprintf(stderr, " FAIL: tc=%.4f (expected 1.0)\n", out.tc); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } if (out.ref_pairs <= 0 || out.test_pairs <= 0 || out.common <= 0) { fprintf(stderr, " FAIL: pair counts ref=%lld test=%lld common=%lld\n", (long long)out.ref_pairs, (long long)out.test_pairs, (long long)out.common); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } if (out.ref_pairs != out.common || out.test_pairs != out.common) { fprintf(stderr, " FAIL: self-compare pairs mismatch ref=%lld test=%lld common=%lld\n", (long long)out.ref_pairs, (long long)out.test_pairs, (long long)out.common); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } fprintf(stdout, " compare_detailed self: recall=%.3f prec=%.3f f1=%.3f tc=%.3f pairs=%lld OK\n", out.recall, out.precision, out.f1, out.tc, (long long)out.common); kalign_free_msa(ref); kalign_free_msa(test_msa); return 0; } static int test_compare_with_mask(const char *input) { struct msa *ref = read_input(input); struct msa *test_msa = read_input(input); if (!ref || !test_msa) return -1; kalign_run(ref, 1, -1, -1, -1, -1, 0, 0); kalign_run(test_msa, 1, -1, -1, -1, -1, 0, 0); /* Create a mask that includes all columns */ int n_cols = ref->alnlen; int *mask = malloc(sizeof(int) * n_cols); if (!mask) { kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } for (int i = 0; i < n_cols; i++) mask[i] = 1; struct poar_score out; memset(&out, 0, sizeof(out)); int rv = kalign_msa_compare_with_mask(ref, test_msa, mask, n_cols, &out); if (rv != 0) { fprintf(stderr, " kalign_msa_compare_with_mask returned %d\n", rv); free(mask); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } /* All columns masked in → same as full comparison → perfect scores */ if (fabs(out.recall - 1.0) > 0.001 || fabs(out.precision - 1.0) > 0.001) { fprintf(stderr, " FAIL: mask-all recall=%.4f prec=%.4f\n", out.recall, out.precision); free(mask); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } /* Now test with partial mask (first half only) */ for (int i = n_cols / 2; i < n_cols; i++) mask[i] = 0; memset(&out, 0, sizeof(out)); rv = kalign_msa_compare_with_mask(ref, test_msa, mask, n_cols, &out); if (rv != 0) { fprintf(stderr, " kalign_msa_compare_with_mask (partial) returned %d\n", rv); free(mask); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } /* Partial mask self-compare should still give perfect scores */ if (fabs(out.recall - 1.0) > 0.001) { fprintf(stderr, " FAIL: partial mask recall=%.4f\n", out.recall); free(mask); kalign_free_msa(ref); kalign_free_msa(test_msa); return -1; } fprintf(stdout, " compare_with_mask: full-mask OK, partial-mask OK\n"); free(mask); kalign_free_msa(ref); kalign_free_msa(test_msa); return 0; } static int test_check_msa(const char *input) { struct msa *msa = read_input(input); if (!msa) return -1; /* kalign_check_msa checks for duplicate sequences. * Our test files shouldn't have exact duplicates. */ msa->quiet = 1; int rv = kalign_check_msa(msa, 0); if (rv != 0) { fprintf(stderr, " kalign_check_msa returned %d\n", rv); kalign_free_msa(msa); return -1; } fprintf(stdout, " check_msa: OK (%d sequences validated)\n", msa->numseq); kalign_free_msa(msa); return 0; } static int test_reformat_settings(const char *input) { struct msa *msa = read_input(input); if (!msa) return -1; /* First align so we have gaps */ int rv = kalign_run(msa, 1, -1, -1, -1, -1, 0, 0); if (rv != 0) { fprintf(stderr, " initial align failed\n"); kalign_free_msa(msa); return -1; } /* Test rename */ rv = reformat_settings_msa(msa, 1, 0); if (rv != 0) { fprintf(stderr, " reformat_settings_msa(rename) returned %d\n", rv); kalign_free_msa(msa); return -1; } /* Verify names were changed to SEQ1, SEQ2, etc. */ for (int i = 0; i < msa->numseq; i++) { char expected[32]; snprintf(expected, sizeof(expected), "SEQ%d", i + 1); if (strncmp(msa->sequences[i]->name, expected, strlen(expected)) != 0) { fprintf(stderr, " FAIL: seq %d name='%s' expected='%s'\n", i, msa->sequences[i]->name, expected); kalign_free_msa(msa); return -1; } } fprintf(stdout, " reformat rename: OK\n"); /* Test unalign — zeroes the gaps[] array and sets status to unaligned. * Note: dealign_msa operates on the internal gaps[] representation, * not on seq->seq (which holds finalised text with '-' chars). */ rv = reformat_settings_msa(msa, 0, 1); if (rv != 0) { fprintf(stderr, " reformat_settings_msa(unalign) returned %d\n", rv); kalign_free_msa(msa); return -1; } /* After unalign, all gaps[] entries should be zero */ for (int i = 0; i < msa->numseq; i++) { for (int j = 0; j <= msa->sequences[i]->len; j++) { if (msa->sequences[i]->gaps[j] != 0) { fprintf(stderr, " FAIL: seq %d gaps[%d]=%d after unalign\n", i, j, msa->sequences[i]->gaps[j]); kalign_free_msa(msa); return -1; } } } fprintf(stdout, " reformat unalign: OK (gaps[] zeroed)\n"); kalign_free_msa(msa); return 0; } static int test_write_roundtrip(const char *input) { /* Align, write to fasta, read back, compare */ struct msa *msa = read_input(input); if (!msa) return -1; int rv = kalign_run(msa, 1, -1, -1, -1, -1, 0, 0); if (rv != 0) { kalign_free_msa(msa); return -1; } const char *tmpfile = "test_roundtrip.fa"; rv = kalign_write_msa(msa, (char *)tmpfile, "fasta"); if (rv != 0) { fprintf(stderr, " kalign_write_msa(fasta) returned %d\n", rv); kalign_free_msa(msa); return -1; } /* Read it back */ struct msa *msa2 = NULL; rv = kalign_read_input((char *)tmpfile, &msa2, 1); if (rv != 0 || msa2 == NULL) { fprintf(stderr, " failed to read back written fasta\n"); kalign_free_msa(msa); remove(tmpfile); return -1; } /* Compare: same number of sequences, same alignment content */ if (msa->numseq != msa2->numseq) { fprintf(stderr, " FAIL: numseq %d vs %d\n", msa->numseq, msa2->numseq); kalign_free_msa(msa); kalign_free_msa(msa2); remove(tmpfile); return -1; } /* Use kalign_msa_compare for a real score check */ float score = 0; rv = kalign_msa_compare(msa, msa2, &score); if (rv != 0) { fprintf(stderr, " kalign_msa_compare on roundtrip returned %d\n", rv); kalign_free_msa(msa); kalign_free_msa(msa2); remove(tmpfile); return -1; } if (fabsf(score - 100.0f) > 0.01f) { fprintf(stderr, " FAIL: roundtrip score=%.2f (expected 100.0)\n", score); kalign_free_msa(msa); kalign_free_msa(msa2); remove(tmpfile); return -1; } fprintf(stdout, " write fasta roundtrip: score=%.1f OK\n", score); kalign_free_msa(msa); kalign_free_msa(msa2); remove(tmpfile); return 0; } /* ------------------------------------------------------------------ */ /* main: run all tests */ /* ------------------------------------------------------------------ */ int main(int argc, char *argv[]) { if (argc <= 1) { fprintf(stderr, "Usage: %s \n", argv[0]); return EXIT_FAILURE; } const char *input = argv[1]; int ret = EXIT_SUCCESS; int pass = 0, fail = 0; struct { const char *name; int (*fn)(const char *); } tests[] = { {"kalign_run + refine", test_run_with_refine}, {"kalign_run_dist_scale (VSM)", test_run_dist_scale}, {"kalign_run_seeded (consistency)", test_run_seeded}, {"kalign_run_realign", test_run_realign}, {"kalign_post_realign", test_post_realign}, {"kalign_ensemble + realign", test_ensemble_with_realign}, {"kalign_msa_compare_detailed", test_compare_detailed}, {"kalign_msa_compare_with_mask", test_compare_with_mask}, {"kalign_check_msa", test_check_msa}, {"reformat_settings_msa", test_reformat_settings}, {"write fasta roundtrip", test_write_roundtrip}, }; int n_tests = (int)(sizeof(tests) / sizeof(tests[0])); fprintf(stdout, "=== Kalign API Tests (%d tests) ===\n\n", n_tests); for (int i = 0; i < n_tests; i++) { fprintf(stdout, "Test %d/%d: %s\n", i + 1, n_tests, tests[i].name); if (tests[i].fn(input) != 0) { fprintf(stdout, " FAIL\n\n"); fail++; ret = EXIT_FAILURE; } else { fprintf(stdout, " PASS\n\n"); pass++; } } fprintf(stdout, "=== Results: %d passed, %d failed (of %d) ===\n", pass, fail, n_tests); return ret; } kalign-3.5.1/tests/kalign_cmp_test.c000066400000000000000000000011041515023132300174250ustar00rootroot00000000000000#include "stdio.h" #include "stdlib.h" #include "kalign/kalign.h" int main(int argc, char *argv[]) { struct msa* r = NULL; struct msa* t = NULL; fprintf(stdout,"inputs: %d\n", argc); if(argc == 3){ kalign_read_input(argv[1], &r,1); kalign_read_input(argv[2], &t,1); float score = 0.0; kalign_msa_compare(r, t, &score); kalign_free_msa(r); kalign_free_msa(t); fprintf(stdout,"Aln score : %f\n", score); } return 0; } kalign-3.5.1/tests/kalign_ensemble_test.c000066400000000000000000000254221515023132300204510ustar00rootroot00000000000000#include #include #include #include "kalign/kalign.h" #include "msa_struct.h" static int test_ensemble_confidence(const char *input_file); static int test_poar_round_trip(const char *input_file); static int test_min_support(const char *input_file); int main(int argc, char *argv[]) { int ret = EXIT_SUCCESS; if(argc <= 1){ fprintf(stderr, "Usage: %s \n", argv[0]); return EXIT_FAILURE; } const char *input_file = argv[1]; fprintf(stdout, "=== Kalign Ensemble Tests ===\n\n"); fprintf(stdout, "Test 1: Ensemble with confidence\n"); if(test_ensemble_confidence(input_file) != 0){ fprintf(stdout, " FAIL\n\n"); ret = EXIT_FAILURE; }else{ fprintf(stdout, " PASS\n\n"); } fprintf(stdout, "Test 2: POAR round-trip\n"); if(test_poar_round_trip(input_file) != 0){ fprintf(stdout, " FAIL\n\n"); ret = EXIT_FAILURE; }else{ fprintf(stdout, " PASS\n\n"); } fprintf(stdout, "Test 3: min_support parameter\n"); if(test_min_support(input_file) != 0){ fprintf(stdout, " FAIL\n\n"); ret = EXIT_FAILURE; }else{ fprintf(stdout, " PASS\n\n"); } if(ret == EXIT_SUCCESS){ fprintf(stdout, "All ensemble tests passed.\n"); }else{ fprintf(stderr, "Some ensemble tests FAILED.\n"); } return ret; } /* Test 1: Run ensemble alignment with n_runs=3 and verify that * col_confidence is populated with values in [0, 1]. */ static int test_ensemble_confidence(const char *input_file) { struct msa *msa = NULL; int rv; rv = kalign_read_input((char *)input_file, &msa, 1); if(rv != 0 || msa == NULL){ fprintf(stderr, " ERROR: failed to read input file: %s\n", input_file); return -1; } /* n_runs=3, default gap penalties, seed=42, min_support=0 (auto), no POAR save */ rv = kalign_ensemble(msa, 1, -1, 3, -1.0f, -1.0f, -1.0f, 42, 0, NULL, 0, 0.0f, -1.0f, 0, 0.0f, 0, 2.0f); if(rv != 0){ fprintf(stderr, " ERROR: kalign_ensemble returned %d\n", rv); kalign_free_msa(msa); return -1; } /* Check that col_confidence was allocated */ if(msa->col_confidence == NULL){ fprintf(stderr, " ERROR: col_confidence is NULL after ensemble\n"); kalign_free_msa(msa); return -1; } /* Verify alignment length is positive */ if(msa->alnlen <= 0){ fprintf(stderr, " ERROR: alnlen is %d (expected > 0)\n", msa->alnlen); kalign_free_msa(msa); return -1; } /* Check that all col_confidence values are in [0, 1] */ for(int i = 0; i < msa->alnlen; i++){ float c = msa->col_confidence[i]; if(c < 0.0f || c > 1.0f){ fprintf(stderr, " ERROR: col_confidence[%d] = %f out of range [0,1]\n", i, c); kalign_free_msa(msa); return -1; } } fprintf(stdout, " col_confidence: %d values, all in [0,1]\n", msa->alnlen); /* Also verify that sequences are aligned (have equal length = alnlen) */ for(int i = 0; i < msa->numseq; i++){ if(msa->sequences[i]->seq == NULL){ fprintf(stderr, " ERROR: sequence %d has NULL seq\n", i); kalign_free_msa(msa); return -1; } int slen = (int)strlen(msa->sequences[i]->seq); if(slen != msa->alnlen){ fprintf(stderr, " ERROR: sequence %d length %d != alnlen %d\n", i, slen, msa->alnlen); kalign_free_msa(msa); return -1; } } fprintf(stdout, " %d sequences aligned to length %d\n", msa->numseq, msa->alnlen); kalign_free_msa(msa); return 0; } /* Test 2: Run ensemble with save_poar, then load POAR with * kalign_consensus_from_poar and verify both produce aligned output. */ static int test_poar_round_trip(const char *input_file) { struct msa *msa1 = NULL; struct msa *msa2 = NULL; int rv; const char *poar_path = "test_ensemble_poar.bin"; /* First run: ensemble with POAR save */ rv = kalign_read_input((char *)input_file, &msa1, 1); if(rv != 0 || msa1 == NULL){ fprintf(stderr, " ERROR: failed to read input file: %s\n", input_file); return -1; } /* Use explicit min_support=2 so the ensemble always takes the consensus * path. kalign_consensus_from_poar() also requires min_support >= 1, * and both must use the same threshold for the output to match. */ rv = kalign_ensemble(msa1, 1, -1, 3, -1.0f, -1.0f, -1.0f, 42, 2, poar_path, 0, 0.0f, -1.0f, 0, 0.0f, 0, 2.0f); if(rv != 0){ fprintf(stderr, " ERROR: kalign_ensemble (save) returned %d\n", rv); kalign_free_msa(msa1); return -1; } /* Verify the POAR file was created */ FILE *fp = fopen(poar_path, "rb"); if(fp == NULL){ fprintf(stderr, " ERROR: POAR file was not created: %s\n", poar_path); kalign_free_msa(msa1); return -1; } fclose(fp); fprintf(stdout, " POAR saved to %s\n", poar_path); /* Second run: load POAR and derive consensus */ rv = kalign_read_input((char *)input_file, &msa2, 1); if(rv != 0 || msa2 == NULL){ fprintf(stderr, " ERROR: failed to read input for POAR load\n"); kalign_free_msa(msa1); return -1; } rv = kalign_consensus_from_poar(msa2, poar_path, 2); if(rv != 0){ fprintf(stderr, " ERROR: kalign_consensus_from_poar returned %d\n", rv); kalign_free_msa(msa1); kalign_free_msa(msa2); return -1; } /* Verify both MSAs have valid aligned sequences */ if(msa1->alnlen <= 0){ fprintf(stderr, " ERROR: msa1 alnlen = %d\n", msa1->alnlen); kalign_free_msa(msa1); kalign_free_msa(msa2); return -1; } if(msa2->alnlen <= 0){ fprintf(stderr, " ERROR: msa2 alnlen = %d\n", msa2->alnlen); kalign_free_msa(msa1); kalign_free_msa(msa2); return -1; } /* Both should have the same number of sequences */ if(msa1->numseq != msa2->numseq){ fprintf(stderr, " ERROR: numseq mismatch: %d vs %d\n", msa1->numseq, msa2->numseq); kalign_free_msa(msa1); kalign_free_msa(msa2); return -1; } /* Both should have the same alignment length (same POAR, same consensus) */ if(msa1->alnlen != msa2->alnlen){ fprintf(stderr, " ERROR: alnlen mismatch: %d vs %d\n", msa1->alnlen, msa2->alnlen); kalign_free_msa(msa1); kalign_free_msa(msa2); return -1; } /* Verify aligned sequences match between direct ensemble and POAR-loaded consensus */ for(int i = 0; i < msa1->numseq; i++){ if(msa1->sequences[i]->seq == NULL || msa2->sequences[i]->seq == NULL){ fprintf(stderr, " ERROR: NULL seq at index %d\n", i); kalign_free_msa(msa1); kalign_free_msa(msa2); return -1; } if(strcmp(msa1->sequences[i]->seq, msa2->sequences[i]->seq) != 0){ fprintf(stderr, " ERROR: sequence %d mismatch between ensemble and POAR load\n", i); fprintf(stderr, " direct: %.60s...\n", msa1->sequences[i]->seq); fprintf(stderr, " loaded: %.60s...\n", msa2->sequences[i]->seq); kalign_free_msa(msa1); kalign_free_msa(msa2); return -1; } } fprintf(stdout, " Round-trip: %d sequences, alnlen=%d, consensus matches\n", msa1->numseq, msa1->alnlen); kalign_free_msa(msa1); kalign_free_msa(msa2); /* Clean up temp file */ remove(poar_path); return 0; } /* Test 3: Run ensemble with explicit min_support=2 and verify it completes. */ static int test_min_support(const char *input_file) { struct msa *msa = NULL; int rv; rv = kalign_read_input((char *)input_file, &msa, 1); if(rv != 0 || msa == NULL){ fprintf(stderr, " ERROR: failed to read input file: %s\n", input_file); return -1; } /* min_support=2 (explicit), n_runs=3 */ rv = kalign_ensemble(msa, 1, -1, 3, -1.0f, -1.0f, -1.0f, 42, 2, NULL, 0, 0.0f, -1.0f, 0, 0.0f, 0, 2.0f); if(rv != 0){ fprintf(stderr, " ERROR: kalign_ensemble with min_support=2 returned %d\n", rv); kalign_free_msa(msa); return -1; } /* Verify alignment was produced */ if(msa->alnlen <= 0){ fprintf(stderr, " ERROR: alnlen is %d (expected > 0)\n", msa->alnlen); kalign_free_msa(msa); return -1; } /* Verify sequences are aligned */ for(int i = 0; i < msa->numseq; i++){ if(msa->sequences[i]->seq == NULL){ fprintf(stderr, " ERROR: sequence %d has NULL seq\n", i); kalign_free_msa(msa); return -1; } int slen = (int)strlen(msa->sequences[i]->seq); if(slen != msa->alnlen){ fprintf(stderr, " ERROR: sequence %d length %d != alnlen %d\n", i, slen, msa->alnlen); kalign_free_msa(msa); return -1; } } /* Verify col_confidence is populated */ if(msa->col_confidence == NULL){ fprintf(stderr, " ERROR: col_confidence is NULL with min_support=2\n"); kalign_free_msa(msa); return -1; } fprintf(stdout, " min_support=2: %d sequences aligned to length %d\n", msa->numseq, msa->alnlen); kalign_free_msa(msa); return 0; } kalign-3.5.1/tests/kalign_io_test.c000066400000000000000000000007361515023132300172670ustar00rootroot00000000000000#include "stdio.h" #include "kalign/kalign.h" int main(int argc, char *argv[]) { struct msa* msa = NULL; fprintf(stdout,"inputs: %d\n", argc); for(int i = 1; i < argc;i++){ fprintf(stdout,"reading from %s\n", argv[i]); kalign_read_input(argv[i], &msa,1); } kalign_write_msa(msa, "test.clu", "clu"); kalign_write_msa(msa, "test.fa", "fasta"); kalign_free_msa(msa); return 0; } kalign-3.5.1/tests/kalign_lib_test.c000066400000000000000000000044651515023132300174310ustar00rootroot00000000000000#include #include #include "kalign/kalign.h" int test_2(void); int main(int argc, char *argv[]) { struct msa* msa = NULL; if(argc <= 1){ fprintf(stdout,"no inputs\n"); return EXIT_SUCCESS; } for(int i = 1; i < argc;i++){ fprintf(stdout,"reading from %s\n", argv[i]); kalign_read_input(argv[i], &msa,1); } /* Align seqences */ kalign_run(msa,1 , -1, -1, -1 , -1, 0, 0); /* write alignment in clustal format */ kalign_write_msa(msa, "test.clu", "clu"); /* write alignment in aligned fasta format */ kalign_write_msa(msa, "test.fa", "fasta"); /* cleaning up */ kalign_free_msa(msa); test_2(); return EXIT_SUCCESS; } int test_2(void){ // Initialize array char* inseq[] = { "ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTTGCATGCATGCATGCATGCATGCATGCA", "ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTTGCATGCATGCATGCATGCATGCATGCA", "ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTTGCATGCATGCATGCATGCATGCATGCA", "ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT" }; int numseq = 4; int L[] = {76, 76, 76, 48}; char** aln = NULL; int aln_len = 0; kalign(inseq, L, numseq, 4 , KALIGN_TYPE_DNA_INTERNAL, -1, -1 , -1, &aln, &aln_len); printf("Aligned:\n"); for(int i = 0; i < numseq; i++){ printf("%s\n", aln[i]); /* printf("%s\n", inseq[i]); */ } for (int i = 0; i < numseq; ++i) { int num_aligned = 0; for (int j = 0; j < aln_len; ++j) { if (aln[i][j] != '-' && aln[i][j] != '\0') { num_aligned++; } } if (num_aligned != L[i]) { fprintf(stderr, "error: sequence %d is not fully aligned\n", i); fprintf(stderr, "%s\n", inseq[i]); fprintf(stderr, "%s\n", aln[i]); } } /* Free alignment */ for(int i = 0; i < numseq;i++){ free(aln[i]); } free(aln); return 0; } kalign-3.5.1/tests/kalign_lib_testCXX.cpp000066400000000000000000000023301515023132300203410ustar00rootroot00000000000000 #include #include #include #include "kalign/kalign.h" int main() { // Initialize array char * inseq[95] = { "GKGDPKKPRGKMSSYAFFVQTSREEHKKKHPDASVNFSEFSKKCSERWKTMSAKEKGKFEDMAKADKARYEREMKTYIPPKGE", "MQDRVKRPMNAFIVWSRDQRRKMALENPRMRNSEISKQLGYQWKMLTEAEKWPFFQEAQKLQAMHREKYPNYKYRPRRKAKMLPK", "MKKLKKHPDFPKKPLTPYFRFFMEKRAKYAKLHPEMSNLDLTKILSKKYKELPEKKKMKYIQDFQREKQEFERNLARFREDHPDLIQNAKK", "MHIKKPLNAFMLYMKEMRANVVAESTLKESAAINQILGRRWHALSREEQAKYYELARKERQLHMQLYPGWSARDNYGKKKKRKREK", }; int numseq = 4; int* L = new int[numseq]; L[0] = 83; L[1] = 85; L[2] = 91; L[3] = 86; char** aln = NULL; int aln_len = 0; kalign(inseq,L, numseq,4 , KALIGN_TYPE_PROTEIN, -1, -1 , -1, &aln, &aln_len); std::cout << "Aligned:\n"; for(int i = 0; i < numseq;i++){ std::cout << aln[i] << "\n"; } /* Free alignment */ for(int i = 0; i < numseq;i++){ // delete[] aln[i]; free(aln[i]); } free(aln); delete[] L; } kalign-3.5.1/tests/large_benchmark.c000066400000000000000000000311541515023132300173760ustar00rootroot00000000000000#include "tldevel.h" #include "tlmisc.h" #include #include #include #include #include #include #include #include #include "kalign/kalign.h" #define MAX_PATH_LEN 4096 struct parameters { char* target_dir; int verbose; int dryrun; int help_flag; }; struct aln_case { char* dir; char* name; float score; int alloc_len; int valid; }; struct bench_collection { struct aln_case** l; int n; int n_alloc; }; static int run_test_aln(struct aln_case *tcase); static int bench_collection_add_case(struct bench_collection* b, char* dir, char* name); static int bench_collection_alloc(struct bench_collection **bench_collection, int n); static int bench_collection_resize(struct bench_collection *b); static void bench_collection_free(struct bench_collection *b); static int aln_case_alloc(struct aln_case **aln_case); static void aln_case_free(struct aln_case *a); static int run_bench(struct parameters *p); static int process_dir(struct parameters *p,char* dir,struct bench_collection* b); static int detect_likely_alignment(char *name, int *is_aln); static int param_sanity_check(struct parameters *p); static int print_help(char * argv[]); static int param_print(struct parameters *p); static int param_init(struct parameters **param); static void param_free(struct parameters *p); static int local_dir_exists(const char* name); #define OPT_VERBOSE 1 #define OPT_DRY 2 int main(int argc, char *argv[]) { struct parameters* param = NULL; int c; RUN(param_init(¶m)); while (1){ static struct option long_options[] ={ {"dir", required_argument, 0, 'd'}, {"verbose", no_argument,0, OPT_VERBOSE}, {"dry-run", no_argument,0,OPT_DRY}, {"help", no_argument,0,'h'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long_only (argc, argv,"d:h",long_options, &option_index); /* Detect the end of the options. */ if (c == -1){ break; } switch(c) { case OPT_DRY: param->dryrun = 1; break; case OPT_VERBOSE: param->verbose = 1; break; case 'd': param->target_dir = optarg; break; case 'h': param->help_flag = 1; break; default: abort (); } } if(param->help_flag || argc < 2){ RUN(print_help(argv)); param_free(param); return EXIT_SUCCESS; } RUN(param_sanity_check(param)); RUN(param_print(param)); RUN(run_bench(param)); param_free(param); return EXIT_SUCCESS; ERROR: param_free(param); return EXIT_FAILURE; } int run_bench(struct parameters *p) { struct bench_collection* b = NULL; ASSERT(p != NULL,"No parameters"); RUN(bench_collection_alloc(&b, 1024)); RUN(process_dir(p, p->target_dir,b)); for(int i = 0; i < b->n;i++){ struct aln_case *c = NULL; c = b->l[i]; if(p->dryrun){ LOG_MSG("DryRun: would run kalign on: %s",c->name ); }else{ RUN(run_test_aln(c)); if(p->verbose){ LOG_MSG("Case %d:\t%-*s\t%d\t%f ",i, 20,c->name,c->valid, c->score); } } } fprintf(stdout,"Alignment,Score\n"); for(int i = 0; i < b->n;i++){ struct aln_case *c = NULL; c = b->l[i]; if(c->valid){ fprintf(stdout,"%s,%f\n",c->name,c->score); } } bench_collection_free(b); return OK; ERROR: bench_collection_free(b); return FAIL; } int run_test_aln(struct aln_case *tcase) { char path[MAX_PATH_LEN]; struct msa* r = NULL; struct msa* t = NULL; snprintf(path, MAX_PATH_LEN, "%s/%s",tcase->dir,tcase->name); RUN(kalign_read_input(path, &t,1)); if(!t){ kalign_free_msa(t); tcase->valid = 0; return OK; } /* reference */ RUN(kalign_read_input(path, &r,1)); kalign_run(t,16 , -1, -1, -1 , -1, 0, 0); kalign_msa_compare(r, t, &tcase->score); /* if(tcase->score >= 0.5){ */ /* LOG_MSG("Ref:"); */ /* kalign_write_msa(r, NULL , "clu"); */ /* LOG_MSG("test:"); */ /* kalign_write_msa(t, NULL , "clu"); */ /* } */ kalign_free_msa(r); kalign_free_msa(t); return OK; ERROR: kalign_free_msa(r); kalign_free_msa(t); return FAIL; } int process_dir(struct parameters *p,char* dir,struct bench_collection* b) { struct dirent *dp; DIR *d_ptr; if ((d_ptr = opendir(dir)) == NULL){ ERROR_MSG("Can't open %s", dir); } while ((dp = readdir(d_ptr)) != NULL){ /* struct stat stbuf ; */ int is_aln = 0; if(dp->d_type == DT_DIR){ if(dp->d_name[0] != '.'){ char* tmp = NULL; MMALLOC(tmp, sizeof(char) * MAX_PATH_LEN); snprintf(tmp,MAX_PATH_LEN,"%s/%s", dir, dp->d_name); RUN(process_dir(p, tmp,b)); MFREE(tmp); } }else if(dp->d_type == DT_REG){ /* LOG_MSG("File: %s %s",dir, dp->d_name); */ char* tmp = NULL; MMALLOC(tmp, sizeof(char) * MAX_PATH_LEN); snprintf(tmp,MAX_PATH_LEN,"%s/%s", dir, dp->d_name); detect_likely_alignment(tmp, &is_aln); if(is_aln){ RUN(bench_collection_add_case(b, dir, dp->d_name)); } MFREE(tmp); }else if(dp->d_type == DT_LNK){ /* LOG_MSG("LINK: %s %s",dir, dp->d_name); */ char* tmp = NULL; char* rp = NULL; MMALLOC(tmp, sizeof(char) * MAX_PATH_LEN); snprintf(tmp,MAX_PATH_LEN,"%s/%s", dir, dp->d_name); rp = realpath(tmp, NULL); if(rp!= NULL){ /* LOG_MSG("resolved: %s", rp); */ detect_likely_alignment(rp, &is_aln); if(is_aln){ RUN(bench_collection_add_case(b, dir, dp->d_name)); } free(rp); } MFREE(tmp); } } closedir(d_ptr); return OK; ERROR: if(d_ptr){ closedir(d_ptr); } return FAIL; } int detect_likely_alignment(char *name, int *is_aln) { int len = strnlen(name,MAX_PATH_LEN); int ret = 0; if(strncmp(name + len - 4, ".msf", 4) == 0){ /* LOG_MSG("%s is aln", name); */ ret = 1; }else if(strncmp(name + len - 4, ".vie", 4) == 0){ /* LOG_MSG("%s is aln", name); */ ret = 1; } *is_aln = ret; return OK; } int print_help(char * argv[]) { const char usage[] = " -d "; char* basename = NULL; RUN(tlfilename(argv[0], &basename)); fprintf(stdout,"\nUsage: %s %s\n\n",basename ,usage); fprintf(stdout,"Options:\n\n"); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"-d","Target directory" ,"[]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"-verbose","Target directory" ,"[off]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"-dry-run","Target directory" ,"[off]" ); fprintf(stdout,"%*s%-*s: %s %s\n",3,"",MESSAGE_MARGIN-3,"-h/--help","Print help." ,"[off]" ); fprintf(stdout,"\n\n"); if(basename){ MFREE(basename); } return OK; ERROR: if(basename){ MFREE(basename); } return FAIL; } int param_print(struct parameters *p) { fprintf(stderr,"%*s%-*s: %s\n",3,"",MESSAGE_MARGIN-3,"-d", p->target_dir); fprintf(stderr,"%*s%-*s: %d\n",3,"",MESSAGE_MARGIN-3,"-verbose", p->verbose); fprintf(stderr,"%*s%-*s: %d\n",3,"",MESSAGE_MARGIN-3,"-dry-run", p->dryrun); return OK; } int param_sanity_check(struct parameters *p) { ASSERT(p->target_dir != NULL, " No target dir use -d .... "); RUN(local_dir_exists(p->target_dir)); return OK; ERROR: return FAIL; } int local_dir_exists(const char* name) { ASSERT(name != NULL," No directory name!"); DIR* dir = opendir(name); if (dir) { /* Directory exists. */ closedir(dir); } else if (ENOENT == errno) { ERROR_MSG("Directory %s does not exist!", name); /* Directory does not exist. */ } else { ERROR_MSG("Opening directory %s failed!", name); /* opendir() failed for some other reason. */ } return OK; ERROR: return FAIL; } int param_init(struct parameters **param) { struct parameters* p = NULL; MMALLOC(p, sizeof(struct parameters)); p->target_dir = NULL; p->verbose = 0; p->dryrun = 0; p->help_flag = 0; *param = p; return OK; ERROR: param_free(p); return FAIL; } void param_free(struct parameters *p) { if(p){ MFREE(p); } } int bench_collection_add_case(struct bench_collection* b, char* dir, char* name) { struct aln_case* a = NULL; int idx = 0; idx = b->n; a = b->l[idx]; strncpy(a->name, name, a->alloc_len); strncpy(a->dir, dir, a->alloc_len); b->n++; if(b->n == b->n_alloc){ RUN(bench_collection_resize(b)); } return OK; ERROR: return FAIL; } int bench_collection_alloc(struct bench_collection **bench_collection, int n) { struct bench_collection* b = NULL; MMALLOC(b, sizeof(struct bench_collection)); b->n = 0; b->n_alloc = n; b->l = NULL; MMALLOC(b->l, sizeof(struct aln_cases*) * b->n_alloc); for(int i = 0; i < b->n_alloc;i++){ b->l[i] = NULL; RUN(aln_case_alloc(&b->l[i])); } *bench_collection = b; return OK; ERROR: return FAIL; } int bench_collection_resize(struct bench_collection *b) { int old_size = b->n_alloc; int new_size = b->n_alloc + b->n_alloc / 2; MREALLOC(b->l, sizeof(struct aln_cases*) * new_size); for(int i = old_size; i < new_size;i++){ b->l[i] = NULL; RUN(aln_case_alloc(&b->l[i])); } b->n_alloc = new_size; return OK; ERROR: return FAIL; } void bench_collection_free(struct bench_collection *b) { if(b){ for(int i = 0; i < b->n_alloc;i++){ aln_case_free(b->l[i]); } MFREE(b->l); MFREE(b); } } int aln_case_alloc(struct aln_case **aln_case) { struct aln_case* a = NULL; MMALLOC(a, sizeof(struct aln_case)); a->name = NULL; a->dir = NULL; a->alloc_len = MAX_PATH_LEN; a->valid = 1; MMALLOC(a->dir, sizeof(char) * a->alloc_len); MMALLOC(a->name, sizeof(char) * a->alloc_len); a->score = -1.0; *aln_case = a; return OK; ERROR: aln_case_free(a); return FAIL; } void aln_case_free(struct aln_case *a) { if(a){ if(a->dir){ MFREE(a->dir); } if(a->name){ MFREE(a->name); } MFREE(a); } } kalign-3.5.1/tests/python/000077500000000000000000000000001515023132300154435ustar00rootroot00000000000000kalign-3.5.1/tests/python/conftest.py000066400000000000000000000211461515023132300176460ustar00rootroot00000000000000""" Shared pytest configuration and fixtures for Kalign Python tests. """ import pytest import tempfile import os from pathlib import Path from typing import List, Dict, Any # Rich table support for benchmarks try: from rich.console import Console from rich.table import Table from rich.text import Text RICH_AVAILABLE = True except ImportError: RICH_AVAILABLE = False # Test data constants DNA_SEQUENCES_SIMPLE = ["ATCGATCG", "ATCGTCG", "ATCGATCG"] DNA_SEQUENCES_WITH_GAPS = [ "ATCGATCGATCG", "ATCGTCGATCG", "ATCGATCATCG", "ATCGATCGAGATCG", ] RNA_SEQUENCES_SIMPLE = ["AUCGAUCG", "AUCGUCG", "AUCGAUCG"] PROTEIN_SEQUENCES_SIMPLE = ["MKTAYIAK", "MKTAYK", "MKTAYIAK"] PROTEIN_SEQUENCES_COMPLEX = [ "MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQAPILSRVGDGTQDNLSGAEKAVQVKVKALPDAQFEVVHSLAKWKRQTLGQHDFSAGEGLYTHMKALRPDEDRLSPLHSVYVDQWDWERVMGDGERQFSTLKSTVEAIWAGIKATEAAVSEEFGLAPFLPDQIHFVHSQELLSRYPDLDAKGRERAIAKDLGAVFLVGIGGKLSDGHRHDVRAPDYDDWUAIFRRVVSAEFQRQPVHQSYLNTVLGSQGKL", "MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQAPILSRVGDGTQDNLSGAEKAVQVKVKALPDAQFEVVHSLAKWKRQTLGQHDFSAGEGLYTHMKALRPDEDRLSPLHSVYVDQWDWERVMGDGERQFSTLKSTVEAIWAGIKATEAAVSEEFGLAPFLPDQIHFVHSQELLSRYPDLDAKGRERAIAKDLGAVFLVGIGGKLSDGHRHDVRAPDYDDWUAIFRRVVSAEFQRQPVHQSYLNTVLGSQGKL", "MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQAPILSRVGDGTQDNLSGAEKAVQVKVKALPDAQFEVVHSLAKWKRQTLGQHDFSAGEGLYTHMKALRPDEDRLSPLHSVYVDQWDWERVMGDGERQFSTLKSTVEAIWAGIKATEAAVSEEFGLAPFLPDQIHFVHSQELLSRYPDLDAKGRERAIAKDLGAVFLVGIGGKLSDGHRHDVRAPDYDDWUAIFRRVVSAEFQRQPVHQSYLNTVLGSQGKL", ] INVALID_DNA_SEQUENCES = [ "ATCG123", # Contains numbers "ATCGXYZ", # Invalid characters "ATCG@#$", # Special characters ] MIXED_CASE_SEQUENCES = ["AtCgAtCg", "atcgatcg", "ATCGATCG"] @pytest.fixture def dna_simple(): """Simple DNA sequences for basic testing.""" return DNA_SEQUENCES_SIMPLE.copy() @pytest.fixture def dna_with_gaps(): """DNA sequences that will likely produce gaps.""" return DNA_SEQUENCES_WITH_GAPS.copy() @pytest.fixture def rna_simple(): """Simple RNA sequences for basic testing.""" return RNA_SEQUENCES_SIMPLE.copy() @pytest.fixture def protein_simple(): """Simple protein sequences for basic testing.""" return PROTEIN_SEQUENCES_SIMPLE.copy() @pytest.fixture def protein_complex(): """Complex protein sequences for advanced testing.""" return PROTEIN_SEQUENCES_COMPLEX.copy() @pytest.fixture def invalid_dna(): """Invalid DNA sequences for error testing.""" return INVALID_DNA_SEQUENCES.copy() @pytest.fixture def mixed_case(): """Mixed case sequences for case handling testing.""" return MIXED_CASE_SEQUENCES.copy() @pytest.fixture def temp_dir(): """Create a temporary directory for file operations.""" with tempfile.TemporaryDirectory() as tmpdir: yield Path(tmpdir) @pytest.fixture def sample_fasta_file(temp_dir): """Create a sample FASTA file for testing.""" fasta_content = """>seq1 ATCGATCGATCG >seq2 ATCGTCGATCG >seq3 ATCGATCATCG """ fasta_file = temp_dir / "sample.fasta" fasta_file.write_text(fasta_content) return str(fasta_file) @pytest.fixture def sample_protein_fasta_file(temp_dir): """Create a sample protein FASTA file for testing.""" fasta_content = """>protein1 MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQAPILSRVGDGTQDNLSGAEKAVQVKVKALPDAQFEVVHSLAKWKRQTLGQHDFSAGEGLYTHMKALRPDEDRLSPLHSVY >protein2 MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQAPILSRVGDGTQDNLSGAEKAVQVKVKALPDAQFEVVHSLAKWKRQTLGQHDFSAGEGLYTHMKALRPDEDRLSPLH >protein3 MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQAPILSRVGDGTQDNLSGAEKAVQVKVKALPDAQFEVVHSLAKWKRQTLGQHDFSAGEGLYTHMKALRPDEDRL """ fasta_file = temp_dir / "proteins.fasta" fasta_file.write_text(fasta_content) return str(fasta_file) @pytest.fixture def invalid_fasta_file(temp_dir): """Create an invalid FASTA file for error testing.""" invalid_content = """This is not a valid FASTA file It has no proper headers And random content """ invalid_file = temp_dir / "invalid.fasta" invalid_file.write_text(invalid_content) return str(invalid_file) @pytest.fixture def nonexistent_file(): """Return path to a file that doesn't exist.""" return "/path/that/does/not/exist.fasta" @pytest.fixture def test_data_dir(): """Get the test data directory path.""" return Path(__file__).parent / "test_data" # Parametrize fixtures for common test scenarios @pytest.fixture( params=[ ("dna", DNA_SEQUENCES_SIMPLE), ("rna", RNA_SEQUENCES_SIMPLE), ("protein", PROTEIN_SEQUENCES_SIMPLE), ] ) def sequence_type_data(request): """Parametrized fixture providing different sequence types.""" seq_type, sequences = request.param return seq_type, sequences.copy() @pytest.fixture(params=[1, 2, 4]) def thread_count(request): """Parametrized fixture for testing different thread counts.""" return request.param @pytest.fixture( params=[ ("auto", None), ("dna", "dna"), ("rna", "rna"), ("protein", "protein"), ("divergent", "divergent"), ("internal", "internal"), ] ) def sequence_type_spec(request): """Parametrized fixture for testing sequence type specifications.""" return request.param # Pytest configuration def pytest_configure(config): """Configure pytest with custom markers.""" config.addinivalue_line("markers", "slow: mark test as slow running") config.addinivalue_line("markers", "integration: mark test as integration test") config.addinivalue_line("markers", "performance: mark test as performance test") config.addinivalue_line("markers", "file_io: mark test as requiring file I/O") def pytest_collection_modifyitems(config, items): """Add markers to tests based on their names.""" for item in items: # Mark slow tests if "slow" in item.nodeid or "large" in item.nodeid: item.add_marker(pytest.mark.slow) # Mark integration tests if "integration" in item.nodeid: item.add_marker(pytest.mark.integration) # Mark performance tests if "performance" in item.nodeid or "benchmark" in item.nodeid: item.add_marker(pytest.mark.performance) # Mark file I/O tests if "file" in item.nodeid: item.add_marker(pytest.mark.file_io) # Helper functions for tests def assert_valid_alignment(sequences: List[str], aligned: List[str]) -> None: """Assert that an alignment result is valid.""" # Same number of sequences assert len(aligned) == len(sequences), "Number of sequences changed" # All aligned sequences have same length if aligned: expected_length = len(aligned[0]) for i, seq in enumerate(aligned): assert len(seq) == expected_length, f"Sequence {i} has different length" # No empty sequences (unless input was empty) for seq in aligned: if any( original for original in sequences if original ): # If any input was non-empty assert seq, "Aligned sequence is empty" def assert_alignment_preserves_characters( original: List[str], aligned: List[str] ) -> None: """Assert that alignment preserves the original characters (just adds gaps).""" for orig, align in zip(original, aligned): # Remove gaps from aligned sequence degapped = align.replace("-", "") assert degapped == orig, f"Original sequence {orig} not preserved in {align}" def calculate_identity(seq1: str, seq2: str) -> float: """Calculate sequence identity percentage between two sequences.""" if len(seq1) != len(seq2): raise ValueError("Sequences must have same length") matches = sum(1 for a, b in zip(seq1, seq2) if a == b and a != "-" and b != "-") valid_positions = sum(1 for a, b in zip(seq1, seq2) if a != "-" and b != "-") return (matches / valid_positions * 100) if valid_positions > 0 else 0.0 # Expected results for regression testing EXPECTED_ALIGNMENTS = { "dna_simple": { "sequences": DNA_SEQUENCES_SIMPLE, "expected_length": 8, # This might need adjustment after testing "min_identity": 75.0, # Minimum expected identity percentage }, "protein_simple": { "sequences": PROTEIN_SEQUENCES_SIMPLE, "expected_length": 8, # This might need adjustment after testing "min_identity": 85.0, # Minimum expected identity percentage }, } @pytest.fixture def expected_results(): """Expected alignment results for regression testing.""" return EXPECTED_ALIGNMENTS.copy() # Note: pytest_benchmark_update_json hook removed to avoid plugin validation errors # when pytest-benchmark is not installed. If you need benchmark display functionality, # install pytest-benchmark: pip install pytest-benchmark kalign-3.5.1/tests/python/pytest.ini000066400000000000000000000010561515023132300174760ustar00rootroot00000000000000[tool:pytest] testpaths = tests python_files = test_*.py python_functions = test_* addopts = --strict-markers --strict-config -v --benchmark-columns=min,max,mean,median,ops,rounds --benchmark-sort=name --benchmark-max-time=2.0 markers = slow: marks tests as slow (deselect with '-m "not slow"') integration: marks tests as integration tests performance: marks tests as performance tests file_io: marks tests as requiring file I/O filterwarnings = ignore::DeprecationWarning ignore::PendingDeprecationWarningkalign-3.5.1/tests/python/test_basic_alignment.py000066400000000000000000000050101515023132300221670ustar00rootroot00000000000000""" Basic alignment functionality tests for Kalign Python package. """ import pytest import sys import kalign from conftest import assert_valid_alignment, assert_alignment_preserves_characters class TestBasicAlignment: """Test core alignment functionality.""" def test_simple_dna_alignment(self, dna_simple): """Test basic DNA sequence alignment.""" aligned = kalign.align(dna_simple, seq_type="dna") assert_valid_alignment(dna_simple, aligned) assert_alignment_preserves_characters(dna_simple, aligned) # Check that alignment adds gaps where needed assert len(aligned[0]) >= max(len(seq) for seq in dna_simple) def test_simple_protein_alignment(self, protein_simple): """Test basic protein sequence alignment.""" aligned = kalign.align(protein_simple, seq_type="protein") assert_valid_alignment(protein_simple, aligned) assert_alignment_preserves_characters(protein_simple, aligned) def test_simple_rna_alignment(self, rna_simple): """Test basic RNA sequence alignment.""" aligned = kalign.align(rna_simple, seq_type="rna") assert_valid_alignment(rna_simple, aligned) assert_alignment_preserves_characters(rna_simple, aligned) def test_auto_detection(self, dna_simple): """Test automatic sequence type detection.""" aligned = kalign.align(dna_simple) # No seq_type specified assert_valid_alignment(dna_simple, aligned) assert len(aligned) == len(dna_simple) def test_alignment_length_consistency(self, sequence_type_data): """Test that all aligned sequences have same length.""" seq_type, sequences = sequence_type_data aligned = kalign.align(sequences, seq_type=seq_type) if aligned: expected_length = len(aligned[0]) for seq in aligned: assert len(seq) == expected_length def test_empty_sequence_list(self): """Test behavior with empty sequence list.""" with pytest.raises(ValueError, match="No sequences were found in the input"): kalign.align([]) def test_single_sequence(self): """Test alignment with single sequence should raise error.""" single_seq = ["ATCGATCG"] # Kalign requires at least 2 sequences for alignment with pytest.raises( ValueError, match="Only 1 sequence was found in the input - at least 2 sequences are required for alignment", ): kalign.align(single_seq, seq_type="dna") kalign-3.5.1/tests/python/test_cli.py000066400000000000000000000024071515023132300176260ustar00rootroot00000000000000import subprocess import sys from pathlib import Path def test_cli_version() -> None: result = subprocess.run( [sys.executable, "-m", "kalign.cli", "--version"], check=True, capture_output=True, text=True, ) assert result.stdout.strip() def test_cli_align_fasta_to_stdout() -> None: repo_root = Path(__file__).resolve().parents[2] input_fasta = repo_root / "tests" / "data" / "tiny.fa" result = subprocess.run( [ sys.executable, "-m", "kalign.cli", "-i", str(input_fasta), "-o", "-", "--format", "fasta", "--type", "dna", "-n", "1", ], check=True, capture_output=True, text=True, ) # FASTA output should start with a header line. assert result.stdout.lstrip().startswith(">") def test_cli_entry_point() -> None: """Verify kalign-py entry point is installed and runs.""" result = subprocess.run( ["kalign-py", "--version"], capture_output=True, text=True, ) # Entry point should exist and return version info assert result.returncode == 0 assert result.stdout.strip() kalign-3.5.1/tests/python/test_compare.py000066400000000000000000000060751515023132300205120ustar00rootroot00000000000000"""Tests for kalign.compare() and kalign.align_file_to_file().""" import os import tempfile import pytest import kalign DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data") def _data(name): return os.path.join(DATA_DIR, name) class TestCompare: def test_identical_alignment_scores_100(self): ref = _data("BB11001.msf") score = kalign.compare(ref, ref) assert score == pytest.approx(100.0) def test_compare_different_alignments(self): ref = _data("BB11001.msf") with tempfile.TemporaryDirectory() as tmpdir: out = os.path.join(tmpdir, "test_aln.fasta") kalign.align_file_to_file(_data("BB11001.tfa"), out) score = kalign.compare(ref, out) assert 0.0 <= score <= 100.0 def test_compare_file_not_found(self): with pytest.raises(FileNotFoundError): kalign.compare("/nonexistent/ref.msf", "/nonexistent/test.msf") def test_compare_ref_not_found(self): ref = _data("BB11001.msf") with pytest.raises(FileNotFoundError): kalign.compare("/nonexistent/ref.msf", ref) def test_compare_test_not_found(self): ref = _data("BB11001.msf") with pytest.raises(FileNotFoundError): kalign.compare(ref, "/nonexistent/test.msf") class TestAlignFileToFile: def test_basic_align_fasta(self): with tempfile.TemporaryDirectory() as tmpdir: out = os.path.join(tmpdir, "out.fasta") kalign.align_file_to_file(_data("BB11001.tfa"), out) assert os.path.exists(out) assert os.path.getsize(out) > 0 def test_align_msf_format(self): with tempfile.TemporaryDirectory() as tmpdir: out = os.path.join(tmpdir, "out.msf") kalign.align_file_to_file(_data("BB11001.tfa"), out, format="msf") assert os.path.exists(out) assert os.path.getsize(out) > 0 def test_align_and_compare(self): """Align BB11001 and compare to reference - SP score should be reasonable.""" ref = _data("BB11001.msf") with tempfile.TemporaryDirectory() as tmpdir: out = os.path.join(tmpdir, "aln.msf") kalign.align_file_to_file(_data("BB11001.tfa"), out, format="msf") score = kalign.compare(ref, out) assert score > 0.0, "SP score should be positive" def test_input_not_found(self): with pytest.raises(FileNotFoundError): kalign.align_file_to_file("/nonexistent/input.fa", "/tmp/out.fa") def test_align_preserves_sequence_names(self): """Output should contain FASTA headers from input.""" with tempfile.TemporaryDirectory() as tmpdir: out = os.path.join(tmpdir, "out.fasta") kalign.align_file_to_file(_data("BB11001.tfa"), out) with open(out) as f: content = f.read() assert content.startswith(">"), "Output should be FASTA format" headers = [l for l in content.splitlines() if l.startswith(">")] assert len(headers) >= 2, "Should have multiple sequences" kalign-3.5.1/tests/python/test_data/000077500000000000000000000000001515023132300174135ustar00rootroot00000000000000kalign-3.5.1/tests/python/test_data/dna_sequences.fasta000066400000000000000000000000531515023132300232460ustar00rootroot00000000000000>seq1 ATCGATCG >seq2 ATCGTCG >seq3 ATCGATCGkalign-3.5.1/tests/python/test_data/invalid_sequences.fasta000066400000000000000000000000431515023132300241310ustar00rootroot00000000000000>invalid1 ATCG123 >invalid2 ATCGXYZkalign-3.5.1/tests/python/test_data/protein_sequences.fasta000066400000000000000000000000551515023132300241660ustar00rootroot00000000000000>prot1 MKTAYIAK >prot2 MKTAYK >prot3 MKTAYIAKkalign-3.5.1/tests/python/test_data/rna_sequences.fasta000066400000000000000000000000531515023132300232640ustar00rootroot00000000000000>rna1 AUCGAUCG >rna2 AUCGUCG >rna3 AUCGAUCGkalign-3.5.1/tests/python/test_downstream_foundation.py000066400000000000000000000446561515023132300235040ustar00rootroot00000000000000"""Tests for downstream benchmark foundation modules. Verifies provenance, utils, and simulation modules can be imported and their core functions work correctly without external tools. """ import json import os import tempfile from pathlib import Path import pytest pytest.importorskip("benchmarks", reason="benchmarks package not on sys.path (run from repo root)") # ====================================================================== # provenance.py # ====================================================================== class TestProvenance: """Tests for benchmarks.downstream.provenance.""" def test_import(self): from benchmarks.downstream import provenance assert hasattr(provenance, "Provenance") assert hasattr(provenance, "collect_provenance") assert hasattr(provenance, "collect_tool_versions") assert hasattr(provenance, "result_path") assert hasattr(provenance, "update_latest_symlink") assert hasattr(provenance, "load_latest_results") def test_provenance_dataclass_fields(self): from benchmarks.downstream.provenance import Provenance import dataclasses fields = {f.name for f in dataclasses.fields(Provenance)} expected = { "timestamp", "kalign_version", "kalign_commit", "container_image", "hostname", "cpu_model", "cpu_cores", "ram_gb", "os_version", "python_version", "tool_versions", "parameters", } assert expected == fields def test_collect_tool_versions_returns_dict(self): from benchmarks.downstream.provenance import collect_tool_versions versions = collect_tool_versions() assert isinstance(versions, dict) # Should have entries for all known tools for tool in ["kalign", "mafft", "muscle", "clustalo", "hmmer", "iqtree"]: assert tool in versions assert isinstance(versions[tool], str) def test_collect_provenance_structure(self): from benchmarks.downstream.provenance import Provenance, collect_provenance prov = collect_provenance({"test_param": "value"}) assert isinstance(prov, Provenance) assert prov.cpu_cores > 0 assert prov.ram_gb > 0 assert prov.python_version # non-empty assert prov.hostname # non-empty assert prov.parameters == {"test_param": "value"} def test_provenance_json_roundtrip(self): from dataclasses import asdict from benchmarks.downstream.provenance import collect_provenance prov = collect_provenance({"key": 42}) data = asdict(prov) # Must be JSON-serialisable text = json.dumps(data) loaded = json.loads(text) assert loaded["parameters"] == {"key": 42} assert loaded["cpu_cores"] > 0 def test_result_path_generation(self): from benchmarks.downstream.provenance import result_path with tempfile.TemporaryDirectory() as tmpdir: path = result_path(Path(tmpdir), "calibration") assert path.parent.name == "calibration" assert path.name.startswith("run_") assert path.name.endswith(".json") assert path.parent.exists() def test_symlink_management(self): from benchmarks.downstream.provenance import ( load_latest_results, update_latest_symlink, ) with tempfile.TemporaryDirectory() as tmpdir: # Create a fake result file result_file = Path(tmpdir) / "run_test.json" result_file.write_text(json.dumps({"score": 42})) # Create symlink update_latest_symlink(result_file) link = Path(tmpdir) / "latest.json" assert link.is_symlink() # Load through symlink data = load_latest_results(Path(tmpdir)) assert data == {"score": 42} def test_symlink_update_replaces(self): from benchmarks.downstream.provenance import update_latest_symlink with tempfile.TemporaryDirectory() as tmpdir: # First result f1 = Path(tmpdir) / "run_1.json" f1.write_text(json.dumps({"v": 1})) update_latest_symlink(f1) # Second result replaces f2 = Path(tmpdir) / "run_2.json" f2.write_text(json.dumps({"v": 2})) update_latest_symlink(f2) link = Path(tmpdir) / "latest.json" data = json.loads(link.read_text()) assert data == {"v": 2} # ====================================================================== # utils.py # ====================================================================== class TestUtils: """Tests for benchmarks.downstream.utils.""" def test_import(self): from benchmarks.downstream import utils assert hasattr(utils, "AlignResult") assert hasattr(utils, "parse_fasta") assert hasattr(utils, "write_fasta") assert hasattr(utils, "mask_alignment_by_confidence") assert hasattr(utils, "write_site_weights") assert hasattr(utils, "holm_bonferroni") assert hasattr(utils, "METHOD_COLORS") assert hasattr(utils, "METHODS") assert hasattr(utils, "run_method") def test_align_result_fields(self): from benchmarks.downstream.utils import AlignResult r = AlignResult( sequences=["ACGT", "AC-T"], names=["s1", "s2"], column_confidence=[0.9, 0.8, 0.7, 0.6], residue_confidence=[[0.9, 0.8, 0.7, 0.6], [0.8, 0.7, 0.0, 0.5]], wall_time=1.5, peak_memory_mb=100.0, ) assert len(r.sequences) == 2 assert r.wall_time == 1.5 def test_fasta_roundtrip(self): from benchmarks.downstream.utils import parse_fasta, write_fasta names = ["seq1", "seq2", "seq3"] seqs = ["ACGTACGT" * 20, "TGCATGCA" * 20, "AAAA"] with tempfile.TemporaryDirectory() as tmpdir: fasta_path = Path(tmpdir) / "test.fasta" write_fasta(names, seqs, fasta_path) loaded_names, loaded_seqs = parse_fasta(fasta_path) assert loaded_names == names assert loaded_seqs == seqs def test_mask_alignment_basic(self): from benchmarks.downstream.utils import mask_alignment_by_confidence seqs = ["ABCD", "EFGH"] conf = [0.9, 0.3, 0.8, 0.2] masked, n_kept = mask_alignment_by_confidence(seqs, conf, 0.5) assert n_kept == 2 assert masked == ["AC", "EG"] def test_mask_alignment_empty(self): from benchmarks.downstream.utils import mask_alignment_by_confidence masked, n_kept = mask_alignment_by_confidence([], [], 0.5) assert n_kept == 0 assert masked == [] def test_mask_all_filtered(self): from benchmarks.downstream.utils import mask_alignment_by_confidence seqs = ["AB", "CD"] conf = [0.1, 0.2] masked, n_kept = mask_alignment_by_confidence(seqs, conf, 0.5) assert n_kept == 0 assert masked == ["", ""] def test_write_site_weights(self): from benchmarks.downstream.utils import write_site_weights with tempfile.TemporaryDirectory() as tmpdir: path = Path(tmpdir) / "weights.txt" conf = [0.95, 0.3, 1.5, -0.1] # includes out-of-range write_site_weights(conf, path) lines = path.read_text().strip().split("\n") assert len(lines) == 4 vals = [float(x) for x in lines] assert vals[0] == pytest.approx(0.95, abs=1e-5) assert vals[1] == pytest.approx(0.3, abs=1e-5) assert vals[2] == pytest.approx(1.0, abs=1e-5) # clamped assert vals[3] == pytest.approx(0.0, abs=1e-5) # clamped def test_holm_bonferroni_basic(self): from benchmarks.downstream.utils import holm_bonferroni # Simple case: 3 p-values adjusted = holm_bonferroni([0.01, 0.04, 0.03]) assert len(adjusted) == 3 # All adjusted values should be >= original for adj, orig in zip(adjusted, [0.01, 0.04, 0.03]): assert adj >= orig # All adjusted values should be <= 1.0 for adj in adjusted: assert adj <= 1.0 def test_holm_bonferroni_empty(self): from benchmarks.downstream.utils import holm_bonferroni assert holm_bonferroni([]) == [] def test_holm_bonferroni_single(self): from benchmarks.downstream.utils import holm_bonferroni result = holm_bonferroni([0.05]) assert len(result) == 1 assert result[0] == pytest.approx(0.05) def test_method_colors_has_entries(self): from benchmarks.downstream.utils import METHOD_COLORS assert "kalign" in METHOD_COLORS assert "mafft" in METHOD_COLORS assert "guidance2_mafft" in METHOD_COLORS def test_methods_registry_structure(self): from benchmarks.downstream.utils import METHODS assert "kalign" in METHODS assert "kalign_ens3" in METHODS assert "mafft" in METHODS assert "muscle" in METHODS assert "clustalo" in METHODS assert "guidance2_mafft" in METHODS # All entries have "fn" for name, cfg in METHODS.items(): assert "fn" in cfg, f"METHODS[{name!r}] missing 'fn'" assert callable(cfg["fn"]), f"METHODS[{name!r}]['fn'] not callable" def test_run_method_unknown_raises(self): from benchmarks.downstream.utils import run_method with pytest.raises(ValueError, match="Unknown method"): run_method("nonexistent_aligner", Path("/tmp/x.fa"), Path("/tmp")) # ====================================================================== # simulation.py # ====================================================================== class TestSimulation: """Tests for benchmarks.downstream.simulation.""" def test_import(self): from benchmarks.downstream import simulation assert hasattr(simulation, "SimulatedDataset") assert hasattr(simulation, "random_birth_death_tree") assert hasattr(simulation, "generate_indelible_dataset") assert hasattr(simulation, "CODON_GRID") assert hasattr(simulation, "PROTEIN_GRID") assert hasattr(simulation, "iter_simulation_params") assert hasattr(simulation, "strip_gaps") def test_simulated_dataset_fields(self): import dataclasses from benchmarks.downstream.simulation import SimulatedDataset fields = {f.name for f in dataclasses.fields(SimulatedDataset)} expected = {"true_alignment", "unaligned", "true_tree", "site_classes", "params"} assert expected == fields def test_strip_gaps(self): from benchmarks.downstream.simulation import strip_gaps assert strip_gaps(["A-C.G-T", "--ACGT", "ACGT"]) == [ "ACGT", "ACGT", "ACGT", ] def test_strip_gaps_empty(self): from benchmarks.downstream.simulation import strip_gaps assert strip_gaps([]) == [] assert strip_gaps(["---"]) == [""] def test_codon_grid_structure(self): from benchmarks.downstream.simulation import CODON_GRID assert len(CODON_GRID.n_taxa) == 3 assert len(CODON_GRID.tree_depths) == 3 assert len(CODON_GRID.indel_rates) == 3 assert CODON_GRID.replicates == 10 def test_protein_grid_structure(self): from benchmarks.downstream.simulation import PROTEIN_GRID assert len(PROTEIN_GRID.n_taxa) == 3 assert len(PROTEIN_GRID.tree_depths) == 4 assert len(PROTEIN_GRID.indel_rates) == 3 assert PROTEIN_GRID.replicates == 20 def test_iter_simulation_params_wag(self): from benchmarks.downstream.simulation import SimulationGrid, iter_simulation_params small_grid = SimulationGrid( n_taxa=[8], tree_depths=[0.5], indel_rates=[0.05], indel_length_means=[2.0], replicates=3, ) params = list(iter_simulation_params(small_grid, "WAG")) assert len(params) == 3 # 1x1x1x1x3 for p in params: assert "sim_id" in p assert p["model"] == "WAG" assert p["n_taxa"] == 8 assert "WAG" in p["sim_id"] def test_iter_simulation_params_m8(self): from benchmarks.downstream.simulation import SimulationGrid, iter_simulation_params small_grid = SimulationGrid( n_taxa=[16], tree_depths=[0.7], indel_rates=[0.05], psel_fractions=[0.0, 0.10], replicates=2, ) params = list(iter_simulation_params(small_grid, "M8")) assert len(params) == 4 # 1x1x1x2x2 for p in params: assert p["model"] == "M8" def test_iter_simulation_params_unknown_model(self): from benchmarks.downstream.simulation import SimulationGrid, iter_simulation_params small_grid = SimulationGrid(n_taxa=[8], tree_depths=[0.5], indel_rates=[0.05]) with pytest.raises(ValueError, match="Unknown model"): list(iter_simulation_params(small_grid, "JTT")) def test_indelible_control_file_codon(self): """Test that codon control file is written correctly.""" from benchmarks.downstream.simulation import _write_codon_control with tempfile.TemporaryDirectory() as tmpdir: tree = "((A:0.1,B:0.1):0.2,C:0.3);" path = _write_codon_control( Path(tmpdir), tree, n_codons=100, seed=123 ) assert path.exists() text = path.read_text() assert "[TYPE] CODON 1" in text assert "[randomseed] 123" in text assert "simmodel" in text assert "[EVOLVE]" in text def test_indelible_control_file_protein(self): """Test that protein control file is written correctly.""" from benchmarks.downstream.simulation import _write_protein_control with tempfile.TemporaryDirectory() as tmpdir: tree = "((A:0.1,B:0.1):0.2,C:0.3);" path = _write_protein_control( Path(tmpdir), tree, seq_length=200, seed=456 ) assert path.exists() text = path.read_text() assert "[TYPE] AMINOACID 1" in text assert "[randomseed] 456" in text assert "WAG" in text def test_parse_indelible_output_phylip(self): """Test PHYLIP parsing with synthetic data.""" from benchmarks.downstream.simulation import _parse_indelible_output with tempfile.TemporaryDirectory() as tmpdir: tmpdir = Path(tmpdir) # Write synthetic PHYLIP true alignment phy_path = tmpdir / "output_TRUE_1.phy" phy_path.write_text( " 3 10\n" "T1 ACGTACGTAC\n" "T2 ACGT--GTAC\n" "T3 AC--ACGTAC\n" ) # Write synthetic FASTA unaligned fas_path = tmpdir / "output_1.fas" fas_path.write_text( ">T1\nACGTACGTAC\n>T2\nACGTGTAC\n>T3\nACACGTAC\n" ) true_names, true_seqs, unaln_names, unaln_seqs = ( _parse_indelible_output(tmpdir) ) assert true_names == ["T1", "T2", "T3"] assert true_seqs[0] == "ACGTACGTAC" assert true_seqs[1] == "ACGT--GTAC" assert unaln_names == ["T1", "T2", "T3"] assert unaln_seqs[1] == "ACGTGTAC" def test_parse_site_classes_empty(self): """No rates file → all zeros.""" from benchmarks.downstream.simulation import _parse_site_classes with tempfile.TemporaryDirectory() as tmpdir: classes = _parse_site_classes(Path(tmpdir), 10) assert classes == [0] * 10 def test_parse_site_classes_with_data(self): """Synthetic rates file parsing.""" from benchmarks.downstream.simulation import _parse_site_classes with tempfile.TemporaryDirectory() as tmpdir: rates = Path(tmpdir) / "output_1_RATES.txt" rates.write_text( "Site\tClass\tRate\n" "1\t0\t0.5\n" "2\t0\t0.3\n" "3\t1\t2.5\n" "4\t0\t0.1\n" "5\t1\t3.0\n" ) classes = _parse_site_classes(Path(tmpdir), 5) assert classes == [0, 0, 1, 0, 1] # ====================================================================== # Cross-module integration # ====================================================================== class TestCrossModule: """Tests that modules work together correctly.""" def test_provenance_in_result_json(self): """provenance + utils.write_fasta can produce a complete result.""" from dataclasses import asdict from benchmarks.downstream.provenance import collect_provenance, result_path from benchmarks.downstream.utils import write_fasta with tempfile.TemporaryDirectory() as tmpdir: # Generate result path path = result_path(Path(tmpdir), "test_pipeline") assert path.parent.exists() # Collect provenance prov = collect_provenance({"method": "kalign_ens3"}) prov_dict = asdict(prov) # Write a fake result result = { "provenance": prov_dict, "cases": [{"sp_score": 0.85, "tc_score": 0.72}], } path.write_text(json.dumps(result, indent=2)) assert path.exists() # Verify it can be read back loaded = json.loads(path.read_text()) assert "provenance" in loaded assert loaded["provenance"]["cpu_cores"] > 0 def test_utils_fasta_compatible_with_simulation_strip_gaps(self): """write_fasta → parse_fasta → strip_gaps chain works.""" from benchmarks.downstream.simulation import strip_gaps from benchmarks.downstream.utils import parse_fasta, write_fasta names = ["s1", "s2"] seqs = ["AC-GT-A", "A--GTCA"] with tempfile.TemporaryDirectory() as tmpdir: path = Path(tmpdir) / "aligned.fasta" write_fasta(names, seqs, path) loaded_names, loaded_seqs = parse_fasta(path) assert loaded_names == names assert loaded_seqs == seqs # Strip gaps ungapped = strip_gaps(loaded_seqs) assert ungapped == ["ACGTA", "AGTCA"] kalign-3.5.1/tests/python/test_downstream_integration.py000066400000000000000000000363761515023132300236610ustar00rootroot00000000000000"""Integration tests for downstream benchmark package. Verifies that all modules import cleanly, dataclasses have correct fields, pipeline functions exist with correct signatures, the CLI works, and cross-module interactions are correct. """ from __future__ import annotations import json import subprocess import tempfile from pathlib import Path import pytest pytest.importorskip("benchmarks", reason="benchmarks package not on sys.path (run from repo root)") # ====================================================================== # Module import tests # ====================================================================== class TestModuleImports: """Verify every module in the downstream package imports without error.""" def test_import_package(self): from benchmarks.downstream import __init__ # noqa: F401 def test_import_provenance(self): from benchmarks.downstream import provenance # noqa: F401 def test_import_utils(self): from benchmarks.downstream import utils # noqa: F401 def test_import_simulation(self): from benchmarks.downstream import simulation # noqa: F401 def test_import_calibration(self): from benchmarks.downstream import calibration # noqa: F401 def test_import_positive_selection(self): from benchmarks.downstream import positive_selection # noqa: F401 def test_import_phylo_accuracy(self): from benchmarks.downstream import phylo_accuracy # noqa: F401 def test_import_hmmer_detection(self): from benchmarks.downstream import hmmer_detection # noqa: F401 def test_import_figures(self): from benchmarks.downstream import figures # noqa: F401 def test_import_main(self): from benchmarks.downstream import __main__ # noqa: F401 # ====================================================================== # Dataclass field tests # ====================================================================== class TestDataclassFields: """Verify all dataclasses have the expected fields.""" @staticmethod def _field_names(cls): import dataclasses return {f.name for f in dataclasses.fields(cls)} def test_provenance_fields(self): from benchmarks.downstream.provenance import Provenance fields = self._field_names(Provenance) for f in [ "timestamp", "kalign_version", "kalign_commit", "container_image", "hostname", "cpu_model", "cpu_cores", "ram_gb", "os_version", "python_version", "tool_versions", "parameters", ]: assert f in fields, f"Provenance missing field: {f}" def test_case_result_fields(self): from benchmarks.downstream.calibration import CaseResult fields = self._field_names(CaseResult) for f in [ "sim_id", "method", "predicted_confidence", "actual_correct", "sp_score", "tc_score", "wall_time", "peak_memory_mb", ]: assert f in fields, f"CaseResult missing field: {f}" def test_selection_case_result_fields(self): from benchmarks.downstream.positive_selection import SelectionCaseResult fields = self._field_names(SelectionCaseResult) for f in [ "sim_id", "method", "true_positives", "false_positives", "false_negatives", "true_negatives", "precision", "recall", "f1", "sp_score", ]: assert f in fields, f"SelectionCaseResult missing field: {f}" def test_phylo_case_result_fields(self): from benchmarks.downstream.phylo_accuracy import PhyloCaseResult fields = self._field_names(PhyloCaseResult) for f in [ "sim_id", "method", "nrf", "branch_score_dist", "sp_score", "wall_time_align", "wall_time_iqtree", ]: assert f in fields, f"PhyloCaseResult missing field: {f}" def test_hmmer_case_result_fields(self): from benchmarks.downstream.hmmer_detection import HmmerCaseResult fields = self._field_names(HmmerCaseResult) for f in [ "family_id", "method", "true_positives", "false_positives", "false_negatives", "sensitivity", ]: assert f in fields, f"HmmerCaseResult missing field: {f}" def test_simulated_dataset_fields(self): from benchmarks.downstream.simulation import SimulatedDataset fields = self._field_names(SimulatedDataset) for f in ["true_alignment", "unaligned", "true_tree", "site_classes", "params"]: assert f in fields, f"SimulatedDataset missing field: {f}" # ====================================================================== # Public API tests # ====================================================================== class TestPublicAPI: """Verify each module exposes the expected public functions.""" def test_provenance_api(self): from benchmarks.downstream import provenance assert callable(provenance.collect_provenance) assert callable(provenance.collect_tool_versions) assert callable(provenance.result_path) assert callable(provenance.update_latest_symlink) assert callable(provenance.load_latest_results) def test_utils_api(self): from benchmarks.downstream import utils assert callable(utils.parse_fasta) assert callable(utils.write_fasta) assert callable(utils.mask_alignment_by_confidence) assert callable(utils.write_site_weights) assert callable(utils.alignment_accuracy) assert callable(utils.compare_trees) assert callable(utils.bootstrap_ci) assert callable(utils.wilcoxon_paired) assert callable(utils.holm_bonferroni) assert callable(utils.run_method) assert isinstance(utils.METHODS, dict) assert isinstance(utils.METHOD_COLORS, dict) def test_simulation_api(self): from benchmarks.downstream import simulation assert callable(simulation.random_birth_death_tree) assert callable(simulation.generate_indelible_dataset) assert callable(simulation.iter_simulation_params) assert callable(simulation.strip_gaps) def test_calibration_api(self): from benchmarks.downstream import calibration assert callable(calibration.brier_score) assert callable(calibration.expected_calibration_error) assert callable(calibration.calibration_curve) assert callable(calibration.run_calibration_case) assert callable(calibration.run_pipeline) assert callable(calibration.load_results) def test_positive_selection_api(self): from benchmarks.downstream import positive_selection assert callable(positive_selection.run_selection_case) assert callable(positive_selection.run_pipeline) assert callable(positive_selection.load_results) def test_phylo_accuracy_api(self): from benchmarks.downstream import phylo_accuracy assert callable(phylo_accuracy.run_phylo_case) assert callable(phylo_accuracy.run_pipeline) assert callable(phylo_accuracy.load_results) def test_hmmer_detection_api(self): from benchmarks.downstream import hmmer_detection assert callable(hmmer_detection.run_hmmer_case) assert callable(hmmer_detection.run_pipeline) assert callable(hmmer_detection.load_results) assert isinstance(hmmer_detection.PFAM_FAMILIES, list) assert len(hmmer_detection.PFAM_FAMILIES) == 50 def test_figures_api(self): from benchmarks.downstream import figures assert callable(figures.figure_calibration) assert callable(figures.figure_positive_selection) assert callable(figures.figure_phylo_accuracy) assert callable(figures.figure_hmmer_detection) assert callable(figures.figure_speed_comparison) assert callable(figures.figure_summary_heatmap) assert callable(figures.generate_all_figures) # ====================================================================== # Calibration metric tests # ====================================================================== class TestCalibrationMetrics: """Test calibration scoring functions with known inputs.""" def test_brier_score_perfect(self): from benchmarks.downstream.calibration import brier_score # Perfect predictions: confidence matches outcome exactly assert brier_score([1.0, 0.0, 1.0], [1, 0, 1]) == pytest.approx(0.0) def test_brier_score_worst(self): from benchmarks.downstream.calibration import brier_score # Worst predictions: fully confident but wrong assert brier_score([1.0, 1.0], [0, 0]) == pytest.approx(1.0) def test_brier_score_uniform(self): from benchmarks.downstream.calibration import brier_score # Uniform 0.5 confidence, half correct score = brier_score([0.5, 0.5, 0.5, 0.5], [1, 0, 1, 0]) assert score == pytest.approx(0.25) def test_brier_score_empty(self): from benchmarks.downstream.calibration import brier_score assert brier_score([], []) == pytest.approx(0.0) def test_ece_perfect(self): from benchmarks.downstream.calibration import expected_calibration_error # Perfect calibration: 100% confidence, all correct assert expected_calibration_error([1.0, 1.0], [1, 1]) == pytest.approx( 0.0, abs=0.01 ) def test_calibration_curve_shape(self): from benchmarks.downstream.calibration import calibration_curve pred = [0.1, 0.2, 0.3, 0.8, 0.9, 0.95] actual = [0, 0, 1, 1, 1, 1] centers, fracs, counts = calibration_curve(pred, actual, n_bins=5) assert len(centers) == 5 assert len(fracs) == 5 assert len(counts) == 5 # ====================================================================== # Utils integration tests # ====================================================================== class TestUtilsIntegration: """Test utility functions with realistic data.""" def test_fasta_roundtrip_with_long_sequences(self): from benchmarks.downstream.utils import parse_fasta, write_fasta names = [f"seq{i}" for i in range(10)] seqs = ["ACDEFGHIKLMNPQRSTVWY" * 50 for _ in range(10)] # 1000 chars each with tempfile.TemporaryDirectory() as tmpdir: path = Path(tmpdir) / "test.fasta" write_fasta(names, seqs, path) loaded_names, loaded_seqs = parse_fasta(path) assert loaded_names == names assert loaded_seqs == seqs def test_mask_then_write(self): from benchmarks.downstream.utils import ( mask_alignment_by_confidence, parse_fasta, write_fasta, ) names = ["s1", "s2"] seqs = ["ABCDEFGH", "IJKLMNOP"] conf = [0.9, 0.1, 0.8, 0.2, 0.7, 0.3, 0.6, 0.4] masked, n_kept = mask_alignment_by_confidence(seqs, conf, 0.5) assert n_kept == 4 with tempfile.TemporaryDirectory() as tmpdir: path = Path(tmpdir) / "masked.fasta" write_fasta(names, masked, path) loaded_names, loaded_seqs = parse_fasta(path) assert loaded_names == names assert all(len(s) == 4 for s in loaded_seqs) def test_methods_registry_consistency(self): """Every method in METHODS should have a matching color.""" from benchmarks.downstream.utils import METHOD_COLORS, METHODS for name in METHODS: assert name in METHOD_COLORS, ( f"Method {name!r} in METHODS but not in METHOD_COLORS" ) # ====================================================================== # Simulation grid tests # ====================================================================== class TestSimulationGrids: """Test simulation parameter generation.""" def test_codon_grid_count(self): from benchmarks.downstream.simulation import CODON_GRID, iter_simulation_params params = list(iter_simulation_params(CODON_GRID, "M8")) # 3 taxa x 3 depths x 3 indel_rates x 3 psel_fracs x 3 reps = 243 assert len(params) == 243 def test_protein_grid_count(self): from benchmarks.downstream.simulation import ( PROTEIN_GRID, iter_simulation_params, ) params = list(iter_simulation_params(PROTEIN_GRID, "WAG")) # 2 taxa x 4 depths x 4 indel_rates x 2 indel_lengths x 3 reps = 192 assert len(params) == 192 def test_sim_ids_unique(self): from benchmarks.downstream.simulation import CODON_GRID, iter_simulation_params params = list(iter_simulation_params(CODON_GRID, "M8")) sim_ids = [p["sim_id"] for p in params] assert len(sim_ids) == len(set(sim_ids)), "sim_ids are not unique" # ====================================================================== # CLI tests # ====================================================================== class TestCLI: """Test the __main__.py CLI.""" def test_help_flag(self): result = subprocess.run( ["uv", "run", "python", "-m", "benchmarks.downstream", "--help"], capture_output=True, text=True, timeout=30, ) assert result.returncode == 0 assert "downstream" in result.stdout.lower() assert "--quick" in result.stdout assert "--all" in result.stdout assert "--figures" in result.stdout def test_no_args_exits_nonzero(self): result = subprocess.run( ["uv", "run", "python", "-m", "benchmarks.downstream"], capture_output=True, text=True, timeout=30, ) assert result.returncode != 0 # No action specified # ====================================================================== # Provenance integration # ====================================================================== class TestProvenanceIntegration: """Test provenance works end-to-end with result file management.""" def test_full_provenance_cycle(self): from dataclasses import asdict from benchmarks.downstream.provenance import ( collect_provenance, load_latest_results, result_path, update_latest_symlink, ) with tempfile.TemporaryDirectory() as tmpdir: # Collect provenance prov = collect_provenance({"pipeline": "test", "quick": True}) prov_dict = asdict(prov) # Generate result path path = result_path(Path(tmpdir), "test_pipeline") # Write result result_data = { "provenance": prov_dict, "cases": [{"method": "kalign", "sp_score": 0.85}], "summary": {"kalign": {"mean_sp": 0.85}}, } path.write_text(json.dumps(result_data, indent=2)) # Create symlink update_latest_symlink(path) # Load via symlink loaded = load_latest_results(path.parent) assert loaded["provenance"]["cpu_cores"] > 0 assert loaded["cases"][0]["sp_score"] == 0.85 def test_kalign_version_detected(self): from benchmarks.downstream.provenance import collect_provenance prov = collect_provenance({}) # kalign should be installed in the dev environment assert prov.kalign_version != "not installed" kalign-3.5.1/tests/python/test_ecosystem_integration.py000066400000000000000000000272561515023132300235060ustar00rootroot00000000000000""" Tests for bioinformatics ecosystem integration features. This module tests the Biopython and scikit-bio integration capabilities, as well as threading controls and I/O helpers. """ import pytest from unittest.mock import patch import kalign # Test data TEST_SEQUENCES = ["ATCGATCGATCG", "ATCGTCGATCG", "ATCGATCATCG"] TEST_IDS = ["seq1", "seq2", "seq3"] class TestReturnFormats: """Test different return format options.""" def test_plain_format_default(self): """Test default plain format returns list of strings.""" result = kalign.align(TEST_SEQUENCES) assert isinstance(result, list) assert all(isinstance(seq, str) for seq in result) assert len(result) == len(TEST_SEQUENCES) def test_plain_format_explicit(self): """Test explicit plain format specification.""" result = kalign.align(TEST_SEQUENCES, fmt="plain") assert isinstance(result, list) assert all(isinstance(seq, str) for seq in result) def test_biopython_format_with_biopython(self): """Test Biopython format when Biopython is available.""" try: from Bio.Align import MultipleSeqAlignment except ImportError: pytest.skip("Biopython not installed") result = kalign.align(TEST_SEQUENCES, fmt="biopython", ids=TEST_IDS) assert isinstance(result, MultipleSeqAlignment) assert len(result) == len(TEST_SEQUENCES) assert result[0].id == TEST_IDS[0] def test_biopython_format_without_biopython(self): """Test Biopython format fails gracefully without Biopython.""" with patch.dict( "sys.modules", {"Bio.Align": None, "Bio.SeqRecord": None, "Bio.Seq": None} ): with pytest.raises(ImportError, match="Biopython not installed"): kalign.align(TEST_SEQUENCES, fmt="biopython") def test_skbio_format_with_skbio(self): """Test scikit-bio format when scikit-bio is available.""" try: import skbio except ImportError: pytest.skip("scikit-bio not installed") result = kalign.align(TEST_SEQUENCES, fmt="skbio") assert isinstance(result, skbio.TabularMSA) assert len(result) == len(TEST_SEQUENCES) def test_skbio_format_without_skbio(self): """Test scikit-bio format fails gracefully without scikit-bio.""" with patch.dict("sys.modules", {"skbio": None, "skbio.sequence": None}): with pytest.raises(ImportError, match="scikit-bio not installed"): kalign.align(TEST_SEQUENCES, fmt="skbio") def test_invalid_format(self): """Test invalid format specification raises error.""" with pytest.raises(ValueError, match="Unknown fmt"): kalign.align(TEST_SEQUENCES, fmt="invalid") def test_ids_validation(self): """Test ID validation for ecosystem formats.""" # Too few IDs with pytest.raises(ValueError, match="Number of IDs"): kalign.align(TEST_SEQUENCES, fmt="plain", ids=["seq1"]) # Too many IDs with pytest.raises(ValueError, match="Number of IDs"): kalign.align( TEST_SEQUENCES, fmt="plain", ids=["seq1", "seq2", "seq3", "seq4"] ) def test_auto_generated_ids(self): """Test automatic ID generation for ecosystem formats.""" try: from Bio.Align import MultipleSeqAlignment except ImportError: pytest.skip("Biopython not installed") result = kalign.align(TEST_SEQUENCES, fmt="biopython") assert isinstance(result, MultipleSeqAlignment) for i, record in enumerate(result): assert record.id == f"seq{i}" class TestThreadingControl: """Test global threading control functions.""" def test_default_thread_count(self): """Test default thread count is 1.""" assert kalign.get_num_threads() == 1 def test_set_get_threads(self): """Test setting and getting thread count.""" original = kalign.get_num_threads() try: kalign.set_num_threads(4) assert kalign.get_num_threads() == 4 kalign.set_num_threads(8) assert kalign.get_num_threads() == 8 finally: kalign.set_num_threads(original) def test_invalid_thread_count(self): """Test invalid thread counts raise errors.""" with pytest.raises(ValueError, match="must be at least 1"): kalign.set_num_threads(0) with pytest.raises(ValueError, match="must be at least 1"): kalign.set_num_threads(-1) def test_thread_local_storage(self): """Test that thread settings are thread-local.""" import threading import time results = {} def worker(thread_id, num_threads): kalign.set_num_threads(num_threads) time.sleep(0.1) # Allow other threads to set different values results[thread_id] = kalign.get_num_threads() # Start multiple threads with different thread counts threads = [] for i in range(3): t = threading.Thread(target=worker, args=(i, (i + 1) * 2)) threads.append(t) t.start() # Wait for all threads to complete for t in threads: t.join() # Each thread should have maintained its own setting assert results[0] == 2 assert results[1] == 4 assert results[2] == 6 def test_align_uses_default_threads(self): """Test that align() uses default thread count when n_threads=None.""" original = kalign.get_num_threads() try: kalign.set_num_threads(4) # This should use the default (4 threads) # We can't easily test this directly, but we can ensure it doesn't crash result = kalign.align(TEST_SEQUENCES, n_threads=None) assert len(result) == len(TEST_SEQUENCES) finally: kalign.set_num_threads(original) def test_align_override_threads(self): """Test that align() can override default thread count.""" original = kalign.get_num_threads() try: kalign.set_num_threads(4) # This should override the default result = kalign.align(TEST_SEQUENCES, n_threads=8) assert len(result) == len(TEST_SEQUENCES) finally: kalign.set_num_threads(original) class TestIOModule: """Test I/O helper functions.""" def test_io_module_imported(self): """Test that I/O module is properly imported.""" assert hasattr(kalign, "io") assert hasattr(kalign.io, "read_fasta") assert hasattr(kalign.io, "write_fasta") assert hasattr(kalign.io, "write_clustal") assert hasattr(kalign.io, "write_stockholm") assert hasattr(kalign.io, "write_phylip") def test_io_functions_require_biopython(self): """Test that I/O functions require Biopython and fail gracefully.""" with patch.dict("sys.modules", {"Bio": None, "Bio.SeqIO": None}): with pytest.raises(ImportError, match="Biopython required"): kalign.io.read_fasta("test.fasta") class TestUtilsModule: """Test utility functions.""" def test_utils_module_imported(self): """Test that utils module is properly imported.""" assert hasattr(kalign, "utils") assert hasattr(kalign.utils, "to_array") assert hasattr(kalign.utils, "alignment_stats") assert hasattr(kalign.utils, "consensus_sequence") def test_to_array(self): """Test conversion to NumPy array.""" aligned = kalign.align(TEST_SEQUENCES) arr = kalign.utils.to_array(aligned) assert arr.shape[0] == len(aligned) assert arr.shape[1] == len(aligned[0]) assert arr.dtype.kind == "U" # Unicode string def test_to_array_empty(self): """Test to_array with empty alignment.""" with pytest.raises(ValueError, match="Empty alignment"): kalign.utils.to_array([]) def test_alignment_stats(self): """Test alignment statistics calculation.""" aligned = kalign.align(TEST_SEQUENCES) stats = kalign.utils.alignment_stats(aligned) required_keys = { "length", "n_sequences", "gap_fraction", "conservation", "identity", } assert set(stats.keys()) == required_keys assert stats["n_sequences"] == len(aligned) assert stats["length"] == len(aligned[0]) assert 0 <= stats["gap_fraction"] <= 1 assert 0 <= stats["conservation"] <= 1 assert 0 <= stats["identity"] <= 1 def test_consensus_sequence(self): """Test consensus sequence generation.""" aligned = kalign.align(TEST_SEQUENCES) consensus = kalign.utils.consensus_sequence(aligned) assert isinstance(consensus, str) assert len(consensus) == len(aligned[0]) def test_consensus_sequence_empty(self): """Test consensus with empty alignment.""" with pytest.raises(ValueError, match="Empty alignment"): kalign.utils.consensus_sequence([]) def test_consensus_sequence_invalid_threshold(self): """Test consensus with invalid threshold.""" aligned = kalign.align(TEST_SEQUENCES) with pytest.raises(ValueError, match="Threshold must be between 0 and 1"): kalign.utils.consensus_sequence(aligned, threshold=-0.1) with pytest.raises(ValueError, match="Threshold must be between 0 and 1"): kalign.utils.consensus_sequence(aligned, threshold=1.1) class TestBackwardCompatibility: """Test that all changes maintain backward compatibility.""" def test_existing_api_unchanged(self): """Test that existing API still works exactly as before.""" # All these calls should work exactly as they did before result1 = kalign.align(TEST_SEQUENCES) result2 = kalign.align(TEST_SEQUENCES, seq_type="dna") result3 = kalign.align(TEST_SEQUENCES, seq_type="dna", n_threads=2) result4 = kalign.align(TEST_SEQUENCES, gap_open=5.0, gap_extend=1.0) # All should return lists of strings for result in [result1, result2, result3, result4]: assert isinstance(result, list) assert all(isinstance(seq, str) for seq in result) assert len(result) == len(TEST_SEQUENCES) def test_module_exports(self): """Test that all expected exports are available.""" expected_exports = { "align", "align_from_file", "align_file_to_file", "compare", "compare_detailed", "write_alignment", "generate_test_sequences", "set_num_threads", "get_num_threads", "kalign", "AlignedSequences", "io", "utils", "DNA", "DNA_INTERNAL", "RNA", "PROTEIN", "PROTEIN_PFASUM43", "PROTEIN_PFASUM60", "PROTEIN_PFASUM_AUTO", "PROTEIN_DIVERGENT", "AUTO", "REFINE_NONE", "REFINE_ALL", "REFINE_CONFIDENT", "REFINE_INLINE", "MODE_DEFAULT", "MODE_FAST", "MODE_PRECISE", "__version__", "__author__", "__email__", } actual_exports = set(kalign.__all__) assert expected_exports == actual_exports def test_convenience_alias(self): """Test that the kalign convenience alias still works.""" result1 = kalign.align(TEST_SEQUENCES) result2 = kalign.kalign(TEST_SEQUENCES) # Alias # Results should be identical assert result1 == result2 kalign-3.5.1/tests/python/test_ecosystem_real.py000066400000000000000000000214621515023132300220770ustar00rootroot00000000000000""" Integration tests that exercise real ecosystem packages. These tests require the actual packages installed (biopython, scikit-bio). They are skipped when the packages are not available, but exercised in CI via the test_ecosystem job which installs kalign[all]. Biopython and scikit-bio test groups are independently skippable. """ import os import pytest import kalign # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _skip_no_biopython(): try: import Bio # noqa: F401 return False except ImportError: return True def _skip_no_skbio(): try: import skbio # noqa: F401 return False except ImportError: return True def _assert_alignment_valid(aligned, input_seqs): """Verify aligned sequences are a plausible alignment of the inputs.""" assert len(aligned) == len(input_seqs), ( f"Aligned count ({len(aligned)}) != input count ({len(input_seqs)})" ) # All aligned sequences must be the same length lengths = {len(s) for s in aligned} assert len(lengths) == 1, f"Inconsistent alignment lengths: {lengths}" aln_len = lengths.pop() # Alignment must be at least as long as the longest input max_input = max(len(s) for s in input_seqs) assert aln_len >= max_input # If inputs differ in length, at least one aligned seq must contain gaps if len({len(s) for s in input_seqs}) > 1: assert any("-" in s for s in aligned), "Inputs differ in length but no gaps in alignment" # Ungapped content must match the original sequences for orig, aln in zip(input_seqs, aligned): assert aln.replace("-", "") == orig # --------------------------------------------------------------------------- # Test data # --------------------------------------------------------------------------- DNA_SEQS = ["ATCGATCGATCG", "ATCGTCGATCG", "ATCGATCATCG"] DNA_IDS = ["seq1", "seq2", "seq3"] RNA_SEQS = ["AUCGAUCGAUCG", "AUCGUCGAUCG", "AUCGAUCAUCG"] PROTEIN_SEQS = [ "MKTAYIAKQRQISFVK", "MKTAYIAKQRQ", "MKTAYIAK", ] # Path to test FASTA data shipped with the project TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data") TEST_FASTA = os.path.join(TEST_DATA_DIR, "BB11001.tfa") # --------------------------------------------------------------------------- # Biopython tests (skipped independently if Bio is not installed) # --------------------------------------------------------------------------- @pytest.mark.skipif(_skip_no_biopython(), reason="Biopython not installed") class TestBiopythonFormat: """Test fmt='biopython' with real Biopython.""" def test_align_biopython_format_dna(self): from Bio.Align import MultipleSeqAlignment result = kalign.align(DNA_SEQS, fmt="biopython", ids=DNA_IDS) assert isinstance(result, MultipleSeqAlignment) assert len(result) == len(DNA_SEQS) assert result[0].id == "seq1" assert result[1].id == "seq2" assert result[2].id == "seq3" # Verify actual alignment content aligned_strs = [str(r.seq) for r in result] _assert_alignment_valid(aligned_strs, DNA_SEQS) def test_align_biopython_format_protein(self): from Bio.Align import MultipleSeqAlignment result = kalign.align( PROTEIN_SEQS, seq_type="protein", fmt="biopython", ids=["p1", "p2", "p3"], ) assert isinstance(result, MultipleSeqAlignment) assert len(result) == len(PROTEIN_SEQS) aligned_strs = [str(r.seq) for r in result] _assert_alignment_valid(aligned_strs, PROTEIN_SEQS) def test_align_biopython_auto_ids(self): from Bio.Align import MultipleSeqAlignment result = kalign.align(DNA_SEQS, fmt="biopython") assert isinstance(result, MultipleSeqAlignment) assert result[0].id == "seq0" @pytest.mark.skipif(_skip_no_biopython(), reason="Biopython not installed") class TestIORead: """Test kalign.io read functions with real Biopython.""" def test_read_fasta(self): sequences = kalign.io.read_fasta(TEST_FASTA) assert isinstance(sequences, list) assert len(sequences) > 0 assert all(isinstance(s, str) for s in sequences) assert all(len(s) > 0 for s in sequences) def test_read_sequences(self): sequences, ids = kalign.io.read_sequences(TEST_FASTA) assert len(sequences) == len(ids) assert len(sequences) > 0 assert all(len(s) > 0 for s in sequences) assert all(len(i) > 0 for i in ids) @pytest.mark.skipif(_skip_no_biopython(), reason="Biopython not installed") class TestIOWrite: """Test kalign.io write functions with real Biopython.""" @pytest.fixture def aligned(self): return kalign.align(DNA_SEQS) def test_write_fasta_roundtrip(self, aligned, tmp_path): out = tmp_path / "out.fasta" kalign.io.write_fasta(aligned, str(out), ids=DNA_IDS) read_back = kalign.io.read_fasta(str(out)) assert read_back == aligned def test_write_clustal(self, aligned, tmp_path): from Bio import AlignIO out = tmp_path / "out.aln" kalign.io.write_clustal(aligned, str(out), ids=DNA_IDS) aln = AlignIO.read(str(out), "clustal") assert len(aln) == len(aligned) assert aln.get_alignment_length() == len(aligned[0]) # Verify content matches for orig, record in zip(aligned, aln): assert str(record.seq) == orig def test_write_stockholm(self, aligned, tmp_path): from Bio import AlignIO out = tmp_path / "out.sto" kalign.io.write_stockholm(aligned, str(out), ids=DNA_IDS) aln = AlignIO.read(str(out), "stockholm") assert len(aln) == len(aligned) assert aln.get_alignment_length() == len(aligned[0]) for orig, record in zip(aligned, aln): assert str(record.seq) == orig def test_write_phylip(self, aligned, tmp_path): from Bio import AlignIO out = tmp_path / "out.phy" kalign.io.write_phylip(aligned, str(out), ids=DNA_IDS) aln = AlignIO.read(str(out), "phylip-sequential") assert len(aln) == len(aligned) for orig, record in zip(aligned, aln): assert str(record.seq) == orig # --------------------------------------------------------------------------- # scikit-bio tests (skipped independently if skbio is not installed) # --------------------------------------------------------------------------- @pytest.mark.skipif(_skip_no_skbio(), reason="scikit-bio not installed") class TestSkbioFormat: """Test fmt='skbio' with real scikit-bio.""" def test_align_skbio_format_dna(self): import skbio result = kalign.align(DNA_SEQS, seq_type="dna", fmt="skbio", ids=DNA_IDS) assert isinstance(result, skbio.TabularMSA) assert len(result) == len(DNA_SEQS) assert all(isinstance(seq, skbio.DNA) for seq in result) # Verify alignment content aligned_strs = [str(seq) for seq in result] _assert_alignment_valid(aligned_strs, DNA_SEQS) def test_align_skbio_format_rna(self): import skbio result = kalign.align(RNA_SEQS, seq_type="rna", fmt="skbio") assert isinstance(result, skbio.TabularMSA) assert len(result) == len(RNA_SEQS) assert all(isinstance(seq, skbio.RNA) for seq in result) aligned_strs = [str(seq) for seq in result] _assert_alignment_valid(aligned_strs, RNA_SEQS) def test_align_skbio_format_protein(self): import skbio result = kalign.align( PROTEIN_SEQS, seq_type="protein", fmt="skbio", ids=["p1", "p2", "p3"] ) assert isinstance(result, skbio.TabularMSA) assert len(result) == len(PROTEIN_SEQS) assert all(isinstance(seq, skbio.Protein) for seq in result) aligned_strs = [str(seq) for seq in result] _assert_alignment_valid(aligned_strs, PROTEIN_SEQS) def test_align_skbio_auto_detect_dna(self): """AUTO seq_type should infer DNA and produce skbio.DNA objects.""" import skbio result = kalign.align(DNA_SEQS, fmt="skbio") assert all(isinstance(seq, skbio.DNA) for seq in result) def test_align_skbio_auto_detect_protein(self): """AUTO seq_type should infer Protein and produce skbio.Protein objects.""" import skbio result = kalign.align(PROTEIN_SEQS, fmt="skbio") assert all(isinstance(seq, skbio.Protein) for seq in result) def test_align_skbio_metadata(self): import skbio result = kalign.align(DNA_SEQS, seq_type="dna", fmt="skbio", ids=DNA_IDS) assert result[0].metadata["id"] == "seq1" assert result[1].metadata["id"] == "seq2" assert result[2].metadata["id"] == "seq3" kalign-3.5.1/tests/python/test_edge_cases.py000066400000000000000000000056701515023132300211460ustar00rootroot00000000000000""" Edge case tests for Kalign Python package. """ import pytest import kalign class TestEdgeCases: """Test unusual inputs and boundary conditions.""" def test_identical_sequences(self): """Test alignment of identical sequences.""" identical = ["ATCGATCG"] * 3 aligned = kalign.align(identical, seq_type="dna") assert len(aligned) == 3 # All should be identical (no gaps needed) assert all(seq == aligned[0] for seq in aligned) def test_very_short_sequences(self): """Test very short sequences.""" short_seqs = ["A", "T", "G"] aligned = kalign.align(short_seqs, seq_type="dna") assert len(aligned) == 3 assert all(len(seq) >= 1 for seq in aligned) def test_very_different_lengths(self): """Test sequences with very different lengths.""" diff_lengths = ["A", "ATCGATCGATCGATCG", "ATCG"] aligned = kalign.align(diff_lengths, seq_type="dna") assert len(aligned) == 3 assert all(len(seq) == len(aligned[0]) for seq in aligned) def test_single_character_sequences(self): """Test single character sequences.""" single_chars = ["A", "T", "C", "G"] aligned = kalign.align(single_chars, seq_type="dna") assert len(aligned) == 4 def test_repetitive_sequences(self): """Test highly repetitive sequences.""" repetitive = ["AAAAAAA", "TTTTTTT", "AAAAAAA"] aligned = kalign.align(repetitive, seq_type="dna") assert len(aligned) == 3 def test_mixed_case_sequences(self, mixed_case): """Test mixed case handling.""" aligned = kalign.align(mixed_case, seq_type="dna") assert len(aligned) == len(mixed_case) def test_large_sequence_count(self): """Test with many sequences.""" # Use valid DNA characters only - create variation with different bases base_patterns = ["ATCG", "TACG", "GATC", "CGTA", "TGCA", "ACGT", "GCTA", "CTAG"] many_seqs = [] for i in range(20): pattern = base_patterns[i % len(base_patterns)] # Add length variation with valid DNA bases suffix = "A" * (i % 4) # Add 0-3 A's for length variation many_seqs.append(f"{pattern}{suffix}TG") aligned = kalign.align(many_seqs, seq_type="dna") assert len(aligned) == 20 assert all(len(seq) == len(aligned[0]) for seq in aligned) def test_ambiguous_nucleotides(self): """Test sequences with ambiguous nucleotides.""" ambiguous = ["ATCGN", "ATCGY", "ATCGR"] # Use auto-detection since ambiguous nucleotides might be detected as protein try: aligned = kalign.align(ambiguous) # Let kalign auto-detect the type assert len(aligned) == 3 # Should handle gracefully with auto-detection except (ValueError, RuntimeError): # Some ambiguous characters might still cause issues pass kalign-3.5.1/tests/python/test_error_handling.py000066400000000000000000000043351515023132300220560ustar00rootroot00000000000000""" Error handling and exception tests for Kalign Python package. """ import pytest import kalign class TestErrorHandling: """Test error conditions and exception handling.""" def test_invalid_sequence_type_raises_error(self, dna_simple): """Test that invalid sequence type raises ValueError.""" with pytest.raises(ValueError, match="Invalid seq_type"): kalign.align(dna_simple, seq_type="invalid_type") def test_zero_threads_raises_error(self, dna_simple): """Test that zero threads raises ValueError.""" with pytest.raises(ValueError, match="at least 1"): kalign.align(dna_simple, n_threads=0) def test_negative_threads_raises_error(self, dna_simple): """Test that negative threads raises ValueError.""" with pytest.raises(ValueError, match="at least 1"): kalign.align(dna_simple, n_threads=-1) def test_empty_sequence_in_list_raises_error(self): """Test that empty sequences raise ValueError.""" with pytest.raises( ValueError, match="Sequence at index 1 is empty or contains only whitespace" ): kalign.align(["ATCG", "", "GCTA"]) def test_non_string_sequence_raises_error(self): """Test that non-string sequences raise ValueError.""" with pytest.raises(ValueError, match="must be strings"): kalign.align(["ATCG", 123, "GCTA"]) def test_runtime_error_on_alignment_failure(self): """Test that alignment failures raise RuntimeError.""" # Test with sequences containing invalid characters that should cause failure with pytest.raises((RuntimeError, ValueError)): kalign.align(["ATCGXYZ123", "ATCGXYZ456"], seq_type="dna") def test_file_not_found_error(self): """Test file not found error handling.""" with pytest.raises(FileNotFoundError): kalign.align_from_file("/nonexistent/file.fasta") def test_invalid_file_format_error(self, temp_dir): """Test invalid file format handling.""" invalid_file = temp_dir / "invalid.txt" invalid_file.write_text("This is not a sequence file") with pytest.raises(RuntimeError): kalign.align_from_file(str(invalid_file)) kalign-3.5.1/tests/python/test_file_operations.py000066400000000000000000000054521515023132300222440ustar00rootroot00000000000000""" File I/O operation tests for Kalign Python package. """ import pytest import kalign from pathlib import Path class TestFileOperations: """Test file-based alignment operations.""" @pytest.mark.file_io def test_align_from_fasta_file(self, sample_fasta_file): """Test alignment from FASTA file.""" result = kalign.align_from_file(sample_fasta_file, seq_type="dna") assert len(result.sequences) == 3 assert len(result.names) == 3 assert all(len(seq) == len(result.sequences[0]) for seq in result.sequences) @pytest.mark.file_io def test_align_protein_fasta_file(self, sample_protein_fasta_file): """Test protein alignment from FASTA file.""" result = kalign.align_from_file(sample_protein_fasta_file, seq_type="protein") assert len(result.sequences) == 3 assert len(result.names) == 3 assert all(len(seq) == len(result.sequences[0]) for seq in result.sequences) @pytest.mark.file_io def test_auto_detect_from_file(self, sample_fasta_file): """Test auto-detection with file input.""" result = kalign.align_from_file(sample_fasta_file) assert len(result.sequences) == 3 assert len(result.names) == 3 @pytest.mark.file_io def test_file_not_found(self, nonexistent_file): """Test handling of non-existent files.""" with pytest.raises(FileNotFoundError): kalign.align_from_file(nonexistent_file) @pytest.mark.file_io def test_invalid_file_format(self, invalid_fasta_file): """Test handling of invalid file formats.""" with pytest.raises(RuntimeError): kalign.align_from_file(invalid_fasta_file) @pytest.mark.file_io def test_file_with_threading(self, sample_fasta_file): """Test file operations with multiple threads.""" result = kalign.align_from_file(sample_fasta_file, n_threads=2) assert len(result.sequences) == 3 @pytest.mark.file_io def test_relative_file_path(self, test_data_dir): """Test relative file paths.""" dna_file = test_data_dir / "dna_sequences.fasta" if dna_file.exists(): result = kalign.align_from_file(str(dna_file)) assert len(result.sequences) >= 1 @pytest.mark.file_io def test_names_preserved(self, sample_fasta_file): """Test that sequence names from the file are preserved.""" result = kalign.align_from_file(sample_fasta_file, seq_type="dna") assert result.names == ["seq1", "seq2", "seq3"] @pytest.mark.file_io def test_named_tuple_unpacking(self, sample_fasta_file): """Test that result can be unpacked as a tuple.""" names, sequences = kalign.align_from_file(sample_fasta_file, seq_type="dna") assert len(names) == 3 assert len(sequences) == 3 kalign-3.5.1/tests/python/test_input_validation.py000066400000000000000000000051101515023132300224220ustar00rootroot00000000000000""" Input validation tests for Kalign Python package. """ import pytest import kalign class TestInputValidation: """Test input validation and error handling.""" def test_empty_sequence_list(self): """Test empty sequence list raises ValueError.""" with pytest.raises(ValueError, match="No sequences were found in the input"): kalign.align([]) def test_empty_strings_in_list(self): """Test empty strings in sequence list.""" with pytest.raises( ValueError, match="Sequence at index 1 is empty or contains only whitespace" ): kalign.align(["ATCG", "", "GCTA"]) def test_whitespace_only_sequences(self): """Test sequences with only whitespace.""" with pytest.raises( ValueError, match="Sequence at index 1 is empty or contains only whitespace" ): kalign.align(["ATCG", " ", "GCTA"]) def test_non_string_sequences(self): """Test non-string elements in sequence list.""" with pytest.raises(ValueError, match="must be strings"): kalign.align(["ATCG", 123, "GCTA"]) def test_none_in_sequence_list(self): """Test None values in sequence list.""" with pytest.raises(ValueError, match="must be strings"): kalign.align(["ATCG", None, "GCTA"]) def test_invalid_sequence_type_string(self): """Test invalid sequence type string.""" with pytest.raises(ValueError, match="Invalid seq_type"): kalign.align(["ATCG", "GCTA"], seq_type="invalid") def test_invalid_thread_count_zero(self): """Test zero thread count.""" with pytest.raises(ValueError, match="at least 1"): kalign.align(["ATCG", "GCTA"], n_threads=0) def test_invalid_thread_count_negative(self): """Test negative thread count.""" with pytest.raises(ValueError, match="at least 1"): kalign.align(["ATCG", "GCTA"], n_threads=-1) def test_valid_thread_counts(self): """Test valid thread counts work.""" sequences = ["ATCG", "GCTA"] # These should not raise errors for n_threads in [1, 2, 4]: aligned = kalign.align(sequences, n_threads=n_threads) assert len(aligned) == 2 def test_case_insensitive_sequence_types(self): """Test case insensitive sequence type specification.""" sequences = ["ATCG", "GCTA"] # These should all work for seq_type in ["DNA", "dna", "Dna", "DNA"]: aligned = kalign.align(sequences, seq_type=seq_type) assert len(aligned) == 2 kalign-3.5.1/tests/python/test_integration.py000066400000000000000000000070451515023132300214050ustar00rootroot00000000000000""" Integration tests for Kalign Python package. """ import pytest import kalign from pathlib import Path class TestIntegration: """Test end-to-end workflows and integration scenarios.""" @pytest.mark.integration def test_full_dna_workflow(self, temp_dir): """Test complete DNA alignment workflow.""" # Create test sequences sequences = ["ATCGATCGATCGATCG", "ATCGATCGTCGATCG", "ATCGATCGATCATCG"] # Align sequences aligned = kalign.align(sequences, seq_type="dna", n_threads=2) # Validate results assert len(aligned) == 3 assert all(len(seq) == len(aligned[0]) for seq in aligned) # Check that original sequences are preserved (without gaps) for orig, align in zip(sequences, aligned): degapped = align.replace("-", "") assert degapped == orig @pytest.mark.integration def test_full_protein_workflow(self, sample_protein_fasta_file): """Test complete protein alignment workflow.""" # Read and align from file result = kalign.align_from_file( sample_protein_fasta_file, seq_type="protein", gap_open=10.0, gap_extend=1.0, ) assert len(result.sequences) == 3 assert all(isinstance(seq, str) for seq in result.sequences) @pytest.mark.integration def test_mixed_parameter_workflow(self, dna_simple): """Test workflow with various parameter combinations.""" results = [] # Test different parameter combinations param_sets = [ {"seq_type": "dna", "n_threads": 1}, {"seq_type": "dna", "n_threads": 2, "gap_open": 8.0}, {"seq_type": "auto", "gap_extend": 2.0}, ] for params in param_sets: aligned = kalign.align(dna_simple, **params) results.append(aligned) assert len(aligned) == len(dna_simple) # All results should be valid (though may differ) for result in results: assert all(len(seq) == len(result[0]) for seq in result) @pytest.mark.integration def test_error_recovery(self, dna_simple): """Test that system recovers from errors properly.""" # First, cause an error try: kalign.align([], seq_type="dna") except ValueError: pass # Expected # Then verify normal operation still works aligned = kalign.align(dna_simple, seq_type="dna") assert len(aligned) == len(dna_simple) @pytest.mark.integration def test_consistency_across_calls(self, dna_simple): """Test that results are consistent across multiple calls.""" aligned1 = kalign.align(dna_simple, seq_type="dna", n_threads=1) aligned2 = kalign.align(dna_simple, seq_type="dna", n_threads=1) # Results should be identical for same input/parameters assert aligned1 == aligned2 @pytest.mark.integration def test_real_biological_sequences(self, test_data_dir): """Test with real biological sequences if available.""" # Use the test data files we created dna_file = test_data_dir / "dna_sequences.fasta" protein_file = test_data_dir / "protein_sequences.fasta" if dna_file.exists(): result = kalign.align_from_file(str(dna_file), seq_type="dna") assert len(result.sequences) >= 1 if protein_file.exists(): result = kalign.align_from_file( str(protein_file), seq_type="protein" ) assert len(result.sequences) >= 1 kalign-3.5.1/tests/python/test_modes.py000066400000000000000000000107171515023132300201710ustar00rootroot00000000000000"""Tests for the unified mode interface (default/fast/precise).""" import os import tempfile import pytest import kalign TEST_SEQUENCES = ["ATCGATCGATCG", "ATCGTCGATCG", "ATCGATCATCG"] PROTEIN_SEQUENCES = [ "MKFLILLFNILCLFPVLAADNHGVSLHCTTATAIP", "MKFLILLFNILCLFPVLAADNHGVSLHCTTATAIP", "MKFLILLFNILCLFPVLAADNHGVSLHCTTATAIP", ] TEST_FILE = os.path.join(os.path.dirname(__file__), "..", "data", "BB11001.tfa") class TestModeConstants: """Test mode constant exports.""" def test_mode_constants_exist(self): assert kalign.MODE_DEFAULT == "default" assert kalign.MODE_FAST == "fast" assert kalign.MODE_PRECISE == "precise" class TestAlignModes: """Test mode parameter on align().""" def test_default_mode_no_kwarg(self): """Default mode (no mode kwarg) produces alignment.""" result = kalign.align(TEST_SEQUENCES) assert isinstance(result, list) assert len(result) == len(TEST_SEQUENCES) assert all(len(s) == len(result[0]) for s in result) def test_default_mode_explicit(self): """mode='default' produces alignment.""" result = kalign.align(TEST_SEQUENCES, mode="default") assert isinstance(result, list) assert len(result) == len(TEST_SEQUENCES) def test_fast_mode(self): """mode='fast' produces alignment.""" result = kalign.align(TEST_SEQUENCES, mode="fast") assert isinstance(result, list) assert len(result) == len(TEST_SEQUENCES) assert all(len(s) == len(result[0]) for s in result) def test_precise_mode(self): """mode='precise' produces alignment (ensemble).""" result = kalign.align(TEST_SEQUENCES, mode="precise") # precise uses ensemble, which returns (seqs, confidence) tuple if isinstance(result, tuple): seqs = result[0] else: seqs = result assert len(seqs) == len(TEST_SEQUENCES) assert all(len(s) == len(seqs[0]) for s in seqs) def test_invalid_mode(self): """Invalid mode raises ValueError.""" with pytest.raises(ValueError, match="Invalid mode"): kalign.align(TEST_SEQUENCES, mode="turbo") def test_explicit_param_overrides_mode(self): """Explicit consistency=10 overrides fast mode default (consistency=0).""" # This should not crash — fast base + explicit consistency result = kalign.align(TEST_SEQUENCES, mode="fast", consistency=10) assert isinstance(result, list) assert len(result) == len(TEST_SEQUENCES) def test_mode_case_insensitive(self): """Mode names are case-insensitive.""" result = kalign.align(TEST_SEQUENCES, mode="FAST") assert isinstance(result, list) assert len(result) == len(TEST_SEQUENCES) @pytest.mark.skipif(not os.path.exists(TEST_FILE), reason="Test data not found") class TestAlignFromFileModes: """Test mode parameter on align_from_file().""" def test_default_mode(self): result = kalign.align_from_file(TEST_FILE) names, sequences = result assert len(names) > 0 assert len(sequences) == len(names) def test_fast_mode(self): result = kalign.align_from_file(TEST_FILE, mode="fast") names, sequences = result assert len(names) > 0 def test_precise_mode(self): result = kalign.align_from_file(TEST_FILE, mode="precise") names, sequences = result assert len(names) > 0 @pytest.mark.skipif(not os.path.exists(TEST_FILE), reason="Test data not found") class TestAlignFileToFileModes: """Test mode parameter on align_file_to_file().""" def test_default_mode(self): with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as f: out = f.name try: kalign.align_file_to_file(TEST_FILE, out) assert os.path.getsize(out) > 0 finally: os.unlink(out) def test_fast_mode(self): with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as f: out = f.name try: kalign.align_file_to_file(TEST_FILE, out, mode="fast") assert os.path.getsize(out) > 0 finally: os.unlink(out) def test_precise_mode(self): with tempfile.NamedTemporaryFile(suffix=".fa", delete=False) as f: out = f.name try: kalign.align_file_to_file(TEST_FILE, out, mode="precise") assert os.path.getsize(out) > 0 finally: os.unlink(out) kalign-3.5.1/tests/python/test_parameters.py000066400000000000000000000030701515023132300212170ustar00rootroot00000000000000""" Parameter validation and behavior tests for Kalign Python package. """ import pytest import kalign class TestParameters: """Test parameter handling and validation.""" def test_default_parameters(self, dna_simple): """Test that default parameters work.""" aligned = kalign.align(dna_simple) assert len(aligned) == len(dna_simple) def test_custom_gap_penalties(self, dna_simple): """Test custom gap penalty parameters.""" aligned = kalign.align( dna_simple, seq_type="dna", gap_open=10.0, gap_extend=1.0, terminal_gap_extend=0.0, ) assert len(aligned) == len(dna_simple) def test_threading_parameters(self, dna_simple): """Test different thread counts.""" for n_threads in [1, 2, 4]: aligned = kalign.align(dna_simple, n_threads=n_threads) assert len(aligned) == len(dna_simple) def test_none_parameters_use_defaults(self, dna_simple): """Test that None parameters use Kalign defaults.""" aligned = kalign.align( dna_simple, gap_open=None, gap_extend=None, terminal_gap_extend=None ) assert len(aligned) == len(dna_simple) @pytest.mark.parametrize("gap_penalty", [0.0, 1.0, 5.0, 20.0]) def test_gap_penalty_range(self, dna_simple, gap_penalty): """Test various gap penalty values.""" aligned = kalign.align( dna_simple, gap_open=gap_penalty, gap_extend=gap_penalty / 2 ) assert len(aligned) == len(dna_simple) kalign-3.5.1/tests/python/test_performance.py000066400000000000000000000114551515023132300213630ustar00rootroot00000000000000""" Performance and benchmark tests for Kalign Python package. """ import pytest import time import kalign class TestPerformance: """Test performance characteristics and benchmarks.""" @pytest.mark.performance def test_basic_alignment_speed(self, dna_simple, benchmark): """Benchmark basic alignment speed.""" result = benchmark(kalign.align, dna_simple, seq_type="dna") assert len(result) == len(dna_simple) @pytest.mark.performance def test_threading_speedup(self, dna_with_gaps): """Test that multiple threads provide speedup.""" # Single thread start_time = time.time() aligned_single = kalign.align(dna_with_gaps, seq_type="dna", n_threads=1) single_time = time.time() - start_time # Multiple threads start_time = time.time() aligned_multi = kalign.align(dna_with_gaps, seq_type="dna", n_threads=2) multi_time = time.time() - start_time # Results should be identical assert aligned_single == aligned_multi # Just verify both completed successfully - timing comparisons are unreliable in CI print( f"Single-thread time: {single_time:.6f}s, Multi-thread time: {multi_time:.6f}s" ) @pytest.mark.performance @pytest.mark.slow def test_large_sequence_performance(self): """Test performance with larger sequences.""" large_seqs = ["ATCG" * 100] * 10 # 400bp sequences start_time = time.time() aligned = kalign.align(large_seqs, seq_type="dna") elapsed = time.time() - start_time assert len(aligned) == 10 assert elapsed < 10.0 # Should complete in reasonable time @pytest.mark.performance def test_memory_usage_reasonable(self, dna_simple): """Test that memory usage is reasonable.""" # This is a basic test - could be enhanced with memory profiling aligned = kalign.align(dna_simple * 10) # 30 sequences assert len(aligned) == 30 @pytest.mark.performance def test_dna_alignment_speed(self, dna_simple, benchmark): """Benchmark DNA alignment speed.""" result = benchmark.pedantic( kalign.align, args=[dna_simple], kwargs={"seq_type": "dna"}, rounds=3 ) assert len(result) == len(dna_simple) @pytest.mark.performance def test_protein_alignment_speed(self, protein_simple, benchmark): """Benchmark protein alignment speed.""" result = benchmark.pedantic( kalign.align, args=[protein_simple], kwargs={"seq_type": "protein"}, rounds=3, ) assert len(result) == len(protein_simple) @pytest.mark.performance @pytest.mark.parametrize("n_threads", [1, 2, 4, 8, 16]) def test_dna_threading_performance(self, n_threads, benchmark): """Test DNA alignment performance with different thread counts.""" # Generate a larger problem to really test threading sequences = kalign.generate_test_sequences( n_seq=200, # 200 sequences - much more demanding n_obs=30, # 30 observed sequences for HMM training dna=True, # DNA sequences length=1000, # 1000bp sequences - much longer seed=42, # Reproducible results ) result = benchmark.pedantic( kalign.align, args=[sequences], kwargs={"seq_type": "dna", "n_threads": n_threads}, rounds=1, # Reduced rounds due to longer runtime ) assert len(result) == len(sequences) # Verify alignment length consistency if result: expected_length = len(result[0]) for seq in result: assert len(seq) == expected_length @pytest.mark.performance @pytest.mark.parametrize("n_threads", [1, 2, 4, 8, 16]) def test_protein_threading_performance(self, n_threads, benchmark): """Test protein alignment performance with different thread counts.""" # Generate a larger problem to really test threading sequences = kalign.generate_test_sequences( n_seq=150, # 150 sequences - more demanding n_obs=25, # 25 observed sequences for HMM training dna=False, # Protein sequences length=320, # 320aa sequences - much longer seed=123, # Different seed for variety ) result = benchmark.pedantic( kalign.align, args=[sequences], kwargs={"seq_type": "protein", "n_threads": n_threads}, rounds=1, # Reduced rounds due to longer runtime ) assert len(result) == len(sequences) # Verify alignment length consistency if result: expected_length = len(result[0]) for seq in result: assert len(seq) == expected_length kalign-3.5.1/tests/python/test_sequence_types.py000066400000000000000000000065461515023132300221230ustar00rootroot00000000000000""" Sequence type specific tests for Kalign Python package. """ import pytest import kalign class TestSequenceTypes: """Test different sequence types and their handling.""" @pytest.mark.parametrize( "seq_type_str,seq_type_const", [ ("auto", kalign.AUTO), ("dna", kalign.DNA), ("internal", kalign.DNA_INTERNAL), ], ) def test_sequence_type_constants(self, seq_type_str, seq_type_const, dna_simple): """Test that string and constant sequence types give same results.""" aligned_str = kalign.align(dna_simple, seq_type=seq_type_str) aligned_const = kalign.align(dna_simple, seq_type=seq_type_const) assert aligned_str == aligned_const @pytest.mark.parametrize( "seq_type_str,seq_type_const", [ ("rna", kalign.RNA), ], ) def test_rna_sequence_type_constants( self, seq_type_str, seq_type_const, rna_simple ): """Test RNA type constants with RNA sequences.""" aligned_str = kalign.align(rna_simple, seq_type=seq_type_str) aligned_const = kalign.align(rna_simple, seq_type=seq_type_const) assert aligned_str == aligned_const @pytest.mark.parametrize( "seq_type_str,seq_type_const", [ ("protein", kalign.PROTEIN), ("divergent", kalign.PROTEIN_DIVERGENT), ], ) def test_protein_sequence_type_constants( self, seq_type_str, seq_type_const, protein_simple ): """Test protein type constants with protein sequences.""" aligned_str = kalign.align(protein_simple, seq_type=seq_type_str) aligned_const = kalign.align(protein_simple, seq_type=seq_type_const) assert aligned_str == aligned_const def test_dna_alignment(self, dna_simple): """Test DNA-specific alignment.""" aligned = kalign.align(dna_simple, seq_type="dna") assert len(aligned) == len(dna_simple) # Check that only valid DNA characters (including gaps) are present valid_chars = set("ATCG-") for seq in aligned: assert all(c.upper() in valid_chars for c in seq) def test_rna_alignment(self, rna_simple): """Test RNA-specific alignment.""" aligned = kalign.align(rna_simple, seq_type="rna") assert len(aligned) == len(rna_simple) # Check that RNA characters are preserved for orig, align in zip(rna_simple, aligned): degapped = align.replace("-", "") assert degapped == orig def test_protein_alignment(self, protein_simple): """Test protein-specific alignment.""" aligned = kalign.align(protein_simple, seq_type="protein") assert len(aligned) == len(protein_simple) # Check that amino acid characters are preserved for orig, align in zip(protein_simple, aligned): degapped = align.replace("-", "") assert degapped == orig def test_divergent_protein_type(self, protein_simple): """Test divergent protein sequence type.""" aligned = kalign.align(protein_simple, seq_type="divergent") assert len(aligned) == len(protein_simple) def test_internal_dna_type(self, dna_simple): """Test internal DNA sequence type.""" aligned = kalign.align(dna_simple, seq_type="internal") assert len(aligned) == len(dna_simple) kalign-3.5.1/tests/zig_test.c000066400000000000000000000007741515023132300161260ustar00rootroot00000000000000/* #include "tldevel.h" */ #include "stdio.h" #include "string.h" /* #include "tlrng.h" */ #include /* #include "strnlen_compat.h" */ int main(int argc, char *argv[]) { /* struct rng_state* rng = NULL; */ /* rng = init_rng(0); */ /* fprintf(stdout,"Kalign (%s)\n", KALIGN_PACKAGE_VERSION); */ /* fprintf(stdout,"HEllo random: %f\n", tl_random_double(rng)); */ int len = strnlen("FAFAF", 40); fprintf(stdout,"Len: %d\n",len); return 0; } kalign-3.5.1/uv.lock000066400000000000000000032441551515023132300143020ustar00rootroot00000000000000version = 1 revision = 3 requires-python = ">=3.9" resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", "python_full_version < '3.10'", ] [[package]] name = "alabaster" version = "0.7.16" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/c9/3e/13dd8e5ed9094e734ac430b5d0eb4f2bb001708a8b7856cbf8e084e001ba/alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65", size = 23776, upload-time = "2024-01-10T00:56:10.189Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/32/34/d4e1c02d3bee589efb5dfa17f88ea08bdb3e3eac12bc475462aec52ed223/alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92", size = 13511, upload-time = "2024-01-10T00:56:08.388Z" }, ] [[package]] name = "alabaster" version = "1.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, ] [[package]] name = "array-api-compat" version = "1.11.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/6c/1e/d04312a19a67744298b7546885149488b8afbb965dfe693aa4964bb60586/array_api_compat-1.11.2.tar.gz", hash = "sha256:a3b7f7b6af18f4c42e79423b1b2479798998b6a74355069d77a01a5282755b5d", size = 50776, upload-time = "2025-03-20T13:11:55.095Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9f/d8/3388c7da49f522e51ab2f919797db28782216cadc9ecc9976160302cfcd6/array_api_compat-1.11.2-py3-none-any.whl", hash = "sha256:b1d0059714a4153b3ae37c989e47b07418f727be5b22908dd3cf9d19bdc2c547", size = 53149, upload-time = "2025-03-20T13:11:53.815Z" }, ] [[package]] name = "array-api-compat" version = "1.13.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/68/36/f799b36d7025a92a23819f9f06541babdb84b6fd0bd4253f8be2eca348a4/array_api_compat-1.13.0.tar.gz", hash = "sha256:8b83a56aa8b9477472fee37f7731968dd213e20c198a05ac49caeff9b03f48a6", size = 103065, upload-time = "2025-12-28T11:26:57.734Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/df/5d/493b1b5528ab5072feae30821ff3a07b7a0474213d548efb1fdf135f85c1/array_api_compat-1.13.0-py3-none-any.whl", hash = "sha256:c15026a0ddec42815383f07da285472e1b1ff2e632eb7afbcfe9b08fcbad9bf1", size = 58585, upload-time = "2025-12-28T11:26:56.081Z" }, ] [[package]] name = "babel" version = "2.18.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, ] [[package]] name = "backports-tarfile" version = "1.2.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" }, ] [[package]] name = "biom-format" version = "2.1.17" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "h5py", version = "3.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "h5py", version = "3.15.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "pandas", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "scipy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "scipy", version = "1.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cf/63/da18b1cdb9de07f8ad07d71535eac0460d065c71312ad400f55f6c2865ae/biom_format-2.1.17.tar.gz", hash = "sha256:8e3fa07a432b3f6d5c3cad491ef1f27b18d10fc151ca2d223761be4f0b050479", size = 11721758, upload-time = "2025-08-26T15:19:19.35Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/51/93/663ba9aba08fdbca7a6a4231f89305dfc6e8534b8551fbd2060222bdf995/biom_format-2.1.17-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3ed04cc11abfd257e84fff693720a6ec1bc092dcb67094eea78bf9ff8ef4645", size = 11875588, upload-time = "2025-08-26T15:18:27.78Z" }, { url = "https://files.pythonhosted.org/packages/d9/fe/00070214677a1ba6ae6952be17c553c0a9efbb7ead7783db47d52ca05560/biom_format-2.1.17-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c04fd6485098a37fd26766fe7d260086eca9f1ccaab1f1ca2e1e52a11f72c1ac", size = 11873656, upload-time = "2025-08-26T15:18:30.107Z" }, { url = "https://files.pythonhosted.org/packages/79/a1/ebdc161b7798ec751a5ee34395aac49f6e971fc1002ac909a94f259ec35a/biom_format-2.1.17-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d882183957798acd9f8ca4fc99a5e0993c2ceaca0765c6148d7e57c7214f67f5", size = 12265786, upload-time = "2025-08-26T15:18:31.918Z" }, { url = "https://files.pythonhosted.org/packages/23/ff/92012af5e35d92ec34c4170331b772ee9bd04b8ec5d133e922d0b31f3be1/biom_format-2.1.17-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36098987ab5338e28fa6267206e222ce8f9e0dd12185dd203b50553b122c4f9f", size = 12268464, upload-time = "2025-08-26T15:18:33.718Z" }, { url = "https://files.pythonhosted.org/packages/20/5f/c66e15b4e405c6eef2265fd1afa31ab5bdf6f6edf267f0a6efa8fc392c1f/biom_format-2.1.17-cp310-cp310-win_amd64.whl", hash = "sha256:b79cf2b47f5f11b1edb134d905838b392af909fd22b7db9863fdc90da0e5535a", size = 11878451, upload-time = "2025-08-26T15:18:35.696Z" }, { url = "https://files.pythonhosted.org/packages/62/7c/c651602791af584a8f3951a61b5ee1b8a109d7de82c4fe555b401f521cd1/biom_format-2.1.17-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8763ea43b39d9b6721607a1d47a54fd12f424a67c4a26b9e763d370150ef964", size = 11875504, upload-time = "2025-08-26T15:18:37.47Z" }, { url = "https://files.pythonhosted.org/packages/8c/92/805ab970b67058f27047c612fa355cf685990e0c577b94a00447347ac433/biom_format-2.1.17-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84c65cb172efc90f7aa77269e23c9034d0de2f49ee094bcb8bdfbad459582fa6", size = 11873629, upload-time = "2025-08-26T15:18:39.829Z" }, { url = "https://files.pythonhosted.org/packages/a0/e9/566455f6e4c6202aae0c97d1fc51483949944e45d4dd5134bd071966cd7e/biom_format-2.1.17-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:270582123050a0114887e3c2565374726d17dc1bc5ae5574f11e2f1b55e50c38", size = 12289428, upload-time = "2025-08-26T15:18:42.118Z" }, { url = "https://files.pythonhosted.org/packages/cc/a3/45d7440f198afdc840154d4eddeafa0af35673a9995b1ef273d0cd908a07/biom_format-2.1.17-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06de7333dc371602c73d33011149a3ee5a8a9a2a628efbbbd6eab22903edf6d7", size = 12291218, upload-time = "2025-08-26T15:18:44.681Z" }, { url = "https://files.pythonhosted.org/packages/a9/78/d12960be5f80d2b8777a295d58c66b25f66e4ba28e92916167999001b5ef/biom_format-2.1.17-cp311-cp311-win_amd64.whl", hash = "sha256:7ac8acf2d9f1df370d50b688ca098d9a82790568eda50fa5aaa6ba787b0c4c06", size = 11878781, upload-time = "2025-08-26T15:18:46.959Z" }, { url = "https://files.pythonhosted.org/packages/e4/6b/3dfb3fe094d048115746289953c88086884c7dede917daa9de72e655a56c/biom_format-2.1.17-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a87f182f6cfa48d2d0cd39911834e89ec84e4f7a96fc01b4cb016a6124f6437a", size = 11875690, upload-time = "2025-08-26T15:18:48.877Z" }, { url = "https://files.pythonhosted.org/packages/a3/ee/2b7b210ded6e1967fa4050278fe20a405a0cd33d1831c934276173c59386/biom_format-2.1.17-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be2b62738a816cf99f3a9d69c5b4ca28882d5383d82a060bd04bb08bce661a60", size = 11874386, upload-time = "2025-08-26T15:18:50.821Z" }, { url = "https://files.pythonhosted.org/packages/c2/98/f51ce183bd3d3c2c38749d64df816b207c5e9f464c53cb5cf77e56874dfc/biom_format-2.1.17-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a571d8bc051147a7402229ea0c55942adbd2539f257beb4b7b2230a18efd977", size = 12311295, upload-time = "2025-08-26T15:18:53.065Z" }, { url = "https://files.pythonhosted.org/packages/03/5e/dc0bc86ddd030bc575305b0d6ee55c16e264588b273729a80215c7920f3c/biom_format-2.1.17-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:601a012503363cfa8d011d51f5d90a93dcca8feaa01cce38eacd5c26005bc3a0", size = 12318435, upload-time = "2025-08-26T15:18:54.899Z" }, { url = "https://files.pythonhosted.org/packages/92/86/5f3c19d24bf9061eaf1b53614cca20de379ee963d7f20a274f0a64192978/biom_format-2.1.17-cp312-cp312-win_amd64.whl", hash = "sha256:6b4b9c3d27ff7129d83293ee8cf26bfad2757438d21d147ae26f412ca7002dc5", size = 11879250, upload-time = "2025-08-26T15:18:57.171Z" }, { url = "https://files.pythonhosted.org/packages/28/8b/1529bd9a804b7a9ea331acebb3afb55f8692543aa5feb7bfd682ba7fc92a/biom_format-2.1.17-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8de0eb6e61557f2ea2e174a6040bee62065dd62f7e7bb754be07bcd8dd8d4cfd", size = 11874427, upload-time = "2025-08-26T15:18:59.714Z" }, { url = "https://files.pythonhosted.org/packages/de/62/1b337636d5a88816df2fc60e3733c1f7790cc131c6e58f69e7c96c6a69d6/biom_format-2.1.17-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5917af9bd459b645e835ee2b9392da3fcbccbdde05a76ccd639a86f2d299cfa0", size = 11873338, upload-time = "2025-08-26T15:19:02.01Z" }, { url = "https://files.pythonhosted.org/packages/18/ab/90a5c2d51fc3e43f5634de070c002be4b34255e00ab9d7fc33eda48ef48a/biom_format-2.1.17-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e7061fd7f68a85b3b14f03696dac0fd9c18dc93821d367da1c50db39e3220d6", size = 12291356, upload-time = "2025-08-26T15:19:03.949Z" }, { url = "https://files.pythonhosted.org/packages/7c/71/f7167a0926994a4fd4740befcf379ded751efe7b53c8b790fd581df0c1a2/biom_format-2.1.17-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d17ff0d09c2d58d111756b7fcf05f6709ccc9db511b534d1a636bda58caa39ed", size = 12296610, upload-time = "2025-08-26T15:19:05.797Z" }, { url = "https://files.pythonhosted.org/packages/6b/06/dbc9e5ee8a413b07cddde794a34ae57b3edd7469934d77fe79c05abf446e/biom_format-2.1.17-cp313-cp313-win_amd64.whl", hash = "sha256:e70c4939545ca65ed0a665ee4b33ded6c1ffa933a9ed1a01990496179f0a29cd", size = 11878888, upload-time = "2025-08-26T15:19:07.523Z" }, { url = "https://files.pythonhosted.org/packages/39/8a/fe6e95757fb736e8145bedd33c312b8557e72f47ca471ab0323007c12dec/biom_format-2.1.17-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fbf60d88248402b3593f19e8e296bf9888ae9e3933aabbdaacee3ad4f5f1a516", size = 11875563, upload-time = "2025-08-26T15:19:09.436Z" }, { url = "https://files.pythonhosted.org/packages/1f/8d/29b43cc22a4ec31d0ca56af33c22366137d33ce8ba1212bb01f3ced0cd2e/biom_format-2.1.17-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f4dfb1e4b27dfd09b63c9adbb5e84b8507c38b596c9fa6db11301d9c081e1c95", size = 11873697, upload-time = "2025-08-26T15:19:11.747Z" }, { url = "https://files.pythonhosted.org/packages/ff/25/eea9d1f0227c3c5725a6de34e8d5510e3f0bdc3b2407921268e4c0849f3b/biom_format-2.1.17-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d6d6a41ecba94f2fd9f63257856eaf05eb29baa768194089ecbda8347410b34", size = 12263554, upload-time = "2025-08-26T15:19:13.676Z" }, { url = "https://files.pythonhosted.org/packages/97/0d/10eb061ea10a9c43e8be99c4b0cd00db26c3dcc9cb25ada4b78d4c998c94/biom_format-2.1.17-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05cf52851552f0ae6918e885b8f123414d9421579cad9396f3cf6adbccf2d043", size = 12265957, upload-time = "2025-08-26T15:19:15.638Z" }, { url = "https://files.pythonhosted.org/packages/0f/e3/be8d4d7e6128993c024d5d794aa912cffe251f53021daa3e938554ecffc7/biom_format-2.1.17-cp39-cp39-win_amd64.whl", hash = "sha256:5f1f0cadea17646817b41ae5ef87ea0fdf4de7b260f085f73e6a4531680e7044", size = 11878504, upload-time = "2025-08-26T15:19:17.455Z" }, ] [[package]] name = "biopython" version = "1.85" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/db/ca/1d5fab0fedaf5c2f376d9746d447cdce04241c433602c3861693361ce54c/biopython-1.85.tar.gz", hash = "sha256:5dafab74059de4e78f49f6b5684eddae6e7ce46f09cfa059c1d1339e8b1ea0a6", size = 19909902, upload-time = "2025-01-15T15:06:51.997Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/79/de/79824470fdc5c2aedeb1bab637d24eab654a7e9fbb7070f779fd944fd1ca/biopython-1.85-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a6308053a61f3bdbb11504ece4cf24e264c6f1d6fad278f7e59e6b84b0d9a7b4", size = 2787511, upload-time = "2025-01-15T15:11:56.656Z" }, { url = "https://files.pythonhosted.org/packages/4b/d6/3c90df2ebc4f2a522235f4391392253e528f19f5fb6a52396a2316e17064/biopython-1.85-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:434dd23e972b0c89e128f2ebbd16b38075d609184f4f1fd16368035f923019c2", size = 2765456, upload-time = "2025-01-15T15:12:05.177Z" }, { url = "https://files.pythonhosted.org/packages/ff/d7/34233c4ee906b088b199eb2af9c4107384a547d44b5960257ef2bf2cc3c8/biopython-1.85-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a08d082e85778259a83501063871e00ba57336136403b75050eea14d523c00a", size = 3225137, upload-time = "2025-01-15T15:12:15.847Z" }, { url = "https://files.pythonhosted.org/packages/ae/6b/e7a5ae49ef7e8f81720593db22e884c1c8e3504e0e235da0395758a5c7d0/biopython-1.85-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93464e629950e4df87d810125dc4e904538a4344b924f340908ea5bc95db986", size = 3245258, upload-time = "2025-01-15T15:12:21.012Z" }, { url = "https://files.pythonhosted.org/packages/68/2c/0035656dbe51ac0bbe81321172b43c37b38408f8d136abaac443e9f44b62/biopython-1.85-cp310-cp310-win32.whl", hash = "sha256:f2f45ab3f1e43fdaa697fd753148999090298623278097c19c2c3c0ba134e57c", size = 2786505, upload-time = "2025-01-15T15:12:26.545Z" }, { url = "https://files.pythonhosted.org/packages/32/a4/f20d5830dbd8654c13e763daef429fa32ef0b2b09749ac427d045cc81976/biopython-1.85-cp310-cp310-win_amd64.whl", hash = "sha256:7c8326cd2825ba166abecaf72843b9b15823affd6cec04fde65f0d2526767da4", size = 2820961, upload-time = "2025-01-15T15:12:32.364Z" }, { url = "https://files.pythonhosted.org/packages/c3/73/c3a1323a3fe0d07212b09c04fb903e2cbb98aebfbb58e55e8717473e1bc0/biopython-1.85-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:db8822adab0cd75a6e6ae845acf312addd8eab5f9b731c191454b961fc2c2cdc", size = 2787585, upload-time = "2025-01-15T15:12:36.927Z" }, { url = "https://files.pythonhosted.org/packages/ff/cf/299524e896fa49beb7588143e1509cce4848572215ebafb8eea83a861820/biopython-1.85-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e2bbe58cc1a592b239ef6d68396745d3fbfaafc668ce38283871d8ff070dbab", size = 2765608, upload-time = "2025-01-15T15:12:43.853Z" }, { url = "https://files.pythonhosted.org/packages/b1/dd/be3e95b72a35ee6d52c84412e15af828951e5c69175080d4619985fd54ce/biopython-1.85-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5916eb56df7ecd4a3babc07a48d4894c40cfb45dc18ccda1c148d0131017ce04", size = 3237552, upload-time = "2025-01-15T15:12:49.046Z" }, { url = "https://files.pythonhosted.org/packages/25/9c/612821b946930b6caa5d795cfe4169ed6a522562eced9776914be7efaf21/biopython-1.85-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0cec8833bf3036049129944ee5382dd576dac9670c3814ff2314b52aa94f199", size = 3257287, upload-time = "2025-01-15T15:12:56.168Z" }, { url = "https://files.pythonhosted.org/packages/a1/77/316e51dd42fd8225429574a268bdc627ce4f42067a3976c4c8c457a42023/biopython-1.85-cp311-cp311-win32.whl", hash = "sha256:cf88a4c8d8af13138be115949639a5e4a201618185a72ff09adbe175b7946b28", size = 2786411, upload-time = "2025-01-15T15:13:02.754Z" }, { url = "https://files.pythonhosted.org/packages/f2/11/3c4e8c049b91998bbbd51ddebc6f790b1aa66211babfbf5ff008a72fb1f9/biopython-1.85-cp311-cp311-win_amd64.whl", hash = "sha256:d3c99db65d57ae4fc5034e42ac6cd8ddce069e664903f04c8a4f684d7609d6fa", size = 2820912, upload-time = "2025-01-15T15:13:10.499Z" }, { url = "https://files.pythonhosted.org/packages/a3/25/e46f05359df7f0049c3adc5eaeb9aee0f5fbde1d959d05c78eb1de8f4d12/biopython-1.85-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc5b981b9e3060db7c355b6145dfe3ce0b6572e1601b31211f6d742b10543874", size = 2789327, upload-time = "2025-01-15T15:13:17.086Z" }, { url = "https://files.pythonhosted.org/packages/54/5b/8b3b029c94c63ab4c1781d141615b4a837e658422381d460c5573d5d8262/biopython-1.85-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6fe47d704c2d3afac99aeb461219ec5f00273120d2d99835dc0a9a617f520141", size = 2765805, upload-time = "2025-01-15T15:13:26.92Z" }, { url = "https://files.pythonhosted.org/packages/69/0a/9a8a38eff03c4607b9cec8d0e08c76b346b1cee1f77bc6d00efebfc7ec83/biopython-1.85-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54e495239e623660ad367498c2f7a1a294b1997ba603f2ceafb36fd18f0eba6", size = 3249276, upload-time = "2025-01-15T15:13:36.639Z" }, { url = "https://files.pythonhosted.org/packages/b4/0d/b7a0f10f5100dcf51ae36ba31490169bfa45617323bd82af43e1fb0098fb/biopython-1.85-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d024ad48997ad53d53a77da24b072aaba8a550bd816af8f2e7e606a9918a3b43", size = 3268869, upload-time = "2025-01-15T15:13:44.009Z" }, { url = "https://files.pythonhosted.org/packages/07/51/646a4b7bdb4c1153786a70d33588ed09178bfcdda0542dfdc976294f4312/biopython-1.85-cp312-cp312-win32.whl", hash = "sha256:6985e17a2911defcbd30275a12f5ed5de2765e4bc91a60439740d572fdbfdf43", size = 2787011, upload-time = "2025-01-15T15:13:48.958Z" }, { url = "https://files.pythonhosted.org/packages/c1/84/c583fa2ac6e7d392d24ebdc5c99e95e517507de22cf143efb6cf1fc93ff5/biopython-1.85-cp312-cp312-win_amd64.whl", hash = "sha256:d6f8efb2db03f2ec115c5e8c764dbadf635e0c9ecd4c0e91fc8216c1b62f85f5", size = 2820972, upload-time = "2025-01-15T15:13:54.475Z" }, { url = "https://files.pythonhosted.org/packages/c3/3f/65814bf221f0bfdd2633830e573ac8594794686f54110571dce98cc32fd3/biopython-1.85-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bae6f17262f20e9587d419ba5683e9dc93a31ee1858b98fa0cff203694d5b786", size = 2789844, upload-time = "2025-01-15T15:14:01.171Z" }, { url = "https://files.pythonhosted.org/packages/be/61/1443ce34226e261c20ae4a154b2bab72c109cf31415c92c54c1aada36b00/biopython-1.85-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b1e4918e6399ab0183dd863527fec18b53b7c61b6f0ef95db84b4adfa430ce75", size = 2765767, upload-time = "2025-01-15T15:14:07.096Z" }, { url = "https://files.pythonhosted.org/packages/53/51/bec4c763c704e2715691bb087cfab5907804a1bbef5873588698cece1a30/biopython-1.85-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86e487b6fe0f20a2b0138cb53f3d4dc26a7e4060ac4cb6fb1d19e194d445ef46", size = 3248867, upload-time = "2025-01-15T15:14:12.822Z" }, { url = "https://files.pythonhosted.org/packages/9e/a4/552f20253a7c95988067c4955831bd17dd9b864fd5c215d15c2f63f2d415/biopython-1.85-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:327184048b5a50634ae0970119bcb8a35b76d7cefb2658a01f772915f2fb7686", size = 3268479, upload-time = "2025-01-15T15:14:20.414Z" }, { url = "https://files.pythonhosted.org/packages/97/f4/6dfc6ef3e0997f792f93893551d4a9bf7f6052a70d34f4e1b1e5e4a359f6/biopython-1.85-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66b08905fb1b3f5194f908aaf04bbad474c4e3eaebad6d9f889a04e64dd1faf4", size = 3192338, upload-time = "2025-01-15T15:14:26.843Z" }, { url = "https://files.pythonhosted.org/packages/9d/8c/73da6588fab3a7d734118f21ac619c0a949f51d3cf7b1b8343d175c33460/biopython-1.85-cp313-cp313-win32.whl", hash = "sha256:5a236ab1e2797c7dcf1577d80fdaafabead2908bc338eaed0aa1509dab769fef", size = 2787017, upload-time = "2025-01-15T15:14:33.802Z" }, { url = "https://files.pythonhosted.org/packages/60/ff/fe8f03ac0ccc7219e0959010750c6ac1a5b1411c91c7f4ec3a37d8313673/biopython-1.85-cp313-cp313-win_amd64.whl", hash = "sha256:1b61593765e9ebdb71d73307d55fd4b46eb976608d329ae6803c084d90ed34c7", size = 2821012, upload-time = "2025-01-15T15:14:40.825Z" }, { url = "https://files.pythonhosted.org/packages/b3/04/9bdf0003913803d3d2239785f0f53875694dd441bd5e1a8c1581cab37747/biopython-1.85-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d76e44b46f555da2e72ac36e757efd327f7f5f690e9f00ede6f723b48538b6d5", size = 2787519, upload-time = "2025-01-15T15:14:45.867Z" }, { url = "https://files.pythonhosted.org/packages/a4/9b/bef7dd17980eb4625c3c69411d3273e9b45d83dc7e2f1c63719607fa1026/biopython-1.85-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8469095907a17f156c76b6644829227efdf4996164f7726e6f4ca15039329776", size = 2765442, upload-time = "2025-01-15T15:14:51.469Z" }, { url = "https://files.pythonhosted.org/packages/94/49/20f55dcfcc5487d84a6a4c84b59bcfb7ae2610f7370847b07e63e0f79cc6/biopython-1.85-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cffc15ac46688cd4cf662b24d03037234ce00b571df67be45a942264f101f990", size = 3223396, upload-time = "2025-01-15T15:14:56.519Z" }, { url = "https://files.pythonhosted.org/packages/80/5a/6ba0066b7f38b9e7a085f2fc4c171a25ebfa64202aab0965961621f561e1/biopython-1.85-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a630b3804f6c3fcae2f9b7485d7a05425e143fc570f25babbc5a4b3d3db00d7", size = 3243475, upload-time = "2025-01-15T15:15:01.798Z" }, { url = "https://files.pythonhosted.org/packages/90/1d/a38a9a61abd4a917fb9b95698971914d722e75027885bdb957b0fe757cd5/biopython-1.85-cp39-cp39-win32.whl", hash = "sha256:0ffb03cd982cb3a79326b84e789f2093880175c44eea10f3030c632f98de24f6", size = 2786482, upload-time = "2025-01-15T15:15:06.532Z" }, { url = "https://files.pythonhosted.org/packages/4a/46/9cb732167a3ce4fd40920d1bec444d1739aaf18b58190f2fab8692fcaba5/biopython-1.85-cp39-cp39-win_amd64.whl", hash = "sha256:8208bf2d87ade066fafe9a63a2eb77486c233bc1bdda2cbf721ebee54715f1bf", size = 2820941, upload-time = "2025-01-15T15:15:12.311Z" }, ] [[package]] name = "biopython" version = "1.86" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9d/61/c59a849bd457c8a1b408ae828dbcc15e674962b5a29705e869e15b32bf25/biopython-1.86.tar.gz", hash = "sha256:93a50b586a4d2cec68ab2f99d03ef583c5761d8fba5535cb8e81da781d0d92ff", size = 19835323, upload-time = "2025-10-28T21:18:31.041Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/03/9f/5c95732ad98a6d40f4be58978be801cc87b50c71d79a7aee46c4a085114d/biopython-1.86-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:02aef2e31cc92544f574ff837cabaaaf53733f3a6b5a433f781c59e5424a7576", size = 2691935, upload-time = "2025-10-28T21:27:12.558Z" }, { url = "https://files.pythonhosted.org/packages/ca/15/9902cbc901073ba2de397f5c9c84e72147e02aaca1755fa650d26bb715a2/biopython-1.86-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e1b12819a78242b529f54e5d2d00ad90023710a5846ca0f2011ac989fd17d4b", size = 2669420, upload-time = "2025-10-28T21:26:40.048Z" }, { url = "https://files.pythonhosted.org/packages/9d/5d/9cb775106361f8ef7ab459b89ff6d725e81dae7abd382309d3bbf82ced6d/biopython-1.86-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e62504faac6e62fe26e40d6905a69519d8b7b5b0506a426d641b218fde788b5", size = 3183554, upload-time = "2025-10-29T00:35:24.074Z" }, { url = "https://files.pythonhosted.org/packages/08/47/87c8db55746099b38baf6c597688807bad2e59074cec37169168fe98e69e/biopython-1.86-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8d4530060aadc6af060a9a049da91a582738837e187fcea80486c71eca74ae59", size = 3205260, upload-time = "2025-10-29T00:35:33.89Z" }, { url = "https://files.pythonhosted.org/packages/88/6c/7822f6b7521073ccc80eb18736b664efe1d59edeb6a3f72c362f542ec352/biopython-1.86-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:186e2065c0d1a6c2afc85b9c21a2911a931949668bd73b4c03f429a31b3589f8", size = 3154783, upload-time = "2025-10-28T23:52:52.157Z" }, { url = "https://files.pythonhosted.org/packages/98/7a/6759f99b481432969a4979f03b4c4966716d4cffd2154749ae5af0d8904a/biopython-1.86-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6915a09859159598b9421e7240561692e7bb4084e5340c4dbb2435c5c38805a2", size = 3173920, upload-time = "2025-10-28T23:52:57.611Z" }, { url = "https://files.pythonhosted.org/packages/17/c2/fe2a223b3fdd718099055679b68f9f15b2006d83a5a1c1593246d5e5fe81/biopython-1.86-cp310-cp310-win32.whl", hash = "sha256:be3d83152fe3232e2d197896a506902b84ad60d40b3f1d1fc934914d138c6dc1", size = 2697949, upload-time = "2025-10-28T21:32:07.305Z" }, { url = "https://files.pythonhosted.org/packages/1f/11/44fb3975df1070966ffc213f52e9fff63fb48b43bc3d403584ca3f4f9a42/biopython-1.86-cp310-cp310-win_amd64.whl", hash = "sha256:6fbbfe19e12170754adb9632155b7e3be0d4c247f0a2e09d3917bec859282de1", size = 2734235, upload-time = "2025-10-28T21:32:03.014Z" }, { url = "https://files.pythonhosted.org/packages/c3/f5/37d6bb3a1245ec5f5f1c66d5cd790b06cdb54a75b36849893405c17f3612/biopython-1.86-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba88b0754ad53c93eba11d910364cfc773686933c89a886522309ba903151e50", size = 2691944, upload-time = "2025-10-28T21:27:24.053Z" }, { url = "https://files.pythonhosted.org/packages/14/12/44d71f333b7302b30788df80705f2207c47b54c17d0935a378dfc709507d/biopython-1.86-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6cceb32b9036bbdc59962e31bd1605ece24edc226c0d50f99839948b5b5c9dda", size = 2669434, upload-time = "2025-10-28T21:26:49.145Z" }, { url = "https://files.pythonhosted.org/packages/a5/1b/731060090ed29b5ac2484865255f1f363a50afb7275717ceb2c6f20d3ea4/biopython-1.86-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f0f040ff85bd7d0ee06574bc6d032bc666802f2fe781b0c316b936237eb3d17e", size = 3196718, upload-time = "2025-10-29T00:35:47.806Z" }, { url = "https://files.pythonhosted.org/packages/1c/8d/8409535c341061b9c78faf151e73b484b456b3c3bdf59b27cf3984f16fbc/biopython-1.86-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ac858fd71f1093380d8b0a16acf060e7c228ad65f9ecacdb9f5760cfb9f59b1", size = 3218383, upload-time = "2025-10-29T00:35:53.523Z" }, { url = "https://files.pythonhosted.org/packages/f4/bc/5e93a11f70732122679747a728509d03a6a066b178cc1d7ca30ed2f1ebee/biopython-1.86-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da4bcf5a48ee647624e2d0bedac7fb1c24ef0facd514519cca074593b8a6a40e", size = 3168368, upload-time = "2025-10-28T23:53:16.425Z" }, { url = "https://files.pythonhosted.org/packages/b2/c6/e187940571a3a24d20f407f1d7514ab1fe0dc9fa49e01790c4bd56ced0bc/biopython-1.86-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d4dd9090caaf364a08ab54cd561f37c5f4ea5bcc8f0189d332dcd36d6df5767", size = 3186451, upload-time = "2025-10-28T23:53:22.463Z" }, { url = "https://files.pythonhosted.org/packages/2a/88/1e8ffb0db6a03888768613d682a79043e9975067b9095e644a6872905c88/biopython-1.86-cp311-cp311-win32.whl", hash = "sha256:90591f4554c09d311193e7774b5143442c67e178a5b7d929aaa2a054048b22a7", size = 2697756, upload-time = "2025-10-28T21:32:23.017Z" }, { url = "https://files.pythonhosted.org/packages/f0/b2/e34e45d6cb46c96486a2ed5f07874b6c9493dec68b9d6262ae05f4fe909b/biopython-1.86-cp311-cp311-win_amd64.whl", hash = "sha256:0a95321ca929c04c934e62252c9e2cc5c4fd13ce575798d98af2d79512334b9b", size = 2733781, upload-time = "2025-10-28T21:32:18.409Z" }, { url = "https://files.pythonhosted.org/packages/98/e2/199b8ccbd4b9bf234157db0668177b5b7784d62f29d9096fd0d3a70e3b86/biopython-1.86-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f8d372aae21d79b11613751c6ae23c88db0e94d25b7567b1f67aa0304fb61667", size = 2693171, upload-time = "2025-10-29T00:26:59.028Z" }, { url = "https://files.pythonhosted.org/packages/d8/2f/1a7da2a55212b3d0a03866d22213f91273fee3722b5364575419fbe574a5/biopython-1.86-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:baf19d9237aaaa387a68f8f055f978af5c80338d7e037ab028e8d768928f1250", size = 2692543, upload-time = "2025-10-28T21:27:31.855Z" }, { url = "https://files.pythonhosted.org/packages/5b/e9/4057d4c2aa22ca25c180ecbed2ce9e7d65bf787999778bc63b41df0d03b5/biopython-1.86-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:04f9abdf6cbf0087850de5f8148da0d420c4cb87905bf4de3145ad24a8d55dcd", size = 2669975, upload-time = "2025-10-28T21:26:54.181Z" }, { url = "https://files.pythonhosted.org/packages/a7/b2/3e6862720d7c51f0fbe7d6d25be72a95486779d9d98122283b4e8032fb40/biopython-1.86-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:187c3c24dd2255e7328f3e0523ab5d6350b73ff562517de0c1922385617101d2", size = 3209367, upload-time = "2025-10-29T00:36:06.522Z" }, { url = "https://files.pythonhosted.org/packages/d7/cb/61877367bf08670573d62513b239dc65cf2b7488dc74322cc6051da2e55e/biopython-1.86-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1859830b8262785c6b59dfe0c82cddb643974f63b9d2779bb9f3e2c47c0a95da", size = 3235466, upload-time = "2025-10-29T00:36:11.516Z" }, { url = "https://files.pythonhosted.org/packages/84/1a/3182a77776b76f3f5c64825ee1acf9355f665bed72ee9e8ff49e48f25d98/biopython-1.86-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfd906c47b6fb38e3abb9f52e0c06822e6e82a043d38c2000773692c29db1ed8", size = 3178776, upload-time = "2025-10-28T23:53:41.487Z" }, { url = "https://files.pythonhosted.org/packages/1a/22/828b08fac8dbc8c1dbc1ad03815137cebc9c78303ec7d21b568544028119/biopython-1.86-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a6ab2c60742f1c8494cfbbe3b7a8b45f0400c8f2b36b686b895d5e4d625f04e", size = 3197586, upload-time = "2025-10-28T23:53:47.136Z" }, { url = "https://files.pythonhosted.org/packages/36/7a/122aea7653fa93d7eb72978928e80759082efffa70afe0c25a17e18521da/biopython-1.86-cp312-cp312-win32.whl", hash = "sha256:192c61bc3d782c171b7d50bb7d8189d84790d6e3c4b24fd41d1d7ffc7d303efe", size = 2698043, upload-time = "2025-10-28T21:32:39.452Z" }, { url = "https://files.pythonhosted.org/packages/a9/13/00db03b01e54070d5b0ec9c71eef86e61afa733d9af76e5b9b09f5dc9165/biopython-1.86-cp312-cp312-win_amd64.whl", hash = "sha256:35a6b9c5dcdfb5c2631a313a007f3f41a7d72573ba2b68c962e10ea92096ff3b", size = 2733610, upload-time = "2025-10-28T21:32:34.99Z" }, { url = "https://files.pythonhosted.org/packages/fd/6e/84d6c66ab93095aa7adb998a8eef045328470eafd36b9237c4db213e587c/biopython-1.86-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fb3a11a98e49428720dca227e2a5bdd57c973ee7c4df3cf6734c0aa13fd134c7", size = 2693185, upload-time = "2025-10-28T21:27:39.709Z" }, { url = "https://files.pythonhosted.org/packages/12/75/60386f2640f13765b1651f2f26d8b4f893c46ee663df3ca76eda966d4f6a/biopython-1.86-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e161f3d3b6e65fbfd1ce22a01c3e9fa9da789adde4972fd0cc2370795ea5357b", size = 2669980, upload-time = "2025-10-28T21:26:58.839Z" }, { url = "https://files.pythonhosted.org/packages/dd/de/a39adb98a0552a257219503c236ef17f007598af55326c0d143db52e5a92/biopython-1.86-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5aa8c9e92ee6fe59dfe0d2c2daf9a9eec6b812c78328caad038f79163c500218", size = 3209657, upload-time = "2025-10-29T00:36:28.842Z" }, { url = "https://files.pythonhosted.org/packages/0b/c7/b2e7aca3de8981f4ecb6ab1e0334c3c4a512e5e9898b57b3d8734b086da7/biopython-1.86-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:593ec6a2a4fedec08ddcee1a8a0e0b0ed56835b2714904b352ec4a93d5b9d973", size = 3235774, upload-time = "2025-10-29T00:36:34.07Z" }, { url = "https://files.pythonhosted.org/packages/52/ed/e6647b0b9cf2bb67347612e8e443b84378c44768a8d8439276e4ba881178/biopython-1.86-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd2f9ebf9b14d67ca92f48779c4f0ba404c35dba3e8b9d6c34d1a3591c3b746d", size = 3178415, upload-time = "2025-10-28T23:54:05.475Z" }, { url = "https://files.pythonhosted.org/packages/ff/37/f6a14b835842c66a52f212136a99416265f5ce76813d668ceac1cb306357/biopython-1.86-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:137fe9aafd93baa5127d17534b473f6646f92a883f52b34f7c306b800ac50038", size = 3197201, upload-time = "2025-10-28T23:54:10.462Z" }, { url = "https://files.pythonhosted.org/packages/f2/73/0eac930016c509763c174a0e25e92e6d7a711f6f5de1f7001e54fd5c49f7/biopython-1.86-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e784dc8382430c9893aa084ca18fe8a8815b5811f1c324492ef3f4b54e664fff", size = 3145106, upload-time = "2025-10-28T23:54:15.235Z" }, { url = "https://files.pythonhosted.org/packages/00/aa/26e836274d03402e8011b04a1714d4ac2f704add303a493e54d2d5646973/biopython-1.86-cp313-cp313-win32.whl", hash = "sha256:5329a777ba90ea624447173046e77c4df2862acc46eea4e94fe2211fe041750f", size = 2698051, upload-time = "2025-10-28T21:32:55.225Z" }, { url = "https://files.pythonhosted.org/packages/ae/27/fa1f8fa57f2ac8fdc41d14ab36001b8ba0fce5eac01585227b99a4da0e9d/biopython-1.86-cp313-cp313-win_amd64.whl", hash = "sha256:f6f2f1dc75423b15d8a22b8eceae32785736612b6740688526401b8c2d821270", size = 2733649, upload-time = "2025-10-28T21:32:51.052Z" }, { url = "https://files.pythonhosted.org/packages/a4/2d/5b87ab859d38f2c7d7d1f9df375b4734737c2ef62cf8506983e882419a30/biopython-1.86-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:236ca61aa996f12cbc65a8d6a15abfac70b9ee800656629b784c6a240e7d8dc0", size = 2694733, upload-time = "2025-10-29T00:27:49.142Z" }, { url = "https://files.pythonhosted.org/packages/24/7e/a80fad6dbfa1335c506b1565d2b3fdd78cda705408a839c5583a9cfca8b6/biopython-1.86-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f96b7441f456c7eecad5c6e61e75b0db1435c489be7cc5e4f97dd4e60921747c", size = 2670131, upload-time = "2025-10-29T00:27:53.758Z" }, { url = "https://files.pythonhosted.org/packages/2d/0a/6c12e9262b99f395bd66535c4a4203bd70833c11f47ac0730fca6ba2b5f8/biopython-1.86-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d53a78bf960397826219f08f87b061ad7f227527d19986e830eeab60d370b597", size = 3209810, upload-time = "2025-10-29T00:36:45.88Z" }, { url = "https://files.pythonhosted.org/packages/3a/f9/265211154d2bb4cffe78a57b8e57cfbb165cf41cf3d1b68e2a6b073b3b8a/biopython-1.86-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb86e4383c02fdb2571a38947153346e6f5cd38e22de1df40f54d2a3c51d02a8", size = 3235347, upload-time = "2025-10-29T00:36:51.164Z" }, { url = "https://files.pythonhosted.org/packages/64/e5/58d8e48d3b4100a7fd8bae97f0dd7179c30f19861841d1a0bb7827e0033e/biopython-1.86-cp314-cp314-win32.whl", hash = "sha256:ffeba620c4786ea836efee235a9c6333b94e922b89de1449a4782dcc15246ff1", size = 2698198, upload-time = "2025-10-29T00:28:02.812Z" }, { url = "https://files.pythonhosted.org/packages/e2/ca/aa166eb588a2d4eea381c92e5a2a3d09b4b4887b0f0e8f3acf999fb88157/biopython-1.86-cp314-cp314-win_amd64.whl", hash = "sha256:efbb9bc4415a1e2c1c986ba261b02857bc0c9eed098b15493f1cc5c4a1e02409", size = 2734693, upload-time = "2025-10-29T00:27:58.312Z" }, { url = "https://files.pythonhosted.org/packages/50/da/8c227d701ec9c94d9870b1879982e3dd114da130b0816d3f9b937318d31a/biopython-1.86-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:caa70c1639b3306549605f9273753bdbf8cd6d6d352cecf23afbda3c911694f3", size = 2697389, upload-time = "2025-10-29T00:28:07.037Z" }, { url = "https://files.pythonhosted.org/packages/8c/1e/66b0b5622ef6a3a14c449d1c8d69749480b37518e4c1e3a8a86fc668dad7/biopython-1.86-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d077f01d1f69f77a26cac46163d4ea45eb4e6509a68feb7f15e665b7e1de0a99", size = 2673857, upload-time = "2025-10-29T00:28:11.488Z" }, { url = "https://files.pythonhosted.org/packages/76/05/7c8f9800e6960da2007eb75128c8ec0b22e1a0064e8802e8acfad53cdca8/biopython-1.86-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4506ce7dbdf885cb24d1f5439362c3c07f1b6f90761a0d20fe16a2a9ea5702a5", size = 3253007, upload-time = "2025-10-29T00:36:56.066Z" }, { url = "https://files.pythonhosted.org/packages/14/dd/a2177328d841fda0a12e67c65d06279691e25363a2805f561b3665cae114/biopython-1.86-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dcd94717e83ba891ebd9acaecbf05ad38313095ca5706caf6c38fa3f2aa17528", size = 3272883, upload-time = "2025-10-29T00:37:01.189Z" }, { url = "https://files.pythonhosted.org/packages/ce/04/1aa91f64db5e0728d596fcf7302e2ae2035800c0676e94ea09645a948b91/biopython-1.86-cp314-cp314t-win32.whl", hash = "sha256:2f6b205dcb4101cefa5c615114bd35a19f656abb9d340eb3cf190f829e43800a", size = 2701649, upload-time = "2025-10-29T00:28:20.527Z" }, { url = "https://files.pythonhosted.org/packages/63/7c/4acaca39102d667175bb3d6502dea91c346f8674c06d5df0dbb678971596/biopython-1.86-cp314-cp314t-win_amd64.whl", hash = "sha256:efeee7c37f2331d2c55704df39e122189cc237ffd7511f34158418ad728131b8", size = 2741364, upload-time = "2025-10-29T00:28:15.752Z" }, ] [[package]] name = "black" version = "25.11.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "mypy-extensions", marker = "python_full_version < '3.10'" }, { name = "packaging", marker = "python_full_version < '3.10'" }, { name = "pathspec", marker = "python_full_version < '3.10'" }, { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytokens", marker = "python_full_version < '3.10'" }, { name = "tomli", marker = "python_full_version < '3.10'" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/8c/ad/33adf4708633d047950ff2dfdea2e215d84ac50ef95aff14a614e4b6e9b2/black-25.11.0.tar.gz", hash = "sha256:9a323ac32f5dc75ce7470501b887250be5005a01602e931a15e45593f70f6e08", size = 655669, upload-time = "2025-11-10T01:53:50.558Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b3/d2/6caccbc96f9311e8ec3378c296d4f4809429c43a6cd2394e3c390e86816d/black-25.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ec311e22458eec32a807f029b2646f661e6859c3f61bc6d9ffb67958779f392e", size = 1743501, upload-time = "2025-11-10T01:59:06.202Z" }, { url = "https://files.pythonhosted.org/packages/69/35/b986d57828b3f3dccbf922e2864223197ba32e74c5004264b1c62bc9f04d/black-25.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1032639c90208c15711334d681de2e24821af0575573db2810b0763bcd62e0f0", size = 1597308, upload-time = "2025-11-10T01:57:58.633Z" }, { url = "https://files.pythonhosted.org/packages/39/8e/8b58ef4b37073f52b64a7b2dd8c9a96c84f45d6f47d878d0aa557e9a2d35/black-25.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c0f7c461df55cf32929b002335883946a4893d759f2df343389c4396f3b6b37", size = 1656194, upload-time = "2025-11-10T01:57:10.909Z" }, { url = "https://files.pythonhosted.org/packages/8d/30/9c2267a7955ecc545306534ab88923769a979ac20a27cf618d370091e5dd/black-25.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:f9786c24d8e9bd5f20dc7a7f0cdd742644656987f6ea6947629306f937726c03", size = 1347996, upload-time = "2025-11-10T01:57:22.391Z" }, { url = "https://files.pythonhosted.org/packages/c4/62/d304786b75ab0c530b833a89ce7d997924579fb7484ecd9266394903e394/black-25.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:895571922a35434a9d8ca67ef926da6bc9ad464522a5fe0db99b394ef1c0675a", size = 1727891, upload-time = "2025-11-10T02:01:40.507Z" }, { url = "https://files.pythonhosted.org/packages/82/5d/ffe8a006aa522c9e3f430e7b93568a7b2163f4b3f16e8feb6d8c3552761a/black-25.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cb4f4b65d717062191bdec8e4a442539a8ea065e6af1c4f4d36f0cdb5f71e170", size = 1581875, upload-time = "2025-11-10T01:57:51.192Z" }, { url = "https://files.pythonhosted.org/packages/cb/c8/7c8bda3108d0bb57387ac41b4abb5c08782b26da9f9c4421ef6694dac01a/black-25.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d81a44cbc7e4f73a9d6ae449ec2317ad81512d1e7dce7d57f6333fd6259737bc", size = 1642716, upload-time = "2025-11-10T01:56:51.589Z" }, { url = "https://files.pythonhosted.org/packages/34/b9/f17dea34eecb7cc2609a89627d480fb6caea7b86190708eaa7eb15ed25e7/black-25.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:7eebd4744dfe92ef1ee349dc532defbf012a88b087bb7ddd688ff59a447b080e", size = 1352904, upload-time = "2025-11-10T01:59:26.252Z" }, { url = "https://files.pythonhosted.org/packages/7f/12/5c35e600b515f35ffd737da7febdb2ab66bb8c24d88560d5e3ef3d28c3fd/black-25.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:80e7486ad3535636657aa180ad32a7d67d7c273a80e12f1b4bfa0823d54e8fac", size = 1772831, upload-time = "2025-11-10T02:03:47Z" }, { url = "https://files.pythonhosted.org/packages/1a/75/b3896bec5a2bb9ed2f989a970ea40e7062f8936f95425879bbe162746fe5/black-25.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cced12b747c4c76bc09b4db057c319d8545307266f41aaee665540bc0e04e96", size = 1608520, upload-time = "2025-11-10T01:58:46.895Z" }, { url = "https://files.pythonhosted.org/packages/f3/b5/2bfc18330eddbcfb5aab8d2d720663cd410f51b2ed01375f5be3751595b0/black-25.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cb2d54a39e0ef021d6c5eef442e10fd71fcb491be6413d083a320ee768329dd", size = 1682719, upload-time = "2025-11-10T01:56:55.24Z" }, { url = "https://files.pythonhosted.org/packages/96/fb/f7dc2793a22cdf74a72114b5ed77fe3349a2e09ef34565857a2f917abdf2/black-25.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae263af2f496940438e5be1a0c1020e13b09154f3af4df0835ea7f9fe7bfa409", size = 1362684, upload-time = "2025-11-10T01:57:07.639Z" }, { url = "https://files.pythonhosted.org/packages/ad/47/3378d6a2ddefe18553d1115e36aea98f4a90de53b6a3017ed861ba1bd3bc/black-25.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a1d40348b6621cc20d3d7530a5b8d67e9714906dfd7346338249ad9c6cedf2b", size = 1772446, upload-time = "2025-11-10T02:02:16.181Z" }, { url = "https://files.pythonhosted.org/packages/ba/4b/0f00bfb3d1f7e05e25bfc7c363f54dc523bb6ba502f98f4ad3acf01ab2e4/black-25.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:51c65d7d60bb25429ea2bf0731c32b2a2442eb4bd3b2afcb47830f0b13e58bfd", size = 1607983, upload-time = "2025-11-10T02:02:52.502Z" }, { url = "https://files.pythonhosted.org/packages/99/fe/49b0768f8c9ae57eb74cc10a1f87b4c70453551d8ad498959721cc345cb7/black-25.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:936c4dd07669269f40b497440159a221ee435e3fddcf668e0c05244a9be71993", size = 1682481, upload-time = "2025-11-10T01:57:12.35Z" }, { url = "https://files.pythonhosted.org/packages/55/17/7e10ff1267bfa950cc16f0a411d457cdff79678fbb77a6c73b73a5317904/black-25.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:f42c0ea7f59994490f4dccd64e6b2dd49ac57c7c84f38b8faab50f8759db245c", size = 1363869, upload-time = "2025-11-10T01:58:24.608Z" }, { url = "https://files.pythonhosted.org/packages/67/c0/cc865ce594d09e4cd4dfca5e11994ebb51604328489f3ca3ae7bb38a7db5/black-25.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:35690a383f22dd3e468c85dc4b915217f87667ad9cce781d7b42678ce63c4170", size = 1771358, upload-time = "2025-11-10T02:03:33.331Z" }, { url = "https://files.pythonhosted.org/packages/37/77/4297114d9e2fd2fc8ab0ab87192643cd49409eb059e2940391e7d2340e57/black-25.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dae49ef7369c6caa1a1833fd5efb7c3024bb7e4499bf64833f65ad27791b1545", size = 1612902, upload-time = "2025-11-10T01:59:33.382Z" }, { url = "https://files.pythonhosted.org/packages/de/63/d45ef97ada84111e330b2b2d45e1dd163e90bd116f00ac55927fb6bf8adb/black-25.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bd4a22a0b37401c8e492e994bce79e614f91b14d9ea911f44f36e262195fdda", size = 1680571, upload-time = "2025-11-10T01:57:04.239Z" }, { url = "https://files.pythonhosted.org/packages/ff/4b/5604710d61cdff613584028b4cb4607e56e148801ed9b38ee7970799dab6/black-25.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:aa211411e94fdf86519996b7f5f05e71ba34835d8f0c0f03c00a26271da02664", size = 1382599, upload-time = "2025-11-10T01:57:57.427Z" }, { url = "https://files.pythonhosted.org/packages/d5/9a/5b2c0e3215fe748fcf515c2dd34658973a1210bf610e24de5ba887e4f1c8/black-25.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3bb5ce32daa9ff0605d73b6f19da0b0e6c1f8f2d75594db539fdfed722f2b06", size = 1743063, upload-time = "2025-11-10T02:02:43.175Z" }, { url = "https://files.pythonhosted.org/packages/a1/20/245164c6efc27333409c62ba54dcbfbe866c6d1957c9a6c0647786e950da/black-25.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9815ccee1e55717fe9a4b924cae1646ef7f54e0f990da39a34fc7b264fcf80a2", size = 1596867, upload-time = "2025-11-10T02:00:17.157Z" }, { url = "https://files.pythonhosted.org/packages/ca/6f/1a3859a7da205f3d50cf3a8bec6bdc551a91c33ae77a045bb24c1f46ab54/black-25.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92285c37b93a1698dcbc34581867b480f1ba3a7b92acf1fe0467b04d7a4da0dc", size = 1655678, upload-time = "2025-11-10T01:57:09.028Z" }, { url = "https://files.pythonhosted.org/packages/56/1a/6dec1aeb7be90753d4fcc273e69bc18bfd34b353223ed191da33f7519410/black-25.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:43945853a31099c7c0ff8dface53b4de56c41294fa6783c0441a8b1d9bf668bc", size = 1347452, upload-time = "2025-11-10T01:57:01.871Z" }, { url = "https://files.pythonhosted.org/packages/00/5d/aed32636ed30a6e7f9efd6ad14e2a0b0d687ae7c8c7ec4e4a557174b895c/black-25.11.0-py3-none-any.whl", hash = "sha256:e3f562da087791e96cefcd9dda058380a442ab322a02e222add53736451f604b", size = 204918, upload-time = "2025-11-10T01:53:48.917Z" }, ] [[package]] name = "black" version = "26.1.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "mypy-extensions", marker = "python_full_version >= '3.10'" }, { name = "packaging", marker = "python_full_version >= '3.10'" }, { name = "pathspec", marker = "python_full_version >= '3.10'" }, { name = "platformdirs", version = "4.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pytokens", marker = "python_full_version >= '3.10'" }, { name = "tomli", marker = "python_full_version == '3.10.*'" }, { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/13/88/560b11e521c522440af991d46848a2bde64b5f7202ec14e1f46f9509d328/black-26.1.0.tar.gz", hash = "sha256:d294ac3340eef9c9eb5d29288e96dc719ff269a88e27b396340459dd85da4c58", size = 658785, upload-time = "2026-01-18T04:50:11.993Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/51/1b/523329e713f965ad0ea2b7a047eeb003007792a0353622ac7a8cb2ee6fef/black-26.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ca699710dece84e3ebf6e92ee15f5b8f72870ef984bf944a57a777a48357c168", size = 1849661, upload-time = "2026-01-18T04:59:12.425Z" }, { url = "https://files.pythonhosted.org/packages/14/82/94c0640f7285fa71c2f32879f23e609dd2aa39ba2641f395487f24a578e7/black-26.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e8e75dabb6eb83d064b0db46392b25cabb6e784ea624219736e8985a6b3675d", size = 1689065, upload-time = "2026-01-18T04:59:13.993Z" }, { url = "https://files.pythonhosted.org/packages/f0/78/474373cbd798f9291ed8f7107056e343fd39fef42de4a51c7fd0d360840c/black-26.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb07665d9a907a1a645ee41a0df8a25ffac8ad9c26cdb557b7b88eeeeec934e0", size = 1751502, upload-time = "2026-01-18T04:59:15.971Z" }, { url = "https://files.pythonhosted.org/packages/29/89/59d0e350123f97bc32c27c4d79563432d7f3530dca2bff64d855c178af8b/black-26.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7ed300200918147c963c87700ccf9966dceaefbbb7277450a8d646fc5646bf24", size = 1400102, upload-time = "2026-01-18T04:59:17.8Z" }, { url = "https://files.pythonhosted.org/packages/e1/bc/5d866c7ae1c9d67d308f83af5462ca7046760158bbf142502bad8f22b3a1/black-26.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c5b7713daea9bf943f79f8c3b46f361cc5229e0e604dcef6a8bb6d1c37d9df89", size = 1207038, upload-time = "2026-01-18T04:59:19.543Z" }, { url = "https://files.pythonhosted.org/packages/30/83/f05f22ff13756e1a8ce7891db517dbc06200796a16326258268f4658a745/black-26.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3cee1487a9e4c640dc7467aaa543d6c0097c391dc8ac74eb313f2fbf9d7a7cb5", size = 1831956, upload-time = "2026-01-18T04:59:21.38Z" }, { url = "https://files.pythonhosted.org/packages/7d/f2/b2c570550e39bedc157715e43927360312d6dd677eed2cc149a802577491/black-26.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d62d14ca31c92adf561ebb2e5f2741bf8dea28aef6deb400d49cca011d186c68", size = 1672499, upload-time = "2026-01-18T04:59:23.257Z" }, { url = "https://files.pythonhosted.org/packages/7a/d7/990d6a94dc9e169f61374b1c3d4f4dd3037e93c2cc12b6f3b12bc663aa7b/black-26.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb1dafbbaa3b1ee8b4550a84425aac8874e5f390200f5502cf3aee4a2acb2f14", size = 1735431, upload-time = "2026-01-18T04:59:24.729Z" }, { url = "https://files.pythonhosted.org/packages/36/1c/cbd7bae7dd3cb315dfe6eeca802bb56662cc92b89af272e014d98c1f2286/black-26.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:101540cb2a77c680f4f80e628ae98bd2bd8812fb9d72ade4f8995c5ff019e82c", size = 1400468, upload-time = "2026-01-18T04:59:27.381Z" }, { url = "https://files.pythonhosted.org/packages/59/b1/9fe6132bb2d0d1f7094613320b56297a108ae19ecf3041d9678aec381b37/black-26.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:6f3977a16e347f1b115662be07daa93137259c711e526402aa444d7a88fdc9d4", size = 1207332, upload-time = "2026-01-18T04:59:28.711Z" }, { url = "https://files.pythonhosted.org/packages/f5/13/710298938a61f0f54cdb4d1c0baeb672c01ff0358712eddaf29f76d32a0b/black-26.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6eeca41e70b5f5c84f2f913af857cf2ce17410847e1d54642e658e078da6544f", size = 1878189, upload-time = "2026-01-18T04:59:30.682Z" }, { url = "https://files.pythonhosted.org/packages/79/a6/5179beaa57e5dbd2ec9f1c64016214057b4265647c62125aa6aeffb05392/black-26.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd39eef053e58e60204f2cdf059e2442e2eb08f15989eefe259870f89614c8b6", size = 1700178, upload-time = "2026-01-18T04:59:32.387Z" }, { url = "https://files.pythonhosted.org/packages/8c/04/c96f79d7b93e8f09d9298b333ca0d31cd9b2ee6c46c274fd0f531de9dc61/black-26.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9459ad0d6cd483eacad4c6566b0f8e42af5e8b583cee917d90ffaa3778420a0a", size = 1777029, upload-time = "2026-01-18T04:59:33.767Z" }, { url = "https://files.pythonhosted.org/packages/49/f9/71c161c4c7aa18bdda3776b66ac2dc07aed62053c7c0ff8bbda8c2624fe2/black-26.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a19915ec61f3a8746e8b10adbac4a577c6ba9851fa4a9e9fbfbcf319887a5791", size = 1406466, upload-time = "2026-01-18T04:59:35.177Z" }, { url = "https://files.pythonhosted.org/packages/4a/8b/a7b0f974e473b159d0ac1b6bcefffeb6bec465898a516ee5cc989503cbc7/black-26.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:643d27fb5facc167c0b1b59d0315f2674a6e950341aed0fc05cf307d22bf4954", size = 1216393, upload-time = "2026-01-18T04:59:37.18Z" }, { url = "https://files.pythonhosted.org/packages/79/04/fa2f4784f7237279332aa735cdfd5ae2e7730db0072fb2041dadda9ae551/black-26.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ba1d768fbfb6930fc93b0ecc32a43d8861ded16f47a40f14afa9bb04ab93d304", size = 1877781, upload-time = "2026-01-18T04:59:39.054Z" }, { url = "https://files.pythonhosted.org/packages/cf/ad/5a131b01acc0e5336740a039628c0ab69d60cf09a2c87a4ec49f5826acda/black-26.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b807c240b64609cb0e80d2200a35b23c7df82259f80bef1b2c96eb422b4aac9", size = 1699670, upload-time = "2026-01-18T04:59:41.005Z" }, { url = "https://files.pythonhosted.org/packages/da/7c/b05f22964316a52ab6b4265bcd52c0ad2c30d7ca6bd3d0637e438fc32d6e/black-26.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1de0f7d01cc894066a1153b738145b194414cc6eeaad8ef4397ac9abacf40f6b", size = 1775212, upload-time = "2026-01-18T04:59:42.545Z" }, { url = "https://files.pythonhosted.org/packages/a6/a3/e8d1526bea0446e040193185353920a9506eab60a7d8beb062029129c7d2/black-26.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:91a68ae46bf07868963671e4d05611b179c2313301bd756a89ad4e3b3db2325b", size = 1409953, upload-time = "2026-01-18T04:59:44.357Z" }, { url = "https://files.pythonhosted.org/packages/c7/5a/d62ebf4d8f5e3a1daa54adaab94c107b57be1b1a2f115a0249b41931e188/black-26.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:be5e2fe860b9bd9edbf676d5b60a9282994c03fbbd40fe8f5e75d194f96064ca", size = 1217707, upload-time = "2026-01-18T04:59:45.719Z" }, { url = "https://files.pythonhosted.org/packages/6a/83/be35a175aacfce4b05584ac415fd317dd6c24e93a0af2dcedce0f686f5d8/black-26.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9dc8c71656a79ca49b8d3e2ce8103210c9481c57798b48deeb3a8bb02db5f115", size = 1871864, upload-time = "2026-01-18T04:59:47.586Z" }, { url = "https://files.pythonhosted.org/packages/a5/f5/d33696c099450b1274d925a42b7a030cd3ea1f56d72e5ca8bbed5f52759c/black-26.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b22b3810451abe359a964cc88121d57f7bce482b53a066de0f1584988ca36e79", size = 1701009, upload-time = "2026-01-18T04:59:49.443Z" }, { url = "https://files.pythonhosted.org/packages/1b/87/670dd888c537acb53a863bc15abbd85b22b429237d9de1b77c0ed6b79c42/black-26.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53c62883b3f999f14e5d30b5a79bd437236658ad45b2f853906c7cbe79de00af", size = 1767806, upload-time = "2026-01-18T04:59:50.769Z" }, { url = "https://files.pythonhosted.org/packages/fe/9c/cd3deb79bfec5bcf30f9d2100ffeec63eecce826eb63e3961708b9431ff1/black-26.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:f016baaadc423dc960cdddf9acae679e71ee02c4c341f78f3179d7e4819c095f", size = 1433217, upload-time = "2026-01-18T04:59:52.218Z" }, { url = "https://files.pythonhosted.org/packages/4e/29/f3be41a1cf502a283506f40f5d27203249d181f7a1a2abce1c6ce188035a/black-26.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:66912475200b67ef5a0ab665011964bf924745103f51977a78b4fb92a9fc1bf0", size = 1245773, upload-time = "2026-01-18T04:59:54.457Z" }, { url = "https://files.pythonhosted.org/packages/e4/3d/51bdb3ecbfadfaf825ec0c75e1de6077422b4afa2091c6c9ba34fbfc0c2d/black-26.1.0-py3-none-any.whl", hash = "sha256:1054e8e47ebd686e078c0bb0eaf31e6ce69c966058d122f2c0c950311f9f3ede", size = 204010, upload-time = "2026-01-18T04:50:09.978Z" }, ] [[package]] name = "blinker" version = "1.9.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, ] [[package]] name = "build" version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "os_name == 'nt'" }, { name = "importlib-metadata", marker = "python_full_version < '3.10.2'" }, { name = "packaging" }, { name = "pyproject-hooks" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/18/94eaffda7b329535d91f00fe605ab1f1e5cd68b2074d03f255c7d250687d/build-1.4.0.tar.gz", hash = "sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936", size = 50054, upload-time = "2026-01-08T16:41:47.696Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl", hash = "sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596", size = 24141, upload-time = "2026-01-08T16:41:46.453Z" }, ] [[package]] name = "certifi" version = "2026.1.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, ] [[package]] name = "cffi" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycparser", version = "2.23", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' and implementation_name != 'PyPy'" }, { name = "pycparser", version = "3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.10.*' and implementation_name != 'PyPy' and sys_platform == 'emscripten') or (python_full_version == '3.10.*' and implementation_name != 'PyPy' and sys_platform == 'win32') or (python_full_version >= '3.10' and implementation_name != 'PyPy' and sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, { url = "https://files.pythonhosted.org/packages/9b/13/c92e36358fbcc39cf0962e83223c9522154ee8630e1df7c0b3a39a8124e2/cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c", size = 208813, upload-time = "2025-09-08T23:23:51.263Z" }, { url = "https://files.pythonhosted.org/packages/15/12/a7a79bd0df4c3bff744b2d7e52cc1b68d5e7e427b384252c42366dc1ecbc/cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165", size = 216498, upload-time = "2025-09-08T23:23:52.494Z" }, { url = "https://files.pythonhosted.org/packages/1f/74/cc4096ce66f5939042ae094e2e96f53426a979864aa1f96a621ad128be27/cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63", size = 216548, upload-time = "2025-09-08T23:23:56.506Z" }, { url = "https://files.pythonhosted.org/packages/e8/be/f6424d1dc46b1091ffcc8964fa7c0ab0cd36839dd2761b49c90481a6ba1b/cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2", size = 218897, upload-time = "2025-09-08T23:23:57.825Z" }, { url = "https://files.pythonhosted.org/packages/f7/e0/dda537c2309817edf60109e39265f24f24aa7f050767e22c98c53fe7f48b/cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65", size = 211249, upload-time = "2025-09-08T23:23:59.139Z" }, { url = "https://files.pythonhosted.org/packages/2b/e7/7c769804eb75e4c4b35e658dba01de1640a351a9653c3d49ca89d16ccc91/cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322", size = 218041, upload-time = "2025-09-08T23:24:00.496Z" }, ] [[package]] name = "charset-normalizer" version = "3.4.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/1f/b8/6d51fc1d52cbd52cd4ccedd5b5b2f0f6a11bbf6765c782298b0f3e808541/charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", size = 209709, upload-time = "2025-10-14T04:40:11.385Z" }, { url = "https://files.pythonhosted.org/packages/5c/af/1f9d7f7faafe2ddfb6f72a2e07a548a629c61ad510fe60f9630309908fef/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", size = 148814, upload-time = "2025-10-14T04:40:13.135Z" }, { url = "https://files.pythonhosted.org/packages/79/3d/f2e3ac2bbc056ca0c204298ea4e3d9db9b4afe437812638759db2c976b5f/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", size = 144467, upload-time = "2025-10-14T04:40:14.728Z" }, { url = "https://files.pythonhosted.org/packages/ec/85/1bf997003815e60d57de7bd972c57dc6950446a3e4ccac43bc3070721856/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", size = 162280, upload-time = "2025-10-14T04:40:16.14Z" }, { url = "https://files.pythonhosted.org/packages/3e/8e/6aa1952f56b192f54921c436b87f2aaf7c7a7c3d0d1a765547d64fd83c13/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", size = 159454, upload-time = "2025-10-14T04:40:17.567Z" }, { url = "https://files.pythonhosted.org/packages/36/3b/60cbd1f8e93aa25d1c669c649b7a655b0b5fb4c571858910ea9332678558/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", size = 153609, upload-time = "2025-10-14T04:40:19.08Z" }, { url = "https://files.pythonhosted.org/packages/64/91/6a13396948b8fd3c4b4fd5bc74d045f5637d78c9675585e8e9fbe5636554/charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", size = 151849, upload-time = "2025-10-14T04:40:20.607Z" }, { url = "https://files.pythonhosted.org/packages/b7/7a/59482e28b9981d105691e968c544cc0df3b7d6133152fb3dcdc8f135da7a/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", size = 151586, upload-time = "2025-10-14T04:40:21.719Z" }, { url = "https://files.pythonhosted.org/packages/92/59/f64ef6a1c4bdd2baf892b04cd78792ed8684fbc48d4c2afe467d96b4df57/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", size = 145290, upload-time = "2025-10-14T04:40:23.069Z" }, { url = "https://files.pythonhosted.org/packages/6b/63/3bf9f279ddfa641ffa1962b0db6a57a9c294361cc2f5fcac997049a00e9c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", size = 163663, upload-time = "2025-10-14T04:40:24.17Z" }, { url = "https://files.pythonhosted.org/packages/ed/09/c9e38fc8fa9e0849b172b581fd9803bdf6e694041127933934184e19f8c3/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", size = 151964, upload-time = "2025-10-14T04:40:25.368Z" }, { url = "https://files.pythonhosted.org/packages/d2/d1/d28b747e512d0da79d8b6a1ac18b7ab2ecfd81b2944c4c710e166d8dd09c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", size = 161064, upload-time = "2025-10-14T04:40:26.806Z" }, { url = "https://files.pythonhosted.org/packages/bb/9a/31d62b611d901c3b9e5500c36aab0ff5eb442043fb3a1c254200d3d397d9/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", size = 155015, upload-time = "2025-10-14T04:40:28.284Z" }, { url = "https://files.pythonhosted.org/packages/1f/f3/107e008fa2bff0c8b9319584174418e5e5285fef32f79d8ee6a430d0039c/charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", size = 99792, upload-time = "2025-10-14T04:40:29.613Z" }, { url = "https://files.pythonhosted.org/packages/eb/66/e396e8a408843337d7315bab30dbf106c38966f1819f123257f5520f8a96/charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", size = 107198, upload-time = "2025-10-14T04:40:30.644Z" }, { url = "https://files.pythonhosted.org/packages/b5/58/01b4f815bf0312704c267f2ccb6e5d42bcc7752340cd487bc9f8c3710597/charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", size = 100262, upload-time = "2025-10-14T04:40:32.108Z" }, { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, { url = "https://files.pythonhosted.org/packages/46/7c/0c4760bccf082737ca7ab84a4c2034fcc06b1f21cf3032ea98bd6feb1725/charset_normalizer-3.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9", size = 209609, upload-time = "2025-10-14T04:42:10.922Z" }, { url = "https://files.pythonhosted.org/packages/bb/a4/69719daef2f3d7f1819de60c9a6be981b8eeead7542d5ec4440f3c80e111/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d", size = 149029, upload-time = "2025-10-14T04:42:12.38Z" }, { url = "https://files.pythonhosted.org/packages/e6/21/8d4e1d6c1e6070d3672908b8e4533a71b5b53e71d16828cc24d0efec564c/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608", size = 144580, upload-time = "2025-10-14T04:42:13.549Z" }, { url = "https://files.pythonhosted.org/packages/a7/0a/a616d001b3f25647a9068e0b9199f697ce507ec898cacb06a0d5a1617c99/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc", size = 162340, upload-time = "2025-10-14T04:42:14.892Z" }, { url = "https://files.pythonhosted.org/packages/85/93/060b52deb249a5450460e0585c88a904a83aec474ab8e7aba787f45e79f2/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e", size = 159619, upload-time = "2025-10-14T04:42:16.676Z" }, { url = "https://files.pythonhosted.org/packages/dd/21/0274deb1cc0632cd587a9a0ec6b4674d9108e461cb4cd40d457adaeb0564/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1", size = 153980, upload-time = "2025-10-14T04:42:17.917Z" }, { url = "https://files.pythonhosted.org/packages/28/2b/e3d7d982858dccc11b31906976323d790dded2017a0572f093ff982d692f/charset_normalizer-3.4.4-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3", size = 152174, upload-time = "2025-10-14T04:42:19.018Z" }, { url = "https://files.pythonhosted.org/packages/6e/ff/4a269f8e35f1e58b2df52c131a1fa019acb7ef3f8697b7d464b07e9b492d/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6", size = 151666, upload-time = "2025-10-14T04:42:20.171Z" }, { url = "https://files.pythonhosted.org/packages/da/c9/ec39870f0b330d58486001dd8e532c6b9a905f5765f58a6f8204926b4a93/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88", size = 145550, upload-time = "2025-10-14T04:42:21.324Z" }, { url = "https://files.pythonhosted.org/packages/75/8f/d186ab99e40e0ed9f82f033d6e49001701c81244d01905dd4a6924191a30/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1", size = 163721, upload-time = "2025-10-14T04:42:22.46Z" }, { url = "https://files.pythonhosted.org/packages/96/b1/6047663b9744df26a7e479ac1e77af7134b1fcf9026243bb48ee2d18810f/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf", size = 152127, upload-time = "2025-10-14T04:42:23.712Z" }, { url = "https://files.pythonhosted.org/packages/59/78/e5a6eac9179f24f704d1be67d08704c3c6ab9f00963963524be27c18ed87/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318", size = 161175, upload-time = "2025-10-14T04:42:24.87Z" }, { url = "https://files.pythonhosted.org/packages/e5/43/0e626e42d54dd2f8dd6fc5e1c5ff00f05fbca17cb699bedead2cae69c62f/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c", size = 155375, upload-time = "2025-10-14T04:42:27.246Z" }, { url = "https://files.pythonhosted.org/packages/e9/91/d9615bf2e06f35e4997616ff31248c3657ed649c5ab9d35ea12fce54e380/charset_normalizer-3.4.4-cp39-cp39-win32.whl", hash = "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505", size = 99692, upload-time = "2025-10-14T04:42:28.425Z" }, { url = "https://files.pythonhosted.org/packages/d1/a9/6c040053909d9d1ef4fcab45fddec083aedc9052c10078339b47c8573ea8/charset_normalizer-3.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966", size = 107192, upload-time = "2025-10-14T04:42:29.482Z" }, { url = "https://files.pythonhosted.org/packages/f0/c6/4fa536b2c0cd3edfb7ccf8469fa0f363ea67b7213a842b90909ca33dd851/charset_normalizer-3.4.4-cp39-cp39-win_arm64.whl", hash = "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50", size = 100220, upload-time = "2025-10-14T04:42:30.632Z" }, { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, ] [[package]] name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, ] [[package]] name = "click" version = "8.3.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] [[package]] name = "contourpy" version = "1.3.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f5/f6/31a8f28b4a2a4fa0e01085e542f3081ab0588eff8e589d39d775172c9792/contourpy-1.3.0.tar.gz", hash = "sha256:7ffa0db17717a8ffb127efd0c95a4362d996b892c2904db72428d5b52e1938a4", size = 13464370, upload-time = "2024-08-27T21:00:03.328Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/6c/e0/be8dcc796cfdd96708933e0e2da99ba4bb8f9b2caa9d560a50f3f09a65f3/contourpy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:880ea32e5c774634f9fcd46504bf9f080a41ad855f4fef54f5380f5133d343c7", size = 265366, upload-time = "2024-08-27T20:50:09.947Z" }, { url = "https://files.pythonhosted.org/packages/50/d6/c953b400219443535d412fcbbc42e7a5e823291236bc0bb88936e3cc9317/contourpy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:76c905ef940a4474a6289c71d53122a4f77766eef23c03cd57016ce19d0f7b42", size = 249226, upload-time = "2024-08-27T20:50:16.1Z" }, { url = "https://files.pythonhosted.org/packages/6f/b4/6fffdf213ffccc28483c524b9dad46bb78332851133b36ad354b856ddc7c/contourpy-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92f8557cbb07415a4d6fa191f20fd9d2d9eb9c0b61d1b2f52a8926e43c6e9af7", size = 308460, upload-time = "2024-08-27T20:50:22.536Z" }, { url = "https://files.pythonhosted.org/packages/cf/6c/118fc917b4050f0afe07179a6dcbe4f3f4ec69b94f36c9e128c4af480fb8/contourpy-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36f965570cff02b874773c49bfe85562b47030805d7d8360748f3eca570f4cab", size = 347623, upload-time = "2024-08-27T20:50:28.806Z" }, { url = "https://files.pythonhosted.org/packages/f9/a4/30ff110a81bfe3abf7b9673284d21ddce8cc1278f6f77393c91199da4c90/contourpy-1.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cacd81e2d4b6f89c9f8a5b69b86490152ff39afc58a95af002a398273e5ce589", size = 317761, upload-time = "2024-08-27T20:50:35.126Z" }, { url = "https://files.pythonhosted.org/packages/99/e6/d11966962b1aa515f5586d3907ad019f4b812c04e4546cc19ebf62b5178e/contourpy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69375194457ad0fad3a839b9e29aa0b0ed53bb54db1bfb6c3ae43d111c31ce41", size = 322015, upload-time = "2024-08-27T20:50:40.318Z" }, { url = "https://files.pythonhosted.org/packages/4d/e3/182383743751d22b7b59c3c753277b6aee3637049197624f333dac5b4c80/contourpy-1.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a52040312b1a858b5e31ef28c2e865376a386c60c0e248370bbea2d3f3b760d", size = 1262672, upload-time = "2024-08-27T20:50:55.643Z" }, { url = "https://files.pythonhosted.org/packages/78/53/974400c815b2e605f252c8fb9297e2204347d1755a5374354ee77b1ea259/contourpy-1.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3faeb2998e4fcb256542e8a926d08da08977f7f5e62cf733f3c211c2a5586223", size = 1321688, upload-time = "2024-08-27T20:51:11.293Z" }, { url = "https://files.pythonhosted.org/packages/52/29/99f849faed5593b2926a68a31882af98afbeac39c7fdf7de491d9c85ec6a/contourpy-1.3.0-cp310-cp310-win32.whl", hash = "sha256:36e0cff201bcb17a0a8ecc7f454fe078437fa6bda730e695a92f2d9932bd507f", size = 171145, upload-time = "2024-08-27T20:51:15.2Z" }, { url = "https://files.pythonhosted.org/packages/a9/97/3f89bba79ff6ff2b07a3cbc40aa693c360d5efa90d66e914f0ff03b95ec7/contourpy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:87ddffef1dbe5e669b5c2440b643d3fdd8622a348fe1983fad7a0f0ccb1cd67b", size = 216019, upload-time = "2024-08-27T20:51:19.365Z" }, { url = "https://files.pythonhosted.org/packages/b3/1f/9375917786cb39270b0ee6634536c0e22abf225825602688990d8f5c6c19/contourpy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fa4c02abe6c446ba70d96ece336e621efa4aecae43eaa9b030ae5fb92b309ad", size = 266356, upload-time = "2024-08-27T20:51:24.146Z" }, { url = "https://files.pythonhosted.org/packages/05/46/9256dd162ea52790c127cb58cfc3b9e3413a6e3478917d1f811d420772ec/contourpy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:834e0cfe17ba12f79963861e0f908556b2cedd52e1f75e6578801febcc6a9f49", size = 250915, upload-time = "2024-08-27T20:51:28.683Z" }, { url = "https://files.pythonhosted.org/packages/e1/5d/3056c167fa4486900dfbd7e26a2fdc2338dc58eee36d490a0ed3ddda5ded/contourpy-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbc4c3217eee163fa3984fd1567632b48d6dfd29216da3ded3d7b844a8014a66", size = 310443, upload-time = "2024-08-27T20:51:33.675Z" }, { url = "https://files.pythonhosted.org/packages/ca/c2/1a612e475492e07f11c8e267ea5ec1ce0d89971be496c195e27afa97e14a/contourpy-1.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4865cd1d419e0c7a7bf6de1777b185eebdc51470800a9f42b9e9decf17762081", size = 348548, upload-time = "2024-08-27T20:51:39.322Z" }, { url = "https://files.pythonhosted.org/packages/45/cf/2c2fc6bb5874158277b4faf136847f0689e1b1a1f640a36d76d52e78907c/contourpy-1.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:303c252947ab4b14c08afeb52375b26781ccd6a5ccd81abcdfc1fafd14cf93c1", size = 319118, upload-time = "2024-08-27T20:51:44.717Z" }, { url = "https://files.pythonhosted.org/packages/03/33/003065374f38894cdf1040cef474ad0546368eea7e3a51d48b8a423961f8/contourpy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637f674226be46f6ba372fd29d9523dd977a291f66ab2a74fbeb5530bb3f445d", size = 323162, upload-time = "2024-08-27T20:51:49.683Z" }, { url = "https://files.pythonhosted.org/packages/42/80/e637326e85e4105a802e42959f56cff2cd39a6b5ef68d5d9aee3ea5f0e4c/contourpy-1.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:76a896b2f195b57db25d6b44e7e03f221d32fe318d03ede41f8b4d9ba1bff53c", size = 1265396, upload-time = "2024-08-27T20:52:04.926Z" }, { url = "https://files.pythonhosted.org/packages/7c/3b/8cbd6416ca1bbc0202b50f9c13b2e0b922b64be888f9d9ee88e6cfabfb51/contourpy-1.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e1fd23e9d01591bab45546c089ae89d926917a66dceb3abcf01f6105d927e2cb", size = 1324297, upload-time = "2024-08-27T20:52:21.843Z" }, { url = "https://files.pythonhosted.org/packages/4d/2c/021a7afaa52fe891f25535506cc861c30c3c4e5a1c1ce94215e04b293e72/contourpy-1.3.0-cp311-cp311-win32.whl", hash = "sha256:d402880b84df3bec6eab53cd0cf802cae6a2ef9537e70cf75e91618a3801c20c", size = 171808, upload-time = "2024-08-27T20:52:25.163Z" }, { url = "https://files.pythonhosted.org/packages/8d/2f/804f02ff30a7fae21f98198828d0857439ec4c91a96e20cf2d6c49372966/contourpy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:6cb6cc968059db9c62cb35fbf70248f40994dfcd7aa10444bbf8b3faeb7c2d67", size = 217181, upload-time = "2024-08-27T20:52:29.13Z" }, { url = "https://files.pythonhosted.org/packages/c9/92/8e0bbfe6b70c0e2d3d81272b58c98ac69ff1a4329f18c73bd64824d8b12e/contourpy-1.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:570ef7cf892f0afbe5b2ee410c507ce12e15a5fa91017a0009f79f7d93a1268f", size = 267838, upload-time = "2024-08-27T20:52:33.911Z" }, { url = "https://files.pythonhosted.org/packages/e3/04/33351c5d5108460a8ce6d512307690b023f0cfcad5899499f5c83b9d63b1/contourpy-1.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:da84c537cb8b97d153e9fb208c221c45605f73147bd4cadd23bdae915042aad6", size = 251549, upload-time = "2024-08-27T20:52:39.179Z" }, { url = "https://files.pythonhosted.org/packages/51/3d/aa0fe6ae67e3ef9f178389e4caaaa68daf2f9024092aa3c6032e3d174670/contourpy-1.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0be4d8425bfa755e0fd76ee1e019636ccc7c29f77a7c86b4328a9eb6a26d0639", size = 303177, upload-time = "2024-08-27T20:52:44.789Z" }, { url = "https://files.pythonhosted.org/packages/56/c3/c85a7e3e0cab635575d3b657f9535443a6f5d20fac1a1911eaa4bbe1aceb/contourpy-1.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c0da700bf58f6e0b65312d0a5e695179a71d0163957fa381bb3c1f72972537c", size = 341735, upload-time = "2024-08-27T20:52:51.05Z" }, { url = "https://files.pythonhosted.org/packages/dd/8d/20f7a211a7be966a53f474bc90b1a8202e9844b3f1ef85f3ae45a77151ee/contourpy-1.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb8b141bb00fa977d9122636b16aa67d37fd40a3d8b52dd837e536d64b9a4d06", size = 314679, upload-time = "2024-08-27T20:52:58.473Z" }, { url = "https://files.pythonhosted.org/packages/6e/be/524e377567defac0e21a46e2a529652d165fed130a0d8a863219303cee18/contourpy-1.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3634b5385c6716c258d0419c46d05c8aa7dc8cb70326c9a4fb66b69ad2b52e09", size = 320549, upload-time = "2024-08-27T20:53:06.593Z" }, { url = "https://files.pythonhosted.org/packages/0f/96/fdb2552a172942d888915f3a6663812e9bc3d359d53dafd4289a0fb462f0/contourpy-1.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0dce35502151b6bd35027ac39ba6e5a44be13a68f55735c3612c568cac3805fd", size = 1263068, upload-time = "2024-08-27T20:53:23.442Z" }, { url = "https://files.pythonhosted.org/packages/2a/25/632eab595e3140adfa92f1322bf8915f68c932bac468e89eae9974cf1c00/contourpy-1.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea348f053c645100612b333adc5983d87be69acdc6d77d3169c090d3b01dc35", size = 1322833, upload-time = "2024-08-27T20:53:39.243Z" }, { url = "https://files.pythonhosted.org/packages/73/e3/69738782e315a1d26d29d71a550dbbe3eb6c653b028b150f70c1a5f4f229/contourpy-1.3.0-cp312-cp312-win32.whl", hash = "sha256:90f73a5116ad1ba7174341ef3ea5c3150ddf20b024b98fb0c3b29034752c8aeb", size = 172681, upload-time = "2024-08-27T20:53:43.05Z" }, { url = "https://files.pythonhosted.org/packages/0c/89/9830ba00d88e43d15e53d64931e66b8792b46eb25e2050a88fec4a0df3d5/contourpy-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:b11b39aea6be6764f84360fce6c82211a9db32a7c7de8fa6dd5397cf1d079c3b", size = 218283, upload-time = "2024-08-27T20:53:47.232Z" }, { url = "https://files.pythonhosted.org/packages/53/a1/d20415febfb2267af2d7f06338e82171824d08614084714fb2c1dac9901f/contourpy-1.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3e1c7fa44aaae40a2247e2e8e0627f4bea3dd257014764aa644f319a5f8600e3", size = 267879, upload-time = "2024-08-27T20:53:51.597Z" }, { url = "https://files.pythonhosted.org/packages/aa/45/5a28a3570ff6218d8bdfc291a272a20d2648104815f01f0177d103d985e1/contourpy-1.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:364174c2a76057feef647c802652f00953b575723062560498dc7930fc9b1cb7", size = 251573, upload-time = "2024-08-27T20:53:55.659Z" }, { url = "https://files.pythonhosted.org/packages/39/1c/d3f51540108e3affa84f095c8b04f0aa833bb797bc8baa218a952a98117d/contourpy-1.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b238b3b3b649e09ce9aaf51f0c261d38644bdfa35cbaf7b263457850957a84", size = 303184, upload-time = "2024-08-27T20:54:00.225Z" }, { url = "https://files.pythonhosted.org/packages/00/56/1348a44fb6c3a558c1a3a0cd23d329d604c99d81bf5a4b58c6b71aab328f/contourpy-1.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d51fca85f9f7ad0b65b4b9fe800406d0d77017d7270d31ec3fb1cc07358fdea0", size = 340262, upload-time = "2024-08-27T20:54:05.234Z" }, { url = "https://files.pythonhosted.org/packages/2b/23/00d665ba67e1bb666152131da07e0f24c95c3632d7722caa97fb61470eca/contourpy-1.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:732896af21716b29ab3e988d4ce14bc5133733b85956316fb0c56355f398099b", size = 313806, upload-time = "2024-08-27T20:54:09.889Z" }, { url = "https://files.pythonhosted.org/packages/5a/42/3cf40f7040bb8362aea19af9a5fb7b32ce420f645dd1590edcee2c657cd5/contourpy-1.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d73f659398a0904e125280836ae6f88ba9b178b2fed6884f3b1f95b989d2c8da", size = 319710, upload-time = "2024-08-27T20:54:14.536Z" }, { url = "https://files.pythonhosted.org/packages/05/32/f3bfa3fc083b25e1a7ae09197f897476ee68e7386e10404bdf9aac7391f0/contourpy-1.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c6c7c2408b7048082932cf4e641fa3b8ca848259212f51c8c59c45aa7ac18f14", size = 1264107, upload-time = "2024-08-27T20:54:29.735Z" }, { url = "https://files.pythonhosted.org/packages/1c/1e/1019d34473a736664f2439542b890b2dc4c6245f5c0d8cdfc0ccc2cab80c/contourpy-1.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f317576606de89da6b7e0861cf6061f6146ead3528acabff9236458a6ba467f8", size = 1322458, upload-time = "2024-08-27T20:54:45.507Z" }, { url = "https://files.pythonhosted.org/packages/22/85/4f8bfd83972cf8909a4d36d16b177f7b8bdd942178ea4bf877d4a380a91c/contourpy-1.3.0-cp313-cp313-win32.whl", hash = "sha256:31cd3a85dbdf1fc002280c65caa7e2b5f65e4a973fcdf70dd2fdcb9868069294", size = 172643, upload-time = "2024-08-27T20:55:52.754Z" }, { url = "https://files.pythonhosted.org/packages/cc/4a/fb3c83c1baba64ba90443626c228ca14f19a87c51975d3b1de308dd2cf08/contourpy-1.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4553c421929ec95fb07b3aaca0fae668b2eb5a5203d1217ca7c34c063c53d087", size = 218301, upload-time = "2024-08-27T20:55:56.509Z" }, { url = "https://files.pythonhosted.org/packages/76/65/702f4064f397821fea0cb493f7d3bc95a5d703e20954dce7d6d39bacf378/contourpy-1.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:345af746d7766821d05d72cb8f3845dfd08dd137101a2cb9b24de277d716def8", size = 278972, upload-time = "2024-08-27T20:54:50.347Z" }, { url = "https://files.pythonhosted.org/packages/80/85/21f5bba56dba75c10a45ec00ad3b8190dbac7fd9a8a8c46c6116c933e9cf/contourpy-1.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3bb3808858a9dc68f6f03d319acd5f1b8a337e6cdda197f02f4b8ff67ad2057b", size = 263375, upload-time = "2024-08-27T20:54:54.909Z" }, { url = "https://files.pythonhosted.org/packages/0a/64/084c86ab71d43149f91ab3a4054ccf18565f0a8af36abfa92b1467813ed6/contourpy-1.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:420d39daa61aab1221567b42eecb01112908b2cab7f1b4106a52caaec8d36973", size = 307188, upload-time = "2024-08-27T20:55:00.184Z" }, { url = "https://files.pythonhosted.org/packages/3d/ff/d61a4c288dc42da0084b8d9dc2aa219a850767165d7d9a9c364ff530b509/contourpy-1.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d63ee447261e963af02642ffcb864e5a2ee4cbfd78080657a9880b8b1868e18", size = 345644, upload-time = "2024-08-27T20:55:05.673Z" }, { url = "https://files.pythonhosted.org/packages/ca/aa/00d2313d35ec03f188e8f0786c2fc61f589306e02fdc158233697546fd58/contourpy-1.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:167d6c890815e1dac9536dca00828b445d5d0df4d6a8c6adb4a7ec3166812fa8", size = 317141, upload-time = "2024-08-27T20:55:11.047Z" }, { url = "https://files.pythonhosted.org/packages/8d/6a/b5242c8cb32d87f6abf4f5e3044ca397cb1a76712e3fa2424772e3ff495f/contourpy-1.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:710a26b3dc80c0e4febf04555de66f5fd17e9cf7170a7b08000601a10570bda6", size = 323469, upload-time = "2024-08-27T20:55:15.914Z" }, { url = "https://files.pythonhosted.org/packages/6f/a6/73e929d43028a9079aca4bde107494864d54f0d72d9db508a51ff0878593/contourpy-1.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:75ee7cb1a14c617f34a51d11fa7524173e56551646828353c4af859c56b766e2", size = 1260894, upload-time = "2024-08-27T20:55:31.553Z" }, { url = "https://files.pythonhosted.org/packages/2b/1e/1e726ba66eddf21c940821df8cf1a7d15cb165f0682d62161eaa5e93dae1/contourpy-1.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:33c92cdae89ec5135d036e7218e69b0bb2851206077251f04a6c4e0e21f03927", size = 1314829, upload-time = "2024-08-27T20:55:47.837Z" }, { url = "https://files.pythonhosted.org/packages/b3/e3/b9f72758adb6ef7397327ceb8b9c39c75711affb220e4f53c745ea1d5a9a/contourpy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a11077e395f67ffc2c44ec2418cfebed032cd6da3022a94fc227b6faf8e2acb8", size = 265518, upload-time = "2024-08-27T20:56:01.333Z" }, { url = "https://files.pythonhosted.org/packages/ec/22/19f5b948367ab5260fb41d842c7a78dae645603881ea6bc39738bcfcabf6/contourpy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e8134301d7e204c88ed7ab50028ba06c683000040ede1d617298611f9dc6240c", size = 249350, upload-time = "2024-08-27T20:56:05.432Z" }, { url = "https://files.pythonhosted.org/packages/26/76/0c7d43263dd00ae21a91a24381b7e813d286a3294d95d179ef3a7b9fb1d7/contourpy-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e12968fdfd5bb45ffdf6192a590bd8ddd3ba9e58360b29683c6bb71a7b41edca", size = 309167, upload-time = "2024-08-27T20:56:10.034Z" }, { url = "https://files.pythonhosted.org/packages/96/3b/cadff6773e89f2a5a492c1a8068e21d3fccaf1a1c1df7d65e7c8e3ef60ba/contourpy-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fd2a0fc506eccaaa7595b7e1418951f213cf8255be2600f1ea1b61e46a60c55f", size = 348279, upload-time = "2024-08-27T20:56:15.41Z" }, { url = "https://files.pythonhosted.org/packages/e1/86/158cc43aa549d2081a955ab11c6bdccc7a22caacc2af93186d26f5f48746/contourpy-1.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfb5c62ce023dfc410d6059c936dcf96442ba40814aefbfa575425a3a7f19dc", size = 318519, upload-time = "2024-08-27T20:56:21.813Z" }, { url = "https://files.pythonhosted.org/packages/05/11/57335544a3027e9b96a05948c32e566328e3a2f84b7b99a325b7a06d2b06/contourpy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68a32389b06b82c2fdd68276148d7b9275b5f5cf13e5417e4252f6d1a34f72a2", size = 321922, upload-time = "2024-08-27T20:56:26.983Z" }, { url = "https://files.pythonhosted.org/packages/0b/e3/02114f96543f4a1b694333b92a6dcd4f8eebbefcc3a5f3bbb1316634178f/contourpy-1.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:94e848a6b83da10898cbf1311a815f770acc9b6a3f2d646f330d57eb4e87592e", size = 1258017, upload-time = "2024-08-27T20:56:42.246Z" }, { url = "https://files.pythonhosted.org/packages/f3/3b/bfe4c81c6d5881c1c643dde6620be0b42bf8aab155976dd644595cfab95c/contourpy-1.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d78ab28a03c854a873787a0a42254a0ccb3cb133c672f645c9f9c8f3ae9d0800", size = 1316773, upload-time = "2024-08-27T20:56:58.58Z" }, { url = "https://files.pythonhosted.org/packages/f1/17/c52d2970784383cafb0bd918b6fb036d98d96bbf0bc1befb5d1e31a07a70/contourpy-1.3.0-cp39-cp39-win32.whl", hash = "sha256:81cb5ed4952aae6014bc9d0421dec7c5835c9c8c31cdf51910b708f548cf58e5", size = 171353, upload-time = "2024-08-27T20:57:02.718Z" }, { url = "https://files.pythonhosted.org/packages/53/23/db9f69676308e094d3c45f20cc52e12d10d64f027541c995d89c11ad5c75/contourpy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:14e262f67bd7e6eb6880bc564dcda30b15e351a594657e55b7eec94b6ef72843", size = 211817, upload-time = "2024-08-27T20:57:06.328Z" }, { url = "https://files.pythonhosted.org/packages/d1/09/60e486dc2b64c94ed33e58dcfb6f808192c03dfc5574c016218b9b7680dc/contourpy-1.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fe41b41505a5a33aeaed2a613dccaeaa74e0e3ead6dd6fd3a118fb471644fd6c", size = 261886, upload-time = "2024-08-27T20:57:10.863Z" }, { url = "https://files.pythonhosted.org/packages/19/20/b57f9f7174fcd439a7789fb47d764974ab646fa34d1790551de386457a8e/contourpy-1.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca7e17a65f72a5133bdbec9ecf22401c62bcf4821361ef7811faee695799779", size = 311008, upload-time = "2024-08-27T20:57:15.588Z" }, { url = "https://files.pythonhosted.org/packages/74/fc/5040d42623a1845d4f17a418e590fd7a79ae8cb2bad2b2f83de63c3bdca4/contourpy-1.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ec4dc6bf570f5b22ed0d7efba0dfa9c5b9e0431aeea7581aa217542d9e809a4", size = 215690, upload-time = "2024-08-27T20:57:19.321Z" }, { url = "https://files.pythonhosted.org/packages/2b/24/dc3dcd77ac7460ab7e9d2b01a618cb31406902e50e605a8d6091f0a8f7cc/contourpy-1.3.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:00ccd0dbaad6d804ab259820fa7cb0b8036bda0686ef844d24125d8287178ce0", size = 261894, upload-time = "2024-08-27T20:57:23.873Z" }, { url = "https://files.pythonhosted.org/packages/b1/db/531642a01cfec39d1682e46b5457b07cf805e3c3c584ec27e2a6223f8f6c/contourpy-1.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ca947601224119117f7c19c9cdf6b3ab54c5726ef1d906aa4a69dfb6dd58102", size = 311099, upload-time = "2024-08-27T20:57:28.58Z" }, { url = "https://files.pythonhosted.org/packages/38/1e/94bda024d629f254143a134eead69e21c836429a2a6ce82209a00ddcb79a/contourpy-1.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6ec93afeb848a0845a18989da3beca3eec2c0f852322efe21af1931147d12cb", size = 215838, upload-time = "2024-08-27T20:57:32.913Z" }, ] [[package]] name = "contourpy" version = "1.3.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", ] dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/12/a3/da4153ec8fe25d263aa48c1a4cbde7f49b59af86f0b6f7862788c60da737/contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934", size = 268551, upload-time = "2025-04-15T17:34:46.581Z" }, { url = "https://files.pythonhosted.org/packages/2f/6c/330de89ae1087eb622bfca0177d32a7ece50c3ef07b28002de4757d9d875/contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc41ba0714aa2968d1f8674ec97504a8f7e334f48eeacebcaa6256213acb0989", size = 253399, upload-time = "2025-04-15T17:34:51.427Z" }, { url = "https://files.pythonhosted.org/packages/c1/bd/20c6726b1b7f81a8bee5271bed5c165f0a8e1f572578a9d27e2ccb763cb2/contourpy-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9be002b31c558d1ddf1b9b415b162c603405414bacd6932d031c5b5a8b757f0d", size = 312061, upload-time = "2025-04-15T17:34:55.961Z" }, { url = "https://files.pythonhosted.org/packages/22/fc/a9665c88f8a2473f823cf1ec601de9e5375050f1958cbb356cdf06ef1ab6/contourpy-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2e74acbcba3bfdb6d9d8384cdc4f9260cae86ed9beee8bd5f54fee49a430b9", size = 351956, upload-time = "2025-04-15T17:35:00.992Z" }, { url = "https://files.pythonhosted.org/packages/25/eb/9f0a0238f305ad8fb7ef42481020d6e20cf15e46be99a1fcf939546a177e/contourpy-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e259bced5549ac64410162adc973c5e2fb77f04df4a439d00b478e57a0e65512", size = 320872, upload-time = "2025-04-15T17:35:06.177Z" }, { url = "https://files.pythonhosted.org/packages/32/5c/1ee32d1c7956923202f00cf8d2a14a62ed7517bdc0ee1e55301227fc273c/contourpy-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad687a04bc802cbe8b9c399c07162a3c35e227e2daccf1668eb1f278cb698631", size = 325027, upload-time = "2025-04-15T17:35:11.244Z" }, { url = "https://files.pythonhosted.org/packages/83/bf/9baed89785ba743ef329c2b07fd0611d12bfecbedbdd3eeecf929d8d3b52/contourpy-1.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cdd22595308f53ef2f891040ab2b93d79192513ffccbd7fe19be7aa773a5e09f", size = 1306641, upload-time = "2025-04-15T17:35:26.701Z" }, { url = "https://files.pythonhosted.org/packages/d4/cc/74e5e83d1e35de2d28bd97033426b450bc4fd96e092a1f7a63dc7369b55d/contourpy-1.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4f54d6a2defe9f257327b0f243612dd051cc43825587520b1bf74a31e2f6ef2", size = 1374075, upload-time = "2025-04-15T17:35:43.204Z" }, { url = "https://files.pythonhosted.org/packages/0c/42/17f3b798fd5e033b46a16f8d9fcb39f1aba051307f5ebf441bad1ecf78f8/contourpy-1.3.2-cp310-cp310-win32.whl", hash = "sha256:f939a054192ddc596e031e50bb13b657ce318cf13d264f095ce9db7dc6ae81c0", size = 177534, upload-time = "2025-04-15T17:35:46.554Z" }, { url = "https://files.pythonhosted.org/packages/54/ec/5162b8582f2c994721018d0c9ece9dc6ff769d298a8ac6b6a652c307e7df/contourpy-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c440093bbc8fc21c637c03bafcbef95ccd963bc6e0514ad887932c18ca2a759a", size = 221188, upload-time = "2025-04-15T17:35:50.064Z" }, { url = "https://files.pythonhosted.org/packages/b3/b9/ede788a0b56fc5b071639d06c33cb893f68b1178938f3425debebe2dab78/contourpy-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a37a2fb93d4df3fc4c0e363ea4d16f83195fc09c891bc8ce072b9d084853445", size = 269636, upload-time = "2025-04-15T17:35:54.473Z" }, { url = "https://files.pythonhosted.org/packages/e6/75/3469f011d64b8bbfa04f709bfc23e1dd71be54d05b1b083be9f5b22750d1/contourpy-1.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7cd50c38f500bbcc9b6a46643a40e0913673f869315d8e70de0438817cb7773", size = 254636, upload-time = "2025-04-15T17:35:58.283Z" }, { url = "https://files.pythonhosted.org/packages/8d/2f/95adb8dae08ce0ebca4fd8e7ad653159565d9739128b2d5977806656fcd2/contourpy-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6658ccc7251a4433eebd89ed2672c2ed96fba367fd25ca9512aa92a4b46c4f1", size = 313053, upload-time = "2025-04-15T17:36:03.235Z" }, { url = "https://files.pythonhosted.org/packages/c3/a6/8ccf97a50f31adfa36917707fe39c9a0cbc24b3bbb58185577f119736cc9/contourpy-1.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:70771a461aaeb335df14deb6c97439973d253ae70660ca085eec25241137ef43", size = 352985, upload-time = "2025-04-15T17:36:08.275Z" }, { url = "https://files.pythonhosted.org/packages/1d/b6/7925ab9b77386143f39d9c3243fdd101621b4532eb126743201160ffa7e6/contourpy-1.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a887a6e8c4cd0897507d814b14c54a8c2e2aa4ac9f7686292f9769fcf9a6ab", size = 323750, upload-time = "2025-04-15T17:36:13.29Z" }, { url = "https://files.pythonhosted.org/packages/c2/f3/20c5d1ef4f4748e52d60771b8560cf00b69d5c6368b5c2e9311bcfa2a08b/contourpy-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3859783aefa2b8355697f16642695a5b9792e7a46ab86da1118a4a23a51a33d7", size = 326246, upload-time = "2025-04-15T17:36:18.329Z" }, { url = "https://files.pythonhosted.org/packages/8c/e5/9dae809e7e0b2d9d70c52b3d24cba134dd3dad979eb3e5e71f5df22ed1f5/contourpy-1.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:eab0f6db315fa4d70f1d8ab514e527f0366ec021ff853d7ed6a2d33605cf4b83", size = 1308728, upload-time = "2025-04-15T17:36:33.878Z" }, { url = "https://files.pythonhosted.org/packages/e2/4a/0058ba34aeea35c0b442ae61a4f4d4ca84d6df8f91309bc2d43bb8dd248f/contourpy-1.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d91a3ccc7fea94ca0acab82ceb77f396d50a1f67412efe4c526f5d20264e6ecd", size = 1375762, upload-time = "2025-04-15T17:36:51.295Z" }, { url = "https://files.pythonhosted.org/packages/09/33/7174bdfc8b7767ef2c08ed81244762d93d5c579336fc0b51ca57b33d1b80/contourpy-1.3.2-cp311-cp311-win32.whl", hash = "sha256:1c48188778d4d2f3d48e4643fb15d8608b1d01e4b4d6b0548d9b336c28fc9b6f", size = 178196, upload-time = "2025-04-15T17:36:55.002Z" }, { url = "https://files.pythonhosted.org/packages/5e/fe/4029038b4e1c4485cef18e480b0e2cd2d755448bb071eb9977caac80b77b/contourpy-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:5ebac872ba09cb8f2131c46b8739a7ff71de28a24c869bcad554477eb089a878", size = 222017, upload-time = "2025-04-15T17:36:58.576Z" }, { url = "https://files.pythonhosted.org/packages/34/f7/44785876384eff370c251d58fd65f6ad7f39adce4a093c934d4a67a7c6b6/contourpy-1.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4caf2bcd2969402bf77edc4cb6034c7dd7c0803213b3523f111eb7460a51b8d2", size = 271580, upload-time = "2025-04-15T17:37:03.105Z" }, { url = "https://files.pythonhosted.org/packages/93/3b/0004767622a9826ea3d95f0e9d98cd8729015768075d61f9fea8eeca42a8/contourpy-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82199cb78276249796419fe36b7386bd8d2cc3f28b3bc19fe2454fe2e26c4c15", size = 255530, upload-time = "2025-04-15T17:37:07.026Z" }, { url = "https://files.pythonhosted.org/packages/e7/bb/7bd49e1f4fa805772d9fd130e0d375554ebc771ed7172f48dfcd4ca61549/contourpy-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106fab697af11456fcba3e352ad50effe493a90f893fca6c2ca5c033820cea92", size = 307688, upload-time = "2025-04-15T17:37:11.481Z" }, { url = "https://files.pythonhosted.org/packages/fc/97/e1d5dbbfa170725ef78357a9a0edc996b09ae4af170927ba8ce977e60a5f/contourpy-1.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d14f12932a8d620e307f715857107b1d1845cc44fdb5da2bc8e850f5ceba9f87", size = 347331, upload-time = "2025-04-15T17:37:18.212Z" }, { url = "https://files.pythonhosted.org/packages/6f/66/e69e6e904f5ecf6901be3dd16e7e54d41b6ec6ae3405a535286d4418ffb4/contourpy-1.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:532fd26e715560721bb0d5fc7610fce279b3699b018600ab999d1be895b09415", size = 318963, upload-time = "2025-04-15T17:37:22.76Z" }, { url = "https://files.pythonhosted.org/packages/a8/32/b8a1c8965e4f72482ff2d1ac2cd670ce0b542f203c8e1d34e7c3e6925da7/contourpy-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b383144cf2d2c29f01a1e8170f50dacf0eac02d64139dcd709a8ac4eb3cfe", size = 323681, upload-time = "2025-04-15T17:37:33.001Z" }, { url = "https://files.pythonhosted.org/packages/30/c6/12a7e6811d08757c7162a541ca4c5c6a34c0f4e98ef2b338791093518e40/contourpy-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49f73e61f1f774650a55d221803b101d966ca0c5a2d6d5e4320ec3997489441", size = 1308674, upload-time = "2025-04-15T17:37:48.64Z" }, { url = "https://files.pythonhosted.org/packages/2a/8a/bebe5a3f68b484d3a2b8ffaf84704b3e343ef1addea528132ef148e22b3b/contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e", size = 1380480, upload-time = "2025-04-15T17:38:06.7Z" }, { url = "https://files.pythonhosted.org/packages/34/db/fcd325f19b5978fb509a7d55e06d99f5f856294c1991097534360b307cf1/contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912", size = 178489, upload-time = "2025-04-15T17:38:10.338Z" }, { url = "https://files.pythonhosted.org/packages/01/c8/fadd0b92ffa7b5eb5949bf340a63a4a496a6930a6c37a7ba0f12acb076d6/contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73", size = 223042, upload-time = "2025-04-15T17:38:14.239Z" }, { url = "https://files.pythonhosted.org/packages/2e/61/5673f7e364b31e4e7ef6f61a4b5121c5f170f941895912f773d95270f3a2/contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb", size = 271630, upload-time = "2025-04-15T17:38:19.142Z" }, { url = "https://files.pythonhosted.org/packages/ff/66/a40badddd1223822c95798c55292844b7e871e50f6bfd9f158cb25e0bd39/contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08", size = 255670, upload-time = "2025-04-15T17:38:23.688Z" }, { url = "https://files.pythonhosted.org/packages/1e/c7/cf9fdee8200805c9bc3b148f49cb9482a4e3ea2719e772602a425c9b09f8/contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c", size = 306694, upload-time = "2025-04-15T17:38:28.238Z" }, { url = "https://files.pythonhosted.org/packages/dd/e7/ccb9bec80e1ba121efbffad7f38021021cda5be87532ec16fd96533bb2e0/contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f", size = 345986, upload-time = "2025-04-15T17:38:33.502Z" }, { url = "https://files.pythonhosted.org/packages/dc/49/ca13bb2da90391fa4219fdb23b078d6065ada886658ac7818e5441448b78/contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85", size = 318060, upload-time = "2025-04-15T17:38:38.672Z" }, { url = "https://files.pythonhosted.org/packages/c8/65/5245ce8c548a8422236c13ffcdcdada6a2a812c361e9e0c70548bb40b661/contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841", size = 322747, upload-time = "2025-04-15T17:38:43.712Z" }, { url = "https://files.pythonhosted.org/packages/72/30/669b8eb48e0a01c660ead3752a25b44fdb2e5ebc13a55782f639170772f9/contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422", size = 1308895, upload-time = "2025-04-15T17:39:00.224Z" }, { url = "https://files.pythonhosted.org/packages/05/5a/b569f4250decee6e8d54498be7bdf29021a4c256e77fe8138c8319ef8eb3/contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef", size = 1379098, upload-time = "2025-04-15T17:43:29.649Z" }, { url = "https://files.pythonhosted.org/packages/19/ba/b227c3886d120e60e41b28740ac3617b2f2b971b9f601c835661194579f1/contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f", size = 178535, upload-time = "2025-04-15T17:44:44.532Z" }, { url = "https://files.pythonhosted.org/packages/12/6e/2fed56cd47ca739b43e892707ae9a13790a486a3173be063681ca67d2262/contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9", size = 223096, upload-time = "2025-04-15T17:44:48.194Z" }, { url = "https://files.pythonhosted.org/packages/54/4c/e76fe2a03014a7c767d79ea35c86a747e9325537a8b7627e0e5b3ba266b4/contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f", size = 285090, upload-time = "2025-04-15T17:43:34.084Z" }, { url = "https://files.pythonhosted.org/packages/7b/e2/5aba47debd55d668e00baf9651b721e7733975dc9fc27264a62b0dd26eb8/contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739", size = 268643, upload-time = "2025-04-15T17:43:38.626Z" }, { url = "https://files.pythonhosted.org/packages/a1/37/cd45f1f051fe6230f751cc5cdd2728bb3a203f5619510ef11e732109593c/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823", size = 310443, upload-time = "2025-04-15T17:43:44.522Z" }, { url = "https://files.pythonhosted.org/packages/8b/a2/36ea6140c306c9ff6dd38e3bcec80b3b018474ef4d17eb68ceecd26675f4/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5", size = 349865, upload-time = "2025-04-15T17:43:49.545Z" }, { url = "https://files.pythonhosted.org/packages/95/b7/2fc76bc539693180488f7b6cc518da7acbbb9e3b931fd9280504128bf956/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532", size = 321162, upload-time = "2025-04-15T17:43:54.203Z" }, { url = "https://files.pythonhosted.org/packages/f4/10/76d4f778458b0aa83f96e59d65ece72a060bacb20cfbee46cf6cd5ceba41/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b", size = 327355, upload-time = "2025-04-15T17:44:01.025Z" }, { url = "https://files.pythonhosted.org/packages/43/a3/10cf483ea683f9f8ab096c24bad3cce20e0d1dd9a4baa0e2093c1c962d9d/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52", size = 1307935, upload-time = "2025-04-15T17:44:17.322Z" }, { url = "https://files.pythonhosted.org/packages/78/73/69dd9a024444489e22d86108e7b913f3528f56cfc312b5c5727a44188471/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd", size = 1372168, upload-time = "2025-04-15T17:44:33.43Z" }, { url = "https://files.pythonhosted.org/packages/0f/1b/96d586ccf1b1a9d2004dd519b25fbf104a11589abfd05484ff12199cca21/contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1", size = 189550, upload-time = "2025-04-15T17:44:37.092Z" }, { url = "https://files.pythonhosted.org/packages/b0/e6/6000d0094e8a5e32ad62591c8609e269febb6e4db83a1c75ff8868b42731/contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69", size = 238214, upload-time = "2025-04-15T17:44:40.827Z" }, { url = "https://files.pythonhosted.org/packages/33/05/b26e3c6ecc05f349ee0013f0bb850a761016d89cec528a98193a48c34033/contourpy-1.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fd93cc7f3139b6dd7aab2f26a90dde0aa9fc264dbf70f6740d498a70b860b82c", size = 265681, upload-time = "2025-04-15T17:44:59.314Z" }, { url = "https://files.pythonhosted.org/packages/2b/25/ac07d6ad12affa7d1ffed11b77417d0a6308170f44ff20fa1d5aa6333f03/contourpy-1.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:107ba8a6a7eec58bb475329e6d3b95deba9440667c4d62b9b6063942b61d7f16", size = 315101, upload-time = "2025-04-15T17:45:04.165Z" }, { url = "https://files.pythonhosted.org/packages/8f/4d/5bb3192bbe9d3f27e3061a6a8e7733c9120e203cb8515767d30973f71030/contourpy-1.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ded1706ed0c1049224531b81128efbd5084598f18d8a2d9efae833edbd2b40ad", size = 220599, upload-time = "2025-04-15T17:45:08.456Z" }, { url = "https://files.pythonhosted.org/packages/ff/c0/91f1215d0d9f9f343e4773ba6c9b89e8c0cc7a64a6263f21139da639d848/contourpy-1.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5f5964cdad279256c084b69c3f412b7801e15356b16efa9d78aa974041903da0", size = 266807, upload-time = "2025-04-15T17:45:15.535Z" }, { url = "https://files.pythonhosted.org/packages/d4/79/6be7e90c955c0487e7712660d6cead01fa17bff98e0ea275737cc2bc8e71/contourpy-1.3.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49b65a95d642d4efa8f64ba12558fcb83407e58a2dfba9d796d77b63ccfcaff5", size = 318729, upload-time = "2025-04-15T17:45:20.166Z" }, { url = "https://files.pythonhosted.org/packages/87/68/7f46fb537958e87427d98a4074bcde4b67a70b04900cfc5ce29bc2f556c1/contourpy-1.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8c5acb8dddb0752bf252e01a3035b21443158910ac16a3b0d20e7fed7d534ce5", size = 221791, upload-time = "2025-04-15T17:45:24.794Z" }, ] [[package]] name = "contourpy" version = "1.3.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773, upload-time = "2025-07-26T12:01:02.277Z" }, { url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149, upload-time = "2025-07-26T12:01:04.072Z" }, { url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222, upload-time = "2025-07-26T12:01:05.688Z" }, { url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234, upload-time = "2025-07-26T12:01:07.054Z" }, { url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555, upload-time = "2025-07-26T12:01:08.801Z" }, { url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238, upload-time = "2025-07-26T12:01:10.319Z" }, { url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218, upload-time = "2025-07-26T12:01:12.659Z" }, { url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867, upload-time = "2025-07-26T12:01:15.533Z" }, { url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff", size = 183677, upload-time = "2025-07-26T12:01:17.088Z" }, { url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42", size = 225234, upload-time = "2025-07-26T12:01:18.256Z" }, { url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470", size = 193123, upload-time = "2025-07-26T12:01:19.848Z" }, { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" }, { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" }, { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" }, { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" }, { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" }, { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" }, { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" }, { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" }, { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" }, { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" }, { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" }, { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z" }, { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z" }, { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z" }, { url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207, upload-time = "2025-07-26T12:02:57.468Z" }, { url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77", size = 225315, upload-time = "2025-07-26T12:02:58.801Z" }, ] [[package]] name = "coverage" version = "7.10.7" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/51/26/d22c300112504f5f9a9fd2297ce33c35f3d353e4aeb987c8419453b2a7c2/coverage-7.10.7.tar.gz", hash = "sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239", size = 827704, upload-time = "2025-09-21T20:03:56.815Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e5/6c/3a3f7a46888e69d18abe3ccc6fe4cb16cccb1e6a2f99698931dafca489e6/coverage-7.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a", size = 217987, upload-time = "2025-09-21T20:00:57.218Z" }, { url = "https://files.pythonhosted.org/packages/03/94/952d30f180b1a916c11a56f5c22d3535e943aa22430e9e3322447e520e1c/coverage-7.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5", size = 218388, upload-time = "2025-09-21T20:01:00.081Z" }, { url = "https://files.pythonhosted.org/packages/50/2b/9e0cf8ded1e114bcd8b2fd42792b57f1c4e9e4ea1824cde2af93a67305be/coverage-7.10.7-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:240af60539987ced2c399809bd34f7c78e8abe0736af91c3d7d0e795df633d17", size = 245148, upload-time = "2025-09-21T20:01:01.768Z" }, { url = "https://files.pythonhosted.org/packages/19/20/d0384ac06a6f908783d9b6aa6135e41b093971499ec488e47279f5b846e6/coverage-7.10.7-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8421e088bc051361b01c4b3a50fd39a4b9133079a2229978d9d30511fd05231b", size = 246958, upload-time = "2025-09-21T20:01:03.355Z" }, { url = "https://files.pythonhosted.org/packages/60/83/5c283cff3d41285f8eab897651585db908a909c572bdc014bcfaf8a8b6ae/coverage-7.10.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be8ed3039ae7f7ac5ce058c308484787c86e8437e72b30bf5e88b8ea10f3c87", size = 248819, upload-time = "2025-09-21T20:01:04.968Z" }, { url = "https://files.pythonhosted.org/packages/60/22/02eb98fdc5ff79f423e990d877693e5310ae1eab6cb20ae0b0b9ac45b23b/coverage-7.10.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e28299d9f2e889e6d51b1f043f58d5f997c373cc12e6403b90df95b8b047c13e", size = 245754, upload-time = "2025-09-21T20:01:06.321Z" }, { url = "https://files.pythonhosted.org/packages/b4/bc/25c83bcf3ad141b32cd7dc45485ef3c01a776ca3aa8ef0a93e77e8b5bc43/coverage-7.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c4e16bd7761c5e454f4efd36f345286d6f7c5fa111623c355691e2755cae3b9e", size = 246860, upload-time = "2025-09-21T20:01:07.605Z" }, { url = "https://files.pythonhosted.org/packages/3c/b7/95574702888b58c0928a6e982038c596f9c34d52c5e5107f1eef729399b5/coverage-7.10.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b1c81d0e5e160651879755c9c675b974276f135558cf4ba79fee7b8413a515df", size = 244877, upload-time = "2025-09-21T20:01:08.829Z" }, { url = "https://files.pythonhosted.org/packages/47/b6/40095c185f235e085df0e0b158f6bd68cc6e1d80ba6c7721dc81d97ec318/coverage-7.10.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:606cc265adc9aaedcc84f1f064f0e8736bc45814f15a357e30fca7ecc01504e0", size = 245108, upload-time = "2025-09-21T20:01:10.527Z" }, { url = "https://files.pythonhosted.org/packages/c8/50/4aea0556da7a4b93ec9168420d170b55e2eb50ae21b25062513d020c6861/coverage-7.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:10b24412692df990dbc34f8fb1b6b13d236ace9dfdd68df5b28c2e39cafbba13", size = 245752, upload-time = "2025-09-21T20:01:11.857Z" }, { url = "https://files.pythonhosted.org/packages/6a/28/ea1a84a60828177ae3b100cb6723838523369a44ec5742313ed7db3da160/coverage-7.10.7-cp310-cp310-win32.whl", hash = "sha256:b51dcd060f18c19290d9b8a9dd1e0181538df2ce0717f562fff6cf74d9fc0b5b", size = 220497, upload-time = "2025-09-21T20:01:13.459Z" }, { url = "https://files.pythonhosted.org/packages/fc/1a/a81d46bbeb3c3fd97b9602ebaa411e076219a150489bcc2c025f151bd52d/coverage-7.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:3a622ac801b17198020f09af3eaf45666b344a0d69fc2a6ffe2ea83aeef1d807", size = 221392, upload-time = "2025-09-21T20:01:14.722Z" }, { url = "https://files.pythonhosted.org/packages/d2/5d/c1a17867b0456f2e9ce2d8d4708a4c3a089947d0bec9c66cdf60c9e7739f/coverage-7.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59", size = 218102, upload-time = "2025-09-21T20:01:16.089Z" }, { url = "https://files.pythonhosted.org/packages/54/f0/514dcf4b4e3698b9a9077f084429681bf3aad2b4a72578f89d7f643eb506/coverage-7.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a", size = 218505, upload-time = "2025-09-21T20:01:17.788Z" }, { url = "https://files.pythonhosted.org/packages/20/f6/9626b81d17e2a4b25c63ac1b425ff307ecdeef03d67c9a147673ae40dc36/coverage-7.10.7-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699", size = 248898, upload-time = "2025-09-21T20:01:19.488Z" }, { url = "https://files.pythonhosted.org/packages/b0/ef/bd8e719c2f7417ba03239052e099b76ea1130ac0cbb183ee1fcaa58aaff3/coverage-7.10.7-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d", size = 250831, upload-time = "2025-09-21T20:01:20.817Z" }, { url = "https://files.pythonhosted.org/packages/a5/b6/bf054de41ec948b151ae2b79a55c107f5760979538f5fb80c195f2517718/coverage-7.10.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e", size = 252937, upload-time = "2025-09-21T20:01:22.171Z" }, { url = "https://files.pythonhosted.org/packages/0f/e5/3860756aa6f9318227443c6ce4ed7bf9e70bb7f1447a0353f45ac5c7974b/coverage-7.10.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23", size = 249021, upload-time = "2025-09-21T20:01:23.907Z" }, { url = "https://files.pythonhosted.org/packages/26/0f/bd08bd042854f7fd07b45808927ebcce99a7ed0f2f412d11629883517ac2/coverage-7.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab", size = 250626, upload-time = "2025-09-21T20:01:25.721Z" }, { url = "https://files.pythonhosted.org/packages/8e/a7/4777b14de4abcc2e80c6b1d430f5d51eb18ed1d75fca56cbce5f2db9b36e/coverage-7.10.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82", size = 248682, upload-time = "2025-09-21T20:01:27.105Z" }, { url = "https://files.pythonhosted.org/packages/34/72/17d082b00b53cd45679bad682fac058b87f011fd8b9fe31d77f5f8d3a4e4/coverage-7.10.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2", size = 248402, upload-time = "2025-09-21T20:01:28.629Z" }, { url = "https://files.pythonhosted.org/packages/81/7a/92367572eb5bdd6a84bfa278cc7e97db192f9f45b28c94a9ca1a921c3577/coverage-7.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61", size = 249320, upload-time = "2025-09-21T20:01:30.004Z" }, { url = "https://files.pythonhosted.org/packages/2f/88/a23cc185f6a805dfc4fdf14a94016835eeb85e22ac3a0e66d5e89acd6462/coverage-7.10.7-cp311-cp311-win32.whl", hash = "sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14", size = 220536, upload-time = "2025-09-21T20:01:32.184Z" }, { url = "https://files.pythonhosted.org/packages/fe/ef/0b510a399dfca17cec7bc2f05ad8bd78cf55f15c8bc9a73ab20c5c913c2e/coverage-7.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2", size = 221425, upload-time = "2025-09-21T20:01:33.557Z" }, { url = "https://files.pythonhosted.org/packages/51/7f/023657f301a276e4ba1850f82749bc136f5a7e8768060c2e5d9744a22951/coverage-7.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a", size = 220103, upload-time = "2025-09-21T20:01:34.929Z" }, { url = "https://files.pythonhosted.org/packages/13/e4/eb12450f71b542a53972d19117ea5a5cea1cab3ac9e31b0b5d498df1bd5a/coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417", size = 218290, upload-time = "2025-09-21T20:01:36.455Z" }, { url = "https://files.pythonhosted.org/packages/37/66/593f9be12fc19fb36711f19a5371af79a718537204d16ea1d36f16bd78d2/coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973", size = 218515, upload-time = "2025-09-21T20:01:37.982Z" }, { url = "https://files.pythonhosted.org/packages/66/80/4c49f7ae09cafdacc73fbc30949ffe77359635c168f4e9ff33c9ebb07838/coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c", size = 250020, upload-time = "2025-09-21T20:01:39.617Z" }, { url = "https://files.pythonhosted.org/packages/a6/90/a64aaacab3b37a17aaedd83e8000142561a29eb262cede42d94a67f7556b/coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7", size = 252769, upload-time = "2025-09-21T20:01:41.341Z" }, { url = "https://files.pythonhosted.org/packages/98/2e/2dda59afd6103b342e096f246ebc5f87a3363b5412609946c120f4e7750d/coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6", size = 253901, upload-time = "2025-09-21T20:01:43.042Z" }, { url = "https://files.pythonhosted.org/packages/53/dc/8d8119c9051d50f3119bb4a75f29f1e4a6ab9415cd1fa8bf22fcc3fb3b5f/coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59", size = 250413, upload-time = "2025-09-21T20:01:44.469Z" }, { url = "https://files.pythonhosted.org/packages/98/b3/edaff9c5d79ee4d4b6d3fe046f2b1d799850425695b789d491a64225d493/coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b", size = 251820, upload-time = "2025-09-21T20:01:45.915Z" }, { url = "https://files.pythonhosted.org/packages/11/25/9a0728564bb05863f7e513e5a594fe5ffef091b325437f5430e8cfb0d530/coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a", size = 249941, upload-time = "2025-09-21T20:01:47.296Z" }, { url = "https://files.pythonhosted.org/packages/e0/fd/ca2650443bfbef5b0e74373aac4df67b08180d2f184b482c41499668e258/coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb", size = 249519, upload-time = "2025-09-21T20:01:48.73Z" }, { url = "https://files.pythonhosted.org/packages/24/79/f692f125fb4299b6f963b0745124998ebb8e73ecdfce4ceceb06a8c6bec5/coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1", size = 251375, upload-time = "2025-09-21T20:01:50.529Z" }, { url = "https://files.pythonhosted.org/packages/5e/75/61b9bbd6c7d24d896bfeec57acba78e0f8deac68e6baf2d4804f7aae1f88/coverage-7.10.7-cp312-cp312-win32.whl", hash = "sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256", size = 220699, upload-time = "2025-09-21T20:01:51.941Z" }, { url = "https://files.pythonhosted.org/packages/ca/f3/3bf7905288b45b075918d372498f1cf845b5b579b723c8fd17168018d5f5/coverage-7.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba", size = 221512, upload-time = "2025-09-21T20:01:53.481Z" }, { url = "https://files.pythonhosted.org/packages/5c/44/3e32dbe933979d05cf2dac5e697c8599cfe038aaf51223ab901e208d5a62/coverage-7.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf", size = 220147, upload-time = "2025-09-21T20:01:55.2Z" }, { url = "https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d", size = 218320, upload-time = "2025-09-21T20:01:56.629Z" }, { url = "https://files.pythonhosted.org/packages/72/4f/732fff31c119bb73b35236dd333030f32c4bfe909f445b423e6c7594f9a2/coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b", size = 218575, upload-time = "2025-09-21T20:01:58.203Z" }, { url = "https://files.pythonhosted.org/packages/87/02/ae7e0af4b674be47566707777db1aa375474f02a1d64b9323e5813a6cdd5/coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e", size = 249568, upload-time = "2025-09-21T20:01:59.748Z" }, { url = "https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b", size = 252174, upload-time = "2025-09-21T20:02:01.192Z" }, { url = "https://files.pythonhosted.org/packages/b1/20/b6ea4f69bbb52dac0aebd62157ba6a9dddbfe664f5af8122dac296c3ee15/coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49", size = 253447, upload-time = "2025-09-21T20:02:02.701Z" }, { url = "https://files.pythonhosted.org/packages/f9/28/4831523ba483a7f90f7b259d2018fef02cb4d5b90bc7c1505d6e5a84883c/coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911", size = 249779, upload-time = "2025-09-21T20:02:04.185Z" }, { url = "https://files.pythonhosted.org/packages/a7/9f/4331142bc98c10ca6436d2d620c3e165f31e6c58d43479985afce6f3191c/coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0", size = 251604, upload-time = "2025-09-21T20:02:06.034Z" }, { url = "https://files.pythonhosted.org/packages/ce/60/bda83b96602036b77ecf34e6393a3836365481b69f7ed7079ab85048202b/coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f", size = 249497, upload-time = "2025-09-21T20:02:07.619Z" }, { url = "https://files.pythonhosted.org/packages/5f/af/152633ff35b2af63977edd835d8e6430f0caef27d171edf2fc76c270ef31/coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c", size = 249350, upload-time = "2025-09-21T20:02:10.34Z" }, { url = "https://files.pythonhosted.org/packages/9d/71/d92105d122bd21cebba877228990e1646d862e34a98bb3374d3fece5a794/coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f", size = 251111, upload-time = "2025-09-21T20:02:12.122Z" }, { url = "https://files.pythonhosted.org/packages/a2/9e/9fdb08f4bf476c912f0c3ca292e019aab6712c93c9344a1653986c3fd305/coverage-7.10.7-cp313-cp313-win32.whl", hash = "sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698", size = 220746, upload-time = "2025-09-21T20:02:13.919Z" }, { url = "https://files.pythonhosted.org/packages/b1/b1/a75fd25df44eab52d1931e89980d1ada46824c7a3210be0d3c88a44aaa99/coverage-7.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843", size = 221541, upload-time = "2025-09-21T20:02:15.57Z" }, { url = "https://files.pythonhosted.org/packages/14/3a/d720d7c989562a6e9a14b2c9f5f2876bdb38e9367126d118495b89c99c37/coverage-7.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546", size = 220170, upload-time = "2025-09-21T20:02:17.395Z" }, { url = "https://files.pythonhosted.org/packages/bb/22/e04514bf2a735d8b0add31d2b4ab636fc02370730787c576bb995390d2d5/coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c", size = 219029, upload-time = "2025-09-21T20:02:18.936Z" }, { url = "https://files.pythonhosted.org/packages/11/0b/91128e099035ece15da3445d9015e4b4153a6059403452d324cbb0a575fa/coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15", size = 219259, upload-time = "2025-09-21T20:02:20.44Z" }, { url = "https://files.pythonhosted.org/packages/8b/51/66420081e72801536a091a0c8f8c1f88a5c4bf7b9b1bdc6222c7afe6dc9b/coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4", size = 260592, upload-time = "2025-09-21T20:02:22.313Z" }, { url = "https://files.pythonhosted.org/packages/5d/22/9b8d458c2881b22df3db5bb3e7369e63d527d986decb6c11a591ba2364f7/coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0", size = 262768, upload-time = "2025-09-21T20:02:24.287Z" }, { url = "https://files.pythonhosted.org/packages/f7/08/16bee2c433e60913c610ea200b276e8eeef084b0d200bdcff69920bd5828/coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0", size = 264995, upload-time = "2025-09-21T20:02:26.133Z" }, { url = "https://files.pythonhosted.org/packages/20/9d/e53eb9771d154859b084b90201e5221bca7674ba449a17c101a5031d4054/coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65", size = 259546, upload-time = "2025-09-21T20:02:27.716Z" }, { url = "https://files.pythonhosted.org/packages/ad/b0/69bc7050f8d4e56a89fb550a1577d5d0d1db2278106f6f626464067b3817/coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541", size = 262544, upload-time = "2025-09-21T20:02:29.216Z" }, { url = "https://files.pythonhosted.org/packages/ef/4b/2514b060dbd1bc0aaf23b852c14bb5818f244c664cb16517feff6bb3a5ab/coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6", size = 260308, upload-time = "2025-09-21T20:02:31.226Z" }, { url = "https://files.pythonhosted.org/packages/54/78/7ba2175007c246d75e496f64c06e94122bdb914790a1285d627a918bd271/coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999", size = 258920, upload-time = "2025-09-21T20:02:32.823Z" }, { url = "https://files.pythonhosted.org/packages/c0/b3/fac9f7abbc841409b9a410309d73bfa6cfb2e51c3fada738cb607ce174f8/coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2", size = 261434, upload-time = "2025-09-21T20:02:34.86Z" }, { url = "https://files.pythonhosted.org/packages/ee/51/a03bec00d37faaa891b3ff7387192cef20f01604e5283a5fabc95346befa/coverage-7.10.7-cp313-cp313t-win32.whl", hash = "sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a", size = 221403, upload-time = "2025-09-21T20:02:37.034Z" }, { url = "https://files.pythonhosted.org/packages/53/22/3cf25d614e64bf6d8e59c7c669b20d6d940bb337bdee5900b9ca41c820bb/coverage-7.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb", size = 222469, upload-time = "2025-09-21T20:02:39.011Z" }, { url = "https://files.pythonhosted.org/packages/49/a1/00164f6d30d8a01c3c9c48418a7a5be394de5349b421b9ee019f380df2a0/coverage-7.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb", size = 220731, upload-time = "2025-09-21T20:02:40.939Z" }, { url = "https://files.pythonhosted.org/packages/23/9c/5844ab4ca6a4dd97a1850e030a15ec7d292b5c5cb93082979225126e35dd/coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520", size = 218302, upload-time = "2025-09-21T20:02:42.527Z" }, { url = "https://files.pythonhosted.org/packages/f0/89/673f6514b0961d1f0e20ddc242e9342f6da21eaba3489901b565c0689f34/coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32", size = 218578, upload-time = "2025-09-21T20:02:44.468Z" }, { url = "https://files.pythonhosted.org/packages/05/e8/261cae479e85232828fb17ad536765c88dd818c8470aca690b0ac6feeaa3/coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f", size = 249629, upload-time = "2025-09-21T20:02:46.503Z" }, { url = "https://files.pythonhosted.org/packages/82/62/14ed6546d0207e6eda876434e3e8475a3e9adbe32110ce896c9e0c06bb9a/coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a", size = 252162, upload-time = "2025-09-21T20:02:48.689Z" }, { url = "https://files.pythonhosted.org/packages/ff/49/07f00db9ac6478e4358165a08fb41b469a1b053212e8a00cb02f0d27a05f/coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360", size = 253517, upload-time = "2025-09-21T20:02:50.31Z" }, { url = "https://files.pythonhosted.org/packages/a2/59/c5201c62dbf165dfbc91460f6dbbaa85a8b82cfa6131ac45d6c1bfb52deb/coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69", size = 249632, upload-time = "2025-09-21T20:02:51.971Z" }, { url = "https://files.pythonhosted.org/packages/07/ae/5920097195291a51fb00b3a70b9bbd2edbfe3c84876a1762bd1ef1565ebc/coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14", size = 251520, upload-time = "2025-09-21T20:02:53.858Z" }, { url = "https://files.pythonhosted.org/packages/b9/3c/a815dde77a2981f5743a60b63df31cb322c944843e57dbd579326625a413/coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe", size = 249455, upload-time = "2025-09-21T20:02:55.807Z" }, { url = "https://files.pythonhosted.org/packages/aa/99/f5cdd8421ea656abefb6c0ce92556709db2265c41e8f9fc6c8ae0f7824c9/coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e", size = 249287, upload-time = "2025-09-21T20:02:57.784Z" }, { url = "https://files.pythonhosted.org/packages/c3/7a/e9a2da6a1fc5d007dd51fca083a663ab930a8c4d149c087732a5dbaa0029/coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd", size = 250946, upload-time = "2025-09-21T20:02:59.431Z" }, { url = "https://files.pythonhosted.org/packages/ef/5b/0b5799aa30380a949005a353715095d6d1da81927d6dbed5def2200a4e25/coverage-7.10.7-cp314-cp314-win32.whl", hash = "sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2", size = 221009, upload-time = "2025-09-21T20:03:01.324Z" }, { url = "https://files.pythonhosted.org/packages/da/b0/e802fbb6eb746de006490abc9bb554b708918b6774b722bb3a0e6aa1b7de/coverage-7.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681", size = 221804, upload-time = "2025-09-21T20:03:03.4Z" }, { url = "https://files.pythonhosted.org/packages/9e/e8/71d0c8e374e31f39e3389bb0bd19e527d46f00ea8571ec7ec8fd261d8b44/coverage-7.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880", size = 220384, upload-time = "2025-09-21T20:03:05.111Z" }, { url = "https://files.pythonhosted.org/packages/62/09/9a5608d319fa3eba7a2019addeacb8c746fb50872b57a724c9f79f146969/coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63", size = 219047, upload-time = "2025-09-21T20:03:06.795Z" }, { url = "https://files.pythonhosted.org/packages/f5/6f/f58d46f33db9f2e3647b2d0764704548c184e6f5e014bef528b7f979ef84/coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2", size = 219266, upload-time = "2025-09-21T20:03:08.495Z" }, { url = "https://files.pythonhosted.org/packages/74/5c/183ffc817ba68e0b443b8c934c8795553eb0c14573813415bd59941ee165/coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d", size = 260767, upload-time = "2025-09-21T20:03:10.172Z" }, { url = "https://files.pythonhosted.org/packages/0f/48/71a8abe9c1ad7e97548835e3cc1adbf361e743e9d60310c5f75c9e7bf847/coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0", size = 262931, upload-time = "2025-09-21T20:03:11.861Z" }, { url = "https://files.pythonhosted.org/packages/84/fd/193a8fb132acfc0a901f72020e54be5e48021e1575bb327d8ee1097a28fd/coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699", size = 265186, upload-time = "2025-09-21T20:03:13.539Z" }, { url = "https://files.pythonhosted.org/packages/b1/8f/74ecc30607dd95ad50e3034221113ccb1c6d4e8085cc761134782995daae/coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9", size = 259470, upload-time = "2025-09-21T20:03:15.584Z" }, { url = "https://files.pythonhosted.org/packages/0f/55/79ff53a769f20d71b07023ea115c9167c0bb56f281320520cf64c5298a96/coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f", size = 262626, upload-time = "2025-09-21T20:03:17.673Z" }, { url = "https://files.pythonhosted.org/packages/88/e2/dac66c140009b61ac3fc13af673a574b00c16efdf04f9b5c740703e953c0/coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1", size = 260386, upload-time = "2025-09-21T20:03:19.36Z" }, { url = "https://files.pythonhosted.org/packages/a2/f1/f48f645e3f33bb9ca8a496bc4a9671b52f2f353146233ebd7c1df6160440/coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0", size = 258852, upload-time = "2025-09-21T20:03:21.007Z" }, { url = "https://files.pythonhosted.org/packages/bb/3b/8442618972c51a7affeead957995cfa8323c0c9bcf8fa5a027421f720ff4/coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399", size = 261534, upload-time = "2025-09-21T20:03:23.12Z" }, { url = "https://files.pythonhosted.org/packages/b2/dc/101f3fa3a45146db0cb03f5b4376e24c0aac818309da23e2de0c75295a91/coverage-7.10.7-cp314-cp314t-win32.whl", hash = "sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235", size = 221784, upload-time = "2025-09-21T20:03:24.769Z" }, { url = "https://files.pythonhosted.org/packages/4c/a1/74c51803fc70a8a40d7346660379e144be772bab4ac7bb6e6b905152345c/coverage-7.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d", size = 222905, upload-time = "2025-09-21T20:03:26.93Z" }, { url = "https://files.pythonhosted.org/packages/12/65/f116a6d2127df30bcafbceef0302d8a64ba87488bf6f73a6d8eebf060873/coverage-7.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a", size = 220922, upload-time = "2025-09-21T20:03:28.672Z" }, { url = "https://files.pythonhosted.org/packages/a3/ad/d1c25053764b4c42eb294aae92ab617d2e4f803397f9c7c8295caa77a260/coverage-7.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fff7b9c3f19957020cac546c70025331113d2e61537f6e2441bc7657913de7d3", size = 217978, upload-time = "2025-09-21T20:03:30.362Z" }, { url = "https://files.pythonhosted.org/packages/52/2f/b9f9daa39b80ece0b9548bbb723381e29bc664822d9a12c2135f8922c22b/coverage-7.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bc91b314cef27742da486d6839b677b3f2793dfe52b51bbbb7cf736d5c29281c", size = 218370, upload-time = "2025-09-21T20:03:32.147Z" }, { url = "https://files.pythonhosted.org/packages/dd/6e/30d006c3b469e58449650642383dddf1c8fb63d44fdf92994bfd46570695/coverage-7.10.7-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:567f5c155eda8df1d3d439d40a45a6a5f029b429b06648235f1e7e51b522b396", size = 244802, upload-time = "2025-09-21T20:03:33.919Z" }, { url = "https://files.pythonhosted.org/packages/b0/49/8a070782ce7e6b94ff6a0b6d7c65ba6bc3091d92a92cef4cd4eb0767965c/coverage-7.10.7-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af88deffcc8a4d5974cf2d502251bc3b2db8461f0b66d80a449c33757aa9f40", size = 246625, upload-time = "2025-09-21T20:03:36.09Z" }, { url = "https://files.pythonhosted.org/packages/6a/92/1c1c5a9e8677ce56d42b97bdaca337b2d4d9ebe703d8c174ede52dbabd5f/coverage-7.10.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7315339eae3b24c2d2fa1ed7d7a38654cba34a13ef19fbcb9425da46d3dc594", size = 248399, upload-time = "2025-09-21T20:03:38.342Z" }, { url = "https://files.pythonhosted.org/packages/c0/54/b140edee7257e815de7426d5d9846b58505dffc29795fff2dfb7f8a1c5a0/coverage-7.10.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:912e6ebc7a6e4adfdbb1aec371ad04c68854cd3bf3608b3514e7ff9062931d8a", size = 245142, upload-time = "2025-09-21T20:03:40.591Z" }, { url = "https://files.pythonhosted.org/packages/e4/9e/6d6b8295940b118e8b7083b29226c71f6154f7ff41e9ca431f03de2eac0d/coverage-7.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f49a05acd3dfe1ce9715b657e28d138578bc40126760efb962322c56e9ca344b", size = 246284, upload-time = "2025-09-21T20:03:42.355Z" }, { url = "https://files.pythonhosted.org/packages/db/e5/5e957ca747d43dbe4d9714358375c7546cb3cb533007b6813fc20fce37ad/coverage-7.10.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cce2109b6219f22ece99db7644b9622f54a4e915dad65660ec435e89a3ea7cc3", size = 244353, upload-time = "2025-09-21T20:03:44.218Z" }, { url = "https://files.pythonhosted.org/packages/9a/45/540fc5cc92536a1b783b7ef99450bd55a4b3af234aae35a18a339973ce30/coverage-7.10.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:f3c887f96407cea3916294046fc7dab611c2552beadbed4ea901cbc6a40cc7a0", size = 244430, upload-time = "2025-09-21T20:03:46.065Z" }, { url = "https://files.pythonhosted.org/packages/75/0b/8287b2e5b38c8fe15d7e3398849bb58d382aedc0864ea0fa1820e8630491/coverage-7.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:635adb9a4507c9fd2ed65f39693fa31c9a3ee3a8e6dc64df033e8fdf52a7003f", size = 245311, upload-time = "2025-09-21T20:03:48.19Z" }, { url = "https://files.pythonhosted.org/packages/0c/1d/29724999984740f0c86d03e6420b942439bf5bd7f54d4382cae386a9d1e9/coverage-7.10.7-cp39-cp39-win32.whl", hash = "sha256:5a02d5a850e2979b0a014c412573953995174743a3f7fa4ea5a6e9a3c5617431", size = 220500, upload-time = "2025-09-21T20:03:50.024Z" }, { url = "https://files.pythonhosted.org/packages/43/11/4b1e6b129943f905ca54c339f343877b55b365ae2558806c1be4f7476ed5/coverage-7.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:c134869d5ffe34547d14e174c866fd8fe2254918cc0a95e99052903bc1543e07", size = 221408, upload-time = "2025-09-21T20:03:51.803Z" }, { url = "https://files.pythonhosted.org/packages/ec/16/114df1c291c22cac3b0c127a73e0af5c12ed7bbb6558d310429a0ae24023/coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260", size = 209952, upload-time = "2025-09-21T20:03:53.918Z" }, ] [package.optional-dependencies] toml = [ { name = "tomli", marker = "python_full_version < '3.10'" }, ] [[package]] name = "coverage" version = "7.13.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/11/43/3e4ac666cc35f231fa70c94e9f38459299de1a152813f9d2f60fc5f3ecaf/coverage-7.13.3.tar.gz", hash = "sha256:f7f6182d3dfb8802c1747eacbfe611b669455b69b7c037484bb1efbbb56711ac", size = 826832, upload-time = "2026-02-03T14:02:30.944Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ab/07/1c8099563a8a6c389a31c2d0aa1497cee86d6248bb4b9ba5e779215db9f9/coverage-7.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b4f345f7265cdbdb5ec2521ffff15fa49de6d6c39abf89fc7ad68aa9e3a55f0", size = 219143, upload-time = "2026-02-03T13:59:40.459Z" }, { url = "https://files.pythonhosted.org/packages/69/39/a892d44af7aa092cab70e0cc5cdbba18eeccfe1d6930695dab1742eef9e9/coverage-7.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96c3be8bae9d0333e403cc1a8eb078a7f928b5650bae94a18fb4820cc993fb9b", size = 219663, upload-time = "2026-02-03T13:59:41.951Z" }, { url = "https://files.pythonhosted.org/packages/9a/25/9669dcf4c2bb4c3861469e6db20e52e8c11908cf53c14ec9b12e9fd4d602/coverage-7.13.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d6f4a21328ea49d38565b55599e1c02834e76583a6953e5586d65cb1efebd8f8", size = 246424, upload-time = "2026-02-03T13:59:43.418Z" }, { url = "https://files.pythonhosted.org/packages/f3/68/d9766c4e298aca62ea5d9543e1dd1e4e1439d7284815244d8b7db1840bfb/coverage-7.13.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fc970575799a9d17d5c3fafd83a0f6ccf5d5117cdc9ad6fbd791e9ead82418b0", size = 248228, upload-time = "2026-02-03T13:59:44.816Z" }, { url = "https://files.pythonhosted.org/packages/f0/e2/eea6cb4a4bd443741adf008d4cccec83a1f75401df59b6559aca2bdd9710/coverage-7.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:87ff33b652b3556b05e204ae20793d1f872161b0fa5ec8a9ac76f8430e152ed6", size = 250103, upload-time = "2026-02-03T13:59:46.271Z" }, { url = "https://files.pythonhosted.org/packages/db/77/664280ecd666c2191610842177e2fab9e5dbdeef97178e2078fed46a3d2c/coverage-7.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7df8759ee57b9f3f7b66799b7660c282f4375bef620ade1686d6a7b03699e75f", size = 247107, upload-time = "2026-02-03T13:59:48.53Z" }, { url = "https://files.pythonhosted.org/packages/2b/df/2a672eab99e0d0eba52d8a63e47dc92245eee26954d1b2d3c8f7d372151f/coverage-7.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f45c9bcb16bee25a798ccba8a2f6a1251b19de6a0d617bb365d7d2f386c4e20e", size = 248143, upload-time = "2026-02-03T13:59:50.027Z" }, { url = "https://files.pythonhosted.org/packages/a5/dc/a104e7a87c13e57a358b8b9199a8955676e1703bb372d79722b54978ae45/coverage-7.13.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:318b2e4753cbf611061e01b6cc81477e1cdfeb69c36c4a14e6595e674caadb56", size = 246148, upload-time = "2026-02-03T13:59:52.025Z" }, { url = "https://files.pythonhosted.org/packages/2b/89/e113d3a58dc20b03b7e59aed1e53ebc9ca6167f961876443e002b10e3ae9/coverage-7.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:24db3959de8ee394eeeca89ccb8ba25305c2da9a668dd44173394cbd5aa0777f", size = 246414, upload-time = "2026-02-03T13:59:53.859Z" }, { url = "https://files.pythonhosted.org/packages/3f/60/a3fd0a6e8d89b488396019a2268b6a1f25ab56d6d18f3be50f35d77b47dc/coverage-7.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:be14d0622125edef21b3a4d8cd2d138c4872bf6e38adc90fd92385e3312f406a", size = 247023, upload-time = "2026-02-03T13:59:55.454Z" }, { url = "https://files.pythonhosted.org/packages/19/fa/de4840bb939dbb22ba0648a6d8069fa91c9cf3b3fca8b0d1df461e885b3d/coverage-7.13.3-cp310-cp310-win32.whl", hash = "sha256:53be4aab8ddef18beb6188f3a3fdbf4d1af2277d098d4e618be3a8e6c88e74be", size = 221751, upload-time = "2026-02-03T13:59:57.383Z" }, { url = "https://files.pythonhosted.org/packages/de/87/233ff8b7ef62fb63f58c78623b50bef69681111e0c4d43504f422d88cda4/coverage-7.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:bfeee64ad8b4aae3233abb77eb6b52b51b05fa89da9645518671b9939a78732b", size = 222686, upload-time = "2026-02-03T13:59:58.825Z" }, { url = "https://files.pythonhosted.org/packages/ec/09/1ac74e37cf45f17eb41e11a21854f7f92a4c2d6c6098ef4a1becb0c6d8d3/coverage-7.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5907605ee20e126eeee2abe14aae137043c2c8af2fa9b38d2ab3b7a6b8137f73", size = 219276, upload-time = "2026-02-03T14:00:00.296Z" }, { url = "https://files.pythonhosted.org/packages/2e/cb/71908b08b21beb2c437d0d5870c4ec129c570ca1b386a8427fcdb11cf89c/coverage-7.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a88705500988c8acad8b8fd86c2a933d3aa96bec1ddc4bc5cb256360db7bbd00", size = 219776, upload-time = "2026-02-03T14:00:02.414Z" }, { url = "https://files.pythonhosted.org/packages/09/85/c4f3dd69232887666a2c0394d4be21c60ea934d404db068e6c96aa59cd87/coverage-7.13.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bbb5aa9016c4c29e3432e087aa29ebee3f8fda089cfbfb4e6d64bd292dcd1c2", size = 250196, upload-time = "2026-02-03T14:00:04.197Z" }, { url = "https://files.pythonhosted.org/packages/9c/cc/560ad6f12010344d0778e268df5ba9aa990aacccc310d478bf82bf3d302c/coverage-7.13.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0c2be202a83dde768937a61cdc5d06bf9fb204048ca199d93479488e6247656c", size = 252111, upload-time = "2026-02-03T14:00:05.639Z" }, { url = "https://files.pythonhosted.org/packages/f0/66/3193985fb2c58e91f94cfbe9e21a6fdf941e9301fe2be9e92c072e9c8f8c/coverage-7.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f45e32ef383ce56e0ca099b2e02fcdf7950be4b1b56afaab27b4ad790befe5b", size = 254217, upload-time = "2026-02-03T14:00:07.738Z" }, { url = "https://files.pythonhosted.org/packages/c5/78/f0f91556bf1faa416792e537c523c5ef9db9b1d32a50572c102b3d7c45b3/coverage-7.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6ed2e787249b922a93cd95c671cc9f4c9797a106e81b455c83a9ddb9d34590c0", size = 250318, upload-time = "2026-02-03T14:00:09.224Z" }, { url = "https://files.pythonhosted.org/packages/6f/aa/fc654e45e837d137b2c1f3a2cc09b4aea1e8b015acd2f774fa0f3d2ddeba/coverage-7.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:05dd25b21afffe545e808265897c35f32d3e4437663923e0d256d9ab5031fb14", size = 251909, upload-time = "2026-02-03T14:00:10.712Z" }, { url = "https://files.pythonhosted.org/packages/73/4d/ab53063992add8a9ca0463c9d92cce5994a29e17affd1c2daa091b922a93/coverage-7.13.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:46d29926349b5c4f1ea4fca95e8c892835515f3600995a383fa9a923b5739ea4", size = 249971, upload-time = "2026-02-03T14:00:12.402Z" }, { url = "https://files.pythonhosted.org/packages/29/25/83694b81e46fcff9899694a1b6f57573429cdd82b57932f09a698f03eea5/coverage-7.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fae6a21537519c2af00245e834e5bf2884699cc7c1055738fd0f9dc37a3644ad", size = 249692, upload-time = "2026-02-03T14:00:13.868Z" }, { url = "https://files.pythonhosted.org/packages/d4/ef/d68fc304301f4cb4bf6aefa0045310520789ca38dabdfba9dbecd3f37919/coverage-7.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c672d4e2f0575a4ca2bf2aa0c5ced5188220ab806c1bb6d7179f70a11a017222", size = 250597, upload-time = "2026-02-03T14:00:15.461Z" }, { url = "https://files.pythonhosted.org/packages/8d/85/240ad396f914df361d0f71e912ddcedb48130c71b88dc4193fe3c0306f00/coverage-7.13.3-cp311-cp311-win32.whl", hash = "sha256:fcda51c918c7a13ad93b5f89a58d56e3a072c9e0ba5c231b0ed81404bf2648fb", size = 221773, upload-time = "2026-02-03T14:00:17.462Z" }, { url = "https://files.pythonhosted.org/packages/2f/71/165b3a6d3d052704a9ab52d11ea64ef3426745de517dda44d872716213a7/coverage-7.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:d1a049b5c51b3b679928dd35e47c4a2235e0b6128b479a7596d0ef5b42fa6301", size = 222711, upload-time = "2026-02-03T14:00:19.449Z" }, { url = "https://files.pythonhosted.org/packages/51/d0/0ddc9c5934cdd52639c5df1f1eb0fdab51bb52348f3a8d1c7db9c600d93a/coverage-7.13.3-cp311-cp311-win_arm64.whl", hash = "sha256:79f2670c7e772f4917895c3d89aad59e01f3dbe68a4ed2d0373b431fad1dcfba", size = 221377, upload-time = "2026-02-03T14:00:20.968Z" }, { url = "https://files.pythonhosted.org/packages/94/44/330f8e83b143f6668778ed61d17ece9dc48459e9e74669177de02f45fec5/coverage-7.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ed48b4170caa2c4420e0cd27dc977caaffc7eecc317355751df8373dddcef595", size = 219441, upload-time = "2026-02-03T14:00:22.585Z" }, { url = "https://files.pythonhosted.org/packages/08/e7/29db05693562c2e65bdf6910c0af2fd6f9325b8f43caf7a258413f369e30/coverage-7.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8f2adf4bcffbbec41f366f2e6dffb9d24e8172d16e91da5799c9b7ed6b5716e6", size = 219801, upload-time = "2026-02-03T14:00:24.186Z" }, { url = "https://files.pythonhosted.org/packages/90/ae/7f8a78249b02b0818db46220795f8ac8312ea4abd1d37d79ea81db5cae81/coverage-7.13.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01119735c690786b6966a1e9f098da4cd7ca9174c4cfe076d04e653105488395", size = 251306, upload-time = "2026-02-03T14:00:25.798Z" }, { url = "https://files.pythonhosted.org/packages/62/71/a18a53d1808e09b2e9ebd6b47dad5e92daf4c38b0686b4c4d1b2f3e42b7f/coverage-7.13.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8bb09e83c603f152d855f666d70a71765ca8e67332e5829e62cb9466c176af23", size = 254051, upload-time = "2026-02-03T14:00:27.474Z" }, { url = "https://files.pythonhosted.org/packages/4a/0a/eb30f6455d04c5a3396d0696cad2df0269ae7444bb322f86ffe3376f7bf9/coverage-7.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b607a40cba795cfac6d130220d25962931ce101f2f478a29822b19755377fb34", size = 255160, upload-time = "2026-02-03T14:00:29.024Z" }, { url = "https://files.pythonhosted.org/packages/7b/7e/a45baac86274ce3ed842dbb84f14560c673ad30535f397d89164ec56c5df/coverage-7.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:44f14a62f5da2e9aedf9080e01d2cda61df39197d48e323538ec037336d68da8", size = 251709, upload-time = "2026-02-03T14:00:30.641Z" }, { url = "https://files.pythonhosted.org/packages/c0/df/dd0dc12f30da11349993f3e218901fdf82f45ee44773596050c8f5a1fb25/coverage-7.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:debf29e0b157769843dff0981cc76f79e0ed04e36bb773c6cac5f6029054bd8a", size = 253083, upload-time = "2026-02-03T14:00:32.14Z" }, { url = "https://files.pythonhosted.org/packages/ab/32/fc764c8389a8ce95cb90eb97af4c32f392ab0ac23ec57cadeefb887188d3/coverage-7.13.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:824bb95cd71604031ae9a48edb91fd6effde669522f960375668ed21b36e3ec4", size = 251227, upload-time = "2026-02-03T14:00:34.721Z" }, { url = "https://files.pythonhosted.org/packages/dd/ca/d025e9da8f06f24c34d2da9873957cfc5f7e0d67802c3e34d0caa8452130/coverage-7.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8f1010029a5b52dc427c8e2a8dbddb2303ddd180b806687d1acd1bb1d06649e7", size = 250794, upload-time = "2026-02-03T14:00:36.278Z" }, { url = "https://files.pythonhosted.org/packages/45/c7/76bf35d5d488ec8f68682eb8e7671acc50a6d2d1c1182de1d2b6d4ffad3b/coverage-7.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cd5dee4fd7659d8306ffa79eeaaafd91fa30a302dac3af723b9b469e549247e0", size = 252671, upload-time = "2026-02-03T14:00:38.368Z" }, { url = "https://files.pythonhosted.org/packages/bf/10/1921f1a03a7c209e1cb374f81a6b9b68b03cdb3ecc3433c189bc90e2a3d5/coverage-7.13.3-cp312-cp312-win32.whl", hash = "sha256:f7f153d0184d45f3873b3ad3ad22694fd73aadcb8cdbc4337ab4b41ea6b4dff1", size = 221986, upload-time = "2026-02-03T14:00:40.442Z" }, { url = "https://files.pythonhosted.org/packages/3c/7c/f5d93297f8e125a80c15545edc754d93e0ed8ba255b65e609b185296af01/coverage-7.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:03a6e5e1e50819d6d7436f5bc40c92ded7e484e400716886ac921e35c133149d", size = 222793, upload-time = "2026-02-03T14:00:42.106Z" }, { url = "https://files.pythonhosted.org/packages/43/59/c86b84170015b4555ebabca8649bdf9f4a1f737a73168088385ed0f947c4/coverage-7.13.3-cp312-cp312-win_arm64.whl", hash = "sha256:51c4c42c0e7d09a822b08b6cf79b3c4db8333fffde7450da946719ba0d45730f", size = 221410, upload-time = "2026-02-03T14:00:43.726Z" }, { url = "https://files.pythonhosted.org/packages/81/f3/4c333da7b373e8c8bfb62517e8174a01dcc373d7a9083698e3b39d50d59c/coverage-7.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:853c3d3c79ff0db65797aad79dee6be020efd218ac4510f15a205f1e8d13ce25", size = 219468, upload-time = "2026-02-03T14:00:45.829Z" }, { url = "https://files.pythonhosted.org/packages/d6/31/0714337b7d23630c8de2f4d56acf43c65f8728a45ed529b34410683f7217/coverage-7.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f75695e157c83d374f88dcc646a60cb94173304a9258b2e74ba5a66b7614a51a", size = 219839, upload-time = "2026-02-03T14:00:47.407Z" }, { url = "https://files.pythonhosted.org/packages/12/99/bd6f2a2738144c98945666f90cae446ed870cecf0421c767475fcf42cdbe/coverage-7.13.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2d098709621d0819039f3f1e471ee554f55a0b2ac0d816883c765b14129b5627", size = 250828, upload-time = "2026-02-03T14:00:49.029Z" }, { url = "https://files.pythonhosted.org/packages/6f/99/97b600225fbf631e6f5bfd3ad5bcaf87fbb9e34ff87492e5a572ff01bbe2/coverage-7.13.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:16d23d6579cf80a474ad160ca14d8b319abaa6db62759d6eef53b2fc979b58c8", size = 253432, upload-time = "2026-02-03T14:00:50.655Z" }, { url = "https://files.pythonhosted.org/packages/5f/5c/abe2b3490bda26bd4f5e3e799be0bdf00bd81edebedc2c9da8d3ef288fa8/coverage-7.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00d34b29a59d2076e6f318b30a00a69bf63687e30cd882984ed444e753990cc1", size = 254672, upload-time = "2026-02-03T14:00:52.757Z" }, { url = "https://files.pythonhosted.org/packages/31/ba/5d1957c76b40daff53971fe0adb84d9c2162b614280031d1d0653dd010c1/coverage-7.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ab6d72bffac9deb6e6cb0f61042e748de3f9f8e98afb0375a8e64b0b6e11746b", size = 251050, upload-time = "2026-02-03T14:00:54.332Z" }, { url = "https://files.pythonhosted.org/packages/69/dc/dffdf3bfe9d32090f047d3c3085378558cb4eb6778cda7de414ad74581ed/coverage-7.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e129328ad1258e49cae0123a3b5fcb93d6c2fa90d540f0b4c7cdcdc019aaa3dc", size = 252801, upload-time = "2026-02-03T14:00:56.121Z" }, { url = "https://files.pythonhosted.org/packages/87/51/cdf6198b0f2746e04511a30dc9185d7b8cdd895276c07bdb538e37f1cd50/coverage-7.13.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2213a8d88ed35459bda71597599d4eec7c2ebad201c88f0bfc2c26fd9b0dd2ea", size = 250763, upload-time = "2026-02-03T14:00:58.719Z" }, { url = "https://files.pythonhosted.org/packages/d7/1a/596b7d62218c1d69f2475b69cc6b211e33c83c902f38ee6ae9766dd422da/coverage-7.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:00dd3f02de6d5f5c9c3d95e3e036c3c2e2a669f8bf2d3ceb92505c4ce7838f67", size = 250587, upload-time = "2026-02-03T14:01:01.197Z" }, { url = "https://files.pythonhosted.org/packages/f7/46/52330d5841ff660f22c130b75f5e1dd3e352c8e7baef5e5fef6b14e3e991/coverage-7.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f9bada7bc660d20b23d7d312ebe29e927b655cf414dadcdb6335a2075695bd86", size = 252358, upload-time = "2026-02-03T14:01:02.824Z" }, { url = "https://files.pythonhosted.org/packages/36/8a/e69a5be51923097ba7d5cff9724466e74fe486e9232020ba97c809a8b42b/coverage-7.13.3-cp313-cp313-win32.whl", hash = "sha256:75b3c0300f3fa15809bd62d9ca8b170eb21fcf0100eb4b4154d6dc8b3a5bbd43", size = 222007, upload-time = "2026-02-03T14:01:04.876Z" }, { url = "https://files.pythonhosted.org/packages/0a/09/a5a069bcee0d613bdd48ee7637fa73bc09e7ed4342b26890f2df97cc9682/coverage-7.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:a2f7589c6132c44c53f6e705e1a6677e2b7821378c22f7703b2cf5388d0d4587", size = 222812, upload-time = "2026-02-03T14:01:07.296Z" }, { url = "https://files.pythonhosted.org/packages/3d/4f/d62ad7dfe32f9e3d4a10c178bb6f98b10b083d6e0530ca202b399371f6c1/coverage-7.13.3-cp313-cp313-win_arm64.whl", hash = "sha256:123ceaf2b9d8c614f01110f908a341e05b1b305d6b2ada98763b9a5a59756051", size = 221433, upload-time = "2026-02-03T14:01:09.156Z" }, { url = "https://files.pythonhosted.org/packages/04/b2/4876c46d723d80b9c5b695f1a11bf5f7c3dabf540ec00d6edc076ff025e6/coverage-7.13.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:cc7fd0f726795420f3678ac82ff882c7fc33770bd0074463b5aef7293285ace9", size = 220162, upload-time = "2026-02-03T14:01:11.409Z" }, { url = "https://files.pythonhosted.org/packages/fc/04/9942b64a0e0bdda2c109f56bda42b2a59d9d3df4c94b85a323c1cae9fc77/coverage-7.13.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d358dc408edc28730aed5477a69338e444e62fba0b7e9e4a131c505fadad691e", size = 220510, upload-time = "2026-02-03T14:01:13.038Z" }, { url = "https://files.pythonhosted.org/packages/5a/82/5cfe1e81eae525b74669f9795f37eb3edd4679b873d79d1e6c1c14ee6c1c/coverage-7.13.3-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5d67b9ed6f7b5527b209b24b3df9f2e5bf0198c1bbf99c6971b0e2dcb7e2a107", size = 261801, upload-time = "2026-02-03T14:01:14.674Z" }, { url = "https://files.pythonhosted.org/packages/0b/ec/a553d7f742fd2cd12e36a16a7b4b3582d5934b496ef2b5ea8abeb10903d4/coverage-7.13.3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59224bfb2e9b37c1335ae35d00daa3a5b4e0b1a20f530be208fff1ecfa436f43", size = 263882, upload-time = "2026-02-03T14:01:16.343Z" }, { url = "https://files.pythonhosted.org/packages/e1/58/8f54a2a93e3d675635bc406de1c9ac8d551312142ff52c9d71b5e533ad45/coverage-7.13.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9306b5299e31e31e0d3b908c66bcb6e7e3ddca143dea0266e9ce6c667346d3", size = 266306, upload-time = "2026-02-03T14:01:18.02Z" }, { url = "https://files.pythonhosted.org/packages/1a/be/e593399fd6ea1f00aee79ebd7cc401021f218d34e96682a92e1bae092ff6/coverage-7.13.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:343aaeb5f8bb7bcd38620fd7bc56e6ee8207847d8c6103a1e7b72322d381ba4a", size = 261051, upload-time = "2026-02-03T14:01:19.757Z" }, { url = "https://files.pythonhosted.org/packages/5c/e5/e9e0f6138b21bcdebccac36fbfde9cf15eb1bbcea9f5b1f35cd1f465fb91/coverage-7.13.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2182129f4c101272ff5f2f18038d7b698db1bf8e7aa9e615cb48440899ad32e", size = 263868, upload-time = "2026-02-03T14:01:21.487Z" }, { url = "https://files.pythonhosted.org/packages/9a/bf/de72cfebb69756f2d4a2dde35efcc33c47d85cd3ebdf844b3914aac2ef28/coverage-7.13.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:94d2ac94bd0cc57c5626f52f8c2fffed1444b5ae8c9fc68320306cc2b255e155", size = 261498, upload-time = "2026-02-03T14:01:23.097Z" }, { url = "https://files.pythonhosted.org/packages/f2/91/4a2d313a70fc2e98ca53afd1c8ce67a89b1944cd996589a5b1fe7fbb3e5c/coverage-7.13.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:65436cde5ecabe26fb2f0bf598962f0a054d3f23ad529361326ac002c61a2a1e", size = 260394, upload-time = "2026-02-03T14:01:24.949Z" }, { url = "https://files.pythonhosted.org/packages/40/83/25113af7cf6941e779eb7ed8de2a677865b859a07ccee9146d4cc06a03e3/coverage-7.13.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db83b77f97129813dbd463a67e5335adc6a6a91db652cc085d60c2d512746f96", size = 262579, upload-time = "2026-02-03T14:01:26.703Z" }, { url = "https://files.pythonhosted.org/packages/1e/19/a5f2b96262977e82fb9aabbe19b4d83561f5d063f18dde3e72f34ffc3b2f/coverage-7.13.3-cp313-cp313t-win32.whl", hash = "sha256:dfb428e41377e6b9ba1b0a32df6db5409cb089a0ed1d0a672dc4953ec110d84f", size = 222679, upload-time = "2026-02-03T14:01:28.553Z" }, { url = "https://files.pythonhosted.org/packages/81/82/ef1747b88c87a5c7d7edc3704799ebd650189a9158e680a063308b6125ef/coverage-7.13.3-cp313-cp313t-win_amd64.whl", hash = "sha256:5badd7e596e6b0c89aa8ec6d37f4473e4357f982ce57f9a2942b0221cd9cf60c", size = 223740, upload-time = "2026-02-03T14:01:30.776Z" }, { url = "https://files.pythonhosted.org/packages/1c/4c/a67c7bb5b560241c22736a9cb2f14c5034149ffae18630323fde787339e4/coverage-7.13.3-cp313-cp313t-win_arm64.whl", hash = "sha256:989aa158c0eb19d83c76c26f4ba00dbb272485c56e452010a3450bdbc9daafd9", size = 221996, upload-time = "2026-02-03T14:01:32.495Z" }, { url = "https://files.pythonhosted.org/packages/5e/b3/677bb43427fed9298905106f39c6520ac75f746f81b8f01104526a8026e4/coverage-7.13.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c6f6169bbdbdb85aab8ac0392d776948907267fcc91deeacf6f9d55f7a83ae3b", size = 219513, upload-time = "2026-02-03T14:01:34.29Z" }, { url = "https://files.pythonhosted.org/packages/42/53/290046e3bbf8986cdb7366a42dab3440b9983711eaff044a51b11006c67b/coverage-7.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2f5e731627a3d5ef11a2a35aa0c6f7c435867c7ccbc391268eb4f2ca5dbdcc10", size = 219850, upload-time = "2026-02-03T14:01:35.984Z" }, { url = "https://files.pythonhosted.org/packages/ea/2b/ab41f10345ba2e49d5e299be8663be2b7db33e77ac1b85cd0af985ea6406/coverage-7.13.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9db3a3285d91c0b70fab9f39f0a4aa37d375873677efe4e71e58d8321e8c5d39", size = 250886, upload-time = "2026-02-03T14:01:38.287Z" }, { url = "https://files.pythonhosted.org/packages/72/2d/b3f6913ee5a1d5cdd04106f257e5fac5d048992ffc2d9995d07b0f17739f/coverage-7.13.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06e49c5897cb12e3f7ecdc111d44e97c4f6d0557b81a7a0204ed70a8b038f86f", size = 253393, upload-time = "2026-02-03T14:01:40.118Z" }, { url = "https://files.pythonhosted.org/packages/f0/f6/b1f48810ffc6accf49a35b9943636560768f0812330f7456aa87dc39aff5/coverage-7.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb25061a66802df9fc13a9ba1967d25faa4dae0418db469264fd9860a921dde4", size = 254740, upload-time = "2026-02-03T14:01:42.413Z" }, { url = "https://files.pythonhosted.org/packages/57/d0/e59c54f9be0b61808f6bc4c8c4346bd79f02dd6bbc3f476ef26124661f20/coverage-7.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:99fee45adbb1caeb914da16f70e557fb7ff6ddc9e4b14de665bd41af631367ef", size = 250905, upload-time = "2026-02-03T14:01:44.163Z" }, { url = "https://files.pythonhosted.org/packages/d5/f7/5291bcdf498bafbee3796bb32ef6966e9915aebd4d0954123c8eae921c32/coverage-7.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:318002f1fd819bdc1651c619268aa5bc853c35fa5cc6d1e8c96bd9cd6c828b75", size = 252753, upload-time = "2026-02-03T14:01:45.974Z" }, { url = "https://files.pythonhosted.org/packages/a0/a9/1dcafa918c281554dae6e10ece88c1add82db685be123e1b05c2056ff3fb/coverage-7.13.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:71295f2d1d170b9977dc386d46a7a1b7cbb30e5405492529b4c930113a33f895", size = 250716, upload-time = "2026-02-03T14:01:48.844Z" }, { url = "https://files.pythonhosted.org/packages/44/bb/4ea4eabcce8c4f6235df6e059fbc5db49107b24c4bdffc44aee81aeca5a8/coverage-7.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5b1ad2e0dc672625c44bc4fe34514602a9fd8b10d52ddc414dc585f74453516c", size = 250530, upload-time = "2026-02-03T14:01:50.793Z" }, { url = "https://files.pythonhosted.org/packages/6d/31/4a6c9e6a71367e6f923b27b528448c37f4e959b7e4029330523014691007/coverage-7.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b2beb64c145593a50d90db5c7178f55daeae129123b0d265bdb3cbec83e5194a", size = 252186, upload-time = "2026-02-03T14:01:52.607Z" }, { url = "https://files.pythonhosted.org/packages/27/92/e1451ef6390a4f655dc42da35d9971212f7abbbcad0bdb7af4407897eb76/coverage-7.13.3-cp314-cp314-win32.whl", hash = "sha256:3d1aed4f4e837a832df2f3b4f68a690eede0de4560a2dbc214ea0bc55aabcdb4", size = 222253, upload-time = "2026-02-03T14:01:55.071Z" }, { url = "https://files.pythonhosted.org/packages/8a/98/78885a861a88de020c32a2693487c37d15a9873372953f0c3c159d575a43/coverage-7.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9f9efbbaf79f935d5fbe3ad814825cbce4f6cdb3054384cb49f0c0f496125fa0", size = 223069, upload-time = "2026-02-03T14:01:56.95Z" }, { url = "https://files.pythonhosted.org/packages/eb/fb/3784753a48da58a5337972abf7ca58b1fb0f1bda21bc7b4fae992fd28e47/coverage-7.13.3-cp314-cp314-win_arm64.whl", hash = "sha256:31b6e889c53d4e6687ca63706148049494aace140cffece1c4dc6acadb70a7b3", size = 221633, upload-time = "2026-02-03T14:01:58.758Z" }, { url = "https://files.pythonhosted.org/packages/40/f9/75b732d9674d32cdbffe801ed5f770786dd1c97eecedef2125b0d25102dc/coverage-7.13.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c5e9787cec750793a19a28df7edd85ac4e49d3fb91721afcdc3b86f6c08d9aa8", size = 220243, upload-time = "2026-02-03T14:02:01.109Z" }, { url = "https://files.pythonhosted.org/packages/cf/7e/2868ec95de5a65703e6f0c87407ea822d1feb3619600fbc3c1c4fa986090/coverage-7.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5b86db331c682fd0e4be7098e6acee5e8a293f824d41487c667a93705d415ca", size = 220515, upload-time = "2026-02-03T14:02:02.862Z" }, { url = "https://files.pythonhosted.org/packages/7d/eb/9f0d349652fced20bcaea0f67fc5777bd097c92369f267975732f3dc5f45/coverage-7.13.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:edc7754932682d52cf6e7a71806e529ecd5ce660e630e8bd1d37109a2e5f63ba", size = 261874, upload-time = "2026-02-03T14:02:04.727Z" }, { url = "https://files.pythonhosted.org/packages/ee/a5/6619bc4a6c7b139b16818149a3e74ab2e21599ff9a7b6811b6afde99f8ec/coverage-7.13.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3a16d6398666510a6886f67f43d9537bfd0e13aca299688a19daa84f543122f", size = 264004, upload-time = "2026-02-03T14:02:06.634Z" }, { url = "https://files.pythonhosted.org/packages/29/b7/90aa3fc645a50c6f07881fca4fd0ba21e3bfb6ce3a7078424ea3a35c74c9/coverage-7.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:303d38b19626c1981e1bb067a9928236d88eb0e4479b18a74812f05a82071508", size = 266408, upload-time = "2026-02-03T14:02:09.037Z" }, { url = "https://files.pythonhosted.org/packages/62/55/08bb2a1e4dcbae384e638f0effef486ba5987b06700e481691891427d879/coverage-7.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:284e06eadfe15ddfee2f4ee56631f164ef897a7d7d5a15bca5f0bb88889fc5ba", size = 260977, upload-time = "2026-02-03T14:02:11.755Z" }, { url = "https://files.pythonhosted.org/packages/9b/76/8bd4ae055a42d8fb5dd2230e5cf36ff2e05f85f2427e91b11a27fea52ed7/coverage-7.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d401f0864a1d3198422816878e4e84ca89ec1c1bf166ecc0ae01380a39b888cd", size = 263868, upload-time = "2026-02-03T14:02:13.565Z" }, { url = "https://files.pythonhosted.org/packages/e3/f9/ba000560f11e9e32ec03df5aa8477242c2d95b379c99ac9a7b2e7fbacb1a/coverage-7.13.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3f379b02c18a64de78c4ccdddf1c81c2c5ae1956c72dacb9133d7dd7809794ab", size = 261474, upload-time = "2026-02-03T14:02:16.069Z" }, { url = "https://files.pythonhosted.org/packages/90/4b/4de4de8f9ca7af4733bfcf4baa440121b7dbb3856daf8428ce91481ff63b/coverage-7.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:7a482f2da9086971efb12daca1d6547007ede3674ea06e16d7663414445c683e", size = 260317, upload-time = "2026-02-03T14:02:17.996Z" }, { url = "https://files.pythonhosted.org/packages/05/71/5cd8436e2c21410ff70be81f738c0dddea91bcc3189b1517d26e0102ccb3/coverage-7.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:562136b0d401992118d9b49fbee5454e16f95f85b120a4226a04d816e33fe024", size = 262635, upload-time = "2026-02-03T14:02:20.405Z" }, { url = "https://files.pythonhosted.org/packages/e7/f8/2834bb45bdd70b55a33ec354b8b5f6062fc90e5bb787e14385903a979503/coverage-7.13.3-cp314-cp314t-win32.whl", hash = "sha256:ca46e5c3be3b195098dd88711890b8011a9fa4feca942292bb84714ce5eab5d3", size = 223035, upload-time = "2026-02-03T14:02:22.323Z" }, { url = "https://files.pythonhosted.org/packages/26/75/f8290f0073c00d9ae14056d2b84ab92dff21d5370e464cb6cb06f52bf580/coverage-7.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:06d316dbb3d9fd44cca05b2dbcfbef22948493d63a1f28e828d43e6cc505fed8", size = 224142, upload-time = "2026-02-03T14:02:24.143Z" }, { url = "https://files.pythonhosted.org/packages/03/01/43ac78dfea8946c4a9161bbc034b5549115cb2b56781a4b574927f0d141a/coverage-7.13.3-cp314-cp314t-win_arm64.whl", hash = "sha256:299d66e9218193f9dc6e4880629ed7c4cd23486005166247c283fb98531656c3", size = 222166, upload-time = "2026-02-03T14:02:26.005Z" }, { url = "https://files.pythonhosted.org/packages/7d/fb/70af542d2d938c778c9373ce253aa4116dbe7c0a5672f78b2b2ae0e1b94b/coverage-7.13.3-py3-none-any.whl", hash = "sha256:90a8af9dba6429b2573199622d72e0ebf024d6276f16abce394ad4d181bb0910", size = 211237, upload-time = "2026-02-03T14:02:27.986Z" }, ] [package.optional-dependencies] toml = [ { name = "tomli", marker = "python_full_version >= '3.10' and python_full_version <= '3.11'" }, ] [[package]] name = "cryptography" version = "46.0.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "(python_full_version < '3.11' and platform_python_implementation != 'PyPy' and sys_platform == 'emscripten') or (python_full_version < '3.11' and platform_python_implementation != 'PyPy' and sys_platform == 'win32') or (platform_python_implementation != 'PyPy' and sys_platform != 'emscripten' and sys_platform != 'win32')" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/78/19/f748958276519adf6a0c1e79e7b8860b4830dda55ccdf29f2719b5fc499c/cryptography-46.0.4.tar.gz", hash = "sha256:bfd019f60f8abc2ed1b9be4ddc21cfef059c841d86d710bb69909a688cbb8f59", size = 749301, upload-time = "2026-01-28T00:24:37.379Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/87/91/874b8910903159043b5c6a123b7e79c4559ddd1896e38967567942635778/cryptography-46.0.4-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5f14fba5bf6f4390d7ff8f086c566454bff0411f6d8aa7af79c88b6f9267aecc", size = 4275871, upload-time = "2026-01-28T00:23:09.439Z" }, { url = "https://files.pythonhosted.org/packages/c0/35/690e809be77896111f5b195ede56e4b4ed0435b428c2f2b6d35046fbb5e8/cryptography-46.0.4-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:47bcd19517e6389132f76e2d5303ded6cf3f78903da2158a671be8de024f4cd0", size = 4423124, upload-time = "2026-01-28T00:23:11.529Z" }, { url = "https://files.pythonhosted.org/packages/1a/5b/a26407d4f79d61ca4bebaa9213feafdd8806dc69d3d290ce24996d3cfe43/cryptography-46.0.4-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:01df4f50f314fbe7009f54046e908d1754f19d0c6d3070df1e6268c5a4af09fa", size = 4277090, upload-time = "2026-01-28T00:23:13.123Z" }, { url = "https://files.pythonhosted.org/packages/2b/08/f83e2e0814248b844265802d081f2fac2f1cbe6cd258e72ba14ff006823a/cryptography-46.0.4-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0a9ad24359fee86f131836a9ac3bffc9329e956624a2d379b613f8f8abaf5255", size = 4455157, upload-time = "2026-01-28T00:23:16.443Z" }, { url = "https://files.pythonhosted.org/packages/0a/05/19d849cf4096448779d2dcc9bb27d097457dac36f7273ffa875a93b5884c/cryptography-46.0.4-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:dc1272e25ef673efe72f2096e92ae39dea1a1a450dd44918b15351f72c5a168e", size = 3981078, upload-time = "2026-01-28T00:23:17.838Z" }, { url = "https://files.pythonhosted.org/packages/e6/89/f7bac81d66ba7cde867a743ea5b37537b32b5c633c473002b26a226f703f/cryptography-46.0.4-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:de0f5f4ec8711ebc555f54735d4c673fc34b65c44283895f1a08c2b49d2fd99c", size = 4276213, upload-time = "2026-01-28T00:23:19.257Z" }, { url = "https://files.pythonhosted.org/packages/a6/f7/6d43cbaddf6f65b24816e4af187d211f0bc536a29961f69faedc48501d8e/cryptography-46.0.4-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3d425eacbc9aceafd2cb429e42f4e5d5633c6f873f5e567077043ef1b9bbf616", size = 4454641, upload-time = "2026-01-28T00:23:22.866Z" }, { url = "https://files.pythonhosted.org/packages/9e/4f/ebd0473ad656a0ac912a16bd07db0f5d85184924e14fc88feecae2492834/cryptography-46.0.4-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91627ebf691d1ea3976a031b61fb7bac1ccd745afa03602275dda443e11c8de0", size = 4405159, upload-time = "2026-01-28T00:23:25.278Z" }, { url = "https://files.pythonhosted.org/packages/d1/f7/7923886f32dc47e27adeff8246e976d77258fd2aa3efdd1754e4e323bf49/cryptography-46.0.4-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2d08bc22efd73e8854b0b7caff402d735b354862f1145d7be3b9c0f740fef6a0", size = 4666059, upload-time = "2026-01-28T00:23:26.766Z" }, { url = "https://files.pythonhosted.org/packages/f8/f5/559c25b77f40b6bf828eabaf988efb8b0e17b573545edb503368ca0a2a03/cryptography-46.0.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:078e5f06bd2fa5aea5a324f2a09f914b1484f1d0c2a4d6a8a28c74e72f65f2da", size = 4264508, upload-time = "2026-01-28T00:23:34.264Z" }, { url = "https://files.pythonhosted.org/packages/49/a1/551fa162d33074b660dc35c9bc3616fefa21a0e8c1edd27b92559902e408/cryptography-46.0.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dce1e4f068f03008da7fa51cc7abc6ddc5e5de3e3d1550334eaf8393982a5829", size = 4409080, upload-time = "2026-01-28T00:23:35.793Z" }, { url = "https://files.pythonhosted.org/packages/b0/6a/4d8d129a755f5d6df1bbee69ea2f35ebfa954fa1847690d1db2e8bca46a5/cryptography-46.0.4-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:2067461c80271f422ee7bdbe79b9b4be54a5162e90345f86a23445a0cf3fd8a2", size = 4270039, upload-time = "2026-01-28T00:23:37.263Z" }, { url = "https://files.pythonhosted.org/packages/43/ae/9f03d5f0c0c00e85ecb34f06d3b79599f20630e4db91b8a6e56e8f83d410/cryptography-46.0.4-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:829c2b12bbc5428ab02d6b7f7e9bbfd53e33efd6672d21341f2177470171ad8b", size = 4442307, upload-time = "2026-01-28T00:23:40.56Z" }, { url = "https://files.pythonhosted.org/packages/8b/22/e0f9f2dae8040695103369cf2283ef9ac8abe4d51f68710bec2afd232609/cryptography-46.0.4-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:62217ba44bf81b30abaeda1488686a04a702a261e26f87db51ff61d9d3510abd", size = 3959253, upload-time = "2026-01-28T00:23:42.827Z" }, { url = "https://files.pythonhosted.org/packages/01/5b/6a43fcccc51dae4d101ac7d378a8724d1ba3de628a24e11bf2f4f43cba4d/cryptography-46.0.4-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:9c2da296c8d3415b93e6053f5a728649a87a48ce084a9aaf51d6e46c87c7f2d2", size = 4269372, upload-time = "2026-01-28T00:23:44.655Z" }, { url = "https://files.pythonhosted.org/packages/83/17/259409b8349aa10535358807a472c6a695cf84f106022268d31cea2b6c97/cryptography-46.0.4-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:df4a817fa7138dd0c96c8c8c20f04b8aaa1fac3bbf610913dcad8ea82e1bfd3f", size = 4441254, upload-time = "2026-01-28T00:23:48.403Z" }, { url = "https://files.pythonhosted.org/packages/9c/fe/e4a1b0c989b00cee5ffa0764401767e2d1cf59f45530963b894129fd5dce/cryptography-46.0.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b1de0ebf7587f28f9190b9cb526e901bf448c9e6a99655d2b07fff60e8212a82", size = 4396520, upload-time = "2026-01-28T00:23:50.26Z" }, { url = "https://files.pythonhosted.org/packages/b3/81/ba8fd9657d27076eb40d6a2f941b23429a3c3d2f56f5a921d6b936a27bc9/cryptography-46.0.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9b4d17bc7bd7cdd98e3af40b441feaea4c68225e2eb2341026c84511ad246c0c", size = 4651479, upload-time = "2026-01-28T00:23:51.674Z" }, { url = "https://files.pythonhosted.org/packages/d8/cc/8f3224cbb2a928de7298d6ed4790f5ebc48114e02bdc9559196bfb12435d/cryptography-46.0.4-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8bf75b0259e87fa70bddc0b8b4078b76e7fd512fd9afae6c1193bcf440a4dbef", size = 4275419, upload-time = "2026-01-28T00:23:58.364Z" }, { url = "https://files.pythonhosted.org/packages/17/43/4a18faa7a872d00e4264855134ba82d23546c850a70ff209e04ee200e76f/cryptography-46.0.4-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3c268a3490df22270955966ba236d6bc4a8f9b6e4ffddb78aac535f1a5ea471d", size = 4419058, upload-time = "2026-01-28T00:23:59.867Z" }, { url = "https://files.pythonhosted.org/packages/ee/64/6651969409821d791ba12346a124f55e1b76f66a819254ae840a965d4b9c/cryptography-46.0.4-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:812815182f6a0c1d49a37893a303b44eaac827d7f0d582cecfc81b6427f22973", size = 4278151, upload-time = "2026-01-28T00:24:01.731Z" }, { url = "https://files.pythonhosted.org/packages/db/a7/20c5701e2cd3e1dfd7a19d2290c522a5f435dd30957d431dcb531d0f1413/cryptography-46.0.4-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a05177ff6296644ef2876fce50518dffb5bcdf903c85250974fc8bc85d54c0af", size = 4451617, upload-time = "2026-01-28T00:24:05.403Z" }, { url = "https://files.pythonhosted.org/packages/00/dc/3e16030ea9aa47b63af6524c354933b4fb0e352257c792c4deeb0edae367/cryptography-46.0.4-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:daa392191f626d50f1b136c9b4cf08af69ca8279d110ea24f5c2700054d2e263", size = 3977774, upload-time = "2026-01-28T00:24:06.851Z" }, { url = "https://files.pythonhosted.org/packages/42/c8/ad93f14118252717b465880368721c963975ac4b941b7ef88f3c56bf2897/cryptography-46.0.4-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e07ea39c5b048e085f15923511d8121e4a9dc45cee4e3b970ca4f0d338f23095", size = 4277008, upload-time = "2026-01-28T00:24:08.926Z" }, { url = "https://files.pythonhosted.org/packages/03/c3/c90a2cb358de4ac9309b26acf49b2a100957e1ff5cc1e98e6c4996576710/cryptography-46.0.4-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:6bb5157bf6a350e5b28aee23beb2d84ae6f5be390b2f8ee7ea179cda077e1019", size = 4451216, upload-time = "2026-01-28T00:24:13.975Z" }, { url = "https://files.pythonhosted.org/packages/96/2c/8d7f4171388a10208671e181ca43cdc0e596d8259ebacbbcfbd16de593da/cryptography-46.0.4-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:dd5aba870a2c40f87a3af043e0dee7d9eb02d4aff88a797b48f2b43eff8c3ab4", size = 4404299, upload-time = "2026-01-28T00:24:16.169Z" }, { url = "https://files.pythonhosted.org/packages/e9/23/cbb2036e450980f65c6e0a173b73a56ff3bccd8998965dea5cc9ddd424a5/cryptography-46.0.4-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:93d8291da8d71024379ab2cb0b5c57915300155ad42e07f76bea6ad838d7e59b", size = 4664837, upload-time = "2026-01-28T00:24:17.629Z" }, { url = "https://files.pythonhosted.org/packages/27/7a/f8d2d13227a9a1a9fe9c7442b057efecffa41f1e3c51d8622f26b9edbe8f/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c236a44acfb610e70f6b3e1c3ca20ff24459659231ef2f8c48e879e2d32b73da", size = 4216693, upload-time = "2026-01-28T00:24:25.758Z" }, { url = "https://files.pythonhosted.org/packages/c5/de/3787054e8f7972658370198753835d9d680f6cd4a39df9f877b57f0dd69c/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8a15fb869670efa8f83cbffbc8753c1abf236883225aed74cd179b720ac9ec80", size = 4382765, upload-time = "2026-01-28T00:24:27.577Z" }, { url = "https://files.pythonhosted.org/packages/8a/5f/60e0afb019973ba6a0b322e86b3d61edf487a4f5597618a430a2a15f2d22/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:fdc3daab53b212472f1524d070735b2f0c214239df131903bae1d598016fa822", size = 4216066, upload-time = "2026-01-28T00:24:29.056Z" }, { url = "https://files.pythonhosted.org/packages/81/8e/bf4a0de294f147fee66f879d9bae6f8e8d61515558e3d12785dd90eca0be/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:44cc0675b27cadb71bdbb96099cca1fa051cd11d2ade09e5cd3a2edb929ed947", size = 4382025, upload-time = "2026-01-28T00:24:30.681Z" }, ] [[package]] name = "cycler" version = "0.12.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, ] [[package]] name = "dash" version = "4.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "flask" }, { name = "importlib-metadata" }, { name = "nest-asyncio" }, { name = "plotly" }, { name = "requests" }, { name = "retrying" }, { name = "setuptools" }, { name = "typing-extensions" }, { name = "werkzeug" }, ] sdist = { url = "https://files.pythonhosted.org/packages/20/dd/3aed9bfd81dfd8f44b3a5db0583080ac9470d5e92ee134982bd5c69e286e/dash-4.0.0.tar.gz", hash = "sha256:c5f2bca497af288f552aea3ae208f6a0cca472559003dac84ac21187a1c3a142", size = 6943263, upload-time = "2026-02-03T19:42:27.92Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0b/8c/dd63d210b28a7589f4bc1e84880525368147425c717d12834ab562f52d14/dash-4.0.0-py3-none-any.whl", hash = "sha256:e36b4b4eae9e1fa4136bf4f1450ed14ef76063bc5da0b10f8ab07bd57a7cb1ab", size = 7247521, upload-time = "2026-02-03T19:42:25.01Z" }, ] [[package]] name = "decorator" version = "5.2.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, ] [[package]] name = "docutils" version = "0.21.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, ] [[package]] name = "docutils" version = "0.22.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, ] [[package]] name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] name = "execnet" version = "2.1.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, ] [[package]] name = "flake8" version = "7.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mccabe" }, { name = "pycodestyle" }, { name = "pyflakes" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872", size = 48326, upload-time = "2025-06-20T19:31:35.838Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e", size = 57922, upload-time = "2025-06-20T19:31:34.425Z" }, ] [[package]] name = "flask" version = "3.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "blinker" }, { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "itsdangerous" }, { name = "jinja2" }, { name = "markupsafe" }, { name = "werkzeug" }, ] sdist = { url = "https://files.pythonhosted.org/packages/dc/6d/cfe3c0fcc5e477df242b98bfe186a4c34357b4847e87ecaef04507332dab/flask-3.1.2.tar.gz", hash = "sha256:bf656c15c80190ed628ad08cdfd3aaa35beb087855e2f494910aa3774cc4fd87", size = 720160, upload-time = "2025-08-19T21:03:21.205Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ec/f9/7f9263c5695f4bd0023734af91bedb2ff8209e8de6ead162f35d8dc762fd/flask-3.1.2-py3-none-any.whl", hash = "sha256:ca1d8112ec8a6158cc29ea4858963350011b5c846a414cdb7a954aa9e967d03c", size = 103308, upload-time = "2025-08-19T21:03:19.499Z" }, ] [[package]] name = "fonttools" version = "4.60.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/3e/c4/db6a7b5eb0656534c3aa2596c2c5e18830d74f1b9aa5aa8a7dff63a0b11d/fonttools-4.60.2.tar.gz", hash = "sha256:d29552e6b155ebfc685b0aecf8d429cb76c14ab734c22ef5d3dea6fdf800c92c", size = 3562254, upload-time = "2025-12-09T13:38:11.835Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ab/de/9e10a99fb3070accb8884886a41a4ce54e49bf2fa4fc63f48a6cf2061713/fonttools-4.60.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4e36fadcf7e8ca6e34d490eef86ed638d6fd9c55d2f514b05687622cfc4a7050", size = 2850403, upload-time = "2025-12-09T13:35:53.14Z" }, { url = "https://files.pythonhosted.org/packages/e4/40/d5b369d1073b134f600a94a287e13b5bdea2191ba6347d813fa3da00e94a/fonttools-4.60.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e500fc9c04bee749ceabfc20cb4903f6981c2139050d85720ea7ada61b75d5c", size = 2398629, upload-time = "2025-12-09T13:35:56.471Z" }, { url = "https://files.pythonhosted.org/packages/7c/b5/123819369aaf99d1e4dc49f1de1925d4edc7379114d15a56a7dd2e9d56e6/fonttools-4.60.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22efea5e784e1d1cd8d7b856c198e360a979383ebc6dea4604743b56da1cbc34", size = 4893471, upload-time = "2025-12-09T13:35:58.927Z" }, { url = "https://files.pythonhosted.org/packages/24/29/f8f8acccb9716b899be4be45e9ce770d6aa76327573863e68448183091b0/fonttools-4.60.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:677aa92d84d335e4d301d8ba04afca6f575316bc647b6782cb0921943fcb6343", size = 4854686, upload-time = "2025-12-09T13:36:01.767Z" }, { url = "https://files.pythonhosted.org/packages/5a/0d/f3f51d7519f44f2dd5c9a60d7cd41185ebcee4348f073e515a3a93af15ff/fonttools-4.60.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:edd49d3defbf35476e78b61ff737ff5efea811acff68d44233a95a5a48252334", size = 4871233, upload-time = "2025-12-09T13:36:06.094Z" }, { url = "https://files.pythonhosted.org/packages/cc/3f/4d4fd47d3bc40ab4d76718555185f8adffb5602ea572eac4bbf200c47d22/fonttools-4.60.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:126839492b69cecc5baf2bddcde60caab2ffafd867bbae2a88463fce6078ca3a", size = 4988936, upload-time = "2025-12-09T13:36:08.42Z" }, { url = "https://files.pythonhosted.org/packages/01/6f/83bbdefa43f2c3ae206fd8c4b9a481f3c913eef871b1ce9a453069239e39/fonttools-4.60.2-cp310-cp310-win32.whl", hash = "sha256:ffcab6f5537136046ca902ed2491ab081ba271b07591b916289b7c27ff845f96", size = 2278044, upload-time = "2025-12-09T13:36:10.641Z" }, { url = "https://files.pythonhosted.org/packages/d4/04/7d9a137e919d6c9ef26704b7f7b2580d9cfc5139597588227aacebc0e3b7/fonttools-4.60.2-cp310-cp310-win_amd64.whl", hash = "sha256:9c68b287c7ffcd29dd83b5f961004b2a54a862a88825d52ea219c6220309ba45", size = 2326522, upload-time = "2025-12-09T13:36:12.981Z" }, { url = "https://files.pythonhosted.org/packages/e0/80/b7693d37c02417e162cc83cdd0b19a4f58be82c638b5d4ce4de2dae050c4/fonttools-4.60.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a2aed0a7931401b3875265717a24c726f87ecfedbb7b3426c2ca4d2812e281ae", size = 2847809, upload-time = "2025-12-09T13:36:14.884Z" }, { url = "https://files.pythonhosted.org/packages/f9/9a/9c2c13bf8a6496ac21607d704e74e9cc68ebf23892cf924c9a8b5c7566b9/fonttools-4.60.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dea6868e9d2b816c9076cfea77754686f3c19149873bdbc5acde437631c15df1", size = 2397302, upload-time = "2025-12-09T13:36:17.151Z" }, { url = "https://files.pythonhosted.org/packages/56/f6/ce38ff6b2d2d58f6fd981d32f3942365bfa30eadf2b47d93b2d48bf6097f/fonttools-4.60.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2fa27f34950aa1fe0f0b1abe25eed04770a3b3b34ad94e5ace82cc341589678a", size = 5054418, upload-time = "2025-12-09T13:36:19.062Z" }, { url = "https://files.pythonhosted.org/packages/88/06/5353bea128ff39e857c31de3dd605725b4add956badae0b31bc9a50d4c8e/fonttools-4.60.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:13a53d479d187b09bfaa4a35ffcbc334fc494ff355f0a587386099cb66674f1e", size = 5031652, upload-time = "2025-12-09T13:36:21.206Z" }, { url = "https://files.pythonhosted.org/packages/71/05/ebca836437f6ebd57edd6428e7eff584e683ff0556ddb17d62e3b731f46c/fonttools-4.60.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fac5e921d3bd0ca3bb8517dced2784f0742bc8ca28579a68b139f04ea323a779", size = 5030321, upload-time = "2025-12-09T13:36:23.515Z" }, { url = "https://files.pythonhosted.org/packages/57/f9/eb9d2a2ce30c99f840c1cc3940729a970923cf39d770caf88909d98d516b/fonttools-4.60.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:648f4f9186fd7f1f3cd57dbf00d67a583720d5011feca67a5e88b3a491952cfb", size = 5154255, upload-time = "2025-12-09T13:36:25.879Z" }, { url = "https://files.pythonhosted.org/packages/08/a2/088b6ceba8272a9abb629d3c08f9c1e35e5ce42db0ccfe0c1f9f03e60d1d/fonttools-4.60.2-cp311-cp311-win32.whl", hash = "sha256:3274e15fad871bead5453d5ce02658f6d0c7bc7e7021e2a5b8b04e2f9e40da1a", size = 2276300, upload-time = "2025-12-09T13:36:27.772Z" }, { url = "https://files.pythonhosted.org/packages/de/2f/8e4c3d908cc5dade7bb1316ce48589f6a24460c1056fd4b8db51f1fa309a/fonttools-4.60.2-cp311-cp311-win_amd64.whl", hash = "sha256:91d058d5a483a1525b367803abb69de0923fbd45e1f82ebd000f5c8aa65bc78e", size = 2327574, upload-time = "2025-12-09T13:36:30.89Z" }, { url = "https://files.pythonhosted.org/packages/c0/30/530c9eddcd1c39219dc0aaede2b5a4c8ab80e0bb88d1b3ffc12944c4aac3/fonttools-4.60.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e0164b7609d2b5c5dd4e044b8085b7bd7ca7363ef8c269a4ab5b5d4885a426b2", size = 2847196, upload-time = "2025-12-09T13:36:33.262Z" }, { url = "https://files.pythonhosted.org/packages/19/2f/4077a482836d5bbe3bc9dac1c004d02ee227cf04ed62b0a2dfc41d4f0dfd/fonttools-4.60.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1dd3d9574fc595c1e97faccae0f264dc88784ddf7fbf54c939528378bacc0033", size = 2395842, upload-time = "2025-12-09T13:36:35.47Z" }, { url = "https://files.pythonhosted.org/packages/dd/05/aae5bb99c5398f8ed4a8b784f023fd9dd3568f0bd5d5b21e35b282550f11/fonttools-4.60.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:98d0719f1b11c2817307d2da2e94296a3b2a3503f8d6252a101dca3ee663b917", size = 4949713, upload-time = "2025-12-09T13:36:37.874Z" }, { url = "https://files.pythonhosted.org/packages/b4/37/49067349fc78ff0efbf09fadefe80ddf41473ca8f8a25400e3770da38328/fonttools-4.60.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9d3ea26957dd07209f207b4fff64c702efe5496de153a54d3b91007ec28904dd", size = 4999907, upload-time = "2025-12-09T13:36:39.853Z" }, { url = "https://files.pythonhosted.org/packages/16/31/d0f11c758bd0db36b664c92a0f9dfdcc2d7313749aa7d6629805c6946f21/fonttools-4.60.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ee301273b0850f3a515299f212898f37421f42ff9adfc341702582ca5073c13", size = 4939717, upload-time = "2025-12-09T13:36:43.075Z" }, { url = "https://files.pythonhosted.org/packages/d9/bc/1cff0d69522e561bf1b99bee7c3911c08c25e919584827c3454a64651ce9/fonttools-4.60.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c6eb4694cc3b9c03b7c01d65a9cf35b577f21aa6abdbeeb08d3114b842a58153", size = 5089205, upload-time = "2025-12-09T13:36:45.468Z" }, { url = "https://files.pythonhosted.org/packages/05/e6/fb174f0069b7122e19828c551298bfd34fdf9480535d2a6ac2ed37afacd3/fonttools-4.60.2-cp312-cp312-win32.whl", hash = "sha256:57f07b616c69c244cc1a5a51072eeef07dddda5ebef9ca5c6e9cf6d59ae65b70", size = 2264674, upload-time = "2025-12-09T13:36:49.238Z" }, { url = "https://files.pythonhosted.org/packages/75/57/6552ffd6b582d3e6a9f01780c5275e6dfff1e70ca146101733aa1c12a129/fonttools-4.60.2-cp312-cp312-win_amd64.whl", hash = "sha256:310035802392f1fe5a7cf43d76f6ff4a24c919e4c72c0352e7b8176e2584b8a0", size = 2314701, upload-time = "2025-12-09T13:36:51.09Z" }, { url = "https://files.pythonhosted.org/packages/2e/e4/8381d0ca6b6c6c484660b03517ec5b5b81feeefca3808726dece36c652a9/fonttools-4.60.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2bb5fd231e56ccd7403212636dcccffc96c5ae0d6f9e4721fa0a32cb2e3ca432", size = 2842063, upload-time = "2025-12-09T13:36:53.468Z" }, { url = "https://files.pythonhosted.org/packages/b4/2c/4367117ee8ff4f4374787a1222da0bd413d80cf3522111f727a7b8f80d1d/fonttools-4.60.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:536b5fab7b6fec78ccf59b5c59489189d9d0a8b0d3a77ed1858be59afb096696", size = 2393792, upload-time = "2025-12-09T13:36:55.742Z" }, { url = "https://files.pythonhosted.org/packages/49/b7/a76b6dffa193869e54e32ca2f9abb0d0e66784bc8a24e6f86eb093015481/fonttools-4.60.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6b9288fc38252ac86a9570f19313ecbc9ff678982e0f27c757a85f1f284d3400", size = 4924020, upload-time = "2025-12-09T13:36:58.229Z" }, { url = "https://files.pythonhosted.org/packages/bd/4e/0078200e2259f0061c86a74075f507d64c43dd2ab38971956a5c0012d344/fonttools-4.60.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93fcb420791d839ef592eada2b69997c445d0ce9c969b5190f2e16828ec10607", size = 4980070, upload-time = "2025-12-09T13:37:00.311Z" }, { url = "https://files.pythonhosted.org/packages/85/1f/d87c85a11cb84852c975251581862681e4a0c1c3bd456c648792203f311b/fonttools-4.60.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7916a381b094db4052ac284255186aebf74c5440248b78860cb41e300036f598", size = 4921411, upload-time = "2025-12-09T13:37:02.345Z" }, { url = "https://files.pythonhosted.org/packages/75/c0/7efad650f5ed8e317c2633133ef3c64917e7adf2e4e2940c798f5d57ec6e/fonttools-4.60.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58c8c393d5e16b15662cfc2d988491940458aa87894c662154f50c7b49440bef", size = 5063465, upload-time = "2025-12-09T13:37:04.836Z" }, { url = "https://files.pythonhosted.org/packages/18/a8/750518c4f8cdd79393b386bc81226047ade80239e58c6c9f5dbe1fdd8ea1/fonttools-4.60.2-cp313-cp313-win32.whl", hash = "sha256:19c6e0afd8b02008caa0aa08ab896dfce5d0bcb510c49b2c499541d5cb95a963", size = 2263443, upload-time = "2025-12-09T13:37:06.762Z" }, { url = "https://files.pythonhosted.org/packages/b8/22/026c60376f165981f80a0e90bd98a79ae3334e9d89a3d046c4d2e265c724/fonttools-4.60.2-cp313-cp313-win_amd64.whl", hash = "sha256:6a500dc59e11b2338c2dba1f8cf11a4ae8be35ec24af8b2628b8759a61457b76", size = 2313800, upload-time = "2025-12-09T13:37:08.713Z" }, { url = "https://files.pythonhosted.org/packages/7e/ab/7cf1f5204e1366ddf9dc5cdc2789b571feb9eebcee0e3463c3f457df5f52/fonttools-4.60.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:9387c532acbe323bbf2a920f132bce3c408a609d5f9dcfc6532fbc7e37f8ccbb", size = 2841690, upload-time = "2025-12-09T13:37:10.696Z" }, { url = "https://files.pythonhosted.org/packages/00/3c/0bf83c6f863cc8b934952567fa2bf737cfcec8fc4ffb59b3f93820095f89/fonttools-4.60.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6f1c824185b5b8fb681297f315f26ae55abb0d560c2579242feea8236b1cfef", size = 2392191, upload-time = "2025-12-09T13:37:12.954Z" }, { url = "https://files.pythonhosted.org/packages/00/f0/40090d148b8907fbea12e9bdf1ff149f30cdf1769e3b2c3e0dbf5106b88d/fonttools-4.60.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:55a3129d1e4030b1a30260f1b32fe76781b585fb2111d04a988e141c09eb6403", size = 4873503, upload-time = "2025-12-09T13:37:15.142Z" }, { url = "https://files.pythonhosted.org/packages/dc/e0/d8b13f99e58b8c293781288ba62fe634f1f0697c9c4c0ae104d3215f3a10/fonttools-4.60.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b196e63753abc33b3b97a6fd6de4b7c4fef5552c0a5ba5e562be214d1e9668e0", size = 4968493, upload-time = "2025-12-09T13:37:18.272Z" }, { url = "https://files.pythonhosted.org/packages/46/c5/960764d12c92bc225f02401d3067048cb7b282293d9e48e39fe2b0ec38a9/fonttools-4.60.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:de76c8d740fb55745f3b154f0470c56db92ae3be27af8ad6c2e88f1458260c9a", size = 4920015, upload-time = "2025-12-09T13:37:20.334Z" }, { url = "https://files.pythonhosted.org/packages/4b/ab/839d8caf253d1eef3653ef4d34427d0326d17a53efaec9eb04056b670fff/fonttools-4.60.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6ba6303225c95998c9fda2d410aa792c3d2c1390a09df58d194b03e17583fa25", size = 5031165, upload-time = "2025-12-09T13:37:23.57Z" }, { url = "https://files.pythonhosted.org/packages/de/bf/3bc862796a6841cbe0725bb5512d272239b809dba631a4b0301df885e62d/fonttools-4.60.2-cp314-cp314-win32.whl", hash = "sha256:0a89728ce10d7c816fedaa5380c06d2793e7a8a634d7ce16810e536c22047384", size = 2267526, upload-time = "2025-12-09T13:37:25.821Z" }, { url = "https://files.pythonhosted.org/packages/fc/a1/c1909cacf00c76dc37b4743451561fbaaf7db4172c22a6d9394081d114c3/fonttools-4.60.2-cp314-cp314-win_amd64.whl", hash = "sha256:fa8446e6ab8bd778b82cb1077058a2addba86f30de27ab9cc18ed32b34bc8667", size = 2319096, upload-time = "2025-12-09T13:37:28.058Z" }, { url = "https://files.pythonhosted.org/packages/29/b3/f66e71433f08e3a931b2b31a665aeed17fcc5e6911fc73529c70a232e421/fonttools-4.60.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4063bc81ac5a4137642865cb63dd270e37b3cd1f55a07c0d6e41d072699ccca2", size = 2925167, upload-time = "2025-12-09T13:37:30.348Z" }, { url = "https://files.pythonhosted.org/packages/2e/13/eeb491ff743594bbd0bee6e49422c03a59fe9c49002d3cc60eeb77414285/fonttools-4.60.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ebfdb66fa69732ed604ab8e2a0431e6deff35e933a11d73418cbc7823d03b8e1", size = 2430923, upload-time = "2025-12-09T13:37:32.817Z" }, { url = "https://files.pythonhosted.org/packages/b2/e5/db609f785e460796e53c4dbc3874a5f4948477f27beceb5e2d24b2537666/fonttools-4.60.2-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50b10b3b1a72d1d54c61b0e59239e1a94c0958f4a06a1febf97ce75388dd91a4", size = 4877729, upload-time = "2025-12-09T13:37:35.858Z" }, { url = "https://files.pythonhosted.org/packages/5f/d6/85e4484dd4bfb03fee7bd370d65888cccbd3dee2681ee48c869dd5ccb23f/fonttools-4.60.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:beae16891a13b4a2ddec9b39b4de76092a3025e4d1c82362e3042b62295d5e4d", size = 5096003, upload-time = "2025-12-09T13:37:37.862Z" }, { url = "https://files.pythonhosted.org/packages/30/49/1a98e44b71030b83d2046f981373b80571868259d98e6dae7bc20099dac6/fonttools-4.60.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:522f017fdb3766fd5d2d321774ef351cc6ce88ad4e6ac9efe643e4a2b9d528db", size = 4974410, upload-time = "2025-12-09T13:37:40.166Z" }, { url = "https://files.pythonhosted.org/packages/42/07/d6f775d950ee8a841012472c7303f8819423d8cc3b4530915de7265ebfa2/fonttools-4.60.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82cceceaf9c09a965a75b84a4b240dd3768e596ffb65ef53852681606fe7c9ba", size = 5002036, upload-time = "2025-12-09T13:37:42.639Z" }, { url = "https://files.pythonhosted.org/packages/73/f6/ba6458f83ce1a9f8c3b17bd8f7b8a2205a126aac1055796b7e7cfebbd38f/fonttools-4.60.2-cp314-cp314t-win32.whl", hash = "sha256:bbfbc918a75437fe7e6d64d1b1e1f713237df1cf00f3a36dedae910b2ba01cee", size = 2330985, upload-time = "2025-12-09T13:37:45.157Z" }, { url = "https://files.pythonhosted.org/packages/91/24/fea0ba4d3a32d4ed1103a1098bfd99dc78b5fe3bb97202920744a37b73dc/fonttools-4.60.2-cp314-cp314t-win_amd64.whl", hash = "sha256:0e5cd9b0830f6550d58c84f3ab151a9892b50c4f9d538c5603c0ce6fff2eb3f1", size = 2396226, upload-time = "2025-12-09T13:37:47.355Z" }, { url = "https://files.pythonhosted.org/packages/55/ae/a6d9446cb258d3fe87e311c2d7bacf8e8da3e5809fbdc3a8306db4f6b14e/fonttools-4.60.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a3c75b8b42f7f93906bdba9eb1197bb76aecbe9a0a7cf6feec75f7605b5e8008", size = 2857184, upload-time = "2025-12-09T13:37:49.96Z" }, { url = "https://files.pythonhosted.org/packages/3a/f3/1b41d0b6a8b908aa07f652111155dd653ebbf0b3385e66562556c5206685/fonttools-4.60.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0f86c8c37bc0ec0b9c141d5e90c717ff614e93c187f06d80f18c7057097f71bc", size = 2401877, upload-time = "2025-12-09T13:37:52.307Z" }, { url = "https://files.pythonhosted.org/packages/71/57/048fd781680c38b05c5463657d0d95d5f2391a51972176e175c01de29d42/fonttools-4.60.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe905403fe59683b0e9a45f234af2866834376b8821f34633b1c76fb731b6311", size = 4878073, upload-time = "2025-12-09T13:37:56.477Z" }, { url = "https://files.pythonhosted.org/packages/45/bb/363364f052a893cebd3d449588b21244a9d873620fda03ad92702d2e1bc7/fonttools-4.60.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38ce703b60a906e421e12d9e3a7f064883f5e61bb23e8961f4be33cfe578500b", size = 4835385, upload-time = "2025-12-09T13:37:58.882Z" }, { url = "https://files.pythonhosted.org/packages/1c/38/e392bb930b2436287e6021672345db26441bf1f85f1e98f8b9784334e41d/fonttools-4.60.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9e810c06f3e79185cecf120e58b343ea5a89b54dd695fd644446bcf8c026da5e", size = 4853084, upload-time = "2025-12-09T13:38:01.578Z" }, { url = "https://files.pythonhosted.org/packages/65/60/0d77faeaecf7a3276a8a6dc49e2274357e6b3ed6a1774e2fdb2a7f142db0/fonttools-4.60.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:38faec8cc1d12122599814d15a402183f5123fb7608dac956121e7c6742aebc5", size = 4971144, upload-time = "2025-12-09T13:38:03.748Z" }, { url = "https://files.pythonhosted.org/packages/ba/c7/6d3ac3afbcd598631bce24c3ecb919e7d0644a82fea8ddc4454312fc0be6/fonttools-4.60.2-cp39-cp39-win32.whl", hash = "sha256:80a45cf7bf659acb7b36578f300231873daba67bd3ca8cce181c73f861f14a37", size = 1499411, upload-time = "2025-12-09T13:38:05.586Z" }, { url = "https://files.pythonhosted.org/packages/5a/1c/9dedf6420e23f9fa630bb97941839dddd2e1e57d1b2b85a902378dbe0bd2/fonttools-4.60.2-cp39-cp39-win_amd64.whl", hash = "sha256:c355d5972071938e1b1e0f5a1df001f68ecf1a62f34a3407dc8e0beccf052501", size = 1547943, upload-time = "2025-12-09T13:38:07.604Z" }, { url = "https://files.pythonhosted.org/packages/79/6c/10280af05b44fafd1dff69422805061fa1af29270bc52dce031ac69540bf/fonttools-4.60.2-py3-none-any.whl", hash = "sha256:73cf92eeda67cf6ff10c8af56fc8f4f07c1647d989a979be9e388a49be26552a", size = 1144610, upload-time = "2025-12-09T13:38:09.5Z" }, ] [[package]] name = "fonttools" version = "4.61.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/ec/ca/cf17b88a8df95691275a3d77dc0a5ad9907f328ae53acbe6795da1b2f5ed/fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69", size = 3565756, upload-time = "2025-12-12T17:31:24.246Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5b/94/8a28707adb00bed1bf22dac16ccafe60faf2ade353dcb32c3617ee917307/fonttools-4.61.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c7db70d57e5e1089a274cbb2b1fd635c9a24de809a231b154965d415d6c6d24", size = 2854799, upload-time = "2025-12-12T17:29:27.5Z" }, { url = "https://files.pythonhosted.org/packages/94/93/c2e682faaa5ee92034818d8f8a8145ae73eb83619600495dcf8503fa7771/fonttools-4.61.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5fe9fd43882620017add5eabb781ebfbc6998ee49b35bd7f8f79af1f9f99a958", size = 2403032, upload-time = "2025-12-12T17:29:30.115Z" }, { url = "https://files.pythonhosted.org/packages/f1/62/1748f7e7e1ee41aa52279fd2e3a6d0733dc42a673b16932bad8e5d0c8b28/fonttools-4.61.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8db08051fc9e7d8bc622f2112511b8107d8f27cd89e2f64ec45e9825e8288da", size = 4897863, upload-time = "2025-12-12T17:29:32.535Z" }, { url = "https://files.pythonhosted.org/packages/69/69/4ca02ee367d2c98edcaeb83fc278d20972502ee071214ad9d8ca85e06080/fonttools-4.61.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a76d4cb80f41ba94a6691264be76435e5f72f2cb3cab0b092a6212855f71c2f6", size = 4859076, upload-time = "2025-12-12T17:29:34.907Z" }, { url = "https://files.pythonhosted.org/packages/8c/f5/660f9e3cefa078861a7f099107c6d203b568a6227eef163dd173bfc56bdc/fonttools-4.61.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a13fc8aeb24bad755eea8f7f9d409438eb94e82cf86b08fe77a03fbc8f6a96b1", size = 4875623, upload-time = "2025-12-12T17:29:37.33Z" }, { url = "https://files.pythonhosted.org/packages/63/d1/9d7c5091d2276ed47795c131c1bf9316c3c1ab2789c22e2f59e0572ccd38/fonttools-4.61.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b846a1fcf8beadeb9ea4f44ec5bdde393e2f1569e17d700bfc49cd69bde75881", size = 4993327, upload-time = "2025-12-12T17:29:39.781Z" }, { url = "https://files.pythonhosted.org/packages/6f/2d/28def73837885ae32260d07660a052b99f0aa00454867d33745dfe49dbf0/fonttools-4.61.1-cp310-cp310-win32.whl", hash = "sha256:78a7d3ab09dc47ac1a363a493e6112d8cabed7ba7caad5f54dbe2f08676d1b47", size = 1502180, upload-time = "2025-12-12T17:29:42.217Z" }, { url = "https://files.pythonhosted.org/packages/63/fa/bfdc98abb4dd2bd491033e85e3ba69a2313c850e759a6daa014bc9433b0f/fonttools-4.61.1-cp310-cp310-win_amd64.whl", hash = "sha256:eff1ac3cc66c2ac7cda1e64b4e2f3ffef474b7335f92fc3833fc632d595fcee6", size = 1550654, upload-time = "2025-12-12T17:29:44.564Z" }, { url = "https://files.pythonhosted.org/packages/69/12/bf9f4eaa2fad039356cc627587e30ed008c03f1cebd3034376b5ee8d1d44/fonttools-4.61.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c6604b735bb12fef8e0efd5578c9fb5d3d8532d5001ea13a19cddf295673ee09", size = 2852213, upload-time = "2025-12-12T17:29:46.675Z" }, { url = "https://files.pythonhosted.org/packages/ac/49/4138d1acb6261499bedde1c07f8c2605d1d8f9d77a151e5507fd3ef084b6/fonttools-4.61.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ce02f38a754f207f2f06557523cd39a06438ba3aafc0639c477ac409fc64e37", size = 2401689, upload-time = "2025-12-12T17:29:48.769Z" }, { url = "https://files.pythonhosted.org/packages/e5/fe/e6ce0fe20a40e03aef906af60aa87668696f9e4802fa283627d0b5ed777f/fonttools-4.61.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77efb033d8d7ff233385f30c62c7c79271c8885d5c9657d967ede124671bbdfb", size = 5058809, upload-time = "2025-12-12T17:29:51.701Z" }, { url = "https://files.pythonhosted.org/packages/79/61/1ca198af22f7dd22c17ab86e9024ed3c06299cfdb08170640e9996d501a0/fonttools-4.61.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:75c1a6dfac6abd407634420c93864a1e274ebc1c7531346d9254c0d8f6ca00f9", size = 5036039, upload-time = "2025-12-12T17:29:53.659Z" }, { url = "https://files.pythonhosted.org/packages/99/cc/fa1801e408586b5fce4da9f5455af8d770f4fc57391cd5da7256bb364d38/fonttools-4.61.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0de30bfe7745c0d1ffa2b0b7048fb7123ad0d71107e10ee090fa0b16b9452e87", size = 5034714, upload-time = "2025-12-12T17:29:55.592Z" }, { url = "https://files.pythonhosted.org/packages/bf/aa/b7aeafe65adb1b0a925f8f25725e09f078c635bc22754f3fecb7456955b0/fonttools-4.61.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58b0ee0ab5b1fc9921eccfe11d1435added19d6494dde14e323f25ad2bc30c56", size = 5158648, upload-time = "2025-12-12T17:29:57.861Z" }, { url = "https://files.pythonhosted.org/packages/99/f9/08ea7a38663328881384c6e7777bbefc46fd7d282adfd87a7d2b84ec9d50/fonttools-4.61.1-cp311-cp311-win32.whl", hash = "sha256:f79b168428351d11e10c5aeb61a74e1851ec221081299f4cf56036a95431c43a", size = 2280681, upload-time = "2025-12-12T17:29:59.943Z" }, { url = "https://files.pythonhosted.org/packages/07/ad/37dd1ae5fa6e01612a1fbb954f0927681f282925a86e86198ccd7b15d515/fonttools-4.61.1-cp311-cp311-win_amd64.whl", hash = "sha256:fe2efccb324948a11dd09d22136fe2ac8a97d6c1347cf0b58a911dcd529f66b7", size = 2331951, upload-time = "2025-12-12T17:30:02.254Z" }, { url = "https://files.pythonhosted.org/packages/6f/16/7decaa24a1bd3a70c607b2e29f0adc6159f36a7e40eaba59846414765fd4/fonttools-4.61.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f3cb4a569029b9f291f88aafc927dd53683757e640081ca8c412781ea144565e", size = 2851593, upload-time = "2025-12-12T17:30:04.225Z" }, { url = "https://files.pythonhosted.org/packages/94/98/3c4cb97c64713a8cf499b3245c3bf9a2b8fd16a3e375feff2aed78f96259/fonttools-4.61.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41a7170d042e8c0024703ed13b71893519a1a6d6e18e933e3ec7507a2c26a4b2", size = 2400231, upload-time = "2025-12-12T17:30:06.47Z" }, { url = "https://files.pythonhosted.org/packages/b7/37/82dbef0f6342eb01f54bca073ac1498433d6ce71e50c3c3282b655733b31/fonttools-4.61.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10d88e55330e092940584774ee5e8a6971b01fc2f4d3466a1d6c158230880796", size = 4954103, upload-time = "2025-12-12T17:30:08.432Z" }, { url = "https://files.pythonhosted.org/packages/6c/44/f3aeac0fa98e7ad527f479e161aca6c3a1e47bb6996b053d45226fe37bf2/fonttools-4.61.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15acc09befd16a0fb8a8f62bc147e1a82817542d72184acca9ce6e0aeda9fa6d", size = 5004295, upload-time = "2025-12-12T17:30:10.56Z" }, { url = "https://files.pythonhosted.org/packages/14/e8/7424ced75473983b964d09f6747fa09f054a6d656f60e9ac9324cf40c743/fonttools-4.61.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6bcdf33aec38d16508ce61fd81838f24c83c90a1d1b8c68982857038673d6b8", size = 4944109, upload-time = "2025-12-12T17:30:12.874Z" }, { url = "https://files.pythonhosted.org/packages/c8/8b/6391b257fa3d0b553d73e778f953a2f0154292a7a7a085e2374b111e5410/fonttools-4.61.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5fade934607a523614726119164ff621e8c30e8fa1ffffbbd358662056ba69f0", size = 5093598, upload-time = "2025-12-12T17:30:15.79Z" }, { url = "https://files.pythonhosted.org/packages/d9/71/fd2ea96cdc512d92da5678a1c98c267ddd4d8c5130b76d0f7a80f9a9fde8/fonttools-4.61.1-cp312-cp312-win32.whl", hash = "sha256:75da8f28eff26defba42c52986de97b22106cb8f26515b7c22443ebc9c2d3261", size = 2269060, upload-time = "2025-12-12T17:30:18.058Z" }, { url = "https://files.pythonhosted.org/packages/80/3b/a3e81b71aed5a688e89dfe0e2694b26b78c7d7f39a5ffd8a7d75f54a12a8/fonttools-4.61.1-cp312-cp312-win_amd64.whl", hash = "sha256:497c31ce314219888c0e2fce5ad9178ca83fe5230b01a5006726cdf3ac9f24d9", size = 2319078, upload-time = "2025-12-12T17:30:22.862Z" }, { url = "https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c", size = 2846454, upload-time = "2025-12-12T17:30:24.938Z" }, { url = "https://files.pythonhosted.org/packages/5a/ca/468c9a8446a2103ae645d14fee3f610567b7042aba85031c1c65e3ef7471/fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e", size = 2398191, upload-time = "2025-12-12T17:30:27.343Z" }, { url = "https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5", size = 4928410, upload-time = "2025-12-12T17:30:29.771Z" }, { url = "https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd", size = 4984460, upload-time = "2025-12-12T17:30:32.073Z" }, { url = "https://files.pythonhosted.org/packages/f7/f1/a47f1d30b3dc00d75e7af762652d4cbc3dff5c2697a0dbd5203c81afd9c3/fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3", size = 4925800, upload-time = "2025-12-12T17:30:34.339Z" }, { url = "https://files.pythonhosted.org/packages/a7/01/e6ae64a0981076e8a66906fab01539799546181e32a37a0257b77e4aa88b/fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d", size = 5067859, upload-time = "2025-12-12T17:30:36.593Z" }, { url = "https://files.pythonhosted.org/packages/73/aa/28e40b8d6809a9b5075350a86779163f074d2b617c15d22343fce81918db/fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c", size = 2267821, upload-time = "2025-12-12T17:30:38.478Z" }, { url = "https://files.pythonhosted.org/packages/1a/59/453c06d1d83dc0951b69ef692d6b9f1846680342927df54e9a1ca91c6f90/fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b", size = 2318169, upload-time = "2025-12-12T17:30:40.951Z" }, { url = "https://files.pythonhosted.org/packages/32/8f/4e7bf82c0cbb738d3c2206c920ca34ca74ef9dabde779030145d28665104/fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd", size = 2846094, upload-time = "2025-12-12T17:30:43.511Z" }, { url = "https://files.pythonhosted.org/packages/71/09/d44e45d0a4f3a651f23a1e9d42de43bc643cce2971b19e784cc67d823676/fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e", size = 2396589, upload-time = "2025-12-12T17:30:45.681Z" }, { url = "https://files.pythonhosted.org/packages/89/18/58c64cafcf8eb677a99ef593121f719e6dcbdb7d1c594ae5a10d4997ca8a/fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c", size = 4877892, upload-time = "2025-12-12T17:30:47.709Z" }, { url = "https://files.pythonhosted.org/packages/8a/ec/9e6b38c7ba1e09eb51db849d5450f4c05b7e78481f662c3b79dbde6f3d04/fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75", size = 4972884, upload-time = "2025-12-12T17:30:49.656Z" }, { url = "https://files.pythonhosted.org/packages/5e/87/b5339da8e0256734ba0dbbf5b6cdebb1dd79b01dc8c270989b7bcd465541/fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063", size = 4924405, upload-time = "2025-12-12T17:30:51.735Z" }, { url = "https://files.pythonhosted.org/packages/0b/47/e3409f1e1e69c073a3a6fd8cb886eb18c0bae0ee13db2c8d5e7f8495e8b7/fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2", size = 5035553, upload-time = "2025-12-12T17:30:54.823Z" }, { url = "https://files.pythonhosted.org/packages/bf/b6/1f6600161b1073a984294c6c031e1a56ebf95b6164249eecf30012bb2e38/fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c", size = 2271915, upload-time = "2025-12-12T17:30:57.913Z" }, { url = "https://files.pythonhosted.org/packages/52/7b/91e7b01e37cc8eb0e1f770d08305b3655e4f002fc160fb82b3390eabacf5/fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c", size = 2323487, upload-time = "2025-12-12T17:30:59.804Z" }, { url = "https://files.pythonhosted.org/packages/39/5c/908ad78e46c61c3e3ed70c3b58ff82ab48437faf84ec84f109592cabbd9f/fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa", size = 2929571, upload-time = "2025-12-12T17:31:02.574Z" }, { url = "https://files.pythonhosted.org/packages/bd/41/975804132c6dea64cdbfbaa59f3518a21c137a10cccf962805b301ac6ab2/fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91", size = 2435317, upload-time = "2025-12-12T17:31:04.974Z" }, { url = "https://files.pythonhosted.org/packages/b0/5a/aef2a0a8daf1ebaae4cfd83f84186d4a72ee08fd6a8451289fcd03ffa8a4/fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19", size = 4882124, upload-time = "2025-12-12T17:31:07.456Z" }, { url = "https://files.pythonhosted.org/packages/80/33/d6db3485b645b81cea538c9d1c9219d5805f0877fda18777add4671c5240/fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba", size = 5100391, upload-time = "2025-12-12T17:31:09.732Z" }, { url = "https://files.pythonhosted.org/packages/6c/d6/675ba631454043c75fcf76f0ca5463eac8eb0666ea1d7badae5fea001155/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7", size = 4978800, upload-time = "2025-12-12T17:31:11.681Z" }, { url = "https://files.pythonhosted.org/packages/7f/33/d3ec753d547a8d2bdaedd390d4a814e8d5b45a093d558f025c6b990b554c/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118", size = 5006426, upload-time = "2025-12-12T17:31:13.764Z" }, { url = "https://files.pythonhosted.org/packages/b4/40/cc11f378b561a67bea850ab50063366a0d1dd3f6d0a30ce0f874b0ad5664/fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5", size = 2335377, upload-time = "2025-12-12T17:31:16.49Z" }, { url = "https://files.pythonhosted.org/packages/e4/ff/c9a2b66b39f8628531ea58b320d66d951267c98c6a38684daa8f50fb02f8/fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b", size = 2400613, upload-time = "2025-12-12T17:31:18.769Z" }, { url = "https://files.pythonhosted.org/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371", size = 1148996, upload-time = "2025-12-12T17:31:21.03Z" }, ] [[package]] name = "h5py" version = "3.14.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5d/57/dfb3c5c3f1bf5f5ef2e59a22dec4ff1f3d7408b55bfcefcfb0ea69ef21c6/h5py-3.14.0.tar.gz", hash = "sha256:2372116b2e0d5d3e5e705b7f663f7c8d96fa79a4052d250484ef91d24d6a08f4", size = 424323, upload-time = "2025-06-06T14:06:15.01Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/52/89/06cbb421e01dea2e338b3154326523c05d9698f89a01f9d9b65e1ec3fb18/h5py-3.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:24df6b2622f426857bda88683b16630014588a0e4155cba44e872eb011c4eaed", size = 3332522, upload-time = "2025-06-06T14:04:13.775Z" }, { url = "https://files.pythonhosted.org/packages/c3/e7/6c860b002329e408348735bfd0459e7b12f712c83d357abeef3ef404eaa9/h5py-3.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ff2389961ee5872de697054dd5a033b04284afc3fb52dc51d94561ece2c10c6", size = 2831051, upload-time = "2025-06-06T14:04:18.206Z" }, { url = "https://files.pythonhosted.org/packages/fa/cd/3dd38cdb7cc9266dc4d85f27f0261680cb62f553f1523167ad7454e32b11/h5py-3.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:016e89d3be4c44f8d5e115fab60548e518ecd9efe9fa5c5324505a90773e6f03", size = 4324677, upload-time = "2025-06-06T14:04:23.438Z" }, { url = "https://files.pythonhosted.org/packages/b1/45/e1a754dc7cd465ba35e438e28557119221ac89b20aaebef48282654e3dc7/h5py-3.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1223b902ef0b5d90bcc8a4778218d6d6cd0f5561861611eda59fa6c52b922f4d", size = 4557272, upload-time = "2025-06-06T14:04:28.863Z" }, { url = "https://files.pythonhosted.org/packages/5c/06/f9506c1531645829d302c420851b78bb717af808dde11212c113585fae42/h5py-3.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:852b81f71df4bb9e27d407b43071d1da330d6a7094a588efa50ef02553fa7ce4", size = 2866734, upload-time = "2025-06-06T14:04:33.5Z" }, { url = "https://files.pythonhosted.org/packages/61/1b/ad24a8ce846cf0519695c10491e99969d9d203b9632c4fcd5004b1641c2e/h5py-3.14.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f30dbc58f2a0efeec6c8836c97f6c94afd769023f44e2bb0ed7b17a16ec46088", size = 3352382, upload-time = "2025-06-06T14:04:37.95Z" }, { url = "https://files.pythonhosted.org/packages/36/5b/a066e459ca48b47cc73a5c668e9924d9619da9e3c500d9fb9c29c03858ec/h5py-3.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:543877d7f3d8f8a9828ed5df6a0b78ca3d8846244b9702e99ed0d53610b583a8", size = 2852492, upload-time = "2025-06-06T14:04:42.092Z" }, { url = "https://files.pythonhosted.org/packages/08/0c/5e6aaf221557314bc15ba0e0da92e40b24af97ab162076c8ae009320a42b/h5py-3.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c497600c0496548810047257e36360ff551df8b59156d3a4181072eed47d8ad", size = 4298002, upload-time = "2025-06-06T14:04:47.106Z" }, { url = "https://files.pythonhosted.org/packages/21/d4/d461649cafd5137088fb7f8e78fdc6621bb0c4ff2c090a389f68e8edc136/h5py-3.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:723a40ee6505bd354bfd26385f2dae7bbfa87655f4e61bab175a49d72ebfc06b", size = 4516618, upload-time = "2025-06-06T14:04:52.467Z" }, { url = "https://files.pythonhosted.org/packages/db/0c/6c3f879a0f8e891625817637fad902da6e764e36919ed091dc77529004ac/h5py-3.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:d2744b520440a996f2dae97f901caa8a953afc055db4673a993f2d87d7f38713", size = 2874888, upload-time = "2025-06-06T14:04:56.95Z" }, { url = "https://files.pythonhosted.org/packages/3e/77/8f651053c1843391e38a189ccf50df7e261ef8cd8bfd8baba0cbe694f7c3/h5py-3.14.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e0045115d83272090b0717c555a31398c2c089b87d212ceba800d3dc5d952e23", size = 3312740, upload-time = "2025-06-06T14:05:01.193Z" }, { url = "https://files.pythonhosted.org/packages/ff/10/20436a6cf419b31124e59fefc78d74cb061ccb22213226a583928a65d715/h5py-3.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6da62509b7e1d71a7d110478aa25d245dd32c8d9a1daee9d2a42dba8717b047a", size = 2829207, upload-time = "2025-06-06T14:05:05.061Z" }, { url = "https://files.pythonhosted.org/packages/3f/19/c8bfe8543bfdd7ccfafd46d8cfd96fce53d6c33e9c7921f375530ee1d39a/h5py-3.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554ef0ced3571366d4d383427c00c966c360e178b5fb5ee5bb31a435c424db0c", size = 4708455, upload-time = "2025-06-06T14:05:11.528Z" }, { url = "https://files.pythonhosted.org/packages/86/f9/f00de11c82c88bfc1ef22633557bfba9e271e0cb3189ad704183fc4a2644/h5py-3.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cbd41f4e3761f150aa5b662df991868ca533872c95467216f2bec5fcad84882", size = 4929422, upload-time = "2025-06-06T14:05:18.399Z" }, { url = "https://files.pythonhosted.org/packages/7a/6d/6426d5d456f593c94b96fa942a9b3988ce4d65ebaf57d7273e452a7222e8/h5py-3.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:bf4897d67e613ecf5bdfbdab39a1158a64df105827da70ea1d90243d796d367f", size = 2862845, upload-time = "2025-06-06T14:05:23.699Z" }, { url = "https://files.pythonhosted.org/packages/6c/c2/7efe82d09ca10afd77cd7c286e42342d520c049a8c43650194928bcc635c/h5py-3.14.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:aa4b7bbce683379b7bf80aaba68e17e23396100336a8d500206520052be2f812", size = 3289245, upload-time = "2025-06-06T14:05:28.24Z" }, { url = "https://files.pythonhosted.org/packages/4f/31/f570fab1239b0d9441024b92b6ad03bb414ffa69101a985e4c83d37608bd/h5py-3.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9603a501a04fcd0ba28dd8f0995303d26a77a980a1f9474b3417543d4c6174", size = 2807335, upload-time = "2025-06-06T14:05:31.997Z" }, { url = "https://files.pythonhosted.org/packages/0d/ce/3a21d87896bc7e3e9255e0ad5583ae31ae9e6b4b00e0bcb2a67e2b6acdbc/h5py-3.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8cbaf6910fa3983c46172666b0b8da7b7bd90d764399ca983236f2400436eeb", size = 4700675, upload-time = "2025-06-06T14:05:37.38Z" }, { url = "https://files.pythonhosted.org/packages/e7/ec/86f59025306dcc6deee5fda54d980d077075b8d9889aac80f158bd585f1b/h5py-3.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d90e6445ab7c146d7f7981b11895d70bc1dd91278a4f9f9028bc0c95e4a53f13", size = 4921632, upload-time = "2025-06-06T14:05:43.464Z" }, { url = "https://files.pythonhosted.org/packages/3f/6d/0084ed0b78d4fd3e7530c32491f2884140d9b06365dac8a08de726421d4a/h5py-3.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:ae18e3de237a7a830adb76aaa68ad438d85fe6e19e0d99944a3ce46b772c69b3", size = 2852929, upload-time = "2025-06-06T14:05:47.659Z" }, { url = "https://files.pythonhosted.org/packages/ec/ac/9ea82488c8790ee5b6ad1a807cd7dc3b9dadfece1cd0e0e369f68a7a8937/h5py-3.14.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5cc1601e78027cedfec6dd50efb4802f018551754191aeb58d948bd3ec3bd7a", size = 3345097, upload-time = "2025-06-06T14:05:51.984Z" }, { url = "https://files.pythonhosted.org/packages/6c/bc/a172ecaaf287e3af2f837f23b470b0a2229c79555a0da9ac8b5cc5bed078/h5py-3.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e59d2136a8b302afd25acdf7a89b634e0eb7c66b1a211ef2d0457853768a2ef", size = 2843320, upload-time = "2025-06-06T14:05:55.754Z" }, { url = "https://files.pythonhosted.org/packages/66/40/b423b57696514e05aa7bb06150ef96667d0e0006cc6de7ab52c71734ab51/h5py-3.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:573c33ad056ac7c1ab6d567b6db9df3ffc401045e3f605736218f96c1e0490c6", size = 4326368, upload-time = "2025-06-06T14:06:00.782Z" }, { url = "https://files.pythonhosted.org/packages/f7/07/e088f89f04fdbe57ddf9de377f857158d3daa38cf5d0fb20ef9bd489e313/h5py-3.14.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ccbe17dc187c0c64178f1a10aa274ed3a57d055117588942b8a08793cc448216", size = 4559686, upload-time = "2025-06-06T14:06:07.416Z" }, { url = "https://files.pythonhosted.org/packages/b4/e4/fb8032d0e5480b1db9b419b5b50737b61bb3c7187c49d809975d62129fb0/h5py-3.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:4f025cf30ae738c4c4e38c7439a761a71ccfcce04c2b87b2a2ac64e8c5171d43", size = 2877166, upload-time = "2025-06-06T14:06:13.05Z" }, ] [[package]] name = "h5py" version = "3.15.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4d/6a/0d79de0b025aa85dc8864de8e97659c94cf3d23148394a954dc5ca52f8c8/h5py-3.15.1.tar.gz", hash = "sha256:c86e3ed45c4473564de55aa83b6fc9e5ead86578773dfbd93047380042e26b69", size = 426236, upload-time = "2025-10-16T10:35:27.404Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/86/30/8fa61698b438dd751fa46a359792e801191dadab560d0a5f1c709443ef8e/h5py-3.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:67e59f6c2f19a32973a40f43d9a088ae324fe228c8366e25ebc57ceebf093a6b", size = 3414477, upload-time = "2025-10-16T10:33:24.201Z" }, { url = "https://files.pythonhosted.org/packages/16/16/db2f63302937337c4e9e51d97a5984b769bdb7488e3d37632a6ac297f8ef/h5py-3.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e2f471688402c3404fa4e13466e373e622fd4b74b47b56cfdff7cc688209422", size = 2850298, upload-time = "2025-10-16T10:33:27.747Z" }, { url = "https://files.pythonhosted.org/packages/fc/2e/f1bb7de9b05112bfd14d5206090f0f92f1e75bbb412fbec5d4653c3d44dd/h5py-3.15.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c45802bcb711e128a6839cb6c01e9ac648dc55df045c9542a675c771f15c8d5", size = 4523605, upload-time = "2025-10-16T10:33:31.168Z" }, { url = "https://files.pythonhosted.org/packages/05/8a/63f4b08f3628171ce8da1a04681a65ee7ac338fde3cb3e9e3c9f7818e4da/h5py-3.15.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64ce3f6470adb87c06e3a8dd1b90e973699f1759ad79bfa70c230939bff356c9", size = 4735346, upload-time = "2025-10-16T10:33:34.759Z" }, { url = "https://files.pythonhosted.org/packages/74/48/f16d12d9de22277605bcc11c0dcab5e35f06a54be4798faa2636b5d44b3c/h5py-3.15.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4411c1867b9899a25e983fff56d820a66f52ac326bbe10c7cdf7d832c9dcd883", size = 4175305, upload-time = "2025-10-16T10:33:38.83Z" }, { url = "https://files.pythonhosted.org/packages/d6/2f/47cdbff65b2ce53c27458c6df63a232d7bb1644b97df37b2342442342c84/h5py-3.15.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2cbc4104d3d4aca9d6db8c0c694555e255805bfeacf9eb1349bda871e26cacbe", size = 4653602, upload-time = "2025-10-16T10:33:42.188Z" }, { url = "https://files.pythonhosted.org/packages/c3/28/dc08de359c2f43a67baa529cb70d7f9599848750031975eed92d6ae78e1d/h5py-3.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:01f55111ca516f5568ae7a7fc8247dfce607de331b4467ee8a9a6ed14e5422c7", size = 2873601, upload-time = "2025-10-16T10:33:45.323Z" }, { url = "https://files.pythonhosted.org/packages/41/fd/8349b48b15b47768042cff06ad6e1c229f0a4bd89225bf6b6894fea27e6d/h5py-3.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5aaa330bcbf2830150c50897ea5dcbed30b5b6d56897289846ac5b9e529ec243", size = 3434135, upload-time = "2025-10-16T10:33:47.954Z" }, { url = "https://files.pythonhosted.org/packages/c1/b0/1c628e26a0b95858f54aba17e1599e7f6cd241727596cc2580b72cb0a9bf/h5py-3.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c970fb80001fffabb0109eaf95116c8e7c0d3ca2de854e0901e8a04c1f098509", size = 2870958, upload-time = "2025-10-16T10:33:50.907Z" }, { url = "https://files.pythonhosted.org/packages/f9/e3/c255cafc9b85e6ea04e2ad1bba1416baa1d7f57fc98a214be1144087690c/h5py-3.15.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80e5bb5b9508d5d9da09f81fd00abbb3f85da8143e56b1585d59bc8ceb1dba8b", size = 4504770, upload-time = "2025-10-16T10:33:54.357Z" }, { url = "https://files.pythonhosted.org/packages/8b/23/4ab1108e87851ccc69694b03b817d92e142966a6c4abd99e17db77f2c066/h5py-3.15.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b849ba619a066196169763c33f9f0f02e381156d61c03e000bb0100f9950faf", size = 4700329, upload-time = "2025-10-16T10:33:57.616Z" }, { url = "https://files.pythonhosted.org/packages/a4/e4/932a3a8516e4e475b90969bf250b1924dbe3612a02b897e426613aed68f4/h5py-3.15.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e7f6c841efd4e6e5b7e82222eaf90819927b6d256ab0f3aca29675601f654f3c", size = 4152456, upload-time = "2025-10-16T10:34:00.843Z" }, { url = "https://files.pythonhosted.org/packages/2a/0a/f74d589883b13737021b2049ac796328f188dbb60c2ed35b101f5b95a3fc/h5py-3.15.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ca8a3a22458956ee7b40d8e39c9a9dc01f82933e4c030c964f8b875592f4d831", size = 4617295, upload-time = "2025-10-16T10:34:04.154Z" }, { url = "https://files.pythonhosted.org/packages/23/95/499b4e56452ef8b6c95a271af0dde08dac4ddb70515a75f346d4f400579b/h5py-3.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:550e51131376889656feec4aff2170efc054a7fe79eb1da3bb92e1625d1ac878", size = 2882129, upload-time = "2025-10-16T10:34:06.886Z" }, { url = "https://files.pythonhosted.org/packages/ce/bb/cfcc70b8a42222ba3ad4478bcef1791181ea908e2adbd7d53c66395edad5/h5py-3.15.1-cp311-cp311-win_arm64.whl", hash = "sha256:b39239947cb36a819147fc19e86b618dcb0953d1cd969f5ed71fc0de60392427", size = 2477121, upload-time = "2025-10-16T10:34:09.579Z" }, { url = "https://files.pythonhosted.org/packages/62/b8/c0d9aa013ecfa8b7057946c080c0c07f6fa41e231d2e9bd306a2f8110bdc/h5py-3.15.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:316dd0f119734f324ca7ed10b5627a2de4ea42cc4dfbcedbee026aaa361c238c", size = 3399089, upload-time = "2025-10-16T10:34:12.135Z" }, { url = "https://files.pythonhosted.org/packages/a4/5e/3c6f6e0430813c7aefe784d00c6711166f46225f5d229546eb53032c3707/h5py-3.15.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b51469890e58e85d5242e43aab29f5e9c7e526b951caab354f3ded4ac88e7b76", size = 2847803, upload-time = "2025-10-16T10:34:14.564Z" }, { url = "https://files.pythonhosted.org/packages/00/69/ba36273b888a4a48d78f9268d2aee05787e4438557450a8442946ab8f3ec/h5py-3.15.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a33bfd5dfcea037196f7778534b1ff7e36a7f40a89e648c8f2967292eb6898e", size = 4914884, upload-time = "2025-10-16T10:34:18.452Z" }, { url = "https://files.pythonhosted.org/packages/3a/30/d1c94066343a98bb2cea40120873193a4fed68c4ad7f8935c11caf74c681/h5py-3.15.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25c8843fec43b2cc368aa15afa1cdf83fc5e17b1c4e10cd3771ef6c39b72e5ce", size = 5109965, upload-time = "2025-10-16T10:34:21.853Z" }, { url = "https://files.pythonhosted.org/packages/81/3d/d28172116eafc3bc9f5991b3cb3fd2c8a95f5984f50880adfdf991de9087/h5py-3.15.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a308fd8681a864c04423c0324527237a0484e2611e3441f8089fd00ed56a8171", size = 4561870, upload-time = "2025-10-16T10:34:26.69Z" }, { url = "https://files.pythonhosted.org/packages/a5/83/393a7226024238b0f51965a7156004eaae1fcf84aa4bfecf7e582676271b/h5py-3.15.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f4a016df3f4a8a14d573b496e4d1964deb380e26031fc85fb40e417e9131888a", size = 5037161, upload-time = "2025-10-16T10:34:30.383Z" }, { url = "https://files.pythonhosted.org/packages/cf/51/329e7436bf87ca6b0fe06dd0a3795c34bebe4ed8d6c44450a20565d57832/h5py-3.15.1-cp312-cp312-win_amd64.whl", hash = "sha256:59b25cf02411bf12e14f803fef0b80886444c7fe21a5ad17c6a28d3f08098a1e", size = 2874165, upload-time = "2025-10-16T10:34:33.461Z" }, { url = "https://files.pythonhosted.org/packages/09/a8/2d02b10a66747c54446e932171dd89b8b4126c0111b440e6bc05a7c852ec/h5py-3.15.1-cp312-cp312-win_arm64.whl", hash = "sha256:61d5a58a9851e01ee61c932bbbb1c98fe20aba0a5674776600fb9a361c0aa652", size = 2458214, upload-time = "2025-10-16T10:34:35.733Z" }, { url = "https://files.pythonhosted.org/packages/88/b3/40207e0192415cbff7ea1d37b9f24b33f6d38a5a2f5d18a678de78f967ae/h5py-3.15.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8440fd8bee9500c235ecb7aa1917a0389a2adb80c209fa1cc485bd70e0d94a5", size = 3376511, upload-time = "2025-10-16T10:34:38.596Z" }, { url = "https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ab2219dbc6fcdb6932f76b548e2b16f34a1f52b7666e998157a4dfc02e2c4123", size = 2826143, upload-time = "2025-10-16T10:34:41.342Z" }, { url = "https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8cb02c3a96255149ed3ac811eeea25b655d959c6dd5ce702c9a95ff11859eb5", size = 4908316, upload-time = "2025-10-16T10:34:44.619Z" }, { url = "https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:121b2b7a4c1915d63737483b7bff14ef253020f617c2fb2811f67a4bed9ac5e8", size = 5103710, upload-time = "2025-10-16T10:34:48.639Z" }, { url = "https://files.pythonhosted.org/packages/e0/f6/11f1e2432d57d71322c02a97a5567829a75f223a8c821764a0e71a65cde8/h5py-3.15.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59b0d63b318bf3cc06687def2b45afd75926bbc006f7b8cd2b1a231299fc8599", size = 4556042, upload-time = "2025-10-16T10:34:51.841Z" }, { url = "https://files.pythonhosted.org/packages/18/88/3eda3ef16bfe7a7dbc3d8d6836bbaa7986feb5ff091395e140dc13927bcc/h5py-3.15.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e02fe77a03f652500d8bff288cbf3675f742fc0411f5a628fa37116507dc7cc0", size = 5030639, upload-time = "2025-10-16T10:34:55.257Z" }, { url = "https://files.pythonhosted.org/packages/e5/ea/fbb258a98863f99befb10ed727152b4ae659f322e1d9c0576f8a62754e81/h5py-3.15.1-cp313-cp313-win_amd64.whl", hash = "sha256:dea78b092fd80a083563ed79a3171258d4a4d307492e7cf8b2313d464c82ba52", size = 2864363, upload-time = "2025-10-16T10:34:58.099Z" }, { url = "https://files.pythonhosted.org/packages/5d/c9/35021cc9cd2b2915a7da3026e3d77a05bed1144a414ff840953b33937fb9/h5py-3.15.1-cp313-cp313-win_arm64.whl", hash = "sha256:c256254a8a81e2bddc0d376e23e2a6d2dc8a1e8a2261835ed8c1281a0744cd97", size = 2449570, upload-time = "2025-10-16T10:35:00.473Z" }, { url = "https://files.pythonhosted.org/packages/a0/2c/926eba1514e4d2e47d0e9eb16c784e717d8b066398ccfca9b283917b1bfb/h5py-3.15.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:5f4fb0567eb8517c3ecd6b3c02c4f4e9da220c8932604960fd04e24ee1254763", size = 3380368, upload-time = "2025-10-16T10:35:03.117Z" }, { url = "https://files.pythonhosted.org/packages/65/4b/d715ed454d3baa5f6ae1d30b7eca4c7a1c1084f6a2edead9e801a1541d62/h5py-3.15.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:954e480433e82d3872503104f9b285d369048c3a788b2b1a00e53d1c47c98dd2", size = 2833793, upload-time = "2025-10-16T10:35:05.623Z" }, { url = "https://files.pythonhosted.org/packages/ef/d4/ef386c28e4579314610a8bffebbee3b69295b0237bc967340b7c653c6c10/h5py-3.15.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd125c131889ebbef0849f4a0e29cf363b48aba42f228d08b4079913b576bb3a", size = 4903199, upload-time = "2025-10-16T10:35:08.972Z" }, { url = "https://files.pythonhosted.org/packages/33/5d/65c619e195e0b5e54ea5a95c1bb600c8ff8715e0d09676e4cce56d89f492/h5py-3.15.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28a20e1a4082a479b3d7db2169f3a5034af010b90842e75ebbf2e9e49eb4183e", size = 5097224, upload-time = "2025-10-16T10:35:12.808Z" }, { url = "https://files.pythonhosted.org/packages/30/30/5273218400bf2da01609e1292f562c94b461fcb73c7a9e27fdadd43abc0a/h5py-3.15.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa8df5267f545b4946df8ca0d93d23382191018e4cda2deda4c2cedf9a010e13", size = 4551207, upload-time = "2025-10-16T10:35:16.24Z" }, { url = "https://files.pythonhosted.org/packages/d3/39/a7ef948ddf4d1c556b0b2b9559534777bccc318543b3f5a1efdf6b556c9c/h5py-3.15.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99d374a21f7321a4c6ab327c4ab23bd925ad69821aeb53a1e75dd809d19f67fa", size = 5025426, upload-time = "2025-10-16T10:35:19.831Z" }, { url = "https://files.pythonhosted.org/packages/b6/d8/7368679b8df6925b8415f9dcc9ab1dab01ddc384d2b2c24aac9191bd9ceb/h5py-3.15.1-cp314-cp314-win_amd64.whl", hash = "sha256:9c73d1d7cdb97d5b17ae385153472ce118bed607e43be11e9a9deefaa54e0734", size = 2865704, upload-time = "2025-10-16T10:35:22.658Z" }, { url = "https://files.pythonhosted.org/packages/d3/b7/4a806f85d62c20157e62e58e03b27513dc9c55499768530acc4f4c5ce4be/h5py-3.15.1-cp314-cp314-win_arm64.whl", hash = "sha256:a6d8c5a05a76aca9a494b4c53ce8a9c29023b7f64f625c6ce1841e92a362ccdf", size = 2465544, upload-time = "2025-10-16T10:35:25.695Z" }, ] [[package]] name = "id" version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6d/04/c2156091427636080787aac190019dc64096e56a23b7364d3c1764ee3a06/id-1.6.1.tar.gz", hash = "sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069", size = 18088, upload-time = "2026-02-04T16:19:41.26Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/42/77/de194443bf38daed9452139e960c632b0ef9f9a5dd9ce605fdf18ca9f1b1/id-1.6.1-py3-none-any.whl", hash = "sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca", size = 14689, upload-time = "2026-02-04T16:19:40.051Z" }, ] [[package]] name = "idna" version = "3.11" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] [[package]] name = "imagesize" version = "1.4.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, ] [[package]] name = "importlib-metadata" version = "8.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, ] [[package]] name = "importlib-resources" version = "6.5.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cf/8c/f834fbf984f691b4f7ff60f50b514cc3de5cc08abfc3295564dd89c5e2e7/importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c", size = 44693, upload-time = "2025-01-03T18:51:56.698Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec", size = 37461, upload-time = "2025-01-03T18:51:54.306Z" }, ] [[package]] name = "iniconfig" version = "2.1.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] [[package]] name = "iniconfig" version = "2.3.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] [[package]] name = "itsdangerous" version = "2.2.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, ] [[package]] name = "jaraco-classes" version = "3.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "more-itertools" }, ] sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, ] [[package]] name = "jaraco-context" version = "6.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cb/9c/a788f5bb29c61e456b8ee52ce76dbdd32fd72cd73dd67bc95f42c7a8d13c/jaraco_context-6.1.0.tar.gz", hash = "sha256:129a341b0a85a7db7879e22acd66902fda67882db771754574338898b2d5d86f", size = 15850, upload-time = "2026-01-13T02:53:53.847Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8d/48/aa685dbf1024c7bd82bede569e3a85f82c32fd3d79ba5fea578f0159571a/jaraco_context-6.1.0-py3-none-any.whl", hash = "sha256:a43b5ed85815223d0d3cfdb6d7ca0d2bc8946f28f30b6f3216bda070f68badda", size = 7065, upload-time = "2026-01-13T02:53:53.031Z" }, ] [[package]] name = "jaraco-functools" version = "4.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "more-itertools" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" }, ] [[package]] name = "jeepney" version = "0.9.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, ] [[package]] name = "jinja2" version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] [[package]] name = "kalign-python" version = "3.5.1" source = { editable = "." } dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] [package.optional-dependencies] all = [ { name = "biopython", version = "1.85", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "biopython", version = "1.86", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "matplotlib", version = "3.9.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "matplotlib", version = "3.10.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "pandas", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "scikit-bio", version = "0.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "scikit-bio", version = "0.7.1.post1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "seaborn" }, ] analysis = [ { name = "matplotlib", version = "3.9.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "matplotlib", version = "3.10.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "pandas", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "seaborn" }, ] benchmark = [ { name = "dash" }, { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "pandas", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "plotly" }, { name = "tqdm" }, ] biopython = [ { name = "biopython", version = "1.85", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "biopython", version = "1.86", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] dev = [ { name = "biopython", version = "1.85", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "biopython", version = "1.86", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "black", version = "25.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "black", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "build" }, { name = "flake8" }, { name = "mypy" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pytest-benchmark" }, { name = "pytest-cov" }, { name = "pytest-xdist" }, { name = "rich" }, { name = "scikit-bio", version = "0.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "scikit-bio", version = "0.7.1.post1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "twine" }, ] docs = [ { name = "myst-parser", version = "3.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "myst-parser", version = "4.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "myst-parser", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, { name = "sphinx-rtd-theme" }, ] io = [ { name = "biopython", version = "1.85", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "biopython", version = "1.86", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] skbio = [ { name = "scikit-bio", version = "0.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "scikit-bio", version = "0.7.1.post1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] test = [ { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pytest-benchmark" }, { name = "pytest-cov" }, { name = "pytest-xdist" }, { name = "rich" }, ] [package.dev-dependencies] dev = [ { name = "build" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pytest-benchmark" }, ] [package.metadata] requires-dist = [ { name = "biopython", marker = "extra == 'all'", specifier = ">=1.85" }, { name = "biopython", marker = "extra == 'biopython'", specifier = ">=1.85" }, { name = "biopython", marker = "extra == 'dev'", specifier = ">=1.85" }, { name = "biopython", marker = "extra == 'io'", specifier = ">=1.85" }, { name = "black", marker = "extra == 'dev'" }, { name = "build", marker = "extra == 'dev'" }, { name = "dash", marker = "extra == 'benchmark'", specifier = ">=2.14" }, { name = "flake8", marker = "extra == 'dev'" }, { name = "matplotlib", marker = "extra == 'all'", specifier = ">=3.9.4" }, { name = "matplotlib", marker = "extra == 'analysis'", specifier = ">=3.9.4" }, { name = "mypy", marker = "extra == 'dev'" }, { name = "myst-parser", marker = "extra == 'docs'" }, { name = "numpy", specifier = ">=1.19.0" }, { name = "pandas", marker = "extra == 'all'", specifier = ">=2.3.0" }, { name = "pandas", marker = "extra == 'analysis'", specifier = ">=2.3.0" }, { name = "pandas", marker = "extra == 'benchmark'", specifier = ">=2.0" }, { name = "plotly", marker = "extra == 'benchmark'", specifier = ">=5.18" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=6.0" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=6.0" }, { name = "pytest-benchmark", marker = "extra == 'dev'" }, { name = "pytest-benchmark", marker = "extra == 'test'" }, { name = "pytest-cov", marker = "extra == 'dev'" }, { name = "pytest-cov", marker = "extra == 'test'" }, { name = "pytest-xdist", marker = "extra == 'dev'" }, { name = "pytest-xdist", marker = "extra == 'test'" }, { name = "rich", marker = "extra == 'dev'" }, { name = "rich", marker = "extra == 'test'" }, { name = "scikit-bio", marker = "extra == 'all'", specifier = ">=0.6.3" }, { name = "scikit-bio", marker = "extra == 'dev'", specifier = ">=0.6.3" }, { name = "scikit-bio", marker = "extra == 'skbio'", specifier = ">=0.6.3" }, { name = "seaborn", marker = "extra == 'all'", specifier = ">=0.13.2" }, { name = "seaborn", marker = "extra == 'analysis'", specifier = ">=0.13.2" }, { name = "sphinx", marker = "extra == 'docs'" }, { name = "sphinx-rtd-theme", marker = "extra == 'docs'" }, { name = "tqdm", marker = "extra == 'benchmark'", specifier = ">=4.60" }, { name = "twine", marker = "extra == 'dev'" }, ] provides-extras = ["biopython", "skbio", "io", "analysis", "all", "benchmark", "dev", "test", "docs"] [package.metadata.requires-dev] dev = [ { name = "build", specifier = ">=1.2.2.post1" }, { name = "pytest", specifier = ">=8.4.1" }, { name = "pytest-benchmark", specifier = ">=5.1.0" }, ] [[package]] name = "keyring" version = "25.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, { name = "jaraco-classes" }, { name = "jaraco-context" }, { name = "jaraco-functools" }, { name = "jeepney", marker = "sys_platform == 'linux'" }, { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, { name = "secretstorage", version = "3.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' and sys_platform == 'linux'" }, { name = "secretstorage", version = "3.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' and sys_platform == 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, ] [[package]] name = "kiwisolver" version = "1.4.7" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/85/4d/2255e1c76304cbd60b48cee302b66d1dde4468dc5b1160e4b7cb43778f2a/kiwisolver-1.4.7.tar.gz", hash = "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60", size = 97286, upload-time = "2024-09-04T09:39:44.302Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/97/14/fc943dd65268a96347472b4fbe5dcc2f6f55034516f80576cd0dd3a8930f/kiwisolver-1.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6", size = 122440, upload-time = "2024-09-04T09:03:44.9Z" }, { url = "https://files.pythonhosted.org/packages/1e/46/e68fed66236b69dd02fcdb506218c05ac0e39745d696d22709498896875d/kiwisolver-1.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17", size = 65758, upload-time = "2024-09-04T09:03:46.582Z" }, { url = "https://files.pythonhosted.org/packages/ef/fa/65de49c85838681fc9cb05de2a68067a683717321e01ddafb5b8024286f0/kiwisolver-1.4.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aa0abdf853e09aff551db11fce173e2177d00786c688203f52c87ad7fcd91ef9", size = 64311, upload-time = "2024-09-04T09:03:47.973Z" }, { url = "https://files.pythonhosted.org/packages/42/9c/cc8d90f6ef550f65443bad5872ffa68f3dee36de4974768628bea7c14979/kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8d53103597a252fb3ab8b5845af04c7a26d5e7ea8122303dd7a021176a87e8b9", size = 1637109, upload-time = "2024-09-04T09:03:49.281Z" }, { url = "https://files.pythonhosted.org/packages/55/91/0a57ce324caf2ff5403edab71c508dd8f648094b18cfbb4c8cc0fde4a6ac/kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:88f17c5ffa8e9462fb79f62746428dd57b46eb931698e42e990ad63103f35e6c", size = 1617814, upload-time = "2024-09-04T09:03:51.444Z" }, { url = "https://files.pythonhosted.org/packages/12/5d/c36140313f2510e20207708adf36ae4919416d697ee0236b0ddfb6fd1050/kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a9ca9c710d598fd75ee5de59d5bda2684d9db36a9f50b6125eaea3969c2599", size = 1400881, upload-time = "2024-09-04T09:03:53.357Z" }, { url = "https://files.pythonhosted.org/packages/56/d0/786e524f9ed648324a466ca8df86298780ef2b29c25313d9a4f16992d3cf/kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4d742cb7af1c28303a51b7a27aaee540e71bb8e24f68c736f6f2ffc82f2bf05", size = 1512972, upload-time = "2024-09-04T09:03:55.082Z" }, { url = "https://files.pythonhosted.org/packages/67/5a/77851f2f201e6141d63c10a0708e996a1363efaf9e1609ad0441b343763b/kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28c7fea2196bf4c2f8d46a0415c77a1c480cc0724722f23d7410ffe9842c407", size = 1444787, upload-time = "2024-09-04T09:03:56.588Z" }, { url = "https://files.pythonhosted.org/packages/06/5f/1f5eaab84355885e224a6fc8d73089e8713dc7e91c121f00b9a1c58a2195/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e968b84db54f9d42046cf154e02911e39c0435c9801681e3fc9ce8a3c4130278", size = 2199212, upload-time = "2024-09-04T09:03:58.557Z" }, { url = "https://files.pythonhosted.org/packages/b5/28/9152a3bfe976a0ae21d445415defc9d1cd8614b2910b7614b30b27a47270/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0c18ec74c0472de033e1bebb2911c3c310eef5649133dd0bedf2a169a1b269e5", size = 2346399, upload-time = "2024-09-04T09:04:00.178Z" }, { url = "https://files.pythonhosted.org/packages/26/f6/453d1904c52ac3b400f4d5e240ac5fec25263716723e44be65f4d7149d13/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8f0ea6da6d393d8b2e187e6a5e3fb81f5862010a40c3945e2c6d12ae45cfb2ad", size = 2308688, upload-time = "2024-09-04T09:04:02.216Z" }, { url = "https://files.pythonhosted.org/packages/5a/9a/d4968499441b9ae187e81745e3277a8b4d7c60840a52dc9d535a7909fac3/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:f106407dda69ae456dd1227966bf445b157ccc80ba0dff3802bb63f30b74e895", size = 2445493, upload-time = "2024-09-04T09:04:04.571Z" }, { url = "https://files.pythonhosted.org/packages/07/c9/032267192e7828520dacb64dfdb1d74f292765f179e467c1cba97687f17d/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84ec80df401cfee1457063732d90022f93951944b5b58975d34ab56bb150dfb3", size = 2262191, upload-time = "2024-09-04T09:04:05.969Z" }, { url = "https://files.pythonhosted.org/packages/6c/ad/db0aedb638a58b2951da46ddaeecf204be8b4f5454df020d850c7fa8dca8/kiwisolver-1.4.7-cp310-cp310-win32.whl", hash = "sha256:71bb308552200fb2c195e35ef05de12f0c878c07fc91c270eb3d6e41698c3bcc", size = 46644, upload-time = "2024-09-04T09:04:07.408Z" }, { url = "https://files.pythonhosted.org/packages/12/ca/d0f7b7ffbb0be1e7c2258b53554efec1fd652921f10d7d85045aff93ab61/kiwisolver-1.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:44756f9fd339de0fb6ee4f8c1696cfd19b2422e0d70b4cefc1cc7f1f64045a8c", size = 55877, upload-time = "2024-09-04T09:04:08.869Z" }, { url = "https://files.pythonhosted.org/packages/97/6c/cfcc128672f47a3e3c0d918ecb67830600078b025bfc32d858f2e2d5c6a4/kiwisolver-1.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:78a42513018c41c2ffd262eb676442315cbfe3c44eed82385c2ed043bc63210a", size = 48347, upload-time = "2024-09-04T09:04:10.106Z" }, { url = "https://files.pythonhosted.org/packages/e9/44/77429fa0a58f941d6e1c58da9efe08597d2e86bf2b2cce6626834f49d07b/kiwisolver-1.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d2b0e12a42fb4e72d509fc994713d099cbb15ebf1103545e8a45f14da2dfca54", size = 122442, upload-time = "2024-09-04T09:04:11.432Z" }, { url = "https://files.pythonhosted.org/packages/e5/20/8c75caed8f2462d63c7fd65e16c832b8f76cda331ac9e615e914ee80bac9/kiwisolver-1.4.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95", size = 65762, upload-time = "2024-09-04T09:04:12.468Z" }, { url = "https://files.pythonhosted.org/packages/f4/98/fe010f15dc7230f45bc4cf367b012d651367fd203caaa992fd1f5963560e/kiwisolver-1.4.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46707a10836894b559e04b0fd143e343945c97fd170d69a2d26d640b4e297935", size = 64319, upload-time = "2024-09-04T09:04:13.635Z" }, { url = "https://files.pythonhosted.org/packages/8b/1b/b5d618f4e58c0675654c1e5051bcf42c776703edb21c02b8c74135541f60/kiwisolver-1.4.7-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef97b8df011141c9b0f6caf23b29379f87dd13183c978a30a3c546d2c47314cb", size = 1334260, upload-time = "2024-09-04T09:04:14.878Z" }, { url = "https://files.pythonhosted.org/packages/b8/01/946852b13057a162a8c32c4c8d2e9ed79f0bb5d86569a40c0b5fb103e373/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02", size = 1426589, upload-time = "2024-09-04T09:04:16.514Z" }, { url = "https://files.pythonhosted.org/packages/70/d1/c9f96df26b459e15cf8a965304e6e6f4eb291e0f7a9460b4ad97b047561e/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:803b8e1459341c1bb56d1c5c010406d5edec8a0713a0945851290a7930679b51", size = 1541080, upload-time = "2024-09-04T09:04:18.322Z" }, { url = "https://files.pythonhosted.org/packages/d3/73/2686990eb8b02d05f3de759d6a23a4ee7d491e659007dd4c075fede4b5d0/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9a9e8a507420fe35992ee9ecb302dab68550dedc0da9e2880dd88071c5fb052", size = 1470049, upload-time = "2024-09-04T09:04:20.266Z" }, { url = "https://files.pythonhosted.org/packages/a7/4b/2db7af3ed3af7c35f388d5f53c28e155cd402a55432d800c543dc6deb731/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18", size = 1426376, upload-time = "2024-09-04T09:04:22.419Z" }, { url = "https://files.pythonhosted.org/packages/05/83/2857317d04ea46dc5d115f0df7e676997bbd968ced8e2bd6f7f19cfc8d7f/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6af936f79086a89b3680a280c47ea90b4df7047b5bdf3aa5c524bbedddb9e545", size = 2222231, upload-time = "2024-09-04T09:04:24.526Z" }, { url = "https://files.pythonhosted.org/packages/0d/b5/866f86f5897cd4ab6d25d22e403404766a123f138bd6a02ecb2cdde52c18/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3abc5b19d24af4b77d1598a585b8a719beb8569a71568b66f4ebe1fb0449460b", size = 2368634, upload-time = "2024-09-04T09:04:25.899Z" }, { url = "https://files.pythonhosted.org/packages/c1/ee/73de8385403faba55f782a41260210528fe3273d0cddcf6d51648202d6d0/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:933d4de052939d90afbe6e9d5273ae05fb836cc86c15b686edd4b3560cc0ee36", size = 2329024, upload-time = "2024-09-04T09:04:28.523Z" }, { url = "https://files.pythonhosted.org/packages/a1/e7/cd101d8cd2cdfaa42dc06c433df17c8303d31129c9fdd16c0ea37672af91/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:65e720d2ab2b53f1f72fb5da5fb477455905ce2c88aaa671ff0a447c2c80e8e3", size = 2468484, upload-time = "2024-09-04T09:04:30.547Z" }, { url = "https://files.pythonhosted.org/packages/e1/72/84f09d45a10bc57a40bb58b81b99d8f22b58b2040c912b7eb97ebf625bf2/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3bf1ed55088f214ba6427484c59553123fdd9b218a42bbc8c6496d6754b1e523", size = 2284078, upload-time = "2024-09-04T09:04:33.218Z" }, { url = "https://files.pythonhosted.org/packages/d2/d4/71828f32b956612dc36efd7be1788980cb1e66bfb3706e6dec9acad9b4f9/kiwisolver-1.4.7-cp311-cp311-win32.whl", hash = "sha256:4c00336b9dd5ad96d0a558fd18a8b6f711b7449acce4c157e7343ba92dd0cf3d", size = 46645, upload-time = "2024-09-04T09:04:34.371Z" }, { url = "https://files.pythonhosted.org/packages/a1/65/d43e9a20aabcf2e798ad1aff6c143ae3a42cf506754bcb6a7ed8259c8425/kiwisolver-1.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b", size = 56022, upload-time = "2024-09-04T09:04:35.786Z" }, { url = "https://files.pythonhosted.org/packages/35/b3/9f75a2e06f1b4ca00b2b192bc2b739334127d27f1d0625627ff8479302ba/kiwisolver-1.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:e33e8fbd440c917106b237ef1a2f1449dfbb9b6f6e1ce17c94cd6a1e0d438376", size = 48536, upload-time = "2024-09-04T09:04:37.525Z" }, { url = "https://files.pythonhosted.org/packages/97/9c/0a11c714cf8b6ef91001c8212c4ef207f772dd84540104952c45c1f0a249/kiwisolver-1.4.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5360cc32706dab3931f738d3079652d20982511f7c0ac5711483e6eab08efff2", size = 121808, upload-time = "2024-09-04T09:04:38.637Z" }, { url = "https://files.pythonhosted.org/packages/f2/d8/0fe8c5f5d35878ddd135f44f2af0e4e1d379e1c7b0716f97cdcb88d4fd27/kiwisolver-1.4.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942216596dc64ddb25adb215c3c783215b23626f8d84e8eff8d6d45c3f29f75a", size = 65531, upload-time = "2024-09-04T09:04:39.694Z" }, { url = "https://files.pythonhosted.org/packages/80/c5/57fa58276dfdfa612241d640a64ca2f76adc6ffcebdbd135b4ef60095098/kiwisolver-1.4.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:48b571ecd8bae15702e4f22d3ff6a0f13e54d3d00cd25216d5e7f658242065ee", size = 63894, upload-time = "2024-09-04T09:04:41.6Z" }, { url = "https://files.pythonhosted.org/packages/8b/e9/26d3edd4c4ad1c5b891d8747a4f81b1b0aba9fb9721de6600a4adc09773b/kiwisolver-1.4.7-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad42ba922c67c5f219097b28fae965e10045ddf145d2928bfac2eb2e17673640", size = 1369296, upload-time = "2024-09-04T09:04:42.886Z" }, { url = "https://files.pythonhosted.org/packages/b6/67/3f4850b5e6cffb75ec40577ddf54f7b82b15269cc5097ff2e968ee32ea7d/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:612a10bdae23404a72941a0fc8fa2660c6ea1217c4ce0dbcab8a8f6543ea9e7f", size = 1461450, upload-time = "2024-09-04T09:04:46.284Z" }, { url = "https://files.pythonhosted.org/packages/52/be/86cbb9c9a315e98a8dc6b1d23c43cffd91d97d49318854f9c37b0e41cd68/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e838bba3a3bac0fe06d849d29772eb1afb9745a59710762e4ba3f4cb8424483", size = 1579168, upload-time = "2024-09-04T09:04:47.91Z" }, { url = "https://files.pythonhosted.org/packages/0f/00/65061acf64bd5fd34c1f4ae53f20b43b0a017a541f242a60b135b9d1e301/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22f499f6157236c19f4bbbd472fa55b063db77a16cd74d49afe28992dff8c258", size = 1507308, upload-time = "2024-09-04T09:04:49.465Z" }, { url = "https://files.pythonhosted.org/packages/21/e4/c0b6746fd2eb62fe702118b3ca0cb384ce95e1261cfada58ff693aeec08a/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693902d433cf585133699972b6d7c42a8b9f8f826ebcaf0132ff55200afc599e", size = 1464186, upload-time = "2024-09-04T09:04:50.949Z" }, { url = "https://files.pythonhosted.org/packages/0a/0f/529d0a9fffb4d514f2782c829b0b4b371f7f441d61aa55f1de1c614c4ef3/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4e77f2126c3e0b0d055f44513ed349038ac180371ed9b52fe96a32aa071a5107", size = 2247877, upload-time = "2024-09-04T09:04:52.388Z" }, { url = "https://files.pythonhosted.org/packages/d1/e1/66603ad779258843036d45adcbe1af0d1a889a07af4635f8b4ec7dccda35/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:657a05857bda581c3656bfc3b20e353c232e9193eb167766ad2dc58b56504948", size = 2404204, upload-time = "2024-09-04T09:04:54.385Z" }, { url = "https://files.pythonhosted.org/packages/8d/61/de5fb1ca7ad1f9ab7970e340a5b833d735df24689047de6ae71ab9d8d0e7/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4bfa75a048c056a411f9705856abfc872558e33c055d80af6a380e3658766038", size = 2352461, upload-time = "2024-09-04T09:04:56.307Z" }, { url = "https://files.pythonhosted.org/packages/ba/d2/0edc00a852e369827f7e05fd008275f550353f1f9bcd55db9363d779fc63/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:34ea1de54beef1c104422d210c47c7d2a4999bdecf42c7b5718fbe59a4cac383", size = 2501358, upload-time = "2024-09-04T09:04:57.922Z" }, { url = "https://files.pythonhosted.org/packages/84/15/adc15a483506aec6986c01fb7f237c3aec4d9ed4ac10b756e98a76835933/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:90da3b5f694b85231cf93586dad5e90e2d71b9428f9aad96952c99055582f520", size = 2314119, upload-time = "2024-09-04T09:04:59.332Z" }, { url = "https://files.pythonhosted.org/packages/36/08/3a5bb2c53c89660863a5aa1ee236912269f2af8762af04a2e11df851d7b2/kiwisolver-1.4.7-cp312-cp312-win32.whl", hash = "sha256:18e0cca3e008e17fe9b164b55735a325140a5a35faad8de92dd80265cd5eb80b", size = 46367, upload-time = "2024-09-04T09:05:00.804Z" }, { url = "https://files.pythonhosted.org/packages/19/93/c05f0a6d825c643779fc3c70876bff1ac221f0e31e6f701f0e9578690d70/kiwisolver-1.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:58cb20602b18f86f83a5c87d3ee1c766a79c0d452f8def86d925e6c60fbf7bfb", size = 55884, upload-time = "2024-09-04T09:05:01.924Z" }, { url = "https://files.pythonhosted.org/packages/d2/f9/3828d8f21b6de4279f0667fb50a9f5215e6fe57d5ec0d61905914f5b6099/kiwisolver-1.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:f5a8b53bdc0b3961f8b6125e198617c40aeed638b387913bf1ce78afb1b0be2a", size = 48528, upload-time = "2024-09-04T09:05:02.983Z" }, { url = "https://files.pythonhosted.org/packages/c4/06/7da99b04259b0f18b557a4effd1b9c901a747f7fdd84cf834ccf520cb0b2/kiwisolver-1.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2e6039dcbe79a8e0f044f1c39db1986a1b8071051efba3ee4d74f5b365f5226e", size = 121913, upload-time = "2024-09-04T09:05:04.072Z" }, { url = "https://files.pythonhosted.org/packages/97/f5/b8a370d1aa593c17882af0a6f6755aaecd643640c0ed72dcfd2eafc388b9/kiwisolver-1.4.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a1ecf0ac1c518487d9d23b1cd7139a6a65bc460cd101ab01f1be82ecf09794b6", size = 65627, upload-time = "2024-09-04T09:05:05.119Z" }, { url = "https://files.pythonhosted.org/packages/2a/fc/6c0374f7503522539e2d4d1b497f5ebad3f8ed07ab51aed2af988dd0fb65/kiwisolver-1.4.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ab9ccab2b5bd5702ab0803676a580fffa2aa178c2badc5557a84cc943fcf750", size = 63888, upload-time = "2024-09-04T09:05:06.191Z" }, { url = "https://files.pythonhosted.org/packages/bf/3e/0b7172793d0f41cae5c923492da89a2ffcd1adf764c16159ca047463ebd3/kiwisolver-1.4.7-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f816dd2277f8d63d79f9c8473a79fe54047bc0467754962840782c575522224d", size = 1369145, upload-time = "2024-09-04T09:05:07.919Z" }, { url = "https://files.pythonhosted.org/packages/77/92/47d050d6f6aced2d634258123f2688fbfef8ded3c5baf2c79d94d91f1f58/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf8bcc23ceb5a1b624572a1623b9f79d2c3b337c8c455405ef231933a10da379", size = 1461448, upload-time = "2024-09-04T09:05:10.01Z" }, { url = "https://files.pythonhosted.org/packages/9c/1b/8f80b18e20b3b294546a1adb41701e79ae21915f4175f311a90d042301cf/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dea0bf229319828467d7fca8c7c189780aa9ff679c94539eed7532ebe33ed37c", size = 1578750, upload-time = "2024-09-04T09:05:11.598Z" }, { url = "https://files.pythonhosted.org/packages/a4/fe/fe8e72f3be0a844f257cadd72689c0848c6d5c51bc1d60429e2d14ad776e/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c06a4c7cf15ec739ce0e5971b26c93638730090add60e183530d70848ebdd34", size = 1507175, upload-time = "2024-09-04T09:05:13.22Z" }, { url = "https://files.pythonhosted.org/packages/39/fa/cdc0b6105d90eadc3bee525fecc9179e2b41e1ce0293caaf49cb631a6aaf/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913983ad2deb14e66d83c28b632fd35ba2b825031f2fa4ca29675e665dfecbe1", size = 1463963, upload-time = "2024-09-04T09:05:15.925Z" }, { url = "https://files.pythonhosted.org/packages/6e/5c/0c03c4e542720c6177d4f408e56d1c8315899db72d46261a4e15b8b33a41/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5337ec7809bcd0f424c6b705ecf97941c46279cf5ed92311782c7c9c2026f07f", size = 2248220, upload-time = "2024-09-04T09:05:17.434Z" }, { url = "https://files.pythonhosted.org/packages/3d/ee/55ef86d5a574f4e767df7da3a3a7ff4954c996e12d4fbe9c408170cd7dcc/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c26ed10c4f6fa6ddb329a5120ba3b6db349ca192ae211e882970bfc9d91420b", size = 2404463, upload-time = "2024-09-04T09:05:18.997Z" }, { url = "https://files.pythonhosted.org/packages/0f/6d/73ad36170b4bff4825dc588acf4f3e6319cb97cd1fb3eb04d9faa6b6f212/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c619b101e6de2222c1fcb0531e1b17bbffbe54294bfba43ea0d411d428618c27", size = 2352842, upload-time = "2024-09-04T09:05:21.299Z" }, { url = "https://files.pythonhosted.org/packages/0b/16/fa531ff9199d3b6473bb4d0f47416cdb08d556c03b8bc1cccf04e756b56d/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:073a36c8273647592ea332e816e75ef8da5c303236ec0167196793eb1e34657a", size = 2501635, upload-time = "2024-09-04T09:05:23.588Z" }, { url = "https://files.pythonhosted.org/packages/78/7e/aa9422e78419db0cbe75fb86d8e72b433818f2e62e2e394992d23d23a583/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3ce6b2b0231bda412463e152fc18335ba32faf4e8c23a754ad50ffa70e4091ee", size = 2314556, upload-time = "2024-09-04T09:05:25.907Z" }, { url = "https://files.pythonhosted.org/packages/a8/b2/15f7f556df0a6e5b3772a1e076a9d9f6c538ce5f05bd590eca8106508e06/kiwisolver-1.4.7-cp313-cp313-win32.whl", hash = "sha256:f4c9aee212bc89d4e13f58be11a56cc8036cabad119259d12ace14b34476fd07", size = 46364, upload-time = "2024-09-04T09:05:27.184Z" }, { url = "https://files.pythonhosted.org/packages/0b/db/32e897e43a330eee8e4770bfd2737a9584b23e33587a0812b8e20aac38f7/kiwisolver-1.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:8a3ec5aa8e38fc4c8af308917ce12c536f1c88452ce554027e55b22cbbfbff76", size = 55887, upload-time = "2024-09-04T09:05:28.372Z" }, { url = "https://files.pythonhosted.org/packages/c8/a4/df2bdca5270ca85fd25253049eb6708d4127be2ed0e5c2650217450b59e9/kiwisolver-1.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:76c8094ac20ec259471ac53e774623eb62e6e1f56cd8690c67ce6ce4fcb05650", size = 48530, upload-time = "2024-09-04T09:05:30.225Z" }, { url = "https://files.pythonhosted.org/packages/11/88/37ea0ea64512997b13d69772db8dcdc3bfca5442cda3a5e4bb943652ee3e/kiwisolver-1.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f9362ecfca44c863569d3d3c033dbe8ba452ff8eed6f6b5806382741a1334bd", size = 122449, upload-time = "2024-09-04T09:05:55.311Z" }, { url = "https://files.pythonhosted.org/packages/4e/45/5a5c46078362cb3882dcacad687c503089263c017ca1241e0483857791eb/kiwisolver-1.4.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e8df2eb9b2bac43ef8b082e06f750350fbbaf2887534a5be97f6cf07b19d9583", size = 65757, upload-time = "2024-09-04T09:05:56.906Z" }, { url = "https://files.pythonhosted.org/packages/8a/be/a6ae58978772f685d48dd2e84460937761c53c4bbd84e42b0336473d9775/kiwisolver-1.4.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f32d6edbc638cde7652bd690c3e728b25332acbadd7cad670cc4a02558d9c417", size = 64312, upload-time = "2024-09-04T09:05:58.384Z" }, { url = "https://files.pythonhosted.org/packages/f4/04/18ef6f452d311e1e1eb180c9bf5589187fa1f042db877e6fe443ef10099c/kiwisolver-1.4.7-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e2e6c39bd7b9372b0be21456caab138e8e69cc0fc1190a9dfa92bd45a1e6e904", size = 1626966, upload-time = "2024-09-04T09:05:59.855Z" }, { url = "https://files.pythonhosted.org/packages/21/b1/40655f6c3fa11ce740e8a964fa8e4c0479c87d6a7944b95af799c7a55dfe/kiwisolver-1.4.7-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dda56c24d869b1193fcc763f1284b9126550eaf84b88bbc7256e15028f19188a", size = 1607044, upload-time = "2024-09-04T09:06:02.16Z" }, { url = "https://files.pythonhosted.org/packages/fd/93/af67dbcfb9b3323bbd2c2db1385a7139d8f77630e4a37bb945b57188eb2d/kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79849239c39b5e1fd906556c474d9b0439ea6792b637511f3fe3a41158d89ca8", size = 1391879, upload-time = "2024-09-04T09:06:03.908Z" }, { url = "https://files.pythonhosted.org/packages/40/6f/d60770ef98e77b365d96061d090c0cd9e23418121c55fff188fa4bdf0b54/kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e3bc157fed2a4c02ec468de4ecd12a6e22818d4f09cde2c31ee3226ffbefab2", size = 1504751, upload-time = "2024-09-04T09:06:05.58Z" }, { url = "https://files.pythonhosted.org/packages/fa/3a/5f38667d313e983c432f3fcd86932177519ed8790c724e07d77d1de0188a/kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3da53da805b71e41053dc670f9a820d1157aae77b6b944e08024d17bcd51ef88", size = 1436990, upload-time = "2024-09-04T09:06:08.126Z" }, { url = "https://files.pythonhosted.org/packages/cb/3b/1520301a47326e6a6043b502647e42892be33b3f051e9791cc8bb43f1a32/kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8705f17dfeb43139a692298cb6637ee2e59c0194538153e83e9ee0c75c2eddde", size = 2191122, upload-time = "2024-09-04T09:06:10.345Z" }, { url = "https://files.pythonhosted.org/packages/cf/c4/eb52da300c166239a2233f1f9c4a1b767dfab98fae27681bfb7ea4873cb6/kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:82a5c2f4b87c26bb1a0ef3d16b5c4753434633b83d365cc0ddf2770c93829e3c", size = 2338126, upload-time = "2024-09-04T09:06:12.321Z" }, { url = "https://files.pythonhosted.org/packages/1a/cb/42b92fd5eadd708dd9107c089e817945500685f3437ce1fd387efebc6d6e/kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce8be0466f4c0d585cdb6c1e2ed07232221df101a4c6f28821d2aa754ca2d9e2", size = 2298313, upload-time = "2024-09-04T09:06:14.562Z" }, { url = "https://files.pythonhosted.org/packages/4f/eb/be25aa791fe5fc75a8b1e0c965e00f942496bc04635c9aae8035f6b76dcd/kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:409afdfe1e2e90e6ee7fc896f3df9a7fec8e793e58bfa0d052c8a82f99c37abb", size = 2437784, upload-time = "2024-09-04T09:06:16.767Z" }, { url = "https://files.pythonhosted.org/packages/c5/22/30a66be7f3368d76ff95689e1c2e28d382383952964ab15330a15d8bfd03/kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b9c3f4ee0b9a439d2415012bd1b1cc2df59e4d6a9939f4d669241d30b414327", size = 2253988, upload-time = "2024-09-04T09:06:18.705Z" }, { url = "https://files.pythonhosted.org/packages/35/d3/5f2ecb94b5211c8a04f218a76133cc8d6d153b0f9cd0b45fad79907f0689/kiwisolver-1.4.7-cp39-cp39-win32.whl", hash = "sha256:a79ae34384df2b615eefca647a2873842ac3b596418032bef9a7283675962644", size = 46980, upload-time = "2024-09-04T09:06:20.106Z" }, { url = "https://files.pythonhosted.org/packages/ef/17/cd10d020578764ea91740204edc6b3236ed8106228a46f568d716b11feb2/kiwisolver-1.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:cf0438b42121a66a3a667de17e779330fc0f20b0d97d59d2f2121e182b0505e4", size = 55847, upload-time = "2024-09-04T09:06:21.407Z" }, { url = "https://files.pythonhosted.org/packages/91/84/32232502020bd78d1d12be7afde15811c64a95ed1f606c10456db4e4c3ac/kiwisolver-1.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:764202cc7e70f767dab49e8df52c7455e8de0df5d858fa801a11aa0d882ccf3f", size = 48494, upload-time = "2024-09-04T09:06:22.648Z" }, { url = "https://files.pythonhosted.org/packages/ac/59/741b79775d67ab67ced9bb38552da688c0305c16e7ee24bba7a2be253fb7/kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:94252291e3fe68001b1dd747b4c0b3be12582839b95ad4d1b641924d68fd4643", size = 59491, upload-time = "2024-09-04T09:06:24.188Z" }, { url = "https://files.pythonhosted.org/packages/58/cc/fb239294c29a5656e99e3527f7369b174dd9cc7c3ef2dea7cb3c54a8737b/kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b7dfa3b546da08a9f622bb6becdb14b3e24aaa30adba66749d38f3cc7ea9706", size = 57648, upload-time = "2024-09-04T09:06:25.559Z" }, { url = "https://files.pythonhosted.org/packages/3b/ef/2f009ac1f7aab9f81efb2d837301d255279d618d27b6015780115ac64bdd/kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd3de6481f4ed8b734da5df134cd5a6a64fe32124fe83dde1e5b5f29fe30b1e6", size = 84257, upload-time = "2024-09-04T09:06:27.038Z" }, { url = "https://files.pythonhosted.org/packages/81/e1/c64f50987f85b68b1c52b464bb5bf73e71570c0f7782d626d1eb283ad620/kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a91b5f9f1205845d488c928e8570dcb62b893372f63b8b6e98b863ebd2368ff2", size = 80906, upload-time = "2024-09-04T09:06:28.48Z" }, { url = "https://files.pythonhosted.org/packages/fd/71/1687c5c0a0be2cee39a5c9c389e546f9c6e215e46b691d00d9f646892083/kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40fa14dbd66b8b8f470d5fc79c089a66185619d31645f9b0773b88b19f7223c4", size = 79951, upload-time = "2024-09-04T09:06:29.966Z" }, { url = "https://files.pythonhosted.org/packages/ea/8b/d7497df4a1cae9367adf21665dd1f896c2a7aeb8769ad77b662c5e2bcce7/kiwisolver-1.4.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:eb542fe7933aa09d8d8f9d9097ef37532a7df6497819d16efe4359890a2f417a", size = 55715, upload-time = "2024-09-04T09:06:31.489Z" }, { url = "https://files.pythonhosted.org/packages/d5/df/ce37d9b26f07ab90880923c94d12a6ff4d27447096b4c849bfc4339ccfdf/kiwisolver-1.4.7-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8b01aac285f91ca889c800042c35ad3b239e704b150cfd3382adfc9dcc780e39", size = 58666, upload-time = "2024-09-04T09:06:43.756Z" }, { url = "https://files.pythonhosted.org/packages/b0/d3/e4b04f43bc629ac8e186b77b2b1a251cdfa5b7610fa189dc0db622672ce6/kiwisolver-1.4.7-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48be928f59a1f5c8207154f935334d374e79f2b5d212826307d072595ad76a2e", size = 57088, upload-time = "2024-09-04T09:06:45.406Z" }, { url = "https://files.pythonhosted.org/packages/30/1c/752df58e2d339e670a535514d2db4fe8c842ce459776b8080fbe08ebb98e/kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f37cfe618a117e50d8c240555331160d73d0411422b59b5ee217843d7b693608", size = 84321, upload-time = "2024-09-04T09:06:47.557Z" }, { url = "https://files.pythonhosted.org/packages/f0/f8/fe6484e847bc6e238ec9f9828089fb2c0bb53f2f5f3a79351fde5b565e4f/kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:599b5c873c63a1f6ed7eead644a8a380cfbdf5db91dcb6f85707aaab213b1674", size = 80776, upload-time = "2024-09-04T09:06:49.235Z" }, { url = "https://files.pythonhosted.org/packages/9b/57/d7163c0379f250ef763aba85330a19feefb5ce6cb541ade853aaba881524/kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:801fa7802e5cfabe3ab0c81a34c323a319b097dfb5004be950482d882f3d7225", size = 79984, upload-time = "2024-09-04T09:06:51.336Z" }, { url = "https://files.pythonhosted.org/packages/8c/95/4a103776c265d13b3d2cd24fb0494d4e04ea435a8ef97e1b2c026d43250b/kiwisolver-1.4.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0c6c43471bc764fad4bc99c5c2d6d16a676b1abf844ca7c8702bdae92df01ee0", size = 55811, upload-time = "2024-09-04T09:06:53.078Z" }, ] [[package]] name = "kiwisolver" version = "1.4.9" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c6/5d/8ce64e36d4e3aac5ca96996457dcf33e34e6051492399a3f1fec5657f30b/kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b", size = 124159, upload-time = "2025-08-10T21:25:35.472Z" }, { url = "https://files.pythonhosted.org/packages/96/1e/22f63ec454874378175a5f435d6ea1363dd33fb2af832c6643e4ccea0dc8/kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f", size = 66578, upload-time = "2025-08-10T21:25:36.73Z" }, { url = "https://files.pythonhosted.org/packages/41/4c/1925dcfff47a02d465121967b95151c82d11027d5ec5242771e580e731bd/kiwisolver-1.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84fd60810829c27ae375114cd379da1fa65e6918e1da405f356a775d49a62bcf", size = 65312, upload-time = "2025-08-10T21:25:37.658Z" }, { url = "https://files.pythonhosted.org/packages/d4/42/0f333164e6307a0687d1eb9ad256215aae2f4bd5d28f4653d6cd319a3ba3/kiwisolver-1.4.9-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78efa4c6e804ecdf727e580dbb9cba85624d2e1c6b5cb059c66290063bd99a9", size = 1628458, upload-time = "2025-08-10T21:25:39.067Z" }, { url = "https://files.pythonhosted.org/packages/86/b6/2dccb977d651943995a90bfe3495c2ab2ba5cd77093d9f2318a20c9a6f59/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4efec7bcf21671db6a3294ff301d2fc861c31faa3c8740d1a94689234d1b415", size = 1225640, upload-time = "2025-08-10T21:25:40.489Z" }, { url = "https://files.pythonhosted.org/packages/50/2b/362ebd3eec46c850ccf2bfe3e30f2fc4c008750011f38a850f088c56a1c6/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90f47e70293fc3688b71271100a1a5453aa9944a81d27ff779c108372cf5567b", size = 1244074, upload-time = "2025-08-10T21:25:42.221Z" }, { url = "https://files.pythonhosted.org/packages/6f/bb/f09a1e66dab8984773d13184a10a29fe67125337649d26bdef547024ed6b/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fdca1def57a2e88ef339de1737a1449d6dbf5fab184c54a1fca01d541317154", size = 1293036, upload-time = "2025-08-10T21:25:43.801Z" }, { url = "https://files.pythonhosted.org/packages/ea/01/11ecf892f201cafda0f68fa59212edaea93e96c37884b747c181303fccd1/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9cf554f21be770f5111a1690d42313e140355e687e05cf82cb23d0a721a64a48", size = 2175310, upload-time = "2025-08-10T21:25:45.045Z" }, { url = "https://files.pythonhosted.org/packages/7f/5f/bfe11d5b934f500cc004314819ea92427e6e5462706a498c1d4fc052e08f/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fc1795ac5cd0510207482c3d1d3ed781143383b8cfd36f5c645f3897ce066220", size = 2270943, upload-time = "2025-08-10T21:25:46.393Z" }, { url = "https://files.pythonhosted.org/packages/3d/de/259f786bf71f1e03e73d87e2db1a9a3bcab64d7b4fd780167123161630ad/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ccd09f20ccdbbd341b21a67ab50a119b64a403b09288c27481575105283c1586", size = 2440488, upload-time = "2025-08-10T21:25:48.074Z" }, { url = "https://files.pythonhosted.org/packages/1b/76/c989c278faf037c4d3421ec07a5c452cd3e09545d6dae7f87c15f54e4edf/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:540c7c72324d864406a009d72f5d6856f49693db95d1fbb46cf86febef873634", size = 2246787, upload-time = "2025-08-10T21:25:49.442Z" }, { url = "https://files.pythonhosted.org/packages/a2/55/c2898d84ca440852e560ca9f2a0d28e6e931ac0849b896d77231929900e7/kiwisolver-1.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:ede8c6d533bc6601a47ad4046080d36b8fc99f81e6f1c17b0ac3c2dc91ac7611", size = 73730, upload-time = "2025-08-10T21:25:51.102Z" }, { url = "https://files.pythonhosted.org/packages/e8/09/486d6ac523dd33b80b368247f238125d027964cfacb45c654841e88fb2ae/kiwisolver-1.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:7b4da0d01ac866a57dd61ac258c5607b4cd677f63abaec7b148354d2b2cdd536", size = 65036, upload-time = "2025-08-10T21:25:52.063Z" }, { url = "https://files.pythonhosted.org/packages/6f/ab/c80b0d5a9d8a1a65f4f815f2afff9798b12c3b9f31f1d304dd233dd920e2/kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16", size = 124167, upload-time = "2025-08-10T21:25:53.403Z" }, { url = "https://files.pythonhosted.org/packages/a0/c0/27fe1a68a39cf62472a300e2879ffc13c0538546c359b86f149cc19f6ac3/kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089", size = 66579, upload-time = "2025-08-10T21:25:54.79Z" }, { url = "https://files.pythonhosted.org/packages/31/a2/a12a503ac1fd4943c50f9822678e8015a790a13b5490354c68afb8489814/kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543", size = 65309, upload-time = "2025-08-10T21:25:55.76Z" }, { url = "https://files.pythonhosted.org/packages/66/e1/e533435c0be77c3f64040d68d7a657771194a63c279f55573188161e81ca/kiwisolver-1.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc1ae486f9abcef254b5618dfb4113dd49f94c68e3e027d03cf0143f3f772b61", size = 1435596, upload-time = "2025-08-10T21:25:56.861Z" }, { url = "https://files.pythonhosted.org/packages/67/1e/51b73c7347f9aabdc7215aa79e8b15299097dc2f8e67dee2b095faca9cb0/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a1f570ce4d62d718dce3f179ee78dac3b545ac16c0c04bb363b7607a949c0d1", size = 1246548, upload-time = "2025-08-10T21:25:58.246Z" }, { url = "https://files.pythonhosted.org/packages/21/aa/72a1c5d1e430294f2d32adb9542719cfb441b5da368d09d268c7757af46c/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb27e7b78d716c591e88e0a09a2139c6577865d7f2e152488c2cc6257f460872", size = 1263618, upload-time = "2025-08-10T21:25:59.857Z" }, { url = "https://files.pythonhosted.org/packages/a3/af/db1509a9e79dbf4c260ce0cfa3903ea8945f6240e9e59d1e4deb731b1a40/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:15163165efc2f627eb9687ea5f3a28137217d217ac4024893d753f46bce9de26", size = 1317437, upload-time = "2025-08-10T21:26:01.105Z" }, { url = "https://files.pythonhosted.org/packages/e0/f2/3ea5ee5d52abacdd12013a94130436e19969fa183faa1e7c7fbc89e9a42f/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bdee92c56a71d2b24c33a7d4c2856bd6419d017e08caa7802d2963870e315028", size = 2195742, upload-time = "2025-08-10T21:26:02.675Z" }, { url = "https://files.pythonhosted.org/packages/6f/9b/1efdd3013c2d9a2566aa6a337e9923a00590c516add9a1e89a768a3eb2fc/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:412f287c55a6f54b0650bd9b6dce5aceddb95864a1a90c87af16979d37c89771", size = 2290810, upload-time = "2025-08-10T21:26:04.009Z" }, { url = "https://files.pythonhosted.org/packages/fb/e5/cfdc36109ae4e67361f9bc5b41323648cb24a01b9ade18784657e022e65f/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2c93f00dcba2eea70af2be5f11a830a742fe6b579a1d4e00f47760ef13be247a", size = 2461579, upload-time = "2025-08-10T21:26:05.317Z" }, { url = "https://files.pythonhosted.org/packages/62/86/b589e5e86c7610842213994cdea5add00960076bef4ae290c5fa68589cac/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f117e1a089d9411663a3207ba874f31be9ac8eaa5b533787024dc07aeb74f464", size = 2268071, upload-time = "2025-08-10T21:26:06.686Z" }, { url = "https://files.pythonhosted.org/packages/3b/c6/f8df8509fd1eee6c622febe54384a96cfaf4d43bf2ccec7a0cc17e4715c9/kiwisolver-1.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:be6a04e6c79819c9a8c2373317d19a96048e5a3f90bec587787e86a1153883c2", size = 73840, upload-time = "2025-08-10T21:26:07.94Z" }, { url = "https://files.pythonhosted.org/packages/e2/2d/16e0581daafd147bc11ac53f032a2b45eabac897f42a338d0a13c1e5c436/kiwisolver-1.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:0ae37737256ba2de764ddc12aed4956460277f00c4996d51a197e72f62f5eec7", size = 65159, upload-time = "2025-08-10T21:26:09.048Z" }, { url = "https://files.pythonhosted.org/packages/86/c9/13573a747838aeb1c76e3267620daa054f4152444d1f3d1a2324b78255b5/kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999", size = 123686, upload-time = "2025-08-10T21:26:10.034Z" }, { url = "https://files.pythonhosted.org/packages/51/ea/2ecf727927f103ffd1739271ca19c424d0e65ea473fbaeea1c014aea93f6/kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2", size = 66460, upload-time = "2025-08-10T21:26:11.083Z" }, { url = "https://files.pythonhosted.org/packages/5b/5a/51f5464373ce2aeb5194508298a508b6f21d3867f499556263c64c621914/kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14", size = 64952, upload-time = "2025-08-10T21:26:12.058Z" }, { url = "https://files.pythonhosted.org/packages/70/90/6d240beb0f24b74371762873e9b7f499f1e02166a2d9c5801f4dbf8fa12e/kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04", size = 1474756, upload-time = "2025-08-10T21:26:13.096Z" }, { url = "https://files.pythonhosted.org/packages/12/42/f36816eaf465220f683fb711efdd1bbf7a7005a2473d0e4ed421389bd26c/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752", size = 1276404, upload-time = "2025-08-10T21:26:14.457Z" }, { url = "https://files.pythonhosted.org/packages/2e/64/bc2de94800adc830c476dce44e9b40fd0809cddeef1fde9fcf0f73da301f/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77", size = 1294410, upload-time = "2025-08-10T21:26:15.73Z" }, { url = "https://files.pythonhosted.org/packages/5f/42/2dc82330a70aa8e55b6d395b11018045e58d0bb00834502bf11509f79091/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198", size = 1343631, upload-time = "2025-08-10T21:26:17.045Z" }, { url = "https://files.pythonhosted.org/packages/22/fd/f4c67a6ed1aab149ec5a8a401c323cee7a1cbe364381bb6c9c0d564e0e20/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d", size = 2224963, upload-time = "2025-08-10T21:26:18.737Z" }, { url = "https://files.pythonhosted.org/packages/45/aa/76720bd4cb3713314677d9ec94dcc21ced3f1baf4830adde5bb9b2430a5f/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab", size = 2321295, upload-time = "2025-08-10T21:26:20.11Z" }, { url = "https://files.pythonhosted.org/packages/80/19/d3ec0d9ab711242f56ae0dc2fc5d70e298bb4a1f9dfab44c027668c673a1/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2", size = 2487987, upload-time = "2025-08-10T21:26:21.49Z" }, { url = "https://files.pythonhosted.org/packages/39/e9/61e4813b2c97e86b6fdbd4dd824bf72d28bcd8d4849b8084a357bc0dd64d/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145", size = 2291817, upload-time = "2025-08-10T21:26:22.812Z" }, { url = "https://files.pythonhosted.org/packages/a0/41/85d82b0291db7504da3c2defe35c9a8a5c9803a730f297bd823d11d5fb77/kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54", size = 73895, upload-time = "2025-08-10T21:26:24.37Z" }, { url = "https://files.pythonhosted.org/packages/e2/92/5f3068cf15ee5cb624a0c7596e67e2a0bb2adee33f71c379054a491d07da/kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60", size = 64992, upload-time = "2025-08-10T21:26:25.732Z" }, { url = "https://files.pythonhosted.org/packages/31/c1/c2686cda909742ab66c7388e9a1a8521a59eb89f8bcfbee28fc980d07e24/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8", size = 123681, upload-time = "2025-08-10T21:26:26.725Z" }, { url = "https://files.pythonhosted.org/packages/ca/f0/f44f50c9f5b1a1860261092e3bc91ecdc9acda848a8b8c6abfda4a24dd5c/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2", size = 66464, upload-time = "2025-08-10T21:26:27.733Z" }, { url = "https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f", size = 64961, upload-time = "2025-08-10T21:26:28.729Z" }, { url = "https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098", size = 1474607, upload-time = "2025-08-10T21:26:29.798Z" }, { url = "https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed", size = 1276546, upload-time = "2025-08-10T21:26:31.401Z" }, { url = "https://files.pythonhosted.org/packages/8b/ad/8bfc1c93d4cc565e5069162f610ba2f48ff39b7de4b5b8d93f69f30c4bed/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525", size = 1294482, upload-time = "2025-08-10T21:26:32.721Z" }, { url = "https://files.pythonhosted.org/packages/da/f1/6aca55ff798901d8ce403206d00e033191f63d82dd708a186e0ed2067e9c/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78", size = 1343720, upload-time = "2025-08-10T21:26:34.032Z" }, { url = "https://files.pythonhosted.org/packages/d1/91/eed031876c595c81d90d0f6fc681ece250e14bf6998c3d7c419466b523b7/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b", size = 2224907, upload-time = "2025-08-10T21:26:35.824Z" }, { url = "https://files.pythonhosted.org/packages/e9/ec/4d1925f2e49617b9cca9c34bfa11adefad49d00db038e692a559454dfb2e/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799", size = 2321334, upload-time = "2025-08-10T21:26:37.534Z" }, { url = "https://files.pythonhosted.org/packages/43/cb/450cd4499356f68802750c6ddc18647b8ea01ffa28f50d20598e0befe6e9/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3", size = 2488313, upload-time = "2025-08-10T21:26:39.191Z" }, { url = "https://files.pythonhosted.org/packages/71/67/fc76242bd99f885651128a5d4fa6083e5524694b7c88b489b1b55fdc491d/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c", size = 2291970, upload-time = "2025-08-10T21:26:40.828Z" }, { url = "https://files.pythonhosted.org/packages/75/bd/f1a5d894000941739f2ae1b65a32892349423ad49c2e6d0771d0bad3fae4/kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d", size = 73894, upload-time = "2025-08-10T21:26:42.33Z" }, { url = "https://files.pythonhosted.org/packages/95/38/dce480814d25b99a391abbddadc78f7c117c6da34be68ca8b02d5848b424/kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2", size = 64995, upload-time = "2025-08-10T21:26:43.889Z" }, { url = "https://files.pythonhosted.org/packages/e2/37/7d218ce5d92dadc5ebdd9070d903e0c7cf7edfe03f179433ac4d13ce659c/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1", size = 126510, upload-time = "2025-08-10T21:26:44.915Z" }, { url = "https://files.pythonhosted.org/packages/23/b0/e85a2b48233daef4b648fb657ebbb6f8367696a2d9548a00b4ee0eb67803/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1", size = 67903, upload-time = "2025-08-10T21:26:45.934Z" }, { url = "https://files.pythonhosted.org/packages/44/98/f2425bc0113ad7de24da6bb4dae1343476e95e1d738be7c04d31a5d037fd/kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11", size = 66402, upload-time = "2025-08-10T21:26:47.101Z" }, { url = "https://files.pythonhosted.org/packages/98/d8/594657886df9f34c4177cc353cc28ca7e6e5eb562d37ccc233bff43bbe2a/kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c", size = 1582135, upload-time = "2025-08-10T21:26:48.665Z" }, { url = "https://files.pythonhosted.org/packages/5c/c6/38a115b7170f8b306fc929e166340c24958347308ea3012c2b44e7e295db/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197", size = 1389409, upload-time = "2025-08-10T21:26:50.335Z" }, { url = "https://files.pythonhosted.org/packages/bf/3b/e04883dace81f24a568bcee6eb3001da4ba05114afa622ec9b6fafdc1f5e/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c", size = 1401763, upload-time = "2025-08-10T21:26:51.867Z" }, { url = "https://files.pythonhosted.org/packages/9f/80/20ace48e33408947af49d7d15c341eaee69e4e0304aab4b7660e234d6288/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185", size = 1453643, upload-time = "2025-08-10T21:26:53.592Z" }, { url = "https://files.pythonhosted.org/packages/64/31/6ce4380a4cd1f515bdda976a1e90e547ccd47b67a1546d63884463c92ca9/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748", size = 2330818, upload-time = "2025-08-10T21:26:55.051Z" }, { url = "https://files.pythonhosted.org/packages/fa/e9/3f3fcba3bcc7432c795b82646306e822f3fd74df0ee81f0fa067a1f95668/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64", size = 2419963, upload-time = "2025-08-10T21:26:56.421Z" }, { url = "https://files.pythonhosted.org/packages/99/43/7320c50e4133575c66e9f7dadead35ab22d7c012a3b09bb35647792b2a6d/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff", size = 2594639, upload-time = "2025-08-10T21:26:57.882Z" }, { url = "https://files.pythonhosted.org/packages/65/d6/17ae4a270d4a987ef8a385b906d2bdfc9fce502d6dc0d3aea865b47f548c/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07", size = 2391741, upload-time = "2025-08-10T21:26:59.237Z" }, { url = "https://files.pythonhosted.org/packages/2a/8f/8f6f491d595a9e5912971f3f863d81baddccc8a4d0c3749d6a0dd9ffc9df/kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c", size = 68646, upload-time = "2025-08-10T21:27:00.52Z" }, { url = "https://files.pythonhosted.org/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386", size = 123806, upload-time = "2025-08-10T21:27:01.537Z" }, { url = "https://files.pythonhosted.org/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552", size = 66605, upload-time = "2025-08-10T21:27:03.335Z" }, { url = "https://files.pythonhosted.org/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3", size = 64925, upload-time = "2025-08-10T21:27:04.339Z" }, { url = "https://files.pythonhosted.org/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58", size = 1472414, upload-time = "2025-08-10T21:27:05.437Z" }, { url = "https://files.pythonhosted.org/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4", size = 1281272, upload-time = "2025-08-10T21:27:07.063Z" }, { url = "https://files.pythonhosted.org/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df", size = 1298578, upload-time = "2025-08-10T21:27:08.452Z" }, { url = "https://files.pythonhosted.org/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6", size = 1345607, upload-time = "2025-08-10T21:27:10.125Z" }, { url = "https://files.pythonhosted.org/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5", size = 2230150, upload-time = "2025-08-10T21:27:11.484Z" }, { url = "https://files.pythonhosted.org/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf", size = 2325979, upload-time = "2025-08-10T21:27:12.917Z" }, { url = "https://files.pythonhosted.org/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5", size = 2491456, upload-time = "2025-08-10T21:27:14.353Z" }, { url = "https://files.pythonhosted.org/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce", size = 2294621, upload-time = "2025-08-10T21:27:15.808Z" }, { url = "https://files.pythonhosted.org/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7", size = 75417, upload-time = "2025-08-10T21:27:17.436Z" }, { url = "https://files.pythonhosted.org/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c", size = 66582, upload-time = "2025-08-10T21:27:18.436Z" }, { url = "https://files.pythonhosted.org/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548", size = 126514, upload-time = "2025-08-10T21:27:19.465Z" }, { url = "https://files.pythonhosted.org/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d", size = 67905, upload-time = "2025-08-10T21:27:20.51Z" }, { url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" }, { url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" }, { url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" }, { url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" }, { url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" }, { url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" }, { url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" }, { url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" }, { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, { url = "https://files.pythonhosted.org/packages/a2/63/fde392691690f55b38d5dd7b3710f5353bf7a8e52de93a22968801ab8978/kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d1d9e582ad4d63062d34077a9a1e9f3c34088a2ec5135b1f7190c07cf366527", size = 60183, upload-time = "2025-08-10T21:27:37.669Z" }, { url = "https://files.pythonhosted.org/packages/27/b1/6aad34edfdb7cced27f371866f211332bba215bfd918ad3322a58f480d8b/kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:deed0c7258ceb4c44ad5ec7d9918f9f14fd05b2be86378d86cf50e63d1e7b771", size = 58675, upload-time = "2025-08-10T21:27:39.031Z" }, { url = "https://files.pythonhosted.org/packages/9d/1a/23d855a702bb35a76faed5ae2ba3de57d323f48b1f6b17ee2176c4849463/kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a590506f303f512dff6b7f75fd2fd18e16943efee932008fe7140e5fa91d80e", size = 80277, upload-time = "2025-08-10T21:27:40.129Z" }, { url = "https://files.pythonhosted.org/packages/5a/5b/5239e3c2b8fb5afa1e8508f721bb77325f740ab6994d963e61b2b7abcc1e/kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e09c2279a4d01f099f52d5c4b3d9e208e91edcbd1a175c9662a8b16e000fece9", size = 77994, upload-time = "2025-08-10T21:27:41.181Z" }, { url = "https://files.pythonhosted.org/packages/f9/1c/5d4d468fb16f8410e596ed0eac02d2c68752aa7dc92997fe9d60a7147665/kiwisolver-1.4.9-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c9e7cdf45d594ee04d5be1b24dd9d49f3d1590959b2271fb30b5ca2b262c00fb", size = 73744, upload-time = "2025-08-10T21:27:42.254Z" }, { url = "https://files.pythonhosted.org/packages/a3/0f/36d89194b5a32c054ce93e586d4049b6c2c22887b0eb229c61c68afd3078/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5", size = 60104, upload-time = "2025-08-10T21:27:43.287Z" }, { url = "https://files.pythonhosted.org/packages/52/ba/4ed75f59e4658fd21fe7dde1fee0ac397c678ec3befba3fe6482d987af87/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa", size = 58592, upload-time = "2025-08-10T21:27:44.314Z" }, { url = "https://files.pythonhosted.org/packages/33/01/a8ea7c5ea32a9b45ceeaee051a04c8ed4320f5add3c51bfa20879b765b70/kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2", size = 80281, upload-time = "2025-08-10T21:27:45.369Z" }, { url = "https://files.pythonhosted.org/packages/da/e3/dbd2ecdce306f1d07a1aaf324817ee993aab7aee9db47ceac757deabafbe/kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:464415881e4801295659462c49461a24fb107c140de781d55518c4b80cb6790f", size = 78009, upload-time = "2025-08-10T21:27:46.376Z" }, { url = "https://files.pythonhosted.org/packages/da/e9/0d4add7873a73e462aeb45c036a2dead2562b825aa46ba326727b3f31016/kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1", size = 73929, upload-time = "2025-08-10T21:27:48.236Z" }, ] [[package]] name = "librt" version = "0.7.8" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e7/24/5f3646ff414285e0f7708fa4e946b9bf538345a41d1c375c439467721a5e/librt-0.7.8.tar.gz", hash = "sha256:1a4ede613941d9c3470b0368be851df6bb78ab218635512d0370b27a277a0862", size = 148323, upload-time = "2026-01-14T12:56:16.876Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/44/13/57b06758a13550c5f09563893b004f98e9537ee6ec67b7df85c3571c8832/librt-0.7.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b45306a1fc5f53c9330fbee134d8b3227fe5da2ab09813b892790400aa49352d", size = 56521, upload-time = "2026-01-14T12:54:40.066Z" }, { url = "https://files.pythonhosted.org/packages/c2/24/bbea34d1452a10612fb45ac8356f95351ba40c2517e429602160a49d1fd0/librt-0.7.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:864c4b7083eeee250ed55135d2127b260d7eb4b5e953a9e5df09c852e327961b", size = 58456, upload-time = "2026-01-14T12:54:41.471Z" }, { url = "https://files.pythonhosted.org/packages/04/72/a168808f92253ec3a810beb1eceebc465701197dbc7e865a1c9ceb3c22c7/librt-0.7.8-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6938cc2de153bc927ed8d71c7d2f2ae01b4e96359126c602721340eb7ce1a92d", size = 164392, upload-time = "2026-01-14T12:54:42.843Z" }, { url = "https://files.pythonhosted.org/packages/14/5c/4c0d406f1b02735c2e7af8ff1ff03a6577b1369b91aa934a9fa2cc42c7ce/librt-0.7.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66daa6ac5de4288a5bbfbe55b4caa7bf0cd26b3269c7a476ffe8ce45f837f87d", size = 172959, upload-time = "2026-01-14T12:54:44.602Z" }, { url = "https://files.pythonhosted.org/packages/82/5f/3e85351c523f73ad8d938989e9a58c7f59fb9c17f761b9981b43f0025ce7/librt-0.7.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4864045f49dc9c974dadb942ac56a74cd0479a2aafa51ce272c490a82322ea3c", size = 186717, upload-time = "2026-01-14T12:54:45.986Z" }, { url = "https://files.pythonhosted.org/packages/08/f8/18bfe092e402d00fe00d33aa1e01dda1bd583ca100b393b4373847eade6d/librt-0.7.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a36515b1328dc5b3ffce79fe204985ca8572525452eacabee2166f44bb387b2c", size = 184585, upload-time = "2026-01-14T12:54:47.139Z" }, { url = "https://files.pythonhosted.org/packages/4e/fc/f43972ff56fd790a9fa55028a52ccea1875100edbb856b705bd393b601e3/librt-0.7.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b7e7f140c5169798f90b80d6e607ed2ba5059784968a004107c88ad61fb3641d", size = 180497, upload-time = "2026-01-14T12:54:48.946Z" }, { url = "https://files.pythonhosted.org/packages/e1/3a/25e36030315a410d3ad0b7d0f19f5f188e88d1613d7d3fd8150523ea1093/librt-0.7.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff71447cb778a4f772ddc4ce360e6ba9c95527ed84a52096bd1bbf9fee2ec7c0", size = 200052, upload-time = "2026-01-14T12:54:50.382Z" }, { url = "https://files.pythonhosted.org/packages/fc/b8/f3a5a1931ae2a6ad92bf6893b9ef44325b88641d58723529e2c2935e8abe/librt-0.7.8-cp310-cp310-win32.whl", hash = "sha256:047164e5f68b7a8ebdf9fae91a3c2161d3192418aadd61ddd3a86a56cbe3dc85", size = 43477, upload-time = "2026-01-14T12:54:51.815Z" }, { url = "https://files.pythonhosted.org/packages/fe/91/c4202779366bc19f871b4ad25db10fcfa1e313c7893feb942f32668e8597/librt-0.7.8-cp310-cp310-win_amd64.whl", hash = "sha256:d6f254d096d84156a46a84861183c183d30734e52383602443292644d895047c", size = 49806, upload-time = "2026-01-14T12:54:53.149Z" }, { url = "https://files.pythonhosted.org/packages/1b/a3/87ea9c1049f2c781177496ebee29430e4631f439b8553a4969c88747d5d8/librt-0.7.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3e9c11aa260c31493d4b3197d1e28dd07768594a4f92bec4506849d736248f", size = 56507, upload-time = "2026-01-14T12:54:54.156Z" }, { url = "https://files.pythonhosted.org/packages/5e/4a/23bcef149f37f771ad30203d561fcfd45b02bc54947b91f7a9ac34815747/librt-0.7.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddb52499d0b3ed4aa88746aaf6f36a08314677d5c346234c3987ddc506404eac", size = 58455, upload-time = "2026-01-14T12:54:55.978Z" }, { url = "https://files.pythonhosted.org/packages/22/6e/46eb9b85c1b9761e0f42b6e6311e1cc544843ac897457062b9d5d0b21df4/librt-0.7.8-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e9c0afebbe6ce177ae8edba0c7c4d626f2a0fc12c33bb993d163817c41a7a05c", size = 164956, upload-time = "2026-01-14T12:54:57.311Z" }, { url = "https://files.pythonhosted.org/packages/7a/3f/aa7c7f6829fb83989feb7ba9aa11c662b34b4bd4bd5b262f2876ba3db58d/librt-0.7.8-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:631599598e2c76ded400c0a8722dec09217c89ff64dc54b060f598ed68e7d2a8", size = 174364, upload-time = "2026-01-14T12:54:59.089Z" }, { url = "https://files.pythonhosted.org/packages/3f/2d/d57d154b40b11f2cb851c4df0d4c4456bacd9b1ccc4ecb593ddec56c1a8b/librt-0.7.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c1ba843ae20db09b9d5c80475376168feb2640ce91cd9906414f23cc267a1ff", size = 188034, upload-time = "2026-01-14T12:55:00.141Z" }, { url = "https://files.pythonhosted.org/packages/59/f9/36c4dad00925c16cd69d744b87f7001792691857d3b79187e7a673e812fb/librt-0.7.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b5b007bb22ea4b255d3ee39dfd06d12534de2fcc3438567d9f48cdaf67ae1ae3", size = 186295, upload-time = "2026-01-14T12:55:01.303Z" }, { url = "https://files.pythonhosted.org/packages/23/9b/8a9889d3df5efb67695a67785028ccd58e661c3018237b73ad081691d0cb/librt-0.7.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dbd79caaf77a3f590cbe32dc2447f718772d6eea59656a7dcb9311161b10fa75", size = 181470, upload-time = "2026-01-14T12:55:02.492Z" }, { url = "https://files.pythonhosted.org/packages/43/64/54d6ef11afca01fef8af78c230726a9394759f2addfbf7afc5e3cc032a45/librt-0.7.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:87808a8d1e0bd62a01cafc41f0fd6818b5a5d0ca0d8a55326a81643cdda8f873", size = 201713, upload-time = "2026-01-14T12:55:03.919Z" }, { url = "https://files.pythonhosted.org/packages/2d/29/73e7ed2991330b28919387656f54109139b49e19cd72902f466bd44415fd/librt-0.7.8-cp311-cp311-win32.whl", hash = "sha256:31724b93baa91512bd0a376e7cf0b59d8b631ee17923b1218a65456fa9bda2e7", size = 43803, upload-time = "2026-01-14T12:55:04.996Z" }, { url = "https://files.pythonhosted.org/packages/3f/de/66766ff48ed02b4d78deea30392ae200bcbd99ae61ba2418b49fd50a4831/librt-0.7.8-cp311-cp311-win_amd64.whl", hash = "sha256:978e8b5f13e52cf23a9e80f3286d7546baa70bc4ef35b51d97a709d0b28e537c", size = 50080, upload-time = "2026-01-14T12:55:06.489Z" }, { url = "https://files.pythonhosted.org/packages/6f/e3/33450438ff3a8c581d4ed7f798a70b07c3206d298cf0b87d3806e72e3ed8/librt-0.7.8-cp311-cp311-win_arm64.whl", hash = "sha256:20e3946863d872f7cabf7f77c6c9d370b8b3d74333d3a32471c50d3a86c0a232", size = 43383, upload-time = "2026-01-14T12:55:07.49Z" }, { url = "https://files.pythonhosted.org/packages/56/04/79d8fcb43cae376c7adbab7b2b9f65e48432c9eced62ac96703bcc16e09b/librt-0.7.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b6943885b2d49c48d0cff23b16be830ba46b0152d98f62de49e735c6e655a63", size = 57472, upload-time = "2026-01-14T12:55:08.528Z" }, { url = "https://files.pythonhosted.org/packages/b4/ba/60b96e93043d3d659da91752689023a73981336446ae82078cddf706249e/librt-0.7.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46ef1f4b9b6cc364b11eea0ecc0897314447a66029ee1e55859acb3dd8757c93", size = 58986, upload-time = "2026-01-14T12:55:09.466Z" }, { url = "https://files.pythonhosted.org/packages/7c/26/5215e4cdcc26e7be7eee21955a7e13cbf1f6d7d7311461a6014544596fac/librt-0.7.8-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:907ad09cfab21e3c86e8f1f87858f7049d1097f77196959c033612f532b4e592", size = 168422, upload-time = "2026-01-14T12:55:10.499Z" }, { url = "https://files.pythonhosted.org/packages/0f/84/e8d1bc86fa0159bfc24f3d798d92cafd3897e84c7fea7fe61b3220915d76/librt-0.7.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2991b6c3775383752b3ca0204842743256f3ad3deeb1d0adc227d56b78a9a850", size = 177478, upload-time = "2026-01-14T12:55:11.577Z" }, { url = "https://files.pythonhosted.org/packages/57/11/d0268c4b94717a18aa91df1100e767b010f87b7ae444dafaa5a2d80f33a6/librt-0.7.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03679b9856932b8c8f674e87aa3c55ea11c9274301f76ae8dc4d281bda55cf62", size = 192439, upload-time = "2026-01-14T12:55:12.7Z" }, { url = "https://files.pythonhosted.org/packages/8d/56/1e8e833b95fe684f80f8894ae4d8b7d36acc9203e60478fcae599120a975/librt-0.7.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3968762fec1b2ad34ce57458b6de25dbb4142713e9ca6279a0d352fa4e9f452b", size = 191483, upload-time = "2026-01-14T12:55:13.838Z" }, { url = "https://files.pythonhosted.org/packages/17/48/f11cf28a2cb6c31f282009e2208312aa84a5ee2732859f7856ee306176d5/librt-0.7.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bb7a7807523a31f03061288cc4ffc065d684c39db7644c676b47d89553c0d714", size = 185376, upload-time = "2026-01-14T12:55:15.017Z" }, { url = "https://files.pythonhosted.org/packages/b8/6a/d7c116c6da561b9155b184354a60a3d5cdbf08fc7f3678d09c95679d13d9/librt-0.7.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad64a14b1e56e702e19b24aae108f18ad1bf7777f3af5fcd39f87d0c5a814449", size = 206234, upload-time = "2026-01-14T12:55:16.571Z" }, { url = "https://files.pythonhosted.org/packages/61/de/1975200bb0285fc921c5981d9978ce6ce11ae6d797df815add94a5a848a3/librt-0.7.8-cp312-cp312-win32.whl", hash = "sha256:0241a6ed65e6666236ea78203a73d800dbed896cf12ae25d026d75dc1fcd1dac", size = 44057, upload-time = "2026-01-14T12:55:18.077Z" }, { url = "https://files.pythonhosted.org/packages/8e/cd/724f2d0b3461426730d4877754b65d39f06a41ac9d0a92d5c6840f72b9ae/librt-0.7.8-cp312-cp312-win_amd64.whl", hash = "sha256:6db5faf064b5bab9675c32a873436b31e01d66ca6984c6f7f92621656033a708", size = 50293, upload-time = "2026-01-14T12:55:19.179Z" }, { url = "https://files.pythonhosted.org/packages/bd/cf/7e899acd9ee5727ad8160fdcc9994954e79fab371c66535c60e13b968ffc/librt-0.7.8-cp312-cp312-win_arm64.whl", hash = "sha256:57175aa93f804d2c08d2edb7213e09276bd49097611aefc37e3fa38d1fb99ad0", size = 43574, upload-time = "2026-01-14T12:55:20.185Z" }, { url = "https://files.pythonhosted.org/packages/a1/fe/b1f9de2829cf7fc7649c1dcd202cfd873837c5cc2fc9e526b0e7f716c3d2/librt-0.7.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4c3995abbbb60b3c129490fa985dfe6cac11d88fc3c36eeb4fb1449efbbb04fc", size = 57500, upload-time = "2026-01-14T12:55:21.219Z" }, { url = "https://files.pythonhosted.org/packages/eb/d4/4a60fbe2e53b825f5d9a77325071d61cd8af8506255067bf0c8527530745/librt-0.7.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44e0c2cbc9bebd074cf2cdbe472ca185e824be4e74b1c63a8e934cea674bebf2", size = 59019, upload-time = "2026-01-14T12:55:22.256Z" }, { url = "https://files.pythonhosted.org/packages/6a/37/61ff80341ba5159afa524445f2d984c30e2821f31f7c73cf166dcafa5564/librt-0.7.8-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d2f1e492cae964b3463a03dc77a7fe8742f7855d7258c7643f0ee32b6651dd3", size = 169015, upload-time = "2026-01-14T12:55:23.24Z" }, { url = "https://files.pythonhosted.org/packages/1c/86/13d4f2d6a93f181ebf2fc953868826653ede494559da8268023fe567fca3/librt-0.7.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:451e7ffcef8f785831fdb791bd69211f47e95dc4c6ddff68e589058806f044c6", size = 178161, upload-time = "2026-01-14T12:55:24.826Z" }, { url = "https://files.pythonhosted.org/packages/88/26/e24ef01305954fc4d771f1f09f3dd682f9eb610e1bec188ffb719374d26e/librt-0.7.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3469e1af9f1380e093ae06bedcbdd11e407ac0b303a56bbe9afb1d6824d4982d", size = 193015, upload-time = "2026-01-14T12:55:26.04Z" }, { url = "https://files.pythonhosted.org/packages/88/a0/92b6bd060e720d7a31ed474d046a69bd55334ec05e9c446d228c4b806ae3/librt-0.7.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f11b300027ce19a34f6d24ebb0a25fd0e24a9d53353225a5c1e6cadbf2916b2e", size = 192038, upload-time = "2026-01-14T12:55:27.208Z" }, { url = "https://files.pythonhosted.org/packages/06/bb/6f4c650253704279c3a214dad188101d1b5ea23be0606628bc6739456624/librt-0.7.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4adc73614f0d3c97874f02f2c7fd2a27854e7e24ad532ea6b965459c5b757eca", size = 186006, upload-time = "2026-01-14T12:55:28.594Z" }, { url = "https://files.pythonhosted.org/packages/dc/00/1c409618248d43240cadf45f3efb866837fa77e9a12a71481912135eb481/librt-0.7.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60c299e555f87e4c01b2eca085dfccda1dde87f5a604bb45c2906b8305819a93", size = 206888, upload-time = "2026-01-14T12:55:30.214Z" }, { url = "https://files.pythonhosted.org/packages/d9/83/b2cfe8e76ff5c1c77f8a53da3d5de62d04b5ebf7cf913e37f8bca43b5d07/librt-0.7.8-cp313-cp313-win32.whl", hash = "sha256:b09c52ed43a461994716082ee7d87618096851319bf695d57ec123f2ab708951", size = 44126, upload-time = "2026-01-14T12:55:31.44Z" }, { url = "https://files.pythonhosted.org/packages/a9/0b/c59d45de56a51bd2d3a401fc63449c0ac163e4ef7f523ea8b0c0dee86ec5/librt-0.7.8-cp313-cp313-win_amd64.whl", hash = "sha256:f8f4a901a3fa28969d6e4519deceab56c55a09d691ea7b12ca830e2fa3461e34", size = 50262, upload-time = "2026-01-14T12:55:33.01Z" }, { url = "https://files.pythonhosted.org/packages/fc/b9/973455cec0a1ec592395250c474164c4a58ebf3e0651ee920fef1a2623f1/librt-0.7.8-cp313-cp313-win_arm64.whl", hash = "sha256:43d4e71b50763fcdcf64725ac680d8cfa1706c928b844794a7aa0fa9ac8e5f09", size = 43600, upload-time = "2026-01-14T12:55:34.054Z" }, { url = "https://files.pythonhosted.org/packages/1a/73/fa8814c6ce2d49c3827829cadaa1589b0bf4391660bd4510899393a23ebc/librt-0.7.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:be927c3c94c74b05128089a955fba86501c3b544d1d300282cc1b4bd370cb418", size = 57049, upload-time = "2026-01-14T12:55:35.056Z" }, { url = "https://files.pythonhosted.org/packages/53/fe/f6c70956da23ea235fd2e3cc16f4f0b4ebdfd72252b02d1164dd58b4e6c3/librt-0.7.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7b0803e9008c62a7ef79058233db7ff6f37a9933b8f2573c05b07ddafa226611", size = 58689, upload-time = "2026-01-14T12:55:36.078Z" }, { url = "https://files.pythonhosted.org/packages/1f/4d/7a2481444ac5fba63050d9abe823e6bc16896f575bfc9c1e5068d516cdce/librt-0.7.8-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:79feb4d00b2a4e0e05c9c56df707934f41fcb5fe53fd9efb7549068d0495b758", size = 166808, upload-time = "2026-01-14T12:55:37.595Z" }, { url = "https://files.pythonhosted.org/packages/ac/3c/10901d9e18639f8953f57c8986796cfbf4c1c514844a41c9197cf87cb707/librt-0.7.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9122094e3f24aa759c38f46bd8863433820654927370250f460ae75488b66ea", size = 175614, upload-time = "2026-01-14T12:55:38.756Z" }, { url = "https://files.pythonhosted.org/packages/db/01/5cbdde0951a5090a80e5ba44e6357d375048123c572a23eecfb9326993a7/librt-0.7.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e03bea66af33c95ce3addf87a9bf1fcad8d33e757bc479957ddbc0e4f7207ac", size = 189955, upload-time = "2026-01-14T12:55:39.939Z" }, { url = "https://files.pythonhosted.org/packages/6a/b4/e80528d2f4b7eaf1d437fcbd6fc6ba4cbeb3e2a0cb9ed5a79f47c7318706/librt-0.7.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1ade7f31675db00b514b98f9ab9a7698c7282dad4be7492589109471852d398", size = 189370, upload-time = "2026-01-14T12:55:41.057Z" }, { url = "https://files.pythonhosted.org/packages/c1/ab/938368f8ce31a9787ecd4becb1e795954782e4312095daf8fd22420227c8/librt-0.7.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a14229ac62adcf1b90a15992f1ab9c69ae8b99ffb23cb64a90878a6e8a2f5b81", size = 183224, upload-time = "2026-01-14T12:55:42.328Z" }, { url = "https://files.pythonhosted.org/packages/3c/10/559c310e7a6e4014ac44867d359ef8238465fb499e7eb31b6bfe3e3f86f5/librt-0.7.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5bcaaf624fd24e6a0cb14beac37677f90793a96864c67c064a91458611446e83", size = 203541, upload-time = "2026-01-14T12:55:43.501Z" }, { url = "https://files.pythonhosted.org/packages/f8/db/a0db7acdb6290c215f343835c6efda5b491bb05c3ddc675af558f50fdba3/librt-0.7.8-cp314-cp314-win32.whl", hash = "sha256:7aa7d5457b6c542ecaed79cec4ad98534373c9757383973e638ccced0f11f46d", size = 40657, upload-time = "2026-01-14T12:55:44.668Z" }, { url = "https://files.pythonhosted.org/packages/72/e0/4f9bdc2a98a798511e81edcd6b54fe82767a715e05d1921115ac70717f6f/librt-0.7.8-cp314-cp314-win_amd64.whl", hash = "sha256:3d1322800771bee4a91f3b4bd4e49abc7d35e65166821086e5afd1e6c0d9be44", size = 46835, upload-time = "2026-01-14T12:55:45.655Z" }, { url = "https://files.pythonhosted.org/packages/f9/3d/59c6402e3dec2719655a41ad027a7371f8e2334aa794ed11533ad5f34969/librt-0.7.8-cp314-cp314-win_arm64.whl", hash = "sha256:5363427bc6a8c3b1719f8f3845ea53553d301382928a86e8fab7984426949bce", size = 39885, upload-time = "2026-01-14T12:55:47.138Z" }, { url = "https://files.pythonhosted.org/packages/4e/9c/2481d80950b83085fb14ba3c595db56330d21bbc7d88a19f20165f3538db/librt-0.7.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ca916919793a77e4a98d4a1701e345d337ce53be4a16620f063191f7322ac80f", size = 59161, upload-time = "2026-01-14T12:55:48.45Z" }, { url = "https://files.pythonhosted.org/packages/96/79/108df2cfc4e672336765d54e3ff887294c1cc36ea4335c73588875775527/librt-0.7.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:54feb7b4f2f6706bb82325e836a01be805770443e2400f706e824e91f6441dde", size = 61008, upload-time = "2026-01-14T12:55:49.527Z" }, { url = "https://files.pythonhosted.org/packages/46/f2/30179898f9994a5637459d6e169b6abdc982012c0a4b2d4c26f50c06f911/librt-0.7.8-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:39a4c76fee41007070f872b648cc2f711f9abf9a13d0c7162478043377b52c8e", size = 187199, upload-time = "2026-01-14T12:55:50.587Z" }, { url = "https://files.pythonhosted.org/packages/b4/da/f7563db55cebdc884f518ba3791ad033becc25ff68eb70902b1747dc0d70/librt-0.7.8-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac9c8a458245c7de80bc1b9765b177055efff5803f08e548dd4bb9ab9a8d789b", size = 198317, upload-time = "2026-01-14T12:55:51.991Z" }, { url = "https://files.pythonhosted.org/packages/b3/6c/4289acf076ad371471fa86718c30ae353e690d3de6167f7db36f429272f1/librt-0.7.8-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95b67aa7eff150f075fda09d11f6bfb26edffd300f6ab1666759547581e8f666", size = 210334, upload-time = "2026-01-14T12:55:53.682Z" }, { url = "https://files.pythonhosted.org/packages/4a/7f/377521ac25b78ac0a5ff44127a0360ee6d5ddd3ce7327949876a30533daa/librt-0.7.8-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:535929b6eff670c593c34ff435d5440c3096f20fa72d63444608a5aef64dd581", size = 211031, upload-time = "2026-01-14T12:55:54.827Z" }, { url = "https://files.pythonhosted.org/packages/c5/b1/e1e96c3e20b23d00cf90f4aad48f0deb4cdfec2f0ed8380d0d85acf98bbf/librt-0.7.8-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:63937bd0f4d1cb56653dc7ae900d6c52c41f0015e25aaf9902481ee79943b33a", size = 204581, upload-time = "2026-01-14T12:55:56.811Z" }, { url = "https://files.pythonhosted.org/packages/43/71/0f5d010e92ed9747e14bef35e91b6580533510f1e36a8a09eb79ee70b2f0/librt-0.7.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf243da9e42d914036fd362ac3fa77d80a41cadcd11ad789b1b5eec4daaf67ca", size = 224731, upload-time = "2026-01-14T12:55:58.175Z" }, { url = "https://files.pythonhosted.org/packages/22/f0/07fb6ab5c39a4ca9af3e37554f9d42f25c464829254d72e4ebbd81da351c/librt-0.7.8-cp314-cp314t-win32.whl", hash = "sha256:171ca3a0a06c643bd0a2f62a8944e1902c94aa8e5da4db1ea9a8daf872685365", size = 41173, upload-time = "2026-01-14T12:55:59.315Z" }, { url = "https://files.pythonhosted.org/packages/24/d4/7e4be20993dc6a782639625bd2f97f3c66125c7aa80c82426956811cfccf/librt-0.7.8-cp314-cp314t-win_amd64.whl", hash = "sha256:445b7304145e24c60288a2f172b5ce2ca35c0f81605f5299f3fa567e189d2e32", size = 47668, upload-time = "2026-01-14T12:56:00.261Z" }, { url = "https://files.pythonhosted.org/packages/fc/85/69f92b2a7b3c0f88ffe107c86b952b397004b5b8ea5a81da3d9c04c04422/librt-0.7.8-cp314-cp314t-win_arm64.whl", hash = "sha256:8766ece9de08527deabcd7cb1b4f1a967a385d26e33e536d6d8913db6ef74f06", size = 40550, upload-time = "2026-01-14T12:56:01.542Z" }, { url = "https://files.pythonhosted.org/packages/3b/9b/2668bb01f568bc89ace53736df950845f8adfcacdf6da087d5cef12110cb/librt-0.7.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c7e8f88f79308d86d8f39c491773cbb533d6cb7fa6476f35d711076ee04fceb6", size = 56680, upload-time = "2026-01-14T12:56:02.602Z" }, { url = "https://files.pythonhosted.org/packages/b3/d4/dbb3edf2d0ec4ba08dcaf1865833d32737ad208962d4463c022cea6e9d3c/librt-0.7.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:389bd25a0db916e1d6bcb014f11aa9676cedaa485e9ec3752dfe19f196fd377b", size = 58612, upload-time = "2026-01-14T12:56:03.616Z" }, { url = "https://files.pythonhosted.org/packages/0f/c9/64b029de4ac9901fcd47832c650a0fd050555a452bd455ce8deddddfbb9f/librt-0.7.8-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:73fd300f501a052f2ba52ede721232212f3b06503fa12665408ecfc9d8fd149c", size = 163654, upload-time = "2026-01-14T12:56:04.975Z" }, { url = "https://files.pythonhosted.org/packages/81/5c/95e2abb1b48eb8f8c7fc2ae945321a6b82777947eb544cc785c3f37165b2/librt-0.7.8-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d772edc6a5f7835635c7562f6688e031f0b97e31d538412a852c49c9a6c92d5", size = 172477, upload-time = "2026-01-14T12:56:06.103Z" }, { url = "https://files.pythonhosted.org/packages/7e/27/9bdf12e05b0eb089dd008d9c8aabc05748aad9d40458ade5e627c9538158/librt-0.7.8-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde8a130bd0f239e45503ab39fab239ace094d63ee1d6b67c25a63d741c0f71", size = 186220, upload-time = "2026-01-14T12:56:09.958Z" }, { url = "https://files.pythonhosted.org/packages/53/6a/c3774f4cc95e68ed444a39f2c8bd383fd18673db7d6b98cfa709f6634b93/librt-0.7.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fdec6e2368ae4f796fc72fad7fd4bd1753715187e6d870932b0904609e7c878e", size = 183841, upload-time = "2026-01-14T12:56:11.109Z" }, { url = "https://files.pythonhosted.org/packages/58/6b/48702c61cf83e9c04ad5cec8cad7e5e22a2cde23a13db8ef341598897ddd/librt-0.7.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:00105e7d541a8f2ee5be52caacea98a005e0478cfe78c8080fbb7b5d2b340c63", size = 179751, upload-time = "2026-01-14T12:56:12.278Z" }, { url = "https://files.pythonhosted.org/packages/35/87/5f607fc73a131d4753f4db948833063c6aad18e18a4e6fbf64316c37ae65/librt-0.7.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c6f8947d3dfd7f91066c5b4385812c18be26c9d5a99ca56667547f2c39149d94", size = 199319, upload-time = "2026-01-14T12:56:13.425Z" }, { url = "https://files.pythonhosted.org/packages/6e/cc/b7c5ac28ae0f0645a9681248bae4ede665bba15d6f761c291853c5c5b78e/librt-0.7.8-cp39-cp39-win32.whl", hash = "sha256:41d7bb1e07916aeb12ae4a44e3025db3691c4149ab788d0315781b4d29b86afb", size = 43434, upload-time = "2026-01-14T12:56:14.781Z" }, { url = "https://files.pythonhosted.org/packages/e4/5d/dce0c92f786495adf2c1e6784d9c50a52fb7feb1cfb17af97a08281a6e82/librt-0.7.8-cp39-cp39-win_amd64.whl", hash = "sha256:e90a8e237753c83b8e484d478d9a996dc5e39fd5bd4c6ce32563bc8123f132be", size = 49801, upload-time = "2026-01-14T12:56:15.827Z" }, ] [[package]] name = "markdown-it-py" version = "3.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", "python_full_version < '3.10'", ] dependencies = [ { name = "mdurl", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, ] [[package]] name = "markdown-it-py" version = "4.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "mdurl", marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, ] [[package]] name = "markupsafe" version = "3.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, { url = "https://files.pythonhosted.org/packages/56/23/0d8c13a44bde9154821586520840643467aee574d8ce79a17da539ee7fed/markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26", size = 11623, upload-time = "2025-09-27T18:37:29.296Z" }, { url = "https://files.pythonhosted.org/packages/fd/23/07a2cb9a8045d5f3f0890a8c3bc0859d7a47bfd9a560b563899bec7b72ed/markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc", size = 12049, upload-time = "2025-09-27T18:37:30.234Z" }, { url = "https://files.pythonhosted.org/packages/bc/e4/6be85eb81503f8e11b61c0b6369b6e077dcf0a74adbd9ebf6b349937b4e9/markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c", size = 21923, upload-time = "2025-09-27T18:37:31.177Z" }, { url = "https://files.pythonhosted.org/packages/6f/bc/4dc914ead3fe6ddaef035341fee0fc956949bbd27335b611829292b89ee2/markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42", size = 20543, upload-time = "2025-09-27T18:37:32.168Z" }, { url = "https://files.pythonhosted.org/packages/89/6e/5fe81fbcfba4aef4093d5f856e5c774ec2057946052d18d168219b7bd9f9/markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b", size = 20585, upload-time = "2025-09-27T18:37:33.166Z" }, { url = "https://files.pythonhosted.org/packages/f6/f6/e0e5a3d3ae9c4020f696cd055f940ef86b64fe88de26f3a0308b9d3d048c/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758", size = 21387, upload-time = "2025-09-27T18:37:34.185Z" }, { url = "https://files.pythonhosted.org/packages/c8/25/651753ef4dea08ea790f4fbb65146a9a44a014986996ca40102e237aa49a/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2", size = 20133, upload-time = "2025-09-27T18:37:35.138Z" }, { url = "https://files.pythonhosted.org/packages/dc/0a/c3cf2b4fef5f0426e8a6d7fce3cb966a17817c568ce59d76b92a233fdbec/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d", size = 20588, upload-time = "2025-09-27T18:37:36.096Z" }, { url = "https://files.pythonhosted.org/packages/cd/1b/a7782984844bd519ad4ffdbebbba2671ec5d0ebbeac34736c15fb86399e8/markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7", size = 14566, upload-time = "2025-09-27T18:37:37.09Z" }, { url = "https://files.pythonhosted.org/packages/18/1f/8d9c20e1c9440e215a44be5ab64359e207fcb4f675543f1cf9a2a7f648d0/markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e", size = 15053, upload-time = "2025-09-27T18:37:38.054Z" }, { url = "https://files.pythonhosted.org/packages/4e/d3/fe08482b5cd995033556d45041a4f4e76e7f0521112a9c9991d40d39825f/markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8", size = 13928, upload-time = "2025-09-27T18:37:39.037Z" }, ] [[package]] name = "matplotlib" version = "3.9.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "contourpy", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "cycler", marker = "python_full_version < '3.10'" }, { name = "fonttools", version = "4.60.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "importlib-resources", marker = "python_full_version < '3.10'" }, { name = "kiwisolver", version = "1.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "packaging", marker = "python_full_version < '3.10'" }, { name = "pillow", version = "11.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pyparsing", marker = "python_full_version < '3.10'" }, { name = "python-dateutil", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/df/17/1747b4154034befd0ed33b52538f5eb7752d05bb51c5e2a31470c3bc7d52/matplotlib-3.9.4.tar.gz", hash = "sha256:1e00e8be7393cbdc6fedfa8a6fba02cf3e83814b285db1c60b906a023ba41bc3", size = 36106529, upload-time = "2024-12-13T05:56:34.184Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/94/27d2e2c30d54b56c7b764acc1874a909e34d1965a427fc7092bb6a588b63/matplotlib-3.9.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c5fdd7abfb706dfa8d307af64a87f1a862879ec3cd8d0ec8637458f0885b9c50", size = 7885089, upload-time = "2024-12-13T05:54:24.224Z" }, { url = "https://files.pythonhosted.org/packages/c6/25/828273307e40a68eb8e9df832b6b2aaad075864fdc1de4b1b81e40b09e48/matplotlib-3.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d89bc4e85e40a71d1477780366c27fb7c6494d293e1617788986f74e2a03d7ff", size = 7770600, upload-time = "2024-12-13T05:54:27.214Z" }, { url = "https://files.pythonhosted.org/packages/f2/65/f841a422ec994da5123368d76b126acf4fc02ea7459b6e37c4891b555b83/matplotlib-3.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddf9f3c26aae695c5daafbf6b94e4c1a30d6cd617ba594bbbded3b33a1fcfa26", size = 8200138, upload-time = "2024-12-13T05:54:29.497Z" }, { url = "https://files.pythonhosted.org/packages/07/06/272aca07a38804d93b6050813de41ca7ab0e29ba7a9dd098e12037c919a9/matplotlib-3.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18ebcf248030173b59a868fda1fe42397253f6698995b55e81e1f57431d85e50", size = 8312711, upload-time = "2024-12-13T05:54:34.396Z" }, { url = "https://files.pythonhosted.org/packages/98/37/f13e23b233c526b7e27ad61be0a771894a079e0f7494a10d8d81557e0e9a/matplotlib-3.9.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:974896ec43c672ec23f3f8c648981e8bc880ee163146e0312a9b8def2fac66f5", size = 9090622, upload-time = "2024-12-13T05:54:36.808Z" }, { url = "https://files.pythonhosted.org/packages/4f/8c/b1f5bd2bd70e60f93b1b54c4d5ba7a992312021d0ddddf572f9a1a6d9348/matplotlib-3.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:4598c394ae9711cec135639374e70871fa36b56afae17bdf032a345be552a88d", size = 7828211, upload-time = "2024-12-13T05:54:40.596Z" }, { url = "https://files.pythonhosted.org/packages/74/4b/65be7959a8fa118a3929b49a842de5b78bb55475236fcf64f3e308ff74a0/matplotlib-3.9.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d4dd29641d9fb8bc4492420c5480398dd40a09afd73aebe4eb9d0071a05fbe0c", size = 7894430, upload-time = "2024-12-13T05:54:44.049Z" }, { url = "https://files.pythonhosted.org/packages/e9/18/80f70d91896e0a517b4a051c3fd540daa131630fd75e02e250365353b253/matplotlib-3.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30e5b22e8bcfb95442bf7d48b0d7f3bdf4a450cbf68986ea45fca3d11ae9d099", size = 7780045, upload-time = "2024-12-13T05:54:46.414Z" }, { url = "https://files.pythonhosted.org/packages/a2/73/ccb381026e3238c5c25c3609ba4157b2d1a617ec98d65a8b4ee4e1e74d02/matplotlib-3.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bb0030d1d447fd56dcc23b4c64a26e44e898f0416276cac1ebc25522e0ac249", size = 8209906, upload-time = "2024-12-13T05:54:49.459Z" }, { url = "https://files.pythonhosted.org/packages/ab/33/1648da77b74741c89f5ea95cbf42a291b4b364f2660b316318811404ed97/matplotlib-3.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aca90ed222ac3565d2752b83dbb27627480d27662671e4d39da72e97f657a423", size = 8322873, upload-time = "2024-12-13T05:54:53.066Z" }, { url = "https://files.pythonhosted.org/packages/57/d3/8447ba78bc6593c9044c372d1609f8ea10fb1e071e7a9e0747bea74fc16c/matplotlib-3.9.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a181b2aa2906c608fcae72f977a4a2d76e385578939891b91c2550c39ecf361e", size = 9099566, upload-time = "2024-12-13T05:54:55.522Z" }, { url = "https://files.pythonhosted.org/packages/23/e1/4f0e237bf349c02ff9d1b6e7109f1a17f745263809b9714a8576dc17752b/matplotlib-3.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:1f6882828231eca17f501c4dcd98a05abb3f03d157fbc0769c6911fe08b6cfd3", size = 7838065, upload-time = "2024-12-13T05:54:58.337Z" }, { url = "https://files.pythonhosted.org/packages/1a/2b/c918bf6c19d6445d1cefe3d2e42cb740fb997e14ab19d4daeb6a7ab8a157/matplotlib-3.9.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:dfc48d67e6661378a21c2983200a654b72b5c5cdbd5d2cf6e5e1ece860f0cc70", size = 7891131, upload-time = "2024-12-13T05:55:02.837Z" }, { url = "https://files.pythonhosted.org/packages/c1/e5/b4e8fc601ca302afeeabf45f30e706a445c7979a180e3a978b78b2b681a4/matplotlib-3.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47aef0fab8332d02d68e786eba8113ffd6f862182ea2999379dec9e237b7e483", size = 7776365, upload-time = "2024-12-13T05:55:05.158Z" }, { url = "https://files.pythonhosted.org/packages/99/06/b991886c506506476e5d83625c5970c656a491b9f80161458fed94597808/matplotlib-3.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fba1f52c6b7dc764097f52fd9ab627b90db452c9feb653a59945de16752e965f", size = 8200707, upload-time = "2024-12-13T05:55:09.48Z" }, { url = "https://files.pythonhosted.org/packages/c3/e2/556b627498cb27e61026f2d1ba86a78ad1b836fef0996bef5440e8bc9559/matplotlib-3.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:173ac3748acaac21afcc3fa1633924609ba1b87749006bc25051c52c422a5d00", size = 8313761, upload-time = "2024-12-13T05:55:12.95Z" }, { url = "https://files.pythonhosted.org/packages/58/ff/165af33ec766ff818306ea88e91f9f60d2a6ed543be1eb122a98acbf3b0d/matplotlib-3.9.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320edea0cadc07007765e33f878b13b3738ffa9745c5f707705692df70ffe0e0", size = 9095284, upload-time = "2024-12-13T05:55:16.199Z" }, { url = "https://files.pythonhosted.org/packages/9f/8b/3d0c7a002db3b1ed702731c2a9a06d78d035f1f2fb0fb936a8e43cc1e9f4/matplotlib-3.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a4a4cfc82330b27042a7169533da7991e8789d180dd5b3daeaee57d75cd5a03b", size = 7841160, upload-time = "2024-12-13T05:55:19.991Z" }, { url = "https://files.pythonhosted.org/packages/49/b1/999f89a7556d101b23a2f0b54f1b6e140d73f56804da1398f2f0bc0924bc/matplotlib-3.9.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:37eeffeeca3c940985b80f5b9a7b95ea35671e0e7405001f249848d2b62351b6", size = 7891499, upload-time = "2024-12-13T05:55:22.142Z" }, { url = "https://files.pythonhosted.org/packages/87/7b/06a32b13a684977653396a1bfcd34d4e7539c5d55c8cbfaa8ae04d47e4a9/matplotlib-3.9.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3e7465ac859ee4abcb0d836137cd8414e7bb7ad330d905abced457217d4f0f45", size = 7776802, upload-time = "2024-12-13T05:55:25.947Z" }, { url = "https://files.pythonhosted.org/packages/65/87/ac498451aff739e515891bbb92e566f3c7ef31891aaa878402a71f9b0910/matplotlib-3.9.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4c12302c34afa0cf061bea23b331e747e5e554b0fa595c96e01c7b75bc3b858", size = 8200802, upload-time = "2024-12-13T05:55:28.461Z" }, { url = "https://files.pythonhosted.org/packages/f8/6b/9eb761c00e1cb838f6c92e5f25dcda3f56a87a52f6cb8fdfa561e6cf6a13/matplotlib-3.9.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b8c97917f21b75e72108b97707ba3d48f171541a74aa2a56df7a40626bafc64", size = 8313880, upload-time = "2024-12-13T05:55:30.965Z" }, { url = "https://files.pythonhosted.org/packages/d7/a2/c8eaa600e2085eec7e38cbbcc58a30fc78f8224939d31d3152bdafc01fd1/matplotlib-3.9.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0229803bd7e19271b03cb09f27db76c918c467aa4ce2ae168171bc67c3f508df", size = 9094637, upload-time = "2024-12-13T05:55:33.701Z" }, { url = "https://files.pythonhosted.org/packages/71/1f/c6e1daea55b7bfeb3d84c6cb1abc449f6a02b181e7e2a5e4db34c3afb793/matplotlib-3.9.4-cp313-cp313-win_amd64.whl", hash = "sha256:7c0d8ef442ebf56ff5e206f8083d08252ee738e04f3dc88ea882853a05488799", size = 7841311, upload-time = "2024-12-13T05:55:36.737Z" }, { url = "https://files.pythonhosted.org/packages/c0/3a/2757d3f7d388b14dd48f5a83bea65b6d69f000e86b8f28f74d86e0d375bd/matplotlib-3.9.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a04c3b00066a688834356d196136349cb32f5e1003c55ac419e91585168b88fb", size = 7919989, upload-time = "2024-12-13T05:55:39.024Z" }, { url = "https://files.pythonhosted.org/packages/24/28/f5077c79a4f521589a37fe1062d6a6ea3534e068213f7357e7cfffc2e17a/matplotlib-3.9.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:04c519587f6c210626741a1e9a68eefc05966ede24205db8982841826af5871a", size = 7809417, upload-time = "2024-12-13T05:55:42.412Z" }, { url = "https://files.pythonhosted.org/packages/36/c8/c523fd2963156692916a8eb7d4069084cf729359f7955cf09075deddfeaf/matplotlib-3.9.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308afbf1a228b8b525fcd5cec17f246bbbb63b175a3ef6eb7b4d33287ca0cf0c", size = 8226258, upload-time = "2024-12-13T05:55:47.259Z" }, { url = "https://files.pythonhosted.org/packages/f6/88/499bf4b8fa9349b6f5c0cf4cead0ebe5da9d67769129f1b5651e5ac51fbc/matplotlib-3.9.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddb3b02246ddcffd3ce98e88fed5b238bc5faff10dbbaa42090ea13241d15764", size = 8335849, upload-time = "2024-12-13T05:55:49.763Z" }, { url = "https://files.pythonhosted.org/packages/b8/9f/20a4156b9726188646a030774ee337d5ff695a965be45ce4dbcb9312c170/matplotlib-3.9.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8a75287e9cb9eee48cb79ec1d806f75b29c0fde978cb7223a1f4c5848d696041", size = 9102152, upload-time = "2024-12-13T05:55:51.997Z" }, { url = "https://files.pythonhosted.org/packages/10/11/237f9c3a4e8d810b1759b67ff2da7c32c04f9c80aa475e7beb36ed43a8fb/matplotlib-3.9.4-cp313-cp313t-win_amd64.whl", hash = "sha256:488deb7af140f0ba86da003e66e10d55ff915e152c78b4b66d231638400b1965", size = 7896987, upload-time = "2024-12-13T05:55:55.941Z" }, { url = "https://files.pythonhosted.org/packages/56/eb/501b465c9fef28f158e414ea3a417913dc2ac748564c7ed41535f23445b4/matplotlib-3.9.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3c3724d89a387ddf78ff88d2a30ca78ac2b4c89cf37f2db4bd453c34799e933c", size = 7885919, upload-time = "2024-12-13T05:55:59.66Z" }, { url = "https://files.pythonhosted.org/packages/da/36/236fbd868b6c91309a5206bd90c3f881f4f44b2d997cd1d6239ef652f878/matplotlib-3.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d5f0a8430ffe23d7e32cfd86445864ccad141797f7d25b7c41759a5b5d17cfd7", size = 7771486, upload-time = "2024-12-13T05:56:04.264Z" }, { url = "https://files.pythonhosted.org/packages/e0/4b/105caf2d54d5ed11d9f4335398f5103001a03515f2126c936a752ccf1461/matplotlib-3.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bb0141a21aef3b64b633dc4d16cbd5fc538b727e4958be82a0e1c92a234160e", size = 8201838, upload-time = "2024-12-13T05:56:06.792Z" }, { url = "https://files.pythonhosted.org/packages/5d/a7/bb01188fb4013d34d274caf44a2f8091255b0497438e8b6c0a7c1710c692/matplotlib-3.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57aa235109e9eed52e2c2949db17da185383fa71083c00c6c143a60e07e0888c", size = 8314492, upload-time = "2024-12-13T05:56:09.964Z" }, { url = "https://files.pythonhosted.org/packages/33/19/02e1a37f7141fc605b193e927d0a9cdf9dc124a20b9e68793f4ffea19695/matplotlib-3.9.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b18c600061477ccfdd1e6fd050c33d8be82431700f3452b297a56d9ed7037abb", size = 9092500, upload-time = "2024-12-13T05:56:13.55Z" }, { url = "https://files.pythonhosted.org/packages/57/68/c2feb4667adbf882ffa4b3e0ac9967f848980d9f8b5bebd86644aa67ce6a/matplotlib-3.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:ef5f2d1b67d2d2145ff75e10f8c008bfbf71d45137c4b648c87193e7dd053eac", size = 7822962, upload-time = "2024-12-13T05:56:16.358Z" }, { url = "https://files.pythonhosted.org/packages/0c/22/2ef6a364cd3f565442b0b055e0599744f1e4314ec7326cdaaa48a4d864d7/matplotlib-3.9.4-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:44e0ed786d769d85bc787b0606a53f2d8d2d1d3c8a2608237365e9121c1a338c", size = 7877995, upload-time = "2024-12-13T05:56:18.805Z" }, { url = "https://files.pythonhosted.org/packages/87/b8/2737456e566e9f4d94ae76b8aa0d953d9acb847714f9a7ad80184474f5be/matplotlib-3.9.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:09debb9ce941eb23ecdbe7eab972b1c3e0276dcf01688073faff7b0f61d6c6ca", size = 7769300, upload-time = "2024-12-13T05:56:21.315Z" }, { url = "https://files.pythonhosted.org/packages/b2/1f/e709c6ec7b5321e6568769baa288c7178e60a93a9da9e682b39450da0e29/matplotlib-3.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc53cf157a657bfd03afab14774d54ba73aa84d42cfe2480c91bd94873952db", size = 8313423, upload-time = "2024-12-13T05:56:26.719Z" }, { url = "https://files.pythonhosted.org/packages/5e/b6/5a1f868782cd13f053a679984e222007ecff654a9bfbac6b27a65f4eeb05/matplotlib-3.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ad45da51be7ad02387801fd154ef74d942f49fe3fcd26a64c94842ba7ec0d865", size = 7854624, upload-time = "2024-12-13T05:56:29.359Z" }, ] [[package]] name = "matplotlib" version = "3.10.8" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "contourpy", version = "1.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "contourpy", version = "1.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "cycler", marker = "python_full_version >= '3.10'" }, { name = "fonttools", version = "4.61.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "kiwisolver", version = "1.4.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "packaging", marker = "python_full_version >= '3.10'" }, { name = "pillow", version = "12.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pyparsing", marker = "python_full_version >= '3.10'" }, { name = "python-dateutil", marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/8a/76/d3c6e3a13fe484ebe7718d14e269c9569c4eb0020a968a327acb3b9a8fe6/matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3", size = 34806269, upload-time = "2025-12-10T22:56:51.155Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/58/be/a30bd917018ad220c400169fba298f2bb7003c8ccbc0c3e24ae2aacad1e8/matplotlib-3.10.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:00270d217d6b20d14b584c521f810d60c5c78406dc289859776550df837dcda7", size = 8239828, upload-time = "2025-12-10T22:55:02.313Z" }, { url = "https://files.pythonhosted.org/packages/58/27/ca01e043c4841078e82cf6e80a6993dfecd315c3d79f5f3153afbb8e1ec6/matplotlib-3.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b3c1cc42aa184b3f738cfa18c1c1d72fd496d85467a6cf7b807936d39aa656", size = 8128050, upload-time = "2025-12-10T22:55:04.997Z" }, { url = "https://files.pythonhosted.org/packages/cb/aa/7ab67f2b729ae6a91bcf9dcac0affb95fb8c56f7fd2b2af894ae0b0cf6fa/matplotlib-3.10.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee40c27c795bda6a5292e9cff9890189d32f7e3a0bf04e0e3c9430c4a00c37df", size = 8700452, upload-time = "2025-12-10T22:55:07.47Z" }, { url = "https://files.pythonhosted.org/packages/73/ae/2d5817b0acee3c49b7e7ccfbf5b273f284957cc8e270adf36375db353190/matplotlib-3.10.8-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a48f2b74020919552ea25d222d5cc6af9ca3f4eb43a93e14d068457f545c2a17", size = 9534928, upload-time = "2025-12-10T22:55:10.566Z" }, { url = "https://files.pythonhosted.org/packages/c9/5b/8e66653e9f7c39cb2e5cab25fce4810daffa2bff02cbf5f3077cea9e942c/matplotlib-3.10.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f254d118d14a7f99d616271d6c3c27922c092dac11112670b157798b89bf4933", size = 9586377, upload-time = "2025-12-10T22:55:12.362Z" }, { url = "https://files.pythonhosted.org/packages/e2/e2/fd0bbadf837f81edb0d208ba8f8cb552874c3b16e27cb91a31977d90875d/matplotlib-3.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:f9b587c9c7274c1613a30afabf65a272114cd6cdbe67b3406f818c79d7ab2e2a", size = 8128127, upload-time = "2025-12-10T22:55:14.436Z" }, { url = "https://files.pythonhosted.org/packages/f8/86/de7e3a1cdcfc941483af70609edc06b83e7c8a0e0dc9ac325200a3f4d220/matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6be43b667360fef5c754dda5d25a32e6307a03c204f3c0fc5468b78fa87b4160", size = 8251215, upload-time = "2025-12-10T22:55:16.175Z" }, { url = "https://files.pythonhosted.org/packages/fd/14/baad3222f424b19ce6ad243c71de1ad9ec6b2e4eb1e458a48fdc6d120401/matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2b336e2d91a3d7006864e0990c83b216fcdca64b5a6484912902cef87313d78", size = 8139625, upload-time = "2025-12-10T22:55:17.712Z" }, { url = "https://files.pythonhosted.org/packages/8f/a0/7024215e95d456de5883e6732e708d8187d9753a21d32f8ddb3befc0c445/matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efb30e3baaea72ce5928e32bab719ab4770099079d66726a62b11b1ef7273be4", size = 8712614, upload-time = "2025-12-10T22:55:20.8Z" }, { url = "https://files.pythonhosted.org/packages/5a/f4/b8347351da9a5b3f41e26cf547252d861f685c6867d179a7c9d60ad50189/matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d56a1efd5bfd61486c8bc968fa18734464556f0fb8e51690f4ac25d85cbbbbc2", size = 9540997, upload-time = "2025-12-10T22:55:23.258Z" }, { url = "https://files.pythonhosted.org/packages/9e/c0/c7b914e297efe0bc36917bf216b2acb91044b91e930e878ae12981e461e5/matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238b7ce5717600615c895050239ec955d91f321c209dd110db988500558e70d6", size = 9596825, upload-time = "2025-12-10T22:55:25.217Z" }, { url = "https://files.pythonhosted.org/packages/6f/d3/a4bbc01c237ab710a1f22b4da72f4ff6d77eb4c7735ea9811a94ae239067/matplotlib-3.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:18821ace09c763ec93aef5eeff087ee493a24051936d7b9ebcad9662f66501f9", size = 8135090, upload-time = "2025-12-10T22:55:27.162Z" }, { url = "https://files.pythonhosted.org/packages/89/dd/a0b6588f102beab33ca6f5218b31725216577b2a24172f327eaf6417d5c9/matplotlib-3.10.8-cp311-cp311-win_arm64.whl", hash = "sha256:bab485bcf8b1c7d2060b4fcb6fc368a9e6f4cd754c9c2fea281f4be21df394a2", size = 8012377, upload-time = "2025-12-10T22:55:29.185Z" }, { url = "https://files.pythonhosted.org/packages/9e/67/f997cdcbb514012eb0d10cd2b4b332667997fb5ebe26b8d41d04962fa0e6/matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:64fcc24778ca0404ce0cb7b6b77ae1f4c7231cdd60e6778f999ee05cbd581b9a", size = 8260453, upload-time = "2025-12-10T22:55:30.709Z" }, { url = "https://files.pythonhosted.org/packages/7e/65/07d5f5c7f7c994f12c768708bd2e17a4f01a2b0f44a1c9eccad872433e2e/matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9a5ca4ac220a0cdd1ba6bcba3608547117d30468fefce49bb26f55c1a3d5c58", size = 8148321, upload-time = "2025-12-10T22:55:33.265Z" }, { url = "https://files.pythonhosted.org/packages/3e/f3/c5195b1ae57ef85339fd7285dfb603b22c8b4e79114bae5f4f0fcf688677/matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ab4aabc72de4ff77b3ec33a6d78a68227bf1123465887f9905ba79184a1cc04", size = 8716944, upload-time = "2025-12-10T22:55:34.922Z" }, { url = "https://files.pythonhosted.org/packages/00/f9/7638f5cc82ec8a7aa005de48622eecc3ed7c9854b96ba15bd76b7fd27574/matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24d50994d8c5816ddc35411e50a86ab05f575e2530c02752e02538122613371f", size = 9550099, upload-time = "2025-12-10T22:55:36.789Z" }, { url = "https://files.pythonhosted.org/packages/57/61/78cd5920d35b29fd2a0fe894de8adf672ff52939d2e9b43cb83cd5ce1bc7/matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99eefd13c0dc3b3c1b4d561c1169e65fe47aab7b8158754d7c084088e2329466", size = 9613040, upload-time = "2025-12-10T22:55:38.715Z" }, { url = "https://files.pythonhosted.org/packages/30/4e/c10f171b6e2f44d9e3a2b96efa38b1677439d79c99357600a62cc1e9594e/matplotlib-3.10.8-cp312-cp312-win_amd64.whl", hash = "sha256:dd80ecb295460a5d9d260df63c43f4afbdd832d725a531f008dad1664f458adf", size = 8142717, upload-time = "2025-12-10T22:55:41.103Z" }, { url = "https://files.pythonhosted.org/packages/f1/76/934db220026b5fef85f45d51a738b91dea7d70207581063cd9bd8fafcf74/matplotlib-3.10.8-cp312-cp312-win_arm64.whl", hash = "sha256:3c624e43ed56313651bc18a47f838b60d7b8032ed348911c54906b130b20071b", size = 8012751, upload-time = "2025-12-10T22:55:42.684Z" }, { url = "https://files.pythonhosted.org/packages/3d/b9/15fd5541ef4f5b9a17eefd379356cf12175fe577424e7b1d80676516031a/matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6", size = 8261076, upload-time = "2025-12-10T22:55:44.648Z" }, { url = "https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1", size = 8148794, upload-time = "2025-12-10T22:55:46.252Z" }, { url = "https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486", size = 8718474, upload-time = "2025-12-10T22:55:47.864Z" }, { url = "https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce", size = 9549637, upload-time = "2025-12-10T22:55:50.048Z" }, { url = "https://files.pythonhosted.org/packages/5d/7c/8dc289776eae5109e268c4fb92baf870678dc048a25d4ac903683b86d5bf/matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6", size = 9613678, upload-time = "2025-12-10T22:55:52.21Z" }, { url = "https://files.pythonhosted.org/packages/64/40/37612487cc8a437d4dd261b32ca21fe2d79510fe74af74e1f42becb1bdb8/matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149", size = 8142686, upload-time = "2025-12-10T22:55:54.253Z" }, { url = "https://files.pythonhosted.org/packages/66/52/8d8a8730e968185514680c2a6625943f70269509c3dcfc0dcf7d75928cb8/matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645", size = 8012917, upload-time = "2025-12-10T22:55:56.268Z" }, { url = "https://files.pythonhosted.org/packages/b5/27/51fe26e1062f298af5ef66343d8ef460e090a27fea73036c76c35821df04/matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077", size = 8305679, upload-time = "2025-12-10T22:55:57.856Z" }, { url = "https://files.pythonhosted.org/packages/2c/1e/4de865bc591ac8e3062e835f42dd7fe7a93168d519557837f0e37513f629/matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22", size = 8198336, upload-time = "2025-12-10T22:55:59.371Z" }, { url = "https://files.pythonhosted.org/packages/c6/cb/2f7b6e75fb4dce87ef91f60cac4f6e34f4c145ab036a22318ec837971300/matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39", size = 8731653, upload-time = "2025-12-10T22:56:01.032Z" }, { url = "https://files.pythonhosted.org/packages/46/b3/bd9c57d6ba670a37ab31fb87ec3e8691b947134b201f881665b28cc039ff/matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565", size = 9561356, upload-time = "2025-12-10T22:56:02.95Z" }, { url = "https://files.pythonhosted.org/packages/c0/3d/8b94a481456dfc9dfe6e39e93b5ab376e50998cddfd23f4ae3b431708f16/matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a", size = 9614000, upload-time = "2025-12-10T22:56:05.411Z" }, { url = "https://files.pythonhosted.org/packages/bd/cd/bc06149fe5585ba800b189a6a654a75f1f127e8aab02fd2be10df7fa500c/matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958", size = 8220043, upload-time = "2025-12-10T22:56:07.551Z" }, { url = "https://files.pythonhosted.org/packages/e3/de/b22cf255abec916562cc04eef457c13e58a1990048de0c0c3604d082355e/matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5", size = 8062075, upload-time = "2025-12-10T22:56:09.178Z" }, { url = "https://files.pythonhosted.org/packages/3c/43/9c0ff7a2f11615e516c3b058e1e6e8f9614ddeca53faca06da267c48345d/matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f", size = 8262481, upload-time = "2025-12-10T22:56:10.885Z" }, { url = "https://files.pythonhosted.org/packages/6f/ca/e8ae28649fcdf039fda5ef554b40a95f50592a3c47e6f7270c9561c12b07/matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b", size = 8151473, upload-time = "2025-12-10T22:56:12.377Z" }, { url = "https://files.pythonhosted.org/packages/f1/6f/009d129ae70b75e88cbe7e503a12a4c0670e08ed748a902c2568909e9eb5/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d", size = 9553896, upload-time = "2025-12-10T22:56:14.432Z" }, { url = "https://files.pythonhosted.org/packages/f5/26/4221a741eb97967bc1fd5e4c52b9aa5a91b2f4ec05b59f6def4d820f9df9/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008", size = 9824193, upload-time = "2025-12-10T22:56:16.29Z" }, { url = "https://files.pythonhosted.org/packages/1f/f3/3abf75f38605772cf48a9daf5821cd4f563472f38b4b828c6fba6fa6d06e/matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c", size = 9615444, upload-time = "2025-12-10T22:56:18.155Z" }, { url = "https://files.pythonhosted.org/packages/93/a5/de89ac80f10b8dc615807ee1133cd99ac74082581196d4d9590bea10690d/matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11", size = 8272719, upload-time = "2025-12-10T22:56:20.366Z" }, { url = "https://files.pythonhosted.org/packages/69/ce/b006495c19ccc0a137b48083168a37bd056392dee02f87dba0472f2797fe/matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8", size = 8144205, upload-time = "2025-12-10T22:56:22.239Z" }, { url = "https://files.pythonhosted.org/packages/68/d9/b31116a3a855bd313c6fcdb7226926d59b041f26061c6c5b1be66a08c826/matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50", size = 8305785, upload-time = "2025-12-10T22:56:24.218Z" }, { url = "https://files.pythonhosted.org/packages/1e/90/6effe8103f0272685767ba5f094f453784057072f49b393e3ea178fe70a5/matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908", size = 8198361, upload-time = "2025-12-10T22:56:26.787Z" }, { url = "https://files.pythonhosted.org/packages/d7/65/a73188711bea603615fc0baecca1061429ac16940e2385433cc778a9d8e7/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a", size = 9561357, upload-time = "2025-12-10T22:56:28.953Z" }, { url = "https://files.pythonhosted.org/packages/f4/3d/b5c5d5d5be8ce63292567f0e2c43dde9953d3ed86ac2de0a72e93c8f07a1/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1", size = 9823610, upload-time = "2025-12-10T22:56:31.455Z" }, { url = "https://files.pythonhosted.org/packages/4d/4b/e7beb6bbd49f6bae727a12b270a2654d13c397576d25bd6786e47033300f/matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c", size = 9614011, upload-time = "2025-12-10T22:56:33.85Z" }, { url = "https://files.pythonhosted.org/packages/7c/e6/76f2813d31f032e65f6f797e3f2f6e4aab95b65015924b1c51370395c28a/matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b", size = 8362801, upload-time = "2025-12-10T22:56:36.107Z" }, { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, { url = "https://files.pythonhosted.org/packages/f5/43/31d59500bb950b0d188e149a2e552040528c13d6e3d6e84d0cccac593dcd/matplotlib-3.10.8-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f97aeb209c3d2511443f8797e3e5a569aebb040d4f8bc79aa3ee78a8fb9e3dd8", size = 8237252, upload-time = "2025-12-10T22:56:39.529Z" }, { url = "https://files.pythonhosted.org/packages/0c/2c/615c09984f3c5f907f51c886538ad785cf72e0e11a3225de2c0f9442aecc/matplotlib-3.10.8-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fb061f596dad3a0f52b60dc6a5dec4a0c300dec41e058a7efe09256188d170b7", size = 8124693, upload-time = "2025-12-10T22:56:41.758Z" }, { url = "https://files.pythonhosted.org/packages/91/e1/2757277a1c56041e1fc104b51a0f7b9a4afc8eb737865d63cababe30bc61/matplotlib-3.10.8-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12d90df9183093fcd479f4172ac26b322b1248b15729cb57f42f71f24c7e37a3", size = 8702205, upload-time = "2025-12-10T22:56:43.415Z" }, { url = "https://files.pythonhosted.org/packages/04/30/3afaa31c757f34b7725ab9d2ba8b48b5e89c2019c003e7d0ead143aabc5a/matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1", size = 8249198, upload-time = "2025-12-10T22:56:45.584Z" }, { url = "https://files.pythonhosted.org/packages/48/2f/6334aec331f57485a642a7c8be03cb286f29111ae71c46c38b363230063c/matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a", size = 8136817, upload-time = "2025-12-10T22:56:47.339Z" }, { url = "https://files.pythonhosted.org/packages/73/e4/6d6f14b2a759c622f191b2d67e9075a3f56aaccb3be4bb9bb6890030d0a0/matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2", size = 8713867, upload-time = "2025-12-10T22:56:48.954Z" }, ] [[package]] name = "mccabe" version = "0.7.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, ] [[package]] name = "mdit-py-plugins" version = "0.4.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542, upload-time = "2024-09-09T20:27:49.564Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316, upload-time = "2024-09-09T20:27:48.397Z" }, ] [[package]] name = "mdit-py-plugins" version = "0.5.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b2/fd/a756d36c0bfba5f6e39a1cdbdbfdd448dc02692467d83816dff4592a1ebc/mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6", size = 44655, upload-time = "2025-08-11T07:25:49.083Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f", size = 57205, upload-time = "2025-08-11T07:25:47.597Z" }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] [[package]] name = "more-itertools" version = "10.8.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, ] [[package]] name = "mypy" version = "1.19.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, { name = "mypy-extensions" }, { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/2f/63/e499890d8e39b1ff2df4c0c6ce5d371b6844ee22b8250687a99fd2f657a8/mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", size = 13101333, upload-time = "2025-12-15T05:03:03.28Z" }, { url = "https://files.pythonhosted.org/packages/72/4b/095626fc136fba96effc4fd4a82b41d688ab92124f8c4f7564bffe5cf1b0/mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", size = 12164102, upload-time = "2025-12-15T05:02:33.611Z" }, { url = "https://files.pythonhosted.org/packages/0c/5b/952928dd081bf88a83a5ccd49aaecfcd18fd0d2710c7ff07b8fb6f7032b9/mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", size = 12765799, upload-time = "2025-12-15T05:03:28.44Z" }, { url = "https://files.pythonhosted.org/packages/2a/0d/93c2e4a287f74ef11a66fb6d49c7a9f05e47b0a4399040e6719b57f500d2/mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", size = 13522149, upload-time = "2025-12-15T05:02:36.011Z" }, { url = "https://files.pythonhosted.org/packages/7b/0e/33a294b56aaad2b338d203e3a1d8b453637ac36cb278b45005e0901cf148/mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", size = 13810105, upload-time = "2025-12-15T05:02:40.327Z" }, { url = "https://files.pythonhosted.org/packages/0e/fd/3e82603a0cb66b67c5e7abababce6bf1a929ddf67bf445e652684af5c5a0/mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", size = 10057200, upload-time = "2025-12-15T05:02:51.012Z" }, { url = "https://files.pythonhosted.org/packages/ef/47/6b3ebabd5474d9cdc170d1342fbf9dddc1b0ec13ec90bf9004ee6f391c31/mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", size = 13028539, upload-time = "2025-12-15T05:03:44.129Z" }, { url = "https://files.pythonhosted.org/packages/5c/a6/ac7c7a88a3c9c54334f53a941b765e6ec6c4ebd65d3fe8cdcfbe0d0fd7db/mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", size = 12083163, upload-time = "2025-12-15T05:03:37.679Z" }, { url = "https://files.pythonhosted.org/packages/67/af/3afa9cf880aa4a2c803798ac24f1d11ef72a0c8079689fac5cfd815e2830/mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", size = 12687629, upload-time = "2025-12-15T05:02:31.526Z" }, { url = "https://files.pythonhosted.org/packages/2d/46/20f8a7114a56484ab268b0ab372461cb3a8f7deed31ea96b83a4e4cfcfca/mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331", size = 13436933, upload-time = "2025-12-15T05:03:15.606Z" }, { url = "https://files.pythonhosted.org/packages/5b/f8/33b291ea85050a21f15da910002460f1f445f8007adb29230f0adea279cb/mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925", size = 13661754, upload-time = "2025-12-15T05:02:26.731Z" }, { url = "https://files.pythonhosted.org/packages/fd/a3/47cbd4e85bec4335a9cd80cf67dbc02be21b5d4c9c23ad6b95d6c5196bac/mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042", size = 10055772, upload-time = "2025-12-15T05:03:26.179Z" }, { url = "https://files.pythonhosted.org/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" }, { url = "https://files.pythonhosted.org/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" }, { url = "https://files.pythonhosted.org/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" }, { url = "https://files.pythonhosted.org/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" }, { url = "https://files.pythonhosted.org/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" }, { url = "https://files.pythonhosted.org/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" }, { url = "https://files.pythonhosted.org/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" }, { url = "https://files.pythonhosted.org/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" }, { url = "https://files.pythonhosted.org/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" }, { url = "https://files.pythonhosted.org/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" }, { url = "https://files.pythonhosted.org/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" }, { url = "https://files.pythonhosted.org/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" }, { url = "https://files.pythonhosted.org/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", size = 13199744, upload-time = "2025-12-15T05:03:30.823Z" }, { url = "https://files.pythonhosted.org/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", size = 12215815, upload-time = "2025-12-15T05:02:42.323Z" }, { url = "https://files.pythonhosted.org/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", size = 12740047, upload-time = "2025-12-15T05:03:33.168Z" }, { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, { url = "https://files.pythonhosted.org/packages/b5/f7/88436084550ca9af5e610fa45286be04c3b63374df3e021c762fe8c4369f/mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3", size = 13102606, upload-time = "2025-12-15T05:02:46.833Z" }, { url = "https://files.pythonhosted.org/packages/ca/a5/43dfad311a734b48a752790571fd9e12d61893849a01bff346a54011957f/mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a", size = 12164496, upload-time = "2025-12-15T05:03:41.947Z" }, { url = "https://files.pythonhosted.org/packages/88/f0/efbfa391395cce2f2771f937e0620cfd185ec88f2b9cd88711028a768e96/mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67", size = 12772068, upload-time = "2025-12-15T05:02:53.689Z" }, { url = "https://files.pythonhosted.org/packages/25/05/58b3ba28f5aed10479e899a12d2120d582ba9fa6288851b20bf1c32cbb4f/mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e", size = 13520385, upload-time = "2025-12-15T05:02:38.328Z" }, { url = "https://files.pythonhosted.org/packages/c5/a0/c006ccaff50b31e542ae69b92fe7e2f55d99fba3a55e01067dd564325f85/mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376", size = 13796221, upload-time = "2025-12-15T05:03:22.147Z" }, { url = "https://files.pythonhosted.org/packages/b2/ff/8bdb051cd710f01b880472241bd36b3f817a8e1c5d5540d0b761675b6de2/mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24", size = 10055456, upload-time = "2025-12-15T05:03:35.169Z" }, { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, ] [[package]] name = "mypy-extensions" version = "1.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] [[package]] name = "myst-parser" version = "3.0.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "jinja2", marker = "python_full_version < '3.10'" }, { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "mdit-py-plugins", version = "0.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pyyaml", marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/49/64/e2f13dac02f599980798c01156393b781aec983b52a6e4057ee58f07c43a/myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87", size = 92392, upload-time = "2024-04-28T20:22:42.116Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e2/de/21aa8394f16add8f7427f0a1326ccd2b3a2a8a3245c9252bc5ac034c6155/myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1", size = 83163, upload-time = "2024-04-28T20:22:39.985Z" }, ] [[package]] name = "myst-parser" version = "4.0.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", ] dependencies = [ { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "jinja2", marker = "python_full_version == '3.10.*'" }, { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "mdit-py-plugins", version = "0.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "pyyaml", marker = "python_full_version == '3.10.*'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/66/a5/9626ba4f73555b3735ad86247a8077d4603aa8628537687c839ab08bfe44/myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4", size = 93985, upload-time = "2025-02-12T10:53:03.833Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579, upload-time = "2025-02-12T10:53:02.078Z" }, ] [[package]] name = "myst-parser" version = "5.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "jinja2", marker = "python_full_version >= '3.11'" }, { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "mdit-py-plugins", version = "0.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pyyaml", marker = "python_full_version >= '3.11'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/fa/7b45eef11b7971f0beb29d27b7bfe0d747d063aa29e170d9edd004733c8a/myst_parser-5.0.0.tar.gz", hash = "sha256:f6f231452c56e8baa662cc352c548158f6a16fcbd6e3800fc594978002b94f3a", size = 98535, upload-time = "2026-01-15T09:08:18.036Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d3/ac/686789b9145413f1a61878c407210e41bfdb097976864e0913078b24098c/myst_parser-5.0.0-py3-none-any.whl", hash = "sha256:ab31e516024918296e169139072b81592336f2fef55b8986aa31c9f04b5f7211", size = 84533, upload-time = "2026-01-15T09:08:16.788Z" }, ] [[package]] name = "narwhals" version = "2.16.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/fc/6f/713be67779028d482c6e0f2dde5bc430021b2578a4808c1c9f6d7ad48257/narwhals-2.16.0.tar.gz", hash = "sha256:155bb45132b370941ba0396d123cf9ed192bf25f39c4cea726f2da422ca4e145", size = 618268, upload-time = "2026-02-02T10:31:00.545Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/03/cc/7cb74758e6df95e0c4e1253f203b6dd7f348bf2f29cf89e9210a2416d535/narwhals-2.16.0-py3-none-any.whl", hash = "sha256:846f1fd7093ac69d63526e50732033e86c30ea0026a44d9b23991010c7d1485d", size = 443951, upload-time = "2026-02-02T10:30:58.635Z" }, ] [[package]] name = "natsort" version = "8.4.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575, upload-time = "2023-06-20T04:17:19.925Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268, upload-time = "2023-06-20T04:17:17.522Z" }, ] [[package]] name = "nest-asyncio" version = "1.6.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, ] [[package]] name = "nh3" version = "0.3.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ca/a5/34c26015d3a434409f4d2a1cd8821a06c05238703f49283ffeb937bef093/nh3-0.3.2.tar.gz", hash = "sha256:f394759a06df8b685a4ebfb1874fb67a9cbfd58c64fc5ed587a663c0e63ec376", size = 19288, upload-time = "2025-10-30T11:17:45.948Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5b/01/a1eda067c0ba823e5e2bb033864ae4854549e49fb6f3407d2da949106bfb/nh3-0.3.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d18957a90806d943d141cc5e4a0fefa1d77cf0d7a156878bf9a66eed52c9cc7d", size = 1419839, upload-time = "2025-10-30T11:17:09.956Z" }, { url = "https://files.pythonhosted.org/packages/30/57/07826ff65d59e7e9cc789ef1dc405f660cabd7458a1864ab58aefa17411b/nh3-0.3.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45c953e57028c31d473d6b648552d9cab1efe20a42ad139d78e11d8f42a36130", size = 791183, upload-time = "2025-10-30T11:17:11.99Z" }, { url = "https://files.pythonhosted.org/packages/af/2f/e8a86f861ad83f3bb5455f596d5c802e34fcdb8c53a489083a70fd301333/nh3-0.3.2-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c9850041b77a9147d6bbd6dbbf13eeec7009eb60b44e83f07fcb2910075bf9b", size = 829127, upload-time = "2025-10-30T11:17:13.192Z" }, { url = "https://files.pythonhosted.org/packages/d8/97/77aef4daf0479754e8e90c7f8f48f3b7b8725a3b8c0df45f2258017a6895/nh3-0.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:403c11563e50b915d0efdb622866d1d9e4506bce590ef7da57789bf71dd148b5", size = 997131, upload-time = "2025-10-30T11:17:14.677Z" }, { url = "https://files.pythonhosted.org/packages/41/ee/fd8140e4df9d52143e89951dd0d797f5546004c6043285289fbbe3112293/nh3-0.3.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:0dca4365db62b2d71ff1620ee4f800c4729849906c5dd504ee1a7b2389558e31", size = 1068783, upload-time = "2025-10-30T11:17:15.861Z" }, { url = "https://files.pythonhosted.org/packages/87/64/bdd9631779e2d588b08391f7555828f352e7f6427889daf2fa424bfc90c9/nh3-0.3.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0fe7ee035dd7b2290715baf29cb27167dddd2ff70ea7d052c958dbd80d323c99", size = 994732, upload-time = "2025-10-30T11:17:17.155Z" }, { url = "https://files.pythonhosted.org/packages/79/66/90190033654f1f28ca98e3d76b8be1194505583f9426b0dcde782a3970a2/nh3-0.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a40202fd58e49129764f025bbaae77028e420f1d5b3c8e6f6fd3a6490d513868", size = 975997, upload-time = "2025-10-30T11:17:18.77Z" }, { url = "https://files.pythonhosted.org/packages/34/30/ebf8e2e8d71fdb5a5d5d8836207177aed1682df819cbde7f42f16898946c/nh3-0.3.2-cp314-cp314t-win32.whl", hash = "sha256:1f9ba555a797dbdcd844b89523f29cdc90973d8bd2e836ea6b962cf567cadd93", size = 583364, upload-time = "2025-10-30T11:17:20.286Z" }, { url = "https://files.pythonhosted.org/packages/94/ae/95c52b5a75da429f11ca8902c2128f64daafdc77758d370e4cc310ecda55/nh3-0.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:dce4248edc427c9b79261f3e6e2b3ecbdd9b88c267012168b4a7b3fc6fd41d13", size = 589982, upload-time = "2025-10-30T11:17:21.384Z" }, { url = "https://files.pythonhosted.org/packages/b4/bd/c7d862a4381b95f2469704de32c0ad419def0f4a84b7a138a79532238114/nh3-0.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:019ecbd007536b67fdf76fab411b648fb64e2257ca3262ec80c3425c24028c80", size = 577126, upload-time = "2025-10-30T11:17:22.755Z" }, { url = "https://files.pythonhosted.org/packages/b6/3e/f5a5cc2885c24be13e9b937441bd16a012ac34a657fe05e58927e8af8b7a/nh3-0.3.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7064ccf5ace75825bd7bf57859daaaf16ed28660c1c6b306b649a9eda4b54b1e", size = 1431980, upload-time = "2025-10-30T11:17:25.457Z" }, { url = "https://files.pythonhosted.org/packages/7f/f7/529a99324d7ef055de88b690858f4189379708abae92ace799365a797b7f/nh3-0.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8745454cdd28bbbc90861b80a0111a195b0e3961b9fa2e672be89eb199fa5d8", size = 820805, upload-time = "2025-10-30T11:17:26.98Z" }, { url = "https://files.pythonhosted.org/packages/3d/62/19b7c50ccd1fa7d0764822d2cea8f2a320f2fd77474c7a1805cb22cf69b0/nh3-0.3.2-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72d67c25a84579f4a432c065e8b4274e53b7cf1df8f792cf846abfe2c3090866", size = 803527, upload-time = "2025-10-30T11:17:28.284Z" }, { url = "https://files.pythonhosted.org/packages/4a/ca/f022273bab5440abff6302731a49410c5ef66b1a9502ba3fbb2df998d9ff/nh3-0.3.2-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:13398e676a14d6233f372c75f52d5ae74f98210172991f7a3142a736bd92b131", size = 1051674, upload-time = "2025-10-30T11:17:29.909Z" }, { url = "https://files.pythonhosted.org/packages/fa/f7/5728e3b32a11daf5bd21cf71d91c463f74305938bc3eb9e0ac1ce141646e/nh3-0.3.2-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03d617e5c8aa7331bd2659c654e021caf9bba704b109e7b2b28b039a00949fe5", size = 1004737, upload-time = "2025-10-30T11:17:31.205Z" }, { url = "https://files.pythonhosted.org/packages/53/7f/f17e0dba0a99cee29e6cee6d4d52340ef9cb1f8a06946d3a01eb7ec2fb01/nh3-0.3.2-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2f55c4d2d5a207e74eefe4d828067bbb01300e06e2a7436142f915c5928de07", size = 911745, upload-time = "2025-10-30T11:17:32.945Z" }, { url = "https://files.pythonhosted.org/packages/42/0f/c76bf3dba22c73c38e9b1113b017cf163f7696f50e003404ec5ecdb1e8a6/nh3-0.3.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb18403f02b655a1bbe4e3a4696c2ae1d6ae8f5991f7cacb684b1ae27e6c9f7", size = 797184, upload-time = "2025-10-30T11:17:34.226Z" }, { url = "https://files.pythonhosted.org/packages/08/a1/73d8250f888fb0ddf1b119b139c382f8903d8bb0c5bd1f64afc7e38dad1d/nh3-0.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d66f41672eb4060cf87c037f760bdbc6847852ca9ef8e9c5a5da18f090abf87", size = 838556, upload-time = "2025-10-30T11:17:35.875Z" }, { url = "https://files.pythonhosted.org/packages/d1/09/deb57f1fb656a7a5192497f4a287b0ade5a2ff6b5d5de4736d13ef6d2c1f/nh3-0.3.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f97f8b25cb2681d25e2338148159447e4d689aafdccfcf19e61ff7db3905768a", size = 1006695, upload-time = "2025-10-30T11:17:37.071Z" }, { url = "https://files.pythonhosted.org/packages/b6/61/8f4d41c4ccdac30e4b1a4fa7be4b0f9914d8314a5058472f84c8e101a418/nh3-0.3.2-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:2ab70e8c6c7d2ce953d2a58102eefa90c2d0a5ed7aa40c7e29a487bc5e613131", size = 1075471, upload-time = "2025-10-30T11:17:38.225Z" }, { url = "https://files.pythonhosted.org/packages/b0/c6/966aec0cb4705e69f6c3580422c239205d5d4d0e50fac380b21e87b6cf1b/nh3-0.3.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:1710f3901cd6440ca92494ba2eb6dc260f829fa8d9196b659fa10de825610ce0", size = 1002439, upload-time = "2025-10-30T11:17:39.553Z" }, { url = "https://files.pythonhosted.org/packages/e2/c8/97a2d5f7a314cce2c5c49f30c6f161b7f3617960ade4bfc2fd1ee092cb20/nh3-0.3.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:91e9b001101fb4500a2aafe3e7c92928d85242d38bf5ac0aba0b7480da0a4cd6", size = 987439, upload-time = "2025-10-30T11:17:40.81Z" }, { url = "https://files.pythonhosted.org/packages/0d/95/2d6fc6461687d7a171f087995247dec33e8749a562bfadd85fb5dbf37a11/nh3-0.3.2-cp38-abi3-win32.whl", hash = "sha256:169db03df90da63286e0560ea0efa9b6f3b59844a9735514a1d47e6bb2c8c61b", size = 589826, upload-time = "2025-10-30T11:17:42.239Z" }, { url = "https://files.pythonhosted.org/packages/64/9a/1a1c154f10a575d20dd634e5697805e589bbdb7673a0ad00e8da90044ba7/nh3-0.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:562da3dca7a17f9077593214a9781a94b8d76de4f158f8c895e62f09573945fe", size = 596406, upload-time = "2025-10-30T11:17:43.773Z" }, { url = "https://files.pythonhosted.org/packages/9e/7e/a96255f63b7aef032cbee8fc4d6e37def72e3aaedc1f72759235e8f13cb1/nh3-0.3.2-cp38-abi3-win_arm64.whl", hash = "sha256:cf5964d54edd405e68583114a7cba929468bcd7db5e676ae38ee954de1cfc104", size = 584162, upload-time = "2025-10-30T11:17:44.96Z" }, ] [[package]] name = "numpy" version = "2.0.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/a9/75/10dd1f8116a8b796cb2c737b674e02d02e80454bda953fa7e65d8c12b016/numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78", size = 18902015, upload-time = "2024-08-26T20:19:40.945Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/21/91/3495b3237510f79f5d81f2508f9f13fea78ebfdf07538fc7444badda173d/numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece", size = 21165245, upload-time = "2024-08-26T20:04:14.625Z" }, { url = "https://files.pythonhosted.org/packages/05/33/26178c7d437a87082d11019292dce6d3fe6f0e9026b7b2309cbf3e489b1d/numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04", size = 13738540, upload-time = "2024-08-26T20:04:36.784Z" }, { url = "https://files.pythonhosted.org/packages/ec/31/cc46e13bf07644efc7a4bf68df2df5fb2a1a88d0cd0da9ddc84dc0033e51/numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66", size = 5300623, upload-time = "2024-08-26T20:04:46.491Z" }, { url = "https://files.pythonhosted.org/packages/6e/16/7bfcebf27bb4f9d7ec67332ffebee4d1bf085c84246552d52dbb548600e7/numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b", size = 6901774, upload-time = "2024-08-26T20:04:58.173Z" }, { url = "https://files.pythonhosted.org/packages/f9/a3/561c531c0e8bf082c5bef509d00d56f82e0ea7e1e3e3a7fc8fa78742a6e5/numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd", size = 13907081, upload-time = "2024-08-26T20:05:19.098Z" }, { url = "https://files.pythonhosted.org/packages/fa/66/f7177ab331876200ac7563a580140643d1179c8b4b6a6b0fc9838de2a9b8/numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318", size = 19523451, upload-time = "2024-08-26T20:05:47.479Z" }, { url = "https://files.pythonhosted.org/packages/25/7f/0b209498009ad6453e4efc2c65bcdf0ae08a182b2b7877d7ab38a92dc542/numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8", size = 19927572, upload-time = "2024-08-26T20:06:17.137Z" }, { url = "https://files.pythonhosted.org/packages/3e/df/2619393b1e1b565cd2d4c4403bdd979621e2c4dea1f8532754b2598ed63b/numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326", size = 14400722, upload-time = "2024-08-26T20:06:39.16Z" }, { url = "https://files.pythonhosted.org/packages/22/ad/77e921b9f256d5da36424ffb711ae79ca3f451ff8489eeca544d0701d74a/numpy-2.0.2-cp310-cp310-win32.whl", hash = "sha256:984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97", size = 6472170, upload-time = "2024-08-26T20:06:50.361Z" }, { url = "https://files.pythonhosted.org/packages/10/05/3442317535028bc29cf0c0dd4c191a4481e8376e9f0db6bcf29703cadae6/numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131", size = 15905558, upload-time = "2024-08-26T20:07:13.881Z" }, { url = "https://files.pythonhosted.org/packages/8b/cf/034500fb83041aa0286e0fb16e7c76e5c8b67c0711bb6e9e9737a717d5fe/numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448", size = 21169137, upload-time = "2024-08-26T20:07:45.345Z" }, { url = "https://files.pythonhosted.org/packages/4a/d9/32de45561811a4b87fbdee23b5797394e3d1504b4a7cf40c10199848893e/numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195", size = 13703552, upload-time = "2024-08-26T20:08:06.666Z" }, { url = "https://files.pythonhosted.org/packages/c1/ca/2f384720020c7b244d22508cb7ab23d95f179fcfff33c31a6eeba8d6c512/numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57", size = 5298957, upload-time = "2024-08-26T20:08:15.83Z" }, { url = "https://files.pythonhosted.org/packages/0e/78/a3e4f9fb6aa4e6fdca0c5428e8ba039408514388cf62d89651aade838269/numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a", size = 6905573, upload-time = "2024-08-26T20:08:27.185Z" }, { url = "https://files.pythonhosted.org/packages/a0/72/cfc3a1beb2caf4efc9d0b38a15fe34025230da27e1c08cc2eb9bfb1c7231/numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669", size = 13914330, upload-time = "2024-08-26T20:08:48.058Z" }, { url = "https://files.pythonhosted.org/packages/ba/a8/c17acf65a931ce551fee11b72e8de63bf7e8a6f0e21add4c937c83563538/numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951", size = 19534895, upload-time = "2024-08-26T20:09:16.536Z" }, { url = "https://files.pythonhosted.org/packages/ba/86/8767f3d54f6ae0165749f84648da9dcc8cd78ab65d415494962c86fac80f/numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9", size = 19937253, upload-time = "2024-08-26T20:09:46.263Z" }, { url = "https://files.pythonhosted.org/packages/df/87/f76450e6e1c14e5bb1eae6836478b1028e096fd02e85c1c37674606ab752/numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15", size = 14414074, upload-time = "2024-08-26T20:10:08.483Z" }, { url = "https://files.pythonhosted.org/packages/5c/ca/0f0f328e1e59f73754f06e1adfb909de43726d4f24c6a3f8805f34f2b0fa/numpy-2.0.2-cp311-cp311-win32.whl", hash = "sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4", size = 6470640, upload-time = "2024-08-26T20:10:19.732Z" }, { url = "https://files.pythonhosted.org/packages/eb/57/3a3f14d3a759dcf9bf6e9eda905794726b758819df4663f217d658a58695/numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc", size = 15910230, upload-time = "2024-08-26T20:10:43.413Z" }, { url = "https://files.pythonhosted.org/packages/45/40/2e117be60ec50d98fa08c2f8c48e09b3edea93cfcabd5a9ff6925d54b1c2/numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b", size = 20895803, upload-time = "2024-08-26T20:11:13.916Z" }, { url = "https://files.pythonhosted.org/packages/46/92/1b8b8dee833f53cef3e0a3f69b2374467789e0bb7399689582314df02651/numpy-2.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8df823f570d9adf0978347d1f926b2a867d5608f434a7cff7f7908c6570dcf5e", size = 13471835, upload-time = "2024-08-26T20:11:34.779Z" }, { url = "https://files.pythonhosted.org/packages/7f/19/e2793bde475f1edaea6945be141aef6c8b4c669b90c90a300a8954d08f0a/numpy-2.0.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9a92ae5c14811e390f3767053ff54eaee3bf84576d99a2456391401323f4ec2c", size = 5038499, upload-time = "2024-08-26T20:11:43.902Z" }, { url = "https://files.pythonhosted.org/packages/e3/ff/ddf6dac2ff0dd50a7327bcdba45cb0264d0e96bb44d33324853f781a8f3c/numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c", size = 6633497, upload-time = "2024-08-26T20:11:55.09Z" }, { url = "https://files.pythonhosted.org/packages/72/21/67f36eac8e2d2cd652a2e69595a54128297cdcb1ff3931cfc87838874bd4/numpy-2.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05e238064fc0610c840d1cf6a13bf63d7e391717d247f1bf0318172e759e692", size = 13621158, upload-time = "2024-08-26T20:12:14.95Z" }, { url = "https://files.pythonhosted.org/packages/39/68/e9f1126d757653496dbc096cb429014347a36b228f5a991dae2c6b6cfd40/numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a", size = 19236173, upload-time = "2024-08-26T20:12:44.049Z" }, { url = "https://files.pythonhosted.org/packages/d1/e9/1f5333281e4ebf483ba1c888b1d61ba7e78d7e910fdd8e6499667041cc35/numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c", size = 19634174, upload-time = "2024-08-26T20:13:13.634Z" }, { url = "https://files.pythonhosted.org/packages/71/af/a469674070c8d8408384e3012e064299f7a2de540738a8e414dcfd639996/numpy-2.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec9852fb39354b5a45a80bdab5ac02dd02b15f44b3804e9f00c556bf24b4bded", size = 14099701, upload-time = "2024-08-26T20:13:34.851Z" }, { url = "https://files.pythonhosted.org/packages/d0/3d/08ea9f239d0e0e939b6ca52ad403c84a2bce1bde301a8eb4888c1c1543f1/numpy-2.0.2-cp312-cp312-win32.whl", hash = "sha256:671bec6496f83202ed2d3c8fdc486a8fc86942f2e69ff0e986140339a63bcbe5", size = 6174313, upload-time = "2024-08-26T20:13:45.653Z" }, { url = "https://files.pythonhosted.org/packages/b2/b5/4ac39baebf1fdb2e72585c8352c56d063b6126be9fc95bd2bb5ef5770c20/numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a", size = 15606179, upload-time = "2024-08-26T20:14:08.786Z" }, { url = "https://files.pythonhosted.org/packages/43/c1/41c8f6df3162b0c6ffd4437d729115704bd43363de0090c7f913cfbc2d89/numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c", size = 21169942, upload-time = "2024-08-26T20:14:40.108Z" }, { url = "https://files.pythonhosted.org/packages/39/bc/fd298f308dcd232b56a4031fd6ddf11c43f9917fbc937e53762f7b5a3bb1/numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd", size = 13711512, upload-time = "2024-08-26T20:15:00.985Z" }, { url = "https://files.pythonhosted.org/packages/96/ff/06d1aa3eeb1c614eda245c1ba4fb88c483bee6520d361641331872ac4b82/numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b", size = 5306976, upload-time = "2024-08-26T20:15:10.876Z" }, { url = "https://files.pythonhosted.org/packages/2d/98/121996dcfb10a6087a05e54453e28e58694a7db62c5a5a29cee14c6e047b/numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729", size = 6906494, upload-time = "2024-08-26T20:15:22.055Z" }, { url = "https://files.pythonhosted.org/packages/15/31/9dffc70da6b9bbf7968f6551967fc21156207366272c2a40b4ed6008dc9b/numpy-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e795a8be3ddbac43274f18588329c72939870a16cae810c2b73461c40718ab1", size = 13912596, upload-time = "2024-08-26T20:15:42.452Z" }, { url = "https://files.pythonhosted.org/packages/b9/14/78635daab4b07c0930c919d451b8bf8c164774e6a3413aed04a6d95758ce/numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd", size = 19526099, upload-time = "2024-08-26T20:16:11.048Z" }, { url = "https://files.pythonhosted.org/packages/26/4c/0eeca4614003077f68bfe7aac8b7496f04221865b3a5e7cb230c9d055afd/numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d", size = 19932823, upload-time = "2024-08-26T20:16:40.171Z" }, { url = "https://files.pythonhosted.org/packages/f1/46/ea25b98b13dccaebddf1a803f8c748680d972e00507cd9bc6dcdb5aa2ac1/numpy-2.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9189427407d88ff25ecf8f12469d4d39d35bee1db5d39fc5c168c6f088a6956d", size = 14404424, upload-time = "2024-08-26T20:17:02.604Z" }, { url = "https://files.pythonhosted.org/packages/c8/a6/177dd88d95ecf07e722d21008b1b40e681a929eb9e329684d449c36586b2/numpy-2.0.2-cp39-cp39-win32.whl", hash = "sha256:905d16e0c60200656500c95b6b8dca5d109e23cb24abc701d41c02d74c6b3afa", size = 6476809, upload-time = "2024-08-26T20:17:13.553Z" }, { url = "https://files.pythonhosted.org/packages/ea/2b/7fc9f4e7ae5b507c1a3a21f0f15ed03e794c1242ea8a242ac158beb56034/numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73", size = 15911314, upload-time = "2024-08-26T20:17:36.72Z" }, { url = "https://files.pythonhosted.org/packages/8f/3b/df5a870ac6a3be3a86856ce195ef42eec7ae50d2a202be1f5a4b3b340e14/numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8", size = 21025288, upload-time = "2024-08-26T20:18:07.732Z" }, { url = "https://files.pythonhosted.org/packages/2c/97/51af92f18d6f6f2d9ad8b482a99fb74e142d71372da5d834b3a2747a446e/numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4", size = 6762793, upload-time = "2024-08-26T20:18:19.125Z" }, { url = "https://files.pythonhosted.org/packages/12/46/de1fbd0c1b5ccaa7f9a005b66761533e2f6a3e560096682683a223631fe9/numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c", size = 19334885, upload-time = "2024-08-26T20:18:47.237Z" }, { url = "https://files.pythonhosted.org/packages/cc/dc/d330a6faefd92b446ec0f0dfea4c3207bb1fef3c4771d19cf4543efd2c78/numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385", size = 15828784, upload-time = "2024-08-26T20:19:11.19Z" }, ] [[package]] name = "numpy" version = "2.2.6" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" }, { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" }, { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" }, { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" }, { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" }, { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" }, { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" }, { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" }, { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" }, { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" }, { url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" }, { url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" }, { url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" }, { url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" }, { url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" }, { url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" }, { url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" }, { url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" }, { url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" }, { url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" }, { url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" }, { url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" }, { url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" }, { url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" }, { url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" }, { url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" }, { url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" }, { url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" }, { url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" }, { url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" }, { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" }, { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" }, { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" }, { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" }, ] [[package]] name = "numpy" version = "2.4.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] sdist = { url = "https://files.pythonhosted.org/packages/57/fd/0005efbd0af48e55eb3c7208af93f2862d4b1a56cd78e84309a2d959208d/numpy-2.4.2.tar.gz", hash = "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae", size = 20723651, upload-time = "2026-01-31T23:13:10.135Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d3/44/71852273146957899753e69986246d6a176061ea183407e95418c2aa4d9a/numpy-2.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825", size = 16955478, upload-time = "2026-01-31T23:10:25.623Z" }, { url = "https://files.pythonhosted.org/packages/74/41/5d17d4058bd0cd96bcbd4d9ff0fb2e21f52702aab9a72e4a594efa18692f/numpy-2.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1", size = 14965467, upload-time = "2026-01-31T23:10:28.186Z" }, { url = "https://files.pythonhosted.org/packages/49/48/fb1ce8136c19452ed15f033f8aee91d5defe515094e330ce368a0647846f/numpy-2.4.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7", size = 5475172, upload-time = "2026-01-31T23:10:30.848Z" }, { url = "https://files.pythonhosted.org/packages/40/a9/3feb49f17bbd1300dd2570432961f5c8a4ffeff1db6f02c7273bd020a4c9/numpy-2.4.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73", size = 6805145, upload-time = "2026-01-31T23:10:32.352Z" }, { url = "https://files.pythonhosted.org/packages/3f/39/fdf35cbd6d6e2fcad42fcf85ac04a85a0d0fbfbf34b30721c98d602fd70a/numpy-2.4.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1", size = 15966084, upload-time = "2026-01-31T23:10:34.502Z" }, { url = "https://files.pythonhosted.org/packages/1b/46/6fa4ea94f1ddf969b2ee941290cca6f1bfac92b53c76ae5f44afe17ceb69/numpy-2.4.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32", size = 16899477, upload-time = "2026-01-31T23:10:37.075Z" }, { url = "https://files.pythonhosted.org/packages/09/a1/2a424e162b1a14a5bd860a464ab4e07513916a64ab1683fae262f735ccd2/numpy-2.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390", size = 17323429, upload-time = "2026-01-31T23:10:39.704Z" }, { url = "https://files.pythonhosted.org/packages/ce/a2/73014149ff250628df72c58204822ac01d768697913881aacf839ff78680/numpy-2.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413", size = 18635109, upload-time = "2026-01-31T23:10:41.924Z" }, { url = "https://files.pythonhosted.org/packages/6c/0c/73e8be2f1accd56df74abc1c5e18527822067dced5ec0861b5bb882c2ce0/numpy-2.4.2-cp311-cp311-win32.whl", hash = "sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda", size = 6237915, upload-time = "2026-01-31T23:10:45.26Z" }, { url = "https://files.pythonhosted.org/packages/76/ae/e0265e0163cf127c24c3969d29f1c4c64551a1e375d95a13d32eab25d364/numpy-2.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695", size = 12607972, upload-time = "2026-01-31T23:10:47.021Z" }, { url = "https://files.pythonhosted.org/packages/29/a5/c43029af9b8014d6ea157f192652c50042e8911f4300f8f6ed3336bf437f/numpy-2.4.2-cp311-cp311-win_arm64.whl", hash = "sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3", size = 10485763, upload-time = "2026-01-31T23:10:50.087Z" }, { url = "https://files.pythonhosted.org/packages/51/6e/6f394c9c77668153e14d4da83bcc247beb5952f6ead7699a1a2992613bea/numpy-2.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a", size = 16667963, upload-time = "2026-01-31T23:10:52.147Z" }, { url = "https://files.pythonhosted.org/packages/1f/f8/55483431f2b2fd015ae6ed4fe62288823ce908437ed49db5a03d15151678/numpy-2.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1", size = 14693571, upload-time = "2026-01-31T23:10:54.789Z" }, { url = "https://files.pythonhosted.org/packages/2f/20/18026832b1845cdc82248208dd929ca14c9d8f2bac391f67440707fff27c/numpy-2.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e", size = 5203469, upload-time = "2026-01-31T23:10:57.343Z" }, { url = "https://files.pythonhosted.org/packages/7d/33/2eb97c8a77daaba34eaa3fa7241a14ac5f51c46a6bd5911361b644c4a1e2/numpy-2.4.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27", size = 6550820, upload-time = "2026-01-31T23:10:59.429Z" }, { url = "https://files.pythonhosted.org/packages/b1/91/b97fdfd12dc75b02c44e26c6638241cc004d4079a0321a69c62f51470c4c/numpy-2.4.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548", size = 15663067, upload-time = "2026-01-31T23:11:01.291Z" }, { url = "https://files.pythonhosted.org/packages/f5/c6/a18e59f3f0b8071cc85cbc8d80cd02d68aa9710170b2553a117203d46936/numpy-2.4.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f", size = 16619782, upload-time = "2026-01-31T23:11:03.669Z" }, { url = "https://files.pythonhosted.org/packages/b7/83/9751502164601a79e18847309f5ceec0b1446d7b6aa12305759b72cf98b2/numpy-2.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460", size = 17013128, upload-time = "2026-01-31T23:11:05.913Z" }, { url = "https://files.pythonhosted.org/packages/61/c4/c4066322256ec740acc1c8923a10047818691d2f8aec254798f3dd90f5f2/numpy-2.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba", size = 18345324, upload-time = "2026-01-31T23:11:08.248Z" }, { url = "https://files.pythonhosted.org/packages/ab/af/6157aa6da728fa4525a755bfad486ae7e3f76d4c1864138003eb84328497/numpy-2.4.2-cp312-cp312-win32.whl", hash = "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f", size = 5960282, upload-time = "2026-01-31T23:11:10.497Z" }, { url = "https://files.pythonhosted.org/packages/92/0f/7ceaaeaacb40567071e94dbf2c9480c0ae453d5bb4f52bea3892c39dc83c/numpy-2.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85", size = 12314210, upload-time = "2026-01-31T23:11:12.176Z" }, { url = "https://files.pythonhosted.org/packages/2f/a3/56c5c604fae6dd40fa2ed3040d005fca97e91bd320d232ac9931d77ba13c/numpy-2.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa", size = 10220171, upload-time = "2026-01-31T23:11:14.684Z" }, { url = "https://files.pythonhosted.org/packages/a1/22/815b9fe25d1d7ae7d492152adbc7226d3eff731dffc38fe970589fcaaa38/numpy-2.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c", size = 16663696, upload-time = "2026-01-31T23:11:17.516Z" }, { url = "https://files.pythonhosted.org/packages/09/f0/817d03a03f93ba9c6c8993de509277d84e69f9453601915e4a69554102a1/numpy-2.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979", size = 14688322, upload-time = "2026-01-31T23:11:19.883Z" }, { url = "https://files.pythonhosted.org/packages/da/b4/f805ab79293c728b9a99438775ce51885fd4f31b76178767cfc718701a39/numpy-2.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98", size = 5198157, upload-time = "2026-01-31T23:11:22.375Z" }, { url = "https://files.pythonhosted.org/packages/74/09/826e4289844eccdcd64aac27d13b0fd3f32039915dd5b9ba01baae1f436c/numpy-2.4.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef", size = 6546330, upload-time = "2026-01-31T23:11:23.958Z" }, { url = "https://files.pythonhosted.org/packages/19/fb/cbfdbfa3057a10aea5422c558ac57538e6acc87ec1669e666d32ac198da7/numpy-2.4.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7", size = 15660968, upload-time = "2026-01-31T23:11:25.713Z" }, { url = "https://files.pythonhosted.org/packages/04/dc/46066ce18d01645541f0186877377b9371b8fa8017fa8262002b4ef22612/numpy-2.4.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499", size = 16607311, upload-time = "2026-01-31T23:11:28.117Z" }, { url = "https://files.pythonhosted.org/packages/14/d9/4b5adfc39a43fa6bf918c6d544bc60c05236cc2f6339847fc5b35e6cb5b0/numpy-2.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb", size = 17012850, upload-time = "2026-01-31T23:11:30.888Z" }, { url = "https://files.pythonhosted.org/packages/b7/20/adb6e6adde6d0130046e6fdfb7675cc62bc2f6b7b02239a09eb58435753d/numpy-2.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7", size = 18334210, upload-time = "2026-01-31T23:11:33.214Z" }, { url = "https://files.pythonhosted.org/packages/78/0e/0a73b3dff26803a8c02baa76398015ea2a5434d9b8265a7898a6028c1591/numpy-2.4.2-cp313-cp313-win32.whl", hash = "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110", size = 5958199, upload-time = "2026-01-31T23:11:35.385Z" }, { url = "https://files.pythonhosted.org/packages/43/bc/6352f343522fcb2c04dbaf94cb30cca6fd32c1a750c06ad6231b4293708c/numpy-2.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622", size = 12310848, upload-time = "2026-01-31T23:11:38.001Z" }, { url = "https://files.pythonhosted.org/packages/6e/8d/6da186483e308da5da1cc6918ce913dcfe14ffde98e710bfeff2a6158d4e/numpy-2.4.2-cp313-cp313-win_arm64.whl", hash = "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71", size = 10221082, upload-time = "2026-01-31T23:11:40.392Z" }, { url = "https://files.pythonhosted.org/packages/25/a1/9510aa43555b44781968935c7548a8926274f815de42ad3997e9e83680dd/numpy-2.4.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262", size = 14815866, upload-time = "2026-01-31T23:11:42.495Z" }, { url = "https://files.pythonhosted.org/packages/36/30/6bbb5e76631a5ae46e7923dd16ca9d3f1c93cfa8d4ed79a129814a9d8db3/numpy-2.4.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913", size = 5325631, upload-time = "2026-01-31T23:11:44.7Z" }, { url = "https://files.pythonhosted.org/packages/46/00/3a490938800c1923b567b3a15cd17896e68052e2145d8662aaf3e1ffc58f/numpy-2.4.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab", size = 6646254, upload-time = "2026-01-31T23:11:46.341Z" }, { url = "https://files.pythonhosted.org/packages/d3/e9/fac0890149898a9b609caa5af7455a948b544746e4b8fe7c212c8edd71f8/numpy-2.4.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82", size = 15720138, upload-time = "2026-01-31T23:11:48.082Z" }, { url = "https://files.pythonhosted.org/packages/ea/5c/08887c54e68e1e28df53709f1893ce92932cc6f01f7c3d4dc952f61ffd4e/numpy-2.4.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f", size = 16655398, upload-time = "2026-01-31T23:11:50.293Z" }, { url = "https://files.pythonhosted.org/packages/4d/89/253db0fa0e66e9129c745e4ef25631dc37d5f1314dad2b53e907b8538e6d/numpy-2.4.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554", size = 17079064, upload-time = "2026-01-31T23:11:52.927Z" }, { url = "https://files.pythonhosted.org/packages/2a/d5/cbade46ce97c59c6c3da525e8d95b7abe8a42974a1dc5c1d489c10433e88/numpy-2.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257", size = 18379680, upload-time = "2026-01-31T23:11:55.22Z" }, { url = "https://files.pythonhosted.org/packages/40/62/48f99ae172a4b63d981babe683685030e8a3df4f246c893ea5c6ef99f018/numpy-2.4.2-cp313-cp313t-win32.whl", hash = "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657", size = 6082433, upload-time = "2026-01-31T23:11:58.096Z" }, { url = "https://files.pythonhosted.org/packages/07/38/e054a61cfe48ad9f1ed0d188e78b7e26859d0b60ef21cd9de4897cdb5326/numpy-2.4.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b", size = 12451181, upload-time = "2026-01-31T23:11:59.782Z" }, { url = "https://files.pythonhosted.org/packages/6e/a4/a05c3a6418575e185dd84d0b9680b6bb2e2dc3e4202f036b7b4e22d6e9dc/numpy-2.4.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1", size = 10290756, upload-time = "2026-01-31T23:12:02.438Z" }, { url = "https://files.pythonhosted.org/packages/18/88/b7df6050bf18fdcfb7046286c6535cabbdd2064a3440fca3f069d319c16e/numpy-2.4.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b", size = 16663092, upload-time = "2026-01-31T23:12:04.521Z" }, { url = "https://files.pythonhosted.org/packages/25/7a/1fee4329abc705a469a4afe6e69b1ef7e915117747886327104a8493a955/numpy-2.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000", size = 14698770, upload-time = "2026-01-31T23:12:06.96Z" }, { url = "https://files.pythonhosted.org/packages/fb/0b/f9e49ba6c923678ad5bc38181c08ac5e53b7a5754dbca8e581aa1a56b1ff/numpy-2.4.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1", size = 5208562, upload-time = "2026-01-31T23:12:09.632Z" }, { url = "https://files.pythonhosted.org/packages/7d/12/d7de8f6f53f9bb76997e5e4c069eda2051e3fe134e9181671c4391677bb2/numpy-2.4.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74", size = 6543710, upload-time = "2026-01-31T23:12:11.969Z" }, { url = "https://files.pythonhosted.org/packages/09/63/c66418c2e0268a31a4cf8a8b512685748200f8e8e8ec6c507ce14e773529/numpy-2.4.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a", size = 15677205, upload-time = "2026-01-31T23:12:14.33Z" }, { url = "https://files.pythonhosted.org/packages/5d/6c/7f237821c9642fb2a04d2f1e88b4295677144ca93285fd76eff3bcba858d/numpy-2.4.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325", size = 16611738, upload-time = "2026-01-31T23:12:16.525Z" }, { url = "https://files.pythonhosted.org/packages/c2/a7/39c4cdda9f019b609b5c473899d87abff092fc908cfe4d1ecb2fcff453b0/numpy-2.4.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909", size = 17028888, upload-time = "2026-01-31T23:12:19.306Z" }, { url = "https://files.pythonhosted.org/packages/da/b3/e84bb64bdfea967cc10950d71090ec2d84b49bc691df0025dddb7c26e8e3/numpy-2.4.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a", size = 18339556, upload-time = "2026-01-31T23:12:21.816Z" }, { url = "https://files.pythonhosted.org/packages/88/f5/954a291bc1192a27081706862ac62bb5920fbecfbaa302f64682aa90beed/numpy-2.4.2-cp314-cp314-win32.whl", hash = "sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a", size = 6006899, upload-time = "2026-01-31T23:12:24.14Z" }, { url = "https://files.pythonhosted.org/packages/05/cb/eff72a91b2efdd1bc98b3b8759f6a1654aa87612fc86e3d87d6fe4f948c4/numpy-2.4.2-cp314-cp314-win_amd64.whl", hash = "sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75", size = 12443072, upload-time = "2026-01-31T23:12:26.33Z" }, { url = "https://files.pythonhosted.org/packages/37/75/62726948db36a56428fce4ba80a115716dc4fad6a3a4352487f8bb950966/numpy-2.4.2-cp314-cp314-win_arm64.whl", hash = "sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05", size = 10494886, upload-time = "2026-01-31T23:12:28.488Z" }, { url = "https://files.pythonhosted.org/packages/36/2f/ee93744f1e0661dc267e4b21940870cabfae187c092e1433b77b09b50ac4/numpy-2.4.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308", size = 14818567, upload-time = "2026-01-31T23:12:30.709Z" }, { url = "https://files.pythonhosted.org/packages/a7/24/6535212add7d76ff938d8bdc654f53f88d35cddedf807a599e180dcb8e66/numpy-2.4.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef", size = 5328372, upload-time = "2026-01-31T23:12:32.962Z" }, { url = "https://files.pythonhosted.org/packages/5e/9d/c48f0a035725f925634bf6b8994253b43f2047f6778a54147d7e213bc5a7/numpy-2.4.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d", size = 6649306, upload-time = "2026-01-31T23:12:34.797Z" }, { url = "https://files.pythonhosted.org/packages/81/05/7c73a9574cd4a53a25907bad38b59ac83919c0ddc8234ec157f344d57d9a/numpy-2.4.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8", size = 15722394, upload-time = "2026-01-31T23:12:36.565Z" }, { url = "https://files.pythonhosted.org/packages/35/fa/4de10089f21fc7d18442c4a767ab156b25c2a6eaf187c0db6d9ecdaeb43f/numpy-2.4.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5", size = 16653343, upload-time = "2026-01-31T23:12:39.188Z" }, { url = "https://files.pythonhosted.org/packages/b8/f9/d33e4ffc857f3763a57aa85650f2e82486832d7492280ac21ba9efda80da/numpy-2.4.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e", size = 17078045, upload-time = "2026-01-31T23:12:42.041Z" }, { url = "https://files.pythonhosted.org/packages/c8/b8/54bdb43b6225badbea6389fa038c4ef868c44f5890f95dd530a218706da3/numpy-2.4.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a", size = 18380024, upload-time = "2026-01-31T23:12:44.331Z" }, { url = "https://files.pythonhosted.org/packages/a5/55/6e1a61ded7af8df04016d81b5b02daa59f2ea9252ee0397cb9f631efe9e5/numpy-2.4.2-cp314-cp314t-win32.whl", hash = "sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443", size = 6153937, upload-time = "2026-01-31T23:12:47.229Z" }, { url = "https://files.pythonhosted.org/packages/45/aa/fa6118d1ed6d776b0983f3ceac9b1a5558e80df9365b1c3aa6d42bf9eee4/numpy-2.4.2-cp314-cp314t-win_amd64.whl", hash = "sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236", size = 12631844, upload-time = "2026-01-31T23:12:48.997Z" }, { url = "https://files.pythonhosted.org/packages/32/0a/2ec5deea6dcd158f254a7b372fb09cfba5719419c8d66343bab35237b3fb/numpy-2.4.2-cp314-cp314t-win_arm64.whl", hash = "sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181", size = 10565379, upload-time = "2026-01-31T23:12:51.345Z" }, { url = "https://files.pythonhosted.org/packages/f4/f8/50e14d36d915ef64d8f8bc4a087fc8264d82c785eda6711f80ab7e620335/numpy-2.4.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082", size = 16833179, upload-time = "2026-01-31T23:12:53.5Z" }, { url = "https://files.pythonhosted.org/packages/17/17/809b5cad63812058a8189e91a1e2d55a5a18fd04611dbad244e8aeae465c/numpy-2.4.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a", size = 14889755, upload-time = "2026-01-31T23:12:55.933Z" }, { url = "https://files.pythonhosted.org/packages/3e/ea/181b9bcf7627fc8371720316c24db888dcb9829b1c0270abf3d288b2e29b/numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920", size = 5399500, upload-time = "2026-01-31T23:12:58.671Z" }, { url = "https://files.pythonhosted.org/packages/33/9f/413adf3fc955541ff5536b78fcf0754680b3c6d95103230252a2c9408d23/numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821", size = 6714252, upload-time = "2026-01-31T23:13:00.518Z" }, { url = "https://files.pythonhosted.org/packages/91/da/643aad274e29ccbdf42ecd94dafe524b81c87bcb56b83872d54827f10543/numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb", size = 15797142, upload-time = "2026-01-31T23:13:02.219Z" }, { url = "https://files.pythonhosted.org/packages/66/27/965b8525e9cb5dc16481b30a1b3c21e50c7ebf6e9dbd48d0c4d0d5089c7e/numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0", size = 16727979, upload-time = "2026-01-31T23:13:04.62Z" }, { url = "https://files.pythonhosted.org/packages/de/e5/b7d20451657664b07986c2f6e3be564433f5dcaf3482d68eaecd79afaf03/numpy-2.4.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0", size = 12502577, upload-time = "2026-01-31T23:13:07.08Z" }, ] [[package]] name = "packaging" version = "26.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, ] [[package]] name = "pandas" version = "2.3.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", "python_full_version < '3.10'", ] dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "python-dateutil", marker = "python_full_version < '3.11'" }, { name = "pytz", marker = "python_full_version < '3.11'" }, { name = "tzdata", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c", size = 11555763, upload-time = "2025-09-29T23:16:53.287Z" }, { url = "https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a", size = 10801217, upload-time = "2025-09-29T23:17:04.522Z" }, { url = "https://files.pythonhosted.org/packages/1d/03/3fc4a529a7710f890a239cc496fc6d50ad4a0995657dccc1d64695adb9f4/pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1", size = 12148791, upload-time = "2025-09-29T23:17:18.444Z" }, { url = "https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838", size = 12769373, upload-time = "2025-09-29T23:17:35.846Z" }, { url = "https://files.pythonhosted.org/packages/df/91/82cc5169b6b25440a7fc0ef3a694582418d875c8e3ebf796a6d6470aa578/pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250", size = 13200444, upload-time = "2025-09-29T23:17:49.341Z" }, { url = "https://files.pythonhosted.org/packages/10/ae/89b3283800ab58f7af2952704078555fa60c807fff764395bb57ea0b0dbd/pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4", size = 13858459, upload-time = "2025-09-29T23:18:03.722Z" }, { url = "https://files.pythonhosted.org/packages/85/72/530900610650f54a35a19476eca5104f38555afccda1aa11a92ee14cb21d/pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826", size = 11346086, upload-time = "2025-09-29T23:18:18.505Z" }, { url = "https://files.pythonhosted.org/packages/c1/fa/7ac648108144a095b4fb6aa3de1954689f7af60a14cf25583f4960ecb878/pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523", size = 11578790, upload-time = "2025-09-29T23:18:30.065Z" }, { url = "https://files.pythonhosted.org/packages/9b/35/74442388c6cf008882d4d4bdfc4109be87e9b8b7ccd097ad1e7f006e2e95/pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45", size = 10833831, upload-time = "2025-09-29T23:38:56.071Z" }, { url = "https://files.pythonhosted.org/packages/fe/e4/de154cbfeee13383ad58d23017da99390b91d73f8c11856f2095e813201b/pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66", size = 12199267, upload-time = "2025-09-29T23:18:41.627Z" }, { url = "https://files.pythonhosted.org/packages/bf/c9/63f8d545568d9ab91476b1818b4741f521646cbdd151c6efebf40d6de6f7/pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b", size = 12789281, upload-time = "2025-09-29T23:18:56.834Z" }, { url = "https://files.pythonhosted.org/packages/f2/00/a5ac8c7a0e67fd1a6059e40aa08fa1c52cc00709077d2300e210c3ce0322/pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791", size = 13240453, upload-time = "2025-09-29T23:19:09.247Z" }, { url = "https://files.pythonhosted.org/packages/27/4d/5c23a5bc7bd209231618dd9e606ce076272c9bc4f12023a70e03a86b4067/pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151", size = 13890361, upload-time = "2025-09-29T23:19:25.342Z" }, { url = "https://files.pythonhosted.org/packages/8e/59/712db1d7040520de7a4965df15b774348980e6df45c129b8c64d0dbe74ef/pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c", size = 11348702, upload-time = "2025-09-29T23:19:38.296Z" }, { url = "https://files.pythonhosted.org/packages/9c/fb/231d89e8637c808b997d172b18e9d4a4bc7bf31296196c260526055d1ea0/pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", size = 11597846, upload-time = "2025-09-29T23:19:48.856Z" }, { url = "https://files.pythonhosted.org/packages/5c/bd/bf8064d9cfa214294356c2d6702b716d3cf3bb24be59287a6a21e24cae6b/pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", size = 10729618, upload-time = "2025-09-29T23:39:08.659Z" }, { url = "https://files.pythonhosted.org/packages/57/56/cf2dbe1a3f5271370669475ead12ce77c61726ffd19a35546e31aa8edf4e/pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", size = 11737212, upload-time = "2025-09-29T23:19:59.765Z" }, { url = "https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", size = 12362693, upload-time = "2025-09-29T23:20:14.098Z" }, { url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" }, { url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" }, { url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" }, { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, { url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" }, { url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" }, { url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" }, { url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" }, { url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" }, { url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" }, { url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" }, { url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" }, { url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" }, { url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" }, { url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" }, { url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" }, { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, { url = "https://files.pythonhosted.org/packages/56/b4/52eeb530a99e2a4c55ffcd352772b599ed4473a0f892d127f4147cf0f88e/pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2", size = 11567720, upload-time = "2025-09-29T23:33:06.209Z" }, { url = "https://files.pythonhosted.org/packages/48/4a/2d8b67632a021bced649ba940455ed441ca854e57d6e7658a6024587b083/pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8", size = 10810302, upload-time = "2025-09-29T23:33:35.846Z" }, { url = "https://files.pythonhosted.org/packages/13/e6/d2465010ee0569a245c975dc6967b801887068bc893e908239b1f4b6c1ac/pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff", size = 12154874, upload-time = "2025-09-29T23:33:49.939Z" }, { url = "https://files.pythonhosted.org/packages/1f/18/aae8c0aa69a386a3255940e9317f793808ea79d0a525a97a903366bb2569/pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29", size = 12790141, upload-time = "2025-09-29T23:34:05.655Z" }, { url = "https://files.pythonhosted.org/packages/f7/26/617f98de789de00c2a444fbe6301bb19e66556ac78cff933d2c98f62f2b4/pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73", size = 13208697, upload-time = "2025-09-29T23:34:21.835Z" }, { url = "https://files.pythonhosted.org/packages/b9/fb/25709afa4552042bd0e15717c75e9b4a2294c3dc4f7e6ea50f03c5136600/pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9", size = 13879233, upload-time = "2025-09-29T23:34:35.079Z" }, { url = "https://files.pythonhosted.org/packages/98/af/7be05277859a7bc399da8ba68b88c96b27b48740b6cf49688899c6eb4176/pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa", size = 11359119, upload-time = "2025-09-29T23:34:46.339Z" }, ] [[package]] name = "pandas" version = "3.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "python-dateutil", marker = "python_full_version >= '3.11'" }, { name = "tzdata", marker = "(python_full_version >= '3.11' and sys_platform == 'emscripten') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/de/da/b1dc0481ab8d55d0f46e343cfe67d4551a0e14fcee52bd38ca1bd73258d8/pandas-3.0.0.tar.gz", hash = "sha256:0facf7e87d38f721f0af46fe70d97373a37701b1c09f7ed7aeeb292ade5c050f", size = 4633005, upload-time = "2026-01-21T15:52:04.726Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/46/1e/b184654a856e75e975a6ee95d6577b51c271cd92cb2b020c9378f53e0032/pandas-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d64ce01eb9cdca96a15266aa679ae50212ec52757c79204dbc7701a222401850", size = 10313247, upload-time = "2026-01-21T15:50:15.775Z" }, { url = "https://files.pythonhosted.org/packages/dd/5e/e04a547ad0f0183bf151fd7c7a477468e3b85ff2ad231c566389e6cc9587/pandas-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:613e13426069793aa1ec53bdcc3b86e8d32071daea138bbcf4fa959c9cdaa2e2", size = 9913131, upload-time = "2026-01-21T15:50:18.611Z" }, { url = "https://files.pythonhosted.org/packages/a2/93/bb77bfa9fc2aba9f7204db807d5d3fb69832ed2854c60ba91b4c65ba9219/pandas-3.0.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0192fee1f1a8e743b464a6607858ee4b071deb0b118eb143d71c2a1d170996d5", size = 10741925, upload-time = "2026-01-21T15:50:21.058Z" }, { url = "https://files.pythonhosted.org/packages/62/fb/89319812eb1d714bfc04b7f177895caeba8ab4a37ef6712db75ed786e2e0/pandas-3.0.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0b853319dec8d5e0c8b875374c078ef17f2269986a78168d9bd57e49bf650ae", size = 11245979, upload-time = "2026-01-21T15:50:23.413Z" }, { url = "https://files.pythonhosted.org/packages/a9/63/684120486f541fc88da3862ed31165b3b3e12b6a1c7b93be4597bc84e26c/pandas-3.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:707a9a877a876c326ae2cb640fbdc4ef63b0a7b9e2ef55c6df9942dcee8e2af9", size = 11756337, upload-time = "2026-01-21T15:50:25.932Z" }, { url = "https://files.pythonhosted.org/packages/39/92/7eb0ad232312b59aec61550c3c81ad0743898d10af5df7f80bc5e5065416/pandas-3.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:afd0aa3d0b5cda6e0b8ffc10dbcca3b09ef3cbcd3fe2b27364f85fdc04e1989d", size = 12325517, upload-time = "2026-01-21T15:50:27.952Z" }, { url = "https://files.pythonhosted.org/packages/51/27/bf9436dd0a4fc3130acec0828951c7ef96a0631969613a9a35744baf27f6/pandas-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:113b4cca2614ff7e5b9fee9b6f066618fe73c5a83e99d721ffc41217b2bf57dd", size = 9881576, upload-time = "2026-01-21T15:50:30.149Z" }, { url = "https://files.pythonhosted.org/packages/e7/2b/c618b871fce0159fd107516336e82891b404e3f340821853c2fc28c7830f/pandas-3.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c14837eba8e99a8da1527c0280bba29b0eb842f64aa94982c5e21227966e164b", size = 9140807, upload-time = "2026-01-21T15:50:32.308Z" }, { url = "https://files.pythonhosted.org/packages/0b/38/db33686f4b5fa64d7af40d96361f6a4615b8c6c8f1b3d334eee46ae6160e/pandas-3.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9803b31f5039b3c3b10cc858c5e40054adb4b29b4d81cb2fd789f4121c8efbcd", size = 10334013, upload-time = "2026-01-21T15:50:34.771Z" }, { url = "https://files.pythonhosted.org/packages/a5/7b/9254310594e9774906bacdd4e732415e1f86ab7dbb4b377ef9ede58cd8ec/pandas-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14c2a4099cd38a1d18ff108168ea417909b2dea3bd1ebff2ccf28ddb6a74d740", size = 9874154, upload-time = "2026-01-21T15:50:36.67Z" }, { url = "https://files.pythonhosted.org/packages/63/d4/726c5a67a13bc66643e66d2e9ff115cead482a44fc56991d0c4014f15aaf/pandas-3.0.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d257699b9a9960e6125686098d5714ac59d05222bef7a5e6af7a7fd87c650801", size = 10384433, upload-time = "2026-01-21T15:50:39.132Z" }, { url = "https://files.pythonhosted.org/packages/bf/2e/9211f09bedb04f9832122942de8b051804b31a39cfbad199a819bb88d9f3/pandas-3.0.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:69780c98f286076dcafca38d8b8eee1676adf220199c0a39f0ecbf976b68151a", size = 10864519, upload-time = "2026-01-21T15:50:41.043Z" }, { url = "https://files.pythonhosted.org/packages/00/8d/50858522cdc46ac88b9afdc3015e298959a70a08cd21e008a44e9520180c/pandas-3.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4a66384f017240f3858a4c8a7cf21b0591c3ac885cddb7758a589f0f71e87ebb", size = 11394124, upload-time = "2026-01-21T15:50:43.377Z" }, { url = "https://files.pythonhosted.org/packages/86/3f/83b2577db02503cd93d8e95b0f794ad9d4be0ba7cb6c8bcdcac964a34a42/pandas-3.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be8c515c9bc33989d97b89db66ea0cececb0f6e3c2a87fcc8b69443a6923e95f", size = 11920444, upload-time = "2026-01-21T15:50:45.932Z" }, { url = "https://files.pythonhosted.org/packages/64/2d/4f8a2f192ed12c90a0aab47f5557ece0e56b0370c49de9454a09de7381b2/pandas-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:a453aad8c4f4e9f166436994a33884442ea62aa8b27d007311e87521b97246e1", size = 9730970, upload-time = "2026-01-21T15:50:47.962Z" }, { url = "https://files.pythonhosted.org/packages/d4/64/ff571be435cf1e643ca98d0945d76732c0b4e9c37191a89c8550b105eed1/pandas-3.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:da768007b5a33057f6d9053563d6b74dd6d029c337d93c6d0d22a763a5c2ecc0", size = 9041950, upload-time = "2026-01-21T15:50:50.422Z" }, { url = "https://files.pythonhosted.org/packages/6f/fa/7f0ac4ca8877c57537aaff2a842f8760e630d8e824b730eb2e859ffe96ca/pandas-3.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b78d646249b9a2bc191040988c7bb524c92fa8534fb0898a0741d7e6f2ffafa6", size = 10307129, upload-time = "2026-01-21T15:50:52.877Z" }, { url = "https://files.pythonhosted.org/packages/6f/11/28a221815dcea4c0c9414dfc845e34a84a6a7dabc6da3194498ed5ba4361/pandas-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bc9cba7b355cb4162442a88ce495e01cb605f17ac1e27d6596ac963504e0305f", size = 9850201, upload-time = "2026-01-21T15:50:54.807Z" }, { url = "https://files.pythonhosted.org/packages/ba/da/53bbc8c5363b7e5bd10f9ae59ab250fc7a382ea6ba08e4d06d8694370354/pandas-3.0.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c9a1a149aed3b6c9bf246033ff91e1b02d529546c5d6fb6b74a28fea0cf4c70", size = 10354031, upload-time = "2026-01-21T15:50:57.463Z" }, { url = "https://files.pythonhosted.org/packages/f7/a3/51e02ebc2a14974170d51e2410dfdab58870ea9bcd37cda15bd553d24dc4/pandas-3.0.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95683af6175d884ee89471842acfca29172a85031fccdabc35e50c0984470a0e", size = 10861165, upload-time = "2026-01-21T15:50:59.32Z" }, { url = "https://files.pythonhosted.org/packages/a5/fe/05a51e3cac11d161472b8297bd41723ea98013384dd6d76d115ce3482f9b/pandas-3.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1fbbb5a7288719e36b76b4f18d46ede46e7f916b6c8d9915b756b0a6c3f792b3", size = 11359359, upload-time = "2026-01-21T15:51:02.014Z" }, { url = "https://files.pythonhosted.org/packages/ee/56/ba620583225f9b85a4d3e69c01df3e3870659cc525f67929b60e9f21dcd1/pandas-3.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8e8b9808590fa364416b49b2a35c1f4cf2785a6c156935879e57f826df22038e", size = 11912907, upload-time = "2026-01-21T15:51:05.175Z" }, { url = "https://files.pythonhosted.org/packages/c9/8c/c6638d9f67e45e07656b3826405c5cc5f57f6fd07c8b2572ade328c86e22/pandas-3.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:98212a38a709feb90ae658cb6227ea3657c22ba8157d4b8f913cd4c950de5e7e", size = 9732138, upload-time = "2026-01-21T15:51:07.569Z" }, { url = "https://files.pythonhosted.org/packages/7b/bf/bd1335c3bf1770b6d8fed2799993b11c4971af93bb1b729b9ebbc02ca2ec/pandas-3.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:177d9df10b3f43b70307a149d7ec49a1229a653f907aa60a48f1877d0e6be3be", size = 9033568, upload-time = "2026-01-21T15:51:09.484Z" }, { url = "https://files.pythonhosted.org/packages/8e/c6/f5e2171914d5e29b9171d495344097d54e3ffe41d2d85d8115baba4dc483/pandas-3.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2713810ad3806767b89ad3b7b69ba153e1c6ff6d9c20f9c2140379b2a98b6c98", size = 10741936, upload-time = "2026-01-21T15:51:11.693Z" }, { url = "https://files.pythonhosted.org/packages/51/88/9a0164f99510a1acb9f548691f022c756c2314aad0d8330a24616c14c462/pandas-3.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:15d59f885ee5011daf8335dff47dcb8a912a27b4ad7826dc6cbe809fd145d327", size = 10393884, upload-time = "2026-01-21T15:51:14.197Z" }, { url = "https://files.pythonhosted.org/packages/e0/53/b34d78084d88d8ae2b848591229da8826d1e65aacf00b3abe34023467648/pandas-3.0.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24e6547fb64d2c92665dd2adbfa4e85fa4fd70a9c070e7cfb03b629a0bbab5eb", size = 10310740, upload-time = "2026-01-21T15:51:16.093Z" }, { url = "https://files.pythonhosted.org/packages/5b/d3/bee792e7c3d6930b74468d990604325701412e55d7aaf47460a22311d1a5/pandas-3.0.0-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48ee04b90e2505c693d3f8e8f524dab8cb8aaf7ddcab52c92afa535e717c4812", size = 10700014, upload-time = "2026-01-21T15:51:18.818Z" }, { url = "https://files.pythonhosted.org/packages/55/db/2570bc40fb13aaed1cbc3fbd725c3a60ee162477982123c3adc8971e7ac1/pandas-3.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66f72fb172959af42a459e27a8d8d2c7e311ff4c1f7db6deb3b643dbc382ae08", size = 11323737, upload-time = "2026-01-21T15:51:20.784Z" }, { url = "https://files.pythonhosted.org/packages/bc/2e/297ac7f21c8181b62a4cccebad0a70caf679adf3ae5e83cb676194c8acc3/pandas-3.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4a4a400ca18230976724a5066f20878af785f36c6756e498e94c2a5e5d57779c", size = 11771558, upload-time = "2026-01-21T15:51:22.977Z" }, { url = "https://files.pythonhosted.org/packages/0a/46/e1c6876d71c14332be70239acce9ad435975a80541086e5ffba2f249bcf6/pandas-3.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:940eebffe55528074341a5a36515f3e4c5e25e958ebbc764c9502cfc35ba3faa", size = 10473771, upload-time = "2026-01-21T15:51:25.285Z" }, { url = "https://files.pythonhosted.org/packages/c0/db/0270ad9d13c344b7a36fa77f5f8344a46501abf413803e885d22864d10bf/pandas-3.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:597c08fb9fef0edf1e4fa2f9828dd27f3d78f9b8c9b4a748d435ffc55732310b", size = 10312075, upload-time = "2026-01-21T15:51:28.5Z" }, { url = "https://files.pythonhosted.org/packages/09/9f/c176f5e9717f7c91becfe0f55a52ae445d3f7326b4a2cf355978c51b7913/pandas-3.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:447b2d68ac5edcbf94655fe909113a6dba6ef09ad7f9f60c80477825b6c489fe", size = 9900213, upload-time = "2026-01-21T15:51:30.955Z" }, { url = "https://files.pythonhosted.org/packages/d9/e7/63ad4cc10b257b143e0a5ebb04304ad806b4e1a61c5da25f55896d2ca0f4/pandas-3.0.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:debb95c77ff3ed3ba0d9aa20c3a2f19165cc7956362f9873fce1ba0a53819d70", size = 10428768, upload-time = "2026-01-21T15:51:33.018Z" }, { url = "https://files.pythonhosted.org/packages/9e/0e/4e4c2d8210f20149fd2248ef3fff26623604922bd564d915f935a06dd63d/pandas-3.0.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fedabf175e7cd82b69b74c30adbaa616de301291a5231138d7242596fc296a8d", size = 10882954, upload-time = "2026-01-21T15:51:35.287Z" }, { url = "https://files.pythonhosted.org/packages/c6/60/c9de8ac906ba1f4d2250f8a951abe5135b404227a55858a75ad26f84db47/pandas-3.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:412d1a89aab46889f3033a386912efcdfa0f1131c5705ff5b668dda88305e986", size = 11430293, upload-time = "2026-01-21T15:51:37.57Z" }, { url = "https://files.pythonhosted.org/packages/a1/69/806e6637c70920e5787a6d6896fd707f8134c2c55cd761e7249a97b7dc5a/pandas-3.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e979d22316f9350c516479dd3a92252be2937a9531ed3a26ec324198a99cdd49", size = 11952452, upload-time = "2026-01-21T15:51:39.618Z" }, { url = "https://files.pythonhosted.org/packages/cb/de/918621e46af55164c400ab0ef389c9d969ab85a43d59ad1207d4ddbe30a5/pandas-3.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:083b11415b9970b6e7888800c43c82e81a06cd6b06755d84804444f0007d6bb7", size = 9851081, upload-time = "2026-01-21T15:51:41.758Z" }, { url = "https://files.pythonhosted.org/packages/91/a1/3562a18dd0bd8c73344bfa26ff90c53c72f827df119d6d6b1dacc84d13e3/pandas-3.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:5db1e62cb99e739fa78a28047e861b256d17f88463c76b8dafc7c1338086dca8", size = 9174610, upload-time = "2026-01-21T15:51:44.312Z" }, { url = "https://files.pythonhosted.org/packages/ce/26/430d91257eaf366f1737d7a1c158677caaf6267f338ec74e3a1ec444111c/pandas-3.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:697b8f7d346c68274b1b93a170a70974cdc7d7354429894d5927c1effdcccd73", size = 10761999, upload-time = "2026-01-21T15:51:46.899Z" }, { url = "https://files.pythonhosted.org/packages/ec/1a/954eb47736c2b7f7fe6a9d56b0cb6987773c00faa3c6451a43db4beb3254/pandas-3.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8cb3120f0d9467ed95e77f67a75e030b67545bcfa08964e349252d674171def2", size = 10410279, upload-time = "2026-01-21T15:51:48.89Z" }, { url = "https://files.pythonhosted.org/packages/20/fc/b96f3a5a28b250cd1b366eb0108df2501c0f38314a00847242abab71bb3a/pandas-3.0.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33fd3e6baa72899746b820c31e4b9688c8e1b7864d7aec2de7ab5035c285277a", size = 10330198, upload-time = "2026-01-21T15:51:51.015Z" }, { url = "https://files.pythonhosted.org/packages/90/b3/d0e2952f103b4fbef1ef22d0c2e314e74fc9064b51cee30890b5e3286ee6/pandas-3.0.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8942e333dc67ceda1095227ad0febb05a3b36535e520154085db632c40ad084", size = 10728513, upload-time = "2026-01-21T15:51:53.387Z" }, { url = "https://files.pythonhosted.org/packages/76/81/832894f286df828993dc5fd61c63b231b0fb73377e99f6c6c369174cf97e/pandas-3.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:783ac35c4d0fe0effdb0d67161859078618b1b6587a1af15928137525217a721", size = 11345550, upload-time = "2026-01-21T15:51:55.329Z" }, { url = "https://files.pythonhosted.org/packages/34/a0/ed160a00fb4f37d806406bc0a79a8b62fe67f29d00950f8d16203ff3409b/pandas-3.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:125eb901e233f155b268bbef9abd9afb5819db74f0e677e89a61b246228c71ac", size = 11799386, upload-time = "2026-01-21T15:51:57.457Z" }, { url = "https://files.pythonhosted.org/packages/36/c8/2ac00d7255252c5e3cf61b35ca92ca25704b0188f7454ca4aec08a33cece/pandas-3.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b86d113b6c109df3ce0ad5abbc259fe86a1bd4adfd4a31a89da42f84f65509bb", size = 10873041, upload-time = "2026-01-21T15:52:00.034Z" }, { url = "https://files.pythonhosted.org/packages/e6/3f/a80ac00acbc6b35166b42850e98a4f466e2c0d9c64054161ba9620f95680/pandas-3.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1c39eab3ad38f2d7a249095f0a3d8f8c22cc0f847e98ccf5bbe732b272e2d9fa", size = 9441003, upload-time = "2026-01-21T15:52:02.281Z" }, ] [[package]] name = "pathspec" version = "1.0.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, ] [[package]] name = "patsy" version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/44/ed13eccdd0519eff265f44b670d46fbb0ec813e2274932dc1c0e48520f7d/patsy-1.0.2.tar.gz", hash = "sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0", size = 399942, upload-time = "2025-10-20T16:17:37.535Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a", size = 233301, upload-time = "2025-10-20T16:17:36.563Z" }, ] [[package]] name = "pillow" version = "11.3.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523", size = 47113069, upload-time = "2025-07-01T09:16:30.666Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/4c/5d/45a3553a253ac8763f3561371432a90bdbe6000fbdcf1397ffe502aa206c/pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860", size = 5316554, upload-time = "2025-07-01T09:13:39.342Z" }, { url = "https://files.pythonhosted.org/packages/7c/c8/67c12ab069ef586a25a4a79ced553586748fad100c77c0ce59bb4983ac98/pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad", size = 4686548, upload-time = "2025-07-01T09:13:41.835Z" }, { url = "https://files.pythonhosted.org/packages/2f/bd/6741ebd56263390b382ae4c5de02979af7f8bd9807346d068700dd6d5cf9/pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0", size = 5859742, upload-time = "2025-07-03T13:09:47.439Z" }, { url = "https://files.pythonhosted.org/packages/ca/0b/c412a9e27e1e6a829e6ab6c2dca52dd563efbedf4c9c6aa453d9a9b77359/pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b", size = 7633087, upload-time = "2025-07-03T13:09:51.796Z" }, { url = "https://files.pythonhosted.org/packages/59/9d/9b7076aaf30f5dd17e5e5589b2d2f5a5d7e30ff67a171eb686e4eecc2adf/pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50", size = 5963350, upload-time = "2025-07-01T09:13:43.865Z" }, { url = "https://files.pythonhosted.org/packages/f0/16/1a6bf01fb622fb9cf5c91683823f073f053005c849b1f52ed613afcf8dae/pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae", size = 6631840, upload-time = "2025-07-01T09:13:46.161Z" }, { url = "https://files.pythonhosted.org/packages/7b/e6/6ff7077077eb47fde78739e7d570bdcd7c10495666b6afcd23ab56b19a43/pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9", size = 6074005, upload-time = "2025-07-01T09:13:47.829Z" }, { url = "https://files.pythonhosted.org/packages/c3/3a/b13f36832ea6d279a697231658199e0a03cd87ef12048016bdcc84131601/pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e", size = 6708372, upload-time = "2025-07-01T09:13:52.145Z" }, { url = "https://files.pythonhosted.org/packages/6c/e4/61b2e1a7528740efbc70b3d581f33937e38e98ef3d50b05007267a55bcb2/pillow-11.3.0-cp310-cp310-win32.whl", hash = "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6", size = 6277090, upload-time = "2025-07-01T09:13:53.915Z" }, { url = "https://files.pythonhosted.org/packages/a9/d3/60c781c83a785d6afbd6a326ed4d759d141de43aa7365725cbcd65ce5e54/pillow-11.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f", size = 6985988, upload-time = "2025-07-01T09:13:55.699Z" }, { url = "https://files.pythonhosted.org/packages/9f/28/4f4a0203165eefb3763939c6789ba31013a2e90adffb456610f30f613850/pillow-11.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f", size = 2422899, upload-time = "2025-07-01T09:13:57.497Z" }, { url = "https://files.pythonhosted.org/packages/db/26/77f8ed17ca4ffd60e1dcd220a6ec6d71210ba398cfa33a13a1cd614c5613/pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722", size = 5316531, upload-time = "2025-07-01T09:13:59.203Z" }, { url = "https://files.pythonhosted.org/packages/cb/39/ee475903197ce709322a17a866892efb560f57900d9af2e55f86db51b0a5/pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288", size = 4686560, upload-time = "2025-07-01T09:14:01.101Z" }, { url = "https://files.pythonhosted.org/packages/d5/90/442068a160fd179938ba55ec8c97050a612426fae5ec0a764e345839f76d/pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d", size = 5870978, upload-time = "2025-07-03T13:09:55.638Z" }, { url = "https://files.pythonhosted.org/packages/13/92/dcdd147ab02daf405387f0218dcf792dc6dd5b14d2573d40b4caeef01059/pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494", size = 7641168, upload-time = "2025-07-03T13:10:00.37Z" }, { url = "https://files.pythonhosted.org/packages/6e/db/839d6ba7fd38b51af641aa904e2960e7a5644d60ec754c046b7d2aee00e5/pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58", size = 5973053, upload-time = "2025-07-01T09:14:04.491Z" }, { url = "https://files.pythonhosted.org/packages/f2/2f/d7675ecae6c43e9f12aa8d58b6012683b20b6edfbdac7abcb4e6af7a3784/pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f", size = 6640273, upload-time = "2025-07-01T09:14:06.235Z" }, { url = "https://files.pythonhosted.org/packages/45/ad/931694675ede172e15b2ff03c8144a0ddaea1d87adb72bb07655eaffb654/pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e", size = 6082043, upload-time = "2025-07-01T09:14:07.978Z" }, { url = "https://files.pythonhosted.org/packages/3a/04/ba8f2b11fc80d2dd462d7abec16351b45ec99cbbaea4387648a44190351a/pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94", size = 6715516, upload-time = "2025-07-01T09:14:10.233Z" }, { url = "https://files.pythonhosted.org/packages/48/59/8cd06d7f3944cc7d892e8533c56b0acb68399f640786313275faec1e3b6f/pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0", size = 6274768, upload-time = "2025-07-01T09:14:11.921Z" }, { url = "https://files.pythonhosted.org/packages/f1/cc/29c0f5d64ab8eae20f3232da8f8571660aa0ab4b8f1331da5c2f5f9a938e/pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac", size = 6986055, upload-time = "2025-07-01T09:14:13.623Z" }, { url = "https://files.pythonhosted.org/packages/c6/df/90bd886fabd544c25addd63e5ca6932c86f2b701d5da6c7839387a076b4a/pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd", size = 2423079, upload-time = "2025-07-01T09:14:15.268Z" }, { url = "https://files.pythonhosted.org/packages/40/fe/1bc9b3ee13f68487a99ac9529968035cca2f0a51ec36892060edcc51d06a/pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4", size = 5278800, upload-time = "2025-07-01T09:14:17.648Z" }, { url = "https://files.pythonhosted.org/packages/2c/32/7e2ac19b5713657384cec55f89065fb306b06af008cfd87e572035b27119/pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69", size = 4686296, upload-time = "2025-07-01T09:14:19.828Z" }, { url = "https://files.pythonhosted.org/packages/8e/1e/b9e12bbe6e4c2220effebc09ea0923a07a6da1e1f1bfbc8d7d29a01ce32b/pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d", size = 5871726, upload-time = "2025-07-03T13:10:04.448Z" }, { url = "https://files.pythonhosted.org/packages/8d/33/e9200d2bd7ba00dc3ddb78df1198a6e80d7669cce6c2bdbeb2530a74ec58/pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6", size = 7644652, upload-time = "2025-07-03T13:10:10.391Z" }, { url = "https://files.pythonhosted.org/packages/41/f1/6f2427a26fc683e00d985bc391bdd76d8dd4e92fac33d841127eb8fb2313/pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7", size = 5977787, upload-time = "2025-07-01T09:14:21.63Z" }, { url = "https://files.pythonhosted.org/packages/e4/c9/06dd4a38974e24f932ff5f98ea3c546ce3f8c995d3f0985f8e5ba48bba19/pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024", size = 6645236, upload-time = "2025-07-01T09:14:23.321Z" }, { url = "https://files.pythonhosted.org/packages/40/e7/848f69fb79843b3d91241bad658e9c14f39a32f71a301bcd1d139416d1be/pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809", size = 6086950, upload-time = "2025-07-01T09:14:25.237Z" }, { url = "https://files.pythonhosted.org/packages/0b/1a/7cff92e695a2a29ac1958c2a0fe4c0b2393b60aac13b04a4fe2735cad52d/pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d", size = 6723358, upload-time = "2025-07-01T09:14:27.053Z" }, { url = "https://files.pythonhosted.org/packages/26/7d/73699ad77895f69edff76b0f332acc3d497f22f5d75e5360f78cbcaff248/pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149", size = 6275079, upload-time = "2025-07-01T09:14:30.104Z" }, { url = "https://files.pythonhosted.org/packages/8c/ce/e7dfc873bdd9828f3b6e5c2bbb74e47a98ec23cc5c74fc4e54462f0d9204/pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d", size = 6986324, upload-time = "2025-07-01T09:14:31.899Z" }, { url = "https://files.pythonhosted.org/packages/16/8f/b13447d1bf0b1f7467ce7d86f6e6edf66c0ad7cf44cf5c87a37f9bed9936/pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542", size = 2423067, upload-time = "2025-07-01T09:14:33.709Z" }, { url = "https://files.pythonhosted.org/packages/1e/93/0952f2ed8db3a5a4c7a11f91965d6184ebc8cd7cbb7941a260d5f018cd2d/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd", size = 2128328, upload-time = "2025-07-01T09:14:35.276Z" }, { url = "https://files.pythonhosted.org/packages/4b/e8/100c3d114b1a0bf4042f27e0f87d2f25e857e838034e98ca98fe7b8c0a9c/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8", size = 2170652, upload-time = "2025-07-01T09:14:37.203Z" }, { url = "https://files.pythonhosted.org/packages/aa/86/3f758a28a6e381758545f7cdb4942e1cb79abd271bea932998fc0db93cb6/pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f", size = 2227443, upload-time = "2025-07-01T09:14:39.344Z" }, { url = "https://files.pythonhosted.org/packages/01/f4/91d5b3ffa718df2f53b0dc109877993e511f4fd055d7e9508682e8aba092/pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c", size = 5278474, upload-time = "2025-07-01T09:14:41.843Z" }, { url = "https://files.pythonhosted.org/packages/f9/0e/37d7d3eca6c879fbd9dba21268427dffda1ab00d4eb05b32923d4fbe3b12/pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd", size = 4686038, upload-time = "2025-07-01T09:14:44.008Z" }, { url = "https://files.pythonhosted.org/packages/ff/b0/3426e5c7f6565e752d81221af9d3676fdbb4f352317ceafd42899aaf5d8a/pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e", size = 5864407, upload-time = "2025-07-03T13:10:15.628Z" }, { url = "https://files.pythonhosted.org/packages/fc/c1/c6c423134229f2a221ee53f838d4be9d82bab86f7e2f8e75e47b6bf6cd77/pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1", size = 7639094, upload-time = "2025-07-03T13:10:21.857Z" }, { url = "https://files.pythonhosted.org/packages/ba/c9/09e6746630fe6372c67c648ff9deae52a2bc20897d51fa293571977ceb5d/pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805", size = 5973503, upload-time = "2025-07-01T09:14:45.698Z" }, { url = "https://files.pythonhosted.org/packages/d5/1c/a2a29649c0b1983d3ef57ee87a66487fdeb45132df66ab30dd37f7dbe162/pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8", size = 6642574, upload-time = "2025-07-01T09:14:47.415Z" }, { url = "https://files.pythonhosted.org/packages/36/de/d5cc31cc4b055b6c6fd990e3e7f0f8aaf36229a2698501bcb0cdf67c7146/pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2", size = 6084060, upload-time = "2025-07-01T09:14:49.636Z" }, { url = "https://files.pythonhosted.org/packages/d5/ea/502d938cbaeec836ac28a9b730193716f0114c41325db428e6b280513f09/pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b", size = 6721407, upload-time = "2025-07-01T09:14:51.962Z" }, { url = "https://files.pythonhosted.org/packages/45/9c/9c5e2a73f125f6cbc59cc7087c8f2d649a7ae453f83bd0362ff7c9e2aee2/pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3", size = 6273841, upload-time = "2025-07-01T09:14:54.142Z" }, { url = "https://files.pythonhosted.org/packages/23/85/397c73524e0cd212067e0c969aa245b01d50183439550d24d9f55781b776/pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51", size = 6978450, upload-time = "2025-07-01T09:14:56.436Z" }, { url = "https://files.pythonhosted.org/packages/17/d2/622f4547f69cd173955194b78e4d19ca4935a1b0f03a302d655c9f6aae65/pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580", size = 2423055, upload-time = "2025-07-01T09:14:58.072Z" }, { url = "https://files.pythonhosted.org/packages/dd/80/a8a2ac21dda2e82480852978416cfacd439a4b490a501a288ecf4fe2532d/pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e", size = 5281110, upload-time = "2025-07-01T09:14:59.79Z" }, { url = "https://files.pythonhosted.org/packages/44/d6/b79754ca790f315918732e18f82a8146d33bcd7f4494380457ea89eb883d/pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d", size = 4689547, upload-time = "2025-07-01T09:15:01.648Z" }, { url = "https://files.pythonhosted.org/packages/49/20/716b8717d331150cb00f7fdd78169c01e8e0c219732a78b0e59b6bdb2fd6/pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced", size = 5901554, upload-time = "2025-07-03T13:10:27.018Z" }, { url = "https://files.pythonhosted.org/packages/74/cf/a9f3a2514a65bb071075063a96f0a5cf949c2f2fce683c15ccc83b1c1cab/pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c", size = 7669132, upload-time = "2025-07-03T13:10:33.01Z" }, { url = "https://files.pythonhosted.org/packages/98/3c/da78805cbdbee9cb43efe8261dd7cc0b4b93f2ac79b676c03159e9db2187/pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8", size = 6005001, upload-time = "2025-07-01T09:15:03.365Z" }, { url = "https://files.pythonhosted.org/packages/6c/fa/ce044b91faecf30e635321351bba32bab5a7e034c60187fe9698191aef4f/pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59", size = 6668814, upload-time = "2025-07-01T09:15:05.655Z" }, { url = "https://files.pythonhosted.org/packages/7b/51/90f9291406d09bf93686434f9183aba27b831c10c87746ff49f127ee80cb/pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe", size = 6113124, upload-time = "2025-07-01T09:15:07.358Z" }, { url = "https://files.pythonhosted.org/packages/cd/5a/6fec59b1dfb619234f7636d4157d11fb4e196caeee220232a8d2ec48488d/pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c", size = 6747186, upload-time = "2025-07-01T09:15:09.317Z" }, { url = "https://files.pythonhosted.org/packages/49/6b/00187a044f98255225f172de653941e61da37104a9ea60e4f6887717e2b5/pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788", size = 6277546, upload-time = "2025-07-01T09:15:11.311Z" }, { url = "https://files.pythonhosted.org/packages/e8/5c/6caaba7e261c0d75bab23be79f1d06b5ad2a2ae49f028ccec801b0e853d6/pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31", size = 6985102, upload-time = "2025-07-01T09:15:13.164Z" }, { url = "https://files.pythonhosted.org/packages/f3/7e/b623008460c09a0cb38263c93b828c666493caee2eb34ff67f778b87e58c/pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e", size = 2424803, upload-time = "2025-07-01T09:15:15.695Z" }, { url = "https://files.pythonhosted.org/packages/73/f4/04905af42837292ed86cb1b1dabe03dce1edc008ef14c473c5c7e1443c5d/pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12", size = 5278520, upload-time = "2025-07-01T09:15:17.429Z" }, { url = "https://files.pythonhosted.org/packages/41/b0/33d79e377a336247df6348a54e6d2a2b85d644ca202555e3faa0cf811ecc/pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a", size = 4686116, upload-time = "2025-07-01T09:15:19.423Z" }, { url = "https://files.pythonhosted.org/packages/49/2d/ed8bc0ab219ae8768f529597d9509d184fe8a6c4741a6864fea334d25f3f/pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632", size = 5864597, upload-time = "2025-07-03T13:10:38.404Z" }, { url = "https://files.pythonhosted.org/packages/b5/3d/b932bb4225c80b58dfadaca9d42d08d0b7064d2d1791b6a237f87f661834/pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673", size = 7638246, upload-time = "2025-07-03T13:10:44.987Z" }, { url = "https://files.pythonhosted.org/packages/09/b5/0487044b7c096f1b48f0d7ad416472c02e0e4bf6919541b111efd3cae690/pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027", size = 5973336, upload-time = "2025-07-01T09:15:21.237Z" }, { url = "https://files.pythonhosted.org/packages/a8/2d/524f9318f6cbfcc79fbc004801ea6b607ec3f843977652fdee4857a7568b/pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77", size = 6642699, upload-time = "2025-07-01T09:15:23.186Z" }, { url = "https://files.pythonhosted.org/packages/6f/d2/a9a4f280c6aefedce1e8f615baaa5474e0701d86dd6f1dede66726462bbd/pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874", size = 6083789, upload-time = "2025-07-01T09:15:25.1Z" }, { url = "https://files.pythonhosted.org/packages/fe/54/86b0cd9dbb683a9d5e960b66c7379e821a19be4ac5810e2e5a715c09a0c0/pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a", size = 6720386, upload-time = "2025-07-01T09:15:27.378Z" }, { url = "https://files.pythonhosted.org/packages/e7/95/88efcaf384c3588e24259c4203b909cbe3e3c2d887af9e938c2022c9dd48/pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214", size = 6370911, upload-time = "2025-07-01T09:15:29.294Z" }, { url = "https://files.pythonhosted.org/packages/2e/cc/934e5820850ec5eb107e7b1a72dd278140731c669f396110ebc326f2a503/pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635", size = 7117383, upload-time = "2025-07-01T09:15:31.128Z" }, { url = "https://files.pythonhosted.org/packages/d6/e9/9c0a616a71da2a5d163aa37405e8aced9a906d574b4a214bede134e731bc/pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6", size = 2511385, upload-time = "2025-07-01T09:15:33.328Z" }, { url = "https://files.pythonhosted.org/packages/1a/33/c88376898aff369658b225262cd4f2659b13e8178e7534df9e6e1fa289f6/pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae", size = 5281129, upload-time = "2025-07-01T09:15:35.194Z" }, { url = "https://files.pythonhosted.org/packages/1f/70/d376247fb36f1844b42910911c83a02d5544ebd2a8bad9efcc0f707ea774/pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653", size = 4689580, upload-time = "2025-07-01T09:15:37.114Z" }, { url = "https://files.pythonhosted.org/packages/eb/1c/537e930496149fbac69efd2fc4329035bbe2e5475b4165439e3be9cb183b/pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6", size = 5902860, upload-time = "2025-07-03T13:10:50.248Z" }, { url = "https://files.pythonhosted.org/packages/bd/57/80f53264954dcefeebcf9dae6e3eb1daea1b488f0be8b8fef12f79a3eb10/pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36", size = 7670694, upload-time = "2025-07-03T13:10:56.432Z" }, { url = "https://files.pythonhosted.org/packages/70/ff/4727d3b71a8578b4587d9c276e90efad2d6fe0335fd76742a6da08132e8c/pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b", size = 6005888, upload-time = "2025-07-01T09:15:39.436Z" }, { url = "https://files.pythonhosted.org/packages/05/ae/716592277934f85d3be51d7256f3636672d7b1abfafdc42cf3f8cbd4b4c8/pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477", size = 6670330, upload-time = "2025-07-01T09:15:41.269Z" }, { url = "https://files.pythonhosted.org/packages/e7/bb/7fe6cddcc8827b01b1a9766f5fdeb7418680744f9082035bdbabecf1d57f/pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50", size = 6114089, upload-time = "2025-07-01T09:15:43.13Z" }, { url = "https://files.pythonhosted.org/packages/8b/f5/06bfaa444c8e80f1a8e4bff98da9c83b37b5be3b1deaa43d27a0db37ef84/pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b", size = 6748206, upload-time = "2025-07-01T09:15:44.937Z" }, { url = "https://files.pythonhosted.org/packages/f0/77/bc6f92a3e8e6e46c0ca78abfffec0037845800ea38c73483760362804c41/pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12", size = 6377370, upload-time = "2025-07-01T09:15:46.673Z" }, { url = "https://files.pythonhosted.org/packages/4a/82/3a721f7d69dca802befb8af08b7c79ebcab461007ce1c18bd91a5d5896f9/pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db", size = 7121500, upload-time = "2025-07-01T09:15:48.512Z" }, { url = "https://files.pythonhosted.org/packages/89/c7/5572fa4a3f45740eaab6ae86fcdf7195b55beac1371ac8c619d880cfe948/pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa", size = 2512835, upload-time = "2025-07-01T09:15:50.399Z" }, { url = "https://files.pythonhosted.org/packages/9e/8e/9c089f01677d1264ab8648352dcb7773f37da6ad002542760c80107da816/pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f", size = 5316478, upload-time = "2025-07-01T09:15:52.209Z" }, { url = "https://files.pythonhosted.org/packages/b5/a9/5749930caf674695867eb56a581e78eb5f524b7583ff10b01b6e5048acb3/pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081", size = 4686522, upload-time = "2025-07-01T09:15:54.162Z" }, { url = "https://files.pythonhosted.org/packages/43/46/0b85b763eb292b691030795f9f6bb6fcaf8948c39413c81696a01c3577f7/pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4", size = 5853376, upload-time = "2025-07-03T13:11:01.066Z" }, { url = "https://files.pythonhosted.org/packages/5e/c6/1a230ec0067243cbd60bc2dad5dc3ab46a8a41e21c15f5c9b52b26873069/pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc", size = 7626020, upload-time = "2025-07-03T13:11:06.479Z" }, { url = "https://files.pythonhosted.org/packages/63/dd/f296c27ffba447bfad76c6a0c44c1ea97a90cb9472b9304c94a732e8dbfb/pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06", size = 5956732, upload-time = "2025-07-01T09:15:56.111Z" }, { url = "https://files.pythonhosted.org/packages/a5/a0/98a3630f0b57f77bae67716562513d3032ae70414fcaf02750279c389a9e/pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a", size = 6624404, upload-time = "2025-07-01T09:15:58.245Z" }, { url = "https://files.pythonhosted.org/packages/de/e6/83dfba5646a290edd9a21964da07674409e410579c341fc5b8f7abd81620/pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978", size = 6067760, upload-time = "2025-07-01T09:16:00.003Z" }, { url = "https://files.pythonhosted.org/packages/bc/41/15ab268fe6ee9a2bc7391e2bbb20a98d3974304ab1a406a992dcb297a370/pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d", size = 6700534, upload-time = "2025-07-01T09:16:02.29Z" }, { url = "https://files.pythonhosted.org/packages/64/79/6d4f638b288300bed727ff29f2a3cb63db054b33518a95f27724915e3fbc/pillow-11.3.0-cp39-cp39-win32.whl", hash = "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71", size = 6277091, upload-time = "2025-07-01T09:16:04.4Z" }, { url = "https://files.pythonhosted.org/packages/46/05/4106422f45a05716fd34ed21763f8ec182e8ea00af6e9cb05b93a247361a/pillow-11.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada", size = 6986091, upload-time = "2025-07-01T09:16:06.342Z" }, { url = "https://files.pythonhosted.org/packages/63/c6/287fd55c2c12761d0591549d48885187579b7c257bef0c6660755b0b59ae/pillow-11.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb", size = 2422632, upload-time = "2025-07-01T09:16:08.142Z" }, { url = "https://files.pythonhosted.org/packages/6f/8b/209bd6b62ce8367f47e68a218bffac88888fdf2c9fcf1ecadc6c3ec1ebc7/pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967", size = 5270556, upload-time = "2025-07-01T09:16:09.961Z" }, { url = "https://files.pythonhosted.org/packages/2e/e6/231a0b76070c2cfd9e260a7a5b504fb72da0a95279410fa7afd99d9751d6/pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe", size = 4654625, upload-time = "2025-07-01T09:16:11.913Z" }, { url = "https://files.pythonhosted.org/packages/13/f4/10cf94fda33cb12765f2397fc285fa6d8eb9c29de7f3185165b702fc7386/pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c", size = 4874207, upload-time = "2025-07-03T13:11:10.201Z" }, { url = "https://files.pythonhosted.org/packages/72/c9/583821097dc691880c92892e8e2d41fe0a5a3d6021f4963371d2f6d57250/pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25", size = 6583939, upload-time = "2025-07-03T13:11:15.68Z" }, { url = "https://files.pythonhosted.org/packages/3b/8e/5c9d410f9217b12320efc7c413e72693f48468979a013ad17fd690397b9a/pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27", size = 4957166, upload-time = "2025-07-01T09:16:13.74Z" }, { url = "https://files.pythonhosted.org/packages/62/bb/78347dbe13219991877ffb3a91bf09da8317fbfcd4b5f9140aeae020ad71/pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a", size = 5581482, upload-time = "2025-07-01T09:16:16.107Z" }, { url = "https://files.pythonhosted.org/packages/d9/28/1000353d5e61498aaeaaf7f1e4b49ddb05f2c6575f9d4f9f914a3538b6e1/pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f", size = 6984596, upload-time = "2025-07-01T09:16:18.07Z" }, { url = "https://files.pythonhosted.org/packages/9e/e3/6fa84033758276fb31da12e5fb66ad747ae83b93c67af17f8c6ff4cc8f34/pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6", size = 5270566, upload-time = "2025-07-01T09:16:19.801Z" }, { url = "https://files.pythonhosted.org/packages/5b/ee/e8d2e1ab4892970b561e1ba96cbd59c0d28cf66737fc44abb2aec3795a4e/pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438", size = 4654618, upload-time = "2025-07-01T09:16:21.818Z" }, { url = "https://files.pythonhosted.org/packages/f2/6d/17f80f4e1f0761f02160fc433abd4109fa1548dcfdca46cfdadaf9efa565/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3", size = 4874248, upload-time = "2025-07-03T13:11:20.738Z" }, { url = "https://files.pythonhosted.org/packages/de/5f/c22340acd61cef960130585bbe2120e2fd8434c214802f07e8c03596b17e/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c", size = 6583963, upload-time = "2025-07-03T13:11:26.283Z" }, { url = "https://files.pythonhosted.org/packages/31/5e/03966aedfbfcbb4d5f8aa042452d3361f325b963ebbadddac05b122e47dd/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361", size = 4957170, upload-time = "2025-07-01T09:16:23.762Z" }, { url = "https://files.pythonhosted.org/packages/cc/2d/e082982aacc927fc2cab48e1e731bdb1643a1406acace8bed0900a61464e/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7", size = 5581505, upload-time = "2025-07-01T09:16:25.593Z" }, { url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload-time = "2025-07-01T09:16:27.732Z" }, ] [[package]] name = "pillow" version = "12.1.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/d0/02/d52c733a2452ef1ffcc123b68e6606d07276b0e358db70eabad7e40042b7/pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9", size = 46977283, upload-time = "2026-01-02T09:13:29.892Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fe/41/f73d92b6b883a579e79600d391f2e21cb0df767b2714ecbd2952315dfeef/pillow-12.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:fb125d860738a09d363a88daa0f59c4533529a90e564785e20fe875b200b6dbd", size = 5304089, upload-time = "2026-01-02T09:10:24.953Z" }, { url = "https://files.pythonhosted.org/packages/94/55/7aca2891560188656e4a91ed9adba305e914a4496800da6b5c0a15f09edf/pillow-12.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cad302dc10fac357d3467a74a9561c90609768a6f73a1923b0fd851b6486f8b0", size = 4657815, upload-time = "2026-01-02T09:10:27.063Z" }, { url = "https://files.pythonhosted.org/packages/e9/d2/b28221abaa7b4c40b7dba948f0f6a708bd7342c4d47ce342f0ea39643974/pillow-12.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a40905599d8079e09f25027423aed94f2823adaf2868940de991e53a449e14a8", size = 6222593, upload-time = "2026-01-02T09:10:29.115Z" }, { url = "https://files.pythonhosted.org/packages/71/b8/7a61fb234df6a9b0b479f69e66901209d89ff72a435b49933f9122f94cac/pillow-12.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:92a7fe4225365c5e3a8e598982269c6d6698d3e783b3b1ae979e7819f9cd55c1", size = 8027579, upload-time = "2026-01-02T09:10:31.182Z" }, { url = "https://files.pythonhosted.org/packages/ea/51/55c751a57cc524a15a0e3db20e5cde517582359508d62305a627e77fd295/pillow-12.1.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f10c98f49227ed8383d28174ee95155a675c4ed7f85e2e573b04414f7e371bda", size = 6335760, upload-time = "2026-01-02T09:10:33.02Z" }, { url = "https://files.pythonhosted.org/packages/dc/7c/60e3e6f5e5891a1a06b4c910f742ac862377a6fe842f7184df4a274ce7bf/pillow-12.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8637e29d13f478bc4f153d8daa9ffb16455f0a6cb287da1b432fdad2bfbd66c7", size = 7027127, upload-time = "2026-01-02T09:10:35.009Z" }, { url = "https://files.pythonhosted.org/packages/06/37/49d47266ba50b00c27ba63a7c898f1bb41a29627ced8c09e25f19ebec0ff/pillow-12.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:21e686a21078b0f9cb8c8a961d99e6a4ddb88e0fc5ea6e130172ddddc2e5221a", size = 6449896, upload-time = "2026-01-02T09:10:36.793Z" }, { url = "https://files.pythonhosted.org/packages/f9/e5/67fd87d2913902462cd9b79c6211c25bfe95fcf5783d06e1367d6d9a741f/pillow-12.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2415373395a831f53933c23ce051021e79c8cd7979822d8cc478547a3f4da8ef", size = 7151345, upload-time = "2026-01-02T09:10:39.064Z" }, { url = "https://files.pythonhosted.org/packages/bd/15/f8c7abf82af68b29f50d77c227e7a1f87ce02fdc66ded9bf603bc3b41180/pillow-12.1.0-cp310-cp310-win32.whl", hash = "sha256:e75d3dba8fc1ddfec0cd752108f93b83b4f8d6ab40e524a95d35f016b9683b09", size = 6325568, upload-time = "2026-01-02T09:10:41.035Z" }, { url = "https://files.pythonhosted.org/packages/d4/24/7d1c0e160b6b5ac2605ef7d8be537e28753c0db5363d035948073f5513d7/pillow-12.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:64efdf00c09e31efd754448a383ea241f55a994fd079866b92d2bbff598aad91", size = 7032367, upload-time = "2026-01-02T09:10:43.09Z" }, { url = "https://files.pythonhosted.org/packages/f4/03/41c038f0d7a06099254c60f618d0ec7be11e79620fc23b8e85e5b31d9a44/pillow-12.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f188028b5af6b8fb2e9a76ac0f841a575bd1bd396e46ef0840d9b88a48fdbcea", size = 2452345, upload-time = "2026-01-02T09:10:44.795Z" }, { url = "https://files.pythonhosted.org/packages/43/c4/bf8328039de6cc22182c3ef007a2abfbbdab153661c0a9aa78af8d706391/pillow-12.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:a83e0850cb8f5ac975291ebfc4170ba481f41a28065277f7f735c202cd8e0af3", size = 5304057, upload-time = "2026-01-02T09:10:46.627Z" }, { url = "https://files.pythonhosted.org/packages/43/06/7264c0597e676104cc22ca73ee48f752767cd4b1fe084662620b17e10120/pillow-12.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b6e53e82ec2db0717eabb276aa56cf4e500c9a7cec2c2e189b55c24f65a3e8c0", size = 4657811, upload-time = "2026-01-02T09:10:49.548Z" }, { url = "https://files.pythonhosted.org/packages/72/64/f9189e44474610daf83da31145fa56710b627b5c4c0b9c235e34058f6b31/pillow-12.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:40a8e3b9e8773876d6e30daed22f016509e3987bab61b3b7fe309d7019a87451", size = 6232243, upload-time = "2026-01-02T09:10:51.62Z" }, { url = "https://files.pythonhosted.org/packages/ef/30/0df458009be6a4caca4ca2c52975e6275c387d4e5c95544e34138b41dc86/pillow-12.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:800429ac32c9b72909c671aaf17ecd13110f823ddb7db4dfef412a5587c2c24e", size = 8037872, upload-time = "2026-01-02T09:10:53.446Z" }, { url = "https://files.pythonhosted.org/packages/e4/86/95845d4eda4f4f9557e25381d70876aa213560243ac1a6d619c46caaedd9/pillow-12.1.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b022eaaf709541b391ee069f0022ee5b36c709df71986e3f7be312e46f42c84", size = 6345398, upload-time = "2026-01-02T09:10:55.426Z" }, { url = "https://files.pythonhosted.org/packages/5c/1f/8e66ab9be3aaf1435bc03edd1ebdf58ffcd17f7349c1d970cafe87af27d9/pillow-12.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f345e7bc9d7f368887c712aa5054558bad44d2a301ddf9248599f4161abc7c0", size = 7034667, upload-time = "2026-01-02T09:10:57.11Z" }, { url = "https://files.pythonhosted.org/packages/f9/f6/683b83cb9b1db1fb52b87951b1c0b99bdcfceaa75febf11406c19f82cb5e/pillow-12.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d70347c8a5b7ccd803ec0c85c8709f036e6348f1e6a5bf048ecd9c64d3550b8b", size = 6458743, upload-time = "2026-01-02T09:10:59.331Z" }, { url = "https://files.pythonhosted.org/packages/9a/7d/de833d63622538c1d58ce5395e7c6cb7e7dce80decdd8bde4a484e095d9f/pillow-12.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1fcc52d86ce7a34fd17cb04e87cfdb164648a3662a6f20565910a99653d66c18", size = 7159342, upload-time = "2026-01-02T09:11:01.82Z" }, { url = "https://files.pythonhosted.org/packages/8c/40/50d86571c9e5868c42b81fe7da0c76ca26373f3b95a8dd675425f4a92ec1/pillow-12.1.0-cp311-cp311-win32.whl", hash = "sha256:3ffaa2f0659e2f740473bcf03c702c39a8d4b2b7ffc629052028764324842c64", size = 6328655, upload-time = "2026-01-02T09:11:04.556Z" }, { url = "https://files.pythonhosted.org/packages/6c/af/b1d7e301c4cd26cd45d4af884d9ee9b6fab893b0ad2450d4746d74a6968c/pillow-12.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:806f3987ffe10e867bab0ddad45df1148a2b98221798457fa097ad85d6e8bc75", size = 7031469, upload-time = "2026-01-02T09:11:06.538Z" }, { url = "https://files.pythonhosted.org/packages/48/36/d5716586d887fb2a810a4a61518a327a1e21c8b7134c89283af272efe84b/pillow-12.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9f5fefaca968e700ad1a4a9de98bf0869a94e397fe3524c4c9450c1445252304", size = 2452515, upload-time = "2026-01-02T09:11:08.226Z" }, { url = "https://files.pythonhosted.org/packages/20/31/dc53fe21a2f2996e1b7d92bf671cdb157079385183ef7c1ae08b485db510/pillow-12.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a332ac4ccb84b6dde65dbace8431f3af08874bf9770719d32a635c4ef411b18b", size = 5262642, upload-time = "2026-01-02T09:11:10.138Z" }, { url = "https://files.pythonhosted.org/packages/ab/c1/10e45ac9cc79419cedf5121b42dcca5a50ad2b601fa080f58c22fb27626e/pillow-12.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:907bfa8a9cb790748a9aa4513e37c88c59660da3bcfffbd24a7d9e6abf224551", size = 4657464, upload-time = "2026-01-02T09:11:12.319Z" }, { url = "https://files.pythonhosted.org/packages/ad/26/7b82c0ab7ef40ebede7a97c72d473bda5950f609f8e0c77b04af574a0ddb/pillow-12.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:efdc140e7b63b8f739d09a99033aa430accce485ff78e6d311973a67b6bf3208", size = 6234878, upload-time = "2026-01-02T09:11:14.096Z" }, { url = "https://files.pythonhosted.org/packages/76/25/27abc9792615b5e886ca9411ba6637b675f1b77af3104710ac7353fe5605/pillow-12.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bef9768cab184e7ae6e559c032e95ba8d07b3023c289f79a2bd36e8bf85605a5", size = 8044868, upload-time = "2026-01-02T09:11:15.903Z" }, { url = "https://files.pythonhosted.org/packages/0a/ea/f200a4c36d836100e7bc738fc48cd963d3ba6372ebc8298a889e0cfc3359/pillow-12.1.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:742aea052cf5ab5034a53c3846165bc3ce88d7c38e954120db0ab867ca242661", size = 6349468, upload-time = "2026-01-02T09:11:17.631Z" }, { url = "https://files.pythonhosted.org/packages/11/8f/48d0b77ab2200374c66d344459b8958c86693be99526450e7aee714e03e4/pillow-12.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a6dfc2af5b082b635af6e08e0d1f9f1c4e04d17d4e2ca0ef96131e85eda6eb17", size = 7041518, upload-time = "2026-01-02T09:11:19.389Z" }, { url = "https://files.pythonhosted.org/packages/1d/23/c281182eb986b5d31f0a76d2a2c8cd41722d6fb8ed07521e802f9bba52de/pillow-12.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:609e89d9f90b581c8d16358c9087df76024cf058fa693dd3e1e1620823f39670", size = 6462829, upload-time = "2026-01-02T09:11:21.28Z" }, { url = "https://files.pythonhosted.org/packages/25/ef/7018273e0faac099d7b00982abdcc39142ae6f3bd9ceb06de09779c4a9d6/pillow-12.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:43b4899cfd091a9693a1278c4982f3e50f7fb7cff5153b05174b4afc9593b616", size = 7166756, upload-time = "2026-01-02T09:11:23.559Z" }, { url = "https://files.pythonhosted.org/packages/8f/c8/993d4b7ab2e341fe02ceef9576afcf5830cdec640be2ac5bee1820d693d4/pillow-12.1.0-cp312-cp312-win32.whl", hash = "sha256:aa0c9cc0b82b14766a99fbe6084409972266e82f459821cd26997a488a7261a7", size = 6328770, upload-time = "2026-01-02T09:11:25.661Z" }, { url = "https://files.pythonhosted.org/packages/a7/87/90b358775a3f02765d87655237229ba64a997b87efa8ccaca7dd3e36e7a7/pillow-12.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:d70534cea9e7966169ad29a903b99fc507e932069a881d0965a1a84bb57f6c6d", size = 7033406, upload-time = "2026-01-02T09:11:27.474Z" }, { url = "https://files.pythonhosted.org/packages/5d/cf/881b457eccacac9e5b2ddd97d5071fb6d668307c57cbf4e3b5278e06e536/pillow-12.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:65b80c1ee7e14a87d6a068dd3b0aea268ffcabfe0498d38661b00c5b4b22e74c", size = 2452612, upload-time = "2026-01-02T09:11:29.309Z" }, { url = "https://files.pythonhosted.org/packages/dd/c7/2530a4aa28248623e9d7f27316b42e27c32ec410f695929696f2e0e4a778/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b5dd7cbae20285cdb597b10eb5a2c13aa9de6cde9bb64a3c1317427b1db1ae1", size = 4062543, upload-time = "2026-01-02T09:11:31.566Z" }, { url = "https://files.pythonhosted.org/packages/8f/1f/40b8eae823dc1519b87d53c30ed9ef085506b05281d313031755c1705f73/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:29a4cef9cb672363926f0470afc516dbf7305a14d8c54f7abbb5c199cd8f8179", size = 4138373, upload-time = "2026-01-02T09:11:33.367Z" }, { url = "https://files.pythonhosted.org/packages/d4/77/6fa60634cf06e52139fd0e89e5bbf055e8166c691c42fb162818b7fda31d/pillow-12.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:681088909d7e8fa9e31b9799aaa59ba5234c58e5e4f1951b4c4d1082a2e980e0", size = 3601241, upload-time = "2026-01-02T09:11:35.011Z" }, { url = "https://files.pythonhosted.org/packages/4f/bf/28ab865de622e14b747f0cd7877510848252d950e43002e224fb1c9ababf/pillow-12.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:983976c2ab753166dc66d36af6e8ec15bb511e4a25856e2227e5f7e00a160587", size = 5262410, upload-time = "2026-01-02T09:11:36.682Z" }, { url = "https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac", size = 4657312, upload-time = "2026-01-02T09:11:38.535Z" }, { url = "https://files.pythonhosted.org/packages/1d/fd/f5a0896839762885b3376ff04878f86ab2b097c2f9a9cdccf4eda8ba8dc0/pillow-12.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b7a9d1db5dad90e2991645874f708e87d9a3c370c243c2d7684d28f7e133e6b", size = 6232605, upload-time = "2026-01-02T09:11:40.602Z" }, { url = "https://files.pythonhosted.org/packages/98/aa/938a09d127ac1e70e6ed467bd03834350b33ef646b31edb7452d5de43792/pillow-12.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6258f3260986990ba2fa8a874f8b6e808cf5abb51a94015ca3dc3c68aa4f30ea", size = 8041617, upload-time = "2026-01-02T09:11:42.721Z" }, { url = "https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c", size = 6346509, upload-time = "2026-01-02T09:11:44.955Z" }, { url = "https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc", size = 7038117, upload-time = "2026-01-02T09:11:46.736Z" }, { url = "https://files.pythonhosted.org/packages/c7/a2/d40308cf86eada842ca1f3ffa45d0ca0df7e4ab33c83f81e73f5eaed136d/pillow-12.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:935b9d1aed48fcfb3f838caac506f38e29621b44ccc4f8a64d575cb1b2a88644", size = 6460151, upload-time = "2026-01-02T09:11:48.625Z" }, { url = "https://files.pythonhosted.org/packages/f1/88/f5b058ad6453a085c5266660a1417bdad590199da1b32fb4efcff9d33b05/pillow-12.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5fee4c04aad8932da9f8f710af2c1a15a83582cfb884152a9caa79d4efcdbf9c", size = 7164534, upload-time = "2026-01-02T09:11:50.445Z" }, { url = "https://files.pythonhosted.org/packages/19/ce/c17334caea1db789163b5d855a5735e47995b0b5dc8745e9a3605d5f24c0/pillow-12.1.0-cp313-cp313-win32.whl", hash = "sha256:a786bf667724d84aa29b5db1c61b7bfdde380202aaca12c3461afd6b71743171", size = 6332551, upload-time = "2026-01-02T09:11:52.234Z" }, { url = "https://files.pythonhosted.org/packages/e5/07/74a9d941fa45c90a0d9465098fe1ec85de3e2afbdc15cc4766622d516056/pillow-12.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:461f9dfdafa394c59cd6d818bdfdbab4028b83b02caadaff0ffd433faf4c9a7a", size = 7040087, upload-time = "2026-01-02T09:11:54.822Z" }, { url = "https://files.pythonhosted.org/packages/88/09/c99950c075a0e9053d8e880595926302575bc742b1b47fe1bbcc8d388d50/pillow-12.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:9212d6b86917a2300669511ed094a9406888362e085f2431a7da985a6b124f45", size = 2452470, upload-time = "2026-01-02T09:11:56.522Z" }, { url = "https://files.pythonhosted.org/packages/b5/ba/970b7d85ba01f348dee4d65412476321d40ee04dcb51cd3735b9dc94eb58/pillow-12.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:00162e9ca6d22b7c3ee8e61faa3c3253cd19b6a37f126cad04f2f88b306f557d", size = 5264816, upload-time = "2026-01-02T09:11:58.227Z" }, { url = "https://files.pythonhosted.org/packages/10/60/650f2fb55fdba7a510d836202aa52f0baac633e50ab1cf18415d332188fb/pillow-12.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7d6daa89a00b58c37cb1747ec9fb7ac3bc5ffd5949f5888657dfddde6d1312e0", size = 4660472, upload-time = "2026-01-02T09:12:00.798Z" }, { url = "https://files.pythonhosted.org/packages/2b/c0/5273a99478956a099d533c4f46cbaa19fd69d606624f4334b85e50987a08/pillow-12.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2479c7f02f9d505682dc47df8c0ea1fc5e264c4d1629a5d63fe3e2334b89554", size = 6268974, upload-time = "2026-01-02T09:12:02.572Z" }, { url = "https://files.pythonhosted.org/packages/b4/26/0bf714bc2e73d5267887d47931d53c4ceeceea6978148ed2ab2a4e6463c4/pillow-12.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f188d580bd870cda1e15183790d1cc2fa78f666e76077d103edf048eed9c356e", size = 8073070, upload-time = "2026-01-02T09:12:04.75Z" }, { url = "https://files.pythonhosted.org/packages/43/cf/1ea826200de111a9d65724c54f927f3111dc5ae297f294b370a670c17786/pillow-12.1.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fde7ec5538ab5095cc02df38ee99b0443ff0e1c847a045554cf5f9af1f4aa82", size = 6380176, upload-time = "2026-01-02T09:12:06.626Z" }, { url = "https://files.pythonhosted.org/packages/03/e0/7938dd2b2013373fd85d96e0f38d62b7a5a262af21ac274250c7ca7847c9/pillow-12.1.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ed07dca4a8464bada6139ab38f5382f83e5f111698caf3191cb8dbf27d908b4", size = 7067061, upload-time = "2026-01-02T09:12:08.624Z" }, { url = "https://files.pythonhosted.org/packages/86/ad/a2aa97d37272a929a98437a8c0ac37b3cf012f4f8721e1bd5154699b2518/pillow-12.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f45bd71d1fa5e5749587613037b172e0b3b23159d1c00ef2fc920da6f470e6f0", size = 6491824, upload-time = "2026-01-02T09:12:10.488Z" }, { url = "https://files.pythonhosted.org/packages/a4/44/80e46611b288d51b115826f136fb3465653c28f491068a72d3da49b54cd4/pillow-12.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:277518bf4fe74aa91489e1b20577473b19ee70fb97c374aa50830b279f25841b", size = 7190911, upload-time = "2026-01-02T09:12:12.772Z" }, { url = "https://files.pythonhosted.org/packages/86/77/eacc62356b4cf81abe99ff9dbc7402750044aed02cfd6a503f7c6fc11f3e/pillow-12.1.0-cp313-cp313t-win32.whl", hash = "sha256:7315f9137087c4e0ee73a761b163fc9aa3b19f5f606a7fc08d83fd3e4379af65", size = 6336445, upload-time = "2026-01-02T09:12:14.775Z" }, { url = "https://files.pythonhosted.org/packages/e7/3c/57d81d0b74d218706dafccb87a87ea44262c43eef98eb3b164fd000e0491/pillow-12.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0ddedfaa8b5f0b4ffbc2fa87b556dc59f6bb4ecb14a53b33f9189713ae8053c0", size = 7045354, upload-time = "2026-01-02T09:12:16.599Z" }, { url = "https://files.pythonhosted.org/packages/ac/82/8b9b97bba2e3576a340f93b044a3a3a09841170ab4c1eb0d5c93469fd32f/pillow-12.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:80941e6d573197a0c28f394753de529bb436b1ca990ed6e765cf42426abc39f8", size = 2454547, upload-time = "2026-01-02T09:12:18.704Z" }, { url = "https://files.pythonhosted.org/packages/8c/87/bdf971d8bbcf80a348cc3bacfcb239f5882100fe80534b0ce67a784181d8/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91", size = 4062533, upload-time = "2026-01-02T09:12:20.791Z" }, { url = "https://files.pythonhosted.org/packages/ff/4f/5eb37a681c68d605eb7034c004875c81f86ec9ef51f5be4a63eadd58859a/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796", size = 4138546, upload-time = "2026-01-02T09:12:23.664Z" }, { url = "https://files.pythonhosted.org/packages/11/6d/19a95acb2edbace40dcd582d077b991646b7083c41b98da4ed7555b59733/pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd", size = 3601163, upload-time = "2026-01-02T09:12:26.338Z" }, { url = "https://files.pythonhosted.org/packages/fc/36/2b8138e51cb42e4cc39c3297713455548be855a50558c3ac2beebdc251dd/pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13", size = 5266086, upload-time = "2026-01-02T09:12:28.782Z" }, { url = "https://files.pythonhosted.org/packages/53/4b/649056e4d22e1caa90816bf99cef0884aed607ed38075bd75f091a607a38/pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e", size = 4657344, upload-time = "2026-01-02T09:12:31.117Z" }, { url = "https://files.pythonhosted.org/packages/6c/6b/c5742cea0f1ade0cd61485dc3d81f05261fc2276f537fbdc00802de56779/pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643", size = 6232114, upload-time = "2026-01-02T09:12:32.936Z" }, { url = "https://files.pythonhosted.org/packages/bf/8f/9f521268ce22d63991601aafd3d48d5ff7280a246a1ef62d626d67b44064/pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5", size = 8042708, upload-time = "2026-01-02T09:12:34.78Z" }, { url = "https://files.pythonhosted.org/packages/1a/eb/257f38542893f021502a1bbe0c2e883c90b5cff26cc33b1584a841a06d30/pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de", size = 6347762, upload-time = "2026-01-02T09:12:36.748Z" }, { url = "https://files.pythonhosted.org/packages/c4/5a/8ba375025701c09b309e8d5163c5a4ce0102fa86bbf8800eb0d7ac87bc51/pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9", size = 7039265, upload-time = "2026-01-02T09:12:39.082Z" }, { url = "https://files.pythonhosted.org/packages/cf/dc/cf5e4cdb3db533f539e88a7bbf9f190c64ab8a08a9bc7a4ccf55067872e4/pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a", size = 6462341, upload-time = "2026-01-02T09:12:40.946Z" }, { url = "https://files.pythonhosted.org/packages/d0/47/0291a25ac9550677e22eda48510cfc4fa4b2ef0396448b7fbdc0a6946309/pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a", size = 7165395, upload-time = "2026-01-02T09:12:42.706Z" }, { url = "https://files.pythonhosted.org/packages/4f/4c/e005a59393ec4d9416be06e6b45820403bb946a778e39ecec62f5b2b991e/pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030", size = 6431413, upload-time = "2026-01-02T09:12:44.944Z" }, { url = "https://files.pythonhosted.org/packages/1c/af/f23697f587ac5f9095d67e31b81c95c0249cd461a9798a061ed6709b09b5/pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94", size = 7176779, upload-time = "2026-01-02T09:12:46.727Z" }, { url = "https://files.pythonhosted.org/packages/b3/36/6a51abf8599232f3e9afbd16d52829376a68909fe14efe29084445db4b73/pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4", size = 2543105, upload-time = "2026-01-02T09:12:49.243Z" }, { url = "https://files.pythonhosted.org/packages/82/54/2e1dd20c8749ff225080d6ba465a0cab4387f5db0d1c5fb1439e2d99923f/pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2", size = 5268571, upload-time = "2026-01-02T09:12:51.11Z" }, { url = "https://files.pythonhosted.org/packages/57/61/571163a5ef86ec0cf30d265ac2a70ae6fc9e28413d1dc94fa37fae6bda89/pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61", size = 4660426, upload-time = "2026-01-02T09:12:52.865Z" }, { url = "https://files.pythonhosted.org/packages/5e/e1/53ee5163f794aef1bf84243f755ee6897a92c708505350dd1923f4afec48/pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51", size = 6269908, upload-time = "2026-01-02T09:12:54.884Z" }, { url = "https://files.pythonhosted.org/packages/bc/0b/b4b4106ff0ee1afa1dc599fde6ab230417f800279745124f6c50bcffed8e/pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc", size = 8074733, upload-time = "2026-01-02T09:12:56.802Z" }, { url = "https://files.pythonhosted.org/packages/19/9f/80b411cbac4a732439e629a26ad3ef11907a8c7fc5377b7602f04f6fe4e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14", size = 6381431, upload-time = "2026-01-02T09:12:58.823Z" }, { url = "https://files.pythonhosted.org/packages/8f/b7/d65c45db463b66ecb6abc17c6ba6917a911202a07662247e1355ce1789e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8", size = 7068529, upload-time = "2026-01-02T09:13:00.885Z" }, { url = "https://files.pythonhosted.org/packages/50/96/dfd4cd726b4a45ae6e3c669fc9e49deb2241312605d33aba50499e9d9bd1/pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924", size = 6492981, upload-time = "2026-01-02T09:13:03.314Z" }, { url = "https://files.pythonhosted.org/packages/4d/1c/b5dc52cf713ae46033359c5ca920444f18a6359ce1020dd3e9c553ea5bc6/pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef", size = 7191878, upload-time = "2026-01-02T09:13:05.276Z" }, { url = "https://files.pythonhosted.org/packages/53/26/c4188248bd5edaf543864fe4834aebe9c9cb4968b6f573ce014cc42d0720/pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988", size = 6438703, upload-time = "2026-01-02T09:13:07.491Z" }, { url = "https://files.pythonhosted.org/packages/b8/0e/69ed296de8ea05cb03ee139cee600f424ca166e632567b2d66727f08c7ed/pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6", size = 7182927, upload-time = "2026-01-02T09:13:09.841Z" }, { url = "https://files.pythonhosted.org/packages/fc/f5/68334c015eed9b5cff77814258717dec591ded209ab5b6fb70e2ae873d1d/pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831", size = 2545104, upload-time = "2026-01-02T09:13:12.068Z" }, { url = "https://files.pythonhosted.org/packages/8b/bc/224b1d98cffd7164b14707c91aac83c07b047fbd8f58eba4066a3e53746a/pillow-12.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ca94b6aac0d7af2a10ba08c0f888b3d5114439b6b3ef39968378723622fed377", size = 5228605, upload-time = "2026-01-02T09:13:14.084Z" }, { url = "https://files.pythonhosted.org/packages/0c/ca/49ca7769c4550107de049ed85208240ba0f330b3f2e316f24534795702ce/pillow-12.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:351889afef0f485b84078ea40fe33727a0492b9af3904661b0abbafee0355b72", size = 4622245, upload-time = "2026-01-02T09:13:15.964Z" }, { url = "https://files.pythonhosted.org/packages/73/48/fac807ce82e5955bcc2718642b94b1bd22a82a6d452aea31cbb678cddf12/pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb0984b30e973f7e2884362b7d23d0a348c7143ee559f38ef3eaab640144204c", size = 5247593, upload-time = "2026-01-02T09:13:17.913Z" }, { url = "https://files.pythonhosted.org/packages/d2/95/3e0742fe358c4664aed4fd05d5f5373dcdad0b27af52aa0972568541e3f4/pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:84cabc7095dd535ca934d57e9ce2a72ffd216e435a84acb06b2277b1de2689bd", size = 6989008, upload-time = "2026-01-02T09:13:20.083Z" }, { url = "https://files.pythonhosted.org/packages/5a/74/fe2ac378e4e202e56d50540d92e1ef4ff34ed687f3c60f6a121bcf99437e/pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53d8b764726d3af1a138dd353116f774e3862ec7e3794e0c8781e30db0f35dfc", size = 5313824, upload-time = "2026-01-02T09:13:22.405Z" }, { url = "https://files.pythonhosted.org/packages/f3/77/2a60dee1adee4e2655ac328dd05c02a955c1cd683b9f1b82ec3feb44727c/pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5da841d81b1a05ef940a8567da92decaa15bc4d7dedb540a8c219ad83d91808a", size = 5963278, upload-time = "2026-01-02T09:13:24.706Z" }, { url = "https://files.pythonhosted.org/packages/2d/71/64e9b1c7f04ae0027f788a248e6297d7fcc29571371fe7d45495a78172c0/pillow-12.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:75af0b4c229ac519b155028fa1be632d812a519abba9b46b20e50c6caa184f19", size = 7029809, upload-time = "2026-01-02T09:13:26.541Z" }, ] [[package]] name = "platformdirs" version = "4.4.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, ] [[package]] name = "platformdirs" version = "4.5.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, ] [[package]] name = "plotly" version = "6.5.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "narwhals" }, { name = "packaging" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e3/4f/8a10a9b9f5192cb6fdef62f1d77fa7d834190b2c50c0cd256bd62879212b/plotly-6.5.2.tar.gz", hash = "sha256:7478555be0198562d1435dee4c308268187553cc15516a2f4dd034453699e393", size = 7015695, upload-time = "2026-01-14T21:26:51.222Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8a/67/f95b5460f127840310d2187f916cf0023b5875c0717fdf893f71e1325e87/plotly-6.5.2-py3-none-any.whl", hash = "sha256:91757653bd9c550eeea2fa2404dba6b85d1e366d54804c340b2c874e5a7eb4a4", size = 9895973, upload-time = "2026-01-14T21:26:47.135Z" }, ] [[package]] name = "pluggy" version = "1.6.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] [[package]] name = "py-cpuinfo" version = "9.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/37/a8/d832f7293ebb21690860d2e01d8115e5ff6f2ae8bbdc953f0eb0fa4bd2c7/py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690", size = 104716, upload-time = "2022-10-25T20:38:06.303Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335, upload-time = "2022-10-25T20:38:27.636Z" }, ] [[package]] name = "pycodestyle" version = "2.14.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/11/e0/abfd2a0d2efe47670df87f3e3a0e2edda42f055053c85361f19c0e2c1ca8/pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", size = 39472, upload-time = "2025-06-20T18:49:48.75Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d", size = 31594, upload-time = "2025-06-20T18:49:47.491Z" }, ] [[package]] name = "pycparser" version = "2.23" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, ] [[package]] name = "pycparser" version = "3.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, ] [[package]] name = "pyflakes" version = "3.4.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/45/dc/fd034dc20b4b264b3d015808458391acbf9df40b1e54750ef175d39180b1/pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58", size = 64669, upload-time = "2025-06-20T18:45:27.834Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" }, ] [[package]] name = "pygments" version = "2.19.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, ] [[package]] name = "pyparsing" version = "3.3.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, ] [[package]] name = "pyproject-hooks" version = "1.2.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" }, ] [[package]] name = "pytest" version = "8.4.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "packaging", marker = "python_full_version < '3.10'" }, { name = "pluggy", marker = "python_full_version < '3.10'" }, { name = "pygments", marker = "python_full_version < '3.10'" }, { name = "tomli", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, ] [[package]] name = "pytest" version = "9.0.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "packaging", marker = "python_full_version >= '3.10'" }, { name = "pluggy", marker = "python_full_version >= '3.10'" }, { name = "pygments", marker = "python_full_version >= '3.10'" }, { name = "tomli", marker = "python_full_version == '3.10.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, ] [[package]] name = "pytest-benchmark" version = "5.2.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "py-cpuinfo" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/24/34/9f732b76456d64faffbef6232f1f9dbec7a7c4999ff46282fa418bd1af66/pytest_benchmark-5.2.3.tar.gz", hash = "sha256:deb7317998a23c650fd4ff76e1230066a76cb45dcece0aca5607143c619e7779", size = 341340, upload-time = "2025-11-09T18:48:43.215Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-py3-none-any.whl", hash = "sha256:bc839726ad20e99aaa0d11a127445457b4219bdb9e80a1afc4b51da7f96b0803", size = 45255, upload-time = "2025-11-09T18:48:39.765Z" }, ] [[package]] name = "pytest-cov" version = "7.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, { name = "coverage", version = "7.13.3", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, { name = "pluggy" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, ] [[package]] name = "pytest-xdist" version = "3.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "execnet" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, ] [[package]] name = "python-dateutil" version = "2.9.0.post0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "six" }, ] sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] [[package]] name = "pytokens" version = "0.4.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/42/24/f206113e05cb8ef51b3850e7ef88f20da6f4bf932190ceb48bd3da103e10/pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5", size = 161522, upload-time = "2026-01-30T01:02:50.393Z" }, { url = "https://files.pythonhosted.org/packages/d4/e9/06a6bf1b90c2ed81a9c7d2544232fe5d2891d1cd480e8a1809ca354a8eb2/pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe", size = 246945, upload-time = "2026-01-30T01:02:52.399Z" }, { url = "https://files.pythonhosted.org/packages/69/66/f6fb1007a4c3d8b682d5d65b7c1fb33257587a5f782647091e3408abe0b8/pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c", size = 259525, upload-time = "2026-01-30T01:02:53.737Z" }, { url = "https://files.pythonhosted.org/packages/04/92/086f89b4d622a18418bac74ab5db7f68cf0c21cf7cc92de6c7b919d76c88/pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7", size = 262693, upload-time = "2026-01-30T01:02:54.871Z" }, { url = "https://files.pythonhosted.org/packages/b4/7b/8b31c347cf94a3f900bdde750b2e9131575a61fdb620d3d3c75832262137/pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2", size = 103567, upload-time = "2026-01-30T01:02:56.414Z" }, { url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" }, { url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" }, { url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" }, { url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" }, { url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" }, { url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" }, { url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" }, { url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" }, { url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" }, { url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" }, { url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" }, { url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" }, { url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" }, { url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" }, { url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" }, { url = "https://files.pythonhosted.org/packages/8f/a7/b470f672e6fc5fee0a01d9e75005a0e617e162381974213a945fcd274843/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321", size = 160821, upload-time = "2026-01-30T01:03:19.684Z" }, { url = "https://files.pythonhosted.org/packages/80/98/e83a36fe8d170c911f864bfded690d2542bfcfacb9c649d11a9e6eb9dc41/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa", size = 254263, upload-time = "2026-01-30T01:03:20.834Z" }, { url = "https://files.pythonhosted.org/packages/0f/95/70d7041273890f9f97a24234c00b746e8da86df462620194cef1d411ddeb/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d", size = 268071, upload-time = "2026-01-30T01:03:21.888Z" }, { url = "https://files.pythonhosted.org/packages/da/79/76e6d09ae19c99404656d7db9c35dfd20f2086f3eb6ecb496b5b31163bad/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324", size = 271716, upload-time = "2026-01-30T01:03:23.633Z" }, { url = "https://files.pythonhosted.org/packages/79/37/482e55fa1602e0a7ff012661d8c946bafdc05e480ea5a32f4f7e336d4aa9/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9", size = 104539, upload-time = "2026-01-30T01:03:24.788Z" }, { url = "https://files.pythonhosted.org/packages/30/e8/20e7db907c23f3d63b0be3b8a4fd1927f6da2395f5bcc7f72242bb963dfe/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb", size = 168474, upload-time = "2026-01-30T01:03:26.428Z" }, { url = "https://files.pythonhosted.org/packages/d6/81/88a95ee9fafdd8f5f3452107748fd04c24930d500b9aba9738f3ade642cc/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3", size = 290473, upload-time = "2026-01-30T01:03:27.415Z" }, { url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" }, { url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" }, { url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" }, { url = "https://files.pythonhosted.org/packages/51/2a/f125667ce48105bf1f4e50e03cfa7b24b8c4f47684d7f1cf4dcb6f6b1c15/pytokens-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:34bcc734bd2f2d5fe3b34e7b3c0116bfb2397f2d9666139988e7a3eb5f7400e3", size = 161464, upload-time = "2026-01-30T01:03:39.11Z" }, { url = "https://files.pythonhosted.org/packages/40/df/065a30790a7ca6bb48ad9018dd44668ed9135610ebf56a2a4cb8e513fd5c/pytokens-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:941d4343bf27b605e9213b26bfa1c4bf197c9c599a9627eb7305b0defcfe40c1", size = 246159, upload-time = "2026-01-30T01:03:40.131Z" }, { url = "https://files.pythonhosted.org/packages/a5/1c/fd09976a7e04960dabc07ab0e0072c7813d566ec67d5490a4c600683c158/pytokens-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3ad72b851e781478366288743198101e5eb34a414f1d5627cdd585ca3b25f1db", size = 259120, upload-time = "2026-01-30T01:03:41.233Z" }, { url = "https://files.pythonhosted.org/packages/52/49/59fdc6fc5a390ae9f308eadeb97dfc70fc2d804ffc49dd39fc97604622ec/pytokens-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:682fa37ff4d8e95f7df6fe6fe6a431e8ed8e788023c6bcc0f0880a12eab80ad1", size = 262196, upload-time = "2026-01-30T01:03:42.696Z" }, { url = "https://files.pythonhosted.org/packages/3d/e7/d6734dccf0080e3dc00a55b0827ab5af30c886f8bc127bbc04bc3445daec/pytokens-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:30f51edd9bb7f85c748979384165601d028b84f7bd13fe14d3e065304093916a", size = 103510, upload-time = "2026-01-30T01:03:43.915Z" }, { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, ] [[package]] name = "pytz" version = "2025.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, ] [[package]] name = "pywin32-ctypes" version = "0.2.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, ] [[package]] name = "pyyaml" version = "6.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, { url = "https://files.pythonhosted.org/packages/9f/62/67fc8e68a75f738c9200422bf65693fb79a4cd0dc5b23310e5202e978090/pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da", size = 184450, upload-time = "2025-09-25T21:33:00.618Z" }, { url = "https://files.pythonhosted.org/packages/ae/92/861f152ce87c452b11b9d0977952259aa7df792d71c1053365cc7b09cc08/pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917", size = 174319, upload-time = "2025-09-25T21:33:02.086Z" }, { url = "https://files.pythonhosted.org/packages/d0/cd/f0cfc8c74f8a030017a2b9c771b7f47e5dd702c3e28e5b2071374bda2948/pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9", size = 737631, upload-time = "2025-09-25T21:33:03.25Z" }, { url = "https://files.pythonhosted.org/packages/ef/b2/18f2bd28cd2055a79a46c9b0895c0b3d987ce40ee471cecf58a1a0199805/pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5", size = 836795, upload-time = "2025-09-25T21:33:05.014Z" }, { url = "https://files.pythonhosted.org/packages/73/b9/793686b2d54b531203c160ef12bec60228a0109c79bae6c1277961026770/pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a", size = 750767, upload-time = "2025-09-25T21:33:06.398Z" }, { url = "https://files.pythonhosted.org/packages/a9/86/a137b39a611def2ed78b0e66ce2fe13ee701a07c07aebe55c340ed2a050e/pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926", size = 727982, upload-time = "2025-09-25T21:33:08.708Z" }, { url = "https://files.pythonhosted.org/packages/dd/62/71c27c94f457cf4418ef8ccc71735324c549f7e3ea9d34aba50874563561/pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7", size = 755677, upload-time = "2025-09-25T21:33:09.876Z" }, { url = "https://files.pythonhosted.org/packages/29/3d/6f5e0d58bd924fb0d06c3a6bad00effbdae2de5adb5cda5648006ffbd8d3/pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0", size = 142592, upload-time = "2025-09-25T21:33:10.983Z" }, { url = "https://files.pythonhosted.org/packages/f0/0c/25113e0b5e103d7f1490c0e947e303fe4a696c10b501dea7a9f49d4e876c/pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007", size = 158777, upload-time = "2025-09-25T21:33:15.55Z" }, ] [[package]] name = "readme-renderer" version = "44.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "nh3" }, { name = "pygments" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz", hash = "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", size = 32056, upload-time = "2024-07-08T15:00:57.805Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl", hash = "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", size = 13310, upload-time = "2024-07-08T15:00:56.577Z" }, ] [[package]] name = "requests" version = "2.32.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, { name = "idna" }, { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, ] [[package]] name = "requests-toolbelt" version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "requests" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, ] [[package]] name = "retrying" version = "1.4.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/c8/5a/b17e1e257d3e6f2e7758930e1256832c9ddd576f8631781e6a072914befa/retrying-1.4.2.tar.gz", hash = "sha256:d102e75d53d8d30b88562d45361d6c6c934da06fab31bd81c0420acb97a8ba39", size = 11411, upload-time = "2025-08-03T03:35:25.189Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/67/f3/6cd296376653270ac1b423bb30bd70942d9916b6978c6f40472d6ac038e7/retrying-1.4.2-py3-none-any.whl", hash = "sha256:bbc004aeb542a74f3569aeddf42a2516efefcdaff90df0eb38fbfbf19f179f59", size = 10859, upload-time = "2025-08-03T03:35:23.829Z" }, ] [[package]] name = "rfc3986" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c", size = 49026, upload-time = "2022-01-10T00:52:30.832Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", size = 31326, upload-time = "2022-01-10T00:52:29.594Z" }, ] [[package]] name = "rich" version = "14.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pygments" }, ] sdist = { url = "https://files.pythonhosted.org/packages/74/99/a4cab2acbb884f80e558b0771e97e21e939c5dfb460f488d19df485e8298/rich-14.3.2.tar.gz", hash = "sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8", size = 230143, upload-time = "2026-02-01T16:20:47.908Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ef/45/615f5babd880b4bd7d405cc0dc348234c5ffb6ed1ea33e152ede08b2072d/rich-14.3.2-py3-none-any.whl", hash = "sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69", size = 309963, upload-time = "2026-02-01T16:20:46.078Z" }, ] [[package]] name = "roman-numerals" version = "4.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ae/f9/41dc953bbeb056c17d5f7a519f50fdf010bd0553be2d630bc69d1e022703/roman_numerals-4.1.0.tar.gz", hash = "sha256:1af8b147eb1405d5839e78aeb93131690495fe9da5c91856cb33ad55a7f1e5b2", size = 9077, upload-time = "2025-12-17T18:25:34.381Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/54/6f679c435d28e0a568d8e8a7c0a93a09010818634c3c3907fc98d8983770/roman_numerals-4.1.0-py3-none-any.whl", hash = "sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7", size = 7676, upload-time = "2025-12-17T18:25:33.098Z" }, ] [[package]] name = "scikit-bio" version = "0.7.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "array-api-compat", version = "1.11.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "biom-format", marker = "python_full_version < '3.10'" }, { name = "decorator", marker = "python_full_version < '3.10'" }, { name = "h5py", version = "3.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "natsort", marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "patsy", marker = "python_full_version < '3.10'" }, { name = "requests", marker = "python_full_version < '3.10'" }, { name = "scipy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "statsmodels", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/90/fe/be2d10a390ceea3a3657e77a5ebd16aa167509b10a709125f3a8e4fd663a/scikit_bio-0.7.0.tar.gz", hash = "sha256:771093ebfd154f02b9d88dcf81997737ce804e384bb3ab1cd389dfc60d566d11", size = 5468613, upload-time = "2025-07-16T18:48:05.138Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/59/8b/f90ee0325c7f59573bdf8d4a5a5717ca710f067a081fd46f3768600a200d/scikit_bio-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e857ad41a3915e53a600d51416ffbc945295ccbca6d7e6407533e8494a5baa6f", size = 6243968, upload-time = "2025-07-16T18:47:19.75Z" }, { url = "https://files.pythonhosted.org/packages/57/c6/0864476e63935459eb4d474f210e70ca1b0aa9689bb1beccbeae582587ce/scikit_bio-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9a07476f9cc87b1e2033e74a6f0c00e2c29a05c6cf1985f7a8ec8bcdb13fc6cb", size = 6190829, upload-time = "2025-07-16T18:47:21.29Z" }, { url = "https://files.pythonhosted.org/packages/2c/ca/087675f3fd6608142be8c53e6875a1a730e0fa1250a85421677570445839/scikit_bio-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5dc9cee6a7d1dffde4e560ebf1f77488d896d6398fe4d149031a64738c3d69", size = 9554406, upload-time = "2025-07-16T18:47:22.655Z" }, { url = "https://files.pythonhosted.org/packages/c8/69/da203001d9a0d4f2dc14426617e5eed76c9ff059f6c2a94023bf48e204cb/scikit_bio-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93585d7fb9d2115685065c76edb365de1876eaac81b789528491456fbec8267c", size = 9544353, upload-time = "2025-07-16T18:47:24.308Z" }, { url = "https://files.pythonhosted.org/packages/45/97/3b928b1f075a6033326244e125f0e3a518fe75c17278359d1835ca4ccb24/scikit_bio-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:be10f43ba5d4a86e885931e008ca9e00d76da99b6b0761a136511afc136bcdc9", size = 6183322, upload-time = "2025-07-16T18:47:26.221Z" }, { url = "https://files.pythonhosted.org/packages/3d/66/5f238ff8fa25080d5baf82287297bfd1e6dbeab45ef3ff1b0f6e1a7c017e/scikit_bio-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:836c24609a33a283b5d57efff2647d2967caf20aa3ad77f4ae6cdb5495479efa", size = 6251825, upload-time = "2025-07-16T18:47:27.598Z" }, { url = "https://files.pythonhosted.org/packages/f9/8b/8ef6e40a818067bdaf57fa779eadbc8ef73f333dbd50fb09daeae13de1f2/scikit_bio-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f7ae35711fe6bcf83b43aa7b351c598c32fb2add4f0dc777179696070fed0af6", size = 6197964, upload-time = "2025-07-16T18:47:29.255Z" }, { url = "https://files.pythonhosted.org/packages/f0/66/6cb6e9ba1e67f65a27b34fcd33b457cb0fea73f93dc184ea1bf38562f012/scikit_bio-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18ebd6ad693c2e4714f18d74b487c5ef1e1e2de570074f50e5c4131dc9b92156", size = 9791543, upload-time = "2025-07-16T18:47:30.782Z" }, { url = "https://files.pythonhosted.org/packages/ad/27/e359f131018cf988f1e4f5e7380db7db43ba4202ffc9ba9e8f6cfb1988f5/scikit_bio-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79845e2ae1685250ce6bf538ae8ac06da33e3711b6f65485bd0edef0ccfd818d", size = 9780016, upload-time = "2025-07-16T18:47:33.082Z" }, { url = "https://files.pythonhosted.org/packages/db/99/6b0ce81f81e2cfe06c899455b149e7f8393cd3ba9a8905efe18c36894420/scikit_bio-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:e0fb859a61ad700803a76a9d4dbd49fc5f60f781ab7d897265e2fe7f6c8d112d", size = 6183062, upload-time = "2025-07-16T18:47:36.263Z" }, { url = "https://files.pythonhosted.org/packages/43/9b/bf339d439568a4fa0ab6e7e545c4487b1cf86e6245f98be0d922f4677ddc/scikit_bio-0.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6eb82ad5f4866c35ae3bfe667382f533620eb188f4db68a9213a231299b7d7dc", size = 6256181, upload-time = "2025-07-16T18:47:37.697Z" }, { url = "https://files.pythonhosted.org/packages/1d/e9/7a5dd2e04bbd361907f5a1942fa4b6aeecfa453801f4c047c55b51036df2/scikit_bio-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e6e9504a27be5348bc218db9d6deaf4044c99341c900d2caf17c51023cba2bff", size = 6195263, upload-time = "2025-07-16T18:47:39.336Z" }, { url = "https://files.pythonhosted.org/packages/19/4b/b63123cf09c3375fa90cbfc02febf32cc20429a49c03d71f37febed7c52d/scikit_bio-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:366a5840796c9ea4d1cc9e77557c89bbd72946834a7e35bb2e9d05940712b993", size = 9711028, upload-time = "2025-07-16T18:47:40.98Z" }, { url = "https://files.pythonhosted.org/packages/f5/02/b178ca48305a230e080732dd02233e0824b1a9b41b273acf2444de116be2/scikit_bio-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3214c2720732c5a467c1b77d36dab70e91a18ac50d4dbe444460838fad907bb9", size = 9709823, upload-time = "2025-07-16T18:47:42.708Z" }, { url = "https://files.pythonhosted.org/packages/5f/a8/199cafe05bb77bf274f0a3db8f5199f4b2966db37589f9e5ec6a212c0b9c/scikit_bio-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:624cff62237f771ffebab63cf0df1605c59aeab35a334bb1feb5726b5b453f98", size = 6193245, upload-time = "2025-07-16T18:47:44.723Z" }, { url = "https://files.pythonhosted.org/packages/d4/31/b943fcf7d4579b4751002ad9a48e62e9f0c7db542dd440f7e3e82f50f58b/scikit_bio-0.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b874e9661000057c92673b0d85fa6e3508644843e3192969cea7c0916acad787", size = 6248217, upload-time = "2025-07-16T18:47:46.201Z" }, { url = "https://files.pythonhosted.org/packages/e7/af/5f3452f0dce0f0a3c7ccb9f067e410b50a8d188c4fb56426f8785317333d/scikit_bio-0.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:77b57b51d1ff844165244d7834862d10a8bfa59866fd24cabfaccac9ad55661a", size = 6188166, upload-time = "2025-07-16T18:47:47.956Z" }, { url = "https://files.pythonhosted.org/packages/7d/20/ef1d2a8accb946cc31b5b987a46d197f69d1e89bab76b5e9cb4235a355f9/scikit_bio-0.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60c00fc17e7fd9f639af889759dd5da627e0efc6c96398bb00d79712756d6fda", size = 9666693, upload-time = "2025-07-16T18:47:51.615Z" }, { url = "https://files.pythonhosted.org/packages/1c/46/3f05eedb58e13c21f5ab7496e9735da2f008aa66038b268ea46138a3e48d/scikit_bio-0.7.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbc3ab7617eaef5d48b7de2582a9bc8d62fcbdddaa106b8dc61c42a4b0b1effd", size = 9669221, upload-time = "2025-07-16T18:47:53.286Z" }, { url = "https://files.pythonhosted.org/packages/40/e9/2f7d72ef933e9328b929295ada98ad2c5fbdc5b3c6bd2f4d886f14d4f90a/scikit_bio-0.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:d9ac56afe6119668469aafd96027ed2dff7db17d37475e63c5f291a371dd9363", size = 6190861, upload-time = "2025-07-16T18:47:55.227Z" }, { url = "https://files.pythonhosted.org/packages/b5/fa/3a7770c445111c6b957aba701887f22506faef8145965a6b9d2816cfd896/scikit_bio-0.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8f83a75c5fbb123e5d5f0fd36b6655c03b96cd1d91e59362dcee55e4bfa44f0b", size = 6248340, upload-time = "2025-07-16T18:47:56.906Z" }, { url = "https://files.pythonhosted.org/packages/4e/07/e2a29ccbb31208c98ff2c7b61b00614885f781474891ebf249d85495e238/scikit_bio-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f81f5ed06d966bdddc67a1724c843e3e1462d342173a3807641ac21cb6e3aee3", size = 6195259, upload-time = "2025-07-16T18:47:58.58Z" }, { url = "https://files.pythonhosted.org/packages/89/15/829f7da8e5083f4d2e3dd1ef24faa6b32da2bf492547bd6d385e92fda127/scikit_bio-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25426738c7e5dec96716c0fc931604aed3893f106c2ae5ecc3c4e5c070462b1a", size = 9552546, upload-time = "2025-07-16T18:48:00.374Z" }, { url = "https://files.pythonhosted.org/packages/4a/34/687f9e4dc73e39a56277e2aa900577fccb3c99ef28a5acc5fc258028e2ac/scikit_bio-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43c0d63656f897fc947dc91feccf472c989121b80827d3c31e5b44eab64c8027", size = 9508572, upload-time = "2025-07-16T18:48:02.182Z" }, { url = "https://files.pythonhosted.org/packages/6c/a5/75fd40c8bf70836216fffe57bdd80c78959d5cc21c23927ada892b246f3d/scikit_bio-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:d76bede1883fde05726d2f90726e020f2dc37d2313c9c61566608f0012df77be", size = 6187164, upload-time = "2025-07-16T18:48:03.957Z" }, ] [[package]] name = "scikit-bio" version = "0.7.1.post1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "array-api-compat", version = "1.13.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "biom-format", marker = "python_full_version >= '3.10'" }, { name = "decorator", marker = "python_full_version >= '3.10'" }, { name = "h5py", version = "3.15.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "natsort", marker = "python_full_version >= '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "pandas", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "patsy", marker = "python_full_version >= '3.10'" }, { name = "requests", marker = "python_full_version >= '3.10'" }, { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "scipy", version = "1.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "statsmodels", marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/08/d2/7c8d097db3f158cf2f346cc2586943ee3d85263177ddacc7d663d9f95131/scikit_bio-0.7.1.post1.tar.gz", hash = "sha256:cbd92418b711492837ea5ca3a088b540e725bea53a45bc2332b2631afd539f95", size = 5665966, upload-time = "2025-10-30T19:19:43.042Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/91/38/5fda6a940bb367ca083acaf393cf4f8d4ef9b9fee59a543db7e84af4dfcc/scikit_bio-0.7.1.post1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:68d4bd49c405d1cda4337899b620027ca6090d011ca900576df70ce97d5febfa", size = 6528024, upload-time = "2025-10-30T19:18:50.83Z" }, { url = "https://files.pythonhosted.org/packages/21/c4/43dc66de1d6699014238928eae7d183e27e5f0838dbaa917711cae95526b/scikit_bio-0.7.1.post1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1b141af25dd831d729a99dcfbf9410bf395bb4f2a10bd1f8d33390383bba6d3e", size = 6533109, upload-time = "2025-10-30T19:18:52.921Z" }, { url = "https://files.pythonhosted.org/packages/b1/e7/c0c3a2b93ecc8a076ec0b526a8596b14d8c97d9d669968ba27e0eb2738a9/scikit_bio-0.7.1.post1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6294f4d24cd5916f45a99291ca197497ff63e3068759a5d05b9141135c760d", size = 10774670, upload-time = "2025-10-30T19:18:54.422Z" }, { url = "https://files.pythonhosted.org/packages/ce/84/618d9eefeb933f0cb080e4d0ce6b561002f7967057a24e52278db067282f/scikit_bio-0.7.1.post1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:683fed27960fb805efc0a2560983035c6e8757a10c033a496c4db46c1f7d207e", size = 10800662, upload-time = "2025-10-30T19:18:57.827Z" }, { url = "https://files.pythonhosted.org/packages/28/44/570eb1a2bda69f03255b4129521ba4e5e045b590855fcd65dec269ef8ee4/scikit_bio-0.7.1.post1-cp310-cp310-win_amd64.whl", hash = "sha256:dd0073860b29561480fc2ef125019e349454497e18dce299d2cbbe93beccd7c6", size = 6447498, upload-time = "2025-10-30T19:18:59.923Z" }, { url = "https://files.pythonhosted.org/packages/e6/91/eb2a2eed239612ec22d69f948cd02a90a86ec0a3eb0ddf468c66e54a8609/scikit_bio-0.7.1.post1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d0593aa776942aaf27431835698b415d1e9f13cd8cd118f412b8ff4cbc5b8", size = 6537083, upload-time = "2025-10-30T19:19:02.16Z" }, { url = "https://files.pythonhosted.org/packages/74/c2/de147eef13bfcc19cb086061ef52a6dcb33613b535c5b8b903207a18b1f2/scikit_bio-0.7.1.post1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:22c9d1d48fc037afe2bde68c7db479df177564a17781377e0e0c4a613b5283b9", size = 6535208, upload-time = "2025-10-30T19:19:03.481Z" }, { url = "https://files.pythonhosted.org/packages/72/2b/68f1ef336a4285b5898a2910d65ebc3f329035228d0fdabce0f1775402b4/scikit_bio-0.7.1.post1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b78d6a0b52f0acc4a28aa3a5a06b8846e147b8404d84d08e18125828f77a55e", size = 11067343, upload-time = "2025-10-30T19:19:04.995Z" }, { url = "https://files.pythonhosted.org/packages/5c/35/b100d2e6d5e0fd4de4af4c3be9e70c291702afb314b549374331df4f99e4/scikit_bio-0.7.1.post1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddf2f40b99eea14ecd3196e27e1d9f0b7071856edf8782e1b31fcd39b28c8112", size = 11085265, upload-time = "2025-10-30T19:19:07.205Z" }, { url = "https://files.pythonhosted.org/packages/5c/60/9896f3378ab768af4eb56749bca7eb229be1ef76f6417506fb2437330ed7/scikit_bio-0.7.1.post1-cp311-cp311-win_amd64.whl", hash = "sha256:4689b8e47ecd235c71a883c1cbcaad48b51c8c2676fd6d11d4e4134e1bf675fb", size = 6448277, upload-time = "2025-10-30T19:19:09.266Z" }, { url = "https://files.pythonhosted.org/packages/9a/9e/1709b0eb124cddba864b855df6c428e96c224d99ffb5d008329a5d8caec4/scikit_bio-0.7.1.post1-cp311-cp311-win_arm64.whl", hash = "sha256:593186762927e6248bba3fa20e2656be61c1e3210b0ddefe1428d4e8e01b80fd", size = 6342074, upload-time = "2025-10-30T19:19:10.529Z" }, { url = "https://files.pythonhosted.org/packages/ac/4e/df25894303407646477823d37409b88e9589a64432bcfd97b5c69e290f01/scikit_bio-0.7.1.post1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b445ed12f486d06fab36c86d1c858b4baa3978c33b7a4f76d967f6ffb7e1375", size = 6539786, upload-time = "2025-10-30T19:19:11.918Z" }, { url = "https://files.pythonhosted.org/packages/a9/e4/f35635cdf167a0335cae98d6b89da08de4f89c80f740304ba642030761ad/scikit_bio-0.7.1.post1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0373e14eb37403cfb64de65a047ac11b91b8d83534e98fe9e4404c3d387a25e9", size = 6544189, upload-time = "2025-10-30T19:19:13.261Z" }, { url = "https://files.pythonhosted.org/packages/cc/5a/25e6fa4db4e0cdbaecf395af06f8d95830ad1e57b0daf176bebe1c957ad6/scikit_bio-0.7.1.post1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd873c615777ab28c448921fc98639897c37ea58412fd704cfe1a96b9bedd0f6", size = 10887784, upload-time = "2025-10-30T19:19:14.829Z" }, { url = "https://files.pythonhosted.org/packages/78/fd/45a25d9c4ff917582f951f08c2f06ab719802f3d4f9a6dcb4fc291c763f7/scikit_bio-0.7.1.post1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb724ab26b393a074cbb5e9bb47277284a1dc68e70684147a6d0a3ea2d822cdd", size = 10946298, upload-time = "2025-10-30T19:19:17.003Z" }, { url = "https://files.pythonhosted.org/packages/ad/cd/cea3b6fbe18cd94226e38196e71b4bdb57b187722ade8df63b38a0c15560/scikit_bio-0.7.1.post1-cp312-cp312-win_amd64.whl", hash = "sha256:5e93c64077e815752d7c27b5117ac498b3847a4cf3332aa71a8fcf601ed0fe86", size = 6459262, upload-time = "2025-10-30T19:19:19.349Z" }, { url = "https://files.pythonhosted.org/packages/d9/61/8dcdd863634f77db5dac566cdd4fe09a01786e42f0ccf06d32e91f68f5a8/scikit_bio-0.7.1.post1-cp312-cp312-win_arm64.whl", hash = "sha256:d86eaeb7b1e101d1d8fa79de2a23ef76697e2252f945884f5ac08f829f0fe1f9", size = 6343827, upload-time = "2025-10-30T19:19:20.77Z" }, { url = "https://files.pythonhosted.org/packages/fd/96/a8c8bd5cddbc0159f67b8efe399b4f786887608292edd90e57b669dfb58c/scikit_bio-0.7.1.post1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8269b297ade34ed58939c1f8d5b9506071d2160ce83277f29b938fdad29fbc40", size = 6532159, upload-time = "2025-10-30T19:19:22.223Z" }, { url = "https://files.pythonhosted.org/packages/8b/e3/679a58a84b5c863b27ba130f3691083f6bb71c3f3142a20a1ebce5f3988f/scikit_bio-0.7.1.post1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6d478ed7858e33d7af9a4bf9c267d46e46eae8194c8ed83fc62f23607bf660f1", size = 6536898, upload-time = "2025-10-30T19:19:24.037Z" }, { url = "https://files.pythonhosted.org/packages/e7/65/c776d8d32e69d2074bc2eb8c46c7807e1ac572548da9fe950eac249ede4f/scikit_bio-0.7.1.post1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bccf748c80dc9779ed93522513c842473de460e58e76bfa128ddf3cfdea2f604", size = 10848935, upload-time = "2025-10-30T19:19:26.074Z" }, { url = "https://files.pythonhosted.org/packages/f4/e0/fc497c545850e2e3683e8a30139dccfff0616f02658dfbd6b5f92bf2499d/scikit_bio-0.7.1.post1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ebdd76585f65a3e28f90833c3e4f5fc8241b36c1378bc65abad3330142fb504", size = 10899404, upload-time = "2025-10-30T19:19:27.821Z" }, { url = "https://files.pythonhosted.org/packages/71/5c/fb855a6f767c88c82bb28ec125457ea8d654b3187aea49bd2696df923513/scikit_bio-0.7.1.post1-cp313-cp313-win_amd64.whl", hash = "sha256:9ec664c8a9da363941570e0a2fc7813d57530b7de2ea1dba71487daaef3be9af", size = 6456865, upload-time = "2025-10-30T19:19:29.613Z" }, { url = "https://files.pythonhosted.org/packages/84/3d/f7549b21f314b2a23f5a6148e0a17c88d8170bd1599ae8c735f492a01ce5/scikit_bio-0.7.1.post1-cp313-cp313-win_arm64.whl", hash = "sha256:d8890f3f39d12f2fc2cbce2c8b84081d6ccdadf87c870b80e5bf45826b7262b8", size = 6342824, upload-time = "2025-10-30T19:19:31.184Z" }, { url = "https://files.pythonhosted.org/packages/29/7f/11d1c5e10001870e42f91e0236d6bb3fabd1bd0f6d43eb149fe74596e951/scikit_bio-0.7.1.post1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1bdb3279fa601edc31ecd0b9635ec7dfac594a441124fffafca5abaa3b68ad6c", size = 6530286, upload-time = "2025-10-30T19:19:32.857Z" }, { url = "https://files.pythonhosted.org/packages/6b/73/60707444c38f8a791046d16c0f54dc4fa98e4d34c01e38e306799a2f0754/scikit_bio-0.7.1.post1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bbd0f0d7928e5f65774b3b63d5581f813989d2f900892864d49aed24cbf6f265", size = 6543599, upload-time = "2025-10-30T19:19:34.188Z" }, { url = "https://files.pythonhosted.org/packages/ee/e4/5a06cce37472df5503192435637a51ee3a658e4ca7a7c2671f0a4f32737d/scikit_bio-0.7.1.post1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4eca29267f503d9900350013f786d04710f81d0f3254e4a7b6121892ddd202", size = 10855453, upload-time = "2025-10-30T19:19:35.678Z" }, { url = "https://files.pythonhosted.org/packages/d8/6d/5700bb155429a6aa74ad8ef94a905f52c901fd6de2c7d03b99222e77f1bf/scikit_bio-0.7.1.post1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:286b1f9d39cd23253bc94b7e510bfabc993dcf8be8062b3426afd14e3e0756cc", size = 10849124, upload-time = "2025-10-30T19:19:37.452Z" }, { url = "https://files.pythonhosted.org/packages/f4/39/05c6f52c53f16b00003099db1ad9b51f037a90382fe7e31c96376896efdc/scikit_bio-0.7.1.post1-cp314-cp314-win_amd64.whl", hash = "sha256:58b7030cfebd3af7444d8f7c1dd2184d296c5f94ba0163ca3e4b62f3e8dd0035", size = 6453898, upload-time = "2025-10-30T19:19:39.581Z" }, { url = "https://files.pythonhosted.org/packages/ff/95/ff64d260b2dd308338842287b0a165eb3b97e123ead5ff5206862475f812/scikit_bio-0.7.1.post1-cp314-cp314-win_arm64.whl", hash = "sha256:56e63b87fc01f72f247de616069ecd1142cfca5e1c10c2f72611703981841c41", size = 6342299, upload-time = "2025-10-30T19:19:41.73Z" }, ] [[package]] name = "scipy" version = "1.13.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ae/00/48c2f661e2816ccf2ecd77982f6605b2950afe60f60a52b4cbbc2504aa8f/scipy-1.13.1.tar.gz", hash = "sha256:095a87a0312b08dfd6a6155cbbd310a8c51800fc931b8c0b84003014b874ed3c", size = 57210720, upload-time = "2024-05-23T03:29:26.079Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/33/59/41b2529908c002ade869623b87eecff3e11e3ce62e996d0bdcb536984187/scipy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:20335853b85e9a49ff7572ab453794298bcf0354d8068c5f6775a0eabf350aca", size = 39328076, upload-time = "2024-05-23T03:19:01.687Z" }, { url = "https://files.pythonhosted.org/packages/d5/33/f1307601f492f764062ce7dd471a14750f3360e33cd0f8c614dae208492c/scipy-1.13.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d605e9c23906d1994f55ace80e0125c587f96c020037ea6aa98d01b4bd2e222f", size = 30306232, upload-time = "2024-05-23T03:19:09.089Z" }, { url = "https://files.pythonhosted.org/packages/c0/66/9cd4f501dd5ea03e4a4572ecd874936d0da296bd04d1c45ae1a4a75d9c3a/scipy-1.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfa31f1def5c819b19ecc3a8b52d28ffdcc7ed52bb20c9a7589669dd3c250989", size = 33743202, upload-time = "2024-05-23T03:19:15.138Z" }, { url = "https://files.pythonhosted.org/packages/a3/ba/7255e5dc82a65adbe83771c72f384d99c43063648456796436c9a5585ec3/scipy-1.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26264b282b9da0952a024ae34710c2aff7d27480ee91a2e82b7b7073c24722f", size = 38577335, upload-time = "2024-05-23T03:19:21.984Z" }, { url = "https://files.pythonhosted.org/packages/49/a5/bb9ded8326e9f0cdfdc412eeda1054b914dfea952bda2097d174f8832cc0/scipy-1.13.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eccfa1906eacc02de42d70ef4aecea45415f5be17e72b61bafcfd329bdc52e94", size = 38820728, upload-time = "2024-05-23T03:19:28.225Z" }, { url = "https://files.pythonhosted.org/packages/12/30/df7a8fcc08f9b4a83f5f27cfaaa7d43f9a2d2ad0b6562cced433e5b04e31/scipy-1.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:2831f0dc9c5ea9edd6e51e6e769b655f08ec6db6e2e10f86ef39bd32eb11da54", size = 46210588, upload-time = "2024-05-23T03:19:35.661Z" }, { url = "https://files.pythonhosted.org/packages/b4/15/4a4bb1b15bbd2cd2786c4f46e76b871b28799b67891f23f455323a0cdcfb/scipy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:27e52b09c0d3a1d5b63e1105f24177e544a222b43611aaf5bc44d4a0979e32f9", size = 39333805, upload-time = "2024-05-23T03:19:43.081Z" }, { url = "https://files.pythonhosted.org/packages/ba/92/42476de1af309c27710004f5cdebc27bec62c204db42e05b23a302cb0c9a/scipy-1.13.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:54f430b00f0133e2224c3ba42b805bfd0086fe488835effa33fa291561932326", size = 30317687, upload-time = "2024-05-23T03:19:48.799Z" }, { url = "https://files.pythonhosted.org/packages/80/ba/8be64fe225360a4beb6840f3cbee494c107c0887f33350d0a47d55400b01/scipy-1.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e89369d27f9e7b0884ae559a3a956e77c02114cc60a6058b4e5011572eea9299", size = 33694638, upload-time = "2024-05-23T03:19:55.104Z" }, { url = "https://files.pythonhosted.org/packages/36/07/035d22ff9795129c5a847c64cb43c1fa9188826b59344fee28a3ab02e283/scipy-1.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a78b4b3345f1b6f68a763c6e25c0c9a23a9fd0f39f5f3d200efe8feda560a5fa", size = 38569931, upload-time = "2024-05-23T03:20:01.82Z" }, { url = "https://files.pythonhosted.org/packages/d9/10/f9b43de37e5ed91facc0cfff31d45ed0104f359e4f9a68416cbf4e790241/scipy-1.13.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45484bee6d65633752c490404513b9ef02475b4284c4cfab0ef946def50b3f59", size = 38838145, upload-time = "2024-05-23T03:20:09.173Z" }, { url = "https://files.pythonhosted.org/packages/4a/48/4513a1a5623a23e95f94abd675ed91cfb19989c58e9f6f7d03990f6caf3d/scipy-1.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:5713f62f781eebd8d597eb3f88b8bf9274e79eeabf63afb4a737abc6c84ad37b", size = 46196227, upload-time = "2024-05-23T03:20:16.433Z" }, { url = "https://files.pythonhosted.org/packages/f2/7b/fb6b46fbee30fc7051913068758414f2721003a89dd9a707ad49174e3843/scipy-1.13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5d72782f39716b2b3509cd7c33cdc08c96f2f4d2b06d51e52fb45a19ca0c86a1", size = 39357301, upload-time = "2024-05-23T03:20:23.538Z" }, { url = "https://files.pythonhosted.org/packages/dc/5a/2043a3bde1443d94014aaa41e0b50c39d046dda8360abd3b2a1d3f79907d/scipy-1.13.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:017367484ce5498445aade74b1d5ab377acdc65e27095155e448c88497755a5d", size = 30363348, upload-time = "2024-05-23T03:20:29.885Z" }, { url = "https://files.pythonhosted.org/packages/e7/cb/26e4a47364bbfdb3b7fb3363be6d8a1c543bcd70a7753ab397350f5f189a/scipy-1.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:949ae67db5fa78a86e8fa644b9a6b07252f449dcf74247108c50e1d20d2b4627", size = 33406062, upload-time = "2024-05-23T03:20:36.012Z" }, { url = "https://files.pythonhosted.org/packages/88/ab/6ecdc526d509d33814835447bbbeedbebdec7cca46ef495a61b00a35b4bf/scipy-1.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3ade0e53bc1f21358aa74ff4830235d716211d7d077e340c7349bc3542e884", size = 38218311, upload-time = "2024-05-23T03:20:42.086Z" }, { url = "https://files.pythonhosted.org/packages/0b/00/9f54554f0f8318100a71515122d8f4f503b1a2c4b4cfab3b4b68c0eb08fa/scipy-1.13.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ac65fb503dad64218c228e2dc2d0a0193f7904747db43014645ae139c8fad16", size = 38442493, upload-time = "2024-05-23T03:20:48.292Z" }, { url = "https://files.pythonhosted.org/packages/3e/df/963384e90733e08eac978cd103c34df181d1fec424de383cdc443f418dd4/scipy-1.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:cdd7dacfb95fea358916410ec61bbc20440f7860333aee6d882bb8046264e949", size = 45910955, upload-time = "2024-05-23T03:20:55.091Z" }, { url = "https://files.pythonhosted.org/packages/7f/29/c2ea58c9731b9ecb30b6738113a95d147e83922986b34c685b8f6eefde21/scipy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:436bbb42a94a8aeef855d755ce5a465479c721e9d684de76bf61a62e7c2b81d5", size = 39352927, upload-time = "2024-05-23T03:21:01.95Z" }, { url = "https://files.pythonhosted.org/packages/5c/c0/e71b94b20ccf9effb38d7147c0064c08c622309fd487b1b677771a97d18c/scipy-1.13.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8335549ebbca860c52bf3d02f80784e91a004b71b059e3eea9678ba994796a24", size = 30324538, upload-time = "2024-05-23T03:21:07.634Z" }, { url = "https://files.pythonhosted.org/packages/6d/0f/aaa55b06d474817cea311e7b10aab2ea1fd5d43bc6a2861ccc9caec9f418/scipy-1.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d533654b7d221a6a97304ab63c41c96473ff04459e404b83275b60aa8f4b7004", size = 33732190, upload-time = "2024-05-23T03:21:14.41Z" }, { url = "https://files.pythonhosted.org/packages/35/f5/d0ad1a96f80962ba65e2ce1de6a1e59edecd1f0a7b55990ed208848012e0/scipy-1.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637e98dcf185ba7f8e663e122ebf908c4702420477ae52a04f9908707456ba4d", size = 38612244, upload-time = "2024-05-23T03:21:21.827Z" }, { url = "https://files.pythonhosted.org/packages/8d/02/1165905f14962174e6569076bcc3315809ae1291ed14de6448cc151eedfd/scipy-1.13.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a014c2b3697bde71724244f63de2476925596c24285c7a637364761f8710891c", size = 38845637, upload-time = "2024-05-23T03:21:28.729Z" }, { url = "https://files.pythonhosted.org/packages/3e/77/dab54fe647a08ee4253963bcd8f9cf17509c8ca64d6335141422fe2e2114/scipy-1.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:392e4ec766654852c25ebad4f64e4e584cf19820b980bc04960bca0b0cd6eaa2", size = 46227440, upload-time = "2024-05-23T03:21:35.888Z" }, ] [[package]] name = "scipy" version = "1.15.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", ] dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/78/2f/4966032c5f8cc7e6a60f1b2e0ad686293b9474b65246b0c642e3ef3badd0/scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c", size = 38702770, upload-time = "2025-05-08T16:04:20.849Z" }, { url = "https://files.pythonhosted.org/packages/a0/6e/0c3bf90fae0e910c274db43304ebe25a6b391327f3f10b5dcc638c090795/scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253", size = 30094511, upload-time = "2025-05-08T16:04:27.103Z" }, { url = "https://files.pythonhosted.org/packages/ea/b1/4deb37252311c1acff7f101f6453f0440794f51b6eacb1aad4459a134081/scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f", size = 22368151, upload-time = "2025-05-08T16:04:31.731Z" }, { url = "https://files.pythonhosted.org/packages/38/7d/f457626e3cd3c29b3a49ca115a304cebb8cc6f31b04678f03b216899d3c6/scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92", size = 25121732, upload-time = "2025-05-08T16:04:36.596Z" }, { url = "https://files.pythonhosted.org/packages/db/0a/92b1de4a7adc7a15dcf5bddc6e191f6f29ee663b30511ce20467ef9b82e4/scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82", size = 35547617, upload-time = "2025-05-08T16:04:43.546Z" }, { url = "https://files.pythonhosted.org/packages/8e/6d/41991e503e51fc1134502694c5fa7a1671501a17ffa12716a4a9151af3df/scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40", size = 37662964, upload-time = "2025-05-08T16:04:49.431Z" }, { url = "https://files.pythonhosted.org/packages/25/e1/3df8f83cb15f3500478c889be8fb18700813b95e9e087328230b98d547ff/scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e", size = 37238749, upload-time = "2025-05-08T16:04:55.215Z" }, { url = "https://files.pythonhosted.org/packages/93/3e/b3257cf446f2a3533ed7809757039016b74cd6f38271de91682aa844cfc5/scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c", size = 40022383, upload-time = "2025-05-08T16:05:01.914Z" }, { url = "https://files.pythonhosted.org/packages/d1/84/55bc4881973d3f79b479a5a2e2df61c8c9a04fcb986a213ac9c02cfb659b/scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13", size = 41259201, upload-time = "2025-05-08T16:05:08.166Z" }, { url = "https://files.pythonhosted.org/packages/96/ab/5cc9f80f28f6a7dff646c5756e559823614a42b1939d86dd0ed550470210/scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b", size = 38714255, upload-time = "2025-05-08T16:05:14.596Z" }, { url = "https://files.pythonhosted.org/packages/4a/4a/66ba30abe5ad1a3ad15bfb0b59d22174012e8056ff448cb1644deccbfed2/scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba", size = 30111035, upload-time = "2025-05-08T16:05:20.152Z" }, { url = "https://files.pythonhosted.org/packages/4b/fa/a7e5b95afd80d24313307f03624acc65801846fa75599034f8ceb9e2cbf6/scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65", size = 22384499, upload-time = "2025-05-08T16:05:24.494Z" }, { url = "https://files.pythonhosted.org/packages/17/99/f3aaddccf3588bb4aea70ba35328c204cadd89517a1612ecfda5b2dd9d7a/scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1", size = 25152602, upload-time = "2025-05-08T16:05:29.313Z" }, { url = "https://files.pythonhosted.org/packages/56/c5/1032cdb565f146109212153339f9cb8b993701e9fe56b1c97699eee12586/scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889", size = 35503415, upload-time = "2025-05-08T16:05:34.699Z" }, { url = "https://files.pythonhosted.org/packages/bd/37/89f19c8c05505d0601ed5650156e50eb881ae3918786c8fd7262b4ee66d3/scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982", size = 37652622, upload-time = "2025-05-08T16:05:40.762Z" }, { url = "https://files.pythonhosted.org/packages/7e/31/be59513aa9695519b18e1851bb9e487de66f2d31f835201f1b42f5d4d475/scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9", size = 37244796, upload-time = "2025-05-08T16:05:48.119Z" }, { url = "https://files.pythonhosted.org/packages/10/c0/4f5f3eeccc235632aab79b27a74a9130c6c35df358129f7ac8b29f562ac7/scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594", size = 40047684, upload-time = "2025-05-08T16:05:54.22Z" }, { url = "https://files.pythonhosted.org/packages/ab/a7/0ddaf514ce8a8714f6ed243a2b391b41dbb65251affe21ee3077ec45ea9a/scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb", size = 41246504, upload-time = "2025-05-08T16:06:00.437Z" }, { url = "https://files.pythonhosted.org/packages/37/4b/683aa044c4162e10ed7a7ea30527f2cbd92e6999c10a8ed8edb253836e9c/scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019", size = 38766735, upload-time = "2025-05-08T16:06:06.471Z" }, { url = "https://files.pythonhosted.org/packages/7b/7e/f30be3d03de07f25dc0ec926d1681fed5c732d759ac8f51079708c79e680/scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6", size = 30173284, upload-time = "2025-05-08T16:06:11.686Z" }, { url = "https://files.pythonhosted.org/packages/07/9c/0ddb0d0abdabe0d181c1793db51f02cd59e4901da6f9f7848e1f96759f0d/scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477", size = 22446958, upload-time = "2025-05-08T16:06:15.97Z" }, { url = "https://files.pythonhosted.org/packages/af/43/0bce905a965f36c58ff80d8bea33f1f9351b05fad4beaad4eae34699b7a1/scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c", size = 25242454, upload-time = "2025-05-08T16:06:20.394Z" }, { url = "https://files.pythonhosted.org/packages/56/30/a6f08f84ee5b7b28b4c597aca4cbe545535c39fe911845a96414700b64ba/scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45", size = 35210199, upload-time = "2025-05-08T16:06:26.159Z" }, { url = "https://files.pythonhosted.org/packages/0b/1f/03f52c282437a168ee2c7c14a1a0d0781a9a4a8962d84ac05c06b4c5b555/scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49", size = 37309455, upload-time = "2025-05-08T16:06:32.778Z" }, { url = "https://files.pythonhosted.org/packages/89/b1/fbb53137f42c4bf630b1ffdfc2151a62d1d1b903b249f030d2b1c0280af8/scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e", size = 36885140, upload-time = "2025-05-08T16:06:39.249Z" }, { url = "https://files.pythonhosted.org/packages/2e/2e/025e39e339f5090df1ff266d021892694dbb7e63568edcfe43f892fa381d/scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539", size = 39710549, upload-time = "2025-05-08T16:06:45.729Z" }, { url = "https://files.pythonhosted.org/packages/e6/eb/3bf6ea8ab7f1503dca3a10df2e4b9c3f6b3316df07f6c0ded94b281c7101/scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed", size = 40966184, upload-time = "2025-05-08T16:06:52.623Z" }, { url = "https://files.pythonhosted.org/packages/73/18/ec27848c9baae6e0d6573eda6e01a602e5649ee72c27c3a8aad673ebecfd/scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759", size = 38728256, upload-time = "2025-05-08T16:06:58.696Z" }, { url = "https://files.pythonhosted.org/packages/74/cd/1aef2184948728b4b6e21267d53b3339762c285a46a274ebb7863c9e4742/scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62", size = 30109540, upload-time = "2025-05-08T16:07:04.209Z" }, { url = "https://files.pythonhosted.org/packages/5b/d8/59e452c0a255ec352bd0a833537a3bc1bfb679944c4938ab375b0a6b3a3e/scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb", size = 22383115, upload-time = "2025-05-08T16:07:08.998Z" }, { url = "https://files.pythonhosted.org/packages/08/f5/456f56bbbfccf696263b47095291040655e3cbaf05d063bdc7c7517f32ac/scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730", size = 25163884, upload-time = "2025-05-08T16:07:14.091Z" }, { url = "https://files.pythonhosted.org/packages/a2/66/a9618b6a435a0f0c0b8a6d0a2efb32d4ec5a85f023c2b79d39512040355b/scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825", size = 35174018, upload-time = "2025-05-08T16:07:19.427Z" }, { url = "https://files.pythonhosted.org/packages/b5/09/c5b6734a50ad4882432b6bb7c02baf757f5b2f256041da5df242e2d7e6b6/scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7", size = 37269716, upload-time = "2025-05-08T16:07:25.712Z" }, { url = "https://files.pythonhosted.org/packages/77/0a/eac00ff741f23bcabd352731ed9b8995a0a60ef57f5fd788d611d43d69a1/scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11", size = 36872342, upload-time = "2025-05-08T16:07:31.468Z" }, { url = "https://files.pythonhosted.org/packages/fe/54/4379be86dd74b6ad81551689107360d9a3e18f24d20767a2d5b9253a3f0a/scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126", size = 39670869, upload-time = "2025-05-08T16:07:38.002Z" }, { url = "https://files.pythonhosted.org/packages/87/2e/892ad2862ba54f084ffe8cc4a22667eaf9c2bcec6d2bff1d15713c6c0703/scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163", size = 40988851, upload-time = "2025-05-08T16:08:33.671Z" }, { url = "https://files.pythonhosted.org/packages/1b/e9/7a879c137f7e55b30d75d90ce3eb468197646bc7b443ac036ae3fe109055/scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8", size = 38863011, upload-time = "2025-05-08T16:07:44.039Z" }, { url = "https://files.pythonhosted.org/packages/51/d1/226a806bbd69f62ce5ef5f3ffadc35286e9fbc802f606a07eb83bf2359de/scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5", size = 30266407, upload-time = "2025-05-08T16:07:49.891Z" }, { url = "https://files.pythonhosted.org/packages/e5/9b/f32d1d6093ab9eeabbd839b0f7619c62e46cc4b7b6dbf05b6e615bbd4400/scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e", size = 22540030, upload-time = "2025-05-08T16:07:54.121Z" }, { url = "https://files.pythonhosted.org/packages/e7/29/c278f699b095c1a884f29fda126340fcc201461ee8bfea5c8bdb1c7c958b/scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb", size = 25218709, upload-time = "2025-05-08T16:07:58.506Z" }, { url = "https://files.pythonhosted.org/packages/24/18/9e5374b617aba742a990581373cd6b68a2945d65cc588482749ef2e64467/scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723", size = 34809045, upload-time = "2025-05-08T16:08:03.929Z" }, { url = "https://files.pythonhosted.org/packages/e1/fe/9c4361e7ba2927074360856db6135ef4904d505e9b3afbbcb073c4008328/scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb", size = 36703062, upload-time = "2025-05-08T16:08:09.558Z" }, { url = "https://files.pythonhosted.org/packages/b7/8e/038ccfe29d272b30086b25a4960f757f97122cb2ec42e62b460d02fe98e9/scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4", size = 36393132, upload-time = "2025-05-08T16:08:15.34Z" }, { url = "https://files.pythonhosted.org/packages/10/7e/5c12285452970be5bdbe8352c619250b97ebf7917d7a9a9e96b8a8140f17/scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5", size = 38979503, upload-time = "2025-05-08T16:08:21.513Z" }, { url = "https://files.pythonhosted.org/packages/81/06/0a5e5349474e1cbc5757975b21bd4fad0e72ebf138c5592f191646154e06/scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca", size = 40308097, upload-time = "2025-05-08T16:08:27.627Z" }, ] [[package]] name = "scipy" version = "1.17.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/56/3e/9cca699f3486ce6bc12ff46dc2031f1ec8eb9ccc9a320fdaf925f1417426/scipy-1.17.0.tar.gz", hash = "sha256:2591060c8e648d8b96439e111ac41fd8342fdeff1876be2e19dea3fe8930454e", size = 30396830, upload-time = "2026-01-10T21:34:23.009Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/1e/4b/c89c131aa87cad2b77a54eb0fb94d633a842420fa7e919dc2f922037c3d8/scipy-1.17.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:2abd71643797bd8a106dff97894ff7869eeeb0af0f7a5ce02e4227c6a2e9d6fd", size = 31381316, upload-time = "2026-01-10T21:24:33.42Z" }, { url = "https://files.pythonhosted.org/packages/5e/5f/a6b38f79a07d74989224d5f11b55267714707582908a5f1ae854cf9a9b84/scipy-1.17.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:ef28d815f4d2686503e5f4f00edc387ae58dfd7a2f42e348bb53359538f01558", size = 27966760, upload-time = "2026-01-10T21:24:38.911Z" }, { url = "https://files.pythonhosted.org/packages/c1/20/095ad24e031ee8ed3c5975954d816b8e7e2abd731e04f8be573de8740885/scipy-1.17.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:272a9f16d6bb4667e8b50d25d71eddcc2158a214df1b566319298de0939d2ab7", size = 20138701, upload-time = "2026-01-10T21:24:43.249Z" }, { url = "https://files.pythonhosted.org/packages/89/11/4aad2b3858d0337756f3323f8960755704e530b27eb2a94386c970c32cbe/scipy-1.17.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:7204fddcbec2fe6598f1c5fdf027e9f259106d05202a959a9f1aecf036adc9f6", size = 22480574, upload-time = "2026-01-10T21:24:47.266Z" }, { url = "https://files.pythonhosted.org/packages/85/bd/f5af70c28c6da2227e510875cadf64879855193a687fb19951f0f44cfd6b/scipy-1.17.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc02c37a5639ee67d8fb646ffded6d793c06c5622d36b35cfa8fe5ececb8f042", size = 32862414, upload-time = "2026-01-10T21:24:52.566Z" }, { url = "https://files.pythonhosted.org/packages/ef/df/df1457c4df3826e908879fe3d76bc5b6e60aae45f4ee42539512438cfd5d/scipy-1.17.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dac97a27520d66c12a34fd90a4fe65f43766c18c0d6e1c0a80f114d2260080e4", size = 35112380, upload-time = "2026-01-10T21:24:58.433Z" }, { url = "https://files.pythonhosted.org/packages/5f/bb/88e2c16bd1dd4de19d80d7c5e238387182993c2fb13b4b8111e3927ad422/scipy-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ebb7446a39b3ae0fe8f416a9a3fdc6fba3f11c634f680f16a239c5187bc487c0", size = 34922676, upload-time = "2026-01-10T21:25:04.287Z" }, { url = "https://files.pythonhosted.org/packages/02/ba/5120242cc735f71fc002cff0303d536af4405eb265f7c60742851e7ccfe9/scipy-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:474da16199f6af66601a01546144922ce402cb17362e07d82f5a6cf8f963e449", size = 37507599, upload-time = "2026-01-10T21:25:09.851Z" }, { url = "https://files.pythonhosted.org/packages/52/c8/08629657ac6c0da198487ce8cd3de78e02cfde42b7f34117d56a3fe249dc/scipy-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:255c0da161bd7b32a6c898e7891509e8a9289f0b1c6c7d96142ee0d2b114c2ea", size = 36380284, upload-time = "2026-01-10T21:25:15.632Z" }, { url = "https://files.pythonhosted.org/packages/6c/4a/465f96d42c6f33ad324a40049dfd63269891db9324aa66c4a1c108c6f994/scipy-1.17.0-cp311-cp311-win_arm64.whl", hash = "sha256:85b0ac3ad17fa3be50abd7e69d583d98792d7edc08367e01445a1e2076005379", size = 24370427, upload-time = "2026-01-10T21:25:20.514Z" }, { url = "https://files.pythonhosted.org/packages/0b/11/7241a63e73ba5a516f1930ac8d5b44cbbfabd35ac73a2d08ca206df007c4/scipy-1.17.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:0d5018a57c24cb1dd828bcf51d7b10e65986d549f52ef5adb6b4d1ded3e32a57", size = 31364580, upload-time = "2026-01-10T21:25:25.717Z" }, { url = "https://files.pythonhosted.org/packages/ed/1d/5057f812d4f6adc91a20a2d6f2ebcdb517fdbc87ae3acc5633c9b97c8ba5/scipy-1.17.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:88c22af9e5d5a4f9e027e26772cc7b5922fab8bcc839edb3ae33de404feebd9e", size = 27969012, upload-time = "2026-01-10T21:25:30.921Z" }, { url = "https://files.pythonhosted.org/packages/e3/21/f6ec556c1e3b6ec4e088da667d9987bb77cc3ab3026511f427dc8451187d/scipy-1.17.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f3cd947f20fe17013d401b64e857c6b2da83cae567adbb75b9dcba865abc66d8", size = 20140691, upload-time = "2026-01-10T21:25:34.802Z" }, { url = "https://files.pythonhosted.org/packages/7a/fe/5e5ad04784964ba964a96f16c8d4676aa1b51357199014dce58ab7ec5670/scipy-1.17.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e8c0b331c2c1f531eb51f1b4fc9ba709521a712cce58f1aa627bc007421a5306", size = 22463015, upload-time = "2026-01-10T21:25:39.277Z" }, { url = "https://files.pythonhosted.org/packages/4a/69/7c347e857224fcaf32a34a05183b9d8a7aca25f8f2d10b8a698b8388561a/scipy-1.17.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5194c445d0a1c7a6c1a4a4681b6b7c71baad98ff66d96b949097e7513c9d6742", size = 32724197, upload-time = "2026-01-10T21:25:44.084Z" }, { url = "https://files.pythonhosted.org/packages/d1/fe/66d73b76d378ba8cc2fe605920c0c75092e3a65ae746e1e767d9d020a75a/scipy-1.17.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9eeb9b5f5997f75507814ed9d298ab23f62cf79f5a3ef90031b1ee2506abdb5b", size = 35009148, upload-time = "2026-01-10T21:25:50.591Z" }, { url = "https://files.pythonhosted.org/packages/af/07/07dec27d9dc41c18d8c43c69e9e413431d20c53a0339c388bcf72f353c4b/scipy-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:40052543f7bbe921df4408f46003d6f01c6af109b9e2c8a66dd1cf6cf57f7d5d", size = 34798766, upload-time = "2026-01-10T21:25:59.41Z" }, { url = "https://files.pythonhosted.org/packages/81/61/0470810c8a093cdacd4ba7504b8a218fd49ca070d79eca23a615f5d9a0b0/scipy-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0cf46c8013fec9d3694dc572f0b54100c28405d55d3e2cb15e2895b25057996e", size = 37405953, upload-time = "2026-01-10T21:26:07.75Z" }, { url = "https://files.pythonhosted.org/packages/92/ce/672ed546f96d5d41ae78c4b9b02006cedd0b3d6f2bf5bb76ea455c320c28/scipy-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:0937a0b0d8d593a198cededd4c439a0ea216a3f36653901ea1f3e4be949056f8", size = 36328121, upload-time = "2026-01-10T21:26:16.509Z" }, { url = "https://files.pythonhosted.org/packages/9d/21/38165845392cae67b61843a52c6455d47d0cc2a40dd495c89f4362944654/scipy-1.17.0-cp312-cp312-win_arm64.whl", hash = "sha256:f603d8a5518c7426414d1d8f82e253e454471de682ce5e39c29adb0df1efb86b", size = 24314368, upload-time = "2026-01-10T21:26:23.087Z" }, { url = "https://files.pythonhosted.org/packages/0c/51/3468fdfd49387ddefee1636f5cf6d03ce603b75205bf439bbf0e62069bfd/scipy-1.17.0-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:65ec32f3d32dfc48c72df4291345dae4f048749bc8d5203ee0a3f347f96c5ce6", size = 31344101, upload-time = "2026-01-10T21:26:30.25Z" }, { url = "https://files.pythonhosted.org/packages/b2/9a/9406aec58268d437636069419e6977af953d1e246df941d42d3720b7277b/scipy-1.17.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:1f9586a58039d7229ce77b52f8472c972448cded5736eaf102d5658bbac4c269", size = 27950385, upload-time = "2026-01-10T21:26:36.801Z" }, { url = "https://files.pythonhosted.org/packages/4f/98/e7342709e17afdfd1b26b56ae499ef4939b45a23a00e471dfb5375eea205/scipy-1.17.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9fad7d3578c877d606b1150135c2639e9de9cecd3705caa37b66862977cc3e72", size = 20122115, upload-time = "2026-01-10T21:26:42.107Z" }, { url = "https://files.pythonhosted.org/packages/fd/0e/9eeeb5357a64fd157cbe0302c213517c541cc16b8486d82de251f3c68ede/scipy-1.17.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:423ca1f6584fc03936972b5f7c06961670dbba9f234e71676a7c7ccf938a0d61", size = 22442402, upload-time = "2026-01-10T21:26:48.029Z" }, { url = "https://files.pythonhosted.org/packages/c9/10/be13397a0e434f98e0c79552b2b584ae5bb1c8b2be95db421533bbca5369/scipy-1.17.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe508b5690e9eaaa9467fc047f833af58f1152ae51a0d0aed67aa5801f4dd7d6", size = 32696338, upload-time = "2026-01-10T21:26:55.521Z" }, { url = "https://files.pythonhosted.org/packages/63/1e/12fbf2a3bb240161651c94bb5cdd0eae5d4e8cc6eaeceb74ab07b12a753d/scipy-1.17.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6680f2dfd4f6182e7d6db161344537da644d1cf85cf293f015c60a17ecf08752", size = 34977201, upload-time = "2026-01-10T21:27:03.501Z" }, { url = "https://files.pythonhosted.org/packages/19/5b/1a63923e23ccd20bd32156d7dd708af5bbde410daa993aa2500c847ab2d2/scipy-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eec3842ec9ac9de5917899b277428886042a93db0b227ebbe3a333b64ec7643d", size = 34777384, upload-time = "2026-01-10T21:27:11.423Z" }, { url = "https://files.pythonhosted.org/packages/39/22/b5da95d74edcf81e540e467202a988c50fef41bd2011f46e05f72ba07df6/scipy-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d7425fcafbc09a03731e1bc05581f5fad988e48c6a861f441b7ab729a49a55ea", size = 37379586, upload-time = "2026-01-10T21:27:20.171Z" }, { url = "https://files.pythonhosted.org/packages/b9/b6/8ac583d6da79e7b9e520579f03007cb006f063642afd6b2eeb16b890bf93/scipy-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:87b411e42b425b84777718cc41516b8a7e0795abfa8e8e1d573bf0ef014f0812", size = 36287211, upload-time = "2026-01-10T21:28:43.122Z" }, { url = "https://files.pythonhosted.org/packages/55/fb/7db19e0b3e52f882b420417644ec81dd57eeef1bd1705b6f689d8ff93541/scipy-1.17.0-cp313-cp313-win_arm64.whl", hash = "sha256:357ca001c6e37601066092e7c89cca2f1ce74e2a520ca78d063a6d2201101df2", size = 24312646, upload-time = "2026-01-10T21:28:49.893Z" }, { url = "https://files.pythonhosted.org/packages/20/b6/7feaa252c21cc7aff335c6c55e1b90ab3e3306da3f048109b8b639b94648/scipy-1.17.0-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:ec0827aa4d36cb79ff1b81de898e948a51ac0b9b1c43e4a372c0508c38c0f9a3", size = 31693194, upload-time = "2026-01-10T21:27:27.454Z" }, { url = "https://files.pythonhosted.org/packages/76/bb/bbb392005abce039fb7e672cb78ac7d158700e826b0515cab6b5b60c26fb/scipy-1.17.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:819fc26862b4b3c73a60d486dbb919202f3d6d98c87cf20c223511429f2d1a97", size = 28365415, upload-time = "2026-01-10T21:27:34.26Z" }, { url = "https://files.pythonhosted.org/packages/37/da/9d33196ecc99fba16a409c691ed464a3a283ac454a34a13a3a57c0d66f3a/scipy-1.17.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:363ad4ae2853d88ebcde3ae6ec46ccca903ea9835ee8ba543f12f575e7b07e4e", size = 20537232, upload-time = "2026-01-10T21:27:40.306Z" }, { url = "https://files.pythonhosted.org/packages/56/9d/f4b184f6ddb28e9a5caea36a6f98e8ecd2a524f9127354087ce780885d83/scipy-1.17.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:979c3a0ff8e5ba254d45d59ebd38cde48fce4f10b5125c680c7a4bfe177aab07", size = 22791051, upload-time = "2026-01-10T21:27:46.539Z" }, { url = "https://files.pythonhosted.org/packages/9b/9d/025cccdd738a72140efc582b1641d0dd4caf2e86c3fb127568dc80444e6e/scipy-1.17.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:130d12926ae34399d157de777472bf82e9061c60cc081372b3118edacafe1d00", size = 32815098, upload-time = "2026-01-10T21:27:54.389Z" }, { url = "https://files.pythonhosted.org/packages/48/5f/09b879619f8bca15ce392bfc1894bd9c54377e01d1b3f2f3b595a1b4d945/scipy-1.17.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e886000eb4919eae3a44f035e63f0fd8b651234117e8f6f29bad1cd26e7bc45", size = 35031342, upload-time = "2026-01-10T21:28:03.012Z" }, { url = "https://files.pythonhosted.org/packages/f2/9a/f0f0a9f0aa079d2f106555b984ff0fbb11a837df280f04f71f056ea9c6e4/scipy-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:13c4096ac6bc31d706018f06a49abe0485f96499deb82066b94d19b02f664209", size = 34893199, upload-time = "2026-01-10T21:28:10.832Z" }, { url = "https://files.pythonhosted.org/packages/90/b8/4f0f5cf0c5ea4d7548424e6533e6b17d164f34a6e2fb2e43ffebb6697b06/scipy-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cacbaddd91fcffde703934897c5cd2c7cb0371fac195d383f4e1f1c5d3f3bd04", size = 37438061, upload-time = "2026-01-10T21:28:19.684Z" }, { url = "https://files.pythonhosted.org/packages/f9/cc/2bd59140ed3b2fa2882fb15da0a9cb1b5a6443d67cfd0d98d4cec83a57ec/scipy-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:edce1a1cf66298cccdc48a1bdf8fb10a3bf58e8b58d6c3883dd1530e103f87c0", size = 36328593, upload-time = "2026-01-10T21:28:28.007Z" }, { url = "https://files.pythonhosted.org/packages/13/1b/c87cc44a0d2c7aaf0f003aef2904c3d097b422a96c7e7c07f5efd9073c1b/scipy-1.17.0-cp313-cp313t-win_arm64.whl", hash = "sha256:30509da9dbec1c2ed8f168b8d8aa853bc6723fede1dbc23c7d43a56f5ab72a67", size = 24625083, upload-time = "2026-01-10T21:28:35.188Z" }, { url = "https://files.pythonhosted.org/packages/1a/2d/51006cd369b8e7879e1c630999a19d1fbf6f8b5ed3e33374f29dc87e53b3/scipy-1.17.0-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:c17514d11b78be8f7e6331b983a65a7f5ca1fd037b95e27b280921fe5606286a", size = 31346803, upload-time = "2026-01-10T21:28:57.24Z" }, { url = "https://files.pythonhosted.org/packages/d6/2e/2349458c3ce445f53a6c93d4386b1c4c5c0c540917304c01222ff95ff317/scipy-1.17.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:4e00562e519c09da34c31685f6acc3aa384d4d50604db0f245c14e1b4488bfa2", size = 27967182, upload-time = "2026-01-10T21:29:04.107Z" }, { url = "https://files.pythonhosted.org/packages/5e/7c/df525fbfa77b878d1cfe625249529514dc02f4fd5f45f0f6295676a76528/scipy-1.17.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f7df7941d71314e60a481e02d5ebcb3f0185b8d799c70d03d8258f6c80f3d467", size = 20139125, upload-time = "2026-01-10T21:29:10.179Z" }, { url = "https://files.pythonhosted.org/packages/33/11/fcf9d43a7ed1234d31765ec643b0515a85a30b58eddccc5d5a4d12b5f194/scipy-1.17.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:aabf057c632798832f071a8dde013c2e26284043934f53b00489f1773b33527e", size = 22443554, upload-time = "2026-01-10T21:29:15.888Z" }, { url = "https://files.pythonhosted.org/packages/80/5c/ea5d239cda2dd3d31399424967a24d556cf409fbea7b5b21412b0fd0a44f/scipy-1.17.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a38c3337e00be6fd8a95b4ed66b5d988bac4ec888fd922c2ea9fe5fb1603dd67", size = 32757834, upload-time = "2026-01-10T21:29:23.406Z" }, { url = "https://files.pythonhosted.org/packages/b8/7e/8c917cc573310e5dc91cbeead76f1b600d3fb17cf0969db02c9cf92e3cfa/scipy-1.17.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00fb5f8ec8398ad90215008d8b6009c9db9fa924fd4c7d6be307c6f945f9cd73", size = 34995775, upload-time = "2026-01-10T21:29:31.915Z" }, { url = "https://files.pythonhosted.org/packages/c5/43/176c0c3c07b3f7df324e7cdd933d3e2c4898ca202b090bd5ba122f9fe270/scipy-1.17.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f2a4942b0f5f7c23c7cd641a0ca1955e2ae83dedcff537e3a0259096635e186b", size = 34841240, upload-time = "2026-01-10T21:29:39.995Z" }, { url = "https://files.pythonhosted.org/packages/44/8c/d1f5f4b491160592e7f084d997de53a8e896a3ac01cd07e59f43ca222744/scipy-1.17.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf133ced83889583156566d2bdf7a07ff89228fe0c0cb727f777de92092ec6b", size = 37394463, upload-time = "2026-01-10T21:29:48.723Z" }, { url = "https://files.pythonhosted.org/packages/9f/ec/42a6657f8d2d087e750e9a5dde0b481fd135657f09eaf1cf5688bb23c338/scipy-1.17.0-cp314-cp314-win_amd64.whl", hash = "sha256:3625c631a7acd7cfd929e4e31d2582cf00f42fcf06011f59281271746d77e061", size = 37053015, upload-time = "2026-01-10T21:30:51.418Z" }, { url = "https://files.pythonhosted.org/packages/27/58/6b89a6afd132787d89a362d443a7bddd511b8f41336a1ae47f9e4f000dc4/scipy-1.17.0-cp314-cp314-win_arm64.whl", hash = "sha256:9244608d27eafe02b20558523ba57f15c689357c85bdcfe920b1828750aa26eb", size = 24951312, upload-time = "2026-01-10T21:30:56.771Z" }, { url = "https://files.pythonhosted.org/packages/e9/01/f58916b9d9ae0112b86d7c3b10b9e685625ce6e8248df139d0fcb17f7397/scipy-1.17.0-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:2b531f57e09c946f56ad0b4a3b2abee778789097871fc541e267d2eca081cff1", size = 31706502, upload-time = "2026-01-10T21:29:56.326Z" }, { url = "https://files.pythonhosted.org/packages/59/8e/2912a87f94a7d1f8b38aabc0faf74b82d3b6c9e22be991c49979f0eceed8/scipy-1.17.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:13e861634a2c480bd237deb69333ac79ea1941b94568d4b0efa5db5e263d4fd1", size = 28380854, upload-time = "2026-01-10T21:30:01.554Z" }, { url = "https://files.pythonhosted.org/packages/bd/1c/874137a52dddab7d5d595c1887089a2125d27d0601fce8c0026a24a92a0b/scipy-1.17.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:eb2651271135154aa24f6481cbae5cc8af1f0dd46e6533fb7b56aa9727b6a232", size = 20552752, upload-time = "2026-01-10T21:30:05.93Z" }, { url = "https://files.pythonhosted.org/packages/3f/f0/7518d171cb735f6400f4576cf70f756d5b419a07fe1867da34e2c2c9c11b/scipy-1.17.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:c5e8647f60679790c2f5c76be17e2e9247dc6b98ad0d3b065861e082c56e078d", size = 22803972, upload-time = "2026-01-10T21:30:10.651Z" }, { url = "https://files.pythonhosted.org/packages/7c/74/3498563a2c619e8a3ebb4d75457486c249b19b5b04a30600dfd9af06bea5/scipy-1.17.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fb10d17e649e1446410895639f3385fd2bf4c3c7dfc9bea937bddcbc3d7b9ba", size = 32829770, upload-time = "2026-01-10T21:30:16.359Z" }, { url = "https://files.pythonhosted.org/packages/48/d1/7b50cedd8c6c9d6f706b4b36fa8544d829c712a75e370f763b318e9638c1/scipy-1.17.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8547e7c57f932e7354a2319fab613981cde910631979f74c9b542bb167a8b9db", size = 35051093, upload-time = "2026-01-10T21:30:22.987Z" }, { url = "https://files.pythonhosted.org/packages/e2/82/a2d684dfddb87ba1b3ea325df7c3293496ee9accb3a19abe9429bce94755/scipy-1.17.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33af70d040e8af9d5e7a38b5ed3b772adddd281e3062ff23fec49e49681c38cf", size = 34909905, upload-time = "2026-01-10T21:30:28.704Z" }, { url = "https://files.pythonhosted.org/packages/ef/5e/e565bd73991d42023eb82bb99e51c5b3d9e2c588ca9d4b3e2cc1d3ca62a6/scipy-1.17.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb55bb97d00f8b7ab95cb64f873eb0bf54d9446264d9f3609130381233483f", size = 37457743, upload-time = "2026-01-10T21:30:34.819Z" }, { url = "https://files.pythonhosted.org/packages/58/a8/a66a75c3d8f1fb2b83f66007d6455a06a6f6cf5618c3dc35bc9b69dd096e/scipy-1.17.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1ff269abf702f6c7e67a4b7aad981d42871a11b9dd83c58d2d2ea624efbd1088", size = 37098574, upload-time = "2026-01-10T21:30:40.782Z" }, { url = "https://files.pythonhosted.org/packages/56/a5/df8f46ef7da168f1bc52cd86e09a9de5c6f19cc1da04454d51b7d4f43408/scipy-1.17.0-cp314-cp314t-win_arm64.whl", hash = "sha256:031121914e295d9791319a1875444d55079885bbae5bdc9c5e0f2ee5f09d34ff", size = 25246266, upload-time = "2026-01-10T21:30:45.923Z" }, ] [[package]] name = "seaborn" version = "0.13.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "matplotlib", version = "3.9.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "matplotlib", version = "3.10.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "pandas", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, ] [[package]] name = "secretstorage" version = "3.3.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "cryptography", marker = "python_full_version < '3.10'" }, { name = "jeepney", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/53/a4/f48c9d79cb507ed1373477dbceaba7401fd8a23af63b837fa61f1dcd3691/SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77", size = 19739, upload-time = "2022-08-13T16:22:46.976Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/54/24/b4293291fa1dd830f353d2cb163295742fa87f179fcc8a20a306a81978b7/SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99", size = 15221, upload-time = "2022-08-13T16:22:44.457Z" }, ] [[package]] name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "cryptography", marker = "(python_full_version == '3.10.*' and sys_platform == 'emscripten') or (python_full_version == '3.10.*' and sys_platform == 'win32') or (python_full_version >= '3.10' and sys_platform != 'emscripten' and sys_platform != 'win32')" }, { name = "jeepney", marker = "(python_full_version == '3.10.*' and sys_platform == 'emscripten') or (python_full_version == '3.10.*' and sys_platform == 'win32') or (python_full_version >= '3.10' and sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, ] [[package]] name = "setuptools" version = "82.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/82/f3/748f4d6f65d1756b9ae577f329c951cda23fb900e4de9f70900ced962085/setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb", size = 1144893, upload-time = "2026-02-08T15:08:40.206Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e1/c6/76dc613121b793286a3f91621d7b75a2b493e0390ddca50f11993eadf192/setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0", size = 1003468, upload-time = "2026-02-08T15:08:38.723Z" }, ] [[package]] name = "six" version = "1.17.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] [[package]] name = "snowballstemmer" version = "3.0.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, ] [[package]] name = "sphinx" version = "7.4.7" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ { name = "alabaster", version = "0.7.16", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "babel", marker = "python_full_version < '3.10'" }, { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "imagesize", marker = "python_full_version < '3.10'" }, { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "jinja2", marker = "python_full_version < '3.10'" }, { name = "packaging", marker = "python_full_version < '3.10'" }, { name = "pygments", marker = "python_full_version < '3.10'" }, { name = "requests", marker = "python_full_version < '3.10'" }, { name = "snowballstemmer", marker = "python_full_version < '3.10'" }, { name = "sphinxcontrib-applehelp", marker = "python_full_version < '3.10'" }, { name = "sphinxcontrib-devhelp", marker = "python_full_version < '3.10'" }, { name = "sphinxcontrib-htmlhelp", marker = "python_full_version < '3.10'" }, { name = "sphinxcontrib-jsmath", marker = "python_full_version < '3.10'" }, { name = "sphinxcontrib-qthelp", marker = "python_full_version < '3.10'" }, { name = "sphinxcontrib-serializinghtml", marker = "python_full_version < '3.10'" }, { name = "tomli", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5b/be/50e50cb4f2eff47df05673d361095cafd95521d2a22521b920c67a372dcb/sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe", size = 8067911, upload-time = "2024-07-20T14:46:56.059Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0d/ef/153f6803c5d5f8917dbb7f7fcf6d34a871ede3296fa89c2c703f5f8a6c8e/sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239", size = 3401624, upload-time = "2024-07-20T14:46:52.142Z" }, ] [[package]] name = "sphinx" version = "8.1.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", ] dependencies = [ { name = "alabaster", version = "1.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "babel", marker = "python_full_version == '3.10.*'" }, { name = "colorama", marker = "python_full_version == '3.10.*' and sys_platform == 'win32'" }, { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "imagesize", marker = "python_full_version == '3.10.*'" }, { name = "jinja2", marker = "python_full_version == '3.10.*'" }, { name = "packaging", marker = "python_full_version == '3.10.*'" }, { name = "pygments", marker = "python_full_version == '3.10.*'" }, { name = "requests", marker = "python_full_version == '3.10.*'" }, { name = "snowballstemmer", marker = "python_full_version == '3.10.*'" }, { name = "sphinxcontrib-applehelp", marker = "python_full_version == '3.10.*'" }, { name = "sphinxcontrib-devhelp", marker = "python_full_version == '3.10.*'" }, { name = "sphinxcontrib-htmlhelp", marker = "python_full_version == '3.10.*'" }, { name = "sphinxcontrib-jsmath", marker = "python_full_version == '3.10.*'" }, { name = "sphinxcontrib-qthelp", marker = "python_full_version == '3.10.*'" }, { name = "sphinxcontrib-serializinghtml", marker = "python_full_version == '3.10.*'" }, { name = "tomli", marker = "python_full_version == '3.10.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611, upload-time = "2024-10-13T20:27:13.93Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125, upload-time = "2024-10-13T20:27:10.448Z" }, ] [[package]] name = "sphinx" version = "9.0.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "alabaster", version = "1.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "babel", marker = "python_full_version == '3.11.*'" }, { name = "colorama", marker = "python_full_version == '3.11.*' and sys_platform == 'win32'" }, { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "imagesize", marker = "python_full_version == '3.11.*'" }, { name = "jinja2", marker = "python_full_version == '3.11.*'" }, { name = "packaging", marker = "python_full_version == '3.11.*'" }, { name = "pygments", marker = "python_full_version == '3.11.*'" }, { name = "requests", marker = "python_full_version == '3.11.*'" }, { name = "roman-numerals", marker = "python_full_version == '3.11.*'" }, { name = "snowballstemmer", marker = "python_full_version == '3.11.*'" }, { name = "sphinxcontrib-applehelp", marker = "python_full_version == '3.11.*'" }, { name = "sphinxcontrib-devhelp", marker = "python_full_version == '3.11.*'" }, { name = "sphinxcontrib-htmlhelp", marker = "python_full_version == '3.11.*'" }, { name = "sphinxcontrib-jsmath", marker = "python_full_version == '3.11.*'" }, { name = "sphinxcontrib-qthelp", marker = "python_full_version == '3.11.*'" }, { name = "sphinxcontrib-serializinghtml", marker = "python_full_version == '3.11.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/50/a8c6ccc36d5eacdfd7913ddccd15a9cee03ecafc5ee2bc40e1f168d85022/sphinx-9.0.4.tar.gz", hash = "sha256:594ef59d042972abbc581d8baa577404abe4e6c3b04ef61bd7fc2acbd51f3fa3", size = 8710502, upload-time = "2025-12-04T07:45:27.343Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c6/3f/4bbd76424c393caead2e1eb89777f575dee5c8653e2d4b6afd7a564f5974/sphinx-9.0.4-py3-none-any.whl", hash = "sha256:5bebc595a5e943ea248b99c13814c1c5e10b3ece718976824ffa7959ff95fffb", size = 3917713, upload-time = "2025-12-04T07:45:24.944Z" }, ] [[package]] name = "sphinx" version = "9.1.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "alabaster", version = "1.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, { name = "babel", marker = "python_full_version >= '3.12'" }, { name = "colorama", marker = "python_full_version >= '3.12' and sys_platform == 'win32'" }, { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, { name = "imagesize", marker = "python_full_version >= '3.12'" }, { name = "jinja2", marker = "python_full_version >= '3.12'" }, { name = "packaging", marker = "python_full_version >= '3.12'" }, { name = "pygments", marker = "python_full_version >= '3.12'" }, { name = "requests", marker = "python_full_version >= '3.12'" }, { name = "roman-numerals", marker = "python_full_version >= '3.12'" }, { name = "snowballstemmer", marker = "python_full_version >= '3.12'" }, { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.12'" }, { name = "sphinxcontrib-devhelp", marker = "python_full_version >= '3.12'" }, { name = "sphinxcontrib-htmlhelp", marker = "python_full_version >= '3.12'" }, { name = "sphinxcontrib-jsmath", marker = "python_full_version >= '3.12'" }, { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.12'" }, { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cd/bd/f08eb0f4eed5c83f1ba2a3bd18f7745a2b1525fad70660a1c00224ec468a/sphinx-9.1.0.tar.gz", hash = "sha256:7741722357dd75f8190766926071fed3bdc211c74dd2d7d4df5404da95930ddb", size = 8718324, upload-time = "2025-12-31T15:09:27.646Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/73/f7/b1884cb3188ab181fc81fa00c266699dab600f927a964df02ec3d5d1916a/sphinx-9.1.0-py3-none-any.whl", hash = "sha256:c84fdd4e782504495fe4f2c0b3413d6c2bf388589bb352d439b2a3bb99991978", size = 3921742, upload-time = "2025-12-31T15:09:25.561Z" }, ] [[package]] name = "sphinx-rtd-theme" version = "3.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, { name = "sphinxcontrib-jquery" }, ] sdist = { url = "https://files.pythonhosted.org/packages/84/68/a1bfbf38c0f7bccc9b10bbf76b94606f64acb1552ae394f0b8285bfaea25/sphinx_rtd_theme-3.1.0.tar.gz", hash = "sha256:b44276f2c276e909239a4f6c955aa667aaafeb78597923b1c60babc76db78e4c", size = 7620915, upload-time = "2026-01-12T16:03:31.17Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/87/c7/b5c8015d823bfda1a346adb2c634a2101d50bb75d421eb6dcb31acd25ebc/sphinx_rtd_theme-3.1.0-py2.py3-none-any.whl", hash = "sha256:1785824ae8e6632060490f67cf3a72d404a85d2d9fc26bce3619944de5682b89", size = 7655617, upload-time = "2026-01-12T16:03:28.101Z" }, ] [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, ] [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, ] [[package]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, ] [[package]] name = "sphinxcontrib-jquery" version = "4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331, upload-time = "2023-03-14T15:01:01.944Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/76/85/749bd22d1a68db7291c89e2ebca53f4306c3f205853cf31e9de279034c3c/sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae", size = 121104, upload-time = "2023-03-14T15:01:00.356Z" }, ] [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, ] [[package]] name = "sphinxcontrib-qthelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, ] [[package]] name = "sphinxcontrib-serializinghtml" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, ] [[package]] name = "statsmodels" version = "0.14.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "packaging" }, { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "pandas", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "patsy" }, { name = "scipy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "scipy", version = "1.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0d/81/e8d74b34f85285f7335d30c5e3c2d7c0346997af9f3debf9a0a9a63de184/statsmodels-0.14.6.tar.gz", hash = "sha256:4d17873d3e607d398b85126cd4ed7aad89e4e9d89fc744cdab1af3189a996c2a", size = 20689085, upload-time = "2025-12-05T23:08:39.522Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b5/6d/9ec309a175956f88eb8420ac564297f37cf9b1f73f89db74da861052dc29/statsmodels-0.14.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f4ff0649a2df674c7ffb6fa1a06bffdb82a6adf09a48e90e000a15a6aaa734b0", size = 10142419, upload-time = "2025-12-05T19:27:35.625Z" }, { url = "https://files.pythonhosted.org/packages/86/8f/338c5568315ec5bf3ac7cd4b71e34b98cb3b0f834919c0c04a0762f878a1/statsmodels-0.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:109012088b3e370080846ab053c76d125268631410142daad2f8c10770e8e8d9", size = 10022819, upload-time = "2025-12-05T19:27:49.385Z" }, { url = "https://files.pythonhosted.org/packages/b0/77/5fc4cbc2d608f9b483b0675f82704a8bcd672962c379fe4d82100d388dbf/statsmodels-0.14.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e93bd5d220f3cb6fc5fc1bffd5b094966cab8ee99f6c57c02e95710513d6ac3f", size = 10118927, upload-time = "2025-12-05T23:07:51.256Z" }, { url = "https://files.pythonhosted.org/packages/94/55/b86c861c32186403fe121d9ab27bc16d05839b170d92a978beb33abb995e/statsmodels-0.14.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:06eec42d682fdb09fe5d70a05930857efb141754ec5a5056a03304c1b5e32fd9", size = 10413015, upload-time = "2025-12-05T23:08:53.95Z" }, { url = "https://files.pythonhosted.org/packages/f9/be/daf0dba729ccdc4176605f4a0fd5cfe71cdda671749dca10e74a732b8b1c/statsmodels-0.14.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0444e88557df735eda7db330806fe09d51c9f888bb1f5906cb3a61fb1a3ed4a8", size = 10441248, upload-time = "2025-12-05T23:09:09.353Z" }, { url = "https://files.pythonhosted.org/packages/9a/1c/2e10b7c7cc44fa418272996bf0427b8016718fd62f995d9c1f7ab37adf35/statsmodels-0.14.6-cp310-cp310-win_amd64.whl", hash = "sha256:e83a9abe653835da3b37fb6ae04b45480c1de11b3134bd40b09717192a1456ea", size = 9583410, upload-time = "2025-12-05T19:28:02.086Z" }, { url = "https://files.pythonhosted.org/packages/a9/4d/df4dd089b406accfc3bb5ee53ba29bb3bdf5ae61643f86f8f604baa57656/statsmodels-0.14.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ad5c2810fc6c684254a7792bf1cbaf1606cdee2a253f8bd259c43135d87cfb4", size = 10121514, upload-time = "2025-12-05T19:28:16.521Z" }, { url = "https://files.pythonhosted.org/packages/82/af/ec48daa7f861f993b91a0dcc791d66e1cf56510a235c5cbd2ab991a31d5c/statsmodels-0.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:341fa68a7403e10a95c7b6e41134b0da3a7b835ecff1eb266294408535a06eb6", size = 10003346, upload-time = "2025-12-05T19:28:29.568Z" }, { url = "https://files.pythonhosted.org/packages/a9/2c/c8f7aa24cd729970728f3f98822fb45149adc216f445a9301e441f7ac760/statsmodels-0.14.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdf1dfe2a3ca56f5529118baf33a13efed2783c528f4a36409b46bbd2d9d48eb", size = 10129872, upload-time = "2025-12-05T23:09:25.724Z" }, { url = "https://files.pythonhosted.org/packages/40/c6/9ae8e9b0721e9b6eb5f340c3a0ce8cd7cce4f66e03dd81f80d60f111987f/statsmodels-0.14.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3764ba8195c9baf0925a96da0743ff218067a269f01d155ca3558deed2658ca", size = 10381964, upload-time = "2025-12-05T23:09:41.326Z" }, { url = "https://files.pythonhosted.org/packages/28/8c/cf3d30c8c2da78e2ad1f50ade8b7fabec3ff4cdfc56fbc02e097c4577f90/statsmodels-0.14.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e8d2e519852adb1b420e018f5ac6e6684b2b877478adf7fda2cfdb58f5acb5d", size = 10409611, upload-time = "2025-12-05T23:09:57.131Z" }, { url = "https://files.pythonhosted.org/packages/bf/cc/018f14ecb58c6cb89de9d52695740b7d1f5a982aa9ea312483ea3c3d5f77/statsmodels-0.14.6-cp311-cp311-win_amd64.whl", hash = "sha256:2738a00fca51196f5a7d44b06970ace6b8b30289839e4808d656f8a98e35faa7", size = 9580385, upload-time = "2025-12-05T19:28:42.778Z" }, { url = "https://files.pythonhosted.org/packages/25/ce/308e5e5da57515dd7cab3ec37ea2d5b8ff50bef1fcc8e6d31456f9fae08e/statsmodels-0.14.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fe76140ae7adc5ff0e60a3f0d56f4fffef484efa803c3efebf2fcd734d72ecb5", size = 10091932, upload-time = "2025-12-05T19:28:55.446Z" }, { url = "https://files.pythonhosted.org/packages/05/30/affbabf3c27fb501ec7b5808230c619d4d1a4525c07301074eb4bda92fa9/statsmodels-0.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26d4f0ed3b31f3c86f83a92f5c1f5cbe63fc992cd8915daf28ca49be14463a1c", size = 9997345, upload-time = "2025-12-05T19:29:10.278Z" }, { url = "https://files.pythonhosted.org/packages/48/f5/3a73b51e6450c31652c53a8e12e24eac64e3824be816c0c2316e7dbdcb7d/statsmodels-0.14.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8c00a42863e4f4733ac9d078bbfad816249c01451740e6f5053ecc7db6d6368", size = 10058649, upload-time = "2025-12-05T23:10:12.775Z" }, { url = "https://files.pythonhosted.org/packages/81/68/dddd76117df2ef14c943c6bbb6618be5c9401280046f4ddfc9fb4596a1b8/statsmodels-0.14.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19b58cf7474aa9e7e3b0771a66537148b2df9b5884fbf156096c0e6c1ff0469d", size = 10339446, upload-time = "2025-12-05T23:10:28.503Z" }, { url = "https://files.pythonhosted.org/packages/56/4a/dce451c74c4050535fac1ec0c14b80706d8fc134c9da22db3c8a0ec62c33/statsmodels-0.14.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:81e7dcc5e9587f2567e52deaff5220b175bf2f648951549eae5fc9383b62bc37", size = 10368705, upload-time = "2025-12-05T23:10:44.339Z" }, { url = "https://files.pythonhosted.org/packages/60/15/3daba2df40be8b8a9a027d7f54c8dedf24f0d81b96e54b52293f5f7e3418/statsmodels-0.14.6-cp312-cp312-win_amd64.whl", hash = "sha256:b5eb07acd115aa6208b4058211138393a7e6c2cf12b6f213ede10f658f6a714f", size = 9543991, upload-time = "2025-12-05T23:10:58.536Z" }, { url = "https://files.pythonhosted.org/packages/81/59/a5aad5b0cc266f5be013db8cde563ac5d2a025e7efc0c328d83b50c72992/statsmodels-0.14.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:47ee7af083623d2091954fa71c7549b8443168f41b7c5dce66510274c50fd73e", size = 10072009, upload-time = "2025-12-05T23:11:14.021Z" }, { url = "https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa60d82e29fcd0a736e86feb63a11d2380322d77a9369a54be8b0965a3985f71", size = 9980018, upload-time = "2025-12-05T23:11:30.907Z" }, { url = "https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89ee7d595f5939cc20bf946faedcb5137d975f03ae080f300ebb4398f16a5bd4", size = 10060269, upload-time = "2025-12-05T23:11:46.338Z" }, { url = "https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:730f3297b26749b216a06e4327fe0be59b8d05f7d594fb6caff4287b69654589", size = 10324155, upload-time = "2025-12-05T23:12:01.805Z" }, { url = "https://files.pythonhosted.org/packages/ee/0f/a6900e220abd2c69cd0a07e3ad26c71984be6061415a60e0f17b152ecf08/statsmodels-0.14.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f1c08befa85e93acc992b72a390ddb7bd876190f1360e61d10cf43833463bc9c", size = 10349765, upload-time = "2025-12-05T23:12:18.018Z" }, { url = "https://files.pythonhosted.org/packages/98/08/b79f0c614f38e566eebbdcff90c0bcacf3c6ba7a5bbb12183c09c29ca400/statsmodels-0.14.6-cp313-cp313-win_amd64.whl", hash = "sha256:8021271a79f35b842c02a1794465a651a9d06ec2080f76ebc3b7adce77d08233", size = 9540043, upload-time = "2025-12-05T23:12:33.887Z" }, { url = "https://files.pythonhosted.org/packages/71/de/09540e870318e0c7b58316561d417be45eff731263b4234fdd2eee3511a8/statsmodels-0.14.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:00781869991f8f02ad3610da6627fd26ebe262210287beb59761982a8fa88cae", size = 10069403, upload-time = "2025-12-05T23:12:48.424Z" }, { url = "https://files.pythonhosted.org/packages/ab/f0/63c1bfda75dc53cee858006e1f46bd6d6f883853bea1b97949d0087766ca/statsmodels-0.14.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:73f305fbf31607b35ce919fae636ab8b80d175328ed38fdc6f354e813b86ee37", size = 9989253, upload-time = "2025-12-05T23:13:05.274Z" }, { url = "https://files.pythonhosted.org/packages/c1/98/b0dfb4f542b2033a3341aa5f1bdd97024230a4ad3670c5b0839d54e3dcab/statsmodels-0.14.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e443e7077a6e2d3faeea72f5a92c9f12c63722686eb80bb40a0f04e4a7e267ad", size = 10090802, upload-time = "2025-12-05T23:13:20.653Z" }, { url = "https://files.pythonhosted.org/packages/34/0e/2408735aca9e764643196212f9069912100151414dd617d39ffc72d77eee/statsmodels-0.14.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3414e40c073d725007a6603a18247ab7af3467e1af4a5e5a24e4c27bc26673b4", size = 10337587, upload-time = "2025-12-05T23:13:37.597Z" }, { url = "https://files.pythonhosted.org/packages/0f/36/4d44f7035ab3c0b2b6a4c4ebb98dedf36246ccbc1b3e2f51ebcd7ac83abb/statsmodels-0.14.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a518d3f9889ef920116f9fa56d0338069e110f823926356946dae83bc9e33e19", size = 10363350, upload-time = "2025-12-05T23:13:53.08Z" }, { url = "https://files.pythonhosted.org/packages/26/33/f1652d0c59fa51de18492ee2345b65372550501ad061daa38f950be390b6/statsmodels-0.14.6-cp314-cp314-win_amd64.whl", hash = "sha256:151b73e29f01fe619dbce7f66d61a356e9d1fe5e906529b78807df9189c37721", size = 9588010, upload-time = "2025-12-05T23:14:07.28Z" }, { url = "https://files.pythonhosted.org/packages/b6/c1/f3012162d55b43291267d15275433b208f63d2e91a4f82ad724679336d17/statsmodels-0.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4d0c1b0f9f6915619e2a0d3853e5763d4d66876892ad352e7d7b93a737556978", size = 10151985, upload-time = "2025-12-05T23:14:22.161Z" }, { url = "https://files.pythonhosted.org/packages/0b/d9/9bcd801ae2881884848bd53b5dc985e8d2a1b20cb1a0350f2a4b4dbfce24/statsmodels-0.14.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e0fc891d6358bf376cc0ae1fee10a650478172ae9ba359daba1785fc496cd1a", size = 10031652, upload-time = "2025-12-05T23:14:37.709Z" }, { url = "https://files.pythonhosted.org/packages/62/37/3b609324f22c151267784c5830d3afef2cc7b22970d6cf957f1b799fca3b/statsmodels-0.14.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f52ef0f0b63b8fd11e1ef1c2a1e73a410720b8715c9a83a26d733b6815597fe", size = 10121095, upload-time = "2025-12-05T23:14:53.169Z" }, { url = "https://files.pythonhosted.org/packages/40/4d/adf7615db9cc7802608b6343789e66ff6e8220f1a84066e502fe51e4f90f/statsmodels-0.14.6-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b328eafa86a2a67303fdb1d25677d15b70cd2a5229aabec7670ec5ea840f1375", size = 10411609, upload-time = "2025-12-05T23:15:09.022Z" }, { url = "https://files.pythonhosted.org/packages/3b/9d/a3d33f4bda4e6a5f9b1118e81f93d5bc1620ad8d685df15d79b291ad9b7f/statsmodels-0.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:3bef39f8587754f2d644b2e831e102fa08ace9a5a1af4b583b122e6fd3e083ab", size = 9590613, upload-time = "2025-12-05T23:15:24.013Z" }, ] [[package]] name = "tomli" version = "2.4.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" }, { url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" }, { url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" }, { url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" }, { url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" }, { url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" }, { url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" }, { url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" }, { url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" }, { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" }, { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" }, { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" }, { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" }, { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" }, { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" }, { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" }, { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" }, { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" }, { url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" }, { url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" }, { url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" }, { url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" }, { url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" }, { url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" }, { url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" }, { url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" }, { url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" }, { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" }, { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" }, { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" }, { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" }, { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" }, { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" }, { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" }, { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" }, { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" }, { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" }, { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" }, { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" }, { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" }, { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" }, { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" }, { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" }, { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" }, { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" }, { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" }, ] [[package]] name = "tqdm" version = "4.67.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, ] [[package]] name = "twine" version = "6.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "id" }, { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "keyring", marker = "platform_machine != 'ppc64le' and platform_machine != 's390x'" }, { name = "packaging" }, { name = "readme-renderer" }, { name = "requests" }, { name = "requests-toolbelt" }, { name = "rfc3986" }, { name = "rich" }, { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e0/a8/949edebe3a82774c1ec34f637f5dd82d1cf22c25e963b7d63771083bbee5/twine-6.2.0.tar.gz", hash = "sha256:e5ed0d2fd70c9959770dce51c8f39c8945c574e18173a7b81802dab51b4b75cf", size = 172262, upload-time = "2025-09-04T15:43:17.255Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl", hash = "sha256:418ebf08ccda9a8caaebe414433b0ba5e25eb5e4a927667122fbe8f829f985d8", size = 42727, upload-time = "2025-09-04T15:43:15.994Z" }, ] [[package]] name = "typing-extensions" version = "4.15.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] [[package]] name = "tzdata" version = "2025.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] [[package]] name = "urllib3" version = "2.6.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] [[package]] name = "werkzeug" version = "3.1.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5a/70/1469ef1d3542ae7c2c7b72bd5e3a4e6ee69d7978fa8a3af05a38eca5becf/werkzeug-3.1.5.tar.gz", hash = "sha256:6a548b0e88955dd07ccb25539d7d0cc97417ee9e179677d22c7041c8f078ce67", size = 864754, upload-time = "2026-01-08T17:49:23.247Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ad/e4/8d97cca767bcc1be76d16fb76951608305561c6e056811587f36cb1316a8/werkzeug-3.1.5-py3-none-any.whl", hash = "sha256:5111e36e91086ece91f93268bb39b4a35c1e6f1feac762c9c822ded0a4e322dc", size = 225025, upload-time = "2026-01-08T17:49:21.859Z" }, ] [[package]] name = "zipp" version = "3.23.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, ]