pax_global_header00006660000000000000000000000064150263330040014506gustar00rootroot0000000000000052 comment=94fe0e4d21a856d31feb799df43380810cb1e775 asammdf-8.5.1/000077500000000000000000000000001502633300400131315ustar00rootroot00000000000000asammdf-8.5.1/.github/000077500000000000000000000000001502633300400144715ustar00rootroot00000000000000asammdf-8.5.1/.github/FUNDING.yml000066400000000000000000000012661502633300400163130ustar00rootroot00000000000000# These are supported funding model platforms github: danielhrisca # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: danielhrisca issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] asammdf-8.5.1/.github/workflows/000077500000000000000000000000001502633300400165265ustar00rootroot00000000000000asammdf-8.5.1/.github/workflows/build.yml000066400000000000000000000026141502633300400203530ustar00rootroot00000000000000name: pyinstaller_build on: [push, pull_request] jobs: build: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] python-version: ["3.12"] steps: - uses: actions/checkout@v4 with: submodules: "recursive" - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install linux libraries shell: bash if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm' }} run: | sudo apt update sudo apt install libegl1 libopengl0 libevent-2.1-7 libopus0 libminizip1 libpulse0 \ libxcb-icccm4 libxcb-image0 libxcb-cursor0 libxcb-keysyms1 libxcb-xkb1 libxcb-shape0 \ libxkbcommon-x11-0 libxcb-render-util0 - name: Install Python packages run: | pip install tox - name: Build the executable run: | tox -e pyinstaller -- --distpath dist/${{ matrix.os }} --noconfirm --clean # see: https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts - name: Archive dist artifacts uses: actions/upload-artifact@v4 with: name: pyinstaller-${{ matrix.os }} path: dist/${{ matrix.os }}/** if-no-files-found: error asammdf-8.5.1/.github/workflows/main.yml000066400000000000000000000052651502633300400202050ustar00rootroot00000000000000name: tests concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: [push, pull_request] jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: os: [windows-latest, ubuntu-22.04, macos-latest] python-version: ["3.10", "3.11", "3.12", "3.13"] fail-fast: false steps: - uses: actions/checkout@v4 with: submodules: "recursive" - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install packages shell: bash run: | pip install tox tox-gh-actions if [ "$RUNNER_OS" = "Linux" ]; then sudo apt update sudo apt-get install libegl1 libopengl0 sudo apt-get install '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev sudo apt-get install libxcb-xinerama0 sudo apt-get install libxkbcommon-x11-0 sudo apt-get install xorg sudo apt-get install -y xvfb fi - name: Start Xvfb if: matrix.os == 'ubuntu-22.04' run: | Xvfb :0 -screen 0 1024x768x24 > /dev/null 2>&1 & export DISPLAY=:0 touch ~/.Xauthority Xvfb :0 -screen 0 1024x768x24 > /dev/null 2>&1 & export DISPLAY=:0 # see: https://github.com/ymyzk/tox-gh-actions - name: Run tests run: tox - uses: actions/upload-artifact@v4 if: failure() && matrix.os == 'windows-latest' # 'ubuntu-22.04' or 'windows-latest' with: path: "**/screenshots/**" name: ${{ matrix.python-version }} - name: Stop Xvfb if: matrix.os == 'ubuntu-22.04' run: killall Xvfb - name: Publish Style Summary if: ${{ failure() || success() }} run: | python -c "from ci import report_style; report_style()" - name: Publish Tests Summary if: ${{ failure() || success() }} run: | pip install junitparser python -c "from ci import report_tests; report_tests(header='## Unit-tests Report:')" - name: Coveralls Parallel uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} flag-name: Unittests-${{ matrix.os }}-${{ matrix.python-version }} parallel: true format: lcov coveralls: needs: test runs-on: ubuntu-latest steps: - name: Coveralls Finished uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true asammdf-8.5.1/.github/workflows/wheels.yml000066400000000000000000000031301502633300400205350ustar00rootroot00000000000000name: wheels on: [push, pull_request] jobs: build_wheels: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, ubuntu-24.04-arm, macos-13, macos-latest, windows-latest] fail-fast: false steps: - uses: actions/checkout@v4 with: submodules: "recursive" # Used to host cibuildwheel - uses: actions/setup-python@v5 with: python-version: "3.13" - name: Install cibuildwheel run: python -m pip install cibuildwheel - name: Build wheels shell: bash env: CIBW_TEST_COMMAND: "pytest {project}/test --ignore={project}/test/asammdf/gui" run: | if [ "$RUNNER_OS" = "Linux" ]; then sudo apt update sudo apt-get install libegl1 libopengl0 libxml2 libxml2-dev libxslt1-dev libxslt1.1 fi python -m cibuildwheel --output-dir wheelhouse - 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" - uses: actions/setup-python@v5 with: python-version: "3.10" - name: Install deps run: python -m pip install build - name: Build sdist run: python -m build --sdist - uses: actions/upload-artifact@v4 with: path: dist/*.tar.gz asammdf-8.5.1/.gitignore000066400000000000000000000102501502633300400151170ustar00rootroot00000000000000# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig # Created by https://www.toptal.com/developers/gitignore/api/python,macos # Edit at https://www.toptal.com/developers/gitignore?templates=python,macos ### macOS ### # General .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 ### macOS Patch ### # iCloud generated files *.icloud ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ 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 found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ ### Python Patch ### # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration poetry.toml # ruff .ruff_cache/ # LSP config files pyrightconfig.json # End of https://www.toptal.com/developers/gitignore/api/python,macos # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) !lib/ /lib/ coverage.lcov doc/_build/ screenshots/** test-reports/** asammdf-8.5.1/.gitmodules000066400000000000000000000001421502633300400153030ustar00rootroot00000000000000[submodule "ext/libdeflate"] path = ext/libdeflate url = https://github.com/ebiggers/libdeflate asammdf-8.5.1/.pre-commit-config.yaml000066400000000000000000000002401502633300400174060ustar00rootroot00000000000000repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.11.11 hooks: - id: ruff-check args: [--fix] - id: ruff-format asammdf-8.5.1/.readthedocs.yml000066400000000000000000000014011502633300400162130ustar00rootroot00000000000000# .readthedocs.yml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the version of Python and other tools you might need build: os: ubuntu-24.04 tools: python: "3.12" # Build documentation in the docs/ directory with Sphinx sphinx: configuration: doc/conf.py # Build documentation with MkDocs #mkdocs: # configuration: mkdocs.yml # Optionally build your docs in additional formats such as PDF formats: - pdf # Optionally set the version of Python and requirements required to build your docs python: install: - method: pip path: . - requirements: doc/requirements.txt # VCS submodules configuration submodules: include: all recursive: trueasammdf-8.5.1/.vscode/000077500000000000000000000000001502633300400144725ustar00rootroot00000000000000asammdf-8.5.1/.vscode/extensions.json000066400000000000000000000011061502633300400175620ustar00rootroot00000000000000{ "recommendations": [ "benspaulding.python-manifest-template", "charliermarsh.ruff", "esbenp.prettier-vscode", "fill-labs.dependi", "github.vscode-github-actions", "lextudio.restructuredtext", "ms-python.debugpy", "ms-python.mypy-type-checker", "ms-python.python", "ms-python.vscode-pylance", "njpwerner.autodocstring", "redhat.vscode-yaml", "swyddfa.esbonio", "tamasfe.even-better-toml", "trond-snekvik.simple-rst", "twixes.pypi-assistant" ] } asammdf-8.5.1/CMakeLists.txt000066400000000000000000000016531502633300400156760ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.26...3.29) project(${SKBUILD_PROJECT_NAME} LANGUAGES C VERSION ${SKBUILD_PROJECT_VERSION}) option(WITH_SYSTEM_DEFLATE "Use system provided deflate library" OFF) find_package( Python REQUIRED COMPONENTS Interpreter Development.Module ${SKBUILD_SABI_COMPONENT} NumPy ) python_add_library(cutils MODULE WITH_SOABI USE_SABI 3.10 src/asammdf/blocks/cutils.c) if (WITH_SYSTEM_DEFLATE) find_package(libdeflate REQUIRED) target_link_libraries(cutils PRIVATE Python::NumPy libdeflate::libdeflate_shared) else() # Add submodule libdeflate set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(LIBDEFLATE_COMPRESSION_SUPPORT OFF) set(LIBDEFLATE_GZIP_SUPPORT OFF) set(LIBDEFLATE_BUILD_GZIP OFF) add_subdirectory(ext/libdeflate EXCLUDE_FROM_ALL) target_link_libraries(cutils PRIVATE Python::NumPy libdeflate::libdeflate_static) endif() install(TARGETS cutils DESTINATION "asammdf/blocks") asammdf-8.5.1/CONTRIBUTING.md000066400000000000000000000033771502633300400153740ustar00rootroot00000000000000# Contributing ## The basics Your help is appreciated and welcome! The _master_ branch is meant to hold the release code. At any time this should be identical to the code available on PyPI. PRs will be pushed on the _development_ branch if the actual package code is changed. When the time comes this branch will be merged to the _master_ branch and a new release will be issued. PRs that deal with documentation, and other adjacent files (README for example) can be pushed to the _master_ branch. When submitting PRs please take into account: - the project's goals - PEP8 and the style guide below ## Developer instructions Clone the repository with submodules, make sure you have a C compiler installed, then install the development dependencies (we recommend using a virtual environment): ```bash python -m venv .venv # create virtual environment in .venv source .venv/bin/activate # activate virtual environment (POSIX) .venv\Scripts\activate.bat # activate virtual environment (Windows) pip install --requirement requirements.txt # install development dependencies (includes asammdf in editable mode) ``` Now you can start developing. If you are using VSCode, the virtual environment should be detected automatically. If not, open the command panel `Ctrl + Shift + P` and search for `Python: Select Interpreter`. ## Testing You can use tox to run tests locally. Example for the unit tests with Python version 3.10: ```console tox -e py310 ``` Otherwise, you can just push and the tests will be run by GitHub Actions. ## Style guide Just run [`ruff format`](https://docs.astral.sh/ruff/formatter/) on modified files before sending the PR. There is no need to reinvent the wheel here! **Tip**: install Git hooks using pre-commit `pre-commit install --install-hooks` asammdf-8.5.1/ISSUE_TEMPLATE.md000066400000000000000000000015621502633300400156420ustar00rootroot00000000000000# Python version _Please run the following snippet and write the output here_ ```python import platform from pprint import pprint import sys pprint("python=" + sys.version) pprint("os=" + platform.platform()) try: import numpy pprint("numpy=" + numpy.__version__) except ImportError: pass try: import asammdf pprint("asammdf=" + asammdf.__version__) except ImportError: pass ``` # Code ## MDF version _please write here the file version (you can run `print(MDF(file).version)`)_ ## Code snippet _please write here the code snippet that triggers the error_ ## Traceback _please write here the error traceback_ # Description The fastest way to debug is to have the original file. For data protection you can use the static method _scramble_ to scramble all text blocks, and send the scrambled file by e-mail. _Please describe the issue here._ asammdf-8.5.1/LICENSE000066400000000000000000000213721502633300400141430ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright 2017–2023 Daniel Hrisca Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. -------------------------------------------------------------------------------- 3rdparty dependency libdeflate is statically linked. libdeflate has the following license: Copyright 2016 Eric Biggers Copyright 2024 Google LLC 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. --------------------------------------------------------------------------------asammdf-8.5.1/MANIFEST.in000066400000000000000000000001751502633300400146720ustar00rootroot00000000000000include LICENSE recursive-include src/asammdf *.ui recursive-include src/asammdf *.c recursive-include src/asammdf *.qrc asammdf-8.5.1/README.md000066400000000000000000000251151502633300400144140ustar00rootroot00000000000000# logo of asammdf _asammdf_ is a fast parser and editor for ASAM (Association for Standardization of Automation and Measuring Systems) MDF (Measurement Data Format) files. _asammdf_ supports MDF versions 2 (.dat), 3 (.mdf) and 4 (.mf4). _asammdf_ works on Python >= 3.10 ![PyPI - Downloads](https://img.shields.io/pypi/dm/asammdf) ![PyPI - License](https://img.shields.io/pypi/l/asammdf) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/asammdf) ![PyPI - Version](https://img.shields.io/pypi/v/asammdf) [![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) --- ![screenshot of the graphical user interface](https://raw.githubusercontent.com/danielhrisca/asammdf/master/gui.png) ## Status | Continuous Integration | Coveralls | Codacy | ReadTheDocs | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | | [![continuous integration](https://github.com/danielhrisca/asammdf/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/danielhrisca/asammdf/actions/workflows/main.yml) | [![Coverage Status](https://coveralls.io/repos/github/danielhrisca/asammdf/badge.svg?branch=master)](https://coveralls.io/github/danielhrisca/asammdf?branch=master) | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a3da21da90ca43a5b72fc24b56880c99?branch=master)](https://www.codacy.com/app/danielhrisca/asammdf?utm_source=github.com&utm_medium=referral&utm_content=danielhrisca/asammdf&utm_campaign=badger) | [![Documentation Status](http://readthedocs.org/projects/asammdf/badge/?version=master)](http://asammdf.readthedocs.io/en/master/?badge=stable) | | PyPI | conda-forge | | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | | [![PyPI version](https://badge.fury.io/py/asammdf.svg)](https://badge.fury.io/py/asammdf) | [![conda-forge version](https://anaconda.org/conda-forge/asammdf/badges/version.svg)](https://anaconda.org/conda-forge/asammdf) | ## Project goals The main goals for this library are: - to be faster than the other Python-based mdf libraries - to have clean and easy-to-understand code base - to have minimal 3rd party dependencies ## Features - create new mdf files from scratch - append new channels - read unsorted MDF v3 and v4 files - read CAN and LIN bus logging files - extract CAN and LIN signals from anonymous bus logging measurements - filter a subset of channels from original mdf file - cut measurement to specified time interval - convert to different mdf version - export to pandas, HDF5, Matlab (v7.3), CSV and parquet - merge multiple files sharing the same internal structure - read and save mdf version 4.10 files containing zipped data blocks - space optimizations for saved files (no duplicated blocks) - split large data blocks (configurable size) for mdf version 4 - full support (read, append, save) for the following map types (multidimensional array channels): - mdf version 3 channels with CDBLOCK - mdf version 4 structure channel composition - mdf version 4 channel arrays with CNTemplate storage and one of the array types: - 0 - array - 1 - scaling axis - 2 - look-up - add and extract attachments for mdf version 4 - handle large files (for example merging two files, each with 14000 channels and 5GB size, on a RaspberryPi) - extract channel data, master channel and extra channel information as _Signal_ objects for unified operations with v3 and v4 files - time domain operation using the _Signal_ class - pandas DataFrames are good if all the channels have the same time base - a measurement will usually have channels from different sources at different rates - the _Signal_ class facilitates operations with such channels - graphical interface to visualize channels and perform operations with the files ## Major features not implemented (yet) - for version 3 - functionality related to sample reduction block: the sample reduction blocks are simply ignored - for version 4 - experimental support for MDF v4.20 column oriented storage - functionality related to sample reduction block: the sample reduction blocks are simply ignored - handling of channel hierarchy: channel hierarchy is ignored - full handling of bus logging measurements: currently only CAN and LIN bus logging are implemented with the ability to _get_ signals defined in the attached CAN/LIN database (.arxml or .dbc). Signals can also be extracted from an anonymous bus logging measurement by providing a CAN or LIN database (.dbc or .arxml) - handling of unfinished measurements (mdf 4): finalization is attempted when the file is loaded, however not all the finalization steps are supported - full support for remaining mdf 4 channel arrays types - xml schema for MDBLOCK: most metadata stored in the comment blocks will not be available - full handling of event blocks: events are transferred to the new files (in case of calling methods that return new _MDF_ objects) but no new events can be created - channels with default X axis: the default X axis is ignored and the channel group's master channel is used - attachment encryption/decryption using user provided encryption/decryption functions; this is not part of the MDF v4 spec and is only supported by this library ## Usage ```python from asammdf import MDF mdf = MDF('sample.mdf') speed = mdf.get('WheelSpeed') speed.plot() important_signals = ['WheelSpeed', 'VehicleSpeed', 'VehicleAcceleration'] # get short measurement with a subset of channels from 10s to 12s short = mdf.filter(important_signals).cut(start=10, stop=12) # convert to version 4.10 and save to disk short.convert('4.10').save('important signals.mf4') # plot some channels from a huge file efficient = MDF('huge.mf4') for signal in efficient.select(['Sensor1', 'Voltage3']): signal.plot() ``` Check the _examples_ folder for extended usage demo, or the documentation ## Documentation And a nicely written tutorial on the [CSS Electronics site](https://canlogger.csselectronics.com/canedge-getting-started/ce3/log-file-tools/asammdf-gui/). ## Contributing & Support Please have a look at the [contributing guidelines](CONTRIBUTING.md). If you enjoy this library please consider making a donation to the [numpy project](https://numfocus.org/donate-to-numpy) or to [danielhrisca using liberapay](https://liberapay.com/danielhrisca/donate). [![Donate using Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/danielhrisca/donate) ### Contributors Thanks to all who contributed with commits to _asammdf_: [![profile pictures of the contributors](https://contrib.rocks/image?repo=danielhrisca/asammdf)](https://github.com/danielhrisca/asammdf/graphs/contributors) ## Installation _asammdf_ is available on - GitHub: - PyPI: - conda-forge: ```shell pip install asammdf # for the GUI pip install asammdf[gui] # or for anaconda conda install -c conda-forge asammdf ``` In case a wheel is not present for your OS/Python versions and you lack the proper compiler setup to compile the C-extension code, then you can simply copy-paste the package code to your site-packages. In this way the Python fallback code will be used instead of the compiled C-extension code. ## Dependencies asammdf uses the following libraries - numpy : the heart that makes all tick - numexpr : for algebraic and rational channel conversions - wheel : for installation in virtual environments - pandas : for DataFrame export - canmatrix : to handle CAN/LIN bus logging measurements - natsort - lxml : for canmatrix arxml support - lz4 : to speed up the disk IO performance - python-dateutil : measurement start time handling Optional dependencies needed for exports - h5py : for HDF5 export - hdf5storage : for Matlab v7.3 .mat export - pyarrow : for parquet export - scipy: for Matlab v4 and v5 .mat export Other optional dependencies - PySide6 : for GUI tool - pyqtgraph : for GUI tool and Signal plotting - matplotlib : as fallback for Signal plotting - faust-cchardet : to detect non-standard Unicode encodings - chardet : to detect non-standard Unicode encodings - pyqtlet2 : for the GPS window - isal : for faster zlib compression/decompression - fsspec : access files stored in the cloud ## Benchmarks asammdf-8.5.1/asammdf.ico000066400000000000000000000360061502633300400152420ustar00rootroot00000000000000 ;PNG  IHDR>a;IDATxieUsΝߔ/T5ےGvx]`SE-MESi ,bZ@Pf񀍍lْ,YeJIMwPg&6$|ĀϜR5zjEe@(whA[B<޺\ rME'8͈^ { ]6y톺tpDX[[yz5qdSԴ\B7Zwj# *e:]%&б_"ϴS" H3?wl Αes_jsjT#F;ʱj9M  N#tƂvKONJAediµ_+)^-BҤGɶӆRd((8TQ/Y8|ɘ{`~<ίBrĐ.릩  baə0 G=~#0ZG"}gڔ4:lȋԇs6 =4*C^q,OwV~tn`@%e;3S#P٤Tֈs8g6gPo; aWHDoT+1]J?\ g][rۂgKZAػ[U0%\JA9Vhc kZl?or&''֚ ȬeQaLh֘ #wFCkFI-$0TMw6i4b˧I9L0=$T1CxoƯu(姙̀fdF#f27i˶uaUE`Tb` iVd6`W佞qX=~%B3*ԫ+eQW8:m~hظ[qdQmQ\2['5ډR VVVh2f*!P3[ihCٺ S¯~ei,Icc< QnpI,/JlYXn;1ÓŝIF _}8M el4r).riaqPl)\nN d]Yh Z1_5ܱ?A-Pdί(_yW}e]Wao9)&R]΍#&٤^#xxf-ڍn/||]H"iL7cC 8NW "px&d&8r81AQt{=zj(tk w(F:!OR>ZO^d4 @»@j-8 wynl <٧֚8IF؁/>AKS̸aDP1 z7/v8dce5vC0P XBĠQZBNw2PJ_t+}Y6dSy; ʣrF!C3!`CD16Tw$/(m8qgX1M*.$0 =7owX;;b9R,SEgӨ O-Z@fػ!VaB h**ȫBqWUvJ?E#SO&J 9Ru4;+P`Hr(b[_=3b'$NdgDK”//_)M^&X#p)_\񜅈kgCXNqz[ Y!q)f8a-   ԊRʬN?Ex diJ A=嗟 jaȒScڷ˝ scI$#Le$I1[[  zAOI!ڣiYG$t1i3EIj&o_ML1f7R s\w,C^9,$C Ǥ RXkIk pF'@ ˑKA$ Y9G$ℴd%5Z8H2B-!5se0 L'#iNJy(qwUv"*ԪeZCTB=iwEX,V+*ưȢ8fЌZ B. gDÞp³,FծRu=B(\4Ke q0G-Es8x4rM3&MS:ƄJ|CDJ{6 SF"VE^^oJ│0 q{[! $7$W0x{<'SD{'q^pM6(ݔ^jr@T D1*%8?@qcmֆi:3sa?}4 m~Nw &#IC[әM -\6R9E9ԍ3)/ -&G89JӲ XJXKF&:_[ '&)B ,R4{|XZ$(RaY!xk3ҤNhDĊtďɕE?&c0wtՓĽ5 { pt<]3@7HU9f#av0ĄT登9~.Dx|~'34Phv hXNccS hހjS)'ۖ~o@9X7O (xC<"Zm@.>A + J)bXMUC&Dъ4kvL.W};HK/7p~8Ez!it[|e-@JQ~'kLh*CRퟦ}#Ԗ>+p<>^ʱƷW Fn$z-` eUX@`AN<0aV*іPpd4A4W+{KpD XAAkfۏsx3> bXҡ]tfnM^173CHBad@亣RnZAF&4Cz w!㧘~[rK.)>|v7c$ŭ|hx-Ԥ 8c;:2zKeYVH`a nE;N)/\Env8¼:jF*w4hsh>[xzk33/9p.AQ)gG͙N`! J{;Y.)Rqv'/s-q7uq>:.zfTw62T$m#_ Ձݴ#/֛gCpӻ/`/♠ʱ%/T/%DB0/cFy 55ܿ\ Ba^ǘd՗C2Qdh76,`$ylz19WU(ggG{ysXj\#YV,jms|{7XSGkUy)yp49wR{@CĢ\FB{ܔ -)Yfgػ9'iz%yju|fԲ .2Ķr4sV3K25k-ZE"׭& S;}nBF.sy_h?sMS:2EAԎR bq#^̒f :po csWs$wpY\LL_9bza5 ~*ֶܐ}ΗٽiN]Ff^WfзTtA+E'6մn Ȳ4IPڠz 7AHBz"/ڔuBH)7ٟU|͑ÃWr`Nz7"NbPzk#d̐nP hBB3@iCc[qDTH*pRoGgf{-6G{pr}33o\륬T7 %h#PB<0׊Zj2g X ?2fB!TAEݦf Pb pR"$c@00gB QJ|\hι;ظNNG`:^牵xCT:,TBpg(*)P826ٖ}\s/_s(Dlc/ {Hk8S'QT~p jM4hEB### L NysSoD0z˼ t$Ki6ᚋCYz}<]sXj̩z~@!.dy й| sbsR<ǍB\qc@W7_ʅ[X1~=C>Պw7uX,G}kpŏ{m~aΓsJ q*ġP *،veJj$AA8O?'Yb=J.AKKbr~tr#J>, b.Vw9'"˱FWgH>-$+3P\0v`WmRL3@!M1 D/\%/+e!fH`p(B 6z-O.fr/Q9s/G+iORϖw3/1>&^6n+(,C٥k uzCw,H|$dx_*wTf.Iuq"ݼ=8KYxa|_6daѤx,PEc5:0"(#gΙXܝ-JJSʔG +D%4%HNb>˂Fӳ]X3غG8 +k*a Ύqe_'q  W?8YyɄitF=?8W0G*HL4N6$x=Yz%M;qZHRE-Q(3S@Qn~kEfc͗G{i[;$O !:H h:|+ɏ4WzB5(ChT fQk(5}Bdկ+Q%IRmDK;F0D՚^cmDYT*,QseXL)h*PsV,V&8 iǃKi`YYbգ deN@!-5AB6P|s-~S"Y8rGKCB.y + 5$9i gnx}oYmnl{~Wǘ`cueN̸%tbl@/ӄ!4n&o:"Uͫcv]x=-,"1-<]/_SP(Z*(5lЎ3*jX=r*XMx"f *S3fu)N?a"ȋΞ0'{+-efƣ]`.Shp;b}6Vzi%g>_sư1 B긕?7ov%j(2'$z=l[8Uɨ5D#so~75}'xz;g2$ h)NkA>:5f]\ I&(3v ,rB8QX5\c]#W]|9D tA"AEXz=057PE󱟙jVOnG\O<ϑ^|כ\,ohKy}Mn5w0{4B.?k'%,ugp=& K"܊yVb~f[/Sd؋$_`&+.?_qjȻ@2&p~`T 9.M8+rAaȨ )n}[KsC)p'ok#Y'$9'j/=Ufe\AձștN#t!MoY:xA[s'9 8>_^*ssX엪tN?Py߻ƍojs+>s79=\M=v2}SP eu;}2 c?4 8^ ?ȑQA]zLR Ss HL.ad*TnsB[yoµ`PKUgmk#M.Q|I)Z?nTmkȿ҄}:-it?X.[ :Ur$M:RQ@1( i#FKC{rH&ď?# +}Ia=p)p@*寋 Ŋt^ARwATEKt^n /Z}e;_]'5 $g!n]{o0x~7^n,8c{@+>;mo-gx,o/ ?zӿL'3.HFFd ?/Ey8nz2Vẖ·5oy/q::Jխ9{FٴNp2i>yNДAczm84p y;yOp y b:>TT6.%U반}[n]#kẆK&,Juc8!*h3yϻ,ل0WuBd;*slLwR Ψ?S,s\F hmG?6 -VB? j:⮵s}s`;*8QXרBuh{)I\)"B/\{g_÷>36?v_'?'澇v1aF *$ >m3CfJSϖE?M?ĻN'^fwq>:LO7)F,2)Bl€ ='V?;E_,ӠjKk#n AW/>$D_ױ*b>}.\8{{¹ܻfo5Ɉ\$"ncc.zv_˿kWw8{)zIխa(VIktM A$#D ǭubM.)Cݮr2zϡ䅕sYi-tzF׳e(@R>9=tLɰc|)R yЩ.)?-'5+7 +8yZ/csAd*"5I/j~/Ascg;xjւ]T\jbPntܫws6GޟDV 5/{=^H=[A*rγgjp_b (Z۔<'Xgėᨲh5<ªLE8W/JҔ(,ߞsXkh8j+<1C,7gO4"eZ?l͂p@u7J| ?QnXx9|>\]v`읒3:6Q[jvXg~f3[Uca9ȟ߷4nhR3m Q,ŖW&iIᙷhb`w봑6!R<ݸ RQHs|ė/,T PS5;)%{Ӑh!ЊFO 5JZJvvVf&2jMTI/D|u%aw-޹ECAWߙ:PfKsmn: ';(MTlϒ:jpa`iE';g4"MHӻw1"?EkZ맶(M3H+oǏJzGy*8`i`YjFKE$ @X5Fs)W:ުwndBrlMp8t8w8cq p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ@a7gƫlOZڟJwiiۘzZhi1;8ÆwAN)N;Clp8U` {[ZVw:ͳv>j44ZK F~m|ّ} ?FkW FmYZCj0I 6 i)CY= EhXoS^Mdc\%^;UVUiR2ZmXfh[.ml-qIKۓ`ҒԔGǥm h tEj5o}Igl:"Kx橳8NC5.9W4BtowZ)$ht[Zk%IZL_9z@)_mC@LK T hdLH0O"A[Wn|-PFY^iip8ڀv&/(eALwնlTXX\V@].45o\5`_(k㑫&$NԪ$Xi=_-ۘ-HUAUFq0LP鹥r~E@-oJ%k`I-_}%Ը4)^sS`i׼ 0elDhe'50oY{0RhO{-UP+ϼlG/XhtUklণmn{Z"h8cKEN]WtjnS)rfŬ9\Yg ^:_#gUoMX4XR:f ᷉lؖ "-S-NKnE_mPqaOf Ji  kP(nTU;~*g #,-VhT^*^mF~ Cz̹ayGuk~!]:ڮ[u<Ӑ%]2$+e~eJq56"b|&]ui4GHn&g'2P 9+YLmiC\FmKheZz1=-F6%iE]xF0o2)l&*^)?v׆ ؆BW @EkzQc)M$4aRԖƐ64۞4+_Rr]c傘%)'LmV2YQ X `IT.*~O!ԭxKJlf@UVͶe[ؖXJ\)vWyeb@R` +JQrv~KKgd6(3@:AiEېe.vM 7/pWY6t)RaKW4.NJ"[]_MS(%qȅ5G456iiZ? "m@$b_!DzZe@Bi)m$o-,CQ?߆($<ԡQ*=3B@[EmJ2Oht`%\v5yؖ@6wn5_iQIg_VLQqu)sȆAcFH.>aFw&ZhPZ-0(k j]I6̔km P_o,vEZ^s ɺ{6z{$j) vzjhIb{KQJ-"(Q6Vlic]\epϲ4h F%,0MT٦|*\:6RFئ0$FmXs;P(XT 0= ,|սWo2}ħM~{殒-(Wn53[óVtDiؖo@>-|a5WTa̽y+ӈ|!A*C6cXXZV ^s¿Td dLyX8mX۬5[Emf'-e+jʔ}HtI(ܿEƯ%Y0 ڎ ?{nBӯ"yъKvkJ[ [Ysը{=- &$-%V%Kd4"b[ WVJX& |d-Rɿ01WJU5x]#_Z@@JPZ#7ܓI(n[t% ?n,V!e} & s{70_k(?ʐl-2 <˚`>-lQZb)fmjRxC6OmSCe1N-֬#?̝/0r6Qz&Am&0C;I(zIܕ7V"b`Ve+e@ikKU2Wmڒ.=-iue,Znȏ-rwx|~><_d` J>1 TR֬l|o^huMUGqK &^A٪j|98`,:^, 5J KFxrϋ4¬ SҶi=2z/Ӳtu2H*O~ mue`֦ N`I,V( 4*DzyhNya&A3kvY;M:Ų9bw;  <ӋׄI0;m(JK 8c$Dʴ0 I %i2_ D?-M0y^{Bau<|TKl$ c R ߟ$\[ܹ!7l-IP^j?ۍEA(2&{ҲVu[ M)q~v9Hdknz*  Ϟ>+@5=ax o6\cŦ=Ds`6d:]AS M'La2#l[ZKx^Y2";7δsy_͇oڬǶ_7<_̀uKzL-9?p|tp a8hY Bx} {74`:ߨUӵ ;::ei<1= ( @ICQ4O /¢lDWmH[%چ͒ϼ2K=D("œ8[UCzBB"l~sYD iDLr6\.h.lI?[s.žz_G HeKف*g *~`cKFU0aZW|e!SQ BlI9;DW%,rlDS 텐| iɖ8hgiic}KLkI (1?jP,=hW hJMJbʲ@Se¦G,ת,ZLK rN &gVy ߴwv Ⱦς2ڔ&roq08`Kb\FTW2+h*2#0Nv ,PXڜJ, P6˜򠭷{O Q\ה}:acUteTQЦ -QIیڀ=-*mNKf^kW"LᤢZ2*՞no%Ж* 7܇Ypt)5ð>;sb3)6!;EشNv 2N_&Mr~!8vbؘ0fh$@UEa , ;9ĮĨdP.Vo0иU=a2(LsS5d{Uf0Zĵ(3M´mBtޯ*ZƿH5e c)-)Q_bnbwc{ϩp8ˠ"Pmx@.*G.2J h pս*xK39·\ ܚN.$g7%WZ43)u4gڧ+ 79fy"8YDy^Tn3`׆bf}^Q\,مBp8[[fs(ﴱA_B͌XPm-_&W{ fzͮ9['UTWw8ۆގYlJxg5;Uð)M5~<̓fMi3LYp٢WɍQJ<&'Wδִ(KQymέXɈRV`զ{( ִ@a6kAs絥q8ۆ*ʉInU[&llCUFԅ汕EXɨ2R+<A 51ζ%Z6 0 8ƴŲLYaMLM*%=JX K*6TJP W I]M\cTm `fR^qOZWLVlئ=n1(s;ӍEKTL?X6uښ*JZtJwVgvq+V)rXh2Ko4l Tac]^+&%׌Z(/w8Mv2Vc m9_kial`"s*S 2K]b ʛ2ly Fn4Ch*UPVrލA[V9YkU:֪=n /^a(^)lflMAZŕ6 @/CifSW{S;Uu5w_.qwuh<1`x򞱌ÑejB2d  YUdYڬp8gv尵Ef'D9 [^S FXp8F#57haSh9p8;IFi)^h ZZK/҇"; S44p8@)p NQ5u'%DsGNPV$"aRvJhi{6T Ro;mt^LM5,qS4Oە4puKMa 0tjMZcFa1"`<`@A(… j)YNTwf` Dݤ-̼ҪU_(t#۽Pq`ASʼ\k}'2f5!c1" Xhd*UبWDQ_p0`# o֍3F#fSǏ!e0xtdsAe500L cA6 Rp8t2'Ov|iOZG$py9Dx 0XbV"f84m2:)HMs {!NNNtYL>-N4mad:ê.( WXr΍)R]|˜Xlxү4e$+gҡÌa~{{{+|v:.sn~,D}|l:: 0N9iQ΍&zʻ>B!rZ5֒/<- IDAT|:b HӰwyHY쩶iEBP#D3LK 2 1f0&-A@`)MB㴴QqOhѶQblKҲ]{PnKZ!H6mJp p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ8p8)p #|t#>^'0,렟y9 _ `2Vq[isg𓗠#n#u|w}9;qn^ alpCwNzx[E+ѣBܸq [g_Nś!3O.pb.gbJEz^^˙cg1i_?,SQo~H,㾇}u{xx63\xTH][;]gq먃9'C(x$>ꡏFQgmew@Dqܱ*mAHsnVx[F.J8r|~|w8~}<;`yd8]/K:_ZΧ |p =S\{Iw8>vN{}lz :{goG&>wPIMc܍>~}6_ޛg/nex1 x`^]]/nr9r[7k|_~ -t=5|K}ikyI249S_+wK5AU\u!^=?y9pF/q1]X6so~} |s @mywm) !>8_L wV])C*MaN&#{ۇ>~3W+U7S7/6~o ppҏL_5l?P/i} eq_[ x{oΧ4#W Xᄓx(oeqҮs^&V΀y=EGE$uDin n6`8ex wko)~CWBL9e GW=s'op'-/7PYiΛ=ݣ 9c֙@4W nvʓQ'_6xkO_ſܜ kt|J4əb9r|0̇,8ۮ0@Dǘf8??E1_aޅA {7a.d"yf?qU݊ޗ- U x>kC[P(R"5x2LBHIWNDI ab<1fT2?fӘC4A^{8tƀ 0!!P;.78^cfYҸʌ{'=,k~bp 0LpyyY87YW8R6ui!c_>#  P`ml d:Ee: ͊p=\^^.!VGǜGl5B(C@{lnjG҆;[=^//^P(~iơ'8_a|y=ϟc2>7^!EGa:\:s,Vl>~L[U_B0|^[nsg5dI'w1L\k׮m:Z qqqW^Q+z&޼|17~ ~=z ܺuo)ʔ'O@k׮ZEE ꖍIr=7:*uyW:̓.^N&5VgaE)~Gyq_=ht-ۮrcǯu;+Ә\>{i})Ec*?olsDBTOǀ_}qK8yt$572_Dk;2_WiySW7 T_^?[$Ȳ-elYq|ul}Z,񭂫+yknp՘9ˋrp稭,}w4`;iy1K*q-%-O5aӑSss(#Z3+ih2]_G~!`#E\o|aV4tݿ"Ԟr{|jaǨz>{)1W;͖l]{t4wV(12GL~_wYUv׏Ϝ`Fr8C#v<]nvk_ݴ ôIsQsZ•{_IV4JЭR,IaVvŠZp} z ]n_wJ.Qt<޼E=.G?\]g-΍A+Uʝv_+R虻G]OZo p3sXolW.}ie8+R0-6%Le(UQٓnh**|E)Ea9"rw|mp hloz2G-ќsQ*Q؞Qv}W~KK[@z0܋oZ;c9ںcnלL&\&uUȲ{M?֕n5+zU8qʡMUכN(Df+-6rwpGObfoTj)}a/OVQ%Sڂ]E})nz)¦E{^ꧮS× d,eu$w ƀ3R=;;OpfG?q7|xj"Fk.t{?pTgZóK L"; .N W Ac& Gvn 2pyfӵ) 2M=P9SqxwN{z,_U zOH~p{oJYV9 +.r՜;4S(kMWݪS,jb,)%u5~,'xEQd=-P̚:{m㻏S~77FEi^;dM[* |4Kj2VeSJ =/5fP)Nغ_9@}LבorFʇCo})h B5e]ejk?E04p Q"Z"`:6ڮJofOO$4{[=ݫ٪8Rlb`+&&>m(M6|RJyjcUŔ4UM5|W;*[c' *RVQ)NM;עk _pGOٴQmR&-.TUje1hiI@":nQELP"Uoj*63 O^Y2 ؔ˺pc'{`>nQ$ E@H CQEaY BA+W^X,-.g10p=mlGcHtMJCqW)T-,y4w_`tx\%~%t`CQ8cT*,954زJ>򘏽r̢D[@3RLK˟;qdz4Z󛆄 S_ur{Ҋ%.<JĤP-z/f=OKGQP6MRH&!?I+Xw-֦¯2By'*xoE _;g)e^ygLFXJYMB[WuyAzXLZ݁|krݳ[P(St.R46,EqX3>;m0.!xp8x4“'O1F&pKx |'PCO>gR@9L{.C WK˖ZrF6[O]YTtj5ROPd/{j!1? If3b F`}/2_ E1Fqapp/+gPHUrwx> d2-@xfO:=pa*>yǷ y<\T{.cQXdf,1{T<.!*cQg=%&b*y_E?iSA⦛,sx\0%Y/Ă/ fGQ):7O6nUT 8R ]rxGcTSGX4YGDY.t8'8=D;W>prrOP DgqE{ܸ;r_7E=[7o+]ʧO1 WL z].n<ܼyliyBLSz=\~={q>͛ݹ,[澏L`6a<\v T|˗'Jas|eoKf3\zK {L\Nѓ.3ۚ.0č7vjjTݤl9nܸ@du*z ͔Xa<~\g0>  8=9MB}52C?--<5Nz e$DuTd,CwXj^'x\QH(A] O~x|TM|뱜0ѱɳHV1ƉuE Ͼx%kƅPK5?/==D$ʕqByv" E24NT~BK!K޿Q$mJ4$ Und8ݦa?[ǫSL|)/yuª䉣FMjdҪm(V"%ҕr>(N/Mo.*m]2EX}vsU%_ߞGC<̎o늀N"~ȬR$1(]+2/g޳ >q, B<9hC?KΫ*9YV YWJiI):J :P MB;֯:/3v*}u[9П+<$dJWV)uS }´1`3r*ջzJ%e+ű F!P%HHߩFb<=sL`$rxYaǢ4 qcғVy75,'{%wϧcvy0?1Af; IDAT,p稃@T?Ays6tM|{a@.5Ϣ? _w'.t|* _.e>ܷrpМ]:wXPc6~OwC&o4ty$&7333 kPDh6S75c=LCJ<$0; ~4$0)yIA6]gvt<h^PS$P--ܛ.@ڑڌiATxū}MJ*،E([c~lOҏ*9SSΥ(<:7D}#Zq·)Jyhip1ߊ:c&r#+ G/&ELUciHuq>YXUJ|ݖ< ;LXȘ㫘P|] C?'/uy@fjזV銇c=4 ޢ&PR4] PM:v8\qqXji.1dDZT7A@clU+}\x1?Pp&yo9Gˁ$G[g t rKj&GV) k|&苠Q=U;X`5(FQ THƿvXn ~H &ڔKt'|0a7 , z,ø |~,1 bU\/ShӷYC6߫ema4u_y?,W:?|>$Ϣ,*Li^G^Hr"ZdEүL/ @(ELb n'ci%g}aPdzb)ֵǧq> ~oUt9r=( ּ<6EX)+|C'/g.0/JS:rVHS9.*כ,IڇrR>@(R.~Ǐ_Nq<)DAI9<37i5b ҢNrA2\07Ej |^rfZ{w<ⵣ> d#24'h> N=˱b3@1 /TA_g. ΀>zdWt=.IS[uV/^?c B1q.T J.TY4='ӹx鍲qK6jc0G_?7YSDncӹI pxeoVw*Bvԙ=NX; PRr_e"S*^^#ŏjJپ"' ~} cj|&8F;ow93requp> qfX4n_SU dO^r O{i2A)5]T֔4:<4H$EJ^2T~,ϓ;sD#b3c)3")KIRk1 @4K bL dMV-#k/Մ^e$&ϝR,r0@D~Kk(n u&dD"ri{U߲rLpuI9Vg4DzD*h޴49#!ϞOS\^BM _97Zg fT4usCUXnSKc *GZRx U~b>W{9WHC.MV wV1.a I؆-X ò2!NnL%u Ձ$m̍.! "Sv2޽Of3Bo%Yɮc7*k8 $َ,`EH6ΔPzTƠD7ڑîmJ9وy Ҍ^Fx6i !GR'#[ [=d`?U,l ~lYf rwFֵq@x ΢/B_/ӤXzzdirEc)echUB}_FFs~ DW2$n S]|2-PdCTFZ48&nܐ>~:/2>% hT։BSC+rHU#R! ƀFsXVX)–u$L<:D:Ba'Li9@7s[EV_.m($g.3$P^2ܓ{C/'!|^\д6 \T=^/2ۦwʾ8kP?Wnôǀ{WG-eSf{ljmJcRI(i#vh_;HȊZf) _~0ӡ[u1 41QӲ@wj:7|W`F,osJw3: =yBau޽Lʉ8H\YWIؽ1|ɸT-,lZXi~M&fƂpM2|t2eh)'})_zS$%mR7f\ ('*NܖTԆLePm[Zb 8TmHy6 k~lW!?}Q1% `qØjl/0V*qeQIŪ?x:MdmIO"/nǁ=9Gϗ 1B$4Yfk0%3R\Sð6Hmd?y6"),~wc+giлhrfQnTaܧOCkß>)F[&DT+xNm f:wb,)˔SLavd(iF} _~>g;$ˡA @:3] 2: ljVleLph*OA&na"'~VټyPi{Rsq t\V\+U A /pՆ@Go تY5~EQm*x\wcSEqJWY `/6'¯֧L{aZU =!/zI`RNYaΣ|*O9eTcEasb&|%eˣ9 dR #Lqd9)^Lܪ܂tIt-yp9DÓQ!0iЪ_9<$K- q7O:䕾$-?Q@ss PWuŶ20 ;9,)ʎY~1fٱW+/j{Q< ~/S#hg_aN"4FP'@G63=xvzUb1h )>f!Q 1'9.JI4%G"tIڞ[>Χ"1q[ T`!/c@m>Ě3k6l[V@$ ʄLW#,Q)򥗛/flb*u^JQt-+gA{6˄.իUރɏ>yPylt=_y`v4F \ 3h.&XAh`]"6߲0Jvz.۶0|}|R N~$L*cr%iMXo*3>Uir]H~j:rG-EBg4Ej"cƟNʫY]W[ p>làHf@u>GQ}oƸ%~I &jpr/?奪{ݤ~遳I}?g SBs'_hdrL޶`Ʊ*W?|6G^!-tr_PF]P58]Ҷw1 D~LDOX=HӋ K%*eή6+B٘(L DHc2&fQ Rf[x9 =g'!F{y3g)2dJ!:rLCP eo9VI;67lnPMB(}>PK#.ou,)I_אijڌ&m, \Cd&!Fmiy:3rb)rB^3LjqQ'4=j(!jYFaы)|0ʅAبy0+'y$6q]30S_Ҧ6i Sfh/ '(Bf|E\]0&e' !(MګmJfSJyrȯ/ꥸ͐KgM}x* ϗ5 ~=^L2? ʋnJO(vU87s6>T!1>2XP(WFъ%\w;0 L-h)^V',-TGY#gR,T_Jf&J[Fa D٫:t8C %Sy)t9fJ!_S13S;ʸY ehde Ia_S`x_FD۹tJ'IO\Cܿ_h+D9 wAǨ,pVoLH 2'&IH n Q;8ʍbEFiUM{Q+c 3_l)LrU#bu,ձM#^F3RoJm_˻,K0S\mG*;v٘M܎$XMJ܍ѫ)0#Q`ou}%o/ J *\ H8=~j85铐p}~ @;m3Q+r@m) P0iWe05NZd7>q/ IVɤ4 dS5xƢ1beΫtS%2Ey F2#-45Rj>5+V,ȭC%oXanSnI^ #sٯBjZrE6EO֕'3+)nUˮ(,⢶Ѻr^S9NOf^W*RQW@d'p^P$!RB|]dA*sE^'3<~$H{r}ZhZOY_ _ƀ\a4K3Xt,\, n:'!F6oyqZٚdŐ4j!py! `77* i-UJ|spH$J|spK-3,R0&R VRj=s}rHEN_ÜܭeHgW>h@_^IdgH>MqZiH@d*L,e@]_(C+쳬T(+iY@A2BfmB0_K|(BOfϺT&)3Į3xMR&:b8  Ba&)8"kt6NLCF?•?lTm`:cO5sDqf3"D M<`2 1m t: `2" ,syToa"7)fem69l:l@n fA)M!a2EXNZ:G eU9r5Ntl7%t Ya(YG=e2P-QOCQ @ YW56{)Q[wm‘5g 3 @}!l4]@'PN2fzFRCSH5+N@p˳3 lz a~88%ɓZe.H2+ N&/T[W_Lw珆 !pq~ 0޽`A"hAWR9zx`{ ;|VQ< qyB!\98Bܻw^?pG@H,"4Mg u8ݻXhI 19F1F1>}2j[1{|݁h4a=vEކ>A1=͓Jfdc{q !0 !lCKz ǂ\!sD\2QW`vQM`{D JakE׉}0  qR:8<*nwjfƓ)~Yn!}c p|Y4pt|ÁƱ88<ʇ4Ki} # F ߿l:>Zh>:Sppp~Y :zٵf)]ai"!9f#Dg8<:BcŻiSM."OyLiIM23!CA G{@6L◽Ms8tJ**ɞ L12,y sF 0gFb^EI*U%)fR<` LMSf4ߨVϧ,AS$V|gmW<?5_ZIhBjR \?_|۲ u wlSh`q=/Jn#bGt"1  l媫4(^c!d$S̔-N94xO3ԉ6PyUZWd%d9h&hDZq!C<4Oq2|2}_'ݛE)X5֒iN57({O] `jF[45Mň;%$`fMORLAw`lv|vAG@">Bhlq IDATRK82K5"n60kj6erɶXmc1n5Lϕ2gL( ޯȮmp' u[iy{Lbpv# 7]GIJC$3Vl|"엀6T=PVӯr\u5k+1#"*N,*SO&ڑ,7)jU0=z CKL kOS#21sF&fmZja7CzWl|iޣ`0{e7ApP w BCW)sJگ~,4>.XO*& :MLz#!d2c8^#Ig~? eJ?5D@av5}~=O<ԥa_=Og.|g@$f0DF< i陃QEW;Xlqqi"zg ~XP=aͳ25=-}?/z(GVExQ$'Jѣ16d3;R&T$ܻ,yM櫶Ŧ($oRj%޵^j0Y TQv7 v6&C%hS Tdr Td+飖(9۾U!/T¢>ڳ4] GN=[Zĭ,*GjNpԉHfYEzb~W VJbKMYdw7:hNΕ2ri:3-f" Kl*ZWf=k'Jlv<*!Wys`)Ou<Η<3IBftDi}$H}&$Qbe4u1Vuh)gN|`Jn,! $Sq˴ 뗙tԛ繳6*Uk,xXW5dAHc#$nKeV#V:ϱXHc%Wү_=Jv~ Փt'ruEiڐ2QuhOq05F$}X~5gtH`@lWjgK iIDfgtx{bL3x-|Om=BaEh#a/s–BS>+fEҴE#e ׆{i,ӏ+iQ1DɛOUg\񽉕C`{Mjw5ߡ>G6yݫ<LOO(Rek*G*F՜bfa -_4MVzI%v}$~lBPqD&m#D]fWgNn@zY')}.ϯx{ Iaj&e!2,J 4]2Ct RcT=.7]v83 b K:"PH2c14HM$T:Wh;Ц.WX)%ՒEѪB䈅"eXYOQolufv^ҹ̪0_ N42b 7 XN5VJ1~ph%Z"mk@^gՓҷjEU'ݫkm,:^%i.-^Y|~R]_ڽB}ZXd71" }yqü2>$gQs+ibLYNF: BF32C 涘ۂ$?=klՍU)Pl4 8Wj= 3N }N"!aU5& 81Wb KL 1J0o[_/^I{GzmЩ]o&62߼x}jq5.vv&reP]־HיiI}!LjlI;lGyj;V8,mAK,2b6Dz85Fhoeu !O|C8(L[(@+RL1=XD^R-ZV:dO092,Vpln_a?Hd#&1k[%i%w:L}Vј4go1{;^)Ep?a?-^8h &딅EznK%,lMfo2x[&ކ?[§xL9'u>Ȇmbh!sF nb2K3 ^1&!E89FS$RqQHʌ*6i0jG^fRh{O_;װ礛K3w/Su]Vϟ\.g z2NFԻ\7V]XniGY_~:]$+Oq,I47Kמ@V[M܃%J} On $<LWؓsEIw(Y z70] eb +԰$hAöӽ 4ۂdl)UEu 5 hsq,'zo *hlˇ80,'}dMCa*nоeAQO;i;:XqGIno?ݗ,ȝ]WOެ==sN塚HnL9 @J-Vp-JTkm? !Bf8i L'2jk|N 6=N,T,~9*2S]/ȌŦ:*="8^>ϝ}f-kڡX] ;w3|p|,VniPyw&rhr0_]@rV܏"ʙγ{n<{.=s?̟.5zbfM 5jɊv ^͂e f h]D+ 7хhu/i>7,Ӏ ݪ66{TMWdU$ç%@ZR8hI,zy oeaj%URuIL3PZ2/>'~+(h̕?]!JEcTANOO4c=-5_Gx~#Ԃ&w='®:-qG|jѱ8,lꎠRy[%s 8@PnЇɘd_]ZzyQ|n` . Rjt:{ 'eur0,@ J%FQ6rBs%^]BБr $l|nYDuY^0W>ɱS~!~7I_>.B" DqCytY~`_9^?;3C?O^%@X|f*MҦY4~r$o (H\ԋ8L11,ޟ^h@l"Iu`mO+(Ei6 ֡IXn|2"3SG5>"t2WﱸDf!(ѪÊ}6LFK`ԴrLcWqв/H+w{/𥥿ɳgږL&nMlLhEE (,o>W ѻ~KUc($3&MKo`15@0&dg+Y4@6dPCdYks+W@X#q,1TEV1LQ}2 |N^ީE>gXcX~Xi=g!=hoXXBcIy9ٌC?.c p(nE֏DâXp8`L)L$!%ĤÕag._W91o֥U)Vpl|/)9LMq?x- Oh&P7a+ C[qiR9*L0!`Ra9|mȩύu;08Rwp 1YmFI ؂-fP1 vcФjp˥]Q܏qw{7$#3L%4 J_P7# Cʚ ~?y/rWT&?/-x8͆fe$Sdmy_(SmYR[üoE8I*NQEHt䴌Lj7 {# & Ŧr1֫Ⱦ] ~ 3x|u7cOqjFFYɹN6E>mѸ-^T=v!2?Qͯ9fu=)Z _ܛcE5nQ}xjgFݱ,!uxQW^ %&a &\?{-,%i$j\(-Ɲ/.$?HS+ϽMMkBZ;L2'.=TmOkV˧OzGx~5inWk]BM3Xz˛G)!:hZZ8 ^~Vg?'6_z[+s?̗}Qz8:d,7%Τn<ØL끤_*)fk`;*@5ey(t^CޗuHJ187~U3>Z ŠyAA]k.}^A~bW8^><g:G~ ;5J4%A;hJ3/c؞$d E}EﯦhR$b@0"3ڱ&ڵzOIzı `0OjMn1q|Sk)[q`pGxz'yz"5a|aF_.iMj@#PId2!YI^pH6]wwNK>iȫ+o,_^+@f+RepM ucW',;C_idLe{ # ۙ:9I/HU7bvڐpnֻW8'\3f:i1s؏qOjyU-ɻ =AljxPK2|6"ck)|˗p'WjSkCqki>sZybur,C+ZK3SRBС'DY,_ *1O51b"+PMXM n|fYi/O`f97R=?Fv4 ߮b1&ݘ㸉EG돸މ@"I_eC:60m\ɿ;KoP#ۗX |ug&b X;̖-^`|gLӫ*:B\2+l( n`?15J uBrOꠍI57ggbf;Ȥlp:87BQk=ڭ.Sl AJ?TAv !cW3 CY67\NL=0Y_ 8f8X}΀D4vKqeaED׊?l*iƶ7k'5?oՑOyj5g*NA^`6m'L@ZR5 #Wu_mؖmdè}y$Y94,|HB, mcn|YLT!0U߃@)E4vxuH k%%!vݿV}t:ضEY]yE2{Mi6+;Oql뛬l?Mk$yj#GRG_ IDATwsG} >ȝtc ^腻MeϦQcӘpX{}FZ5%Kt}$'4.~"@vq]NKhK_%ht'Ml~&E*4ͱ|PDJ.ﳳeYoWtoc[Pꕩ:/ny¬>+XngYyyJowHBߓ7{aoXbm[puK{Ƀ͂_ٶ2NMXv?`m &+̔,z={^.h&ZoB:2l^m3J<]?_3c<{^g\?YSo+\ڤ뫓GYSv^J/i]:%RY\hۗe)ixN^eY5l+"=EcOӄx"N4A/DHt]m*dI/j]EXagRS~%䉜)ww*GiS >SN-B @dvCJϋ;lLd%Kvl {%l71~e5ڦﱴmۉ?-Ip\}dBMVvHY4`vKQ Z= lY\ñr KXxG\\.r4%hrw5;ppc`u|2s,Zvp9 *`1ӟԪe &VY^>\HG1|Wi|Ol&`tA8;_1t鯳^:a̷Tsc;^B bsk-VVVVce4,+‰N˥\[JJJbY-GBUQ=Wdz WWoȀCjU:14HJ YDK,Y>T. C\8a-IyTeHvNٚhVm2T.a;NDWDxK;$tCjjL2JYdxo(P dOa6JrywQ^~+KkMusw^~_K;'kU;A+!Fћ.W*XEVT*3 $^J//=Zkn j*V<`FZΣjU" wʐ|rVHV,煼.uҍ vВT4BWDoW'q+(>nZ8YӊK݈ AcmqYn̡֫؁V Suf?չ@ؙH)Hrea}EWi1<}&]H=\1u ;G~O"j&MLdw!#cLG>?;x»S B. 1$xx`>p'op'oEscy..~>B/"ƕLe4M>Ħ_/J IPB;'$[#!29 sD.9U{$LK,5V?kyzzHk>}Y!], *!Mr Vr(aЭA\g!7tZl:vc\; wL I91ijaC-p=ǩ9r}cYيaxd)!VG +r"( 3ȿ8rHB̷TvCC;E̬ȄɲHzзն4f% [ ?ƿg+vZ-‘yeǹp4k\lv!6dž͖?>!G2)r$p *Ddox㔼!Li^*&FV-]KXqϳ➣t)qD-f`BQ+ py6gnEx7LN4DiH+hB6}۟?dwL>k?*:{/W܃l܎hj(EՁ`ruVu?%ЗtԆXDQW-=o גK؆s|prU>~/ !%ˍYnȽ:q?wܛh'&oJvƾA) e$˴b&bQ)LP|>R,`:#6۸6 W}"Zj4FrZ~-8 L"Aђequ#Qk8m /#n ݏ;c7v[ޓ ޽-1ƙ }lVVvgE"ce ^SC8))kV; S%h jh87%PG#}̝xV_*sցD^w8>Ws虼/bo1b WsED덵"յ".àoo? /bxk<ă s,0%s󬬮I ٮQ=EzF$ _ TdW}GăFkR Fk]S:D[GӮU9F|3GdLU&U5/>~Ұ v cOV:z4VR9$@6>f 0٧Fl,)K%/zóS-=C(KT"&@ZD\& `FF k2b% Psz/*`lx"aՎtm>7o?ɉs|[ C/1۽hfIk*ǹ:5NmS#@ūD^Q8@K(tQ, \fctIJJnxz]vcCaP)\x^^*bE6C*`ʱ^ ٙ.q%}iVӷgKv @x!vȈJ w)odu`0Y kbkSaP3KPdbs{yVߦ[Y8W7*YŪU8QE{c í{}=_~,_\{/˳=k4^H9ƟcۜL9 xU ϕʭ\.[TuǼ 15@ Uh4D 0:kCZ1Զ:9I Xظ~j=_YlM# e凖PRm!o?S+IuF%V&"$Nh$GChQ_Va[<_rfc1|GiQE繠5W؜l)oIē|+ =eY ǦVg}gmo]~8~Tw7pX_ג>в8_8Wis׹Ӊ$׹k,+.E&TĄ"8PTRv:o2յ5,$Ƕ%?FjVgz RCeVHS&,/a%)КXf|IϗtųH0/JK0a)8ѷiVxg&jɵU;o3=|.Ss7x fj}Z_'Y+\z˷㋩a SMNP7ō ?pKR̖,cО@Uh'!I*Lv],W< FcԆU>=EwY)a1r Kf춾6lekbH-E($G0B 2*pU£{m25W6MAjФMG9`ɽXv1zJ H6z)e(E kM wo%*ntHs_)qEy>ެ=[¾05@œD16u]qy}Ft}I#<ɤ p>!el ["EPWdw&Qv؊AΤH^xlfhĞ>TڥDvy^(}kP"XTNrޱ\Oq8b1+ZMn>aX[Jؖ(aq;CmMߡ5~E]mQ'J͝<Hlީ뵇y~V= LX"0ƎRjO=Mϋ ~$m7^rGfQݢ!#+D[ؚl#DDU*@nװQ|ަ9Ljdra)Hg={ci~(ӃEtٖZ{EOrn[MU L+QZ5KJzmW?wz3ט]_M"^|n-!~_8Sjz] /]3(rhx0vx TbjBMEސ!=4\8?2#u&sZB@ o(d)c2ȯCOӏ GaZz|5r"FcxԶQhl CuL(x D pψKv;v?! JXQRNoD)v*gd3[L*6ϱ;a<k [<˙3u^?ƅ@}1Tu [՛تfr՛تN{ag$LɢdmC^Qߏ 뚋.`%A^A\Vfa:($sP-UǹAKbL‡^ʱ}o.jF- >X~qƝ e;TOS=;#TIh?ܿJmVܷY龅p\HΓɎ3NޥF7T7׿\2sN7 /EPO{B\L4vn)H[Ѽ0ZBϕl :?:BFJS_D1a:hsi#a ٘IMD(0͠ҧfzcXL0b.3TGR5E`ngg71 ,\QrV.oByͺFCMNDu^g=w S  gk쇹\:ϟGo1JfHzґ@e{E XaLci6h0IA-H݆-C5J_oĉSҩ;Ț̓g"OFV8'd &Ls Sf\kylvB ]at,rnjtYVol큤,G9}SW8{~ǀϭZX-GyhtbzOis`QZ)?-|nA%] U+|1PGkܭ5C" ;}P$: h|jO,qۢiaЧudfzEϓپ7BcBj'2^"t[.a1Tcs>Ţz$e`L(N^ީދ\$N^ =3+*VWg|[_dopˇ _]>vLCO^vdW Cm!P<7Q_.KlأUt^PL )Cw}TX(`[0DHt1M:I(I$S^^ L5QM7>OX3` ~5 2cd Zn(MrI!^j"2T*+N񕥿W2%˝opoqk}%ʞʶll!x򥥟] FPMJYpӋRP,e=+u%D`p]=;Ocd5d E'yW ]! ~=IX344ݬ7r4G)kAAl}5},~~ӫ/WE-1 l"x2%նGTdO+F VqS:e?kC*E٩r2Vg?d5k7j|J/\<~| 8<)dGo -ʓ:Xk X9ROl0x96}h>~@/xOx5w}G(vOLY}Fw{-w9p7wm((c SJia.VB>wrĽC;q;{?'|ߜleg(ֶ YoR.m:J,M&CwXe l{rfSsB%?3L$L%l+)\hia&_\m;.a{5Xz~d"4K%;iN+4Q^뗶 -5ĜjPSLz7@~obS+ ĵי=tKljے0/xwX{ؼu.VC6NR- (ǒq!E2ij_X|arS% u?s`cK{y> LW%t sq62 -|#5/sעk R1LM8NsƶmWB j=%e:TtnMAjBDښq-K"zm.vQ$rcAӕ4 ̌e-]^F,|EbP?Q`HSnmVEcsk =o .Cb|Kڞ -K>T+|] ^ZVSxM0פhX[_\*y>g^۲dU3yKdtT;vYEH\E 4\I~9p}+˶<sIA`=qFwo[MCrv뮍C|5nt=?mŃ "OQs[\Og5SB@=:\2 : *S^$Tz=Ѫ܀H2zZ!"3\uĞOs+rK*ToXɤ<W^jr CkpmNe8r{zGB.~U` 3E+ +yX.3&.yJVÇ~dtAjYNjג{J>%5<ŋQ\q n<߹' z,qq]'R!*ۈ')E [v,wFp' [a)b- TcUGE#'<0A #izzP&T+Yr,˽Y_;gM⦂ԂBZPூv.DY:mù=N.?BTEkc<iE,'%_"tmCD'ia_"jdNSMDZ=鉡jE%.+^]󑢈]q/%~zb8:8eL["URaE#W%BZڹǙ hC5~ \Y65E+\ Ka_J g@$AɣdRgy aQa"m{>MNIٹO\TʒC/C/CTzH = KC$./ŲRH܂NAF[}ϩ冦ciK! slk,/iw'Me3{C%o~0浙p~֘ C$ϔlz;s?e5-l3| h:^-Ug#IÜjVI/H73TWʾT+*"m d`gUm%=/ vpPw)e4%_ @ʀ T¶]c̖l<깉IЭ;e( !_v%RmJCTt9nj=Mgu׆>Ca{k<7@۞祙Orts.oە|jpE]Q)[J@=@L,r{gfxuf;xINUW}};l3ʪԼKb1!ļ !(j@ 0޹{{g ܮ:uZ<9)[dxۥ!+1eut!i#;HN{_Ak.RONi%Xs})7#1f^jѾ@DCF1d#l^ `ef? Kc|93a 9PѽGIL,4wxˇ_ƼRh_7l/0oey``7,9??JIFv1/ϳ>NΧ&|g]tmƮwzZ{&ꪪU"^~ 2mI\?kAқ۵w9)RL?.bƸyw[plr?}\vyu.1o; 4S:zw$ ^h2`EɍnjV"O$A9 G>V˰Ͽ6/MBcZF2YF]Ud3eЋ}ԙ.bAc󅭬P3kY{`#'lۭ?bUI,>HHmB3?7ux8?O Ӽ1OV8[X~^|x&Fb\Ě☳6 `FP2}00V]q.+6/m,<+~]GvM`||]c2?^:+'f|8b?E~5~?>Bے^3hQ#M+2ɴ,Ew mG[fLy*@U'olplFd ^R(BsLn2$h= R-ˇ8!NHUx=)xIFd7Qt^FiH2̆,U++3~.jxkxAy&MVRvw=>Nai^FA3) 9=R1 XcMv;:iWNZ0bnmŪkcT#敌o c[BRjΤX8w Ya чDg*cbP7CkY_ez(Bg(jR2LfA}v= ;gɶ`tZUXp,Z>u4 %E2;߹l1߃S0=T 5Ӳ>}rÑWByau4wh:­IDhar/Fq,x]˓UK"f`M)h[ƪky6XrXH E9Ee򜜍ڔ/~)r_ױ2|^#˓[mW`i1'k!*H_5VHbQ f<;d AJ^0Dg8E@-m㛱8*l,͞3s h݊ߣx P]C<[~qtdޱJDI|@*zg}piXz"&Å|ha߀:>wC"~k G}h/;YuM޹>Lyb^#3eop{_ 8Vı!pA/^ \f@OI1Ts%jK(n{M[ x`ǗŁX/;Q|mWx5˂!2(ž:,OXR>ӞLr}1QORl!<8S*QD tHG*E-PE WP㒱xKH2T`Od(>_eՀv/LR,<+ 1Řep̑ FSl@9pOj׽ނ7NBŸwvMz4V/QD5 I4eP-Q$EfR δ=,w(⼩;-/Nv T( 8[an! G1'e3S[kk<j0b !J$ 1= Mr4)8OM8'bU9{K+,MڡkG mY =A/#beodUp»oT!#BQZ݊%֝|\Ihk+}eywTѥZǣA?|(;Ql'WUL`8&fqLyz߿ӞΙ#l;5]mMW؇",us&9yxRyf@٬Yvݖ[/pρ s l%FV%ա8.gfru6X,HzV,6D=?[Rv  ؓx3X`su] z\'p/,celie\?x3˺Rp,9_V*kh_k!G_bZ׽Zxur"E= F#(G>m]MeP 3pMt>~gR.%1=ļh!qt]p7 } ',+YӰU+a ϊf֤YG{ `ԙl'O^Aզ ο H3aOǟ8[-Θ_0*,MC{;=3PKX Pm)]\Ioʦ54g5mz@700[uw7;YD 7,,A.,&i o40)}cLڦ95Pf5@yXR}dpr~z9pJW|k[1[l>95 ˥ztړxLJE~>2]jGvϷ\YQ tH`Ebk+R,&oyUK>[gKnX}DA zM_u.+xFBū ^R Ј ?Ӿ3Qwgx2 /џUYRtZu,fg̩mLp}tIE4n Uzݸ٤xQ RLϵ\ӧuՊbdmMk͂]q2G gZs3Qw;pėgͶ=F&^tK}[k8@&tm)xUٖkpO׷ 0֘7YWBK޻/6Ar, n:l gm8P zp\^3Qwt-ONیm-5F _9}ްiv~M3 :w4[OrΙKB)>4 S^*qJ/`R5E܄X[ 71ro75Ϸ\5+$._6}4`9k}ʰblysY/Ų˒;_FdUnBá-g]r^UWm#~mIj g9S勥ª/5MNzhʸbE~Uٶv4~ jfCayǜ]mzjG8];z Q¦k\+kV]Y\Q1ҷQ/N`ŅZCF~v0l-ntg.Vka ]bF)/oO$F:,K ݓ^ЬnN#VZs%B)QB00/3U]UhMMR#/"cI:OH$ PG{sICacՕQZ;Pg$cQd[~i+RJ޾8 I0߃2|lgp~z)Zɘ$h^(۶QuذIFU>>ESjY(" 1agX\N)=$SISi475㸚IOE>@e'V NgmG$qٴkY @<(hni˪X&b2}f3[UDRak C%}4>Ilwئ:I*r,#4)n~Ӝymɼ= !f|ak)yȿ ?w*L@gQ&'&itwwe7tVք8|0!;o.Xk@SҸf 6֋ÇaΜ9ٴ 5S$fD=Jpa(ӃƋo&'0o<VW !$ _0^:1kA1j8F)EAWww򽼴ٿi7[35;~:8ebzs(n>| (HK{qпҴR rLch: lOSئ|ˬW8^!2~O׷~ |lV,N65sqq tw}xy:z=~3'-x#Y_-z@1(j2tK#ZGoGAd#K=̽Ninį%+V3o:W=޲MR W#~-4.%Viڤ!4K#Q)ixi~%"G@`PO1MzgZ1aĻ(易v+Jj8;oN r˭k0{/ 4*D_㪑Q&>bL?d-ʳgtIJUJ^-@d|/pߠWW8;zIA0uㄠ2][8na?Z!^TeuB@0e$x0ꝏ8[Ո,uZ3Yn@am)4/7}EU/7W͋D_x-omV̋i (;M^?+|B rjC[q GSM(ZXBO޻D5z}Hר|(Vq'>*Ngh k> pJ1;vlqs WؗPֽיە|;984mk:~s%U9 an!h .5 Ds!m" ^r,(*<]s< ڦmq˞gBi]\JRcQuގqCcCH$hoD1Ya?Ξ v,0CQ]w˖np+QzŮXz(\'4>Q|6R݌1| Чpprq#eHMU|G^~Ο_?i\2St Sԕ_ꈾ,2T4[/-Ψ)PPćzF.ೃ79?\d#B<2IR M%9ss6M#) Fv;6~X|}U,:fRjFqb%| )!}{7z5O7G=Sbwp=j4j˧ъg.|JJ?[BX혱<'Fn~ >ywCEeL묏1zqw_AtXtjRB4N= ~_9yПa"gB?+HkH?G)(NL/\5 eaV3A)ew؞߿.՝86ۍj'_]]Nc<9LyH 2Y\jůgSd7_uRùF@#2Jpķv|W =b^0v;][Uƶ@ךn ƟĚS(m ; 6BߋYC<]z1ׇێۂ$ӌ x ?dNRDqD DqG-@!%ٔz3+N`(Sf<'x+|v!y¼ wsN(/wҙ-Meqؿ0 Q :r4Z1n.>YLT?V?30Tc_TZsy4`0 /dQ.Zh{6,CvlP^AyMz/Md&6'myϥQ}_`^ 絆"V_#˿WqDAb r'`oJf+DC@fIv,LhF Fvq-89|SMg+E\:' P/4FdileސwaFUb Q l2+z4>KFo%wح@WB]{{n$crr,@MLpBGUpa( !! dYBЪ4aY$"LBRB;)"V7( $20524LOC$Ȓ`J͌2Y)iHey͌ x>oM& #XAYuh_ a@)Q>=5@p-F P%`m' +ZUfx."88R>?I ﱗus4=NC[s/N~("(S4XPCg 0OqRL#}|װ42 b vo߿:>P+ Ag  KLW 5K;e(B %ꨳFgzdEδK0͸۸a9Ν#| nQmQd%Y" (BQ-@,+TlF1 N=,~Rl?wB5+"+JSch -ůz8,H(,A(gy? vtGyw+t[ ,*Xz 7,_ĐC!Rfz0J̱t.@3zq{߭~/"ŐaRC;C}x"쨞:?/3G_X;@VK P!&祦K)ĩmӵJøv軸!zs ҈W޷t\Akxi 'i$szpԻY%tk6;UٙbS`xF:W=a",M G?߀Z? XBTaZaQ,H|P&;q+Zur,7} Qb_?5l1?S`ye'|K9as5Yk@ޞTwEւ+Ⴑ Gge<MR 6XF]S*Ruv݌n.Wk`r+ i#ޅK yՂ 1.1C!&= uW%,6n :#iĞ4ۉnugv蟋qiTa1t8c>J˫6""RF<'&cFxl;k t9ތv~t $#q4][PuF^t 2ӵŸ% Gc[qط,/offy#s3LF'BJc(3%3Ut'Ƹx=a;"V + 6p~N}LrݘtYW,( A(2]5(("HaYH1 buK/#QöFe$I|^}Et@\i^/`Y8%~vP ECp_ױ߿R IҐ$ P2ZXo PW!yNCiIx7cu ~C.^RMc8I7߅EMJ8Է4`-,A(\h ЬS\~:v\88o̔a:@_xuX|G|'⥦KVl$)P7EoJijiY#/S7Ͽ6ť?FHkʯ419ߍ AH™aSA䩊r <[?^ @qr9vHr3F8h"ie`C!w{#|1Ϧ vyx[e픺إ5[N ʼ`Op= nĢGLP*,d$aEr Θ=N,Eܖ*$"L  6r-EH`,G}KSmmŢQ G-5,#L?V,4ǧ'DxZBMlm\ok$IB%*GB8BRN|x^\^~oƯGP*ybb[oBdtXJQ'9I_'X;U8߆S&X)ŕӞ.uaП&(P~?<z& >0;{Hi!RT MPT2ecod{)*z~<2تEeR)p^>߬JOf>;!.)?ctF$fgZl'=tlˌP$+ fίyQOj~K<@)|~?DƏ#6, Gy?z(聥Z';ƴ;R)'tvd ř0pTwLtV3clXz ً 2^9ձ: `Ӈpȿe.L}L֘3X߿A ;ʀ?:7Uqu;oA]904^[X*bM)1}1-1jSa|ވ|(eW`G;T] \[kcObq MBpM8rL] W!y ]a{Ͽ1n}JJ)@5%a<% %W$M* cUyl@"oQdt^J(IinS+19yO @ qMxK-UG UGͲ,SU S'Ff?7|Bu~#!F8 37K#} Ҥ0.+*OI\Uʮp_8Wgv&6N.}l.hE)"i70w hdnͷ;yuXd"Y?ᆣ<;`O`CeC_2Cż[qXx,ͅ]!wf]D8lZwQ.Y&CfˀBȊts >8MV >;-,M{:̜λ3pªON0FyU/{,,菕k ېL%qĿP%@zXD mgܬfy/^{T 46B)jH|x3!wCkOEBXLz鬣( R487ʐ$ D|˕z^ j,Y];obtMOd}AÅ"ِ0~DAb)cy%T4dWrź88 ӞBӽ_LNy_Mn R$Ҙ8)@V)d͏!o(IP(Řw>5]M` K<"uiB(=(O!ui> 0#3Jy0 _ă7#UB .8>0}o&^9Ŕ R { Ȋ>̓rr xA烇`A?3\5X؂<( %/m7ocW`#xR*d}垷E5>-Ǝ4rfe[i/._A>Xۤ!< J.dO6XvKar/ I(>7;4ۡBt#"MYvC;hoN3>|a)@P ';C &4Μ o$4!4^+ xq།Ȳ Ayg')>>C7y'{Lvh_(D~,$<oqȿ L=#j03_;J^_ Y1 4]Vq}^)@`iJ<Ո_FdaSAay;U5,pQYt~@'>1e@S$-Mck&bM)?Wh1M4%o5kg2  Gۿޚ]pbrNLnFbOpN]AEߍt[J+/`] ,KX[A@A`{lyORMg~ǜDț"(W^'~s v7ʑSR6;WѶ?mXv@mEXLsԯ2qHGUb*QtajQ8ʯ)7ŸO\[C<%W4 ^ͅ.>_yzKFcf qs}wWek3w&p}`q({+p*AJ2C*i,OnŪsXxl^~( K /yr'{RwZK e25YCmklmN CB/G+0?|qO>~r@/Ň'")&bӜy^41[shHwzIFђePa7C<~~\~7z}1C%Ilcv|!˫)F4555x$@h ,"|zah"bP-xKX-bcL:Cx B9jR2Vşʼnɗ)S)qt&yTMMuX*x( 3sKbB?_A$(U `f&W(pJWΘ]~j Kq_;|:-Z@Clk"Mi9>(Uٶk1|LTB9(\ba1n.^ _=V!FxQC(SK*Qxi*P~%B`B >$V$Lzg((94 j7|F΃ޅܟ(di8%hyG[Kߋt8_C-QbL=; \*c.NLlKXRL3 /^ܠHymEdlWJsӗEGfgvdySq!LZC wX݈[?Uqk |K+Q6̫[Z>1nQwO!"ł4dY]Bcm8 4SPJp8x<phFd+F9t Y7(7qw"|K1[(^ H&P☟~w(&SoGU)`JGrNHӈD"`:Sd("@-S( ͨ1]a&fD4k&[}pOcGL*j jgP͚#_ZLux3;rLB, WdQG&xf4z7$CW 3c fisXz5ָ dY 6a[!_4{j("L"wj!ApA+Cpf.be>cW:#ͧi`H%% KtV8LXh PPJX&^6Rkq|}̄i)vOŽ~em|3r2@7^sZe{*>?@qĆ ~n XRܦ"PGRc@H$`J˓/fHl_H,H$|3o.0L=:1ۃiO.H)6$ۄ$>Mˣ#"OIS/YE0vhUgjG2 yP(8k*H$`Y@̏{ bQuHnŊt ŧ dYn\͘NQ$ d,{bl S`.c@%_I/'!t:nćgG+rnOCyHS% Py6p$MR<(̉7Sec?FPZh9SB˕x{өU(g* {ЙtJ, cFӴE^ k'd @0lx @20S`}&byE,M%W ȲT2 ͊P99IJge3 = x5r!E)zHÙ]H @0X@-Q<-G*|FP7ҥEQQ\9}l>r<kXBD;Z -ϕ` :g' EQ"nzw2T{ϔ9ev2{tjB@,IE70n)u/oc(I"xWC{fFx+r6bl[11` )|G晈X^RSJC[]8剭z)+LO~ ݀8bxW(+YVa&EQ(z`,وOANnf@ 9jV?&a.5s $YzkPm»V\<|#}+Q   2O.R|99ȻƐK%3K|t6,Y "^l@{0+qзqп JE)chlBlTu+ J u7@Zb/Ƣ@pbO/EDÖc3e!@K%VC$(TqS2BiIkP-( @fX@>:3$;, "T,E-8g0杋qOFyǐoEٟ֑$ $S 5C16zܼm >!W#^u2aj#x 8[V4}Q%\ʀ,IP(~L~vVLyc0@Ӂ8ێ Oƹ9H9̺\A(%q%)KY6.gi YiX vNcGQ{8%)8 @HƔcM`^J! Q;*E"&^Lp{NI×P7M2kA{$"@)6*3Z\hf^E?YJd@Jt34 o9}/15Hlw!l,6]Z ]eΤ [hYWAN/Rx؜4۟ܗ:45LjF#Q$Brs maXF57b; YzX Shq3BRde,N(TQlK)sDUrc3TRbmg chMm3-ίVI̚wT8R=PruPPJ!Wu*Sy6Z $K}m)PP@S2 ԰ -J-, hC>@K]EQ@q׬-Ir^wlQjTXWhL͗ᥦKpZhm#^J!y=fC}OaX_G$Đ^ɘ٤ a5!$yöETa0 Ӑ2BP ÂaȬA(P À4x[aX&qQqeNV-͗㥦K1 .¾kLuҕì*뇎乳R. $ 4Sz$,St!ujԶ Tèmiv` J̜3LFWHfԬ~N<&jҬ} 0# Rǰ6$>2~;]{ȿV"Tlr07{N^ 4/Qny,ٟ[tlע:}N+)2J}+^XQb ^#cyb+>2Xj{ӭ*@@UĐÕIܥ/Rʩ* &u n2E7՚3m!+{,RB_jv|xvNXށ'أ`&ζ妋W uUTL^lU`(t?=Z(h4SZ6\/nU7 RhU@4sɒjj*˾Y6}?=ҷppS-@ U7 P`aKhlP d6Gd7vjNNϵ|1z/cZ8(lGQۢiP +BL϶\g[z}8~2ii#.}ˌc;+1uX= TC g=A,ז’/ղr(.k c^{@tgD`*;w<Ӵ{u\+t>G3#FKɹu AɝooufaAZ5%Xtm..)A.vg`e1*>NBXᒿ㝪[nHҥ~ XxyԺ/Zh9c8XwPkdCJR0ݾAɚ8PnYu -[ k%#"-Q95|z7z/)oDBR(<  vBQbX d-BW|Xn$bpUW%;_1xkK(nPhK`';q3HGe*B=(Ta]{CA`ieS읤tT,c}S^kOvw,i1x<էS߬_]z Eֺux>Ѥ玵0XNmmo\W/z{<^gP~3R)h5ѻn uj{[>^,H~Gu:+ùv'fkUU +z>H~Z#˯Lkﴩں:|L{Jb{gw7z梪`zv6Wkj=u{2Nm:7>> 7,JL囋#F.o{MY,vZ[zu4^|c}s=/ǣ7з0{{NiywK\[n8 $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @U IDAT $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @f؟ΛIu?}cY?]A.L,IENDB`asammdf-8.5.1/asammdf.spec000066400000000000000000000050031502633300400154130ustar00rootroot00000000000000# -*- mode: python -*- import os from pathlib import Path import sys from PyInstaller.utils.hooks import copy_metadata from asammdf.gui.dialogs.dependencies_dlg import find_all_dependencies sys.setrecursionlimit(sys.getrecursionlimit() * 5) asammdf_path = Path.cwd() / "src" / "asammdf" / "app" / "asammdfgui.py" block_cipher = None added_files = [] # get metadata for importlib.metadata (used by DependenciesDlg) for dep in find_all_dependencies("asammdf"): added_files += copy_metadata(dep) for root, dirs, files in os.walk(asammdf_path.parent / "ui"): for file in files: if file.lower().endswith(("ui", "png", "qrc")): added_files.append((os.path.join(root, file), os.path.join("asammdf", "gui", "ui"))) import pyqtlet2 pyqtlet_path = Path(pyqtlet2.__path__[0]).resolve() site_packages = pyqtlet_path.parent site_packages_str = os.path.join(str(site_packages), "") for root, dirs, files in os.walk(pyqtlet_path): for file in files: if not file.lower().endswith(("py", "pyw")): file_name = os.path.join(root, file) dest = root.replace(site_packages_str, "") added_files.append((file_name, dest)) a = Analysis( [asammdf_path], pathex=[], binaries=[], datas=added_files, hiddenimports=[ "numpy.core._dtype_ctypes", "canmatrix.formats", "canmatrix.formats.dbc", "canmatrix.formats.arxml", "canmatrix.formats.ldf", "asammdf.blocks.cutils", "import pyqtgraph.canvas.CanvasTemplate_pyside6", "import pyqtgraph.canvas.TransformGuiTemplate_pyside6", "import pyqtgraph.console.template_pyside6", "import pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyside6", "import pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyside6", "import pyqtgraph.GraphicsScene.exportDialogTemplate_pyside6", "import pyqtgraph.imageview.ImageViewTemplate_pyside6", ], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, a.scripts, [], name="asammdfgui", exclude_binaries=True, bootloader_ignore_signals=False, debug=False, strip=False, console=False, icon="asammdf.ico", ) coll = COLLECT( exe, a.binaries, a.zipfiles, a.datas, Tree(asammdf_path.parent), upx=False, upx_exclude=[], name="asammdfgui", ) asammdf-8.5.1/bdist_wheel.bat000066400000000000000000000000541502633300400161110ustar00rootroot00000000000000run_ruff.bat && ^ python -m build --wheel asammdf-8.5.1/benchmarks/000077500000000000000000000000001502633300400152465ustar00rootroot00000000000000asammdf-8.5.1/benchmarks/bench.py000066400000000000000000001120211502633300400166740ustar00rootroot00000000000000""" benchmark asammdf vs mdfreader """ import argparse from collections.abc import Callable, Iterable from io import StringIO import multiprocessing from multiprocessing.connection import Connection import os import platform import sys import traceback from types import TracebackType import typing from typing import Literal from mdfreader import __version__ as mdfreader_version from mdfreader import Mdf as MDFreader import numpy as np import psutil from typing_extensions import Any from asammdf import __version__ as asammdf_version from asammdf import MDF, Signal from asammdf.blocks import mdf_v3, mdf_v4 import asammdf.blocks.v2_v3_blocks as v3b import asammdf.blocks.v2_v3_constants as v3c import asammdf.blocks.v4_blocks as v4b import asammdf.blocks.v4_constants as v4c try: import resource except ImportError: pass PYVERSION = sys.version_info[0] from time import perf_counter class MyList(list[str]): """list that prints the items that are appended or extended""" def append(self, item: str) -> None: """append item and print it to stdout""" print(item) super().append(item) def extend(self, items: Iterable[str]) -> None: """extend items and print them to stdout using the new line separator """ print("\n".join(items)) super().extend(items) class Timer: """measures the RAM usage and elased time. The information is saved in the output attribute and any Exception text is saved in the error attribute Parameters ---------- topic : str timer title; only used if Exceptions are raised during execution message : str execution item description fmt : str output fmt; can be "rst" (rstructured text) or "md" (markdown) """ def __init__(self, topic: str, message: str, fmt: Literal["rst", "md"] = "rst") -> None: self.topic = topic self.message = message self.output = "" self.error = "" self.fmt = fmt self.start = 0.0 def __enter__(self) -> "Timer": self.start = perf_counter() return self def __exit__( self, type_: type[BaseException] | None, value: BaseException | None, tracebackobj: TracebackType | None ) -> bool | None: elapsed_time = int((perf_counter() - self.start) * 1000) process = psutil.Process(os.getpid()) if platform.system() == "Windows": peak_wset: int = getattr(process.memory_info(), "peak_wset") # noqa: B009 ram_usage = int(peak_wset / 1024 / 1024) else: ram_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss # type: ignore[attr-defined, unused-ignore] ram_usage = int(ram_usage / 1024) if tracebackobj: info_io = StringIO() traceback.print_tb(tracebackobj, None, info_io) info_io.seek(0) info = info_io.read() self.error = f"{self.topic} : {self.message}\n{type_}\t \n{value}{info}" if self.fmt == "rst": self.output = "{:<50} {:>9} {:>8}".format(self.message, "0*", "0*") elif self.fmt == "md": self.output = "|{:<50}|{:>9}|{:>8}|".format(self.message, "0*", "0*") else: if self.fmt == "rst": self.output = f"{self.message:<50} {elapsed_time:>9} {ram_usage:>8}" elif self.fmt == "md": self.output = f"|{self.message:<50}|{elapsed_time:>9}|{ram_usage:>8}|" return True def generate_test_files(version: str = "4.10") -> str | None: cycles = 3000 channels_count = 2000 mdf = MDF(version=version) if version <= "3.30": filename = r"test.mdf" else: filename = r"test.mf4" if os.path.exists(filename): return filename t = np.arange(cycles, dtype=np.float64) cls = v4b.ChannelConversion if version >= "4.00" else v3b.ChannelConversion # no conversion sigs = [] for i in range(channels_count): sig = Signal( np.ones(cycles, dtype=np.uint64) * i, t, name=f"Channel_{i}", unit=f"unit_{i}", conversion=None, comment=f"Unsigned int 16bit channel {i}", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # linear sigs = [] for i in range(channels_count): conversion: Any = { "conversion_type": v4c.CONVERSION_TYPE_LIN if version >= "4.00" else v3c.CONVERSION_TYPE_LINEAR, "a": float(i), "b": -0.5, } sig = Signal( np.ones(cycles, dtype=np.int64), t, name=f"Channel_{i}", unit=f"unit_{i}", conversion=cls(**conversion), comment=f"Signed 16bit channel {i} with linear conversion", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # algebraic sigs = [] for i in range(channels_count): conversion = { "conversion_type": v4c.CONVERSION_TYPE_ALG if version >= "4.00" else v3c.CONVERSION_TYPE_FORMULA, "formula": f"{i} * sin(X)", } sig = Signal( np.arange(cycles, dtype=np.int32) / 100.0, t, name=f"Channel_{i}", unit=f"unit_{i}", conversion=cls(**conversion), comment=f"Sinus channel {i} with algebraic conversion", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # rational sigs = [] for i in range(channels_count): conversion = { "conversion_type": v4c.CONVERSION_TYPE_RAT if version >= "4.00" else v3c.CONVERSION_TYPE_RAT, "P1": 0, "P2": i, "P3": -0.5, "P4": 0, "P5": 0, "P6": 1, } sig = Signal( np.ones(cycles, dtype=np.int64), t, name=f"Channel_{i}", unit=f"unit_{i}", conversion=cls(**conversion), comment=f"Channel {i} with rational conversion", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # string sigs = [] for i in range(channels_count): strings = [f"Channel {i} sample {j}".encode("ascii") for j in range(cycles)] sig = Signal( np.array(strings), t, name=f"Channel_{i}", unit=f"unit_{i}", comment=f"String channel {i}", raw=True, encoding="utf-8", ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # byte array sigs = [] ones = np.ones(cycles, dtype=np.dtype("(8,)u1")) for i in range(channels_count): sig = Signal( ones * (i % 255), t, name=f"Channel_{i}", unit=f"unit_{i}", comment=f"Byte array channel {i}", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # value to text sigs = [] ones = np.ones(cycles, dtype=np.uint64) conversion = { "raw": np.arange(255, dtype=np.float64), "phys": np.array([f"Value {i}".encode("ascii") for i in range(255)]), "conversion_type": v4c.CONVERSION_TYPE_TABX if version >= "4.00" else v3c.CONVERSION_TYPE_TABX, "links_nr": 260, "ref_param_nr": 255, } for i in range(255): conversion[f"val_{i}"] = conversion[f"param_val_{i}"] = conversion["raw"][i] conversion[f"text_{i}"] = conversion["phys"][i] conversion[f"text_{255}"] = "Default" for i in range(channels_count): sig = Signal( ones * i, t, name=f"Channel_{i}", unit=f"unit_{i}", comment=f"Value to text channel {i}", conversion=cls(**conversion), raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) mdf.save(filename, overwrite=True) return None def open_mdf3(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"asammdf {asammdf_version} mdfv3", fmt) as timer: MDF(r"test.mdf") output.send([timer.output, timer.error]) def open_mdf4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"asammdf {asammdf_version} mdfv4", fmt) as timer: MDF(r"test.mf4") output.send([timer.output, timer.error]) def open_mdf4_column(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"asammdf {asammdf_version} column mdfv4", fmt) as timer: MDF(r"test_column.mf4") output.send([timer.output, timer.error]) def save_mdf3(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDF(r"test.mdf") with Timer("Save file", f"asammdf {asammdf_version} mdfv3", fmt) as timer: x.save(r"x.mdf", overwrite=True) output.send([timer.output, timer.error]) def save_mdf4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDF(r"test.mf4") with Timer("Save file", f"asammdf {asammdf_version} mdfv4", fmt) as timer: x.save(r"x.mf4", overwrite=True) output.send([timer.output, timer.error]) def save_mdf4_column(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDF(r"test_column.mf4") with Timer("Save file", f"asammdf {asammdf_version} mdfv4 column", fmt) as timer: x.save(r"x.mf4", overwrite=True) output.send([timer.output, timer.error]) def get_all_mdf3(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDF(r"test.mdf") with Timer("Get all channels", f"asammdf {asammdf_version} mdfv3", fmt) as timer: for i, gp in enumerate(x.groups): gp = typing.cast(mdf_v3.Group | mdf_v4.Group, gp) for j in range(len(gp.channels)): x.get(group=i, index=j, samples_only=True) output.send([timer.output, timer.error]) def get_all_mdf4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDF(r"test.mf4") with Timer("Get all channels", f"asammdf {asammdf_version} mdfv4", fmt) as timer: t = perf_counter() counter = 0 to_break = False for i, gp in enumerate(x.groups): gp = typing.cast(mdf_v3.Group | mdf_v4.Group, gp) if to_break: break for j in range(len(gp.channels)): t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" to_break = True break x.get(group=i, index=j, samples_only=True) counter += 1 output.send([timer.output, timer.error]) def get_all_mdf4_column(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDF(r"test_column.mf4") with Timer("Get all channels", f"asammdf {asammdf_version} column mdfv4", fmt) as timer: t = perf_counter() counter = 0 to_break = False for i, gp in enumerate(x.groups): gp = typing.cast(mdf_v3.Group | mdf_v4.Group, gp) if to_break: break for j in range(len(gp.channels)): t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" to_break = True break x.get(group=i, index=j, samples_only=False) counter += 1 output.send([timer.output, timer.error]) def convert_v3_v4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with MDF(r"test.mdf") as x: with Timer("Convert file", f"asammdf {asammdf_version} v3 to v4", fmt) as timer: x.convert("4.10") output.send([timer.output, timer.error]) def convert_v4_v410(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with MDF(r"test.mf4") as x: with Timer("Convert file", f"asammdf {asammdf_version} v4 to v410", fmt) as timer: y = x.convert("4.10") y.close() output.send([timer.output, timer.error]) def convert_v4_v420(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with MDF(r"test.mf4") as x: with Timer("Convert file", f"asammdf {asammdf_version} v4 to v420", fmt) as timer: y = x.convert("4.20") y.close() output.send([timer.output, timer.error]) def merge_v3(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: files = [r"test.mdf"] * 3 with Timer("Merge 3 files", f"asammdf {asammdf_version} v3", fmt) as timer: MDF.concatenate(files, version="3.30") output.send([timer.output, timer.error]) def merge_v4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: files = [r"test.mf4"] * 3 with Timer("Merge 3 files", f"asammdf {asammdf_version} v4", fmt) as timer: MDF.concatenate(files, version="4.10") output.send([timer.output, timer.error]) # # mdfreader # def open_reader3(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"mdfreader {mdfreader_version} mdfv3", fmt) as timer: MDFreader(r"test.mdf") output.send([timer.output, timer.error]) def open_reader3_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"mdfreader {mdfreader_version} no_data_loading mdfv3", fmt) as timer: MDFreader(r"test.mdf", no_data_loading=True) output.send([timer.output, timer.error]) def open_reader3_compression(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"mdfreader {mdfreader_version} compress mdfv3", fmt) as timer: MDFreader(r"test.mdf", compression="blosc") output.send([timer.output, timer.error]) def open_reader4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"mdfreader {mdfreader_version} mdfv4", fmt) as timer: MDFreader(r"test.mf4") output.send([timer.output, timer.error]) def open_reader4_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"mdfreader {mdfreader_version} no_data_loading mdfv4", fmt) as timer: MDFreader(r"test.mf4", no_data_loading=True) output.send([timer.output, timer.error]) def open_reader4_compression(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Open file", f"mdfreader {mdfreader_version} compress mdfv4", fmt) as timer: MDFreader(r"test.mf4", compression="blosc") output.send([timer.output, timer.error]) def save_reader3(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mdf") with Timer("Save file", f"mdfreader {mdfreader_version} mdfv3", fmt) as timer: x.write(r"x.mdf") output.send([timer.output, timer.error]) def save_reader3_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mdf", no_data_loading=True) with Timer("Save file", f"mdfreader {mdfreader_version} no_data_loading mdfv3", fmt) as timer: x.write(r"x.mdf") output.send([timer.output, timer.error]) def save_reader3_compression(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Save file", f"mdfreader {mdfreader_version} compress mdfv3", fmt) as outer_timer: x = MDFreader(r"test.mdf", compression="blosc") with Timer("Save file", f"mdfreader {mdfreader_version} compress mdfv3", fmt) as timer: x.write(r"x.mdf") output.send([timer.output, timer.error]) if outer_timer.error: output.send([timer.output, timer.error]) def save_reader4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4") with Timer("Save file", f"mdfreader {mdfreader_version} mdfv4", fmt) as timer: x.write(r"x.mf4") output.send([timer.output, timer.error]) def save_reader4_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4", no_data_loading=True) with Timer("Save file", f"mdfreader {mdfreader_version} no_data_loading mdfv4", fmt) as timer: x.write(r"x.mf4") output.send([timer.output, timer.error]) def save_reader4_compression(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4", compression="blosc") with Timer("Save file", f"mdfreader {mdfreader_version} compress mdfv4", fmt) as timer: x.write(r"x.mf4") output.send([timer.output, timer.error]) def get_all_reader3(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mdf") with Timer("Get all channels", f"mdfreader {mdfreader_version} mdfv3", fmt) as timer: for s in x: x.get_channel_data(s) output.send([timer.output, timer.error]) def get_all_reader3_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mdf", no_data_loading=True) with Timer("Get all channels", f"mdfreader {mdfreader_version} nodata mdfv3", fmt) as timer: for s in x: x.get_channel_data(s) output.send([timer.output, timer.error]) def get_all_reader3_compression(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mdf", compression="blosc") with Timer("Get all channels", f"mdfreader {mdfreader_version} compress mdfv3", fmt) as timer: for s in x: x.get_channel_data(s) with open("D:\\TMP\\f.txt", "w") as f: f.write("OK") output.send([timer.output, timer.error]) def get_all_reader4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4") with Timer("Get all channels", f"mdfreader {mdfreader_version} mdfv4", fmt) as timer: t = perf_counter() counter = 0 to_break = False for s in x: t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" to_break = True break x.get_channel_data(s) counter += 1 output.send([timer.output, timer.error]) def get_all_reader4_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4", no_data_loading=True) with Timer("Get all channels", f"mdfreader {mdfreader_version} nodata mdfv4", fmt) as timer: t = perf_counter() counter = 0 to_break = False for s in x: t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" to_break = True break x.get_channel_data(s) counter += 1 output.send([timer.output, timer.error]) def get_all_reader4_compression(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4", compression="blosc") with Timer("Get all channels", f"mdfreader {mdfreader_version} compress mdfv4", fmt) as timer: t = perf_counter() counter = 0 to_break = False for s in x: t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" to_break = True break x.get_channel_data(s) counter += 1 output.send([timer.output, timer.error]) def merge_reader_v3(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: files = [r"test.mdf"] * 3 with Timer("Merge 3 files", f"mdfreader {mdfreader_version} v3", fmt) as timer: x1 = MDFreader(files[0]) x1.resample(0.01) x2 = MDFreader(files[1]) x2.resample(0.01) x1.merge_mdf(x2) x2 = MDFreader(files[2]) x2.resample(0.01) x1.merge_mdf(x2) output.send([timer.output, timer.error]) def merge_reader_v3_compress(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: files = [r"test.mdf"] * 3 with Timer("Merge 3 files", f"mdfreader {mdfreader_version} compress v3", fmt) as timer: x1 = MDFreader(files[0], compression="blosc") x1.resample(0.01) x2 = MDFreader(files[1], compression="blosc") x2.resample(0.01) x1.merge_mdf(x2) x2 = MDFreader(files[2], compression="blosc") x2.resample(0.01) x1.merge_mdf(x2) output.send([timer.output, timer.error]) def merge_reader_v3_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: files = [r"test.mdf"] * 3 with Timer("Merge 3 files", f"mdfreader {mdfreader_version} nodata v3", fmt) as timer: x1 = MDFreader(files[0], no_data_loading=True) x1.resample(0.01) x2 = MDFreader(files[1], no_data_loading=True) x2.resample(0.01) x1.merge_mdf(x2) x2 = MDFreader(files[2], no_data_loading=True) x2.resample(0.01) x1.merge_mdf(x2) output.send([timer.output, timer.error]) def merge_reader_v4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: files = [r"test.mf4"] * 3 with Timer("Merge 3 files", f"mdfreader {mdfreader_version} v4", fmt) as timer: x1 = MDFreader(files[0]) x1.resample(0.01) x2 = MDFreader(files[1]) x2.resample(0.01) x1.merge_mdf(x2) x2 = MDFreader(files[2]) x2.resample(0.01) x1.merge_mdf(x2) output.send([timer.output, timer.error]) def merge_reader_v4_compress(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: files = [r"test.mf4"] * 3 with Timer("Merge 3 files", f"mdfreader {mdfreader_version} compress v4", fmt) as timer: x1 = MDFreader(files[0], compression="blosc") x1.resample(0.01) x2 = MDFreader(files[1], compression="blosc") x2.resample(0.01) x1.merge_mdf(x2) x2 = MDFreader(files[2], compression="blosc") x2.resample(0.01) x1.merge_mdf(x2) output.send([timer.output, timer.error]) def merge_reader_v4_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: files = [r"test.mf4"] * 3 with Timer("Merge 3 files", f"mdfreader {mdfreader_version} nodata v4", fmt) as timer: x1 = MDFreader(files[0], no_data_loading=True) x1.resample(0.01) x2 = MDFreader(files[1], no_data_loading=True) x2.resample(0.01) x1.merge_mdf(x2) x2 = MDFreader(files[2], no_data_loading=True) x2.resample(0.01) x1.merge_mdf(x2) output.send([timer.output, timer.error]) # # utility functions # def filter_asam(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Filter file", f"asammdf {asammdf_version} mdfv4", fmt) as timer: x = MDF(r"test.mf4").filter([(None, i, int(f"{j}5")) for i in range(10, 20) for j in range(1, 20)]) t = perf_counter() counter = 0 to_break = False for i, gp in enumerate(x.groups): gp = typing.cast(mdf_v3.Group | mdf_v4.Group, gp) if to_break: break for j in range(len(gp.channels)): t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" to_break = True break x.get(group=i, index=j, samples_only=True) counter += 1 output.send([timer.output, timer.error]) def filter_reader4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Filter file", f"mdfreader {mdfreader_version} mdfv4", fmt) as timer: x = MDFreader( r"test.mf4", channel_list=[f"Channel_{i}_{j}5" for i in range(10) for j in range(1, 20)], ) t = perf_counter() counter = 0 for s in x: t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" break x.get_channel_data(s) counter += 1 output.send([timer.output, timer.error]) def filter_reader4_compression(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Filter file", f"mdfreader {mdfreader_version} compression mdfv4", fmt) as timer: x = MDFreader( r"test.mf4", compression="blosc", channel_list=[f"Channel_{i}_{j}5" for i in range(10) for j in range(1, 20)], ) t = perf_counter() counter = 0 for s in x: t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" break x.get_channel_data(s) counter += 1 output.send([timer.output, timer.error]) def filter_reader4_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: with Timer("Filter file", f"mdfreader {mdfreader_version} nodata mdfv4", fmt) as timer: x = MDFreader( r"test.mf4", no_data_loading=True, channel_list=[f"Channel_{i}_{j}5" for i in range(10) for j in range(1, 20)], ) t = perf_counter() counter = 0 for s in x: t2 = perf_counter() if t2 - t > 60: timer.message += f" {counter / (t2 - t)}/s" break x.get_channel_data(s) counter += 1 output.send([timer.output, timer.error]) def cut_asam(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDF(r"test.mf4") t = x.get_master(0) start, stop = 0.2 * (t[-1] - t[0]) + t[0], 0.8 * (t[-1] - t[0]) + t[0] with Timer("Cut file", f"asammdf {asammdf_version} mdfv4", fmt) as timer: x = x.cut(start=start, stop=stop) output.send([timer.output, timer.error]) def cut_reader4(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4") t = x.get_channel_data(list(x.masterChannelList)[0]) begin, end = 0.2 * (t[-1] - t[0]) + t[0], 0.8 * (t[-1] - t[0]) + t[0] with Timer("Cut file", f"mdfreader {mdfreader_version} mdfv4", fmt) as timer: x.cut(begin=begin, end=end) output.send([timer.output, timer.error]) def cut_reader4_compression(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4", compression="blosc") t = x.get_channel_data(list(x.masterChannelList)[0]) begin, end = 0.2 * (t[-1] - t[0]) + t[0], 0.8 * (t[-1] - t[0]) + t[0] with Timer("Cut file", f"mdfreader {mdfreader_version} compression mdfv4", fmt) as timer: x.cut(begin=begin, end=end) output.send([timer.output, timer.error]) def cut_reader4_nodata(output: Connection[object, object], fmt: Literal["rst", "md"]) -> None: x = MDFreader(r"test.mf4", no_data_loading=True) t = x.get_channel_data(list(x.masterChannelList)[0]) begin, end = 0.2 * (t[-1] - t[0]) + t[0], 0.8 * (t[-1] - t[0]) + t[0] with Timer("Cut file", f"mdfreader {mdfreader_version} nodata mdfv4", fmt) as timer: x.cut(begin=begin, end=end) output.send([timer.output, timer.error]) def table_header(topic: str, fmt: Literal["rst", "md"] = "rst") -> list[str]: output = [] if fmt == "rst": result = "{:<50} {:>9} {:>8}".format(topic, "Time [ms]", "RAM [MB]") output.append("") output.append("{} {} {}".format("=" * 50, "=" * 9, "=" * 8)) output.append(result) output.append("{} {} {}".format("=" * 50, "=" * 9, "=" * 8)) elif fmt == "md": result = "|{:<50}|{:>9}|{:>8}|".format(topic, "Time [ms]", "RAM [MB]") output.append("") output.append(result) output.append("|{}|{}|{}|".format("-" * 50, "-" * 9, "-" * 8)) return output def table_end(fmt: Literal["rst", "md"] = "rst") -> list[str]: if fmt == "rst": return ["{} {} {}".format("=" * 50, "=" * 9, "=" * 8), ""] elif fmt == "md": return [ "", ] def main(text_output: bool, fmt: Literal["rst", "md"]) -> None: if os.path.dirname(__file__): os.chdir(os.path.dirname(__file__)) for version in ("3.30", "4.10"): generate_test_files(version) mdf = MDF("test.mdf", "minimum") v3_size = os.path.getsize("test.mdf") // 1024 // 1024 v3_groups = len(mdf.groups) v3_channels = sum(len(gp.channels) for gp in mdf.groups) v3_version = mdf.version mdf = MDF("test.mf4", "minimum") mdf.get_master(0) v4_size = os.path.getsize("test.mf4") // 1024 // 1024 v4_groups = len(mdf.groups) v4_channels = sum(len(gp.channels) for gp in mdf.groups) v4_version = mdf.version listen, send = multiprocessing.Pipe() output = MyList() errors: list[str] = [] installed_ram = round(psutil.virtual_memory().total / 1024 / 1024 / 1024) output.append("\n\nBenchmark environment\n") output.append(f"* {sys.version}") output.append(f"* {platform.platform()}") output.append(f"* {platform.processor()}") output.append(f"* numpy {np.__version__}") output.append(f"* {installed_ram}GB installed RAM\n") output.append("Notations used in the results\n") output.append("* compress = mdfreader mdf object created with compression=blosc") output.append("* nodata = mdfreader mdf object read with no_data_loading=True") output.append("\nFiles used for benchmark:\n") output.append(f"* mdf version {v3_version}") output.append(f" * {v3_size} MB file size") output.append(f" * {v3_groups} groups") output.append(f" * {v3_channels} channels") output.append(f"* mdf version {v4_version}") output.append(f" * {v4_size} MB file size") output.append(f" * {v4_groups} groups") output.append(f" * {v4_channels} channels\n\n") OPEN, SAVE, GET, CONVERT, MERGE, FILTER, CUT = 1, 1, 1, 1, 1, 1, 1 tests: tuple[Callable[[Connection[object, object], Literal["rst", "md"]], None], ...] = ( open_mdf3, # open_reader3, # open_reader3_nodata, # open_reader3_compression, open_mdf4, # open_mdf4_column, # open_reader4, # open_reader4_nodata, # open_reader4_compression, ) if tests and OPEN: output.extend(table_header("Open file", fmt)) for func in tests: thr = multiprocessing.Process(target=func, args=(send, fmt)) thr.start() thr.join() result, err = listen.recv() output.append(result) errors.append(err) output.extend(table_end(fmt)) tests = ( save_mdf3, # save_reader3, # save_reader3_nodata, # save_reader3_compression, save_mdf4, # save_mdf4_column, # save_reader4, # save_reader4_nodata, # save_reader4_compression, ) if tests and SAVE: output.extend(table_header("Save file", fmt)) for func in tests: thr = multiprocessing.Process(target=func, args=(send, fmt)) thr.start() thr.join() result, err = listen.recv() output.append(result) errors.append(err) output.extend(table_end(fmt)) tests = ( get_all_mdf3, # get_all_reader3, # get_all_reader3_nodata, # get_all_reader3_compression, get_all_mdf4, # get_all_mdf4_column, # get_all_reader4, # get_all_reader4_nodata, # get_all_reader4_compression, ) if tests and GET: output.extend(table_header("Get all channels (36424 calls)", fmt)) for func in tests: thr = multiprocessing.Process(target=func, args=(send, fmt)) thr.start() thr.join() result, err = listen.recv() output.append(result) errors.append(err) output.extend(table_end(fmt)) tests = ( convert_v3_v4, convert_v4_v410, convert_v4_v420, ) if tests and CONVERT: output.extend(table_header("Convert file", fmt)) for func in tests: thr = multiprocessing.Process(target=func, args=(send, fmt)) thr.start() thr.join() result, err = listen.recv() output.append(result) errors.append(err) output.extend(table_end(fmt)) tests = ( merge_v3, # merge_reader_v3, # merge_reader_v3_nodata, # merge_reader_v3_compress, merge_v4, # merge_reader_v4, # merge_reader_v4_nodata, # merge_reader_v4_compress, ) if tests and MERGE: output.extend(table_header("Merge 3 files", fmt)) for func in tests: thr = multiprocessing.Process(target=func, args=(send, fmt)) thr.start() thr.join() result, err = listen.recv() output.append(result) errors.append(err) output.extend(table_end(fmt)) tests = ( filter_asam, # filter_reader4, # filter_reader4_compression, # filter_reader4_nodata, ) if tests and FILTER: output.extend(table_header("Filter 200 channels", fmt)) for func in tests: thr = multiprocessing.Process(target=func, args=(send, fmt)) thr.start() thr.join() result, err = listen.recv() output.append(result) errors.append(err) output.extend(table_end(fmt)) tests = ( cut_asam, # cut_reader4, # cut_reader4_compression, # cut_reader4_nodata, ) if tests and CUT: output.extend(table_header("Cut file from 20% to 80%", fmt)) for func in tests: thr = multiprocessing.Process(target=func, args=(send, fmt)) thr.start() thr.join() result, err = listen.recv() output.append(result) errors.append(err) output.extend(table_end(fmt)) errors = [err for err in errors if err] if errors: print("\n\nERRORS\n", "\n".join(errors)) if text_output: arch = "x86" if platform.architecture()[0] == "32bit" else "x64" file = f"{arch}_asammdf_{asammdf_version}_mdfreader_{mdfreader_version}.{fmt}" with open(file, "w") as out: out.write("\n".join(output)) for file in ("x.mdf", "x.mf4"): if PYVERSION >= 3: try: os.remove(file) except FileNotFoundError: pass else: try: os.remove(file) except OSError: pass def _cmd_line_parser() -> argparse.ArgumentParser: """ return a command line parser. It is used when generating the documentation """ parser = argparse.ArgumentParser() parser.add_argument( "--path", help=("path to test files, if not provided the script folder is used"), ) parser.add_argument( "--text_output", action="store_true", help="option to save the results to text file", ) parser.add_argument( "--format", default="rst", nargs="?", choices=["rst", "md"], help="text formatting", ) return parser if __name__ == "__main__": cmd_parser = _cmd_line_parser() args = cmd_parser.parse_args(sys.argv[1:]) main(args.text_output, args.format) # # x = MDF(r"test_column.mf4") # with Timer("Get all channels", f"asammdf {asammdf_version} column mdfv4", "rst") as timer: # t = perf_counter() # counter = 0 # to_break = False # for i, gp in enumerate(x.groups): # gp = typing.cast(mdf_v3.Group | mdf_v4.Group, gp) # if to_break: # break # for j in range(len(gp.channels)): # t2 = perf_counter() # if t2 - t > 60: # timer.message += " {}/s".format(counter / (t2 - t)) # to_break = True # break # x.get(group=i, index=j, samples_only=True) # counter += 1 # # print(timer.output, timer.error) asammdf-8.5.1/benchmarks/gen_images.py000066400000000000000000000064001502633300400177160ustar00rootroot00000000000000""" module to generate benchmark graphs from textul result file """ from typing import Literal import matplotlib.pyplot as plt import numpy as np def generate_graphs(result: str, topic: str, aspect: Literal["ram", "time"], for_doc: bool = False) -> None: """genrate graphs from result file Parameters ---------- result : str path to result file topic : str benchmark topic; for example "Open file" or "Save file" aspect : str performance indiitemsor; can be "ram" (RAM memory usage) or "time" (elapsed time) for_doc : bool wether the source code is used inside the documentation """ with open(result) as f: lines = f.readlines() platform = "x86" if "32 bit" in lines[2] else "x64" idx = [i for i, line in enumerate(lines) if line.startswith("==")] table_spans = { "open": [idx[1] + 1, idx[2]], "save": [idx[4] + 1, idx[5]], "get": [idx[7] + 1, idx[8]], "convert": [idx[10] + 1, idx[11]], "merge": [idx[13] + 1, idx[14]], } start, stop = table_spans[topic.lower()] items = [l[:50].strip(" \t\r\n\0*") for l in lines[start:stop]] time = np.array([int(l[50:61].strip(" \t\r\n\0*")) for l in lines[start:stop]]) ram = np.array([int(l[61:].strip(" \t\r\n\0*")) for l in lines[start:stop]]) if aspect == "ram": array = ram else: array = time y_pos = list(range(len(items))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(items) + 1.2) asam_pos = [i for i, c in enumerate(items) if c.startswith("asam")] mdfreader_pos = [i for i, c in enumerate(items) if c.startswith("mdfreader")] ax.barh(asam_pos, array[asam_pos], color="green", ecolor="green") ax.barh(mdfreader_pos, array[mdfreader_pos], color="blue", ecolor="black") ax.set_yticks(y_pos) ax.set_yticklabels(items) ax.invert_yaxis() ax.set_xlabel("Time [ms]" if aspect == "time" else "RAM [MB]") if topic == "Get": ax.set_title("Get all channels (36424 calls) - {}".format("time" if aspect == "time" else "ram usage")) else: ax.set_title("{} test file - {}".format(topic, "time" if aspect == "time" else "ram usage")) ax.xaxis.grid() fig.subplots_adjust( bottom=0.72 / fig.get_figheight(), top=1 - 0.48 / fig.get_figheight(), left=0.4, right=0.9, ) if aspect == "time": if topic == "Get": name = f"{platform}_get_all_channels.png" else: name = f"{platform}_{topic.lower()}.png" else: if topic == "Get": name = f"{platform}_get_all_channels_ram_usage.png" else: name = f"{platform}_{topic.lower()}_ram_usage.png" if for_doc: plt.show() else: plt.savefig(name, dpi=300) files = ( r"e:\02__PythonWorkspace\asammdf\benchmarks\results\x64_asammdf_2.7.0_mdfreader_0.2.7.txt", r"e:\02__PythonWorkspace\asammdf\benchmarks\results\x86_asammdf_2.7.0_mdfreader_0.2.7.txt", ) for file in files: for topic in ("Open", "Save", "Get", "Convert", "Merge"): for aspect in ("time", "ram"): generate_graphs(file, topic, aspect) asammdf-8.5.1/benchmarks/how to.txt000066400000000000000000000002131502633300400172030ustar00rootroot00000000000000Add two files called "test.mdf" and "test.mf4" to a folder and select the folder for the run. run "bench.py --help" for available options.asammdf-8.5.1/benchmarks/requirements.txt000066400000000000000000000000671502633300400205350ustar00rootroot00000000000000numpy matplotlib asammdf mdfreader[compression] psutil asammdf-8.5.1/benchmarks/results/000077500000000000000000000000001502633300400167475ustar00rootroot00000000000000asammdf-8.5.1/benchmarks/results/x64_asammdf_2.1.0_mdfreader_0.2.5.txt000066400000000000000000000060111502633300400250700ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data no loaded into RAM) * compression = MDF object created with compression=True (raw channel data loaded into RAM and compressed) * noconvert = MDF object created with convertAfterRead=False Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.1.0 mdfv3 801 352 asammdf 2.1.0 compression mdfv3 946 278 asammdf 2.1.0 nodata mdfv3 490 172 mdfreader 0.2.5 mdfv3 2962 525 mdfreader 0.2.5 no convert mdfv3 2740 392 asammdf 2.1.0 mdfv4 1674 440 asammdf 2.1.0 compression mdfv4 1916 343 asammdf 2.1.0 nodata mdfv4 1360 245 mdfreader 0.2.5 mdfv4 31915 737 mdfreader 0.2.5 noconvert mdfv4 31425 607 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.1.0 mdfv3 575 353 asammdf 2.1.0 compression mdfv3 705 276 mdfreader 0.2.5 mdfv3 21591 1985 asammdf 2.1.0 mdfv4 913 447 asammdf 2.1.0 compression mdfv4 1160 352 mdfreader 0.2.5 mdfv4 18666 2782 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.1.0 mdfv3 2835 363 asammdf 2.1.0 compression mdfv3 18188 287 asammdf 2.1.0 nodata mdfv3 11926 188 mdfreader 0.2.5 mdfv3 29 525 asammdf 2.1.0 mdfv4 2338 450 asammdf 2.1.0 compression mdfv4 15566 355 asammdf 2.1.0 nodata mdfv4 12598 260 mdfreader 0.2.5 mdfv4 39 737 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_2.2.0_mdfreader_0.2.5.txt000066400000000000000000000056151502633300400251020ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = MDF object created with compression=True/blosc * compression bcolz 6 = MDF object created with compression=6 * noDataLoading = MDF object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.2.0 mdfv3 1088 379 asammdf 2.2.0 compression mdfv3 1287 298 asammdf 2.2.0 nodata mdfv3 896 198 mdfreader 0.2.5 mdfv3 3533 537 asammdf 2.2.0 mdfv4 2027 464 asammdf 2.2.0 compression mdfv4 2504 367 asammdf 2.2.0 nodata mdfv4 1668 268 mdfreader 0.2.5 mdfv4 34908 748 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.2.0 mdfv3 398 379 asammdf 2.2.0 compression mdfv3 523 302 mdfreader 0.2.5 mdfv3 23881 1997 asammdf 2.2.0 mdfv4 554 471 asammdf 2.2.0 compression mdfv4 615 373 mdfreader 0.2.5 mdfv4 21288 2795 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.2.0 mdfv3 577 383 asammdf 2.2.0 compression mdfv3 13504 306 asammdf 2.2.0 nodata mdfv3 9506 210 mdfreader 0.2.5 mdfv3 30 536 asammdf 2.2.0 mdfv4 498 469 asammdf 2.2.0 compression mdfv4 15310 377 asammdf 2.2.0 nodata mdfv4 12565 280 mdfreader 0.2.5 mdfv4 40 748 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_2.3.0_mdfreader_0.2.5.txt000066400000000000000000000051601502633300400250760ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = MDF object created with compression=blosc * compression bcolz 6 = MDF object created with compression=6 * noDataLoading = MDF object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.0 mdfv3 1011 379 asammdf 2.3.0 nodata mdfv3 725 198 mdfreader 0.2.5 mdfv3 2973 537 asammdf 2.3.0 mdfv4 1890 464 asammdf 2.3.0 nodata mdfv4 1542 268 mdfreader 0.2.5 mdfv4 32192 748 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.0 mdfv3 359 379 asammdf 2.3.0 nodata mdfv3 352 205 mdfreader 0.2.5 mdfv3 21777 1997 asammdf 2.3.0 mdfv4 525 471 asammdf 2.3.0 nodata mdfv4 542 280 mdfreader 0.2.5 mdfv4 19591 2795 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.0 mdfv3 589 383 asammdf 2.3.0 nodata mdfv3 8841 209 mdfreader 0.2.5 mdfv3 28 537 asammdf 2.3.0 mdfv4 494 468 asammdf 2.3.0 nodata mdfv4 12330 280 mdfreader 0.2.5 mdfv4 39 748 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_2.3.2_mdfreader_0.2.5.txt000066400000000000000000000051601502633300400251000ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = MDF object created with compression=blosc * compression bcolz 6 = MDF object created with compression=6 * noDataLoading = MDF object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.2 mdfv3 831 371 asammdf 2.3.2 nodata mdfv3 609 190 mdfreader 0.2.5 mdfv3 3083 536 asammdf 2.3.2 mdfv4 1710 455 asammdf 2.3.2 nodata mdfv4 1349 260 mdfreader 0.2.5 mdfv4 30847 748 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.2 mdfv3 348 371 asammdf 2.3.2 nodata mdfv3 343 197 mdfreader 0.2.5 mdfv3 21244 1997 asammdf 2.3.2 mdfv4 530 462 asammdf 2.3.2 nodata mdfv4 522 272 mdfreader 0.2.5 mdfv4 19594 2795 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.2 mdfv3 681 383 asammdf 2.3.2 nodata mdfv3 9175 209 mdfreader 0.2.5 mdfv3 29 537 asammdf 2.3.2 mdfv4 599 464 asammdf 2.3.2 nodata mdfv4 12191 273 mdfreader 0.2.5 mdfv4 38 748 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_2.4.3_mdfreader_0.2.5.txt000066400000000000000000000051601502633300400251020ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = MDF object created with compression=blosc * compression bcolz 6 = MDF object created with compression=6 * noDataLoading = MDF object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.4.3 mdfv3 768 372 asammdf 2.4.3 nodata mdfv3 597 190 mdfreader 0.2.5 mdfv3 2742 536 asammdf 2.4.3 mdfv4 1655 455 asammdf 2.4.3 nodata mdfv4 1292 260 mdfreader 0.2.5 mdfv4 29513 748 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.4.3 mdfv3 384 373 asammdf 2.4.3 nodata mdfv3 379 196 mdfreader 0.2.5 mdfv3 20888 1996 asammdf 2.4.3 mdfv4 518 462 asammdf 2.4.3 nodata mdfv4 502 272 mdfreader 0.2.5 mdfv4 18299 2795 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.4.3 mdfv3 662 381 asammdf 2.4.3 nodata mdfv3 8735 208 mdfreader 0.2.5 mdfv3 27 536 asammdf 2.4.3 mdfv4 609 464 asammdf 2.4.3 nodata mdfv4 12104 273 mdfreader 0.2.5 mdfv4 38 748 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_2.5.0_mdfreader_0.2.5.txt000066400000000000000000000057721502633300400251110ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results: * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.0 mdfv3 821 371 asammdf 2.5.0 nodata mdfv3 653 191 mdfreader 0.2.5 mdfv3 2909 537 asammdf 2.5.0 mdfv4 1694 455 asammdf 2.5.0 nodata mdfv4 1297 260 mdfreader 0.2.5 mdfv4 31074 748 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.0 mdfv3 393 373 asammdf 2.5.0 nodata mdfv3 383 198 mdfreader 0.2.5 mdfv3 21464 1997 asammdf 2.5.0 mdfv4 586 465 asammdf 2.5.0 nodata mdfv4 550 275 mdfreader 0.2.5 mdfv4 19036 2795 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.0 mdfv3 613 381 asammdf 2.5.0 nodata mdfv3 9161 207 mdfreader 0.2.5 mdfv3 28 536 asammdf 2.5.0 mdfv4 606 464 asammdf 2.5.0 nodata mdfv4 12403 275 mdfreader 0.2.5 mdfv4 40 748 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.0 v3 to v4 4773 885 asammdf 2.5.0 v3 to v4 nodata 21903 605 asammdf 2.5.0 v4 to v3 4823 882 asammdf 2.5.0 v4 to v3 nodata 26090 740 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_2.5.2_mdfreader_0.2.5.txt000066400000000000000000000073731502633300400251120ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 mdfv3 832 372 asammdf 2.5.2 nodata mdfv3 615 191 mdfreader 0.2.5 mdfv3 2876 537 asammdf 2.5.2 mdfv4 1690 455 asammdf 2.5.2 nodata mdfv4 1289 260 mdfreader 0.2.5 mdfv4 30755 748 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 mdfv3 393 373 asammdf 2.5.2 nodata mdfv3 452 198 mdfreader 0.2.5 mdfv3 21409 1997 asammdf 2.5.2 mdfv4 552 465 asammdf 2.5.2 nodata mdfv4 563 275 mdfreader 0.2.5 mdfv4 18899 2795 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 mdfv3 633 381 asammdf 2.5.2 nodata mdfv3 8703 207 mdfreader 0.2.5 mdfv3 29 537 asammdf 2.5.2 mdfv4 633 464 asammdf 2.5.2 nodata mdfv4 12241 274 mdfreader 0.2.5 mdfv4 40 748 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 v3 to v4 4504 856 asammdf 2.5.2 v3 to v4 nodata 21983 592 asammdf 2.5.2 v4 to v3 4731 883 asammdf 2.5.2 v4 to v3 nodata 26840 740 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 v3 10572 1428 asammdf 2.5.2 v3 nodata 31014 519 asammdf 2.5.2 v4 12852 1558 asammdf 2.5.2 v4 nodata 41054 610 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_2.5.3_mdfreader_0.2.5.txt000066400000000000000000000073731502633300400251130ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 mdfv3 876 357 asammdf 2.5.3 nodata mdfv3 636 181 mdfreader 0.2.5 mdfv3 3295 537 asammdf 2.5.3 mdfv4 1889 436 asammdf 2.5.3 nodata mdfv4 1498 245 mdfreader 0.2.5 mdfv4 34732 748 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 mdfv3 486 359 asammdf 2.5.3 nodata mdfv3 538 188 mdfreader 0.2.5 mdfv3 25780 1996 asammdf 2.5.3 mdfv4 628 442 asammdf 2.5.3 nodata mdfv4 579 257 mdfreader 0.2.5 mdfv4 21399 2795 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 mdfv3 732 367 asammdf 2.5.3 nodata mdfv3 10205 198 mdfreader 0.2.5 mdfv3 35 537 asammdf 2.5.3 mdfv4 688 445 asammdf 2.5.3 nodata mdfv4 14187 258 mdfreader 0.2.5 mdfv4 45 748 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 v3 to v4 5056 828 asammdf 2.5.3 v3 to v4 nodata 24569 576 asammdf 2.5.3 v4 to v3 5300 851 asammdf 2.5.3 v4 to v3 nodata 29128 725 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 v3 11408 1387 asammdf 2.5.3 v3 nodata 35575 487 asammdf 2.5.3 v4 14531 1507 asammdf 2.5.3 v4 nodata 44399 568 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_2.5.4_mdfreader_0.2.6.txt000066400000000000000000000117511502633300400251100ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 mdfv3 744 368 asammdf 2.5.4 nodata mdfv3 536 192 mdfreader 0.2.6 mdfv3 2763 546 mdfreader 0.2.6 compression mdfv3 4007 267 mdfreader 0.2.6 compression bcolz 6 mdfv3 3897 1039 mdfreader 0.2.6 noDataLoading mdfv3 1493 197 asammdf 2.5.4 mdfv4 1793 439 asammdf 2.5.4 nodata mdfv4 1317 249 mdfreader 0.2.6 mdfv4 5520 1319 mdfreader 0.2.6 compression mdfv4 7009 1031 mdfreader 0.2.6 compression bcolz 6 mdfv4 7082 1755 mdfreader 0.2.6 noDataLoading mdfv4 4724 952 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 mdfv3 459 369 asammdf 2.5.4 nodata mdfv3 524 200 mdfreader 0.2.6 mdfv3 8607 579 mdfreader 0.2.6 noDataLoading mdfv3 9265 578 mdfreader 0.2.6 compression mdfv3 8242 542 mdfreader 0.2.6 compression bcolz 6 mdfv3 7787 1039 asammdf 2.5.4 mdfv4 572 446 asammdf 2.5.4 nodata mdfv4 512 260 mdfreader 0.2.6 mdfv4 6248 1341 mdfreader 0.2.6 noDataLoading mdfv4 7095 1340 mdfreader 0.2.6 compression mdfv4 6455 1296 mdfreader 0.2.6 compression bcolz 6 mdfv4 6067 1771 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 mdfv3 605 379 asammdf 2.5.4 nodata mdfv3 9065 209 mdfreader 0.2.6 mdfv3 66 546 mdfreader 0.2.6 nodata mdfv3 80570 418 mdfreader 0.2.6 compression mdfv3 628 270 mdfreader 0.2.6 compression bcolz 6 mdfv3 273 1040 asammdf 2.5.4 mdfv4 611 448 asammdf 2.5.4 nodata mdfv4 12484 262 mdfreader 0.2.6 mdfv4 64 1319 mdfreader 0.2.6 nodata mdfv4 117087 1189 mdfreader 0.2.6 compression mdfv4 637 1041 mdfreader 0.2.6 compression bcolz 6 mdfv4 301 1762 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 v3 to v4 4640 849 asammdf 2.5.4 v3 to v4 nodata 21774 589 asammdf 2.5.4 v4 to v3 4842 854 asammdf 2.5.4 v4 to v3 nodata 26222 728 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 v3 10062 1408 asammdf 2.5.4 v3 nodata 30880 497 asammdf 2.5.4 v4 13109 1503 asammdf 2.5.4 v4 nodata 41532 565 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.6.0_mdfreader_0.2.6.txt000066400000000000000000000117511502633300400251050ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 mdfv3 780 364 asammdf 2.6.0 nodata mdfv3 562 187 mdfreader 0.2.6 mdfv3 2825 545 mdfreader 0.2.6 compression mdfv3 4198 268 mdfreader 0.2.6 compression bcolz 6 mdfv3 4041 1040 mdfreader 0.2.6 noDataLoading mdfv3 1466 198 asammdf 2.6.0 mdfv4 1717 435 asammdf 2.6.0 nodata mdfv4 1351 244 mdfreader 0.2.6 mdfv4 5589 1308 mdfreader 0.2.6 compression mdfv4 6794 1023 mdfreader 0.2.6 compression bcolz 6 mdfv4 6853 1747 mdfreader 0.2.6 noDataLoading mdfv4 4035 943 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 mdfv3 392 365 asammdf 2.6.0 nodata mdfv3 421 195 mdfreader 0.2.6 mdfv3 8355 577 mdfreader 0.2.6 noDataLoading mdfv3 1159 370 mdfreader 0.2.6 compression mdfv3 8510 543 mdfreader 0.2.6 compression bcolz 6 mdfv3 8150 1041 asammdf 2.6.0 mdfv4 438 441 asammdf 2.6.0 nodata mdfv4 479 255 mdfreader 0.2.6 mdfv4 6491 1329 mdfreader 0.2.6 noDataLoading mdfv4 1142 1117 mdfreader 0.2.6 compression mdfv4 6637 1288 mdfreader 0.2.6 compression bcolz 6 mdfv4 6349 1764 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 mdfv3 601 373 asammdf 2.6.0 nodata mdfv3 9213 203 mdfreader 0.2.6 mdfv3 71 545 mdfreader 0.2.6 noDataLoading mdfv3 18000000 198 mdfreader 0.2.6 compression mdfv3 663 272 mdfreader 0.2.6 compression bcolz 6 mdfv3 275 1041 asammdf 2.6.0 mdfv4 650 443 asammdf 2.6.0 nodata mdfv4 13256 257 mdfreader 0.2.6 mdfv4 63 1307 mdfreader 0.2.6 noDataLoading mdfv4 18000000 943 mdfreader 0.2.6 compression mdfv4 657 1031 mdfreader 0.2.6 compression bcolz 6 mdfv4 292 1754 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 v3 to v4 4658 832 asammdf 2.6.0 v3 to v4 nodata 22138 578 asammdf 2.6.0 v4 to v3 5026 838 asammdf 2.6.0 v4 to v3 nodata 26169 723 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 v3 10739 1390 asammdf 2.6.0 v3 nodata 31730 478 asammdf 2.6.0 v4 13171 1482 asammdf 2.6.0 v4 nodata 43173 545 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.6.2_mdfreader_0.2.6.txt000066400000000000000000000115351502633300400251070ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 mdfv3 757 364 asammdf 2.6.2 nodata mdfv3 537 188 mdfreader 0.2.6 mdfv3 2619 545 mdfreader 0.2.6 compression mdfv3 3928 269 mdfreader 0.2.6 compression bcolz 6 mdfv3 3826 1041 mdfreader 0.2.6 noDataLoading mdfv3 1408 198 asammdf 2.6.2 mdfv4 1785 435 asammdf 2.6.2 nodata mdfv4 1460 244 mdfreader 0.2.6 mdfv4 5246 1308 mdfreader 0.2.6 compression mdfv4 6468 1023 mdfreader 0.2.6 compression bcolz 6 mdfv4 6689 1746 mdfreader 0.2.6 noDataLoading mdfv4 3798 944 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 mdfv3 367 367 asammdf 2.6.2 nodata mdfv3 375 194 mdfreader 0.2.6 mdfv3 8522 577 mdfreader 0.2.6 compression mdfv3 8144 542 mdfreader 0.2.6 compression bcolz 6 mdfv3 7676 1040 asammdf 2.6.2 mdfv4 457 440 asammdf 2.6.2 nodata mdfv4 473 255 mdfreader 0.2.6 mdfv4 6006 1091 mdfreader 0.2.6 compression mdfv4 6271 1288 mdfreader 0.2.6 compression bcolz 6 mdfv4 5932 1763 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 mdfv3 593 373 asammdf 2.6.2 nodata mdfv3 9008 203 mdfreader 0.2.6 mdfv3 63 545 mdfreader 0.2.6 noDataLoading mdfv3 18000000 198 mdfreader 0.2.6 compression mdfv3 631 271 mdfreader 0.2.6 compression bcolz 6 mdfv3 261 1043 asammdf 2.6.2 mdfv4 623 443 asammdf 2.6.2 nodata mdfv4 16745 258 mdfreader 0.2.6 mdfv4 60 1308 mdfreader 0.2.6 noDataLoading mdfv4 18000000 943 mdfreader 0.2.6 compression mdfv4 631 1032 mdfreader 0.2.6 compression bcolz 6 mdfv4 281 1754 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 v3 to v4 4540 833 asammdf 2.6.2 v3 to v4 nodata 22162 578 asammdf 2.6.2 v4 to v3 4909 837 asammdf 2.6.2 v4 to v3 nodata 30383 723 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 v3 10287 1442 asammdf 2.6.2 v3 nodata 30281 526 asammdf 2.6.2 v4 13297 1523 asammdf 2.6.2 v4 nodata 51197 587 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.6.3_mdfreader_0.2.6.txt000066400000000000000000000115321502633300400251050ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compress = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 mdfv3 792 364 asammdf 2.6.3 nodata mdfv3 568 188 mdfreader 0.2.6 mdfv3 2693 545 mdfreader 0.2.6 compress mdfv3 3855 267 mdfreader 0.2.6 compress bcolz 6 mdfv3 3865 1040 mdfreader 0.2.6 noDataLoading mdfv3 1438 199 asammdf 2.6.3 mdfv4 1866 435 asammdf 2.6.3 nodata mdfv4 1480 244 mdfreader 0.2.6 mdfv4 5394 1307 mdfreader 0.2.6 compress mdfv4 6541 1023 mdfreader 0.2.6 compress bcolz 6 mdfv4 6670 1746 mdfreader 0.2.6 noDataLoading mdfv4 3940 944 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 mdfv3 346 365 asammdf 2.6.3 nodata mdfv3 374 194 mdfreader 0.2.6 mdfv3 7861 576 mdfreader 0.2.6 compress mdfv3 7935 543 mdfreader 0.2.6 compress bcolz 6 mdfv3 7563 1041 asammdf 2.6.3 mdfv4 475 441 asammdf 2.6.3 nodata mdfv4 443 256 mdfreader 0.2.6 mdfv4 5979 1329 mdfreader 0.2.6 compress mdfv4 6194 1287 mdfreader 0.2.6 compress bcolz6 mdfv4 5884 1763 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 mdfv3 590 370 asammdf 2.6.3 nodata mdfv3 8521 199 mdfreader 0.2.6 mdfv3 59 545 mdfreader 0.2.6 noDataLoading mdfv3 18000000 198 mdfreader 0.2.6 compress mdfv3 609 270 mdfreader 0.2.6 compress bcolz 6 mdfv3 252 1042 asammdf 2.6.3 mdfv4 627 443 asammdf 2.6.3 nodata mdfv4 16623 254 mdfreader 0.2.6 mdfv4 60 1307 mdfreader 0.2.6 noDataLoading mdfv4 18000000 943 mdfreader 0.2.6 compress mdfv4 591 1030 mdfreader 0.2.6 compress bcolz 6 mdfv4 277 1753 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 v3 to v4 4674 833 asammdf 2.6.3 v3 to v4 nodata 20945 578 asammdf 2.6.3 v4 to v3 5057 835 asammdf 2.6.3 v4 to v3 nodata 30132 723 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 v3 10545 1439 asammdf 2.6.3 v3 nodata 30476 526 asammdf 2.6.3 v4 13780 1524 asammdf 2.6.3 v4 nodata 51810 587 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.6.4_mdfreader_0.2.6.txt000066400000000000000000000113161502633300400251060ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compress = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 mdfv3 781 364 asammdf 2.6.4 nodata mdfv3 570 187 mdfreader 0.2.6 mdfv3 2675 545 mdfreader 0.2.6 compress mdfv3 3791 268 mdfreader 0.2.6 compress bcolz 6 mdfv3 3910 1040 mdfreader 0.2.6 noDataLoading mdfv3 1436 199 asammdf 2.6.4 mdfv4 1921 435 asammdf 2.6.4 nodata mdfv4 1476 244 mdfreader 0.2.6 mdfv4 5520 1307 mdfreader 0.2.6 compress mdfv4 6529 1024 mdfreader 0.2.6 compress bcolz 6 mdfv4 6757 1746 mdfreader 0.2.6 noDataLoading mdfv4 3948 943 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 mdfv3 375 365 asammdf 2.6.4 nodata mdfv3 360 194 mdfreader 0.2.6 mdfv3 7983 578 mdfreader 0.2.6 compress mdfv3 7966 543 mdfreader 0.2.6 compress bcolz 6 mdfv3 7566 1041 asammdf 2.6.4 mdfv4 493 440 asammdf 2.6.4 nodata mdfv4 444 256 mdfreader 0.2.6 mdfv4 6015 1329 mdfreader 0.2.6 compress mdfv4 6105 1288 mdfreader 0.2.6 compress bcolz6 mdfv4 5875 1763 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 mdfv3 636 370 asammdf 2.6.4 nodata mdfv3 8535 200 mdfreader 0.2.6 mdfv3 59 545 mdfreader 0.2.6 compress mdfv3 605 270 mdfreader 0.2.6 compress bcolz 6 mdfv3 255 1042 asammdf 2.6.4 mdfv4 675 443 asammdf 2.6.4 nodata mdfv4 16774 254 mdfreader 0.2.6 mdfv4 61 1308 mdfreader 0.2.6 compress mdfv4 598 1030 mdfreader 0.2.6 compress bcolz 6 mdfv4 276 1753 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 v3 to v4 3420 823 asammdf 2.6.4 v3 to v4 nodata 18877 572 asammdf 2.6.4 v4 to v3 4009 832 asammdf 2.6.4 v4 to v3 nodata 28683 718 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 v3 8251 1448 asammdf 2.6.4 v3 nodata 27406 535 asammdf 2.6.4 v4 12183 1537 asammdf 2.6.4 v4 nodata 48747 602 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.6.5_mdfreader_0.2.6.txt000066400000000000000000000113161502633300400251070ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compress = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 mdfv3 779 364 asammdf 2.6.5 nodata mdfv3 551 187 mdfreader 0.2.6 mdfv3 2672 545 mdfreader 0.2.6 compress mdfv3 3844 267 mdfreader 0.2.6 compress bcolz 6 mdfv3 3886 1040 mdfreader 0.2.6 noDataLoading mdfv3 1400 198 asammdf 2.6.5 mdfv4 1883 435 asammdf 2.6.5 nodata mdfv4 1457 244 mdfreader 0.2.6 mdfv4 5371 1307 mdfreader 0.2.6 compress mdfv4 6470 1023 mdfreader 0.2.6 compress bcolz 6 mdfv4 6894 1746 mdfreader 0.2.6 noDataLoading mdfv4 4078 943 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 mdfv3 356 366 asammdf 2.6.5 nodata mdfv3 398 195 mdfreader 0.2.6 mdfv3 10164 577 mdfreader 0.2.6 compress mdfv3 12341 542 mdfreader 0.2.6 compress bcolz 6 mdfv3 11427 958 asammdf 2.6.5 mdfv4 805 440 asammdf 2.6.5 nodata mdfv4 522 255 mdfreader 0.2.6 mdfv4 7256 1328 mdfreader 0.2.6 compress mdfv4 7010 1288 mdfreader 0.2.6 compress bcolz6 mdfv4 6688 1763 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 mdfv3 657 370 asammdf 2.6.5 nodata mdfv3 9647 200 mdfreader 0.2.6 mdfv3 67 544 mdfreader 0.2.6 compress mdfv3 698 270 mdfreader 0.2.6 compress bcolz 6 mdfv3 267 1042 asammdf 2.6.5 mdfv4 736 443 asammdf 2.6.5 nodata mdfv4 13552 254 mdfreader 0.2.6 mdfv4 64 1307 mdfreader 0.2.6 compress mdfv4 631 1031 mdfreader 0.2.6 compress bcolz 6 mdfv4 304 1753 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 v3 to v4 3675 823 asammdf 2.6.5 v3 to v4 nodata 4607 379 asammdf 2.6.5 v4 to v3 4442 831 asammdf 2.6.5 v4 to v3 nodata 5105 366 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 v3 8605 1449 asammdf 2.6.5 v3 nodata 11089 544 asammdf 2.6.5 v4 13469 1536 asammdf 2.6.5 v4 nodata 15565 600 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.7.0_mdfreader_0.2.7.txt000066400000000000000000000137421502633300400251110ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full mdfv3 737 339 asammdf 2.7.0 low mdfv3 648 187 asammdf 2.7.0 minimum mdfv3 395 98 mdfreader 0.2.7 mdfv3 2310 465 mdfreader 0.2.7 compress mdfv3 3565 200 mdfreader 0.2.7 compress bcolz 6 mdfv3 3706 1535 mdfreader 0.2.7 noDataLoading mdfv3 658 188 asammdf 2.7.0 full mdfv4 1840 403 asammdf 2.7.0 low mdfv4 1765 238 asammdf 2.7.0 minimum mdfv4 1261 110 mdfreader 0.2.7 mdfv4 4660 467 mdfreader 0.2.7 compress mdfv4 5813 181 mdfreader 0.2.7 compress bcolz 6 mdfv4 6113 1433 mdfreader 0.2.7 noDataLoading mdfv4 3226 211 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full mdfv3 329 342 asammdf 2.7.0 low mdfv3 383 194 asammdf 2.7.0 minimum mdfv3 926 107 mdfreader 0.2.7 mdfv3 8053 482 mdfreader 0.2.7 noDataLoading mdfv3 8762 566 mdfreader 0.2.7 compress mdfv3 7975 451 mdfreader 0.2.7 compress bcolz 6 mdfv3 7875 1534 asammdf 2.7.0 full mdfv4 412 408 asammdf 2.7.0 low mdfv4 464 248 asammdf 2.7.0 minimum mdfv4 2003 118 mdfreader 0.2.7 mdfv4 7498 485 mdfreader 0.2.7 noDataLoading mdfv4 6767 595 mdfreader 0.2.7 compress mdfv4 7701 441 mdfreader 0.2.7 compress bcolz6 mdfv4 7517 1444 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full mdfv3 635 346 asammdf 2.7.0 low mdfv3 3222 199 asammdf 2.7.0 minimum mdfv3 4347 113 mdfreader 0.2.7 mdfv3 58 464 mdfreader 0.2.7 nodata mdfv3 1117 403 mdfreader 0.2.7 compress mdfv3 599 199 mdfreader 0.2.7 compress bcolz 6 mdfv3 248 1534 asammdf 2.7.0 full mdfv4 687 410 asammdf 2.7.0 low mdfv4 6612 248 asammdf 2.7.0 minimum mdfv4 8661 122 mdfreader 0.2.7 mdfv4 56 467 mdfreader 0.2.7 nodata mdfv4 1506 444 mdfreader 0.2.7 compress mdfv4 598 187 mdfreader 0.2.7 compress bcolz 6 mdfv4 278 1439 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full v3 to v4 3505 498 asammdf 2.7.0 low v3 to v4 3697 352 asammdf 2.7.0 minimum v3 to v4 4426 267 asammdf 2.7.0 full v4 to v3 3788 497 asammdf 2.7.0 low v4 to v3 4225 334 asammdf 2.7.0 minimum v4 to v3 6625 210 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full v3 7828 1333 asammdf 2.7.0 low v3 9350 476 asammdf 2.7.0 minimum v3 11020 249 mdfreader 0.2.7 v3 11437 2963 asammdf 2.7.0 full v4 11869 1455 asammdf 2.7.0 low v4 12764 571 asammdf 2.7.0 minimum v4 16559 249 mdfreader 0.2.7 v4 16126 2966 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.8.0_mdfreader_2.7.2.txt000066400000000000000000000127661502633300400251210ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full mdfv3 772 319 asammdf 2.8.0 low mdfv3 656 165 asammdf 2.8.0 minimum mdfv3 441 77 mdfreader 2.7.2 mdfv3 1783 428 mdfreader 2.7.2 compress mdfv3 3330 127 mdfreader 2.7.2 noDataLoading mdfv3 699 167 asammdf 2.8.0 full mdfv4 1903 381 asammdf 2.8.0 low mdfv4 1783 216 asammdf 2.8.0 minimum mdfv4 1348 88 mdfreader 2.7.2 mdfv4 4849 442 mdfreader 2.7.2 compress mdfv4 6347 138 mdfreader 2.7.2 noDataLoading mdfv4 3425 176 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full mdfv3 359 321 asammdf 2.8.0 low mdfv3 415 172 asammdf 2.8.0 minimum mdfv3 993 86 mdfreader 2.7.2 mdfv3 8402 456 mdfreader 2.7.2 compress mdfv3 8364 424 asammdf 2.8.0 full mdfv4 497 387 asammdf 2.8.0 low mdfv4 507 228 asammdf 2.8.0 minimum mdfv4 2179 97 mdfreader 2.7.2 mdfv4 7958 460 mdfreader 2.7.2 compress mdfv4 8170 417 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full mdfv3 772 325 asammdf 2.8.0 low mdfv3 3784 179 asammdf 2.8.0 minimum mdfv3 5076 92 mdfreader 2.7.2 mdfv3 65 428 mdfreader 2.7.2 nodata mdfv3 1231 379 mdfreader 2.7.2 compress mdfv3 487 127 asammdf 2.8.0 full mdfv4 800 389 asammdf 2.8.0 low mdfv4 7025 226 asammdf 2.8.0 minimum mdfv4 9518 100 mdfreader 2.7.2 mdfv4 71 442 mdfreader 2.7.2 nodata mdfv4 1575 404 mdfreader 2.7.2 compress mdfv4 508 145 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full v3 to v4 3461 751 asammdf 2.8.0 low v3 to v4 4092 331 asammdf 2.8.0 minimum v3 to v4 4852 163 asammdf 2.8.0 full v4 to v3 3732 753 asammdf 2.8.0 low v4 to v3 4348 313 asammdf 2.8.0 minimum v4 to v3 7136 134 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full v3 8152 1312 asammdf 2.8.0 low v3 9839 456 asammdf 2.8.0 minimum v3 11694 228 mdfreader 2.7.2 v3 10352 2927 mdfreader 2.7.2 compress v3 15314 2940 asammdf 2.8.0 full v4 11938 1434 asammdf 2.8.0 low v4 13154 549 asammdf 2.8.0 minimum v4 17188 229 mdfreader 2.7.2 v4 16536 2941 mdfreader 2.7.2 compress v4 21261 2951 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.8.1_mdfreader_2.7.3.txt000066400000000000000000000127661502633300400251230ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.16299-SP0 * Intel64 Family 6 Model 69 Stepping 1, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 1100 327 asammdf 2.8.1 low mdfv3 980 174 asammdf 2.8.1 minimum mdfv3 599 86 mdfreader 2.7.3 mdfv3 2567 436 mdfreader 2.7.3 compress mdfv3 4324 135 mdfreader 2.7.3 noDataLoading mdfv3 973 176 asammdf 2.8.1 full mdfv4 2613 390 asammdf 2.8.1 low mdfv4 2491 225 asammdf 2.8.1 minimum mdfv4 1749 97 mdfreader 2.7.3 mdfv4 6457 448 mdfreader 2.7.3 compress mdfv4 8219 147 mdfreader 2.7.3 noDataLoading mdfv4 4221 180 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 676 327 asammdf 2.8.1 low mdfv3 541 181 asammdf 2.8.1 minimum mdfv3 1363 95 mdfreader 2.7.3 mdfv3 8013 465 mdfreader 2.7.3 noDataLoading mdfv3 8948 476 mdfreader 2.7.3 compress mdfv3 7629 432 asammdf 2.8.1 full mdfv4 672 395 asammdf 2.8.1 low mdfv4 736 237 asammdf 2.8.1 minimum mdfv4 3127 107 mdfreader 2.7.3 mdfv4 7237 467 mdfreader 2.7.3 noDataLoading mdfv4 8332 473 mdfreader 2.7.3 compress mdfv4 6791 426 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 967 333 asammdf 2.8.1 low mdfv3 5690 186 asammdf 2.8.1 minimum mdfv3 7296 99 mdfreader 2.7.3 mdfv3 95 436 mdfreader 2.7.3 compress mdfv3 531 135 asammdf 2.8.1 full mdfv4 988 397 asammdf 2.8.1 low mdfv4 10572 234 asammdf 2.8.1 minimum mdfv4 13803 108 mdfreader 2.7.3 mdfv4 95 448 mdfreader 2.7.3 compress mdfv4 534 148 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full v3 to v4 4986 759 asammdf 2.8.1 low v3 to v4 5573 340 asammdf 2.8.1 minimum v3 to v4 7049 171 asammdf 2.8.1 full v4 to v3 5705 761 asammdf 2.8.1 low v4 to v3 6510 321 asammdf 2.8.1 minimum v4 to v3 10434 142 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full v3 12251 1320 asammdf 2.8.1 low v3 14453 464 asammdf 2.8.1 minimum v3 16830 236 mdfreader 2.7.3 v3 15635 983 mdfreader 2.7.3 compress v3 20812 993 asammdf 2.8.1 full v4 18172 1441 asammdf 2.8.1 low v4 20083 558 asammdf 2.8.1 minimum v4 26374 237 mdfreader 2.7.3 v4 23450 981 mdfreader 2.7.3 compress v4 28421 985 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_2.8.1_mdfreader_2.7.4.txt000066400000000000000000000133101502633300400251060ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.16299-SP0 * Intel64 Family 6 Model 69 Stepping 1, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 1054 317 asammdf 2.8.1 low mdfv3 919 164 asammdf 2.8.1 minimum mdfv3 592 76 mdfreader 2.7.4 mdfv3 2545 426 mdfreader 2.7.4 compress mdfv3 4188 126 mdfreader 2.7.4 noDataLoading mdfv3 1015 173 asammdf 2.8.1 full mdfv4 2438 380 asammdf 2.8.1 low mdfv4 2311 215 asammdf 2.8.1 minimum mdfv4 1649 87 mdfreader 2.7.4 mdfv4 6176 438 mdfreader 2.7.4 compress mdfv4 7940 137 mdfreader 2.7.4 noDataLoading mdfv4 4013 180 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 507 319 asammdf 2.8.1 low mdfv3 515 171 asammdf 2.8.1 minimum mdfv3 1263 84 mdfreader 2.7.4 mdfv3 7590 454 mdfreader 2.7.4 noDataLoading mdfv3 0* 0* mdfreader 2.7.4 compress mdfv3 7236 423 asammdf 2.8.1 full mdfv4 599 385 asammdf 2.8.1 low mdfv4 703 227 asammdf 2.8.1 minimum mdfv4 3157 97 mdfreader 2.7.4 mdfv4 6764 457 mdfreader 2.7.4 noDataLoading mdfv4 8053 476 mdfreader 2.7.4 compress mdfv4 6677 416 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 1016 323 asammdf 2.8.1 low mdfv3 5599 177 asammdf 2.8.1 minimum mdfv3 7105 91 mdfreader 2.7.4 mdfv3 102 426 mdfreader 2.7.4 nodata mdfv3 16651 208 mdfreader 2.7.4 compress mdfv3 515 126 asammdf 2.8.1 full mdfv4 1080 388 asammdf 2.8.1 low mdfv4 10658 225 asammdf 2.8.1 minimum mdfv4 13554 98 mdfreader 2.7.4 mdfv4 91 438 mdfreader 2.7.4 nodata mdfv4 26847 204 mdfreader 2.7.4 compress mdfv4 517 138 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full v3 to v4 4995 750 asammdf 2.8.1 low v3 to v4 5646 330 asammdf 2.8.1 minimum v3 to v4 6902 161 asammdf 2.8.1 full v4 to v3 5750 751 asammdf 2.8.1 low v4 to v3 6572 313 asammdf 2.8.1 minimum v4 to v3 10229 133 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full v3 12050 1311 asammdf 2.8.1 low v3 14122 454 asammdf 2.8.1 minimum v3 16537 227 mdfreader 2.7.4 v3 14710 974 mdfreader 2.7.4 compress v3 19571 982 asammdf 2.8.1 full v4 17569 1431 asammdf 2.8.1 low v4 19297 548 asammdf 2.8.1 minimum v4 25442 227 mdfreader 2.7.4 v4 22324 971 mdfreader 2.7.4 nodata v4 21581 1013 mdfreader 2.7.4 compress v4 26916 974 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_3.0.0_mdfreader_2.7.5.txt000066400000000000000000000133501502633300400251030ustar00rootroot00000000000000Benchmark environment * 3.6.4 (default, Jan 5 2018, 02:35:40) [GCC 7.2.1 20171224] * Linux-4.15.0-1-MANJARO-x86_64-with-arch-Manjaro-Linux * * 4GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 3.0.0 full mdfv3 706 256 asammdf 3.0.0 low mdfv3 637 103 asammdf 3.0.0 minimum mdfv3 612 64 mdfreader 2.7.5 mdfv3 2201 414 mdfreader 2.7.5 compress mdfv3 1871 281 mdfreader 2.7.5 noDataLoading mdfv3 948 160 asammdf 3.0.0 full mdfv4 2599 296 asammdf 3.0.0 low mdfv4 2485 131 asammdf 3.0.0 minimum mdfv4 1376 64 mdfreader 2.7.5 mdfv4 5706 435 mdfreader 2.7.5 compress mdfv4 5453 303 mdfreader 2.7.5 noDataLoading mdfv4 3904 181 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 3.0.0 full mdfv3 468 258 asammdf 3.0.0 low mdfv3 363 110 asammdf 3.0.0 minimum mdfv3 919 80 mdfreader 2.7.5 mdfv3 6424 451 mdfreader 2.7.5 noDataLoading mdfv3 7364 510 mdfreader 2.7.5 compress mdfv3 6624 449 asammdf 3.0.0 full mdfv4 984 319 asammdf 3.0.0 low mdfv4 1028 156 asammdf 3.0.0 minimum mdfv4 2786 80 mdfreader 2.7.5 mdfv4 3355 460 mdfreader 2.7.5 noDataLoading mdfv4 5153 483 mdfreader 2.7.5 compress mdfv4 3773 457 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 3.0.0 full mdfv3 1196 269 asammdf 3.0.0 low mdfv3 5230 121 asammdf 3.0.0 minimum mdfv3 6871 85 mdfreader 2.7.5 mdfv3 77 414 mdfreader 2.7.5 noDataLoading mdfv3 13036 195 mdfreader 2.7.5 compress mdfv3 184 281 asammdf 3.0.0 full mdfv4 1207 305 asammdf 3.0.0 low mdfv4 5613 144 asammdf 3.0.0 minimum mdfv4 7725 80 mdfreader 2.7.5 mdfv4 74 435 mdfreader 2.7.5 noDataLoading mdfv4 14140 207 mdfreader 2.7.5 compress mdfv4 171 307 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 3.0.0 full v3 to v4 3712 565 asammdf 3.0.0 low v3 to v4 4091 228 asammdf 3.0.0 minimum v3 to v4 6740 126 asammdf 3.0.0 full v4 to v3 3787 571 asammdf 3.0.0 low v4 to v3 4546 222 asammdf 3.0.0 minimum v4 to v3 8369 115 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 3.0.0 full v3 7297 975 asammdf 3.0.0 low v3 7766 282 asammdf 3.0.0 minimum v3 11363 163 mdfreader 2.7.5 mdfv3 13039 1301 mdfreader 2.7.5 compress mdfv3 12877 1298 mdfreader 2.7.5 noDataLoading mdfv3 12981 1421 asammdf 3.0.0 full v4 11313 1025 asammdf 3.0.0 low v4 12155 322 asammdf 3.0.0 minimum v4 18787 152 mdfreader 2.7.5 mdfv4 21423 1309 mdfreader 2.7.5 noDataLoading mdfv4 20142 1352 mdfreader 2.7.5 compress mdfv4 20600 1309 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_4.0.0.dev_mdfreader_2.7.7.txt000066400000000000000000000135731502633300400256720ustar00rootroot00000000000000Benchmark environment * 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 18:10:19) [GCC 7.2.0] * Linux-4.13.0-37-generic-x86_64-with-debian-stretch-sid * x86_64 * 8GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 2013 331 asammdf 4.0.0.dev low mdfv3 1913 178 asammdf 4.0.0.dev minimum mdfv3 617 64 mdfreader 2.7.7 mdfv3 2892 241 mdfreader 2.7.7 compress mdfv3 2947 234 mdfreader 2.7.7 noDataLoading mdfv3 1652 175 asammdf 4.0.0.dev full mdfv4 3504 304 asammdf 4.0.0.dev low mdfv4 3292 140 asammdf 4.0.0.dev minimum mdfv4 2663 64 mdfreader 2.7.7 mdfv4 8215 440 mdfreader 2.7.7 compress mdfv4 8535 309 mdfreader 2.7.7 noDataLoading mdfv4 5413 182 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 1083 338 asammdf 4.0.0.dev low mdfv3 1308 185 asammdf 4.0.0.dev minimum mdfv3 3936 68 mdfreader 2.7.7 mdfv3 0* 0* mdfreader 2.7.7 noDataLoading mdfv3 0* 0* mdfreader 2.7.7 compress mdfv3 0* 0* asammdf 4.0.0.dev full mdfv4 1279 309 asammdf 4.0.0.dev low mdfv4 1679 149 asammdf 4.0.0.dev minimum mdfv4 3776 74 mdfreader 2.7.7 mdfv4 6710 465 mdfreader 2.7.7 noDataLoading mdfv4 9615 483 mdfreader 2.7.7 compress mdfv4 7191 463 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 2182 342 asammdf 4.0.0.dev low mdfv3 9133 195 asammdf 4.0.0.dev minimum mdfv3 13574 81 mdfreader 2.7.7 mdfv3 4 241 mdfreader 2.7.7 nodata mdfv3 2319 204 mdfreader 2.7.7 compress mdfv3 42 234 asammdf 4.0.0.dev full mdfv4 2072 311 asammdf 4.0.0.dev low mdfv4 11022 151 asammdf 4.0.0.dev minimum mdfv4 18972 82 mdfreader 2.7.7 mdfv4 114 440 mdfreader 2.7.7 nodata mdfv4 23070 208 mdfreader 2.7.7 compress mdfv4 255 313 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full v3 to v4 6898 674 asammdf 4.0.0.dev low v3 to v4 7447 343 asammdf 4.0.0.dev minimum v3 to v4 11432 116 asammdf 4.0.0.dev full v4 to v3 7294 601 asammdf 4.0.0.dev low v4 to v3 6613 251 asammdf 4.0.0.dev minimum v4 to v3 13755 110 ================================================== ========= ======== ================================================== ========= ======== Merge 2 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full v3 14380 1107 asammdf 4.0.0.dev low v3 13896 425 asammdf 4.0.0.dev minimum v3 20179 138 mdfreader 2.7.7 v3 6081 251 mdfreader 2.7.7 compress v3 6285 250 mdfreader 2.7.7 nodata v3 0* 0* asammdf 4.0.0.dev full v4 18774 1054 asammdf 4.0.0.dev low v4 26612 349 asammdf 4.0.0.dev minimum v4 34256 135 mdfreader 2.7.7 v4 28264 960 mdfreader 2.7.7 nodata v4 24660 998 mdfreader 2.7.7 compress v4 22881 959 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_4.0.0.dev_mdfreader_2.7.8.txt000066400000000000000000000136171502633300400256720ustar00rootroot00000000000000Benchmark environment * 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] * Windows-10-10.0.17134-SP0 * Intel64 Family 6 Model 69 Stepping 1, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 1466 337 asammdf 4.0.0.dev low mdfv3 1372 184 asammdf 4.0.0.dev minimum mdfv3 420 70 mdfreader 2.7.8 mdfv3 2794 430 mdfreader 2.7.8 compress mdfv3 4323 129 mdfreader 2.7.8 noDataLoading mdfv3 1187 176 asammdf 4.0.0.dev full mdfv4 1786 312 asammdf 4.0.0.dev low mdfv4 1637 147 asammdf 4.0.0.dev minimum mdfv4 1099 71 mdfreader 2.7.8 mdfv4 6706 441 mdfreader 2.7.8 compress mdfv4 8542 141 mdfreader 2.7.8 noDataLoading mdfv4 4539 182 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 894 343 asammdf 4.0.0.dev low mdfv3 866 190 asammdf 4.0.0.dev minimum mdfv3 3135 78 mdfreader 2.7.8 mdfv3 7733 459 mdfreader 2.7.8 noDataLoading mdfv3 9353 520 mdfreader 2.7.8 compress mdfv3 7827 428 asammdf 4.0.0.dev full mdfv4 982 316 asammdf 4.0.0.dev low mdfv4 974 157 asammdf 4.0.0.dev minimum mdfv4 3600 80 mdfreader 2.7.8 mdfv4 4669 459 mdfreader 2.7.8 noDataLoading mdfv4 6612 478 mdfreader 2.7.8 compress mdfv4 4525 418 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 1605 346 asammdf 4.0.0.dev low mdfv3 7224 199 asammdf 4.0.0.dev minimum mdfv3 9965 87 mdfreader 2.7.8 mdfv3 102 430 mdfreader 2.7.8 nodata mdfv3 16696 211 mdfreader 2.7.8 compress mdfv3 622 129 asammdf 4.0.0.dev full mdfv4 1685 316 asammdf 4.0.0.dev low mdfv4 12592 157 asammdf 4.0.0.dev minimum mdfv4 16428 84 mdfreader 2.7.8 mdfv4 93 441 mdfreader 2.7.8 compress mdfv4 624 141 mdfreader 2.7.8 nodata mdfv4 27146 206 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full v3 to v4 5677 680 asammdf 4.0.0.dev low v3 to v4 5737 352 asammdf 4.0.0.dev minimum v3 to v4 9341 118 asammdf 4.0.0.dev full v4 to v3 5095 610 asammdf 4.0.0.dev low v4 to v3 5328 263 asammdf 4.0.0.dev minimum v4 to v3 9983 115 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full v3 17059 1641 asammdf 4.0.0.dev low v3 16730 622 asammdf 4.0.0.dev minimum v3 25156 166 mdfreader 2.7.8 v3 24608 1335 mdfreader 2.7.8 compress v3 30669 1347 mdfreader 2.7.8 nodata v3 24093 1456 asammdf 4.0.0.dev full v4 17949 1513 asammdf 4.0.0.dev low v4 17592 461 asammdf 4.0.0.dev minimum v4 36417 166 mdfreader 2.7.8 v4 36287 1326 mdfreader 2.7.8 nodata v4 35904 1361 mdfreader 2.7.8 compress v4 42410 1336 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_4.2.1_mdfreader_3.0.rst000066400000000000000000000136421502633300400247330ustar00rootroot00000000000000 Benchmark environment * 3.6.6 (default, Sep 12 2018, 18:26:19) [GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] * Linux-4.15.0-38-generic-x86_64-with-Ubuntu-18.04-bionic * x86_64 * 15GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * no_data_loading = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.2.1dev full mdfv3 1305 340 asammdf 4.2.1dev low mdfv3 1236 187 asammdf 4.2.1dev minimum mdfv3 598 80 mdfreader 3.0 mdfv3 2231 435 mdfreader 3.0 compress mdfv3 1987 301 mdfreader 3.0 no_data_loading mdfv3 1035 183 asammdf 4.2.1dev full mdfv4 1284 310 asammdf 4.2.1dev low mdfv4 1145 145 asammdf 4.2.1dev minimum mdfv4 1089 81 mdfreader 3.0 mdfv4 5509 460 mdfreader 3.0 compress mdfv4 5202 328 mdfreader 3.0 no_data_loading mdfv4 3552 193 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.2.1dev full mdfv3 707 340 asammdf 4.2.1dev low mdfv3 775 193 asammdf 4.2.1dev minimum mdfv3 1959 86 mdfreader 3.0 mdfv3 5631 472 mdfreader 3.0 no_data_loading mdfv3 6499 529 mdfreader 3.0 compress mdfv3 5802 471 asammdf 4.2.1dev full mdfv4 770 319 asammdf 4.2.1dev low mdfv4 969 161 asammdf 4.2.1dev minimum mdfv4 1959 96 mdfreader 3.0 mdfv4 4038 486 mdfreader 3.0 no_data_loading mdfv4 5733 501 mdfreader 3.0 compress mdfv4 4117 483 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.2.1dev full mdfv3 1448 352 asammdf 4.2.1dev low mdfv3 6566 204 asammdf 4.2.1dev minimum mdfv3 7904 94 mdfreader 3.0 mdfv3 86 435 mdfreader 3.0 nodata mdfv3 10937 216 mdfreader 3.0 compress mdfv3 192 301 asammdf 4.2.1dev full mdfv4 1532 317 asammdf 4.2.1dev low mdfv4 7031 157 asammdf 4.2.1dev minimum mdfv4 8222 93 mdfreader 3.0 mdfv4 98 460 mdfreader 3.0 compress mdfv4 203 334 mdfreader 3.0 nodata mdfv4 14895 226 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.2.1dev full v3 to v4 4946 679 asammdf 4.2.1dev low v3 to v4 5074 349 asammdf 4.2.1dev minimum v3 to v4 7463 122 asammdf 4.2.1dev full v4 to v3 4448 607 asammdf 4.2.1dev low v4 to v3 4685 257 asammdf 4.2.1dev minimum v4 to v3 7211 115 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.2.1dev full v3 15050 1648 asammdf 4.2.1dev low v3 14921 622 asammdf 4.2.1dev minimum v3 20606 167 mdfreader 3.0 v3 19063 1314 mdfreader 3.0 compress v3 19101 1313 mdfreader 3.0 nodata v3 18661 1434 asammdf 4.2.1dev full v4 14612 1509 asammdf 4.2.1dev low v4 14546 450 asammdf 4.2.1dev minimum v4 26211 164 mdfreader 3.0 v4 29422 1349 mdfreader 3.0 nodata v4 28634 1330 mdfreader 3.0 compress v4 29076 1299 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_4.3.0_mdfreader_3.0.rst000066400000000000000000000136421502633300400247330ustar00rootroot00000000000000 Benchmark environment * 3.6.6 (default, Sep 12 2018, 18:26:19) [GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] * Linux-4.15.0-38-generic-x86_64-with-Ubuntu-18.04-bionic * x86_64 * 15GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * no_data_loading = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.3.0 full mdfv3 1304 340 asammdf 4.3.0 low mdfv3 1226 187 asammdf 4.3.0 minimum mdfv3 587 80 mdfreader 3.0 mdfv3 2251 434 mdfreader 3.0 compress mdfv3 2038 301 mdfreader 3.0 no_data_loading mdfv3 1027 183 asammdf 4.3.0 full mdfv4 1292 310 asammdf 4.3.0 low mdfv4 1161 146 asammdf 4.3.0 minimum mdfv4 1082 81 mdfreader 3.0 mdfv4 5447 460 mdfreader 3.0 compress mdfv4 5190 328 mdfreader 3.0 no_data_loading mdfv4 3545 193 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.3.0 full mdfv3 983 340 asammdf 4.3.0 low mdfv3 827 194 asammdf 4.3.0 minimum mdfv3 2009 86 mdfreader 3.0 mdfv3 5629 472 mdfreader 3.0 no_data_loading mdfv3 6618 529 mdfreader 3.0 compress mdfv3 6086 471 asammdf 4.3.0 full mdfv4 806 319 asammdf 4.3.0 low mdfv4 983 161 asammdf 4.3.0 minimum mdfv4 1979 96 mdfreader 3.0 mdfv4 4162 485 mdfreader 3.0 no_data_loading mdfv4 5774 501 mdfreader 3.0 compress mdfv4 4209 483 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.3.0 full mdfv3 1463 352 asammdf 4.3.0 low mdfv3 6353 204 asammdf 4.3.0 minimum mdfv3 7671 94 mdfreader 3.0 mdfv3 85 434 mdfreader 3.0 nodata mdfv3 10770 216 mdfreader 3.0 compress mdfv3 189 301 asammdf 4.3.0 full mdfv4 1553 317 asammdf 4.3.0 low mdfv4 7455 157 asammdf 4.3.0 minimum mdfv4 8694 92 mdfreader 3.0 mdfv4 87 460 mdfreader 3.0 compress mdfv4 204 333 mdfreader 3.0 nodata mdfv4 15565 226 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.3.0 full v3 to v4 5001 679 asammdf 4.3.0 low v3 to v4 5118 349 asammdf 4.3.0 minimum v3 to v4 7497 122 asammdf 4.3.0 full v4 to v3 4531 607 asammdf 4.3.0 low v4 to v3 4756 257 asammdf 4.3.0 minimum v4 to v3 7226 115 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.3.0 full v3 14903 1172 asammdf 4.3.0 low v3 14862 372 asammdf 4.3.0 minimum v3 18476 131 mdfreader 3.0 v3 19055 1314 mdfreader 3.0 compress v3 19076 1313 mdfreader 3.0 nodata v3 18650 1433 asammdf 4.3.0 full v4 14754 1107 asammdf 4.3.0 low v4 14883 287 asammdf 4.3.0 minimum v4 19386 130 mdfreader 3.0 v4 29473 1348 mdfreader 3.0 nodata v4 28672 1330 mdfreader 3.0 compress v4 29113 1298 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_4.7.0_mdfreader_3.0.rst000066400000000000000000000134211502633300400247320ustar00rootroot00000000000000 Benchmark environment * 3.6.7 (default, Oct 22 2018, 11:32:17) [GCC 8.2.0] * Linux-4.15.0-43-generic-x86_64-with-Ubuntu-18.04-bionic * x86_64 * 15GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * nodata = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.7.0 full mdfv3 1290 335 asammdf 4.7.0 low mdfv3 1203 182 asammdf 4.7.0 minimum mdfv3 578 75 mdfreader 3.0 mdfv3 2304 430 mdfreader 3.0 compress mdfv3 2067 296 mdfreader 3.0 no_data_loading mdfv3 1104 178 asammdf 4.7.0 full mdfv4 1311 305 asammdf 4.7.0 low mdfv4 1220 140 asammdf 4.7.0 minimum mdfv4 972 77 mdfreader 3.0 mdfv4 5483 456 mdfreader 3.0 compress mdfv4 5163 324 mdfreader 3.0 no_data_loading mdfv4 3515 188 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.7.0 full mdfv3 774 336 asammdf 4.7.0 low mdfv3 863 189 asammdf 4.7.0 minimum mdfv3 2102 80 mdfreader 3.0 mdfv3 5800 468 mdfreader 3.0 no_data_loading mdfv3 6733 524 mdfreader 3.0 compress mdfv3 5947 466 asammdf 4.7.0 full mdfv4 933 313 asammdf 4.7.0 low mdfv4 1027 155 asammdf 4.7.0 minimum mdfv4 2015 92 mdfreader 3.0 mdfv4 4257 481 mdfreader 3.0 no_data_loading mdfv4 6040 496 mdfreader 3.0 compress mdfv4 4352 478 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.7.0 full mdfv3 1662 345 asammdf 4.7.0 low mdfv3 7073 197 asammdf 4.7.0 minimum mdfv3 8624 86 mdfreader 3.0 mdfv3 88 430 mdfreader 3.0 nodata mdfv3 11710 212 mdfreader 3.0 compress mdfv3 199 296 asammdf 4.7.0 full mdfv4 1462 313 asammdf 4.7.0 low mdfv4 7866 153 asammdf 4.7.0 minimum mdfv4 9462 88 mdfreader 3.0 mdfv4 101 456 mdfreader 3.0 compress mdfv4 222 329 mdfreader 3.0 nodata mdfv4 16240 221 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.7.0 full v3 to v4 4312 645 asammdf 4.7.0 low v3 to v4 4423 315 asammdf 4.7.0 minimum v3 to v4 6588 117 asammdf 4.7.0 full v4 to v3 3608 573 asammdf 4.7.0 low v4 to v3 3608 224 asammdf 4.7.0 minimum v4 to v3 6176 112 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.7.0 full v3 13630 1125 asammdf 4.7.0 low v3 13466 329 asammdf 4.7.0 minimum v3 15622 125 mdfreader 3.0 v3 19818 1310 mdfreader 3.0 compress v3 20245 1309 mdfreader 3.0 nodata v3 19546 1429 asammdf 4.7.0 full v4 12837 1074 asammdf 4.7.0 low v4 12760 254 asammdf 4.7.0 minimum v4 15506 130 mdfreader 3.0 v4 29927 1344 mdfreader 3.0 nodata v4 29324 1377 mdfreader 3.0 compress v4 29627 1344 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_5.0.0dev_mdfreader_3.0.rst000066400000000000000000000104051502633300400254220ustar00rootroot00000000000000Benchmark environment * 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)] * Windows-10-10.0.16299-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * numpy 1.16.1 * 16GB installed RAM Notations used in the results * compress = mdfreader mdf object created with compression=blosc * nodata = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.0.0 mdfv3 329 111 mdfreader 3.0 mdfv3 1942 425 mdfreader 3.0 compress mdfv3 1667 293 mdfreader 3.0 no_data_loading mdfv3 864 171 asammdf 5.0.0 mdfv4 455 123 mdfreader 3.0 mdfv4 5217 448 mdfreader 3.0 compress mdfv4 4999 320 mdfreader 3.0 no_data_loading mdfv4 3644 178 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.0.0 mdfv3 544 110 mdfreader 3.0 mdfv3 6017 453 mdfreader 3.0 no_data_loading mdfv3 6808 513 mdfreader 3.0 compress mdfv3 6124 452 asammdf 5.0.0 mdfv4 449 124 mdfreader 3.0 mdfv4 3409 467 mdfreader 3.0 no_data_loading mdfv4 4841 485 mdfreader 3.0 compress mdfv4 3597 465 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.0.0 mdfv3 4783 111 mdfreader 3.0 mdfv3 59 425 mdfreader 3.0 nodata mdfv3 15259 207 mdfreader 3.0 compress mdfv3 200 292 asammdf 5.0.0 mdfv4 8210 123 mdfreader 3.0 mdfv4 80 448 mdfreader 3.0 compress mdfv4 226 322 mdfreader 3.0 nodata mdfv4 22078 208 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.0.0 v3 to v4 3090 157 asammdf 5.0.0 v4 to v3 2665 151 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.0.0 v3 8409 173 mdfreader 3.0 v3 18133 1329 mdfreader 3.0 compress v3 18285 1277 mdfreader 3.0 nodata v3 17846 1432 asammdf 5.0.0 v4 8902 174 mdfreader 3.0 v4 29391 1356 mdfreader 3.0 nodata v4 28493 1334 mdfreader 3.0 compress v4 29109 1298 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_5.12.0_mdfreader_3.3.rst000066400000000000000000000105511502633300400250130ustar00rootroot00000000000000 Benchmark environment * 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] * Windows-10-10.0.17763-SP0 * Intel64 Family 6 Model 158 Stepping 10, GenuineIntel * numpy 1.16.2 * 16GB installed RAM Notations used in the results * compress = mdfreader mdf object created with compression=blosc * nodata = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.12.0 mdfv3 257 155 mdfreader 3.3 mdfv3 1621 474 mdfreader 3.3 compress mdfv3 3251 174 mdfreader 3.3 no_data_loading mdfv3 714 222 asammdf 5.12.0 mdfv4 401 167 mdfreader 3.3 mdfv4 4408 497 mdfreader 3.3 compress mdfv4 6013 196 mdfreader 3.3 no_data_loading mdfv4 2901 234 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.12.0 mdfv3 414 154 mdfreader 3.3 mdfv3 4129 501 mdfreader 3.3 no_data_loading mdfv3 4885 562 mdfreader 3.3 compress mdfv3 4339 470 asammdf 5.12.0 mdfv4 351 168 mdfreader 3.3 mdfv4 2399 515 mdfreader 3.3 no_data_loading mdfv4 3647 533 mdfreader 3.3 compress mdfv4 2535 474 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.12.0 mdfv3 3953 155 mdfreader 3.3 mdfv3 47 474 mdfreader 3.3 nodata mdfv3 13157 257 mdfreader 3.3 compress mdfv3 512 174 asammdf 5.12.0 mdfv4 7528 167 mdfreader 3.3 mdfv4 84 496 mdfreader 3.3 compress mdfv4 560 201 mdfreader 3.3 nodata mdfv4 41172 260 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.12.0 v3 to v4 2173 203 asammdf 5.12.0 v4 to v3 2043 191 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.12.0 v3 6090 245 mdfreader 3.3 v3 17474 1378 mdfreader 3.3 compress v3 30164 1327 mdfreader 3.3 nodata v3 16876 1482 asammdf 5.12.0 v4 5995 291 mdfreader 3.3 v4 25128 1406 mdfreader 3.3 nodata v4 24789 1390 mdfreader 3.3 compress v4 37270 1348 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_5.16.1_mdfreader_3.3.rst000066400000000000000000000106601502633300400250210ustar00rootroot00000000000000 Benchmark environment * 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] * Windows-10-10.0.17763-SP0 * Intel64 Family 6 Model 158 Stepping 10, GenuineIntel * numpy 1.17.2 * 16GB installed RAM Notations used in the results * compress = mdfreader mdf object created with compression=blosc * nodata = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.16.1 mdfv3 289 145 mdfreader 3.3 mdfv3 1581 461 mdfreader 3.3 no_data_loading mdfv3 717 214 mdfreader 3.3 compress mdfv3 1317 329 asammdf 5.16.1 mdfv4 420 157 mdfreader 3.3 mdfv4 3914 493 mdfreader 3.3 no_data_loading mdfv4 2818 280 mdfreader 3.3 compress mdfv4 3712 365 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.16.1 mdfv3 421 144 mdfreader 3.3 mdfv3 4076 490 mdfreader 3.3 no_data_loading mdfv3 4586 552 mdfreader 3.3 compress mdfv3 4202 488 asammdf 5.16.1 mdfv4 347 157 mdfreader 3.3 mdfv4 2320 512 mdfreader 3.3 no_data_loading mdfv4 3470 588 mdfreader 3.3 compress mdfv4 2440 507 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.16.1 mdfv3 3682 146 mdfreader 3.3 mdfv3 51 461 mdfreader 3.3 nodata mdfv3 28372 251 mdfreader 3.3 compress mdfv3 167 329 asammdf 5.16.1 mdfv4 6792 157 mdfreader 3.3 mdfv4 93 493 mdfreader 3.3 nodata mdfv4 32486 314 mdfreader 3.3 compress mdfv4 244 368 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.16.1 v3 to v4 3143 205 asammdf 5.16.1 v4 to v410 2665 180 asammdf 5.16.1 v4 to v420 3145 222 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.16.1 v3 7853 213 mdfreader 3.3 v3 16464 1367 mdfreader 3.3 nodata v3 15816 1482 mdfreader 3.3 compress v3 16459 1315 asammdf 5.16.1 v4 7216 208 mdfreader 3.3 v4 24205 1407 mdfreader 3.3 nodata v4 24063 1455 mdfreader 3.3 compress v4 24381 1343 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_5.20.0_mdfreader_4.0.rst000066400000000000000000000106601502633300400250110ustar00rootroot00000000000000 Benchmark environment * 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] * Windows-10-10.0.17763-SP0 * Intel64 Family 6 Model 158 Stepping 10, GenuineIntel * numpy 1.18.3 * 16GB installed RAM Notations used in the results * compress = mdfreader mdf object created with compression=blosc * nodata = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.20.0 mdfv3 269 136 mdfreader 4.0 mdfv3 1531 453 mdfreader 4.0 no_data_loading mdfv3 687 206 mdfreader 4.0 compress mdfv3 5398 154 asammdf 5.20.0 mdfv4 409 149 mdfreader 4.0 mdfv4 3910 484 mdfreader 4.0 no_data_loading mdfv4 2836 272 mdfreader 4.0 compress mdfv4 7898 182 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.20.0 mdfv3 393 136 mdfreader 4.0 mdfv3 3996 482 mdfreader 4.0 no_data_loading mdfv3 4658 544 mdfreader 4.0 compress mdfv3 4133 451 asammdf 5.20.0 mdfv4 341 149 mdfreader 4.0 mdfv4 2241 503 mdfreader 4.0 no_data_loading mdfv4 3461 581 mdfreader 4.0 compress mdfv4 2497 456 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.20.0 mdfv3 3892 137 mdfreader 4.0 mdfv3 73 453 mdfreader 4.0 nodata mdfv3 11587 243 mdfreader 4.0 compress mdfv3 517 154 asammdf 5.20.0 mdfv4 6940 149 mdfreader 4.0 mdfv4 61 485 mdfreader 4.0 nodata mdfv4 17585 305 mdfreader 4.0 compress mdfv4 527 184 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.20.0.dev-31 v3 to v4 3252 194 asammdf 5.20.0.dev-31 v4 to v410 2901 180 asammdf 5.20.0.dev-31 v4 to v420 3273 218 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.20.0.dev-31 v3 8339 205 mdfreader 4.0 v3 0* 0* mdfreader 4.0 nodata v3 0* 0* mdfreader 4.0 compress v3 0* 0* asammdf 5.20.0.dev-31 v4 7641 210 mdfreader 4.0 v4 0* 0* mdfreader 4.0 nodata v4 0* 0* mdfreader 4.0 compress v4 0* 0* ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x64_asammdf_5.22.0_mdfreader_4.1.rst000066400000000000000000000106521502633300400250150ustar00rootroot00000000000000Benchmark environment * 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] * Windows-10-10.0.18362-SP0 * Intel64 Family 6 Model 158 Stepping 10, GenuineIntel * numpy 1.19.1 * 16GB installed RAM Notations used in the results * compress = mdfreader mdf object created with compression=blosc * nodata = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.22.0 mdfv3 277 135 mdfreader 4.1 mdfv3 1564 451 mdfreader 4.1 no_data_loading mdfv3 706 204 mdfreader 4.1 compress mdfv3 1403 319 asammdf 5.22.0 mdfv4 432 147 mdfreader 4.1 mdfv4 4084 483 mdfreader 4.1 no_data_loading mdfv4 2966 270 mdfreader 4.1 compress mdfv4 3835 355 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.22.0 mdfv3 395 134 mdfreader 4.1 mdfv3 4056 479 mdfreader 4.1 no_data_loading mdfv3 4818 542 mdfreader 4.1 compress mdfv3 4313 479 asammdf 5.22.0 mdfv4 374 147 mdfreader 4.1 mdfv4 2270 502 mdfreader 4.1 no_data_loading mdfv4 3424 578 mdfreader 4.1 compress mdfv4 2475 497 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.22.0 mdfv3 3978 136 mdfreader 4.1 mdfv3 46 451 mdfreader 4.1 nodata mdfv3 11929 241 mdfreader 4.1 compress mdfv3 166 319 asammdf 5.22.0 mdfv4 7060 147 mdfreader 4.1 mdfv4 60 483 mdfreader 4.1 nodata mdfv4 17991 303 mdfreader 4.1 compress mdfv4 173 356 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.22.0 v3 to v4 2749 192 asammdf 5.22.0 v4 to v410 2239 177 asammdf 5.22.0 v4 to v420 2611 216 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 5.22.0 v3 7604 202 mdfreader 4.1 v3 0* 0* mdfreader 4.1 nodata v3 0* 0* mdfreader 4.1 compress v3 0* 0* asammdf 5.22.0 v4 6990 206 mdfreader 4.1 v4 32816 1123 mdfreader 4.1 nodata v4 32998 1229 mdfreader 4.1 compress v4 32908 1118 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst000066400000000000000000000106471502633300400247400ustar00rootroot00000000000000Benchmark environment * 3.9.4 (tags/v3.9.4:1f2e308, Apr 6 2021, 13:40:21) [MSC v.1928 64 bit (AMD64)] * Windows-10-10.0.19041-SP0 * Intel64 Family 6 Model 158 Stepping 10, GenuineIntel * numpy 1.21.2 * 16GB installed RAM Notations used in the results * compress = mdfreader mdf object created with compression=blosc * nodata = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 mdfv3 369 186 mdfreader 4.1 mdfv3 1741 498 mdfreader 4.1 no_data_loading mdfv3 646 248 mdfreader 4.1 compress mdfv3 1463 365 asammdf 7.0.1 mdfv4 468 199 mdfreader 4.1 mdfv4 4350 520 mdfreader 4.1 no_data_loading mdfv4 2892 310 mdfreader 4.1 compress mdfv4 4105 391 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 mdfv3 378 186 mdfreader 4.1 mdfv3 4310 527 mdfreader 4.1 no_data_loading mdfv3 5070 586 mdfreader 4.1 compress mdfv3 4456 525 asammdf 7.0.1 mdfv4 331 366 mdfreader 4.1 mdfv4 2254 539 mdfreader 4.1 no_data_loading mdfv4 3591 618 mdfreader 4.1 compress mdfv4 2400 535 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 mdfv3 3354 187 mdfreader 4.1 mdfv3 40 498 mdfreader 4.1 nodata mdfv3 12686 283 mdfreader 4.1 compress mdfv3 154 366 asammdf 7.0.1 mdfv4 5243 364 mdfreader 4.1 mdfv4 51 520 mdfreader 4.1 nodata mdfv4 20210 336 mdfreader 4.1 compress mdfv4 170 396 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 v3 to v4 2186 232 asammdf 7.0.1 v4 to v410 2008 394 asammdf 7.0.1 v4 to v420 2359 438 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 v3 6449 224 mdfreader 4.1 v3 0* 0* mdfreader 4.1 nodata v3 0* 0* mdfreader 4.1 compress v3 0* 0* asammdf 7.0.1 v4 6713 409 mdfreader 4.1 v4 34746 1156 mdfreader 4.1 nodata v4 37608 1266 mdfreader 4.1 compress v4 34184 1151 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.1.0_mdfreader_0.2.5.txt000066400000000000000000000060111502633300400250740ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data no loaded into RAM) * compression = MDF object created with compression=True (raw channel data loaded into RAM and compressed) * noconvert = MDF object created with convertAfterRead=False Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.1.0 mdfv3 1031 284 asammdf 2.1.0 compression mdfv3 1259 192 asammdf 2.1.0 nodata mdfv3 584 114 mdfreader 0.2.5 mdfv3 3809 455 mdfreader 0.2.5 no convert mdfv3 3498 321 asammdf 2.1.0 mdfv4 2109 341 asammdf 2.1.0 compression mdfv4 2405 239 asammdf 2.1.0 nodata mdfv4 1686 159 mdfreader 0.2.5 mdfv4 44400 578 mdfreader 0.2.5 noconvert mdfv4 43867 449 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.1.0 mdfv3 713 286 asammdf 2.1.0 compression mdfv3 926 194 mdfreader 0.2.5 mdfv3 19862 1226 asammdf 2.1.0 mdfv4 1109 347 asammdf 2.1.0 compression mdfv4 1267 246 mdfreader 0.2.5 mdfv4 17518 1656 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.1.0 mdfv3 3943 295 asammdf 2.1.0 compression mdfv3 29682 203 asammdf 2.1.0 nodata mdfv3 23215 129 mdfreader 0.2.5 mdfv3 38 455 asammdf 2.1.0 mdfv4 3227 351 asammdf 2.1.0 compression mdfv4 26070 250 asammdf 2.1.0 nodata mdfv4 21619 171 mdfreader 0.2.5 mdfv4 51 578 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.2.0_mdfreader_0.2.5.txt000066400000000000000000000056151502633300400251060ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = MDF object created with compression=True/blosc * compression bcolz 6 = MDF object created with compression=6 * noDataLoading = MDF object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.2.0 mdfv3 1149 294 asammdf 2.2.0 compression mdfv3 1368 202 asammdf 2.2.0 nodata mdfv3 861 123 mdfreader 0.2.5 mdfv3 3755 455 asammdf 2.2.0 mdfv4 2316 348 asammdf 2.2.0 compression mdfv4 2694 247 asammdf 2.2.0 nodata mdfv4 1886 166 mdfreader 0.2.5 mdfv4 43210 578 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.2.0 mdfv3 413 297 asammdf 2.2.0 compression mdfv3 592 204 mdfreader 0.2.5 mdfv3 20038 1224 asammdf 2.2.0 mdfv4 720 357 asammdf 2.2.0 compression mdfv4 674 253 mdfreader 0.2.5 mdfv4 17553 1687 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.2.0 mdfv3 784 299 asammdf 2.2.0 compression mdfv3 25345 207 asammdf 2.2.0 nodata mdfv3 18657 133 mdfreader 0.2.5 mdfv3 35 455 asammdf 2.2.0 mdfv4 695 354 asammdf 2.2.0 compression mdfv4 24325 255 asammdf 2.2.0 nodata mdfv4 20745 176 mdfreader 0.2.5 mdfv4 50 578 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.3.0_mdfreader_0.2.5.txt000066400000000000000000000051651502633300400251070ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = MDF object created with compression=True/blosc * compression bcolz 6 = MDF object created with compression=6 * noDataLoading = MDF object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.0 mdfv3 1126 294 asammdf 2.3.0 nodata mdfv3 917 123 mdfreader 0.2.5 mdfv3 3743 455 asammdf 2.3.0 mdfv4 2359 348 asammdf 2.3.0 nodata mdfv4 1906 166 mdfreader 0.2.5 mdfv4 43166 577 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.0 mdfv3 420 297 asammdf 2.3.0 nodata mdfv3 445 130 mdfreader 0.2.5 mdfv3 20078 1224 asammdf 2.3.0 mdfv4 711 357 asammdf 2.3.0 nodata mdfv4 738 175 mdfreader 0.2.5 mdfv4 17822 1687 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.0 mdfv3 777 299 asammdf 2.3.0 nodata mdfv3 18662 132 mdfreader 0.2.5 mdfv3 36 455 asammdf 2.3.0 mdfv4 681 354 asammdf 2.3.0 nodata mdfv4 20439 176 mdfreader 0.2.5 mdfv4 51 578 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.3.2_mdfreader_0.2.5.txt000066400000000000000000000051601502633300400251040ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = MDF object created with compression=blosc * compression bcolz 6 = MDF object created with compression=6 * noDataLoading = MDF object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.2 mdfv3 980 288 asammdf 2.3.2 nodata mdfv3 670 118 mdfreader 0.2.5 mdfv3 3776 455 asammdf 2.3.2 mdfv4 2071 342 asammdf 2.3.2 nodata mdfv4 1610 160 mdfreader 0.2.5 mdfv4 43559 578 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.2 mdfv3 406 291 asammdf 2.3.2 nodata mdfv3 432 125 mdfreader 0.2.5 mdfv3 19623 1224 asammdf 2.3.2 mdfv4 691 351 asammdf 2.3.2 nodata mdfv4 734 169 mdfreader 0.2.5 mdfv4 17657 1687 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.3.2 mdfv3 963 298 asammdf 2.3.2 nodata mdfv3 19059 132 mdfreader 0.2.5 mdfv3 34 455 asammdf 2.3.2 mdfv4 868 349 asammdf 2.3.2 nodata mdfv4 20434 171 mdfreader 0.2.5 mdfv4 54 578 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.4.3_mdfreader_0.2.5.txt000066400000000000000000000051601502633300400251060ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = MDF object created with compression=blosc * compression bcolz 6 = MDF object created with compression=6 * noDataLoading = MDF object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.4.3 mdfv3 927 289 asammdf 2.4.3 nodata mdfv3 647 118 mdfreader 0.2.5 mdfv3 3583 455 asammdf 2.4.3 mdfv4 1956 343 asammdf 2.4.3 nodata mdfv4 1509 161 mdfreader 0.2.5 mdfv4 41613 578 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.4.3 mdfv3 415 292 asammdf 2.4.3 nodata mdfv3 437 126 mdfreader 0.2.5 mdfv3 19103 1225 asammdf 2.4.3 mdfv4 667 351 asammdf 2.4.3 nodata mdfv4 714 169 mdfreader 0.2.5 mdfv4 16612 1687 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.4.3 mdfv3 935 297 asammdf 2.4.3 nodata mdfv3 18635 131 mdfreader 0.2.5 mdfv3 34 455 asammdf 2.4.3 mdfv4 827 349 asammdf 2.4.3 nodata mdfv4 20404 170 mdfreader 0.2.5 mdfv4 46 578 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.5.0_mdfreader_0.2.5.txt000066400000000000000000000057721502633300400251150ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results: * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.0 mdfv3 1009 289 asammdf 2.5.0 nodata mdfv3 663 118 mdfreader 0.2.5 mdfv3 3705 454 asammdf 2.5.0 mdfv4 2031 343 asammdf 2.5.0 nodata mdfv4 1690 161 mdfreader 0.2.5 mdfv4 42315 576 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.0 mdfv3 439 293 asammdf 2.5.0 nodata mdfv3 462 126 mdfreader 0.2.5 mdfv3 19759 1224 asammdf 2.5.0 mdfv4 691 354 asammdf 2.5.0 nodata mdfv4 712 174 mdfreader 0.2.5 mdfv4 17415 1686 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.0 mdfv3 807 298 asammdf 2.5.0 nodata mdfv3 18500 132 mdfreader 0.2.5 mdfv3 36 454 asammdf 2.5.0 mdfv4 804 349 asammdf 2.5.0 nodata mdfv4 21315 171 mdfreader 0.2.5 mdfv4 49 577 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.0 v3 to v4 5834 709 asammdf 2.5.0 v3 to v4 nodata 28427 494 asammdf 2.5.0 v4 to v3 5474 710 asammdf 2.5.0 v4 to v3 nodata 30423 638 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.5.2_mdfreader_0.2.5.txt000066400000000000000000000073731502633300400251160ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 mdfv3 951 289 asammdf 2.5.2 nodata mdfv3 667 119 mdfreader 0.2.5 mdfv3 3628 454 asammdf 2.5.2 mdfv4 2142 343 asammdf 2.5.2 nodata mdfv4 1585 161 mdfreader 0.2.5 mdfv4 42997 577 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 mdfv3 530 293 asammdf 2.5.2 nodata mdfv3 457 126 mdfreader 0.2.5 mdfv3 19931 1225 asammdf 2.5.2 mdfv4 705 354 asammdf 2.5.2 nodata mdfv4 707 175 mdfreader 0.2.5 mdfv4 17803 1686 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 mdfv3 865 298 asammdf 2.5.2 nodata mdfv3 18442 132 mdfreader 0.2.5 mdfv3 36 454 asammdf 2.5.2 mdfv4 803 349 asammdf 2.5.2 nodata mdfv4 20397 171 mdfreader 0.2.5 mdfv4 48 577 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 v3 to v4 5824 690 asammdf 2.5.2 v3 to v4 nodata 28060 486 asammdf 2.5.2 v4 to v3 5591 710 asammdf 2.5.2 v4 to v3 nodata 30169 638 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.2 v3 13152 1226 asammdf 2.5.2 v3 nodata 53144 348 asammdf 2.5.2 v4 15031 1296 asammdf 2.5.2 v4 nodata 60374 389 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.5.3_mdfreader_0.2.5.txt000066400000000000000000000073731502633300400251170ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 mdfv3 897 281 asammdf 2.5.3 nodata mdfv3 648 112 mdfreader 0.2.5 mdfv3 3836 454 asammdf 2.5.3 mdfv4 2098 331 asammdf 2.5.3 nodata mdfv4 1588 151 mdfreader 0.2.5 mdfv4 45415 577 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 mdfv3 469 285 asammdf 2.5.3 nodata mdfv3 526 119 mdfreader 0.2.5 mdfv3 20328 1224 asammdf 2.5.3 mdfv4 752 337 asammdf 2.5.3 nodata mdfv4 751 160 mdfreader 0.2.5 mdfv4 18135 1686 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 mdfv3 846 289 asammdf 2.5.3 nodata mdfv3 19460 126 mdfreader 0.2.5 mdfv3 37 454 asammdf 2.5.3 mdfv4 809 337 asammdf 2.5.3 nodata mdfv4 20778 161 mdfreader 0.2.5 mdfv4 49 577 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 v3 to v4 6121 673 asammdf 2.5.3 v3 to v4 nodata 29340 476 asammdf 2.5.3 v4 to v3 5645 690 asammdf 2.5.3 v4 to v3 nodata 32115 628 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.3 v3 13392 1201 asammdf 2.5.3 v3 nodata 54040 327 asammdf 2.5.3 v4 15031 1265 asammdf 2.5.3 v4 nodata 60397 364 ================================================== ========= ========asammdf-8.5.1/benchmarks/results/x86_asammdf_2.5.4_mdfreader_0.2.6.txt000066400000000000000000000117511502633300400251140ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 mdfv3 898 289 asammdf 2.5.4 nodata mdfv3 631 121 mdfreader 0.2.6 mdfv3 3431 460 mdfreader 0.2.6 compression mdfv3 4722 184 mdfreader 0.2.6 compression bcolz 6 mdfv3 4624 940 mdfreader 0.2.6 noDataLoading mdfv3 1824 120 asammdf 2.5.4 mdfv4 1943 333 asammdf 2.5.4 nodata mdfv4 1547 153 mdfreader 0.2.6 mdfv4 6326 881 mdfreader 0.2.6 compression mdfv4 7354 594 mdfreader 0.2.6 compression bcolz 6 mdfv4 7379 1303 mdfreader 0.2.6 noDataLoading mdfv4 4343 530 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 mdfv3 434 293 asammdf 2.5.4 nodata mdfv3 461 128 mdfreader 0.2.6 mdfv3 8901 483 mdfreader 0.2.6 noDataLoading mdfv3 10331 483 mdfreader 0.2.6 compression mdfv3 9247 450 mdfreader 0.2.6 compression bcolz 6 mdfv3 8775 941 asammdf 2.5.4 mdfv4 687 339 asammdf 2.5.4 nodata mdfv4 775 162 mdfreader 0.2.6 mdfv4 6943 901 mdfreader 0.2.6 noDataLoading mdfv4 8039 901 mdfreader 0.2.6 compression mdfv4 7061 860 mdfreader 0.2.6 compression bcolz 6 mdfv4 6811 1320 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 mdfv3 754 298 asammdf 2.5.4 nodata mdfv3 18535 134 mdfreader 0.2.6 mdfv3 79 460 mdfreader 0.2.6 nodata mdfv3 108596 333 mdfreader 0.2.6 compression mdfv3 673 188 mdfreader 0.2.6 compression bcolz 6 mdfv3 298 942 asammdf 2.5.4 mdfv4 759 339 asammdf 2.5.4 nodata mdfv4 20622 163 mdfreader 0.2.6 mdfv4 78 880 mdfreader 0.2.6 nodata mdfv4 155000 752 mdfreader 0.2.6 compression mdfv4 677 602 mdfreader 0.2.6 compression bcolz 6 mdfv4 322 1310 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 v3 to v4 5772 693 asammdf 2.5.4 v3 to v4 nodata 28056 486 asammdf 2.5.4 v4 to v3 5828 692 asammdf 2.5.4 v4 to v3 nodata 32825 630 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.5.4 v3 13135 1220 asammdf 2.5.4 v3 nodata 52395 336 asammdf 2.5.4 v4 15282 1259 asammdf 2.5.4 v4 nodata 59918 359 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.6.0_mdfreader_0.2.6.txt000066400000000000000000000117511502633300400251110ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 mdfv3 888 287 asammdf 2.6.0 nodata mdfv3 609 118 mdfreader 0.2.6 mdfv3 3457 458 mdfreader 0.2.6 compression mdfv3 4665 184 mdfreader 0.2.6 compression bcolz 6 mdfv3 4619 940 mdfreader 0.2.6 noDataLoading mdfv3 1890 120 asammdf 2.6.0 mdfv4 1971 330 asammdf 2.6.0 nodata mdfv4 1630 150 mdfreader 0.2.6 mdfv4 6414 870 mdfreader 0.2.6 compression mdfv4 7495 587 mdfreader 0.2.6 compression bcolz 6 mdfv4 7473 1294 mdfreader 0.2.6 noDataLoading mdfv4 4418 523 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 mdfv3 450 290 asammdf 2.6.0 nodata mdfv3 457 125 mdfreader 0.2.6 mdfv3 9455 481 mdfreader 0.2.6 noDataLoading mdfv3 1314 289 mdfreader 0.2.6 compression mdfv3 9263 451 mdfreader 0.2.6 compression bcolz 6 mdfv3 9305 941 asammdf 2.6.0 mdfv4 617 334 asammdf 2.6.0 nodata mdfv4 601 159 mdfreader 0.2.6 mdfv4 7063 890 mdfreader 0.2.6 noDataLoading mdfv4 1452 694 mdfreader 0.2.6 compression mdfv4 7227 851 mdfreader 0.2.6 compression bcolz 6 mdfv4 6954 1312 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 mdfv3 754 294 asammdf 2.6.0 nodata mdfv3 18843 130 mdfreader 0.2.6 mdfv3 80 458 mdfreader 0.2.6 noDataLoading mdfv3 18000000 118 mdfreader 0.2.6 compression mdfv3 690 188 mdfreader 0.2.6 compression bcolz 6 mdfv3 317 943 asammdf 2.6.0 mdfv4 784 335 asammdf 2.6.0 nodata mdfv4 20635 160 mdfreader 0.2.6 mdfv4 79 870 mdfreader 0.2.6 noDataLoading mdfv4 18000000 523 mdfreader 0.2.6 compression mdfv4 704 594 mdfreader 0.2.6 compression bcolz 6 mdfv4 333 1302 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 v3 to v4 5720 679 asammdf 2.6.0 v3 to v4 nodata 28738 479 asammdf 2.6.0 v4 to v3 5731 682 asammdf 2.6.0 v4 to v3 nodata 30795 627 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.0 v3 12988 1206 asammdf 2.6.0 v3 nodata 53020 322 asammdf 2.6.0 v4 15434 1244 asammdf 2.6.0 v4 nodata 60260 344 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.6.2_mdfreader_0.2.6.txt000066400000000000000000000115351502633300400251130ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compression = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 mdfv3 1191 286 asammdf 2.6.2 nodata mdfv3 706 118 mdfreader 0.2.6 mdfv3 3910 458 mdfreader 0.2.6 compression mdfv3 5040 185 mdfreader 0.2.6 compression bcolz 6 mdfv3 5274 941 mdfreader 0.2.6 noDataLoading mdfv3 2033 120 asammdf 2.6.2 mdfv4 2237 330 asammdf 2.6.2 nodata mdfv4 1969 150 mdfreader 0.2.6 mdfv4 7759 870 mdfreader 0.2.6 compression mdfv4 9439 587 mdfreader 0.2.6 compression bcolz 6 mdfv4 7679 1294 mdfreader 0.2.6 noDataLoading mdfv4 4878 522 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 mdfv3 434 290 asammdf 2.6.2 nodata mdfv3 475 125 mdfreader 0.2.6 mdfv3 9329 481 mdfreader 0.2.6 compression mdfv3 9743 452 mdfreader 0.2.6 compression bcolz 6 mdfv3 9806 941 asammdf 2.6.2 mdfv4 639 334 asammdf 2.6.2 nodata mdfv4 636 159 mdfreader 0.2.6 mdfv4 7679 891 mdfreader 0.2.6 compression mdfv4 7436 852 mdfreader 0.2.6 compression bcolz 6 mdfv4 7027 1312 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 mdfv3 804 294 asammdf 2.6.2 nodata mdfv3 19036 130 mdfreader 0.2.6 mdfv3 78 458 mdfreader 0.2.6 noDataLoading mdfv3 18000000 118 mdfreader 0.2.6 compression mdfv3 724 188 mdfreader 0.2.6 compression bcolz 6 mdfv3 305 943 asammdf 2.6.2 mdfv4 883 335 asammdf 2.6.2 nodata mdfv4 26520 160 mdfreader 0.2.6 mdfv4 77 870 mdfreader 0.2.6 noDataLoading mdfv4 18000000 523 mdfreader 0.2.6 compression mdfv4 684 594 mdfreader 0.2.6 compression bcolz 6 mdfv4 355 1302 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 v3 to v4 6359 685 asammdf 2.6.2 v3 to v4 nodata 31124 479 asammdf 2.6.2 v4 to v3 5778 680 asammdf 2.6.2 v4 to v3 nodata 36685 627 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.2 v3 13305 1228 asammdf 2.6.2 v3 nodata 54322 343 asammdf 2.6.2 v4 16648 1267 asammdf 2.6.2 v4 nodata 72303 364 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.6.3_mdfreader_0.2.6.txt000066400000000000000000000115321502633300400251110ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compress = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 mdfv3 951 286 asammdf 2.6.3 nodata mdfv3 639 118 mdfreader 0.2.6 mdfv3 3490 458 mdfreader 0.2.6 compress mdfv3 4624 185 mdfreader 0.2.6 compress bcolz 6 mdfv3 4654 941 mdfreader 0.2.6 noDataLoading mdfv3 1884 120 asammdf 2.6.3 mdfv4 2251 330 asammdf 2.6.3 nodata mdfv4 1791 150 mdfreader 0.2.6 mdfv4 6447 869 mdfreader 0.2.6 compress mdfv4 7549 586 mdfreader 0.2.6 compress bcolz 6 mdfv4 7730 1294 mdfreader 0.2.6 noDataLoading mdfv4 4553 522 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 mdfv3 448 290 asammdf 2.6.3 nodata mdfv3 467 125 mdfreader 0.2.6 mdfv3 8992 481 mdfreader 0.2.6 compress mdfv3 9228 452 mdfreader 0.2.6 compress bcolz 6 mdfv3 8751 941 asammdf 2.6.3 mdfv4 630 334 asammdf 2.6.3 nodata mdfv4 628 159 mdfreader 0.2.6 mdfv4 6880 891 mdfreader 0.2.6 compress mdfv4 7101 852 mdfreader 0.2.6 compress bcolz6 mdfv4 6839 1311 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 mdfv3 779 291 asammdf 2.6.3 nodata mdfv3 18127 128 mdfreader 0.2.6 mdfv3 80 458 mdfreader 0.2.6 noDataLoading mdfv3 18000000 118 mdfreader 0.2.6 compress mdfv3 684 187 mdfreader 0.2.6 compress bcolz 6 mdfv3 298 942 asammdf 2.6.3 mdfv4 801 335 asammdf 2.6.3 nodata mdfv4 25176 157 mdfreader 0.2.6 mdfv4 78 870 mdfreader 0.2.6 noDataLoading mdfv4 18000000 523 mdfreader 0.2.6 compress mdfv4 686 593 mdfreader 0.2.6 compress bcolz 6 mdfv4 319 1301 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 v3 to v4 5884 682 asammdf 2.6.3 v3 to v4 nodata 27892 479 asammdf 2.6.3 v4 to v3 5836 680 asammdf 2.6.3 v4 to v3 nodata 35283 627 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.3 v3 13305 1228 asammdf 2.6.3 v3 nodata 52775 346 asammdf 2.6.3 v4 16069 1267 asammdf 2.6.3 v4 nodata 70402 364 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.6.4_mdfreader_0.2.6.txt000066400000000000000000000113161502633300400251120ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compress = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 mdfv3 926 286 asammdf 2.6.4 nodata mdfv3 615 118 mdfreader 0.2.6 mdfv3 3345 458 mdfreader 0.2.6 compress mdfv3 4520 185 mdfreader 0.2.6 compress bcolz 6 mdfv3 4635 941 mdfreader 0.2.6 noDataLoading mdfv3 1867 120 asammdf 2.6.4 mdfv4 2250 330 asammdf 2.6.4 nodata mdfv4 1706 150 mdfreader 0.2.6 mdfv4 6413 869 mdfreader 0.2.6 compress mdfv4 7368 586 mdfreader 0.2.6 compress bcolz 6 mdfv4 7733 1294 mdfreader 0.2.6 noDataLoading mdfv4 4474 523 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 mdfv3 407 290 asammdf 2.6.4 nodata mdfv3 447 126 mdfreader 0.2.6 mdfv3 8865 481 mdfreader 0.2.6 compress mdfv3 8919 451 mdfreader 0.2.6 compress bcolz 6 mdfv3 8548 941 asammdf 2.6.4 mdfv4 578 334 asammdf 2.6.4 nodata mdfv4 617 159 mdfreader 0.2.6 mdfv4 6758 891 mdfreader 0.2.6 compress mdfv4 6999 852 mdfreader 0.2.6 compress bcolz6 mdfv4 6639 1312 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 mdfv3 818 291 asammdf 2.6.4 nodata mdfv3 18416 128 mdfreader 0.2.6 mdfv3 77 458 mdfreader 0.2.6 compress mdfv3 665 188 mdfreader 0.2.6 compress bcolz 6 mdfv3 291 943 asammdf 2.6.4 mdfv4 860 335 asammdf 2.6.4 nodata mdfv4 25362 157 mdfreader 0.2.6 mdfv4 162 794 mdfreader 0.2.6 compress mdfv4 710 593 mdfreader 0.2.6 compress bcolz 6 mdfv4 336 1301 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 v3 to v4 4389 680 asammdf 2.6.4 v3 to v4 nodata 26231 472 asammdf 2.6.4 v4 to v3 4586 681 asammdf 2.6.4 v4 to v3 nodata 34042 622 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.4 v3 10262 1243 asammdf 2.6.4 v3 nodata 48898 352 asammdf 2.6.4 v4 14443 1281 asammdf 2.6.4 v4 nodata 67092 377 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.6.5_mdfreader_0.2.6.txt000066400000000000000000000113161502633300400251130ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * nodata = asammdf MDF object created with load_measured_data=False (raw channel data not loaded into RAM) * compress = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 mdfv3 916 286 asammdf 2.6.5 nodata mdfv3 623 118 mdfreader 0.2.6 mdfv3 3373 458 mdfreader 0.2.6 compress mdfv3 4526 184 mdfreader 0.2.6 compress bcolz 6 mdfv3 4518 940 mdfreader 0.2.6 noDataLoading mdfv3 1833 120 asammdf 2.6.5 mdfv4 2214 330 asammdf 2.6.5 nodata mdfv4 1695 150 mdfreader 0.2.6 mdfv4 6348 870 mdfreader 0.2.6 compress mdfv4 7262 586 mdfreader 0.2.6 compress bcolz 6 mdfv4 7552 1294 mdfreader 0.2.6 noDataLoading mdfv4 4797 522 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 mdfv3 462 290 asammdf 2.6.5 nodata mdfv3 521 125 mdfreader 0.2.6 mdfv3 9175 481 mdfreader 0.2.6 compress mdfv3 9727 452 mdfreader 0.2.6 compress bcolz 6 mdfv3 9284 940 asammdf 2.6.5 mdfv4 657 334 asammdf 2.6.5 nodata mdfv4 710 159 mdfreader 0.2.6 mdfv4 6706 891 mdfreader 0.2.6 compress mdfv4 7030 851 mdfreader 0.2.6 compress bcolz6 mdfv4 6693 1311 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 mdfv3 791 291 asammdf 2.6.5 nodata mdfv3 18430 128 mdfreader 0.2.6 mdfv3 78 457 mdfreader 0.2.6 compress mdfv3 738 187 mdfreader 0.2.6 compress bcolz 6 mdfv3 299 941 asammdf 2.6.5 mdfv4 863 334 asammdf 2.6.5 nodata mdfv4 20637 157 mdfreader 0.2.6 mdfv4 77 869 mdfreader 0.2.6 compress mdfv4 653 593 mdfreader 0.2.6 compress bcolz 6 mdfv4 313 1301 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 v3 to v4 3843 680 asammdf 2.6.5 v3 to v4 nodata 4656 242 asammdf 2.6.5 v4 to v3 4261 681 asammdf 2.6.5 v4 to v3 nodata 5231 225 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.6.5 v3 10058 1248 asammdf 2.6.5 v3 nodata 11174 363 asammdf 2.6.5 v4 14232 1282 asammdf 2.6.5 v4 nodata 14629 380 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.7.0_mdfreader_0.2.7.txt000066400000000000000000000137421502633300400251150ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * compression bcolz 6 = mdfreader mdf object created with compression=6 * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full mdfv3 892 279 asammdf 2.7.0 low mdfv3 794 126 asammdf 2.7.0 minimum mdfv3 523 71 mdfreader 0.2.7 mdfv3 2978 421 mdfreader 0.2.7 compress mdfv3 4625 152 mdfreader 0.2.7 compress bcolz 6 mdfv3 4308 1307 mdfreader 0.2.7 noDataLoading mdfv3 812 121 asammdf 2.7.0 full mdfv4 2296 318 asammdf 2.7.0 low mdfv4 2139 152 asammdf 2.7.0 minimum mdfv4 1599 77 mdfreader 0.2.7 mdfv4 5662 421 mdfreader 0.2.7 compress mdfv4 6847 137 mdfreader 0.2.7 compress bcolz 6 mdfv4 7033 1200 mdfreader 0.2.7 noDataLoading mdfv4 3759 134 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full mdfv3 395 282 asammdf 2.7.0 low mdfv3 492 133 asammdf 2.7.0 minimum mdfv3 1197 78 mdfreader 0.2.7 mdfv3 9073 435 mdfreader 0.2.7 noDataLoading mdfv3 10121 464 mdfreader 0.2.7 compress mdfv3 9323 407 mdfreader 0.2.7 compress bcolz 6 mdfv3 9053 1307 asammdf 2.7.0 full mdfv4 550 322 asammdf 2.7.0 low mdfv4 639 162 asammdf 2.7.0 minimum mdfv4 2672 86 mdfreader 0.2.7 mdfv4 8705 440 mdfreader 0.2.7 noDataLoading mdfv4 7930 500 mdfreader 0.2.7 compress mdfv4 8836 401 mdfreader 0.2.7 compress bcolz6 mdfv4 8609 1214 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full mdfv3 854 284 asammdf 2.7.0 low mdfv3 12495 136 asammdf 2.7.0 minimum mdfv3 13589 82 mdfreader 0.2.7 mdfv3 76 421 mdfreader 0.2.7 nodata mdfv3 1419 327 mdfreader 0.2.7 compress mdfv3 699 153 mdfreader 0.2.7 compress bcolz 6 mdfv3 294 1307 asammdf 2.7.0 full mdfv4 885 323 asammdf 2.7.0 low mdfv4 15095 160 asammdf 2.7.0 minimum mdfv4 18019 85 mdfreader 0.2.7 mdfv4 72 421 mdfreader 0.2.7 nodata mdfv4 1914 351 mdfreader 0.2.7 compress mdfv4 706 142 mdfreader 0.2.7 compress bcolz 6 mdfv4 314 1205 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full v3 to v4 3997 383 asammdf 2.7.0 low v3 to v4 4474 234 asammdf 2.7.0 minimum v3 to v4 5185 182 asammdf 2.7.0 full v4 to v3 4634 378 asammdf 2.7.0 low v4 to v3 5111 213 asammdf 2.7.0 minimum v4 to v3 7996 140 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.7.0 full v3 10048 1184 asammdf 2.7.0 low v3 11128 339 asammdf 2.7.0 minimum v3 13078 201 mdfreader 0.2.7 v3 0 0 asammdf 2.7.0 full v4 14038 1241 asammdf 2.7.0 low v4 15429 371 asammdf 2.7.0 minimum v4 20086 185 mdfreader 0.2.7 v4 0 0 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.8.0_mdfreader_2.7.2.txt000066400000000000000000000121221502633300400251070ustar00rootroot00000000000000Benchmark environment * 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.14393-SP0 * Intel64 Family 6 Model 94 Stepping 3, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full mdfv3 918 264 asammdf 2.8.0 low mdfv3 898 110 asammdf 2.8.0 minimum mdfv3 577 56 mdfreader 2.7.2 mdfv3 2462 395 mdfreader 2.7.2 compress mdfv3 4174 97 mdfreader 2.7.2 noDataLoading mdfv3 911 105 asammdf 2.8.0 full mdfv4 2644 302 asammdf 2.8.0 low mdfv4 2269 137 asammdf 2.8.0 minimum mdfv4 1883 62 mdfreader 2.7.2 mdfv4 5869 403 mdfreader 2.7.2 compress mdfv4 7367 101 mdfreader 2.7.2 noDataLoading mdfv4 3897 110 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full mdfv3 452 267 asammdf 2.8.0 low mdfv3 495 118 asammdf 2.8.0 minimum mdfv3 1206 62 mdfreader 2.7.2 mdfv3 9258 415 asammdf 2.8.0 full mdfv4 642 307 asammdf 2.8.0 low mdfv4 693 146 asammdf 2.8.0 minimum mdfv4 2642 71 mdfreader 2.7.2 mdfv4 8548 422 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full mdfv3 889 268 asammdf 2.8.0 low mdfv3 12707 120 asammdf 2.8.0 minimum mdfv3 13644 66 mdfreader 2.7.2 mdfv3 80 395 mdfreader 2.7.2 nodata mdfv3 1413 310 mdfreader 2.7.2 compress mdfv3 529 97 asammdf 2.8.0 full mdfv4 968 307 asammdf 2.8.0 low mdfv4 14475 144 asammdf 2.8.0 minimum mdfv4 17057 69 mdfreader 2.7.2 mdfv4 72 403 mdfreader 2.7.2 nodata mdfv4 1806 325 mdfreader 2.7.2 compress mdfv4 562 107 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full v3 to v4 4048 642 asammdf 2.8.0 low v3 to v4 4551 219 asammdf 2.8.0 minimum v3 to v4 5847 121 asammdf 2.8.0 full v4 to v3 4394 639 asammdf 2.8.0 low v4 to v3 5239 198 asammdf 2.8.0 minimum v4 to v3 8392 98 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.0 full v3 10061 1168 asammdf 2.8.0 low v3 11245 323 asammdf 2.8.0 minimum v3 13618 186 asammdf 2.8.0 full v4 14144 1226 asammdf 2.8.0 low v4 15410 355 asammdf 2.8.0 minimum v4 21417 170 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.8.1_mdfreader_2.7.3.txt000066400000000000000000000117061502633300400251200ustar00rootroot00000000000000Benchmark environment * 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.16299-SP0 * Intel64 Family 6 Model 69 Stepping 1, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 1259 260 asammdf 2.8.1 low mdfv3 1076 106 asammdf 2.8.1 minimum mdfv3 767 52 mdfreader 2.7.3 mdfv3 3146 392 mdfreader 2.7.3 noDataLoading mdfv3 1159 102 asammdf 2.8.1 full mdfv4 2792 299 asammdf 2.8.1 low mdfv4 2645 133 asammdf 2.8.1 minimum mdfv4 2070 58 mdfreader 2.7.3 mdfv4 7372 397 mdfreader 2.7.3 noDataLoading mdfv4 4526 104 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 581 263 asammdf 2.8.1 low mdfv3 688 114 asammdf 2.8.1 minimum mdfv3 1931 58 mdfreader 2.7.3 mdfv3 8902 412 mdfreader 2.7.3 noDataLoading mdfv3 10490 420 asammdf 2.8.1 full mdfv4 843 303 asammdf 2.8.1 low mdfv4 959 143 asammdf 2.8.1 minimum mdfv4 3698 67 mdfreader 2.7.3 mdfv4 8084 417 mdfreader 2.7.3 noDataLoading mdfv4 9524 426 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 1278 265 asammdf 2.8.1 low mdfv3 18354 116 asammdf 2.8.1 minimum mdfv3 19288 63 mdfreader 2.7.3 mdfv3 117 392 asammdf 2.8.1 full mdfv4 1266 303 asammdf 2.8.1 low mdfv4 20515 141 asammdf 2.8.1 minimum mdfv4 23939 65 mdfreader 2.7.3 mdfv4 116 398 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full v3 to v4 5667 638 asammdf 2.8.1 low v3 to v4 6483 215 asammdf 2.8.1 minimum v3 to v4 8301 117 asammdf 2.8.1 full v4 to v3 6910 635 asammdf 2.8.1 low v4 to v3 7938 195 asammdf 2.8.1 minimum v4 to v3 12352 94 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full v3 14564 1165 asammdf 2.8.1 low v3 16148 319 asammdf 2.8.1 minimum v3 19046 180 mdfreader 2.7.3 v3 16765 928 asammdf 2.8.1 full v4 21262 1223 asammdf 2.8.1 low v4 23150 352 asammdf 2.8.1 minimum v4 30687 166 mdfreader 2.7.3 v4 25437 919 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_2.8.1_mdfreader_2.7.4.txt000066400000000000000000000123361502633300400251210ustar00rootroot00000000000000Benchmark environment * 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.16299-SP0 * Intel64 Family 6 Model 69 Stepping 1, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 1207 260 asammdf 2.8.1 low mdfv3 1065 107 asammdf 2.8.1 minimum mdfv3 746 52 mdfreader 2.7.4 mdfv3 3061 392 mdfreader 2.7.4 noDataLoading mdfv3 1154 106 asammdf 2.8.1 full mdfv4 2811 298 asammdf 2.8.1 low mdfv4 2708 134 asammdf 2.8.1 minimum mdfv4 2081 58 mdfreader 2.7.4 mdfv4 7293 397 mdfreader 2.7.4 noDataLoading mdfv4 4557 109 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 564 264 asammdf 2.8.1 low mdfv3 628 115 asammdf 2.8.1 minimum mdfv3 1780 58 mdfreader 2.7.4 mdfv3 9021 412 mdfreader 2.7.4 noDataLoading mdfv3 0* 0* asammdf 2.8.1 full mdfv4 798 303 asammdf 2.8.1 low mdfv4 916 143 asammdf 2.8.1 minimum mdfv4 3992 67 mdfreader 2.7.4 mdfv4 8069 417 mdfreader 2.7.4 noDataLoading mdfv4 9646 434 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full mdfv3 1226 265 asammdf 2.8.1 low mdfv3 17517 117 asammdf 2.8.1 minimum mdfv3 19145 63 mdfreader 2.7.4 mdfv3 120 392 mdfreader 2.7.4 nodata mdfv3 30561 130 asammdf 2.8.1 full mdfv4 1234 304 asammdf 2.8.1 low mdfv4 20214 141 asammdf 2.8.1 minimum mdfv4 23583 65 mdfreader 2.7.4 mdfv4 115 397 mdfreader 2.7.4 nodata mdfv4 38428 123 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full v3 to v4 5507 638 asammdf 2.8.1 low v3 to v4 6345 215 asammdf 2.8.1 minimum v3 to v4 8098 118 asammdf 2.8.1 full v4 to v3 6761 635 asammdf 2.8.1 low v4 to v3 7732 194 asammdf 2.8.1 minimum v4 to v3 12232 94 ================================================== ========= ======== ================================================== ========= ======== Merge files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 2.8.1 full v3 14283 1166 asammdf 2.8.1 low v3 15639 320 asammdf 2.8.1 minimum v3 18547 181 mdfreader 2.7.4 v3 16451 929 mdfreader 2.7.4 nodata v3 0* 0* asammdf 2.8.1 full v4 20925 1223 asammdf 2.8.1 low v4 22659 352 asammdf 2.8.1 minimum v4 29923 166 mdfreader 2.7.4 v4 25032 919 mdfreader 2.7.4 nodata v4 24316 948 ================================================== ========= ======== asammdf-8.5.1/benchmarks/results/x86_asammdf_4.0.0.dev_mdfreader_2.7.8.txt000066400000000000000000000135111502633300400256670ustar00rootroot00000000000000Benchmark environment * 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)] * Windows-10-10.0.17134-SP0 * Intel64 Family 6 Model 69 Stepping 1, GenuineIntel * 16GB installed RAM Notations used in the results * full = asammdf MDF object created with memory=full (everything loaded into RAM) * low = asammdf MDF object created with memory=low (raw channel data not loaded into RAM, but metadata loaded to RAM) * minimum = asammdf MDF object created with memory=full (lowest possible RAM usage) * compress = mdfreader mdf object created with compression=blosc * noDataLoading = mdfreader mdf object read with noDataLoading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 1792 272 asammdf 4.0.0.dev low mdfv3 1650 119 asammdf 4.0.0.dev minimum mdfv3 556 49 mdfreader 2.7.8 mdfv3 3526 394 mdfreader 2.7.8 compress mdfv3 5373 96 mdfreader 2.7.8 noDataLoading mdfv3 1427 108 asammdf 4.0.0.dev full mdfv4 2181 259 asammdf 4.0.0.dev low mdfv4 2045 94 asammdf 4.0.0.dev minimum mdfv4 1396 49 mdfreader 2.7.8 mdfv4 8189 399 mdfreader 2.7.8 compress mdfv4 10217 100 mdfreader 2.7.8 noDataLoading mdfv4 5227 110 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 1150 278 asammdf 4.0.0.dev low mdfv3 1303 125 asammdf 4.0.0.dev minimum mdfv3 3978 54 mdfreader 2.7.8 mdfv3 9154 414 mdfreader 2.7.8 noDataLoading mdfv3 10710 450 mdfreader 2.7.8 compress mdfv3 8789 388 asammdf 4.0.0.dev full mdfv4 1262 262 asammdf 4.0.0.dev low mdfv4 1382 103 asammdf 4.0.0.dev minimum mdfv4 4015 58 mdfreader 2.7.8 mdfv4 5285 418 mdfreader 2.7.8 noDataLoading mdfv4 8016 437 mdfreader 2.7.8 compress mdfv4 5027 382 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full mdfv3 2052 280 asammdf 4.0.0.dev low mdfv3 21601 131 asammdf 4.0.0.dev minimum mdfv3 24989 63 mdfreader 2.7.8 mdfv3 125 394 mdfreader 2.7.8 nodata mdfv3 33777 132 mdfreader 2.7.8 compress mdfv3 676 96 asammdf 4.0.0.dev full mdfv4 2177 263 asammdf 4.0.0.dev low mdfv4 25377 103 asammdf 4.0.0.dev minimum mdfv4 29231 58 mdfreader 2.7.8 mdfv4 116 399 mdfreader 2.7.8 compress mdfv4 666 105 mdfreader 2.7.8 nodata mdfv4 42202 125 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full v3 to v4 6679 552 asammdf 4.0.0.dev low v3 to v4 6897 221 asammdf 4.0.0.dev minimum v3 to v4 11120 87 asammdf 4.0.0.dev full v4 to v3 6004 511 asammdf 4.0.0.dev low v4 to v3 6294 161 asammdf 4.0.0.dev minimum v4 to v3 12459 79 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 4.0.0.dev full v3 20648 1411 asammdf 4.0.0.dev low v3 20279 391 asammdf 4.0.0.dev minimum v3 30807 119 mdfreader 2.7.8 v3 27054 1274 mdfreader 2.7.8 compress v3 32342 1288 mdfreader 2.7.8 nodata v3 26471 1343 asammdf 4.0.0.dev full v4 21532 1335 asammdf 4.0.0.dev low v4 21272 280 asammdf 4.0.0.dev minimum v4 45546 111 mdfreader 2.7.8 v4 40785 1260 mdfreader 2.7.8 nodata v4 40467 1284 ================================================== ========= ========asammdf-8.5.1/ci/000077500000000000000000000000001502633300400135245ustar00rootroot00000000000000asammdf-8.5.1/ci/__init__.py000066400000000000000000000001501502633300400156310ustar00rootroot00000000000000from ci.support import report_style as report_style from ci.support import report_tests as report_tests asammdf-8.5.1/ci/requirements.txt000066400000000000000000000000141502633300400170030ustar00rootroot00000000000000junitparser asammdf-8.5.1/ci/support.py000066400000000000000000000152641502633300400156220ustar00rootroot00000000000000import os import re import subprocess import warnings try: from junitparser import Error, Failure, JUnitXml, Skipped except ModuleNotFoundError: warnings.warn("JunitParser is not installed.", stacklevel=1) ROOT = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) class ReportTests: delim = "=" * 120 def __init__(self, dirpath, header): self._header = header self.passed = 0 self.skipped = 0 self.failed = 0 self.total_time = 0 self.summary = {"failed": {}, "skipped": {}} self._parse(dirpath) def __repr__(self): return f"{self._header}(PASSED: {self.passed}, FAILED: {self.failed}, SKIPPED: {self.skipped})" def __str__(self): # Process to MD md = [] # Brief Summary table = ( f"|Passed :heavy_check_mark: |Failed :x:|Skipped :warning: |Time :clock9: |\n" f"|------------------------------|---------------|--------------------|------------------|\n" f"|{self.passed} |{self.failed} |{self.skipped} |{self.total_time} |" ) md.append(table) # Failed and Skipped Summary for verdict, datas in self.summary.items(): emoji = ":warning:" if verdict == "skipped" else ":x:" verdict_table = ( f"|TestSuite |TestCase {emoji} |Time :clock9: |\n" f"|----------------|---------------------------|--------------|\n" ) verdict_details = "" for data in datas: verdict_table_entry = ( f"|{data.classname}|[{data.name}](#user-content-{data.name.lower()})|{data.time}|\n" ) verdict_data_entry = ( f"
\n" f'{data.classname}:{data.name}\n' f"\n\n" f"```python\n" f"{datas[data]}\n" f"```\n" f"
\n" ) verdict_table += verdict_table_entry verdict_details += verdict_data_entry if datas: md.append( f"
\n\n" f"#### View {verdict.capitalize()} Summary\n" f"\n\n" f"{verdict_table}\n" f"
\n" ) md.append("___\n") md.append(f"#### {verdict.capitalize()} Details:\n") md.append(f"{verdict_details}\n") md.append("___\n") md = "\n".join(md) if self._header: md = f"{self._header}\n{md}" return md def _parse(self, dirpath): # Parse Directory for root, _, files in os.walk(dirpath): # Filter only xml files for file in filter(lambda is_xml: is_xml.endswith(".xml"), files): filepath = os.path.join(root, file) try: testsuite = JUnitXml.fromfile(filepath) self.total_time += testsuite.time # If there are multiple testsuites if testsuite._tag == "testsuites": self._parse_testsuites(testsuite) else: self._parse_testcases(testsuite) except Exception as error: print(error) def _parse_testcases(self, testsuite): for testcase in testsuite: # Means is PASSED if not testcase.result: self.passed += 1 # Collect data for FAILED and SKIPPED tests. for tc_result in testcase.result: if isinstance(tc_result, Failure) or isinstance(tc_result, Error): self.summary["failed"][testcase] = ( f"STDOUT: \n{self.delim}\n{testcase.system_out}\n\n" f"STDERR: \n{self.delim}\n{testcase.system_err}\n\n" f"TEXT: \n{self.delim}\n{tc_result.text}\n\n" f"MESSAGE: \n{self.delim}\n{tc_result.message}\n\n" ) self.failed += 1 elif isinstance(tc_result, Skipped): self.summary["skipped"][testcase] = ( f"STDOUT: \n{self.delim}\n{testcase.system_out}\n\n" f"STDERR: \n{self.delim}\n{testcase.system_err}\n\n" f"TEXT: \n{self.delim}\n{tc_result.message}" ) self.skipped += 1 def _parse_testsuites(self, testsuites): for testsuite in testsuites: self._parse_testcases(testsuite) def report_coverage(): header = "## Coverage Report:\n" try: content = subprocess.check_output("coverage report", encoding="utf-8", cwd=ROOT) except: return # Print Raw Data raw_data = f"{header}\n{content}" print(raw_data) # Process to MD new_content = f"```shell\n{content}```" data = f"{header}\n{new_content}" write_summary(data) def report_tests(header=""): results = os.path.join(ROOT, "test-reports") report = ReportTests(dirpath=results, header=header) write_summary(str(report)) def report_style(): header = "## Style Report:\n" md = [] for root, _, files in os.walk(os.path.join(ROOT, ".tox", "style", "log")): for file in files: filepath = os.path.join(root, file) print(f"Checking File: {file}") with open(filepath, encoding="cp1252", errors="ignore") as fpr: content = fpr.read() # Extract Summary result = re.search( pattern=r"cmd: (black|isort).*?\n([\s\S]+)", string=content, flags=re.MULTILINE, ) if result: # First Group check_type = result.group(1) output = result.group(2) if output.startswith("exit_code: 0"): emoji = ":heavy_check_mark:" else: emoji = ":x:" md.append(f"### {check_type.capitalize()} Check: {emoji}\n") md.append(f"```log\n{output}\n```\n") md.append("\n___") md = "\n".join(md) if header: md = f"{header}\n{md}" write_summary(md) def write_summary(content): filepath = os.getenv("GITHUB_STEP_SUMMARY", "") if not filepath: return # Append Data with open(filepath, "a") as fpa: fpa.write(content) if __name__ == "__main__": report_style() asammdf-8.5.1/demo.dspf000066400000000000000000000222051502633300400147340ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Plot 0", "configuration": { "channels": [ { "type": "group", "name": "CAN Data", "enabled": true, "pattern": null, "ranges": [], "origin_uuid": "59e30cbad3e6", "expanded": true, "disabled": false, "channels": [ { "type": "channel", "name": "CAN_DataFrame.BusChannel", "unit": "", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#1f77b4", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ -13.31, 2.0900000000000016 ], "origin_uuid": "014aa309cbcb" }, { "type": "channel", "name": "CAN_DataFrame.DLC", "unit": "", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff7f0e", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -8.11, 7.290000000000003 ], "origin_uuid": "014aa309cbcb" }, { "type": "channel", "name": "CAN_DataFrame.Flags", "unit": "", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#2ca02c", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -9.91, 5.490000000000002 ], "origin_uuid": "014aa309cbcb" }, { "type": "channel", "name": "CAN_DataFrame.ID", "unit": "", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#d62728", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ 92.29, 107.69000000000001 ], "origin_uuid": "014aa309cbcb" } ] }, { "type": "channel", "name": "Curve", "unit": "", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#8c564b", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ -168.596, 441.244 ], "origin_uuid": "014aa309cbcb" }, { "type": "channel", "name": "State", "unit": "", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#e377c2", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -3.3100000000000005, 12.090000000000003 ], "origin_uuid": "014aa309cbcb" }, { "type": "channel", "name": "Counter", "unit": "", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#9467bd", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -1.11, 14.290000000000003 ], "origin_uuid": "014aa309cbcb" } ], "pattern": {}, "splitter": [ 394, 414, 0 ], "y_axis_width": 48.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": false, "common_axis_y_range": [ 0.0, 1.0 ], "channels_header": [ 394, [ 220, 83, 28, 35, 35 ] ], "hide_axes": false, "hide_selected_channel_value_panel": false, "focused_mode": false, "delta_mode": "value", "hide_bookmarks": true }, "geometry": [ 824, 278, 822, 672 ], "maximized": false, "minimized": false, "type": "Plot" }, { "title": "Numeric 0", "configuration": { "format": "Physical", "mode": "offline", "channels": [ { "origin_uuid": "0", "name": "CAN_DataFrame.BusChannel", "ranges": [], "format": "phys" }, { "origin_uuid": "0", "name": "CAN_DataFrame.DLC", "ranges": [], "format": "phys" }, { "origin_uuid": "0", "name": "CAN_DataFrame.Flags", "ranges": [], "format": "phys" }, { "origin_uuid": "0", "name": "CAN_DataFrame.ID", "ranges": [], "format": "phys" } ], "pattern": {}, "float_precision": -1, "header_sections_width": [ 259, 130, 142, 130 ], "font_size": 9 }, "geometry": [ 0, 716, 824, 234 ], "maximized": false, "minimized": false, "type": "Numeric" }, { "title": "Tabular 0", "configuration": { "sorted": true, "channels": [ "timestamps", "State", "Curve", "Counter" ], "filtered": false, "filters": [], "time_as_date": false, "pattern": {}, "format": "phys", "ranges": { "Counter": [], "Curve": [], "State": [], "timestamps": [] }, "header_sections_width": [ 220, 116, 206, 130 ], "font_size": 9 }, "geometry": [ 824, 0, 822, 279 ], "maximized": false, "minimized": false, "type": "Tabular" }, { "title": "CAN Bus Trace 0", "configuration": { "sorted": true, "channels": [ "timestamps", "Bus", "ID", "Direction", "Name", "Event Type", "Details", "ESI", "EDL", "BRS", "DLC", "Data Length", "Data Bytes" ], "filtered": false, "filters": [], "time_as_date": false, "pattern": {}, "format": "phys", "ranges": { "timestamps": [], "Bus": [], "ID": [], "Direction": [], "Name": [], "Event Type": [ { "background_color": "#ff0000", "font_color": "#000000", "op1": "==", "op2": "==", "value1": "Error Frame", "value2": null }, { "background_color": "#00ff00", "font_color": "#000000", "op1": "==", "op2": "==", "value1": "Remote Frame", "value2": null } ], "Details": [], "ESI": [], "EDL": [], "BRS": [], "DLC": [], "Data Length": [], "Data Bytes": [] }, "header_sections_width": [ 159, 54, 41, 83, 96, 90, 68, 40, 103, 41, 39, 97, 181 ], "font_size": 9 }, "geometry": [ 0, 0, 824, 717 ], "maximized": false, "minimized": false, "type": "CAN Bus Trace" } ], "functions": {} }asammdf-8.5.1/doc/000077500000000000000000000000001502633300400136765ustar00rootroot00000000000000asammdf-8.5.1/doc/Makefile000066400000000000000000000011371502633300400153400ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = python -msphinx SPHINXPROJ = asammdf SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)asammdf-8.5.1/doc/api.rst000066400000000000000000000031041502633300400151770ustar00rootroot00000000000000.. raw:: html .. role:: red .. role:: blue .. role:: green .. role:: cyan .. role:: magenta .. role:: orange .. role:: brown .. default-role:: py:obj --- API --- MDF === This class acts as a proxy for the `MDF2`, `MDF3` and `MDF4` classes. All attribute access is delegated to the underlying `_mdf` attribute (MDF2, MDF3 or MDF4 object). See MDF3 and MDF4 for available extra methods (MDF2 and MDF3 share the same implementation). An empty MDF file is created if the `name` argument is not provided. If the `name` argument is provided then the file must exist in the filesystem, otherwise an exception is raised. The best practice is to use the `MDF` as a context manager. This way all resources are released correctly in case of exceptions. .. code:: with MDF(r'test.mdf') as mdf_file: # do something .. autoclass:: asammdf.mdf.MDF :members: MDF3 ==== .. autoclass:: asammdf.blocks.mdf_v3.MDF3 :members: :noindex: MDF version 2 & 3 blocks ------------------------ .. toctree:: :maxdepth: 2 v2v3blocks MDF4 ==== .. autoclass:: asammdf.blocks.mdf_v4.MDF4 :members: :noindex: MDF version 4 blocks -------------------- .. toctree:: :maxdepth: 2 v4blocks Signal ====== .. autoclass:: asammdf.signal.Signal :members: asammdf-8.5.1/doc/benchmarks.rst000066400000000000000000000712141502633300400165520ustar00rootroot00000000000000.. raw:: html .. role:: red .. role:: blue .. role:: green .. role:: cyan .. role:: magenta .. role:: orange .. role:: brown ---------- Benchmarks ---------- Test setup ========== The benchmarks were done using two test files (available `here `_) (for mdf version 3 and 4) of around 170MB. The files contain 183 data groups and a total of 36424 channels. *asamdf 7.0.1* was compared against *mdfreader 4.1*. For each category two aspect were noted: elapsed time and peak RAM usage. Dependencies ------------ You will need the following packages to be able to run the benchmark script * psutil * mdfreader Usage ----- Extract the test files from the archive, or provide a folder that contains the files "test.mdf" and "test.mf4". Run the module *bench.py* ( see --help option for available options ) x64 Python results ================== Benchmark environment * 3.9.4 (tags/v3.9.4:1f2e308, Apr 6 2021, 13:40:21) [MSC v.1928 64 bit (AMD64)] * Windows-10-10.0.19041-SP0 * Intel64 Family 6 Model 158 Stepping 10, GenuineIntel * numpy 1.21.2 * 16GB installed RAM Notations used in the results * compress = mdfreader mdf object created with compression=blosc * nodata = mdfreader mdf object read with no_data_loading=True Files used for benchmark: * mdf version 3.10 * 167 MB file size * 183 groups * 36424 channels * mdf version 4.00 * 183 MB file size * 183 groups * 36424 channels ================================================== ========= ======== Open file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 mdfv3 369 186 mdfreader 4.1 mdfv3 1741 498 mdfreader 4.1 no_data_loading mdfv3 646 248 mdfreader 4.1 compress mdfv3 1463 365 asammdf 7.0.1 mdfv4 468 199 mdfreader 4.1 mdfv4 4350 520 mdfreader 4.1 no_data_loading mdfv4 2892 310 mdfreader 4.1 compress mdfv4 4105 391 ================================================== ========= ======== ================================================== ========= ======== Save file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 mdfv3 378 186 mdfreader 4.1 mdfv3 4310 527 mdfreader 4.1 no_data_loading mdfv3 5070 586 mdfreader 4.1 compress mdfv3 4456 525 asammdf 7.0.1 mdfv4 331 366 mdfreader 4.1 mdfv4 2254 539 mdfreader 4.1 no_data_loading mdfv4 3591 618 mdfreader 4.1 compress mdfv4 2400 535 ================================================== ========= ======== ================================================== ========= ======== Get all channels (36424 calls) Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 mdfv3 3354 187 mdfreader 4.1 mdfv3 40 498 mdfreader 4.1 nodata mdfv3 12686 283 mdfreader 4.1 compress mdfv3 154 366 asammdf 7.0.1 mdfv4 5243 364 mdfreader 4.1 mdfv4 51 520 mdfreader 4.1 nodata mdfv4 20210 336 mdfreader 4.1 compress mdfv4 170 396 ================================================== ========= ======== ================================================== ========= ======== Convert file Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 v3 to v4 2186 232 asammdf 7.0.1 v4 to v410 2008 394 asammdf 7.0.1 v4 to v420 2359 438 ================================================== ========= ======== ================================================== ========= ======== Merge 3 files Time [ms] RAM [MB] ================================================== ========= ======== asammdf 7.0.1 v3 6449 224 mdfreader 4.1 v3 0* 0* mdfreader 4.1 nodata v3 0* 0* mdfreader 4.1 compress v3 0* 0* asammdf 7.0.1 v4 6713 409 mdfreader 4.1 v4 34746 1156 mdfreader 4.1 nodata v4 37608 1266 mdfreader 4.1 compress v4 34184 1151 ================================================== ========= ======== Graphical results ----------------- .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Open' aspect = 'time' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'mdf' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) arr = ram if aspect == 'ram' else time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Open' aspect = 'ram' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Save' aspect = 'time' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Save' aspect = 'ram' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Get' aspect = 'time' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Get' aspect = 'ram' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Convert' aspect = 'time' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Convert' aspect = 'ram' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Merge' aspect = 'time' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() .. plot:: import matplotlib.pyplot as plt import numpy as np res = '../benchmarks/results/x64_asammdf_7.0.1_mdfreader_4.1.rst' topic = 'Merge' aspect = 'ram' for_doc = True with open(res, 'r') as f: lines = f.readlines() platform = 'x86' if '32 bit' in lines[2] else 'x64' idx = [i for i, line in enumerate(lines) if line.startswith('==')] table_spans = {'open': [idx[1] + 1, idx[2]], 'save': [idx[4] + 1, idx[5]], 'get': [idx[7] + 1, idx[8]], 'convert' : [idx[10] + 1, idx[11]], 'merge' : [idx[13] + 1, idx[14]]} start, stop = table_spans[topic.lower()] cat = [l[:50].strip(' \t\n\r\0*') for l in lines[start: stop]] time = np.array([int(l[50:61].strip(' \t\n\r\0*')) for l in lines[start: stop]]) ram = np.array([int(l[61:].strip(' \t\n\r\0*')) for l in lines[start: stop]]) if aspect == 'ram': arr = ram else: arr = time y_pos = list(range(len(cat))) fig, ax = plt.subplots() fig.set_size_inches(15, 3.8 / 12 * len(cat) + 1.2) asam_pos = [i for i, c in enumerate(cat) if c.startswith('asam')] mdfreader_pos = [i for i, c in enumerate(cat) if c.startswith('mdfreader')] ax.barh(asam_pos, arr[asam_pos], color='green', ecolor='green') ax.barh(mdfreader_pos, arr[mdfreader_pos], color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(cat) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Time [ms]' if aspect == 'time' else 'RAM [MB]') if topic == 'Get': ax.set_title('Get all channels (36424 calls) - {}'.format('time' if aspect == 'time' else 'ram usage')) else: ax.set_title('{} test file - {}'.format(topic, 'time' if aspect == 'time' else 'ram usage')) ax.xaxis.grid() fig.subplots_adjust(bottom=0.72/fig.get_figheight(), top=1-0.48/fig.get_figheight(), left=0.4, right=0.9) if aspect == 'time': if topic == 'Get': name = '{}_get_all_channels.png'.format(platform) else: name = '{}_{}.png'.format(platform, topic.lower()) else: if topic == 'Get': name = '{}_get_all_channels_ram_usage.png'.format(platform) else: name = '{}_{}_ram_usage.png'.format(platform, topic.lower()) plt.show() asammdf-8.5.1/doc/buslogging.rst000066400000000000000000000025161502633300400165740ustar00rootroot00000000000000------------ Bus logging ------------ Initial read only mode for mdf version 4.10 files containing CAN/LIN bus logging is now implemented. To handle this, the **canmatrix** package was added to the dependencies; you will need to install the latest code from the **canmatrix** library. Let's take for example the following situation: the .dbc contains the definition for the CAN message called "VehicleStatus" with `ID=123`. This message contains the signal "EngineStatus". Logging was made from the CAN bus with `ID=1` (CAN1). There multiple ways to address this channel in this situation: #. short signal name as found in the .dbc file .. code:: python mdf.get('EngineStatus') #. dbc message name and short signal name, delimited by dot .. code:: python mdf.get('VehicleStatus.EngineStatus') #. CAN bus ID, dbc message name and short signal name, delimited by dot .. code:: python mdf.get('CAN1.VehicleStatus.EngineStatus') #. ASAM conformant message ID and short signal name, delimited by dot .. code:: python mdf.get('CAN_DataFrame_123.EngineStatus') #. CAN bus ID, ASAM conformant message ID and short signal name, delimited by dot .. code:: python mdf.get('CAN1.CAN_DataFrame_123.EngineStatus') asammdf-8.5.1/doc/conf.py000066400000000000000000000130411502633300400151740ustar00rootroot00000000000000#!/usr/bin/env python3 # # asammdf documentation build configuration file, created by # sphinx-quickstart on Wed Jul 12 06:05:15 2017. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # BASE_DIR = os.path.abspath("..") # sys.path.insert(0, BASE_DIR) from asammdf.version import __version__ as asam_version print("version", asam_version) html_theme = "pydata_sphinx_theme" html_theme = "bizstyle" # html_theme = "sphinx_rtd_theme" # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "sphinx.ext.autodoc", "sphinx.ext.autosummary", "sphinx.ext.imgmath", "sphinx.ext.githubpages", "sphinx.ext.viewcode", "matplotlib.sphinxext.plot_directive", "sphinxarg.ext", "numpydoc", ] # silence the Sphinx warnings about # "WARNING: toctree contains reference to nonexisting document" # http://stackoverflow.com/questions/12206334/sphinx-autosummary-toctree-contains-reference-to-nonexisting-document-warnings numpydoc_show_class_members = False # numpydoc_class_members_toctree = False # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = ".rst" # The master toctree document. master_doc = "index" # General information about the project. project = "asammdf" copyright = "2018-2025, Daniel Hrisca" author = "Daniel Hrisca" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = asam_version # The full version, including alpha/beta/rc tags. release = asam_version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # # html_theme = 'classic' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {'stickysidebar': 'true'} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] html_logo = "../asammdf.png" # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. # htmlhelp_basename = 'asammdfdoc' # -- Options for LaTeX output --------------------------------------------- # latex_elements = { # # The paper size ('letterpaper' or 'a4paper'). # # # # 'papersize': 'letterpaper', # # The font size ('10pt', '11pt' or '12pt'). # # # # 'pointsize': '10pt', # # Additional stuff for the LaTeX preamble. # # # # 'preamble': '', # # Latex figure (float) alignment # # # # 'figure_align': 'htbp', # } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [(master_doc, "asammdf.tex", "asammdf Documentation", "Daniel Hrisca", "manual")] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [(master_doc, "asammdf", "asammdf Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ( master_doc, "asammdf", "asammdf Documentation", author, "asammdf", "One line description of project.", "Miscellaneous", ) ] # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {"https://docs.python.org/": None} asammdf-8.5.1/doc/examples.rst000066400000000000000000000301201502633300400162420ustar00rootroot00000000000000.. raw:: html .. role:: red .. role:: blue .. role:: green .. role:: cyan .. role:: magenta .. role:: orange .. role:: brown .. _examples: -------- Examples -------- Working with MDF ================ .. code-block:: python from asammdf import MDF, Signal import numpy as np # create 3 Signal objects timestamps = np.array([0.1, 0.2, 0.3, 0.4, 0.5], dtype=np.float32) # unit8 s_uint8 = Signal(samples=np.array([0, 1, 2, 3, 4], dtype=np.uint8), timestamps=timestamps, name='Uint8_Signal', unit='u1') # int32 s_int32 = Signal(samples=np.array([-20, -10, 0, 10, 20], dtype=np.int32), timestamps=timestamps, name='Int32_Signal', unit='i4') # float64 s_float64 = Signal(samples=np.array([-20, -10, 0, 10, 20], dtype=np.float64), timestamps=timestamps, name='Float64_Signal', unit='f8') # create empty MDf version 4.00 file with MDF(version='4.10') as mdf4: # append the 3 signals to the new file signals = [s_uint8, s_int32, s_float64] mdf4.append(signals, comment='Created by Python') # save new file mdf4.save('my_new_file.mf4', overwrite=True) # convert new file to mdf version 3.10 mdf3 = mdf4.convert(version='3.10') print(mdf3.version) # get the float signal sig = mdf3.get('Float64_Signal') print(sig) # cut measurement from 0.3s to end of measurement mdf4_cut = mdf4.cut(start=0.3) mdf4_cut.get('Float64_Signal').plot() # cut measurement from start of measurement to 0.4s mdf4_cut = mdf4.cut(stop=0.45) mdf4_cut.get('Float64_Signal').plot() # filter some signals from the file mdf4 = mdf4.filter(['Int32_Signal', 'Uint8_Signal']) # save using zipped transpose deflate blocks mdf4.save('out.mf4', compression=2, overwrite=True) Working with Signal =================== .. code-block:: python from asammdf import Signal import numpy as np # create 3 Signal objects with different time stamps # unit8 with 100ms time raster timestamps = np.array([0.1 * t for t in range(5)], dtype=np.float32) s_uint8 = Signal(samples=np.array([t for t in range(5)], dtype=np.uint8), timestamps=timestamps, name='Uint8_Signal', unit='u1') # int32 with 50ms time raster timestamps = np.array([0.05 * t for t in range(10)], dtype=np.float32) s_int32 = Signal(samples=np.array(list(range(-500, 500, 100)), dtype=np.int32), timestamps=timestamps, name='Int32_Signal', unit='i4') # float64 with 300ms time raster timestamps = np.array([0.3 * t for t in range(3)], dtype=np.float32) s_float64 = Signal(samples=np.array(list(range(2000, -1000, -1000)), dtype=np.int32), timestamps=timestamps, name='Float64_Signal', unit='f8') # map signals xs = np.linspace(-1, 1, 50) ys = np.linspace(-1, 1, 50) X, Y = np.meshgrid(xs, ys) vals = np.linspace(0, 180. / np.pi, 100) phi = np.ones((len(vals), 50, 50), dtype=np.float64) for i, val in enumerate(vals): phi[i] *= val R = 1 - np.sqrt(X**2 + Y**2) samples = np.cos(2 * np.pi * X + phi) * R timestamps = np.arange(0, 2, 0.02) s_map = Signal(samples=samples, timestamps=timestamps, name='Variable Map Signal', unit='dB') s_map.plot() prod = s_float64 * s_uint8 prod.name = 'Uint8_Signal * Float64_Signal' prod.unit = '*' prod.plot() pow2 = s_uint8 ** 2 pow2.name = 'Uint8_Signal ^ 2' pow2.unit = 'u1^2' pow2.plot() allsum = s_uint8 + s_int32 + s_float64 allsum.name = 'Uint8_Signal + Int32_Signal + Float64_Signal' allsum.unit = '+' allsum.plot() # inplace operations prod *= -1 prod.name = '- Uint8_Signal * Float64_Signal' prod.plot() # cut signal s_int32.plot() cut_signal = s_int32.cut(start=0.2, stop=0.35) cut_signal.plot() MF4 demo file generator ======================= .. code-block:: python from asammdf import MDF, SUPPORTED_VERSIONS, Signal import numpy as np cycles = 100 sigs = [] mdf = MDF() t = np.arange(cycles, dtype=np.float64) # no conversion sig = Signal( np.ones(cycles, dtype=np.uint64), t, name='Channel_no_conversion', unit='s', conversion=None, comment='Unsigned 64 bit channel {}', ) sigs.append(sig) # linear conversion = { 'a': 2, 'b': -0.5, } sig = Signal( np.ones(cycles, dtype=np.int64), t, name='Channel_linear_conversion', unit='Nm', conversion=conversion, comment='Signed 64bit channel with linear conversion', ) sigs.append(sig) # algebraic conversion = { 'formula': '2 * sin(X)', } sig = Signal( np.arange(cycles, dtype=np.int32) / 100.0, t, name='Channel_algebraic', unit='eV', conversion=conversion, comment='Sinus channel with algebraic conversion', ) sigs.append(sig) # rational conversion = { 'P1': 0, 'P2': 4, 'P3': -0.5, 'P4': 0, 'P5': 0, 'P6': 1, } sig = Signal( np.ones(cycles, dtype=np.int64), t, name='Channel_rational_conversion', unit='Nm', conversion=conversion, comment='Channel with rational conversion', ) sigs.append(sig) # string channel sig = [ 'String channel sample {}'.format(j).encode('ascii') for j in range(cycles) ] sig = Signal( np.array(sig), t, name='Channel_string', comment='String channel', encoding='latin-1', ) sigs.append(sig) # byte array ones = np.ones(cycles, dtype=np.dtype('(8,)u1')) sig = Signal( ones*111, t, name='Channel_bytearay', comment='Byte array channel', ) sigs.append(sig) # tabular vals = 20 conversion = { 'raw_{}'.format(i): i for i in range(vals) } conversion.update( { 'phys_{}'.format(i): -i for i in range(vals) } ) sig = Signal( np.arange(cycles, dtype=np.uint32) % 20, t, name='Channel_tabular', unit='-', conversion=conversion, comment='Tabular channel', ) sigs.append(sig) # value to text vals = 20 conversion = { 'val_{}'.format(i): i for i in range(vals) } conversion.update( { 'text_{}'.format(i): 'key_{}'.format(i).encode('ascii') for i in range(vals) } ) conversion['default'] = b'default key' sig = Signal( np.arange(cycles, dtype=np.uint32) % 30, t, name='Channel_value_to_text', conversion=conversion, comment='Value to text channel', ) sigs.append(sig) # tabular with range vals = 20 conversion = { 'lower_{}'.format(i): i * 10 for i in range(vals) } conversion.update( { 'upper_{}'.format(i): (i + 1) * 10 for i in range(vals) } ) conversion.update( { 'phys_{}'.format(i): i for i in range(vals) } ) conversion['default'] = -1 sig = Signal( 2 * np.arange(cycles, dtype=np.float64), t, name='Channel_value_range_to_value', unit='order', conversion=conversion, comment='Value range to value channel', ) sigs.append(sig) # value range to text vals = 20 conversion = { 'lower_{}'.format(i): i * 10 for i in range(vals) } conversion.update( { 'upper_{}'.format(i): (i + 1) * 10 for i in range(vals) } ) conversion.update( { 'text_{}'.format(i): 'Level {}'.format(i) for i in range(vals) } ) conversion['default'] = b'Unknown level' sig = Signal( 6 * np.arange(cycles, dtype=np.uint64) % 240, t, name='Channel_value_range_to_text', conversion=conversion, comment='Value range to text channel', ) sigs.append(sig) mdf.append(sigs, comment='single dimensional channels', common_timebase=True) sigs = [] # lookup tabel with axis samples = [ np.ones((cycles, 2, 3), dtype=np.uint64) * 1, np.ones((cycles, 2), dtype=np.uint64) * 2, np.ones((cycles, 3), dtype=np.uint64) * 3, ] types = [ ('Channel_lookup_with_axis', '(2, 3) 5: return 1 "this function will produce errors because it returns non-numeric values" def Function1(a=0, t=0): if a > 5: return "Activated" else: return "Disabled" "this function is OK because it has explicit return statements with numeric values" def Function1(a=0, t=0): if a > 5: return 1 else: return 0 * the modules `math`, `pandas` and `numpy` are available inside the function as `math`, `pd` and `np` * functions can be cross-referenced; one function can call another user defined function .. code:: python def Function1(a=0, t=0): if a > 5: return 1 else: return 0 " Function2 can call Function 1" def Function2(b=1, c=7, t=0): if b != 0: return Function1(c) else: return c / 2 Virtual channel dialog ====================== Virtual channels can be added to Plot windows using the keyboard shortcut ``Ins`` (insert). The precondition for this is to have at least one function defined in the Functions manager. In the `Define channel` dialog window the user can select one of the available function, and then for each of the function's arguments a list of alternative channel names can be filed by the user. The argument `t=0` is reserved for the time-stamp and is not shown in the dialog window. The alternative names must be placed on separate lines in the text field found next to the argument name. .. image:: images/virtual_channel_dialog.png ======================================= ================================================================================ Option Description ======================================= ================================================================================ ``Triggering`` the virtual channel samples will be calculated in the time stamps defined by the selected choice ``Computation mode`` the virtual channel can be computed passing the signal arguments samples by sample or passing the signal arguments directly as numpy ndarrays ``Function name`` select one of the available functions ``Function info`` displays the function definition code ``Arguments`` alternative channel names for each argument. In the example argument `b` will use the first existing ASAP from the choices `MAIN_CLOCK` or `MAIN_CLOCK_5MS`. If no alternative exist in the measurement file then the argument's default value will be used (see the function definition) ``Argument search`` opens a search dialog were channel names cane be searched from the measurement file ``Computed channel name`` virtual channel name ``Computed channel comment`` virtual channel comment ``Computed channel unit`` virtual channel unit ``Function definition`` Python language function definition ``Check syntax`` Check if the current function definition syntax is valid ``Store function changes`` Updates the definition after the user has made changes. If this is not pressed and the user switches to another function then the changes will be lost. ``Apply`` Accept the changes and inserts the new virtual channel ``Cancel`` Rejects all the changes made by the user ======================================= ================================================================================ When the computation mode is set to `sample by sample` the following steps are executed: * the signals linked to the arguments are searched in the measurement file * using the signals found in the measurement, the union of all time stamps is computed (resulting an ndarray of length N) * all found signals are interpolated using the union time base * the function is called N times (once for each of the N time stamps) passing the signal value for the current time stamp and the time stamp (in the `t` argument). The missing linked signals will be replaced by the default value specified in the function definition * the returned value are stored and finally the resulting Signal is constructed When the computation mode is set to `complete signal` the following steps are executed: * the signals linked to the arguments are searched in the measurement file * using the signals found in the measurement, the union of all time stamps is computed (resulting an ndarray of length N) * all found signals are interpolated using the union time base * the function is called only 1 time passing the complete signal ndarray's and the union of the time stamps (in the `t` argument). The missing linked signals will be replaced by an ndarray of length N filled with the default value specified in the function definition * the result Signal is constructed using the ndarray returned by the function Example functions ================= Average of 3 channels --------------------- The same definition works for both `sample by sample` and `complete signal` computation modes .. code:: python def average(channel1=0, channel2=-1, channel3=0, t=0): return (channel1 + channel2 + channel3) / 3 Channel clipping ---------------- Using `sample by sample` computation mode .. code:: python def clip(channel1=0, t=0): if channel1 > 100: return 100 elif channe1 < 0: return 0 else: return channel1 Using `complete signal` computation mode .. code:: python def clip(channel1=0, t=0): return np.clip(cahnnel1, 0, 100) Grey code to decimal -------------------- The same definition works for both `sample by sample` and `complete signal` computation modes .. code:: python def gray2dec(position_sensor_value=0, t=0): for shift in (8, 4, 2, 1): position_sensor_value = position_sensor_value ^ (position_sensor_value >> shift) return position_sensor_value Maximum of 3 channels --------------------- Using `sample by sample` computation mode .. code:: python def maximum(channel1=0, channel2=-1, channel3=0, t=0): return max(channel1, channel2, channel3) Using `complete signal` computation mode .. code:: python def maximum(channel1=0, channel2=-1, channel3=0, t=0): return np.maximum.reduce([channel1, channel2, channel3]) rpm to rad/s ------------ The same definition works for both `sample by sample` and `complete signal` computation modes .. code:: python def rpm_to_rad_per_second(speed=0, t=0): return 2 * np.pi * speed / 60 gradient -------- In the `Define channel` dialog the computation mode must be set to `complete signal` .. code:: python def rpm_to_rad_per_second(speed=0, t=0): return np.diff(speed) / np.diff(t) It is not possible to implement this function in the `sample by sample` mode because only the current samples are forwarded to the function. asammdf-8.5.1/doc/gui.rst000066400000000000000000000501101502633300400152110ustar00rootroot00000000000000.. raw:: html .. role:: red .. role:: blue .. role:: green .. role:: cyan .. role:: magenta .. role:: orange .. role:: brown .. _gui: --- GUI --- With the GUI tool you can * visualize channels * compare channels from multiple files in the same plot * see channel, conversion and source metadata as stored in the MDF file * access library functionality for single files (convert, export, cut, filter, resample, scramble) and multiple files (concatenate, stack) After you pip install asammdf using ``pip install asammdf[gui]`` there will be a new script called *asammdf.exe* in the `python_installation_folder\\Scripts` folder. The following dependencies are required by the GUI * PyQt5 * pyqtgraph General shortcuts ================= ============ ====================== ================================================================================================================ Shortcut Action Description ============ ====================== ================================================================================================================ F1 Help Opens this online help page F2 Create plot Create a new Plot window using the checked channels from the selection tree F3 Create numeric Create a new Numeric window using the checked channels from the selection tree F4 Create tabular Create a new Tabular window using the checked channels from the selection tree F11 Toggle fullscreen In the single files mode will display the current opened file in full screen Ctrl+O Open file(s) ============ ====================== ================================================================================================================ Menu ==== File ---- The first menu command is *Open*. Depending on the mode this allows to open files individually or for batch processing. The second menu command is *Open folder*. If this is selected then, starting with the selected root folder, all sub-folders are searched recursively for MDF files. Once a file has been opened, the user can load or save a display configuration using the *Open configuration* and *Save configuration* menu items. Mode ---- * *Single files* : files are opened individually * *Batch processing* : allows processing multiple files * *Comparison* : show channels from all the opened files Settings -------- The following settings are available * **Sub-windows**: controls if multiple subplots will be created when the plot button is pressed * ``Disabled``: a single plot is used that is overwritten * ``Enabled``: a new subplot is added * **Link sub-windows X-axis**: controls the subplots are linked on the X axis (zooming will affect all sub-windows) * ``Disabled`` * ``Enabled`` * **Ignore value2text conversions**: do not apply the value to text conversions * ``Disabled`` * ``Enabled`` * **Plot background**: switch plot background color (does not affect existing plots) * ``Black`` * ``White`` * **Plot X axis**: select how the X axis will be displayed * ``seconds`` * ``time`` : values will be formatted as hours, minutes and seconds * ``date`` : the values will use the measurement start datetime * **Theme**: switch application theme * ``Dark`` * ``Light`` * **Step mode**: controls how the signal samples are interconnected visually in the Plot * **Integer interpolation**: selects the way integer channels are interpolated * ``0 - repeat previous sample`` * ``1 - linear interpolation`` * ``2 - hybrid interpolation`` * **Float interpolation**: selects the way float channels are interpolated * ``0 - repeat previous sample`` * ``1 - linear interpolation`` The settings are saved and restored each time the GUI is started. Plot ---- There are several keyboard shortcuts for handling the plots: ============ ====================== ================================================================================================================ Shortcut Action Description ============ ====================== ================================================================================================================ C Edit signal color Opens a dialog to select the signal color [7]_ F Fit all Y-axis fit all active channels on the screen, keeping the current X-axis range Shift+F Fit selected Y-axis fit all active selected channels on the screen; unselected channels are not fitted G Grid Toggle grid lines W Home Whole signals XY-axis fit H Honeywell zomm in on the current cursor position using a constant zoom level of 0.1s/cm (real display width) I Zoom-in X-axis zoom-in [1]_ O Zoom-out X-axis zoom-out [1]_ X Zoom to range If the region is enabled, it will zoom to it M Statistics Toggle the display of the statistic panel R Range Display a movable range that will trigger the display of the delta values for all plot channels [2]_ S Stack all Y Stack all active channels so that they don't overlap, keeping the X-axis range Shift+S Stack selected Y Stack all active selected channels so that they don't overlap; unselected channels are not stacked Y Lock/unlock region Lock or unlock the left margin of the region . Toggle dots Toggle the display of signal samples (using dots affects performance) ← Move cursor left Moves the cursor to the next sample on the left → Move cursor right Moves the cursor to the next sample on the right Ins Insert computation Insert new channel in the plot using functions and operations F11 Toggle full screen In the single files mode will display the current opened file in full screen Alt+I Toggle trigger texts Toggle the text boxes for the triggers [6]_ Alt+R Raw samples Toggle raw samples mode for the selected channels [6]_ Alt+S Scaled samples Toggle scaled (physical) samples mode for the selected channels Ctrl+B Bin Toggle binary representation of integer channels Ctrl+H Hex Toggle hex representation of integer channels Ctrl+I Insert cursor comment Insert a visual vertical line and comment at the current cursor position [6]_ Ctrl+P Physical Toggle physical representation of integer channels Ctrl+R Edit color ranges Opens a dialog to edit the channel or channel group color ranges [7]_ Ctrl+G Edit Y axis scaling Opens a dialog to visually edit the Y axis ranges acoording to the expected signal values [7]_ Ctrl+S Save plot channels Save channels from current active subplot in a new MF4 file Ctrl+Shift+S Save all channels Save all channels from all sub-windows in a new MF4 file Shift+C Cascade sub-windows Cascade the sub plots Shift+Alt+F Toggle frames Will toggle the sub plots MDI window frames Shift+L Toggle channel list Will toggle the channel tree for the current opened file Shift+T Tile sub-windows Tiles sub-windows in a grid Shift+V Tile vertically Tiles sub-windows vertically [3]_ Shift+H Tile horizontally Tiles sub-windows horizontally [3]_ Shift+← Shift channels left Shifts the selected channels to the left in the time domain Shift+→ Shift channels right Shifts the selected channels to the right in the time domain Shift+↑ Shift channels up Shifts the selected channels to the up Shift+↓ Shift channels down Shifts the selected channels to the down ============ ====================== ================================================================================================================ Single files ============ The *Single files* page is used to open several files individually for visualization and processing (for example exporting to csv or hdf5). Layout elements --------------- .. image:: images/single_files.png 1. Opened files tabs 2. Channel tree display mode 3. Complete channels tree 4. Command buttons 5. Windows area 6. Numeric window 7. Plot window 8. Tabular window 9. File operations 1. Opened files tabs ^^^^^^^^^^^^^^^^^^^^ In the single files mode, you can open multiple files in parallel. The tab names have the title set to the short file name, and the complete file path can be seen as the tab tool-tip. There is no restriction, so the same file can be opened several times. 2. Channel tree display mode ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The channel tree can be displayed in three ways * as a naturally sorted list * grouped using the internal file structure * only the selected channels 3. Complete channels tree ^^^^^^^^^^^^^^^^^^^^^^^^^ This tree contains all the channels found in the measurement. Double clicking a channel name will display a pop-up window with the channel information (CNBLOCK, CCBLOCK and SIBLOCK/CEBLOCK) .. image:: images/channel_info.png Only the channels that are checked in the channels tree will be selected for plotting when the *Create window* button is pressed. Checking or unchecking channels will not affect the current plot or sub-windows. 4. Command buttons ^^^^^^^^^^^^^^^^^^ From left to right the buttons have the following functionality * **Load configuration**: restores channels tree and all sub-plot windows from a saved configuration file * **Save configuration**: saves all sub-windows (channels, colors, common axis and enable state) and channel tree * **Select all channels**: checks all channels in the channels tree * **Reset selection**: unchecks all channels in the channels tree * **Advanced search & select**: will open an advanced search dialog * the dialog can use wildcard and regex patterns * multiple channels can be selected, and thus checked in the channels tree * in the "Pattern based window" tab the user can define a pattern that will be used to filter out the channels from the measurement file, and as a second filtering step some condition can be used based on the channels values. This information will be saved in the window configuration. The pattern based windows can be easily recognized by the title bar icon * the keyboard shortcut ``Ctrl+F`` can also be used to bring up the search dialog .. image:: images/advanced_search.png * **Create window**: generates a new window (Numeric, Plot, Tabular, GPS, CAN/LIN/FlexRay Bus Trace) based on the current checked channels from the channels tree. If sub-windows are disabled in the settings then the current window is replaced by the new plot. If sub-windows are enabled then a new sub-plot will be added, and the already existing sub-windows will not be affected. The same channel can be used in multiple sub-windows. 5. Windows area ^^^^^^^^^^^^^^^ If sub-windows are enabled then multiple plots can be used. The sub-windows can be re-arranged using drag & drop. 6. Numeric window ^^^^^^^^^^^^^^^^^ Numeric windows can handle a lot more channels than plot windows. You can use a numeric window to see the channel values at certain time stamps, and to search for certain channel values. .. image:: images/numeric.png 1. display area: here we can see the instantaneous signal values. The raw and scaled values are shown for each signal. Double clicking a column header will toggle the sorting on that column. 2. integer format: choose between physical, hex and binary format. 3. float decimals: choose the precision used for float display 4. timestamp selection: use the input box or the slider to adjust the timestamp 5. signal values search mode: choose between raw and scaled signal samples when searching for a certain value 6. signal name pattern: use a wildcard pattern to select the signals that will be used for value searching 7. operator: operator that will be used for the search 8. target value: search target value 9. direction: timebase direction for searching the values Double clicking a row will bring up the range editor for associated signal. .. image:: images/numeric_range_editor.gif 7. Plot window ^^^^^^^^^^^^^^ Plot windows are used to graphically display the channel samples. .. image:: images/plot.png `pyqtgraph` is used for the plots; to get the best performance consider the following tips. * limit the number of channels: plotting hundreds of channels can get really slow * disabling dots will make the plots a lot more responsive The Plot window has three section 1. signal selection tree 2. graphical area 3. signal statistics panel (toggled using the ``M`` keyboard shortcut) Each signal item from the signal selection tree has five elements 1. display enable checkbox 2. color select button 3. channel name and unit label 4. channel value label [4]_ 5. common axis checkbox 6. individual axis checkbox [5]_ The user can also create channel groups in the selection tree. Simple channel groups are only used for grouping signals. Pattern based channel groups can be used to filter signals based on the name or samples values. The selection tree has an extended context menu accessible using the right mouse click. Double clicking an item will open a range editor dialog, similar to the Numeric window range editor. The initial graphics are view will have all the signal homed-in (see the *H* keyboard shortcut). The user is free to use the mouse to interact with the graphics area (zoom, pan). The cursor is toggled using the *C* keyboard shortcut, and with it the channel values will be displayed for each item in the *Selected channels list*. The cursor can also be invoked by clicking the plot area. Using the *R* keyboard shortcut will toggle the range, and with it the channel values will be displayed for each item in the *Selected channels list*. When the range is enabled, using the *H* keyboard shortcut will not home to the whole time range, but instead will use the range time interval. The *Ctrl+H*, *Ctrl+B* and *Ctrl+P* keyboard shortcuts will * change the axis values for integer channels to hex, bin or physical mode * change the channel value display mode for each integer channel item in the *Signal selection tree* The *Alt+R* and *Alt+S* keyboard shortcuts will switch between the raw and scaled signal samples. Each vertical axis width can be modified using the + and - buttons. .. image:: images/plot.gif You can insert new computed channels by pressing the *insert* key. This will allow either to compute basic operations using the plot channels, to apply a function on one of the plot channels, or to specify a simple expression than uses multiple signals from the Plot window. .. image:: images/compute_channel_dialog.png The currently active plot's channels can be saved to a new file by pressing *Ctrl+S*. The channels from all sub-windows can be saved to a new file by pressing *Ctrl+Shift+S*. The sub-windows can be tiled as a grid, vertically or horizontally (see the keyboard shortcuts). 8. Tabular window ^^^^^^^^^^^^^^^^^ The tabular window is very similar to an Excel/CSV sheet. The most powerful feature of this window is that multiple filters can be defined for the signals values. .. image:: images/tabular1.png .. image:: images/tabular2.png The tabular window has the following elements: 1. display area: here we can see the signal values. The raw and scaled values are shown for each signal. Right clicking a column header will show a pop-up window for controlling the sorting, defining signal ranges and adjusting the columns width. 2. integer format: choose between physical, hex and binary format. 3. float decimals: choose the precision used for float display 4. timestamp format: use the input box or the slider to adjust the timestamp display as float value or as datetime value 5. remove prefix: remove column names prefix; avoids unnecessary large column widths 6. toggle filters view: toggle the visibility of the filters (better vertical space if filters are not used) 7. filter enable 8. filter logical relation 9. filtering signal 10. filter operator 11. target value for filtering 12. apply filters: the actual filtering is done only after pressing the button. The user can modify the existing filters without changing the tabular view. 13. query: the Tabular window used a pandas dataframe as backend. The filtering is done by performing a query on the dataframe. 9. File operations ^^^^^^^^^^^^^^^^^^ There are five aspects related to the measurement file that can be accessed using the tabs: 1. channels: here the user can visualize the signals using the available window types 2. modify & export: this tab contains the tools needed for processing the measurement file. The use can filter signals, cut and resample the measurement, or export it to other file formats. 3. bus logging: this tab is only visible for the measurements that contain CAN or LIN bus logging. The user can decode the raw bus logging using database files (.dbc, .ldf, .arxml) 4. attachments: this tab is only visible if the measurement contains attachments. The user can extract the attachment and save it to a new file. 5. info: this tab contains an overview of the measurement file content (channel groups, file header comments, total number of channels) 10. CAN/LIN/FlexRay Bus Trace ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This window types can only be created by pressing the ``Create window`` button. If the measurement does not contain bus logging of the selected kind, then no window will be generated. The filtering and signal ranges definition is done similar to the Tabular window. 11. Drag & Drop ^^^^^^^^^^^^^^^ Channels can be dragged and dropped between sub-windows for easier configuration. Drag and drop in the free MDI can be used to create new windows. .. image:: images/drag_and_drop.gif Batch processing ================ The *Batch processing* view is used to concatenate or stack multiple files, or to perform the same processing steps on multiple files. Keep in mind that the order of the input files is always preserved, only the samples timestamps are influenced by the ``Sync using measurements timestamps`` checkbox. .. image:: images/multiple_files.png #. file list #. file list sorting buttons #. batch operations a. concatenate requires input files with matching internal structure (same number of channel groups and the same set of channels in each n-th group). Each signal in the output file will be the result of concatenation of the samples from the input files b. modify & export: similar to the single files view c. stack will create a single measurement that will contain all the channel groups from the input files. Identically named channels will not be concatenated, they will just appear multiple times in the output file d. bus logging: similar to the single files view The files list can be rearranged in the list (1) by drag and dropping lines. Unwanted files can be deleted by selecting them and pressing the *DEL* key. The files order is considered from top to bottom. Comparison ========== Use *CTRL+F* to search channels from all the opened files. The channel names are prefixed with the measurement index. .. rubric:: Footnotes .. [1] If the cursor is present then zooming will center on it. .. [2] Clicking the plot will move the left margin of the region. Pressing CTRL while clicking the plot will move the right margin of the region. .. [3] New in *asammdf 5.7.0* .. [4] the value is only displayed if the cursor or range are active. For the cursor is will show the current value, and for the range it will show the value delta between the range start and stop timestamps .. [5] New in *asammdf 5.7.0* .. [6] New in *asammdf 5.20.0* .. [7] New in *asammdf 7.1.0* asammdf-8.5.1/doc/images/000077500000000000000000000000001502633300400151435ustar00rootroot00000000000000asammdf-8.5.1/doc/images/advanced_search.png000066400000000000000000001206271502633300400207530ustar00rootroot00000000000000PNG  IHDRRmsRGBgAMA a pHYsod,IDATx^t]} o$m)$5yk QGO?MA#OM?yxa%Ar/5HMX7]γHY^lC B4uQ8-濛_z7{f=3{ǖgy%gf7̜3g\s5oEO~+B$ްv.r6]V`ڙ|.>g/ 7wсuMkk1|UyD5<d0-o+>*QU'~_y䏾OW?o&?~ߟ:~smCBtɥBbVaڶ',zus/nh.Q-=y PɢJe~+ͬ)n;;vشic=v5׈sV*F~Ɵٺo\8+o\?xςߺ~?ƿYQ&=9v7݇jw+CAJnj´l70R}rH@tnۖJ mKʆᮦ澱Nf9>:PmbPiJbpb-Fq|=vmtUut 0aj֭D'CW?:~귗'~Ӊ_ z\{k1篾yћj/"1jZLN4qi5~rpS(bƦ4]…I<39 &fhGׁ+CA=⢦IW![v =u;렑v̙3לS%kj2Z^}S??y}qW~??~O?z2pК}=ÙN1RboX_]4De {ۃ LȉW1R*rA`144TS5UQ1=UjALi&xwߜ}9wۋU?_/Zo|_/d\b3/gLhOM]!HO)!2 4jm.G}|GW48)]=+KfO'mNA`Z2<<<>~~┹Q=iUEoW*Wɠ7~X7RUնbX_ ֮\J]7,6L m^S/THSh^U~L,BƷ˽-Tgxaeˈ,۹q#I#JL,v3e sN^Ξc hN`}'+[g۸3!fBg÷~~zwluK۟}4X"g6=QEf-tv5 S߷DhֶK"{+?b!O<7W>]q_:z2牱v@=_L*J8+Ŗ])Ԏ/rĉmKE.`qeu]e3C<%k'^HR1څ⛯N =yr yRQL8`C&u@əg.xpCM`߭о݆S _|Cøg|&29fq4E|Meǎ"СCk֬ {]rٳgE\tEH&i :˖-  t!,`撏Ϟ=[UU%>@}9䦫^~PZ@"3|3?O~" aQ(D.4<禫f**|*|ȇ%jY䭫V +٫oa I V̦xW(Eeɇޠ~b U}G76?^*msNڂ;Ż2V8ZcLYNJG{Wqx|3G%6k;;V~UY@R;X[z:7ˣD͘Lp?f;"$Rdfbi%X6g6W+~4Ls*1_u.Z3Omj^H_;?;usmÆ݅nY#P1_+&QY?!>5xC'qs_iSXN* GǘTj<ݽA)+3%AX21 >^.ȒG=42֋ݑbٗe*Peu $E./I%#KJ+*-ʬO}o? SZ3@e\d튇Ft0RSW`DU׆{ڤLއF)=09jxOs=VӚk=w?3b'i9+&F\UxƲZHZ+ K5ЊPwR hU0+J_MsÕw| vbm-X櫮*_{;,~6C Fş U*fX[wZᇾDg..LZZZv!R:fw޵k׊ؽ{w7 L[YlH8:  Ux;+p/ ']u 0x饗H %}댑?vq pw0QpB }* ~pN*|*|ҥK+_V䔹AO5LX|r&oI G_[LTUw"C\o\0YTMP7VR}LK93m@gim>絣`W6::{{8Hn_l ڶɂF_{mX@Q(`l mfY6 GӒ\F#09?_O&BUNiQV{ .1P)]5>;X޾6=(?5VQXr xNeii}C[aHPzxeaY\q״n/VQLc}=1n+g$ U~ZdeP?凿 ο=ˡӿi3|G 5(%>GKt.Y}TfmC%}s!*eiZ\p ^dY/fHqz?N֣Sž. nMI0N_Z%[/gr~ J3}2(LWK{) *A培Z[6l aOyUfv|,m*yi9FMUU_5y We ?jwǶ~D_{lr>{bPIZ9$ai)0]#xO/_?sG, L|G;Jy3\ ),U}TyYp[쏡p7s2z00j(+%_vf-VH2n˜_W 4srWYxG>s8>tMm71Y4ƿo%V?2D3wB2EsK>sD%tPZm Hw[Ӻ]|2-|05O`)[gE(Y^EԽ  JO}iҙ"dPY'P 9$݄B"20iV"G +|GIUwTQFtK%MH)>/?6I]|M=6~eiNE:{;gWKV8Y≆-Dm+D)֛zD2GnD"r0i?0)I4((6WO>/ՋuꯂЁYnL'hgvF BaCyOn^kwKnv"Klԏǩe[u:$>3N7X/e(;JrOJ(2\EOYMu>ߥ꣋3o쭋>%[ΊQtp? `Z_αc^|xI" %m}Ė(& 3](??x"˿p/Q@"ɒ,w;,IT$~*,3༐:  lbdd*!jTUUw/hegmXU0qEUkͺx͢o?u@L`L71qyAoY~[T* pY\Go`J$8ocՍs\SZȽ^z%K ;oқwIun/aʨc03='c{87n/"jcܔja9T"fM9d¥$XUfaˌ9C *DxqDl>7]玊,°<I 'y׺'Dojo 3ܺK/aʨc_{bU+cԐf?2f9ZY )= nF$j4bf:Uwn=qbkY[;9>L+ӒX$sюA2uŋ^95x.+{:uf8H'}ޠQY] aJ=DeϜyQ0P6:ib,31hZH \rJ{Su!qAU]wn}$ n9/֍0lZŦdα/ߝ8*:|>3ٿ-^p=w>rsLD=Q/vxwpWd_|gBWQQOw(:ĐR(Kabɯ.Sُ *N?Tв~}Ks2~upyype44syi9AM]z3+I4\"QT(Kg?C_'R`S]i \S {-D"^-bA*s2z05Ч{t+n'jC[$;2f @JrexGҍ)|]) L;<ᖳecx*:iͨιׯzLm[{"!)ܖu UGZil=:il{^nMJ/j[z#wg]uOb}{&+j7#e)oz>ֹ"*h۸{Q`m.Ӓ⧞;nyvJ"vՓUOO[q 4{6f03PY'iUv 9W$)Jcؿ=$n-9bs%yaWhMIuVIN*§bI4kjB-IعCfwGMz%\cS FterN(ZXpYFrCq~:f;;w^I<,J)hJ#.hSzd^L쑴ls9jhOpMK4;p(_^%a^~p .ˈ}d~:hƈ]^I<,o(R<ј8PB*8so}D$ J [S?|f}c]Cnu^~0_WQ09Xhطgs&^yṯ֌v:?1>lhTp? ,ʼ܀~@$'On*W30KX|_ ]Tfpu@@Y\(˗/ 08x UPA]u^ aXrDY:fgֹmH+mw'dc,}{m%ϡq݄H70" QD|E"Bbo.Q6WVUIun/aʨc0KԣR SJw 8+w[GiZ1cY4ad30RMD*0< 'm̓ *C?>qB1jMKbɒd-^𳴶N}ѫ3gexe8s_Gor8H{:Kjw}c܆U*]Rҭ+l\ǩ*,N[>SUo4⚂p;XI MK93m@gimn0wrr{0 }cΡΞG᥊}A6YZk/ Zh"*;9٭EEDoh &JFdݵz8C4wy{ha,%q; .X*Npw~5:H|޺u2`[,9 #vttD /KKwnhاIL2,"c;q̫m)B0uGhT.%wSQ@4t] `m{`"ִo ="xB<2ɰ, FNfaPSWKմnfD) &vz:Ģ6Mq0 eŁa,%` E *xa<~k, 6K "l<ر"!kN ,C !!$MYQG.Gˢ]J閭Lz\w@ .6,Ą͒S߾Yz9׾JxY:WC+,K?" Ghʊjbnig7/ T[{JT2&YdnY8㨌QEz~hnD񱴵/ͫ8NKy3+$yWхx\<5~tŵA"QT(KȽ3 <`kª/9v-CXZ*3;>՜G48-ڨڛGjZI4,koޒY:>0*wy8z %KOӌT *-tR*Rn!mI4 U`~փWےoc'E=&6[S!mQ;ӒO ۵E,e묈]dy~o[o?9 |ӴVι1;@T7H>K:saOOgUFwr6NyO?ߺ+a;d~:f(R$?3xXj[R<ѰH q,ZW$ J Wm7#繕V`/?о5?S2Q'ಌk`MmƢ,Ku*٣v^I<,[ᤍ򹦮m" `nR>NsaUj;skW4[Y ?4qi_L23ah*a`(r^U5ѰoϺyNKK:g:|K/P6\'zj^TKZ1D - >s&^yt<Ί >{ faP-U`xANښqs>{L$B^ܜwU;*&Q6&X7]I5̬s.+ND$QJZJoyuzºcԜf?[49noohF',YKtݮѡB`_1 MKbɒd)^𳴶NQwѫ3gexe8Is_Goa1d):UJSԭ1ōr igݜeSw8:**̣ 5aqjVy\!:*+g)I&v޹q(jN`'~X7iI9Ǿ|g^~Y m ʆ_uc"2YWx>Yǿ8_nn}gT]+ cUPpffeN2Sv`QYMf1UFKzO$>o:-xΑgz;::D";7u4TW&t͉: 6Bv8;DR~*ĸ`(|\.fsg)g;ocue89T'>Wշ&cŒ>³lsH𲴴㛻TW&޸1g \c×zCWx[57ȅʫoݸqh[_ڸg|m[t="Lt7̛/͒3&BpfH4[g-;LqzeeiVGhʊjb ̎ {8&Zt3M*UDg)ͯnz n EߡD͒s7.HΦ(Rq,'<=tR{vzeeD^ӪKC$ ʡY%|RnS 8W7Ԕ5ӞTFW &KN1v#`28f7UZ%-1['<$¡ے_NLi8^-!ަjۭItd.MT zKg鸒ZNKZ;r#.f![Kx\U9u1-5@;]=so{"y#čےݯ|}k'ԉe`ttܖ|ыM۟ZQz -3F@tu"G }U_$U. &~km]sf9U,EA"B[~y^%:nyvJ"vՓUOOY|}] PP䛦}rέq&>X=d̓])BP5VgIG{.쩰WI AƇ!#gY|]S5%YY&9#˫ LW7WĩW ߴ!Df`s'<=dt9NtQ# 9qd nI&,#cA~:g;NI~fz%n6y )1Hv\Ƚ:;skW4[YpihްgžT̅vt$Fؿc]r 7H{'ﺹK )gYS;QsW]^I<,oݸOsk>5Ƥ|!Q2Rh}ԈZ=<nRlf=vgi}UN%r w:FǦ*]?t(m3a݄cSP/_.`pAL#򡂺'6Gۋco||zֹmH+ 6ûD=*i)0GbvwqCX+Paf+5rMrΧ@ wUUu De0,]lZ?.KW6$^Q'faxG%-qVrˈZ|nsb*3u*lȎn"$c*xĒ%:RgimW7gl ʆq`辒oT-*ŏR'67M:us}m[+EUtrTt~ỶQf.L,S<祑R3޿esdK8Ym `c'U5-d2u`W6::{bj"Yjo*mdqjX6jidwQ0P6CZMe٨Zv4-e<HR4]~~W['cŒ9LoGGH𲴴~z禎} $Ò91Qچ?WSH6&3+pQu[oGtx'žv P>・k݃24ׄkZ[eXr xNeii}C[aHS!^dXWu#'30+jZ7w1basC{)bUP> @:U\l0/PN\}+I6K)+D*:krL+,KPv/H CJT3W'wL>[`3K5Ӟ蒚%Z e cmC2R,9 ɩU"l<йJN ,kf/$ )+T` +& rxAet\lg *Y6{bPI* *Mې|mI4 -eY&[wttܖ|fjs>mkjSt&QoIm m{ϬG[,!<SC6H$Dw[vgl=ttܖ|QZ4VEM-s ProJt,WV'){<ȤɍEAB[0gZI#ڎj%XY*§yWACmBdo`ڧr7S$Zqfjtr|h۸mڢu, k<;%XY*§&f?9|D Vι΀Ѯ )V9'T@Wn}~DNh)/U.LC )gYS^5w8s'ÒnR>ϫmz43)9DBFԅp0wQGƒ&x:(B:e_kj 'YfTG]1L$&%sM]!Eܕ|: wն6ljO<_W؈9XKNKK:2VB-yL X_zF"?P aMt@4+$_Teqb79ZXrxӺi g|H9>wTdMlL!KW?~kY=]z WF/\Ib5*uǨ9͒tȪ _lh:$.:ΏbD1gMh߉]TLWA,E T5-%K9tx:iEn sϜ< }RtnC%nl|u4~Ϻ9!)+} 4cejѴ$0w΍O{n\~Ӓ(6%s}ni~)-~<< s#7;"YWx>Yǿ8_nn}gT]+ (.{ͲlT?j(Ѵ$dD> /1?e),'Oti8oz.ӯFG[N~%!sގb;;7u4TW&tK̉: 6B0uG7t4yN&4)3&?X}.E&N5ՉªoM~%gA}KGg< G%Aiud@);0Q^{/A6U<0oOR0[6KS5+D*:krL+,KPv/H ESVT3Wݩ`=^~=|s n qŞ.}UYrɩE*đ\jN ,kZu}bP4eE5~}iɱTXNf^hu  dS]%(Q {IZ[K&eB2+3;>]Wyi)gyf~iK`ѝKԅ0]&+IY0Xxa;z-6,C/ 2cik]I$H*r3o8O"KP<6 PiXumJ^|uݟZ )<:u2p~17̀AEtm(FsIL# 7$׋0?dےo?Zk3ߪ&ؑHW%Q:U++w=M#3s_3'C"\->.Q>ֵi2z0dגےZk3u^buK|~QxUv}{S0V)թQ)PT;-PUm\M, b޺BodZ(sG"N uVĮz驹Ii%qzDPPL&RrM&vvMHma<87жo}wS}KCGHiɧ"^;>USl/eyQ;*&8JP_PLkj7F('&<=dkr6_'a< J:Y$Ӏa1TEr6GvJA!d2 'YfTW]1NI~fz%6))6D[HtS'#.hSp^L@{M_ɏ߱p.9LpYF̽w%g&O,֩ȝ'?3xXVߺQ.)ߵYlg>XІ3L$zR{] lͽmK+7LL{Xq|t uvYql%1x(SXDhLyW՜Eþ=9-u.[I4Z(bu饛jڅ4VؤD? DMO䍬S-Kؖʼn&(k~e xNys8G)&n^핯M<[:-uMwv:W$SH4Z =ǜ׺'>$:?0rg=t׳f%JO?~/G7D ُLW*p~5:B|޺u2[,9 #vttD /KKwnhاL2, cu̫mK3̅p`r1@ohR SM+xRg< G%Aiud@);0JTAGE(imb)9?;0eii}C[aHS!^dX2̨ài#b&3}k7tiڰ{DŽUMUL`)FdHbB] *n7' =- %gMڕT eiZ  8n BBєrw*Ǟ[Ѯ"?* JS'~/4\O:i.,*D; z9]\--CXp_񱴵$yi)ohyf_DZDwNPNS*+IY0JPr:{8@d?eʁS9"dbݵUeB2|*3;>UMU@5UUU悙, N,kmdsƿ1T+fLݶE7װkI6vdʲ)۫(*UIO ařR:{0|m @6YWAEѴ h.)\C"*-bXH\L8f-ҽq[BVr_Xmw5ƶ5@'^esƿqT+flpeɢ#I P`P ]EȢ u="an nhtO)^A4sx,zV=Y?mYo"/:Zو7/ZeA!;EnT͏8-u}r w:F<)0jCPS<$'#[ jjdvڱeqb$™]^{#a~̾HNSz`(m6 ( ~@H4upA0{*(*img<]*(BYfQH: 4 *h3pbp?8aҏ9U"x WS6ûD=*i)0GbvwqhVA,[L,ݗXc KZ aTc"mjޓ'c"漫QE`6A0ĺ9ZHr-]af[w%l^ur r%zTR|ӫօ4K'b3jXUԾsعex%L,\F q(ɲ&!J]qP;:cY$] w?iI,Y̡c~)/zuS{ l8V;#K)PT@z7]:us}g۪5OUZ:Չ=GS]Zб(!Nd#X@"ȽP⥇`2w΍ľo~ߋu*D)sw[gim>3ٿ-^p=w>r#Z^~__|u FiwFe?qߵLs[sNԊ]\>qaOꂻk쬽N q(+О:SX{OΌ/Jt}_n KNCCN>9aw?P͹q| L}2s YJsgN!y}"<9Q`_I6¤:krL+,KG{A"@H(X bqXwIv̿s\؉HW68nן\;"YTWa%o\QxYOyzΥ` ˒Uח*H ESVT3ח6.]ߞ*1g8U(7xڰRxSӗ;gͥ`@&(c2r@Yw=U"dm)$Zر[0)$ç2ciku[WqgVd.iR>NJRZ c.ٜc_mne<^Ny* ϋpibm2d 2*3;>lA48-rqu'߳5CmjZcQ`ZipȳSl,"|zjn17_Ři6!7M}0aU$O>Ҽv;`p6>#m96mCw_f1 ӒOw4}$K:+b_W*§bwTDM1qꕠ&ȷµ7n$T9tlt+;L$#3x8F\R>Ns4gG_XLЭ^ݫa9L:5Q +vvgnP@hHK|J;pG_%'`^~p .ˈ}䜁"cr"l>O0q3+eynM]F㣏u m19DL!e3 -ݯGT:65={|v^'3IH% dןeG,YIt|w}\_WQȎE-9AXiطg0;9zKM1q3ok|MY|WWw:i o#'tKuyONH\"]t{7tC̱z֌vR/&g w_4|xͰ թG~Q_yLl9֏%샐UAg)F'Xý󮏾(Ǥ( ~@Pi|q ȋcIÁ/|.. Wyhk7CN<`<P/_.`pAL#򡂺'6Gۋco||zֹmH+ 6ûD=*i)0GbvwqhVA,[L,ݗXc KsK*ML9֢˘e66zD&[8*м_Y61T*C?l}ůS$,IЩe ?Kku)=sfk\W6c7ujg!KNT7nz7M:usmg۪5OyZ:=GS=jn_C"M@7)#a7%66\xړRǙBeY5 R_?~~W#['cŒ9LoGGH𲴴~z禎} $Ò .y a)~8L.fA>NMK|҇ ?~t97dRf~D8>K3I8U<0oâBtfə~vao8UBxYmp^dY{APH(Yz]sƿSE'"mSa +ks)? p}geP]%Q8j|肒hnŽ̎u5[ ͫ8NKy3+24dAt'd _)~1l1jҌI,R5%`﬽9'D)RHf'}iݕ+8Up%1'<$ےh\/82W,'^-3;iߪEAkTL3}Z4cGDa@)2Wgmͥa|$Lu{0, mykEA"[xy^%eO=w$ܮ-`)[gE*˫[_ Nj|VOĜc:}!ͫmv{L $!@&Ap/4`?Kq[+_vI CN(BLpYF5r@19eiNE:zy;w^I<,/gm5m0ǩc3 k)ի{U:65ܻ!ZM!ќIG"(9!,8gJLgJS/_WQ09AX˟Niâ;tKu 'V^)?&/(2{x4߶Y}xdeqb$™=^{aw:uq}/\X?~ϗBVI,߾@3kk(%e3\{*{@08?+Jetp(Nm)`<`: =z L/򡂺jkX$B(+$ae`eUq[Z!6:96ûD=*i)0tp̎ElCxY*‰Ff -)D%c8zFJVlZDJRQE8U[F:;GDq `(j1VRӒhnN ok/cYZ['MU;9̝ fxes?tRc}#T/h&SK}b7aUKWDe''f\l=6tXo6FT?ThWr/ >8UQ{:Wq'ڢ@t`m{`<"jմpb i"x<2ɰd99QAM]!,UӺGDo& qdZOeRuf sDc}=]*zMVUE2U<,YEߜYr7S5D*:ky@IWY,7EBBє%zx,[O{g%+U:' YU\TFWRyݓckw-C!M񱴵fyi9FMUU_\[JCj 4/YC}iJܱz*iÒU/óT`6sw*E"Jŝ0DsIL#x$b)s2zHJm7Дmߢmy&ؖdh S=>!#j C*Si^_*ԠJI;.ѢpaQ ]EmAB[Դnz#ӒǴaJ"vՓUOO=H5uPKh M}LX9Jţw!I˽Dˀ1&v\dOGK)G~>@EjB!'mI2eM{:QsW~3+I\SWzQ6M)9Dޕ:MM="Y>]4d_HXE-G>UtŝBźQG>_rZ}6QgYnG BSfJ.@?x DMM#}c^;V¶,N7gջR[SQoҝAN(4 8U- g^W1Y,7bd,?VG/HBi MkQI*Q1]Ewvꇍ3 OH`Z:XQgim4U0wrr{0 ȡΞ#d):UJï=)R_{QnZ4md,[O (7:)~BI:j`u]j mPjpqTca [;~8gp-JN8TJWӵ!52X,9B޿0$L2, R+"2uG'>SYrGO:ԛ:*d꣧3V!4iMLM&*"DtKjjj"hПl͒S߾Y7Y%Rq,Y΋E^dYs{AWH(}kcb~7{HU2VOttOB-8OTFW#J4|'n¤F̎u%xi^qZʋJJ. !K5x\mlg _)F/EdJ{$eE0Ue+<&kħT(ACVӢpR!# ڢMMpnK.2W,sW:nKĥhXm2ƶ5@&Cë B]V1y^ Q9ħUJip)}8sF%tmWJ׶  my< Ql,"|zjn/)f6(%T &|D&KI](Dcbd1O35&OTb3*Ot(Rs 9i3/E< .&W?Gϲ4["=j1O~fz%Զ )k V/ )1ӻZⱩG$'QaSmX%Ȭ๜' ']E!#&nCnT}Η:fMYF(^BB sjԏci2&O*uu@c}PiZZZv!R:fq˗`6qkVLaY.]T;; ӿݻl2pp=T`&0?Hq]a&&άsZVttOB-TFWLC|y(;n¤ N̎u%xi^qZ;FJ!K5v\lg ߊn5/Edn=dF_l/e óT` QiȪrZ~U*1D[i=nmIŚQ euGJmɷ”2mߢm^&ؖ6doFa Kڊ[2B1բ9*ԠJI;.Ѣ#pm/ڶ -JL9v e_kj+_gYS5w'?3xXj5uh[s۔qCW\365$ ڶuD x<_HXEHU>8䯫(č(֍?ŽRלZ#hgv7WUmjƁ4VZ j "1 ݽvmYo"w?s(cIgZdT(>ETԏZi2ُ&uxu@b}pjiiٱcH98tК5kDÇ/_.UW]u%'N,]Td[H_P{]lH8{*{@0+L71*B+.ۺTA?is t@>@Wt@>TPWnho ÒW?0tmC%l^n0KԣR SJw 8+wZJ9$KijusUoŵrxbcP"ft;7bd,?VG/HBi MkQI*l~TLWǝaLЩF;ݴ$9tDx:ia`0+)CiRt_O&=)^N8m3Yn=%^19=ӜiOB[&7T(G9c.tQvpt[_|qt8]ޮ_0;>]*-B!CS$bxYZZVҢW&tMxo)RsB\̺#Г U6n\C3Əށ(9O:<5Ikhr-(e/%554O6KN}fn^#}H4[g-;qzeeiQ!hʊjB!M<|N9^'LV{MYC$ 3a9)ݓPʦ2J|}rLlc2I!WK[KҼ㴔W_\ICj nJRZ]rb_YoF{",i^ )TmZ?n!U9=57 |tV %ZBJV0n&FvJQe4#\#|=aOS|P UHUϐ6R`P"ಌk`MmotEg,Ku*٣gWKm򹦮mPinR>Ns8>jkƦTc9Uۖn(^>eBfEPs$=/$O'3O@cFNF_|aiSlkNDni3Yli 6Kn 5Y@r+yL,5QQ^;V¶,N7g;̟x`9ȱ3-2H/nK>96)#|SUv?,jiiٱcH98tК5kDÇ/_.UW]u%'N,]Td[H_P{]lH8?]pHP'[1%]\ő]G$[1?ȁ9s@W&*|ݷ%3v4~ojۆKؼ2faxG%-qVrh33,LglUeןhBYRnjX] #Q ^H$U8Ft]٩6 "?iI47'stC2uT`W6)3T-*RPK}EyShB;.4-sbϨ*jrD##c" gǧڢ Jq{]v|4:ĻU%PP4^7I%]A^[ 5u?6\m&$gzzSMV`tyj d`.L*xYRS71O<ΰYr7kWS5D*:ky+,Kd{A[H(Y|>[gUO7#+{+" *qx@bN{rlnD#Zޱ[0)$2ciku ^WqRO1:~~Pv~$g@s8Ufg֟0M[sh *q˜%1p ^#"ے({W2W,ttܖ|L+Yц-fgmkjNfo] ?9kRik7P8YljϣES.l*h۸Km Hh ~?.˴lG,e묈]dySsWsM~0A.(M}LX9Jţwu8G" {Sae;Ny 'ɎHԨ&e_kj3k,Ku*٣gWKVK\SWzQ|67*)9DޥN6vkxn^P$OLwUqbAf'(F՟5NKb{_&,KuHS_U!XRtO ,^} iA?u DMM#}cx^;V¶,N7gջ֩@#i>ԏciKTPq KiNUKKˎ;DC֬Y#6>|r&K.Dm8qbҥ"܂(@:LڻweD_@@ fOitp!!mu*J?ec;U]UPA]E[~ 7 Kngl_i : ye92.QJZJ%L)5jf,+gY Zʮ_c9ZZ1Ob,)7Ň(ˏ0PZXUtqg~60MPx%ܜ̡#~ISՎns''^p/NiwEOj(UuJWh6Zیk2|'S҇+ͦeNst$kW=&gV 0{8k8Go-JN8oTJWӅj"k4:dU%PP ^7hI%]A[ 5u?^\&$gzzSMV`~ֻoҸl :<5^2ѫ`-U`*ik3, Z1~Y}*F/N8oTDW` m@F%QlKB+`~]q9+%R"TWf~Odc[g&gFu*@.șϮ_•Ub-˥(32O shF%tmWD׶  mA{c€i0_K%XY*§ff`A6(%&|5D&K#9iػZ|XL fiFFyy=OZ~>$UF0pH&,#XSgYS5w'?3xXj5uhVsqC]Z$ llG뾆W(kjQIzXY wնedVH_tT8Gy=OZ> * +u/iSlkN䬑ni3Y,i 6Kn 5@r+HH Z j/ݽvmYo"wS ^GZzKYa Yљ*?[屴!J::X:GT;vCYF$l>|x"M ^uU\rH89qҥKEֹQt<we˖Oӕ= ǏKs"+䔙 Ul2JZQ[.݈j!L ɰXZw]RU]dV d Ԏm}&E6Ys8!]Jbl,!7Y FebT9@WCuMlލ0,_oiuyi #^6ûD=*i)0tp̎E%t$$^a2GsP{2;Ӈ: bC#֊hnI)>DX~.^Ҳ*"#TT@yTLWǝa,d6Cޱܴ$9t8x:Ea`0+C=ڡYRtAN =)^]o2MMkl5dtDdC$:|SxU5 wLBOai 2!=4T+CZMnG9D/OKа>>z5%C `*TJWh"k4:U~[,9B>g~>6٨rc_ Z$\| Oʳ,֩Hgb^I<,m?g ^$9ч"mp$>]p)r!#6zS"QgU]mܫ1=xʾ3OxXźQ76ݗREҜtKu͢HS_U!XRtOi,^rAƶ: ~:nmYo"OBqg5.a4w(^SP %IX3JZR?/2tO٧;>Y:GPҲcrpС5kֈÇ/_\$K.ig9'NXt:; ӿݻl2pO23 e.M\8p1mt( yBoRyi/ Ξ= ]o+h nbm+7a=zz[I+^MZ4.Dߥi%xJ5n <\Abed3",[QIiQ~ tp̎^FЪsS rxӺ;s $x[R1]EwvꇍEqOPeZ:P)O&h+~)¿ x/c֮8@!Ca ~s:):}HI@&-F>c*?Ō1IۤYu?1i Cfn NNt8ݺl&FkZ[eXr xNڎ,iE|ݫDth9Bgk7[nJeC[aHSuNJtGKjjf""11]Yr7ks-Lx]hWBY^aZ'~f6QӺ} +iR9S7s0Ͷi8!eH ^Gh7yz+YOetG< jª{rln>#Z[0!&R-z#/ٿʺF` pP. KBo3;.T,jfa/TKPV+}+ Ң9Eh. ݖDKcS^h=,Y$+MM8LӐh\2P{&8׮n5~E5P6$deZyau?}MЉNˬ^$۶1UjmNB5u4:kY)LX9炦JJuHZZ6[  TDW!9@~%(6RuYFŤ69mr]Mx[f" (1+7Bюq.%pWm[q )P}QjH*It-S {cSHƪGNu_WQԡ?Ō1IHYuri Cfn NNt[]v|4:UQ%P ɣ U"^ء ^FN  7A!GK7s;%5u_hS!Fㇳ׊0޿0:'6駟o,Bǣ%55:"_Na%}vwn8ᥖo" ;aDM7I=#纗5ṉ6rᄄ)+ @xNN8za$( ,7Xg=J$87qDfU"( IqIJRc DUf9DeZ/t'WYH e_\޸ˀC%/]r}9!u'eQ3 {YZr XAV5XUFEt)"E',wH$J\ MXBoqd w5%I"(kԄӪ΁QOG>-4黶L)I:굫[G?+TD`R ]ŢIm2_2-<0_*sDžNˬ^$۶1UjmNBUTdj[OFfM0a *)!i鸺:l}`%>V*DtmZb#[e_LjjcHՄev/R|#+[ wն:n4J>/JCM]!Gܕ$lbkp}dc#'P~XuţX8źQa@kR,*6K^$azAVzR(tB8~mUc3)WSiQ:Gkӂ bcleǎ"СCk֬ ^|Hh+x4LoQa2ѣK.-; 09x`޽{-[&>U$pb5w@>A k7!  >_m6_%^8_%^\U30*|*|wΜ9Hg"|;/첅 4 3K 1szwy{Dzo}MozSPicbu9 LΒ{ޟg"̞2B GWG?wft4LfUp V!} o]5 Py7At{ ܚMhDW+,@tx!ш옯_rPy7)|{5jȪYt{ ܚfgsؼpL?]{='2˅* I)|{B͞d,=mn17yc6cv6VB.<Ԏ޲<8iʩ=MS"#OJVU z"+KcYSZ EHr<Py7#@M? IS!ID&Gt{ rCfm.ۻ<V`bdSυiVeEV'HCtl:C k牔b𫐁d0anyjկ>>UݻGvÁۣ dfذ0lm`w/d]Ly\>Fi#Xg-9y QY- vE p?x:+}ddO:y)ʹ e-=?o4!x{reS>Ʃ|9,RСWpwˆw@|D`Em_~.cffkRYbNO#[.h>TͺՓ$X 5s"X1ʱW_xV 3x+nȲ/*\uf@tUյ RF-'~AضTft[X# aG|ZlYEғ#ݟwJx#A倦m\@X Ÿ&;ȟ]Y]lx~ +|2ljuʹjmA{==u,HSCOGS$) 9A|D2Z+G02s\Wm)M(p|_O.oAh?4r` OaӺr1ܛ:3 7]A#_|C u|a)oDo^=7>! \~Z%(~[x|k`d8Quͤl-_X'רD9&d/g!qE'Z(3G yKx^ްADW󠪥eǎ"СCk֬ {]rٳgEzrE8p }4 .!- XlH8>6/ DT;kݞ6fe]U2*5nOW]~gϞPXY7YgETY\BaAp骗_~9  fibܧ@>w~ӟ'?tFPif6bsU3s{@Yt@>@Wt@>@Wt@>@Wt@>@Wt@>@Wt@>@Wt@>@Wt@>@Wt@>@Wt@>@Wt@>@Wt@>@Wt@>@WCUKKˎ;DC+Yɲe+Ǽts `VUo|^{o[_]\|C]US)*F do3U d t@ɨ?]u@`.a`*U? ?@J@-`=6+0u ȵ%IENDB`asammdf-8.5.1/doc/images/channel_info.png000066400000000000000000001455021502633300400203030ustar00rootroot00000000000000PNG  IHDR-=tsRGBgAMA a pHYsttfxIDATx^}l3[~ysm[{mێcJmzFC%zY^]^ڻlB vc1X:?d%0b; ҆NL@Ll6&r?dc[HnUV*To*O7::";T: 3~*}g7߈__wB+?G]_Lb:V|JgΟ7_/_)~mojvfet?o剈ŋC[򗿬_?ոsmM/~:[?_ w_Zw^|Xm×GE˯G2qYsU?+rX,q8,,:q8 g~g;&a+'w_?yr^oz7?}7O#{B$cWOί?_菟>~uϾ??o}۟ qlſhI?/?v~p?|7}rN_?'^x~'|xR??w?|'6]O/~ӵ=?w?G`5~WOk_Ļ/~vW?OOu_}ï}C,#/|*`dMq<+bF??6}/_D?wf8׿"8o&qv>xSRϾ1&~ŋ7fq~Z} OI5kUlHBQc ~(Dz\q8Yn*x=# C{TΡM j]`፲=/1؆ʷF?? x2q]MنNӆחVԂ㱮8 NǑLԸ۳"QId0Sow{,ޟ~]N>7Iw|ƻ/d7o$Ow~{Co~rnc_Zֵ4K_¯~sfaXG%|DpU>~4rT?#;>/Vß&/~[58ܮI~,z8owx~?t8☿EwloF`G!𹳯4K2b9fq<!H5p$˜y鿢f)=?OWv;ڟ"8xW?/"/x<ωa8Unμ QQuDh w~co;O({|=ݛ_owbAP2H~wm!B௜}K2qgoh(> \t?̿>M뇾??3Ds?yFb}!ki?é284K=*7<`$M9g dC䛚R7ވPRl4Y][%}&L)-x …1qß|O ߒ~ϾO$eㅈ,LS_/?hC" ]KLMéCJ9`iƬ?E_v'Oꌘ`x78tx#_Մax k>j&x&L-= &Нh&+ …w>IxMS} Žkijz;XήMqT1|zo8[m-X3/ǎAM OJ78|x#d(ƽj?[ k+9i'~Y}3}/ OgCwH1G_}2m'O?oz,MS4 I"ϛAwص$^z44IzTbpU#ALxY_}!p;>s_=V>oP9a]رE>!{N 'Fٛ}@ZyX41qxf׿vW&Oe ~*Qi+\KŒ"cͮN?pTSMثߕOGF^E]s!9=an():% ٵW<`{B&%w &#緿E#oG馾כ^K }cEI QuM#*HQPr/F MpN"O$0 '/љ2M }0B1q{M?w_o$Eǿ{_oj s?H`qFpmNmr_=OM'ٖ0<|?o~wm򗾆-߼C?{g?61k dlrlRGx?m&`_1Qo>?C񍏝WOw췿?}`~ K?m:5x zoͿ6 >oGbqT3?}]lOm{񗶿udHk?5~<\{ =?_O}ϧσ㏿+ֿ]_cpS_SxY8,ȋX, ,΋< o|5??3K`n>7K`xNC0/Xw/`92/|}Χ+0w8,q8C8yd^9{~K0g8,q8C8,q8C8,"Nu1KI[X!sý`xs;ų^`+/#գgб<9B/;M +2UZ+dzYDozt@|VҴ^@7yDZssZ}{t&VyY*K$sFEd{ɾޖDN-P;$#0J浽Q֢l@\pْ)dw̒_>pJv/L5\ejmne/-S$ix&dDDW WIJuFXSsS+k9w0i]֝Z>KZYJŤqIJ 8NvТIl9GElo/7t"3U@-Pzmn ~wqڨ?SVEmIf7~P7PA0ܰ&rfJIэs-^TՓf6q8C8,q83-?yW1I<+]&) |`셖8_oooI|W0AT^q.fow~w~0G}grE,@􅖔g|83^QCQyXjojsژHu%E,̯#8,q8C8,q8Zommmll7773====<>ʨуgYN=DT1Ԭ4"]6tw/~]_Lw4tHVRnJzC8;Rb~Z߻51G<$EYw w.8gE]9Cj&A4>԰,nݕs*kuwV@fw8{,MՑtH#ܸs( [}Xpul^0LZ#唤34 *PYmgǹ9K{m9dzY`YQ Wi'JPЬ >cSrU)Rf\3~Y97=X:s t5j2Wwj/#.O6~f+֕^խG}O5+ڹznSnUV'C؁xze#/` )5)ϬIkaoz1IsFTf7*L5ܮ: Vܶ*^7Uf)/M5oL3p>h`PcM~ 鰢QnʄqED7Jpehq/R+Imk,; ;N0ŎxowKqʢ8\| W^d s+M ۷*JtP݋@ԼΘqw$C-Km*_t^)IUчX"*E#pp@Z>5~[ս'UŮyp50"js`|^H|s#ȘWj \J(rԲ5ӆl%X+6xؖ_ėT|UwE ;"í۴x{-ʘBY4Fc% 7N$qQbWܲIZ\buGmb׼Im Pc}қ{V~yp&dGnc(peHq-xA/ul]>&~#Cf4/vk]]#;Bmsj`ř\RSW^üYAq+D{/yQ^SӔ3jImxPrNGmiPƯyC|tck`DJ^HQf5FZ~fG3r.Mk\#Q@# Z,GeQ]fŤ'Y/zʅ2G o&\2d/NflݑT\S-(Ϭne_#ȉf_#E4sqxli3 3V^aڄ˷;5?"͙jS?񯮳^h8+s٫̲?F?XhVBvG?$zzˮS5+S&2uݛ~CK-KNk,q,Z֜4\祋ou U~M7f$n+ 5QR%PO/#G&A+K-o9Do wY 0[T^Th2Bm۔HxT =8`ֻ|אNVj&VPp-%i{{-M*r}TmY׶51nN)ٞW.Pͻ;.D`F&e}r؋gJv=-4cZ4\pm4:nNm]n%eF%Z,SnMTc}#ǽM}P^r|twLKy[R `v6ݩ'x\nJMᙣcq]{+NxYwTbhN={惼E_;*oʎCwү_ڿ*9=)G"3Go-@CWDA/$%07k]VJPj&VыjzrrbvaC&u}}g====<0i`8,q8CcAO@/̀ =m; x&\E9xC];t@y{GꙃR=ɂsΌ&ROXQqG˩l9BK!F-_H,z" -c_4QrҫX}c6 νh<[?8^!QL".!(!9o,sQ(߀Yv O:ܦm*FGav~eaP_Bgö, L68:P~F~ k9v3Vꓔ]ÆԅJ,MitWun[˨Q:CBoUJެt(5Wo[G[[RoݪY`Qa]9[rfvx3hfM5Sh##oBZN5*]CqD[_]5-]w6;絮鶕F?hh0A}OԆ.; ys.Χ,_ywg»qz3{܌>ΐm+V&{.>UlѩV-T C~Fo=#^G ?xlq!) "*KJg$8$F̋jzrrbvaC ED>3.X`Nk: $#zoo,{zzzxx6AT^R X\hI}Jh$k: $`8_1`J,q8C&/@hrѿH 톊 m;Zb+iz;d^̠ M`r6+=>>83hS?'g1S.Kџ[B޽i`G^_^`#DS䟆D,c߻t2.Qނ}CyЌ%, ދx;Rԩ =!upZCS5g̫ 7whg=q?K?Ly2ljfũ4+єJw/e+G=Ti;/ IgyhXwzD|[Xr޽ f6W)ON!{诌0h|8[΂nPNe|Y}}3G яھ*^2Ow4tHVRnJzC8;Rb~wyX߻51G<$EYߑf+.d9\mwm^-j_ErDk6oT7efbIjƾ(8T =qh Doɷz5IC 4V-;#+3X 9xh-gt+WYf?稻VҴDKa۷fi"Ǡܯ\{lq?zw'MqeO.kŅ&\9|g b#!Y.JhX~`'PoU%7%k}6`1z 5,W^]gR+hcFijnSaڧȑ8nPeje{TzeMPQ9w,˿x$]hm#}J T5-DPChNW緻Ar@ܜ7a ldS|7`a徯X("*;wqqYBŝ0<␂g)ގ29JȒ#F zﶷi-Ӿo!qߑVN䠺Dߑ?-R%7+e}(*K6ѱn9=y'ZFzf';hQ7@yȉ^k0rK2H)ȐHFcY#`(;^2$;E(Twd?fIz/n-aomEsr1h @kxԩʸAGDª۲ݤdoJ*ɆFe/[n'hy#`:0w*"'\dc?I@ S}u'=#R!➗}FqPny'?YN<.Bx by2dw^w(#÷v=~ Ƅm~C4$C;Er؛hyRCL]{Fvdȣf8׺ C/Șܾ>>5t+"]ߵ0CT7.C44Ͷ?,ԍcIǝa6z]NN86~9!O'!JKR(ޑU:ԷƭxK}'*~a lp@w W3jyզxvϡ$fg6$'zŤZv2drǐwikCnr7ݽmh R|;X*@tmY@b7kEG,#?$A4G,Rؑ+m~CImSvHaos (Cƿ#u*ɒ)m&v?V{>&/ɉYƆYqsso0#Nɉm&sf!a|Ttg-Cf񎮯BmD (߀Ʌ.s0#jyM,zALLQqZS3SQwa.YY؎,(C&tc&UE,X},q8C8,q8C8,q8C8,q8C8⹻xs1KON5$DZ؎0pnμY [ (~!uē9zxV4KH1]D[ޣa~L.4+NKu C`2*PpZW!Ў`> 딐ƠNҩSrZy_g"<ޱ4R{=ЁÔu(b1',Z6-7FY}Z^ǶĻVҴsKǥֹx;9JЊFN:]-ͼ++/qprnS]"YޑWvڍBpE4^))wTᢊ{| fQ0kۇsj/&9$>Bج8Y>Q[#R23ZE) ͘7h90kVt)ʷc"Ҝ ;n7Ib) m3st\zE\[9[n)]ܮZa3*+NMH1ϻw,e?ÄPM/!Aн}Ҭve%1_ǚFiX +)|tL,U^2KrCId8$0MxwʡL^0XTh$Bj>{j9mH5(BW0W;2 u4m]vVOx|rAA_eݩe>DǸY{Q3zbO! f/Cds]Zk1SDW4YJ0gn# #rr-NYn/]ERK&/"yZommmll777fI]__홅pOOOf9 @ Q 0 ->p8!`qXp8|REQR0NVՖ&*\JHYD",2u ų^`ga;Πx}^GgSrMQ.CgYTYb:@Ut%uO=(SR˹/^[/qd9M)%2k]i7 WjuF˼&TYq *P).RWXˢs(Pd9DPvS$@-Ru5+T*E9eset0s CW+WQW;ͤ7}'V̷J3}Up*NO>ԅS{PDl,.N=۫BYvFF}95ㅕNnVI4NQlJWsJ{BL]u؛-TTHNaxNm]6*2ͺ~)V^횄un։ShYN&GZAн}Fȉ*^z UH[rk$Zf)Y< k ƙnMEta`m,ooB2׫5!9lˈB1C39q=E) GF5S)4F'W2sdg7_MKa]Xm♜qF"і鈖L`p-xc/[DN`V׺zHbtb*YΨNB'Ʃ;%QW0 )grkT2szq (ytY%k8'kmp*53[lk0\\˹3hg.=nVtFԒ~!%kSN\z(aju3VE ƳrBxgQ2s1eܽJWTKF@:Qy=q$y9U4f+dzh 3Tu݉طh9jf%%7#e0"qxR{Vcsf+:o\5QVM &Q&Ups'˨wB[;uKΜjvM,*)LS蕅ۼ7dR3{ 3Z*(}^Q*IKxPZ+fQx{-Ѕ2AkAo`PA39QB[d!獎J@T)l3-ԭ叏mUbA,$׺Ð'985=wBvG Ww>BMOVtL;&SUX+)(+ɹ).P+?\mnuN/|k&f> /RUn/JEl!V1ێ܂>}2C3stOt\jOs7kӬ9d%51R(ӫ+"],V'''fij[[[f9Y`R{{{f!YBoBKjp qo3iF`UQa-+4(߰Xp'qww82N``%%'JpuwH^0XnnPHX]T^@ T2rsb,uҩzc8vf:@juZNPR+S?'V~"zv'&&df xM}$N6:FtC/*S -a<%2c)ʢ/mJZ$U)dT\Z]+y96/רΤf[;7=*!ι4lKz:°}oOX7T^3E<K 3^_6fv{2=Q߈S땅STm?z앦D 7}'+ %]+|PoS-=Qnsbm,tJS7Uv+)gjhم^/fflM\PL/TI9TȾJ=Pѣ96FPf+a|*2%RnXz (I.wM\Wv)w4X+UnדKݝxؖv fAζ1wldC5u "z|WQI?~ooQ{9iuo(&:'Vފ^px&jτ갌,trQk\yQE^F7>x̺͝lۺS@Go&uKQIהx8SrMUrJ|DQ?'`=QH$KW/e%t7}'{]Zvtfq`SQp9wt s~~Ȭrk]Qy|_M75zeߺG%sL_V*?;F(_]+y9`i uP=Q!q!?ny8Zͅݦ쵏zWc:xb#| m}I۔|S5J>.~[Pl ZwSrRRcӭ/LI2)fQ߳Nܯ7:sQv/UL7QO /;L}KF}({BWv:R\d>V:ĩηJsg9`V^֚nUV'U٪k[P-zuRPeQx;|[ (Buuu>'TG+26/mqV-JtJy^iN\W{m:Q(ɋT$9Ͱu8_QÈ/Y7cs"*))^횄Β)ʡVNR-2BJovK޺CeԒ2u'J´Yv Jk\(Cj ͉i.Wp9`9Ů)"}S4GY[*A%~YJtZ8xhuVe'u1]d Sc"/9w{&[Wrw/#WBɌY>5UX57jUk`)xThnmUR=;<#õ%a*-[MXN/2NޗJ.Ze^7:9:&l&ifT\? -',5kMagֺN{wAo6]/TXfӪإmlwk\CIF/ɉYƆYqssoޞY𰽽mP77f`eBKjn<%Vq1$<)W`>VZϔ0j)1˟S(߰8irw详YA)S)@>\1ȓs N!AMaOiDl #btZ+Eh2G5ޤ)/^`Vw/oNn"AyRɷJ=Ы nn}]6jY}Sn\]jvT'<ɐsQ0qw}1{¼^xkh9*YYkM#>S +oCNܯĹ7ZJ!PSN1+LvTE kbƹ-q՚4zSp_KUU9:^hGׂS(JSwXgJ3tu/N\p6 (LD\gfy!wrTQ`Lh$ue(Nܦ>S)S=݀+VԍjrpxB]w)3u^mə{i.('#:'E2NZISYe4ȩ \F/bJs-xs 985U.Nzs^Ǔ$2W]w/#SK8"Χ~u5*]Lc KCW)Sd=< \Z]ܳ\Mn4ᙣz"U.˝"Te`uw6>/;fY\4[fq3*qYj3}r"N~)>չUqz;9*u8j>ɱ'46Y `krE,/ɉYƆYqssoE|ۇjʹ3 ឞrP*/0(߀Ʌr8C>znېqlN+G,ßGXo :(`qX/˨f&" >8"[o1azX?݃%r:%~NK):#"N,q8SrM^(Dҹ fY( tQNج4NiHR 3am@m>gQ0{Иu&qW/^l/]2v()ݦ䭞uM=1pkNߘi7 W̸juF[(ԧ\<#v+9Ju8n'[poyx /3VBnJ 5Ѻp-rbQ'ۦ'va\:Ś|eѠ| )KW:P_r z21xpj)ȃt\6kudVi>Caj)oneNҭ z~\zBzeamt?˚(5ZΥJnV-ܮ(DoG~F⼋NxZ{)Oⴡ^|p׏ǷyYC0+ P&h牲dEc$[啨F%e9w$h[޺/~b `Rs4ʗ-ha)3eo-2GǾ-3{uRm3&`z;+dw|R}<;A/.VUo@}ce7 1M_5Qo Xn)ՔM9h$ue->!9@ݠ)Ut.EiXJ@;PoߪףFՒCb `"r2|bhbܰ1)23sP*LT,/z˃yi4-ẏ[}v &񅍽ML*i o|(fyֽ2O7tq\<͸IPŷu_:%:'L+-iL]_{7K[!|T[8\֡dGXʺ͝lGx527#ϲ{wo.__ƔLhOf Y U?r{g&aFdl}SrFLߩy.Ɩ2s^8׺h7W$Q*Êgޤ1' Z8\Mw[zOu37AY]=nF%"qZ$oUș呼GY) UO>Wş)ѼxkO4Տ*DZ38RaĮ9dvuu-' peI]P+DRtVf΢+j0ܝ>( (kuܣ&婯 RڷKj,M~kkkcc,7 Lzoo,{zzzxx6AT^Rm*">=r03L.>pj=H,!@*QX 2Qvk]F`$(t֑dsXp8|96533 q; Q TsZT؁!Ǣ$M@Iz{ob4gCIH;yV|oʝYAQf6K0d'npbMx|XN5_5U+(^:z,+߽;]߃8:ղ3>>6+AQ43!@B׏<h~)ڔ(2lVЬ8'pLW;U^/;}yB~`ώV /u2l|rzk]dO ;Nʘ7i7 WꢿjuF[(ԧ\<-Fl,n,ONrA&$`j^M+ſd9|Kf*@Y:Վ|{TsƬNf-&ܒD^’łQ\6+xKrGCwcB'@9֔i4sm] dJ[IxxO$ηJznr.UfT ޠN5{lRN6 /@eMFixc^qogANUcXe]]ʳk)o0n5`j itUӬtk 6DX9oY* q-E5NfQ+uGZ6kRKvy[ :-,{-dŵt5]^O_D|Xʡ0Ȧ+Q]]7^^Q;fc#kiYn&׼/mDe䐖jy/h$ueKOwQFk-d[0-h&LuZ%Tcm K^!N#U,>o57:7:ڌOWj]Aa3D.bqg{fe3\G˞˙+ĕ8|9 2ebBD<{UѡD!y0 12z2et IM⫺#[vrTszLٌwK-9v$hƧO)s'J.?exN[L~?6=yK{_B=(5d[h kpCЯ&aoUO$;^m?SͷJ/S*-Vsg+JMQfGDǦ4 a+D;JC57:5{F2GǹE>ۻc6g"N_?H&st)#ŝEhi}}D&4f ӝ^L%꛿"5M_G<6-"TOwI.}3Kν*|OPmuEvMH@W^CXҬ{[eTsz`I 5y7ċZm( =n3~qM$+s' ,ߏ a!^[,M~kkkcc,7 Lzoo,{zzzxx6AT^Rh7Ϟf}!XnɅ.ütkS-Gí|!X] },XbGeN8p+&VPXŎ:7L`A8ɩb/$w77k"N3)o}MIу)<`Pџ[JwHp,pd c ȢiB%/Iޭ5EQ}K^$egܯ*+b}{GJ}ۈуW?oOxx6SnVsg$. Ó~1IuZ^Uيs9TOS- uDJ㔂R_S*n6~w/Ey%VIFBͪvЬokR<"^woNn:[ =m$z&~'%r%m;OwHam z׺&ɞh?ERo`̎;FJ5 Z]+ug@D=3ovΗW:J05U2QE[B20tQruNKgSF%8Ԁ>q\RgF~VxWӒ:Uwjg M;m2S@VpƬ:_۫ڨfJqۺ2DXj^YN\ԊZDi|â;w>0j\]_4ooDi:8[s'߹8b;U+4C}KqX?w9p|?}XsjhQx.\l Y^St=qDC8D9G'*AFi`a=D lZ7/{5A@nzÎzaoKS%6+N~G[{ysDz\WIԂ oߪע.[=G4S `>Sru٥N1$csߤ$G0lHZԒ^60MN_wxڼ oXni^/V/L&w*LS@A|$qQkv NMxؖ%_`p{ȺQ>T5^(}[?w՚My[ZzLd3Y]gS|dlBi?)]h8N:߽qJ%/|mX$7W=n hr/:H$qN09Kc<0wX7"r@#pw[3Y|OJvHitBݱi;;<>nU|}i&͖wBBfX`\/#[.uL~Sx5ZX>E}Mx'ޗ6*~wƍ-aܩ0MO|¼LQ)e΋ft;e`k9w }]l]!)1%;jZ^4[Fq3*qi3g˩О:rʎ 5M} : ۑsO 0X{S|%Vru]NUkI3VݪoCL=9Rb&ZR{|w! /`]t CZ#_1τskc5)"()VWU]=]a6q¨:d@4%>Z.2Ra8,Β w Uj۸wCD;[4{ aV&ߺl0zH"`<Wn /g,ʌS7iRFW- i4euS\c.AMa=KGx.ߟ#;+;Vrf7g^'$goE?1/Lk"ұjkrJj9~NXg"{\gq:r'׬8HՏvc{_w0~q[=wHJ,Ʃf/eX{Z$ ˣ+^Kp tӯooӷ]5A6{;! ƿSo`̎;FJ5 Zj<֜$ª$Ka+CW*>oxu,OTԖl8"?y1`2>}߷=7͸'Iռvߢ|u1M6gUݩa%V׎-6e.&2 . Ke*,7>Xii݃,U5zM2GtDhprPtj/׋νfMse m kDMێ'DhKܬ4j{wrc'^qo;Gr*FR|r$B$QǦ[V/~bVJD Mˏ6/"}DBn ];4C šL# 79RTG}V|YghJue*e]=|EXo)}Vseuѽ}FNw-!0zMJԣ0Mq+ި>!&A+kM?Odpo&5 \ksSB `hFu$x?,%$}3Ih"4&GңRb~+R 4en .Cf]=|zq XU5+~y4ݞ( kF4 lPv WA D97xz7EwŞr<ܥ{&cM|+La{N4@\\Z%qNut{gemkt]#ݭ9#ɬBͭr7"{3䁆xg>6[@ui1+;;|tR&3xH$vlh(Vf[PJRK`~hfԥ'\[.˯S-eX8?mcNl<Kc5לE4a Z-l>Vh-< ^üt8Y8\>\[ٰ5Nuu[Ght"G@=N&ڎx!5O=!@|p:b ޻::e<_^b|~bgerbݜyX{/=_X!+g@T\S=]WjEբ!ҹ fYhuwX^6[ClkY@?67C|zLj)dw+yHVgvh ͫuۻR<wd^ݚU2EUŪ_8_:KT0̽e-1pLsNuƼNQR퀻X"`E>9hF޾ }+le`Vi :ER[̇[9g)V+-a<ҁuSy1`2G|vL4YW~'Uݩy45=Ьt^Tr<ׇeJNGUWjuW{&Js97}'+>Q[z鿹]/u;rߦi#Q'!tBjQ} LTyymM,N5|}(? 8m?˘UHjõWѥ8:py"YQVs9(h@<|w}y4*fNvܱDMyܾkR960+T=],g>5 r],o5lGwrH0s2ptG7n62pd[niSV2լw/KTQt$-Gu 6#:`~zr81{ێC}3XqYGzo F4S- o$(fxC?Md6ч[0%)J5:΋_8fr~oͣwKm'? @w4ҽa&똕59ww-;|{&B?ǝ'ϲ;SͷJ/}I7S~{_RkLkwB#{l+ Uum&kǘ~S(}%祫~Uy`65I+st,G*iݑwfXgfV 9_<ʸgV}H 6iN~]sIju!,>̂NR^E){57x-o7s-ܘyǻ͆>vmk{zkI5'>mommmll777fI]__홅pOOOf9 &'3(~;쬞 X\hI} ~8R磿:r{h-`Ӷ ]W0/yЧK0gϟᏑU:T{RPyI_k$&ߐLnZ?ߑ|8FߑH\ZW-)U!)ck!5x'[r'8$yͩ&[8ޫ̢Km_y%(5EؼO W29 v!WgɌ~F\-?=XJXN5_5UKWjEB!ҹ;' `^.\KZ8;pwRmVW sګWgT<ZֲZI" #ӭNnWW(|mӷ#-1{zcnTzw-V ,,cBC>QCEnѤ|5)lHs_B6%a=S9-<ҁuS.5 B 8!2qy?U5$lMb={̎|r3:KF&ކ6}(wUݩ'b+muB$HZ|aw# )cF޼E}|02%݉qQJ_2C77sasOtik^ofL2je;ԙ tlO,|J06U f)A:e+)UiAQ4ݙ 3/ϻ7N$qNZu7)#ᚚ^)h\r a3%8|'[dw)Qz1^l6MGT{i2sĺV񦒦c8|d>CiXOh!8ǒW^S5E =܎m?f@yė>JNO d1=[ l|yݰ=YRL?TR4UYfۖ;SִqzYxV5YK:+nY5{܌J\̗Z\~ks u'95,ern>؉֏C@ܹ d/c>B̫D7T T^S$4TS$ΒFn̼x龍~C"UEЯ%8~#po_%}>md+޷{DTo:L0W _d KA̋͜jzrrbvaC&u}}g====<{muڍT Au2XJ/kCb@Py(+[@]3sةcRIR$A^U?nW}͌tꏋq8 8EZ8S3Qǽ[~ȉ 4`<<;W/HuCf [L4r;U'7"^}[_>U|u_?ATuJ`zju(K btZ)|+7O2B=L(3U:~YwZW;>NXW+Rh͊SL},ؚthV楈_֜>l}uN|"zvo9nZ5_:kȭ 9r%_6UK-_=` >qVrKGKQoՇal5E`}ێ-y(Zu>u:@J9 :(HBE<t.?hxˍrP&4+ڹ=zcL%vy$SrDBn߸@Wn-NWwj/Վ{wr4*+NM̴֘? Ň0q biT#BX*/Qd=.URE>BkF˹ԩSvG]˝V*5ux嵊_)nEQBn5p8/RP*Md- }.y-hȫЉ*ܽ{vN{_,վo+i>5 6@O/ C#*<KPRybR_|Շ=)ے:.LrH͢])Vau[Q;;S ]cT۩[0k+drd"0Mf7'Z\ٞjy6I.@YquJ&)LySB>}guKsWLvDnJIjxMt@#R\C>=ՒlxiHZz+O3#J&o7W2^SlHk|Neker7+Bl-!=gݧ O+Nqߑ[}q 7*@j,M~kkkcc,7 +S<6b}4@뽽=a{{,Qyu0#oBKjWtTs-҅R}xڨ[ֆҩ~ s`R}xڨRfNg2,>f8!`Q>&`)_cXskBe?j;ڨ'})!9O1:"btZ+3 z ulwT%T9%# 2GcUs.),Jpd [T7n^Ǹo3V;׺Ns $ۑڄmuǼNQR»8ٜqui4qF9`>5E +2CK ;r|~ ~Լ$qxv%Xɺrl~Q=nD[*/;pg6 ШNjty$4o>woNnWA[z 9MƢ9(}Bv,f ۷u0v `ٍ*\ꪢF{aOɪo,9E*Jޞ(d:B:TJu.(&1;*QˢvOb܎2%͕*zQ~Ӹ|}klTߘ-gX1-`^p`#5uԶW */[-iLV!V)0:TJun"öl⫺W͊#9[ Ef7'ZٞT#6 Åav~_qNxfSWZr$SHexN[LΰnZWF0\Fd:}xV[DxUK5o:1g)T;;uVIÅzR/S7;|9`;{Rj2}f[Ji}򱨃pLjƅ2-_՝Z^(lۑ;ܯ!6c;qJ-}nVdIk^n')_T)5`Fk +kat8xJ֒c e4:{QVONNﷶ666r}0Nu4r0mkE3 ឞrL+/j XA3Вza^N83O `],Yx Z{}t;npk&?\=ľds@j 02K`Y8Kagbb1$JʌOptjU;ؒ X{ZC>֨mWi$oVv8Eg]38%Q{ǐǎgLmP8Rұjk6iGǨ)UU&kVI%0fũҩ2{;MEe*w/Gֽ[v9z->9x|eMNLQİ:9Hwvk]%s4:t洲.=ޒd=ߍul =wڍBtZdxJǥd׺%Me8$qMqR@WJ%tSTU4g%N`{S0$eM ewxЌ洲9:tqIYW dv{,sNj IB)xi2Аh_[z 9M65fsPe2&vjWyCѴ6ƺnμJĺ#ȽxzRb:r̫iVBR>L\; R)q;( iQ[;fUj(dw0i ,¶i#oxђSwnln-Ɉ}m@*87+n;PpDE_58<:0W t9#z4v,IS77D|GZm~nz3?ݴթLuO4r9wPۦ2Ck4ƱHM=;}iLC ?M^zJ^\ǾBEP@/ɉYƆYqssoLJ`@B,cݶX뽽=a{{,T4õujJ3ВzET 9,VgVZz&ȷJz_/rݚ(tAn:Ik:m; f{&F˹Tj KEQY Bבsvk"KaDe-™XR)+M, ۷*m r$rlq%6w9n益!;YnuwqnAxi>>5 FxAMaб$G.XsV ᬻwQ eͲũSD4V9m /۲5݂yĎB"Mlkr;$52B 3"s)]6n w^7]e$qx5!d7vEhZzTL6e,a`@CZqgrij )P٥i4&~4_.qŝO8`pݽ);$xUuUݩeRD9K(=fG>[RLng;uHBRK k"mBTwWJ4[\VsxQVONNﷶ666r}BmʫSllKa=7BKpgUpɰ~LV^T,ȪgO@U^]pT,Xp'qx:GoCe;䬉$ݐX1S !gMk>ǹ uCv^0L9a^z7}';j[1N嚪WjL{\^Lp[ww!AǷYRZiyㆠGrFe5q[ ۦ8ƜNQROjsЎI]z7~;kW/ZۼunhNq_\dOQ}tG35,rݝ9:t[W Q&sZV3[SǦSzEc$*z_ToT`5Q蜻#ꖽZ&8y SRS7dE3AڨZ7F˹T͊nEn)Xv.GhL߂nTJSWR{V* ;fFF~faR-p^-Q;قܓY{@ⴂD4_X=zQ94  V4Q<ƶ E5ˎNqo3`!⫺#8rmؼԔ9>qöl29Q>Tۊ[2ww復伨y=5L,%Eu2GǹE{0 @/P prhqjfBvGNx&7zj^Gsa1?MX=^xGH~4dh^N+Bos{_8u|H}$!Mّ?Vc׾G q qBJ-&a\+fmtWt> >G*D6m\<{<j,M~kkkcc,7 /.qBmkrklKa=7BK[es>dq6f4H筧%X%L:!fR" N- ,tq88S S/ ~\g7+5qj^fbeeϻ%' qW/T?.{\,rᙣ׏rTNS?YivfSrRZ9X ׉=:;Ntk]Qu1,D._kxջINqnJ<*X4 WZZ9KACKq <$w-k#rpƬ++գqw5p;,,PF}Nn/ΎS 2b[~dEqY=,! Vz~9Ѣ5j2gҭ<ט\PMH l>לzw7ѭW/?cy Cku  }߽;]&:|-T*R+Ϙ `bj@7ZiU7vTUAonA83M(_]ćڦ)`J Y,Lh\_nnW'*nRf=)`d.mDNu)>TJo9z-;~e,zNUJlVBRMklyD**+Niˮ[=OD-;K=%zkZQ=֫;n(e۹Nm]ʸr@N4N5Rh:NiůS}ţ%9e'[IZmq~V|Jeh$*P:zx&MY64u99(oU(6,x" wH/isBFfxO j@ڬF+:lpEWʾƙ(ժ3/[8։teݩ#Cqww"xƇᦦ,ͭiyhʩoyڼnB_OFHj,M~kkkcc,7 sb35X:F?|BmNTbX7M+yJX xf3ВzV9mct n N>_wW7/'3 $:LVUyng7OFטHwLLm?xMWXZX6i޽wیؑD0Y%4g@{׫Lt{fZSHyhYSrMx^gҩnt.tapi8\Np{؃m_//16 в#=߆D.DW3_$6U.5s(c9Hm.]/IR4nTTwiG4}aVEh:E$wj@h#î;%#8V;itq?2 Qҭ::st\鶮LKJTcϿȽGl;2M5-sT̛2ɲ͐25C9ɶRLwoNnW!Wx(髏QRSx83B6MN i1x ed:t[Rwʡ5߀v\^)vBl(INL.`o4Ek`̡P֥]GH?\>>egh<Ȗu7zT;<.iLniO=ն'`ͼNKwk]9 lfh(dwkx&7KL:U:е yDel;ق7F]=t0vܘ{ÅQ<8s̫*B)V~n &$fWh}Iel:yc5}8W+ro=[4[D6m˺V7mJrDżU}׷}I?K#_L>V:i+!*ڶ:_ƩN+O/ɉIƆYqssoBZ}8{+zoo,{zzzxx6A3`6(߀Ʌ/,U!IRNe5k!qxlIj `-0/!`q2W0>sw;8 kp,C)s31ixS>/g9 (iC {YB{ݸ©cK2^Cj}uZ9+tY@|w/ou Zwj/ 'OwB}SpV/nltlƟ}n[m\.r,E(_$X٪Q)+Vir STIi)0-2GdvsNz)Cr0 >h9Yug7c")N=0qۺ25vXn[u;IR߸:dz<wrȏzDuJ/GN}8ܴ_T FֳFmUջYn? ;قL7lBr tnⴡ7}P8?.Aeh$) өӽq Nq{6ocdQRf{-{w\:l&CrZ_hj9&N:ƒ)lMEKRH7ʤөwMv\0bNayXwLoC2%h&S@Wwo+F 9ZYVh"@Ce"WEANS, NHeE-ﬓޒD=k0\\˹Sg.N-/͊Ψ|5POdOzX#|ZmnA!s:E5lݭ>t0}RT4UN=ߔ5_FHj,M~kkkcc,7 Lzoo,{zzzxx6AT^R X\hI{K7# %|ӭXq8)W?!`qXpS'` qՑٚRxHj+9E-Js=^V8md_a=$~*=/4_ nػLBeS:_sf:~cBvGcQ5 {p_BsVF권əMޡk3tOtU}Ў]6JN2"O#pw޺PzK7b7>=xG޼LMihD2G2WeyR}9e6պN򪤱"j9X851](#JLvm .Ok ^n̹mZxgiV'''fij[[[f9Y`R{{{f!YBoBK[Xb'yc6mUqF}|< @4jV Xp'qwKܴ?C:н_uHsnRXKRq"q%W/e j(/?'єE}MqJf7g^3C`\Y,EsuZ.+ͫ9`u/g뭞BvǼAxU_xwHrF)?V/1du/.dɚss3_:˪ :TvڍBjS]9h叟'\Yųt>5=N`{ SnX݃ȬaV˲:{~Y4PN1ݛ͈tdNF˹ԩ1uzv{(6֭=7u0jt\T`:"?$+#R(UIPY\j_\SswYwj$wyB#~h X8\VM$st\޾uv^2Ϲ L6 {6*j34|T'ΙuiVI?',*x&F4W'])R$qtt$5<49``o!pxf7'7N$]9*)ԽkH!}䤅F4Z@j"~NXURwxϜ,dsuGi!ےᙃRqj]6Tv~6{P<(9v_%W ͢_!j!xqx:絮B HQV%uV$.{MRKvúU|u%OK(>CD!k&-Is2x\3G9yK$oS-n[ opQ͚~Z⛿l{'Z,w kuC8DM9^1k8i9`Y*Iށӯ_z j = ;N$=Ẋwo7+&wDu>mY7nzQVONNﷶ666r}BmDZo'X>oBK[XipRz UC>Q H )|:8!`qCy7 IX??'ySh!n fqFdj(/?'єE}՗+?D;B|NLϹ:|-TOZU.^²^.ie!c^ <*[SX4ᝪ>nwoM t{\ kb'_\d@5|4/2ثSi7 W uw?~NHТ~J rAdMRSDrd{V~~q*xJ7Lyٌwa5=MTfo\J:Y[=Zٞ[hN՛/S*zw7}'+ޮh%[zgiTB!EJ2\TzOd%gp 9ux.ּz_VyܝcůRcJSdJ$QJrCe*ǦUl&Otj"9".;M5 %V%zH%!g6,ĮFnuO8Oh|[d".O}{Ǖ'k dd`AE# ,BHX؋ |KnKźE N::.  egvA!vd K֟׭Tݪ;^uUwu꽪8.mM/72sbs&Wd]w-Fǐ4=};sӖ{ O.-Hρ']+Zm[:1Y9{W!4M,q)`;cwh 0NۅʃݖJG$ kY$LP8Uz 7Qkm #TCeM}tl)NrxKQXYm:6 dw uDۖġ($W.m\݌ "EH6 =(y jMv^/--ҹ  r333Н$Jo<~ÇSSSH(57'_n_z^T8ᅿ5v ~_87W")l@}Z^(Y^Qighݎ9+*v^"róKvCv9&Ӻ[ {3]& HPH^(M?>ҫa5Wel''ֲdB绵=צ~];\0?,8Yè[?7;x'5I zV[mC'g%_Sas-mlnN/uM|lF[TS3|1%h9hPhZtGܮBъNt i~pd@<'ߴi͍:HK[#Z2Y>w[dW3mVflyEG~l'qbr}.;Dt!$1Y|t'kZ-mcu.tOQ|Ns霱|pU8lkde[c;߲Xk9d./们@:y.)QC}& sed]rV7/ZדGS>ѲnCmlk!-oqQ4; YJh\w?Chzb{α,zGE}i#q$0~<͍ݼΠJjWIk;y17]m܍~'CixI'yߒPV2PT 9ZG 72SOK >H=9@s\::wl'뚵=P%"$+ꗅ.wex~s#[;mA /Nns4H_v{˵4Og#@,OOݮ ӥܿƽGc7fo66v,uUY7s+Vm2K/nŮ=?'ͱ?Snc`|HJO?!0{rmq)YT+ mYn+y?֛c;TK#׶%!9M>jKlt~D;\q;_P(\Q~(|}]tLz|vGgG^*7'svڕzJ綷7<<<44mloōÇBP>J/IX~& kM7{{>}֭p}8@mnƿf}~y:Cٸ?isNsIgؗZe;]%~_ssI(X=Mw&s'x<mtO>P_I[ Ai٣7榷=NV\cYv v~.6mzF%V2S:yߞ?}=TU%`ׇ?~5̚;.>=;]z'jwv|9]|KAT<<[yE{[aPr3_ZnʃݖYxqӧ/vׇ'gsl؎;xy{˵$G/njLO/nΆ>Y٘AeEwWnFo|v\S~۪egae-˭b%zGv\6}DۖzJ綷7<<<44mloōBwTx +>|855 Q^]s|zE>G]|9gw9 ./N?@vG;O9 @t|~[ΆB9~; @׿(777SKI\T~a_WCaIQC UX `pT>mO>}CW[ Bÿ_WϞ= *(PCaT<,08.r<<n. υ2Pa g>I I\HCKNUÛIx_["IUPDPdU/~oB g$F$"ZGUuΝ¿& +jʿp3ԐW6cDm7 }Ga\բ5U`ʿЭjTvH[n[o˓$:2ʼ_2ZtXkg>C IDh7  .WEJɿp39 OGpx n08.>m+Y(5$IЍ>I%˕zJ綷7<<<44mlooGp>SSSQ{###|TDp/Z/&zO 7y] y8siWkn >3/⑇@㴴4)Xjjjdjџ)nvM_'ߥ*6|2_5L'odZr2ӍH#qь[l@lʿ#bD@1h[pKV=ԄTo1._!U`D :::233=N1Pz9"UfI#*VCò۪F{k;{`bŋ/]T[[Դ{n1P>cfPPEUfI~6bޛ>KcLOeTk\-XRg'3Hyyyׯ3f̂ ?LvPj]W߈#6~|/Yj"hVo{#8n֭o„3I?C(Dׂn4D,gE14#+&d~fcL~ܾ5K.tﱬSLU#bYmϔ[.йBHӆݻ˫~X$ a -MեŎFc㮌M GŌKO>b5ؿt5-E,ӴuQ}Pd6ٕn4v:76M+6%tVF@Rb˖-)?FcF=FgYaϊʺrqU 2{oV {Y6SYsT(}f(bfޛ;@犜l,!`Pgg`en -5Fq/;_{۳"2有24S uٞ3XLsɎ]y/$OcccFxLvQ2siN5ZfL1M_ 7aNv28Ey1~P3!U1ϓHLMMMsҕ$?o8=ֆ lf/DCƒ: W&]/?y _ܳgٟ֟93Njγjժ-[H71#~ٮWAH}xU.jظ#&bD@1h"FMX~b4#&bD@1h"FM4˰?˗/_pA跴ѣGO8Q$b2\rI" $q|)Uw}իW\"UK_ҨQM].R8#KKKWUWWO81==HU|}o݅9r׾5>{J@j_v-qw!:{, 1X h?3qw!:{I1‡i]^)^P9 Ey bA %VhZY]eiT1aI]ݒ 27 ~}ַvz#Ϸ91`w!}aŋN5WS5i5M`O؟^jiw(9e]fozʴ* v}ZB־k*r?!ҿ'] .0#<;yؔ]] jӆ=z䅚XiMI Գ{^+ySZ7I}[ӄ%;(*znɄ K֪OmSsWWު,oh(kxIkĉmf|UkEuoy=ֲ\;5>/xQiȜRp+*N֚>fXqD|SV{x,OJf")N((-ڼ\eELͪy@~ -ak(_[55Ĩj3ٴeuJ R`yȖ%vǹ ?G?;;_QmNL_A=?anX3pd/*͠P)ڬu>E &ԇqkXc}{%}[ z/eRcx40;)+OUڬK n=WdrlTz8eY#$X… ^n}B| &??+oW ~r3?.+3NLڴɨ 42ZKé=X+rNGԯ]oe#|"fG&&d{g'g;gg< h>(e_P81"NzC[L1"   r] '# (H@Ĉu#a2zKM0zK]~bСC ,\uR`(,,b1a&E .P4#&bD@1h"FM)bY__pB)DpرsI6nܸl);1BeׯO>]G1bDNNć Wdt 6wbĹs|0 x b)?gr0M  t nJFtT=:rUR g3 vIi~g'J,m3u ^0;=֯Gs܀G7ov.}Y- hĮTvX&*[c+w6`[hx(/7n})o/<@)(gnQjSkaaH1 5u֨0t„!ݟ\cjP'vѱsrx ;6vw~+{)ӻǛza{v)'+6Ԧo۩VsEWqk5`#7i^{&<"?~͚5K{R5^Z8Am1Je4xΔ/wqOQaw..)Q}=6JUm?_c#mCpoڌ^wH'vYqe[7WyUz.-ӡUO@_Nn7,g61< ?S\LMɲ!±ܢU:5JbF(oc9OH\_9FFZ8H C@b(O7Z{U[~s~nmfv5a;Զ}Y~h籴 YZӥ~YQ4Z8y:Qb*enkL7gjsqR㻭 9WL[XmJ̮g6=*+Ֆ8i^Vuf"Ű`ݏ?cN$Tbss:04˳;0foYnֆu-YTykq֊Ջzifu3Y=DmWd]'މ=n?am%{gd,V`)%t]ιW7D&6̳WU[ ^z;k9@=$4LUR `oC_p\Pr_rn-Q~w[(mS,mW9آm_6ێ_r#1Gk^Lk=湇ӓk^nڊgΈ8ثPjp"2{#DvhDzH!lr0#Fxkط`m׻g:=V0y|fj政F%ڄYn3ʦj}-tmm>X6̱V;مyEs[es gM\NJ̵=Vfu6;*=?2<籇e{ք}Z¼XхË04yQC~`5"f}V=|-vEaN " P:<+=dunQM;͝ieKu-n̗nKq_j{QEw֘[eGc{Y5]W2QZ֩E[09̰OK+[A7wPxMMMqqqWW >RRR߀pE>) I| Ibi'~=#Aو"Fp6=2  5|:\mmmv8Qu!FC;5cǎ]x… RH@xQõ@S 74#&b>;;;ϝ;'e ĸqRSS  *C\~}R"8z#? qN2b\tI N8w{7\-2Dw M %H @w y6UG\,TU^)X#GmFtT=8Knzjf_f?]V!H$$8LjAyƎeR,c]xzg5v5k,Iըzi @s0Q?̼-%IocǪ@5%0RSS+++տn0@pgyϴnM/~窭.{yz{SWdY5'X ffnOcЩPQQat(HqŲe(K֊Y=gef{X Fo5Ϟmo+ܾl42&RKKKSaʔ)_5-/_VP5Y}'dzj-TcMǩi:ŠIMM]zu6y\H>Xh`%yV6T"Xg &[W X@2p󢆌=9Y;/*V}iif/핪5(ep2"{C555]]]Rٿ_AsW}-[k/e$o'?ȇ͘/G~w>r-8H|# Q73'3H|Ĉ.#z Zhkkz 1;X*ǎx  PBɑ2`KbHM 0#&bD@_}t)@|=ztĈ} (d!(71[a8W_e7ndddHo}K 9r$R VVRR"#GEQ⡇Duuu:cpKKgr !15kC[Ԑwčn"FXchWOE Һ8 A'`C$ %4IH~FHRkGZ̨J$&Xbƍ,j™$v6B]QԌhUGJ]p4}c9_azۼ9tBlc;O}!}$A/*=Ż:5MvjzЫI +veD\bDG[>:#T唷<=ejW\Mb;w7[w4mo7-[0d?~͚5K{R5^Z8A'̶un5r2U'7W^Dݒ 5PV|kIDanwԩ3fwPEUiUu#Fxj'7JїAM7\nl-0n8ݨijOY\ QϿ,m 3T(^d#4 `IMMTE}H iBfN]^ol)ۖV= 2!ުg//s(Q5\H91t^鎘jzЫI07 *e{# ٙR3m%ڭ uƼ?vWEλۭ*{nZ:Uk%G {9 9jp(t(9mpb{aW^}㛷7uEv*_=>@/~,+u+_Yt؜o]'/it˘dXjzЫ%鍴bY8lֲm?sVJƬ vсQʺ rLUk3G4 @BHKKSՔ)SԿjZj]qpY­= C̨Q[vam!1g sioq89[hLk=<5;$r_rn-RPS_"K={!O}]zu69脐ٱ0|wY5 _1V 3F^2Γ)qu?cqAfh_ÇBUsio7bweujڪ|voY7(KvĮJbQVvP{i+쿣¹"oc>VmM8pdX~jWcGLU_`&|SC,RnU8T?gbF#Z5RaRv˷'zЫI+2yd~᠊ҞH~slմaܙv@5̟`r3_YLhA`[vx)կmgU]n"F@ɚ]6mK3!|Z}DZyjZXU>ժ$1gWS[;#24n3/r4V"'j>s_2P*v} 񑒒RWWOsq,Q^R)`@TWWIu?яԄ[["dNi.I:!d6bTtP"(C A'`C$~)8H~s'Fxd AFj~(4X(ƍ) ya"ip-F?' 5bGAEQ9" ya"S/Ykk[1[,cǎ]x1W@uH'B"K.;wNd1bZIcbD@1h"FMnވK.?^`;vlZZZvv#2č7220Lr-ՀƈDs gMMMf͒B8맸@qkK4#&bvUŻ:̢]T6Ia4Uڭ@"q7F4UfV,9'#y%8t:o5 5r&۴)oHQ}Mۖ攖ڵ #؜E$KY<f y 5o%LX#siK$"/jX4Xyo/9yF#m7v1cWq DyS32&oU;d,E YF{\sJ[[#Lե;dyK3ډ $:!Ng0ܽwbرce yn Ĉ#GH a?UV_^J/\P ^xRCرcUΖr555R`}韺#@҈1Fp%D@G19E:~}S㧭:_HqX_VtO*ojdee#Tz cI17>[|Oe.!m@csY_=#<Ƙ[y͸v}?I!-ν>3¸ŕ/Hbɵ Ģ $çR_@1cWS]*r\1ۚ$*+=Jeuœ qވMF~ubsrÞ ^\n+{02$#cɎmR|b$7./%#[$*d$#WcDƒ%R0O lHr|>CndQ7פuscEYjA}}… Λ=yj|e`@8* qߓxVSSSXX(܉m_HqX_vAocH1x@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4#&bD@1h"FM4yVZ~z)EP__/S`x(,,b/_)0.&Gz}? 6t5ު׮{;Fu-jAױq)v׍kOYܚO~8\)rhNwTͿU̯JZ9a쯰j17j#ަZ3Vm[;?cU}/l^~khm{usIm/鏶w64ꗟ*kVm\y+j kz.,yk]qE 1+(Q2K 39Xd(jUi]{,WşW[`s<OaN ݏnUl}g&U{j =flg/2uE}V~v]#Fbt?oc͡+s]wfԿUvL#KĚ܂ghi9ʂv7!-i5/~*Cd,8~t|[`ewÔpT0.6sW6xV\̓ )h53n;h׾;.Jv8fM["E_:5mwɳλxk+rΚN+1~X,=3hr._f_1 Fbs鄄]9_1Pm|ơcj}M f5)?+]n>dÒaմaܙʧe[ŕX+qʚN_{u-3_rRs]Cq]]RvGƦ|"]j_#퇛RRǡQs>_}}}qqqW!#%%P>} U&tQVyxvץ22{ 1']}|}[ۼlo;,Cpc#16F0wFYmHT;+1)oݩ[}]])OJJ>TD۲Fߐv3fL[[$AjgeK@v\xRNF\W/&}.~|'.]r2뮻T4i#"F|S#FM4#&bD@1h"FM/ÖIHqZZ,55525TO~oL/n|R5>7ys]x{ß?Ҙ5{"@XZN|w)͠>._w\_xM\ƅ_;͋^ѳ1{noP._jQ'–'K[.ָY 8vdtgUa>=4TEg&'K"{o&88s$xZ A74},߹tܫ׿kߖ?v}Wt?οfƍwW?}v?M_Q&˟|br(#R[E-s&Gd>1չY>yÓF{pèFI<l05990%u֕,[ߛc[SSM>1+|%i[UBA74},^~}S{Oo~淟 .7?/l~sڕ;8|,.L],5e66 +5 ر0*.ݠTW=# CCOD˟ >8o*ޔV@ϝ^Ⱦ|ʕ+.K[f7tm_zO]/\<|w\=֙ϼnG${r5E9m-s zFy,PQ \6K+XvXqT9&GF!9K tB[kQt0H[^ kw^:}m![û.~yKov}bwf^tӥ^;kn{٭~>I2絏H2\ѩkE6W2US)/Zݠsq,s` yg1.̟?I/eKz澷Ͻ2R[f&|Ҷ.ow{SІ/_ΝtG"wMc'(_wyȑeLK tXI@>p^lAr+kI@KeXs٦lW]zfKW{~7]Z~w|~TW7׳{.-ڰoeXC'7^LWzrGG/<&Z%|hc:1de7 _^h*ݵtMƼ#-)DăP>GA MmcW+޾ƩӧM6tew|柹aOf|"i?kn+mc'=L;.G-,jYnc m-mP}+F'/̛'3CK+"r]MlI2xl?s_q ٫7AW&ӝ7ܺ1{zmcRnU҅Tρ$n9PRhH{@@T@hB @Ch4 ]XXhΝjvm^htܹn- ~-O}+^Q~kk-^f25ޢLW6ݕݶkۦlownݘސ&A4k76olސwuuWsk 7X7)6VCBϵf:`M3@V~l]4tw}o.noѳ{CGocoy[l.u{KOa_y;vl WU0~(x2Z -&e50yd ZV_ KOk{}KksxB>U5B9︫w~ ۻ޵콩5[W|wo}]woyMݶiGwo' Kgr`qȑxri&|#"J k.#B͌3וJ*JQr$Nv)Mʵ.'{nfn7_>qL~w^|7/_v/\>v'FT&GN>14 gx,Ç$_ß(shKsٺ0~/}ʵo̅o\|m~^ܻk٘=]7w?7,Sjװ08ءã L~{AR8ȁd.*}`Û 84^46X<\mxGsەc5orʾ/Ef}'<\|l\*\lt@ҍs^~[7p_ҕg`^;B&}7߽2/^ٙ4}qB7yd񡸏ñ #340~d)CzO< O7ڿԡHbGÓFȔ2 >~aPP03f>{QEOܑ^Jo/gjM߸ʾH?IK1 /\{kS 6o?{. \o~M3_6ʵ+_"*lͩJ?؉N%} &/r{Iޙ?aVɱP48|2 9%/N qq@*Ni };o^ hwI`] /+J+UL }}^W\r}o4evKԅw~So=D%y!ZFyauv^ -&aD4|"ݰ-Tx)ɩ»K{a+#FqiJ_–{Qaxc5ΕS|]1 ȇN-][|r6.oG;/y-Oo]e 7 ~1s;]3/nKg{w\?=DCĪfKN>1^ɪh>b۴?RE\KդKgIcUa}se}7g=o[n-~m7|ԭ?s7=jFr㇎fS>]R#\rRxۈ $$lHq]'VZp]Ғm`EB=?Lכ.Ϳr-M?q;?a~=Nm2[X\M9(4|ҧ{h\&ݵx2Rqء:l%,‹_4,sGz9uVKuuXlސݴ!!6ve{=o~ߩ?}jOnٔkCWv{Woٞ1Vm±ZrJRsW˵ȵnd:bKsy?>jt^>H8|‹X|7q)U=6p$ ٝGټ!{F/BJv/, xv4@hB @ChӧxDgxgمx\ha!wO:9sf`Ͻk፯߰ckvkw0ve0wn\qfnehq^}lo{S/s秃aw7aWYlΡxELOw{Î+_sKgSp a2kJ :jzlvx.,oy )][K]0cQtZMe6[|ĥWVM\JVUzOs6mnonm,`epWfxK?|b<34"N7ʥ '%e2QFlC۩cKNNj@=𞥃{ralsg=y8E6 ??brS&SS'6f.^z~Ӯ_܂` dCLt.=gk \tPbr(EG,*R*ו(]S10uM};>Ap a2+s= ` `y8 ~hy 8MmoQ(le\s8|8x#!m;PsX#u=PF_r~u!KoW>~;\ nB0 V4@O>1;Zr52a5>qxfgQ0fMs{mtQs8y E {AW)2DF],rU $l ?P6:v,Sxlkaa!pjz&);'.gn nB0 Vwuu;Hw}w<t@Xz@|>W/ַ^gsZA=KirT@[O?@S K DϴeC]hVI,}49=7h9qs9Rh)(|ӂcy\ato+hZ i]ГG;>tryhf 44NYL=wAhV ͈iCCCeǏfy؁cޙ3<"I,}h*zn6=ṯ3^eCf'&2?q>iFWK'GN\WVtMV41\~yEɚyŭ5\]SĹZ*`ܠs ^"̏3GT6t43шiz:3ӻ2}Q{‰I81 MGWU&rYp /fԋCwwz,3t`>`x c@J?MBL'?-p(iȱ&&2#' /sa˹r͖ƹp㜉7ŃP^LwRQ"o'M5'{rU9 J9\ݝ$A uy 6*zdTMU𝽼0 N,sbb:r6WlHd/~}vzСѥ AOLV8=6=q 󱾨(ht'Fxܮa<8Xci*(>X.5^||-X3=[SG՚Edhod' 1OO;?G(=Ծc[n,=TMU.XRb5SLGOi{@(rۙZg:g(|ՂI:X㿙"p\+^opo"#8g)Ndea )bfy܁`TfF)z|yXõh}ȥGJe$kJvOkOwX\W|:ezbbܿ6m|47y *"7uW{=txtj|n 3x6Q&58 C8y G6̰;ϖ zksr(g\+Uz$ccљubdV?<;|ꂏ@np֍I=Kiou82:Yzz@d8X|ˤӹ)$grpV`m&WG9q4H1[zҕ۽1WRP?2+s%)XN,w%U^28+yxwgLWYᎹrP2 U@L,=9ꨀ>~N[1)④k˔KfFQذru$.ɟCN²ɾ}w9s&3^W¢c5d/^ZΉzdp@ٹsg|ǚќx@֬AG_|>ﳟle-˪2h#r#v…xn)̙3wr-8=?[t-]p5gP9-bR!t@@QV @fprd .I,}3z]v:g¿RgbRW:GF'e4V,܀Hωv kJ R.bQ :z@O>T@mfꞾcr] Zp[89:+R +jJh ~zT|6ƫ*s34udngX_ls*ɞ>}>sLg#ߛMrɋќxl4 }?/~x܂~Dmuڧ -U8ȩגOY߲DkW_ژ>{&#r#v…xn)̙3wrCC'OTѠz @uOБz@ YZ=K{{{˩)}@%e(z~*.a(eGS9}Bg#__ =Rp2mVCNO?K}v{e-*.a(eG4G,N@*rӧO'dㇲwEY M.M!. zSU@:45z2ʲ#7N>mDs~TWOt@=K=(|=:<:5,G PLL=&XֲR]zn@=5Z6:w|.4,Q )RLK HEM-8&?2Ba)ts@[xk3ğŻJ)|6SK3[PZ'38¡cdžƛ#S5|?ʲm~2hi"I,}UK=59ߟ?[ĵ=_v>o=C(&RgbjDϵ&Q-t٬l*ݮ$EMH"We,IR~.+IUE;W>rϒS5橰{t>cqY =Ab]TEyxCc.g&'b {EJ׆bڷxTQ]YUzv)ײ̻/|#=i~c*ű˾ ޜ*SF|Z@TVK9uo*X =7`m(& 9nz/r(Ixx Y_&3𞡂/x^pm^|m^9l} GB^TWj.]jⰼ껗ґal JڮY`jη+ F,?X|SuQ ˙-T=,}6@]$>~{.>e}i_Xk<-Y"a1mҖbȑDW9*=Rą|\gu%eeAGꏇ;O%Y|Y}q#HFWv~ڌ$~;y]w}2\Իi_aca-Whhh1Q!/_[eвėڊ\V8Sre.E/Wp0+/ֺUh'2-RDW݋zj$ѳ֌b" u& _*=7L,P2}yUy&{6_e˖|#Q=66NJa:? ./P55tx4fU?/w;֗]jhEQta\EpT0oƲžI2SX-iJ'/;mta <ڌgX/e_z}իD_Ջ_}w/]W5$~'RIo`4Ӿ5+^?td4S[Y}+"2cRK+*Bܒ#|0vx"V|%^V"/VG 9wyI}5 a܀HR Xwx-=xضos7:e?p"(]'ϫ "DW h^?a cy=|Ø45zr)Z|+r+mZwT+ 5Q mF hO^XX,f?/<ݫnk}ks9^2{ą_ַF f^|ڔu5::/5(z/>wmǃt}KiRVKSOYhOYk-^ZVjZOYiE = 0{>b->bqRY>}:&e*o5Kc_xEmvܿ8+ߋ׮{ko t_x:RTC=+|R-ѻ+,\VƖ];3W ܪ5Tm⭁kF' E -X1DМ x-s+ǹ/y?xK6D@S $)| 9Xza!՗~k7l=;2Wfo.='/_}_ۻkҽд>CJ eO>}w9s&3^՗>'vks~폿g/]ސ?/^,nz[Gއ7mҰu:%lΝRit@Fs:Y]gO\Vi(?55:G?Ώ_w}gAKYqu}@~:P4?)sl-foYNSl G/>b-~\pBTM7y̙ݻwGdbt6jV,uސn^4=7L [^}맾+9o-=N]\K@M܀fH:G&Xj%6ouˆ˿Ky{c[?W?lgh'Is<Z2=4z6v;0_矻ٷͷ7/=˗ub".zn@Z-7o 7U;nԵ!-]=K8j M,zЯ۾n9xբ{_eƮ]=֗I=+|USpmڛ{.\k;z^uc<^?Uxk3ğŻ܀֢HϺG&HEoy[7.Gk_o!M.N^Aϟ_6@K?5wemf{n5f_?9z/\97sW={a.ZΟrd@ H1: =7ѻϿq[o|hCڭnܥکGݶGN%߿mkcR{U*wL+pgɩTؽ8K+\SE/LpKpUv?y?lqgԩpmkBdԇ#xL7Q0 v%]v zhKtOH=^VH-$]|swdgsvI=+|=cUk҈`Sz|x%v__ۗ FU+R6Bo_򣺲pyXJǹgKô9wK>g+}EBF}oh=Q^?Ɇlqe>$z>@{h@O/KW@Eh~ _lŽ"y1iyo_CȋJ-sԸKT[WzJB0m?;%;+++y@`UXќ߫EeiXWi] Zf>CGi|]w~0ʠJsQb{a~^T5hbTU5pew/WD _Z.>]TmZ.ԢH,,+~Ɯ;TYU+Vlբ^WWvfympVhD@=KsIe˖|#Q=66NE0p0\C_.j> C`ZCԻ}QUmQS.5t(|Zn@5xtYrbE!IqkV^b#贿-,[m`@P ,˙-h--=X u:ɠxT(p5QiռW3ŗnH*ܷR p=/3V.tXzr}C=H^wxO>F9n+x# R ?kW9܂@`yU=K=}@A?UkUnF\W.ŀ76l_*fǏNH^&aJGTynF%uv+]8C:Ka^E\epT9VU"{81Gz0vCe "J}>sLg.U/^u}hxӦMOO=S*._/ƙ!r~s nOU0Dksxi޺Sz2-3f2O:붾wL?8۲|%kʉ~g4'#z^wE_x>w~_-g?O#Z@>em?e<ʧL-Z)k9?eo"-=o٣Al?.^p!^ছn rJ =ԨgN>׃?'HO4+OҳSwʵr}G`= k5{o3u[T&_`_fpxG/u~o{5w}Ri\pP}@~:P>e5SrOYTii}(fq1N@*rӧO'dyLfa|箽ah̃Ϟ>d&355๰:t ~ io@#9D @]ξL\p{p&=xc&3k<{c!3 f]<jq&h44kZ@>D@L,x.L,w7x4g`5Z>6@g?5w %=k3ڡD[v}g1 hblK6N{b pW0ߙr{/tt-&fKeۥcE?HUE;W>rϒS5){c`Ň*<Υg(=pG~#-p6 *ܯkUrEe},=]xrvJWb|||`=ۼdŜ^ҵa[9H}GՕU˫gZ* #ݪ/j'(}SW8_c_Q&~BX\B\\p#CKt\zjD>;k}_~9^Z<@j5xPAW?\dF ko_CȋJ-sԸKTɻ*\R{ͨ)]JoWkK( +vW*\P3^%~~ꙜL3%6znkMǏ}{qZs^Z>5͖\^\'Ŗ a#e]k߾QUZf$|o.///,b7rZ"y@7e2vEkK(l%,lCG'`K۵@M ۖ$ojx ;']PL =7L, 'wOˁw?eiϹp1es QMȻ@ݲ{\#ez/{TUt%bGXɁ#TCV&λa=2/q$WM]tIn_U]Vt!;w?gY$>ki1Ymٲ#HA>Ga~u`XԚgɥ5 QH *lNP6֗]ҕj.V-\x70kvM >T|uɂg5Wxۖ,5V7OY}-7(z N&Cw=A1: Rc==v`ΰyb8;v`od/b%Oxa/Y?GeF5*nWX8-GPDEy9yrzP";<}vf ^tȉ eoQWI/~b[Q$KAy`3~U߫@suRyrt*y=paȹc򏿤Ck2Ǫu.5 `r4B ^!ε0m^ohpdz3@*gbqqa!XK+817x4^.yx__o}kkf8^ϧM)Y3^ZWkx Y8#^/nx>wmǃt}K$u.^ZCiOYXOYZgQWL p7K14@+Wgbu=}w Μ9{hfL;09,w{xb&E[Gއ7mҰu:%lΝRiAGsMiWAzSSS|ǿ/>[}~6uuOYXOYJӝ֧Lhf|V,?sogf}ZN}.\/UpM7&r0L=881\vpbl,X2@L,P(aT\W}=9 od:g8 !D1: T!z^ 4[pLO'WCT݀kdZ]-8.Cxb/k==UxL&{ǖ[-( )&Rgb>D-8#t^g/-@ۨG:Ou>mK<#..&}dP wOK»+[Yֈb"h$z>#K 8G㻚ǯ\V"f}eRNdyԾ}ľzj#em$Di1@"}}ր{G~w7O?-%?P}N=Harpba:\e aVЮ=22=RM7{챏}cH}}2N>'<0r~N4KǏ}{qshCO]zÙtU*=I#S xǫ*V@ @OO&M75h%O<Ѩ9tM°sQ`^pF'ÙUL)ڭ`3iX&hBu}}}It&5(~kIr7z޼a簫F ߿tg\sj:rsX9hhgc@8I@i&lrxP>gf^~7 w/=gzJ|?TK uƂ͖{SgpyxD@L,t=7WE/}|[u9b.N+H~K`cS,-V=~}N=ȩͤuy-9ͩzzcΝq {k6w{=PBk k鉉ёσGu^/S[s ˞G*WO_x7QLB{KgZ2@Ӫ5.s`M>t83@YsTHv:2@S;}¢`9`W 9J$S˿(^ϧM) 8^ZWMlx):G?ηxКx)msRic[V}@>ehm>i}Zzi-)kRS ?pHߖCr8,Ux9֋󉾱L)4m%I1T@asX 5sfvDeb&WO @.}=B @ԙXhzn4X -@g@D3@_['/x @QBS 2ϼr׾XW@ $ѳ8-z~aͯ]l=/dzv%zX7>O>Ι+`__P >3Њhr&hg/|Z~{ƿ`Me=;7w,Zb" u&EX o.b%n,p׾jgokLû6xc'/'/k/^µs >?wcD֥|Oz-ܱڍ/_?S3{g&q?z ٢(|n&hEeM]ٟl41p• /x_VM%kLx ߽sC6Nr/B1: C6L,ТЁ[7gx˶޲'o l6ݷlM͠bf3w8w?m?whewW67oټQ 3 >4jt\[6w}-[.3|>%gu@lܲh]7mW4$z>4Z7oݡ3@QLz=1 Zh&@3@t(D@L,=MN ™-huhNw9ZW=K8=w 4@}]{`t{T[{=̍˭6`,zh-h&=9rSew`nϜ w?z[o5RLBC%ѳX=ٗx9س?Ltՙ={ˬ"zhihޞk=ZT<;tO] tMV>cZD7=m+lLtisfFPL,6`ve#==w>rJ@ R NMk33ܚK{z̝ ׼#Kc޽sgsF1: )Jgs3@;@4sޞ]5}~3O  <|O{\Ut "3@[*_LIpD?s0yg3F,v>HTLw7?cHq;%T>?xLsf ڌ:rA ԙXX$z>SG 3@;v$hԙXX=7BZ8#eۑh8蹽)&`})|(!sD @}٢FI,}fY&:D'("'z(Q 4@;SL²ܠ^&^>'@j>KLhHG4rfY XhKsX93@I1: E`L,ϥ@}(D"u;'؁!B1: 3@s zn.ghzn,zzΝapwXH_>Q\辑8:@PL>&Z&@N=K"I,}Q]Ѹ9HhHci -Jaؘ @{sVGZ_R*t_4 Dg|znjz@OhƜ( Y&ZyV::Q#$z>DHK؁ >HCYK&Z@OOLdF<=:8ZE>5x:RL>Kgsj feSi)|f8E=7NH؁;GF!Y sjaf}c;Ù`EAShǞ=tRlKg֗&y @FN\XrT3=7(|^34G?3L<0'O/?Qf>Kg@@{RLpf&!z^{hh7I,}蹱^j _2=sk &H i6&֝uTkuc_^0+f@:mS;nWEM@1:KsebYG $ѳy}@wen7>{/\VN PDCΞo~27\OO~vK/]_,gڝ=m7vsƷܲ#@j(|n]u񧗎c{npz~Ξ?гgdžRhҧHA0.ϭ?7?yxvlҤ _=K[Z+2Wo, ܺ+s[|)|("znl&sm>\ٺ1ۥ@+sf$ѳ`bah3лtݲ߸򥗮}饹7w+"z(@wwew.7o3/=7hK&VCs5iG/u޿ѷgCg|I,}nKu DmC3@s@tg^=KiW&F@@c(|hHe-A0P;ϝF sH=K;y)&RgbYg"%ArfphHg" @4)D@L,ebDrI,}$ѳ)&Rgbi3B)3EP7=7AYh)|ȧU/$~83[iQ  3лS?$z>DܠZp4D@L,'z"o~& {u3@B3u@4UM%*|>K1@gKg3@3gV&<gVF KY s@4 U@L,=òL,F3$=7)|&hHv %ѳ@й>C]g%h6޹ko;x[THS~0wW5,/=7h4@{m}df˷g΅#|]+X[ԙX= X]gD DξL磬9=>gsw|f&\:ePMR:gJ м޺2BOrJnh>ԙXsVҖYLVޞ)ݹkoϮOݹc{|Wn#&znDP#3kC дf{6)={w?ʫ]LO]Oǃ5@+PLhIs<xzn 'wOˁCm33ػw2kNV>=7 &v5 iH[6{\'=-,Ԯυ]5JP PD3zzΝapwXH_wg `~8ny0's[ D@L,{>gO3U XK?U3oą2@3-~b" u>PdO3뫮zpddzB @89|r`Q,}9eޢ{yW=66:֍g"=Tꫀ>~Nh uĒDgh?4@~1`=(|9@O$U''hP7D@:jbsgY}`top/X>Úqʼ%$ѳUW71>0R _=Ki9ӃIߍĄj iiuЃK?}}z6;DgXGN7=7huM'2gC}IBGH]L,zn@KPL;+P$ϴZp t(Pb" um0iKu87k39sSH X-8~@닗 (|قcxzD| Fh D@ZtbQ O,B3N,U=C-8XF=K"I,}@ޠ,C1XDEDt:{@gǴzn@p|A7V~:g|znб-%l)|=j'wMG 8XDgt::o@D@|b=C+KC-)}iP$ ҧ %ѳ"hЄg>Csk렿v93PLn'=7^I,})@7{l<|͖\/umF PD W&~dkt[&(hiznsRkksX-]-,,h5;:S5R )#G޵eke h] (|%ܥb" uXY O,%ѳU&M>h'g"gh2g>x @e@=7h. ::S܀Q1~O=s[qMF3@33jǻtD@ҝXY O,܀5V&ސԕY-1~֛gX{e_;Vp v(&RĢ@*|f`nБ\XD\hM |N'ѳgXh6q0B=ú@b" uXY Xx 4@k=Q C P7@V6Tљ?(|f#hI %ѳ>ʟu`~f+@us\ hrh z(o4+|]Z&=7tO, UEY -A P+@O,g"gh9hbz\ hQ):)|(ZWq;% 7ԕN, UjX>Cӂ`%ѳ Dghih)R?m֍@㔹fC3@>=7$;` {u3VE J v~i 74@5ʟE=7F E3=4@EϪ C*R "$z>C'@4Ji3[@Zkb=C@/>D܀$(O"bg VX>C@@S N lzshgקrOړ[hq5@ T)+Eϕg iY L D޺ Gy\Klu=ݞɭyGo 6)]qA̖@O Hٗxcρfg9kQT& uM5$ѳ(UEƂ&h]*Hg>3\/{͞-hzg'z+GL,@qbsX:/B9qaQ ͬ>zh3Q,}UW=1s8^@R"Is<x ըvn3[@xbIg3b5йapwX߈&@P PD :s]p?S"t$zN7}V n&=7@W=haZg ]ЃGRJ}`xtP "@#؂cbtD4z>-gY zhX\Z h% -|hEgꪀL80G5]?W֒@4h@@K"t5abRĢXKhm)|ȗDg`@O ;.DZ*Ehok\ D1}vf H]*:҂hznQ /4ЉT)BY& uX>@ uМY 2瞟gO]zRv$ѳhg s/]oN^9 hRsVpfKύ|fn~?~ZiPD3Мfwmlݳc|}{n!gꚰE3 ܵ[rՉW$zV̺iBI,}V L&gCvo˟{}gm-eǃJZWF&`P&^Xlqw^w{eŹ-Y8nD; {n4ԲgZHFW6s=ͧ^/:3G$\?9?}x4O Tk?л!Xxc;'`|y;7d&% M,@L,g+lo)߲iwwT=+|Jk2vc<h2UPlbRWvbQ tQE_f?ͫǟԋs?Ӊ=7֒g /C F\ҵ|k3aͫ}l}?m{mP5 PY>;.XD@;)W,,@/,<|s_oۺkKMٛzB׎ E5rY3@D 2(~ة}o~=7UМZ:z6 &=-@x䥓/_מ̓oڬHEh;?E@[*:p¿9yWn77 *UTڣ熉H@+@o~`ߖݽ)^ m=+3[@+@7t޺ooX-=7(|:G'oܴ1&D ڬ^R M,@{xBP PD3Ё@{RL(,}6+Dg4e UggX}+t<%ڐ`]$ RlZ熉h`U>Q @F1$zny P$z^6} !JtH Pg"ڊb"Xzns4P,|t3cB99@M>s`Yh}(&ILM,@Yab:cgJ>Ԯ8~1%D:=7L,@>tzwJZg|Iٙ-hP PD @@1" H熉@h $z(`@SLF) tt #&3 sP$>B 6Dbg"g Q3[Ёs#Xh, (|h4A]>х Y Ig %Zb"`mQ/gMύ|& =)|ȧ@-I1TyeL,+z6}$ѳ =7Wg==v`gXp7SLeWmI uWW==6<1xhpd$31[Xoznigg}}}h %ѳgfPW=888112ccy4ABsZL,6'z6D=xD\+#gX{I,}4C JyLȉ ^kF1D2@h&D-J@PD3@%<Q fkח)l¡@޺g]{{v}ꞾG{3O{>s[L|j܃K ֲڌb"U=KמS=KډMDIDp{0 g?mQݧfx omٙ-J>g1@Nj o_*'&֌b"j|0Y L,<ڦ熉* o%1@Cw¢g@(&=$ѳX$řX[EOJÿU@@%g" :M}9}}}߃cc~@1N "mV @ 'b ,RܜقD>XU_=rH_Ν;N!,Q PD & EhEI,}nN&X{msP;s7@  @OOf2cc}G/\876QLDks%X`-}3uYI k@gR /;!}vf FuЃGfw 3@y>s꬀]|…ѲRLDKgs0@u`  @ >81*t3@TWEdž'ODϙHfb@JhQ&h,|0` @OO>#$zٙ- u/.B88811\HhNg"znPz@=7sx" z8sEhSIs<9s#`bRK!􍜸( mF3@Lt!)&y(|n&H焉`js]7Bq3hI,}$ѳA:V`Ɖᱱ;cM8USLD3==Z龾hzn%g`5(C&>>s@O G=M'Bb"֋6fb=WabR9KѰs)Mh1I,}@㬨@DmR @C znQ\#gu")|ȗDgM D =&s9YoM&=7X{Чw}-+h4s2@u Wzoi]n]F(yt-+fhY zqB=}~c9DϫdbRיK7v_٥܂8KUM GןxcE7$tA>2wn{E`!x >4=U&;\-1~r$z>DY @v…o6Dqf Dϩ3䉥bW.x 6ws4g^Q-8 Dg2>7H]O,[tec`x7Hg" h!yͦZ-8 D@=K)BJg3充|-@㈞׀3[@L,Gr)HEu@_͙[0XsN352!XK& u&@knecr EDZyͦkrsAF$z>S# mOύgbhZhh3@h ?rQE>C ~*~6IϬ3[$z>  :KB R F0hchQH=KY1 mFύf`bRgb'`-(|pΟBP @@@ %ѳI8RD Vz`E>=Ё@pI,}&E&ZZRi& u&Rh$z(N&RZ7^h/&Zg@ZznIgsrf H,4"z("zDqbJ:se{n!L,=7ZHzwJM)|(Ji9db%(|n-&$VI,}$ѳ9UHڞ%`zn^٢iѺL,@L, F3@;?>@}4WX灞xShKh=^L,4!UϭIJ,4@JfϿ;W!XL@KHlznrο͈i&J=K`yg2Pgj'HWa~Y3mˏ\-*[<lI,}F3;3p`,eb8]{2޶g%{v}*NvO*o?(\kL L,@L,u+DQ_==(T\*ٳ_Ltՙ={ˬ5 f!3-šQ9L,뮮zpppbb"d&Ƃ5hPq3 zg3a s٧{z9krFx tX0 cUrf^DY k΋fFN\X!zv=}07}gUpÞfg9kN%z9EC;Hej 'wV24 eaK]Du={|f5{ C:EUK=x4.y. h.)~0ޠ^3>{rrg>d&355๰:t 4sM+ >ӢL,4NfbRgbY:[p?/R ol2O]oapB?Hr jÖ:;Mv džr裙c~X4سaް^2s&psߒ>ӺL,+1J@OO&M7GF2~(U@1B "znqf He '&nLOOrz3F|t]hY Elj 'a祁ޖy!F|iG7 ϴ Dg"& u&ը%L>84 'λ~0 `E =@Gfz@\S y0WXr{xhm$zn*h}&VC 24艱jhGM3`>=S qfk_|+W}.蝻@ #zfI<x ׂ/S؄C f?=Jg3XԙXVO ZԻ̓Zsk)ϴ7 sXS}ZpTP"e|xe g֑3[F@ D~^hU~ZY`ވL,B3.BXT [䪞{僷EE{pB`9 %ѳ9Ē\H_:{P4Ǟ?7@wv7(L}9}}}߃cc~]u;̓p%"'t XԙXRTW7==5=h2sgg{9\.=J$DE>@/9qb/kpbΝc}'\ 1 [?y`grmܕ9uiQoFSN1>@{[A bx@h69 FO g @$z>l3{oP3@3t3gX=7 Bk ]ox@2 豱yDTg4U@ !7?fWI3QLgRgbh ucj'wK@$z>Dmg]9ӃIHfb/V^u=s:\]t__E'&5U(&LznP& u&/9q4\ =>h@CxbD3eb4gրHqj r ]\I,}1Ȍp`fzll:\pbp@.ڂs=CL,C3PV(zp0\ և+=EznQsf Hj &&j鉉(zq(|n~oh$z>@[?;zt0Xfdd0hmWVDϬ  :KzL_sh9 O\=K"zn9ڗsaL,J3P4@znQ̺sf He )|ȗDg^htS 03MIJ6З-|?za]un~~a!$ѳ z觾{WWc_z=uѯ\߸x$ځswgH=(|XZWK9/|so|?za 14ڦscN֚@ǃB /ׯ~˗q6@_|)^ْY |=3Wa%/\_ߞS 힡A.3MIJ'_>W+u}~Sg>!x L<{cS&W|M#o>#< 87VЙ>CC)&jE ir& u&5V&tF{7u}!3w +gЛ7d7- ̧}x/fg` L ۻ6mȎ/'^Coo޲1?[2:{5ͭ'ѳJ1Q Ig3hZ;5s6\ݽ%gdž`.G4 3@3-ę- u&W&o2orʍ7ES/]Kz¿ʥkJnЦoM "znx`M uvo-gʥϝKZ?/,`|}oY'W kL1QsVdbRgbYe wIixy[37n5(ԕ7lۖ֋g"g`e[6ƃ6ve߽޹9)YOg31DMK Zmٟssw;nkeOK +3@ϙR1c~{n._ݕܾ~tSM@3h(hՊ\ M=;67~d{zR N1QSIg3-IJo߼5u۶3wiX_ &T-޶){?n|֮m]gZXۜOg3;DMB ډ,wAf"z(sfk} #\znQ 4?4>CRLYL13;4>=-D E'ѳbu @3=Q "4;4?DkL3к@sH=Ki{{F8)&!hhhg-q_ h-րt`byfx?44>Q 4&?ZbRLg274֒Y Ig3;>!V'ٵKtIȵs>݅}^}CLA(`͞s|2;?eI^o`lʩ\ggZ:fn@4g(,@p KѴCd@gffnaP5>C9h& H ) @ѳ et@@K e\ @B3,d Na)&4gfy,}I 3PVVM ף),%*)37Rh(4g'W55[@5m𶴷t}PcH? d Na)24@ 6Xdжj˙Ol\rz 4@סֻgUbW>;w%v:4I\A~~ 85x#O47Ͽ90pWhXphp0ְys<37'(tƞfڶgүlMI_3Tfi|N),$ܙwCk~lѰx B3@s 5RCۘ]Οk<{\mѳГYk3ُ̅3;ͧ4>̅wk꽨/ ؅T;J_ g&DK=Z(,@p K: G?G~%՘=9tga*d=3@ U(mNGGfffg-ׂO><=-}&^+"y]d VE3Q+G7gX NaEГS٢^ ;@&}^9)[TOR5>EGd9];<8{SY3(Gg(N>/8C5y 8%:u@F?̀> zzt:PtvT(m@7;h|h!zf@/N|m&1ѳhG܀ӥ@zhh G~%= %d+RгIlt\fn _v@ON;^ ;@ZYY KNaWGd9];<8{gg(N>/8@E8*ٙё|pPg\ 3@: '癩d'[k7>gk.d #s 84: COs 37P~h>q3rgg@p3D h'̛!&y edL [h[>zvTgtfntUO4>C),%#^3sY=KG ~3 b3D R>mBBmɣg)37s!u=;+Za PydVOgRڟP4),IݘqrjdsUbWpL6 (ɇw˞P3@dK Na)Տ*3s,L=3'_yWd?F3 ^PXTyݳ'}!Ug`-lGp4hB@Us7g\@p=(,y,}z g^;YKj^ )3T#s 8 gjlY7zr3slf=;;34?%;~M3 .37ܱ),fdּd* eZav@{赓#'O?szv>ɣޤ37Xv?6z<;]K6 e @‘9RmЉ_uX3%b@ ]'4T),y,}XJ@PiZH @Esgg@pk,,fnc`V/_og4>djV?䓷zҥKw4%PnW*D3ݳ\g?>͝/_, j}U8ʣg3$G@p K-@oذaxx8[42wyxZFpڐ-j?X @\ 2sY\gxlUG%o|KѥTBaݺuO Xh|h^Z9Nz_Z2h(6>YX4>{mЉ4 w @ѳgT=K692SX*zݺuqWAGfqP4gg:f-}ol Sؙ͜-SXV RePX@At@_rl]r-wq 7H(S,,gʕ+Lno}z+5>Α9Rqmi|7y6l[Enn @@ʕ+o;ED37*? Naan @,rt:y֍۷ @E.),om3;a?Eq;C @ѳgԕglX.ްaÝwy lܸq&oc%ra @DVqƝ;wn޼Y @E=sN 8 t"!}hGz4Rk=+,@p BN CvOlU{̍' .RFXr@\kh#7Vν@SWn:l),@p Kj g:`T5H8XR="}VXzUGp \@ 3784tEg'[@p 2gH  g@" <40zr@@1sCa&X8SXXVP&hX+gPAyܥYaSX!Θm@8J Na_9'[I *7P>h@(hX gPJj|N),a@ l),tJ @ՉK1gPLaSXVA @= 8(ZPVh*837 37g䥚`E 8NaaY=k|@@Ct=+,@p "ݔ| vNX 4-DjG>9[- 8Naa 0fEGz82gPp1F vh"7>gkHgPX˧Ra G3@ G@p AI=KgP(刞_@XB@37 Fh.gPe), {NH KsGg)kd NaSXK @e"%8+ Na_gX8"84rdN㳓- 8Nag>3l$k8nˣ %hzj3TrSٙ U&4>d Na{tQe2!-z@ @i&Ni|^94mɣg3@9K Kv]&`eg`Tf"hQX 8^@4375@PQayUPXkPNzL UT3XL),@p B .@Xh*Ǚ?4=),'[jq)}+Iޛd (54@h|/h~itD륡lCR;Kˣg3hq oL}sx#Cn5vĶ!wX3L% T\R:-QXv "(wK>=7|wpι8kVfn"ܙz`~́E❆CW0DTRX`yh<}geΜK5Pbd .),?sh<1:|5?'3[4,*@  l`k繗muO-4QQX 8@W=S <}h륡3ޭmk\؅T;@eN|#ovV{,[{&{Z9 4>/Mavvz&3@l), V̍{8(4%̟2s 8Na 5@Q (3gL=KHaSXlbtw-H 3mr{&Hu (-\;ᕣ=7>gk ris4>- 8Na)@Ɉshƙ?ɣgs),@p Rfn@̍% (gD̍(,@p @G SV<4ᖋ %yEhˣgstl),@p K_h|nDP&y,}npO;NaSh @837VG @P4>@h|^54@0y,}.'[@p Z ˞7&Fwg O =@ѳy-DO3}gF(,@p UPga 3H\V @ei|N 137舓- 8%8]"g(w94>W),M @9hb̟=W@\5ch䖋 eG^@\MN 8eD"*Pfn8KDU),}gFj7@9 D- ,}2L(4P]sl 8SXڤh@ѳPI @Lf ,/$*$o|@D' Y#,̍(?;3nvΥXϚG?z`bd NaYX2ˣFL_J=;;|6VOLBFd-}LgõWg?S+Ӎm3Vau37YpsNj_rg|un瑟=<- wy+Փ% KaSXfy,}(gn/xFc>#v>{varY_)Ԟ}Gd:m~bzǎ;/[sD?[̍N6;Lm4q쎇I'ο;v6 |~f:eYzj4'[ ϱ@PtnhGgn{"zs#qnysW^}`CjIysyzDcGs ՠ@6>t2 ;7 R=-R㦟e[2o; d{48-@KF @i&z+c7(5w,fnJFsY (.],֍TtM DC3UP#gV'y疼"_'GgNa w,fnT(.3$t)b),%z&4P8Qeh Gbi|\qhYL78|w,I=@ѳ4ŢKjܠ^=L eݔ- rbh Dbuh|̒@Oѳq\8Y3'}s=hr3s[!3@eO @!h.+3g:" XQ\8Y4g()4gFh|EVHZ0Y (~lk'ϴ?C-+`g@k̍/~/cO|%[@i|& 49v?끁 z] v'vbo|NM 7n} *= hv[BྙOlv4sju2h)o| jν֯_w?fktպɑlT^t) 71yl JKhۖ-[><1wϴ^gۈ_/JVxӨvjjj֭2@\U`.^]]2e10pQ{ynGepקE ۙ ֶ?O8{Jűl(ѽ5Ŷ٫'-yaT#S*bIE?gw E G b7Xӊo؋/_wlϋnL#ѸAlcމƫlݺ'›Qzbe{ y#x>t؞cJ#q{ةc,-!EGגݻq;4@>跗< {h5(?PP{6V;K**ةzE<[96//m=0 /aeڱ-+ߛ^;7=B޽5q,\Л7oήƍ_xᅧ#Qg@EL]>5&ޯͲ׏կ(4BOYLWXl ]x1]xjjj֭22(z9Y׿/9xW$:obɿ=.e[ӈ_]cޣ/~7/c6ƢWpSOV4WXZUP +ԍZh3Kāҋ:u׏M䟺E%9ٯtљfىeBLݓMvm^OZ@5 X~}… 6M6oCE s%wҝԷ@uO>y=CVdn˗/g[հnrrrdd$[355.]Jwj˖->ƍR._0[ŋul޼9>55ut_ Xeh#8 4]!+t@hB @W 4]nrrrdd$[355ՍںukryZ4] XݭҥKыj2w@gB6ŋ?0KIENDB`asammdf-8.5.1/doc/images/cursor_bin.png000066400000000000000000001734231502633300400200300ustar00rootroot00000000000000PNG  IHDRY0sRGBgAMA a pHYsttfxIDATx^|}HQEɎmIq,cTU[)]?k[:4umw$ەn\M5{AY5t]7Vqj )Ē'~g3` gy7>L"jEP@P/~1^?65@NAt6i>ةzEBkIh+[Zֵ%6lYD`քZ٢|M۰2ϵ+U2GBKubRi Ojh]B?_M۶mmX%lY߶]kWlM|]kyڌUyOg=&'5hw"5FQ20ҧ/uь #!ʺP#ѣ;vp̠D1K,CuC---sunZs-WwɹbV57mi][RfmdF ~5ɢ?m(|2ݩY}rj#&"(`,)3h3} I!._ymkB[nU⵳W._[|c[G_|u[Wg/^soۙ7/XWWR YefgՐR Ldm'INV8f;`#BSAW/}}ū٭ھsʷO_puʵk']s+ūg./Zxҭ׭uxu+[\W O˒bIs/`ݳeG2Ыe>oVE'L(v<0Q/\r񏊍 鳐O_zܵW޾uv{ϯs73_ݿN^xZ"sKK_w4yRwܱ֎Wد(KlEc*l]Wٰ(b;ʌ8F!|?KgZantլkk߰5_?}roɖ6/,_vG7y2e03RbxfdVv0f%C5 dhsq801h{#ȱ}6{qT)ЯuՕp+w^6sۻ^Zuu^X3xsn~{?z魮ſkomS{gT9f.OfJ, :RЖ\x[?Y[Ųǁ3h?3.#5dV5KYUy~O-oW>?lKW~-dZ;_^?zM.͌>dXv@GӒ3#]f4[E>q29"{LC%Qqni x1+OF˾ztRm-7aGhlF8}6T/VRV[ݚhkM&cEK%!?Z]Lig$W|_K2~rDSҞ4kt%!'-􌹟Hvlnt6WmQjt6e,#pZΆ<7g;P z|@͎`fj<$ #?.W&.-M[i]"q^"q^u4|> f,,GY0g{@"h@U h@U@P TE"ͪA@xԐo|;k44^{|Xk%ş_MO>M jQryk= M0WIˊ֒V$ֵkKlXٲϵ++[ 3IqRvu~ekB[niiY^ʵKڅ٥,-8nBlw>rOky0[p$^-FJ?(~w>o F -6~ m;ߵ}UG޵׊?߹-~Go^Y-뷵I.&S Ԥ9ݣ}04js2*T2Xxl顿 ? dP|0B Cn{Ɵy}KK˽7vݸ潛Vܶqnw|]rսy͍knZ־R!92I)isz2 l2FLL5B`Y}&/i =3tuI2+(S'2DxukeV%^;{kK._>ve~W?uuvyk8q!=μy󲱉HI&Q{MlddNy,ɑ|b?<hr'G_%kX7-/\ɋW[׵}o|kN&fjE K^{Q* bGzrtDFew,A*ݣjA&L`9ۗ#/3"g& FrVO۰IM9̨e//~:P]3^b}%_|1M.f-v,KW.~?|| /ܴ|BK$~xni)x.}ճ6xe)klr~!5]I`rr4!NNN&RcHW lfs%3|AS}a#ݯ\ F՚' gFRp}Rbxtut%N|kn}D{o2hXjFu7=kNsZvήVp~Ć痿ξs]Y6`A = }I :WWv_meRV{yG_S -[|նym=oo0ն|%q+ٹΗW~+ϮD͖eFSGr =4ʤY{i|UpX)/5eÐR۷EdZ2W]˿r(l5֚hMNJDKB>~ݳwϵ?yyEҦjmI,lXQt6oK{2YAw[_m'Ϙ#ӹ bH~p2ei^Hܪ>ut#"---9<򤺒WAM:|ג#䨱Lj2CB ^ BSõYM[׭nM\ZR#-2vE59nE>' jh2MZ" T6ge> F$;L8@dhěفBJifĿhpf-8U8s @gFьU ,cR-lkJW6"c]qC/BXngV<ŏTjvd&+InmE-ag;>-uu!Ĩ(fi+V%\̡I_uZLEc-"՛x<'4Ɏz-51ڤd0L 5œѱ,Rӊg;x2I.s mnz!Ĩf@eЖ35ًeB֓\ݜsWIz鴹)3Fp&gCw 7Eb)=Ky{Bvyw+'_C Q1QҮlh,*e+hYbSv1<,ЕSlYR?&|k$5?i!F~ȧl^ZNS,b]>l3?]V3䗔=JA7bWq O" ,T:ُxJ5dK5-і8/-\Hm1 FD1eXLeI;vlj M/|l}U⺶iHȻ e-ՖҪ+mҲ~A_#͛7M,M+wk oWzcBWϧzɿ9Z>Ā}ND4BF4C*A h@U@Pcǎm߾][XXPC͛ş0-,,hV0B7:Ac5  v6n(t [|F h@U@P T4*UA ıcǶo߾ TBM6!ӧՐ7?6olz<3>FjeDF%\ KoGv=1zF躺fggjh>A qׅ8_;WZ&Y\3ƫO~E UWgPTUrwOt Ψć|!_wtW#:z9O @@"G^ma=p1@;^88?7lXΞ39Ըz[K'|Dl| 6{{1@ @N&Հ=1f Rjk g^VLWǯXj0lٺSĈQ\=e@f269:ҕf]#2@zfСך gݩ`lhXw?V&''.MJ&ggp;312h1/+yQ?փi$(|F鴖J$RIY?TP_Y_[Z~^P2]#US VSPjRݟJ~cxf(|+ȝC͈FbD<)Ԉ;n+3w5)vCS 49 QC3m 4@v@i>Iq@s5?d @P fȝ1yXchhA ԘrҼ`;-Nn N 9Q fSMjVF mjRhN@ݟI&RD"g?bY:7-ZtO9rZU*e." ;S٧vXX/L//Q'ĪIX¨กz@lfLledCMPzI;vl O5-Tj(+? >,N{S;mAN`.dn;46mRCqQԈϝ &B/WkvvVvϪXhI(>vM,--3J* t\DW"~y*圯:OVC.6n(\XXؼy1j&S ِƦ=GQBDL,remư,{tbL}+.K 릧;:ާF3ȯml.6aYh-, NiƼcÃl}\zT94$k[`$0Y>Flerc?;z{;.o@VƦ{%_ Ƥ⅔g^'*JPkƎ9FXG>uOt! @jh5*fP@OR#3YtUk󮱂|޻B%鉎y‘=󃹤V-j CrDmC.16f]]n`zLOsג{ N:镥~Ύt\7P|{&6F^v 1RX\ּϲiIEˋ]7ӽtI|Ri{>e^:68D'--{+fj H˟\!ԣ\z~>7KMOˈ\XϟJ9k9QlҨԳK,߅"˥3;Ęå_+YNW4ŇZ{GzTb~z:3P5ˑ_[<9oz0R6168&>׬#KeN"wyyW{$dBDĈIQwz5ݰ됹Hzeas!CY=毄HwtQXV櫑~]mGbS~-?7WvFQ8{п:7:&܎5jeF&UأHn=vSimD.uHzpDZY<'.h!_هQ1IfNaY85/{lNd*>z߿?SԺh)۴/Zom7sA1 5*Ӫn=7nP{&rSe`'+ٲ~\ϒZi,Psؗ;1[Hy~R=/V☝u8l! woem@33?F~Z"˧c!YzmGё[KtjE h@$Jz_}z # Acǎm߾}aaALً>2E587M##lӦMj(.S=CjVFtjeşՈŖo'oWWA ޽gU# %术1O5V#:?'K͇|iyuvY_S8术:OVC.6n(\XXؼy1jhJ̨͎g]*,J@àFY1pC3(CQUB0vQ?j(z'(W4C%~B$1(s܈x)\@,vdn;@lm۶4lM7H eZDA Ђct$3JXBO[R=qםjt)wm7ad>8&@ 4iλ^8<>[{OYG=je3M(Cq12{{G7WA%>?;:ч@ΜxyQWV%;µ4Qf mc}g鿶=@=>7 htwjhcǎm߾}aaA9ˌv?=9Ѯtd*1 oP}jՐo6mRClHm}9KbpmCwk??~ESec1lJѾ>S,+屵Gtj$fggՈ{g}V4Q,<_\|?'vXZZV㨎ȠW%D77 Wkqiz9i5bFYraaafY^%Fatd*L 'U gk@kws<.o8z3VS^8 7XSZ:*?:"i%n6g^Ox#*¸zi;ğ]͋W+tt4QHhYPZz]wʁ/{gsQ Arq)}Ɂ)yPgtD@ t(t~AJK?zj-Ƞ9A ='S ԤJ:qPuW~B擙ĴL˝bߗT<U*4}Fݿ&GPAq1РГL֢thC4>4fo }Fֺ|4}hNFL3x0g~D D=[/ŰFF?@>#"gU:{$cMh ghNqxAT\ F?:>4hv>&A DG3_#|Ȍv'G3jL(Z ##7Pnbd@}vO94<9la:?G}S+hmJ>uZyPnPrT 9fJ^#nI g3.k,u%֢FsG?x,j9 ď=>7-2h|>e0O5;ұ't#1nX؜y-}ms:]^8*L+^teut۝maY!`;U/T|)8Ŝe?$. WY8-fWnO?a,ﵘXpx7%MUq;=h*O鶆DjvdQnB855uE5R ٌ$LzDo֘Nz S3IhG%gutYiv*^cm,Ȩԫg#'qͨeiqbS;&)oefĚq7O>Oc7=Xİwq?۳¦t%|ed5Vy-c ^K}sbzKly*u^\|T8hVu11)XJ!@nnӺz湀T` } y^Y9bݞDʹƻO-V*86庋*o'tu>..l0FF`P#ȻPxؽ{jjE"|lT/m,>JXO<tyC>6ChF|kpsKyawƿ;fþH/r}Ȩa|>%+8?fmwl:#%[9UN?ȅyƐ^jL1%syq ^2Zy]27ɘsmSv@K@vMHأ T m7[orGU*>MK>oKϭZ.9y`Ip8`'>WɌ>{zVnG^BewBIM8ƏwM&m'd!I|hlɤQ+uLƉM#8k6U3eF&ޝ-)6 am'jopфm71PHd@3_#Nb@OMM}?~=}d}ißDc-,5fFG'KT_<އOX G3n>1>LQo.Si=1ZQ]J%̡L ;_lWr \[Q=ΒdyލP3+'[X+}L9x 豞̚e^:˯V8Z69_81_aۻX?78mTfF 43JsrA+%opѧ^z{9U,2o\g~{_{zYfA>g}h2#]U)&Gh٢?-\sMfbqyAuӴ𽊏VWۑ,0KRq{܃4#7ˢf;l)CwJ|jn T(|o>#2h<0e0b!>.]1/~Ԥh03C>kz֗Tls'ZzdjtDi]^0JVi*AVӊ"1Bܢ#wO ԨAzV)Ə߬B>*p;z'2GgyTl!.ȷ bۦYG/xe#QK?_ ٨8Q,P"۶jT&8`XKZGjH-8|C&ڧ!7N.I!}$hho ^nPDmsNP>2gfUL Wa3Wt ?|vO33wߺ {U#^{_?UZTkl^ɮ|%cHW:+k߸˻Noua0wm&G?9 r8 w1\`Hii:Z-@P d+BQmڴI xg(}XʈNJsFϺkvvVV]δؽ{>F")?zukp术:`s 7n(\XXؼy1jV@'CqJ-zWDb<g[d5 1q v(kVGn]k3o^՝~Uk"=X[eDϤsӪHdh6Uja`ĘW sq;ִ>v*m^'?/hGQC3A#FPVڿsʟ?:oXu{?օtB 'JFU TO fP kV^!kk)\x[ ڶV[4@Dv@uA4f|x+@oYwmUso]Rrvl]zE˯}UzB Pw>hBϨ#2hm7 oZݶk]xn?<{}UMkWzZ ##7g (JbE*&Fvܴz_{1 מD¼9aMikO| ~hZyJO!!}FDA#R̗=tK"qūu_;qWOW) sq-Թ:;H!{ce&1]xg`@Qd|}iSփSmۗSbU_[yF~' -m{o\xZUxMSpiu=zqbP<ȝGiw8m=ݱbmcl'Q եTW?pE5^{sOMuۛZFtES`˻܁ھֈ5o8`7Vۻ8w9NT٠/&\98500չ% m#Ozt_ۺnչox\"h_ȯ3oGt=67>ν (=}yׇ7m}l'yQ TF3"(@ <~ǟx≇~Lmꩩξ:e~i-,h! S@˻5qy΂"8;賤2m:yܧӊ~0Tat/n TۖIP>lT)Oz?ȅyƐ^jL1%syq26FPwK)YߺEnE( khV>7TC-3  ! |&RC9f裏IPg`OܚeЧZR7sqw9*yXvsp0,w{lI tv} $w#'gN9]AOגAsܞD*GiGyl{K 8;Tl o`;FqU62GVn܅ kh>hhCOhFgb@OMM}?~=}zZQ׹ kdݬY;wgmk=C.VbUaVȊqYm+r]La: #`-sBU-vxIt;hVl9W5cN~;;;1d=sr|^ׯ`,/U[- J34"@$oGyȠCO7iFgtdjZ~Wr-)&JAw<*خ*WAvpMbR!tḀ\BO*>N_=1rC RQ<̀ĩCf[btxk_8;l)xZ<ޮ;MEMwty~W7ʟpȠ%>= СCϚu}{YɨԈE|eĪkˠ Quj+B1i&5㩞a5R+#:5bn=kvvVDO]ؽ{>F*F)݊9_R'b׮e5 x\}վcmJt>䛍9?{{3s[.9륎?؜>}Z ظqsaaaƨ9 ;xP3;v%}FjDP4nK\ , @?Z >% GXkČM3X|1C#,'n=@"}B G~A"^lb4!h<B1F*cǎeYj8]P./ߠ12QC5vBθK ER]ؽ{#~;A6W|?'Z[ uW _ˋ:ft>䛓qm7)ʅV ^az6e;v5?,MmT4D W1 OxAFۍ};j@@1 S i5`j&b4-h?ʟф(FPF3m7B %WG o1ɠ_>hzG@j5@xjD>e0Y*Vд_QÛS> ʟ(7ny[p\>y^W#}FIpA m7t D{4F&SԤ8-cNF//x~Li/:h᰺\pX-)qP|0rѠ/Y-8Zmyq-l2F _.W1*y+ի/Y;btr%b1[czI!\d,SDdRvUPkeFҞԻ),QcΌ~H >fYLP|0?$lf3)ҥ:ӸM<f>%WE EM@\$?~q5zl P s%n屖A$kKv8*%XUd|C-f,M N/JFtJR8mo.ΙYp^@ zИH_~Dlb\̗(48zoGyȠCO%_gNVvӌ.K%ID0Gە\%w0KhQmd0M$[%cзؠWS;v`}*3))..,Ͷ͖Ey5 G t(EN/JAN{}}lҝVGXqzj6h>Wa|4>֬Y3>>ndccc!FbV$@%>CIFA]vגQO*v=w kQxr4K-NE]cLAo|./[^>7zg򞋃G &ٰCʍ+y> vfqt,.8<҇dV\Eɯbf3۹i,Uvuӡ;3>tPXjcs4{-lx25:Ğ./G%u 4 "9l)W/o.(~̩s ؃} jF)oNamugm>\E-8Jl9G{M>A[n20 ;9`W͏#޿y=j! 73jyԳldilyQcyi,ӵm7pNU4!ux#[V9eCM_z9=W/[U@[@]ooj *%:B@ ӚIX2ݙa_a>}P+! (.~ՀHp(dTS~RO D}V7#8]*NYsL|hLӡ HPA7.#zhf#={i>@Ƞ @\A7&,|(qر۷# 7o6Ln== sdOAmB VN26hL >?lkkSv Ei&5㩞a5R+#:5*'F]]]pdi>Z vo?kҲJ O_ԑj!@j=G\J`)|?]7n5흞6o;8=6&|RoQP *Xމ#cVЮ!J3P%dG ބPst DPxG@k$44#zn(4x*#gӃ6m9 "kPKUF3PAGV|8 ނc~\5jQ| ނc##{:Ԭz:ZA;.۲E- T_VnrEutzPo@Q]P`=왟n?O<tvtjss}{uN=ef1Wjs_RەQ紾O`Cũۦ?jRtVG٪{@%E:=sXtvt!goۿ#G MyAX ^FBdQW1-XjlJ詩ǏWaRޣFSP}G޽}f#rAD,2NY &|~/GF'>-~_Jq238=ѭF EС@X@̧뭷>#FnZ~K' _%в7ȋ.C 4dB4({/lV T f҇S=j$.(/g RȠCD3 vjfQif͚q# ?}6<V~o>M3p)BgP9HX خʾ_rT]_k$D m7*J @M7:z{;5Vwf}СjYqgsA"o8X\7~j~ͽsk]'1J}>[pߍ\r0SmSpv~g (m7TCczڬySX_:{2KqΥz<);je#)v-Il,+%n9 ܁_~XmsNP/f1)~y+q#:(|P==G&4 = i͚5{qw3iaܱ*{9sܾ.]Ӽn?=]?},5O|t:?f%v? Lf9r۔._`(}AP DEel|&f K:yC--C\l0nNe\&'r%frU= Y֙;p`? v5/A!+)m^~LCq9!>Q c;7~ Mn{Mq}j 71?R>QrUG?#\COP>imkމ^KGzy. ZU ܫIxjG 42hQ9F|@;oPL@DA@ fT@uQrU/?#,\Ũ U pرlV,&8XxŽ=GXsj Fn _A e 4PcW1^(ZAS A'nhpE3HuфEдݨb +?kj@3 @gq.kjRHZ r҇S=D4PrU{?#\\u$E> r67]o^e=g1= VдPq׭S>n(}Y>1 k$ KK'_tKf[8bⱷ-gR ?x|E-aeˏ 'ZcW?+޸f\f;ͨѼT"/5*k8m˘S G`evڋ9Z8.W,,V7UG9žel{,^ʲՐb]ɵP#)܃Be9l _t+]55;2'xS7990)KkYnKD\2O{yף&8<YUw]$`%%i8.?c6=!9yQyLrX~_LɆs>mwlZV[lT)O:CȅyƐ^jL1%syqd6*ο 7?X6tC ey!v PrUKϨHAMsqe@ - m׻V]J֚XזؼeMm2WXem7޸j,\o1G}TM 4=Fzz֌u-Cjی^Gw9*yXvsd7X]@&6'窢ΌY9=/_-Y,O[LS,xT|]Uҫ(߄|zTT#Wڣ8񖙡VQ+hGeyJO'2y/+U|)9>1_F[UW&! ]MX@*72h 닫C-߼E-,eN_7Ή?դ"7oUC5f͚q# 9}WRLt\Eq:\xDqXWێJκkJiZ^ū߄gl)#fuUԤ'rfjq7S\~-j_;l)Clo8P==B_ (|ԅg._  f.YWjcrM3S|Crj3/cѕSE n@M5Fۍ**@$~a+rEK> ZEݚ5k^5ӇWg2+]]JtV&%*o[)%w9*ޒø;a49-Lt~&s{ՇAp5ێ󷄖y7HiiY-Rp0zWr-s䱨AB{mo ^]p7߶\8..O+[Y{w;;R7Z^#9Nꯢҕ8$GAwv(F3д"[M 8vۍ͛7o] ^Ytm $ך9uSN]\\4sO nܸQ رѣ- 4TbWhCړ(Cg_(ư6mRCq1JV#2S#p{b15;[7]`{g}Vs:\'b׮%c35R|sVzV Pއ;ğD~h^?*k=~<OVC.֌Ũ9PmxģX;WgC놶|ܒvni57ofgR03ʦ>}P+oLJG 4HAS5 .ZH$Vo_ؾژEu?mHV߳I5ּ>}SCÎ5@,yV- 7_SX+[">EUmP*n u/~ojE"y_un\&@##}`cMۍk$ 7!P nB֦nڵ܄0M㎛VC 'z_?NsJ 7!Pٟ eߐm V?DY a&cϨ&OrT)|8b ,5Eg̓l(}x<գFFU P Q g &C s3v5>FjhU͠i(@h.?= 4-hamCݶE@%WFj*Ћ)|>Z ##7ZmH]w)nf)q۲Z _#CQ vW.>}P+ܝwߥpX޵,~jj-]q8nZМ(S(Eдy[pq/g_Uwl;q9t'Nn\&o]lsC_Z8$8nZ"+qD 0:;֭q`NM RSUe)HҏT;E-V+N*ޣbK2=/ieYjHEOEZE |! `β`߅}1oĪk+8]J:`En-%RwfoIJm˹m;NM؍\v{rzNÁ{nO/@ϝj߰Y ?{܎xJ1eIf>$>!j"g]MsCkACU#hfSSSS/^T#{jJ윛zQv|y|ǵ ST#/qTr֎y8<vJ}S))`ۋ"pnQ;T% Je[508(m@Gӣ;_RG,-2έN§љ?GG]{Wl{.bރm9[fěY[[^[yYW7oyy ggΞR#(ގ-wUoWϨ ZMs* mq Џ?O<UWL=5@L.\gGfD e(*398GeM|y >KJ,I;OQY iK?$t` _dx?gU5V,Y+,s $X~%̩R+)[ 1ҋ})Ơd./^9#S?S wZ$xlqymzc8wlC[n޺e˳rKj[vg0>z뭷P>?jR%T\驨504槮k \܅]J%)V”\(u -{3dhrC?#ܞ,XZd|M>ozWYz<(w+}sESt[t C ;,R(hS9RQ5}g]e)>sT65^xQ[J; 9}1vhۉqcmIw}րۧoa>5\Uzbۻin !QǏ7ׅ>BsQ#l)<2ȊYwRy=C.VbrSR%bb2@V[+ gxEmUGmУ֪԰xS_){WGuL֠?k9}˺|>8@ 2AU*+B^>˖ۏubgggH\Y3(oo׉E싲yqiӯ%'3ϩ֊ط#O4 g_#ŘGm>G#*$&-8[oG12g=DeكEޕ\Kzyjʃ+yuOPLd'үM)/ +XKQWxˌN2G1Y>/@[!PwjϯC4۞Oeԇsg5 5}X4k֬72豱g#DH/Fs}]Ts4}ud>|}W7R, QєƉw=/}`dup-X8x"V,{ й|Jd =y޺ÖBS쮁_[SGU@劋 >&f}СpgM,}YɐԈQ|ekˠ QuݪLš?F }fy3:K˻dtԀG{˰=ނe!1W;)|V,_֛g W K ~v9fAv5@ F~?KOxjcnM=+YVu~~܁UjƑYZe?9Vb->  %\ukc sLw.h-8<_]*(O~??F2F4m7@v]<gxU-Y{U#>߼Wh20UY*w<-V %w9*ś@>l sdqQ۹-wԞzl;_LW+!F| Z5Z)cQ>'( *vj@:;Gng/c+_[ѻ^g?5wLx3ҧ̭,ͽ \WsA7\_Ɣ|+ (WqCI ڌ96鳐8vۍ͛7:uꔱEcJ>_`[[޵kѣG%رS#PuO=P~L_.Y)wڵk{/c6mRCqQY,ꚝ5&.ݻw?jĮ(cʯpE صkbiiYKt.Oxt7f ŘhGU!ߠg~ۼ8ǭ!?؜>}Z ظqӌŨ9 ć^:ǭҼ*J1\svK\@}V0e3B J #ui;֘2PK*۽{VC +O,s.ODkk 럢v T~srw!OOy@?x#zawƿx:L4D3hV@tq lAn @yn45R3͆5l&h҇?{AP A (_>Ӄհ0?: JDhmgќϦ +Po?).|qq6톕z~lMyzPW9ֱgOZ@ (&>~cQ#`m7|{v0ѫ+q74n .@hD3-|~FPU>@Ngݑ=@@mTX<JV#qQM;z{|*\?Q !n ;: !@k$Tm7[,4jFTZpg OğC8(l >W1UyCfĈz~l禝ϲzpZ@ Q MnP 4:>3L {'&zdQr5PS%m7~bF6(F]5Rձي"(*F(*ol|ЎYc* PS>p S=\ogONkM{Qns %Wa@(>[Q e{BwMAML5"}Fh\Ũ+;:97A3(ݠpn4 4'35Q85> n@c!ʅVAG _#!( CD PxG|@ P.߅f8( ϨhĶA ׮HϽ|e2h5E 4FiQ :  >vJںKz24z j (axyMoݒHc\kfLPႇ ʟQGNW>[Q]_\(6?5/kY[g)@3j3 h 7\g v@m6WO_{N7No]"_#EcS뗏_Qu@ Z{޽7wر\u]D["o^ҵeUp"XݚX @U(F}qFݠ= 56]*R_Z:|kڦխ+Zf~?ԕlnSH0Dy<3>FRԒ./}ywտ߱\wW~݊\;u#4JQ [>[Q  ~}Է/+_:~yʖ[7yϿwսYuK{k",hR\(|F p7^WǯOֳW |?qE E@UEgjwX٢mnr6+j%Wn oݚvuY_Y֮HqTOC͋5ʟQw|: Q]=\M+"?7i~u}_W:[fPpCB3ڈTsOqf4+㷯=~~9ʥ6wR3(@P"h ݈>GEǚUj"HaꅫDi4PJFUψ漊SO\@ >(UB4`Eۍ8!G$A Aۍ!xf4 ʟ|m7j"pI>Hf<<@a(}f@5Q >ħ+|.xy DU(5F4c0>9U3>/{k$o>#cn<搨@v(FSi(-8rPr4:b7P>7hC3ew?}(5R@UjfC ogDWq:>G EЈ%n4'h,Dc~e+j Nm7S=Cj@ʟ2ghAs#7FU,PU@T@:ʟHQPFG3h J4: m7`"xEψf"b|}1kQSxh`C5,hZ\x2P D "h4>#,fф_#v1×׎+D @RF3 ZH>UX=?_gDjg3۹i,Uvuӡb(F4U[n!}7=?tǞ#L"c(}x<գF4;>>#28"?'C%=@-rfB4(;.A {왟&@ ht1Q`cc&zWhȣ EШ17 PM4@Qr h6(|FЂz-~_#v͆/낶xg(}X\Y}wz'-8d>*PU>@T[ӶݨˏO,5ntv)j -J>Tĩpg5@3?D.P1=mM X*ʟA1itFXh @ϏTw P07 π5@ T[ u%1&@3. EШϨ`|owwmz G\qb Ϩ@too|/A1ѡF4'ʟveq4_WϨ@ 6=_jj`fg -K/|gDPc}D3*"h nxO 'P D3ڠǠF(\ m7P_[p? oO~55DFC|D +f]828D@l1?oC TOC O~@yhje'hTgo?l18爺{w҂㒫⇚Hįb ~\$jB#{Ub@32˟gg'QjG47*G3"gxAnB/>n h'?#yvD'fF S=4ܨ4@ |\ eg E͆gDzzpsl ht)|e38hW-$ @v]I@ɕ_vAأ 5m7JeOY7FC 4T)g ψ cɈIX|o|Lc3_en)Y+@ @%(|P>A9WWR6[WUj!]6k[RfʟeugDYAe7njђHW~ՉbhM$ɶqK{@ڠ-m?U-YH$zju#4%WxPS-(F*a)QG< Ԅ~tyYaCMg t|p#jW?7.AMgD3EЍgĉkݒH+oZx͐A V(]-b m7?q!Aqq3޼D 4 ʟhtQ.`+n DBwްSkoA h(|F9?szꖄqM/u_{qP XĿgĿjt\W1@wgěC}{V%r5-f?hq5><1鿁fF3b[Fψ= eMkZCD&@  @m73G5DU5-+ʟqUA7@%߰gBnۢF@$v@ T^ 44y)][fja@g\>SMqu M彌)@SFI?P&A'躣M!ߞ?_=^Rbw}aykE$wY3bǵJ.g -ܯ(|j9 .S=Bj@? j`N|\~>*y=p2ЗN1ǵJ.g @3h6Am7\o-.w.|jS6TUvݥAky(^jGDYXW1m7FnLɩFc5Ι<~C,V>9J..WPZFև<ɯf@ 4A7ϗ> ?DC5֢+M7o>sZ@@mĩC7Gx&͉ocr-r%9ԘZ94/ox{_3"«g@'j0qBj^ ȆpBNj>$vbܘi[ݾE5i- 542 ( @P'd/bW͖dOb$<&<.&Xm7m7bhF D_yW1m7Gu㿋)|@bg5@3Mgo?#~hĭCA3}D e0m7"Hz=}X fG3g F 'h7&A3hj?!g<)͗>A@m7@syI5{fQ #ʟ=@UQm.h*z+` P9k$ p_v4X5mm,8~T;,.ʟX(|j)|y֓giڹSgoި&/o@3h*q @g`ۉ/g:htma?zPw?}` "2_JJ1ysB\A h4:@ ݟ}S&M 6ĉ/g߱M )|b _S 4 w32D.ʟqFFUi48qP6>f@1n3W1*P{Tb@ hVg71?T n(|ntc(}XC@P {N?A4a|M5@ĩ `a>TD4Y<٨4 gbE*/hB~sSj"j(|BAvh*Q͙Wh@v@mv@i5 {Y5"fc“[ _#Q: W1@ {왟&Z8)|P>Qzll~zp&^U@u(tDgDAk"c@jN>zt^5 ~smgo;Y5≯FWǫ@d NYsl^&vԙwlS#-w;(F}qA 6"^M cӽGreϽ{h hjgyE\{7|9Kjp,U >,P#@wZ>HDϨmEе))|n.5Ftoy11<ݥʟՃh:33jMo'}PmS#",Xމ#cVЃđ=u|ɬ~s G  ֱ ]DQo/GMErA xtHFL{8'MfyOQЉ/g߱M,"j*ΈIT͆*b#hty~4⇒;<=7E⟋Q B)|*ct b 3֛>A_eX@҉o-z@jg - hR[mvpݻ٨T@@ v?=hN U(m7L|4.ջiăwB<Ьڷ>>-! h(|g *ɣxE(pϨp 44[g f|нع h*>5B)|0JV#h|*;ʟQ%>(z4m7@B$PUmU D 8R Gw/Y5R. # 4[SwݩhTU-|@3@OnvϏC:14NfJPE~ʟ>sh>މӎ&z`(}x<գFy>[vh*PuCMEv@mv9! =7 DP"JjvU 4:Ugx৅# 44 @rpw\S@dP8Y5.|W%)|C?~x K4sq-2hz>5]Ŵݨ6^wD4T=7!mSO]کj*(Ј8o/W#ʟQnc4m7N=V~koi_^?U3z@F$P9n lV|Ply$X߿si[DQA3PgFUlAS ʩZZk֕ʟteY \m h6(|P!f1ܒ፫)sፋ˧/gsedI+ʟHDnpnt|J1uhIh{U{WϽ}msFvvo?o=ϫuPxG(|"hW }φV1㦕{Y%W=VUdD2}c@gA @3|H3xrAh7?v{޽u}ە7T'9<^|I- L>T )U Oqy+B0 ݼpmM+8Mλ)m7TC>7'ĶwG?q_6_姿wi[7ܸ28qg߰/5nA43@q!w^_߿򴌞<=A+GN^}?U43wrЗNYq5ୠD9њˌЀ_*1@<<ĔC?/gw/{vm?ğ|h?.UBg5]lE4StBJCߺms kZ6Ll\ʁ-Vğywzݾ}ܠf7 (|PEK%퉹K{W~+[L}7!Rn'K>=(m//3g޺[Vo55 ! v@ dşet`pe߼=Ϸ -]ݶEIw3~V5 5D3<8m-WN_{Ýk>MM6ئ=+'ը /m+-8TC˟҇S=j4V3_# ʼ`%W1Eo^ym't77;FrΝ:~F5@(|Po@|};ݲqfT@(4B#*Qm7(zB3s{ց]3pB@eP| C_:qK{x欚 !5b3b`fp{[9v@@PWӇrd hŅφbp4nR#hg}mQæ gm@(|P>6hվ}(x캧]P 'MMڣ6%n ji;hufC< #PiSrnC05qnm7L\ Ń8+'հ3OJqfC3ڨK E @yh T%WhN(|}5kh y(}:EƬ=5A%ne0E@s"l[EڨK (ۉiz@M"m7U(4jg .hs ؋e3NE@) ODmrl-GA T 4-a5&V@oUq9dʢT(톉TjKrxg@{q(}xFii@P›/rB>Pyn nQC@#<['/(P |yF 5gpOf@P G T+F> Pz?ʟc  j>*hP) @ nhBm뀼Ʈ{ڍ \@mĵE@@P?^|I-fnf]H lmH>dE3ڈkE@@Pmw߻W63M%WJ|ގzHPl*bl'/Yn8۶Q(-633j$(|PnaHA1F @yon?wjQ(NoجFqC m74M1_ > m7qY᳁@  {zѦ м@h5P>s?t*y.F4@mP l7Ρ-])nB@75><})|(m7 3zB9hNfJӂ m7Fn @- {{ͦ{hFsv@ PE@ {{{?ᎎ5@3xPg\=vݳQM+D*N3EzzzzpZT4mw߻C{{P@mDQF`fg -Mc=|/-lN޶E"g5@ 0 5kg@ZܩE5,;վaPGvB\ŀOmUʍz>Ccc"hj_QwP>.@тrmm!{NP k>~QFǾc$;rz(.I%~R#W-S yZpp[_kmۆR8 '|@OTP,P*P/*7ZpN-ʡ?89)Y}=ɯfoPCP5FLsmP 4`7!,̉0`V#Bj V W1P ʸ =z)o/&u}-U?7!Gs-33j|D4иU@::_h;@:q~#EnB5F3ڠ!P1??/3?-[o\ @sv^df}ʟkj 4h3P9Ϝa5%Xȑ=?ӛ6m8MkKrݚSɞ5P}>F/|HtT-8\h5 @p6/Yn}O%o4`pC A3T(P=?sӠ|C ; h^7;FrΝ:~F5ۆmQUݨFB3G bu,մ鱱ӧ':d @3r̚Si7[TJMo(̦N/4 F݈+p= hJg_>s5p}wmμbiλ^ͣ3ުqS| W3\Q\%>x>U5x/e5(7mݳCAklfu2 ZXa7xsc.of؅~0\w{%M8#e\o7!ܳСCa&PZ2_Wj/vY8~qzVmZet5R*߾Ƚo`DؙA^0G=7z@9¶Mm=Y:&l]=oB7Y_\H{ʿ;y=ބm ^PH%å+scm7k:&' 9Zc˵˷OtrsAFqfk?4_ٮ OAPl8斞z@|t:2ydG^|"g,@?0yhl v`-@?m s@[|[/={1Im7*z<,L m76?WHz@o۳Gܢ4@W dQ.#u_>4f?蹆PUs ACuYsy>Mϖ6\F|N97ȍb j^mV G(&!-FK24 _v[B IEF[ߤ9f191ZhO*=3 ğH/# Ay ПN7!R  |H 9yv(0g>l1.g[_ֱhW8(o]-sw9"he.dZg;WWX] T:sKp m7bGvww^] +玲vRWaPld|fq40ݽK mVQ|r)ߗ:O_KD ?`Jy-6̎W>#i-8(g"q 71h>dQ]|.^kqOBc6L KپR޽*~b9|sLvcfq]8 m:7v㖾G@Xً3_^Q}uv@!sA nH ?g~ͥgP(oY\zV}FJAwZaMg^6<~pU[B?貛9''O >w,+,^/k].aPO -/ !3 g$ `·t%:8< ]U2e$Ⱥn u+^[aE׬D׿jB.0G9} .hAa-@-7lK4 ;9/ !E roEkQLf1i b C-@7Ԏ[@'L m"\3 g GZaR|.g,ED}g n424gZaqBLvH.0F 04w2Cۍb}&%|vcIsm-aG$I+ed4tKٿv]vct\FPBRXӼ D-Wm+N|m`@Jt v !yUFςD'5g2A'hH4 KnB3YWY }Z}wè]]rD9!L!]-OhLz(@@VXz3a_ڸA  ݠ$#Fbb ?+֭|b̹|ҊuȢğdhн"_Fj/@ :֚;V!DEH3YV! ?rg^~{Znlx|Ϻ'݄g:r|NY dЯ/Vy}jX)Wn|&7IR/#)@.ꕹa3U&h"bE }Z}w#kC~8w bY9Z=z(*m7e&f4g΍gWOVo~Fu!g ϐ G&8# e?+֭|bcmJϜ.yҊuBE? >'lXbp[nB{xgާ(h峗6ܹqK\~\U`DH^w3W5e$w*4gOk~8=-'_ @ݠPr'TI3hœrx:t^=:Hgzeӟ (@˲/Vu> |N 4 {#ȰB+3g,7"tR9sKڋz@â}')d @q9m7 &йԤ HyaтsY 4gnT_|~dc dH o> v:҅!rU-rd_(8(C?y}\y\`Xb }=/\8gvg߾ҡCΐ(6DۍqŵDKAjxҶ}/\zA@=F̻(zFiIy (ZHn Ї&o[d!~n-8.adhWb3,r!<4\s藴cYH3 .sI :l99\ynCH3iSۚq胥{86<2 ^?ۺmWFe$f:W =V0bfqAðV>~|ϞfӍ=R.|{h\87.1si!=sеǏ߶m[@Ӎ˷7Ϗl [!+H\zV}Fj00}h24}nt}6Ѝ2Cׇm@%C𙄹TXqY9t҅ŋy͆PH+xzgFd> =(?poH?BV|+&8B$XY\!h\OCl> - @|Fe (m7dh?.#A֙ŋ&Ǐ;'jŗ@Z$vH34 ۶o¡\s. h2FXcp4Ujjy" b3 (nX"iY:2%l>H0L0Ywr^yf̥/!3]ߔ݀B>tPƈn"WF47"ZpPX͛N,OTܲ~Ֆ۾2K 2R7z a[YZ*/&ds>>|"C7!|a߶(t{$u7!n ge|.8stm۶{?p8E~Mwmߐp@> v [\FROm۶?~{݄pF 곇5Z?~OmѓnBH8OO}5 rj3Rի0|,^T޳o_(.l}Í(4Y@(8 >pZD5tMa?k$C :!hIo F !lx~|ϞfyϾ}CYn[2%l`ŵYDKV z*@o۶е?tx%`@X >e-?}e dQgm7H;ŵ%lUiA+8O[Go}/,5oBx=/ Jt v !d<0S:z?@݄rgg P:AC7-@7?v B2Fg:2b}СҾ.\8t /9tlARO y2R-@`gOcu[h{c#iDV'€v HXRm۶:H;?t= $L>\,,3mz}==m=PڷoO8c3g(8!hX\7!,m9ب99X}a3@6!Ln\3,4O@2H'{f m7h]Rȳ|5ςU i7HZa @> |.#A֙Zwf߾o9_zW̄}^qςdK<Ѻ3C( o_9:'?z[o]U` s*z.@*=YBzz;L[}wڬߚʫWo˯?~eh ?k$@ {t&\F܂3_=ͷzWgJ?~핋`r,L>Tju_N3m7`@ WgJOzWp!ӯ_?}}[ۺ-W/ggD:hK卥SSo?! 8uFA.y2Pt+̿o52n7Vֿm7._:3q1H|#g|;xJm_}-k#z;߾|YAe7գgJN}(-Vv!rȄ,4V*ݾbM7,{^|ٛ>_~7.'+}7DH0 Z;4sՙ75se_1溛mZuC[mw) G0Fy k4PJ30\JP ?ᦰV*}ҕ7ܻGco^g1{TMKη LHH$/zEO0``fu(@oZw 埼LD+o] +hnz+ã`n?C0::ACC7,{xۛ4ξ~^r1/[ot-7 vF*όY ЪSn]7n\G7}]hF?1g`dAgHչ|ٲy;y5oY߶\ 2},LUe?3^ 6g Io bZƼ[!J}+\UPP9&LUjr} $@p/%bX,WoV\^l٭7-۴xrϊ]v dC0.pdHCX禿Ww7~˾q_GMoTyHϕ=~if0+m7>R-O;b[oZ6mǚ7ܲg>!r5 $,#"x 3 g;hÒJ^-O|R`>ğ>3^O7,hH՛+m^@4/: X4ˆGraB6,~ɋsGϤJ4O8[/ںpP4 _o#dqy*Fu ;k6^v#yG&8# x"7FMmu^=]QwV)9WJۍ&7h4 c1 ;76߾as[NOF{Ԝt(蓶0. >Zf1dY! ?XK_,jlƦU[**RiN☎ 7|rIh/@M?zý;_t &3րKؗ)d$h ;y>=/Sh{5/BIr)a 1seg n@(@ݸn?S@\iAN2:B0 Phɷ 3Ā 7Paa1 ٿ꭫3%h"//i $@g7!}||. mX}"pA>A?=׬Yʜo2eFkXa6m{Yb*ZXO[+[:v͚sχMױ>uJ `fE}#="f>1u" J׮Yo`r3UV'`{~0 &'Oomc}kαS}b*HJgrLp A'=#s6RqY \F ' fCFsTcϐKqY`ɍ 'z|K:" Fόˑ#;f8r%LAN k ni >ğa%l%g ^`%=!aqiz*@ou)M7r n K:J@FKt|.z@En?SX\iAN2^BЃ3Ǯás' $C W]O<;_~n.i>ğ)SXYgAo=%#|. 1Yi! ɫD LDO5kֶ޺䖩So r@JAT>Ҽu˚sk׬9w|he% dufqJ>1ռ`zk[Ε3|H ɮ k\s8~>Uzx򾵍m 0*ϐ!ٍ\ >CLp`Xz*@Gm<5l`2vC2G ̈́{2RzT>T?:Cv@iQύt#=e/3EȕFp&z*@?Zi޺eԹk֜;>l`8UmKq=gh ;RaPWϝ?v͚x ϕ|?Sd)[/mm7k{化#5ɜ k\s8~>Uzx򾵍m 0/3 nB'!i}ְ!8u[nzYRN 넠ɖ^ ' A7c,i\ > }*=ϕ-Sjv?qύ|Sz>Y!8z*@?nfߍ[}H@v# ZH-{rdȎ;R5kOL53禦E[m75ğ)bm7Kd4YSz}M>}S 32R:z­g޵c >4MD3<@*mW#M5F[Ϲ! @A7Zgn49WeZZD(@Vn?C.# > \ &ӄ#fq)@gaY<ܦZh[h{. ݇M:23}|mKP0m/e4ie>޷MKyf  ݀}:8znqR"=yڰYj! cS rO=ۇԖf]hր,|2b (T9& c! b0yOAaS "tBERWa0l}ބpN@|tXC"Ibm7`'ɟYIoBw吀 m7v:r)z-@_1E(n?|WyZb!d8:+X@/7!l'[]j@! >.# >H N$4`9ğ!#R-OTj0ȩ$Cc2RVz-Sjϝ}\ P >;W'&ʮ݄(m7be$m7H= /\ &r63h7!O @.u[>働aи/4k>g7! QKemlv@A:A~]MMֆaևzbJ+g c>WjKyE-aegKϭYZ~nD Ot|n# #%MtYXkXȶQhր,{ tY^{߮5_>Sէ߷Mu:5 ?y1ҶM k?CXKpb Gn v2R)@ŕL9& E%)@% Hϐct7W[o1@%|4g3鑃HD7?/FA9dۍ&P@Y>Wjjy" XzWo dV=]FvR`d:mgboqڵa0[Wrʕ0Ȏv-8gVJ49 >g1! Ź >WmK2m/V"ɜoBnֲek d3\+zv@~AdKGƙřt:==VH9m7#  &a]#q : fkЧORkm75 Źl0D-[6Z?˗/ ğ{lb0̗Yu#q -կ~իa 0n) >ǜ+C^6\ Ih|3xI2`XN$̙3g/"K+Vq˗bc  I.#@㙙o|Ν R[nٸq 7cM;Wy%M2*@wo cq|F2E$5hU/f[o;P}+fLqpGd3@UZ= a7g6Ϸr30v)>g\Yg3'ͨ-V;o={6gz׻}H ϐiufqn,Vr70(n;C#m7_ 0 7x;|z׻t%Cg7 fMw\-Z}|GЅZ7|w^Z#g n,R_>H Ͻ=^,Γ% Б30.:>34_ @a A3:K%Cm723Nbq9>\A֙5hFDH)m7>dKV-g "W4N4[Gn@Yg4@QO=ڏU3Aai/@ @Xff 1`>5h ?t>\Yv&M,FdY Yg4@>??Q-OTj0 4@?RP}&|\@Ԡ4v|.#A֙ 7䉶*y>/ 3a Hn4PgA97hYl٧p/a7eh}eh]nROP(e_ٿ* MF|&aZ=^9 f5_ږ8hޤ9!L$|3asC4 n@AT( =vE.)@3ٕpY ,?,@bDP0.#4@+p YwF,N sn2dY is׉a;fq)@d34S芰 n\Y }N4z izs:&C?DV,:#&m4džGYx|aB60F wﺧt^իGW?E '!bATvDeB:րdF4Oa8(@d3)! $`Ⱥٟ>0d% @z(@tȕ3i$N(@v rZa@4gt)@&m7jyvi6g%J TL'3Rw\n,ή/a&]d ) >I #r:>0, i$XdFHufqFUlA4Р0.#J+?ܴLFvw@/\F3i .$I aBE !LbF|;+5BQ|&*z<Huf1)@3_!Ph֠rv,3rI ğ5m72tA(@?rH;LTHDl.a7B  |0m64?3:@2${ @э7r̈hdt)@@FoC֙Őuf1PgN"!S ma gh@ 7dDԠJ@( b ٦Bй @1n4 N4@T g \FfqX!QH3CQ3cj9 %3!b"PH3v:D]FhR}f@nš v>U -,NԺ#HhfE+  LZ}%m. /HB N+g& t(@@i܇3!b 0ZA t)@ŒpXC^ >/I ` I5LS|e$ȺM6tO`Tğ3BK(+Iۍ٢ 0tI P\Ff YB 0|tC'jY "Tjjy" +L% >YHBЙ Bbʪ,N Ag4@q-{Uai1g@BK83Sm.!Qg?x3QV_h G@ͅ%Ke$! Q/seg2{~ug!R h!}:.X :@foSr.3ťgjyBgrC:`\:2yda# R>sY>u[A)@ DV@uxnJ)=jq)@y6갆3GApXRBq9 rAO4i 2sPnQr'^YۍV &"|r/s2WqIȧѝ+>|H ՠ|nR3n$7!b`\_}ۍV -m7 EpdDx4"EhJȡ+?s|%IZ}%4 .TI+E& + r0V.ZI# |nRfa bvc\'HCm7Z)@,AHuyAF+hh' cA >7)@2sh1vMV'€.ϭ\4n2R!h6 @~ \YP-)@t\(uf1f#Akhvυ" ДHA >/N +zS-OTj0FOyI .m7Re$: x!hn(@\\@%p(R۳n5x Zۍ)@y rES,&*K8F7 #FO| 6 A >AA9ߴM5h(@7xXC9ߴhVFs3 "8 E5h)@Ecp)όHg5hm7 @> >0 m7 d a_ğJ9C'!b t[ZyXBS}m7z2R$\ڋCy 0?n0 RH93J ,/蓂p)@܍|HMqC dUqY9O4D)mT.h@s}nddY YgG:oP z$m7'\¡ТIg A4I5sG|+R/CaBK8X[ۍԠB( ||2V.#Aywl(@' s+!)@SXC9I yՠ s>h6.#Ap|n=h Ts@r콟x?zg556D+|kbC[6OtUm7:R41"W!Wf1~⅟(=J]O|{#O[яS~QI~ϕ^9uiөٟs¶t,2 Q4Cys >C>Sa|{s~_ٴ)/xSe;>ϾRz %0DVHDq.# |n}4%ݟ+>gow>>tSܴ|?'-}sχBFG?hIT'CiP(@y#inoޝgǿ?g_iÁf~Zc)GԩF=ZZ.@ F!^)@]P -?WBY;7mjrwJoCγsq nףQn!@<0'ߗ >ADȌ%ϕUK pK={]k$;von=naңhh=m,itP}.}G?ZGO-㹏~೛B/@|PskQd-B}>N{~T)IŐu9w|V4ZFF|Ssg뎏5΍M-iCf5vl_tPի0``ɴH  @6,P}(m7FpZU/1dG/1@_lёN813{a/rooJ;hcc=ֺc8]w_àw"i ⑚'?~ O}~\?畕9oz/?u[XKP|qKSO'Nh }"g4s9E(@7U(>EqRg3@dbp&mԠ[)@z- (C6jM @6>gTի0(l(A+C+@i>gŋYlQ)FZH\:>i H1g|A+@ڲ/_|#7`^sGA+@)0&Pϭuĉ[l ᙚŋ-C+yg>4z0P kv[XˋjyRARDgfCw]w;v, R>ӪKz/~1 # yFmw>x0G]ބpwWàEoY]7i'ȋ"£x;:?`8zxoϭO:}lpBX[@\Zn]4q9 H+gLHs6q9hh Z@Ujum(lۍ ҋCHvu.%FGA+@gIw נZVETv V}|^Rq(@Й PP=eI!J cHjyR0m7(4͕6# !ϞmxV*=m74d݆Gra| +XqCmV=aM;hȶwS:\գ+ٵ!l^7ǀpVcj'<\hǡ aO7|m7V8 Fop؊7nЇ0 GG$5e'NزeK Tc/^o_̓?իo70mRa# /^|̫{0K^,߾qփjy"{a b[j֭[ Wn лJg 7W\E .,Rւbu^= hȴOoع /^n4~ic`t ^:biW㖃헟8<شjKq‰F-XmoB֎IGs~>YW7c{' O{Z]gyO̵?|²1JnZXf;;_-+{w}TK޽~$E<F$_qDOpj7,=z,`ݽO{5N^kʥ,Jݻ'lO.Ij|TI{}0u쨿~ھ1DݡGA{c;^l}q9s^d&|*Eݾ Q}#EECYc2x>%*'8wT$|;۷w#%ػc{Ow<=~rfx yZ^zuXd7;;Z@+:@ hs_~r\BC5c54oV|򚋍sx{''][lڵĉ[l ᙚŋ-C+y0`~Cak'w~a\*ov?xٸqO}SaL֌"ɍ?x4:I0F-/=$ū'_~ &…8.<55nݺx\d蓟dke''~ ZyJtk~PNl\A(i>)$\Olj۾myϮ@1^m6JlzMֵAo$ڌO>3A z@@sWXēriEǎ5oF2x}*hIP!TC=VGAɻcG &ڷ!$m?'/z?6j9Y<޴&'''|߼ۖ/_[ $`fArʕ??>h(@@ng0^OЇ/1h 7#-Ο?m[gSmܸs\ EoFt@Lzo_~aSh>7x#lZvĉ-[LMM?ŋȇn#7Ɲe.\k XzuԺuas]-RւP`$ hFBP`$ hFBP`$8qb˖-a4 1f ;?&J4*I"T4*T_ c-j TD\>SV6Eֵ4klXٴkWDV6G"f [#bhe&m]j5,-8"ZD?(~M ?7H1;ܤi[6~ M[vgm͑g[׊?߽x޸s--rR]ItGb 5bJIDL3EGjZ^Y;执'PA<8v3h1Q ޾u}SS=ۺn^zmZ7~#Ykn^r˺֕-ԥȃ8}jE_8P$Htfmœt.0@c@G>AX@ML||ūk# "zWO͟䏟~ucW/];ɷXWWT Y%gfPH 'mG&FSEN͠> ׿yҵu-3W.^[z\}+KVD޺t +>z/yf ?BvgI`Hœ'+z3Kf{].&XٌIcfūe>gVEGd2'v1Qo\زy"tUg!@민sm:_\n߼^ |{ʼn^?Kuά?2c rCB‹玬>ڥWvѡBY3tLÈ|KZ3cK$'wsxZɨ8;b.@.ܱȰf54 d␱ =>ٟ*o+H-z /q2閳/]:wzjX^sk߸|ؙOYlubTͨ4K 햍毥];k?|\y̩~w맚Νni-,_꺏v{2e03RbxzxFv0|KVLECklsȎA,'@Oi־f/*eЙ5O}s%U^Xw59wћp;ow- W_eZߤ/>G1+w912,dh֑: xU,رYF-gE"lW{fЙz)_WB.}o]_坿y;s;Gf:W"m<7^=qnōj}tyмށf%+KN?8nߍ#*1w g]@F/OZ2d<@$S@ H0φe*^Ji#-͑|h4Eǫ;~l?]++ZŔ}VsSdye~zdГÚ_X+7d 99ߒ6'"{H; e&JpW<.Զ(@_<2K8-wΆDs̛Z_fB'P z|@`fjB"FqBg9ǯn\^R#M2vEu9nE>'hx h3}̸YX`8Uz@PYT@P T4*"TJ 믿\{ZP^wjcy?׊ݟ|j(Щ|˫iEDkh+"ZֵD6lZ_ϵ+"+#3IyRju~esD[njjZ^.˗RK)Zp@Tƣe5v?~(Vz H/[cQC -߻n*9i}ˎm]ռ9yZ7D7ĭ~}ܶ~KkG"%̉ƠIoqg 9]ZEޜ_ kbz?\g:r?~|I.snlo轣'o]t?׼㪞m֯ ȹbVw׶ܲu\t*-'I&eɑhTԘj0ģ3޲R/oi== w{uI2+|Qr.36WMe|ūkeVE^?wK\??6N-/_v['/gwo]16(h49"ޗ5ִHԞ7З~P=G%ҜQ6]]%/|.?pz>"}@M 45:iu3|{ʼn^?Kuά?2c rCB‹玬>ڥW 0 [un%t[ʎKחNeDT>HWŘLgu.NZ+rF\Z_XFrS|hj4j)ԟNC((kP3Zq]v Ri[kqmiSMN]xsG]|uG_][&*!;D,X74[&%r?0,Vx'Ŷ޾Ћ҃p%F9)tJC8HpAЯ}𝯭xU+wx.=/º/y녏[ߙ}O4_~kn[-[MKVV֠&b#ZYhә592m5vR0IX ^ Rjs [ $2^JiW}ŕ?ūgi_o[WoyoΑ|mgf;WO[qr=-}KʏBFܧ{pXILUpvR/Sj,;Tˆ!ŶoGsF Y|e֪x ^'?[!մV7GZ#XiǏWwf:WV)-7*S>^r݉hNj\:YOo}0olOP33Wf']]uwɭsn_unDYE󼨮h]oBzSxýo\~jxtX&ܐ׽PV䡯 i͑KjIVZF׮\.׭\S%b%nx!@ h3}̸YX`ϨKÄsa8Tp3;PH1lU5-8DR)i*={V P9y5TH{{dm65maa@h@U@P TEd~~~۶mj w^DRj.[+jܣv5@7?{77])F#McZ\Xqji44-8Zg˧ǏĨt$S+@IC!b 5H$ZZY]qU-!Ĩ(f5[ATBDGjTM0X&,IW*]Liෛn1 FD1K[B- @'%>-qHXwOO?SxWrƘET,v&WtK͵gbUȠdvR-ϖϭ;;=/LbOc-Wo&w+əfv~M-b@b4xv+i/.uZ,/ՙŻERMMOό1u2ZOer,O%ڽ{?F#> pתU+$+W|rx=ٯ ri51sGGqJ yhC] jԋJ jc&mÆUjܹ=ߩ*J+Wo˕R=-$._—|a @D{@'G#G Q=p5^~|-[T-!b>gE@ 3d__%FTkxDܶP+ 5jvYԺ3j6ԭ;:rn%s@+D"ҴhtfhH >#_w*>95U3jǺ3uDϨ8t_<"Xoh(*렵jjKK5^*35r^55xh5Ϩ/}3ȟjg`Y׻Y<Ԍ⡦@ vS4N$@P 4wb0hoh*@g'z)4jgdu;JT) /-8#ݲ{$FX` KS#v@XxIgQ #&e}CZ 4h |4Hդ N 1Q ߸gɮ.n;P;>#{5rgaLo$?h 󶃉aps;v\بR@c@Ԩx7ԤИhyDbpw$C̟ӱThvnjJ[Z](w0ޫ&|$Nyauk=;=x^Z?3 VLJ?/25 QkΤVFm<$ Q+m۶-,,?մZ\\TCGHvj`@X+첾,N*vق1+\vlܸQ EM7S#:7wʛ %dK]]]333j>ڽ{?FB^j'9k"5l(uS]} +'z]cVjx̟9sF &\XXhoo7FaZ" 9|65;z{eb.k3?Geٛ,cz[n^jg_X7555"utIGfmcs% B9OjN_ݲÒf,`g9<0G̅{މym emٜ&׈8RNnl_zGooܜݼ[ѩ}bIW1)w!%ㇽ>Ԛc}QEҺǻ'f5(fPr@'bEO\XfntW]!Ӓqxǜt j边tRW!iz"mۗ۫R&~¤K?GxnjZG@xֺrAw֑N#SzKͥgR) 2Y)g-3'Mz dBәbڈe,+]Rx˹{zTbnj*;P5ˑd- ՂY15 kֿ~2 'Qû+5 $<1ggԜohx&Qv2PCL2lyyPV%y+21ksz3Ȃ/](\m_GbY~\3+e~;#Yc@ T;=#05jx$x$ZM*Уpf=FwdR)mD:uHzpTZY<'j!_هQ1ypͬy'-eu}qWx[.v"+UcEdYߢօDKܦ=}VI# h 4R4A:Z?j(~3KdXo<=e@ v2p0Q-{+K9 \N,vB9Rz _3#<N&b [Ch1.5%Lj02j@ꅇ jl khwkG% l6\=n j7o?S Q_ ɸYذޞ^ênZ[?pOYG <`gA&>#VBd掎oP#@Pvu}ofd$Z|Oc TBmnzZ?}oje ܇IBVY Ի;:g5ԏmğjHړ階%bD6ЋWʗ<(ϯ|n@ qF5TUQpcϼrJ o{lSƒ2soK/c,8S#VY;533FQnw~Hʍ%ry Ϲ/~f׮e5= Z|pEYr|j/y8I?[sMsJ 3gΨ<䭇ۍQs}EbPTM)Jt yVbzCFcSt`+GNSwƶ[pl}_ҫ,1[]ItZş5Lu4@7@]+@Wa\4—Ϯ9$l%: T*eY b*7?O +gD9:Y)ibQA'gV5TPMpNSCuHCW Y8N < vrp#47{ n>z9ZY59[=1pJ yeϛ気M,f?PzF*m>(T3_5k񕱬)ckjLWBʭ;: OYxh+h0~"hfD >G O3@c2gj=>24|FlM.tJ>It Gh @sAE3ªhi=w43o4&0q<ɠ-|BhWs4:  s @3Zp$G##I5&R`@oHZ (m7sC12hbhhF&NJhOYo@%kjMc]'S_.vb!S,8@ v M=LvuYg+Eכk?Q=@3s"7cJlFՍ`=cvsUepuy^dZ9;=kȳ~{:ggeܳdVγXFIYO_xgvA1gwY~8J/fWLsdf \  }(|F_T h4nPp5H"z KH9d3h48dh!:d ,'x⡇ڻwTD"{ *c ]]Z29rYː;USA+k<;JV"tOjMűE_K!zs Ķ6K:Ts1br!c1d4VЧߙ$XrfFd\?̣>&gvhDU#Ƞ*:~m5fϏ[ڧ4"Z.9c++ x(Wvr7;,/Y[;U(B QM8Ew;$93DAIRl;9mi2=< sͨ bKv VCsyuf&XTЪ?'YGp3 !Pe$2hJ+|b0$$?'Nϖ/7zSkZYLkڹwZB;*f7]v[=Ϊ:7;S>,S]DOaH]_s nQrHí"g14P>:>~xg~_^~g9R,o^~{xڲZYfؘAV8}ZOJ.KnPr@k b3.o۫#ܾL ׫hEasgg^*nO}(J0vƍJXzί8vdSE DŽ퓗 okkˡ-}"w(|n>2h40q1!@хז/_wyo\zu5) СCM/*QO*DldXsiz]^0JTEa9{>}2+Ry >q3nT梒9'q&`sZsقCN嘑L4βNZj#>Kc O !yMG+/ߠ!2QC>VCjUC!;(59ݻPb/Y[U:cz 5?{8K>7 X˗|K~5T67g g@Z1=ys.nX|#o[TS׭;nZ=?VSkakjB_7,/#AT톉B%ћV?t Zر-yOnYwxWAC3A AAP HU+\? jU[o\߿/^n.Qr;bz] 4MoZb XKS[Zm׶45ݢ Ϩ n>s V<޴~ojUo_VҶo^zEӯ~UzB Ps>h@Ϩ!2hm7 r߲nſܺ_|n?:wuU-kWZZ "+5ˆg+JB,&Fv,euso~ј||s$bޜVVд>>Q- ՙ>'lhh>L5i4g{z̒ mv#Cz|aGSڕj|irMܽ.G}oǔ>Ǒ4m1يMͩR&v.W!{>%H\^쯌+o&\?`2&+lNB'1k,SP3 g.A'~P>?#jR9T٨5Ӄ>[fw->Ւ~<{%w*N\bf=-3isxfU|#CN(|es kܯ% Y{&qxlrnjfzNC n֬=xp`m UEw8WUZWdZ[!+S&Kj[g{SvæT+k-@ݫR[(Hjy wXz}&>4EOc;Tc=Os/Slj& 'IybbFo:m7JN>A# ,$}w?F]Yzӱf{PƨFwEג2hheyǽ*]Eډ]'S4=D2! S6nvTZ zF]nmq崂vT'!^@VtVB'˱oYf}-%Ёe=ӊ]QG/ϽU ^k3盎УD B 8B@YfllȠGGG+>kzԫtT~@-S˵7 ZC.o+0 ݾL ׫:az K&LJ"}8nLq]^='h[_p[wRhr?1Ad1>^wJMGQ wuu A V̠:TYcNճV9yV2*52kjWr|5^^e7]'2>)6u[Ο|55rܜWV}wCԮk4M%%pOQw* f˛mrp=7.زFg!w e uHW~v_vw.q7G3Pq\)g,&Fh@ #>p91sC-dc7HT9&Kl_MN0jܐJ~ضU$y[R[|?%}S)2rfK7X+YV5wO`UONCcx2A瘙,A<ҧHi>wq|jh4c5g(Y0 ZXf=ܣF}DzZTkis^Zj"ke٢+¸`vزu(weOSmJ=|jƨAEzCC ۋ/]˺@n4/jн}!xw {c 2KO,KL,Mmb;=ם#x1i6 Y`K@&K'] 7D 0>#(FP Ad~~~۶m O5P|򹁖1k׮cǎӋھ} /F_" +wڵkk/c{7nTCa1V#~֩PRȻfffHhݻy5RS*ҭEi{gv_ZZV(CuK8g6}.to(cVj͙3gPmmmυvcCv ;1`IQ&EZAE3̶z TJ/xVނKAޏkwM3X|!C#` ~>FU!}z?ɠQU/|6w14??*!F*T*eY g7?O +7hzԐ݁gե&G?vޭjyq]? =_|3?U@ϓ:dtqm7)WaZ6ʞ7GO o9톉ItbBz kj@@> S aq 0W g14h@A+@}!B#}Fa!>ɠ^>zGj5@xjD>s1, \S+hg}lF4  jg48Qm7z׸-8RWP#}FQpA#n!@hO#ݑHHRf$bXBMUWqږ1'{# 앾Oӳ F ٓjM3 ;#B3%6Y{kݼm}QH엝0ˊrDaz(mOd̈w go^׏XnM<ʼnbWm*9+v$;%brdѡ {M?CcAsrzPەgbn IdljU/ {_"g L@?|x#ZߓC}akȒ8yg)x?#jR9Tʪil1Z]%Z"4cq:p|`Ivra'.W1*y˩ի/3Ytp$ە/sx^?4#y<eh^-0̌$Z+9MfAHs]1bs "ǃ%a3L.ՙ&t#@6S PrXt avГO8+>5:4mhbXˠwHLp%u;ثp"P'3Dř[b՛1(M NoJRtJb Fq<%M1Iĺ3 zgxͲYХ^،3uW4jEiE/ ᰷}Vj8fgݭR{q7?<Q#@}"}{ { ф)80Zn~Ƞ+>J,͐ѝ ]]KKǓz#ᡗW;lWt ,=R[#9=a}3s,7!ly^?b^MBځm+/ss$btPeg#@JQh6Zzp"62y]^0JTwI甲GLzys}Fۥ`N_L3![%/vHbH}FT[8mا̡+G@,'[ރPHOȠ-m7L\  .}G8UȠ8&}^AOYL(2[pI?I'b@x4y0ݨ;<*tY{Q#z~E557I^[qE"7钊.gtz{Nsqa6##_Y Fۊ =[p5 z]F>mI,lzp9b^3C?Y 2__~:֥嗜]g'UȠ}F3xl10/ӀCUmrrҥKjzM\HshOe/;{lg5/kbѹر΃}59L"wMgg[blN :u,vN3}N~t|/Ƚ 2%GYΙ Pk@ Qn(MUӍ'x衇Z :;: 'Ƀ +e5i!u-ʨZ@j{7ߜ+ݕ=sb~5*d}Ěnl(9gȠ蜽 tz@s@3}~GԤ)- v*ɧ&;ޟ/C,НâP@|%پԈZU1e?ۮ9|_uB%.#!(|v([jl JO'NPLnjXй^lvZO8hVP̍3\~R2d @&7dCCfן. T?#LǻH(|P)^{@[ w[~a#l…,0\{:ֻs_-h؛阻fꊚ7)'h^엷+th,j'䲺KVbb=j$,(-g PȠ+g)1UG{vǚ5kƌ zttiąc;kB޻ߨ}j@gK%?ؾl#UKK2&Ո ':7b5B\FBv+b(o\otCLQc5gfЇVla eRUgRSh?XI>T;,_`r0FgȨ__,s~TL)ֈu+/?Dth<SSfԜƂȠ8&}~ܹavK rO*nFNg' ~ kə;;3Kv+T m f=rNGzpAv6k$ݚÚ|"@Ib=5Pr;b[f61/07!4Y{Q#מ9wC-*tvtZ m:ǎ=:kΔ=MtFu*bLk/ԧ?eɃ:o |W|9v57mhƭgs&lAɸ`gFd0~8^P E%d\Fz^M:桖.Wm K221W+nDͧkYgقͤ&2_89%UhSDs+5[!(`oNK>6莍;F_HS7]S+މ ?}3.oOV9JjgTgqPm7e=75gm;>k]+/xV 6Y"\-寞]S3PȠF6sߠ" ·g>s@;f͎4V(FpV(|bTV%8}Ž}GXsj~/4@ɌPRHMn6<wVC ѫj* QXyJ)=_|3^fU:}?ğ3_3sGتkMOwz1>5<տ3ma?914 N+Q )qh\<h3nTg1 P Ե/@@u+KϨ,.#DAvz8<gx+gq[٥/||ׯ,ԤZZ "+5 zj`?8kA)|@nTo_߾+2zNiczsMiPqS_.n0~8Q>! gp (RW.zY ƾuALr*(ОgrF AV<^/9u3O^ǎ_|ҒrɑH{$F3HF,*k8m˘ J'SwYt^rb5}S(؟%k3.ieYnH9/E>]ѵrP=~O9˲ۂ)9$w#ҋUu=#s;LܺxdY@Pr3ʟQqA"hn8y,Wœդt)GPBFCCʹx*-w\05922l/WrVpe~v8KfG{K%^Y"Ҝrj-\;Z=|x#ZߓC}kr(e![&⼖.LS9<,#kp/nM p>VvEL&_x3j%X":_w]+[u5;0'x⡇ڻwTD"{ *Kk^,h?#jR9T驨5#>[fw-Cjی1ϳWr 8Ev؉Uݼ#=N2mvɽOWE'3Bd9nv&%k*PEi^$93&bjOʆ23Om'G- @gbbDTO[ʴlqOqrAZ[y"yK7n;y(x{[}x] ѴZCkkx'O'NPO-^n6&"2>792R,q|**Y*3LϿ:/d9` .kLP@ E>fɬ{%wXz}&M4FOc;`czQ-81C#!ݑ#91_o]ؒ+WbHXP 4:-z@kW޹ťǎ_VF>wl\fm\/o[F|w}~?AW<}֣t"={n(^@r߻kI<ݯ{Yq pvEWQ+߄|zTTw<,k-Hi1#:U+>Yœ:nr[2P8u$Yˋf*tNoI2g#7HQ%~0WMsmqp׷Dhե™_y񧚔jwk֬32 Ϛj2Uh٢ϸcD\7dT]um 6p2-\RDRFbA-\&ͤ4뒫eǩw&#` k%#Ju-vQlG8 Ԑ Vy;~((z=3 573yN_;}qԵe9kjꏧ/>K33CU6}6VL[g%@$ZF܅,^̽K{L*&YŵYg&RFުx 7isLŮRTsV.7\"E9N1B,Ԇ:*{?weJ-÷1aCɕo(P]AS 9Н76uŵ'/tpј{mY?[|z@3Iݿ)P @/+^jP6?0k迣ik!6X>^ b`;mKur8j7O)/% 0Ưjܦ`=˪ΟBw}xXUsnvȗx2Aɬ}#R,n[pȣ&}>YیO o}Nپ-Od\FBh@薦o[ն2b.-.\K]4XNipc߾x&UtͭY{Q#}MZT%9赺Ѯ.K`pW\VDKlNoaܝ0sÖmFG5 =Sдà O.}ϩ}_WfCY;c{iɡTU3e] q5^>G!wpuvw'̏-KbrM,Mmb<ם#2F}c X8D͖k>]Zlkj㚭#!gL}ѻVb=5hp*9h PYyh!Ѷm\տu?m1qej+>HK!:45BC}ŻVj6CgT(jȸM]^-JA3Լz /+~'޶BMzF T e$"ބL>܄Eڵk a7!'{˿xy*&OnBXJ! ,O Y a&bϨOrE>g1P)3A x6?<Q#Fɕ(ȇ"7@\dljUHu4m7g1PA G3E %WFj,AS }# DWkjz?3&wߥ2۹YNh:2ݠ/?P\wTV*VдCPOv|P- [6W,O)syS2"%2,drzێm <\'{ǿg>oPl\OnhNNzL=xS;%諺Ie[5{0ט/6 |cj QZ eKO'Vr:_Fgu[{UQc: u&k?MķpgOiD+|+hsẆM %?~~ZamZb٧&g;ݟEbk:;;sͩϿWhf{'Y*{?1/ l98?1KWr)32|3ߺxXGŻ'vc]pQZ ._}Wl{6b f܂֭{tDSIgo?{>xyN?z:S" p>,E>;ı-p5x'z衽{O&{L.GgGfDYː;Ufr,+k;1:kIe2zIK,ץRHΔo_rj|Tۣ49U5YV ŷKIӉshaN2(&U\Șg ))*;'oc.y|cvΐ8y;ȡMn޴x^eܿS]pStճXl,C>T m7 tVCif#IPqLl1E޵ TKd.K⓫;qQ7\w$h~bS<^*Z>"!ו/7t32ܲ_~-Y:-5P {W0v(ͻO(SHY05"x*mA|Y3{f%[{t?_j5{NٜBl)ӨZ.n~yЪ?ֽă3$^>S8rRk[;ɉ#s] ZsюV̒L Jg%sS=彴| Q?' ϖL :3Z 2ȊYwb UEw8WUM sYm1<{OrF61m2Q*5E>2Ҥ[n{XЕA{eY}˺L 81K?G'*?\ W]|$-<։/zا_|4[Q]gXPf //r@5fJ`N993e+A'~Q8* I oᇍ 2칡̌G}%eTD<{U+iX& ԳL`)S7ɤeigJRϨMVЎJ2|`Ma5RoB@YfllȠGGG+>!Dr1k܅NEi.ڻߨPuy^ɸ,oeZ^PQ /rt4%8a^ZVDXxg2duq-X{]1(|C eL~zEG[2[RL[| ze=K7xe__'%Wbg-3C*>kz\f)=j; IZF.`\7_xYŹ߄C /`SlAK9Akk9+wƪ%%pOQw*9f0+tvBe2=e 5az ȽZ ǜj'Sh3ǭX\(&ϝz{3|qm7HCjUCu.<`dp>|dZȠeY)Z&$ Z6oOZZr+b֭v8*b_҃JK5578)(S )_J`T5[C_'`=˪ΟBwO`U1 )0 %P6˟-ЊCb~BCc82jݚ`}m |orzPL'<ٯv3jcAvRC9\ha͚5s ,Pjzmn&to lKlNk`ps^w;lkdqN۹-}=7ٞȈוِ~|wf_(jFѵ X+E W1;̵8^9JK;r2|Ļ3i9r.[ڂx.@{C<}!Az~:;+uox#;=<ٿ@փW*up@Pr;1sG@shg!2??m6cdaa.ӧ...S*K_ ]v;v̘^_x5_'R\+%X.Xvo~QbLwoƍj(,jr;aA]]]333DTCj?*;g35{gv_ZZV0=bL4GUUKN|w<8'_Cf 9sʣMibCv R/3G5의Њfn>9wA!a yF@g>Y _H $YOٹ'xjVc"P 6sA _ HT=>A P[!.|6@6zz[ XcP|*M sj~/4@ɌPRHM~>?]]]$βݻwn5T9k"47)h@|7sG*m%41Λg|E?g)`=l3^S Q vÊn:NVݟk :A(cۍp#3.#=Sh8F+|6@5?;g%ZlE4)80QPr W5! 1 MeV@- (ϸ%>[Q]8Ꮖma2ݱq,Uvvס }I9m7r_X4r +tǾgܡ wu|@᳕Y (Re _G}2,qU;hp>Gca5e܄wntn5J*gUيF>e\G7!T_\FB5vrz@G Xx $?(Ag독C2z@]}?}P 'pY*áP3Bm=7c[gY=0FG?ȧm7( ]r@MMimϽSb2(v@c*Fr@;oPLgVAg1*e5;*[< e\n}:FwX[>O l۷W}QrU)?g+PdnoB914 P]Ϩ~s?vus9\BǾg2)~5AQٶK F_S#AC3v"o\lEtp ^Q\A@m z r@qiYtZJpJYv"hQ\qn+"/uK/B W@ȠHpU>ֵDN]XKD n;z7/UmÞP)yj_9sݘY5?(-|8Q?Y?5/k);g)@3Tec@>\U@g~aRvWG/@BH5YQ+ǟ08?/7/<1{_=uq8{nhW5?\G7W#U@3P]L m7|@۰zz˿҅M_z̵_^olhix]Gׯ]9riaQr;b@Q?92йԬۗSpڟ_+K/߹v Y{ߺ7?K=Sg gq4Hg}e$dF8 "'Wm^ҤZ? g.;W޹SZju|ᏭWrńF 9ªfm{W~t/tĻWn^״9I[W>~]&D"#4(ʟQ[hAЦWE>rKK샫d]ǚ,^߸yES|}ߟ@>ڸC b=j!MMʲ;WW~uw7Ѝ+s7@(@5`EЀo(|s'K&{N\}ĕ +nok}몟{{޷HY4Р(gqUQ p6^'sW (Š& B X ^./ZIvÊTJ<<:JQ m"vmY_]֮4qXOC 5ʟQs\F8 Q]= + Y?7iquW{o\W;nXf܇ugTsOqf4*&w=qa9W{Vt\g d(|."h"h|nhMO65DHB gq H Xz\hʟР{A%@@P8G3@1ʟ4AWu 'u5@Q ݨS@(*v|Anv~@u`0~x,֣F h2RQ\ @(9Pr;b(|F4Y,^xj$(|hA3P(|+n 4P: '4nm7BcQ(F@p%n"pI>gHf<<@a0~8f@5Q ķ+|xy JDU(> !@9U3?/{2Ra>#8Cn4t{@v(FC(-8RPr;|h>7h;:⟿N\sAV.#)  4PϱX:(|n4g~i(FppgsPPFc"qpAԧWFPvc,3?FP 4?P =>E 4 ;bg5:g@Q  "h; !@PrQ ݀oc܇ ?#P2m7Eй|!kSxpcù5,ha-|YK< @ EU (F4E Q)Fрhbp`Xz2@N%ݘV#BXnRW(*7( uS2t@`vEy 6Laantu2HZ)G-p18P(|KeV@A3P \s;6nSʎю}:@QrF8rmF4Zg2w^5@` z0sGǧ^{!H \T# ?~~"hPjUI3@77E CPB|33Bk *GGMA3 EDU@&@ (@ Q>O`-1t` e$np1&h!zJ)1UG{vЂ(O&CM2oUE3 t@5lۍz蹹^FGooߒaCMO ')| !<SSfԜ48ʟY~jgTzqlcn7!ht|Fx a 3B+O(F, 4**U,pB> s#P \ m7PmnB8:0a@k;F@eQ (F9(|?ssfߍ})6@QrԻ=)| Otoo\/A1ѡF4&ʟJJ"h.Wzjjz`JP@x/^vVm7rh(x䋔?#2(S(\ (l,3?FP9hPI>Ϩo-8l6F0 o(|n<81 h4cU5F]\F*+d]8\A@yl17gC XOC~@ihje'h²~"5ܾ΃gA JKsj"?)| H< TgT=QZp,6&(gT[8Q> (.h rB\hZB+ YL NЍzh4p'\ . 2hP D3j"FC3}=5Q1:g @xPrԻ@>%Ps@q4ޫ|j>#hPr7h GQ:B {AD \ v)Qo5?<Q#P C3"P2gg7} x_Q RuJgu!e=ROn^y{WtmI \(F2:*bpa@]sՂ)m#5-+f5 @ ꝫz禖{&{,D"ڿmxF Dɕ0>T ʟd59izA'Fsd#j|*~_YV#Bd0~PSA3Pq\ vDsee#jUƥ?7/A gD3EgI)'W޲F-֥?&@Pr;?b ڸ`WޔΠ߼o]&π@ Ի As1؊%:~=ꮃ7n\ڛu߾(4F7n1gn]/n[Q7iLz/W+U,6.6Pps{ߪH:}6ܼ> b=07(|Fp+6SieMxȂՄc\(g>(aFHF#ߴ?z[BaE3Jh Zt_ (M>B|P~3P_䥔v}9JQ$c=cq]jJj]{eF(F N5G3Cx׾~+߻@`ܵnay,N _: {vn>>=;nRP*{gy1皐u9j@? ;<~BSm7і2gK2vtϷgϝRCPh>P]@#@gq/^!V,?ݺ];9zf9ܢ/mS;y|sϼ~ނǏA:5#owRg1m7#Lm7wT#Aŏ1A7~_!V-]w-}6t;aOC_fh<}k|!vEЍs1Zᇙ@qW6GZbE PmmϞ;:{^FAt޶Uٔsϼ\VChd>G r8П߹>ZC6"6ݺyyڄߠכAgA6dSm@cFa}ktFyS ]m>&nB@=yKNl0z~InK/k''swٴaXمv}-Y0x0?LD@b0m7,ԗ# ^CNdL<|lv&c9m15jK!A 47 t>@Bg>( (Fv([V@a:2m7 `n {A0@g π'AK?o g>hh?.D3PCs1g+h@}P !Gܗ?zrjPebntQLC@@(b0~8CsLLwwb0m7,P3`sΕvcמ6(ݟQ(| eЧ+Dm:0s|LPK9o,8p9b=_j@WC ` J%89+԰ܢPC?@ #nUE@e@P {ߢ䯀E73@H>u.v8hʱeŗ/nKg7\M3P%T]n>u?}v}{|@3P=?ӿWdv8ݟ[ʟb=j;:⟿N Er1g(ω/l 9!pi掎o }PU|@ @963@ȇ~XY JthqwnQ#LFg ` @P<ᮝ=c1AA4gj@M( ЛA)ouhaϜ(L3Jo/g~ '(|wc0~XC@P{ N@0ƀ U Pԅp0~0j*Y)ݷonk.@(|[F  nÞ{֎+=y=wߥf hD>0O ԩ:M3@*dUhL[O?FSϮo;:R)5RzWó@`y YctNvwnQ#Zۦ;[ϟ^TcPs? /dсޣ})~4s=3 _WNAS~Y8g ssjNN @PZ^ )Ze/Az?ꍷнSSmFGh@r*VnBLLww4;:N@Zx^0o={Ǐvn[AhG?{֬ ~s 9G x ֱ4 ]Q o/GMEpAe$#z&}=~O'( WܢF5agDϤF:?`膻vf+8\ߍjaTgb8ApS /Y?O *;F;АNNد[4 g - hPݺI ;k=mj@UQ8 @ UY Kpo *ve$duYL н9%Fպm09m !E >-8@4= -ET(FT@]saP w\;BS Wg.#g1b=jS07c(UB3\/V.h X(|PնLBʟQqUj 4h/RQ 4)k,v]j zUg0Q 4Fa93CTK/1UogO3g1 2?hW-b=jG3H݊@CXj*A p#b և 톉wֳ}4(B4P > !~GW؅^W@`P8>>E>!?ť?464S ;Og1m7M|Q#i,Cύps/nlqUً8}MM'j@3JC XM SH͟ZW+WSj(@Q8 |@3CJ/֕MG|]+ksyIN?5/|2P f4*5-92бl^T~ZpA3,t*ᦈ}}_o^/ɋo^Z>s%xUW%c%(g1nG68h[v{W;;p~F^ύ|Cֱ_:~Ay zgT2m7SIoC~{߻ޣ}ߪees$rm>Ʊ?3?P R Ro@At>?q=]躱Rc+rɉAK/Txr[lފ |I~ 5@Ck'EڣjȽLscoy\@gH7?+\y'syeԕL/;H4P?[|(m7p Q?4~BM}u17=3ߗ_zԵn\s_e, @c0s]8uv'<@aYT'ȅϑH$:dvpO*PRt^ҞޕW<}}t.uG״S5 B  >[Q TRTw.?tiMSH۪S4lڰ9+ ̛33v϶M? j&ʡPgq?_YҞw'uXY l$W[wqBv=ޝZyPWY~@ 4yoxe0Oݶq&B >H ?KHZKu9Gӗwv_m[3ݺIIw۹Yo@ 8-MW\Ck>ޢ wnў;)5*|䥗ljw`XG*|2P sS @p֕k?۵]䳾E5vmj r?n_w[ 58f͎4Q8i3zlY ԣʶݠ@ޛ=<瞻- 76nOMW_m7)2J T'^|?ڑcsj.T  j2,2?<~LP+@gb^>*uӅXwA 4ݺI 6ڔQ >6hJպm0xӪf(aFQSm7ñ(nXR]/s1@e@P;ʟC/(8VA&;>]!jsch4P:J]Y Dna 4B'SW(PʟCQB T-8(צ讱XO`X m7^ 4hʰnke[N9&( %W)|,jgg1j 4z蝚l+D( 7‡gArފ Dg>4ɾ a7!J_S5/톉H@MvY2e}-j4P8\F+|m7 tC@c#LK +F> >1!nF>@Q\e$O(|YL4\>Anh@lsƮ=ƀxЋIF bamA4zD6K/m7څ\FPUm렪}Kdp:E3ي"h (ՖL+oQ3A߷c5R;>83 4D?ɉgڣ[7Q(.4j$(|j02E@@PO/e j6Fhqx Fwlv%7Q_h8 |)=zfWݷO/@ܟ.5 ghgpa-P#4Z֮ g)흚R#記B hPͽ=R ʟa5 (|.H@v"zߝw`whƁ)6~t3qn5۵UTN]nG@cǛjIShPg?u _x;.P8IsvjUpA&ؘπِsrWNaӹ瞡41 ]2P>sw\<@HP >h([p͟(fStXEPrE})|v(m7ܠ 2сz\1hN%_ӂ m7m7L\F'o\otw>mj(n^Q wn.P#41صMM%W KY xg OԔ 65h<[gW{z?X\/(B[nl@ذ'gON<ݺIg><КYG3aoo=zQ(OnhW#9np)m78QXǿ\ւct^M3 7j|@sхrnB@ܟ.5 @6JP[>A` M8hhX''2>]@O}ZFp (,xS -8vR 5`}5UӾrmPmv!/Y%ZpPa;7ӯ}k_ʯTA/O1 Uj?H\=A%~?kpp[-8mسsg_cgGvy#'|@oXϕE W7Y VU@o4O/ʡS?<aX> 2쳙;:T=S&YT@=y\yf5J7X%@:*|+&GuT@~=6nSc܄@~2ggUU_m7L!D4PU@::_h;@:9aG7!Q x ;::d 1hL[֫գ ȿO?(|6oB>V#@I!;qю܄и6Ew,u/ F794ԩZpH&jƳ-sZn{NG0Q8P e@ύ87:@Hg׷UE p ,m78ԜznWӦFG;Ϝq41kvL+ksj9}wRnݤ $(|zoVtQ)-8{А?ǚosW,M9*ﮝwkGd?uF.J(|p>U5p/e5)w/@r}|H"MJ`G01w>g¥IJ>[d_92d2yql]Jr>9.Л##3e `h Dbg`_gO?>gKj=ίwNLW?sϞtiN?lc/Vmccbd#gξ2}vҵBt Rv3Sg72sD]y,-ܧrV|*Vݸŋ;.C@9T 'ҕs˗)MfTF< ȲLo6\[ 5Q-GiBy4piۓ~0nqW!Y)(_:ǖ.ozkϥҊkٸ[S-1#гnħ?m٢=hnuv}vK{@PPGc_+m0b˯k<{J]^?<4)u#94'N4>>f;A_oș=ҕƔJk΍w:v}Xk+`ԟ3@K "2%ʸ.BsŽ@W/>|Pܹ^p1 ?:{ƴs4ڏ3K)>UL 0s~lΉ6[9~1 z4"Wco_mEͤ+"o_u_>M;c7d\HO3@iwx=/]&̂BjKkōm1=0vH 4@(fqmc PO?B9U 2v8S4 ү1u.dN%h1ږ hQ|t::~tK^S|"g O?1|{p}C8(8zp Df@C?)g n Q77.8y Pl_|R# ݨ&屰  2vhcLနj; 7m@ @4RxN4A_ 7ov?amx#3PXE+>4\Ή gN=[ٺ"0sʙAnl)A}i(>r؍bRά_`xryI nÎ%TXDJn̚0v:5cН.B˧Ά'c7(>G ~I *@@wa(7$D n@c[Px̥-V1٥ r7˷:=JkGW3c@h4R2-ǫ+n lCI@t؋pg c7ǷϿE'PTŬ\?+[c7*jy,$٢P(8z>LwQ-Ujaiδ@!g@?qatES|'aCa/@?6@QL@!3 gz `};WO_~-zrgP`oӀ@T (ƇWobI'c7`@+Z0^u-nksεA屭h@Cױ>؍88%Kn-zrgPyHtSϝ 䉱@LjPX\B*|$YqTQ|f@! ܢT"[cG6]ãƒ٧ $C;N#Ag@__Is˷!R]wPc7H4 ]yܢpდ.BH\[nUL ȐvrgssAn h ˌ PH)` 7d(> P|&\4;^'@n+;yekrB`XHsb ӌn9Ty+U@dثQ ; 4I*i$4ҩjmrm& r n~1vKkG׋FoKw!dVϊ &WEe948J$*@@wm]WzҊ ?b^~fz SHH3d[&H4tgW]Z{HٳѭKg\^F (TY#sg]po\;g-7%ww~OQhΕsGn,ۺnٹˍkXZ* 0 n$9?½w3{[ Ho}o#hΫZS}ǥC4@?t 32T6vHJJę4@@.}c*4dF(>)ѳ~@˒'/Tu(> P|N fjdX?CH3EKB: o{R;d4/n5+:BV1h+gc71%hi&4tgdwy:fXyd@Н+oZ7#8(>_j_-Trv(>U _'Gw @݀yA9ԪľWF" k}a *fqn|={J8BЖxހd˧Ά; HU Y4)A/:n`7g,>qbf?ZP_Fzp/@Gd(>0,;wgݍg[x؍qmR*Ë6y5a4dngНgU; o֎n7RHyz *I9b wN\Jpc/)73 g]&AN#ͫר?cAXw3gҦľ}uAPT#\5M|#`8Uv08m_: Oع9tc=$ԕswκunɈϣ~%8Qs8q̫͛~8^|޽. YXy@Y Ԍ BaD;7 ax\|} hրЏnX($iŠgsXd N9y@(e;72YNd(> (`h?JV| g½9)k$VV|&y*Wd$F zQ}`߾75(e;7[b c7i$:xq^ GP7V>O"@a(Gؼt#8i@1S|RNRP| à[RА2?+>3׵La BosiLV LoN3w9R<3us.EE\7e B݀} #8e՟ %Tr؍ܳ3$hZg oD!Z>q] 4R;:4$ѓ-"dc.(>P|"C!|iFN hh:|pE!=;Cq)*S8;56os}PTkG/Bm$}wrEH4R: 7o|ĉ7h(e[ו}frpbÏ&+Lo}2XMn0v,K{6y`ʕ6"5˯Tҙg[t4@_oAj\s1Ye MVqQwmtruэe[-;w}+nJ $C"+7ҫZS}ǥC4@?t씋r[&oLTjXP|,RNu@ܳ' JN>GhF,g nHuVqG:k@w p]]vBn0vN :Y>.B#cƶJنlP֘dU)>P@'=y>0}(f\,*ngbωmҞ=;`8?+> P|Sŵ{D=s9Qg+lYCPJ3gX\4ϼgc7d(>&rO :^c7m@YϊU K Z&_g/UI4gSMn\3ݱYHG  O]^[3__=?k_C0q ne44R Ͼ~ķ ;7:So]קެ~/+ʊC6ifhLo~j]Wx*B6GJ=R|wV1@d腷ԟo뭫3w~O@oe t@@soǷ㖿ߵ5SseIȠuۯ3ӧsJW_qmý}e}4R)AU/q{Vt[nuS|'oOkowܶ{OW*}jog n 7ڹe̔gJSocFw}֬^+G0Dy*k43rP(k%K~=z^%;R ʊY<1MHқ?m{y̘Ge7 %?-ޥh( XS&*6׾WnIj7b%翸zdɒn_~m;yom#Vgz >2vS8i[,w _FWw{޹~mgiXyɓg.;Ceg`X1}gX,%xh[V6r-w:Gg7(AP|&IV1r) f~S| C'ȃ 5:Lq\@(ASdh ^P8Yg$t1vC3ZJ R^P|+jy,gH!4E9 tD}ڡfVg n EtXedwyZ?ܳݏnXnoιKgYDZU/ Yo&%h H YrJ'A-ݽm$;sXil؃z@'J 2u3[g_>bF!2~׊ +{Tkּvt]~zհO^XsL)g сzm2@  .]9|ٚgJ/-۱m3/>{)C?y^ϤJO;v(6_MhqN۷ڼslecG6]2g tVѺmY2eF2%7;44dӊk.zq+_vS/2 :RrܗMo 1v %h E 2}u[kY{J#Gٽv{А$c7*WmR|&b:8s}W*mO^p>(C:]K"+g:#8Lߋ1gO#%衳!]0hJYcc7ԟ)(>M g dHuVqb,f3Q|2Z&N'=4@$YP|AP 2*hy$6vC 4RY̱rc7bpohK ijylgKqȬh s/>&nLQ|r`֫q$&Ȍ++> 0vF PtLre98(A'*NВmˊ@NTc=܀B@d CLr5w[WK#3M(AKh"/ $g'!(>tu 7mKCL՟\o JOGU7=VMo=4`C/>K)U\ou@_К4oڸjjU_ on5wȝg'IXiɰSopaU= @_M|&屰3lqz zCէK?~CH6'}6b*HgrLq)A'Бk Y ݜFOsts r1gȥ8z>4Q}/4#Jḭ?ebKء!Ǖ+g BqXʼgtK[9 U-nAR| b lO _FM0e@R:=VN d$gPfF[xhCg#8~S̀H4PW2vQd{g]g &3OH@ O>]/;~Ӏ6i.>ԟ)Yg>dU6ON5/;<U{臅3W|6H ɮ:f?W.=6}O`P!C[R|$@t@GcylS gg4SHQ}P~n5}4X9sc7,2v`^X6vt:zc\/@~O ->ԟ)U݀Y'I-%h…֤yUSSWZu…p Zn 4e3dHiɰSopaU=&>Vn9Lo69w0׬Wh 4QUӥZ] +oe=}2 X$dU6Бko\۲>?C)>d4i}L @_o\oK)k@r $W'.=ϕSO7'BНxF>n?Cʉaq>OV(A/*N o؜z=a. $ vOC^43tJq`@ [[ϳ(Akn97ԟ!=(%&RtlޱM~Y|F6Y-D+c7ԟ! NiJ8x_/>R-1e0c@@/tB!_笗5ԟa諸s69k ̬x e4if=:W?EJyɓg.;@6}uVquWjX./BxI@u]|tYC"Ibc7`'ɟoyI/BOЀ c70v4R&t@_1Q(n?P|SqZb%`8:*;N.B،ZmgHa'ϐ g*ɰSIi"Wϟ}|xU|v , O:m@7ʶ .B1g 4Ṗp2} *ΐGp4h! @.@D}Fث_PȵA[P VЋ-<e^٢-v mЫڶ#O>]}C\c7 CdpTcnmgN!,mz2`Rt C @@GV?4^1g /:v)e gh}+>p)NRL&A3\ydc7wN#e(d1g(2c7.%hH 3БN#)>Cz(N 7x/s?CHFʨo^t)S @c7+Ce\MVca[o/o :c7ڧ ::dt *ήnmaA_>@v n2Nˠn9e gh*eZRf֋UhId/Baɒ%k&2DH@.ϕ-<Y1%+cdUi7#??2h3v;)%hV3ȠϜ9 pn4)k@-s9v ,Y}}+WRHо\݀q2V *κvHAA߸zjc! [|&] H4@)>Hf43dILٳg,JK.{nE @2L|$9f333ַΟ?K;sݺuzkThܱ3,c7+%hVϭ~mAHn@)NMɠI@[5Ļwu=#}+R2%d3@Ucd!GFʇַΝ;LNg`R^|ֱW3͠-@Ǔ7Ν;=>Cd g4I:87 ~oaT;30Dn ٻ0v*ɹ[x R's/~_}/DyeMHC,Y *Ƞ4Rn P|Ȗjys)g@dбwvZ4 EHƼg+: m@d9=H z i@iٱ2dI@i g g b!\@W%hev}O—(e H]opA7'|E!z`3Gϊɫ{0s)*[6&_3 RM6K"/Z_[-<@R'h!b4@3E`F UjUS8ut薉-aO(A;oh9V @yL^|v *M/@&)>@8{h.XY2vM@>vI *@ O3@qTcd!)/kHɟ>c*W)4]@i 4dU\hQ&OT3v h)k@2>v*H WԟܨǢ%K>ŷ-< r)7Z_Z0IVqq jɓg.;&+>Jm2ޮShh8@ :沆39@Y *9{/ASh pPP1vE 6 @Lv%\|V!=/,@ s1UjX`F*4@+C YWA,N yo9 hr *p=Vq MLymQր kډVPN2L Q|z4RTcd!ˢ#vJVq1  FvǢcj=33C$ldF½[:dpn4\@Yi#[M9Su+m+wP)o߱vt{"m]AL&HuVqa  /.]9|ٚgJ/-۱m3/>{t؋Z%]9xe}wnhn.Z8V.L];9:{ 2k[xPf^hȝK~[|K{UQR%=۳N5p@oRU|v)™9[xndg]t :k7 B\hȋK\~\W7Pyd3CgΆ{67H-L 6}u[kY{J#_ٽv{GUswо+KI-c7%hf@@>x>^2zez\~tWvZqY *̑AJ Y7?L;t3G<|0ثo+4I:4@6?*n0 Q屰@)A@OY*>NA Ϥ3$'!>E%ڒ3!G*WϤAϊ&A#c0N#FYgCY,B 043EJ9& me 3}WsL I 2 2@@(>4U"mnKh 9vIq I>@8YpOG (3}Q3c2@rEv)>Ǭb:QGn*jy,FR4PDC\I鑱@qȠsC iS,Ji$%@ر#tkɓg.; }zT--g0`VqZ[x@Fܩ CTM.g@Z [x(U3D _2g2wu3@ɠB >YgC֥sˠ3A 5zȹg抣gs_(NWdBF*AY@/0vlF+4@7ԟ(>H$RfIh :&4@ǤDie9.>7 |ܱ3@:e(wI 3n$'!b`XҟA~F+4 ȫjyl-< 2b-<ni)؍Vh t\d $UjlI)~ny_,A$h:4d]Vq2gzTsțA5ԟ؍aQ" %bh% s15 򴊇AvF+4̦ Cɠ@\4n $iSMVca6Xϭ >3@%A1/4<υ>Ygi6 ؍f>3@SO# "V|^ +:eS-Uja<@@ H! bȺ>!N\@屛n0H~nyzϠh+ڤZV1iVMt O7w ؍S| 늶+A+>wA P'}7c7 Z;h z/kH؍Ve6(NC~54PtS|HHɨnjxf@oA#4 @ȶ^3ϫ?s(NBY@%Y=h~@&}c7:4R$z_:C@X>珱H@IG9T b Oߍ)HK άn3@wFjϭ8 4U+gЋvϭ{'9I ye=@y&}c7i$Ⱥ⎊ϳȠ{!rKϐcK/}{^SOz{RxNEkW :1/t@ƨ\s^YD>~a|ӥO<%ny>T΃8I_>|ӧKןn|O{>}mf؍Ƞ r(:.T:gȱ{OЇx:_? /ǹ?}zv|?K!"`NZ&$8z/>_AwA dI2vǿ'o@~{ׯ/C_\G_zO>S{~ Ia G=pO=Jҟ8]'}A_}4c7r' އ7TxM.97jsѧC9< d[&9}) #h 3nz,}.g(z9<ܸUo>;>ZIyck5UOף?QM Z|E>4R|.禞'J9_z1ć>r~OOtn?CF8}ڿj|Os&I0.ǫ826 <>gPh1Ͱox~YpvnyJC_&R=KfƼd@ٰHYCQn$¿!;f? Е$nK}s'O旽8Wygk/Nߠ92=O^X.ɓmG@>g3=zy=E 2'Ya"wR E>Nc7R>d@#}c7QnK=HYe s(>1EʋϳȠg@Y"}g4LgA@z,}gz,2&4 1vVo@*jy,Fn+Πh 6sV*Y<űŨB 􊎕⃶p) @rP|ЖߘX"@WѾEPNV\nE|+a0PgA۷OհOڼ᪻7Ng]W}\w9a7e(_$}^@tCEǬVGpt (zny??y>;p}uM"?,^Kz| wQͷ<|x?]ɓ'ێnߌ Лy`;6C >*Hѳs@iןi itw$Uh̦ >CZ{o[؇t*ɰ؍ -R4P|c;뗥ڱ/V*w{n(OndwyZ?3W;ρ:gywD.G7ȠrO_r3C vJ'+걥{os Z  +8i#[M9Su+m+wP)o߱bsR!2v诿r<ښ>ǖ.'~bG?߇}rDy@A/9yƍ^LMM_ҥK=}1s_bE}~\2J#C[oPydsSk}o^9A<n{{vӌ7j֬Y6o (ХegX=Bv\x1Z"+ͳ490hhȴ#gFZ{KWoV_;tn;'} Cmc?8@åxyj=$iWpD=~g||z3゚D'=I-]'ޏ|²6J Y76Yod3Gj9CV+DǬIU7I{1n8~w?I׿?-c[$qĮ]=ڋ C1wﮧ<5fۨR}"}EEOOe!ǎtoo*=oWKT9]Oq$!noJ$|:ۧk׮'#!صOzOʱ'<9rfy y@XQ$~'Ƞjާ AvI27v4[i].6ω6OoFG>1O<+~f]KN)Jw ɫzʻčSn|&aRb߯ɺ;G~x\.5FT}xa$#:\ 72AB $H̱k譲;~0D]T|=O59yя^m'k{k43 W\y-ooi@0??~nhnN =y0}Fz뭿#?# @ ]G?yE|?@@7no~oq…λ(:4tlݺu_K___E&μ#HEt'? oF jɓ'7ngjj*.]|Xr?;#7_Ȳ/[ XbEԚ5km4[$6@0hB @4!`  @0KNB@9.Fkg&Wqm#o߿7aKݙMOҎ:O⁢Ιч]RX.re۷߿_.ED:c;~m/j8)N1R!MDeHPO͞O6tƐ &Q(,k[^uL̄mV34k|ZQ#]JkaF24)#}D1&@U 6m]m$铫^B_O]RXE'uPӮ7Rg8pm/Mj䮋 9*llxcF4>-g9u!!&t3H۬LQ&[ *#j,0Ueir+NNe/O5E#3^s-"=rftI1z`۶mSСCRg}Gm/յ?PSɶjGō[*6'L ojLg!DK*TgTzyx[a&K#t?Y03^ˉ-Մi3ӼºY-Xqt*.zgpxGbZD>|罰p)ߪW{G/\Sv\4yafRgiq>8>dl)=ݔAC*8\@(mߒLR:lV5SZɫi3izMEb`:A\/*J|U #NvVT}ΤgN>=yǏV%;7~~񍋫?%_?r.8;E=hwBd6{T.M R 7լtp VFajNcsݤ7+rM7frec͒;䂚!߳)<#C-vh+#1 5]>Ub._SJ.E}CAΖj.)FEիW?~5o[yعF^   rWjƛl4; P 4l( IV]2Grv4dH /4SJN\1 - vR.lkJN k8@/Nq8Sce`r&uBT}LdKGΨE 6J9}Қet10z`Rܾ}[:x70xH`t10z`R;T^EȈ6% ~.1E-2nER@]׷O3 ;wZ~s*6>XqE|My("_oW9zo^=JEN7C!@+;:]HN V'Wʠ`K$C6u"ХC"NO|ѣqE8b(_˧3"'>?谫WCҍ7tjTIENDB`asammdf-8.5.1/doc/images/drag_and_drop.gif000066400000000000000000026123601502633300400204270ustar00rootroot00000000000000GIF89aLx! NETSCAPE2.0!,L‹(H&L6PF)Tf\v`)Bålp)tix#1)*蠁硈&袌6ygpc饘 馜v駠*¤骗&*무j뮼s:sN8,ˬ9Άc{3N--?? Ec?㨫+D.Zqޒ۸{o-/{ܸjϵU0qٶpjgƏ; o"ϩġ3 39H{֪{p+/L=̛INq\0Fo=FFpV34q:4hl#]ɵ\)L9Ӳ{,:8S43WKc}3Y y4px>n7B7pG.(os'wlo 0ò$kкD/6ZkyxgHW<5Asq?xnӟ8=k `R*v@]@﫝'H Z]-4a*:]CY0G x UdV̗3{l+[:lx b \eZrZKߵ41}UvDpMOaX@lOrKf6p#xEGZGv̎Gzp8x9HBU0؀5 as9m.rD6Ѽ{}_Wpm\G<0(޳iՆ2~i_C` XJi4dMGՂPpԫYmeak;IɃҔ_*6./m'H K{5Ez-F2*wMjW۝:;i%YV⸩MZӆVr pKoirw'[EgZ'ޖTvK.zS/|K/~M/L0;! [rD,i a(N[70gL8αw@L"HN&;PL*[Xβ.{`L2:.6pL:xγ>πxЈNF;ѐ'MJ[Ҙ1 N{ӠGMRԨNWMհgMZָεw}dW$7Qkܣ@6;b,Dd1zaG[~]dn07MrN8}yDaS~dn3'8-+'N[pwƎ:^s<:F0~=#yNɟq~<8Ϲw9߸ mns]αaj0uO]RG=O%)Qt++1:þ[E pvOY1{^yo@չᎢcv՛xmmo8/fo>1x;>7ߗ~O}r8y~[+'-ϿR)@sG}t;mOWpǶ~׷WAVP}8-wcFI7}3rWv*,؂.0eDR w?l8$~ozu= ȶv w8胛o/3ϧ|A#p>8r^`b8G$6pFGZSx@mkX0X|cv-Ƈxi7mSxumKhvXv@ud8nDj](gW8F$琉vpv։؊d7jW0Hg8؋XxȘ7،ҨqPhLqؘڸ؍8Xx蘎긎؎8Xx؏9YjF& ِ9YyG0 "9$jfGp+fQ,ْ.0g1y8:2X`c<9DYFy5i@+BNP A)VyXHL^`1Pfyhjlٖnpr9tYrٔbz|9xdi9Yxٗ٘9 P阚ٙ9IB01@陮Yir YY)YyuFk94` f) fɜ9 й+y3kC#fD) RBZei9sҞky +0ٟړfp 0eij9 IeIjɞHC JiIU.te=$ږD@M:4Z6cʩ=3'zO:E iI9 &ʡy@/'HiS=  .W*ivOj/ Xr0R7p7Jh@n ND: ԉxʠBZYy _=zOjZYP]ʥz[`zcmIvٚrڪI$kjm9ʤ*F*靁ʩjS_SZ2c Yjʝ쉡*kPম:zhXzZ҉?li3BڝUgij-$ElW ;Gi9/뉱k-Ҡ+ejCGӪT;*ZJ9\g <I0JD[F+ E`Jz .ܩ"j  '9+*ڮ5[[8[? ?wyxzیIZ0J.l٩z@ʧDs5:ɬ˵k{![zLI@`q9{ۺ;[{ۻ+Ww{`;[^K˽;+{蛾LJ۾k[{@Ǿۿ[<;{Lf <\& ±\&|’",$02g*6|;:<|x> 8B^~ >^~6˞=&~(*,.02>4^6~8>@B>D^F~H LQC$9>T^V~X8㔐^`b>d^f~`\ͩDP0t^v~xz|~>^u>\抾>tڼk>Np`/~^>^~~낐>^쓽}IGО^؞ڎNPݾ>^~N^~^N~?_? ԛ{{P N.P t+d+7O*C@Oѣ*v:C?D,3_J^`b?dViV~@"r?t_v?NhөWz0z`4z hzoCP`@oP_ ogl{xȟʿmDk-??H_0EO~A?av2w_[μ⛯@D0Ad<XSV`_mNճYgN>bZk6[m[oW%GM<.R&eEu37^y祷^{7_}_8`vpF8afaqCQIW&3ti(#dG&dOF9eWfe_9fgَ>#9gwg:&4ũb;7:jj:kk;YhF;mfma"\)qf!o=tG'tOG=uWgu_=x!=wwwHrs]L3z"ہ>{{~tFٹ6֜$~0}߇?~秿~?owЀD`@b*Z7A VЂ`5v1ЃaE8 41Ѕ/a eXAІ7au1#HSg8D"шGD&6щOPX7 WbxA(vы_c)>hTa嬸E6эlc8G:ֱ&DFd ]hGBҐDH9|rA_r0IJVҒd&5INvғe(E9JR2Ld*UJVa$^<–e.uK^җf09LbӘD.sJW6әτf4?U%c$jLnvӛg8yeLDg:չqH9g>O~ӟh@:PԠEhBrFhD%:Q8gWAϫPiHE:RԤ'EiJURԥ/iLeJ҆7iNuNƒ4?ըGEjRT6թOjT:UVժWMjMwUvիui5j#Q#[Q#-Xe[Wծw+]Uկ%aXY<FaKֱld%Nֲlf5Yvֳd XҖִ`1AZajrml[ֶlq[ַnp;\Emr\M{5χv OBEa;{xwwX]b-l-v;_׾o~_׿ Ans<`[8ˡ^K^Nl{/al4=nPEӄU*#d(wfoHѬh0kI"tI3NwӟgRԧH˗udܘ# 3cYd!]zXd/B=lb35lfKϲ=mjWynv9LV.;h);rFw;lsV4z6ǬTİo~x>pGxp7w%>smy(f,c 5 yE>r'GyUr/yGq7/dn|$>tGGhs7N9Wy*_{ؿ^gG{վvoҟ>wQz#3VY{T|5G||uI.$i›}E?;^G}7z㝬ͺֽsn E20w}h7?} _ٟZ~-2vhc}_h`R-^i.޿~tf$p>=J0h=t!+I?ū@3x>@C y?c TdAD9K@<C/u(?H?;¿{.Cd>4ZZ?ȿB@B`#==[+/1v BLCs[@fj<=,2s)t>E\@{h[8>/Ŀ K<>ۨDL4O|8ޣBH?04/CvLĸ0BTedx.tH`XsHp0>F<>NS &,qV?G FT4G TCWBX@/0E~ByD+EDo.,dlƇȈ$^@`hbtCmƭ@74F7CH| lEvwxTHlH<Ȧtʧ t@ aaɐ?#GlU4ŔHQV$PDE)E]@8K;c|yɛܺӊ+F;4'tDŽ̛^HsX`HtDJt@Dļv\PCKN$LeL DbFbJt D&I=DP%ѵKhk  B DbѴ"P#k!%RyQE$+p8b(s,--!=R%0m?3G8+.u7/9x8O(h\SNZ3`Ijii7.':L]69lpΪr6@%6XCAEXZ^np`U|UkUY3 TM5cճY@^rRy8TV`n_ըԧWIe"5beOduwT4{=sHgt?VjEUZR1J/t7"dX!L7ȐU_ DhD{@Xura-)q5 t870TEzFkXz\bנnWOhWAy,UըU`0XHH}20IخD(XՒV ٲ|H4Em[r[e-q4]Zc9WYWH[@-9W5EٺDž\b=TYFI֫ ؁uU0XZI1յVժD-7 \m[t WݔUܕ]م5ŽՈWkUݒ֮qe)e+Ԧ\Νڒu[1]]uUؓ}V]er yх]uTJ_m_#mW,,QSW֩)4W]Fs4HKF@YeX{0[1X ^^X%fߨ1Y]XMWT\VM\Y_)^kڨI`~XY`C5M VbY=eb]9YmIYEW% _1F׿_-6vcz6.6]`8o֭6~A&dhcܾ cvyA`֚Jd6.Og:duGU6 d751 Xe7:F^6OX`+Z\϶\ X_vg~;`iq XV9\ho6vhPD;V|I$Ar&nR :)غ|@xH~6?{6܉n!$ꨖ"FJ , ,BkD`M( )LKA BO,Lks+4,ϡ&Ɲ n"xj.pdžȆl-!jLόP/TIJFLijNT¶dQ$EVLIU|lPmK<Ƒ&j&>wrfnlnh αlsLG}VBKI|?iBn 2E.6oAhJP~f@j^zn<|kNudTȘDM.iN6'Gkg'qo> KnD^p^$tCT˕\N6LqPKl*__owls,MI|MuD|?ai砜>JI4gstK,r+'B?bwrojh 촫toAPCPnFoɮltg {OQkg}pwɾ{0wloG pWIwf}.xxxWvH:q'Q6FYv64p gIy4Euym'E?vKIvUJMWM5hhgh?G+)ͺӣ} eubij-z-;.}z'85SP!Z{/? iY#m'V +0 ;0K +,>a0)2N21<35|3cUܪ :/I+t,;43U[}5Yk5ׂ|>*늷шF6m+:uq=7u}7s~Db7=b}M_d,*/,卪Yq+sÝ7{9衋>z[{[7~ yFmKԴWp*ClDQnp4@4RyR#L:+<;ޢ@VQj{H;D0)>0ե????C}nLaDۋR@GALHKV.pT)QoBZwy3 :,J3#I$>?A6>!ǿiB[2P@ SC؃8ۙT쁥+Bgz7B=iTuCAD+(t_S$E-jgNzA1)BA<$"#6DҌMC+7-Q{n#G% = ) %mE)K!L>}喚]*K$0)acZ$m5PfB6D{SIh 4-y4 FI"dۈK#WLgm+b2VboRFhW%ְ%k+gyWf ricSղoz]Of.- s_=.r؞>sm TL첿:pݕV.x+^0`%ﺴA}/|ҷjˋĎ1 AgC,7>D3q]JpCHʾb6_~-is-rHU61sïCzuB](:bb_NW*'Ceam`s^ݾ'$5ދ\HΎD % T~sEoƨ,+n AІ~X ґ|gXF8)] Ȓ~2s9i{mh$=\cbwk^ڕ͓RJP%8kUSyrNS2Jٵ<Ϥh2X 𕳼.` 4 hVx@Ҝ%y/pxg28~_Us^/L : Tn>{ EQlJ鉓tpNōRft7;ʟ{A<v=DX5ўEܴ'/XJv>DjΕ\(A᳦򌃢b0+9=NU0Hܿ?Ƀ8E p1JAM:6}Fj܆1Juv ~`D, `M }@ԃ:|;M!ԗ {)M  S̃< r@$Q]UZFavV^a51a ̟1[Ѫ[*3a!!\CjJ@ne"N Dĝ[} i~"(bDj %ͽ:H0m&>_bd"00jq*Z+NP}Z uPMZDj֥83ZY.lZ4 #<ƣi^+NZei]EYQI^;)^[]DuL@/ΣG~$HJ??aI%,U (]IU$U\EǑؐ RM8LQTN-'S>%TzJ=T KK"6y",$9\d-:QH }uEсz[aT^e䝬$T!bVf>戒yRD!]fƍUEݭ}DCYbcb$XJD%Ec.=Q!_&lƦ~| $-Sm ]Ybx M^5:IYU]PpSa9y^CHթ]\;JfSʦy'zF͏!怍v-WDJᵔgzg@Cϴ'1JY.n駯%fn(^]"kܣ֪q(ʸ&gyKj&N(gG(ƨU娑).iHW=ꦍ)g2)fi0j:]gVFj)\h`) N)|)r@~:v.*>i" 6^*=jv*(*vRH`.Ӳ1ʠjʀƪ~Ymē~_m+:X6W0*FkhVٱ&멚YmUJ+T^++~e M!귆+̸+֫wM@JƫګlZ+J;>ql ͪ.,ƂɼB,vLI첞F!kf zʮlLrzka,͢,,,?uk^lm,mlNZlFԂMJV:BvM ʧ֚,~-ڦՄ-.fmن٪-̰-؃ ƭέ: RH.n>J=&..n.禊䞆ÐN)«v.|nAV)֮%Hk冩nޮ/Hn^F+"N+u>/ ]ƮNj/d/o-ޯ/~o/0Yo 07]o80 o;0gpnN89/Vׯ E?x`9C:C8i^ 0 c/T900|-1iH'1oG110 C9:$1qSC:09ȋ1 1XDA021!Grr{9gA 2^#)$K(s.%93'; ,o) װ9%r,sؔ#9HA00q,4O1D'9TA33CN38Ӳ0 r/ov s83V󆬲+s3<ʳd0>{q4A?4A?&`.4CCC4FD$EW4tFV>@9+4{4^H =DJ(K4N*L4GtM[MP3N O4H5SlQ"uRR7USOQT`P_5XciV/xǯTw5VuX5%@5]׵]ߵdpZ75`Gt45b_}u`?vµa#uEp3cB6gk)5^]k\:g69vglrY\6f7,kvn6mmj6qC%oo/vpkpsqTrrWs?7vctt;su'*[gxG81Tsl+wku{vvzSz W{7~_a|Iwcv}wx緀~sH}8iytoϷw'8u_xmS89%K{%g>Sw[>V=0~~~"32>~=<~4KGw˔<#3kH__?ˍxq# DysϡG>zuױgY@o^˛" ^w%76NMry&,6>wNw< {_)w>DRuW~i uNqu;>uGA?zIc`z+}ug+jCF >>=`ۄF9·ߘ;l'\M>{3x35+ ѓ9=RS&"+{4Ys*t 7;ApD2Ɣ ¬E1\t .d9ϰN1simGlH-^nx T4oGFkFpIKL"oJ:r 33錍2N ?۠tp(5I1̔MMRGN RRNHNKWk%OtI o2IDuUJɜS;U$J Tx,N5*SJjSnUU2OZumoQ"W9YyuqX5X?%5Z&Ye3auZUɪZk5\7[\\\\ѵ]K]]u^ ^[U^5_^;___O_`J`3` vae aYRa6bOaWb%b-bIb1c Jcc=vd dMdI6edG eUeeeafIffmvg gLgy6higw hhChghi+IiWivj jALj6kj1 kkՈk!klHllvmmLm6nm nnannoW 35wjo d׼LtpImXqoIoыo!rGrr-wssKs97ts tEtttQu{Guuu]wvg*qXvy7`dwr~wxWq7yoymz7mw{wk7|ͷi|gַ}ew~c77cw 8ax^x!fl}p7w[rw#8cm5[ʃAEIMx]7JY89Ņ% e/ʆq E}xI8KD PGp-x0Xj؝x&8n*8gx gqXw Xm8̘8/xx捹)8=ď 3ɐ)DyycI)9S$0YE8==UGy3kQy|Ti9^,ٔBu9nyry5z~9y43Y93yy\Yx`9=⚳9ˢf甽YSyչ9sxXI9y:YD9:b%:5;3ɢ٣AFIɟz$La&8Z^:mzmmqZtzO;见3(:z:jTzeu):ګzx٩:9z溮4Zzz(?Co {5ۘw ;yH-{H9;³EJUMa+H{^;m;T"Øo'c˨':I2ٺ+۸Ye{!{|;[sKZqb{vɛ9i黼n;xͦ;{ܹ|Ի%({1<ݻ{Y3<+ܥ ޶AؽY%)A"69==6>v# MQ~=J~呶3La~e8^ u>^~7܉_yQ9狾fy^rh鉃^eExy~s~۸5ҽYXQe _ 9?k*!ߧx+`?(}A?/_ɝK_EqU_Ba^e%h uO'_ypW"[_9S_Z>%z_ù{~}ܱLɺ_ߥ?? xsP:H … :|1ĉ+Z1ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{ 0(BLQL:]4TZ5֭\z 6X<6ڵlۺ} 7ܹtڽ7޽t$jR:6Ō;~A+[9͜;{ :p >jEC~ ;َ%'$;ݼ{ <.z0k֪" =m=ܻ{>x^5ۻj}ۿ?'o^S{`mA`>aNHa '؀A&b"b&b*b.y!%c b>dBI$i1*7dXdRNIeV^%EGָa7: fAeffjyݖIחbIXdgzg~LyYgu矊.h>jfr䡖^JUni~ j4"Bijj k%ũj:k l~T으l> -Nzl6lnm9^K~nˮx9n"xnދofn KpZoKWoOLqKp>qt_ r"n6q Lr. &6/q:skμ\7>tJW tz 5F/MuV_Maӫ u$NubMvwZƵjvn wܟ}kߝUrw~DvMxmx/RpFUxlx_F+9y袏^n9ޠzlߎ{Ni~O<¼5]^|?/% rHB*r3!˕HFJrs#H9Jjrٳ%INrb'uJRrH3)UJVr.s+1KZr-wG^ s>/ Kb*s%+lRd5,cNNĦ7+mnSL9)qLD;߹(u[=+ySGħ?%}GA:$TDEC".D E/:!N^ĨG?:%n@IO:=%EK_=-MoΔ:5ũObQ:=ESz.u6MUBg ދTYTuAժį4dm[/#Uo]W>w_b#k~z%)].\:a L*veK^!+5Vve1vv~,htXҪv[d,WR4m!bZ~E-Rsۮַ)pw/=.rF[J}U;^֭ v ^rLxkw E{֢ﭯ9^w/yӿK[n*\;xœ0r%L KŰ?<2`$.Ox,n_ x41 㓋 y5:.2Ly<$+yLny e"TL(k٣SƲ f!oyrό4l> 8ǹt'y|M%.BzzFtShC;)<[Г~r?N.&(OTIU XҤO=kּuPvk[!6 d@jl[E!ӞT)q7];IڶqpO&xύt;ݍ ں os7m|?7 oՈ{$ +| o7s t娸+p0| P`, 94pC#ÃQ#8In p? wV#頃ab#(O8Ώ>p0 wy…t/\@˭k?G:at_wx5?ص\ ! "a/;0[NOS:qk>`z:q /χ x~g== ^wVh?Ppgrhuk|{g}Ki k˄l˸fr+Kk˹빟 +KkdK XĊ +Kk˻뻿 T۬Njɫ˼ +KZۺb˽ +Kkd[ŋ +Kk {˿ ,L{Vh  ,LaD[ ! /")+-/<&/k79;=? A,CLElGIKMO Q,SLUlWY[]_ pK*P@3"gikmo q,sLulwy{} ȁ,ȃLȅlȇȉȋȍȏ ɑ,ɓLɕlɗəɛɝɟ ɤJƥlʧʩʫʭʯ ˱,˳L˵l˷˹˻lG1U,Llnjɬ ,Ll׌٬ ,Ll ,LlG! -Mm  -@m=]!-#M%m')+-/ 1-3M5m79;=? A-CMEmGIKMO Q-SMU`RMIFPD@C0B`gikmo q-sMumwf6b{& ؃M؅m؇؉؋؍؏ ّ-ٓMٕmٟٗٙٛٝ ڡ-ڣMڥmڧکګڭگ ۱-۳M۵mۓ!,   #%'*!",#$.$%/%&0&'1'(2'(2()2()3()3()3()3()3()3()3)*3)*3)*3)*3)*3)*3)*3)*4)*4)*4*+4++4+,4,-5./600712734956:88<::=<<>>>@@ABCCDFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___bbbddegggiijkklnnpqrsttvvwyxx{yz}z{~{||}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}}}}~}~}~}~}~}~}~}~}~}~}~}~}~~~22tG4dj͟0m`@!,L7 :""=$$?&&A''C((D((D))C))C))B))A))A))?)*8**1**.**,**+**+**+**+**+**+**+**+**+************************************************************************+++,,,...000222333333333333334334334444444554765:86A=9QD=`KApMEzRH\LrT]ehowzȦЦөԭѲϵ̼Ⱦɹ˵ͳбԲصٷۺݽ޿22 Gnܸh)\ȰÇ#JHŋ3:lQBIɓ(S\ɲ˗0cʜI͛8sɳH@ JѣH"ɴӧPJJիXjʵׯ`tl!B ö۷pʝKݻx˷_ULÈ+^̸ǐ#KL˘3k̹gˆBMӨS^װc˞M۸sͻ N{ܹ=+_μУKNسkνOӫ_Ͼ˟OϿ(`utDCr& 6F(VhfvaL+Wh(,0(4hU1J4t@)DiH&L^?TViXf\v3RihlpN)f+Uix|f>)Jj衈&袌6t褔Vj饘fF駠*ꨤjjZiNsh 7)$˪`Z\/.g%^plc#xD+V5c ϵLCI"qƽ1a{сR^2-ʑ+Z˧,ngӽyP.]L 샋l^ ̏MuIȁah? PfpZ"6+begä6GhAr۲hVe,y1r<'8,LT"]cNwӞt<1dz\:' ; )TPTJU!@ZGcwXJֲSXuֶpyh%׺xk׾ ,*M:+Z,D'z h$ciMjW[ҞlgWͭnwJ $DMrE\.ЍtZ wX ME0q wtE2Ǽ.KnTgw0{escǼXw+_'o0_ ǿ(E7</%FqUTsyd;PΞ{b7 ;ANؗð ^ڑy&s}өyEC)| +wMΙLK4kX9ʐ6ƹЂ.)d[VĘ]ɵWӜ~N mC6tthQX%'PD^PNMJ7G>/k!CĞ/kWۄFCkL[ܰn5j,ZYnw`wM;O3ԄDXZGE,o-gPxr-vS\`5u;TN >\0$%tvofl}NE7;CgKBwWlh<Nv0=~yLqov͊7K\@7[skپ~];?|6ijGOI|-W%F`wGɤP\T:GUţZڥ$ps^:dzhxhťl.p:)$tzcx|ا:姄zb⨐:"zB\OVĥCd$@>zT=_P OjګydZᨦƚ҇ڬRƬCZFB֚Aڭ7­2Z暮Bڮ2}(:)fzX$[~"k ~';K{"[:&{%!{*).02{$I1;8+$-<%۳@K#;8;D+F{.[ON"I&R[*$LдV«\RJ dk!Q[{hj ۶n[p:tv{yQɷx𷀻{'{vkۙV7+W;ۙt W˹p5[yXV˘W+[Wxu )wE vP V ً෋+ ѫ{k6웗[W{ {|ze 쾁U@R\Aс <$&|*,0,2<[6 K9| =?ACE GL\NB RQ\{XlTŬ^ `Ƴ;d\f|ƕj|lzpLFDjl6p-r=.Zvx&|-~؂]*Єء^ ]5n\}\M ڡ \=mڧ[-ڭ[-۳=[퀷۹ [mzۿZ]zM=ZMzɽнZ=z]ݱuݚZܝym큕]ީm=}^y~ 9^~᱙Κ ">Y&(╹,.24^y8:}>@u9DF~mJLcPR>[YV~XR\Δ^Hb>d^=yhj5np-9tv~%z|瀞>Y>ސ>^yޏ~8ގ~^>XnԸ®^x.ʾ΋8n~n>X쎉.^x~8v O pφ?jXob\"$_Vx(/*N.τ0H84O6B:<:@B?2XF߂H+LN%RT_xXZ^?`8d߀f jlpr?Wvx|_~~_w~?~7}ۗo}}?W|ȷO|{_w/{_z7ğyOvb/s?0Wp؟ܿl/i_veNb-6`]O@ DPB >QD-^Ę iRH%MDRJ-]SL5męSN=}TPEErhTRM>UTU^ŚUV]~M#Xe͞EVZmݾW\3śW^}X`…5Xbƍ?YdʓWƜYfΝ=ZtˣMFZj֭].\lڵmƝ[nݲy\pō/r͝?]:jӭ_Ǟ]vݗV^x͟zݿ_zǟ_0@$? D0AdAt0B 'B B 7C?l*CG$DODq"SdE_QcFoqsGҵ$H#Dr!dI'2%J+2)K/-$L3rL4dM7=TM9N;N=O3PA%7@ E4QEPF4RIstRK/4Ӳ*մSO?59蔗z٢z*{*'7?}7}߯}%?׿%8@$)!8I$1iA8剐' Qܩ/ a8ɐ7 q鐇?8 GĻ)Ot8ųIWŪi_t8ƢgѸƚod8ǒɑwّ|9H !H})#!9IuI%1Ini'A9Jf,)QJ_+a9KWɒ<-qKP钗̔/9LI \1LB)39:It53i79,ѹN<;94<铟t?: A )C!:IEE1i=A:R`y'}IQR/Ka:SȔ7MHqNٔ?eO:G}Nf*OS:jJWͦUnj_ W:rgMgRк2o}[:w\׿蕯Ջ_;عuaش(=]!;Y 9Ŋe1٩hugA;Z iQZka;[Ȗmmq[薷o;܌Ed]s;]Hu;]nr㎗5y^{;[j?`ot=hBЇFthF7яt%=iJWҗt5iNwӟuE=jRԧFuUjVՊ:qhG,tk^׿v=lbFvlfzv=mjWv*#3 !,\j     !!!""""""################$$$%& '""(##)%%*''+))-++...000233466673:81=90?:0@;2A;4@=8?>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~229G*\ȰCzHŋ Ǐ rWȓ(1$dʗ0d2͗#Ivɜ:yzAx;*}h`K&ljTXQ5nH֬[G@ =|:qku` NFݬ#'Aؿ%9J ?+Y.k T^K.CMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνMOӫ?/JÏ|>ϯ?8`o[`-G}G'!,            %           !!""#% )$",'%/('0+)1-+30.4206537869:7:99=69@39C19E09F/9G.9I.9I/:I0:I2;I5HA;HN*JA;I>?I>?I>?I>?I>?I>?I>?I>?I>?I>?I>?I?@I?@J@AJAAKABKBCKCDLDEMEFNEFNFGOFGOGHXHIPIJQJKQLLRMNSOOTQQUSSVUUWWWYYZ[\\]___``aaabbbcccddddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~¿¿22;8A:>A:?B;?C@H?AH@AIACJBDKDEJHIJJJKLLNNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^`Y]bO]dF]f:[h0Yh RiJi GiEjDjDjDjDjEjHkLoPr%Sv3Vz=W~IYPZW[_\h_qawcxdyfzh{k|o}sw|~p]}Jw9r-n"ljiijklqv%{-8CHOV^htîɪѨuקmۨjީiijmprv{LJӕܟ22 40ḇ"P@-JD< LWf>(ߣ<_<2i=2)@58PmqFO3,hA1N=i`Zvց׎̴j sn\ `QZ{pႁ`_R [?ijI&&*Ű8014X ၲ!,L?A8(   !!!! ';Rikk-kBiMhYg_g\iUhPk JmEp&Go2Ij?LeMReVYc``ddfgghjjjkkkkkkkkkkkkkkklllllllllmmmoooooooonookoojookoonoooooopoopoopooqomspjymcl[mSnFo2u6y36:>EHKT^jnsvwwyw}eL;0&!   ~~|zxwrpry%:Ncu݀܉ےٙ՝ҥͬǵٺݳ܌ً։Ԇ{vu}22xLX`oZȰÇ#JHŋ3jtiǍ^Iɓ(S\ɲ˗0cʜI͛8sɳO JѣH*ɴӧPJJիXjʵׯ`lEV$-Z oFP۷pʝKݻx˷߿LÈ+^̸ǐ#K{˘3k̹ϝ'MӨS^ͺװc˞Mv߁:ͻ Nȓ+_μУKNسkνOӫ_Ͼ˟o\GcϿ(h& 6C-fv ($h(&&0(4h8f? O*f޺>jgjq~ Dm뮝v nދnGn8q2.{lzpHpClƪBApK<8 +,4lsvZ0f3 f2 3ʴ Nhc}N" +Guʱjp-3BW gwA*-#.F4ۛ6+LW%s, ,\sZWj \#sBG^R{FB8t'7<@]6AN/kq;߇.Sk\-b7y>;[U@],qY| zGUNUCz 6EBIz&`:GC6^5<߀ I]tX N”%Ok ,[|~c;p: EH2h -Dž}+k7bC۽Vלִկh;ՀCGAFD&@슩GHcc HR<!{ٺ%\{#ȴ K"ȨC;b?Er7LUhb0I['9̍-L:N^nY<,ȚV3z`mŻM<@LU[ L5KwI*Nݝ.qҖ0N 9O*a gQ:PJԢEQVeo:TJժZ5@Izծz` u*ֲhMȪֶp+*׺xͫ׾ ,*Ml{:sd*IͬfKYn hњMmK ֺqf[[ x+q3?!]4wB1r9V=^w^ݴ7M|Kߩ.8uouC]~c zN`?$3Ͱ7Nuwd!psw0΂+ N0wþ1k`񮁃"sq)H+#%MQz{n%'A902V]NV=|exγk;wtnuqg PF Ac$P֮K%e͍vO,>8Gym _7ӐQ=ָT IKo߁hɈk7#ȓh!6IW[@f+{__fsUߙsvO@#d_8޽ZZja;c+8͜)`݆浿-nӻׯw{ ?{X.5,D8tʟ݄wv[gw8̏ꃟ|NyC;J@bALnTWku#7SV5J1YCVFs=F{鼃Luu1GKP;D@{hϼ7]hH&9Oқ>?Wz`sfOIO.Џ/[O>OiOtOO=8x@# X7[.`$0o"8~7&xW(,xz*؂02X6r4x:<@a>DX5FJ[HNՄP8TYRXXuZ؅^W\b8odxhVΗnmtXr%gzb|U~XE5N0uXHFxɓX3X2(Ҋ8h'Xhb؋}s8Y2x$@ CyX|hڸ&b!X쇍明y@ ٸ$Kx؏DZ9y y  9yI"ً!9&I@ p,)-2YH6戓:ٓȓ>BYHFˆJٔXNiRYbHVYZٕPȕ^IbY@Hf7jٖ0Ȗn'rYHvzٗ ȗ~Y$`[@Oyy(yYW2$/`Ykَi9# hU:r,   $yUĉ#)ș `0iUi#0؉ʉOGU4М٩ȹ N԰ *T)# y 9R#琝Н pڡ4/ǩ$(jJ I,ڢ.0ʢ@Т8:<ڣ>@B*cFzHJb0NP0)ZZѢ`b:dZfzhjanpravzx `|'+ڢ]ʢ_zzaڨ`{ڧ 'ߡZ^JPp  ꪳzjP@ j] [@I ڬjଥzZkBZ JPu@u *͚ڮJ*j^ [X jJ֚f* p0 vЪ۱ { ![&{JШ_ .`8[렳 ]°Yۭ[qP0 L z]L봨: #M[Ъ;0 dJ0jLk-0+ 1  bk:hr{cV˴; zz B;Xҙ౭c {;w+[;۴o˷дR+s˸ ěwk\k۷q0z;X[ ;< MkW+k+[N"٩F {P0 \|k {p` |<   , ,<  |Kh..N1ۛe0,*ܷvP<)>)PkHKxp>l%l\'l (+ b 1NNЛҐ a`̸uÆ L$ ANP,Ŗ$DzXL- \u@ƥ̳lʫl*\L(̸ (^̫Ð<`p{4ܯ`NLʖŲl<ɓ\ɗF᩠ʢu \ĥŨz ϯ̫ͬV{ϖ댪 |ΰ< L_p3N0 ` e (M ]&. 2#Z\Ō:<>@@Γ @Fc{}̠.pI=!<;V1=\#5m0:Q,phjlnY o֥uB^7FEJhN"R^DVʃZq^b^nfjn2[(v>BwT$|F) >T~RN~>4[zN^Jt霞Fp頮\d<^$ꬎ$.3^n##~"."^!/n('@՞w$n&8>^r^A_<с 0?Mh! "?k*. 2!@)?8y<ώp=RBD_~H_JNP>TOVߞZ\`/ ?h: gnko?Mxv|_l}ȱ_AɁ_A//_}ti??]Q?E_rohOɯ`Wҏ_sڿޏ]??=o??A_8/`# DPB >QD-^ĘQF=~RH%MDRJ-]SL5męSN=}ha`AEETRM>UTU^ŚU֥B rVXe͞EVZmݾWrśW^}X`AFXbƍ?YdVƜYfΝ=ZˣMFZj֭]\lڵmƝ[ne\pōGwr͝?]}]vݽ:͟G^z벇_|Gv_~$@D0ApA0B '$A /0C 7䐴0DG$DDWdE_(EgFoPFwG4OG $H#MH$dI'\LI(J+ KJ,K/IK0$L3τHL4dM7TM9N3O=3A<4PAEOBE4QE3tQG4RK/41J3SO?UkSPG%TSTUWe՗Ru5VYguk5W]w V^6XYaXcXde2u6ZiWj6+ն[o[p%"\ueڅ7^y{w^{7z__& F8aS;xa#bb7渭;9dwdOF٦SfeKZegk9oֹgSg8hFzaf~v:jۅzjjY;l`ll֖l߆R㦻D;o{ono'K G<)WqNjdq'1r/|E3s7[=v}Ӗv;|vw.w~8߃'ۆ7>y嫣}yy觧2tA>{x{￯{'G?}W}%c}G,~ǟ/_XЀĊ@D `5@ VЂij5PA8B' QB/ a8Cɐ7 qC鐇?8 G)O8IWi_t8‰gѸƺod8Dzɑwǩ鑏d9ȡ ԙ!ș)d#!9ɑI%1Ɋit'A9ʂ)Q{+a9Ksɒ-qKl钗/9Ld 1L])Ϝ39MVI,5MOiߔ[9H笤9ѹL;9Pʓ,=Tꓟl?:X A\*C!:`J-E1djmGA:h'IQl/Ka:p7EMqUy?O:T G=QT)OݏS:UHWeUh_W:V툕gLѺV$o5[:ȕwՍ]𩕯m^;XaX(͌c!;Y]d1YMYmgA;ڨiQڬka;۰ʖ-mq۴ꔷf;ꖸpܧ(Uq;8u]hߝw;^Myѻ^Jz;-|^5~<6` !|_ Ox{1nb%Q|]x-vsaΘǵ񍇛c=폁|[!yE6k.ɧuGe)U앱|Y-oy]cŎ̇5f5m|W9yu[ghAЅ}UE/zvS!NGiMӝA}SQz6KQꕮ'uGkYֵq}Q]zC5le糡}OiO{ն;unnq}Mu{v3eΛǴo}~K|7+U.tGq1~Io|#AE4r-a~G|5q5gtEё~E/}Mw%NGՇu]~C}e7 ў'tGwu~A=;26kx!cO>ȕ<1#oJzCQoeկ>˭w=a/Ϟb˜{ݣ_f?7>;/zv}oho?>G6+~ci??Sk@X#D@[S̵t@^ @a , @d\Ag4AjCdAmsApAsLAv |!$By3#$TB|c&ܷ'B) *B,<-B/l0C#23DCS5̸6tC89C;,\?DAB4DCDEdDsGHDJKDMLNDP|Q$E3STTEcVܺWEY ZE\<]E_l`F#bcDFSe̻ftFh;FklƦnLoǣq,i4*tudDBw wǚzlx}t~rƀ($ȓ1ȃLTHJȆvbȉD(ȋȌHȏzȒ'DɄQɕ̧tIxjɘ~ɛD'|ɞ Jpɡ4ʂʤ&duqʧLJhʪʆʭD&ʶǰ$k1˳Tˊʶ·K-˹ºK0˼ýK3˿LL6L)L'<ĴXLd&xLJDL%̐"cLϤ%Mь4M*DԼdM-#٤ڴ$|@Td5D@2HA/LB-OC+RD)TE(VE'XF&ZG%[G%\H&\H&]I(]I)]J+]K.\K1\L4[M8ZO=YPBXQHWSNVUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaaee]hhZkkXllXhna`pqPsBq9w0z)|"~!%,27=BINSVX[^bgmsyŅzn`VTRPQQQRSTUUUUUUUUUUUUUUUUUUUWZ^cimquy}22 vI #JHŋ3jȱǏ CIɓ(S̨ B ~c͛8sɳϟ@K&4xpL ]ʴӧPJZߔEKTÊKٳR6t97.ݻxKT]zD È+.L>#kϠCCCӨK^ͺxb˞M׸s޽Ӷ߼ N<;>(&CwS$z=#(w_2uG4|:=P=w}g = >eǃva߃ف#4 4}{_<.۳W}Oˣ.??u+/~+g@/X @ye8GU7ム%H;}P8C^5ځY8fq iXCЂ;9pw[! |Fa iDt(xbc: X;-ZgDɇATF68hG> ~hg~ģx<WP pTGA u:AT.@R^ G B, [29 %?zi_"5!gfte5 QT!,35          !"$%&') *"#-$$.&'1((2**4,,6..8..8..9..9..9..9//9//9//://://://://:00:00:00:11:11:22;22;33;44<55<66=77=88>::?;;@==A??BAADCCEFFGHHIKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooorriwwh~~fs~}{xvrnkhd`[XUPMIIKMPRSTTTTTTTTTUUVWX^djovz~޽22 / *\ȰÇ#JH@1ZȱǏ3<ɓ(/\˗ W M3gɓbN= USУ<EʴRM|:RՓTE^1kFMa3`l5!ءx]Kn4^B%6h-fu]6+^}wxn4[LV ?n(on'k:c=Z>D-N2?],Id/Mc7N]FPROOPOOPOOPPPPPOOPPPQPPYQQmOMUCh>DQm~|x{{y{{{}}}~~~jS:4:FT^cnyՇǮϷʾþ٬ߞާ22A6Zj*\ȰÇ#JHŋ!z1c'R CIɓ(S\ɲ˗0cʜI͛8sSd@ JѣHɴӧPJJիXjʵׯ`txh"]˶۷pʝKݻx LÈ+^̸㺔"KL˘3kޜϠCMӨS^ͺװc5۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ#VϿ(h& I(dVhfv ($7&W,0(4h8(@)DiH&M`LF)TViXf@:I\)dihfW= f5&HF^+!)Gm̤&7.bfn#ϝ[ї)FEJr scIk$hv—Y=b Е4^6MS7v6nzs?di62:t˃&Ys;"n`egpgٷbgʜ!k8\ƃMtZF7юz:u2 &yclBͳR0LgJSKyJm@ PJT4eiQԦ:9*TJժZ+*Vծzt*XJֲC+ZֶR+\J׺ї׾]BM\[X:S+Zݨ\3zd4(ҚhIֺjcKVmoF׸,x F#&m,\N-st6ŭxK^7n&[RºenKKLUvכb#/}_ۤwMηAox R/u[J9%1fg6c|_O8x7pF2Yĉ_o"љׯ/601lqRINu+8xޙv9T.6};3=aDԛ<+]nu\7Ũ&2c ,hOxNwGp;8ad]ۧ'oϼ= {oқeoVOoq/?򋖃x}<6~ ؀Xz 8xx؁9"Hm 8&x+V(,(^*؂02X6Y4x:<@W>DXn5FJVHNTpyPXVVRHW\VYHz]bT_8fxLUhl8Sj؆prXvIR8zp|؇WD~;8x+S(.؈X'xq8&MX92"~Xv x؋1#8("XȘr،θ 8wHؘ#"X}明㸎H8xً9 y  <  xّ0"ɏ3#yȑ(è,09&I8i  \: h%KzNjˉ-j8 : 0Z3~XJo`J+w*U4Fcjp0+yJ:S:"С:* ә%lѦnù 0Jz*V ,:2Z j᪩ *jjɮw ٥^Z9J%9M  0zj *-  ˰ *u+ [*j9 .@ {FʟZ;*mRڱ [BK*J*1˱E !ˮ\ZA+ ʥcZ1kifyɳ=ڵ.ZЭ/ ]j{z J:d EJM[[+9:{gij;pڶ:E+"@v븎J‰j:jJU zZY a:ZJiЉ˱љ*{#ɝɉ JJ[ۿ4rRJJ+;0\xE,f"\)#&m0|[64\[X8lZ <,T;@@B=?9MDJLN4]1҉pXZ\^`b=d]f}hjl. G)ՄPv}xz|~׀؂=؄]؆}؈؊}[,\U}Yؔ]ٖ}ٜ٘ٚY@%,Wڪڬڮڰ۲=۴]۶}۸ۺۼ۾y']œl&}w||=]}؝ڽ=|x}&Mܶ!,\Xm׫R}>^~ҽܫmM"M ߉ܩM])] ">$^&~(*,.> wΔ$܄[0D^F~HJLNPR>T^V~XN)=pI9<-^Ynpr>t^v~xz|~NVEb #d^;.@jCVUPS>^~ꨞꪾ~ꛞN]a0 .DiܖY`>QO>^~؞ھ>^>Up_N68+]@nVQKJ_ ?_/IK[~0>nUF`E0C :<>@B?D_FHJLNAR8_FO0V04a.cNubV+npr?t_vxz|~?sY$' =+_~]S+?_+`JUC&_׌ @jJʿCNa!}M[PO/A@~޼lAП?aˆe#+=QD-^ĘQF=~RH%'QD)Ul ASN=}TPEETRM>UTU^ŚUVF#yFXe͞EVZmݾD9e(KX`… FqE!IDbe1a97fΝ=Zhҥ~ kZj֭][Թu"\p 1IK+1e^Όstխ_Ǟ]{Ob^xX0L-U${b߯S\~s\a Tr2b 33A0B nB /0C 7 =B!'B>#EWL^1F [A [b*, \C!$H#WH%dI'B6X+J-RK;1L1$z 2I9N'3O=(Z&* Ĉ2/dQĨ9(8@>ZL֌l20S>OE5UUUsUW_5ֳM(0C!U`ŕ;^!V;\)vl$ɠ@ڋQmE$`.` 4"r9š pl#5NY祷^{O˻{zi 4r!;YQU\IxVZgQh36?xm%!s9٣navCMyflfwY?A̢[ 2XTEU#Udqe;*aBzck\RMYll1 {;nyn[ Qh\urbT{־{/kopHEOR1vUW_"LCD=-P<4"i D6 7c#-Xx[e+_yƇQhJ=A0 / 9Mjέf6%I!|vRIĩH~ @EN/`9x@r%Fu=8qtY䠏&kCfJm1|65y]鞸7oNE'eD IsiVznrg>;v9I.̲s*.̀ $ջݎ@ Bsmlг( RvNjX3h$5|%>O R WVǺWf}l`3RJV?}k]7R˹*ֱ3 QVֲe5vEa{=E`" MCΌ-[ֶ4-ijuFvzmp˖׸ǽ n[67F!3\V*ŵnvKѹ/pUn׼lѻ^o|3h]/vW0`ZYXvm16I$O|gB*tyg@7яt,+;5]CFKӟuCMiDnwUNկuL٤<*sm9˅f譑ѕ{"yt!SVw2ևu|_Z/I=o2׭u3]vʋvå1s yAmNv_@RqsGy ;C9 Xox⟅/|;}AaSrx d"sc?Ȳ9S< g@>?+7>mc8k$ s:W@S=?l 3 2ܓ @>ț?ͻT >l(J@n[@ Bx@D# ^@蓅ü9)@=&̿s8̹ 0TCA,-t)t D=<"?z9W?5PB<3E\Ec2@#C5ĹJBFSȞkHkȅ\Gv*wJǖztɘ ;3AIl{GxɟII˼7=! ʥG<ɏ,C|I2ŴJ$ʪ{Sʮd@$K!ʰTKLI\IYPR 4DTdtDŽȔɤʴ,Qh`-8K[MG Z$jgh٤ڴ$43(ϝg]=I]M3epPU}U]5%^@+Pp ^__u5@R@(_I_DG$c`%55S  U`Eִ`aa&vaEC;&uu^޲&b9 #N4#vb0Kb%N@&(a[bnIRWXbVhb;3)c+cqU038.6n{cҥc=-;cccB-@fge+F;H,E^dM,Kymdp}d3S,PeTeNX0Vne{J].&]X eed+[.-e8ff[j*g~u;!fov1`W0&mn>`qYfft.hN6wVfwggy]lܔ}\Xv߂ޮ~gmSgFpviR腆_z{vhfkhh}&i>iޡVi_ci6i陎韞WiFj!^RΞvjPj֬꼱걶HkfA~~r晸Fklæ&>3lĆm">vVzv\)m{alֳlԞ6m6Cm֦ՖmXqVخG^m4mV&nT6>2Vn2cn!5M&*n힡4E YPINhfhh&v$E/0N {Jhȇ|Pg`΀ف!v:g]^;;pGq:VJ8c^s`uym72w/z9ߌfzy 7y7 )Շ Կxw} ig>2N!^oϟkПf=}TW opw/lG~_ϓ p482WT? GwpjRv'[Mvv7ƣ^,h „ 2l!Ĉ'RH"ƌJ-\qc!I8Rʖ.b!D(ѢfҬi&Μ:w'РB-j(ҤJ2m)ԨRRj(]+ذbǒ-k,ڴj\0blR%#@V0,,#`^+lNeU!gaq8e#pۆw(O0`2̏+n5حcȑ%O\e۵‡/n8ʗ3ukҧSn:K۾%wnݻyK"Iwo0,ӧ,yl[pgcHal : tF)H"dJ*L2i7"%x")hs\"18#5\re^z_z^|pGdU* /1D)!]zCBcaB!o"6&q9Z-y'y'8蝎H'aFXdeAiged @%z)b֡o '*+z+RݎXJp2Q6)rYYN *jTn!p"z.k.kW7=31u2Ntn* c>O(@=l[O/t7 R0u 3Bnf[ CDt5f,|! AI~"!g-o'b(!˅D<" zhCn)R"$$ ! &^ē(1hу2R5!WHᑱvLQ=NnjON1sU_k$/ ВDzfnَϬf[%:hA1LCpJf8;X:\ 3̺Of& Yr8 sKz5SZqQ323JPIAmqD! LIYӶNWok9=a^܅y<&BbenΖs;V$ׅKj]sV6g6A =gyfkc;.`ᾷ/}q>#Cd5 xuv傹ܠNDvI 񈸵8<97yu.oH^D#9[>D~*|/sq=is3پkkVMw|_. `[*1E A RY m`2^z~` ƞଢ଼ f [ t`a٠!Ea>!-!Um]nQaz!u!&a4vvҽ*af!^ b""V! ""F\5#>MU?^RbM'n%^bAb(2("O")fb",_ӱOab"_-~"-#b\zm/J)#3n+.5c44^c@M#55je#87v}8V8c79:N/u?RZ?d.d@>*d%$D61>]E5ebdmbANI$HCj$G^XF0Y^WN%]v\e]]^ZZbZ&o%b `&bbF 5c2PaҔRmM&ge^f@gg&h~ i&7kNjffl2lf&mJm1&pofd[p^p.q:o:'-5'utF uru~gdvt')'z*ykz~zg@'~~''('A&}Jf[.(AgFN(V^(rde,:(rf(((w(n6ӈ(֨(ƁB^vh&(7h)V_nv|>iV^).5)0J)6Eb)fb!*g")i),:)g).3ة*3|).)v gB*V>(haޒvp(P44TC)S+)q4(>+FN+V^+fn+v~+k) 4hfv)ҧae.婺@FgkL+$+̾+Ek ,$ Kl>!w6,1,źB8Il^,YǦKjl4ql,Ȫ*Ĭ,֬,U=y%--&'n*Բ"ԭ*v~-؆؎-ٖ-jA(۶۾-ƭ--ݪ-&gVQ-B݁<.&..6>h'-V^zBvg-Jj̃.ꦮ.붮.΁APB<Ԯ...=mkv亹\FN/V^/f/΃%./ok"oNЃ=/֯///=t/A|/0隯)*(=T_0go0ww=@| 0 S< 0*p>pV/ T=00߃/wC/=0p /I71>tq.#hȱc=P1Z1n i1 K 7><"/2#7#/2¼B>L T#o2'+2>Pq[~Aw (w0=沨Ar 2-HC?/20027/k+p 3?30(SB A_Ff17G/75=22>3??22gA3B'4?4'r';& +1E7`A)d3F[@E_C72>3KH=(4M3'@,4tM4?7tI72E78+%BD+rQk(P/I2't 0VOLCL5Pt>+*(1X4Cܴ[[G[@]?12ut3^5`u>VKtuL4-<6dGdO6e?v1dK 7`Le6hG>L?i6j6jk62]?1l?1Ek@n?/bOb70vEA-rW6¸-s<7g r_7d46w6g܁is p>h A@k47XA(di@zwwso; 7gqS`7?GtsV,ro}w7 >l7Ol/Mvv~tw[GӀ;owZ8x>È/p88Q!k!B29'/9779-l.L9W_9go9o9[5P8bkgܐ?9yGCCC98ݙ$2::''z2L9PS(/:0::Ǻ.vqx>im9;:''8m~:wY:oV!o*~;Ϭ,A|.;6-C  _{  J;£Xx>LU/(Ɨžķ|svY;VG|o,ǔ,|;0Ϳ<ͻ"X@A$<I=[Ů =]l0ҏ @8=[AW}֋ ֿ =oOA|س @\ڳ=wM'>Tl}X8A=&}<Ə;oSb!0=G}>諼~=]|}> Ư}~{~L?R8~~' do?w????ļC},׾LQ .N@y e+S")2$wHre˗1gּsgϟA=tiӧQw Cb.y2] T^߿>xqǑU6ysϡG>z}%O1~D #C4x}{Ǘ?~}׿ f馜ࣧx[ĺ ) 1PCZkA QI,)pB %0By R!,#LR%l'е (6$PB6l PB,3LSS7S9BQ; âx H<#CCMTEmG!TI)K1TF4,p .0QSUYmU|UYiV켓;Z"s@EcMVemgVikVm%vPGu:u71oMWuٽ5vWyѴӧvnaOf X .NXn!X)X%B&qK-WRWI.wMNYY+W7>uBy矁Z衉.裑NZ饙n駅~bԍk'8[ .lQKט{Պƛ[\ /[nq&W0s!L)<ޱ-\YM;Eӷ0߮QO]Yoa]iq]Mj/˅'9/o´]ymW}^_/O_'?ns<#8詈zճ@. t!A N1A nЂ-T?%4VwBLzG_ qC=D!E4"k^ FN-La0;ڑ!w$0e4јF5mtG9ΑuF1__EAyW$!Y0SøGIN%1IMn'AJQwE&4!]KYljK]/La41Le.$YNe5MYҖ|7Nq49љNut;rv1=ɪk擟<79@y5AP*Q?!Q3Sh nGAR%5IQR-mhFGxQΔ:Mqj=OTE5Q:Ԝ.DZiSU$UUUnըRWTfYњV=-[ƕu]2U}_Xʅ5aXuc!YVe1YͪgAZv5iQZ©uka[&mq[voV5q;Y&us\Nյ.D{]nbv^񎗼oyћ^de{_ɽ} W6y/ vp[` Op1a wAl%6kG|bŘMqac3q<=Ewc!ȳ rd%OKv\HGUr+|e-o#rf1c6|2mvf9ϙƉsg={`Ѕ64m|hE/vs!9?Zҕ)}iMoʙA]dOԥMjUիv3jXϚ uqZ׽{yka;&=]c'.mi7Ӷ mlo۞vn~[6`}nuۮfUwǛo}oxp+V[ wx_pO|y1^9g=r{#7ɧ rRya7\5yh~sC9ρ.E/ЍtKwtO`zձu\]]:Sua'ٳnvjgۓvronwzOw'/nx/g xOߒmyoݚyЏۢ'mzԯ٪gz^ײgm{^պC{_'#m|/_g|O_ҧ']ro}'l~g~ql?UpCL 5p'L!pM(M1pK9ApKIQpKYapKiqpKyspeKWp MK ? p ] L p K p J p sL pJpgJ%qI q L!q I)1qYH9KAqGIlPqY7aq)GiqqIyq}KqEkq]NCKqY-KqKq7DqPPqr P r!Q!! !!r"Q")"Q1r#)"9#+#Ar$3Q$I$;$Qr%CQ%Y%K%ar&SMh&qr'B'y'}'i2(&(Y(%r)I)$2*9r*#*)2+"++!r, , 2-q--1..1-&/YF//!s0Ӛ 01%-1s2m2%21U,3392.3E3NҢBs4Q3M(5]5a36es6i6m6q37us7y7}7ss "a888S8s983:s:::3;s;;;3s>>>3?s???4@t@ <AJ!@ 4B%tB)B-B14C5tC9C=CA4DEB#LDQ4EUtEKtE]EO4R!,/LCm     !!!""""""""""""""""####$$%& '$$*''-**0--300622855;78=9:@:;A;F=>F=>F>>G>?G>?G>?G>?G??G?@G?@H@AHAAHABHBCIDDIEEJFGKGHLIIMKKMLMNNOPQQQSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22۵G*\Ȑ #J(!D3Vǃ~1H(#<%•,]ʄSfJ5męSgG}~*$͢7a"E1ҝ'>mqjҞVjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k޼ A78?99A:;B<=D<=E==E=>F=>F=>G>>G>?G>?G>?G>?G??G?@G@@G@AH@AHABHBBIBCICDJDEJEFKGGKHHLIJMKKNMMPOOQQQRSSTVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22G*\Р #J!D3VcG=2ȓ KDɒʕ-OL53ęΞr͢F5r(DMErz'իXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹τ/c{!hFOZ mlٴanݽ/x\]˞Co|{h~5>T0{(K_R w N#/ OD jIC!,%           ! "!!###$%%%$&($'*%(,&),(*,+++,,,---...///0001112223334445556678899:;:;=;B>?C>?D?@D@AE@AFABFABGBCGBCHCDHDEIEEIFFJGGJHIKIJLKKMMMNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 HН;"4xPÁ >TQD2jPG=~)rŒ&Lp%ˎ.3N)SJr ROe~P`E iD|4EJ?TZ:`S$ʪ,!5-ҵl l=.ȯzr;1iA  ':;/-(Zo^UMSr7Qo*hㄿd, L b@!,f"P            !!!"""###$$$%%%&&&'''((()))***+++,,,---...///00011122233344455566677788999::::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___bb[eeWhhSjjOmmLooHqqEssBxu7}v.w(x#x"z!{!|#}&~*,04:<>@DGJOSX^djqxƪͻ|wututtttuuuuuuvwy{~22 Hw>HŋȱcD C<^Ǔeɲ%E(cr粦K2s59e"%I-'EZʴS=(ҿÞYʵ׭KYxؾ]ڳaU%eEݻu˷߿L0ݷH. cK6Lx=v^MiuAN˴qQ:nyڤηx$mqAOwkk9蟳q^n4ۈ;t˳=fG|7ɳGѩeÎca_ye hX߁ Is tMx 5H2d|i3_V8&!ipq%C#јnӍ:Z9xNW9TYetܔ[)@5:te)$ 4RV%YWeriiD%!faU[l5`BUHME X3TYEE%N!,L)B7LB9L [^R3  "9HF < 771$#!"#$!0F U`l&q2z: JONNOOPQV fp p n n n r{'5:!~~~~~ ~ ~ ~~ܘ"Ƭ&!  !#}4|EwZtqlppommmlllllkliik\ilJumRrmtgccO$ {uuvvvvvvvvuphge \foqyquevMxIzKtLsKqJpKo OZ PW TPc1h! q %&'%('*)++++)+++,,,,++++++,-74==IIQQ^W~]bchq媉׺ͼձ22qSFPY2d[ȰÇ#JHŋ3jtkǍIɓ(S\ɲ˗0cʜI͛8sɳO JѣH*ɴӧPJJիXjʵׯ`$FVdCY˶۷pʝKݻx˷5~ LÈ+^̸vHL˘3kY3ϠCMӨS^ͺװcKͿ۸sͻ Nȓ+_μУKNسkνOӫ_ϾAvϿ(h& 6Vhfv ($h c,0(4h8p$@)DiH&LBG?6)TViXf\ILdihl6.b)tix'*蠄j衈ף.&裐F*餔Vzfiv1h33@#&H̱-V <+Spm"l)l:+pΩÙo6*k-qԪz+a{1x7*GoR +,ަN Jrj 거0b \8:rq f&rL󷷡-Dmtyꖴuִ0J1O,+n*vT-Wܒ]Nb]˪:ss}1ys/\ш'+4nWPK-ݳ?K *~Ȇ8²ݢn)ln-jۮ'N ;:Fs̭h:p~L?чnlִ˭|?Soʵ5y+T[Te+\K `b53)+pgYR͂4|ƻȡ|ˍ&("X&CႣl3`8>o[;qb U5/~HLDi{(8\th+)]pM||# tybV6 aR!FA#^{QC3 DH/VsȖ&ԙNz e9YrAWn##e3r7Rݬ61{#,ɛV1aƤ l#F ~e- 2sg&'_P&L]PL:N2;O\qR)[j\I=ADZVS|h\83e$AIt: zw'w TQB EMn8JХ mLgJӚڔ9)S3:҆Xub&@ukL^ÔR ˎlTC8eE/k3u3NDIu(׾ʪ`X#yӾm'7N}qb44vc3Zͬf30 q\fWֺ-myb ny+Mn:Ѝ.+Zz /$Mwz$|{ͯ~\E `N0a XsSCx7{MdGL,(I|bx+nqa98q7?; !y\$ϸ:L*[!U|-XѲG 'KYXNip&Lg5G,:psg?ς6ulF;:7㈣4cͣ5hD}v`3QszӾEQa TqQHkԥ i}k6tLbRsg]V6l0GMӆv3ˡvAp7ܸuk=^טyެ{֭ͣAhvm|z7 .fttc[Ӳlp6Am:'xuAr56?!jC7ͩn]!qE$Λ{?7i>pGK]GˇߠKDMG+Y8>\0t;@ 6#[!*[;_|-=[+7]{_Isݞr nfC .͌p|{i {yWj8p0\'Pj6PPvw|'|vwp1y(R` u h p'P|'k"8jB87~jG(FȄIxI8M~RxJLs5 6E  tfz}jpm7 ؆j ҆|xyr7 ksvyy ovoP}8uZ}x H8("SZx`Y)׊Y8gWxW  `rpp`co jFoq8t&z7xFxjOдgJwx xȸli·cXxra֊tm7rh6 ƈpth|jo)(jǎ '|p0H}#3h&G%plH˨Dx9tDYFx נJٔNɔװL~.הP)IrX KZ#le8Vc0(v6{Wr lj gzx{Їq<)חwjtify(wkhwwYyIy dN&SٚٚIm`vc-u1AGvٜ1ihv}gٔ)gҙmrI"S)ly`I]9ѕav 9$b|ty p * z6S$Z&*/  d,NѢd':2 `a @`BDZv^ȣNPZS8TZVDSzZ\z4Yڥ`b:)_:fzh'elڦnj&kr:t$qZxzz#w~"}Z zڨJ:z:ک*:z 3Jڪʨ=ZjjVګ:ĚZȚyڬJ:z}֚ڭƶje:zV躮_ڮZ]z%@c^ {]k ۰] ;{[۱"{Sj ;(*.D,2;4{8K46<۳𲳵ՌB;D[F{HJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶O+@Zn;t[v{xS;X|۷~;[{۸;[{۹{EqZ ۺ;[{ۻ;[y)PJ0={`&pK[{蛾꛼˽ и*Sk<\| <\|ֻۼKRKK0(–{ 0p ,0>@đ+4lA-,Ĕ  [XZ\^`b<²v$&5H՘-T ҾLqh "*lnffl)zy>:^Nʎ +^NbO| 4-^ĘQF=n\ &J,G 1&L}YÉN=}ThTC:T=>gJJŚUV]:vТ[`11tXS^-umضnkj^}:w,ூzQ>]1ȕzJ*TCYihҥǏi֭][lڵmƝ[n޸qqzIr<I͹.Av:/C?p e{^>-GH̃O>nH鿉ϞKhiJzH?(4P. 9/841EWd"( B:mh8+馜mJ*%Xb"a&ʿ!dB.򬴄$-}I'钰$S3)N K;s={M+s@ PDVT̳'E 5z4SM7SO?Xi5HLJ.9KE Cr#&U7|ashA`j!>GBq!j#ل TAh=b5>8r<@r ]ZV^Y } 쏗DhT&%;9(%K/)[ PfYbj)-N EMю:Q$OҦ7)NMc'C&E'!OCԍ"K |iM\LgP+j| B#ɝȝwCX᫜«YbV 5UzeS? gb"z&d!A4P9VR--JG',R1QK*mlҘlD :SԓZN\m)Hd,!CCvrZhdw$"^'Dwaa7w֨C}i 6Ң8] ]X'+!WY~b0|-Xm:H_y3,&X/`H= e/ 0v'J0`Ƚ%Y2~i(87 ',iIfړϚ$w'j,Ct0=Ft/mXZӟtؗNtN: XKH$z9%DEDZ->(,@$KJG3['y,EGe#y1ΒOfkm$I:ٹ5xsսn98tCm7( J %L( +7,Nnd &ʫ36;liQh{ڷ,Ay-eVZ{y -im18-U =t݊~C"&t7=~xԥ>(WzF">=Y5y ]+I5uwLmCf6df2>'}mJo$}x 730Yc)ѳyw=O!πhʲB i}ot4;=ɤ-3yW5zwG?;>f7==dʄV;^E\տ(󙗓2K$2=A>D2LqS3 ˾ پ/?Tˊ1S@ 8?:6";b1ѵ'-,Ө䭡9dA;6C68%+<BD D , K 0243D2,8APӊɨ#ܿ?<9?j@DI91M 2LOPŨ[ChC(`5ThA9Ċ\<7CBL?RIE,$;fEAQ;Q L=C4ҧ= mOH-CϕAF`ہ_{`v vF%`!x~-6suفnHRa 6W .`  Nၸof aUƅ sa[hbb'0լ m^#ЃVղ5_'qF;-i֗Qc;X]F ㄠq"`MqM`*V*.aX &eWV`Y6Rb d[.b^Ne{/TeS℠ba6WOuf@fcj`Q6f%Pea慑fW.GPfbx5dkUܟה\=]! صImzP-KphAe}ZM<5,\%7VG6Nd({`[陎[-[hna*ifYvvaf_[`_f.f`jjet~a#5nbe.jj>篦epbjs]bj&jfuob[y^{|}6hC}I>DM̎VE.hM4˭_:l+ Vm$ՓmLdSA{z߶Xgt`%hd_f~eV,~bf"^gc&Vj[( ff knjakNfa涆k.e*hpfe%.s&fo nqpb]]Ů ^;.h-:h'lnbUhf?PVqcdMFGjEIt28! HFii ߞ&hN6baV.o+gaftrFor|f|f2`.la%en7 nfr3reyeq>gn?WaVao G E _;~ ] ]6?\uQK.OleqHX I,M28%c=U1ڵK.&gfjofvsT/nqo`l'wUj!VeN~sr2`MGf>Gneb kkj_rvf`_p(%vF&nF#M-^_9> Tq^uYOueuuwPZ_ϴ [l68c{@LTrUJ`?p'tW_vw~sWxV{f~fO.w)o7wm_tt~A3bMGڒ'O1Ҵ ]B)9֭R}ߚ0B\&\Vhܧ|29?/g eozL'|6nvk@߳?`7pvOenxwf`SfOsF+hP]4[ !x@lu'Ɛ"G,i$ʔ(o}QKP,XdM_vt'РB- 4Ѥ SҨR:DɒOr+ذbi BrDҲgӮZjV^:'TX-3n온ߵ|`༇)|gf9w mPZJ(ԲZg6$ 27‡/n8ʗ3oTiO m!aaPHG9T%zNhFs !-D: A7P|D~ҟ-TaH)}f}ED#jaJt3qm4cF$ 5X|-dGf*EзDUZy%JiPL;$M`O=VR`1fgJ=&u2"蹈neTYy Op'gx9[vأJz)\ g )U:癠$jmz Ԩ )ZlV[q!t+ ;,Y36i9bcJJ{-j-.}-B*v;. 骋1.ڣSh:P^3/u Z\gu]bo>)l0/1Y19 rl$ckxqc3A =4Iw+oIp-QK=K-tjazb86i=o[X֠q|7jYg|Y2çͱztw ߒ8ʲUNü*33^:dzE:>kT8;; ?<-ZB?=we}ϽsZ*僥p?(_x< 2$I0u/y2 {:D'/| SH"L}Ca@X0*kB¯/8QF(!qt %225TP-LHF 82̅!4#g? `Y+h1*=XAA;E2, *ڑN6Pa,lsg`Q |]21$"F Lqd=Y2-` +5$T~ ѭF#ai?&|&4 D>ּ&6HJ1, &^2YIeJOol@I4bw 1$ =>LeuL8ut =:Q~çRgJo͍r(MIi!:ɘj6\OZ:jRBTl>/ԟlii0(([C.8(VjH^*XM zy)JUMFe2Ɲ ?Oj+uSYP%؟bq+_ v(xth2 Z,fհr,&I Z%7 Od/֔v4Ae`%\,uSk'::MM1kV+ 3n.x+ނRS7[E⌋+loYm{!{W*Àq0SK'n~kU ~p; S-K[gr~k׹ߖ=wUe a&n]/s)PǸU-fԨNu( umcY3͑,)/vW~ ӻW7bfi0` .}8wg,WF*M?AvǢ2ZNX Cc{@!E-*ӈl',a JKM%Ć\kWTdJ:mR\ʍ׬ceĽRқ4PЂ.4 EWp8q-olsUVI5jh|U|fyݵXfO}50}浯Vʛ垆e1my/?fp>7c.MVJWlnբRRIRtPu^ L_o{ 5WQC[645헊d&QN~wL7OJ=X(8<xNoSf#/3߭nܪ s^Gt`:zEVvդz6bi~j|DMn=;x>Y0a$OCN+.ǘ#%wU?7_{<ŝmމ1oݒ[!MŘ]9 lϵ͛Ia_ w-HxC,,Ԡ ` Z 0 ZM` YT0TR<\БQ<[Xҝ~qQيa 5\:U\EqQHJJ> .Xo !f NpH,̂,D$N"$B^"&VDz#""yVI!vF" PLqB9A=PXpa蕡Pm͘a M.>`T<E% *~*Ţl,VVXܮ:f!nI 6(I|$N=F,|B&#?v;#N|"WY4aX _Rş[ma/ed 0__1^J]$2"7[xIFEm-$8Cr#9ݭ#QR;jD' ?pI=c>,@?v%kpFe*%Dhk<Rn?EA*32!5F]TH^]REjaXDFNLYLAHJIIҭnٽ/ݥQb[_FI` eQt.8@$I@eTR>9̂Ub84:BozqnJngr.8r4x,L'm.KE1%dh7T,7N!BŢME bbWma'ō3Q )DhejN h [}Ť}$U8ݐJx"7gz'i{h? khC=RZv8iH>bzkAt΂.e-G0iZzp ϑ&'cjb\FFeT]N. ŵ'FD 2&@fvLk!$f؉!LfYx>Ƴ EV]2Y*hSX6HNn9xLXre8ꍆ f,ʦMkV i*k¥B@J\ [(6gW(̢c@-cXТʧTd7]̖,af*ni>a^Qbjm)ٍ'gbjʆmcXE.Pf&!fDllmh荮U..oB^ؼkVhAC+[hvFwwb m=2de&i`a)A~X&M fX`mvyJy$.(L yB126$Rn0ߦ(lM(ON,ަflj,:.4Cu,t.)ڃˁj%[֬j'(.+_(sSVz&gx(^W'Pe|'R"d6ci ՗qRF6%Y0ṔCuFzJ1g ՚꠯F"KD0DhmB,tq˂/ޯo,")qjĐfp0s *gr7L:0@..j.Qie%\ۗ:aT$r o2pPY9jI0gxٞbrZ&p!)b+vNҭa ;q@򰰯F`G'p1'kYj/4Cn1tlge[%7Ɂ4BqqeqP)2V!WO|cp2Qk'+2i+mQ<ɷDmC h<G;??F-0P1I8"2's˂% k3NP| !,sy~/URw,61XU@`]}2/T{U'~h1V\{:4i--Y^^g&[k/I)bSGB2S5-Jv(O+ Ӑ,BFb(P`VlNWv65g P5Z)oc!2=E"mO$ڤE `.04&' .o>Y 7&DƵ kYTti^Ki[j*6w?OExYyfSfgP4VH/F|Ƶ*A2F}^bI,ic6t o3c DbϽO v4i=7|E~st'ž[vz?zE{osE6&ucuh9c0.lguGXt{oX'"s)?F :FW1θފh-pˆyqy6cO8xiitS-W<2e8 cx_k*X23yaٓR$GWR"scy.USF:p9:ycO&:[4>tTӤw@yO\M)REEGDw .k`*380OCyzX56WMSF4F W%T{mup/|!cRǻc5_7//Wb+[h)iWwy<[6^6%%_ '{;m3zq3< SOZ4ži )Թz#i;gI`ɗ=&a;hw9gl!ԸR}ˆb~fx0{ؚ;S 4r/ײskxwcWxҢO ybݔ&~#~W5G&p;نmP, TUh>{WO8jzw>EWiީI1l}{\I}3i=@,4PP2aC!F48"ł{(CbG^t(dI'QT#E.Yl(p"!ҠKhTΝ*=jiVHsϣ de%J\h_Yg͒ Zoƕ;n]wջo_zYepaÇ'VqcǏ!G+qn:.; ;0Ȣa3l#K\97[ģ̑ V l*AKJr#S9ORp *QM9O l0I-SQMUUYeQLʊJ'z"" >Ӓ|H⸣Jg4ءlMI+*P0+j =!B[ٓtW|EZl۳T.LA.Q[-NXY|50:eMVs]W>5>(կ&bezO=e,;֨Vgs\m3g4SyΚpZBZKʸ .~`.NFq5ՠvS< ΁ -I'lѕC[^i ls3[ {thw[4$GzL]w[߁^f}ku*֏[{͑y⛞KOFsc;MsCMЖ5nJeSx!+abV'qbBW5ucTNQsT(V'u)D:I Qus)ۣVz(Cf;!eoiE#_될WQZ׆6 -aCڏ|1[6Ȏeћ^Fm##V鼴Ut\Un/q>uu>c)G#`J}M\"43$Ϻ־ĥ~av:RkyAyqw=Oi#uq㋐^v%:qYU=+2@;r~\HI; =HKbw"pL]]LSQBY*C:vCu" OҕCdMdksHP IW2_R y13q2:4Sأ]CDZ[d7LJCm+RKĦ imo-<xL^M<@KavqLuMQ}wbXlsQrcZ>e;[t>eo89eM܊Y~Tp~pD\|1d{%&VŃq@V67Hү]cF>ў=. dna=g@#6ґR+2Ho`f Lf,jQl2)/- V=-% $c:X|}4$0*"B 8$$ur%$ /i&A,l**M2-((%M)1SB/ B0g ccƾko ",˘"ЈJtC ߦ-"L,aPMϟK%034 8r` Hr0b(s;(!;3$8( ,=Fд o|q$B5ñ>i72%0uM1.coB/{P,3k/c?k=i;A;sD9;DQ17 s=5JP=s+1,17,9FeCH|:q[vr l'b,[HDEDtDL4EɴL cE_EEգ&i(g@4WxTfSh89Y MHl3I;8 !TB` A5PA"/Yj'TFٰ300LMDLU5<4ԔM5k(G/'Y?)5@ix!6#C7[tA!NYT/%9e9eXV74nCKTDRuU1[U,^ mYbFiԓMpU%|9P,$qZAB6uYɣ0"6GYT M^͑vfz 841cw1udI*T uR%SFN=22Hb_(7R6#P 0>!:U.YVeGb;7pva67il d/εdO(R8ih `Lg`G fW_M3U4TU"5h+fLRՆ:."6i#svmIqMdTvrkw]-5Q^u hܖf[6'g7iMF% u˒v+9N;VGWsR  xbk)7y_resR=l3^?| DĦ)<f_b͞c_UJ^Ssu Pt9'0b 8" 4/UxHxDVy X)7&Sw$[)Id)=O>SG;v6_ />:=v}$v X}$1T'v~qCZ7lwo#58%urhb+r01t'7R6%,X,|Ia+SN9!xcw884KhݣŦI nXPN]KWW~jchu T2AǂX q|M%k"*PÐ sAmxx},U[u ->3XxU_18SZ3V GA`8a{N(َ#Ps\uyٗ9%9ZJ|tCU7 $x$N`-R-5%+U,hC9Ǘ45V6it<6yQ"nwgruoG'$s6'zK13?thVu!PQ[;Yx|[:jaxl$p@Ys/s|IW}vWVnuS7:PvG!Z)Rw}J1Z)MCLL)*!:s"?z촎5eCBowX:!6#j8> 7<@֝#QI"GA:.)c-³B Ba"l<:$:/>Qok' *ڴFҷ!TG9۔sZ/(ܽ[^6kPł= y8)uZ~g {&poK]\) |'f4yǛ]$pə9|eĽܲl P|z g1{C;&d88yH oH향%ɏܜwe!l@ \+(7ܒ w+˿ӋJįB;F[U\VnE'U8 dzVV8NNں~DU)8[I$|/bfXʲ{օګhk~H<>Y9YU^&>r!isݍY' 3K$ "Y[l@+Y9^/q5|۾>YM"B.JVMR{>n[_iqgd :He0Bldĉ PĈyLT1ȑ/.QA"| 3$J4ѣ˘`11B%,wgHCsHSҩ"J5֭\:5iW_fk؁e zjJU<%T"Қ87@(U<ڿŌ3&Oǔ+[9͜;{ :ѤA[˞լ[~ ;ٴk۾;ݼ{ <ċ?r!l*s5N.A.M_[]uu~[h 'P*`@aw] X` `P ԠDE((sɕ \ E<0!y=e"Ai?"Fc6ވc:hjdBIdFdJޖrִ8s1Aga5(AX’%PdIL "0(^ ekPq.teѝ% f Iߗ %{Z"'a+T(hjɥGiR d&wbfIc kzvZjKފkk*[})%U&xlAH{IV=@N"ƧZQҎյBU2T(R)).E˚GUI -A6dLpY.p? qC {N%w[S~.&B1AaEr@i;`d3L,rjgCMmB)]uE-7q%glbA&ƌMvfרjvn}$OI%+e@*gwmrLt&:1ܸަ*k3E/sߚ+$ ']NJWXuSwwbf.9jz}٪/{OpO|϶Pۯ. EmZF3sOyUoPޛWy ӭ&N~,[#o,`*p l qG4n&Y>1-dzw4\Ҳd =ZU" oJnRD}cY K+nAE;2xCdd[**p\g0qdT t1-|y!FvÿNB6ΎT9!>DŽq}m SM9J\ŻF?-1A'ǂvWdTr`,+_ X-JHآ ɾ0@HaX^g"+$ld$VCTO-̊'HѴQdf͗|^0tEdq[)|s -MdKD":{f&p,!DP+,&ꀂp[ѨWMkJ -(7Ot( ş&dx ˗Ѕ ăNiϠ wQTA @MB=_#LJ +qdV*Jly5]!(~"!I[ȓo+oI\ZR4*2-DaSaVUOMј8A( HƹgQnKVVf1mkHHhZ _] w. n'}z5NG.Kt[Ns4Abmo'9ޞkyʳW{}k>xD$^+[yox? cNR3[4g㪶+8ZP ެe3@;wdGwH6)}<.}5bc-]$w%pBxs[Y.@ ɿG7H1LhӹG—WV u>`OoW0Q49gY>,cc:g.hU17~GJFH:'z=Nb/Z|Џ~,=Ϗ~޻s~thg%W#o t}g+"'Vyf t!|qqqWL'0Ey1t,7.ugy~F~+E~/bjjzƥy{vE;HSGQgQ1Uu7/3kjglƀj"t G%)bWKǃ V`Qw>/v,(]1hw$3H5x798=ixC$^NXFXWG5|r5}gsp)7U[|TLctA?eS!AcshSx$z8|~8j8.9iPnG.wSivZMR(xpZ~:J x&X Ȋ(-֌}ȏ,vv'WH׃x(Y}! Q/'XF9HVjUǍR84dm'?Ձm ي!8eIEY~hqŊ *ٸS&9c &"8-8p)EQ'!tdi^hGW1(BYo?i0Ci!g"DBX>X&;h)dGH%`LBiItw Rd!sQv9n1czĚyhY0I pwC?X2?@l-{9'KO9֩cX9dݔ`討أӓy1Nћ+8i+ȩ|x" ڠ oA qzQ؈gB@hu}Y-x8yc y!(EI^#C{i11#z%iVy)~J8B1O Mɤa#g52e%.a_pI i79ږ|$DiDH+^4k1{SxsD RZUqY緥Qa^YXJ*2ڟJ!V!I.槟* )(L3mPm$1cxa9<j#*vΉJ 8Cp[㈍5SBBn:yR0ah*hY*X9ܪ&Aaڧc s )[^tj>7Qr8֕o2>f?DzWӡ8 bI/#UiZ\*?S n]akj!kJ١^Jj aK bk g 4 Pk9*]!1JQ:Ql/1z!Cr4b+մ#ZFרUk[D>s[^b뺩V4hvx1NPv=97QwKEkwj?b{ SA*}-3*xI3+wpں{]d;Qq 1Y c;Kp9(Մϻp%K&^0)舁c;L*諾%)n P`  KZؙ/2;ڑhXu|E4"gY2̺/U2JNJT $l&*F~&zBKS]"#ak*mJkKȻTz ( g I5+(:[a[轤ȝ9s;w,(elƥrkz ,V^̿)Ԡzl:[B]+-Ӗs"G v"C=nɳ6͔-ǭh}:΅,>1#+0#Aj_&}#3kC={׍-y ̼9On ηIx XIuwn2. x\jm欪5>Һv^MQcB 師&dL^\Mόl-4MȜ[Ra=jέk6= Zwk!-Zn# O٠} D :\3vNf^ߩn!T8ܚ7/~rGxR": 1>O(ͧyN z +Y<](/n=~ hI" Co YEO=6>A?y5EtW.HU'm`W] )Z N[q@ ֬WA .dC%NXE5nG!EW)UdK`t&Jh҆. DJ=.c%3DTYQRYc.- :u%,&fru%BE˲lKm[ԻLaf--:4op:U*U,J|_%h- :9%ԁI6[ulLO?efz'^qɕ/gsѥOHPuٵowG$RYmtK쪴wТc6p,0Ϝj$D@R &ϐZI4Cа%0S&K)DwR2Q4OZiE6SŜ [q4%hsGb+Q>/* QDݐ-骴J,rK.n<0sL24L4*Ϥ$]JrL%쁥֎԰M3<ӱTΕ=Nc GCE $J HDEt?FѬF0q!t]ԏflMLө>km5K=|y|ӯDo^7xWޣįy)1sGi;C^4۫OP{wG%zhz&_MmݲQlѥ!T}%=_Õww@xˣ`-xA5/WSJBECƶ'/1 ._ '$ݯBg>Qt2\6Ȁ#fQ[1E0Qe8H!Qn5BN:LB)?B֮W+i BÔjWM\"yA$uf)Ʀ!:;"qm&?Ǝ!JXr8^c-myK\n:cR$EDtIu<1wHjdIt&ζyl@#6(AU+@m"?T1E41Ku$K4eA zPD aKk$;D`њSu F9zQkmӣDzB%UIq.)٤Yԉ%qSѩ7w?JRDA$[zJJs'.|+IR7h )PoEhYz)4JSM6 \fVʵ aX 1+7u)O4aO|glL"B&>oQ7q{1w"ScjoUV"+Z]Z"nHgbQr'iQW~mtL"ߎ/| YwaEXt%m4Y>.@.t6\WKaX\m}V寘|P$7=-MxB*f&-5K_|^Mm\gWD-lbyTuxgwᩞ ZUyqYCu`-έ+pi<bHV Pn Xwer`)_9E5.1(pJ=D1Kl6ޏf>&td"'Zыi[$=| l|h](+1c&*T cWYj$~>3_ k#SC_jToӉ 6`]\05| lhьvhv%uGiR`fFUbQұ)4:+lf')LI|{~SCFѱm_]ct=5j/~λ\TZe.!JkN0|6-1S!1Kly5ݐ_ aszUSJZqз@s{ $>>`# ;bB: f>3,Y:B$⾝0I<ټA?55S {? KZ=#!{'e/۱ X?,B#L  ¿苍[{ C碔aIɺ^ik3Aٸc S:Kv{A2|b̕)L*̿V?!D-"#z~Ɓm7Ts?OȸHDG<88TI1Dʼn 'N9C,ɩH)S tIJ<eD24[LF>qP¦IAT:'{EtJL{86<Lr35ɥJ|dJp 4`J,J̋8ʆ4|KĐ"I;ʁBAy2ǃL xG{LP1Iv\E!*{Ɉ $MİNsG\G8t.D|Ot7[ N44N P{@HkF<;s̩ 8+zQ&S̜D}'ϜD ]CVtGtP͏EHPOŏQ cO-$Ф4P5 Rl=EH6xԳQHk,;J Q%,Pu\ ALBIS4e&_z &4 F!T,!R#=TDRTJ9 818 l8 E6OπOBU-1TD VcTT^JF=\$]֩tBDәXt( UɊH%MŠ`V}W}:Y5 9o gesHT_+VaW#$֔3V4Wy-9'\# TH;LIIG#U חPQc}tӬQuW,W}.NYX; \u}O֨WO9΄jUZ0Z XJDbSԺH4=V (k׻Y8YKܠVYm[W[/(лIMmݜ" Љι*=%ܑ5 Xu/]s0WAY\d@L5b; u[=4[-J]beT|B]]Y Z֤"88=ѝ'R&}\0Z`Xw,WUJ^ݕȽUݦRC ]]}]EնnUV=OqP*@ԥާW֋y s<\Պ7uC}֫,-v"ш߅V==}Y^M_ m_] ((=)k9_MR L=YWDؑ̊/\PۨZ4) R5pRGCvش.Na3ޯNNYNFzܝ( G2Ք`I0CS _c\UU)aYuZA߬c81F2>cNv45>xrIT&cѥJ>;>Q剨Ubڧ^rx \d +ZƫsN ݬ~K`Ifph6^T%%h$h@[R lHgz`13#ƊVvQe$'yJ b~ cfQG3&Մje/:Mjd~fBghgMsejCpZvYF`lvŁ^ MҤ")fuع:,M*şMWlަ na>i}cfΙ Kg߭,ZÂԌ輠26 0im8e\Vl:nf鵍܎m>Y~_IRBVP!6,x]D ~b8źn7of-T no.&)5L_9grnXZJclV?ڝTAQHǴpԆViqS&] 3gdo6q./@$N %hQelԯ Q _LvJ~V:U#3#JV,-rHg/W03%2O^$qUؚtM!;Wv"5$f tzN FoA}H?gtF4-753 b$6vS}U3w d]ŕlI?wQ$fqІvNGj8,'v!5vdw4Qiĕ@@&uuq. R% 3W&ݔi7 p!'m޴]:boEUdxv~Ox7 0 x0x&i.n%hvxl,=iG՞."*/yȍ*.@dy kᬰΜy 0pNH X O WqmDU^xw.bogp'{zc$g{%/mr?o4o {{ fː_枖Wpw'·:Oʍv k4Eq%~x1kwN}?NlNh6p ҠK"L@†Bx/bTH`ƎH"b"Ɇ n–.%Z"4%#iI%KjMt)S9w<U+URfӇ15%DK&A]z[jbڿ~0F#Nx1ƎC,y2ʖ%[Ξ?-z4ҦONz5֮_Î-{6ڶo틯_3|2TI!$ol21ϫ_~Ҕ+B/v J-vJ{(ߣ=ѫ*U@K'QyIDuut>aM/vrء"fV'+آ/˜nՇ)8A*8"dP)P}6(1@eĠ6Є!x-уzۭF*u`DDGB$D5IR%'T_+mY_KlCb.{GߗY!ƩNFjR*va"rکcmڪ}:Vc9Siu H4?KC.FQaZh̄a%$G 1{!$! 9&k<" rTב4;SIBH6Rj4G0I"'ĉdF7Z"'H2RL0=\&3HCB3Ҝ&)Ez`JL;8E:o9*坬(JvA`E(gPVΈ0l&CgR3(Egc8a#lϤUIxvKkhIbB[KJ"o3"JS^:8yNOR }!v,=ISuzNQAu I2> I(`DM94ZmD+կSF3ԫLbr'%M#iuMT*J D;nQaVl3){F!Fsi`[׼n%`:5R fBտX[-iEհ6XTVU:_ '}0-M GJ4!.aTϪ8idQ@mp] s]|/]ai^v/})g|>)y[K.(;"PϤ!u,n_"Gt)nn}ʆ؋h`rw_:!pp2'ޥ/}/{7BrZ^$5 &X K""gɎ$YMo߄t'?5l-dS [1fu4ّ"UemWehȒ4]dd !Y?lYBsVڔRwxbb{v]/'Wx\maOUѢ}4 W:ҞW%)~rJ mIEupX;*u?s]X )D6R6# E;;͆6_B3IliTλt(N^qq7}szq%rSGD&v].>|kϔIr+<>fÛ!G<@HB4kWֱs*Eh p]`x@siZӥ.UjW[W+γىq葈ޠ<ãǏOy?kE9~v 6&e'_Ia1HEx9S%G>!]Y`C]iч55[H G`yD vR!ąiXRx_Bݎ,Q졘 ]u !A b"r!3e af*`tݗʼnߑ !=!M֭11E\&au !>E$u $J:N_CE)%R~OGĢVPD"}AD}<"+^zI6p_a"%0Y6b7ݐ!vaB!-zKyU-% zAXa0vG=-1X Չ-dZ 4$3#^(:7r$|a8dH8VG9"9.K@"^ R[<ڡ 0ݣ: 'dS8?A6J6oOCߚM4*d)ד(e}DhdGr|HeXIJIJ[3zF9&"D6%>`T6Xc4_D""F\[%\UN_\eDc{ BleWrf|XfhYYR,M$S 䄘DZ`9'yE>&E;C`QN3JdP jʢV6^gr|hgxiiI:jm&MVzI$z¤b2#m\f>e`%cvc 1A'oguS['hRlfwj|xzvyօy%M%[zcvKfAhbc*u\J:'(Ben\u؄ahsa,ho(hseRit(b)x[~"gl'}dg|ΦQDj6< >O9,?f[Wc!um&[|EFfb buRngJ\iZjXniWti+vEfe:eәIV]&yO T\%MӬp(d'-ű\Ԝ=by*NjZF^jc6Ŧ:}jH!{+ `Ez }O}Be] kcѪR :FJ"2jO§rT~&_dd=^&<"+K*$VFic Y_+ U:`Il! ,,c,*R0,bjC+f&ia.^*hR"b&BoܥݎoWZ`oHf\ZoƮvrn/jKn0 V ˽k1E؊m G0  Ǡ*e+:@;0B;1ԩ5p^N(Pg")r.nM/+͝/R"q k^Ze۞/6|QI'š> e杉^/#ï.pB'ϓ+Y~1MvE2v?#Im!E1F$u猝n-0 D-vD5@&) >ʬ,w1jr..3ޡ;33=2Ys^2v>mx.ةc2IDOV"n*$snP LKrBi+ 4J!ٳG3B1sE-JO['& Q5)3^j9\ AP4Z,'Iw5!oXk6uGuSL*Z2NUEbg4jw25hǶao6e"]P5%ˇh'KGS F(^~fKw*ȵ25?3RI^AA\Ȟ&Ss6Ov g]s8ϒ>+'E jq/v7s?wFt;tvF|vF(auK4bD6zFW$%  殾a%xl79e].YZ8dJ,Ђtf?UX~]7‘oM3jOqO8piI9:y/ ^S'cM3i5*mro${#yOTd[}7vvw:_`yS5r9%7V+Q+Mn8~=5T1ôVӹlC /G&Ezr : {{O ;/;#{G:W;#%k{c{;{˻ @ӻ{{;{DJ<<'K!軿|G/O<#<H|c|['<ȃʧ<;@t| ʻ+{P-zΊ +0Û+8szӿʌdƬ"PD{{_;swcՃד;g{s{ֻ֣ڻ_{<|=ޣ=߇_}'>೼7ߍw+%hC׹/=;}w _D=^AXLD0,e~+ ~~~̔$ (UsC{2#@}[7M|{~KBdyOc?ԾI}OӮQHs~?'C83G:&g~K-'PK 4hp64hPE:,aEPǠ-j$yǏ=PtkhִYS efnhPC5ziRK6Mj͚/{SVzkV[vlXcɖ5{mZkٶuPŴ0=u6p` 60 7vrdɓ [Zth %5`bhA.5̙&Xd~YGv {egoSÉ7~yQ6wztөW~;X>.ɗ7;ٷw~a0-ZMȒKPT.K)M!`ϢbllS" M߂S=JL<U\]j;Aiju$O} !$RI \RpI%7z H@ӄ à4I2<4"6|83*lƂ(8i4 <с[h!H%tHF mKn[BJrҢM;M"o4Kh@(%)LTZm86ܕ^}bn LIdMj)P j#qPC9Vluۂ}ܗ+T (+ w˝zT,jpTP){9>IߧS+0ĸO˘ fLTe"*l/^>."Y<hj(j %t; 7i:Z<ϣp#<s (ʫ%:H} G{gxAheއyqÔҁVWjPů{?+֚<~qا~:>dR^eb]A8;0f BW] R@ew]:0鍁 X@ f+(Ԡ;zݣGCy9 h*pTׂPbwvm!F aH.}XiTY?%'˵lt`X vHE6o!Y(;\XǕQ[Idd Ef<0ZX`PJMYbC5'%MzY5зy7 cLє47p@ɺgJh [|V#HRr dٷ$N{ޱa#Y|Пd;wXN ZZYC ƫ=CeWц},=K``NLv@R!cg{9KMLTMЬNyӞ^B 1pDI AlI?cVHr՛^mW IVVU ! =*aD兟u]qZC>$" A04)5;E V0=Lq2-N}Y~~@hMၤmwTr1*HѶm#8\ݶQ+eغ͇*T k ڂ@w5]jTEp驆2Y/J)LfY,h \`{,L!jY. [|'A, FZ *AVK-!ؙ}:ë+Q.p/3y S]īB UO B^y#Fm)]J!QDNF?(KiFʀf79E@ᱚՉP0J=ɍcNvL]hCL/^X3vȓlͰ d' ԡ& \jS:. ]3>.yS8X2ϛhT< Lil JH+?,jkԨld%3jsƇĽH=kΨ N40B`ލ7j_hvnswaL=&R9~DzKvo9^~+߄00li;9w3ėxljnxF0BL%%%~ˑd^s:}*}#CO9rtUKL~ˍ@6兩oD{5vk4nnq{)/vmXeDi𩷩z׳miC8@+u+˄b$# 4,r%w%^h4-?O%ٿ>L~r,bE<&N'sUfP1fXb^$.0tXO~%0 ċ~gLXiz1Bwz3 N~ƭ \0j?XUsyI2P݃>"Iؖ"@Okv%>0~p N tto#`u $gq\*P hrR) K= 0 1QQ!% )xr ˃tipC 0_ ߚd0^ Dq(ˆ kqEFǪ( Qd` `2h| o~F!~ E[Tq)eF}pQ  Qz6 Q@JsTTq Kc.ATLD"L-& )80nBC:"7q()DZ*4E7$#`ȒL"xpPgbr*RyRQ%*US!UQ)S;u] p1|MHJT $@K KbtL{CpMu7tME#NP&Y.|MUg bJQ5Ib˱4 2aPA}\XU]N< ZY^Q8K[QB B64C t2x\6Wt]#Vb Nb.O-]5UUdK!o:UM?9£Z?o`|@Q"f]ag"]'h X8aLVЖNiA\9of7)5+mV7nVHȵgv~ 6h6BEk8'^ "iǘmEiJ$LenBn A3VpGMlpsSmumdd6BeZe6sd vq1S++t}gWuqN.VY2V0Җ r_qkwn )usU[%Bk##jkOWyQpWyil6C7wvm! weJcJs0.VocUtuy7u~OlMkqCP7t #J U@Wmj DwwK|crWL}}㗂wN Bq%CvwŃ5ьW/7|xwK n2ki3Ow+ l{vcvCkWC30=4[`{..M]B- b(ykX78b~%dz،CRU$gsiIa v>6Àuv}}oX79-!ZZŗ#]\cetYCX4X0hQi%w%r/V6ot=kAY992~8_y^\+7 >u_bv'FWyٜf~lFVm߹Xey o?V!ÑYV x{Y&~iY%':{r@X 0dy6wڋڥRX7$ڢ_řszF8  Yw9)09WaWo~y\vZ+Y -T|9iY0:`1KaN2:Q#xeJ 4`Iz Zϕdh8Aس)J8 O BŚ,!H;+k+W/;sE*v 7|mnSq.TV 1gj۶uQ$F~a^'Cz䍝.u(jE'מTs `{,9Zx#Zt `:+!b4\O=Kě,Dp2| kKOIfNtswu#8,-Aup 0q& L x(zTP351]ˑ,ɋxʯkxS!^|hN J0OUz(3$1B/,#9t:t \ԥX& bcN)v~#ቁr|Lr^f G[(d+?,\[NV[(D.f$Tk ͸/^Ck͎Pv%]!Quh:gt ι 6 g1hnQ]>ѝq QσF>6AKI Mr3E3Q6pQESy0aP< ҩaAUNer;]?][zԛ炻sr^֥s%,ⶤq<'>^Ž~Fs+qhGt93_!i9fFs>[Digg+C|!S]vxwH6_&W<y]a@ݝx0g2A=1O• xQyKbyT(Oh筶 g[/D ڤ ˅6Cm#O<_成 tp@ H 4 tHË tH)Oj(dOXQD ł?>lK9)#P7 p͋1w4'P-Y0W1CAHil Cfb`+*B Kr݂~CKW-xnvr ʋ /UxmY3Q{!m 66u;՛k֮akg,eǾ[K; `޼Dh%5/8谒- %K̀C%u߀]2M ~> (f85t2fh(,0(4hX=<@)DiH&L6PF)TViXf 9ZJ(:Ա A3aTOuY@4@!5 LSJ(gH)'IzʉEfak:B%%L*{WM5TuJ#w|kR~I USD1Js9XvjYWmdQ4)MQrAlܯ_|!v}vykʇ<~ [[PՅmk^n{^i[,!œqa6>ګlA@(=n,b\}04C=8 {v%DSK WE9ڑfH8̡wH$chgBQ+3ihj*N~D)YUt7I b&s)i+â5yU #m:Љnt?ybOȺAYdy* dY"P8di:C0}:[BP{dŮ*L~^Jc% c_&P>ezcb`i`X]pLjf * = VFAnB`f?+Nv'bz̧>5hhH@1`PVg Fwz"<6d&#:D.uC אS(N6:ĥ#\7hAwZtqlB; wb*n$&~B Ma|r30ЎYMZMӸm=YWηC5x &Kzu?o"O'{|{h!imf!n%[nL %5l=3N 9 O8&‚C[Md?ЀWfpzjَ _d?AsЏN9ik1 \Jo'Oywϼ򂰇7t,{| A<?S?]R]O>r/;_|!ܚ-{Yp[3p$o}^}Fܻ=O?ğ:χ8vGw}Ar!vpi#v4~b{ׁBg"8$8tw|,0lHᇀ /s>};8nwnBn/xH(]USL؄Nj‡1X7VZ8BX(([ ([g}8B7-bIpCKtXvhOQl p~wX82#sz6hi6mb @~Aql4؉r(Cw8ۥNR^THq.ew.h2'WIa~nsIPhzY&uy6#4^,ȘJssɛe9yYl82 R4_r sө{9;W֝YCi湞+%}X\:ِw(D=|zE,6 i }(R4z$}A_X)} ;9Bymh(-:Tz5/\13*i\ Gm ҟj畲}"JDjR+¸$Z{N vJosXz!h|ZҞQɦA[5ǡzhIAC~wک/$|$Wz\Yz uIvq~١I٤ʡЉ!cj29뗝zx %NzaujG"Q&*sTuqjfLScl<.ɗzrJz BUȺ*єQdt(fMQJA=:ViA銁hj#,$%([yʯ. 5 2+D[M982qq` 1 v<{`'us'yu)ݺ^)C'´)!>Z[K)xc(4:fbeX^ /OIdz1eu;ueEdBXZwձH?x?fNZ+۫EL{#1;ˢ5;B7K7.u_JkyEi]dAEFh1b O'y69<`\zy1 b::Fe1!Km00/ϋKAg3Bg ay m_]9Dc٤H"˿LAlcěa5H{SQ(;KT^7\<'(k.jK,6VY/lgu?v#4i1ܧk*j4[Ĕ,xyĘ̧O6Q$E'WܭP ST_{(38e8j̪CYatV)l+ ͂|~'}!1"J*%#eYɕęEEqC ,U(;S`SqS9R55L*~εK` 콀5.;W,V  ]XvLљu|LƒLmDܸZ71,0eg*Ո1|eÞ9<xp*͓;5=xCӞ|˥^|WÉA*%iҀ ؂Mئ}3,:KZyyAɸ A,?ו[G<\ڧN=u`ړwnJm̩w[,mܔʽ#(iwwizwNc'͗ޑ%9fmrN||!֦ۗJNF̩* ! .~0Ǵ=2  (=r}]4;0H'Jnx-!9r&iq"T^0TnW[WDZ^N`gc9eink'm.oquNw{.a>x =m~~艮茮>鐮nʂ.BN~ꪞꦾ^>.n4A|71umטgǣ%.(6L']᮷c8AI_&OQ T  "c'Vl]āu1oJzOz C7ͬm;) ii= 0?^򓇫i֯!/9h_u%d ?e|a#d@@ 28PIB -DRC ) DPZJ2'b(YRʊ,]tPC 5mޤ8h%=hi1&pŤmL )0FzTւOQVMk̞E{V?efҾW\uśW^}k͚/{ FXbƍ?Ydʕ-_ƜYfΝ=ZgL6E {j=![7֮*ҏJr go m(0rHըq[4yk.:7p.:лq[o,R(vLrF+&`@ZOcNZseZ9e(ۆd=j:j b;@e#ZwJTE'^{ŷJA_8`;,wM U}BPq|Pnm')/YWc :=` KP!ɥLA ohq2axc-޸7if}:j `Vv>mh{)&7܋>SV;gRʞ[>솖!dq\ rhns?iG'tOkYtqa{,1wpl4Vr䄾]nld/q}'wb^dߑy_Ui?T8=|LJTtG?}Lkm/"{yֻ^0n5$ʰ俁Dp7JtA& BB {id8C|auCVnR(fQ RgH60a@F.e8y&(*q%VFdQ)c vBHTKh%5d iАDd";CR&BIǰxkZDu wST`$]Ӝ+$(EݎN*.%/L(|%Ƕwd(1IUXOF ҙ$_!9MjVӚaHDJLbb3dF6O2=b pq[݀12E;:IK״f@T7RwOzf {8#:(,fHE/i^Ӥ'E)Jim5Iϛ꩚P''Csԣbo?"^PeHRiZAQ9zR'O9vPNJOذr~6V<ԭo}TIS:W+ESKm2Ar{b!&՘@0|Ijʆlx KkP1i-ksL]"6b +%oJWUiZ Wֶikle;[G'7)NvbP듇je9#8 &@-*U,̠{3s3DD,w(GZ>p;eo|)[׾m}וuDo=%^^!% ms`t%ϗM8MeϭR:;1DJ',%T 2S7|-_WKNպ5-&P.;p +gS–m{#ɒ:9-rq=h7EUVP1+xfx,A Z.0"vhkM힐O=);i;P mq=pBvC}Fٴ+ob:qmmH gY GGz]Ξ3dY٣<7#\ǮfZyh%ud>[ܭX*U#0 E@[$AԍBBtٴD`M+ѓD:W- 3D8F,;j#`FxXsŠV\p۳YdǥE\x 7cr[Cqd):dTEȽ2 +Qs;5TL53|42L4Ǟ; XlǕwǗI͠zG(t,D'N>,qsz3"j5:i›0++» J8FÂPId˸˸zGdT9>[ڣ}0 7bQ/KDLw{34F)\ʠ=LK>˴\˶dM qI<z@)K"Ll 2wbqYRh̓Y Cv! EQT+ EIȴ$l|tOȠMk k1K;de<Νj?)h5OLړdT";HKI_t <4T^S|Ggq2`<ɽ> Km]P4\=-P,촷\N;T2CD+ e- D!͗=K ±u#".d. .<z(Iҫ;A9 5RR,uTR.T$Rۼ* "SP͓za#",]1X0ҏI̡n 1i$W}C:҄ʐ\U[DUNF}d}Hf]JmԍT ^\Q VOCR 6 rHՁ@ɘ sb\UŢ4:LIBVe`VgؤVm1;"4O-p=5HћiUDf!B=!e.XE4PuSDݣyEVMր؟e),ա9ğY<4I.XR-a9ptqSUO4VZԬ ME:UlZUYYuTڼ4+3M|zռvX`{ DUm=<} TR)RN[CNms ] \,QEe}Ke]JM|; ŘB]֮ݻ|,gY9c6?KYNo4Tqc2tBK_R| ډ۱ڥ5[PPh߭^` | 3^ 3ʷeRU F\Č;ݭy_U Ee y=˩Clu^9XZC_o`4$1 r+`ԣ_=aWb >] N] &N) K:b aV=bK<"F؋]NZpU c0وtGj3[Mb%[&vA&(6OYWaU;kc!-%3nCWR5fc5ܞXsޮ9R"&]c?udBD2AdUCNOFZE{H;_fLȰ8NX^i^*9榽CTXY[\xޡ^]ݩ%bt.=W߃Xb&.zhfSUt~aNnxk]*:M}VuVvv]]yFi5_)F_+~>>. IhfhH\aGHrLcz +YhZ^X^MWj$Rڣ BcCNeFh ic~T&fv韀hlϝbXf\o\ڞVj`Zn^iA}ʦ\ÆVl,elh-zjV yer.8էL?\^LwInC!vܻmD^VmY o)neoqf>fb u+^a毞k~d㐅9 ntA bF>ϯ6)^c&Z[`(p8Zm-__$hJ /kTgU`wov9k":h*<6"DqEbqvq>yn`7yu..qSp-ɾ wkP^S[eYO~RV 1tL5`{`r(>Ys:767f4rv.h-6[S'Z6Ji23_|V`sremU,rqup\o&rDOmwaWLW"ݻ^ Vvgeg[hgOjWx P~TwCp&z: ?\sk p@ f? OnL]󆽗˖FP[/?xGyv~Z; v:_s43yIlapYmjwvdJZJZ"4)'9%JTc̣R+&]Zc*֑=f(ƪLzaԆ=J{ Z\p(܋tQk.LX?ef 3n1Ȓ'Sl2̚7sl͚/G.m4ԪWn5زgӮm6ܺwMЗa#SaTg\EHA̅7GݯܑٯY1C弉3'& Z$d{({?үcY`FMԟ E -GB! &bu6"%x")h"18#5x#9\aRD\Y*dWr9'aщdoa єRZX{lMep/-уMM5(G]!Z%Q֠Xm~$$s.ѓ#}~%ue| E'eQx%)E6ЄJad!.":*VYh:**c&Wxnbu=1$az,C>%:EyS*4ep)vT"}9CITE}9:lnXA. q <0,*0 ;01Zerb${ŀ <,)!arU,$'dN,F2Zz)kѻ1{Dr>]{5$&1e}6i8w\&6`JThXk:]z Wyuo31}QIB:Lrף9U9Z;uص~c;l#kH]WGR2t 0OQ~"()QbT&VZ,Ӥ_D"#{[3{/~Cf~Y;dᮀ'G'1\("R,&ȐRoTȹ_TJ/iD"$2a2` A*թNQ)>` ]2%9*ё"FPI>}t{!YywҲT>,mh ,y奨[6'"t"k#Bϳzh2t*f3+*RڜPt\]W3heO,eYř4+y7N6v;5+{L*j=r 'F.Uf]Pq.xu0.3ދm$YDMEN%եa!" ZYľ.`_sR ɦ"S#<0rKӺѓiB EA`.2 /c,cV/ Xy:Uh눉e~E fDw9@Uu!cm=nF|z0$R$n3v3c^<=Ͻpл YcĭTW9>2P̤OPE8eD7Rt:]a$s|<@?ӝ ϶a]׬4`Z!i/ZTY%б3(9-BNn0uso3ld[S@s)GtK\%m%=/f6\\g\;5k`E I-FVK"M|1+_t5(*QNFH0¦{)kAQc$%g:g iae R־E+n F11(^)wW*p2jsջWi6Zuo7/uo*R"|E ?'?vغe8ѭ 7K?ӀqM/sT c0 #ĵ#Ot"q(*0b f <` XA2e$]Ez$u q=dhb TA*;ƣLz<ڣMޤo.vHIK&ߖ< ǵ9b1G؉(H:Q"2}YY$Acba#6MPfDL$ZLM$[%m>ˇU6%QPrH(($xP$JN12TzE`%<D#]eEl(dn% ]d6&^6Y%jZ%kj~XFf$HƽN( 3a4{5e^ F e'a!Q&nyfcqKjgY`REn&Lbjgk{cl?Rxve DC^5N@g$J!)g^DgFP%uG](^]-} H(+z艰{[¦EbBD9 ǤciQi(D$g9\ 2(i_(2&M]ahtݏaqhE")t t&&v$fN&]HJ~Z$"F_6Y+Wp ej̑";)@Kvc 擕囖'i闆~*ʙ*§dPb-]"goZ J A*W|[snd*HNQF6uL$A hԍJNF` ʚJfZ-f*\(DT\( kVsf)ī'U$nS~grź6(R`*vfcv,kkC(u'nkBPh%49㸩79` Ht+VD&  ak_.j"n+j,z,>2kCLlPzEYK,J-Jf-nmNn}B鷔mJʲ%\d*E & ^&nv F,ֳ.m*>V]>\^,zB.6R.v*DwzE3ˮ*XgiYJ*6H^iU^/o+b/>/DXČh"nV:VhE$cK UTr#nR>W!`o.px8 , OE}\̭2PpOj2+"QjpY,? ) ˰ fpgT̄ }w B+ *jI{bv#VR?m-nr ? {h%KU;n^*WQ:LJ@1D#.:ٱH&lCXfDl"p&%5~ a(/ $kl%_24T&;/] QMPˮ6180?4'ݱDgQ'=fγ9zZ':$7sz>s4?t,MuT3/&ކ#Q_g̊9R2ʺ"MF3IKRnHKYHB34j:4D5I4uP^tHc hC9ڮHlJ+&x_@5nXfg:5ᚣ/Xc54PP^7Q R'IS6(D)IL*6+cOaE_X~Y@wb:4a2w ^5`5e0lծ ?#nG|fqpVNvk6VJr-2JnOlB/k{k6yb|j%nr@%BK3r7ĭ6bO@n>6*});/1y&~`EqPwVwE*K{dyuxxlm#)V6 ZQꀉ7M_(s*)rMKySqx)~' (wkĎ˞o8,vGyÄ_|1\|OZy7V̍~[m[Q Gl,ӳ pdygg8&/?/9 cw*x;B/zPy^TsvsԜ 7CwOnq+k88s_{< IK >92UwgNa7﹃̐Atˉ/33:yǥ#⋁SpI}7:xWvZ'sL;B\M94%`qz;㈣Å;,;bֺIQa}Ge;u;Zuxf+P|WP[KGi6(n6y߼;ȽEۊ:A?JGcZ*w7rC颒ăwW\.E?6dO{S2<{E#U򻒧_;&D۞<xqr0!mV(lGNO{֧w=wEb޶r7?T1,B{)yy`+EGZ7ej*zjj'~Po}<~VD~̫q$?p DwmR~x:+8|g:Cc9}FL cg'@ r0`AժTZ:8bł ڂ@%hdI!P@"MƔ ƌ(gʕJZZ3 C|9P%˂KƄJpMuFs+@slXg:m[mESfm]wջo_iNDH9LH~P=HoiѡOK:&θ&n 3< lP+ P 9A<,1H,QLQYl1Sm5k&<赡b́,Вܔa%Qɰz\G񄔆k%:l ##yK!~k'&JB.v\2TRA9K +Y<ֵE1XN0uTQUBV5 V)=.2&uu;qMdg%.n0UzhkX%sݖJv$"W{ 8@IJcrKk^r5*tH] o8`#AqA- xe K݀575F$=T~SPzmS^'& 6`;\8[ PI,[a1sغ"6#˲~:iz&( DNB#('3 :CXXQUK24a)eĹZ?.0g0Fi7Ђ%$R&qe۸-k3P( }p _# xR0"XO  "~8. )(K8 kOo gZ Bel)0& Qt 1   M o\HAL&h F"ς^͂Bkp  +B#h"I+ }jPqO[/m'bdlx nDKri bںiwMz8nWX&O"z_r igLQ" QrBn70n #DN IH ϵz6[N0R<OrOAPbb%Q1y_ 2(lF !w<mIs ^>a#AWij~R!+[,1)\)qOӰBpRa)'{2/;'/11-o|!j M䛴R( $Es KXj9 ɦ-sbP]Fn. /r6=/620b0hpR q!\QHf@Ϣ,N'`qr&*5qb2rQ8a36w6Dl7S u,ӢR,5-O8n(B5:9Q;3XPWR+y~&Lsh%d/5>%$3'es=Mt0=U4,擳RDrOK"@#@%n=24iB:ԐT+,5gheB7as.(K?M7>.2#fu'MBNGGx)toPXtJ❔$]t<{= s\/5[)/[1V5)U'P[#R@Xo?$XU͢*1RWe^wb]2358 _bdIBQ-ezJevfQPGgi%Z3/x+vx~) rBry1{djN# '{v}ü76jG=+vpS]h,?RW~ǔ~xu{ /Q /fRK]uBlI"8̕'yuJ438"URCLGMԄQ ]ò8|K-"o82kTWwvh^'=&a$bZ9gK7[ڙ@;mo/w9wfvuz":X󒨍:SgBX,FOFwJz [s+mAҺ'vr׮IeBr˛S9Iy"%U"¼#IgYh &X$6XV}AiUM; c"kq˅J898#gr[ut?2NLH69dLJIJsK {; I[%ޤ'B8xRnf`]XC̻ \fkׄѵ Z[}y ǃ<iȫȋy!EmUf ,#$%UlnN @i_2`Yh`UXQa-GMsaK ΍YC z[,:>Xmͽs) Χ;_V{2~I-c 3Sݾ'>&73Oonw?$>&[\ Q}E⻃ARD Q ?+coǃH?exInM0v;곈?ȦBWEbc_m5)c^+۵GvmQGð,A <0…m(pE"Z1/DRƑ %DK,AɃ)?l0NJt sСDZ4Ҥ")34ԩTZ5֭\z 6lWk|;6ڵl} 7ܹtڽ7޽| 8}=\Thl m\1Ξ> VTJjT蘒)#",lZXó9.e 0gp:-َ.rqDh9tʽ M0rӷGx`Ua` .`>atv5!N=gD=\B8'fjxz18l "W{2=aB :SJӑ92dO&Y4ї9 %'FeBgU~P grIgZezg~ hE!bLfӆ9n-G㙕Є1Zyb)l=&>=:d ye:Iy*Lf k_XbR:`>Uig^mW9h~ n⎫`dQ(IvhH9Pi-CvZjba^Ѱey (d&+q$ Y !*x)qk*Ԟ.KKLs6-:s>젹ʘcI@().4Z*-H{ifncZ9HI?M#]!+ /mfa­tM[Yfܲ<7x t?y< nb5"*oպzyTl'pAH&7v7%jcOLt Iˆ9K,M{mޫce_K}~`]zyg׋))nʥjɯd41./#Q&9$5@JIs'gN*˞?Bl/|$, OؽEGx '2rV0ϭ}Ҙִ͏9 2 En3c$I&8 !GDQ$7!K5T`A R)o ǥt("H'BQ0#3ZCu"BZJb}ßw|w MD|Ebu&Ϗڥ+z,z"H$Y0`T:` zsģ1dE@*IAbt6OFS"I$Mur>R(Ƌ -i~PEҕB /vzgrR"K*r)Cb*shE?Bs ȀGe4v ϓ- ])G>Nڰ'RoFRN'3`N-4rxiFf؄I`?̘PQ?U%Qju\%!FhhrNq#НlR~1 @u!I.ˉ^"W2Wz4 #1 d]ZִȢ]=dYm"LVX]1eNO5Ga \g*CI/.c?{|sbH$/d PV@p*,:D޼z84);/z.5ύn= J:0lߧ &TJ#%d F:E0оA 8YjcJ`O6Ȼ)Ye)ΧCM n-n;#inx2*ecIB~hb7 gKpXQqsbent&^U|lc̽3s(v%cMc_5ܺE ~w[l|Ͼan݅[8dɷSmov}!>-ɾ}ss&|oOawXd PR1ۡ1N}Z՚ғTU׫}tfW犯O(_Fb4(Q <{f(kvCw[0;."yl р =2"Rfq&Xwp8x3٨!A!qQphxHPhfniLx}[VpxK(ȗ| oSࡋiX%h}qrH$'AhU ۨ !ݸh%_t/VS"Vx6t%I:օBu,cN֧&xE'$$sT'9CQՂ)S  Y,U]{V8uwa>h|T5ۗӦkY;t)Jͥy )BzH Kɔ)'QI`((}_!_3wՊyp>|G`g ){XYOB9Pxiє)˜i1E6Cs6Ǝ5y?_1r&9؃Q7țFxuŧ/9YyimňT04|V)& 9Xeɖ4b1ٚ, C1̘yt5rIܹT)- y1zYd$q""R[:rXCeird.SeQ#qy(9oԡ.'2ʦIDa"Yq"JeJhDF*v0Y|Z٤Th!%PtJu|-օ; Gy]7a*z9'[eJg0ڦvo:q韟*ɢ5/+eE_ya:Ǥy𥨅ꏖp.yY :QA) SJ-ǪZiHI=ygڭYqf)}A֠꯷XЇU#$}WtӟI;#᪱dFx;e%k(ZKwRu&TKP+< -})!j+%;zJKW{f!#1qQ;z!<&W"\dK:X8W#2IGңyS1ⵄ+nk$TV+bZ\۶xzA*2g[@Ѿf2; ~bfhùm uJuB> +X'\?HR)IAq \/7ȝ2JyOɌ;\Bl̅ qĦl,;<ętXhIsEQz̕'{МL=lmиRpc\}<v3N[(rADxH(=^ N ӐC q_ Ӛԥ c<81QxdZ3"ُxK#%yG?; @-A5m7q3;=-\eQƫ̆༸$!Ȋt:%m#@{FJ[1d uϾךn]p-׫3t=qzϓwlIˊKK;yc?زWtuyb-+6Jպ\r|jۅ+ӧڒڬm A55ҹW.g iuGWWܒN`sE+=D7ij]!㭅}.(^q PN#q8v4FE.GIw46 i9%#7zi ~mLh|Ag@}zw/z\(rx=,3SsN ш1 ݄uTOoJAymYHM/wU4p,ɹ\.^#c~Xq Q&ϗދO(}orQlz(:5 !|Γ>'=H@P?\N//f珟# A"q.>@o~xW $XA 4f%Kj,XE6@\2c᠂ 1$9P\Yeȁ "d/u.iĝA%jQǏRQNZUYnW\YeYiծe[qΥ[]y_50QtBI`N%rZR*UQE&p ԋL U5ŔRB|bڷ@,+|qe?pv~1n <7_QLe{Kv}p <{1"%BPj#OHᬳBC.KV5dQ0"pQ"h$ D%t0!S$h!Ibb1Ih IJ(. {>4TsM6jsN:N<ӭRAQ "˜jP£P>3OĔ()MEGJВ6&ͩ%8 g%)t#G8b'uNI*61k; ;DA~8`!$%)RRR6amAAnSq@іViW^Ɨ0fU܂X iy*N LQL\J 1t%U{ Nŵ$am/|]@KR'? ulIsWu|m|c˥ymED:ah x],&v3e)|ɷ9үD8k$7OX`#7L*AKn)CL#[q\Y9ޱvzL[<8N+)erNULCDj!KxJT4rz$)gԉ̜cg\{uSy!?4QN%sߦEWrAp ^:;[ ٿ3))Ys%? ? t+?@*"@(RBؼ <=P9?e"|KƓt@I1j# \A lB!=B)++b;A>%, ޫA §$DH>'9'ph)̂2BR.A /&tBFl BHBҸBB== KD@KH 2C)@EXF\kyDI|Fh J KmҾ0)DdL7atA3+'bT4KGH,Yj,h<ʎ$rl@βo\BcFgFHFѨF_z1≍\HIsØДʿ ÇSbXt{:3/ ш1㮎8_YBİk 4@D Ie|HLHJHH1\JZ&q wLQ4Xˑ迒EZD,G󀎇S4!IA¦|JƌJȌFD $܉o/˗ MD+CdAC9~#8Cg9KԮ lLdnjL$ cH 9̹Lɐ '1E.9%CS\߳?4PNj#V+>J\@_1CXs΅O PH.ĈNPMgPq1O'0{  ЗPB%"._O|Q8Q+PbMʽCX B<$ 5vt P2S:3=:1 ͈ü4;RRTĆQ48Q6J A1T@$ 2-WO" .Q1%CK.:)MOCJRE.5QUTnӅt4U6=U|{ӝAac۠ԉ=SR}TT#K%UߘAGVHL0#@@2Qc zUZ=Q%Uk5UT=SH+9, iՉ$e"%TҤ4OC4ЧM+uQT/ NB1*;WVkUlV1n} V֡MӗDXE-T Ԗ%tUxU)6dTPOـz'!4gX]J]X4m؇=Xn ZmxUueI K[EGUCW)ˊG%P, QO,X֡%5Z[Rڒ`M=WNh,ZxQ< Sӂ@ECYY֐ )לXպ쌛YMIIA\8ؼ[ݍ\`ڭyNŽz֏ &(҉!Vd75GM8KtW"feT]%N]& XX^- ,rZ5M[iW`N|ՉTٽ--D8X2-iU\]_l-aK_`Z$ BZ`ŷ-\:=WɗH :ܠ%~M\[{]䝥va$ab(B8PPWV_aPO0̽܂ZjCϝxxcc 6c{+3bb/cc.#4& pEm|ɭ+)e'I(NDܝ؁QbĠגGTZ Y+bGfFHdfJ+M6N$ǝʕTVch^&^Y\`Co JM[E LY%aޣv.SdNF\fyff޻憙m(d{TcQ^ e)x}~g'hn!\s51M `^~hp. .TB` <:Tز TpDߤ@ +Ij^Mi@viVڅBs jm0e.b:'s͝Ԉ@ш$H)|gIv>FбlL*`Z_;SP& rc8CvKkc%dѠm^Ҿced1Q#b' kN=lXXcmgvܶ9僨n\g!exPe Z5O\^]QNB|b_{nfO3QVn>}Κ3f}nB=FkuYEn0g} 4j`gw` m{YlgQ;s-g/pOoh p£^ݫaȗ& gmtF}eKx& ֹE# nq8/66l&s[s{Ŗ4֥i+J)o@S6osz{8sF6qfA F펄hIQV  y/ .WqrebaModuR0dJ< W{Y>4rF y4/8Et׭}/i[Ov\vkOxvr?zApzq΍W7kFT׉mT&H¾Z.PJXԍStp'h7-lqax`Յias!broi|(s(y-g+w mm5' 1ˤgzGf'Cx?{A/PPEZ-uo'3t{{IEXt%d&w.W_q|*{hoy#_SnVRfLSv5 oF .uII 5Z>l$sLMy{5}7p G (Qi &7uV=4b]_b{9};2{'p "Lp!ÆB(q"Ŋ/b̨q#ǎ }Y ɒ&OLrT,_:doOZR(>Dɒ@"Mt)Ӧ'/DӪ``9hJDVu%aϒEjԭQhСY %~i߾_e'*5!Z3Έ -zh!z5֮_Î-{6ڶoέvH_.|8Ə#O#H_K^jo޼S_cs߽߃_磟=_ߪkQ5ZGʞY@jV*ԥ4#[VvI=+iIӢ6%`5Yإ5efXBVR,t%-IS▄+f{%¨jkbw%E?+ѹeLo Z 落I;QiVok#; n>o\ᱹ.kef7 ^^֪b4&HKI\y)K*-)\F,=&`CœDc "{L9B l##9J^2yx'pR2+c9Z2/d(U3.9j^3\/933lg9z3gY΂ܝ mC?ϊ^4hzВ+miC?:Ӛ4;HO:Z4KmS:ժ^5[]@FWԲ5km[:׺5{_4(0mc#;^6gC&vmkc;6oz7ms;^7-v;7m{;ǰ<8 n _8C< o#>_<C><+oc><;σ>=Koӣ؆2Zc>={?>o#?;]4=ҟ>O׀!,D  !!!"""###$$$%%%%%%&&&'''((()))***,,,---...///000111444666888:::;;;<<<===>>>>>>??????@@@@@@@@@@@@AAAAAAAAAAAABBBBBBBBBCCCDDDEEEFFFGGGIIIKKKMMMOOOQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnoooppprrrsssttttttuuuvvvwwwwwwxxxyyyzzz|||}}}~~~22 H*\ȰÇ nŋ3jT(@ CiQ?I\ɓ)[ʜIK5sdyΟ@1Q*EySCc*ШQʕ&Vvp1ɪ y^RpuZD.ʳi (?^PfLk'+kn ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKN:Ğ]{Fݽ[^AH}`q8@B(Ei ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼N8Dtav1ĄF<@'0O,` D%L0m A 2A&h@,$l0кdC(Kd 2H?2H@o 4C3O{xpJG $X "-A@ 6AZ"k!,      ! %)",%/(1+4/71829293:!3:$4:(5:,6:28:69:;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\c]XzbNl8xgQ^g_SkgPoiLrkHvmDyoA|q=s:t7u3v0x-x*y'z%{#{ |||}}!$'+/37=BGMSZaiqy22QGA<8Ȱ? :|0⿉-bПGQ$=3)1Gu!/z\ȉSp&;]ZtDu *A \}T \j"վ%\rMV\~{0�qkq1ƌ!,i        !!"$$%((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttvnwhxcz^{Z{W|T}S~M~IHJOVZ^cipx‹ÐÕěģĭŸ22 H*\ȰÇ#Jh03jȱG2\Hɓ(1F'2˗0cn\r̛8sʤYSϟ@g3ѣH+2ӧ:ym ՓRڼʵʥDQJ¬D5˶-Z2=ʥ+{hLз~cP3#`Q~kT~IZ հc˞M۸sͻ Nȓ+_μУKNسkνéOӫ_Ͼ˟OϿ(h& 6F(Vh  !y!8"x" ""b/P4"t#:أA"!)H M>bH9V2IQ[~a)be@!,N.  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 H*\ȰÇ#JHŋȱǏ CI%S\ɲK|I͛8UƔ1ϟ@SѣHv$ZTӧP2mի4RʵWZJYZ{[ic]qqp_DyÈ_'#KN{'k޼?sMɞU[k|M6Amͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f* i~ jgjwj*:gIkoފkzS tZ,!,p]         !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 H*\ȰÇ:Hŋ3j ō Cҁ?$S\ɓ[ʜIsK5syΟ@K:eУH!,3ӧgդRzάqJV&X"]kheK7vhdP]xᒁEc& Zǘ3Fr tDӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkν^Oӫ_Ͼ˟S_P~H_ʇ`-Ƞ{>^Ga] "b#8_@!,K   """"""#####$$$%&&!!)$$,%%.''/((0))1**2,,2..311544777999;;;=<<>==?>>@>?A?@B@@BAACBBDCCDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\C/0cʜI͛8sɳϟ@5~2ѣH*]ʴӧPJUѩXjʵׯ`fjسhӪ]˶۷6ɖKݻxS\ La~^̸ǐ#_௲$k̹hGXo1ШS^ͺIʣ+캶۸sr8Ӻ Nx[޽ubУDήץkνwe又ӫ_/]c5`OGD%'12c F(~5PvO3h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+kKR +z<l0 C GLKl1nW|Ƭe1 !,$2c(˃24%s8r<5r@sDۥ?[ PutT5uXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN\}iN[ \^Րd+?Y͌R6$[uW!,>                      !!""#$$% &!!&""'##(%%)''*)),++---/11244566877988;99=::>;;?;<@<B>>C>?C??D?@D@@E@AEABFBBFCCGDDHEEIFFJGHKIILJKLLLMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 80D/ ‡Ckĉ+.ǑƂ;fx1G!M㼓,[c3aɖjn%uBȺu /ƒ0˟T"E(qi*JSԣ@p˅?k0EP52Ν .oÇ?[̸FĐ WlL1ʕ/cvp>śA/GYeҜ L€!,0!    !!!!!!!!!!""""#$ !'##)%%,''.))0,,2//533866;77=88>99@9:A:;B;;C;F=>G=>G=>G=>G>>G>?H>?H>?H>?H>?H>?H??H?@H?@H?@H@AI@AIABIBBJBCJCDJDEKEFLGGLHHMIJNKKOMMQOORQQSSSUUVWXXY[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 - |‡4cqbHeČBvHKRI-3[0ft4̸-ǒ@3Z$56@78B9:C:;E<=G=>H=>H=>H>?H>?I>?I>?I>?I?@I@AJ@AJBBKDDLFFNGHOHIPJJPMMQOORQPSSRSSRTSRTTSTTSTTSTTSTTSTTSTTSTTSTUTUUTUUTUUTUUTUUTUUTUUTUVUVVUVWVWWVWXWXYXYZYZ[[\]\^^^_a`accceeegggiiilllnnnqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~¾¾¾¿¿ÿÿÿÿÿ22 G%CRrbĆ>1@pC#u:Rrj`fBouZߺq[BQlZGuʢ|T:L`V<5p+ٳ`سA[}ȻN 62~2d'o=/nf, 3a@!,   !!!"""###$$$%%%&&&'''((()))++,--.//111323644755967;78<89>9:?::@:;A;E=>E>>F>?F>?F>?F??G?@G?@G@AG@AHABHBBHBCICDIDEJEFJFGKHHLIIMJKNLLONNPPPRRSSUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaadd\ffXiiSkkOmmKooGqqCss?tt;vv7ww3xx0yy,zz){{&{{#||!}}}}}}~~~~~~~~~~~~~~~~~~"'*,/145678:<>BFLU^jyư˴ѻ݌ۄypf^\ZYYYYYYZ[]aejnprsttuv{~22 (3:CFCdI83>GcEeFHR?f!iuCΞtɜI۪r dOb JT;_lq"sBIJU45(3^կR%7}hu͑۷I+Пh» 4:BO#oFY|a-kqdžQJ0eS/_A0XjB3st^nʘI0φ[ JS{.Lz){ieN-&6h.W<^50c9PU֟D\XdEP45Ԃ' c*I-E.S7 2(&: 5װ ]4C`00!?AP) 2D"0F@/)D-8a S@b2@O?ȴfHbܙѓq!, 1(%)(**++,,0/VOmasmrrqqrqqrqqelkN_O(:'BOA . 1 =8%%*4CCZBk4r4tN wjaOOOQS` k n o {} ~~~~~'$$ۇ#ˊ#.}?yEv<2'!!'߳CTco{ƐǾƴťŚȋǁylbYNB92/'z!wvvvvvvvutrmgghm! }|{ywvvuttttqaRE|BwBv4w8pHpJqKqLsLsSwС22 H*\ȰÇ#JH"y3jƍCIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH-v\q:իXjʵׯ`ÊKٳhӪtjӧ ڻx˷߿ L5(ܸTKL˘3k̹b76]vA^ͺװc˞Mҋ@Զ Nȓ+_WieNسkνdJ+~ӫ_Ͼ.yϿIh& 68HVhfv ($h(,0(4h8<@)DiH&$RݷPF)TdoUf\v%\WBdi4lpΜtixIP|矀*he|jh6裐FԢh#馜ve*(ꪃ@OԺFO{JЬD@3B$E윸P mtg u+J*.nOR ku&-z?:nĦ?J[r˫+QO\1tk(lʲKI$JJaq~,#Cmwl{!,Xg=sj4UPpA~K4 > CAف[稫v!<tCz?y wKu8Ԙ˼ю}kh(׬`32V>J tW;@⮬ow{;RN;Kq=ҠoLx^{g+`1f.w]&UN 8mlhfE vgA .Zc?Ljdٯfˡw%} lSէd\ BP}#U6F'BRħ=sϠ@4[/]Y.mSH 0}U3"IzYY-y"a󎵰Ln ê{ĢG1̒#98ŰQWd$Gᰎ,YtG4}[:S n] D+;8r?fh/{3rD/af#(Iэ`@ziYQ-GI IOF 9yJfC+95SD߳Pj^TaǷ|3(DGJҒvU=*0C-Q%d1ͩNwO< PZ,HMQԦ:|TJUZXͪVayխz`2+ֲjGֶ5RT|\J6ŵxͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~L`n;'L [ΰ7{ GL(NW0qL8αw@L"HN&;P<(+Ȳ.{`L2hN6pL:xγ>πֳ%~ ~ ׀g}wu 0&'X$0284X6x8:<؃>@B8DXFxA L4c J؄:( HXVxXZ\؅^> acX0Ȇ 8oȁr8tXvchP0؈5 @98 pPXx[8kg@hnh8qx؋'( hp䐌8 mp̘hPXxؘڸ؍8Xx蘎긎 0 h ( R9Yy )>А8H(Ո "9ɖup @\ Y P+9҆8:<ٓ>@B9DYFyHJLٔNI  R9U Di0 PhjlٖnpjsC@'9:(ixvٗ$Yy eYw y 049 @֘ٙ9Yyٚ9 x i`& p `1c Q  U 9Yy9)əYٞycYg i h 6gП9fp PZz ڠ:Zzq 98` e 2:4Z6z8::i =J`CZ?BFNP YG TJ hPɟgd `g UZfzhjlڦnpr:tZvzxz|jPgC j$TJ@0Pe Ч:ZzU:eT:gjU*J QnQ:Z8U*me ]j`f mp gzȚʺڬjU:pB@ $*J:C:䚩 :l횪ZzVT*~֥;ᚭ:` Z9@e  ۱m ˦%+,˖u&6{8:<۳>@B;D[F{HJL۴H kP[ B iP+X`b;d[f{haA[@pn+xzhY' ~+ 4Km;[{۸;[{۹;[{۸ {{[{X'ӆ;[{țʻ+າ+ ˸+KڻkcY  +m[{蛾껾۾;[{ۿ<\| &国ݛ߫ "<$\&|(*,02,;65|6>.r .]ZmQ */+M`(p-.N)`;a܂]Ӏ( rӟ-M^E.-= LnQM|%N\_h&Puѣ}6q=>>,!{~nN-xN .r=N@4;Nܜc. j>η.^ֶ}ָߛ^uN%3pؚQ,֑= A蕎 ~AQٝ>=U\}楾dl8a{` ^fX[[0m#wn:n 4=>   =>n-}⡮^&/dN ao ~oa`.~]n}/Q=R_ O֡]}hxxm:_(8{ miPvҶ |1!pv.T  aF^}1Y>骯ʝc aj_c) wv =4  P ɣ21| OUNt q@/ 0B>$N,^ĘQF=~RH%MDRJ-]SL5mnSN=}TPEEgy%vK.'=4]~lCG:e +c!9}H.Ajg-mzmסہp!0q2- HMSqdʏ7KeȈέPၚ^=}B{ᢶG,Xfy̓] H(a ?;0:TCgy A?<J+ fJj!Z09>(: j  @((G2H!$H#D2ɔ:dI'2J)bJ<ڎk.Hພ+4z(5*(7ʇ43tM 295ٌ,8tL$A:l=E!mD lւNlO5 Tm3'KsTtJ[;lulH+2`+2'z"Ͽ4@" {"![g,*i%-! /$ pO7YHĞMkx] Ɲ>`+Rb/8c7cq7dG&d*rʣg *P˜g+5n9ɜ+ ,NT~23B:/ xI^ TUk4m*K ]slahҧ!2])ڲ,ꝰ8C֡;*lVPh;rJkZizZuH[eء dC'u4yW @| E9D„]wxၜ @({?|'%G?}u26Gnn.e~ru k@Y% l1q@H-pNeΣBպ()!)BE )ۢ($ijŴapPk~QO~[,RZآ aNspHhanY ]"d\@ B=2|h'Ye_txWz)(,J"R (`@# V O(A6\/GsʷINvғe(HRҔOjSާwt`xYE9a &PaeAS h!E%Bd3ECjm1a6&4a.!`@x$Ƙ! fS͐ʄ)h Fl&Qd)Ifu:hP</c1$:h9N| \#SA|B0:bA#>(ii.BxDL9Zz(DT6թO:UV5(tʄE W2Z:˥հ@?EFfYըv5ø͵i{ҫf|-T:K(HjM+93~`ּl&njҪY3Et3k(l9MTlx4[y!Dy P uȓ'ڝd5A(Jjzջ^o|UEY;<x6Ek-0*Cqj2I \YnSk>n8XGhfi2+E%LLY •Qa 7/'ʭUMJZ4M-ƉV3,_!'q:\l!}q 4NOzԥΑWB5Q^x f_e-|8A4xG"Ò7niːHhi7߹̼qǦ SCu1mt;T ^AYf`!Px|& LaV!q2W!cC|CSuOʧr1(-aNG$AB(\oJӧ>K}ߡY!8585@T<.ڜ2 @s@@ #@1|#<+A lA@vAX+QpA $"ܿC""؂pP%TBP-@B&dB' -˗K#+3>>0>:q@? J > Ӊ>CM.4; B4CDċEdD迭b$&\B(y0>03ND530< ̰lESA/[ dȰ^d-X"` ;v32AA"ԜFD3TF4BAz4보)>Ӿ93tGsǝ8KǕ2)s#/>ĨIKLҤ˾˿LjHٻ# aThdŔ1;|<.xNA}ѹ4t~z4 P- BDdO+̟AUtE˴FڬIȜƕBBռOAtIDJEI4AIIs@͌tJȨͩMóqDG$ǖ:tQ.J 99*R){CDx*=lH4T()R{OL EʄM E] dMPR,3}SPМMFdF<-Ћ$SIeJ|T.Q, hFMtJ3~m̮CQ讄螺C&%O0O*\^-, QDR/')V!QpAt҄$؀g%BU:/O5ViM$,XكأX։ʡjm֭VҐ04!>h";K6hC; ZSNɸK͉[آ5ڣU@֌eإڨUQV&3C'W38*W?[QzڐT4uKk԰M*(Eھۿu \i5E\ZEu N ɐ8J-Þh\Ξ):Y !Y9M˓TmKdݡ[ݎH5]\j%Fe^kmHmen ?΍QWB3ݝQa)vy^!Z O@ʼ߿=EdMދsex^^3uIbuTQ Ѵ R=SVZm^Yx`Å`Ґ*a\  aF Xȕ;H?ٝ@ HW[WUD( EȂ\/9f6Vc<ج:ce UTD$AcTݓ ߝpYYA9LՉB*PUKLEcuvR6D8TfV !c"ɥGT%FQ>GZ]dR@jۚ5]յd#I[aXSl?WUo瑁ecev>|Go^uTsf{*][sn=:{C2ƑsaKf g懖nqk=?xJ`:@CexΠh[Mc.uΉn4Y_݇ 鞎*>ވn)0Fj fIdBK'B彳r,鎮)C։%i.k(N@{-iiC['WV^~j vnl&ɖpv l6>2ThbvB~ћ*딫4Ec(Y(m9@똆Kh..ýkK$F\vl񀸐k)ȦV5-=jB˟p扚B-:mPho1\ zFsy_63kYorff \>vX*n*X WqC 1lBe< 6)<ܠx#K۷kDvQ`_m`Pr%26׏&^J5苞YJr 4 6wsY ߉=>sYjttXtH*8CBXF'GuDot~Xj*DIZ.uGtXt MUVvE['uWuOtc+t|0YGuEu+mW aRcvLs8q ^oZ6CN;0;Xǟq}]*wΝAK(/wC=3/~44MifHIs~sxy)su.ss?y@w(u(o'zEpƸ=GQ'Ngzt߁o^zWtKHu'uJ/uXvv_jG oO_z?tOzG|DztVwzuovw'Q-t>ӮQ4xxUx!%hG xorCr-՟rC-as!hH} =77~yq)HqG(uYuvKzWPx'`P"e2 N1a<Yw#"9qŇ(JC*W8HӥO yV)9tH|'ifS%͍PRPլZr+>(%Hʼm`8lew^wv`$F bF'WsrбFA~`c:UoЄ;k ,Y1ܹ]%'rk/Uʗ3'{?^gq#bʸR\8ٷ@vNƨO FU[? 8 x * : Jx`xj!z!!f%x")"+&0_W[l-i]sApQ SH1$E9 IP@K6H5UAqRUTeMU^\BF!% ;1R!g9'rT'O)ѝ UG8HB1fM3E)VBUx9}j] Д-:OZsŔ]tEZ50aV!mhc]Vujm͎\ԊUНz p$S=wi9ݡ,:<&8p/}) о\:h8M^1в ?R<  xmr \#8)qrE{W,8{x@1>SgԲ)hRHS.Ɖo,TXґͰ9ZBD '$hMZDDmm㘈đPq(JѢ֬sGɛ!*Px ɉ!D-KJ DA#tdQ{Gn/ #X{5S?ܮ~VdG⋎8Ȫpr Aw=ylZJ4y ̘aC@22є55m,g"v)-- r ©І.oע(\;Y &׹/bPL:RӵAn ':U: к%aL|֠ܮmJ_l!H]#D*5-"TSץk5,8#0Z- #vcSÀ WIVY v謁4L!+d$:I6̛4~({?܀wZssg"9ЃnlF'ٕ%tua Ї&\mt.LQ]rj,fvps7vd ;ιo v;-WG)}QFvz2,AL)*i_U\ .c@+q-!0Gr4{ħDH+Kja`Ãˡʍ"#~V>| Aڳ}p&i;;3-RAo)8x^LAoe&dpݠyQemYTUE A4M{D}Fr@$ubW]@`ZՀ|e`n^`y(U!D WXUC%tAt-\XGV]!̓:P_~!.!LH=Y[Hơ١!өan_2 )`fA 2$" R1,t B gfuތܶD(` U qE Gn,mEZ^Va*"D-@@"V]\@ͥYN#n!z5f6v7LuԵ#~#<#kb_9=)S5@<"EL2%VE2qj<=L]\lFt K ZqP_"(F.Wa /2j̠W@ K{$KC˗5dD[4zm#QCZxR*eQ6%#TFe8Vԕc>9v]:=ޣaTX:PV""&b#EՇ|VABU$Y]Kf')F@? M `\H`.nA,Y`d.ʤW0A@hBA(eb&DP:mȼd(m&pTV&%9j8tN稨u[(UZv?b$^@ě/YR$M| '4R$\$VKd~eJIfc +q$A6#1$kQHdU4V&T:thQ]q.?rΝިhU#[#IUy\c?&^gu%A[e_ fo,)Ft\hNܐA:_hN+`8?\i[gV'f%VX!iu|Ao*.*(WU(^*"w?>˄V*{b^aYa(Mh nx^ 蒎5&'dN(_%&RKgu_@Vy V@!}&m6_fẍC6e +kTnVN6c=^)'S{FUa&[vhOn]&Bt,vH-T"b~v\LXB\` Āq+͚dN+@~*y``+-X_B\KJn^)/i$`(eU+-`F\cn,NW @ 0-A&ffUUv.&fn/QG~XZ.b.k\XJ%B$?\ ǵLm!ήqJ,v?|$kdWGc-FTGb&:ҋUҪ^r 0 #pV/ 0 ."*.0qE.b$j \( Jni-~\u#6, DK~f1O9GN^263oWl 11001g "/flly.}`)N1LF2tL&0jX)cƕ `©A )'Y+3@b˱.2/V08q.@pu'w@Tk -F"q0֕?-kn9NM.3n!3R6bS-SDdOvb_vX_m6S+̫#nn]?$WXZ!rbPo5‚]GY&muhK4N&raU0A/nHtOGA?rzEQ'6ww7b66ShgU<zwzW6x7C7_ؑ||h igUC_o, Ȃ4$j1k\ oG!(Dup^rcDpnSpU@$4|LYZ+ w׸'*|x}w}kEew9RXMv64O,Djg.$#OY3&r完Gv8 M⇩2q=.@\`A%ܒ WC!F8bE1fԸcGA9dI'QTeKaƔ9fM7qԹgO?`^„݂-.$(&fՊEP9–{6 Aa+?|IwPi 6.ȎڤoyCjb Y&)f8A9CGN 5` !XKάTY)^@aS9:5I}&[n<7Z|/"`ێFkL%B^Up<P0Ap稍VCKp&o Wq-s_:Sumw'':r&\+|2`'z+5ԋʹr!x6פخ$sΚL $ CM$79 >!:tRJga$m>h ujT=N$P֡69F/VWN/f~T=P6`z?lRʼn[t\K' ޣ"* <_`6߲,3(a*gK0O]Y2M5IO.art:58Ld5eXiiwBgYCO]k>SCuer/UW6kXC/~ ??&@`+\>t)J[2 A NXA fpqO6Kw0/qL`X2F2{qCk9z'iKrj1nd}ӟNxV+Hun#< `t= iB ȩnCLGlmSGG!L81/c :j2Jf5{lmAjQ\[6uĮ|jUdS< @+PU161ړQ!/z0U+Mڷg•5| 3b&M&5;+/UIoyϛ)iɔj|ɫ! Zc](;Z#0Z-qS:I\]&5nۈr3!0'xH|3@){[ёt?M?u7N5 "kٌIQG<ʞQc#ۮ˞w /g|.n . vk6rIDWqpr`׼.( g.򕷼y@]<ԫz~Y=ҍy2=!c:=zpntaۅ_Dy{o˾p*y_I?~p^7OCk̺@oa@jQcm;yY R8ή z/耫NN NFV0XZe tNΌ~fboY!` /is( #LOrOe"k n0 p}piJK @P0 欰ft rb"9`Cz&aD\0po0Qbp0tK/O h c?(j̨19$m ?6FƝdVΝ-,&D}n UD11]m, o@ O8$h̏ H+zJQs}.xE D$φB$ كg`Fb1"%r"?5o-2#50 Q0&,pM׀XiK>~6x@T );-Ա+T aq '?ÑE ORj6!!"+602,ɲ,}##/]#Buث(g‰ R/'P C( > 0VPN4LZVLT_Fbt5 ;?s;j`DPpxAHCH@iAsΜ9tnT)F;-d*{6މ4TEu4δTQהFND-wz]84zw<0@F'")fWZp x7vnPkwg VِψtA "mjq΢7k7Զ!0wF%n7(mESOQ ܩؗ_wr/އS5J YyiFw-RC'wx]$Yꁍ8{j 6H%Qw%IeIvn| "vuVsW}uX|Si`javUķ˧"48X%yx0/m06*7^Ij^s`"vurgcksR8rɸH(aa:)08<UcSq$Yx}Y3`T-yMFtԖVgyxfx 4Xe7.X[,nq>h1J`Ĵ'M[eUvyhl9鹞;KyUgp]0xc3sP~36ۘW~q7LQ_ٞ5A5Al&")@;mByi!9u:bΗwmِW'$-rrw&U)Xx5V~Ș=hia!` 2?lEYGےTky5(庮ץϩ-BU1?|: Z36@mrX$p햓voB ˫:zj+3m8C\Ñ;a;zuzm[L zDcQì. KzHk)[wg7LG2[y{au GeCq"3g5:[o;qj{FrzZ>j07 @Ρ+q QX ~4@xix%<#N:S>#!&s;ũw 'Y} ZBgj f  i+ۣ¤mk$ ×v6aݸ 9EA N7uTXܽaa\<<(dha dkv Sgy]S  򀎜6©IĊu5m1|ꪺA 3_Er]ּQ]'|>$QeE fdgBPsâ:c~g6?Cߌ5rkG۷5}ܫ)/uKP~1VP?:|5ɓONsnW4E-UϚyH}Aڔ±fkzA <[pƌCy 1EǙZj -~ _4>L>]{[&/[;.$K0STXL'ceQ8Abč2>p }+F?Kyv쳥Qы }ܠA^06Z)ܔ;eVk?] ?kd?͍'¿ׁ^x80Ō3R%GÆ;l1F|c@)]Q#fZ& tn)E=}^S&ˆ5TrԩiɓjIBj 0X,4Ztԧ)yҕ[B?=5QF. >8Ō;~ 9ɔ+[9͜;{ :ѤK+:լ[~ ;ٴ ݼ{ <ċ?^|yqCސnAjڕqֿQLq,:rrHU!Olrjځ=dYt;}S+PL"u{Gx&'VpG?'eT zDAa繴nb*b.c2H#f݈c:8mcBIdF$p1s:J҆}8DMH -gYX !Kё]H|!?)TIqhfEF\VXbA )UGiZr~gQ~ĒՈini~ j%Ij#n@j kB.nO4A -ġ\^_XN5' T*k NN|2t.'6 vq9Uv`"ֵqvyvuxإځY`Jpp /?pALq_16ikP6O51Rl5'Br~y.~.`lTVX)v^desMP_2`3u^ vbgqfzgvnmNz+G!nG,]Q-zBvG[!r%uR .tDG[ (X+ {:RJ-&G)p_%qG|dغ{"J|/qrwǺ*$Gk?Ctl3Kks hFUr\A ~p8xbb&u)B88K ~8 1wx/A5o38pq[Ns+؍zxF&$r$>ا6<_-=]S~A41kiC-r[(e -#Gr4qllHNJy0t<M cy+gݩcJeYTɈBi_B܎䀲Xq%xoZ8@ i`9Hv+:+Tit2*h2cC\r%cS1,12Bp־5+<$(Md=SIS,[,R hb[HMn UL 9yɡp8}Є*t;C4̇JtM2S ު\S&)9ŒHY'ՙQȩ Q'q:J2t) 8OH$*j]\pШJuTTEJbu\j sBeFn}ha@EM U| N, V LZGzD?ŒY|vZQ$SdHIYIXU? Њ4^-ljԪ]f3̹+&="JY%V]uȲDa(),op؁AE8 X,G::*I5g:w5jߋw]^kNŕt8n=d*r. `jTE 8gm`+@w)Kj:϶DD2M_jFvyx "x]`1Hإ~(>Ω8+,k";U8K:b#$jC(z,-l-Q8yq}cl25;͵(ڞJD^¾+sU:/<8QGo!v5؆k*ґb2Pc|q:Joie匸IiGKJO} ʉr S5{XwOFMUsʗTy~xևygLǁtGW=yC-LFhR9~;(m'vQqcsX;/Su dT0c(j0T5ff>!^Qh5a2r%}ȅ]k Lcxk"8$BNƦqYH5FuWw=Btw,@|a\ Lw|Ohd`y8?WF?%Zx^bdhGb艡8cf(hQVeVzfrzbc:].ǂ!j!1aEJ/<(!QNq-bCV7ǖ7R8hYG_(h2u?Ɔ~QrG`Q`_Nuxdw?QыqWEeW.rb_x8e{xY()U8BhU7SWW`wrdtB&M( Wnd4dR)eNBYx )ΧEO SiőFuj5"$i{r>+RiR!ц X2FRm7 5 twf`VdHˇ'fT;tS Ŕ!SwX.d!vGY&aؖ)Y&i<r\ᓬ5P Zv?SI)6"(\L$, Vպlĸ;ե Tdv\ꟲQ$[܂"̥{ID/8  Q0,%<67qпFۨ3P@簨ټSѫ-BW6!̢KxA{E8ƎS թl9B[<|'kCL[9.;} l/[ȑ{v O}R-+,})I/L1ƵnGgYMOh#ٻ';=Q%2mzc>-˵s8X]WE]MdėlF{m:&4\텛}]mӿ]VL]bнzrf [{n6)z^Tu'Ł۝L砜N5GnӡW{򽱈4ԒJAJ Q=e2~1{у|L5' > n(I3u\1-[[8kK9p;ҩLm۲!R13F`]wuC͈yGF>N~x9u]Eʦ[Nͨ<&u͖*er%% 'en9FIus&2ovNHN1~_KQB@,p!~sܨɱԡw9{YNKxXSK5"=)ٳ^N}댾]Q@ lp-sk^Z/ -NEDaFqH"4H$0 \,'kP+*C6KK̳L JErtM8sN:D*I<ȷO@t% <,*JOL,K #R*22SR49KشTTSUuUV[5jPXc}OwV\suB sA(45ӭ(rBdb|>%ZQg\[pwv5\ ]vu]zm'@)Ou\V۲QZf+E˄Tr+b3^٥֎Cyd@zMk vSuYgc.6gkLbzhFd8iv:ד}ޫ4WJ`D$8` Ԍ߳w4SF9hnu|z!o't0&QZE @᮸Ĵ!t\9 + G]0f2UCۼs}w~x+_Q*Fڀ 2s~8&LJ$Hte_vN߮q~ןFKxP R`IUB,2-G@K(AFDy ?^UL$ǵ?<U9! ' pH`d7d@XJ L}"hG Oc$cB@4idcg!PA z8e=,zFGP+譂^Ȉ 2{U2D?GQd DS~2Zi%uf[_VtQe/gF`e$f1;+.*á /-~qWTl "@GJS&%ohNK AteL$&8]<-Kբz&; җ ehCsgLfehEcL/!yºJ*>BF&'@UY !9ns]#gKzIuVt+?7iѳB|* ,ׇ/nk CzUf̢V#aTBT,)m2Мf%WJCTެe*9r)(' P 6tV4g-6FHYlg={*%mi#V$*4,!KH>nh:# yȐ^l pʼnG&!Lg&|ϝ't*$U[ťR&,YVKˍWDl{^o} RˤcWX$m!ยSz# ML 18.M3:+=W`C &uݖA֕Pu"^X;} H_Ysɯ_Tk/ҏF>[͢jREcKw,5^v Xc&P? YkKr*o(SJ  FsldS"׊%TfD'Z9a3hHG;#kU;k *4L/ZeiielUjX9ҿ{m=Ix`dU4V_Z,Y*\~ry[0ZӆWkkg[uyQ%gOf#(~ݺM窄w/7l[^v^\ָz`fW6cC1h̪v>t-~q]ixǍ*zNmڜsz|]d0RcYq)疥1V)ꄕg٦m]E0 . 񽆰b]jw;GIu|sSl\'>2^ˉ.}+K- mZޕs֖;ɰH%c`Q`IOG,zeX~ko|O~Gԅ.lg_E[|}z|3^c%^fgM CZ|*tتP?K;$.#{|@+@ ,>;/ 6>l?~)?JAZ4$a?['뺊+(Hv?|ٻ $Կ*Bˮ,B̧&BC1Bˮ Ѐ"HyrC0s5C:Lu;#(!Į9!z/,ˊw!'H@=Q4Į*QBK49NS\ET+ Q4;Jd;K?):E_>4 Fb?]ۂKL@SBVGt{CJ9dJ̩AJL?1 (MTFJJP P (Cр tLгM883P-ɼ,s2f $PxH T9},-JvG'kQQ#Q,Rҕ`#E%2M-+O}SۡR+ӃҾZS= +?$,1utSPMTd3eFE8}9SN=-TQ P С3ԀkF"h)S]SU{%f LT`QPVcURSUVS 9W%H=I*ZJePIiMSkPEܴM Vq;cb-WtRM hVeM֒VMR%VOHE\pW͹tՏsMX Ҍ@BWK;TDUSieFkXQ4KmF ,؃]zkXX٪85XDQDY4x%LuVd5cYT<mڸO@Bd$QڬPXvZגe7,(=Z]4E ]tZښoԏ͔#(2UR=l9۴]\Ys[h[=V$MDM-0%7U[[g n[S{]E)8e\ձ ȍQY}!56|}T~֍-\FE\e}]m/݋m=[=5Zŀ H=߬޼x^Rm3MۈU#P}Ym2MݲLE_n M`}_!-Ѣ\[U*ѭU]X>`%> u`` S`؀9YmQ *,a 1Vf=(Z%[a- &?Tb.#b+T%Z6^&];Ұŏ4;+. -b?1N0d\WU=cx YpaUW^Yގ(]\{mӓ}9?d!(bQd @de},垫b^Ȫc Oߑ^_e`NR&AfoxPTV^FKW[@5)bKX ڽ%fu8cbngbwPTFcWA572+;MȨT ű) ڌ|z P   @:h̹ #m>΂PB B1\QJ"K{ x˒.3ωLO<1#)z '6iDNRj; ٺt^g#xw=D-0͇NvHۥӠK ʭ")L/譡& :J"6NFTP,@=I")* H=,L$ +#!0SCn=Eik؛ٶIMN߄mO˽ v >_j6#NDfz TU͵n@0l-sBkɭgn!;J??8PN;$BG~T,%!ڤ ! mt.Kɬh,?뽙v¼L^PsIŜf_NaXn?y~ngtWXUT[b)ᦀVAJn* A ȑirrmRiX^B&%n15oG&I|BB'4s@Oڮ%\mNd_VypqGWR5v"hMɠJh3U8$n;<"OYWO#BLĂVExzppIvrbvz3/;bo?{#B*œLrwWFŘDNftw7H(Rrue^ь7O즽U'ZoSwf ɝB>7v0I~3G1?v2L6=l̢@/CBmEwz H/zqINUKے ޿/~<ϣO~=Ï/>ϯ?X`A ̃;#ؠBRX$IA SSATP ȄZ5nm@iV=:@p1VdBEʴ]vQYWb[r٥_ޅcY! g٦oe8AՀ$Њ1yQVA5$DJcO.`edQE㓈n$vaZsڪh&ݚZG!i~ @G|Naj2;lqc5Kեj4碛ۮd)⛯VT^KMB"avD$P[m[aޒ8F.Py# 'Q%͚/ݔ"J0 q6K-m/qSS]Wc[s\c[DB/8= )umNCЦRg3޸dC-G^嗧l6~9PE74.p}_:# 8nݳ{㞻sN%_{3A<@yFh=ַi~]xf_Nb(b{.nD;9{3>PpC / vBh~ ! Kkmғ(ɭI{"\J74g |t>|v]h#"qT&\GD'B(f(νPZ7)t>Q Q{^71rOH'1zp뢌H$͐TEMpBThKb2#'N2Նǹd,"9LfdHEp$H%5_}'ic檏# X2h-hM󋻤!Bzo3YCf'IsNJnڔȴnhV.9`MnRś(A ڮtќ](C)F1[\]7O"Q5vMy~1jГ4j(җ4@ rqa2zώnVT?JIT)S-Ԅ.*UJZp)Zљ3 F:Q*r+]cUNzAtcZX:VMVb}Ƒ2u,e+_ i3Hl4h!.mOu,mk/K;;T,2]·ZbԞ=,ÐmE.ȕ6m*o%$`*XgV#sH-WXk]sm7%hx}XVA6W),+6i bL*aDv0lz8y0k @%' KT0e /B(435(`I*-ti- /J^2E 9;9K$1iM,![!*`O֚1K"lD<>V^h/kJQ L%GQYR?5~cѐ*{@㙺07xILUЛɤf.^FC Sȱ -q%x4>9`6nxnaIGt,-ȧn2;z(FQfQfLz.ʪm;*h1@F)-@.#z.@]'G9)p w!N Way۵\qٷws>f~L4 K͈B}9My1?hZ4Y) ^f`J)6M'b>qŜr`X./ί9uX$llf,х+CqSཊ@(]zcx>K%&.;ۋvg_\wMEJ>y~=Wyr^, ?Ui"Jq#vo'N_~7p?Ռs _Qeg]ݽU ٝ9_W7\a`KqK=WyNStaET@إڤ#|Ą) V  "!nD*`-@dF°Q_-)ʈWWY؅%iaxʡ |}߹UEW0ZW[ 6Z?BEO ń u^O$>O_eȆȍaDssJ}ⳅF#EҘa-"̡a.vpIh\%UY1OQDaRE-Z5a/.jc7/БWa44:j:ɢU#6=7O>c!jEp!3=̽BM :K]>ZE? 7jdG:8)WW,9W)9d3 ^<] FMvG GdO6H@cq<eR Rƍ4%0,eU:U%VZUJ%WnVeVX~-YfO Oe[P:82 X*%]FWv]R^b_._e^ &^fXaf]TeW%ZBedZfF3?(KZDNt?x&Oh>hi&kk�nE[LmnnCn&opo&mrp6gq&n,t>'sF'`L'v^ufuR'w&x~Efy^eIezbH!@ &lgkz& A'f.ho*hm2(ڦ:hF(Vf(v(n((ƅxJy(瘨Bd&N@A A ,AACԂiNCJ @x)BB Di-ę2D Ԁ^D->Đi ,i-D)’,`iB@jch.َVHbD^p@ j )BA &Ё@liC K VAȪAFDR6*FijAj:jĤ iP~qhnf*A\)*B k)2 &@@@کF(+C(kΫAH+ҁ,ĢJB q0w?2lf A%XUP1]Bp_'KnJ_ ߊ.A\Dm+0p  j64W6&H];o 0 Cg1o1Kt7NC{3C#nT^s%J&Z) U:2RFoLkE/> rqѲqpACPg5;/ CTTEgE[5/I0wG_Ğ41>Ĉߞ7U`j s(s5 2C3GP3m*ϘuSKtTW$UcfuE`fVTWĻ.PZop2['A h2JK3?6;kt 2 Kn DHra4arrA`rBk/tCKuf7y6g,7˂vQQn,?5f X|[3m7mXnn3@3DDp3O/v?iiA_Evwq8txDtvoES2y@sQ;*jkժ2ps q7+K+c.A`*ru.vHex7Cĉcy%32DE<I/@sڶ(44C,R=y9g43lChhiOkf 쭌3w&):KA 4+[j.ot*1o:, iz,zHzCDz_CijJjpb+)+,GA{}L3/v` DB+D#ڹK|1nv.@t~t73`-\~w_O܋ݴFKoL"~{4yiW)P'i DƳ? QaBt6p 5f3ZtH~XBJRL#AR^fMxnI hPC5ziRK6ujTSVzkV[vlјcɖ5{mZkٶuly486E GYh] >F9 905!5DY3货WLgXٷw~|׷?q~)W1 <0Q? ((Y.I"NMBl9Ⱥjbh{rKh6m3+:ZF";ƒHk:XIN N(ELv|8圓:SܓK>B =+͜` VB,hI:6t  nLoJј2m2ƘRB6(MG:ǎ餩 Pꪭ^5- @Ii Ay`20VN BYJ΀ c6Nncv(L!Pujl(WJA9Z0yڝ-_836m>U_u~u'm{[B"Rc;,+M]Чo(~<&6j:6K-C@Z48˻, J' TW;nv{)XA b0IjxP0@3Z(@r b10[cѡ#K8Wo -p `Z/U%,IYWE׳^NL@/~a#}.XFwEЌiTƻ 6 /Qn 06UHyHM|A!}iNbo?243*?T" Gڛ_g&Mna\dFNQ2/]*YJW(le8K[rbB;f fd!"u4(bH5C #CR!ؼs"BOe696SIpQ%,Nwuj9O{x%_j0~V4&|u_( Pm #+qТ?)qs y2f$Nx1iYSӦ9N1h .Fnz'ٲULd=9|_4j4 D$zdQyR;:( ҙqkVxZWԮyի,Ծ aGūĞvx,)d|ciQJ5[ڬ*,`RsUjY\qb[[>pa `g614ea$5(Cms3Y5&Gsְ wN|-{)|-r돗-::о,abfFNV7"*#)$ʢ'H Z""<&xYR1faHoPkoW9^mG!3f^ʠ-MdIˊp0PCbP i-(KX.cj 6H"%B Nc CQ)' K#>gL#ؚC4 JN)̯M b3&2cȢ/dpU'uq f$// 9ƙg 6 ~`r(O 2vQ!R‘JG0t0b|d0 1@*ʘ/!{'!a!()"cGb,H#4b暉X&hRCjg`"vonno#pl&.q' 'R.(f(/oGQLN"gtS_*}*, &$BP!@5"&R5P鱜f .R5WMrj5cjBcS.mXBz,'!jnr":27 3X$$ %zyVuM2OSb2NQDE'dt Qy#r=TR^GS1M4tT]"Uehg]uj.*0Y4&0\<2D3ޔ^|o D`mXU792K:bDjBZ_"dfQHKp@L@`6Vau>oWjSI`K\bS<@`5WKxXSXe&kL U31@%8}6u&Ӹ'=8A8ߘ-@/^ Zf_3#Cf.11I`:~ڇbb ?c1bɓ9"IWHFeؓ čC˂z1OX-,H`ee,yT>琅/qNYJ&7RCn=-- KךywvAVK0a/b,pcH` Li."9+Y%z?FYZ x#ﯜ1î"1b Ǝ-'g`Ӭ8Zu"SɠZС&@jU Ʒ)2 v7"oJHD 7#Ud!,Dٻ쒒b0g/Ϻ!™uv/x`KY7mN@LU2R,Ø=S4Ȅ֒-gboZO#+:4{Ź*|7Ʈs}Eu78u-bo,(ek[ڱ'7ⲇۃw9#5T ö}!x9q\- ~39-Ax1";[㌻/Pɬi S+X/|qQS,4e-B-p&4,";{;?~۽;{/ bJ0#!p:+꣇p`; ς4M>d2D ×FC.8|K}-SUo)/V~;_GOj[Egd=ԟV-T]ڵխD6'04R b6Xک$Aŵ’1b{O`|8Hss١SׂA.ZqY/:IJgbjϢo{3·%ݺ= Ӣ_^6-7-5"oPOVc0-doB˥#} 1D5W州d,b7{U/QG@<ˏ &_{q* B9:$k+e~9ӂ֟6,`+))ų ٲ ,B%,1] uYI?()-ςcsunzKςҼ,"dl)s_Z1b_!-,ϻ?-X>,% jGq"aZr:hŌ3ҡpY5Б!G!Eʪa 0 lIfAw8$ųϟ@ JѣH*]ʴӧPJJիXj5ͯ`ÊKٳhӪM0'njʝKݻx˷yuί  LqÂ0S1]2gѠGK̯ Q@LvF !2+lkD<%āi[]+_μУKNSسk![pO <حvHˍ#sd]\ftVg4} IQ֟C)\4C t[2a,BZeBslcJȀεw}Cоh, #PءyT,LbF 13ɤUT{3 ΀ a42k^Nΰi }̬6 ,kOm2; *+wr[%r~.U$ KQLk+qč|8 )\$,Z8}T#npEƺpU//~֞\zd iKvם-2|-^9Jbf˥,ޣul=!݁;O [BKc#W.]T'SQ߯n}ö-KćQc燔AN+ev5|/`c'oN0SOe#<ǿOL"培H[7,vKڵ,4ݖzcgβAi3bQ H5q2A2X.BjV=!Jax}"8F~$~&f~C7yDsVRVpecA@PpRqo1VLX ;C.&G3t5rGb8˥@f Ƃqap@aAg)FF]3Նq&r/A;<8rwfaLhSxuL\EfkS:XaU`1"T%Eraq|rrtr(\r-(Vx"z%J3[X&)NH>똒,NhߕthcD.VudQ:=Hl"6D#y !voԌwR,-45urkvcY9c15wlٖ9Ԓp9ss9Yߘah!~E9g'&qL)fq|Z9\Lv6f(薤Y C#?drå5mti Ex A)"tUA3rw6 (( jteZg9R`99N>*繞qXru(i)Y9B,WA@jIj/a-ҕKi*"",YJf1幡#1"79i8)vZH73q5ћaFdX z@G$25a')Z'Kl9k5p(V"Yڡ\ڥ1`:Siqܥʟ5-H9h£2(!-P L9"|hÅ*$饖z6B#کbhq iaF4h ( x R I4Q356A0Nce35`(%ƓZڬ*Z*zYxla3W9 g:# JE誗XJH;81;';`t0CxeȬzC7 xsf!!?{ /z؋h6џ68ǧJhUѳ-RؤSZcAO:>P2B[!14A70a*u MZHb*'3yɺ@;@kҰczk*H+HdނqKKVV[KE8*L,a{ɯX˶95!t;IBѷiXli ZeF2Ɯ,z0< )Ųd2qn]٤,zdJK{;Ix$KJ8iڭ0SKIDkeGeς !c12r"!m$ Rق+)5Ѕ50xؽ<{<D+*GUuwr:;:!Ro-Qvm3RC5N,']c5CRYL|RpQR8Nq2Ai`'+{²! o~0V&L8ZJ6ƙE,\GYĆLSLQȌ [zb"ze/ܻ$z%!>2k]xQ9 `Qr6;+0|넅|ȾllNļ성h [릕űtq4sxһY)YQDûë"&6 0\H»Ŀ|\Zڱ7%p9Ep,Q^39{3p B+. !3C!Xb\_: ɸ/  Z!9YȲo 4=l||̔[KDSz>z9kU[c iʡc6lѨG%m鶬4D(8f-3]j}:9EJA-‰%X&\"Mф%,J #If9GϼQb  iZjk' }b! ӟu6bz+Es8FQZ5CEz 茑-۶ gl'|p;c֢7xĪ 퓛 G]-}b-hN;#6R-ZZ<{Ѣ6A!bZ3+./L~ ?>Gr1vnF+I4vZ3Aq#;Z45џmH&R31T])m5(]Mdl0h-t9k1̬{ٯIBdYm9S^{ufa뎾+yRyV L=$1|^LH: b{³?xKo>6A,dNO/J>M'i3n(r Чa6ed!W_^ Oit/dQ/P?:!YC=nB_貗/Z_- |֙~AO6Rշ؍h_Q?݊o^@(I+Dʎ(7ٙQJc"RkF},Od7^z4(^*O :DP|xD-fԨ!ZrdQc5NT(I.J e2ْ;[TPEETRM>UTU^ŚUV]~[TXe͞EVZmݾM0'nośW^}X0y՝n›v`$̅1eD8f $otЄD!g qʓNo>i >1#ZO M, i-]cH6||8E3x͟G^zݿX|}0@˰I bn!6@ B*4R+0h,:-␣:^@+׶'9-;ƒ q Bf"Q#d+2J)J+2KK/o$L3D3 Dl.rl"S )C M;<,C.NO2펃:xz!It\9$1R%I 1#,ĉɵ2VYgV[o+5w05Xa%X.DM2:3l3VQݳM;k7:haBMȏz3zp-Tl4nwTXI%Nvg+k \&`F8e~ugL'b/F6edPE0 CT7, PR[#f6dQnܲJZ 9=9KVh 鈔^J7WjdTKubI`k&,%.;mf{ل B,\T9[tpl!s B,uveNsv7ϙuW{z2lOG=uսnv=vgyzS8@[c]/0nAeC=zYLT[|,H3HQ*떴^~?jX`H)fcc!nĘ Dy+4y+\r^RmQY*hEeVkH2HYHZpp3^A/th7D"шG-щO" !9Dx7-K:h  FƘ#:\Tf^BPHzHB?aJO(3Øo-1"%9IJVRaQĤINvғz@/Byq45\ #wFIj7EF:ifȢ9ȵ B?,e"iInvӛߌ'MӜDBB7)ni.]\+K:|-/ߵ@\ A,BP>fGYʱhë%CgHE:R^%'\ĄR딏ܮ;nV&04 B]gm<)/Uhekle;[Iն muۆٵxiї wThH!2\-pGg#UQG%=$<+"-$C.nVjo~O斿0|+& PxNoe&V9:0,snKGtuv `وHѣn ^qjD7q,W?ЀSw"yBLr-MKuNy,Ci0=tJmzh9/%KOmX|dC<9s<+ }t#dnы*4،>1xF6B ([b -H ؉xxg^@Viz Yc ľ{uuMAϽvBA9N+T8*,)] It茻9xK}H|KS2cmJg[xw"qNi 9YtE򧥱a3Kئs%djI͝xPsj8jZȭ=s\(錄qs/ƮBh9IpKXV9gi:Cl%]#G1CYg}򍉺].WZ!2ykcRuǻ}3$+ PK[fș#qrCKP D0eJe!Gĥ=wַ~ya?>}/};悁a= a9AU!|` !âOIKrTSloczח7e~z}Bv$v?1>P,6_<0[7z815@$?-'0d) c.H k/&i 6!Z]bo_d<:Z&г( 'KS{CA.K10N'2 3+$[C?xsA~Ҿ C h2[Z5[Q #ҊD! mР(̚,hDjFLE2*t"E;`2 9 *:d9ڙ:Z*_Ą+c tDk 93F r 7IiȈldkȋm| ")㠧eG #L3+j#( **E <Bd~d#[ r$ːŐ@{F;+dʦ$,ʩtn"=|IH:A<ȣCqG^\X>$K'ЈZHg,JtT*ʱƄLʶl0h;8AXt DžcÐe*TH J>A3|dȤ4h%+2A%&#fk,C -XGx*!: Ddװ~NϳÖˢ h$OPNA%PLUʒ̄Gq0IcĺCN M󑄈>V8ȉKS|DTݟ-}$D"SJKEV$ P Sv0)l% D=‚`I{C ;6uӯa8S3Q3R$RPGKRK`d@e *0e516: fs!R5]7UU:9uX"3;4 %r r5jL&3((PX`U*EʚQ[ -`N%O dT2 fE dtUWYUXew]Z՘CJS`6괿7֍Ti%KZ8YHC 5ׄhK#La옪`VDuqCH}QUXTUט٤3qךYSn,|=? +ԉU 's82R$(gh j؜Ts]a$ӧE>*ث%ҽrU tϜ%u۸-C=0۽۾ۿ%5EUem\eN˽ NTHz-6]PʧέeU٥ڵ%5EUeueZ-6HSH2l:+z^uHIu&6յ[AmPѭ&[M5-_DVL E&6FVfnasΟG:: af,X\"&Nv%f&v'()~_^R b+ f]#FDPb*v789b*ZUHy"1ys( |0<HCT(*y`dscxt8d>`IlمMB04V[cMR:XYZ^;%؀rXEQd9UX_FУJTd^^gv`@J]T@DRRkdb6nv3^tV6wxyc\f'C^g=i5rf?NfLnMmQ}`N}gfY쎉N&TV7vwFV`{ph>e^׆cΦ f=V@>^b`dnhOg3f.NJ6Afkyvi,^j~V=j @*(hE>dTBef-h=HjNtv=ɦʶ&.gh`nSUA~]۷>ԖkƦ~굶iKm"vf=Ȯɾ&6l8Ύi~>& ~nPl~mhm9>6^PhnضBPLܞiўfj^le_o&> f -Oi.4( G6bžRff6岽dGGpÆhEHfqpsj grye)rN6k~nr v- ^0Oqj6%o4dz'*w79&q/`r;01o6o>WVB-6 EgF/9',rAe=nفld2v 7P$D EwSGT_HaIs^Ls?w%$[~uT&tQu"urrU'b7veua-Z:"gt2j0_ 0cpduWgriL[&3OmJvovq~ws+@{7nwg+w?:Ex'"xH-Pgw'7GWgwOՒz":H'7GWgw7|8gw|CO|ɧʷ|||'78gw? 8  vg : J蘂Zۄj!zN8"e x")$b^,8#5x#l0#f8#A 9Y<y$|D*$M:DHJ9IPZy%Yj"]N%a9&yye&mIq&uy'ɹy' V8(*( hJ:) )Y)zJd~)z**:oz+&G++ +ZŢ6,*:;J;-T={mkj-݆-1z;.嚛Pu.;r.ڋt/˩/ t0 ;L0[Wy1{!1%,!2-㗲.<3q9뼳q7K3A }4ICVJ;4w1pU[}YS 5]{͔=6ef6oq=7AoK7ymwz| 8-x+x͈8䑛8[~yŔc9>?K:{kz ;+{;{;|ӊ<#K?ЫJ=ًi{܋ > )~櫿>g>>C?'" J|`v'Rʑ, r CI&![xH% X◌%:Rb"'IVbOXE,rb(1F ;"#(3Hn|c.F8qrS;H~"]A21$"$"h>%:\)IBBd +i!Lr҄Ё/Tx>O?,bex&NOx.FN_,x6Mocx>6M,xF.M xNL,yVfLdy^K,浄yf.RϬfynJ,yvF%Jy~I,zІH$zю.J!,  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMSNJYPG`RFgTErWAyY>}[=\>}\Ay]Es^Li^Ue_Zaaabbbbbbcccddddddeeeffffffggghhhiiiiiijjjkkklllmmmnnnoooppprrrssstttuuuuuuuuuuuuvvvvvvvvvvvvvvvwwwwwwwww{{{22 H*\ȰÇ#JHŋ3jȱǏ CI)S%S\ɲ˗0cʜI͒'Qɳϟ@ Jh:*]ʴӧPJE4ԫXjʵ+ԪVKٳhM˶۷p{Rݻx}K޿ 쳯_ˆ+^XÍ#KLcȕ3kY尝CMZҨS^0װcVKw۸9#W5;Nμs˟KNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*& z*|*z띹+k ;o<PlNULf#jJ? I+=blgʮ¼J?/X6,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBACF! Ay@"0TR  !001,`1xHA"%,XA A.{ @,S\@VgS 6X6g0`!7`@7AA `Iop  >@0%'Ih?@?@B@@CABECCGCDHDEIEFJFGKGHLHIMIJNJJOKKPKLPLLQLMQMNRNNROOSPPSQQTRRTSSUTUVVVWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~221$G*\ȰÇ#JHq"!+jȱǏ b1ɓ(S\8dƕ0cʜK8siΟ@EB?EB@FCAFDBFECGFEGGGHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~221,G*\ȰÇ#JH #+jȱǏ1ɓ(S92ʗ0cdR͛87bӟ Z9 j?*] s'O>]2JUѣ ʵ+DSW׳h>= civ+h rNg#ETKxuh32cXV_ʏ3 y b4LgF2Xmbqv Nȓ+_μУKNسkνmOӫ_Ͼ}^O5,|KòT~DA 8 7x 1)80)ȖDD~=סbٷ(zhԊ'U0ؠ}6FxU@!,    !""########$###########$$%'( )""+##,$$-%%.&&/''0))1**3++4,,4--5..600711722844855966:77;99=;;?==A?@CAAEBBFBCFCCGDDGEEGFFHGGHHHIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyy|w~usqomkifǎd͏bҐaב_ܒ][YVUSRPOONNMMMMMMNNOPQRTWY]`bfiߝm۞q؟uՠzѢΣʥƧé221$Ga 20Ã1|HQ!F0=~;8542.|&t#o!n mkfa [USRRQQPOMH @ 83- & $%'*'$#       ,/==A?D?IDNITOVQXSYU\X`_bbceek!gs&j,m/o2q7r=tAuDvGwNxUzb|tր׊ؑח֙ךؚךךככ؜ؠ٩ҵͿȥթ᭸쯲쵶鹽~wlb]WTRS22 H*\ȰÇ#JHŋ3jȱǏ ɓ(S\ɲ˗0c>cP1ɳϟ@ JѣH*]ʴӧPJJի ׯ`ÊKٳhef[QIPݻx˷ߡ!GrÈ+^6dKLgneI72ϠC]9[rMvHװccp?2(L"C?bk1Юݵ0ÆxUسk= ]<9SC8c կ?(3(ŀhG=~6P_Bq aYhh I"@"(A : t5<N8ܲӋ;eꓨP F\Z X4t:-{Nr^4`3d=\; q s 4,nKl3=G;4B|fvslqO1B"v!8%ʡ⪤<#͋7˸_V99?K hoS;G~[ וhatؐiNc:* [0_WEwz:sݟ{D ̢b Nd/#?iF؄Mc``T(&U-L<h*]JZ4`S^-▍RH@Z+=<*ADB|#Lr+#9a"q' )NPXEtKVd4 Κ ,+boS;HDR 4C HKjHaދ|1 p!yA-B2$&3K\Hg|חD 鏕I9]MGZnc,E'_4(tQ)φ 2rU6iԍzd%ž̓dG!\gy1wOy8~1ΥP7.O8y绁+EeЋ#! |.ΑFUGnl[E]qXՙN-51P]>)q gGB]ZR!UyLui4qŧtZ*To/`6I(444M8,kA(Y)V.FhĔȕʔSLS["r,O)N*g9(2jR4> RL'ơS_9B&$9|A8V- )Pb "]& FeI*W2Ah ۪%EH"uޅ pv z`vVm|KߣJ~=d@(nE  uۓ_6x0&T&  b0(=\ $/ҷt '#$ 3g|L瓈y ArMh"[x!SvDibgչ˅)g@yҘ4C[a?,QoдW-J 63gMaɏL2Ao=hW D&=CD$%ka3G6@ll{[.eM߫mX^gݖD}@<~1(@1x^Τ=o;#bF&PP\[&ac(5Sdb@2p-ϹK][!}D4 d|0ϗP_)N8X׈$H47d 7vi N#so^`);Oe/|kp'OyVZ++|7#_"G-9^\XTv|hjH^SSyypI_ٙ(jg ~(vrnYr9)ɚ89{IX*qi99)Ϲowzw 7))щyߙቊqH9ʙ2Xឺ) Ȟ)ْى}9Xo6xx.eMbד:yjkɛ/FDє !z'qyp9+>Y|h W@^ZqILj{8z}jب}ŘzZ)h 8r31!T?)b>[)(&* Yډ:+2hHJ27Z~-ԅJ8׊ۺ- ߚJ~w3hꮖzu*jYo\֓ 5jͧV*1xy8g2$%~ c6AjgybXkZi,|z6hZ5+}"Hn]@Y?}劳~Ze}ɆK}z&y7ʵ`v]xA˝c|* i{|%vt |Zy|09j{ٶs[t([|۸Lmk~W['j"*~˹7mFx8Z{-kq֭3غz{9yJɼ'T؏ G2;Mz&)[w6XnZۼ;зۤV۾mbV0o k|g9kǔ[vC|Fg۰vBŻ|Cꋁ4⛭OoU$\~µ& Z Aák ,"j)|kLGΩdbyN u8\Sv\Wu[rCZP'"ΪGXwcح%1:TpLhMƵjx `l"b qnCȍ|Ȕ <•q*+lDɪɛqY&"& K&쳣r$(ʿ&ˬk:y˼L zh#ɦ9hq&r Ve8I+,ol6qA;"tșrѿ=jp{%)+m\ٖIE2,nfkЈЮLJKYPw"}m$]v(Ml**Ҍ0j2=ӪV6i8ӓ<i>ӄBgD]{vHfJgNePG6T]dV};Z=]mv\bd]2qh j֑˓p͈M wl&=}m23>؃lȋ-im󌖑:K}٘]I׵٫\易עpڮ̱ڳq]۴wۼ-] qȭʽ]ݬ!jFSܝf< f] }fםޙ=i޳&ݬ Ҩ-F&G+MNdƊYBJ:XjH Ndfc1~dMF%n+i/1^3579;^=.?ACEG^I>KMOQS.UW~Y[]>_^[esm-c, akeg.˱mq)|2[*8h+ s-.9© nrn+}-Qy.*Kw^.A#nN*<Od _ / O?!?#Ϯ%o')?+-_/1o3579ox[&1η FBIPExUoYY]imglko V,sOkicR; )[Kxk/dl!,C  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@AAABBBCCCDCDEDEFFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 H <*Lx‡:QD cF=&츑&U(K-ׯ`ÊKٳhӪ]˶۷pʝK`db3 6ÿ}W0_ wM*'7X*cfby =CRXZru2q`ago2ڿ`ˡe@!,y  !!!"""##$%%&&&(''*((+))-**.**/++/,,0,,1--1./300533855;78=8:A9=E9?H9@J9AK9AM8BN8BO4CS1DV.EY+F[(G`#JfLlNpPuQxS{U~XZ_diortuvvvvvvvvvv v!v"v$v'w*w.x3x8y@zJzV{f}prcR<108:99852Ŏ/ʍ+͋)Њ'Չ$څ݄~~!&-܃5ԅ?ʈNŠZgu}22 H*\ȰÇ#JHŋ3jȱǏ CI`(K\ɲ˗0cʜI͛ Qɳϟ@ JK)*]ʴӧP6EzRիXjʕ)]ÊKٳ]˶۷pERKݻx˷߿k LÈM̸pCLe/k̹̞CM:ҨS zװMȧo;l W:{eNμ˟KNaسSѿ;SOϾw~?h`WO% `VhfQn M$Za(hR*"E"(c'h#H1q;"<"RN)4d$LZ4)T91RE\BXc`cdehzgi9k!FUѩ'y{*^ j(v硌N裍FܣJj)r(ztʛچF7iM9稣9| ^E6i;$lkN&MݰʲM5lM`+tkO͸͹^xGڴ<N+8+4&o L&a} @Rax1#b%N >b2#-syr^ dѬ5_R3ra,xh:PiCH=6В.h83 BVچZӛf Pg b+aլF_ 8oUk5K2aPƖ e3:~6G-mEF*qBmWޖ -}u+Bқ'`C=&Gq"CsхD#N1abd+n2M#3<9;x*7e>smV9)s|?om0C?s+=eNi~r<z֣.u"r늱Ƶo`knp'>wBG{;~pF|1Q|%?C>-j7\1Q.I+C(<$6!0*%!   %(+.5< CJS[`cefhmprt!w'y-}/!.#+$&*$0$4$7%8%7&5'1(-())()((''%&%&%%%&%&&&'()*++++++,++*+*+*++++++++,+,+,+,,,,,,,,,,--.-//0075I=XK`g^[Z}Y{Yz[y]y^y`ybyeyjynypyqyu{~؇؏ؗיךךךכםערسٽűηؾ22 H*\ȰÇ#JHŋ3jȱǏ Iɓ(S\ɲ˗0cʜI͛Eza ϟ@tjVB*]ʴӧG իB j*GXÊKXhwj۷lݻxm޿ +^TƐ#t+V$k̹C*zMڡ\˭^ͺ5޴hMvM{UHͻwپLȓ59ӗQevNϱO2}wΧ?nϞ&O8s@1W߁(t6bC2@J!PhQ nho6~4'd 4>](5#Ta͸QFaH6[@&pJq<@ZV`YҊE9vd pƩ)E%ʞZgX|ɗ裐J#JsXjT2F \}騤gΑn8ꪖt Gz٪둱JJR榨 >ju7.>[{K:*F-g''Zݹݺڢ٫u*/is oA*UZVܙt: Wlgw ,$l(,0P~Z׊:)3IQDmH'L7!ό?%#dh`-dmhw!+NZo͘mx|#~ ]<*7`73Uytq*砇.gmxϚ_.nýz끽ٴ̢,ܮ~ CTBѫQ]Enr3 5q !췏?:/S1oQc t9ck,:0iX#T J! Gx2 jlO0.6^ٰX!p b8C HbwD ;bUpŋiEh yQ\d0 ]PָhE5vшLyF8V,Q3 юfaHqH㎌l ɨFiN" T9NȤ8*Jq+' #!ңt%`)AYo\l6̢5H63]߁J@TLc6ɆjO&*54i<ʆ>)j@ȩ. RCɎts͊@]YYKO|@u`C'eWJ /ڌw2l(׳ }UdI6c4m@iYԦF9ğƕP]UrkEqkIb4~t9ϋl$AHRבmN}I춖Vņe ^UZ%b+8v3\aF֗/uh5Zׯj0wY~vAE;A`{Jr ֯.+VѨyg_IP38"i1X5n"}XN*W :J4Ctg3;8u|s'b$I ,mIPqXľ l~zW><;yG8A}c 2ml9,f޶٘:̫ m1CfwLvQk>@x5b\ r~ZLTW s)U#S!N喬$XVAVld݌^̤5NZo_h[[Zk%[C֡3\[v.qxTUkln7x&Ebفu71nV-z=+nXzefiqo9wf`E7I8w9}<ۜg^Y^W-fBK*WqE5:oN4%<[컦8Ѳ^%'))q䳡gq%.c<7Ҷ=\&A^sc > ؀ RA7^qp8㷁&x(6d!@vR)X6x0ׂ/ *B8D=X|AXPE`6p ,!\؅)Hg3ё[h '4|uj8t(B31-Q~7x@$f؇؈H;=ȃ] w90Qx7|ah$8x6Xp0(Aq1QXO ۷{XS90e2A6  !`@ׇ}mc8H88u%!ᇉ31>1K  ؍>?3AH?6K{;H9p1<[J&plr9X$1v@I|pxjh;(51|1k*yud2DŒDD%wJ]{wBKXב*hB◓')@2}E&TmFc@ ֔P(t9X$6`m%ecueY{%idpi{^r6MFxH7{ٕ}(k&G]{zQtwWe?Xd`VI^wH|i~ٙF4cJ euˇH 5izgJazHqByUv\yv=J15o4xciCB4ωSNWCunJ9RQ)X97ћS$syWؕО4T8֔٘8A^],bC)]C:IV&GVs\ud *XX`v%F9gaSzOD02z4GluwHǔOǑA 9/3yTZW8h=Yh8 g~DWwyB8 E!dp8Z t 詨6C1ڊ/jP3 v2%B$E!AaO# Jr!w2U2Jں4J b6ټK2|5ydx;ض6I$ƒȿ3Ywik 8 + "j&>\Ă(F(jL쾪ū+8 ܆(XZ _a,A3Ɛƾ Cr=ټ0&Z[g,1]R%y#+-7ԫQم}02> $<~ UR X"7| "E]L({'Tެ=1%*۽/P콫ѻb!> bN٩|^$S& #\g\0r q9׭ )҄z>-/,jxw| }N"~JAun?"{|޺(5Q鞎h>͟>x1~ڌ;֫څ^ї&ŵƾǾ~)ΰ,~~<.섫) nb@ D!yR!wʟ*=箼]b<\8e^p@ۧ O$b0v>.Yn4=*#(.=άix^F,OIOKuMO^>NngN>@N>%!8|s?s:a܆Ǎ2y>rQ޺quNߖ"} `m_-]xQ޷O_"aܦZH_/ z$M"^'RڛVq.m~OʼnG)O_k憋U 1*=iPB/ $laD QF=~RH%MDRJ-]SL5męSΙ+翠 1DTRM>UTU^P̥7Dlڱĉ^.\ZmݾW\ufDZUx`… FXb ,XǢ? XfΝ=^|lQh֭][lōn޽}O˪\r͝+_\tխ_vݽQ{x͟Gz|zݿ_u}|_r~~?o?$@@dAt0B 'P /0C pC?1DD$D7DWd[1F{qFo1sG1H!lmG"D2ɵTI'J)r)&2K-9rK/K0$H1D3MTM7UdM9DN;B.zk우;˾kcAV;$NIÖkd;qjph>\q=c8HC+8?0'6GIft%z oiI>:YE&Z{TQiǯ|KVhUbπ0csg _8AOUã ѐ> vp;l4WxЄh@^/#|ia?Xj:bxx]/GB!щQ"S W'V:QT hE.>IIEBE26< ʸFЇccwsFPrYAI- o2ҐxUC64IGGV3IhgINv1;9|&aIJŘ%i+eYWD^*,u9ZD_Fe0˔lD\yG8Ʉ&ViN3HD3^ӛSfHo*"gNvF9Ϥ##= ˞Q9ДI#L(I#V&3QMV2 SS%e?ص-[p0Ԧ1R-6J?P4*-Q[J .QwK\h*lrQ 8؅)LcVyͮG:ExKP\].e}/=P FE/|{"żiIb 0M **Q߳.>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMINSEOYAQ^=Rc9Sh6Sl3Tp0Ut-Uw*Vz(V}%V$W"WXYZ[[\ ] ^`bfiknprtuvwwwwwwwwwxxxxxxxxxxxxxxx yyz{#}-~:DQ^mv22pL?(!64ĉ-NQC AFREAIdw,9 eʒ O:e0-_8Is A$9ZX4b]˶۷p-ݺfݨwoþ~,p0aÁU1^DžG1’@fw0@͚6`@!,xN"$$'* . 1 1 ,(! )6 B F IIJL P] inqsstw} "##$$$&*/689:;>ADGJMOSUWZ^bgmr y } ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | w o k i i k m mn~jznzs%y4y@yHyPzXy_xewiwlvovrvrustsstsumzf^UE5-! ~|zxxxxxxxxyyz {} +:Let~|zyz|}22 H*\ȰÇ#JHŋ d\`Iɓ(S\`-U|sC*-sɳϟ#qJѣA)ӧPԸgSXjz0B\Êkdg=$˶۷KAhe)׮߿u3\ a I≯S6#c)Mʾ3kY-pi1o^ͺ$ b tiLTݺ  堭9q@#G=:i)p|q~!ϫ.Pz Կ;؛rgiiF}6`B >(![/JNVTo^P'PGUx!q ȖF&2ewK%aay5QGK"؂@6^yB6Re 8eV5Rr|elAa H2i Xjd|fAqfE[,beUx]dJy;]YAg֊kv*JZI*Da.6%+kѯ**{6(Rk-P^En鳊k.KRz NHy8%ۦr$6X/ ȓ\4l_p7iVUt1hg:1!kxoVy|2)hW9rJ|"Ar. 3u,W;-aYLt{P$5iDb0Ak3Wߗu&4c5]M&=ecMz֩Cvf Hye Neh/ZǓ?8bz.Jà gBz|ɞfŽB袒*1Z2wX9?mx^]njk ~~fwZ?x _d * i3ɞIW,4^{ O ~0(. r@! aC$bȣ&<zP*H fHC B).E.d8J B4,D#,30! t*8đ(X qH=bQ2bׁC))0XH} b>'2cq5S x8򑐌$ѯ̐ HC %Dqc'bQ(E o>I+_iYq]._GNa*ZR2Llcq؇(YnF4ݮ:Q+PiI7)vz$8rq£,Dڧ@*-mHj 5ϕ|ҕqp$>#Iʉ "cZƳ9ީ,=jNGyH' eI9 Ʌ#S";x)U7!ʄT?Y(K͛ͩJSI3Q'Dwm/cRYrPIC2jMJp'O#UG#X~hMI7V ɯ\7-0:8̑uH UobsRdFe"&FhY0-3iWY&ncGMIl;ݧ427'H\a4c鐨 v?л: vDoX8g^'~[;iybw dj9K\koYa 8)[ig=1Ctb$կRZ#SpP;qlTܝ2# sݲS[']&zfoU((A"RU:lA0`#H wӔwWJMhdVv5ytX3t: swJfyW܆-Ms{"1.Ng3c!2A9L4nkGpؒ+w "qj?c"k屮CzǏBwCI2s'[)uN; q.IӃnu*U!˙N׵6iwj^Bm"ht uGG%u<ΒVo&UX j=(:uEjRq4+o0$ 6eo7&"OVy!zaIu.q?k=]?{6Ǖ_? 05}8΋+rEcFۧH}"~6}c/#|m =3cp%4cX}ǀh Ȁ'}WzvW6&wChzz#8bmp)GgM?({9;Vb(8908"S9j7XG)$x'w[ bCX(i.z}lO|Iqzzg9Hddo sp{K1leGq؆nEup9؀7H')TDŽc{K| (R‡{G|XiH}vx| -|7xXdXy QL(4}x1rtmrjk X "{Hu ҋgD]ɴsӷp]%E#oY|T1ebqgNQȁS;(P'6o6QV'w5u!5wRNWrxGUz7@w~aN!>5iuو%9q)KɔM)OQSUW}Y[-]Ɉ_)~aIc6 {gyiYykxmixowq9wsilyVvyGl'G%~炚Owyexr_h9y:Wy"_酫WQ]VOǚIB5'1G+g& Ǜ'FfƜ&Fm)f IٝgވIKht(p$IYjwj8P YV" `ǑyzWl` qơ~t&mFgfb[TƢNF<&3F+f!ƣ%Eeυ$1QCZn݉wQ/xP6X[xD7kY%`9iǍbc觧姛%yEhe[J9Ũ)%Dd̈́ĩ䩝$DodbUCĪjڕ7k9Bi$RaU9.:<DSDhJYZPoڕžh iaX|Z dĮ #Cc냯裯ï#Ccƃð㰓#5yMp.: ; <izJɲ~ɱ2(iUWóND8#1C)c!ô"Bb킵ꢵµ3f) bザޢ¶C ]| d{J%w8 G!,5n  """$##&$$'%%)&&*&&+'','',((-)).)).**/**/++/,,0--1-.2..2//3113224445666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGEHHEIIEJJFKKILLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaa\ciVfrLi>l2o)q!stuv v wwwwwwwwwwwxxxxxxxxx x yyz#{0|<}I~Vdou|~yrqpnheca```a_^]\[YXWWVVUUUUUUUUUUUUUUUUUWZ^bgkosw|22 (P *\ȰÇ#JHŋ3jȱǏ CI$I(Q\ɲ˗0cʜIM)sɳϟ@ JΣE*]ʴӧP'իXj݊*U`ÊKESͪ]˶[ʝKܷx˷ݿ LX^̸c#{L%'̹Ϛ7M4ЁM^ͺ,꿭c˞]ڸsi}WCN=xسϾњNhbtG&餀 >)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘I(̢ .&Z& ꪫR (j몵t"r믪 챺pBlz,d,<(Zډ"mÂ+i,[: &k#{/ #k7tS&̨6+2ƌV[ c-ɋ6{2#-ˌ;0)+K7㬍(Z7鴣BB/F{3\,4vKCN]p5N\*؏; cip;ҁ?t`7y#(PߍpӎhO9~#. RLclJQW Vp?N#ZA\?nqc;?ʻ?{^C괻^~^R!, J.   !""###$$%%%%&&!!'""(##($$)%%)&&*''+)),**-,,/..0111222333444555666777888999:::;;;<<<===>>>@@@BBCDDEFFGGGIHHJJJLKKMLLOMMPMMQNNQOOROOSPPSPPTQQTQQUQQURRVRRVRRVSSWSSWTTWTTXUUXUUYVVYWWZXXZYY[ZZ\[[]\\^^^_``abbbdddfffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvwy|xolhc][YVVUUUUUUUUUUUUUUUUVXZ]bglpv{22 HW0bÂ҅Jŋ3 嫚Ǐ񪨱I\10cbIc1\1sfU'Y'1 JTY*{ I#ѧORtWFXEU鰦$[aNJ l^ ժ=-_q-nM` ؗ^=#ͻ Nȓ+_μУKNسkνOӫ_Ͼ˟Ox<~tϿ(h& 6F`fxfv ($h(X࡟0(4h8$ HNrrs&;622L*;HVβ,s`y,2!36*QpLg x3Wg=g3M-քND`ѐt,J[”7-LsӠCMR{wԦNUm5gMkʺָεho^Z]`ȮfuΎ i[J=n{{M[Nzu;m7Mʻη(~[ڞMOi;j8'NHIx.{OG(.S\.̛$F R1F χNB/җ3PӣN#hVϺֱ`$}`{TŠh/Ogn.vϻG~/OƳ!/kBXEFᅄJ؄ńN(VXcxZc$^b]b(bƁcxVUl8ֆp8aat Xxi4|8_P؇XhXXW`{؈H]VXHV\A׉[^xyhkw֊[xSX(RAI=B'8F!XwJI(INcR'A7VV _w\&A]?;'f&Eyj)inmrq9v9uyzy~}I9y#00#vAY!Й[ I!ű2+`P)Q72ћQAIAqAʸٝ9 ٚyi49y2yɞそڹ}ٙ:J[ ځ j..#Z+J50=ɜ2ТAi4j): 0TZVJ[Zڡy™`J)*A92-J8wڟY@EbZq:  *}9W :Zڥqeg#*#rCđչ+ZZ*yje8 TJ::X؊Ʊ6P|)jꚴ٫zZq:ZڈArNZ** +  Xk+p I*!i ƪʜuʮ/z za늤Jћ  𴝰 R;TKXpXa*, 0^!;=jk(˱1 10ʁ+q 3}sJ[x:ѶqB[4PhЉISM O;0P{1p,]1e{qi1,zu;v˷q;Kaz¡kzyRz K밠0`p{п{1ȑtK|+ˑ; |9 M*/ 1AF//Ͽ\4^6~8~)5N(;>56N9>H4@ L^Nn9.UWZ4H_aNcNKmbrniN4"n P 芾>^~阞难yKZf*ܘP p^~븞뺾꾱/{~{Jт܍`~ >^ ވ;`Ɲ^ya^뾾r ^7Lp*|އܕ`? "?$o 0ʈ}x=l <>%?D_ {0χ2/MO舀:@=/F`ýχ/o2ܢ@ 9< |^/?龎cqLY __  aa&yɫ_ooovo@  _ r``pro\pP[kŸQ? BWSLтXzџ 6Ҩ1 Y!M$yRʓ#KdL5męSgFv  LƠCuxTAU^ŚUV]~VXe͞EVZmݾW\hx3^}X`… F,޽i׾ S%I GU]^rV_ZZ/XP3L?[Yn޽}El4UdXtk\Ǟvݽn͟G^z.n8ʗ3oKu.`X`ti-tN%$9#УrǗ@lg\)2(C\O Vq# 0Ž#ݐ #q8S3(:22K/3KL3D3M5d=L2,Lf .b =A.lƒЅuHEPQT@YQR2EipAL%otu |6KeCYg=LhZkv-oNPaso[zE y3#qۨUnfH`E!a_&Kx%T{{8$IX)2[Z$V9fݒvfo9gV>9te _z &^)tqw]Xa}7Z7!a_GK7a{kNxߗ2eU :d䢏 0ʝegqlkv[;[tmnBZ^鴒eio2؆Dlm[6׹cs[>TSVqC^nxk;MjTf$y ^ַ/uJ ݒvFpkܵ$lT1.Á.Ru axv1_Ћ cS72L R,OhܖtWk t_'L)eF8f Yr R9-F?t=N98yt=hFRЍJ!=ia.җ1IٔFA=jj4?}jDկ&_2tu=9YSHV^Ok(Y<@ljGN٤f]Fwή=l3yឡnvlܠ.nٻ7^-}cGp>x%.O}HPvGoOA>r<'y#r<}\#Cnuqvw>tGmv Oѡ>um)}3өH_'u]nCk{Vw~{][;wϝe|s, _v |x\OP6 <@H oyO=v@Q=g=_gu|_wЇ+ߐOG?ͧ 7?wǟǽ'C =@8,k=ԜzĊADԶ*T:E!AԖjzI!ITTr38293;M]OE5թT2P2.2R5T)MUӬ+x UaݧUm+jb^UVc1V^U$^ձg>#njKgt2qƂ 8WVvUoW\H?- `׌փde+xZz5X ؛aش&l}{Xdؐu7w˂XV_V{%Y~ٖ*ςx^mYEלPE6jZ؂X5ZkX%ZWMZ٩ 4=\b]YZگu}ZmYٰU[ZaX mVcۺuݵaBڿe*֭[ӻU\B"\ZEm3yܩ2@[PcR5e}Z]1 -Sҽ5Wtu]]-̅U Z]\k!}*Mݏ%^BmM*M^uŽ")jr 1jEũ\M[u0ߛʥX]X$٥!5_꤭ڮN7Yj`x`L6p`~!Fĸ ` ^zF([Q& (^# !("UbI( &ΨZ\*)⽰bh X//Vc7ץǬc2v -nca<0c c462>v=6d:F]#NAHVE1cJޙI䳰zdISP\dUOa_#WcSe^ VާR``Ζ_Ffzd3&B^QiΊf.F'fn l&'h:kt&[>52cbvFuq"2Xggzgqd_^gg hvo*h fiNhNΒ}v3d^Ng&x]FhfgN&hF鏮.9wƶ9ffV`idriy6Qnc"G6&6cv~%&`ރyjia"gވk,Ikagv뷞,9ek_&Fvk&l0l`FV"s\nf˾f%lƒe^l+Z&mTNmXmYnSZkvmèQJk mUmE"c>n7&nHS^Dn܆F>46o >$2njd&.od9Fgd#gpvpD2  pCp2JV p`?@ߡAs7t@(Vtj3wGHWIϡ&#t=.gPt0W(3TVQWS9uu]/vcgfdGathWgv=lcm7tw&qᮀjOwXwnw1wBy?z{n'v~slww7 `|tfx_7tyFG/ sﺋwso7yzGlWa'gvvx' O`w_x 7`oxzvg"z1w {o?wwy_{{pyx-/?zߊ_''| ^G||o|Z Ï̷ɿzχouџO{ӿ w_՗wׇ}}Pw}˧{}(} A{/G}UO~Yo}ӏl~~~l/}Pkq=/u7y^''ĵLg „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔݛv[O0Uѡ@yʀP'РB^ J2m)ԨRR:U AZr+ذbǂdL6qI-ܸ"k.޼zkA.l0bf_ƜYfΝ=SLR 5$3ТGL4ԪW^nYӮεw7T/nxF׍Bn;9tR:C ;v}V@nV=*˯o>a7G?EԵ }* y5xMx!Vzx-1V^l΁_v"-/8#)=hl^#A IQCy$7яMJ9ERy%*ٟYǞ^9Vy&mi&n]&u~gy ܚ9Q`ݟJ*he}hh XdZz)ab)o9dIZѠQz*[i*2iz+ XmH:,:{QϾE+DJ{--FۭWRDV5Eֺ;o{<0LT3CSՕ;1H:14JqIx1%˸)w\k1ψ5Ȳkq=wHALJQ QE+M K;O7TR[-_WkM\[tCI{=vY}j]ho ^\s[{mX[Z߇+WZKZ[NVW?4ɗ{W埋UV?e磫NV諻TRvۮ*.WOP \UNP;/TKѧb+ 5?=&E=U/}U$$Yo >'}?~C(ٟ翿 a(D,D%0OטK(o&\^!?~'|aFCm5pZ MHBH@1$2," H8X! Q@x0 !"$̊%2щqnMjP,~A)kPp֦Q|xNO1 UŒ},d+ P&@>E{ eY`_ԺMKģGI?l*ݚU򶷽 tlT4cfRc jK62Pc+6=/z; % _rv)]R7W)W Xzm;amp3P apewW#UC, ol +0;MG5ְ>,!FF֌,4Qq LL[Vre\%y=q;qӬ5^~s ѹvcl`3G3-@ϹЛ겡UVgH0:f|wH=y43MsӞ4C-QԦ>5SU{F" abChH9ѣCMF;϶e e3~6-iS־6msve=kd׍#v`ٰ-f<7Ⱦ7}7.?8Z޹N]vy+s8C.򑓼&?9S򕳼.1V_47r>9Ѓ.F?:ғ3Nzo:K}bH:ֳ p?:.f?;Ӯn;.=]^uQ};~?<3<#/Sz}3/S$ѯ>9~>rӯ~??$!u Z& 6`,F:N^T n Jv | ^ Ϥ ̠  ` !!&!6>N!0!^!f!val!!*!ơ}֡ޡ!t!! "!i !&"R".#>b_4"$N"%…$V"&f"W\&v'>'~("P")"*)"+b E+Ƣ,R,΢-ba".b,"/"*"0' #1#&#2.#*#3>!:#4NJ#5^Z#6ncj#7~z#8c#9##:c#;##<#=# #> #?#@ $A$B.d*$C>:$DNdI$E^$Y$Fndi$G~$y$Hd$I$J$Kdչ$L$Md$N$O$P %Qv%R.%_)%S>%99%TN)"U^ J%VneW~%j%X %Ye%ZZ%[e%\%]%^%%_eF%`fG &afH&b.fI*&c>fJ:&dNfKJ&e^fLZ&fnfMj&g~fNz&hfO&ifP&jfQ&kfR&lfS&mfT&nfUz%o%p'q'&r. 's>g8'tNH'u^X'vng&w~y'xgi'y'z瞨'{''|Χ*'}ާ'~''h(h'.(>h8(N(H(^hX(n(~h(~h|x(hz(w(u(q(o(hm(hj(h(e)a).`()>)((N)8)^)H)niX)~)'ix))(j)))iP)iJ)ީ)))E*D*.jC(*>*B8*BN*V"*f*n*~*)**©*)***檮b)**B+")&+.+>+F(V+^+¨n+v(+++b(++B+֫"(+++',},§.,{6â'F,yN,ł^,wfb'v,u~,BȎ,s"'ʦ,q,˾,oƬ&,m,¦,kϢ@~.VD (-FT @^mSD!X-vmi"p׎O!-٦!ھ"--G#L--..&..4FN.VV.fnt~.膮.閮.ꦮ.붮.Ʈ.֮...//&./6>/Fo?Dn/v~///AJ/K5d@!, %(& $ 3%/;/I:X@hBk?l;n.o $r%w))z:,}C.S3jL}h~saLCBFLQXevճӤϞЖ֛ܠ22l@0ƛ 8ǰÇxBbbW8>eLBHEMx((dg+ed*VkBCiѐy*yݱ+騹y[{KEƊƁxl' Cmj6,Wl#&G\E ,$|asy\,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` A2hL1{l:box̣Gt Bqd!yD:ydII$"ك "YP#KLVN'a+g:XDl)\%G| bvN!19dbĎ hJ󚎣Cn&N7I8p6DL8Itz"Irʳ'O}so?AІmytDQGk$eIW0-KӚBmiNS4HcI>ISuhdKT%KmTWԨN!jQUi5] ˾S\VVmk޺Gڵbt-]*U_'fK"!*X j[WZTe7Kg iMP`+򇶶}pֆ .l+⮆Mb΍.`ŖU%`]lwK^y^M{K_̷}_췿.eZc&=Nժ /t# Sp3r0+Ƿ&NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNW]A*y5P]$띺qkׅ'GKbܯ=haЎ a-فv9n{;ʾ6og-hrC5Aڹk:ۗox݀vwNpo{ ·[|w'^{?n-qI(Oy?9woo Wg^E<08wϊy{Ntwї3fZFSVh֙;nspY6[?c>Em7ۻTs ءϝ|^ȿv!  y׃@y h.@g(7g<^G>Ⱦ'#x2!p{ۉ{ނ}p|C^<[`sߌz̋5=-O?v"~7{yGuzgnW7xybGy}gwv~Sw~hFws @~SVw~-8%x)vY}72 } 87rGyX~+؂RW "+!/XvSxXuqz%u>xy|AhpC(7qtWx7M؅*X}`1zFd(u؂@B9DYFyHJLٔNPR9>HPs7y6rGJ`b9dYfyhjlٖnpr9tIJG`]}d#G>i9Yy٘9Y)JXɗ}GC9Yy)J0əO9YyRٙl49Yiٚ5ryɛ6ٝ޹Ym4yY`R빗59y]鞿Y:WGiCG G)JW Fj5Z>7!d4Y-ʢ, H%(JZ5j!쩣Ss@ BjD*5F:H7 ZYMJ5O*Q*AJ:W4Y[ʥQ3iPfhڠjzSJ.ij m:6:}zrɪ^JgӬڀsJY6ؚڭsʮjw抮Z/ڮt*z k檢zxj6ڮ0+ [6 ۮMయK6ۮG GW?\ױc"Kj&VӬ@>7[` G{_G@Bˤj =03JXM|(+6(?#Zt׵g#?0KkҊKt+<ôkOk4;w3+3G{34[32;3K)g3 Ǻ;Vp˭q;-{qh=[q $ûpNj"pnU 7;Wk[pڻo+xս%[w;1˾0+F0馿0|0Lf\0 - &l-l҆L-,-!,F%*'Ŧ+*-£1l*3LÙe7Ypz='H €?J`ކI,Z> U{KpNHyN֐>r翝n^ڤ^靮։^̬sٶ~5nҎҿn>}QQD-^ĘQF=~RH%MDRJ-]SL5mPg!OLqPEETRM>ϟĚUV]~VXe͞EhO>W\uKmEX`… FXbk}}0dʕ-_Ƽs@~ZhҥMFZ͑f[l 7LTn޽}\pЬ!#Z[r͗=tխ_Ǟ];jm]s^xޞ^zݿ( ǟ_]W0@$d@ 'B /AA?lB0$DOD1E4$HA_q<SFo1G=b-%1H!iqD2I%$G\2J))+R'&2K-()$s*2M5dM| L,N;,:#O?4#'ӀNCLeQGrBPE4SM7@IRQNOE5UUtN1GuR]]V[oUV勵W!g5Xa%];5-YgcTZ6[mULTk 1h6]u׭uZoɅWFsc^{ P7xxG>ygy矇>zJǞI{?|߫z4G?u'}߇?~7Qǿ`[ꇩЀ_@6z4%8$Ё`AZQЃ48Ba U*Ѕ/PBe^RB uC.O Z 89aD%^Db sa JxBE.vы_c8F2ьgDcոF6JXzD)юe9 z!яd 9HBҐDd"HF6ґd$%9 tc&5y w<&E9JœD%)UʗlL%+e9˒Z%-uˍ]$/9Lr_%1LcƋ) A49MjVӚf6y`(=9NrӜDg:չNtr`\fO~ӟh@o.=GBP6ԡhD%уS%=ǕutԣiHE:RԤ'MN8 ԥ/iLe:SԦ(FuzGZjP:TըGEjRJ`@OjT:UVժWjV1ӝv= լgEkZպV`B0ծwk^Wկ[WE*؈FbX6ֱld%YlU!skf5Y)lhXd @mjUZֵֶmla &dmnu[ַnp L]!i}Eeùυnt;]V׺׵2j XCox;^׼^p^ZADn|?^1o~_w}^Ao|_6Uˀp% #hH D/Åp%e8\ƴ<*uE=jRݜ^  uEM#cuuk]kca"$@@vum K/r'_YZXw=no NpnrEo-mi ׃G\:بNPmzGZvOiQx%>qWs@uW}MQka'GyQ{|{r\&…pmҰDҕt7IOif6WOQ__{@检yca_._=Cǻ^)l|?x7Xw%?yo֣E5ys(ȼPzq(P ~@3?ӧ(r{ , G~?`A$u+'%.{o~~t(xOz`x>upoG (}>JO 4DTdd ,@C!H Z N@TdtPؽ Aé@ClO OD»;!/'()*++Z#11BK0d%'4T5dC(tBPFC:;<=>Nh@1$ħ!:y'EdE|n҉2)1BĠ9:YئOPiBpbTTUdqrX%dZYED[\EE^_$ƕ Fa4bTF9FdecrɉkjElFCpoFq4G!r>>???@@@AAABBBCCCDDDEEEFFFGGGHHHJJKLLMNNPOPRQQTRSVSTXTUYUV[VW\WX]XX^XY_YY`YZ`ZZaZ[aZ[b[[b[\b[\c\\c\]c\]d]]d]^d^_d__e_`e`afabfbcgcdheehffihhjijlklmnnnpppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 H*\ȰÇ#JHŋ3jȱR<Iɓ(S\ɲ%A!]ʜI͛8sքSϟ@ J#ϞE*]ʴӌG>Jի;bʵׯKٳIŎE˶۷%ծKݻ˷߯zLpR +^%Ɛ#K)w˘'V̹g<L4dC^Zְc}-۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TVi%rz]`'_9ޙh?p&xlIigxj?gvsZW? t*g:v)Rwf: tz)h& Q?Ht?,e/&c f5,vvQ̱!,             ! !""""""#""""""""""""""####$$%%&!'!#)$&*'(,)+-,-//0133334535736947:58:68;8:<;;=<<>==?>>A??A@@CAAEBBFCCGCDHDEIEFJGGKGHKHHLIIMJJMJKNKLNLMONNOOOPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22)GRa#Ç)3` ŃucF?v #X1%BbѥA2cp<8sϟ VQ/ӄAիq @T ol/HMmºk P bl7ahd,f `\Ml.?7͸sAΦ=U:0MPv!,Yo !" $""%""&##'$$($$)%%*&&+&&+'',((-**/++1--2./400622744956;89>9:@;;A<F>>F>?G??H?@H?@I@AI@AJAAJABKABKBCLBCLCDMDDMDENEFNFFOFGPGHPHHQHIQHIQIIQIJQJJQJKQKKRLLSLMSMNTNOTPPUQQVRSWTTXVVYXXZZZ\\\]___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 O*\ȰÇ Hŋ%NȱG5~IaH%S5sKNسkνÓOӫ_Ͼ˟OO1A 8] J`=pU:Ʀ?thڇDCS,X(@?<?1B*D?K6 r?ͬPBuΜ0!,M@F  !"""###$$$%%%&&&'''((()))***+++,,,---,.////00011122233344466677999;::=;;><<@==A>>B>?C??D@@E@AFAAFABGBBGBCHCCHCDHDEIEEIFFJGGJHHKIILJKMLLNNNOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22թG*\0 #J!D3VG~I1H(%qjҞVjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷]p-ւNыmdɔ^\9fΞ%KgJ} Z45jh-zْ1›7nGV7m5+@DG섿h- 6/[i !,fP'                   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///00011123344656877:88;99=::>:;?;<@>;B@9BC6CF5CH3DJ1DO+ET'EW#EZ E]F^F^F^ G^"G]%HZ+NW2TU5YT9]S JK3ثs.o Nxln'NΥУoݹسk\WFfTLf섹hNs5in3Lg,˹xγ>YǨ}ßM'-c>3ѐ#MJwҖδыM{4GMj抺ԨNoOVڵ~gXָ~s^u׾ ae-6*Ў6R1Kf+n{۫MnN-nu<7MpʻwNmO;j8'NEIϸ.{NG.g(S7Y.̙ Rpq󞧨> -:җtP:V`[Y^{e?ڡm}u[};?>$T``z)_}< kpAOcSGyFڏ<}q/⣚O[Ώ/Ͼϙ/O?ѯKyH!iWXjsX6$l HuȀ8hhXg엁Xa؁ `$X`#X(_',^+؂0h^/4]3X8]7<];؃@\?D_E8f[NbRhbQ8VaxZb[V`8&dxeh5lp8|%txuexn|g净8b%x[eThByX¥^f[煛t8xd4$@_&zX؋ËmX`%Ƙy،}ȌXH֘؍ȍJEXZp`TEBGZSWZG؏t$Y[h IF踐)F W86y##"Y#!9&"%y*i")."-2!196)!5y:s>YcB'8FyxJ[Kk2$M T)'9YXW\i[ٕ`_dcYhyglX=ٖpy\oty#kYx9^s|"l֗I{9 "wyy PEN y<N; p= LqpCā9;@ ȁĹ鋌|)iɀə=9ʹHU OYٝ)yA<9ќii{ӹ iAIѝiȁyƉў xy08@ 1N@iǁ)቏ؠH:zQDZ;AʡNџ0%jN"$-I1jb =nʣQpkj`Z zIZi٤OQlIyB:J^Q c lwjC Yhz #H~HCj2)Qa8$B`ꠈN:01 P靟*J*i )j+P؎N RP* k9z  ڲN:6jy㹲!3ehPEZ O0Eб!pѪD[* Z 5 ɯ9+;tzX˰4zc zhpGyK˴a&{ L΁#*.J7j+6Zj-[šiph׷Q[O@UKWr[랮Zhk5^[kMk+A@x0ߺʚe[ ;jjȺ׽ #QOQ+e$ʾpV:94{fy k_C h I*PIqI? Sڬj½ѰÁ=1 g^z[3þ@,\yF|İb\IO;OkQA`ܳ+i ü魖; p`ls| :ۻ}HqȽqQ+ȋ2 Y*ěiK_8Ԫf ;ra (̇{ y ˈR|(PȟS(QANp(𫘋=(p|Rϟ <= *= et xJz4ε+ҠD猟(b]G: )>=-F8mmP-T *Aў"ef |%='7 9,9S+֟ӐB挬BԵuMXLӈ]Bׅvf_aMc-e))֟]![4 AMܪ\Ã(ЪW *)HSv۲ؠ2܌ҟA@Yـ@Āѱ(pHHE ==,ə} AɍۧFО) iO))?}(3djtr Ο N׫]MMO(Uף9).}uvͧ@$)#)zuh`Vکo·>]-&ϕJ*=()k8ݼDm\0Y?uz|HNIWY.[9Yk(=}K ܆P~@L[Έ,*|հϫcnJ*(@ꆝ˞U瓾AN,˝^+l눈LMۮIM^>7q5m.(A)* (t(m [ўݟ{νܪ=̓R?Ao LAnkE_,$%^]R)liϬ9ɚpn^->FMh)}=b^k@^ )iB_ە_W:qO^K,\~_9ľ]/yP+~wNOylOp/ g͓g뭟 AAO/.1*(0;o/O¸Oͧm;<ǏA/ ( DPBBtBDdМA?!#H%MDRJ-]SL5męSN=}TPEiqQM>UTU^Śuj<]~ذ= Eh4W. ' LjT7.L B4Ƞ޹8A$.Dy 'Dd@%広# wCtF&,75Énj26Ȏ$\pōG%Rʝ?]tխ$=X_E`[=w5yp!ǦG܇'¶`3 <H;(5Z+„6TA2H#B:OD1EWdœ[EgFođnG O<\hS>P>^ω'3^+m ĜI l0OI1$Z3A*H %{˱O?4PAqPCE4QE=Gut;Њ'fS5Z44_Ð Z0"/ + $RLGӁ B;SVL_?3#pk=uk\c,d2Tt>=wwio>xIG|h'q+7^|‚]!`=?XO{ǟG BD vQJbn>w`E<OHJ>(-rqqB'v2̖/9 lUJ! O(̚Ҝ R @E7І7pC:+u)NЈr6\j]kZ2>'bW3~gJRЌgDptF6эMM&muN,l>ڜA%AŲHl#?Qe[߸INv'kd(E9JAږTID.:pURHCLAuzVc:.r v4IJjVf68dl) JE#$kDN`r,}Lɫ4͙)QoM44hBnb@DgiFNIX)O3ؙ8֕ !ll?2m%MGS=jPoЙ< 7pJ=U|G ZMtYf\%rBZ<#fT%$)Vmk\ȳ HRYjPd1kYRI#j0SYLQE(Aiճ]<Жִ\j(]ˣ(_ԿFUK; ˹]&%UI-2`*i$N;] mu]ֻ\aGQ)L1AHS^UJjBQ',LseR_wҪJF 2х $;nB~ϹM 8PVȹnv/a /z)N I+Q$ 'WEMh ( 2T`A/֫fUcoNOx̡oWis[|ٜ4m-a+#O=}t. ~jbMВ_0> y?s/pAz'^r_8htުuSŭT2[O tVd #Y7~۪yq>Gz0 Wh$*~s?7_?Aǿ+@??̿<@L@?B bA; /"';? ?K+Kk?lA?t@͠A5AAA!A B " dB&Bk@@*s.| %/C׉2'44)Ԏ*D@B:\0 ;!Q>*4@4#6̎*|-ʼnÄ=dDH(IuIJJ|H(˭ I0xK5?$K|\dž@>[ȗDKl/ xā+ljGǤL,.̊4RtӴDդH9Bɮ,̃ʽɂMJ݄Ƀd?p4̃˾tKܬNvLGHD` 0@,MdՔ<ׄP4 uHҵLH- 5 J/hDQ]ӡ|х8:m$ƶ`I`" u*}΄<ЄPʃRD -ό5DxTp7S;5UASUUSCD,Eά\?ԗ˄0PD@(Pl4R5]U U#EVUJ\-5=4ӠL1V7%r\rT5tUVE:JLKPI`\W<|K߬KlPWe[%$WR3#Ȣ3H,TqWS׏M_ّ v2(ы$#Ŏ [tY/$ٜٚe mr8;`ҡEU٥uZYy MBAZ`xmwZrzڰ%۲  E1!Ÿ[۫ ۻ[@۠ᶵQCFED}5\:Ņe툾EDD@EEL e ݡp]\ɕMw[- U]z$х]5ݸS:z$- ׄDEנD^Qy,#?P^Z^?^H^^Eߎ څ̭MMǘW=ZZ^i51 σȟLPuLVL`OE^ST(` ` ` O .a8a+`]^Z'cD8p[;1aW݅LP$DeR#mD}%`i݂Vb$̓*bkb*&Mn U2->)b5fpc*n~㜵a26e6"s1']IUPIDJudGIYML8O0`4M^Qn^(2ck-cWb3^eXO7)[<]3}-Uj3՝_,NMN`Xre$+ՊajFa>bl%FmF^aha~Ḿ[m;k?VNdV[ff ]X|tT_%%LDùf'_^0l،]e3/i onR.o}戌mVԯ8"-mݸ`H6pk" =R% ϔg_\-F? ] Gqh G7q(']laqqbJ#ϔ 7!'Pr*/I&[mY"),g+'rdvr8s13[3s{L r=r"h8?:7[:iDgBo$gt]\cvtUx%MH>/ls L'WO_NGuUlqNDt/R7u]uUZD&W>Ν8u[waS-DX`c'vCg.\0ovg?i'[>luv)Yu7CPrGsvnwtm|BPaJq GmlUFi?x$)II 9!AEa@Q:tRXD({+݄Qc9yqRr*Ef{g{tZŹX8)Zz)jJօm):*u"U+ EeN8Ĭ($ĭbI16It=ɐܲ 9Rr*, KBg1ermE$QQS~ߝv(9FH&BYVU*0 ;e![|1kL?j  E )Ѓ0*m[M9eR#=9 #?B&)nIGuGĿtOeEKR0/Iq}SV-L1 >8JLq+81䞁UE2ӌ RL─jκ[=GW#FSLv" qFZ<"2y8[6 =λ9& wL6%O+aw'SVx ??7~?/95VU$V e1 +LF~R G BDGdP!KBLB0D'SPoEQuo^3Ă]C-*LXJWV(QV-r^L#2jtI(:7AfCa#2*In^=7w9?,$ZE2ċ)IRґaXFֲ L#ZՈf,![t-.}+}6az% ТJ򲗾b$)aSp],Vc%t9B3\r8 )q1-A1өu>,|'<9czl,$YmΔ&9zH ͥ<ЅZʝ }(D#zvlr@j\2[,hLQ=)ҕR.})L'ИҴ6E EU0V'6Q:'*-*Rxӥ2nS*Uy4U,ni3CMjQ ֱhf=kMֵUUEE Xg@\jp굯i+`N [OWrwWMWu=,f3HjXbM؛W-[ʪ}-lҶ mFu5]-_Wq cL*j+PJ7˽.vCrinhtKԠڱy'Cm/|F, jzTʷ.sJ^7 dZ S/0|`%эp, f&˅On3]G<+1ض-̋QRDg+ɚf|!F272y^n+V5{l~Sü*Ai~Օ_89n3a*g)z~M@3n4:1ΊvMe|[FӘ}CIYe "׹ծiɓt@쨕; )Y=ҼS(\g1t~Jru%'=h2zi1}]/^}X[^^7~o-?<?xx[ˇp{X߬e 5i܌-Uff 6HΓ  E,G̈ 5 vo)Bt@xy OKT4`q^ QRirQm zoш܈" $$.M\[q!UMB`I >Z^8"nL@ '"EɠH]Qe&"-.N".> %/Rʘ S0 +Z+FiY.>"4N /^c*1P)6z1z %+BءQ,R#:aX:cX5&C6N=JI!W8cK#@.4$A~F8Au v yjr2"no_66K"IiEiEPL:8z'x:xң+䫾)k)daț> fťv:vkmG! jD+,BXV:+N,tײFJi.k2l"-V*,imI`-'pվM˂V*Bh-̮QRnm)~;-*lz,F)Vv-~1,kk|lklξ k)L'..nwBnh&آJjnJGUZ(~҉Qj*h4B6R"+x~zoopn^+*ޯbkąS0.06) /jn ~T7/^ on^ppʖgJ1Q ./q"frpZ!1,p+J*^CgG0*Z&W&Ʊ@qBR'Br ;:pv/0˧tn0$1&[]ji=1,TAFTBq*8 <)So"+O##/]^:k0Vޢu(͆:p/f,"A4/˞A!f7Q3-BuK3EW;U<+isI3 '3"0(p6p@AD1ߎ2 02gEW/4Hf4dsE S68Ym?jxZNzANK1nqFhpp5GZ4ZP{'#D|r2kjItrktׂgoVtRpWO񍪩6LZZ?vQ_2'i5]A@M45Kxvתzخ`WDVBbGYPdCOž_eHnqw0{Z5dk pal1mg0BMYnv;F6x.푞JP)57=rDȲFwN7BLh~xx8ɕ7ޞ?ǴzK0035J2{r 7 *p8H)kV #:kyksBl{t:'7ZՕjX? #V:Ɩtl@1ATAK yQ/l] C?msh72ڳd5';5"u #İ{Ȋ6BTxz}Wb5#DBklc6Qv9x"<)p=[+{@%|H{2urxLs){1<'gLQCF~^f'ϼ ~h63k=l$u!$9r3-oپ6+z:׸H#BҤis*pxyonmw{wo!w~Q67=$u5|y~[>.ٸDIu4h+?'[l>L;aZ;0 <̿yMh(ͣ>^v'll;'#/qF?u4@0qd &TaCIaQMUUYVaUYi= [ ԨF44NHz@ ^Y"3J!RMRv-kb" V!ͤuZ3 D،Zmwe}y7qW0]A>_E"P"*'C]HԄ\ {BKe͍XW)\Uc"Vԥ+t@7 qJQ E[WN:a vfGT"U0g ?G2G &/k2֤_+(WaESETHEg:iRv-s$-{A2Kt,ψ M? MAsO}:JBgK]]Tij*A!dW-bՄ85)O-gY{׸۠ ;=!G} RHBW׾kka۾515dTC#AieFR;co8%W!DY."ʖk^񖅶-TTXvyTo;+D~_!,I0$\ŢӄՇ"x`W vTʫ▦CW _/ˆ ;5y =*x|q  p&La"fNP/pqgNwȳЇ^MҦ'SmqaN!˰1uIK6d'q9Sy Zv[ZfBDWs!3Fh}۹~v !-UwW[;$vd! xc]E"sqzuxkau҃9'2 HX38}dX ZgTX.=p%'?PafY}FֽvdjV1uRm: #%=-7}Q5;eE}qR@Ϛ2pրcaShHNӑ#i!3e+3s3R$Tx# IH yow3"<;a]rynEsn7GGϑ]A+X !+OAR$@R*#CcNpZPbW O `Z+Rz@]?Ϋߺ4`zvoRI Y`1웧")Ѳ Ql1V_8V i Mb'YjڮMZ@PK!<G#ߜ#le^qmO_0Moq0 ïn0QcGnY hb-d* %z>P!I' ]j1NrQvfDs J1!~>Ϣ&ED@n4rlzm tЦ ]@ @ 6qm6k5Oߑ%C1!MO$UrEB#24 y4 I XFJBD3lLo%NR)3s<88fpfxE"crrN ̍4Q|47 829e=<@2"ƓP:]q4S;{&nzHK4TOEUK|v:KND"NnH@;uB(r#VS7!>vT,H5YoTw/>gDld44Lk$)Z>$֓Yl£]u+5vJC;POMTs@?iV]PcJfJY"1BA5^%(ubs^Pk!Hhr4JB VM7 Gd'NWq1q'Qf@ Oby6)*gcP$k"#:7QV,Sq1J\1]h%g3h4cRH-(SUV &*S6r1eWv$nI2bY6prls/ m F6xLu#v i1k 胎̕Su7p 7Ttp/NUo:kn#bn[l?J&f)zt=8iFQ7^OxRuev`RH 4vew` @r[Lx<<(xcyExW%c!/Y1_!Qoct_= 1&EU+0Y搡V!h1Wq[OoXu"Q#y ʐb&accc $~؂",'y7] /@9!$_@n!{%|oJss vLXQS{Qs "eos$Z9!5#ۮ hys)@G8>Eq2ju"w$۪$0[HC9H$"[%66qW"XQVH""ܡ'P 0 5*8Á|D ͦi{zMfyi+7x?bÇ8}+pL[WgB l@JigkӤ86ƹD22\1 ͼї bPZ'^'CB;۸Q{ܾ/m̽2踆 J*=λ:ɕ8@JMե2Ս}X}ic5=dQnCj] ]o.G"}}moKc?WH됅ҟ|a\zCHwvnNA3 -x:У;Oȵ[\ϘYhރӲus]#Jk9 l%|Ja%]!\|V xyU^SVTӧI_Ew+fqʎՄCW6Ǖ$so!8+qWP <Ď}ԙ@ۄ" Y0>'h_H≦z5k쳀H\{C8}Q~Y!=&Q hC)r@'o'X]Pb_y!a&uFYhpvGWNyXhEY*X@6@&Co3h A0… :ă( D&LqR!Ay(I%"' "LvLDСD j4ҥL:} 5ԩTZ5֭\z 6رd˚=ÿ_tк} 7ܹtڽ7޽u 8*3(6Di;Y8ɜQ9_\&$1D&Q4^sw vOzH)ċ?<̛CUֹԫ[=v{0QU2|5m' QX&sA9b7}`b+ H!M^u6{'\Tnana~8tmHb&b*Z^.X}2zqO>!D|h4cJy~OO$6$kvRKѶMAD<]FхPybbIff%jfnԋrv'PAW4rDN숂@dƝ1A$9]}(g!ښ1IV~7SDN<1!pjti kJXs*XBJ^8 }hX"Ɣ$݆GyUlU` n䞋nꊉk~ϱP6QN0oc Eb]JR~`iH7v VŦĎ zoqǮ5"Lrs.ːl( Y+?Dd gNdєg7ml6CEpCdP7)jw {Sz y˪_9`*6ĝS@#M}p|:C]?A*9ٶK xDrOJ tyL|?GO}kzJJb銽 v=4G#y;?J?U8;oc, pL *.ٓʆ>h! I~$G1ZgLLo1ߨ֙(O XD2p\9  */z8_5eLbr4, R@4PDʢӾyHI \ȄĐ@!!8>(@"ȈRA $"| x gۗf·D #n1c7parCoOv2yE]-^ mVcsw{Ʌ^7x:GyOJIm%A~7Ax(zD*dp@Ȣ(44jW;X A凃!)O "' S+( }:QmTp7q{CIh)Rh-C0ȊTAwT%"{{a$)q0@BB]?(;Ic( ش+A/ty fb(!})AbT/E,1Y3Մ(]I$6s ɑi[H/љL9|#ɚi)I>z'"!aE*pY7Xpc ~xCVDs'1txnA)[ݣOx6Y-j_<:v]w7{+S0Lsy?8'+*:O VI  娛VƘo ~<'Q<`ؑ]8)i,sO*q}w'kF!. Ck ay;'hJL4 &F6uQjuꢠ'hA_B:{9f+!{uEG:u뵎~뀾wNp>Ŏg~^WNN>ՎE~>5N,>%~N >~O=} ڽ O=}?#!O =%|)-1O<5h|9 =AOilEnI4>M3QOU>YS]+aO9eyimSqO}u=yѸ}Oh8/zy~{⢟{ÿ7|G}Gc}}_&)~+O K@&Pe1 @n`%aA`=AP#$a MxBP+d P3a _XC0l@}C QC$bxD$&QKdbD(FQSbxE,fQ[bE0Qc$cxF4QkdcF8Ʊ F0 ^,b @R$d! yHD&Rdd#HHFR*,yILfR&=Kj‚V@!, %3! ++ I ])oEr w,BK MZ lp j q } } ~ ~~ҋ!%Qeؗxrvú¾ƅzzyvprqqqqqqpppiqigdBA..,,,,*-')${+g5QcKr ?s!s6 R]kpvvvvvusuvwxwwwty;IMNTb`QIQY22@(@ ǰÇ{"&bk8> 2fK*+kPA\U1!%Zz)Wwɲ `kEX"zЇ(,^m0l8<jDmH'tT1i.-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*Z] .z` H2hL6pH:x̣>X $a k3H"F:򑐌$'IJZ̤&7Nz (GIRL*WV΀Z,dH.̥.w^ 0IbL2f:Ќ4IjZ̦6`P)8IN4':i-~ @JЂMBІ:D'JъZ'06юvT )GA*ҐӛLiRя/9Rڴ2MoSnQ@P ԢHMRԦ:PTJժZXͪVծz` XJֲ(0FVi ZRu(FrכU)C ك@HbXyd'KZͬf7z hGKҚMjWֺ4 P@-n3[I_mWt/? bZͮvz xKMz|KV=om_~'=Iq{\s> ]F7ΰ7{ GL(NW0gL8qK#1E J2G$%(h9D~b)ȲehKIG:̉tHi p.?NdGp:8B0BЈNF;ѐ'MJ[Ҙδ7N{ӠGMR{~tm8կ>u(X"з|d$SHɌCL0%06DlkDbHlj7YڊH37!dH|7y.&Lԙ&OSη2'(BGN߻ժ^] XZu-g`H׾n}p9(Sޡc'P9RAyCj#NA3DfrQ!#cP#& ?y%{`NhOp;~# ;OrOO|ہ{oz>?>򒯸^ ?˔H'`HDŽr=yqs'=F }1/Ҝ)`" ,^QRآ$OϿh  }:}'8Xx E}~#}ky  103 0c@ JV qJv l5H  |*{HVxXZp]ht{U}BtaEg8nWn`  P 8Xx؈8XX+P X) !o#؊8 oЈU@kp/ ĶG6rv Ė {rԈr S[_ ^|~6}4HWn P ѕ ِ9YyّىH0) :0294Y6y8H7;A=@Yq ٓɸ X ЈrXlT֍ Wɍ,|TxZx `t}xm\Ɔ˕}n|àXX0 ` З٘9Yyٙg@ px y|#Yyٛ nЗjqPpɗɗٗLٔ e0rp؝XٕVyMFPiapX툖`kcFS&p9XYhXfj &S||O  e  zڡ ":$Z&z(**o # z,:<ڣ>@) YI DjGKڤ N zy 5Xe3SYY֘ej{\hyٖn\W{J\f{{0Tzڨ:Zz {*ڪ T P{@zXű pP@Ϛ Zrlv|g֧z*SZC%:z zq#:[{۫ ʰ*M)kNK4!T"[*T#{(*,.02;4[6{8:<۳>@B;D[F{'K2ku1˴N L;j)e e X\ZI ooP$f{hjl۶npr;t[v{xz|۷~;[{*붋۶+UktN;N۹Nn0n@Dۺ;[{ۻ;[{țPPR!QK5[;Kн ;+; Y۾;[{ۿ<\| ,;| ڻD"<$\&|(*,.02<4\6|8:<>@B4^6>%MM`ΈL; CkBn| kW䊬䊼]qɕf~h>)l>f|r>t^v;^> ^E;=^0ߕM]-PMdNmk>ꦎowz>nԃjטܶ^Έ{@ݑ.e~^]N. ]  ~ pﱞ~mȘ߹Nˮl]LN>X^ç@~ )`a *,_@02p/?8_NN.ԻN= ~C?I_qO 0c."`Oïi t_v:y j?/A.QkkKF*BQ¶b_A!.|% qLg?ïH'l pȟ_|{~Aoj p\HB??/ٝ.m!1ô?ôAEh`"PB >?%^ĘQF=~)df -g` ȌW ٱN=wrvS(;Mc CТBE2:taNe7P3zGb+/;N0)=噘3'>q=h2`6BЄ'Dd (8ĉ g<',LԶ4!MmCbċXiMā qK+*֮6ü]DeZu8D+ҩpLDcؐ#+5(As @GuXeȧ@]crH])6 !ŧЊR!Ghhx494(#Gb3ԧ?Z%0@|.W푏KYl[i^29.+aj.[e]*oYW DZ%e) ߶@EKT,mRͪʳPU5{Z^,YX1lfLxxJ nSܐvoR?*Ӏ8](, nO Zlo#\D"#Yɨp26׹υVh@~Qwg-FuFEozb҈lۭN $hj %;`DaF (#PZj TQYaLz@]=U8ܻ cxZ {jϯKEJ7&#RXS2aO'tW?&0#UVʞ mc"=ՍT6Q+fvv;v8e`06nn+g#r]BНnEK6NKT8趡M4E4DmLGNHԧf"{;mRܴE?ӠAu&Phdl\T 90݀KE M-ծu1N=={՛ecr3hE ahQBeܵR(+b܂K'@K~Oyq^;9գr ֹ/,~mn;gNs?' ; j!#4@0d4";?k ACDDQcВJEJ44M|?iKІ|ȇ @S.dVtW\+18XEXW]E]T\` 6lC 5x=93?R9˒`EDU63% J;O`RB|RAPmN+RSETUUeVuWXYZ[\]^_eRURb5cEdUeefuUV:YjkmF-GHݭ TMPL=RKOQuWD:Wyz{|}~؀؁%؂5؃E؄U؅WWPye؈؉؊؋،X|uXi%T7lّ%YDM:V@XF$%IPr-O`R'T{מ Gڡ%ڢ5ڣEڤUڥeڦuڧڨکڪګڬڤڭ۰۱%۲5۳E۴=ڮ4,ٸ۹}MYEYt5 qX̙}lvFOYCEDՁɥʵ%5EU\%\`ؕ٥ڵu]dX Y%VnE}FpUJ ܪ?@>;zHAAvFvHIJKBbUCEOeUb PT !q޲05WtLL]A `0&fd.XΆdhfeNiglmnopq&r6sFtVgiFd 8Mxglf|f}f~f^&6vBd 准hF @^Pi8~V 0 ^J!eZ^MxLO(-6} VgF&6NfN\i{gjiNgFjVj6.bc 0F,`]ŶahZe)e TV k ,=iH (oL?nLaF! "8^C.04;hN"X3YNm͖٦ڶ&6fdP^d`l׮mYHm*ՆM,nmnmԾ nxm>oNnn^hS]s,OcI?r/'4Heqc+rbTWUgVwWu>gd3^Ņ `w b7*xY(i݊-Ehv0 fx"/..ONK0CG46z/tX7GWg7uZO[_A?(o3KhE'2JwQ;u[߄߈8< 7`YlR&kOb3pbJlq>N_Yly#@7{$z$hM{3(${LJȗɧʷѿE(E#a|߄wÏr$` 0o||?|{L?/~/|gw~7}ԗ|u"uP  #z'O/ [d Np+W H3zbg.w^cSÈ΀hDn1l#ȉZd.&? >_)HRd9JFԤGL)ԍRj*֬Yyd(G^Y%,Ue[-ܸr!\ (а/*׋ Ep&(QŎ'~CȢOv\-s$9uhfG)dv7‡/n8ʗ3oyo*q!YbL֯g_];lm*L~ӯo>? 8 u&{AXa|ݕ|Ue݄^!&w-"18#% l #ARJ3"dCQJ e N#$N ?ICXjIS#NQHj:TPN?if$hΙbQS&%CLSJɥ>IIR(F"z)M-E|%_e^>jUP:+j*kcZQm՘\z0)Afc,Ah&ealrqkڎcU7S.b%[3LS,nA// lt ='>? ٱ18OAzL@3|2)2-21<35|39K( M'H0=X{!"(?W l,rҘ8^}#<6m6q3쳐:"ãu0 $0@KS*^%H|xC II JɩI0yDIzm&8H ]& &MuRN9zP':LAx+nk=Hr^kPUS.h\ \X],t|Q[niR˨4\?k3iL^ r`q ֛5LdHsž= eC!:vTCi&s>\݀0h'T-'D/i{[1S M1fcG{A b HIR$-J.@*)j<Is;$Teȟ #,Tt*7mGISRwa@ IB(J m勠=.rOt+FCԽ.vr.x+񒷼=/zӫ^)r\@9mYISҖ43MsӞ^AԦ>}Uծ~5E߻-tn y`@0$o0ߴP1U"LROMc%dbtPVd_otU%o9!+Y߮2knJY.<- 1E1j$ dͲu=,:. q :mӼT4FIú>9Ѓ.tTh:A3NuHkbo3hnX_^:ؽK.x'> d&XO8H_cJd_\ֵ x{G}y^Nm{:wY5b_}#W,SO˺$rp3Yg$VWZrZx2 0'\|Y.w^~\.׽/sWa)d??ӯ?/ӿ?B  &. 6>ٚY (q]} ]QtIS\JPl[UA[( Nݩ %N[X>EQE դ $P'H![ >Lű `1 ̀Dd }mFhA\=jOIV<m1_Snab8Kp\e]"&fn(Z)BNӍ"))bB)H'f)",,"-*Xa`@ ~\@JVU1.#36UȞ3=3N# +\#6f5:5j7&桶;}Y"75m;<>=Ȝ&>"C).@$AA$B&B.$C6C>$DFDN$EVE^$Ff$A*?j$HH$II$J@rT Z7z)1@2 1LI[P#TdQRZωA.%TF8^b;.":[T?P-%]֥]%^,%_e$L\DXa&b^@OJ%c6c>&dFQcU9V.9YS9֖X%=Ab4̆p>%k&l&m֦m^ަn&NM. dp'qqjeV&\%dkqW~Ɯ.4Fȥ\F'kΚkmnv, ߶%R.V&2\jJ].v--f2#Ψ&ʪ\7\,fi"Fbլ-4H8,b./oJ,/>.ENt`n.f:SJ lDPCEȵXv )e'Z'&)ꮻ\.o.&dB&0':20:0BI/RfoUtr~Y,7d\l0n˪/f)۾0U"YF6 CEl@/?$(07-/D+W^0q{peF5|[l@b+o"`7180\'q p&` O2%Wr%7^,ek-2)gW%ٵ w\\. ۮln-n#青d\lm"/s,P 4M/f?Hr/*Q!ls%38?/EJ1E\\CM:9#8C@6P;;7'ƆAǞ8l7CK!1rYί.ǯ jygq"33KǦ3S'$?pZ0es t7 :3@3+AZDP45ZYSB[\7$6r\g#8➵Ҩ`FV7ʾOd@p-gFҐɬچz4.lHoC7,ba#s2mK@!Lƴ#6{3Ok6=DQtXBN AsT{sRN>kk?-'ֆr56BQ4uWuS74[o7wg+xxyCQA^^߭&F,)1cSAvŷ:6600G+[gh'xz@8#69+u;1UEOsnk3B-s;x:+ U:߳|s>8ĸ<N/'?!?+ ~ $}n3=W,#7o\sK^ ;|؇;X@#=?&݈ _uރ.@P`Wz(6pm-j+xX@2 %J#ǒ#5,SfM7GTg 6̨3g͞U65DH)dfպkW_;lYgѦUV*\e͐{G/nȕ낓?LXgA3ND!C\ _4ؒ^ϟA=tiӧQVukפOA3 7~8@M) V~ [ζ1>1ehvM.n}$?SW}{뷾?~}׿׳ CϿWA.H`^yv酙 1^s"I,M>1DLlaQiqQyGWEdg ϡD AWbrB)_tR-bhnR!Ʃ 碧>*"NJ >pphO. '|n³f:j3f΃<8 JϪ8OA UQzkLXm\x#̰f,*3 jYCCV0ZK[gViW60{LHr-Mk ]!qV.y Z̻NXO@x?rg@%B AfHa@0OKwI$d'I6HѢF)=3*RO\o<,SBu(rL>C=MA]EtL?^aa ~]iv.?`@>tPݛBC? D/ygߑdvqy'_'fr駕0iM\) %[ :̞&0%"z' &=)I5'mwI' d(#0J3$8-t!W ɭU֙s;Q4C$i.vsE.bK0mc4$d3c'5 fKҒG9Αuƾٌs H%QI-z* c6F3Ij$0T@H̭ SI9R7ʚ@QHʣ7A-qɖbErqV{xP4fhd3<mD)Nմ&{HA3"uLcy;0`65MH3=O}tQ&DQH~+e"1$iC X@B(K Rx ܠ=JhPĢ $FTZ撧=i.w^zY[aQT9LeSK͆IUU_M*H>ݜA+.xw̟u]4lD,#[uN$IJá_DtR_SJIN DNZ*v T)B*ZM<3PbL=~[VqA*iTR"*ʜq9 *V]GխWg <3#+zִzH%+;ÔlDC d&м{OHD)~c?J֦I 5k |dg1m̈́>m(#ߤQH6J钜-Nyc,fXd!ymn1L&u]+Ƽ)kzl<QAf15+Мf5g^Xc DMGx68*)G*ђ%&AR[oΘg>gƸ1iVAjQԥ6QjUխvakYϚֵqj&ʽvSͦ5ee/[Ѡ61?vhBemyVDE"җDh&@cO55{( I5 GMi-sp/ w!qOj1qk4t E8;4`sڶqsq\%&ўv$Yhg;ޮv=ENr *ˡs/{QB@dRˠt v!%ʊ^!~F =nfO!a…}L#q'_BWNw!>cddK%1 BXj+yЂR+ 4;Ioe(jI3oH(-0稯NlBp",@<mjXJh b>Lmh/K Ictbi.p +5P8M(.K2p<WIGmQMMHK. pȐ YW)PlAA # pI pn#ÔO>ID'2mTbLJB)Q+1PI P05QCɱQhP1F°OOUoܰR &'>i_k1h+!q1"Dž"G"QG"5rQ0M$QF1K4$Z%cR @:p[$6qTPoʭon)Ƅo(;j!!RCA+vE3B,b6R+N12+  ,r .-"W b/1 :!+R` A' -1aW(c0-1r+r+R`/S31^1/52LNE3.6"7bWP388;s39S87k9g#Y.;ۣs;;p%uB8 ȳ8Bs&1QʰRXl-DRѴ@ .#ԄV +)Tr+T\TdS:+2tCf-_DRE9C94D 0cTD54174+FG2x5Q/YC#Hx4HO5465}\E=E0U@Z`+X6[H5-HA+f6o :LYh9MH/T1=OtOsM[HP; 4SS$pQ!5R VUpkHb@ׯlڏW=S j/X`E!`8v`F6GV6ǖ_]es+Km_ɔLt-( N5GUDa4kTJ lV.!.^lUO+T6>Vq4/rC552CwFt5.9,R4xA]ueesUheud; #w7x5Z6 {YKtPiamq$6`F]HGGk],\ެC;k}u>{qv-i.8 iyQmU~EeABmxwݾZ>To2@t+]¹d%~X/1qP>9S؞S>?TB_o;s]G#iQ+vbn ?ki5oń;;ž,F-S+}~Qd?_/dܬ=s3hKO?U? <0… :|ĉTdA1ƍ;z2S"K#i2@*lIp̙4kڼ3Ν<{ 4СDRE=~)rɒ'K(Zx e 6رd˚=6ڵlۺ)jtڽ7޺*ko߾.:dKذ J(\`pp>b&]iԩUuW`H QqQDZ F'0A5|W5ބsU\YpxW8xwh"]LlzS u_qBIdF tEG.dNғE)ATyeKne7SNA%UݷUW^fn g<8Qvț#^ۀ b6^ Ww?#]Mmf2UJj%ij*dNJ*ZJ9gRUJl,tJhXܶa֨Uei5V?N[3|WNWދooG $Pl *|ewfI_q,~̗_]|؋ZYXM)|ʫn3uilhe]tFtRj0U3yuJYsqm2 ,~jzvj-g M&N\}\b"ycmaLgN{nofF-o}%3>mӫf4/^W7]KN~yn~CNZ;<[O?YVhjçeo"CZ w]hz>щ Ń]+skaP~*pl.<4R^A>X$&K|T;ӸzvYY&<JuVDEƄPԗ9]'Pb9l2`q$sF$ǁz$ ` I 9C&Ғ,&YH إ&1D"h@0Er.D*/IFđ|etiM4?`9Cu!1-yYŜ&p MK0.P@@|&7fd+WR$u8= 6LP!J'N'6_ElAP1vzG \b@a4|8c2;étK>TÜQ7UЉT9yNh3%NY^ҧ0STNR4f0TP6YDRPSz k6iH5XJtxMeϫjiNSD88**!AޓH dy)=$"gBjP 1v5"hON. u FD\-*zW4G} =fhmLJf76E,K/m$=!]j>@LAbV[A,4ɛտvrۃ*T㌍rȲ Of5cw^x 6^Ȁ{49*(85U8 cYu5isŀ1J!jV`z bHB<8k&_E:>x?݂;釶9t6HNk7?~֒ d~BrpoM+ ̳?HGwQoXӟ6X0WA~y);ʣAqXvvAyӹ;ʤ< ɢ[*ʥ_./lףqk(gʦm?*AJwzLzABOZee8wiff-z>W$*A70 mn54D<ʦp~rJ4" zxڇZF{ZTUF"%j] ^ 0bz/!k8ʆ ;Jd'!~ʉ"IZQÝe.YfHE2㦨+tڨ Uf$ҬV 9݉zɪYvGԏ%c# nz"mg IR!+#K%k')+1ѯ/Kz9F'_ə࣫xQ dҭ 3\!)=p隫RRLjY˟rZéCm:i{~7Z9)m`4 RHK#CJy+>'*][$`hrk~; (G!i } &4Z ڠԩ_V벙*k*ǛmlPqBK3P RZjB:-D("z+,ڻ ȫ[6˾cD[Ϋ!Xmky,{ws@(x[ L[ܕ;EdU:kGի 3![M I7l\cEO; JR|8xc  )c(B4lÒe\<,tNJfjĹ3ZwJolpZogoz 42Kw-3+ <ƿ xXy5n}K`)OKL{gǔʡʣ̖=l:@|C1;˷|;y 2A3;[ZY- hi<[*4L/ŀWͤY5/g֗SV ͫ|U I%F6ڎL;;{ڽtv\\Ÿ- ^ dvҸёX5v"N V(ATHhҺ`4EQ=˹a&Ӓ (lЀZwӋŁeѠ U/9svlTKWY]BU_R֘T VmI{H׭h)嬬>-; ¼K"ه);)EFJ=#BYMȠj YsMlYh\yzIxJu$ a*HιHDl0Q  ]P-%~0K (wgwλ!M A)IR6b{ ȡIͱ>vs]>y]wjܯIxtX5 -}6}Md ߯*Ӵ#F㪪ԥє,uߩ -]*Wd=/]^^~[1#Qѭq&ܭww!\M 2/+,8kHtazCo##*ƅeT,.Qz؃CHn0,/N/\ἮlQQ0/olyҋ.ɓ[=nMAN/zZđ..ߚ5:- -u[+[!3nI7)贏-z̓Pw]d_g~g (KA*Dذ@A aCj,*;"D!4L4PStM8sN:NO@tPB 5PDoFFu03۬BS[QN;SPCuϒ^bLpJ< U8Zک'g O(vJLYhkMiZlQVH=4K1)MQv]vuwKeWzhUO֡3Uf\;>dmטd=bY]vm38Zj7cCy[xK69IAtDL=1-cyfkzs8f2J(:j֎tm ${)aZ{ؽg$i{=㑻{l6++sMTmQB9+_cb2` p:Pa~ngڡñNfO;{tҧ tSW}uvE]n~vsם6o/ ~?u9J;휼 W<ʥ. |:s?‹/ktW}}bWmskW~}xgY)h@!9zx5&BF}#HxBPlc!.#e$ZxC0^8ߩ}G@xd`&(@,sDs"}9ȧB0Ȅa$c͈&0s[Z&QsC)PW"vD1!8rA*D$$ {Vs G&Q2 6IPBuT#eH;8ڐde+gsGЁo|ҔhDZT&| 5?70)bjUH; ;;8*L}R(){Q5Fay&<~Q<^W]wj(N&VVV|0gXK耮&HIHtQ9[JTNmm5Xv*n}[eձ,$̒IJ^f{R%he,GR +ykj[v%oƀK7ݢ2=o{-7a"=ty*}2ɘZ !3"#o]](B.uqpޚ*=FW o&KYR $f룴V9h ]U~e|d8fثd(GYC"΂7,nt[E9B1^FӝCJDmAaEҗxW?Hc|g<{Erjڸ[{&tkCwby.)y:RaaqȬ{nq\ \2>;Zիdrճuk-_E7A( mgQO 8Ar .sۦs~ɶv V^%qwR.@lcAv-VcnF RÖ۪Ns ּu-~[7>xr">z[;#dgOz^%\gxi~<_StouYgܱAϴ7Q2yO;i'=>O[Y?V0?v o]͏TÎP}~ 4~N:+3û퓞xpp?;?+ Or@ d3B @?<ʼe;H{=S.)%Sڛ\ Al L@ ,Brʼ#v""̷, zp=*CAkY<3L1BӨ86CJ7uv'&4$jaS*̙њ`f@D0 Ci@5E; FH/̷E|_4bڲTtqFcB//}L+93uI|H$zܐw4;3ƊHױGAj-)b=ʼn?E7rDDXܒ\& 1kȉtIL J:v󑅴4~ť 0|=oH0TJ)Ý K||\KȾ*]1[ZڥmȈPE†Y|ɈA/B_*3,KlLaHMLl%VL+Gd+4쎀ˋ1!X\&AKLǴ ƜMd ͼ!ʢ?4@"2Gc8N|C^ ͽ@l6\T[N <,Lϝ:N/K_kҬj͂*̬CL ON]PPOH)=tP ˤT\1)嬷i4Oz΋N|ePPPQMyQT GLϤ' u!=hHXiQER-. ~Ҭt,9ӬžRERR>$/(1-6*$eE%Q+@dAf{<#*S@-  UR.'3TU  PXYu2 PjA|TO) T2+; Gr,ShV=T]UmD% ZWݎ /]MH%.K(+1 y6+sI%8ʪYVtFdRsHjQ]X-=k-lVn%WՌ XX\w9XJ2I8T7MкSE%uثhXQ?#qӊmZXsmX\Z <6)px6bJ 0TMYUҢu(i[5UkEpMȄZ 0@\,مגΆPW#\ 3Vk[bFͽ]][I)f MPcb.29))`Ev]Fnd|]ZBdJdy:˒Q#E^R[8e[vb^3A⯌՝eZ^G[Vxd]J#_vlްNܴ} =?cWg7r9ʊik>lnunnoc\MbfY1- }x\-MF<{&2}~\܀&܁pVQffNdcvfQd ϼOUk菮Đ6hqՒxfKZae{nf1 iOv.̥.jZ&ꢎģf7$fjI⑽jah(6R QƑRՄg[eNSnd~4H庶kSkkVSj>Yefl-k9-6^glA_l=q]kcsCٮܚ%G|Ly&ޏT%nu:=Ϫ;Ea'd^X\JQ*63KN[n mn^Տ5bv>W72g?a.CYu)oW1Wgʕ=It6rK ftSRoSOjWAdbyLNuTt#`vOjGDvUeOf@ r&~%Np'A y<.v&e6Y v;~xQ_qRz؅dx^{`q^{9m{Ng*}^n||wř瀏5讆mFGY:|Y-}6ԿxOO*U|qʝ{^)Ms,:OzvudM*sռ~?i~( P`!0p Bpp  *t(ѢF"MtiΙNgb*u*ժVbͪu+׮^7c,ٲfϢMv-۶n+w.ݺpeq?9dɓ%ODlSYvC,y2ʖ/cάy3Ξ:r FN { V 'W]Ao $(Qʔ{ U4͜M(o3G~ز_B=iͰÏ/'b*Qϯ?Xdxŗ_ FacN9fbrءuTj ht'ĚkTy5GPjƅp‰@!ym(Q@c3%twՈJ9dDA'Pr٥]wߗcYgIk&Z_ V.֘{٧h[!:QiU@kP'%.4cm17I:ddJEnԑrt'i6dyBYeeګ{K ٠wRQSR[mδjZ;Zj8nܬű*i(uuQt>G)c+# e+'u>xBsܱUrAv;SVy%8PϝL\4q%H5{REۼn2%ưKd0OC~\5/H6+Vc -",Pi̭@l46Μ.Ш6FG|ﺞr[DONK^c0ٛ_us}ל^[fz۩ )ht73zr9 L?gVtB]R>c0g[3+:ܓ_۫Pi 밿Nn5M4Bm$ v&/A#x?я\KZ*Y0 A%NYSV $}0*\B &{€ tJAEPQ"T5\K`o"W0/1Wa!=-b^_7j(}lF 9Lb$ d$@UA"OR9gHŁosҺ&OJŋ%)K8$ QW2$\ξi.K$AآSE%i=ikE&7-(Ktk}iss-|rpswX;PnHfG<)${]YXjףAԚJ%Q׿ꪥhTsr 6 gm4^, [yj{*:\()4jD ƾ6bFv-o?Fq \,&xNrj mLiЪh\G#14z6Tck{fEؚ7}Oov[Vz/}C!Jȃau"fdS9tUQ4hx_kc#-vDKlbcg|ØMpMSM]ϊ\Q%ZyVѵR/PH!MNT.+l+{:Z`jmk?v_@V.@I_;L^k-mdjD ׄik*?r8ӋUz '+uBӐ(RRwj=(KSܙңzq?Qjyӫ}$X[ d',%?V 2l_tvƶGћNn~8C|YOY$%XM}w1HˡGSs|@t)[I`rPmH=a`Y4;Uܹ_P%E\^[䛃%QIBN arbI!a*y@߽߷iܓ]-/S TuID2!P>>Y bYAaԸE֛!u!'sN1I5ú"E!!&z(ab](9A!i_TZ"Bq]aD܇T \؟j'I'c22)z(vM)2c4Q*!^"Y!)"-U#\D3.NWh]0b"12 2<4n3r=#Q#Y#t$~a7.q#D@9*9RbA4C#=b>!HV=` ,jcY5 ~B.c9rǁ0b$ڜGR"RFMI^|1SR%p$۫!Lŕ%BIIÎAdB5006#SGe]vIUTM%^%\ Ə$Wx$7AD٤@43WZE]]h_f^.5ifJd6fO&fHG!E& fYf/Nds?`٦Q&fsB'|&]$4Nu~ Jfaݥ~ܺX_*Nn(L+gQJƪ&,R 2TҬfD,hf%DdҔ ,A)d{\ʧm mKb,jEJlX^2ܹl׆$^ap i@&OPc8,.bӦJDm^zႌyUT"ȍ V Dm oZD#\2ӇiE%MWʲOnBfmjʨōV:*.PbA͒m>"<ݫw.%B/6>&R/ hjh(2[,nnNo/!e b6C'D0Y+&I͟ D|r_[o 6zoY<0p/*l,nt@ Z1 l/p 0 c1p,pnNmkrʫ$ҫ3̩m/ۯ///[no1oRv1nmÊq"n &wф#Ґf{ܟqʕ@0 G ֪&+ A.1IFN(Ur* 33=2* 2_>2-O1RwT.Z&gt2]lJ/)3߄3ó2FsWse3ԅ3FJn-brˌ؝BH^1+v+ c<ϳ13:sV=rd:$^l8i8#4K$sd vK|2^lfFf4Fg'nt ">5F<@uTCuHuUӃ@UKSp\xkKsyxGul5Azwoөqx]0ӸlxTS@Gdy@ FC Dxy5/yi<9@j7^OzwBzW6z;Cv{_yl5B, 4̙GG K_enkN6Ĕzez{D;/6KC,@<# O;g KGZ{bcw8zWyvzɟɟ{6TdC ˣ|{Η7Y|@?gGjH+U}w=_}ࣻ ģK:ڳ+:(}ֽs˹ޏ)ߧƧ?cÕ W|tCD{ >v~Qji#;|8;6?ȳ{Tz/ģ%B `%xp *xcF9v$3yeJ+YtfL3iִygN(E)kgPC5ziRK6u SVzkV[vlXc~ :zR%O;>ep` 6|qbŋ7*Z˕ lP2_PAe Ykٳi׶]'Iy]*@7~yr˙wztϦ]mܹuλgɗ7}zBd̚?+\asЙCsV!R[3\k%dJ8& 5ܐC N-܂K.N/D|er+:O2Ѣ X^,ؖ|(-z*+ܒ.0NN |8sNE8o2 ##TRJٚLFoH%=*I-L5}N=-RnE6TU]V8 7W awKdݗ~ۀɓQ55[^ W\vs]h!32Rw=PޏEfMPߓU^K~1EVM݄u~XǍPgڰ'y褗׊d ӕHO$j꯷ȬN]@vnī式KYoElFuNX铸hlh?I][!W&B]Swh"؏}-}wf eO=v*)Bߞ +MTlo?Ɂ͑5l. iFnKH֐^dy$A6k`AH C2 k71L'>|yC´cS0""-s.?11H"I24SY43).F9:8 I NGTE?ϥ_v9 Ӟ<"Q)ԟ>UDŽ:U^J]X4/*)RaV%w x $!JքJlLÜS$%d߽n`e'=v ,c [I/% Y~BcWՌuG-Q,8mR m/r*W[k&=Q Ӛ+PX1kӪ st]J,hYQHCjuX'9J#iI5'3o \`̷UE{5`?D H7հl`~ !1M *OT-Y<mr3X~3aӦ#fucuhWڻ|AV MINWPj|c+&?.e3M'(\f3EQ4eUq޼/.=|C8a{G$H>;Ҍ_9?z#Yγvꍑv ;FVtRoW .xOkz:;ww_K? wyLʇ^oG~Ó|S,zs?yfHUz_Bo`+| _wɉ>fz-V}]^|Mfnn7),$Υ U.m NK0.Fʏ8Q'` "F|"AƢa?0J&M0&Pp'^Tj g'`GfppTr"Av눦a>ghA x$"V,kiF"Jఄ* ]" k 0"".!#I 7 ,Ri< khN #˸J靨!D!2Bv|!w+1k G@]2LGw\r+Q)&%8*2|Q'3ΊPCz- QaNj2'Q -WZ'ux41x !.l !B"" {'!t!"$$O$qT%G@@H0qQ ?ɭAaE s+G Q7RR!)$!4 R+ 2*)uF$M%IR%YR^.nbԪRzD h&(Cƀ( xQp)#@2i 223732%w -IR-rR sn:/.c31pDg&a"!iӭ0100j D@Q+q!}Q"]Hws+9R:4P5u"5ӓY:-e>& ͱOND*7mP!pV0a4~a0 3B,`B9U#SF 2x*yx;-Cs#h<=[Fm= gٖP皰>s/r&C!t~t\T#x;SiD C/4lPt2YCr+lPDuvZ c&MKpF+OuO-FF-'J/ " 1s2IӞk0BwK'BRRFv2zT$3NeNS>͏4Og+b?mR#z2No)}W4qUYU\V [VFo>7VcU>v2t!iE?E͸VVdZ_fWOfaYfi`-*4N\|"FVP4tvuiKE6NYoY]ξX\H.Hk @"?llViF_GYj[\.PV75pE W% squޖq+qg%eaLe37Q6=s.tfKt\oa;bGXVkQXvvwsvN{w4?q?%)0g6v{mvJWzgz1-wVX:̗elw}_}i6cOWWWw/cz>.VvՀVie3G p||/xA7̓jC.%.pUXJX]-ti86m8Ķtv3f}-%87h8JxX-Gwx?xb_-n%p8I/- Ex.Opј|-y6 *:O)wsw),yq1=u(AQ]cQS?lETQOL瘕9p& .85[c<$zq1XLnjxИY˒y uO2*$2ih0iR*/06򗕋 ̆]R4" T"mӈQY}LЎXrsf Z rs*R!GM\vʺ !Zx 09:9գ?ZBG9RΈ\}7#s4)t3pv k,z"+庠&K)hKYzZEתxDxMzx001"f>Yɹ.s:}`4!ڹ2sׯʸ5y=7= "P"@Q14g:ິ{ M{RD-b7al%lu]Q/tT?G KiJ HKQIt{B![s̻ ۬j󒶔aAzyPGF/ rͦ!Nr uRƏD9U'*½1\+{Qؑ?p\wȉd=5q묬nɖ2I&Yʭ{'[\ܔӖ߼q;C+Su_p% T?!sѭ˱z~0=+i`A F?n}~r]o7{%؏=6Dٓ؝ءؙ٩=ڭ}ڕ=d8:8}e]ogK ]q]{=]0[}]"~ Z >4"{]֫c<P6^6!#<"*>@^24@^H`W#f#@-"L^!|"9]p,>ZNgցc=oSa~[#2O !~V?!m-$C^^|^^6^ >"꯾,55P!/A~^ad~#!$#>5)B^o5?_="X_s#<)_/On^q_#P>g~3?$My3_mx[k͟#,I>6 2x@gB3 C 4HpQ q"DA~hP SV\SɜI͛8sɳϟ@ JQ.uӧPJJիXjoׯ`ÊKٳhӪ]˶۷pRE=~)rɒ'K ~ *^̸ǐ#KL˘3%(Yr{ zTȈa(QH* p fΦ=t5jy5n{`]$̵Lӫ_Ͼ{˟Oܺw700X}h& řR+)BhUXi]qGvtTAMpepDž\s>Rv#x݆nGL)XgH&L6dPF)Xم^|vXRM)dih`R =iiw!v!FZl q p ESJXx.鐎rХv*ꨤiXaߖ\倪j뭸.EԀ4ii/)ёbB Mç$l!܌{оQu㦦.U+kN/W\Rl'l_g A ;l5YqE$г8>43 newqEeБ[)Ek3ŋ<3| =&e_ L7ӨJCfuH^ǔJ[4.tmǶM˭lt0_ߣ n8P'^ Ѯ*.WZg>'-K`'mt?g6B P 3n];O.aJ3w`G.k1ѱB4G/k5m{gZ*ExFsJrH;L!] yL+MXK<€\RlI m {AへKalT7qd?^wC0d HLT= !V`R uUdj(EOv'){HG,Bt\x;񏀄L'o= m,^4C P"d Gtȼd7P HJıL%<2πJ#+gIZRaU.gFHqn:<%egF2! lB ƹ5s#N&srpTSr$-: 9,k+i@(!ⰈDB`9eD" "y!r?ycc+3_s]ӓNTz I=XhC|:DҖ4<+"ϕ|b u,74X*4ZJ4h:gtfTQmL*j"GJ꥓ֲ+'ctpM%V{j b W& QfTDK _3*I(8jDWB堑"F9QՆchG+BM*[M"lê>׼fnYѮVō1&d1kULf~+*\x -v]iݣjY7UM%V'|&[_j aI PMe eT1 Ir/S+ [x*MXxa9f Rz1׬5y/mjӾƺ ZvOe1Vdda(誮^hL.|? 3PJ swXβF7g׻BrQi-b94H8Ip5eI7'ЈsUetѐe\ OSr0"F( lAF瓑z)oVf g]ɒUVv -m{f7@>=ӮEhRv>ӵƃ N4^CVEE2L^ɠm^Mv-b7ˈm0Pxf-hh!V_Qt{1Yl3qO晽SrLV_N[}W7kϭkd]Yoȸtu+2kVzGk.w\ow<GP\02X=/d\:JؤZ9 v;>dLϾ^+&Ѓ+t[\|¡{rn:zjJ'u4~?wOS 9!y KCzzͨ*g؛J sDk%O~M6;)w?Bܞ.=O>?w `nwR}'*Wx?eއRzaRe7ysakptA L|7-$dB,.w52uTG )X8x8X4fl;yg)u!\ŗj8Fwt„kBa>gf$(J#rbX?r ` ]׀JVBDEf#ԅ/v4:UP%PoC|Ѵ1(1UgAB6ԠR҃3'H1Um2O{$H''6'cXNu,(oÄE\mIȈ4(B3PȆ~6~wԉ,QSn˧A72ÕLhTUUe/d$x(*8 8@SKh=dA؍ykb\:wh$}_⑎yLҎ%x{ Duhmtd)' YIac>q3z'H 1e我z>#p H{~ ٔ05W,0GHtvqXX`>F,QzB8Ea(ap9롑^q ґL| ="eSDUH6g""ґP͠1dYjH#Ʌjztrٙ]D)x z}r!!g75Xv!#b\"MWmxLڦUٜYa^ɀ})%^{ڙ8YO08`(9Y9 9IgB9[XǙ̹)T0r4x˥}hٞ"xv%ׂ]s9Y(j@a2aPiҸ XޠM  a2zn7I:yBwVqP:?^`Iyx3TV=`4}jʊp"0E" k\eT#raH :\KpԐYz 0a`&#inӤ56> -0?pHqxJqŧiI@!2юK 0[oګ{{ L:TjlJ7J!vJmՐ&X*j EEnxo085hW_"̀_<2YF)h$?ѭ Kh j'Ն'~ٮK&+(6HntI ѕۈFIfjXKzz&x{)r (30 媥犱(sرN;%d8pZ˅T͠C:F fa"R5+>=ix0 3p骱~K{*!SKz<ڄ*)#_+M䦙IZ$ۖ=)C뜬 `ɫZn,jY) c#Jn8ۄ$mj궝[{4 < {xF0[Xjj[ Я`6HAfc%۶O;Kۼ+# ö\lCi۾녺;{{0&<z5X FTf(P;S][8 #P F|"l7y<pj+TdfhLfa5jv9kKue.z;/YG҈CyL6M"Β͓Yk4&Ɗsџ=u̻bRU\ҏm:%XΑr˹ g]7!ƷtU$޶2 ؃Tމd؇M'qbLK2AK}[N̽|Ϝ^VipStB]!3=lJm2)Pܲz2tS2.K^@ޗ0ׁiT9m6-& e2;N-?Nf>C~zLi-䪜! ]"F\q X(ijMYcH]j苑ᚑғi>N?t(egf!dOC} xrM!E`g]`ᩪ)=LjN~%nN|S=Xi$f@ - !ЪEw NY]ac^>nxRW[-Oo6>g~,rޣ>MYr_NԆl:"R^b!Q\v]=EA&bd>8B|^a8W<<;_bFpm1/1r6m~!9MȢa, Qg*:k6d85Ϸ_z~O,'1of>0rO_@^)e] Ϥco^:3:b,M ~uXۄ@ e'U߻On[_n,_qn+- P![yu]T @"(o2)՘Mod *LcB7[Ȍ `-/n9SęSN=}TPEETRf<UTU^ŚUV]~VXe͞EVZmݾW.VYhǏ E YdL…i"C6ӹ?Ydʕ-e8A  lZbzCExr6gJTc;c?ncyI(aLݒkk2Ş]vݽWx͟G^z׽wo߿6\3b0@-ˬ0DФNȥFKp7 fn{&x"`%+:棐7 ON"l/GwGo@!$H#D2IK/L0CL1‚T2K-K $F1;h.hb.6i^D'$f@` Rd$=9jMB4RI'% K//4SM7S4UUWe-0g3V4-!E͉q&9EN;|(`,cAئ<]495bTLG)6[mV7\q%KJJ5ʙ-7^y%U*d#3a$Xu}(fl+!:؅}O?7qYBʍmakc?9'x%dOF2P/]*FNfoV^|eշV~@׃ ٘1>6Q2.kCkyg&WNw%Yd߆;ty̔8~]kkل8iD}i`/Ur/G*l7sϗ<7ԖcJ?G=p鮻ƻA!hj?j؜.hZii9ƼyIsէz1 eu+=ӯ?#Yo=OiGgjm ل8[ק7@NJfS@nmrf*yWOoKSjw^6Vd8PcĎ? CI`8D"끣#n" щO9oVK p;`p7Xdap}ad XA!F=cs*v5d tT1 Hhf"5 \"pwdF8!* IR}f8KZ##uK^6j ^SR|h>I^Q5{o7hBb(١ScW8QOu kNv4f<9϶2 "3[0F5Bm.81yaxcq26:Avv"?E:RVŞgYRNϟھ+OBÝB.Eu^DT>!c8QeK:U!4T>U k*ћ.:Z&09'7 H=ReT:Pj`[DrJ`3~8f @+F@ǔyFF ѵU+ յ{j";[ں4{i'̲v^ujYj0ABmNq̂Q`+FV @\ʼntq/̚/1%LR*T pA A%TXnD#mH4#kSOk%O: UTV-9h*UBR UEF ԋUES$?d;oȦqNef=g~-iW pB0/# ,S_I%6 J#ӮD}`̀%ؒ'UTnVX-Cˍ؍(,IC$YeREZiNLZyS ` @% .ETxTV1R]W2qkSol Z5Z}ڷE^nkR [Yi=W JDPR 0$Q|%Z}7~MͭsZ%3R_ ;Y[w܉8đS=Hʅ7u cRw!WA1:\7+[= W;]Q=^ \;QuE]*B]5hhM u 6BfAþ8F `]OލPf0zkR^=Cܠy^:ԗ_J nD e`EgbH4jnNk_l63mgfOO܀vr&s! }g ItLi齼fϘ`VZF蒖dJ[Pf\_cLvsL*lh6б.BWe|ivhށV=h`1e8aN$iAh+ZgPlhc~hɉ9t2nMl~l^o=ok,paOUnw9ޫ(n0Eog*_=pj.qjo{ spNܖ,А6/n^qDY0#G$W%g&w'()*+,-./01'273G4r KQ6onFp^0MPr 2XIIULMNOPQ'R7SGTWUgVwWXYZ[\uVJuI`sm{ns=D tjtCWf œiG 2 r7rsWugvwwxyz{|}~'7GOw`b/:;Kqle/gl/OHFp wwyV'7GWgwozGnx}p ~vuZ+@NK]ooW< 2[{`'7GWgwLJȗɧʷ|Vc׺d'fffG+nZ CgD? 8 x * :zp.xOu!!8"%x")g@I"=8oEk gA PBs22#A(p\,܍Y[1DIމ9&eyfLCmr^m qy'y'}' :(z(*(:(J:)Zuq.v!`I+z**zX?y9sh#k 6kBBۑFpFZ5TCܖEPU\CFT-p D]h;.嚻ҨyQELEʺ{/// <0|0 +0 ;0K<1+Eڜ]kUM8< RO:ɑкyF2j5].^E1ع(CE"6m6q=7u}7y7}7 >8~8+8にvgr*k9{9,S218sD/&QC|{PM8osNU^If5;5AR=G2={=?>>髿>>????k=#XCI@2ܜH2VS3Z:XOղdw8~QfՖY-y6!= a >!V0F<"%2N|"()RV"-r^"(1C,bPT|#(9z4QWgYA:8C؁fQ!; «nlҩa3Md?YB)Q>a %)SU|%,c)YҲ%.s]򲗾%0)a<&0MJV.azic(iRpi R"alA;Lv^T#BJ GKHB^z cIN򳟜Hx2=(BЅ2}(D#Ł.љ{Aƨi͍re6m>Zc7AM5g",ArZ1p10ڧ?*ԢF=*Rԥ2N}*T*թRV*VխrՀ?*ֱutHGj]pKRHX٤%$c;i4%' m9@dHԡ2*jW#+R,f3rYC+ђ0!M(Hmt#xM3\7N ѫKsך3<yb}.t+Rֽ.v rޭiQ;Ҝ&4F2qζ,iN"g&M{rs,`@6>03v+ SsnOs<7YA,ږ6]!Uy=_o%w6q>1,dfF>2_ua VUkp.J]gw%b XψeW451|v3=C"K2-h-2QVD`oAީO㲮^(̇KV، m͛әϮ~5c-Yg6ƒ5sBhF[}Hr IL:4@5M6UD\Ixގ3dK \>7ӭu~7Rк7mk] {Wq lDa`]C$55`X7z#8F D6PAl9c @6~#`d6c5^eTy >%=N^ $7bA&O9:LApH8dd#PA<*FV#Av6~dmbB(JdPp$B Dp$^LK$CVCZ@CLMDNEbdDN)6S *FAE̠@(-" Ď[D!i cTα!"XB#]4@:c ` e @7 `&_@=%`(&>#;5%`Z&_Z.>EDR$ `$P|&#HF&fF5$iel$Pd&inH].Cq'r&r.'s6s>'tFtN'ug-d^`Pr$kfA6PjPvh¦HyfxҤylZS>%}j"V` jBkb2@KIZcΤ$3"\%]#F&fe6f_h`e`~(zDB_ddBA@rBryF>ygCP$|&)z*)QNii$^$mi.)|)))))Ʃ)֩))BxeP)N>0@NB|imjD& 8\N}^*'Z .eK% WZP[Jh2& :c檙l茆8ch`;a>;@#&cb58h~ChZzO E&i*NBLh1df@.B( ,,&.,6>,FN,V^,fn,v,djj&$"k.)?iJdsiTRFT "VjC( ` :;HЫ2f݄ڪ\⪮mse$6询546c#<~c 6@5Ȟ^mRc(A@ɖfm,5:iGMjkΤM*{5h6K*.6IB),.붮.Ʈ.֮.../.FnP`l>niN2nnVg$|,amZi7U\9mEZ֊>GBX<]U](u5 +#?F7.0J&C&hZ^kh9 D6.|+A@+" +mBr s^b G*\@gu11'"i. /iA(pE6 /$ZR jH1F m/(-*lQ; ɖ|mN}DF%* "((6p;rcF7nnV($j`حcB.*!++%Dq>q 2&pJ,k}v$228o2/lFr7*0mRj 7{gF85RFLm0W`N"3O8"P-f#T@Krr.0e`@C#C[#@t 8 hC*+{&Ljo:B-C1zlnJi7&tlBytJ @6E&Ԃ'&3QtDNjc35tkb5G$MôLON dO}Wo8Qh>5h ]6|6GF$is?u'Om8j5c?t@,p7 %86`c:dGa8(t)lLfRrH@OBngkvkEhdmPE)G<*[QwjgO"viwq_#vlL':.hFB%ˤȒq75xlXKX-A);7.#]߆]Ɓ"5hxxhY)Ԃ*/,7q?8/7xZ~Kl/ IZ6 }smܷyP"󷋧.H׸l8qy}^ecsa(;=}q诊?%bxhy9ń 9 yJG}@G5rTRR/#GFq^{ؑ]@BO:C9ݛ@Ɯ½ȝoDyh- /_1>ˢ/zȕS*8x:g:ۦkY: KGÞ z] ۭs+z;t; {;wz _D ZY9KD/˖S{?/<7vG|Zڧ.;Sk!#+÷˿eϼQ|!JqYZ_k'5ü?=O<Ηy+Y{ Ag?kwwx=:کs o(| CFlD~>~W?]?x{?@8`A&TaC!F8bEʢqcA9dI<*׫ʒ(]Yg&K+Sd%$y#+5-j8= )T>oWM%>#3XmUݭ ^7Nrg?~}Njt P ,LP ;-0TM ) 1P ڍ#@$+&CJf)I2 9{)Dl1p:8+o:(/, #k'Rʺc+R-/8,3LS5TÎ3$Tb)&3ϣqf')"*٫&j$;#}P%RQI-Է09L GU[ [qU]yu1!lSa-c} 9ΕJQiTPK? E*9[ڑR%/ Sw[PO{+UЀq0հ5&3}MXnD&1Xkg,=ڑ%GnlIq5ꂲPB[u|Zh{%`@#G.C03⩩꫱.؍([l XN3ihjfœ6Tf8sChMq8y%ܹN\+z0i 0ߏ,Yd`:Z]u7B+OUqi߁^x뱑O^ϨcDpF&gveSfк?{r]z<=C鯟.#8M@V%kT @~ H @A ndc0AEr#PB*Cΐj*B$Ԉ+PMj{ $yZdK]@HCQ4uF~釿M# XQu`>5Ip$x5xW!4!üt#!i=:$Cg*"Pw$:ndI7&:z yrl7]-q/1&HYtcxL<hw5L1%MEnIqt(KB+) ؔObjes#g'I)(v)FВK.^|5:VhT?8Q1`d5i$IRW 9aSp:22MQ{g(_9Iq*$(|2婃R! UPt#(؟7rLm| jcxLUdEYCT+ J 5a?ҙ.XMmڷɞC-4=#)|DggWIO%ɠͲ%Va۾8t Pc\*ʌq*𖚭e=H9hu](ֱwB%8'QVhĉ7ڒ T9_ڋ*,ke`š5`q vo#񾤼E fi^%nEbeJt2*wMgEh|cǥ qc-1=)" g+q} ӧ(; < f!/*7+, y5ќf5@v< YDJ :O$A(Ƿ7H$U-KI,A#U%cl5oӝv% řԥv|pyN: Ъ=0kď'M)H! -wasϜ5qs=ρtE7ёt/M9Ug^S Q{SFݚ2ɢxbunxIw\( w}x7x/w!yO1yoD!A LV7鯎NlNsĨ7 W8~nِXbI17,w}Oշ}o~7џ~w!zLNgCE @[Z^(MN)V *Mߌ/DA105p9=A0EpI0AFoboYbo.@bh/$Ŵo,D,)>d#n'toe/$ p 0 p ɰ 'Ljo$J&$.E"]y/fF(. p^ QD0D! p!1%q Sa 5q+ +&BP$ڰY<';b FbP D 1 )}1q,1 Uqs#+&.@pL&=&+u1K1qI Gqab0@F$ %(GՊچ =K$޸,*08 =Ŗq$$Q2%Ur%Y Ԓer&L?8s0<4 TE,~ !Ys$)-(:t:x1S83E+J`4FetFiFmFqF]L>5G4HLaH_4G4IitGGŒH/@c@ J@q e4A(%$ҋ&^6I)$ *{/z1z1EREJ0\uP P P5QUQ]`J!`uQ-RQQkROJ#&#uT7KKBK?KO.#BEb*!'ST/Hb܇D?%rOt0pYY5ZuZZqAYI5[{ZoY[UZp@DU[Lu$P#z'BÔ$z&e!t=ER ޼!tD;D DoqXa݂EU(b-b16c5vc9cuʵ]Eֱ> pcQ6e7dCvJ5udiU$`+ =AUCBfxQtf`E7;p^Tb$NVekbYfXkVcv^bJmf?L5f/M$"rQ1avC6Edu$wr)r-r17s5su msl7wtIr;[6Jgt]l* _1Dp($pӥN1jd{yy7zwzWz{s_7{ez{zQL!8dmm2}+vdD̋vv(]IĚVxEIa yU0[  $%x)-1{|ƒ7τe8M5sA5V"ZC ԷuE ~ndhoD 7xm1N3yq  3x!@m'8Xͷ5ȸXCbx1ьxp8tXBҿ|c_xCb8*#6 1*ơMQ9A\ٕP9T\oHaau?o9x%e)Y9O_eiuf`x{y ǹw{6xua9i&W^V$499AntO^NWLxAa7U0106Q:UayTTXfxֹ˹!sa sZ:!X1ړE($Nz_9`:ez|_Z zڝ}٧Y Bhz\yǺ6KzlDhj=b6W^Nԡ[Q"Qբ;z="C..A:Sz[癜ɚzyi[ Zq[IzZ 9_;oك{Uǰ^Aڕ/͐gQi [օj'UT X ۾1'K |a }9:Yݺe=|'CL]P#lq\ݠs"1DBqnzsjֱ%:O=}#]k Ou#]̓s=Q{ؖڃ'^{]^艞\b^j>z tAŻ9Ys 9M=d/B5YE?# ,S{_ݮAtR_(X[nS@ ?e?Y6?I!^Կ?uWO~5s7Lp6"28† 0bD˛IYjQX~`ۿ?6V^|VWUILz%Yv`NHa^hWiBmv )`O/64u8R5vQ%Ppg\vAD]r1wP#(Ca!uyN> eRN9P,THE^~ fbIfaJA,an grjUZrifz~fI9gf~:`T.h>ʟA)Ii(bD4'VzCθڍ!XMITAF[DNdH$ l¾dSX:V*Y YR`i^-" lWMm\۲Xd6 o*iI{"m b੭epM$ZA 0BhBPBM'"o2䑫`Gyl)Ks6SW)tBMtF4Ѱ;I? uROMuV_uZou^ vb[ 9=Kvn]62hލwzV/a ]l3mXATM Pހ#tq- 0i뮥O61)^̌snsN+wO||/|?}OO}_}o=Buhe{O~շiٰ 3qm78/t# ` WxrDjIdq]tx)} ƿǂ ,_D0DȱZiż((;X`k"T HpC${8Xq|I rB r,!D*r Cwp$(Gt#h,aJt_ Hƍ#b"I,ҍuC"{H*ad(34lf3(@6rԬ5ljs{dS"IYr,0ID_;"=h9a'H꩹QFq8JmlYt-=b4F{㪊 i519љIqs$-IOҔ) 8iΘtAg:Ul~͘O&ӞIJW:s (EYLAuۆoa: #Qlԣd-+@Zitlm[ ׸ʭBy)M׼bƦ7EMNA 4c[踊ݓFբ%ecۜ?׸okTCL! M袧 jjd@iA `N9?r¤{㦡INu_/zul~8$uu>B__U𭊄Y !կ`n`=$<a/mrxDؗtLa3J&Nnp"6[v^NťyR׊`??AGg}֭з~#H_{^é N|mx߮D)aEx MOٱA̋ϏjAhL )\'qgz~7WRwwŧfcs,UsNA$}A2}Gk5L)2q5gmT~'3H&~A0ǃ=xB=H~HwrOxbckfs}:8_!#ccJl/c:$A-m8B1Xq(s=EE;XV"WkY|tPƅ Uf_hH~l膭;pH( c¦Q%?T) Z%:ٞ)PPPuP3j.z2Ԣ7:5uP3%VG*D٘[YBYi)g ;_7he (in O o q["ry=mZ{ʧpzÉJ>2( x"ڜgs:[Ls +3?#a:ʂiZ`:c, o2: RDڌH Sr Ф pS Vōv֬e:PaPǑA A0bI6ʮjM, C|` Yu(( p/p/uSŰ\KJ?2:vqe:Z1#aj,+{Hw'c'4/{&iuŀzǯ k(%2B*Ր9ֹ:٨\[ 뜫R@(ҴKB'˶-, q+Cɲ,.-v -7aθr=?{0?`G((B*ސ}AjTX;tX5ݪ k[){%۶&r BmC6C[5k÷淀뻮&Z*Z++rvKb;+ː ;' Ӌ;ˀ +Kk˿ ,Ll "aBK+L˶竾XǾ-!,#L%l')+-/+l7,͋e?m̪0LElGIKMf]8LUW:%@]dBa,cLelgbkmZ;&^lwm`{} ȁ7L0*_JT)^Rȉ!I503ŨAɈq[ǡ,nǂlʧʩʫ 6X3(9Ȑ"t/t91Jʵ K|9Lpf ʣ \Rl׌" ^0 M?\%Ek0 <0@u%1SaN$T˔0 !/IB˩AМl6Ҭ[8 ,#Mҫ<( *M,* %-M61 /=,(%Q 2-,O/PD)J>TDP  =0MmЧ1մˌ-SA m+5P%Mumׁ 1|Aׁ{ӓ> %Dׅ=8 )4T}J PȮ0^ڬY[0ۻ۽ۿ -MmǍɭ -Mm׍٭ݭ܃PP s}m'=y-M=Aq.35]]!0͓Ā+TT)U)MD" ֓Cg=B!MEE=j ז~S\z۱8u8ubڈZ.NnՎ.țNcـ~~鬮ܼ>ٝװ]^`]1L1s.?C^ފ!Oo׎0\- D 0G= 9M.-s%Pn?Om(oGIMc==(/1-`ٓ_ELqnM@o_B?.XOowyL} /+s/~u'ǃOŲm/_Ėoo̞)O/ /VD/S>oǏ/oן$LOo /Oo$XA .dC%NXE5nǍȐ$YI)UddK1eΤy?9uOA%ZQI.U*SQNZUYnWaŎ%[Yiծe[qΥ[]y_!,Y  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///00011122233344455566677788899:;;<<<>==@>>A??B@@C@ADAAFBBFBCGCCGDDHDEHEEIFFIGGJHHJIIKJKLLLMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 HfPÇ#JHŋ3jȱǏ CIɓ(S\2d! [ʜI͛8sɳϟ@*SѣH*]ʴӧP" ԫXjʵׯ` R3ٳhӪ]˶-ӱdʝKݻx߿ |q/_ˆ+^̸SYuL˘3[d͠CM.>^ͺAO 7۸sW]!kNqc-ȬУKΘre,fgνi3\פӫ_1E$ۿ(V4 bLS 6F(Vhfv ($h(,0(4h8<@)DiHwCI6w0TeXfiەZvh\~)明IhfflIךn)YpiYՉ|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\wM5a=vb}6fvf-t[FyW}mPفS݇l+l;lm V|w8s.~+!,U     !!!""""""################$$$%& '""(##)%%*''+))-++...0002334666777888999:::;;;<<<===>>???@@@BAACBBDCCECDFDDFEEGFFHGGHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~229G*\ȰÃ~ |Hŋ9Ǐ5nɅ"G\_J-cz| SM4kܩ09::?;;@==A>?C@@DBBEDEFFFGGGHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22/G*==@>>A>?B??B@@CAACBBDCCDDDEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22xGDȰ "|qD!~Xmp'84ŕ&l$kԆӠN~0)䏣Bs~ ^c ?l0^RD?$QȐ_/Y 53悋0x˷/Gvw0aM8↎/|1`/3̬ gWMZ4}Skɶol ڦ-6z !,Nb"  !""###%$$'%%(&&*''+'',((,))-)).**.++/++/,,0--0..1001112333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEFFFGGGIHHJHIJIJKJKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaadd[giThkSdl\\kmUl}PnKpFrAt=u9w5x1y-z){&|!}~"&'),28=@BEHLPU^f~nvptrstqupvowownwnwnwnwowoxoxoxoxpxpxqxqxrxrxsxtxtxuxuxuxvxvxwxwxwxwxxxxxyxyxyxzx{y|y}z~|¾22 (D-Rt )tŋm zq[Br՚ŲKD#͛8k:9W@ tX)]ʴiSASIJUWʵׯSTٳhV:ڷjDݻx{$L_rqZ̸1'2:^ߠɎ!G4?xCwCwCzDEL8\A|BCE?% ~}{xwvutsrtss22 h*\ȰÇ#JHŋ3jȱǏ CIɓ(S"Ȳ˗0cʜI͛8sɳϟ@ JѣH*]ʴӗ40a >HѢ@`ÊKٳhӪ]˶ۄOʝKݻx˷_QZŪ+ *^̸ǐ#KL˘3k̹ϠCլ[[N\װc˞MvJѸsͻ6M8jȓ+_μKNس *SUNӫ˟tU2>~(g& _~bXVhfe v (N=am,z#(4ֈ}w؋<@.fDixX܄A6PFTViXΤdV0)`)&YihV8p)yiixVg`qEᜀ*蠑i衈&zY%,"D*i#j饘fvF!"U|ڒ檫xJ\njȂ 6{ޚV뢳fꥵ+ۖkudɡ+.;«NV׽:'\ 7SKW<gOk ,$lK+,|0cr-l31s3|@DksH'nL7JG-NWmu@=\gz` ]ma6Ő}pGtvxMf|-z.8~n7G.Wngw砇.褗n騧ꬷ.Չg8;/o'7G/Wogw;;.~ѵ_ ;觯/o HLuc|Y* wX̠7A z GH(L W0 gH8̡w!\-71H4 ԍw8PܠH*ZX̢.z` H2hL6pH*vx̣؍~L{ $GA L"5D5q$'IIIf̤&7Nz (GIRf_$$*sҏ\,u#%^C.IbL2f:Ќ4IjZ̦6nz 8Y;:0g3ѩNf3pܙ>}uqO<}Wv>=1Ǒ:zc2+*[,GOқOWֻgOv=.Q=_A>~f>,[ϾO{q/z[l-?9a+|7~|^U!EI>=gyj `y0 }@~8Xzć g H|"(|`y#ȁsPX g W284Xu~5H{~'W׃~G~'ׄEQO;xXZmS^|'uTpx&zU` vxw8W7''KXy焌X&PxpxTHx؉8Xxt80o@x ɇ8oȊxȘʸxp{}('wטx؈x&h8EӘ긎؎8X~`xGyxi$X`iE9Yyّ "9$Y&y(*,ْ.0IޗG1 ɑ9;=?ɓ YTA7ٔNPR9TYVyXy4 ~搕"ys #IcyFٖ1^9tYvyxz|[ ~}yH9{TGɖn٘ 0Yyٙ9Yyٚ9GYٛc3;YyșʹٜS 9)P ):ٝ  Yy虞깞ٞ9Yy.ٟ:Z ` 3a,wa9 ≡":$Z&:y*,ڢ. j ^2*:j0ڡB !HJ9ZLPR` J5 M ;*=ZPCZQqSlڦnr:tzW` Y7Х/t1jhjZڨJ :&xZW^9YdzzJ yx }꧐ >*Z:*zȺXP3 \ک:<jڬ:zPZ2j  JݚuZ;{:Z< 磌-JZ۱ yz UOz>1Z[".<@W[P4Fв ~B=" di-pL҇*MhɎmU}qٞɍ يؖלdȚ0xݫT׼-=Ǡ6=] >+\0,"D 0 >; >z>>.;.~1.>+->㎁u皹57㍱> lM1DFHVLNP~=QW>߻ !dj ?o ~>^~舞芾>^0>^}m篌n^~븞뺾>^~Ȟʾ̞>^~؞ھ.^Ů~>^~G ް n "?$_&(*,.02?4?_:<>@B?! ߾_PPR?T_VXZ\^`b?d_fW-hnpr?t_vOFϞ5.1w_g,A?_y?H6P?_8o?_ȟʿ̏qϞ?,"p\ u?_o?_o?1ٴr`@PB lQć'^ĘQF=~RH-RJSL5męSN=}TPEETRM>t" "LÇ)ZhaKXe͞EVZmݚ}R*:pQ6M/7\ձX`~&lbƍ?Ydʕ-_ƜYf΄1I70dzLbȬn ;εmƝ[1eTōG\r͝?|jիYvvݽ/7Jхvݿ_|?Ab@@D>Ki0B 'B /c + ,F$Dcp>/;X#0FrH+N4y/d1I%dI'2J)J+2K--&L1b@I$Uk4I&"iCI!j$G5M#_TtRK/4SM5s0TL|)CSOE5UUWe9CD4V[o% Vj\">AkcȎ_q4b _G(`[o7\q%\sE7]ue]w}w O4eZ=٣[`]ī_c6mE_gvjg4Tbvg9dG&dOwLzwԖJu5fgfo~V Q;\;]?%]Y~k:kqSfenAWeP 6ICVz~k'ۖGugx'xG>yO _}aZtcv+cbIukv;Yg~?yuG9ЀD`b9YsX<ǒUx-/  OgЅ/a e8CІ7auCЇ?"S0T !vBP|@j B;PRY*2q!b8F2ьgDc[0DLoc8GU1g`57+0 HAR|'H2Ȉa 2< INvғe(E9JRҔDe*UJVҕe Aa"Y.|%=ɷq{dBRb $M;S$#Xvӛg89NrRmc:չNv)v8[<&yyIE4c7$B/Xa9P6ԡh(e|tOq0@YI@4.鉏^Ң| $ςT|gDe:STdݹSԧ|FOȞ)c T6uxsjT:UVժWjVUvի_kX:V`ijAYպVխok\:WAi^W,,j`O7@lbJld%;YVֲlf5YvֳmhE{EmjUZֵֶml[Ztնmn%W< ַaG,82nr\6׹υnt;]V׺׵n PBb׻ox;^d%2s;Vo|]Qy@׿p<`FpW%Uo{W0;Tv.p#xp 'FqUb/qe2m XEhF7яt%=iJWҗt5iNwӟu=ѢFuUjV:Etue iRuu@z˅s=lbFޘ09o=mj׾0mnwwl;?Ѯvսn\ն=oz&6a3xKœmp7xr 'x5w#\ xE>rɅS፷Nj r7yG_?:c.szGGzҕt7Ozԥ>uWWzֵuw_{^u8yվv>z4˝v{wÄ}?OD߻^39so,>wW//󚇼r}PAPyvϰ>%#ox'G!{>PHˏ7O;?~=?~埻㣾 +3@?⠾꣼x@ӿ <>c>㳼3ck`{??St' . T@>@>Kꃾk(BPK=H '<>3\,8;KA1#|Q<B(@$>ü \>&TB8§A DD#D**AT=.|/T0$M13 > p@|<BK IBJt=K3L49M\EDPcJ6 CX AEFXEkE?|E,jDJœ=]4s^ZE@ @>HF=c+FGX-~\BpŚAN0 l`Hs GHed,dpȚHoTpqDrDǔTSQu,v> E>胚>p6~* HJH$Ȏʤ8? QxȜHȣHȎdȟ IŒŕ$˲ltəɚ>H~It|c988?ȞʛJ J|ʛˡʯT$4̨@˴t7M7pK>M||n`Lˌnk(!ռǝKMKMŬM;́8NHjLLHdHלH~ML7ɞC4L ,͙p$sxK`JMTNʋHsT $gIȈ $NdȌȏQN09DQP. ƺcKRs?ccK}PT4N+,-./05;J8@&N@Mp4 KI4 =I, }TQYtQOHEQIdK<T>xdM~|BHߴӼ:ШhU℉2=Q ՈHp0%cХB?UC=U~NIACJUEF5I0,OIm JF 0W c I;K MF3=U;M1KC:Py=0N P 9@Wgz=NVJg؃EԮVj ϛ={Tnuٗ oV;ٛO YPMF SP| ՋW yUΎdHlZZ8ڎuZPmR%VˣӐN($ԑHDEQQ۲ٙEQRkZ\̉_n<ېۻ\t[25F?8] ЅL]@ Q\j< ǭȝʵ\ W+]]%ĕEMYXlMIڭ]ɠ]X^8^}QkeYrdL}4Q L>|>??>+t_9C%@-> C&M)[ ^Ʈ`}r݈]`#5_q;Gl%?"tB>>dAC@dD މ>#` <`HHK V ݱC$V%f&v'(^E-?"[#)1&263F4V5f%%~6޺G Îp/.1cAA%;Ke$>lB9>e$dFfXd B^ IejSU:?^@.AҚ =<dI:=a!`@&?M:l e )fi;eHU&8WXs=ZT[V@F_R^d >`V>^d:la~.hߓf fKln~ ֵopfX#0gthSgeXCe` T*,iA>啦_}dD?&hV„6kF憮amDhq^S0视qnz^ iiW>,e }L}9UЏn\nnfW}n5XnK([0;IV[L=n =݂6~p4N d.ܦNcPXXvo p l_oml;m*WNĎb1`:pq&qq&P7?#?rrr>ڍl[*7Jf r r(I}qh+g0r& kf &c s>r:p=C_tEDoؼv'gm]qLlP0Q^ Q'.WuVw͍ZToW?Qu/w:_t^.0'(b_U/Vg7ՎrDu?pY^=HtrTOa^uvETg0*i;rt( 'm U;mT>` ڐ<u%ژNy[Q.{/b6Yfm90 gsEcәP˄N\q>ԧNİtqSӁ 8!qZY}:g:ǠZ(_ZlkR"2u>+XK953u xTf=-!J4 uV"y-v`x#Ő#]W;vR.Ig ټt7 >8wh8p NxZVJ]^fׁt}>yq4v {M:>;cv+8ッ AkHmT\7 m>髿~./ʱV揚FgEKMl=qew R ]7ͯd-/H%]NɀaXk]^>!~Mh0E( )P48'f?b\1&22 fE|e|#(G QwD@($α4*=27 Lbg(HBΛg%2.g̉ SWGI$(C)ʤl~x<(Q/X\+WH@吂!"KXbFVIR3\dX6P|&4ieS%d(1mr&8)q<':өNrh|g;)Oys=}S<&!YeBГ<(BZ8jZl&PX(/b̥.C*R]d,i F/Q3-'@9ȁK|+3'ӝ^ u(PQ4Ĩ, E.b^܋ScW(VڥnьFFf=+ZӠ8CM+ WN5ReԋQE%f+Q2 >6},d7ֶRv7o\*ꗤR¤4z)gYJ"6ZqҶele+{Yjt}ܲL2=ŽLVW *V5u 'dPrb}-c;Sҷox:^5#ziZVɰt/z}0:t?Cה) -F/+χrOIA▥x^sv!,: ,4G-5E-0cPHZv3 "L9R)gPse)Felh2,i5˗c`V"x )ϕ01USP-$0SƊylnhy-RNh я1 VUP4cӜ2B(ݼCj5=’Qƴ6hQ.L:MSmlt^<:KiYuЁF~_G[YHT0Li [`{Jcdo-cBډiHx 7Z۷~PČkZBaFx8G) l|Vnf4:gϧ6@iFܢ$7tNߍGժZJBΌ?h!\w1=B}?\K#vI U0ThNn'/  S~ |%1[ RJՁs<38T zU ܃|5zyx;6$+3[ VKMv..R'x!M2y~~a>Tk-g6VЩO>̉GWy4o?5.o1cI~N]Fd``I ]]lD q Wf!&-ƎFAHF|JKH[FIDP~  `JDA(FpL|_N҄ZAp!"KvM2!DBEXJXD9L$?a b]O L "oF` v \=^{^u} Ӎ&n"ݔ nHdZÈut|_]*Hy_m ć_,M\-߄|G]BXDž%љŮ]c7\cl#̊97X81:b8Ԉ'qby`le"'>= 'VxZL,"ǽ;B2Bb.:"گbI$1GdVU~'cd | [@@YYbL0ċ] Ze[e ְ$u qXFՐ]Oe҈medDŽESTZL]%ldV򎅍En]%fKSR{^|i|r.'hfm6mrYY)ntvVpwvp&q&|Q%s'{js>g*qe'ً݄}kTzҧh]'|^|K~E^ƃj~5k.n(RLtrh SD(m *\!(z臶I薘]hgZ杵&frN(ыB$Rh%M.)Vi ?})))ӄT `Ω>n) U׈('Zp衦Ɠf~YqMIr6Y*jp0ꦢP:Zq_*WzojШzNթibꃽ*GBj'Z*jFmkZְƣP&kӛKckZQk憬+$y-yV+rP kDb ,f2Y1l ٩-^؊=^PJF Jk(:>D6˾e˂Ь$׷^R˸h-4lu"mo(ٌJT1՞`{p-պd6jOu,~Ӷm)m^V uPE(ȺмL: 4pZ`f`X@f^<*NV饂,ۺ-*ʴ9nLD-XLxe* HB] µ.nUR&Y͎Pnv.zj"žH].nJUp- r/b$jmV.io-6-b+ y*ؒno W/Dpj 9&5?!c7?V3B7t AprAgCW(?2Eotg.D(8s4I+ dIQjI32Kti`'j4M2ILGPNts4J#Q mJOS_M N?3tRVETTo5+[1uVYCWKW"u`5V\߱[s \5_]]u\ 6P56bW0aôa76[+v~1d'cg^_6XSvxY6gsnfcf6U{vni;h_IiQn2Qv[Ct=O6e6olk[k7MxѶqpWIq/J#7[7tkssW7GK~)vkuIvwEs7PQ7ykxx7B7@{zH{Ϸ?wC7~j}k}8뷠yF3x57jƂG,;8c6nG7Ao8>c)Ag鄟F"i8mƊ茗Fx88lƏ 鸒o葏F?2 9kƔgyZyɷ떇Fyۂ9(b9GkƙѪ8F߹y9+g#IdOozzg9+ P(G::g@:G뤇t wzUjfp:jΨz>fϺzf:oj;N:f;e;i3NG9`@c鴧tWn;w8k4S4 l;;bD;3kJb`h;hL{{`k[^<h̺G<{˻hwc@kn|~C<Ǧķr<.E߼lҼ>>[7)2K_>}s>e>]DU~}\>Y>y=*v>oξo=׳}>Ӗ7w޽E_?oQ0?G ӛ>zZ?V?f〿O/#+@1`A%TaC!F8bE1fԸcGA9dI'Q|eK/aTJ )!B  :|viSOF:jUWn'PD;lYgѦUm[f"50k]wջoߪ2fIӥ_9wthѣr *5tjլg׾{̷ g}{2 :u;| пm0xPO!PB]sOALMdT]-UYR0mM2[[q͵Dq<  R]-vWcuY-|AVZByZR=hmY%-'Vݶw%ۚt\[W_]_W[zeYnx~`s2X7U241YdDGW#xYVIc ӼmU/zy&5cf|NZtyݞZi-c@Z)jkZ쑩&:3]x^ .;fqKnfmO˵[7Tmo5@i9q㔼AEgNchIo}ARti/t$>zy7ثӼqRkݝx9)4\quy ^7wձf}{ g_O|ŵ_<ԯc^4!Z̀_18$6p:i3]-) AAFǃ(tfD/TBӴ=K /3ЇEOuuȈM˪6 :NæD-GWah!Z_4qŷmI+3F*эutM..jɎ} )#ǽ$܍#6dFN/xL$H'Jn$4L$IQVŒX&5JUvē~eWKҔpAdK/.ɴ,~V0Y(M$4H֒M 39J^ŗD79Bje6gМ턈8YNwzQgA9O}Ք>Xϼ32[щ)UOԾrmki~oem[:qpܛE,.ܹ)&̕ ^wmUunwS^p+z^l/[ߩ-n;$&n{X|d֟a l%هi"0I>\be$VN<z,iܰd9^SU_!G<C[7u4T2dqHzeiiO3 0ytdVl4dqff;ngksG\ :nzVt|:*cW~t8ݍ4kuvzř4MR/Ih_ַjF^]:pun\:j6]OdL69_?>r%I6ԣA% ܎v8rL![E}ބjE];tw}gⓦfDo)--6k8E^qIJ x.>\`I^7kONLH+_8j-У-ry<^t! ="DWz?[Lө>g(Yukk(6s.Gʞ=D`w޽s[gϻm^@WZ~\x, x)BY5uϯ )z*=N^֯LWs}YH^!>,!~B|;^~__Mgoo?]o_I?Uɓ0a۳]r?PMXp40OPIr*w"P'&60گB:mN5."O[PRYpH혉qP O pK^WI| C FPJ0pRP4n h }%p p/Ps #%  00 .Pw`iOQOP%/"9Q* $//adEMY1PQRq03PpO-@oB qM~Q+?c<݂1O;e$1 QH-qC"12ѕ611 ;i{  Qq !emQ)82F,0#%"i"E2D>r$-c#-%?$%m)$a6\krBdri2' $$}AvR?Vr(&)% 5m 2!(22*)!A!&rr,ݣ(?P,'unn+Ҫ).,g-3 3;Ԓ00Ӑ1#1Wp1!3*2C2)/3C3)33E;@'KXN 15#.)4a3%H6473,,yS6tsS/n8c898S8eӟh9A95.s;7#;;U`֎53Ws= I."w>G77 80SSs@"@S A;4>SA#A)T/.t TtCs&B-jBATS ױD"CEQBaFDTHtFetFEUMG DAM.GIF[Fa4GT*xtIC{C)tJJJJ)tK=BI&4L7L4%L+KJK$M+L$N%N4$tOWMM#tPMwI=H7=G#W<'WG+;/wF3w;7F;:?EC:GDK9ODS9WwC[9_Bc8gBk78oAs7wA{7A6w@6?75W?4>W4=37=3W<2;2w;˗1:0ח:w09/9.9-8-78x,7 +7*6X+vZn'*Z/س2Xo7:[?BoG8J[OXRXpWxZ\_bpgXj\oظrXqwz]qÊ]XXrŚ^rXƪ^ؽXsǺ_sʘ_ϸXtX`ANDh9y 99SQϓ#vT8XX195y9=A9.OH1?>C5*:Da9eyimKpQ!'B3[?py9Y_җ_uG,;D9y`HLyEf>}yٹ!љqr#S yYy)y.y9q 9=AڛY3E]-Uy$$]a:YSUZ?XQd:ZiZ"m/q:lWz::u:!ْ\y™Qz]9zZ$0-z:(1.{ {ZP ;%{oyͲ[J;e'(A;7ٲ3{W6g:{D]ӴOmR{V`{yD k1,9};{fM:阻CU{jSz5{V;麚;{aI庠yt O<%<Zo̜z=OA~!>%~)-1>5~9=A>E>\a!imq>u~y}>~艾>~陾>g^O~z͘">V#`ľ>~پ>~>~?>M<=e ?aHF [lۺ} 7ܹtڽN51tke10K8Ō;~ 9ɔ+[9͜;{ :ѤK>:fÈ;6|uv;ݼ{ <ÿ,Zy;=^y=p0;0=˛?>ۻ?ۿ?`yKAu dq>aNHa^Xb\ZkIb"FE5B##|.Hc6ވc:c>dBIdFdJ.dN> eR B * ^~ fbIfargy8bnVEBubg #0Bg~ hJhh.h> iNJi^ini'eu]jj&reJDB#Jll.l> mNKm^mnm~ n{mBj o+~k%'Qipȿp /p? qOLq_qoq r"Lr&kL l s2LsIիrslMtFtJ/tN? B+rm;ٌuZo58ϪsbsfvjVOU wrvߍwfacmkzNxvOs/x6}xONp| xo ^ymx馿 y誯z藇y!rz{^{lʎ eqִt-_OZtԣtSNuUl0qh8nʉ>bpMŕ%m;[O"2N Z Ȯ0x;מp'H/OVƁޥvDР x.+x n+xg2ޛTUy'h%LJ3͊&׍iS ccsHa:f 7+\6\-m-0pPu!W(_%{yR.t%\4C͎u\8W?R@ @ zЄ.D+zьn HKzҔ/?Wt7qMV\%gό ԓkb&v64cϘ>KP;91y c#OuS=FIAae)uھpfytO 瞜Wݠj׊VeMo؅+}b;,ju~wǪݱt ^ >pZ oK~򔯼/k~?Ћ~/i 8Ʋ®;Xjګ:glN'zhэ/6Wj.B_WFٕ+v;^~Mrӛn0U9|^roO8}^?NXp` Ȁ a&zgUK%SETE%S*UEJ00`r9bZu{9 pY-ŋaXj}Xa%Ya6r4CHEiGoSrDaf)Iؔ-Rfs86z9)VeL#ҏ| 5 rCs)-I8P I 0zIiJKX3|f yi9;o 7陜 y٘Ii9G9΄rb '4)kmI )I6Ș)|ɜ4<9Y)]Q7ɝiɚɂioydN<`Is# )ٞ  ` S >) !*J)Bd/á#*3J5ژ%*(;J<6*CJE M8:ʣKz;>dQ*SJLO:U a*cjݸ&jk*<]nd*sJ4z'loqZ*zw{ӧ~ ꨏ ijzoڨʩ8YJk^ʪM9*{â9s<~&ڪʫ8:Ú5>,a# ZzJ:3BKkbKZh嬳rҊ隔J֊*/ @jޚA:sn8突#jfyymK+Sjɯ6AgUX:Y sX RhXE7Ij^ ]%i9ZR∰? îkQp+"1*kY94ױ4Ag\es$U{:[q[ VW[X9[XTztA+s˟ *yz{+3I۴N "ʲձ-Y's7fw":Exv]G˹-3Y|+b˴+ߪ.+ǁ[1{Yun`˶z)K[CQQ˼R"x{{踶3+jK &wwj#f۹띡ۼK!ϻ+빱io{ˎx\kh(bns{X-w4z7L۝K# k2YY Rpس;o;Iǐ3LYfYlA )$a){UlʹMżĀRT|e Q-6ANPaGIMKaSMeU-bD\M<k=MP-!tMfyCh}rAGqׯ$rC׋4uTؑ-ӃԒJ yمMm٣mI==֟S8ʨ=mΧMۍ=ڿ ձ}ۣk۲BqL _ -Mm׍  _`TC>]C8["}ܤ@CzN M3 1DC<C C-IM_!.#F)+-/ @$n6 (IE ;dфb>JzMOQ[1nWY[eDRanJ:ݝ\. V EG>IxunwyNpT}.t燎j>Csn?*CCnkq3A؅Nn꧎+Nu*C^=M b,pA7d)<0A\`sQ].HEOoU譱꾾EHڮE?MQT7=[P!_/ A/NNe>/H"kpK‘5[1v"mhUq e&RU!2 su h|_w?uC)NqleI xr?x/'N/N'u1mWY/#]"f;#`m#0#p {@$SS%q ZJ/? _r ۿ/KT.#V?Z7P3vI]Z&оQL*? jaB5npU!E2QI<K1eΤYM9uOA%ZԨGm,eT[QNZUYnڵ*0)P#rQ6#غf7å<%)?ҸJc@UȘ//|̚!_\iԩUfkرeϦ]mܹu[6h 'N0bAze z 炟gM#F0vE,9ʣϧ_}߿hҦ) 4@*,N*UFHaB0Cr(0 8٣r STqEU*ZLa0rl>ì3l|BH$TrI&tI(,F$J,]QFCb{$ ^s#Ϙ襡Ϭ3(M?@tPB 5PD$PAH#4A4Rha[ =Z8Z>@Pr6uUXcuRDc.2^Ms4#4XdUvYfmVtS,qi۷hU[ĵW`55:HN:wCcRik.Ŕ<2|)3"E]KgzӝtG]Szխ~ug][z׽u]c'{~v]kg{v]s{~w9w҇U,) HxG^|-yg^|=yЇ^'}Mzԧ^g}]z^}m{^}}/ I?aV %&!0`8`D}g_~}_'~_g~__ @@,@<@D? >>CU> P0@ F@ AA,AC?C@ DADB,DCmDqGnL^e^q\ s[Bvd`qpovqqqrtqupwquxmYKFA6~}{zxwwvuutttuvtrphXOJ}HwDwBvBv)q \E#22 x*\ȰÇ#JHŋ3jȱǏ CIɆYY˗0c|͛5\.ܻwh gϣH*]tӧPJJիXjʵׯ`ÊKٳhӪ]˶ؓpʝKݻxWoʗ.w g;{KøcJ<٭˘3k̹ϠC=ӨS^ͺq lxsƲ7b==8{^μУKN-سkνwײWҮn3wiȟO_~I$Az 5GwT7\쇔qTu 6F(ᄤ}gf^Kvno̊,}I] s^S4D`5C` RhH&LPF)Tvx!(&N`K93Ψ57 +gkG.CgIs[a 3~CKzdɥ^Y嬷jm.׎-8;3:;'7R.ݹ"%|Y@ % Zj7< WB|QH2-̡wpe2 H"~HLf*B4HE,Xa脣` H2jp\,(6fۗ3kG񏀬]rGQ}L"F:2nH!;s.򒘜#7IEL%R2hL*Pnf;,g9Uj%{Z%2`Z¥2I%]&KY<5e1Lb~ 矘Irjș_كU)I!sAW>ED' ZhWڀ=}gCG љ?2؀ "0r0JӚE\(΄1юpd G\J]:!'=JժZXͪVծz` XJֲhMZֶp\J׺V^̩^ `KMb:d'KZͬf7z hGK^c{MmsIllgKͭnw pKMr:ЍtkKZW4G6[zw xKMz|Kͯ~׼ސF3<`gHcM0}:^u'̙׻7{ GLXp3V;'0=AXxg|8;c 936 gPL*[Xβ.{`L2hN6SY-s73rg-Y3%|Bg̖12e`,Ҙδ7N{ӠGMRԨNWVհgMkMXθ^4jkRX9ƯCa:؋&m$wݘ&=ICz>ζn{MrNvMz{pεq~{q7>n\8j؂ @ l !HAP1h  GN(6 핳!7z)8yǡ7:9=p~ڠk@ Ng&OW8;Ⱥ7Єa 9 ̈́.a ѺpNxϻ(z<B+O[|3zsidyzs g=j'齑&Hgߕ$߈8ޓ Є.tA O;ЏO[Ͼ??4{>Xup࠿?tw{ |{xH{Ij0dX@PqP kucePiX&x(*,؂.0284X6x8+ [p f0 {{Blb5'7A[E ٢-hp :b8dXf8ΰ jl؆n pr839u( p{8w'x~XIjP@l@cqeHk ؉8Xx؊ =( ׃`P W00Ű  y `'א؍ oXo ☎8cc(𸈺щX؏QdЈefd 9Yyّ "9$Yi =x,y ``O=8= O x&YFyHJ)ؔl K9cc@iX!VٕXh搖栐6mIk HjYvyxz|ٗ~9Yy{ - zЃy ) -y @0P;Ip^栅𠘨ٚiN93IW9f pٛifdu)kP ՙjP ٝ9xi p i \ jIvy P @: NI M9ę)  : Yɜdd$Z&z(*,ڢ.02:4Z6z8 iPPB@?;jJH`=X$ 1 XZ\ڥ$ ^Z2:c/:t倦.lڢj ǡdp ޅ|ڧ~:Zzڨ:px::'sW:@꩔*>0Z'ڪzp o :c:t૆ ZsJgxū:ZzؚںךMI poJ * ʮȪdPaگ;[{ ۰;[{̰K;tJk'+H!6{8:<۳>@K*k B+UѠMUOkQUS dе^`b;d[f{hjl۶npr;t[v{xz|;[G˱j}[l+d={c5&Y˖dT{۹Fb&[hIW;[{S лۻp[jKFۼ";[{؛ڻU4GPŠۛo ku; [kݻ4Hp!)ۿ DU<0q|T?J 0|SP ƒ*k2\6|* QQ @ 8,“CKJN<? p,| PElĬ[Kb\f|ƆǢ<< ^ld,x,d|ImlmZKu@mHԿ@ Sն½\NVKMָ\0:XAD-'l o^ ,K5O7]9 `ԅ=ЊX={[lD @Ц-֗mαNAl+=mJ-f]ԙ۾m Hڧ=ڟ ЈPMڸ1 ّ-N] EME0h\  hɍyj ׃ }c`M=-c` N-rL+ NM Ԃ=ԑ >CMܾ]3}۩M ]ຽۙD -䡍l]߅}6m:K I}H&N(T!~@mmn.E]p-R1l  s\=v|lNm8O -ڸأS^~ NJ ߵ~0S.>mݒP _n1>e벴R!0@{}2 8E}W-Үԇ='3}~AnR{^Jھ S/ٜP;> $H@+1&_A(*|8`Q{QD-^HPO=yH%MDRJ-]SL5męSN=}<TPEETRM>ȏU+YUV]~VXe͞EVZmݾɫqśW^}Zǐ? FXbƍ?|Xdʕ-_Ɯ(+iZhҥMFZj֭][lڵm}zϹ}\pō/-3‘?]t՝kƞ]vG9/\x͟G{wݿ_|ʗ7_~;$3dA0B 'B /0C 7C?1DGPHRDWdE_1Fgt @wG@!$23ădI)%J-K/3L1$L3D3M2=8q$L~RM,լNz駧z>{{{)ZS[[nyq]h\\@y?ю /}8E^с LGCM}:yq#эo#ڧ33aGqЏnT 3!'Df9:+&2g` HNvғe(E9JRҔDe*UJVҕ )b+'IDRv2H%31t,*Hbs$c$KjVӚf6IY !9Nr<' 9R ;OxNwkPzӠEhBP6ԡhD%:QVԢhF#*9C> ZO+>JҺ4y$(=e:0mFuSԧ?jPpӨGEjtйTZONw;j궃H@C@Y w 8U#ƫVխok\:Wծwk^Wկl`k-_-bժf4 o)e0V*vd5+b:^]MiY`mle;[ֶU-lQ['L. ƶժ`7U4~SRֺnv]Ƶt9s̚liۏ6t#oU^#[ͨ\Wbw<`|`7%Ɔ[TưNJ wqEpݾw=m7bֆv :x5Up -q\%G9=;/gTen:Eayus?zЅ>tGGzҕt7OuEgG{f85o{>w}'{mJe{vG|i/%?S5yw%oE?SȔ}eG}u(}?||%ſ=w| ?}W wS0~Gտ~?Ӿ>3@?hd@l @ |@d@p A8A D ,A@lxx?+BK[@@ L@hB'DA`|4A-@- dBA8CICTB9"\#'|&ƘB* A,T.\B D+ C2$$,CAYhC@8 Pt9;T= ,VdVoqWkh(IX|]Z0Ջ mʲLRW\P8ͺЙV"\0 _% I)4Ӥ؝̞ =Q0SlMiκdVӊԏ%ٷ5iƻMHW.mM)xYyU՟ZH\Aڔ(ZK|=Bt }`)__ ^v 0CV,^asBJBDf^b,\`waX Gca V!N89:;<=? 63~5 nc"DVEfFvGHIKƿ=x P)$wA&e(:0X kLRmVa*+@vU.F\VI]f F`D0֏cWB!Md diQ.kS67.SYF#Dbb/JlFE_E^NbWBbcHd&e^lMhejfl6JpWX^Dyvh\Dz=GahfrhWnb_> |6F1~~gi;N'n]o>gVbqNG'>gm,g)~EZ\LjbyefaǥIKai/Ji^8&kitZhhhVNWagFh+nvV~kƟfub cdfi:jMh# .N[ ̮-%ڪ FάFlgJO邖֞l#6^mIlqjFm1Okv #X}]7- (YY}ݑn熯R.-ݜ}GPVduYKvP 倫n<55P1 UnnDQ{mLjQ,ռ_ӕmӬ.mfKkifqP]Ub@pM [b(]8\qg=\EqEJ$7GX''p7r.r;q|&ոDKo|JE(7pr+-g?м`r->sBOoC@tEGDGt`jiolnLOhtnOdhyqSGuxUG0ظZR0'QPus'Oo^Gpwo6ururSOUW7`_/p_YW?fxs=LjKcqR/&O\wwowcwHmq!9L.=NG!w7GIvq_uLrP/&5X:Otw7[o`7/x.7Nx.v,&f.GxuTvg0xpl`p|ftuRwoXM5]zvw@dV2z,Ѡqw>qP^mw>/5q[ֵ/iwsy// %o`0{/x^MZv evr7P{?v9xlSk@gpr|vWzwWPED֤?7k&=6{GiUOoXUTNNU7?'p~iT^0,A~$7A <o@t?Ow „ h%@!ǥA n@/3cAX!Ĕ*WT%̘Ȭi&NnAIK9k/V|Ɍ|]ONZi;B뿁^,ڴjslr-ܸrҭ֏ :w7`E.\ 23n1Ȓ'Sl̚7s3ТG.m4ԥnD-ƌ.lw: A޾ִӌLܳV^y٨/wyh_^;w[[ o-{I9[~ۙkyp(5m]]L_ZrXng .凷o-^+9/<~<@_$mHlU>Ojs\v5` -ٟh%#DKLxBP#Hh.|@P1=dWAn=x%2H|"*/)!r0o7Ģ ߢ0t(օ ["rã=J&~#j8ϊ,4U˸j^K"yH,Q0D5z/wpl$DǵGI %*SʜD?$7в%.s]򲗾L~)a3<&2{id2l&4)iR'/J26)Pd;C2Ҍ\lKBrdP(OybTԤƹ HT8-#~3})Q@Sc;ߩO|s'<5ʟ0v "SFqRH%AS ,ԎLsSMPhIw2ːH&Uilet2U]U/+5-ekNձl>=z>C&]4TVwUq%=Rvr[jYmU$4=,ЪXUz"F#@+"dG|ⵅS\KU!vlCMi\cgY<&RlrA}+u[lW[Jm,F鞅,*-qܛfuqëCG{LL&Fhbم{Y$L[Lb_(h!8bvTvf1.VJQ~/ `O a@ ~b8;ZY۞VZ؝"%Ƶ1͂źzw"M2R\q,U0X)H1(V=8?;Ò3b00 1ӓtT f'l%?gN|@aG 2t_IѰ\ 7q__Rob]8H"X2uy\ RkxvukGd6RvMY[Uc 6Б*;4Rng>I 2ԙyliP,7AsXerqxT:8Ȼ 3)UĂ*#.γߢge3 @;UY9гD]\<'cL#L|hK;7>s.hY&,ilh+Ao{c"TpoxŁ ^DR| |l怗!oI. z؛NryT K̫-ts9::_[RjYuJoރQ7E6KZקhxwyO%#],>5}!FIlL!ˆW㿚R!$Amܟȭ[xDD`GBDF`GXpD `F_I_G .DCBL`PG@ J S D ^ N | G B b`<N YJJ_ Bل 4EܩZ !Dr[=T]u?aa`˜ 븋sFppELz4a˽GG|[{N4ȰGH %bv(NA]f"VYƣ]L?f "*Ț"[ e(ȉaؘ!0_a<Ȝ4 Tʠ]Ɯ-IdD3nG! vG .aXz⦔W}JҍꍠY/XI7҉VeY"A6_AR!W_9VJ8iamlH}-YMZ0~aHfFc%I&L:ǥJd Kd!`ɘ (&HMZ"]?ϭ܌1SƄ^K?̍ deL)BZQ4A]e|mLi#z!^H$yQ E`%ַbL &miiX5aN&D%1ecP4"I|fũNN)&ᄖ]$e<ef8Y0blViF^jk21Tp&qmmg^yKn2'de%*uVqar^g@&xcH'Qq'zOvvggMn|.yޚy~z_{ԧYvsFB("ON^EYN(V^(fn(vh.h kzp6΃J(]fjcc6r(ɭ:!'ꎈڨp.i(ZMi|Uܧgn8)A):rK(6fk"iGz\ibyinnioaJik))FטjP\`iii>*@*L)x&ښ)F&cHx%<*h0XͅEj|aXūJ~])G.k]jx51kYYp٬`kY$ZhU+=ڵ2&jΑ~J2:`thȤٻڀb+l0߹U)pk+EZJ MſaZPylQ]m%l,l΃1de<-0*9-Z\kk6~+^\ZJmzL$`,ʬT^mNFB6l\m ӶMk!-V۶Qf>$ml"anJMRͺJ,l-.fcBRH`.I&..d,N*v^be%8-ZJd:cr*J…~/.ZŖm!6Y ZQ^߱\"G/>:ƸNgfoO*)n*FvjGp:Sjpe`n밞)zn(ҩ0tw} 3 OT 0Z 0~&z$p/| ?l g+)/k;1C ץg)'v9}cq OkpkCRz 2!!2"' ?\Alfq+=$_Mpw0&)%W2SQ'r]hrvq2)G'ST(R*2qq*,*%߲2q2/h..p170GQ1/3#p)34g3T+S5o45osz^=38sp77u3:9V:sq3=n</i3DeC;@W(K4bQFECray4IaH3VFtaKJ7Hϴt`4N\MOK4tYPO/M55Y5SKYRVPGu ;XAU'ToRoubuWi5X\WgWNZYuUuN5]V\#\uuN_^MZ6L 6bdawP_7*6D1dcC,]6RCY6gTfWd6zCiha6vB6l;Tkk׶~8ѶnmKn6z86qRp[Yi'w8!srpOwqB6I7vQu[wsw7j*qxwwNx*7{GTz?u7aw*}c|zw7*7cg7I}x0 x(ρ?x2898g/IgYa;+Ixȁ8O~x_΋ƉѸ8SNS^9wxgАƎ/w!9)9cNƓWyvIQ͕cylry9[MƘd˚FϹj99ifyq" z9_7(:[[P_Q:,:fWЦx[9{[{ƝLzȬwFC:H#G [ƱoƯ?61{8;OFkƴg{*Y;`cƶB;;7F;;q+ƻ7';]{j;;Dž'{K7Z,K÷z: [P<r|=D<c'ɧM|w<ﴼ̇;o_M΃q͇q _Nҋrӳ[NԻr[}ϟGry_rسكks#WNtz'iyߛ1C2ܽSN<7X=~-SL+N~'>~4c~~o~s7˾B㾐W3eM_'NHsiӧQV=VpkaSq?\%WuO:oN\Å{nWҒ%IQY\CYhEiN۔N4V fֲhR4%kZkk ꜿ.Ѧnǰ?[c+[;nO宷p&\q4p\)?%q1qKHAGr/6>?F?ig1` vy(vg]xRtu>^*wKzə/KE >O߫ u6m'u|ۖk@P5-! %i M@o`}#X{ R_TdD>R]<#)HjiԖ%ͅIOnY(j+%NbZ^XޒW-y9\:i/LcmG*2IV)mk搞YMOIU׮)l~RԔ7ypi\97zR; (x =qOi@u i*Е)F (*y^颼,Q-eM>I$]IYh1KQ8t3MQMy $4C *3ghxgs;;#>u]>EPJU*.J^>jꬄꇰVUE0*b8+A*XoP\ vFMl !>6_EWc)kͼm6DZfd,:ݕJ-`YrhkIYFmn;[~=R;7H.i+>s[2jvYhn[wUˠ8}{r.MMa~Qd_i[`8V0?85 ~)h^?`Ci/c*Nbʨ3"^\߸04y(4ks/q|v(y,2 (_lTN<,ga ]3cy+r_Y5?SqƳx&AcvO @eЉ^ۃhGwekiHFi||i\Ѵx8Ꜩzա^X&y\gΌdkc3j]adCцΰSlkdVmh \nf'SSՍsQ񦓸Cn{g C={Lm C)7js^qIo/] vq9a߶E햋dvߠug;}~;#ކ_9 ȐWnyI^/̃HgLz8ު|:rB 1qa20Gu-V04Q 9" cQmIq/L/PQTq;-e.h/lp1b'q{Pq2Q/ь1K/Qk K=Q+1/1q -(BB 1b~>љ sB !r[r )"k"B"l#9r&<,@rDr$c$$,%U%Xr,\2`2&e'[LNn,q&Ţ&&R%022*"ũ**2r+Ib*ad,m,R$+ز-A-".l.#+r/{",I-_00// 1R1112B2y223oL330W4R4w3e45uB5[55s6QL6q6q6G 7cR7o7=7U8mB838G8k9)L999Ä4M:+R:g9:;eB;;;c< L<:E>>[B>K?ő??9@Q@W?@AUBAՋAASBKBBQB CsQCOCCeD#@)DWDKBDKEIEeEF;QFGEF0F GGEBGKHHCH IQIAIIJ?BJwJJ=KmKKِKKHLPLKcLMՔT ݔL/NpNy / (O0OݭQt 1~}PQJOŏO ,5 }t1(i;u?Tu(RUU,VSuWumV 'tR~,qutTV2YqTgYyZ UZ-rYKYY U&CFJ5PqV5uuו]N)t^U^^m0_URW'0^[[\YUU_)'V\+V* 6R}2aS?&NX7X;^[%^VS*vk\v v_%5ICF6JvoVVIvvWEqg]gG"kukWU6'/62`Scb[lZߵRv%6bvfnSn6oc6$vc5pivpl/mQXUvnkUqejjjEpmm?sp2d0)&uUwuYu]ua7vewvivmWuZVltv7xwxxx7yS7woy_}W9wzzz7{uWc;tiw=||7}w}Wfs+1o|}~7wg{r=7|D 87f#zJ%x)-Xv~Cp-7/A8Ex+FX3it=Y]7qvq8uxkWQyv炇[ćmXz8yXÖEODxxwwWɸ~oXozyz#%8vpVxy g_.h8E ĄQr~19 SN|/YEyߘGד9Yؔ|?eÕmw uh9Gq9o`󠙛8Cy+V`v+ٚ9yYyӗߗ9՛W鹞ם,-y:yݹ Kky!Z08ٟ#z9uY(Z9WoҴUz[Y*A7X#0hyOxw?"ħ:#h^:5 !|9QzŦ_`zZ}h:z `麮@ :+t;{ ;{!;%{)-;M1{9=A۳z:⺮Q :5hZ`imq;u{y};{;{;{`3dcO;z-Y1"ٻ;{黾;{<| <;{yU#Z4|9|A~ >~!>%~)-1> ] pS{$L@ ZU> ]~imq>u~y}>~艾>~陾>~eޠ5aC M^KB*RYʾM>>~>~? ?׾ ZG|$@>BR >UY]a?eimq?uy}??{S>aS͙IþtM*d`_\ ɿ?ٿ??B <0… :|1bBy\ tE;z $K<2ʕ,[| 3̙4kڼ3Ν<{r(D"ҥL:} 5ԩTZ5VQ#ر5dK6ڵlۺ} 7ܹtڽ7޽| 8 > ,Z2@:~\D$ɔ+[9͜;j44[K>:M#;jM;ݼ{ <ċ?<̛;=ԫ[6n5 {9ҳ˛?>OТf ?f 6`H`_]aNHa^{%U_~bT]Hb&b*`.c2Hc=b:c;e{!IdcJ.dNRfcRNIeVrZne)FIfP!ejf] gr)enމg;f (hIh$.hv" iVQi :i~ dJj6>jZ{j kqjꩩ+H liJ,U l&kҎ^"&mgzzTBn枋nn zmV8mYKzK˒J,p? qOLqS\o̱  roKr5+r*sVp Ls6ߌs:s>\ BMzt6t-tRrձ\Zou^tbSPfMjh 7IVύ)_ߍw\WbA~wq.2ۆ6'MwfڭwO^[N ~λx9Nɉn$䓿A%S hy q¿Tz>|β|}8>N;wBGd|"?~6~7/_O>`4?f<P[fYq@oG?U"!pڥJH@~ Y$ 3&b *d{7>FV(@+$1r!0vUmCF胢=վ6 P3f|Dg&Ț9~3_cA?AR[%LPD y H†*#Q$D"IVCLr$*[ı 3 hJsԬ5ljs3ABEFfp\9"$8;N-ʓ~9%xǀBJ])b`BPI>ҁEiњEP(CQ.{`?J`,mJMл!VL]2.IS]₇%"MJcy%nլju\W ְud-Yϊִulm[ ׸bUG*l}:Tu#xk@KJ4Hi] Y"  \`*ڋ҂~@ifׂt8dT:M ۙ&AgRE8].IjX.Uo}cD@*w-yϋwm{ w}wo%׎3h0l vGl𰢝o|Ɔd?MhJ|A^\4~i =|< #1┺`D.SӞ"Ѩ% kDC.ɑPi/:$v+]́ Rh 8ytxDoM3>^aeyD 8Qd06]ԀL%g*kKeN3spT'XI1FwO=g>5 twJWjHft@)' r0a& +WD1:7bGYL\D6 K0DQpU Rj dX0`o O;_UO?s=;}J;d^e0(M?hhAS #k?5QXOgp#O:Dgg'FaiXFdF 8}Y CJTg;@pp|+Ȃ-1N>D7e5(pE`Cc$AjWBj^B~g~~cS >Z0[ `se*ik7҄O(Ou7QW}؇;oHhӆX7H"uHwwy7艟-iȈh'!3芞>{0hX%+X鑊;hX)[׋h68.״h8H(X Q ^ n!r?uBvCwCyDF0N)Zdlrttsrtttuuvvvwwxzz{||~,=ACEJNX`ilorv22 H@\*\ȰÇ#JHŋ3jȱǏ CIɓ(S\r0cʜI͛8sɳϟ@ JQ[ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷L!뮺sͯ;&6F+Vkfv+kcs o 쬸뿏RոӁPcO(ppgw ,$l(,{̍B2&- 4w N\Q@-Dmg8r(=0PC1NW3W'-v`Pc65s`=l@?1x|߀.n'Wa4.'h堇.褗n騛RQGwS5<.aaM4O?'?~CȻSWogw/o? LC4wLOǯ vMī@X<"0^/Yx hx=8_0aC gH8̡w@ H"A91s*y +54|Pv4a`pH:9P =z4F|dFg,$yg=$64p0D&IRL*WV򕰌,gIZT44]bb%1).^2vهXtZ VCЃ/ )"L:v\e^bS0e>'Y{N2j'?IЂt/.HCclpKIJt6nF3%\a_ CyЅaGKҚMjW <+.ʁ ׊sXg[[s6Ȁliۮ}W ;r" qFpkz/b)B 7*:X{}WP/RkVocҶn&r:V y GL8EF;^mLuod#З@ !8>_X-p^]wUr3L*oȲ2r3(yҲL2hN6pL:9qg\t@31!hBYEmA﹛'MJ[kE,|NS:Cm5,js{Wb^|fݎXָεw^MbNf;ЎlXT`v3lns6G)Εm7ڎMzηf[ھ_o/68{mpX;6쌊;7{ GN(OW0gN%7qsc.@o94!Cxᒅ$]ԧ~XϺַ{`Ů}(ޡ}C:NlxϻOO;񐏼'O[/;1c&rG_ OWֻ!+S!B.Dv;ЏO[Ͼ{OO׿~W@HOC 8/8Xx ~ W'؁ "}XE#G؂.h284X6x8h%XV 9,B؂1FxHJs/3QȄ*CxWT\؅^\o/ lPp`VlHzZpr8t(6i < uk؆8wX} xfxw}hjXa} i i`m\ h}h\؊} \pmX}芸H؋.b} hPw`،X^ÌQ ``88+Xy`Y`(FqFHPOPY5D!T||hԘ I'X) ِ# ᨌ'ق爑$ #IčMM X ђ4i=tȍEɏ9 >Y970h/K eYHHɔg"R9q\i PIȗE) WyMH}Iّt;TQ))S6y}IzyuБO ) 8aUyfxI)`ݔМMۉY鏂9)`9Ii+iw_|47iy2Zyי_iҙ щ  ʜiȠҟ0:0ZɛA Y>4w(DΩNZHўIYu"bZgYA~i|q*Mٍ9yfXOj;МyJ[q; ڍ{ a#dh/|g/A (K M{ajɪ Ȫ9鑦 ٤[V) @B4^6~8 )݄](pl}䡐}( !N lH p( I.hjlnpr>t^v~xz{=%`Gi( hNf~h!Mc^\噰Mԟ^^lm窾~ |V-HNXM!!Ԉ.Hp>^pn7k^M.ŽՈ~n\~5 nV亞>( !O g l "?$_&(*,.02?4_ o`%#\ . C?IO 6\^`[:O6Xa%PK5vg6ZiZk6[m[o7\q%\saeZs߅7^y祷^{tEb8`=dQteaxW/Jx7cO ⋹w`OF9 ~dPcgfo9gwg:h&hF:ii㘕j:k뙝j9KVlF[]m߆ω㦻n49No6e&pspgdp'_+Hk7{jI|'xs}߇?~秿~?`8@ЀD@u``5AvЃaE8BЄ'Da U/ a8ʐ($õu$! BFq3{hHM73lG<2vP+dD~S DYj ;8 D bhXZӯ+:EL-QhtL Gmj=nի#)Wc;[P~SN T  YcBje k>Jѩ,mmj ;um]Xé òi<ЪV\ 4iL1N\F` QZBv;p݊\50ծut݇E)QZ@Y׬VŀF]mV*Ջj`-Bpec; 죬ԫf夆J;uAT@|1P`X$*m{έp 7-(s P&Xpm1P,,u 2Љ.UVޭŜ,zBV΃p\J>WUSwϞڶ1( _ħ~e [?+٧S5_<#+C<*)ˣ5>=?6= = Ĝ0@MQKBA4#D$T%d& t()Q H@x!4ñx3PsIK;79C:t+B.B0C CQ@4`CCC9:tG;B-/ C-*M$MEPQ7SDE?2@X{RlC[FL^(ZEJBpE?EZ4YDFQL[|ƹ0_j<`LAO K4F@\!&>k4si&kB"vDw`mCLpGqr8SgrG#*ȀD:\yz|EpTƙ:*c.33$7l <*-H&34I$˧D}hI".<ctا~ɽ2wʰPȐlPH7c+cɧɯO\Ďګ梪 IHJt69˲L7hȍ !llEoL?e]lR))ЇKlkʽ,,L'˿ v'LÌ(JjJL\-l̊δ+ I+L<)SL3+Jxz')LJ @MД̮hOd P* MMLIdN!CPI;}I:Oe sQŜQE"O!{KPQۤ(}J#KtRRQ)E M`$-M4LQD z֜)R5eO4I) μRs@Rm@N$ɴTԀl I`hOTHȖTD2,¤`MSTyj.DҲQ<R}6sMbW}>F=1 RuYdԫLGe.M pERڒ, X|5rʫR USX}NX X: MJ&55Yˌ؏]5Wݐ x]EZ-{OGWKW{׵Pbف%e38=4 ۲M4XXNI 5`h-P[ޤS>/4,ܧFR69dPҍEPۼX;V~D=Se盿?N]. `?lX>8>\ΪD#gY&Փ`Vd~U .K^`.q@ثe^#@`{Za;a,?}h.9|/fP=jfV`ig&Z8#@ eNfNn&ofz6wzhZNe dyVh噦v.F}(mcq^膶ib+N  Pb$ު0ަN4\t>8i>At;gjfhqfgNkh4`gvCjfY^2@.Vf!U試-#Dj{Vv>uVg?^@fNk^7q65,lT-mnFv l}^g®>lml>Cji[剦kxvVnTlk 9])h?Վf~َnneKlie6&n>FWf=&l[FnS0N'\X0Sڠ\ou]MWeuuSUu}z@^I9'E࿄`2l!Ĉ2!AT8!SRRP IVԾhiJ%Åw'РB-j J2]  1 /d+`6!-k,ڴjײm-ܸ ѭk.ٰz4Il$(˖Vl "Ê#d "ņcާqe;Du˜AVXbƼV7,L~4+ CaBH p5p,M-v,Cщ[3Sg݂kQC~'r]HGuLA=z 8 q5uROE5UUWeUWz5VZx!j!s#yI_ J'&or]6Iu&sܵģc.o1Bc(Ps4xQ Uu.I8Q]`YdL>VgY$ō&mxl :pyxyiRuJ>lN6#[NJ:)i!xRQeVZq5WV:*z*@XMM"0*LU"P:Z6kBڒOLE#dx肄fȂRx];fevٞDn9W]e[1'bՋKK)` p/D*lrLJz1^T rৠEV%|2)]RTstCn2+\Kt#Ls*UCCԖϾey[I3HtY5e}R u=/Б2ZA(K7'=t awZ{3rVR(FT>2'3!TCgwvBzWZwmps^yo֚VfCBʰʱLuF;_Ȳ].K-A'W.EFO\a,-= 7WXExC"E5pc߳?tJMzqԡ7[FN*ن@gy )xLTVqF GXr1 a7~N +aڣEQd \j(ծkP $ N|"'BnD"!-eH4vǃ|\"(I1APAn$(36Eo/;EAV@(9{\o9GxY4%/AȄ4ku<,E\q#Qȝ"* 4uH:%l$7S\ g(IJ˝EIuҳ(CTEll&Y)H>jS47ye"S1Y@e'3YMV,-N}uS攓#'шF|iyďn)NsӠ䳔aKDC Pz j2zU1fkHU< DQNsX6Zt]%Dr-p?YX+zU 2*ؒeq9bu,T@.VVY[l^#ZI[̪5*:ҷӭ&m.?YV~ֳt*wh.VNTfmcU% eU R{N%} `ʢؿ.v}݉nRB7}1s\* >1,!F>2%3N~2,"gV6r#gyN2u_85~Ŭ5g/;-'PTn g y-}foɼ̀>49JU M-~NI4ㅚ˩jH9;i_WӺ<^lHw5QVOšgk\Tقv[Mi`b^۠fvik&-neӼq-oV,}7.p.npikrS&DVqIB!:n›\a`l2A q?H,|*Sz64σ܋{Uqz;dK `ܴBQҡui1:3sF6ӾSR{޹@1JBCÄw!fqN{{.v=vf?6/y{DͣHT2BO9'܅.ѫhXz,@!TIf}s^{mx]aߌߨ$Kvkڰܩݟr}GOs׹tRa 0 !Aɡ!@aŞR" HZI"M,4"$D' ILb(Vy\`!rH]*+!UXqQW{%ҢR2XRO],Hn_16c\TH}3N:P/byEXc-6.E 4129#Z@{e.1Fc=Yc22aB>!qYD"!YQ/26Z.dF"c!dEBn9dJP["H:Qy/Fd6JN$r$MP:ϱbQ.I$?M=2ecbaOBUR 5#7Je]%Zz15לέVd1R%1]G@%^>^eG&\*^!cKaaeyc>&dFdN&ebYeJ]&fje"bYg%,MkU&jJ%k.i&kUkfnnYh2;;ަq~nJo[rfNp6b>gB"'urJsuct&Rv9Zxav߅lgyF*zN#ys|~w&{g,۽!((&gY&SVVhB'Zh!Ƨvb(iz(rh h;2h((qڨ Ҩ(WN2ёR_.&[ "]NZn\n"Z~)uR*_)r隒Z):l6=:&*6iA*֣V-*n\*~~:fj*jx*bcj*pj骰kkKk6+"t:1V^ŦhjZQ+~w&C~Ij c۽!k+^+= k&,=!,>l(9ĪkV'Q,~nliVkdž,6Ȟkʶl,+,֬Ǝ,,Т >!]҆,6-bNHBjfm.mqn-R ֎mvH٦-۾:BmVm-*Z& ..*EFB.^ZEvr.Fd*.R|hnQ.nLjO.joSS"//B>/:%%V/RCvzr~/V/u>'>q//"/ko& b0å.70Z>pFK%ۮ_Rfn0Ӥ.Kp떰 W$ C0 ף . ;0O#wp31Ǣ_.'q+.16"GOV^1[/.wq~1↱ G1_qq1jC/1!O!-"'r-6#$$O2U2^2& &-'wvr(r}ٞ2*7*-+2Ʋ,-s-rr2/;/[-032r1 .33ך3C-4GMsV56'6ou~38?8-9+R>Nr:33Ƴ<==߳3??,@ A2+)B''BìBGt}MtVEYCKkFZG+tHFI2C4KKJ4C+/4j4ONc2P5L4QP3L/X"u*5TӓT{,UWu:]fV;jS;W'q5Ǝ5Ys\X'2Z5uŶ[;\K\55!5^Q]?,_uu `_3a$v.6c*;˦2Q?ud0a1dg68vgfhvGc6j#hiv٩6Ƕlk'm4kv*66o^n1pnq&rwr/wNvC_N)t?qscsg7Jp&Xw'okwwznzS{;{w7}}1~t^yk8'밃?n ~[R N&w5"Gx #뿎u8ðQ8+#~8xx3o*x#yJy䐏kgSc~qz9X095 ǹ$3?9`#y9K˸9/o+7U^ʅWv)kxsxK' :G:+%[v/N(9:˭Sܣ+szKz7zzsz[yWyK볷y;봣y7y+kyKy+y yxx꼿x꽫x꾏x{xSx?x£+xÏxċwwswoǿwcȫwWɗwS{wCgw7Cw3/w'wwv vvӷvԣvՏv{vgvػGvٷ3vڧvۛ vܗu݋uu{߻uou_u[uOku?Wu;Cu//uuuttttttot[tGt/ttts{swsks[sWsGos3[sGs33@T8@7f(@h%Px!1_GA9dI'QTeK/aƔ9fM7q|gO3uhQG&UiSOF:ȂWLÈ+ŸjYgѦU֨O;8m]wջo_8^ժC)ʽHocǏ!Gm\t%gּsgϟA \p0W_+1tkׯaϤӲ\̱qֽwƣ .qXŌ}'W<잵f>zu}7p`U>|y /|{7=+wF.RO5+ 5/ ) G 9Cl“Q 3"0aQFBoR;y챦!,w4'?r=(nt1,ӳ,BL49S-4$Q&8mSA % OE4:F!TR2TpOAR.e3PQݬSmU*GUWi@1r]y0%UXVuc5D1MYinY.V[Hm kK MqѥMw"wMsO^m}JY ؤ|. !!)aE#1Xދ=Y86udxA>YKwtS~Y[ܙyzy>V砉ŀ.סn٣-iZ^jaVkPlMNlM^B~ն[TD$u^նP̸g -\[V)'>|J9?t:E?] M_]eqoܫ߭x'}?~o䝟 _3^OՇSs1ۏLmD[G?)#{x@·~I_@ %P- f4jg#4I0xON*taRRޔP2a uCC; C!ƤCl"&3HdD8Qb3CE,[.1`$cxƾQKcGQo]xQlcG@參l iB&xdGi&H*/td'HPd(MR2)dVʶlXTb%t?ٲ/+K`ĕì0._z+ Df3cRLht4jfs%ܶMxSk g9uLv|~NBS_<;-O,K}FoT?  gpQ! "LhTzѢH IE5-zzu`>AJҥdT83)ɖt3UK-,ٔ/y:E5!tKNzTҩ)X4Q%%;՜T*Aij[U;zWX!^eW(`aBV~b[/7Le1YngAZю5iQZծuka[Ζ?<;ׅ|eɺ\Wl0q\.us]Nյu]nw^񎗼5yћuv`ԷU'_!`6`/ v!a O1a oF?ߒWk:!bXg`acϘ5qc=d!E6򑑜d%/MN!$$Gl Dp0e6ќf5mvg9ϙug=}>y2<+l:iIUґ>C1iMoӝAjQԥ6QjUխvakYϚֵ_}iI{bNH/bUd#;^miOնmmonq6ѝnuvcv~` #ۊ*@Q 4  w!qO1qoAr%7Qr-nA4ɾo5<<aԟ\hБt/MwӡuOUձuo]ve7ўݨ@NsaAS s:s Ψd.Z# :iB"@@@;Y!t;#<7DA=Y:bBs@#C@E@Q R LATAC4$`F]FtAa8T6CrF_#zB/T=5#3S#tJS Ρ# Kt:=J?ȴ#SJ`:J3NQ> .$,TCG?bOyG:PP=4#H#TC`@OO$Px2TEuTITMTQ5UUuUYU]UaUTـEE"=CtP uS?"@CVaWODABX|UB#U߼3#4Z[LӴ#T̴#Ε 5[5Z][=YDNoHX?_RvXYEaI;`oC__b@BE,Π ";{޷}8^ǷmxmZIN@@VhTxcKwR(6x->5V 9y gk5ywh֒AXR?vQ}Q'#N4[]Z#mU!^U$dV ! VPU`bAYxؔ_1QY?%hvwKw9W6VhYWi*<=S =աڴ]A UN4N<`#yYЙonOG-v11/XwR',Bqx؏6a5S:"b8'8g6X^#,FEw-⧹ /«5QYyY5r ?Z :u;աY{>S;=s:8<4 O 3Z;4EZ1HsK4Bst?[G-CtA];(nd $;IRѨ""ғBMZ@:;t:}Ը[YO;F!㚕Z1Z p=b $ "ݛ ƒ[r0۸-(>b<#6X ( ~[5|+ʌ\ Ë mǻ6ؾջ+{g|%9|ȉ\e  *UI9ʭ=<ߖ#\A|\\51՜[k<{}ݜa"ȋ<ϏGϡ|O\}й<]$<K!}<œEW[.Ry\ߜ%rWqY|}}g1=Џ]3\/%6|GW]|O=%<χ|'\҇։ }ҧ]]|_|9i4 r{2w֑u]s{}E۽] 5ߝ49̏͝Q-]~![=<=IM~}#<1;׋>R˗Qߞ"5=ג9߱O^ظ俾PBOM,~tؾ;'}ks(^xWgU~޻ciVk UQ!7c%&:?hTCsTy]Ra@sTHM!NOtSM#xI!QE6OCREAWvKK!A4 cw8i4]_Y?qw_o4_4%q#Obpub_x7H  *Vb{b`!Qz/ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3;z̦D=4ҥL>z 5*MN/ca8!:)ɔ+[RTO6$Q#hqvaZ{F z>|u67e= <ċ?ț;fTvK4ۉ_q ډ2fJz5CTոO#>} r]AWt` .xr@1`NHFIU]F>q4V D[nf /mTZ*|;"∬^,"+lhPBIdFOdN vaT&O%lIZY%f阗qӓffj%dC grT)^YW~Zgzh>\;, iRX'gw**h瞠塤~&j%)J+f>Y[ᨀ阦&*֊lʾ> m`J毧+|j[FKn;ӴU-^+nk*/ 0qLp;&PEx? qOLq_qoq r"Lr&r*r. s sEXjp;WtBMtFtJ/tN? uROMuV_uZou^ vbM^j˳H\DrMwvߍwzw~ xNxx/x?yONyEpښvHZ]y袏Nz馟zꪯz뮯^oN;{|O᱋szG}OO}_=LJޯڼGgO~柏~꯿ u}"?M~)p l<}~Yp`R&APЃ$p,D Ƚp:cR/a< qDbC5qLl(JqT,jq\$zD_X41z aGFH8:džaG q|@ x&#x#EnDN F1 N@!,PL  !!!"""###$$$%%%&&''')((*)),**-++.,,/,,/--0..1//1002112333444169/7>,9C*:G(R#?T!?W @YAZA\B_B`C` C_ D_$D^'D\+E[.EZ1FX4FW7GV:GU=HT@ISDJRHKQMMPNNQOORPQSRRTTTVVVWYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffgggaioUk}JmAo9q2r,s's#t uuuvvvvwww x#x(x-y3z;{D|O}\k|22 H*\ȰÇ#JHŋ)޹Ǐ CIɍM\ɲ˗05I͛8sDQϟ@ eȳУH*=Y4ҧPJEԫXµkW`Ê])ٳcӪ]K۲lʝ;[xV߿OLO+xd e'̹͞CnzӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\A2]`RiJhY#&q& )Нxvoyџç:١J?0CN4?é -@1˨ij2--X+ܺ*=@ɠ5/jc0P@!,>&     !""#####$%%&'())+ ,!!-"".##.##/$$/$$0%%0%%1&&1&&2&&2''2''3''3''3''3''3''3((3((3((3((3((3((4))4))4))4**4**5++5--7//912;34<55>77?89A::B;;C<=D>>E??F@AGABHCCIDEKFGLHIMIINJJOKKOLMPNNQOPRQQSSSUUUVXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22+(G*\`JHqaKV"CQȓIDɒʕ-cD௦ d|I0H-ytI5)pK,X㒫Q6%XoLfi=¡B׈~-Tf5vYJpl rΚOڌ?Ȕ7Z9Θ=7Y胡M#$M0ꂬ9V={k mߞݚwfd ~uoˮwF[M楋]j>'!,J #wxwwwwwwwwwwwwwwwwwxxyyz{|}~              #+27;>?BFIJLNRW[_hsz}{xvvvvvvuk`SL|JvL}TduÒϐ֐ٗڙۚܚݛݜݞݡݩݲݺµ̺ѽԿ22D*\ȰÇ#JHBE6q䉓H,I'(S\ɲ˗0SI͚3o)(ϟ@ JѣH*]ʴӧCiEjOAݺuPΝ`ÚKXhq]˶۷pBdnNߗ_ nxA+^̸ǐ#KL˘3kfɮg mOV1װc˞M;3ϸ?-4knsȓ+_μУKNؑ'3'D[M\l˟OϿ|"X`&%yt^B M3{+-Y\^%ah{n^5H"y{7M. +3*=\й-#3:]QsyIo?n}2HPqX.%| sK 57yT*0g 0BucPRVXZ+|!:BPKZ؈߭P 8̅yʐ<y\5lDtCOtbqXv\#~D*ËdFg6V\a(#(*X̢_z?qB MlcF:d4Nw1Q%Tw: .ʂ4xɗ8,PG#22pQbPr3r-mY_ԥ k%2 dr F/m[#fp.Y as&2da3 '1jj qrPs2:f;9gȨ"5OԠ0EA参r!@'JъZԢw(a8i4ԟP±J$]-RRˀы0xF[ Ӡu9PmԋDuM}J$@54T[WU^әV+PSF`jSiWiw*TqNϋ((iJ'd02W:}񋨻S~GOy85GO8gOϽwJ?#h={8χJVXϾ{Og>UC :?U0@8Xx ַ G(8Xx }ȁ(*,؂. ̠}'8:<؃ 28 $hHJL0` xwMZ\؅ 0h|^Xfxhcipr `s|؇~h~xX腌!,J E  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[W^dTalLf{Bl8q/u'y!{} "'037?GNU[doyЀχΌΎΑ͓̖ʚǠã22 H*\ȰÇ#JHQ!3VȱǏ CJHȓ(S\I˗0c>bI͛eꌉϟ5 JhQH*hSGKJաTj^)^uį'[Ӫ)Fp۾Oh߿UDX0nD1a#/4|2CG̹Ϡ]r=|(k ɎMvm|d~[=HI7!M^U(A}Z,]=QC.VWW}𑺟O~}^=}'Mހd  6҂9(!J7v! v̈$h!?OY0(cE.X֌8R";b@PC&i #P$dTViXf\v`)dihlp)t)a_C䩧w*f衉*ZР@F٤"j_Xku>ST7HC֢.a:?V« {j0K*9 Dゴ~1?3p8(t C!, >  !""!  !!!"""###$$$%%%&&&'''(())))***+++,,----...///000111222333444556666777888999:::;;;<<<==>??A@@EAAHABJBBJBCJCCICDHEEHFFHGGHIIIJJJKKKLLMMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22۷O D A>80BfLpcŎ 1NQŒ&IRԘI eb Ëь`};{N ái 3KL*= -T'M0ِ –-e h+2 aNXK*LkpȂJx c!,J Qxxxxxxxxxxxxxxxxoigioxxxxxxx|              ~}|||}~,~4x:u>vAyByDyCy@z7|-~$%.6>FLRYbkr}r{szsytyw{ׁ؎ؗٚښۚۚښٛ؛םצװ׸ؿĮɱ̴϶Ժ׼پٿ22+H*\ȰÇ#JHE2jȱǏ CIɓ(SfȲ˗0cʜIS͛8sܩϟ@ *ѣH*]IӧP\JիjʵkS`Ê鵬ٳh]˶mִp궮]#;zH`^"l` \!1>\@6 ,+!&0[ +ֶҧG߮-P;؝wY2 |]Ο GX2`{˽;ς"i,\`ūFtٻBF/0|pԥfyUvz)t=gl g1V`0fER`Tv]y'(9fK%%G@8/ِ8e裊)JZt 2gTR(hLt_H$4eDN UˈeѨdY*k*fe0X g)ittByeuyLdHaf١:(ASܛ6gK+@ g߈æ{ęʲkzYlxPwmjgQV0wHnaRlN؉Uݴ]Zm`*#1}eŧ;Ř|Ҷ0ǣ8|hfK|ᆠ'Ohz%bAo`eDUSI3Z&Ӓ,K`R:0! wH Oĉ7Ad)G(?$$L r0 0&K aZh?"HDͲĸ41PS JXt b,z3٢2"b˂)m3q!Li}IWaX=:> ml#>xN#Z⠳ CIl2 5g m~sI4{$Hﵪ}y2w0:@8W"&0fEOtIC:hHY'3PI Zfc ɡ@2\N<:5ne<(r&d4MV6DᏕ/ѧI"!IrLi*9.:FMD1 8Xyb3()Qf:ԌI]VRRz1RB'm4OCVISBz٩ZGVZ.4U LKS\Az&Fxk]e^.jxiuVuX ACZuVMQ2 u6t=4QӔZĘ"".Ǿ el,Ok[$zt2Ʋ/f%3؜ׄ&zQYrVlG-m^L՘ZL".q_#`|֮pk%69TA^n% r,V3UH V1: l6:Qt5{)\[&W츭Roh !й7'm鰞H|wyϡgkzrbJu*`-h,}aNTYG$mrVӵE83I}| 7‡|ɳũyt$4c!(t^ߠv,[ԯ r&Qg5 L)D{QюpCNˢk%i`NWDLmn\AX4qs\̖Lۣ|هroD -VL7О[nKюG]6:{l0W+QGC<6fo֠)#TU9ΉujtF8ߣiͼTi~"hPjkGnJysp`Mm$I)]]H (  9G)K$[gN &2x0|@bϋCaя&&Oy gH[} {`NhOk|+pOO;;K$ ϼ7{1t OWֻgOϽw{݋^{OO;1B!O[Ͼ{O OϿ' x~C\!\P Xx؁ "8 H@(#pp4..8IAU+908Ã~ !YPP EJL؄NPR8TXVxXx^WȂ2j0|&P5(UE71gg_! AF`|؇~[ȅe]AB7Rgш_"a!WpаX  @ Xx؋88HȘ( $4E[yxJ78Ј1_tf$P `p UX8؏9YyIH ِx(Nt\ki_&mZAb&*+Y Q/1*y8:<ٓ>@B9DYBhJD ёxbS[eƑ9QI8,fa+)ْf hY  LٖnprHsyB Q#` (|Y ᗙYɆN!h 0Ip ٙ9Yy)~@9z92a3l6fdk1cy79?JàIiJ 9Yy虞깞ٞ隯@Ykn4  <1p" *UMa2EPzڡ ":$Z&Z)'0sAr :<ڣ>@B:DZFzHJ:*1TZ>*6J AХ^`b:dZfzhjlڦnڥN~avza ?Y:rp:Zzڨ (ϷZ!*0Zzڪ::YRZګ~@+PzȚʺڬ:ZZ+ @ຬfЧ A`pڮ:Zz &z Я[jscWװ  wp \{za P;$[`&,F*I.;4[6>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhdjp_mxVpIt;w-z!|}~~ ~ ~                    !3Ov22 J1p!C5#JHŋ3jȱǏ CLg(%Ӗ-6oGʜI͛8sD,eʕ-[jѣH*̧͙OA[~[JիXi"seԖDKR\z-ٷpʽ,گA˷Xd'\֭Èl*x0ޠaKLcPwϔ5v87ШS0[հce-.emUtbǪ>ͻqkk3&Уd|y󨑥kߎomGm˽ᣵu׾'`t9UČ3Ӂq>(ŕJ~O?S!$fBӍ7|"R⌼u> 4SK?㑰u8/HF 0KӋ8b\J 02$]IY/Cl"$/)t9._%/v/(j衈&袌6裐F*餔Vj饘B" ʨjꩨꪬ*무j뭰駟v+k&6F+䩞nv+k覫Ղj?/~T栗l' 7G,Wlg,qh,$l(,0,42-0#@ߡAs1A?4}PF@At+Cc Lt_/-G3N3ϋL=4M+"JUK-wd+] ƍp'=7m e"s΍v₧4xa=.{+b<<㱎>s#=^O}O_ﵫO+?}*?KO>s>ܷr[>N@za` uyD N @8dx,4! BaH8C p͓*̇?ya mXma"lbmO =!=D@naQ@ 3a !o7V[-m^-ҐǘdGͱc!Dְ!ݡlXQF4|+Y!A{,aG<bA d.H,̃nZc7`j6ksT&3iN~C'99Nz:Lg4|A|Y8YNks:1ƅ (?Y  f9M!TdgAWb)e*iNkj[y=iLiS g0jR1EeO; U4=RYӉPCy 6uTXU,ԭaUR UU|*VŪ>u렫\,uWjUuKEӤÞbibV2g1ЂE-XgC -*L;׎,fY·;mmaCƵҶ mgZȪpor.pOVW2\zlf[Bv!yD7 Efo~aH; ~p{ ^0}gN,Zt 0+ Cx&1 v0< `B谯NLa G&iXc ³ q{|0s <3]ߜcYrFlg4[ 8ylNhEX=g5KυV H7"3~Jɀ0fq:ҬjEv=H=in4 Nf;[h^ųi[ζn{1FNu9*ޑY;h*~~w pu \O+2i&N[ϸ7{ GN%Ha0gN8Ϲw@U.FHOҗ;PԧN[XϺַu$\Nh?;!fB,pNxϻwBpOxg'O[ϼ7{GOzϤOWֻ?=gOosGO>;?O}G_.{<_8ď ~8~GBggg 8z~H' y}*'%XKÂ6x7|k31h3}88x}DxH(yFL8K؄POTX.XX(W\h#х`8!,e  !!!"""###$$%%%'&&('')((*))+)),**,++-,,---///000011122233344455566677888:::;;;=;;><>A>>A??B@@CAACBBDCCDDDEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOPPPQQQRRRSSSTSSTTTUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmhouer}_t[uVwSyL{B}:~4/,)%#! %*2=J\n}{x~trpomkjhgffca_\ZXWVVUUUUUUUUUUUUUUUUUUXcp|Ռբױڿ22 TZ|E+(#JHŋ3jꕰj CƓ(S\900C#Ų͛6Uɳ1U8 Ξ<"ʴJP/fҩիcI ׯBݚ4سMU ۠"^r{We<6 &آmո[Iy˲g2kN ӢD)iZ^ ӡ l3[`foNwѩv-oN;쩈.Z0wGG77ɋS^ȫؿs*'#Nڷ?/| F pFݽN?#"0xhRh:Vf|d I^`C 8$_JdWBI]c|Z[4Xcgp)tix|矀*蠄j衈$ɢ=$: 饒RDi^imʩ* ꧾʨŠvjJBkqhjl:K*J)Z[ꭽj**;-z j n~*zjn{o+@m0Kt GD6 +1E_r@!,LܤٝߤüŮϥܠzmeYNRV\ǫը٢hҘT͏HŃ9w,j\%Q0ODROx_`qkjqoppoppppoopooolno`lsHiy*e` [ K<$~umg1eK_[YjSnLoGnCmAk@j1ge`P;!   $##&&&')))***********+******---1/122222222222˘9F7pș3Ç#JHŋ3jȱ#DFCzɓ(S\ɲ˗0cʜI͛8sɳϟ@H19Brsٶh~n#-$X3=d}w'~ ٻ{uBB˭lCSQb#u2@,f3M: V @er/+-X&y:^E|(L W4ꅐKCgk1;`z@^kܢ#y7m 8$IBYg $u=;򕰌,yGPmc ţ7k: X+!u)т]R:hS_l̓։(Jkd4'iӑmps883x/:pgt՝ji0OQަyojc.dz\;4ٍ[i3yޭ~-u9[5}ݮeq)i.m7gǽ~{gav8*E\CMO'OaUi̡WOCWz [Ͻ=_,=ONO*3Џ>k/[y>ǯxO/b?OgHϿYXxch ؀A8x[؁%o8$~X(w*؂.8{,284x8u6<؃>BHd@8FxUHLx\J؄PRXVZTxZ\`xX^dX{5fjV` pՆo(vx|E|؇l~xV8xXU8S؈Ԇ xXG؉޳88xS*؊X)xh%XL2Ƙ#X{yX8%xڸzX7明"H!X" x+؏YI ِȐYH҈ّȑ"Y%V&0.4`/Y:7;8@9(DyhHˈ>ɔPi$T SYXYW\Ʌ[ٕ`Y_dɄcYh9glɃkٖp9otsYx9w|y{ٗyY X 莏9K؎yRhǙiXB 郚yIقI99|y{){¹z9yyʙxɹyuir9։oy9hٹ9d٘9y蹞ʧ陒 y{YٟǟZם ڠŠZEڡ~šw"Zp& *"o"4_NY8 ]$谈G>{#+Cۯh>H>  +Hg>Z\u4 6{j:d˴ !n+e{u; pmz ~ 0xkkVw |01P u -[x˱[ Z0;[{țʻۼ;[{{ۖ۽;[KK˫۾;[{ۿ< L <\| "<$Ep(|5Y0 4p8,:<>@Bv-E` D)难>ꤾ鱐Vn .ZN Rp>楞맞홚 Nܮ^@럾mmP`u. zrr1 *|@P=) Jmp t?_  {^0 ĝ_{ұ. O P u$0@ɾ ]/2 `@ |@osQ6 ;)^'EPfhjlnpr p eO w P°s/upp~pw/ _Pz / P_RU._8f`T_>K!Oa?[ sڽ^= i6#p*_?%O@ PB *DX)RF-~"G)#6l֜1C'Mѡ=}TPEETRM>UTU^XX~VXe͞EVڨ 4x@B BH!C 5- 1ɌFhR:f ᢊ 37j؜9SLEpZj֭][vYPƝ[n޽}-ܹ4=G3nxtԿZX ?+ݸ)fizAFzV#C4C3pB `Ha4@p r?BFWӁ gX0a@$) ҄g\DyIBCa sBaH DpG+' s?"шLDЉOb97@ӡ \`gwK@b`!fQY0?%.q-c9΁qY0< qx E%PGNmk`Npmr< 9HGVi!Htpk"5l8(Ly7]'4!uuK]&&T8LbT,m"p,A-,8 1Z.6aHG3' qZIGqrD 6HbT;W?* m ?'NS64c*Jt~ahfYC fHE8_Ԥ'1URNVD2XXhBU Kt&c%G  @WfhFx:MgR *Ԧ>5SU - Q PNh!b^49a;\ԯuWI;X԰K ,6ap:-"IvTld \";ց@0FakW`QGUӢVgN&/Bm[+1Fs+6K2 ;]BJ]Nl*NʧBN kl#: C4. dѵg@ם5 n 0٣@^iWRnvEryT|N, 8;RՙTl,34 2Th7}qT8M*ùJ2[+8g%2HiQZ 8X If2)!̽F?ݾַqUn?f#Ǔi#[`-aSV6d'ֱ.d,s[m)wܕ2LuP Q'Pot™֛*a.$Ӊp7bF׏g1qxx tdȟ퓧\+ȓ\dl<MnZvw,rv|+෿M2'cjnOxuw͕WrgѾv]Qnݒir";0Ʋ6`v\uD>iWw?/n˼..lw@+FAB Rw]my|nj;1aH,q!f{uliv6a˧v42_*G?ɄG23/c ['w\iě9gksĵ@P4*ㅢ6+۹乻[>;$#k+̼d1,:s33C NH5=ҿ;!$B("DB93*-{1,[O@2 *@'9xS?!.r9c`+-LBS``:r: =\;=YK?ć8@$Dj+Mp<";/+AHD'A[DlkDùN|Ġ;7#9C7l+Nj7G8+}: <\E5+`AbL2:'=KK`˽tItH˼T`K\, ”LK-.ü ܥƼK$M̬f:dB,$"Ѥ$"D@DHEPEXFN}V DTNʁML܄DZΥXNLMٹlΓϛ4OεγLtϴNOw)χxϱ\Օ4PИu&ʈL Ќl  } %EOEUuQD |Qb Q RT1 &T1vd2hC&s1%mk,v\213>2+kDqe"S2|lod1(+g;%S2%7g[Te(_{<TI;dSg+8ۇ; Z-@Ŵ9iĜ2Hm!';fV^%֖rNcsTeXU9cU@kn>[ƝMNuDKV-@X)#YZퟯ-mٳ=Eۢqd*qTt2le~Yd[@[1[B_XUڷk FKZreݜ*T5&,۵%]ap%|1 C'BPW5VɁ>BaB=ٽFW3P֣3CX=ѹJ6lB2m7 w4D%[ޛcG fkp#^=] ΔQ_޸MCDDE ]rnUQLAf <7 LF+TaQTsM`,%+N],vIuFGr2Ż2ö}F|-FKF>(s7&@Tȃq-1Ud>?V7k1$<]aF.\|GJvdj^wHM^*H+Uf -`VNIϽ]S?ZڻImP1D]>]?,td,df&}\dF<2;C[33[SFReXpp╂jX+lPT Enؽa՜Xee"^]4_K^Q=Ғ 6ƩιR,*=ZF m=d6^ #Vc`덾1!k4?@s05J8 Wtsܜ:AKLM/(tFOlF lJVwWX7sO7d.u&\,mUguYa'btZu!P^w]gvJ7jk-G gig'OFK0됳iwx'mǜnwp{&PaJOnt˜tjWtz{U%~oF]Uwgr/LeQ7y&UB-Yl,ʁ_#Z9FSrjtn'yX'"(;*Lc>*t)'6Z!wz|7uz)d_FYWݦw{yf;G?nN{_{{_r;?+{gΤos"{&ǜ`ħwG[}!:t|D/}%/|Vw?{ܿ|G|_v}ɧ=N)<|+w~~ڷOYc4%ȑ7d`~t~g>{g „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ,h@B !NC 3o 'Pu)jhФJ2m)ԨRRj*֬Tr-SdL/JtPq" 4`.޼z/+`Ċ3n1Ȓ'_dL6qthWZG.m4Ԫ65زgӮm6ܺ (7‡x`ʗ3o9_ƜYfΝ=n;ǓںbɚE[rڍn>x? 8 .6fmg]yJ8!6uW`[{w|8"%x""-"!Xfu]S݅f!=#izW[|ѷ[M:$QUZy%UΘuiك;9&e)Dr8{ɗ[}Y9'uGy'm_:xz(yhH'}J:)Ⅷj)Y fWz*Y)!G~撝:+bZ+]2#S:*ԪjꡛJ+J0 6-j` &NJ;..Udm&bۺ.c-r{/u Jζ/ ;|׼><1o.%,{q'uͲ)2C21B29&rP$3.2 =4.}474W >kYk[{K :jQ}SST> 6qٵu=nQh7 y%݉+#݋;xyk}~9jv'C96:'bbӚA>;ʍ^;u\z;e>Ǯ~ۺ+"MO׫olZ?E?|j=,js & PDXB,|a@ʍ6$D8Ys0a\!BNAaQnp܋8!Jr3"PX%rBM(FQqfL.QB_|_(ǯqvdY"$ycewA<(5dIZ̐HGr4La0){Yr&Nr4DO)irT*!]& }xaB}Hko{Ou7(WTo7Yx۝_w?Iً߃,oKc3}Ig'F%~׻?:"_BIh0AE  OuC9VHVQ6PmbώtC(}B3`$u(&a}B9T }`8E8M_ɕ5 OZC@ Zڔ 8ڛq!6\|-`m(2E>9!O:J$B]aba5Y=f->ay 6 2 $ `VX"_#$R$"l.r3b ޚ.\"+&bW,⻽"Ѣ,͢3IBY9OC1&F A#;%ބP05"0feZ5/bڌba:+^3#&C˹%d!Q)!,F%AGN\yFf"#2$aKR-$G6dLH$MR:$pd ecCQ=%!uR2e8TOTn%$VVzt%YXxYBYQ%7%V@%PG¥%_֟\%*]d22%c``Z"=.Sa [>&8&fZ`dReZM%Nn& iie<Xhh:QKiҋmQZ&TnvNg&oe rLgfqFZMfs.sfl{ tduu.&wvĜcxoޓR'}6=Xac||'ুK2ƙRga&g ^8ZIJ,2r23.l Ǝll,Ǻ!^b(lݠl*Ž쮔ƈά,Lr>n.BGJ^X.瞔~&e#,~nx.*G".GήE9.*h&hnV-*&nȮHFoo ܅l& /F^/X/JF~ox/>F/2FR/&F/L.J/J0~/EO?pt80t:n}^0X0E0s0 WVQr'yp0 U /ðj  0I0oG&pp*$#'W_ wFql1O1Fqh1C1a&U%rTqcKWfb cE 2a2#3W?rv%c\U&rL%WDF82+)*(2+22-C-2.O.r+0/h03r(O.21G83MB353_5$6gsIl3%w3F~388?29'9L;7!'KM2s3> :c;3G3#33@@2A?tF$ /4"6C׏>WF3ֳ=C/IobtZHD!ED@tJCKK LǴC44N3N1OOB55Q'E75sL5UWU_5VgVo5WwW5X_F/.TWSurHuX[5\ǵ\5]{Ys uu]5``6a^uZpua7c?6dGa%mb/_1cK6gwgvWG_rdvo6h6kg] vqvknv]-m7Ub7j4o7r'w\4qmK&rWu_wVbՖs#pwPP7v7z7ef^oD+R ~7788'/87xA 7}6||" A|88888Ǹ8ׁBP8rSF "q4e8WH s'#9GՒ398{OK F[`wwc9[87_yɚG1'߰7$XB&9::%DR#GO:W_:g3!>'/o,TL>W_>gk~pC$lWݓ'[͟T#>>Ǿ>.&~Gd8~;h'/??2?G?W?~>d);{97R& ??/T/?? W% ?@h8`,"TPX2 F("A~9S2T ,eK/aƔ9fM7qԹgO?:hQG&UiS7ciUWfպkW_5e*hqB JyDwջo_GpaÇ'.Eº-/h1gF., @=Z4`F3>RVv-n5٬]#$z+^̸ǐ#KL9ysϡG>zu8N{w?~hٳi׶}wnǗ?׿*؀oH&$KP@l"X:A )"p$84C.@4<(C Y #8$H2 % R!t);LR%l'{2-r .O-RXS1,0u9PL,QM3s;9Ps!TpCC0?dŽdFpLnG()K1T#5OA UTDtUYm5L~X$gYy-A` aa-b14MFPQfbuYC#9VcCFi,Ft\nsMWuwWy*Jl}eX .`6v@]4f׈`aLD?iOp)?bF.pޙixݽYyR{ӳ,-Xyn$ih^Zk%[ǮH&"hR?N[#!oOP.I}N\.!\|>Zʤ@]I/]t^t,6]Aoab`îkS@gn}{@i;=xQflRrc\^ǽ_ߡU\=Ꮯv۽V_'=PQzE>.5_!A |BK0LAB%4a yp;"0p aCΐ5 mMpTd6A!Lz`D%Wh UCδ%^R%C0{K4#mtUu^G=~Pb '\cޘHE.R(kd#!IR-,S 3HM{'Oh 0B0)QJUt+aJȀ$ JT#}La.11#JA%"aB(ȄQAVp0"S4g)?њ$, yΓ=O}] X 5AP. e696қe5&M= g`mpΖյ.v{]nw&f[S' z qћ!`045t]n7oa!@N0p^.b/ 0Q4z1lflY*{R d``>DjWZ$(%a8>!.pH1 #uxCK ]:1Vg 2e6ќf5mvg9ϙug=y~+k]f_vSr NM y@b(!E(bAjQԥ6QjUխvakYzӉt!?Ё/ ^_&=t ENxt0=!aimonq6ѝnuv7-@zs+R–Nyl٩U`"8 kh0:x 0qoAr%7Qr-͇:nh|&Ǣ9/s, Z8/' W >:AUձuo]ve7ўvkmz09 jXs ]!Ơ LN"%-Eh3A m:yoAzя7Qzկw}7Խ!Cޫ~V1mၟ;YΣJXzpW շ}o~7џ~s_ j`m]"=w">b| !0%p)-105p9=A0Eנ ʀ <"RKج l0u >CXf@ ` 0 p 0 p  Xt^ CLt0k-t@  1q!1%q)-11 ӰoڰްQQr0Y1>PL0q1uqy}1q1q1@ ^ NgVq1S%gu`ٱ1q1q2ѐO "-GK1!g2"|lCLlх#lp1@{)R"U] r%]2H(-btGh'y'}'2(r(((2$EE1!$2%SZ*2*3:+s???4@t@ @ @4AtAAt3=Bc>-4C>S&#CA4DEtDIDMDQ4EUtEYE]Ea4F?T&iC)TCqtSH3Gy40mCi4HtHHH4ItIII4JtJtBSG904K(~K4LtLɴLL4MtMٴMݔC4NcKNM4OtOOON9tP P5QcPQQQ!uR)RMSR-5S5uS#S9SA5TmSETMT}TQuUYUyLU]5VeuV ViVq5WVuW}WgWuXXIX5YuYYY5ZYZZZu[[qfG5\u\H[\5]\յ]]K;u^^E]5_u___6`K^` `_vav^a!6ba%b-Z)b5vc5c9cAV=6dIdOudM6eU6SQve]eeavfiKefq6g-fug}Rgvhegh!6iipi6jvvjjjvkشk6lwkŶlVlvmo+mmᖰ6nnjn6o6Xvoo owp p7qoqq%wrq)r1Wn-7s9svs=7tEo vtMt tQwuYpUua7vtevm"vuww$wyw;|7xxcx7y+wyyywz(z7{yz{W&{W|w|7{|zw}7y}xw~v~vwtsx r qxp%o#x-n+5m3x=l;EkCxMxjKUiSx]xh[eXgcxmxfkuXesx}8d{Xcx8bax8`X_xa_8tx\Ÿ[xZYxXWxW8VxU9Ty YS yRyYQ%yP#y-9N+5G3y=9C;E9>CyM99KU0Sy]+[ey%cymYiu`ky}{9yyyyyتвyUsyXyٿYyyy9yWyRz  :z%Z"z-X5zg3z=>+EڍBzMJURz]zZebzmZ|juz{rz}:rzZqzzg:zz]zzTSzRIzZIZHzݺG <|ټTa\|A=} =}!~=%})-1=5}9=A=E}IMQ=U}Y]a=e}i @$M Ӏ=؅}؉؍ؑ=ٕ}ٙٝ١=ڇ}ڭڱ=۵ڵ۽W!9 !,  !!!"""###$$$%%%&&&'''))*,,-..000322544866:77<89>::@;;A<E>?F??G?@H@@H@AI@AJAAJABJABKABKABKABLBBLBCLBCLBCLBCLBCLBCLCCLCDLCDLCDLDEMDEMEFMFFNFGNGHNHIOIJPKKQLLQMNROOSQQUSSVUUWWWYYZ[\\]___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22MG*\ȰÇ#JHŋ ȱǏ CYPF(S\Rɓ-cʜI3K5sɳM= 'PH*hҧP6uUS^ʵh֮`ú*َY]aӶp2|+]^ W#A|+Z†+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihl$3bFby'Az~'vv'J(agϣF:Vh?iAiĨb'= n'(ɤjF,`g2(c !Za?-X b8CP@!,6     !!!""""""""""""""""####$$%& '""($$)%%*''+**-,,...0112444555666777888999:::;;<<<===?>>@>?A?@B@@BAACBBCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22G*\ȰÇ#Jt(pċ3j@CIRE%S\?,cʜiK4s Ο@MzњC]SiEP*95ՒU}^݊ɊUcرh/5[`o}KW-Jgev߉q LÈ+^̸ǐ#KL˘3k̹Ϡ o:K/꣬[~ 4lڵƭӶݼg=;87?p˙t[t!{I~?$!" @j513*a!,*$"     !!!""""""#"""""""""""####$$%%& '""(##)%%*''+))-++...0002334666777888999:::;;;<<<===>>>>?@@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22/G"c‡^0Ň):ȑ`F;~Tȋ#xRaJ-]I1׮bN;u`P|HsL~P4<ᘱ Wk@Zѫv  d54x a5q7LPdȖ/ͬy)??)Zq]?c漚ŗ_S<!,6M  !"""'!%+ '.)1+4,7/:1@4D7H9K;O=S?W@S@M@H&AE+BA2C?5D>9E=>G=>G=>G=>G=>G>>H>?H>?H>?H>?H>?H>?H??H?@H?@H@@H@AIABIBBICCJDEJEFKGHLIJMKKNMMPOOQQQRSSTVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~}{zzz{}пպڷݽ22 O*\P!A #JhC3xQdž;~0$ɓ%E\"˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵpᒂ {t,٢fM6Yo1-M۸my!ALλR"J~Wb0i؍a#zĠBqWr̊84d')|X K B:rI1BWޖkiz Ցmc0)4^MC a=:ǭ}MíM~H'`6B8 `>U's)B61%XB3>A>?B??C@@C@ADABDBCECDEEEFFFGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22G*\ȰÆyHŋBㇱǏ 5ɋ"#\2HZ82"e鑟ϟ?y ΡH-i¥LJTU^mZuԮ^ZVejM'۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸s{^-nق"Q 9Fz铭_7&YbYG_O1gqz9~-Ÿ? 0-sM c0 !?HYB/*# !!?0X& \CP@!,o%1  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555667777888999:::;;;<<<===>>???A@@BAADBBECCFCDGDDGEEHFFHGGIHHIIIJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22͙G C >XE31D =:G$I \{0cey8sg@ѣEm[ʴRJړ XV:^LG ٳ[[.spϹKݻx˷o ^o?†v{#b omyqOʕ.,U%pވnFofM 7^c9rYac8]w;Lfbk֏ȧ="XD?i) Eh%"!,f)P-   !"#$$ % %!!&!!&""'##'$$($$(%%)''*((+)),++-,,-...///00011122233344416;/8B.:I*;O(_"?c!@gAjBmBoCq@sDtDxEvEvFvFv Fu"Gt$Hs'Hq*Io-Jm0Kk5Li9Mf>OcCP`IR]OTYVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22G*\Ȱ!C_IHŋ3j1"Ǐ C(pɓ(S\ɲ˗0KI͛8ss> JѣH*]4PPJj?S3 I(< +SffN,Y`)V)tx˷/ޱb&"~+{O~M L!k؜ϠCypwס9.G۸sӖe`Mmʑ[μЗf.0XYEνy9O-7{FOOV^g8DN7 6F(VHa͆v ($8@d,-Z` 4h5<@7"HrM6D)TViS\ve6.xs.fh7Q/lex'ᐈ j@6h&裔VhZ@'覤>کvO4ꪠ*0꫸ ծ"M7$ 멚(0kd--+bkPq?TT npn@YHO1+./.[P?)+/'0B0Wl13[wq"##lm2(*22.c@6L6#t3;!,f(P&  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<>==@>>@???@?@A@ABABBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___aaacccdddfffggghhcii]kkWllQnnHqqAss:uu5vv1ww.yy+zz({{%{{"|| }}}}}}~~~~~~~~ ~~!~~#~~%}5|FySy`{w|ɝؠ~zxvuttttsrnjgfeeefedcbbcccbcd22%:*\ȰÅ < 3jȱǏ 7rb,S(S\ɲ˗0cE.8S֭rܮI%\ӟR)jJR,=VV%2׳宑vWhϺ]۲-Vh٫=} DݯcN߿}.0U\9)1zRViy*8 OѤbE+O4q vJi f(EgC^U6ոk>@+'^~#<9˗>[7]~OX_a=%oa݄X\&S6ԙrIB͆ӂTRE!yt8(b#L0f4!LC:a($B4yc5&b70CFF)eCd7^̖<9`5t%7PLA[2#a)AkxΩ($lFiH B6ڐ ?HZ[b3 h&0c#Ťfj֊)믺Ȱ*$Bj@!,L˹βѨҞӖӔҒώȂzurrxṆϸҟznc\UNKHD@=6.!v rpnlgZQ QR4NJNonJPIBJ9P+S \ c"p${-ȉ2А=ђȂGĎIMS}[ugqpnoooooooooooooonookoomoooooonnnllllkllkllkllklkkklkllilpJlsgr bqSoInDnAm5k(f2]=HE4N LFG0   $"22d¤ (QLBÇ#JHŋ3jȱC?Cz쓥ɓ(S\ɲ˗0cʜI͛8sɳϟ@$HѣH*]ʴ)SPJJիXjʵׯ`ÊK,.hKbRʔ(MdFݻx˷߿ La+^̸ǐ#KL˘̹ϠCM̨S^ͺװc˞M۸s=X. Nȓ+_μУKNسkνOӫ_Ͼ˟O3g&o(h& 6F(VhTq4v ($h(,s/h8<@)4L6PF)TViu3EWv`)diCfihp)tiF|矀*蠄}i袌6裐F*"(f馜v#ꨤgNuat.6S9,.#@p qu* ܌ "g 7jĺܫ7*n.+ ^:ת[qDl,4;R+º,7#Š1- 1ɑk5\jl8a+lBAy,aOlâ)kT["U$H8Q%0dU)v6p^Hm/:5\v\6[5cF"*-P#VVmil֊Ent좖`Io:qH9򕰌,[DG p ö+] /J$׵؉RE !D p ˾@n+q)R| ~m) HNs+b%;PL*[JSe2`w1hP6Y@k~LgĹxγs=πVoBE"/F#zЎ I[mm 1NHGMj(ԨNuOV¬~g=Xָs^w׾ a-6*Ў,j[[Ͼls֫MruNzqww_nyow~sU 5-8pX*8 = K3l*9WrF0^.N4w^]j@NFOҕd$E,zP:TKX^- *;v8mc$U}xz8|?ٞ;~[>ꕿ捞{mћFj=N=q{~_/CO~ёH{OzS>os>l6?kv?j?i8&xfxf$ } Vw'~ oFuȁ j!Xf$&',-b084x88<1@8*&Dx#fHL P8&TxeX\`8*Hh8dlHd6؆pcothc#Xx(c(xy؇$6~I肂X&؈Vo}Xň؉EXʼnxi؊e$y8`F]LJ؋uÅXLEƘ8 [ҸZ8KxGٸވBH=8BJ8XLڤJNjP2J:HZVڥ]:^ڡa cY9}cE ^l*ajgډi|q1 Vʧk{z˩zz'"PZ+ b$s#J,*uw|zS>j9 ڨ©Ъj'jt:Xɇ:Z,j 2zʠګJj j׬Jz"0 F, @>*zQʫ ૺ J)Z|ڱ ;jp*[JJ, ⪰ڮj; 7嚜[H:d2 y0/Jb,Q[>FҨ:뭿*][>'0BhjJ"TӲ 0@ >UہJ-ҵ1Jҁ6>1Q~-;jgDb:AN -axPNNk9+#,Եt;b>۶ٲ;D뉤{;$ 2y *-V>QT֛ UFʂ-d@:+ ى+$;{ pA;L@lh(!LH`'< 8. <(a&a)=ÚæPRxϽ{)iLNJ]zխ_Ǟ]vݽ[x͟G^~@cǏ9*fm(;lE\b6KjH3B̸8s)ւQ.)KjEk*5w٬͹bff1F.H#H#D2I% Ϯ%2J)J $.l>"c3GGlA1L0zChB DMr]nDyR7!dJN?ԩD5UUWeUt5VYgV[!1.PTQ52Ӊ8= M A"A&д]"%CKmmIm]-HƒtWX;wE1iR~M?^tLwwz 4ü|IZȵww߿#߇'xbj[ّ^d^ZL~ >3œ٠{db]c'vi}t$~Z|Yo_NO(M19s'3$8A V0+35ANPgL짳ϑp ,_ QXB0 enAЇa8D" AH4筞ω* =0WlV3eщ!b rC-9ԡUF6JAtc8G"*_Jb#8'R%0BdzŌy#$:VҒ1INvR/v\SǛ#$ (BbqC2@t?4C>BAT!DGDj,dIHL0KtJP!RTQTU:T"tEcYX|EG]|\AXEa4`|A`4F#ed\AdtcidhAhFӣml@lq\p@p4#ut@ttGcyxL@xǻ}D|,@|Gǁ?4Ȭ#ȅ?tȤcȉdt?HȍT?ȌȑÐ>4Iz#ɕ>tIfcə$t>cɝľT>IQɡ=4=#ʥ=t'cʩ4=J%ʭ <=ʱ <4"˵Ĵd1F6(ఁ+`i . VB }`$.GNva`FVaNBZaa U">a#B$N!vbVabb[QZbzYbb_ cY .c=XI ^chmcWyc ~VcczcUcT ,U9dN~]dTid~ dCKVJ@ML# 7R&QnHTI_U~@VnSe'qe7e%e$ f,fced@g>c~_hfi.j^_kHl&mF_n?of&gg;gM\g&1xNw?zg g{g~?^6h%hMh]lhF艆]ގ^h^]6%Mii]miDnfi.iii>P拗~^>i}vj`jP꾸j&NDfAF0^jm{kޝ리븸kkk ln.=nv]ƮJĦ/׺쵀lV.J>.]>m. ]'~m˦m̺ mm n.n>]jnNnڎnnxnǽn$no~)onNYo8}ﺌ-loԮR oooo pJp>L(pmpR|ptp&p3\ qp-I? 8 Vx * J8!j!z8"%xn"-"!8#5x#x2#=l:9$Ey*"$M:ZBB9%UZyeLRb%]z%CZ9&eig&mq9'Y'yyJ' ݝz(V:(1)ZzYb)z:***jꫳz+֚+箿 ;,_[,*:,36-Zj-.N-;߷{.ܕ.ܺ;/e[/ /j0|Z+0Ù0KW[|1CU1{<2\2)+2-<3\39+|=/? =4A}44M;QK+S[}5Uc5עj5aSem(g66ܭ7uw9y${}>85 ^8≟x;!K>yS~9Z9׷硋裛~v:ϩ:~j;<+o;|_C?=sI_=ٛu{ߋ?S>E>۴H?? $&p_(EpD_/ep^?(p&4^ Oߥp.] _(p64] op>\(qF$\Ľ%qN[(ŵEqV[ŭeq^Z(ƤqfZϨƜqnY(ǔqvYnjq~X(ȅr$X!}%rW#)vEr4W%/nerV'?)grDV)O_rU+_)XrTU-oQrT/)JstT1C%sT3)eNO*uFNQ Y*TFjSUjN5[*6 ֱ)d=+gֵ̊^F'L*[%Uv]+u~e?P׿6p b2},d#+R,f3YN,hC+vv=gqղ}-lc+Ҷ-ns򶷾-p+=.r2}.t+Rֽ.vrn&0! T?1 hH|+ҷ/~ /,4>0x~Pؿ!, %ߜښؗƁtrms㿑ľŻˎԖޓxtobhkc_UJGFDHYvcdpcbdeeeponqqqrqqrrqrrqx~s( "$ءAޜGژFՔF1~~~ } x q l pssyr-VHKNM;vK|@93FOOZkd0LB67,-*.(/P> cqiME9,(  ,AFNirro7jCqFmQqpcpMq$4sLs KuJuBxEGG/I#Tgp$s vvz ursuttvwwz{|}|2283FPir ǰÇ{xɗb A^08>,'z9-mtuҜU[۸sͻ N-k.af Mq*0N:s/nƺg\Zۙw#U _nlOJc7w̍g܂ 6F(Vhn^$̈ ]E]Mه &?O?,>Mxe"-JEҘ3zPF)TViXf]Ab "VH8`_hr{Y~l̀xΙ CeYr[&袌6裐F* !guk'jf;]Ι}]kku) JYv+ki^*Y yڐ#E Rmgkl~-\ XB(hbh+k櫯Tɟl-$)!)Z3_́z4(`Rޥ34_9Ƭeq2,q{ܷ,0,^ Y4<@':JjH'L74T18OWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX7.z` H2hL6pH:x̣>^"@BҐ"?F:򑐌$'IJZ̤&7Nz (GIRL*WVl$?(y9n 0IbL2f:Ќ4IjZ̦6nz 8iLnw@?Nvr؇<@z>~ @JЂMBІ:D'JъZͨF73vԌ-cG;5 HJ O}|Lgz8ͩNwӞ@ PJԢHMRԦ:PTJժZX)7ծzիpMղr5c5Y:VNHЀ6Ne}iVKMb:V X9ೠu4THm>b;uͭnw pKMr:ЍtKZ[ nX]nݮjYAhkڼ`mlkͯ~LN;'L [VV|lXp; _vH%0wrܸHph@ @ vC* 9HN&;PL*[Xβ;>8r>\'P-6pL:OyR=,/z=nydBXχ>&@ 8zj'bqG39T`d8NWVհgMZָεw^:p}юL>l`ЎMj[خViV{l~em{tM>#{.~|'S,bطF__B.o#W_?;2a 8;1 d@[7Xx ؀8XxX jP-  p'ȁ-P O J`<؃>@B8 :F(PM(IKPH>H p Y_Yb 8eYx桅 2<҅80c j؇80Z~~e'pX}hpD8XxhfwP X7xK:4h8؊8XxC( GO8ȋSehgbʨaH `9Y8؅_Hx>v`hv6 `mP_pplp}؏9Yy ِ Y s 0Pp W P0294Y6yinЏ ؓHA;yKCɔOyq` 1X5`lp쀕^I* Ѩp550vlY81Uh`e~Uk89YyX*w / Y r٘' ࠉ9Yy8)> ɚOJٔG Q9>XI}S)400@)Sdy aCaƩ: 43HSIS9ُؑ0\pKi yK r9鹞P/U G)Tl q@é"90.i?)j։ @[TS}@5US0:<ڣ>@B:DZFzHJLڤF` @@Q:Uz]j [jlڦnprJ[Eu:F`9ೕ<"8BSI_ :+hsY+zZ9OzOs:Zz*y*{A}w hګ!#,8 *}pڬ:Zzؚںڭ:Zz蚮꺮Z[uJj:*Z;#Я:sک횰 ۰;[+pFkF{[FˬsR',K 2;4[6{8:<۳>@B;D[F{HJL۴NPR;JVeUVUX]e%kb;'Pf{.k80Kl۶npr;t[v{xz_ i[8t۸;[e䷱sHN0;[{ۺ;[{ۻV ;;ۼ;[{؛[˽{蛾껾۾+[{ۿ{۹\| ; V<\c "<$|TQ*,0|86|8:';@/D 385\JLNܺ=O,DZ|Lˊcˁ,,|Ԝ=й̓[ϹΤ:-Ή΀ =Ҹ$$}(mз (13@:=-kш*|JmNR=վ =  +Mӂ+@A`ֵ֦ր gmB}8DmT=I~с=؄VX= a+׳+u nM٠ Lו wm8y]Ѣ] զmͨڬ|E۫P65:`ڡ0Ma 09{ܝ]ėrRfqP}2mϝݾ]8U ռ^߼ شm&2"0g-M~.*(. p!M.{݂K.n '.j`&NC"}gR6߄G -˕` ˤgM` p`^-TNp^~KI0^X~Ksp$8UNWN_Nnnyf W_Aj~~!Cd@1pN~dt ^f漐 h>nnưi^h薎t华l~KϾ`ư\# ze >0.ݲ)+xᨲ+5]*b=Li -'!"ݵI+$f 1>rJN~N>8PҮW꽼]*M~弾D1.蹔 Np<g~nDGokA_o^79?D_`nfT1e`_^E钎$XwK,`[OMKOgrM'tف1p! nr+Ⓩ6n],{P  kߜ//8 $&( ~{}KR UK"]ye܏ϐ i pov /eGyOծD3b -:$H#h+BbK)J\"ISKcETҖVp5 ӧQFV~="MNX9Ȓ jْu V쿫d9pyٿW FXbƍ?Ydʕ-_*ܵyy_| ㍺с%#v^17Jn޽}qōG\r͝?]tՏ3"x*Sݽ'e.f0+:4Nr|ov鋾$1_(= o &("Ei # e,9ioDZF#➰oкdIJoT#TZX07L\Wg{s\#gͳ@}3ȍ\wcةtb\tnu矇ۥz>U, ( >Tz`כxG"@fb9; p{ߐ)eE& epsY+74( C'Lh/Q3P4#PnBXv@D 6a 3lL&>7DW+zxmH4FG4IG\RmC&aFwf ep] 'zgDcոF,i8Q{wcxG%YP oZS°o"Aș\Â|TAyV$#Z!IbZs'XxQ.eRb)lyBY:ӟoP|EoG6ԡmNv˕ JČ(JȖ AD: %ha'sJef/ɲ7(q̒Lyh'o8ӛhA =z6'+S͗FTҨD@T!N  Iv\mJ`CR+P|*$d2RXϞS&2;U⩘y*]T̘PVֲleGvֳPY(DE;ZQ(bi"o= RIS32>L{[:@vH5II/Tmr S>J  hV5̖[/d=[{=J/LȆ]%ř #APpmOQ$Lu̫;I(_K?̽*rGإ|0egE+kЇv1ƇdiNҗ4lgl Gxiy8SB$>qWx5qwyE>r'GyUN/L1_ye>s7yu>3zз-GGzҕt7Ozԥ>uWWzֵuw_{>vgGua;<7S>ww{w|?xG|ow|%?yW|x[}DǴG}Uzַ}eo/ h@ L|G~|7χ~?}W~}wo c|Gտ~C?+v7 NoQ@ө0==?ˍ2P $4D20 T d@ ~!%#DBkĽ߻>P{ܳ+,-./01$243D4T5d62p9:;<=C-C<ĠB$"BEDF4/b|Bd@ss>MNO6CP4SDTTU Q@XBܿCtD_c ]%&,3H(D@DCPedftghijklmnopGglWLqDtTudvtwxdrBYGzE6^E~?H!E,C03B)Ab݃H,iȋȌ|ȉHȏɐɑ$ɒ4ɓDɔTɕdɖgъ4{'njiB,-,k!.A<[.&0l䞕]U6|G%Q޽|r`c3Lz~"V|3Пּm)}MD5' Ͼßӿ﯐?ׂmxGHo3_r=( _A n\ ŬR8 ㄤh 3b6><ÀEJ^W-$l"A*CT{#ąDq E,.N]@Ŷ}Fd1(&& c\0/ Q"BXD!1~s!b#(ԱzN ݔ)7f=4-V[T>{Bj~d*Kx9Z'Z }lYAĝO _ *SPsĬg ځdӬ--fXV|Dr#Ì8rvd2d!S#ɇ=h \X} Efyhi5f,ٕ`.тDJl+xۻw+|}PXbWl#6`~·es0N tz%|FNiU /H;;/䜤2T]ctY\>[#WUrEPyڊ:$R()dY`bczGӳ~Ơx1NMҳtuź<˙33ۃT16@C/~1HZ5ujUBXCP{H梛q-~cHnc: 5g+k@zz-KL^*sVs5Xۥ|/]+c'\Fsa7D0|~waĠ@Kjp\5w~x(זG71m k(7 "Ѣ-n#`aE" 80j"'^c2"c1~99f\Z ,""6``q?>7Jw t A$B&B.$C6C>$DFD:G& %M(a<4++>6J~.L8~ac0$#cFbA2 M֓=bHⵢI*b?SGK.^Ȥ%Uj^EEd2#Gj$[Y#Րe]X`%]V'JIY(`&aa&b&b.&cRe͵[NfTDed^V%efMfZ!mZci&jj&kkƦl|A eJH&eeTvfl&& 'Y}hJզstj$hqIئSSDfݑؾQyԁq֭adAJTKKmMm٭ݶЎVp۶RkQtIm*T*T;@ /Q`Q3d.T\/AnT.CN7?4@( 8(?1PC.FԮA$oTn/nN%UĴ BH\€H00 0S^uȭZJn[vB9^ֈqcDnie . V5a ﭒpa ᆘqbk Ee I,6\.PqO1n.pq;銄1[1`3Pq>w&pqq@ sH1qD".tnH/8Ā"q"'2.jzu_Î-{6ڶ6B?|ymsuL?>F?5~ P(4d͵6 #!P*(*B24f u[@ DDܭ9۞K(a:",b5yDALRɦ#pI|R)@L5^  S1SDLLmEガR9Qӑ ?0(CMTEmG!eTH)K1TM9OA UQI-SQMT25!׬[q]Ll3WpmG:-@jGvg.Y*XV[Ϛֳ( WoY5W-jwWv=y 6qN;u݁lxn%v ܊1xr<V]|I.d25ޓ}5s`KXy&/dbV⢷sq.cc꫱-V OYَ3슏J]ulP /oԡ[9mgv5ww  _[MgCA߭5Ds6>]} t`z1"%PbjL:T@MQdSt=MuM8pku:RfQ)~p5d{BJX)QTؔQ(H&zJ#Hf4A6AL+Fnk\)y֮~51 ĶjLq_S JfԄRPi &R1Y LOu9ViԈU" Z}l^ЂD'q lUi v 4`sRUu+}ծ_?*݆2+SiV\h(,I/8#CFCʼn3KB(%J6ԑC @\`/$/FEc "= ЍdP'"#|x>0C_J(AFJ<'#^DZ2#AZKd+b ?Mlk" R沗9`NhY`iR*oJ@suw)sHZp5kKXXTlJCWLV.eґ^\2ڬ_5K#ֻqw5^@Ԕ*Kd @ kKCm$3pAF, 6vE]kW®]a;0v{ ([6Qlng ~?JLh$5 !{ܸ޷mp<ܪ6N%06n607劀YxsF攷L5Fh[ͯ85_5>sPн'wwn?^ [O50>u8Bz3p\rf[IYN5k pis 1v np@bn k ]`KϙoR+"pPz .ą* :0:mʩo~]bmDo*B^Pbp.Z,"OH" xo0MĨ.!ء(POp{ڞ,Bt- ʰ|0 [ɂ$v(p. ɖbqӬV Oa 6&'./$+P ow/: z# DaR*#.ߜvL9%-RZگbG"9rbQuZ .as⨰Rb0ڄos"&lpv% %p GȰtQ'1  O!q-! %o(j0ΐ%.vʊLQܲK8ؒL,r [N'JHl'm (&nˆHBr[(.r1%#%f#34{W@nWzGVw&s1~x_Dx|ɷ{_ Z)"}|dy+uy}[zqv={Åw*~W I|W+xY} .|C>@Pc9a8pe=ŀ:XŁs*"xG>'5 ϷQoyx8wq6c@}x[b$ZXs88~ˆxŠuUuu{6 xx>3eY~ë*OXX?ُ-XBS8We%rp=#k)J&(O)h kb苪HȆ}ȘȚL .0}sWYY֤O ❍QY5yAٕ5Ygmo@LF)x`|*'yi&cF! ꙞAJԆnFHPFi^ɖZf:coIZI: `>ٟ!O HAb?ybZ8XcYegyu-Y×ϺYJ* :# X 6JʩzZ(*ۅV[Z?~zz>ៜ(J:(<"i]*20~96'Dv׭:kfhNoக鐬jJ"9ʮŻ抇2̙ ;%וXڟdC kHD{{g۵Ibyǚkq{jyevY/7\[I*ۣ\ܺ(iVHgK~ ȇ\ȧ `˅Za'0'>*b "\kK\tup/p3|7מģ.V0a âf _u#[_,ܷ{Buφč0z lfk< = Q|X:ݭN`<*̹iL K i׷|w ±A Z\C.'>.,L7]Ů]s܁X84H\җdΤvh . ޑ>ޓj= : BףH[]g|1 ;"J$,սg~`~jc'D֝M=4޽Iޕޟ[>N0Li{LǾ*H֞k}=P <}KOZb y%%:*3QMĶa c@ u[s!ȸ43E ULjC<c#J,Y)~1}dO Zp7 C hpiID?ݻLMĸqa!?1 C 6e^CߍjJn߭s O7ew9wX <0… :|1ĉ+Z8ъK8px#ArҪG*M~d%+"kڼYK:Ms˘!=ĉ4RKDTZ5֭\z 6رd˚F 8 aB 2\XjԽ| 8`, s6[A8ɔ+OGՊ͜j :ѤKSlߗ8Z~c^FyD%` ><FRPBPj]$QP.|+, Q4jșۿ?kڵmƝ[]J5_`)Y~ZXNH}Va]aa~"Wkl &uGqۋ2v3Oc:c>dBgCnG&P.E]KҨdqLu^MS"%`V9d{=\j~l\t5[vމglvែzՅf8⡊.W#ډ(P^5F"Px]STfjzTM =1j|/ H*%ӑEZS<*nj뭹+3r,4*/0\n˕ g枋 8ɭg /~[ZދF*kUJ e:mp tSC p/r^p7In"7rd\0LY/2d qBM4 3pMp }'guuZ;dM(GM@`d|vj8B=cvߍwxPz#MxdS[/x]ONy_yoy?y袏Nz馟zꪯz뮿{?noq+4uM|#<,N#Wxα6}>.Q-=f/"{sέP?|ϿcH//~~[Q_5q}\+ =xj_,TS>n?8)ow Rxp0 k@ H R<۠@$~}_ ? E4ˡd4FDgѝ8qE@ r"[$0:plf( } /I\&# Gd!vOIc*_HN /A,Y\rC`yP' 1wJ be\hEIHֳ]&ypJ3jT\8dŒϸ: 2$YViz OV'Z΁ʟ]?OӞ'E!zщS -C5JTi( ̴tTUDJҊ T+*/kzDS NMs'Q{iӚӊGm2v!+*@ӫX5 XJ St'%@%fJR*g'VJ"TI JWz+_׺6n-;*XTb~^UWY_:ֲbe]M*"q>r-PwM6dF]-'=;ҵ]TYfU 1*j,XjX)dS!}gZK].מ .ۊJ)*YUŻ~J%%#hu&ZԴ?EPk ;6od;J+/M;Yְ7bA_(|25:J-W#*IPO3]1dlc-mqy;<{Uim kux߸(iP}0?M2bS`b°lHa6Jpƒol:4!ure:ϩanHWBt:*v<ђ''iL;Afk@tK6^*P6k٪;YYNAIɄͼˀ{Y_,7)&}7sn?7کfL+|竇V{no"W tWwqYz9֭+3q]z~m_DLOo'3 Ri@tzu>̠/~LpՏ?F?o w(&TB~-G8ူ$Uay$Jb((-#Jj&,Ӏ$xJ0JxT-2/c!ʴtx{wp:hփWO"Xa`ZNH1Jȅ_фiSk>6>8XThwIp!&axDXzMhx1jȇ[цghHQ8DS)VHNIH!BgpLEyD:Ȋ芯9v䊲h$gHTȋep~Zh bHbdӈH(p}{ BhXJ>(^1cS@8KǍDxL !R38dxI/؎6GդgďY8)zIy/ ) =LSt/Y(Y'$BhH#IKɔMO Q)SIUiWY[ɕU] a)cIeiOgkɖm[m1\ԓ84D5Z"d )Iiə陟 )@ɚ隯 )eA2qwCy /{}E_E~|"ajIi׉٩ɝ )㙝@牞驞ɞ )ٝ҉=y(V TS4R&QagveoEP ObQ* UShub R;0RPvM6X(V$ā51*3*[@79;ʣ=? A*CJEjG0KʤMO Q*SJUjW6ڣWğgYbJeXsYVVAw]&rYWWEWwz^uX beXFX!"⦪VUegWը(*(**,qM e *Jjʪꪯ *jʫ꫿ *ꩣʥ]*C_'[j%u,Wt&\!hըe]եU*l%^JF>k[V^1UZ'B[ee~_H  ˰  +Kk !+#K%k')keɪ<ٌX30aCag=[eT)F&k#VbMa)v&O?vcNcOcR;cTljVaJPN'=FbrOFRAnS(Ja.Snuu[Kx˷} +Kk˸+Kk˹빃x eз 3[@&N'a R m% VXh:WR hii{ii[iʻv6ꚼ?Lj~{olkAƉyyh苾˾+Kk˿ ,\@  ,| aXY}rN[gmNn'tܖafWB;wVnGn6\%5Sr+_ۡ)ªfoy w(,˯;pFp!pa8S [ W]_ a,cLelgikmao,sLulwy{}a[ \ k2Ulڶq;?mPqltL&E9Itxq1\ņ˻,[˿Llnjɬ ,Ll׬ ,Ll H`ȇ8&r'v,#꺑XWvt,oxq3$[nyD "cމhéRtqkN}^b5dă~?nnx.42(GH뷎빮yDxQnq謮;*z瓊# c-P~ntI.N$x2|x>HM~|T0P3oV b#`!bO8X$ep=Zr0nt_͑\C~!OSAKz7.o[w@7+# jO QzcPnuS+V-=uDT0K$/QN;K*cHrj-[QmD`X"ljM@0 Ò W<2J(_hV3>$L %Zщ&ZASQNS(( N%[Yiծe{+0_z[׮ #FP_/fcȑqPAC([nPgСE&]iԩ?O˜jرS;]mܹuMoo'^迒/gsѥO70mok#F+aYɘNMʟ{Ǒ<~| ȿ:p$ d$SKpo) r.JCBK4Dz E+ CLrQ.,;;nHp$TҀ/p 7ڞrJ*7+rK.sKnG0sL2l:KqM <0Z'obQΑFj;FX1F" PC%¨>.?tұ*L'CoJ$AP6pT[EjSD#G jN=tuW^{)V hEjlF Icviag,E[c۫ C-J[uիZi+0Hz/m hyA4~#QT ž0h\ch8X~E244-J[vYe,_#a`8& f{ ~c2gЎ.:VX/zk14KSW 3<5+JUp2ol i&BGPvꞻ7NqKӣ 'U7\ޚ֌|u[_+a+cKv$ˣOiuϩ/*wq]2$~{W4-~b%)󣞿`/Ӑ $`4A d`@FP`-xA fP`=AP#$R6Q8cѳQ,0['HL4|b(~~׌xD$&1:a#\ǖQH $h{yJXrT2Q%!4Iy?j"؈1Wʛڸu"VE.(xHD&r(fg, 1s4'$2_-o/(B9N@4*S;r9e@-myZJ3Y4v j̗Ky!ү2A5b 4/N4$S@7Ma ? g9yNtSdg;NxSg=yO|Sg?1j 3_,L1J&R;NSD%fT(GDEY8AfQ'ۏ(/'o~Xj6NT$-O_SΦcGS1)i@B+Ċ3mzU.r$"iI&X7xHGiG[WҬ$0K\vX1h a5gKUb# +Œ_hbYYfpZԦhB\ZVmmm{[Vmo}[W%nq{\a(hZ=4E4"fFy@!V %iMQW GEҬ:*i0/ВV rIZV䖭HNl [`9p|*N*; ;fLT _<~X+VI.FILP k魬$+Żx;?n^`XoJS DYS N7 WvA&>t}‚mL|ٖҐLsFxpggOb3k֟4Y_pFf!xy[p C '<<@՘< S&*9K ܮK@R?ۿD={AL" ؋=\==| AdF*8ӠmxAYZBwFCBo v9v,dk0v ( )0 K77l"w+9tÞɦÏDz [ *Ó Ђ)@I@ DK$ ACd2<4w Ec љI9DhE\,$Af0b%Ge"ES:5ݹojh;:ꉥ*B»YIT O%P5?"JU )8DqqC  2Ie\-BRLMA)Sb%=V$T^C91hQV0 (Wp tEWWnEDzU~ ''ξЊؖ~6kV-UReMX0V2meVg 6`5A0510k݈UaٗuYp E YWPIRRײ НP-X;]_EQ}Z(HELJؤUʊ o\Õ=Q[]RaPՍ@[NS[ImMQ[R0B$zǝŖt x ʕ{Z5tZ\`X-֪Zmɭ8I0$A0!ɡǑ]ġƩ]бݽp#q}WSᑥQӅ6A\uG\̭ޟZu@^\E5ЭB227!- E0qM#u]]]Yiɝu3?rh -P1`}9=K8ި`u`HVHm \ו=5a/Y9)-))a)V߽G}UUmѱ!a^ZUG5dxlcR7"VJ9e^d+Q. 7ë5`CF Q[fĄ"&2bga;YWNgېevZd]Ϊ^N_9P a%V@Eezc!85(5r^3HSά , &q=ٮ;zXg w. g~&Fz9{g"~dѕn`Ѡ,J,Cg% gCl~b UC^^3uT难Ŗ雍ܛFԨ;,Sꆹ8/`Xka6/ɕjVln~yafܲh3Ts3*;N aKx72f ~AVvCg& 9Kx3jk>9л! \喃1Kz9XAk6B.ڈmnm^m_mbfӦ5V>CCj楖nC,"pc0p&jC!S3. ^op.i55`,pqqqL r"/r#?r$Or%_r&or'GL*>Qq*NOTqGo.(R,P+m,o'3ߨϵsaqt:}׎sB?:s%s[s='>JF@bNB?oM DXJ?"Gg1Ht_tQ45MwmYVR_SGu^Qd]K6 ' hvgvhvivjvkvlvmvnvovpwqwr/ws?wtOwu_wvowwwxvrʁg,[&s`/aHbw_~Hx_xoxxxxxxxxxxyy/y?yOy_yxzy}Ǫ~_%x?zOz_zozzzzzzzzzz{{/{?{O{wA?^O$.8҅?Thp1>L*MԋSEU_|T02ߕUMT-Xz_]ԷcL' (z?}O}_}o}}؏}ٟ}}|\C/j klWY!r=Ws] ~?יeA{EJ.QzپNw H}} p A+!Lp!ÆB(q"Ŋ/b̨qFFɒ&OLr%˖.[VՂ@fwJZ 3do+T2vS%VCI=Z:N,ɧQON%ФSt" WSǞ5+Vmٰmf})w.ݒHZYq/_IZmh%TL\/蝾C,y2eɃΞu A z5֮_Î-{6ڶoέ{7޾.|8Ə#O|9k1=`֯cϞݣtu?P\tXJ䨛I2f V}Qu_~4V& Z9  B8 Z(!n`QQ%sE@^*i"E#~(t?B?칧?2&f! Zwϒ朔SRYWb[r٥_n ݒ Yg w4o5~؄Sz$U2H+շRRWO4I4!$SM7xǎW#)UAU:)R馚F jV2I%R>?&DdBMȔ5;6;$CF"dh5d`BR[bEAł}Ħ碋vIMoJJ}?gIDT½$J^E&o/p  GLqn׸ 8"d+B#Ch+ܲC"#lgJz[ڒn;ܳ?pbzG tm^ܴD<zm6ՠZ|ZU[jSdMZ'՞6ovr%7PR;-b("3z5롵b>-tXߏCn&̚<5{sjBs޹矃F4F)my./5*Oј{ 4~^R?Z7{7ϼ?ޱW| -2| ?rß߸P +GVN6wg  h"0:uy*XY0ܠć:Fd ! 'q\7)| 2! kh0:*pB"h#"1J\"'B1R"h0V!_-1]VQu 9F`r##"#(Patؚ)L\$#GB2$"]C*0+yDN2t'YsIN) Wnl ic5Z2`9=2|d.gF҅gB3Ҝ&5Y/,S$6}K`5̴&99p ߬%:_ʐD, Bu'?KS0)3A“4!YS@4(E+jыbepM?nzhkѓԢ$uh?߸Rwvt!vʵO8)O O4* ,FN\lЀB5R*Ujի^(Q!Ү:p*YjU = ZYΤ5@V7zOIBS5h2P4t5N5+cاmW':jdqeKAγʫj[ƾ4E@ Ib7.qk"׸ ,mU mrk].mhU#w;7_3MnO̒:/8a=gd;Cؿn.Q:vwH<\Zr V1Kl8*^1[b21kl8:1{9B2l# ٶ;|Z_6ܽZ2/0pE,3{2 Ns)9rsgIbaU;yc7̤𲹫 z]B#]mZΰKmaS,"LT.y Q.&`m#LC^5^`+((=K^7= 7"tn \hFjo7T/;HNkm󦷽׍o py&9Bn<|.9/ ˜y5#NT`{.:rl&n6 I'ձ-T:_ `,(=gA齃O gk@!!} qhe:Ջc($ܭ@bvWFY:VCIn ^>H…֗D6S/rh)Ћޒ>z#ߐ{3@x{ 81kj|Iwv/ >?j=_皗I(\ր\Z&ɆuXS _Jz_.[=ACݗCU}[ 3 V  a !@#Z@޽9ޭɑ__1G a"q Հ!Q Z+m%;(cB*B2dC:d\@,bMBpA^cv(=>dIIF$E:#7Z]˥!lKDʩdL^dM\aB/cG$ԈGT%`1DH yh x~ OYB%ZeYF[YHXWS:ч DFᤌ4Ze@#ocZdc=^>^~lCe&"?vIzIdYij_#Gz&_gg&K$6&&Jigef%ezaJ@ 3ǃṪUK]ByՐذg4܋|z }}̧~'x E?% g̽`BT6C@Mc0HujSbbWS]x臂h舒h(buRlhF茎hnՈyc(]v h 4_HΎ+Pӝ )$6<ɸkJ *2ĢC(kYe揧鐆j,CQ*z {ˢM(Jͼ,Etx ~ JAl'Ti.%bʂ&L2DОWJ۟«l: B"-Ж9UѮG|wλ4)|ЋZR̿|,Oge(.Znb21J[r.HmkQ-V±R,"Rx-VfE8i ܸM *DHU/|Oݚ Bԩ 8NO>PҺ@j .گDS)/o".JkX ^NYz屚SUd0td0ECJ-PeĖy!rOx,YlV4yny|}{~~.{}&WXx "0TƯ%) BLh0kG+r{g}zu o;߻{+zW&$,)Qz% VEcŤrz<\MVD) GʸHa0.)c3|ΓS}:\:oT|_:>Q-0<2Qپ*~Ў:Kٛ}K§XﵧLB={㌻H>uؼZ#Д }7C9F7[: w9^>|y!R}l֫ {.,Ě 2Kr~JȲˣ~Įӡ t؏zlWFcSL"%:xѧ"3Fw_'n A\~c-hrDאmNm&V0xH $\P!C#BlB9 $C+Yt?V\ygN;yhP$"m؝VzkV[vիҜaqmZ;8uFH{p` 6|qbŋ7vrdɓ)W|sf͛t>}b1Nիp gŞ] s=o5~yr˙WeD`00W~;g$nWi%tDH Ԕ>IA̓7:gq=*!D@>K=/ 5dH&hj:ʨ)?I=)emK,2+׊-d;$\&|(B4ҵ.rںx÷ n|8L9"<Ș>}O?0<`Ƙ](L"=IU$D :OsB%@SmTSKю>t==uq|SHU9]&PhoڱGRȺ4pr=tLv5C 潷/dyca^c^}c[]ᆗ;w 5ޘcDVM>yN6[~LxoRmuޙ22^v75yh NZ.aewX뮽lAU.Je[%yޛ+Ciu<:ŸnS\D:_5?$rnϊ{eeڑq ܇=0nJ(\s̙z=x7QmrHpm?/>"\5_<>yvY^<^5Tm /f8A~KBN; SKh·Pk$Xõ.L` CPC  FD#q'T/QXſL eE/ 1\aXF/0kƅ-:z8G;q%Ḅ{@>zJט'nЊT"{l$GQku&GPD2&ʼnÁ#YJWTd%9J[> :.yK_0YLc 3є4YMk^6Mo~S:q) ICT:Nwf-iKE̓&OzCc= *Rfę4N>md<ZPȧ?-V(~c(zQBb9J1(7VFAj~_AnYҜF)UK9iRtQTiHժMvT]ԫaUH?)ЭNJuST@q\:%hiWź!AWHcBdzj_5 hX OdYZ3\#i1˫y:naZagꖸX.n?Xk\?`\pjy*D0uO.z6]P'=Z<(c*BxC[#o}_WE{'з5qx _xW|rɏtw T6?| DQ*+c?NFyT>o}J?M|!ՐD,z?bEv?_}%O'搏|HU{gV"sПEXmn%P$(M!e)"&ߘeEȯ/>CЅOKSPn4ϫ!CFE=M%l x#A@zB?o(&&EnYEW HP 0P [p {jVNSheY%]!&T6+EeTU"UVU 1=lXWUK2XB QEȮ` # QZk Nk oQw_s>1J Qwr.z%Q-lh9q11(ykqq*Q!p!# w"s +!%$C!K !%Wq(#ȺG#W"#gҳ8<%M*$3l$Y($2U(v҆.j&5 'H'rױ0I+++,ǒ,,-R-)xҳ)+*h*ݒ Vj./0S00 01S1112#S2&2/33S373;3?4CS4/!.;K.R겍4IJ/g1aҀ6k6o7sS7w7{78S8889S999:S:::;5gֲ,;S<Ǔ<<=bg6 `;b8T>n>45+5X\s?s=6AAB#TB'B+B/C3TC7C;C?DCAADKDOESTEWE[E_FcTEI4Bk@aN?F[@U=HITI4IIJTJJJKTKKKLôJALLMTMהMMNT NNNNTO4Ji3H?kGy|Ԉ4PuHqh"5IR+R)5I#US7S;S?TCUTGTKTOUSUUWU[UTUcUVgVkVoWsUWwWiU T @SKuXLX5Pt P QHQz*uU\5\1[]U]ו]]^U^^^_5^A__`V`` `aU @^ `aa#]a5 tuZ9ZmZ5UA!e!RZe_e`4RfkfogsVgwg{ghVhhhViiijVjjVi~a!k66k{6e3dcc?B6[϶LV.@VVfdopWpp pqWqqqr"r+r/s3Ws7s;s?7r6qVDqIttlVm6֖mm%hd]{`zwD &b*@wWzzz{W{{{|W|{|}W}ח}}~W~W w{ՠ&~}&Q~'&O8}uql`׎Kb[Nh0@Xe lȮS ľ*RGx͎jr yXDnw8ttw}wK2``*x%@` To痊؊|z}z`w{OXטX~  xwXmZHb麍$ V&"#lA3"Iy[ Ĭ+hxlqmИD"9sԮrt9@y@_`ٚYٛYǙٜYY,XyyٟZ@Y x ژӹzO9XO}?Nm%܍MLAD¤`k=ͦ f ;I FL-s"(׆--` Ȁ 5 ZךڭZ皮ڮڮAz ؁/!۱['+ۯ`Z v0!A737I;9:EHKN .tN|h/pBP Boc#{&Q˹˷\˳˓?n3[EĻ'm 5\  #]'+/3]7;?!.b1|l \A]gkos];-m}׃]u|Z|bwspgn%xMO##ȝۯe%$AUH' -syEOC `o ǵ #^'+0Oxj ak`.\ 8>W[_@'B,k@i~ygnCZ= ;q - ۞ $n ͠>C$ǃ-dA꼩[ MiiRH\`@\` #_'+/3_7;?C;;aGEc_gko?_ N y@h`{'~?m^NPq%/e#5Oe!˼Z?~]m2쇭} H*\ȰÇ#JHEV Ǐ u@IV0cӧO˛8sɳϟ@ JѣH*]87Al(`HUS`ÊKٳh T k۾4˷߿2"pp+^̸ǐ#KJÔ3k̹ϠC;S'̨װc˶ȚƎ s,|2ʖ4k|ȓ+_μ[[n̘/4Fcw1cVOytm];mfh&Hi6Z~2T[VhᅀM(m6$ˆ!d(H,0(4h8<@)DiH&+e#dPJQ\ve_ YflVi_FatilsrG(j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjP>V:*6j[i^ "m:+찝1`c6P mv+k覫+kj,k-'"0 w[WJn ŁI(s -nYJ',4l8<@-DmH'L7PG-Hg`Xc]s\_u\O(E)b_aV H60M G)@񊄼e6] 4G)0q̃240؄IF7} ธlcvLء<ƈI~ @JЂMBІ:[QR03mɗl$H,%Z6s -Iţ ).Kʓ*)BZSbԤ5IԿlsL<8TbS1DgQ!vz(p{<"7Юz` XJֲSQfT'nt #me)2aSЄk`WW䯵_XPmjT,Eͦjf -j]jHGxhlgKZ3 Qb.9h cIip M"ƽ+ASԹ AC&{/mgE+В ")5V]Uͯ~s1F(KȾ]{~"-+ ,Ia0!?DdyS5a߾||}@2Da!GK )v=.D}2޽evfNs^1dAdolsBγ>5"lMEW$%0,^4Vp 14C+Qc-s` @(Ӷ$0:v Za;( \1{׸.5bzeټ~v=mi;ֈMmv\oZ .V 6\cl~oDa3-+9d?$=,gʔvA1F4;i1;ԄSgZ:1ȅ4b]4նN5Z6*؜89/f!B5h3̝GPյu79cPl]}.a; C/H%tS}ok渾8đ;ޞm'Oyɷ/?tZ6.+b;yx 2X9!%~M+$n?wJw3NN&" +g˛1;Sb6ϯY+k-~痟G͟~oGL%qin@vt_ 2uw{&wtwZocyV"4x @P&x%D(؂*yh[Ee ` z"h8 p\I6pv\E8i'f#q{!+jj'}I|1G wvI`r1 1lhnklŶs6e|x~H}Hegsk>~vӈ9xv9tQ}U^ 8_瀋1O{01 xx[/Og 0Xè~%E93! WViA8&ոWD{TGHTbZ(օ, .W 憏QfkD0 ,tyk IF+(8Y)ɏxk=f7h;ȉn?Qtx+َU~oa8_?1O8ِLٔNUOOx6Jq\qi hTd8h](7l]Egqь`{8M|_sCjЇktw|MySGə晋s})鏌ɘv;vQ)nHk^D*9g|co xYؓ DYF~PyչKiOwn@OIOYOy@7癞99O0@.0Tt*z>@Oy9ڠiOiOʡ*j/ꢗp(IPZ*:OBJGZOQOSOUoE\ɖlEjId؄pɥ8EAdoiqYEh0p1[:j 5y|W|`j)Eau/' k ~ښjl#sǒG/)1 )T/s>yh` '1y~2+0ĬZ. y-ښ:* **ͺ1JOʮ3j2m: jO*-j Js:wڟ 8گ ӊO癣*[P n.Ԥ8O_RpjhrUEեf LYT28hjse z> =l9y^[=͝˿>^fPnrm ,a:H(&Η] Q\vͣpJN>B>D^C|^o8[} VZ~]'.3.S-\(Z޽*]IaL>;ŗ;mw0yG-mu>MLy,!ߞh]1 1 4̵Jp |Ndz -n !ח@`Ύ쀚6оj&DY'w&q`$a>][6ݣv>)-i >`x,'߯ʰ'J) ^jIڡ^D= R8o>/K׃NaֵW6\PUWe_;._f&CY΀k !1HA~PB >QD-^ĘQƌdZERJ-S̘(_?={jPU(b1 ։YզL^e 69|9ܦMYku+ۯa%Mu{]7+[ E4b[atWdʕ-_ƜYfΝ}2"XhaFZj֭][vk+aLƝ[n޽}i+=G~Jr͝?]zC|Cv:v90͟w<%')|"t_~))7/W5#CFB /l(+6*JD$eN,sJIb -j 1G +jàDl:)J+% ҬK/3L1$L364dM7߄3N9礳N;3O=O?tOˎ;CӒ!/QGR!RK0SM7Sl4TQGJT/<,lT ɢjUǷڋ`Y\t(#3Yg,-8kj[ow(Nhϥ:te]w5S'B =;-mR}%_8`&]J#y+'N(mu1$1,(szZXI,:6f^AX71Yd!.On1f :h'mE[mfi68v6^:g^zC^F}v`fmŤDXa6d,q,ciN!ALo_L'?Yq%d|es>hGmiOG=u-5ϧugk!l-m݃;x'x XL]'~FWzU.ֽXչ}zɄ~W{+{')g ݜvGtDW]M@;6Ёвvpݝw]Is<vЃK+5'GƑqE3Lle&/}1W}#"'GeA@*V( Hnы_Le0gDg"X(U<4юwcr¥ QX$lɄ'}{$H'8J}u'3OؓFF@1@ >gi%H-i]e.u1.1/9̢qƨ͑yf49MQ?TPJܑOsJ %ćȅ'K&9q(}XL*M/A$gd@]WӡW%yv9:\NԢPE1',3_5URt#Ħ$ޓH-P8SN-K*IU-|tA_>O}0@2&yDGEpJn U@:VtElM!XGjftp Za;FA @Wc5 ^WŰ]i{W֕,^1kWN,gCk͒e/W#LrOT,Yu 414i3Q;׸m]m276'NؓWp/ P*c-!bUC!*wgݩzһ(b# Yhu®<]Yf- Z{S nj^)Њ qGaJ6šEMj<%fp?*nc-q 2L `=S+1¯p1}"%,;hk$% 8ܳ!_. Ož"]YM~zA/,瞻Trb<x`<8͉] 3X9a \>j*S<5N͎_ 6!qM]u;YeRyh%d:(' ߮h sսnE00 g/k>Owٽw]SaYS@ O(Y 9YΆ!R=DyI6JJńǒ QV$#cR\':߹>3%]crZ9Ako4Eپa &@|O?_N_A%֛k~/?CZ^:jH@@`"a:Y0+WK5C6V+KiF\+:HuFslGQCdc?2`PN`HAJ8(E儡BrM͹ȄL|z͖ܘP$"E< " B:ιQP L<(P+ O۫ND%$,(d+seDԠ/p.=(l1%2R4U0Јh6 N aT ; Oᆀ\6`[bfa[gVfax8gZ`Vntڲ gfucetg}bϵb8 C\ͦSZH=%]M8P' THCUCAOHcUG9dޝihK{ޛdNCPPߟi8VU_V>ܓajt70\]v` 6 m VnkVg@<ufk6gvmz9`Vf\v.geV߆k^l`⯮-_k[9mhmuSӤ BPH*>h $hQ*yQ} ؼx#W\=>KɄ Aơ(Ezi%jd6KLo4jeBjP aR6Sj {>!ig^np~p{`tvl k;̽p&fɦ5mpg @h(zViu@hpm\8 q & ?[ (?PWPEv!1aIěA#*iII`Ðtu/TnZ½@q:QGIJKLMwt`HNŬq#߰z剄9owneFZik..v 6` pfpi_vrjiqv`q_v^`!o{2f6)_؎Sَ" cu#hQs8=A9H=g榊|'$"QnE6oFRo`ȅ)pSE\RnuTuY?]rzp_ٮzpofFlp_r#fgi_Eae' vqnv԰v7\!wl_NZep(x)b?;4mzIɐ̋CыNQ"!Ԋ]^*=@y8p"'ENtdw~Cdwz$_- Ewuǀnq9[gv~6`7洙oy sQ_.iX?tӱE+ n$aɅ)(1I l"? "]`.7!ʕE #1gh'hѬZr+XS?[b5xuq:,^ƌ#_V;aĆ*>LcȚ-qYq30LʚK,/M6z Oƻ8cxUw1ie'.]l.[ʕˏ+ʴaڭ0;Ǔ/o<׳/ˈ!`>?gE x * : gEYx!Y!z!!ۆyE8":0u'_4긣v_u06 I*$, ݡByYj=Y! T%t-Ki9fYЖ%]Z6O7ݡBwfE5tfm|HbJ>dhF+i(M 1QyDE DOo*e )ҡ`kJV8z+E*[ J\p;w1x{[VmYS&pm{lu^i k{]hEfo=kpuz-- e[^au݉K<1A1h`!<2%(!Fh121ވ$Μe"=˘16#E;*T 84H+`ҚiYk5]{]_5eiv&6${,`01k/sV9bFfۭ1Mg1-xo߅Ux2~v- ly8v<͵~g ɽ ?<NX!A}+6\g̀u{L4WzsqNƮ+hV` C;>xĻQ@+"Leą)R;Ћ^5D]E?#nufBQ Xn,(9ұv#?e#v>,S dNL9$bÿpK_$"+-72ŷ?PGXFehpà0e˂!.)+/)^6y<L]/h{c<#6mr&8Y6>e)g u͸+/_<#B8R1ċ&hTrm:I49B Y, 8i~rv˼(F9Krk1J+퓄@+qt/"%JaRt05:xԴ8eKjM]jRsTNU.)Tә>uO1WQ`d)* 𲼚V[*W4E MIEܑ5O=,b~-<dYNLu8 y".+^7 9Cy q:(fyJҒs6p-᳻!(vϘithWPPi (nZ IxO&8 ܛʗ}o|;jU}[^bWM{>a?%g-u0U[k_r}1+Ӹ6- ڛp"Zb[Qj[z"\"-qڼV>b0*܄&[Z;(:`iϸJ\`x$ճ~`U %@%]O<`:Hڼ)Ig:#M9/xbus^*VB+pYüq?jTו,6(-3iFa5a3~6k%gPb@ZnySd8 &ɣ&;ǭA|ѕ_s::ǚ!3ܛ6i˦'gDuވ[`#ȅ.8ba4qi膪t`9\sK7-kN3չCO3`%JQtFRlozemՉr_Mr6 ˂:mY9Y (~g oc:\8!KZj?48α1)J'^ABCaZq3%4sOjvXW`K }O_ͷ~|z5}ӷڤtft>N=aO1% &x$C,`ny `i^EN=F)Q[hV&͠ư͹ȀLyq}}t~NQ}HabZi}ߡ͙vYhuQa! fT\0?*[ V&"."#v9A``S(`,A}i}+M&b( Fr(n't ޡ-ڎ j >|!]HW}!z)Z}\Q#5V#e#70&^.1ƟZ:aZL-^Ԉ4-S vQ!bS#Ad]18 $F?"[x'C$ vД eYg*`el+nRET,޶b=d. b` #~rԠ1 qPR>݇Sr0^UaVZObVveeTO*R5خ-%^L^cލr2>!l`3ذ @$B>&dFb)?C'@CJb< >Ef̓p|RhqI(d)HhEd¸1d8VK"Kl`B%E%qNL.N OJ%'s28Gqet`. C^?Aa?G@6f6I&yyypXf&cXb+Ubl¿qmUMMGb!obIbJfa+*G"+bMN'jNRsrV(sJq&S!Abw Єxy((pH_'SmzEި 9 gh^ɧRf~=@9'a*Zhn&=Q`>臆z'e\0mhtzB!Ua b)Jc3P*F^l<CV4eB֎V&.(nIe]gf‘h'x u'bX$ (hj&:֛*z *"v(b)Q>+Fkn"jnzƝ)3h?pk'u}I^D'$aj*(Brΐ2KU^;P+v np~L6l +qN,2!+b dfLvDzEj, c'4$lFnRI%ҧl+keވRBC+g:i,RԒE:,f@,_J~-|djBd.-۶fƭۀڸݮܜⅷbk MgbjqNpf iAPH,L*-V"־>ڤײ.b"cXdC-4&"o->/VRo]Ln]m)E_Ȇώ+`RfmLh 1FXn먚*V].߱ bdii..?0nMnOtHbjl6%Mƀ0(.B# 0.D EWdﰠG.) rB.UP&+ a|vjklzn@m^dRvDm+r111DZq̱111  2!!2"'"/![n0xv a w2 7B ð(0WWtym>:nVip)a_T'SMn]8i;j1(*m1k+.?Fe=-Ԯ1Д)e7Hp=Rp6\0FeAr.%0H?d|l'{2(Hd2Aت ZJ(@IQV](ȎFhF82U}vjU/! jlk]'Q2"h*^Zdزe.087QCZ]2q(:#󮲺cS<s's sLpMA4Z3VZ>SK*DЩPG?GH2'޷IK6`RK'˻!l4YbHm,SGPh?QRv-q(ʤsTkpaQ<x5Xp(PVEZ7b TqYM ;)SBfԲNL`KaEJ&lbd:vldپD1VΪjbp6jGg68-}j6Ta>k`l EVWk>'LuA(4QuC[qx7)q7Z ֨ʬDkD?7^O?8ZL-N?F//m"n0{8$NdafCPJfk| ,}16xqQ7w"y 8{';˜\0  m̃n[ @O`FC?J8XYG |xz]縻E'D<4dS1lK3ye g=CeC1cYͪ7m5 5 y:'е'~Y mܷyV0ԑ~^a(7܏LPl!P ) 1P  .C1/d<tQ%ɡڄB1Ȝq6HM@y"h(%-ꈡ7h!bHK0Řl$GP#q*G.Q s !JQA -Pt'mѣrj— +˩"+(kJjk(S:嫢L%.YŢ[qThNʅPeώ:TZE ^$tq%7-4*8eNQGyŎ%O<=G@gn!X)bB9֘y2XdgFi1 !RN""5W6ɄR4jH(JĴ!=0MdAӖ|z#$_ٚ"5ek ٕ䐠=dhVzqR6ܴ ![+Dv _+!qls a蒶Ym!6$0p |7JTAq1!e[!405]fbPgD$.G䢱D/qd #zE`o"TW0nL o.wSR7Oxx4dg%cyItIM$='Aŏ4)QJU:,&Ɉꗳq-'#&$(e Rf+`ā"kg%eGoJXH1< SC:339(HXb]8ȅ.rjYPcW)TU(8ܡ bVN1ZIB?bđtwӠԣ-f^Ȗ:$&i]r=*TEuK6L뒓OG/k&L)54Ү$AЩ"Wf!\Tf2L]͙8]WQF;I eL0zbq\VQKXY{*[g}*Ie3j\qg`Qu&{K7 ٪?LJ[$0M9ijH:;O=NյucD%lƤ>(3J|ZBU)i*T6M6˚eI Ɍ.2܉`P=p0<;ƓeCH!ܡC:mC7ƍ U''WZ kFEiKacL JK\bǵ9YEԜ5M\89]5mv3f $5\cҒS^ثUl= =Zjծ^uuI4'Q~2UAr%&8 4'P*G:ͧ2n+-Ӄ{s{uw~nwKzSx'p(<'ѮQk+x>j^iq}+rRlB;G#)we˃ fH| uf`HRhKZә~ nW>6;G/vgX7>ekkͿl\gĕxa/omL_Ė]#}j#kQϻ.v T0kvŲT%ktjEosvU+lT V™l#E#*R¤%O1N}o}U΋&P8xxy9ڙy)%a#ٟYP#Y[jӝH؈opt8ڣcq*."+r8'sZzs٥c SyTF, SGzvLC!w8x$oa%:%nuNarPUqR!~JI-ؾMpF:NԺP:բhj))$T$4R3ƨ)[6n-LEI:7 i)i]֨zf׀?J5:i)՚ٺF︇VOvmۅ(M K;,]nz+% b86ʡһX ;>{)N{%! Q,10Rj=P{S81c |j#v8{Z/c4aW *!<# yHH;;ϛ.jT[k/ʳ|ȁכ!(<[ζM )T~ Sܐ`dܕTP$IC[O)4΍f9կĜ:JU*!બR +61TO,v',^L)~\ T>u΅kA1,{1s%iO"ؘ͍xA~}'z"b"AZ#Q} >IPnTs^K%üczQ2S%og#:35"}A^5"fb^\!~|h=a\?ݯƃ?}{>w#%]N06"͹A#6_x>X˿!^"abS_տcRA쑪c"-#(I@јF;3q#H 9~$RNj#O|)2&V3Ν<{ 4СD eD`ҥ3x 5ԩTZ5֪V8 6رd˚=꿧V} 7nN+rڽ7޽|  4qMK} 9ɔצZ9q}bDkujÉjH>@ݤor9rUesyԥu rlw) )ByIB ]D,${ `FTҠ`NjdM?NJiTfhᦞ~ jQY֖ZB⩪j"a6k kyQF6[mPRK$r\]bԥ7U^71q'˟=^q${Q⒇F&IM-k p=]iVp /p? q;_qoq r"Lr&r*l_jجڪcߌ\̳d͖}$+{&y L)YwC cw,LGƻ4_$wG1wxg8XwP6y==+̃H+MIy;wP?? i3F0f+>gСFH \]N4,0Ix"&)Z;tKR`t%5hqj176t!Ÿ'=cz颓״GE{IU7F+Eɬ/1훟g,jqCJG0.e9Ll ط֩@{ !dDK(PL#>1Pce>'qq"h8,br$KQr""'34 F$+%W ,`G}U]ҫl _ |EHꉲ&N,٘NJ7A!AQ,gdL3>(k4;wV~0˜4RQ!FD8Lf *|187#ә()>y y5榸iьvR D?t1\@R3:(F×3|EBɭI1 M%iT͔F7ѧJՊɹԬNee:cVjuYuREt CL~$ CVF4-C% 2=kƩ T:DI`FdRYcxcO@+qdvf=uVlcY_HmmakYͭm-K޲vuc9YUHγh?\ZFց"*I:mw+ڗ(UA!f~AיH[̾EU$}'I7bR Ds?"<#IF S\x0ZZdxǭDpE|BĜ} q@0ik x:0kF1bȘKdr¹Jliv+:?|7,e\V0sn F0# t$y(O2<  =>YW9kc?w#=}"ZTد~{Urs_r=v̤}fJn'wy^TrB(#&b-U&AWfW"'k q,^؅\Z`8bh[0wLdE3s˦uUY+UZ[b?x?Gh)NF2wӲwׂ-!&a&f-89恳.2Pa=&)6!x!)X=Š03h3x؋؊3z>؈|B(DiH!'Y| i׈b%Pi)v~I ܘ|hjYȎɷ|F~'j(|'9WyHl`w v\{xC]fvՖbĈi @AmD+a5!ngx1PCo.oay6;<7=/-1)_pC XXy3ɨ%a77YI[!6\u\[i fY ϘY֘`blyaՖandϰ_\yagbiiq(i98euxnɔ?Aw M V_2@O)ig W0glCh#:گ*7˚9I8ڙkS4Or4A}((kI_;X gPR( O`Ƙ3Sa1 ] :6@͊yj7!4,Hc,XF!WQMPZŔԮ u6eӶ!²:d;f?3Ķ*oۦ3GݺBSEjO®˴tigW#% 2 2 +Kk׋5'U"2 d$sFCy+o_kHuuԸwuV/{[ 1Z[?;ҹ% <)tD:>{D4m;ESKNh5JaW>7+Qtz <33 ^{<# ZA"ufM츅*z,\+ēQsz8:> Ŕi|#D,Dvcګc@aVչl9a_faduuu}^fmƽ tM8=x| Ӄv_.}]IX,{ Q%7}`P7i捶oY}kvj6kYmvjUtbXFYiu89B2Hҝ,sD+͉m.L\>0MEsJ] {HrLrT/tPIs6ZX(uFYt[htTiQ+Zl%v=Wv9@rm\|pR]HP;g 'KPvyM̵a&+~KbZXg~Ҙ~Dߗ}}꯾}>ۛ|X \|-*}a'Eqo}rFˀ0ݐ$8n݂Nx4τˋT ZXY mlhro(e[d(c8dw:cُ`֏9v@wH5}ҏ~-}~6hmP-M@*aHWNi8dhx~8(R8V_qMf+|X9ey8/Vnr %|C1H/3.2N\ЌhR<7*ttY%M`yc/\df9iWYO^\eØINOp!_#oڸw^}m_R6N/]Sm7?ʟv[Lد߸$(ǰB*|X"D9lG!E$YI)Udr #eM9uOAPI.eS=ݴUYZWaŎ%k0_z`֭4v83LYy[6jξVcgMC8deIf%2EEbVÌIl 1 ۷Bri[8Ӣď/gsT.luٵox}`ڵn>?կgx{Z8ؿ I+QA??t&l0!:8eR%e80 #Y Sg#9s \bdHhHTI1DS\Ƙk1;$ q#Ԓʫ :0K.L24LjKcM8t/./98/8ӷ#(X RXѐM6DRE//?cțE U'ԃ`7TE?`zpա Q %4`$qECG Y[! gq[eIeuY=&ڌp27,w^R94 jL}_"5jNVX9봳-Sx M('M:1T$TPJdD dMkU%S'YcMgpF&TV!$VcdփhTY6nilFWZ c)#](~F[s}D%a7D{ŵwTko!!R4^g`~W|q&'MB8r+oX!ˉk5}t h $FW(NQ3UhӃHEWUuw](ԝVzYm1î]Q wZب;5.jbNE|_jF_i3p g<8n:  h˅'s#BF0KR։N!/cF* w8U:J* JwZ3UyD.I*JQg])9jSQ\+wQWP$' ˊHfa!\XE$SF82ExG$0sla`y:ǁQ2 -1.uBLL‘ŎE,H31BÄ0iB%?:6|*y!\CGk,Η,$B{ޛQpIDH"R08)ڲ\sQ$2FƐlIclfSf7MpSQyNtSdg;NxSg=yO|S=nΏDyPP*@@ֲוL$<) l ܓ;RɊ#"(Co?jfkYpy=dqv)lFT3]) 0fJѤB k%grV՝rfU͚=c V(q*TAePt @'wR E[թV iP0cG8©a˅{΂|U-Ƃ\j>/~} Q(XRu*VqkXɺ[%F$rz9I2 (f]B Q цJTidku+C AWm+`!W -$Ck r'yU)鶺V헆~X+NX $}ZBP>XIFJǑGR)l-c@BYpt2˒QI0;*"ޓK#ZXWΌנd|˫i׻div#Qf0EsCb;&mkgh 0-ɴ<%!tz2e*-èlL0c5bHh3ypFY''FuO̩UlAm?/Mc6,z$=@6#Q#jBd74]f2IۜZT5bs9 mg<ߩ|~7\]؂EG}F+wK'k6W$Ӯr)xNjn2[vrfnKӖ6'gyy8dj+.\=^8i1%$On ohA|u|=T ȎubA&_;޹<~K}e?H܅ ❺[] nkn޽rgE$z]B70Wms:emG麯Siլ&B5Z@g8VǺ ;S N1Qܝq>^#h ~O=$l?ۿ?mp[<>:&X? ܾ㣓3S$;AзThaR(/=9oא뷟 j[ 4X:4k>x kJpB>c1 :,\5 Cc68|9,;CBstTJ 45\BpDH\ A3(AD JANd  #Dn˶۲e:/+"LE' D&L{qB>#1XB- eL;pP-꫼Kh;c3;(Fo8Fpn o,Gr$o; ;3;3*$DƳ< |KāF |D FH]KDxIMX$3ZL8PWAiŽK<2ƜHJVg Ӊ6Ժ#i0&:$r\IuFItJelJʧʪʬ;x̉$CzD㊜$G5El ;,;ȨKD \SLdȺ$ ˉ$ TSL"[T%CIDEڻ9DI60LIPBԸQP_adsGLJIh|?F׼[<8|C۬lMtGNd<@CߪG@ ʁ 7<ތt4˅,NK"1(LŌ8H̽ 4H$,OJQMI,DM@T#?T$SM]¡\P: %KN C/+ D˰΁PLKdPAK!2efScP<2 J8;4ܳE{^^ްL-_4:Z5^+X>VA%Am`8_0M5OJ(RUH\5ޱدX_-߅-*  U''saaaa b!b".bvzݼaHAA$Q֩u߉\6YAYY^J awA`URW `|. "q٥e^ifRSc䷭f-f_fn~5o.Yqv.rhb1˔C(!rAu⤛Z)yribj :$Ajgܒäfff vBh8-khzsk i` c3;u8a98 i!Ap9Y%1ڑ2֛ Ͼ`ɛy)aiR͔8kKkf3RmRk$v%.Z%_Hr\ ng&1>""qHik` 8۾mg}onlఘ0P!oH!Onpj!%j"6Fp9o v^ho>Фq̺ [Q4<Ԭ;S/r6<;$;%%Gr!ljm4dĶNED}σq&d%X87`9%!;pN`q &q!"-nhIcd4'@t>{SG3?sPW`MMxuXu\\u\D0*B$+ u> t+/WJO 3Wj 5w ޼!nh/QR'wdS)wtpv olcUhydh)FG]IkmНlKתcUGL: 1C3rVWaO@u<2tygy:v??Lyk#gWvDĴ,/IԊ/kmȔ76%ctP6]i9!Byj#IjPg OEqI*Gꯖv-? DGgtǯFij*l ߾-}: 7}g}jԁ |~Te4Ķ<_1$γilY~c5/nd0#X+ D vm~)_<6䉝If:D;SWc8E@%c $h:d@jQi"ZX )r$ɒ&OLIE+')s&͚6o̩sL-04:1jݿQVĬfA5s+׮^ +v,ٲc na.ݺ0bn~,x02U"ix1Ǝ&X`Z6xؿ5m^3hИk'IsiC߄霤5$]fM} ]#O8#vI,}:"Ge]0/C@xRWoEyI'0E?[)I"`}G`ҁ.}AE,Ia(}AQ1%qM y75h/cNhɤ[osv_2C&HD"`LLeALyF[n7n6Sjɦ%aD&]ƶenM)+Vpew♧LȗR%TdѠwE@9^H %Da:=hR4jWJjHjNс ZkJZXmD@C!LIHcؓhB-4d#9gyEW_҂.[ǐ +de0QfX&f%kWNekCrKeilvz'XlL'L@l.3cPyζj 쳤@-(\)3=aK/ESL [0Q됊1L%XQ]6YdnHqs um&<#gI9!9 \pL`Ko*lE.f3mޣ=7:Ɗ޺ÞPڵ{W6mk#f ޹ߖ zS/9gӜ4J'/_F~8ݾn-k $njc(EˊO[L4c(M!S$3%!h"&@!OĞ8!LsZ9'Ivr:p҇QO@jիGڢBճѤwk(f'M7q+ZW*uN L|Y u&K_&tKeb,Ѵ&HD)p:]%+ec'u_G+zkNNek---V*T6bqci@Q…Z$tk,s0@ aET!̗@X:URj哉8Z 14HOWz|v^D&Z&`iQ&Fƍ P*]0*(Z IzK] HXNAMe9;Pd»Ҝcw镉Ikc&5aWȨ'iV%bV2l+c9Z2e-{b3l39j^379r3l;bk#:a=;f4#&uggW|8&9Mcf&&zyMJ}EogXsИ03a6V`i`#®"']3|X}tVdStvFe# 1ٹLpC&/[ru5C]lnw0iQWz&42DkZص^VN8WUZZⶔƏɀEہ+Cz4.%hʸ&3=`C9bcOp"幑m 8!Zԫ鬥8qoV`wlpNr]nͻ.Jl$y։ǒm|xQ:NˋZLhun$K0J6 X4ń/~y?<7Ui sxopiл'~vot,C>C?϶_GO5hzLɽ&.gݽػMݖh!dR<li`"q5Q:P`M4C.̘$$SJ2` +'fY޷Q^FaӻS=6 dre!' ,yaF ڄNL4$Rp~~K{?gɗ/~ٟ!l9Dvp̓Ih MЌ1@J |̤H)1&V+Glb(",b(Ev,L4(N*N+"+ePMMc$Z M Bc5rMc6DXUM,Y\ c!b]".`,e$jcLL~(x)( $Ī@|ʥP$(G,ˈHH6$I30Id T6,pFTU c$P?4 Ge ldN,OH@4ච`)%dcT7  0 !:Dy) f<>6!"8 LH59UB@RSGz$$9 DlyEZ$PCLaNfxT\ff d% y$Gn"~SP#o _Vɴ8(qSĂa~"G{ĂALdl"}gH(7(G("|((yˌh,fN2J%L''U0gۨaT%<=pgLWi=v&ӑsRtfцZzu\wJ]xb" y6\.:$APzZI\E|L{4JHĘ2 (E@U|)ǜi)~ćOTNΘ2Kz$R4TĄO·JˉʒnR*ݰ(UK7D*,`N ˥2WJS.r#}aBc!ωah'&!SxfjP)aǕ }Rɀ pH~<ȆG6$H+y++fJ+GVh!pPKR+LGMͿ&+XoajͦFe:>֟(y)OgL*XD:|,gl.NJIFȲۡD&`~ D }|i\_&xJQS, 464)ī䁙mNQjʱ&d0L, :*JX²0l"2SڨJhZ eD'ɞF=)ҭuL| XЊvhfˌǍNЀn,jnGbgDx/fNhZPLV+MSV#T>or M]ک S,e) j]n .ػX*Y&v&X p4F/f60do@:4 rpoO]q?aM:9iLlS&oɎF)p 65 \#Nc0&PW mIkr؇]cHlMXܼ `L19hU&hPژ8&c/F#*0V"+ _r}L8c< pإߞFpqMZnL:Fs]0O #  -s@24JQUc8?/ /+\߬xq<^i^f14W!-d1.s.2;'0_۳s$&3Ltc8.]f&˔{LHB0d!L!e\ig}Zh̥`wR>sP0<3ԳH >Sc#4e{EeF!oMm'ׄ16ĨƄjE8X481.3Lg,[HϴĐtΚtYsJOKu4t[cHM?ńUe7 `CM8596i~s&tè: \;cJuթu5fg[71\;V]Gs9NhtnHI4LuBgl1Tb ? wy?iwEYuYYwvkvsww{wwxx)򲡨>KcеR6OTDWlt6/_qԍ}Za?ap\~;g21ϝs5*=֚}uzof_gwv}6򄶅i#G{g鄶132o4 ~ÄYZ0' #x!.".S="JR:8O`8i'ayI{f҃-rz5Pȗ9 pkS2)uN8)6r'»dC2-*߭#=>HGeO9NT]yӖkzkU5eYzg{_kkN4朞Dn[ffzu&(ֲ/_oJyĥW]z*p{z{{A;YxdS5duOt"6 IG:SMXayC|KQf[|ז)'bW9> mgq_I;!; <?:mDD7{ITO?TY-Qmybfuޙ&Ds1LA Nm iS2$S^AXQ-%#XzeL8U]QL^{#YuBb1{CggόJ6md6mʯ$!il$l#ȁW@\qwK\I=t FW):!\Ǝ7f\q?yi+&e4 MgK} _Ra'UR7ULJ:z!OP >h9}g5ƍXtD|^RFvKF^yY!Bp&a:2̅d [%P5a"9w9<|M,v & tMyYxD+^qegI(X@3& >ܢSX^>?ֺ5/!c>@DFK^Y\X x)p0梸A,GA\WPRNG\(7G$2.\.yy%Ne_B614db)IUєbeǐYMk*ey"qgu0YNsC B҃BilBЧ 0U'G@¿Q|PO$B'@˜w49p^qQB980%IR&^ 5ȍj4St)NkӞ" L դ1MBRlr_ʨGiSzln8fZN$'E)yUQHdHDJ4AlU4kP{12+}( E5ODns{([9YTfiEET4Cj>mӋd&Zޖ-ܺ drrq}jKO?V&UER$7# =^ :مhנr [[qӶ)|ڰu0BHK_b>oݙQ i4y.Bǽ~['" Dꐲ-XR P%≦e^k9F}ÚΖ:]\E'Q ͏V0y˩No S{9Ea4W07Etzh4,]p Ŷv,de/YD6hy׸ l7t61S}Bȧn#pk`uIgj Sς6oȪM&Ǚ,Gop_4vO"DaOMӛ.O&tF̮ЄT+xO$ȭC5˓ANЫHmW{y!97|7H祓!z,v5\V28Yg;N̾K:݆=uN]1>u I-B%Dt~|ǫ?oݛ_~W~`_P ^-V"5׶MvX!s:V.!ԆO?!Nm#0~JՔ@Q+4U$m*(OTתq"EkD;.)D7N^7(ŐLj":.aPr$\C 1lMk(!Z gVx1&1&Y IQbOX °.°`$%l߆NT"jh|rE$n-%Q +2캱252 !Ra ֑$ā%+#M"!@$w#`0Xa D*B"ϊ"Ar7.*# q+C2*u mor%֘R!o&3"T\ӆ (omUk !u0 Iz,!r**2;1 N+q$43<2 E3+@Q^fK,Dp&/T j#l~ ~Hrx/xU/25Ä31DzsH+A";:% :A!R5;$!,!n wABTpRn2 _mo@9K9O֘Q:!zjʂV Bf2ꓘ"TąBE2T64. fBJabC5.BbEJECE!F;o~JFDjQR!b#|T)$4*44|TH1I;3&r4!r;7]RTbEs"s#KGA#5;=#=o3/c7LKTrmclO$|O22LS"*ƃFjC)v-$-hTc*4Sc1<1"2Rդ.#00#P exTH_GIgUVVc5;1HwVa/W?SSBUKh)K LӧmX FO3bD3))SZA(Ev1GBK`)(MIJvJaJ.*cK2`[u;qV_9W?H;Sd=HO6"b!XvIMddu"vQ5fpuHɬ5mA>&%\A8aġ8't]#"s!)1z%.QdncedV]2Z~0fJ Fo۶o_\҅abXE?ob!tW!d#)4eiUr-Ws{U!s3]pՖgMK{YcB+u#l1S 5BMmi$j j9 %&D ݵ@Pl^sv3lF)hKug)Z>C5g svsZsuV}׷xxv0IDwVIc7H9d3wdV/wr4xsU$tfq`s~.7vIgu!.zv dB[>#')p2"l}b-"W0yl,clrA?z*`EFmًGMH{QXWt膒8f(؊RBDJ*P\cWI 3;B\BȎ3ȉ$JNnsvuakg5=Hhe3h3D/%&WH.qbwWp/FN_ b1gP0}Cm&ٔS'nlyjgK7B-W=upמP7 RJ$*)$*f緤|*v Fq:Ba*-DKfqyXs9e%ש7hȦY(S3룳z#kblDB6ik̐<7&X)`9g;oUV) {1׸t&>뫟PN U26"jAA&UtW㓍AZ!"' {2M ;GJ5Q,L9%Qv xkMy$>j" .};!ty Ɏ{;nɨ-{L"yG1=64k^m>εyjJʦzqJ)C-ïO@![P/ר%Qtw\|KQ%@B"ȌQ/7w11|!E}k\؍ԽJ|c}mu3ׯ#4=RXk$> NA"%!6 dݑ@h=&h1yTdeךݫ۝ޝ߽Jis}/eLo }-cB |i20{ѥ}F o&5~Ik 3րelD~=z]LOҞ^bi:uCdL^'T {hW- D>Ҕ>mW,kHЄ2k u9}?PRY~\>Kj,C{cPQIT2_.Ն'ʜ&?#&^| 1o}ZVvF&_TX?]߳}_uHm  H,CaX 1R 6kfИǏp9ؿ'=D)GsY#&IMb͜l )Τ2bIMSjBPpbG`0JٳhӪ]˶[Klx˷߿ J+^̸ǐ#׊˘3'ϠCM0_ PР!Cg*XBPq "&ͻg~KȓU3J\&TS%H]S'W,'zTo'z_e~TS[YEWa܂ 6Uׄ g_Uxveማh((xkqfC<㏂A(DsEs HyՁ M2yT&05T|Aɗw97qLI%|jI8!]Z&^ (>*餔樋58[m1@Vjꩨ説Z%Dt WRZg .Uՙ戉SYesVq4}-gPj9-Tꩠv-rjW!J5o^ZvZ#8#믊,wnDM/jʩ6:@9-Ԍl3{:SN t@6U''QWTWTy>\Pg+ƌ߀yQZGxB^3B_78M|;WG9[zN>;n1wGs4|.zz=3Hӻ7&ۗo~_>{-űCtPd-TǮSO)'1kel 1FS3!{{W Z8a6z GH(L W0 gH8̡wp^Qf>_K.&+@d`0n1zxI@z?$VH:%ʣ> IBL䄌4Х8$'IIjJ*II~DtDuZʆ$Nx)J/ 0G0EYXZg,oI'Ԕ!*0!M -x`'><*̦6nzRY["irǜL:-xN: 8XnHGfqXnXbAo"4't | "TbNO$0e1;4H˲Ds͚8ͩNH3-?HP2Tj;u!j7T[c 7Lo8 m+O|@څm$RٛڤO(E&d ‘ )-wL9r`OPM,h:l7{ r>r$!Nu-D[YҎVMmYLTjUj[mA'Gnx(hI_ rF ,H 2ܺƕ6!A^zmadw-P+k62~C״ůKزֵ~W\5Tp,]@@2P\$z'Sbq< nъ'/l!/b㳨@|p x|O+&$HoG[X>ereeiUE趫 q.:5Ք-а@čؕysK4]e_ƀ͊iIx[z'̐\8/Ҙδ7N{:_*RԨNW2ȑ-KLN(O2f\e)#ԭMb~mid;ٚTjW*>%&2Wb*W g6Ϲέ*/L:V tӇ"ן =@)^_*N-~͛mHw S0;>!Kϸ7{|cek({ɶ~~\*08Ϲw@ЇN =5GA,;WzNk[R?(d nn3K¡A+tHoLYH:NG eB \V@[ϼ7/LhGOқEXʪ~Wz\Qa WO ?O7_ 4l:M/>.zJo%a (%U۟q01 >B UWgRFpcU Ѐ88e0! X؁ xS{Tk_'G{_+Je }"X"؃>G>6X)fD|v6neA`'1] xy`xh1F+ach}SHc tXvxxzzHtQ|8Xxx~X8f5h(xHF/D!qfi>och1X ,@0V%k#FD1p^HRaahϔc8r8iyd،v`8XڸܨVdD8_`G#(hhԖi$!X%px`1Haohh&`@h HdxhbR|3p6ّ "2(*,ْ.YuzzDY|1"_𒭱' FyHC9HNe@Mn"^.1v# >q&`cbY@Q?qZudhXɏoX^QY` )|ɗE0 uЗ9Y#9Y)K@9Yyٗ9aAv ?x iQ#JO_#;p0)pI {)ɔЗwY`@O8ET7\I !WK_]({e0n9j1p&)A !M٩Z ) Zz X)E0ژ  Jj*$ yI S.:(1Y9 G  003B {.z5X D0 s:a=DzP9 }pc:C9^vj : :U::wKJKYM:Kγ9xQy: @b _P;ؠ0}P Zک:JJUw`O@ \FlOWobgEs_XH>QoX֪՟Z'Z * ʭનJ  3YJ:h` qqp @*3@;TLy:39Yڧ+v {Z;pJuj:S jZNj;S :sg9ɱòˤ*X ` ,ѪJzMR ̺`?Y+W97\Bci1Q`GʊUT )0F0 j`xNu{:  J|+{; [ó ac{yk {{kv/`uK}뺐˸Ḑ+(J2:sᢢ!O0ưuѣP[{0CU7: 6+ +`30+{P d q [{q}3k:i :0; %8'</2۰א}ó$&ktФ+<~( ~!*{9IPô:9;_@kȋK;: p`uk@qP[+ 0˷DžZu#2q f h0* 2h9gP fxX H#Pʯǖ0K0L˾Wlʜ˘x̹ͬϠ,ʰ`[il: j,L{,i\̿LǼڼ/ڿrУp<lb뼿@*1ݾ`x-@}$O! #[p1ݣ컌E 3B|)LIԗ@Ix[K19ې !똮ϋ [=Nn]p 81~줩/*/2A-L"|K, wR\߱dE )+Ix1_M?|o-I~nN|q~~ Kꦮ F :Oـ~Lo>TVXZBxv^N HDeܜ[i pt_vdopo}+0pz@jOuh/~poq cڂwuĞ~ 2:xa +-*n/} ,3 ҩ>R* 8|&&?9RJR]|1Դ?:l!?|Od_>q.DirY. 0jO5F= aD GNpB-SLV1"@SN=}TPEETR3=_LU^ŚUV]~VXe͞EVZU WͶuśWX?\a(~FKYd.7BZpWIҒ|Ƹ0%m9{fZgvy%ㇲUnse/B@tҿxZN-‰fZaϵ{8h-o;*!A,/VO>ꈘDJvq"Zut&Q!lGzC$RH_dLG" ě2$2)"lQr3 SF*̓8 l29 l r"›Ns(5$2%LK8@-08"'jUW_5VYguV+W]wW_6X"v.FE6Ye՞4왷FS0Ti_ TeZn}W\u`jC{k.1FhU^cUNZc)ؒc [f P)$yfטm$`W?.^ xc\jC:cXB8+x4Fg].d%f٘+vb"YgY̑QqGȱ,M$J|I.f$G/(ԛ>;nmχۘ­,8 .[v7]6kK0L[%\Usvo=wkf>x'>Xb2xg+gyKpMz믷3={﯏='||gcvs ~5域'q/kQ8@ЀD`@~}8A VP}AvЃLJ7BЄ'᎗<ЅzNʐq|K , , \4agC!=D&6qSaD'VQDvt?1nM@\8Xx*cF2l3D#юܓnB;,яDBBҐT XWb2hC(+ rN҃[1%vѕe,e Ke*euK=NRf07HӘDX84XɄ&$}9Jbʥ0yMmJw]+g9NrӜOɁj)9Oz֓(Čf>B*Rs&?zi:8ABP6ԡB-FԢhF5QvRZ'EiJ&hLe:S|$iNuM|ԧ?jV8FAE* )d uPU[Jj SPiX:V7'QLU'dk\zʬ,wk^R㽅zl/ElbX6_H+U XVֲlf5YճTfE;ZҖִEmjK.$mlٷmnG)ʠhb~+vY C̐}#\L}60\rA|!T&?/Fo| 6I/8HOgL|+w-Y.sE=jRڔb6uU3osL!s )j<Yյz?#φv=mjswӞZ@jnwnr;(*PX&\Y'%Y\oeK sx UpcRmGmex%>qqw_xEg'Gyugqxe>so7#9WJr>gυ>(GG:os_eDzԥOWUҵuxM;TuվvkU+U{1wew]woNwgx7~'aW|5yw}E?zҗG}Uzַ}e?{o{~?|G~G>7~?}W~}w6?~Gտ~?<!,vG  "$!!&""($$+&'.((0**2++3,,5--6..7./8//900901:11;22;23<33=44=65>86?:7@<8A?:CA;DDGM>GT=GZ=G_G?@I@AJABKABLABLABLABLABLABLABLABLABLABLABLABLBBLBCLBCLBCLBCLBCLBCLBCLBCLBCLBCMBCMBCMBCMCDMDDMDENFGOHIPJJRKKSLMTNOTQQUTTWVVXYYZ[[\^^^___``aaabbbcccddddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 $LI0)! "|+^x0Č=Nl(ҟ?y4AwOnI7crB2s?e@koէ>wEֿ+NmXO)}[!o^mhms%ߣ?" Fƀ !,    !"###############$###########$$$$$%%&!!)$$,((/+,3/0633:66=89@;E>?G@@I@AJAAJABKABLABLABLABLABLABLABLBBLBCLBCLBCLBCLBCLBCLBCLBCLBCLCDLCDMDEMEFMFGNGHNHIOJKPLLQNORPPSRRTTTVVVWXXY[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22xH!x!  L"Æ UD?zh!’"1񤺈-O[$#1<ΑUE@GDԊ㑉\^uBr.h3?!,v ,    !!""#######$###########$$$$%%&& '!!(##)$$*&&+((,**.,,///111344577788899:;;<<<>==@>>A??B@@D@AEAAEBBGBCGCCGDDHDEHEEIFFIGGJHHKIILJKMLLNNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~221$G0d‡a0Ń):h1F V#$<1et)1!)aDNЬIp!H8/Ef }ia*&¾J:$d1Yakl=HkEQs˷߿+x0L?s?<2/Ӥ<3Iυ1' f >xqb֟;#9kځ括7ä!,v        !!!""""""""#$ &""(##)%%+&&,''-)).**/,,0,,1--1..2//3004115226336447557668889::;;;=<=?=>@>?B??C@@D@AEAAFBBFBCGCCGCDHDEHEEIFFIGGJHHKIIKJJLKLMMMNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~¾ÿ22 Hpi*, j7aĈ)Z0F V)ȁ]8俔*!(ʔ2gH*|9Lit;CF-Jw\+ eB&ba&v}&TEڅv6_jS!&akBSśv-G*IRJ!,}   !""#$%%&''()* + +!!,""-""-""."".##.##.##.##.##.##.##.##.%%/&&0''1((2))3**4++5--6..800911;23<34=55>66?77@88A9:B;;C==E>?F?@GAAHBBIBCJBCJCCJCDJDDJDEJEEKFFKFGLGHLHIMIJMJKNLLOMMPOOQQQRSSSUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 [@&4/D)^XcCz(qd?>>???@@@AAABBBCCDDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~221(Ga20Ã1|HQ!F0=~>E?@GAAHBCIDDJEFKFGLHIMJJOKLQMNSOPUQRWSTYVV\XY^[\a\\b]]c]^d^_e^_f_`g_`g``h`ah`ah`aiaaiabiabjabjbbjbcjbcjccjcdkddkdekeelfflfgmghmhinjjokkommpnnqppsrrtttvwwwyyyzzz{{{|||}}}~~~2274G*\ȰÇ#JHŋn@20Ǐ CId 8\ɲ˗0L1͛8sD8Ο@ УH-jTӧPI2mիSWS٣a#{[iC]=D—ݿ?<@ֿ$+^L?žf7 7?'1ƌ@f:i1k'pM8dͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)Ov9vIPa_ :\"Jh-%Bzy2P.䨕t駝ngb'N]bg'!,99J$     !!"""######$###########$$$$%%&& '!!(##)$$*&&+((,**.,,///1113445777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJKKKLLLMMMNNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~221$G*\Ȱ!B C:HE "Zȱ#ƌ;#H(Q<ƕ=918mȤɳ$Bv{ %?tA,J]2%nHT&1իR @ߍY`lƿpnarHbFP&0q+8c'eM_vh(?k=gҥFm4լ'<;ږm7V[۵}gpFg> С7gh45;=s!,99          !!!"""###$$$%%%&&&(()++,-.//0222534756:77<89>::@;;A<E>?F?@G?@H@AI@AJAAJABKABKABKABLABLABLABLBBLBCLBCLBCLBCLBCLBCLBCLBCLCCLCDLCDMDDMDEMEFMFFNFGNGHOHIOIJPKKQLMRNNSOPTQRUSTWUVXXXZZZ\]]^```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22G*\ȰÇ#JHq3jȱǏ Iɓ(b˗0Ud͛1ϟ!CћȒ*Uzӓ: "URʵkЃD/zK_TD͞-˶NZsȩtU{w޿6/*bj≠P#$W˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνϋOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($hte""(`5 9cdB9H?4ߓtsDS\^0@?M?a*BkA\Kfw/*s?֨@ߜ 4!,GF           !!"#####$###########$$$$%%&& '!!(##)$$*&&+((,**.,,///1113445777888999:::;;;<<<===>>>???@@@AAABBBCCDDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~221G*\ȰÇ#JHŋ3j܈a CIɓ(Eb1˗0cʜI3JkɳϞ7qJѣ Eʴӧ(1:XjݺT-Kh߅-˶ۓ%xxUȹ}Ν nǐ58̹sSφ ϨS7]VM6daqMXh_<%kKR\ 1ʨkνöOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h.}"( Z*bs_1ڨ_=A Y-91${N&{N9e{8&וc\W9 _di&y-0)ߖ!, ! #""&##(%%*&&,((-))/**1++3,,4--5--6..7..8//8//9//9//9//:00:00;11;11<22<33=33>44>55?66@66A77B99C;;E;;F<>H>>H>>I??I??I??J??J@@J@@J@@J@@K@@K@@KAAKAAKAAKAAKAAKBBLBBLCCLDDM@ES@GUCHTJJPLLROOSRRUUUXYY[^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 8ЅN*\ȰÇ#JHŋcƏ CI\ɲ˗9zI͛QɳόɤH)(S Az\ʔi_ҦX| UΪVjK$BtA RpK7Pp;պbR0`ŕɖ"T.ϊWБ%']IO>?|#P>XS&W8I#ba')d'Z^ד$Hi!,D      !!"""######$###########$$$$%%%% &!"($$*&&,('-)).**/,,1-.300422555877:99<<<>==@>>A>?B?@C@@DAAEABFBBGBCGCCHCDHDDIEEIEFJFGJGGKHHKIJLKKMLLNNNOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~2210G*\ȰÇ#J@dċ3jȑ1tIɅK˗0#8sƜҟM@vLOH:yҧP15Hiԫ@\gחZ vȰ1˖xF]۶FBݿ?k?l3+O@MsiDXi1.~`?S/B3հc˞M۸sͻ Nȓ+_μУKNسkνu|FgD?^=FK/aς _`Q?'_Q4~44Xz&4!:h=3a>a ĢB:a>d?.P@!,_3F            !!"""##############$$$$%%&& '!!(##)$$*&&+((,**.,,///1113445777888998;:9<;:<<;==<>>>???@@@AAABBBCCCDDDEEEJ@FM=GN=HN?IMDJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22I$G*\h #J¿3j$h"č 6Gcȓ,I+%̕ Jx;psf$I*7D•ը ȬM6߸hDݳq1YhĚ ǐ#KL˘3k̹ϠCMӨS^ͺu|8?N4  ɷ̱96%c[ ANYz_Yv0?Wr:)ݞwsM8ʳğ_)!,C(   !!""#######$###########$$$$%%&& '!!(##)$$*&&+((,**...111444777:::=;;?<<@=>B>?D?@E@@G@AHAAIABIABJBBJBCJBCJBCJCDKCDKDEKEEKFFKGGLGHLHIMJJMKKNLMONNPPPQRRRTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~ھݽ߻221$G "JLmD NXp? 1fQǏ YR"84eKLpn&6ovN5 %_QeKz:D8OЦEwTgxV[b&GД; Bw6J\RA"%.]WR„-Μ8.xd ?(E:hb6q }_ s7|C3W !,:         !!!#!!%##'%%)''+(),**.,-1..4/0601712923:34;44<55=67>78?99A:;B;?F?@H@@H@AI@AJAAJABJABKABKABKABKBBKBCLBCLBCLBCLBCLBCLCCLCDLCDLCDLDEMDEMEFMFFNFGNGHNHIOIJPKKPLLQMNROOSQQUSSVUUWWWYYZ[\]^__```baacbbdbcecdedeffffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 8П?4xPC >tPD YqaƋ5pÑ f pȃH_ d"ųZpٱ(CBs`RI:)B#^Fܪ2! b)ET<5v-İeզs0nrF&'y տ8$L ſr/f`J/VO4`&17%HDgBL!,6   !""#################$$$% &""'%%(''*))+++....///00011223544766889;::><D??F?@H@AIAAJABKABKABKABLABLBBLBCLBCLBCLBCLBCLBCLCDLCDLDELEFLGGMHIMJJNLLPMNPOOQQQRSSSUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 4P`f 2LDvgqbF9Bq`H:xҟŃ&D)0&Ù4mĩʅ8aRbP׌TZBk2dFЈU#QM v ?%^U~ȵY ΊY^nRUȁXiC{ 1!,6    !!!"""###$$$%%%&&&'''(())))***++,,,---....///000111223334444556667777889::<<<@>>B??E@@GAAIABJABKABKBBLBCLBCLBCLBCKCDKDEJEFKGGKHIKJJLKLNMMNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22GA 'Pa &d8]TXDC?HqG^ICi#B%0̘ >g3(̆PYZDQh h;2PXk` [U&Pc!&p 1!,*+<GLRYejlgaS38I Yhnnljj o q9sEsGsGsGsGsGsHsHrIoPaa[j[o_qdrorprqrt j _3R>JDDI8K-ORU [bjmnl ic](Z5qX?iSD_NIZMMXORXQUYSYZV_YVjYXtRS}JNFKDJ=J3I#JK LLPW_gnrtvwwxxy|~ ~    !,;CFHJMXdnw}}}zyyyޜޜޜݜۜ؝՟ѧ̴ǿ¼ҿȽļ̽뾄wutssqndWOJIII22HA)\PeHHŋ3jȱǏ Cا'\8˗0cʜI͛8sɳO~P %r@??*]ʴӤAz:ʣ|fʹk.D|R1JٳfŢ]˶m9mܷ]Ź$}F5`*U EcU+LR%;X̚ltYO.a,C;9ڸbuN8qTzK9h/7Noi&acC{ߠrKs;t銮|okzg|goG!|A`{ VW!r[gdI-pP)w}"@ .=ߑI.HW$9wD #szTn[)$,O&EyfZ&$"pi9$tfI'wJBNM&)h3ԝkB@yy8*0%^Z)2r|hg * *)F:)zi$ZjVj^ !!zެZZ촳A#(Z߆{ڒ*k~ lZo(͆ZI/KlX{ن #ߪ .۱K)G2 Ǟ " |2)@ڭ5rD9+ SAᨭ@x!2nTF֌Csub]bO=㐭5կX͈k_v(V3Y+7t=e k5-~]7RKbԉ#~xPP!褗n騧(z02gi{{RB=$''{آ|/:r'Uxo觯/('>oP߿CEL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&Nb}PQXt9.Y m,a MFQ!i6*o@;q%Bx C&2`dd#GJrd/IM*R*q'7 ʆTL*Sq㕰+12*WJ 0ZҐ\-L64f #)dryhDXAr.,9 5bp8} +fCA^Û  iuNq΅S!0:|qǙd7U"PР ͨCyAkt8&[L ("WTN:*wTGN AEmT`XELm SQUV* qQ j*E!u\ԗ]i$}QW<@y$(9GjͧZ{TԾ&4'H%#X?R4 gaӁ5jNuŽ~^:XwVR$A>ϙf}g m`-mMkʶElSZ q)pkY3U%q ŷbUnkĦ׺Mm{sggs贳%hIXem} _2w=!LϩMhj՝l b+eIb֖*I]J*-fqc!#&q,Mؙ r-cؙ!rK8c=vWUzJUy*3 h@1\YsMB0_ͪGviN#bqղ^rz~s*d*9m85RQ XV;Jwԝ6v}Ľ7QC+\] ; b~4^ۆګ"~ktYZjjJ%\5Wz`x5GPnv@q{ggpXnǥiN%m_J=^V|gAqSFqȵyPjfgjj:Yt4eterW ~FeegegYEQ&X5AvRev+Php7J:&KMyU=r=tJW;IxWJsh_׆/ u2)usgkuavmWJS6hd7~gǏiN_Gx[ 6UwwJV,@ Hxq6~ȧJFEyzoEʡzzm+w'3 Ήu* o7lmg(~җfzKI}gBmwzyj{o2HTFhWq*C;fץ[~~ɰ zyٲM;B+/{i~E'pX5ԳfWsɌ xngI`X W6Hw'yB\|w׌_9Ifve*{Dm[*tyQ8XSj~+ĵpcce:AP*bV|B\+B[b;DhCֻgډ DX*xȧkDG;fzzoJ:gxgxF|g(6H˳īzȪlH4{'x JjRZˏ7몄{yͺif)6{XZ[::ڔLVe ?n.:mkB;ci\GwKx{C-4F{]!! I ZElPfX7h1Kj6ø-ĵ ;ZIg{peL[yW,Dw6Āz* LW;l^;xvۗ+߻({U&njiGu'J:ʸlۿ5ڹ{g['tiKK|Qz++t<;F=i*謭W[kˊ̻}r%l[Xg{gˏmCuک껩꾨:W'hhڿ;rB].'pqk,9~-3L a뚓/ɔ `-´j$m7 tz{EG,>,@̗B K kڢqAܾX kJ|X<9y"^\zWThk=,meo*֥{u|ul}{~j++l*ҙא,aܥ=-̣5^<ѬR|B-&)o:Q*G un z]∡d&|^K'̮O=V-kL-fkhNoN u|}۰sfՍS>y^ w7}O|u"d\ł}^;yʭ)eށ DPst>vAtپINksx<֙lk$ˏ\ʑ `pQm8`ukξd$$˜ =ӎ 2SqWQ}%҆VCܯl>B=K KL&~$H9rnR@zA w$G#/!PWdڗFWA<_A6= dKAgVSG5hvB&Zyx&\DT"*XZ<ճ vT$ e^Ag񼅾L?qfH|+g:pNt WΙC]e/lo^?yG 4C_Vo5 oTMyk.xz* 䒍v_v^f@oABs*Š 3{}?e`N -K?_DDoi@ۖ_`fO wDžc Q6D-J,h`7ă!Z!?~ 0aqbFM3hqB-]V̖hR[RiXE>y1Ξ^T"דȐyz<uDznt!B~3P(hHS /-炝W^}sW ~*X,aÄi:Xq,_lyd΃{tX0??{{[CW,vCXrf⛃G\j=y`խ_Ηٽ/x0mZn$>Dm"K~0it,m*/,Z * :[ti(1 ăʊK*ŸTʋI@k$ᩤɽ$X)$"Z #yKҤ !: %2RI ŒZ 5ǖs4i11iH̨.=W?iTK6# h RTLlR20j4QNdSe #38=: j RA{RH+5OA[j%KUWʣ]ߺ%d$mƐ6FWcNX ~U [ Y^aWn֥`+*Vq lY6-Z6V S-ō0V Dpy$}t][PQ:t oshZ!7!z܈ ΊaEߑ&niDdNpl: Rۮ0 rJYx*FՊ`DFQz sݡ4iXtDB77̸i:-Ϙ win5rwN:;sσG'$ K^T\m[qvIR9f]NvBإJ!SUsvvm?NΦa%ۍo]7{J!$3\\Zc7L2-v E JS6|IG׷9;a ~  $MUjb$F&0A+^CA棬E*3$( P5̪N7ԽMVɢu\\pU$|.Ml9㠘"c\Wσ.x.z=gJ5:lZr^2L޲c ť 2BMz{”pl~  I$BQƨljZH%<;NR2dX;vkaL`,=#e4` .DZO% L&\~L2icQ 2$ -\\Y`J&tkgW;:oyt7!,8Z,  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///00011122233344455566677899::;<<<>==@>>A>?B?@C@@DAAEABFBBGBCGCCHCDHDDIEEIEFJFGJGGKHHKIJLKKMLLNNNOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[U[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22G*\ȰC>Hņ^ȱB=IQ⿐$S4hd˕0=Dŗ.m꬈3ΟJ NC=Қ&AFtԌTĪ֟Sszjsh׬dfL[5,۷pʝKݻx!^R2 0_D$>)[(a hHfxڠ![V7̠pʲv9 ǃ 'nFf)_Hy2a.?'¾K~P|C'p0 1!,#    """$##&%%(&&*''+((-((.))/**0**0++1++1,,2,,2--3--3..4..4//400511522633644766989;;;===?>>A??B?@C@ADAAEBBFBCGCCHCDHDDIDEIEEJFFJFGKGHKHHLIILJKMLLNMMOOOPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22Gd C_txh1_vDFGu$J3eG.QSf{tF4thB (5K͂J}rHU}(UK k*B2/fT Ck0A![Y| 3`# ԁآ4LɎ|#8ti=Ȭ¢$kmT_Dؿ;y_2KЉ56 a3!,*m     !%*.013 7 7=BG K$N(Q+T. V1 X4 Z6 \9];^=_>`AaG`P`Ya`bdcgdkbm`o`sTw LzE|@86~9z@y Cv Gp Od \YdJ p7./3*7%:!=@EIL O RUX[^bfmswwwwwwwwwxyz|}~ ~ ~  #6K^x܀܉یۑەەەۓܐߊ{skf_W\chyodq\saufweye{f|h~jlmoprtuvwy{~{xvuvúwҼttsttuwz~~22 HA)\P#JHŋ3jȱbÏ ;Iɓ( ˗0_N#x9 HRZm-}YWpyMh>_:KO3)lxpYKiT8p:pϴkA[KACI~ªukȂ8ٹl*7ۅެ%lEb=l0`5Υ>mEtG {5OPGgKVhь"&Wx\Ok5N>ߝC$Wm{?uYA}l*vM}m">0tPe[!z@%USTarr|OSpuyYzf?frfhx>#  64¨WUAÓ%VeV"`աgxH8uc@U)]iFv_J*A釈dc&6H|{Pו#x~=b݁٥/JfVpUY&a%ix!g7DnS\nJnIbm?S t j'O1#+UNٴ>1{]NѧVzixѕ%CbKֈR'ugV dLtfdtT6G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.is328$?1 )^L0$;1 O;{>| ),q<B [o1#o<Ǩ.1ψ_qǏ,D 1pMPk^H W.f"08̡w PD&:P!!*Z^ .z` ؉VhlM3bpH:ы} IBҐhcAq #*$'IJZ#7 C-~e(A QH"DIJS: 4؅iFh-U,!JXr6RIje8D5S Nm3L&9z <`kBBv " |s =:B⌲(F.ZayEBu) q9Py?Rz6~=Gы8]g;NB⧀D5S;L@P 8H"fB^E09EթP*USFkUPԪժNSҖ&vD>׿?%Nӳn/+]浬] n5^j* C`5kػbvkeԻ֨(lPA浭ۈnK\@(v.r9S8XX-|rD;X-%#6W%1@!+b*61#b).a 8- lu>^d([PS4 0Ŭ/{ G!'npX|1a Her8w̃3"5Yrw΂>4:0Ӡ.WmT`jLs3Ћ>#F$κַf4im6úՑinz4mOVDC=QΠj{݈M v#ΰm(}筈MpX3l(Poxv <qT@'Ǽo0g~A @}n(X9g CԧN[=ꂸepW{ s8I9d 6N|c݅u O|'TԨ@'O[7<6s@ !A?j,wQ dA?8@!,O---+*'$   !!!"""##$%%&&&('(*()+)*-+,/--2./400611723844:56<77=89?::A<>E>>F??G??H@@I@@IAAJAAKAAKAAKAALAALBBLBBLBBLBBLBBLBBLBBLCCLCCLCCLDDLEEMFFMFFMGGNHHNIIOMERR?WU>XWDTWPLYYE]]B``>cc;ff9hh5jj2kk/ll-nn*nn)oo'pp%qq$qq#rr#rr#xs#xt&uu)nu-lv1jw6hw;exAcyG_zN_{ZV|qM}E~9+& !&,5AJOTWY]`djnsx~DŽ‹ßɚ͖ҐՌ׈؅؀|sje`[QH=5-$߿߾߽߼߼߻߻߻ ߻ ߻ '3>HR[foy22 oA>~W/ #JHŋ3jȱǏ -Ϋr!.˗0cʜIŔ(<͟@ JtΜ8y"_ѧPJ:N9-hׯ`f҄ ]˶TWRJxIܔKap^}`>Koܾ#Skc 5YΨS?̺װkM۴c r ͻ񋊒+_μУlϟyϟ=EݓNxs|廇>y{|+O7Gr_}ƶ_HfȄGaBI-gH F!>\Ha,n6#衆L⍇UXb*)/($a;#"ˈC6Y؅PxEI!Xǖ\rkOW]i&U= DSgn9c ix|矀*蠄j衱CO<;3#:di&}ΦjN=IOjJOy֣6i.9˨tۼѪ|뙸f^3,Ϣ#ϲḿN4rD,~kfڲmD˷nzMN6ӂ#.ӶtoͭB"Y)Қc)qMtLe Ȭ lrʬ<3˛{LƦ4gzCL쎲P(kTWjMdݵh N4s-l7i)v)]w2NJPc@S?0?GyWn {9Nr?0:Ri\ķUGh0TB8jpB8u߈+OٷtϏ᳨?bwϾ d=ԡ}l_!,yH>    !"""##################$$$$%%& '!"($$)&'*)),++.../001333556779::<<<>==A??C@@EBBGCCIDDJEELFFMGGNAGU@HXCBYIIQIIRIISJJSJJSJJTJJTKKTKKTKKUKKULLULLULLUMMUMMUMMVNNVOOVOOWPPWQQXRRXTTYUUZVV[XX\ZZ]\\^^^```acccje]pgXwhS|jNkIlEnAo>o:p8q5s1t.v+r*t-t0t0u1u3v5v8w;w?xCyHzN{T|Z~bir{ɮͲ̻22  *\ȰÇ#JHŋ3jȱǏ CIIS<ɲ˗0cʜI͛8y0ϟ@ Jљlz<9%hK;^ͺuaU'l׸sޝxqZ wpȓ+_X/ سk\;ӫ?\޼}Z߾( LӀ& ^FPJh v!  h≚;CO<NF8X:?94&Ѝ:&dW?ΣNG%Xfy;Pv=pdHji?LR t„kz9E gu*H=f;oW6Fg=|R֣f:G騤*OkSꪬ~4^Ci9Yj D.kUmqf#pf8gJVP+^OP:ҟWnHUFj.H6Z ?֋(wOfgIFV~j. en~lrf %?dsu69R.0l&*9@ܬYc ?H)!CPk@WGSÌ)[_#?Ȭm'b?MB7pwL ބ؄1 ^"0.WT!dX|TͶ@xζ 8๮ˮnuk@;rOmn.2ay!,7  !!!"""###$$$%%%&&&'''((()))***,,-..000222544755977;99>::@<>E??G@@H@@IAAIAAJBBKBBKBBLCCLCCMDDMDDNEENEEOFFOFFPGGQGGQHHRIIRIISIISJJSJJSJJSKKSKKSKKTLLTMMTMMUNNUOOVPPVRRWSSXTTYVVZXX[ZZ\\\^^^_aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 H*\ȰÇ#JP:wՋ7 CII[ɒ=uOʜI͒r޸@ zRϣ+#ʴӧ!z'ԫXs*RyݴK;^ѕ]8^mKnMp˷xyKîy3̸qosL1dM\_H i|tCmS&`>:۷[6wjl٤[]xCr6KčKON]Y-SPwm7կvFU^VO}A<'}R?`@C+,t:} j`Іv83>~pmp"ũ@ j;8涣h+yܑ&-,h QJ ^p?Kآ%j`>T ¥k~٦I͝D玻FjJ9袁(x` !Z*@fzdZ jꨨ: .j]&dˬ"+,S" *msn/bڶEXpvv)ޫj)_+|z ;1j{1ۺqX@!,a.0  !!!""""##########$$$% &!"'$$(&&)((***,,,-///000111222333444555666777888999:::;;;<<<===>>>???@@@AABBBCCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnoopqqqrrssstttuttvuuwvvxwwxwwyxxzyyzzz{{{|||}~~~ytpnnpsy}{{22 HA_)\˗#<׎ŋ+'Du0Ǔٍ\i1^:'ձ $̈BdnMw\ѣѧ TGO*RjGOzWF9$KOkDGծXL&+kX]!a&V UǏm72Fo,bDι=CȿU88A:;D<=F=>H>?I?@J@AK@AKABLABLABLABLABLABLABLBBLBCLBCLBCLBCLBCLBCLBCLCDNDEOEFPFGQGHQHIQIJRJKRKKQLMQMNPNOOPQNRSLTUJWXHZ[F^_C^_C^_C^_C__C_`C_`C_`C_`D_`D_`E_`E`aF`aG`aHabIbbKbcLcdNcdQdeUeeWefZfg\hh^ijaklcoohssmvvrxxvz{{}}~}~~22f "4B18ЈEq;"P,?/,òp8s挨'Ϟ;! PѣG#"]qӧO.M իW!,  C p yt:tEtKrVf \M`/fu " 6T m rz-=FTir{ƻct9t̆!ږ=ߝGXnΆۗޚ22 H*\ȰÇ#JHŋ3jȱ# CIɓ(S\ɲ˗0cʜIǛ8sɳg}>)%H"ġF [ʴ}$JJիXj:5*ׯ`ÊJbEҳhӪ])[n}0.ڭ^˷Լ~ [È8\';Lc̹iaȠC}PaǢMܹ묚_۸ժ~:g {s+_ΜﵽA?ůkNOշߛ}T*oP ) J-%?MF`Zv,qՃXUu~8O2D(jh|(Oe\KtB7^"P G5ȔL ZEbUjPf!&:`嗧 ` @4# e=fD]XVKR' X X`6Q;ȕG/E#F huZ#_U܃]+N8E9eK<RhF6,sU7Rz*+{NSR+-B2k9eSR_E>h$*KV`M˞o)ZU[P() Hytyx.Ds!z65/R&*p2l@-^a9L4, b2LP2+n BT1t< 2Kd `XC~#cPq. Kq'rm6{dg^ilW'E;v (A$pLV@+kB(µ]0( A|*$,!gb(C08d BP#%!qXHLBj&:P%ZX̢!H.z4"-8D60n(9fЎ/8!xb 8H񐈴_"Bbё탤IJƏm$"uo (5J%HDeTYVrm&{BV:%jĆy}Mz1*81x0.^l .i6| ؂~)6W`2( Mj d|6$_Kdи` cf>9dk|S0F5J @Tc]@ +HD1ъcm9$$:`tWyԘd> ̔!iI%tJHq#l`)Ә~((fP}l s >Z<TP tPCK j>jӧJy%IO5YXEVAU*^y׼{B7$um|]aoJu,dLyOiհBJ&=FѴlG*k6=:e}Vw҅Ԛ+V1wZ\z草\5WQYPtHς`\o8 VN:'ߡ3Voyk/ˡ0DdMf0Iꔟ{ؕ'A*G QcLQFXŋqAE dtsO5&MMj#N*w43k2YWLPyx*טcWMj%CӨ^,6w"rG k5bG "N{ih/憱ֺZ-gN]Zw>;~JUT496i]$$xS ,ayu*4aS5R{@dF s_׺9voYneVyӻ-EG%k>wMuJdzT^$}K:ԃ_̹͙D;޲+f{Ձ7&s^qJf[K|>'nט2džxvc'tqr7S7}IX%t[ѷZ }|:v6}8)/TJ}sN>g4 lJ@&,d^jUCbeRh[YVC{>FOk>':9U],?iOdo|1UJ րk(JGDIHU H(DHG4*G#XC%hF'0)4F-(C/(Hd5؃6adݗFBXF,$JL؄NPR8TXVxXZ\؅N>2t%Z3bo HlXC"dY$΢vjn|?(~%(AxE(8x@hE(3|VfgKKCUvusfVLR4MNhNxuWoWNTNg$MxNĘNfd^{ha5P@Qi"~u5y(ҁ;RVVMjLYWT"WJō=[RSrœ^pf}Y"$YVTFrgVlvÑ9R'.%p<%l$ucSWsWPtzeXY[ؒ^i1B%YZ[p!YLlfYXVTX)l9%liM_ydY0)A2;˥shW@?s?Wg`_K)EkOɔ51_` UHa!xX&A5tlx@N5[ GarJlx6Z]fxpu_ƗdbQ?6GQ͙kc#y AWc~GrF6[Npeg&IeNduzL j#)*]ma6fffV›`gkYev%ԗ3Zm $h:sʁBU xj'PYk*svrnhžvZ6j WjmyǍ2l9l 67N,l9lvcMeTMWIj"$=ufs:@ɵ?VcZy1%0ʓmE$ !(Opyq)q10NƧڤ YIg`IW#i>$yz%t6&mŠ}Epv: wiI$GZ)\oájl*RnpjtMp"vKgNG*cguuT~vYatzSuu5IdYfZ͊q0*6SKiWgTD"=唿ƒҺmhIKZrmš'J;y$*"eY&y:}.|ʍȤ#izWv kkÖ{x|Xꩫǥ5:=t_g͗oM*|eō{+cJ߷~oC@Ck~l%G+D+l~5~it V^;Dԩ"xhfc 9!$m۵Ce x;DF8)ry AcCt+˸KuKo۹Pr{[ᅨۺXH;33\|[K;@{};uڻ{F]e> ]lSǬ ڐzwAoߺw֛*ۭ*mî)]l¡Ta>&zy sOu?Q?{o l~ Ud "e\uj{'+5}73M:4N+AkIC஌yAKMͽyR[vgԻ\K_~4D8 ˶LZ (JfB]nKʒw( "N(؏(NH'޽%?%QhnB,.ɫI۾ZT4NȎCcB븁1ԞюB{nξax~2QuQ0 yΎn*(q2ocmn: " bϓp&&𣱁,!1֪J\TB=,`2O7}k8>vb~(`R(FxF2BO(NQW\*O"& !RhPA6b *X7`͑P}|FT _ޑ}E/A ^F(P SPfjmR7xoz_2nf]F-o΢݇qiZ"o`rEx/]ymMOit˿5_GFh⭾I=Zqc? QD $QPD-^ĘQFk\(Eǂ2Lh • $I5mNܗSNt2(PEEiDMސ?֐)֬ a|s`HeV?Z *ױśWbUKW`< 3hN?ndx'WƜrf'2E(tF]Ċ[ͳmS}[wܻ1.(tiߝW4 rN{7Gl/8xî~rzIg?ݞ;8{f@Dۇ}+@{б"ljB 3z¼ k '$0D,$KD"3^1FgFo1GwqgG#D2I%dI'2J)J+2K-lQ#3L1$|Z؇6̈́3N9N;3O=O?4PA'V4A}RAQE'RK/4SM7IWpQG%R@SUkM|sUYgV[o5W]WHB4(HUWN`1GARc6ZiKyJXk7e`!%\sE7]Y5Xn-VAhq7_}w_v5-n`F8aeׅ؅b/8c?u8b8dG&dcd_9fWEY Vfwgm?nhF:ixb:jeZX:kW;l&lF;mfm߆;n离n;oox'xG>ygy矇>z駧z>{/T}nG!)? ';(#_@$pρ%گ `0 "H/AITB9Я4xސ 9@h}0DbC<"A `3p0"@˂>D8HX=1f\BRC ~쇀/{AGGLb"cw>~G1 B$HBTF1'2 bbQ% )IO&J\Ql,m)LL R2?xK2 t9F-P &j}0Ħ'ξȎ6) :)?fr<;Gv$/o [E)²QA3TIbЖKA AREAA'Zxޱ|RpiV&2KΓ*Y!FP:BD>?F?@G@AI@AJABJABKABKABKABLBBLBCLBCLBCLBCLBCLBCLCDLCDLDELEFLGGMHHMIJNKKOLMPNNQPPRRRSTTTVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22O:4#XF lÿ&`Ł%zC>?E?@G@AIAAJABKABKABLABLBBLBCLBCLBCLBCLBCLCDLDDKDELFFLGGLIIMJKNLMONNOPPQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 O DȰ A90!CE- vD# rcɂ,9.|)0B $l5< :k3ZLJkzIU3bGYbKſj,;IOZ,BV x 3B4!,w$& !!!$##'$$)%%+&&,''-((.))/**/,,1..4/0711822:33<44=55>66?77@88A99B::C;;D<=F=>G=>G=>G=>H>?H>?H>?I>?I?@I?@J?@J@AJ@AK@AKABKABLBCLBCMCDMCDNDEOEFOFFPFGQGHQGHQHHQHIRIIRIJRJKSKLSMMTMNUNOUOPVQQWRRWSTXUUYWW[XY\[[]]]__`abbceeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22GD0? .‡+f dž<ɓGbTǂ,1J)R̕2SңM=aR!Њ>F )B H:-_ԩZT^P-cɚEVوm[0BrtU. `֜3 МY8[&}3QPv2a oo Vxm]!,_7+#  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^______```aaabbbdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 HCȰÄ JoaD.1BqɓHbDRD-]:S&B5męS@'}NF%8Tȴ)Sgp0ѩU*UAYn)ؔЩ+WV d+/^6t-Yw;nC nŔae K|0riy̝C,Qth飆kjGczkTc?ok-\'6Myr}:ztأ#>u SM{C^!,Dy  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///00011122233344455566788:9:=;;?<D=>E>>E>?F>?F??F@@E@AEBBFCCFDDFFFGGGHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 H*\ȰÄ"ŋ3jdoǏ C(ɓ I\2ʖ0c>|)͑7s I!M,ТPDtsNj%r`YÇ"?˺U`ʝoڶnz;Vlٳi}ԯU̶H*hܺ`Phe!,H    !!"""######$#%&'()* +""-##/%%0&&1''2((3))4))5**5**6++6++7,,7,,7,,7--8--8--8..9..9..9//:00:00:22<33=66@88B::C;?H?@I@@J@AJAAJABKABKABKBCKBCLBCLCDLDELDEMEFMFGMHHNIJOKKPMMQOPRQQSSSUUUVXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~221G*\ȰÇ#JHŋ3jȱǏ CIɓ(S\C,cʜI͛8sɳϟ@qb2ѣH*]ʴӧPJԫXjʵׯ`,ٳhӪ]˶-FɺKݻx}{P޿ LMc^̸ǐ"&o˘3kY,Bp;Miӓ FK"װc˶ 4sͻQ&۷ȓ+H5]X@_NLJ:/O3J?Mf1ѐϿYI?:h&S4&F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌ϣFh2Vj>j馂f)ϨJjiϪ **+]t3rڊk+ȶ;K*ʓ촲ycmCz:v-P+ijP}.+Z.aA!?+:l00dmrpaWL3ְ@ 𾅥2l2"ʅ{.!L"28.̼ {(F#m5dYsBr-69^mv[{9vcoM/m<!,b             !!"""""#"""""""""""####$$%%& '!"(##)%%*''+))-++.-.0002334666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22/G*\ȰÇ0ŋ+7DYƏ C:ѣȓ(?,ˆ͛b Ο(uoH? GTI>\JPjMH*!\=صjcqe;;#ͪ ۺ 0Yv\՟f 8ݡ28ɯL;~iCTVZ-?^ڿ]~̰\ 1bFZwٞ~̻psП#Wu8^e,<;鴱{?7| _@!,       !$&(*,-/49>ADFHJJIGFC@ = 83-+*('&&%%%%$%%%&'' ("")&&-++1405=29A4B??E@@F@AHAAIABJABKABKABKBBKBCLBCLBCLBCLBCLCDKCEMBFPECUI<\O4cX(j_oZ#qS+uL2zA?3N(Z bbccddefghijklmnoopqrsuvwxz{}"(/9FRbstuvwyz|~22-g̿Yh@fJBŌvbv'1U,yeʃ+-ҴSf8jLҟ9[KӦ%?崘j+/%/) PR ')-ߒY8W [k5@k_`Ep"`@!,i   !!"##%%%'&&)((+))-**.++0++1,,2--3--4..5..5./5//6/0600611711722733844855993:=1;A/=F->K+@P(AS&BV$CX#DZ!E\ E]F^F_G`GaHaHa Ia!Ia#Ja%J`'Ka,Kb0Lb5Lc:Mc@MdGNdNNeUOe]OeePggPhhPiiPiiPjjPkkQkkQllQjmUhnXfo\dp`apd^qh[rmWssTtyOtKuFv@w9x3y+z${|}}}~~~ ~ ~ ~ ~ ~      !'-5=FOUZ^cgjmpsuwy{}ϿѼԳ׬٤ݝ22G*\ȰÇ#JHbB-jȱǏ odȓ(S\dI0cʜ$I4sq<q^JBHjSH0ՕH!)yկ`9"%׿vm]XCҶ݂cjoݿlK4`lLȒ/V\ϜCL0dѨ^Nzְc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ?Q}N:=?#΃>XN<(=D!cFl("|H=#(&BO*N-:O)ScC8$B!8bC&#“dB0)";O"SAWF3)jeAQ*`N9fAK)":?Eƃpj=g 9'3jwB223gA/ک!3>Z^n&TF( tj`LQ1メNHc>Z&^M"t,I 4б, íf[jSE4 S?|BU&SB/Gd l?Oip0o[6< c>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22 / *\ȰÇ#JHŋ3jȱǏ CIɓ(S\#—/[ʜI͛8sɳϟ@Gz0ѣH*]ʴӧPw,իXjʵWT~KٳhӪ6ڷpʝK.Ҷb˷߿vLÈWǐ#Kvx˘3kܵ2QΠCM硥S^ͺ50]˞Ma1mͻ7Y } N8PE+_μPUKN_سkG.q_Ͼe˟>,0UcE'&hF(Sdf!HU%T (Dvx(ar~0jb4֨`p6vCabQP ӎ#:qX'ZJ"_1+ZQAԢ^tE+CvIG8p.M\FCVtG"<>{@e iȵы؄"F厐ć$GK%V,7iD:z,j('62-d|(yHJ|hb(I02-U%_Fe3-D<2wDaDe,wњ̦YZya5TH0 N`` 9vh!žqy>@, U_@hD`C}0P CV g@< *adfA_Lt,>%w|Sܔ)QʕKeVtzОJը3 FMzի+C@!,LkF    !"""####################$$$$$%%& '!!'##)%&*'(+))-+,...0002334666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKLLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhkkdmm_pp[rrWttRvvNwwJyyG{{C||?}}<~~8520-*(&$"!  !#$'),037;@EJPV]dks{22 ϟ *\ȰÇ#JHE3fȱǏ Ajy0ɓ(SN$ҟʗ0cvlR͛81Ҭϐ;yJTbPE*UxTҧCJTU:Rט\5~2FhE--ǵl] ܻP/߿ ̔+:">|4bS |Lnē)/[2.zXthˤ <:5Юms.]9sع'3a؉Nxv~uGs݌b؇{g33g!Nt/9y}DɻCվCxg|&ǚ] yܽg6΂w:EȐ{>΅XiH<fI_!אw"Eq]!݇05{S#v8裍5(OH܏ PX7O܏m9xV~yybDsFƤIsϵ9\t?Ǧq |5[mn 9#DJa0Pra&%?@KdC?Μ*0l*QB11Ì.3kR 2&+f'$4, ( :#=$HSp@j{SxOʔPn0kmߞ[^K'1l!,.)   !"""##$$$&%%'&&('')((*((+)),**,++-,,-...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~zuplhd`\YURPMKIC?>;>CEFGIKMOSVZ_diov|22 (М7={[GE3"d'ǏţxdAcv&/O`˛$83#<7[ރ'v*eY/]Q]\ IݕўӒXʕNX,oLIr*IT5Z~-ջJ2 ILz[XkFV:bgoM>V-T?VUHOͲrӝn9bÎ%rc _ɲǗ҄@+!G |ə :qbfBc~?  ŸA3#,ԝ} ߁ƼO36AFx,K j(]?dh[28ZL b D>A}dA$'~ 4MO X@X^v][ fЅ9cGrϒLcr8*rXdQrIe3VΩaOH2d!;,:  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///00011122244456777999;::=;;?<<@==B>>C??D?@E@@FABHBCICDKDDLDELEFMFFNFGOGHOGHPHHPHIQIIQIJQJJRLMQPPPSTOWXNbbJmmFwwB=71+'$#"""#©#š#̏#v$f%Z'R(M)H(E+C-?2<76@1H,O)T'V'V'W'W'V'T'Q(L(D(5(,'(&'&'&'&'&'&'&'&'&''(''''('''(',(.*/-1.110..-*)$$##""""!! !!$$**20;4A9H;N=R?X?[?_>e;n6t1y-}-~,~0}5{>zFzPyUxZv`tdqhqmrttzw~xyxtqnmmorvz|俊ؾ׸ҵȭˣ͞ИОӣ֩ٮܶ22 H*\ȰÇ#JHŋ3jȱǏ CV2D$!!!F!4dL'I z JѣH*]ʴ)ș~c*ZQtjլZJrџ$:]˶۷pʝ[tfͰ$v!-THQUI]̸ǐ#KJ`y ;5XU<ӨS^-e̜573eHiͻ)>` 5 {iУKN]s g]_ׇN#םv㯏9?BJէ߀h`[V{AxVh!Fy܂vx$8b{ܔI(-(4+vxۃ@"I #h<6L6ېxb%٢NfJ~XeW:"ahVetx.d&Fb^yҷ& aQT)NVz(QVx&╖*jhU٦BM:X*B.}Vf!Q4+qj"6K5(ȦjUe9a[hrW-q)%XUrҝG؅+'Mk\T'CқYo6pRh) ܥbw [SlQ7YC#1q0̑N44dsCly<}DJg4HgL4RrO@( r"_kyˇ :aNgrM \ Pc)nlߍ1#F乆44XwLzkN?ĈN!hsm༎}'c:BriC[OO+5`Nϗ'? l}Y 44w6D({9Ǜ│Ѡ`18F0_@4my]1 @H%]wwuP"F }Ӡ f: )EpH_qI{BBk Q]0I cÈ{+ ʬ9HG4E'bz#s!Xt#䈤¡cuL(}IHRUUVJ IGPJ!FN$'P}4+Xz.X6UQYyN{&i$ ^j׉k`O[Ͻe)CӃRtlSLy-qZ)w  B(܅dWKֶibsQvgY*Sq /]HhÜZ4/+~ b~ ¥AVrѓ!qRJ,0W F|}oQa(,qCyQ@1:cx+L{fC # b&ꂻ&"% BJQFyhKѠ6z5iͭB5R8ϭZ ' ir[C }&[!vt5%MS@wW q6$Pf{#x1vMDg;? Aqs}={ؾN7=vn kjEfg;| 77pSthW%MrU $ :'3!?{2]s{>"v&C>; 'M'IaY.W}t%Wgz.'7սG%ݣ> q]T\RՓs!Z]}׽58{R^9'ʣ6R-:W;{nzҡH.Iߖ淝=[{[~_O?|~=ř/$<'é_}\=t2@B=D]F}HJLNPR=T]V}XZ\^`b=d]f}hjlnpr=t]v}xz|~׀؂P؆}؃-Ӈ؋.ؐm؎ґ]0(mٖ%ٚٛ ږ(ڟMohڣRڕaڑ A(۳M(p }۾ۚ ]܅܌mÍ]~}]=ݑ]݆ ތ-區ޅ@޹ -]=}m}n>BP n, } .73aR &~(>{/2Nz1.1~`wِ゗޽@s4D^-JnR>T^V~XZ\^`b>eu#%'X Ɔyt8I8R"oh..xLvN"7ug_؃pr-|xafN>sy$ve@tu~r5WIry9f@7p@7n뛇UaQb|FW?w~'.dPIՎB&1>Wx^Au2k:X~sCw`XNwo'7X _=j.o>nn(G(۾Tv\Ha^{q1K_w',h|Ei7 qb0vCj_us(/WHqhO՟d&GZ$#NO{PoCi?O@ DР 2txaBPcĄ !$Q ǂIjD0ɔ-]SL5męSN=}Tȑɐ7DJQ=:V]~VXe͞E+QJ -j2jʹ[dHo#uuLX`… FT,/t\%5WƊ=Zh҆;/j1\*RNВ^>WQzn޽}.ZڶUk پ<խ_Ǟ]{KE*e|fސ.YYhݿ?pG>*of^啟@D0A>(2*@?1DB LHB(ti6C/C$<1Gw->zQR/Z-D>ndG)p6*3>X|)9EDJ5dM&!U1D Ls(jWrCLB͵0CXgD*:pO<95. 8ҙYdALju@cm'B2QdfD_JF0er|;gGB@ۗITX4^oWHJ4HH- +9JK.)AEGr#)e3zRIqg@%zDJj(Ћ\99щ4G| v $:eZ &PA As`ӆ* (iNz&dk]P0K*T!梢ՐJYEkĂ[!$Ed%V-|j[]WEtMH\Eh}lBӰO2H:;U5'Ay&#;ZlK!sxWJZڎhBaUDlpZָ!E3j:C!Vf]n_7=nvN;A"(ZwEo9:7'- R3u<؄yA9XG9 eQ#|W:FP^WӥzU 7%n8WNjbSn.q?[O?n1U~ KAOxaCg*zc?FjټQ`,͘<[LMa|2P3ip57lesaK\̞?7,cFHA`E `GlJџ- P)X1](ea!J\> u}kѾ6@`_ҘKUvOkF$ !,sA4        !"####$###########$$$$%(""*&&.()1++3--500723:45<67>89@:;B<E>?F?@G?@H@AH@AI@AIABJABJABKABKABKBBKBCKBCKBCLBCLBCLCCLCDLCDLCDLDELDEMEFMEFMFGNGHNHIOIJOJKPKLQMMRNOSPPTRRUTTWVVXYYZ[[\^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~2210G*\ȰÇ#JHŋ3j CIɓ(1b1˗0cʜIsJkɳϙ7qJѣ[/'PJ:2(Tjʕի9K]˶mȳީuK] ͽ˷/[KؠY<ذPo럒ʐ3kr23L4PJٴ$Ȍ?n/`= 0x n 1ֈ+_μУKNسkνÀOӫ_Ͼot}L_^ԟh`Dw H &VB Zr~v8b%Rx~ T+7`~0h_/h}9Wc@c$!,    !"""#######$###########$$$$%%&& '!!(##)$$*&&+((,**.,,///111344577899::;<<<>==@>>A>?C?@D@@EAAEABFBBGBCGCCHCDHDDIEEIEFJFFJGGKHHKIJLKKMLLNNNOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~221$G*\ȰÇ#JHŋ3jȱG Hɓ(S\ɲK|I͛8sy1̑< JQ>]ʴӧP &UիXfJUׯ`6UٳhӞ$Koڷp]H>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22,G*\ȰÇ#J(QÐ=3jȱǍɓ(S߂K*cʜI8e$ɳψ!qѣ?;%Hӧ*o38ԫXA"WCR֯`D.װhӎ=]ib]kg!rB]i1lt; iDqn<;DD?0Y>bL+vr(Tͻ Nȓ+_μУKNسkνÚOӫ_Ͼ˟OϿ(h& 6F(Vhfv ("8y-M%jb.3xa6V☢c@HdA, UINբ?:dJ'x%Zxb@!,\/                  !!!"###$$$%%%&&&'''((()))***+++--.11355888=:;A<=C>>F?@G@AI@AJABJABKBCLBCLCCMCDMCDMDENDENEEOEFPFGPGHQGHRHITJKUJKVJKVJKVJKVJKVKKVKLWKLVKLVKLVKLVKLVKLVKLVKLVKLVLMVLMWMMWMNWNOWNOXOPXPQXQRYRSZSTZUU[VW\XX]ZZ_\\`^^a``ccceeeghhikkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22G*\ȰÇ#JذX3jȱGɓ(MN/G0cʜC$i͛9{ 'PH4zTӧի tWWZ Ұ0xsȕ۶nϟ,cݿE߲€0[*l2PՂgL~sk(2ͺװc˞M۸sͻ-grӶq tN-X^rWo:ŏ;_-gU NG}2Ճ'W̱Ta|BaU`"}*b@!',MU    !!"""######$###########$&)"",''0++4./822;45>78@9:B;;D<=F=>G>?I?@I@AJ@AKABKABLABLABLABLABLABLABLABLABLABLABLBBLBCMBCLBCLBCLBCLBCLBCLBCLBCLBCLBCMBCMBCMBCMCDMCDMDEMDENLFNQGNSHNSIOQKQMMSOOTRRVUUXWWZYZ\\\^__`bbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~2210G*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8s̈@ JѣH*]ʴӧPJJM ʵׯ`ÊKٳhӪ]Vc\jKݻx˷߿JЧÈ+^̸ǐ#KVJɘ3k̹ϠC&YӨS^ͺװU6۸sͻMȓ+_?xÙKNس nAtMhO'˟OvGp&)߀h&xp,HVhfF $h(tB.h1I8<´?!`7#L6i?+$N \v񕓂לDliO{pixys矀*蠂I'&袌NgF*餔VңY馜v)Bꧤjm)9 )jɩewܮ*&j:F+9[f܊݆+:l覫69+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz H+$0I%ҕT.}dKc*SҔ3)NmD洧>B@!,3!-   !!!"###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnngotvpg|qar]s[t[u]vawg}xoyyyzzz{{{|||}}}~~~22 H *\_! J\ĉ V1č=~$xQ$CKQ:p;.I!B2D9ZfJ:p)X<@V`z 2IC L⟵m Vm`Pqvǐ#K\gd\_}4ƦON,k̮IgooI'tt>)땿x;:ro.0{C!,e      %)+-.-,) %                 !""#$%%( ()#)*&*,*,...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~22#Gv$;Ȱ`}C6D_= >ܷ7r0H$3`ʃZ|y0̂4/pCf\rѠ_@kYO[lp.&>O}L2leI3آ\!ƙܻx˷߿ LÈ+^̸ǐ#KL˘3嘗cŻ9,'Fa[V6AN76&$ `_qR`~HyCRzsϣOh?&۾_U{[EQh!,&     !!!!"""##$ $!!%""&$$'%%('')))*,,,---...///000111222333444555666777888=5:A2;E0=I-?M+@P)AS'BU%CW$DY"D[!E\ F^ F_ G_ G` H` H`!I^%I[*JW.KT2KR6LP8LN;ML>MK@NKANJCOKFOKIPLMRMNSOPTQRVTUWXXZZZ\]]^```_ab`bcaccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~ҿսػڹݸ߷߿ݼ߽22 Hp`b*, … f0ʼnZT1F+~XPRཕ @v4A.TWx_<(&=9h1Ae]V~a803\@C$&O.A 'pl+˅K?d>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~±óĵĸƻǿ22G*\ȰÇ#JHŋ3jȱǏ CIɓ(S8P˗0cʜI͛8s3@= JѣH*]*%PPJJիX{4ׯ`ÊK˭\њ]˶۷pTUݻxVmZ L0L, +^̸~F~L˘NNϠCWӨS%iհc˞m״s͛mu{ NN_μ󎜁~N,㊽Pӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @O( A(y(х:q<,Y+#pbG= 41đz9H]lAJG1p&q,00jL  KAdψ xd!(,    !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<N*@YBdCk@n?n@nDmElEj EhFdFc#Bc,?c4>a==_D>^I@[NCYOGVQLSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~~|zyyyyz{}÷ŸǻǭΨע22{GA| *L0‚ >筢Ň0qƌ0: ̠!=v, J"8@ɗ®SgnhfD!UQ6R(W1뿮` D^'%!,L&&F))D))D))C))B**B**A**@**;**7**5**2**0**.**,**+******************************************************************************++++++++++++,,,...000222223333333333333434434644844<45C46O7;]9?k:Av:A;C>F?HAJEKLNVP^TjZvgtĠǤ˧ϭӳ׸۾šɢˤ̧̩̬ʰdzŶù̼дլ۩22 ܗ/Z4h=sưÇ#JHŋ3jPǏCIɓ(S\ɲ˗0cʜI͛8sɳϟ% JѣH*]ӧPJJիXjʵׯ`Ê˓3'۷pʝKݻx˷߿:ICÈ+^̸ǐ#KL˘3k̹Ϡ MӨS^ͺаc˞M۸sͻ Nm|[μУKNسkνOӫ_Ͼ˟OϿ(^4(W 6F(Vhfv a(,0(4h8樝@@)DiH&L6dv8̏OViXf\v`90Chlp)gdĜx|矀f)衈&袌6裐VGVj饘f馜vᤞ*ꨤjꩨ~(Ūڞ<׍ہZ8\O !\K(vzimһ*D7pJBmNӕՔZ̦8-P[ƺ_u՗p:mrKZm.vz7IxK(Mz|˞ͯ~cVo&Qnp;.n~[Nm { vlb(kS8+~gLZƸ8αw@ZL"YTC>dF%P)[XR.{H[LhN7t5p.PL:ۙ>s1c} ?ہЈN#C/ѐ^t#MJyҖδ,\nӠsQPS3Wjհ_-Zw-\&Mb[wNe;ٷm6MJζen{[pvvMo[ηzkNKuOq;l8'N7=s CNk&OEj9gNDɼ8n<χN4HO0;NNշuEZ"h_hn4xOЄ9:Ox/o#OyO3yo/COSGi>hr=wvc}O|c/;}%O }qoO~hO~`OXϿ?MHihX(h g ؀gQUh~q6bBǁ k$k%6a,.k#2j186i5x:Xi>Hc=BbA8FhbExJaINaMRx`Q8V_UxZx_Y^_]b^a8f(^XgKwdžpXd9tcsXxay؇5Ƃ~/vXFu(`eZ8Yx8YXXX8WxbAX^]Qr j8xl@`؋%|wXƘ8،4` X[8Zx(GٸިB=87xH4鸎3/8*x8*)y)9(µb R%`YO}ّđ$)&9Ky*YG .9G2%196$5y:$9>Y$=B $A9Fi#EyJifN/IR"Q9V!UyZ!ĸ^ )]b(8f)]XgwgRwlp9~%RGx'Y|9{ٗYI٘))MY$J֙)$9YIɘ9j-(ɔyy^{؈` !)Yȩ!VjٜowiYbyڹZٝiR9yJiٞB|Y@ɟZ1聠 ڠZAԁڡ"ڡ$Zz(Z*ڢ.ڠ0 :4Z6z:<ڣ@ڞB:YFH۹LZN))yiUɥ bdZyhzYꩦnm t:sziz|ڧ:YCХ a9jJZ9zęڪ::YšZyʺ}٬Κt9 zlzڭc:[Yz蚮SKzZCy;ٯz39{+ { ۰";Yk{ڱc ";[Y&뱜!,K.'2[8;:ڳ>7:D;F{JL۴P;R;XVX׸\;^bd[xh+jضnp8tv{z{|۷;X{k[x뇚yع[ k([xK8{瘻;ۻW ;T[C;Oһ[Gx;ڻ?ؽ޻78;{/ꫂ۾%;X{ۀ \\x \7~|\~ }"\@q8D̆(|ĸJ<{LĭPzR<ťWVzXŝ\y^ŕbyd\ƍwhxjƅnU^^ ]]^u^]\ 5$\&~ƕ*\,0[2>U6n[8㱵BZD^uHZJNYP5T^YV~哕ZX\`Xb>Uf^Xh惵lWn}rWt^wux^Wzs~Vm5脾V~d.V`>U>QUT=霾S9O^tꨎONK4~G~u>G.B>*Tƾ=Ȟٳ~=7^|sخ7ھC4?3/~/*>RN*))_ro) (2(( '"?}R&'(y,?'.q2&4_mr8&:i>/&@`2D%F\J%LXPo%R?ORV$XK\$^Gb_$d_Crh$j:n#p62tO#v2z#|."?*R"!!!_r!?!2  / ?Ro_q/ʿ1ԯo/?Qܱo_q/O@ DPB >QD-^ĘQF=~RH%MDRJ-]SL /ǧN=}TPEETRM>UTo欚UV]~VXe͞EVm٫:׾W\uśW^}X`… FXbƍvYdʕ-_ƜYf!wZhҥMFZ5ϫ][lڵmn޽}\𮺉G\r͝6\tխ_Ǟktݽ^xG^zO>^|Ǐ4~~0@ɭD0AdP0B 'B0C 7CCG$DO(DWdE_\PEgFoNFwGMG $H#,LH$dI'|@(J+4JI,K/THK0$L3L5dMt3N9?83O=N>4PAsPCE4 UQGt0F#RK/%kRL7SOSQG%TB55UUWe!T[5VYG}uV[oUZsW_Wa%`E6Ye=tG'sOGt'X`u_=vgvo=www>x'xG>ygy矇>z駧z>{{hz%Va}߇?~秿~?o(8@Ѐ  pJ!Made with ScreenToGif;asammdf-8.5.1/doc/images/functions_manager_dialog.png000066400000000000000000000457511502633300400227060ustar00rootroot00000000000000PNG  IHDR [sRGBgAMA a pHYsodK~IDATx^{%adz؝iư p0hLhE73ya7`7< ZXmd d ۍzFi74 = -V'{2ܼyUfqO>ys3OV=ʼc7|0믿.]z^s5/w/G’_x;~aIk)'l7=zߜݬm#ͶvZ]ԿPsvrqhR#hPq<+^w+i9vw_{qɲ^wSN(P-05—A3&,>\uU-ZdIXz5XXX6n1.*g/Ӭ^nbb"nT>W6W/{C*ڦϼvh͏P>ڡ?'䱥4~gC/?ȥŭ+ pVA:1'-!t:ǃqd:p^O/yw>Om}zi5nM{+V h6Zxh 3KO|kˑ?Ž?{gvn9xOmwylsW}7>5$xtik>uKrH20-&_xK]O<ϟ/<}w׾쎯͡yͣ[nM:՚"UvaOBك@qGX-C?гR$v:~gk{H6Z'a3opAZȃ̳A`x=3O}|qo=/3}ǿ{bO#>\0pn.rޭ\*R.7ƛ{t0b6P0N(_ .iVe֬l ҼukT;ق7Sy<*!b~/ݚT‘jMYV-{-+n6ճY[! )j*M}5l5*c앪` +XOS}LEuӿ_|r]>&n~b͏oͯm|G_ZuG^=_5\Vkr;d_v5}Knwv+gtv+fDk$hۜǃmWCG7֪_*x}>+&/k+wkҹ𭬎Cclv+Y֝vF63z6U߭*'9:Fщ@ʩ3IFJi ` q}˾Ƕ^foOn-n>?kǑSq2%`Ngp[B'^+Kҿ+n)!t.5e9/D=SpE ~efl%9Nrysr]G.Z pAxS<5c:AliNeUWw=G߷Ch6Lxǐbte qcx}B<_y`E7z_ʊ9+f9V,bQԭ5ws4u{Kc RY}xS=Bl3xOΘxFpSY{+꩕+WvC^6?HX\ߧ[ Ƞ"ˉܳ;N;͇?؝}Y_lZr~ :]*߄x0[x)0xOL?xn}kgW?T%*֡4 +x,?ΗcE+UEGSI9W^7 ^u$BC9,(6:sv9r.# :33Y6>P ^joK'Z94:8xS;Zh=p:&SڠJEr.S7\H<مo޸`Q9E0®qHΓ*O. #Tw,+jn=s˽.n+6嶿v l'JRvy4hv tԿ[kȡ63'>K(3x̘3Idi، }X(YuzP E!V@8ͩ:gmk ޺qs6ϥ(LٳOSQnkmPfdЙ)o?mET8xg}[^~0VetRvjq~_]NϗD֬_9nܿWk1w Z{!n}j{9(=-+ӘqޢE'v" s {uLY_٫u6.L==gxW)3ګrzj7<'.h=|N21MQYhmhȖqP嘕 :3>O{)Ý<Omw*38橕GyR]ItmmꄔI*C]8q@5 z!|m栔wvm΋걷OiƐg%`Z<8Y=lnn+!W~ǁ8h3t[69XL{gwʍ{6Zޅm栔 n%ؾ} 6n*e{Mxlj=B<A^~bmq~kGI$AgHD}{9E~'Gl;X; z!nψ֭я~cǎ;w`؄.k_>Lă#G1 6 4*g'{>S~O-ox{[nFAgflYOg;4?bV'v˞rÛf1:B\ǃ[n-6q}/ƍ7}Ix 8gZ '>|8ǹ;%ci، #C8ͩ37ۼݼP%T9v[9(G6^W_}U<Mx 8gZ0ktI}eu}艖EL8pdi`F33"o:/xF"{5k֬8 '8«`.F33"o:/x.\ făn)nax)6z @L%-o%I!$ə+x@!$əF<G ([H37YķJ<Yz$9gOn}E< Ig2'?YDsON|&~zM_V9.[}zJdٟ~'?$a-^3-}۶so}2tG陽t0xu*{+*8ۚ&wKxM_Rr$7xO>$ob{ln?7NtOʣ8Jp {I34TYe2d a/ߔUUjHă>[?)wǣo?)3wmm<G7 O4TV岾avD{w#76+g7xatl5[gYBd;\~3?y4Oxn/EpNx[AAS5xz}jS_?u; G?^I7|3V<ȟi<,TUur=݃ƾ1#Z+L-QKj7Ak;<hԗ])74 ,;@BHR<>)wCN}rgMY O=|tpӛ7q{V|hEˇ_2hzhEc767I.g%TMkx(xP]m7Z{=(?xбjO?7"I &ɧ^ܔS5|pEQs TK;G:zCֺ Ozscjj97y?} X$YAV.ŏ }As^yC/:l{<(6rR4A({;w➍͞6_+CDQj͔%̔rwc`F[/Km-ڴBG۞CR<~wSU'O}KE,wҾOcw7^uoOl$kq]t߃fc wflG!AM&O߶)w(nc__9/V k7W-޽GYn}H^7C~&779h$L)wmq߉Sw_9Gnm}%v}㎖nwz Rͣ2I֨x@d[?;Hr$L&}M$9G"$3x{%)w_%9k6$M&ڱ$H)db$H21d}$~gO?:]Snf/p^[gC;$qYZhE=N! HwM7-[Ӣ# Fmˢ<ܣ"ɞq4m@G^o=}ߵg1p(Ń_" G=t1w|VꭕMϻee'A#1&IrόxP)yᓿOXucOE8كF_2`+RC`>\ ֟q<(l$9ƃrAYS]wTfkO-,{`g M30?u^>q}rXgك=SL$&76xOwA 2}t}L=3A,POk5?Эgxq#-S$<3A r>+%~j>#EqAϏ&$+rH $Y$x@O#x0 p[r_碶+#$V<xpGࣗf!˟=u|=׎+@bvH `;w ﻨ~bM/oV^$xB<8k|{ͽm::x_QOk ʚ*5K*Η$9$HEoF*(G@&dP.,BV3$9Hя]zĥgT?/'?_z5{YxpMW[w-޾Y}~`WV̻+o}}nXo'y]QT^qnR:ǚ=`w=|-o,t@&LR$gQcA*@/ ENW6SA(~(ƃmo4Sx~9$OTP]gfޑ?V]By?n(v):AQHpwv᜻Opݭs 1F9=h}֨L}#A3R6vƃr. :Ay˲P[(CV<Ę``goIRyo)ŃEmK$x^<H $Y$Fs':I#xl<8k|{ͽmM5`&N>?e޽I ă^ᦂeOoZg_‰t)w/i$ɹ,ăZ<1EM]zĥgUk%zMY6{zp-U{ǃKmZ~yG=IqBfM~4yIb*(_OxCmRHHю$ɴ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1ăk߾8$W<:; dM_%x1+/܉k/\pe>$ ﻨ7Wѭ r1K/(v|>$@g!x 9 0p.rgM5tZs'93Pcnƃ@Ӱ|/~`ix>fHAfϟ$9#H 7,;+^+d_H Z}r'gMnL\zd]i@*@bx@5H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>HY ޸CL HAHr 1F>P+[yN4zN\zV[/_WjH5(@bv<8k|A@fyyfYcw$gEcA@n5= B}$gCcs/kǃ"$mfIx1 m9(2."YQ<xPex^ke!.$9+H)+@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b}}}׾}i{e ^ߕK:ZI2YH 񠯳]8qy9 ii%Ʉ 1`H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$xsg#nM Jd}I>H $Y$x@Ygǭi!@x@YpH)@b$x"I>g-{A< I,k2 $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<H)@b$ 1d}I>H $Y$x@OC< I֧x!$S<ĘI<`RF-·ͱI3G<B<0Z7F &"h!D-xL?v LD~G<̈́ _8/!!h1xAX=z''BwN Iq 2ӎk׮& LQ ˞7._xŴ+} S'{V~c/$!!h1x ?Zwbۑ=8ztϑܵɲ4݇{v.x Fƃק_慎6 bMxa{n_VoEePB[:r N<xăv:_r{=Nw:q˓?kDQ_Z#?]OV[9 'CG<b& ,OMN|kۊlB†GcM^ ,48UXM! hG{ tqD ,Å#h1x'}wO iXdE~cVFi@ +'Kc#FEB=Gl}[ -Fm?RG4}p0Gp`0Z$Exn2ܼfcCwh䁸6U/U1{1ay؉ؓ1!|-lf[hj|dÝƖlW¢yC4 -:NyrÅ#hQkx뚻0'r /> '?8=ۀՑfebQ(fװxnGUF+6 N<xLAXٸumO`_QklOn;xhl(pwlUuxєޫ祰YUP}jUeQ W^Yj}ص09>|yۡ o(QWPrFwwBM6lZÆBbVċRKsʼ*Fs޵#1'kq[PU_+O<{ۼg}3ʶnي6rʢ+{w']rCs.ݲTPYԨvh+G7O$V-ܵ!Ed\誋6ݟ\m6ʳ[tO{p`0Z$9rP+ԒV;6$-[x_,09=#-!ͶχH*'3\8:3+ܻ!2۞޶@E{ݸ1|{޹`WH!Eop0t-]#B23޾`/C0]mSD s{ 'CG<b&СCЃ09ν> N<xŴ5k"8܏´ S'O}{nݵ @} \x! Fiǃ{g Kgh!LK0Eq*۾qrۮ;4 +\۾q?/$!!h1xwf͚ LKlPYy .lԁxL3D<B<0Z7F &"h!D-xxx`o"}Ν;7o!׈0B7nuk;N| ^`ڎ;7] e~[.L@I7lذqW.k;N|C @D<D@D<D,,Z(nÈ"x "sk׮8 ' / T.ae9?4v3Іx0wYvm\<Ӯ`.+V9C8x@%ߘ3y 9@űhC<X6KX/9@8^`@%xpؒ`]~c:4{Ń! <09f `֋axbX|K̟˱b+i8%iCp!=ey8 arz@e Kw\ xf6֋ax|8tw;gwxQݻUyE3"fx0h=*#=?;bm̲! b!LDhC<bX8 TtXB.Bu, ūvQ(ΔpLgziZq)eŢԜeؘI^cRz@%0X?>o|8nŠcݸѠke~qiNW(Ɯ_tkfŗ^ziQ?=~9*j#^n I b/]&n\yϽ?oimYwFSZ/[Pv(, /:՞y->qk * ׌D*Ѝpw&#_2Up 7tXRn)3#~xc|A 9vf~ݹQ$҇IENDB`asammdf-8.5.1/doc/images/individual_axis.gif000066400000000000000000026153731502633300400210270ustar00rootroot00000000000000GIF89aOĿxxyqqqppppppoooooonnnllljhezpZzJ>ƅ9Έ6ԋ8ڏ9ڏ:ې:E`eegs̃Ջڏېޔkfdabd_H:97'}fed`R:71 f$d Q7 %!&'$))'4,38 7;:L8b)et7:E_de! NETSCAPE2.0!,OW H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8s'O JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx ˷߿ LÈ+^̸ǐ#Kw˘3k̹ϠCMiO^ͺװc˞MۗSͻ Nqܺ+_μУKNsسkν{.ӫ_ϾrAɟO~}ϿX`& 6 6ThN v (EIX4(bG0(4٬#.@)cHV;4EC;WI8M3L S6L4(^4|P2CBd5Dcd9$%fTrC'Ty?gɍSe ( J䢌6裿Al=$QF R(A3@$Lj2Tɦ0uSʫSjJT%Ʃ(F+ZFQ׮PRQ4cB2h@–ӀЌ%L:hkR)1,R2ů.[pV25oC%\G,K&LխjL4l) Hc4MQ¼3'n#k/7Y ́*psr>9˘e٫u+q]k2|u9H[fs6[mX7Kc&pA6x_ LXT.JutϞjPIuoè4g>>辻Lڻg}z+: Q+:&ww?]^ ֓k%= M4Hj: : ;?l85)NƸx_KQ|g%pc`PQp[ ͞E6FO6ӠP8gR yB8!gRYPt\B6""ae;:)"OQ( ;W54F~x_'eCᗑ&ە`H#x$I{_5vEELxx+&AwJZrC/egfiqj\< X?%U<]-E˧++e ^.J2*Ќ4ȷlkpT6MvSDfEzB9IJSkJ1lV s_ PϰqP-d? ȅ231CRiZiٖaS*ڤđ33{||aNWlgϙ&oy t&NQI`DτSYԎ)1)L>cWS͒SP>*[KhMb81 rQ2D m^sA3'0:pw}*MWW vMв $BS9l+iֺl _֡t4r?q-­#[վm$n6[ o׻η~g~Ŭg|юk1sx?F>}dx0q)߻>9cXV8W09m\%pq;GkLgxQeN[XϺMsE~cxc*,-v#9Xǎomݎp[G;n#ŝܻ{tl텇vŃm?7{nG߅_ йݏ]ŭmc<yыw}m`I??k>횟ԁ'O&}}ohƼb`n89 .o(}zxnc`~&t>*F`wṅ~&x(*6p7uxIB5x6oݧbWn2(m;x>>ӶW|h|YFyH`V|FJR9TY;Ɣ~yhPi^`=bYfyhGjٖnpƖrYvyx&p1З~9Yy٘9Yyٙ9Yyٚ94Gٛ9Yyșʹi8@z9ikGE1Yٝ&p8=8y虞z&p>=>9_ƞIFf:b7Z z7 ڠ:Z7Z ":$Z&z(*,ڢ.02ڡ6z8:<ڣ>@B:!Z9zHDڤNPNjJZVzǤR\ڥ^*Tb:duZhjJaZpro >xz@ #j=sZz p{ڨ# 0کVʢX!Y~ @n`Z OZ," t$2@* 2C< :./)p`$Zz v0Ȋ@ЭߊQJ#>p& B 'ʊJ!-* ,{,{05` F3@ؚ ![R!; j$ʰ4z F W ;xBʰ* !,J/J0D{6W9 JG۳(0nʱb;d+hۢG"+K @ʲOSAK Ty;0-$*귽p4{'AH +N~2K/X0,Z{[fgˢJXںj +%ʰ㴜)[[:S kr[ Xԫ@ڼ{'K;]+':`Ϋ '}TzA;ś KG":[˸{A3)Z -Kf)@A{{"ܫz"{gkk"Œ뿝۴LN{A# D;4T\V,c [t[ G! +'ڭ0銷;;ǼR2l!J08P :S|Œ<&Z4f {;+/2;V'tr䲹Lʂ,w 70I  RLWlɏZ,@@-@PP@ ,<4$2S\|$ ]} Б Ј =]}- c "=$]&]*9 '02=,}8=.M<>(B=7@}H&mDNFR=T}LXU^Wb=w_}h}aMliiir kv}V s|u׀F}]؆mՂ؊}؎l9ٔ]ٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڪڬڮڰ۲=۴]۶ۼ۾=]}ȝʽh4p}؝ڽ=]}5Y.]}غ ݋ 7`= >^~ ">$^&~(*,.02>4^6~8:<>@\ݞݢJANPR>T^V~XZ\^`CnDKjanpr>t^v~xz4>^ k>K~舞芾|E,J>^.Nen+.>^~븮G~>^~Ȟ~^Ӫ^~؞ھ]콾>~~~N~n~^~ ..}\"?$_&.Y02?4_68:<> 9AC/E(LNP*oCq" d_fh$>r;T>xz|y_|~?l/)N%+C^_әz?_&@ޱ>@?_O_ϧ?_Uʼӯ@?SBQzTU^ŚUօ>~VXe͞EVZ pAٴik6Wfw[m׸{fvWZÆs Ydʕ-_ƜYfΝ=Zh+B(zuX6eRƍؽgze\pōZXnw6WdE_1FgF3m@ d< (9f22 )Iyt\*ݖm}Rk6Ws gN%Pz&}7i|pc[g=SCi=XmciP&lF;mMUXc~4@q) g\C5}W'=zե,zįZL%>x5ZcŦmOG=uWgl>^p 'ixwuA\ #g z@>3^@&{!k=}g}Oy`w>\b=h|P-^ W5uytރ4 VЂ  vpaq }a e8CІOgֳќf>|h@:tEhBiӡhD%*w)ȟT@M O4 } IMRq/iLe:SUTTlQh4iPS4@#T6թTVժJTDSvի_eljg nխok\:Wծwk^*!4VjR؀ `KZn5ld%;YU{NkVvֳ pW⠱-ijPֵmljٸ=%Qmnu[np;a˜'n}\6׹%nt;]иLgrֻ͚ox;^׼Eo]׽/ʮk74AY_׿p<`FpY6+ꏷs5a6.pEdoLͣ_@JŨ80rh# >f(?;уdElT "PہfOzԥ>uWWzֵu _;,tbe%gG{ڍo'[8gr,`3w`^+\n ~17yW|5ywBa9ljG}Uomپ]?;~so+3֐@@t@˿ @TdtAxq,Bf # @h؀[hzP]hB\B} )%܀'B-B o `0#KB B0r789:;<62 ?D:91( #\ B%%B,\:fv-LDHlމKDŸQB` "%Fd=4SDTTUd9% XYdC\]^_`a$b4FMCZTedF4\ʟ 'rklmnopq$GqktTu &=S)Ţz{|}~ǖ2;v$Ȃ4Ȝ!x`&yȈȉȊȋȄHN:ȎȏL &kHK{9TɕdɖtɗɘəɚɛɬBGɞIೋ:,ȤTʥdʦtJzdɩʂLȅlwJvJ$˲4˳D˴,/֒ʪt˷{2찺˻K6˽˸3d4lT Dсɤʴ$4D̶dt͐ˡ!|4kÍ t<[.e0#ЁE3DTdO j8.Ȇ g O(%E{ρU$d3ϧ 6X R;P\E0Ч 5c+_J:0dhѦhH e&u'ReQX*bdp% [)f9k8(U5eSұ8b Ҩ c:384mDUE7-9H,͆ ih M)r#2:CQ5SETUUeV:G='IY d/} (Y5lu9 :a-֟cH9V ShRŀI4VWmnoX-2Z%rMd ̀  >&D<?[@c{Mz{nC<`@t؇؈XW4׋XQZQhuՆlR#.Ļ Շ32ĻDĿ 2|YfhŝٟٞXGآ5Z::dihWfTw Y-Y+,C(FTV.šhDٸ›vڠe۶u۷}ۡۺ!&i"dLDG?B뀕{M$Pdcʵ̵\8]JRĸOD$}\+$\';Dcܰe]Ņ]$M$F>55JRmPi&Ȼ]&/BEٵkh~@fd8d(_oM-&E_ɵ# L*k'/5ĵ_  `P ~&aE~! xf>&Vd7E T%MD$V%f&v'*Ŀ Lx =(1&263)5fc9Xi^,;<=>?@A&B6CFDVEfFc5nHH" `LMNOPQ&R6SFTVUfVvWeHYd]^_+Ya&fиeLRefbh+,#>mlm^go8fH@tVunvwVoy ` dh'z&IjL,g/gn艦h{ګyȅؐhP (iP L ^iiؐfiȅrhcyAiij^f\i~^Ijkhۡjkkk>kA&NVvk\hiއ6.On#YAW8u]uȁwMtkIl̾iEq9gmNgφtTv*rcTnNXvwzw~r m>qk_p~2ioz'p?y&{nwyY_Q0/zDwa_t G\[|7|k(nƇ|Wзhӷ[gG|^_g"ȡm}|}U}o z7W~Z}|O~Hm~|跊uOv 'OQ?Ï~g,h „ 2l!Ĉu@h"Fq6r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-j(ҤJxVa֬Zr ꐨjײő7rҭk.޼z%R).l0Ċ3n1Ȓ't U*UVrkXuд\Vz5e [eGn/‡+#ʗ3o9ҧSnOQeVbW$5C56M }65f}P7q 8pƑWv * : J8!iEށxB`]eP|EP.9_~EğtH 5V#=#A 9$EtT^Y1HUOzxh X} j*V_66fZ;Z>@3HoN9z#ҕ#yFJ:)Zz)jiIHvdgQB$Wxe]Y"// eO0Z.ߟ(@ƫjq-;.{L**>t;NWZ:fɊֶ0O mD/k!2a=6e]r˚ag3V\7o lЗ*+4^.l=xLtwS}UG5בXg[~9k9ʥ!\!-э1alCSf}iߗ[;#Ss۰䧷<)br2|८]{^iwkXN(fekV]ݫַU=,cA f5k-`TҶZU%21=M#Wrxa]&0Q~@{=k?岵aW ӧ4 \qmT櫵w^sٞlZW._U==d.yiowߣXZNY-[a8#oHW!vB `YYLmhXyk-]ϚK&ӌ:V+ke|bb岾Us{˵^yg{^]C/u6K^:ے/Ϊl6p8-P@]|md|^^w(C.Kv&޵w2׶w x{'oO]]Uij ;SbSUFhڟ- xȑu}Zgh}/E/h"ֳ9GﻝZã|u?<ʗׯ^N&]V6'\_=/*gS\r;dɗi,_]22Ս`Y^aY1Bd%߽q_eyf,ܚM`k 1  8>H@j^S5`%;(UUMa5ؼ1^~yA )![]a}!]͗_a)ݝ zCRaj]1&".-V is%j-y!Ïirq!i>+)VW+& i'¢^X/v%rV٩_bbbk.1"6f6)ЩHM@@*,::& n;#<:Ž^8 aC:>$DN? $EVEn"VЂAaDHKME$JԟRVXhL$M$NN K$dM%Qe!N&R.dAjYB-$CU^%=$Sn%Wv%b.BGJ⳥Y>bZ5iW%\%Q̣P>[P QEZ_ݤ\&a\Be$x-CK^X6݌Wekauk]eZ}&Z5ue&Kc&i!Ifi2hfͦiVԝ5&r&r҄GV$AJ8fsM agu՗wEZagYضeXjrYY .V`k&"i>x؅&R.(ZbFbMV$OE]NfBݟ՘X?XkXa(郈awY`yh>&Yqe]wE}Yi=.qzH)"GIL^M@T'&%j]-UٗZ ۦq鯱iݚ%Ӡ@NX\ڗ2eNVZtF۴ fh ҜB_}[I7gm껱W¥V_% )gj!q2V*/r* *&+@TyCVTDZƁb\}\5 6̑g+3z+\A.aE \媧=]^jae ֠`*.,J7F&B !۹_bbmN\har֙lii{j*ҫ؝뮊lz*L%,-#]]Bipў`Bnխ fiߨQ_b,mxnhE_)blע--6mN>m`^+-Z>nI`,"j fѧ*ܥ^j)[` 묵3` ޓ-.oQhڣ>r!=!!JfRV />}\B/z-qš.m{EZ0&2҉hJ45tB肛e<4LkEVMsF=s.KY@ vF|nw(Qw׉uyyaSNc1X!\jYgiT{"VQt[tL[I43 ȀӵN6ˤVs V.(r(((>bw0#؃mu}Muq`baV;5jv-(,fVu6HC3@ ص7Sq?cPOҬ-٘ilppciڟzg%~e{iXtgKڶ)ZW*Kqz |ϲ#KC vZ@*ebVz*4ۍqye.Wj1ߒ꧖77{8(A1(;MrQ4"!,u8{:OiibZo ?5akyIhZr9O.sCr}7j @LMj@u81^_VZr6l9i)r{Eo`Y2av&Ô7幈 kxo:H9 D4в6з}/~3Fe-ZzxK_%6qpfw=Q햡+66XR8&{y_;CUv65.V n^{ZzRv.})}7cOX늬z>^nvcKig;G7k7(Tc1[*pEi~緾;gB"E1>8c%/G $G?Q&?W;?)2K?%[?>3_wc;;)FsYNYV?F+(@#* 0aC!>T… 1bcGAAdI4eK/aƔ9fM7qԹ?3:hQG&UiSOF:jUWfպkW_;lYgѦUm[oƕ;@/*/Éȳ#'.,3cvy×УAZvuLc?gwvlv͙gk޵7pҭw{c۴q֙U3w>2lْiog`sѧW}{Ǘ?~}׿k݁BHt/̻h0>0,.Sk y9n;% 3M:iβ+Q3}:,2>嚎@p;j4PܐŎ<#шFˈ 9^b^ %F*uKK!ol#ix*/AKS5l7S9;Jh=L$+x2~!`B RIFULS'9R9%" R$GMMSɄ4UJYK^SVT-S;kn2sPVikVmSO>/?KA #@*hIIfwzAT|c4g] m_{՗^#֣+ cCt+38-d`#XYۛqYy矁o 5A饙ni'twrW.@LQFe d",lVuMeHh吾>6X#[ҹ;Z)3|d9 e w5b6[o.sL1\9A)4PO]Yo=0iڽkKGwqp%oT^]ۛ'w߃rST_qknWGgc]rn'e桻3C gk68#:񑑜d%/MvchU @#F{_e6ќ&K9mvl~,}svhAffhE/t35gLҀ.1iM8SfAjQ\bK+(ׄ#1~ubg<5uk_#J֗arQe ְF?]kW;06nMkh>k 7ks݈Yw;][ۜv׍eٸ=jg#"/i4D @SU Cf>m jSw;y[!GȥqXZ߇E5qoQ2azmV-x/^w>yΑ}^VyX[$wzʓNla޾y8fq$oF<Ŗ6=!tכ5xcE9fAr[n/9_n#oi~}|?1ѿZVt!0%Nx!.Ϻ,MZ\>`Oܸ!QNC0A<p]NO1.O//0T.PIs:mp _eO.bxL ڸnT0Pbۦ [ܨPp5pTΰm   EqIb @ TM./ ]/t z֚isq.jQ poa9i p۰2qq8-Mqٱ1)p/h!N%N2DP0av :ݍ!q&T%߀ 0 0 ߱%]%0N^QNLx-Z n (vrz-(M*rr!~*,1!Ren2*aRa.2/N&q  !1^13A|A2sz ی44kވm Q%3u>WR29s9/_jmvהMܬ)G$3;Z.ǭa;a:<_=b0=ݘ6p7bpAr?sK.B14C5L&[mR0qr7DMD1B5tEYE9% M,'QFq4GgLE]G}G*ia` Dh@RtI4J]GJJI 9%:NJ4LtШKL/44NtNLN4OfMBTtP P%4QuQwRk&k, uS9QA5TEMw!C+UDkLUF;uVi5AiTq5WuMdҮ\IU)mXIBVkX0>uWY-`@l:˰ fM>55m[o7 m@M%'ϰݼuܜO]-\{ \ҕYva6-V lZuDQl.TD0 S)C.nbURc)u ߕq-beAc?ۜ'1m)AVPaiYa, eT0hNvq75qgk/NRhPq2]P)g|f ~-,l[gNr-`Yai6q7/,0b SmbsG0/-R*7,mC-VnKn/ tVtK hipwy/^@Z@ZȪV: A0d;a.I."{67uv'=R^QZhvx 7iCywx /Z DbW̰2Ӑ{vP ";X}Od/c.r7lv7<4Df+!Z9yqxx/V aV\7ҬFiQ }q|Xҋwxޔ1I7b8~2Xvcvt0Rv\WCYx/AArg4VSw /q o47\me#2*cؒP$~/ tCy hEd.v>1yQŽ $(9.9P3YrA`Ymoa r89+X8*oݒ6W{Ж i*yR-83퐉وQ:/XUI 3Q33A423w'24158971C3J3_ 98Z#t7Z:3d X!dT+hS?X>S5s11>ۓ;,MU2PAӶqc͆*BZ>੥z9JAQ&94{aQ=:1V@;;u[J&!d`!V{ [c; ?r50f{.j;1^`v;δ)!{"XےE ȖIqI;ku5 !{ X A[^PX@҂1N:>Xa7 |I/;S#79u5v~wfw7W=tG7PuQWОuGῑ ef}n1E$,W]̩*jžޟQ{ YP|ݕ.; mpnWWvG}(Z+.9{x2K1=Q_Mmg8 _o07S8?U׿+q\TP? :LW-PXg5rTx0Ǝ#A*0FT&UC!Y/Cs"$΄ JTϊy U'ϩTyꀀ5֭x 6رd˚=6ڵlۺ} 7ܹtڽ7޽| 8 >8Ō;VIƊ͜;{YE 6Q5uU!晫=[v-)QiSsFޜvσL!L˅'ڇwӡd[w^5`H`` .`yE6YeAh^hj<]MT rSC,rSx.vȝM#Q2?x?)5^Hŭx#A$w(SQ T$ PJ<Nu[9fjfn grIgv !eeU!~vaifbᘩ$};͊- &Qm@ UTTzd/WJ@R*r#!%⁇IfNHOZD[{>h&Zbug^mnm~ yJȧf TZфl)$oT14HFv?On[0%*[+]:EFOcZ~08,SBK\sU> tBMtF4_ڇRuZou^ vBNtfvjvn}>aԃNTv~ xC;ox/x?^W h5 8ly0x袏NzTn&䪯z뮿{ J4u[.ަ{5N||ʷN;Nf|_=|~⏏f5CG|;d Wtz+!$7Eb0^,)OT|S_pZ*˜{reUd.Qv I.0SeĖ dG%ىAhLRɤFQ3z)P*Y)xsg77We}P J?2JBu2PQ%/IA+ʢdT$/' Y)̼o;$0N}*=oӜtg>]iL dARj΢ވ1U3Y[=Gg:UFit7g=i73ԯ>u'BB3HH;[SS t-a34g9u dGF1QfSٗ%13/KMPjWMvIpmdW^dݭjF+]Aq*W.]>7K4BJ;B{u.P g['q S.]T]KUlۏ: g5p6-?~(]EAPON)57V4(-Gj"p00UaumHҷķ*ŦQMJxKS*xD.`>+CVQr5aW$yn7Y>-7"\)?>٣*=Lju 7K]iKժ B> @/ɋ]r","/HZ5fgT- E֬ r%E `z_vӤ+JX/LaӇokmT*T?]#RvA@bJY53\c*$ 64G\8{T홌=[Ý`4s|{E۵+ & x͊yvzN=`6>(H1\a RcX;՗1~+VWzws/ b3 ]NV"1TlwK}T:תaӿ&T{ɸu}lo&!9P3gD΁|; ~ 7S{H3_Ɵ'߉-}瑡 r8HmT,G(G͒,uJyT%2PVDH4Mhrq1FHs!Idc$J8vv,@I8'DI5\T5h7>ҷ g5KGK$S qLKS6 ^T$,LԴK$&SM+uZLEj3Mߦ[3wf_T,fds8q(C~zG|h8vQT6QH %HJ0Qٟ Ѡ-lMٖD؛گݑi=9 Ѱ 0 p|  mD'ە ڸ}!ۓ}Tc|FO,ݍܒܶ /эӭ33=`Mmޠݿ[B~ ߕmn=w}-L H۱G, $#{$-/-G\08Ӡ{;-݃? ޔ/'LbN;nE^LUqLPdT8a^{ѧZ\X^h͢b8e}%=nD}狑΍HJLOnዻfkJsHP;(/(~^s[[+ Σ+˩.넑dنߵBKۼ>X%Z%aVqE!$1רy-ҳ9 뺎n p-Kx 3铠R \MmJl9znۭo!}HމN5cIC1/iQ2Iƾ%Q:|%_#C_!~v) O_糼Kp[U ]xWmg4^|w_~W@tW]whGvyva_+b3X߀duW KJ0dSb[vٽ^QxfkfsfAvUe 6hW~yi8>zjjxgPLlpH1HBhڶmX."nmn6>s"_Û˨Ͷ*:8j\{<O3f66tSW}ub:v lfnϝAgsIewI#}\#-5z^GZwΔ3|W3χwn{&Wz?̧bP$`\Vy >`SHB(n|9?!? zLM3'0D`HhF{B|1C 募Chz/}sQVR@$&QKdbr@B+v#]Ėg#AB-Nx^f1g/j15:ĢpeG P0c7Q\ W/FNd%-yIL^ Qdס%+{["GIFD2?*[ RP~$9VE@|7pd Crot8={L$LfSf7ŵINRiA#Y(Mx xLe-3yjCN;g6lm7C g/s3S?CёΛhG=9u'ZؗrHi!܁4ˑeL_V$qv$(7)( NSlPHiWU5? HjUkeZRwUQc)4rGjW.5Ys8X6e0Y˦Fw,ȊR$l"wZ1fXM{ZԦVOKTu LamrWPuQ@4dI\GM[Dx>.NF  ZCsMjk\;&3DdY2[m{^~cmm.!Z' o! M]P\g,` d2#W8Uj$ u0 ;8 z_X;^"YV oh&yec3dfLE>0i lo:v-t aCdع\e]Zs`dìWq }hDGM$ g'eENi[DgZӛtɓ):*}jj1}"ӳum-Ot_Ң˨HZöz }kd'[RjӦ.fg[X[{$fTמt}źfwoI`6ԣyn|;^Ɩo\&~9t_3afxrmG\6fp,,eGYJ#'y5mqa$>ѐry3_M~sܽ(!rɜlCҶ65psI'PĆo1Vߴۂz9Ma?&4Gs#:Zäv3W?G:l\s;Gy>0ݜ<ޙYg5H^5SMW=b G8Ko|V.N*D|'YՍzǾw'خRS (~ CJ 0G>QK ąQ 12敮 u(A['MG{u\ L!FsLhcw?sFʣ%!b'ڥ@J$ .7ã룷(@ @AgQHc?@0%VWB npL)=Z:!4rTa $#&eꡀ,z*;|B(B~AbkH?C)t>x!2\{Cƪ'7C/º:3y~8I$14Wk?K/ڸʨBE\DFLC}BQ[?.ӟL)))P.2&̬ T\Ū#ܣĪ# "r!1/C LF FaP],${/4xFbګ-+R.nԫ%l,EA CBn-ރˆm5'$F{G||*ć@fJ6K, j0ڇrH*\<ޚHh2HF@( T..6tv /k|IɝpAfD+ 0,0c0*3C0x0|J= Ss s,8CEJ19=i_?@ IKv0dHe-$H昳Ǩ30);),-B4LHh20u ;?TǨ;9L:c;X0<{>:`=KڬMۤGosHbiK{˝L;a\NlN{hM"sCN!DWcQNO,ϚNG)K-_`N4O9ZdNO-OLP˻P$P G NM PN P=Q)е-_[j)QQ%?iр<8"9=1]R&9Dف9*5R$җ|&R.%9tνS˪+:6+a:5M92>4Ӽ;[{PD5pE=;H:Z#%RIvs6Qle41%;LTI<1ϣJR> SkGc "",*Z뒡/+b!z]oHdYVg X4h 8j@@S.s?^?}<3j@Wؾq"@Z,\"UIBv؈džUXYQ| RiVR*c\eEtq^MbMXR,=F]^ffԞuBNEftNKffnmORL8Ok>_n^gvopVtvg|wg~[g_zN hnhMji`#/Uh~hiySha!%ҍ3gi ٤liȆhhR阦癶iNiihi(gf$S0T5]TvS3-82ݭITuH>nxy]X|}noKy mmxhnqŮeXލX]#4ZpG9ؔMG-[6&bBY[$6_oe~ooi^f)i8~6jݢ5A콦AfZ%&]nڍA=ͯ%ٰ!“lrhr"4vq2/ɆU i iP1M]]ٽ=Cy[۽s'K\C+(}U\ B/5!C OE0( O6sOh󔖋d Ssl]U"^% 兛]Y3YsPvj?O45 RohȆsUG,uj B{_MÂ!G-_<$wFxG{dhjOxkomws8UujfunHz?a`Z e?H^>_@veEzq'g:_q_Ű(J'LE*V̥J(vJ 02pZQpb&p4l7~WjvjTO9/s~i~_\(ug~Lq|i@!p (TpaÆP q"Ŋ/b̨q#ǎ? )r$ɒ&Ǫ!ˇq^Œ)s&͚6o̩s'Ϟ> *t(ѢF"Mt)ӦNB*u*ժVbͪu+׮^Bex2a ۶*l2bJ5pͫwo~,x0+x1ƎC,y2ʖ/cάy3JŒ5Z]_%^Î-Gڶoέ=.|8Ə#O|9Χ.{a͐n]/ϣO/vÏ/>ϯyt^g]vqyh@Ea8- ELE3nءEJHQ.2UDxXQN-X EX(Z(Nˍx>*pbܘX#C8!I.y)#. Higk٦oTӥ` [(%Q 3O=D*`4BiRAM8 JtCHt>b4ވ0 Kġ.ɍ/NhFL^qvqou%9Z̃^#\g޸&{ѹ< v휺jK;qr#ztxa֞!,9 ^4l$t^Q뵿> -S_8iv>Vѹ:0p~akAݾ/C>/`-2Bb򇯲JÛPmh~[x@!OH8`/"! KhG{A…ɕr)f4y]?(pBg>u5LbۨV)avFt&;`t }̈9$j\#7&* E)#Թu-`ϐՠl RIl БL,Gfkt": 10 Ld$K82%-ki9{q_w}t%M#(-Bd2iFVP fQE Ae_0IMZ(N'I&MiH c{3'?9,t\`H=RO|G5"h:"7!QlC)WSH |:)ơK`a4c{GI} *3?RO3J]*Sԡh/4 jիb5WEH $>_4Zx .Nޣ$k浠uWҼҬV+ŨB!"%NU#te=`'zv`^+e#GuSKkӢ6pbp6AK'-o<6.q2ֺvʝmmy_6ҝnGb7.wթj5*Wm[,W/4.{Xdݝ/}kB@7t ="8 ^0Ji{E c810p8Rj8*^`8,82f*'߹A_X32ld֘7~E@62!9Z2a\.!MwcfLj^h79rvӗf%v 45"-Mv 3#g/AAyDi,IE$)%N:X|-ֶd/#X3[W'=qAʑ- U2@mET*D*VuV\TOLr"LK_Мdͯ! wu9jX;cdݽ;o~T݋vR4pU `y3.O0 sKG0hg.nbuE,p nT7;*_9˟bcI jeyj'N;g07upGZOY 9t46rOoNљw9$C?PAt\S O3932aQq1aStSM.M?H7S60Y歕1`SMzE:#BbR^z0C2=H`婔CA2i[q*޾G(2IDKT-NaqHԋp[.`i^2*ZTuMTCbmD#Fb6j6eb3X"&j"'y ݽ_,_[F5 <ʾ;U9^aE5ZLUʡSLмBR$Y?~i6rFrdGV78^7#XJzKdL8c?jt"OJLeQel -HNd9y^WPR%UjQbeVje~ludaUeXUneYYڃIG@>R]5CIX]Y^e_^FW N2^faPeb*b2`WWfe^^2ffjfʉZXG?,e[@&Di֜efna&gk&ONmҥsșfjfoGkfp gp&8IXO➡Zߟ Π0>BIIgui'<ݤIagmt# $`穑p~$q@&(9raDmy [ ܂b>(ۺU^󬋃Lj'Y>`hAF^ =hʰLd-[_Kvn&Mz@C:er%lň C h©!i; N\ŽNu\b;\"&a^z#\%: h1'FA@ ݅ )U~Q )`"S!^M驢Q:'y^N_䝬*^`KH2  A_7_V`j붾$m~`bm"ɏ^eF^'Qϸ'ݸ90A!ə*Bl:^C`*OhJ>Qî_bƪ,Ɉj 5(iҳ ZvybJ*fO>nԚ&ӾN z%šZUׂ] :a!4EV?zf1`QasZA>@~C^{rgEHD6NEzV1кo pc }" O pm⦑+ 1kpqל>eJWTNeC1zذSqתBfsqPNqӘgF YJ~Caɥq1qw#iD5rSׅd.e#$Sj2͘$0f&$rFJr%r*PqBN +mnꦙr)2o*.O^7ڑPF4]|H3ڣ$3V3h xzŴvȔEbImp2n~;G^2h^ǷC2.Z(F(t2.Ѩ&zh hȉ#a jh)Q͚\BIq?{[P=+a}+H\ ~> :.vLsgx?n!d0† ',xPXg3nTq^5HQC 檨% YbN: (8C5ziRK6ujTSVzkV[vlXcɖ5{mZkٶun\sGUw{0p` V…ut!%4vt'2̛zZrf3Z5k*KNTI%J6@f)gv 3j䘅F4&xse8#${" O䝋 ~|׷~.  [AKSB*B| \83$NLt'V\FYtLOE圤PNsP4ъr U3mgBJl=|uSJ#(={zd]f}h8;>u P•ѣ+img"$t݆VUQS#SHu|t}ԩ_V-X:|s xp\BߔxbEM>U9V[;os_}ǑfpYnޕV.HH{ihqZ`̝.hg%_ ĭ(?e Rv%G\y~@\6IUW-mXc}襟zǖAmߞsqo2\sI؛3L5+1})1iݟ\r_37X>Ҿ#/ap "A)JXxH !I֣x UB%OD)ZQ30F}( o HIZRf:t1UJYR*%09D9)PAP)ә&fjN;T ~YV0(748(ZVq+Cy^VD#Y RUUb ׹>ZY^_ep8zV0WX =&1x89W;@SNjuڄUem^I!b ZM[*☾蚼vx[^bůG8kDc@L12S= _4b2Id)g v<2bJmaݨ$~wՃbhq- ՇeiaI :ÑpgC:(6=Hӝ56rFcpJ-߽Z[H=wPmȨnP7w wo9GYAT;dS#0 ^̕›aG^K爿-%<_sɍltڄ:I3n3m [q&AYLq-S={d׮VzJg$mEӆaIDmFh#ǁCf*#$f~mg3]Xw׿ݷu>C9]j}l kد,p`}.NҔo;G^Qs}rwGsE,zQ~摌_~_,Sށo| <շ o~3;0GkO*D(34ڎ3_rEX$'58:l-`D~뒧SPWP)Ofl,fdڡjh>o<'Sв\-bL1+2*3;B#N6Zzb 'OriC̎M~l#?NQZT 0H( lDMdBll%IIXYÃ0iJmoh@/D1z/5YtU]AyW9Jsz˒ҹ"4 lʣ?gTnÛmbtP4i4'yYUp04CG'ׅDThFEȹNS's8HXF67hcGQDcEY#go͠0uytQKZ:tLE30隺4ڤJkT&-NT2|%Uσu,0JHc{kzwkKS 75 fS%T]WX\͙oW,wrõxnHݧs܂֋sד]ۂO7ا=}ٯǂơ}w\4ٗ=n=ݳBй}=!7)|M2R ٟ] +޷}[M?Gb3߯J Ky591%Qh3ca;牯0H"~ͱ<7ZˌQꉾϳ헝 (џy#|,!ͯܚS>=-Iw'i|k>q响U7NR)=5߹Cs;:&y^O_=NJ{5s~&Aw[~??ǽ_xo;>ǟA8}$rӟާ[ H`A*\B#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ0#ު q@S=BE 6jaׯ`ÊKٳhӪ]˶[Jݻx˷߿ L*5RNkG2fSbːϠCMcrfװc˞M۸s=Sqѣ CYs =kNU#OȻËOyf|)q2e.YǑ+vhv5F(Vh-\R W=4aO,&(4ֈւa<@)iؘp(%wbm8_26f喨`)dihdd{WSfAa)/埀 ׉ i衈&袌6Jؚ-9g~ٹ_qʧ*]yəꪬj:֡ęXghz??7PV0s@P3F+ifvZH:Z} *l㫻VZy,_Ss )}t Z] *k >٧1@@kdP,0 !5pJMdY ,TVY(74A*&TWmXF3d#2]_$Sv)؋pǭ@ emx#mMUYN̙jQlпl SrW~2݅w9~SՏ7Å;y}oڏVbI)Zs/e>{-ثxAێ Zٺw/h/oxƋ 1-ǯ;oWϬ H@L7,fC߸T':| A Gh?I*`WB|0 gh7JprA\ wò@ -͐A2Z6p+=}H(X̢Ŀfh4!L s2ALH:Bi4ÌDHLF:I_2G>NCl^I2$"!IRu1 XI>fuLybCtO*~ .3JT &J'=fF4y3vIM^V1|̦6͊4^h egܗ'et5Iz$c 9a1ˮz8aXR,s=7юb1tb (&̃B1ef`׮w ^Exң@ Pҕ AUE}y1iclzzџ` l1e-:B˳ؒq4cqէ^W}3}9[NgFiU6>\j_'Kh2{fؗ"6f\v>I΢d-ֺUdef_̖Bճfh_8Ɏv˺]RվM$9J^2mb "=VKM* oL?yUnU| aL h(BWm{Nz˞HMI\֪l axW bQ89N><9)N"ۘF,wa2:!g]:A9dB3߲ ?ǍGVq.X⢱U22=ݲVbU'|f4wmγa wRmgXrigVqψN?3 jfE[{e{ NIzi3GMjjVfkB=]^Qƺ-V;,6uE]^>m٩*m5m%鱺_Mj2IuWO%VhwoNmp؂LKZ%6x~ {w^lC덽T'N9*4 6{J  H{+-N ]0cT8NH~xڣmr)ܖ2OGs͉Ac(ʅ]KAxh_J @0)W]^3N/SX=7y1tVkTwON([c}2=$қ~j/zRحoe/=s?/y^ğOll}Nj G?=g ~Ͽwww7H7nHz؀}駀&xHbGp'Gf8$2 *PP'&%X6h`F $R (F7xH'x  -X zDjFX"MQ|BUhgWfxfNXPkhc8 vx *T17VxXZaehx`V +.÷Fֈ$frhxȅm"FdX艰mX(jq(xfxHHf8ԇq؊xcH{66P/9蘎긎؎8Xx؏؍xMy ِY'ّ "YH؂Ax A70294I70-5< 799ٓBi8.9HE>ACrqN)PɔFSɓU9 i^Y5`dYfyh607p"4@r9tYvooy|ٗqF ~Yt {i4 闀 y|I\_9y0 0m9ٚٚ 7ٕy &3ٜϹyHa%F9  H1Bؙ pй ՞ & 5Fک>ř#&60gz4l ʞ! $D @IΩO٠ I_ ,DŽL@ yj Ѡ u٢AڜDVzXj*G:"C j `d""4 I^4 )$Dh XЧB"Jv:XG @/۰[i۫Kl{n+ PuKw;J+Fj;Ke;bMշ4rѩw[0 ҀD(+LH$ tjNtY9\0[K@@{d۹GӰm˸Mq `v+iBJJk˹ [pLɀǤLp{ |}˱+˺M;G @huL+Y, D ۩+%Tkl/J{$` FJz E[*Z9F+ KRxV\Y k*X{eL¼˻ f,ƅ[VƴGy:ǽI!ܣΙlB>PǴ[0Fķ`Nks7ŠvU\ʦXŹ{ʬ]`ǂDɳkeˊ˳pKz<ǷwJl̽\,{L*FD|0ɠ+ Nq+εɵk̞ K7ʬ\(\(ϥȔ Ͱ ϧE} =DP _[WMYc~TޣР  n.nͬN~NkoR:#E,0+N.~nik39 0>G'Y^Т ٧+@垝.ڇ 뫪GL;o|L~-|'/מ)6Y9:s, 89 Gc]=eB_- &Km?{] X4?fDŽ'_7*y& 5И>}xvO y_wz{}ޣ|o nޅȇ@J۩/aV*+ekr/ڡɩ3o-^b ߩ$ $B`I7.L %|9ﺳJ&jӗܯA` PB ,!>Ę}\RH%CFXF 9vSL5mVSN=}TPEETRM>UTU^ŚUV]~VXe͞EV>jKA\uޭ&@X>0/aƍF,b⾎->Lyeΐ Y7LF-lڵiŝ[n޽}\pōG\rl[Atխ_NA/M6@ ݿg)ѧ_{YO3jfOs?d&0B 'B /0C 7îs *D*؎;|`E_F+oođqs1 "ɘhI#o 3%<33L1$L3D3M5;RkA9眳R2O=O?4PAhMCE4QEeQG6EK/!`SX4 $TSOE5UUW4RW_5VYgV[ojҶ0ȠW_OaXc3TVeYgvA\Zk6[mJ׃=VXNXeE7]ueKn߅7^y祷^{և 4_7sE8an^8b'X|%`2&`?9ddOF9eW0_ 69fg58xdw9d:h&\ ifiƹg:a:k|7 l&l fm@;n离^ron'po`-2x'xG>yg9!as>{{?|'|G?}g}߇?~秿~?`8@ЀD`@6ỹ`%8A VЂ`5AvЃaE8BPyoqA UBЅ/a e8CІ7auCЇ?b8D"шGDbD&6щOb8E*VъWbE.vы_c߲ 2ьgDcոF6эoc8G:юw<^=#d 9EHBҐDd"HF6ґd$%9IJVҒd&5INvғe(E9JRҔDe*UJVҕe,eIȀ!,kV]22ABL$ JKV,,8((4BCM곴..:33?`akH*\p` #JHqC3jܸ"F CVQɓIDҤʕ-cj| S͈4k܉0N@tPEeMt)Ӣ9>*5G$B}(V^6(ٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνÁO  @gؽ|ߧؾ~(~$8B`` w}t`@8@bX4* pa^ !8fLX@!,3D22BCM$ KLW,,8/xCDNS8! 8..:((4 H* ‡#JdpŋVȱ@=2ȓ KDɒʕ-YsL5;ęN=%tТFg"tiҊ%UIVjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ|č Lo?+}n({kN >xʟ=/,@Z L au  ǖ$`\$P@s9!, 3^22BCM$ KLW,,8f((4ې:CDN..::33?ff:ablHÇ2HbA -j81Ə'@#QܨJ*SܸA770fJ<#TТEvɓ:5Q̩ ʔDvXX '\8˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k;@< hF-zjt_Ö+{6 ~@m{pxݮ>` hN@rqppM"H@>p!,U22ABL$ !BCM )7H22>XB}BGTS9?K=@K3dGJU#곴#++7#5H_`j "9>K1CHU--9''3 6=JHP`*$x‡D !C7A6 r#ɇ-]eƈ'WR8&Lg\SG.CѦPJJիXjʵׯ`ÊKٳhӪ]˶۷pC8PuSR74@'&@5|x,Wr ;L"3͖9eJ7,p‚RS4q@BDPjv`]E)F" B@@x0 %B!,&!22ABL^#$ @AKJKVJر,,8e((4<@KpBCMir.9I`s,-7$jN..:kɁ0F$4G_33?"#`_ !x`ak0`@ DPB HQ! Tab`!G!] b' @8 E ȔyP& -Ob)PѣHMti-+(`E+ FEH*JAhd76 @E0H*0FV`NHÈ qpd Zf&0{hH#@k81rA!,$##u22w[x߼uuABLxvuwJKVu$^xwwuuvw شwֶuvyΕ$xvo`wgtvv((4wwvvwuw%_t̊%_vxvvw^v,,8v$wxzxu%{_`vvw嫬xw皫x}~~ ߰xv|..:EFLuvwww\wwx霒,j..8ʹx桺w%_wv`vxȫ33?wwwwvţιހ-|ab?x㸿wwwJJiwvf`akgȡ@A/x*4r8q0&( @МFB9-&(S*C 0͛7%'O`GΣGSٓDyJIX&N Ƙʵkհ|qkMAܑ&/<(`Vlv!>Z9@+e Ha$j ,Pt(Pʸq`SMTHBl+qP/Y]fg9"7;V&@@yW"M4#!fqJ@b{M1xȇKe8w%pSM@=$M$X_ Nf DMT'@v&a G/93AԤ=A<IZ&ާ()U\سkǮϟQeQYQ[t @ $ẒϾD#N442 LG&lwy] @G` v } 4yI!p@(0%B‚"b|HxZ&ce8:%3F`#}tY XfN>I8^i[e^@W2$ܸk@LП @cpA@9CZP$lХh5R@qPU!&jM|i"*}`;k&鯱!,<99@@9922111111,,++))!y!h>(,&&(*)*+(,H>@=A?@@9?C=eHr D~ X bjorv"x6d|urm7*&@ SJ &$''''Fp z ~ /Z}}vH*\ȰÇ#JHņ;&L2 bF%x˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJ-c@u2k p3N]˶۷pʝKݻx˷߿C^MEI MH#KL˘3k̹Ϡ I0ׁ:>:AiC˞M۸sͻ-GP#bd ;V5KNسkp0A$2/hvX0 wOϿ =7ww DH]߄Vhf]W`Yd B>'a,0(4AXgwA)BWDiH&7x$A~ Wɷ\v`)ZMUj( TG 8tix٥p<ɩ矀*蠄Jj6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+覫q@+K믝GQlp|0Wlw !C @$0ܲ0,̾08>dDHWLL7te>!TWm5VguDSMdmv?lVb-t=u]Bq]Iۈ';= ,D.9 +}rC>y5qkyr .DDAz1GuA 4;V?&C:_7C1o =O觯f>ab>?˟0#!p01As#1 H|PB7%wJpl8x%64Q-r=y|ӊH$H9P*Vbh0V"z \1^8F1b`8At@" $yBB~ǃ9+C]LaG#{$MHVQ@K/-k tͲ%0R\2oL/uq ;pȦ= $D#wR'lGO"Ly#4B)P.ɎX#ӟ$g9P`ygG4=sFO˛IOUrMJWҞe3{a1r=L S]NT0\s  'n:uLqp8O )It໭P|3 GbČ8FT=CTԜhCUêuR+b Wu' Ϭ ob5NJ».'>i "xL8Ƕ K|. ,@Rz]=-keںs5mkUv ~@NAQP1vӬTKPv!DIRJ!yS%7P*nV=8dbz׺Uy;bgE(աڡ w&y; $Ͱ7ta  DZx ]@ׇC<Xr&qxr6z@8᪎lB |Ѓ3"-8U{/;CZ.jrܩɒ5Yd׾#0`X%N(=wy#n iExrf 94Wvt"ؾv~m(w3sgJ2kCԻ&#iIsҗfnN&c{F[ZE&\\]d!hOZ?9fUa]<,;$~}m)+rq^/׆&wʇ}>;%tCO:ї.PЗxcEv.{*rnf(Yʦr.{gp7(ړ}]<1,kw ;5yCuXaye:ְ¹{+N/-VH}E7>KGY/9׿]@{sسKsUs5M3 FY}ɢЃsAՌa`|)WPSpvM{H$_NABnf>U0XXX.x h (4 ؀2I DR08 (#؀5xj6q 1nk8V0V.=(?(4A?c 6R8r2UXZXX02p\8Y'aHjhH1Tpa.OO0@Pq2th"8X!ʅ//_x.؈}XXx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6ْ :<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dIXhjlٖnpr9tYvyxzOy|9Yy٘W闎9Yyɘٙ9Yyٗ9Yy>ٛ9Gyșʹٜ99Yy)ٝy9y虞깞؞d9%%P ڟIz ڠ:Zzڡ ":$Z&z(֓ xI q!@1zv>*: &JLڤNڤ&DZfVTV 7b:9Pfzhg:l:7<\ pvsZ4@!{zڡ,ښ.0Z9J٣**OLqZ ( Jʠ`ʦiڦڪJ `yZ ~ʫ zZx:=n]TLׄm 8>-9`D-5jM!od=a]V]6C7NSQ]_dύ|}֭}|νҷ;O>(qC-Xea:v<#Lڥ}ڨomj< 9hdN= >MHrD TrI4W}-_a=M:e->^^4Vre-._OWOb}MnP,lw#,.^~]}NvU.ͥ L>*^JϬ}s=.r n,tۀ{ͮMj*N&]6uu]b=҅.z!.u#~mNU._ގw~\n|lgX{]T,Nx;'>}Q-=W=VQ8^On~膞ɶ`nC."_&ϻjJ~~J/HtN|}쥪40j ~H)HN`4`KesE! jf]U0lOv?^Q\Ca^K_ x ;UϰPϫMm˞ R8ՐN8 uU!Ah8W߆nmIO.kͤYzMۥHNO;* ;)cOy1E@ DPB >pD-^ĘQ=z\QH%I8R 3SkRrʖ3}:ePEvysRFaȁCT.^ӨSqT"ӊd5J2\4];)ZX]8@^}X`… FXbƍ?Yd-_.dCYpNgҥMF.̎XC}%6ލYsgӶ[EÍk m@1&Ut52X;Ƹa'o]<ּݿ_|GZ~`#p/@<-=Z5m4Zox(9LNB"p5JZ㎺Co;Ѣ@;8O-kq8j?2H!$>D2I%DMBR0ǘTAp -2%+iG0%ΫM#828 zI6ZiU[I,.d3Tw+mܠPHXJΏ5w#t]C:eU؄7̺m`F8if%)u- % XT ݉wVb(i(ʹ6:ӎE\1d>|n6^^{2NnWg=w{]f#DZ>mZ81rn~^{a><'Da UBЅ/a e8CІ7WJ K&(ՒݽLKID z]q5Q^# ff;ȶiOgDc#>#oc8G:юwcG>яԣb?oL[+#qOHoArjaY"ǘHf:ы%I/:bܤ(1A5ҕLg~F@Җe.u= ! !HM t 1XPq22^LSArl(/lz$JXӜc#/չNvӝeC aHUX{Ɗ^Hl3[2IAMō-n*OdIwvԣ-ɐy'I}c;E׿\ T, UiL[J&zK0QphFԃ3OjT:҅''PJs2}>R&Z QP\5iL&kR$ui(!ZQIej^(6l`{ְElbX6ֱld%;YUJ-Y~ZWR~Z똜;bCi[*M 6kp˨ Enr[Y6׹υnt)k\V@;C(5CKkZI X:1WZTn*Va: ֌pT1 A T ] W5an6!V VڭzLՖwGu^)# n@괨%ibߠ40~o2"DGF6 Or4CrP_sѭQɼT:6 (S['T=s 60 K5=>˃ L<̃e+3S;<㿬aB`܊@M-N<4OS7c8. :C!@s=ߓ>CScA|=;I$ LP; ͒,\ s?>+KMTlStucxŏXȱ)"9`d0{0$O %_*mOO PR,=tωӶ89S ;9ڴ45xl mN qJуrE9E3 BQ܈ 򘸈T'2Pm%$SETUVu P'<³6HԟԳ UXԂV7G% cQ"N57ɞ{nE#6#,r5sEtUuevuwmWbyzWuq#% ӍeΊTг`EԈ$㜉uXHN K+[l5!֑!pדEٔUٕeٖuYtW ͊$ % @lݍ0֊HL6%٫6ڮگ۰۱%۲5۳E۴U۵e۳ٻM1T֊ 9mrΉ=}ډX y/E:Υh=U 1]"5 X]۹QųTƵN\)EUeu^].c9hEXބ^Xg]֭ T&}7k]O/_1=BԍQ]F Tߘ@ݰuڜŞZa%%6F_` 5F:\V؞Uˊܽ•4\J7X՜֩&nM()]=mܘ&<ƈ] f eNa` `ǭN'*>ӫ:`o/vaو[3 be` ~𠈨 %N;&<e?6SF  %lIdB 50))J)_E9pbQf"_} Ti^hƬXheՍae_ C>dԑc4.cb~UO^fg!yfR.j>^hjl6m.BгCeDUqn]&bhH56׭ˏge~f y C0-x2集SSA❵ሖ剦er^caZx.E`Fub^ݢvƼnVϓչ2'i`nkX;ljVր;ذGDVSH/Ig6g)rV[j=bm &2}N:lxf:'im?5Z2~]#8`#abkUպcvNjN g%p nd26v$j 2=s2mІ8{2cn3;N~۶F nXp Z6V6nnjvdžKMl &v2'es~+a?=n^V`NnSip`Q^Fp喢d]c<&@+o s70sq'q"h;3=R;4'>'3w#m!8^Ɗۋ qAD_&wM` r]r,n</s1's( 5 8lV.~sھS;W#mxA'@_Ϣ of]  )ot@#0[{M t/ _hC/GTUuϦs,7w[sDeuUmR{Vj <0|p*+ ;09 k1W^uΞ-. V)rlrY붘 0#a7FUo.I'̍4d/0I+4MOQWF<5U[hV l}'h`M2ԡ*kGv@ 9 Tm7SC#~X!4K>9A]Wk9 g]m"&26h)Uz]۲ޖ.@bA% > p)<\GxK?=P^ykJbd!9}vfF춼`zD"(A zo@;b6/]z;y-mM؀2n<8fj@pLeTV&4_L:3э@֭)́:=bOq cXR//ݤP\S |9[7+JъӜ}*TQ,5VjUGժ^P Le|.W>SJ17$yQjSOUJQ@S2S"+vA YA* +*hɒaX4]i&Z5Ha ]k؆i 6]jB2{lNz`6,Xv˂x6trZVtjiVTfEz؞e\y(&8""WEsA&aP.M>2(#y)D$%B]7']yçյK["Y0~EwIk"u-7S~d'sn҃ L 0@$x=)@z1Lb>+I|R)Rb kS}^'$4vCT%BNjB\M)ʞ\O^" /;9@{&oɺȶ:z쥯hh*KQ=Ev`Դ+9PNj0Xl]ȗQ]aU =Du'R{)xAK.^"/HA0Z"I#盼{1Y]hE;P%mh\smE)3Sy^b8-MMjSZ?Rl+$#5Q+B5:72&{,"/1HE#& r;]M, ['W:xfʀ\^=`)~Κl\>ʍr䳯4xޯ;}N0j} e-8H(M'(ߏ0$VdaR\qYiћ4E ī ShZ a~]"v[![h\%oU_c [u P}P F (IaGDDLMGr} pل`_OyH Z,6n%΋C*uZέ!(Du[w_DA$DL0D "Fx{ a&1K !##XV(QaPm'V(Rŵ ]bi#⸹<~s@GM`gm-|évv Ǯ%)]lXAG"BE-&^$HM$E7fE)"8V9Fp]tbS$c£#OVY=aN "P.ed a=A"MI|Iz&dKK>เNAa!$Z&TKI)w}P[%Q" RT5r4'$Y5N7q 8J"9^*^ fbM&^eZ^&sMU\n&%RaTPbmedaf೭cd|M:%;~TeboBfrp:gnZtfVΉiffnBUmflj%hЋnXF8nPoyfTpzJq&GVFH"f*U hAab&d &A]%KFg5y>-zN(4b\T^SR&IvuFaNgT@%uU9c-Eb_J9((I(XYF}fiΐF%_+ @`f-&d.xxz(SꨘbYt&O:&}&Li]4cDwhht"Mdz)㕆S)>)&V'\L$e#* e_:EubghHu'mb%"P6FģISrgj-) do"b8_@: ***rͪNOjh6EȽ㥺K>!jrJީS䩔RZ+Tx!Rk;ګơn.cѥ[z;lH{6EV ik.Ũ^i(\(2+c$ꦿ$:, H1nn_om,ȀbkRK.*/"._Q0C{L]yvK0#%wGb2@ ysixn4)qj:ⱸ7dy=ct-يjGy ?B/BB{D|(|HsU$KEZr65ʕuII9 K|ǵR(Tؼyc8釃g7"cWSZ#Z8&;wh`\ 69[ \zVwz[%:&:v Ƶ7<߮vlnwzynrY|4@RPTmᴡy:fwҌ7)zީ*:J76{?;SEL@D||@/9 ߻xOJF5yϯ]mi@'n|=o==sهEW0U\=f}~@ƣ 8W~\^~V=7ۻ}={c}'T|~ G6{59K궢4a^"?V<}G?=W?@L8`A&TaC&ND<bB1fx"9pAcB%QlhQeK/'А90R8BrgQ imPYfL1O%4OHA݃lT~]UTޖl!@uޗ=Ej!X)ZV9pTUQZV^ qVZdWeWU)ULD6駡z1꫱[@.JˤQY8O#4SRUh yw_x^gahrZo,ZZw_O7_hմq{ \7d7Oj׆zq=|sÙ/>jȩʘ噟r0IsޗnA V[]Ăj_|{yLY!7^g<>{ 5z bN]aj[B7`Q2>\O62ۼ t~sL`C! q1JE&KaCҔA7: p{<]/G"53[ Me,K C5/ _"F`\$ V|EK&Aw;^D`҈ьd%FMnr/n ]"" 2d{7!e-qs"wdg)A,&TBJP4&2IeѓVeKDCa2Q!"+۬!4-{͐%BifMcN&IFǴ=eͬ3UNM|-M3& EP gv*9g8ʹ]v"Q%5O.ϟA Dfc (:5@Ndg8:TC!u]NUR,+*Z:DAiSR dN" i*Cz#Z }U*›_ ^.X9v y VW5v'S\5kJDTԺM` 6%Y8;:6sZYՕW;-vrBҠ;9cX}dw RFݝ([J/WL"J*#P<ȮE+nhC\̒4J{+D\u3Ի v{;^ k*J`Л^,> C NQoKȹx>A\,x!NyCa:nX`A:_(X-yc%Xt.,=!yJ6"ڱ7/^H̥A}V.&;gz_fE/zc.s knlXh"Yu K(B}V 0l UFǎ #iQ:&2}m{nrub̮SnIGY,݂:tZcIbn2nm,a ά"w6Je*g' Bp?±:(jO!坝 x8JŴoݵɵO=-w9a~s8A5]q>jLVJe57dIIcTZ&ӏE€{}/կ~Cg:L}Oà=?Ƒ;ZobaGW.kޘov~73#R;g_}g8C3_$kLz'sꋳzV{"#ň~hGGUg{;B26͡)/OO7#wD,MFh'O76NEj&&0/lP*40):0>p6B"F0tJpx "ɠpn8.Cj߂ e(|0Npx8ee# b 7Gl)pb#*_ ds0rf J%/0g ٰ5!p0WE L#jz;.3  O$1+.152!61p: ?qBuDRPOE oQt'{q~4q!ѦnQDD0*oma1MQaEX0% #FǑʱ4Q!lSW1DPI"pQs ]RZ2!i!!!&"""DO#DfpPB1J QEP p<^*%%&eh)l!phI$'Ml,2%/d&pKI,j)Q#g,KC%1b *Q2+5i+++Q&,/َ6" 7AY-$ Y$ M*4$0~`*Fr'1($͉3+(V133b3uS.bE%4Qs9D5W3( ӽb1%݄r2-qR喀334%9Z955KS83 3"$17G:<.7A?=K3>)T=>>' ?c?gӶS)-*8+%`Có35B= _=+4GB1T( R6?k;A 2Q%]Z4!3Wh`GuK߂G{y~( P$~2B#SIST%P]tA!0#dUFfB4PLÔrt't t|Fj(Q@JEwh3sE\R3#(n5MmqQPQPPq"QbQlTsf:;ST#3A" 2ONEO%/Uu,UUaV'@VْVk5DBR)3TPN{XvT7V}Mu^"Zr4t8S]UDlr<%O<A˵!X-%ՊKb^c%[cP[ `?nUdT!Vp$-kOIQwb1c5vc +_m_ȃ_ vNW'@fxue V"Jͦ|,biֲn]tfwP{ghc]c!u1V`:%2d-7jA1bu$gb6l/vlv[̶%HQ\A.g!pH Y{`Q!.3tVY#l W3g Y pEhh$Fm beĵ,7Ev],%obkO^SWu3%qUbqa*sz[d rQ6s wQxET{skQp w^y/zSBz`̅bG;g`M(awob-"tWPW~ɋucu{gqUB{K騘&8s?z&x7WE0Su)J%C1w%"`O4jY(vNeW%8}[RQkIn$r_5w]$Pm5b/NfWeͤѕ}YXW7)5bٖUؖX1LSy_P8w?An) sԊ8?8#uuO:ɃȸVėsX%N;$8^cؒ3v4GȕCYpB)'vwj`ꥑ8q9>uyuJ,{} -H\,+UA7s"i؉]em_ؖ/:-X08iW!7G^vyd[⡱cq%}Zz0 zHZ!9:ns@Œ():G~(bЙ D*#U/˗=(v5͙YnErl9~z <4AZ9BC+Z]B'z2UЋOtZ\ *oG)yp>ך c13؜zE(9)/'kQBв4y{0 "$){'΁Yu7!$XDH%EP[T[Y5]#bUz/:my<[޶$LQW_[Vz:1br[ywA^6L[]ð).[P@;'&$;a G S% -#!D`Á+1 ֏7o1`$|Y\Xyk/oN!z ܶXU`{?9: ٕ?%,iȜ *݋^a77׬3,6ޱI}!L9v[<߭4]O)VΟڣ]ySu^ ^!~SC9MtW+o?:I_%:y64Hk_]wB sKZBG;^Ge_6I^=# ^~6p+r~_3~!;[lH`eo>a܂I1SqA}t$aqEWxg%.F.Ȁ^z'ގb`H~>4bA`N> eRNyڂ/58aZn%n $!_\I lu'vݷf p\|wgz~8h`K$NJifKXviv%mQEreu&Z&sqp(^`5 +d'Teh6װcEzi> m,eЦ^m^f:j X:9' yߢdЍf뾒 }h @tvŬ? qĮQ[_Nn'r\toePV4ges,W\5,qFtFÔqN_qibx˜wZ!һoY&_f VX_eP|x~,jvdD'w~CtC>MxF}Ԏ%ӽxB^Gn{dw^ޔ|p'zu3ž3߮{34߮H4Sh2֟k]>A+0,nn# 'o䟏>!C+6[Wv}rJ'xkQU̧ jpa_Dw.IBoLz(.19@Xel]f(Ёi"&2ApT [bBN W!&{BQB xfD#APkL, HJ 2? ~YZG\2araHy2 T`F%#mYH &r, K!RȐ̙a%[˪XqAgT0Jf RQRVivlwڂbiX٭ek=h!,% &H;:=B 6@"jw j a޼V)TPYx^WY{K~@&5/KtP+ 7|wK09ŽeD09 .[m< w˽#=/X *$|1TzUz\W2>fή2!=1yo~~waRmgh&tLg?Wx&(#jGyCXfg^ǁyc_[؂}bw$ hv1m:k]x4;ȃNjAX`W|T'DP\*2h6~{^H_~aqEaeyg|wG8V>T}ԅSH{hb}1>7X0`~e$6'$xLfKPOpyg>kᇖS5H~ ~#ЈV6畋WܑIc}}xXRoRь]adF,xtKUC&Gߨ|\|h8ЋjR# !hɓ$ {&dW}(Ǐ%Y)cXq'6"]6"f2юwD9l"0}J#)& T)YExU?&g5 n7kJNOBM8$FɂoH~!QN2T9E+;.!KOQ'1و02@^G`k!`@fa0u^:=k"HrɇoQ[W;tBZ!%cЛǘP7#seaol(I9|aƑp1(~M9yy )9ۘI-ǞéIGg60hCI94( iّɌݩVh)ї ?c١I2yCj!0<ϩPYo.H(ؠLx Q>=& Xi-YNf \T'W|؁kX}llA9=38(j jf A8EMSe p!W\J[QS~"e85}piqʣ=Z>\JCڧ :TZB'$!jSĦCbxc/MmGI(r:ZJӪYGZ LAb *hj6⮪d2 j!4=UIa3dxbgPp\!Ax9rh*:* MEK 4=QTEZs6Cȱ*iœb'J'ۣE{1 {75˵JC8mB']Rc5x6O[Q8 +.0,(ڵK7 P#fBdh@;Cʮ [<(VpkjRsȸq/~?*K-Vle[ Wx :mbh qQea.R;ڲp|;/RWwzN~BZ[ uRdF6J&Wv{]{-Zg{[{x[hwQљ@[⑗Y;;)sd,]->V%۹YC/ *I [,ѫJJ0+]Ὠ eU\aĮb2ʾA@:w]S{|RފT^>"==?k8.Ԯ]hݚ曬!CN}. MXsNhwy~V\^mPJ'H2[S=%nٳ½->|c=߄>׭]D>k * پ q Ğ4~EvꃾƯ(ߘ}Mf2*`X n7nػީNΔ~>^w3% ?B9=H溮؄]R꼞&?.?7}\,st?OAC6 Cr.M_#d.l-z+ >BOYHOٯpOr?V L :5kss]q}ݵX!@II$Zk#xb+ [vc;EԂ%J݂"액;\O;UxD!!"8h\f(aizHj6 \B6h3vdžö^P.\(g~~g셆;mÂW|q˪j#jOۢ7hd|"he{~[u{lU {Jɋ7%c(@=MdH.ygWlgq!_ ]>a ?&] l l CC:lN|]pol<8MD LO/0bφc$#`)}J󾶲P`?lFHDYb`f5ObH4!)p: /FR c-yɿ/&O:O40z s`1$f&h%'NJJ%%teBH,>idf3XILF .3| mU,TyMl˅m`uY,GrFP:/SvȠYg<扈ς@ҙ%()MY@BPVɛ8 BGf :! uQ4fŞT@mU Ƭ?T;hB}ZG C# n.FSm YL~P P= عO 4]29#НUOݚ^DRĔ S[T連9 T O0gPs1gY:U R[Yu 9/+jQs0ЁT KjcKu-mX:0ulqςV-A><7@&W^4AkE7R,m+,(+(oX 6~)^{_'o;NF $Z.k7nj  % jyَmhثTb}!!$\W+n_شB \ >cOZ#G9^zhnUzKʙ2ثF4@g]&e7cόslYr:1WszyTfs9<*V nu~>=#:~]'[S +S v~|q|# g_Pk>z)5"dxw vV~ªr= O{3])K쾟\/ ~]ʀ ?߰7Syyªt~ߝ[$=I_fS3 K4k3'\[0x??d&?2K*?bؐH@A_Y ,? Q, /@|Z@AVx`2{8"O! `\Fb|+9Dl:e|%&|'B1ZK79 ٵECY:pAT+ǔY^tJdG|w|ǟDyǖ{T|}gC 4EaAAoE@0;5AG5Ċ,ʨHL$O:7b3=i˸$$qFʱVZT*L\R4?ZTI,@J٤DLtLKJBPlJCE\jۜ#+ʌQ4I2 TL0lp@2nEMdi"9tZƧ$ŨD :pHM2&4LKO!O4OLsC4N Ш*lNɴ|3ؼq2& 6s4L GP% PAsJPtOr ϚN5·,Q%5 'QRQ*kQl2RʄQ8Q(SQ3SR0=Է1= &L# e,6ҜLtL}HFdHB 'rtԟıDTZ E]TJ6hρUIJR"P!̈́8roPI8U~ݐ;BuEjьUo#DϐtTdO0YQK=PWՐ@2Am}hS@V{s47noM0 WqEB"D֓v-w<ύz~Xg׏-ր, Q.VٳՆ՚4 |i d7-\S@\(;-1̛ĬR-@ZXZ@_YYYYKҨ"Z@ORn$-}=,ZhuT[[0ԮY[U8TD[b#=e펻W.[[HVaW ]ݰ8\U=u 8ѣul;%P+#U] 9N9]ͭe])׍C5m ݧ^0և\-т\C^%8s°A5ؗE-\^o! V#$͞ӂ0^ͥe^+mpbT -`斾 g;ee k`.OyeM 0߸[Tm]% 픭 \>T^o3s RFUM8a[` nӄ $ `y"=A=bb+~_5 NZ݂a6 ~ VcecKbQ@-]FYb gżXrfY0gLo.R8j.mftVGu^mgU\%4[Uȅ& `kVn͌6FWVZ6bފhbhBRh] |wa@^Z!TioN鞶AKLMUvi@`bfyK}19n).ꅠc.|W].UM.(䫦2i|kweCn6,8jlظ>i~c\:6akoj ~yNzljsV։Fli0lleUEmc-i6ܿ -mFԖ dߋi ;^=m%k.m4=rxvn~dgn^6`M?ھkPo7L8F?NW}oן@pnkɆJEW7^諭 p2z,NglöX  bkWU^Fixp )qpG62kzT"WW$>nKl0m)?vH\9oo0O1Ĉ>4e6q(khȀ' xL=8! BGCGt|bԫ4iU60?Xh)Rh!ns>gS5LuiVW(>F?r:51߭z%^fW[Vm!rO\uujφv]i' ?.tA u%S'w`OA5&TvO.XHgw{gTd"<5?Ͼp̽sGoxPO΢qYsNtzFƒy5  -'Ett~axhrcG 0ǚ }+~$ZxXy^jgsz:6@wL{L DXؼ Xz0sY) {{ou` xzAG| δY\gfY|P?ۮ_A{g}/ǧ&n|/2^7wp7"ou\}4& &.x p "Lp!Æ ;8$ q#G:1$ɈKL r*_" 0ṕF̍+^Lg)F"2`)ӦNB*u*ժVbͪu+׮^ +v,٥IϢE۶n+w.ݺvͫw/߾yMC D8pH},gi`bA9t渑@dΦKh lԴo>7o#in Zt[3ѲΟC.}:֯ke}Z޿/~ Ct!c39w6_}OElF$ Q 28PʆN5OhKv'+]y3X7uZ{=!d]ao6|CDMq'۔ 6dUnE pY6Vk0I.♧{٧s0%#Z)FY&LHj$|68 JRJz eAJiIiQZd mؑo 駯"&@T-=cLAdJ f Kv˙ ɉ FcSjNPjLr 3ܰUlR.[#Z„m}>p&*.fgn* ՛P' ',Ӫ1߬=ĤĽv#OC/JWcu]j( 4eʀ 2!L蚭dcFx6w wc JnB5ԏCXUm֗c~51p/y ߰ .7jk6`Gw!mЕ5}%=5C/uGQy`AKQ "*[=nۙޒT/. ȭ45-o2 @=M(+ F @Ǜ|߮ؑ` :63$ bi8!"1JNc'B1c^E>AcaP!o`{a5C(N 8 }ح3mAmkƏ(Ld?2ىhChetcϐ>0Pc8"7ˈ9ba'"QN$-kiK4eyM#!(#'2Q".M2ɈƵ%<|JJ܌;&) N͆cs{җI!19υ.@' Pj %yIN'maۖX m> 䜾yp)M(*3;ڑ$e ,cY32}=i^j 8$# S3 fRd6yN{mT u(mF)n$ՍIuQiXKJebL&tf5 /K戞[Hq7˝Ü/׈jF|CJ_0ʵ6X_u'SK<.QO&Vɨ-z_ߥ9Y#wJDw:W3#sHw!:u Kc`_\Ď2N.[]xh>:;C2Iy}۷%n|'sp$֕a5Q6qck|Ǫ.GȆu>=o?s}=&3NWE ԙdG\}WOA5з1DB(ItN!Z]I ^QZR@`N\F۔ FH"  ᖜ] *NiN<`2HjP^V" N N@ NTR`Ġ  GW R"R!Ԝ]m!d>z!õ,!zBń1b-F#>Eb}aDh\\bAazac'rƶ}+2122 k-rc=R..G/:/M#ܟ&#pQ13*_+Ma7 $"8vIKEȘ׃c:F54b 62<)SDc+Bh6`@dKNNAd!de`X0ƍ'G;D Z_ad NaZEI "J@ģ,-dU6 Ld{֩Qb=.E_ %E Y~ed n %$eP SI5euaY`J7fFW%7S4e%Q 3%(^JSFTUfj Vl}PCfBfdJ&i,[2Pƥ<9GJJ* !BD%Qft^aW^a`ljCQ nrdRZojpv=r6e儱Iĕ$ &J~ kVMmeW969Bcg}[XP m6c{~f F[?}J &hLv$!hDa4(}H}¨yJ DsrfHp'MrDnڎB@:){uOB.d(Ch$xmP&6fϑ>z]!nRЕf6=iHJ)"&gGh҆ZaBי_nQIXfh^i|$=gs駦!iodBltOrDƘ.6ꄢGI))֩vF*\cB*j*Zh!fH*r!gGg*f*jm*""N.V"wV\޵bkoQ2*fzVFg  +VkłΫ]]'jJiR:N*Ҫ Af'V4,+lٴ+tZlfuf.RiB\tEȌGޚlQbGeq(uRl~(/-IL*FȗrFl>~kMN†8,! zz" M.-m(jik:&-܎&(6Ff,ITվD>,.&nR6.%&+X-}hbhcmgzo6^mn %o}0~Jּ֮&Z o2bmK *".bnVn?}Oav jwƾRҚ~ݪ,O26: {MAp%ncȾ%ӝCJ0Tvmsn#cŜ8J !mo/QpO_<.Ȝ ^{1#qW B2F&ĴۦD 0d_0Oxn/UorY KXck:'OIÛƕxij>2$'KN"/ #i_* z1D.[2ֲ-3K 0|Cf/ks݊(KS2&B93#_f6J*} 8wSMs˦ss 0)333BB'sZ>l? $ 4cO tL,h)>2( OD **<3e=,4JTtHwuV-1QDGwLCCԺ3CnL4N^V'56GR)7Mbi+TK 'S 4‡*D²X; H DF'MOP[u&\.a1BбbQYZ5gF Jwo^_ߚdWOjDQlfkv\s6NCF曆_DŽe;E74 s5;*mvq+ndt8 ?#f nvq%tJ3ńnokDk:46`3Evɍ@0D{0KwŦz]2tJw'I7B6d+7 18h xZG 7i2qCxAiA8vHp6}4&4lw*8XP͊qx;Eto 1/nT['MT56Z"4u#ʁC8sNWa7}u5p냓wy_9' Mu @`zxBv~w.ă~y#:*N .3twi t;ey7-oxBPv[w_93F1ć>:ƺE~pu׍Ȅ8:9Bz#ĨSjKayvg{n;7mTǴp˹6}cSiĽλ?&|8cuo'u|@䲸4 ;S4uuvk5#;v/g\aSAܼ8xs/]7{O(|C9k|%wr|"gtz;7<@{IsD;B9jV{w{ї*}e4b ~B=7ϚSC:GmBTsUCH|RF}Gǔ?lZWÇGgk>\a}[d,&GK9G|#>쓶Wge?S,R&[Db](gAr0&;C~ N8PaB 6tPa)V8` 9vdcBhDD 8#&'npJN; hPC5ziRK6ujTSVz'O[wlXcɖ5{mZkٶu.\6Q͉'\ad_m"QrpӼ3 C,<⑃+_4Dfv}zfԫ1"$͚#2t0%~nNÉ7~yr˙7 |׸өW~{s oe[؅ $ͷiK2ݗg}~ڇR%No K@2"0%[z)<<EDK:T\],(Ʌ<-rHHn;!7/̖r2|ɉ$ 4MJ+4\6;_:.Q9rˁlG=Mț˰gmYj®;d=*QGMiF@5>6H@9d Q%LޜYV[+I>"/Hh#g\ķvS0]1/ꭿ^Msw{Q wn6$g7 UTxhLqYcW*EY}E=>^tWA iV[ݟFj .=P˒`wТސdr`L(BȔ rITX§ uú$X|3<BdL\}qaZ 3uC#w2ycPD?1,MoE<S,ڎhQFjc߸DnJOc>;8v$xy2Ǖ=B# iDA410XQj ؞] r~$CBɥT/LH)!L2PL)/RbF>0AZXe-[z'u*$GeMoA")IU"|5y&6M,i&EsbQU(KF9u{gNri]./"P "u~/p'{cDUfd9Q>U] Ti6)4$'=cG'D™qҴa}cNaT \)P+&$&j9SѕP`$Uv^VŪGcy Z Up.]ޤ0h#9K0(EH*+T2'lEdXVĈ-*H;W uNJq UN;uo]MqӚ Ŋmq[9HbEReh.w&k;JuufϢ`SЫ#hC43op8ыMhIAubt8!}y\Oש. C|+ո+pE_eR9Sc:qBq vn`- \-kկZlr52fHk֜itfK镧C[2D|Ea>M-Rm<^h4? lw2i_җY"!Mf +Yyz–*jNq5ec Y?5>=?Ma$X#vSW&l]N]q/UʬKoI{A\/Ѕ]t#!;g ~8&wznϚۼι~2G:GniRgrZ@cg>Ʉ]n跁wnOcLMXZ*d+HN :ܦM&N8H 譳CJJ>p[(65>PGBFP?;pVzzb00hlpp0CdFL/ "ol5O{ s0 d⮠cpP 03Pc!P CJNgdQۅ' ۬)o M/3PPX>џ o2Rq1VZQ^- 9N 뺊}#Q3# =QKP=}q]Ѽqy;;0p "p)!3%I4R%!C$Q{hr ɯ %13&6.i -q9= hVo# sm ͬ$UTr%%1%o2k(cQґ16*cR,?ḓ*Sꬨp)!)NrB*'la'`N*#xCABQW,/P-$#r(- ׎E²&FR/K3{/B*a Ӽ5 "5=.3L.4/'?0"3 7#Cn.12ݼ4sDV5q 6WC663c8ArFy2?P$;Z72::C3;;*ECɳ/) l՜<8'3'E@K+:Fa4AedA7hC!gdCgBr"󒂳=hvA2(Ѿ@>RGp 0E8V^Q ;Q;"I&H$n+>T? 2@˔tt jCDuߢ)PJ4 ;%Tx !rDN$|ts'/4?PH-H.O2PSu*u0PT06#tT/ jR;RW9%7BtkHtTmOU*X5:PuFFQ6%5B-u2#U800~=3R5O'TdU:_5S,:F5c6]xIȱM{uF1V TsY1 #J._S(@X``gQ獷|#S4cvdMSSC?Mgcd&ĉNv_Uje64´!2M"G3h`D0h3M9;v}:t>H󔢞fCMo_Vh6f9L!lmb4\uhnjqQn $*aHooKwVp+kEkF8f=-"Rre`lc~hVrVAjW4huIh@% ow?OtuS{V73Zw!"arYS1Q]14L:x$sGydvK_zzt3W!w"pK3:%@4q5 c;H}=vr;%izjEp*'"yƁ51|!bxD\&bȂ-C?yyn.˃UVGmw28!X!TL^lx'6I(v-Um@wVt8e؈kCblcb^#7]3In|x777n|oV 8 rfoQ0퉑 v&xVgcKPy}xFT@%hf"Yט+`aTvg@99\cmuJL wha$bzȖo_X#qoXBHu7i4=JS+=Y0Q9JOx!v+x|Goؔ9w?#l%a|V :s# {Sxvڙ\^qٹ塆SX9ǒO@YYS[V^Z0bz ΉkiIϦiIPxV93X@9HaJZuE &9Hv&#'yڢ}z aڞڬSNGn#rKڮ:/Z .q[NE 5wz!wdp:+BR@@.jI7;EڳB'@rM;$㣭8f'kd#YĀҘ$}۠;;joOJź'z=X {Z;b6 b*c5xG3{ɻAj#y@ > %#"``Bǁ\ȉ"aI¤=ܿ2醁 ;Um go"B/>+\ b'g"šA;b{|]sa`3HtP\<'`-Αz^> ^ ~=+"苾4bC܄Q>)MZTsum>{ 3:Ê><޻6K}_Bj>>p)!^шh^%/;2u7i6#d)EH2 d_w"&Um-2$>Aw ?#~-Kc$C^^⹾ܕ LxĄ*\ȰÇ#JLaŋ3^<0Ə?\@ +1˗aBB)rɳϟ@ JѣH*]ʴӧPJyU?iʵׯ`ÊKٳhӪ]{ի2㞈pݻx#zw 8rP儐}!"Nc.~prQRl12'ul@f 5}ҜJ۸sͻ7RdeKȓ+G6xM zC؆Cå)=utoVpo [/>&iOV5}oh& ν5rF(\$]e]t`9xб!>6L*2}vf-&bw،}وcJc.L6䓴5xՃViXwsnHWFRbm`'"dI];f^sN0Z~ tҘXt+ٗ0% 墌6裾IiYVjYn\yih^~ЈA”*KlBҫZ䣌zR.) &TIzF+ZJtEl6&aڒtmDD&g fn gu4(ے"ln>K 7<]ˡR 9hj+Ǘ"yٛ CV$@0Vm4&8_g1h$ä3G4_] `/t׭5A{|W[KMI"rUQ;MCw%` 76٭C7Mz- W^ nDIjxG9F#5C~<ŜU٭5j_[w._4x cQv,R;ϾS˥xA7ԁ S;Y]U)˜:@LfSԚUHmS`ɯ_*\"= HDh*|@[$ ?G6P!H80lY aްmLܡU6>PEx$dkb|(f33[wEe /0pj #/+!rs&738񓴣Mw*$B'%3DOR1[Cɲo J|Y(K*ȌUHLXfQ+'/Ȧ4*c:Ժ*"^$UhbWNVITE5RX2օt[i3#xTJ^JZ ?SWD/kJ Qˣ/e,D2{GBGB:0MQF[&ImWK[Q"i%ZJQ<-D&S߲!oaZDO{.U/mW%eD{2{g# ˗0s׉6[5`_r=0-lL@hU~p8a aFm4?-ꉥY`3jQooetrFh{z{ٮ=_IZ'ydFn(_zqbʹ82L襆ÿGsRU}v#9β3MR<3Ĕs|cAШ-E[|:[n Z1h5m|7+o[#U%Eߗ6C^{ҳEbs ٬?q Pon[sdmHaoP%'3gCG,fD慟6:qs4=\0ɶ}'}2--1t׭]?ke/`~;~rQwHNQ G~L-r%"Co+כH:O(dcd{ 1g|﵃^HO热d5dԄaq"Xt-yL}x7(c&."0(Va@FtZhU(=(r!A!?|(}u(xr9҇Og~v$EĈPsdI9}#ljt#a@7U(c2}y'WpXK8D/MˆtJWƸ{M˸wQ:[6g ؘsDe#x'hOXwB4!!25ȅY ȏ泍|э b!X?#ry{r3rи~7hב@ #yA ab8i%)‡1 7WA91D9;FHJy.8Q̈R  yIZ9 rqIFfy}wuaosI81Y3599p`{>xuhfwє$*.I0Y22ؙx6[~"pمٜ䚯)xh)#)u-YT$ǩX}w<~Gi4Im-7ZśNtzXwb뉚يYC!0)YإPH 8˹z:R*y),gi,Y(*:suw؋` tbZ,xT;I= ?:A+rEJ$Ԏ-%qN7Ը_J-acZxo rڝI:qOڢ |ړ~z:%5֡ {j&ʐ'hnf HtڪWJvY:)*A1j J!yMJ1*3c:R-qDVhx1 Ѭv7Znz z٭X*:Jh҆fd4|x[5 Kh}v*+.J*ї!zʞw!JQeJ4ڰ.{S0Z灱*Zx:YF[%:zбlزQ[r:cN8:+2zKjgK!i+k~8HV{Zpw IK#Ѹ++JjGz˵a~2ѳ;[y͉!kKnI:Vֺ˙-9b[țE;M|&7+l\j3xȨ˟,߼|*<zll̜w1{kq>}+lǢT;cЯM=wuL Ȝa{&}k}&SV,H5-7-9-q!P?*buw{k'-SN y UmՈY []_TcM d  &r-|< z\ׄzʪʤ; jmq,Jd ٦3٠],dUt][ڭ]ː"ͳ˾9BgӾ|F$G ͪ2 Am!к=y_ ].>]΍p9x--Ѭ-N+ݥ~4-Ĵ'i}Q]:$^) ~#''YVb$x@;K-p؍CNx"6^ ,E&kM:.en!Τtʌwڐ^-ٳroBlIdaǻ} 뮷.ޟʨMo_w$*aɧ{HY 7.7׎z߂Q h^.~5 !7 ~y2Ъb(`()QSm Z nv>/?޿B,:nq , iM )_!h]I݈]B '^)ToYJ@/B_uNFiJJ1r?zRwOn{#8A|0N|UTU^ŚUV]~VXKE?mݾW\uśW^}H(W FxP6p9 ŕtY0 ,N8gFAѫk~ybfi׵fz 옳m'6@4fpݚh`e?]tխ_\~^xzo?:aaտ_FȒ)'jZ,1t4Ì t7hcp5ZBA|%ͧ \,;OD1EWdD<gF: ʽ k[P"GK4 DJ (60)`? p'i*E7߄3N9tŴb1O=Ѱ2A rH"qaP3LMQtTCŬrH)6 R& 1Gԡ3]>HQjNW_5VY-<5W]s@+u }`9eJ]ٝ: @UpӅu!PU˶m JS1+WkMjuVw߅7^yͪ5[w7_}u!b'2 -Xu>۔3&[pMe 4cN̅UDE9eWv^9fU;wDLj$XgDXfa۬33Yo/L{z'kMe&l\~yf׆fn)&ȱ̚肖b> b&V1xFuN㾮]/^?F&gmةNiu$j-uk|w!Ls#"5gy(CFAq D੓ϸ{5tJ_e(PZLH^p @E;لd[Z8C+^u÷`- LK { >( bd?s׻&Q "ŽkPZBgC28a("H&jlq0N0›Tъ .GD^#BhFJVyh\c&wƤ$qTcr@DЂyԣ! GdtR1S&]PKLҒD&0IfZHI@နR)QGR[ET "ѥ HHX&ALz3^lf>?hOP%`;̊祼YpRqBuLeJ"E%T gHEJ'|Ӥ2Qّi MiPyQ]jJTAyݢFeOJzR+SX)GZq26Uv, T[# wWhQUIEdlYWhU,Սl`%sY-6C%H1Ɔ3,ة/;Y_UZ5` _hH ʫeBF%gF!";KeSֺNr[H^3y2!L jk#]! TK-gR/Lanvnk v̡p[2h.PW~)wp}sT6l q;τnYeݡdz4~'Ј)kƸŃd֕G4%mWcTWgf-}fk:($6qJ)(Gi5_<bRWMʸ ;pG8]I6 bajW@~L?}OhA7%/d=p6-.!o}š0ts\@yЅ>tGGzҕ Ozԥ?\=$Bz&zzƻ͈6%Q4) l7ARn%\NyBG|!x7|%?yWw5S4Bf{>Z.H \L;_Y}y޷ z|A4gW~}w3ySz6$Q=vzŝ~5n p3C7@K <@>;; db>c> $4$c>K 0* #?X["#  s܋ 3 0@ B3¡10d1C 04T5d6t7897<3d\C$,,AӰF԰DGtDFtD|RC *&BC9("TԽw9-.B1E\$CE\4`a$b4cDdTedf_é^|F?$(m4ā@D0XDS=JDGAgۉV $w $=&ĈQT}G(dE0Z4Ȳ!1 ]d\H1ȊȋȌȍȎȏɐHƨHIl om,pqTTGsɛud%DUG@;(BǥGJ. 8ȫ$ȅ\ɓɰ˱$˲4˯,I0HXIM(<(˽˾˿̿,H$Ѯ0T  @ƔɤʴL|̴|:l̔ddɝpImFsׄؔ٤|,t/MM0DTdt?@A%B;e`שQUU!M0W4XW}50L3uV֢5ڣEڤUZch$fAWؔ5YIJ0ڐ#W)U/M7ME[Y¡ۼ۽۾ۿ%5E5\M֪"-YS=[YY`[U/E͍[CRYI28Prׅؕ٥ڵymR}/WV-*YR%]o Mݲ\! ^7ҙRԑ%U7]N xUU%^q ([3_!%/VfV)UJRe1 R VY-_5*UF/ .B!!(\+^  !&_^"a8Ȩ'(n"*+,Κ#F┑" .H263]-V5f6v7 .yǍ<4<㷁>?@^c9x̑DV<FvGHMB.w9dZL'NOPfJYH0@MVUV`QvWXTR \e'f^e۝`a&bReXq<^fvghijklmd#cn&r6sFtVufvvwnfo~[ qcx|}~h{Vfv臆舆Neiץ抐6FVfVeq陦隶Fi&ꢎF0fv꧆٤Fjvh&6^n!,Z22BCM$ KLW,,8((4CDN..:33?ablH*\p#JH+j;I#Ȍ$S,hʗ*[I̙5sJSτ<I O]zK6@@Ԣ- U& L%j[`80aY>H`^=@Q,`ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνÐOӫ_Ͼ˟OϿ(h& 6F(Vh`[Ҧa l0"l%bk+ȢA.3V#/ xZriA84~X8$#:SiZ@!,K 22>?I# GHS&&2))5곴++700,Paطiͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)0&0H&I B dGNDE)mpeqIWb99@gn9Е&\pec D@z0@hZ$e \ @qT$<%"I5BQNّId@!,o22    곴0 `0a:D1bÉhƋ5RGE2 90HPhd2g4@ l$@gΊ8`OI @\0ѨD))U@_̚@Zj, ZvZ+ ߜ~:;3Xw1!,hN22# >?I  GHS))5곴H@*x‡:L8C 8`Q!ƌcA#;xP$W3CIfę-k Зz,K =6IU,:@N/$@lågT` ~:Ĩm X(1]*X7a_t,@.` rpϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνÞOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,IQZWF6tN8 aA\U EW5x$Lĥ_ !,g 22# >?I GHS &&2))5곴  >I  80A*,( @Å: 1ć^B(` G$b@Ɂ'QR˒1hp͛ t9w ˘)A8MNKiR;@ȒNP6#Ap[pk҅+7ޝ}fdK8 ]<81z;>81劅KXf G!,^22>>I  80A*$(@Å#JHD% P !F&"qGKp0@B,C8m9$Ƃ-)〟 Xp遐8pԥEZTKL<@ٳhͺj6,S!.,;t&nnmmnnoottvvvwwwvwuxk `S>#0*/+,+++++++++**((''$$qhfghn v $$**1144::AAGGNNKKEE??;;8855222222222222222222212121~~~ ~ ~ | z y x x x x x w r n m m m l i]&S5A4/.))''''&'&'&'$%##)$9&H$Q!VUP OOPN G ,zj;    $=FN SNGB*69+";$'6"(3")/$*+')********************000===???????@@?@@?@@@@@@AA6JV!PiLpKrHv CzM|b|tspjhghlppppkhmtvvvvvvvvvv w)}%z,xr~~Я]HdǐB"KQ TEƍ3ɓ(S\ɲ˗0cʜI͛8sɳϟ@ Jѣ6:l"E.f}|*U#UO]4Wh1lA`6 ,+ ܮ]z  'WVf D+8E^L6$AF>C` `.$59'}A *V+հ*utbEIzԨ[nug%@)3v+g)#(3O ^` xP慊N䎑 >ئQ8eRm0:hQ j@ɔ"AiZxs3ze :a l٨楩F)M,֚^BR7fdYh4eIPEf$-ڬBeS|5h ,GKn㖸(^D+ZgDl(c{"=^}U$BMq^ J./?,Uɫ wD:Ň% zNpkFe.$@:w/.3¨ Fܿ`\cMmt|wMYUS|VjGy fugls_^ݡXW^V&1Y9*ӹ;yM6}.cE`l=ȚNئ* @[QEQxJsvx+ߞ-WoQ[;}s\߰ƤɄ"kVT>ֱo r3/Rqr/A(- ~kUiNӻZֲ,'WC.h j瓓ٶ60P#4K rBGOzZ EDx!8=1^va"PۡmNZLņ%!QXBqFW "E,davw`qڔFZdx9ұ4C Aw#fJF^Hu'[]%[:&l$o7.&FA cnVJiAz"qKE5_B%6^H ylg?J)d ai `܉9˧jT+o#>aVWA*@&:yr9CZ-|@D&JiP&]-5XPcMgr! K?$.Ydf9W}SIO꒔(,&ԶBFL!s4qV4 摡O`6s@k!'$ԳpU-;q(^JgeOS F4tڴ+X#\)WEuRZBZT"K T%aCŶ]1JcQٞLH,xOeNô M۪hq@R2KnY['n†e pR$ -k x.ν}IdΔٝvD?OUơ}z$ww0C$z1+;S +2WY&<W=FkJY2Quq \W@!qLRNt-2Ә(u6լ]&S}CK82{Tb4G;dC9 )qiŴqzQ_ ;mj=k4^wz>y&mcγ(YV}{"P25IfFԎnJL2͕&s~b tWyI0{az;iִ/5\G0w95[_)0h=V.&[%CNhZ]dhh&7M6Lowץ5 vkK{kD|0L%]oYX=+^p`z{FnppC̺5ݿlEƞxg9q[rGgq=LC\G09'™pZK.qxљ֔0ypϡq-o{:_f|vf;8!bknv: y,C\ϻWyv'DdS_Y⥸=F^򎥼-snX'h@~{LrHw;s˗LJu8Y#]_pfPG51Rg~X2YWQ6o Bt7tX0`w_y؄{en%IJ(J"]CCdHwg88(5Ln&p'pXX8bJx7'Vׂ~H<;ZXWj%dg(}WoP؆wx$ERHvuxPP q(:uY}g*W@ewpӈhB g֑IGkHDhBJ֏*~giX;LؐՍR(&9O혂+z*]Dx #YuňHђ(YX1#G y| vȷiaH*khQ*Yǝ1{7` Zp0&~F"*$&zr])ꔮ3ä]i3)0]=m A:gٛ H/$7^ZO8!JGR 6tUJZY*zaA풧sPaメ6FsX\mKmKhN}lj*M)G^i?jaraGRZ[VtDijf)JO2ms{5}9zA-OSƱUY'u *hg*X&06d|zVFI:Oh3Rg=JPb ˰R1MyK63j֘Xgevo[G(ba(԰{z"/j0K +G e$EH*Jg氮j+jɔ ó@%j0UG&I;+ִ"bzM Wӗ0bڤiŶ3*ʱ1t;_vx+Lz|_~|;2_+;e˚ '!ﵹչiK:W;eZ˺9~C[;b(犹:LXK˛ *wj_5:7.a[溺EۢI2ObZ!A@L1K0!+ l !GTE/P/K"]2[I9KGڗÊa M";G=LP@.`GzLO̼ #M,c֡8^&<˥l[lKyÌTdǬn,}ƅhi%aNR"~a, w3HM\bxy~ t^a]*=,9 -;<;oW4 \~ݖT 0a c*fMѐ p ٗJ-έ{<%m\5U^V~x6]9m>mKj}駬n-ɠ@Z|>ώ ل"36ݱW|SIKwpF$nm!Ҝⷝؐ}yN6>!^~]'S.*o;nK$5{ d Q@[4?> MC៌>Ll$,Ϟ@ug;~=M%T㘺;..GQ_ >ح& Ϳr8=Z,/wBi.L{1\o^`o7!zi: n&"s*?k2Q?ߛ[Zujp>)>AE6? Oe{&ɝNߜ?]҃mҟ .>-gӞӷ/ɿWuoXOůɯ>`d/9/Ŋ5Un@CB >\ 4 JhF<M$`M|1J-S#Ldތ14f"wP.=ڌiE҂䇒UJ\iUֈ.lrE ~Dq˖2ejrEOܿ!&TĢ]h,1g=v iafeE:lW(gn2m) j~ qMXif(.nց\@pY2ot?߇H0b5 =d 'tu?G;IB0ii)/ f֪ d h ljҷj, Q=sďx16423p_vŸ6@ h7(? ˱z-˷26XɁBY0}R."k 3mlhu0qt 85s:SތͻcSYASxl#.@?'m-vbzڧoTD(uE;L6 RY4]5fO+=5em8n:*jߪjn6kKMkr=Yl ?R E{qi<1E,fDO^5_V5OD-n)-p/]cO9fcwAk-̅wף 67)^ӇE\d=7yKyW3Ɇ' *xsS~[2 R㙯fzD:X>3v24u/?jI~>o|Sr|\ b䏅q៘1ɑy,!u@a d`.>s _TC,eAQ9f71wI8e/$ Îpy5ܚdIft"HG!t;\g+HO;A+.>³B1bld!ScP(n.S֒ ufc8Bofٙ SI>^/5.Vx o!C.{餀zBQpVF'(RZeLx>Lxe1p|$9}ØA-އx[lVj#*-X t Hhj}$ ~""%-I|#)OhgFfjdkT4&G‰yO"Y #[,3TEFٕ߱f,%|x(&$6k$R#g9覥UqDWԧB#R-DCkӘx$RMθu`UMJp6̤i8f!Se lv,XP"9HEZg0\Mo">?.α0{3k{=kXb>žjqkl V%E-Y^0< jUۖznW qPsP6Lb}{Hw(6uŗ)÷l{“*eJ7?zq}-ivT!ob|)On$Mq&X,#|"VۖKSfR=eD7vwӟn.}:S>_ ߺ 赹^]`C㗧s%Q@٪z;Di&B}5WZK]h]eoS+:-)5^hSo'!D0~?hļ^Vg{6i^ʚ|X+Oo0@'+HIȞҾ#7v+ 4?EБÿS s2ZAӵ- 뮫a13L,#4z%d= 䲽AsRA:$r'K K 042|+ 8ĒJcC"\;$=d'D(L=B 1 >+ēJA$D5ND,IgĻ"BS<U\ LnF&,&XD5!i#n *]eP+nåd,a3C0CCKF˻jƂCvÆL>L?3úËS[ RZE`ɳGC<ٱcI!=Q¦CȄ;m,?VNjB;'[4&G.\.` [ D5R+0t h$Şɾ$KtHnȢã*8G?LDUZBt*i%}~\@vZi 9La* @J#ʉdEqE0KGC,LD8_tQaQJS|K!,_lʎʁ[#Zcɞ JT D(ÅNHJйKm(#BnCsax ȴ:_ 3"Pi ^=E"هS&yUa?c#>VayS-=dE慬Ȝƛa?la S`23Fޢ]">-O2e5YRFghE>lfZ6kt~Ze i:3kk0j֘@j,KaȖgh)lWi%$5&편&FՎn@h~2 .)[un+V _fp&Bi{囋H. N/vmo>/svtc$*Vy.Th2o(1o`_* lveVqUi /o)vx2Xp 0t:@2KqTFjN撆F/.'=H! _oNq^+gF !.eс r +erwF+r /r#?YBUyf)97R$t/oduDv>Y3ަ.+)'77Ld =hRtt)Ud&$˶~ Z/'J)KTE lɋxC-v?Ʀ1Bsh`]>.2~`1QZop'д C>wRb0d8W?s}Ì/cq(&S"РEwOZupwf_v0v'$wafv͌էC Nksv(g $6=,ry9yEO.x6$- ""'y8vI +`LgzPsx` E@qfYe؟ġW~)uS[z)vTK.}嫁(*B|i< ⹅uxċ mW.ѤJ+^,̦N${olC% hrE\qVeט}y7Y$T0A O!:P?vjKٶ^1VcV`qT5@F7ha`$ EBYHFMV5yudhVRfu8bdVgܚٝ5EjkKEY`T6h$qсS ^N; PDA#rhf1HjIIӝc:%:cfGwKfbz᫨jꪲlq*Y8y?~ñ߯Q(IX~ i ёN)W-Dv*(VZK҅.["/j \͋۔.:2~˯2K.(-0$iتpͽ|srYppAQ*4}'uؑU]8b%;t2l){mjݨRzv;]2/KkZO`k;O,,n"Tob3_AԒ ]s;DNe"-[aId"Ŭir< rD!vybFX$1]+lUqN XBn*c"&Lg#; NCGCB%? 1M٢]ضG0}H)|(6ҕ4,EutNNaG('[ϑ{"5N rMRk>i7CSBehSTqԢ QAmaZ*ԇⲜUi H/}AN^.PU.kUdO,JRi*(Ujv)TZƱ5d:I[":<[\ogC^hȨK`U]U6&rm-kP2ޒ›P9cM(,v"[Yb/[uZַfڔq"ä|E[D+;rnpʊ%Յuedy/7أqdc h|YX,?'o3d׿W,,wsXVhUML6Ȗ+ʰGG6j\U}dó͂ tp1Qs߀8Rֳ7[Hrfіe0bՎQ k[_ŶTPN;#[_upxvrH?1&Iɖ(i3g')6U%rlzw:M0nR bŜ,\xִFMf[ItwXkb"VvyPV~g\:Ft Zlnd̳|}wd݄LvN/5V|S~]m4f{.G242Dzݍ~NDY:$-RHk'_8zش荧v5{/tPTv}͘*=Ҽ\_AH(x^HˠqY kl_u-WT9 A!_6I`1w9Am]j ҅ӝTJ]F@!5\L^>y}{J a}@XTFuGR 6ELX`mQ^LN^E _a WeӹeEP%E"ɕa=ǝ^2]PC!""$P\g-"^ 䉠y d/~ 1BU(1׹"ǝ!5 a.XYlH8]Ȑc9EEV? c+6=<6%A/&BxA!1ƠI`CJW@,e@mdYHF[5 BF\LMDV E"֟udq|dH aS$~&\Xe$hmxi̹نf.6}lj) f(p .N!\%Nvi`sf#Z&u&8V( rh> oR]'l*Jh!F>jsec^Qx"a(($D3(dh(ΨXi}aV'ltN}͇萪Fzj%Zr⣔NG?҉m"Ҥ'qi?qJ N̡ĊJωvq4Fxi{gA@! .D( *fh**꽪.i-`i]j ꕦ৔HjYH겜j$*-jh6j<*k*]T)ejw1U"kZkkqR+6*S*P*NgM ƈnethl~ЖPD28$aBDJ,h.Iʞ2UΓA&zȬ D-,lM:RHnXIοlȊ+\!Ӛ\\*Nm\-֜ BPz-ʁbN+jO k^鞽:-2jڕTb. 2xg(RY:zA b`gntp~ɟPö.7߂&F.'nqFkAZl% *ErKj45HA1LBDP +,p"ʮj]+dz/j"ҿQfi!Fz#H=nCB$"<0`$tm3p&pO.*bjc.*rpImAvTBڅ6[bmn o + nGRt9K71! Vknw #D +,t#7&n1+yIt+} %zmC-knDn$,4,koX2a,N5wW-O1rajHmGhnc)2@,Y%rnrk A%%꬯}򮽯(:14K o2pRXs2=7osR&q<慠󷩬jrP<s-2jv{?22Cq_8ӭkxeC +(2S]ޘ232ؾBF{Vs-7@c ]gA땎KeL3;3v8MY/BEI ,.r #O?h5KUt7';Y\tJ[(m[SKPt4F>5Z=[NAsāv,uΰ^5UWD?3VV?GW$uΎu6OkGu0@𾵞jI cf D_k_񺕐 q4zRwk5lGJׇ9_)Go^gcp7(w %,ØbkDjf@4Am6Rtwvwޔ7zPwYb/tC (vuBvuoU 7N@튁@ +nj7{?k77zRwESf;n i=5Ǹ |W1OxgUԱ"Lvvs6"*s6Kw{xiJIpSEd9}m c50+rg`[K7lKA fd0g빉l 2E¡'ŵ8 !t?=95dD<9mSG2#9vh2qz#+8ÉGc{Iȍ P,y<;t̳x-+2^,t?:6zV9Ivoz.M3*S7C:7oH3{I`n(m;.q;g;w|oQsF;|3#6ŧ7KƋPrt[6-|{%*{Myou!yߴ˪Í@W:ߓx]&IwC%^~#>m{i1'N7O3g7 @@@@EA&Tpa FlB@ز%DAFt*dI'Qpa SƔ9bņ$i t(9QhQGQSGvO]@ U 4\]X:ł8,6EDƝgًXaQ6/ѸE#GHKɗRf.f+P]Et)SPWg6հAqӽÅ%pxk/t‹ASe-:ܸENq.:{,qH5,I j=?_fFu k_0Anl/v[2p,sЮ d(h#NB;S+Jѳ@ﵧ/ p®,6DP/`R"R' "r.ꢛ*On +]+Un2aLsL-7?*!1,hQI>ko AFKREn,`2:ܤI3ф2)U3ӢL;F#V(l4]s0d=-]ӿ s>l8EU[μ;%ӵ\zeWMrw'C o]_e5" NEIͶL ڨ5W6Kw۩'\s4~wys V{-тH~ߖ7 x@\Ze+JQl#bvb7NUb\ݧidP^a9}';̞H/ Sź!6.ine>wZ=9Nվ^9\lg<HRX~3.ނD9KUr''o-Opz36uluK=/bv{$>o7.8ߐ$u!6 l'?_uAyzE8hd"W5:v 4)fI 42Dq[ WBL&Q݀Z{ G Dx)ˇi4 ("rFtAq2PT#7›AQ!&Ţ-1c#p(32:-=%hrKXGR(‘F:%Aiy3=qvxVbkC9wJKJu.=t{bnw떶?ֵ`\[R:Q3_m^Жp(LYM.oN=\FɑZ ܅ xHqN!H3 05"fwۄfW%|)VܴN_5c՘7.Vy!p]LXxs "a:» 4fY}Sl2 e':Yζ*1[ @D Jd$8` nh*)7S鐋#wN%&?-2AMc1Fr,@,s͒*YڢFAJ>%qnKػx0\%Wx֘;&6XU%tdyuޑ^P54TNdn[xէ.VF*y) ކll'.vc46'Z|0AX^_{j>Y( 2 Tg7riߌJ5O/Bo{k*)o:I\ #s&m*RCn=!پ20 |e#%S-oֈZ\-o6 CN@? Խ Xk ڀҺi⾣6!rP0^6:9yN{B=rzc\C{6}ՠ/%O}X"w멝;z= ;n*FZ.|ߖ؈o+@/eO&k>F'qⰯ/}- Љ? Џ f<#ol.>vJ/%x,eZY-MUIl/F6لSh#Adz/0{'& f$ e0Vf륂O 3dPJPw8oDP40(CU_ N CH4FxpXD7oø(~Ptb$P0djX1.ĄN{>c*u"8|OFWc#m porP "Rnc +M `/M౤C %D]Tq+H M j74 Aб[ "#R)"J)>ijܚ $j_d&$Q a cK&1]nSe .(*'%BgDC)G͢+)q|O q@E+rX!J'w2,ђ!Բ(e- cJ-] g/ /%0Ipҧб2130r|4RPƐY(])u-s I%m/S*ž3oN44Ox9r ^(apl2713*Sbf8Ou=ĒbRS:W"R1>΀0Ssq.ZX29!J 3-b' Lϔ6E6$7m7Tn2 To7^L5'*Oؒ;@D4~DH1P0Ep=ÆԗTRG?nqCC! .g?#2QDI%1`JJ#M9AFQLr1@3y^3C MIQM&))=%4Iю; =OA[7~CP9A UL="aP uEC<-P.@tj.Z0DdEJS5id4F$VӲQ눣6ӴWW_zuh~gNzLZt44i%XU\5ӥ5(Q볨BD (WERRTT].4K`2COO+U9&RVGRa/#WnW3MC223Sū T ^if R^MVN_qee#u?Qb/uM+62foF߰:iOE#ʏ 0qV15?&.aVgDfrV9"CY aX\!P9#x#c3yyy+uo ~wioW@x6xB㖁GsS\y}`d~zk+ui. 7 KәVj|Ky9چoWYW~O?%ZkqR4 Xk:oΟy.W$Y!ٞ BCFK^'1ꩥ|xKxȶ:s#םu;#b:Z\'5irz|0Mq%;AydiCS{-z9}U$Z:Glv͙{!zŰ;{z&I;ua!{uQ=ز!W(ș;K(gȷL;3P{̂ W[#1ZZ7ocYr-KD7'ۗ"-g M{FuuG ?ێϛ^Ku+} \;Ñ)«;ۘg0;z*ċSO9fO\O\[7LSː{x'|q2I!oNu R\'HsABo5Tƒu+mSS'v9rO7̅Yw<җܗ0]Y9)Ƒ{!3#TҮܳ=덑|րXNNC @#e^{%;\H;.".ی񦻫ǡe=!=n=o9 "fAzp7й6. /l<{ڻ,ە&_9iq](ڛܣ<#qxk7>jC;/ٕ(z ۦo֕fd +]f}UZ 4zN=;bg]+_Iȴ k$~iޤksٗ գ(v1 f;NwD>Vj\,l~Y}bkс0pi{<+1ia>s(uy>~&/^baa$ 7;?'5ּ,y0vK8{O;^&!['ߋv"dsYIÃFf"SZ?ə#_5B <0@)|@k+Z`. \ؐP!K/ݸ(4`{NjvO֯+hn!e[7_N Wf1DMAt%tiZꡁ4G V*`1dy>J^Ubi~鲂}P 6`pz'guqBabէhlAҪb!5)uVR:.[F Ie RtXTS ;kQѼ#rn/btHV}۵f[;<.&vu뺈*M,Q g(oE"ΜP-ktN]c]':q4Lo6jêLXP$4(ԐH.'ҩvzj`3MmҋE9!ɗ9Rcs@I]'3wim$+P34[B?Qٵ*2C68LFTU;nuQX4euVΆ-[% ]T0,-Bđ{LWY QP0#wuJ4Qz^P(j ?@B*J!U(\ 97S ֓ ujޡppg&#QSHAR6fssیQ,QBB񞞪i'm0*F.;|TF b'xB[FYsndXai4ՈS)qJQVƾ ƼhNsA f;5Uykdvwʃvn}8.K(.^v!-iFߛ) ~xiemW\ o \[փelf^{..ᚐq{#E lSigdWs!A*YjDPDv3u]M]]?K 6z>K~xoXې?;=џ^o0қsS-4uoQ{hjjd'7v3G|~Ak3 qq2t'vDq#7}lqFW}mPX|&F}3a^ᡀf,^${$gHhyh|b_?_!,#Zg}'(}LzxA}R[t!u݂{Bx~=CD^CȆGO.8dQ0|vG1`irtPlgZT^$7ATux P{`1d_W6[׉RuIh\ af3ShcfqwH}`؅`X#5{teh: ?&Sh'?hV0C7Wci-؈+T8va8Cx~'jȉ1jp +!r" kQct[wḤQ1IEX'hx'ŏDppoCGaƋȅ,x09j6kc1IAoHbvdԁi oX7x]gz2B6FAaAP(mI)~_X1 "hG$`F7^XS2qwg3t>H=hx8AIeő >ɨҀၗy+9-YS)ixq_qŃ&&&%ǓzPwKȑr9r(wٗj'('bx` QOT 1 5 &YW:9eiڇoNLCp 9tB9fg+ ]; d (Al9!4DZⲀiN2ՏCsYb !3R)C(G;A(ʃ, 1VJl3z2 Yգ:xG?91IJExx|R=ٜ?{%sVgYz\K*N_z&)jiCizxĦ[d4v2) p*ѡъ|*ՉgJO>֡_[(G5E)czb6x*92E*jZ t\z8tdE)Y:JvaƩ uHj;| ĬG!i?ؤMА`ȭ,%VCvz}zh [g5pU땧Ț}2.I"iVjBB9YaY kr׎aU*@RYgOI5s~_v$;se?AJrFg92Ku +CVAóL9Q9Qv{tK2f'*,*v@ o%|u?ۢPZZjirK$cizfIַktIc]UrS#giۉCKE_p Xnu1&+Dӹ~:J$NĨVDekQ«iVVTwۼ@븪ͤ~X9A@cEK᫦;KRuf++2;+f;ak+]̻ƽF9{"L'5[:U"VÔGR ȡ>8bZAKj lPڲeZ+M처*gk"֍8wT̶8M`ztL¾ SL#A F5NARǟiXC}\e|l>!sʔk`gi]4ThO$;mxJL̗|\^ܥ\c\öE rrˡ˕xu·$J͞X 3cBgX1θ;{֧qCxDv|wΟ \ϡ;UǃP_TrL|Ϙ|a!h,LĜ1ڻq#̹L',=\gm =A=m=\l̅ҶY<|8}y| 8!xIGѯ˛S=]ji}:tjrTp }:g b6e ~`cn&]ÐۻM-}F|&^4 pDƝE Vns: >lr햽`QM-i+.ǚ.,D.j~E`nMBpKVnQ:ힾE>%uД{ jګOʼNgν6=_dˋt ?\㸩L信ŵO596ro)}>T#O:n`(FcQ5BH19bw?סX1oQΡ>*ڴTYv=Mpؠe݆lpkYЩQqp۸1kVڱKM]ޙ3:[zK]{u"l$|Z3v Wa ;@|ȸ\ CL8츎~&4 3g  @BTхV㪵oo$+(+0*+nqB +,码 sې$2) 24X 5ʏltPLtm 8R)g믊<.!#̬C %2ɾ:dNPʰ|ҢND҇Ȅ="Y5O?Iڼ.PcN0 k79Q b'.X-u(mh 04LgE!P%ECsB5[cn-K !K9 ȶnQłfז[릉ssuNxfoo/9cju#|3᠀H2Q@bQ%dު9 V̡Wzv)84wcr.x ")m.\7(HJry q7YO,T@l[Vx'`qȬvS+~ @Ђ]K{"x 9UZ#֦R"'HPTrɩ%Mm12 %tk2\λ@n@qK#zei,_UH3c (٦;asW?A%dj\b0z 螚,3\*їdJ)qYLlZP!(- i4G@i>F+:,%m5ҁJ$-GY^TfH14a~ya+i]|EUP~($&ɥ9pBٮ8tY΢@ c,5Ȣ`p*%Mx _S5ezљy8cčpvT< >'ԉ3g C})S@ :ӉȊzЦHyvmӫp >IgrTW%Dǩ-yRXlVMRUt`kQ5ѓaXt#]QT^L\>)ȫ*4+ [HʔyHh@-;uRWu]1BI)S݉>`Zu!֪q!+ZqNl&z2i Ԝ i 1P:ˡFɌ0V˯N*;3Dlb\i.-ZFٯt~X/K Vϳx,Yf3e_67r]7 ᵰg0\ o!,K#OpBp,&EGRvWH ;O@pCQ:~V0%qgI'aflNfu*TN~0R#L`J+4lXvwp%291NvX j)9_lS^l-qƄ.킛KaSW7~5]aNud; eJ9-75>hG5ۉ̬Ⱦi\mlvzd@-?`Q\Sɡ% .{Yanf H"IlmVt]gahZ4iwj0k'.΂F/ȎʱAȯ>|ɺV˾6?‘==;DT5}tNG-(лRa_6mh#oB/E~2w)&41/%pq:5yLھ H5z#3n=˽5⳸4:Is c;˭飾S:@K,k{c@#|8=sX03*A(#,?8A/R@iAsI)sXӲl :ۡp exY 3)*\8,5;B$쳱a,4|%54.#[D;t09?T; D[V\ũ>h:I=;'BC6L7:N1PCC ?)D+XU3&@04F|_dD8n apYp<ÊC;D,G\`TG ֹ@TFO {LJ c[nƸ3D.{,D[@v`A"DXA G`WrƒlT>ۚSaɷs=JsAD@(;H HX̝Qj8Đd#ɦ $ap lܨ„JpKÛ4rC6YKVDCJAx˺ 8\7㼗\\HV;Lң!iLqǴ. .yt1^4deLL8JLq.6TEK$t tN\#J{(L*#jN|)ZoDsl@ Kq3[9d?!L+m|nd(E4O = K| P̔ԔCP,Ϧ|x˼[O;K޲v*YN3P,I+VYDu%\Q{=j/ Qݠ/J,:lRnkOK$=Gͳ4:qV5!I)wPtPRljB7tMDXEgsuu};*KH|ѓ.7_!r>2'SGd?e7fgrsv90V'kCruv]m'b/cGVvUgvv*q _|vt.t8cftA(:qOfq(fY4uup7n-xv@A&4vGܔjyTr$yћ番 lwvuH3?(6HYzՕ3:qd\w*z}H&_ Fq?K's8$ ?4'>u{j튯y&|(|G/'ػu'Wc>6iI$YIpŗL0/t'ud?{ ,/ âնQk6o]3@6Vjq̽Ct^!e_Yu`w$hHGj|q{n %Vj8>FY8ՒOwPTڶVru֜qއ{ tmفua\VX'dWtB du}~A9%D6waKۦ qFɚ׭focN&l+452/kF70Q*1V->7헢5fCe |I#qJwٻy3Y[3X l{, vq9=UҖG&1 -ru}W<β9Q|vg=F.Koq*+u)~5|:pqh۝>^:N Ҟ|]FbC9~Fc/q_;l@>ǥff pJ'T6{#bEᑘK;t`'@ v@hOo滠V"@-w_e*EA+.c'+uĎKv 4> v':o@éc[5FRN.1)aT*P;\S!nD1)qf?Onq&C֬8l;\2.Q! P(i3X=‡HQy6)udOWY,^a#ؙ?mL-|]m0Z["7(}W[ldqؑ!5zDs&%SR8,7xY^BN,Z13r͹ ^1BtQ)(39qt0C' e(R53lM|h̸1[(?.O#GwsABnD9$v֝f"n¤c@6.K8?slīZ5zN&]L%[,#GvU -9v4!-a\3f/9$dnbz]3w|Ec$t\)s}BRף7dyc#*s'vvBx`)UM[cvySp‚_ޘX@;6mUz#rB-~qs@P,@.낟2 Epd-b>s{L׎M=gO m<>v|$,yq^!// ]kHaJiBfUg)DH{#Y@?I 1W^w̽YpNQOYvߺH fTpE48֪^A(aE_o 9$id i` ULqJ%  Al` nG9AQ E=\zDN rJʈ=iDC,REU vPD$u2|v]مQᚱRݷ $&ٕIJf != oFDB ^P| AC)BΉ5]ԝnRVe`)Q^%V̔&2'>' 5W+~& -bވiY.^c0 DC Z%BB &C )g%bb`^8ʜIHl-SҭSnuzm},bf~aJVjlBѧ>˺%̂~(Y6ɪ AvMʍ,Pmk*:BdI-eR-~Z~bfe_]qo4 Uj+y&%r>ƪVɐn/ .moѿn*{nfb(VNn0N,:Boh`LzhB|0W#*"(۸/.p԰ooJB0Q #s n-wnpPҘ-*2ޅb۶K0ve+vM왶z0~o ZkS #10 D*ӰR^/'E;q.m10Àؾ/Q͊2t%1,q81̱Y0pw9}2r&=]sn+ŝJ,s,$#k%#%cV,'sJ'*s0IP4.HRXbjsͣ9u28m.3Ooԥrk3.,0FJps}2(09TAps_bhܞk\kE1:&FjE{9 A4*B,<'B\Rݭ@ˢ?tuG-P{pIu.um6LCJPNm;f50d H(u\5O0#/I3P=;=l>COO`Q]WVkr u_:+GTZb[cϮc׬ nLVUfu mwHCi26E Yb jj/k.dSFisYlrSf^:apI,CaiuDGDGq[0uItc(fg6@uA3 tsoG)hkxw7r5?kmU |{}vB6gsXgJJ"4ly[Z{O1iƷlϷ6Y8U1!7"$hxx%-#wmrHxBHe8_7@`&ow8!ESe&v+/y}ݸǖ04{# {}y9+,8[M'Jƾ2unw ퟯkMC堯K+O)˸Iڜz$wg:Ƙ92z%42zMq:OkY*㋦vy ;.+79z}߳ExWGmzE{떹]>#ø2%{5XFثzw{nD׶M䷋HTc8N[+|)fL;`eyv&U9a|,;uyG=&yW|O}nV}|L>;+g1iЋm˗TUI~GOgܓz5M{|vWm~P@+>Q*M$VG/ W;k31vV>ԜߛCϻ>wqcӋ*;}k/??0xAv %tbD6cŠedH y2b j~ #'7a9y,hPY EX'PF)0h,hИQUX E 2 $YUfWB m\(Ȱ\]\ ʷ^"7|T/s&< OW+Vɑ]ZѰ]euo}wY~wܺ'ͭӢPqW^i6aC~;-7Ђ`a]O\2fN_ #s@p͹FZJ@~P0.'`.2Ī. y`Vү7~Oq 'S)\IA$y%{λ&EJ'3ď,hڲ>/Q"n /Մ:S9#Kʌ\9L*934JRPT-Dm>hBL3Rٌ܀ KL-4ND\͹sV@}T;BOC{dլ\: q}ptSNX>(Ѕ CaO1m5C_5+`u7U! "nE\,@WiV5L) H!_X]'Ӎ{xJx W2 BZA+Y8 BK-^<-S!+G}Q,Ƭ%VMNi QhLkY@.nm21O6{.kQ͖n 'զ#jl qμz3vd}3Uy{FoW.pU#/Xog$'ީe5߼f2nX]oRד[(7D|Sֿ=5O}TyuB;5Z̵~XBlDaK[۝,ڕ}RIթ}qr_7iN AMAܜ.H fe'?許O4t- cqh WvbR f;b~>1r2X”(1,RaX(GpO!1~[ W4Admh9'$KU*ic(<[8޴)[j8N>#+~#y׸DפSz1Z%E |_i,?_lWmHJUL#I_B՜i~Кǃ_6MЛfbYP8!.Y#tnl !̗ԙ$K 8I/T)`[Yϣ(+l+p8Pȋ?4"`*:0qŜZIMTYr+][Hzk4Nfx QQ)lE(.Ȥ2ҨγW'3gӑ46K%,U @-kN##Ȟ 5/He]^US LFժ.հNbƚ2ډ,['WLkeC=ٹ*CFI[Xž|CXVZ֢Դm+h.<@3J,dukՑ6D loR5%=V_~viv(-hA24 |1\ΰӗSAzpSٚ`:A$Nh 򶆕rea τ¢%} 잕 PU~M ĠZTbq۵`oXKMJ^z NFuH].xa 68kR~3#Pb9˲2/.h;OZOic|&YKf2u Nݾ=g#L \:?ڡgaXGvKar!3 GLJ)VL(WA+'ۋjخ?jU,8Qsg8NE0@Wj{6;.Egҗ]j{amiC͊XtKd<#"3QinuXOtYڽ&eUX,RGpN:9jKq4G1.~T=?c6δ @E8JN40 [bmҸKuGIoLq<NEqM[E(U4OJ3S 4COT2LŔw 4@U!RiVB+HSB `FC.Dus U?;H~qAo K!ZAbZ?bEY'W!Jj% KuPk\^8NULuba<$<;CSǽU{Ew%PSOUdɇbr XUhA)" MRde9&ǎ@ 2H0|̔paXEP(-g{0vUu 7,hǬY}fii%D%V 4V`%6\@&9SbT4bfW?1bm9.Τm/n5'vqꖑ6`FecOqq"qfvq}or6hfNc-W;K1v!:<Mt5tt`TuuQ ,!5nWBvs]/wQ);l.6IsG tUVi6{Se|_V>\'|1Vg%P~)P7<g6 Bͽ` qzz'/[ Vjb@p8Uс3(Xl`-uAyfXx5"Cd3&FXš\'bnҎ]fu kXpc ѼAUˆg(~e^IM==B%a#y"偒'Bft{a dk؆xM&X}Ykؑ-C<*#J#:n p'kۣ-`w{I$6[u{Nh9EDs0X*b>Vf-;S2v;_  E۴)F% "'<gv[Ib[_\7 /(!ʇ§"!E?2 {ŕB#c+Y? bګ ?g!#!G|_ ]!=⻚mܴ!]|]GKOd *ZqU]Csqh#w{رb!XՉ =fI9=Zc{۳]۷K؉Cے!] Ti!:/\%fA 'NaA !^a Aj\h^DۉEq^yNקGxU] !{B~G~A"P~ǩ ~ޗ}aK%,c~\ ^>_; ]1#B뿚67gam">[ 1 с3_~ޣaS^W"~>hs>E0_^^^k} { Kk^]m 1߈Ɵٝg_5{ \H*\Ȱ!@ 4\3jܨ1P4{v8IcaP4˗0cdG̛%t\a q Bg /] $s:JsCN:RgR`3BV4ZʰhٴplAc_5mit忷&q\ؙ_T`uΪb=g~0_ѣ:3ǭ#O^4헁oͻ N[s#_μУKNzsֳkνË'}ӫ_Ͼ5˟O-(G& 6F(Vh!Z!,,t,+,+,+,,,+++,+,,,,++++++++++))((''''&&%%"}"kffeeeedeegiw''..1111111111121222222288AAUUll||}~}vmaYMB4 xvvvvvvvvvutrqqqqqqqrtvvvvslhggfedc^UOG A > >AHzKuNrQpRoQnMoJpGo>m%heb.U&4N/9H:>>>=>=5=?'OX'IhR.{+]zJx1=Q/W%H;5 "fHId"$j2VCrhAm1VOUUqg";}W;a}=0Ƶ>;\ bW/5 W&5,_oA}>5hbgnZM'+RZ6 A HH4Kz>|N^J"j* 1vI9@pؿRъXGK`1(,IRfv Y]di}O◼'@^'t_fV6q>f؊BE*{\yqnc/bjg+,%A1ޝbXsO#q c[*%4.M)lf3d_vnAV])K>cNS ƎƦ&Cy hd}M5Œ[S*QԹsP|N{Hfxj8 saӣ4=LWJ~Q1vBudBWlRarU|/$e;h ?Ȁg5jrHq AFmQx#zUZ!a#SZ|U烙a|)7or3jXlnTR2XfT7TBRѕyqh5,@urxxt%/1Ր{-I%@y6&AwkH)|CgufjW+IPyYUt璖x'?)h(Ig'xIjnxxw$My|)}Hf8s9П  IYI-ȷnjay{YԙiM)}~~GLx釮zU}gY~p8:@T{ q{ؙHC (ɖL<50ȡu4 zh,jcwWDYYp=Z`yxwJ15&~7QZˆơFkm\ڥH#_*ڛe.z8!c٦nqsh/)k|ڧhytzꌆ17uZ)G'ccZ{9IqUi+ j J=@BxzzR~ʅ@ .4s٫zD)%AH)b*ڬ`yYZ  𐭅 ѭISѪ}S>w_(J2*[G94庡 PZ-:AfmT   B, HJа>ʭ3Jx⚫zJnb檤 iZ"M'],c 2ۯʜ2 ? >,tʄvJ ɱ/ q3qkj:b8l9{kз+6v>|̽k^sh&c@Ҡ uZ⬈ V)~ų|R`]Np QZ = 0ecf, mol̉2jz~Ls`; | 雘9_4K%Zp{"M>|<ȿT,L = a`\<t@ ,ЋŒ>k \ " AJ7XK@\D9j@L-I( JW;)lfa ́| iElϥĨ M U=]ZmMдP` f@ ] d8@ m &̇ <<L25/} {f[9<):6 #ߙML ȫQ^Ý w[ACUce^ f ҍo=ung @\~.0>]-]=.䢸:RmSlu!^ΦVYMf!Wy`ESM9@O|`: p1`0}֐ $NP7͌>߾FHN/ CӋʓ(ȟ^!Î\nTN9mVcAf|"58Okм^Mлq=0 -_ ɞ:12 ~~ J3x6ڌd؂LYSDiIz@m,0”TO'ԍ4*=\8Tp"O _ y..'N. z>..}؇ޱgiҏzޗ ͕2JoI7d{BN 8pPN 4 4i^ĈBE=~Rȁ!aC)ZLӇ5-4bΎ;Yu E ʣM>:^TU֣ﶅ+ze͞=ݷlܾW#]2Y^KؓU -y1 F.\-C6葠)KpgIlqcѤm=X9Le.+\8 gCCo&QiIj_v-6YlC^nʅֶw?;2`G6㰐j>3 tl3:+> #B i$MC)dmJ[ j8w2(ŕX ]TJD2I%d w2J)k+>2>Aʏ.L ?(m&yX1єL ђB+>n Dž WtG&Ix2>LA^dLKЏr-Ҁ̶<)VҒ$I= JJ`x@Bg=LO76FaĈ,G0 yRc"-aJڈL.xL^u UBk^!{6ƙd{8u:æ7)N1OzŞXE8?;@)୩cT%-Y?!24Ń@\#jO"vyXEEƵ  mJ]x֨B`Q kUI4I#曻+b<0kpijczN09jk36{%< =,¯S#5٫yˬ+@ CxRӯ hLR@0rԗT#d0|+>Zh<t;?R`6;K \?l#+BD<$|j@:[4)<=r:î.=Jz:88 WԞqa Բ0À,\z =,Ak 8#?:+Ӂ 90FEB$ƿ/qtĻ?t<"lG#$x6yzJ:jU\E|US M ' ' =MPGv#*cӰLLjQ'䯂H-|9iU\{XWzԅ?{dˢR]TQD\b .MdTRjxJE+Y )8K 'VS"-pPnT'DeT5U)e&9O-\IVWj&HNHOVSE`)և֋%Z?Sr]#[*\-M8U|Ա_%O;MZ%V5{ <Q=H)ST ګڢ%MTZ8א?4C*6RRU-}͑d}%1m8ӁB[e(a^MXW5]9ZXU':w3%\si"+,.fcgۅgOl8܆fyfp LN4yDg(dgYeHM@fX荠YN[f ΖҢN刖Μ^ҋnj~Aƈ[ޔ FJ>Y_CVeefـ'ifhiS[TOy3JpNJZ%X`.9u~j'姊bҜ⪦-WE鐏g kƶ.d|\a8{SzlpNlDh RόlZ6%c;.&Z+TnJ~9miv_ /m;J- eQNf֕G](n>nnĻgEkm@oأ#Xg`oko)`ľד[;XȘ=aoM^u˴ R^N^n&BԎ.. Vٍn\6 lom+Vφ6r r3$oHL> O2JAwdEݼ iJnNPSU`P,SRct}pզsֶ[sR]u~j(NSmÝ`Ym>޵eWgg?h"ln_"@w^9+6tt>~vG/i1K[eLS}tw]'xP^7vwoxo|[toЍ^?7m\Ϫ/1aeHByt K]jwxYyvLw+wGtvwr'eQsnG|U?&{J&F{'WxĦV Ө feaO 'QvZdgN_pG|5Pu!ž&z m_H R8nm/vJgQMfJ-}Wzů@TPU`UPT@{^ڃ@o&vG&%@x ƒ2d!Ĉ'Rhˆ2B䣰H,I&- \l%FaҬiJ7 ])A0Ώ!IT!K"g&jB` u^+ذbǒ [,ڴjf3-ܸ2ĔjzJJ@pNىE.G9lBVh1jՌFZyaacԉ?r3 sf1)yu s^5 -P4cyL\8Zcg;]גOV.z!N»=IaC Xbh cx0gkMAgFy ~%$cE1jf&k!! HSI 6D6t]1M  쒜r,[O@r!b_eUI*$0yAw{T4 CaOEb=֤i$}p0gTGA ѷ5ۇ!m%JWā&iUs#6B )*֓E)%\%zB yeDِbEp:Eh9 A[FjNvu2PPtĴ2aۋ%TFJs&n*/Jު%~.JTEgC Ԇrfв@ai{EY'r$"(ЎI>/a JkO6&Wi5Oԏ<΄g0tDts6SK6Ykݰ%p\<6+[…5Yᙥ k&q* pY <|h@,7CX|A)NM /ݹXy=N[ӥ뭻6_HB;u`9T, mbVKEt/K5i|GA+mB*XG"mIxわ~.SPYOMo{xFCr1 kTHS.kGH;cFh3_ cCx#0;x |!e0 P|E1RjDgiSnvsB>xGXO 1G'"$d iDkK,I,jTғOSF<"ʥDXKaC7*ȕb,H˚㋹c. ^#h}z\#(INC5SZtjFoUfeΉ1}TfwVX9$"יoܟGo$GuE!ԓeEuϭ , j!2Eшq2+Vڏ6@l5:)XꡏBT_PM u.Fc^ BժJm9#*uyz OS#Ȥ텕 ap95wr\(',䔕Õ] l?+KVE eHao,*ajbs_l/qp 2N{ ^Zւp/PaT bZ$E5/FCΑ} ŕ$;CŌٵ\(>ֈrJ%YX8ͭʴN ;1/aEjL×&Mb@`ZY<0X˿/58.34`NYd3m*Q;pm]'7$xsfo{9.N,ͽqW馓(P 䉮9PxzbbM z)i=38Lg35E6I̯9Gwv0 svvT4UHp E3"G&a{|龡Dy[P:)>]zt;zjG84k&LMtRò-5:Q̎B=f'vv_ԆHEgoBssdաhưjO OC5<4: ި!AZ)"K#4ّt9FAʥXD|pJju.#b/=FD>㣽 ў5MA>AHB Rc )A),"}c'ZiCr$vWha;@YJ]OwpGn8Bxhg`&IIB`j^&X[% A}'8\n6^ND8o$,2N`$Uc"1E5B uRJFOeHlHTrv} !yi$E{'|eA~*'~ڊ,eE 囁(>B\a:#tZ5|W^f?qpV׍ JOPaGwFF璹nTgz@]f_P ml%("^N0Bpg`&2ir:-\tVcB* 6©?@ƚ.E8ax霾j:giE%Ԩj^ag'֧VBnE(i5Sd> )eM)N'2qZ]vD1z&WJ&L*{ث*Ġkg*k**Bpz*pPNkpڽA%CFZi&qH"TvH앮ӐǖP[e& ЦmfB'E-*UCh6l֬&ʶHF:c"e݂R$MlA9E*ʺ2 (ȳ@ )(m]gv)>"l "D-q쁏qٖrQ\66T݋:O4nmڒ]ġ`RonZ`2k^.OVӎ4R-҉,f8\S.ّ,>MzZDғ.l@-, \BtZn˧umnVUpLGRIC$jPombjo2M*Ö&W@3Nm,qur볬C!2J5p5d/,pB?.jK Ad]AVB[/CIHd'%ooPsn &p60ZVA蓳Z^٩Jq0QH%aq{.u,4Pc܊͙!îѦas 1fLj(UBATwA )uTf[!nk1 G}&uF$0_rc&'6ѡWi2D"Eh䒚ж2.0jQ!#z'5hJo0 ?)0q 30Cn`,A[H#&^C o71C\/8+-#rtssys%sb20sBosb&JAKs"/13o($b8;AD7roZ$4F;%&Gۣm2N1>7D?3 upA'"1] emVas 3L Wj4Ró/gr.3 YA4Ctt[Q&MPX1+72Z1# 5pٚ\QgR"^fSSwѐ"<(a3NVKVNWOs|&,6Wm,+5(gvXƬ\XrGs&&j(Wka+dmmSvnKC3"/Pofrhhhdiwi;pjcmU4n7Y+ltD|6$/8p^"\fo7`ѵhut^omu[uT5etn+{dH[UzӲ/<99<- |\@󭬟|HsUjSu/ozϴo{{P ʃÅ˓3sx 9.3cKn=.zv<7b#ԟQտw0H;{S;ϿُV#~qxƞ)(w=77~KwGSk} xe#O`nX|CH HTWN=cGs{#<=dZBQqhWdښ 8Rp+R \q5"WJsBOuEW.WXlG+WBcBnvb鞅jk uAYlLIӐPfH4YYT^!C%s:ߦf!dF -:c۰.ɲ12Z ta^ga#A"̭-+Y.6ZUk7]P)2bbovsVS6Xu8`kœw!zJZ#$s D-ҍ)_=T)uFSHDLP4;wxn#WWT^$-LPO'EK񰥻 j"|>Bόp4[ 6; q; (ýDpzQHn̄AcdE%3CQ 1 S I,OJ߹xҩpyK "O-/ha& jA&{=)2RR<h#IeRBi}qbĜ\8/Bkc*Ȃ, 5YVKOK4w4AL1 Nc:?Pdљ Щɱqݶ)Cw*{XW&4H";԰HI 7TK1g11W !hAyi FPE^a7!qdۨSC@ָ$;qwgG\5 4Lkִԙ95N9jjI#FQܑ#HNL g}c'UeuT =\_&2D㩸9QoɍCYKMH4Nv5:8(V^Ul' USCe1\hl%\S1-$-zXҰ+K[F]X̒ c̮mr+)A轟&Ѻ(%AԊ-SIG׋'nTˆ}lҺҩVP%}b4U ѵ¶kTO[+6U{soo;Ɲgc;&dQ;`8QV1f{2"iش YT ;pMlmG{7"0\e*Glu܉-S_VkW7fy g]{#/\ny|G!rJYWUG*U#zo Ė~Zў.cMSHP]-Arz$=Rə|0"|TsʸnC@ hy 'zv:-;/iU/tyQC(l*ybCm &4Ӎe^;SU "oKǎqApMo٦`4mWF4ⅷ:I!Z BsnBӗ[f FpQcTܨ5ȩp^n>k@n/,Oo:Ө:{t*R6Yܷ,&?9\wi-;!KGkr3dHrc\k TZ b* `[ξyyJt6ܧlwV>箐W^vaF}I1; Nd8ϯz1gƴϗFaϠf@L ONUd_O1.Ԭ.LhVKQp. 0fGbB`N!0`' bԌ .Ȯ:O%1Cfq>pY. ]x l QмBΉ ܨqe^Lk QLbq&jlsPP.:1iE׎QcFqGF6bqN$݅eWJ1/fB*!$Սrѣh%E%%Y%Gc' V 2~#) P"'+* 72>hB$=*ٮ/RS1xrH1o0 $P&iщ>pmliDp)0-KR5N31+e1- ^(٬ 67S> .&H4Z6e;TS)30k00pt3><771mn@02':Sʜi.023-#;pָ"8Q*g2ɓ><+=#7[QfͲC5hH `- i?#R I*@S-F2B:2^sIThX,T0K=O=2 ,R >"?ogo^:"ArhI+A; ԉd?-BE.HT+,)A >-0DorDI4'TthjJY$KatE)+LTAQG!6ìRM NLN'N'0?D4nt?Nh>̈́Q!5G4$r*YNM?)V5B(+MQDQ1ЖI!*s!uE WtP UV1p"ua“0RFX@/sHaRYw OTTR ,&V(4:]VtMsYFo5sLLKl~uiu]]KCϑCtYYOYk4IOZ/s u[-DY[ \UWcʵG'fb)6?F 9VhatCS^ ^d4Zo_J/V:SQ8gMft,%Gf͍aA[Qsxgg` U TԼTTqdujOZ[j OsN4#FlɕR(mIjm<nBn]HV!Gi[Evd%,p)rBQyjW-&<r] carr/:,Ve1"563,otCAR-?d*>ӫA.].a8vP/WT")fVpdw{7OGxxxh36i7Vbs5߬O{}s_7kr-cw $~q04~7x嗙P X >$stytwz \0_*}pk,`k0Y2uL+؂;Q5x#VB81c1A *!m[7?7^[X_xyTŢM@KPv9hP=0twSfw$EgI85+^n-ftjXjo7Xw43kVKDfM"/ Gw}}Z#c18 FWXX tϘ>X w#ޣ~%sVB<44+~ /D899G5>pPxr7c] [va2~FQF}=Nv>4k/O< cBat<]OKgn(^Ve-3m^f~Rɽ#~՞ٞY`7 /-sq#d~'?Ʊ[;[[ÝqX&X+3pX+;?C)VmMcP빼_ ފWH߽#_ezB7YsS\ϿLWS > FPP=4ҥL*5ԩP5Vs fИ$ӵ*9Qtߺ5x hݽ C()-%_}aM G!qmF|bBʁAIhE-]Qv.Q~5]Fa)&c@8E QqD b}xD}AARjd#t!&[Vfi&YxaVE*KhЈDt"mznUcRWx:%hzJѶ07(I}p@4dQVvrb - kNmg(TT2gr{|ّZbĝ8u$[[I^*^AD:l^v4aVinD+Ufr"k[h0'F)^gP]{:TGKZdvkAjyL $ߌANoG"752^.b><ֳ@laQi`G8n*2aHc`vpj%(r)G/=,%pN uR3 Zp# q6gFgM2Y=m 49=31~wU"GxMk DK;~wIp3obԵߵD5Y+/~z]wb ׌/{U{(W|P0FSÐg7eirz󄷅<)֛ 0Aޫ">4$>z>},]tg#_;rMx3 Wud0S T Tzأ롥!!P 8T1 SE1ЬAkQz8}޸,NȂulOC`ΊF+'8Դ$H(NF[Ub( -~Oujs y͍m;'ϔ5b(H!!K#=cBIiDs$ >`L$6UR]8DCutQ(ޕp9*Y,.; BK|` B m!NODaҭT2= BkX` 곚 5RĔ13 oq,oDKNu 2dArɔ 22fH0ST#A::lr̚PNfDC͉r3-(srr><@xCHX*Xd 'ϳr@täP2u9ZběOhȊ'7t zgsy"a๎B,LF}EkRIB/B:uȢ L % fj_ cZ<%StgeUS^ɘ0ek[ IVAewBF#t!XNҶgxXj*p KؓB4*LYM++]K^ڕw,+#şoHGDmn /JLJDv@iI X줁 ^]2mPT< /kmp{!3}ODw4>C&ciçai,yk)lᚠWG2E'Yph7;'ՂTtaFsavͨ9m|c9%O 6?z(O%5-ȫ;1cZ.o;m]P*fm2ܦɪ(Ѽ.Yåӭ˝f4kxx\lL0cB&bl~49{zsno[Gz+uI8FnTfZލW s>МяSGvOoZhZ+qOW?#M 5ſ(xc>^[$Y'(_F:vysV)rj!}|lomh=mY,b*nI+ttڏH6,*/f|vvSY/wchsjv)ЇpA}ow}ه+B=RbR'rra,y&[A[S" !"D2{DxlKzeAaly0g|G]i7m GBfu7 1AօRaq.{ɴIq&{CU(hf\&GtoSQ"f1i0dcvȇv ؀V愐dQS(x~х#'cwLdžJ6b e:8Ka 5kE(iGD!R`@|olv ԈY]XeЉqx2W+PrrPy&xFx4ahc~Ÿ9nxRRU@ċ[-(jQ3cpwQa ~ X IGSL[/x` C<8=!=7DS8&2IY؄nHhtx a_x?I98}w`䨆*X~gshEŷyH1) pWdi7 9ipؓۨ0P2%aqb~*w1Sy .Ls9}:ڡzJiZwb>u/[*oU:xW3r{4j(6[Z躱<ڱ}J$"#KcJyJn  ccvvJnbW-;J窱jɮZ TrĴO{7QyMʥI\Zgydܹ&G(wkDtwj~Ȥjb06ڶ˶y,JHdO긏;H;o +c5Ƿ( N ]# {]=Mʫ+iVm1ɻHC+#JtwR -(i ) ˙,@skm8>eT9 ̪x®D](?8KĴO˺Ll! տگ-î<؊5>Uĸl a#MmͶA-GlAFm.D7^Xה\Ql+۱McY`l=c9m<$*l>n&,e2A^+-_(3e۹ (l?E-MOh2mK ](Z"k==5(6 nNRZFzx$> yhA̲?ᝠl+aճlԩ!+%A>#_ϥ=lN^얥碾JUL.=U4ͺ?.h4w&pb MfJ֞ZajnN.X-G(K.]4 O eP6^ A'1S<ӗy@u^^ 2rLpy =/jJʲ8~}m"U,KznM$#IXI~X[w.>{:=4VCvjk׍ qxO05~?[m ˻1* λx<܎َc6rQ 'LO |^iqו._ůodimr$_DF/HEb~А: $4ida8А %JĂD`XukG ^H GP ɂOKCY͚?*gOid)%QIB :4bP7AܳM [zshƺ 3m3,ӽ6aO:c51Fd33$2#R SZI4LL# /DS?eI$t"cqUvY!nPBϼWorT̖Wf[F-' Z hE-u#]?r=X[5 ܏ ^}ӳ9A*084#8g6ZɶhQo}Sc4.l/CqǕӭЅPKTSe!ӻ7Wjo_}Mԥt͑UĖNd!.zjǪ ͘Z|U!%䪍VW ՕPO`htglqU&ڹ[LZ郕+qXb+{qƓZh)/tj=VH[WT^+bDj H/$UN&Yx`F67xo+kƼkw>4mc<;#8Y-dּw]q!}9i7FaXoxpqʋK 5,zkImDoN{1)Х-ncƷd3 #+h dN@h#XI2Wk&4հĔC,E 1CePf)*0͎rWDbAO a¡0;#X0rh1L4Ƃ$~saab2(ڌ'8ve])ZV,ڄSGojk$ =цAm<.yB% 6'Z*c -2|zb:(tR"h3od :)B$E+`,V~!cH[sj%^~ˈD#!xL-isdK JuBjRu=[(8JE2ASC4- 's̩<]&z2"KD a2h iTiIz:AI&6a {qsmϴ TH٨Fv*U&K m8,G1@k"T7ՉFe5ZhT/URVu>U Sk'g9ݤZ`b?6Kh,џ@'"Shae4e8*e] `)"f;\|czYݿ \XW!9q}[e3 ˨/6[nUge/59t9"iBMAd%)}qRIyZgU!H&݅-hf/~Q w}:4,w%0}L1Ft |Sm 2StTOݰj Z [V~M"3VnUajJ.6-dg\" W'88nYp#ٗJnɄD ?t"XmH*6+wFkeAbmDUH5,O/d?;7J5PsC' 8C^Hx2,=xL00_[ZͼuUzՔX=',@_w=FD 7}O!:KO\^…!֍6ujnUVܟoX-ayv7=dV}h&*ʕ gAXЂ(T/kImnzw8ֲK> Ӟ,bv1}g%M/8g-.(C joØEzeN(xsT&z=y9貨aR# Th"h/NxZ_vb:^ܭ0NhQ/j'W:tlITdV_D'=#[s1W->LJ/z |+OpV"|7+:ЈZ>-Q[& -3?ۻ=S?򽔰+; K#;hAj2k$͛9 ,zm"<3¼z 3@tc?k<2+#8y:;8` *&%to6$LiC: >+!,T+-A?78gCead5@ߢ7dlB򡸱0:;<)=4;9֘* yDB 7C"1&4{![C6 >3£#BS6 44$+->gL'3 zLt9 EhCN=DWBtMrԮstL0LLx|Ąsp/$O|׋|NsSDNXQ˰#K%@TO M˟2R0u# {/1Cd*U%"DPDţODGl9$dkR2Á3-Q8ȁJ4 pI2Q\S 9:SӸ2-%)R-;LR;!:V4IElу!9S-M4Nmӻ\ L02 I:U҈XD}= Y@feGh2CgdմPF*I51The uBLͽ ab*ReM>9T1~d^^EUQc[E9 +:T9d"cn=eT2FObQ&[ee\^id<|u [1`Ef80SdhOÑT[%_Xndae%(&svtq|ׄC^_^\WI>՞gg?)b[l]e`憆gm22\&習 v^P-8haMQ%gii64F]K?{ ^XeYY΋ͤ0n.%"yN5)~&vf.>i3{_>?^+BjͺfQq}djwNg_FjEq/7jn%?k֦i6^yb)j[ evꈝb~dUh@l7Z~ȶ۠mV=h`JpeЖ !@6c֮g͡-c΅̯ ]5-ozl6pNh; nn…qVEEc`>g.?WVm-}jfcߏJnpJ9o sk.dn-qmME_מF mɖ_xqԎo _m(n=yvq#?Nxl6nUkUFW+WIJ 0w 4_f&WZ2 ;j ?aNb[Wuhm_A~ktu`tnHOvSޣQff p]S?TWu@Om.=)Zru^WTV`bO~f#qn^VlGs,s jZWX\=wvKXd+EZv|w} wIv*O |ZwVqoP/HpItgw'D=L{ yHiGke*y?yyOWq r/՗xxv1u767oxg}׋hWoRkr wMa7,GwWs>&lHz/1kY!0"4SZ}nط1 .| TEZ%|8<7yxg\=ɸO*+cIu1#_fr*g(Byk Ax5[Ct\hrmv17[CQqÅGǜvΥHWBuA ]wbXJR$ip}P]~}=`FRYea`AuhYE8ZkBעAv P! [j&]Z-rSiEeetap@aAD[%d'#u__07ida i,}`%.˝4:u!]-3"472h}R AkqB}琌/Fꗪ""[bTĕWJºYAcmD^Ҟ(1^R"J#ۉ nY;]xާR:" V1U:1\Pu]hB7R[\Pm,peM2 Y[riUO6ܲnOI-|Cn)эjxTZck)D5,1}=DȱM~('7Fh|PwI3 ÿ}E~δБc_KJ9İJa^?S<2CcllW;re Qw.1k΃^G:=q,x\*-r[JYs&]8>D T RŮ^VdK]@xВm!x `ȢL8?k,hE`1[DZu } /rBnM^B I~_r$ 92#MHAdw#^Q;KAx'9W"+ٝ,C)adp1G)$F6ʊ<@;_ztQ6BW!xH-/Y$ŏ5zT$3IMg"t%չ9cH֧Fnٞ&ǵ9%-X[(% B$HW\"k=P`3 gnQ2Ҥ櫮)FQeIB/)[XF1X;S,9T^1gHG5S A{j&2f5ar0OfSGطƮd0-nЙΨr]%5)J{M +#= <ə `T=:|&ӻ ]hQIYMM&$+ ι~(B*R3n,,ӋboebI)tNإI:Zu"Ѐ\F""DƦ~B(G*fI *#bPuS=q9R+ 8uq㶶:#gv7R: `gh(Rς-IuM;u* 9fa]g4}[[ԗB yzx]=r{/slgA0 M3u Oknۜ1+7BG5)n-֮0XIػg!e Eyʁ[QLf_ ŸA ʁAuOFU\%^$DWh\խV] eߡEu}BEfɄ ]n=[mwz-VNZ_XW\PV^Mv}!It f*ܗ\Z %`j5 P_ Jb!iHݢ6M".8#N^]/ilhlp&['B pA! 82AxVޠYۑ y.2Yb"E`q\ǥf&&ZaAxYߩGݱE@;Il ņݛ 9#!?Z@zU@Bu)1cYBZmF]TD^AR}+֝hJh%QڡK.b)#BHOPPdRaB,C6j2A%'J^$eB]dTX,$[$y bJJ]d#fZH@J&a%E!$Ɣ$Ya坜c^DNU&B\&0XG2ŵq[1.HjG8w*bEJ!dnfRƆy]xpgf!W#͍XN,ꄆ- j`gOڿ%6'oCBD槕i#t!"V# e"xgA,''zJ! {JX"4[XT㉢hdneh@hrrҤ_FJ]t0FJU=咆DؒʦvA]Dibj^X~#CuiPR&⟁ޜ1LdBhwjf_Xꑎ)m*Q2ꦡ'Lc7U)6*WApF$(eJ,.`Z [v*:(DP:)N]l${* 9,~g Rg߳^mQkZbѫl+z*.cejo"Δ*Hk򪖥%y hJ.+u"ނֿ J0"@J^]Wd{zK|RlNkƺiBἊ,JJ%VlV5$.,f,F[o*_y`,&CW~e9g M~lr׺-j``ʙ"ZhYZܺIF])m+2 Nlj,(T(nں_BnNn|MF-JjwvNlխmꪮ[6Da,kҦ"˚G2\=hBQlҠQۮ DoGQ* m-z6 ig+^FolN/A~-Öfp9OoGM/]T/0V¡n+Ԃofh&.8-ni:|`ΞΩLr֯u^II Җ3m*'>Z1  Ye䦛  iŠ}i/ێkLqN01 A#֤:>nd811A@o G⵶iyrn-{nq*=TY2^.ATn/'2,Ū2ɰ2ʤ9-A4" -_ZL,R!/.i5'`3#?RB8-sbAt+C)r),rӉ1&o O !:e9ۜ;) Ar$=GDcV>1. V(#!7 /&K0C9Okn+yp3sʳx1Pzz nAiS26[B4P1ngQ /[SAd  2+tA$ r9sF5x\|ZIgWkl??ھ!p{ڴ(6hiغ5˪QgᵎTVSwQ^Yjt# JCv"5st4./sff#]g[c1/`kRS !untvv&bsL=pTq"f#^v2B3K O75.puct9ktŌe.7vc8"kn-7D&|3r$f}t~p7[hGruݜ]4H봙A\yxn0 ӳ|볇}t+8~#wqCx0='xf97n-lx^t8_dOXDY_E K5w=OwFDw8jw?G~CxrtV3y833&іUR9^yD3[C hʩrC 9!変xQq"o_SzȝC+c d*g*D̲x7gh3 a# X:xczkz 6//{FԹP$48Γg;3tH~}xD`@^C ?(N+5ϞTn6&P"O86NT'%o{j2'7|4:{vs-4Űk7Z;Cx]ڤ3#KT||£?3pxJm1 ǐLJ1G}ףջl"Q|۵|׋ W_=qD@[}{Bty =LjB}ߋ<ؒ|Ͻnd>ͼTMnLk;OA1ç'uBSw|C(~=?<~>w=g5|H74yqi3}  4X TbD)V4P!2 $HKdcʃ >rJ3'dfNYzdN3y5INMSVzkֈvk6scɖ5kn (#%ٖ2J͈@*mHâݎZR *4HW`B5Xn,gPɚX㖈9lS^YR5Юfր =Go(۳F;9R ʖ{7wzUӽ={},qt)b.nEཽMT`YubB>쩴dT1|>:-% lNb. k#@ #,$*АNHbjU\6\"㭸p"(s6@X1/ l""Y1# |PILCM| $|1#(̌(C3W{5ܓφ\:(/JŷwHG0yG!Č>߲$?s!3*9/h' (X9ʽV|7zւ7to%}Ÿ*~DtF5ݎox*Oң+@C80.O|5`j˗f|[վнOC KplUKpx?zaY; oDذpNƵ2|1OW WVeKhB4qOR[aEMźH~GQ'2XyC[St)P`d/.b6 s+$(9VEQ AaKRR!"7""@H2s"H"e} sX`%U&fX*2JfЕo_,HG]HD&JK C (dgh\i$B䀓s"# f15@-^=>PScDgiNLd9J~e7oˋA]S@ޱ@-QZH)$(E5>MDp!ܔ$Xl~1.ĒKLZFl0LsmNijg ,[P$ c,";:\L _2znf[1SrUY`ttZNmG0 \Qiҹ W][Wy޴O9iJMЀa\ -vVJƂ2tMd)$mRbJI"m,kZ*r'k \:eYm$.B4]m€'ΏY4Ni+5bҹntFH-mDٹ\l,#4B߽( # :q'8By&Ί}KK.N~-SL+aie+I;7IʽR#f}&x>mdX1_5}Mi+A:V xDkp{ް/j )"Ĥv2Ne4/ꊹ cw656qg.z6.bFr}ֵU=$\*kx =0]E7nvG{2{Jj7Z=g4^ӁgM&kaN-ײe QFkḰd['=jp*i|JTQgU On1xgwrMo!P;+?mȏ`g¦(Hi!gK )/Svf4;ԭVƿSFZE笯ϳ~py) |7.TK8)xCna} ߉׷4u<6ԻNZ4L[Y;~ŝ<} ;lO'9)#v~g!9kh3'g2z5DÆHYozj#x:Ӑg5X~?xUjN~K{?>qTxRZn&&څnf,o $o@0,X g Dpp*\ς\"ڶjo nޯϊlj*O/gCm0p-в$M.0uOVBo"S0l9^cmΐp !?JpϾl>P k|/se=oVvg_NCd;p ]pWhX95S[ ׌͸pmn  牫x%8I^pq\14]i.1]G!.ĄӐ|oVPH^!gW:΄mVnm1Q-˼O~ᤢQG 22qFY-aF0r4ARDHØGpF/*p"%O$R!)I2' / M$xJР2ѐ$E*f<+S|fp &Q0wr-!#W$ꬬd))S00)-pg1#1D2,* 8?Q P %=- 1.kL3/we//Y3\3 TB6k3< >2v`2!"m0= +sY Β*9,4F:ۑ|*[V;K;# S sN[~r375")3-31_|ɈFF_jF cptt )W*$=LJERYۅNb TU[\U lD(UȌr;t2 U>CY9/.0\"vK_9u`jS=aE5IpTTK)&bf(6,VOlU&mWW'U1X5sJvY+e*`'5/@kև'G%j))P71.ŠnG68Ch8ooMT=FjU 5e3(`VSeV@nllmyv haQ%Adjh 5A& [Wgq W H3kȦy7N WLD*ח.7Ew s|Tn/ngCgy-mQu7p#eoR_5+|kgFrшrnVʐDİMp#h+z1]KWi#3-e? 3Iz`WxX|u||%D$}wglwmw3xs%C)20uM'VcODiao7pUd|%e)X{%wys})}9jvbS疅XLwcocuKr33u}8qh₱$dhjgCb#klߖwgjt]O2vKyR{)8U?'؍-WX/;<؎9WC]w!Kq0ڣB YuxDłxc鋙3u5rjQ*b|xÓweѨG`JنOqEX#MBww~gtpuՄ][cQYy>V9g+nΒuـy[foxX]œmLyYYs"mg5=씑 ,G~#{&PGl_)U7Zx|AYkQYX T:BOxK%MX 89Jن]u6&W3%= 'ZV1BX\jCZR8'y|ڏ/Ϩ4Dqn֮MUO@2?!T G?EJ_C{"чቿ,m"0p(s=w%y6(!uԩk+5t^g Xd;!d!J4ةbʼnw۸ ǏAP$ɓ(6l(bE># 4hRdQΖIJT'K05賨GYR5.[~8p`B`Rhx4lZ B`-;9R;崉È+^Xǐg3G/X." 7+ƍo!@y&tԧҒ-f=tJ#a ?QBOLw@ó7ZصL]xvjǒJoTc#<ʚH&Sz,ܲj~h4m1TM9) y&7!i7k VTTYUT`PAHwmuxݥ^}G@XG6d}E(ҀH~&сG @#>yx&|\%hnBsEǒB @cs҉cEhPf]]BVĞ{&}fSQ7%Y eh!"1)F*hyҴnDZBvz\M՗!իrl]ӞLEDZeIԩ~ `WyD~AH)9f)ۊj=9%gJ,%%{вowht!(p?iQl'R,rFV~D*yͺh[u].Toj>:I2F.+Y^JW:Irg|a xd{7[-I7| =/88 v `?{ϭ9^YA $k|wC_dǂvvq {<؃hOXzbd4=v`8n'0!$Z(u"zqъG,(g[CHГEAIhĢdc$ iPyl#ur`- 8Ac29c4kliw^Ux9DC V %aa?cɎvs@Dβ[֖:y2=' 4ei;V鐳ٝ7TWd3}17svfVgvV"=JJ ڹy&I9(Te$8 7nɜ:YxhHi!I{z{ljrɞZ}9*6 |yi{8ԩ})Z4ʠrrRƆ/Dj5+  D.AB4n֚]ڞ%eѣEQ7I*hbޖkSx-0ڪ::J8Ɖ(tکꗘ rɫ"Ga;cʚt)Z2*ZyAiCFt._r ]ʡʬbHJW@&ѯڠɨ'f b g )xJjK!B9V;2ZrOk@y#@ +JKT :o^ۦ.>:[ZYk'%3&S1It$_ۨ[Ah' 9|K>{Gaa[ :+wZ|iH,juwkR˷71+G'kI&H9jQd9}҈Fe1 MkrO;Q;KM£x+x۵,Cl+H{'Zwұ;NjM巼FΛ}$,Dۺj˧+ɉ󙛏<}}Q.*t7k ,{kwݻ ͇= gV훯|=d!{J%\5!^$sQ[x.[{L:cjha%";Ĕʼ#DIJxǺP(E-L/,)'-r9ʻcIƪFS lnj:Q&a(\j\Ï}LB (8\fۻkKEjpdƓܡ*G5+s}_L?;eV `<+ ؄*ؕЅК8Ֆ~|ʩLIm9Kj٢]q*GKթZ`[[=samп ^֠Ci,ʛ6v &|  )=1]UЌJ=عۦ<=ߝH+ҽ=_}٨-.y.2]-z 6ၬ $];,ZH9~y[$~-h71 w]خ(5 7ˋ` =QAC6{\D^Zݤs^᥉8^`>h4d^Py#NFw~u+rNZ ,<>TFj^lnl?ڟ/nOӹXJt=v5Tcɕ>kл Qیs؞k@BqL\㈜쁾f< kF>׮1œ<n. ~lܝ~DLh}}ܭo؜.n. /M,\Ů7?ox?ui<=.WG'O%/>6-0{>m /9b;T@/bϟ>@lsmOh_]O~_;eg^N.3Edko4I& X~yMnn 9mPc/᏿5xi\PO}آ?̿-W_YQ}28/[/A_7~F|\"-Hϝßa_~>VO B N 8pPB&dÃ$*Q# 8>H%MRJ-]DyŖ- %G)GgC* TRM>UzU^Z59]~57uJ 'Mv%J4JԸq1gРI3"ہ*Byۑ| %nDC #djxޅw-(-mY3_:T#>|tV]@mƝ[جn+ ˖,ؘ4iw&Ͱqr~Nj-B'5l0fK6>QK?w2Vc$O6jA)&N8#ˬK,:bdYo[+т<|ǃ[h"ԨQžl꿁@3ZFiC2K-dnB*+ M:n "&ߊ!e+c$"-4cLL%o @FL!X2`(,!5TQu70 ;sHZ9/@n K1S! 1'ht\chW3"GD]':| /#46AOY`ZsԬNEu̒ʼvCtǂն6":it4#vX?%~EYC.iHjE#l'VӠ,5*hr3F9Ŋ0% &Ia^޼ mXqUXf86dbXI)FL +=:mmc7Ty$_9囿Mֆ:lc#b3ot=eT珡SE|cm/NݴO^tӡj*-nU|#ՐW9񅱝\Vzb!|5dTdI?=|_J]TGy޻YZ܃}Y>8mNVP= T}IozUJf34AN$ e_g)2Y/sI&e8n '8ϵ&\8ExaDH}BbBHSHGCE$_e6nss8s9w퍬{b"iu%YEx0g!|$q_ ݸ8R&GG( yb+bo()@R@*̞, *җdd#ÒwER"4W%ٴ̅Dc AY~!*Oڈ>6̪ٴNd*t/`6 ٢u-W{tS,5g収T)=2pjTmN.zˉD]/9R|TH>eBի{t/EaLfm6@)1"?!8ԕrt"4! Vh&}JRfD%Yɞ14̂zF 2.AzyRt2IN tI%!ҪEVeM3"ȴ2IS8oEjK6!U)WՎ b8ENivB-Iv~4oElnؗ1ued%nZ5뱜t *X(ֵщVE*K֯%:Oּ-|;B.DpkqFƙLTk瞓 )r5k5*:"n;a47b{֑{djwBy9t=w#m׵]pSgK]"pda,bj$4Y IJM}e⃮չ%et xՈ8~u*HBs|! v󉓬?,he+e5)F t RL-p'ޘ2xYDpTS>JE-]·Tnz[)w9͇Fu]9ںzӖ3I-\($t@QW?sჼwTu*bФmnjd3v9us`cz,mR9LTSՏe7-"-t|eGD,gD̬wWyV`zRlOm7xj<ʳx\ӭVބ7`]39GDžr0Ip\/gWr m|#͐XV3aZ휣$tY;%NravT fsT?woЫ&OGfa2~k\Ҋ_sHǍk|Uȅm_k\gUy&ALZxn˾^GE?9½Ԉl;o?-&22+#3'4Z[=8#3?ٛ=֫=#MFñoNӫit3@@ 88C< #B=q[5K+NP'8˲3#;`˫AdrP7 2!L:_;AC&d.{ Dq39C[:RC L`DWk_ds?W.5%Z-h|"C^D_ϓR0q>AelfL|>7_ : 3m_4<567?@Ot(Cl#@y3AG(pcrHIȓHH/?B(ɞ:I\ DE<<z44#(DdD- IH8A+JtQGHHɉ6LI%ܺ{5F AB|EF.ω6ʏ$1ļˣ̪$(\IbdM<=2Sn ,Lli8ȼƱzJHؓE =?]3Ţ nkJ(:F ״ʫ$L4L[Gll,K:KK"ʔ˄:NTD=>I1[2P$MMtބ: , PLT1lmη$ N|NRJE,OQ|SByЧG#=?$J&M,T(m)e*}+yLƿ$BQE ϟkQFlE16DӧПSGQ>ӌQFFT,]|.M=H-DYLMu90?UC@HA)DuEe0hTU[33-DjoR4bT ZRfeN']Ml%L|DM1.IҜq5t7 bmDXWzmҶyR[LOtբDԋUm |T@UBEݤӈƕ^)tBuJ28.Lǥ0V`h>Fc v_(?mi}cX`%? 3<=̟b,F,-BF]X;1a2^dG^5^?%beUWd dBd(DݛA_H6M#c c N\{f_) iR^'~%[=e-PxMe-.g 11^L)oEDBlp.hY^V p&^wn /3=/qL OqpSϯ~+Nqpk mwN~Z^jVљn8fƈ(o7eqNe, %-P&q :n3/`VOju#jXfMP<9?eý^(wFkb( ]oF&w^R_wwUbojP!gvj)&'rȖ,B&X0qg[j7u>khrBoo(y@ VseUWsjOO}Wqvc*KA/"qppeGΈ2oz*w7|&{k'6oyl|F"-(N8u4ϸ7':M^fE#(yWXS\XW>8#/g\$2||_Vd~o-E,,h „ 2lSA%SA7r1BG,ɐA&'1ʘ iN:uIE؂ɝ:y *VUJQ筁f-k,ڴjk-ܶѭk(6(QBc%S&kLu4iΜA&XA7HQ@/7kP3i A'mԍv#>r U8S X[8,Yxiu`ءs{ٸkގ}B\lXAcfQ4$˼xb2aZye !|.w2wKMVtemyz\/r] (ޚ 3y7}7 ̖8L_I+FoYsG xZo]kE my:쯖l(iX7<8<+wΐ 5{se@#%4cE{yj wS~9,5Ơ:0Ǐ`;] @ʒ^Ж'MEmߵ:ݖ' R[D9 ij`IK#}k2HGuPSǪՕL1Dݯ@)N` PX$,QؒE@= b䆳ex"(Fe<THf$S"a q{4N/9 %%L.JjثO#b!M_#8|_X9eqFJԢ1|e=h8k,`Q$kH6őcLU4c1U/D2JHq4! G!2)#e::[<"`D! L u(F()=)\ˁǓØZ*_H ^ė\`h(dkA)Rc#i"LۦWCSAIq%KslqOX.3Hebg=v 1&R3(X*V!y /@J %EHr/^J$*u(є!U3XMgHtixxZL Hb:˂oO"Vs{׮[n +lc+ֲ^ z˵~6 h~R؉7v \v'C(V$gG-#%[NlI2AH'= UiUZ,Q%duaBk3Xb2~0#, /{.U!ZJ&>1S` m^m9F,di8/UdA QN~2,)wV`_!.G~ݘ Bp%ovo·T-!`Ж~:b!vtj+mf4G˞t4.dχFj~VubI6Q2غ}m1 <=W㑝+:dKڝ?+NNf3PZ&H_ ;ͪnm<nA-[ٌi]rݕnoikHYnuY|ƷBzgޮ/?-bg1nZ?W81p9<]=[!e>yLIWzq@T pgCdF6.٣TV6Ү=Z0ϿOj9{|ÂE#38 Gs\e[>Nd=ӐÝYr7%N3DA;f;#8 xeךo0'ؽ||I5Apr^w]ϞS/{J<7řgt_V/? >7"޻Ϝc`Y1꬟fn v~ *  Ơ .D  ݠ!n.!6>aB$!N!V^! J!n!vI@!M,tvvvvvvuuvvvvvuvvvvqk dXK?C L]effggi"p-{6>EMTWdu~~y}uzxyy|vmmaaXXLjLEQEBHB@@@@@@?@??@??@??@??@??E?>J>::22557799::;;;;;;22222222111111111111,,,,,,.,.+.,,,,,,,++++**((''+'''&&$$"}"sjgfeeeeaR)M8>J 3Q+X&\!ad c_U MB4!  """)))))))))))))))*)**)**)),((<!R `u'-,(# ##$$%%''&'&'&'*&7IV agk l m m m p x { | | } } ~ ~ ~ ~~~~~݇!ȋ2Ɍ<׉N]_hpw۝ѫȷǮܥH*\ȰÇ#JHQ⻋3j8G5 r$>yP<)YH˔sɳϟ@ JѣH*]ʴӧPJJUjѤHTB&cj؂ -(R"?>t_=(I\  C u 9!ɔJL z셬P\F׮M.lNϛ9KKƊo2} Wus?hХjkݒ~z,M߽$@wG<%pp߿_~ƍ-Aʩ^Cx`B*8{ %i1ăj(fZmy$lي}J :5@VDݐցXڱJ8DK-=iyM^ 'bXaqi|c& %AZ8GaiM61&Z (B%5aE1DzrUPMș)C>~**CRWWI~uҒAA M\!*+:+\U5jtq%I_ fqq`}&ryH Ayz'eZ*ܲ&l"hhk۞ibWZdfZq&cl0fNg$II.U%k $pZ_L.񺯕J])&fbmJ Bjs[0Y[uFQyWCt,Erv&)Q|.?o8Zz3Щԋ@Ht4}"}s]꛹zT +ב@]o֪Y-aF^qrPv~z%A.V?uτo9a;~RKGNR+ciHW z= KPrKs'Z4Tr1Huꥋ6[J9qu*|\X758`p>.aOٝvdX6N.tC V[m!yw :%{^5s +L] &6ձDA쏀kĦ$k˘$$.\cFka m.D( bF4`ߔ$|#1:4cW8bĆCna/GH bKd0 5͠*5BӮL(<$IZchuL?(H@1_L Jl%O"v%F!{gguBaK"AՅߡ]5ڑRH: LoOo$T$%lY>۔ZGxuv^ב!t+ϝ{̹lfZt?ls%]mlՙ>ncmn1$kN6VZޡO21_/p qs!Op)Ky LqC/԰sߝ*˴V!\2[YylXbw=d3èt1~x#[B+qMEn.7 $_-c|o7|ss}ymkn{IH/f%jƒ}Kzqd{#a=ȨCo\+Gz6kdg^iv[zG}imzed:~vtNA~cȅb-^ svZ7rFexgh.^l%^yb9 jĀw5Aw]$.I[{ׁtaE"WF{SWtF:8b?1x|3Xauwo o}(b$~' *CR~whe*؄aztODWq%Q`qQrfKgHV-׆rHPwx?''x؈HAm7q3NbXU)y%g{8RTfOaڸuqgW2QFnpyyHaWx@8{Ew~dr#gȉIDZqyGqX!}ّ7 z}'i");ZxT֒.ُxEna|8ޅǐAi^uY$S]8MHWTH?}5!4t#PhQxY)U)ˈ~duj)69YÓ ᓕpr9=?i/\4yY}HM7َVRt yeØVYV~&ǜ)9p6XZ8qsXWv sQ]&шч9Y9N؊醜܉?d)HY($g`ٝڡ ; 2)Zif紏2#B99ן`X#(V}&'ĨiY)9 ۉVz (|:avX>HzrH5 8zK9yًHjRB~RF٩KIJFyT.ڨY*ٓ`Jb y5g@iJiצY(7#Ms;hC|:_j 5R:*zd3 Q3t9}n:[j͉'8ubhj~9,hzatt ì p ,PI&z;5n^G: *s"wmD z{64 i ;dꂱ $\VL*ran ú 7k9;~| |۸}{!O+Q[+JiRWk(ȵD wd'n[ʺ!YU8@K먃[ 1{VHK$KKaʹU[%R'DH'`zr7mZ4g fX'[^W:ՕB&3ě"pq|"ۨ L"<$){ ɞN;1ڦAۣMڦ}aeͦ] \M&ڛ–=s;dy]^>}]~ENާ*[R,&du׊N-Z߂*m)^N&MhnM Nڇ~ږ-e>}x.z>|N(ܖE薻|0N^ q79;N5?.L\yи߽LMg=a ߆Mې u-#M>>P4-`1!~#}ܴ,>N.\6ZHȿ36>- ^< oMhߍ-$MZN 6OjN'_.]r2?4k\ک,l..j lc76QCցH +u[ۤ]}>)BԐ8D n]פ!p[$Wyc͛ $cƞ]`|Ľ^wQL A_=@bϪ㚧MJT?﭅Hq *OA?l ) zI +B (|VJy%/kL 001Hc9講;붣#/Ksr!8f"Ыp5Pu^>Q/[hx,^R& JAƲIw qwm'xKó%sO.v>juqRqEo?g*Ox%BEwZ}j\g)_ԧׄ,Ew:_tNw 4(oy="yвU8*DS+O 2S,xe.! _瀂ht4 x$0sfkj%Tșf"h[V02o.lLVxy0Q+w.$-E@Ѕ5^ך.)B)LKRᱼI^߅Ԭem>_PEA Z̾/FoW|AuXH\ Stғ0woY8,P\'G,zb\禎uqeC"*66˧"P>&kjTC 3dv#o!jꤕ[G:z3)0u\A%K'7ed@\¬rcgT92_\ڳY }F J?*.`s!Nܢ5G(Bjmt\QF驹%/̰FdÈ&2άk_/n6!Z%Ёڰ?<:RjӞXW|ǼtI}p!-έ|LkU`hY7F䶀o8M["^@b &\*$$,q| .%a4/ s*^zʝ/h5Ψ#U :t`|@ӟNzQfnu`g#Nۺ\!op  ;sr՚׃,lvc<*釂^<eCGm]CB ֛."97jԿBw(Ρ<#0ȿzT8쨆 7{ӿzHͨ7HQ8K#NRk>"38 /梧곳#e3>gc9ijh4&j?yq?9?j?tKTu3ң h|@K˷k L8>|j&48z;2>ࢸ^«GQGA8ꃈ+4Q!<29@A{%2(tP JGkn˼0lѸ[i:0c$d #= Cp=zF =?D$ІyACr 2Dx;Nĵ䣻<령; ( Rń`EB;QãY BZtB1ETh"RBEG B;j=lh Á ƃ1TConD@HF@DCTK8=R0h23>|Dm1GQn6Y 3OHb)%,4@H*llܴDCzT×t#FxFx L@I{j& I ɁІBЌo4GQCJG=DŽGJbŬG遣dS,*1 +0$J;ŗ("Kz(d|`Դl/gp7ķP8tkF47dL7C˔LJOCDD M{DC5xDŽ@;MT4cK]ŭl9*E_N63 Nخ͐SC+XU?R-vδ FjpQj @tB8m  dCĄF<dR;\8pD70K ,@;JF$Al P.KJޒzt0ʂOP6 P4,B`PXjH;NMNK+AEn`,2s$MyC: ȷ`NUL ?=t|C4čk=,sdGtGDJDGMKˈD>.<ĸg+Qb+VH H<4B::/U0MJHv"aU4 5DTM[M8M9 Bî _%LjuKVЃ0N}DY4CM.#ҪzTI%_w]O/؂2n|=SxWm1BefuV7ZNܰX@ρŹXkU MMim[W-,YN" +;!փXc->+Z-X=X% zMu%T%TZB˔MxEvR챼դC}O=ͦY}[5=dVm8K h ݥ 5HK2C!ZruMŹc²Iϥ^ u۞ >S&]||HیgM:ӘJ>A< Z֫XP6(E_bQ%Yuܢ:ꅠ^^^jy%8}MHӉ쏾 x:_<@dʫ&ۆPZ&Rz^m\fr2e8="`Z ؿU 'V,ƚS M߹M]ߒ_\aVnaΗ;2 b\".b9bW4| 4 QۍNA๪P=a})ݶCѪ-._:S6~ E̛㌉!ccԌ-*݁#\{A\HQP5=;He9,xdc\;QbAԧYs&6,g>eIe]/Kc 6A%C% =ae_b{/ScVKr,f^"7U qNt]o0opqvrs~&P]uE\xgbSD|VQrM34V΁% RGfLaY4VٛYPcc5`n __*^~L=Aiq%i$2ΟZE9Ra0VcZ<\>i!V0Gy2k/Vj%VV;Eg vSZ~d@[aOE]sMbn;!e~ξ瘖f㹆=H+#@F!ޑ2Ȳ>nF&]fM茞u~Sj:jԆ&Cⶋ,+HBk^;{hΖ&%tmnp7&nO1W\GLF`aajAV\^mnxޖf`^Mb_6fTՎ;%uNjkif ryz@c7˷г$ÃpٌIpUUgrm~slHz^Fa^*w^>&ڗ6?FsMm ƹȇ4p(r#G1Ƣ;IL:Xtד:1D CR-DPW'E.47(Vo{>>(n[:h;Jجe$ z ئl"qqI Г;84=tO=NThUWqDU[p H|p28u@]c裡lao.r@q_yg&vF!&`^vS&=q!/rsOr@$E7/;3CvWhl-&Ph lWXWYgp1gpIx _^/h`vG-Gc,>×aFt&qG 6LFlG@7|r9,zSg/{;`OL@$K}rr {QBߤ Uj/ %V~dXacqVbE~ [˧b*/]aʪ YWy$ ,c@HkJR7a\9ϹϡjO5[mr tN@89As>TEox# 4ܳPhjˇ KK+7X1Cc|B(}͢lB !\:sz+ta02U#M83x2qѣ!rGQNmn}u` .m[&Ggd@tww8H7%pb| +\$yA܁t`)01)ER2.TW=2|!.tC0o I[MyM7~  z(O%Nq+IFrA%dc;C%Ku?k?YEMUl*eI)HM72 Kj{sI&%It#|%, >a1Dۢ T4> 8$׸8xΗCCBFݱlf<eܝnIFH d~;mЃ( ϣm)0,%ً‚8t &HOG#Lĩ8zuCQOW A)7yL`!8ar" H/ӝ+zE.BI1Ħ -PeōZhH-*i4u٣>jЊ򔢕ba +\zF"fiYE'ϼrũ|+X|*NgZr:D>XZFR̮b=k6zfrVnbfV+B&J3{E)䆷AD)/Nծe%_+ܕ6<< l`C5zr)1+$+rP\8!M=f D62d>ɣɎƓBԴd0IR匑AO Q)K qM*8 ulB>3p+{C|Q yU1!l-`x#͐(ѫ>H/wbKvN[Wz35gAwxw ߵz5I\И6i}=l:4&lt"P]^ Wo#d+oe{̝̚Ru)%!x/SC#4Gkuy֗6Ƿo M&F%FVX2}!u;X b[q0n*'H<,45|k{PoO6kd,;זBt~"-p!Iz e5:Wc$,we_ZSB .MPDAB9 1Gd4L@L N4 _BO>}sqAPiVXZ)1_ȩ}3zZUR\HE{ܙhn\X0`>N%G4|A!B NFFk)Mp.!LpQ?'XjmLj\~"pLCf&V]NU`GzNȞ !PŴa7%# 2 34~DcL=Fe@NjOlaBFT!"#&$jKkZk~ݣ?VmeZ%o$6VZE!XRaƑe_esUqYj"iLg0`y:gkl nLXϒ|a{nFggütiBρvG`55D^Ypfnd" 'hZ_,'sR`Z`Tb`!]樎bw%ܸaa$zΤ5Ҥz7~l M9TN9K HuPMb>5F)V`\(z@YkaF-@YZp!*>T"[!#F"u"hZVI`Y5tfrĔizjjk@dɖXV"OFiP*R^Ã.l6<娘ZBLx]XS)W:$+޷.H-r' "*/2ͥB]^kWJR#y&GСB45>)abv"(鸔A!> hM״ėhKRlQN<Ʀbb>22 "D)ɂhV)p~a]bPHEBe:F 9G,F\YA{͔wѥΜY?+ԡ@@-+FiT ^76tD` ~"2l̍cN V%m50e:eC."mB9ʊ+"`#pMީ̢ZnVj>gY].ʯZ_\nAp* B D ϵTb4kb6lCOܬҭ*N)y<^oDr(plCDү݈Zښ& L T`"2i.6/ɰ6R('F0ɞ"K؂ ..Qm_[Zo;mX,71\+5͒ 1ɱDq^n;aLb[fٝ5t.>%.F%ZSE2!o#YX75]IU $@sD!s8Crr-FC\םf15ѣ02\&sN]4e(c$5/qCE(ǖPf N3P9_BJtKf0qN-<1zUNoX /(iC@L+3>+r&!DIZ#SU4]t5g$-82P5β 1{aYJPf'v5jF{5-8ăX5K'BKT:c4\uZǶ\]Moc+k foBV@#rf)_Z=@\Y6U7%_`h_v1o{q 5Xs8v\Jsط[u04o5$$_< x]UxKna2vAG1ok\D,daty 2JEć5-jM3m6;6?+,[^x*8$Ph֋QsxCt *ҍȎ^go5x©I,rwsig>GǘJ!#u"7W]Vfo~7/{菾~aӯ~?=T 2-2 O\B>AK~kEZ^P 5Cr+=+@8`%T&!F8F1BLbƊ,<9$Ɏ$9xR/tdYe0qوgϊ$ `N!{HJS2IBevA9rĚGz0eX/lU)V,Nܺs׳h#څٲfT|+ldbď!G,`efNxȍ+a6V@بWUd̂E-6j\+~~tarvu%c5kzy†d{iǗr}57\sEE(z/5^1*("5: @ -K-()fE;Il 2/{?HHJ$$ɵB|~"Ar@8q)6ڰ JE5|Q+iǃ4TE'">#,&#LQ%ꨌJt7(*B: O#Q@]NJUQ>yFQU"X0tCDm6HG4$UZ20uvM]Iְ>m.Tm[U"n&(33jWԒV8WeWXUnv2>md$ q8╘},R-B҈*PmݕN]WU9#ja{\uWy-׈拙 =!#`)fj3L#;&cCxdJO%9uS畝m,N7 l!xzo¢Zѭ^}ȹwA8Ы[kmQq l9,kί둾*& +QV[\fyB5)lԪxJ<8iwȍ 22׼cS&)[UZoe &E}&R;(p&*ފ|7Էx[C01Cr8=}Gس e7ift1J꣈KG,A[5NhMNtSS2$OqM]8d(jD*xA)"&B:$k[F?OqMAdLX U1l&yhbLU}*;7W0#|4 #CREl03YS/6+HCqQ'icj}g:Nr0X<$ү>p $6< uFB`?(#:yFW"Xb.خa`ue3WC=GfMf!ό&Ǧjf=2 P#A3.Yl{\GA K? 8qE$*!DAʉ氢*"BNB5RwYVU dȒaĆSdS<O-Lna-V!µgt4 r]GHMm՝뀈^K-j~)|tJd[oW ]W[!_#*QJz2R{w!jjY8և`Uf!8i%zU>[k-[ɶRvMo} _ތGVe#B) jԊvb]^O#/Eh{)ێđ[KXZ>@Uj};FvDr+'\+[ |o=i+ROZzN/WR!-| I%~'Oc?9Ɣg\xkH}Y8,{A+}XEd-@If8Z U,c8]-Jػ0/afA0Qv旊6 3׷--:A{itJdӫ(1f?2C׈#u:;faJ8؜u2?[Y^Pif:$vD c{3m^ERKGq%GjSXf=.o;}օjyR̚~Q6ln嚃&]ޣBydiL4&$OKwޑ4W`l;2w̫|a$=(o#T#[D'74|O]s;4U[̩<;t}:A.Mx+TLzF}jזgFD"S|yN/k7|uwu)QOGz Vn'wɅ᝕x.^ɍ/osN^\'5 ntW cL3f+ϼ>|w}o?c {fݚe|5 |w/c37c)6XeŨOD`/ԏXNP"~-b.eؖr~h_ KEM.iJ+@n~!>LP"F0 WN* Mltsd#PU,pҏ z˭p M源+MŠrL ЄԐW""nqHOyU {l'4|N( # W  0( ?QՈ1 QqgT]P`&"úKNR0v~ԨNhZl4%Bk@1nx/=MѮP Qubh ձln.'B Pp=qwf1 yѩo!#r&!ТJ"14"Uw D] &Q%) d !qyr|RyEP)u)#Q. 5\q *o%+Kz%WR,borgprg.N)3)r"*k*3p% ʾM1&PJ22j222Lr"ҩ +sQ C9jn/X$$=#p9b!N_6kSjRxsx2iM3O489 !8)q:5F5W$5G1g+YA%P Ok7Ң7sGs(>?s#K:= * ?7#$;N;<ϳ3U6C)!c'ˋ>9DS/U4OS'3i*b̥%eB(_B+4ֈt-O|=t S<:k4DkG:J!l$sI}t,dvTȳ4Hi1k"^M#N9tNCADt33O9*)U I3@`V#Q+"Lq:Ϭ6tMMSݴeTIu>L/3UsUMJyu`[P5b5S9жXUXB 2USux<TCQ4ZeZUZeO-[ >h*V  ݰ$+uP8r] !$^t ٔY?Z>6mQUuat`.[}##PuKS)#+]R% ['y#Bɮ37VMFܗ{!u^"H.<iixHܻq__sUӛv|9#Uɓ@_I&D[O:x|B-tqLc|ZͅΉ˯G)T@U,I;f'-q9jh\ SFos]$|v=(`:O1:z9|UD}yzRfn]oe\dM*}%=8w  #0`ݥ8՜"+]:\<{U̥&]O:۝!Zr҃e۹Ĺq7!&+='}́ݻح<`KuRp` {b.Ñ5ַ1=S]Z]LfB;PN!O\3^b+nacawVt>q$پQ"{}團0^G,m `꡽._]EJOl7P0ѾD7"# . (!ᾢޙdsh>5N?|+Oz!?ꇶc9S+N`\<> Ÿ .… 5yσ@~(č;>l1$",ʕ,[tye#N/s%Ș%m 4Џ,imF8t&̖Y 64$ώ?aZ2ҍ^-3Qlۢk5]ظԍ<׶(2d̎YAel/ɔ+[l0f ;'(1P@$)4K[)k&Y/n!>sdey /]Ȗ#U~)Hug "_xXv V%MШC^%cn) u DRP.aG$jXaEj N'mhk 'R5{9M R9I=JGik|Rǩtzb 㞓Aye#geіvgթVj*_RVAd:iOQNzRSOqdSUL*Ҳ͊j!ZiWZd`>99vY~ދ+h V"V+Q]&˭R xp!1mH#+h]=%[~67X b>{-~P_nԇbg$KM+K=B<뿆.IvMYʖdTagv<.9!̃Z,yW@ &!|_;g>t91KP,0| BWǭqG^"Ȣƺl?P @*% /%{ 4Y"B8MpJDVF~_^HJ]6.>̇zK"? kH4q  J0@:d{0{&&Y tҧ&. ] [BQ\$;P}`' rp]4 ̻,R J@p儒Z$(Y! 7rBTih8[Vҏl7S'I( =0L@%Q2qLYZ8GMYsHpSQma;;6p8i`D#U\fA+GPѢJGn$TDYуz~6?sz41{]=HӤ%SĖեÄ R=)&@V -'xdy =Ⱦ vnyG!,R՗q3]nu:;ֱjv%/} V:4hG9ͺ@6be^RECMZiz]߉g|)YjܬsCYz':nPqcizZAƷkۘz:L68RJN+ЬcHUd`ns`D1qm w&|>]j$Thck/Rkp<]C^,r#`x2 U^WJ00iKƄq^Q6T#ŸUpY☫{-k'`a$?YU{24VȆw+DGОgZ\faqKO8'X∃r"+ZsJ$)OI{פ2YRe&\5_4O͝,fQkԎkpud`xLbu }-!F_.Vl5Ub{6иmAN(q5JnAui-^Xausgەf]M|U%!;m ǛuiAܑ hO Io|^R@\cX}cy;m)?R-"7N#P 37yy܅3<17b Xa^?{4\"=侦7ׅ}ZEz/j'/K.8·py:UV:zDnIV>| kȝ#?xB/h~9벚MNT '}O?V"~Zܣ}m Zy#0׌RǼMpRBl0t0gDϖiyvXE(Ї}}1wJwa X\G~'C @Cu"prbش3y:Uv|UWzpW}8+8=i%ENL]7qKWq!(uWxVl J5 `+J9d?{o4T"_!fJ̠*E}!,EP%1nX${VhI x9U3WxL 1(&g2h6{[lh~Njy}yv8/ALHtxz&{+[V7jlSb !-%Ve5ardz{fHs(WoZ%kwLz(+8WX*g,IVyh,1Wa1*mxT%XisՑp2A(4']M`Gx"4|Fq%aq̒1X*\8xT(׋Xw uP2136`6vAT^ѐy%|ƄSd6(Gx%F9-_6&8?zgjO6&mK=i8^A)>B}80)y>JelYc`,H4$踒?e<rg='|fNxADo!q[(~HZ;7藻G^eIhduQ8;Qvlg핛Zy9{5'XY8 |if:y!IeYR% ?̩DɒgXnXc癖鎙1]@'a(!PFJsFb?1qb9hIhɛZ"iWǟ_"eǗ)`Y@'"Xɢ'1y$:ǡ_Y&y<&z呢EJtϤ]1Z3:5z[Z?g0Y{GIJ9M" RR:Q1S Zv)B]ʧ$ QE8ꤔQF]Ɍy(}&E1ᶄtYD*<`URy fWuTZ@LF DV*R*~ڪ艑GY]@aGʫUMcMX[֩*yӬ!ڤgYȪٚ89GG~hP檫י6eiz]/bۆkÙ5\x;z-;R ЮI\!_+F_J&yokvꯧ K*Rb`@H Vpx@5N(#Zi|!/2wa(k :{ڳ_a dQ'}Xລ}Yl+?Q6byK̈́n$a +WsɤUFH;ghe= kڄ+;nA;"1 @XE>Ѕ_~ʂUGڻYU MsZ{A4Żsiڼ51ɹ;@rث'%NJJ*JiӄY+ֳD"ZetT¬M ]V*ʻbE,Rh1- 7lʊ'!WK /b B7v4NI  wp&i,aQmvsB |ʄĔR[+L:"[<1d{ZHwB6S 0:~]64z F H[EKr2G)6)wZ'(R,LƔ Gl==<<4GW>Ez\ǐX3K|~tysܡ-!̫ BƒR=r@cfl9mge4=љ,mkk"a-|j$-\|55̊ɣ/e=]qMP3Imԓ%|Q(xUpJlcfnj̆=3 8D͡͡ WyT=;a"ԫ\+cفe=gLY~,[틜u}b|]l|ͦ\V $%Av]#\Y͠(DS-1~ۺ3EN.-9<ɫM+Yj`*l#i)&TVe[Ay'n U>ί[Ѝ-u799=* ޜ%Dǭ `,.^5oGpH!'y AŒVXN"o>NfU].ca;X7ӛb#4h^G*.~(+' ѵ:ҫIF7ZJaP2qE,opG׍ϵ [^OV +/Z{ҍ0Dk F>Eof; n[V<.NHfŇ2?;{$h::ŭ1~<_/]r?oY$̨Cg'RoY? ?4r.O:QٜLNW,b $XA .dC%NX?5n(G!E#A ULpD)e$Ҡ̓V F8ZӨO y6 4(^ǐ-C(SN zH WaK\XTb҂VDdZ@Ul\ qeZmޙMw5ŗҎ%ĊƀS6+e̙rHKٶa˺cjF4߁Y_}l˦̚Uf`#Z{`¾bEV]>V6I< ^:odTl4VؔwI};9Pj"\S- K)l\Њh'XRK;PNkRQċś(JFb)qH"H s H T"e.ʇhr"*gĪB/ 5͠^EDRѺ1Q4M? ³O0 '/ljcd6CPJ+%HTR40H@4 LĴtņ*Ɋ3(D>M!_U0҂R0¨1&s1"'Uv["1OMI55VEOT%Ձ\vX| -Fq ́^9SXgYӠAݞ=F 4l%uw^gֳMEBQ*5uc@4Dפ.`dRX߁:5nXb_fff>hqNI Кůj-%]SGnL_m^<{>90i[{/> =隮z2B"Ѳ㗿Ḱ~J?74#r?~=3 <&x?c3{*.ӧ2$!1љ>*!CA;H l=x=;V+?(<~ZX+=;J5[;<}j @*rK'Z'zA)(8Y ($+tŽ3B$;?:l>;{FLYCND7?t<\#>9@bpfk8Q#CDCJbCCIčDzAQĕCZ=<8`rZS\ (?kW(oS.t%u >v3"CrAh0F5DC{xF$<%\7 C5+k oLP{|G`3.|oHٙ),xG$ldKIȉC!H= g lnIśrEAB4J1>]h7EzJʢG"i BS8$$#˅qFӰ)T8D3˜ H$ʢĻlLʁC+üKL cFĸviIxI!:T:r:>,= DcML MM*!PdŁyh[&~ N(FLhElH3K6*ˠd4A=NJ$ ŋDOQO *M6M1Um|oìdPCKADʺiGP /P͠M^ :ǶJMB\pZ˕Ȑ EKQηR555җBҤ{ HS0P5zR(3ڪM`k{AYΊ.t$&h8E ,T#gD/K>>T Ur3A DFaRŤHID70TL%^h܉ 2+uӠR5 }0ӓ$U@\͋]Ńp@PWSޔ`JO ӳ fPV #$}jPF"VZQsKѕq%/s=׸R ?ȀDMExP{S*VX={:MKcN՟F8`RV؃Ȗ#gVb@(3ce`(X6}<<&E `9&b 6c`-] 㞝FKP FbDWv^ҴȠEcyFر#/X1ee@CcǨE=%aVVY|宫'eD+E]&cmeEX/ap5 cvG N `fQ.z e TF_Dh>P?Nj1g#tvSU%>^gFv74gcm=;Ne_l%dn6N|z\y-AJpjն ]xg;4m vi<B ^jVf%bZZ0ޮ'A^LfdWyAjP""}djUʓ\7]|荔f酶 ZP7&WDNVhw~3a`FZ7FLtx` ݱ&]fhv.` ˮ`?$lsc㒮C`FԎe`mhu+TmJYCx@2'鵃VziDahŷc6XFYaa f_r>o]5Cx$>p鮄^xdXo?AםV I>kXٮpXCf2p.\)fiM{y"rk@o"hgpkH1^ W,Qo r?߯GqwVl}dn~604VqjJ1d:/$P]`"AO*C'rj'ٴ OGt(M[cL/Eqݱ!w6oPvS?&mipkO(^/6i^Etɾ6otN? j&.In_yl!9w0S13xvoLWpFtg2h_f_07BSU+6Ygǔ QQ߮؜-' &'uTVƥQ./z(agHZ ~JSY-mb`{m$>̮}T%wE:F-]{vd ByzN\%&f|χq.{}* r*Tok}}OW?|O^ކWE-﹜ ~jڳ*Uh"p "Lp`#BłVȰ`Â:6 )2bGVlp$˖.Rlծ&!˞.} WLt)ӦN*u*ժaͪU+Ƭ 1 +wkx}l& n_"kޅ8#Ww5N6(yn- 7r>.Z[b<[6AIwZcx8ЁI@(yb|GBa |V˘(}H` ld^GEeL%0"ɫxI!/ˉW oWD /B/ڤ'I3 hJ 561s;%~y+:OўH3L gZ66t}a]$A>]}Pt:nRtZ#.9M@̚d,H ݚV6"~ԭ^{Ig*Z>r*Zb*=ҝ]jau6?6Xzi&WMKm`ZKGgT@"ğ ,-A$͞BH"R(k]*5٤0,0pL4y?O!`-^ISUév &euBOY8s|!Oܾ=~;x 蒄TՔ7jM]7f"C$ǽ,֩ީxn 2O^m8/ GGmYmYG@;^e%e-z-ON̳u}l(Sb4|!kn}nD4cܛohW|+~Y$kQmEK D^ݱ11ۙ%^B\i_Q\oLgYU|U 9kU [EF`Lϴ+Y`rLcf͟`I-Y]hUIːV N B\z@\z \2aPh}B_Y9WCEU2a!ܜWfpX.aQBTڅW!DGJQ`. D##ց5iYZ`5 \`i  ϔb"*މ*AHf10*D-D.".*a bݩ:1 uA@Y=ߠmWX#…\H!88AOfDLI9 "A c "I!-Ac%*ANB^\& &_C>$$4fQEZd aku@xE%T%]ajen_3dXDΤQ|c^!Nf@7gNdZ&BL5_e1(" FgffA㍀D`eaETαd`-DPŦY2¥Iy qE$fjY $PjLk2^CZA_04NfnVF*D+\[,&' b!b[]uvg[A #OAfݜx2 yu!I6&SʧzYb:̥hQ=hB#aYv agA d]ZwΝB^ZeX6͆D`gbOo"ؤ]c#BUN"jc⌒a/ef*BXgL6h%.x%C g$,ef4Y)~eD gL5A''zXV-"ƌYc.#@Z\O~'fvID bѼg*"(q6*R (i?=/zji S]ib՞N(r]PG401z{X*NU%Bh)nQD&ߚJ:(:3ifö귾r,a{Wig`+Fon$l"|ްc^k&ps!ZaYk#D"qgAe.ޛ_£"(B} )Ȓd fO-p #Պ0,hDJ,")Z V, RI:=BDm#Ν^-`dإl(&ڭd^*@,F'ZnPfT#mQrkZK^nPw+ڣFI.k9&9>+ׂ&T#f D>炮&i-.֭ݪ..jIm+XvGFlHN'zM Z8ljL2o_Hg@] S4ďv/cB6p%-[ij"ÓjIo6.T6bNA8GJ}}G_Z= 0޺fk>/I+bo&ģ. Ci~*Sa&t@FZ0jb(O0"vp}0S1.dpڱ ;&1o h\̍ gX1º׋7jM~/ۄ/!7.~##kI, 1t',BeJCCgJ)zsEc8s 3:{&XLGL`)J!m?Qo5xhlg*uRH6jx"s! .Ljoz~N, lD45ö]߬`E{8_PXAjoy6aWv(*-繏k3B9L@4\]#3oBb:9NK4|X$z7Ҧ4no#2/NmyaȲǺAr1/Dpq$ ^5/w-Q2&`)zgB;]vEz/!p{,v0ao->!ŷTܣ5 m';sOK;X9z4*+%?'gydT2D;\>lwO|Sqa93w>=9i^`?B~p;OIfy= *-&c {D>>蓽z>cwy!}ݷ X`T4/;"~#d@+<?=(CΩ}k<D 4xaB 6"heÁVx#C:lɫ 5څ2d20@@FlDfN;yAC5zT;K6}G 5@N#4bVv̈lZ%., .):Ȫ-ȶBf*˹UlAhdM$p`a DXWV3w&0"ʞ=o1$В{m7I׶}w£y'u[~ VsF̅/ۢǼ b%wr u ]C_vw_}A vvf ߿4ĺ￞LC#DRZ"`h+ 5< 8˩8 k$R d=K50\TE"\ о R~ J,|2 Ë6d@*<3(1D*%3*,BF &jH TG4 D/ދO L%tRNlD +LUDd$TbIF^i\uSC6 9:Ӌ,+P],T!޺@كDGUWj!22K[<,?G[>-ovI* S #-6&b#By^mjĚD9-:=7VZ C6 ɓ]ht?L-KwH^(Jx6Wܰ|SWiuZmi\ `7tata%֐cXV0 l Gp&d<\szZ\7io6޾-ޞ}^U._1k X7\z7_*QMXw1;@6;R 8Q 5pcdׂTB9RY\Pۘ b79hW!|qV [3*68ħd Z8﫩Zk.u*[8 W+TF(-mG (T+cxE"HpA@NQwU"0qH2ёF_ <*;FXMJ}#VD7:Bgq(OC@ @dpE`#yHx & 0$ Ro &@,,_ZS4b XYϲr( GrsKs {E)'?(CF;svsGe W, ďDA* Ɗ̢Ea U6%9ON§>hs.EX<"7=5-\Ƅ(2 }\4O-3tL)҆0U WRI1)9r* iٚɴ+*sמ1 R;SQLH xF멙͡ޕ+0Q΋-:^#Q(C`2wɄ̪E e26"X]e>m4{.fV[>CZrnna {X`WdU\;SɥV԰Nt=hשvk#F7:xXQZJovv59hc1)>m̧@ePRU %"rlflͪ3kϵo_FLRF˖ַLf>/ˠ/+N_ 9;Yc D$x7&hk2?-Tp!7C2l}tVvӝSDoܵUcA~="+27j+_]]p*l~lr׻.}wٹWэn)}L'X9["JdWv$z_pB@7^ϲ.[,0%t޳,,kx!Oߏ%dw^XbFO/>$NS(FfcO\.<[TlnOxF%z* K fZ2ҔϻnR?D ox H~F>8e~pui~jsOL}Z!p'oҰ`.h V/0^y. u1p0b k*p /Bx_bORnV  zP!n/ 2 Kp'of (\;M @N  e'"잫 ^0dIoNo 0 #0M ŃѾi0"J!6Q >%뎴=DqB&PNq3JJd2Qrkf{dI* c! o# OL! "#!#ɱ̑3VP p^X +k5L T!: 4q/r^q!qGge4O"scSh@7N-4y |&<=(I+e52T=DM"r>[Ll1R8QL549k9CJt?lDAGNב;kHmk ϶<LC˭8pJ1HnK6?KCxppL?#z8< p,kT ~Cnr4mXCjO O3"dWiu-CDwu>Խ3'*2uE6UYS + +.`4!t y JRtOP&N _1uh\v`f Nbv&tAGr!4HPBEbASdv" 5Ub1SsZ4^>ui 'NZmY+06GB5;1RՠBoHGUvb;&bo3v*c4)<ZFyK6[(12w>.sFCWttb+-6N]uTozuh3m*b +%NW*7v%VEz;wlza-`jMhB{{1Mu}aG}ݷoSsIip0ij`p1#KTE5'X{񠕅WnE5o!$a܀ [v 6}.y7x'9]igRJhe8q.uh|$ È@m`ͷ ar՗Owo!$=KX/cXxSx1c(yv;xx.؊[xx^X8踎ՂYf*|vZq2o? gՐ x77t}xY˰Y+Y}⎛@T8tSLBo wQqog빙1 95L+Qy5xtzuz_oor qVeD dNI[;h٩;7Yu[Ԥ'YUr zlgĦ*|Aw-ڝgYL\JoySU4L ZJ&sBSۧ5UwpBFG^3{JZyxe;d8% #Em{$y[Wpb+Iz w۳~ מCu`[۰k@yX;lyL|[ٛdܻ;5 [vaBd;1wv u(YnR;,֛/_&NOꎅhmlsV:q'@:'IK]@届{ALVf= 8BWB6k' 12 l!(φc趃o@ Jr-)v$GRE.M@( b⑍4Z Cf7fۈJc$(c"`aENdފ"9jJ S{_H21ZeBt7>p!8[1cbv`J154 #M?&*Nk\8&sܤJNS"a;)Jzqece 6&SZH txFH MԁSh,:ʆ4tL-0"&=lZKO.}c ԦtPKPU<:ʨ&a/4vfUpB3 nUXq#>ِ󬷛hd5}^źn/T@FX6Čx3d:$ndj3 i9O]m]wL*9eMd7(6=/RmǑ93kKVm:Yx}nY€]}a-ӏKFG%!وhbh''\ZfpgCNn0/S'2:ƀQ(h.zs-c1h)8Rwז_ؓqt؆vSvnΘy{}Vc;v H|o#L+ I%m%!x牤vgllV'}VTBlIǐ$*l De4GadB1{ Wv(΢{HuqS'[gE|4yplnWbW&% G_][ԒAryaX9L+X9x瘍Y.yK61.Xy䀦hP!W%+֕0ACN3rR:9qlMِJKux[b|$kTUhքe+Y0Nx]_H)tjh醨yJ]|ӓ nȔilO P"?OX9E9 pwa~Y,q'YǜYu(7n9^^s#X"}?g7Mb&wSF(gIbYqəىۈ*j(xW" WvPT9+2(sT*{Yq.ؖ<*ɟa7ba2 頶XK88Wpami9JOdJq V g(c *gpi9t2o{}ّE:x 8:mjz_u5D) @x*U59*Sy(C*x:VxYιJJc*aȇԪȈ'S;AיWq J٤bsZmzڥp:,Hfaբrzf9j>KvJ$z{ mKwʫ$*yLnY: 2Q鈵87xȚ6: `֙xt1:#Jh(!HW:{G 4a یM+`=ZյţOVPeڐ}Ƞ`rQ`RJ͆f5h+@WD@ 3aK{{jʸgK-r[;끰w{d["Zzq 5{1i7Fi Kꚩn> '/{!07e(0;F;3+$;{gdɽT'>,KkƗ~(rڇҾRif~3a Vc|T }A 1Y(K4<3\':7lW{) KJ4 #Ÿh=KZX+71 2j9n$\]t\=}y-ç 1<Fxt M |-SCq]=6cOM8Ues$pY;k4 b? VyȒެ=?ۇ` (t ѻ߽>)e." -y$V$3n᢭4 y /aׁ}_aR:h>tڍx2`9;w?޺ANF"CwA{|p]h# LJU^Iz$.p*)n5Zp΂>V<> l?$@:j$oQօͰ !Ldq0$,^ߞzz㨞gQwz;i=\';FJS@A7-!x1.?觫쁒?ڍl^=۵ȶպdrrؼHk$?M,…/H>>Uv^B ' #M0p.LMeqx>ψKҳ~f1Q!޷*^^1>0i1/޻s7O<=Y}>ۆ!joXOrc^V.vx^M9nwUIoqXRx^̉Z鞅zemWאuQbk=Fr R$4d9;S$Yĸ԰l5md/v=:kHh&PT h"m$$q-ivExg3j+1jb6-j)w0:Y{)2ʶ_kXmK:*bek[92Ùg,B<&GZG |h} T7abzSd(gAb51];eyL5^\x5ݍ7j*>F(]"39p+U?2-[Nn&~3VR%flRjƝ5c,XYqN4wsy\Ϯ*f].]zuS\W3ikd _IS#XCu\ɯ6E&] 6U\'qSgS{ϘaTk&ccٚt*'fg[:?Nw-k{cܶ]jT9ܻs/[6آhVPKxth{1d7A&uk٭aخ߅sJqKܷŵcnEr=Ny\S"yL~`Mg3mqZNJ5f5=3o#jCce]'d=?9?FQ1#:,op뭯삧;=o.C!T-h3~) [mՎ2g8k|RR$7#'F'">%^ݓy~mz홗| =y': KzTӏ #È7s= C8%%k?ǻ@[7Z9<48>?k?j: @;:MSS[(T3s@vs 3:CSFx72c  ,{-وqoQa12sŷEZGE&Eb@K,y?G EQAkGٻAab5c̾k{i#Odm% lJ«²G PɟHЪHHHTF xLCD:ġʒ@ Tɦ̀y_CIDG)`"JD\K]iKz/,JNDSt54:I V 4L;ɉ[=5Z`IԊ̼)$LG̦ j3;LBF$I]K!,26lʙ!76E$}h$+죳bSNzaN T4N^%lŅ/ʔOB=|NwKt01.ezNJETK3OHN*ɄJekqҥ)5JR =ҰMKIڄ:tQASs,%PRTRB>UN3E5PTOSAMNZSR=%JSOKiE'rASU eS!SNcMd7dVgEԟ@5 %BCNZM%2J% WJ%Hs.tԼ#VZDDwEVPM3Q)=LXVam!Q3TC٤JLIu5NK5a]W4QҔL xue5Yؓ>T-iԒ/.єW-Z1͋UeXkY98OBZ˓AWú V|R!k)WR%gڧeO~dWeFC [\Y؝X][KifXEC~A}[.UYGeV_Й^B\T\= GB۞\yz]Ѻu ]UAa Kߵ/ \0sݯmL\Ĕ#=[594U!mȍȡM^k޾ֿ5}ro^ڭ^_ +[u]mW˅[vtm_U[)YX#a`9ca5*F,. <.vD/`\ۊV '53FXeP:Zmc7~ԛЗ=O"mM5+NSe`j./>Xѐ\[vZ\~]{%bcG\t=U%|J^V> cPбdf.垄hdutec%Y . N5vJDgqPaL\` [(yB9g6|&if0f}_Dpg 5b"մMpd]`MGTvh|i.gkNB.iz=tgE ndSh>\ٙFZDfݬ4adٸՁ]fxɢϣ.gym}jVk SCN4^hwE'Ɯ#Ix8P݋e붾緆DỆقvVu>].6bȄQ9^ՆbɪUn9v*V(͞ήMUmTY|jl6ݹ&KS-MZmr[^Ql>~W(z#nLA_M'Pfh=M6U0mJiLn.a v‹.;$V`V i==iFen>~>sNDuk3pO^7y& li&pq_־J^v\]? }Ԥ] Wh&NELU}`f%uq~q] ^rᔋРq6EO²^d4RA$Xr%~=7qs6@OM\&-PiIx=LnH%ڮcKq)7[t,KKOu-rF@AS-I:O׌ipy!Up|^!.%5c:txowQWt^nI>qHv.xv JFDg'rq7>\IGw_?Pa1px/HKXSoth$xpOx.nMH}'y zuDBzqvC+Wsz~LO_18ur!ӶPolGpPMyu[{}]'?wƿ{=ts8{:^v|gWuXvşy6dmoy2M_pHjOΟ8YfT5ݸI|Yδog_TWdhx636[*>r|cFdfWsoiߌ]&lD B,2l!Ĉ J b)22d̂U,Ycu2g6|"͜:uȒØ{6aOGsn@XJOZ^mR)J7H@`j\RdIڸ3bU\/.l0bq3n_LP0fo"m*#H$30kŒo̒QϔZ3LIc4*ڪZk=UmmS $h;xǓW4)״I:rwi~?}TngTT R$XʍQshAarMU55JxX|!_hy=L1ZBZI)j[C|thm">;VCK—18XEܓGD!nIfitocxoyC/h ሐxV֣=4hyZAVNfPPaB>eNU| 9Na=&afJ#uIgڄ/gz(&+dC„a,RQXP UpKZTfQfTk*Ї%ڊח/x8,l%- J_},#1=zf ,Lf19(%'1AJ[u2 \\*rΧhCNJjW (SLnǾyrMPL̉ueuWv4 =}-QV=-jGR uDZSm_s7ou2Zvm-w.:'qHViIzkρ5M7gI^桳ƚ7߾zz؛Nvɏ]<sώ};:b'\[axxDK<h%>ħcԷ:yO i r!jq! HHc$iMf dN>C}Tq"ĕ匂(=J֋ f'Ԟ8ID&˪B5('dк ؼ FR8 *I΍Ĝ4:ΈWM "K3#YIHbn%?'ɽf.虗T4ݕ0'vhMi\3p(T#K.-CW}1#AdD @gyHb< MCFdT\RԛL$qFS,UԉW;yd5+A:)FPzA\@S Ck jI< 6d (𬺞Bڌgӳ.@)ƇѴ'2;֕gɋ-S 8"Y7-( 7,C&í) -GVZ_ QC]&7 xyZ-6&|1 aGQp_Dy (q\g]6Q\-k9}%;Gx8^@%Ʈn7Nu!< 5ͳr \}&ZKSV)mI^.u ngN3u\B&HcCeBtd'G:.[s<8P;DԩrJM=^lt((n;띵nkZOV6FW嬃^6rƾ"[@SwBpbm;vv/jzܮ~w tZ ڵZxk3p%sV8owp&! n.zϞfn-dٶKᐋ\N+ҫ[5P1c>5Roήqyq#m 4 ^/9Rq/‹O$j0׵hd&\qC㮅MڙX}=^n3jȽ;M-MkrMO)UF[^nhM_ļOlٗ|c7N }< 3,zWz^{Kr @NnmO}KtI(aR>H/:a?>( [_|"8:ƚ-~ JD##*sqEVc>>`= $9Ab֡@T( Y 8ZZc %%FrFH cqH0D1 }Y>Zܨ)Ec( kiLbcTcͰ_a%"F:vFU$eR ͦAFء]D/1ITO=%RM YΞ?&cKΚLdM!M"N~d`QNNEtL %!HbQ9^~R:Z1z@dMbH&XHjDhf)e()f)M^hhREZfLM=xft& nn6A0 }fUgU'g\ (rz%K:'Avgbge`qh}R#]Ŧz{^mA@.03'qvXn}'g-qDO8X!~^/'Ng5EỲ&{tsT5em(ZkZdψ#ܽ`1Z%~2p5nr쨻U&4A)WM)U#TYBk1@8) fqWz)rhpf)il駔|, /0&)ZՉvn)'uj2g^ॼ㩞u%d71iF^%ZqiF͕楤6l꘶[R"i}>JhmAXj$6MJ#g!UM*DI+`v.+ ډ6D*o:,j\mZܹjkkdr[xW6 &vF"&LR&ֈP2 ll;&k),QkhJĖo(cƖml]hѠՆ,j ɮ+lfXb&@޽6 bFyB*N{ k 5/ >ӎ*}Z,՚#FQIy+(n؆%(mPN,V CLzb&^E*,@D!SN,n2-q>gD팲Bl=e.l5AfnS(^XOD2Տas p/kW%+ -1WkOB\B/J:(AT@D0U&Śjk~ljzoƑڟm/ . -rR.|6<&. 6E6;,3 D_R'.)>6i/(*k # A0 í*ȥl]NDwd2&Bhq[%O㲩:Kj.ZZ11z J#3| nR[ k F9!o#7E34G4O35W50\1qD$#58399\66[oB,/9dz<3=׳=!' 7C#=@4AAD>PIs)G؃?C(aIA=u@`4aF6GtB*APH%䔴aA 6jDMF5fFDDj5Ezs-1HI4t+6  Q\5 @uU3A`Vs5DDtJDScDZtE44u#`-4 ju#X"5)W7̃F_75[^tF/$Y?b+H[/F@cG6BuNgufAeFB#L6 i_`/_6Cva ICcGVBB XtSY(LLw}v:(7 g\G^S4 tjSjvk,! 6GtQbWyS'DrxUl@OL&]sweKkh6E7S@7ԃ?79Ft]vw8<8GO8l'mv+2~s#`pkvC8gr8A5s/5d8wt=Low#ݸ@wG_l@08jo8zgECwf0}?~kG}7AoSjø[?oxx Յo98u_v`)FĒSroUyVk9^GFL]SvOy4{9yx+5n3G/: @LM Atax{KD{EGuyxfUzv5Nu^;@z#;C3/;7?{q%;O;W_{H;o;w{_h;;;ǻ;3;绾]@!,[22>?I# GHS&&2))5곴++700h1FrGK292ʁ'EFp2H 4K)!'ǝ"!x )RA 0< s@p@U * X0j4Bׄ  a4˷߿ LÈ+^̸ǐ#KL˘3k/?,4Ѩ615լ~ [BG׎-pܤwxpW-|HƛF|yg];tݫBs:ǣ?I GHSBCM&&2$67B09J))5곴++7 ,>AM01;?@J00<12<[\f# @(!FT@ CxpEHp`LJQɓC$K))͛T9͊т'(B p)Vf˵k `Og@A oH;0B -`.A ,0aD̋ &Jx$ɞ!, 22$>?IBCM$12<67BGHS09J=AM&&2,,8))5곴++7)KLW?@J00<01;#[\f Pp$hhp@ t"$N<@8$XP* f`YE,HfL -bgClaRPJs W;Z b@Ύ  ׂT,(hA`BDރ-.Xa0 !),t++,+,,,,,,,,,,,,,,,,,,++++**))((''''''''''''''(((())))++//112222222222222222222222222222225588DCMFTJ\N`IdDm=u94.*&)҅,.0.4- ~~~ ~~~ ~ ~ ~} } | | y r m m m l k l l kie*a6[@S?H<@765//)*''''''''''&'&'&'%&#$"#"!"!###~e Q<*"  #AB:(1.B)R#^bdeeb P #>#)+)))))))))))))))))))))))))***---111888<<V!k>!~(F Df#@ 4MB BTIYBv A 7`cA5tuod^}o!zgŗ|H@tbETԟVieB `lME9Ђ!9FP($Q1yDbU`nP].P_9Y! IH9I6EIДyniꩨek*ЗH&@eX3m&&RmbrkwJNJ.B h\.w#Vn(Wwƪ$)C ߱e")KB$@$%L#j]P_6Ta {Zn&0b,b+e Mk@(u%r(!9.Iva!iqcJ;mj:ÆtTIa ÿa^ߴ5׬\J76T-^ޡn*˓|H7gA:w  d#+jJ =+k*oh-KGDtr]w# sHpwoR !:G2ӜQJSSu}!_iE.qmܵ{'B̳&o *+_J>IN`I>}hF%D}I PL@i>2MAH̢AS ᠭrB5r`! #˨Pb,XE~$ñADA';A!E"̈3 )y@;\N[:0ErG7V }r /O@sC#H&Pd)ā $%X!S%U|&=nV: :tP495nk{ ,TL"kHB ц$IEdlY4RɃs} &Y͎z%ɁIaRعN&sd{U/fU!D zV#_ H4Γ'@b: X(=+d}Oזh;,a [ $F ĆLvPbqyב"CBb<RpLkjju[W%Bj6Dݜr`y..0֮'|$4\iE :J,Haom!)3:@ac"CL$h겦+`)(AH ;Y.  hw`8ƉƢ8۔+E$k=bşE{DW MD%kԧ6BO8ā* C4nRJ&7@(.pTg=oqx{ZHS mtr9cvNr"ь9 d pg]ѢUs4سԌHA1/mtq=f?zڮ'RcUG':EVτHTK>[:εP |gaۣw͙*{@Uih'6&ӤR Pmu7e:n/qYelH4֍շw;8dyaU+BxRRuh >+wȋ ɫVWWO(/]Q:G^cϹ+L} 0f.V ElC=BBP߶ClO *g?$~pfQ0sO}~kXzg]^s{f>4D`xQcWM1v AGvtu`ط\1UzI}ַTh/SFpV&yMH d5겂8тeQSMa3hif5L?` 1Kt 2UKȄ쇇c!~V*WSDžh7&'m瓁MiU7lxn(77j=w)t$|XSrY؄x<n7&؈x $Eagp{oe8.|ySTGԋ(u{dL h(6:CXq#bŸq(2g(;Jb{X&f7{bJBq1r"PgM7'.Owȏ4ihu!Î. p 2#i}2|hŒ‘OyQI블VH})_[!9Xj*淐CL6CmcAQO$DY&, AzHږy3$xP(vkq#Hq~!=uTrDmI ^JɕuGW ;Ã9P !x"- !Q|i aؙٝ9Yy虞깞IwY;ه3'Y~EITY[9<"_ I.ia?!ٟ%IE":$Z&z(鞣雓ٓ9qOh\*@) Zs^{ጎ9uh 9HPu?:n9L-z dZfzhɢj _ٌYJ): {)?ɀhE*_{U| QVEoavʥ0:Cal nʗUǩ9xp[q;aIAQdhӣ̷ yD))ӥ/Dںz'8tY_R 9@ zCJ|ٍʣ9]'V}0;zZ٪ Tꚧ쪩 q qjLZlJxèَ#w"F83U5M[ Ӆ H'Zq >.Y}i~I?whV34ry:ے A˧{YSzX*zZ[bVm # c6(iI0[<2}۲X@JA` a 逸k@#˻Y[)b{JkQ楩0{s9AjYʾ?ŷ }عpɛ0 =Ы>nh-n%s&нp% !Q9v(T(;#6A۳ ) a )t W0ؠJQ=,|`  =F2a+Dᵸgh#ۻ .aM ա,]ˁ ) PؖU̖ܱ-` ]1'l \H{2F7mu}| ֣ܫϥ[lU< 1G-MզL)PպQ+*F͝ A q(~*Q݂mz36~7^͍M 33fIb,6Pm=q_tpcegګ\ .̼P|nnq> 貪@퐹* Fr+E^Q~߮XLG!פǰǰ۪yJTJT|U^YĮt>~g\8/Z+K:>'\?SN|0[nz,d?! Q]^ʿڷ UVma>?mcY<Ю is޻=X /G+'Ay͛;vRD$vloK<B;mLPH2J_Ϟq R/~k?}OQ Qcoڳi.r_yŬkgG'ό O(21u yÜnB. DPaG.QbAW-$wCSسH%MDRJ-W8RL5O 1S΁}T:Bv#GMX`QU"XkO}&BNJY &*1.µ )eFe[mշl" %0kp´9DS%Z>{` v.}0-یQW;m߮n޽gʶH;SG~hH [Yh^=2SJ3~_[>uOn}]%zTiuzٻ)2Sm #3LdK4;?5DOD1EW$80Fѹșf:'+(.!oJ c {k$:WժAG2!Ӽ"K6J]g<zdf<R˳,INZ3Td)j:7-iR}WA64C:W`~CBϏcf3I褦XGփQa4XPrƭ{d=RӮj0]REf+jvǖkD4|}71ȫZg5r:1TR_yqr*onIe$'2{ p0wOs*;'^\pB 96Cٹ@I _lj"nfE{]eșf[[qFu6gW];prc GNPYBa+C]F;s&m*Gp͚DPODԤMM7Uw۬bE̔G20mMj$T-7O QL1MA,fGZۑk2_s9*_\ LmW<9HslQ{&)EUf"CNWp Ǵɏ*/!YF"=~Y^84iƞlq7*HEߚUyx;cʫe3p="܋G`%B;vyszAٺGTzgYpd%CXi"BI<^픻 7 {[kO|ǽBI)ܟ?Nk_|șƂ ogrx酕yėQmY P̤o}_{cLLjs?>!uxo{F1LE<>99,C6ؒ[A-cWHs*C >>S^=C=|@T?!C@]{绛$"BZ>s6 74a=8" h3T. <4[ ZzA?K\,+@8C#"d;ﲹXsLar+>/DC轌=1Ct#Ӻƺ)278T&;Ћ@ƹ'lG(ġ{@FQDA;cIL#2nr<<Ŏ E1ž .ncE?F$$<(Ȩ;(l(E0 ", C}I4uiL$;`CAE}@B&:B 3–1GcLYl6(1Es.yLBGC(ǖ-0Ā|F(A4:ES;Ɔ|GTy V(уE镜=rwD"stG7~!fԿ#5B@ðqHF9JqHh2/8MJJtΘG(J4J )Dz4)ơ~#iaɗ<'aClKÚ@>KC;A:{TI-ɬ. A"9lz&伍qƎPQ.ܲ +05S}PDQ\-J%ə|ɖ;ETиL㔘|ԯJa¢\&'( I  mFR S,IK5V8LS5hS7]|ʧT]!\HYKZă;-QWuREDOXdQ1c 74mTRxVԎaS JSy !mDW ,Uz-3k`$Vב]\TX5e]Q-M0wЄUTD SfMW4[|J]ں@ Wy Y$٨VS}WM7Vm-W*XW]ضL aj-~u=85zTܕ3}NelYtIEMGCk[=hGfĉ!#"®e;ٵ}Nm heRi;ɖz7&y=?Uʷ#"Zۻ-ݼئٶxӅeZA\gUŕ}6-^o,8^ -Gr݊MR]m RF "^. z\BFߕ- }x\HuJĚdҿ_q=έ7M*3@>.#9U\`H#`w[v`1] &1UJ Vf]ͥM-(vs*U^*vL4 JqQ⬍` Ur`b"U&>Cшg*)#vR+R6׎}'r`z$Tݿ}9VK=ݔ]:]FR߰Euߋ_@Vb{aBU şZ&k-С*5IMeL&fkyeQwZcM\e 5IX2 \\O> Ibbg,eNfF}^{gjf{Penvu" yMԺ$Pp|de fx%eEgڐ.e >e6rXb~CYf630e($g]s䪸u|Vj:U8gKvfhnib Vl䑾PI@p qE+bV^wn饦k~ z~j] ^~I^<&6WfWYu9T 6RT3l { O Pel$성`!ƒٛ Vig&Ur=vφZr!m뾮㕱j>N}j E~f턆2 9-ʶw ෶Fn^Nv>fa Eim %H[nvU.a2q2#es:)n?5R&bDV mQ6\qICG0 poggrCk~方c[?j*d\O؆`ߑ΋n''fm ol( Yz9&wqki M 6i8ә. :O.%GjFsL eL{Wjs)qMQ}~~:)۱>ws{{tkʺrbo o =7s‡]HLz5njnW껮|}&~X&+dz؏ /R|akI> G~~,刧柷z,h0 >Z!Ĉ'Rh"ƌ7r#ȉN9q 2+$_*DpG)tGf䆒ˤ?.Oy,I$U|ӧRL R,ًT%9CWh>R$ke5oZ;ӎ Ԭ˄ n1Ȓ'S8R7%L1Cz 2sL)zKØ})@:(t4DS%ؒ/99@hԞb }\DE@(N#V5JyƇq)+UB" IP(T)L1)jmG1R Fr[*i"؟@BCyCnj)<[V[j e>6b?暂[+wsIx^|Uwjc(PT_TL׎;2%o 3ӈk@֩zcCQieA˟{k^º\f%Bm ݩ|z4cc6Tr<6e.}Մ ESohNU`;Zx&9GDAG,1<++sowڝ{yAh{S"6Ŗ3:m.8Ht7gԮ{Ń]{Mv'V[=9@6CO֨w͞U汘Hw6gM(=<AI.{|Es".r s[3*o8GXVr&%U)f8E5p:`)>!Wv4p(~]>oT_($/KF TYVY]U|V V0ַ{`ڊ% h[ގ⼣8E!~S.* dMs`DdaIy]ͺJƚMwkw yMWm=Kbۇev ֙*lؤU %A!9" .ك-Nq0F"Y '>[V|,䴩;qSR8`)Fb ;5nމ]T!Fӱ菋,A$K2E`K׿4qm2>Rox˜8"FzץKuNWĠ$h}<E6=Fѩߣ5 th.m5thqzD=j<ӂj؎Cq;lb-`Kmd>=[BDZCDKLa[ ۓYb,6H]q&g>9-{KkL& frhvEbv?ʰ!ms jܦU@8'j|93?Vby6K("@ :&)fߌ W%^.w҇~q @xQtdΖ.jS^a\&[[:J遧.mYsu {Z#S,oza3J-ׯ8Ư< ylebY;thlw %,Ixh||[MAh?^-W@b.[/ ?`=!PeKkP99= Xn QE],DuhRW}Sa]ŠdYO` 9P_YEՔO]ݽ^zڹE>Axуh I] ~aK ԅ Z35C C,]`Za\Y c, Qi [da,S aN"tIbHW!`!emg  q &]Na_U]I@:qmP"1f &&Vj9TX JB̡7"ya*M,nYB;`9Jc=-="?E2#>r1JJ21#'fecdJ"-] b8""`QD c.2"M.99#I&%Z]J$!YVEDN#pah l#7 7Ę+# KƩc!6AHcI^ecwi"6#Ň$MUB`$d,d*pDrG88N Z"qdIba:VB WRU"I d0VY*dZjXH~eF0aDEԥ,]vЗ2^eH8%<] FaަIJr?^"@XΌkX5eI^vfD&R0X&q6keU&= W&ng $,W~egddwRU\(1Q[bH'ގ0fFeİU MqzlVgblzf.:bDQ&)XgLrg&FThgJ8d,"jB;1hV~'G:Mą^6{p(xhofagpbTI=>M+1LlHU'eO(D(}֔E$MU!wJnDבNDDB٘gGH=`OKff55"wEPNdu*bg$e2А~D_ 񩟶*z@$㇂cgN-j:rD6j|[=۵'Ε`"= x6YDip򢭺*%ªȪgZ@$j֕2\e~s.-B^ js"rĩšլ"pNB掦kZV땎*Dj.cRĝE0Gp?#F+M ,,E,9$c4,`{AlE"j껺Y!D #> J#k-R͐ͶΞKlo bi}Az'|찞 fD`51#?6ݲŴ_3l)V{l+LX'bxML,dmvjA\zZkӾlmD^G n#m)mEmZb&H)ZUm 4f:RPE.O ;.nr-TVD⭘>B ޯB$o4¬nD$d'f>'F6_ӎjVOeJo/ ΨkT6o(hTX@D 6=0GH0[St0T D`㮠Ip 0 _D y qDXnW*D=s D.2"|umpx?l/ "#+IS,N1tXc(}JmG121m2^NU^1M"&#'pn⸆A \4nj, ''GKBܨRg̎0I* /0E26iiCN2#{4/֛C6sA0$Ɯ.-n44fm* ǎ7C.s/s{3Sijqp)<D °|jmޢ,,l2A14B r̾CDϰDs+EE V)0 zI=sWp *@eiDN~D5CAkrB[q}ZFs zd:/pa`|ܥIqr/Dt5Lq4Y`_/Áu[uPõzEc4Ŵ5n)5ކ&t KHpt1Xc$\jD1v`ec9kvzpQuFSr0Mv4_jU7q(l{lrg+ֺq6sg1Au,cĽ(g7ziֵ;C6$C aRP ]7.4wGtwb2ĆAknwG(HHϲPp"jwC_;D*N/;6z(7tё22MOxxv# ?Ćs8{8D2L3p~%b)8k7k {'25yy d/̑ZOL92h0㡕MrRߵCvȎsc; Ǝ{:`oYiyGqe*ye\}7۵QhXs_us5:>/@ WSxgD{D}CcěNwzoC'sRY|Y,oO0מ77V;W.S5zG~'thViﺺs;J:;@ǻ{V{68-d{{v(M^.e ǫ"{/F@'zPozOwJ*3ۓO6~:xױa<7~v>6|%Dh ::Ɵ>n8g>OjGF|~0۽+l7ë)G=RG~gHc֯ӽǮt d={/<ŃSV#n?F#c@8`A)E0T ) G%NbI-T qe˕Vځcʏ6#ts%ɒSgɐ7RL&O*H4"r$RG&3i׃Y[.*W=;m[oƕ;n]w[[ʲyڗE?%\oˏ RE6YbdHtxnc4ϜcA 's\J7ܵحO~kk^E>zuױgWt 2_0]:p!9o$Ǝ bVtn΀<.6$bn)z "?*-(COYlF@j) ?o'|ih%+4F{DU;((r .0S(񡍢~LKND BqJ ?H@nPR 7TG6$l#;H">Hm0tJji5-!uQKuRVJ"&#']])֖l%MVekf3$ GbBM00C<ױԇRC6[`eU (.JS8 Va_2$=M!g%`qi(r̂C7GrYrz6|eyu er~a1+n_j5i6|cm~1d!dq]#>tNWQY;TR5iVgtb+ 7BWV` .Io֤Z)K k^ζkhKR,g-m߻P7³]-\'סW+qjn\Or3?k;Xb/\#mQʵϣ94(xZuLمv{qUSe/׆9x\ښ@.pb#TL"!ekTҕ{AAP(|;8j utB\p9zya8~ 4APq㜗siH|0f")\VM53qjGN;'EuPU0N0 *ǟI萁^Lwj̅ːS)"8u(FÌ}VbHIUŤg"{SGLtsezjLK鲠V`M[:T~>w!D$c!;B_ EsMӖS.uP횓Eok_Hɖ^֛$T"UbD}V#\e,h۝dՁi#von-J;TZM :;f[Iu146*>Wuqj!lz6eM_v /M+^Z-pj[Âîl|kmUm΀ BuޝnAB p9c˟Һ"{idVƦ" b4e6UY 89ӎcJ$b:ksV{dژ-Qf54MZٽ)#G|0I/lfM7R3c@qyB+2 e>S~MdC+ .]GV/7vzY_]39jsBTP~e[>on6J6UIh9.ɱսlNB(iѻBN~ⅶwV1?y^=^E8ail#Ӭ7\(Ѧ 1W)>Dn&ƸR`x+B.pO>B9 #bO܏Rd%FǑR 32O'o b(lFN 0 ΨI6;I,^. PYO>.>, nJCIJ"ܚW>F+զ#V΄phEIi$L PhLf иPz B(S $d-)./pP 'f [lUHO h P%"L)MV& hė1V'XN y&m<1~@1hD.(dWc)VUOpa*%&)/Ѩ(%I6cop(pb-X 2bđO^qPD eHtQBE L%q^glM$Laq΀ K"#'!+" ld Ѫ^%Ӎq!r2 &e24 2)o,'9dhL %(k)! G X1" '*EH  &&, -a '[24- C(RF3S20 QB!b6"$ S u(',5+Lv23./%BD9".a:pS4GQT"l#im6Ue(5t$D|s.23&8"$p4s@B:j./nt^3(nH<6K(7v7508s8Owq,4[5 k 4F@AAU*sBi6r*bC3Ed`ĬD|)2DDIME;eK F[$z:sw DT%+,7CIUI NY94MUT3(bKb2 5QqU%EFq4uT;KM%As?s01_TGR9)T+}JU5ZT "/3?lKPM'9s\tQ#sQLR-\{H7Q$U]#H[TS* > JV5)BV٢\g]) vW(5JÂIbSbYZU69v \#a[%UaY hU zbbU]56c)PqΦ^s$u'0Ta _dBIQc`P$h6jVbۢPVb= ]ݕck&3 piMdvHj[ؓMb֩.jeòu1mg۶rKm#nh!Xt^S<WUr6NȽ-4!k3I1K'v,rs6;Vvo.1eI=^?~`Y'?|Icٷ믵ƾhTZ;>K=QW?޼=h(T["L? "U_>f 񛭜Es~B_H#MX3 Ӊԥ[¢W^ bݣ <0… :|(ᣁ+Z1!] 'f2d W)",RA%'$8.=6;p(@Eb$iɤL.rD"&DJ5TQ"YZk-@'[ },"/X#| 8 ,aDoضٸRY*kNdFN\g-=h Yub e(;0MW$T59wFRt.Mԫ[=^;ǸowB(E2l6i4?Ux26[NyUQfJ(Aam\c%gay~b"&![&D^k*j 9f3M}8GO>_ A7`1&O9IВJPp_Aq!cdeFvFU%NJn gau''H(*- U'CepY݈&i7W[:!&؟iGeAPi uZ=1\qnyaR ]0&}ފkuҩ뉔1+~lAnࠋ.5ML3-Np< GF Nаnاg{_wiיrW0{ad'Zlԯyj xAYH:ĩYeiζVl][Tc&Aj鋾bow# /t t=lbQay׳qlG4#G{e`.l](,mIlx`&`{`)!!uo7$o/B/EskӖ_yAP/-5ZEkM)U5ld@(sZrX Bw)LR3x3^&Uy9N5萍]CP>o1uC3/ƹo' o};8 YxAr D%*W_T?9h|BWEF)!TG%uANP@̎dnurD}B iLVH&dQo3\8 X0_jc b[ɨ1rk\klX,/co L$ @Sx1j\2w.Ws侙dk&\$~ gmKtApU\~Y&EG n'atyu]up7$AO }f:3B-V}~`qC˻_hNȯpbΐk1УzB}z7 $V]Y hoց DkLzH0y,?Gz_r}~}Uwg,G5d TЖ~u*~Cnw0W}}R&!A:b2wm68\%Gq_}7Y{wUSwNO+'"b50(b%8WHyK3}3z>,rBDx{ڧdO"lJ!jZ]:D3{&LD( TK6)k+>N*alঝWÄ5+gMGrR?==Yߣ})mNY6ð}zのCwzRZzA>"C m uN y{.HM K>t00n[V>E>X^j6w.FaY0~nl;b .=K֎ފA/r3}ί."&=@j!MN6mIaҊMԶ!N:mR 9Л""@7h*]*dBdn]vO-ttf>  JU4$?"T#ڜyTq/&1^zфŮg\.8C߅7ڻ=K/u9l"RU/V 8MlqNcV}}_!pbBAaf""R"am'I$`_.k2N>O: A/C/0}/鸪!"(a^CZz-Zp./?W-j0 )$XA.|pCm욟5G!E$YI)Ud2źG.e u~te0L&etA*KAR g؁cG΁Estx#3r>ծ[BMhϖnQlP^ -7.C AR ^D=6k^A>L d P _8viԩUfMf뒡kGYaywK(,)Lͺ.H9ie5_UqI.s>ʘwv=vSa_J$=rst1L.4R9 4@z-6n'[!*4h"pj |N UcF,rۊ2OSB=zīk7fYR 1q9RdfʌEB#zMC.K:DB/1P4R%F,q.ӑ]LO/MBs$O ϨC]Q&M32D FI ?T‘ p S9jsUV[u 1d 3_hM m= ޣ 8h9p3@AԫBc)SeG6Wՠ(L"a7mA'H]x7V/gVy uw*ސ7Ī⓬eNжvNZ=hbDRERQǪgv=BKyfX5{ͤVh4E<L7نvu2Zӂ+\ c$Q4f{n2gg_װR8nN z9&MFPᱚ49jmVr/:[H%lHˏ~ kEjnk] 5;$|kp].b Wīrije5ִ[Մ'ntD;>tc]&M4!GQ p}n+i]yV gS'!qX ,m-%У^vu{agPH`CX*2>%cz y6P_ǿZư:+JM:y|bAq5cIZ$6Q@(H>)yZ6n3dc5TCݐ'90 , f<@.12 G('Đ"H"A(3M8b#=°DIia'wҸQ,$GOt008LaJgD!"H):2j"x(i"m;$meԥKJRl+ X1_v4"k0r,&N.+ļci~XٷՀnT62NzDuR7[5%ؠ9=ѕ@Bgy [Y]:$̝3GvIgIU2/)|SæQE) LU"` [HDBDu媤Ҟ"Ӕer$Kѩ*SQylKKSg:I&LKbc]le=U֓$c]gYt~HO[T:1D5S$k7PxRb ;RRr^cO?N Dens YHj^;D{#8TɴcRW\Z2qrwl4S= {0<֓I&y,9\&-(}zVCvg B]|7qI/-BWTz5Tf1^x|{Ra,[WUrPC(i;p6(pb!\:i5ع Zucfmy[HkQqьXu3WQUYϫ4P<]˺^Tpa){pVaӱtʏ?25/,V c&T1^%%UjV94.*P6 ~VY6<.ӟI5޺ՊM]4u*OX JX;>MXlkAK8A_̖؁Im콺"ɤkiwõtWJ)u0r\Qk_H/1Yx\&mwt轫^6pwSobicmpqJ}hA#3F}cm#|q ׊H MKu<0|daNQap9C%n.x)\V5}q;Jۛ * Fg^fb7 \޻)t< %btSh# Ub>=EjsXjl,iۍ+d`^R.$W d NۗzߪA1=S ~291{ue:((+ #80!v@' {[ =7 ׫ d3=PC  #K)ra@=[ QI |B]:K2,&(ذ{;AHjAE?\ 3!L#A% N=[,%L s>(,6)lϓ+|,dCk?1@C4T7?:P,T > S<$CaǻJACEAę ;>]х$ģX2zkAK/ LE1{C쿆ąqţ'a<pB* -:\lGEGEs_ Fn# {ˠNL:D{FhLǕFz,84:9{<q1Sq$KT̨Ey츎rG<xl ^Ft`d(cd\ iFBFRTHܳSD1C`ضȒ(GsԸ*\IXǒJ9iFޡJViI%Y ;c}ܘ~I$d2<JKsSm$Ⱥ 숍+v L J TdI{\  <čNT?5$ 4HI+źȻRu]%EM)2~S˛M2d=NH^F_n޸d,` =yޒPoя%נ,8&V^vLo;ͺ14-\h]ܼV xhv{X ktaҮƾPSVl}iUkh+3\Z>/A ]jgN\*jFfmjn\.0鐀fm^.NQ..+kڵ>;vmfihuG{;^ȾO6hB`e^[3funRa.mf&߇Xm&gW$h.[B~b4@ÆZ~ oΨm&! nRn kn>HP.bsqWv! gk5:WV_ii.9_ﻝq[P;Jn:qWk.%ُe1 p$O% R.'Ir7Ji>E/^pM߉NPp-Gr6*3o0#G/s?R@t5q/6k6 9GEfCt;4Os_selt gJ:sj<7 #VϮ)]bͮuv.\tM5u-zHLO}m/xyUٶx2_xgwxxytHS,S"*m"qu'X\2Au{H͕oέ{7޺>k[*ᾟehG;mmR-R䒆xxS8\ebtxCPE߆C2HumO38]7yAmMQARpSU8Ure!MR%]%݁%Hijŧu*bRRX|>*Yp7HE\ؐ7MC`!Yі>T%䇌gg^[qRډ t!HB'Cf@բYK-ʤWBud -IP#E=mPQYj'::[J %1l"ZTm&nqښRWRt+e]׫J8XID2(^N|N$omѓQꅩf W6mI @:ۯmoYm%r [jduw1Z]eﶇ^:^.TFlLIjfLJ0Cs'pej0LBpsx ksUΕhO8x,t!3tq$܁vyn̰PN'e]Sn`B&A`EScʔҏCUdgtJ\ZkAT0[MqYL9o\O^bdzކ"Dl;2r+ˬ ^J]xf" RSN/sd|ې'}G&&(JSTd2 0lDFqE1H`){2.2^bnh ɯdhL3H(re>T"Z$md yv24H(yMt)1ѠX|R8'O{~F%vfVx09WyiT3Np rTԢDeH Q"'2`X@6E:! /!xƉ:I zӉ`cѫO kX) E]:΃m lQj 'ȥQi2QL1HRcUL}^a% ۶yǂ,'E)[\ior]U+W aUfIo 0%5C}hA8Y,Rd+m>["kmRNԞbkCҬ< q yRdyAEőU{.:(-U$2e"|yLogˋV;"7 w7/F*3q:J` Su0;ao4,@q+@>ʄ@bN=<4_ߑͰ#CR$؍2k.#6Dq2 (7+rfkx)4d{1'*^z#r%ƃv3kX_ןuq8gvȟU%{-܂ ");^^Ξc1Y^i֧VjmX*lI062kQa M _x I_##Қ% %'YHqYPSN>,1Xb7+2^Jvb%*fMG q} #Hb"- ԉa9M}(b)v>&QyEC##`9:&~eb;YhDY=ڡ|}X q!d;!]C n*N$adS 8M.IJ:$Y$&E>N9ng_! [B2_uHD_mP0Z?NHi PHz_鴡zܜ֨^"u*[ j'j?"Y#ʣn)FLE2kUX0f\&ѨOf]EkTܩA/Ydz- v+*\B5%+@jgkl kj,o:^Wۺ f"~6Ѭ,ĸ2zJ2:xAyzfPޡl6#:ִBlbT0,,-f"$RdzP-#^]ȺkSNtl-ˊm),V:E-|Sih:Am"jJ*~섞.R"Ĺ@M_EF oohWZ. bnSgkSmgZRYu*|DJ-uNm.BtJJ`C$Q A(gxV&$k8[y.n+VU>J_m/oЭN*.6I)vY޸MDP*8 B^fi3[<a:#ͪ7o;ľ'gPDOijdXK;ۯ末 Ok^DyO̦<̓W~Kg<#:#lwԳ;A_|z¼R|Rp6ǧio8@ U;NuV)^C^2(E/bRūp` 6|qbXJ;r9¬B.XŌpnn8ҳỈ[*-j4rK䃡D([NشnV^kٳ^N%,\\b۔'zw~|d\Zu}Z?%2-$*8"! B-%48 r!fl O*$ <N,9Ø{ CkgIdJҢjA^.)"|l٫pԛ(s) ب *88?.WO@ 4F㲹NÇnraY܁w|i=GZӝ%icK)VbrH#bj|3_"4U5l#T һ>}MESY؉5L%*d􄱕AQi|S6u$ćzڪ[ܗ6LR #tSky#cy{zg8|D X+}8LW@Ν Ʋf!yxCaM`jv9fyD^nrXױ|Ysfۍݯѧgn =A*[G.T*h1^,-6:H^NBg;;x.6Oi,אָqπnjȌEԭ|¾.n*3Tނ/oDڼG:"ʯ#,p2p8 q2R࿾H>oz Ӏ[0(vHMn 0x\/~Nܴ56* 0 QTP ׍ y}'oJbPHmOn؋ܮ " ;3Q0&٭m2}lQ"tˎADLrBbaίˑ0og ).Wl1b$1E)1?Sٺ#L b" ZkU@q+*J"GH11T%%>Q1!֎yRB"ۑ"L20#eq"1 P%Q% AE1p n'LOn$-&̙ )rz22(r80B)Q%eJ/l*%_r0_&k P'#[']PL0+./Sg RJVJŢFw٬+-01s%Sb22'.!ʒ61%֒-!#)rr *R5qXB2㜱xPu7<51[R$A"(29&-2&N"BS4H'&(;!^s0If!C ?k%FDEREqI[4@@ =SXEGyTMKG30n,0=;<2 YC^4b8J+>PO1KW:dt=vvFG(SM)H{OQ='JIq*2%1^Q<43TBun"LTBA4SuBG#<5Qݔ%N*qV]V4-+Y*t5XHK*fǔ#&u+5M]+51-6J-BqLTs=u_OSUUeiJUm3OW 4xu3ǃ-ֵ]7v>`Q W?`Y5ZJPZTB~R6VGb)a!)ȵ\΀L(4c=2 ^#d ^%`#_Ue`VJKbf9Oa#Ca?)l0Vr!8c'ViV1d]P4t%[d 1UveVJ\KZ:hlQb7Mڑ7hY%`^ao;$ڪ֚oy%אc4Y!Z wb9.s;{ѯ R?b 3? _M{:f(:Jĵp+4yyn; v[ds}u!k1n:q;9bp4&eUtݣcNUs fվ{ uy>x⻸po ?^9*VL8}?w\mOQl(Q)>+ӟS]v7S鸑;;$@NNqʼn:ں{G:{|%X4\-C #!%$2O FYWW|z{)\<8a[kRh;̓ǃ"R)š9}S0?,]{YK\C•]Hbs7c>8Q=TWH;](|D*M=֩ƪ7s[[: p9^]m!π0?\}S١L"Իz<` /]Z˝"JQm֝}3=3Π}Ǚbr܉~G ! dU}J+OZ+֓͝} me-""tFL"C6FY~a>ze^ 2x 40CCO>a.:a+ BfCꇣk幞;ޓ"UJ|@7ݚ~d7Ul@~]wk}r=VF漛oM?%cc~G#>'>+^Uk ׿!~AAo/_?,& emVÖmC Rt%"|0#J<Ȱ3tȝI6GB $EP9HGr E4Xѥ͛8sɳϟ@ s]͏g؁cg&ѡ-i>cʤ*0kǣ6~˕d${r),۲7>נځ{o ɡ{0ȭC,dPZv̹ϠCjeͣq%@R} l|;Zޜi{ AFr ZWj;{Ohn;ݷt&O(Y?OK#=|ADd-1ytn:YQEGB !Doe$39y]A8Tu$vHd%ye!TJ(ԡ{gb@)Rv$ $IE(UUmcB?F \y%j@~S@Hv,~LqQ24re#QNVYB_mp>袌6꒑ %TSK:ꤣ QI@NTaC hnfyШ7ha [DL)Y^π:ӤTNz:cf ph $J@tEQO VspJj*&f&R"A֋Vj cG@Ujmgq_R>I胺>Tv(Dԯs|/OzUҒtT3K0B3&+: ߉+U饴R$Q|Ho\qA!j zue0&ю 6뤖rQmVl%tDX?Xհtru.e=:Qsw lj;rE) Qv+~s83\nՎS$\ 8^\E{dհwGԱ6(x( wt׼\sŕ98򐖂I)pU4;@ zrDa @t ~tel|R:N>DaJe7ld&&&4p \@4qpDZS&NbR a`P$C+R@)Q%C {P6 E!Ǖ!v ^vXkVRpGD"aC P=h`ZESЋ *$0%WJm[ $=FFMnPt\}G;p6 $q =DLy/]F2 KVŧb@JAQzd`+NE[mX-UT]7Kkdj E FȱI 4 YVX'0>F + /FJ^$(oE-0VE6KZ-(V3W fA :b*@;Cb>f6ө%j#:dd\A2i0]3( {,grr&bֶ>sni^­擧XOT ] R 'Ԃ|ꑚFd׬hyDhq^^bܓYCVǺiE3O" %#v̞p~&2T T>pѬp8IbVYR A.6"HAiSKrThv٬t2 -quf\3G߻G +XYī|"NhЂ/F .jCZ!q=EHhK*핯o`zDiGJn:^Ω CV*!E"m['ק޵k1>Egi2컈9N[߃#ᙦͿv )V7؉ufͦZW^8]wcⰉ{c#~-*QX<Đdjm*1ixf2yy_p~t'\HG-EGp {]#/vPLG3́mGZ7Qx(h +3K 7p(Nk(_Ii-ϧ>TXRx߻%ۖnCB},ϐ=.񵀽n.V[vӛb"~}aC\ܾ&M˃M7Y}Bkv*w'ugBGw(}=|[n/ dwPumܿ!! ёiuGZA?KzWlF%sxx{>1Hކ@sLW8w$=)'6obd}'oi}u1'A<2)pL_v`ǁC~!#XT5'h)xw"GG{ݗz7Cb+rarml>X~@Bnpxo"yI67yV|V5W()ׂov*xf3{a~^7UGI8v|vyErw,xJ B*T$fXYwxاxxKu~@~J~臬X{81d(8׍`Tԅ:_p."4XoEdž:f|-8XS1BlчÉXnkḐBb!%)[%,2EH$zw`bTxzxlpOHQMȐ<$9.Y|&8/]rPwHm5ovQsu(|+9 F==U؊yؓlI$?I6`yGs_ȏ:I=Si+ ؆pWpKYa$Aܘm@L|dwɒ>{y (3(%jX\T%dBD8LXv鍪V\qq[bwGq}YB }7os99"{.i? ł?טi&ħxI$XvBչQ3<)9v9s1e9cq١qC\|B) ~ Q8XXڡxLe[_;f- B"S1DڟiH: 3ymT?!BJFJ:CA7"ϗ)jcUj*zz٥r c:-y=!kڞ)"799aJJv $x:tŅq~*s]PآR8XY_̈́r&`ډ=u?61brFJ* Pz:?eڙǘWlk6@Ap*:ʦ|rɢZ>@ڧ֪ /ުGwaK7*ڮ>1jrz>ꪌĭ0Z9q6jst2c@ڱHkkZ& jۚ5kJp®y&JEpʲIѴQR \j< :ply̽q C'݋\] ͣpĘ˺fˏ0Mz"]6dܯ ҍz  Ηx>&}b (ލH6}ιrm!?Ϙ-M6u-g M ~;o,CUc2n̚}%╋;J>LnW?3> sk x0ñknV1>K. n}U~`7M8D=m~N]Yl7ҙYoZ0w<>խ:5n୾$DĊ*\.ej>NlilZE5.@>d*;T.|w^u}n59g NZ%5>Ӏ<ۉ پ@+m>Y}rRҜ2]W|B 7不2N]zK-rF;5U8^SM1Nn:Lo4 m(df~* F7/`~^[Hf&8_̣q./uo!N5.leNIq?_𱓐_D,6E^rN ꟟wt+Y?ߴoG6 Doݏ,w_8VQHk!dB3) DPB !|PD(^\H#č=~RH%MDRJ"yҢØ ARdÁ=W:˗ ^,Zs̎I:iO7:ez7r]ɁsȨ0Z50+Ū*봅g ZE\Rǿ| FXbJ]6V0'Kr.Qder+sCOS, ybِSG7ƪ2)W伅O?fzۃզ۞ 0𒃛ƞ]vE>^S'E\֜ :wt}|N־͖ͤ3辔鷍ꪽ* :3?>?1DGoDS"n:/kAP92:lgT(Gb?ryF@=QHA3N.qđ* 2#1M5dsŚVĩ()Ơ!Y*F8DǒH+TϾ\J!+OŎ(͎P^r"DK:UҘU-#nKH}0QRv"M4!G^e]wt]dts,\bEW!F deHIۼZB`L!B.ZFra2`yWfee^Td }*~u nXCubCW*\r&E"[xމBA PF虸䔧u%w.cmGE/pX"DmJ-PMo_'cwEVjwC{(Vᆦi O5Ƕyc+ &v r!E_3_E"K}#)OnV6*[D[]v4hFh) $"8ƸI0{ʸVb3TQjrvы)aN}_,hP(`kCdf"[_Ff)I?̝Y*KQk]@Q)RT x8` Q]ENv0adAb7;0.tPQ7y^h;pTՁ.ⸯxʉ eCDk]Hq%<Glғ&K@*QzvdTt:AFx=&]̱͕-H\:mb{M!%XJKad$A효irEj;V#bDU'9Nvo~=R\U!7i} ; [c䜚XKH]zkB"#G6%F$YJV%)1<;c+Bf)͵࿼#]5QזYXի*M +F<O<1RF/kU9NGw"~ eKٺʄ)쩐ԗQzy:hnȄ)ubۊ4lp '8-mZVBZgG)s/Ѷ^ki}Zn +m1Od:C=ĎMNV%94BfGd6C]^6Oa<ґ6)]A{>P&Kmgl*nY:xγED>VѯVT !p< w2oV;9h'mۢyhR?[ y'&8+V o8o[{vk l {M!K_oeK3y,-n_ސ2Ct3SswqjʱS,CFbtWH =]1T0"e $bJR۾=M_纻x;^rs]?IG9ur%^s*\:?gf/k.q7nߑxWϺ;§7)mI.0>㻻z+) k:ʽ\G{@?A#A Y렣k-:5(D>baX3]E*M:B6%TbS"Er >GS@1,>.d6(COo;Ի,+7|:`9l:;(s%A(C 4J$l]\Gn Dհ@ŎHq[8s2;QD Sc.U$6S9\ ӡBFE^TDdb-Ȧ 1:5̈ǂldJeD @8T $ɜtKd(F(J , \JKʈ?ɒJݹaIGt:h,;K6B)&<pȺ,ǭǿdL:œK2Aɔ\\t!!˙θSJiLLܪL bV環򔖰C1*J(4}JI((D74ddC\hvJUI4)?IJ(rT4=PyUCc }HXQ|Pĵ Q=REQ슷OK%O3*<4E uX!U$3R/45L,t=u?͘pR(,Q+h -RtQ݀Eɴ ,JR5ԓ`S{S96Z LASP\ fHOB%CC)D E]TS͑ US]?6Y-^) RP _:ŽTHe"q_९8k Z@,,a8aˠg`4aXP H_ñM>2} U_VmF!` |s<\}&f^b)_;>%Wb"O2.cz;cKc5+č%8Y ^AEc$C&c?^<*d>dMxSVN_I&-Z*_zdOgyTR&u}e]^?ueY&ZF Vc`yrBbUz!F o_P[b@qhfk^dѣ9Xfo^p~E0$_.9u@v6mY8N *atfq@r@ifU ֈWH\KvhLxSZs6thy5da~)bV/ܡgdvt#nixڔ؍72d^igGvСh>kgZR~ӌ@gvFp}xNM>4J Ɖ\v,^å1lVjlca0itE]HT0 lPވ2>^`Kl**@ Kݱ lÐfY^xeNfnb PК\FmeNbMX~XːooƉ(vڐnݓϘkkaNhc0h n@&6kF䇀popYm)Ap(p-mV_v@YԒi c"ȜtBAmHS@orP6"JqF7[6V?gn~B.T%?'prDk,dɮs0sX p>ח7gc 9'/$c |5+lu=+9imgroSF,%qLHstnyv922DsX pv \eAXUrLZ?u˛G),h „ *xˆ ,XČ ]i옂^kǔ*Wl%̘2gҬi:,院P$B3y$У *$)"UQꑣA7jlQ+װv+Wf xI&٘fϦL;/nM8ɪ2n츱ǒaΥ[g2sYmظ3AO _Lf5زgӞ#Nt%oOJuRtʵgM|ϡKl.a( \Z;%>㫗0M\p#˟ٴv짋1]DAH t~9 Jm+@%O5TR5r NXD&8u+A@(jXjHxwzAu^WMf[yfvGЈg)h#a9&ey&i&m&1KI\r`y$}' :(z(e*(J:)Zz)Ve j):*z*gj*=ڠCGV=+UI?gbJl^qb,<{lmVke+۬bk+])7z/+!{#tko@t[,Eyp /Zd tLG L: =7r\{N' M^IJYs9\/> #-&߽*v|޳wYWKHn)]ϴsLb:Sk۴6Ʊ]ܩ[&G:+ν.9Od/{/9czMvho??:Ծ/DC'lPNyLZH#b)`lE-K°&Kל:e!!,[PL /U, ;b` q{@:քf;$#%a".Ib-$ Ɏ!, &22$>?IBCM KLW12<01;GHS,,8))5곴)++7󔕘((400<͡[\f@A  Pa 8dX@…-^$xQb 4@ DIQJM ) &5SޤaÓ)ϕE!~9!҉KYДV &~!±DUZd Bp7N#Xl` 6(h!<07<0gBXСF4 !, 22>?I$BCM بKLW12<01;GHS,,8))5곴)++7󔕘((400<[\f<@ * B xذ-:,qb D4y`ʕb@̂Dl 1N !C &DH@R&B@װ 2РV T["p0-q 0 #D !,~22$BCM̹ >?I,,8KLW01;!!-CDN89D56@ ,((4%%112<abl@ X lp8L8^,$dž 4pA$dę4O@ :~&XHPH @)  @hp̐a 4ίi< wP$J`: ;01`@!,or22db\#k)l̒+ɏPƢбcd?"h~~ m/fqOIJL//7|QQH0 4hؐ # \ 3Jx@bD<2ǁ \IXʼX`' ɳO4 CH*]: (xtդM @CVj5V'&KY(m[A R]ZBoݿJ]b.`x,y^bPرPM`ăWaܯ1ldKu_T"$~\'7D:T@3/a9A*46`#puL"1")dNH}+'[$@P11ewA8t1g@Mx!'! ,ot1111111111111111111111111111111111111100,,++++++))(())**++++0*4)7(;*B+C1H;OF[Ub^qq}}|lWJ0'{#y wvvvvvvvuvvvvvvvvvvpljh e d e hmpsuuvvvuuut}t}t}srokhgggggggggf_V G @<5,|h`[\ !W)S.Q =M'AI/EE:CA;BA=A@?????????????????????????????????;;;,,,***)))''(%%'%%'##%%%'&&')))))))))))))*))*)$5(J$W ^ceed%b8[+Q&G > 7 2 )!       ? V ai " " %%"##$&'''''''5Ma n o o n q z | { v u w | ~ ~ ~ ~~8QrH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\YW,,͛W(d<AQGi$4JR8k-Լ;4!'`Y qTlav@< ĠlQ}g`~XyA;u;Ȏ@)V]_i8VI^{ؘc)@"`4D]Q Q xJYZ%1QĴAe1Qb+&5Xa`5+j's*X(]a9+W$YjBGPLdo{R j 7Nd]zknҐ^r|DfBiz[mQWnԖCQ ӀÙ$m͵E KU 9T~XPZq˝r;8Np{H6ۧ"sDM,"/}IH/4UZ=EWX9X{& 51VET~!k ;ĝesKKyN[8 dp ap:BnVCt/j]߅縘k4PC)4}ߞW8^DXnv…n:$n=VM^Ozq!tO6wѹ)/`M"D^ya$;NJL E҈Վ- -"DJ[ !Pa?b0n]\$3H.~ cѻ./kX,XA6Q0 HG]GKL${$"bXLKi16Ei06$ *SٓUj8.RKwHԣ$-(Cc&Q8c&)39D^g.čl1yY6̄mE1c+ ep=bgG,S ĺ4)j?cH S+H2+vYC O WPkpIU t%-KitP,)~d|Zγ 4CԊ,/>[Oljf#-G4Z/^uOd7=mͤ4-IJHwՎI?Jt]Q»Dg{P6Fe(E.&8YlVRfq* m^ƲLm[Wpm-lʒBvP(l9dG^DŇ0UN_! YlRttVKAJ>f)x]:V1`TƤkލ<ҾR30T')h>Kcbp;8dtEhInݦM6+\Aˆ4`6b⋼9j1Gzw# , mU*HΡ4nIԢ x8Wx t^uIрE3L4qLXTH\9>'\BYW‡F_XS@t$:׮#[̂TW]-u#%LG{ Mxrbgɚ H{ʩ:w| I.ͱNK+;RUYbVۢƨ=tXl$SFnL?V9hk9gt` } Zb5QI?mwix֥ mKO4VH Xk̻W |{^vi,ҪjOg /c&x v bD8zyP+tNY/5 7댜~ESga;Qb^|EQŧfPEXlyP$0g\eӀت7អF̍y"c'Hy[=gi.XPG/ȑ=iu(ֽٕߤ^׵0BaSjf4_p#}dy1kַ,-/mEwRl6=G4oGt W#&P˴{w!Fq zA,a,[lt$j8udIsgM7}eTݗ%7ZqBF/-(py{AHx.(xh{COtdEwKPuT 5nJU>ՆUT\idJgGz"2JB<'r#w6HajB/pq4~[A׉1OB:8@Pq!4zn~8jÄ,QYR|X9s_81!*l&xxu1r8Du`*c؃I8*7HwxW|xHTgɁؘxHlYQVHfnq!'eLj "Gr|G $ؘ{ 鐱c,a8@TEH)Y((}\ՆX6H8X0IZXzg\qE4qґ&7nV)+Xi9@(ocI)z|I*/Ȗ,)醂Gsi9в1umI&PД -Q  X! *INa)uceᙤ;'!ap9ͧih &i1nuʒ[2&vni 9oU3z)xʙȒ}Ac0ѹx\Ňyٟ' 1{ъa<ay1}iy ay|+J~Y FQ7˥*١hA UuZD7WRTd+؎.%0o j 7ڥ~q=ք@WydR=\T9Vj_ATEGm**ڦ!Yf "m"mE"dÆ5ɧxYDK1vy4|rIuMuck(Pi}xxJ: g;`dǤl 6mDQ6eyjI ʂ~aثѪ!(wWښMV.ʛ }ѢJzA2yj C*4 ʂ๝IT:7Wú-?eI*JY!ҕJ1gwH|j:xI %.j*+*cW\0 ɇ[Q8{1$|>$Y\Ljc[ݩEce\Ԋvdm[kTJ1kէ9ȵiQN-hs;e;\k\k${4E,.t+ǝ| +,~{DP<R|Ը9<-ɻyۀlLѻ/|Tqz6=,BDl/dqܨAS!&L mS,B]QլxЁb};am*s$yJ,Ŭa|( zϿXX Q{ XZJ ~tO A}p(L]a{%Xy\yG T Z=T5ӻk֬\<:,ns1f2ZjlEwגM "L !Ɓ]}maMRyګ9}\5=,_j?XRZtO}#1qݓ/ lsV Kˏjme]uQexa8Ŕ,1MvF )]sqJFeg͵{<̮ aJ| s,n&=d 1&L PE NJү.^+ػu`㐽==ɭm !D^+ JKݣ|`m-F'jW^%lנ&6~9y| qA$̀},HA1gRݣq8܋͇AmT 8೓ߌ'n<ў٭pQ,æy^۝Ѿ$!βNhT>҈ԭ37Ϝ ݅Jcx~ڞjoݡb%PXd|4CLТɾ٢.*~RFi^~,":gޢ.+rG!u[ N{ 6!1Ğ _0>Ϣno7W-c=x7Qg[e~ߓjGZpP_W$L8ΪY<?h7ۅPm[K?KSeNvj\"cYIo'ejNrLr.ޱлn~A?A̯#NK?Y*Bn)Z@@ 3PB GoD-҃8ϟ?=~ D2%/,OlK)0iE sɃ SA U3|0Sܱsn\A>d Z%++u<,m`R ,gix)X)BOeYfΗiXY4\)B::oC;h,JX)쎺e *PX"-.,Xvv{ o' uvwim--wٳ=]ğB>$y${pcDր>/mܠJ)h(Ƞ9Nusg,+#K#ɝⰦbfZO)ZZK?kv ?,#$3$qAK7xr r>.] :C*D(M͗V) gFl=2QEqģR ifh&ڳ&*2϶<+c9fӂ$LmAaT O[|V R+-PlBkLǁmQpjumm|9zPgc^^MoK |Skx/oxN%$u/ &_Cn*!}K#?<1sl=̴ Ylir2@e(Lv IAo 04<^č(B"*9er󂣟:+],tB:>&U KEyUjY1MQqH/(Kf$d$ԛWZozi 3Yq\LbCb S'&¢:.) )LQ!!XL^4bk9hV id.Y;by"(hI*R< 5,*q{NCcan gh Pfn 1T]tthC>4yk GK85ԤJAiH220ynb%7l+CIϝ0G# QШ]\(p):9TfecStM_L 4I+HPV_J ̂҂7%gw#f:s`)[؀2;(@}.*ULίB2jʍꯣoiEvZ^#cmk9UmW+&'*Q-e呂)6"nGva6dUCpճ恑XpKޗ#'KXQ sZą3UCBQp|Ԅb9"xcDnAv%an⫐7ƅ rA Sx%Jⓘ8U┉+V.ڔmї>$̡xK"*UAp rUEP \Bpr/9anj^N*^5{gQm_(9K`-h Q,fNf۟*3ϦOڴbr׭Mc cRf_scU-vCk\\T9fi.Tsj^ʅgUjW;6H]4o]hT:sbb>yC%N٭[Ibzr4 U嫔vgp&单C-U ţGaP439D-r:[g_λb> dl.K9ttnLğR!|CHẠ0kָ &i x.Γgj=g/.[% x,&r#&̹|<>Sݗ*',i+za^rW~aC{[=bxH~Z7k<$z6k=r3WR/ks$-?7B5G#wІvy?ҏۡ\2)2|y2sA Y>cVXKxvcAʵQ+42Lmm `k轴Q˰ذlsAnS 7z3d@,Z‘ &$X^{kІ0L1,2<ӿɈPCsղ"Fd !$Bb9?@̖C }k ?G‚E;CM7N OlTTE:WFPd Y7Wc9<۔ʻ_Y.K)l*l+d0@VFXAF2£SƈƣC;KCHqDi\5HZLٲ1̗R˃ƼG(9(*D::ݻ*Q LIPT͐жtM d1>KTVtKt*u(P$IK3tJ|ɢi'N30K!CtwMD̏PLأ< {9#+ 9 g )LllϐlqP HP >Yτ#ͨ KCCQQ2G|R=jl΃@0!%"H' -P@Y/qc-.UdI&tƖvQRcʵh[PkЂN;U=U>?MJ;Cm/D/G/7,AԘ\B:0`SpNgS0Մ017YR?M<aJĿcFP( |Dp^Y)Y ]X m@}MBՍMUe)Y%CŬV M5^Sg}hY>@E][cUn&-&Mu ӛde~V exVʼnDy% QΒ@ji]{VcƛY-Pcxdtvq2R/%cHf32#9ZiNiѦYe$3NrcXX(H.sf(IQ'`F~i}>FƉ~%/&KlM^nkRn2kN>{=Nvf`_A=yi-Rmh c ΫoN䆣Vφ&8A/pKmn.jf [1P Wc|S~V2䢻J"~Y?lVz@ݾpIg@v}J"$(d)Zrz>mQF1tm>tѸx EU/ Af&$!s>'qAq9-*[t1s'ut@b<7UD>ߕd`sCy \,WT(_u#NOup*9htntGڨ^kwu B>vra"o-BCvM^;=wDaȱGv("Un/\umO@bvGw(Ѥ88wm X.b'WNXN'@qrn7On)MazxґWn{O]yK* ̲glG aoZ3e8$PFsy}owz{x Mj|^vH2BS'7Lm!S .6{ v mYVuvGvā;LUڞ5u{΢b|au~A}{҇ՎyngNA>W}F_Ng >Rf}|+ڵ٧G=Blyjbzu珚^w|dwxuع@ 2T@D '6LH"F2rdh#Ȑ)dF6)J@c^#Ϡ S*ԥю,Lʐș0NtG*֬Z\1+XMJݺtbYKmv+4r0gٴo3unC>SVIy%6l̨.M7T 2 8l_B(QgӮ+l\WNكlMխR qy, q)w3g Kٛ95n;-ks`AXvnmaS7ښk`66{teVO&Q\S\ 6;q&v܉'ZMPQ]ZбXCSs!wZW~ɗ2Հ+*J2ՂEÅ֣EAmh2_8fWaOI0Ҍ42Du֥_(ڏIeZyBА1%JpA|:4d)x8*|K\n-_5 q8 x,3͑o4BA+3Cdj9L~ңs˪F=ںUslֺzmvU6ՄI8V G}B%7U}@&DtLrtq ᲻P*͐ݸT>8ԫ;m;(.?J!H#<=(-((e),y LNo|4$q2B^(!B8>Oկ  Qm1Zu5ngA)-b{` U/z&B#Z|#M~0[5\ˊϾQK} " '@/)BVE8 TZK@37I(1"N"'Hb}H|;24{Bq[K.UzQ^pW,1$ )}#3"qb)%&n +(ߡ'AIX 9a'"/ 8Z1lL-FC5\j/"pĔyTL+m?4́4ki B߂$EjUx!!sցiu/E8"(4 y庛62\{ђ6_dzx+ a!p |{E^d&5ފGK%Bc(\.wp"ydžg'g`ocA`q6ap !Xe?$Wf$\Ԓ+ I']#(qe*RG5XW򝏛9Μ KNH2N.4C0=o!W5LiV%tlAx(TfkzFm:֎j [ۻ__EfkoAIl \K'!ɍq*gƥƊmծrlktN^lȦho 3u9W7g68 NP9yĹnCD:qs\tyKknsbd W<')O/{\IozhNjO㼓Poȵ;jo;)AЧ7 BMئ3lHVA2uW!EFKoߩIpMl\r~%Q m]A*gS<'nҿ!SV pZee׿'j|Ssnz: wo?"Nh/z ܸ$fhK2,<{} t&HqZ]GY^\[uюܠ_&]_F_1Eduؙ u$P0R? i!`|R`P^9 ʚ  =DR tM V]DaIMa6.vcm5 D&B YQ/E;^xɣJL=2r"?Jc cKIG:JڤS*D08C"D&8c[\-D:NAD$HdUI5*w^P d'6eLdH$:"+NP:7b\Q"%edF%}L HV*E?n`LFc%Y"AG**7eťHdF)=Ŗe~u@`Y%FE\b,fqKmW lz SdA.%H4$hh i>fE1Fʕ_:E;^qX_R9&Edbo:^BFu'Oern&g^EkgFgL'Tg]%jDፉ1yymN2g} gJY5pS9f5cG0 hV"iBj\# ~:cCxW`:ptgaަ=~{'J&:瓞ɏb&r:PW¨_c&e"2.ndJXN[&eN(Q_, rrT|2,(N[}i2xiD,Ң*$ wܩa'C(h3.$'"n)lṂBgΤ.ިD}8ʢdA*Vdo*^YjadN2^*F'2J8j߯h\ve.jNdC̩IkQUXkzD]1in,f:5 p"ƾ.'\ b ibjn^txy%ޫ1&lsU溲$L2}ꑑ+Ek^f~ ^\f8.h"ѧB봰z'=Zaf(߬⬡rm>l+Ygh&mǾ6uJɱ:Χ;mQJn+-,d2_5 y}2N!,%A-kけZB,e.מ.x&M&9bvok+ ]fLnB)|Q&EZq&*f'U z֭֠l9F-Ecn8h-+x&*DhF^i .pުq`c,f;+o4kVeRlFna~aI>qDD* Wmf 0NoFlgxk"Um{kͱ 'r!~걊` 6MB 3#2\1%.&XD[Bj֘i='m)ڠrC+,22o"kjG\dqi/E1yM~6"aBO 'So#q7EP18-2..bFJ3%3ףϳ3OY07P,К-eLC3O@tDDGGE{un#?rﱬƳ<%Ϯ/$T&4SMLĴL/M/?%N ǒPK.G,%|z4jO>![V2VKE'SWAM4MtQOuiqxE_sGu vrH;uIzvrDZ`eDtW&66,v*7d_NSXvQ^ffO턁5qui6&jbGk87–m5W5Y\oHL6ppG$q[2\sg*uK^?5g睘j_7EdZ-!6o hxw[}yKuwm[q7;Jr{ksbXY>s'wlssCx@b ܄z[8X`8mh8|r#,5S6nGNwno#GXm"p1׸l+w׶߶'Tg[o,ۆ;twrΎ3KT9oF\ڌ'RiSE7D]x8ܾD54Qnhwg;9|E__9,J6<;܁4G>Nz~|婖T`Ojx݆s9#wT0[6Djj;Fd)&Gz*&5ӆ Q5{t1v ;{Dy%hd{=c9Ch2,;Veؠ('80:^4 r9?+' ySa@f!_7W;7R/:U5"8ʺxP#vG[e=|17ǿZoz##<z]$ދ$; 2P 3<;ШCOk$(j,B\Iz0)߈Ϳ) ";:F7kJNX>  Z/@$>53Dl>sKˤӯ2.ITND.lU9]E렿j36=?u*&)CT)"a U4 !T0lxel׺6EKcRYĴTSu <:wU7aYRE\Օh AyNA4e.f ,lDjz2-ۅ q rm#5mӋU{i6ޚ{—c@79b_u,dDhT7Vۍ8#%SMヶUي PXne`Of溽Z׍Uz$ 6*ӋZoT5b4k: LF.m|/SSnsCMts?9DZ3cR(" Kb–Ć9lK4o;D?2HFu!'&WBc"-K ^o)7Bpq&hB hM,t$(,ŐIP3h]'5Of'9`/} ̖ CbL4pO3uNE5ME/grt8QNv29IK3r(Lx< b5LEJR\T/rgA%RN*Rq>Щҫ#˥f.'hVqխԝSp09dnL ,mTuӟ2+vjs:B&22's@tX"h)*[rqqU` ;Ɠ:xv(/Zv[X,w_ Qc!¶ݍO _S*q&=)WsTȁ5-b`9T-|e;E1 C*VGV'9a>ƉdžlG"lvDk;E\R  [(-wXI.NlKQJMq]}ۉbQTΠ,x"Ԝؽ$&@ \HyAP EzEl-s]P/ڝGAN,:0sT]ۣ ^fBeݲC'By(~+waV]81}4{2ѷbM}- a #] tD]2LUŒoN41vѦ8+J99 L*d9؜n:d;X97`toCMb\( *]WvbQΛz؝?ǞfcT,gZ*]0LS$[Y{l>r!zkr7{|[;/4}yV8Jbt8ӡKh4~VoR ru d]'14vZ,B>¥g$Q_vw]m;?Qz5/Ðd^QHИ0ް!./ZFTھ'ALaRo/<(ܤMm2`.ءʴQtf$ 0-x.Oim$| īd4`ɵBP.jfJyFh BH$ l-yaώ|p,%4+ P1 LŦp.ftOR.GD ;N@"zXn,b -D0窃1Q aCbAXK Q, ōըO4i0 dc@<1.&ab>RV Fd n= On1.rq^q7n~V|$M#ΰ@nDq I) bPCC+gO 0RNx`"<h" #F Ҫ#!ͥ!%q 2"X#lȊ #B#c#q}$o"A %yk) Dp0Ǫ"~xBy0!̕ (2)Ur._do{Ү($ B+/ac,iMRɲ8o>Qb-; er"K K 10b0[E:#Q/p"Ԁrty2 3!066S+aHe4sR-pq555c6g6y6=_rO3S+sB2-B,id=3]%AEs$Hs,p4s;-2R/@Bɳ. K^k£*=s#lAڄ|)?F[ s~>T;,{=$iA?g)XZỶM1C|/hgL;">CAY}#}-Y5K(ҹ^ <&<0^ (zPD 'Z8ƍ +r BJ8ɕ"-jdyQ%BDZs̋,BIAc,LA#N!]髛;wm 6X+=у@ѺHdLoѮr+w@*&NKm 6j!:ɒ.ػE%jQҍǎx)q8ݭ;3%䠟;vˋ2R JL[rt&d+23^}gѪh{ۊ?+aJ+M_*g5A9!/x! ֆBRdKY8 ֠%kj1$-HJJ飑4zjШ~j߀`$ jPE:PCQlRZA fgacnuꝗd!S-hcQgi_k&lBJӀB/V$OM@Џe5f0jdocrE+CD}`Bd@ X 2d+O[X̠\l,˜."LnTd9FNNS&Auz7ˁu¦de5p._+TA7Q#7/4xNb&baRC^=[zL_Eu}YE[t:#M $("UPSSآcy+9-dUuADOU_doK@C@1H頷g)@XHs@wxdyV x~#Pr`7t#cϋ_?@1 PkH>6d]F!48a$%S5ùpirȑDe>#őQ)dޔ'F)F;,P[ w mU1A\"䎞c?r"d~3eabdtIʡeβ3 q\@3-2@&cy7YRE)"h0 V a8`"&',y,{ ThLGMjsݜ$v~&cPW?u&$ÕƀW=/6`dU?Ch>q!B )|[B"PxG|dĨ7+Ċn&81NP s*p*m$;ΎE"*Xէgk^Bɠy("F7Ij5bݗun43}zV rdz _VnaWcW!PR|f0!C's1 x= c[NUx&c&dlX$IWW#[ ;d$2v~e%=9-VEH+?1WϓF\1afUZhYcj6?pٞ7$=A:ɈvtvdcqnZ IAZd~o'xG>$YolWbʒ'ћľ7#]t&}Vi'$d63q#øhyPZwsϺMB>('gt{70lw ֐#WjH:iRM[73N}__ssOQZ񳪰JD3(?~*&ADs8O ;-Cx}(6c~A]U}>;?3|y`c*(Y婌y^]cyG}li}0I&-{XW}Gtw~HW{g$g6{o$kGARBeU|TV8hscp&l|o5d7^npa(-EH~wE{x8Ɓb{zZ=5!h<3㐂f"HL&oh7}X}3nŅр&!( Rs6Io@Kb u=ؐsXadUR{tHEQ$^Gcšؕ^c.%8un( \&ѓ><sG3EI(9X,fQ&l6$M|#yw_RX0vTQK0 ?>3YY%TE'?iHqoz]F_z fP'jƎ ؜DjŚ *(WkAqz H;FR:Ojspxg+d!L˗xz|W#Sb1lX(˷IAiz_kdL"H_q#u "G;#2.W9DsdP_׵EbAE* =躙 |`*oP @E1  ĺ%j(:G zzZ!h̵M1k˻?k;-MIKʤlɊO4\Oϫ38#Vd9kNi)5HSk"K;q[n \z061l;lk3 IܒC0Qu}¾F ,Ah]ʼ;|bd˴;F+j 3b~KE1qPqWV<|"Cc%˹ 0,90QÚo ZG/{ XǞ[|JlLN,AeGs%Kg!Evr6 9v q}_ڹI\:{ ˉR|l+ р aƼ!XE5+ɪDjLE@ :q1cLc7#Έǃ6\JDWi΅,&V &A݃=Cx,8;u~LC)Tkh sܤp L3 g8s.^|NJѿRg>$LY݅i<+¢½ .-d,b:^ͪ7tg6T}z֫r,Z\m9:^ҁڎ[H|:RӥGfۿ-<͏ݸ+YzmƧ}fhma-5 Rjuw ݸGؐd˵M%/z"1o܁ cmU!A-;b, νJקݟ͑"}6]$DDYKu-92]ԙm ]; $~J fr >[,A5N|o=xPa.->7=M%˟MmX p[ b0dnx#K' aB>ɊKX+}ЖqYn"$-J݄PFŐNffءsOzuZ=>L&j]nֆeǽ r4-P\ⓞ㕎$>M fq u<]ѬSN⪅X)y,AlR e띮3~,Qk7/Q.2߯z.%_p(Zd~r #͟U^i.G m1ҴQꗧG}}I-偾@rM<nlq1pκ /Z$F彚%Ab?z##nƿyɢ// 1ٝSg?oc߿eO|nơv5zkloFRnV01=>gA}jADs%)~_  $X@ aA^ %*8qb#ШbGsPq%Fb݁di!/Sܙ3M9uZ\Aqώ( EeF?e DƥMjtuڲKY9 *;Mt͸R޵[6cނu;u d -فJ[> L '`mRfKʕ~%W*um=)a( F9_.apZ*`F [/'aV;\w _Eqox yN@:ɦ0A<4i;@I )Lm9֞Qm";K,H7m7Pk)R- QqªaȂ ha!hpO'bRnrlo2r?hJl&΂7 +< 8^HqH@B1п2h1aTЩhJFaǪ;ҲH$n'2s6Nq/Œ|'\c*EM%H+h 4V&HQjwZ)VQ.hIh,<$O؊H6-CUyU֦Wˊ*uT䌾(T33e9 "E&V\y:0dKc[q7ƔŠɦ+h&;Jb@w1ddl>Q~k}6\l> <ň%ۢ]*|oXBAM Q҃3lr#h| Lڬ~7A>iPr#+_HhNqQHl|$#"q! ĵs*Xa愎S#Ш,S"JpHr/#ίiA`=(Q[f<#2EN]ц5H'ehydd 4H\r  ő Dbjtk?[j R2)*>t9+FK2KZdޡ ~K9i!}*DDquTjpҔhF&u"E`/lUs7gB? Cx@`oqva윧H˴WÒR)*3BgZ ƋӼ?܈>D<còۼ{?8pJ?A;89!ٲ`3ʿ=a j5K:@J_;7 A< ;z㾂:A"X?hPp*Ei+69IyM=𔳰A 783¡b+ %\s'\)KB  3*?8?1 2T 4t?5;6$ `::( x;D!|5BLE۰᫯瓈Sx(|W‚pP>,ܾJ #C;0=@OEg4R$+`<.X̠Y\ )Rq<$ ǩ8FĊed07SD)5C2q3oPTF*Ȗ;?C 뼵)F\]HH)ǫ8^$Ha {+I+ HT I;'[2&Ę5/(!( !"_t<ātI8ڻr4F <.;t@fA e Lˁl{s;KÁE(K(IIk˯ HM4$ <\H8JF"˿L̅LM<̲ʲXLhLQ2ͲAlA$(\M{ɈlITKFp!+J&j2GCÁMTN$OJLDBΫ\7MG$<@ɵN˸LPMq+J 4=Ŏ@Od ,NLAV:Nc<¹PI\>C MD䍨˽50+:4#LQkAI{QѪYdLeFXPKR !5<#M%sQ*DSO/M45EGtɴQST%"?O c݈R) (GΩ9(KT 3Tm!P2>QSF%1S՜TO|H{զIZ E]T)U_a%bcu|me]2Q9۫M?V,J},TS j NAwtӁ4Fw( ՔH4`iW}yX UoW t@28UhdX<حSK?JʞX0>sB"ZBJ}˒2xM_`mYҠҁ2NձpEX_J[QϤB,o-Y8.6R!EPfqD6气c(m,Tkl[x)KeEA_&gV5g$UtFh`\!f,\0 1c{ / 4g}>~n3P&]ќXGՅӿ=CN],SB3TiC&ϋVM2i+j"^"&k~yQF`hjl&>kdfLpĖr>W%uV'1 O^-bFV.H:lلmE ZhNm+FZS6FP_IH\nVYΥΈVnYֈRm[ k'nj?^o,V \h@8=g˜l}B3?];NW3Onf[ df奄bU[7waqGp,^ bq#b$WU%WMX͈Uo.lp9Bol>/4wncN}[sG"m,,A;M!BnosUumvqB'KL=N?^gIgl!kTo`p@WQY}CGt\nugfAseµqtyBC;k }|l:(w`[qwoWFX- uwϙ&mr d<.ў NDxQTex+'m?o$7U:tA Z^orqyʧf|ٮ}tgM}_Z;}ZԵpWy{l.>jq/ꐗБ\$ȏ<8}zMK~P@ "Lp!Cl(q"Ŋ*"(WDذ1l/ ;v&4ʒ'k)QJ54p SRF19&å ou4'O0Z)VJ vEQرt4"RarűhM8v9Y)p)o#Nኡ%;nAɏ/cY/kng3kŬEipuc̤)K3C֋y+7VÆA Yw7uj<^i"qt yܢ_US,|=5N;Lc ϶fDJ'oDCkvw6n PwV}NPPb( 4gZѡVMZaiՅw`ơB${%8j ~ ČA (NP ]RdN_ZȡpjQ{HA(Bi8i]ٟ&kb{)*PWI*$"F$~$-3}dfXAR@gRh gC׹C\DJPN(kW4ovJYSh,k["l:O:qIz^{t*tNiڞG"U&D ԘT**&jE.䓘d8! lbyxTl(06x4*mk33/{b)T9*6׌R=Jdm 7 E|QW|m"sJ- Y2.{7^J K㭐qiy&H"˶N(03 Q5BU49bS>f{{Q ZZe_&ڍ'pg0J@1.t{cs p`EvBI7M`e<J#RaPk,a(>z "u[3pf `h'^qgR أH >ɫckGF%8wCPhotR̸9Nc/,^Bd8]7DH]J0nh-S?,DTpTniG ` u))w58if@/ww7]8XsoqxVO OH*9c38udF&6NQH,̥'Q~ gnr)\~&94@nVW|)#K,NNv7x:pZ ߹^*Omw΂akn |![$F>Û`Xh>xOgtF;=V<rɹrֈewarff,Ɠ[c%Ad`^I>fQ[ Ndh9dX&L^hHwtgS$ q#'blvZj`xo!,՜&wglbef&F՗&fS^E%΁ȄDŽ:fi™qXrrH.NfBg]g&ZhZg?Fl٨h&"xfhB&`XhaeMAmGXgWĠ^h`r<.0fnMETu ̃v$j^ޑ" ke꣔"5L܉nXeE"Ҹ0ޗ*~)V*^( N(g2D'^C$܉L\geQFu6`>)v Bj"j!ѐ*xtiE q%&~Z˱{0*O:QDz #jMiQ@\!E*Npv](+nhѩNRʤ0k[PFRĤD xBXb;&Ƨ&Z樶CjVn߭9'ExbĻEͫiEj6,.ik4ެRUs‘ղlD$B+.!~;ZNLJ^P˲ib+hE8M aQP _R篢&-hmR \'º%DkM# QmWX-amrca&K-GQ ڋD:!Y$8V :*D+yaP ^:*RZ5[9^dVmlJ>Z.Um:tl ^ڜ]6,J)莐>'NnR̽oF& RBZOpQ0&mZD ~ⰺ<0J<0/8fgB`ݝ`Nb nCF^VWUZUݱRކE1V_]!Gr.+fg$0%% ϊ0=Vڨꍀ2$(J)r0_22+c+ 2jr3xoA$*s˦ҲN~*s_''"VqYDh3NT./qJ,;31hr.S^;9cs%,ݦJN$3F#3/LlB˧4C"IJ\XI8#lx*J:s*r;+H3.S7dJJcVjQ;//t(˰@N'ϧf']eG(,gQJku-ɐ&PWɔXET#ީ,^6-ޭq5B`VM)]5Pp7viw4es?wtM;~wwvʵT7*҈rٶ2C5&sk55#F~xw7Ko;lk͎[E+ /W6{xۢ#P9BN4U_y[*gB:GQ4ysոcTzN0Fr:tI*Sn`;z9%;u/!wFLY(Y Ϲi7WWBd}LVz:{מ!zk|?{5z#SVzu5T+r$@l[lmRJdNl'i. C+5Jt\Gyel6# 'C@Wth)I.FMۑkdm0ۃ=;B"㓡(eiۤN[! 4rt(b\wodyj_kvvz/1A{4.vEWXY-l Ζ#!(1vA^f*(7(TÊ*KP+6>*.Dzˈ;{tFF\<Ы&x80쑱R܈?F pH0g\s9n͊̋PVeq>J XEb,+Γ ;t) 1OE[̈́jI T`//+tJnKUȂ%Ed-7E- XO/ĨTQ KD=ASX%-6n1Tۃ>\XFMQ l0* V<`T2ۂ Hؤ=Be-0jU.f٢OV.9Q+bw縜hܱJNM5^;r"'i=>2V hz#XENX$8s^b:EO79?Ndq>(Gq=l:ϊ4xUIgu,|_#m\ĵy5^Ǿ!]`/r gU?f"^Do%zT&7+ %^j]?|7o7_TSy! ûj53L-rE6R11k;!lCCsg2Q]}2R_2`:;RܶA"a`W! ~Ȓ3D)p ! !L!E[G02U&{-$Z5LPƾݎ[^4T?(*ou'u*Aj$ :6A(SJSE o4Ah[8wAz Q4"Cr~ilV|r:aEF Dby 9ulg G#5dlBŢk)'Ĉ F:&i"M['za@p?Bn!ELC"rIdIHƯ,%b56yH>R<`p+[JʠzAP"^!|Rb|T23&2sPil2l1MWg23Nf epAqR|9P!}m[TJG~%ժ\Bl2$Y9ɌSkm:OP$.Q]`"Hǡ@)*UbեFqj*v " :lFM9ys:Qb\y8WUN6JBuQ۵Fj*~}TS#LRln)J'{1 ieqT;H~fkVNyl-5 oݨܠӖ|܃$ Ci-IHtɧBhh ^"8(yB )1cx^;# m+$e/_k"nq A(arZĽ-յHe`x(:#9Mi iVYĽM1Ac_ c]U,`}c ٦ IU(s]x3~;.+0&s[5lirD?XpFn*/xPӨ"s).^z%U%d\wL4DԱK'*srd)f֟R85ʧsҀە;σ_;˺xuQ?t !x^ɹvJ_d6 mn!+3L2݃!Nmۭq{lйqlV\ue 9`y4Ϸu-IݺyA906qO;̤Љy3x Im70!WMiQuo]vZ eIsx 8FovtcF:Wujo}[lb:߸(9RpCd+ FRBOF﹂5>R䠂ڏ^ `0.!0 8n欨o&v@JN)]֞/ނ!B+kڎQXPDP bH&ߩʩy~Ckt%x픺"B؜O0 b^,]|Bf00V$3]2[/qMN-2 'c- .rӝ2)1)X36q307R0oS _+1!3q38(9'@&~P)C): #( oL3붳#K=V2!s.@9O+1*s?a?  §|A׫.(C{r;w9254C1*0 U 2^kRt8$\E/'L'j# TD DEb~6I#DLHE64I,@21t?IKL?h'&F@I0~ QAoC2C</NRwsD+ u'EIQO00[&)5B G7SfNiBC.0QUCUU1cP}( P35WAu,Q+ -IXݭS40 b #hI}BFSZtCs6l 2$+"c,.ES_T$\= Z9T+;:+A8_Ux0+5%fUHV`e۴Z avz=e5 b%h.˶i7%􈀵BM2*z`˔[;?o gUXf/]ZQ0{6paUO4b%vюI $hTvVlXIzSS`'5fyAlu d/)2mY6"hJh[_nO$v`voiV$k6T3p24YkVv/Cw$T"r%8g;W 5ws-+`sEM utat#u1cɋf"RWثpIp,q=`ym wuT+4`Oy b*Psl#c$Az ,WwBJ]M];|?jw{5|VqO}w}Tlf+wOuVme~ H{WD"OWE 8o 8?5Xk-58\&PUvq1$_1 /~rESn["1&`EehX/2 Xnw`kqHS{EIw2Xy)c(Wx)bL3=y"|2}wP#m+h;f?y-Αxv+w|g?Q8T3tW~Er84PGSc%g?kyxE!3c^t!"pC4Suv fZy y&h՛pj6u9de}O։ٝ-X+7C)On*t I>V(y oUFȖbB2ҙu=2}DKcS5N4PUߋYzGy#zڧ͙.cnm91}=:5qšzZ~Nz PxQyƇx49\'Luo-у+9eYz}x;Mxw'Hu+;9Ք0S;iog9;{ru#^9{:ZaP5N"xKZOSYMyh q3zٕe}Qхpٲ/U!F$o懹7z \,ź y)لǻo;M wzͺ"ƙ J71zG!-Z>Z=x`A;5ұ7`4'Z&'5~:B-)#:gz-;h83Y<}0SN`gزeJ|F;;Cotp~`C| {u<I{L&Kҵ{z]ӔLX7!b#?]y< ]]{G;#,0/5[{)Ms%]9bY4o:۬D~y-Bl+a\!"%¨'Y\=I^6^m5|m~D;$+ݕ}>~Ba[Ow$CT'֓/onRE$\jӉ=}}yy?ZӻFt߮9+KCcĊ܏ ~I H  0a BHń.*(ƍ12LANŲeA `~93#͋2oDR'ŜyԨ!6arıfhE [;wAT RYٳhӪ]pEP:LɌ3lR~J0޿mRpݺ cU+tE&kS'4%7FB!o\ 䛕jZ/Ў .$ZMdl-RUxZ9~]?&s R"(7R5s.Sr/`_wQ~Iѓ7T V<>K*(Y5eZlE,87eXj1uX鬴/pYGGյLn0YGCAoahO-SIbLVz)m ~6$rQm88gE.A:ubz s+e=;@4EvY8SgUjр gZkchc'^>lTk |3F3*FQҋC4$4Y[Ƒ-[M[ȘC$u2SɑGbrAJkp] ?-buXr)B`~ S#_=L{l%4ՆY+o5`}5m)gc+g5M(fZoWe_9OuwlE>T<7,YQI}!m4k^lf*R莺M=>ZDw{+R;VHDy^ĹрPpxk^N5t)+.*"ҲMQZ5TU(@W-qH(Pf ;<<AIIK^@lx6V>І ǨI^hBw`!(l<Þ|r@-bWجFj-\4\d_۠F:G|ц#DK ɉ"$[q~xcn k]dD9BJ̐]vI%)ɋL*kS)rP̦E>P>6C 񯕮d ~F,^s[@d L,f&__.-wEqڌ@)UG=c Kf 8as|̪9[4צ7EHfAJ7 J5 @@Tڤ(uьuAJ<,$ 27ycY +eOR=qǜ' &Nbմ L-%+u UQu'as`J<7(RR4j|Njn ).5D$Fq kJB|{-CJ[VgMUa,Dm 1)6%IG΋dK,YVc h)EdgϲELs"C#iIHۿr:i,a5 'dMK?Md\ND:0wkrݴfk.Cj7@= % brE'B˔T~瀢,{'RSkѩ:~{)8 /h)NAYCV+GԌ,ZF0=ƍc)Dps+"r@9(]L'$N"Xl[~(9"OYDtR"-nAjCخ.NJxrԺ(&Keex3.imy+鄜*պ[^݆Bk>A3hsd,`5p8}2%[/ R|My gtR!Zg <ӛ.{A* =&y30}e5j .4Hlh N+⯤t0mu%K|.6aMK͉$ҭ A6 ׊^P>"0@ ċE:|E|g7kՍ!3 j,Ȏ(0],%Ȅx)ҸGFXP<ّ |a琮%F*Q~rr"ő'!YEdK茀ai!7gci1eTl<٘i9+wXCE FӇ3 )#Yз'i&H&`iGyKم:akٓm)@Y)H0iGCCw&ŗ !pSycSՒɕgABEdf(}ii7> 8Y(yʅAz1})|+n=".?u~j]5#ÀƂ6~}:N2]qsn ڝ)N>п)>`ݝMJ#Fb쎱u_s^<.nߎOMnߞtng(NFC?D %~.G^.BV! -N-4Ҕ)|>%/M̈́^&^kr=;_U7{}r{|:/m؜c_`KjOl/Fo Դ֥˙|/~o K>~; 9?f)؜{R~^(7N)eOsMa¦OWT2'>+DA7>Y.i; _Odȯϯ[ҕNemܱ@@ $PB 5l D-2TtD4Fcć#A0M<Œ3+9SwNĩ h04ıЏ5`K`΅.RM@/RuUXe2\!ZZan;vE:ϥo!f8ļpyj8S 6Vx&/yL#E/26%W J<.uiaV դhajZɖ.>vܺwg;mSEmƷ+ӻq_x6.yS^#c?*4آ%+˷d8T 9qǝkC ( ;!Φ,2$2 cfzo"$p0ArJ6nȳbHAr4KB䪋p2 0EO ?.)ʱE %؃*0F qJzIN'(rPl-,KJ77-;K.2I4iUHMkUPӢ錌Pr*ֆKi=^4,L"T#W_u*ɂ}Qֱ|RCtVo7ۗDUB :XUќcEP\Zyu l%<|Lebj`JHٚt}'ֳ7c"r #1D5Uf!w֜ LbX=3d!&xBMyG;z㢫cCwEykjNT g.ˬF8Рu٢ҏ{nIm~kŃxqNui3#|llUKrI]0h742BUdG8g(Ƌ?6(7J\+KHEE.Τ3 39+L'T5qrJՑ )ڎ7L3(DEwT-U79UVUqW} 0ҕ^).}C5VVeCQkBYL=#PovvL/$pMJkIQ2Tij$;=V>_zPfۜH\*ZOjLQSZ7-Xc91q ӶUíFƮYҷecK^NV_70͚. tA2/NwLQ-Z^ ]Z:QK* re{^"jo+< ,F)wmcI=oFzhwx]/`)~EkS Ө$+b{wH1ȾxDТlfWm{[ \R  |gڈ|&Mm)xV%5#2f Es8 I>c%֩W{ڭxDp!7UFH\R˗2\$= ^Z1c]%20,BR2mm6M0̸3UlN&׺r͐&OLXbߚMvZvW a끽y8ApG4/u/ l`讵do݊St歐IS$=d;py&[G6u3CJ9Ϲke~0(J%0Yk5o!Y<Έ@QԈ)k=9{5@H8i. 㹊 rJ LA5A07SB^<; k.þX4439MS$XB۱l8#(*ƅ#sCC9|36\CCQCy@GH5A,B;le)(??D>B + t:BjqD<”8D+4D@;|ńC(ES7ܑ܁E@,Zt;DK_, \sAC&3ef̲g$3j kS4m$<Ơd? 3\6w܍܉GB{GK~tMFC{K@0WAHQHcHkJC8$Gպk^W 4H >o\$;\4ļiB|lmɞ,p٣ sd0tH ȦJA˚9eJqM2{- ;;H`˾SY4'ʸ, ѹBbJT̆JA/ܵ0l(*|;@ҤQT l?" 6L,tӛT 7DFฎD*ͬ/'M MܴʬdBt"D;eNM>tEԫN( b̺O;>TNlC@˂`ONPO{HHkP<*\DTK፽tzD dPM.OFa %OĒ ug lK 5De3o|+Ƴ1,IxA?Q,AhT+|L#eӝLR%Pt)uG7R EJ Q2mP>ȔZ8U:,K;9N,&U,8(*TTlX :1}TH3FW 6C S!=RNՆhR5b5TD >B5Ҕ éiFmUoՄ,5 }E Bk} &5N;a7!aNAfS\rY!YuTӭ& s,"K!*5 %E'(>v=9];N`%Oᑨaa'\a⑌?]4 K[J#ic ]L"BVmKf.~+I]ҙ:KzM>@O>.b )> MY>n5DzY<>-sȄ^>U*dPfs>f}Jf4 va\gi^ ?B;Wcfn3 pqSDX"l=_6`hyn&D[h_X͂߄]hI%8y΋޾hɐ+iN籘h.fhU"vQr;7֢iZ[=/miih.N*~id9f Ԥ&緣}giٛ ." $4ciFvF_r N]~kdXe`62akUh7LTd" ;&@ys^l AnkL0mUm`=e3+?{dfE1bF[ /nn FPA5ENa &E6 "1c][n(?ZG թm Idm|lo6izUp.qm;v=54L돈gl'A~F?R왈Jlן7Lph_H Ζ"` Q w,tu̻wwqrX? hgW Jqq1W6 Iwlx/m0"zy(dcB>x zFt0Zs{ҡg{&s1|AW詇 xPu9fk~j4WxȦx8뱶ω69{|pUo||)y8u.v/rwܚh,t Txn z|Фp{Yh]}ևzrw}Ov7:wcxçRcsfbS` „ BpB^%B\ب"ƌ42V|cBw G,i$ʔ*K`n+gΝunɫDi I2eX)Ƌ%BJ nM9TIDZ- 8hU36hв(cm Arb5X#5Բ6d_O ^)r0̚3D?N;?eR:uM3cE UַV֍0GZkjv@!ܔ?.>a][Xl;ӧrӨChiBwlJ%D"F :HJ!z+AHل P]!wDE'r4QdW!wFx a 57czAV{Y%_ERg8}vPjg8i'f]La}9!o&ێcZD\ YV Ũ҉(*g(bo16W@EƑ>$IfDdZ@KF~P:hc%p&)}aFBe:U ҕ"zI!NAd# ꤝBzС eWbkIJ[`P)7Ns*_ ]|vkB"jfb#YY]tTfoJ5*@U-z(; qP[n~* WQa+v2.]g4PqɜF ˲uqFN &yx7cYpU-<7f143NԌZbMt~3Z$u5նQZM\QG8BU3bF4vB;XW`s$ N %6bP\a0Tr'Sv#z/is4N yBO,xɴJZ^g?ٽ)N,]E{'|gc{ y:o0jz7VEx;cǺW*4i~%Y^ޚA/z"'h ˺2\9 CS*R>aKk_+Id@~ (? j#FR!a31BfV< yFLWӀFFs,}Ue TZvA`,R5 t_EfG kEtx30v^FkBAr)2Ɋ@q!RY7*"$O120xtJi"D.t)aR}_"4cB$K@ JHI(E7T<'B: $' A-“J^_7'%G3@3)jh1Sd?"3˵ mF(,49P C$DX d&щNuf䓠̛BX.q'+È`duӔ4iGJhKӗ XEZichA4 #M)IMϙP /Ke*׹ҵv+^׽tAC$yQ)"; udq+d#+RdQ*ɴǭ-,hC+ђ=-J81E-lc+Ҷ5Mn$9o8#@V~@!ɥrahFqۣZj vIJW(R#Iof[|c0 q%LIN '&rKhs]Blpbg6FAnJl+JŢkm`qJ{E4tlx>2ᮂ-\^r 26qcFaY7UsḛDO*\+kVVy&V&msd5'RZf\8͉!3\ &-/.?{Jz35n^p`xuL='`IHS  sϛyA}iyΊi̧o,aŵ[9F]ݡ?9ϵ\Fxu[^l'de|;$7fU/Ե.|y{Ksng݈V/noWU/,l ,n3+o~۾nE7|> v0#e-\J_+f} =3asKt][%ƥ:}K'-wD2&;T,=!5i^xG^ !,{ 22BCM$̽ ,,889DJKV &&2CDN=>H((4"".%%112<abl"DHP‚>h!à  0F108 HK8iB+Cp!( BA3P$@ɡ ;|j*| A\p0Y `A"n^BE nLua=@J#iO 奒%gtle:!g:kQWm!x;2` =&6vԤ@{NCQf0%rYI)iYaf@eY[ETJN&o=C[VY,NnB,ZJ{on{(Dc)(+B*JeGHyH`R E)Q.G T[kD.|ИTjekv6-WR]{ؽV=fRC&/%:F\pEz{G 0i:lNB_}Ab-nqne]r"+\A,OliPq Kdsrtt|\G5MEsTkE oY[]# KSGqLU?ؔUv( gAmDvB/_IG+dUfu9ZeJlD˛F:`TӶnbx.s{9sj»$∖fIy5$)MTՋ5uo4 ">y("a!e7 \% R;,a \!0"ÞmWHA")Z-6^q!%ZPPx:.')0b8?PIJr&$YX=M"G:ז%ďNL(EyX\/=@)i2`㵣091]a# eG#Ƴ" HO)@a"H;&ۓ=M\OINXaY%0D'ɰp%6hDeL fD-](D$-W~MiZ#QKsh37\qh1.Ql< yd^pFKx\nsUԐu7ɓd+irVUFWBdz~O׭5}f>sőI_nBQX{j3g 734I\[4XSҶ(M]-+GM}Pg[":d BfR{ͧ&H]*[ݗ;k~E8IQ|R} n͊ Wݯ~2".RWuoX.6a-bNoo.:n^1Yܯ]ջz8IlɨKitɷTqFa(}ȑ]#d!{#93XGC!Gxx uFSC!֚r֊:ZQjꢪ鬙::tZDvئr׏!lJmqLCyrxd;hm)$| ** ^R$ FHG*ˣUn@_Mdsg 65umƮ%4'Uj.ź]گe7K3 Z"TyzQ-QPː*WUjZ:vȨ_kaKxY۲ }1KlfZwB˵[q  D/CZ4K&A$kWn)ᵑ % lTfç{K-L ELj6fs3nf!hB+ͻ5$ aE쫑ȡ% (q{qPkcЫug82z軡_ 񾐓4{jg{; :i)&!RڻeʭbˣJAoZKH24<kWj(l-I7z !s» 靰*`|ۙLAQI\v<ܫL(Y,1ۿ ',"cLm̪/kEFlK) 4UHmߨqFmcN2_nmn2LųmЂf_&L{0n`\rDÑ~6QPmM;p~nߴwSc[ 0 B1H>I-k%bQݽ4U%!T2.COa܈7!K4;^3M ?y.;ETӞ5}aݲ'w};͌ \da$.d$y]HQ? ^~OJk02?hi=D  owA?*FIqK*x'$pm0$ q%Sy&YL]e>e;> Kn!tW~R츋jm!8EE_K-+z㡜-\ao/hOe2`}^'a m:5WA&3t oD_׻LE k2AB >QD-^qY?/RX?%;zI-'r! "1dn,钡J9hF 7, t!yU[ihЊD.4MX"͌lvaX1 &޺:Uл.ET1ۆBpBxĚ_Ɯ.K Ƴ*3VtCY$k6PS;GV5EwNOgs,n>jVm߫c#ᇭޚwu׹ɻ{8N]vy"w+X$C MϿ#@8CB%<3PN!bO]DJʽ"KJ(;LZh97K>.ī#Y+1 .BF bȌ30CDD >_{?!H2ʺJ1lli+ d:jl譣2xG:͠z^MFiO91H;D!Ӟ$Wc@'/G%*yprr!KGw5L@E@mU3Na|EJ-W Aeqhڢvűl#jL" 4e+ QעT=!+mօA"CXǬx5_lц BG\:Zp3o͌=.bm8a*\j$7$mN]Ԛ/Őz; x|/)7["+aJOV9l&l 8݌ceP$4Ęآ m0MhKNdEk],?Ъҥ9yQ*ӝ]B&V4:s|zz"/q'J]v3nSL]1idmvmjgXR&a{)xe"'xɞiF{}+CIDCfm#l\ڈk@:ydo'QNh}`Ť- !CJpz9 jfeICn蛿}&D% mS[H$u](FQTyOce<5gWd.]1Z9FiƗFR^9Ⱦj]}2jؓ< x D:W%󈤻0ōXRIf8i8Or%"YJnFI0'1BԖǾ=cP5.#9Ivs3ֳfTtCSa0Uԇ)q79ix\Y!BQ\]?RXH%| M;?x^gb=yq^@3՚Y"[gIȵVY59s^͉҃W3 iݹV$;l0 N^9Mcƻkowɝe" Vwҗ&iq g ši 3=浡LWpe&u뜇C0pťr n=tg!=E̽cަfynvd@% (13?8 Tܾ&j=s DA A %CA@35cX>@73@GI9B)z+l,["jM>> "A,lD./Q5H2d4C­;4hCEA.++/dº ͓0,kD.Z2B?,50T@?PM|$AX#b9ӦHPYԾHԴ@*6^䔆B?.ac E>Q?X12Gv7R{ 1CT:4}ʡJynjEmY]-|HT"- ЌP$˸iLCP tMAktJgRMQoȈx5AS-RS`37EPL;PHPT>(5$BڜTDH I0`3m;<.LMNe'8m?9xRSR&mUWF)>ZUU^MBh%G/LQ(J;Vd eE f&7}OΌIClE%-o'RK4iR 1QcTU.Np-eẺ~9~= (xiMPE!,n> X;ه8%mWw5\LaT@x$ڥMaYpYY2 Rk12E%DK[=ض%CzAmXE?m#n<¾UEAWZaU=1U;l k ȵm=.ͽ]\CХ!>41ۯ@]@U]!}'!9؇2 vlԸFy5Ʌ`E8s< ᕉ{L3 <2 ŋWأE_ U>1 dGJ4YC E1^@Ks֘8my^:ҡP -^@]]gm-¥jy} ̀Uj: zaaah}^Q=`8y.^2bZ`S- ZRN aeu v+lm~|\t@ 0^&~H1RE]#ɫ8^;6+a]>f+*ڭ`cQGUt!T ddb@][%T%]VhI!>kBjK)m 9fJfYfifxffДnmDƲ_on<\",]m]nL 0ʋYA_,bOM܃~4CMH.%_=aTNȉ8OZ#OBLwv_ ǯxbO1^麐i=`)H1HHK_1M1e9& e)MS<@ViM(a aYa(¸)̥+91D1NAY`qk. e 1ԝ21Qet>BȶǤ6 앾gxjNm\>ISk>Sm6KjlnXKTol^l{NGjlGnX"_$M$kxcU*mlpmp?jx.`maDV}T ̦K6#61R4pm&b2yGWqLn-R_oGdߣ>_qHq?$hDv#n9R{J _ډ M¸-D@:D&`2rNbs6հn;k$)0 ;Ei"c61qL- 5K7˓AjPRCGN=`?Ѩ؋LVKB/^rY EWq l$?,퓔"ƢL7pPă5ekXwvQgoGslm?AOcAw4oWbjFvw^{@W{?s2wlW0* ?uNuUv&7_ٕ_-Cjo/3dv=,"Ook:煘G߼UpGcᏄiGNL_rX=%{' rdSjuߕ 癏&'fﶌbDut?x$}]k ƨfG|QUmhky?j/x{=#w.E_lG{PoDwYvwƯ|VgxG{V}L2F/= bM}?,h % 6Iaa ,Xq"F2rpǐ"G,ie.l!EA&dyr$mDiJX-avIR{^yR䉰DҤ"4ڒ+S9]+ͤӝYQV,NI=EOvBo#I}.eVgH&&R tbHA#(*Ќ7QO"NSm)JbyjFzRLUMvc%-$W\%Z!HD^bIjPB$H Ke{b{vgKV#/f# A5X#m:9yԨ@*Hzb?VZupHTȭNaDq.Q)l ϖpCv SaƎ|с'ukz&t\QkPNQHaE궞L0= vG3ވtsO:Nk-DFx|_oeqqrI>R S\EMP!*Bsd'.nj|B00fpA3O smdnطOdvK;,Q6wm1ߕe Yf^ʈ'܄4eO Y}$t0z~xzJ}4o>f< )wtx;&m)DhR Y <@ki68\WǛ^euh0cG*}%"vέHQk5GBNH"6.zN>Bk n`!,Gp⋟hC18%fG B2EcljP;ԠB9 1T.IaFTXqRN? 3YWx$R-1 vb <@4xck xTUa!L q9Y1=cYLDP0ҕȁ|B(^:J _IuR (H=Y{F@r_ r. )#a;;c&z,/ 4#͎a&d '9=L17!b'dlyP:,6d eVc" GBi٘S12HG<$RB"IJQ#QKDԠ2>bւ{n5lL䐪J yLb2u -a4Uj4WVr6%}YRn'EP+/jbCnS _], !,rX6B 1㇗LAV~k.ly6jM'X*ɛ]hABDk7iZ+ KYA&U`A~jM3ۘB7j}K]hwC2p22+s>J[W!Kk]fA/^c;ʸR!z|zj\MF$ƒ'*^\t[M&'ww$9uu}=y.>AZ)|rA#Xs?wߨҦr_A=m7\惀 Uﮇna|Y$cV_d#5n#}mLotu]ǽܶ_| ɯh[`C>#-~dbNBZ#B_8]M(2[8+&eB2#S>S.MG"fUJrHTI%#lSZZN\Bd[$gf]+^*e&_ZlTbD/aSbjm1>Al^-P%c%AjfEgRe AСȬi.[@\$9k :lrDm^tbUfeK&qU^+`s.^TԆ'ӎ+e-‚RA'~&̲۪+ܮW}-B2]b&kFn"z)UXFZ5m"ZFh^.٠Imnؤ-~eBx,_U*^L-|md YC.*2nihɷ n-L/&mfߊ aN`fl̲n_VRi __#+Ɩ V/,OAb20q8t27R٩:m g0H꺯j  EAkzppƩW*1o]Sdf2)D-z0q1_qu0SDmoqŨ\~O{ֱC8ΰ )RDE { Dn!#""62F3fFVo(,''s9rBD2[22dqxT"3RCX)s&1W%& ^3;HmhM5]HhsNӯ8k.99:r/s?cQbes*[z) 2j:rf0jN_0op tΦJ1'F![BH:F ; s cd0RpSsdqtS)fHtNM#8Ltw||v1F1F$-G3֤53QiH]K3VgW5Cv|VNxutE_p.DܭWA,GB5I{DrpA0אV2AdLo0XOcdYC4eÇef6 mBgz]35^HvHXI)U4K Dmm3v44-oFppp#c;31 RfP>utA~Mu?$vg7vFbv^Wd7(2 k7$rm*-f3ibO]q;P^ vV/|wxKqs+m] 2LR7W5G{S[o6;Q#X/cDqX8`Nl?q`7U6 yx9d$yfk70?g[cx8twcy81)cmxۉE_99dc/C*}?A۸Kr^ y&_G ˴!++2z999rHrNqk+j3gt\;Þ:vVõyB*u3,.Nĉq*,'34z+_x0:{9uQ8S_ޱmw;:4"3O([}]ɳ>J|n%5="Ҿ#Q D~OVPSkɾ=ӊ˶< ^׌>9J7@d8`A&DXk9Q )ZTcGA)rY?#Qɍ T9s I Oʤ$K.fFa T<:%x3e (5\f挪U$ՃISf%V$ڂ>E.]Jo-δc7^`lG wJPJ*63Q$C$SHqgϟI=Z`k$Ѧ]ԫS~*ДZKy<ㆋUɨ:}3Kn^q k( 2zyGe{T'wvϻz aʼnsD/+к;P%^.ZK('gOJKBԛJ%hz0$J4;!BQ N!f\xڑ9 ? k衋N?RK-Kqˎ|/3pL/Tjn8ራ:c.y1e,E KḦ́1!"<2d2$B0?(RT2amX\3GJ4S54|. "#!7RQ_F/Ubt&cʩIU3 K3PSk>uzJy2^Zl|5!f'䷴tj78;2/O,YWk|-cf6pw6%xC5SsI~ݩ*KzU@y= w xi.H(`xa(dg;eOcj+E{ybKmQByM^.H|KaMqX,.;|I9 ߧsZh֘7([r^t:R. "nWg+C:Z?pU3ȡ!ǥGHrEݣu`ת*^hY缒.sH$uӳљ>ڽԡ:qowv@+U(^ r=8H{^7y$zFGo&s; \Rx2;ڑg8gC"O)+W4VxD F wPg KL<|T>b/QMR(U| /DR+ ֿr* #E!D&r h$qHjw& n{l92AG=dZoIOB4>R֣IcC819 =G7|cA "g$H1qٶ#1Y$iHVVѫWE4FҔL-B+kd\d9ˬHWQF^#  "y:1RA$g60e:'5sA~f6 nn'HFroR:ɒ% S,z}'B9~RF!-7^P[$ys"H72r"9" Aӎ"T =A3Yd'`ʷ6ʕ;P:L#:J JcJFUVSfU%;Axt !B/}akŰu+M㖲H;{Z{1g|'oX7%kr6s^ b[V1;LPuEb ( w4B¡8!@A#tRGpKK٦sgl{^fTC ^לX X%6o ߣק<w aS6^eqdӉ=DRw{ܜ^|AiqHDN3gɕˮK7] >񶅾(!^Iӊ)3ű0dD2B P;fYKgnykIwUg;ļFHJ?05Q<,pdJCmXضڤ }<,䐁DV9WٜM$]sgIp`D`~ Ď~b(^_,2x|e胤x]21LNMƠ=#'ӪW\_)#_rbؘu&ѕy|Y19tւV:?_H_Lmwqi1u B@9 ANwGsMn0춄Mn{W5nvOsY "x FK[zr"P>!@ yϼ#V 2tl֟E~~FOB.R=;X>ulS "B /t 㤢 FŸHƭ= =i%˓U5rj[U:[ς<4#VtȑBtrup L^eN0b0#64[bKL['UU.ެK3AGD]i]qQ;VĨޑMce 9_#@m6K3gbgg@%asë0V=I_jb6#pja]MBBGckv kGpDl#. U+6tb3u4P6oyVfcHh= i#W!zfULWdB{74$wr8, lvR%02ԯFM&K@9K#V@A_#TUhv.hOkA ,6jdvߗ7dAľHxU!7rw !q ¸{t=l{zǶT4b-7")u}@`=)jU%x=CMAn17@/z 8˲qVdgW|6![2|3xw;v//8ce=BSoHx~2rUaccV|)H(Aa5sx#ZC]]@ vC!RQ]}xKxOUX1X<ټ$yeR >l1imG8_L#IKJTx|؈7xcJh'QL~qSo"i My8XŸ S lXVRَ!W96V =H pʋ1X{Y~9iX`3M0+aʈ6&, xj7 {'ؕea7X(v٤rٞ@,1~2sjOtٝp=~ɀĸ v"*( ByIKzN ՏojBDWJzP5LZ "Rᦈy[ڛWu2^Q>$F!x5v %nz :V|9CWvM 38xϺ٫N3~í98(Y֘7Py3J 3а8.VvKgFXCVÚ:3ۊ,F3s B7Ed楒pɄ%PXb9 bZ سd3GQH}+7*{_xL)!B{' k$Y[abiU=?d7<' v)˱($#˜aϼWɓ詁3Hɂe {]UZYZZr/\ң8?] \\Իԫ)Ӝ.nևؑP|+xY=7Ŵo:5G}Cӟ]K|")XQH qz ݻuu !\ɓݡMZ'34]!J]͹A\q#EIY{I^|_V7=7#F~<)%KXholӫABؒɛ<コ24g~/X&J U^٩_/[!.A*b\j <~og };y}?!QbH^!kT䓚[(n>o]&݅5`NޚͧC,(q bhdHg'Y۫O_wQb5} ݥ;gbK=_@ <0aa *0BGe'1FqΕPbȑۜD2ʕ,[fX˙46 y̚V^i]Po7`+dO%!vc&fd=C@VnaȖBlaaAqS9t%mjVbuw]Cޑ[5$gB驔hDEYhZ^$dVeAKS)uԨ[yЁ%˃n6HXCZjey&gRw╃T,Y6ҴhJ$ Wő Ii%ȴr*}ڝ:ڬL @&.Ui+r,g'#"<7Z\y+%RLktj}s7EjYU;ᮺƬQ [.LnBBԿbLŭ!g6lq 3Ul 7Ka5usJ  Y(%!щ ؒy2=(4#nC=abt˦h{ @P},d(#ґ,d>`MN679nK`M3ª- kt"H Q"7}e!R`Zt4RfE5N)Zd G>|Ni\`_)i<5’%ŦVѝKX/n.f#Qn<(YS2Z”#Y X4%'+|*R7%7K$-Ҭ7pu4Z%oi vQh 5T`V5y)O)pg[ ?ĪW,k5ƓcYrPTvEmZ;n0 'K^q3@׏d.rz$HjK+%CR)Gz㇖J_±9oLϕ75| ^ϡSiK策pÐhm/}OeoO"O}#jAr enf.]2 3tt&G|bw_u۶uXu1p&nF2~Gn3n%4wRbGXbwm.4|=G9UI&<rtI%_gp}ݗ7u6G%hW(+W/XMC'EY|89B[ՀhyJ8ԇ'uN}qU5!`XmVI20`=QRt3ASK!j";hc$6VWi q)1]MDӷCd(uBXƂ<7siHcO0voe LZxBDS4qcȇDŽ(NFU%hb"èfv8n27w8C1B^&'  h"8R8x莁qS%҂|}EW=zLnW$/7w-$C9)LxDD)d$ȍp|arrX#!yXkm/lH}ƑaIC-!N\ԘHGuHj'cr POSUY8'#hǕ}lc"1bgĈz}qbui3aj_.9Qtp рtyA&}HF( ߖ/)@6EVǙvuoyt.;)EYd}ė(xh>Rٔ 8"ٗXَͧi6Ɉ4z$$u)39CZY=剡~ x9FeI) Gq:u!iٕY(-  V\S BW;km.'w31Ȣ>)rxa&:yMآ*e$}b9E8Z6=K>r#W^(,Ds6Ĥ&xEO C QnXJŷl] ˘aYyczi:k*mZ+*vvA;,Dʚbz>e^ȧR $ʊJi #)po:Y&)Ȧ3 h1k)Uz'@{DYH4BR5yۺlcY E:q ͊-*2Ԫ)+݊zt8)Wٮ$Xh:(RDBԛ8"3Y:.Q*NYB.YEK˰\ŬvzЪR<7j$ [z}z)E/\1,Goj|U [\8 ˫Dȑ!U5,Z 䫻sȹ\@،bf~J$9ɠѓv̸?ޫWˡ\%[{[œ1R˚Z͜uJKȢIEQ3-jFa#ӯ 7 xIm"M$%[Ck/"r,K5̺7f-bC+E]e! TёfQ$d1=RV}i\3y%=e`u_̽ K\*ؚ X є@` k<S 1ٓ)M3}a7h{L rЯjFȼ-,ay^ױ"iV TɴipGG_M~rar +\R.'k |x-I &  .!ӶNl~^6)܌}ѯWQE0]K2(7~ (?L0r=׀  1;_* ~!LN?P_{nMb!>ax&t-/Oo撎ߗ\wmks,?/ZWAQ)SϡOv+C$4rTqЗ/ϙĮf;m41*pv6/Oqy;plW-Q|_}0 2 $X aPa?%8` (bǎ@$i0aI(e RΤYeoxǃ Y$D.-<:ᵏJj%KW^'Ml!ՙ\k $ڙct[nE *I]XvkJfbetdpd l9JA{&]zdĦ5uXjH-== ֊u 4U.dS}+٥ܩ< q5n 959B[YcE6vQxG#5ajBwwٍ7_'ޤ&zE SKcLUVZ JxunR,({jFFװζ@Yl>1\FUc,r?iiKh -W$욵6 ̂c)eR6@ڒ1>:V$e(stqrK%הN]Ǟ̭þ鞺7.2= b(gM=v[@QvC+w.ZcVb4MaV̈{*JuH#:+ =y"I+%,CM&\5k)T va45TlJAs/$H;~)10¢hч$l; tQHe)/7(2FH'2PPpWlv)xCJHgkIf4~[88A&h({zB:fv̓&6 IM@PDR!65R k :e˲Xvf HP}g+KʓٵvlJ@m˽jbSڌI(Fiȧ^R(.CME5)Tji2*JIFT"=թ: S *Q?#,LQ MOZ7,⩦rGBU=$9NyG(9TMtV֚ SELQZ6#3j=oL<оH)ѧZ:Mmԥn p=D/L> aGd%gr5s`F`o"7x+HsU(W=:H$!EA 5A@` 4W!{0C]Y2s~E $2(xB 2&[t I&q` @{y x ^>qmRla| BuhK]vu =3Y9'ūnNkv,RBT.=> *Sq'x3@2'OJs\ 6\4E-]O?ξ d$_&tfSh5#bZbe( ٴe:R>`. MTswJj}X-Tys_>y.Ş̐`RWwI죪K).E^lA͔o &K 10ݰ93&YGH8~тF8d_x[v A#2cmt_yE(\!\L,|"jtפaM|+d3V5\ W-gJ!?V\fsW` . 7%-+T} WSM A!2GnWK"w3JX/;~2EjG/~~{}!;4/;#@瓛rQ)~,;4 9.͋r=n*? ,sws˚?Ki:ڽ:>3Ө:>br[ @}W?Ahڀ8b̘v\t|ETdɿd{ G*`a4c}@Ԉ(!`F MmR^] IeIjV?ULɆeOn5͌@0*R ~'W2W5WpL`2תՈIm$uؖe]$-éHVM0A T)T;Sћحx(xNvEJH%LPU欣0qz4DAeX| ϤT,Z=Z|ևR:U2DAXȤbID W84ہ0;L[@TԜ e UaHkYt*mp ֛mE3-MUfRU u:J ]Y/ڗ$aUaU U0RC7Uݥ8MLYRY a׵+oL}T@ \0Iqd^ Qh]u?&a`^㓓bj%`rQb_PO=p#tH0Q- 9-W5ڐ 8F#aUU\Q. hHP;Ğum6f E6FbhSIJcKi<ӈ26Pexca$V-fff(ne6 Ҡ;B&y:f )f@dervӈ[OaƗ(eWuWca ibށx[~\'>g؁q;?AC9}ffÉ[{eА_5e>Cp㡵Pr"g!vxyPszK0NQAҺ\5cte?~Nߜծ^%jNFr Xh^a.( PeJ1Hsbyjճb,0|뉠igIWfnUց 1FPȃSͩOPYgm v]& >V. qhx?c6fm߶iZjf0,p2`z`vf)0#,v"v Ն梀?fn^o^U^Xetp$TBNnm4nLG%F8?X Ҷq"ƞiٍ l6]q!/&`& #.K5q\Ul*IVrOXd&m.ҹr Xۥ/ #UN݇hOht6ggeC-|g[m 4(ɢKCDOOa +Rۃm]ܦuns-h >UgGXǭ:q #;n҆0Hrp uq}{hds'H$]s6e8 SuT^ w,lw'*Vtȱ_$16"mC4Oxwvs_OOjvM=U:xMw<$wP/,`Ԩ@ 23givyQ'> ^eg`hd awzJz|/n6δP_vUyJ_/o7_~Ѭq[*wwoIorU _Oױth'ic?Gl pWrZo;uez wWuqyWGx83/$=uv+{W~e~ p ̀0!Æ >P y=G? )FMJ’-Q6D(<6mV)#&ONpG +{"Mt)e xI/bE9Iƫ(\fCWѳ8O]ƏMjuI ik#܂f=j.~|h@V1 gPvdV?* 3K#EĄXl7O>xm;|C}T·nd"L\p3ƶh'z yŷQb'sQ7XBQuCuH"dV%bDtZ'T{TV!N=im)t\}#Xs5XV>cV؁w@aZjyBFdH#⑋+Uڎ t~%_ Aɥr26{ &s5VTQ8c\7-JP A"Z[6O=]O_BJ NRԍ5F_BdW6]t]G 'd:$0{ZbţR/bYP.Vf)ᝨYM}Ah@%h ]:b7nRz^w`)w^@%.VkBu*A<`B2u54/)K6ASK@8@&PG;H\aayߦ3ځ+\P;L#Ee:mM$,P) S7'O!jH\ns4ԗEp35+BcYF܄u 7DwlKT41+|Vyεb=0y]zuQPi?zlU7{gh $!Dp^wK)VXgtEILK_CRV_G:UkhOnA#%q34/K^OTnSDA7NUAo:QROj.XZ}5̈ bnjj26 Nst *47?kMsB4Q9w7oëVǥpwd) 2Fƌm gTP#"7 22Q`=}e22;^ B^Lf"8 J dL(L#qbJ P~: 9W*F}Bm<5Z|^03Gs|<晨G2m >XE&} 9hRSĭ,,RnF);r@T1u'ߗ 8NHҖ`ψt0`PfZu:[˽M.ꜳ_{61)bO9_<C%igKo.)qK~_j,ף1%InXkN9++A0\e91i`bS̍&3k9u(n 2cGWzi">1K|GnK1TSp)[0LE*Z8-$v@X)'.uWfN阷 5, uIJhbWI}`]VR~6U*X]Y$er;^?QɘQBI܅ vfD%ܺy5C*.E2Gؗ'nounPlS ,џfӂpz۪x6nGgv:S,zg}D| Xg1cMN@G5bpp|JYm*ڣW' ̀l[JxA~uj~.?MU!cn𭯬~R!#ߤc|P% 8z<ЫUDNO?GeN=(:sJ>d쒈o%tG uAST͟L_t^_,_FPœ#ŠE~FF6e6}S29ApMs`Mx[~|I@-!.A/ъB "6I9B3[A# :ءOb5 P$]FĜrM\R֬b ڄ0Qr TD[4e#:T"_TU>!e]\tiemJ4 (4@F8\H%ApPG@uD9fAGK^%e9r$hV)eT'STfQ 0ֽdO$@8TSTffb\"M)dcT'Ԇ (klD↔@XN,ʃ„opϩqZ$5@sBgL5_ Bjt|Rr C ygF@(|t.a&d;WL@`YȨn J8 \ZrD[d\^>D#<d$GQZ0&ċ RO ,Xt>Xb٩t)O4gViAXֆA`@hiAf[*'\j˙`I hC)CT٢ F(vFm6AG=_2Ҏ*-Όe Tg} gCz*DDD~lPaM@P$ld8tFiO@x$j>*jZĤyh)㰶eNV]:"K KC&iDM _^}z&!Ik<+YFmke #7}BuSR㽺ڄtR`Jg|,&ĮDyseؤæi2FdC6ņhR&tRk! )윊g҆gd۳>!A0e$:Zp(r[sIKCi:I`Ed&2+LG  j.:Yܢ,lU"ű.W6`.EaJ@Ň*jed΅v.ؘ?*^ gB]Z*},ayzQ> *҈jڥ"nfnD eC.Vn/Rx.'2/j&w\.ĕ\gZz Cn]ͦpIp%* pF,l5"M(i V 7Nd>T(Zmюffl2^ oA0~ު+ seV3J"rp$f@~dB#3%r~ c ).2 '90땣"kS bri zYFP$JnDQܪirK%11-#WJFrqN)Vt` s) qۅ(˨7*߰"qC k^IXȱb("2Os*.sHqg2-&H5+p,}'JW 24pL9sWB]gEkĵB6%gL7YJym?3r#|`beZ1 1˜. 6?)U'2F.ݦG/}>~x;ón1C64V$ p7qCE3L S*Pcv-_uGS #DDK:u7_)[5U`..,fV66|kx_XM 7zݞvVTlU7`7zwVS a X5Gs/.8媱?(/Lo]w[_t_MGJK,dS6~4G88ӈ_M$qi6F3ODd&uLm 3j"3c+bF7+}34ghQ+Kt /;͂.&q9ss~~+Ep/e/da#ot._A+󑥇4qDžOlGo^Nu ]Ҥ(3Ɉ/_4*qRM@M TE=9 أD%9R=!ׄE&*jٍ\]8Z?r΃gPA${aRvoE`Q8OCeQ6A9wV1qH=L¸\p0Rc;K;ذ"v\-w_-F7^,ltxfj>Jv ʥ3@N7GԇǸx=W2@>pҧ 'A{ @kGf )&݌f.(,T( <(E':q!C33ڪ~ȿ/0K mˣ4+M:MnKo*:ǵPӢ1*θ"𮼑x8 A"dJ0hZPsT"*}Q,]TK> RVC"s=ϤT-ָfM0Q'8ϡ^s!?{ Z"Ɩe(/rGI=R7sUJ &C|ҩ(.}-)f#}Ad֓z+D[qBw5 M]%tC&\xANh#NZ62eXo=)\q_ִ.z:ݳbjݕ8"S,UUk._i +aϸnN Ըnu`s+FLfnR>hSR;8Hp׾͉(y9zYT=Z-!J!-GʞO3q'lZU6o/;Z+X6ɦR.vr]i<9KTxp}!J̜#|Hh${}"`Q Gƛ]ҶZw_,R Rc ޷`JxM),NHӘDh2փ6ӆ|C_n#=ts?Pmjli`dgk6 U+2ܯqܖ ,QpV9/3$qWHDB0V4y# T P gUD=4ǿ Qn X@- Tu(-[*X6/?^9QqHD! #(LUV$9ʙaV| K%ȴ#n0-DM"/*.2^R xr^8lnN@J=bпWN__00Bp_ؐ#PLF&.N%-C BjO 5 od.v-NB\%p%B?%"P_D_Ɛ3"\H  -j;2n/A1bʲm"oPPn"ӄTpŰIXBx~O#lqNdrb^Fl#_-8v A0=ft<1L"bp ɫf']e"L)a%y/!Rj3 lK%R !=hrG&1[e'ݲYdD0mQح+'9kQJ'_qCz"+,+R-R -=&.O.Ӹ&&kl!nҐ2@]pBDRp#J)lS*iq1gJsQzr"D@AZ-2` .f17vS1%Uv/c8p!F1fBEtӑ7,QN1;3cWkB3Y<~*_ |ʓ&6"Q6oJ@ sLtBr ׯi :o) C339C2O 3#27~;o N&d!3 5/ JGcRH::JnAɱ7&!:MGk;M)CF%q>uT(1DAT,r PiN:1A/ g5ݘNJD;SnREԟ³ sc7<@X%#o#lrmN=cUStRb%pO?!trUW): XCXZ1XY_LT HT<'S}ZZ G,2GT˵,OQU]B/I7WTN4eYP [~D~4LQU,:U\-M"Q)Z2b4n r>…v?uGW*Pd#d6HB@sH35CGW#ZQgiaC56RCh!6oi-jzbci2v6!GibA s3 t3"!T3mk54nuOmn^Ǟsu gLb;nC#h{0v*մ fw.6RrEwUZw+\օ7JNus`"$MvTfI{^ݮW+@%1,BMבKt3,(W&M67|o(rM)S,"d{K{c@w!&| N|e qy+0gvod+=$pkbx= iLi EvCgטX $d=7&Aϧ;u2@Qd_}B"EQq7$dcx`DR6;NDX/rwU'M589RT?1_{s(_7mnˤ:7) hS+<(2ecUw{|)9f)Xbe7W8nߗ0x,!#y# uu]Op)4xpWx y‰ d X!J`;vtCИ-řɩՍCVEB9꺔#]a|95sؼ3}1ȅB˙&8XC#dH5ETi& ÷Э})"#o(иӣ:{|9p\z^sOVsijAsݳM]vǸ\\`R8WONc=o1E=*=%.~]8+-ܝ}S+e d7坣ݮ=Sښ ܹaQ _%UWɍ\ce/П^A%ة>ps%6}ڪhĚ,ǒc >⽫]Z~`>V~^EUbp?h—( 7?-G5Cɱ^W_M9wh<`gs+{e ?ۓ/vվ;;nH㟴n 2d \ȰÇ'A|D 3Vc )$H3\9Q"K*_hLcyk(ձ̠ny4$RtүyKٳeڣ&:r.T4U )=X xpžeYJaٺ)d\R# `fV]zzms{[V&q{O5Zzby3.j+3n,eˋV?~wPFCuek-SꐷWwY±|v!X1s?`7u|q]iYaDy>⡄_OjX|/_o8emf{""\$d{AlRm%9z,M%̒|aأAS %P\pR&""7u7^;@h7'ɩaɠ@ytgYuKO7VYf rU=TMHaIcWVgE$ J~dnV*K9ްe+ī0롴9VYZƥSU^kml :,J&JfmcEZK}'5A YQ{ŋ"*Ty6l*A/DL@=!Ai0q 9qcɢID~'JehLCY~'ɵ? Q6T1 cP--HjBp25E1ZNB R'CԢ[K:ԟQ2TMJ@!2hEN;Ӟg4KCS4eOaZReE,Im=S9*Բ/UpU`ºbjm%U ~FԞF]W&J.ר>xDK[4d#̍RS-vE\ L%/Jϒr6U-bЦ5.CVM)Vge-^ړ*Eu`;EA!,0kոA.C8BXy=TtOrYFF M]}RLG@ڴ hN͘ބ+c߽!nP}[bSqW<gD 0 \*U$E)u 2M!0$: {eهoUCO.Nޓ Ng+X[VcؚgF̖X*rkK%[DQ%p0L^sO HY3ҊX ISy\5ٛdlc RX&#[ZCwTqB0SWo,LGS&kG=+x\gjcߌ a[X6#${4W*0/D2SeI'[&ˎsBbhQW^g{R0QfJVzܶ?"egOo&h+ߠ\J'Q;^;;jnw&8Bbf%[ zhNz~~6~ɕDS{%:n0owrDEeGQj|@|A&V}eq}U4}tT{kW{5GC\jD`W Ve$i-o7b7q ~18} t%OA@FxA;u!QS8]Vl2e5@XcXօU@\ytEV+avƒO>mQ|}lj{gv1Q2{rbsbU vI't\H(ee(w Azj=eƆu8Ĩ{6ײw6 y(%zY$ ׀b$2GvTpʈ4sfX#7vxdԊXH3~ Ўggk.hd(2{ӏ A}Иg4h~uY' ehn0:l(kDf*i8,j6=0enㅓ|ŠP%nIr(Wb Ћr7Q9`SVjB?#+ =RB;:h^v<05A g)6{+}rӰ€Nīc1D ;F[jnd" nj!+Ibg]‡:.kе:8Gc+?cg˳y,.9n;sj{gXjNQ%o=q ˲A{sWr@Ācep NYMm;k14|cҹަGghsJ8պGK@T +W3»Ű `P )4L(@hZwf"1-m;YuqUXE!;Zԁ~hֿd2e[Gż˼ϻoY7Y\)تC{S{|<35HR:}ñvg*{ĕ&Nl9PVR b0bl$? @hlGo\UzRӓ1C`Ȱ\+;@$i Bȳu_*+ pS, €kWppՋKZRMBY͟\?t0T+em<ւÄnF$̱ONމAFР m_L| -,5ٹ]zw[ϲI&t !![Чfo * 7r̋OLK 3 -#'}7+M c/$@CĹx2vw䷔X){F8H-F+;r*+%I@m7L\^՜b=Qzs~!rm1S+q KtM\Kəzͬ dK AŒ}! Mܦ)୩4*kA) 09<Өi]ڞ~ Ďsg1HBm2c!u-W8Q/BS1vߕ *ۺ-}-텔ޅ5 e!DzA`r}*λ&Hq;; >tL܍a[:<1>NiCD~/F~J.hDneAM$4x7e~g!}ڀ&…jXz6z!d&.:QV4Xlĭ9ʢ{Kn&i>m};X.pnN#cANƮ7㻮!!yr\t|9Tx|_FQm8/^z{~iRVP{ N"1cGG0 nۍ /&u;L'e[V~V^t^|ϸcY=/A/٣ϑ'yވ`+ T//Õ24I9/kNSq )$_COJ/e2? g/Ab׮YOt^ 6OdKֵ+yolFo^ކ!=u?QO+B}@ߵ AG`3L"xB !A*NĘIF uxdy#M\XJ-]rŘ5mfظP͚|Σ0" *VihǤ-sl&іZ*ǧx kɝJ%HYWQBea[+bC c͈-ΛJ-9Vō?9-doR>َOu e\bGmZڕVb,=)aY'`̬yftE?|I˖Z :wѕ cEclݽ;ݱe't(؂Q1_7Y'ro譼j+l?IR2ɬܓ> cAk@ODqR<秠<[(,J!bд1R2hK,v{D|AB%^aι{IC8)H@l-MMWt%݄g3:"no1J-N5$bs!v'B1D*ɥP TH*;"$4 TF U;8cU!9oFJT+PK<2PBmZ 4;;4u NY/^B]K:V-!_fuU[_D3iSp9Ѹ@OKjKmɰLjJ[=n%a/Gw%\mJxO^e7E~^-WOex eZ"W*Ӽ֠T9*-˓JT[@֏cg;S zeWRlG[F1Wy[Xgwַl3 o c1Wz3:"&iеQ[m3J{twyf2mCGn!Ѥ"6a<i˕4ObMRKs09n5=J}NK/az=wov7m S.@}e7C?Rfq'i@-PM/- gtZ4|)OtU}(:g,e?V ADaû0/SNϞ95gЁ`$X,lh'YGJ8!צ~Jq MRȺbRƏpyA;B5]^kHl!j٦ȎTlWdCQk( cȼ2* SZae4!p}<#'MAp%汐 ^F,et#I'[HXPX 8}+ّR9R֣6}x˵9b"0YaɢOb>@&Ё)ɤ&JFid'T`DJNSNWByA8H Җ.E_sD=#Iʬ)K3*1%H٦qeKRMMtb] rTAh+82 ̤'ejJcΥ H̙cNWP?uCQPp-Ťgsv]ϝhWJOR̼L_+SVԬ-3[+f6#6OYQw<*R9GDFK7v5IaItXJb,e1IMdeCiYui}H asEKiN65RבY`ET5[UEuWp!}nMgyJV^r ;ϾqqK{t7#&D0EMVu".:/x\Qmi0u%(M;&d -jz1Պs*PJDp%l8^[ާJOz-+܅Db8C!fڦ1bqz۝x{n)6IUsySoQDo$Ms#IW$H H"f&I_=R$rڟܐK"k _KgӛfZg/{/*'sozAzMps] |5ʚ#xn;F^}ręrw7t" )sSːj*a| V=(r?sҰ;k ?Y@+ HD:v'Q@0>>Sз?@;ck+`D$9'CAPA` cC̊=d{" –@9'*ļ{5cs-cö3x55<@“C`)`;C+9 y HCV+!#>IûZ8;D$/DBB>•E|FdG< xI|v4`[@h7|P$4ۡXd7[Tʃ@FE9EETEwEPF˸D֛O<  @BjGwj CW2I?DԿrsD)lK䲟 c{4}33j&k|0VVDHn,ElH,|Ƞ[>$:;8$ȴIZISDIRD:D 2'`4I`kd0tFd=U,RI,DU Ǔjd˶Tʌ*JDC[o jJҸL#LLbBl  6l*(K;KpLl$̜R4w,%D*Gd)L ȗԜ) mFƴ͟M- N|t*Թt˥ĤKdMʺZ?,0+OnMބ͉L̗tO7OOȸd8ȗ{ M?IQP(0O;ьPDPPMXndJehJ9D9ۻJ;EüɚJ4QБЭ tK+ҌhcNKd!RdGp0[!3"ݘ?055k8 XhK%ATN4G}6cBΤ9:;Bg;W[ev^~w94m-ʰ6DŽ nk>%FU ӍƮ.gOGuՔ՝gPg-V׺g{QFϘhik.eFemHbp7ahFh]D0ަQ6cŬ敔NRgjfdH.f6ue-f6 MjڝkeEkRmnc> c@v 0ӕ^G`lhKDn}f&0_VkgJVi=ر6Mo>ᮎqeݢ>@Cq*hfm OưFgs^$ DdhNsoߏdvj%~nljxj8!+!Hplf~hv>\7Ӛpo=͝&qk_d0a~fqg pAxh>gl?Lj?hqxV1W&g^G}p9sŘNrs[='>q<r"g)C*K t$NN5F} XOdAgKZ]7pu:6cMdeg"O)uRvTO&WV< oKK]`d&dz0AↀxY{윎Ai_jkws?[wApgl~x|wPBiW;;+'9 y pGy͖oWu(ヷrarWε+ j3 aHfc!_z*w>L RzӦ/x*7zw! #{{ut3w4wi _SsT[p(`/ŊGF@1:tvsq1O$N7Q5|P_zwr\-9#ޫ|( K)ϹF^}SVȞ~ 2,h „ 2l0C£7"6r|IK(Xb"C W~R%˘2 )pC)=L&А;&N? FmHVQa)4ҍk^{)²6Μ(W>J.޼zA.oC~xư`Iq#p2ee|гAhZQ +kUق>H˨Z;G-pGCpMڤ(߶;wxNҧS7wuEgX]oiKU4v_9f%;\9ܪ4}RT[AST-7Xo<)6A @\pÅɱԑJwsD%u'ҵ]CxwXbhg ay dL'j@ZI'` "́Fm LA\Qq\Q1Wǝg~}@WgKkЕr_YA56PYU5C~n%k8^:w3xCAOa#2}^+sI~D-kJХIpt!(C&pg#B|W>d,y2`2հ~Sܳ0XBjm<̢/fNp\ K,_d.p1:$| :N40f:%Qm'k۠XKѠg,j1l gQ@FqwCE+o!j:Ύ|JDG>ЏSe#"i;YEQW\'k`l nF/Sc23PFPRbPz(S&nLvbsʦIJ=%l)81ߜK>oD'PdZ4|)laSa24%MNCjHB$H=s<'ishdTi3@AЮ)nҭRdW B t emP Í%Cv$gS(AT:42#RL{7ͦe>5CWMEJ5#QԛDulMW3q6٪HURVBcyVnOYecJȷ>f%HY$IigF#d2 Z@*ohC?/34Zg/<#e l*]f9MzNm5&ibH-3vd^>aG<#lWOrлYy7JyL KPXNVd~J1 ҟ=.qO޼hK 9&YkM'Ba DtaU*UmI)ivN_.ɓ_bzn1[ϰmx`]'L °czE+TΡv89;p_ϕW];[f@iXN '35NV(^x >e]qf X ,e>*ќf>YMxEhy0]՝Gge@ݯ^8dЄg/6OWoeMISZv%Mӽ8j9w2*5tvR-'[#AϽ6$m9_ } !mJ(vUS̱r*4UhHUuGsfK;d [b)?U"aNW^p|9g.?3ϼ6yݞ5 ^; :ypsrIw,(| j]+ Ge{<4rE5`-MG:]>mL$^"D_79˄S&D R  `{ w iqE 6Z{hq -!C4aL~%aBP Tl%\ u\xcRxl$D2AE$A(dOBz3x V_X#A(fn1 2fh> a$BkΎ^MMLjJR`n!-$bל`V6ѩqr_o%YZvnLif%`gk^yHjeY{BepFn'g@$D}OlUfk"t #^auZ'Lc TNڊ\n3flڇfl"hx'`*hհ(xYHەJ;((񨁺!tޣnXNb2_r1)\g:D֠3ENƕ Hp%쩉~^Mҧgv\Mb.&gVg![0~n 9酐BU{Y~&K&hw&Nj*AO҃i6jg.^d^ѡ*%*}"gVg*DV"[B跊`ݵ)A8Q!?DCwM)Âh2RϘ(*&u`ا*vǎkQ-7bOfPȹe?#B:lľfA쫿*]EU6m,](B *. 6dfmFzrƆmL-ق,+ↂչ- j&hfXhlʤ.&..&./6 R|".rD胿8pDL-://nឃf//-fίXo7?0GpllζGlxmn'(?E# pC(B 2t s p8(?pppL q _nCpC@?$0^,1RSǁoJ CðM$Ccg2q1A̱c K1| 1^1-&c CG#C$g@2quTj_0 !W$Æ#S ;Cߋ !arS2erCr2%/0/#D**wrr(p3˄0*M202 JW3-Y03PX?sQqR,r#w2q1A$,O13;s480;ߐH>4'+F6e/2E/F:;B 0[t5AUbZp+W^DS %Hp>5AxL [ L$- N/! < !,l"22rdb\#BCMkKLW} ((4˖󾔕+Pn $,,8jбcd?"~~ h..:mϋ//733?IJLŚ҅2|lQQablHL%D( # L@3J@bD B2ǁc"\1B XHFb8$CeNf L 'LJ:),vuŠK&8X,XpŚ%P n[K_"Ƽ^;`o]\@ Ǒ805 OE1닱'.h}a_7=WFog=|7v oJbGRr4 "&2sK0\!QJId7ҁxpQ >(`ILуcA `H tCv @:P@5hG4T|pG ($0CYX9! ,lt BBJJPPTTNNGG>>2222222222111100,,++++++++(*&(%&'()*++++++**)((&'%'%&%%$$"!"#$%|$umjgeddeec_\ Z YXVPG?851.(%#" $<V g mqmg_ZVSKA93)  !$? LZg[%A(',+%(,#',"',#'+%()*))+*)**(+*(-*)**,,,?????????@??@??@??@??A>?D;;O;0_7$h0 r&"y "     "##""#"#"$"$#%$&#& &#&%&'&'&'''('.*4/D5Q9V=[7e+opqrs v k j k p s t w s t y } | } ~ ~ y u z ~~~ ~~~Tۻè~|tfVA8&|wvvvvvvvvvvvteZemroH*\ȰÇ#JHŋ3jȱǏ CIɓ(3G$B44T̛8s$΍ ThѣG Ux];jJj"C2 1ւW-z1ihY[˶۶i F]"A$,{j¾a 2+b%"5jpeK5SɩJyfF0rOE'g!h>2>kqgѶFJ(.py5F<" Ƨ-?l7=p}(܁Z6?цeJ-RQw|B1(s4"DD"Aѩeur(4Y#5} )bWUǑbPq4$DfWPgXd"vY܂^ @E[ouhBV}0(%]>9fqJRՐѱU]\(3Ps^ulbD񸥟&zPiIԤ@nu_e,W$Pd`f9(Лf]#!R]@B|*NzI}6,H$"uSi6fpj:AjzEڧQs?[H{*A &#IҪI.eORCqӊCjI19\@p,;br-yh"ZrfD y0!Q53ޱ n<&G:2:;-dF=,519ED$D>&57 ВcVIa3X09".*Q=W)iyz Da:&,_ޤ荥g&|ڂdPD"g%VЋd2&sqlZC4TjCNH!R4 =yK|v)6%Lv<D Ɠls3'HL_9s*r4iȠz0#t"\%H,GĔ44AlʠObӟ1,#G^YL1wtQ&iUn-zZ,G{:7s̊u kK7Ov tEPQδ˼5QK21H}a{;Jg^!rZ5 i5ΌЭ|\cFcO}ڛt c2{X)Rm/B59v1tKjVg Ўx[:.z^lPm~ ('W\&pXXYdeH$l$z4.A 7G-!{#pzGlİDiɏ#tMcซJʌM$DM!^kք@9fa[rM%S0&b`92Nm(kڬ7Wl_ n!265+dqLtOIC#:02^\"Y SkI+?i>zc[/dw]rQ!L!:'IGkMK> X[c֎E]\;v'<ʌu,O4ٱN,ש\W\qraBnY(vsa\?q@< J50̫ ۼ&Wb*(ˣr܇1ްg@V[p{lAQv6 ]Gn7rIvN%39obzfpdXo;xCcB{'Qp^U-FdܹeNcCvCo& ףT  #+4J8>'):yiV5p>g0Avc)u"z O23(q {=dnU|U}yG2)juHG}y|rsj7z9's~ez;Rd@i~0&! SWXl7^=Vv4u ?dcHYyiv$rog/w7pGg'x{(1ԖM-8{X &;;8ug7LwFk48CFH`dLqxs\o.R.%G%%ȅ$&1`cLxY|Ldžn8l;evhчGc ׄPAs66ctG~ws#Z[h8 +Չ$|tUZq|82qL!x_:|"!yfFeLwTXڕ᷈ThHzG["!x1@{WBEmxHXjz6 rQs׏sX 7*,}8zȈX~13~b {f?$IQG蘎s'n>臄hYN-ف{8~ϤJhhP):Y0 DJv4K)MY#7!/S)a( qh q".s%BdyYTiQ&ǖQlu^sIbf`{s21fI!a3cy=|ٗ}˜e:ĒYQ(AP[I=nvBǚZl87=gixU.WDlɩ&'o>e陦.Y"gZYt8?8鈞Oxb!ɛȷܗ ɢ!-7ș4w &ijKӦɡ;rSZ:چy1yVeghfꣃIAcAzC:U>Hy7{:MyLT*y"Y19\ʟy}YaQy8SuIn*)@cBahy%Agz"pZLz(2jV8iv0cQGȩZhbcqjt>izXاI{ +J`((AnSh>;)7(Y2O;7:zBV5qrʮ%:O4yyz:4Qb')$5EjmZKJ P>X4FZ K+~B!9QU唲&(c]*F µd0:\GkQRѴ a8 Uz(1 ygwi2%gjq!`)-׆S23n۷`y;@jKR]¸&멈*r[Zzi7K i#EK qoǷ^B[旮w2" ˺ۺfJi&f+Qٹ<ġKī)VHU0Yg{vۣ;KHb t+H"̕$wJ'K =aۋǽ9&y}*lܠ0 QS+p)&/![Nuܛ[<Ò;뷙V+ԻSLI2Ḿ $&5Z (ͫ,Ɯ6.e,&r <A6Ǭt9xI{4Y+ct ];Jl%%{e3N6 jjâd; ):RC*yˬdi)% *Q:OR$i \XyW}\Іȵ;ŷ KڻlZ|.)VB33dJ{{Ct !*iOm@ KpK Oa+E"Qg!)U]}qv֙do), ;A^H4|׀sYmß?-zdHT  _ߣJ.ݏf Ϋ&A7?~H~sѵe8d8PB JK66yiCjUPǐMDRJ-]9/1U]|^|PÚA.| ,erB ЗR~mt0X69BkӤ +ʬsr6oL{*f4h*[s%X/!iwaͺ`a WeTx*٦5_ D1p-hHXkزxB;ܾUFeb鏮gfL.%ıQî+hZ2s " Ö(,EQLB8Ⴓ8DG+͞ˊd$ _I|+|t){ 0PL0($pCɘʯdI/4tK.MZM WbQ * I6YFK1PO? H*J~N?P\rj%Rt P;AE)l˴29<*QES5,M)9劔g'3/= +]]ШmU Wk*6X#EWżrSޖLߑHe$u&!Q*u*\H^Y OWw=W!*V_WՂ` ( &2ա]xh &08P(yPRm$jUpzyrרMj{eĶd*c =,~STչ&^y.n[5:iȾn2u[>2wItDYec2.ko㎥mr!$HW] jNq[_ޠ<]İ?^.1W5tZZ]BKCSc'> =5iFmȕjbswdT*6b RƮ=oO8c,*p, BsM-cwK<'ShW6}='#:kb&?@؃lb䇪I02jv8H)Da9iJ*4&C鲗~,5=K82ke+ {i0toǟ;)ՇgJQNjdyU|:x cXK:aZւ5jS~UyYj|YuM 3nzXDs!ӄYӬ Y6Gfu73rgw)|LS14T\^7[e c!+-MSD\F5Ss;`P6%5u#HR vl4Fw`beP1fլi=`-!(p ;kmQPB,Mr*`+FIަ8I,x1l$ W*6e/?A<w屏 dl^,X;F$WP#Z1kaI+nyIfwUHЁբJbT>h`yjo,Qi=cWsQRg 1^(7 \9/QzM!]ǚB3i;gf4-10As+Q7Ԗ<V7,vvd-"?{:uB#hQk\^Ȗು?:qѮ)lyNhCǂ`wPxҋy>۞J${uJ{״҄#vּ^Bz/=!|f8~X n;oŗn7!Hr=Ӝҹ-9+ieɉr%JS!7$iJn26^ŝ>x@} )qUaJ]\+|J5{hm/fud!+j̀z~'1 t߹lT_[D];t4:;ȽH. IE:Ft+2\~t7\\kFgI,Y``Iʸà B*JfH4EAܡB I-lD5AJ} tb64#34?ذJABS>r9JKmK kmlM yM#ʠOpD&J|T7܋|If캌LN1 >;̿Nk ݂ZҷNs̻< dOM20{ M< %y[C Hw8TΛ5;T,Pk ޸"$$У& 4O U,2|RbQOtѫ)Q7\M s%GWZTGdEE,(,aC,ʖ$Dٌ* c"3M5JKtGQE ɩt+R)PO%чS˔C'( ѯITҬNlI=1M!L4AR'y4ByAly<ՠ8=ݐ$ÜڪW\l`[`]  N ׁɵE-ռߗYHہYEW,3FcnM򽠅]aIJĊc"b|8mY}⯰NJ˘Vʊ+^ A&vf d`r[IOaTBJ&Zcv-a5%VEY@Pj䜢ԡTFanXM_O `iVc߻USDfAZe ̐"6@{N~`NFK Z=":a._did>.cܡfj-*vXI @ fG}p7WPge&vgY8_$:d9F~V L%c͝>yܝskyۍho`@-ف^y6ӜagTgb 锰黥g&h>oŰ{hⓘ:jj<(ꭾtj#nNh֪VίuiJ.ANۜ]`kjnxă)ӤvDk޽ìN#ѵSlgfIʐIsn&kԳ2f8+on6m.<^^am3lH@ m1=XTfl84|"^2]foiśnn p pn(6^m*o9VnkIꤝPOqߓȌ2+:So1^ܖe߾J馘hR?p$>ek,qk؆' (r(p(r Co8>AǐH$efq]9ioX1.9gp,9c)p(pn wm>]!cp>@?nsD\ڮwsK[]EQ>\58lwE|DOކ=pn>`OrUk9&sO\l&65K^0;  7bu"EAMVrІfvp"dr0?FMnCf m-Sf핀RۍzjvbwW\7D#'"zG%&_|p4.c,_sXØT;^bn-0oy~Nen:ÆsE-X+zw@o5O ~C'ao(ma~t0h?v)xX0is~Z?/pz"gho`z/{ 3 -f W>ynyd{xf_{}WiU<׶}xm:1|0'B6wmsh51|e5}}@{n/poW-g(OMWe/3҆?sz)/ ,h 2l8PÈ.bx K<0!'Z4 7:9$KTi悏7xʝt)PP֒2Mر)T3R]oYnkeѶ=^a'\nUײ=Hn?wDlk`PH>řc̈́Gڴ'ysKa_MfMZ0 q/MA?& K4nˍ=L1Ύ<]Z0|>h!Z(јI\SO,Mux)H7Z:zoĥ~g%\툉؇9 uZMeef ƶQTUU1g1emݹS9x^-ޤӢ &GZXlB!ɧnRŨzvI^ՍH9yUWBaԥ`_O; ҙF&A`#m(H,СX%a$T}&VTF b6(z2W1hT] &٩mEoVYa8cYX՚oR|y 鞚֘dh.2Ϣqm%We+np.u|:c C;T$0/>< A/tiX1Kәræ PKUOMSU1k[_9D 7^,d#^Mu$"CtESV@钘Hϸ>yQ eiF Ae^u@Kh 2E-N&GѪi$;CIz7`GTS#eH6yoě< G'W},"Aֈ! 6RX˃ijlJ=[n]~OIsL&PkX/uV2': u:D=FJhիƑϩYF*c .[uۖJ5jE]XQbR%ror)s 5/}a ]$lb!_vml3bu!mlGS|02 FD+-p2Z얐 5"^-Z]$ aEjbh nyu̓V+PY/ޫ,lhVv K?HZg\|e/A :YF:)_j(`*e: ;&!V}U:ġ,@$*X%1HkE`WǐI, wȘ}ґnx쓥,IVdqδˋKPҡ/ b-D=ϕM{f︇?>REM]O:C>hA5āJM^]UE asNƆ"1dN,-iW 2O6M!]ߨSBtJX`A ąA ^A5 Q5`_֡A yM;$6Ӂ@BȚ DEQPQ ijA5B_aj" !,衳"C b A$%&[LdB"_jڦ&n[ojofgpK*cz]yv 6~B'vjX3I[RC!EgQ^bb0&E6zZ {g}'ħB6%I-"sY eZ2.fRۍnPxs0(]*&^`)'mhSnJ%1 '.at¨\eD`[(^P3JGR;>)m)e VNj:zcR)FڇNIN7U\i£*X;' )!D#r('@FS0iwYejIjDDC٢S9j: *hyi<*8"&#iJ9(JnLߛ)BЌ6+뺀Z| ڈʪ*.$NPѩh*V)CxJHV:(_P>grkBk뫊+F~٥+:+'f)!Ac-km"FtFqM %†crh9xk)nhZ,*Trz~lkխ@g뤊iHFmeJb6ح$TʏlةҤ_XD@lx^Ś+‡*FmD^Rdkt<)kD̞ȷPE`h>:i nA m8'+~ޢMgnn2n)At)/.P>Ğ,,=,E#Z.2/ȨViЭŖ#Jiz$g"ҧ,A(zkm}mAx*,B'$i(e/iJY2c_n+IH/K#6/pn !Pqo`jGmVlx0lWpzF Id3_@- +K$p/6R< 11uXZi`jڬAP1Z1bM _m ONqNMp쾱1z.cGGH¦l߄h ;oVqr`#KEM]xV&mrx i6i1@2u)[I*?GHo1Cį 2nr.'r/3+dx~į^1003jqMh1q6'5(/ ,A3R40p-)"Dl$S2p%3?/&FϏ3@Sl4 tBBkCsD>c nAoH.3b/pE=tWrq)=4AmFintmoX?P83CjWSo}UnH qU5f)F3 rr@S24ZNlOok2#31ecrd 5vnuY%Zu\56@_XvT`,|hl]N/OaH,&ՂrA5#[Qh_ #l4JvsYema3:ovCh=Y'r'w$gw6,ǵh/i+7VvK*k3pdLslollycujUc)@3pR6Y}[Z~w""t=p72-'s%as(ִ'khb)W+xDȷ7qc85E7qvUvC:+!;N\x(nxow8|8цxYwYKevӊrg?3b6t˹]޵KjbhHCE ُ/@԰ Fs2Gy9s;ēV xc1t9;>ƣocz|7 cb2_54gRc%X'u/_P9a~7tCn/zܹv:3{"Mx_6!Cxz'q "yO9î:Qڹ#/4eao# 扜hny#) <}}q]ⷃG7Y-7^6*oٛ}MV}1B~#T}읳T`&>+7tq g΋{Dg k8ojB0仲M~<׽'_?@,8`A` !8`; )*̸q5A|$GX%QTeKIRbAG93E&vG)S9Z&ڴ;.r rЏ^Q8 VQm6O)k*A Rz5܋k7r;/غ領_ <90e˗1_8sĎ'3'Pѣin箝;nI4҂%U6Ǯpe&x,KhCN9'pC 7LܦVNQ0j (E]B|}“Y>QCwY/ +h ʫB+Hȹ4ȸQ@z#&+*ha&΂r92/ĕ/Bz, S[9ۣq~ZkڬSC %&4 dz@F:ďč-EӮE[/Fft/e?C=hDH GSR#0srdL().CTM̄`}kR#55 GSJ[j@b-_#4/J(m9AZ%{2kCYni|:.(`;W]>xnʜV9X?W;b&Fj9lkFM5ٴ:3=2a/vOp٫T^m;gUry}+|V;i^\㓾;^ϳݠV_ݭ_;CY/!fȜ.0 #<LH0))O-4-j3֏&y*W{J_e7gn[RBYSeĩ̈́N;gċYdyg(7@ajqCqʢAPE/e5BU )ԭ0$%;Yr@m|a5oNWv?\ Ǚ<jZ=d2C$2b\5#UKƔ4ez5̃>5+JU%8L4AR1}96/gڥ%`&V @ t8@ ? P0y}[ (>O0BU$( ~LXJ wV`!ՔF#KWÆh4v=f`q2$)K;ҏ\,ST%H83Nl,,ȢT )Ğ*΂v UUem*Lmb1]r ȭ;_LUfQֶԥ,N3Ӂ>rZs lw'TvNj>|{]j XMk^˗]Pt{ޮD"iH@5lIO~Bynd~%Ժc&Q?mP۹!ۭS`!=R*UιQ=Zdac,[lJ,QzJf!L$css\{2L`3z%4'fIT%u+ yU:[i;Z߈."Jj!B 7-uׅ#(*߭rwCu$  DMF6mIaʆxcdJJ֎D=ZWo'ʪg M}]eO|q"ķ拇4:^NOb W& $px 04t n&C|#܏A p(0 $*b-ӴeR&An hЇb/!*32 F b nIڏA.c *mST,+#QG{,gC.!)2NG98QVXrB#/%&b@r!,'P ! _r"֠B0R 5r"7[OqJPPiotӢ$= ,LݞX!q&I+.'Qp# (1#c)4Arpmbk*2AqrSn/viRdb5 WO 0[T3m1O/'m"|"R 3)g)? R2HP Ut2.'2>B(,r+$$Ȭr5"2#J<. ~h3oVty27w'{>!1* @:1c~2kȋ 2 I!ᆮ>YA ^>B:GjBo?THk-|P 7@t%DTbcK%S>ć3;>6b@d Aj^n$s<3B8j-ZEHN`T5q8 S& kQ ŲKG2 KD;`TtEsEdm$*W$O,"z3c*nrҿ4u]`A3J8Qd=ҚRr.KQb 0mBUTTQrێE7rW`ٴBrqhuNW%ldK]MGC3S"$6N4]M>1.kvgu qpFSAij*;HrLkQcclElS_qe-VeDwjł]J4vf_2IZlvf i#%Mt#h-*v[CHqGt\B3GvY;H$Z6U3QW%u hT0!b]gm?b1i#,w f $DɞHKfZTGu^ |ԗ8@IvQ$!:jx@9xn; 5#Ev]-U7_6u*O‚2@XdzXl@XFY"WWԷD}]Tt#~*e52Be$ 2gk8lSu6M]v97#N(p=XU5zQYBld5w[bwR9!PykUǖ]ϳ5X Iw&’;Y5f=J)8]+mqYfWu+Μ]b'y]V9#( 2yB%J#z ȡ)R>$zr_+yVuϣ{JgB:oybk(N:9$Ue.y $4B`jښ[C"!C!BIYO:IZ3cLc 0Zxw 0X'62ّz%%2f5;_պ b1#: ~#83"3Z)ZU-:+P>#rX f[^Q>3hI[<  .?u>/cӘ޿W.`};R aٽ="ZU,~~dDBEd>MaM'Bxh+~;>7o47w!!G^9yW?%tcw W5b ?`O cQg.DtQW wǿ}u$ ׶Irv5R* +a=XD{Sa tfhI=BHx#ʯTgFIllSQ b3o@VᏕ{ aiY>#EÙ\$M~=P&# )Qg-XjC(xq[3-QQ-eCajD5^kf h&<,ui @AC XFgXi fePb2l $i8:vlu;:wLT9 M\}tmo< 3Wk@b18𶖖*uS&j ǧpahm\!YS5աrh.^4)ӼI 9+&Ю990 $T闈\!!CX=^"k ^&_Ϡ<8VNu|]ޡ^2aLrzAQCiԛ򆍆cwE,O5 S{dfu)$Q`1ORT i)VqYa =cqϻ?k]n2`ͻDQ}?i&9fwGT/w{%sr7wtwov'!Ed/W}\FFUapkX pӐ +}`Mguⷂ'~(uC^wf˶[c `zK1rFg|vg`v~{bsxX#VtA'Wp1]8;+ g]AT39 eiL1 J J@n y+(K13',adrHaՃ?91:1~Jh؄gGas\9GhX(LR6QdXxap8< rH< 'p w8 ,։1JLj -8"v~߶3zu-fdvhpIL3{P0 G#b2`Uv 6>RD(|8' e )H((Q&(◈'炝' 6!!ӎ~C"[W0)ѐCvMXh#kP(J{Y}z+ՕE͖sgPDx&֗2y j0qxf"N7}W ryW7+O{PMy-7'9Q@xvAq_Ll\0'h 0RGC`yZni4vs`sI@ИD ͑2YUxGBgWa~S(B HЙ~)oɔ ()!n5ar&{tvc(1l:Ҋ9I yhj©z%S9Ql|)hl(90 I39f|Xj퉟%Dwe&QK>0;n _IlIkvSAR(8jLKٜɜ%#&*i+& aNxI'xR3>[hz!r=(|(D#FǠ.'Ȋb_ SgWnR"Jd8Y #wZ*1ʸ_b ʣSUZ`7`aj b 79b׃YUT:ȅhL!tVj!lJPt6 ڢCp*!Bq$267irB®ZXKs :aدh6ɧA;paL_WX( ,pD `@9vR8:CkyX9P^+JZPcd} qX.Z8FWW|da]B}j PA.[vۮa*M9J4caa4SdڪJ۠۸KXq 60`dK"/ 0醸<$!- ([71-VjN  @[Bx Jl벼ҫQ@ı|JfZQ(뽞ks'<`%)pЙ%ayk{D˥勵<+%X@3'W.PDY{Ik <;[qQZ apӧo pkbtnt'WQu7-Â/[#X3*SvfSnSL<)  w<l$WZŊܢa<1$'ZFjAsu 5,%kzܻaԁ 2(|ĶO M+ 'I!H˼'AR'W`q+<<5 쩧IajMncSQǕ?)%) BY"qYm'l%[CAs-ПELNq\Qی_0]1m,B'鷄2Ij=땭J:g͂*7®ײ8 ė t,p0bb~.پK"V { 0An#ze؍דO/Ʈ^<щA1. Q7&!3=ϛ q?Ǽn@{A 0ș<Jo N K,3"Nn&:%狾Q^+K!!-4uNPR/uRQrZQ"(%M?V/--ݭE>qosBf;od ABb?H^qpWS/8t!VQϛOI|V/y2uV%<#Ncl_O|t & xYPA .dؐჄE (QG )2VҚ2za"K.!t׮>w [z\4pgFCpdъHxtƞjaJGjBe֤Yі;2dUV]8?- mՈ״& V!, R%cȑ +mRD-[f 6VVj 3D^Mw9"cP5F"@@ έc0ia<4q{dRnvmw^dxYȐeA 1.2',{k6lbA*Ol"ܶ㫻kZ 0튓 "[DR>jNDkP!@t(֨Mt,rJ(#<+Z./4&Iʂ(Ʉi6~4C9 (."<bJ E,91Ƌ+Чv/F~S9!b}f(/Mᙂ(&07b `\b4'4L^׆ >Q` իF p4av&ȳZڼV;*v!CՆ[BYŠGVGӔSO5/Q#TTPUaE'ZmMIi#f̱d+W Z Zmˌ:ސLlF%Q,rN2`wp3N `Y\.Fv^bd|'(M;4T>5U#XnMn㌙rJ^@v;9X4w۫3jǻ=!1 "\uB-r49(r6_wkԯ {r:RV R2'X`UXj#nkj8H uEzt4pf~3NƙH 3]˂|0lFs^LgR˯Wkq-@^+>ٝdz;UdxŃ^ɐW15Py^FY(!R6d<8КnO)cUhg9rz.¹8sX2nDT HW#y$!=x$^vIqr2-3(J$ly͛dC98V&: dÐPs2$ Cȏi F 5m-R[!/ $LRT11k@f |ﶸ тXFd[Yl.@M#0 79+K!HQ i$PUŏ $/}hR&^ϠB(VJ/r de+²%,zh(|c }!K(1 P>iL=i<;d7K%["ͅt"0EGzJ#`AЙwT,41/oxs3F k$<va`t+)yي&Z6NL4؂U٢+EjAeԥ^dt5<jyB niqk*%qx@}7-$qmy-Xmur.%]NwnHW!|mUX)Mݾ C7Y>nΏ*Z RH/'.K+!e[mz*]rlrP[q?? *쨓>:;@ʢ<>>K@S-"d1#0 +r{4= ܛ9skۿVkAAA<twⅤK* R1jK@ \B`E"akk j9 F4ÏO65̿4|5tErC8D9:;|9@y<8;k:Ȁ+*DC D E$kG*8XԸĆ`+JK늴@RA;í&ƃxŃ /9ṆA?4@ *E9FdCYƊm@#;Fa a!v4*EP̴P#SLDu@Z=x=} ʢ" z@ btBD#@r+ȡ9N F4lT1݋9U=15`G*IV;IZLI$.4\#]`ԝKI,B JD0yH4DHG?+q2|LtˮK /+9J<ə|J%IpUp8ڼJ#̐҃Fia.AmFpʲL̨\N-DdAh>u|̪6=EsZ}HK4MM@ͶPI"$CȺ\CTFk(?rMl#ƊPT̽2,?N\E|ʅPD/PLllͅx L P͏cSÊIt0h8 BzCX2|&MJD)xOrdujC$QUA,xO݌݌O0Q휿F ơh?#=HR[ $Qs*=1]Q$K% \@;!%8SbT` .ЊQ^SʅP(.̣PBT`ωoۡTέήTL]M}RЄv"ֻȋR:ȁ,ƩpMx%1TSUw{ .|D=jTǴ BUD V*Vp!ڄ UILH@?\*A- X/dFՉLޣRcև ghURSRM` !YM#!QmКِS;׻WެWRG RB5TPڥUԦçNEZHȫ5،Z,LPd۬5iv2۱R[m1}[<&q/X ɋ<>v's ?^F= EVQ"*iSH_%LZPZP9XX MV MtnO\_I "]>)Ӄ ,O48P8n% 'Tb*5`m6 ߙ-:ҁ>`+^T`y]^Jib8Ha/\ EmR)fXyYZNAPjQ**6maV"! _e%+a`J~#d7K#9;;0R%$X1ڃ3v~a(UUFDWXNιXc͐2=~_-aaDVfvEFndR/-zTlފm܂<3Lάqb(uM %i!@ue|ƈ}NY6hXa晒IKhXh%P-NI}ffaNV/pnMN_t b:i{ _Fdh%@h *+nn`vhejtGފ;@$(i") /HRpd)B<6(hm@*^B.+µ\K f%lɞ;6>cς$afiUf@m8['f ^]n%iNEpZZ pX!GȦ&zW>ByLgNn~h| {bM^61 ]iY ↹[6.1ZhB p?V@j%"T$[΃Y:19qdDoʛ6]qq cneAr~n*A&'W=(r)Nj5 [p&yA0XDIǤ,97wsq[=7Oe(rtR& 9L+O^}td~ 89jtu=LHCG\'SuSU V<3s1#u *Lj:JEp@~ڰ H7v~ E0/v-iiBCL',*gMns- 8-(WuXhì{$ϵrƭ|Pw>X%_(x|efGNyTg2~L8n|ڕ CT'VߔXMwtZ(?nbG?dwCqvh^$Ws7ɱS:w{%{ENIԑH n^thp7R{t-zk>wx± xxhX|O(z&!-Б[s= ?]/H0q՗{q}`'R AFBX p A^"4Xp!Clk׏@k /b /k֦i@#ɒU<0X&_fd s&͚6o$ ΞG B>(R`AeMGe.r+SLl>w4&Vk`܂o}%ۻ>٢: n]ibѬ8ە܊>ZX,Ҵ&Y5c\S! ]nxM((_Þol_:YҘ/^ 4҂]31La  :ͼ,T?_s=w;2I fE>A- hB֠6{i'0yr(x$^"-'sXs3Qn8+4"5K.pOifTD$xѦ}'RCM4PqG!h jچoUy XQpEuʵ1ŵG%3@c~3YedGE BiR$) mJR`ƹ|P^DדIu@Pso@~RfmhRP flAh69y|zf%2yX/h|4B]C0 ¥^8fdaJ f藔Yeafq+AIJ8-MՊ>GɈ 'S\gm]ǪIOoj:ђޙ2䓇j=mҫ*+IsCAdS%lhB@ldu.p& ff)uF7C+%̒ ^ag4X[/Y5}Oif9CDzbV~ٷH} bkvA:xBi*nmHyF(?_TT3s67O7?磹 nC4Ξzr>U\Y[Us%`Iezb_S`G| EՆR.= d{MprC0Bb.w;s]r < i'ib|֪B+]W[51 Ԃ`-5h&vAUPv]-l a(à&D/+/#bŇb Ɉ{C"N(tMb7CUqX(G)qvae.aH.T5Q=J,nƢIȾ26:B ǽ=9ɣ@d(fDR(i-ݴeףu+!ES6W-*@iLjBsͪ5Љ-^8?ZrVqKgvœQ램̧XP)4}.AEgS)3 Cm3.lC`D+*șy'UYMY6ac4҄%iA\8kaKraVcC44=[lS A ` (sR(/ tM0[WRlf(-Ϡ# NJ63ze7_X;$I+Ioݔ\ PfDNh3jDg(^%~dnrԆ+EFpj_Dwu w;uCfp7x_ToZ4 $@fo ƾSV˹5+ b<bb}ˮ@*.m9? UWRƢgM xm@eA@A17?3~?o{Kh+Ċw:F=> {)[4Kv~"i/) `Y;~ﮣ7Aj4U 7%$F7a1Rp;Hd]Iw7F:׋/٧_YER%Q%y\߱M9RpTi]_e1MYSyA%= y֔qZս_ ri\R-jMdPDXmbtShIVKVUQppif`߁q_ZxD|] z^ Z~Ź u`a sŅ PJYdOl!}ᆄ!^a!`OTQܖt r ^Y  e+nb ^J-%`Os RDbOP@U""&`b'uM8_a r-5I_\Şq+f,5I@bf;ĠYCGbv"c㧠cBΞyA!cGD- d)A%4VpF6, 4JddMX7FFGcfeVP;d"*a#Fiթ,@iAEoM!dI}bQ8EZo8b ~U3QdeXJddK `g>4@Qi *H'eA IQD$ 252bHc tTRIe@ҼEfB $cI܀ ZWr„jGxF?$@xfnew_g &pKp %qjvRCs'+vH`g^:a~=Cf4ifIXhC胭_0$^fF}D1Hm"AgmefoF0$ؼD5ޅqVb~5UjUF煞cYʆMfd`Ĉ.Dx> CPևp2"6l D(tcq-qhWۅء r uEٕ,ܰبP$2 !͓NF<$eeD`lff))w(JGL+Xʪ*h.j*_aР&D NS@0+a)i6YxjoaDszcr+8_k+)+N JPuB@Ƽ4aDcl| HyX+h,Id(ڠ:`.Da m8G$ l bĄGnd^WWX Ӣنf @WFj2my֬AmAaV*SBd֒e)_1O`+,F-igZh6diDep|h@-~.߱f&nQJBfbRFDd~NPT^iOD,:-)-^WR-RzR;JT HxDP)k"E(6ndN.f;}-ҡtrn.Yn|.Nn:>*1e/-in#2*ooⶄDNn)f^/vk~҆9n1R'w=ra:Iq:1:Δ}Hl%sp&h#r2%Z}vR/DHm]o10ZЮd/36a4J$"\Z,hjFh)PlL\rChq#~0R7!b$" 9EȮ KHo3.Dm&K3>1sLMc2oIX*D EA"kDFJ2@CCt&WoQENd"fo:כ4FegV4IA&f Yc4O O'/jDB5:uR3DD*T BMc !$Y@xTIWcT2)d5F5a ՞&]3&FRa؊_/`0vHFB\EU[u҈G/OpXU-%2~ /*MH+/k7$^56_V3WޟnvSuFd(p@6+U7r䬄M%jM^Ӯ?- #(}xvM1kӚ(1MSU0-ӗ 5P kMk*-Y&פ݆Ƣ$96$q9kȷ+qz̸S/5cO{ 2t"x\f&X7˝6+?K |X@#}Zం&d 0;$4 j8].Q% zDXs Ud1![i$&CRt&.y.$% ZrE=,5"~|$nϛ[N2KLR'wں:A:64h~0 J,CMZUξԬOְnUR{Ml؈G#a2P5=Jdg}KFZ:$HuOl'N95Ћ@l\AMiŔqu DzɎ3pMjPB8͋p9%L:$HP5C4^5* r(*5i׊u^ XpsmXRۄ  k~6ZXکZ\iLd ;:t#r&u~z[WY#R;].$e:GגTn=kc!dRHUt2 yחo Ċi,֜^/TѠ8F؋k^iUꌈfi^^ɖA!"e L6wz?qZzNqllϏo_%\%\# !|!P 29inYW;ԾTT ]VFT dVsyTP- @z#pY4#/g/ <@kB(p$o8;V8{mgNR$Uհ2!Jip-#RɑʀGTnHA Ξ7|ň^BԸGx {PH6DOM ٤} F>(%ZljS7E!z̓t8cFpi(8C#s* Z#Z߀xɰ% 0;s$$d҇ (! &D&hAֹ1Rg#Z(i_ѐ5=B@/)O) |$:H+DtoL-S̄mp#-̘|јacF ,mT-s$T/2eCތ ǚurB/Әvt7INnçl=#4Fŧ&?؍^N ®zԉ&2ram튫d2Slsgar"{ AH$O;fCϕXmCo:#^P;bM|9DݿaPCw 7M}|[Q&NXƩ;!pJεu/R92YLY㒔7{XV<_m[B/L;גҀS.y fY#E;BʽXQ!q.`4`$);v2A[KDx<Hx+p7n93om]F`ƴ)H?y'ySF!}L|j31ZQ`2笧+dhkC|0! *^Nۦ@ /jvb,V o"F * +8$(ύz#E bf!X繬Izpd#%* 1`-)*p.JNTx(dB_ p,Kʤ&+8"bf/R# iʹP$ܨ,)tg2Td {c4/40 Ê"#۸elb$+t0$KpCJh q!}O*o:OtE3;dL @C!(mbhLa #ol9ϑzQ)PMK o,:pga("> + w(}c`w/l/hQ\$%h1~6#{4q!O!$ B:f( #YD##!-BdNP9D vm$Tj`3rRV2ZRIvK&͆7nrb"p%|Rʐo(_R)Q21*/;1+sI4Bd@fd˺$JNOjK .Yޱ.+;*>R3p!s31)/( o())-N(3"+b(4bJZrF$5%J ܲf[3!tso7 8"[8[0o3n1A{c2A(,7c<5&Z Ϟe$wG(>6o!{\,7(@OL1^؇'+AMl9ūA)ADb:BB4!F08"m(B4;n¨ B,dN1W:CF1M6iTj"n qSGeHGSt@)?!CiNL 5B+:Qq;GeԢ, HcRk1"FB9g0 t9.ȝ+NI1N/56Nm2G;7qP}@kCSU"NRY-b=cJS%p 32Y?5C;Tg2UC$3=Tj=O#W1 WX=U\##&?k2)tqP+x2G93RQbns[bBKX"K!;KU]b]HS^4 NUS5#Ro6a*`c`/m *\!ZKZmn3c/;g6K=#:&1LCeM#2,M,͒DWiyvUQ}T*3UnRHa#"VboNjS4@Y[Tq[6d`NeSrK"Tp-V%$g/VkVdhS(wp'2sWqG%j9ujqy[pk2Vɵ\CqTOIQk/buuRjUvoq)0ispob*wQi7wÆG( 1y'6SSzz[4C{骒յ9W "|ϲVmU6x8h О}b8?3 R/qnPm8s=~oSd\4]I7yU;|gLɱ?O1Q B0O'"Uԅ)pwӬi Bt%8r%t%3x7Ċabr{vUWE=k>_scZZR' vwl0JP.4| PוrQ 9n84|#.DhO,;QfvƗr-RkJ"Y$Ix ԋw1bh"cۧwwTkWAM-ytl&_ e49F=eP^d3XW?7!#9KYu5us)I.!W5"fEȪԢ'nIF+b{a9Y#&uBYD Zn ^"Q$agIY}3B;#qw2Inŧ͹IM1XZ.9B,0NjsNFEYc7i$`;OeȈH0:{4`x=L9w(yW75ccU :xe]Z#UMIF ?!Vx{he~V> b]yeTYzzSئE7U}YdUd96?W[ǸBIZ$ۙ`eXq;oxIGڕ!cٴEׄ>m,s=={:f=נuzYCi!4YۇqY?I <#ܬC;ZѺ37PBҭ쁼!K{m]fk[f f3L˃'_\!bo{Q[$5oTҤs)k.!|杽{e-9/<ܵ{W1"זmYmA-'exԾW<8vv| x+aRpOԍE[szįĄ"Ŧ' }y"*.K);f5!%8}ce|[1Dd=۲ց[[X e Ӊ\  yGD)m4 ڿTi6x7 wwdܯA]9m=M9C[o=׺^@@ËOIYu@ف# dG†'\Iͽ|)}}i7G!D _0cׯ/|r C}wy:!BaNtYҧ!XG T+W;g'oy;>"X{|2>R׳BIe}> 0GRB\5OKh rR3@&?)HۿYa{J=>JbO~cX2^BN"63]}/ X@p*\Ȱ!_֬= ჆3j±4Y$X,XSIɗ0cʜIse^$OҨK=qΆ2T&͚4eJ] T Y|>mȯ;nJ6،k3Mfڳr+{W0N#LfO~޺ ҂% 3h]ɹ!}#B`xE l,p'y78IkjmVGD:&sXdhϷ<3 z\~C5[ET4Yvqh>א>haxA2M dRs΅#)a r0*t8ViFLf ܵX WcSj[!{7qdk]¤}V'ddِL*[A `=%hA*@#Xoˢ$Svc_b/ X]VjԕK2W}9HofzeBFQ}6&ebBh$`zUHY*NϢG1j{o^*x^%4V{iC, R:cr$EFېɕ*pQ[l[jі vpq3SNk¥ЛVi/S9hӾDsVak/jCq/zYƒKa&=Ӻ/ "(t>iY), 'Q+MPM4`;%F]1vC9qoƟHât JBEt>u H@>3,P?[\al3 7 5,0 ,bBW2.G-vL{.P/tv8WBT5fb6}/@6Ik>M]}E^F2Y [1Eo/ YVo)>sZˎZyHm9.E}*QPEQ,VYp$pWw2ָ0]1ovH4SێWJbtl=pci rBA |[`?c{3Em>ATr62$ɋYrC' L_&!O|_s᧚*=Fpx$mχ)d(L !cBHm*[{"SHT@,Zr|CeTrUKnl#7Gq7vLZK]ŔPadAIR$[b10aU=nM0w#晎ѰM YfD!RwDe;arvh%pbS<$ G? ɐFPrQ-9}Y 2EraH`ҏ=d.9sM*Kf4 ϓˆǍS`g"P=%' JfPn'Vm͊rgл(F^>DtO'U+FNP2hҜdʟ9'`YĞZQ}Ĉ$\,6@]n4>Hʾl¬L:+粣 ($]N/=u^@OwMFYSN7_=RX7,34Kg".w=LE dRpn1_D&O,@GG\ŏb79/Pvo?qÿ<0mֱWk'[og,e]{Wx#{3,'"(xR   TA:,#.}Т~D7~Jy+yt!'jSGqTtU#\'jY]satXbVіgqs a~TxHZ{Y m~7IyNI{ \b'X >*ٖi' X2Ӱ':ңI@ y)_*`%[9LȐM1Qɘa_DqVDb lozG  tZ(pjI bJ/IzZzʧwęYIbjE [K<8B>#U7aVJCԊLF2kH;#dik)Ia0/Mj#z5_{z/17*jpNnUt ʯSTZR! k KIU;>ѝRL{YtR)dTz%uj ʨ!ukKy'^`Ҋ r:EUyA;HV,#9J&zt 0]-)H ۵ ;B+LrV]kj,D)` |ʷz;ÛFnj/_ 't;9Lʻ4ѓ?Fw躁J a¢eFkIuQ*p׼xMJ1g#+hC|jD'ۨQ eja91ۃ[-³G\3q5A( U?O {icĹ&9aYEj©¬p G 2^dL! SwHy3rtvLz:e7faȬ]%:eEm<L·*꾓:ђl_[?q#!, '"aȒբ3Ź.dn 7,T˃m$@HBV.847_˫<]ŐL;|-LZwg `,ZI|/+ h2}&jٹAg/ͷ vÐaQƢy!OG3-+74 a]oҢ ),MzG\46 1ң,yҹ5Sս+5#,9;]b1lm+r ~t0!x=̹ N7yk'KH ]M%=&"V]? X|ZٞMt,ymI)K#!Ll,-}+[o> ٿ=ݷ1!ݧij,I8Խ̀ͫTe"ފ}ʸ#H\oNIhm]͌!;PgW fnMg -)hk1 MA#NBA}M>݀f[~֍^ HVc?OfD^ր 8*̳ i;>O,ʌ5Q@"sdVS^=],B$8C|vb鏮B'qQ;uMtWN:5S;yN\W-,òVՎ͹GQ9K08">Ԭn#^N~;3ƿ7>cԜ>>! % ='NJkԲULeRŽow%璽n֏1~@]㾤%6z5ʖ`ۚ,k;VA~@\5%^-XWsi5/]to5zi/KNdY .>(L6?/Bm@(PKm>j'.Bv *,*Hb9,#ԛ?c1F]n!ܼ"o<b0ȹN~A\$5~[[@&)EtK"R [ިP!#!R&1#-}DkE&F&Ԩ(@/#TbL>ң2[4#K6<4,ԒǾ L0Pu0Tj:\QF$DM]m-=S;?3E6وP"STٞ*s9#}R,/YU,v WejK$[3Y%s]O|@587O,ҝ|] gvp;VZ &%awhGuKzmD[u7SuYL٫UB{k77lpҜ{eyhXJXƕ]kcc4(vZc<>0e" iMF#XN-4ofո MX\[Ez:9R穚;s""H/"kc +:l죻EN?sэy>n6Muv|~l`?WKZi? 0<貲@H~'ӧ.lFE}gz7IMЯi[\!╯Ii\<c{' {à["Y(GSc* GAi"FXwE&}aؘVF'rDdQ.D ׳|Z M:V+(GBҘ)E,&k`Æٔ lt÷_j ?] ɴaE$ܱð! .QRۉ'Y)!Bϟii%6_I0e鰇-eycP~ sgL#̉v*>`Y'm5?f;@VTHF*./H:YwL%RbԬ$FCBk3FOW0D&h7ZJSTj\?NTuUI;k.#rϳ4q%tVcُ- SHY8u6ɢEb]VvJ$u_Je\HQ=E g;J)oSQ_JjwJ\='o{=4DKoˏ~4F+y';]cV"[e pײT573*!p|Po\:DmS܉4O5rIS8;=˂.c2Qv56iHkǛvq`uñWQ+ d쑓Gcs1]=tw>gV(HɁS3yaÒ<1#ZLL@0C(bTz?q^ N3Y4@ eT5^mNB`O_hp?8a7N-PIcoBZ"q^n YlOBBm06cð%$/.;Rlk[.^|-!qM0P0ng?o?[ֳ&(!۬|(Vn6GrZYtA)!q$>rq-N!T#&!o/ҽY}NQ.\GI)-)hB8O|xAv{YQBPX|tIrt((WSIvEe Ց˾Ró-*az~=J* k7 M|!ih"_C6 {PE M, _+;F2+kyx3Г泾惾iHD hA*8B#KAKL YW{B B0#B?7wP4529<ܣ T:ȊkP-=\@$:C -Ddb>C|+Pq%S3%XN&ܚW(ts{TdB*s_#([©E,6s۪̯|9c;F;k+g\9F>`ȋȄԓE>>h1X."zܾ0,vȁ@S &«\" Tb6B^ѐEͶ|G5ɩ8!FKeMTU]:"WPU2\sm Y ڜ#$STbI5a bc 𜦰iP%PE:e,U.TWj͈R0<˘Bp5 `N\t==Bp_5[62a[?eQF[$& :X=Nm+W.*Vegb5i]gagf\Rd8Tv%"6`fl|YbLyN\z[t]^n._$Pb3qL͕ c;]@yngU5j-[q^+^^]  YF.I Yʑ1f XaDgH ٝe]\._S_t,Hƥh6u扪'Z=R~fkBf::ZJv~:!,*-&6(g8砸h~ ^> z]Fk؉kŋ\XVi >Ğ9nl4>&v1fM mskd@!S^~GaH{K|01m}Av0>hro"Mjdp Mؾ\ZFmp'd6dENF :qyZsj" [?Àlf ﷢Rrl-Rrd%md9C)Gilk. V`7ϴ 635gto7p:Z%sr@Y*t,cm76KcG]jF &ְehnNP7ݎ'&aG.7wB.uP;f@3 wp[WkAGVneQ<_ Ӗi}J,XQ`itq1iskwvK.X>V{wf8R dpw#5nowvMxk"]p٨xxe>rveZ[ϒoo7[m—_wkن#6w GwlE5T렧rOrW|gdwNdljzJ/c_ r2x9"6gVsd7(}GSwzHxWwl cubkW{AUc:ώO|||o{6:zvd&MŨ} yǏRzs/vxz>ѯvzF/ <h „ DD{ 6H Ɗ7&\#ȁCuoDo[6 nVe%EdF)wWs=Gtu7`0I]h=Ud^y}8>Fȓ_-e_O8~!m y$S4ΦӤ|EcD$2i*QUeP>"vsU"&U[Ģk.7=Ĵ5ddNW}T8~_9_:FKBY DmEHhSVxyעW7y*xI d`'S!x!TJUGWJӂT)mV&y{:Zau |Ϣ'Q0+b NQgʚo [&ʤ]Ek-BVl4f)-'aS_X>Gvm" S"sxK)[e+A<彉_3P2AT)N", оǫ x V!uZ$$QքYGaq(!_E E&yQ=q{g_Cv@|bו0*nsG S"(@L@| (H]2cz YBGFջ5)UGFIS$I;@~+Ȝ'DžŠd"@ I=d YO)%< ލYc`Ԡ'9(fә/y :6Zɚ|ߜ9J02gY)R̓cJɖ8$m[[W9)e%fyyHNʧX6E fΈ4U)nQV1I,KjzBsRRP]4QHGTS)(He[/- d#H|ᵰ@\ k$M"^eձ~܎g@GNr3{ nQ_xgN#Ω:hpJ7 P% *C_ya3y$U>!OOr>\o1]ߥ PH* TӾ8Oo; i-% YHFH<,-H&xB\`n`\߼ePlߑtAѶΞ}ɞ긟A\TRQRµRlš !-_J!]U`xA  JQ5̻Hl5a}]_YEuɟjUQͨ|&݅M!.!]H.TarhF9=\lѨ=U5"E77=ƯB^uB@P Ěm`$q%D _9jPH$D(j`Ym}a*‼=_Trjc1RcC \!D1"cB\Ra4v FDB91\RbYb`A୤њ%.!))=cIٴ^-^E.\%BRdC&T&;b!N"XUp}UM-VDE".A.D!81$rGT5@x!x5[X$|eUX$`Y:a%H-@x k^XR+rbU`aFR޽ ™c6dfWP=SsEWH@0vfqD7RXJ"Y&BH ,@_c glbhĺgn(5AdyBpVq`!0 USǐIS^"|n]HP(\qghhDxnZ'etű` } pJLPƅTNC&Qfe6g =Yn Fv] aQADdj}ҁzV%()ݍfBDimLiOj$R"mL fBo"bg`gم_HX(Yƃlil\BNHޅi**Adans+l& '1QfDDa+ܑ D yvkI~VDΫN$h+ &陶VhM[ҍJg2liQwz͡Fݦe2l- kHim.@0njr©6ď 8цahdiV -f, 2*%afmF<+rk.:Ǣi쑭.blmқUš'ݚjK9]WgkhH :H5.}f (,>an^(ĂnDÖ.^m$,|6nhڠELb-:..HHPO]تr.QDlLJTcJ*^YnĆo/,/c,i~[ [ ~PzlkmN0&cU6,-a]b\VQհp-ZdCHcE7Zp ]@W." 1U1&r)3}2∲qwqq5r[^t ƬV cDo(GhڬlqO,~1$Sdک`jq8c_zr2qgTl+1C0MۆoD,',glnx {120'p증5ϢQF8®rS0+ɱ&5ϳ6Wۉ7+smSb92s;C$sj)cH=3=;'Et@=cH,4IC(i9STs/ottIWHl(s't3tstPIS7+4Vf q Gk YE*"u;c)WS?E5K/563VV#)+뾚*+z/Dn\]Og.XUQQ-Yۆ^_S58aK3rQW_p6SXp76M"ǔ8i\ #sv 2gdžvmwbvtX5Ӧlk2+ t!mϰA Ӳ-bXqq#wN(i'sԩ0[hc7Bsa7XOu >)YL+'ZUD[Gp.7Է}~1 VޞqUC5 7>U]vlti.W,xNWnMLtHZ|8mw#ɉ!Ms,Vl@L88 ?߸kD9jx=@N׉xmP/9CwmjHM%6Upy, xӸ?x@ b3/Evȹ఑[8S o87ϴ0 z.~7`^I:)bP:sYn"gd@ 놶)aZK rO58`"nF>1zJ𯟹fx/zK8f9;,sx&îC3-nw;:\/:{4cwD_ێ{/AX`u# c_SE{{RG]|G9}#|Sw M#e_7kiA}<;pkɏ<q[QҺ~ʅ{^_{>(5oCaR,{&U۔˹0ח5IL:k-C@I> @hxQaC!FA1flHch!I1D0v/wE7ofT}Ϟx$ip'Μ+k.4ԆKq'vY ehMlYA͂m[oߒK.ĭY&M5e v1*ڏs^T&5h eSl\3J~m. KGbUy:iԵno# v3C fKFFysr;9޾iKX!ݾ3m3<<'7\"CǮO5h;MZkP~k dKL,3z ಚ/#;+CĬ3F/L N̚p<,lChx\1$//4  @I 2)dXx(H08:d7Ύ2ѺdŃD glM%; !x|u !)7B\i5G4wPQe/P̅:*SF\ӹ6C9uh+esus@Y5V8`Ht *!fsK#۹RKo0 ܙQd@pE)UXդ6s#YM+ mm.^ vׂ] 953Ķ$8 ṵ,-\RrxSJD,\,MkKtSq%~qĀ;i&Neaw٠};Uq &L>?"w9ffԲ:{P^gK {c}8SBzq1Ѷ>uئ\a6Q*K󎹬36I\_Nn+4͟4RGGDz@)uˢ͚',7 tw_ Mt/WFe{1LU#.F$a/# ^V>l`QJԥaO! AW(jD 1k m`&P\#dbYNTqiU2H²Đz`_xX␎aYc.'#rʫ2A-ƂIE<%s.$A*4# (c!XGU䎹^5lOC< 1qV)㑐̤X>c|1iI+g+4SBgRgC*ɓV‰J+;4K."#t`T٢;(yql cUWO{$-ۤ)pNT#tS_w~ҏe k%""um%"6J.Sp;rЋDCn5jD, "ceOs!L{NMHgMt[;Z*B|1+ܴ.:m7L%jEHPS*7jpQ}TD(rSH5TeHATLŐse=#ttQ@dɹ£cRl^k] =ia(WUmb e$nNy)^nXˊ$ifFb:VIT4x)T;bvxauW!cTUkۨ1=)?.M.K-i(N˨N͸/ !ɂ'} |U4.g䲶qG߽0[Kރtkk;C,a8d3GNr`WRjpB3[?&uCa|HԢH{S8fLW]qD%ְ__;mX`"PF6orlH%W+y˨i]+)NlTԨsp8B΍Dc /qQtGj{+]R5yO< `OTI8n 0b0 |rOVnbt-h*0!\%>EB}De%!%A J A/9kB9@`A@/#l,'r0mJWFpL #>cYm"pc}Pl a >ax9)> $a T PՂ#rL ,0W֐gG`M0搣:'%+lﶤ}|ĢL0P 5a c"7ڀ` a,"V _`1ΐNrQdG$ /@w+;G11 !Q!QL|opQm&q2'ur'y9^'`"R! Xr1pm^ H נj'2,r,ɲ,O1($#%1CrC&ݑͲ..2/rD-r%U-?.hq/s111B!1<&/1˃0"@QI!.!0߄!\`4A\T9L6.Cx3!;!rS6*BL34sH*8.6J#Js6ks"5b =d+0G-r@6AS,:`ZM 9+"J38>">lA>37o8|S#b9B3CT:H=YT:5ESB͂5s@B!Wd@5+5ѣ;BB/L:~<C3FG9*BG_FcE[tKCFcFi,T@wTWaCDsLHS7M9NEN84tJ E`;!THUJtQBF!CG 4$"9!?.LsRM%7d8]SGTU2S)>4K!,5J9Q}-Je5CDP4A=%`{<8R{VD9tZ'UB[GtX!J@U [yb:95QW5\aK5+\#6S#4!DM%8K_\L^"[O6)AXb">>'c/^4WNv(C _ˣ@I2eOC:q0:!rYf"Wrg1]c4g4p95S9?]M^qb#;vZA VVhNV^wK?LPb"l/b:OuaՖ mC=.!,J22vvv  mmm  nnn888```bbb777___eee󠠠ddd @*\ȰÇ#JHŋ3jȱǏ CIɓ&@ɲ˗0cʜI͛8sdrΟ@ JѣHbSӧPJJՏL^ʵׯ`ÊuUسhӪ]˶uKݻx-W߿ ܐo_ˆ+^̘Í#KLrǐ-k̹ff=M4]ЦS^ͺְc˞5۸s̻ \%ߡ+_ΜУK|سkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄U&ZU O @V:jAa)駡ZӨK&Z:R@v*E. DF t0ivk" xknC !{ 8*+ 9+0A 0' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWq*`0L  Ihƛ0N8p0HQ{S KecT)@*Q `Ze*A`:5[P@WjUcQ=@ (^:5TXZʵjԮ` Kزh{2[ }Kںxa˷߿P@>XKvɘV3͜=cZtcҥMF bkc7}o @lȑ[,-y L'nHΗ$N>0ط !,T22    곴H *\aB:HÇh6r8!GDhRJWpeʘ2Ytiœk(BC}4z'OD2E3BԎ+R*Z]@GImY` 8~-yn H/ ȫ " H 1C TH !,X%22  ^ B": :(<: QS 곴 e^} + , ! - HA\Ȱ! Jl1ċ+bE=&)QH MDiPJ]fG*)3 ('P(]4*@J2)G غՓYLt(D\Jش\; \| 2= 5z&F]*"40YOKp Bgp $6A !,b22 w H w  )UH0few0w UwC)fe UfwH`*Tx‡ h5b`ɐ 80#J |2g `# fb0@ϊ&&U V<b&OD=*@*)0u UT*txfi2(MZ;Py&L*p)n؋/!8V!>NJ 9d {?h˗=p}Ͽ]aAg&X\}zA F(Δ}Sv~Awa}(P (4ƞ c馝v" CA%lX+,h˺ 90*\@ p-5Ϧ{ iF>ԫߒ*nvK+ѼZ:-ǎ .l0D!DL I [p s0B[Y,e:G쐸3)l.!L6;dt}BW-P4Hn= |jROl'Mk vհ|ok-~3D]'V`_lGnwsw.՛k3Zym^봿9;׮;+;ϧoS;s7/};YgG7ᗯ>zo_~uo\U:POH~5D3Ao <sp-Op))\[g wrLJ< bRB ! u&QB(GTGC&jH"2„A8#lcAԘF1܈>J'ңhG rlFVD# EhH%#L 'Ir;%QIUr+M)Xnp-?)r%-{ LBRB,9N*̼1 h6$%14l7gMins,ĉӜl߹s~$=I}*Te3U@K&hyjiȂhӎe-$) 6э6 oU|vLgI *$(Fr(*1T$&=e2{!/H ҕt3 [L;Ul1ij(U"? 0Ta=I>'"Ju5@J׹n[G}vCiHP:T-Sʵt%\ع1 V9U rR+\eJ ud,U5kSzV ?O5EԸ}?{4)Hr[Uج|!WA۬E6TS*Kڑ6s-GT ,ZX]یjO>VL]fצ5 'ku.}bw}w)9fw<.` @2a). :`xWi f< lxȉa+ ז-1+T@xT#>,%USKlU<0̲ J/@= +'Ik)%`/82hA^78Z*S`DS(q |f2GzE4 v5fJyxH-8f̟.cjԛM4 l;HKk[/~[}id4obg@5=>99܎tlv{Ns|H ՟ 7wKoz= 7J[)+[}[GUnDj[Kb2Z95:o {"%CG1Qna˛pp>ǸdF67:UH|;r#.T-}CE?ȓ.0鷴]Ny\n{A=]m]O{=vc}-&nܠ{$N-yg cgh"LW'_86_O+=-ծw$v' "}LlG <>^B*Ə 1v7'T]cMk?9bWsn@MUWgVχ"æ~ Gc"i 耋<g ؀h5a# aLew%'h>2XUz/#1ȁFVThc5s.(jbX$|L"ﷁYm5XEKX[}E%>ׅ^%6xYUTx"Q"[Xvbra8&sxbr&wy(&z!1woB{xA8*Rx"v ȉ''*UsFQ|j'Gwh!'[<'h$F'8 wr68!׈~%Ha(y޸}dȍxظ(hrShr2/э8asSH2Z"-*+ `,c9'-y02",%0*+`ÆX86y%>^e0*Z+5=vHԑJ U3RI. 5*%5UX=Y[e + Z3@0he)d5\1!$|'jI5w[7H1!IyH'E :,'~|_Kl8;Ăjn}eLMw\cZt87pKurC0lKr7Ȭ*_P[PK7`=Ɏ*cL}'ƨqqr0(<˓4K@3˔\PIͅ0BH,]%~ܘ4R$fĈ>}Gfƃ$LHÎmԃJl%&!q$omnx=eT%%`._`FVT_Y6MTnfDnZ*F՝E/.vT$-H\v-h^&v'TD9]H)oB /݃9UXH OC1/:Oх4'^xH"B$3O _k/B+Og@6oB^ٺo=Bn{gf'^~*Jj?-nU@sOoA_AW?]7^Kc?efs۾)T?$CWmد]O$DŽم>HPpQD-^ĘQF=~R$H G< `SL5J0``:}TPEFi3%9>USV]~5MLVZZr\uf,8fo豩Wbƍ?68fʕ-_BƜ`aYhҥk*,Sӭ4th׵m=̾gsڶs G\y`40wtvl$uݽ-rAr3y_\2KK=h82A ޤ{= 7жKoAED1E"T b EoQ,E+D D2ɮv)D%m# !K4R'ĒAί,M!1K3<ğ\M`R6t325=N"3#wN#8XI7@`z4IBҷLk-!t*Jm#dX 4 p`ZoUO%UM3`B`}jW\g%Xը$$`l=\]S%xܴH$Pr5H[nՍkȤdB&`B`]mHUtχ"Q9K h>X|ZJzԂ p/Y$t*OkJ R˛byՙb(e1Zt6\|ZڧX8 j j:km^탡".*%ȳ;({h89b]WV};rۅڔ&XyuW9p:ьX)Ve[-$(>7ڏ"=z|Ӷ?jN񍄡S$C68=Db]~6u8E,L>ETWHuٰ~ hJТ201/_Zg:E!u^[H6iqbp"{D-CDVrYJoEAB+}d(7ɟKZ\Avv bח%`Z ;Ѷ$K5 4RΦ6&9$wm߹Pi\" fMw #6synsH\G0rzR jIJu\QE3\yFӭPSK^7l[- J ʱOuzV?enTZ'$|a\+K7x$%Mual]X4Zh鰘\@5$3rn.Oy͡ls`9UͱM3q|& KLgx14~ܩC& /Sٰ4,nͭkHߥ4fuRZu+)lU#pLoƒF6Ԗ]m]_  ٥6uE9+-Q=]x{-f̱;g+mNr |CbGO 7O8h$N]M[<9Sr7j|$džP:qs_Lԝ\L[ˉTє$M1M`pI5jM\MҘ́xؼWy?Z;MCTDͭ(hĿkTּNT>`i'L O(N^C ($ƬOTϔɈ!SP:[ϭI`Єyn,e ]!|N}! ŀP@Y|tQi@1Q݄ч$ 5E(u(RR)&U+R. UM2Ӛ ;S\RL5*7$:eM: 6S9v?L35@%ɓDRD&Cu͔T7]I=HUNLKHMΫP4P% SRCTUciWX EWӴUM\Q͒^acYE־Q֑`fhu”z֦,k]SoVWWp=er5PWu}mUR`W ּzUv{WWEW~%|%}}OE؄%ՅRuX؃؉UtFX؎ӁY]$ٓ ̕UHeYYhkX^XsY :Yٞ 4U4ڈ٣}ؤeZ&֔\ZrڪcVǛe؝ڑ[۱%[%ZZT][ҳu۸dںڻײ[4ۿ\%\ *u\١\%qޜܻ\j\UO]ψpO͛c݉p] 1]ؕ]ͻЁ8u ^xQ[Q^OX]EP'Ӝ(߁^C^ @< %_8_SƸZ]߇_0Q]P-<^9^Qn] K}"Q`ͻ<``favI7auI`Ss޴!+%F#nb B(b)ee*>Tb-Nb/bb1f2[46c+m5.Vc8f79/FX,:NbwM۸s(;dգ7@xȓ+_μsË8crGOw?.T)P˟O.6^lqtZZP$`߂ 6E{' Aםzr$hZh}".!4h8"/@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覛[z (BƐCkY.qdY4,O^T&0#/]vmNSy,0S=VdE =N[o*L"Eo#HtGAlPEg/]"/yG;:@O}( .R=R>> .a"ӝu;R3/Fp9>PAL0#6/{l'BQqRMwE,7Y2Qpf,h42ǍlT߸8rlϥ},YF*[5^٭HȒ$OLNˑ'Imr*TbleR"`^"VʲIN#ͻ 2 `L,_&a衘զ5]WYnvS7 ,R0;A&iNhӛr'# )6i.3HZ'GS3͌ ET@Qx3>CΎ>4HTc?h ED N7aA#"> - Q v1KZԊ&L-fΙFZ-aXZNV˘V5}ZoA1NwJ+Nƈ[l$cݜ8{E ]ؑz]鶹j%ڬ+7ssIN3Ľo3{܎M5l%K)7#%*;VZC wsI$HO:>R͊{K`Kq[-Ȼd|cO>oRSt~t%eCSuMUwO]ߜL"7v5/8\r4AGz/ı'oM h7mw N*Ek_R}M й/brW%ڵ'פYoSڻ{7]<%{Zv/!ho7ss|ߗ4t&D>=IO}G Χs}ŏ~˿]{h~^y[qYb2-5UW$W~,a5BCUa!St3+u y,(3!O .P 2P4+[wT@h!QgyXX5Pa(U+['W|Xx4e4JAfhLZ~Ќ0(eX3/ 1Y+ YwxOY6JY}娅H8@[5y)89sFw 5i%4`WF:p 0$Y֑#508k)Y鲑:y.( #5Dy/'}H’ E 5הT.7m:ÓQٕ^2S9ꢋL)h1julٖEuAry/o `w.8]{i}.?89@)8Iy/5PY_5"'If5K ai6ey[Q3jƐ. 9:fٛy1yi/h8"i/niٜG9G g悝)I.ݑyx Q؅Y-8!1xSx/sv($z8o HA/`Ɉ4-~s8S>AeH)~&R!ʎaS)J]I @ 0q)!9xu#cy0ם1m'A鸠Kڤس/ q B rGaN#I 6`ڥyw}0D9zÇ}~ӷ1RFJgyDg:ķ9꧁w"i3}z!HsBT-Jz-/r-Yj-Z-=J-/d*6JJzTRt-1҆U[`#>JIP'P9\2QxIY4PaZ`8`Ge2pGW6[] LQ\vM _2)!DqD_e+4m-Pdkf+P'\$mFAdXd%-//Kj5E G+ku аVY {E7zvJC:\ǘ:'Wx8:<6~X8<ƫO Abkiysˊl.A,9V{y)"Q496Y~:95W哲dSk95g˶6!?PYc{GF GE³ 9N ø *VT 9Kf[%uK8+xAR(/9G8[ҘKF ǧ8X)0|(Lڻ5k zkAz񈌃VjY6i{+Z *'(Dƚf[8囿+K  7p 4h黂:pl;_QUMs'{ys;|S-4kegSVq!m6SDZƑ5lAŏ| I4WǛ7),$k{¸? ęܼX˼-ky|`'9lz`)qk*R[,\u<.d|l٦BwL\cG\[.LlČFK. 0wƞW-98μ\-Vݜo8ve<{@T{-h+ {ӕ-r;˷K~wғ7Kĭ*-*A g_ռm*1U@x,?Iߗ1k&"ApUgݗC))1pI@NC9㥢M)YܖMHUrwHNH`_Pޝ/_ lGG"W)32܈LlMs5)UWed9s"5^-)&cQ{̣!1\|qWԔ׌h>( U15l.ӠhUG|2 e[3l,5l^jsόr糱!6!nMN @[t(c^^3SĆ~9pߐz.\!kS8l7@(gqo]7av M񛙒2̅Gc>)g(ȷZ~Xvu0^+'F铩 hȸߛ>L{'z ]ZF&1O/iej'H(aXolTg~h>gkMMo[m['1Aju/*bt#QoP7c3`6PE_O&|/xA8_%1W2O})ֲ郯Ro?o<~j%.z<%6aYTBw??ߩ`!@ DPB<D-^ĘQF=~RH%MDR%LjW"T@NxS 6( P@A-%DTRM>U*HGs.@0sM1~MOVZmݾ-RfּWoƭ~Hܽ FXbub+bh6cʝ=ZǪJstھ >qlڵmn[:lV[Բ_Cp2r͝?yx5P%@.;x{A';Vǟ_yk?z;dAH70!(6 /CG$QªB$P D0B,1[GjǨND V P@/0ZBʣТ2Gr>:H 4*&\P9rT*ek3K9qs=8mոF31Mdcȟ/scWrQHܘ>?ҐhFD6ґ$ 1$`+\ d(/9:~D!𔩄Y9H2##MIK\2ė.}9LQ Sy$f2+aSt3&MhVӐԬ%/,bsgf8sL9S#9dNtsd<9ñg>ϑRT#?ѤMՏ= PW"SehD}QlhZFfԣܲ6Q.tiIUϔ"+)ZԦQ;ijzS,"iO:CEIwZ¥&թl*Tm̋jUZBǢjX}U|Ug'YocVplu\:״Ujk^Mf|z,T񪘉4u_E"ֱ U,zkVvN~mbOQq_h<ֲh(4SEʓdh~ `A@`:)VtH iQkՖ,H/msAEn1#R\alDw;mIUF1nːBw+-~@׃ @Hu*1pk(`߆TqI|w$>05 W80pk"MHc0դq ]=*lQ̐Ha`CrK)ɤsrGfe_f̔]fkLdiL%v2U<$~3lM@ĆF4Q}g'l%=iJWҗt5iNwӟuE=jRԧFuUjVկue=kZַuuk^׿v=lbFvlf7φv=mjWvmnww=nrFwսnvw-Vz7=ooi8!B p +wpqhˢ}kk$7o`p| >k{r<*?H'.ou*8З\tfww{w|ֹ܈ȃæ5~͈*Ox]~˼¬B2{^fd~%z˛vV}XyׇẕOZ_^I] G~|7χ~?}W~}w?~G&  ne !o[KWt52-B:J#jy Ts@ԭ7!9 D+4̿ 9;#8r <r8J: 9 ‰:#8+7$t -./01$243D4T5d6t789:;<=>?@A$B4CDDTEdFtGHćrՓI$=;L%+=OSDDR\"CE{3V3݋EZD%x&C.^L%<=NEa25kbtJEd,`Z w̝G@سk޴zHXs򣹫_Ͼ'}wPz4([TP~ٷ "<4`E!ofvUsRDU{9`Պµay(4hF'P*8@7)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫fO )ؐO֋% Io  {}/j7<0,"Io\rq&LEj'D18 .ks9M /Ũ+%LG-TWmXg\w`-dmhlvv ~Ջ`=7noTIY6_d7~{bzuYhx#/$8;x|k49wC+ȹ⟯9`U蝛~:7(]G Bg1P_9ózxǻgxU[=P/}+:>F\H9jN@? iG?Otߨw B@U~I$@yn@5)V$Gqntq;8$B,@b?^ RP`BQqF BN cA7PEDJBP4h4.l01od&OVr;ej[=EB. $2Mv A+zk F5ӤJ03q)dzMjթ,Rs )qz/URT!tRuE M"48*|" -D=萀 J<3Z[) IgўVעq3u"a5S(h,Ca*u"G @iIy* Z6eM Y([4@}ӂ6 0oA[Rֵ:Ke'2Xveeb2\: MeWi(k ;Vϳ2p䫫mw^33d3 7/Q7fs@j] B[]&H2t=Mr4 /(@\ nUŚxC!1ƪqQQ;G2SBV\$|Z_!8JZ|ɢ1EL.'Y>I|L0{*$uSdȞ}uS*2]= MR#Ȝh_.t84:8I9 ,iHISɢ3j3ϝTn-?sǽ 4S 6~u;fXҺQp?kd#F'#vO3.P2-H n[dmv|تC5X*n@Y6=ɺzGmssD^7(};HΈMkH¿{p_bA#v3>'ZG))&Y.zX02)׌3xRYvcXHײqXy=q7_CIt1{Qqу!Ġur3xr㡐ס9`:+jrOp"JkXC&ـq^aC^DyA4᣶qVH9~T؂Qa!|Sm/8j9D 8b{ #t1y׃#o RDX/RVho'>Ch6f:ق\:.,:RB-z-RxʔJzBʫrMղ]CJ-A4BUT$@h S9:%r8 VwؚnfS81Q騭Bu2`^:aTRPN8+OϘj\ Tn7rqGfȻ B^UKΫ-ZȖH͢eƈ l  lj<-J`k.DZ>9wz-Ȫ8z7CzlZ[pMza'q:)Uj/|Χzɿl+l17~\ȴÂ,?|<74"<06GQϑ k7 p-3nI+KI#_AL@s0MR LѦ'l8cSyΠ˻±|c=7E(3.б<~ ),e#b)*ߩin݁+,MaߌR5J]*ү"ߐsek͝r4^. A-lȨôK΍1ۉu2s/Ojy+^Oy)͵maIVH_%!3(iS0"H.}~{Ne )Ihw{޺2^YMln'^-gnўY.㾮`ެLHqb>}>&nL&ޔ$gN f"ap^#Ow 2܉& <m%=0:#/o%)Y-x/1<07ߵN_==`I@AwG$Q?L,~UlXsNe;$33VaC?^o/QQ^.le@ߦ[u7~_h%g~m:Vʐ_mq9t1VRr)Oz ?Z~*%O¯_7G#ٱ)qu9Oj)=l/G(DrvOolojPߍ/@@DPB F0@  -^ĘQF=~RH%MDRJ-]8 ^^,Nr0BM)E#PpAHjUV]~֥3X ծ:4bѶuVS88b *p0>Y Ț@J7sZU:w]xp¿Wkt`&,]i޽}1S4hl0xa xgn.}` ֫N]͟Ge̙*lmc|+/Yn k1@ 0*dA Ģ** -,, P#D?TTD_2P - 1t09J@F.F£mME:2J) l>24HnʎM$T[51߄3NPkK˷ԨM.(3asQJQRKA&ޫKϟIP/ҫ KԁFJUYguj,⍳PuzLj VcE6ُ,+"lWr]W^!b[oάg%IZ"`.7^y+ W23Vyov`N['<-|%y ނ]4?%ij׉7?}H8bfOboT{CoF:rgw9,ۣ[ffLjczf_=mْ[E3[޴UmoΙ\>זoke8yf.?2AO^bWgF 8ooǽ84Q ߇'^yY; >{Zce1^'pm|UXՇ?~o҆+A@p_(|@ V3E =Q͂d;i|`UB{Is=І[Ї?H6GDI^a8Ő):̝ HE.v"BE/ь Y"q*׺'o 5(;-w4#i(7.tx02q]"H*1~ HJJΊXINZra|t!]6Nh9Rҕ7]츶DҖHlY`4ΰ &]3A0C5s;PLjpL-7YMnPs4-%Mr zrSL巎dӞԣI+M HZͳE(]IdILhDFbShFBjhH>P|EvAARo\cP>;ԧs@WY?E*nO!IY}pegT^q"Sӭ{S-)Qs8 ]lfvGҴ8 W5܂tVYLD"5zѯ9@ rJbP^6ƂF'e[c؂:U]#egCqulJYSs ¾BEmqE@aj[TPY]aq1].`6J ugȌv=q6[\+f oZ^,/IfqUn;7 _uɊ[Ky2*/}'>x-;XJ!PCFI&$hWؿGo< sdZ@+_ȦL"wYְaD"%"*B|@ZrMay5\sBlfלp.%Nxwpѝ6!q988=~pW#c|x}s51p97\9qN7Ozԥ>uWWzֵuw_{>vgG{վve/OQ"3f pP_!ف2ol+@Nx`OC& )ў|`{_Hrh+; {a7~=n8~"?)iV!~}w?~Gտ~?:e-28+K@9+9C),:Q,s9{9 Ɗ<@ LA@|*938 !$"4#D$T%d&t'()*+,-./01$243D4T5d6t789:;s;?CF;C逾>p@ÊB= x4K<F<##I;3<+"E54뻼;K3V,E.2=@xEE("P2_|X=JD+F.rF^DD,g4Ӌ^4VF/>Di sA D<vGxl@zL"{G|C8A~ \ tA$dGHw{t@}ĸGA!,(22wwvvwhueg ftvvHu0www0)fwfew***@@@w (<w v C)DCUHDWWv U;ZvC"# WUH um &^Vm CHWňUf}}$']d+?'',,T~%,-AVg'['(m | {!E]VC~2:~ɾ2;fS~$'(D[&UVD~ @E[}#@@4Ç#JHŋ3jȱǏ CIɓ(S\ɲ˗0cZlPB ЙN2 JѣH*]ʴӧsB\tͨ6" ׯ`ÊKٳּjuԬ>KݻxR-V8n%_+^̸lyR<,h=#?̹ϠCKM1^ͺװ-mڭep5ͻE^ XZmK μC'<سkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4hE%,P@ AcI0 0“htAWfXjd'99$<&P yq&z | )jTB։l.Zxy9Vj:ZR$dB*Šj E*@ڧɧުyJҡw*l>]i@6VZ+V #*'r):+k6;뤵𦇭Hr]ji!KnF`6޼ E9xPdA_ @I#g(̮:2v +d1/-tQz27,ʯ0-CG-uJ5\,T tS-6G(غZ>;gc-7Ey`uMq]_ܘp5i;²MORj u@ׯ 5Zv`ۓ*,)fBcM'px^*vӈݑu@.,m5Jl + ؟u| n7΍>-䷟an ;8|{^ /w9_H|"g>ρǚUN| a~v~bWXHC!kC,{HD{`?h":q; sX `Z<ˢsD)9BT(r1:BHl1"G@g#UB.f{RNwhFe{@"-J⅄$ iN8R$-8GS2o $y(Wr)|x^"{z .qXWICT1$47E 'LqN ȲLL%'8BD:nNv gaw&kLJ>N0%gfO!K.z45\ -'%40ʑ'H (JAEѰS,LY(Mitҋtr Bu4C% DT^՛< U b%Y]IZe2RuUFqq|B9Ll֛4]P$)DQy֓dqe MǹR*G[r~(4K9Xf _Q{˹j6u#:ikɿ2$4 a|KVXlcCOi[Jզ.5Q2[6Ҷ@UIHޓ5qQ^Է$ڌ/K_zmZDKGApHF0ѥj,[LYN QR1Ģ k@̑򒘇uq98{h`ܘ7,vw\C8-Ώ5b"cpuu o#*Xv`-*ex# NYaoވ/fi3vj猈8uҋd.irIyAE.vZ i!^ޘl"5&GWv=Hp `iU/dxvkl֥pBQ:^!#W=#9C>e-ވϳT[;jF#m+{l\5mWOd>wF]mv3jv+ ZX~Mm:<^su'pTTwȬkMѻO]rٱUy 2S8q‹}^7R@q@8qt =UPG?fyD$4GC@sͼ:zx#R /}_F9fsxH0sDM޲e~A!Wߡ-pa U )Qx?玣/!,֥S1TCDD{ΖAz[=H5)ށx|Ή~k@xǗ=C;3~*Qxz p_y%0)^1F[q&4UyXޗW!lWF+ruo9#H(ҁnIU6Ƃ.n9 4"6~7eCI="? '(hEx"'" ,63؄$#p@cVxX g}]"G!~c!_X"חxt)iLpXԔrk8k (\w8a(O ӆT=%UucCF`(XMsBic^XMnXPX-{sLX|!HzfTUs'Rve:k\苿(h8OƨwkʦhcM(5`x=ebts6(X@gȎhW!yHxpY7!|8\&y\WY먐pP_qUIRAلكqe# Y'Y,X$ȃ4Y199NÈ=u>C+xKw&ɔW7 Hi5Z7LʢNBv9cXVz6Nhb,iH)VHeY Ol(3b7ZJ)EHuJc{:3Z:@*xݵC:EWv%1~WJl)JZiЩ1~4A 'I0W(~zD&jZ'a G p|;"{"`H96ڈQ`Q|AƇ&g'~Ţ}@zd:Vj к1$xJE:66zqk#UrGwwgwJqz=X5$y;1 hK7]H 9 {x++$1uy*&`)`!ۄ wFpK[HkigpyЅzI[^%NKc˶] oK%U2zxO];KPEзA][ḋK\ʃ [ ]WI5FkKPWev06Jp >WIbia9KZiph $3X#9[u2 Fw#i{]Y)' 1ZHb[bytɿ8k[pɷSaUǽDՔ<#v]\g;h)^)ָa\{Y%d#lkP0"Ƙɏ l^V0B8n پWKKt@o5ăuh领YvLjj?NLT0T,QoTyC[lXYzB:v,i–mP 7Pk)ZoXIi-@+'fLta Ƀȉ~/qAO 'G iGmlK6Ȗ ʾ#LdFķ5v;vʕ 4L'lTU3ЄLhx-ʀMI8̅y\ʯjJ ͽn:ǣUqL\C:O]`w\JXVQL`bUq6UU0˥ňarj6lqI[ܾ0Z ` FW{0}80MbIZR'}]|\ۓoԦll~cLRxӮ$Z=ͶxBQmԶHиY 1lXH]!h"l?s7zW0|"J#@:x jI)>7XPg VxZ,[M޴lM\&J'XA1n<+F+X{EnUb)*zMb^Dwץr%!x8)co[ΩVjBxgm2MQ#+xײ-m"6=ɘsw2NcMC_hߪKv@n0rӁń;B> ߊOҮS35ͅ&}؉=? FXhR/{_)0gu_ Iouo/rc?z.џ=/ ا_@?.gk/3?klH_)-`/)WzH/+6$N!@=@0[R$aۈN~;(@@ DhPD-^T8ƌ1N1$AK~DRJ-]SL5m|8@@!?TPEY ѠHO t֪P~VX_%$p@˾w&׫,)ܚY;m1_ F:ybʕےCb\03ʒA{FZjr @VrhֵmKGӧ)UIӹ}G\yJBM{ħiiJ$hn ):v[fӀϿ]&_~_?^k)%ЉkK MOQI'SbS4IJrjSQG3Աe1ݛ*Y&·^mp м֥;p5@ٶg|aKi 8ágCm|Yy˻}U9l{BocWuU?O7(K{, Ё ^8&d}Ġ~ֹۅmPZAJa!tU3`q%ᜲ5P)IHC m_=(&dHbTC\PFHv2E%XIL-#"I@`R$K0 r<*[J$IA6 `&5 rcB/II`z6)̓8|h 2X=OoNi((;c {"3!thK2]h?V;,$PA26,D_m2`DRfD7ըr‚x}t)_B)Mҗ>OZӜlB((8ʅ# TԦzੰDiCZѪ:/(p_ʟ%/,fZLQ'7 ϶Xpaj_`̴ZfL\Z( ǩ.':C,$֒@fWЊZK[uJ,ĘGk;ԡnYBU#ntE4 `O&L+J1 d,X׽gNT/@5hjAv\zE\-J7ԫ-{y^1ꁗ<6z_yn}8\y{T(ljQi'G?'o*bbJ=ǿv܏VN mHh=/_Lg{kۢ@SC(AK&d @   >ƈ i C 3LA Ǜ#A6 AAl?!y A%l JB)\ @ ?!$$DA5"l /ֻ1dB's:䘽C).<+@C!,(l1l&@ 5\hM =4`PB.̬P,;VHÜ$SD d [EI2\|W?^ͺPOd ۸sN\kN(ȣKN]` 桋_Ͼ $ ?T߀h G,p6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx| @}7:8ᅏz8≃8w8k:9_z9S9G9;::/zzꞏ^i>8.o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KAΝ;HfIt ]'|Y5-hsv"qu&g ;ԍk-;q [ܙ68Q;rָ}e/!,F#22BCM$ KLW,,8((49CM%B:0-.uCDN..:33? ȐTabl|@*\Ȱ!(8HpȱcEHA4ɲ#ʔ+[t!@*g\;P;$pL %4ujjB>-X_Z,];-kR@p/C B>'BXc7_nS撑=KV!ӭ#{"շkM[7ǹ}&o?^03q;_=ao7Ϭaq!,722BCM$ KLWf,,8ې:ff((4::fې:CDN..:33?abl$@ !C |!!,y/22$>?IBCM ب67BGHS&&2,,8))5곴++7)KLW00ڕ+.B!, 22    곴@ aÅ J$1ć/:(PcB=*i#ɐ"OԨrĖ%%,8LdN;{hp<.ѣA_.-zjRNZIU+RjeUXj<ډl. `@`o  `J(lA9|S!(,u"22,,***@@@ww~'(ev ~ H~  "#v}n m w''w0wwhw0)fdgm m fe|| fuwgeaa]^| wf-- (<'(w++} C U,,tC)UH|v:fv~OO:fff;ZJ:v6ۏD:'(:DWHfۏ:UHv-,y!W67f3%I)JGKUC~ KK,-F5{ ۶fuT*((~2;5(+?'(WAKHf&^>$57S)7)l43J>#GT)VH)4I@~%3%>#Vw!A5mC((:f')j >#'^')CZ'_E]SC['\E)C']5H~D[}#}${!H{ ~$AIS{!66')%VDYTI7{ 3u!H,@8HŊ \ȱcB<F(S RKN^ *vӲPb N &p0PgA>;EF|*d5lj#Ĭ],e&/K6Y̆4o ݍoK LΝ pl6}{#p`@C.Zh;ԪcΎ0w:3{cܾR[ҧ0EW<1[apdr9$D9$@ 4 "L܅v\u4v:4Y\}'1(qUN}0W]vE1^DJ3PF`!(5q \z =G5]hTxnsʶwŕ|XY/d[ A$Y^PVEjYqv .WECŸf nШZd҄#i|w/$%jd꟰\RYzpiRiRR Hmm$ PH9[zşbCi گƉ/wzA-qNl B &׉**e ٩%k'Z@'b1p@*p}Ú,&W֍(i/_Ŵ.ҋ1[-GE4ĝ 0\XA<-!! ;(f\vō~Q!'`b%Lh|t:ʲ./=H^hD$7u =x܇ C`TN:czq'gz-u'T[ul APkw6KS3@KY +~# soj0Ċ]?< om(j^d'PBΗy%>(vSZVq% P p\ޥ&م?tI^*qkh#a=٩Ѐ <!@P0'/lI >8Dhb/ӭ -XO aw@ @J=ޯ QTĨx8ApsCX!u!ΈFq{lMu8щ ) &0*(bB&p{\#b;TNQUF( R}l '!QnyN)a9'r1uX+ xLpJh.E<Shr#Gyb׫29qޤ P5kb#xqBS2,[U@'!j @fI-^T8N0Kq %9MiNF Tu#]ɒ@/S5rR`=CG^$כm!ȁ&t U_C gD$Yd luxZD3$U}5uAKbPc( -ԧk"`]vU%uTX4V"5KJi֖ҩBE;R^y vzW)9XVR4*VzPǚ訟,YY˶B'LMP$ hSUlZSN"V/ Mmm\r9<WA"+V-Wk5s2 ̴;iXp]AM p5Z`ŗ_%eYϩ2z&@}JrQ%-n!ߎDmm"{v7*skZ:t8^z%OԗUӋ ؤqr~" NqdoWZt[7wꎣca[z갶Uj`C4a'l uXWF483-)FeDˣ<ix/ rf捿? 0RMVATz)_WbEmFSPhOQ!WmL21&GK#wl64|5;{4PDݵT""_5ɨJR˧ [-EwMD~6b: la IlԢ׀KFԏn*Jg=ܳn-mp1 ނb3t3ܵ+޵֋2~b0ytلvʟr}$gN$l=4'7J'~p${~ݎK'X;d`h/O׽f@ ;WUOW_ ,:͡t$ر=tuMv?GVfAe/2Va~Ηbw='O64c=:YRb7u! fwn'V Hۗhvt'Uzz'ATy(%R,A83_)mihܗ{~7|0<ǀ/P]'O?HrH6I66b% %u '8xhP_{&Zfguw\W_QB_sfph!6B9Vr-x%K炠{%1w~`XH$y8BDD/8R a%rʸ0cbاw~jhfX&vu_wi0AFfԋl)Ƙ,7#t^„U>(uYQz9%hDcsX&[Ո3(a13Ht#XlȇIVGi|&2|59$||Mgh$9y%$9=wS3A=@y()HXǂTڸ3!~h~^o(y<98I=Y}cG*I|ƔrH݁Fweby m&[ӕziLg}"w/'C4k)y(AH$uhlj2AT8T'בYÖ[|YYi" EgaV&n# y+~ " `ԧK99p2_ +A'Ixv$JE{^ IEe’3_K"N'Q&JkBgg04+2ׂΩg󵘟0~Yh~ε@$Ix/ )"Š($r՜8:&<iz1/ٙ/9j<)*b$0:4-Z\ nS} "E50!zB:iDKʤFlv-Z3jU:gz ѥZx"ɞcje3gsIzA)ut?Mjcy}Z&p zjTJ1hQ- qcjH^R1~Ǫ.*(Z\ :9W2r+WIA>1 3 +uʧTxz^&ӚW6f %j"|TKǫEjgaSjzxc01n'H#מH9Es8yMqB܅ 1s ~g@*KRJHV']ۖj5v;%@( e4{01.\fZ:¥ڣvnRiWXiX.a;M1j.r$xH#+Jvkeȩ B391R鄴n]3Qy;{Zwf3ˮᅥ*ۧFRK X*.'Jt;bMy.{?{B[#ek^V˻iaImZ5X)rKҽC + :<[ʶs(V1/;w++70S;j_w$&] \7[1K# .\u ZN&ܺף۫mђ? e7NĿ4ԥ:GcFAJ[v]68wPD5gzYkv%+ebĹ+ qlwl] 4KÏ,Aj~r,;.;n.{&og ~öZ;z̬_,C\}Qrʐĉ̽Ls-lM1sILDB/",XE&HL +6 E{ڜ& v$ጢǜ #=ܚ{01Aѷ;Jd375yEׇ$!З|.4۾\8EL1]8 mQ3$TWƂ-?7--ϸשe4mqի XR\P|}t̩9UFM#4k}(ѝZ+"p9c=͑hr*4(J-~Tk xm)ɵV]},| iJ-LbId<ӌ<mww)ˑԱc]=o bԶ&ms'z9{$#mmƘo:{ 9FBg A!)r7r۾Uށ*aLʄ~G^(_/)q@24M 7=y)-LH6W,DnyynĽ;eH-4ذڎa^ k-.wxc2^nXgҷJHC/̧(nqAnp84>9D0hиՇ ,MJC>^fGn(Y9F 2Q޵+ dqlݝ; C0oכM璄:܋T" ԡ@Ը@q \SU3a҄}mDnt@>&VtG3^3!N"^UQGu`_>Q(f_|% O284k/b^֦Xe\z\H^A/叼&@@DXPB 0D-.(`V` /DiPbJ-Ort@.H02=}Sh+E:"-*Ha¨Feh@N=uUe p˫s=ͽ])Zb|*,դdu+ɌF3ƍ^1bgҡu-t^ J#Q~xO/;v*jΉA/,+ٙ#lh7^Л$ZDž}ްwTP CgbqfCV9KϿ;0?î#,:P=|I ~0 WP2SĨ@ϰ+cp̈́lo|qb ܪC0HV-!%ɼԲI-1J˫F]tnI0wL䐻0 $#OrNNڀBQI'$K'dTdƩ~xLP1e3"Oc-Hn&T@J0 0,#mu,̗f3F6. -:5=3чBb؁V*-=yU%1d6Xi{=w Y2v՗jC%j Rt2E'VhI${ , I^{/`=HN5 = f́LK`8ŋp] !Zٕ;(3i(A19lp̙hS}X┮Z @CzjRQ `- ~ma Xm?'fh:%[9Yo|+\BP Wq W -k!n-tJ]|py?3v=EKT߁>u-㷋>ݥLyr_/[Rd\ _'[fw{׀}/ITN1 e_BM)]Z 4QXV>3$W|}_ g#~x4̈́qxN"6hecy.]_ j+H5yQt@#%Ibǁ9Jl~dC4D 9GGyHHH B0l M /!(QB_r2RK3~MA *ǂK4PYzK1lk-kIM!1!/MM#-SXr'+"r6p }٢U0n''T5RWdW1x%l+/&61`*VnV=Brp@ ZFw΅t:5c]K@PMFHȾn2/aKx憿7Yz)t=m Xv9-:5ɮQO߰B7qcC@ Bq l iO5X5j:DЌmigY.QM[̜8vCRKF G'̣ϋ:&Dnv[]ܺ6X}g 8>bhx q-pjpܞ69n@) wMjoq_&>InV t;NZ0G n~:|a9zYGUȳpzN2~J7ћ^DѮ:W>ZїF"+t^;{$O  [=+-3#ýN1"+ě  O4 ,3@5HK& Zçፑ[)@Z؁k-p Bø "¥` Py7/yhAAedA+s+;B$.BO?Hô. 8a)Iı@TB3h d8DX;/MC '3CB1:#GlĬ@J܈KTDṈ`|#3Qt+h[:U8w! Y{ע#uJ EcfD{1ӂ2d :8ߣC;$GKћ%+Fp$[G)yAGGٱ=u387p>2GlY"}Dd¥k"MQʂM@oEiUL9B_Gw/9т>#ivP|F}<~ D!8J4BDEiAAI v Z#J֩Ђ-jJvnrƦ*ɪ<~4pK Yl< :KkWD BZ#K$zK I)AC9F KIL lF`DL'f<$!PM1;$Ei첬C%b?ԸK"q؀? @αdx Å6ؾ$ϋ&JN9 یL1;OI#98Opǰ L =A=dAPJ4/k*<J25íгYP~z-Q AN *ЁJ| K GJ5 uI2ݓD<)όDQː.RNut̨m3%S2SZ-dDRR9 q"sR4R|t4TQP)b ϓD1]H ̳#- )+p&m҅. UO֌PNU= }@mz]IILP9eLU!f5̂R PL"$k%:XV*qM* )WsOt}0OvsSNƐW um8&ئ.K ZؗZW\P]]u_OEM<]ͷRVX8UA5m|RS6m}MD\Q-5+5$ `u(UTt8DA ,9oWSЂǕ5  T:ʽE-O?`} O *3ޏCq5YiU a1W^`n|,Ze%~jՀȬ sÌsTFSaXGP)1^H&d4@8㈲9$N=%ݻ_exdK;J _xbc-I >:Π=.4??Z@ `UD@@dvJ^_I7R^ nZS%jZqtZ> `B7^[]ݭ>dbrLqh0vQY4g$b f6h+Pc֔*& o~U|j䂹X,- -R@yN~#! }N ~>bhX;f閎 NVj,> { ,99+ԍ.~OrjdEaVm'SU6@N=)7ЄhH nk8 6[V۾6f핧5jĮժbVxNEv_7GS2 #0$6>.ak!f\lFism\9Ae.hV6,iY~h .6}~f.GcE;_pp$ޮn ~O^C^>mͪo֩"o!&'9*x.pX`cdzZm\ ^p.p v(fAꁩ"jA , qh6 w}"o `Zݳmdjojq|i^~b8i sԞDKsl7]8_tQ~<~l tWm7 )'̮Ȥt̢ -_Ocbb9rr ބc gVlVT e!C |DE YGnu3nMg9tq<(/(jeoƾiodwrQ.VXYg uhvQN?E(lFf_EU .Z9Ex|b7tQa5Srj- n'x{בf FyiH|")ou>^nu: !]EA(hQb*SuJgxGS Bi]FZ|kvjB,^2 Yل^Dd:U 0vv X^#N#,=]^ 0lu:m\b8.(7n:ޯZvǒR*_Ì lK\: '73j1Iq[΋ ٯN!\3ӌ>4`̪ V-EǰCJ-cN| ۨC*/sK.#`oǡnbBvMvڐVY[*_=܏-FfNuM4Na F.W9ڵ ŝ{4C2 -mj9py^ܛ8C6gSOC En}z1 -.n'P">s;bɭIY9DmQ(Ә 0@jiok id;ҫ @=0hsT/uA Jɛ&Z B ͅDXNB=XA)a1/WYZheD~ay[')L[ALp;eT Ð}aǩ1 K)F@֜(=E/B uE !}I.\?L5D1+Ay HA/Z Pi22Awg'C#11XH=}jfm"2Ps;MOB :L8EVfh`|eH|QWP^hd,r}D;G(I\=JDcOhE*ZN .)٩^$xvi [%*VO.y5PXm/-`S?ˡ?.bu\_V! Dbyj݂;"G[(商oz0#[Z0*k!h^n%Jbr9`Fi34$:1M][7^ X);ߙ_Jw2"oCC](EF?]kE@*\.orjՈn4. KHXz $51O$8vI5Y o3?ۇAjtta2K<-YhnD_˶xNo߅)=NiS[exk!߼Mʘ +w[]7),Q >+jԥN2W 5{rsb((2Q?ԩk;XmNDj,CBg$Hiv^sRR/J|2 8柄^[fBtiRMugBhK=Vu{ѧAFm7 oӆx|q|+ *ćK^מN3xU2gHϸzL|yڂ>5㞎߽Ϻ1tLɜD5FƩP_) y^ήp>ݰ DJ aZ ՟1Vg1Xh ^`PΘ\ǬQ\ wp L=ݮ_TnZ IUl଄iXH ELY )n^Fu_ Rim Aހ^Q w!tua"= bO!n[LQ"E`ujb(nia)~^Id`Jb|0.'Liz '^Y!B%@AK@cEݢ"6Z˥ 4` #h]w5 9n]*ㅆhM0!؀eD#?EWA #)$["*CcQ`1XϦ`$h=V>^t?|JduM1C>"ODaMڡN Of!(VFPV < `J AhX@i88z  IEk)MЂT->nѐl M Qb SzSYUdKN..%BQBe{5FYBd e¥\^LJ6%?f#IT0W =R#("zf)Xe*nLoroFT_ `'kle@Q'\'RRwF[BhFkDDlmBi(gbdL0{%g6Oz}*?v~u !"t(t>U{ YeV[ ut3Hцv(fhgZRgpg^-DVҌjCݡD.=̅E7 ե2IZ[^pzm FjEjaF#G'na&RH%nZޭii-iB ^ґU% ,&IX krMG (.QҦZere>*rޑ+1iFiZ\]a8VB4PnWf *Pmƥ֭Nj' R( +SLS\D:,Z> ɫ]gn@'~*i"^‡BHTz mʠ:I2RF(v럐*ꮊHI$^Ƃ_] {ثjZۂdlgiv+R` pNN]EE j*$WKx^Nn䳈Z be_V0QH jjGnEmmmzkT%;z*2F_(MYrɘ6Ƶ&2n:n@nzhҊaJ>D#.&祐*kvĊbڪ$G] lC0,/NzV}>+~~aQd/c\ɛ# x wYJB2$/h$/o߫bO A[0Olġ8!;~" 0M`"Nv[rhni=A0[eYA]reDUx$ꕖ`+ *±fopЧjn"D6ė)ud]qԛ؍1ɮg._khp?DpG03,nmOgF>9A$rFPX2٥/!e_Dz dj2./rGs/F00,_ NA)d' @jra@聤^53m3AU^S  3Ю HQCb ;4tOLJ4ĉ6KE(4->_7QǥhҢĎ O% 3zH\1Ds/%42 PG3y4H$ )>bP8`!&d ʎPڎ+KKD)ՒD,O44N@K2NU jtVkMm-^ Xj?K.T&vߣ_ro\QKT i&8$<v]wsw\&,l$z"^N`Ւ}qf1`n1U `%ֳ/6V;8V'RrT_"yCNYҺum;[v,ݬzZ\j:$n*@spC ftk"M"QVx^m.'x҅|oUІz` *S(<!'|Y?qU[rZa ĻsEimKtŲe@P( ׯJ7qof}v[`۶>PA{MS:XwGZ_XSH+14aJ?Zv0M` i{a@Qwu{X|&=.'3MxhvI;a ]I/9Wc2è,2wf_K'75"悍IDfDxPcbȐ&>1 i`$:0J^2- -=ЯtB[G3LnЇXIX).j(J9s) ƨ4;%L鹞fuН'V1x[3<%'됌V!E +E:5H JQ5eQ#<+ NuמI}yRT$p\(V= =嚒t%~4{unY\[HijMQEvC~!'mCKI&BEjĈ"rUο0tY92d;S++Y4zx/ P@b Y+I#d)YNt?W/'O8'ԒO䒙s bQW.P*ftPJYl^_d~)g)dYѫ,h$lxrDm+I3oёmtjnL̳4/Qh񧓬,*7d%`N=[ Bv9XZg|unYԭonbp[]K%;l9Z5SU渉F(mn"4mN m]~if ZW23I alu;7tSKeYKCfߕ uٍGbK )y i]s49 ;qr."U]֥O}EHʏ팴+cbqp敲D;ܢ MpON3j?U3ə{#=CM)5wƣaud1cjRch'o씜 );f~e4u/~. 0u{"?jQi`7ҵu=&B MJG`ooRbXUB"gʲBl9l;h}3 0jodn8 o2lڊގ/@D,30P7FF "v*`BV& o`grC %Gp"Hqlj0odՀI8 KKI  e[(CH2^0Ȑ~2eB)4M,>#B!!0G&M20T1\00' &>ޮyb~n;H-Eѵy"ЛpDڬ5M;:B'&o,&ʸB sBqb1kKqL[ꭺM7r'xY.&.FH!0J ~/ܬnYPLZ9T2r ',7 #h$Rs$"+Qf0]qaQ%)\r|`mdPB"/|I g##ĆoN rp *n" ^-L+q"'$ӥ q21c$Wp0P/n %. ."& S2RetDŏ|o*2q1( g$W6Kpީ:q<lr +#gp"n` 2d6q ?R@Oi("8uqSA/BL++)3;/>B(V.<61ѭw2">3#{ȏ8?M1RX#!q\A.%Rsb5B@Պ,,p37Si77NRn3e#2F5 ya4gR$B930)74 liATGƳn -}GH@A<b8͇6B8s0,2'TM4H5+HFC$qt0%:d~nZTP8{aT.t2JSxx'F5LdC6Z-*UkfGIV!<+]؂m=$vc}10v0D] @PT*6~x_һ.%XPJiPVi ` 4)ťr-u@K!6:SDfN;U.4@ jӅug+dW#XP]pW$u1 .RA;0Az6rW{6׈8un;zNb˨y-t4W+p|"̗5+ ZP}ջc  aCJZxsmbmWX?wK+zwY{ 8qpaW|˽Nce?)f)Fl ZA;Axݶg7׆qm80wo%yO(B&]ux+5p(9q-0a|B]ԅk>،cxXswJxZoю$!رηvpWQqdeFԋY98,)yY؇UK-1Z҉Ö%N)3a`TiuCҒw'$CuDjAY[]'".5*8vC  t*/mLWdqr$O (*57WP19cUC6?4ٝU1k5X17£`pJ2DYUJbd %zçm@; ꋑ//(`Pi7Ҥy BJƚW>ZCUbMЪkS zc67&Y #2EIK4@PsuX82<`G#w,S@e9s;?nTE9麮o6i0C!C'k~2?j){8]3Mͫ]*KMd*^1EWέx݋eȍ^P4{>~r޴!8g~O)w--}Ҡx[M NWaY]̀>o)Tо; ;>_#Gm(QW,W;&co0Uc@5|3o_B %pڙ߶oq([屟' <0!7 @ +Z Ƌ 0c1PҢƕ+Qtyr G TP3gGt<ѧС*IthF*(@`iҭI2VD=8¯jۺ} keנmIt6&H'´ Ϙ82R6(ʇ'\d:Y/ޓE ;v߆LX#h{o)X֋*w{24w @`k6;opFG0#=gbȹ9݂ ڈHuf!=(gЖ;f(n[/U{xn+FoM="&MTTy+zK /KoW.rYs EVP@90 P>M?uwo%5aZAg1\bJdjBPng?Hl9 5p@A$@;-wu wiz x29kvrҫi˝wC6rp޽ '~;FyÃA xt!<|cY/ wV'y|$Ρ3ϸ}X{=wW8/Aŵcdlsz_E:BE(eKuS|GئQۣ&?h$c*Wpm`X%C2 vEIhE4 ρBUԷ@@&I bT'"JawxA#G+B^h@<QMR:$F_c+ v͘Ob&ROh0;dTŨ3o9 RGi-z&"MҐWG}!w(KQ.c[h(袅WB0ۤ!K}ti4FmLz̕MiD!: k( ʎ/.57lC%=6cibIO~VmzsmNRRg.t&7hIKUQ=vp ZY/kD/@ ^sZ _ kX%I^ r9 OR(?nyՉ)(`6W#H9zl[tYGu[.d76ytk/XwuT$*_ Gw—nP7 c2kՒ"~«D7Lρ j#dۍJIڐ3_v,K!OGz츴7řZ:?-7x^W|X|wxxG%8\gsm.hIB{f%\ah]ft6e>SXTdpadx"Wz'Z\Ag7^aW!KZ~((M0sg2{cq$W؅qцvTt(xGa!2B;Bs&}X!%8p",oh1*؁xxhaB5nӋGHXmEW\ȌX%oU`wgw甉0pBpQ{ew vw[@xx@Vb2TkQ$DNf)*HEfdy[֨}׌:I?!) L/ċ`G6o+x,=BEAߗ_E2sa/o>%[tU7vh{+ U)OxcYiR<)*aKY 8U2)O7Ki7dli}X6 }烗y!(})`8C58|%We~ђ)eQ.pWXiz4 @6t8>`8Ok|): Z ah))E) [2mCYNCdG<)8G!eSWx%*)4Uzn09yZ4 GA9??zI{C 5Yƚ*!sT')#UI9LAjՃIF8:C5$ġ=CNbЉ)r!2۹20P£:RmFK KCS ZINWs#7"M٥8F qoX51&㉗ KG95GIi| A,7G'ʨ z\(kS*Jh?zHJGp#<.u bKH*:Ө(NȆb< <*M48x*JS7cպyz\ W"rp♫:+k}:jSJ\8S:ڬYAUaǵVZjtj(e/Zg=x^;ظn&[ꦛ!n z1Ra)K|?!Aʬ/ê4Â#C<%yQ**g`g0Jz]›әEB%?kny%%XI7U.ۜ#qx\Z$&!FB6h_qkm[]U"]֚] **UY%t۸>BqRu;7}±=A4ޗx뻊{fY$_Q`Y:k˚ܨ$!o۽Bpnfa@Mi+rqutUQpk&7<,Ӫ |MrDE&G^&9&MD 2013) :SbF yhoyK_"i<7WѻyD{BM|*5lLD`eNg S|+,)Fk fRl|T%Fv'J6AyܢLy&# ȹ'ʾKlG{B jp,)XKǕ7btmX ||"7c#Z(U|&3?A$L˵ܘd˛˽l,XfrUyalsQ)ֱK/?y~<CQCMOm5,L5(uajmͷG8,^:<AN'0[m媮?"PE 휼 ߿*=w̬|."<bΦAh˲\'#*a'<4?O5a9c9.$jl _SqnR_jh'QaeEe[?1 Gӧ#T4j:<:HR~TZW9zw?$hf^BLnN:C.<tT6nJs>8W.ʔZ("/O4šcGAs#czUy3^%~nС?|_c_$X dx0@AB.ZT4BDA>al&`2{&`G'\%*:i;} 3'eOA H4: =n+4<ź&r)iuP>pxa#0K4W463=-.<5Y;uUpmO?gv:m Tܩv9qS3RW}\B GS6[x[$a&5`ޥ<6B{75VpB a!.\~gѭZ/bč땹"݃`69fnԅɨϽ ~ /ΰg2֘^6l,5uN:Jo`κG]ڲ{{M/sd&;EhFt3Em9ƾʐo~8t0%6*IRl-E]9M9E vO-'?'YMoo Oy@xx/^ymoXӦPsRWO#-xZg7!&+ #x-H xm1{)\zE)ujO-v%+{Q<|1G!KL3E\Ǚ9a]ǣh0͙%.y!Y=eb,5+&Ikh6tU6窪@픡E[@CG0"s{fz$,]ݺ. d에Оv =AzӥQvuFR9ɩj=4Ԗ6A""y@E.X#6}Lou d{d|!A(;`{&)g@&@T|5 !"M@?_2<@{,rx0jd|]2+`67894Yj/g#;a4"Gíb2*@0@i h<|?6ƨ7ښPWC_Ab,JN,!вB9`FrrFVAɩS#kX:ö[%nso9H58Q\ z?ȊFFئ.gG~ApD)B? Ɂ,.CƕA/b:E Ɂ\L;]Hq.þUY0 JID5LGz=*J7A, `:LQ$HpxCē:ZLǴn @̒GLML#FZdLlH\ T8͙)0bM2LQrMdaJ1B-4HԫlY'YCMdN*3N6KɾLOLT˛$OO͊YϱPr0<{O:$H<:}ϜjPM4NTP\<K[$;J}P=: GM܌Jl Q!:Ύ=]MhiQ%ѣZBqJm R#Q#E-(,OQ˴Q Xȗ,{A3(/ 0}@MNG459Եtx+RUt?VґĐ#%TOF]Po4HTIS<uN}QUAe;D)5$SEF(VuՕI 8O7U*N`J[N-cE0Ao)S|J=TBSlO!5Ba9%(0*5E pKԘB'ʾoשKՁDC.J+ WyUɲoq~ 5:؜W!YUՓSTو9؊K#A@SMOM]u8"ځYִe%uۡVprK٭V]xЈ$?ZZ +=۰\4(7ϩل*==5%+[&W i:Z NӲBzˉ}ZEYLqHT\ɶzܹ,: ]AJM=\eI\PX6]:(/!DL]=%a["Q\NU獘荗%YZ\+ {P _1_ u':JX[Į7%-!C4&35E)U t`D3&BF` L _W \V\caYx߲1a̟ -Q a+i 6 xܕٷ&%`),~[4}~ř gkj<6n=n )3>=fQ"Kmc7J+ܨ9J< !p66€ <㖌EF5]a82\VI?NN¨cs9 c9Ue,*;b+R*VV6*Nq\H66BU OX-dfS>`gv.ey.Kev50]"^RG"g{c"Y6@g8dKB<@ʻ< *h*#JئkV g]%s.u#hE]6#s6 .6M bFvixF$ iJJ5_2sY_]άK` d.bi & <6᥮e8dIrV! \o}ѾWv6>amfag6lv嵩Uf׍D5ooϷN!pf6$!|} UTqpn]e lӎγF~ .'oB:G4'nFFIIr^Ӯ,wY^ K_ xK v3F8-._6j%ҡo*Br:LHqoM,&$"p>hUK'sX67GuZU[?\]Oa#oj_AHvau823e_˚!'&=os?srCuusL'܌w~UEH,^71lvא[Pl&qFAwW`7CKؑkGv;I/ x|3xChHg^>T 1Dyoྣ?wv>xrgj'zztD/WJPw-hߩf4/Ȯ_tmtpKCu^6hٷ'ޫz$MOuF/uMW =͊0:?Oq7?z Y| wzO|hVJo{Voڂo[*Sx)R`?|Gb Ǖoޯȿ{w kV}Ɲ'eï.~7Q%~ p `p!ÅP(b̨q8 ) đLУʖ. Z|)s&F &O/‚ &t@!JLR uʏ*1&ծ$zZ2,ف,RvmE8GdT\tiBZҭKlʿNn*8+Ņ;8UŔ|+2,;~Q.m9'o^F¾]6\ނ i;x9$Ml13W3r9&foE[,9#{4uc^}_j$X f *87@rubΑf }&f!Ucp+&!\xu=tAtmRk+bVM$c-gw8bYAVB9$[tH$QGCe{teo\YeI`yf5^%:!'5iMzf٥v~"鞜j܏Y)kT0EdjR>ٹ**%EE0C, PD2(dykY@n@vzl2pK\ ~ZHJKPFJB # 8 mʣ-?z :INBn&P̈ 0/A\ۀ6F#-q9;Ŋ.n՝o us*oM&8%tCDs[5B2G?̓+]Y.[fSʇ9~hn6~=8Fw/wKK>\|-OSQܸ}-u;|W4yڜDj9ި3;;CJPDN >Bnu ?W~w\?*Oe'cݜ n C60mZJK5BOG+NFs}LTok•6ܞGp X"FÌ9v`V&xF[~Ajx&FfG9nփ^†Y轁΋P h,+?kZlX%DnE941s"Ű5"X[X4c9DqJ׎PpP GbIpo\JC:&(w&K7(-+BT#J6K]`+R"GC|3gV^[#qRꛅ1A Ođ3N*?j-]^W?h?:;thK`xJՠ )k_MMz0^B8y -x  AL RKƬ 4-`Ui/e_=ya}I7q-4PU \a DM_yEɎlQ߄ߌOfLS ΛNuH ܴ輐 LHt츎PaYfcs))tv){sIfڦ\Fr~*2j^fjqX'j o&GB݊rA9b*j*܍zk4)_⩗F\׶+zi2VZ괾k2鼒^қ jqޕ@ %O@mI,vfzgZkD0lÞǠDRq,EvrkjŪXl~uI%ΉEQhbEҦF沂D +FCոfA88#Pmk%v ZۡF6B@Jz\lielACE.\kB2mJΧmբhH6S1D?3!3g0 @4SU5 HBnrCA7,f hH3>3.73ˮK)4 QBgP1K#Dr,OP+Np%$#S4V@C4WtIPDZcuZdvصH Ff̢pUv`r)1X'X+ POvLxEFiRv@4t@#b/,mO4dTV Gpqj'VV~5ebǜEWvC-wv3LX nfu~7wx)w v1`a8}&>k{@7z4G\sWtB#xL^|;8~YQws_% iAB47gS(" i>DCyKSy[cyksy{yyPTLAn(,[J\{LHʟDH,x4z7B9y:y9C#/:9d:Hퟛ9R} '('),-Te&\E[}#@ AL@ Æ#JHŋ3jȱǏ CIɓ(S\ɲ˗0c̨pË \aσ3 JѣH*]ʴӧw"JT>yBʵׯ`ÊKHQ!jMfʝKݻx󢄛#ۃmR9XÈ+^Xqݪgk̹Ϡa8Uҗgͺװcmi˒%ͻOV 7"W_μ}V. سkν2@ |(At_~_>=魇 걇@ \P,j߅fb с .Q9@ "(4vEbE&gэ)d{)J5&LnDĢIC_@ GR4(;+`N@$LaG(!)H)@RH"O l^Cu/7E) ~0zN!? ( cTJD15)Ȧ') ՑŔҳ?/фI"(?qIٸDuV":}$i 8[cؿ@dc_TߦP~5d$Ffx6]r&?$3i"ZBǘѣbI#)Y6CK=-J[XKMVɏ\W%r}ͭ~:Z8=F-|W*AT$.]NfhͷG㎻ZG׬$.6ﻧޖ&žG-;YG5?D=^09ψ9-e3t}EϺ8|Km<#8S`o.F=eWΖ6"Us9FM*Ji$[VŅ5 +!~(S'"d=Sn7>&ݹ2TiSf7 ܞ3PФ )ĩ|]gH/YyC>|5N3wgMAϊzC] &(ԀOӒ;Ϥ 'Vѿ^uw>|XA%DoW-Ul'x8%!4.@b@X@"lǃ?XK?IȂXHj-6M)P{Wc8DX'dh/){k(uxx%2A+Fd=Xx/>ft("Z74L56(}ms4cIwdfsrӊCFxchqW/ O~{QHj SfF2Ԉ7`fA맍cf{hTHW3$$A9axC{eȏ}9BVF @9hݸ #{9u 9I9Q#Ic; lȒϗ08589999j5 ٓoA)#_vHI8֔(4I}Z 7Gt}#bd7&ؕSvÕgYnI8az 1cWF\E1 ~)8o_b`ӎ>t8]56>X}9=Ж3'b\v1HVʗ8YgTGt1YyIe6pYx^ ^D"3oS3)iuԹuٝryo8@7ZXV5 9i 6Xvs+qÚğl\ 8 6B 7 6u6D Z4f !j5yijzɢ Ic+*W5e8J09 WH!Q%֟S ]*£g CxD#pM>HKKҁZ8ä)SjM)5[jld`A+"~GJJoӆ>|ZJ~%v(Ŕ$1mW:' x8Q7J;jmg( c9T:p&1( 9 @ ~"Xhi҅`Xګ㜦㬼bC),vZ9H &hGZ8a.BIҩW i*:!#j<[i);+\ >8Z1K97;(|{@`R;xIYaC"2J8b<6<ӳy619ɮWM#ϘdSK5PO`[ 4#c{1p{)}Ij IKfu&M #旷tcFq68q# %9J|c393ޚ7[h /7iDyx3 kJi:{5ku꼗*7qZ-gػCiȭqfSa|`c q;ܛ3y{k71QD V|Y Ea}Vi ^vH&c)B(мofJ]SlAK8tյ[(k̦%<(m,xHp>/JXgsE\J;R'{d7nBRz`LƻwpZ*^l4s pS+k$(kLH$tDiJКI'u,tn('ȍ\HW*@JȖ-lw(5|3j|-luwj+Rr&1UK\bB:o, aKƂ7P̶\Ll^@k9K̪ӢWթ:cr7ɧk x릗q_jݜeɄųK,g'f Aӥ:Hƴw{cO,ÇƟ[I3gN+:\QfLu4(͙[: ԧcÈ{Hҩr17 h:LPM(CѮ'͞cb1<Wز_2D?aAŒU0N~Εf)8`R=o/m0s1֦k-aa&B<״q1L[!$~={̖M}c'ؙ܇-Q ;-w-(}ݽ7~r; ,L=m GxzQgO1/P%:}PL2xsylj0xr+Hq$:.|!5Nmt J')$BƊ;]u7N E.A%'^ @ګVm Wl5)ݎ!:pweb 5ٜ:\׻^0Iڞ.7Pl"ZÚe1?_iĬ>Lyݞћ1lnloGzxyΨc|k_= )V=cf~NU#wcϥ|f̌>9o !g֣jָa8oNgNrY5QD-^ĘQƆ  G%MDRJ-]S̃hN=}Tc @ETRM0O^ŊG~VXe96:Ym&R[uśM bܐ#FX6dYPE%_ƜYnUWFZjhzf)eƝ[wD rGō8'rXn]tR4ٽoԵZ)0zٯw>| {oCV]j6]r9l[ef x 롷Vz%)o:!f錤 Z=N^&K+.^Ufq;q@AY5JY!p<r8)~4Ӹ\LM)Gq^ʣӇ_h@3~yq!ɞ7@Xw\G@zzR59(xؗoohH%4L I4ERr*l<)+Rf'ցJd/ԧ!t*%ԨcfӋթIjN=TǢ>ժřU3=\իA@:!jZG':Z*&j>[l٩\W&uHֱ҆ kHyŬfJQlh/c$99iEZlMYSV3A->wӗַ!-hEnf(Ő66lrIy+Cֵb^;^"򯨩l?ɻ^ ^'Rղ׾)@X [ڽof̘ /` ]RF{;V/h0U喖YRpaڮz!)[뤂 Qo<`AJk!fҗ) hGJn1 7( IPTDced = hַg LJ5E{_97Ίㄙ)Bs0#y&)421+,$%5*cFX.0li$\SW3Pd6mY԰꣪j8G4O-:^/Ը0ٺ_q=r;d7Lr7njwBm|1<|>tGGzҕt7Ozԥ>uWWzֵuw_{>vgG{վvo{>ww{w|A^>:. R?Y_4Me?~?7yCޚRwU*f@/j6n׿>/g[Wg|G~|7χ~?}W~}w?~Gտ~?jyoCfS: |@7@@\3L,!xa KP*^CP3Q%T -T# $(,<@',)v;@}y%_ŒR׉1ai=d6lCy3 Dbh7mEtF =CJD LNOPQ$R4SDTTUdVtWXYZ[\]^_`a$b4cDdTedftgFO$ÛFL9;*=ٻF:P`"M=;N(D`GpMGv|GEO h =kQ!%=HٌQ3&-QפؠȀ !,yD)22BCM$ KLW,,8((4CDN..:33?abl@*\ȰJH+jܨ"ƈC4ȓ!KDrʕ-c&| SM4di& ;y AP'` )˒ :)J DAաH׫bّ D$ oe@Bޘ\È+f b?Yd-_nYf=>ZhMNz3֓_^,tڶmp7oԑuW-\rf#|УKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f-vZs5fiFj̝ۨ*p*ʭiΆe6gaƅګ:+ɺjH!,'^#22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇŋ01Ǐ nH1ɓGDɲeB+]d 3̛k3%{ uC", RP` Ո ը W7%`j[Q80aYIH` *>I0D .XXl0aV_Ɯ1͜{z<:ҠM,MZi]dMlc߮0n57pċ[D~ٷ[;|s/6>Xw@!,T#22BCM$ KLW,,8$((4% CDN..:33?-r&Dabl@*\ȰC |HŋǏ j abȓ(((1˗+Y|IcL5s^Sφ< :h( -5)KtJFo (kWEc(0`K nӆe @hP`"P1@@أ0ؠ1Æ-YO:{ :t)OFi֩>}ҵi۴)➝սuwg?.kg^!ƫ;0!,uH22'(  V  x  ' ܷ''( '"x!('"!1 1"V('('"4kG 'IX|o22 ! o X o| I2BCM  ܟo 4I n|X I2o|3V"[ $x" 4o|o|]XH 2 H2H] H2 "Dn \X  p3J2 I222\ܷKLW 4 2 ,,8 I2| 45A [Xx!" \X2 3 n|((42=|p|"D6A 4 fJ\ܐ2= ez f] fW2V57CD x 671 J|CDN{rKkX f..:qKm4XzlGjɷ!(lGkXXyqJk"C X jIm+e!33?n3kImBEe G2n|+"D oe[ablqMnI]|2o|H*\ȰÇ#JHŋ- ȱǏ CIRƒ(S\ɲK'_ʜI͛cɳϟ uJёB*]ʴNJ*իXׯKزh^=ۣlʝ[ݻo~5ÁUocNjsL,ʜfYПSE=uc 5eכKM7VKQoƍ;6`K׼s{ν~O詞OϾOq_4`t` f`R`>4a*ta^&(#ц&Rb".`2Hcވ#:_>d I${F^Jd= %wRN+Aa%x%aV8A" %|B&lzX& )A$'`vv'z Aa*i' dgq/*)~`* }>(:*l|jQ 曽));f|I&#V gN[YNmm]~KWEnnZꮋVo6o^݋VUpN0S /RpEnOs½Z{1uFp []'kȦ%[-23\]C39Usϰ[(guFNuyPO]SVu[wu-} JbRfsh"Axtmx|߀.nx$c^A(G.Wngw砇92ꬷ.nP@: o'7G/Ww/cP:,/oo*0 L:'H Z`r@h@ (L WB% ar D8'w@ H"HL&:Q7!D(p ,0r$آH2hL6p#EX3H  iy8,c ҂D %`&7Nn2(GIRR}#D +1 $'J"8ZFdSy1frle Dd6y%\ֱۤr^, 1Cl08Iz$3܉~ (>͇\@+ 0!u(p-0A-"щV5A8nw nd ؇` 4 0!@n`N$R׻eD 4 ^ (nԑfw3DtYb7 ='0 o0N6rJ "0C2$n@8àzpy8!s 3װ"XP>fq} PL*[9C0x YaҲT(Y8˙XH&2Lds4pr`>9pvr@cĹ- f\cA~a63+[Ҙδ.LiBx+R dH@D6g"!p7zfqk5̠ TB ~5@a tZ 46~v,,koK!67[Mz{ޫV5D6xP T 1•A" 7@hЄ`B1A8 q.( L@KM` U<+O#ix;~Zd(Wŗ;PԥpCI OjԧPmLhO{e,AjG{vMz³n@Yp8.*p'O[<>csd?@OқoCxW` 7Pvj)Oo{+:;ЏO}<>[OO/XO?>+tR" p ؀( 1s@ ؁ r,,`ς&@1sn!j4ȃ57^ 0m?iDX`OOh Z Vms&^PV`@ _xM8sm`І-Xpv vx+mU8syHڢȈ∏"Hb梉ȉ≟"HbcXpKs12S(D3x33ȋ/2 ŁĨM.،(28)Q78(1?(Ȋ稊鈊hH(ȉhH( Ɉ I 1'h*ud%bFpX,&'xY}v8%_*b'*BxB1%W{; ( ,&'(iC=) ,KkB,‚R9WÕDm_(VHKh?5nÖG"6^Y411(Dw9@fJ3ZŨgciipɗ( $si,y (@riY~2P})u'(~))'s9'^BUYYh4+A^2;#IcS!tɍ,̨ٞC !9qj )i^z9i*iRx/ ʝyjʹ1P%!,)8J">*5B4s颦Y]^ž  ,7/4,0v+){I,ʕ!W RZoæIC٦)w'X'fβ*9)N rV ]r%' -*ʑq9'b6xsI}"B9FJ)Gi+,)j!9:2P a,`ZɬЊS:"~zL*?#9*κuo6&9:Vp *ګG*IQ`ߚ") A|(f2񚥁*㺓Cʣz" ˕ϺwZ* % " J+ )yJ>+z:ʮ!+K6 Z1S*Vv˦ ?_QZC+*ʴHzQ*['".uMZi@˟عm9!] J]뺦b JhkHo˹㙹 x1#YZ:nbU)!6:,i **kӋ!{{'aD˦A릆k)G۵#ɻk"۬:n+>&Z7[P)\S5JZZڨۍ۹:Rx,L.:H^1"x5I7)9ɕbz-;l˯Pۧ'س:B<O9<<}AX ^[VzŋZkթǀ̴ YK{Bs,!݉çȓXB-k鬌z@fkëLCyqʝ<ş<B};5*\< R* ,\չjKKϜYl&^<#j A%U,s<"Bb"BbĂ"wBebVSPMJG"DBAb>;852/",B)b&%""" Bb*SNAo/0[aaO fZd\(|.^.R_6Z%4~ڇgšxoz߃sҞ֫=BɝbuO/o/# ?#_ O0τ/s#Ta<2ȟ#^AB_$!H$؟TN/OCo\O1!!A > D-^ĘQF=~RH%MZL!ABD 0e(N=}TЊYBAH2ITTU^j TK:UXeӡQk|\uM@WIXyzN? h/ܬyyȝ=R&tH i )/[잫mm;jδ}^Q7ݺq^|;r杇N7Ǟԋ^ӕ[^^|ʻ{~w0@@"@)A## +Đ 3 ;C$qKD1Sd[ѷcksq{Ү$Ҭ!D#dr%2')Ē+-S/$1D4L6t.㔒3K:N}zp>z| Է>_u= Y0 |hq  A HpPn'AXu,P+(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n;;`)4POi 0AW*A$8/A/߼g0 8  !8 A@fߟ>΃!>/RSF` `^`нER3^B矀W%j({rfw袌ZwJ6*餕 Z$B)P  bN}*Br H\뮽jLv陴 S:)@V{KrоT.nҮA(ċ·fKB)/TK.jJ֫1[-ۭ[ g, Cҹآ!wNS$++3OTD@0D t0%U H-ϋd!|~gII+aA2JzE_G>~r9SHȒNJ\DˋJlb !_KifΧ@]LgZNSXIMW^󛯁A|7TA"̘3t*#z3*IJs3UL Jqg@ OЊUBNzDO@CI=~ FQ0uPӚuH Bm#P}MtH8;7ͤ:>ФS Udb0UJD`eҰu:dS뤵#l\J* V^!TWr[/V7pP:6 K5!;X ZήX҆ LϢ ZKѼsmmw$݌oVʪfT Ĕ͍`~J~Tݿ!xŽhAt^v .m|ɒ)jx_μ T.^0/BLa5^yoCw` .+S),Vx߽0K۲?>BDVIpRSTـ?eˊkx*b;c$F~!szOamgvO7.*@f VTe6![ Bp5Re. O!MD&NT͝S~ I+ g7VB%DĻ5j#ɸe D~aCQ=dNKغP2PJŴjtۡvҤGl3qRm\[% @Ӏ0,j CvuiהNX睒w-VF@홇:6;w;$ǀ]lb31Y9q I9篞 Oyؗy7βa{㈞Ȇquhp@2\=Q//iO ~+Q+$7ws_w/8?Yr?z!`:VZT1' P* h XYWO!zh~wV4%aa4gxqoSU%A&F%.d#4X\luF:(`2$e'B1"X%J_wf-=C(SVK.BObąPHlzHtVh o[eE`NօnV^UqH}xb-V$b'`HI.{xZ胈H-0' druTdxPad v-_TeD=r&M8Tz/!Pm5HGg'j$~=AQ?Vܸg`'Rx]^#dx^4M\H+(\~F4Y\Gsply9Tgi#m?'*G[ő+"Z&RbpYx++?V(dA"0"O|F SS&<{RL+h7b=e}sV'W; {5>_Y7Oc=7WPIN$gL8WUl3SHVK2$Ex':*wf}'iPQ4SuvV(y9C-,vٕJ%kCHsxVerAIDly5Vx)FT(!!I;W}b5cB#Ɯ=O%pe1ĹkIuGɞcK;Y)VC)3cij;6%} ٠(1d%Y,iPKj pros6cɠs(g!t pBl'GIwٚ!Z?r)Qbmpc߆nkT~|tnV:*SJqNj4+6:sp¦PG:2nr΢<-Ksh:0pHCJ_*)w$i .qEʌ%~oM-k&k֢}$RsOtL35DGB t94Li`51*J[E?RXZZڙYɬsYyJZ0;r'ɮ=`*@he9zBZf:$ xDc%9˟ea[8jK{kCQV &KWfe5{d;}2۳|ʲf[泃8D#Ajm҉f\{b䪵 z0d[Q /b[k[9/js[Lk>pXI'OeiSն[+K[b{KvS죷{JKS݊'kS K%Ryfaovj d ڹH4gG37л;L eJ[A{$Q^@ZjcԼ[dtd TZf½8P⛛[4q~{7$r6s W} D2 28Wb3p Ծ\}+<'ܸ%&' l+ VMJ-ӻ18< Mȿ^6ÔI*|K9컥KNכI\ĖGLO#|^LţčkM_/ XEd,.(˼ou?ia Cyuf,ƒb++1ZʴA,~4<8ɗⲼGq\Hw/%|ɴ\7ȳvtÛ,J"@1ƌk6K!FiLe\@{!,<fך?{i8(V4%K V: Er͛l//Xh$| 8KP#ѡ@J ~Мұ !&]{",%Pḥ.%0PAӵ/Pu@D"$}A]AKm". R=iʡ66Sj[]p,,J3A2c4ڟz"fl .׍jlRx+v1:UzMM5n1)nZQR ,mc& 7p-+ciyCײ{mвֳvFa-ע*,yQ.:تt!AH XUżڕ {bÒ*O-՜-y؝ݎX~, S }>-u R>}- P|~R|]̝LJ/Z&~z~Y<+yhQ1y>/=7~y#;u`mgS=wnSIw}uR\TNw?͕p}O -NE6g^6f儂i>䀶I].` #^{xhtV^wM,Vw=V|.&k.bMUJ !_uf^>_l~q_p>e5H\s.VHJra`_뻎Dm쁥ŮT!FAe6&bN83 ~a 6e&G[~__2dL7n;\^A͗nn^YH|r)ef?$c0бfxl3_Z)%q}8QK~g1E1o _k.Y hP_4Ke'_hdoXBJB.n#~=mbbR#^4rS#z*$N"yD@==2\?^iZS_ZO]Y۷Qu?`~awXU {BEr/Bi[YAy~yOUK&ro`i _J@@ DPB >QD-^Ęb QȅL$RJ-]SL-SN=}Xd@kDiTRM>fTU^jqHDUXe͞=8Zm>LśW^XpM h}=X! PEdN#.Q83t"@ mD-N/]tR/1/3ʘF[HFpЋcFPĀ;Ċ}b&v4)[C#_ȋO1GA$\A9Nd(GJ52&;i\JipKVp[^䏽% 1&L+p2)LiAP.9jPrU7&~S#D9N23#\q$;Iy %9Ozn̦;{IMFm((0 ZР- mH?!*E6ҘMF9KGi(.aАҖ%\R,5 C_tpM]jSO<EDyJ1jȆУ*SI@eS1BUrd)Uj՛ @ PJTs~Ҫ;k ʹ5@CJ8<|O}5K9UUwv-IjwU̪hw7Qu V kNԋl0[Ӊu03[_YFdoY+gϪ5{1$햖ӡֱ)aՖ.3{|,nm{0V"O*5P&q[&ʧGk3B=o4 j;u]l _33{zU_#fӯ"+})X~%j$O 7_S2J8M/ ~TH}, ̤នҫ˨W]l~;̏n1 Ͻ?[+?ӁNKgo>w~U4Xs;|?,x$+ ܗ|̀,$G 1 ˿  k1 ))Ñh? :Q1,@.1p F=t5)A[p)1A ܷ$A? x*K%$dɉfɕ]^1'!egA/i"B4bCSs{C:9)׋C0C?C>l0?K;.:?j$o? .PR[ب)DD j(78'r ʩv;Ѡ W% D,a\H?pL4l o'1/+;Q*D&)o{̅0Tza$^j❞ RzծR2;*WJV(,Z3x-ŭkD׸Ft벫^Q_kWjĒicYoMd/Cögbư)iWZ4X"bZΌǜeH75B3aG ZHͱ%Wf1 L:>.,;Pc E}DI^Pj-wϒ brr&),kGw%` HX/GA|; 4oIFhig,a݊q)܆dq΄re Mix;"6 M\`y 𑵗d>d(Ky{v|௥x 2H\Y =^吨yCrZ촯9%wsgs<7YsȖ\@ z 8ZqE4MЉ^tL.Pzm9s}'o4eB\vm!wkVdY]W\'ׯkf />9lskp[M^hK&7_e[N̛`m`mlo#6Wm~F'>2Z|spfɁ( ]1p}kڦyMr`a&7+%oAwq\2tu Ll݇5s~<8|O[ɼ)v_)G%fwVځdd'seazFB@u_XKG/C;/i؇]DGUb~o9RO< #%SwvG"g*lD8GN\tcs~ ~0R򀃃6$_T[dzwW#)TEXx0I~2"Kb$ \e|F$V*؅I( a8yyThW(+bc6HWmX"Lwg}_QW)q-%{FxzW‡}h5&cȊmA(V4h,g0arw8ka`_'j6,eh)t,vMSژ' Ty&08{0HCxQ¶tb8OXf鈂d,y;zOyIEdg;=Yq)D" oP7~pɒP+b,t(p 5( (0M?H>r51E`Ri;z75@DBV ;\y0Mf2ȓ%u1P':~k8K Oi9;&(0 D(:)(x =:0(C/(xrt9i(y+XHe3C`cxxqt!H\1S@@*Qs$kȅ1啃&;d&w?Y+E M_sYJ+1v a4`GU#z)i+Ȣ%!x9Vrй_46NZ9c9=tbr|s8[(@sZ 9T*V'dZxw`lZn 9$oQDzDsij95 K{X8:D$F_sh `3s0g!Z?5}@J%J<)=-ڪIIiJȫY2t*AS(᫿ R *ȚӺgGR+ںf1LS2J --꺮[qZ%JY!rZU-ʯ71Pz=J51)Qm/˰-a Z2q±)!BVs/jb * ltjrj' 0òp-<Bb5)D+>F-ykv;%4 J-Hq {'0ٴP{7׳slv[':mrqrIrmghE,&ۓ |%w+n pkq0!'gڹrF. @[O^;+YE]c.Jek'#뻼Q&q3`8XB "t |++'j G :8U[aRh2 a^Q Lgѱ_% #k**'ڿ`dsH%ռ4>ڜO3;#]`,v +H77˄8$̺0iK;+Z9;'k.2,-B:(}A5b,X`FÿǴ@L#ɲ~s#>X,v6z4#;Gs$]\fk_*73SfS$x+m,h\ &,}z\ %bJwZ˶C"Ȑܭ}ZȆ\cɡ$lV'RrȶWe%,>\VHZrrf3i3^GZt &,RZlMr̽9~W˽\ҽe*I@|Ql̬ͤ%|=ɥΘV~}'d?¤#LLAHľ&.3yL'r Cmь0F"!} T=4&Q[B,zs&YU,t%/A2=U2VFBᛈRojT.p*ʩ&QGg[k3 VFm*՚{a<֮6DHiԡ,'Cͦ6u*-HNmJ (MW*M{0؀2VSس1N$L_D{ׄڎOr#9+HM%NNOcM-? =+;~F"ڊ%{5A}ݷ]mnmnc[N]ޔ!} :u3=1*MK߁: n< ߲sg=V}C>F.u.~DoѧcRwܧ+hqʚ⒖\0=8{$|u=2JOW8!֘h?}=P}TNI^ervWkL>[I`0LpcnteT^> RCg>Y>xVjG>H ^EЉmpq~ߎMg0yDnD,Ѡ,ʹE]Jn)YNX Q)~&.@ 5t.)nІ~&@ whe:*+w՞Ӟ^[t𼲭NST+n1&A|7)@6y$ @FtVN\B b<5t?%\_jkE{ހ{n24P-<=DASk^{^kfLw D_?QK/yg:Y;lUV"HdDIUr?v|Z'/Ƌ.}XOEcD%Z7er뵧wE^$ Edy6zO_NOwT{ßcHKoS8djH#Pʯ+imG=m`>#տPןߏ#|hۯ؊|H"Xz0+!@`  C \ѐ cE%MDRJ-YRL5męSN=}TP-ETR9BIbƕSzdSM63We͞EVZ$W٭!bdiaP/ๅQiXbƍ?+dʏxY":E6]y.ⱪ][v[m>!_ΠC 6kōGnvr͝?')61tխ_*vن0x巷6^zٿ2z{w_~J0@@< AT@" B 7.C?1%C$<41GTE{1FYFBFqGD*G o:!D2ITIXcI),)J*G,J.|LK0LK2ϔ 14tL6+܄3OԳ3ЛP 54ѕUQu4RԔ!Q2tAL;CPG}TS55U>UMT[uzެϾEn{y|`;8Itw|uPH v4`K !UB@ >dt1mz=x:: J qOr k7xZ Q =FᢈcCaP!|A<q vD%QSb 8EjWO]=+r YS|xFpq+c4g^|c4;6Qh8 HC1rq IGd!3I=R'A9J}r\!̿5/̔*IʉjtfrJ²R{-WrD+/=KI nh}iGV mn42L; h2F0MDkX p˧ummڔ 7 uNEkIy3f0٨k6dw;V\7d,$|Ɉ]>4g0 :$Wg4w9~4xJSRxF7!Nu=ԧOZը:jR3TOe\Q:U^Qժ:UJnի;W*լ**Y Yiuk\)WֵTvkWg}l}X®bK6OuldYV[(Y⫳fA;ڇִ?-RYB&=R>d%E&RRbFalL%a1_6Qr ~LD̓| 5 *hC[i A 2wp5wGț{ߙd+.@\FQPLMrPl&w`:){ gÿ%wӭ[-Zx Yo, )AKoڤR8~5h{5nO2XNvyҩ$ pq$9"N+'6,G-IE|e֥ok!=Y>9J-¤8s nctJ$ atBx:Jaoxȱz Y1}jw|?xG|x7|%?yW|5yw}E?zҗG}Uzַ=hF[skio֞ `{ۢ=INrBMv!].(+'-93rV"o'ǻV'=^z|_2ǿÜ?9 : PP<Ԍ( $4DTdt !$"4#D$T%d&t'tr-ͩ(B0>3hB0\>,ܠ.$?K 02<"\Òq0888ܠC/C>? D:~<YT X8Z]^_`a$b4cDdTedftgJFq#Z!F!»jܹsC!mm$Go\+6'r3G"&踡X""jQxE{9ⴾ9$}H|GJi&0¦"JlIDqZ[|:AtlxI\̸E;(T?Rˀ+ĭ:(Sɹ$hA ˑŘB)!(,v22'("# Vx '('"'''(]^x!( !1'('",,'(@@@G '" 1"~'(wkV(3%T****KKv7)~ wgR*vx @~((dw!(HGT)tm ''FH-,y!D[fhm uGuE\1$1%,')aa--v2;((AS ve&\HI) AL@ Æ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIM '>p`΅ =xѣH*]ʴӧPJJfO?1̪P(Ъ`ÊKٳhӪ]4C8z-ۻx˷߿UuTǐ#KLX"ݞ!ZMӨS>9oN,z۸s;jkم=Mȓ+_~|CvΙسk.U(Oӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlpƉ$0'Jvd$Z<餕B*)vic6Z}:`'@~*zJj뫴+Y zֹlT´% k2Q @Uw+ئ`RtG;N fz)yk*0la-*&101YT(P_pluL<,r'< P3xX;tJ+0C WD/5F# 5Eom6S }p4xAGvހ ݂'x_-Gvk.p=w}_L^͑)[TǙݞlj^wO̡om]3/g/%_[ R$ГDyz/շKᅨsIGL:*,bj2@ZBܫ`H4x:(At@pp(,rP?CJ _HCO)3B*aRra@ B-j*{KՆӲ$wMibuK3yKD;hqY(ƜqC;I$,YuF7PcŲQGem㇐?J)dѬF)CkT9%H:\/5,!?2L'l Q96W~2-dXR^Fc/ɗ%ELYdęʌ&XfhJQYn2i7i6rL'_ ӁZҦ,'I|[y+\ cP:t D8AN阆>6"cыTs'GGzE"%JeB8(4+J S4$eMGoJ8f<%?kԢh PzL&UL@bJԬU:TXu.'j Vs5d-Ym[=Uոu+n:H\^y_"YHE JJ[Zұhɠu"k#&Va,f͢\5NQvPBcԦ+!IeSEؚtUNB186Inc}+&AeYkQ2)qM+k[77gʝxKFU5=zW1r|8Ʋ ~;9SX%EoFp`kͧq0Up$?*Py)Va"2e W$(@ڈ"=k_TM獆0u׊Stc d5B\ɬՎ]\d#0<#שUKֈ W >;z|`(G]jP#ҁBy$˕o24Y%>#Z@\C|o.HG u]1ڣ<8IZ{ >]Ga}q>fOC8@L_:o}/1\e=GR[V7}d|v\s _lH_uviwbwch7%y W'~ǂ%@&VB 6xUC~;o3t?7XFcY1≟ fwwqXg`,'Tb[cK=*Xb-8Á:HH$&g~ݷz';"8$՘0];㌺7Q7F{{}ه%&wZ.h7wv]ҏiU!9hX$ & zoXN %y& {JH8E=I h>%!iNWr8h"1?> ^.YXoKpo`L A`we`SB V8 q8 )]Y>Y!ЖG0YGAi;+3mcKYvuіFPMҳdJd2 /Xi&݈ti7`rI}&9&9m5 '|l)  ,3![)AٙUkɉU"rɌpa &3V2#&b-&$ɜ~wҞj2F&Ӗc#i.&jk#h}ֲgk*<0ifailrj2lj',ji(RI)&%\i>Zi;ijfn*RRe7'H/(? Rix.&df6h(d6FǦcejḎlZd2f&tfmv1nU:d6iay("Cj($agf)X*,w||!)i3 ~{)a6~㨫!G rAj7j%]@qD0(Qzq[Gګ 葪 Znx9 3`Ӭ'Ji'iZ%8:zb6SPl s:H{rzz6r[_#lNzAc0xó6# s/[ 9H;Z8UkFK`®WLU R#MJ!`h];"I)?kED!3``<A8"3$6Kۅۛ@Kd["@$Bjk{ٛBp"-?؛Ù;!MT4*x# B4CgJ2EK&'7E*;!`' )ԿxYHx+?C&8! "z?#e1a*~ )~4,5嗾'$>u)xM.;D~;HhM:O~SY焈cMY`^`Ƕft[#eVȾώ 1Wc^T E5uiR o-'?,?+,rl9PP:'ERG&IjD@7TƎ-)$G[%>aeNdNAŭ~ [lno;la?Mo&=enwKX?U9AklEց5_Key8O_%ߕߋcCJmF"O3F%oE?c$P?FE"`,_/$8#Aҟ4?/4ۿA#B/oAoA(Ÿ  QA.T020PD-^(0~RH%MDRJ-]SL5mę1N=}p$r$@BӧQ,0~VXe͞EWmݾMYݨOʥYkp FXbƍvYU-MI`CdHp3LUɭ][쒐i}t?CY!J> 9Mx]tխ}];'n\"`}zݿ'J2D'/@$@30;<O)պ:8:C?AGzp D_1EFo1G9qG2H!|G"D2I%d"#2J)'2K-䒱+l21`L24L5d/$,S1%S9O?M@L< ρ MSATKA#ݎщMNF-SJ?uICu9/t:sOM_=TYgVB[E3\wiSSa5Xa_uXRӊ|uQD65dEWg[oףƘMl\uUqepM \ͅ^{{^}w|8`w`FȂfaA\a'ؽ+8cgxc?C&d;9eWkd_9\fYfw8ga&耇6:iEziiT:k?ֺkkn2lF;Hfv;n={noVn7'7YC]V[rY7=PZm3muzeMDzj`ۛ[=y=hI0"P@/u_ݕ#?J+51U#ݳՑWuwڼ@z 6$c'Po|YTcE8Qe\G -hc #3 Ґ}IHl9dd$'st; :^m|hBͤ T vt#ꄖUcKYu* 4kJ7eZ/eUS[rQILw o*"LMT.А&jєʯ'Ikn֪'3k^_ןhCzXְElbX6ֱld%;YVֲlf5YvֳmhE;ZҖִEmjUZֵֶmle;[ֶmnu[ַnp;\I [Oz<\ZF՞tH]zTYͅt]Ŗ#lUt״NwTy< S޽.}WVM/L`ep%s7]5{#a;ўw]Fogs@*\ȰÇ#JHŋ3jȱǏ CIɓ(S\IR@0cʜI͛8sɳϟ0]JѣH*]ʴӧ3JիXjʵ+KSKٳhӪu6ڷpʝK]` ˷߿lkÈ+^8-a#KLe!_̹Ϝ3kMӨ͊6װcc+T۸sx-XuУK ӳk=iO>(ӫ_Ͼ˟OϿ(h& 6F(Vhf P |((8% 0h#|+朇*.鹒騷q.7*չ);'.! 5 9WW}Ӕ_2}oeuؾEi?.~ Y VOG>%i{<RFY-$)g@x eD7AAnr#Pt2T0sLj0` 5Û` Y =@.00q' @@D<PP@*F\@B0.$& ,2 !CfS{D#x=I4HB @K2L(-Q5&O&1!"Ȉ2RHT2 L(?Re|$9I$*R #12JYF %!pɎ Y=i6~Ɍf 򙰔6U),%rK@se7a$L<*ds%3My3;JYNx %L=N)gB' AKND hjf>[R1E1Z¤/a<Ӗe57ӢS50A;WtP#HTTB*YʂĩX k𖩓p^UZB͓P;Z>K>+]+\fOZ^AКW6m= ^BZ6[v +^HCKųlfa2U,MZ|-mXCKzU5 o92E6ȝj[&cFl ew[u-w{Ry': -'9hf{{nՏ⥯~Kزڒ;n,Q|<B?`:zaTkZdObrjg, Ë=nH cӘ/vkKٱrJCr_J2d&he"IKL>YQEe0_v>Is=:NkafFu01/IKYXFNrgVф;9kzVK>[Yhq}Tp:mf Yi.4oN:íMG % oi,5؅ }b1- b6g5WijU2oM|X/ r,`DR74 룛o5Qo~g yyίlȈD+ȊO+$AhՃPz8$pP$XgՆ̘;u@X(MP8"߈L5hKaF+Q%cMmȋ.P% 5Hh%A.[Њ<`Ő2X @3Y04 $@*@Gpu#I$!Q0 AP@;𑒁Gw:Xq@;@BRTw iU \@q 7z 1ZAbǕu顖Viw.!uR:ƎؗMw19g[ ]IvB AQ rN!0fa`FGp:i_!nawd2G 24~:yS/V8HK9flVf֩ɈWga6gVgI7ם8Vٜ#X}Uj . mSl9ٞՉjj`!֘z`Pb&HY Q@`i`Р 9Y0(P-;=(c1JHCw78HTp=:DpXc+BpC.BɔJ*Xd)UZʣ^6:rDHcZJ: 1wi IG%q=Ybz\sDR`gZ{ʧV#s*?ǒe_EL@a:a 9`:(A[j3gtڨ%J\fojz2:<NJEtӬN3PMCj*í+|:z3⺤95=:?S=Z%:;ǫ&8ڣ's/;<,p^;;yx80+nG-pA+; ]ᚂxK$""y2ܛ "rVHz%'EfE軧~nJjgb鰧-^X7͐R]K^{З.EGD-fNRH$y$ޅ1Z'Hn#4( ^JT4C01+ѮMH䉊#IE#@H61Z|E[d5?5/,5߶N6[:`O!$q6^/+4ުL (*#k!oe?o.%ucG[5߆<7~Sk%6YFJL_c,="2f .ވ Ϙ Kgr{g}OKG4BQD-^ĘQF=~RH%MDRe"\SL5Q $h&sK6ETRM>^Śu$Q*3hLjEVZmݾPś7jYdϖX`… V? &X`dΝ=Zfѥ?Wys4[lڵ;ou\𸸉G\rw]tխ_vݽX{x͟Gxݿ;{ǟ3}0@D0ATA=#B /lnB 7C?CG$ĴB41EWd1_1F?BqFoısGG!$Ҿ D2I%;rI'R&J+cJ-䒰,3L1rL3DӦ2dM7AZM9836ԳO?OA}2PBEGCeu4RIItRK/RL7AMQ NG%OM 5RWeSKVg*YGZw)]ጵWaR+DWbeլL"fv-e/b U[([sU\L`a uхw#2!^{iޅrŷ_I7!~%NVZf8"n8beJm'xapUE8c#G.8dIF_/Nx%eg6UiSEιnw>gZ桏ӘEc6OzWκV6kGtmF(̕m^n[RλDK`'4-#qqh!4C 3-| D;Wm!5L$vF/"$](2 m3(z% 5؀*`w썯}@/Ȭ_G)`WHxnF)D}9BPԴ*c& TfH D7x/HpR!1A,y#Y_(cL! 6_uf1V0_A"j7$&aEBkOX%LRq%fcgF'MoTQ8G:юwcG>яd 9HBҐDd"HF6ґd$%9IJVҒd&5INvғe(E9JRҔDe*UJVҕe,e9KZҖe.uK^җf09LbӘDf2Lf6әτf49MjVӚf6Mnvӛg89NrӜDg:չNvӝg<9OzsL |O{̧Q\Ar9(/> yh~5G9' cH#p-]J1хTh"Ӑ , )WN%(Q:t,]JJ^ЀUm0U[% UUխok\:Wծwk^Wկl`;XְElbX6ֱld%;YVֲlf5Yv67q AhUKFJe /7vlWls;[6"n f PKvm.roE2ѕ.q[+uø\񆶶5s!,22'(x V"#'"'"''x!( '(!1'('('('"G '(@@@1"V( ]^ k,,~ x ww3%T*!(2;~ ***KKFv')7)vD[ ')m uhG CZE]C[}((A ')n m ~ vA  x #|m | S)E\| >Taa  ɑD\?# T)((>$S A( } 08ew? AH,&$D\G A@aB#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIƇذB u.iѣH*]ʴӧPJJfO;RPUÊKٳhӪ])ל;+J7m˷߿ >y'V5l]ƃ#KL˘3T V^uvLӨS^mR1w۸s)װG; ȓ+_t[>zسkVs @0* AٻϽ(DWh 7P<`z :@zUhf`F !A(@ P)j0(#Z!B4"ŧ@ 9"|+3iH&R$#F5&aP @V29\*`_D@Rgex9"< d-(xg}g 韝-袌6ZYQ 8aR觠*^B^!EG!뇳7ꭸ檫RW^k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH' iއ49Pqxzt) >( dDux⩐#*)dtluےNf!i[-}7E5~pjYxpYKLK".gys|& ށ-wpnV ;Dg~_.ƥ{) K/ʃm"ܙ .(ЏH%?:*ZnMs~R,vkcuGB&v%@m^$B P^+C`c')K}.|Lmֶ ;J,+p<t&ݮ&/,oO\,OI{)mo=޶}Hp WR\9d:Iޔywcpʼ\7Ɔ?&s1B ӅH%q"dW؂ow~btMTUz~}Fˆ S_Mf6hfK}r)&5QQ$b7[{hRm(dHO}Xܗ8Drpx15~PՋ渍u瑍x( ȉ\wx帏XEH 9P:XyxgIz؄QHHW7֊~ݨl(-Nר(SOԋ)iv1o80m(,E'9Ȓ@YTd?X3YE䨌LS[AVU /X[)kaIVs&eS7`1(31)tvI#@y)}uy F0FƷa،Yy;ݨy+љi峒`V,Hpk*Tӓ1IwiXИq#4`=O 8a hQ"<҇(c%ZixXv$ `4Tai8=O]Al3)P$#]x;''KD~)4Оr HI$ƒH888ٞ4d@f@+*i_)z s4(@$# Sf4 Iv!*24pY x$* qS$TD o~)q(Bvue5ב<ud?)p>`K@ $zbt&Q J)8Qx%q3n2Аm)z.רnmZ;s< AJ!ju=4sW39'G? JA4ɨ1B4x2;e􆓪B.tP7ʪ:vCe'_1~,1y:w2i7đؚV*=TyVଝzj٧z.8,Q1@{0 ,FA;y],>kGl; K9*;m7MA1>P93K,ˮگ@+x8kTF3? fl<RK)vmӣ4Dk&K7b۱EF?Juѩ=pEs۶g:wktJS;UE=ʶSq[uSQIeaL)&ydM+1`źkA54E,g:a1Uk1YiCJ΂[S Tp[9xs"Z˂UśYa8D'XKՋ_ڻjх8ԟBk˿.e29yX%#:ݹ2ok`2Ac$6;7"+^ ,4ќG#e0z它>#at\cSk!Zٵ2DE<r>Y%3ɐ,WFV%ٲ{iյ`ZL?,UxLX\ukFLS,Ȥ`- ɘ?LO+˧at$xlFجG˪up?|ʑ5?E|Ǭ<@|Bu,@A+TT\<r]e]w]\ ~s\lΌgKMk~j[-i^Xv #^`m qk/^+xHSn`euad]\2YD^r9|I\LRM'$tFfoV}E܎flV98nDeuN\j6Z,hp^A\HdzF.I ^@x1綵.*<:g/ƖD-Y-XbPJގεF귪9ٵݵ0[lqg~02Ɠ3PpN0:S^wCt"j@/A:w# loރQ)-=2Xʑ]?.!)!m%+3F0grhyk$ >/<}o* uᎥw:KƦOZnc-cwtr4-_0/SQDT-lT!`^aR]}da]df=YZp JrS%}v@@ DPB>QD-^ĘQF@@(T8A $@ @&N|rTPEETRM>aTU^sA,speA2!ǐ#=9\uśW^PXƷm DlځqC~t\xdʕ-_ƜY3п=-KAfW[lڵm&n]l DXDę]tխK}rG.@v͟GO[wzݿ_ǟ_~/@$@@dA+A'B /p 3C?Ѽ C$DOD1SdE_qcFoDqFwG G!$HD2I%.H&2J)rrJ+2KԲK/K0$L"43M5lM6߄3N ݔN; Nb i+o.dD~S+Tj'XR OH8cqZ;PB:<x$!:윣ja_GZf>};nѷfܺ;ѿ;pYyЄu埇~am|A WGM}}W~- wѯ>CgPlD`*7 :}sܴ* ZP| VY@EЃ!冄| \w1!. 9zшD&6щOb8E*VъWbc6jE2>[)L5UF: niC~ӘAcc 6# Jdr'd|F1J+ 5,f`a[$E9ērd" ,mcM3(eJ [KcB0BҗO".QԨ5kKf*n)& Ȅ,_sM$o79NrӜDg:չNvӝg<9OzӞg>O~ӟh@:PԠEhBP6ԡhD%:QVԢhF5QvԣiHE:RԤ'EiJURTM4"2WJi"SQMǟ.-2&C.^qOͥS,5pJAզU L45&OyJG̫!@JdcԵUկ%II6M%TB21d z!*W 4Ĥ9ج,T9p6EmjUZֵֶmle;[ֶmnu̷&-F&@M}]p/*B%W*Bn!fpaŮ;~!!*]Rz;H\UzK |ؙ/z]nͮ{`7p%:[<_Y; 0K]nvw{w|?xG|x7|%?yW +lqcj&lYw{۴.-`]Kcp#:YonM57ʈ2'?V׵5kq w,Tasg.x/e`7A\uJ8$ !,bW22   # ( 7 V곴^#- %x k1XaB :<8@DT bÇ;by#Ƀ4!-:`C m:TP`K,pЧE*c`p @ Nႀ$v<@ENd@@ڏ-( !6 !,HW&22  '(x!('V x   '('"'"~" * Z' f~'ɷ!(#Z!1" #~' '" H\Ȱ Jt1ċ+bE=&9QH =0`J(XQ/BG| .XL8@ 9! L ԙ0XXU@(fB3P0pҵЂQ,xc͢.ˁfQc.ȚhLTd A`U֊AVlZ@ t A r 'B@M!~&L1@C !,G` 22   & ,r#~ *G"곴* ,#Z 0&,,r,#~'  qhh!P`"(v8a4xʊ(BP8H$t xӠ= :@Ei Vr дC J  p2P0F -!,ug22,,''gd$$fe,,&&&++,@@@@@, ,~&,--***&,w Y&aa,& OO5P-,&Y wI)m { }~ r,~ +?w!y!&r'\n ,-vR* H),rm u| 7)((tw (('(&^v| vy T)=$m &\W'_|m$G j ']fD(| hu!'(l Z''_ {**lE)#Zw!S5Wy!"#} r&UnH#~'vL%y 0GH*\ȰÇ#JHŋ3jȱǏ ɓ(S\ɲ˗0cʜI͛(Gɳϟ@ JѣHgLʴӧP6\*իOwbʵׯuKYZϪ]˶-Mn]vݻxߣu L*ˆ;VǐmLDƖ3k|q2瘇?7,iѤOhְc~-;%?7ͻ[ھ?.Ynȓ_\c2uCNݵ=c=W_O9_Ϟ}aW(H(`zzNt 6H8^  Beт8v(B]x⊰,"1ș nhcA3i8H䑙X"?>W$P>dA8Qfה9ZxZ9XTzI$b]2飓X)gYlh2Ωg[piy)(:)o&砌:&h.WhչㅋV)Q}B~j*T v ^Nzzߣn֨X> ,Nرm&JI_MHY;1-Zmdkֺn ~{o:ஈ<*T7\޼ +b;ܯ+0w{{",2CL.B1.aO&ԣ>hGi"(]YHxQt42i:u MT>U);taQ)KWS5a(M4{mm[.V]nN'5]#bGdߜ? p,!2c\Mx/!e3gW-axdUW=^{;ܓ=q ݫe)@<#>;.O_t?3qC['$wv|teGu}w{ Wr8~ X^Dz]C6` sHd$Gt i1h烈rwg2 {)Hm58|'78MQ͗iR Ƃ[!z,vI؁5]dfHQhU4j`؅b8Nswq@(dwwU|eqoVty`xOndp~`;hz則ȉ8(n@evmcȊcmsN_\h(j8z/TPl(H74|8) (ahFŅh_x&0甆SVabHp(vc鸇n%\ qF؏hH QA#AX ` 8rG'Hq[9ȑk(dp{u8q31e$Di[RvUɧF90:sƱ* Yjǩ }+ɨ>dAZ(qZ!DvzXIdzکڬڮ1ezcdڭH4!kR'=ڪ誫JWږ2 JYkS. {DQðC,2!*+(;ۊL/[Z:!+JpН5uzjl*S>W,;9K5GGK71 }cA4u V*k4pu~#sWk[/z%AztxWx⩷B8$wkMw|||TBgx{+=C|K{G'%S X}*MR(n ۷Z]/ຯcEK}[<++ ZO|˶l kvKz`i8CC^cK*[!J%Ѿ-8L>@1Bը UW0 [6/ ̛H!'/,e{9f+\3L/)3cd5\É* ,+aÇ -HPcֺQ+KU"[IѣqV#1G1e*'"ld)%8%"`j#nLFZ"LuŊ!`#Cg|,o5bȇZL3FyB0bp_a"%û#(<w 5D!ʡ<<0 * \QY;$s|"<(,&'B;Xg|5\,|@#qA1oϐ9V#-m #b|%O1?`V0L$jџ"=l.mҹ_*=XHRD&]@@L(=5V-AML-`WP#ͽM%Kx8Ճ!V K;;~d^抁h~SG7!y%狎ڣVGE2V僡jy."Q/~rHV 奮~wNQ.^Nθ+qJ.V؈/ѫaX}PK-29x塮B@Ѧ0p1zNAm!PzyN,bt2@1djM|:?L1 v gza/ ][mqEʹ"Qqoy~חOa]qyywj?r#;ߴ_Oġ;!u/!yBP/ @wN 2~"O@@DPB >QD-^ĘQ5~Pǐ%/dJ-]V$0@ʅlęSgN)wTP{,sdRG `UjK,H֩]nXe6tzRV.V кU\L"W`0<(ܒmbfLryc=[jVM@,1ӭ&`!f׵n&0b#k7o܏?/\9tba웼K^;@sҭ/7^zzg9ӳ}۹Ӯ->泭3Kps;J7[AbB,"511M@}o2 q@HECT<cqF.F5T&&kC6 TTQO3:HzS4=M4`D3S@)qOguG_P.UH@ZRLTU-`U3b=Yo1 eog!Z]+nw"_rxTƲ"cE!ʪQ2W!K9#ɋX"v7\+cQvXeF.e|+/]{X. /(2LYE9;b7Teʪ϶i^Wl?XѦIb;GuSYlZ*;h{Ϳ:)^NlR͔;_;ڛ/˻4x^›U[s N<=JbXW}d7c[-;,sqq$~nv>eԳ[۹>[]{nnW{zɶtrz1~Sw[oZn{3?Oa^HVO=[譏._S&Hf \!0dľӠ ʑ "?!칡Wb2#(CPԟQ2;+G͓s@PdD*5/qT'E+я"M F-jRt*u H4RX:4Q8^)NT0~ӳpT(:?Ԧ!hRճ9(XmU.J 5uHF5Ϧ叺V&^/% 븩&V*hTΩ-QA4-[&rao#[v% ltCVhK?=.: :+znpZTZgح-Vvag]kM @u^w gɛ($]y^$(*lc ^3HpN  x9|o]Nӿ*^h d%4@ : `@,:dIKZ3B,eђ/ Ѐr-v01e) W2I<0{ya&ILnƓ[TapPEdVѱ@,Y'md%uiOO'Mu3yBj7j&K-YvfIemg=+Az'oHW{.Q'w>+ <Yz пE #: ೒dIlc >\ A$0%uA -@D-A?ȻA|A"ĉ(0±“.hB0+ t-B/ $@ñH CB7S98@.Ĉ B$2$30CBSD[F|@!\]= CD t2.cd ZkŜXE Ejn4FƯ r<3sFqHE$ld aG>Gx<É[l GQtG`G tE2LjF5AlHxȮHX{Dz|gXHȩȢCIB؈C|E0L4D~bœ !LG?tĠ 4ʒ"Id?̔yʪ4JP+ɦEZʯ̙K <9GLKLuKɸEJ$̥=K ̹P˄ĮLK>YL@Ȣ|LJ{͵JɄsȼƼ\͜5C̓ؼӼ,ۄMp4LńMܫj#E͹K\ MDKξ˾MÐɒN8C섗)OO͜ˡ`Oɠi4 4Nu5ld |P4P ]LϼKQ|Mп\lQяPѡP %QP$P$:Q#mRTL5 KOJ/Uܢ R7iORҊ(h#4ЋlS%eN:+R,}S#ӯTS$ @= !IL D!OԂSmQ8%T';JTTEM{΋SLD7SUYa(d%LG}T[\ZTq ֽ`HTu+DUUY}]UU29=ֈ0geIZ!meEԧpMfupUPUru2˷7\R5Uw؀TW46˶!sXnO2ɰVjeWM 9X ʹb2=1PvXDTXYH`X p5X3YRlVtٔ=YX#ŕGW"4LkZ9ee֠թUYګUN{e9YYZoE7ן9Wu5H54Ja Y٪-TGYcOkMȪہض-yڼ-DT   Z{7z%Յx[Nڬ[M)-X=۟mȕ=]-J Z1J[L,L I]ҥRCMmׅ>Mݲݿ^ 5]mI}"^=U]]۝\Km߀O]>]eY_?]_EV-Y*5Bȿ@[ +|_!NeT' 3f.XLDxX_a~EWboPx | V ]%f9*։-7m _(^*(c5UdQJԾ=Ob$1cV '&zd;FUC\D}_XS%DhdMO06FH dF&B6e8fKPWV?vҝDEHHe]d96HRYe-<`cNcd^Hje( VvBfjN>YZFIdbNoR`!QVr\Ve)l9!Z:d=vxgfo%$^Da|FDg 'NM_#ŌonM&vTFM$?hfh1hb.Frw͔h.#hCaLjk'!Sj\vjqVTeTov5޼k.v~xT C4n ȂL>dnlhlʾm~]lykmnf*lӞFnl&nk\6`tmyl>lj>o.oz^poێ~olooD&cgvp9poږpn w17kwp9 ipm0fcqW OoqNqD3ror.jq+)gEpDR-c.*7N _]3wLX#Q2b8s"Oss8 ps(G$E% gDqGOnѣtt;$WB7nQ|\~J?zqYyzzyv_rzuzzz/rx?{Izzu0Ov^ zw;2x|uďy_{'~|ȿwny|Augwçt?Of7(vc}MgۧWշ֧}}ɟ{/7rIroJsz~_~K'`~g?' _>sWڿ}G,h „ 2l!Ĉ'Rh"ƌ7r0ǂ C,iȓ)Ol2ʐ1_Ҭi&Μ:w8ϞBI:(RE3.M)ԨR&m*լ^Dł-k,ڴ6ɆUkm[r¥;.޼zkoTJfĊ3yX#C얲H˚7s$fC$-iOnzկK=5lۺw:7{I8Ɖ*7 PáS ;OQtJ9~o=|eNraG *} nL^ZiY89!!6r(`"]H Ȑw3xc}8A!1.'$m!$(I%+:!g`]> d%^i_7fiy&ըf~%Ffy8'ygz _tJ攃*^}gdo.:^^ȧRiv虚r:jsx)ڑ*ri:kp:hҺk j:i IJ,Ckq*,={2X-+ڎgV&[ю溛cvm^@| o"k'w/`@T`[l"a۰[hЀ r+걕._3)$1.r>-z &o AW\ppr nyuIL5-0FKZMs30 zziq31 Hz'>Yol^pqM4ڌzx9m;؄,zWǭ]yuF<<?ӡ<4=5| $N=}/_>>G|_SneO{_U#&y g@"P* 8=pJ܃ uyg&!xHBOLQ !0 q8C y0!HDP~ 1aS$$ЇT vMplQ )@.45J#BbKE(qX|G#+^# mCDnUƘ&񉏼d$Ո3ђ4d&鈢Ej|tR #gK>֋F|e+JZP@ĥ-X')H^^1Ǵc.Uf6ӓ1M.Zt.MBzݔ&89bS?9vp媖Nzv$'" (@@޳ħBpNT(jPF ю (EQ*C4*KW}4d}eIIMִzAi cJH8*ԨC*NTPөQ($ԡJժԋIQSUԫkSU^լgjV'YխjU5V>ȮGݫXVEg_*.`XIbqXjM<7YզqhG^vJIjU lYRk$mvKO `[I׾ָ՝rIb2 Zw!kk&3q.wVqy&8!j2Y ioh෷w@  [}o^Xw(@0']qj +H P{ m*<t H)#~'vwAu 65?#H*\ȰÇ#JHŋ3jȱǏ CIɓ(BX@$(p Sfʛ8sɳϟ@ JQ/Y@a20u 5ѫXjʵׯ`Ê} -8H@Z3ʝKݻxݛpjYhx-È+^̸"@ a3ǠCMLV=aLߞM۸sw,uoº Nq>УKNcfbmfOӫ_Ͼ˟Ot ߁&]0 ` Vh  (bD"R8,bn衋4hc2>k9HU8^lC;bNދo/#/8/*|+pXj0W(q"F <+|% %rLodbs#<\7)n EsG@7m?S 5 $-moB k?-Xם + ~t3u܄%^؃7ϐGn Un9 e3磇Υ//$}O찓76e;з& ;CǷ o{w7>ug}A `i/?6/Pݾ NJR'Ǻ9+@# 'z7na$$DIxA w*%8"BL`x@JI(BDD! BYR!P|*qY3 #D1$#[8A%q@=ƊPD@jB?.~\#ݸI* A!YDϏĠT3EN}AxE.UCFSdAXW1\`-m R|d1i>KBq&1ǣ02(LrIEr屟kK A3)%@ p )|a"M!l-yy0c%iӑsAENsTt02ӡ'BY@bs_ a$Fwш&)Bˑ2qDcj 9:]:ѕfsjF'kø&qyvt4viQس[@`,G*fuԯFӨ6U)jqa|W^ !\3^ծѳ"CpMa Y\]BښٞyPz ULa @B8biR2m )u,RzA8/[$p*1H_ HKfhmc(4jE*v] 0ͨZ 9;_ކ,tgi6nq{P =AO ]w4WT5n\X@G /DnL -k3<9Ѿ-rݻĤ-""< 8ṫ%< ڌ>*Z_nqv?+BrG-7nEkO4wo:7\'6ƜmzIΎC[=yIJ|K^.wнVc#]޸R8N}rEf4y]|]_Gnv%mo,pMxH8O֗>s"uPkJ[sB|$ Y FSkwQڄ/V}*s뛷=ctt>~}< |RFv5R{kC!Lf (Ӂ{|Bw9YtGZ h2x%0}@~}U )Eg&=iG¢AK2X8,f-c.8au"@@a iQt4Y#0@@'!$d&%Bd&X)y!`crs> 5“?X%D73)"II6^'pbI: DUPqRg-,GQ*'MpZW:kZMʦ]ȟo$J媷!P:ڄwsPJ'yjj!zoj .Rbậɬw*ڮu튮a"lzpz&a&6A$J[*F2** ;"抝#KL7AE""-۱=²+BN2&k%;("6F#+@C۳?® [H+8k#PibhBҔqn 0$R_+M;$Nǵ[]VS{[!nV%^{a yi$vlKs;zc7_gZס{!ΖR~t#;",։Ժr+e[#} ak#k$K<۹k\]#[65b_{{Aw!+ rP\+ 4;+Nȶ[?#V>="tDһ+'׸;b<;[ Nf  , ܫ+<!"W2O5Kn%<74' m7_-L$K&A<E +\K|wo%պSUW,8ilmC%c^Q,I8Kʵ?BL]e `@tk<ȻxPZ`]?mpm#(/"=2WsؚՔ@Ҵ1kU}ϡM|1fj&]3 Q^-ndM2Z*O}mQ#rۜ׉*}zCKb ",2|A{/ٲ:x*M]=}gYO!#<qߠ152ܕ (ڝ-ՉB[!N4ܤ\<-qs YQMK16<R0M~(ѵ*EhXA[D+0d]I qRniS2]E]*KWgcT~;rZeNl}q]櫂4\nq:o/uNA> >QA =>n:M".꫎ a$ˆxa)? (8n쩎C:1ǎd^cs>@hN(nA At~ݹ5(gb^^~~N]0A >8w(_Ҍ%؞7n~B=T];`wVx(_38`5߯#?GN˖}$u($*8_aw=~Fa9\[_ ظS!aTg_b/-q]4jZ^x,B^Vw_LuY*:GjJ/2؉7A利OA nv*y}~pނ8{"KOSRa~ vizƬ;??'q|ݟoQĉ( pQF=. `LИqJ-]SL*i1M&$ @ sE:SD6>ZsLLUV]N%ObTZ8 005bSlv${SYX0jJ^)gP-|S.˝=fY0;hifRnZ͜g aY=7, @ʹp C\w-9-k1z'ql̢|>w?Ic/2bA|0@ W B*XХ?\B6DD1bkzz+. kq DzTƇ$ȆT\qG%C&I+)RAQ ТdH{dRF'(͆\C 66LK<1:"S.(݌IA<ςKn.TLȑF"("%"33IтNKQRWNTUZ3 -3T5e=TnXVG|ЌKتS+uUh%Pb*TC6ܧ0=VNûUZ+MZVDY\y_IU:EY%S_5`ewU a8=N܅Iލ?N}ma~wa=AL)^dwf}yfxc]5_R]ys֙Ԙn9TN=ikߣ Zh.9T8ޚiqJL2%6gC;.^:sPoœFFm\{q-]oq5ǙEkE"v3Qg LZaA =v@o}u9]mow 0Ƞ &_ W]Oigqn歗pP隴!JydH?m/# `7}A41:}Bw+^ ,~ģ! UNCQ<80qM!ݱw !$,:}Dg%v tЊ8ĕ&2D@8Bg47 |*0HZ ySH8U G8Qw#>yQVc5BD LiuMdIbUq!ITE,Z,0ۏ,HF29SFsHOBRLh:Tf8ib3#?pӝ7̈́Ssa1߹ˤ'B칸`QgBσ,'A)RoN1|3mQ3* S٦*M:ӅNtrh5ˤR1 %/i:qE(#64&S:տֵIiP*jâRk_VG}iQ@eEnoqK [&׺l)t16KLa떗&҅qEv[0yNN;_Yv]0GJ^`oDWo|%YN.^(aNpH=Xop•<̢ecnXbg< &^΁垯8:ȑETyՍ͆>?O>Y[>sutv_r3vhu3p;ѵ#D3dMj sO;ߣA0<#]80r70_zzwe%y ^^6S5=[u'E8HlpkO}j:{'OiZ?ϾEzĿcþTWepcԐ?cO 45@h?3@VC+s@nٽ <l1+ @&@M@-ltT DS@A!TA$#D$T%d&*pŊ0(+,-./01$243D4T5d6t789 %<$%:þ;$ DB+z)R#Fd#CiJ!b!  )Z H}r!QR2E!EV' Er[t'L\qP_&L)$c,&L!QEdhijklmnopq_K$tqSw4 <8xuػzG!9`GǁylGD~2|LȆGytȉs#ȌȍȎȏɐɑ$ɒ4ɓDɔTɕdɖtɗɘəɚɛɜɝɞɟʠʡ$ʢ4ʣDʤTʥdʦtʧʨʩʪʫʬʭʮʯtB38$˲4˳D˴T˵d˶t˷˸˹˺˻˼˽˾˿$4DTdtDŽȔɤʴ7H-tG}+BLM34;Hl6<{TM9͑ܤwMߌC6Nv\64dt$ DC 2g-Dła(XNtu W6!`VhoӕU^ 6Y)qa(Bߑh+(##\3樣-@ޏ>(Hfg$]K&5dPVilR֕\vYٖZRdF&``"iU眂@-PxVHgfy6x6Z $$(AXrJ*`v)a:*f:P Zj됢RW) x[kY,K*6u+X} n䦫nBjfk;z.b+rVCy&p  0hWC l%,k),3y#OV8si;ss=D?7lA4GǖPFmSS]\i_w-bMhu6[etuiw׭s{ހmn^k6S7̋7.w]}9 cd%栗^缉nۥe޺.َ"H <'O3:ߞЯxWzӮq;Nuzα3'toc;@J?`Z' dB ؏p" 8oނH *!9QR2pB},0|!ECN!eTЇbp8,k5[ڒjUC$2a7%pbƽqd,4mlDcF7t8<-@ rc+dH)Ґ%l9JJP\d$/4<6Y&!P:ғ)JRr{*_VVrW,9\ /eKs3:12)lhJY P6im̚5pj9ӅNrs, yS,幣|SEdU@v@΄JE2Cc"j-t((6/QVq(h??- pY(&R4KLURmh2i0m ե-#&QoӠ=N-߁es"CX܂$`5r % om+4"1\E@P_u5Wγ 'E #Eb+,vqT**VHL* [,䗾#A\0+0q\V9D0mekcD`S3ID r.Rg;Cy--S mhqT}U2ad1 tWxx`=x,S.Ԣcey2nr]mƚlFG˞&-_͟25KdEey5flC6>Z֮!ku)5?[Ʒi֚ mh{a;)Fw!..T ?i 2qi98ђ\m]q@hfS؉v 8HrR\9i@sK=Ώ-pÿ,N<5_i3flZ+2"=3;嬨uT{> ϰP<}򓾲]Πjvً<] 2;_Qï}[ྦྷ}!9W=ݼPta$>nRC 2{n~vn\=>) |ϋ?g^׼hsN=ߏ1~j"yy~44z$ wʦ񷀤q6{@"{'"ga'$]'mNE|h)9T6I#.`uyRI8x"0_sGQMg8)Sוi-2SȊ2xv8{W)0x.^W<ؓuɘ$1/!Y #(ؘiI)3|)gI Aa.-#3ف V4?S[ᓁ1 PEg)؛3 qKWhI8aP× 1VT牞<` ~z3763:pUz6) ڠa:PTDIiω.2jSzJ !..@6~0:2z&&`n0:bc@%a&p 8k:sA20iH8K[:g`4*#{y}Ajj@W8L*hi3:7ӗrj9Ɏ7IZ>:Iʂ6;}*C1J5 d𤶪ȎX:.J:ya #wiz`秤ӧǩ!>&.qyCl70s1qxy~I#:zL ;@ Y,!ي; ;K;}J`ڤi};O!hzVSt2zPHh4ɨ/z8VV>cI-YQXptN6ܘȌ)QYˎZV7ѧ9#x@bSJClK.Y$*’3,\ueGr`H4rzE[`!P>e!!*$R E/)U}3r{Y $A)D?ep3 p|8^9 ʡ@ ?iP+˛9ѷ;v@ZL5ݑk//bbݪs -{*T8 E/}&[8;;ރ+[3-˓hv9lt8&;-}"j!chlܿK#a<.,\90NB'n%l0 V<0q^PΩc.{seSG/o40MJ<, Wyc.̕tVN%UiQN<V8YtI2/LiX(z}3umr`y7_G[48,G1M+=8Qr;=ӗK -tQMM2ǜ$H>{ݯmh4RM8t5]]UNHb-S^lJW^SkO K^=/ȈT }AkSpIJ&Z>H/Ƀ$n&/4@G:ЧCmpoՒD@ e傾lVwl޶-ףGaP~rU^>txg=Any^X)J>xnus#@^=Þ|wꛝ!ƾ=]XЫeU  {16(2>Zo6nhj +QgC6yIlOT?V4zGS9=}?6SiWCnj_;O4縣QnMmQhHw1 @@9_?o= _:Nhﭏ om OK.x?p롔 y@  DPB hBAC-^Xpd8AMDRJ  ( @,m^N=}TPEMhfT>E1ƎGUIȤ5%b͞EVZ riW, HW@@L'${XbƍHĄǕWl޻ <{jY4B/c `qѭ]}VdmݰW5+-[p bÅ Ɲ?`&ᙪW#]^P0~]xT|I3t Sf֬> @dm&F@΄"փfOC[+ ?$ ˵KdſE;qw){ҬV 2I%wBrI' 7I+G,T S$A u5TLDPH{,)okrRM tS%37$H5C qTTSUGcmQM,UZwtV^UFWc,X*%WU6Ơ:PtY_VmmYa\s*\ۮ]SU7޿ҕw4qԎz ^~c`6X{}߄6Sa xl&pbBxnU<=&KVLڽQcIemofay zcFECvdi+1: {@!p7@MMxK(x;yE+` p:dp`,hIRn-"Fa1W/(NmZB:iXTQ}2TMQzNu%O2Zϭf@]}'X5#b5kz֢lsk7Vn]1<$}͗]+u%b V͕`XʊE e1ۨn!X,4Kц65mJZoIemkQێ–9r{[얖@}۹TÅh;IZ]sQ(]F nu\蒋Y^/)yY1!$"H _O L$BE؄- Hpxƻw[Wvc` /0/$^ELeZȼẏAl?f, Yk#BC~ґgd$cr&RYʟ2D|lYrLLP/Y6cg<2k&f8sŗgvY4}sH zj&E'Z))NIГFjhLcάtiZA1uR}~ږfW=Y`vlmU]׻{k`%u)l2[CK=9{ӦQlg;~&]mkY>Ikmtu;=w$[w}ﺖ4u\fq Ձ ϴpGEx#*>7\x:3zd9Bqݡ<*w˵_}b9TKLH--ƼiNt')v'pNBJ .om>DұuXU v v /lWN30]']|\a_/kEN9S )8<`&#~Jyjm:*L.7 Ia=OczYyy)gk3=#3;OcVr}OTi]6[?_Ʒ?qٮ,D:t@V5} @4 A4k3dhr|\4&D2A+ l$#İ$TBb&!)*b",Ĵ'/0CS9#kR-,É10s7|˻:Cʀ) 279;hR;Mj49C(lkiƣn oRq1X4Dt23BvDu+ydwG|G 47|Ȇǂ,DHU ȅLtH TȈD0kHȋ #Ȏ츏ȑ40CɔdI)ȗTAIjɚ%Iɝ\’I,ɠ$2ʣ,3 !ErJT8dtMiL,>\MTN|朲bNN:MD5NtO&1O\<'x9O sB€B w3f`0/X$%gdf@DHj]@B .%$@2seʪ]wUŢZ+ZU%23K\~ "ۿ,"_~,"_|ű,"c X4=,6ۄlM˽JlM˿۷.cߴJ0EV޹u}lmwnM+[8[VBԿ'4`^&g~G^Ͼv=Gɧ9/ӟ䥷2ȉiS_RH;=6f@u<>dW#Gt0fV;Azвʦ`/l4y k2={eo߻sv=o+φW|;iv (8*5 Nte;SD$;ǖM;k4f@5(c' a.~n=fzdRFEϠU_Q.RPZtn5 ecuTJ48zxUBx3k#V4SU?`L>}Mw]+Ή>O{玻n-[}_]zup ?4HUjYfN5q7ԎcM;{,#VbH<>i`PK6fV{jkS yQH3![Szd`@^3ZHw5/֏pЮ0^4{ko[n_|nǭ<םS˧.|O|;+7i2(84f{g}Ҁ{V[x5FM;CvVPI14[cg1qb#BwT H^iF9yq^6=]PtB,l*؇Jܰ&u?yorhˎCt;|57>_81H\lTH JV]uj ۡ׽igaHvUo[mLw q #]]LL 6Ezk PoN~c4]Pø5X Ye<~rM˽~ѶCq{o^)o~7|_VhBPZq(f]ɪUf@ oerjbfFv4ҭ^O+8Ӆ+G8:fzt3HfK줪zkCno,zꮱG[`@^ilv13S@Bl$~Bx;eʻzMſaػ8mAA=hu4UZ8V, 1':704v4By`- ՊcQMyأ/b=.:Uvf37Wks0lPӹC{i?#khf龒z=w"ϏE]gk> ›/KU%t3T#㴍+:.;Y*~e2pΚ?}6B]ԍeiO@Nd{rg #="_~,7]|ű,7-o-`ф\?[ ``qbXLEl K&b`Mw|g?MULwklՊLF@Gfu'd6񦳩guy^z>4#12r8"בO};ܧ;ZǾ-Wճڒ\!g`(ۿpީ_Øjtzt-Ҡe{ jپI6Зz 6ZUu|St*jŀ~C-+pJ:u:)WT+SK(>3y"/--X! IZ3ŹGL!7ƎfdHg3Ϊb`X-鮇JvGjC }nz{$#`s{(˰a֏})gU>/J\Cq_jM)v@`Ÿ\aE.BQ9P=$^[__[:֬Xۋ7ۯ95!xkE[025:yb=3鬎qEexԒe`iqY&3>땋ҸCBO=٪پ~;ۗk`V1 tafrɑpfjqp9ԦҮǡɡ=}rR"}e0H4RIzfSQy{ƾ "ہw7̐l?o!W+~>9$̕lMVd^~#b>&}`d{Xl=,6lMVdMb X4Seڵ뿯;vd)N pQ>_NeVx~{vcEQFˮǞ}iߵkW<$b|_U<5B2srEywmo.~8Ǟ/^QEWv3O9WOP_~7-c*[W.y}/2?}EQq%%d{alŃv^1Cܴg;1>kWEQ2g/;^d{gv›?wb8|/(2l=L?dl_=»~(ʸ2UluwОwm5^QՋloExcW^/_+O;tfEQqE~7ۧNXdktdJYץR;wG)Z}C {<]T=I)mCKqw$##6_3>'c9O7X^x~`Hc&q;j_E.,!@Sfݿm[:۷tZB+E >*h5fxpkwɲUl銠#WKQ~7єYKxN53c}n]^Y-?q7x-ExnE2lеNv>Wʲ^}u?ꡬ\_Gx7_ ߍ|u=-n T=՘U}hj+x>u+ٽ9 ~_(r7bgܚ`JpIK6u7h?GR ~[OtpC/}2ۗ^`!:ۏ^+e_^}5<++nI91s1Yaǎc{˗WfRR?WsCkyu`QE1` plK>$=:'XN9Ts!o~G{wN! `]8wܓj 1ܦ鬺^:6cBeIi{&V'ME)r cFKG) %^S"U/ ;)r{9$X9xaT#L헖bZOqǫ XW]ڟy镲^TW ۯ^qKT^2 tVS/GjwвakV:W9^FK{V;tdW={b]uZ{ wd1u֪cPA*ۇV)}yS~Hu>4㩱>F2|$R ihgig]1oSQ2l_~ۏ_Wys_4,egm~jfSmIѲ[Yl*E__9vXӑ퇢}T%fur6Rz2l*+(9U >AO08ulն^VvVGUMLK_Q =/G & FK5GHvO#S&hd@dl+/ʾ?3(WleλS,,1l_|ۙ}>d-W^yeI̊p_P-X̓Zn:Դ.:Ͱ' 6f 3t&Gr\mG54wL*A}MGұt`;Jr iuO~x_QEWf+ SWU'Nhtea$eh%٨qSbs0<蚕2HҵfcKi;'&Ύ#LMY<slLq;ҴzO^ScOU/u%^d4g6cCm)UVNn6uOڍZ׬~;m&cKigkJeĤcVٚXNIMU?Iױ5hh=L~k#XSf/kF^xEQe\ gdַW]yW5t>[髬^7JkI@5%ͦqLkVZoPkujq@ǑC:'&D wώ#I֔?]kW(_~ԅ7W;1e˽v#û/(2'yXƞlyUhtd02iuE^ )7ޢѬֹPPTkz7e,qlŸKе~gh6 ddkiH_ztF]'(,fMxD˜2sm[YC#%j>^QEWYbrz}~זcLW.ht]/RZ&:ZUfAP]oflޜ h5\}G>X6֌Y2~:fzmY729Y ^s^}IOݕ,>x3nm42ۯS/?{ˣEQF˭< k/.7=k6C~l"*M,/eGWEQVC}ٱ(}' idM6\l^?8Mo/Lӿl?OP7=|ʑG<;!w7ۧeꛫd'.}#wo_$l.xM=IJlke92l\yjS&.8TƍߡO2^bWOf)}xj2u;|ribe94緶VA֑X/!k͘UJz}Ch5tONȢsʗ]1,+?w_\us#,)t[եw}5oetVQ%ze[ cWWF$t}w^_sd94(?|e Y`_wߜ/f\w?)Cn'/ԗĹ".z fઞ.[7ԛkEޮ+Ǯ|-,U\/vmBSZGPhO::E[G>O\9VOKkpw."_~C9dd{߬}Mme46=ͬXH`3f0}O~kٰ :.rSql阢`CS e}]Y?$ЌFX(gyߚˑ_krXeGؒ[{gUTet@ӓnJ;7k;ڙdY^_Q7SL&o2lQ^ŏƞޝSXW7DWĹ2y7uwUfFrӟKײU:MNBPa?UP3w)U `-='ӿLUiA@er:ܓů!* `].?EV&eFlbzӒwsEzؽlɓE08jz̅j`| R,%q,~71I\ |~ah|!yZF#i_XdZ/}8xSZ9SZ=qpd~g&nF*eپd}~~\կ~K/}Ff W_OL7tՔ}+sLjzѻO+kxlWQ\/ScOW͛7Wͱ>`l̥3yjZue{EQTScOiTʯ;vhտhٙHvjuqKJ=^qd@9r] zk t7^ZVLL/a,iۯ)_U'_Q%۷%ƿo_e\y.c}[Ȩuɥt{0\UWnjљGjͮh$}.W}jfRδ2zfdZo*]׬'?麽(Пxj?ҫ^'N^}H1`&Y;\ٙ*01tՇ:5aԍ]ך5Zt/A;*4]}Ți+u.wVAՙև:%Φc9ӗxXydj}}%)!O ;ˉz7D{Lxn^>˱=z肛C}'&k5l_~s^ڿKsֳ}e=2g/]Ff/is/{9d$WME4e}}U>l0yd} e}|:w>qGS#,o˿˿|^~X~ii)L[W+[|sh}}ԋE*~v럈ݣ-[Ko+EߖqXTNClIe}աau"'/FX(SgK/E]3!7ѶLI;D4zSih .kвHw6 A 8G'OP-/ڶ2uwW tVQ߲Cߖ-In nwn g&g3'(pm~'cP nfH^TcFWŞstb:rB,Y~h 1ʬ}e.Rs;4ZI93\KfdĤv6M\/ժZWY 틿g?w={©Q 3xad|+Xl:5U멡]fL40_t-` i=ltLꭇR@4]y ~, @p={M<[:_DŽtT< Cz@ڨ1I/ֹqE;f&g3EOMxoxn`Ne& gxcv_xIپ:vGV*N?u,[fè u+wbL=N [sn?7`LrWQ0e$l=4+੹g{`C'jsVe0:f]ׄ{#Eo,w=~ `3vxS _=~O>@9eQԸ&u.L;7%Uy4ڎ`po[_u7mzgas{룟yC<p_X=׸n7l_|%~ߴiˮxj M1x~>[f;Ǡޝ?3HXt o^ǯwb{k]i]+-k]֕AGzz?); Љ# ;= -; gŖ[C:5k4o-9;t-8Γo}|gSi/${*PyZYEuY E-Z6-UfԁAgum \M*\ }uHi&䥉}p&EQU&gj ڟu,4qV*o \-HPizf$ g'qmGz`QO6doyycX7Gze\}]߽ۖmmO^Ot 9gw|hW{t{e{EQzg+y[WB UFEhGV^>rd'f^Q K#wn. UFe׮]> @p p17ۧeꛫd'~iOP{%_%qdO\]pWk7mz' tUORe[=(# EQf^޼38m ΓlϛcL.lέ+\}rޝ}4zUgJͲKY8|-ݤ(J,=rڵ+ΐ}FƷ‰l5]婳{<ӻ>ؚ2:׶Wߝ ҬpK)9[d{a~U{2n}:vxmv:_ TW1zlUQCZ8{628rʼnaC/eĕ1G}AQ6jYg}3t1?_=Dbn3f0}O~lǂEk.Rgig#1j/ŀ?|l uW|xi *ۇЦ08 `A8'T;iͪ17!*weK!՗=݃%ׇй(EYl1OSx1lJ&BMtCQ{ۿ5HKUgYgOLxi ou?|UffA:.-{7=ңswO>eǞ\hʤlHRnC iU:s(>yG;/Wt_ = Jqdp^u(Jsį+ _eP]xj0c3__|=ױhYEQֳLKKKe>f#olg{EQ6nYpvM{[knl(ʚl=L{~MmO=(er|8׬'?麽(̯_غJĮR<5B2 o^?3mťd{EQgqʔk~ .=0eWEgq>8&g3.q9N gx 1 #[h.%;+;\>uS/qnQ`xK8O~Νg>پ+'9iJ;CX7hONp^{lD⪞dF ҥ)s>9:k(x׍砷0Ӭ,;FsZ l}Vno1ͼdFU FL>d^MNgՙ^&giɟotqV[Izz `V›';Xv=8#60`{Jz9l'czuZM<6ܷ},#ylg>w*`z=50݌ F[& HeO><Ȯ Tp_Ƹԇ:Gg%=:M;=Fx3޶>?MzU_}uOYI8bONk@ӨdΓg9۟;ogx.Gnwвɘc(w 6پJi'ϭYO:g&<~梚~7=+teh3ތ l/bCP{eۋZ, ,8tv }5jga`D=+tehFΓg=_TtHfbQUeP04wvVZlq{ AggfJsd%Nql2]ue\-RrT)sSOYI-;{uzYOM$A;w eàB6Bۂ8)ܹzYaF6*۟Ŷmz LdWnگ- >[g=7=ܳ Lze<5ll\Fތ>}:Ͼ;z 62Γv]=Y:fϯU'|nzUb4#ڮ]g}. ΓlϛcL{qO(ߓ_e\ychtd4߶aJEI*Ce ]c]+ Տ30>~00o6tId{Ɛ9\?ҫ^0q}Е2FImիttVZ|xZ RK(ԍVn7o~7lϐl^aNG}ho{O/ыl?:0tVBw+f7ѝ+tH#G՚Qo-lRt F0 |}7ۇyWhLI>NrGM.cet]wO/#T;6Z0-МOһ;l?t>!Ii-MgZIQ-i:]sdЛ=z`k`K8@4ldhnp}p%oE#Ww *ךYo&֚6oY9 Qӹɬb'CЃldhr_ZZ&e3$& }W旦( &A24l^~&) u=]=\L`!@fox}q/~s(,Ȑl=@d{A249۟wSd{ C@=9dqd{ldh~Z= A2$@=!`ޕ0*!xx/o=pvE8 !@){1d{ Cg-*ߥ0O{~'x6$-cm Y| oF`>O)co^d/̞lldtd{`>*$$WuWl0k=s(FBѬ}He?t_]w7d{Y큍,RĮl,~ii)o7^4o}~6~Mod{`#K}+i5l_\|L}H;cw&ۏV&{\36޲iӛ"ZMlew,h]ղ֨5`^9𧥃Le{`:7}[~luoLͫ|.WwA3b<}[ƕ{,l,ɯr|}C~ +u|o|U)&F C87S; C]پJINo}gge–?0WBE4Suݾ2lW9VܜddtQ0훜JsxQ/tvY+YseQ[*pF^)lgŚ=0}HuH1u%*[΁/L!{XDHF&oFĞ({Ԟ[(66 >Y큅E 2;/wv61ܺl_U)s΁?B=;' MgZ]zJKǯ }=ɐd[:R탡x@|}ܾChrzkM?:=NI72Iw]lY^kLWh4B܄ss&އJ*x/hnxuޓw:p5F|9ldh=]=d$5 S</ d{ CX=e?=I24l_{`@}O>Ȑl=@j= A24ly1t_`A@W'd{ Cmd{ldh>~= A24l_(/d{ Cկ,}e{ldhn>ޘ Gy{=Yg{ߓ9E24l߷`@f%d{ C= Ȑl=@رplX=ydOGvn?F,̳Cܴʻ-;GX>zwo_݇CnĻe{ldh>8~?}n^rJ ͫ/,gGVBrǎ7Zߓ_]ү= A2>i?Нfң/d{ldh}y1 oZ4=d{ldh'=;?ßo˻?پߐX=hVz#,L}y`V^XT=Yex?:C`@f oZGlb #]>7= A24l?  Ȑl=@d{A2$@=!z ЃldHd{ Cyo(Ɠ d{ CEo=?ƻz3= A249OsOC=t}U~͎;v=S&dI2>>xgoLȒldhr֪z!sldhrܓ!'wA@&go Λ7d{6l?==ldHd{ C= Ȑl=@d{A2$@=d@nc d{ CRl71_iS\M!u*οx_`,м}P\_X=~=ɏ]>X=^owy{ldhپ Sj= A24l};ʏ,Ȑl=@{,? d{ldhN>(>c/ d{ CX=yeUo '>D4d{ldh>پV/#}q#w}SX=dxO 75 OOt?Mz= B24l?|{XP=!z :׷jߔ/d{ Cg0 OL`!@d{A24l_~l}?'d{ Cz];W,Ь}~4,%|#uVo5 = A24l_7緣lb !OE`!@d{A2$@=!z Ѓldh[9=lB ر֡;._p-=ZmZlB wo[C>xdף#զ:=<=䱇%} Zl\Xy-+~p,{My߼\X='o~tm_=x<ء?8t?<|\`@fz=;Vv>r,4v޲r#B#l‘ $>ao?C7?t[t@`!@fO;W>P+}ߑ"d{ CߺrGg/iyף>s:E$m?CeGvG_XD=fGv#_XL=9e#+]9ГǾQ#kCM|ۊlb 5?||?,~ d{ CsX=!z ЃldHd{ C= lt^l'A@\d{ C= d:x/d{ C4ߥCw}U_cǎs= Y uwo=2 K=u=f~8()$Zl?~ĉ= O?;rH= OyO`!@d{A2$@=!z ЃldHd{ C= Ȑl=@&gO` nuW(G,|}/1փЬB^WmX=]/WF½lB Ѓldh>پt_=uȗX=9e % __lB +۷WZe{ldh>پƼd{ldh>~{G,ܮ d{ CUoʗX=dG.=ldh^'X=Yg7n9B2= |}=O,М ЬB^WmX=]/WF½lB Ѓldh>پt_=uȗX=9e % __lB 'opn }m#_'d{ Csn?&HX=!z 'ۗ~˯̯ѯClB )e/,luX=eӿ} d{ Cܓ_$Ϸ?~_X=dX=~=ɗ8G@j= A24ly1t_`A@W'd{ C3K#.1+,l[n!bk< B2$@=!z ЃldHd{ Cs_ë]wZO`A@CUBU+kO#sD= A24l__/non͗X<=d*h/d{ C,|}q~`@uW}Klb l_^w#:xd{ Cg)!d{ CߥJ= B24uJ= B24l/l :>X_d&Џ{ uOB|}I2$@=!z !ۏ#xd{ CӒX=!z ЃldHd{ CRl7.o{uU,4/:M nZ)lB MxO'u8\;lB 0=~⯿yhx/d{ C3c?~ n|X=fx;,4~ߥ8r_5j= o5;w~| ݓ__3_`!@{XX=g?`@f;Ww4+ a?r_'>X=fO|sՂ} d{ C3 b_X=f`CG"= A24l?= lt^l'A@\d{ C= Ȑl=@d{A2$@=~ii)ƻz3= A2>zk}H= O~{+dN2n~]dN2$@=!z ЃldHd{ C= Ȑl=@&gbkd{2'rz ЃldHd{ C= y=kٔS;b'@{~Oz(FdN249/--:ԯ*e{2'u7 9<#ސdN24o Ȑl=@&g['9ȐЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= l['94/ٓȜldhl|d{ C= Ȑl=@K"lo@C24u{@$Ȑl=@d{A2$@=!z ЃldHd{ C= lldhr?oؚ=@&g|^l͞l@d{ C_['94 ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z MKKK5{= n=@VUldHd{ Cdbkd{2'}4d{ Cgݓ=ճȐl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C-dN249ۿdN249ۻ'=!z Ѓldhr_Z]z@\d{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@&gbkd{2'rz ЃldHd{ C= Ȑl=@&gؚ=@\d{ C= Ȑl=@d{A2$@=!z ЃldHd{ Co M-['9lћϋٓȜldhrbkd{2'&=D=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ЃldHd{ C= Ȑl=@d{A2$@=!z ߿gϞp`T8C>9^߼&d{6K Ƀ=!`سgO0ijldH(9e&T2$lsX՟u[WB Ϛ=G]d{slDܴJ.x֖r&;l3/ 68'p o[ >vΓ=p޶>vuz3o4bGc̬RyR==Cg}Hʭ<ge{8'p o[_<=Gm+UMap9k߰ >Rۊ-f!T_{m񻀴쯽VH֊ɘ=f-<)αm P{֘)ap1kBr~-ot-CբA5 s%{m ]m _D1G3_slp'P{O~1{e2^9?uw18Pt)b{ˡp8~׮]!q"* /Y,4αm0^U5W~nl5v\ie;ҌjJ25 hꭑ̀ddktɍy\eP]llx[]sl?~{qIrJ=K[}7?3?y)|}J_L[8>sxi]w̛@Biŗ~[cS!.8t:nH|#ϼsun}1bGf/S. Q @^|<|W`_wny.#oiO^mr)=Y<>x6ס&W? /~|]} yjτ=ͷj:A8:@}N}` ^&;9VXFC8|sǞ}!Do=4psbG?4-٪W[}KbfTyU(}Ht2xi]d3L_L[Z}٧ΐ<9_͢z(vH1/>|XU#+'-l6$[cTyõT]vU;_o4B6Po+딕kzquGїC9GJ+W?(x~8Sï?|߼ç]z :rh=fTV#`C/,4q{7 @[8Cd8[پ=[I><c^}~~kBz5f7mjQKf̖bfn5\d^gg@kx({L?rJdu+UjŽ;=*m]w:q[ߕ8_!E8բ =J9l0lmۋco=SLrse' jqڠs`+d{s߿k׮p`T8CN A߼Ϟ8#:7ۿPv O:e٪KM#aP3UfIkC>t4L"abR>[GV|鋷:rO?u: rѪYZ(5Ęz pxP:teCyM{?7lnse;U 5ks1>r]o6#eW~hdkn3eWUj >sXy&[O %6;+Eڿc=>uU#9P' ݝ%HIHOsnW=øWdвow|k1 1湶'C|3S}#?]_˶zNZZ 6ZšͰ2dIgSN:=#kf#rG[n|Ujb{woc'c;^ Vң ڒa!Ec܌ᐊF2ssXi)7Sҹt YUqB%7eoTo1jwܼcѣ|un,)ΔU G.Ik\yPN$uwrxCt3kalӛo+!?v%aXJ./P Ǐ{SW}17Sҹkdux,e4>/?9MCP7o[lVqPSm]y~Lyφf (O˯鸵Cx OgׇO\u)}8nnO= $n*tG5??:+VyEYu߿޽!6gCxë^NxΊU^6l ًo^߽{wXp6_Udb X4ub X4b+En=ت{b X4u <`}d{Xl13G$IENDB`asammdf-8.5.1/doc/images/numeric.png000066400000000000000000000473631502633300400173300ustar00rootroot00000000000000PNG  IHDR7JsRGBgAMA a pHYsodNIDATx^ |ل- J"EARM%T_ClOD9zRQ/`QUA1`D0!hZK}3ߙn6fx=;3e/}|g ^>%o[1SX댟tovϾfL//#Nއ^Ļqйm+uҫ/˜c23k$)n#-4㖕w%}AU~˅ 7 %g}.gLqoɦ5¯0LOwԲjNzWݩK cA{-;6YAW~0'_98ʻh~3!l%-ֵ9Q6i :їmn ܻKdx)˺Joٍ:kdazu1$ڇԥ੬=la'ُ_/ RwMz{c1vpFJeF?wS^10i|bؒ/goFie~rq^v*zVI+:sG0;6rt/0Ĭ '|}dYpuX6@ָٛ#0Ʋ$= -}MoK9`|m(8씸GWffɯ2>~aq9~yF{ .5>( kjrL:e(}S C7bdge[#Qkـ;9VA eC%v0>1lxȩ]/ړ?`Vv=uKQ}^=i6j{ [C`fjdˉ#̳r+WnF`{|qL[/1>7ՄG4n5ƚyCεƋ^^s: z0g2¨SA ѥK5^֜rMZCDae&`ܮĹw Fjj|N.F#tAx~KW3-].ذ+ؖC]h۟؝wOA=c^cDq?5C߿tzc'>:^wFy Ͽ` gHlѸ(:6b3\b-+wF"xu% g]teǚh 0ov[=WqžMɦ=/#]>X7`|xlsնr?.X)/U PD,P´e,-mBo?ήVyÇ?c_g5x?ow*IDh2pQwYKvk]3_6~kP+fMM`dAF5.RMFd# ^5000 HJ*6o`wuɖ= ?ew1?WK7X$pVo5a)kߚi|Fk{0\[;=3MLǒz ?yc̈́~N}@&Qo솒eoq]Cjk``````pɌMO&0ƚ˿P3}M-f\+\W%ї1eB^M-P ZV{Q'oECBW#v_z.j;߶mqXw/2qU8#Vs)0m{XK8>1a7Ae9sGj*',KΚT>~=%jv<}z%ݝ I::',Ts'?nKk[rJs7uZZD6̙Ɂ}2 kWxE=֒=6=T9GO)ޣ^. O;Pfꉗs W@|H*oRns:Ν1wꚻiMBu'4>3JT|xQ7WH` ^z۶m dk׶}z7iLS[1Ot?#3?#Ok׮Ç߿_Ox>|A t:j7I$wܸq$b˖-@s6juPGH_ΑZ3?~z…bQeO>?G4^2>yޣ'*5m\ݣGy.t7E6j4ZƟYO]uOzH&y} +p#5=lwzk-E'}8xƻA-"΍w_=~_7 㱅cnUG̙FӚSO3bUNEWl(cֻg^pv#Zj٘c}ySN.鯻^ˁv+k{ƧȆۄ/Y)-n6/Es kD31Z=M"Ԃcޣj'OӷJ5欼r+WNCϾd/=Џ&_i6^)F}S{Oy^[KS5._% 8Pڂ?_ʸ.Mѕhf?=ثn﹅7^c 5)Q͂;~gM\sc44Ҽ8#VyFmmɶ%C J郓8jzt㫓PK/U<_UP LP_D {&| ۷?S;3։Ezv%uA5GӘ(PMEbn7&܀zv֚+ 6wIh|m2eO=)ő&mCڐٿ 1aOS/֖ک(k՟e]Qmy{#Q{NȐ/V Q\a/ ؼZJ΀ZmڬΤ3ňhm"#/äYdq I^oAmC8%!WM4iU8$/8{t_eSyڐ}[7c(]dǻ^95jZ#VN^0N o v$rG٣-Tg.NEsdj}CMjݨB2a:]ϮZ ՛{$v&% \\X.\$ 7kb~ʔ)z:A߃#u#8n"t~k):Z:BҿZ+D2^zG-OחtFP}w*{>=l>/ ><»էdt@ {pA :#XpD8pvD䘕sE6j3sPG>v풳QFIdۭP^aE#ɂŋ 1+X,4g\nUt^)&,{3~0~. wQeZQiiW4d|JY=,] puISy<=yߊmvX͊FȹD1Pb ͠_Ru=:>;+E FS͛?ϛ((U<FcՋVIkau0J4Kh*;${ֺHFz Qں]-g%v;(Xli*(T)-G\ZsoVD;<2@ۖ.FMiЗJ1}+~*o7[?V}@3>nxpo?wxOfS-òuzd[ӎ1ÝK.6LVxv ,K ]׿o*k$k*/2޾A/^ҏ؏vxZeSU|4նd %)&}/ |۹gtfuMStc)Z%vzK ZHT߼1 'tI}moE}UcΖe2AIޛa=,|wf|~5G`gX6 ?ҙza5wϖW*)ot 5}tU ;2ykquEyy5 q;}ݪ2h }8:\wQO:޼oN!vjYI#ZI~7?[/cχǬ n;Ƒ9VI|ՍkTUZ/7@0%K 7ӽ>~%.º3o~&:[ﰍvxJ\+hm.FˬWH-Gi?X)s>Wqg &~2/9Gt RLzpw peno]dt $=~Fg}^)m_ׯ_߾}ԫW={ѣ{ݺuڵk^%)~@:w}etb"4V,S- =_SjFNZը:JW $&P{jiyΕhT=.ޭ˖+tKs.]%8lUe)eeS̻3j|UacaRI'HzrEbzhkZ9_ΪT.ѶU5u+X71O;!W2vlH_`/宪3˞;-a=OP^Wu PW3|yq[[UY?FfWv֯W8ʛ;,zrLE"C&oم^^`9*kg6Q H=]A0uZ7бk*r9`'pb5#Jp-vM&t";c#uެ2npf*ڙeϋ牿B#-"dLNB<1>ۢB=MP /U3,}]?PcNPNe5IICC+W_}l7o^{ݦhII/AP\ET [9bMB ..e9^$H#?&[6E;,sG'9y_] I|+st 5(>Ӊ󒻦t=:w}i^<IIYk^Xď~r,lYduukYk4z7"6F M)w*푇5>BF-E]LM~-,eUaL1 q6ܬjD>DXUiwU׻&leq~~^->x?ўZuUV/ +4*Վ4ޚJQQdIղ =Eiu\VBf_9S|V`K| \vV֪3ϖXR0,=d1%ˬ"ˣTO KRdgOډE#m$^ծ6W앆h]s7b=j#Y%ƦmiȯgVˍ ];UZLY}c?:Zuʍٳ Q(y[4R'E̙v#i̘uKJKs륙4g-H|-֌+ZjT(hUckW-Y IW.IF򆏱WyKt<&xQ;1auftg$vLB'od59r JIC2Ckl'Mtfaߦh5M#gsiV#;Au+F[qE'[$7syq)+$_\E V=ccjݤt ^=KJ&xQIFu_ 䥫INξ urzS3oDs-D>x ;awzq5RV&uVho?:V$nV*rC5-rj`NTשQ:J|qk{\n$njԮqR٭=KD>')f.[%;˦ҘD_ּDJe M5*X^xK2B(Yd,Wǰ\mY'UeJQWT8}PAIJ"'Uo,Ǯ$}"իbFԌ\̛ı!3J ժgҹ(&׎\亊Pg%-s=yԱu!1g/kSgFڟmH E-<>xH߁#кVڰ;ԝGߘ7hI 'tRNzI *ˆuXӼr2t iŖFclqEPOH[#AdFhgRVEjv\jhDV÷ľju3ޯh5[~\E\7ՙy"rHYqS}&eu_wcBPmRiwݬpC%vRjz'f(yU/"yLoS⪞ |: }rFryg4RLzʼn}T0ƹS)]̚nr)VdwH½Y]OV3IVdL0{VDz}0 /R|& WDITwCozemhWI7#ue$=HǤ2&YL:_DƖ;僇Ա !}Vs5kA:p>#"@SO/vsZ>}bYr&ZA"&oЙdlһ)r]n$KW.ҾB@gIҀHzϒ]NNN]houU.<ӋݜVߧi@g$=~Fg$=~FgHUSh !~tL^:L7Z>x@reWy3'sRUVhT/V)af3Jԭ=ʭ:Lm+V.0E#kͲ8}?HU떔N5b`J|;'[x%hJ- +KrϺm%_RexE2=SU_^lU806VUVCQ[xKoozCLTwyۺJ{}J+*hTջ|'@.i9>E#kn_m(-z\ь<}:EK O_Og@ nw7x$#UZħTJZ۞rc~ҾI/N{ejukYav9I0F(p*XuK#<ӕ}"'~rҫ2y+X\1I[[iШLcFsim㱸\%c*惇p1<,tR>=}逸g@rHzHzHz,o oٵߧ S}z?#3?#3?#3?#3?#̷ >-].@P\xǚ6t$2ܐn_}9/4;e0tٷ?#Lm36?3WHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHzHz2W =;իWo۶8t.a^{s=zs\0EG\tEd,555k׮%W_}dE X8)oll4Jzz\:=Id?3M%o'=;a$=n:HI@ָ~ 1/Hz2%$=Jz=<?#3?K߽cm߽O"@'/g7/?ߑHz«_e\@>?(κw.Hztz޸0nG'g~0 ܷvuid999ÇH;{zNKI^b>ދ/xM7xaÆiI$[l),,0z"^ziܸqzm[n9m@r)۷o}V&=kvڵe˖磑ݻwz187Ut$ {]c}8)'G6@ҷB}ѢEM2{]pq'"K[kLה*][j. LYUD%zDdg=j-I+ M[o%nkn%oZSD%zDdg=j-ic<'b:RSO@mmQMޅ͎Wi&oIFkT#PCII?|qq0s5ԘKUeeb\4v̺(%B2l]ΚlRVG0X~f^j"%ަ뮓W^y3MnTmHfNO"kޕDD]J h6ٖO_0痌T1;nCy>eU`qmq9FV[wyHJ^ʻȒް,qo? V_.BgҚ+>c_L{Lx~%#t5ޒPz瘋aW#K:z)#Kr aY& "':999z"SNuJi'(͖)?ST׋-5#K,%蘗:-7 4Q~Mj@KIIIIY%}_IJhqN2I/IieomO۱tAp.J"}z>3jg'}}cT~Iމ Uȏ7;רnxF{:~s6K YMhfuTgR#wb.PU=S@DOcFo(^%wε.MzJOZr?gYsÜeZN $=X.ę%,}n[:qydsFKm[c:m3Yk]:g̊3yHz}@J"',4oJWWu/|εƎZU2qV o|ڰ-άF![^5}΂.LĜzwg>QDVtJIޛT5N\}^Y8Aչ/Vv3;d$_k|;@YsR@gDD+<͔*`%=*V:nd;^3VS} k櫛 r7LDOߡ{˵3r%՝s]>;c9cͩ;Gy.sg<o}"/qU/5ʮ; @ ~tRիWo۶8t._MMڵkO:?#3?#>{ر}ethGM3|xС4T?8p`׮]4hwNڿt |N{2A≜'c%|?#3?#3?#圏>h]tѼGٿTׯ_~~k׮Ç|uxK+bnoUW]':7^xz&I& /-\ZѶvK*|~?YD @.eBK+y$N@۲M>{_w:3ݢul\@'۲}>={l{ty2zg@g'Wvrn'P&]Yiŭ~V PѦG}i3P d:ݖQcqAuܟҳ#!bGY3bOcLҶ5kL5_{6V\]V==?<Ӿ}뮒pR"庆srm'㲟yzs=@mY:zn/>A+io;qA^w2>{ɓO8b;zhϞ=b֎1B||o]#9߾׹Njop3uѡ7RMX{#cKUjTƏ7ʎ>ƍۺu`X%gqFYYI;wz'yFGy^[n]UUYg5h YzRwRGjʤ,qFgW^/6+}Ԭ/θ̵ln9ljwO+ #ر#jcjrӥߘns8 rOOys VTF-4z*H5͔{饗KXudq ,qސ *jeRƽ0Wa†{^keu[GJRԗۭ}15kF 5GwzcpHw{^|j u_Е0 #6ҤgH߈q/se1ɛX:7|DC2iHKTկ~eV\pw[kwǝdzKFӣ 4[dݖi,a~lv*n9>jrN-YZ+nj]ힻU6Se\LsQUbVYudrf2.e\FŻ|u{mg{}d6Dw\ H#y\VᔇƕSsKF}r|7ɟ']Sަzy =BY+ &N&w9?4.VIfXý52>aI@f~}!xHyWgc}b+m?Pf[HJ XF/z7U⛈wrokEE(m{>8iَGX6wJrlyw^>o萂/ս;jW9Q{͛;^w<Ԣw:1w9E޵ȢK;neA#Ɍ|mҏ먐|=S9l0=N|ׁM.h[r;D^=$=~Fg$=~Fg|~#G߯S5p~LΏo:^ ?~n-[X_x#q37 dUBꌔᏗujI{T?^~:D4M4!3&ڣ=tQO~|'DlzuOnl;xztDӆ^6եIH?Z'w][sf=m7jғ&ۍ /ë9(OB'77;64!#Q(155 vֿT׳Y쟿dxknaw\g^Q Ӆ2ߎ?볈OY5Z 7o\hTm֓>{3q%a/g9Vv@O_t+1lezL=xJ16]HN4t颧f݇>pNްatj(:t 555k׮%dJzz3?#3?#3?#𳤓>~iK*K&=:N≜ܿgϞ~yu)h>KcH_=vؾ}M#gyf^tQ $=,w??#3?#3?#3?#3?7 ]bڵ|>Yg}IENDB`asammdf-8.5.1/doc/images/numeric_range_editor.gif000066400000000000000000017745201502633300400220360ustar00rootroot00000000000000GIF89a8yڛ֗ђ͎ƃy鼅ǹxqlgb_]YNJNVmđy~sdT͏KӒDЎ?ȃ,uf W OKL*wNBhRVZUgNR~FICG?G,Q bgZE) h\T PV1_@fJjShccpaqcrYrKpEm?l,ljeUD* ! NETSCAPE2.0!,8yw0*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0U͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`.XPٳh͎]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KLn˘3gv3fΞ;m iS^ͺװc˞M۸sͻ Nȓ+_μУKn/׽:v"5*(П??T˟OϿ(h& 6F(Vhfx_0 p!"ax<0^(-^4h8<@)DiH&L6PF)TViXf\vc0L)&f8fD"p"{mix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v)` 訥: *L0)D' 8<'4PA*k&6F+Vkfv+k覫kX1cNo+D'T'I$pɜkgw-t#,m|0,4׼,R/j0:T@%`r#xINw1&$\w`-dmhlp-t vJxobX߄n'78D`6Du>]c5_3הWpp & 'xr'2/o'7G/}x뒍$=}vt32l/o觯'#ߞ.?㎯@O'^ @|C+3 Z̠7z GH(L W0g 3DqH3uC' Z hFQAf݈.z` H-! p oوF stB@[€|(\$BzhF:򑐌$'IJZ̤&7Nz (GIR29LeiTC>T;$1TAFxbL2f:<%i1"ikL@D:ՙHWԮ㌧~ @JЂMB{pXT' QТ8⽺ljņ(MJWҖ0=i0bϞK@LkJ| :8o:3CBƓBET$DBXͪVծz` XJֲhMZֶp\v"Qd<:a صG1vb[ŢRH:d'KZ jS{e5Qf9φvJ,iM=lgͭnw pKMr:Ѝ.o#QEp]zwTmht|K7*n0ꗿ ~o랲vxJa;'L ̸v F{wҮmeW0gL77 _ǿձksDN&;PL*[Xβ.{`L2hN6p*1u<;48iMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWV3/ahY֯VcAMbNf;ЎMj[ζn{MrN7;t nwf x2 ~NO;'N[ϸ7{ GNc\(OU<-8Ϲw@ЇNHOҗ;PԧN[XϺַ{`@NhOpNxϻOO;>쐏'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ2-&x;7 ؀uHt 9 tnt~@d/ᰁ>'IG*`5ǂG7 K*Xҷ6G76؃H (E-B sD㐁Gh/ KA2(߰RAbR$ * DHD>XЇ-X(`bXi(H2 ؆Wh}@h^hMHnT腎Ȉ' G;P'x`I38h|! psHs؈``  8^(8NȀ(('ȄN1VhhXR8ۨ☏ɇX눏XۨYJh Y{H成 ؎ȎЊy ǏjXs%i8ƨ Y8 3)*i*@H0Ԡ96ٔDL MHHx(` 8(dz*`ɀbقJYF臬XY||ؗy~<}^97٘9Yyٙ9YyɁ9Yyٛ9Yyșʹi;ך9YyؙٝމωtaQy虞깞ٞE1979Yy F:ꞀsY ڠ9qF7 Qzڡ1 9G:$Z&z(# :.02:4Z6J,zsp<ڣ>@Bڣ9Jt;!HJLڤNP P5wQzXZ\ڥP:G7 a%dZfzhjl$@* m:tZvzxma:70 LzD§8'=BPEBKbک@E7 &q@{Ҫ:)Z' %êyxBzbʺڬڪ2* rp='6ӭ,Q` z:P pܚ,j,-:[,劮檮®a4Pm*@{7|mPІ 8";$[&{(#+]3ʰ8\ rDP c5;˄:~c`=r R O볼|*{XZ\8,.50s{~;[3:SZcٺk }k;cـzr2 m{;| rK@;>k;KSV㹒 @+[;[3Ő۸={=ˋ=⫺ط+ـk[{k<ثz|=,  8 <\| "<$\&|(*,.$|   krL<,+)c 0NPR@B=D]F}HJLNPR=T]V5}\^`b=d]f}Sa֓n=`G*&|~׀؂=*8zM،؎ْؐ؆Et[8ٚ٤mu Fڮڰ۲=۴}ڡڵۼ۾ܲ}ۥ]}ȝʽ=]}؝ڽm|~=]}=]}N11^np  ^^J'> 11~F$,1 ..&8t*^<>.N,q9~<❠@ @N1-.PFX~s*[P^+A.Q#qY*n: `r>A0athHN p Q  Uh/>a@ 2`x/n 0 ~*.#+D>..>I %n  ¾n,s뱎*[P0n,. ^` 1^   N V a!>> ~ H0>ІO2ߠ鎎{o  ^ݐN"!>6VB\/ ,S?ꭞtNE>[`` `R>V)` - #$~5B{._ۭs"[` o U_%/$ @ _//?}o?COB@ DPB >QD-^ĘQF=~%8@ @%1"8,_>PiҙfR pf8JhUTU^ŚUV]~UQ5"'P9egѰVǖR8M%W=NYݒ:A  9Ѡ+ƜY=ZhҥMFdIN<GTkP|Ռ-z4)Ԛ;jF\r͵2.[Xn8޾N1s:Cujonu;lT?\&\?WES0@$@ pHaA;/B ' ߳P pCAG$DOD1ňt 6j0Fgk,FqGCT1H!$H#LHAd%{'|?$2K-2#%3L1R2w/ 5guʽ~sZzM w|a^ ޒ=~_~K}\8Hi f`D5lPts@G 0Ёe7aP (A S+@܁o lڇ.!4hCjυ^|gC;@u\aW;v+$z>P?І@ E׍pn`%r5uht#'8E.V c$ 2T!Hiqzl^gnlDE#C$ =I*|}mnHhPQ !F,R&e #s "ؾ*0f.~u,/3C Q֙uid1傎P_W+~!1AD |`]7̶^¿ToUjnpI2Ԇn'B<ąHQ n 1FJ0rqK!yM%[smS}*e:Wn\Ju;lNc$W\5ve(WN94*MΆűixƢSŷߚcsޯg)A?d:t-cGVSԡ1mʎ/e=j^NҰNupf˺:u $; h;鮷=+nWl  Z/zJΤKb;%xoͮ}j\Wuf[Iu%2[̏u4. m0C >q<_s-yz`N7@ 6/d&z&-GFtAB~.tWJDutg8Ȧnu}FXWu[!y;hw-Z/="Ku{ %o xw+7:1zҗG}Uzַ}e?{}u{~=?|o$Xyԉzcf\pQ~^Hn??&'9_>=?5!@;9@T@ӊcDY@I@nj@$ gȏ`,l㘉"rA` ˉ–PAXv \h–(BA#D \w0`)l FYBpB3l !\PA5', 8(D Cœ8h?B$D,? A D9룉kth(81tjC ’@nCh܈8TA[DARD;IVtLjmCV :0EVTŨxXtBTFS,@DJFWE[ @f\FDekTVE(Eus,CGHܐz|DD8K4ȫD#TXdH+tjBFG7tAZtdXVTFLn0IhȆFpGvDbsFr,I8ɩh5@ƘG1IF\ɁHŁ C]I{\F'DYˆGẻJԌ<ȴTcĉ(ķ\J1ïHVVC+Kl CFMDŸ D(e\IW:|CLCF*Ddl FEmʼD;M =L wD$CDCk)@ݐٖE\=B}֟: | ܙx5 GMHUD8 |ة&]P݊-ѭ!]ެQ]D5@*߅e^г=e͕T^m]me3M E?&6F=e` 0= 6a}yT^E .vaT %5Uၐ!aE&"#vg= b@1bA .eD~+ Ec.P0c@P bG<ޏ-T aNX h dU۞4CP|\]?d /eRϖ}MF P{RnSd&Y>>4Z~0Nxc'&YVL bLcZLf\fT>tNZkuL՛a\LavgQKY4pq\h_|翽cYƊM%Ծ/FgOBMRyfLV}nD s=S2L,U^h-/Pfo—(W[[]$UQsnb>ɫUWLleYhYCg i ~}\1=0>C{gO]etZkkkYbfj6+NKDVb'ql~fˎkflĞ*Ц6fFTf)9d>N=6VEvVn v6&F3fβfuo[ΣoLo'GGWw } a '^  'q GGWw`qWqq!p!'#p#G%Gp%g'o')o)+go+-o-/n/1n1'3Wn3G5Gm5g7Ol79l&d>@c@BobB7DaDWFGaFwH`HJ_JL_LN^NP^PR\R7ToTTWVNVwXl?aYu[u]u_ a7+cWvKewkgvivkvoo_nQp'rG:tgwZvwnzxwzw|u}_lW#wx Gx}^xkE;'-Oדowyug}/`yy #g7awAzgz o 7Gg{wO{w'7'W|gLJ|ɟʷ|W}~'G}zWՇw}vG٧}r}m޷~iw7~eG7g~awLJEHw|{w|7~zw?(& a?)| „ 2l!Ĉ'Rh"ƌ7r#Ȑ"'! DP TЬiM?#w'РB-j(O D)ԨRRɔ+[9'X:-k,ڴjTPESrҭk.D(Ut Sf5-l0ĊM$Ȓ'S^Wk߮&\3ТGCmJ5ҪWn2_r5ܺwKva`y/n\1~{8ҧ'ղS{g7 <^_dnӯPlsb q r7J8!Ts3@Q!1m\)"FՄ1,8#Z#g"M(Ҹ#)BQ5f8$G٨:$M:$G:hPZy%Yjٝ%>Xa9&e%9&m&Rh &uy'wʙd}'aIez()e:(-Zz)6iyj)y:**Fv*:r+k + ;웾vF,* -,^٬yZ{-,R+Vz.+6{.I{)Gb'{/"./ff|0Qۋ0 ;ܑ><1G\1c|{lq7%|2ߪ21?5ۼ+7s93З4E:I+m'K;4MC=5PJ]5Yx]{ "_=v!֠6 6qCuwgy78ᅳ5+^;QC>9:A~z禣:媳>;~޶㾻ܺھ?|#3|C?=S}c=sރ?f{#䫟!I?-L㋿˿. "-*b#+J3X,m 0S#,! !uQ+l! O3!AKb9!n!ID<"%:IL|bvH9AA"g-jʉ\"ذ 4a8ʱ\#f=|#qAF֬*,кX԰n +&)kS˂5f{Y 0l{ղ}-lc+Ҷ-ns򶷾-p+=.r2}.t+R֝c֫.x+񒷼=/zӫ}/|+ҷ/~/,>03~0#, S03 s0C,&>1S.~1c,Ӹ61s>1,!90,%3N~2,)Sʀ`D-s^0#A1f>3Ӭ5l,99_3=󹼀X, AzЀ3E3ȳt#-Y4Җ43Gf P>Uծ1I3 Z 0hmUSc8 -aı,'îx^[ T3bsy#Hȸ}8#Hnx@1M7m{#xp׻B6M KDڝU qX\ߜ;qᠸ)+s|n$Tr<A'9Ѕ>e`zӻǜ&"xYc;XF7^_;4av|q}{52D8<A@\ ~G! ;`^n9$ 8!Ayɯ3]T=s=/?>3s0'q k$A!FN!V^!fn!vaA``` F*!M ^M:%`MaM` [>"*i]$ù!M,L'v'rbX `r \>`"* ";ġ /Z.,0#11#2&2.#363>#4F4N#5V5^#6f6n#7v7~#88#9c86)2pc ^L$-E Z/.$OO$PP%QQ%R&R.%S6S>%TFTN%UVU^%VfVn%WvW~VaX=`44]>XYf_aeJԅI%y_!$_B_& C.`c߸aD\f2Tf$Y Iƥ)`QJ0$I&Mbͦ5Ann&oo&pp'qgrfrsa Ri!?&pC:C3[x]x'y׵w+R,lW.'.Bl4^u[.c_B(:HM(^J+hgl>-$gϝ((e.cҵh1M$Q%H(:AfBAݼ!I#ƛyܿ lgDU-V™)䩩yU]̕tքbli!()JZg jFC*\]j(iwhBlj$-Bpj`:N#,hh!`**ajhhj*ʪ+2,|.+*jFN+ןugtZv~+Z j+qB+֫+櫾++,,&.,6>,FN,V^,fn,v~,ȆȎ,J<ڄAwlɶˊ郰lh~;,fthl,,ĒbAa`4\ɥYc-7x9-l1-'` .Yў-3f ځC_ҲƣV^ƩYeCض?d.⪫me]m:gƠhmY Nԕkn.V cjz//00'/07?0G>\0go0w00 0 0 0 ǰ 0 װ 0000tX$4?1GO1W_1go1w11111DZ1ױ1oq8AwA 2!!2"'"/2#7#?2$G$O2%W%_2&g&o2'w'2((%t2)2++2,Dz,2-ײ-2..r&'031132'2/3373srpA0?5_36g6o37w738Cr4s893::3;74W;3=׳=3>>3< 53@@4AA4"33B7C?4DGDO4/+04EgFo4GwG4 X`4kp^Y-+KK4LǴL4M״M/YI#4M_NHIYŞR/5S7uٙ-N4UWU_u>%SwSCI5=kuyuW5[/5 u[uŵtuYK?yZ a6b'v `0bO6edٱeY7ZMޤh6ivioecc j@h6l5tvuvm|vjmo6pwpvdɴ r/7m7fOmnsnJ)vgvo7wѶq{ r_wwywqM`Tw7|7wsx6y˷~(}S 0Et{{Dțm6?8G2x?ąw 7K#7FdD8Y xHB vdA6HBC%|"縎x,]E'b;D r/9[{_D9xXKTx;XB0&$:XByGƹKKAdc0 ܚ1 1z,:[ rWk$/w$-z@Zz]k1x;ŖE8f$Tfe-[2C( ;7W<{gyxgC'zAG 7_@cYBe8X³ {մ;{S@{zBsÂ{{76{g|2l2A7||OA1仾::ÿ;RL}<~nkYBS*h@rB>>@{:cx <+ rD>>S~K>9AzBޟS`~`k>ljG¦./EB'ty?s@417~>@t8`A0FCDe Dc qc7hl〉8"F}Ĩrdɔ7qԹ&C?ᢂhQGr, F:B_ԺkW_;lYgѦUm[oƕ;n]wljߨVB ;^2!icJ7Ce˗1gּsKVipiӧQVukׯaǖ:4ɞq WfcE!GxsϏw-8xuױg׾{wNg|sxyK#QE}׿?*`,LP+@䣯 )A0T=THN1FqsFb aQibdKDDYE1BQDc'R)J+&/ S1,3LS5l7S9;SO5ؑI'22.,>D%mG!TI)K1TM9OA UQI-SQMUUYmWaC[qU]y_ Va-\g-cmgVik5Yo Wq-s%u[MwWy^w}{X׹} NXn-e42W)$ODAYIEPNYYNE]OnYf_><.Yy?$.裍DWncs꫱ZgY[sN{V[Y[oY o훏o.\u|w[Y!AR(݁K0tdK7`=GVKV]E9]/Yx@H)%!婧WE~HJ!́7O_YK^U?u"|pH% qQ A N\|_"@RlL+ y ) @OI aC6k '? "T% gE)Nٛ@XmˆG _+0!jWbHM|1blbG9Α*# 4`t͈=`#>ut#!IYTCK^c<$7I&1|[IU0K 4!e xT̥(K <"|%*;V.lS4M 2'I04NOl$&)nn t;᩵oFDa:ujf0yt(lP.4`N!r@G8/,C2Q ADv)%5Iu̧3!et*R")JqS~k9>*yD8QTiԧ* ꭘ:T&SUU @Vs!dRX5Y**G@Yں-u]=E(3 jWz-_JARV.-XMXNbPn5fYώhcZծB-QDZΖzm$[[,Β[4HoCem#3X Iu]nw^񎗼5yћ^u{_Η}_`7 N|3 v!a O1a oAb%6Qb-vacϘ5qa2 Md!E6򑑜d%/Mve)OU򕱜e-o]f1e6ќf5mvg9ϙug=}ShAЅ6hE/эv!iIOҕ1iMoӝAjQԥ6QjUխvakYϚֵqk]/9 !,22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ#Jp3jȱLj\Hɓ%CĈ˗/UIM2gɳgN= EУH3m02ӧRh բP)V t{TҦ%'A"]!H߻i u+F)F T,tMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνÓOӫ_Ͼ˟OϿ(h& 6F(Vhf(]ava)*Pآ XB4·")#"I:yQ(&!,|Z22BCM$ #KLW,,845?((4 CDN..:>?I33?abl8@*\ȰÇ#J<Á3jȱ# vIɇx˗@8s,(f͛; ٳ͡HF,jҧPy4hԫI`WZ Rl˰!0dȕ۶.љ XPݿe%€cP@$CXx@ˠ%&P`C'<װc˞M۸sͻ Nȓ+_μУKNسkνgOӫ_Ͼ˟OeU⟩>|>AW A JW! * 5^RX!z!7z&硅x"3!, w22BCM#$>?I KLW,,8((4곴CDN45?..:33?(;Mabl @800Ç`AZ1FBz|H#H*0ʐ0\H(gτna,C" уGYPji"-HU*L(Q @m"MWRv0 ѭPCzPP@d81B p,J yn׏\>گJO)56|a;@@!,812121212121212121212121212/1mTEc=e=k@rBuBvCwCwCwF|esstuuuuuvvvvvvvvuuuuuttttuvwwwwwwwwwwwwwwwwwxzzzzzzzz{{{{z{|}z{{{z}}}~~~~~~ '6@FHFCBCBCDGNULB:3.(           ~ z+wNsnyw}}eyZ\anw}ßӫҽ̼-X T*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0Ux͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ` ٳh͎]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3Μᓶ4ѨS^ͺװc˞M۸sͻ Nȓ+_μУöP-h@Mڹ~78Ͼ˟OϿ(h& 6F(V8uYާ!dmi%,0(4h8<@)DiH&L6PF)%ըaUxe3^FeXdihlp)tix|矀*蠄j衈&袌6&upZM))D:ic!fZ*ꨤjꩨꪬ*무j뭸뮼z>:6r2b=F+VkFk)J:ƶ.+z nˊnގk,l' 70λs@p񽿊#><,$l(,t;.1lʼּ,2sQE5H'L7PG-TWmXg\w`-6n+U=c3H<T1J9lmx|߀c1W1(хI^Nmgw砇.褗n騧ꬷ._8۾=#ʲPb{>?˶(`#d@/o.cnc~NpeHL:'H Z̠70 :@8j 88`w<ngeрDa pm&:PH%Z (@{Ћ"8j06pH:x̣> IB򐈔#4=-ґ2;EoY(y;9cx#CDL*WV<()2c.X[fo% >5L2f:Ќ4IjZ̦6nz 8;+'$!uޮ4KnwC^>= @JЂM(@xL JL{(ӢnjDSeUԣ1В(MJWҔ8zNFԝ$:4$[JԢHMRI8Ĵ,6QBtMS1թ~`+X#XJֲhMZֶp\J׺xͫ^׾(Qe#ĩ fpIy(Yet@@ͬf7z hG+U+0[Qڶv"cKͭnw pKMr:XhLeu+r@kw- z|Kڗ@p- wo[`N;'L [ΰ7{ GL(NW0! [&1ocT&HA ("HN&;PL*[Xβ.{`L2hN6'YuvSπMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨN5QΠ"Ьn5f^ XZ Vw^MbNf;4liS{ڂ6n{MrNvMzη~NO;'N[ϸ7{ GN(OWޙ50gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋dw 8XxȘʸ،8X(``p䶍܈n؍{ 蘎긎؎8Xxm6yX ؐ99fmߨ "9$Y&y(*,ْ.0294Y2I 谓@ .yّIYp z`LٔNPR9-I pXZ @BYGmFW jlٖnpr9tYvyxz|iZY 0܈dofzp 9Yyٙ9Y Y yGɘozI  <Idz9Yٛ0,М Y) .PYƹs  @=Y<).y <ɝډ,9雗) I z9pv<<nmE֡:A:5z0*141:D:9 =<@JYK Ij \ʥ/dꢼ`Q W =fR0eڦ PڦQPs{z Р : `cw*&;^~ ߱-)J=ny ">$^&~~>X ~C9yۀ:<>M .~۠5.7yF PV~XZ\^`b>d^f~h-,N䬍 [ B<|@>x^-P`~|NP>|^>|e~{`p뱾.ľ{쳧]np~`Î>{`߮!,Mj+111111111122222222222222111111//-.P  1F R\(g;kDlGjKfO^VS]Gi4u5~4+.:'A0D:E>F>HBLyNRhTQ]dUUuVEW4_'f)p;}nVkjgjjjjjjjjjkkklllnnnooooooopooponqsZw>@ES_k~ؙ֓ HA*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗ ʜI ̛8sɳϟ@ JQ5´ӧPJJիXjʵׯ`ÊKٳhjĶ۷pʝKݻx˷߿ VRZǐAL˘3k̹ϠCMәŠ^Y5ם]ÞM+rͻ Nȓ+_μ"=,0bƑ/_νOӫ_ϾO^>ϟmJ(h& 6F(Vhᅽa )eq#$h(,0(4hcaܨ9#=(;a$H&L6PF)TViXf\v嗐 P݈ߴ8p)tix|矀*蠄FyhhFTj饘f馜v駠*ꨤjꩨꪪ:#I[[ ѴP&hJK#bq#l9k&6F+Vkf{v,ކ,k_PȺ+k,JInd&4ӭRDI8dw ,$l(,.,22<26笳^Pq@-DmH'L7PG-TW-5"X[iZB6)lPLl:J+#tmx|߀.n8^މ/8ߍ?.{1E!gw砇.褗n騧ꬷ@cH[#%]×\8d,Ib(| 7ogw/o~]0I˧?J /=K,{.LA'H Z̠7z GHpH!~u5k]&b%771%/W8yH8PT>U IBL"HET!ZX}5D[.A+p/}NԖlgKͭnw=YT&G^r M5s_٤&@ Z6wvYUXp״Kj׶SxKͯ~LN8atC SDXJ@XG@b$a P"(a gBR@`I*c#8*Ah"HNLNǺc8 )hm&81Y\$1rW/dŨyH&` rp^A%@ll@/v% A8 mk_[ζn{Mr$0laK[ю@ka{]^ʦgKun{{ͦ6 [06{ GN(OW0;Rԇ@fV{V`[<.Q?H'ғnNӡt?ɺַ{`{ן.[RANuGfv}p:=OO;; ;P9aq;獰B%e>}~gOSU}i>zԳk;ЏOh@.2y!Q*#N??8(uPiXShuXzYzxّ "9``}pRwx04َONMT`>yWy l@<+ K +QN 0x5PN(YtgtZNeetqutkٖP@(r `YNv(pvZɕ^YGtZ\E] Y( tyt L阏Y{ivX,x$©|^00 dwpΩuA@m0{p `0p Р 1USHL K I ˜i_IH. u$Жpj e : ZQG*Yڗ%0Y@y'* `Yyn1Z-Rٛ3!9R:C~)YuIyzI )ip}pٔ +u )K FtQptФj7ꨐj:z1کZFꛅy }I j*uAJ 50Z꠰P -PTuQ`k~й\:3u fZihȦn K)RO fS9)ɡP`zbI` Жj+ -u:98*eş*:PkuQ 5Z#Z75٬K痝iP{ʖ4`ǚb[O`Oٜ^*ت i*ئiiK]P]LʑZtɫzt~B:!;aA] :[*)P:ں|y9)+Y9[śYR {9ڸj dY9_{c{+Jjul[ךh亷qLL1KbNJɡ kڡ( ܱcYj% JB&Cp[/ܡxY뛢 L%$t(;6,źۊak^)ٶo;gڿ~ \| |zsYɸaٯ{, ɖǎ옞J/ 몬l< zZ#Ak6=|M Îy\T,|iÄڙYl\|T}[*n;r{uxz(Jr:XyljJ챬ɛei8>jyέZ+<ڤjй5Кod-3[:,A|[BVw ),[JKik2=@zLwvnd{>]̋B-CXZL||jPl̿l'󨸉ɕĮKրCЖ{pGg>5fo[)O׼o(02>dtPewlY z}j~4])߈sӂ9=~xmNl^ηcnR{ߔ鿧nیN-T].8;uC]nNSn>\,[^~0^?_ ~q^͔ ?_P"?$_&(*_䢞2?4Ю5>@B?Dm[pTODRO2S\^`?FH?@ nqan7:/0oxz\?~zi|_Bn3Q,)_/j&6>s?Paƙ/q/FfO_OKM`r?]p@ 0]?/jE@ DPB >Qĉ&@E(~RH%MDRJ-]<S3^ęSN=} Ee&N?5锼vqM.\>eD R#EMDI=QN-\`ֵK^wk@o^ ]E8ǐ O\8`u;K1ʣ.veГ]c~[Ơ+>|nޛ=pʼn'6.[wr͝?]t[9Lvݽ^xfT)SPRU+W`Œ5V-[/˔n 4Y#,4#0 |0C[($ 8;LHX,\.g|Q4P1GwG+ $H#⿘[ڪZkS2Tq@2%473TFt $>Ͱ;Ռ33!s3CQ9 0QNE[dGA=sB"4SM7Ѩ&5TQG%TSOE5UUP&{=)嫲>,rZU1|Qa]X=X83C | 9|MA#,EF+ݶPS1]!5]wș^{7_}_eUWt/o-5ղ]nM[8 "R ;uCXXgѐT>9~7qY 5KάcOތg&8yefi:j=(r>+2?.٠#_EpgUOuFxnԤ%nk}{fni /Z9=x'cjo6s?=tG'}tnF/X VU(R#j6e &OlՖtwVcz:9㱗}v'|M/?oaqdq~YࢺqV V"W|6Yj0ckmwy :6q[pp4s˺gT! uCO} шGG[E a_ø#{MxE."nh/41ь8ʱF61,r@),@XFvc )G:x#8q(Lfm?{;THhJ*)18[^KZZSHG.u7j@ G AW#ZA1_Sd.YheLgB,%Im-ҝ2=%VGFrz%Ev W9G#\KA Hr|B z4;RsfW-k9.ܖ9e ]JUjV tHΚ4Su=8?]XjF+ZGΙ]^{/[lnw15i*k9Y?-sކw)gJƷs}c+:!D^ıݸw|iEKLpir ٜ+YK6/6;c[7/7uBJK&Adh]s':tgƑXI2χ(]3}-O~OzRj7u,Z`?QωwmHE :v7~2g)Nw N  Nӂ;J֮ieUYeZQ_n^躷F/ 5Mw{|l|_Q2e8)gg-e?]sv_g,2x_l[3c>s6r5̱ cw"lqC;⫶ʁ@L @ 91k@\%LAy[kA%4/ 2!B=|@HMD;DtR4SIDpõLDYZ<U\E$ E A_`\E#EEedf b,Fk>QLFMslFahĚV|>lCRr4GNFo|i7Xsy4tTycǙ@dGe{ܪ|WBr ȅdHH/t&|ӸȌԹ$c~Fɑ6GEdɖRVəɡx;pC6xtɞIw8$ʢTFYCQşʨ\<ʫ$9IGL'ʰK!U1˳D˴4&pIɱ˹<#˼}aKFwG=$"TdLDvǏ4L!)M9ʃq|T4Z$G#l"Q\ǝGd׼)aڴtƶɦF}NII휤 *mzr$X;rDʇ@AJ"tKIO$og YOgb:&n)To t }ڨ Ѝr$<:(*+((¨? E (]j|ʄB 5ʩE<"ZR*!"ݩbѿ̯tCu|-ʒ)+?ʫz*Sʚ.|PP}5P/.խ-$.;}S*KʄLM6%Tt=EDUI4}Q,I NLMKR@EȊTJ%!"H%PE͸,X/ 36[\%373?eUMMY%V,CKp4XsTb֨,SkVxtV&pITGTXtHrFsUpUxGvFw}a|Hz-F{͐׀G~EV؄-G]E U؈FDЕ،mFDUS`X4[lJ|H `E a$6(`ovHa\mވ᜝aaVރuFbbN(%&{Z)⽠a-.V/~b(&b5M1aVl"߹c1^<b`ߋ<9E3#ccdQ&fc;cdV_P ag`hT"vKff3mQcDfdb^GnrsVfNjff_-MX`gfga(guga4hvhU|g^-KJgnh|hdh'>d8iznl|甆ޑ.ȒTdV镶gfhi3EqFi_f=vcfFjj~_~Udj;V騖{jVh6ެ6f]hYVkk.^逮kv]kikilk>lkc~]mvkF]Fvl>\NlNlFlr̵m6mnk}p6i^VVҚvnm.nʅnPjn׾nnme>Mno.~vl^loomo6ohoZkmoo 'Zl٦n 7[ppo6q&q^ wiqmqnqq!q j$Orpq'q%mgn*"&r&/r?r2r(np50̆ssf:;ps?O@w '5tGD/t3m,qGEFt}t LsHm#rOsPW.sRtSn1sUMuMgu bu)]^mZvubcre_u+t4ugWftjuhuTulUkOsoOWpvqWrOusUtvu/TvswQxuy[WoAs{_Szs~Qtwm?uWwOwQtx|oFtx_KxPxP'vxo9Ox7TYm?y6_rwoy>xNy_xazRfG|?oz)zdzoSp{'{iO_Ͱg{tλJM{Q_/L{n_IG|/|OƷ|T'Y\gI}c|ooIG}j-}}֏z}TڏxN}''/zd7_Wٷwl~~y~y7?wEqWW~H,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,9p˩*Wl%̘2gld̚8y:ԈRSڥ4ep}%H4%E "sɰbǒ-k,ڴjײmv-ʚrҭ;fΝ=ZhҥMFZj֭]m1Ȓ'SlŸv7sLN> %jRNJjV^cl6ܺw훣f‡wwt_ӀSfmubٌSn:ڷ3 N;E-Յ]#6ӯo>FO9~/i~jvlSm9 J8!dw!q!gހ̩w t-Rx")Ab"g'r\{ N"=##wɝG`s!{ 9%UZyeICL2z:^%i&ZrMG7#L~cQ&}'n9)^*١c>)⎀:( I(/ab:gJ)ny)a6 bfJ9*:EJ$uzx#PR ;,z당.gJ;"{jj,;^_.>hᥫꝽ2ꩼuvh0 _&즭 k1[GĉVܭ|2yqr"s.)|3̲]!o <4D3]>o4'\JG5 OMg.');{]6_ݥjp{l뽷ohv7KߖMg?3uچK>ycx$L9[,a>2B{~:=Jө>^0k4hM;{~ݴ+vn㾯7[C_=eogw᫿~ۛ^m?Y'^?E?Os #(A0l]& *T "P D!p'Y P/dY ϗհrX?{@W%VK(E9^P*"ekyQa<ƈ2noFア8C;oxwA폔 )xHE̐B")I9rP$&sVI8]2D&ORc(KʅT#HA3jeRi] z( /L] GMh(@&6mr&8)q<':өu|'<)yҳ'>} PiJ Ϝ@+X WDy7@wl(HC*ґ&=)JSҕ4@5AtCAB%.HŨF9ҥ2N}*T*թRt)w`*S:O*TϨF;hյn}+\*׹LkzӜ? Pj6"5 (]2},diW{_آVIUkdC+ђ=m;'ի} +`:V-nskWumaj2}.t^'}mq7[V/LAPB5i#񒷼=\k뺖m< h>[7=`@,b~0#RSq%60C,byR7{ ? 1c,cľ9{aüM,!wƽ39ҳ8+=7L[ofrqu%kN.6krB:f~nD 3~ U/x|M3>2/*w ^nGy-V==c?Wf=+=r[YGcW^ΒwMr1)ME߰ӿ>Of růK1szӿud}{E?AU_&6>FNN U:U v U]`c# b[< ,!A"'¡$EFu")2'E(`)ZgAP+ޢ bZbm".""Zb"0c Y*#2>c*Yd |Xl"4v#~LpAāUA67cx@ B!"("}7FVHH$II$JI*,̄lAMفB2C#%UX}?n$Q~,4R.%S6S>%TFTNT"LdLdM$Od#$%dY]PaQ%L[%\ƥ\%]֥]%^*U¤LҤBv_XYWPfZ.`dFdN&eVe^&fff^f_&N&OdY&P2&jfcb6k&lƦl&m֦m&6pfL`e_ne` W&i"&Ffj96s6s>'tFtN'uV'unnoj_r%pfXY*&r98z'{{'|?,ħ}'9Cvv~whei'ZgK96>(:h>@ BB|Zn(6(9KoNaYȁ9&:ƨ(? Bhvohx (q(c;L)V^iڀԀÍ΀X|i)  (;): )Kܥ\9xf>)c)Vi>?T?0?8*}Cxi*D`h蒒JǠ΃*j),d<)gz?+Ԁj*O aq.թF+} **T^+f@d(**}+@,hkkL 4SIrckNBVkΧ+Bj+V.FN«ߒJ9.~X*P.閮鞮㮂^kʏ6UM]?fFK袮.$Nk^l yVCtGn/voHxr_>+KY=o[Z^?oB+=onao̯0şƮv/G0A$x`.jnJ![P/*/2/0 K ^*0g0 2+ DAآo<7?1GO1KAүq#:JK(111T֯kIDD1!!{'+,pq ${~4\2&g&o2'w'2(2„irm$O+˚~452-ײ-2..2/rtfo)~+'5p3?34G4O35W5_5_/&_r~'1*9Y,s73;;3<dz|{AAӻ?=aS<$8sᇾ>wԟ<lNGN@T>T`~>\=N\C"1>Kʣ`\?go?w?????ǿ?׿??;@c'Ϟ>~ :tHQ#G(Q2`ӧL(ArH!4zܙFM1ax҅ ,WX9fM7qԹgO?:hQG&UiSOF:jUWҲ/bʠi~*tQÇ'Vq"Dj@3r3dĈAReÇ'VqcǏ!G:x 6ԀΌ2(QLQYlaQiqQy R!,#LR!h285pöAm܂ķ.6JN;7`cS9;S=? TA -CMTEmG!TI)tR4Ԡ7HA- 6L=4c5=l5h[qU]y_ Va-cMVemgVikvZ6h N嘃DHDu"2.7DU MW5X .NXn!X)1X9AY(}w;pMj/׭(81-dy܃U47U9.裑NZ饙n駡Zꩩ꫱Z뭹[.NlM0= ryKtRf Aљڎ /O\o!\)1\9A]I/Q?-@^n/# Lň8^gՉ/O^o硏^驯^_//?[_cndfl=wYU0D= 4@. t!A N1A nAB%4 QB0&?G<~./D!E4D%.MtE)NUE-n]F1eW@km,Dڢ9v `5LVܢA4!HE.t#!IIN%1IMn'AJQ4)I LQ[2ˢ Mhtc.7l8r "?a41Le.t3MiNմ5Mmn7Nq$'0KBH8>a1FxK_?P5AP. uC!QNE1QnG)3"e&)yJ(ˈf8CΔ5MqS=OTE5QT.MuSUNUUESүg4.'  @ 7 : D!@b xL"\p@!,<x*22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ ŋ36(PǏ CQɓ( R2˗[I–,m9L@Qd94QE'](QP-:Õ$'N5+ǭ\~3YJɂ= Uiβl$+nAv˷߿ >8`> uŌ:~8rɔ-_6YN;{ :t/Kh uJ(vm6i '1-o"'(Q:^N AokSp`wC ($wy S:Xp!,<22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JHŋ  Ǐ CI8\ɲ˗0cjR͛8st9@`͝@ J@O* PӧP#EZp)ӨXj%:@KKeW-˶[g4y5mݷx5zBͻk 5)%̸qSPر7)dV1@P`hҰcgy@ n ; & $ [}w/}{;XpBv`yb~qG!,@&22>?I# GHS&&2))5곴++7008i?8b@9]A9VB:QC:MD;JE;FEG<>G<>G<=G;;E9:D78B55@33>11> aẇ>\|8򑐌$!Ic$%1N>2(@!(W IP,gIZ2#Q4f%!aMc`-L{Å4IjZs84 dC`7ɌBJCD5NzÅt.GLQQJ*11212121212111112133445/6':Ecw nacbhl_ME8( #)w,m'c"O8&  %4$C*N&7[,Fm3U1a,j#r2{;HLTVсXmW\XZZZ]]aaeegglkrqvs{wx~åӜʿйӰ׭ڰ޻OH*\ȰÇ#JHŋ3jȱǏ CIdG?~LD˗0cʜI͛8s|ϟ@ JѣFY\ʴӧPJJ*D?jʵׯ`ÊҪٳhӪ]˶[ʝKݻx߿ L6l+^̸ǐ#CV˘3kޜ۳ϠCMӨOc̺װcGUF۸sͻd N [|%'jNzuGW[ν;ubOaҫO㷏O}Ͽ" N8G/;$sNHǁSr'pQ6H@(Ђ t"/-20(4h84BHȐDiH&I$PF)TViXf\v`ryPJiL""loUbv`HFIyfws|Hy#I*睽\"*ꨤjꩨꪬALrάj뭸jk+z &liF+Ԧ'v ``ԋ,見riҹDNLF/(Bw۩EװF,q?Tgƿ /[1AV`,0\B8.( $>a˒pꬷ밿n7Ann>@zyP(rk7ЯaEb8Оdy\d?_{)8dE;2P%>rzީKYdx y@E / ̠7zPziFH(ޣRxV/6K:HC8b̡wx%7$Y3D@TN"0H*ZX̢MѾxbTDBPNQ5l@pH:<G͍v 5!dI F. O0ᒘ̤&7N" (GIRL*WJSABC̥.w^rn <Dv%bEUP=UgY~栢[Eg:Nՠ=0듺5VѪPբȄXIN_F)J)I3fv@X"LthU49Ӣ̀Y NvT,9ԨLjUT9)$?R&Ķ$ / pK~R;r\R(eH%^Q]E@յVt Xsho]jN~FI=ykVVs}5ΆV}WT* ׵b|̀$v nv ^5HMA, @1/xDžtKN@^cqX \$k X1fcR -lܜA^)܀& pL.ͱxȁ$4$`B[F;:#.m a7^X tTMӱSt%bR4 (ӽV,gIW#kb>7npOm5{znsgxXַw.{.ns4F46_fddK1ngd GO҇> $ [,o$w}<TRzμn.o{Oƪul>3aCuRh0u3ݰaG۵>{4yGn{v yH:K :x8dIPBcd%eXe7yw(zgzr:r(0g1dm;hm=BqYENFMńuXIoP>ׄ YC WY3&NN(~w_e}[7%X}VbHSh%VǃV~BxDX{hr';n(co9pz'K-pgxpgpwqdЊH+Xxo 04؈6g@ xȘʸ̘GvlWP%aNe~ӸOԧLdh60khVf~jd`gkP|_UX5au~f~tHvnurNWW89AGxp-wg feBVKvJVdcfxQpcAvy )"c294Y69hzC7X1 SFyHYC}ԔN6pCI9TiKi 10P_yb910ᓅx@ Vpr LOyjSčc%zkR7n9y9SID6 N$dybi4jyXrLy5)Y5JV/'G$_pD/Igz/rfCȹr`ٜι%ps9)P 10Q b0Yy9d0*g'y ٟ #3YJ%c :1!AN)G4 PZzb035a8'ЋUq-$@. iR: +Т.:0$(P$P .FzB.6%JV&pR:<"'cgZ<*4xyZ:e¥j"TjV-Q Q`>Nvzxzu~:Zzڨ:Zzک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;[{۱ ";$[&{(*,.02;4[6{8:<۳>@B;D[F{HJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@BxpB=D]F}HJLNPR=T]V}XZ\^`b}wf}hjlnn=wtӖ xzׇ~׀؂=؄]؆}؈؊،؎ْؐ=ٔ]ٖ}٘ٚك ٠ڢ=ڤ]ڦ}ڧׄmC!ڰ۲=۴]۶}۸ۺۼ۾=٨}ȝ-ڮ,A6v 6@7]}؝ڽ=]}mߚ0`dccV:;>^~ >^N:V`ߊV?*,.02>4^6~8:.@(fH@G0J>HR>T^V~XZ\^`b>d^f~hRApdhtQ K0vR~>^~舞芾>^~ndhrQZLVZ !ꪾ>^~븞뺾Ơ ?~ڧT&Wehp`f V~؞ھ>^~^.hVf w! rW ?_/w_O`:p,.02?4_68:<>@5 "! R?T_VXZ\^`b?d_fhN_ lnpr?t_u 1O/~?_|@ ?_g!,22 C XXZZ]]__bbUUPPSSddbbggiippb 9 : , ggtt8L aa$C  ll;  . B ; {{rr__ll(  & vvXXB ii3 < 2 mmyy++  }}2 G@*\ȰÇ#JHŋ3jȱGHɓ(S\ɲˆ|I͛8sY1̑< JѠ>]ʴӧP &UիX. TZÊK'׮ -˶۷3-Z1 P+  a˘b„T $`\]d A ۸sC}.""+_СK @ s0=_ ‹0`Ah{Z@@>F@,#(X qPÀF_6` $  W @(Ȕ\p(?I?@J@AKߜ HHGHS))5è^_b H$$0H$곴ttHt((4KLW33?+"% *34> *ablH*\ȰÂ5D6J7O9X:`ps?fyA^AXBRCNCKDIDGDEDE@D=Dd2ULSDD¸ V@,"G#qaLdD'&R:EZc$VF"L0IRL %BFiV2X;*WrR7̃i!å0QL2f:Ќ49_={1\M 8I0 "(IInlR>pxT >~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧNuK̺Y S8Nv=ߥ(._ޛሻNxϻNHzOO záFUJ1'SN'r)1Đ ?R\"Ԝ^ n\!,| 22R.? 0$L8@ DhPă/`bF5~8bHITdʂ "@#̀!,7H`@!,622\\\ߜHHH߾ߜHќHHH֕ؖopDEtttHttHt[[[ttHtH*\ȰÁHŋ3RlǏ CbH L\ɲa_œId o2gM>U3QCLҧ*@@)ԯ `U 8`+ط@ā#@h oܙ<_N;An•+r@˗bXF v( ZZp: /` D+iɔGrH!a%;pGP8s?KpCxh4:Nta|>MA7Y%n@`eR=FVQ)!,~P22@AK$ABL#AF sܙ#23>++7rۙ((4BCMwx}-.8ꆇJKNɳ..:KLW^^^33?퇈abl *\ȰÇHဋ3jȱF TУɓ($I2˗*dYQ͛8ssJ{ JTO*]jT&҈JJU F\zií`*XlW êA;(P,ڄ˷nhpc_w ͫe >"N@z ٿ=|"$`~ g`w9`Y 2 AVh" ZB!B0a BMxC#"TI - l`AX#$LA1)B6`Sf !B!,22BCM$^^^#ABL KLW,,8((4,-7CDN..:33?abl4@DȰ  @ѐ , BE12 X @dž@`@IYb̗0e܉$;y:t*M(QG .]i PNe *Y2`ҪM[iA  h`(wM`oN|BA @ 0@n8@D`] \@!DE( q! )L !,422x׫xrԎAmx~x\ғC>?Ix#Cmmvtԇ mk}#tummCGHS }ϛ{Ïϖ\$CmmC&&2))5"CCm/mC_rrwEmC.MKDŽ{dH00zf4f[IbVpF)g9q6PYh)I& $t'j%oNJd~UFrJj4\eG2"TzVؕ+NFPďVkfv-kk)|@"E$;DPIfTvG$Su;H Cldy|TwU ,$܈%dء cQ  ?۫8XB|$,UN*, _BO4 6kyC(qCP/Lp {XDޣ ÞI/" H.2@EI@ b\">TtD9ގEC=9ICA./4BEkl#Hf%1I1ĝ&7No HJ/lle_Xc$@wI1j-3(/1JKY0/q͌8d o&UCq$5NslѦIMrf'Gy?{A}4YG*yt(A-Z4(D(эeEi7gDH=Z'F1,M΀Dl5mzрZMIy@A#i#ASxtM]SYRVSTYUnCM%SjүffU*(z8fj%[zvՀi 3J׼F|uS*ͿӥL^9S d|i8;Ν09w!j=3#CƵjj˺ZmOeTJն nwӾp"A Mr{@6p&؋^)s{"BKM/s^ @ͯ~ @۴׽@ N`X!,<^22xA#BCM mғCxKLW,,8tx((4ABLCDN..:>?I33?ҿxablHXȰC #J(E3jxƏ;zIҠȇ%S:p"ntgybpPz%,`M^g\aa~as"8]9l,j(4h#ip# `##@ $,tE*9djM:cRF%,iڕ%I>qPlJf@!P0'PAV & i$$0$5>).P@!, 22BCM KLW,,8#((4ABLCDN..:>?I33?abl|0@A *!@…! p!^Xqcƅ+c$bhC tH(gO: P0aC  (iB ZXJp@*T4p@p@0 !,22#BCMئABLops>?IvwzGHS$ 3,,8>?J&&2'(2,-7곴..: 78B.MKLW((433?%%1abl%&0CT@&!A40pb (`C H"ЈR[0fCFԼ9'; €# 0)@x0H,HWf5؀C 2@`X@Q.'X G6?I78B%&0$K:cdiwx}tmm3̦*+6$Cm67A 4򳴼CCopstxmɊ.M1"".m+mx忪txC%4WvwzHXȰa‡# lHċ'Vd#č=4rȓKZDyR%˖%_ti 24w$cPBkNh!LPiʘ5iTz$WP*V'ٲAϢ-vSn5z[ʻxRX޿ a|,Pp1V 8p (SN@sLthã=6}o̫[93Ҳ&;7׬}ޭZxn7zسkνwOU7oA}~h_ WZ4`w DфRx%,ءCXᇫEP!X ̰a~1P5HPB@b0`EH'36ޓ%fp%! 6hEA|PD4^20j߁w2,ѧ*8B;"_ PDi} 9Jj~* RެkC!R,22x _ CA$K..M%&0*'l3,-7'(2!C곴-zopsijoyy}Cl1 84Wvwz @ Xt(p@ )Z(0 hdȅ | `ĔH~!'УKNczƑKc,@ӫ_Ͼz 4OۇO^@(h ߁ 6`5`ԄVh vA8 ($~X@g\: BHipC84@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6DdL QPcft QJ:Ѧ`* ziD6ʥ"PR+D4۬`/|jr0m~M`,PD,l7iT 1!,A/22BCM$ KLW,,8((4CDN..:33?ablH"@@Ç# ċ!P1Ǐ7rD#M|2ʗ[ISL+m63A <{)AP d )H :G DAաHٯW80aWH`<@&,`È+^̸ǐ# @Cʕ-#LY̝= ңI{V]dצ-ÎukۍqccҠ1^ܷ޺}|:t!, 22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JHq3jȱǏɓ(S`ʗ0c|ɲ%ə8s܉M@ EУH>,jTӧJ6JjN \Z5TvKVWĖ]˖Y KנO @ݿmk(̸+,oƘ Έ,tRHXʉ`Ǧ{,ݻPč+׉2c6w>=uE?cv/w=Zw|>/oO_b?x_G!,.22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇHŋ3. `Ə C8@Ǒ(SXҤǕ0c,̛8Qִϊ;yJ`PE=ҧ=՘RJ^=~#O4>7S@!,D22BCM$ KLW,,8((4CDN..:33?ablH`*Txp𡀈:p)HG jT)I,)taB4kN41Α +l`̑}PT#J!3k̹g@ӨS~!c˞Mm /` ȓ#EЕ(nFد#à^0I/@~`&?a=(A},DЄjƂFx Jh BC Ye UPH+bk0YA8#A5tA@=4;I ).x@dS*Y@` AP]~$B9De} EifSh4'u` +q|@*>J:d\$e:Ѩ:jHJd*d*jk_+!,o$22XXqqbb__UUllvviissZZSSdd]]nnggPPxxbb>?I# ++GHSppttggaa&&2))500{{11[[rrll__vv11XXiimmyy}}iill++7eegg00?I# GHS&&2))5곴++700?I# GHS&&2))5곴++700?I#JKV ,,8$22>ABL-.8곴_`j((4''3--9@*\ȰC>HŃ%^ȱcFCdȓ'KDrʕ-c>| S̈́4k N2}R(QF$$_6I`T{fڑXȵWn-{Yj#mڹ2kS^- ӳf(l87#6vg̙9>8kB6@P`u@A 9FM <?`G*p!,>$22>?I <=G?@J;H(:;E9:DH ,`B" @hp"El`R&LH! .8H L@ϟ?o(`倖/cά)fΡ<+Z ΓVxB vK,vEVImFWAuěW/߾rV+xp†"N|u_zH,9ށ2k|Yf t6@Z ӝ .X uA[_!,K 22>?I <=Gppp=>H?@J»;JT UPF Ӯm`@!,M&+12121211111111"z,    4:9aEIOX``vllnonoukhj_i\j_idiijjrquu|{䑐Әt[FDJVdwѵ¸ٲH*\ȰÇ#JXŋ3jȱǏ'Iɓ(S>ɲ˗UʜI͒orɳϟ@ ͣH*ӧPJJիN}r\ʵףXÊKN_Ӫ];۷pʝKݻxN=߿~ LÈ+^xNjB-Ki̹ϠCMzn򭈹딃b˞M۸s-΂3#YμУKN:޿M'BxCӫ_Ͼ/ݍ A/(h&`y ]peweZv ($hbZh >(_SU፮M<@)DXWdb2Vw6h_Nd\v`)]>U\$NhߌSbxI`@v|矀*@ġYBQE[ fIy!ktVf馜v駠*jO,څ@ UZjW*무j뭸뮲RVhŃY!&6쳵Xl1PFJv{+n?8^4}R2+[RCOP+,-DCNDa,HWP.Up/Xt!9o\v^jBAz~Wt! L(»/V.Ѯ`M7-Kx%lȮ*@A-/q{G@v0 r?*dW @ eB6M"C (?$PWrB.P`C"у Lcx6n]a/:Ǝ!(1?F# 0Co,Gbx3@Y 4U-J~6TC(B:ɋ'(GV(MJWҖ&@p8ͩNwӞA@H&֪@Ԧ:P*JժZM:Dba4XThmTֶ6\%-+JP5ըe%J l` l E2"+^ZbXͬf3 z fkͮF4lQ˽lgKͭnwKbC%jZ`Hr:Ѝtۋ3ъW`E<za| 3v)U/|;8elaNf-.lA S/5"^0ۀlypPpp8 ]a[8& ,]We0j`EH! [``2'ߢJ XB,K^-~ ҢDk0>π DHa;4V3!Mb !v`4hJҙ\I/Zѷ/kWYgMZn)v]7ѧIi^;u ^[Pu/Yٱb "MrwOAvCI 0A=ozSN P[n܂w;ݧ6/V*@ ȸ7{"X(FNQܸƃLbV1cX4obr>>^7nRT^1~UW^Y*A._.@BprZ樭dzn|Vn^jy*=^suሞn鐍P鋞 Nޒ 2ڇ>ە>Ž忎N-oNi n.x^>䓾.wN>nn>~N:ql/>n /n/ ڋ!#%麮~?_A?5䟾C o 0/9O*o,OY[X/of/hjloD>?Up?rt8mOoqOs7/]__e4ʝnnM?_/Oo13_O(O_a/4O?@]bM?Og/\?Oo/݀ݫ ΝԿ~ݟ߯Ni@@N B >SA\"fPGo8:ukWbʜC7PJ-]S̕lęSN=}zMJDTC1jH&QŚUVA~VP.EVbӋ7vrdɓ)śX} jV` >}+Unպz?Wddi .yaQR{h])FmL̚]+ ԹV]:ɫe~bğk7Ν2o}}.\me+m[vͽ}3t#Lh#3O8mg\ϾM?c0i 45;7 B%d 3и0E? ̨+QRQq%_91UڑǴbTP!,#JRɥ R'2)r,+52CtK6$фRMجε|tQO,NMSP C9m mMID4,47MyO H3KmM[tUVdM-Յjbvkkh~힪f >[.I*n`c|'{qq#%pݮ77Ws1}/#VQO]YpA9f/qOǽleaw~yݕgic׃W|xv=X{/_c7Z|g~S'v׽ǚl^Xca/| @ ۣ_(h=0y @}0k84RaH>PaXCP<9/8p#`.D>QQxD+&D)qh\]pv?щ@dh etCǍRr!M)q],h8j+L$E$:/C..`Z%ۘ3^}#';B2 +Bpk%-h?2$1 iL"&Gd&Re L.BӋҴ`#HoFRe59yMOfuT(Kwj2!Jj9xLŬg0 ̃.3% W_3 fC)P063?̧*9Mq~T!fE9KS$uI:9"4Iot%S:RT9}QJCL0TժVAVU{Ti9l8 S@ `#:RJtDKXZֳum}k\ZWyՕXUlu+\թU^XB6la/ ҥhkdKYBt'-mbؾ>e7W0vMgs+ݪRi;{Նֵ}DLK[z-xk*׶mkKڝw]j׸=ofq Sw\nD^׹.f2`Z⽨a ՆHjMpU_վï&Pլ8ȁv /vBcan#sNxB0*X 4FdcZ Z/ mJ1 w^_;{_h׿s[WQɋT2}6#jw+{5mxLބNy b۹>nn~_ < xT_8>3=Ӹ/c`$$^p@߻?? <4]A"; B[؅ls 4 AlQ[)*+Bl+A;0*#d$> : 1C*A x8;D1#%?v?PS\]^E6"EQ cLF dF_jS@Eƪ-@s6L@\vEP|xP4bx<pǀl4 F'oEr< PȋȌȋĀJDPGbI}$I 8~ȕdI,pm#ɟʠ5ĞMLxQE cEW,Xe6f)b0cEdUeefugC_ex#V\noW,i}@cAk%>Ӂuevuwxyz{|~~Sq؁Z, 4UL ^ W4$tt5>؍؎؏ِّM5ٓ=eY5X`؅ٚٛdD ٞنZ=ŠMCt?Seڦԙpڨ=mٖG١ h!A-|JJt[Xl8:\=CVE=hmV0Ec[de5X[٥ڵ%ȃ۝]haN%e^޵C͝%LӃ -bXݪm]WVp/ȅJ;hAJLJ[^-=3 gv.@ ^(_EX`H^0V(D4FQ_;=/DDRl>CPޅY"a``.=R*+bR6(<=@]H[[H]QpGHdG.QăQȽDI&I~cز܅:uWXeXeY\n^[(d>ٝ][hR6cFdVfI>rU@jkl߁hogj^Ɓu[0XRvvwxyzz&8.9U FhDlra Y|sQgN粬m&6>ViƁ)SH>TiNT沜V`.jn&w5é$5[@7FVfv뷆Fkӻ뼾VhsM7Blp_8TCt_Ķ3]8~Ȗ@+I˖ņ%kN8mФC^vnldmNG~>gnlgG!mŦfn+(Բ^ mmb+ v 3|5;+.J6> ֖FmNlГNrJ@7FVnNXm2pN΁52f+Dz  0GWgw7Gƒp !'"/rŁվ)p-sA#>`q!*+,-Kr1bS+)ǛP5g6w789s6_2)lƿ?4tB7CGDWEgFwtCo{11n DG@FOPQ'R7SIs+LXAQ[\]^^1V;W0pAYNZ`hijk#2+л,+vu(OMgvsGtWugvwwxGw#",Ȃ,[+}72(-a& 6蠂ٗqws,vabO($h(Xb,}݅68?EAP@)DiHF!P@bJ؛r!Xf\NTŗ`)dieRAŒN>DQ]ix(ƞ|矀*蠀ŗK>ÌVƐ礔Vjitgd馜v駠کfQ{*9w鬴jk\m*P+찹allf!FTzfUt+nϮ*^+J k/+hFQ89sZ; 70DF,^PQRI,RlF'ڄz!$l͕lpǰ()H'4<72+qak(Dxl\wN=1+t^T.Mp-wnb/+uUGfs8݈kkLڬbdžWnq%yGg8j|4樧^x%kQAK-r?[KQ ʮp / G/׬d/AG*1R 'mDD<M$ 10h`@Ұ첷Y"|;c @~ǿy#NB YC@h_`fA`]"l]2Z MsvWT 1!jxox ķBڕ"N ihPx'/  Ƙ@I#86V<"#;${C,G Ĥ (E*qd(G!GDH*D2&l F7Zq$.wSđH-ZQI-DHBY49$d-Hnza, 6;iO2L:mNe.IzN#y3yN{]§HMh͑@CBrn3 DJw235D7Q,$ }<ђnE)~0G?R~r38ffꑚ: Pア.RԦ:GC9ԪZ5-PU*TխJUW XծQ])< ѱE)+ZկxOJ׾6ծ.ի`F,P zİ=bZ"l_'Kz ɬfYhZZԺ]mW[mͭnw-SʅMr:}nr=,UWxKz^ ծ|]y o{{^|[л7}JD'L0 1`NuE` V0?bLOwL;F%b"HN-%;Gc[^>J&;`L2h&WgWcc E-fhπS 8h UkEm3 MF+ЊNGG/5ғNu*KBRh4ARZϳ­ ځ",lSslY[;05RQ=  owx4v-B*aη~;e¾'ķ/V3?"ށy?QC D`B)Sx8.\b yVNs@iuA|BERޣknԧ. 0R! :{c/4.~ ~td!2p;=ԁKȅ~&|MB+cg?y7yMqr O|X7tiAȍ/rOר;{fк{E=U*qЏO[to _H"O_\ AEHwo˿ [ zEmԁ|`b$!a{^{(u`4"Has`'Ḩ}284X6XGŴ} @B8DX? j 0L06w0 ~`sLOȄq[\Ȅq]Xhe [e[o8)!bxLJӁohcX0V=:Qт XxhȰ< 0 8Xx( $Hvy׆&g@ XhH϶ WX`zV (6H,eS5wt"d$dRƍX6PHȉ}T!  $s)ԘcUXC&؇58踎& eЎ19*GQ!P6y8:}&xi89Yyٓ)$1|i/H 4A9yE/{`$EZ$y]!(Fhb6 p  i A 99Yɛ)  Ұ fɛnةṛ  ɛ )P ٛI9ùn) n𝳹 ᙛНoƩ@j71A@r@g*uiј yY812Z6G12z/H FzHJLzriy'MQV'QjBW`U\05!lʦMpm֚ J9V  yɞq6Đ j* II Q )  a*:P :* o z3vmڬzhҊ7 b$Z&J@)Ģ-1}I*:f2?3@) LN/Ym0FOUT10mP䥰Yc:kmqm "+p Zwvjn.)J* z /-+4@ AH+*z X+6 I+ W;l{ *oJvkhP<ă̪>Y=F'z/@;@gP/lX@&T k/Plgx kC+{kx ۹t |ֹ˗ { ;[{{<n&kl kkԛ;[{/m pKzhaڍWqw =0GrsHdKQ* 0ۙ ک^; JʵK+I扶ʟz)8 ʫq*&|ٶp{U{0SQLUZţZB!/bI@4xt[g| Xns\Z/@ C 0x ׫ Ȝ++ xgn@0ʤ\ʦ|ʨ䰼vAmA:[rD: ˾˓G[R Gp{]ixlx1z L loKÉ 89pʪl y-<qH W0LڟuJ ] opþ֜z"=$}xk0k@ AAƲf/+ I;xi{[`/˻Ӻܘp˸g0}梷J]/E<O5^ժʸsԑ9|9 Pf- ` t]v}xzIH$^&~(<Y$ ؃]؇؊'iݍZ dkꚿJ&ƫJ𹩹)9 N]nNрР>&8tjķ ^KRy>iDŐ~zN'XίP~؞ھ*~~U4<^K;Ip( ,o|흿Z -!R^ i~й YѨq)D{0,}ٓڻ Abf~y?fK2?4_>>O'<ҰƮk WdǶ+ԩi vP  pllplrԣ}Ա>pr?t_ ֫=.MN p W$0~؈m@t瑿^"A(+7dY?8>/6 bk?sؖOnؖ_QNH)M#D-1|-uP,o3#`_P9.@@H- P„>w-^ĘQFq"cRH rUʔRJ-]+䞏5mތBN=}T"EEC(DF`BĚUV]vmHF|zBcW\uW^}9#FX#|{nXq#UXjh7'nDuǏ]xlڳc Qn޽pz4)Ӧ-:͝OKv !$vuݽXxҶ![=o#^t|%?+v0@$p@vڡ L0- 70CBDaAJ) *cN <\8nq2H#H qdI'IF!#E+AذwYL3D3M5dǝK9ėL.3O=O>3E ӰREqbTQTnE./EK03Ṟbʷ0E5Udu(#C3 )>2 L5 SU$֡cE6YeU8 KM~ɥZk6[mEAs5ܡfEq)!JER\Wyk"zԡ9{Ń%`ZE/$98b'ϐ3 _?9dG7_OFhWN Ņ'r]a<9rE^KS:h&hF:iXfZ 9jٙfZa|fNi;l&lfiyE͵YgͥJ6;ooGT[3c&mFC$n]߽;p'r/ǼW..JUҺTE3gu_=v7s>=DJ,*9e'xG>hqQ48V>{UI/ΩE:>^߇?~|¹#8@Ѐ˳7Jzމ@Ђ`@⯁_Q>El4BЅhDQduB ?bgua$.sA6pS!VъWb#e7HPR5 Rx(0Yc8Gl5]1i\#F:Ґ,q?ѨF6d&5CEr#}?RRn&UJVүd\B)JrlcJ^җ{hb YR'd%Q_6әτa0I2LӘ4e.MnvӛgHk$3NveO/̞'ޜST;:P "كOڠ@hD%:Q(T,hHE:t&>gC3҉Z/HFI&ӣ$iNu.t! |ըGEjR6թE%GiZJt.s0e*Oy({[?"42h`*gr\K WLs d~+ sl\4}6/"z泠E`;9U7,gJWZ{t*2Nw#B\xӍ .te=Nl\Yki^ZvޫbBb۸@0&~{R& ZvMh4ÒN=֊խ]7{0xӖnSUwv:\ VyU5yV4rR nDsG*DBq$H/zq!Zgҕ~u!:$Nuw;V΍f|^G{KJqz{>wJw _3ב;xc1W'!?o#W<זsP;UuN{W?{s{YN{^WǽOpSWx|~¥Og~}}$v_͟Oi{Y~?%?{OsĿ0BpL4 ;˽Cs ,$&!l- & +$'l D)t;+t@vx;A $,< >oCS)t!8$-B&=+=-1%+܊"\#L?2dCM2ÚB6CDzì@TC>//t='> 5CĢ;9A<=DG#Eĉ<,AGKLD@=F?Bdɚ H)ɞ||BKICɣ$8ODʧɻ>~4A]J4Jʰ tʦLGTK.!KJǵK-J=J˽dJILˋKԌ4Hń:AtL̔tļIͭ`LLAlLKՔMLSMd&s̫,͡8䄈L،KLNNDLM?]@x$T0CUDEeTptހHI"ԉԧ<mPUQ%zLRMEՀԷWXuSU:U+,U"\B4LU`]G[M-WEd3dU'ef Geu_Vy luVa Mom5i5WhDWuEg^mnKW<)U{v<{dX\؁ Ƃ5wEX|M$lhTJ:~P؃TX E,XYcmЖŗ]ٙ=IW,؛=D]9YYR.١آeţӤU6Z٨YE=S1(<Ϯڇ%H4͚ OïԘU[Z^Z6ڷUB-J[[bWiٽ[ J5ΠeY[ʔO [jU[~ \ɝB L}DEN]ZƵKO]DrM]6\]m-|č$ݪݴ][f\=ݍ\}A PMߥƹӺeSc^^޻u^n ^uK<]]^m@___ ^uGS%Y.F&`S]`S  6a n}MaCVϣ-P !&b3#V$Vbc&'b#)=)b./c1F6t_5c'Fcb}56f7.ɿc:a;~IbcL.bM^JNc0c%R&SfdV^bWNe}_YnK8]f^eQV c~@EOF>QGVKhi8ecfrnvoqr6[Ng^CwΪx\-fwg9}Ω~du怶{Vvfc^2vhh!T䁎туhqe9fihrBQ6`iaiRi_=^f<8f|nhؓFj~VjeꦆjVVj7|Ǎ0k;걎/FD*kX>杶ܞןkRCU\jk,NjVZ6ƶdžlQlC.VgĞW\lnm nVbΠ׆ E~fӶm&mam(6nAޠfnvZ,=pNA&@??n>/Vȃ:x502/)&P#".(ƹ~^ooo&o o$ppqqB G _pqn;qpu"p!Wo#Gr'< oq7r)oi*/G+G'r%q͐g0//ssos(8iJ Q'r8fJ_r@w,B3YE(wtC4qC83 CFo`(K˪ܾ(OOD-s`S@uLtm{64OrWu7P0_CcqG0+hfgvvc7dC,oOuZqktApogwwbOtk?Y wX}~w%u?|u_%iDr,O:ewjEp * :nXcWz!!8r׀F}-"18#5ɄY^wA 9$EyE'* TE}RAGH9%UZy%Yjie86^a8"y&i&t-PI}rAGy'y'}^2f{cq@(:(9)NMIm)z駍*K*):+Q:lБk+ĊZ,**(}Z{-j֭pAG;.k8W/[QoAG |0› ( K-xp/P,[ 1!H )s2-< 1;35hK BG#'H)#4#<2!H+ʹ)J"5U[}5 |T8nkT*pQROEϸKNky(# PNБ0 [DlY`_/\ C;?.|! w@ !! (BKŰN|bfx\͠#@"EaZ(1qET\RqDy(9JH=~Ր5&qo#"4:D P$&3Mr@RA"Jd!U?PRCɌ%%ӔX0`'"N 8fPe2yh,Ӥf6ּ&6eSbH#0ITT P3өuV L#yg00/d'@*в3/| =Уe>ɉSr(FQRPeg*8P6 g Č.FIяҴ/ qLoK*Ԍ.uIM*JᯔtJ*թzRJ<*j *ֱҪLRJBn}+\*׹x`7Jȯ.1d+`h֟X myK(0,T3,K#,c?X9 6qw[ t=/zӫU/% kOx/,@`j~|E_VI:(03 s0C,b#81O׉".~15 &{Q"1,!F>Y[bX‰7SyT[V H2,1fNQpn.fMTp F8PI ),Atݯm̎~4#-ISz@G:M t1 y"ԥC41O|5ci ^o}\]׾5+]RkQ j6+hgë5R6-Ɩ`":ysMnyvmow7.ppǖg&ML{ˎLQLD[ 6+끓&?9ʁ\u \U|@ E7/ 񢄜N9ғ3ݝ+HУ.SrCwAѵs^:lB#;;ӮYgq.ӽ??=%#ZM( ܾos?<fK ԈC"/S<+4~:ڱѓ00h(~ 3`BJ1`A v +Q`Ry `I _ FpA4 F `BMVY]`؁a  DA( FSnA a 1AHvI!DR!+Aޟȁ!!桬a DR   Iq(6#b"ކ_ d(b0#~"(F +"))+)"+b*"+F!4".梐//"0"o #1 /Á%"-.f63v7~#88#9#Al!&Fn#=#~>>#??#@chEF&Hܡ=FDzT$DT$FfFn$GvG~dEHV $WxEv!c&& 6N$LeM֤M$NN$NtEoXLc->^#}pL.%S…<%TFTN%UVU^TV% *$ȣ|lR6%Z%M[B[%\ƥ\%]֥]%[W&FD-:Q"ďZ&b,&c6c>&dFdNcEb,apc@YY&hK\i&jj&kffRA5BAgfYvbRn&Io&pp'qp~AfƦXeaYtNgDTDTvfvn'wvw~'xVfj'fDmm&tR{D |'}֧}'~}zg5c4cxfd'R',(6>(FN胮>Vf^%_2XEˆ(o:!((m ̨ Ԩ(J'(()f'hCD^.h >)(h)n&2&fv~)&B(C )m))Ʃ)院i蚶)6%)*j")i.R">*FN*&j1*&fm*vje*ʤ*rI! ,M+22222222112222222222222211111111111111111111.."" 2AG LV*`h&ia|gpo&"b&ۊZ裐rh2'%ޙ"{F駠5$b(-3^yzN5#ʔtfZZ4)#X+nk6INRj>j4vѤHhi5[\b),!")ᅠLK,ᄺ d%K<nDz|G +Ȟ"p.#ULb-(L4d 8sN:$'b;qH1/Z$rBrsC}=Km]&$:UI 3]{ 9m4g.8Vil'sRy7=Ce0,np1NxWÍ|=v欷>xnp|O?^钫OSRSl;Cn:꓋W-Wu0s|G:[o!}Ed+/5 >;珗莇|䛞HOw^ ^w?ZE$a @() w;w  XDLbM0KDpXT7<̢wEotNtaHGц_T# ޑibG.s$"G/"F+"Q%0f FP2p̣ OJ )%HH*V1@d8㘕(fAvKL{0RFZNf, HK&K0=X4AMHu'5iuSa ~E (AtT\&7o&9tPMGBiC6 iU*PtDh^H9JRtltpEJt5Iә2l}v=QHZNELe05cVW]l5*fWUup5JqST K$H*S7b"RAHRԪ1fu( sD(mLGYsuԐYA *lhM1umg [6ug/7X(MIY#l[U@рx C:֫9IJ{0GAA߁BKҀ%}`L^m0ڀԥo9׀"#k]ʞ@ +ǻHAy98'Bo>Rסo9 B۷x-9_Arc!TI6r#+ Ar9* 3T|#Vv0b,+HU ^J5oZ(8_ck?НJ{Br@K]@Eȣ tqfSfsgd=@i `& ${B1?!횄@U=P(/g½oPe =jq8(@,0@2Ȼ~'^;r % y] =hA4w͓<߃1@Eσ>$=  x5ЃG}77W@Ѐ2|  |Xy pz'||Hyw|$&(/|Gzg7(x$x&(wX4/@?z/Xz&|%7}20(E( ^ȅ{}tuG~g~i~2k~~]ux,Gpu @0HQFQXw0 5x|G{yHUȀD({'|x-xK0W|NHAKwWUX@脺Ȅ'Mh}jX( A1z@ G%ƍ6mK N+eoltjfjVtu[#G&se]FdhW Ng-nj ~cD(h%*rW8@uh jEdh]WlV dtoȀy2`y;i@`CɊؓDy׌{%G{wG8{gxHX?xxWxe Os| 栗 W0~[`l3%݈OGdbW-eu`y s[W_bd)~5DsPVDf) `iC`Iurty[)Oi}sĦeDqTdcPHy-= G|3@?WV0g䩊 yדHSyVi8XuW(_!a0_e)r!ufh*O  Ynp5i$c.z**SojZ\q,١;* I5z7my؜+w1X9 xX{&wz')xǗ:e*؄#?xu:} jq;j5O!TJ* &9؁ :{bzwXW'hwz駷W){gh pzȗ]I Jh+f 7LtU&Zn_6g]ՏitX/[VǪ̦,*ː,j pA(6~~t(pŐfh(IQ PhQV_ָ"n#7R aûie t~v[8%zk3WݛK+v4'w;8tL\kt&`V*Wp9KSnWe b*-f'{\1,çX #AbCbZ (o'baLpr`+K;Pdl\ AXPkF6]_L!^u^m^1<^Vv|!Xe1UYǕ|t,Uҋʩ oʴLMk4\˾ <O˨ʌ,Mp|̪|\5b1oӉPl,ϼ,l]YddD_ÅdeZF|-Qij@hhhUieMFZ&eFmv`mePV^CNiNmnQ1Tuvovr?N}N$T 1Os.˖zlh^.[F0)3)~键֔֋v|ڮ.̑.Uwͷ~깮Կ^˻,.RǎɎR~.PnO^NێNQ>nL.M̾n4PQ  oO/I&/#0-4_$G:m>D_7OHdE1NIPOR?TCqXHZ/\AbGdft?lFnpb4:QvExzR8D_It6?D_<41C?22B?'T0qB.oA ,_@4'QƟ?o8_K_ܟ3?M1$$8Ō;~ IV\uśW^b4ҵNFWbƍ?_+'M˔ӷR+ZhҥÂkj WlڵmmrnJ]o>,;pōǽw̅awN\tխU~9ל_^x-plݿ5._~#ӧ>?D0AMkOA 'ŸP#A؋B?BUBD1EѴ;qEgQK{kGG!G#Dr G$2J02K-{ZR4+c2L1\о,L5dS 3ACs637?:;+˳OAO%4QE-442D4RQI/Ŵȗ61_nJvdvw5WW\9y'Umŋg>IL>ɛ~6wҽzu{%oz{?^Gs:?}mZߧ?o~8ȕ$ AHFЂꟐ(]Ѓ\ 6pY!gBgRZ8CN1  uh? a uBDI&8 &Q|KI=(DS^arE,2O/bEQ#cKxڥ(FL FrL"UFCN+:LJ~7`FH"p,f bCxF4Q kp#t9R:իnc=Z:sxȃ<ܕ'U^< ̙r 8ueoZP$p沖~!9Ft9(.(tar /$צx2TO;nߡ P7ݥaAe=? DXF(5JL؄NHU`VpWxDT"5?8RT`XY`(dPe`gxgE)Q5p 4F5ЅQڶAXGMtV|XXjE0,^LjlԅkbIKDMlgjEW玼ߜV}LTO.f] fjAلM~V<ȣqF9~kUOdEqDW~nڶVWkPkf|EhEZkIv&.Vkx^nl~lcÆgdk^[ҾfbYÖ5mE>VnmeEvgX[&L0L@^VDOP$AyE>-%(/ &DφSҁ`V^oo&ogCW:qp pHp!,}j22$>?IBCM pppب67BGHS&&2,,8))5곴++7)󑒕KLW004@ hU+ †MAàhӞ C1  (@X z0ݺw Ex߻ߺ#/vBĂ B hsː ?I# GHSww33ii&&2ll~~))5hhuuzz22||--66nnrrkkee$$곴++7hhkk00?IFssܙ@AKۙs ݚrGHSFGGsrss&&2))5rrFܙFۙsrFrۻFۻrrFr,-7FrrrɆGFrۻ++7۽FssrșFFۙFFF?@J00<78|[\fƼssܙ@*\Ȱ!JHˆ3jXP CIɓ(SzLɲ˗$WœIGra Qv :C D*]JgRH.*՜hݺu^7p@ `1""?궂ٵm@vZhJ@t%{B)"W  kf',> LTÈ9sfmڂ?˴f9qo1<\f?#j 4u_@!uݡwgex P=:77 |kaJ& ]x 0ÀuBEBG}1vM( `xg"E( 6rix|g@<@)>:Aq? ЎLF)e$pdBS$])&UZ>lp)oi&x"A HBilb-|ܢ6裐6CR:D>gv@Rjꩌꫬ@j+ȚkV*,7D뱞K)F଱F i$AJ$E v;\ 2 mA@  !;a  {G-[-k, {|,"oq @(!,m2\1!,22#>?I@AK GHS&&2$))58|,-79)FF3ĭ|++7 00SC밧f};LztT?$/7/G/Gz5'K(S/D?8?I!+/SD|| ѡN88(Ao(Bor7%5 2O %D gHC8̡es@ H"HL&:PH*ZX̢.z` H2hL6pxRx̣> IBL"F:򑐌$'IJZ̤&7N2 (GIRL*WV<$(cIZ̥.w^򗋜%0IbL2LD Ќ4IjZ|&6nz 8KqL:NH~3!ᆂMBІ:u! J$ͨF7юz4#@Ғ(MJWҖ0LgJӚ5ݣE?Ӟ~4|hDJԢ?ȀTJժZXͪVծvuc%8*iqֶp\*S=xJZU ` V!Hb:1B,p)Xͬf7+|Ns=&"J"Hֺl]jV*hSZ~aApK3+){48Ѝt+3x= xK򚷼l)yK#wrp ^y3N`_Q~_<Bΰ7{#|GLئWbyNNy=+3@Ld4L•0wS܎&;P eXβKd*{^rc|8Nqu)p3pOF8dKqa0MzLB],.5'MJ[Ҙ[2xӠGMj:#2}DQ 48 zsm|vָεw^/>M־N X?&MHjO_z4LoֶaN.uPUBuأiCksη~f+* BI^o% xIqOTPx񇓔P.c\'yCNpSa(99"+G9I񕗔;~q@ʁq޵# Igdڵw[Ӌ 7R xϻvN2W]yφ;H'Z4>ȱ)< Qz7 L}9Pr`(ơu(@|˾(>ρrǜ+/W[] #Gn_񑧼-x̃bvivl\{~w$wvxGn6 ؀xvg{jkNw~2]w~"x&hxV8Z }J{Жnpr9ؓFishrBx4f yi͘Gxha[` ٙY4uTqM(qg/w|9gqx)qZH|:{©z! {ّ&t)P((p.ב1])hG"w8w䇄hxj&QInmy9Ɋ56ZI\9vc)iGɘڡ꘧F*ia *,ڢ.+ 0 @3s>wRK 7uz @r7r*+CJ*GOؤt\8`z9,[):h2 5z֓|m9\0sʗRY XI R@I:`u t=:Zz j:ju7eڪZGYxgg 0imʂH}7|K(t@ @zDIR7rӺqNJt!܇[)EȬ7$|)dZR(|ڜ@z8)Ɔ+گy{*QPG\ДheS YhY zYXyڟi@B !:#*V дNPR;P 6Sy4tYۥȪِp:rS0.ggt_.gȣW|=T:rOgct,ש[LKkn:k{DYP jjF|zI0/ȋ֦jɹwh+m&۲. CٺHBۼۼdw]~4Akp ڻ۽۽ V[lޕỾ컾G {FLyzI;ۿ?໩4c| <kGG p W{",[Sps:j8UwWe0 @cF| d4Q1R|3L#|XӜ@=D]F}HLN]BR=T]VZ\KX`b=֛d}hjHfnp mt]v}s}z| y׀؂ OtT؆}؈؊،؎ْؐ=ٔ]ٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڪڬڮڰ۲=۴]۶}۸ۺۼ۾=]}ȝʽ=]}؝ڽ=]}=]}>^~ >^~ ">$^&~(*,.02>4^6~8:<>@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~舞芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_o9,Eu(1p[XAQ/n`_؟onb?O߿hhȶl_!nuN@ !aPāQF=~RH%MDRJ-]SL5męSN=},E%IÈE TTU^ŚUV]~p̞EV-Z.wv4 =r>e7JQ[b FXbƍ?n,_ƜY3f)A|ϵF5B.ʹҬ7}[aɵmƝ[n޽}tspō'$YYc>"(Y1gEr݇_[x͟Gkܿ_{.8bЉ$=kS/AdA#7YB /0 ңB4pnCe Wdg0FgFoicvGvXqH)2J)y|G+2K-TO)RHVx3cM7߄3N9rcb3O=N1s,PCY9eQGmӍc|RK/4SM7SNQRQG%TSy;btaUW_5VYgVYSwW_jCtXcER]Xg6ZiM k6[m[o!,i022<=F!tH$BCM ؿ((3ߜ:;F((4tJKV =>GABLtH߳HHHt..:HH󣢤H33?ttHHtt`akH*\ȰÇ#JHŋ3jȱǏ CT ȓ(S\ɲ˗0cʜ)I8sɳϟ@N4YRѣH*]ʴ)ʛEJJիX?5ׯ`ÊKs+WdӪ]˶Z]ʝKݜh˷߿LoF̸B`Aą̹Z-^ͺkW6@ s kM"nڕ DνE7{O<ӫ_f^˟OϿ(h& 6F(|%fT \ h.H(G*4^5#C(#D&ePȤ{)<NVb饄ZG_! $kfF2@l›x2أ@)(20HpB0rY0A^@-p*j4LP z_@!,@#22H0@Ç# dPŋ2ȱ=X@ȑ(42Kbʌ&8męSH=}vTE3rD*S)FNʱZzW^rX(-v+#ݺ⽨wľ~!p0ᄆL C~;pe}!,4222211111122111111111111111122111111111111112211111111111111112211111111111111111122111111111111221122374=5C6I7M8S8W9\:a;e<iqq?fw@_{CS|EL}FGGDGBH=H7}H1vG+qE%jB e?a;\6W1R)G =3-("   # % $ !  ).!!0++3556@@:JJ5SS1ZZ-aa*ff'kk$oo"rr!ssttzx{~!$'*8HWfr}n\NFCBAAAAAAAAAAAACJYfs~H*\ȰÇ#JHŋ3jȱǏ CIɓ(G"˗0cʜI͙bɳϟ@ JѣH*+VPJJիX6]ʵׯ`ÊKٳ e]˶۪ʝKݻx+QѺ LÈ+˸ǐ#KWѹ˘3k̹ϠC/LӨSNmװc˞M۶ύ^ͻ ܸȓ+_μП=سk߫h"U3+я_|% 6"|# 7@\+:0IF` 耆:!yByLfGALT8cR(J3^ %.1]&t%y`* 1L3*tf4ic6"LnSW4 8xC!<<3΢$;yW$+_IXB/С2f,6J891,|e>-1 R89jԒ47l(ҖhLgJӚ8ͩNu*}@yԦ(K 1P!ᇪZy*VGHՁL 衏gXʹyhGJͣ8k>1׺ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻ3(US@[?l)A[ϼ7{n9FOқOWփ4'gOϽw{s GtO99o8ЏO}Ͼ囝H?~y`Ow/;'A3B8xd ۠ ؀x0 r0 pEQ F0rP @(ڰ 8v 284X2(w M$ =Y%>6xHЂbPR8P'& zr &X*Zb&#Hb8O dP"1 Y҅\(xx a 8"X ހ$ 8-(00PXx |v ЉЉ 1h8g 8ΐ_̰؋ȋM x X 8xȌm ̠ 8Xx u ˀ 8Xx pCm Yy ِ p vNExyT !,v22AR { *aÅ J4qE /^8G <,D%EreG[l(s6MDfϙ?1)pI*]Ӥ H*ՀV L(ׯ`@رv!,22A ; 0L`B0"ʼn-fX#F;ZyQ#"Xy%0_ !,7H`@!(,722\\\tt֕ؖopDEt˜H[[[tttH*\Ȱà Hŋ3RL`Ǐ CxaH L\c.aʜ 3͆6 ɳ'œ>3QC L ҧ, Pj4  \uGAsլ[hCV@ ղ%Й G,-7$ɳ/.9AHp*\0! 4H -j܈q CI$ɎM\RJ-ct͛8ss˞@ %s*uA'9H@UXj@`FJP**` ڮXZ"ܻx.Kwف LÃm .`!P 2Aʋ3n׮+n|>Y_^ͺuk ݺどiV-@ݳmw&޾e_-4崑'6 kνßg0\٩>}w AeWþg闂 h(X`~3 ( URQ`ׂva$F+@R0 ‹8@ lp"< `p$*0A4hpWhB'`@!,22@AK#<=F! $EEO((3%$0ABLJKN㼻**5YYa=>G-.8곴12;78B/.980t‡(C,TL(AB7@2!(0dI'Sd9K1eis)=P8e4K@eXIU0"ׯ_l2Y`ӊЀ0 L Vld0Ww@ !\~`@ &l8@B8! 4pV"bŧNv5!(,I22@AK#! ABL$EEO((3%$0<=F㼻**5YYa=>G#곴JKN 55?/.9H*\ȰÇ# Hŋ3Ǐ r II#O\2%˗05IÙ6s!"B:< B\  *j)PJիOv{0[f ]݆q媽Y|P_&^ /F! 8QՂ2|UA8Txs$ < j|PHD<R4,  !>,IH`@!,422x׫xrԎA~x~ԇmx\ғCOx#Cmm.Mmk}mmCGHS\vt#tu_ C:mCCm&&2$))5ߨCCm{Ҥ/mCrrw Km$춴M`Օю5m{6sQ }T"Q+++7>?I>ϔmCRǘZS00QO-~`u+ !P2w !=3c @$m; rMw&C"J?}l~'N׆x@b AKm9>{7肊NzDzC8`޶$p^3;)E';ߎ;/_KS}Ϗs̟a̾$ʛOuz ?xo f㫠KAp> 0z$,!Oغ2<_(n4 YEt By` DC#>~( "p=8Vъ6â 4@.~a\H3:dkq0a!ڈGԑrwz>> 2!D*ҌdHFN2q<%IAnn'Jy_fOhMs\tOv*4>-*Gqʩ4VUTQJYf5*Qի Z%kDzKfh=֓լX׺)J3׍ L+_)E 5:OcFƞ4YPXfGgJcJ׷64|j'Zv^k]oX}6 pKٺ1/hAԠ:Ѝt[ kAp- KX p-dW1N2$|K0 ; ` 18L>@ ` 엿  6Xΰ7aPX!,x22A _ C *HÇ@ŋ$ȱG ?9pIO`˗0cʜIsd'H`5 T'я:y9hǖ'2=1eTF5+K\*@QԮz<4-؎l%!,22x>?I#A GHS _&&2))5 C$3곴++7.M00UcFڨ@*r.E${ Hp@`8PA8 !,,\22xA C _mғCx$KU1BCM:. 4!C곴tx5Cl 3x忪7H*\ȰÇ#JHŋ3jȱG Y`A$K~\ɲ"J&_4ٲ͛8s#@  ѣH5SN"M(RV.*!ק[**6)ղMϢ5;@l| 7*v˷߿ LÈ+^̸ǐ#KL˘37ϠC-ӨS^3װcMvٯ M7v~{.8rQ3OytR;PQtuogOBÅ_^z `8 M(8sP zEH@ fwF8]! g#v8^n & DP߉@H@3 e@J@d ) h@ =@0 !,,.xA _ C.M xGHSm#Cش&&2))5ғtxC$mCmCC򳴼++7m>?Imm?@J00<x忪C[\fHXȰÇ#>(ŋ/jܸ0#Ǐ=P$I&OLc10҆ hr!70d 6ِF@L DO 9u$ֱZ7xǵa%UrCХc[.\!J 7X1KϠ?C@A4.^ͺ5ѥT۸;C TP AHPu9(q>gPbx2V8}ā-d8@={ "0u~'|' 6F(!,L22㫫BCM$̪\\\ KLW,,8ֲ((4EqqȕDDpDCDNpE..:qD33?[[[ablpp0*\hP HHŋ9(Ǐ CCHD(SJ0˗4TI8sɳϞf: ѣH*]tiСP%@իXj (įQQNJ,ٮ_8@pʝK\^Ӯe`߿ L8pjR#)T8Le&*h\D!*x2 @.\k,N+z"=cH -ⵈB = WHb؟(";m߆pAj0Ͼ=ޗ^TAX/Ѷb& 6WVhf hT  $h(@ b07F])DiB5 X$lФm]Ж\2tW&dilWpƙrֹfvY&z}~Zxgyh.g!Vj饘f馘N駠jj*+j+ݪkk ,Ɔl.,>KlNk:-m+5M@AJZb.4M:lkѱoRoK LN ̰!D$oE,{1ľR\~ rc$&l-J_T-+4/ƳA7C \/c$|@ R*Lg/tCHg}$AR0B`5AՁ65HqwF xn[8W?8'+V/y~޹潒^0sXꙋžS*{ܨ~ Uz>Ӯ5+3cK.M+|k=<>+>;?K^?[~o+]O= 0v] (% R>!,xO22 !A!+<=F , J#.Y\/ B",VZ(J!,2"(Z]`)3ilB(2TY- wzB#-QV B$.eh]` B *_ajmfiH*\ȰÇ#JHŋ3jȱǏ C8ȓ(S\ɲ˗0cʜIs4sɳϟ@ 9 ͡H*]ʴӧ; իXj ST`ÊKlS0˶۷pBDn] ˷_È+(@p 2,L忍0ϠCY$F^ͺ5ҚpMKKwo RpμύPسk+ JXb:@` tHOp9h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀UWeW&V2飔V5ifԤjiRv?**dꡩD#*֚ѥ9Ez(&Ѣ5;(Vj M5 !,<"22<=F!zz||wwuurrppjj mmEEO`_%$0((3㼻**5YYa=>G0/66/./.9 @$0`‡ 0ń):1FQEVh”*7Bl!$VΤqO:4iӧA `€So0/"hպp$V}ChJIaB%:\4bݻv Nl[`CrP@pa" h8@CP$M4B Mװ h rf oHμxB2|@sWQw !,W#22hh~~{{yyvvmmssppeekkbb__ZZ\\WWC" )( /. EEOC'؍ a_%$0 b_tt||C$rrggzzooww!**5C&Z^OS IOYYaC*C%C)HL^\D&`]_c55ɣ<=F!!TXebMQca66X\ C(UY/.9RV !!]aKOC#H*\0@#J(C3jlhqǏ-:IA#M$2ʗ[I̙5syQO~ @JЂMBІ0)H2 tb>`6&Q &|$7<*!(b"H7)NOEԢHe6vB5;Q]QZ0ʦ* No V;qUE~;(&b׾ `KMb:d'KZCORZFa)KZ~!4Q7 i21 h` K"Bn< XyDY: >d@rc_X]n;kW?Q`cE.y=tU#Q\X#rLLN;'L [ΰ7{unhD0JӔ֣ jkpD# D d  !tkrFCh#W![Xβ.{`L2{AD D^ `mcB` f2(?9`JS'2A޳! 54ZC#ҘN{ӠGMRԨNWVհgMZָu7ȁ"g HXlHGgNaŰ:@mA;`k{;uI@Ԁ !B oη~N;L !N7k@'hp|v-总˽qow\ x<,ow@ЇNHOҗ;PԧN[XϺַĶg*ij}gP8"ƉNxϻOO;DRXsOH0Ć@OWֻgO۾@HDD= ;ЏO[@C8| 9vE0PO<Bŗ~6~G[F z B8Xz@pc{UyQ~ x*,؂.0ViP[sviG Fp| `)(HJL؄N(@P[pr v|c?0@GdXfxhjwQTWH `5h @hEPC@k8XhQXyQF|臀xȄ;``x;  w>?CPhZarp@w8 D@ P7I@s<`HP0:PшЈ>(Ę8>'I@IXX; ؎Ȍ(xΘ8X5xى "x;`8,9wB`}` 0 ~A]xwYGyGPx LHC IY]  c8S9MɎJVIylYb9uI(Zr㸌ٕ(~昔YbIAxm9ٙwC@ri05y9=|(ȋؗI騏ɛHO})iZ1gَ X։ɗKIQ9ٝpytɜ6afx,i)4i8< IKwhXEwJv) ɍ ٜژH8pDp) +!:izIpI7 H9=ИC:zi*ZCȤJxIGJOȥX(xC s|{*Zzџ'; hwښ ʠ CiF i舍_:$Ig ɞwʘ横jb \`gJ I*O f  ZFZXJL*Hʑ`Hzͺ\ԈrYfxXPGڮbzc*;[*9>גtwʚ ٩ DyZ ߙiXҸ$y"+ XYۤ8 Ř@1CP ΡCJ۴9 FP O1S`С`{]˵I F yI+JٴskRa;[ ӷRkɠ`Fٗk;s *Y(ɢ0+ۏy[VpF2"!K«0 I! kի!Ǜ!N!˽;[N拷! I!wK;ҿ<#q| Gj;J>{U2Jڱ9=@H&;سT) %}9+J‹P&C{&A@\D\&rY ␵Ij+ hABfr⠌M?M&a\?܀QCib]lWsX\ ^RȆ|ȈȊȌ\(;+k@-0+f!A,"]$Kי1&6tC ӫ<^`b=_X eDEK>^~ ">$^&~(*,.FC; kM]8*QPR>T^V~QKKE @69:<>N@N 6EGe2R K_X~yi/~>^~舞r5dK^^ 5.f~iAnbܸZS@ 9@>^~븞뺾>^~챞JX8; -R~ jlnb;vz4 `>^~?_ @}Y юӾ^N隻nC.@ `{vPt rk4_68:<>@B?D_FHJLN6kkl`;H^~隀g^~ qΉG# pr?t_vxz|~?_OX Z/ \OM(M}͉dꨞcv(`?_G{J|dk ICu/?_]po`}ZcgЯ߉+U)D9bB >QD-^ĘQF=~RH%MD92kF)eUTPEETRM>UTAtIӧQ'[ɦmG.ZSLH҄";śWўj^4"@yޔQRbƍ?YdʕI&;{2Q$JpWj֭]j֭][lڵm۵#@BbG~oK%2N1-_Ǟ]vݽJ3m#@9yL_|+Xd!E/߀8C D 郎5°< /0C 7;آ%9:DD#dE_T Ϳ߂8d--(D B ;dI'2J ?B7K/Js' 3et3+y4PL7L̐8%j?O&ґPCE4Q"FĚJd'/4SM"6ro7"7EUt?xÌ-\Ȉ1n2PW!>Q4Xa%Œ5ި#׋=KZkS 5Qw,GlQ]9 !6Ђy&^ywF7_}Ű.⢄PŠ7R&]q\S[3AQHeS\\A风5*!eX@$$}JaAf쁈gE:i _x +Q;D&R۸kSRk1`m#ަ"v8!)` 4РN^y{GIb+2ڡJ`!Ƌ~|i7;\v  B!.n#f[mg- bpځtgiN"1$4X(j:422! $ 2:{=}ח馓b!4ÐF(Xvf۱a_qbnЁ"(x+'9zD4hF^PQ er8EN3fY <čb('TCl!h`8D_Jfg? RlQAL19$ Uy[= ! {>(lh#JPFh9,d IEF6ґI1"(%/ĢHNbckH#cXuPc:؉iLBp(C5JL*'7@/d τ&wD$q~3)6FӛJ~QjX[#r\9Ě8β]آ-zlÌvW2e wB F]kd%ۚ%`G*/UnNֳ 49RPgVxqB)d;[VApjuNf6*oKЖIle[ֺ4p%J2V׺uD2] з]f]\r+)!-E@:1D\~3Ew75xNr*c)\RpeBhJɛPb1 ]ư9,;#/O9SN[qP-)@!D"@3l1@q!txEVQ\%o %]*[9@D㠈c汈I"gld("Wm] g 4eLh4_SkNy7p ]tLt4.ӿ3jNSxU-\VQ4%me bolnDF)!5 F$yٺmw֙>D#6P8HAV ·tYF oFmkmH$v &>rClowKxکe|7ǹ6d.NC\-_-\{I͌>u55^ "AсZu"n>FgAJ>wg"HGP{F"}f7Ү۵>HDnxW/w;Qx oyv"so y=Suͯ:^On!/\7f{7(,zQ^'DOH3Xge; ~_LodtR tSug?{"+7[34C˙!B@pQ@Z56 + 4 @w;@@1J3@е4\TT9L L=,(&AdAkBᰁ[zU/߉/ܭ'@0)D=,l-"6,1,@73\ Jc%=*8$>:\ Ӫӫ7}7 UUR5CEDUVVa}=UՆ/AUR]O u *lmno-V9<֩J$e5hL4ЀQ:X *}~؀ W7W*eESu 輎  ɀ@{Ex } ؏YRJu&L=J>]@!pQ;eX<5耑@9H-٣J GT:X;(hטM̙YYؠ x5۳} @۶u۳M;-FkKST2e/ĴZtXY ،M| pȕuY[̕\ PZceX<:,ZsQÓۺ(w/p {]\Xy^Ε[q[E ?T3?K]US4νhm%υ}:X?h}^4^D ^E)_=-P4^[#[Z_߮P>QDž ``@_UˌQ]%|4Tkmp `~~EDY̜P$-tv xy=Zx]ڹDRH_'H(03p:0c==:O$O7mQH&UV,XMϔKU7f(FI@KNLM䋄cHSaXe]VeTdre XY0ea(#amMWfbGcedefI_`NOx!qFy8 Ft(uv.PfGf`yXs>F}f'~NfvSXy|V.eVw0 hcdilFRmfgF[&fiUZ&iFv.b2j>GY&[G6GU&>EFU~&fCF&T>%CFFS$.GFvR$GEQ~$J1i7Fg&F¶Pv$Ķ^lJn4aM`1DmYMwkg>iWGjk7BsTLavw7xǔywݲo7}~w"m4x1Agn'mj6fTrxʓsmFjGxHxvvKxEojmO/7?LfA|\øhl0yÚWAyoǘzsA-z09zotN^k9'Ƭ7{EzpGqGo{CaT{//žh"|]4|ALJ|LL3M? {kT7E||JKSy?w|LyrO_NzA|xݗ}o_~~if}KJhW~FVw?"NdqgK!]iViđKoĈcQ ԧN(kU'G (i$ʔ*Wl%̘2gć/9qۦ%hS$CyҰi(ҤJ2m)ԨRRj*TW¤P#J@%,†6m-ܸ)4P!C%VQ#G Ek0J8u 2Т'Sl2̚7+Xd͢ͻ3Ԫ)-xڽ^̸ǐ#W8Ξ~B&8ʗ3_װc˞ū_ڛ [yv '.xӯ9h飫u>kց'xar^pdZx!j~щFwm8"*xW ` [ApQ#9d6i#bxUT[5X$[3gcdPZy%Yrt?ZܑB&by 8&TRJX\l9'BY'K5NX塍:ew~d{BzU(ELY(3%z*JI $Y*Giۊ*y4*+Ҭ&[MHZ{Y)&"6hݪnR*~˩_:/fn v:(O>;p| 1{^p{j r/+.-{o6L21W&22?j2_(7p,G6 =t[4Kt8ϦsƉ4U/eVϩDL[n5efɵ bO6j=dPl`+wށ}븷 m8292O/3S9œrϛG{,$N͸Ǿ;1@;g ʪ74Fl:]|ٛ+.}c?ӯ+nȦ*8g<5EbU-N ynfw<pC#leLԥ0~!NF\ '(?1b\Ϥ"rƇ)gT|?I^=Ī}2Y4`X5,^؈3F0#7c ~B @IPeTM(0z̆եDIPY(07z ݥH/EҒ~L)VRK0}LgȚʩNSXQ@ jZʢHRA>9k'ʧZXͤVծ^ +J)hZZĶ&r\yHAڕMx+*Ⱦ鯀m`HX1$Ll:ţdDZr,6zhGҮVJj2Jf鶸n[" ˣ7{ȥrwVSKY͑v8 xwG^"7FM|sH_/;7r7D-L9ΐ'\ ʰKbլC\6JbA0qf 8F-C r "fHn& r}LeY9X. C7b8"Ҫf02񉳜Fg9=xs|>oπGhJF;[VCJ+o͇\O=Z] |#1i]|fΦW}Vi% Vs+Zg ѷkRYHR~T0]/]Tzԏ 'qNk3zYmrCqnSy獩z'޼ɷ!o{5 Km=۫0ŭSNcxj:y|w GG>R7UqLţpbs20To&?]GtYJz떞;JP1CCeu"ys`ǾSItPۜۤ>NIp77r D>.O}VO{TڿS S޻bJ鑽ږSK>Y[?;73b$q͇F}ZL87N׏s^|_لU"V&`o,4 U< Q LQTXZJ g`Ք`T j R e(emۨ)K >V}+e\]^]AaK " > v!e|!фS!" 6aм!Sġڌ.[R!  űS! !&!NUT"\"Ԡ&b ''E&"U"ȔQ"*R"u[#(`ꢰb%!##b]1㩨ǰo42v/0:!1j^665 6#PǤL";9<Ƅ<#2գG#L>;R?@dgEK$B@B CC>KDL䮬E BBFDEv$K`<A A4#IG&$$PO2K$4"L>Lդ@\B$PB&t'*XLQeR.eScAPUbVrWX%%R*%SS%[fT\^eVneW~eX%Q^_e`>[Ka%bb2fYId`e&]*&gc~fZh&=iebjgkNRlBl!mfjf^V@ܤ 'gT'ѝmVafYA eAtu.Piqn&0A8>_'MZq Kgnn&ģ$`'٭'9gw*hҧhz&'|6>zӅjh}~`R(eg\fz'? 縩Tf@(@A (E^(H@"@qv]n @?@, @ 0?#b$F Rʥ lXGFiz^j\(hB*2BAI顮]RӢ xinC ̙^*˧x{n.i'8):vj4}^bB*Ҩ$k +4(h  Vĭi(^*ӈ'c3hj2ikk1+*|+1k*TB" –Ds:'tBkN,",0]JoBfh&HŮ e^oFʮ,,ɂ0֬ͺVj,,pimvbfњ̦2- .mcZmҊ#j:mAr'b,"ϊm֒mv(n'rhVc-܆gPy-kߺ+.lngJ,zlVn^n,e.)^Nևb"x-|(X-:’  %@.vޭ¶m bmBvவF%:/~/ZL/%xQ@mF-..Zr U(YI0B 0!ԭnp歺¬Ɇ0„p ϰ As'\''1ߺڈ#)1qHKf0_p TpAA 2 A4p+ R4ApU "$B#8VR'2%%gy63/*|%Dk# #\X/3p 1132'2/3372KAHA WhV^Bb~7we)_*ǂ+ q, A %|*/sp?3@@4AAAo4W57B6o7s3QA2ysU9B,% ;slaB"DB&3>;C5qHB״M4N04556S6{DS48_8$G -t"I p!pXd—LCXX5YY5ZZO;4PCPKDW4Rg4NlC5+HT -ӳ/tC8 84c?6dGdO6eWe_6[DCCG4Q5]c)o?^'*'v` AKrBTC^(066pp7qq7r8d6KlOPQwEF9BS_B# |7xx7yy7zz7{{7|Ƿ|7}׷}7~~7wq.I/rW{^W'/87/?$O84sswv\\uߵϜGr&8!$l\g8׸8縎8899'/97?9x_lA!J=IL- ^O99?j)9GxyWÅDgK7Sw]ޝ*{'\AwAL:W_:go:w:::::[:@zqȳa>vӹ? °/y[so8vRב8S#!A0z;;;ǻ;׻;绾;;)sV4i8C 48_'/ B$iB2d|#$ix@{>ㇾ'3??'/?7??GO?W_?goE%#&}Y/ $0v1?y1t)$@B@P`AL6AC钦ONM&\:|@dU>uD)R<{)bM7qԹgO?y9q۪MsLد]&S^"CӇkW_;lYgѦUm[oƕ;n]w!C9tӧUvٴjz re˗1gּyH1aA=(%Y-0(ҷq.0D1jQȒ&QdLG>P&u)rR&BdPyѧW}{Ǘ?~}׿ P) lL:Ą)ǰH20P _@ QI01P[,E] JQ '*(#Ȉ+nNJi^i&2C!(J;[S1,3LS5l7S9;S=?E3H(OŊa1:RI)4CwTM943m R2U]aOaUu!yKR9&{a͉t.KvL2KJkVmo Wq-sMWumw7[i-,Q[ ltBH!Le-VP?]K1Lim #RW#{MnI|N'=YufuTaYiqYy矁Z衉.裑NZ;) lW1YY7◨[;FU#[n{Qo߄.]yERt뿧(\fIZ$Po!\)1\9A]I/QOqDW$|u -ql߁^/ims;c%ܩ*Nd0S_/O_o_GLA )v۫@6 R@. tȥ&Dyv_qoNwpKђg>䔇-t aCΐ5 qC=!"(=f#>Dq {e.PUpE찃i ]=`uLeHG6B$E)&;S=OTE5QT.MuSUNG/{ʔ]:S`# K7&yw!^yӫΕu]W}_X5aX.u_Hf.@\b+]J1rp[YȮuka[Ζmq[o\8jZ.2葑CȎ]nw^񎗼5yћ^u{_}{2Ϭ`Zc_֗6`/ v!a O1a XpD&v+鬢)u?\ -vacϘ5vqq^Etec!E6򑑜dxb%OU򕱜e`]A~ !B0' jmvg*@ VPNğXY΅6hEvƳC҂&ZiMoӝO}u le/v6 iIҸmmo96M}lk6oֶnyϛw;wp/$xm}pB7ťpWj5Ar|';k- x5an=ρ@7ёi;NӡB/rѥuot]pz }3Ϲv^5 }rT#$*{}L>6f/i {΀Opۡ:|hQȃ"oyկ<;BA}F|41rH[|3>b 7{@k>}C[0bߞR@>wYo|.A{0nKe! N΀0M 10`"A0OOo4 ԏ|]a0epimq0upy}0p0 p 0 p L̴p `Jm/9 @ `  0p1q  1q!1%q)-115q9=A{HM}@ Xq ! H'%ڰ*`  p 1q1q1q1qɱ1qٱ1 @ bq mM C *L ` @ 2"%r")"-"12#5r#9#=#A2$Er$I$M$Q2%Ur%Y%]%a2&er&i&m&q2'?!' ֠ F !` +r+++2,r,ɲ,,2-r-ٲ--2.r...2/r///30-* `i^q% )  3A34Es4I4M4Q35Us5Y5]5a36es6i6m6q37us7y7}738s8886`9%ҏ>!)qҠX"*4+; s>>>3?s???4@t@ @ @4A=/RpL$!z@a aZBLƃ<$DEtDIDMDQ4EUtEYE]Ea4FetFiFC!APji*BqOqCDL%ItIII4JtJJJ4KtKKHcB)GS)ۀHEZ%شMM4NtNNN4OtOOO5PuP P P5QuQQQ!5R%uR)RZe|T:H/tδeTZHU^LTQ5UUuUYU]Ua5VeuViVmVq5WuU^HT_fS9S=w6fz5YuYYY5ZuZZZ5[u[[[5\u\ɵ\\5]u]ٵ]]f5XuX *"LL__6`v` ` `6avaaa!6b%vb)b-b16c5vc9c=cA6dEa\jx X ea6fevfifmfq6guvgyg}g6hvhhh6iviii6jvjjji[vkk&(lvlɶll6mvmٶmm6nvn6mqn6ovooo7pwp p6' 7qwqqq!7r%wrW'(r17s5ws9s=sA}z"tItMtQ7uUwuYxua7vewvivmv2pwwyw}w7xV:xx7yv+eyy7zwzV3! ,,TXQ>*%* :"E*?3683=/82222222BQJpO~C3Ĩ  ťӇ|qA):s]C+IVc (*$ DTax-˒'ܞ'ѷ%8vBiSa`en]|^ْbɨ`ƹZKKatǃǑǝß´ûDzǧǙǔĒƼDZɢ͐́{ooxyn_[Ƿ]֯r}֠{ɓpȅuxumv\yW{OpLX8QUi|,#§˭ @LVVόPyIiNYRRZJd3e{h S: 2OXL$#|$+~D;T5{}7R_j{ŎǚǤǯǺǎȗȧdzǻ}wV+/jՏԓՕךҩpUB H*\ȰÇ#JHŋ3jȱǏIɓ(S\ɲ˗0cʜI͛.Aɳϟ@ J(GH*]ʴӧPKJիXjݺ1ׯ`Ê딫ٳhӪ]v+ٷpʝ˴ݻxݫ߿KÈ/̸4KLe3kϠCNȹcG^ͺu^԰c麶۸ͻ7_.ٷy6 <ϛFNҳV%^ Ͼ}؅-V߷?֥Py瑁%6`d$ T(_'㔇 |=‰p+޷48߅4!9ܳ}]s@ҧ$5Y!-vY\굂9)ftb|+~xbt(@dnJ橩e||`) ͝-dtHPffxš~fiU:*!!\F"9HJd/8 UU+k&+_F - )܅_B8'#ę!‰>*X^( ^U |o 7<CWŘd%wܱ% [R$Sb$(,,Kb0l4|8g<|`DMH @L7-AD SX=9c` 1 lKBU tўr7uwop 7pČW&o{$l2%)2ns8cs= F~tK7BDU_5Z d` hͶ nCT7|v#P}7 on0 K8őONy\'w9<:ͥ? 0P>HNvpg5w]rAO}?o~$l7 0D@* p w;8</m" bB1`0=4CÂ8~\h9SWE Ԣ|b xA qk w=wL!>4DO 7BS"H!J*AɔY/&QG \I .ZF leR/ə`g7?K"QH\%?lfR7 IPfQ$g9QN2]s'cyYs_t.N8?И~0e2t&DKV?k^Tozt)J0['J_βQӗMES5o9_v⫘Pe5 $8ɦzv)8s~UV+UƳUlkM-"?)F>Vֺ%FPjCDUBXL 6dӬa[Vљ]Tݬ*GѐjUi`lZ)J95 m[ߺGӚ-I>}o>f[ûp-鰿/rRQ:P=nΦIXsOVc,Yj>Kw'HW m_5~-o.ˊ (.8V8Rn5.uh3S5k?/1^vH lhN׼lv3|f9vs g< $@,MBвt7߲\-Ȃk%>E.>£-kU\Si=vY4 sCku^A b&Nf;N@pj#$ȶmnK[ [ =dZuKhd,:w]_,!wxr3dO#Ԋ5XTO c+WjܰXfHG. l!خ6|Ў9_rk8-osz 4قxwlWDGmh#)I +D5O2й9Fc.ia$;mrr5?ef=s}>1@-(݇G<2:#/J48qus] !UV:x9Zַw݇|1)OEf~mj{|#/':?ybV7o_-#_豞fSv(OgA5hAvlq2{ {g`Xxx |ʧSt|fB7}1W}wsmn6~gx3xy08o2UowyWTLyiz7d7:EUzdegvaeq78UЀ ؅gphjl؆lxHP&'Dw(m$XiÂ-Xx/@}4(69xtaWDH8?[f11EhHGzpIfj@N6W7Yv `{bxAg膺nx$0vx!xwz~ׇ~H~7(~X~H8oyo 8MÉpxzejpheq]XV{G(pȋ9|(lXLj'P5njgnP ZpS=o&EH4MXXU7EvQCg'kŅӏAH0JH9r Srق}Y _@_;Hy!W#I89HJXQ/N^7h;Bhm *Y yNě6I긎Pd9vTHqA@F7kȜ㜇1Y׉%R(ƖGEg $+b nXi"o=TAVWDMD0y3IyJ:kȊA9jANɡs +hٌ(s*z02Jx=(09$L>8DZY?M(IIJMRf;xɩUW{YG٥`:)$xvhl֙9g)p*-:7\ٚz?j@JuiDJ`H  ZApTcө qG`蚮꺮ڮzZqq͗&hjѷId pr:yz >:;j9:MΪjd3 Kj J]܊WʩDia:4;*!JygȯZ  鶫, r1h3zPʰ}8k;y;Qۛ[xَJv'ۭ)U*0;2[x7Awfyugf+h;thfY< J`* +*f[j)D%5mq 8Z*\kʷ&vb ټ뼋Ĺ⹘g鳵 `^9:z0ӺKMԪh+#l码 - [zۿ꺷ȋ^ʫld׋i4뽦K {;d;EK!@ 0{Y;AjXq;A @Ar9TԅrBIrNP /w:T]V3/wZ\]=WTrkPf}hR[4"ʣLʢѤ;Q\U,Q%](M;*h,{2E]@3]9];-fԚDmԞԛLդ`-b^^}ڨ}dֲkMmpE8J\k#Sy|~}d-Qȇعز/رِ=ٳQٖ}ـ١ԝE -ԣ]- Uڬ=W}:=AОrmmL=ɝ0! ѝȌM6{բXݲ: ޘMwnfF-nmM߫-- +Nͽ}| M0~M3>nѝҹ8=$n@&( *==@]0~nFu^6^>;_f9n@j]~s۵ ~mwN02NRM>n&}nC 4ξؘqKm)½RN>Ԋn]؆c^-}ꩾ.ٮ^7->a:綎>NmĮnBNo쏘O1`nP2z]ޞ~* $m9z->X= ?|e>Hy@G9̓M~V^p$U@߷B/ca MU=[^ߍ?$׎O"$mpr_v߶5>8%~?0?ތoN[Mߗ]LεfN`U~&.tȔ:_^@@ DPB :\Qĉ[:]ĘQ-mRH$;RQƓES̖dSΝ5#nTPD}~4-k>5QU=yl e6 m-H\k޽W`N n8q ?~\lmΑ[n}ѳ]U˪@\yŝG|]tխ_Ǟ]vҟ\#Ӓ3/L*iQLJTT_*@C,BPb E+/ 7᫯.3L 1&4,4Q;5-z-vj[ңdI'2J)J2T"<-CBJ,=ڢ=1a/M4'0)P@40,RP º&īJ0P8`#8Vl`Lmjoۑ۪$4HUWUrJYgV[oMJ/Di-56CS4=6sN3+ =ϷBDe 4DI'P4MG#"_}=DRsTz5I"[M.aX%5b't VX0}،;XlM]䒑E hWڮv۲er57]umwKWKP@{7j~Y5a`O1+[~bF;m&19>̶/ YdT^dQ.cuY*i)kfA{g1zݢ>JS駣w֪:``a aaU;vg*=wwLw]x7ߓW~w/%WXfY>tKɃND4?]OI O=^/VOR8@aD`@6Ё 7ka@[B ІF˥O}I>O~ChC07t9:5lb؝шGDbh  }БIR2^b#ihFMr6l0֑5MUvӛe89NriOX0 B\d{y_%RL3cz$7 *O~rT|#Wl6Ԛ,7%:QӢŨey=t^pS|.w9zSh~ &7 :$6tUhPj@!Mz1!{ 6ʃ9 Q b/iϓC*RO3AMi:LXiz͟j쓪t ְ=,SX6ֱe %$;YVLIDf5Yr)mhE;2%EmjUϒֵe >d;[ֶF)(v!<2` h5 QBR/d:P7T5ܘӃu+E;^ngE/bX>6e1Yv?LZumlm;`*CWz+E` pMzOɝA7nk]Tv)^݇/qtΛ^_b1!_Sbr" ҂GF퐉Z0d`飿*RجMrSxyXt!umJsGe1 ;q{w=L_%/YFF &?yQ6NrJe(b; =.uE=jRM`\fYm殊9CοsX0e4h /M4 F;Yʤ,K_Y-tp;iRܦpU "VI33B,4c7ßu8=؍Ev'+hfovvY &CL&0 ]Js N 7mq.qץnbXƌ?,ylg:xNpۗm%CƸl5mm'铗=f9Yw\hwq^*2?teNGՙ詧zַ7S[0G˹<e7ӽuc/o{g4oz s{a W:Jų~e򖗉YF1}O_A2yПfUwѷ <檧y~[L;_{{zp7GƛSCCc>!苾>ͫ"۾R> ?3! 0 3?[ k={:ʻAT?cۿd뿆" @:T8c@=po 5t=H!9,Aֳl?ӹ3d:A9\D"B @)D '&@(yc?|1?=4DRbsAëCLE|?@D@Γ CDPB ?% Fbd5 AZ=B0RaMtNkP3 <*E; kE㛺qT>XEQEBE^EDtbTcLF-e1gD욃 :Fĉ`.XlHFn< «󬪳:r8sCtEu\v@$xGAi|I(zF+Gc@dTF+,#JT,$B4DFɘK9FG|IIItD$H<ݰTȔdpJ̤y*L̫:$Dz* 1ɓdKdI'˹I)KcDɾG,lt{Ĝ,|ʴ̧&ʹNʨDD˴\ ķKG\$AFN$̠,C\L`NM|NSTePudG\tl(͓˽OM.H* ^U`-M m };0WP9cY@uW}\^5_D{֝Wt_E]%hQTĂ6%)&vNV⪅` &^ `` f^`a^ Fa0׶LY_Qm)N_+ΗF}F0-bMXiU@jPmb.Ob*b+b/b-]./12645f=K%8c?spcad|AY~4dDVE!vG^]M4eYbOPQ&eseHcV~[W~EcY[ZEe[TP =cE\A&dg.QD]EX-jNLH_2u]OhȈN&q]P6gMguF v>gw~g]eyV^03e|^06 NɁf;<5^h?d.e/aN FZե#>2U}O@iV.FZSbT igiXF ijjyQNjvܕ=h5^uhfj$bk棅яdPqnk-ipiuixkz{l}t$g^_na^Ȇ~WYzWlϵhlM] kk04֮]>帖kb~giޮgig6e>n6uUTRnF߈F~6݋T_oFVk~iv`Neg~eg=$wq&h;F fgR6FGjhO掎 tq0&qV6q3FqYVq6fqs;q_fl>}qqq!j #oVrNer4u'()'*+,-.O/a"1/so?os%ed L:wgds;+0sGs/o[V\Ot]_`^G`V뾶l5Ed^f/hfhtqkYmnow#-txXwv/Uwuxbfg_%Y&܀'wav6uk_3xTvsxtywӊ؏5o M***cov]Ytx3 opnw7z',{P?spovG_?;pp'{-7}稂DV^[bWukS;35۬Թa=;H/цڋ/Ҏ/ӗ 0ԟ L0\ St#ey1/qdb ,l2)&<]<8ۜsqs@'E}t.4OG U|5KYkMjy=ظ=6#fjͶw";KrD&Z+L[Qj瞯j裗^ :v~촻vxWP+KXo6 "( 6zd+rګg9 /s4d>x 'pVS?~_?o>Dӊ%oVL ŞX0q6Ay}0Q᣾WBL* MBe >: +)"?)HCD>QoR[RE+re/x3Qj\cF$1sd`r:(LyQo@ r֓HEcFݔ(%RdH2@d%&8 'J^*UY(Vkk[ gH|}19!10G #(2 ]42MIPTmn6W 'HCq«<=urg By-=}@.jChB%!IGhC&:ɊPV(67J*vs%"*X!DxyBURvh9)^L4P#vXHUR ΜjPT UZVj2*mg+LJ=Rdk܊9nNU]sp|_ 0brԤ.]lA2B6,YQY\h2ВMiӫ Re 젝FWzU%l+'ۦ6jnsO=&1׸EnrK&|BF]^`v+Rzwo\*Kd.~S[_2o2P/ 'x`1$L /ҙhȰa/13{IΪ,^Ӭf4Ki<6!fI*|r#Vcr aJym&tmXf=$aė.xQ2k>Q 77Nlo{˝Qk1?=>x^:M<+>4=_.76l7|ƧWwyѿ?O飼֗aeOyA_+euh)_mۈ  с[ΠɞݞUA著*wY`}Z'q v`{eV^v!l!vza8!av!!aơvJ:!ҡa(]`  2``힤 aa!] i`Hb)jab"?Ң-a & R_!!`"*bAbb5`Qb%_&&"y͟(~L)#*!+#,!b/֡=b=ޣ=>Q# dm`2*c#:-`C2C\DJj^Ef#5ahyGN傐bH9I;<"LX"MMNN1O2b#PJ^Q:$LbRJ`5ZcSZi aar$U.fUfaVjeIjHWbJ-eY򡆴$ j `ʵ[)0B&B.$BQ2eDZ"E^c*&S bga*&cgnXcB&HdHeWb,~&h!gv&>ZuaZZf֡f fkk"dP1dQ&R.Uo*'p^ a'b'rR(rVH:rettRgfrgwfvfwExʑgjfO'zʦ{6$|f_e5ڧ*g*X'&T&h&$2ht^&^Rv/&0fqʑ'k&ag{f^'nJ$5¨~Ψ (c(:V&R&TgHw##iB0f(֥%_fEho(v)DhJvebcvi$fĺB)"*Vb-&|)f^J*&Rj*ЪFdnj>kN|rVI*X*vZ^g]*+*ت1j箖n)5R[)kF0+:+>>&#ivkz$@ꡦg]>"vkzXR+qrj^ccútl ]IĊ筪ʮjn,k,Ⱥ苚,pʲiˆn%e6(lX~+h"igêelm r1q2%Ԣi^f-9n*Ƭe>(.6ښ&ƭP`6m}'&Rml{ nH`^HRnbnerl{e.vn隮Zf.rnU~&/~ok/`!o:Z:DAJgV`/r/y/-ƪ/n.oonNF-.b-W~0!p*0kBJpsQ0I"+rpz1/0N '-. W0}0ɖoqqh1#.7> E0&"cpW~񚆱1!rlqqc.S+԰ oW'. 2c(2 2*2*3+#o$7㖾$[12.Ӳ**d&or'_/(#)3))ht*?*2+2O2p2--ks.08s06::31("3<r.~q3?s*4O?3ХC0z3z3BK83=:Gt ;GT`Fo4GwG4HH4II4JJ4K43="G?@t@#,"7+42/sR*DK:StEsT؂-U_5VgVo5WwW5XX5YY5Z{5UL[7sMG44OuO .QӲ4`3R'C#kS;5:CuTןTpAZGdO6eWe_ves[5g#+\;\1N5i6 0B 6% k/taR#(SrcT`A;o6pp7qq7r'r/7s7s?qcfw6u\Mio7@66k kQ/6&b3vn/n|Ƿ|7}׷}7~~77tKs6xxyglwoSw{{888Ǹ8׸;x 8g6h/\k?]'/9Ӳ?a3~zDxn6@z=z;t;~y\;y<+7B/O{sv gT6_={('ùz||;ϻ < @>9 >h5kBˣ<;{og|5?,L,'<3|;v׶m/6nS߷އ=ȽߧLk>=臾<҇3};" |ԛ6Szu׍*{w?|y|<[NCjoo|isǟ4uZk3!ˌl A384@f+!jm_ނ Ua9n R!ӎhLR%l'I䋜VX sk`r}2-:L6+-%us2(̑O^y ,^驯^_|@oC؉}vkeeBx9dy4B:. t? /} Ͱط~ _ w?Vl%-ta Cΐ3 gAvf}9AOp GC0 EՐUUvC%Rp|]쀸A!zIXZ 1[X'JuG=RQnbYF #јH4ql&&v%GMn#$+ Q)),Erjt!)R&-I]< _9BF;1Vd2Ac3`R -OKmn+7{M4g#iLu4"F%& n[?>4ؙuS zP1On(GixÉ:2MBQJHҡ]I9RsxM RtU)ajҔ+e* yT4UqU\UOz?TiDV%ujŜ*@J[ʸVWR5u]YDnacWYГ&i`1nlb*6ֱ=h+Љ֮e` /rmZ֠*o[I4%b֖sۗ\fu]nuM.l\Zi^Uw+S4}^oe̷~M v0_wL;om; 8U6&I,ՔEE)vNcϘ-~Sc:c!Sd%/;E]d)OʛSe-o1e11Rf5Af9ϙpRg=O}B9эvyGO҈+iM;pAN{:ԥ6GSTL5[kY7gqZ9׽v_ 6le/>=`_9Ummomhy3wXns*6kw-3["p 0n}qw^O|+~-{ow̸pO @<7=.J-<(/g^ bg-pODf@'>` BL oip!e:@AߤMdoO0+dQF'/0boMcu")^(L{" /(:/d @6MD +0 gp k S p /&"  "   11/Q&~\5P( *,QY#GLI 9sTJaP)0z+mJvpkK1|QbߴQadQjnq?I P(0+.,1 Ai0@0@PmB+p! ! pA_ ,i14/d> qBdP2K` /;veedN KB ~!R"i-0hQ#X *&H*OIR")r) *i"2,]&N䖄D+e,ɲ,3 -kN-U+]S S,r/nf媈22122M0SfR]tR]V|3345i4IsH |ڍᎱ77g66o3774W8ŋpS9 99k9v2K&9e覓::Y;8Dؓ+“# Ǔ:3;/c R#$LV DO>V dlV` OD@3S9򓶌QQݓ/1ADp' LtRtDUA=647;>c0qFM#tcIez44t0H%ItIIqL4J3L<<ϳK K=\ 3g4M͔&`4 mF?aP;O o-K#sK5'8s{xR'SN٪9>r#CA&p`@#PiM O<@A$0)+|uTn*NSWNd@5Tr-wU(4:uﮕUU..Ut)'ZtS1ÕU#ӵSڡ]G]뤮_N^UՊu$S! ``EG`nb+b+2avaHN1E.! ' !N4*BVe_VddKd=.f$Uq">iBt%2KAW cpte' taDUL6`pijQje/dyg}66h_F eOv~1S qn T24to i)" owvmmmKf&FU%P_B%OnBdM|Pv+4%CR6)LWooWWpr/seakV;o"K QuiywH[APAqEGbwzw+WxmxWs7WfvyGP۲((76)V3{-B ;]~WXYٗ7?NpuSPt'a/uqtD+؎s؄SRY؅Q98'8؉&؊x&o~ fp1 2GzoaxS"/pcVcJ?۸+j8xxd bxؒ+*(15?9bǘBaUAW@b%4i4`;d2kE#Q$qwݏ/&Go&C/=!;&$9=yAٛEy*H&YMea-*A!..*2Lb::Z ٔO9f2*9鹞\36.r}Y9 Z*aYm͝ee_]KڎNZSWڨ[)^cڜgڨkڦ ib[3'SکZ):ZZzPSa5(N5ڑZگ˺)Zzڦ-SShS!;{$cڰ9;۰?ZCE:':[ڥ#ڵ) {T{7۳۶[[_[Q/eCG۸kۺo{)zMٹc Z[g[ZLb7m\fr qty‡ Ѓw6 j/?d~\ߞa~?n'q1p 99" Oc9qR!!R"ق3?nY0ᖂ LСā!.[8QbE36G$!V2ʕ,[| 3e4k&B+V|4=r-BpGϞNʵ蹯SHz+(Pn]F ͚D{vGN?>]ɭQHb{ȌVbJ\_Î%7Ō;~ 9ɔ+[ժ@wp~GJVy5Tm[ :äs'Jez M1kTuKI4 HTrX"Vu,jI]|g1' }K\{LJXW6T(R4)g&^}](oaM{@=nJW$-)LZӼj:p2pUEٍ@rP &B/z /pl{߫~pPg x.Wq]1 pr<L9p9$08..Ga K2nE|x<6}{{WXr<-dPA4yln 8H.5@,;9ɵ=zYgP,YB ={x芯(HhXOP8%ak6O4d$AB/ă4jG84 G٨i$qD-3f2`IȎt(`Kp舏 ďJe(IHh .XN uiKcq.  #I%i')+ 3M礑Ifɓ@A)CIEiCy[EEG Q9<UmQoeV!WLՓa# e GwVfEYUnVbVT Օ5`)ido9mBlЖqn`u\P!%VٗdtJsWdP@)=F`f`qpb66 vqe&^c9ٙMy Ϡɜϩ(JsЉhn6gUixinj9dIȩ Ii9myo6 ɝtfWllƙyOIʐ ʡ rɠ4uPN' I rgrr4% (' %w`ZL* `GIK@SȠLJU'y>ћvmojww|A*Jo q*sJujwjXJǧwƴl xj*W~ @r~|j:` ʩ꩟ *Jz yYtJ JjʫhhH8ڪƹP*JJ Ȍ/h:4h,ҸڬŹHjZ؋H**i[E*D4;;D˰Q ZPKk˱p +tQ 2P #˲X(ڨ-kQɳX7 Q pGK A˴8Q2ISPOYkU0] \]OWcKdȵi`b:Vahc e+sKUgWil6qK+V}f5Z j иpf;T=p `r! IBA{rpԀ KD;|(5mww +8q8纲K BUqlB wa ΋K*$k˽S" WkWd-]i ۽ qSځ(mg`ƺk 1?  ,Bl  ¢RA% A(LAk 1,HR79 A3?! BElGIKJ2"?\c^4#;i#.ha$0#-4 5#?xlbd_a]H*\ȰÇ#JHqb3jȱǏ ^ɓ(S48ʗ0cʌ̛8slXΟ@SѣH-MʴӃD/>JhTUjy֯`CvY]Ϫ]s,۷p ^K7ܺxնP3߰#KˆN̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸s͙ޛ <3 .|啛 !dD{y@< /Og/` ϧ@G|' pyWB (* dxxa`@A ba ( 7$c\!,bl#22#>?IC,ChL1ȅȁzȅȁzzȅȁzȁȁz ȁȁȅz," ( zȁȁ;_~Ȃ}xv}z~~ȅȆȃȂȂ3% b; x|}{|}āutv|{}}~ȃȂ|D,w{{{ȃv{xȃȂȆȅȃ}wt}~~|~Ȃv|{Ȇȅ~u.#}wȃȃ~||}~xȃx|ȂwƁEk01;}|~Ȇ~Ltu{{xȂȂȃȁwȅ@*\ȰÇ ŋ3j`@ CȱǑ(S,iR˗YIfB3m꤉3Ο({0Tѐ=!`ӘJڄӫF@ׅ,D%@׳KP%hր<+@w/7;Au:$b5 e9$E*r)qA$g!P;ŠW#Y)HQ wJ$,'tztr'2 !g ;-hPmH @~6Y"T` !? X :ad d g@I6M}C%]$Q4  H@O;N0"!,- A22U𹹹 C- >?I# GHS))501;!!- B;Lt곴)31"%?@JEk   @*\PaJHa+j8"ƈCȓKDɒʕ-c| SfL2ڤ8` aB{X`P  mس¦NJ@0aU PY]~kZm.`AuK0[8p@7pl'8 (8~<Ϟvx fJ^:B>5<;۾[bzm[xn' rK~Nq:u!,& 22U#>?IU CGHS))5- 01;67B!!- B;곴)"%?@JEk   @$P``. !D A7VQaHHq*#flL,i^s&͍&D0@'ipӧ$(ԧ',ը$Ã&= h`Cg\%X 4@QPcaC!,&22-  CUUGHS &&2))5#あꨩ++712<00<[\f8$0‡ hĉ"Ƅ9"`HTIqIHLZ,q w"'B\a@R XeT&`A .kn DxV, , `Ab78+P .͛pAM9 $ޫW)',pf=W !,)~T2122222111111111111111*)('&"%  !!##" !+.>U entwyz{yxwvutrqpomljihgfecba`_^]\[ZYYXWWVVVUUUUUTTTTTTTSSRQPNLJIHFEDDEGKQ`mm}eyVtBs=s;r9q7n5j4g1c/^-Z+V)S&N%J"E@<:50,'"    #    - ='T-h1r7wB~JLNOP$L.H:AC;M0T'}Zxavctjtltouq#{x9vPze}zĪ”˝Л֜ۡH*\ȰÇ#JHŋ3j8PǏ CIɓ(#*󘲥˗0cʜr%K8s܉, ,iУHTBP>xXjͪ`` Ph׳hRd:iԷS^JZx ,߿ `^W^̸A <,bɘ3}0da LK =7=ִ/Q3T͘^ظsb!t B߅?(_|ڲУKL:C ϧnBΞ{mOOH|8~ERgÑ ND ᆮU衄J!$V‰(bX⋤ 4"D.¨cc5(`H CB$ZIFi 5H\nI%CVb)N] 92pBjigKq y% 蠄'B~(H+4裎zPV6*AZ)EbiA~jC,ꪪ'xjkR¯ l K.´VKmnhfm/+~kyû o&֫k1+f7& 7p6WLqegqW4,"lQ$,T0 s4$/׬K6>,4J7mF4IH7]PTWMuXkdSgE9-bmDdl;p wt+xw|w-@<n.x7xGηgy 砇zta騟^aG^:a>VG]\޲'|heJD/;Ko{G M"F!4&:N=*1؆-.zȢX)+VZH1F2*J pCiHjc-cGi쑏v "CkXDlC"rMTdq HV!%/)&.<&;)D`@H(1JR^)4e OR C, b ^ҖN2e0٨E+r 19fzSό4)rXsf6My'<)HR/z45өv @JqR/D:(D j{"4YhC$ю>ħ9GzhtWhGI N0iO>IeK'Ԝ*jjS"4NESsV4ehQ tԉДVUY4#'9U"hM+Z Ͷ_5g7ɉ֕eݑZzVq#fQN­R|0_,+Ql<4T,Vc'nQNBfZU N0?!v?Ah pX8o5(YesņZ֝njWwiՆTe{MSo,Z+`/xQp',+a oO&PM-f$6pXL=dJsH#?PND*[V2*kyH]wf,YGuH׬3ÈpN_g8ϹDvȳ;πγ9h@zCwHCCѐNiHO@f Eo>xG-OӇԨjTʂ~)p(6ڑ# (I2XJR'hM -HRxX &J 5*7ȁxP Cɣ Oꏺ7hj*YT+?I# GHS&&2))5곴++700?I# GHS&&2))5곴++700N1(Kp)SNJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿w J``F,@᫉/Xc+O\Y娙+; s u՝ gpTMܻ  /O`pDЊ Z-(p`@!,QH22>?I#DE>@K #GHSDۻDŽٙ$&&2EF))5ښڙ?ALEFlEFm$$3DFٙGؙؙqEEFEospsȿȻdzqEEGs++7qsFEEڙؙ.MٙpFؘG՗FoFٙE1L?@J00HE%^bFCLȓ!KDɲʕ-c2| SM4k޴SΖ=}<tϢFoL:t)ӝ!F}S ƩTFj+ׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿cJQTÈ+^̸L L˘3k̹sACMӨS.Àװc˞M۶a Nv_μ X@س[?R@4, `護(@˟M4‚ _A߀Ʒ@A1$ 6  @!v` %$h(x%1V th(&P @)dm\P |0@D#r )APd\veS13dJ\P\|]2P ix橧!xPD*餔Vj餅 XqA\!j:װB檫++,ڪ6ˬՠVkVlf[A=C覫춛"ѭ>!`, 0ѭ 7, 6Av`jE؄Cњ7Tlg,|h}1w7psxجWt@P'@@y@~ bT@!,)."22uṹwԇGGiu^z$W㞗x!ھ!޾gwxxGu唫x5{xGx!z\GwĶzு~ b|ab6؄юgxW~ҍTT`ݼ5Yh IyӉ!;¼x{5$x{ 8:EyH*\ȰÇ#JHŋ3jȱ#ǃ CHɓ(S\RK,cʜIM ɳo Jђ97xӧPo&ոT@ԫXj85cխ`Ê}ױhӪm)Ҡkʝkųtk"޽[Èɶ}4D S4 唒'R̹7{M"舢KV}bհ;~:mȳ־pΟ}M㍋+G炛NسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k{ @"0IOf+r9{DHKOMèHЛAԊ+uYH:*s7c(E%  A$a*:o8HyKYvacnkdaiiijjjjjjmmmooooooppptttqwz]yG|3sp Nȓ+_μУKNسkνBp7A[Ͼ˟OϿ H D(Vhfv ($h(,Hqr9BtL^g<@)DiH&L6d|<)QNi%U^S!,`)dihlp)tix|9!q12Baz;ƣh<4裐F*餔Vj饘f馜v駠)j)z)ꪩ^"무j뭸뮼+k&6쬰D KWC7)4.6N`%֣cn=+k,/üL2n騧ꬷ.nG{{;ڦ$7G/Wogw/oډ/?~ټ .s :?;X+ 'L :'H Z̠7 AhA@ Mb dX@`"HL&:PH*ZX̢.z` 'HAMqcܴܷ !$!pNQ314d!@4,合 &,"R@2$ %"CC~dh H6d*d"38l╰,gIZ̥.w^ 0IbL2JNpeDZ>r#h9q;; 1a}DyYO"E,N9Aq22VΐNi8ҐԚC؈ch{-4`X 'MJ[Zm0-#Y 0  ?hp3Z6zѦ5{=1Rф-i*; =kQ:חNj۰@8ЎMj[ζn{MrNng B D!GԔ;ssqOХ ;VV»`W )L Q*`&H #W0gN8Ϲͱ q'HaQ8=/8a GǂX-|G#>[Tzԛ+Es<\Oc,lpNxϻOOozObNo9ௐ璁 Sd GOқOWֻgOϽwق!1{"=mnonB5x4F%l[Ͼ{O~ HD#$12?@>]AƜ`8Xx[@|8 c$yԴo| q @} "8$X&x([g|ʕ|?\4]0q Ű @ )B8DXFxHܷ}0p\0hV58 R qG @b8dXfxh| y73|C5?Ud j8XxEȆЂ8u| gq| qP 0 8Xx{p~\Fhpmke8XxHzЀ`\r(UH9؍PU|`l0mq 8sW  ` LPP`  Lp 7!d@PS@ aI@ ) Y#YP DPUP &9;y ɐ)g0@B8<ِ?ɐG9, S9=yL` 3)FYXIZ8yTy@֗8tYa pk`{ G Ő P`@h4zr@XP@ q%UL`;?)TTI䓪)j . I 9Pf G隰i`IIoY rivٞ'ap{9)z_' 9 z쩖9@pٕzLSIVZɡH*ٝ>0 89IɞrH89"$:3))g9&j@p TZV:k{y-  ` 0 Ơ #iU jSZ@PB9<ɕaʜi Z::@٤:y( `jd`::3zj0ݹ`K Yj|NВ`0ٓԪZ ٫ɚ:Zz蚮꺮ڮ:ZJWYڗ׎hz_ @fj:mjoq l3/ FJU! H9,ȕ<*PZ ZXipXz F#˫újLk(;?+; zL` ` Z;DP4ۧ`+}*Iyr;t[v{xz گa:ezix vڠ'ڧ]ɕ٢S YEj JڝFʞI";/ ggJG۴L˪:Y*pkB3ɻl ,IJG1齭 ;Z|껾۾z{]+klZ*t {QɐŹX9ٜk0J <J< L鵰Ԁ/:Z꣼:лNf+ ,UO{% 9̔ +ˤķ V|XZ* a +U;u树Zػ(ڛ٤DVxչ||kɛD +Ȏ⻼n*ܻ6K\#\M9<œfZ}ߥߢmmࣈݸ- ">$^&~(*,.02>4^6~8:=M;^F~HJLNP!]R\^`b>PNhבt0qlPNt^v~xz$n懈棭 | p@膎Z.>.Nh鷭՚ H>^N^D^>>~ͫ^~i=s)xNhh킞sF.gH .Bs?_nnRZZj/OzbE O_"l/o߷0/:}9oIH(*57o};4?MOX{=!D(|IP/QPWro{:CKhiuT?1[zۏzO s RS_._$x ?@oo_/_zlCPz?]Ș_EO޿oPoPB@ DPB >QD%NqD|<~RHmҨ7-]SL5miS=}T(mEEtPM>UTU^:B"mꕭ]Ì)7ϝ:s}k.[^JE /[Q=IF>ͣݿ_=ǯgJO#(D0Ac+",b-./[0z#7A1EWdE[|=fFo,'>^GᣧE$rH"*#d&t&2Ԏ>tKH4Q1$L3DL#3±M7߄"ӤN; 25o.TOA%0(N*6 '0zCw6SO?5TO3NSOE9EeVRtPd5W]'8 p;<#8bWJ/=*SWvSReL5[m mjV=%&m \u=W) JGRR1u'8`&8`wJ6a~H~ 8bS#s a8ɣ@cOVDQbԻ{Q&Z'gwg9-"2! $bNi0zhfZZY0jN *[oF:i"^ZX齏&^z6{VBmnpz3qs;4)?A޸cPψ"9g*aCkf}穧xgxRڀ>6HY~}ڬl"Vo7."qOj:pZ'|ɓ_ro~`A?Y-}0p$DN~+`@Uns匶>\ LD5τ',. Bド5CІ7B08=$tψG(a]Qx 射Ҁ _bglB@W3li W8ʑ~ktZ}d\4Ap`"H;m t`CF;D`"3"#"EYl gA*bջ%VۺK,=i^[1vBH3jWgPTo/jWN d0& fQT#O}(fW0!0`}|"\AU܉>$~m`@^4OQ:\ϑE ?+Dr7IK!#l<oBாe.+E/{_Y@%M0yT}7UH3M*0m) 1W*7z.cE@ uKMڥ)ia-.NZ֐;2E¬{,7v'Y@K'E  ^*S=e,˰M&H[Wrz%f!Rkhz*rg0! 3`䩌dGxp+ V8aW2v6Xp'i`M1䔻cb`g]T~Rq\$3G72Cl7݆5o9޶wf&|y_Gr2|*ٮ1 Sxܭ2pc|?x;< C|?BeҭtgN_%ݰ.3)p+LF1Tzַ}p׾FJ[{<"WhFOҡ~yjͿyW?A/0݊~UA?~G4|ʇ~|P0QqAZ"|c';c y2a`4c= 20 @XBL4} bA, (` p!\ TmH% |kHA(D` >d>8B3DOB MP_P_PMH D'-=̊)@!?> 7؉XPĚЃ244H\ЄC(KĒ89TD\OPE<|BBDEú+4{IE0XYZ[Œy]dU{'^Ĉ\$b4cDdTƤf _>wR,a\jklVrnh4:4^r4sDtEodGpB;TTyz{|%vFw$@CGTǀȁ$HunG@ Fj,Ȇtȇ4'ltƄcIeigȎȏL HfH`FrɕdɖC*ƓqEɝIʓII]IqGBɤTʥtljW,JxFʫtəTJQ˱$˲4˳D˴T˵d˶t˷˸˹˺˻˼˽˾˿J!|GtFtDŽȔɤʴ̬LDůt$4DL$D\H^Tؔ٤ڴͶdM>t͔$4N=M|tMB K4DTOO($O\Ol|f|:<EP@8K0EUeu гdCQC`:E F?0?p в !%R 5KF8URqE0>xݐ)*ؘ<K@3/01S4EUm̃%<0":;j6è=eSi2 {u9FZen>БcnMcܲkzNcnc&Vgl#`FFGl}G}eFiD3WVpdQ=<~ m&m6UdEdNh]6fXK0^_\|[g-7vf4F_k&˵|_ ﺮ)/8&@[hi{g òE~Hg<ln>o ٝhi׶!dfkՁKLMN?qC_Z fUb~CUgu c2w]g}X-6]wr`]_`\=YwPPRUuVwS:;wHMe>pP!)"-h"1ʘVӡfjٹ]l&m8P.y$I*fD:$Aaxc ?Hb32%a9]yfS򷡎~## fdy'y}y=(bZ':(J:h_< "Rz :*~z*TYZenW*zkokRIYƙ(z,*S:렙b ':6j-z-;.{.骻..;/;A; -Wyh\۾ +0 ;0K<1kqk<)Vi([ι1h|2)2- 05qR[6s2A =4E-s48;-"3U[}5Ykmva贴؂m6m_+i]! +wW7 >8&=߉ߗǯkQ>9[6fpCǸVkM]~:ꩫ~uQ-;S;N>gC}v#;;{Ff|Cn=Q{=OO2sT8>ou3(~2@Ot<[( Rk38Lj C(s![%ԜS8.y ! c(rSYO>m-!ԡ@ 2#"̔fD"}sE]0cS\`-"E0h? XAv# <"n|lc.uv $$#Y4BbА)Mrre%χIG11ּjfWD6yMm2|暢|/ 6sϛc'>e)ϊwf>}֭;HTa=(:߸\(FP=tdFCjƍҲh)ER-v&Jaҙ2{bK46NsQExIzTzANԩRzjzQruV5Vդv*zrϬnZVzoꮹ+`uj~U^`ޫ*=+S=2إx-j 'Zu:HJo[ [[3ζunѥ[Vv=ւ[nC.t\1UgʝFq,?{0λ.(~s}˦/~U&_їׅ##[KoANԨ# 6;T 6M"#+Mvf2C)Q ˾19'⒒W&V\cWŻzqd㴮إ6:Yj&tFv]oToG~p %39Ȓf;A -kr1 MHm+-/̨j,J٩n6=GƠ3Ǭan|2 h< :V:_uсs:LѣVV[N--Sw{6S}6n;[F7"ٻnQ*6}׬O+!dw ¯-&?,9(ߛaNr,w$?^ΔW2g] o\'+a=t1Ox!.sXy}.s*=ML'4m {O:vG(yק޴SH#R"4AvޕwZlÝ^'~>)#__~|c5xM/t=sЏVἳTvֳC;-{w}}z'A~;swƥ^W9 3 ?i[7B?~]#w?Ѹ_V߾ _tF .g4 J  UjfM!h9Oqa|}`D!jy!J*_g ֡E^!Qb e! "҉"*#6UġE[M"%%J&&R#'V(6(I))b**U++vI,fb~&&a' -N,a-F/b..F/f_1*U00BI3v3a4>4rU5~5:I6R6^a771*Z2B2_9T8>8I;:9Z::E<<;"a>>T??H@@`AATBB.O#9Z]bCF:GzZH6EDHI&IFV'$RФ٤Rd褫dFH5Xȑ %d *1%:eRBIeQ$XaeVRe r%yeXeZOh儸Z$ɛ$]r]%[a_r_r"^jSa͙։2\"e_flevf`V&hf&beiQX&dޠ&]fj9g`v|'jzj rJėmnrLUgE ttki`vtgzrdGfsF'|mndL3ʧ'EYOЙweppgfA\w>{Ng$a;~(RY}*rVs̋hFgnvLBy((ڨ"'ub*!B ބ((\.}4(h  ¨Zih~j^*fUhzہnirZzi}z''}ީWy$*<Frb!QYre"2j*.&&R*wg:*VByH*ajQd&sjdurffh^*ʦ&yy2kfk'e[~jbgfy&vVf{(vZ'v( V~r(_ޫ_6*|(߸꫆iq6Zj>+*q.*.in,`t,~2s9z$,kkɒjQ"cN,Vj|+D̜FlZR+fnk2ک ,S*tЪt թVꑊQ\**%#v-۞(Pҭ©"mN2.2Rؚllyl:nbim2a ʆl"nڍ>nrmnn[V>m&לvۂ>*I(*n.zm6-.pTNV-~~nVoQ,NofMl>lk\6.RBpoZ-n.0 cZo3p"{r0ps Cp m_o2'VZpiC ְ0R~+ op11Oq[q/+#Ja10v /˰qqWq32 ;r$s1Rp2.rW"1'gq _ln2v2)2,r,)k*lݎl"r-, 3-q Z0GN1?3,'0G/-q3q0S3 r#C8B_&+3g3ss5s81K2W0 ޭN±,q;_-Ƣƪp 1?&3J&BK>f^CnVMnstE~tbb*۬Nt@5Ǎn.;[mή#-FL$I7IN2"LRo/kW3K3WK-†-0R.T;T+;cm*Uo1>3:{\+:tߢRᲴ..7[4VKqbSVSr9/@#zrX35M4d+6/۱=OsWaLsXgii%7uתfu.w6s[si=ϳhi?%F(Zv8uffA7$su7ug5dn#7p: g?t/rw_8_v3uk{ӷ)uF5C/4ZTXU7\a 8b׷f߷jYJovmk25Bvow\o]7 uH5xi_po8p3~t ;CA4{8wwh[E4/Ljug;:sCC3v|ok88/86t x9yw_y?w/8|#K9 pxc4N۵תstN9MF[y+D7/Ny.n+_z9'4*z`{673z2Kzy!2@o>`z:az#gwC';/c9gz'x:[{{;`w%軾;ˁЁ;'l&@"lA$g]n"(B#D&l'B*+̂-.[= c%}㓾?A>0sme3=;A$4" BPs_=ԾT6㛾+טyw.~*8߽㗾@$E_&$TaC!F8bEnӸcGA9dI'QTeK/aœB6ovrF?:9thPG&UiSOn!DEҴT^Ͳk/v5UT$h!Tw %o_y5gbǏ!GY*UXr V,ٳhղu WnQnȘukׯa~YXjewoN+Wukׯaǖ=vm۷qױg׾%{s |y_&xgf~^Y(c-?ciL(,;H6 k*Ѡ#h4SPI,C P@C$a(p4a Kk+( Bsae',(R&<,j.{ g,>#;LrI-7S9b;S쨂(c234&'US{ Ҕ*)MSa p>PD! qD(X#/ȇACZTS*0!zԧ^g}]z?=_da /wkf2Br}K^"?|u?51;"pOv|vM,_# -105;P?dEp!ho ӏ"oi0\"Patpy}0pN0Wro\0/j0 /># p ,a@"px 0 -B0p "R0 ! ^- 4 /np#/"4q9/ Q &a P'aQ,qg7 1 V yOcqdiKQ [1_JGq LY 0qOiQ׀ ` QMowӐ  :ir1 2"5 &! =L"9m(t,R {Q#?$M$Q21Bِ$S%a2&eR" -%g'}')LhL2)r)UN(o(9)*22ӠR2+2,G(+ʸrR,r-xȲr-*۲..O-A..!/30SYj r0s13F s+y1%s2)ml(0+3=32,#4M4Q)43S5a5W3J36m6Ss66q7}s2uS321830()9-S.s5:&+ S9:S;J= =!A24@2=3R8?tA4; ;395:TS:z;{;{;{;{;{ɻ;UyY[YݚL8g];{۽[;<| <|!<%|)-1<5|9=A~ >~!>%~)-1>5~9cg=yP"ϡ+Y]a>e~imq>u~y}>~艾>~陾>~bI> +b Q>U>~ɾ>~پ>~>~? ,h} 1 ?%)-1?59=A?EIMQ?UY]a?ei_ q}?????u " ?ٿ?? <0… :|1ĉ+Zpƍ;z#Ƒ$K<2ʕ,[| 3̙4kڼ3ΝC!,<522BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JH3jȱǏ 1ɓ(S 9ɕ0cʜ˒4s= zҦ@D*]QLJ]ԫX{Vi֯`Qn@kسh3lڷp@@ܻx} 4pT_yi@^<@a FfL9LȬ $ S=@հ:XpB۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔VjiqPdi j0ꏥ*ʪA2긪X+ jcrk:~Z,:[c@!,)|22<=F! EEO%$0((3㼻**5YYa=>G곴/.9 !H0@ȰC,|H+jDxč !1Ǝ$?8eɕQT ̑^4xs;9hС#Z.e*tDX@g`kSTpY L$ o@BރG3]<.&U[baX^^Ʌ.M^4qzR^0FP  _cQ]`a d/.9(<%dqh1*Lh‡#)b3j1 %DI@$$\ɲ˗.IPCrɳϟ,l MѣH*]TÒP vi@իXfհFԡRKٳg58rMʝK]jXh떤 Lp ;ǐ#KL2z2^XϠC=2śF)װc6}ZsjLͻ߿`|ÂXμСcI% 營N=q;l 1˟O>TX?D* (he WS-Vhf!yx4":L,.^!@#B(D )Di)G3̅J#9"7h=AbaʋAKrN.MɌN"8k@^OLh>_ cLi?`"6hOa#8  /.9k@dMd%7#cB C)h)&Ld 5L!B@JP12Ƞ)r:)B?qHU $\@E D`l €aF PY{[>F0. H@_? !`"V\  `  '0P~HA!,,22m= ~Tx,ԇ}  ~SvI\!z<=F|EEO2xΝ)((3%$0!x8yM'$**5.ŕ,z7=>GYYaΕю.3S_w9#Sn=㳴~&@܄Lɯ4.M0Z\0F/##4E/.9{+&~ O[P')HAR !A0*Hqhܨ1 CɍZ>\)pJƓ0318ˁ[ɳdTa$H*]PJ5"(D`ׯ`@ٳdټ耂 p AKKݿd1p/߰k_㯒' G$'``wsg?8fIconA2۸a >pa '(@]]S6Q p/0Av`m^  | gG]ETAEeU_Y*@D` V`RvMDqgtc "aM!Š8\1P0d<8c,d!(BG")K" h`~R6 e,ibH: <!,M+,DUSL=Ƭ"Ȯʐ ~nM& ,9&B6B@9@1622222202Pu[~m{txuſoڹx}ʪٖQ4,GUi޼ôúǹǩƧǽdzǨƟƱǮǶ³Ǫǧǧ}ƶņȊȎDŽuynȕqǮvǾpu}ʼnǜ~ƣy|zoooafm7V7L&Y0Q+U.S@5M3 &,x6N."@,V6r%LTTYhu8+ ұ$Ȯ:ʗ60lUF *=IOc\asX@x{(5>Ð>s8y!ɚӳ 2SUU-HA6*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cx͛gɳϟ@ JѣH*iANPJJիXjʵׯ`ÊKٳhӪ]˶ץpʝKH5mp·( LÈ+^̸ǐ#KLʘ_YΠCg^)ӨS^ͺװc˞M۸sͻ gM{LУKNسkνK_$u_G{_ȟOϿ(h& 6`l' Ffv ($h(,vH0b48c8#i-@)DiH&L6PF)TViXfj޴r=ǡdihlp)tixH|gg'#袌6裐F*餔Vj饘f馜v駠*ꨤjAҗC^&dA Za&뮼+k&H:>KN v+k覫+kzhM soaA4G,Wlgw L1#"l1&|1*Ɉ 4l8<@-DmH'L7ܢ|kBy,mhlp-tmx睶#z6~6nߎ|7G.Wngw砇.褗nCk5B'1<`v* ;xьo?7G/Wogw#kq@{o/@ʘAL秿C< OL:'H Z̠7z Ex:nfQ \ǐ%DvCP0 =tsȁY 9X&:PH*ZX̢+>b`hFؾ.Q_!Dvax4 H_  XBL"F:򑐌$'IJZ̤&7Nz !xơ*43r7H#"/J0Ibih`.l2M3~co~ @JЂTvC!M`BluS[*;  !.e<_<}Je-T*S8ͩN1ʼnE}AfX# h:giLSE`/@S u|KBT(GmZzD1oy1ݩZ#ʼnZp\J׺xͫ^׾ `KMb=a ehT`|0J V S@3/&ь(qS>@Q͜S9~4"U[.NPm3~1B~.0֗׆ιJnXͰ>~(npO|Kͯ~LN?~[{Ȧ 5z6 )Pp8)b;`s 2<o/ir<3qL"HN&;P T(3bI-OUcw@qQ9iCx9YՌsk|Bʷ(F;ѐ'MJ[Ҙδ7N{ӠGMRzv00<e'<˃7pE-] U{&e _Ԃ`*_Ģv.] q,CMrNvߝZ"ʨŵMmkWEw^8{讷mli/­lj G8}x#mk(W7o0gN8Ϲw@ЇNHykҚUlY]+8A-{`NhOpNxϻr A%(%eQaF}Sz8ػ'O[ϼ7{=->鄯oQͶ*xBϽw[ЃN _R}CϾ{?oCV}~7x JuϿ0WN750R:W7XxyPHY|&uT{g-v 284X6xw  z0Sx'x) <,w8؄NPR8gw @B%Xx 5lp{TxhjlV(Y8WbHle؆z|؇~h9p 0q +`+y]lp &b h_zg%p{ p i0P0Y7A p@Z0!H# cp8 (R0p ((8 hȊ՘8H r@p@ 8苤PݘXXZȎ Ȋx1(y v%Cpqauz`,p=D`HP~qE艠v Y39` Ø@Y99X 8 DGi<铽?)8)TWَW Mٔ V6؏8Eh8ٌ؋5(Six{w Yyr^ב!9%y)|4 9r@qv)i I y)9ɈXɛ[Bɍ9y=9XQwyi#yGYY ,0w阏 )$i(k{.ٙ1yv6 cuYṍap Ha:PEbYd頴hm) mPW0 eHPAєa d@ J 2J#P pP46:B JqP0*x(7j ڤ:/ Ȥ2/ ꍢ1tZvzxz )~ Pwya)Yə0.jˆɔ8RV׉8)≪ڋh^;M!Y2ڍdXT.N*!p y6jZ:3 PzΪ ;ڤZJzȹ:ZJ}}@ vIj@2 $Jcp9 ؗyie@ۡȎ +Ū+Jeј3 5MW}ٓ4y7! ?;Q7KA8M/Kk} Y9a+(I@L rl۶npr;m |P-)i)ذYƘd zcPIۜ[o)x@:M9-Z⺮!!H@H;;r+!M!ˌM Me{½h[[:R{蛾껾#qw{%t;-EYhXٝ9k*精ێl ,ckЙ2!KDI&h&+*f­F r0éhËkX.\&kMy&=f"M`% c`-Zi/ĨDF0 &M\&X@W,ƷeBlnprL(z}kZ*Y(aʸIpɑˊR ̸KThɓr@ i:c+Ѩ+r`e+LDD˹R "lʿ+<)˾ܢ(h̰lD̓ʱ,[|ͯ<-^~ CC“;_3%֢-M=1.~&M&UM߸aT6~8:<7.QKB;Pg8vݿxzM[ CضaGu2d^f~hjln/sYD^~阞隮Iz+t9uH!yQ稍Q/)~Hs茧,HZ(%`yX>^~Ȟʾ>^~؞ھn쾮N|\h^~}!ia2[w{~j?_ ?_jj|+N^ ^⭎񾐲n[-<>@B?D_FHJLNPR?T_VX_wp+'),MwR݇s [vxz|~?_/p|UPWB8h~^2 yQ)%Vy@?_=zgo13o?_ؿ jFJ%87XE 5!5} ٟ!E@ Dx"Ds玝'PPE1bXRH%MDRJ-]SL5EJTH 7z!bI(mE +T|ڑ#wjĚU֓6UvtWBmݾW\uśW^}X0`^%L͸G-_ƜY8u T(QH2u U*U]u%T}\pōG#EBsǶ=ƞ]vX=3Т&:ԪW+FK#P"0@$@Z!c"T#&B +4F+ϠNK5ZDkȲ>NpFk$wG2Hxq!#:.ʈ# M2J)/0<+([)I6b1?9D 7߄s9kiAH;3O=HÜ>|" LEeT*C4LKXsQMGөʺ̴D NE5UT1OW_5VYk&i-^YkC'۴Xc TJEM; T=($5 rdT=BZpY5HfQ X挻(g_8^yg_ W[XG;H?Pɮ6bTJI=t6hgE=ٓOF&k\zA[UR!\a<]hW.x7^-f|iZ^t%\ndI&9dO<&l*Â>|B)" $ "J^Lۘ lfHXI{OWC 㕻s?}%V |vX((B0K4v[_ln֛| y 4;XEҢD22*] ]u&$ -|E? qu% AX:YnC`p,9w:t@ny[<n{UB\O$D@}UnH..L{BZCj?bm¿DoKXкB"xe,D/2EXx :9<ό4+שL8}t,07Q|#9)_mvd6S ɬxG™1bƑcz_xGX1slce@rҗ$, ̓$2l LfZhےfXʹ'$0)F! r*bY Za|`eTin};gzM4J!MbL.N\A%g6kwWɉD`fg 7vp2{J~#xus5)::TnG!Jȇ*OPNY4"HU|e1Ve V6sl$"V (FѺziIzpְ- zPW66ouh2XʚUt FZY 6mOk`oJ5j1Ik(2-H.[I+5Ze Ũ0*0`m ${F.mS'[v o)+G7hr\T׺{\BJG1#W̕@[/UVx0/.XjiH;w8}] ,ndp7)pGxp(H lj#^tX[%/"hxUr/y͋g .E9`0-8no?[)m - b̀09!sWWzֵs^,7_F[E1pй8gNpriow{wn21_iWS^3;wW|MssYρ~-=P]^Wy!Ԥy}^M L`(GE/jIzκ>*hF5W~ x]>F>Qg]miq |3ך>$Tʂv/*&Ocr>S0 ;bs@࿷+;X2ݘ=A?5|6t)t"c<}k=940Jm+<uD@KDA/B7lsDD1u4Uuٹţ8v1Ee_^\fDL$b@MB *·A@Q>k;VD T>3v_Ş9W"sTE`nFcy>dLFfDE@FŐ"lD]䩞EIJ2oTHeFS$xljHڳ{|ƵFjD0pV,CdaD H<ȕ|HȊəܻHNH ER<Ŗ4p8T, p GZCtutJS4J8ɖʭʮʯ˰˱$˲u1˴䶰dpɛ 12{9+u)qX^xŔ]E1P̒$̫ss@ʴLtHLxxДM}Ї|@|dM|ׄM,b0ڴMd`` 4NDTLLN\\dN|pN;44mPdOooop$rr0Ps̷6\EEPAI3KjL?ąɤˬLLMҔLMlՌMۼMtM<-\N|TNNO OTd&uOOO PdPl3PknsFl;  L Px=?mABQETTQQHN!mI #%OMfTPņQRSEqPUVusjUY=|6[ UPU^5_Pb:dE=>MgMhuQijkeTm}TnVp5RqL5WkTuev}OSRTWVmW}W6 X"%a>AlIEp1D؄P8mXLcat`~_.M֝ E_&N['Nn!NT>n`F޽ c.kn+c^5Z6neB*RSO}ccE]b5caA@-bDNEGfTJnLmxU^+/.ekYYm;4.aWX7Y|Hc^a?fEV=-d"]_gV&Q`jTKMkfLfo ,=gj+/ lKTm)ܖ\wފ{e}mㄜjii6jFjjcjvn޶ >P;Qv]dC]E]F~b(nJJdk ^,MvՒFR>cUvF없i鶢i;i^6NXnvj l̦jhmF NNm> N׆ؖmfmm"m&nm.jh:Vւ6N^~fhvToVhNWmh(b.h6tlk]ju^e.Nflx!gE(\NN0DnlVRl& pV Oݞ p&m6q?kÅVwpxfbm b]#&[%^nT߅茮M` WV ro45oo$eRF ?Jk[p?O9m жp p >m 't>C'gLqҴqqE谥6[N^[^$.xg(_&\*GVg+/l,njlh]^_ujhliO8sR/6Wp8GO9;<j?s@mtBqCGWt}etqIXqM-[%ttiޝQdsMr%7^Nof^ (c}ojrVib \׆v/8v<3W0s0xvh7Oiͮvkpvsnpv wqmr/>wcNuwvwwx_d."ߴw rHwnKx6xVބoޅoQ~fe jmȆ{j`G3ysksk{s_y y/myym"?fEonxztje`!r.r?ԁ'YoU6W^X^Tloˈ׆hXiy/GDS|W3%cGw|<ȯɧ|@D٢ojw?I{,f 2TC`' `"ƌ6r#H ,$ʓ V|%"Фi&:un'oB 7(ҤGɕk괜QIa*֬6p]תZǒE2TH?}ܹc^/`Ѵe+l0Ċk70Ȓ'Sl2̚7o,nB$Pnk-XPiG,Nܩ7Cz="SڷsǓ'=+'h׳oY Pؓ6p : r Zx Z :za:!%)#-8>18#>xA5BEDQE QGEtH%RJ,2TS7Y8QF)|O5%TbYW`ygZgZj\reW^z `='z(yhjlنn(vZqݱ\s*`Uݹꪄ*j骫꫄Z k*dq!"h*"0H# A9dK2yRNBeLTڄ:i\vH)&P*ViUggZL)o5W]wiz챠zz:2%٢Vi&kW6[m[o'd"szG *ؽtvtx:zz|5{`NJ`˚Mac= R{bf-m;[}-Ѻ $ do@)U^ PE8?Uo0X njM\q1A}-t̏~#ɨ{$@Tᔔ 0&g ZNK;عL;S IwI Vf!h| 8|adѠ!, <W(Oxp[S3IUО?"HsTVE]NjNw2:gt6nג<1zЃnv7>\$ܺA>0&B$Y ^nED0L#DX&IHQ ±Vc,)әj&a/H`>1=Ό4Cj\I.z?` 'I2hL'w=#1)0 h@t (A8 N& 5/ETS,Q0,(|@g .!Z.}) cђ/6!/S`x-mPf;xR2N}*4*UrPҸj8ǸUuիJc:fg=ֵ\Gޕy]^%2z$$Qy)Z,U]3 bVl@A2=.Dr}6UHGM6LS+VaTr\n@*lc:{UgE.Wky 2\XG>RsaAxetM=SG?:&EJY*xv0o PR0a ́^ag>4h -ъ#mhHKє/DkzӇkl8cݱmDld"!px]2!3UldPkfYL[N~Oث@(YX_ "{QWʹ3u;FΓpsø(A0C(˾7}c[7.] }R]Pzq_`WXVJ}rl&o:KB`sݶfv%TBQ*%U.uxVfVnVV:#!\=<֣=c!I%2㓡MPN6 $A'.4~ _ y*F N/REN$H>i.cGB&$JZKhƤMMdOfO$Q&QNeUΦ0eTfT&mRpoWXBX&"YcgD' R?Ve@v:T(`6a>a]+*zg}b$||b&i''hupgi聮f.kRhuHi^h憂e;q(=h>[h\(tN"%*%ҥ֨_wS'yNz:cB/.ia12hf)in)u|uUF:()W):Ʃq~(کHBhstV"uj@"*v'2"|+ZÏbD!bjrj4GǨAj^ǪNje&ުT*"Vj+"(+\A\Jk&b'^B#eB~&+̎+Q*bZj+e\Ίj^gKdkNl2(&H:2#R;|絣؆^+Z=ڮ=0ĭ nlQ.Q-JȒlɦn:CSt+Fl,lDb,Ί fk^Ƽ֫-LkҲ*z0mk^fJ-Vnf:!׺C؎mY-Ţ-۲-۾m @DZk᢬n/8XYwba6˦䂫@~zjf.IV驚.n2VW%2vׂu/ D&.: FDebr/ gzZI/z,0į~c&$&kS6qƇ**BĚ-Vp/+;o~%f kC pⲰ8:.0 ֬DIM%^|r$1/!SFdk?CqSn^e7?lkoJ^ sl* o3)M0k624+rg4C#oNr%%i&/(([h'{8O(֒Pמˍ*rr,H?shr.-2/I 0G30C:2c2f5o4gLsG0G Anp$ ow3~󁆳ڪ'jU.*sK?t@@F//B#13XD 2" B!A؁ j@AHex",`HInKSX.7oh %Nnv:sPG..Q;gQw*R75>kl@Tv?3@cu.^Ac@W{5cdoXw/C:Yˮu5\5]5^5_Ga_7ruW&5g]a4JJ3KosLKvbvfgN7:cThvi*#uRv2uSml϶m'TunnlA6p׎p~7_u279w\u]u^u5v_v5wawbby$+L({M&}N4zH-9}7~sqr=x=lӶO5_<8ExW/7C{x[GSw8{wy۸cac6N:7ڢgZgc?ڣ[c)H;68#x{XUWB_8y/79 8tt8x;if+J :!.;7; g\:gz*szwYloyzzzp/tq:S4/txu{_+;'{c;=~k?w\s|m<ȇ#4}sٟ_pۇ{;݇3K9C=k7C~IS~?[tɃ}؋}C,˼?7>`>a} > >~j/{#?+?@0@ &<8aÆ FQ[EeԸ#pA9R:,ܑe/mĔ9s&.k7qifO3y-BTO;&Txa#ǎAA WfպkW_;lYgѦUkD`qiԩP՛wf-XPiG,NܩŖqcǏVM = 8NB~4tiӧ9Fj֯Sӄ lԵmƝnޱCL7<:չS9syϟϓ>}:=׭Ӿ}=6|yW^@{ /`_BH@.5)$H:If6tx &tК - -:*K*LYla4- K lKl,r-( 4c3@N+88/ 3-cd3LSM5ɜ7SN9;SO=? 4:(CE3mGm34\C0]訛O㎻HS[OUU#@O#? p 4LZI%:PR& 5̉Cgi(R)n+E# WqUkƸ2.w/#0+^r63gR,`\SaaSbbA MTDcH%,=.ӓ7TPETRQEuՙhUfپZ gwWm~6aK: qDOjꪧm&j 1[ {.!;Fub/w{HzDnU_'À.˄N̆n͈'Ί/<7|?}dOnnSyT^]~ԘϣyU/Veyy(h{-`AZbi8e-(dZj8lF먻vmٮmmyyޗ~Xp 7`_q9Mr41yc .Fa*eQX׉vS;ۍwѝz׻AdhFWakbF!,TjA>- j%GU\`^V[٪ȫ8kLEŹov;+U6n}L4%+JSRԚج63]!:,e)O~ I]*OK685}QvUeo`v] no)Q /+̶pTnHJW'ͫ^$iR}v o"`xJ^vEez{m|fM ҞU_`%/,>lˈ2P\_k[?WԹ&.4ELG31LkX3$$ccXv:/zSX=qC!B\zUoQҕvruбjp/Ma阕Yf9iN=f8<,3bx{3'kc˶,hgbvhS>5hKV3q(YmO5uq)\a^xq?TFV՚udֺss ޞ*r2.o\YA[D;d _Gڡś]qRvAm4.CqcTrGM}LT1]ǿQ57U|Y/γ|pywpA?80~q[j>ёCb-þ?>7rӭn䲻ݲye<ݼr9ؽ?sm@ p |HO#@?"Q@pCO@a֡t_O[9LGۜF=ެ$v9s45ߣ9ǾRs7/CKzlwUM]gڷߴF6/oxsCmgio4ktlp-׊.fn o?teْ 9Oj/ڶZ8Joo'ڥlh1}0p0 Q`fצ|-"&o,0OPVpR'/v0  0-z00 CP9!QJvVaWIw:rLo ;8Rư ]:./Uq\ؐXobmq10 io6^aŞOVabQv# 1o>>o KѱHZq,˂u1mQ1Q'9zq qYgUi_%mg8"qW MMm ɰ_0UEo%g1m`tr'y'}'&r֌|q 92T!g"# #V"1r@1Cp oxz $C2I$a.%ݰ.H&Ƣ@m(S@ 03131r0(rr)03U'2 ϣ*+R"7Є2,d,,ѲՒ$DRJDqR&7/7lP_9YC& Sa:::0sJN9W#R 's2!3s3=<@*r&"59@,,;he6=-wsA8s ]A-8,BNaC9C=CDtDIDKN!EUtEYE#:B);e`;9p4GutGwNG4HTHH4ITS<ϳs=W=ɣ*WAt>Es4"+2?Ss5?]5q@  7MaHB+^N'/gOC4C CCDDQEE_0cTFFmG1S}tH9uHTIAUIM$I!JtJ3;ZUYU_UT*cVTG4KsgN s?'Lt _6IAڔr3&TtZa-l3N)'8aPP\!Q5]Q]!RR+U;$S5G7S>5TF52TU_AUW:Z`VcViu< Vq5WkW'+UL?5-7BdMukZ4OS[}"\C\ ]UQ]^'U^R^5_S_A5`r`M`a:ab1Kb+bwW47c%XU#HVYO$R6V6ZSfTf5BfE#guV4x\}gOT4]_Z`j6r/Ui3iHEjUjTjV3ak6Vl2&b-b4LclvoςUX!mߖ#Ք#$nNeNZNBrAW6Bwp;4qwDqWq#wrr[r1G5wsi=IAw|tKkSXwlc>#2cw v'kwy7|@Rn7eY㔵4%WBW/c8B{7T{w]{!:!Wrŗj|WGW}sWTwI)a!t7_cleL? 9`8"A6dEHd?bVyQN7A;5dM{Y]Xcx옆kGoX}w1`~Q׈uɶl2mq7!i{wasX!m.yf4,IɍWYEWY77w}&j63vy857ywwCYI֋+XeQږwoY7]y8aخBm9C ׄAT4RQWxUԗ8exU4pSuXta~7u8W)y"Yٛy5œ8`zYC1hmXNQ.umJ[ԃ8i,Y6eW6{sV'wkؘW'yVX;#KGH>FK"uSz\da:dzni:1xW2i[0k򗔺ppugy{_Ԫhz|z_sz٢1~:ךZ3mGy:Mگ:{ ;]y.[%Tˤ/g3[]7q; B{16'-a_{c{lڮ{9 X[; tۦ[%p7홖oO؟{z_TTu8V;ռϛ[ٵٽZ庾{ᶯ|6|{ONX ^QE5~sU}[_͑xUA'c^o5o[-}>љ[eY*~gq^k}>Ja}6=KMh~/>}؉~WQYI ?UaU?'+1 w>>߰CɘKٱn[{[ r~>OA>۾-?w?퍿~?M?J$F#,PS+Z1ƍ;z2ȑ$K ʕ,Wz 櫙4k3'V<{b4UD=JҥKS9ME TNj*k\Iyuر8=6Zں} ܹt?7޻+X-UZ@-ŊQ?yP⅍;z!bI(P,>:լ[~ ;ٴk۾;ݧk%*A"%chbO Sܻ&= >ۻtW_[WрvRa- ,5=NSOB] RTOA5UTUYU@VpX*%Z.WqU^6W 6Xa} cB&#IIFeiYqVwRNIeV^m'q=r5\tUuefGA)ĐCI'g~  Jhh,h:(ECi^ziqA~ *j kEފ+j*5 6MS"6$cEtd]f}y\nދoۖ qbIsIG]ao)ޜى^^|1n1~1<2|222ΜZX`$,Mk,C)kL}T#"Z -jm~KWW涴.GAX!$Lk wr{o60s0j I^ّ/?> O$_N(oީ,n04΅̒;s?A͡J!M;"aIMuVψ\Zo͵ׄd6d}.)ݤ}]77p ϾmGyw8Cα䔃l9$k9yt,`f:LuaJ:lvn;CҚF+RZr<%oy{_6tM/&o{؝yma̔ LL$fY~=PU<@]ā`; Rv4 uZV5fI Bk^gHE]8\Ljr&#-}$X8U,qTb|hFg4Ҍa;X5'v8T"( zFqQchC?%FN-:L~Q MDZ*hRiXҗ.iMmZGBRi&6uRQtԉ ~[_e(SjzdR jU Ue,jQbVWlm[cx+*W^~- `]:ְؘ|cw IJI{%? +R9KJϊaU?7*ÊjU~umYq+LR$A(G;JY*.IQW菀d_ J=M;8#d;׋Æ3yGO|;PF~߆((kvLrS /#fX拔?"ɞJ-EN}c[9Ccyd&L6'`$S!ܽ/Z7+&u2ۥ:};zqBvϥ^y"+o>h8h06cQh\4ɿt/ͦʹSd:W[oTtўF k -4nM; +s(T |2OE kz{ķ2HU_}&hgyl5s\I7a~4)Io6A~e[ܞ6$nS0ݡa|n#598vw^ķMӵuM}sUlk֊V-v#e?٫mr0B9W.u%w{)~> r,tKed'bz|H>ߟk/ApƃklVrW\)c/Ӿ3Drb{'cwh Ȁ!mu}q~TqzzPSrăBz{Qj-B^Swsgfqz0k/؀9;ȃ=7yiQ;gvGivҁM)~FXqG.W.'*Ȃf_/1JoC?kȆmJfq5&z4چ'ńM89Yϩ:}3],9;M==?A Y DFU[f\LQT]*>Fyzȗ69ْr4)} r,|7l-ʼp rݫ ] {ݹJԀN Χ,]Έs W͑9Ǎȍ kMڥmڨ-\]ͱ-} kA*KػU۟Pu,mf̝=o ,wm^lG-۳M۵ݳ3<ޒhմض{|-͵lnmߨA-]ڽݡlú ~ N5ތέr=Ma !]|P M*,N.孭ͭl_ h͊]?}@DI-Dqn;J~M^ O-pL_}tancen皌{L 68\].ˊ뱾.:<,? 䙎#v.z\,(S/N@j뷮<뻮UlR.qN`,ǎy}>اαnVXt2ݮ޾nR 徸#n~+P x# 3O5o79;=?A/CO8 -KW?Ȟʾ[ N)+-moq/sOuowy{}_b3SUX ZM~C'?d_h?R/Ы=p[O/,T)gNQ H/Oo_ >SW? ( $Xp`% Zb,lLXѢ \4nQE!y-BTO;&Txa#ǎAA  9uOA%ZQI.eԩZ 1F̙5Hڕk/ZXӎ1XS[q"Az>xXaĉ/fcȑ%O\e̙#"LYEfxiԧ1fuLeϦ]۶&ܹuo"^qɕs&M^ݺA*$c;H&QdL6qΥ_}':U+",b˭tЩkb0":CCqDK4DSTqE[t <\ѡr|mGmLzrH4r9$L.:&3h3<,RZTsM6|?2S(:+r6#K/L0j!bFuQH#tRJ+Q/~RN;4M=uTR%%bjqQU؀U!kH\eW^{E$JbrJ*TqYheˉTO P>@[p9mΉ|}wB 07xW~ywxPBI4b]4A7~!|827B8|M_~?p6B%2q-\$79`Yf9t訅0.[K;|xwB*Rt.)NO w;z^!zC QC$bxD$T=/2rANTXf!Jl׃L:&%Vדb8.2qLbxG< !ES.q $>0deA`sؠg:JZIK]LhCPiS evN]áE e-myK\R,!֌9QSlpi7ZŊ) gRo\2}9Mi2 C/Mp=#H@G*d!D*I!9IV!%A[JS'WyPU3 4í+Ok%(@hG=QT#(6JFMn'Ԥ1=iJg78pԤ۬NIRUCi>jDS vF7Y<Y9z6ґ'%~Ο@9tkek}:롨][Uѱ _;A_WV%la WPQD1BV}CcŠ6573ʞֳemk]5v'~|lw͜g~SA/pӟ>A?s^w"X vk_ 2USj>l<ǡ>;@þ><= ? )ۣ?!3>LA\AL)@0=MAs@\@ :@@ڣ|3A%ld[B@B+BS>NNBAϳAA5DEhC B-t5i@[)iB?B>$ *BCDLD`7>PĤ۵KBWlFPEt;?g fEnFC\ \ErE_> Fu7dcQTF$4jǥĢ={ XF HGqGrO=Xm%6nMAօeUhX Ye%Պ@zבmYuؒ=֓5vuV"}YّYY~mU=ZWZa eю5ԤZץeZ%TFmج[VR4֟ZZf%Zײ[5ѭU[d[u[[[[ ڋZ'֍Z}[[m\>eW-ڏu\D]}?dmU\MέWZ՝]MAmݣ{]w]]]9Ҫ]M^}:}+ޕ=ޜ]^\k^U6FX __-_=_^jueCąj_____]ߧKG<~kA6C=[} Q}[=J`a_DHHa^ana^Z aVDP`~aaa&Yմ`Afa'~-ak{TL+b,GhA*Zb0-(5#CbWT%&b7b)6u/,޶㦨c;b<ֵ"63` ]EUM\^|cH~86=fZ@Ld@L?.JNFMe$d{%d5dXE ]G6d\IPV @^8@eH`bbdV84FE59elDfP1^^)>PِTpgr6gc6?Uh_WNMXfolzKg hSQ2^nfgq`S_0hP.3`Y>|hx.zi>j֔\," `&77}){}!hKm2iiuiF Pjc pr闶ę6&fh/fhe_hn.ft#F. ,j &k_&얞s-BvZ…e^eFeEnkHhJ0Rnl8hPPh|h>#Ğkzؾi!~f"l{|f>L>Vm7~븆j'&Ɨ$#fžeP%i`X6@nγn^h6oln+N%rm0o !.i X ''O?nm]W؝empY wbpni&jn֨;hw2P%0&m'gVh(.mr,g-/U.q g-r^f&3Wnfnvsk/ w,w|b.NEȁbwsvք@w_}Ha4O`Y' %wO*\`<>zNz[nz%6/ZͦzzpGzw{!MHǘ@V{o~{@k%{o?̄&oMA_0_xf0r袊/0_^oyȧiɟ|L.qq%?-88"㶁O/mį؏ڷ}L'q8}{Gk}~|~k~gsD\vplmi@1 *@C-BKă6*4q$ɒ&OLr%˖._ŒW6o̩s'Ϟ6- *t(ѢF"kB1 9vB$PX+v,ٲfϢMv-۶n+w.ݺvJTH 7n E „Ixт vĝZw/cά$H  ()ke}pT6L768crA>kΝt:֍};w@LϣO>D_/>Ze.m4ԪWsXX"qW_i`b9dYgCi,j5"0/ 8G43-.$C b3oE<2t9פON]wSRwPH"-p٥_|Ue*+i)o~IsSNA%UVa`Zh] QXH-cMV*"hfjUZ啥~ȁ$$j 򚄭0'{秀"n胋za^(vȬiJb(~bJB{䩩ݪfK஽Z 6K/{~zg`n[/묢NبfH)S,W詊rܱǦ&p'k.ղ2( 3- W(7LNCC]%"cB+7[˙bF'6m6 rBF͒y\,ҀFJ+J4COn]_MؘB1|B'1Uޞ /&Mlω/ӟm1C曋yLE2iRE)ۅX˜!~UCPzy>6^4aB|(Z7.v+藒 +`>]*hA aģĚ "lyU WJhBVMzK 8 d'J%7|ZXvH@"A!hD@ql ]\:/7q`8N8<"K< 3Qj\, Jx%B]zܣTB ^Xy'Q>Ňm +iI1ą0@ѣH/d|Me]X ApVD %/yI%NXf_%HG ŴkȺcgB()#$"xFi|83DgHF"YkO`"LeYdyEHRi: vrg2qaÌ#8=C̜\4;ѠLTKD n i8QaY4gH_jjӛ$!irE) OVŕe($iӧ@ ͝јѫbUh1ebuP%Gj֔T!i #H_.XIW 5}s{yʃN5g[X;L2YB3)N6-m9aⶶ-oamI$IrYV(^_a d$^LohzWh0#E;U"UТQ@WS؛]O]A-qc0jU-q%m~rrC\" P$!HGH"xӧ#!Ñu1DRXS$2amr#?}K0(98i#2My,ٰOypiGh?Љ[羸'l}FR`:z2}(C҇yL_,/|W .m,jX%|GbE#ъ6_;]H[(jPn=KԨ㴩mkۙփ1ꗔq 5&kVjGy%nr^6ط]blq4ZͮI; J+Nqү8oq5/ԪJ$]/1Gesg;_Å俷脻⓽o/`oT:ٯ}%=E_=Q`^[‘6 N. r Z` N FٙҜ ` _qު!غan[aX!t ".*Z@#*"N&-Ÿ-V ..!//Z"0 B!b2@*+.+,v"'N5~'"(v!&(V01F2&E^:;Gi_93ai#2a5.s͖p dl@&$s-dr5q=p#)m `ɜIEfdHvFrWx<*=!4¢4!@*L 99勾 $dO^J~ $?B*$M:$tQ[ Of\ĽJPJV~3Q"e>>` J"]S%DZMeQT$ ،WG]]֌%XX`R $6a6[2fRĥH%Qe M%xLfTfM`6#aa.RʢZ[k5fkB%EFW?(툎lfmnȩ$fia#S&k5˹t"cR9>na)Q􏏝- /0OP`ϐK yy5qe'r:D>2'jNs]Ar)hDW@6(D¦OvbI'RX`qQxzQL$VDYڊ& !`L(]~#7\"8fb-V#^؆JRnvc+ARђ-ҋ^AlSuY(Re$E](Jh"% F)[J'%>-FN)f#6n6vZw 6ـD~bE@@ђABxibӛijS]b_*ff%.i*i.k6k^*<V, Bʪ l~"֫+b"RiB&k]JQ)lh$}zqC=ƌ ƪXL --Ԃ `ijribZjFg/, mmmNLnj9(yYYeAύQ,)[-ڮm[ԙ!+6gj-tfX_F!^`*, q.$oyf֣qnkͮkk#+lZdɄ~iZ}t| 6f.(%m6ݹoYB]~ƁU/=Qp"z# S -Kj&ndO%OC]K&׵0Le)Ba>0GNWp_j0Y$ށ11߹.5>1 +k_qz1`ݹ#<< :2p%B-Sgqnwq&_#Rgk&#CI2꫰-c2kr's'#. p)G)h*G*:g%+2/3o,/?0ì0*/4,{r-821uQ5[a611 (:1%q/0%*A^f($@7W3AӖ1; 3<_YγNr"+7FÄ:GCC*˳) q3tK3 WCH7w-LGSLԴMosI/'=ñ=%uSۀOoP; 5QN=3T4TsWaU[a5ju25H{HuZX5ݞFF55u\/\R^[s^L[v_{`ZvbSaP(e%rfkfG',6cc+5d5J 2gjvkk"B"Hvnnv"(Bքh_ict].j'W*r3ws;sCwtKtS7O(0tup7r pqrFIxՃGf͛9wthhAH@Ԩ3^L끛W l1% t=;5pݩ=bn˙7݃N\ըW~{v۹WiÓ'=6|(LDz usRQ_ԂN :mƬ\V j(2 )r *Rݕ^}BK-܂kRz<C["2jApr=t͢76t'^8H-Ͱp7eG"P},I7`3$=߈EXaa՛喵+tC5 b,rA7B%I.d? "izGh-ZI})eW g s>[,%k[eZiѾ{+ku̶m ?ρ4@fz( (/p'/&'܋L=q]}Hru=qZ]Y'iNfc4ghK/FOܼޚ5Z)B~XIٻh_&z|-w T@>#< x+ءi&t+ 骃)T ]2?bX(V7P;֏ZAXD#Ib.D'>QXE+  愉B8xCdq[g±qě f?H_制cXHCTdNrFl>[cJ(]L÷Q,B3!ʻ~!N:a.yK_0YLcT/o`ZVPќd& Wl&I6g`n H"pvqL!ܠq ;4Ni@F$wTh5(ID$YQB j`[ #QZ8g`O6lS_PQo<":Q APZTIURT>DEw⾊ބQVԩ^բB_77FЅH1QgA`,4i g V` [XÆl7؎#"(ԕwc1WYhI[Zӂu'9PBvX'm:2W@guzZp6zUa+mmYPn$v]~8M^+mR,}f95ym5 jR{# 8$]o{ƷmP}8'm[ ,\{ ]3 9q!`G )WaUnA6xygNqm(Љ^tIWҙ68oQԩq4Yg8;n][>q,t"iWvo/kR #yw3z\Ag][qw1)O6a9y}@w2&&WYv# ^Gpmw^y A_|W ^!_}ѓ'[#esC| ܆_n>  ! P#GR!4"pȪOo.zJpCE x"j7BUj++ t'!].+Ÿe_ w @L DOqdH p loa<4~{6"=RP Pa.m ^.RgpѯT Q\Ld&&\PB|A^(w BQGKQ_J1C"uޠ% %G zJPQPњ–!J VAэ!QEK%pZvctvpES% r`f&k&o'ig6`arR(&s ')F`t``>^]ta2\(H #qmJp-J2q0%Ұd../._ d4d'R0.o(!u@g{vf"'6+Arhq<Rے.Os`5[5_0g0622#3BR. >-~AAΏ-Q9+ dS:::;S;S0 <Óh#p77bJA9[9??@T@@;s2=q3Œȯ,44SC B>DCTDGDKDOEK.J&j閖 Fc)*/4 o-%'oCܭD ITItY&iBˠ 7oT7QGÌG+T|T%> LH؜ MTMؠ 'ԩJA3ζ3͏Vr@L˔P 2OTK# QBy-^GuL S;UQbZiQOoBRMS=Vc5@UGwTQR nAAXu kPeUYU`N4GsUt>a u\\,a fO4H7YU^NZ :JLԂDU^$F5xbT`9b, N Bn@x^b<NeSVeWe[e_f[a*p^_X`o FdXa)b'bVVy,`cUbcAVdGv+Xfcfqt-x6}Vh5Ga^@J`^n ijQ`Tc`kpq7dk*g?tgg6hGmw@nGwCy!NEUWp+p!bWvgvs]qcqalE,+mo 0onnDt9y'26j50p*\+f{,@xY"wbw#:'riN1C"y%y,6ljbpz+paX7·#WcrVr˖r-7a6:WL xAGK؄OSXW[؅_cXgk؆osXw{؇ Y9j *p 4˗ׂVm5xc`Nʭ !UX؍X瘎؎X؏Y ِYX5UvjoW*poѓI]C4FٔK!Xy}W7}"VaX[X٘YٙYٚY*A[ aA(70K5*pAϑ6|9XCCfw:W8= p[ +ڢ/3Z7;ڣ?CZGKڤOSZW[ڥ_3ZU`VT+yBBBٝ!1I``J|B=ZB*!Hx`wAZr:z C k9~C`uZ皮ڮZگ[ ۰[ߺ[[ c)>Tk+ׅa%E$$tG\v`YYlӫWOAay> @[۹[ۺ[ۻ[Ǜ˛l-_5vyBsAwȁH qDv{ P e[&j! ALnǤ#o{}ϯV!"KӚKOS\W[_c\gkos\w{ȃ`բ-"t@)仧۾;2"4nqQ |Ɓ`C<=v\WK%g9ˋ\xSo\] ]#]'+2=D|=wTk؅EE{޴=)׿0x3\Hⷃj.OS_W[_c_gkos_wBq ,cG= q1I($~͟~95wC1E_P'+3)f_aڭ, c9娧ꬷ.n{9 .o's.uL/ogw.K._觏E/oT<"G &@ ‚dv:' @*oGGH @J8̡B pa dHLHP/"*ZX"ArPһ H2hENiH:hP<8 yXXϺַ{`NhOpNxϻc:In4},dR0}9]ϼ7{GOқOWֻgOϽwW}۾W ' |B|N[Ͼ{OOOϿK^(E+xWx|y8Xx؁ "8$X&x(*,؂.0284X6X ^d@x˖1ЗFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjhHx>h'nxlz|؇~8XxRxn=_Fq}UaUw؉8Xx؊8Xx؋xG!6`@p7ʸ،8Xxؘڸ؍8Xx蘎긎؎8xrHA֌؏9Yy ِ9Yy Jё "9$Y&y(*,ْ.0K4Y6y8:<ٓ>@YLDYFyHJLٔN|OR9TYVyXZR^`b9dY4fjlٖnVp9tYvyx9#zٗ~ɓ!,T122>?I#h,-,01;23W$V3H7Q3C7L3P;Y74U>;;T7778\;>>I>Y>JAE@!!-wx@6X6M4G;?;W;J:R:EA::P7S6I3N0@7;6F=@@R;I0;7I=Y=G>_>E;D3M/N666,-MJ9T0?3Z9T=@;R>J>Z>B>X;G0F4A7O0[:C:>4E9I@K;S;L6U2S/94A4J3G6L7<7AAF:V:J0=3E3F;R=-.N%%1H>P2H2O7C9B=M=]=C>==C2K2@3B6W4>9ABlV9N9?:D;^>L;O:J4R4S099Q9M7H*\ȰÇ#JHŋQxƏ CIɓ%(cʜIML@7 J1xtOFJJ hibӪ`Ê*4r)! ڐKnUCT@r޺`ÈcaDLB(p Xp‰3k,т=j LуC̹מeTeR .v$hI=&0@#K>U˛\ٲ({@Ze#h?Ͽ?UQ#+ E9PIP E(H~}$ $At0(RD@Pi8b4F @*$$(! D`BTVy%@A DVi% 0eAA\b)f@!,u22>?I,GHS 01;&&2))5Dhh,,ꨩ++700?IhU,ب01;67BGHS1"&&2))5곴++7)#?@J00<[\f;$@*D"ƒ#F, @3Xƈ@#ĐdBa˃0c")͛s4ȳOAt(A>*)QXb0eUO`ҦMSn̺o.E0 I碵@׺ @ >&4B (}HLv#6%:F!,22𹹹>?Ih, #GHS))5&&2곴)++7FGQ00<01;?@JƦ0@ (DPC >tQD/ " $ FN, @+ <ʍ2 &Μ;d@%CrL;ӨR3 UT [r*5 .im[5(ix z4]x`B* l @BX`@!,J22xxCf{xx xy7xy9=J輽f vvDf􀺾GHS))5f {ff:>JNJ67B凵iiK>>` ttE۳&&2f۰//hqqGkkJ.7H"fɳhf-7G#++7>?I#EE]QQW{~~\\QFGQz{|11g`c. ooŮMMY䇲++j00<^^P̊.7G恷ӲR""n4rrFH1Ơ@ K#JHŋ3j(ǖ:B D(S\W0c^a͛5eϟ@Q2@h/-*]0wJJU XôkW'(TK6% Lɀ۷p%dGlٻx)M  ly'&LTK S3%#SCaCͨǞhb(ѡIoH @x{2 F'%ppfv#z]c @.{`8b9Ns؁0aWyx _@@-7 ZTh=PB- . * Vh!vB dpCQhtxɊ, !'Jfr#B Ii$h¤=  /YI@*8b%Mr6ptfJA+7*@k`o*`衈rl' T+rWv~@ si+f0Ea EHj Bf*HB#,4 ], N mR.㦫+k,l? 7'LWܰYqG ,$p/kϠb `3H^vth{QM;kаʮͻ7۟s(_|9УCҳkwϓ_Ͼ}ͻO`Ȟg f F(o 8džva ؘ$n((U")"Z+z4FǍ8c<ؒ@D$E&dEx4N.) AieTf@WZP9`)dfxǙhBbfp6g*˝xg/qI s&4Πj(~&jj"t裏**i{vTj饖$˦vꩧ3aꩨz*jꭦ뮻*뱬 FdzF *K8,춬IV rkjs+nj{ko,8K￉!/ Un6l`qdK,n,|${\-,!\a!4ϼ I?ߐoٟ)O} HA< 6r0}ˠaH `H#PL*ZV.zZ0֯ hLhFqp#۸>9t$>1 HiᐈL$" ,8|$#JZ򒖜NzD'GP L*Si߭l@Zڲ-wI\n 0y_N L2I3iˌ&2g, ̦6)X3o '6o]|9զv&G5xڳ'=6~,> Ђay3hA6jD'JщBkͨD/5fUhEAJ5(=)IҖtHLgJә´g<ȩNwӛl@ PS @-tԦ:J-SԨ,XͪVjՋmXp@ֲbmYJִ2ku+zVxͫ^jWzxWU@m ajG 6*d'KvlJ*Y^lI:ϮchIKYӞ fKֵGl6HoytH 2(q[Zw]G8K]\׺]7V]~=:N9/z[T8-+;>(V 7aHb`x- O!Q$tq;$< 7.&c81ɔx[q\c!Y2<%%Rr򏡼$)U2d-'^&h>36yevs#9ϙ5=9}L#A32t"E. 'MICEδ/"Mg(tA}"QS"WU:D_ "Yǚuq!]򵫁-!aϚe#;͎ Xؾ6n[{ ꀸMq@N] urwyှ}{? ?8|qx!N X8rn=ru(OW0gN8Ϲw@ЇNtEHwUSGm(q uLǪձuk$]vs#1 X:2o5@sw=r_3Վu L0BD2 7|f|I^=w#{3sD?"ZozԳh}k?x;,U|4B>O|_eQ>'[^,^)o] '"T "Ate rw{wwznwg(Bt Bxt-/OvaC)‚/!TGa₃ƒ9Y!CHa„I脯!SHa^ …ᅬ](db8vgX6fZӆJҀ8|hJi(%Wtq|'~}臓I"}G7~EGgp~W{w~~xE{XQxRwz}g ZHB n8Xq(ʸ͈XӸxHȅ݈HȄ刄HHm' gɷGvwx(0yljPz(uizGihxw^W}9hwG y7sQp@| ;)w&i ~" xGDy3zSI4 P P SAWYɐ k)_d? 0P 6z 6%h؈ڨȘ(Hh舙ꨙș?IBCM1 ",,8tꨩ++7KLW00(yrd`&`3Aoeӓx!,P822>?I#>@K #GHSDEttDۻٙ&&2))5EEFߜښڙEFlmnEF$ӖFٙG3DFؙؙqEEFpsos3dzEqEGەsHH++7qFsEEڙ.MnٙpFؘG՗FoFEٙE00kT"Eo#|@ϻd1]  C)0t2Ah0 e,Q& B"!,/ 22>?I >@KGHS))5DE#A3&&2JKU곴!"-++7ɞ.Mؙ+"?@JؙU<@,\`C `ADLp@F:fP (t0-_FE5    9T ) tI `@Q& !?( D !,M+)=HJJ =5*2121212222222222226W?=A62(n.X3I6?7?7>5?2?~~~|}~~~~~~&~#w ]PE %0Mbp7zEJ7>EB/ <O]hgb \s]>aaUbeeghhiiijjjjjjkkkllloooppppppuut~ohŘ`ɣn޴3HA*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cx͛gɳϟ@ JѣH*i:PJJիXjʵׯ`ÊKٳhӪ]˶W`pʝKݻx˷߿ LÈ+^̸D5ՁG2tz Nȓ+_μУKNسkνBp2+k'JIJd30Ё(7УOP S!`H:'H Z̠7b4E@P  2NPp#x-)@ QHL&:PH*ZX̢.z` E12*Om{>`H! p0px:A fp3Ђ,PKI"bO !fD`("# 9!\';,gIZ̥.w^ 0IbL2O20>Yq\G9bv23fq0Q&S A اz̧>T0ER?>O0͐nZ!B;S)x؉4SͨKx HGJҒ(MJWҖ0LgJӚ8ͩN-q^™iM6f~À0 ]ȁQD&a4,ta3a&9 ,3+!=qx+䰼Gfp+ZЉst-_ yr%`=PVL3·XV A&Vֹ*toիj'6D⵰lgKͭnw pKMr [IP w=9#!|a "AXM4v f7N{}-$Ѓ;WmЃ" enc;ÀJ:^a .-5ҋ.GLDWh3iIkˆ5ζn{MrNv=z_8"QGHoF 7fj-.jQ &C|CABBoc(ĉ-<0gN8Ϲwgݣ\ V`i8Xx X_0|? ddyDp'}' q@ 0 h׀$X&x(*,؂ |7gNU Ӡ @ ` cFxHJL؄N~_S8 ٥U~ POxhjl؆nx~_lfwGޔU `oXxJ @ V(T7hѷTC} o p @Xxy@uHyX|FÉolPmk8Xx_P@Y|p} oЋ؍x BAч{APQApzY(nq r0t\ P E`A G 07Q&@h`3I !Y#9%W`-i !ipZZZZAǗ  * @ z @ Iۥ蠘 )!07) y*4yG0P J%ZGٜ񨅺Sj8j^­{> ^ك޵] "~~8.0%n'<>@B>D^F~HJLNPR>T^V~X3^5߯ Y>d^f~hjln?=r z|~rtnu0q>^~>䅮n= 0~ꨞꪾ;). ^꺾M( Nyʾ~j춎ھnnkߞ^.~N_fm*,n?_el.i5q68- _Mѯ6"~ (*O2o !1߫8LI;?9ϯT=_'_KdOGOFHYg/p[?cٸOn_{8?Hxo`gP{Cjhi_c__{./+O߂o.Oog?ONz:_+vDm_z?o/ -(_kOЏs\߄qO@ ːPB >QD-^ĘQF=*'JD 1f԰q7:x K-Z\z3L,QTRat" %jgڵ1UhE\pŅZ԰r͝?]ۆ(Ǟ={Ɇ^x͟G^zݶ;V|grdɓ)W|)j)z): ?=ЮB C6C?QDi(WLHE!g ?4 F؄3N93M d mNA'Hɂ'QEeQGutMRK/KH7qdHA3H75UUGS4J 5W;5ckpU9\rp~6Xa%Xa)SeeRM6h?=SWJԃ[X}c8`# oP_ޘm6_}Y{5Pe 5` ;aqOZ"f1^?9dG&9dp7eWnˎK9fu!1 9xƂgWysV H8Io:kkeBx"m*"lmfV촟 \ Bюp%?\ͦ`Np'OB/OU͒/vkftک޹gɀW ":ޗg"wSu@BѦ{?c'Q@?}6FC Z**O*T=bu_XeNpWp򗺹)n% R@]O3Fume` %0@vT\ χ?^/1D"*ÒD&6щy@'b|*uyWĜF=!*W^ц~ Aخ,1 l  P!L9)oU yAnpKAANlWABJ 'L` Y7+)J$9' Ca-} C9r|P$Df2E!A0@ @ 33<ӚQ{`333)#L3M p&d@[G g@c@F5mz檘 B-I؀(6iVԢ(Qm0˹g+#M\6iR,?yҲQ2(`F U ̤ Su._Mҗ2s `I\ QS _%&$UMDbnLo=:"@h&0|)gɧ]MqX,bϮ@| ?@GP*L^(uV3jl6ZkT`mle;[ٶ 6uOq^cW#a vvۛ,'5uvba "h+ςO4RAE<<OJřx7|T|%yszuA|ЂӦ{zycPFu{4Byk) 1rBg~i`>O*TX |XMQx)ZO~?W2?& @P42C@-f8 @`᫿ !f fAA:{ #D 9eAT  D$܍,'¸z*T d8;?K?+T (Ea ̌a&!t7 GG`BB >//č4Dx 1䍪pH 6lC8KT2 NDX<<ÐR4SD@\VBt=S(WLU[\]^,ZFKҢE_DdTedftƄ hpɴlNgnop"i$ad@1WudvtwErFsdABA|}~D&yFzFF4ȃDȄ|G FYeu-O<@E(@X@  !%"5#E ]GuRtGX>+,Q M01%253{';$;<=еT9}REX:87@`FuGHT 4US`S,d2Om:Q%R5Su)U>ԓ CŌ@H[\]]ͺTELNcEVdUTefug)MiWUKDXOoo=` VA,ka`QVxy}Vim{OyUVo ׀ q-8W|Tu{}״ׇ؈S{]XvkU/͌n؎Wr-X8ئLشAٔYVuٗ җQٚ%ג׵4] `=cm]Z4&c>_$@d a;-+~N~b &&$݊]u2[!840Ȅ+gBe<qUPsrQFKR6Xy:YN0&!'3X!b-Tp)#ƥJm7҄(6P5f\-ePtZ;[xvdAnuvmPwgM:d}&`F\gc{Ngza{~P]Zh6\|+FRnpƆB(m޺jF0fFKei]N"ЄքY߅~X҄e&U&h#~A=Ԛ-v`Np/25]лߍ~$``EJkkl@Ć[46l书Vh~fg]KF>X&mւ/-d]>jûeyrmTXmh^+jMHȄnO`Kjn FA^6H3"75S{k\eP4.o5\ul^d-d..~>_{chNd?o ^5~]??oӕɎV657;.FNY6q>,n"HNefˠ rff >A, 5 rj*ЭF%$r&hFvy[~]=r5wE\v`nVl uFo]sD6ps&P WR 6"ptp՞a׆q"tt[n}N+uMT=jV[['r#fjf"sʑLⲖCd9*PC_$HuvE<]l]F_h]_&wEGvk!_h;wЀgh`^nK>dx:LHmQ^x^Oxq#pZsrfÛֻdVO]@Trj輙[vxٜyRX~?ZW"oH5˿ҝ܊߰P'"R>WH_N+X`g_G@%WzcvW'մ7oYf qU|gz?@%3<0WԿgׇ}$_ڷg nOn}}CMK;A%tWc׏]DhDBXЄP0okCzbBP24}}WU(h „ 2l!Ĉ'Rh"FBr4Ȑ"G,i20G6 T̘2gҬi&Μ:w$%РB-j( J2m)TM#Rj*֬r+ذbǒ-k,Zc$rT(Wt;ƌ6nƙCްazEKQo%ʒ1i'Sll:?3ТG. ڎWn5ز'}ܺw;wA1m8ʗ3)ҧl:ڷsᄊ۸sͻ NN>? 8 x ַ :|߹\tم^|`b9dxR "-"18#+x#9ȝUHm;*]M:$QJ9%UJ$Yjewy!{ 7|[ym&q9'ky'u)e}螈'Oѹ(:(q&:)r`9$桖")z*F'*~ 9Fiy+k ;ifI&J;-R,.h,aJd"KZ{.骫j{Ϊl/N/ɂ | ;0.<1K췝,71!:Oמe+Km«Of:~;uSJG]ooV+<}<' O/\X{=.}slMgPc߶w/>Ӭ?|+x_X2FC(A\m r̗\H.yCc1`g<>af!̆F _WN|"SPIf(r^$f1Z,^:ʆ=-Vn|#X\c=DuVG;}\8>2O M AàMP4(iEK^0<$*S9MG$% wDUҲLp?W:d m)aN01xiC_*r|&4CLdP5dmr3o5GM6걛 #)RST~7]dRjΥ{6gRhVjP۷[=0:rD+\U֡a=$?NƵZ=ӯe$`'X}l;2, JRr֋%eXv|OCnִgiZjH3ݾ0|X[-"p='ܜ<{չ] t)]Q7˻/z'Ip`z{K2o{/7zom+JԲfu]C_~0[W0GQ*Y 8jfaŌ.S 6*|7rLcM? %Kq$2z=&S9B,=&U~b<-Sf'+1$c,g0:yk^7=0͠ <>Z~-&= Eі! *wQzutGMsyln UR%::V:&06cmj֥խ5o\K֞6]Mb;m׷QU+{'.-ZTN⵳euh5n˕dõۮn5o^ZX# #Τ5QKo]okk|{gX~av$!!^f!`~!V Bd "v!v b(#$%VbY@bdb2"q^"wm"))*^*"Xxb|Ţ,z-f-.⥴bs"0>.b 11cS$,c*"9cZ@#H#,R#Y#Z`hu57f8 8:9z9J:#7*\9E;;:Zc==W>:>J??c@@VAAZJBBbCVCVDDRJEEbFNFVGG&JHvHrbI"IrVJVJIKBK:bLL>VMMINNaOOVPPIQQaRI6~, -eY%=biqe'zeX %eZPm`ձYUeƝ]^Sn_[`(9eaRaZc[dv`jIee^&nuM&2j3flf}1emn2Effofp'gn&Eam*g1Zf~Q'Y9biguZ'r. x's'5wvn.W>z!w玨giw^obh޴'~~v (܍'4Q<{.&ej&>u0:}BhIZ(,(g\ kNe-S0iy|ih (NʍSȑ集&߅ehΞ+bni*Eʉ).*륩 h"(iJ 9)^J*0n*vQUPF)Vi_&}&ꈊr**hjogaf6(2ibj k굞갦j|:f꯮h+ngc爨urk2fRf*k*V*uk~nktk§rzHn'6ƨt)l+,9vwfŚ'ÎF琞Ǧ,k썴l뉬b¨^i,)i:k!f,j>kbjlҎ㰨m*fZkՒm(Զ뷲+-Fj7>j̩آ+r' .2)rn>֞J_iެ܂M~jiV.B_l5v.-nzkv-6F*֭Zj-n&/>/F^.R+*onMꟲoș߆Znm/&΢jpzEo:p{nz悯NoVo2Kpp p +po}oeg0 0 0 00 Nnfk_fp1 SqcoPp cpҮ- wHsqkq{oqϰ2-j!01"1'3o11As!K1$32+r(G1 1k+&!:r#-2(K)0*o200-.*r-32+&_*+~0%?322//.s2r7s84 r&Kk"k'gs36k1ϳG3lfm!sѳ;3<)'s*sA=_m:Ws /40K'[4%۳&s?_4@4D1EW@A0;11W1tI[/W4I4Ngtd1,p35m- W+KG5n1nrGG]ZAt- +?,zŽRWVw&Cj.Z5R+P/F-6p`5Gs\[\K)1BJ6uV?5c;46롶v35Y;b7tv{vqw|8tp/x+F}_vg?,#{wv4K?qv/3yöy;w_gxtw8÷۸rw]q'c6\7,xo+KTîx st#x{yo/3tYlF(39vyo8#KyXu1wu,cy'y9tu9^-_uy/9ͪ4u_znsy9SYWz zsn'{z1a::C5,↙׹kz|;y뵪{g7;z:Msy>;:.nB;u{ǻ-]PF;<#w5;P{ۮã{c<[z5Dw|"ysO{Z,{Y~~g~j4>fl~>co'ܾa;o+%㣾~>?/%2jf&@|'"F"U)(Wh 0Àu,WByd,PTeK/aƔ9fM(ԹgO?:hQG&UiSOf:UN9̊gV\;TfɦUm[oƕR A2tQ"ŋ5r8 JencǏ˞8Ō;~3L,Q9KϡG>SSv- vo^ѧWnm;pQkG|} P d[m4Jk@" kҭ,M+0Lq YlS;P:q)qQǶ4-/+Q?wL*l'AP֠,j+: r2*LSeL9oKD3N,C'kAQCt5F!/#4@<=D+F(SMUU=ԴX}UYbKHФKZaO3LLu̯_?/~P=O.&ӓ J1X n&$"r34 FB.>bP~$D qسЃs_XC搈ElWJ E)J *Tl6 RpS1WE^M!+F5Qeb c' l[7r΅!G)M=qx4!ˣ $@:""~dY"$-E5 H+d<(JYRY(eOYT~ h@ 0BΒ=l\o!$/X.1yK.|1h_j(ThMu^ټ!7Lm,?Є">9u,@J2O}[L'? S( 4]Bj‡/f4((-R`*7:KBҫLVʼn=L"Y@. (Ң.`9L)F,uRj7C1B"XD#G쵑 !Aa .WQB !!YFں-" IT(F WBk(,ư?KL"S,\ 6얷o\!d:PA6ϊ".N;*1]uH[dumRBЉ녉r\rֳ.- n$b4 Bl!l: a O1a !&ms7d( `zwJqji9pc=d!|k_ݔ8]mwYbbZ@k"]f1e&s^#7dCYR̗嵴ahAЅ6 =4lg_gƧAjQԥajUXK G+9Wi]׏Z7lafZbvW$H1m=һ{=6憹 s7_Ym(ߗ 78sUh\DQD `6qpo\ܘ6KP%' Pr6ZuAذqsߜXM` 3PƉndDoΡulh+vL{2+7>70ўvBG5dr߇:QM}7;61!'D Z`5 p339s?s.6?t@!m40_ A!# 40:oA#tC9'B%BAs3CC;4EU>BIT=M!x|w7xwxxx7ywyyy7zwzzz7{w{{{7|w|ɷ|7yy@kOkl.YaleA<dW"amA8x!8%x)-185x9=A8ExIMQ8UxY]a`XʮW!kdmW8,195y9=A9EyIMQ9UyY]a9eyimq9uyy}AY쪏XrU9~-ՐS"D~c#jaB*#9yɹ9yٹ9y鹞9y:z 'JDzPUT>YYa9v/H#yHMQ:UzY]a:ezimq:uzy}:z:zz5+DsDu7o<):zٺ:z麮:z;{ ;{zZ?!Ck V됱:S>!s5WQ;U{Y]a;e{imq;u{y};{;{ik!&;7u4{WA^]W-!{ٻ;{黾;{<| <|!<%|9K{!@k-z%$#zlۣ?{Y]a~ >~;\ܯu۽}3[;A>E~IMQ>U~Y]a>e~imq>u~y}>~艾;V{c+~I=%>~빾>~ɾ>~پ>~>~3{")&,1~>!?%)-1?59=A?EIMQ?UY]=)-&03^uy}????q_k,41?ٿ?? <0… :|1ĉ+Z1ƍ;f2aJ<2ʑ,[| 3̙4kڼ3Ν<{ 4СD=4ҥL:} 5Ԗ*Zr֭\z 6رd˚=6ڑXۖ !,/9=22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JHŋ Ǐ CI$8\ɲ˗0cjR͛8s\9@`͝@ *OD*]4ѣMJJu&Uj @\Ê{ѫ`ɪ]˶YҶKW[7] L@>(\F ǘ3)@ >kMLH}PI``x n +_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬʰ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7ý@O|_,PƕZ ǓzȐ r(#|P+'[\͉1//3=s|3 t!,Y+22!<=FBCM$ KLW,,8((4CDN..:33?abl@ GecB'TWcbPSB)VY''B%/ SV/.9 Y\`^\_*LHHŋ7(Rb  CI$I3Jࠥ˗0cʜ 8sɳOYJѣH(x#ӧPJJFAjʵׯ 0@ٳhӪmQĀpʝK˷߿=,@È+^\#KLO̹ϠC(hӦqHAͺk @6mBͻwSHN|81_μ LN}qNk}6H@<1Ͼ}$lLYp `;PAQ_O :xY.4!>XmHa "AhB( ".XB1Ah _*yDb B.$(^@dA@INPh:xel @Am<0AuA,ߟ*"j(~"h FڨAB 饃Zi jBz!,M+ul0Z.L4;;121211120),3Uq8{LufhnZ}WʆYlwroooago8U>GF#BrnO GW!i *%.AS `r/ȅ7֗"¬ 4I\nxƣtĕqӆ}ytprboY|WUfB\*\h|+'ų״ ;LUVϽYĿfn~ŊƖĝȪǷ˜ȗю⅞ЅȏȠǥſǶƺx7NwɐˠıǺƴƶǩȢϢ禮ښȝ~ȅvn{hYS]t}scSI;ɯ!Υ  -/&t;^W O-  *(8-C&K-T,Z,g0o8Ƀ2Ȑ2 HA*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cx͛gɳϟ@ JѣH*iA~ @JЂMBІ:X*Oj,eCd׉Zp)qC(◴Q0)qcb1$/;5S@ P)<0lDOgPJ@yzn6$t醨Z:}W<A׺xͫ^׾ `KMb:gD':I\u,7!"!JjEMf$1Lt\HlA5HQu pKq +fM&ϹPqVD˵ly} 5.hMm7H ͯ~LN;p"&LWyFXe3YrmGH$7ZFkD1F4L RS@/iE. n 0APS۬9cqmcP^G@DN2<:Cq0>πMBЈNF;ѐ'MJ[zo"!O 7nu,gJH6V9:\M9 D m@ok{4Z;ЎMj[ζnk{ִ6 \:Ǟ4x`lck޴>ѝf׭Ʒ]M9궵=c|8Xϸ7{ GN(OW0;Exڲ|] YWb]((8HOҗ;PԧN[XϺַ{`N/j0>:,^ъZ} fϻO; E8lFQZ,\k#GOқOWOz86DrQ>G1 oxOOWA`D%A{ɋ8[ LHsXOOA揷j[^`E%ш8XXx70v=sy` ؁|`sW 6y}0   84X6x8T@'.5qyvPu@qxNPR8ǃ|?x7'vpIMHdXfxhȁgul0 1 chptP_hwpyVA}Pp@u@x @p0 1 g 08ȉ mQ((' hhHqH_8h0 (l`((XÀx؋hȌ wꘆxhu0lP\7 m !yts  ` ~A^x8uH! P ( 'iȒm0*Y.X옉0"ٍ؎$i IiF9! 0Y؋C_ H8$ h; hv>npytu0]gaI 9i|ȈaI8`x 998茓٘؋eLj8ȘOYYi9 ٚɚ6 zזquy ))Ijyy)u) mYM``Y^MɟxHyYhkiَ $ ` QZaQ y t0 aYzG! ,x@q0쉡> aY*zH*PR:TZVzˇl`'tzɗ IɑHMItZF?$H9P陧iG ,J(:@1أ :*:zᡔ0/ W:xGXʫXʺڬmK7i꓿ixjږ깩698ڮFI*ቨ  ({ ˠ j [α {б  KkG!͑a+m0 B;D[F{H+!`ނٹڝ ɦ䚙*DYXI󊶿霛h rb"Jj1R!!~s[`2p+Pk ¸Rl +kkK۸빋˳򌨠#ۻ;8"ux}ig♑JYpzT齞 *K <˙) ;P& g @er +8 &`&@?60,)ЁATh܊ CE p͑ηeѻ 4d]C?flnpr=]6ce!L-N-\| h^3 0_;S<>Tٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڪڬڮڰۛ]D^~QKD 0ۺ߼NPí35 0_ ?w>bZ>@B>D^F~H./Y@$&9ni[MC >wR) &@jlnpr>t^v~xz|~>^oJ8B0 M2T~V>}!晏^~;aNwPebHP~ꨞꪾ>Y!=4X  y.O0ai>^~؞ھ>^~Ҿgu_{ x  5QS\~6Nw`  ?_ "?$_&$/} Q}TpD_FHJLNPR?T_VXZQFy"3O}-MQh `Cxz|~?I}JӇsefT]]8\7=pwO?_fsHXn^xpmwZrAOȟʿ~}a%Hko  if.tox5׏>jԦJ1PB >QD-^Ti&K&IQF"AJ-]SL5męSN=}TPEE:TCA !JhFE4%L1~VXe͞E6A=U,ZnN;~#Aj F|q#J@lHBT&ŜYfΝ=Zh rzEU:ފkbڵmƝ;-[pҵW/_%Xn˶1EURݽwσx͟G^z.4Fr\~7뮼`/L6)$.:CqK#DOD1ErOAS-J+0Gw䑢}#0_J8#G%͚Fb:,X2K,xdE/3L1iA^dZlʐYsp\N;3p<$$t& JP$;AIXKai%dFT^T|fP;0RO%3VYgAD8[sI="$ZJ7)4YeH A(DnEh`6[;׎:ƭC8hc*Ѧ]m(4˖`Tb!Ԛ^uYi_W5afx]Wzx `7#9 7\;6mG&YYgS?T JN^pZbyE*D !=] 0(dyKaW'ZTTku׉4@L:kγ-O 2Gig ZwJ酆Aa9ՀTAPQ_T|?/Oo=oŕ"BnmuG>yN3Z"[$P޿k9QvNhyI0C,_hS1m^T5Oꄈr77@0GЀlỲ>cۚw<VPw̃֐\R$%Gxqsi{>eJcѺU4tb+>4 qC "Db(N"3AmW,󦲽o6hGhfphXlÇLvsU 9O;!zЅ>t#/ywU-7cӇUrt{N_{>OJ A{e"oVDs N>xpl#2)p]r7iw6?zҗt%:a37UIpKv (U?CGW~?}?[J Q7Te~q'd+=L?t欟7sÆx{Cp8t6@\??_tԀ-AD?Sˍ \d@C0RJ3J+ :p+ـyS<6>?,2<2tkiJO'45'()$5<>,9;¤RONXC*434C+ ,&-):!CDw<\eRDPI5>6 %7$9%>;THN@2BLWdwC[1DEULEK`$(5L6B98$EL0Tā*FDL(tSdmEVkEaDt8P)᪨ct&N5gt i, C'pDFjGm4Hr$Futȇ7P!*tGxGff,gT+|N CGFmaH3hEYXY[lFTIRyɟʠʡ$ʢ4ʣDʤTʥ\Jv@Q3ƌd92@1{T|4}FU BdjĽ8DCFtK Cz{˾K\Ldd&@l'`L(pnjȌL~~|zz$M My@MԌՄքwMwhdvXTuHLss(440N P\\ltOPÓtOtJQ{%5lG{NjB$BI3B؊Ƽ½  5TLd'xLȔ(LLL,=\MtؔMڴMMMN PQ((QLt-Uu׌lڼuM r "=R$U%&' (-OL*ZտP2%PDSTPduSCS8)9S%^Ŝn]YUD-\mT^u]YEߠ\}NUHZX\+-%]_NHS[}a`] "^`E^[k=Nt%^ӬumW\|\N#_Mb}&%]ؾbN,6-6.n`c c3"4,.^6a7~,amQmamY-rE?Q _OY{E!FeFW@w_BW =dg.RFiNfmdodMsbU[g0vgcgy6[ݭ VVWg}vZe;vB5TpcLa^anhu(dh WMRG&UڥRnFX'ߪLgsFinQ[vMNyz6OÃ&M36lVlvlņ^Llɶˮ5-Ej>hsQ.f>懾ͪfjh>jf\kn]FpVk˸䷆k~]/f~2k i{`^^ö&.olV@o\ <^Rgw4LqF~xx%A@7i;8չ5F٢-BXvVu*u+u_N](yg1v'vMPMdwpVYf^^>:vJm\vy> ~FvHFq$wm.wswztGtowJWny4zoi{|{xWgw(x9d{؆wVz..I.TyFxn7yuuJymc<~ s%z7l?Wdeo7t(fmRuIJgnfL'N ~P{!''G > P9U2×;ş|x7y|,Na` „ 'Ĉ'NdذSAZlȐ"Gxd7*Thr ̘2e6i擜Pv翠׏R|J*)O«jժqmǎݺbץ+ڴh͙m`z۷vhc7&۰Q2̚ep ](G\a4ӢI? "T!D-ZĨQ#G(n8ʕ9ҧSwb9ڷ/O&;Ǔ/;׳O?gE*z[xC`bI%HbG+lR#J8! .r4Ho $4"hКC#"-hA)8#5#F.#x#A )dyP)dG#IQF#i*Y 3iM]6[aȁ < 5$7j]RЍVHzC)OR*+mKVҲD%.Wg]R%0E"̋K<&M#2s'4'iJ6'nÛьhL:+F/=fO<5a0AqeHF Lcq#$A iЇ&tU[C9Ɉ:ВQ *hA.C ](IQR-u`4"6uNs0B jeC]4?9yجMrYhΝ}{a+DNx3}Q  nc6A_ ЎA 4C {&ֲdl%)AN/ӃƉDlIC`&=P mm^{vmۡR;T| Q|jʖGVӣ4@^M;m2w׺h!yMЎ$k|A_ޗl~`xE%[AO>F(` ",KR8-i5,'S IS.mkw.6Tָƅ*r4Un25;V2&Ov-2O lX;Ae//~s@PӤ;Ql{s !U„;h.z#nmu0ٖĴmiƿ4j)Waq jXzҝ.nm\@|L;{aWZmuMyc'h{<Hې0CP>9ЃNr~l&#KAq~)q{5x:ֳ^.}_/ٹk}lNiX%VBk[0P7c+8xc;7>Th] 9Rxe@rM:$Or!PЁC8{h^\::s/p /=wYOq /Ov5O0:ukóo==Q )܁rܞ5 ] EٸE=f T  Qu_<9EVVAa] J,!2>Qo@,`^"@( r0A~X`X"} !ai Nx 4-4\)m]_WQQu1Yfw5!)ӪT LfBϡa*z[-beq`ա 63># ӊ o1Q!ߩ`#:UEb`H:#mb'z'""@dtW~%XX%AnAG.,)Tp#uFʥC] H"(ca&bV$L%Q6j%NOJPzPť#RJ@;!'bm^(&!XT"UF*_d!tn&oooY%Z&r ĥ^V]]*Fr~_%`Awg]۝xf]ܽ]yy]zz]{]KQYc M6&\TeR≅fcgN9%ƍ:djjk.M[U%mb?Ngdqfprh5g2~p8pn xՁ樎( ip)&i4>)Bi@Rifn[|)H)ܥOKu}Xd Bќe."$X8t)*%:v5SNhTV=lfVhx.rP$%0!^J'*PF (kj2ikNi&[\)6+zFLVk6Aʩd~~'qh8z9:*:N f¦]>^e?j,erj*މ>abЫbjR~l򪯎,, V):J͚ZΖ)}L!b +"BW>8úBbgz"Q"*vm-CԒ.~&^ܼ+v2e}bYwT-fDB܎%6-Ŧh1Nomnlz,.,6 LV)fnn|j:Ђk-2>Gɼ~cB8Į: ޮtn:ABjfff*b>jro{00B,ln* 7KZdf` vrj//:[Hj)/Z_*Az5꧝ntn3.:09.UVGJq.F/fhpxh+X02s0]F'3찇ph1/q˺ G1N1,^qƧo{W*EuU wE;Smq+1ϿZ(>o '/%A.vDo7KbJ93%fgm2''  ))ǯ*w,rkrnֲ-$..LuE0/p s273&4O35SS ڶ3z"8A#q(ڴz3&e޲PK;c3=h'{2((/qr*2+S'toC -L4TE#N 3i4G.}4HcH3ItJJspKpm&5v@N@8*@5boQt$O6{,56>u=T#qUU;qVGVoWW7t-5D3$>uZ0[õGtuݵI:u?s_3 vcMkrt@N!rH/vgGeg$fR?jl<{vhhiii7njjok[k_qlC?4۶$u50v[oZ\@$N85D^I7r+wg_pƴV 7wt!x+ xq:oz*wFwTq}+}l~C~Onovm.W+Z1H8\xkx^s8~;7tt&/!AS0;a--+$]VB$4B 79&.6y>KFXOyɕthyu{y174w77xDTi ! "4#HB%`B'B+X#sFovˡ'B?z/|cs??)+oA4Β4 .qnsy3:_zyq5r#k _F|k<>);;;K;[;󂸿|Q0g#3!HS:X»j{޻KY3kFC@c|ƃ'~K5+Ï7GW[׼߷̃}rܼ뼣Czϳ;h =7) 4A+'B=I2 Y/E+:;C|ēy㑽q}rگ}Ƿ={=}={='?ewb૨<@H8`&TFCkD8Qb$10cGި9HQ !D=T SQ^Ţe.^ :hQG&UiSOF:jUB 2QP9w䥋lY7aTi$;Fmhќw{'[hzHҐqcǏ!G8hNO-pаTumw/G-ԧIϪCLCܔDw G}T[-.X&4ZMյװBx핷_vXbdn;fs̕ǓvZj>l#>:6@Aߡ.]x!%t^z;DMG4ZjERcLX뭹7nxV%~Ɋ/67c#r:3Uf<ӄ9f9ȝ6g=3y@ TZ)r] 'mLEыEa4Yo=aÆa#8 -8cdٱFyL2ppk8rP_2^]<jǿS'1<H$^.. izS*)Ӛ%k:t=OΡGMj:v>5jUyՏdgjNI+hд`R!6wҒq+Wf"kG}8q"^cݥviK]/:MטNV,O1Y3nogZMiQIn"dXH[m YF\ OpEQZgu>+Wgi0:"4}W>&y=2:~/ )3amna+Y{a2̪L Ysr'! 91L]񐘉vIX{6D:YHpLN ɠVG-Ֆ 6̾g*+.yxk#e FۻvKqe;m.NZܖ.wuݢuyDT#x5 ^ fW:L[o'Rw&vsFqX8ȫ"QSے=!mS嗆eiSƹZo- XLmnB:ޖf-oLPOԧ>:{zY랝Yl rƖ*$O/c{GzD7yP{='|1}EG3򕷼1ao~ĝ?;?D;=<.ۥ8 ^o޿GmO> Lc /Jc f CײOd&̺L]ί^ t*TΧL8 >KDJ f 8 J9AcA'*'oknL(~u$s2)FN#; O#1$E2NJ-1.?q.I.R/y&oRf"88rk9t@0s/3-gI';s;;3<œ<<@4DATd==#3S#q>i(?e1?T$axG}GG%@u9APA=3$s#$4( -B/C5tstGFHtkI93IJAJ%JKkMKGqC94<<LÔdLD$E1L4TQM7MK0NsN)}Nud2!VeuViViuO4W OAIcPq[It-=fJB4yTSRK-5D15S7ZAUTՔT;TUSUU*V3a]5^ubWUҵ*5u4P 5X3w4BQ;D5Iq<9TuZ52USɴSkL[[ŵ8e]`6fevfgv]cuX guvgyg5vhhv^ ivii6jvjvpj6kVkjjvlɶl W` Ia5Ja!J0Y.;Sc:vS9uf<#dG NS7W?q? ^/%f5Ws.g{6t{v<7htivukujvvuaklulѶWՖmAmfnVYnV)v5-<pWD;cZW[GVqduq}3rsrˋ)ٮ`os7f;sE7~ut/tQ~M@uYw_vojvk6ww7wSmזI3x{xJaYYb_oyEnzMp;Ud{qET1Fr ԫ}}AW~E~OWwu ؀c7X؀XuWP# 'xaJ5YB7Q'փ%uGOXzSZcwd'qg1kNeӈׇ8~8~vlg7lPxwa87Ӌ38y8w5AEXxz؍CS{0c8\8)8ӏ7W9t YuYVoWv!v+yl3k1(Q4G1T[ ǘ9#s8wvx9kvy؊:8IٔyÝ߹癄ΞypU!`Y8?\xq]t7w2Y\:}/%2Wk+.svz9ZhOuI6t_z `7fԦo:y9:|]yڨ5sYqEyㅈZ8˵e:@ȫz#!ǚͺ:w:E+ٮ Хx:kz8nX nۧ: 幱# pe9{\ev]Y} 9v9pۤuy[}` 0{pCK;۰;{{Z%;û53[8{qI|r ݗ)Zcs;DGyAz \ [Ÿ۝Aی=]9t q]8XY=;i)|o+)mav]o<Ǔy)Ǜ7ȳqё<ܒ|ʯ<\y.ܰŜ̟̅ͩWMuټ:F]?ݻi|]M} }!}}%}ҹZP<ʥӍ9G]MŜY]z;[嘼a7sw|ծ!z؅3ڣ?zȡ>}+ɭڱ=5i۹}IyԽA|ɡW}h~KW:`>A=7qԻ<[._>]z~kYTq^YK[ƟR]):u^?u*7?;EI)U?Y_ _-vzi=qiCNZE-\xx1ĉ+Z1ƍ;z2ȑ$!dhѣJ&\K̙2; J$i5jSG<4Ҋ qݲE++8+EjȐ\z 4Sd˚=촰lۺ} 7ܹt޽Gwk98b-Xc92ɔ+cˆ9͘y :ѣ;:4[Qs!jۮM!ݼ{%QFIhB%UBQUlE2MNJiJhnʩ]'_-#2X㍖c=BY䑴%iI%UZZ閗`r\dgz{^m.U'x26Y mK VahKo)C*,ة*#ޘ&kMlR aIu-]r=ki sv{g1+N~h2J(ދtJ/h/'<# 7<ï)1XfqqqerXʒ(Gz߶ t|9灂9EBG8L_yӡF=ԈUm5Xguf\5ث=_`6ڻ6nqqr`Mo}, _?I(y8>=䓻mA~柏>^~??\dKݿDǘƔ.UXKݎV.lbjg; .w۝z5xt޴c< Oe~Yp^8h#ڻ*<|`D,1aLlq`Tś\,(ψF4x@8qx<摎H@n (5ёtQV}mD jwkBF) UJoB wXƉ6!tÞK/a!qGyL:^qˤ#L:qӤyM:qc AxD@́ـd1IJVJR7Of,RyS `YJ^*t%l9.\6N U/L1 %*$3R.J,-5 S7j47bs99tsZOnl&yNzRIN\WUteYJy8%xv.f?F;я#-)3ORh|iL9Ӛr9N~0rT{}b_zE%l {X9&Vzdlc7LBd Sb6Q9A n ǰ׺6\m++XyR[]*At _KL6υn;]/V׺gnv]ѻcM9J[HzHo@;7}[E9J,V_%M <$tT^([Hܫ*l`bxްHf/\gs}*ZƘ`l|YkmgTюvR~wf2X&h%.֚=4h\?0g4cF\4kfsf5Yssxg>r[IJNW}3 uԼ;qC ~59,YSQeu]sW򍥼Vyr~OAOqo{ԫmd/{'O mowB&eg3{5w5GQ8&>|ͧDD]XGXwXڧXܗSgy'䇂UgY7q~~1~`z76Sw?Pr&(d{L{2e.K8K V[րL4|<>7|WRRS XS"S$8@oxu,؂5'wHaq<?~B^&nxs{TȈ wPHsRH|xahx{%%(E,e04D@xp+(DUy @ ?"?$y?e騎*(HՇA؏@5G  nψ!#SI))Ȓ-y:a _i 034II8c0Ó6IJyJ9|QYIIW~Y[9`bd9T69ɖm6o AC(u9I8z锁)UWiǘ9 >Vwɖb)9UɝɝCxIњÔY I)u~6"I2hqj Ya)r hj{  J#IgYYIj 9vSyɡ!K)#p%Zu] Rj,ڢz9I:6* RZ=꣦Yt7Y ٔIّ&I?~? ??٧h7ꨏ:I0*:X~.]ZZ3JIejhwdϱ]¦iqsuڡxFo`tD꫿ JGJJGUɪ˺t *JG`׊ٚt$ JG!q:~Z7Bii`igvigkzꦊ8ڌGJx>갷*:ʬˬ:;ժ!% jʲ-ɮ:I ;ةbZr %ojw6|7>{3WKU+"k@&′RqG)3kZIh}ڜڳʯ` DGKDŌM;ɰjX{Z>_a;[gi%۶|&۲p`|} 8zk ;鸏Lˀ?˹۵Sb{볺jۺB 񋮴2K_ӻ ~;F˳Nj?`:g=^`߉⯭K֋/S{3N_9.ئ?m%G.OKMOP>lWη]~-a>Dٸ|8}l>w>@ct|ʑ~>E>G^膎萩NݍNU~>% b/]3=l۶ɤ##~Py\®Y^~ mڙnϞnNOOn댾h^# {^Gy) J5=0_O\r+G{Oxn/1/_9;9@^`ћ#? hnŤnQoS/ nM5|;dngjI0 x}wLz ~o~5o_<_>i_~7휯O]Ղ?8_/[<⽿{/ŏ!ʽ] 䪏/O~?ȥ a$(A CޔXbE5n !D=T SQ^Ţe.^ ̤YM9uOA%ZQ4 2QP+[U7aTi$;Fmhќiծe3&[hz%HҰ_&\aĉ/^F!/%Oe̖9{gD&=:iԩZjذͦ]{6ܹuo '^ܸ1ɕ/g\sѡ^Oؽv?YdJ.al{Ө,WzU+W,Т@z+Jګ/ 3pC;CCqDK4DST?̱(jԌ3r4 6ZGۊ7$ n>sR:*JS". $H2 %tM8<>Jsh kΒs8.ҋ QH#tRJ+RL3tSN;SPCt1+pyrVZ1$sI&<7)MJf5J, 0K%lLQ]36/y bxD$&QKdbXDbtOb)ZQ[i@jdiF(> neePsM`P!DހB@aవP|S wslrb|9zMd'=IPR$e)9I` @=OR0e-C U-}K`R`܈26hLcg(6HpXG<y ?G$k,dg;@!||v]h 6LDyiPOӈ0!PRހ*bPfTDL3.\c4FM]YSfK=rJD9C ;iREaOO ~ESTFUSjUT,b5H!FS~uaR!Kӈ T # e},݊EmEU {X6Ԉ1Ge2sτIݨT~lgR+ԁ) gšgeTQ]ڞgtۣ.>ߧ:%nq{\&Wep!Wܠ!f N(]1\a\׹%Y_\>w}EAMWؽ;{ڗo_X06"H)ґ`VLlf %bӒ )d:[X'y ;+\qcX;q}c X+E!<ƥ}D^% 2 9B~2d_s|f4ͯ? &X f0l O05vXK S{1fQW,ϻ+ltfIϹt=iPZԣ&{ Nխx fyէfuV][Ӛ֭P4:2S`u}ld'hC4e3KZhYg>Y]C{aGu~q-K`Eo\'x S.m=v(gx7~ V8+oC~YQZ>x]r'vȝijmwŭᛗY qnESai;oITwO \Bc'{~v]kũ~! eëJa=^S}n;~\CLSV]|gQ$]9iY:ы٣[ -Cߔ'zgv0tˠaR {|'_g~/ښC?C@ DADB,< NCSiB'̾B*B+4+f™NCcCQ3,ݫşpC@$EYEZE؄@(g!FE I=Dc<Ƣ .d/AtbESEjDR?F`VԃFp GqGr,o]EEv4`b AdGz ?e#flFC7hL43m S?\4[lH|HbZ=vHw xzHzGdDqDPn m}Ie&](W!- UQ̇Q }W,u֦zijݭX}7؃EXJuPcEY]uŸ́Y|VاXNI,YmԓYNdو5Zet@x]BYY LZZ͢YLٱeZ=[4K@MWZWy$}UMY}MlZѰ=Z-ܨWM\]\϶}۷[R=H0Y| ]]-]Ax\ȅۛXz\\0]TͅMϭ]]]uPM]U\B\FUTZ]^}^^]^-5^N:R}Je^m՝=_6<~k__^uQ_`.˜ݿ5` ` XXEXߠ`a> n .ב-aanZ aaY^[}b'~b(A^h_(b/b!bf|EbYb/nc70cU}ceb6.dG~d=dD=E_F~aHdMd۫dM.eSFPIee$S~eX6TVctXe]Yw]fb^JfbnfgcFfFSdgflbVY _&c5\@n5lNguNnOd#νTbVsug~hgܢfm~678hNh^hnh~Ă^߹{j$7`hii.ih.B 1Gi\ivfhjʎ>ijBRNj^jnjjA j?ಪŪq//Sg/guPs!tXt`_$a'Cb/YUx +Xǥџ@\'tK|_|Ζߩʷ!zjV V : H:sK|~nO~FZk~B~x[벫~Àk%PEi!ÆjDEIӨVbѲu /^NLr%˖._Œ)s&͚6o̩s'OsZR!Gҥt҆0Y4IV6UzhNϮ^mY-[b kF ix(w.ݺvͫw/߾~L †#Nx1Ɔ ̐NؔtBaά3+#S|ҝFXbƍ$iR4ڶoέϠCRPRU+Ο[lQk+}3޿/.aϣW y?=Jʧ75E5rQpH"/&Q!E\q =TU]V rtf[nU'{/.ފ 2mY' 2\5ޘf;Dk֡OB%N !I6Eq*asRՇԉkW0 lw♧{'zf'uYh_kdRZT>pgar2g4u#j'qzޜZZV4E)q"rIVw]v%ں2RjzkZ 찼b \lB[h҅s׵r70- ?ejc 廚;~1jfuB* !r]-30 JKZ,C;qk驲^=)ҞiW4d6A!2ˎ2%& 44 vuة ̠2#ȼހ|9x=+ pA7_- Ul.ӨRK.[+lI (4ȄzȀv'wr^کܲշ߰mnŕ3߼@9HXz4/xəϕw~[Ɲ7埿ˬ_)&O10.i\4+deP!V#0~]?ON&\-0$ -}i2d /ha_rIː@0;ܡ|].[b#B0.ߊ3jBqQGj Gy44S79{17 ]6mP[2x ls"%%MԠ& HH~xa#zȘY"\%+[Uҡ$,AA%,iK^5sUcm[ Hdf' %55JRǔ(rύpo7ECpӛ4jA3R ?*Pa&5m(4L':&V CB;JJuızF^ ۨh)āU5hѰ2)ff:ӊ`M# v1IjTKѓS4Z)KP+tWm ;ء]PgUlЀ1V[.D]S*k9]wUMTaZvX&8a I\U؞(vk:Y  jZᵏzuf>O[6%l K!0 Dqm`(WR!\&t,0B̥EebHv*0\GhՀ#[݇]/tR;3 lek_ ,\FadC. DэI!@!*laDHXMbz48 ܁Y a*^2|^1nܛ%"p4&Uc*MBfO~i߇8s#4`׵y!Ym$2]\Vnb[:]둘4Pw0O.k8H ?Z->-9)2aG!X<p7 \"ԢucQ mI6"C9ukC`8יԺLb(aъ^d]UG_S%%vo;߆ũza#AAVھ5uBq;Igd&&e3;q6K_yVɶSBe\%tp+]㯨,Y BxK{Cl9יㆰ !7$68a2p3=G\`#=JC7R7zԧ[շu7` pks'0lvs(1`-C+ZW+69tgvV+r뮏ڜNhw,1ss:!3yD-^ v& . eA D$ADBzD hY_36 ҄B`L  GZ`T@ABA@2w8aN  bT `|F ޠaD]6]wd!Ni{bf^! vT H`^]¡ʡ'aLaa>GrG9E~9G]Y"N#\%I8^l"(vb~2")"L)"*"+ .و9b(6!~;//]\N4V#5#3&(.=6#4>KD#'!6f#.䟬 dA*( ._#ϩ#Vc<>D?";c"bD D]F~$GG$HHIңI$F5$c$K Kd:>REҤ0XM$NNv%OOPnP%QQz(el1eSL Z%mIͅV~%WW%XXYޤY%ZZ%b$e[[%%%]]bbՅ^%__v&``ana&bb.f8TAfdda%0Y?хf~&gg&hhii&jj~k`.lS‹$!Ufm^]fofhxp 'JfgqrVsFkJ'&vve1jw'*~'ygp'zI8rfc'|X}c;Z&1f]'y((nz"q*b2`BdJ(9[ 2"EVmeщ]aݐꠑ]~rf'cj#/a./R0 diҖriIx">CF(u~T:V$]dҊ,D: Cۚ"[i_MHxTM\f&z-jUegФ6{UMUfOŪ΅*{* (V*j_ljMW}UXDZDZU⪿஺VeZ(fks+ȀۍLVc=Vd}*jybatj붺i$ͤz+룎߬tCkDqZp r1s}H,P_&5^_~Wyy짦類㾞Ҧf&R鬔ZNJv],Viaš^ZrI!`X,Y_LyB'Dʬilvڬi(x(({fnv(~R2gv!v MYTټKٝmL̅ ˊV"U~]ʣf$d ߂.mRNZ'@ŚDy˧iܮZ%9nʘZmwUIQ/ƬR~%--Z&eIQJT\ug書`2)/}.p50*:(r1Y/ ӯ0Vicz.1_JIdq}\+D0օ˕.mDܵKF0j q.ecLP:I]X)We_ ^+gA0-UEIL^etm^a.nq_uq~~b f ׯޯނr Lc"ű"]=1p_ ^9+nMR"7U_$QElf%oT&[Mzi p ߎ(2qJ+_@+i [@sqNϿNl%n4*{J383)J˰{sE!&Cb744OG??1@s4.΅*3LMǍȢ~j-,~P5HGe^Mev '5 7)5tKt{/8r8]GT7#ot{>u uNuvrZr[4c[83@J^茢QC $ffZ_o@bHuR6'Q+bkc4dCdcce쪀hQQk5l lum?uB+tnn67R b7S_"$4n37D3GksPttvuvv5{*&wwws_747 ,8z|J}}S~Ϙ:x`A5\x8P`{6Y׬I+\Ktϗ8JxKBxy2\m"vٍ y}x7/y(!9L4W_ Uym}d+ )yۚyubz1 sKUÉg'S35o2ygKcgʠРieSzz _zz gzli`jz{ ;#4 hU_zovSfx?s{{{)6+ƓD3//LA Ajyվ{| |#|+-j{XAU$)W|sf͛9w𿦞jj kJ - . M/bM<U\EofmH$FF1#Ql&GR)Q$1q2X&AC|t̄"<1T&ұdFSZ<4UŽf 8K焳Nf``9G88Fa&uR* j3PE5 %Xr &h 'xXe։ J*JK,BKZ0ù+$:`yjlݖj̆9W\LV]t_RV]s!RiwQPdB3jZw;߅KH_}⊵Ԑޜu$ejTTϒ-%#PЏn(5%S>cRKyfh'=G=zL/XU+A]앤_!Ď7h >d7dCgCW䞛iuE8L31`6|pTFu_?@Yp7/|~6uA&NdL" RN'gyі(uIPo\=\A$a !ͿHe;Y\i域ѸVl?Éqw0k+Cs [@ pr`x)!uduSa^7ؕ,O3E(<6r)r;ؼSGUiUD'>"KЮ+%w#1(:1}j5:iTF7qLcp!7 `@WݱFҤqdȎ V|+\)y 5Cɰ:NҒpXJSb'RBW~ 8/!:BCetx3_< &yCL!"1"ӠD}Ѵ=+>Hqb%EiZ/lcxQT:Nws9'a #)#vl P1 2s\6b9 P!MPI'A)%JТL O~TVZJ&,Ӝ=PHfv! )Co2ħMIU*vf7zpmeCU~aXZVT6'UmZ(TQI [CT$:MzL^Z j[69-vT-Vd)[Y^2Y~hI[ZVkue[EY\6-zKlyۡ4\פjXn"ַZlѕtKQVemueܠЖm3W` zh\"Ho;ND&_ \` V` 8oZ#zoO&ẖyw37\~(D2Jv#3]GJț&&P}ZAB\dl" i-l b:\5*h;}vG{-5s?oqyo6 9$͢qZ{mXs)_y_^g&mxYK`#Q:Yzכ=Oz_ F{/924>2$O0MPT%R &2&]a,R,ǒ,vPʒ-r,](@[NL&Ll$K6Jfj/wIMD22. Jd\2R38d:`-7S42.2" _a"-e^lg]NZ00;1 O*9a"*'S 22:S::8d>PN:;sr&{2snshSqFf (<ur8o{~E^/L`3+Ð94ל;t::A<}Hh~,h%T&C)C)T~LH> O>?k B-?2@kָBsl`8Ha\i8΍t4GP0)HTfXa8j$DS1GXte49F״p4NTNN282GO4NIHɊT&hd<5hTH0yK.Eq8? :*g%T G/TKTOUSUUWU[UPɬf 5$R-KqB8!F.@o0Tø!\YZU3!.[;F$2Wu@nzUXk UYu*^^_U___/!.⮋[0Ewu\VSSSUbݪ($c3Vc7c;c?dCc+#kLeW6""u$ Rv.q]c2'g%bUhhd% (f s7f=fR@ܵgVyOVlǖlՏD"Om vRvj!j*svFakVovV`k/0}oro%& W bq#WtGWy&wWfVssA^7 69CtowFR6sWؠ@A  Ay y7%!) ܀v5w{gw1 }`x*%cW,!b|'q\6$FIWiЗB\U|B #X'+؂/+')o}wW,KrBa~|r6w6Xx('1ƒ.1vM7T~[~o# WԴg5|!,Wdap}8(ט #B‰Y~t.daZ"VYYoh Bђ/Ѱ-BM刷O8YqW-.nQ}TRՌsB'&(ʧ{ٗ `+WⓓXX#P.#nX/,Y^99g!p8w&dUrY QYYia)yMمwYHZ ڠZڡ#Z'+ڢ/3Z73je{} 201INy"yCY3X9d&,z ^|ڨZکZڪZګ:ux}XCixfG:M6Ej[eXZ"\Ai?Y#%z{"['+۲/3[7;۳?C[GK۴OS[W[{ xAR"`

S~ ^ce+>>^~ypYBd___d'غM?0__ϜY)# -zT)ԫXlKÇ;I J$E"H"CIɓ(S\ɲ˗0cE[lђ WX ŋ')]ʴӧPJJիXjʵׯ`ÊKٳO+Ud ӦNDGjg,Y dHS߿ L7*^̸c:,n3kIJ74PoC'qcǏ! ˞Mnɳ+WAG "ȓ+_μУKNسkνËO>y[%>UXwZȗ7(hbJVA -tjVkqH ᇲ.O?PCڋ0(4h8<@)DiH&#Q+ɂWN$"Xf%mvLR$`)dihi&Fv@&!Mt!F|{N p+(ܢ6裐F*餔Vj饘f馜v駠*ꨤj꩏j+ %,%}筸x+,zfd@P"lHFBgvZkƖZn'oj覫+k,0*wMPV{oTlgwv{l6B1ֶ!lF,smf"-<@-DmH'L7PG-TWmX ]:^,dG ɕ0,Ю\-\܂Xӷ9 z߀.n'7G.Wng~R´m+ݤnlg+6aĵg1nI=7{/o'7G/Wog|ޠZk_/'AvLȜt {/#~; HL:݁~ˠMנ8@ Z[T־] ~`w70 gH8̡w@ H"HL†aPP"0&B jNJv,MH2hL6pH:x̣ǽ|_ DE+Bu%XA$'IJZ̤&7Nz (GIRrL*=TH8]riJ .w^ .kIb槕9$biB1ҘЌ4IjZ| 2 FΤe6IrL: 3B6 p< 9́'>9; @JЂ ! E8ϸϠͨF7юn eC!*ѵ8(lGWҖ0 HЇFW&m JӞ@ PP=i3yѡ:PT3:Sڴ]E8ծz` ZS4?ֶpYU5k^׾%sYE6Mb+5:jJKZu,Rsʘ hGKM5we*WIֺ2-Ux6ͭnw>v-jUȍo!Y4Ѝt*涇vV*qK% jzoLZկLs׶vCiZ_8q"O qZXʈ$D "g|"xIOL`G0! 'y~KqbϿ8Xx ؀8Xx؁f~xgzar~d24X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅A(A&j:TR$"Q*&-cr8tXvxxz|؇~8Xx؈8XxPe&dWvffV*b`:؊8Xx؋8XxȘʸ،8 fxhHxJA&8Xx蘎긎؎8Xx؏9YyH&L Q1bj2Yyّ "9$Y&y(*,ْ.029h ِ#@4@B9DYFyHJLٔN9Q! a9 #@VHZ\ٕ^`b9dYfyhjH'!#z0~vyxz|ٗ~9Yy٘9YyٙYt9Jrٚ9Yy $*ћ9Yyșʹٜ9#+9Yyؙڹٝ29Yy虞i$/9Y1qٟ>Zz 9 : YRڡY!,\22   43444.^u$42c4/Vy]w4 /;$:WzX}Ri44StZUt53;$842L/G;$9Vv40ɴn4145Rq42SnTq43Y^z$)4-Sl#&(,#'H*\ȰÇ#JHŋ3jȱ`CIɓ(S\y#H0cʜI͛]ɳϟ@ԹSѣH*5JҧPJJSXjU`ÊWhӪ]+Yp]ܻxάkW߿7 Lኃ+^̘Ɛ#~,:̹3Zm3{M:ҨSG=װc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(68)7 4H(ЂX 8pУw? P CrW(DvK Obe,\Pu [R%_eJw&^.@ѽYp@* ݙ0৛*A ,páu @L @  R'Pt'42!,22#>?I 4!+GHS&&2)*44 *srugkwrolkqpottvusmnihqrpqutX]wmjisqpvvuw^d))5unnmgrrjwvzuqhsrspp/0;xsokjrollrurqqxw=>Hw]`itssmpponnrr}~ztqvukqovttv$#(%wzlnwkopsopspo^bx4 +vi(?@Jkomlqqtxljmnmssqrtzpqvuvjkg}hlnpmnH@V= *\pđV #.I i!EU'YXeP9Yd* @ 'Tł3Afǧ( PjDC2l4DX1LaH4K ;[.`:!G˨K$`mqʄ%dy#I+]E2(1dƁ'a'ΆR)ѐiӨ9,E@iԨ0`p#<2gOq`pàa Z!KQ7pMI(p1tf }̈́4@(@|  ЇiH!, 22>?I# hBC 01;KL1(( tz}67B,,"wwvx}}x|~~BC,ꨩw{zz ,++7uuz{vvwyFGQ||00Sz&N>썃 &>| 7ϼOCo<&'C>P?~|Oc[}bz׿:lHe5B!\@B1Q_⥠PR:P8)N] SPі"!Ǘ %!, w22#>?I譸 &GHS~M ))+6'&&2!Aꨩ++7>0'00?I# GHSmC&&2))5ғCCғCmmCCmCmmCꨩғ"".mCm+?@Jڃm[\f@8PÇ6Hĉ!^ĘQF~rȒG DiPJ> @HVx3̚0/FP A%&8L'Hɕ8@3#Å J`R(%Z]˶۷p(tWyW_>\XaƉY.>LJIX.9q;?0.}YvPpP6# `au`.L]!(,PL22>?I#>@K #DEGHSDۻDŽطٙ&&2EF))5ښڙEFl$nEFm$'9L3̨ٙGDF7ALؙؙqEEF67|osEpsqdzE3EGs++7qFsڙؙ.MpFؘGn ՗FEݾȑ?@J00| S̈́4kܙSN=}dtPE̩'ӦK5~,ɏUS]KٳhӪ]˶۷pʝKݻx˷߿ L *ǐ#KL2e)h̹ϠCMZ ӨS^ͺװc a۸sͻ0b@ȓ+_μ9s KN:rZ4ν/1ȧD&[l0OG͊ cD! 5By5 P D(VhaC1l(lx$R@ ,,*@+VE S<DiHIJYD%0r$iG t`)fGD`]>qc)g4x|'DD!aF { Tj饘fiju8M8Ѕ:ܰ*무 z@  k&l+F+$fvmFpAޖk2;H+,ҫm` l'ξ1G 6p~SzEI7q8Thh0ürdF5wB8sxGWt P'D@y@B F T@!Q,M+0;H@5v#M /$3.Mbw~~   3AEH&M'^ rgdnVr Nv#ZxEdkQcicjyrs{vwwuuppppppppppopooommmkkkiiiiiihiihiddu[Y:%' %%1111112222222222222222ppdVB4/>HپL٭S٬^ܲpջϷܡ|];BEUisHA*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cx͛gɳϟ@ JѣH*iAvPJJիXjʵׯ`ÊKٳhӪ]˶WRpʝKݻx˷߿ LÈ+^̸D5=CA3 *ĹϠCMӨS^ͺװEMڸMͻwqJ Nȓ+_μУKNسkνBpAZϾ˟OϿ H HN;D(Vhfv ($h(,Hqr9BD^g%<@)DiH&L6d<)QNi%U^SN+`)dihlp)tix|9!q12Baz;."4裐F*餔Vj饘f馜v駠i9j)z)ꪩ#ˬj뭸뮼+k&6쳴"-,aJ8\\ ݤPE!l#:*#>ɺ+k L |BQ62#ꈇ1fIZ̥.w^ 0IbL2f:Ǩe1q3*}pR!9GsLE;~d&X eJ؊Ḑ>0#LC=~`>4Nm)Ô4Ӡ;行z HGJҒ(MJWҖ0LgJӚ8ͩGhRf6y"c)RF=kj3=y2@kH<R^sT Ր苫\J׺jַ̣uhJuyg`kޚ"}gYyAÁC|Eay!!h+dX6z輻4VֺlgKͭnw pK3hBuio&U8h; F5gQ |l<+]2hXeW0@LN@ޛ^Ұp><`Qذ| YwM~az'V2Y7 ,2X6L"HN&;PL*[Xβ.{ذ1 i@(F/6̛QPHGHBz4?f5ük׻`zqai%HKJ[Ҙ-=X_>zZ3v- h2{cZ'^j{YC:ut3MlңHf;ЎMj[ζn{Mr7q kT2Vsfh ŚJ晫j-iʨ5{:#-KhJ|{jʹ; ۸˰yȗWlp*tj Jʙcy+!Zʛ5 f ɥQBʛjKK^KYtˮSʚɫzs[p/)hkl+o ͛ɬ yᘬ⺫k;xʷ<\|K耹6k ڧjJzɺ ڑJ"P\)_I6lIʼGEe [˶?\0Lb˾=ZeK [D,񋿼ʿ`ffnpr  i:{+kT8̲Lʖ/ iX9dy D:ٛm0\;|A;Ŵ:|u[ ͚T|YcS<ܷLm݄,ϩ >.Ι߷] ">wz]#0]x߶>@B>D^F~HJLNPR>T^V~XZ46Žލ[^f~hjlnpA,(|~>t>va퀋@oY^~阞难E~肘Ľ# P ȍ>)ߤnޜpꩾ>^x8쥾>Qn~턬>~N~n.꧋; _̍p "?$_&(*,.02?4_6Oۮ Zj GEKNa9 *AOI .e?E_bTǫNnVZϯ\D~ojl}jsM!?u?}CS/^ob/?FO/_^OoIo_z?{go_Oz_}O量kOǝ'E@ DPBSV1bd"ҤH*$OHJJV\yJUk@j)ęSN= TР-SRM>UTU^Ś RC~VX#Nx1ƎC,y2ʖ/cSV^"5Wh_… FX⯂2Yra)ZĨG"IDKꝜ:s֐^;'Olڵm=}\pōG\r͝? 2k_Ǟ]v׭C;x͟G^nsm_|b^٭縡钾+/#PRJF0B '0Bp1(: 7C?1 B ODʼn _1FgFo1G= 2HL- ..r!s2K/3L13Ț,L*6U6S1"ʌ-L.*,(yEeQGQyRK/4S "'RO?r ЧJ3NLeU=[ODU E_6Xa%vXT4Yee9N6Zi cuBU [o] V#OI?sRPpu(y I$^y祷^{m_}_ZRIȸa>H9f| ly]C4\{n CMd:j:Du9kVӦ;l ( v;!v m]Yr-&VuJdCqpG6 l>*x h} g@2}#(?xQG۲PIZ)#"H4<jP Pr'4DorZT}\<&UEydS֪*gD,n#]ꌇojњZ6x\:YӌC!Nw4lckp6*ϑӳeXRX  AR6AAGն-l;[`P> pJaSFAչDӣ5W)8$+4 oxzD$Q];װ+g{Z6 l2֬88IfVrkVwh8z!@jNfvQn7$hUҶ~l[D; c7 1?<u2ZpYɆy#6@R<$&e.pr<0s[zl*Gٰtoo|$suU^"8L4h9GQ`b7 8w^|fNw$P4ԘۋU!_Ƅ4C'Ld%oÝ5DjZt&_c8SY82OWiF%tE{ۦ'mq;{2:qSo":902*H;}s~JXF'!YR⏵vEmSw] [ o+Yo]=]r,>it#y+,Bp:J4Ozԥ>uOBIb3\s3%]W½2Σt4<Dpv\ٳ&\p9#өx/~F%OϤ⁣ 1(@-z@i(v=n(-Ҝ'VIve:ݘ跿/1|G~olsw~?}S|Xy6@~JhX0@ ~]D?%}_jK; 3?STJ< @@@ ?'=(dDAkcTDd@ľ AB@H ,M`&K?) 3-'.\1$C)cZ80$A@MȄ89:LtXA*><7A$:C5-TE,4De=34:@Dr&dBr@DSDE dO Oc kGMϊ]ݓ$bCCA@F@R4Ttg4@ljY< ldodl\]^4?)0$vtwxydž1G0Dǡ# zȀȁ{D|,fDdȆtȇȈ# C2DCȍȎwH|""‹ȕdɖtɗԣDB,ÿ CɜɝH BDdG$ʢ4ʞI ʺȘ阏ȣʪʀLC{[lJuG ʱ$˲ŭ'GL@˹KS˘TJd?2˿ģȼKIdtL9IJ;LK̔D`$4DTdtׄؔ٤ڴ D̑l$ѽt|KH$4DTdtNMLDۛu4DTd tLL:K%5EOPL EݹL P״g05EQ cQ0utHp !%"5#E$U%e&]άl)lu-.Q]+kQ$fёB5CED3 HIJJ`1GXL?txS<5SETUURQluOP ]^_`JTTLPQeReghiQeO!df]q%r5sEsU Vތ*?}˩$d{W}qVj~MRkׁmIoP .Hׇ؇~h׳ IGR6_?CWzؒ5ٓW ٕELIPu؈Y؊ew Iz=XxaِYD٤Uڥ5U-ZnJ}P٫XMbA=د۫W5۳E["V۶ڪ=ҼдZr٭uW3I2 J5V}YIe\)[%m 04ȝ2QQѥ\P \]2H͕\ڽ\ԭ00\^5]҅]0]-U荀Q߭\= RԅSkU\ƕ_YʹۼM__۾ۿE$c=Xt8P'5 j z$]1_ 6 `޵\^nХ`Fa`\M]0m]a՝a_4\Q5^]Pa+b%Vtj5r8z9`LI5`6[9.ܒ2JEZ~Ytb0RڠS@HNa>H^2d0L_n+h^dI6_'Fe b2b NeE &XN~OQ.6 ~*bJb$L4Btb'wx#=ʹ|(:{|4(5(:l`gmnf(~LÂb$c/ 6FVh=ٟy]LMc*NhRdz8*GnQb&+`Xd2b`&6iUf[iE_v*^m^^ 0iP^iMi^X-垖/T Un'}f8ʊ"Ƭv,z4L5~I67&-b8-rngp̌xkncbH:[g=X}^g3P|`.PfhބWDI ڹ //:R >e}Y jݾe&ne!]Qfjf~ݪV*o\ gFmfo#1s`kk7nck_:o~X4Ȁ5l (T;Ͷp l>l\@X4m2/;336f^ eg߽af6efۅ̕ZjfZNR^۽a##f6r")\ fgq6PWpƾX4lWswl83Ox._ g  'c2$4q(q/4"\tniUNqLπ_MmNOJOX^ھ")~rS#6Ve[_uuQRNo$k3Gt.5l62_s9p4nnspFs36V8 .x? G>ߔWJ~kkxt"M .x1(Ptb^2H]&a]ԥ&OnO\.rnNx*Qn ސRewffwy{'ٴ{km{{ Vs̼/ 7GW矴Ek?ˇV5oQ7oNR:Vɧw@'J |ppŗٗ}Oc?׿g-7-Pl4}AڗCG{{xMH˜h^BP܄''WUk~Wg,T}d}B 'hv?OJj%V^9[~9k9{YQd.:b9~izo>;~;{Z_; T 0|;_~=B??7寀_w5/| #( jok @֡ cE`H((&"Bρ`:<6!s8!M|A%2Qs>x)6f[먈&r^,X;-Q/V?XFn| 9bnv :5~# GG rwwP<ɹ%3>P G{qJvh:ё}ԞG҃Ʋ.}i8QB+/aӝ拉MF|'O@=M{̥Rkj<Ĩ.3V*X SiBe8QunX?WVgS*ҷ5X\Ul_UX=,dX\.g9 өF0,J+ R=KASю,+U֢%+k1HZֶ\s[ja}umn>{.t8G*H.xibmix[2;oN+SW|9;V/~KT=0 [G/E0ߨ1{Nn3 ۻw5,&r{^;+ě&maC6é2ٹ+:Yhsw^puluuV]qH{|7\ yڙ-rCwkww]Y\<8 Ƀ߰=wU qwK,xݢ֓7wCq՛{'')r|{/x;<|y7GyMYܸu[oDPu>Xf7Kn/ X~/F.W;N3ҵOhŶfeaZ$~:_;ێG!%yQ.F3/v<ރ,zapSw$׫>}lO`mW/!Pn {O˪sGo}s~5]-??u |o}HymE_9\%ޔ= A BLb=\j`f]9\1ެ k]Ù r MYa &`:!.ZIQaQqyjߙ.ᝥaָ!J BN!Z]!a ޶"!b"J>#! V$N$:M%$fb{ltb}"(( )&)"jb+F* -Ι-ޢkb/20Œ01#τ_222b4X5Z#^clc-y#.bc4&8r#9n9":ҟ:cu;Q<" c=~8 ?Rc;?c>N d=b0$;^bpAd3=BR#F:FB` $HbDj JҘJd$ :KCzLEK>MENEO:OXLe+d%Pe8ANJPeYLb%heqJz彀%H%%F%S)H%%%D~A| ?f|!=*0z9;BfHfzQ9Z`fxi7rfx&x5&&u&3毨tf1!:]zm ln%So\p3J*I'H8A'@g!R'Y'obg#jqg"%'II$xxrtJzz$y 䕽ŧ|jdԕg}6%~~wna | fZ^*(}B!q>EhEg`i,zہDp((ǙR.w豱hNh (#h(B f6i(J#~BI]{Z)52c^RY>hj,&izz) GP(¨v)ʩ)ifa6R)ԙ)<)nƜ&*BG6Rj9JF OE[]fD6(*Q葎.jj j!4FGNjު$kEĝjhʓ)*lQڑF*j:Jj90a)j*NTk+bkkrkf󙪿ljUr*s'A^7qFkҫ*FJk,󰫥+nv~*2ƥlrr}z(>,ȶ,&(ɞJl~*vׂmHF*y'F, j-ݶZmmVh(^nn"e) ͚-m)F+>*Ϟkj.ܦYFԦBlrmmn̺n.Z.R.զI΢FoNxV/\oxl"/6]Vzoo骳F,>޳'RJ_:N+"of../l^o:mB-߯ʯ+-v0/po|oVz o _03Ƕp R::k[ /ǁllWqs/wڰ71?C[q=.n s.q1 +q 1#r_qnةڭ1&1!'/ s&{"W1+$cNn.&r!r((Cp'r.r- w, q%.2-2(3(r4C Ks51?62+S[&G'?s/O9_s:535ynNr-2_23: q?7p;>2O6o*n7/>s@; 2O>SAeB/1i2;tDC?j9@IsJJ A_<0-MsGT;RrETHUqVrM3WGuX73OsY4V+/%sM\Yu\1HvItUuZZ/.jW`S]u`t]6ZiʴVujPFV6uvPSvd/0G fm{sʭnv311[vl'ks$Lv:nrrr:wh3nt#:\tuo^^svG6S*B3#w [f+e}f{ug7;/l3Ww7 sqvg~tS~S7cr8pn'8tK[Kxt5f۵rW8 8 kk*R+8sv vkbYpvrweu8+ӮO8K㵐w&/+3`Sy[9kxtx'v q?jzOyW4/spxL-[k79yU^63zywRݥxWzxskonz77G[u ug;:dy: zOw btKcsCzCz[wCk%vRC{;#{v+#:;ϻ9u#sq6Nx^5wg9=C<:8p5T442C1B.Ԃ,B*)>>뻾s;#k(>>> ??>C?ӑONVD7 #9@E`(&TaC!",8bE1fԸbDA9dI'QTY҅rY&cz%UR<DTVjU̘gղsjUU9fպkW_;lYc A;Ww o_˘3k̹OCMӨSg,rogϟA=4Ƹ/JDfI=vm ÔI&N<}J(RLBz`ϡG>NNnߛs6|y;}ߍ%.8:x? P-J@!rP )kϸ^9if*L1/Yl#o;ֺSU< Frα"OReIw+_Q:˺ G,73= &I' S=a2:.uOLTQ̰H:L29rTMג8 QIQ"I8J,5PiV$ZuבNuo#哴UJ[mvO?S6$^ڃeUU'0kessa9r!wK0|Pel 䈔Uo)%@X ݃Pu >0Ԇ!V^:jae 5ƒ5Yv7a6P噁$vac ' SNZ4imƹQ5#V~F高[Z!RwI4kW*[{-/Omnv:O!)M442Xp>pǭ$QO]Mo}1#|81E~Shd-u]Ձ^xN}/lUu_M^w|zS]mH]^{!/|O$S%Vw%y/Z}@ϯcaC9:'폁 F?a7b'?B"QȐ )ǩrPA0$,B&d{_xҐ C%Py?tar"N|GDC&OrHE1NϊW_uE2P# ьCc 6~1WGE|wDaCG BϐD>RБ$PIRE8ze%1;b*(V2lG@F`Β%GFH$J4&1/&^R.NP,YMkҘ2@oQ<YBsLS^;u2(bn4hƑO 4ILZ@*+|`;GY4#`xX@?'j \V R~aH w+}

a22ݿ̰پٷ٫پmm̰޹̰ȥ̰ٷȠپٿ̰̾ҳȥٰٗmmپmmmm;@M$mm肅mmmȂmmmmmmmmmmmmmѐ̾36ٛʼn:̾WٛW旝W6̾3ٺz1 mz1̀mٺz1zmzٛWȷ\̫р6WW\((4(*8mٺ47DfaBCM36f ѫȹQٷc11WO\f|ajmjپ\6..:W1KLW\6fS@Ē5H}oDy`׾y؝Ff F?x.ʱf:+VoD0/ y?\^`}0#A'_q{HRZtuAƂt[1F)! rYWs w~/ %4"vu&Bo$u#r$`y!d9uIA ćZip!`T#zx[Jԕ'<^a W rX3(b9XdtXYg%YuQ&u5h_ޅX/uJAYq0V:Ҙ$fqp*nل{p+b5玼]ْ'mYԝwamq_p).{۞m nAz+38tgp)'"݁ܢ4Atjլv-,E}6L` Jn66Y_"LR 56c*`J/,W(z`(tpAg}I5il_t4qQerɚ)pM9d͸g*]-L:y"Gst'nx4w|$v߀(ޒ\7G.Wnw砇.褗n騧ꬷ.n^/o'7G/Wog͏ /o觯w/o컏 L@xX(C!4;LH DA&5rp߽hU; s! {'C߽1 gB@ AP 1 ~ w`A&Zq| 8XL`a7P%p #0*w`"yE9qFLjߍ0{cyE:qxX(F&=NPB`u00b%y7JR°)I P}!K:rL!*aZ2m q]71Oj|Fz׹!&˭I'߁lg;، у`FwQN7M"Y8Tw蝩HZk.(%NeO3,0dx4NkB 1p}C"v*,s;3L2BR^$pH5 aP">]&=@ FNr _''O_]&_}}s>-h@ip\ @Gt߮-Aк/~&;:u_t#}ozW.p,qӝ^?s{_gB}c 'p#pؗkGs8sNGq~Wq'}G| }o} ~gowsy2vs){w.z1wrq XxW{Gs8g `u`DWwr3w P{w6x}`\؅cG~hvC7,~wR7.X+}o{T( v @|Yx@8t$8wsNGuX0ouY^Xow'rEX71˗~qP'p`qq8{ATPsv'r҇vQw؈[xotpp {){sXz8ppX'qHg (p {Wt6zG4!XYv)j8F 9loȋ9YYnY~̘0ȑ  H(Y)ɑ&.#ْ2Y9ozXjGNXsoxp'h Jٔn,k0kx|Gws#iN l4b|G͗v4q~88rYA)'f}RoqWp{viktrVz sFsg8J5AoXsɔywT/M;a`wY(Ynٛn1閉HIIHל9~9InEsoy7HswsقrxјIGsH`7pI؞  l1٠؏:J_Xۦ-J"Z!j(D,2*:p{9v#{ȌwUgƙrXxPgpHVp3*䇎xve(+dttWEsqsqv []::(Qw(uƂLXwiXxhyxTJ{QxٗZڥ>7Wzh:rptʧAq)(ʷuwxLXp}pu{@jZXj%H9Zxڋ)I7 H9WٝoH8:7ɺ׬3aԊy9JqJzu:jJHzJn-7hwǰ"yW ׀q {  ZVjxp8wBm^^Dy9yo(ǩ:jmGZQSs*x{7k~oW0k)QXNGWunz(pUyW 7v8k˪ףf)rǵv{itx˪鬼s=[t8pwzko { ;.:vy$Kk뼤}˱+m⻿YKֿ <\| ` p(*,.02<4\6|80Bg}݇/&o>D/^P~{vMy<_<:֟&RE\ Z*b2].)Mpvc0곝@?n+ԝql%;$}z#!* HvU;ln |Z c&}0xCo^giQvزFYq&NlbAr@\e(iy  BDK1q8f|Ġ?%oz@ TCXIQ.P4oIs"Tvoq%`yCYxp)VRy/LU2~["r˱f͜⧟D!!T9j<'F" ZrHg=èH`BQҴ툜A,HH9HQHH#J(yЍbK  Tm3INæC aK 3~N @ ӮNEY=t DG^r$^RL+NRz YvROP9AAJT3VԢ<&-eRCW":BL%tH5:F0x%,1RK?T&\BV10ž 挈*VD(/@IhV ^nb{gRՋx8+lZaB;0H C*lUh׊--zH_03e #H[ޟ`g(514R:RWQE`"ܶ&>>Nbjl߶B B1ȐH]tŅC1R\n`813SH*=EJhNiZrڽל'VGV̓1Zir~9@xC&ė< r#hK:Y)+3^cչ$p.rMD+:8i&MJ[Ҙδ-3h`0FMRԨNWVհgMZGtW^MbNfyuMj[ζn{MoC/(ΑvMzη=t#NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xxpzz!z#z%z'z)xz+hz-Xz/Hz18z3(z5z7z9y!, 22;@MKLW ,,8((4BCMRSXΧ$곴..:33?]^a *abln @A4 BlP"E#ZDfBC XebTYAd`@> J(`^ @`A4HC!, 22$;@MKLW ,,8$((4BCMRSXabX곴..:vFJ33?]^a *| ( KY4|]˶ gථݻ˗,x ,pDF^x}4Li|#Tyr-tMUPkP'P۸N@M`v ~7+̠q KL؟0{^\`7; V!9&{~ hzrIK|gf&H&)fEbany':ꥤ:i砕^ 뭭9i}ZQ{:kk&˪)+],"(cR줻 φlv犊쩛vzbٶYr;/km)dbyÒ+/mZ\;Z±riæ [2F\J:0c[L3l*?Lf(?'pb*>ю.qTKSh.5{͠0S.jkfluty3x uM ɫ:Kk" 809L9pB9P2VyTݪ\쮓 {`|ؠ'p>gYv>2Hz91sr۝<=~Bӝ8>~kȧ+O{f[vo=ok"0HOz<Y@Lkޙh7,!fY xƺ~U>]ps b+ M:6@VysbC)j6\ ?2ЅHw5ҫ kB$N{!v<cl[CBo(@aߪbH%}`Fr e6J n)ʐA˻w&^ 0IbSr<2f:4IjZ󚽔&6nz8INqL:!,>i22Cyўmmչ~Ѡ蹇mmюmmmm燎mmm肄~mmm臇~mm~mmѠmmmmmm5=Ml)mȐm.4:f򍎘f4趹fې:~.ۇm~mې:ᎃ̦fs4]ʞffR扦񘠇mmR:۶f$R4m~::ff:]R4fчѽчf:f.4fR(8N~t:~.] mѮﮎRfek;QtjQ$sks4:::fѹjf::H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗ȜI.8sɳϟ@K ѣH*]ʴ)A5JJիVʵׯ`^:(2y]Pܐ V`"`ɻ3#4P 6{el0ǮO ><}oDv`׾y؝Ff F?x.ʱf:gVoB/ bv?\^`}0A'_q{HRZI`Ăt¡@ rYs w~/F@# vu o$u#K$`!d9u7JA ZGp!`T#zx[.ԕ##<^a rX3(b9XdtXYgYuQ&u5h_ޅX/uIA"VXH:Ҙ$fq\p*n {p+b5玼]ْ'mYԝwmq_p)-{۞Em nAz38tgp)'"݁ܢ4AOjC.,E}J` Jn66Y_  56c*`J/,W(zz`(tpAg}/il_t4qerɚ)pM9d͸g*]-L:y"Gst'nx4w|$v߀+,!(rQHAFq䔋!jP暫.^UoEF1GS0;/{l|7m/Wogw/o/x`?S HL:;flAR! GH(L XugECgx:a8̡w(l^(-&:P>"0Ha.z` c(+oBhŐApLd2@ Ё @@(u\!E" 80 0 9Fr\&9Rьh4i(,EhH`Br %%I ;([2}t&'.}tgBӛ )GPj,`H̰gGX|=7P&A ZHҚ@6AI_s8>.!}XH 8at줁;9tU!K0 s@C(Y ܑ(YPA@LȀM0&.CėD. =.@UL/Fa KPX4;R^!-R Zz|#I"V$y&u8ESJ$Sd(PnseH |dd`yV}C8 W_r7XCgfC2(Ud|L»Єn`07)]V}_ew&rWX[﷿U%MXI@'׸s~>"T(NuP2tr}6/Aٙ m3)L_WP0Z($1 ׀|! hWHN_3GBbZeR/)H` w yb.c`fz!^Ɩŧ]2{WKLvYN2 o< pI XuvpDvgn(2\0|C9S8yw<_bYpCo̴dkEsrXS:t 0C@ C^14)!-LTD6 l)[&0!?[Dn8o=$#@Yn ,`Qs_ηn/b(2xM@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYxHXZ\ٕ^`b9dYfyhjlٖnpr9tYv 5G)4Ǘ'2%)0G#i.0yYٗIr3W٘aE1 y)r隠ٙYr鑽rɑyrwYyșʹٜY&!(, J7&7!7'5011212222222222=ڲE֠B̚FØUeiq}yzzzzzzzzzyyzxx|vwuwoxmzl|n|t}~~|snnmkzwjrublrXdlO\^>M],B`=[ ;Y:X:Z:_=e>e=fChIrA|;+33#00 1?B@2&tjaM6  0 Kai q!z-7K\dhqv}(.1/),ANYaeoy{zԀ̅ċ¸ƿߢ׏tccefjt̀ԆڊH*\ȰÇ#JHŋ3jq:Iɓ(ST@A$I͛8sy@< J(ʖӨӧPJ*RDTj#ٵٳh&@@ 8Uݻxgz#墘\4iÈ+@r˘ .ꓴ"o}. 5ӨՊ{!N\ p"D+H Nر}:Ymb{*bνt]#H0˟c_p/gh& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼kY;)&c6}(+-h Q̰k."$ ߎ_䣏oa \Ҽ&ZC<ГO>T+06H8q n VNrtX+ ׬Xh<n+pi ep#ƪ_],6gX-B 2OSܲ=JJ{l2s_Yր  l!hԒp?.7v76 8A@U_+UA;> HL:6;'HS<)j⃴8EGlO7P*I9!UHYAU8 q~(1BL!xC$򎉠kj¿'*) QU6IosbGdf'xt*lqbxĂ asL094 <  ,@d@2p vMncJ!`d%G9bS#8 FPJdP UB|8bzlIВ9$pl H.Ԧa9i(ڜN@TqM|GBծDyzڥ%<t :0E e #P`T@|8@Ȉu.v`!ISt1&JX0@짶l5ҕD"Ibyx酐yEjt~Z>4gd>Ä榜m[coZ6&C/\ m|.!{%-LФȔfE T I!)= CN0p8mo"9uŰ-y"]ӝlg g<-o7B+qsr5X.3HSTIgG;)3ؐm}Ȏ.)]Jcõ7IJ |zpFWo Ǧ*`@ Z<1 R-@c @.!Aca-%ݖ4-Y|.n@ y7,-`ߖY Xw)wt[^޶N5>)6J˥I(]p^%k?yaTؙ(S?mFG jakaXc'G9&OyV(/̜vڜdtr^{,WTZGҳr.+sz^߰#_Nr*`쁅蒤4{G:&QPd:fKQͦTsr®h;޸ 0%Lj@V i',-ۄNg2AuEeE^d[D9tjFdT7bC~_D^6#\rMMH\{XWB~9EquYg@%}U/8biqx1zPfYpg'y6xK(]rIF؉G7\؊*G'xL8@Ћ8XxȘʸ،8Xxؘڸ܈mҍ8Xx蘎긎(؎8Xx؎{߄WINy ِ_ŏQy!DK "9$)BA AzY.G%Y6y8:A*$_C1dlą(/1΄k8^t( 8XiC QD[Thij)iY] T0|鐤 w xAɗy y %Rٍ y ) (И;)p ٘y @CM32V1T MɆIKɔvX [nY p0։( 4~ٝ nyyHphU)P]Pj9I9XIYT) HɈrpH &@ 9Xً  w p &($(ښX !jyC:$*&4EéFdC-)ieɠ`ziר繟*q ^yٗdyI٧bʐ` $`ڨh |8Z 7i jSɕQ ,ҧܫ@(ݚyШ,){-׿h)ms:Zw-ҳC%=ɛ+i~]YKA!w,.ʮF(-]߰ho L<ƍ͐-}y = Խݯi ]}&m8 1} M> 3G.NK * V#QT3dO?d!^{|Khfc-TOF*RQ%w;xfjI>r%QA>`=Sg!uQW )uSO.w5U}ŔtY_'5> 1U.-UܲU.9_geWm↎qrT@ցQNX%wUYX~!Yz}fxLZ>Q~YY]Y]N 8xZxniV,0~ %]z&V]'^fg`X^/%$y7R}Z F`^6YF`!~($I`F6~n &p2b"ϡVvJr7kH^eN\nC1cHM"P6q~1oEdc”zQfwo7 gRVreeNe7Tf#FM5/O"/dOmfJty$fq它(HR6PY.LBS·5ixcox@(ꂨwDkuq(PjYl0Bd(z#nq]z&vݿX7('X~O,NF&:l%c `201[r3@2? D(%(-ŲG2`2 $1jƼ/Ch0Ƭrp2"#Ӑ*sF8[щ=4sn"ܪ 6PH0ML;@M92?|436S;S;QGߋ̫%"?󌀡G7u :I4@OJHL*(Q*Xze URVN#X'%h™@UѲ\_Q3\ե$"G(2p/W*VC[BXJWu/VU^MtS4jsz AܜԴC8:F=o7o 喃9hP3Nv9g@U(LjOIj* 2% -\55j-\v"X1-c"ܫJ|쀴mkRm=ىi&/qD()/0)nm o{묥aB_esm2F9Ob:D<|G?}t}߇?~"@hw$@6Ё^8A VЂ.AvЃaE8BЄ'Da UBЅ/a e8CІ7auCЇ?b8D"шGDbD&6щOb8E*VъWbE.vы_c8F2ьgDcոF6эoHjʈH' яd oS#@6ґ|^-hўCQwdd`FUe(ٳ2ItWgNh+c+D_J⑓e&E9Lb,%84`Tҩ\zi&Gaf"wyNvSd19N@F8Gu’U%ocFG=rSc0IN44%8Pʌ, Jy£4 er"o} 6́nӠ'Ei MRyl3р '4)$(ߣHY ՗4iJ+FK4#V_B4'eް"|q!PCOCU Iej\x,-%Unկ0p䕪t˥)ld%Dk s T]'rMֳ5pŶִEmjUZֵֶmle;[ֶmnu[ַnp;\Eq"̅nt7\J׺e ub׻s]Ev)\Ůz'P/|{]V},غ&:`ƭ$ oC4I%S0&zC=kzCO}T(К9KG9Mؠ@04V57Ϭ:qPk̙m54͢ag%ovvw=Ɋv}D\Bn=p!Gxp7x%>qWx5qw?rxD8Ar?ꁧל"T|b|&Gl>2;oUe3A&U\t__y㐆2Ene-Q_(U=10s׿.x#fY?EJcؑwަE"di4DKlvU=?S1r&eixsHýV+{̃O_-dcf1fjwW~րʥDr">I??c ϋFͣo4)P< 0@A?4D7PE\6pDGWpCDprCHDFlGtD2)/Bz.MdNDP\DQ,! ;*hEWTCXdDGDZDy%$)/WJUC0`CaTDb,F e*^{>}G|T &;v|wlFܵyD ySDž#u1lCaG7ص7@ȭ2 'h҇)G~HȌĂTĎD@hdA"XWj2')k5k.삦lJll@HG+J; $ʭ<9>G#K=Ĵd˶t˷˸˹˺˻˼˽ꃿvKk@nj>X,̻oo|̫Lk|8|dE4qP5LoHU.tlͭL؜37`<Hdڔλ2N嬈h,eD}"=\`\{G:*K#COlj;$:NlO֔ȝЋşFp |78 MOl j :[+P K$U $)6 59P=xЎeܧnĒQAi[@9 Ph ] LArQ@ ؛)Y"Қ3RNpSo;ʙ_RĆ uS7%4MSc<-S:ݺ8TABS?EDUEeT(GHFFIHTWMMKTMTK CI-1HVM1:ULMU4X\]YZUU]GU]>ތ>9BHV[VbuVрV_CFj-kbmn׉4`V4Vj%}̛)2\XMm[Wf=wfz&4OQ;ʦm<3aW=0hw:"$~T}Xve֗=((@Y(]Y˃3xY]YJ))hd=E * ZnÆ-ژZP2%E?~\\@8f-86Cd֥]Fn{dE`$s؂RMd6`r zd\\P\eBdWKDY2ߞ)_@{ 9i#ԫera\eX}!߽( k"ef^"N`]' 1?isPoff!`"`rQxgg+fT|! hb+ hBm޾҉-&i3Y0c㔞7nib7A7~cIjFU6FVj5Z꧆ꨖjn4ꬎF#j3 dB.kNfDv]Ln^뢛~kҍK~l0:lkRŶ"ve.lå,lb^\ld: l'Zpf\֣lRoQn/zmp6bȅ (m/mybDNh=zp?Uml^6c,&{mNo.booo2oo)o,2ip.p+:pi7." p "qq)_"J`wWq) !""G$W%q#"&(r!w'r%ψS-g*w".'r+&s*ψ32g"5r1qEpsgs'$<;W"@=q-sBqAO"FqCo"H97.0Etwt$tK J;EO?Px'RpEp1UuJpu#@S]>?o`'aqS|pq_ugvhoQg"(klv!nOsr"uqowwtgww`zyz-wbwGu7J!xPDۈrD[MyrD8M?yw9Rũu+ޖo$PU$Ll6(7h6nlIp#G9h5y>ȋƩ'H]zw#?tp2d- j!-z%?:pj볐⾜ H''6fgC|b\{aZ}@[>֮'7GWgwէؗ٧ڷ'7GWgw}G~;~2~* #*?J_j  ,h „ 2l!Ĉ'Rh@7r#Ȑ"G,i$ʔ*j\%̘0[ʬi&Μ:w왒ϠBrJ(ҤJ2m*ҨӨReBj*֬ZNs+X^Ò-k,ڑcӲ-ܸrj}KnPx= .l0⌉$1`Kܐ̚7y3ТG.m4ԪWn5زgӮm6ܺww!,>022mm\:f:3ѐېmѠmf޹:ʼn:Ƞaې:\ffҳ蹇\ffmff\fmmmѠmm::36mѠmmma66::$mm3ff:f::6:BCM3:mmm̂mmmmmmmafѹ ffȹѠ$ѹѹ36f:f3:؇%/CMf::;@MKLW((4f::\㫅3a::f\6::BC:q,,8۶PTCDN۲ۀѶ\6ȭum* 33?宐..-m,%ȐTQablH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8s(Ϟ; JѣGDʴӧPJԫXjʕbU b83!='\S!vdWٷ={Cd ,+ oȲFTD-?08`G+ Ye BA.g9dC#35֯򾼡nD'Q }тȗ5PVZ|,XCAx jQXu01GrFCV'Pkm@H(u#d"uFp.NWr؈#@L2CLbJ]F(P P̷ރQYBZnfHs@zn s%n+a>2o"dqCZA( zA(<\9 ǝ[Hڦu6 *wAd&@9찈 hjHѓ! (@=QXгzǬ^_Q_ʂ–6`EWcۮK,Rpp6 Q]t90CNbrl)ŭjJ*H-YdǞj+XhqE2$6#!DCG8Z)سf0!%WYNfz ޶yVYn (A]ﲍ_y)f`]hQ*ȹs^ӌQhQ8oJkFKgM;=fDa4'e96_zKЖz.ғG[ <\w*LγOi8$ l m `*tahy~)+[F$(Et@TˌFF"q*l)JAȿ׮,tAĔy4m\z^*iG aF7oQlVU0TdX9KeA#!uqӍjt=Y.X%~$pg4J$%$)(Lrd05QUY.3sA"d @ZVt;H-n.LX; f 5n٪ˁ^8-J^פ5[bn-ƟaW*{s')JC9.C"Ȣ&C5M>NI*H3w%OӌRAy*1 P"ơ+2ԋ4Mi&TJժZ(Uծz` WPhMApJ׺xͫ^u `KMb: d'KZͬf7zHlҚMjWֺlgK-h';Z pK?;r+ZޒvЍtKZ׷ɽp\z xK׶yg@ʪ',}'kDeBO:`e2XHd'[@8&0B *{>X }5, o&bX7Ae] ŒMV\YO>eb Ŷ)K'<,'X\pl _@ =d\` ,1kV"T $+g:K@י.t w,8b˞pS@bFz5 ]ZR{3/O|^`g>/\sYZZ5%k$AD-gƵoPXWɮ)k.](nٞdU[ޅN'ω3e{PSϔd5aV`}_Gߧxg qx.౫}3DVviG.eڵ *SS2˓8Z浔inns[& p.XYwW'*X\0-jMΑNuГ: l g Y?B-^g|lʖ;Г <z̏Z< d۵s A5w}cڞ.>n{}۱']3"֎~ZٰkӌǻoA[xIW%pQmg?f^izAQ vxYoGYo|i x o7vw^}t? fgȷeׁr-eksƧ{ce8[F8|f8w7m>7|hv)|EcKb6nUFmnvl>|%W'YXGYffgTjWX_wabvhwWpu@~\^  WYvup hjxvhhhH^(z.|kׁNjLxdUs4&>{.r;8Y(жe@kXsOt|Gڧ}Ym붋mg4@7WpX~hhoipeZsx` yj?Qo`q耄oF(^y1n85-7{0|$l&Əs6?s7An\xKn8fm}>UhYvbi ƀ# ~qYc3 ^70)pfgoׇP , @ YagjWph 8Yi``MI|H^m8+ke tGr.xՂAgy6b_568I[b ّ(eA|X'~vW_YbȒGw(y>vpk׆b@ lw t G)xGy_ww=1&`95mcMؕhnfPbfePlXd*őɩnT|{)[f>`i ]UA\@ :|hvZjZ 0 &yX{izmp[_Vf"^5&z(8W*ڢ.0Z]iu1Z6z8Z^RH9ڣ>YIBzHJLڤNPRXEJ 9XZ\ڥ^`eu;fzhjlڦvţnr:tZvz jx|ڧ~!,>d22趞smf:R:ې:f.Ȑmչ~ې:f:̦ff]RfRff~mюmm::.4mm:`:f4m:fx6s4f.f]::s4::.:~m6Rfm~mmx`~mBCMff)̞llѐ󇐽t~𩎃:fss.4f)R::f.]~ўR4:KLWf::xx((4]fũ ::fx6ɰԣxmЇLf:no;*iBC: t.:GM,,8++0t8x6x%۶++Ubãxx6}`  /{w:7Lv7xLx~y/CM+}{$3?ɰ!ΩblxOOqe!.:vvCD;sȶŵxx6:Or/Sxx6 ȐT)ablQﮢωLu̦iH*\ȰÇ#JHŋ3jȱǏ C: @ɓ(S\ɲ˗0cʜI͛8sɳϟ@ R ѣH*]ʴӧPJzhIXbʵׯ`ÊKUZ]˶۷p%y6@ڬs˷߽un})YC,\ H J㬕 Z݋ԦM;mDXe S^=(b$_λ+$I N7'DAÃ>q =u$E<؁UIMx` WR]vRnYXi$@dA 6v'|g@&@xK Lf UX#aLy ḛ\X~ׄ1@|G%LNByKGRUBu%]pGI~Sd%'Gfz^Wg|M0M[>`&TYop9) S0Z%1I EtX S2J!ܠb"|Skqp$0J0Yzd\|tI&ZAwTy '$G 4B=2ޕ]-q6g@ ZI*P r@=zJ*@dG`lDBA'5L ¢+.$~uifMJ>l|<[1\F41<^bX A4nR{`z+~R G{I6[XQN~ gt!z`Tp8.\+YA~PUƚcinmϪ$;QbJJs 60g;++uHp1ݷ`_]dΧlpܖ% U=/d%öxf1)?hP} (fVƺWL2},7"b4hÙ<İLi +%@!p$4Z7S- ,:a A8Jf[ nWJG?Tdz..ʛ&yyˊxDnxD䎷dMK8r_I5ĈB"E)Pcl7ᢝО3򩎅#ZҢJ$#~ǸXS6 8XYLBUd0st+ t~ gX\4q[c>h'^9ղkRbu ~Xh(7.yJxcJ>##2n0$$RDCu$J" 8%t`tP@ $^AwhJ9t !\.Wi^uأ $ p=xl4D=^`?g™^vB^W6 xE*>3QզHa~V\pt%2HHO#~$W*sn賏a%Lкsq,Z<4MHS`Nj;iu*A (}^jƘnX)MwG+AW hd^)0{$fֺ]fg]-JPǗ餷8lpC+m_`*^=KU!{Or]B@DtM/[A K*nċ¶ `5<Eΰ7{FGL(& C8 ,B\,8αw@L"HNrZ b83!L*[Xβ.{jBYd(#` j6po12œ>π_a2F;ѐ43t- EGӠGMBťP3B $ ,Rָεlub hag`%$vf;1 &P+Ph{7  1 @B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9YyّȘ " & &)wђ&49d90#ٓ(908$9FHVKJɔT1 tXXQ U `[ɒg"AB&`U)Yqy5)SYzɖPobl",)V9 iYk&0mYٕczIVsI0'֙&  pɓɔYw`' fԙiٓrٜ=Y.9ypɉ9铚Ii޹ .ع96\ɞ9b)U))Љq9ВKY4y٘\)I4߉6Eɗ&zYry422m\:ѐȠm3޹fʼn:\\faҳ\mmm36mm6a6Rfm$3f6:3BCM̦f̂mmm]mafms:]$ȹs4.ۀ;@Mf36f3: %/CMRKLW]fȐ\3aR\6:TK7*R4R:BC:.:,,8.44sCDNP1۳ۿ\6ѶB0%((4:...-宐330mq. 4,s4:ablH*\ȰÂ2@Ǎ;jȱǏ CIɓ(S\ɲKIlQ1q"|ɳϟ@ Jѣ5I@ IJիXj FNelrS*]˶۷pu 6qE߿ nKюa#KLr7m]qԥCM?7~H̎t7?6M۸rAs1E.n(!C]μ9УK>չ$PνNş_Ͼ˟O2-(h& 6F(Vhf" ($h(,0(4h8<@)DiH&LڈPPF)TViXd\v`)$nIhli&'`"-b `@|x@@xBP gKE}2( t:J'HVz 4*0" t c " %D >j@.k*:(m& "Hlہx{A*2D2Ђ L~X@}ZoF'[hA&pȰÓ'N0ܢ+A`<&(0֐Xmμb/C~34+B?8":t=uHG::BѲv@-VR`rk1d7ǎqyƔv!nplHwtW8a6p tG4@ U蹳rn@І ؞^,J6;zW[]:GzNmBhHvwZέ7 a>zL #?>9XpƂ}ܳ"g@ o}Ԡ87bL :eҁmS2AqQP<ٮGBxPʠsG+ Sqz;x7LTwT"5>Q) x[N OrL.kLG]pL 7oP B+Iӥj[`iD~Y8y:[36 j@(#XT[ eއU`{Ȝ) .2bcҋ֛ݡG7m+H1Ey93VJJq J"P#rX@T*DҮUP[rfGPXTb8ţ ZT+LKTԔD<_31EN8 ΢t݌?sQ$AEEno''}nyTmvBAwKԵpuH$EUc [b&yg,Eh5Rq 6e6 OlDA3|]D|֐Ū Gxs|4@Gݓ_i~xv5Tf,΅3%^?T^U]l$u. #GʯzEęiz7QCSiig#>?U`~zh $儣`"D[;75|2~4ni\ri Ez9F %2sXyzcJD˜8jhkD_m%P`Xβ.{L9]-)HȳMBHA@F;,J J[a@b0xӠ7PԨʨIV.Y5aMZۚ#8}^bjM{ Îj[;?, vA<*\>Oa gvOg>B< ;FN=Fp{ i,c;ᓉA" D(O7q` (DGNr0DW^!,>dB@Makxy{zzsnlmtuw}ٌ͏ֺԮqϤbȖNBq9e3hGjZorolc}AlkZg TeFe9ۈH0 4M# "υXAqXp+03P]Z:\ W|nǬ]`@9 ]k['On[P!dj]]HCGS! ӁDA7zY5V6g1˦ɴTXM"F+;Y$| H_*S+䨪׼8!Nms}>,Yn!2U1յN+԰alM;Z׼Yzms 7@g}K^ԺҰu+0JOkTgI(SJw[VxZ3G qO/6\5jkvQc.O^kXYIlbUt_Ĕ Z 40j2+6ɼJ  0fbqP&,ewe-lik񎒼N̙PV /t V~:1p՜],-?9\~Fz1tcޚuk7dz 㪪<&:ͧ `Zkퟂ*_e&dfrcRgFn{J1ipZ)7 :\U<=a}Z=წܶ3z`/@! XcTwYx\q0+.rn7F[˄:OzJY1حbJޚv{N`x-<ܗ}|ڗ,D7&췱;502h;G Z-ȥjAh<p &DA Rݩ)@6O|Kjtm/qIUAt04/WWs0o D02."|3yvkc)CݧuD?aQt;]Xf>'=* zp9\O.ԬEm)X̖:kkz/r9m)EuF2 'Zs{An{`(z"c]6oFO"WvDdaOp%rWo=qvw}؇wS\wR~!0~y%QW%\bUbтGkWaTQvTX!PFs%mt^WtXg[xJ-wwgSXI2Zu {Z6x}O#lx,oG`}~w)vX?wN (NTxLqJx(PN8XxȘʸ̘M@8HMЌؘڸ؍8Xx蘎xDЎ8XxH9Yy ِiY}ّ "9$Y&)r#5P4Y6y8:Y)+钒y68@JLٔNY=َ?HE K@\ٕ^`YQISi]H)g鎊8`p}|wTwXw)}5WYQ!ЎF!5I,=qXxiy8S)RHSYSaY81SDTJcIUOU\UhfUD`hd ~p}ZPܧQY\YI߉i営&!`<YX)َََLVH Ț؞ٚ,Zvy0u厹)񏻵[X|vɜَ 9U~iI#3 55FiXif@j^9 o4`lK)%C^ (NE j@=LɚJkIVvI֦e#ap%h('k `.S2HV!in9#jjZ Y_G&o>т (Vp]`{}-t@U bvy:b7aerkKɡ~+#@rF2D;sfsks3HZflI:S0') NzF+&iu ʚY*J1ȩc:Z`;Ʌe[ks'Bٶ,HP0x[߉Kz;;xk= 9zGG .ѳPzҚ=ǥ&y؊{ɚڭO>A" .&|aṰ;dKp),./P֫񈧥V9*˵KW_K[*YajR;Y[꿎I6˭ ɚǺ]=% xŪoR[ުSpEbd?Ѯ\OɂNwnV"f)`s0tP:wjCLKhYIK QZi !*o?ZţHkL q쐎aLZ8k{ p)`Msp_Lgj y(blt H@y4\X uDK { Τ]s`K\5(*q.=4]'6@d09@ 9D]F}HJLNPR=T]V}XZ\^`b Zf}hjlnpr=t]v}xz|~׀؂=؄]؆}؈؊،؎ْؐ=ٔ]ٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڪڬڮڰ۲=۴]۶}۸ۺۼ۾=]}ȝʽ=]}؝ڽ=]}=]}>^~ >^~ ">$^&~(*,.02>4^6~8:<>@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~舞芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_dd@>q6lX`vo,p]Û_o?6X=_?Ovh0_ם3Z o >go /UQpo /h?}1#X0-zf *d8 ر'b YgD*юɓ-]؅E56bG@,7_SPE+>\"=hF2J@DpRNi؆X}х 6|D ݍpfmѭ,(cH7ZxuRK.m9WV-Q8ֽ+q؈)ux0 ݏ!&yr =9s篙C;I:fѮ6ZkxAͷTK< %dّbx/ 㭯Ƃ > N,L{BSB- <=ȫh=?[ο*/t P IiҐÃиY‚Gc1{,]FkqKvJ1 LE(|Epj?^Ȉ-J < :i"+D-rs()0LPŶB%;4OC.%Ծ$ϕRZi4M4ۘpԣYLh>ee)TB[:T-aVEt[PeMV1JKXKդlq-J׳zu7X8PEV?+]jPNبE[3a5?.*T eSƛ"5{ҳLxL+ѻ).h ,ҏ$Y<9W*8bxwdm,w:SŁ vnGWbL,ۖ&Y c/+zllNZvW'zb)M, ;֑ٝi"홯uE-sBתUb ANuOU0+0P=(fPf67ގvÜ̟l,)Đ7 tHw;0Z]n3Sv>]@ObJyNݖI>n}j`=A2U1|w6loӪI0us5kt0O]'QR5uH.48ByٔH@($bcؿNg7& zLSZS%Xz]}e$a1~0B" %&"gήЩ"ZEp;в!(A4Ǐz`$36XW0 TI'voPc&Pk{P`FLlR")gQuqSaʑzt&vɑhD\XQJDVy9kə4˔0g )dfpGNil~Ve71NIz0y*]+{*݉\Jvm?/קN\S#Io0'[LZ*Z*2KhL %#ګ>GVLHC%rVP `UxU'NQ$@c(֦(zRcZȐn4(frdFUl`;XְElbX6 !BH(c5kX5Z6aj"͖vy$hŤ!,WH22{RfBCM$̑]̦f]sR s4.ͦfKLW]fR::,,8((4.fR4.:4CDN..:R33?Ȑ.fs4:Ȑabl@* #JHŁ, LaNj C9AF64!၀0c,$Bn̟@ JthУ1*-)ȥP5::1UT UWPj@ٳhˊ۷p]KUݻt 7Sm` &] 2Сcȇ6n DЙ҈|@t֬I\:5; 'f8`pݮT&xx5,NYpϑ ٺuّNg3ns3g+޹}n+0~`h& 6F(Vhfv 8((@."*z8#ވc:a@ @ HZ$"@@XRf8c x@&f- " 0@!,g22l[53Â5Ƅ\^[4534[^[^44\\353^4^\[45Ƅ34^\[4 @*\ȰÇ#JHŋ3jȱǏIɓ(S\ɲˇI͛8s8RΟ@ J(G]ʴӧPJիX?*Mׯ`nٳhg۷p)M:7ݻxe߿OLH{|d '˜t'Ma)^:ְc],۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Ķ `gwܱ $l(2*' 4l5\:2>m38#`@J@TAL/M3H3pA@ ttM7l6 D\^#p"mu{=xu@3AmsH@M 0`Ail d/v霛%@&8֨n @>{7m h@;9×̳p$LK|Ɂo8D"cKNP@95'n}H2f 'H!,6522Oꪀ[6Ã63€Ȇ!]Z3`3[[[5635 ![``5]]Z[5Ȇ [563]3335`:;F3`36 ـ][55`H* Ç#J(qŋ3FǍC($F&S|B 4Ђ'fȌ1 ".@4̜R@L52p!A 5M+å<46T`@WAܢt?<`Slio+u`ƐiZP`@Dy֧L2Kh3onJZ޻d?d CN_~HfXL v5$:26]ۖ!QҳSO_r=+O>Ͽ(h& 6GVhfE ($h$z,8.( 8-(8<8U0#B)P 1"$NJDIb%K" tA]$D f \ %X,pb2AbЦ^ fXY٤h=j&b)^~j8De%*驣2(魳Һ돽c®Ţ!6!,6=22q秀[5\83Â5͋#Ƅ;?K\3\ɳ^>?I3b[\545 34#GHS_^[^bسQ4&&2))5b458\\352:J4^3^[45\8b38++7 Ƅ_\_834^\#00Ͽ(h& 6WVhfE ($h$z,8.(|81ˆ(ȣ+V>( B( @ )c<2iAp05I!v@ ,]N:@ 9;: ]`A\qD+T@' lU^ z*)@I a*D [rb@t "Y9*-6% 0A׭鞡8+i8,"b,.쫛>N=DPZf[@nFVkW·"x߿0BP 0` ;1',Q g#@ /" x LrY!1,"! ! 6P(pAPM.@7:8987:(~D^S8aa _ ^4a@aBjJoEw(;}02>&PYa hsȁ.ӎ;ٕGߟS[agmu||ybM>22221212122222BD^ibghhkkknnnoooppporufVSZ`etߟӣגُےuH*\ȰÇ#JHŋ3jȱǏ CIɓc\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧ<BJիXjʵׯ`B*ٳhӪ]˶۷iKݻx{W.߿ L~+^̸ǐ&L˘3k~CϠCMҨS^ͺӮc˞MJsf*K.tf;B( rnZP,n}&v3LM$'_"t;{_We\.wBҁRq璂2!vѵJ|٧R~;]ER4̵B*`*4c7t^dDiN T~$xP @+V^4\vBZe_?7*Qۍ(0ŕJg qyBA( `JwtޝX۔Uv%7> fq9@gm6Z^٥DÛ*瑨:X+T}"3-aDYXE ϯ݌ kx%?(@,&2D3BuklP? ,+,bkA; &m ])rK<۬&>^- ?(+o{{Ϋw ,$l(,0llsrqdAF#]DOh]ug4frXg;o>l⎽5&X_*0k6nz.,X:`yMD࿪@ԅ ZsΐG.Wng9:9Lg2Y kV4O.tySsS(U{Ɲ_W ËSkRY{P{߷c? c,:;I/1$ 1CBX!m,V01k9$5tal}SObؚ,o׺KaXD>f ] -وqG"HLc?I7YX`t $;)DMOך8.+[a#p'qIJRz}KܚHAcJ}#u2Vj]*`D$x:.̤&7L7덶?h,L*V,+gIZ^2e@`L2obҗ0)穸E̦6fr 8Ir̛L:v|~)JЂŤ@І:}B#JъZ(F7юztHGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢ4 )RԦ:PTJժZXQծz` XJֲ`*Zֶp\V耮xͫ^׾bUIŰ& 8*p6%VcUYKkYP(ijKZljW2vb7`Y'mmLz}HpZѶ5I.7vzemvU;^.@ P^"ץ'@@&RͥIR LنUm7Of˰',C)ta{9MH7l* kJ@e;*jM-C2Ra> Z8%V a.HNLۻҷC {#Ȱ h9ͰdS[X&3.C @}ntY%!|K ;ߪ,F;&oo[ /jЌr&\4˚,-`VmPWV^)}67 i v,Ozw?MGNK#-wØ>L<خδi:lu-j:زq=>욿?%Z[ηr7Ҕ@WJfwY 3 -𘪠2^sU⊝dG:OW o9>rz;\j_v 2~+Rr3SKGW0qv)qӶwt"7Nv,g+g_ֵx{T{doOO'O> ϼ7{GOқOWֻgOϽwޫOO;O|O[ӿEO\ͯ`e?O7U"BVXx ؀8Xxx$u؁ "8$X&x(*,؂.0284؁)})Ѓ>= B8DXFxHJL؄NPR8TXVxXZZHhb8dXfxhjl؆npr8tXvxxXWR.X \8Xx؈B#u-YTGP 1؉8Xx؊(T؋ˆ(RJ0F،F@G 0Pxؘڸ؍8Xx蘎긎H'eA8XxX}p+ 2Mp  ِ9YyّhRx(*ȏ)T6y8:<ٓ>i!YR#%9,yHJO-11P?yXZ\ٕ$=RHEɔhj8X vyxz|ٗ~9Yy`9RbI(lYy9.Y,1GЌY,MИYyI)RReIgyC2у DpH yșʹٜ9YyؙܙyRE)y虞Iɛ05 90 @@ @ ʟz PjY`Jy0*d@IA(@*,Iy-Z6j*]Р:ڢ8$:!+*3j&5, \^S(ě,Q SM=^ @  <:{)Y$- . 쌽m$`|чل @הј=|]ى-tϦͽ(ۖѠ}ש %,U C(=-& pt]bk\_]}ND VAUyR%}~>疲sc]nZ TA_)>瘎uI踁&~釞_u.}g/agZz~N쵖ξ>^~ڮݾ#>;urU 43 3r&(D(Zd} ނEodN!  oo ySdN&a&뵻)2 B?D_FHJLNPR?T_VXAM.R)M j|ɑ=?_= y_$V~/z67#O>@EN/ w]H0x;j>@Y?_}@@ݭ }n> _z|o pd b}sO|O֘O/5_==OŶI@A0! RQb5G(&U=~1D-}D2/ :~iIAfƼ_ pW4 In|  <_ :TU'?Ue9Ge4/D98}iLhɺMSԯBM*P! FXbƍ?Yb* Hd'̝;"rsOMFZj֭][lڵmƝ[n.l!1ajGJA@1Vz,ܢN1E8Nf(2"jv*h^lƯϯ ##|Oۏ "*lp2G$DO,.L3#^1FB4̚$GwG2H!$H#D2I%dI'd7pA<349<.B1(3M5TM7߄3- "3O=db4N4PA%PCE4QEeQG4RI'RI!+ 3"" SOET.!-75HNYg 'Zo52UD/O XcE6YeeYg6ZiZk6[mԡӉ5]ue]w%>p^{7_}_8`&`F8afa7UMō\х7c7c!{سd#p8eWfe_9!NHb+)\2c:h _1!0b :j|iFp$:l&1~Xi߆;n> ,-/n`h`{ -xG74qH(*L$CHI!l  9˓!ICnlaJ pj1\ STsUlDf2єeXR. DHMI{eS5rRlX6MYR^"@]{T )6=dh7l*!aRfF51f,%e,?'yͣ~{(㜇 yPFE;wu`beʞIġ ؟ΓM'PB/l +i-&$o ʱܠ 6`C֬]޾\B٦R C!pv-yg;&׉f}/{KJ7mY&j҄>]^*dk|HQ8,t @"Q*d*q3"/Ni}s_f-+XǼG !eEbi]~׊DN.XB"%b ld(Rbu%V[RN̫dwc 7nkɜمP7zd)+֋"pry{(򕊫$PY"[8P)IQS+2DQV05d//( JUJ=e#Yv T7x:~!'hy.& K+%,f#r.Hz/﷿?kCWwvr- ÂNpuUBK23a_Y ,^d2'8լUf5&`b>+uFU'@I%mZnR$߻^x " M%F or9_iQ#ݭgWqbǗ̽k Ļt:6q__Nl89)%dADg;_pz g^?|DBEFBűB?_}`_A y٧c'B zz挣_|ʇv~Www ގW D9t,:DA/#ACA!F$d „ 2l!Ĉ'RpU7rc+1(dȧ*WE˘2gҬi&Μ#u'М$-zsѕW@2أGSTbVjjUZr!+^hI>|5IزgŬ/l=ٴdj0Ċ3n+A& %L`@3gϚ'.m4ԪWn5زKcDH'!0gk"'nJ͝Szt˭s/=ҨN3%=ӧy6_umQn*1A *`Lt7tmJy7!j]qasxOgUV7WՇ{/8#5H #=#A 9$Ey$I*)  T,5"4QI[eZ &QcEbT&wJWآU69'ui'}' :(xB!ݣePUIZ bRzdr*椚z)֡ٔⱩC❵z+e{+ ;,{,*,:K}daۢM9vɑmݚꭤ~鶕bafhaj.sjTq/y{:0|0|h .k{m^֑ g Zz:qӪL۔1 gV|3=3A =4E}4I+4MEje *2!k2alq$<`=< RX՛|7y76U~Ug|xskqؤ^ٯ,qkc=G;ի>z/6NϯO䣨B7:<`|?aNBc ? ʤqܪQ7}!`Rp*Py]^`Ұ6!s>!(!F<"%*QjS (Vgó;BYl="U6+fNbDxFmԒJBm1_1!ԩ8irCh=2Y2IM, H)$(CEQ<ﲸ Nj|%,c%TMҕ%0IK\t[&WV0)iNS.\zm1&8QiM:b3= u|'<ᩅYoj'>9Cw<+ ĨЅ2}(D#*щR(F)}&$(,!(JSҕ.})LSfϣ)4+ӝ>)P*ԡF=*RT& )T*թRPh2wO*X*ֱf=+ZӪֵn}kZYv+^Uϐ ɂMPR8,b2},d#+Rc!WU,hC+ڑ9})~ Xlc+Ҷ-ns򶷾-pqˈv$=.r܌U{ܩւе.vr񒷼鈲z"e}/|㋅Ġ+HbD]Pa/,>0 3~0#,Ew#=/3a6| %@3h$o/Dи61s>1,!y ;58ȅ7,)S9f_ס^2,5l1HVM|!@6wFw_R4s̢f4`qqCrf^4E_,!yΚf=#}ބWb.8`fs2YӺֶ5s]zj8PkD:ғl=#Yj#/v hLfhΖlewu[se).w|z;e. <0H|ywӿ-.-dF̊X\q]E]<F 5޿_G A]&q@A @Td] ` <`᩠ɠZ!&E؟>ah8~` Y lW @E~i IF x}Fiަ:@ gTF \E`fL"%G(A&nbUIaG%!"++%:Ur"-Ky"b(H)Ȓ$1#2&2H->#42W.x.N]/It7~#8~#8c49>.^^(j#J<<#=֣=ޣ=F˴x?Lc_:b;#C6C>$H,AEc:5~YXt~$BFJJ$K>DRd&^LcFFzYG$/Z[I6L%'d5 ڗ^a6SPT:QFM"I>VVTNW^U6UANF]Vn%ZTW~%[.[X2XցY6eZZVd[ѽ%M[Y[$6$^&7%_.%^cO"dnb2ec_ԱAdN&iSe^&j&WfNzht|Xiffjf s#`zkHڥVJ.rn^s"j}&hfqVdA>.xFn>yUtF]RSjqBJ%$B bVgb~jDSyT'd&bpvHZg]]Y"`r/'V((ޢozph*(?TqȁnD@~慆bhvhI~hJhfhNrJgeĜ%`ęڅ!WX]hڞWY[)0 )EqWelrw|ցhnDZW^h lM]Z[[iP6'jKi}%iv&hI@@}nD}Yeqݗ'^y]^*('GV |ŋڪaY@j^[~ňk"]XjLFJcwc蒪|],zNhhEr Db,޽dRUJg*bFhkIrĘ @ bz]ahD} &\EZYlY,>fmCMkAʬF,MZ-Ijr-Yzd]'G&mmrŏ>ڲɺ\R~Ɵ. &nnhfL.*2.ςj. v. ) d....q"hb-Rr.~n9/H*Zmf/|L/'׊~@o}po:,/GSK/֯<ߎ(.Hn,¯V,07?0GO0W_0gc0SU9o/s0+vF&" '.ך&o + CYp𞎝n0dqPAOO1I9@聾/SXATA/FlqamzaAHT fq-@荚bұt)?D&LrgY#j"Al?sj&b*#k20&(x2AC//9$?|0r2;eX"T5Q 15A?FۙYږFZ3X- B$3W>03@.O'3627 7^+ A#빥ۿ[h"- 3qst04')2_&msC)4v.a{!&WYITi eKoLt 3&uP[x5[ MA8PV+^(5ErZXJ`?Lo?73ŲXc[ 2)cZG6gwuA58Qk~jjʛN`x 6Yj r mAn'n6Yby6PD \q?7thKP 4,at)]aUuI%mmSrV_&wI,FwOA(wD,¤=᷀xzeqDOP5A-t 6gOFm8wtׁH8PobvJM[of8x{hw/8P4#? 9wQw\;AQ0s$͡XCw7uc7@}9̸y[x$A\E3ޯ9o˹9v3?,ΡOz8%zA,縔C{z1Y=X:1z9:ʊ_.ֺz;%8.;'{zW{=_4m;w;;'[;e:bO8wzۻ3+o<ëKr§7<ãzw1W<[|Ė;gN|ǟ<&xy|ˣïɣ<{խλ||{}i|||μ7N2˻ԋ+og=|_k?eد}M\2=ۯ;:+<ϽޗDwî}]=7=ᗶg.'~/>7>>Ӽ0嗮_g>o>vs{Y/~>3.>폧߾z*~/rП>?ۻ &{2~G?旽 ,_B[lgwſ?}o%`R>?@8`A&TaC!F҇bŊ=zXH1˝:A)RΚ-PTeK/aƔ9fM7qԹgO?I╈G&UiSOF:č1^qdIgѦUm[o%Z(Uwջo_Vfѣ2 caIȒ'F|i [1cfuG>zڼ}׾{w [D~UyH\,dǗ?&9Ō(/$@!FlO )PH8TA QDQܯ?S0aiKLQy,m>2hs#L{l'1ȭ^$2AR-3c/ !)[Lʐh"l7R9L<#PC, TAkCNÉ!+6 RB MTM%\Eb44SQ2SNYmu;O0 QTq]W`%0'@C9DuT]m6UVڽհP 'hˆHCRus߃vuمZ!_|TTQhT#(?)EmS݁ P)+*["‰&">1L9w* 'a+.7Yfkca &5R埁&ט.4 V"D%֠zי p[5Te%.UZzY&Eѭi[ni<MC_e[q'Jr^r\sEgTr+-\s3t#ЙMϞ4^=_u'}ŽzmB .w$?"Is`Tև3l! 1A,,AN0%4;B50-Dh@*XB|W`1:9Ck/}DtuD){(NqUTlH(F5eAg5q7sG"}JB=֯r~4dHE6dA!! @.\V$1R 2ʟL;ck>r4Q )KS:̑#]˗2Ыb8` a ,1i^{C3werrt&4eNswp.Mqb܄)'0Ls,9ML۵ӝ҄' 6,$=E{>' `M>ԐhઙJİS%ah&PM(ES25[>)u%")&KjRɓpK!S 2JS]tD(8M 5D-*"ZˉtSeDxA%UJR{bՅO]аbd%M֦խ ++zȶ֕]Q*^ǽuZ=-ЁXҕ *VmNY]`/뫻Rγ lheՐu+iKGТUUl*]ZƖ-lܾvUo.aťqoM4> TBWҝnF[\ϻߝSx;׼aB?ջӶ걗P0 KTD~UξiC<S{- C\H@` Wx 0|XT#&1L|bX#v_ ^Ma 9&yQ&A^kd8ɨ[GV!Y֣r+tFm]>.<+sX,&r|/Yv&8 ot֏BL$(w볟Cque-ь):ĕt[ G{9Ғ!7Gyp;_QC.NW}~ub-k`zzr{-l؜f3/hi.,mގǍj4Nwno~oyPC|ûm%HA.܂(m gK|S8q?Y3~hoG</9uONZߛ+ˣn4Ҽ9Υs@oЇN}]HOz\t<+ͣ./9P֫B=  [, 펴]ȰLmQj߻ Rς\nßMYT-}տ/U>';/Z-= #|=>{+| nvJ_׽y4eKuԚf>}#1wk_puixY'ǩWTo?'/Q""/a.06l8D)+h̏ѯHOq+8Y<7pO0@I *r⯟ soZppdpdpsOSP+0 gW+7` X`\ /p*1r0o #/0Kt$+M00 PtΠX=dL -E> !1㱨/ 9BPgK8N|UEW14leq>$ qG3j>/PouXSQEjQi0Y‹|,bqqк cDgo"ۑiS Y RDl+P!r1/RQ#'o#G$"'#IrALP2%y1#A2f]`2&aZmo2]rR'Dm$#('.Ґ2)d%y*E2r@m&lR(?)pBq,u+׮%R:+- (27R'-l-2`,n&#z2~R,0.6R.q2r)!3t.,R32l1R41;($S5W,[ Q65g!^7+47}sts7I$q8q8N8d8 9S93S;:݂9qn;e3;6LB΀B.>;s(N,2?bt@5@s=t#3Ai;_341424CG@#tDI'BP4EDE]4'VTdtFoF FqP`?yGG3H4&tt@f lslHaJJJ4KtKKK4LtLɴLL4MtMI;C,@JN4OtOOOMF4PQ!5R%uR)uMU+ +`-rQ%Q+5TEuTITMK/*2590=&4AOuViVmV4U7bUGD]UUVqXXTuU#x0ISX4ZZM"5۞TZTu\ɵ\u[+Y"\a"V\u^Vѕ"5ܾ]ߵ(_6`%uI6O_aHV 6ŠXVaaaU+_s5.QQ-6%t4 9@ok_Cv%FvJV1`d][V0b5d4gKBggiFUhig_hi!Vr^+9G?JJ kbJBlcJl˖lmm6/6Kϖm6mm6o*Ԗlp !?fj 5kvkJ ̶pos-m5WK!bs"pntӖsvr%p+wpsoCtpY$qmsii>Z7u'pM7*~swngsQm?uoߖtS7nz6p)wx6rMu7z kVQqwxwz׷KQxWs}Wvt7~7zTzkVyxz}w|waWY76i9$3qw ~lOxn6AvStxUx~]tuQ]Wovj͗"wb5X"$sv=8~}oz Xu%yeXx=}7=Y8-T7N.tgzC8؄xKBnxtGE+9ِkVXiٕq9{[Ax8xx'yQ9!l]u׎+Xq50 [;P|+Yمq39szkcxua X~GwYYˆԂ3p ?ee{Xr` Wx%)z`)zZA9# _9w}jKU՞YK;EV9wդEN/hѥ}Od[V6zs5!Yᓦe^c :^ US&6QwU9Y:\9DbRکZڪ/pUz W{msV {T{H,>@w{9OCc!p֬U;;UM?9CأM{P{mQA{@([o۸M;[uiۺW[5ù[wC[oƼڸ[` !; <[j%;^ ڸ@Ԍi5[ ` Ĵ\1<57đ i_BVH\MqV VܚT՜ƥsC~G }  [[zGi>zb>|ӵg^M3c^]굞J>+B~_A>Ǟܩ">/tBh?_9썴 >m|_!?~-1U~/:%^?9_K]aK+=uY]Qa?ݾ;GqkԃS_58ۻHv?}q{ z?gN{=ӣJ 5L dY= @Y9a cIXGΚ-*Z1ƍ;z2ȑ$K<2ʕ,[,Ie`+jڼ3Ν<{ 4СD=4ҥL"3j Zm1V_z 6رd˚=6@Nۺ} 7ܹtօuԫ| 8 >8Ō;~ 9ɔ+[9͜1 :ѤK>:լ[ٴk۾;ݼk <ċ?|̛;=鳗S=ܻ =˛?<ۻ_ۿ?`'```>a FHa^ބna>"Hbhb*d(c2XՋ4ވcڨc>X @Id idJ.L> e9)eV^y"UXneQebdfifnpI'r։g>ީg~矂*b(&h.h餖^^nʩwv j}*jGꩪ[ kJkjkz殾zKlalk*llB+mRkmbmrm+nknnnz+oskojoco\,pUlpvpØ"p?B,q8Rlq1bq*rq#,r;2lrirr,slsssG,t{mt7t1tA-uQmuau"u؊-v rmv_vvܫ-wݦmwޡw w-xnxex!xA.y~Qny52ya堇.;n銧ᬷ.-znݸ.j//{Z7G/;mJgw/,:o/*//{?0 f*, 4(B_*hA{a0 +"4 K(, ,l [X-p4 op< qDa$*qLl(JqPB^EE5/j!d,ψ4qll8qY JT!)OTrl+_ Xr-%\r4%(GJNvR2(1cS l3 hJsԬ5ljs&.y p)aBh'#w2̔=|s? Ѐ t-(@Mq*tdg;q`N{>"t #Qxe.ѐt$-IOҔt,mK_ Ә eMoǏr )#(ZQ,"DOJEhaHmS ըJuTUլju\*UQSuKE*OE5I"ފHJ׼u|_ v-aX&"cm8J!X+[ChVF!zv-iOԪvmk_ ʖ`co{nR -",{Y-[Chams Jwԭujwܵ!l8sh{;Bh}w x.xŋ>WHz3AHx  kx? x$.Ob" kh_ x4occÃp_ xD.$9 jh (KyTe+ Y>eb93u3j|4ùso3lmMe| @ zЄ.D+zьn HKzҔ/@@? PZ8ȴOT!,D22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ#JHZȱǏ C^Qɓ(S8`ɕ0cʜIK4sܹM@ УH(jTӧ2hի!Pׯxٳ` ۷> @ۻ`m(x@+:0^L9 ,@BO Pi\pװc˞M۸sͻ Nȓ+_μУKNسkν֋Oӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6䓿@RNyR^IP%Z #z f!cUPk.^ZY%oo'}ryX2e@!, 22ABL$ JKV,,8((4BCM곴..:33?`ak@*\ȰÇ#JH"ZȱǏ C^ Qɓ(SD8 I+cʜI˗5s͒< OD*iҧPQ6uhԫX+NuIj֯`nukس`Ǻd ۴7 @ۻW}(!@xGm@ ^t@a&8e h$ C= ѨwVXpABװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<璈7?~8$Gvd&1Iy!HbIAbe^.dKVyӗy#d9'W !,z22ABL$ JKV,,8((4BCM곴..:33?`ak @*\ȰÇ#JH"EZȱǏ C^Qɓ(SH@I+cʜI˗5sܹ͒< OD*]zQP uPXU`rWh6$p"4z倻w,KnKhc@@A3K`@cHLZ+.^ X˞M۸sͻ Nȓ+_μУKNسkνԋOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TVi0cZe/~ fbbff'fn9brHgީ&{ɢr gfI0~饠!,R7;22ABL$ JKV,,8((4BCMƫs곴..: 33?890-.s`ak @*\ #J (j܈rIǐ$S24yRʗYISL*m x'I,CN4*Y89SK?0 AX Z@ASa`J`@dL;Ar+^̸ǐ#KL˘3k̹Ϡy4˦OWNz2֑_~,{vڶΝx7o Nwqْq'7 u[N9!,\5N022ABL$#>?I JKVر,,8((4BCMَ,-7곴99..:933?َ`ak @*\Ȱ!:HEDȱnj%zIR!Ȑ%S]w@!+,E,#22>?I# GHS))5JKV',-7곴 *((433?+?@J`ak89C1t@,@‡ h&:ȑ ƌ;ZrH2$A$D*CD33 ̨^*O@^$:IT$O!Fj#pq+W` f`d+jp…D '~aHLY#2D9@N;&h+N} ֨'ǖݚiUvM; !,4(22>?I#  GHS&&2))56j ++7 >6.*O n?@J·00<[\f89C#6IK`@&H"ÇEdPqbF,X!"( (1ˇ'Sd˄1ei3N('D2= 5X(A@SV@A᠁X2€Mm̹倳gs D@In]x0 \u]P@ 4$L HL^'6(gQ&5jbxPl!, ' 22>?I#؇`6 GHS·&&2))56`6`곴++7 00?I# GHS&&2))5 곴$@++7 00(,%B 4Br+Q$sשuÃ_a0 ; 1G誻 #7į?\s?(O@4a H]za9.]Uhs3i! VƳx 1{DZbccRުK\4?p z,.Uv]WB{k_c$8:`w0 xhap\)xו}rFWi:@ʶB!)ElbL`&ֳ9c YpCnB ,x\d`ÕLOyaۮwt,ҾqPВ1he޿ಘqdhk6x𵷰VJS}׵_b6^7_Ľܼ7z˰}5va,MMjQ :(.n| WYxc-]Gbo}/ ~.t4:L\k5XRwSiKx!X\Y04ل [j?Z`<-@;tBNJ'Ev%6N["x$>=jOԨNWVհ^B["`uMF@wMbNf;&6&Hqi!P*H!Pxۨ ovMz;ݤ@2q텀cʸ-hAp iB- ;@'Nqcϸ7{2x֠4V0gQGA@ЇNCc8n#% pXXK,sZкح ($e?׾p{: V!,'?2222222212111212121212,0$1O6$,+ 7 O %\ .iBIOU]floswwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwyyzyywwwwwwwyz} )6=?@AABCEHKLNKJIGFFGJMOQSUVXYZZ][[[]_dkry߼H  *\ȰÇ#JHA%fYȱǏ OIȓ(Sܨe˕0cL̛8s>Y%@3УHOU!ѤPN\ԩԫXRuj5׫[>J(h1[ێʝKݻx˷߿lÈ 4< ǐ#KL˓[ \1cΠCM:恄K{.ͺק&۸%0sUq؛#cĜyУGoͳWfȻg#yǭn޻p=aٿx ȟ_[|%39ᗇaH %2Ko!#5@-'<98"(&T+B7 \2 %!AP O}#.3.l 2XY#t@!&)&y()BQ9cX9SyfXk Vve )#'AD9$>dD(0g'CPPx& zii7mzet kV::럻Hcβ6[Jul㛳VDn-D2XE} r+ko~#R` ' 70r?0@goqw,(L31%,4IJ;L0 s5-rXp.)?=T,GDJ !;\1qsl?LϐRnWMըĵ"24|O:eg6/vrύܝ7#tM}#8?l8yA#\/\!U@e$3LKf$l+S?h;FCc v2.G'ސ!z5 0a9 ? %}np<33Kͥ37y`CFR48`KnfF0X@q۟Ė _K*W ᢰR%&XA%0apCP #!#( -q vDp8 vb/;FHө(L0_3Q9< #YAAqI$J"JaoDL:|(!ٲ!oc"`ґJrax2JYjl0HaS<2ƿ}9Ќ4~d؅,Bnvh%@qzL:vi-@6xngCjO,Xڳf4KeH|XgVZ3ub8}ӡ-'Myj+-#z[(r˒\#]b;8vgz'{KuvJcy}]M4#ݨY/8Ǫ#B)`v٨OҒƵ3/}ӲR6"a *f':u L va/)_k< $ HBZq*"GC:GD$IAB򒘄$+d\tJ򔨄&ȀL.@42i ZB(4`&%OzJ)&[fęfG?3\d.eҗ%O2pcf.a&4uĝҌ'AJVfLji 6 '<)PsQ>fsfP0cq1 Ys\JP*rԘ6i?WR)8Õ`No+hK4t+tiGUSOptkt+)-|4 J3Pwزc%Z˭7)*V*ήSg.{`̵J+_IX_2Ӯy=h2ҢYmW0 &Y V͖S%b,]P &]Aiy_ju, }-ނ𱒽%dJNr$DcV˅gyB]I]gRamhsVUM{Q`1~5h[p.)yGWTUl+w՟Ujuj^q(|_9Td8; ewkZ%-TW%: a"LGr-y(.FF#;TsɊ,\k N @h. \29psVxγ,>)tnMBЅh ѐݼJ|7H[Jt";MRND=SէV6;ָughֵ֙}^{5&c;4fg[4.qn{Q!rNv׎fQP]~NO;?'nl_b%67^{ G>p2>0~3&+x=! s}|җt)ȬrMϺgzΑ 8ٓ=k;].Nx.;^-3Y`S^%Ǽ聾҃<.[gp< ="F{+o3.w@ , WO}ߏ %@w3O;|O1!>bL~~7|o;0  ktpm&PP } p~2Ѐzs W*zIu`6 t `8p@?@0(hv+Fтo~ &@l\؅\V@7YFЀnC@W'NЀ6s(n~x  Y@ZP}(&(M@8Ȉ Ȅ8N~f^X] t?q(pa \0p<n6 mX j8 b2p6PCP<0Xiȉ Hu8؍8X>/8 ؀ Hp&P8 H|(hi)嘇눍(H (8 ، )M0ii2X|Xgp_" `pX jߐ(ىi- 60iy؍I.ZY\9ji5}VhpI "  hPAGP @H9p@ #( 0|YE@I\ ixvgk2іW}KP U( pw I0W@مfXhEX|POّ  "eٚ (ɝ0#)/0uoHpA ) @iP DɅP p@77 `GupgG ЅG Lw9}:v6)Ǜ&  p]h&W6;@zBJFʅHǤyʊvqw $zpApGZ:\^z`*gp)` PJpSP uo*xq*NzP.Wpm Ѕh0hoxsPptʗ}e]I39OZ0sYp_@Ayʅd*`rgHnڨ§nzg'J fxjڭP||Wjl@&뚭횊u}| '4h6Xoگ,WpX& {'LH9  |$Kz&(kunqל3K57w؊Uw*2p0g*XrAC^]bKa;fe{jinmrq;vKu{zy~k};{[;+{;;{{+;{; ;[ƫț+ҫ[{+ڻ۽ޫ;+{꫸۾+;~[v+n\f{, ^&;|ښl ̥"<5Z&L(,̨/.÷ʭ43|:<6ç@̵?<[FHL\NRT\{XZ^|`;dܿf|jv`N DP<4T]CV}ՎZ\`b=\f]hlnrt]}x}z ~Ѐ=؄=ц}؊ьؐђ="]ٖ]Ҙ(ٜҞ.ڢӤ]4}ڨ}Ӫ:ڮӱ gY=Q۶]۳ۼh ­D]ܪqͶĽR]X=Խ-aʝݟܭݘm]xk=ޏͷX}߀;cߪ*=+$| aNe^θ =$>')^Hhd.13~G-^fq80㠡>@DNF~1JLWP^R>夛VX`T^[df~;j>iDpl>!vx[|{:肎~^}>0Q锻~*Nn꜎ꙮ.Nn녎낮|yv.sNpnmjgda^.\NYnVSPMJG.DNAn>;8531..N+n)'$!.Nn .Nm -Mm߭ -Mmˍȭ -Mm -Mm -Mm~{x u-rMomlifc` ]-ZMWmTQNKH E-BM?m<9630 --*M'm$! -Mm  ,Ll ,Llތܬ ,LlΌ̬ ,Ll@@ DPB >QD-^ĘQF= H%MDRJ-]SL+CęSN=}TP oETRM>զHU^ŚUV]ARVXe͞-{ZmݾWZuśW/S{X} FX`?Y䞆)_ƜY或9ZtbϣMFliխ]ulڵmߞ[n޽3\pGq͝?GtJ]vع^c͟zIw_|Ǐ~~/@p@T@d70B CB 7,C?0C$ļF41EBqE_ Eg*k1tGn1H!erH#DH$dr#%2ȓJ+UzJ-rK/K1 sL3},L5qLsM7_lM9MsN;?N=-sO?OA tPC+PEKtQGkQI͋tRKRMtSOSQ uTS+TUuKuUWikUY[uV[MV]rW_Wa% vXc+Xe KvYgjYivZkZmv[o[q' w\sQ\uJw]wj]y*w^{#^}w_y_k x`a*`s[ahu8bb'!81ָc(8d@d869HVe[NeKykcsxg+爃aVh Vziv_wjjy]Vk{lq6[vmumiYVn{oaWupm5pYWUWqM|rQ+S3ts-sICQKWt U}uA[wOcsvv9sM{Ww~x17Kryty)Lz~{2~r|Wfۿ}uhz@2|(5.j t M^ÖA <A6m%4!P¹vs C5 q(8p=!B2D"шGDbD&6щOb8E*VъWbE.vы_c@2ьgDcH;эocĀ!,";pMIPgݵ|͵|qtqىĕsllxyx~uuwpoponnllljjjjjjeef\ZeUSpPZLfImGyFFDBF=* {xwwshX:+f)_"W D +  $&./57>=J4Y"ace,e5i1u#+4@}SokV|7546$2122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 H 7u@Ў#Bܡg:'VOᑣG"IF?k(ɨq&D08 QϋY)s:Dx|"ĝA;~:Q+~D :kMHG6 #FB_tJݻx˷߿ LÈ+ʸ; & ?~PcD;xs:u0a#:M`6QE޽Ts3U4R}`[q6:;~%c76I陈"RjVbFFidUI$GO:lp)tix|矀*(Y7G *h{AC>GR tکuH"2zjmȀ\zꩨ1eE&$1kEiZꆧ6Î+‚,n*rk覫+ko𿞪 0|H*цF, TlRU4T41.6 !o'7G/PCw/o觯~@/q H@Ie 'H Z̠7z  =$x x @ L fH8̡w@ H"HL&:PH*ZX@ ;E?!hȁ2hL6pH:x̣> IBL"9>/+ 8F &7Nz (GIRL*WV򕰌,gIZ̥.w^BIRҒ@0f:Ќ4IjZ̦6nz 8IrL:v<ه>@R/D2I&8@JЂMBІ:D'JъZͨF7юz HGJҒ'CB p@# P8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծ}`a>9T8u ^̀p\J׺xͫ^׾ `KMb:d'Kbu)L7Ѐ3 MjWֺlgKͭnw pKMr})Z_@40ͮvz xKMz|Kͯ~_>*) b20bN;'L [ΰ7{ GL(NWO7u 8αw@L"`7} PL*[Xc NֲL2hN`dBL:xγ6aœLBЈNg% Z4E[Ҙδ7g?^Ȃ@JqԨNWj{FֶvHw^ךZg2t k`;Ў,l! \݀7nPnqÁLp+T`qpMQw[~;ŽMx@ _ rÂPvA7\OpMY MpA jLP&kz?x?ȅq|HOҗ~c\.w* ` P^n6p|e~n;Bݤ@vg'$vv`O?؆z#Đ:t;! iHLD1]G?N8lP*L󆏽g_r@u剧uhFSA5Cфk`ПlKz`"bʫb'.),&2#Iê`{sJ˻h}O}P Ыn3L Ƕ;ƫܾ Jn=ڳdZ :׏[. 8`ȍ<-Rkɏ@=^y٘MP.wڳ,GLh֘1{S`.bwb~_{ !k(05j ,eL*`3 dG JZ bFX .:Y٢idin~@(yl&mPbnz>uF>^~阞K>WpNꨞCfd>.~Nba9B~Ȟʾ>^؞ھ.>~>^~? c?_/ ?$_&.(,.!P`ABpP=?= DA;BLN?2?N` ;p@\?^IfhQ?V Yx0 4G]ir?VA P?`MP9 ?7p^\ /;%/턯?B`=[_M@d??= _N3 SAH?: 7`_/ۿß^cQAApzUTU^ŚUV]~VXey0\0Jl| `ń]Tiɓb3HwtzR6m7f=ZhҥMFZuXjٺKՉ=a2&Z#Q6ٌ)"&sͱzsj͟G^z^Ո6O !AT @>)Jk;:9tI"IC?1DG #2WdE_1Fg\Db+hG2H!h!dI'2JDQJ+2K-J3L1$Լ43M5dM7BM9N;_N=O??OA%PC+PEeQ0u4RI'TF/S4SM7SO?5TQG%TSOE5UUWeUW_5VYgV[o5W]wQ`r%6XcE6YeeYg6ZiZk`'[o7\qE7]u mXy%Xz|7Yxـe^x]~g%be%Na#w8c6by+}7eW^ffE_vwggZmgFYs:h^zZcK9bu`yؑ768l&vknپ^8ΛeϸjcG;v笥womwy_G䋿oE>iʃ<{^`?{%]nK_׷fo?s?MG}7?S,I/\{  a'8eЃ@u3|Єqw@ЅL e8C.5!ni5Pgp0@aO fk[Kb}9"wE.vq}[b8ƥ%>)؀ P?LgAshG>я3Ka'0r~c4d"qHEΐ+kntp&ܐ8“A.\1KYxBVrpe,XEB^!.u]fBItЄ&<G H.0PBs?JЇ>Xbe8H4o! Kv3]A 1:-l"r>ׇBP:g/Z{ '?zHD PMajDH3hNsF2Myf7i-qZV:!`ӝ?Ss*T'"Ջ[tD*!ÊVόͨ8΄fX_᤯[\RpUJP;+la 0)fZVR67} J jhE{ժkWTiT՚Zk /gIP]cDp\5sC(݊8 4Ci0dB`ʄKTsl6`hq 1C uTh>POM$pzeh|)5 S+OHXF_d!au 'A/| sXO-h<,Po, a2ykS-xFߦk<&Ѐ@q@J :DXэ)ͿZ\hUe1Kn͠iY&>BgXLPYs.@ɐbun£;73ϐhT!8MA:BƼZ Ks j7a]`t-:́t`OR+O)r6lfCmZ:K 1݂Լi<%N<'՝=? $ jܶgbL1 ;O]C07 쫽]`p}V jXC dR3Ms"rsA0wdn݇ly8:}}&w=uv=ӓzRܷnJQ|aG< (>[YÏp'LhTJQ]Źe-uE`e4 5_8w-A u귗\ =^q>F4/a:k'˧;~opkkR/ŇjZ> Vש#?zK7#=L Os8 427{@C8S1@۸쓡B@/5[b@h³'h?A+ v3A"@%2Il)B*\,A.t'"dBڂK0;3$"s q$O @(: B-B/CXC4%D -@T 5;D487><=J?4DERLt$NM\!FlZ 9KDIAJ4U LDM{]EܚGdF$E[|X!Ta^anqEb>dEb7<V _AUk:e4fFbFQRn-drTG9n|!ntODFx`z\Gg9|Gǀȁ\pq|}BtH!ȈȀ|Br|Hea~ȍȏƊLHDLGD]ɕd0IgL0nɚɜoʠ GɣTʥ%nكhc),Ǜ&2%TJDʮ˰4$Gh_C˴Dd&%.f6&:ʼt˾tB6<Ȱ9x9(LLD-[)o |̈́$d5 MҔ9p6h7`LlBQlMz,cLL4;4C胓+lM,9h0۹K14ˢP F 5eS7}8ԥuRf UYz?c?cRM N՜T5ZJNDVu՟_]Y\]]m^e'`U։V$֨Tc^EX%8 "mo]ֿ8qghNj?A(7`>peAW/׭q-F$!EפQWcQvmW>zW(ׁ[zl5WjּX)XcGHXSz6x;qDPECAHY; UIpA1m@Kٕe5E7YEȱxYYYS =Uٟy>Y| YZYUYEYSXXأ G[ Ywեo[{%y۪C4! ~Y!yD+ܟ(yW;4:ZK&xY9Z#ĥXC\M[Z4Ŝ5V [\WVn}\VEٗדE[EMDZ~]˃xO܈[y1aZEYU5YB@]]r L7m[حY_۽]@k6^]5_ވ-^}^>z5`y7x`m`>N_-d!͂FV$X Tz_;YMYSC_K`ZE0aC᱕W!az/ $aPfayV0ỽ&`ޮ߃לY=$V\ZY-$ĥ9FقcA|5 ZAb$Q&$@ T.cy0ZpcXdN\qI!]"$@TUF8XeOeqe^e_&`.@afKUfK@cghiek&"oJSnDqg%$gp1j"P`~&fy6z&ho1gt~xh/,ƭ%b b`t^uF.N%~hUk薖*@(&c( Xh#+{R=iC6^hbivcX"0#PH#e+D jjFJjhaib=i#iS6ij±\ܙ.iVnSҚjwjk~b'0`�%C5ijɞl!vbpϦaV+*΂~mʖO-E`bX#jc -6mokIbh>lMGVioeVp%0vm޳Vp!+Y0omcTnQ P4HPȹ⠒ pccoypZ_uw 'r7rD$w%&'r)oP.R>n r"resed-s?dIs}f6~/sdIsϻ.>=>??|VhnLs#)ȄDWt>cFIhkhaӬ_h(MNoG7it~t\Ti&EuWfv`XYf.Ŗ)L^__`$ ޶I`2)JuhUiOk~/bvn.Sq'w2sougmі2egY?|mjj'`9mi+/kefx*rʆxnYЄsđg7ytߙ$`wf,ns1yO'y듟xyĂ? y(7yv!Yrߪ)qОzw~ϨGY{1R?vid{᝿8wgŽ7כ{{{'6UDV|JAWȟ7|+:}K "{/R_znJ|}iܧ݇3_g_.r$g"ƌ7r#Ȑ"G,9"J&Wl%̘2gҬiflj|^ĸ& *Rmd!D)R$I@LjV#ZZW<+ڴjײm-ܸrk.޼z򥩓OBMʴS(6 ժS˥ܐ,f s3Т-m4ԪO3PG2uW\Ѻ Ks4uT6#+0nR0<<]=ݷ öQ8WoF\. )Jd#C?8cJFvL† 2Xxf쩸"-718#!`gG(r( ^CFU%YF")dDLVV=CVR"ey&Q5&mv`uDm<AyV!U5Ж]秀C)hS BfY&jʢz)%y9eJP$*pNX!U5+*d1qဍ&H z a^):KXJ;m8j:ۈR5RB^6nu[s⒫U..D)"Do&., |{YmۣJ Wb81O0{lى>~hRʻ\RˮlQ`sF_3Akln[kV͖^4Q)4ULIh]sE5oe=i=-g3;n=\k}wmӍ&g7h=80}83T8䑧v)^9K9yQ9z>ܝ~_Z[^3ٮˮ1۾{&c|;{s^< <Ku<6Ϸ5[RH1g~ܫlo>+>mK=U"ͯ~LX8};"Z, `h10-B E 9hQ0Ab0![$0|*=tnTx͊N%…N bȐ(xtZ .\ Bq"%2ky"yŔ@WH20a@FKr!z]bI1Qˆ+RQE=< ` CBKJr .@R$.r],a1 T1UrHFg"*c Ę0&vq%6}mJ˗!F`8$K;Kf$}R7%R D0 v̸Yl'D)Q74"PF`b,dK0Pk &DSB$Ĉ9UхtCOMTF,m) 굮0p9).{TGE$*U08ZTE[fuS*k:RuUgY ֵ|jZQֹzNVW ҵuqW5l;X1A,9-,$;YYU"ϳh[ђw}mNRKּtqm#ls35t+\P-p]7\b|M薛f͜taK]Yk+:񒷼杄Ɓ|+_:7蝝z׋Vr|KL NØNŚ/v#3Wg  xFȪ(AIV0Ua Ý=̲` "=\`GF$J~AKMťsqew32vȍqaX=MptDZ *݆$!X,(Wr,{\xDSQ)t a&O~f*!Ғ#2x,)hnI M!"383O#m3Ms>}]\2TiAu ,kMӺrj ڞ q\2yQk_݊q{붷ngۺNwM׊^6/У{77&oV?8ҫ쀻vkn9-'O^ezxyF(ʗZrߝ嚊Y~\s8W{WOBqսra0aDMB#00yTkXyKΑ񲫇#$3g={\K$H+ ~W**XN#ځFr|G'}5Lol}!Gj~8Gu%;aqS @`@_՟u^` xJp `d,RyY#\(MɞUPFj1i,0 M EDŠb Br Yˮ^v4鋰a. ^e^))T,RõKX Q#Sv%Ԙ%EMف!$!~Frp[!" %aV8#B"RƱXbaiQ'f$Nh%b*&\TI"退1#2&#W"(4#Z19# AL4V5667J7~.딣2#: :*;;"#<ƣ:"D#>b>6#?O=@R@A#?%1#C*CAD.cEEOFfFRdGnG$D($KKB$`(N&OdQLM>Mr"DN$OdO%ImQ&<."FSBT `%hD$WW6 -DeT&PeVq|Ȗ)[DgJAhl蘷sh Ek[eR0,v뷎Xd%v_u< e_w( [䫾VZMqD>"l |Ɓ>ڜYp˦UnlZtl })J ,L4@ X\்`m,,|,E.Dn4%QpnnjBr,QR 4&onLm uoTZ.@ NUoE&k B!gleUoEį)/6oB 0 ccCpi\MV0/h0r0xpp/EDPB%p%̨#6Dx\%X%ҰZppJkw K% K+#q~E{Y+kGEDxE~\pDo e auoKJaloh-;'l,y]!l ,ܚ$0%WήD܁R%%()"snI y_0ȣ(㮅?o+GiQPnCAU.3g m)R*:J/ U$B#p$D{. Ra`٤!*+.1tLb/hC8̶t" 8@/(|KB^jV#$k>Ht{G> ~Qǽ~lq>G~۾F> и>9[\7cD[>[>OETs6k|s??m`owS0{?7`,.@ 8`A&aCAbE1fԸcGAHdI'QTeK/aƔ9fM7qԹ'9|^ĸ& *D&=d"OZ$_t21U +)"!m(kYgѦUcOoƕ;n]wZ(ۏLFjA&^êbŊ%re˗1+sgϟAvW(QH3[Lxj#G40cf]'a'>x񲢑'Wys6jk# 9|zy;W}{;~jRQS@i8"l0 P /[ͺ~ÄW\qkl;Pi' / ?JQE,H#mLR%$ 2,#|TH!R-D/ s'11Ƙ 9^eX!.8\j٩P{yfBYNgRYZ],f fY:Ktw'> ipnƔ1^V際vMQn;=69貛5N㴛j /.oe{qc?f:p.\_'?e7L]b&$iB=K!77qt؉.vR ^plϨmܩuw{:8v]1 o^agg7sc/_K|=t# #3 ;hMj*byAJ`4$tH &O-Ia*E(%q qC=D!E4LrD%.Mt!#l(E-n]ư$Qe4јF#RъˢG9Αu$cG=1l؅GA HE.Ҍ~Z IHINc -IMnM"&9JQr$)QHO1t+aESƒD*J[D"(}La0SRt& Ir<5Mmn7Nq49љNut;OyΓ;ۘiRӌp?CL' Pd Yσ1qB]P&+*bT5:*яz1)I xRJ(+cK_ ͔M!\a .&8iL{ AT@ *RTbS'U.VmV#VKN+Wєլ `Hd"b_I6ЊַU ]*TAth!VJXfʄJMW+=Ǯ` ɧ1=Y^m`bzS 6yuE)zZ|5cqY-e[F׹k-D[\!oQ.PfqQT&մɮv ]‡Ulʐ~v-_j y/|6_umOx& v!aQ/R %VɇA\Dm&vIP!R{?WOqwǸ@瑑d%/Mve)Oɯfe 2S]d4[/r\JTqWN|f8`6(lU9`YЅkhE+ЋvthIѓ)i0'ҝ~e=}PLSw7 jT;Ӛ1pakYϚֵa]j@זTuj\.9 le/miGζ*M}aB{mq%nocmKt %Rd-]aBj(1k}Xnr޷n-zฮ/N|3=ʆθM|˥pgr&E_:wŽc_h.Wj1+\>s/QSdk-t;=L+uw?`&nu sW$msL,{)oWeoשa7/w}z"/~c'poU]y|]>x^㷷9Vﰻ>9_u7_~~&\ o0 0!oaN5PF-=E>BU"/api lPq (f`/lvXpQo7P0^ _0p ;N Ph"* G ^ j WP ֌ _`p R pi Q( q i Yp 6-,*QPpX]!eqimq1uqy}1q11!1q1a21(p     1 1q2 r 2!r!!! "-"12#5r#9#=#A2$Er$I$M$Q2%Ur%Y% aV̐1 ` @` r( 2)r)))2*r***2+r+++2,2,2-r-ٲ--2.r...2/r///q&U c'π q ,r `2-21335s393=3A34Es4I4M4Q35Us5Y5]4'6m6q37us7y7}738s88839s99d3:2@joР @ @:3:@ =s=ٳ==3>s>>>3?s???4@4? tAAA!4B%tB)B-B14C5tC9C=CA4DE @M@:0q  *S r }ttGyG}G.РHH4ItIII4JtJJJ4KtKKѠ8 T0Y4;@'@F-S MM1pNN4OtOOO5PuP P P5QuQQP $1iR-R15S5uS9S=SA5TEuTITMTQ5UUuUYUi`&5V%ȴ& s4=%6W5X;X5YuYY 5 Z5[u[[[5\u\ɵ\\5]u]ٵ]`ZUZiVW0f @=e_cu ` `6avaaa!6b%vb)b-b16c5vc9c) d@XdMdQ6eUveYe]ea6fevfifmfq6guvgygY@D6hCVO^W4_ BVAi Vjj6kvkkk6lvlɶll6mvmٶmݶlH4nn6ovooo7pwp p p7qwqWL˴d EEh9Wd qEwtItMtQ7uUwuYpNdwvivmvq7wuwwyw}w7xwxxx7ytO!$V)W@J w{{{7|w|ɷ||7}w}ٷ}}7~w~׷f~g H`8x 8x!8%xI h:n ;T(N t;]a8eximqZ@})UK%wr) ~-uotnJGx <`8xɸ8xٸ8x=``=n&W 0g !9%y)-d@8=A9EyIMQ9UyY]a9eyiYxe w;XvQ 2U@[cy9yULy9yɹ9yٹ9Lsyw`R `:z!:%ڛ֏%1:5z9=A:EzIMQ:UzY]% t6y ̴f] }:zzv:z:z:zɺ w@Fۺ RjSV2d ec` ;{ ;{!;%{)-#w{8=A;E{IMQ;U{Y]a;e{i |ڭuI P^Vܠjujmr z;{z `;{ɻ;{ٻ;{ XJbu Nﹸ3L y^` j{!<%|)A[ `9=AH33?"ablH@ȰÄ>8q@32xQƏ #ǑKVɒʇ'[|0.i)CNy("0Zd.e:&` 0@^ .k n+`@ $0!4=A +^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸犄q>|q7^y_N:Su#zt4NuxoݫF_z:f|ci!,c22```?AK# HIU&'3**7,,9೴11=]_i@BLH*\ȰÇ#JH3jȱǏ 01ɓ(S yɕ0cʜ˒4s"/{ JM8*]ʴQMJԫXyV% !h֯`Sn%kسh5%@lڷp%@ܻx}\Ԁ_y㵹@^<@aF`Lr`ŕC Y%< `;Iv sϔ=a.wo{?Σ?.z夭k={O^C<\{ ˗QMϟQ~_n 'Ђ:`"p r}W`H+X.H7}?c@C~7I*Mn$QZ7Ujwe\v`)dihlp)tix|矀*蠄j衈&袌6( 餔V )MfJ3i)2y)1)0j)*)):)ڊI޺kH ~l,G.QVmMKmD^P6m } nB{Pn.o[ojRp;[#p 1Z111s#CZ';r+3/+s3#Z7s;? tCZGtKOuSYWۙu[_vcYgvkowsYww{{xY{xsxWy7Yy99zXzC{zW{y;xvkuWWtGs7|r#=qWn=l!,_22?AK HIU$#&'3**7BCM,,9೴11=]_i@BLH*\ȰÇ#JLċ3jȱ,zIɓ P˗0c6T̛8sΟ@6ӦУHӘK}>J#Q Rj\Ê=Hرh}0 ۭ@ݧ X!Aw#[8'2@wq/( &LbP+8pm[b{ ߘ{ŏ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫇*무j뭸뮼+k&6F+Vkfv+k覫+kハ020."ܢ,2*B(R|&b\b@!,_EN-22'((?AKBCM$#^_`Ƣ ?@AHIUض&'3**7wyzMNO,,9೴11= ]_i$@BL89CH*\P@#JHŋb pǏ +j1ɓGT%J"a(`K\0MeN,)͢ D4#ѥ5Bӈ60!z_$XJ*`ز. [,4ZQ@!g[e +%Ѻ5E!cD~H 3krԟ x!nj ൭D-F !i԰e[~\ά9ĵ9~ \ Mnس67?z VW֮|K +$,T*,Imn ^->:.˭!,_EN&22$'( BCMW\`$̝;@M$ HIU;>A,,8GLO&'3nuz 5=M?AK,,9CDN11=#Ȳ󆇈 $]_i89CH*\P@#JHŋb pǏ +j1ɓGT%J"a(`KlQMeN,)͢ D4#ѥ5Bӈ#H4@!z_(@ñV]VOcZVCDh$U rEPR=![ӨZ2FlA0# |0&\6GI@fLn%ԁ©Wm[o&8`+ wזs1ws5pН7bS-WWVaXiŕEHTGPLp!~i!DOI$%+bH'# @4@ VDed:F6PF)R@M>d \@`9W OХlIX% kif)g"0pmY&P" ` z%T._:zDz*B9:C Nh`Bj*T`Pk˫ð{+[- ̖f{mܦ 2*[;n!,P22$BCM̴ ;@M5=M,,8KLW㠷̼CDN11=..:((4 &'3]_iHIU89CH*\ȰÇ#&$@ŋ3jȱ!;II0cʜ)0%  Iϟm`N@*U*thQG.JdSJʵ+ƫXj구Y`+4`)۷nʝKDxx(!Bl֦A 0㪆 J(`ǘV gϕ-LM 2bK˶ 5$:t޳w$`@[ |8 ,x+n$0pΛΞ#4_^}1OR?(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬհ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8M,,8̶㯵MNOxyzꠢ೴CDN..:Ɇ((4 33?&'3IMO$]_i89C H*Ç#JHE2jȱǏ1 9 ɓ(S\ɲ˕%_ r͛k$Sϟ@UtIћ:A ʴˡ-1ǥNjS@ժPM@P`JNxQ`m۟iaL@W !<kJnQx@1[yQnABἈ}|2tWZ`_$L@ > ʶιQs-<0vGs 60@cE}b*(`M,`ͦe=-Xv\10@Wib1L(a{7k$,@mb|8ef0$CIAvuEV`I)aNjv)A ߋ]ck8eİ ɝLNY%miI` h[Rvqu,ɦ_EVFn~Wk 0)Xqqd:c9Z#J I^aPA4ژ|4ѧl -HJp9]sOjjt:FbXŇje6>{Ud{{*E뢽(kp]pG쮞L /Q@G4)$1!pCA0Kt4lsH:EbE DGpH'L7 3d 5Xg5O5X6ht#@p2d3j7_O] t[mވ'5~]#<ۍg^s" V GN嚧z(@~괯Pq3SPܻ!,E22((($'(BCM```W\`$;@M$  KLW;>AAAA,,8OOOzzz5=MGLO15ACDN..:̣ #((4 &'333?$]_i89CH*\ȰÂ"JHŋ3ȱǏ CIÓ(S\ Q˗0cʜI倚0ɳϐ, &ΣHc=ӧP9J*Iĺ5ׯ&ֳ66˶mp.\z`jՆ,` 8_]Խ^cčC}Y*ok=~f;;@m^@)U.Ah`z lPA˕, t7v@s P A^$ v{͟(p5\d5 pW@VXPuzyuWf$Pzv{}eV'U8Ҁр] |j.]@\Z0!!PqD@ HzHٖ}`@IF\vx%AhIB~9yP玐I'rPDj(L^ezTZ%d_9VGMь5)sY]Yd0`LDuJiIiuvi~hr@ݗG6]I$B`Cҽ6yR^ݹ(HؑLp]?kcѿ2E=Y0&fw~lȕ̑ (׬\Q 1C:OTЊlCItL8P-de  \w-q Pd-bz A>C lAV [zg7" x ^4wA!ÍwO^^`Kt7{Oa{/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒvmVDiUJENѥRie E>ѦNiuD.ѧJjĀ!,(E722쨿 %( qMX`5=M$4do_=ƅ~B!, E22xѹmmmmf:Ѡрٛx&'(蹇ېz٠׶W1mѶBCMmm$(Ѡmmf쫰mmٺz:fmmm:fې:mm珶mWfxק W::m~~~f:꜇1W1剾1z:fG۾[^` ՠJKmfwwwHF:ٛWFFKLW򹇇F>?Aٺ:x޶fW:KWGLL,,8ItH::z1LWJ((4󇹹L1mjIfI11O:EMf::fzzf:fO砇z1c::jKMOCDNfIX..:ffѠm:xz1133?Q1z::fѹېablH*\ȰÇ#JHŋ hȱǏ 9II(S\ɲ˗0cʜI͛8s܉@ J&ɴӧPJJիX#4ʵ+QJfKٳhӪ]6Vp {ݻx}9b޿iKx\$+^̸qH&rL2÷x0<0È LNҖSJ~yBsW|A€b< 싳,J k߆jf@vf "7 葥˖/QyC}:%|Cp@8x߃ p AH! Sp2`!PFPR'_]-{DZX樣Kw! @AtF6L6@T o f60 ff7@8'2ZbqH+#UC>8F. o4#1 Ɩ$ƉkX#Ÿzjj 覜xJj7 +H*:!Jέ^^鳽5;(0mqi⵱:kȖg+,+fCg?AۖJ[~*|pvK0[뵰' jPznw|f1j.T'wR308{s& l -HK4z)VPG]HmuL Ww`t^mgh;M6WftmCn]T߀nm' ;W8.cnwuz褗.o-. ;^7޾oQ7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> $n1 Rtnp#PB$z;! WKD5!E%/M!*c KbRZZ)wM(D XJt+c 082pk6` 0ifIqs ^MX5`p3!$ iOt+M)a JPD3@ O8ԚیH4S1Qj(E),&NPZĚ2'@`SHeЄ@4%GHRltiMsB ,TsrVu*WӚY)Bzz@:B*$q P]wuA6CUj L|0f+6N'J*@x,xM)S賚%WUӪ8obӊ1H@;yjgb4 &JqQ6߬vG6TC`< 0ԡ=C20 fau DLvWRhlr1(~^E-8hZv|Z֘sg?!~ M s<TF Ԑ& &<,^ "H"([.@Rka`@`M=)ܦK $yRJun٫@X b֞$h2\yin2O إ@-|_`a X6N #Z]t 2X→pNYt49,7 U lld/I̙=RZq'7:)ӈ뉷@Aۺ @vY!Ҋ6'g7遳jglOyr8zw꒢!k]%uьf׼fJlNk4K@.$nbUwqW>4ߌ,S4I p3 Zܽe@r>ӞLI374%nH]W> zCUj۽a/#ΪU:6_ڿ'lձ :=LVvkN,|:A:oLf6FMa>t RnЫ*<< =*_M} <`7KpG≟%8Dzg+'(}})\yLQD//DnϿ8Xx ؀8Xx؁ "8$X2q(`yt$*hG'-u24G6x91=F;(@k4DFFHPKhFMQ8FS`WFY@]HF;DHh(c(F6i enyHXxsȇaDi(  @gft @؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy9YyiٙəYyeٚ  ٙyٛɛ9 )SK0]@iS )C)3Iɝ靎CP I@ E ќ)iYy] wy9*Ϲ) 0)(ZY jI+#J*91J QI׹YGՉ9E $j<ʤA*dU9Yfh9۹٦vzڧɧ~)Z٘ڨ:Zzک:Zzڪ:Zz9*:-SzȚfКZ֊0byǺ:ʬ qjZ =^튭a9] ` C= .Ǖ~j#b " [5;ck욱 p ~ m@[&{ JmP! K&{I@ "P2KZc3&YR`IZV{XZ\۵^`+0d[f{h[)nfa tr @m`Pu{_kyp^ K/PG`v˶; B/V GbB0 +];PB0y y{/ `\ /&y0 B[ɛd{F+;"py+{Ϋy+ ++ K盵 k{˷;!,(E222(((BCM$̴``` KLWAAA,,8((4㹹CDN..:33?OOOablH XȰa‡6 ŋ(:FC H@8`e–&c @@̓lPP( 0``pBLX 攉T)LUORpJPO.` U0V2|pvγ<}xD t˴gb2 #)qWy;3VÙ$}yįa] @22ѫm\:Ƞ޹ҳmѐmmmmmm\3m3۴\;@M$mmBCMf$ʼn:3f ̂maKLW3:3,,8ѣa((4 m366ȹQjCDN6;.%..:󂅇33?tmѐablH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗ȜI@8sɳϟ@K ѣH*]ʴ)A5JJիVʵׯ`^:S8DKgӊr* 60`]KP1ぎߙ  @vAH`tiF.F$ v2jz} ߺK )~/vǹfhB T?4xL}{|ɏ'_~gq'!`x wTyA2fLŅ mlq0b\KȄ4X|G U M zah~-'x§](q[i X@tP%_8%Xj @t,YNqQlk#h/EZo DhV-h96yvo$Xi:0iW~g~d87e|]Yi Wwm[} jaآ/wEABq@ V tÌy<Ђ$*!噧1@9a 0VV|2Gd(Az꥞k&b @z&hڮTy;ͮ2,S$ )~7g>1nX|(*齌HVk 2WY1\2J駜eK,W'[Zk lsAwjbKf1NwsbHGIAߪ+xajy-mf.YD Jn2\[^XM0-jpod`3ꛙmao@f;HQ4LeO}C;o}Rt=!os㞯>P䯿opBG0,x:II @Z{7@+=AGH(L W0 gH2ILDC@ H"HLg PBH*ZX̢~Љ*z .hL,A86x̣F@2Q0'L"`B#'IJZh<Lz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrNtL:-Y:<;zS=~^1?JP" tMBe(Ѐ.]aCъZtmE7ѡL4HR )EQR4DhKgjOS4iAoLprX!O8rB#Brqt? dK:1VkMХ@, 0 |0fkYY@9#s4w ri Paw-XdF9iBzq`q_xt݄柩`4A*@u%Vi3' !ilVf|b{t6# AO@p/xpn gλiRt]x]opܷp+UL( @Ԇٚ6S~\]A@it&4߄oEB:hp@G;G(sNYOASDςMB} MAJъZ.'юz 4)Ғ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN+[8Ϲw@ЇNHOҗ;PԧN[X:u`pOqhO{4n?aWxs@4@pW@R ' =ASyO;@Dx/Ǽ O @C% $ nIz/}zϻ xxʧ$x>.!C) *j1( {Q?I++7.00Hǐ#K˘3kYϠCyӥG^ͺu0۵۸/Ö=v彻ȓ۸УO-?cνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ`@T.N;N|/zz g.z` H2ы!,++22BCM$ KLW,,8((4CDN !+..:#33? `adabl@*<(p‡E-jT@ƍ v82E%MBLQJ ]FLÎ6cLhN8E6)#Ŗ?֜HtPH@u*ժR!^Uծ`ÊKY05a† Pܹuū ]{ %Xp^861 :!h\`7{P̯h ڪ 0 (E@t@0 !,n,22 :;E!# >?IBCN؝##/ _ C''3VWa;>>ꫀ[6ɇ[";>I[ﲹ3]3`x!1H5`GHS `]&&2))535# "!Cꨩ++7>?I 5Ã6Ur00<366㧇[[\fH*\ȰÇ#JHŋ3jȱǏ Cɓ(S\ɲ˗0cʜI͛8sɳϟ@ JhF*]ʴӧPJJjSVjʵׯ`Ê=:ٳhӪ]V*ֶpʝK]o˷߿aLÈW N̸ǐ.L˘kN̹χ7M鳢O^ͺԮc˞M%ڸs6}{NqÏ+_μlУK|}Vνۿ}ӫ_Ͼ_Oߛ ןh`mx F(eB8"6N U$h(,hb0h8<2)dI4hH"90P>:XHZXr)^yAI0ce lYxXH&/uX( 0t>&*ک(h <#sڈ z*i @%'h8p頸vw @jyu쫥&k謹©+7Ь-w.@9@ԉnjhiZ.{c n P짼loC/&f5BҺ˭©nm(+71YR.2_:঳)],iB'E P4&tQg-`Qj-6k\`'9ڦM %t Uݷb݄(PvgP2 >^ |קB˔RƺΞߐ߂{jfddb_\Q?. md[I=*=7;@M^cjhiikkknnnooorqpwW~2v!k ea[K: 624k FZ ZM[TPd;e9a6\3V2X$``O:1 .LS3 ..1111 H*\ȰÇ#JHŋ3jȱǏ CIɓ\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧ<BJիXjʵׯ`B*ٳhӪ]˶۷iKݻx{W.߿ L~+^̸ǐ&L˘3k~IϠCMҨS^ͺӮc˞MJ}sf/\tv[IAr{:ZzӇ,n}&v3+=,'u;{_W.wMҁR%pK ʄƅ'DRFކv|-T~*4+mJH\K4*fK5ޘKa#:zhH%JK"'8t88GŹ">8?]~&ny22ޘ*]&K83ŕJjf7Љ)lFf%` ^Y\5 f'tr0+j3?}cWzT}43-Ђ -#]kx%@, B+-<Ju%ĚR<;,"k,rkʨ; 6m]+{LN= [ko,< ,$l(,0,4 \lsd3K0вK1 LD U&U#nZ .wujkna൦U># (2 .x{-x.p7s55bgw砇ɒ~Lst0L12 -KOBN \o_-GO/Õ+_a8w{mv3`ooW߱3X ˀ(NJq c,X c" F,i`KB1 V~aA0Y{SՃ>`1tƮމÇALp4ecH*Z5#2d H2V0Yr*,qaB~)[%o_T1<dWG.Ak~X5H>+`wdX Ft#GIRtJM Aֲe*wYoq 0IbStL-Lağ7jZf1Yfzә~S@JЂ- BІ:̆5 JъZ-D3юz FCJҒ)JWҖtՂLgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZD)Vծz` XJֲhMUֶp\J׺pe+^׾ `WzXMb:rիM3섢:zAT:N5+ڡ9~ tS׷=67hO_f;[GNmY '⥾}Q9mWx\oدv׻Oxfٶ>|S/[,5{AқOWֻgOϽwOO7;O*O[ӿgu4=8-?OVϿW]2 A 8Xx؁ "4U &x(*,؂.0284X6x8:<؃>x9~9 pHGL؄NPR8TXVxXZ\؅^`b8dXd8 %h+l؆npr8tXvxxz|؇~Sx .xf؈8XxL3U -f1 Px؊8XxX8EXxȘʸ((SDp x,0 8Xx蘎긎؎8X78K،9Z+A2@0 KYyّ "9$Y&y(*yhS94Y6yi ɐ1ɍDYFyHJLI-YS/1ُ8YVyXY-ѓ yKDCٔdYfyhjOISԐ 909ZYvyx)\) 9Yy٘9YyYm9Soȏy9و:,= 2  ,K9Yy))SSr)tYYyM ٗ1q /P CYyؙٛZ7+1yyɓI+ S@p9 P? Yzy*zy0@pаY  p z(#z&ʢ4Z :.Z5Z ,z ɟ@Gʟʡ I1zM*iSiÙ\ڥ^ʌ^Y9, Bp:u xzs{zy J p; ܐ x m p:u*৘{*tʩZ*jJꩄ: Z ozZDz*jp 9_ڬcy zޚz; pxڧp wJJ j*ݺꧬ 窦+ @xڰ+[xj9H&ą+$[ Κ*k3Q82[{2 0 2۳J;i jB;۳<[@D P 5;0PZ:>;91j3 VR2[ 2;P;;ehk3;F[0%t˴KTD[++bгs[;L2{ h @8++rں봀;{˅Sțٲ>)fK Y{f? Z " \ckU[lZ ໽g; i˪ [[ 뫵;gk 髽ۛkN[ < ˿ Q˽, \,׫:*:k}{6> Wʰ*P釞N R}Ұ`n=K=|}~>천.>Ҿ>~~ݾ.3EHG:'pgmA MX#P#j"I6  -B@ .mn? _;oNKmx!?~8-~򽾼Z\,ؼJHJLNPR?T_VXZ\^o.S* 9P P hA8 4߄. N酎Kv7QDki1#l=R$WC-]H\(KOZzV'yʆ=*H0@ d&s% R9*4,]1T*UXFYdJ6ا^֠wKdn-[PSSYfΝ=Zhҥ7XKdH"\ {E![n޽}\pōG\r͝/qcGA.y9t<@zjڈoIP x]y(G /<ʀB˔ʪOAI~J0C½T?}zi&3 %̏D@IP4o1GwT[c~H#DҘVS'2J)J+2K-K/3L1$3誣ꬋ-tF~/2x̔f4PAPCEl+QGQ%lRK/4SM7SO?5TQG%TSOE5UUWEL8ZSVnUy\nW_y3o*EE6٦RYgGZkW[a %[o7\q%\sE7]ue]w߅7v](ꪛuJƒ6`&`QZ-ja8b'b/8c7c?9dG&d:X i_F8fgfGSᇓg^09h&hF:QH5Yg_SZf:k] &ۘczCifm߆;b1r6KDۺoŘB*.cx#ny剮v2Czx:?xwY>|'_I¾}Z{';/?o?QUπDg!{C! UЂT9msJ`E8@-t )( C36_4l5 Y %6vІ4 Q C6wLtX 7!eĤHEaY,*_b^6&:nE!aFGA|ďМ<BҐ 3Vbp "F =e"1Kb!Fq&Cw$X s@Q2P~2%eiN>b*5yˊRbS\cÌ9 i\ad$L^QN?d_ u+r"XDg:H1ґ0#6 7fVnBl'|f"1鰂f$˧/JKb&6ϋ:lht51͏tjJ`[*#xRgNuZ3v{hG "ړBGQ'ΐOla$zғ^q g :!ֈSn-j&Yi!=U^5wD _ UpUf<%#̰A̶XUʎ&Uzk*Z~mQ*Rl:l+qZMëdm,oiVWlvki7Ƿ¥9atS`=;ч"IxET,cUD@Yƒ@.D%v43 ]fqdJ*~T-w.tOZk#v_2׿buuJzQUװ> [b$OLkmW@*,o7@z@8cҲ YS!b!))VVKl!Tnc~^. f^o=-8Z! GrØ\_LD1q%6V\Ig)At ŷj4m~33L .z$ukJqxu2~R4ui,¤=Z֞afvW3!&7YN#6 :SԳT0jۘ\=JE[t&ǜ.$~amm[ϒVGlmqs[4*-݄4*-S:WSz*-7KS1^22 Yg(iLAk@dhCyL .;ɂĤ ûJ-Lp`ԾGQVիDS{,c_t55H*H'#|+uPn?8eExUo=S/4Rv YW݌yuDnYVmъ2w* HAОC (){,H<E Q}s05_rJ1"x l^'6]"W2c!͞cv{p&!;#HK"a"J ʿc82TU? -7AQ48b<858;9k Г0 2h ?vA P@B0 sx!lXf . a =؊KBB4T>j(CɩâCÊ >ҭY` \{}# # es fc I u K$Bs DDSĹB-D5E:: [ŋ8}h{7[@z@ {D QKdB8EVOĹ+LsPSTDaDrYZudvED#\ɱ]&j e I 2D%BAld,lFGT\EN< sH>qCzvɑw̎~A?)!SяIK`D2= fpi"ȧ tu$ɪ1IbJFh9$Aў!TK`t˷L|~$ q])'_9g K1Q,ԑtTLɑ˭|y Yi?a 14DTdtׄؔ٤ڴ͜L?K %0Gdtt&CDNX$N?`4^XDTddO| OLnj 8Mp%mOtɝdΜ$!8O DnrLZ+џ{PPD!uQD5=QLQI !% ߌ%U'u䅱 c"+ 5Rdқa\01%253E4U5e6u78=S\`pR4MHx?@-Վ.5FKDݑ\?QԜ*5MSp)?uOM?#UPa#Oŏȉ'ԁ?TQ UߺՔ$U?h(Vߒ MfhUi՜jJ#Qe`-:%eԃst'UJ5- On eMm\VbUM`??jV՜]Vm̀MMMՈ%~MneՎ=XVhV rՂzm&Qg}eǬyTW ٟڠڡ%ڢ5ڣEڤUڥeڦuZθՔWU] ~Y}ͬXJJh͉mm?^-ٴӴض׷MY\ָ&uU(h[SYEn"`~-Yץr٘%5]ЍvwԬZ[Å[ZTU%XҁN轜O5eNUi5g+Tpۆ~]0XV՞@] YTܭ^ޫ5TWa`_?5^ mP^E[^ |m`׋e^b]pL7\ 6FVfvaՌW?-ղ&RZPm]5e\m ]>޳WXZ^}VSxU}^P]^G%d%US\U)v'fUSY1^W].0b$>0%v_(vc:8^cc6NּuA>9^a.&زX י=\l`` PUfVvWXYZ[\eYHNxu]r5#]% ղf(`pE&>^Oibb%>X&&d`xaim A`Y qfթyj碨VŽ n ^gcodM]{؀g}Ndnd׳eg/ݲ- ,#z-VnOPí籝g嗔$[YH]fv闆阖^EIpkڨ~i | HrP P.[f? Ɖa VMI&^t xjk&kr.WJ.j}ԡ.Wh j|k~aHvk^ V48h@hեv[Ɇ9 X xƯȹkTYOHem؁&6FVfv>n娴iOJalA Fٲncehl^f>bVVnddjkfXook^3njPooNVG6$ppglA k6>>-q~jPq¦' Nne ќLH C׾F+2NYS u,o,124W5g6w789:ws?4k5ꆉnkQ>=F[Y L-okls漖tG_࡮vjt6W6WUqtOtRlVuk&u_uco7i\tq8hSgl+k찮k`] "$OрPE@fTar4>(= >r xI !xLBi0@xixta^x")"-"18#5Xeȩ\MDK/A 9$@wI*钒I$w6idSFy%vVV %Y wi5y_')&m&f#uy'y"]#LJ3(JqePF]J:ݔK:9t_>&WcWMb2/h9d*5 V:+z+++ + U#KFezy)MA{%bz-TZmޑ)x$0.z6 d;/{//Qa,eB|0 +0 ;0K<1[|1k1tp\ )2ha1<35|393=3AlI4/t4QK=5U[}_2V#S<6eGH.\6m6r #G'w. }m15~8++qݕ`6f[~91r,{9衋>:饛~:ꩫ:뭏~Kvx0/p1;+xxdz de<;)0n?/5𸕈 {; !2tg!p 3p*) C?>&y2X> QEуmŸF!y쟊|gKWjGKn0E0grP2+F=*RMlX!ЉFq4F!6FT&Az5GҌeUaE+&׺1jli[T2H6 M+b тt;Ɍ R#*<` ,!Ht瀎Gj4ҕ-bhuGq$kI7Y [LQ=-Jg GviK]vupG[ql}H`v7mguHF~7q IV5-22]:|vx\A6Frŀc+]#fd}j SϙN%5+iIĢbEA܆!FVDE/ zWv,nGݹG<ZۺX|ma,'Td#QRRA6=120d0q,2FN~th*{f)MA+]{L|W|FURIŽ~4'2,>kgq;M3ԶrL0_C~R:#I]gZG+ miHTZ$q 庹׿v$J7Ml/~6Aw|N/Ӡ+:Uܡ6.AABǃeB"}{s*,=ժ*ni ZድvjTE)XUɑk'@vi>-W>ϴ| vZgv+o' Kh'w4X!s0~St7辳~.ast _czd"Y_'1~hm9ԠdNz}A_q7mz1YxǏԕF݂c\+TO70~ӾnU+ kKMge{Ρ;Lh˖g`sK@ރ/_^8n!wߑuIBӫ I-`h_iy5TIٞ^ ឆQEMOJϦ= VQ:R a1. ֠ `BISPi֥Q2 F.am!!uή !!!  "!!b Yh#>b Bd&n"'v'~"(("))"*(*LO<$֢-Ξ%R&~00#11#2&2.#363>#4"c"J"d#X-v7B.X/~:#;;#<ƣ<#=֣=#>c<~5}#@`!#:C>$DFDN$EFfFn$GvG~$HH$II$JdJ,ALƤLLf4CBF,@P%QQ%R&Q~4܀R>%TFTN%UV%cIL,6 /<@JX%YY%ZJ x,#Aĥ\%]eeB~6EOBP`&aa&b&b.&c6c>&dFc5PeZ5AaV~ƟT/&i&j&kk&Yex\nnne^H C^sJ8H gEu>] q{e S1vgx~?1|v2'r}Fg!  T TgDg~}(&.(6>Aeb tV6 sd$ &(l mr-oh&pVda '>h_(=<%\_̅6$),4(la[x"@ @(1)@Çt)ldi D8ti i i)BCz=li>J6i:*F*J(5\,* `gjLp( Aj**h(VjneJI9`gc`g[+@Fq[cjZ?bijCDF:>kDT6eC1+ÇH6+J+>dåb&hv*F1A*kH*ȨU*Z: 'Ȱ%誱VIk[cj\p"g@DC\Dp6eʞ9l,AlkJD|B|klj,Ɇ,AEr x%.-6m Jo^6)&Eh_@Fj2 $+łgj4fBFl )Z FDh( D).Ơҭ^.fiɱll(FB1 Ӟ.nkBHJPmfZFN't-BWViB[20v-PAC@JliHf.4T/4حȆ@v/> pnxn.QE$ /In ^-d˜x/?0G"ʯЯF>GFNBB3T:@0 $Սp Pq{( } g=@)+ W&)J0H Pe + $N,PU9 ;S 7Md@MxÄ D(M̮ p K4/1K~n&'A@qH*rG:r +{0( #+p3$kd) rXB3r&2 7rS%r9LX?// ZЀ0sM1qop7č5_36g36o gV-0342#GzB9G+GW4xl,7+: [I3Fr>1?d>7?$t%sF^qA+*(CD_MDDkt1"W[3C3n4ˏЬ4KK4L4D-G 4C<& ð>l2W ;g>27W&(3 U_1D5#sQC&rT3CU Sj,'(W}Lu,;5\w} Cd[!ϵ u_u`v $) G]C^ @Ecfr^XqM(gsilI4h3m׶mJM/mG.sd6X 'Sdfu s(S5Uò W0 &spq8 u;@ 4qDc G6u,wu0r3uy rO$}wqSu/2 рcv|wzwdK+C~+f{&sk!G{rsWi'v3nf*<A4(l 8noNw&`Z<\5G6T+zu~~pg+ygoî B/c .s1 kyW9 c>&pڮ9s8[x'p_1<3fw7u&ÆMH)2qxønʸA>x:f( #y"7Q2+~0g?uS5+9G{Cy,3%4c?yp?>+9O:o0;0.3[ߵD_u;l;_oh8O83o:J3?B M0Q~FWw_G1?:spu&|K?#?; #|::? &~D7>RLuRR@TF_A&TP !Fє+^?f[aΤTr/ɅfM7qԹgO?:hQG&UiS@BHĘ+ ٸkW_;lYgVmǒEyLkwde̙Nzugk]?|f$5^_~\׏u P@"lAc(+O )@J^Ĝ#>n[LQY@(FiqF%,Qy ÐF2×A>S n'd䋂Pl+R{/G,`I(܀zBJ<s>kt'A,Cq*EmG!TI)K1TM9OA UQS KҴҖԩI8ElyR>o+KjEOS6gκ5ŘB&-cxCN[3D-U 9\<]w[}yM^k aM֔}<X^osvtYQ/k:[REbiqXp.TYI7]-}Y;m2p@uE i}{??bEG|{Oߩ[{][ݮ< z]_+ |[Gme3@ k{1va?-D.r\[Xfy).wA}0^,8*\2͉s}2< L.R B5Vix-R zM6!ZЖ3lOjo,!HmzNϤV)/ '8I!{C!67dj+`/ GRTh8Qp&j(hT΄(AMFMR2Qsk:¢PF9sx2DLɳt'QKhj-D5ez eTuyؙ a53ދeKDϛ~]vW(EK4ьIo^6zGN^۾ZN޸qfUUNʹ±Ղ2v9O&*T xUz`X5,gDQAѡfR>g~Ł0䀧l,9Ym'8.LJr -wUrhbh<>Ks{1h,3a=tc&Õݩ\gL5yw媄;r%׽Β%kUR4[bL69]/+V\eRu #eOrTNkltv^v}lb˺%1n벛61O(em}1o妢^n׶ny0wkE4zm>695;hlQӈ $/lx(='LmN;G?:H8 W0NÀn(JӜ`/(*A'JoXB2Dp%R/ܰOhpb˞Lܫ,# 2د 'QR ZPmp~[0wR[l4d 0 k" e ] 0]˝ndivM ِQPqUEf pa 1%q)-115q9=Aqz% 1U Q:j%q Kr p1uqy}1qq`1HQ6Qi k1ը=VW¤1c~xbua!q~w.aQEf-'R'1ZrFR!bnf2#b6#; #= h$Q "#52&b:&;@ h&k$%*d2(r(c%Y2_\0`(R!f h!b@*?|& !i),(e'F<ɇLj)) ! B-B/0SnrmҲ3f@ f*r2?+m+@34Eaxa4Q(^V(.r)a7Sx|z|d"Ov352Ba:4s 1"`g9s<+d5U zxfflgr&W-j6!V *3Ot@@s"!<+cB-Bs6!`4%tDI7 A=wo8(p'qetA| ^&fr)?/4@W{@g8K,fatJTJC ;i3CCItLb5٠Ʀ ؠ%uyXzjz--I? (xHU@zf9,f 5R%RGK@KKOQ=Sb- 6! L'HNAzq8qhOP!/ @w@{PE0AAu+fJ(2mYIR1KT#X5[ BTITQ)qj߲lIqk8I#ij]Wh bَS׸U=ߗg/RkX6x#x"BwU-&q %HuUBY<- v+vKj+ P wVo"|BwHwzIphjx㗜u19w"7y噠֟sYb/"yzYl9dh`!tW8+b3Ͷ7m9pw Wn-/y[8Π Ҵxvؙ=)>aE\!H9^(#>+>}3ͽQ>#?Eu\a>e~imq>u~y}>~艾荾Z;"ABR>cr坚'`I,B뷂 ^^S9F2Zp>LE>]d۾T:V'%ݨo-Su LrQ%]Z!T&aa"&A?7sa -?/1^~D?e?Rp uy@U?R>Tvf?g`DjlA1KFc]?Ro)͟ ŌؿbL3 }МDl_.v v w/#m#.Qm xE5УMRQ]M8o4~i[g_{T^j}%ׯ m >˛?Oʸ/-TbyV܏V_cCW.81Wy9K&qN8`G!<BlB%Z8&ִ bMHK/rv46}[uav]uw-dN> %[T{u8+(j5ʇ pHedR'vS_"ys(n6Y_5KBjEdZld Ei~ jSLa5(L`M6<!5K:jj3`i3r6Z_-Ȧli+sܰ2Vk ֊dmZ .;Gk6\i.X7_-8/a.MjUEb)Xr*rFViɈ檊/9F*\8?vpnLe:YfǡЇU[}% 9g{֍[v: jX?h}fY_i+ eE;ΝsN#`őF/!تrU"gGr r馟/3QLs_K,sEo|8mP[qGxb"#m`Oe[;nfWsoK^\k|X+KYN^6ǹ"}:AJpӺ.K[T2f#U*8Mf) o{iT3ʼn>lJant="z䀞T| m'p|oYD6Q1_EXpUQbZ*0`n$Fέd[9H qtKEסj5%.E5P~ֈ E(v mH 75l:j^s5LDFdLFKl@4yKh(h8!QzQ"yeZ )-FiT vF7BԬ5SvG:XIѵ֗_IWJg>Qً3NbS}7ΰ`ѱ7a1^Q˜Ggki/ْag<t^X 3P\jPV(2Ss4n蕬9Ry͜t65ǣ6Q2ԣ*5JQJEPL-d7F'uduKUH eUm[ ׸uG->xf [ֲ vEYaGvmc Z`U Ґ 8-g?[X5(liOԪ)lUZ΂vթh֠vogΦ|-f[*1JwojWfD q-/[wU w+qX׼o9 x/V{"׿ npFKx/ kx? x$.OJ&ʸ 4qy <%wǼx yD.a Kec @ 0ydH\= Ƒ1 gH9D0 2\cc ( @ gn#~cwqn92γAkzӜ%'/TZ"4g"$Ӵo=B_֦>O` !a}$zn-WlōqFEtg{tQ&CumgH@^P!{7ϭfJ.x;Ó ' *lfTB>+^[)nee* ¦%JQ(8mn0Sl ?p%jGOzɛ1+'ހqxMh߰}aOȃ(< rEq=[\ m?ʽ{h8~w%{A^ă|*?b/)\ {'hѯ>?rhЀED^e/ϛ|9 wM4.mHpzFz}g*~˞?ny _[aqs@rtGq"$vS7qrK~ 8ygs xq BxM'a ~'x-$Wz (x{au؀qv 2 )u+v>XqrHLu9Hx2pqh8 G"'wp2wdž}*f_ M}HXaXaqu =~@sH}+x8w@ru-r)gux>g|-|v7@sGy7x Lj2'{AUHWqH8w؈؄XGH6LjȈ,gu0xl"gy6 (!bvhh^ Ơn~H&guvY;r荰}_gوk(~dž r7'x$'uG,׏'HY|0  WW,} vuIyr n^P h 蕡uVj pJ'|w/r-AIp)=ws yw G(vqm٧ow!i/Ǘro~:(ȗ3h\N\HUh~iuk_zYVhaHaA@` ~0U7aӸʠ~DؐHHeXzw" @sYw9{DhxٜIw8IɓXzwz ؙzǞhPqR٠.tYu^Az]ɛ!SYaizDɂ'u.W0+(quq~YGHMgZV *\a9aciveaFdhZk*diazd|zMg HM @DfFjFzHl Mg  JA:az Ϫ v ƀLg 票SfldvъJZP\ƐM ኯ,ìzkzPJ  @ _Jg @kk ˱&Z Z% *;w/+h{P ym&Ni0?k2 z^;`ƴM봩%PP KIMI a+c2KZF۪Y˶k\J]ҥedkw͔v ۶e:U |M+ 'q[BaP]KֺeŹ{!@A^k \)m}˪ ŻeVG [7v׋ 2A ֋?ʒ3OL6{ QQav@K'" FBӿq4΁<+CRa!t9۫LlGX/AB5lh$"RaR!A!$b@!35,hH5S'5QE"0"3D#A@2"|l![Am%%<`(trfT& l'7EL,2kDb('7lc""&\(*B;L$Rz;$ }W Y<[BtL2-<"+k/+GɘQ#O-5%N,L6ZQ---%%O.bF"/"Q262/20?O̼0501<CDcȔV amVE3LV3qA3m3>6a4?RR5}548[,65l7dC+3t2L}#7N@7L+M>zH%ЀS7BK0888 }>D9:R#24p O Q-Sm l L, RU;Q.Sȏd=EQO!(-^M-CE<#=iBsOڃ8C1QREDE#,ː!K'KHt,Q.CmMCۣD;$=>B (GlKX43בEНҽsؽ(ZT\EecdW, (ԉ ڪm?[N!Gm-HѵRːHH*d8BD8lJ4IIIl7RJFҩIJ$K/JJN](:K&LL8Tm4׼;߮5޴Dd"N0DlOlPP+PM`nPʑPU> &עQLdNQ]$ R00|&IR!NYDCn<4QDTRQu黕鰱EUDn9/1٫^&W v\{.ꬎ빞@KbN=Zߺn;a ~qU;[ϋ^]c~.឴K &Lc>o*&UmjUee\vo!k%g/#aYkF/O&k0~u3Ψ6ʖE*?>߰mnF/>zafoS/+Y϶aG}Qx)bz蜑xrq9u,071"}y:<aA CFvt^xEu]Hab^f!\{:kzo7aqa~s}vZzx,ꑓyaO %&aX4mzzzr8{oW{pU-! hΪG|XbxzHgWIw}8'/ٿJ|tNA%41‰3^$QcEIr*e(F"Jojiٳgl>QG3;r_IɅUYnWaŎ%[Yiծe[|ւHĘ W2C,][5gؓ<}t$&yqc_X2 1V?SkJ6QcȘ՞iPι tAȠ}LMq#OV U3|Zo3CWdn.AO$e%xJ'6 1i(bЧJq9JsBjCCqDK4.+/Kk =Ȕ3EK㱣gj [$98S$NbLnKv|iJC ' „mM%"1rlɔ󠜌M0%HxS<@=q1#Ct\I9w$԰o?VQ ohA|($D*pCPuW^{W`JEXEc/2R.zL@ό g 4ԇ|59J6%nqEApȿP5O}Vi:rrHUwNTZ!XP~a_TS\eǔ4:UW}W#ufY9fsygQ$V cB6Y'O"PAWJv6;HVڅ'v9-]\该5%x$#l6@Aڡ)1[7!޶̚C83cFSxV|:"VAg%7[%gK7tq9 38MC6*%I:@6i^@w2 t!&7QB Bb._ +He6 d86JfRd'=J~R#e)%dҔ0ʜP8?& $ H\R\K#Er$f1yLd&S\JR(TTR&7})4`E$g9yNtSOXLgf7yO|^ FƹNT%hAu@.0Y=PFXt8iPfThF٠wrndRJZHT+E^T31fQT;eG M4)QR&Ue٧TFUPUOzUfU 5 აG]jYz}jUkek[%Sī`-OzU{WV%la {X&VelcXFVle-{Y:5~*CWІ~ lzZ^emk]ZVmfZh}[\8F0q\&h\FWӥnukۮ 5OiJn[W`yaB8/`]Wou OYmm^_L=oz ^¹ep`_~{+2氯L ~oM|bصi~ 3qx݅}c ,gi&'Yjp {`DBr`"òFFe4CBWfsL,Os˞2|gM K9ap&WC&(ڡh&2 |)z+*lXBoBq˰kAzԬetYBѿ@5a7n>` Pst!i}:q ޫ [b4F Ե~ KnDx8=nӁB_}hQF,|cܮto:;@ vҀ_o[␖Z3[*1L~]lj\V, v#s*Lل4}/o;nYV菭ֽonc$_wGӞp||9)l1Z\9]ث6G߆{ J[z9atpx]%=y}LMA lBf~7W;۹t?_h3ԟihqȈ7;!-{Э 26m3&ޛ|v0W6+]l'0eO|N ןpx[PyQz]wϻw0< C,C<K8\{V<[Q#t^ѣm^4}Cj{5s=Ss QGc4T R;>_@ 4T+ T5 ?KA"4µCBSB$8C+ ,N7sBc3[K̚;㱙+@=$,'Ck4v+,2|>=E;DS6 NV@wSNsأAdVGGL84IFDDDWLGT42lEE@Tx;HLWL䵢s@eۆ'|F8C>,-<=G;JI˹I;ÁMCCw8atcZcK,kBzt ŧR$QtzŋCA3y$1@$,RC`H?~Lɲ;L:4Eʎ܄ GD|AocmAݫH IG#KleK|I\€;ŎBzzz+CC?7QP4ll mX1ɛcIL*s4,tD<rţ>{K!A[O^#MI\E{DSCȨF4\MQcLdz{8߬+DNcZ\[NCMܴ7kAĖLN^DŶ{I?ѻMIh;M-, f\dE} 512T -ܲ ѥJPZ7;QMIJgnM,PQ"2QQ u3 PQ"',Q%]R6Qzb"R:JR&R-U1'].(')R1#:S45R6mSc?9S9PqS<2=->sS@ T+!SE=TG}T.uQ9;;9KTc`;]TNeԹp+P UQ*'TT%%ӨUYUZ]R5MMU]=_U` Uc=Vd[5UgOuHVlY]V mg]~;!(VmMWu*nu6oWx-qV(c XW}WjW.x X]WcH~MX%(3X%^@`0ׅX=ewXh%z8HmY Y͈8Б$bG(.ԐiOK ZgRZڈ0%o4B"(8T\9هYe姜a Yy9ɋĭ:٘aNJQ4pbZ\\@8H@]z֍0(ѿE` ]]mD[= ڜФa\%mx޳̝}^h!Qդ9߂0 ^͌\mnEȅ[_``[(^UV ܂p p @ Y"RS1Q ֠.Y^ښ`8%2 "` ~ ЎF#5a8πݏfpU*_ӂ`/>`1&fY %ԸAA(jCQ% )+\96p0I4Ihٞ968V]>FiA!IVKL^IJQ[L9NA%)QR#M]18^J^p૵_7y0b#d`~ϭɚq#;IapI/*iɖtvg1R5Zziu$-$Yy0\eп[yY`.^a'40nu! lF_ x9im`z{Qj$o1fufᕼ9Y܁هۈي٩`_q#DN^yHA"a_橍!C2Z"^Q뢶cMnqiv숈 9;ɉefUjƊܯ&.Y@"e"|!υ"a!*-2+q '/ܦ"DpfIn0#"Fnubq`y#Ue9ZT>2^m1nm`QRfo"%pd"pR@eg^c~Y pp&~pۊhbpFmppq pp[׋׆qoYWm`"x):򙲩_r Srp*W=br-q9Nm(2r2/[ yD 0 r3s- *t(ѢF"Mt)ӦNB*u*ժ*x0kA>"̶l}=#ζn+w.ݺv$*߾~,x0aXn庰LDl76ڻ/cάy3%[x4ҦON]Ċ6~Qړj9zέ{7޾"Z5Ə#OuB\aCO ?{;޿>\9ϣʼmw=+A){6_~ 2ؠRXjЁ~2Eh'Zc&ۈ3X%;&!hG"i<2٤dW/>T1WbY eE&٥_vcYzso%[`Yxd{YTiZhZ(rޙgBj^r)bF'NZ lmyۜ+Z"*5z"CB`R[mir:~7RjJrgnԺARi%^%\0曰ICzhec|Uæ PEL#dq' $3K&\*#*?DCb K# 4OjtHw2W4[)0k͵ez1VewiSn-r#uǛݷ x؃3kC`u/޸>MNu嗃^g曓N^H]^Ijs߈S("_߾+{_Jd"k'"0. bx+b*׀3e?71r#h;1z#?2$! )DJdD T@6C#%qFѐ$';O2%"}Ȟ<,,/Ti7.V2*d Gi[2%/5YʞsXI2/UzgB3Ҝ`~ `%$%8es%$5is3&6iw\j '=Fu3'5 (,2'AI2N~"4 ]!ɕFg:ձvYЋz (G;C"Fя4*gH9F"EKJP4:ݩ-LjJ]+mQ0}>ڈ ըEjR÷l NETIժ>kD)ծz`]kP:Rդje+]5@jiDո&u-[mf6 kVJb94%daXYё;ع6dKkX~6|[Cjֿ֋mhVr5oɢٳW. }KLrAmr(\B͹YZwMoU dvu;>z^ Il}7x_L4oëc< "bΕL┧0__x'0Klb7:4+zHPI ؄#>1k+d٪wB2CqEY96/D2i /A)W9bӷ6架glE.SWdg_^sf1TEA&;9zGqNZzEѐ4ڠ]ƴ4Sw2>2jRwԨ?ZXmX\vmf%]kctД{-'kgcƾNZcl;̘e0 $4[w; 3*&hºٽk;4LWo <⢤ ~z߽:F1j_)h { yy!N'7. 7g`CUU 9Λ^G|y0V 6 !P›]N; \NMUoS0`I{ؙMgĄH4ݕt] @yO1>ozwx;]Ixd;D+c:J+37mۿq4W9>Fwioy:?N>~.qO~M~zТ}msQ䏳9jgWPT_M " ^e )& - M"@9 Pf v`A=P#`Pe ح`R Z (Y a a:%JL>aQ^Y!`>!4}!ӄ!O _Zԡa"aP  d!Jȡ#BNLb'iD'%('+jQbָ+b,r,Ң^)Ȕb/J/^0M-c1`" 21^44R#Z#ac26b77ҋ6cP&(Dp1#c::! tL7ƣ#= ]Yd<4*?c3NM|5#B`HP>>$DDB~AcF*JDr$٣7H> I$#iY䝸KޟFEDdM~Fd$PK|dOLC edQbQ" SITJ%QeyW`DXeYeTYZ%Pe[e\[e]%s]^U^_fe`fa`fb* b:cNcBdRHfebff.ejfgzfpghJhi&fjfkjfllm*Gmnifogpo gq'Zfq*rgr2sB'rFtRgRgubgp^gvr'nngwgl~gx'jgyggz'fg{cg|ҧag}_g~]gh[gYh"Wh2(~-hBp=hReMhb([]hrhmh( }hhhh(hhҨhhhh)h i"i2i,iB)x ' ('΃ HAJц 0$  @B,`!ُo {pĸ6+Woݽ~:t@ἅ%p߳36|1˃΍ 1!, 22!$BCM <=F/EEEO%$0((3 !**5KJmYYa=>G곴0F !$5HO0EP "0E/E/.9 @*\ȰÇ#JH"EZȱǏ C^Qɓ(SH`ɕ0cʜD*ɳgO7or᳨ѣ[|ӧ `ԫXYÊفM'&]T4(ж݈o>PpߨAL}>(8@flfqX;IwyxZ\Io*:Uv2jf)&<^!,Wu^22fe]]]^ꬬpppӳjfTTT_aH*\XÇ C,Hŋ ȱ#nj CIУɍ$S\c&YʜҀM,Xp&͟@IΞA &X `i*m-jOJD`C`7pEӲ$Ǫ]KmS# ȝKw.ܳpA+nސr=HL؃]x^|:G@BI%=&TR%4o觯/o HpG@W4B? B#,Xz GH(L  c1h>`>2$E@$G K A$1 :PH*ZX̢.z` H2hL6Z\ ,ЀT,p@'b IBL"F:]l IQĤ)iK tb$jAJ L"@!0 ,gIZ̥.w^ 0IbL2f:Ќ4~PE?lւ @(fARnL:v@B8DXG w4L؄NPR8TX2h 9h\؅^`b8dXhjl؆npU Η=f|(e|8X'؈tpv|xB臀}pJ؊xwX ȉp8X8h|؋Έ}8X@Ǹ؍8P׌**}x>|ڸC +؏209U p h HX*P;Px}x ّ" ؂ 83P\3Y6y-  Ǔg'Y1_% GYRUIL9_,(<&8yh((l8tYvIGg\1p;p[{$ɑ x&ٗVɘE+ <j9yn)@)ryyi~;P9 8 hIi_ C ;p 9h虁ܩ  J ٞ(Y 9J)`JCi ; ♟Ȟ ZI %Z 'ڍ2z8=9!BIzy||EH y{*5OʤxVY]׸pg9فFЙ!XuB Iީtjz 9𠧉:{uڢ}*ɝ0Ixiʟ)܉ɠ. jA 9ʢʂʍjy:J EG:IJ8Zi79XZ˙b& n Dz r? ?:<0۠k: ˯:z$ZZs*ͺC K˧: ˟{ $1: ڳ*?@ږG A8ț3  d8ݪ3X˃늂< S m:X*);;*p ;u;5 &{I,:0.j˷~!*5z tʪ:0 Z 橡,k¨KBʶ+ʴ(@8_*ѧ%;1PV;8߻:8'ȓ` *lns:ʷk. 0:}+[(&۝ 0k ̷也܁{*/}Zktɝ J¾;DIہ[Mki>h5G]PlJj_lAKZ2>,tI.{Z [ZǡZ\5ܣ Lܲ 0 A  { Õ}l \Eܣ<0ǴIKk:k}V+*`lLNQ7_*܀k@ +o+*鬪90~| ,ςl< ΓZ.|$K< ϐڬΒp5;:\ǡ\:ʯ m{K\b +`*E;^Wͷ9zZ[h= % ,:l$8<, c}#ͩ <їx- C)G|8 ̔>(A}kI$ȖF0Rmrz!?č- 1 sz2ʡ?`ݞ2Z% K@= ݯ꟝\sm މ+By͸Ktj*Z|Kj۩MT|+5p x5-:HƲ] NgI /U|+, -Ĕ&j̦}{ENS.bJQn}=:.ǘ<\* їKmPH [^Ҍ|+M^A\FSwnR8/Џ/@tQxœvNxTZTj(GN)ǥ}~}ބط]7̼nݚاjg`n|>>nQP~G>}|^֗>}}˞'L>{."?N`Շxͻ>}.1^}<||$H?&ԧC?X4ͱ.}3 ԧbZ]*`S/E(ivfyZWA-\䶧͆?Rb}_ʷo rυFǨ`RSUィ.Ӌ_ng |5?@ԬSBЯv'_ |Too|a_͞>_|#`jC DPB >pĉPh F=~RH%MDRJ-]SL5mq-=}n3І{G M>@5jܠ:ƌTfZXe H8X %ٶ;`5X`…%P|w]%_긪U`w5kg*0FӢio[lڵmƝfN{`tRlkbR/\tc`w۸JeN^şGT5RG_=f}w>TJ9o,.50B 'B o"߀BM8K0Įj :n0-D"s A jh(sGQ?c>bG#q NH:%Z5/K/3L1Sp 00$&,+wM"#R2.SarPC/#CnLn9?fuK)9:ҷcR|[z![v<6κl63Fob86@]` dV %9hYG5`qXÄ#'Ǩru"<  @=W.L`H !@ 9n1{wT*x߹W'X29w6OHܕ.|"ER#qWr'E4ZvC^|\|+C#F @iV0#-/wfC51L!]ɻ *X9适VޒED}=[FN-|{[(_ e8Ô#+ 8g4T~ j_jͿ  b0G#pW":Gc~!C*r## @Fr#D$GK#\F >˔0HTΒ'9 Cr>JJTe'}K*rd: Xf>JBR4ݵJ尜$ao +tsgBDQYH̖x7(& ݌'1a,ʘD< iҔ4>tٟ 5㉰cUi7`aW\:Z̮PmDh|(RXu%cFhXV$%5)#PH}0–qEؒd_Etuhzj,s*V{Lij(Wf$/)gk7UU/.j_E';Ү1.}{̎й+iz2 'Yg<B-XmKڧV!\,ie&ET1ulDaXbl(ۺr$6R6$-\D<( #`TY~UZ?pz܈8S9dޮ\EbY3rLҼ{ V:D "-Ev] L&U^;V/7Ŵe?9r7j&UID;y}F`w zŞMՀ~zjQ0STZ[l 9 d85 6IPk&ϰqo GbuGLev[9rK Sx7*uόg};󩊐TƛߦDuM`@8 iJ~n4}P6\{Ud}ijzx'aMC>55|0aSkzRlD2\vY@N1gm!^v֣mco,پlm-yLfrIv{˥dEJ+x WQX_e~}O8yz> 79pFw97fXGU/8x/lI{]]s# yM8CPz}Ixoud'_gqhS~#F]H3Cf䍴GK[N%ˏ+Ϸ7{?X 84 TڃJ0E c=4ۦ=3:0ѻZ}P=4[4r@ҋ=Rô/$9)X{ttҐ!>0>;A: ;e?j"p>)\! 6 6(؞L0&Au?<~*s$@20KK=\3=>į9\4+A7L뼖@B,Kij@\+l$=ILªJ0{PD̴+Ec 9ck ۏ!,+ዤCB";`B*c , Ӛ$8H;"3d1 @^`??GStشҷE|4įz|=|%%R9)G⪈D&w!HFĿQH.ZL.ۿdҤJD %@ڃX$AIrE[bG>F2n+c$II„鐔12F,/F-bԶ45;1,C* طK2˸:Kٙaõ$ $$FԈ¾\JҒ:k\c̳)#4Ʃ 7yK {"JlVcM ɦAJ٪hl4Č4LsJ dkBd 3JYiOMMo PB"'<OT614  ?, <,,FOI+1OO#%1QI]`PpP ڠPGٔ$P6>&tbˬ ](j#()B TMY e6uS`K;j =e Oa41DʩaTC SKҦ5}LM!="#MAX'RTc'CMNA]W:FYFUO mkT-GLNEdTO5PQEXcTEQ=N)]>ԼfUQmUtU:SVTez}MfE9L1d4OhՆ(+m q".Ri]F1UBݗW{؎%|u0ۄ׬xu mO}G WuYԘQ\u T6uZX5ڣ= g-!T"P*NMX{(Ya؆ SX(W{ڎ)Ze۶- TVӈ% iӭ [Y6-\<ӻMuɥ.ː[VF˸TXƪ^ܦU]H-t nu\Zkɭ\܆\X~\)]\,m]%]ĝӍ]uUmW0w=E^^(^lMS;Rf_ދ^UuY(5VItӡW̳QR%Xnu])E@Wf. `3  X_h߅x˘ΚcKFb5ṍ_ۅhʔ۬m$P@4Vc%@vctYK8abɰvRۡ(݆`B% )6a+>W,2Sj}\"> :@%@Q&ReQ~TɞA3 1/"0;(SbEedAԵU*M$f,W`c$Hnoe%Pq.^I嶱;-#b6&^A;fߛuA=fT[eNfOH!onF sX0S dv+= ߣ8~6Fgefs%A鶹pgDU`h9h芮苦$8h2~2h&xjjy~N1R>KYKޏ>Db$ng^Ϙ_i!n hӽi IU݌gf7 sވVjpKB~21l]l>@Bئ;& k;-li1]j-x8ڶ˶f͖F&IhRl20Kz>jHkm%yV`,aNb6 / WLFܵ#K%lhNވ0jpm֖n~n^MoWm@oHŏf֟ xd2E~FY뻾gp ngp.nnLTM-8d:y}lq#7sCqB"Omyw>oVZ&/%z퇬~jN3Ѧqxq3?= r2Xו f3-WsB d.nrdq2q#Qo硫@StJu%I_utGNo&jiROg\ j0:/hBuksb4udse7GxÀ]Hl>EMnvu˶Dvl~tPorwsWoԦ&tQvxyz(AvQmbf1 kڂW]/̠ *騗 -Bp7xxPWvO0Xt wNgdJRHo ؇?kyF vk?xeƭqN~U@niu' E&8g*:>tx¯vyky&?nyO4@uP:viD&}EzrDn:YþΊGî %so盐{mߏtO֙9L Ċ\sVΕf%Ulɚ1YY3uQ$um^N vS´tT:3ijy7ߙN!}p/މVn>gJ1m8\rV|4yӊ]wM7>;{xS׵뿨oRrT*u=|<}53Xb_'/ CTZ,|~>?^֑n/X')!?Ey'Mm$YV@ʙ7g} f );\ 7D.g4O"bBp~I2"$y|$XÊJ+ 2%2YOA-CDɷFocoJDz<.3Nj8OpgFl-Hl"Ga|8GxQˆKZ 9qHKd7vbӓ$Z"Mj<%*DD&SlA9KUE4썑4eXɕϊS#/9.<S)iRS4N+gJ7lDvB^|1%H%Y=0QA#uweߤI4)ЁɦgwK$;r1J)'(FGܤ2CK9b>1'@I904(w*q%H3SnhS[ 5Q'٢Ѥ=UjҩR0ݎLU g=!xʔL.իGR+SV0k]9*V~UՔl8+K2'teaYd?EljTܤ]vXr=-j %xrJڇԡ/?Yl -0gkn)'V1mj+i7 kJ\ńX//BJ&rWW"|Jz#ȸ=^@wXWݯzKgFx䵧:a_:EnB0KBH cx [.H["X)!);^tPE5\0ƶ{|a^׽r])SA. ?"c_v [ś~:r; e>쇍{'k=F#0 g5 ꏩXg@;oT 4SNJSQS~Fj'5BrZuCķV-wMgy:Msl\.YȖUo~:|O;t}c]丶VjNkwzH6}s\8oy[K`Fj$M,#lHl 9 tbSgG=u'nXzGm)Tg9N:ycָ[8nh$n.څf߄ƏV*Go7K_WR~DlܝX!_A\lQ[Q__T D 5ׂ[-` &uDU! X2 `J TC`D4ص8Uɠj ]S C!S(C0`PXF j' QV`!&Ŵ衡!$Z:~R<) KTL!Bc2dNedO%P#8b@Q%FR\~I]!A>DT6(j4. &= G6]RbMV,&YF%dQt\B[fCd\jWW@R``_>Sa)NIvh)f'acfXJ&oBN>Pep eC"YR\;~$-ejDUzeQf:!l^Wɦ1n #&HfoC eEJ$EBz'f*¢UF'3=!_冐u`5"0$av.ie}V` gE'y6hQfS9儢q[Sd=~fvJ'DMXhFsnR fM2ΨLfag!GZㇲbkʤ%h rVfg*h>&V(K(f )iަ|k^~"ngJCȨ`Jh)pe%yHQg4 u)+:)j(B)ƔW,R'֣i狺ҖfFvTjQijņ:-’:; Y lr%*M*Nĥ*؅b簾[j6&qi3)GRjZwVjkJ)FJF걂ԕN~rU㿾+IB璺*1ګM⫾f,l$ek#P<ꗦάe򉣖)k^+Vj^Ǣl&ey͓ A[ubѬ(cJkQmbvmlHl( i -HH^F&B*켊n5m-Hm%guJܪZL꟮m>iP.,~ݙbl֮ zN&Fd;z)ژ>6Z~n׆Fnn)$Ȭnh릨Xrb:kʆV-5f^ ʐZ!ݽڮ"DݖԆj/QbJo\)~FZrRi BydE/fPm^F00l럙 ndh.Nx_nXpVop炰0`EFJ ,)e> w6/f-0ޭV/bpߊqo*Vy,@<0}/"Q sE S 1EDذƱܥ*2 -J`C21 O!ki#籗:q/M.9&-qVqc'i([{hKr@1*carb-Zиf˺^/w12{ʥ0g1052Ϭp4ږ.{7{/8C(C'#1[q:3?!.cM&rZ6+7d? ߞC?vHB3'rҬp E..-FbG{4 ZF5r"1C42B)s1Kt&krf4dg4Dr~g4ڣQK={Lt4.oN箒5szC4\ :#s5)hSN}ˆ0=u:e p's_0`.d/ʬ4M#cM1^PVK/vohC.5_v$CMMll6dGlM5O^kodX[͂'vb/6"665wqtӭTm=n3wkwڴf4]w,!Z;E|xuM[}[+~緾w0nv k/7H jX#cԮ`<4Apf@w_;gcW4k}DHvvwRpx△D ָj85M6]/l ŗSw$jx=Z-?jq_t W4X7cyux'dϘ+cWuEbVtwcrx_7znCEa}Gqu @R㗁,pv$m3yUk5g:6nV!lE cVȺgbSx[:S~b2 {+ǔ:NOj_vg2;g+袒q_; bAj\`IS;6C"uk9Ð0*|CW)T`}3+{xg#̛z1" ׻LB;e3k޼yd󯗹 7cCϴ>cW5C}J+Q}twKrl}SѢ,;TeHS=f{,b<܋kG| {|^cv\uxη5g?>E>KLQ*+>ϏL;=ͻJ~}}H\3?>ҏw^9Ag*k~FW+7w@̨cG&TaC!*񃊁;bPԸ1ć1FAYeK/aƔ9346=y Q0Ժa%배(rqEq!Zۏ R!,)mBAQJT0bK-n(q!/r- t 1'S"l 2=Q?# TA -4*$.ƌӓGCCL 1M#ΎLTEH X0G{=hUGCqU]y Q%'taЌp9}0<#%'I8D+$TDi[imVz-sM_]Ҭ⬋5ycbnSȄkH4SK!ʷ 7"㖾 RǞ#V?צ[A]XizX$w.O;5G$^ +AQ/fS畑HcBn駡jJB::B8ϛQY tҲC4sfE2GU8[,zoΛ9|j媦jjWm4S9GIwkFݙ6Ux^ձ{4߈/&'=O \6A)&}B~-ٍA `R9{aCFa L"ϭp^;yǾ oY#D"gOWT5Dkx8ΐ]RjdU̢:T aGږ4τ$T'!qk[!y0f.a 40q}_b"A"Hm;U2'ΘtMj83Hr͐t+H4R&[$Oɩ2e{09TxŸIQ03QH7#re5:Y0$5K fDPzO"4CX\< $ jG?Mt$ Ҥ> N6~=cj45v1٤ҔӼgGPzY%5:dA2H!ч> ^Ir3M=De>ݟKSgb$=SKA 41Mwd%+9 aq);bu5jVԨAJcVʑ x>I|F=+LT)ZM+C恛]a ;/_؍ q l06}A(ѵSk*f h"d,\aִulPjmUdj[0=w̭/]>aN|ʣp|~4>==++>Jt3]v: 2ҮKTx`P&b{y m0e/(S{;v <-k%.YR[feyٍغ0)Q,E ~߈WAƮ8%:`, p1H~2l_ɔtrld5rQ2D{3)e1(˱.ievXxMaySJ!M6ͮZo e;˱ɛWVۋLJc4iYvpG&jyh9YO8ЃC*>u4zՎjrҾ\ 9HoITwۏvmm}I [ m31#t7d=QrG;L5FNQvwNh'v96͐h!]h>:W) }6k;łZE˹U*ϖN뉌CҀqˮ,|!WUT茑|wzrԥ ~{8®/_gH>]O*P8;Sq9H3Eݰ{𧻓GhۍO:!iBn @wjr{1kJ&R{9;oxr=Cpv_ a;Y~1_-t#_0.arL cDt\8D0/@BZ/%-;H69pqPDl,&ᄏ2!SJne$$MM޺/7n00j 0&/! $k@ NfP.B1B n20M " ǰC a 1D åGbmefP6+`an _BE1 c+2tS ¾d-FBQ:Q$z1Uhp'M1]B} PT#8qª>S1s[.$UB I9lƷ1U,15. 5q!Y5!O9汄< 1kr82$ B2;T%ri%!K"S.> G2RRD##3l&(HoR gR.%үvjo)'mR/"$/1kTǘ*ZQC+E'2 u1)R@`$d-?m iB'װ&#H i2(s$/# R02.!󴢒p15#&C/A-Oc1F$H,1ofr2I1#36 d2g2]QV-4܌2/ 5Ri,822|Ԓ86a6e3:667_P"3sS84i~7<::=b.9.3507WFR<<Ӄ t2T>->4|c$5tC94*T9BtB ADB>7BIz,PA I @?t^eE1DQGBE5>yXvH4IgGIBH)HRtJJMItKJ#BJtJ4LɴL&GtMkK!LD4NNs%M*!NcNuP 5&tOO: >Q!5R!PE!TRQ5S%R+A/7SSM5UTC>GuUURViUSYUU/Vk53WuPoWeSW0X5YUX)!XtYZ!Y2ZÂW,P[5%U[[3u\e"\յ]W\%[%ص^5^r^0_Wv`q_UTC ^?a`UbW`Vv,<&LcCvd)[MVd!c37db| ^ dfhUhhfge_|0jN Ve d rV`9ckjvllCm=vkCkY6cЏjS v6icgAg&9i@ico oov\pqo{bvnn Vkvm=a6lA6>hdlt7tAm#vM]h,7^cv,vVulimtAqxUx9z7is h fI. >WykUr<d@||Z j9|vz+zupĐkwmݶkEWp7wY| <~ vOl Xv U1 ]7ld5%!6,x|{7u}Z{W7o[׃opznN؀ ku8p_b7kmxÆZMvkYk8d(8vpzw}N_x}S85yHpŘ%fxyx@xLV|Cցdq%yY։=k h-! g PxٍGw>i;'ou{5quyyGG7jn 9" kY ߸wjdcY3m!y؀Ywk'ƙ![8?pbpWYםYy!Yk'n͹RYb~ZYQg矓WY9F jY]W4b똢2َSYEW;4Hhy58eIF:XCZV:}u3!7oa28 Gq{Y}њXvZH:!.ZaZcve"vY*?`S%ۮAٯGQWz!uU{U{ge12c6%ᶰC5Xzw=Iej`scE[wd74C۵e㹦9YV Q#[3z&zzЬ ;Sۆ}[T[iSǻW{۲ח !n34ԛ}<㱟Xu#5[杫O,9>}}"݅d*q^S|\} m}^UĠVj:eI~OA6y}a\҇!ƭ;RW֢׹f=uQ=Y.JAc`37ߟ;"}5RTS#S_Ýe]9I sBs$|مק1&>{BN;?ߢǙ@{<0… :LXg;wy1#i9z2ұ%x$K<2ʕ,[| 3̙4kڼ3Ν<{iRihPHƥ 2}G O.gϛVz'+ŊVv}#VlJ(ŪӃo*ڶ\X*)W/º{ 8ŌbS`{3$,`eE3g,v$(ЏC ;ٴk۾;nBC <C:ԏ#O:z +=c-f6noa,5.콽Fۀo]fvFA4k=aNHa[G WQ%Z)Kasaֈ&~\_{|ދ>^s|X}^{Oe&.ؚ^eZne2eы%ZraWN>)u%XajaWY{ٙkJh[K֘yB hvYdxZlHe^ni~ M`eUi*cE5X(uhSIyJ_h~Jl=j4y6jAvTg)denm6zsF2"abLc6vUK zB Aa"}Kq_J:T: nk1v:K-g`:*T:+ҩG _ (1Gf uROm M׈{.W,vW˭t}B1s>mҁw|p]fӮQx/ z}. MtV ]f[سv$pmJnnB9?xV 'yEgFk{6hocwBtx:G]򀧿LĚߏQ _Xs^8g+T/#əH2%ā㫠t28,A 6lZcבaK,l Aſ`MkLy@dM4Dq-ozsU2h, MpBjFDL-EPp̉E.aK^4B1P*PS://W#](C|ok Y$#,J2/hWCh/5#9Wq,)cƶt iК 5rldH#F+2Qd bhXlf[tIEAUj7T啱@+YNQaeth]Ni )]5ʼɐ:%{,hF*cc"B᎗fVΌjtaWҠtb@ar0kP,j6=ds1|2eO mL TԡJ-x ~$77 ըQ^iQ\Xb(>;Eђz)P!c$g::T1c kP(vQ35a^:P&1V*;ዞ**T sG:z^s.]O'2h \4EVU;%*KQZJo{g4^pr0;lW: vbكVȊ50kUB ]^& hZ[صq+kIbZqaswL.MRu=KԪVEoR˜F&S[ݦӯO-Q3͍N7oGܛVwȄHcb/?n-Ba:ع7$H#$vN9{݇.y>*_gWIr0%y0#>.rPl[ńH3?os˲}7X;idg"Ei6?yB~"yeb8ׂA:pj=b"zִ~PcGw~}2PIk>rEPC2RiG}=O|fr`HIF%4Fk pjs{Ąy1v}J6$I450t9p>֜ T[C[{EnS'wx5,kqK|: nHsE}M"Qtytr[3d|z3Hly(oR|DoIpʫLZ]79^Q2|W=%'庙7|ww^>V犊 &}8nNtwb&x]\ET7ӷ, Hl C}>";ܽ]b~ r^˦6I sE=H_ސJ|K}LJm2tf+?4-o>or[/~umk1O{OIA+?SiWUrgw]z񹞾?|]?w5o2g}uF~ { ow~syg|}qa7w7gFgeJG\_uJ~8(WE_ =C~ya*OGKa-DxJfsg^/b`w:I_w~`~g"T@T.gLK:82HWV EsByA灇sxeLY&(}lxm}{Pi0hy ~l9<(#gHMƇi5u:tQ5焩C'pc]u07m*Ǘhi拔4N7 *zȌ,w{zՃ&"Wif]#T(^Ox"Brdy!h}Ӊ͈}hRx&^1Sma(pwx'S|ǎ ًw0%MMvHmE )]WA0ƅgY(x/3-‚Xh,hMBҘ+ 4xb_Hg7O>3鑖8pXkXÔNi5n#'|P3WHh^IfA0)֓h $؎8_~ rdQAuy \y1{Yak,V pglyaӀe9m))Z))xBwAiҕr 2֙# Beq)U|2lJT ւ]Oa~ldyU$(L81[(>?w6FyxlmLrSɈVq9sه2ءpYm"ʤCn$)JIdzb#eF ya= $dxi烥;X$Mjڲe7$ɟn@Yyi L*:WYhG)8m+ k i񞎚w*Dٱ$ȥ6:h**DDɒJ9ɺ_8U!q@:&2ʨ*g)`#IÊ5HjAu%Lȧ:nzV :xiڪΦ9:#Zjx-:E*F\;y:d s<ڭ2U湰A+ 9Nڦp˨E)cwzO[dyrxgʝYҴ;kW:>qR{CF ]R ;"^'Kgg!ɐ; 5_!a}˲y:>[G iѩ{~\ۑ 1˺ qZ{ѫvc ۴zWu6lK+dkʭ+֍<1i(=[ȴުj;IKI [jK括 T*vSeEɚ^ W ыȫ(ssl ,ʉ1hP3,ȫlL۾k \VŐiUY _?ǜqvS|C\|կrӌV{G1Az<勦1]rlɖǕlL\ƨkTL͂,<+;bڝj|g{oll( Lhʓ ̽3 K% 1DS | a <{^:ӝ<ՉNW#L54-}mQϺ#΋ЪP'e}/<ԋ=E r'{ _,LUm -8-ـ{ +Ƭ=_=ڤ˓כsۧ|7Ynڏ]ڪ+y]ۧ_ѾՀ}ԧ6݁L-UwW)߆[-6} *Ո_+=Qms۸mWޗ٧G9. f Kt„m b} j˗K}-kmo-73r ٮ]1U%%^-Vyj*nn Z Hn䔹\-w:DLќz.fw./FrAliuS>)j.\l 慾V-PLBӖuqN@XgmlܷNќnLlBGxN|, f9.T>}gJ^C >Ԑ`Ȧ~E.vgK1{}!-LN|Qug^^>>X^q˲GYxzNn_ U.̱-L+o~,!nrPd.Bo.JB~mFY|"^]> u:I.A;=ꁎR$[wmoe]ѩ4/1_0]_oIZM djh}σ^?~ IOE&/ﵷ Jg_Hh,o Zv^O!` $X .$Ν=tNXE5n@7 %!Gp>bAIdKo|ӥMu ꩉOA7Sh6eB3)J, (eٳE4y03g >mX?n;qx:5uh|cicO;Kuٵow H ͉o,# '+gF*i#0jml*p"hJBk? +H9:[pt '0J7,4 褃ZtEcqFoK A4㪽l -b OtR?VRHҎjQJR! ?d?Ԟs?P¤#E< =ZF3#8x`-ے""S*M=v/ * jM@,,J1U+8<\%.sS(;>pU꜎?vXb52( 2"aC/+u۟<-:Z%r UMr4Rn(Wv*2Wޮ|XVxa[1G@=pF^җ`[ށ߄ا6B" ߨJܷzs3,`6hVZ@uY9 X)KojڠV,K&ӣZ+&;Bv[ 8I gv߷ڬ|pLvK ͇͝8;{ܮҾ[W.qZ*92z6ݦ*ps}v:\ zVH'ʾg?tvO>'sEg R'UE}ʒW({jw(4cS*ց*Lbf=]oo^dc>tfI3 uoWe>]lnG?P ;'5}x B(J錄 [RE*!>)S5 ޤռƇN ċp[b;1P Hި&a`0;@L1$g6SO<'DlujO9לу:"->bD^dd#"- 1P"&vSLTF7^$Y׆=:4ic'+4Jr䓰h "!|d/}P ڃ fL!a Ze* 5BrNqiJ6v%cU&v3#A֮(΄g=FYl Z.fe.kJ OU4z(?:1 LP0/JyX>h<ˢ"S+g$BY&WӢP2bQ9~%SFkjUT&}Sm<[Rdi LU4,(KzF  7" Q!QS0\?@׃<=} CYI=|*RwMRa%T+V lB$*~m3HTyUZ񗿜kmk`4&AAJ?lErG#nMu]FO+HhI{]NBYkk%@̬v%z>Њ84&Íoj{J 2%f;j"T/G{\fW f!tGɖtwq ox"qQ܈F_'|:]t-.sA\Z$EX` fp}E(f+lڛ(3ØqfKܾ'bRw!qfCsH&+b,3B8^r\^XsiQZ֮x32l妗F†ʷsGDƳTSٖF&8Yԣi!$Q60IӬ*K]biGnPNXkN9l!&umS[:3'mF4@2CLvw{#oQq+ַfޜkt9͛1Oj^[vmfvM&{˹Ys}EC|xN ZV|wti]iWgy݂PV2A*r$N]w \/nf 9A\[ ̟rT\H&'҈vt[jE{ƹTv/6 r;ɗ~lo{x ?F5-Ry7K}T{ ^O<Osڼ":J/z|gwo}:7ycZG#~Z> {轿>.O}oK?ھ+9A'ZS#z;,u;v c37 90+??d+++jC@ A>z@28SB"0ӲC#3mT3cC#@BҲ3R; d 96 >3Bƈ0lC x3ۏ ٘'|#C1B,DR.@ 9ɿy+C0;*J ; #<%0("6-A$DV'D[4KEH>D{WNWB{J( @ieUlEj%B;Z>SŽAQZ__ED%/,kDRo|>؃jB48Ű/BəNjh0@áʫ8#Ħ-Eńx.HUGHd)ӪD+cI* 4D[h@ϠHlǹõ0E,tCI3i\ID!-.|#f [JPɋk?3( o<ƨt,*b,Ző,]G`DMF|KkdIEglCF5(ɊuG Ƶ$Zs MLl7$t<A ɩO}\NɂNOYM4%{L,LK;{ȡCdK뜯eƂ(IqO хς!QOv5XW*i̽ V]qy,ܸ* E?}vہ#_ a:;+ YY14F=*ۜa_5KEm`9DP[D4ĭca' U(ۅWa^`]ߞ 1`%\z#ߜE56͘}b;($f=6!W.Vc`u[ܘt*Cm I`4ݓ^սcNmuIQd0[eP^[[L$b>R@Ne@1#Waea9]+5xu-:Fn۶@bh__fslD=n[fJ.`ueM*&T2V]f]T^G\-ZN=y6^8+s~ȶ>^fR>]\hzƈ7ȭV/NFA>PdW^.h:dh]]\a/K~㎾7b2]eDyt!^N>@vc4*i]؝k›z`FEfhؤ׶֒~EV#5&̀kPnk^geB&kdcgJ X[3?C? V"9v([l kUlfle8da收#6rR>gnϮmTV.0ElS~h~W;,jڮʶ.clN .n叢큅U}nҙNF vvjnfdl# 'Ǎx~&V&o.)!č\ AF%lAޒ:xĐq n^_vq ':K1֏a HU&oVOX^?gW)f?򊀯Cf4iCpoO.?HݜrcN\pq/ź)cDs3WC W$^nn=_l>Y>f0w?2!FOivsxYr섈Bu*sts.O-9΅6uv?w 0W~;!Z%tuKv*p`'W]?hs^WfvnRƻ%powtQKnmtg#rsl^&jx?ek!FVlN1]num'gMOx`^toO pBq+xTb2$y:ow>f ?Ox+_3}ajvMv'z]z񉟒oֽkf碮lO-)*dcrhc{M{y!s h\'m*X:L~<|'OĽ7D;OoZs ҃hX{t~oyڏ{a3坁}Ixo4lvBt~{ZbA/owton/\;MOha&||PˇrΞ;X A(q"Ŋ)*ܓ ċ?q!OLBvTŒy= I̩ɂ,rܩ;A5%CHBrUTj ׮^ +v,ٲfϢMv-۶n+w.ݺvﺵuB*{H j-J&00Lox2ʖQ $C=o:^!G/0شe;-#I&C6/TȰm&u۷:%OzսӶ.}:֯cϮ}]Y'Rj6gg7~>ۙW6uScl' -4`͖m "ՓzgUS@AءNatܑX'+f]UuWrtbK5u}v?} ߂FmH.d r҄/=o:H\8eYE :7"k٦oZ.RePzTន2QF#fJ1*ZqXGt im 9Ff.(nr[tUPZSJzoȆ(RUN_C:ڵE,Y벫vn^%M^m*w~Kp?yV`AUsܱ.ETq+kϢ$/{˗kďyG5 kBv\?7찶]z̬Q/1U\Wc*m<:aPXؓhC MtAHWx | ޛeSֳ@}a%y h Mٸ0M c\sjG{QM:;[6 zzrS]3j9?ij)K;9z/z&?/ى h{;0}iZR't@ޯ*3Z })"6yVC!SG׭P째הn2U 7(Ax0Zܢd+~"UhEN8z,aƽѭ6 |5FUf| hC"R:[s`DnfDD84$jAmd lG:~2'<_, чK OJMJ%/{u!OӜLF)x!.8ItvI)i>ecbz!ѥ/v^VSYè$>թ=NJ$e:ęttCn[5a B֧ ?'w4[&`bޓ0k!,!X uORJԤMa%[I׹_X(ҧB[\#zJsD$UĦJE[LRS6~u>@LްSQt:hMjM|f:VB25MQ,aEP0Sp{3*ԫnu(Zu\}ST;K>(` >RC/me7n zמ<pϐ>>{ 7! }Ϲ`ou=0_W;{׻ [E <7x/ki7pzOc;o=%yl gC ic?rǏ˝ [>?}tC>O -_l0_" A}GjMɽ% ̔Yr ٟEQH Y ``N 65Aߏ ꠻ F F_b`=ETZ, ퟰzat@aD^_0a^Z "aFta "\PH""ʄ 6  ZZN"#br'&B%udbR(z"b, J)NTb*b`/ޱ."cWbN_0:3FZ1.Ll"4,r ! Y5b6jr7~Nc T9#*cc#4c;~#:`1@=6># މ< = dJ 7*B*-Ҡ *aD DYT$J\:zFaC$IHzaIIcJ$JcGKdʤ`3fM\8dOOrJP:PŽꤟ%R S~M MF#$c]%VNVzD3~Z%<>8eHRE%[q-~e]]ZW>Weٱ$e`aS#T&&$)cB&I&q"F"eQ2\gv&}fP&0Z&iZ#j j&뵦&Jl֜infoM&pT"5q'%gfMs*--uVg].dsrgd\Nx֕gWԥhe&5'g|.|yzdfZ( h^hmV1h܃JpQ܅bihvvvrAgiԉ:\.Jhw~(q݋((2'~ڨg'?^~B&)-y4iB )W6YV['z:izkQ*ߘilh蚲[_*hiڜi'\)TXi_:jA*ԩoRjNZj.P_Jgv`꠱*,N!ݪJHai N)#Z/ڌjk#j%(6RYİVV&'n+̧֘nF^c댱I+l+*tr+kH/R"Π_+0lN*ǮbFN,BDpVJ)'hjdHiǂ,L0xVjm#:lւ(ާ6DpnR;-ʈbb'禩~A,nSk*lkkn/YG$,.J2,. Go,/4zޭm.6uę(-m2^D"Z/~n/E/(onA\z/Fn0կS/!BEoW00&nG\0KKek3O~be%o O 02a,r0p0Й0K.j^?]"#1Ds!nFq`q{װ#bn1 q®+ 2*m0#_#?ٱ1'pQ>wb&{ wE2*z+_*򱵲,-.]-'#_(3(]#! r ^2MVr2 -?E3 ^"/6/'o 3"3s9k9sj::#b;G+r<93t4p5,/?@t ₪)+t65=4qEc CgltvtctH=G!>>38+JsaK134K_N2LPϚڎRNʞt"C³S?uQG"!t4{>nVu3_W?WkbXXoW袵1B5[GTO+8c&k]H5uv'275`ۏ`v֪bc7<S4e5W_65+1UmV{v5uhVfꔞjevD]vvn`o37pH4'w|sr35K7Qwuugtowuwsx1u,7w6zh3#\\g ?'{ywз67 4*x:~!D'4+w|/68>>8%{਒j7Û_^W_)xOzC8"vŸa䀓aKdv7ڎ]8s6y9x'ҒowfK9]8l{c9iESK[9!E yH 7y^ĹIι9ED7yynx 5:&Ly6GO7a+j_9YyAkYC,+zY xlWXܺz4d;7\KW{Nh:EcisE_\;-󧸻{G/3_OĮ;;;-b޾si0Vٯ:-V1=AD= gG-})D*%mi'." >_*.ݪ.K~)@~c}7%@~q>L˃ezA :h3 V^F޸KS?;t??A)'/Ve;7?4=8< 6tbD)VxcF9vdH#Ih+YtfL2̴ygN;yhPCWhrTKQSVzkV[vlXc,rZBkٶun\s% ٙ5&Bo`eG?X2_W|sf͛9w,جj6}ujիY;03_~}QGͷLNM=T+<,}XĔ0MT%+5`He=du0[u+aKeR(lJ]I/+`eL,v4sL6f~RJ4d8bΘ #7yBovOYO-L]fN"Rٔ3p$O-z~K`CQEt!PE{rQrGY*3*hDdOSZJ[Ӎ4AIybқs%4gyS B*uvJ$cSuEuaL$$ne[U^ biajEr|^j(jYtRU,*X¥9jPPdumTcz6Sf5$BU-8Y׊$8,ŐZ&\ӆLjy;־mDkԟr>7;mVqeVZeve\~w"d֮j饐w^&W=ߊ^Au~߽PIib_Gmi`.0{28&5j# 1[Ήnt՝5#g )4q"udҸ4r2}MӶq}Q'ԜjgGYԒNΩYIghR׶ٵfVj/65md؜ oj#řgb;v]|DN6]o{ޒw}o7 pp?)^q_9q!I^r{A* Ѐq` 8+W#C ~7:G:`ܼ8?`qS8:wye31ի;8͜RviWvq^wyv" Ӊ=+mpb!&O)n)3 ϙԯy}㭎ȫ}y{o`0}ӗ_\!G8=ͱߙW/G>oSI?}_8/3NOpN=C:688/X1cP3OlSPW[;.aG!s6f3n l03:PD/cg{^P yɰ3p$p6 %ذ 5`  -#pN .8TalCN918(9 3c3o1p`@osQA8N!P;9 m.LS.8q]o!eo;#pnpQב;ۑQQ R a iR!!o "Id"+"0"3R# d"/#?$o#G$#C%hSR%$[%$WR&g&%o'%!k'{'(R(((}R)))*R*2*+R+++,ǒ,,-R-Q !,722vvv  eeeAAAttt&&&MMM  ؓpppBBBuuuFFFnnn===### YYY666(((aaawwwfffzzz;;;H*\ȰÇ#JHŋ3jȱǏ CIɓ@ɲ˗0cʜI͛8sYp@< JѣH*]t@LJJիXj)Э`ÊKٳCv۷pʝ{Uگt˷߿ LÈ  IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4A(@̦Df04<@82 L<"@( =)p@;A80~s < \@ p4HD { 5(D2{ԣ(!H@ $@t T T q  @r`y49yj^Sf"!,a22    곴@*\ȰÇ#JHŋ3@`Ə CIIt<ɲ˗0cң̛8sI1%͕< Jϟ6*]ʴHJJ'ԨUj:W@KU–]˖Y ԶKW[ 7Q? ۷a4 pRǐET\ 3k82 pix, ӰcD@kٸO?(! Nȓ+_μУKNسkν÷Oӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,\1X5(9=HA EI*IM:QJUZyZ>IeC1 fQb&hPhK 0!,8U22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ#JHŋ3jȱǏ CIɓ˗0cʜI͛8s9ʝ@ JѣH*='˥PJJիX6uׯ`Êu+WhӪ]˶ۆfϾKݻxcƕ߿È+^|t/ KL匎<|Ϡg@@ӨSFAaMM  ~n H''μp80aoسk-K  P;XpBϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫"@J.>:/2z/&//:0z0 0 091yqO1 g" IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXuƖ3$fHj*ְer5)[V͵etZׁUz];־l>k^zD!,6222BCM$ 㲊|.e@Z;gA,,-,KLDC"KFW$(%4((4! B(43abTɛK&"@*\ȰÇ#Jhp3jȱG\HɓCĈ˗$UI͆2gfN= УH]02ӧfh ѢPu'Vt{SfҦ%'8T0!Aۻ/-(` D |r߁"0Ѐc `dp3p ͠9~AӨS^ͺװc˞M۸sͻ'p-r";=zЭCN]vٽ;Nx揟jG_[_?K̅Mu'0g``B@@!,4 22BCM L,,8$.e@B>MK;>gAKFWCDN(%4((4eK& 3abTZ @A\ B*| C%bxʼn@I*, %A.!h b@x@aC %J@ < (AADHtAV=@0 !,0 22BCM $LKLW,,8((4ĩCDN..:33?abl @A< ‚:| D XlѠƋ?r i1Č3hʂ!0x@bC3 (`@"-S` .$%tVL:A\h [ l ( Wܾ!a,~~}}|{zzywwwvvvvuuuttttttrlknuvvvtrm\ID}CwBwAyl:< -)1B) $J/p_Y2121212111222222111111111122222222222222:HAZHtSZSMLKJOYizߖѿ˱Ʀ׾ܵ|޳vxԙ C*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sIϟ@6 JТDӃLJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ Èpdž7 Yr02?݌9ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μ ^<@zjQSwOOӫ_Ͼ˟OϿ(h& 6F(bXx/ "xNh(,0(4h8<@)DiH&L6PF)TVi.&bh#^ȥ/$`&lp)tix|矀*蠄j衈&uϣHZgJ覜v駠*ꨤjꩨY%ƪϚkf.+*k&6F+Vkfv+Pa@1:Ї,l9 *+.Sh!D ,$l(,0,4l8<@n"#q4TWmXg\w`\/#} ?m;`w٭|߀.n'7G.Wng#Px`@*n"C釈n'^/vӷz|ڷ{`=Yw/o觯/o7nxD.} -D<tzPk̠7z GHB +N=}tυS! 0!@ H"HL&:PH*ZX̢.z f@D@40 H:x̣> $_І$>2H Xr̤&7Nz (GIRL*WV򕰌,gIZ̥.Is Xr@&phu2إ4IjZ̦6nz$d&(MOⴤ>8L3:N3>~ @dfR G!40J8#z'8ͨF7юz $Q ֶp\J׺xQ IfC+`W!b:d'KZͬf7z hGKҚMjWˢ@}.$HBdd pKMr:W /]Nb_` xKMz|Kͯ~LN;0z ^ SxnC5 L;GL(NW0gL8αw@L"HN&;Pb"rېcyZ1L2hN6pL:m@ Q,<(|@g9NF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεOM0׉5HNf;ЎMj[ζn{MrNvMzηM~NO;'N[ϸ7{ GNߡW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOOy;Џ~}[Ͼ}/_O~SO[叿OϿ8XD ؀8XO~h "8G}iiЁ,؂.@"y13 H:<؃my@"yl/JPO'V TRW{>؅^`w,D ),)jl{Yyo$vxxh;Dža؇~xuc&e7mx'xyuXxtH"1"yH@|yy(D@ȊW(hO@-P ؊ΰyxyHH'tpOW"ȈhȨ͈ HXxyӨyX،Ȍ㈋W(z行Lj[ سщy>0y07ٌ;X @ p'ޘI (12y(?8yxyHhh(X C9ˆ.)@/)sh9Ȑjl &U9uٌ(/ z|蕺xYItx~)ȌhؘYy錫Зcɕ$wy;Gd fhymٛ=l'QivI?(yC 8i8Y9똝؋8iW;Џ )$pDhH@8(9)GJy©bxYXt;НxyQy ɟ:y莮 ؍Z9.ڬ)~zSJ9Zɨ I޺8 RhOi;Zȸ[̨گI:{jt  wz(9F9ɯHٟK띓yy&+)Sx TNZ*iQ!{;گș5OKiT[Vv k(ָ{:;+ɋʍ_؎ꉎਟ9':u[d H3@ y5鴚g+:W;YQg&i{5*W[q@qKۻt@(ehh)xx[|ڻ{s&O{;[|{۾/{yB;ˆ ۿ++a`替 +|<=zs \< h,t* !L2&,|8.ܺ03WD\oìa0  N~Bs)lT\Vlw ;WsxxH]Duc4~6]Lg|=^]&7Xl@4mp'Z>dsS2.W^lN3 G@wbx-GQNjzރw>~W舾茮x^閮֗隞{c>ꤾץ~wF벎ʳ^v~뺾;^ȮǞ.О>^خמ..^>^_ o /_O $O#_(',O+01> m[F+G=4ET*M]ZOD?[=B//h/gl_kp_ot?s_x?w|{ǃ_OLJ_ƋoŏOē_߻DPޜY/߭ m }*o5P ٽŸL=ʿڨӿߕߞ_|o _lI F@ DPB >QD-^ĘQF=~RH%MDRJ-]SL&hęSN=}TPEETRm6UTU^ŚUV]~Xe͞EVZmݾ*\uśW^}6W`… FXb?Ydʕ-_&fΝ=Z芚IFZj֭]O5Zlڵmm;vn޽}\xÍG\r"7]t_?]vݽ]x͟zݿP}|o|~~$@DdAp#B /Đ 3C?pCG$DDWdRt1Fgo1G[qG2HzH#D*"dI'iI(J+=J-K2L14L2D3MTM7߼M8N3O=\O>4PPCPDeQu4RI' RJ/4S,մSO?mSPG%TD55UUW= UV_5V\V[oV\wWt5Xa XbE6VceQu6Zi'vZk m c[nE j%\*p\wߥ\uq7_E^zV_S^^ftˆ'x~eފ7I/XG&9LKF9OVecegFfo1fwY;{:h~h#h-i5jΦ:k!zkLPavF;mF`"r8[mNØEo=5F@YHhAy?C6rULHJʌd"8/o яe"GO2$U@ҕz_9KLMpxe.uI]BeHxKb6Wd1 l09M$I 5Mi߼3%KpV4g:sKӝB;qnpT]IJ#ٵ U&GwQEmY@XYBU! \v-s<""ָX ljׇ*p*qkPV8d.Bjx8Wp}.q;^d!śpF9׽1/C[[ڶm}o~{VJ-m_7񍦁\7X5U-lT+yIa 謘Q[~,%-),mt"Gʑtb©FQT(4 ]=:+u=[:ĻvLz S.1lffvBhi\~u> ZwHP;Dž㥑|nvg=GԾV+-w wf !S;7чF*$uc=.qrK|'r@2?xd[['cup|F$J?Dظxv]6ٯH:]n)R\`g;҅w_Nҍڏ_j%B׸K/4/£զ)x V7ӾN?miRӟة뷍b>m}.2Q{]#gT,ˉ?Jʟ.3="<,:k^#;9˟j!35w<`ϯѥe/Ed63;+4@X/23̴m៚q@L5R{. ? ܶT/d[dE7r B>+B4KB0;?Ĵ&>)t3>"B4*0*@&,@+À4Œ;cCCK#Dª$˷<35|*C9:BB4ɂ$EocD[IĤ$$DKJ!:$R)E9dE3D 44Ef]^EJ\ FkU,){`L6:Bb|Fk1piԢ0DF c3NFږ[9i,G15bFX #8rG{Gzd{\|,4dGsFoHZǃhCj140s?uHGȇ!HjGkbHIIKȓd3H+*H.I,E<BXBJ-TDC E>ɻAE>4I+WQBʿb2>,N⢲ZDANH ܬD0l=;0LO/ڔԟOTO%P1ŞUPaP E P  P՝)"UibeQĢQ )R"#E$UiRb'(R+,R/͚0Ӫ!23EӧQ5]6uӣ8-9Ӡ;<ӝ>?TA$CBEԖQEMFuԒH%*PzJTeOͤP%bGR-"2՗RU_jU{UX%NYͥ[Uw^%_Va͗b5VxAdueerqgŖhVkjkVgmenVU1p`9$Lse#Lt?BxN z}¹3A}Nm#|M/U#YڭՓZ;۰%[81۳uU[5a۶E[2۹[/ۼ咽[-ۿ\*!…E\'Qeuj\-ʵl\n ѽ5]Aԕe5y]]rUڵ]%<ݡku;^eTe^aU=ƃY:E_Quu_E_%; &XNX۪^V .5` |NxN`NNO 9@yEAzMaM|ᴁ?[`ݜ > b!."6@$%fp'ގ(*+-~/a0Q1.&c03F4Vchc#}a8F:^R;9c=ƍ>c)dBCFdPEfFvG䯁I>JLMOP RTNSUSfpWXǠZ^[]>^`a&0cdV`f΋g滐i !,/22BCM$BC=B"ɛZYe@  Z;B>M,KLDB"*(%4((4KLW.#Ⱥ33? ȪC?5 B.= ,"K&"abl@A\ B>(qŠb1cÎ0 @ȑ% DipeHlI0@Ri3Ε-e s̡"qB$X' aӃPJ CՂbE Paiy ܒH*8A]$Db@``n DT DAЁ >,-! R谢!,;22BCML$$ KLW,,8w((4wɛB>MĩCDNț@..:B"Le33?BC=Ⱥabl@A<8PB >bE/(Ž ,adH@%*D`e˕@a%伉"U:S &l*S H'Z-a၍c ?IC #$o ?#wU*}wt_ CҴTw#ˢ mmCCC$}mmCT} CmTCCmCC;sCCm TwCGHSv1))5Ҩ=vy6}:t:w1tӚiz7=wrҚgmTT&&2mCs_:Ҙdt++7mmmt9ҚhU_  pmHo ҙg?@JHM qқkCC}οMq>?:&7It_ sқiH*\ȰÇ#JHŋ3jȱǏ Iɓ(S\ɲ˗0cʜIMrɳϟ@ JѣH*]ʴӧPJJu̓"jʵׯ`ÊKٯUӪ]˶۷pʝKkֳx˷߿ HÈ+^x#KL˘6̹ϠC+}ӨS^װc˞M)ָsͻʵ Nۿ+_μKNȡkνzQӫ녡i|uCg> 6 FHWwvvN9$!(PbN Y 4hR<(X D`@*TTVi1ɐ4 ;Bӗ:!p;@Eiɓp$&f cl @ufNj@ ; Z ع Y 2(cV*颂c | 7j_A߀ )US)69ʀ$[ upVg9 xK0ObnAH}Gl`&&:P b?jr& d 71Pbh5.zyiz +@-8*̠,J1jCۻ4V3ݘ;#O$Nz8iʴԥOe k<3\ |e xFʐK-W̩L]ڪU-!;B-wh f/KU )i=l1hRIFmw^#%HLsL:)CzfGy8Cn3w;( Wi\"!8a$Hi`~"BJ$W 'p=qΚsZV ΋%鯄3F(wIn?]@ ,,WTSAtA?[թaV(jGaC9ϔ^Tڰ [)$E ndLyb!MltJ!tdR<ECĠ.JKҚCNB@ \8dͩPUŲΕaKZ5ͮv^ odK7Zxol#b#׽ͯ~o"we}K&M) [: 7 qm2{(.0V0 @8αw@L"HN'FRJl[X^.{`&32bpn1L:xγwLb̀4bL,ЈNh;$' B[Zƍδ7NkjGKŞNWV%4gMŝ4vw^""P$.d/ ,\ApB _{t{!If Tx˛6oݚ a "O}; !NLh= @M_x!R0Wo,&Ivxf; 9A P*H2pPm^OB)9wwNv,!M^  mw ݝ gޠ]x|0G0T1X ]p7}?xwJߠ@ex֣>=Gz3`D]m`R1+Ԡ?( q\"z}!iwȃ2P9<>;{ cxggw|a|y8w( vGWww7w/y@ 8mGWr18$w'w7}9˗Xh| #>}<}bu9~$6`6oo`8rWfW,zWjza} ؇p MwHgGҷO'O/}1vzȇG{'}؄灖>x}]@?x F YXik97yHZ i"|,06Zy乣ZѣAwX}vx npNJ'^y$#ӗ|ʙ9J KPWwwwʡڊjz8{%7>8yh שڤzo8qʨ47#ڮ1A1p0gDceS`Jhg>  B aڰ{6 1 _C c`5 +Ev(g.am  "#>s- B;)AƳ=LnAKP+F{McJ˯UQ۵;;vfkbƵ^۶ 8Ƴm rvз{趄Kpgz[c"OƷ~ pK.{p&; ;} }{+o;O`  ;t+ț,}[{근;Ի#{ ջ۽q뼙[{Ѽ 䋾b[+{ۿ;|  < |̿"L <&|›[(,<*02\64|:f<@|t>D\ĵ6FJhHN'PPlŦ 0@W8M}~@=!}A}UrMlfH RMS]qVZ`\d]c]hgl͹kpݶotMs]xw|mv}=M؊ԋk~+٘-ؙُӠ]{-mڬ ؝٭=״}f۸۴ۼ۔=܀&}SfȽ=&}eؽ=%}ޤe8=ߞ$}Odߍ>3#~bW >>9"~b >!$~a(⾡,0>!4~a8㕡<@>!D~zaHeL`P>IVW#Z-^,d.3`^hglkpq>V!fsuVt~us.t <}~b lL^^0-LMN >C^;~3^+~~#N} 1P?$O ?% ./2?4_}8:>?@=DFםJ?L- aSUWBAeQ2ԎE7GSPNtB/I2-UWd2Ԛ*UZu2vQ{SK u%ZS*$-WoEnUa$֫r5lՐ\W4n]y5(. h0ZH]%xW_%.QE]ۆ/QӁ &OčW&/ 3F4gbЉ#f_7' $KF:^{9$}hemf:hnfv묃#9>]VZMZ˛flιn.[SUnnu\l1Ip#62J;OI!^uIP!#pikvt&5AF=y盿`e{M=ݑWdn-iS3` <Ѓ/61va:x=taA炇q OЇ3Fn &*롮B!q؜!: W(E.F`JB@<Q.X!5. 3'.2φ:SE=LÈ1IFE?nwDcG-6ҒMEXiL{d'!IEꍓ*)D?DdMI$і4#i@ Гh:[aVrveݖ"jL&0&aҚDe+7M,0$5oMey-qӞn&:Kx ϩZGK~2X Ֆ?9n]0g)ј 4|3RU< /]E;Q{ \N,_K4iR߲\E]PiS;Rqzèz~BehMՊzUgL)RIV(\hRҵTj[xRTHEk`bАU{z$['׸[^? {b֛ ֳ2,OJtvu=,V ->y,MKplnԠMdQ0f . .Em؆6* Y% qen;_@@`/B+sE~gݐ5j}w NJ(]x쟍P ~a n{_"QjZ9WĀp " ^pwO2A\)MJ7Կ0WM r6dWFлcxc0i "ׯ>&_|#wcǝٗVscЋ! gFY4SY|!ŪhFіᮔ8;:ϗ~+v7no7fVn–|C2z!Nu!=`Zm95u}hzqoLކپΰ2sjMmW=Q9tvQ-knגG<[Ki*t aj6ۛN<\S>w4mTjoc A/vm[ߗQT_qzҤsi9ȶ&w6BHzW y/.c^[H$)*uQiouyurʼL jYYGG; ;[y@lSFV+~뾻dK^t`ނzqwR(@7}r5]Cw-w'TO ?zc|VN6a}hk1Niv}-'}b*^&hCz3l@o;蓌I <{^evkJ'˗^SYsԯ/v3{oIߢ}%r>>ۃ>JS{x>:?q,& <̓+@I&k ,Pƣ$@AT Q>;.< B|8L+[Ӛ:B.T3ԮAB@;sBP(̴*MW8&7$B>|*;Ay2!C&5MQ4AIԙAܾ,LCEDň)D89 C֫DDTFb|{TDJ̎i($\7Ē4Itʚ$ \-I,93q*_GF$T O艦$ M@&4|jHbo !lLPGmGL . P07NZLн}JTMݤyM"s!uLbO$IQX#*=<ʂC8 b&Rn<E 5ёAe1/f2PD4mQN*7R+ G$VAϸtdZ_eW`;6yQPBfPUL勣of3hRy=Yfc-NdbD]j`.pcnFWS.eqe e^gv^Pqgf)^jvmi_Afeih}hc7ZvUi~ᐎxi8NAhky^fߺP>myJ`KO]ybV^/N몶jĎjOOnlԞln.%gNK=~jܮkM.h^^ {ٸmfvk!iݞRӞߢnuVVnnW>m&mvnlﶲ-ijjƆ$PiekTfn1U>Ng?&@S6{6ݶkFkv*)_dp ?^-\rM4foA&}qS?Umn!qۑ[`pv?_V4~"}͍CmڳX=gN#~~^s؀Yp rn3ο;Y Gnh?ڱ 4`a -,sFPtNr'N5sVGOc55ZP3r"'lWwWН0Su['g]o9ot^-1u 0Su:OlrRFgsVVutm'Xv/˱c(*8'wyuXoqZUr-/x{-Jw~wsN_uVWPt_rh_omx5y=rp9>v3?W^q1yEJt\A؈x뇇yvavwwCOksXX_^S7uwzzGUo;55x/_zZyol|*z/|~[V^k?Mǿ{yӷv|G}'{fvo^xw/,Oկx}p}dcO'}_}o~ qzRt(O~~ qw,h B.Lp'RaŌ7rEGBĈO$˖2gҬi&Μ:w'PD(PGPztygӍ1R uQsNMɳKCnk&ٳeA>ݹ6!XoS=k.޼zweC$(HԺn*.ìm,2ʸ![~b礘 jF!ɥ?n5زF]bM{L;wY*.:tk ݦtԝs;D/@0"s =m4~`v+zNv{ : 8C['S!lf߆%%W~+f b}8Yo.x#9[!Ir/r4㎏d(ƔL$b!1:IY%a9&vt- tXBE#zI&pap%OE%iU~Wʹ]ic:h MXaNؚMZߢ}BꗝM]y%By}&feVj+:jWSr" 5\p'Fܟ&IV^Ƭ{.g^aj^iSPK#+--[Vj;Svj*K[uu'7),ܺ60!|3ο /0ΚY2\/^6`b%̲TGDk5Xb2RTsݒ$Ug #\@=k7:ͦeNiNUU[+QKxj6{(~o|j=s2_lШt$MmzkQ~ wk9@zs{Z"{kZhVݽEӃ)_;y}YO&sW,mKQySxUd<r ZșDҬt3 <2S/!30D EW6Qw8, hh>e -W"(6Oo\L"6n()h"dz< hps`Fjqp# I1^4$&3'nX48 Ov(C(*b HMҲ $C@0$uP0GżsHI:|&4Dx%3-hz0]^tѩ?urz>\jӊnta,U8 k9'eR2%ߩP[G'(yOU.btзTRL$;]v&eU`YS8}&O]L)ڲ60Cӓ00+|?)B٩P3'@ys#IcZԱaSը겨ŨMzO lsd+`[I%[YR5 WRJ5 ,f9x( Fx:cBXBtm$+w (6 ]aZsvC-\ڸƄm RNu[M `F%DbK:ּq2'K\Vؽ/YB|%t[e66NZ/s{W8H]Rw"L&N>5yBK#ʸTKu@#|cqcL:TٛܭX>T^;[VWlR7艏werI?ÝK1?(^|/u̱c ,|L[KQ&kgJ:8r3_ǹeA9 fx9~srt^}ddzӶFLB#ˇ.5`Oꦐ"eCZ}Wo-*#i]6/vtYꚎ*y\i;QA!;}& *(ڡʪ-KG%n7! DޡYk̂ESwjl|_g <6.KM;࣒iplD>og.9ԘCdy3 sۘ˭\!wгnWneC)ޘ7ٗ!ZUԵ.t=ە>v}(p܄?ūwȨ=!ߒϤVϒץHVC~ʏ>krrA>sQW_}l]}ؒO?Ɔ\_D\&]Vx__)A`fFXLfP``9_AI` lm zف}G  `  O  U*6H֙r:N&z:RZm DYamԡ!aޠK }äF"xX$^Wb^rZ% Jb$F%U "*N.b*<+ z]X,&` "- ( #/Fc^aLo5a=2F1Fآ?m#5b7J:5*50F9 2~N:fٰ=7Xc_1: h *c#@ @^dO"HE:d0$EV<8cCJ$aJ*֚H$'ңH$DRN$O @\<:3dH& 9I.dO_w5;NN$)$Sz#?cS GV%m Un\%R2TGeZ$ՠ^\+%Y%aoh%WWKnXf?bMMjTj_f}P QD; Nj%R9VZR&[ &g&Itl@PDc M&^&=f%qNmf&i;f6i%rnqgqz^&s~GhvJo& ]grr>v't}fD;FMlWy*tާg{e|&'&(l5't6fUB m磰gL(.hM&&iv(s_Qn(ƨ݋Ψ(jZ(f֎)rS)&jё.>)*OF)V͔^n)Jv)ȗ)G)zƚ)bc)io!ũ)iόHg*&j(>*B.g^*ceLj~*)‹hJ*ªj**2*J".k&+>+F+V+Mfv#~k`++.+k-ƫrΫ++++ .l$,>,6F,V,Z,flLvz~Ȏk,ɞ,ɦ,˶l,Ƭ֬ެ<-l,-.-*->-:-NJ-^-Z-n-j-~z-؎--ٞ-ڮ-۾--ޭ---n ...*.>n:.NJ.^Z.nnj.~z......n.nhfҮ.Ony.>;n5#n>w/y:L/@Tn/dh&o'ZorF.ojtPަF/zon/00'070G0W0kg0w00 0 0 0 ˴I 0᪖ 0pƴ/*m 1_1&v>1s(qo1g! s1 1C1k113i1x1߱1111 r2!2"/22##"?$GL$O%7%g2U&wz2(g'2)W(2*)2+C*2,+2-,2.-2/.20/310321'33O3?B42O535gk37oQ5w38739?T93:3B3;@3<<3:׳=3>s83?w?6@_3A44BCB/t37C'3DGt1O4EE_t/gF2Gwt-4HDzHt+I2J{fhohi1K4l|ʯLӴO*Bh<4RfU/SyJT'5U$N:5QW5X{FVwP5Zw%OuZ]Qҵ^^ul_2`66aa6'b1c7v?6ddOvWe1fg6o6gs0ZgP \jjOj{6Eoꬒjj6oۘkvo6jTxvppk7s;q77 ?7ttO7 Wu0vg7o7wcw7xC0y77z#z7{0|7}}߷~o/7.'.8?F.W^8oovO.8/ᦸ.߾8בָֿ-8-9o/6O-GN9/_f-w9~9Ζ'mW5̶7m#5u@!,E22~n OQ ~ ~PP y m x n y m n n m m x n ~}} xy| }} || x ~x >?Iy x ȱ}~ }m | [GHS))5̨((4QBCM |s糴}ȱғCm..:#Q@KLW33?ҧe ?@J&7I>?:ưablU9@*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI2E8sɳϟ@ JѣH*MjPJJիXjʵW^JٳhӪ]˶۷Cݻx˷߿LÈ+^MKL˘3k.ϠCM镝O^ͺװI۸sR m N#+_μgQDAسk}% M߽gN# .:˟O}S@( 4 Q,_F(%9(D ($d (dQ,袋H/h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(La^ @. g Q oCLaO"G'O4Rs2EшKaub@QEl6Nx$6r1g$bq'I\|tE#O(H#99dO8=._D@w2F:h8$u,<&n')sRJUfѓ%x8e%M&I]K$@X2%,4E򤏈#8%2 4!`&M@i@(,8GW^rfXJB"ʸʙtkl'6ks&D\b%RS'I њTb#3Dž.-c}撒6$\fR;uxTi5%Gy`JUH}<70MM"jPDT=Qz䞅 < *ѩ8!dhTEZqͨUG~ 'Oˊ⤡LDFpטҪ, K4*<)${t< /yrmKZ̝H6%ZjYRC̮E ,KqW|Җ?b_24i14ަ]BҲ2l_tZ^s33Ĭz$4y [HH+ߑԔ Y~AЍZG5uW6vY9IN8BJt'_-.Z^<%j7zTL\c#䑣b ̀$*cpe-c9&ZdTwn抸/<%d]n~1,w29tb 1$W)I P.6pxr}L<.Y0]4#RZSt@b؜5"ؽ)2<>F4LH눐Xeitmpu!u$RO7S2H0'Wؠqt b,4Rq1|!~8Y p;AۨS^v S@"ooú%j8ɬrb-'J ) Qb ,Y8Ln^ QoE}%H?;V8:#H%lojʉ.KܷY s z0_񤣝jOɫOqg 8n^%~w1U l`6Wuj8St̑TrpcOy&qBSqL|DGWZp_/Hkx?}}/8?~P}VOs.u"i~#qp&b~&sD~ڥX4lM7X}g's,{/Ax&"uW1WhHn(C'/7y/|B|"xew}p}EK~ǂ/ t'|@h.~=G=}W 'xop52~'h] "Ag/7x=Dd[eXupWqWpȄ\IXx~y6`(z Vtkro-Txw٨?MÆyy|÷WL H5*V }$ҏI18@b¸mdRl"`Ҩ}) ґV(ѓ ʸ/X;F"Pg nK !$>Shh&y/w7'y]D  U$tYV)}$qq,0S/s׏Iw(eSX1PFp`cxHԖ2w:31ؔ?svty $O A8JY)鉰 KXZ%Y3y)5" qw:ؕ%Qi sb9'I1QrTIVYE!^)9_H91)0s7ihKYIԊIAYէvڹԘ!-٘wICJΨe6:zRzs)2Aɠ.wO*L6ء`$Zc7!]&q-F ɖC-AaQaz;JYiZ)!EzI48Ned ǔUazZ\"AY w ¤MevGEGdti\ɦWAiQxUqWy a*nt*'PCqQ!5wYmVBezzq >nњXFfr*'AY} :ZvkZXn*zXq=MɜWAimXu[ĩ!!]_ZDZQԪ᪰:ű:Z**IsqD+<It S٫&JGڳb"% p銶8у@@Z >Z O "HKt D70 }zZqQKdBZߊfK [l+qE[DJT.;8pj ɵp[ +)jpahZk?au[ʷI _';ز VzٗY eqQcl 3!07&hAJuwy\<稢+[x'10wЋRjX˝;.qB\;:Q^I K^kZ<+[c%l ]"[nlʟj%KmX2(!\v+sk~̼]@f\"|%O&ѾPʼmaKTWdܻ \$|V 1||o,j,pA  D:pG %R,1așKx!@ӵÝշl|'L;i03;JlIӼJmɷɑLQfR-Ge]0 ,\{;ѿ] #˭lV 2Pbihm/Ր-FU9-|!^ߌeG=_K9Z1vRK|1Z،p,ς,Lj=ČJtҦm=`|Mո+f^1҅M $<1-mhx1^W8a\ 1ԩ}ѭ0ԬPk}ّ ݒTxڍ Q_ =& ߕ"4}ہc->!.'fM+׌  ֞y!E] ,N'>Z[o)*ߟ}*AȍfC. ŗU+z}Ӝ<ր}j䬕z"rulݹ$x,_!mfnf]yub>[i  E޺ǸSNLڐΟxz@֪}t:fn p1Zݭ}/ qA}ھiΐ ];ad_%@fy!fNw^蒮 Oò᦯1._84<ϭ[naBn'/KӍd*Qۣߟ!r_m}k\B}Z홇1D. ?.~m!!M\1G%>4~"OOm__gt_|ļAMO?>q^HM[&_>~0FsdA@DPB>"8QF=~`@LA\\P%* PS΄ lZSPE"\@RљE YeS-bI nVXe͞EV*"اUl8GkL0Q (EX^iueA gPRZj֭]Kڣ gM*lus۠LWpw17+􆾺nr=i۸j]x͟OibfZzMʖ>L( ܴo(6ҏ?$ 6*:0C 7P"5.>:-a-{p\o` EA|KDգΊ ͒`DŽܱI',#r0Gܳ(%㠯ÚBǓpP@(-/ LK!24PA) ,+|$4,H2龡"I;A=W "lTXN2=U"BV[3sWP]JьYgz%_?Bva*%Cυ>tB~VVw Ryz'J;~}؍~ʀ\z<7u ,832o$ [`5?D}s6 AFz•mHԇ"9YЇ?J;| ,4I0&!ą$_wb }+,u8$iD$JzA)p-̡3(|d\hliz$RGBPcxh ڮqh ?ؑm:I_9=ZuTyҔ0D@q \0%!đ]@q#džmN-3tG!)@dyP'QG!JҊW"k&ώ\f:$Fa#Ѧ6pHK ;QԼ=ّv$TgBW+U#jD'HZi$A#9O2"t8@7P~ E)r̋"f]<#}ym"MFMR%'G }t%LiR9+NcƘtS QK="1" fIQ%T$JE+Vjӡru@fYR/SN[{(Զ7Z"}+tni'+irÐcP:xkt*oA:~rDz<^NV.k󛟅>y_xgVAzݢ}<$ce6X//tw#*8m,Bs!ѡ {{~q.>#v=mEʻg3-?|}]T;xzcu`Aղq5^/~G3g?$ǪG~dr+퓯V0nqnlg^f>ޡ'RzhqܰhKºCOVWao;<`5QKpSLڂS>S7k:];k7S߸<=Ȥm3Pkq9jS`I7Bp :C="<41<:@.T'z&/k˓ ,㿑r@735$@:A:R?18˾ػ,;C2>c9Al DOiC&κ>ۃ>VL+&9D<# 6bOEԪB2z&T̒ĝƃhŻ[q$ BQL>xd p=*Iò0>K{E$ Ch̼v>ǼEs(< wt#K)ˋy<|>uB/X`]$FɄ<(J&\bTC>lIHGĒ"Dl̈M I. ´2&\zF{ǗFրkD,qDC0J8 ʲ,#nI4TL'PJHXJ,,HU(ǭC\<\K|3äK;m${DXf*IT H@@@L4LƄ~.C J2:"˻, G;HӨ͈\ A {DCTMՔ[2ȴLKCdȳT 5f9Àl||,[[ÔP M@OܣL9|BdGGȐETtP5K0Mc{ P aJG$A;\ b5D$ .ڴMSuGh EE hϾ\%I $eO"K |D9DIR|{ ;g:G3-K(PBê¸LLQm ȃ6];gbRBMP6cKZєRIM*E ̀I)44 Q"ROEpN5^4-ҨԩSx Q}`ի gV\UQú%"2ʹPG- nQרY< :TabVj%@X4VҴWb3ES񬱊%vX!ČN-+M ?<:Vp}rR!3a(Yڕ@ .GX=P}(5UH";AM{J4}ψU5݀0K2`5 >9}Gz[s5tUן%L5 8ѥe[ à5=R8 cTO=EZx9 hمX e; E.<"Ӽ\-\X-u[Յt_*m܈@<)[q]} %@Y3@BZ-_S1cȽG};m'Sh5#V; "~[) ؇4q==pܠ-OE E7q ~`ސ]8w#=D7*L%/;=UWlad%p̮M@ 0٥a_ '3s  ⼵$S]\A!=5 ^M]+&x:[4 uHGUUdwH;Ĺq\ؑZxJ3 <ҔՒDJ,c W֡&/}`F m5P=;rW6<VYQ N.ab(1e Vcff)Fff86?ND ý\OyH-A,qV8e_g3]ɀ Nf2]^1g&-H%i䨅3i;g8ؔXnf"bG^Ȁ;am!-N$4 dQ(t4Dj=dpiqӊeF#GN6gJ^kM`^AƜjd o&Jb5`Zb'TA-^k1b.FSV31hYcfAliP-dU$N+.W?36 vv:ɞՑ$yE9PzBifE.{>2V.ExN"llmlV>Hn N6w^L^n.—V9ho"΋N 搬]˾B^86CV0k~.0+nmja` ivojB|Gp'(P'-kn +jq|hpl铫BPn3V(6V7>9pQk"/r$m8P"( rp Uism://??rwds?^3.*5_s4XcD9+jisS 1'3o .3מ:hJ?8K'0nN8wqSFq~ sX_qr~yqt*^&^OSt?gvWWrqז$/it uclꅍ$9Yo2IqgZ_K.:j}{`_ ن&s>}rV'1}1svՠitei;M'Ax cG޹CYC-հLjw>ŘuO7Rojl4ayo [qGwfA|/&@! JuPzRz0 +ߒr/v07м(i7_%nn?A{Yo;F|c]toV=?햫6Gl&~w{j [gVO0\V d H8 P0 OA?H[' iG6֘\!ԏ ՅOq 0 ` 2l!Ĉ'R  T葢(hdV@%̘2gҬi&Μ:wS%K.dDQ(ҤJL  hT)™r]b3$i`D&5Ju4@˺ j0e_7`AaN` @EYpX AY/ba_ tqG"-[T &EF6Y,Zv"q%9q32&*J FH袑Bg `*u"@ **b @[HrŪQ))Y\SZkٮuYl2P]gXZih" +z)@9nW;gi;/躝AJ/1n?80f :0}."|k1ǒ1.~/@iWȃ2O!,F >22BCM$ mCKLW,,8((4CDN..:33?abl @x@Ç PA X܈QƊ PI$\J- s&͔6OeM;e ͖TAN&-իXjʵׯ`ÊKٳhӪ=8b \v+7^Uv*xp"݉-d0.ϚcM  MfDA K.` V 6h !,q22BCM$ KLW,,8((4CDN..:33?abl@\8Pƒ >$p+ 8" z"A2eI'rF'# l%RhC@ D# 0 PU[(! Qn% a80a-X   @B^\@0 !,r22$BCM KLW,,8((4CDN..:33?abl@ ?IғC؞wLP a!CC mmC&x!@@-CC- mĩmmm!I٠oqqBBy3|9tt{8BBx3ĞCءorr!,!#! rr!ZןlCmCןm؞j؟mءqCCqqssH*\ȰÇ#JHŋ3jȱǏ Iɓ(S\ɲK\8PpEɳϟ@ >TENPJJU6,έ JٳhӦ `kW -@ڻxkuBش+X+^[`6Le`2u*ϠCSK&΢S^ͺְc۵Mͻ器Gw#_μ9^ΣKN:سOaӣ˟/;>AϿ(ZhT `2JFhTv'm(HA0(4h8<@)DiHȐpܶ@IF)TViXfH.\=)dih[FbI)tixp矀*蠄Jq袌6(^TZN-C00v駠*c `T0 Px jci D0D.4':ƫm!E+Bб4PvC;.-k&,ue:X$eHCd+ψnLc& pR~pa*gC6BT .#(= qH˪qj(?c%8B 4".@/v0 }t#b<- MF#]0f"V u_cn]/=cBPfwsýutW}4dSm <c%Tu7 cҩHhq', ul`8-~omyN?.!Nv7Ҹ>Қ=.9sv8O={g}s~vo⛣9.]tL偺RԾ`h@F=e0nF ɍyTB4E$ GXBiP-DB {IB|:\F9B 9agSqHz<1ѕDehtkEAXf-|5 @#t>˻#B2cMGQ`O4\ qyGF1L_J.}YhEL}1zdGgqvx6q<^2"k*S 6;QvRkkJДd) YMrq@VHh4%3y({z3t}cى7zjv˟d4ߩBc[ӞgM: 密Y3A~2GLpsGw4:&۲9SyK6ui :gӥ3-2F\d/aV]HӇBM_D)F2Sfjv͐͜y49R(+Ҷ<[õV54]8H n{]+\e:ԢYXٴți5Y DfFۘ7ob LKJRaHh܈jdV;rIMG]vaRzZh׻ 74hV>RE3Q{QՆucefY5,g}ZfSXwt*8zT>[.ـT 3>wl';OBeFaEʳJ2j]E 5Cla$l#0.B|L$GZVilJl45<TH )Lw0Bpf:+2MBJF5*_v'MDSҘn3NyӞ QԽJ4VVհ Zָεw^MbNY;^Mj[ζ}fC^5MrNwp{뎷Mz~]}~ ONl\ 'N;&W/ .H\%_pqp!c58Ϲ=WˁNvPAPԕ-[ >q\Nv]cW7;W2)4X#ސC4 + 6(\7W*7Ak}\"HލM)$\FP Ow[BN a+{Ov˕\/~%z |벯Y~\T5}ЄT= +{7LUt=|g úiQ~!y}W@Ix>P~>{{"8Vz,z;Z /WywwGǂ.w*77~~:X׃v|)Q:"1w:{7{ 1{ׂQ40g.x~헅:ȃH}@dK(}gSX'W 'z~`'N8JoLop}wH1}ȀR~8GgX tPP0mX.8(xOO@.Xx K!w牳ȋBqP`8.;؍Նtmk;8xl𖎻`88}xk瘏[7wnhkȏI Y.ؐ6X)nɑh(r(y&,+ْ0"/4!3Y8 7< ;ٓ@?DCYHI6ɔN GRIQ9VUyZiY^]bmG113jyW`Ғk9zLq:t|w-h:—CQ٘r阔iB1'YIo|IؙaYiq@ᚰ9;!y y,*3-ÙFҜ3 QF9ҙɜʢyɝ܉㙞a F 4 @ٟ)9zə * ڠ:Y:ei)twٖxY&jv)n-~9 03+:';Ꟛѣ,y7iKA@VژX\^sbdZbyhjZ٦njpR9tvzKz|ڧD : aa R*%RHQ˲}a߽v] -ٍe{][f$NUNڅnޝ_ߡ.q,~إ.NåNn~>>>NnIݎn|e"^1h~6N0+{~rkЎ'YҚ^Ay$ҭF-<@ _ ꅾ'>v˧kĹ18:.~QBүzW^Q/` tn;?`O';c/a>d/q 6▒)["~ p@zYn*Jz>ȫ=/g-ks]ɓǘ>ǘp?'LjLKY#ߓ._3q̞ޟ t}䲯xg_n*O*k:*п^ua1s_?Q@ DPB >QD-^ĘQF=~Q`H%MDRJ-]8L5męSN2yTPEm4TRMDTTU^-V]~EXe͞{VZmuW\'śWޅw_ Jbƍ*vY䕐)_ƜfΝ=_Yh r8 F&[v\ \P ž\8Pw͝-~|`$H<Ǟ,3^U^}M n|^|YW5x/@yBo@ܨ@d0"0$B0C1԰C80@H41EPTXt1F`Fh1pԱGx1€H42ɺTIt2J3(Ē+2.4lK0TJL2L4\48M;6>M3ЩS:#HMAPCw{4"&eRP:S0M͸<%(O@Ke*SM9mV5Wpյ׆x5%b XdUv^u6WhuZjYZRնSnrq\r`UpE\wwuEvͥu^mMs*^}m_s7с~ۅdSretU+P|@όs&vPhgc5^ ZS^N蟧Na֢&椥[ۘluT{mv[FvqnUn[Do5|p 7Bpqt#@+r|=s}MRKW]<[uI@?ug҃9wdjߣ>>KMS\ꏟ׸ީ隃ߞ3|o\Lۿ}wLw~ܟK?8¬T@ ! *I1 I\A8H%$ Qhlz+  *?6p@XGD-͇¡Xc@x==Q=kD+c8b|8v0G92u,ݑcȠ ?1!H82qP"!iIN2Mf$B)Q~)âJЬ5hdlrވ1^o)-q1-)` sqOtyndflRQ3;Ӵfmr7'Nq:!9Nu2T;Yy3=}gfρ<=ZυγԌPJUh]ŌfyYѽ|4R/$iIєƢQfKiOicΝi9*Ρ~)!,S,,22>?I# GHS$BCM&&2))5곴++700?I #GHS&&2))5$곴ɴ++700M곴CDNɴBCE..:B"((4waȺBC=00<Ȫa[\fɛ@A8Ȑ458AX{P."07.5p]€PX0!έ;crC^Ƽagr?4輠C[znfͭ],י_-@޾!,z122BCM$ ,,8((4KLWwrmwCDN..:L33?abl@@(`,l(aD cÍ x$ؑɕ,@ i k8aΝЉ`DCa"0Pk al@Yd% ;7<@C *J( O*x1o}!,w)22BCM$  KLW,,8*>M((4CDN..:33?ɹw =abl 4@ 8Ȱ`6D V @CF FRĆ%MNL " YnӠ̖$i0LyG<` p*e:@V$@ ^j $bPp#tmό~ i/}nT]67!*,H);22BCM$}w KLW,,8((4㘆CDN..:33?ablH ,`@Ç2 EP<8ŏ &`Q( ipS(PcA/cHfO9w4hS РB+(Ҥ2)ԄRV¬>A5 `BY,J5p RT&7Zs < -(xY׽F1PpatdF ,F` AJpAC!,7!22BCM[W\UYTXV$SQ]Pdq  KLWokmih,,8pwjq=w  ,rOqcֳCDN_ue©s..:2~Z2}/\~33?At[,B*;abl+BH)r\p$H(!<jdaŃ C0B R\I#ȜIS戗 5ɳN 8P@Q%@ӧM1(5bիXZp`~hӪE lpʭP$Dp Lf $8 (^B$Ckȋ 5"hެ^%J͐Ƈ2( @`rق nMkֳ}@eyK"78buPa4Gh+=!ߏE;y{n<9:8с=uXi$ dЃ}dA\J@GZ@!, HT22bfDl)fdށЈ_|Pef쎱Pn;q\SY~etxKaWԆa`kmzM}cŭtitu8y| pfjR\ZF暑 }_`RAtOlQ_*l=rkyhlXĴevLH*C "4q@ŋf #B`C3\y0 !@"˟,5|x1F€HXaI2@bhҫ 8AW2n\K@V =xe,YNWXWn0^TD ,`G \!CQ<,o&05dUEHN,( L> {'C$ޝ Sa (ٹs32pAB&E!o5uū~}P_F)90J4@, (HS\r  ޏ˅'ɏAYjpXI& q2T0<*++5HKz P!+ / +::\ o. ~4%A ҫXjʵׯ`ÊX)h>-PطpʝKݻx)jK?mLÈ+/߿/-L˘3[Vϝ!#lfHӨS^͚Πc>艛ָsͻױeFXZ3ȓ+_μy?V4 ickνwХӫ_>.tCˇO "AϿ'8UL8e߂ 6 pR%XvsR Gum},YS("3a<` MDhP9L6$P:"BHXf%GQ4%Ide| f.vAxasj矀})衈&[[s*裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧M.nOI~ c  (!_@J709;HJ": S0zL:TZVZN0PڢRz^`ٙ (ڥbj>J c'l:tZ&*vڧ~)ʠKɣ| ʞxz0z*Pՠz:H:9JШ Zʪ` Z@}p } Kԧ Pr` n0:n[:JʫHY `}PԀ̪@ͪӠگkj j:亰 K:0*j*[j;:z. {( +0 ;j#뱱[:9 &B;0J cy̪گuY˱N ƚAKwf{hjl۶npr;t[pn{4J}}n[PHY J۸2k%;d{d;+b;a{ {[{x[}KKp+ʻK[E`{kHٛܛJK[MpN 뾋R0KkRp{Xпh0\z[}i$K"ܺ+&¼¹}PƋ˼6 8LKFpثHн k۾ F{Th ^eY}KI}jjܞL< ¥+©K«{&+02L4\6ܼ9;\> Aܽ߫ElGIM R Sk,Z\\c`g)B#oqsL| {~,\̻\ȿ{ȉȍ +B\ɗɚĝɟLm![]/śb>5fޠgI N 9>~驾ꮎ>.yښv ۱-suw.}-#х>!-KʪΓݕ~7/L k>D~ZE < P /_S0_o >NnGɾɃν<Y푞Nehk. P Y ZOVa=M"Fϼ(*,P- P*N9^֜+2>d> ީJLQA4T_][E bOܹni/loҼu-+^~}O֞/ʇ[/>_ŘQ?o?On/ҽ濞j/³Ե%?y!N@C 4HDG>F0͝;]~խ_Ǟݽs^<}̟Gܿ' BCp"EI0*ш >.p> OZ)›& G=tREO?5TQG%u뮼6%lGY G[2ʊ<('X2YްJK.Kn0L3ֺ6u7lpσϡ>H =CSZ%FHtMS4NKE8afNQU[YgVquH^{XclXb7dM٤{/6-3l;oq%w>s /݈c7@-PM{crT}A҂8ӯ:aF;mߊ UWcG4xsPN4aMM䔩dJ7hjq>S4{ghN:u ]@Pj՗~ .ltmw!NuFVm|GVnxo;d/mp¡zmhf+<;̹<Π;s~#P=Dl q-f˒w`%6n+^'uTԚ全e>O-b‹[Ō\*n ș9S*Y]$9|:"j \؄6|3,gMGtojgR_ )"~ըG=,4V=(/EQ4Xl8rʜYnQlT#Jꭓz ڴ7o|=Pꔧ'H{޳HElb N<ͪ*cVZG;. 0Ze5+?Кֵ~ouO%Җ*l";ſ֊?-XP15XVυ{F[nvl׻wŋW5wћ^{g̜isԮjmy~Ҕg8Zm+'kzSWŝ)KߡudnE,]ZgU슬/qev5t~_Wl U:L48 -]K󢗅߉ahx@>wd,k)-6sռf6'S7Ʊw6r?ӀaryHI&GLYW*W٧WNn~җ>tǜ6͝uEm79r?T糎yl>N2n]JhrB8iC{5B<9%%J{φ,Lˀrz*6K3#msPUZ~k:xu`^KN6_hc^v8h+tl/_0[1 5}zMF[^]܃t q6?z$n;3|䵆u^)J]lc;BqbgJwn]7mϮ{+ҝvO/ͫ&oō;8ޏ7Cc+p)tE,\2/;Eov;xs@}Uf:s}n{M?|yD|3?ƇsW׿~h gB2q<^깥myI\Gҫ. b<@׋ý= 狾 ,k l> @>A>[K;?BH?a?s?@Cab{Ke\g|Fh)F",mHKFXFDql@r,GQ t@x@ tTu$>y{D|}~GC;A:AZSHbA)dTʨlƓFE?FqjĘƎ IIP<;G=@| ɚTz4Aï7IFʀB(8JTȥ 7HfFLcDJLH |4lpDK3ɵt˺>M $Ad6K~\>(L,HL̤\ȥtL LTʴ\<*Д$<*MD(TՔtMTdɨMI6M NNOD9:Sb]b >'()*>R=be.(]\#㯡3dHc^6N{c[m9e6b;c]m<>Y?WpWW&d,{Qb^_e2bamdevPd]PQ&e >ScHeU&VSXeYZb[NDewea2z>K>y~}~hfjekfz=eu7o^epqY_5[ufgN.x~ga b琶dd>1LV^^޶[i ~ii/ d&b=ӃfSofh~eue.dh茦V^_djdJȃk 0FNv뷆k΍|뺶뻾k l&.Vfl kȖɞlg:i(eFjWs>u꧆Ԩ>F1.VVkk66lnnǦlf1llmvZNgvhm`>.Immmpn&p>0nF|PnfopnplnponpknQއjp(ofeg_moxמjwoA(qO^_ vp:lGY5.rCۣVfq>dDnZ@885;_r'"@rW%?pr (l@A'>CDWnF_GȞrtKt,OYM~tOrPcR/F4Ws*hrWuIzuWYZu\r@_7rCbgrFGerIJ+qjkv07m(&unjFq/v8HMwZ9owwsxw\]ww}/w nd/xt.xv_x ևׇvxwrp/&sx&xsx77Gy[W\g{u}'v?WvUiK7fj[zlОҮf֫άuނLJ|zuz8/_?[.g{Oz,̈tz`}F|U|wGʇS5|'Mxy?뗇y`kWtGvԇtՇW"~{;{Jrzݟ(h 2\C-'Re ƌp(Ȑ"Gr$ʔ(?lR 2gҬi&Μ:w'РB-j(Ҥ?׮\hr)Q@pIRbǒ%K髿jײe{v$%>rҭ[HJ/ސ.l )ak1dȊ]Qf2̙'S3С'{u$4\xi5fӞ}w}7v'^8r䆖3oQ^vAsǓ'?A 3"cL-ב&U?W0)5 x *L9TTYV\(XYfY[vș]!_%b)Yd-șf1șh5HK٧kcm[oE\p)\r9tQNg]vu@^y]p@PeyfEg_Jq^8Lj0'}'SQMUUYm՝`ihXz8iZ x\$^()a,8jc0xe4ڸg8㎧#Iې+)Iܓ>)%֑SvWn>x%6&DlFpҜtd 骻.:6 )Rꡥ)&z ꢩʨ*6J;cފ+n٫ 1JI%.ϚdZ&i+ݦFniYnKy3A =P*a2zn־~#f%f 7,*ijV Ŷe1ow\ \uȚcr(,\<;K9L4kyFG(~K 饛~:ꜥ:_:κ쳧^{^HZkmM$ܺ=u}꽷͂x絼P0>6V99?Pϛ<5?(pCMڌ%OyCjޑ'Hcԫ=qOpsY4>m/#+7&gb(~H ro>!- d<"`-xA)ePTA0:TBƝq*\a].nT AW =#0m\PD1щOx[_7Qx_ O pr'LjK"*~qSG5KݑY"fygs5m,u>d9ЃB#]Kw/ !3Wg?.:d.ڔ]pwOn. }?70p>R; $P[Y`^Ġ _~"(¡)V2 klLLb ^3jZ%Rؑfa ,"!ғ$;b. .f}/ꝵ"V#>2f% 3 E5[6[BB6Z7z#8&&^,,:s;9dJ=c0c!c@ d3NBRŎO$UNP"PQNQURrizAGz$d-꜓dII2J$Kޣ>cd$J"%nNAf7ETaԝT]^ TkLe,Ɩ= &a&-#phe"cWbWXcY2#@2$\~&^^iڥ#h`G&lb&bccz臺IqqN\M('s'(H(n)֨w('NyZ(g0iL*"r˒#MNɊROe^ jSRN&բ.գ6UFzklhyy)i C iǝG6)@MPrjn*+gr,+6:+gg^+fkr;t~++gr3+8j^*ފ.h).W)j)(ih*6H~S[^+n,*~FJkjj+ʆ븢ˢ̾k\Zj=ܫwgxr̾~j+YK,jFji0,~>gFHRnj,~-x,Ȏ-ȪSɞ@ʮ۾C˾@ά>C׼+.xkUJ"*-6[fcúfRd-rׂƊ-~ٞ- ښl۾ܺlޭ--m¢j*..V*.1b:iB><@.*ƁN/N)Ajv.~.&WؖRWڮ.WƮ++n.n!i /:"o?1/:-HF^rf^0Nt+o.6ob+./. )/>QF^@a:o+"2o6N. IpSp[b0ovp~ n0~ 0~ np/#K p`#)3&AqJanO2L,]sWlqv011\1˦01N/0'#qp r:2Q!"7Boi82^_%R4gh'p)*p筪-q--G./B/2b 31332/jT3[o4G445[rt65g&sjsz3 3 l1҃H:i;Ss<3)!r"+t@ǁ3C#Vs&csJtSZ ctjt sz4 44ItJ2KKLWMMN#s2r4PLЪ$u5#5*52:B5J5R#buV4WwW5X3Zg6Lg6:5[[s?O3c^K3_o_-``O+aa-bb-6cVo:{5/.e1gkw$wg:<:!5\563v6%׾66Ɏq)_kmmmnntooGpSvZq0sr'gCwtrhv?i4wOww.xsxo(r yw+060:.,6pr}wew~'~Y3st/N42vP/6>4Dk,ylmz,l{,!󈓸sdƳ<5Y틇ys 3OW|x#]g6jDSyTTyU9Q*f$T/h=,:7z=tqry{~8txN8uOM(g^yQ+qr #:kqp/gzM'{:#3v;i48gf2:a:뺖o:{f{v:W/;73yh"֥Vr[y6︓X{y'sw';ʻv;wt;R)\ʧʯ<˯|)ȉW9H#:;C|ģy['>s=nzw·u|}L=;}i=2}ߧ( %#+ee;`9H*t>wB3zl{=#گ=#p~{o:N۽}3uj:p???gǿ[gp?s@(8`\%THi[C!BDڪUeԸ#N)9Q<'Sr^K/aΣ7f͚pԹg"?":"G]iSE::Wfժ5]Wԅ;V;gѦmm[xoƅIa#񒌳o_wCaÇ bǏ!GxQyR7zu֡č{w߿gdmW%dLiI*@JP\J +0LKó4iv H>KŽL<1/(;c1,qQyGH3 5Xs 6hsQޘdR<㠄R<稤RR4ItmO>)@-7B =DeTw}v$WRL/|3T2fԁ .IEuUt5XiV\ԕ*}6KacË!eURJqY&AyZMl_NoOq"\A%T]kxޥQ7+-q1Z뭹>TdW5b'EV/v.cc> I."U^KyiŖNoy'y67 .hwWiv:/7QO]wTX"[E>۷ՖR1Ec3oYv8 fT' t@#yrF̙]SZطp f~D%.k [dW6ƀ5;`x7ATЂ`)4t0pϳViȄ9AP={.!ъV>"͆mapH$*S0Ȱؑ bSM,2'HF 1j7PuMxG e(9"BFuS+Q(r7Mp#L 2Ll))t&uGMmϦ䔟<~*Р쓇QädF<TXIuUzY\@/~1a#V *+eњZƄ3YMo= wm׽U `;XMa&5qXm6GsՋuUc_XX5VeՕgj\2zdlU[5fP ުGnB #No¾lPVڤ+˺n[&ѻOoL;^腐zwM|Z_uLqcH%pc"c 9B&|'Y;fr74JU򕱌6!ycOO1jbVdϙΡFg=+ 1{? e6}X0% K+ַbòT6Qfh|[.33s:Ϛ XA:S}l:6IH:Ҕ5NӌE>3P:3V ;SUoy:pװo}oRvKl_[W^xڷnY)fupɍ_ lx%7yi\78w+ϵQ!õ^O|'6(-7kS7z?ܓzKwKh8|,_Hl1i9:9308fn?1q0wtnw{Gb 2<,(Nt^3+#XC6xʶ $pǏ.|,pv&ocj6+j*X]a0epimq0upy}P+\D P"-3pyOo2HŐP/>! p ٰ 0p0p d  ]N pb 2!ۏ  -C1 GMQ1UqSpu)+;5DpA)IE~1q1q^qqehml{ ,p3O3 1Q! 2 r 2!r!!!!2"%R!`1Q#QK9qUҚ1!q`2&er&i&m&q2'ur'y'}'2('{"36#o#ARE IRr%ҒZ ata,ɲ,,2-r-ٲ-2r.-R.2/r/rfȱ )#?2*p*-*҆2Z2+!Ar3=3A34Es4I4M3a C.?5A35 N6E cB6m7}7{Si#)S1 P1:H398;K5a74A !45; !6˳=>IS8QR)ҒS33$:%O:!:R;!tu43pB-B14C5tC9C=Ba4!.ϳ0!.BG.D= Eр5eEqF.F,ƠE/T6m4.5FaCIIsa8?g?g0q@@ @.*4ڠLL#tM֞n$ nNN4OtOON@aNkdPQ_rSRo!<P7NQ`2U LU=O]Ua5VqAJJ3@OK KK1O}XTMtYF3o5ZuZZZ5[U6=@<.u XZqUr[ϕ[=@4A5WDU^5ZuQK^I^__h$T0q0%ay|KjXU YUY5cM5ilDvdIdMdQ6eUveE.G[eTQvD!fie]VfecvgHVgff{eviima`y8W`vuaaa!|$)b-L1Vc͖`4famٶmm6nvnvmm P6.PaoaJmpgn=amTuN5Urn5ws9sgE66W0WWkXtlAvC%meawyw}w7xwxwww[{DvWR EeAyx[xw 7W5t{||tnt-!utuu5P`*eWIvk:qGEww 8xW}- }/ ~R~ki~MĖAG4s`MQ8UxY]؄eximq8aaBW }ݗтI7x ?8F450Mz>3%XKcW x3aA8x9y a\UXaPݧc RTCUTydY=}g%:ay)Y E#fp3]NQ>a>u~Mg~MUp牾>0|!4n^^鯓>뵞ڧ/O~ɞMN˾ݾURK^I>C ?M-P/A?5kVC?UFKŵWg?[8?dym/m{݈??n>?ج=|?տ?B_ǿ‘ <0W :|1ĉ+Z1ƍ;z|ƃȑ$K<2ʕ,[| 3̙4kڼ3'LbĀ+-Z\:EJT(P<>:}$ԩTZzё\z 6ر\blۺ} 7.J~L+7޽r 3 >8qb> %jRv+?j9W :4X)~*լ[^ ٲ?*]ݼYǦ F?<7 :ѤK⾊=>,i + ;>C??4>~ïq H``J9]dQfSEHaSy^g$}{"#Wb c2HӂA6dYф<EjH$hwbJBKMBNHaJȤPJ$ HcbIr6>&dlE)W.K虧ޙ"$'je> ish:#iIgeI(*}.nMPdej l`kz:.z$FʴNY)"#L3jx051A.:J0*nMENd"^3u{%ʮR䨰 /&^FosF{ѽzd;t5hÿ撋ZnU.[dm4RqD!, 2Es.6pROX B^wq؂p ŚhKos QHH 0 Owd3;Ak Crwk.xN,QTz,=f_s]cm#4m̈́} .pγ8n51LxqF#|,柏Hcz]?GSho]w5@ l MqD"ul `7=p`҇6l}ƒf~9? ֡gR)'r-(Jȴt&Z0N6aɈHtmpd #Plh:;ܙP5rC40LeY<-h! IE#bwk%uE!V~2d$-)2r2:龶6ʲ!ogI:Vhhd8>n=ܖ[b\2gAGB^ZRK;FbPl&Dhlìve ='RK[ YT@e @ zЄfsEyC:U$=dJPFT9ɵLz҃B.Ӝ&{!G=Q+B X(uLU,Xj3MSשӬj5&˳_ /g>5]|D!FVD_K*DhR7jej+[Teב`*KNlnOӅ(:Kct!d2oV(EH;{s}F\׿ma{Z.VWU*0p*so|ީ=3zט/iֶEDi=[ת fbf~ ˎ)s~B}{3-Tgp!rnGd$ZѫUiɮ2jD$*yEw(o1氞W1,9n%%5|JKzY$֞#4$!938A|8Fbb6+MB$<D/Sxy:.GP@]ik 19Bx+I}\]1t^[ . >]<^|>>,).+n8.:<N/?Պ۰[ 8X CNcGWrN3Eor{~:}:"[N)h^艎SN!N5NU[~K~1d/nꃉNn᱾O ޚR붾J®%o'k׎پ&neTwANn-ixN瑝A.cd~Q /OoqntZxcuGu\b!/#O"/A.R +/F"3O5o79;=?AOx^WG4.OQ/SOUoWY[]W? 眍esJE.moq/sOurb{}x/o{B◍"99Ncf?UhE`Õo߁G83-00 _/+& /GSB=,m(g||!zW#A!O.O[_3eç 8o+m/n6<Јq Ɠ` } ¤ͱ&̠A4 Cӣy:8;ȝlQdH9;-0;53Nd>@tPB 54JjjL[*RL3tSN;C5 F" TUT ոն`#ZsRSorU\mpVO5XNoٓ%tY٢<8߮KRyML(J9ȵ&́cIQ˓xf%^gh5Zǩӝ qj!-wy^~{lEsHKY{nn[.mkfpْFdn- u*rg=u''TO>%h+UOI?P"=-zaSq4'* T#%iIMzRT+eiK]RT&'vMT$iO}SThQ:OєC@TFUSjU[YѣfUKj)iU8c%kYzVR[ek[}5$bk]zW5kuk_:(.tka {X&zelcEϴSw%b-{YfV|ulg=ۓrԮliM{Zʋemkgڥ֕mmm{պVl*V%]s[zַy nq\Fɥ_;XDWD[]nw{^eQ;WI^󽲍o};lh&p |`'X fp~P_ 7v= ld#&qM|bX+fCOX3qO,Q_fX}pZa Q r|d$'YKfr uXSrIXk1Zd0{ s|f4Ykfs̍09Yss,oYCYf@i̻ t }hD'Zыft 8nt-}i5yϛh@=؅.L}jTZիfu]jW" m}k\ѽ4}Q&QqE}lAc4fvYu\{ջ JO&7H1 #ЌVt $t |[7~<xn[j 7Y]rsRBV!,5%es)~ zW/")8/pc}8đ͍ gƶ%!R;~Ad(me1zVPg{3km.jnu\ܦ8gk-xhD rGPn $a]7:VDw-W4qW6~E*/XOxԇUE|̍YB}m{c(p{~DyWq|,-[ {XX @ @ @ mXX@A Ę :s(¢;@4V0 B!B",B#C?C@CS :T:XbC7LDDB},r9LP&f'ODi+E,èHLDW|EX ~':(2<3E^DERUDk0b,Fc<{0) kF0]Ei _|*` Fl]D(TBlGrndHqzHGGH@HC]X9rPb, ID$3a XXIxI?ə J@IԺ0Rf:QI,G0#ʢ<{Yh tɧH K0ʪ\ʝ$lK|KKKKlKKK˿d8LL\LlL|LȌLɜLʬ̽d5XL̲DHTʧhʖ~JOlM|M،MٜMlMGͱyMMMH(DM\NlN|NNGNNDAfZɦBqr-׎m YY4-g%zEY;IԘ}W&-؝=Uب]Xy}"+BC5ZڣԤXئUWZBZ٫=3235E]s%WtuZm۵MXu۷-1$4xM\5\=ٕX& \}۞51;\UIVb@\ Yu*k]* ]lݟԭԭ]]]]]}I& ]]U]^m}M@^ !,C,h22#>?IO 7t;sNW)$%bX &&2 *n M %U7@B\ # 75?7g0#Uswa>?:[\f6716?I @*\ȰÇ#JHŋ3j1a:Iɓ(S\y XʜI͛85paA@ J ӨӧPJؔ өXjU\ÊK"إg˪]vYiʝKgZuݛ2.^ È[-UŐ#m|˘tl8Z9W. G^zhְc,۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjC pBꪀ $묯z++ [jjj,pF WL  Pj LPª"P?ICC-,ғhғGHSm C&&2Ҩ𴑒ғmmm))5곴#++7 ,ғCCmCCm00 `y/l0" :^Щ#'*˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_~|$x}ӫ+vܱtc^y0 '<ۻ]"s {4 t!`B`y* `䉀9p\$TH0z9 .XP PA!, /22$,-M>?I# GHS))567B&&2( ++7aB %%1?@J01;Ή @8PÇ6Hĉ!^$F~2H% D2DblL4Wleȓ4 JgP7& jϣJwB-tիXjʵׯ jجE@YiۮVۣq[WݖyN o K~0\B40A "ؼr .d 4j 4hP:( 2𐕃 "!,+0!22𹹹- C #3  ;x>?I 01; B  LE" . H@ȰÄ JhPaDZcō =Ȍ%MRJ-]sC8siဟ@PD*pA"m)TAm*UL0 @_ Hli*mYpl{ނ|;] ~ !w/8N &p[3e vE `cU`Aӄ) {`d@5<u@!,922U B >?IDGHS &&2))5#01;ꨩ++7󑒕00<12<[\fH`*Tx‡ :HqE+ظ19zT2dǁx,i2J*5{99>HMVar¸ļɾͿѿռڹ޷ H*\ȰÇ#JHŋ3jq CIɓ(S|Q˗0cʜIB-mɳϚ,eѣH ʴ)ӊbJ*SXjݺҩסKvR\Ӫ]vbЎeݻx߿~ Ka3^ܷ Ð#K#œ3k޼EC͹ =[4װM۶c y6EkN_<УCoNf؟[ΝpvO]菶XϾ=tOU֧߀Z`{&`C„VHa.hf!nh!I2 0x*.(^,x񈢏1ٝ$L.i$wHJ>]R9a顖MrYɤIlNpFhh*©g)~jh.G(hqnب)Y+b)v)jlª: +X+Jخ*]:j*fFԳ(HkmQ'd^-O܆$nӹܪJn[: R /L 'pl-,1 /;4 _ $ LP,L*2l%۬8=A0E}t$4N/4T US}uYC5]?aG=6e7}6i p-wn?8O'"c~5K[?"T'A_Sʓ/|A_ CUͣ7@P s_I Z46 >0=VPA C&,! ;X@D.|!bAe#4T opA560H:VyN Z:GֲZ)Rncc5\sδT% `+ +s Yu@Sh+`5Z(~Nz4Y@,򙖁"a?XXb Di)ZΒikZnDR;XnbM.rKʍq:ؔntk]U.wy[wmwkN7%/=/@ڷnyy7.{_G$p !`tF o/|jÙ}/L]HWs(f-o.3^1V3cC=!AEN񑑜%/PdMPr|e-S2,e1T6(6j^L8ss~f=n} gALJl6t|&F;ъϣ'Hғ4z0hMӎx@ iQԕ6uwP=UwGcjְvp}k][׳uu-kaS'Nm,n6sli/˶vqlm.7o}nuvn-nydžk}hi~1;'N[ϸ7{ GN򒛜jLWr5!-g8b|51uVCO1NtbuRu0rt9N5o-&?:L8 q`Gu43g'>+OX̝S'cD~{2ħa@ifG;Uy>كcJd2;` }mÌ/1d(NCρ.DP4?џFqOߜ??˜D8W,K r Hr8.hCTu FWS"8tOR'>auXu!Ղbj'z8vpurw޷7|.4hzW| !x7xg~yKxwEH.GWwSya߲Iy{jXL-{w( 00wHf-hx|y(sxu||ݗ8y7xX}g}a8xgHXh!w((HhèȌȁ(HhQ,PN0u[QAzVg v=FySXȍ;qwOFчP r~{'x-ywlȊhh-gRg}x(}7 tؐ;Ň|z$y O8xpx4igR~PK } Y X F||I}HRٖԚ  yǝ^ٓÉ=Aj(|y]XQԹ֗{qvdY(9xww@g)7Q2IO Jɟ '*)ʢ+0!, \'22U?ALU$DE$ $D@BLʄٙEFEABMښ)*7ڙEF@ALFIUl%&3mEFnӖF[^j01>?BMٙGDFؙؙEEFABLq#psosdzFHU+,9qEGEݕs#EEqFڙsn՗FؘؙGٙoFpF˖Eݑٙ>@KEۚɋԖFؙ+T@*\ȰÇ#JHŋ3N8PǏ CII;\ɲ˗0GT͛8s~ISϟ@SѣH>$ZTӧPu2mի"Rʵ׆Škٳh 2X˶ڴpFuKܻxu_{Leˆl ǐ'%H61hƀg9MӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*+YL2A+창Z&l+4F+Vd, ۆ+kj8Cn \k/3hA  ' 7log K ,[B #2#6(ġ8 6 @DH,Hl` -AHXg hH`D/6K1Bs )x 6 >߀Nv{\PHGE&T Wn?a t烗|n:9a E*n>{ B@z>\` Sh@qG/}hXg|k/ B%# /c_:8́cX'8 3'HA@CH77,[p|(L W h eA9r@u@ DhH!EN`%ZX̢dHAH2 'X6p  ;@>@8HBD$ vPd< !,F'!22>?I# #>@KGHS))5$3&&2dz++7 .M ?@J;t@*‡^x!Ň2f񠀏 ;IR$G(S4iс˗/YBL@M ΄ AH*EjP>mZիW\kWL?IiԇGGxxWھ!u g$#x!߸^GHSxGzxx5ؒ&&2))5᫨x!zw䗄G⦎uGxΘz{~3=U?ȫюgxWNҍ椖%5h++7ߴ:K~~:!{{ ^{yd5}?@J00<Ì͚aɩn[\fƕyH*\ȰÇ#JHŋ3jȱǏ Iɓ(S\ɲK$c"|I͛8sXϟ@ѣHX`PJJJ*ODjʵɫ Jٳ!b۷Ef ݻ(b߿^ ᾂ-≯;L٪ڰY+k|2EɜCny"ѨS{,-װ): gCky.A3_Zṣs~\e^νOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7d Ta4-5= l(rI/ߡE*ls <`g6-Dm4& L+FG-u"< Lb457D/&d l+} iMqO]Dm uk=7hm4y̓R}f H @A!J CE+n&д%`> X\4-z7 Җ7BCNfwKOlt 4JK\t tW.[~<ӨS 3$ qҰq$9  t85n3],h k &d/e-{k axB.fϲw71[v2#OYqGB!0.,gpďhL#p# K@Ih) xch0 @@PcabcwdnYcPZBU/TTTTTTTTTSRQPOLJIIIIIMOOMB7655555T552*!%$   %$237:;9A6 F7K=UKhj-u| ~1QĉŲѨڢڟءױ!H*\ȰÇ#JHŋ3jȱǏ CIdD0TĘ\ɲ˗0cʜIJ5s㆖@𱳨ѣH*]ʴӧ0 իXj:P*U`Aٳf ˶۷pʝJ&I$/ݿXlT&z+.xǐo,L˘V9|E2KѤwFogq@X ۸sͻą 񊆉M)ǯʦ=v*@O1Npǐ[4~v&K1w:o0?B~T{pT!a Ba2!x ^A؇_2w"D Fg8J$^Lfw%AƏ<אF&$kS=SQuD)B% A~&@`ҹe*fygxނ 0gbA T -Ǧxy~g)cy.Ju$b*jN6`]Uꪬ$qRUZI퐊,+Bka!m)Ԫ}zb)ϊ^(5ậ9| ~fkm"*CX6er~z*gY[YD*Pȩ0 G&LU -1(p:ᘰC}{D=eBԶ4'EN~HЃh3&S+; -njʢ"fE1S`:KMc<v~THBn$JLQf+M{ sH HdNzTbDR0@XtaOT-L٭LVr  ='x5LAO=^ʳ+r2RN1uӤ8ɐ$0(euCrI ̓l+ӝ$()y?"`=/J`PaN|P*J.Fxv&MQQH):3mԃV#H܈µ )>wJNL{E2 b*S:9% ST q;T84-B\xծ ;!:uӫY""VsIHE+Dz$*r]HWnYӣҼzD$kY?VVOU s2ƕ&e#ZX gâњ6|D|$dgb%ai$2lV&?Q . Nĥpk5}I[ZnDRKF,jU%=/K&+la{Vn8Hq廒V5-^ alDI69w`ֽ&a/K f/(x9񉝀P2 lj_mV#t:1wSPhqdA:rSM.~Y;7"2f%df'p`L-(Vqb<{N@`,!~YvB[% <:O:MPeyFXd2i5o4-Bt|NE%sJ Phƒ<__Pj_"B|(:'aelc? nfۜUֶ}r0cڝQ2Ho -]7qDm8o C ig#" ; 9C=0VX r;0yu9Y3q~5OZ[HW R ˜ N:q|#B:]D~#^X8eg52ݣ-qmLk$dK}=#;\w+'^rߙ MFL|K Vqeח;./_dW +>wG{:#u_u0}sů籧H }Z٧{aMy˧]k|a_8M_}4muMwwxZ"tGLb&57@wq\Wzl' j z3x+qXy53}$AbjlqYxugmH6oȇF[@gHSx KhlzT'ڶuŁ3=8fW,vItS{lq|Yj.qYT(o7Q\@cf~63QQl؈;#jxugŧm2{4чqAv3d5I{lWv~xȉ>P!q]hvx=w8h~h޸XW1x7~Cxs+H+Ǎ q~bGv vJ19,J[5Xo$*(g_H87gqLuQx8y)wMuiV!#I}2!Mi1yK8'k֏9ǁL>iZZup$}Ӌq1 pPH$wZatT (h.!ySpC#q %ȗ VQ~L@II~gxwM6> w؀)Lox\ٛLPIfh %YIѵLLsc9t7WV- yLѵ9hYԙ]3[aٟpa4L]IByd(-:Z1Wٝ١Nv}YXц6h*g uhH Aa`A@j\zey엚9Ih )*GuyyG`jO)E̩!Q]ȥ#yg:uZ^Ɍ$a2љd U 1 9&yKyrYY*hX)*RnH q[/vs H9OvǛګ0)7j絪kz qK&*&AӤnQ 8;5̪A^' I_uЊpAڭvcP,ʠ,gsiEJLA  }8vZ zH KzK`zJؠ{*Irqʱ:˜t1ըɩj;_64;G"QJ; s?:\ a"a&[ # LѲJqxKteHɫ`KƘcioNRѰMaoɓaA&qjg_iI++pQ{y%};nCBZJV嚋{˺S[+rAX ; aD`gD:n^{۹ur[#-j_ !ѶOۺƖ&1CK&˳+:[tǵk+{g),G!x+^b+9Fq? лW$ëa_ |I1QxN̯qk^B4](F\SjP"șq2˜[ZLFoe,%H)i`@`ylB~鯭;]+^k.A8uW.mpL\?n.Zr؆뺮kmUɹC>^ߎ z~mޭȞߜ5봎vރ~с62NM)\[\ Â(~v#cRxNͭ폮K.oឞ.^vr( aBOJHO69ΩlŽюnX 2;>I-dE6K7__E؋ T;ElckϏxoYHjU.ooRΦA0B گ n. ;- %66IC$%O*˹wGtpAD8dIlLJti?l\%ctk:pK*$L3Ϝ)G4ĊEn' ^5,U"N&+D4QEE95)O& ·LJ,E9;!J:<(1CⴡC!IV[oM:MquH#4:XMzu$ʔWh.`4&S6[mITָmHde)h#jՒZ>u-iEUKPT͈o8`>)ɝ/]caDbRs˘sbG&ykIfyx:ت>-!!_]6IgSiך&hV(^y@lBC}hW߃幤ۤ&l_y0ęecln{&5ֻiA'pt%7 nu'^c|3\Ͷ'޹,Z =tѻ{h)/&;uXꖜ TfcgI$=xIH2t}$7)Ð~Al^#Bs&=?|8'c^V@IelmGƱGwԻ)ORZT@Ezf, gWA qVSOT1NLHMV4`J8p'9YuÒlK M"$y)IWF̝'D@W"w0{O2CVgC|RB(ϊDΗE:֑VZbGMIB K]/A*vd$4?y+¾PCaŊxFIҕ@bH0zN %vn")JyS3wJl/,+Lpp+LB L"l_?99B# %IQޒ%df:M]|tɦa&҈g-.A'<7 Ӡwя\2Q붹MG09F%#BE:lpIg`5!( TtKdC=ԧғr嚩HYV,4NRiS iVj jy%rf3e CK&tRq< =$U>$[k^qb)7ISIn'FʧJ'2Ʀ$cղGf5Yvֳmh= Wz1L,-t )De<\`0Km֥," ̥Sse6׹υngIkZWVd˦֩dmң ڬ/®s\$o~9;] @Ak3$$1YmIL:*L C r:dXo`cC#92oU ]&(0i@ȁ_Rĸ ey9[n`Op5,YqM:soqٸ2WSX( ?6y*p'/gqm5!=TȦw;gd V hJWyE{𻘛;*pGqĨ:n<خ `ŷűGԵ.L*^UrInd o03 sջ+t{gEY,l[\Q>3+?=2= K #^$[b᛻l<ʢ@41l.A4A,A"4#D$T%d$0XB&hB$4)H,D—( @8?;lD9C ";>?C|B@ABBB%lZqJKasЋ8AETB; RDTT&tALEO1B/$D%i$ZYS ䷱H\t9PͺP =L@\Qz> 0(a\HݲU3&P%#RD m27=/> ?B_#A.䎴dkZUL.ۍhdG%^\<#^<$CTvnYEWbYZm_R ^`m`-K:1mf,U V^„4`af0]􀬨YF \ܭItXcg@Zzhy~ghÛ#0g%^ۀnd]nF8;ȕn[; QqT9w'jhh-I.BbcbhQiߙ1& >޺e1*SB]TO@g;`dᥴejjB^`6 ]e5fugvTfq8Vb~륎kvUjg\b^4⅍hv,Vڄ Pnluzs냀kIcezie$W¹x Yp uv:*Fֺ6C|eݮ] na inpAX.ϟ);ݿ`N':fUɶm]a]ij nsdȰIQNpI^v<6Jlv%9ܷgop WGE8AC^q^ ^k2u!mpYm _'9nE>FOqٚ@ų% q[[ '8!oQ#O`Vrzh'Dqr >MpfԆ-:1liAs8Gus:q;`hc5ctAn#sCMG+NWto;dqc@ ?<-.ue*uS/tZuE&pDlFFޞ药t^nuފ^a'bSG&X_e(W+niR :rlho~EVp&e2s?njg_rDF5km=/[ӄGX۞눯3AYo+gB5u97MVomj6_y2twxuʖynsn&jvbqOvfvz\sy5G^GCkl~fϋbލvO2yuUWBOgj(8wHKt{x֧~o<%D#ƽ]g&v,h „ Va AL ,L"ƌ7r#F1I$ Ȕ*WC&QZҬiċ`F$sǜ;& Ɯ.yE)ԨRRj*֬Z+ذbǒ-k,ڲ4VlmAp ݼz/`PLR!(00` (:SXJ:iĕs`^)o~fwBmx損WN$<2'hCE2Z{,TR,Zکi)Ֆv! [ض=;`$1V'LS$,EBڡKh/1;ξ (| P@EشZ|tj+faܖ͊n jo63=E0" B@DHy4q`c<5Հ}$d'4t׏|m/,αMTu}7A띥 7tY56Xرr:ҕDŽdmHqƻ\DLe 7ޭ:{4 C, i /^c9/-t0NqބI_qz?>P~Ycwtw~ןbOϼt$?yrFs:HM[{dBzmЧAO:1Lٯ&D07\4Fzn\%kE"bFv#WHFDJB2#˴˜đtӍ౔`Yi],#۔jmqPɍQe3A懨|&4J ҏ-y)2k(2H_B$TpNdlMҍϘ1'즉jZ&@DSy3!T/1'lMHUٙLԳ6mMэM+iHe uJR9gF'8&eL{](P0)L}Gٞ¹FQA48iMWrS[yNJWA Qf=k*;B$]*\Qi DLAL tCtnX2VYj[9˿2 W׃\rfpܬխI2Y"V2YexL<֋,fnM٤Y>3|-Sbr^<9%U3ڲyRn"g:vE߳cr[BS::B&3MXjby[QZf4SjyJޱI-k\:5sV[^ݗZR>6k6BY&־m _9_-q*v uz~7㽒s7% \oO;7zg һEn~#R8 {pѷ…,BϵCqY-7ŏoFwX>-Ѐ (W sF?:aN;Ghv`" PŜ;y"@s} [z֋JO#%nЭН[Z@֊A.catn@..sױuOm`'1w.T..“5YiS@0sj?>PQ>C热 \Z:wo_N|!懦|Lqvp_è(}|]Պ| >Y^ JS1<칅__6^U \_"HeQT^ap_`  `X$ vDB( _ []}`%N`` r Ơy~ ~N*^] 8aRKAy ^ !!bR a[ z!n"'*"2"[d`$ra&v,bv}bHIBϡ]/b"#~-&2'-V?bJ#0r %V#&N`.#8U43\4zڝ5^cpjq t扣=cTc 9ra㥬 ^ 7#C6>t#]@v +^x8HG裥tPtJf$ab1r<䑤Nb(Bνd#A%^@޵GS$OF%COcPrdQ @煥XeMڏRcS%TJ%[#URI@IQX^eYR7n rc[&85E^bG:nou%X`&^ee%&Q@%b&-*f?\b4VΥoe@ &mfm>f~eBAo&qriꖳ]XJeYΦfW%mfX6Sd1D:xqeccFKf_z^զXnDWe}o*/&B='Ray2&8|s*GXg^l l/F+Dyfd'ng`Tj'gB"=hhhhrVj] z] E~N/*0D.S6h6E¨s@ h/21n_JdJ6mAt`ghbhͩ^šr)-tft@lp@xD.*]iq5"6.:G҅ +<+E$$^mA/ 8.Ze:k pҕj,/Yv"rmorjH,NYsDHgcL..@@n#^ OeƒiO,/'n: bhN/.  -+/f-1elAt0wq`/1o" jNp-1qAC1o'.,$ܱ!%c `nqXdГ@S!E|}^+f!' VDNrA@1U&&,:* RBX ?7'_,#*a]6se'07׳F%tr&:[P~1ss3C?>G>'G sHs[hW}^=>=_l~*As<8|oSڂ:Ag~^>rɠW$ȽfxsS_|q46HܓsGF\=*@8`AI !".#:ĸ%(Z8dI'7NAJj8\@ѤJ-]fDgOhJgQG&UiSOF:jUWfպkW_;lYgSm[oƕ;nO?s=h@A Kp [\ qP.G8uyI3; LPAV$返.A4S;\A QI,O #Ϲ sP` <yN%a#m;%l'RXJ\2q  \:Rt4$:&0<2)"oR=?5A D-$Ҥ€,SAB.KQ4K$G#242MUUYmW"T* =Sɂ*2'P# [5I$`M:+U)QkVmӛ[jՒ\U2QsAJ,ݑ $eIb!g+J/iڰCnX .XonPWƥGW w1FHSibzx0~JQNY啣LESrzx1Q-x?aQf+#zG9IS)o% !ŁKYΒ[L#'rD䨨MN/˙=2cCPU2.h GKmnijpLR,IG$|bu%EfLSH42ͳtʜPE~34ӜYQGXg.3= C܎)k~"5IQzE<ُBK;2QHIbchAZ&#%]1Y>B0U2AcHƓ!)YΖ^KWU:њm%jVO~V/\+a.t\ YmN{wq_d%4A&4KJsћ^>J.ts[]pnL wskdz\m%5i^Z}V"o{+(.VQ~ށxcT0%]FnvV]= wogbe3-oϕt|#y^I ἤY*d͑9tXY.ae>c^P9rf9K(vlx,ke/oO9 ZO篵jKb]X_rZf+s²td/ĥ(Yߋxci2vjOPVү..s IW禀ַ=1~$iwG>?⪼j! kנޮgxGMvqsUm7ɉ;443 :9uuO0[ؑPv8: N Gg9 wu鸠<_:iى Ҝ26xӧs991-O, ^oorƎp/WOܟ\m)gw:H0G;ǸF鑟|ڠj|s^[m/}3٢~0.H,.v̋XGXIo*LIXКhZM O*- .A."T0ҮN´ܪkp2nM&oFԯ.~r \ ѶoPpy0ET-&@*pp/_t @$ipMd.zp QtdNk cBp2 p-X:f @M k 1&IP2* 1ptp2 ti1HnJb֏F\Aڐ:hg  >m#Nu1]dI1yQFH ڨIbf]l1#o {1q2ђt)I ],Wd-2Q<:K?QqQ8W[1"^;Q(srwqLި cOG4zO rV!I:@* !U2"HkQ#0J ]CR$E@5 !EW(ɭ%l#?'dc(K)rٔt -&1 #*dr+/߮+r./-,!e+rR-1)2. 3.""8r**R2 @209SXX(q/3r2d 2-7LAQ 3e>)C#?&q95#:(/.Sr6jrq?|X*3q3;k99Rr:8v,0që!s>5 15(3A3>{?Bq^?{$@{%(T.C1SjxhXOZ0\YG7l+i.g:3 *Y~_ZC5i9ZVE'pZ+j5KhIOM#!*v9/xSXu[Jg(Z)#Y Țc u9Q4z*!SI۴y{)P!V[wZ S4gvLpym{;bٚCZ#:tG[͛'&;'z5eG{;qV([;鷽M[D;{{ݭ׿\j o6/ƞ>CuP\]);Qg $߂ڃC빫ʦ9m=QAKG [.rw_VIA~0>Ql?q߄bAeLgEG>')ȳgh_V-?<ٿ"aŽ :j[N\uqVǏ;\ݼ{7ċ?<̙~UPs[ܻ{<˛?^5NaCuOzٿۿ?~`h{uOWo~Nh_pfD`na~!H| bwVȢmH2Hc6޸ϑh"m(NB׋D>cJ.dNck<*ԉZn)\dbIfF)%O؏eerٜgz'ih6ty%dىhvxig> igBgXh_2:礢Jj^jfX*z +ijފk'&ql.KVIz*Nhnmނl:FkҴמ߮n%n[R\ pKpܒ F/p!bv / QЃ"U+T/wVRzp*.SZH<`L!qq.֩(BM4Jc>5s5 ؑ +¾!p4L ]mp>^DPH5,vÄp m %+ISrMJe#WCjҕ.h `͖.åyL s<1fA&sk5ٟgBl%5{9JDas 6M xJ j?GCxٳ3P} m(`*sg8Ќj. D ϊ2O٨IO>룚)hE*Ҏy(M}Rg43.LcD-*rb)P%TuTU"R{DR ְ^UUJʽ~imj>duT+VXALb"έfe;%]QU֑4bJ@*X^^c?k^|,ː lbDdAAP[nV$ n/݁v"+բu*aV-qPB+fQhvِ6{v^yj7nX׉a[*zф\ i5Z[_Zͼ鯃(Ŭ mGaSb +"!A>0X8n0#<.T#>׊"b&ݪ`7\Jh-qU"yʉT2{>y8hyV\.3?f,S2^\^*t6⚟;α2o h5yv)?&Ќ6f {ќi>0!YJIѶɴit2~HE=$RԴ^ ʴ!5dZ {xYd_-omXUᷛl={ے,d_Q Ͻ7ogM/xMaߍ{Dmhqq2W ~]p.!|Sx|j?E7?F2nH7~,GeB*ooGc\2j.A ]Y/9{s=.Coz>pO:鱎ݜuSAd:!VY/>l Nst?Σal-+z=Xu/^}> /SR7[ƫizZ*z2]2}|g=dNI {^#$~I꽽 5 9 R|#?"pOx26r~\֮y ɾق{32׫~M~bG|Ra{ik LspA}K8Ggj( lg b'C tw7Xq *xz/iwt570E?!F}GIWMxo$ Q|ÂDixZp\؅|9h܇Qjsosh W xVxlpg{tH初(q8 P{s扫8s8p)hC{3xi{ч8ȋh˨J4xgQfшhL!r爎Co>VH"Ǝ}aA1K2QY~(Pi "8 P )HX #!9 i 9"I-*ِ,7 6|?a 8)'9s)ѓ>C Q[AV+=єQ1@7Yg:ّJQ`Rq޶IAY }(a;ԕr AkiUdy{})OVIWxIJHJ1l3+əi)O6I@`ċ3jܨqCIǏK\I-cʔ̛89ִO Q;0 z)Τ"0uJ%T V**@Phю]1>*`K7Ƿ<.Pox \8`1|Kn ȓ3#|@QϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνÔOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($B@䝈x*^.zcHv6ވ]:ZctBi8"1YR"P!,#jwd22    $1 2A"1&5.5곴 jw#@*\ȰÇ 00ŋ3jd8@ō Ccő(SDXʗ0CtMrxO3wZIfP $L(TQ"lhJUΫ.,8Ykħ9JbK; [’`ݷݿ@+&p^ ((lA(k0͠CMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOOӫ_u./}?\2G` r .h\*X|{ix]}a@@!, M$022  9>  곴 @"@`‡0Ň):ȑ`F;~H%1 XɲbJ'dIdFaJfd> $)$%cy6rhlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\wE&f"Ivb#iAIlwYdb!l=#cר~Vysi8uw7e9LB!,v~22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ#J,8@3jQ;IÏ /\ɲD)]ʜI̘5sxΟ@ѡ B] t( JJS `M4@PYaӊDi@c[ 〻L, \$ #K<@ɘ:XpBϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkν~Oӫ_Ͼ˟OϿ(h@-y .!A w!a"wrXv':bB*Ј]0f75hb'"=X!FXd!,aJ(22>?I# GHS&&2))5곴++700?IkBCM$#Îy4GHS i|&&2t))5xÏ|9}:נneؠmy)؟kӃ<++7١oӃ= (ءpy(00?Iןl؞j؟mןmءq00zjm@B`SB} T`ÀڗP80UB!P&&ĄH 7@.a6@@!,.7$22$BCM KLW,,8((4/e08*'$A/)CDNA2-B0*A J !ǕlB2,abl@A Eg;Ũ =/~{ow;ZZ ׼hAg@)ю( PQS416[=Ap+`􇗃.H`^#2:a8N;T!Y\(DDbɅӡ*ڑ?OC!cWD%ZbcrHR}_'F82@#d;Jf- 3a9ђ9Cz?,#'I4j˂4W# ٨ˤe&JN|Q'MxK$r3$KY6R|]&vKV"qK7m_gi%hRL4yY z0ob:gMvSmL-lҠ\7 '{sꨙEv/Ѕ|,#9IqQ0eEQHPQӧLҘ,USoнut<-ISB%*QڠG}JcK5yZ+jէx5a`\RuL5kBѺ(l%WzոQsM {رFF-2 )e;"UhH`զl_*1j m: ڲlYέu8I*j[WsYIjw\eJ6Xuӭe{VWM&uŭi{΍/F* pO#gk* [ΰ7aè0಺%YZ"\y+8Ok#8S*g0sI`_PAyo0&uqɺ+"QNsNM5C֯zS+R: -L7jj4_?q>feQEz%I WLИ0[ee3h8Okp7Nղ]ԢM0WHu~mK!4k]iz΍u{{}\lc!FC0eه6 țJ־Nql+yzv6mbr{ޭ\jvǩ^wzxaSt$~{N,UH:}{8bxbq;GU9o4qוJژ)W19Pq/"\"'!!n1Ϫ'x?MTv<_}憑b2d'jy"Oc^ {2JψC[އhj:?$>]x>~j_ m2Ϸ|1}Q}gE~{À0C]WR2B[Fk`C &ڷ}8sZ7#xmAt{1$Ɇi!{']cu4a(.0X6:H5(h7IH~S!yV8+ք7`q"ǃnvnGybfdGfxV?hvxT*(vq"yf{O|u8LByGqy1tHe(h~Q膃X(؈ቇ|&wHdC}twR׀x{dZ7e؋ pƈk qxgF;]]lHh'RCWMiGa7:c:6N9RXh3)֎GȊDA2|ʕw|T.莖V'ԴgdY"=4iȃYH.2ߦ7YWчyK*MBAYSCyKU uo9ܩlRXvY'hf9))Umi wyz j Cw،Ǚ%YI>aə _6yᨡ,ʐk )$#BED{$ڢ>Z zy5:s+7j 9K?mpٙ2* I:ɥօ ٍXp#CG)tRlz=;9[6ٜ*'Zʤ,8c왜i:v*~MڨUzgz_Y^~|!~:Iz'8E&#:IJɗ%zZ#( YJڬH/_j:ȚjފbO}1:kNJFʜ2& ~6e(Z٪<) J_HzH B {:+2ʭ::s{)0ҩ;jz"$yɮ:(± K:ۮ;*$x8 ٪ٲ2˴0KjJAQ @ۯT;V{XzHK^U۶]Kg{ni 2kR˪e%O Z*d9!V[=){{c۴qskl۹Yk!ˌ+{!w{ڭ̷r˯ۻP[˵\)fS+x鼆ʸa<۰īm`JS:b}[T[{e{Njs;}9KEy{=:ɽ+۞Bbk`{Y:{hZ ! rL%'*k+ k6l{,Jg8>Š6K5HJ<:=-CKg/{͟g-r n٪(]x"щy2}s]&X}Ү| Q=7itļzB=]ݶlTȵ-wmGhymv m }Mwv߿](ܲ=/Y-%&-\&[` N* .d>DInǝu+ML'+ދ֣1޵,E%n=H >~ZaF]d֑='nBPR>/XР`us0 cua{?x(C~b;]j>?p>-IkvћЇギ^fV NF>\Nܞp]K>WKvo雾V~`WMMnHN`dL鄾^kM:,^Ej>t|ȮM7̞cn"Wg=vi00Н@̻kbT.LQx.6)hN]J݊_ n9m_Ϊծ^[N@*HS=%`/UCFZ uZ>1AUUOWZbÎ4$eg&$޾a?_t/Kxg4f_rK?- YfGIo`_S_TE@Іemq2aEB]ßOcAzXgoGѕ^ +eMV\1i@` $xPB :(pa‡-V(qE=bQH CD!ÌUt0K1 SN=}TPEETқ8>`KRyJ0vIǬ_4lڱmݾW\uޝ:^_&_MΫځO*v2bʕ-_ƜYf9I8j`[myr6= }xd٠mƝ[nL_дɪo{'V<_Ǟ]v̹Y&qXK?7N;Xcǟ_~GқX ֜O0B /.2,@31PCzp#[0FgƆ F 2;gGbQG'2pTQJ)%CÒE Iߎ2M5d33*ls9-iK.ų- s1,24PCE7 Mt9TѰ|ܱO52I4F?5TQ9t#SAtZժT(2t4IXMW_+k:c=Q 6SrYhVXkŖ7uUUdiv*j]9ERڰ]wŎJx/UيMϖn*x^F8'·&.I}UٍL`s+b?9dۙ<,TL)^R㍣wdo9g0CB9ըkY e2Zg:jxnꖃժSfɒ갥&l^g%ڣzXs冎noʍ6qVKqw:wgy'?|}7%v秿U]ti_G0C`:{`wpmvЃL]a0pɫ &@ZD a e>ʻjR0\Sg8D"" ',N̎ЈWb68.v^A+.QZDcA8F0цn_(ENg|#ոG>Ώm}9~>< !B>6ґH #XIJ>ғ$IIN쒚^)Pҕ<եuI qy _@!,()b=22>?I# GHS$BCM&&2))5곴++700]iRL\TjT%V4ʭ\j$ 6Q0ǚJ4۵pvݻx˷߿ LÈ+^̸ǐ#KL˘'Pa;/Lh pajլ[| [6Aڵe}zw[`!$ό<%P-:ί)p܁nTibh0p pA!,~S 22#>?I GHS&&2$))5곴++700 %BP@8 @Qrh@ p@ %hK JQH #*T !,T22>?I# GHS&&2))5곴++700HիΝY6lӅl˶[ 5X M@ A 0 "Dn ZP!,R22>?I# $GHSBCM&&2))5곴++700?IBBmCCCCCCm ,,KLW,C,,8vvv1DDzzy6:t:w1((4㛲ӚiDDz7ҚgmmC𴥱,_,:xxҘdCDNҚh..:mmmxx _ mHo ҙg33?\wwHM CCқkMt_ қiyy\\ablH*\ȰÇ#JHŋ3jȱǏ Iɓ(S\ɲKbʌiP˛8sɳϟ gҤY&УH*]ʴ)IC4괪իXjEU& JٳhB vjڷpʝ[rl[T˷/]jLak≠;BLY 3klRϠCLZBgѨSnyװɶMퟳod {&_Pt&"LWۍz@P %ħpX/t&MH6NY!蘠OiD ~`Ng=A蔱L2NJ0j!C^LǿH KH7uRC\΅K<7BUqQ hRm3V7Zu) 77өY\ Wf--L8Q6{^4"ϔ#:K>"K rWM ;/6# ȒT(U5'oVQWŽ7P" /HqJƽ";Tû V&L FO#8?]>NK/j7!&E\r7}skU m__% y\m) hm%g[u] ~f1(X&Qf0, Z:Ɩ1fi&<8W$ǏE(C!M/ӚETԁZpZ{$`YcEc5UiCBj]QFk*%Ў*fWI6y=;k;[V0nζ nr6}4n+ y_wMpDƶp|w'N[ϸ7{ yy "OW0gq8yI^\@ЇNFOa|PԧNǻUz֛^rB<]`ǞrA:pp;.\kWW_q]9 x/ }PHR7}Ɂ5_{^K`&>yr!<ǛH tw_M< xA!q=y!zxO} >タ>>_>IϽ{_<5>KG /->r,>Pqk0T= ~({g}7,''.^T@Z 7}/A+ ,hqJ0`y NHx4Hq6~򇁉QR q@x30> "8 Z0f_X?Pi@f&OzsQXg7(+ԇB#(gY3`JІEUGHq"{(rz~Hl!BZ\(#(k`8qkxpgxU]؊ [(#u8S83Qǃ*g5Xxoxฏ(Hq(@kH ymȏXV̨7yN  Nr.0qrsHH@'^3)u ;)LٔJNR~P9VyWX\wZٕ`gbYf9udyjClp)s tYA vtzٗ—~YAၘ٘YaIٙYY)Yٚ :)ʈٛ9Wq9H¹йRYqi9IYy鹞 Ygٟ@HbHy,qP/rB Z2 ;bڡQ,2/Bp.) 2C+á*z!:;6>JBƢB=HA*ZIP*R:ZVڟX\Z^bdZyhjj٦nښ\pjr:zʧYzt ? hw 3xڨ7:J|ꛚ٩9zڪ:Y**Z~yȪʺv٬κъ:Rٚغѭ:::Q骝xZڮ)G*ѹgIʯ N t+: K۰[;iY !+ٱ$+&{*-,2+54{:k=<BE˩GRʤI C: z,-lCE|H=ĕK|/P5*'YETQܻ{b\,"t)ƃ11Wp<k#uKXA۸.|L}tzċ rQąQBoɝLѝ*hakLzˠA)Ȍ(˽LLfa|:xl,;Ki̘)`F,\S2,Djv:z i,h+G\'*\|r0ώA{,se`Wk@)6 M BVq" !}IA,=17 <= 5ҙ;./$K4 F=HMo,ԟkR=T ?m[s_}ac}]gXha,᧶l=Jzm~MV|*ZBmבMeՙmÒ֏(͝Aگ .ղQN}BAۺ -jܧ˝M =- }m]+=A PQ-MMݼm<۵ }ߌb,0ěA$[\(.+^%u= Ψ:)LA>9GCnMIQSU~pa。, ܝHи jN.q~j>T*A_1T ^<u..0ylHʢQ` AЮLRm詻aKmqKМ..]KnQ#J>B]됽 F:\qтn,;X>QL^7*~K=z/˪^0)U>! $>-]^.Kt(57|-=Ҿ% +$_#o/_Fq)y\.2O??&Yþ>T_1<n.- H^.,k O92.,S@}\h{??nrugeb> ._/n?Q1a_eS ح_`Z?klP也Jo߬>O/OI/_/e..pA_33!@@ Dh@B >QD-^ĘQF=~ 0`H YSL5mę`<AM:ETRM7 TJE^ŚUV],*Gc-hZmݾ+Oh5 @m\},ݍv Xbƍ Z(a80xD;CZ 40 I];Zlڵ1"X`/5Ymōf ȭ_A(hn͟Gֵ[0|΍7k0@T+ :A0„/MB 7Ԑ h CO<$#O>g$GlD $D!D2TI'cI)-J*1+˾2L1sL3\L4d6߄3)5N3O=sO? PA}OBmPD5SQFQH'RRJ/mRL7%RSN? 03dT"GլEOMe5Ek57EYo0õW W_P%6Y5Ce5qUhMZjZl]L[n[pDžK\r]\tJ]vm]xEJ^z^|I_~e_H``Ha.b㝸b9-X'3xc%CyaK>dVy[v[cm9kQ]fwF5Xyz U5hΫfEǥc~Wfu:kRjkjZVlU{m_vWun[nST PPGp~!kc|<>W*+x!_":Dw=?QǷ0kYms"5L!,Q 22BCM$ KLW,,8((4CDN..:33?abl"D8P‚ .(`f4`cA=qH?>D@( xI2dIfDi'S(OD/)B5.4*=VZu!NW6XҦztڶ rY`"H 0\0!(,\ 22BCM $KLW,,8((4CDN..:33?abl@A  P :C#^XQŒ'@"ɋ&Clr!C F$)Aƈ 2@@X@$4@%h)P@P1@ a*lt!,S22l)#$tu8$<#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳ%T Jt( }*]ʴӧPJJիXjEٳhӪ]˶۷pʝKbݻ LÈ+^^R`L˘3k̹ " aӨS^ͺיM-۸sͻ#<-ȓ+_μسkن Ou2.:A˟O_ Ͽ6& TmP`d4hf/@(U$h50(4v^@)dZ-c L6L0|Of\v  8FFe4h& 6^.ti'@ٛy!`杀*Mp_|Z%6裯y A馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pK_\G-ͽt\FNtۥfw ]v׺.uk^%ymԫWAz/|_Ʒ @wݯ̤/ؾfpL^ 'غ=cDaoH?|" UpQL#,&Qc7'qѫx1!C6V19cy,cgxTVG >le,A=>\c5g(n~3muϗ<4sdAyCE#ͅv]aIh4=eMoZm| hQǧѦjխ>uXk]_z1=X=sge/سiҶ6wkmWf6_p7憶i]t+wpfd֠j'wٝpz !8MHo\Dw{yQΚ坹8F6 s7t E Γs3G)z̅h]?i.vԼ!;/Soƙv{Cug;Յw+~~ xŴ_8!{S퀿|bԮg< R7}ZTNtwKoDZ=[ wݷ ܳ|ӽŗ _Xu9;"wG?ݷs~<1YPqxpHLq}h _!(~5%H'؂3w$H~2wQ{:؃9@h?80F8I\|M`׀Q(EXG~XHW'^\G$hQkB_؆6(v8c,|S{t8x]{ihn((ሢxKȂmKȄF&؉xXh H8XxTxxʸ茪XXØȋȌHwhHX荱눌`؊XWQwxO!{,22,,x''dgLfe----w &++p,, !!!I a&&a !&LI!x,&w5L!,mC,!,,,x,&&,>?I#x&&!ғm&&CҴ!wmғC؞wLP a!CC mmC&x! @@-CC- GHSm$ĩmmm!I٠oqq&&2))5#BB|9y3tt{8BBx3ĞC9vءorr,!H+#!!:x ++7rrןl!ZCmCןm؞j؟m00S oҽ(߁W 62_VhfXۄv (bUh(0(H8@)䐏HH&SPF)#9IXfVn`9cbihFHfl tigorީ|*砄jhI$行6 %ҢVj{Jzvbj Sꪬ*무j뭸뮼+찺2 jDF+Vkf;"͆+Jږk覫f%q:. Zk' J, Wlgl7Z05(+,ˮr 4lBlB(H@ CC L7tL0DQ/4u'<`Hϔ%4dKk ]j!p+mu*x7&i ͫ!Ex$0 ,8:!gc9Y,z$H@j7(>׏N1 wv怣$`:<ȋyCξj -L*@j=+Xj [?j}ރƟ*@a8Bp? WJ{` @_@/ l0?y#w-hl*Jle3%zZCUi.̧QaJ`_ EUpt 8CIm +@*4'.n|x/nqs DVL$"?TUђp U:l;pf Hf2$SJ= +#l.+PBhF-a}~`qnyKeKf'GFkZ~d&)H9od97YDґ-L %)G띰y>~ %pnp+XlC4R0U@E[XCa,#FQ^Ϗ >ǔbthEI\|.xw>rԣi:-{zLdOt#$d:ϠfԏI^5Al*8!V鎠<1"Cz&&KyB+n2c'қy^ W)Wtkؠfo'MtH= GIʕUw"R=/:g@ :+)}VLnE\锫' 1'ESF֝rU4JХ7*Yй8nzUUWΧSKrWkה-zQvU(o`B ]=۽z<>}=sSvi\5||"`bǪş|"N0'd÷/z<<[yO6HeY<3 ;!l*QHqz)t(d҂'pKO2g{J2$ #s֌@L+Q~]?`$!9ʤ{+IY.ȖpC'bS#"]l$gU1|nۅS,VWŮN39;@gNqӤ|Áԧ7RMX!oV_c5pmT-|! /NJ WWH_aZ(@ c~o7*|FO;񐏼'O[ݎΫH5OқOW֧DOϽw!O;'/tϾGO'AO޷/~nh x}ZZ`7  (X' !'h{ "}3P&x%7,8|3tt0<>x*'Hh4@x7;=TXwC7B7,1a1dHKM@7d  VOg+q3P<&Aqeq a7*nXy?Q7N {vxS|7v3x-s(t7G׉ˆxS3e8hv#4(U@_4?c0vnx@3_ x*x8Xxy0C[ CPXQq qn؍* G@tx؍p(*@؋wӑXx淏-qeCY΁ )x5XɎ*N}*)ؒ\;D:#BDD6 @ ?p#FY7"rMx|QTJD`Y!Aa>b먉wht`w{{9EX;ᕆYq7d@ؘ GY4I{#ٙ{ɒ闣iyWW7YYPz󈉔:{XX`7ݹi) Hri:pi0xuS ϙYVqlG:j}p<ןZq՗ڃ^ ^"G&Zw:ui  B}4jF*8j|ڢCz9G:0 PڥWT^afzbYAplZv*!wz!~ѧ:ZqڨJ:zکn:zOQZ*ZbV1ګ5F1!qlIP<452aH8| 4$3%4e9A\3 =F15S1]]X:=lk}-/؅M=9l-Κ2q;zmL~ZE>e{KZ˲]PaMd޷lyp^r>j^un$^k;<脾dž^Î狮};͌~; Nқ_k>.]ʩ}ëN~˨Jް뢞%0Nj6&>Z-Qުھ~^~؞8iNÉ^hëYELo3 k;Aǭ/Ųq۳ﺆ=ک߻jBNŸ?˯/?_Yq_/MͿO_vߺ %@@ 0PB >QD-^ĘQF=~RH%MDRJ-]SL5m*$@`NoTPEETRM>Uj̜:V9UV]~VXe͞E˴Z+}W\uśW^ m_… FXbƍXdʕ-_ƜYfib$mNq:I$1jO]S:UIWuUi_EW:VȉgYѺֺoM[:Wծ]*կJ_+6h 0@ZX,d]ؕ!V1 Yʞb.]!%eY]=` 0iOھ}pl:Y*Lyf_[^W1ho[|j@nĹ $#ok/Ff[>mv\-`lNI.?GWyߡׁoy)kh`~*ApN2vmA8`nc̵q_SD-FU~+ø"/:^J7w%H2(e~uW,Ge"9\N!b8bɖ"wⅲ׬9=rg`H3,RݹƄ%e"OX/QCK:6#cZ&tL88ԉ>u<v:4{gGWZ1_cR(i` {lٖIhlcS@u3ljs>~.m8y!r|np1tMfv}o؛]Q 6xmm<'(ԅT2)TۤxŃrw' (o'!s&tˉrX撉o~#t73s@U"͉N|J)m溜d᜞wBug]wu;UI^ 1n뷟o_5^wׂܽ] :Y|ś%mu^\ܣ93{{cJ_l;'=Krx@RmS~tyωSd/Xt=cL=E7wOF_KɿMD?dҏg?n@ 튾 LBüì{AL[@ Ah<m<1 $H[@q;A&|OA/ c='u@+Vy"2A PA+yr/LhCg28l9 ?;<ܤԶ%CB )DA@ DTD);=Y6zG-MCPN$"@ARSTC4?UV,F DJ [4\TL A^,ŷDaD_ԟQ4F=AFAE8\4iFɼ{hiEl4**CiTGE)Gιtu|LtG[G)y|G:DBeGbdzFtGzpDÁA.DsF,˱)-dD$l' F4bH;G\"/:G$#~DjI,1zFM|i1drEqi"BBsČIrCDLJ~YʌFAyʅ9ȫLFcʄKQ6,K$j6\K9Kv ȇKKo1H[KT˾̘vL!fÜ d̖qSq˱$,4.L£JlLK|TDJҬӼTͪa5Y״شȤM"ĺD L༑$N1NALNYNq٤ξ촛޼FdY¦,$IklϧIP\>kB(#PI*'Lоk>웗5,Jг τ̓XEK$DQy*;)e ?ݛZ$5Q1O$=%#6(p-.:$\SSI?I# GHS&&2))5곴++700x4b+!,;22$BCMwزB.KLWțe@  ,,8B44B"*BCE..:,,3C?N(%4((433?Ⱥ B4E ablKF:( `0C:L1bÉJ=~H1!H\ a+cƬP@̎: Й)U: BeHz … *360f hE{x@Є8$/˜@ a0΃\Gq+-SztVΝ'fJ0Ι'X]@֭!,d322BCM$L w,,8KLWĞe@wKFWCDN..:(%4((433?abl@*\ȰÇ#F `ċ3jqCIǏK\RI-cʜ %L8snySϟ yJ *- @Є".SB rJkDM. YW"|oexZ'(Cֵ;& 8cD @ˆ?.L5F0! ;<P „uȽu㨕o8A0г^* ١&'/ o3Bڙ>K/,V]!,/S22BCM$ &&2,,8KLW89DCDN..:L((4[\fl@*\ȰÂxHŋǏ4nI"G\I1@)UK9YK9Iy'˜&IOTՏZnU@׫4@P[gKjzSDX\[Prk  "Х$ \`dڜ A= 2Mmfݍ{n=OL !,,22BCM$ KLW,,8((4CDN..:󔕘33?12UJn_?d)UGxd[s"x:Ff U'hz6i]H*Z5M4cc d]`AI2]ge&u$ H2L=.mI{Z_EW}KW骖A)m_2d9 eGjMoޙIdsB2An2j%wEX< &VaR\M3RV{d_ndfEN͵5H#𾤥FMܕ&!#LcC0 ~Ʌ×}jEW+dS2/K>[VYIcrtXH Co ]jKEi AV`tS|kI22D%1iI] ad *-rPZ-= BY,;eҝaRefϠ@3g4R~5斨э-7 dqmiP2PEsd\0'$,OjXkO xokm:*mr*jHd2dڇK}P.L) @NuUj?\8uT}XVՖ_]6k/ht@t{At4wR!3xGs4#'quo.8i.=vYpǁ:lZc3$qKQG_f8g|s6iM(yٓ!sd=jE2n&zؒ#af55i )&Py"xu>ы!YyB2ĘH]HIh5>TXRqsho9c}Dɕ|cr+]2cW5IT~U׍or }ٙQ}0zyp3A2+cx_b/)I3 S{虾əQ i縐h9-AEq yZZ)?3蚆 4]C'Ii>!01ǹ Q3)O9cY@QWS} 4<sgjh0٠ ƌ vyA2A!4dIk4C:HjFs1l  'Iy*d02x?㈏hy7g{z I)5ȣҊh6q@Iĉ=Y[G4"zٜ  .i%m Wx) wt1hWٔ z3 vS+ɩhړu1Q~$à5%.-Lm$ !ʏSV`Mګ uiIAxİfڏ:a4#I9Qʒ: XѥkY8v*+)pʯj`ꪰvc1H|0wb9ºjkb'ڦ1| ktTݙdB!Kq ڨ l?1y9{8jC: syS0z 5.@Qn)[77 բZA{q"Kƚ,ˬaJ۴(>[wZZ{`Kz/AvIJmhH%ˁ8x[L~k|jAb;k}A+KWb[ۻ}۽d{*K;х:gI:Z<.ۿ"al w}g¹ʺ+ . QhV|Dp;h@KQ\,+Æj۲![l>Wʁh-w/2 ):`J†*ljW%v L▀gA{ʞ<Z|@C ǟaY"q`ö<ὅRy|xLA,{u̽ a{(\k̅,7!n,ˇK!\ǻYQͷѼ,f<\Ƀ ~Zrj`ɭ' Ƣʞ*rL $˼qN|K,,/ѩ%}$3!'Ӄܻ:}V =&Avȏ N}#聃JL<] ac^=iW y5Fւ]҂Ո1[$1+X,QӃzѯiY>םmه*xZҼ]] ۞}ס=<ԩ]$lnݬAJjܥmo&Y.](](HDDm9M]m5G-qxaH2MޗpUw!ڙ=Y ޽# 9&˞(n݌W$]&17] (ѩS\lm(J׃!n.3m}'|(:Ѹm(9XW^(Ѹ'.3uM& t^a˝zz]f.+㩫L4^E#ِNѠNctl])Nk-NMn䀮'=^$sN={ɰ^nË]>e0uEY^&.!+<ҌMڂ"L띮^"Չ a^V-^~Ųl>!lmZg~'^i)B-!]0Nnڍ~$*n*+!n$JoX;@^ҭΞ9O.B/d?ێQ^D"ݏ^ ?-!i;T?XNw"ŭreHrojvlrv"n;ZoK"꩏u #홏{-s 3|> .✮Bou-r/žބ^t=;"|M_i~@@  >QD-^Qa 2^ `<%XPeL.ISN=}TPEETR8rTԉ*:Sbj9`aC`PWm2P7EܻoǷ FXbƍ?KȕW6{!O  ӿ(Ce"{$zbsiʖx7/`ε[\pō74q㣻čѹ_=u.fMS,Gzݿ_|L_Yg@i4ʾ*jsl=*Z)=#?C0C 7CK.3'/2 Np+Ұ+j?FD i@QRx:q6h$H#DrD K*,+(8J@G+PhRD /vҵ`B 3N9,pM;BK-+[m!412Cs׎*4O$%iSO?tAA*V'tK3TT Ұbƌ4 *VVcE6$Uٞ 49;UR\qG4YVƕzT[[w߅7ޥB `9yW*1UeU$a2*-JpZ]Q"[ER7q<\/8cBwc^_(J>X!˜PaLz1X:n9gwF6by._=`RgLHv.^܉q9h;j w_a)GZc^5N"`mil}4a`jW*=hWd.ui+L}- Cr)IF(IjKaAҚzGc.vT֤ǔBoJ|VԢGz'VMrEnt`8\b;3R6/:Szk""OEeJ7хYa[ExԌ賦OpJ/i*~&-|MΒ",mfEU8)UPC(]RC9&kBFÇu@eV61t,`KzՂ;}W+XUY`BS#}(DFǶֵod wX͒RAJUHbsHK1Ӑkj{ֹeCqڔ ũ@d#|`j\Q'E9B׽% Z[,A9 RYU"o§xSNbU~Jg@ KH\"~U]eSLe+{RŮ }HI9적G]$]eq Ȟзo[MR=uD=AdsgVpl_ũ-H^ԴNsd[\ӞȄ-<%K}&)zW 9) Q?;3%t.:> -|͞8B&a7HE1/c9gBqg;qz4BP_w;)$"=8C& P6-cHmw=0y |޴Km~6KZlmɝGSNtkOs դq| qPLjI)7tJZ99[m>y G9AKIWLtH=b#0xΥ~O|O>vNt3v^kqt2橷~nlmU"biI~1}w{uYu A7zwd-G-7lJt=j\?aKWAՍ"L?Kצ}wy 2t*/SD+wa|o|/Cԧ SXi?dQ/$s<R(y=2¿ط>8A \@ { &s?{@y+  p $q:(3>hgCS-ĵ!B/ĩ݋,˰竿L w[#@.?1̶6h20A\9z>3T:?:t89Mܘ #DJD ۾i A³Zl,R,PcF;)CC.3f|zIEgd:ƁXMdɤl'aHVyCc`JJ>K=v4;$dD@Dž :|6ʕqc1؋F [ǁPȲ0A>k&Ǡ2l06D˚K2#LrBPtʸ̈( HT)fL"δNZéW ŴLֈ#([ ̐M>t9!\θ,P%ԔKtcPÐbM c(!$M6mQ`vjn-M8SEIb>R: %ON,n.vv+gMN6i<瑰qnU}KyQOu炾( V^1Kv &b?~ K; vu4萶(nf8 }vW>>gm 霾h@i"9 2 =ؠ. .iji&b $.>W^ H~k pk:QĸP !,'+d22BCM$̽ KLW,,8((4w CDN..:33?abl@*\ȰÇ Hŋ ȱG0Ǔ(@`a4LLI,Ϗ7qDgџH!JѤP.ejĨXNJլ` nhٰ?>saOXs&IgT(]y֔K A!5Jy1c P0aA[ 3֩q4 sį 00 *.; sG`!!,,22BCM$ KLW,,8((4CDN$..:UBC<33?DɚablH@  pAC2lxC 0fѠǏ'C$ir ȋ+YLRe3 TS N4%@C+XKt`RC d j͂+ @KR 4P  b:-Nv 8nߚ (P&J74tr8lNY`@!,,22BCM$ KLW,,8((4 CDN!..:U33?abl54@`B *,@ 8 Ƌ r"F"%&,iʔ Y| "I5-ޔ`L@&ˋ2!D4QhBJ~ zрHXzHP`iŮHۭ\+P dM~( б%l(l68 !,+22BCM$ KLW,,8((4B  CDN..:B(?Imm\CJ'˛oҴ#\fmmCo\,}x CCCx_])\BBN Cm:,ƛ#KLW,mm,ײmCCCCxNxCCmxx:,,8$vvDDzzt'#`.Ӊc҇b((4m㛲DD4Na/BCM♛x:q 𴛛:qr6,,xx󽌕'U_@//`\mmm..:xxɵfܹϵ#Cm33?Mww\҇a҉d?@Jƛ҆_yyҊf\\CablH*\ȰÇ#JHŋ3jȱǏ Iɓ(S\ɲ˗0cʜIMrɳϟ@ JѣH*]ʴӧPJJիXjʵ+QŠ kPͳhӪ]˶۷pʝK`лxz˷߿ L˱d4[ǐ#KLj޼ϠCMS+װc˞Ms5ͻnZ, ͼУKVuI)M4}Lm9k˟OLO !0(`RA&aujv߄VhfH~ `_1Rȇ("T`9aX{2h4hS5 ( ΊK] HJa L6) A I^-`Re1q C`7$YdQ䜛iYpž|'_) ^d8Y9hbhӣ4- )K:f$Er")*'iO*U(C*묱Zꨃ7sR ѝ,*FM:`5 .J) )Q$PaɠQ QL;+B<@ (pܱ.ȝ  $`p$ 6.,0-Q L.jkfL R[\2!/ {^i\ !S*`+' KH g AbY>f2g ҂@js/#Sy#P@IJQc']_&@^&m`bQU\"[HH$7-INkħ *Or?!QpT /QMMf \dk Y0* _8d.)8neëU9 Y@GJR.ss@]`Ka >lCP=َ<3g7fDO6/Xj򥁕. ̣msK؆`(mWsd#+-W:/t6@ۢѣh$QVZ`%ּNo8kŴLŃG$+w"ˁ̱ͣN ~1PBT-\<0#iPsb \\7&_ķtR/^}s@^,NԳ䳘S) WA ?3Oy)NxmH?x|gJ%\,=d|!}MB#Z,F![Ğw 9:Bx|2l+FCLwlQZa b@C(W+}+{ ~瀇q~~k6xt~р  ?+h.!}4xV4w(8hsɇEA{Y571Q  T 1 h!G>]҃%oEHhS\ȅf 0kqx#-\򆆘`hXEXw~Ƈqo18x0s0 X#8%Ǥl(]1DHc.)~ ܇:r a7f(,Ѩ؋l؆ HH8~ϰ2r{ԸH xh?E(؏_~4xYP P b(Oqۈ]Gkh .+l0I#2 iȒ)؎:hp6_"y7y9Iٓx짐Q `aN‘QűhsF{(iwIL5~49Xby9xy.9"CE)z)-Y3ؔywil"X)u%."l9IdY܈i)lhE y՗ I9iƛ! b&)w9y_Zdf'YKڹXY4()x^{`I!Sٛghj)剜1yyhbAy9Yɔ 蟪Jj:rti *]8ǟja9Z$ڣaȣ)i4rF:.+:2EGsYƢ>V'3ġL.?K:WfRvaH)z^t\:shZgxJڧ9,~mڡ*yY woʨj~bڨ]Ez*piHh yکښ:!'VځʧꝹ0zl. 6٪*šJ{{ڢӺu};:ΩjZ z ٭).Jʫ䮥j'1Z8~˯^G.,Mz*$ [,˩Z5K%۳qxDkɚԆjoȳ&*;>{!AzfTSz *N 7NjtٵX{ P% 0`x%~i_aGjxiiU o ,vK@p|:˦~-+⺴=qø;~9;@  "! 봄 |+Cog{I[{ګ랡 Kǫe굁˼<>ϫLʺ;Syxۿ<\| *qyk{!;[ɫI;Fk)uKWK{y2<4\6|8:l˻ {+M&, Q+¿>).L,ow<\^`b',iE̙P\m/%!R+Ⱦs9pc<Ȅ\Ȇ|Ȉ|0s[w[ Oф՝ p/p- Wn *8txݡn ]^F˖#mԘn"\yy:,}&.$~m-p V0/pC-.CO~xGE^rm`5#+!~!Q.%'~^"p*B~v.K݅ywNm]UWYxԀ7qLc>&sNhn8@ ~y~4.ڴn++O>N̽NXl3yNҘYQ}>jn;BNz]׆e]j=͒~p5n#Eę<(= v>2p9NV񸲞]˾6*?[Q1<֭=3 H anxoĎs7 ͐ЎhjϿ ã];/BnopJ\r/ȣx_z'_Ӡ Q1AoσKώ9IzQ5Ys Ǿ^.؟LsQk"O`SoH߸/JO.@@ D0@B *‰-FhaF=H%MN yPJ-]SL5męSN=}TPE9汚ࡳ]h۸9;luL9RՖ7mylgzܸo7,{Ѷ;Dﮊ]cZӯ}~^'qw_^Ч?g) s*~[ s: 44`Eey࡚I0` )tYGC2 q_%3? BdVъN*Ö h?&Љ<b-.^эo'!=H3ψ`sH>=@2c"y& ʱS[]CUhIHqrY[d(EiGHBuT$/BnpI"O;5q`[*GK^U$n)EԵҐ1WN9c/9 Ar>L.~s(ilzјs'˟07$g7VԢ',*3('ѩkc,/R>(g7Ji.gR2liPBsٜ)3WF"S})$7M>uWj{FxJRK)CA[g095$K4GϜপi<-t{yhK8Yd4lP[$mJ͢QkU#=KbW”3B6Y=jb,V7ڨ.h6 c! zƶɎ5>SJɬ]9.ھsl;`̶WWnZAm̷ݞEmw%+S`{I }@ա'/1 I9]Ɠ?!->Hg:؆=s6˸Hº= 8>@?.* 7U ӿ$A}y=\?:; ܮ\,Ԗ TAct}Ii7i;@d9L+˳\$!:c@>/k0D'B)t} B!>FB#t@0:D2B)KB()C83#?;T2 2A=C#lDGܐ@/u[5:\O̕KĔD@ņE$5I3\BPEEKԻ̓4+l"\tԛ5ɰCI˖ XUѢ5Za}@V9Ws-ا[Հ ͊hZXlZδY~ۧm0w巵ʴuUUأS%[[ CW/meZZĝۼEO ]D\<ܐݰ\\}}\u=]\]m۱ e Wi^f mEe֕Z^U,]W [R^3MYA[ȕK^4U^}^Ea_g[EE_==_ `K_E] $]`Um˿e>D`G a+a ]t VeE]a."aa!&aaGxR e#~%f&VbnafI`bd`/J㿱()"{G`ˌc8?9ad!=[>cf]ycBVW0n+c96]J6b;Q]mde$bbVvbYE@EA>SV<:p;ޑX0vZR^]V^eE2N%a]$^fedf^;g6[iFbfl&VFeo.4kpbO{&cs>Kglung7sRUlgEd@BvGS聞MyvKh^hjv^L8պbh3~.G}`%in3z(qviՓ~wiՋh#VMjRju7lcjJqk,~ǷNҔFkzFgk<0=lYk6&l$셵.lw;lMl{kDֺ&^' UΎ%lVgѶQ.ˆL|\BYim2ٞmkֱYޖVnNPV'>Z۾nI&cnn&n&3?6n>jp3c.=oŜSoloc6To]֛h hvzTp]q7{.`?G{MV{{b{G_|2]x O/ 7'/ gow^qvFug}G}Pw:\gBgǧ{}&}{xG~4ZOo}ăoFH/p~GBw`O߲00~KcI,h-aD,X ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РBx`@ I6M@bѬZr+ذbǒ-k,ڴjײ 5^ ] /.l0Ċ3nwnDŽJz@x1kJТG.m4ԪWnHUξ5ܺw7i!):9ҧSn:?J.@9s׳o=c\}? 8`|ᇞ~* : ^xd蜄z!!8"kx})!-"18M~4#= S@y$I*dk&>#QJ9%UZxU]z%a)^c&m^p9'uڙ^}' ր T*(:Z> %(j)ͦ<)z1$**Ri7+꺫+  >*,ͮXZ{-EZ^f-VlK骻.4;P5%.{/IM/Vx,|0 4 ;0U{)[|1*{0%|"C2-,j/|3U֜3=? =4ѾҊ+X4M;]`sIwU[}5vRO-PX{5XIZ[tiP{F6I*F`l}79M߆t7~ޗaH[s}8KQ-.wO9睯9衃 w~:Ӥ:\>;(m4;x<7{Ԫ#<&/K?}6ʌ,klKq=᷊ã>cJf}>yP?Ǥ޹D}< i4@Ā | E;ā d r+DKJBhbc! c8 O6!|N=a|(!hD<"c$2l949V%^^Dܴ/hJ7ų9Όn|Pe( *=d[TK<򱐆\T1;Nq|$$_@bnu$&3I PdX QF!(IJ'R`)dd9%&gI[NDIE\󑺴I"IR<$7ڼ ~մmҔ ϴef&:(NQ*(\:FD0(}ZN,'Z>?Wr΃2~,]C#̅J&D-{(GMF3+})1?Ҵ)NCE{$)P„A=*ECNPO>k+DrUwr +ձ@kl&Yʺ3<L XZîʳݘֻYyϫXe}T·:lF_v/vK]YnAƋ3[).A<S*ZYkX 3 .0uݟ7&{W,~R$øƘw$`xS"{,GL2po[#m̨wqP2_!m2V帕%,ìf+E*x,#5ŘZW~Scؼ2[3نR%hr#%9XҖF5|M(ELsK\Q[%5aTd/q @Q\l]ۉּ| a?H>eH~| iGԾvvmSGs qF>n̍uB(-nvӻ-#9³fL[1QTYNd?_xtD"s8p_["&Sc~y˼AQ#mU09O!H:l/&C9g:Ec/|+~\oC}_/_k?~1/S|_˾യ=qZ^#=}]\3g|#g>=|ܟӯ׭ۿ O{Ͽo_kzGߨn F. 5F M ^ ebv`} "  `y` f. [ v_r!E@/8Eh`vVRF;SE6\ęH.T`\Rǽ sM ڡ,ա !~""ڗ"."|5#$FyM"%z%^ue&>'vbr}"((o)*bm"+Ɩ+"kŢ,-bh".b.b/Zna0c1c2t5 J#Q#2Z5fj 3zU8>9#R#::cN;<#L#==ޣI>?F#@Z@DA6B&A-$CC>Fnd1uGH*$II$(JzKd&$LdLd`N$QZO OQ$R&P.%SS[QF%M%UzU^eVVWve}%X&XYZ%[[ ť\]I,!^^v_n^l;faRXKQ0_,&EALa5J)\fj&[^ &%hW_T6f&l^l&զm&n&o8f_ դq `r5)oBtRg(DNVh\(nht_ ݌(ms'"WP6 MVhoV*f.'"iu٨2 6)<) NT f)li!g,,5.-#D0\ q8t/{$ 6B95567FPPJIIJMOPPPPRSTTTTTTTTTTTW\j w~܅)Њ0LJ-*y,h9aC]NbWydbrkkponpooooooopoopklt_aPV?P1R&UYcqvv~^!B#+$$%%&&''((++//1111111111111111111111111122;;llykd_WNHFBPhٹ֦ԗۛxƛ *\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛Lϟ@ JѣH*]ʴӧAwJ=իXj \ÊK֩We:֛ڷpʝk˷@xmVÈ+F BG@1pdO MG90s^aFM{a=oU݂u Nq=gM?::@w^hr#!|`ӣ{;gN$$ +X]yF(p%NteOݗ[g"vȒN74by(4"Yc"X#uV\)Su?pݏ*! (-ē,ƈXfR|ףl%YǟshS=7&I9$ށx|Vc@y7^\%fMD$]Њ+ J駠43yeP~n& nwg AAs*C@}yMG(F%GkfN;dg"X DII%,D? Rދ0ׂ@u&dOnjRۙum Lĸ,- 'ãd(1cA=M* &?('N$[0zOI/>\6+}2a'LTXO5W,3=SrwWְx$mtHeh#崳4sMʌq$63zwq[Etn8NN{ u '5 Z1[N.KoLB8ۣ7߃jT77oA_oiK?WfM[5gl?#k=GU+T]{aN/?]p»:?%%@rS]wl~a}؇MMz`b8pE?zT'B1zX{$&1$a*P'` aP^F̭, Ǻ>Dtx9JL7 2&B̢)4LJ$$tP.2ದ™Y{\_GC ;kәx61?|%JFss4# h%FLj%jMXEK-*e%/`GwZT0<$ BTH5Gv$s!(0rs ik! =텫Mo-:(۶S_oߨ\f{p">C8Mqzj-6DG ryIj wȈ]$/*u8\ ͌oR,,8~>]ĊF0ݧ5ۜ08PX!4Cm[mn:$Fy5" YrփÁs~},^~;v$Dy6bߝy9RXnÂˮr/Ԑ'OԳ^$S֙ZM:/;Ez-o{*3{ǷƛRˀ>:>{/9ejv ^}7F።i_l'n`'|rJ|r7uMs>WeSؗ}J&Ny\A~*t&iss{HX$}W~D9dqGx!W=LJ~n+xkJ1h[L*%-08{yn'1rFz1~zwdE1NXMfwNXZ6XyQ/U7nD(rBhhGx#QP!VW`~`y:(g}w6ׇ5z|8} hvREL!Z6(X&79xZ4yȀd(~}Zi(5\ׄ7ofǃ*:H(1ȉaQ$-T_uhx׃vvv l؍AXhGcֈ8Xgxj~ hX1!y WsYI\Uw9#Ar6'GǍoo YC$y>ŎE<(CF猇K!6XrZpqTICrCI&rvHXĊLx= n[ FVyIytXrxє!a>9:j8~j9H{GI7(t(QQ9i8nv?H&9:%9HNɘ5㒅^t7S ٜi8sVKq,iz8\8:驛єM}R/{W0q4cYi'٠^y C{PF;A|!ɚ1])zi1y~Atc)2fSʘI2&1ɕ)ى;8ʠؖq9$Z Kc>Y`1ʙaJdyW4ڙuѝ؞wbi3 j y¢}Ar!:C_i5yz7'"/Iz8:Ln)Z}ژ(*2Iڦ#i|]I:z6i4*Ǫ zڢNJZ g855i򪖡rZxBӫ~ PPzIz/tpi#>VtcMxz[e ^4{纩 㕱/3_yp4{~q:<Xjjm2I :֪%Q C:<a-jH\9[oZ$Cr; {ڵYIeH$qpLZ&XZ!z'JxV1>˰oۏVZ<ɱwKы(Ij崾29i(KcEv[+ڙ웻ڋJkbƧ쒳ZiF-Kӷp )᡿qCK{#\d̽x_k;+Ñw)&d~"g&fj۰:|D;@1z>X\V|Y?5\ ŢK>F.kK zKƁd!yʼnw|7;alz·ؑNlcȃ˿l&K\LK2A|SLʀlåh%z/us̟z;[[ǴLbfY' ƅ â,̬,<_vkꑭZx,{\+Lǿ잿Э4) A\ċ'jl-C}sVyA@k3đ"<1|ؿ==n >l1N h[DƦܙJ,ӠLc*]-ׂLgN*6}Ƀw} *T j}xIl% ==w)v]+h<%ږ@ңԨ\YڵI}⽉a+^m8ӕ=]}؝ڽmymyl""k=u1{+M!Zϵ}-%޻3 ]Mw!m|s/ c[ Ṏ sC04^6~8:<>@B>D^;͐IK&t 0#0MR~A~:[^S1ASnåM*N״kt8^z|~>^~舞芾w ?a%aO^`nf^&P{t@`қ."ֱ ^8]~>^~Ȟʾ>^֮v ڮ^NUN#^&@)NaQn`~ۂؼQ,'atC¾?_ _up $O?AaPNP.3._0(057O2~?-?CO!=><'~M OZ^`b?d_fhjlna_0s޾"4#@HE9a/G! ~O;*p+w}n^=ҽXZP?_t ?AwO@OI/)! ? a1/?oOٝ 43~0PN@ DPB >Ȑ/\ĘQF=zQHDQ#4SL5mzh&̐;5Nhr$:Dyf% I3"u2gTU^9VX/¨Za+ NFEӪg^ԺU[u}O/?|}՛7/^wܵkǎ:=Ydʕ-_ƜYfΝ=:2^K jɓUNE[vͥLNTۏD~M;hQ_۞\yjy_uخfZjtع.^ν| L0>>|ǟ_~0@$%(X*& 9/k CЉ.p{+JpB }:+(C Χ`X+nۚqDLk/t3o2K-K/3L1$L3D3M57ݜM I=A>0*9]@1MAQCiZ utOK婢qʻ|t*S|Kԭ>4UUkZүKLsIJeQFcvW_6Xa%XcE6Yee^٠%hg@I Ul|:6)qo\:փrצmǚκ-j,^URt c&_(2-c7c?9dG&dOF9e8gqO <Yu*jm曣* ιivlU j}:&)JP+`>rɅcGJo8_xE7on;ooэHb86h@8HBR@]绱\ kIIKhx$dTv8,E29JÔDe*UJVҕe,e9KZҖe.uK^җf09LbӘ@,ȨN`>v>x׼^\<(9NӜDg:չNvӝg< dʤ"]R.xI,8$U*9*r<|YX_BW9QVԢhF5Qβ12D>Sx" hUQD+bqpxhKu꓎ԧ?jP:T0XODJ'ygԪybo9jXSRTլgEkẒDW"MFd]zլ0; YuZX6ֱg[G2PIşIi;R% yS20EZֵֶ8!;[ֶŭd?B'JH.nlY*Z-5-Pۑ&ºŮuWkֻox{QzD,puTdX ݖ l3@yS E!<`#"o&ǻ`7eyh߶hvMo]^Fl1 a7-pg*;q&Kl.7&Ng(x}W Z¿%1e$4 ͑+@V(@ 7`3Fج3wȠ5bhD_n3#f&PБs/-69sNg8ca0g7's_}=֣3hҦ4u*|C#ӧ<V{lW69A |pJ@^x_pհ{J%DV.(Kl ˥2;qj364b͠H  =@t܊_rN@G-rӇƈ' ,_Cc|济$sQZ*>Z|?"pjy yi~ DH5hSδƯNUY6վv#,)^dL`7xˤ%i}M,;J,-iHcӘiXxyNߠwt[3(.ӣZ/X}\gZ71MtOѴON|JxFNؾ_)>ػj+;A;4S9,@Kk:ѻk[S>:hp[6#;> VºC69*3;F0VH3@c3T:6|3e6<c=:C#B$+6u 7q%t (؝{<|C(p /3; tB BD463FBCI{LKXX9F3FMS:X#F٫8`ܽ@ W9 ?h=mEX+^\k a3e4™B뺯CS% ?0l>Bec5=ܻ#%? Ku"8t6=G-«sT򼫻Gd6bk+\ ;>,S5T>`kJ:;H=$HȬ3ub?F%GDDJ0OĘ;kJ E"EST/;:0C8+:(8H4@,A\볜+4'Z\6F$;̺D8{5:V3E$\#u,Nd\u5!GTJ:|SN3i;6K D¼llLDde?;H,L+͂K4I$Sd1Es7.5ޔ[<\D5=VF=rl:HϾ$ZLQI;5QIK=+" 3RA!;31͈,5_3fB\%0Kf4}:\G:|ԸLӴK5C-"LLkT LдFڿ2$Q2іD̮N[ I >Js:UP0K\U"&@XN5c-Νe4JWFQT#lV\Uˈ7*G HAaLVS' f;>z]`5^ ^ Fava >9`^^U`']I^+!&"6#F$V%f&v'()b+,-./01&263Fc1,xޣ}K 4=>vb+@A&B6CFDVCn`-#$c _EPVd@R6SFTVUf1na戯EM6*o 9ا\zeT&oq&r6s^bX2fhKF{mnF}prgfiyaXjg$g.莾ʀʡۚ,[ڙ;h}Mi)>zz ie:d[Y.~mh集ꩦꪶj0 jx '\6MxNmjaf뷆븖kf j2fze֓kFVlN&莀`Fln!l!&6FVfv3٦ڶ6N7@Vfvv?tjk&JDlKl+f"vov%N 0v`klVo8ooH/p ~o" ?Pbp ؀'z6k>ԭej $p q!~ !'"7#7'X$xVpyؕf`q>QSTr073G4W5g6w7yP$7 kOkr_@_1Wt%s+1HIJKtLs%sn7Fnqkd>Gtxp/OuXWF7Pw[\]^_xs$&wPI=keVG7trk?\Y'1nC?pq$rGtWqa?N= 6jUwWZmvqǺs_wu/Wwvtߓy7pgWꊟ~ ~xWYm? y(xHh&oDAlOIØy;l{uy/ww7:wyOZVN zPW V0wVp9v5v(A@AO7w{'{'{_E{h/bK{o`qԐRzv.Ǘ|`WOQLsgO}'|/g'O{__zM|⯊W~v87ttӟ~~~wy~PbSrߗH(/ȟɧXHmVI N +D^( %&0(qA7LjF,id7Vl-2gҬi&Μ5at-j'@ap0)Ҝ%*֬ZrW~՛t缅SLRE\.޼z/.l0Ċ3n1Ȓ'Sl2̚7sfFf<:h53Upjڶ IR07ALNt]7MK: OC[יvǓ//^,Yhղu Wvӯo~? 8 }Rh) :`iM@Hr}N]GٷLE݇:"UYi[qe7#=T A 9$Ey$$QJ9%UZy9` QH2UT%$Pc9'2z3g#9'}%9(z($Ko'J:)ityR@5U_g yw'c{5‡z+Q+됌7s,*,:,͚ awmzSLS#:.a*{4w;/{tI8/-I'}f:'hنM"P0[<1^<2% `-21<35G_3t+nz =nyƺn'K=5U[Xk5-,gK LU4}؊ 5۷& |6]}7yh]_Y扟m&B'u;.n|N?~^{k97ࡋ61ux199;FM~;^;#-a}-#}/-[k Xn֤0S5%}W>r? >c~r6Ѥg@c[X?Q[2صD# FբI&Jk7J.|! = 0>aPw|Ac!B0!D̰Nd 1O&C۶|8@#r1'Cؾ%fTL(* 'ř}bcL(?zg# ϘF5Ґp E8y!ld% $&3 A2LwHԡ%8Iۥ2v|%,N)XJ,[UQ%2Y{CGx4F;"VS&8Ù7f63x\$"KJRSo&MxMYNѝ3m3#撞̦GIDР'D#J/}pY(YEQR[shF>M&=(ZQ]tf*Pt"cMҝ4I*])ZJ|PEuQsJVR )T 5|;Uu1NU SՇJf\U )DTȋNH}aO]-vֽ53TM*p)M ]U_#+Y,w"SmV}ǂP=-jSYthRN~-RcfÓٚ&ncg[&WN}d}[k'-@w6r.+^Jw6YV8eE(JvjyK:gqW.b}t՝ԫJ,(= 9)'ep/t-)#چ.(C߾0#<t"t[w!3 1_jEpA(VNf:2q^r Ǿ[X*llϕ|u3=~3\gU7*"6Wr3$I2_43MZ*|t] 8ҌN6ǦΔ~uzкֶ5s]׾y MGJ/dV!iS־6msA^} ̆ײ]g{1K<-yӻ7o|ӨU^WHk6SS83s|7sqfҍ=;!Ӽ6y+bIܼ4oE w "+gʟ~S}{9щt\YֿuzN KNQoW.;}xюaAL0 >;#CNNoʷk~+sdv?=I/i<ao}WT'&珏3_sf:/S7M⧡5_i?:|o[KooVG:_iLC:j- EZBW1I՟RI| DG4DHB0C EXDVȧa HՠMlhƄ0o 1Hl$4m2 N!} ftv~D]!aȚt!ơ|Iٕ©B!ڣXXJ!"N ė S" FXZD%^"&fbLI#~bVJ")& ! + Q*|"-Jm"/"ΐ-N"ޢ1" #4I2229#F6NU* O5Zac n#9 4N7# ;9V:c۱##>G<<٣@n>ZV?#d$C^FAA")5ENCUDJQ]$H>FFVFrdyJ.HUI$MV7LҢL_M`JdNNvO_eE PRYQjRRS6e=%EONe9UUVV$W6W~内ԍeM%-%ZZ>[Ҥ[v\%}JޥZe%J`va2a$b>b.fr5=&HFQfZaEjf M&gghZhRi^i2[j6jjibf&CΦ'f@fԦopp $qq`rFrcsq>REM'>V3a'jq;z7';'Ng3Ƣ:"-g9\'|:zR}#~~_Fncπ^|6"jcZԂ*_YFOc> cBㆲTvޅ؈cnЉ*bՋ]XMgcXYcn~%hi)&U19A))Ji,)⑕bJ v}遅i$i`)á)) җ!^֝[מaN) *x jjk!I682:j*Jvf!FZ6ק`:"*u*Q'j"*2"*'U*}"֟!":)36kFkjrak=qk*)^+ֺ*軂>(Ϋܵ+++mklZk+ʥ 6l=,ElNҨ^lR:lr%ǦǞla,h,ͺ>:,c,ϲ[ mehU>[*-mb=-ԦJ-nQm^YE>֕؆m^X-"'ޖ:~NmNSmbm-s!Y.HR-5ZV.<]nMe.m.":-躘莮0y.In^vn$.Hծ.z-ޗx26oCE/.R/=YAa}M/.*vVM/sůoNiRS]/(0"+'2n0/?"_0 7m0ju+W' p⦰d0 ?_ ǰ Q  G pp_M Wi)aG,q+UY]1K!qqYWi/aCq%ϱk¡k /  *!6-.2#7r>2X(Z2J&ۊG'2&gr((Q)_)j*[*Q+(rղD2../G/qr13>1C2?237sE4R3 ?s6bsi3,s{32M395s:;󊼳383=g=>+>sx8:3 t3A#4*,j:AtDKt;btFkrtGS|E4&4IGߣJgK4w04 ŴLHӴ JE9[45 4QOR/PlS5H2:tTSWu^,h9XG5;& gԨLKT̪/vͫúWSպ:a:Y:_9##sOO;c7"bkde~{]W{ŘkQWt?; Kʽu˾ۻhgd;ND x>һ> >>w>gS~>'~tW?3s~C[@coӾ}c@+?þst;Wܗ|3?@8 A~՛t缅SLREeԸћA9dI'QTeK`Ɣ9fM7qԹgO?:hQG&UiӞ~8F:jUWf8eW_;lYgѦU+`… FXUkջSGֽ7ɬ>x߆Kiϡ=zuױgGwwG?|yb;i7~}{ P $.=D4 lp8 P )00<9[:P9t+PYl.PF6DqPl!C)A{R,-OA 5G#-՛I;MU1UUYiUTS!E]y7MZ-X1qMVRam_KkUY2uoM=sMw)m]r=>Ch CuߝmWw-4*N߇!7`5lQJUϋ㏯bdy5d@nYEWyڔYyYјef|~祙y:+=\kZ_|&YAN;BW%#L{#,moO\#!+1wmqƱrY79]Ut2O]u6aTt6-_]ݓjuq>%Tṅϝ_wwC3\z^|~Ok{73z[Jg+Nr?.s%+t` Ⱦ2r 5U%`" r!"ވ2-[7$ I\Cw2?bC DEl]!QK3$rNNaH(neSd\B, \4cļ70c 4mlG=k_G+!_HAtC IcjT$DInV %/ L. 'ePoC4+ʑrk%aK<ɒbnC]N/`ސ1ۅdo4t5mIs ή?龹BqsET9t;xBn$?O\s'PT-ZAN4; -C RE#ьm Im\t%M Ja*I,ŚKSj$)q 03SMMQ˄ԤmsUUnMUV2I\WV"e3k Ε(mQYj}]W5|~5,O! ba!" t"YL##k%R g}@6%M[Zg-e[vfE nF p'Whr\27un<Q.w؍ׯzYZ㩐{#s^6K/]R)4]}?FUO`A'a.ofKw;;j86ϑ&n bG,`Jŕ)ǐSqܹ!YƢ iL$_EKTe)VFg53?s???sܓ6C:8ӈ38A!Za"a@w@@KtAu>HDMDQDYa E]E't^tFK0T4Wd@AsDitFQFݡ4HatEm:s4Pvdznjn'aB#@ "^tFICMmsJ?>// #nP.^OOOtt84]N1s/O TqAQEuT? `JuSݏ #5NgR19? 09Ta@XuxWU#1VU%J9W[>YP 5@UBu[e.4\ [YiZ-EZ1Z95_u_T .@ XPaõ__IUMbՃa5vc9c=b'jS.ցaeYe]ea6fevfivf!drd1b-dQ9!guJ|V.8!i6jvjjj8۳hg&i6*:!!:Ab6J֬z`nnn6ovooo7pwp p 7qwqqq!7r%wr)r-r1wp15s=sAW2`mAdkel6-]7 uewvivmveP7uMa.X7nqwxq%vx7ywy%wUwRu!xwzxz7{w{ttsym{*|w}ٷ}{Jwu7|w-}7}7wwMAeaV}77{%|bGU "L|!xzExI8{t㷂$=al<7m8uxW~U,X`nyzq8Xf&{؇,"!AV~du8ɸ8CNҘ8jN!Ft""f88ػXJxρny!9%y)-195y9}@`IMQ9UY!`]ٕ imq9uyy}`GYg9yYg'8tdD>!57a4!9yٹ9y鹞9y ٟYc`͢ Ljm z @tߪ9bvoadJ<RMQ:UzY]a:ezimtZY#΂ z$:=^ 8wndMDaC:zɺ:zٺZ ֹ ڸ Zڡ:☐tm ;%{)-1;5{9=A;E{ՀL۴YC `b u X4|an9;{;{[ >!Û56 *im{$p[%3FT8"A<| <|!<\ Y<ë@KᛩX!wa}vumq~ @] " }+Ooi;Yގ[/0^UmH?>~艾腞f|YCZ&^پ2f7%DSoY>~ɾ>^`Ycܔ2osHu ?  H' (+ ➃ ܦ@%S]ﯞ>7޽| 8{]Ō;~ 9ɔ+[9wy@ԩ1LJjM ; NH-ǸTn>ċ?aNt@(p(Ї`yUA}(.c2H~ވc:c Rha8$q bPdiID"Ibո_GZne^!,*.#22BCM$BC=mC B"*.!ZY ,,-B9M("4KLD,,3ғCKLW((4eC:NȺ ҲɛKF:3$abl(@*T(0‡#hBŋ la ;<ȓ%MRJ-]SL5m$΅=}LsC(E¥L:M`Ӧ3 xf[-B Ԉ=0ڰl}Wu -^5) zu fAZ@Ѐ帒0 @ A 8@b+ 0@@@ .X A 0n%!,:22BCM$wL #>?IKLW,,8((4CDN..:L33?01;abl@*\ȰÇ#JHŋ+ Ǐ CI@%S\ɲKQI͛ ɳϟ$9 ѣH 4ӧPY6@4իXsܘׯ$A]E!7x|uKKTLVǐIq˘=N āC8/`S `uW˞S0`ڸSoT Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)diF2 1l@oYМt'  4@q*(hzhe0虊£eFjiA PiA 4~  t0j+A ڪ,h@vP,\B !,22  𹹹  곴 @*\ȰÇ#JHŋ3jȱǏ CIɓDɲ˗0cʜI͛8s~TRϟ@ JѣHyDʴӧPJJ5Xjʵׯ`0`lسhӪ]˶D˺Kݻxm7߿ @ƒ+^̸PćKLe ˽̹ϒ3kMj=װc?&۸s69 з\ē+_;ḥK8س/Oӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬѰ*무j뭸뮼+k&6F+Vkfv+ @f 0)@++{/ŻX,Wip  CqP\qG`2!?I<)K.ˀ1L3 D@0[s , (KG !,+bX22#  >?I 곴@*\ȰÇ$ŋ!01Ǐ n ɓG P˗ U ͛2gּdN=)У `ӘJ:ӫj}@ׂ*D%@ׯ#@0ٷ,p`@o;P Ś`uW`ɘ3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNzcN|;w޿3/7ϣ׭~=mÏO{>}w{y4pu !,cD22FFܙۙ>?I#FFsۙsܙs ݚrGHSFGGsrss&&2))5rrFۙۙܙFsrFrۻFۻrrFFrrrrɳGFrۻ++7FssɼșFFۙFrFF00?I@AK GHS&&2))5,-7곴++7#00Zh=Lj;C_74M5(@9/@'M[$j,}, *   8@EIO^n ΁˒1Ob}qxwttookkffcc__ZZXXXXY[X_WeWsJ̊B3,%27?CGGRdq톳֕ŻdzȢ˙ΗҙԜפتٱۻ7H*\ȰÇ#JHŋ3jȱǏ CIdGpnԨ\ɲ˗0cʜ 88sɳϟ@ JQ()]ʴӧPJ*ѫXjʵׯ`FtCٳhӪ]˶۷nʝKݻxը߿UÈ+^xc#KL˘3k&ܸϠCmQͳӨS^ͺװcs&M۸sg5YMȓ4=ivujtνwφ+OuLƾ=˟O>ϟ&(`H]c—qu@,7ItF50 Z $t]d z(4h8<%ab "DiH&d`rPF)TViXf\v`AB.iK6Ћ=pa" #547Gf׈vs`t"H^)=XjwA4>*ꨤjꩨꪦ"dA\̬j뭸j%N$+AjЧF+V*v `\d(iv^.5iҫ v \%&pdG,>61r&M"GԱ 7CRD І IBL$!xDE:҉76l&7Nz5¸(%R@"8!JL*%&2J-qJWB $-My!RVL(LɘȄf/3Hf+0M"8S݌^W2%l(SzBI'q5N=*Ve)O)ӧ'403] iU}ue]k*h*UC'i6)Nә.5HBYP6ԲlD5;QzDP &$=i Dtp⮰ͭMa5}^>uP"qI\:}YUX~SJ5'[]dVW'h)MxT]{m~Uk%B pLy[;wb "[sm`smmŠ$6.Alg[@Xf%"E\:da SX3#Avw"HNтBX1ÌeA$D7ψH3% 6Xߜ:96ӌff2o_A/$4*:?OZL4#fP{~Q^^׫lA FJЬf6rgD ϶-BE8ut`< Q&l -/ $Rpx܃RrAcM^܃?{qQ7;,N&K֊q DĬY2Gl7{GDZ0ɛOj}(KaPysLkв+._\}9=V$̕W) 4Ao\$ɓ]8v?زwdB\h @ڮr1hxw rT x*ڳ]ed<>"B} ̞_,AқO}1zsĂ,Vto;{7P+*_RsW)W{Z>O/+ $oo֫dٙ~uBnԱn<+~l۠wv~'EYЀ8g7 y'qtEcz!zlm怂oF~~yWDuL2K4trU@NT7r9NCW5U&NLpO|N]ne|*7UR8%xUiftTM>}55Gz,kA%xpVvywwx|m&GLnobw&o~vxU0xX7E#4( pq!Rgq~8@JbXNj%TboW(aj~gaRc%F&-V6P.9ldwbsDw3p8E YVّ iXAH7+Y rcP6y8:8 RF@dc64ɓFyFqFQ$VR9TYVyX)xaD~`Av .!>@jlٖnpٖSBY`M8_ڔPg6i998fLw%XZyԕbYvy,9Y Ɣxbpyy(9`` 6.ٙ750ʹt\b6ɜɜy!-YyY7sp isٟ#FYJ%b :0!Yxxߙ*S6p ОdC+jbZ҉,- :q2+*  .Fz⡈4a&q2TZ=2'd2$h[:4j`zYʥdj&^z00bjkOzp:tZvzxz|ڧ~:Zzڨ:Zzک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;[{۱ ";$[&{(*,.02;4[6{8:<۳>@B;D[F{HJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@Bo)w^=zP;n ڠ D^&Σ%-,&2>4^6~8:>@}`D^F~HJLNPR>T^V~XZ\^`b>d}hjlngA`t~xz|~>^~舞芾>^~阞隮vN0Ң>^~ꨞꪾ벮ꐾ~븞ZX#3=^~Ȟʾ>^~/]뺾 VZ4 :>^~:4Cc4`>ҐD?_ "?# ?(?O>4pI-O N:<>@B?D_FHJL_'P73? Aտ3IZb?d_fhjlnpr?t_vJQ4x׸4X@?_ z/S-;fv@v ]?_ȟʿ _?_g4`{ gW =_?_?qa'@jm@PB >QX,^h.V=~RH%MDRJ-]SL5męSXBTPEEX>U9wU^ugU]~VXe͞EVZmݾW\uś?X`… >U9?~XrNʕ-_ƜYfΝ=MO&ҥMFZj֭[O Yl!,B22BCM$CDBDӕҕBCԖA֗ՖCBCєmDD oDkqpCDElԖEDBKLWpBؘӕՖ,,8mmDnє((4ҕטlmpӕEnopBDӕєCBmnlϓDkCDNBo..:DoDDشծln33?omnҶlDдoԖablCpCDH*\ȰÇ#Jh0$3jȱǏ CDDɓ(S\˗0cʜI͛8Yɳχ JѣH*]ӧP%@իXjʵ+W QÊthӪ]˶۷p K]W ˷߿ ,È,࠱cA\q˗Рϗ (MzSCװcvۯ "P#q7zH@Sa9ǓS!s{_(DO~ :B@A"A!}Eg~_}2(`8p1qa`P_}B'Y!($H+1P8@>T¢;`Î+b7 Dc)ZAPTVIhl 5FUz%W9HXɥxRD|B (@ E#5衃Ǥ&mt)N@ND*詁n"b1N`BTF "Z!s􃬴0CªF j 4 tmb귽1k覫:2I "Pl&4G,WlqG(1]/ ,$l(l,Q1H,0`8<:IlSg|L7tD/}G`XS a\-6_=S5lvmMr=vjkW ߄C wላxx7G.Wngw砇.褗n騧ꬷn.P箻{ Oo>@'|`FO^=|`=7>_TP~ë|㾫n?H@_}8 vRF@",898h !, +22BCM$C  KLW,,8((48 CDNB ..: 33?abl)D@*\ȰÇ#JHŋ%r!Ǐ CIG0ɲ˗0cbDr̛8s)fM@ JOH*]ZQPJuԫXN A֯`PbӪJ6ᄳk6sY7ALXd,Р">ʐ3kv8`2>7L_hp`Ӱc+XCۤ%8 Nȓ+_μ<.4tsJ{ܽX7y@A7>Ͽ={ڷB~7wg] vFg!eX!fH!,y22#BCM$ ABL@AKGHS&&2 34>ʛH곴H..:>?IPQ[:;F"".33?**6?@J T@*\ȰÇ!@00ŋ3jtX CI`GJ\I-c 9 a͛8uJ@6X(tQ(,hJuO#Lʕ&қv*R] *(v- 0燺uA@(H0ثJhL TA8!NʺBH͵mު}Xpk$6}]zZ=zׁ;sWe>^9yï+@@!,t822TTT 0*\ȰCJHaĊ3Zȱ#A +^ Ibɓ G5D6J7O9X:`ps?fyA^AXBRCNCKDIDGDEDE@D=D f;l! Ȥri4ZH]E) 5V5(j뭸6H;k@:i:2kf'KPD !쳿vk;B sԐ  lkjPF-BMS &,F:᎛m媫9 |B32X&#*oo  |24#:@ż,rŵeL7MCG-TWm5ȅq5N-Shl@-pNH6|7#n'⊟-Ԉ80wNxh{WnM#ꬷ.8RCsM,@츕^ o7oGWIKo;w/Oz䧯~拦q/jnzU=rw LD:'H Z; z=1GH0HL W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBZ!4#Ni'ȴ7N{ӠG}@"3NW]԰gMk#&=^Mb1)f;ЎmP؎<bRMnqsH&7}v;1)ܱzUR,*o;aROpBo; ;B`^0 9;ApHW򖫼Rdl! 4T#@O9;JaR#HOҗkaV:S]Xm`{ :IshO3lR9u%PfO7LsO`p8 /S^7yğc&9:OG{j.ogwAO>8la{ЏOGן.^Q{W1)O`a nhϿWj'V'P ؀`i) 2h5B!,Y 223 @$„:T(qbň -fEAvȇ%!,H`@!,22\\\ߜHHߜHH֕ؖopDEtHtΜHHHt [[[H*\ȰÁ Hŋ3RT@Ǐ CaH L\ɲ_œId oρ: JУ0"TѥPE6EJtAOj}8h fJVaWAt8[31 Kw: 0vۿΊPpCo[|PAePy\c yąrn0"5#=x_&p D{vT˗6`Kl(` ޶hm[@]0 (@˘3W‘'Sw` ̺ǑͶMkc,{Cp@}8ě7O[7AC8='Mvˇ+7h!{{0XA#g'd 6U`)`P P!BD8PX 'x(@ #/ $+!,|y-22BCM$̪\\\ KLW֕ؖ,,8op((4DE䨨CDN..:33?[[[abl@*<(CÇ#JHŋjǏ C:\@ɓ(SL)˗bʜI͛6_yA@ JP<*uӨӧN.3XjʵTödٳhӪ]طKݻwSP˗B (t)TX#G4rC@ϕE0ɨBpװcVqClS;(!ܨwP!̝8hνӫ_>x OO?_o5@& 6`u<`f^8DH'<(: HU !~d4-H@VC>H6 KBdR .I0UCXX$A[.%`ْiE©KlY&O_ʙigRqY%'<JDjfzԨ7 nVjD5d)r Ԃ@&DPjn~b PAºjjub 0¬``B+ЀJAeN@,yx ^ 9 P@!,=22BCM$ C KLW,,8((4CDN..:33?abl @*\РJH1+jܸ"ƈCnQI$K\0J0 @(@̘3Bye΃x4C9=@@҄0W"*Ua(@BQKnn%\[V&,_ ,qAȁ1@Ctj}VhGsEjP 8t״k1WsLwiyxy!,"22^^^BCM$ABL#F KLWsܙr((4ۙ㿿*@AK,,8,-756@..:<=G33?12{xl ǑUNw3@[dҫ_Ͼċ. R5'h5,`C~_߀` 6_7|jh,袋J 8,`#%(Y-L(/ %SI0# I*#\v]@2 -`t@1iPxlpw :6i:*)HT %ߤrdfF3駤.$*J*v q  @@!,22x׫xrԎAԇOx~mx\ғC Cx#Cmmrwmmm_rC  M5mCCm&&2VTCC+Qmvtѐe1/mCGx|qxE4WmgGHS`$ 3:m{!CQ-z++7>?ImCK(ObQE˗0c~#M1ɳ._n m'(]ʴӧPJJS +ʵ+W0M K,&`Z pʝKݻxkLA)+^X0#(A}ZϠC)@ӧ˄^-d.gSάAÈw(0rv]060mŷZ~=8  ,]Hw]bƇ c_Q;A§>e< |H/ _ndp6L@fw` 0 %8_$4!h%D`$bhH`@!a_ P8Bg .6ĐE9bJ޶y!cBb萒 i?PiWbߒ sieuFHʹpoyY i嗖0fg&'uN磐't zЩUZeLj qB ꨫ7j?q;ah q!GPC!~X-ZYbr G)Xk/zdeҭ@ 8UWlcլ.-\W8Ld`2)fwLɭ#-DoP4GCF3>tXguSX_M!G0Ha<6W-m x]ŝEz~nx~]AS B덲881k>9yzXoN:fC8 y`{ԪΓg28ä< }._cKɇ/y~Lo?d p )`@OtkGI~4/ np+ h zS h9(@~2v0:P*v 4! ADQ DF0 D-.!bA1f4c(A5 t@9?=捏#I?Aҍ:4>EjXd! wHpC 6Mpw/| #G< Њ$`xCͮvoX#~QaJBSe\);Xed&}KNB02hJqCfMfҙ%AqF$4'љBuFf9J=fSq;(~~b{Fanqd1:F v7|"D734 U(0uYn_z˓>S͔!Miq"m"4kyFhԑU}djS\jPsjU_UhˮS&5;/ʁ3v\#V яjT%ӚSt Yd^<,^#ؾZgX;Y6`lSQz+K@ HjWֺ_6[#p, ͖@@ MrG?@&ͮvz9Ot l`8z=z !,}6;22xA BCMxtx#mғCHxئABLops>?I㿪vwzGHS$ 3,,8&&2>?J'(2,-7곴..:.M78B((4KLW33?%%1x޿%&0ablH*4ȰÇJ\ň3ȱƏ; Pɓ(Q$˗0cʜ9!͛8sO< tїEMt(Ӧ?B)ujΪVo>}Wp )֬5װcߚUٺH⽪w־~6 _{X̸ǐ#GV,˘3kޜeΠC쐀Ө-nh:kЫ~Mslk]0w >͛orKg~s+_x\ 5(<2>Hǜzzp7@iB3Л%<G!h"TmY'be$É)J&3Q,Ҏ1pc #>"Ԁ$)+ - @Lc\pP%X @#i |Ppf L s2 > P@!,122#BCM̎𫫫Ax KLW,,8((4ABLCDN..:>?I33?abl0@ @Ȑ >\D2p`/HPQdM@PJ 6vHr%K p8˃9wҴy`Й#Չdģ*5Ԍ{Nmt+֯`ÊKٳh!va \t̛.APJ->hd /Ϛ|` 6 @օWavj5@@`!D, #B !,}<E22xA _ Cmmx$Km'(2ғtx.M1C%&0 ::3 #?. 4!C-zops5mCClUmxvwzHXȰC #J(E3jxƏ;zIҠȇ%S} p_~Y4G]^"`}`vйvl BClgځ \&bq#Ȟxs1 Aq\(#Ig^A *('$s)rJ‹Op>tdA0Ö#n؂2\Tc/u7$&zg0/ th.tA'MZ  DCU!*E0)ۮV 8PU@!,}..xA22>?I# xGHSm _Cش&&2ғ))5txC C$m3̿CmCC򳴼++7m.Mmm?@J00<xC[\fH Ç#JHQ +jܸ"C C>QɊ$OrK-_)$M jh'D! 9F,Jab؀Q!lkVSrd*Dz=â%v(cnڳJ!{7_!a+^̸q 88ʘ+C<̠oLСG6=kՂKtV|5f؂eF\۶c7c t(qёPz3HQf Z c/h 0L6 o8G[v10 ݡV`s s9@:,1†_`>(4&5xc4:#h>YBzFb!,},E22xA C _$KדCش.1U/]$tlmm3Cm!C곴CCtxmammx3t7x޿CH*\ȰÇ#JHŋ3jܘQA@"C.6\ + A!A&jɳϟ@ 0ѣH*] ӧPJjөV*MѢ^. k!YfBM)׶R+Oڭ*~LÈ+^Lxǐ#Klh̹ 1ӧ Zְ5^=حgӶwnw훴n?/8ڝ3@䜥w vu*!^; '0@v3`[whf p p @"H~ŀ5x@E0ti()Qf P g 8@ 5ؚTB>X`i5䓏!,' 22 C_x$K.1UA/]l!C곴 a37k4@A< B >$q"E+f8QCZyPBCXbTi, @ $R) Fu`x $pp`@!,|:22BCM$̪\\\Ҿ KLW,,8((4ŨpqEؖ곴CDNE..:oD[[[oD33?ӖEҷpablqql *\hPCHHQ2jȱǏgXX(S$dIȜI͛8o pR@ JѢ;{D0ӧPJ NX_ʵkWX0`ٳhӪ]6퀫a.P@ݻx꽻؊Lx0+\J$VV0sa BrXc@X Ac˞hT9Q#ȏA">0@:7Tνvީ?>vz;_~Ӽ}H@o<` (hV F(F05Xnxc5Ԉ$]@0(. Vd0i/ tCH&CY|PF)TIXfie\vד^b)%feEj&EnƉfeIgvezj fb hgf.ʨp> DN*QX )jn*ʨj }ҪwJr"꩓ lHloR.ױꦴmRibku,z[,x+,^(˪;ki&{i-ʛ)J0 +AG/6B)'z1f c r߻T|%ʲ'`ȷUps"D\D41C `B/|P|6\_A pueKi`!Ёw sg[2SA=^%!, .22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JHŋ3jȱG|Iɓ(S\ɲK|I͛8sS2{ JѣHM:3ӧPJr)SXjի]ÊKƯ`ͪ]˶-WiʝKM ˷ߋpPx@ǐ*@@˘3Cj@ϟ5MR"װODM e۱s=qm&oͻ $ ȣK} ӳk'` áOӫ_Ͼ˟O ^ԟh Cw D F @(QXvz(b{n88 ,W/(#r18h"<G㐢D&ّ E$PVYSZhMn%fA~)_!,&22FFܙۙABL@AKFݚFrGHSssFGGs* &&2Frr#FrrܙFr FGۻrG++7>?IܽFsəۙFܙFۙFFsGs00?IE٘DDEE֕ ؖז ԔGHSo̸EEEؗՕp&&2))5oppDDooDEDEpEqؖppDpDDՔ򳴼ԔDؗEnEDDoqq֕Eo?@JEڷnؕնp[\fEE@*\Ȱ!#J(Сŋ3*1b CIɓ(Svh˗0cʜI͛+98ϟ@ J(Q%L@PJJիXHJaiKY*D[NxKl ~ [nܹ=07ϿI h&X`Am, Ac4x vw 4`(*\Ea $p f4 EpԈ 9D6 AA$PF)"|V01;n\zy9kcp2F 2l|9,'M| C 袌6裐F*餒6$=|t駠*ꨤjjlm!j뭸뮼+&h@gTQ <(pF+ P›N0=Q7dQ*-#tH)RD^M/ao{ ; ѽ WlqGl Q| K!,&22#   >?I  곴` ࠁ‡H(1P8"F @Ɓ"Gv$ʔ+Y| 3L\YRf;SYAcPCeB p4@ Hezc22@0Uh( @VMPhpX mA] W lXν"@S2G/CΜ0 !,%22 >?I DP p !A JL%&L E \B0,˗0UYɓ)?`s62bϟ6z@$=ƣQ^ U֭z رe"Yi+-ݵl^)^}&@N|!,p22221111112211111111111111112211111100////......../3.4.4.4.5/6.5.6/80<1?1C2F0}U/va.qk.ls/hx1e|3_7Yc k޳B<#^1)kHnp>vp" @ y 3%n_a3Rv0[%4upBrp:qJbDž8: du$<&[eI--桳,L#M/;jLd*[W ڲ lb#7Zo%-mK][ˈ 3I.ix8hqtFY yҫn#̋‰؂66m{k0Ǒ 8%-b H:q٘8vK"b$.QAM|"<*BZ2Q%Ɲq!9[SNEU~K0ˮIe-}a6?T,iv=(q1Tg(ݙyh%υNҡ HD&zH#OGwЃtiEңR!}jMڍQjJӱѬSkLߚֹnѮkNfѰSlY.Ѳl]?&ѴsSma_жUmeи9Sniк7nmм SoqߛоouRpy Wp}?ORq_q!ȽRr)ʻr1̭Rsߜ9?ΫsAЩRtIWҝt?QԛRu_Y֙ua_ɞ(ev̽(q݉w}(}W"cUxg2i+݄5l~ &_%7~x~Hg}VLA~ǀFဨ2)QwW}x}'÷f'f)g+g-h/h1h!h5(7y9y;y=z?(zAHz3(jCzEjG}IjKHMkQlSlUmWmYn[n]o_oapcpeqgqirkrmsosqtstuuwuyv{v}vHw|}~X~88{H|؀xhXXU886XH}$芩Ȋ:(@ȋB(D(*,Ȍ.02(4HTt@9V nč` h qrFH0x鸎ԎHxzFtЍ(zt(ꨎ)|p ؊'Y਒)+-/)13i5Y79yֈڨ?ɄAC E)IIKiMOQɅSU W)YI[i]_aɆce g)iIkimoqɇsu w)yI{i}Ɉ鈅Ii~ɘ~ "(X>i@yhˈͨȚHD)FhBIHF雩 )Ii)霹ɜ )IJɛLɝN P)IRi鉞TɞV X)IZE%Q @X :E e' pRVʡ5Xt%*jF wmt  0 PvQ5 " @ Cvz cA!T*C70Y8=@Z#k {9J[ +#k /!9Y 9 !9PzK: 0Qpj:zPI5)Yk[ ]_7*WU<KT+g$xk²?d3/pc?\ {Q < 3Dqpސ% r 0At^X`!`aSP]QZH +r[21E [C2F#bY ź\ !+ S5a5+47^3j΅6m3Ź qXkye/K:*5cc^9e:ݻu @ s1,:*sC;';;c3 Q s Z ba>>Bl=J> >֓ @u593ۚ)PAYpAd= >bX%q Ð\pk3Z jǥQ:2N<!::zEES?c$@Q?UcLD<ȣ\PdViY4:`*,etFO:+\%̨ l̻L<ʼόe<Ϳͩ9̌lX|F͹<8٬ج <#i!,2DM^hmyj]G'11111111111111112121212102.0/X@k^5z*ن+'uk|, c%i+"zEQx ilp'A k/Ak$' ! ۰zB r+4wr{R=x ű<5m$;_ڳbq+m%(7M) PGMԔh5\?䵥mdKox"5vCoWbk,w /8)r^hwy^v M>,/#鴏.__zu-OW:7N}ZyzE>Y?~oPsOS۟H@lL:'H >P̠-bz   WV( # wA@lyHHD%PHEXe`THF_c(<41jd:x̣> GF!>H"F:򑐌$(D0s$}H ,0 Q(GIRL*WJPB%82f:Ќ4IMrP1k@P 8IrL5/vBh;z̧>~X'0Ix܂:D'JъZ w # AҒ"$ `Җԥy@^JӚԥ(ўJ H_әԦE=RZ^ӧPPkB4XjQcj$"4c)JUHE* \e]@:Vulpͪ^ SBA@$ m]U:d'KYk Sf7zTXLMm"۪.plg+ۭ 68PPocVE)ni#(7( p>E-mW1FoK؀U,U-H>0R}yyrEuG(;#L&0Ȱ7{8THļUC#[鮔)}dbX (ni8)}M&A 'ÖL^ZK*[aRI%EDqV&h hN6Y~b:xγ) -v0C#ZNG;MN :FF f@8uIyj>ʰ|@Zۚ}Rj:~ǂLbfP!% MiZ1W5?NzRbxNz#؉);hO]SNxț7>ւ!+;W7G!\vާOWֻZV{[ڌ>xDmzO̚MO>%gz7݊ i: 2&O~'tRSHO\Ͽn"{!x|"R$R9%|'耍%.@ `|2 60x؁8!@ 0hȁq,2 Y0?`-30a8.8P 0082Ѓ!X*2XUHZ??k80HY_u6TLU4p%/W#/7~ׇ1~a޷'*}Q~~7)e('vqx؊[Pxw0W57} WT`jD{ux8/Ѓc(3ȅ#-XWX-7H+1`1&-Ѓ-X8 PchhȍȏhQh|GHjk6O7kVW "IRP&)tWy08d}8}a~8~r=Y('N(w`xEkX%:p[W>fiV , ` 9bqؐzXdȌ.q8+H(ЁCo8 d08 |id^q r0Q")=) Y+k((2Xz`'+GFp}=06E'xWl`'r[$`P0F')ٙ606F}.06D}iv}*R)g*p$P=^BI ~F'I𙔘I:ؙ'MgHZ*,HtIb[ (]=p=]f|y Ɂ yxJbHLڎY[*HHɃ#8Qؗ&2Ȧ[ȑx Pu=hlhW*Yq阊7k4wgoz]i-ɇj'C2F+~9P4 ~f١ozpىIi,oj ڠ'9ڪٓo՚"$J&dV E(2$ MWab=CVdAږB4(V ([(9ObڎɎ)h>,;0 H+((ȖB(ٳ 3ئ]kCJ%RЩۥ9Y,KpVkTp ;Aٗ05Y'+v皭y)u^ƪ )p{={[{(ܸ8rٺ}$xK'0𹦻<|'8ԺƯ+ha]{xz̸ )kX1H*ˑ+o(1WZ\Fڧk,2`hkIHy;)0p޻9X [c̑7֨ZiLɄ lX[;9IS} k.yJkK,9Ы* lZ™:ҚpM<+˟" ٺ:̽%˔:èB|DDLF;VoAJY˖ , F w@Ot|*+Hf _܎H؎|Аy{Ll2MYl)m:%'-ZZBUn>9>Tq֞d5N2)NAq>;C~!^R0 Tv{ !c2u{ w!Bn,O}"o.$o6-`0_d4_6+F`<-1Ou(? G?GJNPTFa۲[/]Rlb/-d/3z pi#|o,qo_ CD}X@O6nvP_# dwB븟eIt 0B/+ J[JQ_LsP3OO){/ڏtk_Mf] MAI@ DPB>Q-^lF=~RH%MDRJ-]SL5męSN=}TPEETRM>MdT>(!šUV]~,%u&ŘOmݾW\uśW/H}XpQT@Hbƍ?YdɈnsbZ"~ZhҥMF`֭]~ZذFlƝ[T`~{62Bpa"$B6(1FgFm*0G;p q$H!$ sD&dÑ@I32K-iE_L3D3M5U۱M7G"N;ēN=|3.=92 L` R<e4G4l֤RK/4SӦ⌄QG%TSEMJ6I>}8R[=V[#4I5W_FO%8 $YeedDB_%BY=C'X(7Aհ]E7]ue׮b@楷^{7yoOP_year#v'b/. ^ߔa?9d}bs1F9eWucus@ffo9gwyAJb&h{9 d:j8%=:k4GlF;mfmdunƻ'v(j'\j0Zgq;;r8M".z/yZyz?*g'|}?.Ǘ~W_8@d6ЁVn`( ZЃ E8Bqy`CHBu& SІ7 u'8bWCĊGɘ8E*̉3b*vыb䲨qgDȷ11}ic/ƽэ3lvGB5~  Aґ "Ed&'ɗQd(E9Nv(UJe<%X9KZŕe,XK^;W.uTҘf0Ic6әJf >ӚH4IMbӛ&M}Ӝ gȉsӘ8YLwO4:GP6ԅu@PVTmDIQvݑFuQt BGR~(͑HcR4|0-LOIStz8%N?Sx@]JgTj%T"ZU.w^kolbZXՍUldŬU);91uf9YAִym`KFȞֵhJ-`V־ֶ6_fַ1ʭH;ָ .Tv ׹Ir[Vwbэtg] .#;`}S-\sɻ^Ҙ)=z;ϸw)|߻Wy$ ["3 \pg`=(= S-qM6LO!FF<)JV27ΌWq>Z y#7A2*HnyD3^";+}/ўuHBz~?=k~kxy?R>LA_4u?ԏ>ݾT?"7ZH _~?_?c7߹, ?-d`>4?sPS2@rdmq ?Sxnd4K7 -AӲApKA B <,ElCF+D ECIT,J\ xHĹDDLtDEO,ŵ ÄY7<'$&KT>&$3K>&3¼&T3l&Ŕ"D'>ȌL ԣ8LΌ OBT*O l|O9bO χO P+{P(LP/B]O C P u1eѲQ"+Q%"͟equQ2<mR!"5Q,KB&'ۑ)*,,=.P/>0m-%S13E%U95=)6A7}S1?9ŝ S<>S?U ԎSBE5+SfڈE`T>B}.uATLTATHS TRMRHGVuQT="\%RX&_4V+Vb]bU֔afŘgV:VvV%U"mmnupMq%օ:W.\WST{Wx]y}tMG|vUC~zdX0ׂ#}GESG* HX7x=<]S8ś3ّ-5Yܒ؄L٭AٖmHuYH-Yٝ5XH5Z7 "PڥeڦuڧڨکZ"x,Z7xNگ۰۱%۲5۳5[ˬ]?#M۸۹ۺۻۼ["X[uV+E%5EUe"[Veɥʵ\uܑܳC%55Eܵ\"HٝmBXݻl=%?p0MuFݿ]]IP7M5^Iì&\_"x"E"ߍ_ H]l_vyF:_%Q=8'`H`#`f`=Lo}ߞD7H@0VVf 6aHaA !&" #H1ha`v0h#+Ar\@0: V(p3Nc@c5=11 -^.V`2>?d>N>na06Cd~@vG1ccw2LMNd(YLNVPS>eI~J%TSOFSd\d2dV.-3a&b6cFdVeV2e_,#:(9klmno2\h}9ufvvwxyx-gsBCZfZZ}gH>g>I^h8~h<>h8hAN$&Μ)h>u闆[g& iJ<96FVfvꧾ;ejFꩾ? & XeJfv芓Ġ(4ǰ>ƨ81 HbPܐ6 ɦ!n( xle FVN8]m?Ab(H# _yۅj`&6ْ^, $_&DY6F1DAo(AoCXQnGlP yY`VAVaoY!p5Z[  jd d(p(noQ 1mw{AbAp5("Pq{Qq=m7#Gr g&o!"O)*,-៩o01lnҲ/ 2g6w- :;7i~>?'!j EgFwGHIJKLtʱOtv N #S?uZu|u JZu "u)uuuU jV^`Pc'_ud\]Wb-vgGa/ubvvv`oght/pqovsmy(_wvxoS{ ~'7GWxw!,22>?I#$GHS &&2))5?@J곴++700<[\f8PA(THaÃ.\!D'2bD+z"$KnJ["|iRL;[Ty`P8s0В2dTG/VՈ@Ҭ)_v:5ʱ^'J Y2tQ ͒Ha[ M€ VmX 8`G.hN gohЁCn!,$22>?I# ))523>((4ʾJKVwx} ABLꆇ..:33??@J`ak @"$0`‡0Ň):ȑ`F;~H%1 XɲbJ'\pR"˛&hx&5ct0b?X9iSGU 8:p" 8Pu+R`  0pda  @Ih(8ZPnB Z@c; >|9͗z9g Jw:+To=]מCp@ {>hv8!,"22>?I# GHS&&2))5곴++700?IFs#ۙsܙs @AKݚrGHSFGGsrss&&2))5rrFۙۙܙFsrFrۻFۻrrFr,-7FrrrɳGFrۻ++7FssșFFۙFrFF?@J00<[\fƼssܙ@*\Ȱ!JHˆ3jXP CIɓ(SzLɲ˗$WœIGrA Ov :C D*]JgRH.*՜ hݺu^5``1""?궂ٵm@vZhJ@t%{"B( " kf',6 LTÈ9sfm?Ǵf9qo3<\f?#Z 4ޠ^@!uݡwgx P=:77 |[Q ʕ& ]x 0ÀuEBEBG}1vM( `xg"E( u: Ǟg'}<@HAiDEX@9&;RN ! Z@he$0^hlat։) &|})%袌6h DK8jx^馌)p*ꨤZ駡ꪜJ**묊*)Ҫ+FzD;j Ȋ4{l:I$E fP چ0E!`+np HB,8n[. tq .#+&,;0+Lq#1ƺ+[p"7k@!(, 22>?I@AK GHS&&2))5,-7곴++79BL008qʼn*p0G %? 2 " 8&`C@s @I @ 49(X TS4p @=z>l7XBPLJyP9hW+PP1=3Ko (CK`Bg_kgnnrqwv~}ᓌŞüƸʲϦӚԙ؝ݥ۹=H*\ȰÇ#JHŋ3jȱǏ CIɓ(SJ|C˗0cʜI͛4aPɳϟ@ JѣH*]ŋPJJիXbuʴׯ`ÊKٳhCǶ۷pʝK]i˷߿ (#È+^̸ǐe L˘3kQÚ[@ZHƘ'Zi8KF矀*(J2|C͡% |'*Z(Jd)ei~砨ꪬvF4 'J4cOgϜw͞ IBQ8F6b#IJZ̤&7N$8OjrL*WV򕰬dCȑ<$*s^ 0!ZfbZ 0e:Ќ4rpI66 8Irqh7Iob `KfPD *:d#[P2 Ef7z-B(*R9X+_Wk3<񮰍lgKTmT\&'O-AVMr XI8@Z.vpFTrD-MzW |Kץu~_}׉UyZN`WEx'L [p)89nA(NS&0yZ8GaX h@RPȰla(Õbm%X5X2ht{`qLxSMdpLBx>π({1ʹYp٭a'17xt=5t|C9ШN5 eHQ |'rZ6GO|x-r<(8S?@V'yp379L|hO;Nm?.c^ENRw6&O{C{&E#ϼ7yΓB()6F0n>GQt,W:>S}5{v=yPsǷ9̕>r!Y|yq~w^??zѓ͚ؔ>3νW$yiw+wxEuǀLTxxxEf@>@mb'"yg0&hgye;%G}Wu(rq0gu*z+E}JCX}2X~:~r;gu~^׃H-zRx|\H~_q>S.Hl7j%xS>D6pmUDCqmSDn`o}ȁ6DxhvDxvm؇6m׶ч>o(|mMd(Њ8 D؈wm؁8NxOyhVm̖Pc99pڸXmX`zqqrbh+Gq2(HH7}JtgtW@Wr9Xt(GR;}'qwJ8R.|e7ȍ(xXg(TvwmϘmP@(knD֓o_m8pm.`oHxIyv@Ј:ot ULd'jlٖnhW HV79[a)yy9YɌNbi<&"f9Yf0fp栎:urHwsg=gfW|$|ʧq9H |ɚZtٚ-%tIc9ԉəxٕyhDC2y nR)kh_O =@\A)8&ox&:Z*wL4kX۶KN`،v;oie &z(*', 9bRXGGٷH13s9:u8 vŷ^w>RDVg\'WGv7{a=HVU/:d,4fr DU )DyWr*n ;06 ٝ %Ш:Ds9 8i NZzʡ6ihaz+P|@S@(~qZ*UZ=Qzgt~SZ|'YytǪRJ: 5_ڭR>jSjzؘJi#ʦo >8PJٔiY9e9k ʉ{ƨK*k[WiKiJ,.0oo `ߐ <۳>@B 7}\HsHף^~ >^~ ">$^&~(*,.02>4^6~8:<>@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~舞芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_of Kfƍ^H0C /@?1DG$D0 )TbPEDo1Gw䱩*a&H!$H#\P$H'd&zJ+2K/3L1$L34)dM7߄3ΥpKb3O=O?OfBNCE4QE5CbЄ4RI'-X4SM7Ȣ QG%TSOE5UUWE5 L!,yd#22TTTH*\ȰÇ#JHŋ3jȱǏ C,(@ȓ(S\ɲ˗0cʜٱI8sɳϟ@:4YRѣH*]ʴ)țEJJիX55ׯ`Êr+WdӪ]˶X]ʝKݘh˷߿ LoF̸= \ ˘9̹̠C]гS^}gְc˞۸sc ,зȓ䭼!`سkx} YvOӫ׍~ßO߲'dHZe` 6ԂF(!ONh/Ua XQ\g(xQ@!,V*22TTTuH(0‡#:H"3BĨcAC q$Ɍ&OVLR@0H5̩ Nw s6|iϦB-:5jUWf%H`k^ +Հ!,2222111111221111111111111111221111111111111122111111111111111122111111111111111111221111111111.8+>(C&I#N!S[biwomve|_XRLI)G.E1E4D7C9C6C2B-@'= 80z*p"cXRF= 5 ,$!&(' *3.<2J4X4d"4m&5u-3}61@.H,P(Y$^"c iqtw ~'/7BMYūj͵yʼÌǒɖɘșśĻ}obYPFCBAAAAAAAAAAAAAABEJWk|H*\ȰÇ#JHŋ3jȱǏ CIɓ(K "˗0cʜI͙nɳϟ@ JѣH*(HпPJJիX6]ʵׯ`ÊKٳ e]˶۪ʝKݻxK1 LÈ'˸ǐ#K7Q˘3k̹ϠC/LӨS^mٞװc˞M۶^ͻ Ȟȓ+_μП=سkgH^#V!,ˣ_|% 6X_"#zpJ;wÅ Բ@THDt(Ј+jx"8C<@ҕH;id~b>0I:xbƔI2:IcG>PbIaΎA)tYR"ꠣz&:i-(П˞2Y*i禜v駉sΨꧢ9jKbIZꯣk%r86l@ N٬ӊA˶D2m%К˸h̞3,k、) oAD/"h3a+,D$ ĺz >$ v ۥ$l();o0,)%b78<@g(-@ 4'L?d6PG-TWmXgMw`@6dchll{M\am 2H6Z߀K m۹M7/RxWngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:+XQ Z̠7z +`.V0 gHڐ@ w:VG1X"N1Ja&o*R aqL/E-qhD\y4nk\MHǯQ5svqYQ@c~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{ f!+bA]S9mVη~8] |O;?# ~[ϸ7{Kqy(OW.ȝ]x8Ϲw?>7Hҗ;' ӝ[Lwљ]t\`pXR9׎tl}٥@9Nu%` s= {V»ot]٥09&O[b%ՊbR,@. ;W?ys<>ّgO~iʆ$CBQ7{ZOeibֈOKDq +50+Y8^R#5C Zָ._XI}~V @ ؀ |B 2(( j ؁`ƆP&x(*Xc-P +84G А:<؃>~PA8=x|?J V R8TXVxXZZ NHl ΰ dXfxhjl؆j8m d vxxz|؇~zHLVnvA!,V22 RA> 0L`B0"ʼn-fX#F;Z4P@#L˃/ )sf@!,O22 RAH*\Ȱ#J!ŋ3G?rɌ%O4b\I×k3QC L ҧ,ybCPj4@$ \uGAs"լ[hCb @. ղ%7$*pؾ#%LH`9Ox/d}yaązjxZ}eg Y+4D$рj~yĀ 6ӂF)@! JP@!,[22 RAYH0A\Xp `pD+QCr($’ = PeD.Y6"0yJ`OFTzd@!,\22tHߜHttHHtߜ tttRA80*\ȰÇ 4ŋJ$H1Ǐ   @C\ 1 (HɲE8܈ дI"OAZ£ Xjĉ%QJժW ;*فPQtLg8dq%xnޚ{"we` W=8.fC@!q)(٫>883ҦN}vk!,`22RtHߜHttHHtn6 ߜ tttDA8P*\ȰÇ4լ `뫢q!,w7'22<=F!^^^AF̼ KLWs$,,8ܙr((4ۙBCM=>G ,-7kɳ..:#ɣ33?ӑablHP*\ȰB#pH ^cƁBIɓ&?DɲK]ʜ9&8sɳϞ6 J@ТH=h6p!aX "(߇a AX X#+ .PB 8T0diP\@C00F 4d^9 @!,22x׫xrԎA~ԇm>?IғCCmmrwIm ~$'Tf#mmCgGHS x\3x~vtgῪΘƀȫҍmCCm&&25))5ʨCCmx#mCqxmt򐐐곴ʄ𬬬l++7mCKfg:{00@}WEa ^SgE)gQ xQTW`R_-XU +E(D7!fxZ|},:X /V8 S4ָۍ7fB+dt)%Ha"h"Q}?F9eUW_ĘB9gg.pBIXz:xDe(%CѹhD՚g>+NJzR@q⩨ꪬ H5F(>tA+[X:|:5OQv["8Vզ k!@ / +Tl&@k<l9 7o"9D.{El\oѮ$k2/4\ \l3?S;s + L7^0P!\bjԡG]{ (Mv`m u}&w퐇XnK⋿wE L!\_0xdP;  y u8Dn{ N4%PIUte`yHY.e5 A%Rt` (Č1_3LHH\~]b\̌ XUrln""6f ~8WWW3 =g˚s (Fr AȈJԠ COfnԁ=G3 Q!IG^bEQ--M'RNN*ӂ aOS3p4X ÚF~gx22A>?I#mm xGHSm&&2))5ғ txC_$3곴++7mC.M?@J00<ғmx C[\fH*\ȰÇ#JHŋ&X #č=:)r$ǒ P!$,(cF81l 3fN$ JѣH"ӧPJիXjݚ)ׯ`z KlձfrEUnv.]sp]!>]; 1w-|[DX󦸌93b?jwg~E^l­m:!U _μǓ;>ztԳ~]ܻc㩗'} px| gnA귟}5 ``G=(+W0t@@ ':W7[@!,%,0xA22 C_x$KC3txU1 :GHSmm&&2Cm 4!CCCm.Mmm00<xC[\fH*\ȰÇ#JHŋ3jܘ1 pA#5D\ + ԑ!,jɳϟ@ PѣH*]ʴiPJJTVj݊uׯOkU,ٳQ͢ZWk0R kw[ݩ8F|;pVPW`C'* .1fT!ӅE먖9SԲ9𰳅ƌ1[0\NNsJ,PA  [>@ڴ@`'K 6 r7@h* <`@!,6xr22ԇx~x\x#rw3Tvtg$ ~IwĶ r5N5qxrx Ņ8B6`Aŋ-dhqC^c(/V K%6%(ɳOHXѣH.А ӧ(JըU2@*T kc2vZ uhs]Ā8 -Xo #uJBر]|2`%:BXl#:&@4` P&(AVD1 !,Z22㫫BCM$̪\\\ KLW,,8p((4Eq֕ؖoqȕDDpDCDNE..:qDD33?[[[Eablpt0*\hp HHŋ1vQǏ C 2ȑS\ `ɗ0c؀͛ɳϟ@yh *]ʴӧN)XjʵC!J֪׳hς;ȝKݻx[  LÄmh˘s,ظǕs5 bǮY4[ҥm@oD~Ăྒྷ''!F}4]pH"<ҩ!Hw!zB BY~ mg(`ffxbD$h(BbU  4h8֨/V4@9)d;<* TViXfIOD=`^~) &CixIDy 蠄2f'6碎F:VV ini~hhꪬ 무֪{ꫮ*k,d,_.l mNK-^;m~ .َml.Nk@/ۯ0w[_0 GK.O\T1M Amlqcq"ڱD'[ԕ2k<ͫ3 _2ШL -#4qBm V[tT+ >kA0 vKvt~KLA |rq|;whC M(uĤߪn:®S,𼯿0鵧|ۻoK;|Wϯ޲}"}=ۼ}޼ߟ[>s>[?;&?`DX@5Ps"8:Qt.A-* !, /22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JHŋ3jCIɓ(S\p,cʜI͛8!2ϟ@ s'OD*]ʴ)SGJJUP^ʵצY~KYaŞ]˶[i|KݮiP{߿AxÈO @@ǐ#_j@˗%k٣@"Ӛw&qk԰c K͛0 ,@B@Bз:XpBسkνÒOӫ_Ͼ?@ߟ>}Bț~h! F Jh!b>xᆆe ޕ#h"Y%~xe!0zL蟍8ԎU9~$D&G*dSA>)eR5NiM!,l.22<=F! EEO%$0((3㼻**5YYa=>G곴ɷ/.9H*\ȰÇŋ3jl8@ Cq@$S\Iɏ,cʜK8sʴySϟyJ(H4ʴ)A",uJ(V݊j Z]5cӒMjo@ $,WIUз^Ð# (@D|8 S^ͺװc˞Mtt6 ~'p?v 8^x!,9!22hh~~mmpp{{eebb__yyvvkkssZZ\\WW<=F!  /. EEOa_؆((3%$0)(||gg**5YYaC*=>G0 ^\tt`]55ebrr66caoo`dzz/.9!!ww*L‡l@ŋ3bD\@ɓ(SDDŽȜI͛87Tϟ@ J4΄*(]ʴӧPUEիXjԃ#KٳhG|5x۷pʝKڂ˷߿ PÈ+^̸"KL)ϠC`d0S^ͺu4bݡ۸s֍a (dȓ+_ HسkΝѧS_hӫ_>ɀЄϿtgPK,h 6 G` ``S!!{5L8 ^{Ax(89h ;8"-TP0B$V࣍7ciذBFZ@-N%0KޘNd%  Ay" u9 %5i'~9X! ,+m}snh]xL4mYJ+8C1E1:33111111/*'4A"YXblRy+z { }7Lizroooegn;0MLJLfA6XioYt迂SRsʼ:#6۸nZfQTw˄xȓ+_μУKNҕAپ=a0>kmۻVI{=a/j o~?j51$sih& 6F(Vh *ĆⷞLFpZ}o&I*QP8"UR>P18ƑH&L6PF)TViXfɤ2Mt٥i7b9vA.c|;ʶXfZҐDwbj衈&袌6裐F*餔Vj饌*SǦ U5hBљgx]kj[)ywG'dрG ưk&6F+Vˬ2vdO:'Kkz*UdYNΤPQ^El' 7G,Wlܡ:孚ʋ2_Im*خ0r˹2Zq+DmH'L7PG-TWt3xduM}\1߇[2I)}kp| ++hLZn'7G.Wx3yd9LyvqJn -]|4izp'x~%)ww_qEo'7G/Wo졽y_`اgA@*>L:o<@L:'H Z5=F#'-(:\0f)]t1_;-qB8E"HL&:PHE%:XbKN#tSp&d|r#٘"G9 tJH, O Bܔ4BL"F:򑐌$'IJ&d&BDAIKGkSjJ6f WR'QF,;;?J M2=lЌ4IjZ̦6nzՄF 9NNēI Ug7PAjDcZNvډsܥguL|7(8D'JъZͨF7юz iG1(MJWҖ/Lg:S4)JsS@ PJԢ= S2=]Ka@ԩOiTrIWJֲua=JZTtl(7 Pg `K0uW/. SpZͬf7Y;%$V̽jWֺ-l^?= _yB`<6 pK=2 m.0voKZͮl]ByBdﰇjMz^H[BK+&ࡼͯ~-:r;_|0;́_=&B`{ e%a,0kjT^K5`;TC&J5.PNaB9l\ 7DqX3@p K-0+DW&Ae c.@\- q.07񲙗lc'epb KE8l_fjLz}s9,4d s i2kZx>5 !ԹIgMa^C5!x 2+3"Hn ?hF./at9iToۦ^s)M%H^slJ[Kp3ٍgj 9MeѦe%s{&H8DЙT~5dj(;Q2qZ{m LtpZd 5鸪-f^ aҠ~@n~=#cҔE}%]9f_z;w)>tA7ϣNgqƳhXxƯh;#A x QgQadÜ&6w5(2ݕ |V#u(kq|9>D> [W>CÝu@ GNe_mD9r9 P_o{@`|#cˋF<G_XG?dܗrsCϿ_:y.P P>c5rglb7Vpdizpfqnov v FwxoGjUv|V~sW|(GhWKi~qpGΗw'q{w~n7zL(ordSX}g p7Rx2hSFy7pr8tXv#khc6,wl.lL!k'hn=HiFv vtveֈhqnW7eenp P f hhqw s ;X 8 7Gg XiHҨx6 RXm‹Qƍi( !x蘎긎؎x!xQ zЇق32d؀/dPlf)qopn ub KƐdوDyvtGeIb&$)y$_$"cpsc`0+$J uВ* h' HoGboI'iv% Fo(LIr$FYv$xވ$cZb9dYfyhjU AU@%x+BfahxmHfht&ppgifY6pXphfQ6_l0gg`e8gX(Pv(Y[&L`&(J`i(&(qp( a Vƛ)(K@RJ@gxmgn iYm/y(7)y虞깞ٞ9)Kr 1Hr(vx/b2Qjhfgs Zygd\zj)׈h7g !:t7Jicq@,PV,1zr}6,1 H ;Jr;J,VF`,C*-ji"JzҜP֤Հ kx1px0ڢn1zBz8epr:tZvzxr(IBaQ 0 l?yP ȗ/4s1ZzCmqک:Z*0^@,$Z'_1(J,;D8:4eqfZz 8Yؚںڭ:ZZES0bp$~ZZ L+'ب<3>WA8c9;' ۰ :4ªrY7Zx_گC#<,.02;4[6{8:<۳>@B;D[F{H+8 ;jY#_%8#<3@d[f{hjl۶npr;t[v{xz|۷~#<*iUYWYkI~D<T@Թ;[{@N`@1@sc ڸU"{\7 C`GB-;[{؛ڻ۽;[{蛾Ի)]R0@N˻Fx-'GuL̛-wLL <\| "<$\&|(w`uSP˴+k3X{LvLδ|AYLNPR^ADv(*,.,m}yR]; DC| ' PR=T]V}&@ mө=m?XmM,{H=҄O}r=t]v} ]9-@N40 14$n![M7_MAu q4@, 79) r|~FN H =+QZᔮv 0 pqP ^ u@f +J o 6 y.^'d% P NERT.X CUpL~`" .$@`d qw>zne9 ~=nթo\茿?>툝^Gخ&0odN ƠXf@o!wV4@ 604@$3Oi7`,p) nL߮q}\ \a?NOV4oG zeOfnprz???r^E_< }^SVXoZu@0`_ 2O /hm/.? <@_BDO 쿐O[OW_@nv_0/Ͼ #o/o"MLdq!;}ؙX "qӀIXKlrN@cD pP /)x3e17ęSN=}TPEETRM>9ƠR4QHP?}Slj*Yt#fL3gW\u@ZFo3iƈӅK*PbKE a)db|ReJ.W@E4B:H]JlSF}/~r͝?]zЩ9̺װc˞Mt͟o^.|81zP G髣B0C?1A4s25UUWeUWScU#, P/6X J(Ea{ NPPWQ5[m[eMU+ uM2Q_eݠVL{iCjI\o&`X[qr3tW%a݅7(yTًW_;6`ZF9eM8ۅ?sDW&a9، c2BΏiB =ye:Жm}Yh0Wy]rQnr6F6h"Z2Cik]:j̸M. vPCl't<^림rf:wvZxG={:Soqȃ#osw]u?)Kv\;~>-i@13'|G?}g}߇?~秿~?WJy:EvUЂ`5AvЃZ`.4oB$ؠ$8CDO Ưmle͚γ$-\F2*)򯸳Enr[|kb[*?Up )5]nkRtg1+ZHm q^`o~_ܵ:םJ%[?.ķ݃A F qE=fwC1H\Xp`ĚKX6Ҝ[8}}o|^{mkaVv1Od&ӱ5*6בVX/J7KҵvDgmq䭏}?o~{ߙx Gx 3E($>q)Lq w!yE>r'&Ur?/ 0Byu @:~0Gt^400uW P9!.wĆ.baA#v_P xϻw~(&>78-Rh'yE~r-9i^>yЉ^=LW: uM}a;k}fSb]q.kww󦷽o<nxO<8\|Ck?|=sC>,#7僻k77軻Ӿ3<PXЪB8P5d;7|tC|7>>7=<>N>@D+LDA k?ID+K 'DD+ESG G9e@C0AA @??>E=ȑVW wEZł\]_,6F+Fw:T;ddj8BDmnBG GHD+G%DSGv(B{lyRDJ} ȁ,ȃLȅdH к@{ZŊE^ET`tC,3A;ԻtFTilIƓɚ\DoGG?sDG& JMlǣ{Gkʨ[JSlLyJ~G $HD=P J*C̃YKH+A泇8CI,ɾKhԾFƼIJ5>)kN=,ҾQ%G SТwC#udIJ<|WTWUFo,X0=؟LXVmGWm:X8MQdы- <]d(De1Y<ٝ\ܚ\\%-]M:Edڭݭ Ů}wא|TH7;}M}][ҷX-Ut\U2-S[e5GGʄSS}]L!C86i\]ݝߘeY5ZU]95 `@ٵZ5vݯmT]zm>LM^e<=?06a U#ع5U%LU^^m4^^Hb3|&ޗ~)g},-b}V1NN`m5feW8vcWHc&mR=.Ї a~W?.a@NE\aBDC&VuU}Xd\5{|}~!>eEձVjV␕ee+b\YZ^._fu3&4vcF #uffJEjkԋ?fp^8JuDtuwx.\ FβnVǁX~ن߈h%h0%c3&f5Y]+8cMܜf(>IɻiII#&g6sF M][_\}j jmj"4Ah6r)Hk5볖]/fַ됶ucAE]zkܵmmab&d7Vi;fi3[nkn>Uq^vǖ^P ENU\Lp]gn|oow개ڙ>e۞Y_h9x:/ǀtu'6 Gƾp[I qOa!&".J-4NTEmF b«ɸ.Ko|/I[ɡ +0ʠ:^]l=#tfxF'}YJZiڢ9:k6)o]zq14N7:IjvNL:I! NDBJ[,i;8C0@A=7RK#xb+b݁ .PxnDT;8K>9kycVqq\NJ,c$)p7245s| #(]s&nt1utyfvaYQݤ*e8 ZǼ8/ifUzG|CRA m{_0eЏf<#Geo!+G T =~|!A,Xv.a1B(LdV Ja 5CQ6Ss֛x?Ts74!iE\ħ1{bei,/~Qmal ȨL9RR#Du pfCxj$y4uk$^iHNru$&3IδP4(IA rQ4%PJD,#(FS'gĀ)EAP;PhA|&4 ΙҴC ޴M8ִ2fzcܩԥ2uӀ#ݤѓN$,=/Le ?:P.w)S6ԕ,iY"b4٨{٪m/SQiH-b2iLWRѦN(@T"(Pdj*jSZ=Utx-=IӥV ف0(Ajֳj W5Bz+H_%RaV1#WLdeaDB4ϲM~mhfTQ"&8^+0vp <*$i[O;V)-oAO̝A;)\ΖNhͻeҤ;]T7rh|'x KS RH+4D9o7MuT 9B?J Ҭ5D,9ϙH(3g=~3h"І>4Mh0ю~ISҖ4MsӝFSxaQ[XU*%aׁ3#~uM+FuɡqCucI*d$wޞ2 p!`-G.{p34m~3Mg;{-hB'߉^4iI_δiPg$%ɒ&Y;zTl;T| Q˕8^G/zbQI;V }-tu!fN@r7!Iw-u5[Vu[^w-\f v \n7pRCԉ/}+*kӀQy֔ش^dx]"yy6 $J?kvӿ|9Szկo]z>~O '<ɞڦ-4@ oRw$OCM|}ˉMyz`$^Uyh9<QЀ2 GD DB|! Ğ9ݘ^Y y % ͖=etUp_}A*-)O\IX偎^5ճΙL1Y* hB(`B0`a@zf } Z񕠣 R " lŠ r d &mv*'~'Э)!!)_J^UHm^u~ ta! #C!B!O ܰI UND K!* "= ##F\$r R"&#<ƣj\&j"!(bbr%a!G @F:ğ+Z_LJ~  xa "2!11&G~2Q=#44Vc6fNlu7"8c 9#M:NVY #S]=z ^,c>~l#*خR+PdA dB:a+6/,_VdO@ AGeI"`HH^^BIa3$KY$ŤL֤nc $!!"QZQ]T$cS a"U]%V"(2@Wb@A%BF+R^ݟ"qi ,GeA%rdtYӥ$& KnL6&6>F7Nf!V&9^xd&lCycPb%hnTRUfVj%W>W~elʦXA">!BIHdQdsV)'A0>K`2JuR]"&ig5r'z ' '"4H#ƃz!eR6%P|Ƨ|b%Be}&UfȂj?#0.@bXЈј:,h+΃eH(pzކ)ea@h(HJ(vJ!~&Ҩj;$*{v{SP}}B, (2&I)z\(hip2ti,ل"^ HiAHBh^hr_ݞ_ݟ2_ը=$;,c8*|BΤR}^*i*v*Z!)j.l&m*Yj+&C^F ԁHAdtDVSNOf5ѕkkkZa޳~]ݴ]ݵ]۠r<بkv:#+hBf#FTƌBn+*뿢elyl.l>lNl^lƎj]K1mޘ,ʪ,:.+b,j#N͚`O!cPnZlm m<-$-+6-&>jӮXIB'cR&.pioHS`o22>o^ s[^ߒ 3Dvl-հLK +jkگh£n(`n+{Ri>F@NZtqipSxۆp:/Fo 1T-%# 0zj!hqn.-TbqVn ((30KptPp+3+7Bﲌ豕,-/D +,!#2/331*qъP$'$__%V0rr'o(3(7p?p**S0/,rLN-02 0nS3 1027A4B'[!q?2Ws?nRr%o3&g&.'{'(r::+;,69,4d$+-cfGf3"ow6vh@t[4h6Ap q#{7|?X}G}O<^v>U$6gob&qKc#w(+7s;7tGwL7ueNvvK3Zx7y Nj '8Ǹ88x (8986/97yI/DO9S9go|9yCl666n/357cq7'Cx̄S8Zcx+kx]]4t~xww4v5zr8cz8899y;9;9W9Ws9s9yyQKs__IKZoyWot9y7Z˹3fug3:LC:[iSuAX;oz?|z;(z:ª:«:¬:wm󺯿Ry&8cbB83 sCK[v4gIlKvts:;{;{<|zza5?<ćiq+rs|{+@N{Wv-{w O97~#=䇹3^W~^>O=7~pk=w=>(>?tm쯭=4i{j_:@p8`Aɤ$T_C!BD0a2P1fԨq"d@9rdDžPTrɊ`Ɣ9sK)RԹ'O:(QN7O^SOœ*]UWk׮4vl%gbRZQo5(RwލoXzuױg׾{w2˜I3F .\TR'Og׿">)c?161AHB B "IC bCIDD*JEM)zjp$BG 2!+/J/' {ƨR$̲θ2/?3MPg)&5];Mnm~ nKn9? TPs>oG!? 0A߼OpQS/pUAWQ qYa*[sJq]jcqxl*cwl!*Ү#IQ2&0+1+LK̺,w30Ӵ2|SM6ckSԍ7߀8SHX ƯPU⛯ xISMAP? MEBUYUX?mD]y]Ք ֩a*֪csLe}lgEi/lv[+] p5"R؝7wk_;_n<eчλO+3tc!\A6\SI.QfIij`fug}h VhhZb0 ۨ˫ZLmlæ@ޱ˾N}wO^upN4ψI_KD&bqOlUUVWN2^u 2R#A7xG<3|@ičX HM{=&.y!|D@> 2eIPXQ1+SKYr.M^esKuCوa.O"0 :Qjg40);9+*\睓5X83ͦKWDw tH Rr\%+Jn xK\r /!MÄc CbtE> Ґbma*IQꔖlƫ&i6y1a(^GibujrAɰe1Ydլ<Z˂V%mi7{ZfVlk][կrFZ-`B:4F&zV'flmc+U24s[Wy^[3M.-$,7!^Җ_:3O6>oxBOF/!J 0zV9Z/6A8r@9ooO/oJ֯r.o`Gd**n L @/7H͐L-0 f<0PcH 'pFp oQ{@Y0 a@i05q@n߄̂~ vf!5ʜ0. 0Ө M* pP pR aq`Ȱ90# G P=pPWQg {BO$ Q41%m@1lMp[PqPfjq{pSp11p1&NuOZQ 110U q'㦼cv x:q>0 Ep2 Q!o"R"/O"/Q#9=.Dr$$7$QZ^& 1 q(s<13:RR)yo r**2+kp)3R#7R;,r.֒--RvP ?%/?Oq&S/o/00}Q'ή8#1kc1S S%s2!-3 '3cp39S+=3'RqFL+P,=r5G5>6c[fTrnrS7y2p0sA0ͫnr995p1 :2:;2-3+s+?+M ,1R=4 /E>>i>3es???+@7 4Tl8tIABIsC$CsC:'DRDD9DE"DzE=rFilF"Gui6}JaSHT/}mA34QIbLBBY:C3:KLRLLL%MU4=YMFT-TNmNNGO3P7O&&uXQ2JUR(s:1u 5 9=A!EI"MT׳MTC2NFcUVyV-OOmW]RWNP{7 IAuXJUQA,YYI0ZqZZZ1[ q[-ZE_45W5[U\stVUdMv]^u^5Uh&+__3`J1ݮRTK5`#sA~Dݛ~W[~Qꩾ^ҽ/=~ӏ.^>^md]]}[=wٜAC<w{߅>^!~+3,6;{C_nZS߹ae@_^k?k>pz߰o"80B L&.ĉ)6t̃ƍ;vX0ȑ$K0iZ<34ks3Nz 4OJDoݲ4iZL:} )TZ:+Vl\z رa=Vڵں7n7oގؽ7/|e N8ă ;vh@s)UhF̘4g48:լ[~ ;ٴk۾;ݼU]&x3iƈӅK*P㬷ԫ.]x-˥4dzO 18>z($?'C?` hBh_E *hG:hIJ؞c,L5mhM;$T"TQJ)U)^bUZeU`E#Z6Ŗ[o]u] I^-5Va-Id]f}hYe^~ fb[n r1tc gowUxWxd2} :}z.:`>zP NQ^Qn*R]Rp4bAeԉ(kS-vE#Y6c:nctduJ2B&eag&im~ tev&qt&\sEnΩx9~y/|" 0~2J0j"-zkjkj#>H]eq8[a*RD)-^ۺtN?mݸ&l u][gw߅Woo0/5GGl*Ϥ z1#jT&Uʷ2Y.k3cxW0,?7)JDOIf֮RFkfv^ 6I;v*gǧ lx /7xK4 ƧDxdž#>XG_ ^4 1KU%ka)[[ڝA.͎69vn&vEp靼'{PeK^}ǼDyrInݶ7{}_Q d!C7k"W?r3#8p HFS4ql|`A5+lG/'|Hr<!GC"\d ?B2}$%uŻ?ID#d-R"'F~S̾\YEQLS,( \#֌; a5ljs7IQq$.JQI4.Pʵlrk\f Xebn2eƺBs u2c0SW]C_'yG? Ґf3gs₈E\Jw3~=+g9W ?.n4V]tL CaeV l*2JM=t\W$ć? #Ίִ5)Ui:]83uBO_i,SpdǺ%. F:ƨfB 橯DLJ]X^ ЊvIujm+:ח^e2zśXE[3Jݬsʶ&?pAkgIw+YS[֪][c+նvm^_۸կpY$"W ݀M-hԮՕ2]éy$? ⭚פ]zUR'/m+ 9moV5pQq.rd%Vh&oOdJle`Wr"eKRȒ$#'lVoUbQUTɅi>fc|޳`.vT.B H3ɩKUJKR4Pzԣ?NTZ_ X>ok\ka.mV({nvL&$X77FQ|gG4Va97hyL砿Op 7Mw?]: :/%(nGo+8"{+H~ն6˱rS3y.lNWx;'=|7At?RܪOo&cw) u+bo8qlw{.!ǻmImGxr|)_g|р~{QL?qduמ}u{v|PuRj(WY{[]y_ac e|hȖs֎o>q)ssuYVS{yyKtCYvɘMI'_GU9vgFykI| ZyjI 㖮 }fwiWǛ-y~Imץٜ{RIgjǝr!ByVykٞ x)y,.zV?~ U堀]9Wfwinqסv61d_ɖn٢.hy5 ɟӛXD Ii dؠФbwYkSZؘOXܸlY[>]8` (Jx.Geʢ-Z Z kʦ7o u*ydDzezaWw %="ʩ_, 2[8iڪqtw@dQ6eaf[ffԯX6\:^ZyjggZ2@CZzz KɠF*HQb3K5[@@ ; :[yʦ(!!K@;(&FQgj_ 3ó\ʭfJEkx_I[˴M3aAI>j)aǩa;Z8[;{hٺA+ q@nxÓ394ڣWL)[ʔ.{0U˻+^KkNjil+xpk kk4ڱ;#o ˺i;XKj}u UtÛʻK+Ikkʽ᫺Ƨ۲ꘉ+ 7[%L˿ʼk}L \\l ۻས ~ۮK Q|+{UuJO D&IUlW|&&*mks.0d84lx9ly;==#İ;E)][Q NŃ<[l+L1lgL{ \v릢{n pr\y,<ŝDȱ\ŇLƛo0)n \|LÖ|x8Ǣ ٸ͖ ^Q.SNUnWYQ)[a]bngV&n!(N.q.s޹ ynJ46m:.=?RK~PXͭ_ ].꣮H`4@,d馎@G4 l)ntn>{xJ}NɃNn9蟬-čǑ~J͕ܯΐ.~^KpKP .poM @^6.N^T;޾~^Ցν 1/3O5o79\@\+ ^NG?3?n9갞<I9 L0J?>^.R;kkN1sO*EyoTM>]G̝NZ`od]9 _+nLoZ妞??Əp7mtozM؇}I] ܑY$( 4RAa6X)(P .r0! & QcG5"Y͡ɖ)+ΤYM8Ϟ %Z(3I%bSQNUYWĎ%[lbiծek[q[]y*Mj@6aćf,D!AٓN'Rd1iΜiPiԩUfkرeϦ]mܹu~:9V!^L1btᒥ :y8]uG#WEs)DrgI' EsIL(!o2x!ht)?T=ГBk¥B +:aBqDC mtI(rJzS+k覣rL2wۮK<T 8sN:N<8 $W\RE?%lPFO8ՙvq ӌsTRK5,DBjXc5CZ3psD^Kvy|ofkLm#}r#g ă yzp_YwqP+b\C?7T7}/{!k>/zC}؆]7Чz./޾ǽ]|cJ>cݬls>9~>L㶿Mq}H>w[?̃8;@hhq? $ @?@@ @[@1@ A<AAA^#ӽ,XA#4BӠA"AB+B,T= tB0, $L%L["B)\C,|Ù"9C:C;CC-0,C0< C5dCHiCJDKDLDMDNDO-#BC4<%,C;CA%DYtRDՑ Q̽30|KcFGEc^4BT F',FeFm 5ܽgeWX XiY]Y)p%9h% XhF7x g/`Y5=[0YƀqZZ][%ۖ=[/H[e& U4}dEZ#Sڥ ٦]xB0I=Wp\.肀*(d]/PYp\hm]*.8ݾ>P]M)ESVŭ.mz}8\\e ^P= &bXުm g]-_]Y%X X ^j5_]ԅ1%V-\ ?=J^u֦xmm__E = _^p.aMu}]`Va.0t ࠽R%ZAEE`z]`m!m`qY _u`.b/b.8a*஽apb7ւ0A` M4;`$,VbVe^}&d b5Z+^ ȂdxId` u^(dƨ_Ndp@SS@d1:T=<>d{Bf_)Pv1`PZ胱%[胁cHxaP ]cUfgh;xf9¥le4ccGD\ZX[^^LP8_`gpX[8Q8qrZu2ggu8p;hUtVgcpgT،gfg%٨uԁqeH!fh<\ve!,bMU&?ih]J&i&jj|V"MBiP4bBjRf! gޞT[Ukbp }#뗮@TGu*FKu^PvR..nvэąɾ.0gAmmV*>Uǎkֶ.v.u#ERRR8](FjN,޿fY.nCnDN>\Nse=nYn!.o}:o6gqoBfL{cn{DKa])h o O_=^?WMfpv|מmV݅RAj Wqgrdo]p%_m]f%]N_q%PAխ OrR&GZ'Wrp{ )aŏ&ޘ d8c@Tss;'6OOkNF/&t1tSuPt@8k?gJK'PfE v]ep)X_]5/u2?s_^ah`b7vm~OHoInvoo(p?]auwsXhg}ڄ rQZޗ\{vv S:mx4;e< 0uxOӈoӉsVu[oQN]uI|{lLUITvTTY?xXbwwk/&wm=g]UhNwՙ7t;yw-ڝcWTvTrrGWpV'ע[tz_iMgתwG%X)j)p?O ׾o'ص]w{{LwǪ@ٔn(7G ϗdo{Ƿr6`̺|Rwp)hڭ^,p['hwY}`)O~/X~qn}uz"VWqO&܇iUKH>+fc6A$O.^IIpu)HYR "Ê/2t`c#,fɊ7Ireg)A-($(П>{ܩDJ,Z3&͙3,B*u*ժVbͪu+׮^r}ѵ 2gҌ ,UG#غv}.ZJg@&n"Nx1ƎC,y20`άy3Ξ?܀nA%8TBE+Y. ^M%7h+D 7Hl<4\I؟ RHnZr1E,FN Hívѧj*SޚR[m^vjg{觵7h F)Rjiey3[qyӟGzE!>E_"x'&䐈ܐ"H#Gb=ei%)5ƪw*%h 1>ZEe.KѬD>-h6 z3]9sv+g:<ż*=IO|t*#?zH[,/_3mpc= Y81DU*ɾ̲ o> 8$4R`ԩ^&^!e!:#)(f7#8689gB6"=K>6̤$L?6 xìP.m ,M) N>3>$DRDb_EEjdrcG7neIb$XfI6܅` vC0&`FphN<'1 8CD[D6&AN$CTR5bY$'Ɯ&VrXz$WYƅ0Iea J,u_.F4˦M"I@&!A5dݝefRr+y;}HivGg$y%{ jfh4Qi|e#=%efvwjfbcg~'Z)6FW{ |eH @5'~^H6~%Uu(p"F6:Zai'Hz''Wzh{{ZhJVD5 3% T265UZ#I-xNhҨhzhzYh|ڕBTh)^iJRiYf^wS=(iF(zv陊) )|ieU9ݔ:iF)vNߝ\–)ih:BJhf*ګU]yjZIbf]("ꗎij*תzI+h%X*X *:(*ZqۢNbDFfZzg6^D" k+rR^kk^f,뚩*+Š.l6>F,: ೥ lլ,$ȊZɖ5fi6*OkJm-v'j4=žN-U--+تtm}f؎-ʞm&---Ҝέ-+"e@k& bYzfZdBI..璮Bdmn>~.ӍrWnnV:]np.c"oխW}na*oZboj2Ǯ*! oo۽!>/|E]M]oopSjobĩsi*JRd.niE ksp{p.p{ -i/;WE p pp]z $|00  ^KSq[cqksq{U' 31c91Aqqqq:.d|%qgmFI$Sr%[%cr&k$'?&r(2(w()&W2n!+J"+2U1qKs9r![,cR+R32))j!G@'=}~fvj?b BO:E4juĠAR4xaB 4QHP?}Slj*Yt#fL3g4yeJ+YtfL3iִygN(DP2F1-s&1`pRJ<}zk֕#.婔x dAȜun\sֵ{o^{w.inqk7v`œ)3|qbŋ7vraѣI6}5ϡ6)TTS׶]R`C,É7~yr˙7wztө+,E9z)mɗ7Hu7}ujk7 L̴㬻%3=b6 =ʾ<U\]06γBu,›{=ۑHBjJ&|(5ۮ3@ . f48?8圓:rA|P>G0r3$cF}Hs,L50К~l!714QTU]VmrZmS>LQotb=XXq_}\gڵL!;6`OenRZ=] 9D3]Up|Y`%jPP{6`]T߆~b!e4vCEX6M>9\~em6%eFuNW^蠅袍>]E! {1RY>kV]ZfTwx%^~l޻mXJWպ%5-r]A-5ߜ=w!dFodjKYRP s(|*xzA~!IXB 3B1 iXCP \.f <Lę\0I +'>QXE+^ъ]PaA~'DB FAQ`/# jLl:)\PBІ2ahh!i^1tQ$ؠ%CIZR.taiҫ$tJyO>*XNySTV DIUOpP.H2Є >)DN5dj$҃{3Uum4et޵N^W{U$_TUbTT$1?jL6q(H o(34AJ%0mLQ[SNh[[m?yQ1n[\bᠡ%&o%;ft5a ujղx*DUz&3QPB3½z+M7C/K+1\/3]`Ev nqI[0^U%])@1i\cSԑPP$K 2Br[d >0 R8TᙜuEeiYNۘc"Fb9Ef7q\g:GXg-'Puli,0ċK\E24?E)]iK_P8iOƽ]NJV3Czi]k[qTHmjTZcFqw_kcV A]mOA ׺S:~\2٘nwϡn!((b0;p nCud^4nu?=KpmiMc (m~4;ѵ+7]")gC!?xwA^-rs7XNPrFhya~;4˄.웷9Щ^uE_+[8^vG'Ay֚+P'}v߽8nۿr`BPwS#D`L Y8)B(c9yQqo9->}?dP^yfӷ.3;eDg_`= ^I W!0My3ӷ}%ƏDc PP|R/+mpf:PO{b/$DOoHW[0*P 0 ,7,6L`@"#;LKcȌP  Y"n P ǐ  P א PP*B5"&ʤQ p%pFN7p)^ /AbNSQW[_cQgkosQw{Q]HQ "/K0J  kB[ :!>EQQ R  !R!!AQ3c+KLi8 S@ֱ"k&o'sR'w'{'(R((()R)))*oO3# y#bHԁ| p$,¸j ,$Q"%UOIt7`b0 01S1112#S2'2+2/33S373;3?4C01 *o ;C+w+36 xAx 7=!z8k9+ $rj$)rT/S0;S>>>?S?3&o"*"r5\<:.6q+ !" |4E9]-72q:@/;/;FcTFgFkFoGsTGwG{GHTHHHITItF]45`5 3A&B-$@ n@BLtL}V 9M9)HDME@E@XTPP PQUQQQR#UR'R+R/S3US7S;S BuP;OJJ5TKkbt8-7L nr@ > ˍ=H E;Z[U[[[\U\Ǖ\\]U]ו]]^[ v/+5UbflxLm$X >*a` "j`l ՠ+BYIYOJdOeSVeWe[e_fcVfgfkfogsVgwg{ghVhWvd_` Ru_5m_3R @jjjVjijjs3lV ,c -:F)TY5ZVnnnoVooopWpp pqWqq^5itU@*as;s?tC sIt}DWuWXUR쐂cKtO `,lww{wxWxxxyWyyyz^"i@3 AU]scbtqǗ||}W}W}u!CNncv;h:=VmǫJ99"{;#i{wBqnSd~Mw6vvvqLCCXGK؄OSXW[؅_cXlQ{[UK@w]OWq C=%3Xv96m0ֶX؋Xǘ،ҏJ{y&:y}F؎XAXWQ~9xYّ#Y'+ْ/3*؍8l5yDž>ȜZٕ_cYgkٖosYw{ٗ7\8x+M9UYٚYٛYgmNf9P癞ٞYٟZzYٝm#Z'+ڢ/3Z7;ڣ?Czܦ9u풡KZڥ_cZgkڦosZwznJ6O{|ڨZکZڪZHqZǚڬZךڥڭZ皮ZZ<[i¯۰۱Gy['O0+3[G7۳?_CK۴ gO[W_&Cc[gVRos{Bl[{۷4x&۸[N_[ۺ[[ۻÛ;ۼ[9 c[)N[{++x {ޛ {XӜ#\»2b ';|*\)4*p=O+0@*Jc\JVkLoYa|{ǽ:'0D:yyǏɿd*ʣ\ʧʫ-^@˷˻˿Z^+^$~~7 1)3_7YP^۞M_o^7vc_ghCO_>=nY_YI{^I ?'nD_?s*u_*??}_F H&조aCB8Hŋ3jȑc1Fx@!;RAʗ0cʜI͛8sYϟ@JѣH*]ʴӧPJJ2(XȰ&D[ÊK`hK$eٷpʝKn\x˷߿ LÄIY4:L,ʁh# mϠCM"ӨS^ͺ럊K j!P7gJ.MxϦU`\ƣKNسkΝ{lƴ7 >p2VsrvϿ(]c5 `g{U(r V󅦟 ( h(؁%h>fxED͗Vs9Wه<iѩLbL@:@2:"i$t-yihNjlyؓ8`o=!Ag?%䞀* i衈'M5CoAV*}eFvE&*.:5'L]  X)뮼!,V?22*?XX+?UUZZSS]]__+('PPa^P/-?D5Ggg=8,?0?aaE4G/?<-?H1?=}A"4[[.?B#W3?__ll;:0.@/?@u=iibbXX/?,?DEmm2?=w<3G9H*\ȰÇ#JHŋ3AǏ CIIR\ɲ˗0c^d@̛8s3a5 Jѣ(Q ҧPJ}٠ꆦNjʵ h׳hF⇑ eͪK.$+׮߿17È &c?Lmd3kzyE;MZ&fɥS.W հc,moͻ Nȓ+_μУKNسkνƋOӫ_Ͼ˟O<`%7* } ʗ% | W/ !{ bBQ"z+"/ 5w#.R@h'|Cލ9$ᤏDPĕEF9 < !j7PgyD C {z!,$22,M$D#>?I2W01;ضM 48w1aB\,?I$#01;42W,M67Bhꨩ++7 ,FGQ800<-NAT@*\PJHQ" T /bر$Ï i%B)d&̘gҬi&N:wHZ`@rPB5x n kׂU&UDh +ifϦ mW\&PA })X!DؐX@ ` `4hz!] E8P¯pIwx!,*"22𹹹$M>?I# GHS))567BE &&2곴++7󑒕  %%101;?@JLH#D@ȰC">Hq32hQG;~RȊ%1JcTa8opY`Μ;ygPCy1ϥ\ $ꁬIq* R*,شdͶEܹ֠omW|ւഄr8A/`nȐ% ̗A[As`A" p$8^Ž[c MCo '< ~#ڱ?`K@ ZB@wR|-6؎v-R(Zτ% AP!pxAЅ>nD!V4"[H21N!Oh@0}T:`xfqw$HרF)9GxFi-=6 A:w̠?‘ X"h!dd#c$+KQ*Wa8Rx' a.w]:h.Ўk0@\^/_.1Q 3c2agg*D64iGQ:B0})K%ӚtiMq@ƔPJԡ~EMP>&sjQj=ճQ<.XJֱ5eMκ;skY:^׽ut} ^93l_8򕱇s_!7X,e+r`glgAk6fX3-fQ{5jRsea+ -mvMmo4斸G3.n 4ꖹ;ӀtKB7ͮ3f6nu[3R13uѻ2J+ˀ|KWeͯ|;2旿"o}1ӗ3}1 8~0 c`p1,1 G 0A0KW8-^ 0ǘqq/ @1"x2r,/%r2ܮ XX2ӕ.[yr<.1g23Ѽ- p~3:yٲs\-=Ǚ3=-A˙ΚE#:э,IGɲt1],M3A+ Ԩ>5KVK`ճrua*Y֥5q*]ט򵩁la{RHc?NmhOPfeo;ONɷn{N~ɹߔ;Jfλy}NO;'N[ϸ7{ VFN1 9RP\Iqg8͏|FMt Y):M؈ khYYyx)09.Yi9+!,+22M$UW84l:N곴?@*\ȰÇ#JHŋ Ǐ CIF%S\ɲ˅'QI͛cɳϟuJњB]ʴiǤJJJ!ԨUj5z֯`k&KذhD[j-yݻuݛQ߿ ?I# ))54W-.:JKV$22? 3ABL''4-z_`k((4?@J@*\ȰÇHŋ %NȱG7~IbH%S,xʗ[IӢ̙5s6Sσ<{TМE*etқNBTbDTZ5Ԯ^ KٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠC{%P2Z֩~ZkڱϾ][m޹ =߷9<偛V0nh~\3Ȑx (H0 $,  8DXxA!,6P'22A>@K#$$ʷٙ&&2EF3ښ)*7ڙEF?ALlEFDm4WGHS$8AL3 8)DF?93EEFqėpsDEE?A<q-zEW^EG#++7>?Iqssڙ ՗F@ALEݑ004i'ȞM۲5882Ex^IPȓ>!0УKN҄KfJ|Sy PA>hp?bǂ@ 0`&P08!K fp ($~WxgXF08"  8yI(aܑC`)e hly%nPQCx晦 -*蠄 =a6( AVj饘fJiW*jBꪬ*aꭸ:p+[ްit Cdv- `覫! ACL?`CKLR^w i+6g2zftooonopjnp`lp\hok>^lOpFn>s/us l M #    %>#Q\!k.x@PLMJG9$1*2-11111121212121212121B)^m j TD%ҿҥђؗۛ٤нÿݗz}uhPB6s2X+C"* 3QdVwHA*\ȰÇ#JHŋ3j0ۧI&S\K,cʜIM/ %O8_,KC&%ҧPJ) NNVuyf֩I9Kٳh&Xonu4ݻCuTg6]̸€G-ܕ&b8JùϠCMӨS^ͺk@ɖe؁U\wo{oԫ ?^*\徣K \2e6gI&sOӫ_Ͼ˟>+"(WNM]JsUVquX$AO]M Yynh(,0(4h+fCʎ;R!K&UuɡwX҇&m IJD$sRX2Y^waO}9S#wbhlp)tixڜ⧟>Tei(KV&TwMB6j]E#1XbƴYbh*무j뭸뮼+ڤ"7^HMq9R.(ya.P[%W`% ᝊf.b+k,jUCVS(XLBLzKO@ H"HL&:P"7AE*RJEHg\bRX0zq%dDT3~lZb3rgub]萮/ Y'DAS"hF:򑐌$'IJZ̤&7Gz/.PD_THpK+nc\EWcܢ-9\Zx|! 9lU%DaU"/*jZ̦6nz 8Ir2ֹQJcoi(Vr*i1 m/ދN|P\|(ݮO" 07{ M21 ${u! 0gLc.EwUb.L"x!qCgX*7n /d$[Xβd~,`a\U޲6ٻ$j1º0F>π|b:wE0F;ѐ006@H-v!5 B $rsv?B3M J`Y{Fчz )J `c@&Ik,bvGkȺXjX۞5+ c `\]uvwl{ܯ 2ll[ԞwIk_vK{ |b$]!Mg QЃLũ@ /@ `ֽinskS@}t}}8G:̡b?cᎺ8 /yՕg;἖uY}t_/Asp_;:?O*  ^rA230Xg=V ]@ H]֣GiNuzmmnzWn{_A!>}[Ox|y P䎧0%OȜ$X)Pw_8z3ײVk_'hltwygkG{g ć xmx X$ȁX'}8k%8 0&((9ȃ#(n88Ѱ kF7(kgo ǃk3lƁ"IY8dXfxhjl؆npr8tXvHݷ-ߧqqW"6j r-'vklжs6|H'sXv7ssW6n?qnVp}/:芳8jG(ǁ(Cx3(sw$(8xw@xWGw( 8܈。[Xk[xnw؎8yh$!}(H W8y/;(vt8o u|7w逵!s ّY]H=>(+s*hsww|I8x mh*=M'hFl"8/xw[Xi7)H!TI\ٕ^`sxB׏2c~YX6 oyym_'fy {0iwzIwv{;6'?0H(Ș<8~)i%y,yIOx=s+!1y%R 5IkVٛ%_(YyșjHq G~,$gpYyH9w fvI| goYvv)wn'):Wo֋xp:kIƘ6i(uPhIQɟ/♙ZIٓgj舃fgh|丙8ʹ,ڢ.xȜgYxjҩiby~Kon޹V97{iF{ikSZ8sM|NBpmKnI@mȃVzٚ)oif=(Ƀ6Z$]0zz2${ii15C؉Z:Z0کfǪYfǘبj6w(ڬꎸZ`z~֩?2Ίy 5+xyeڮJe*eگIeӣֺV& ۰Jۖd__j{(* _!V#{d+[6{8[-+^/KJ@J9;D[ ճ#2[BkPR H]J+L3[dӵ^`b;d[f{hjl۶npr;t[v{xzU]W{Y۫Nkd{[{۸a۷3Z;\+۹;]x+A;[;]Kd;[{^ڵ";[{ożje;[VŽ; K;pB컵CFۿk􄿽G +D˺ b \||J\d"<$\&|(*,.02<4\6|8:<>@ F\MB"цK<%!#AC|41&1X>E5Ae3d8V㪳]\ewv|:_lddlf|rmlS ʼnMlȇ{p\,T@;ȍO nlɋȐl]Q,| lNJʣȄȻ\t|ʭNǻ 1|Ěa\ip|ː,V!>QO3 /*&~(*m007%6~+.]}Q}eȠ|഍?+hi=P(-pRNV^)S]a.WYV~^[@*k~BRUgRV.}~U>D0pY^pc`.fLngNy.睾EPiғM+h;E'2'dHl侁E#3 >. Һ0f %y>(dzَY^pNpn~Y.,) e>bSN+-CX ^_d ː @(iu$O̸Nd..F_8@>j @N@OyKҘ>熮@OUrqn~H?@.dt_\@;1_~O /!?[ȍUȘOZ[(Ǩ? lћ;0G~ձ ""/Р@0b 9 BTn.p_n_ҽ?zn|~0es>*^͏Zb /81 e GDn-^ĘQF=~iEH၄]g9-<򒫗={aۺ45WRl_+^&foJ< ZUA*tp3l"\jZ陫A1l?lҺq7k"~秿~npW`8@_)w GtA ZT`5|8z֎Ar}BTBЅ/a 7І7a s.u! (ЈG4bhW 6tb`VъWJAoX$ D2qaոF6э!bD%:0w(3\xxc A-ɾ|䋶@7VҒd&YwjlAX[X8ʎ[d*U9B!V齉\#׸D>K^җf0yم"Df2LaD;Х09`SI' gR:At6ԡ'XEE>Zܸ=/kpãiHE:R~4gJUfFLe:SԦ72et?jP:T],T%_h"eTb%ժWjVUvuTkXTD5bWպVխo):W+f=']Wկl`W~Ӯ\ "6ֱld%VvJb+jYMֳmhEMΖՊfjZŒֵmleV͊jmkַ. J|Ŋn6׹};VjȽrv׻etQIX݁v[׽%t^ oX__raͩſp$`Q8 !J,Dnq9'y2hF7я=n jiNwӟuoLIbUjV{&MշuuZгkb~ :#5PL Mnww=nrFwսnv~ 8]1P\ l\jeÙهtE! jTԠ$>qWx!mxwyE>r FUC%3>s7yus gAGGzҕ>DakW58^rw_{me`,_ݩ:FCWz.w7{OG5)bbn|?x[{x7&F%?y%6lv/GE?zҗ<9~wK9v1}u͓~oG.OǶO?}O_𨓍uiC?~/o?_|AW=1=ST?ă$9[ -4<@!@a6@dtt6? Av<l 1 |-1ip2$Tc?s)*+>C8C!D3 243D4T3D8znPnC9ć:Cn=CC|9:L>DDA8CyFE6H4DHD= "A!K D;D COKn+KTKC$NC@EpkŎ1\``D!"t-{'1f1gl1h<(j,-=& c42GF`>sDtTG2Ѕ҅t477HXG|ET{GUDCE~n{G|W6~GUĀtGTCEDLKC:ćHDH=AWGOHB{tEŗCoÔA uɝGQXex4Fd-eLXFƥT1$1jƩF-FFg+o䆜Gɰ KuGlXŅT;IKD6z`Ioc;EKEoɒEHŒɏ$ȾD}KHɂ\XLL~(LrK7 LGX@ˢ?ABo`ug`y$lhr$y#M r`Biv(N ؁uHBiJO+ʫL8"J2p! N@ nO2GwɜC `D<\HDȇP}|K|OC4̊D?DǤDmH~Hm̅PpDHI,hPUOPMoh.TBt^hLJN| TB)M#T 'RLM0 N$Ωr74S+>̣@%̨ PuĂU<CϏtT mE}ET]T P L;DI ITpQu=["LR[ƤdBM`RMa흦 !g^`N8&5>s8nopq5lSbA˖+@hJoϵPosKSCULTGYKHDז,PTKȤTWL=QuUO6759kxL^.%lVj}FbmcrhY,%' NYhV.q5ڣ5r=cIW0S˖I&N}*)t\E MHQǰ]X@ڶHDK X~ 9IJ~Ez|[mюe-܏ɐlIAeeMAҔUV_YUεY.=/ 1ҤPJ HShe!nEڭ]]biZ{ tE7[D HE㥀̴K\Pۂ5D̴4\ED$QRL\OS<؈DQ ¥ Z$MQŝUZ uٹda]b5jV`|ጅmdlRVtaa]!b6[a_{MP  6:5>1'z) E| "UU7+n-&>sb(c%_2Gl!f!&a#uż0'!=ă<;c9"cUNMshFs(b8~9^b:f>G'I>N:xQ&R.eP*:cN>t`dGefHdo#1l%j_&&]1O&b[^e.+.a+WlWt(+Lj63vvgw;2ygS#1.rV5hof g"6c1j跀#w舮ᓣ{hη}[hhl@h*hCFVi>iFJ"[陦隶i(k* ji Fꤞ顶n0ꨖ[cr~f&0&6j*f붞./뺶kkΒkF^/6ök,6/vk^,./ l n".,./&+ж.v.&ن ^n1-ۦ+֮.F-0"n2Rnb{nms~-nnf"ox9JjooPo' p*w>;Jp/ ? _- nw" ;&wqoqOAR;qq"qrpr2'p$)%G&/-(rr.+',-'. 0Wb\.73Wr5O%1,8s/U@G=>s6FqEwmBGpCsDfJmGpHt0/\9P0LpM?_,QW#7StΰUj~uABª^o[\XWW_7vv,u:godgegvbnhvْڦӲ pwmnf+qW"6*BwZyvWw/x+zȲwTwwoogqwxBQ xzϠ+xxBbxPתg+7q\wy;?(yN$Ntsg=w.v`gyz/>> ox7{Gy7?zʶWt i{.{Oq'A7zg| {nG|VR|Jo/q/ɟu|~r{;mԿ?'}et/zWڗ֧q?O0}/}}~:-}?O~ _~-~՟~t~~}w~a )J_*o8~˟o~;,h „ 2l!ĈPh"ƌ7r#Ȑ"G,i$ʔ*Wl%̓;`ΌQ"Μ:w'РBzi9nژse˥OVLЬZB+ذbǒ-k,ڰ5]5-ܸrZTѤK>:պwMk0Ċ3n-Kd Sl2wsU)TTblZԪWnW*e=m67сu 8ʗ3KsŧSNDߟ\:Ǔ/o<&{ =#j/٣?HҴ 7D]~ ' Zxz9~}8)"iҋ-8#Ј ]#A Mx$ZPyCJ9%UxPj%NK2$&riYeyWvlc&B^.fX';0C[G+lk.S[YN`pC|2J2r0r(T+=+ǛJsB9MBtAIcB4]wRu"]K5ۻIqbDhWx=}+$-q_;,ySiߍxՆn/^+܂G<י)o"Mu^Kz6^y[ͻߩؕ#Oӏ<ӝ*K.܅['7i=Dp}r޶U_r3>F7;O9+ l9y{ d'=&|b>$t.XA~lApr3[ cX6.N[ZO> wgæy! DQC$ZXC tKb'9HG6,^Z +#uƘ=kc6~b9+?l( *b$[29}_4KQ&I%#~2 a)cSF&R$%$ʲV:!m% y/4iL[R.uI9X*?J91b~&/)aM|BhcZqP9SrNA,d()}t'nTLcs'B@]74_ƄRzcCnzӅcECjBf,5=1h#MA4EKsښD3E<҂r:=c`I>+D*( NRU1<SEӔ3EiUz$ME@JpUn]RQiV]1P]Dֽ&kQzz+bl6]W&$eK3[5a;-+Z"]kg!V4}Lkn0Q KYV\'mQk!+Edo./Ng=*TY! xj$xVv%/|+. J!EI4\e(}dߠ2n+Ny*n ^'غ W E+⭰ e\[XX%LLf1o/0sIőmbV㱖C&2l&$'y KNG JTOb[KKcf|vOkFRQ&Ws~m{#Al@Kj=*\c'Yщe4F6Gd-]YL3KӨ€-ն"vW+zVzִFnR:Խ>- -;|֯ϐ-d+;A?]]Oc<[>lfcpv-t;>wʝy{^7+"}O?xf |ๆv q;K>Lw\u^%ݶ/QNlg#{bzx2}F7Owԭ3uk4:ij^ PN}7F>܆^gxOsKNw_?<<]p%5M_tg~17yۄ>o;_=VqN)wz}oU0+'~fZ׳,]~EAwuOH'yk_7_L/U{iBp^OوM_¬) `xL*1 9 @ {Z  ^_ vA B V] fi`] >AL``zD `}`JFF\% :!]ઉKz@^W:_!\WIjK!WnYaa [!JJ#Zb%:t J$`ia'Jr(rb)b b+`(&y)?V@b-" cVݭ1a2*P0#3Bc.J#PP5bc,j6b!1>cPpq7cӐc$V51c"ʣN ~">?6"?B@@"d-AcBJB-$kCN$Qc17b䎡!D z$Ed3Z;#"a]!`sJb9$LZ faMMZPGdd5>K$` >dR*0e7VSBeb "RA!bDjBT"I"%YUB%ZFZ~$O-^ ޤΥTY2a&fpe;nW%bХB#C!raV"&[$LFIgzfPgFirPB%*dz eX"Cd)njfnfCihk'QZTZ!lF$^Re-#nnpkufvvwR\vF>s%/EWy fqg|vu'vq%wgU&yzy2l(f@X}'M*XV}'x~Bxg~bPrZfd (Af_'2hY:ტ"ey%\bIaz(C"h{R|hh)]ZhVBg9J"c^().$~('%6qbiriVJih.zz)hߟF))FcJi)Fzi.NF*V꛺i犊H!jr=՞>jBiꜲꦆi[)Ҫ kBfcf6j>+F+iꗺ1մnB+6kRYbH#ڨ:;¨> (z&*mN1߀뺺dk+f(Sryl)c>¢*h N"7>LZ(e"#Òjs/:,.NeNlHR}zk,j-^Ez -VmVD^^2^b-FȖ&^b,lK&lLImkR-jmTΠr",FmS~,F^.nn- gɢrJ>-b.nZnvV!m6m2NmîGlz;梬)"o.Bo +>iNZz n*/z2&&/ʯoю(N//nolcV,Cn0*vbc0 ©ǣӆj  1 6 ;_%8s9O: )b-/`9/4D[ț\>go~#: :/黃1 9$P8p>WO><??# 3@3C4W?;8oD WȋA??_87?S>?@8`1v$Tp!*4d7m̈'Rz C bI'QTeKx`Ɣ9fM7qԹgO?:hQG&UiSN]F:jUWr skW_vEP4w_@lڵm|6l]W 4PĊ3n1H'VqcǏ!GzuױWv{wϡ?|CMCBy[Ię׿_]0K0LФl!P oR 1|<8ԯ0I Ͽ8+l a܎iqy9nB!,#tM!K1TM9MR8- tUQbWaU֠XPj$]y8?R2u@O_}Ǘ|׏__S_w,4ؒ6v t!N~1x 揀AH +$ɨ]QBn WCr-(Ґ=l"E4"ւ%MtŒX'NU| }BПF1^Z UCrmt#V,醨E07}҈#Gt/GE. 9P6AK"E+~A =6t#)JAHIO<Bp-qK]/La41bFlMiNմ5lns'P Nq49љNuDA @)HA4v?P5'UT4ʍPE0q e,c;EQ klGAR%5IQR-7ӘH9;"  I T,i+Ќ@C1 bcEn]WVe5YњV]5 W)P{T !x Td$ _CĘ1 Re1YngAZю72ڹnPN`w5j_a./Le)UE0Kbus]Nյu]nsU :&DJW/&e3iR̨HųmiOնmmohwn6V߰Rl28 L(flfp7p/0 qsT" {_zMasϜ5qs=ρtoEQ8SP4pzӝGc1 ߲sP `= We7ўvl߆/' 8 Nv;X#I시ؤ܊h^"/w!yO~#o~fh`MM 0~0UqY]a1eqimqx0TjJ !0M0!0101~d.U@GqJN1q1qɱ1d3 ŐV?1q2 r 203v !_0lpo!& 5r#9#=#AR81!O "11y.) f1t!,i22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JH3jȱǏ 1ɓ(S\9ɕ0cʜI˒4s= Ӧ@D*]JQLJ*SX R`òl22BCM!<=F$ KLW,,8((4CDN..:33?ablH$0@Ç#(0ŋ G7VHRbKTȕ0t&4mBJ$  Р%=Q(vt @XJ4 &4ڴ* c2W {!,D,22~~yy{{vvssppmmjjhhttee/    ! EEO10lloo((3%$00/||rrB)B *caa`B&;;+***5B(&&YYaB!+=>Gec^aB'TWcbPSVY<=F[^dgad''B%`cSV`^/.9 fiB",Y\Hl@ȰEJ4hdž3jȱ# 8L E R\ɲ˖*j 9rC8sɳ#sJѣH:ŀPJJ* wʵׯ`hӪ]˶ c KxK7\'쁋+^,_ H!)3k̹0MB0^ͺ p@0ͻw x@._μ9 "@>Tνv*@< yRBr#h &~MpEF( ̧ -T wDLl(#@aAu4X?PAZi$S:XPe!$% C P|D(1-})c[UFT\SgGe2ZR2  z,zF y@53F+RTYviipooptttŔƇthĮUʲTRM+ נɵ!!{k,]BZUpSZ`zjpwwՃ|͉ʛЩ~˰oqy݀́yiWH:)DZ͜$ʐEsAn(peTPPB5n VG< ,'&***&5' G ) HAT*\ȰÇ#JHŋ3jIHt&S\K,cʜIt/ѥ%O8]I͗4@PMJJuC2UzU(ϭUrKٳhӪM5%x*}ܙr&m%ߩk>McJeW*rHNسkνO7%Uc~mO2mS])_J٧%Hԁ$L\M v ($h(,bw VX{Q <*V^6†TJHRN8UM㓥EFEy5SՍŗ`)dihlpI4YgaP)SEe%AEvO`UR^N55H i(cn駠*ꨤjꩨꪬJ4IL&5 @Q 'u)UE벓(a=BLg@_ŷ+k覫Ƌ3[S\N2 *HF_u #{tj^tE ,$l(,0,v`J7 72ڳL[eQ =BXtl`-dmhlpm0]wQM/kU[I h'oߌhk95QxmBNau!n騧ꬷ.n;y}*8|Ƴ&}I|@xP8q#ЦYkEI:@/o/`䤟cT:X= OJ WBJ0p@F. a)-%W>&ѩ=Hzv@ H"HL IBL"CzqWYD!pxYЍaac/4Q9fmk+ԧ>i2t^ 0IbL2)=Ϝd(42Q¨FK,N…˩5&ޖWv|hK .@JЂMBІ:D'JP>Ψ4Qd7Ip$%G9t(^5eMЈ<^m4{=HMRԦ:PTJժZX*,U` XJֲլ8ZJbp:AWuxͫ^׾t:zִY1Wհk`YFse7z6-]?VueMW{d @2ͭnw .qBj  ЍtKZi b:0puKM/u@[~Wͯ~1]<)-/ EP.s_ :'^.BkS GL'q-,Z[%gLۘ X߫oL"H&ou1L*[XWi͉|' Z0,hN3X^ ,f`B&`r d#dJbfX8 nBawk7t{kG$ոۣ] ǹu=n`;/gQ<;.O Wzos (kֻ)EoYϗs,<@6kk\tg^sW:ѱN||ݖyAɣ׵'F;[ίt=Wt)Qp3a~~~||xVln|~}`j7fhkQNP,؂.0284X60+ +o5!vcggp5!mA &jpv|l5n7wHplQG7fF~k'hPF$hƀx#zGSt~ׅ+X fILXb8h+hljh8l7Xx9%}`o>@H!Wv{Mplg`m!i.yN@zzWڷi}px8z,k8|"iN!!H!h阌Q"hp"HRXvXihhs X숏r"ّ "9$"  /0R2{(f|i8|jglX# mh4zM'n6z> x9ǓEmAk-wI荀%&[bZZyZvZ x@` &F7&k 7Q&ȕ vgy{ uu&0%GiM&g`hr2Yyٙm"ف?`g{,'AUhgKh9iꆇsm7s9Ir=Wn#}Wys܈oh y{hbY9 *@[|k9|[*~)i0I` @*yӉi[Px ڠ)o+Zzڡ*c!!q+I{f9`|{h4Vjxhi7yh73ӫ2bMzȚʺڬ1^.&bz^ [:p4)"F«6꺮ڮ * ٯ;[{ ۰۰a2C[%*j^S5&55:s;(* ,2;4[6{8:[35 3bBK^b[4ᣫ$k>tx>V{XZ\۵^`b;d[f{hjl۶nprӳI0]0Zpr֕CX#9'>C;[{۹;[{K>#:EB[}F %3 haK$;x>8CLʻۼ;[{C5CCBF{KEK]k]FL+cXJtt FKtKۿ<\| <\:C볲[k蛾ѵ۵;c;vGtK;44\6|8:<>@B~֯_`B) "Q+^o3P$p0P`#&&  ɒ[,oFonq#V``@&fh64mV@ԾPCF01Fn P^Ob) E K_?='MO~~)0~Q>pO`Ґ?AOj i_pbo\h?!? LM_f0yo{}941?NP NBapo/%A)` !!D.f30@ola *( Ġ0-48s>hE=~RH%MDRJ-]SL$O;afNLH 1hCH$]h2eJMU^ŚUk}-|2-] -lԱeIc- ,RY'=|81Å=h†K u6Pz ڵm]r'!}J(RLB[reve 6l]hղu\{Mdm߿@G!h{*EWG3퇮S% 3E!t0&B /'n駠*ꨤjꩨ0EW|+ʎE!./>ң!$r="1I%dI'P8+92K[I:Ʒ0ڋ=*7߄"ȤN;$( 8;1OAm1$47=@!ȣX.eE:M7M?4TQG%TSOE5UUWeUWGTAV[oMqO8k4XaKR%/ ;FN@AǴLCVVO=Ҷ[o7\qqhm57o1UJ?}Yy5ؔ1E靍7m[WV]faJan v=W*b%|Qُk! v܈fo.u'>܋u?g +yߣJy`x`9kvXgy~ *}:%6iDT۪](eƚkVh-$[㍻.m}kt|Jn[=t9j7(ޘ_r$or_>KM_httOW $ǰg9.v땓}$r<}<\G?紕7橚ߠ;z>]۲ءUe%Zǁ`%8A VЂ`5AvЃaE8BЄ'Da UhIu3` ln2(z[a8D"шGDbD&A=E61ЋZ!H2!A`h裉oc8G:юw4>DzTDTT"pEla Y0+_bZ94n[5INvғ!hb>(3$h d,așAm&G*lf09Lbӓ,)=~Xe.Z͖34wɂ^Ҙg89NrVP|2J <9Mzc$oXOe L/9PԠm(Q{H QEa-ʓ=[:\ MԤ'EiJ%8J"(F5j?b ]N ԧ?0Y#A0)?g:\YtӠVժWj:PXReG"˩M#/}gVd%o-flZέmb:@IU,Z3ukb?X$2V߬Wu:|g=-\k[Xv2.gd5Ys6%?)RTQַ jNMGm4Ȃ",&tnvAReɘYz si_,린ۅo|]}׸Y(ǹm4,q+?T">E{9), uh8oE\Uо<^[.MUo+= pU l"qXb)8GЧF5 <)nE"mVFd%PWw F` rL`#xEsMTDZvmnww=nrFw-h KXq֘ 4\?>mVG}ZPa <޳= ^9a<4qˣ'Fȅ1r #'0T_Ee.N7D?1 "?zυK@%*tJPbO$$S=W1_^@)0v L@#vn@{ p9?xs_Gxvg|%y,kpZo{m&gx?r|(OU_|淿y; ?Ѝ~/Mzԧ^Gd=\/ gO#v}vx?<xxo;޽jycv5;_ZWcҫ +=:K=[b9bpC9ٛ=ۣ9ݳ9 ỄS:scs>>>#Cc;;; S[v0Bøà>&t'tBƢ? <0=[=\L@\{@ؓ@`=۳@9 :$AC>DA[A:>쓀A;A;A B"4Bv@‹S bB(DxpK*ܼ+,[ 1Ը4CCC \ l78CL=>> ı,DADTDFlDG ꫾>ƶC ?j;k4?l<#ĹMKN\IK LLDΘɚlNI|̡N,?|BˤLϹ8|E,MՄ<ÊdTƷF`?,",N=UNbmtPL%\JzЧ $d9@lQ9dM <ؤuϴ{SёANBK#m$%uN'u̠)] =S >E; B#TST zI< bTeGH|TxT-@;op;q5q-sUWoMu=vuWtx}yWy}{WLU$U54SJU]ӲщXf[U^U`5IaA-֍[VDԐ͠fmgR)VjT-+VQ #yٟZ|퇢5ڣEZZ!tڧ5E;XګZՁ;KjZڰr톲5۳E[Z0D25UTekUWOdX|H<;ՋMD_]DF RaMI"$R#4#EN }'\۩ &=PJX` ٜeݯ }ݯMٝݯ=ݭگZF]ݯM-޵OSlEтdN[-K[ŀ9MĥmH_G!XXx`&v&Nb \GMYi MR-./Q؄ 9v v8ܗ%l̓H-`sFn`}`~Z -W r䱝Ve4OMQ LeބEIaA !5#~\vx_{[f()_HܫMa&b6cFd )cf8ghiif45Φ\Jle];<->f?d!D`Cλw fm7Hn,JFa-LMMU\mk&sWn†(Vlrf y"Rjo2j mw6eVp f%?w 8ݎdIY_Ha7dvaNdmqR]t_qnq{qV#kqfR4 o7 l"7Oi$7%_&:oo/mr-ps߽u s2m51}7s^[7pqa ^A.t;'Tnq tJ7ފLvGNPwf{!u;oRc٣nurҾr,uuEW.jm3G4Gagbws8^eNO9jGkOܻvnYFwtr sJWYB'7zBwwPww$R5 4x.?vNx .dj^u1T9gef_X9GҧS`s Ɠ0z hO oo6p_9Xs(`gTh}3!R N"ќ2 (=T h҂ f3BAD !x#%$#YAz#EO,RL3tSN;9%UB4ER.$hWWeYi\m^qcubyIuFvf g6hkl6/Yډpgq%\%Q]tԙzvivYx䕗z7~矀h ,Ƞ<9:˂š =X, ј#nO?j1BG;%))L2dN:/&aeS\2 "-Vf:jJ<nZrjL}BVazlX r)S6fhhkB*q3')М):G$jʪ:kz1^{+׽+[N`2ѪM>aO%!hT=0?K!~8+nF8)kҽLdRf>zUR/ B 'H>;Gf;;{o^#<`̢)J4|39>О~H+4NzARO}^ն7 p?sk`7؊u6MCbۅ6-DA XH"H$c,B6  ?Xn"? 0 r%|aD6WI s.m)uk(!F<"%nPdƨF]5mSDG--Uځw'+jXkMmD ;& TEFA*tƒ!%GÇ")T!Xn22$ /(Qխ@(8A+]򲗾.w((NzTȽY]4xRQ:NZLlWqtOa!h裴m<FNp$;Ɂ2> JQ:EU~0 kFne[·bz\CRU֥p:N `iÒM"bb^::,NsΪ; PN~MjY֝mYm'1v\[RI(\B\‰B=r7օ,8u]Lt812`IybKVF>2 ̽,&KYt~5-xD;`V-:`sJU U8po+/M~3-A z&<>IP  󎧖Tnys`=?A/#g^c1|%Oyߜϫ^}4Cw,ge){&ZG4R)թM 溷cy3b/[tgxy%ԷD~c;t! 7P `68B8N&"'&'!Ȅ"")j)"ȽY^+f^*"Ţ,FH-ڢhbe."'0>1Pe36#4F#5V5]`:>tBP+9jZM:];Á"==>>a@ ??RAd";(BSCƗAd/fDRdscx! 6%\j}$9#4d$U$ ]6d?ܛx#MJDb:NO2OaP eeQ%RRNAeTh\UAVC.~%XFX6`%YFZZn$i`\\z!;%^N#ݓ$6Ff) PAb:HLJLb QQL& !!f<(*RvR.%*S+&i6S,&f1@Cl^<`&Q`Vn[okq^N_Y %wb +A#c.IvNxgegfyJgޣgcir^|gZX%Ѣ~'WCfl XeYZY悶GB(״8 qar1熪>u2v`hYf'(yŌN\⍞bڟZȧTҧ@gg~j% |ye&ǒOV~=)F@0(GXdV(^^d(!j)ܙ(B #x>xfc.:a䎎jVf>ʢg/&]cn8u*j}jޑnizjJrhEjN+`I AMxI ыҩ)j(SkT"&✡FJE*]+%8nnv+6>9kH++  ԀAth m\>%Ok+N!)Ê **2j"bk6 j,R*jJ)&U%9.91ñ,UkQl,, -2-n6&%j':v8f@L^& ,n-'{F!.l^!3?? @p1p"#7DI<.Q5#^FGTV|U1d1GrF94ۖIs3K2xzx?ᾸX̸f82`oxD8E#yz?9:[wy{9;/繞c5SGz[w_;c{v.:Rz9e{67gǓ6o/6*aq:<(:O}Ks>gy苾}>dگ~k/o5@8P`6jSq!FHbEe4f@GGACdI%9Tҕ )Vp#:~)-XL10hQG&UiSOF:jUWgJW*Sh%!?pЀBOVoM4$EH VpaÇ̋qcǏ+ySe˗1c-ϟAIQVt;`ǖ={vkw"ֽ7ow>8qہhT1ǐEO6t`ױ_{w6?|,WR{LJ~}oп   (LpBlP!( +R.@ِZz)j)z)(`QiFʫ",b!̊.KCLJ)J+LK-K/[ML1L3MM5+M7[)9{ι萩NO TM[O=ޓ/>kGORp &A.t=s>#xb'Ԃ5ݴc>N+,9Ó]iV# YS\_4A/g~>Ge]uK&}izjȪ:3mkWk7.ݗ߶ݶ.n[oJfocL5p7q UU^e/GquqFtAJXEkiaI0`z5kc &yf_6E/pwaoa^"w/|6ƱNHj~4?%UQ(Ybi=' Zpw̠6y G*[1, 9 9C (cA>#ZPR9XDVEUY|:V/Kj f3N&[#/û7+rL;q7ۣ6J-! iȃ-c$HIr?:Im!#GSD51UOjֹYrS`Y3tdĠ%0a~wƔ2YCSb?uT)hr@k@C9tAA/9r2B-93CrC;;K# IDY/+Q4E==M4ZEsO5e9h#_SwOGs$UH'H/4tI11)B/T ;~C=KAD )LtL|柁=x}Iw]{{5]0(~-^1>u;_>C^ܭO>I}9Ǽo~y>ۼ֋>m@|~ũc_oⷞ1K9~=6e~f݉^eԭm8GP^>_ [?<'?!ѵ~]A9L?Q_;}na_˿m?u/q~ž@{t<0BLH 1hCH$]h2e$K<2ʕ,[| 3̙4kڼ>TzRE˖.Izr:} 5jʐA&)rTGR.XppTd˚={;ں} ڄwXٽ7o޹( 8`|8ŋ -ɔ);qfƗ :hї,ujgY'{ ٴk۶]+n݃zې?~̙x=ԫ["?x![;>}iۻ&-|ۿ[_i 1P$` 9DYFyHR]ana5TO?UEQH)Ŕ*UBZ)W >V9vW=vWAv6XEvYuVYM"dF%[2} l \&q!!ͽtr^Ggݙwzǧx{G4[Z7v`>PCE4QEeQGbJjOH@XQ[hjhU3rX7cdcm)dvidAfL: md6ZU^ ڕ eږte6nffŵip9gyY /{d-M 0Y`r:ʊqo,3Jb'.&_H+YmU ꫎ # FNKkE-=s0%j;v9nb۹pns+/vng37, 7czZ~ 2&Zr˔U+Ә0nj4ez`B,O5tt}466N7 u-RKeu=y}e(ucyOO/7vJ!~SVb_R㶲˼59ku3L9s*FpmyӠ62vX"t'k㡍P[  z,={c oC&+җCqWs?D+CfI B:p\&. `u| !H<?Sa Y0o۫X߂D.n/H QF3ːD,tqE)҅ %(mAF֌2e;5^mt|=勎(f5է2{ ?N/(7Erܔ#[Gd $o2a2-Jܤ[2IVp.HLyJhSJbeU׭Xb-A_WK[jhy;_^ @hb"=lR3ۖBIsS5'],m)stYI%tВ@ zЄV`haD¼!͈.wٵ_~\fv|cXqViOM;y^ᎌjo)3PъniwMk[3J3sE~YO8,W-*]SRUQeSݽTx#UGUyh_ Mi =lx8VO5l5(\ 4Fa&$ /0 IGEܒO򔧼3h_sw&4o~b<}E}D/z;+}LgzgK}SLMz{u! "Oed6> W(Gڢ1/N`o6ȁw|W*/|Y|8oZboYqiN|Av`gwuc- eo~& /"0//"@?k=#ؼs}EtpqO= G7mG\ɇqm#m!3|;|}җxg}}y}~yg~~2~T~~7FTpoupkk`<Xc@EhEHXvmր`|,1r|2X}@!}#HN'X~)+F-a/x.1p3b]cep9=CxI{K8\>v!qm>Ur\xxk񅊧bhsdX<hHtjJgn(uprktvX&x(zHif+2?HDL|'r8h蘊8A闥GPDIv#`{ȇJyٔN R)AH0xcf`ɀΕfYbm*rpirYtɎvx)z|~ɛ[Gɋfy^6pLY[9ycq:i`^ykϷ9}aؒ0sɊ)n:ܒ  ;Wv=]C_a.cNengikmoqn[Pqs@;wB>DFu WYݛS_}W|̦].Nnf MꧮN>]Pq㔋牎{}NnЁ܄mܑ zM]ZN^nn` N~  ^XAN+lƎ>K><+׾wd>ݎ2 /3 ^8b`Obp4P~ N:/KJ.LQ!o#?Pn"~\.EasOuowy{FF .0 ` O0u_ P~/0@a` _oN_} -`S?UoXգ]bdgO)*ɸZ FPo׏ٯE0OPaEhPEpMEAD@1gɌ E5nѣF#zt$Yrd<)UdrK1eΜCM9uO=I %ZQIaӦlN j7YnՍaŪiYiM[hM+ZF ?Ie,S`cȑ%O\e̙5ogСlis2-] -oɊ_NR0\HH=EL^uٵo>SNGMZCDe@SpA,Bt@, UBvpà:I)CqJlL|+ )+B؂|fQ-ҋ/0S 8$TrI&t3"SsQ5`6pI0M8-;.嚋P!pM8sN:N7{^{'K1+ ;,tYh(!4+#cᶬ-/7Z23pKӹxw^z^|7xRAEOJD߈mX&/q҃7b"48b}Cyd.OoPT_*<\u[u5VugR`Ouh`a2"i:jԴŲپrF\MW9إvm{n붻3s;&0o&O<+0q>K/=C}MZV&[ǩayl9geywB,wעF %r#vyîkr,\~3Dʹ׬tW}w}E7=”U^]u=viw Y~ExëOwt< kH2RwA f8ci4me[]M4xBDŽlSSP3a mxC0a}C QC$bp2~K xEc H#*Myt xF4B`@2mkiD Ϥ ]FcG@R$d~D/FKd$'BqU%d%-yJNU\=-kbMiͣc+]=V/kVVWbЎc r$f1yLd&Sdf3LhFSӤf5~?kd#yHJr$%5INb哟 %FYvtA< R8Kakr%?˳+B'0 PFThp`udQS#-95ut+JSޅX\*hPL@!2\:BY6z`jSTFUSjUzUfU[jW*;dThGsR>keIMjEl^ S@ֳdd%Q5-I8T˨DjEXFVUdjVp5lZN5r mioUx2uiRyϛ&V`F{bW%d+[z igK~)niM#u&WOކӓee =PbB^W3u{&wTe._FW |`'X ~˒tj-i2WÉ? GVvR{8_X\bX3uwBIXǘp}?YRN$U%>IdVzm-C[(?]qeBc&s+Xq;d8yHgL}d~7{gx˜wXX0'ZыVYusgLYtVg*&ǶУF-‚xs$uhXǚbtm]I皤2kok/WZ߫Vyꮉxy}ۆ^[N9=<%ɰjyٹ2=&/'v\ms[efr'=7ъg:Z{zAGLqS4' >X+3it49~siY| sx'?g*w͗~_T}>C6;@33 ˼6L|[!ƒ? :@@ ;?{-@ X@Ɍۼ;@@>AAAt<4XAs`@6$A'A)B*ܻ#4B$Č4!l'JL^_$FjFk@c9dtQ\\]h7.Fs(e>pMdhdޒxZTc ^e\p!h ZWhU6dOD6UV2XHNCIV0Vd _5`xR>#`n^[& fH~x!fmvVf)nRd`d5aDjFV@:XЃwih!cib.T-vhL-hhXNv]棡V9h^ick|يU_Gv]6naS:Ӯfj#ԧj{1UUijQ=x=ӻ>-k+h>ukɂ.Bkҁ@1ȖְaE]k~dŦƖ[Q*]mmzmeET%iK~,N =d֧ІfF]ƭ %5~Nk9?vnmlm\3Êi^86o~[fo:f]f0[&5q3`{ZXP ]pUPpp2^Rso5ҶjX\]Y\XneP`2. qKțp`wq3"3C;~`Mr~ĥbaJсsԞjr+?!,q {Xp6]23?BG ws(7sW:Ϡ;?E=cXK&DЁ02!0L#P7lm*ڞ/־`JKFseAzNr𠄑0 A?uv@pguZPI_("Rr_,'Rrow&Ew(U__f v~iVFowlk$TP ԀSPSw^o{)|'awUwwiOPj-4ۇǩmfxx 7b5(-ZcUc.>>qLym(8op7WwWy2`oWrfizJ~]o'b>XXz`XuXWWnjnG.dƀZ YZS`ٮ<[/0Zş#r֞٠uXWf{W|/|Çy=PYC@gee$_eQd%*]/]4LTphz B!J6\e̙5o3-ϣOԥUkرg6ַ?E]X"&6BXeFYAg{v<ч!>Pz+hmxf!oc \D ,""v*L2dN:S~Wb[*՞R]W^eg^_[8W]w-sY:4{B6!!Znqшa $Oz 1{PZI6g܏*ᐦM (ڪ jWvMrwSg%ګOyIX,Tj\R[ab-N-܊;n%K.鞻''agh\q5WRf4L KBт+P̊+-@[u_W=6e6Ri'D|/|ż^}dn9yz_,~Mwe/> y߿(vnjnĦMzՓgA 9i/`&¬*_ Z`ń'TP ]Bo~Ëj3BXiD]<Jˁ͓2 Tb;E ~/ I>G=X#۸F {58V=k?MF$ uw@mն=ϋ$$X*R1/c$x7q/?ΈP',e3 hC$-kA<-'Fk/\$/9̡sT&&)dPpTڱ:P)ObMlfsDA_? \'R0nfb'~I5( $3)dBsmf?3MJsmL ޠB4(E+J7'iE;яc?z4EPtiy4K\`0Ϡt)AzSAOЄk]*S:RW}eLZUťJ*f:3+QӟzD*Է5: ),DXV WxUxQ4PwZ؞UEFhr,eJsNu," ,>m]iEׂblZVA,5+ ѳ-LK4/Ոce;VHsZ~-w+Αgxe?[bM~W+ݢ}mk&z,;fF r"ũ}97=ZP8jxO: 0^+c,##Pa\'͝T! TAE_/í36rj^H5٣mn꘼t^9ZEhg,xڻUBc:t.G 钴cf#;(;O:ԞCOJmRk5[iR:֩N9Cd96|i f!i|6mZ.5kA 6m؍)=Tqx;{%Q],NQA!R'Q|J .w1?.Nʇ$F6"aaRZ!ejlXr_I1^4͡xlđ Ɋ(`_qȡ)G_t"_x bmU=:&cIm$Zb%^f&:9|@g E48*ʉDʤT \dJ *7`_Dʫ=_00!c".`1b$>3.#4NcB!&"#EB5TAJ .E, @AIb*BLƸcrdK=!M ͼ?֙@*!A"1>b36E*#U2cCN%5VV^$FRFBM|d D N-O`T-FMTzO ڛN\ea0*%dA阖Xee C>$56 \2hOPb.f5f9!Bӎaf&$TjU2Wh* ^P jZrj: if5ffBH"VVJVgTbepreUU.pzqt }'l&muS TyNd{B4:"{ gI[*)]d(+?h h1>%ne^fonQh[}85}( "l(ʕchd.BzFhB'g2g|HYNԜeZy阆TFil\֑gr9U:iVީ^ f`5V:ޠijvZ2>*yZ6)F(|b j"j2%hdVҩNjj2Zrꭚ/irg5*&kjJ*RrB`*J%*ꚯ&**WY߶+4:뵤+Y+bi+"rkBkS=EjY~)|æOBl,"l)2lkłHlQl*^Bƚ¬k,̢^lȚX,2ꩊ2-lq6m&bzkrmWv-M-^Nφ-퀁mzؒ퓙mˡ2jW G -mA%n:BnJ)jŪrnzV%.[nnn6zm|4:n.2o:BoZnb._*"go1z\ȑooooʯxm/t.p#p+3p;CpK0]7m~,jܑp p p p 0 S0ۢql0ssv#q+3q;SD@gex#f4<ȡ^tx,_֞q01&s0'B+< !'0/ -z18AS?4'4#ss7{s&ׯ'JA)C,D1 IO =3>-/H.2W񲮉/WaAA#tC"C"}D7Al -FFAG*ܨe81?f(BF+ m\tIG4"E-~D'tNN&h'SN9{F^,3HE =**HET5UOE?Va_ց0bZZ.Vr4AU\D\%5qH5M:AHs^^D)(]ϵ_^[]+B vo<`Ks[svg{v/VvZp#,RI. C DAmmnVkW]X$&˦hA0ws;sCwtKt7a@EKvsG1vD v{ww5-wD7ݟ}{ż^ +t|>J?g;G/IӿG n_ m??D-\AB$E )S TxcF9vdH#I4yeJ ;I&)XlĈ8hhgePCnHf":uE W:VzkV[vlXcɖ5{mZkٶun\LH B BHh` 6|$?1e"sgϟ)W^yͥ?*UnhѣI6}ujիYkw` 6|qeݻy-t33to1'iԩW~{v۹ϭ{W}q^~}zExd@\3Sw@^///|B31⒂ 9"ܐ$3 M<E-l+7e&,B0L}1"<$jEfs*3q>+ @[2<M֚ O8er$-/^AЃ-5ޘ5~M|Mv^5ǓWeYuޙ}>餕޹Fd>5Vvu\z->^Ezc;7EQ20qق%-W+=ޜ=G[asrW7&u*HJSo0cNvtuߝ}_^Йětj}zWר{,vrh‹?_o:^޷p~Mv{t2 %cVX+Ex)XA ^` |gU4j 1<1b@Dj7#AXD!IDL؄"D0(D#x*zBE/~\b-F3gTcBCAM ^Ću4IyNI YHC r'$A&O8$)I"`QZ\a 'p8J3Qt`GW+EG?rP xK_%#GKAh@E1LgN6x0 D?L#>C=i|pӛ'&Fpzg՘-4J2u8\LZP %NXP1b XB)Zф A?!#Fb4TuH1OQ*WYSIJ">õeZTI%*CPԇ8RZUb4sEVU~^5gy! [kM~q-BL2Ө(tW SVAUb{Xb"i88,X^v@LbDFKmZί ^*[[)Rv[oل0L :(1\>>@-ZN:pkHdrׄ&-,9^ 4BkZ{ɲZ䶹/׹یzFt`?n-pemzsFdI,2o{}YKGlq~[c)b5ycA򐅼IV?otq$l[Ne1ma\f3iVs9 q\g;y3ث񽲸OrˉƎ"jfG?ґ.s ə$c-ъuk1թVYjWֱv5 f;8yk_ʪTq<7mzZ[lF]L-`hW9 p$(lA?Xjm{f A,+'^pbwH;{_4+,Sjt3^rg'Tf79W 䶥N^sf-[5yTvЉ.ܯ$=0.@}3-o\ `}/N-GD"2/ w :bbζo H3B/.n`@2!/PB(RPW|`G/ 是tD~ d'\{P P  P  6 iP 0 ^Ŕo2Cu"f :V@RPhQ Q#Q'+/3Q7;=$6/h* 4ʥhZjk 5iPPO)TԞXSpPQQQǑ1.loH A0 RV(@ XF* rJܰB't\`W/#3R#7#;#?$CR$G$K$O%SR%W%[%_&c#+T`I1>66Q8Ki(H"!NJ>k(i#v!{'\t) Q"U,-R-ג--.R.../R///0S0-%r[ .'/ ~2(ҋiH B &3 :,+/B+G'3f :!s0sS7w7{78S8889S999:S::}s,1q~/M2U2ĘN==@N = 5яBk2&85\6]"mSAAAB#TB'B+B/C3TC7C;C?DCTDGDKB:0;"<{r<30,"z=wG!P lF 5-b5 ?g)lb():^@KKKLTLǔLLMTMהMMNTNNNOTKSL@RqNFbKUt(-~ I+bI @iB@hJ d`6USUUWU[U_VcUVgVkVoWsUWwW{WXUXVc Oq-PE!\`?۴Om&.Du3Jc[KZg{k$j ^`}<"[[=#p\p{Tr[;Rb8zb㛖5囿[;Glg \c`"<+/3\7|ˁ?VKOS\W[_a\**|k<ȃ\ȇȋȏɓ|;!pRt]Qʯ˳\˥˽>a0aVa\"AܿkB4뀀|b \&] #aa|ټ]\1 AΝoj,SGKԁ>a0 " "*2}չ{6AM؏ٓ]!h׃͜o"؜ām1d9$]םuts[Z-ֳ9۽5&up`A]}=$6"8?C~ UZ"})ⷁ/^}uqw{=m}⭝.=Oq*^}7g^~ӓ喞雾lh~̰>02 ~둾(A潾}?Gnj^0~^>뙝+/zZ#!$_;ZWzZi+MߕP{_٪"b:|y#u?_b0ʟ ѡ*"#N^^< H#JH1z3=JYIe8ɲ˗0cʜI~r38w:6qD*]ʴӧPJJi«Xjʵׯ`ÊvaCP/BTk >nGBMݻx3:4TÈ+^̸qE#KLȹefE.Ac=t^=}Z"ڸsͻ Nx}Ͽ'xzPmC D$(b?SDNvK(∐!T:)gkaT*}8aaӄɨ<!,AS22nn^^``cceehhjj4'& 4'%4*$4,#4)&mm;/+X4-#4)%4/'zP;1,#~O$V5*&("L=44(& vR}\N|O mOlP4(%tR4+$Xd;1+tSyQ#WMKL4)$H*\ȰÇ#JH" ,jȱǏ Cjl@Rɓ(S\)K,cʜI&8qɳύ IѢ*=pӧ( H*իX#ʕk֯`KlسhX˶mptKܻxOu_{Lbˆ+0i8=@<Qvcɜ4(>(TA 0 D%Y_q2HCbpAd<@rж@B0Pp A!,iV22>?IhBC,GHSȡz &&2ȤzȔzȚzȪzȝzȥz01;ȖzȞzȓxȡȚ|Ȣ|ȣxȡuȥsȦnȟvȜwȤwȗvȞ{ȥ|Ƞ~ȠrșzȦ{Ȧoȥ}ȢvȠȝ}țrȝqȨsȜuȗt ))5Ƞ|Ȩ|ȑxȝvȟuțsȢwșxȩxȒwȤ{ȗzȫ|Ƞ}ȝwȚtȢtȟzȧzȕwȩ~#ț}ȡ~Ȟ++7ș~ȚuȥtȞsȤx ,ȟ{ȜxȒzȦ|ȝȞ|ȘwȦpȧxȡsȠwțvȣvȚ{Ȝ~Ȭ~ȡpȨtȢ{ȩ}ȦvȜȧ~ș}ȧrȡqȘuȨuțt12<ȕxȨzț00<Ȝ|ȩvȣuȤpȝxȦwșvȓzțzșwȨ{Ȭ}ȟpȠoȣnȤqȩwȞtȢrȠxȘxȔvȦuȖuȫ{ȝ~Țȟ}ț{ȧ}ȣoȧqȞ[\fȟqȚsȡtȢsȥrȝrH*\ȰÇ#JHq!G ȱǏ Cⓣ lɲ˗0EĦBTɳO !% Μ+*]ʴ)A:&HQNj:rƇSe(U*VhӪ]ƊS$AlN kMR =hTi]X) 8h\q K,# 4p2A˞]1,( Ҟ ;\ #0  T\pEx k.0 L8CW@<}vigJb-%:1"@|f]A`@vp#dqf"oxGps ( 00굆r A@( 1 Rı B,FFxB00J(RvW@!,e@*22𹹹BC  GHS &&2))5#01;곴++7>?I󑒕00<12<[\f @A < |qD2FHQE=J )dƓ&lD򤆕IP`˖'!D)@w ?Iκf{:>J؉&(6̶#c̈́f.7Gg輼AFS 0GHS  ':>K &&2f̳蛤f)*7-7G{z˚ސ cf;00<怮RڲzƵ[\fH*\ȰÇ#JT再Pqď CIA)GzTaӧ A(3(Xjʵ+ԯ`b"l@]˶G)vK7kػxJ ,Ruo !_C2a<^dϠmL Bsװ]Ec-{̮Dz+Ĉ-̘Qqȗk7٤FItPٷi I  A * Fd"|9p}0՝QzVЀ,I!Aqء}Nm":D8AI.XY ݘ#?a#Dp )d 1Q 0Q%qa[V 4Dbv"m ,1'|BF[8FAi *#mwZA,1h"hnx ٩vcV*"EC bp* ((&-h^>vb`  |!G*nr+[ BȀ.b&n `'lpS~p]F t '.t G,ˤU"-<ːI&!,^ Q112222111122111111111111111122111111111111111122111111111111112211.6+:(>&A#E!HKNPOqReT\V VX RZ N[ L\ J]H]G\F\DZ CX AU IPTSMB/    ##&&**--//2266;;==B@GALDZGbIbL[O YRXUWWZZ__cciioossxx,UrȐȦȹ̶P?H*\ȰÇ#JH%Ǐ CIœ(S(F̐0͛8oɳϟ U e̗3#N[ʴ)SPJϤMiu+կ`Æîh]˶H<:,EݺnN ˷a~KfHǎK<cY!knL矉I.^8Ӧ?^2 Q.ͺmEN(߾o :ȏ_0УCoNZ؟[NHOӫOo{ONo(g }& ` F݃Jh!ud^!q$ږɉ(b,ɋ0c4R&/֨a8޸z(#D%dE& ֑3*dTL>E Xde\Ǘ` fdz$_&Eh)&t2$guНc@|矁1|$袊F*i9饐Vvi騜J' 'f*k9뭰֪&Z&J& %&lr6%J%ZK%j;%z$ъ覫n枻w$[$K$ $lp|v$# ;\#KL#[bwq\"#L"'0Ǭy,{|!8笳3wW3A"D IѡL/PtuMW4AQg=Y]@-d\ui!h-L B-|w,<qߌMQxm3ONy~_y{&褗NC6y桫f룣z8znRS Kß^|NaqTo~SOoWM{OYO柏H#?ٟ?)z (= #:2]0̠CG~/!IyI"60̋v"Ra[|HqkBdKD,чMNH*R1±lQ] H211LjF֬Qm\G̱u>1  R!,&IJR2&'IlR,'-JᔨL%*KU+]˼ᖸ%.k]l/}LL&2e:3ͰLS5ͯlsݜ7N v3Qq< OS=ݙϟ| (@A Px(DZ-E-QlTIFJҒ4"1JGҐT- fJӚ4NgST=JԢ51RԊ,UMSՉhX*V*z\HJֲ51ZNJև`p+\tm׾5 ` ؅ VU26 qd YTᲘ,f+{z5g=ڂPᴨM-jKKպfK6ngH .p{+QHr\2Q-KRW. x =xӫ^ | m~ %>po3$~eb+@7{ GL(NW0NNfL8]1s'L C62c%35v2fRUK$%oBP /,c0s$8C|+(\Hk3)1Fkt.L/r='C BdF HB b5!D'~VDg4 -u i:Ɇtf0yui[/>&v}xOniSRvsQ6qqOmt~w-o7|}y8^I !ԄPHnocQ]yk%!CBhˇB5-IӰ0 Nqk#^9SÔkt;̼0?|0} O7Lқg] 9HPC'SoVΑ@9f4zaZ4g_Л&vǽKv{v='ecxV6e;9yLV>odBvc88Gcø.b8$^aa`8|Ƿ_۷|5{ϟ^7Uwo]C~I+2~5k_p_ !BJp)Vt0 kfjvs jn vf%Wlg6/(E3@ F~Ɓ,x4x; 8:Hj>izvExu фCw|fFi@i>pvMw_J؂Adkj&Fa膼d&!Çu!,*Q22#>?I89C !&&2CDOtt //;$$0 ))567A56@tXY\<=G23=%%1 홚YZdt(EFQ:;E P*\ȰA#Jqŋ/jtbdž->L`ɒ&ELq%K._Z)S"Ehag ԧѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]6Pt@uܥԮ^}ԯ`&sbb@^(\aY/)>Bт5z`` u`D!@ lp*CA N/x`@!,FP*22>?I#ѼDE#))5Dۻ ٙEEF!"-pppښڙEF>@KlmnEF<=H!!-$ӖFDFٙG3ؙؙEEFq##/ospsqEEGNOTFqssEEڙ.MؙXY\ؘٙGpFn՗FoFPQ[23= +ٙEݔE?@JؙۚԖFL"@*\Ȱ!C-Hŋ3jȱc CIɓ(S˗0cʜI͛6uDϟ@ JѢv]ʴӠIx@իXZx8yhZ񁄷pʝK.55$rf3Ks,X̸ǐ3ɣ1$60èg9".h@ӨS>Qi/bX`!H۩D }PУQAسk:>[pà=c_]A˟O}^ I"&g4F(Otrx0\7 >(DD`(,.Bh8ՠj衈&hLG񧢔VjXt駠:v*ꩨ&Jjꪫ«ꬢ(Ҫiv밇aK{CP촙NQR2k+#etKvPCuĐ G$E0B; 3D аºr`Ņ,ч#SLk ,2Ϛ(\+z@1s 4@*"t!,X9022uṹwԇ;=ӽpppiإ$^>;.M ˼߸;>GHS#=`|&&2))5``ezz79D`>xď$zWց=aځeҳ\]7_Ӣe++7|}>?I쁙Ӊc00[\fyH*\ȰÇ#JHŋ3j<ȱ#A CIɈS"<ɲ˗0',@͛8 ɳϟg)ѣHa HT@ҧP^\ԫXRh5ׯF^ ٖb-=˶FtKLrWaڊk nbx8㫋%6~L9i䈓+kyb͠e:7鞝~>z̜qnMۤ۳k߼{Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼&_ab ;`6,TcH8kmR`av,F^E覫l8/D@@/?l0khq/p}LBWlg0 ,BT,rC,EP1<[L@ B/@HG L],5(A4@e`Uiu06)`6L/`kS\togL{S6 7T@|PnSpC<Ғ@NcN曋"l!7?nz!z۬[|x`7.u`\3{q]S@'q]'t6t__9h=Ń dqqͻ0O c82}"3` 7@7O&@u^0( RV^ gدLp;X@BC?G`a[D@b"#ڈ&i.4NГ6X9U2x_+A )A0J:D'JъZͨF7юz4{pHE!X"d#VH,}DcbҔD=Ä>Q$.%\nҗd Q[J)sU41A@# `XJֲhMZֶp\(ծ%MJZIX|ZU$:)IkJ?alJJc]e"Y,uD=QBNu A bֺlgKͭnwuF2;OMr6΍ntZ׸nvz x{ Zu.tK^׹zً\󾗽sͫy`근/{*/.ΰ7{ W`MTX \80gLpJEV`Vu bHNx%>}y9=0B.{`䚖V &1p'?RҪ: G2MBЈ֐!=WMṾA'Ҙδ7XFe<B;Vհ>A<}fq`Xe Fvj0Kf#(ÎM/Є(M@ PЄL,AZOy^mhȶ&@b VH^ F&-lId{7G~ol7 q;٦w$0,"ζ0r\,7s@@c\ +/m7޹EcκgcC^ofg Em+6M+&/@0[^r{=%F.xv|1q,LPOIpx'gxӛ}ew77~o( 3ύkrL' 9/ȹ}R/3^ =O9̟;'qOt.zy'|xW{xOt~g g~7Ð{}7$J| Oh}VnǦgՇ׷ns''y H4'totgrdxGwWqJH{GzQq@8pGE{{u|' PMgXj`xjHg8Ƅ x xwk'g gЇxh€{~ s(yҘsoVi}T)W~XzQyy'yg]VGȐl9mȏuhzY[} ǀq iׇᇐx;pgؗ9noٙX;9Yyؓ qv52 FI}*f}J}2єAsyd xow\"x Xo7G{1W搗x9uHryyMӉ'剘9۹ex yؕxx]j ٠ʊq`},vG26{+مfuWyǁ:syGz]Ȣ$.*xףc؀m oyٖj{ sIwه ɐDF*xy)h9(9Hӈ}zy x  ZvzxXa |i:Ɉ41s,s8HpCxq O`OqRhy tC7w:%Wuyqt𩤭 }rzZFZyVىЖq(sw8̊r'yYzRz: | ~m&n1Q=ʌKiz1IگdBizFj>ǰ [{Kdkn ʨtۉI(*eGֱ/89 "i,{8:7tIy6˳F{HJ>یET[V{۴6C#Zb;d[u4Ƶ&qC+akpr;13%_KoK~ `2$4˷&۸[c;h,!6"Q궉VC{ۺ;[{ۻ; !!iۼ;[{؛k`[;[{蛾껾˽h[{a^K{ !|h|a,Gl" g|(*{6|8:.a0L4lh;^smo72- -# $a ⁍$ ^Nc)$>Qfj}3(2+.<>$9~2f.>0޷46.䀢V~XA.~2D>Hca!JC34npp^;v~xr~.1 6"Hfh M+b,P= m- ֚^n֥~ꩮ ֣.o}Ґ띞 PP݀ ֨> >>NN, @BwL )Nݧ1f3Js/ k?yp?   Оm ..'+&_.8.o֗Goe.eeAO0@]r}Jo}?{p?5^؃({HohqqЃ~(Yq_ZZmh@ ѰA+z-Q"D=,Ꙩ<~RIޤ-M_B K&Ff(Mn8?lMZn"_$R0A&:Ԛ=)F(srcؔ0u _UI U'Б^Ip1„l\ $^ƜYfΝ={\@5 X *Kc9sW b-5ؤ NmeTiݤL:#TIiL[rG_Ǟ]vݽ^x͟G^8„ 6xQ A0Y=$@ m 8`Hk0B '"=(`;üaK(>iF*PLˣ IEJ+꩸n*}+c Y1ƯiKF4=˯7İK/| 7 ?C3M5l$͊K48K@ݔ#.簠s:+NKb\@I'RK/=ЃO>O?0SSOe8V\V[i}V9K֢ /v*Bt!gJVɏ .F(!wI/m=ɴBԉoUűR rܢrWdUW}uU}9(Ӡ3$`;sӷ;M4}3H47ߎ֠X7KFɭGIUOF9eNW9eU̷VZW^I %Cdhz]p]:է$aڪdAd|`l+p?* ڤmZǨdli cà K<`'| t:K̼smEa,8]$Ӣgv lټ?YԚK=xI#GЃG>ygy=upfLo{ﱭbxzv{2[#j޵ wWH,#a|j%9ρt gUЂj:ӃO Xç:%@isMBaN\s`: tC /w]BE3RݬG,4щOb8'BhbE.vы_HE2ոF o,Ő8G:qR?$OA5Q̎܎ҐDd"HD zad$%9-,1 I-'C0єkt)$e,wD,(Ht=hBЇFthF7яt%=iJWҗt5 xP~:;FuUjVկue=W o[cֿv=lbǦu\ߙf5=mjWvlnk٣.|mmrFw n[u5*`SwHߖ7oGxm:Nx%>qW| v\^[yek65Ay_hY7yus?zЅ>tGG:BO9WǺW~p+[(oԾvo{ۡ0?'w{w^>xS?ƾx7|%?yWe7x`3t}Ez3a_7 2@ˡ=h}ut@;!/=V|7χ~ɠ^Fw~<~Gտ Y .mmo37]8h3< 3L:$C0 [;, ̂3@@N3pKes@ !$"4B!3d&tB&#)SB}sA.A{^A*T5LB{78(\:B3<,̷-?A/+[;< PEdFtGF,JKKHN C>RPU;TLU,4.YZ[-"D3āо a$b4cDd4 DoW]j${hjmFAƚFi9jƚjGlFi܅*0GwFt/XGsa`GA`_/js-F|`kDŽFoGTy jd}Fy IWkr;Fedɖd Q,,tEW43<4 4Xşʟ0ԝ1t8_l@`|@ Ѐ dhʨʩʦ<ʬ̃J hƤ1|L8Fǰ4]L˶|y,KDK|HYxTm˸\K KIGp`Yǿ|T"x̍d˵˜k\ȔFxLOdOH9L,GnKxl͑ HDOϜ+ %P9O<mJ'uMBKS9 >kM868Eg3J3=1pQMS,:3J3XE*#msT./01%S.E4C-4P-9m Ȉ<\FphGlK@EM1P ILTqLSCIFPƄdL@H{-PLUYTFEOOPTTMA9Us?7]@ ;݀LjɸBM]?QW`#63?8ҜiN+VW-R JR*RP-3R2{-3e4EOcS<T/1SGev\رGAeȌXІ}5XyK{H5LDy|ՔeTv[XYO%I 5Ms\qg$UD?ےZ 1YQIfUZ5S#Mrmm^NIR?(Q$!HxR|5۳5S"\~p}Iآsȇ[kXP}PLT\̔HTtPܔϑ%ܒcYU[O];[9KT|+Zn]30V3dW޽I-WKm[y55z=״eNTS왍3X[,g M҄Tym|=%u4ǽl_u|_sD_uЋKW`P|XmY%_LiL͏_6 X幋>{)IV]ua*Eק?VKa=]?pVqMsER5uW3؂/`&v'(3.b1_+̲doT U{d6 eGTM?P|HY㛝_xDHm`f,L>Pez4AVHj7ٜas?.Ov Za &ڥ >9eV:Z:=RSFdQ>] م!sRgRW.cFc*^<{[-E&2jf0;LmfYdkg3M}^.MtVeFS+&C\SifEr0|=,-L&:~fGճzFhQ6RL7IpN+fuheWWhֳ=脦{f}@hf&ge7(5u.~.hh<C'b%jsFFVj'.1[30i>m[k=Z&덚Vk'k"x+̳.k&gN;*V*給?[&xNjB<cl<Vm3^~eSP3:ΒCkn?{~>Vn::[n{nvgu[=oUnnfAfvW,On~jn88GWpt#p=3h[ 77 pVp9z'4gwqACoŖ24p2h63#?r8#%-!/2"j$)2&_+2'm/s4s r r9 5gs +x9s46<8_&K3A's8-s@s,BH7D JEw@2IN-K P_rL1M2OGT+Q VrR0S2UZo1&'XF/Ĥ_ ruv2u ' eg)vxv8?Kv'kkv8v"pVvivouxqglhs?thn{gwsyo^g|_\wfjg;OWz(wt7wxz/ryHxxxVgA/yU:yNyn_ﲘ߮o20ySy򠏳_.1z#WzbzrzOoǭ1*/w{?2_ϭ1{s,Ւ{/r7||3;G_g|gx=/{|j| 'o0W}|97}B}['/0}ܷG/W)/w~B~gW~_뷭x׊K~b~ o/~nt%#}w:O.,h 2l!Ĉ'Rh"ƌ7r#H<8„ 6xQ A0Y&Μ:#&'РB-j(ҤJ2m)ԨRZuϝZr+X#;X䶩gkm6ܺw U]‡Zcki#\ҧSnT~ICv2o=|ڕΧ>c$9zx Hէ w:s]r!t j!Q b!%&Es& !18#f"ecv.cX(V"lHEy$ M:  OZ$Yj$CuaiQMiac%mA锚uڹPk'J7O2'VўB&J:fd)}j5_Q:*N)B**vЧUZzPQ߫Ś8z,JвDw64,:%{-6+жVp2D-qe{.ovۭ{ nG{/V1I/kμf/ø+տ/\Kl {=|W XyAD<2v2:ilr+:2O$W.;+OrtNW/͏ڟ}MW?9k~,^go#X_Rk 2!}8hhÜAFAAkyK]Vꃣ 7>n ol Pndł?p wиu@ FX]8\"8E4wO\XHD/[<x.f {GE0yjD :6:ύöXBNL!_#,HB&NZ"}FSq$ i8LR咤<"Iwu*(xL!rIeVJ qFiUr!uY.OЗ D1hT:5B5 ,%S>Ȍ 6y!™'bFL:(1B^4b<)P@>OX}5Ã>+O\(0PrF$E+jWb5cGS*2ŲBKZmT6ݣDAR_t})1›y,=Nmv*գ^*aITSoδC*X$^UeIS!*-ԩUܪ׷Չr+E.:.z5{=,P ҿj*JLajGR6+pM c+B'jeCˬJ3Z;ѵVUlKM{ډVd]["Ul]YV_|ۈ4-ln{\҆H}BgUkRFWEn\&V]l^;ݾzQ$=u[*P;& ּAmzXbV$fT>+7"o`\[=\]+ f|)KF,nC;3֫'|C$/q56rcd)d2X,(G9GF25d,OU23en$sQ1D[zα~j"aݳw-^/niC_Y}uV*кHѧkjbR~B}o(lw=˝s6C;&5u{~s)T\ |pP' ?HnZ{Bnmţy]e?cwO: 7Kr<2OH(QȾ_6Pf2کrRGzFa Z ١eNaR bUba!"b""69bPhHB`] V"֡&n"$)}!"pBX% **N+۽,J`](".bbb'n--b:+c0c33~J4VJ24No59.c)~#8^8"9#$>nh2#@"%ʣb=#5Ң(Ed#@rKC:$;$ArD8rW%>9J'b#(h@7^dGd䪍G#Mbob+$FңF`K*G,FbhfB~&&f%VaKf%fDlRDUZUڦ9f#LfO"eqpfjU$p g4fEgR"XN'u'f&vk.g4gw%ID'2oڦzcsN ?qJ5r#<:ghާ=gwV#R@dE.CgzVjWGI5&tF@ (7 zg@B$$((t(vt(&$$~h?"C#f(K.V1di'?ިIZ锶h畆%""rv)*(*gxn)jvVi){`'q*%z蚊i"ƑSi.iBJj2G&Xhz)>F騚jNj^yX^}z*~=Ujꪪjj갺j*6t¥A])"+V{Īng)xBcr+~kz+k^*zwV`*Rb+Z++i~$kɘk=hr*ºZbrl6^k࿲iŮƲƾ엊!Ģb¬*+F+T&S,.,lުV^mzj-k*- w-^mֺbmr"mȒre.mz֪-޶+f.&ꁦl2mނ*ndԾeeNޥ楸*Au>ކLԒP/vjnlp.KnJ%栂+e"fbnmkn|s./[6/ZF&6U;.~~mhŮmo"n܎mf>~D.omm:^,fV;m*p٦opc070~nf*6)K+0 o0jp"'R"G&0_p ol&Vj|/ c #qpn.1)F0 l%ðo1R 7+b/Yj/dwqgS**q鶱mr%/1ˇ1px~&0%2&2&r6r,.$$?*w&q+r'ϲz2pN//p0.;s!G0,71 G>s&{+s2 #3 )os3w4K37w-G.wf::ó%{>;IU=c3d?_2*Bq@LJ@PA+Z.9-/:=['G_-s$o*FtMGIwtt.k"JJ(g4t)OôI˴KWMOZ1IrR;L5SZ4&VKOW#JXTktY42IZuSS UJ\Xs[+ރ5FuOYOe:cG'~HuIUibK1H6ԴPZhU c5a5NbGi{\SnEw]W[v*$loV#d mc\k'cqeKoD?W_>go>T&W;o㻼A`f~Ɂľ>׾>}?'/?7??lknW?XOo?w?COġ#cAJTǿ?׿?O/@8`A&TaC%8bE1fԸcGA9dI'QTeK/a„8fM7qԹO ?:hѡWUg< ?$h;}0!h2nk?mRA -PMT8G!TG @@a24H8%II-,χDH?UCi[qR]à Va613c18 AYfApvfb6XR%hUZ%y-7\MWu5}Ay^yWK:ejwyK\ރ[=4]^٭1n⍣7w^Uvo O8ьicYZ衉&Z3niBPY r9bXw筹k/<*N[nAjs^W{ʯov,9J O\o!o`3fAq N]YG78̇|Yb5 ]yiB}4)JBBt+a;U>2-qKERs/La\0Le.S|$-5LiN,pXMmn(Nq,$9љNuq|uΓD9rxړ ɂS4Avb2bMC! .T}ڧD1Q& GARڨR Z-uNHjɥ4,K(KqS(JJNԐҧ!P{0$UUCXFT'{2 f $Pe5k=JK!J IֳΕL+~:ƀCX_X5aX.uc!:#'0Yng?k Ўv?HZծuka[Ζ?@c@-fo5q\.}-N֭3 '<P0 񎗼5yћ^u{_Η_ Ab/E/ 0}cu=dt"ԺF8`&cOxwAb%6Qb-vac!5~ _\ `Bh iuh( ~#X IX]'l]f1e6ќf5m2gſ;?qd1`$#23cI @”/\e%Lҕ1iMoӝAjQԥ4DG8L<!!Dw0x2~!<G0le/vmiOն}=x۪f5K |d> n =`7zĞo}p7>=xtֱHar;d4(e  A0Qr-wasϜ5q~=,<א"pd:D0A[[Sqq؍_M-p-ol]ve7ўvmG_tX:}xV0z x/w!yO1y+^ɦ{].qrY{'qhEoկnxϞq{|ybV;Z0񇥗{ xkr]8 ~7џ~wC/"-ϭgZg)-105P<,/aHN*2CQ~XPq0upy}^PC~a MIO6TpH_'c?IBCM بKLW01;GHS,,8))5곴)++7((400<12<[\f@*\ȰÇ#JHD-jȱǏ /ɓ(SnHR˗0cr8̛8sƴRϟ@Wѣm$ӛJkF}JjȩjqT`BZSٳC H[k2}KWܬsuʶl޽f6a$ ^/ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKN؅ ܻ#ˇ?4z =O7 LA`0`JRX!P y$ H"-8&`@xd@ .EP!,Y`^!22FF#ܙ,-7>?IǙۙss @AKFFsFFژJKVrrF$FݚۙFܙFsF,,8sFۙFFGGsFFrFFs''3sܙ22>sGGssBCMrrABLrrܳrGGsrܼ_`jFܙFۙFGGGrr--9ޛGH *\ȰÇ#Ba@3jТE CT–(S\ɲ˗0c4͛8[,gK6gH*]tM4).E#ԫX+RXLJժ׳H $۷pߒy@d̀W/ @ q+fn`D>[2$3CDsiȨ 4N؁h\G(!hڶ#\@¥a֏WNQAA,Jp]:+JҐ@νpj x?,GXA]=W8so@|H :yp@Q H0fa`0!fD!jh p`!4a:!?I @AKGHS))58|@92&&2,-7223>78{++7 "".((4$9BL x $?@JA1)Ɨ`akx|H`A2 *\  #F@  ]p 0@402QT e&ʜ fK*:Tϑ ܉gˑ)J@ OGrBׯ^1}Z!س}6m۳hlC%]Tw/؅p"@ V4PB`TA`S E(NV]  pL !,J![hmn+m2oocK2& #""! -06:8< ;:P+^ cb)\ I|qg&tdehd7l~Φa0m7+c/e|LJ% `\s?$h-PNzcg;Ilt17).p ԸllN’Įa c9UR(Ha` CU Xn @7L̅H*ZhY `1Y KBa,FR3_p2N%:aL*Wf4ȫyy%uS! ~\o5e2AO(lO/U3I'o `R:Y[493)9d1F*;̟h~`b2?b!CD'Jъi*s@زʗQˣDݖ#!!ikπMBЈNtQqR*> }пA΁JKc tF,-iDၤj`DtCjI@#w^h%I% ֛Wmj "CjLS9X=kd[]a]l%HlVN )ot? vp!2qo$.5Wr)rn Gz_#逾G/DI6WcA7R?$L .K8׸%P mrj;+I+K $FHeސ!a_ޑӘ6Dtr[#G'yՏ}BH_r_v/q{Dxpy#_/h!DwzW{?9CTnx:<l^ggzkB?~i߽ӫVD;Ͼhأ\$?rK>D&s{zI| 8+l}gnwTtlWt{~| qc'z#vU|?|t5&xW<zovyeG a~"sOw (m'S(J(xfuWE#z}Wywn%o1ȃ|mXKln*xuufVnp3x'|F(qdHk{PA(HgW׆3&z?&icx@GJgTy%yg&2A_8~Xt6hs6EXWLXz&1A႖j E>h5~$Unv~֌(0A`u5x~X/(rJg8Qx1 TyYD"x8 &y(*,yv-.Ʌ9y94c>yDYFy)H@@ْHGM#؅ehxUuKɒQ!`bijH4s2pDv>Dcyx7na)(YpPG؊v-ٕ4{͇*gyp8)sy;>Y< 9 b陥9~(QVyWXI (>xiIْ9{ [WYQ iɒJ Ci9чm))ɞAY Hh)ٝRY`XYjٙc9ZEY}&1Ɍ(hIFi(JHٓ y1)'x9:ʒ96NjXיGU$z Y; iנvYj9)`iI, IzkUK?_t*ɡ-J-+ɧi~u:ѣdڡG,ɟ ѦZ G|IjyFyn{j ڥJ'J-٨U*@zY:*~XEZ4;`9QOrʐ glg qg݊g JZ!  㺮~zjުڭڬ(Izj\j0zʓ ևIi{jjʮy,2 ZJ۳/0>ʲ:Y"9[ʩʏ/1z +AUkcz6:'F:K4KKk:q˳C˴y?HsK˷˭|l괣  Ie;t'v)K٫0 a s9zIy& Ϻ(ɨr*+I˴{3[-KD7K;۸{ + dѬsu VtFmfɽ:*٪h ŋJu+ [ L˷gQ*ɽڤi ^ L8!L걩  Y۷l.˻k<);ūBl~by'9Ib1 `i˵k-pWcLK" &6uhkT {̡Ѓ-WGO{ DM7.qnn{M!MLWiκ){V-אN0aޑ ñ W 蜞8֥tWt|믮>ImW o>阘.ϵ~-n2@`Nz>]*澄#&)zɋ,ӞnL..q ~ O s9Q.Zu~s^Gr~殞 z]uh|ٮׂnk *^^nwy>ꍛ/0*6/NFfuJ~ՊP^>jS@?$_meng)Lo˽v-Gk.BnSWk/4OVOǞ /Dokp /[aYp|Ok@ʅ_.ï/~{N?1A@ 4HDaD-^ĘQF=~RGo%MDRJ-]SL5mŅ=}P8]aDM>UTe<$ЪMYƎO]{^iYUV\y8Tg2[Xbƍ'Ydʕ-_rgRw5ÝMF-N? F, 6ôi[!A&;wFXtխgƞ]vQ>|quCzsu|(2sݓ~q'V[@9ɾB /"2C?SP :o&,E* sMsqE{1HEu62: J+1qDO s4˭8 ,/5ވ!,k4b+%PC1R-[SNG769Ⲫ!KE|@/dP)4!Re?t5VY;L3%*E;5T_K$1n W%(83V5[*aն[ouE;j!t6҇ eS;AuwΖdQoƐ[fآpǥKWxs_w҅u0VᨵH5@VL%yTG^aSf}߽$&hԔVK.C>-d7Nb0!wcZ w;&О]&W4yji3XMz8ߞS`TBbf\ʳ'p:xX`8bys"Nq`ځfg}Ϟ"A54$({\ S]WΤ^d 5yezN:L yGH>:eH]q&n{2eL$\=@r6qp~INo/y.ĉ\ne`7%RSCG#I5E_ƫ\ nT%-iaEŊOyaވĹ\_Sbc:#6cM" F|i<FeэE]#\$ ED!QGJچtkAE>bc%2$/LX+rAw!Dx]䝞#JQ R{&14o`%AiS_JRKr#fF)-R2\3bFSdg¢` ޼c<\KH׭ y7"%|i]O͟jo>50+?+!$3 I09ۜb{?׳+/K;8a5s˫+ܖ3B@!1TKb< l;xۛG) *YJ*)$ tAa&糤 kÊ =Ҿ})[ @bBY6d' :)*@7..ù8{#۷:58dDƑú,C9lCTM *DCR6JGLGdŰD¥+D ? S8blWtCWDFŹP@Jȁ Eȋ=\O /ODCBa$C˼e7DYiFP@; (k,fj8_*D,ql$5duu$HWiǶxxL={d,KFx {~$2PDHl+,He$ɃIHXH$ǰ&n<$|HT@5T=TU<$ʢ4JHɮXI4kyQꍈH0{=Iɠʣ$˲4KHʪXJ\Iۑ줪 f DR""t $4уr1\>h -Ҳ˻ ˜, 0F1L8$􆴤dLxȸ Hd̺ˌ;~@9$M44J䋿[LMM =q RT\DK$4䓊̘^_o-JHc4P@ϨO%p#ztM< ƁOQJL3>xDзQМFsٔ=! CP #=\7y$£hL!r| PL1ɱH$QA1%ӓ(PPM$0\Ɗ>`T(kJB*D 0ݢ21=ӭ`N5U?&m/%1M+ՠ 6bP?=o AuB5TcHQX !%)۔= P,UwIsT!KOTP#աaOuKD}0ЪՈЖSeNMU^Ԩ"&QVq>QfU؅=,Qb=LWUnUoMWRֽ8Ւ{S`( EdfT4Et#ϊŢͻ" @=Mp:XhFc흀%Y%&xWZiuؖOZlVrBWE  @ ڢUjGKYZ%)ے-ᲦZ׭٢ "Y`%Z (ܡu4a\˕ =$/"ٽP\hZCE j%5 ߥB}"^M^TB +&e+ԥxDڭ9U"Z \^X~Ee\@_u4 dލ8 'U%\-S5[}ܩ_V0-^ U_<ʲ] &S%`` + v`R]5R-Wu%4N$>^" b&^ra=Cۘ;0 .cubq<_]-0v'f71;3oW8$7㚓%J3.a4A6Dfd $dA5kJK16K}1bLPn@a5e4aaQ. >fW6 R>YT'haX&W^ Y`>N[>)b_^Fed*g.Mb6-DfQj[hfÔfRGY0`lkq.gse`w&on0 > Y&&Xgv6t{}gQvgx6衔紕&/(0~^|-u膞h]&iKh}~P|nhghhY6f&9K~. xhvj j0&8i|n먞V.2xkk&l\"J{k{g%ivjvdž쿾Sg.Ѿæ_8Nú p^Vj&ᦨ.f-qil|mm%n&`$8/ hn(yh|ʞ h|譶)~ fo+o*iZ^n[% op&}3O.h|nopxo%oOQn< ,h „ \ÄPnʖ7JX 0G(0E$Wl%̘2Y)rɈv'РB-j(ҤJzk)ԨR.j*֬ZrEjXk)[̍DlIPrI rH%6)%B]+Y0}'t\-J1f(J{zsΥWn:fenj6WT7‡5u w^Q^R0t]..! 0IX.-1WU?.E7ѦQqx`P)( :`Dž%P  tB 17s^_ -BcU7FaVPhSMHPl#AY]*bI*ՂM$QJ9bMP![B}s0mf[]8c9+fj; E'u*9(U:M(<9dJ`]ifi{yXKaiyJIjIџ<֧瞨 +nDE~jФ&h*lWi_öl g,ٮ*:^AiBK ޻/E9 #2y)-kD0(fgyJh깹% JdpLc̣]12eE|QU;hƸKgG-_릚nwih7Ax:)ъ: ż6'D;O>-. ߫ rCk=^t@5s_m51H>O94;?:ü`\y `NB.,g~jQɨ Q4s-u*ΰPTfrE%Vtռ2r5P㖸sJn'B*uJGUl_c)զ) NSP8\Z9@&f7W>h͡_)51+eNm =4!] $TCn{ϪY2Э9 k}Mubf,V-$Chf:W[cbor4vbw=3,ĩ_\Bi2 ,=dWaHdYuK"_%;1~ ߘ\^P H?ps11PB_ 29J{%^XIqIE~-@6+*; &C=p j%Zw.'xe61gl)+,LQм$5,AV=U+j|%%5 #rMl1aLVbcoruxcvZ"ڗ7è^]&gܚB]@ Mo{7}9Dm6ߒNy}eiK#-`ɷvZe0;q:y`ɘ1[uS88Jů,^#+X[,t(x QxߨL6pnX\_ݸae<բl>GOvO/WP<-CN]UL74Ը= Hnyx@'@$Ҍ>"7toƧ2GݻKj|);o8,$ߴok챝3el_ [9G(%@rՀߴ }mQѭ_%X!F`zMQ &@\|5_iX߸YQl`̘}ax `  IN!Aܴ E 6aބړ]Q͝Diay&H6$NYHi]b& *D]-ӱ`!F:" @P.!%.) @'ƭ-bԤTUZ` `ӱ:b-fl#<":*I%AD1*_ѣ2k4bJyۛ*v! \EJ8 C9#/pF#ZhbFrbA|bBKhDGS]@ dZ $7FJ`CJ" QdOLNB%0rD1¡u$>A`S^DTb# 8nDH^faM #OdnX$C RD#]@6&0+F!bXM$cOVu`ԅYS-+JB7Ra A-&&ܢZEBfdru]fZ"V%]!%Ӟ_`hn`VzZoNfmjųyG"H҄jVX0'qflpvqbB&X:DfʦDcuG%%e@g}G@oMKDqB r2qʧ)bSJlg~VdMd|]]5܃bݽgr6'j}JhvZ}J`_3LzݟzJޏnD,M؞S XY"uhU( t(dftޗIYy!'c^(Wc~F) FYb(Ƴ#3w猦Zf'K$6jbb,!*% i.$_|eJvRvDwfӔ)݅>A26('I!֩})jV '_N y%U֨z.+Bj>ꭦY _QL |dA*G4mF['6j*L|@<䵮REx+kQVb:IElЧ% ڳ^,rrvlKdRbJ* l d@c!Rj*66LZd|lZШjQt}+ EY)٬\mP앝i.ī* -IDɚlN.FmNmVTm1zɚ9嬻zd=k­˕ HҶmH.:-Q-IB2j,Sײ B5KxUa.iNEmz6:,̇&n_@JVm"m..Ŀ-EEnZdEP- .d mӆ,No /Rˤ@V>,jN +'-ڮzWVrgZu/mn&&" gn*{pAe o0Cm~Q K0%b- LDc~`ia,`R+ spo-RIXl._tn[n>6䡶j 3灂AqQ|Nۦ ƌ?qd~q!f1KoOjq,r4VxEfelH") ']p2('L0rAhr5pJrвuNf@|B/"F1croڦ?14k(.P 66-S2{گ }r `n[2lsq 3b/c4[ o+פGv tCOCrK|,3b@sNtcqʊvr3 4d.-BkB0(M5>6k߶5 7A@$M%V/\qXZ!:v!Dߵq0w73v47;R xox{qRoZ&o|Gu;'5j˳d51+uw 8Q!7KD\rb65Cm8glw3_6Of{8tu`oxSt[89ð:s6.TKkLKK33oWxq'1@'aSW60OqVq /o[3yTS7f2n6 5 r_kϹ)]X7;3w)xev>76Yy7Nz{'eKKyg7{ovs{+Ȱs/acυ7 8ՕO8l7[9]뷵G:殘;3_ojyRa+xc9f9Ezx:qfr6[,{3cqd\gu:SX/ױ{{{//jkO&T7Z{ۻϮkC@BS9z9ҼG)|*x1q悅?ً2xLr\ S/Oj䆸Ϗ{KbioW>1첼>g=+Vy7zJnO_@$ K=;cy7DԿGSO>L(?vOx=@0 " aC!8. Rb&P8rF$=,seK/alɢ&,.hcIi~\)ρ)o,jbP0:jՉ[vp?_]Q gѦUm[oƕ;77wջ.].tױg׎qbSCU)k\a^~} ]'d 1n3bO: +x+nn 1 A]xM‰*ϽVH#NF)AV|)(e0čQ򮰉FHZ?(+P/q8Ȁ̤/Ez|h'js0n;;Ф%oOʨ H<E%#M)-R+M9r! ja +oMҳ,&"P<[y&IЭh DH<6\]/&M+:vLVmPzaTRmUZui XemVީJ. kMUz4Է-C6ʴ^ۇ ÖC).1wwq+sJU|7aQPmI9J_V&bǔygI`Ch$襙SD!y'i]YUt^YsY)l6&cN>;H-~jZon!D kjkbR!g~[fe=6e#(/Z\Sj1U4U`-y:] 􄗠O$^& m3L_,[x}o֥{0cU̵#\bw4}u}M^47s}sPf ,tay= V C8VɜU,0tSH¾\rVA^xqF# XZL /@Dc櫌r̭w,~‘" 7(z@FTқS 4a^!(C(#LdKh7?* m&| JB;K/14&5U,!;û2n`TEPQi%}$N2(F{!cGnkx-COӚ~RPo_Aru IAق&c!~%qV-MqI1c/ar;R#Z5öG:VĎW!Fl>*gy bn8ξ k%A4Ҡ%ڙ53l*'E s+2es5[q|E.64 MQ%v4eDB<:?1/4>TS.)ZũNӖV|L\8ՔM;h.|.)}20ĞWU8DI#Vu"A$L^W9( nEhFJ@ydS)@3<衠ԗ,[]e*ET mi ̓6C81Tj!PbֳZ-X[6OIjC'Ӽ2}N7zȺ%$qy ўeTe + y䜺^zUHVw#v$Oضi< X޵p a4\*q ?aN2Ce!9;$ gu'lYGJ֠el{kʏ *~C'_sbaX>tQW@F% M!3 U kxÈ4Ebe%yv~-=CѳZRԏ9{%z4CYO*QVゲ.1,CX])8Q)k-7$R&%>% !+N(R,7r0mN$($($$2.g}%cgRI* pEB,0# -Er!V /б2SҭR">m 23O "k"YT35U;Pl!x"DqdR7ˣeI'M>3˃~&& 'F :[j: 50 M;j>'*F3&Q4+ۯQSk>9\ClԎq 71@d*3D;WP+W/Y&^*t,/t5k1޲*f@Ct9DE[4!lA+UQ $)+SBF>n0sTDvF!2ٲHEr0s$Mt]t^teD9H0(D3 "r?!P;At47sARM tdȍd^f4B0Xs^(KRe1Q!x3=K3T* mR}$r@K;0OS4a ?'*")U|UIxZPVOp5UW g0`\.SU0+^ FGCfP1LNu ~ uZ+M< W`=9BFENG9\ #j}tLe[7@Q!uMt< pA"cfT\[VK6;2b gbQu5cbc]26{<}vVkdR4 f\3eeuXωYGWp]Rg_5rDA>hc=cv^vP SMVS0avXi""Jfc§Q^*=ָv_yhQc}Ǥ0e8n͉pܤT2'Yovkh$Gk`~g)x`6qk(raKwjmHVo7@zt=l?g<9h >^2 vHv#I)PqrAtw6Ek{ōhwVQ4uu5Sy2yz>GT¢3 RxL;w|1h|!hB7 e.&}Y~j z+fo7{bW&言0AQ 8W8zz y1r%CiװR%P1-kxbmb&gk Jx%O% |2 fi7f~êrWׅU8k.It2x=wumJ8iaPwr"Z)˺Ӏ0xKgÆ+g"%f W?sl;x*>*Q"Tp#;} W^^7f=y}%[(9bхn{?ُMF a"45n|7^՗ f9Sjjl=yc⣾VwG a"YTWly\;4Ca|w֛A9N8%e_YSy0n2,gyg/ן[#D렕XWQHC(3eѵ4rڣe*OȷQ%h3WubWc8vi:XH*!{o ˆӗYkw`:dzb0 1+(.sa:6xKZ*o؉mGrz3Zi/Ȃ8Mbw2G\))ЀE_SVZ4o/j1Y:$4:95;'s~%EI]" uDL[yGk[/K_@A2]eÏq(3MF][[A᧲󚹻ǹ"Zs/ZM1;+b S]OT7ۘ/㩟׽’{J7b;7[W W槿ۈ|;SF!{0lZ3Y#yA*|3|"wWa3ڨYIY ܈LBHmb(%|( s|$v\ ĻMȇm "k P:ɿ#/X zҪz "<|y RWhHP}]m1ex!*֨UCmHĤbmOz\=b|}neK]5*z!= " {~ZbU[v?ߜa7N ң["^͛%Q3ވؗ>! @ՅE1wѝ|^讟K4Ym?g_ J4xf… :|1ĉ+F #I :z2ȑ$K<2ʕ,Qz{ 3̙4_3Ν<{TjPO1`1iE"Jvti JX4U!z 6رd!.hcV(˖֪[ν p_(^7ݩT 99kZ ͜;{t.58"ӻO&Wa˾;i֭) Br{~[x<ܻ{9<˛zG%@|umۿ?~m￟~,`!]J[rrt^$^MaQ g{'|5b*"m w"׉AATT؍M(hцBdu8ZC^HeVJەZne* fFVffdQGWbYSz ge)gvމcg٘ h'_dg~E> NQ餄gXF jJji7Yi~驶9ꭺ+DjK7kXʬ6 mKGZVm{_`-+m=+nvm֔nqk_{nko~o{^ѻonp&qŐlY!pW1q"e1Tr:a# s2Kr'Ts+> tH<(%TB R+FTu-fQM-s`}`^Zs{@|hRWqLb7j'UݔMB 'ۋOx^-ޔ_~D9фgUO "6dwSxc~嬿jBr.{͟7š-ܻ/D#4ze|֮!̗|Dz1:r?}r>G}S+Sŋ:߿S|Hqs\%ǚ/\[eԿ/D$`mMs",!( ZKL++Lj3vGBÊ"!x"~RTD,vr"*b,ݒʼnlp"ؔ2nrԔhĩqQnܣS1:cY(5J}\#BH 2g2$YE>RF") I2L &!IO(}"W&b9CR2l%@2,t.y]"I,a 92k28y&71$ͯPS,睾o3B8 xji+Q'=άS!֔OU3%w}NM6*B BPB41+Z3mJFd4~)x T)'KUڛ2 )O%3ӤT8%N"Mw P͕BKRʓZSNG:^+kj|5+Lɺ$16enjhp5V ,{Y_)WY vJaOvX"\ml^jY=vbhfك&Y--YHZv]}j؆}lU[6^WxkܐVXp V~ 5rY\Lv"nV݆]Rv%6xT^>7cmDk_{wLyUS~߁ͷen9|OQ/lBI@]p@R ?"[UP!-1CH^iO)F8:~ڌ/Uc~9qC`ld[UAɊ?JI6NLɨ \eR$XDp!-1;!HL-x+r gH}du\Ciꍻ*:Ў2 E`#SgyÓ4LЋ(7?PO¦uX]E0҃3=a-aYVLw#v= Uuw-v,Yr⽻>r~/A.sмFCmkUMׁ tr4]oY[{ _;n*.ܠ,zsx)~-Ie}2͛$C/z$ B=T!Ƨ}B׾=IX)SJڕoW{i37M# A>_s[7>~b7gu?G*f.m~Gz~KW'55C`]gx<'68G\G|?\ W%|'f*],.-Gv hkwg 6xDX`Vh~94H^6󢃏c?(|2Rhq@tAfH(`JS ؀-]Ȃt99v6]yw (MH:gjP'28L=ڃ:1"7uׇ=N084=DA@`;=7e0HȈgx闋ń"'ux@xeR'p<(ZYȋ[82X}8Th/`l،37(]P_^(u;%c_DSUH9{1U{h``!(k~ϗÐX!eƍSww~Wz#)>1x3:57)Oxy>>w@)?ȇ)ՏCJvL)i\+9 @D_gc.^_FOXx F_ta ptwZHnZ$x3f +Div tFCR0 i% sH@l/# ֖ᷖH_hzyijG3I%qI_eY/Q?)}t9iȚ#֘O@ pƉJi_,{})5 "oyK^i+ɓy#Y4F9t)i4 HI60'nwxDI6 #` m?c"4 y d Z+ ;YB &(h*ZM^y'\ٜ&0,"iF 1]r $N0**nyHh Z.ۙhCzgɡ Ӓ\ @ c:yJ}{j甸3p0+2MV qҢG?4ds:%[ɦtзF6{Vt"f jZKz*'nʫ򦬱ƬĄhVvӔ⟕Jml*N^jqnN] *PÉp2$Hiե5 I9 1pyKu"*+թd ʱګUyw; +[R9'])P+-z@\B⩱ 3+L\NKkeG6xذ E1k[:8n $kt'pr:vxrz[|`M賄KCf6KkZiQ;eaHK2kF q~+׸F;ۧ *1wNj;[|87;٫{̫v֛˽髾W|٭滱뻬 ѳ]iCc \˧,ݧrZ|x΋RKdS,#|: !L-˺ §/lFFmV9LKÚkR[ZḒ]ċLZ$BBD|C\Į&i,D[m,]!_<aƚkiv5\}\Cn l "ǒA~馓k ȓă!c֛jhɣ,;l.lɐɤ<h!!ʮlZsʹ,©̣n',aȌ%۬!Ϝc L>ܬw \{G^ Pưwl ,к;hsM"-Dbx ד}OՄ=M<`ȉ՝Ls=BؑD٭=}QמB]&9ڰ}׃-ؠUӪV-UD{m*Q-}ixԜ6 J՝ם9` զ!}]UMޱ|g .Nn .Nn!.#N%n')+-/1.3N5n79;=?A.CNEnGIKMOQ.SNUnWY[]_a.cNengikmoq.sNunwy{}.Nn臎艮.Nn闎陮.Nn꧎ꩮ.Nn뷎빮.Nnǎ$0 N.L% P>.Ɠpp ΂N7 17p % x@7`ڎ O  _d.?on'٥ */;Y:GOV>!OWSP!,1Y22   ()   @*\ȰÇ#JHŋ3jHqCIɓ(S ʗ0cʜIF-Aɳϟ@l ѣH*(iΥPJZshSTjUզtvKlԯ`5˶۪NVXݻ7ƅ@߿uڀ@È5cÉ#K6 (̹3W D`Ө  6M' Xtk&X wONx!УKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬW*무j뭸뮼J` lK,kkl> -Njֲmn-FZn.!,T22  #$"  곴@*\ȰÇ#JHŋ3jpCIɓ(S ʗ0cʜIE-Aɳϟ@ ѣHvҧPJ}9˩XjڰU\Ê{ԫWɪ]YҶKͦx@k߿2u@s&JqaĐ#oř@A $k,e, Lt, `AfӰc$$h FtN\+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬz*무j뭸뮼+k&6>@NKm^jڶʭrۭNm p~.ڛmK{/ /!,*22    곴@*\ȰÇ#JHE^ȱǏ C,Qȓ(S\yI0cʜK8sܙM@ УH:,jTӧG6JLSj*kV`R*يdϪ])۷p KwmI.-`޽ Lˆ+^̸ǐ#KL2,kN9@͠A9iI>Zbjխc?| [턴k n޲}3( <D ^ 7O6pwM56pi _`鵳&ps{ _k$ @g!,+22    곴@*<(p‡ x!ċE#H"GrdɃ)U"l)e˜2 Ҭi Μw 'PCme@Ҥ' @KR4hhV %Z0# lF8`EwɊ[@vyM( HqC$P% !<, ">?=<:4-2121212121212121212121212121212121212203/303121111010000/0+5*C&sT`jHk6s%tv smj f'b)U(I+@)5&+"# 2?BBCCEGJPQ Xe2vHEB@A>< "2>@A@@GS^gmqruz ߜޝ۟դȱ  ~rmkea]YVUUWZ]a gkq*zAVo}uidmƙȓˏ͏Аґ̎ՔؗڛޠyH*\ȰÇ#JHŋ3jȱǏ CIdF>RLNjɅbʜI͛8)ɳϟ@ JѣH*]ʴӧPJJ*ϗXj$Z0ٳh]˶۷pʝݻx5Xh IÈ+^بǐ#K^7X3m̹ϠC'Li}\ƬMѰc˞M;۸s'4k N񧺓+_pNu̳kz Ŝ>Vh!<\udh_~ ~EP P= S0>,XLhHy8: 塈@vM;A3z =̈TRcP<\vyJQS=|0dJ'Oy S>'OsTNo-v9hOp(> 1ktB%kՉ)QJ*Ph fiz$O,*`4(x^窇D=R"6硡hjJӕ@eIԖ^vE`%&Cd> OC1=1}9);k/oO:J% }LX5'>L ;oʛ.%ܖ6c-KWInP$|h ,Zd,AQ퐵")$Fvő$Cx+]1d U8jz)?sfd$۠ir̜Og<7P􍑚$A3g.K=`no{]M 8 9΃s!NЕ5SU;FWT,QuLcLq>D=Uo=C0[Ecq,49;UUU̕feeT*=pTEzIETN2cbmBx-oP9vv I; 7ړ=)\yrb?XTj3*i햓̦IR'ʣDUX^ wdΊ{*Q}YR JЂ[MPZ5[(Si85KpV+-T^4NTw# 5#4G NH}Ka7+1Ć5D!8KLgb6CZB]C8ͅ)yfh"FFPlILe0ʒqI*{`<"˚ “ny ~S⥙1cK2uDyKpC.k+wsO>m~M8B3͓;8A^X^:ַ^OįkhO;Ϯlxgv~q\*<8/[17sCOҟOջ=gO{s޳~c? ?ZG8B1 }$C @;xQD?K/i@D1}t5iğ>`p PpQ۷{! D G@ }ǀY1~xe} ~ԗ<}~< ׁ.lG%~~*}&Kx:6DHC{J{L۴PۡR; ZV;X&\^,*gd"f{jkmzlrt[x+mwѷ~{zzK{Y6kl۸Ǹۇ;K띕/H7ˍi(p{t纼›[iǻѼu7s+֛ ˰t 1{ꋱ(m{9˿ +Kk +Kk΋˫ ¿+¼Kºk·´²¯¬ é+æKäkáÞÛÙÖ ē+ĐKčkĊćĄā~ {+xKukromjg d+bK_k\YVSP M+JKGkDA>;8 5+1K.k*'$! +Kk  +Jj *Jj˿˹˲˭˨ ̢*̝J̖j̎̈̂| y*vJsjpmjgd a*^J[jXUROL I*FJCj@=:74 1*.J+j(%" *Jj  *Ii )Iiݩ )IiȉũԿԼ չ)նIճiհխժէդ ֡)֞I֛i֘֕֒֏֌ ׉)׆I׃i{xur o)lIiifc`]Z W)TIQiNKHEB A)=I.!#%'~)n+>-./13΋5N]ߖ:%7n<B~EGI>Kn?~ODhL9T[mX>Z&Odi~mfm.hr.uηt~爛z}lo~k l^v舞lN^l^|>钮{^k>ꪋxknhXHaifK >O eP01op _ _  Sn!nn!15? OD_28?>/Ɏ\dPo@B"8?kn>َWf(dY(jrOj?SloVnV~d9+?_ȟʿs K c@4r?<@ُ\0}pj P/ ? \3c6⡣g n=dAPIR),i(,c]q''$곴JɾLթJJ/X%%ִM`p\%WQ`XBD y1 ERxq9^#H@@ʋ-_t)a̚ogϚ?e}9teѓGE&eIsRM}F:UhUWfEUiW;>We:Tk,ٰls];mںrꅋWl_{7TT[UV\!{ /e3 vß^!* cv ] % 5!'  <XK(^ ;XL7 0]   ! 11 HcH 0(2! TpаC+jB"E_0b%ARʖ&Yr6q gK)RfN;TiPCySK1 zU+׬T6KXemص[eQI.۔SQOKnἇ&obˌ1; ʠ//9wo8藓稇n:穗骿z촻^;;᠁V\T% S_=c߽o~׌U00Mtd-IAdDkB9z!, 22    5C곴 7  1 ( <0 pAD)fp1#E %80$Ƒ$!XP,[Ve5[> QyiAC"}XA' (b$0@@eAc2!,22     곴5  1  A0 C%R@"DBvpH5y2bI,9T 3d _ Ya$͝t t@)H@ Aʒ`ՉpVs 0A­xU+% 0]x0 !,2255Jxxd'xx  ֩Jxyxy++tmmrrbs 3344 VS^$S]ִNU:vv ``ӨJ^^iiMMtt//QQOO<<55VV㝸T:: )S@@acJ/RJմNbcTTq'']$JթJL/0 qq߰XJ/EE%%ִM`oo \peeqqvw%`QW8$H Y2C.$,0bË#"#F(ZK$1c-;&͇3o:̩s Ϟ~M4TڒiJ$ 4(URe^hף_]:i٧gZU`֚m}{.εZνuK࿅maƏ'me's3XbAm4ZjQZƖUmMY6_׶L{sο?=|tO'O|5泟Wer9e SJXq1o+y*I ٍu-pWq"r 2נsERHb rȠ$VX'f+v/&ֈ*Ȣ.2IDXGKEp mDt 7U}_u~_7!%<`lwB Ђ/` 58CЃ7aECЄ+L`BQ?T!fxD"&шODbQE'NхWaeEvц_au8FчgF%fXE:zю`ģHF>яhHmmb"(H7b#9IF%!&zd(; RҔ<*SM2dc+U2c.;2c08?3$-eLGb%G! .%6ٖl 45IM]e:Na4f<9Oe>4'>i}aI[ TEH( H C'і )p!,2121212111111111111111##!!$$$ E ,=B<83'    ) 2 ;DNX\c[YS PK EB$<+8/7163545454444444444444444444444444555555 66%66*7709;::?D9BW9De2Ds?>nG6mQ+jT$mXo[p^o`kbge_gYk%Km,Ao48qE(sSucwpwvwwwwwwvurwususuqyn}kfa``_e k t v w uux{~ &ؕ+•4>CHIIMOMIIIHGC?:510/038?HJKP¾OǿTVоWջXڻ]birxz|~ݖݛݟݤޫݶ޻н֧֕׌هݕH*\ȰÇ#JHŋ3^GCL ɓ'\ɲ˗0cʜIG5s.,W--: Jѣ1oDɟLJJU8 Uׯ`Ê}qY]˶[ߊKݻx&]R} L`"^̸1\*L堇/3{ Ew&RFͻwF՚Yj6$ N!™R8J`Ev+^-gGJ:Ft'v'}e7!$GtVxځ-`T$ 279BTۋyH4jbc*NU[5iٍ(HDbPYgMFi-XXvaSjdveac&gp `oigs V|ڗg`8W&z_!Vz!!"~&i^[6bZYZ٧xzz֊vjn*;o+^떱b?C@$L$T,ʶ,XFl1?⏹l{gl}lZ08닶 ZEoflԳ,%O Xk@`o;?ӱǦRU#[j~,CA<ض;P.eTl@pH'rdLWHJ`otc_mD]Ul7Wk-7BokxTUwV܀W%lNማT7RE.֔GeHg术9RGnȶ^ +;QC宻 94h? 9{+̓ J8?tC{=u>FdM #}.-E+s?C=m#0Xhi E! oDp ,vЃ_MD8P ,l !MheD w؍Lp0ŀ,|PeBEDl΃^7`D{a#S8.lYV=j}q^cLH,)&lHJM$%/$Jd<'[Pi,))iʕrx`^ r$ed)\> :^Ɨ1dozi3?i+!5MP s¦F ҈3#,٪oUH:Yj3;9x^d?-Ѐ:f)Ac\sB_ QEIt" (a.*jT0G?ڗBd$!+N`i\8A 4Q OTРtm)gԵ(u44mJKT Ujbg\#^cT5IYӲua8u[(׹vIcּha_؆vQ),CX(v!mQJ(Me/+J]ZC+'. gdikeۂv0fP[F+v -JӈSWo@[\#ySyo\gUH\)7./yh~~$)8#=@bcz\k\u$K>=h2z!U;޳w:>xV~W-P{썷?'~Ũ<%~;dϋ?O[~H7Q_Ԝ~G˞!{^vO|G$o/Ώ<> .hO?=Ա_!/ ~p:~o170nv p>c+WxڵβH ؀zG6+` -p!$8{p@聊GP !8/?'9Ӱ;X{'qG9 O|zRxZx\v`X%c[ljmIlvsuwHyx{Ȁ}~(~h}†jxֆ KPň!UE֑]㇈ax\؉8VNJ犲'GgxnNjeXJ'=G0g" nj&Ffrƍ&荩FhȎ䎷(dׇDfȏ䏱(Df򤐫Ɛ& Ie ő \Hi%#&1I"e7'œ= |̧WHCi%ƔQ锆&WIe]ŕc %{Fiivoɖt#qyilɗi)E聘Edfɘ_)EZfebYe edid9d dccYciY &J ћ*&%F"fƜ& Ffŝ%EeᅞܥŞ%Eeş埤%EeŠ~y%vEseokgša\W%REMeHC?Ţ:5/%)E$e^`ࣦ *)U rI٤GJmQDꤹ UQʥL^ tIf<( _F}Or٥w y:I}jj:zʧڦ:ZQ QPjPPOzOJONNZN NMjM:MLLJLKKZK KJjJJIzI*IHɊH:HGϺGjGGF E D CAߚ@:?=J<;;Z; ;:j::9z9*988:8777j;7 K8 ; 6KHˉ{686;9K!5%9#ˈ'[5+9)ۆ-31+:/317{:5;=?˛A ˇCKEG˨I KkM+OkQKSUk}9{MWYۊ]+_akcei g;kKm[oq{suw+y{k}ۋ뷅+;k[{븕+kی빥+;k[{ۍ;뺹[{{ې;˛[ےB PnX׫+;㛓[۔;훕[{{ܙ|d\={F ܻ ̚k !%#) +-,/L1L35l7 9;l=?̳' A̼V*|Ԗez8t~fڠ =@%p=ps\[|=OCA"%@ŨknJ yJ,V h<P [ Z=zeP% !=w ahcF\\~ǟəQǝ=β*L\r_a,Ulƛ\ `˦&ʎƇ!|Kf,w ̤`% quW<č,q\ʺy=Ōf>ί 34LLǜ\\| 88ELe .д\{I81ѧ,, Mƙ ʛE,GCEMKM=G I O]Q-S-U}WMYM_aʹc FU[] OM\vJɑ>!|J͍1 =qy &{{؈؊،؎ؐ@e0 ZQȚ͝ \` zSȒmM m  0@Ɲۻ=ɽ =. ڀ -=M=]ޔ j޿٭#۪@==ީ M#qr ޝ- +]~sީ=mՍ"qmɥ]ҭܼ@!K!䙽 <= ];ژ{l`m+ !,J11111111111111111111..++))''&& "#&()+-03~6s8n9h <` >PAAD2G&GEB>92)" $$//334444444444444445454545352506%+/8'%S+b*m$s(z 6> FNP Q RR}TwVp#Ye)\]1_S9bGKx2]m uy{}|yzxxxxxwzv|tog^VJB=71,+1:AGKOV^n t tu{+2ل6ъ8ɏ@FGIIIIIJJJJJKMQYadfgfeba`_[VTTU½UV]_emx{݀ކߊߌzH*\ȰÇ#JHŋ3jȱC CdA]\ X0cʜI͛8sYpHQ УH*]ʴӥ>I>u(TeѩXjʵ׍#"zUٳhӪ]1$[}Kݻx[EW޿ ,q/*+^̸1[o;L壐J̹3 ӟE%ׁUeAtV$)dM8qhi'}p#:y sukߞZjSGx;.xa8#?|u?o>}ws' gzF(Z8MQx߃(Wam^y0%Ty[]u2)NXOHt`?2 O!Ml(sau .c5g>0+?-Z[gŮ ` /H?YX5ʤfMHFŮ+t@(EEʏ1y'JdBl_)MbT|,I\JR6\bY|HK#+&⎹d*SpԈ3ɷhfdԴ51lm7NsI+gEΉN"l'9xb=y|Fd?!Ѐk)AP(tjhC bI!.j4WUG?:&d$uIҔjiKEStiAnSL <oy D՘QJΤlLMSըscUUiu޾ ~pd-@jle[иJnt]=׼Zt_7 X v -ؒ*xmJ JIP/˦d5gВi(iZծ6Kk ٜvS-nҫp+Y=\`1z.ti%龪Mv;rSn+^֮4-Nn\RcX&&n1eX,c!ѸzqLbcܸ#1cxȃ2#%NvoMr(V-s8^2l,fא̨93/ -iS+־]Oek;-vV- (*ܞ˽-U+2K%-ƛ7hJs;,]zHwpQx` JT7- a0"yB~9<9y =x:]pXOyԅWWSbs6:|QM]JܡwľOt]/|NO/xp} &Oy;: 8l7QGOz)7{U/ͷl hCqv=eM;|w#˞}h|챗y̫|"<{|_t~ xOr{շ !3h0]q 0 oP$H8& @2/5(mPP@ 0AHH2HMXmCn@TXsUL(`ᰄiko6XAnvxS|HpbQ<"5>~c'=pSX pm;6T8XH؉X? Գƨ(ʸ ׌  X h9؈8Hh'騎@q;XÎ7q؏8(3Zh(U y Yi%<y2Z1ы(Hh|yȒvso(iH`hUMAȓ5$(Hg委ǔ'GgǕuj'_GUgG7'ǖ 'Ff솗妗Ɨ&FfΆ˦Ƙ&Ffƙ晢&Ffƚ暄&zFufpkhƛeb_&\FYfVQNƜKHC&@F=f852Ɲ-*'&"Ffƞ &Ffş%EeⅠߥŠ%Eeʅǥš塾%EeŢ墜% q Yx7 -? !Ca¤M !K ᤂBI*Oa å Zz`Z^ 3ej0_GS*s:`\J姈%~EyetojŨe`[%VEQeLGBũ=83%.E)e$Ū %Eeī$DdԄϤĬ䬿$Ddĭ|i$[DHd2Įvq*|> KzTگkK kL{ Ѱ ˤ=;=+=<".∰ >j#=r!,522222222121212121111111111111111,7)='A&C lwmb^WOD:/!  6ID<974,!  -53~< +6=AD=6*//4444444444444444446699CET^ `olxwwztzuw{w|x~xyy{}~ ~| v+q4i;bB^E^IcLhMwNMKJIJJJJJJJKMOPNMKJLIHGFFFC@;+ ذ x pmjikmw&Ҍ0і9ҠAάLӶXֽ`flpvzݏݕߠݤ׫ҳ˸ĽѴϺ֧ߗ㉼yj`YTZe}qox_TOIIIJKKKNXcr̩H*\ȰÇ#JHŋ3jȱǏ CIɓ(Q.Yɲ咔 1Isf11aɳϟ@ JѣH*]ʴӧPJJu'̫XjʵW.[~ŘXMcʶ۷pʝKnܱx˷߄a_XfZv+^̸ǐL˘ ̼ađCMiƜS^ͺF j ۸s>- .` +_μSУK>rx5;νO^uصHKDAcN~ۙ~([zCԁ9#NUho †vVy( H(X!xN5 OcNfeC%$QE&)ddlMeC;u NTӕ| T*,SNx+yT(JhO&Ӟ}  0S) J=I-M+L]2DCm,ʨ6wl({3ɒ'l65;%#ʷ߅s {(97Bҍ;iWԷ{A-ȏI6kf d<:S8t+9==}SO3ʟ+u狯S[n}\ P\9%q,٥؇Nng5A~"X+hpT*!05 q5dصtհx_Kw学yꪗNՓ  @(KypRRYf1>F)`q'HTIpVU0;LiNnU=83N" N Mkh"/nP4SZ :EU6Zb@Z䉻 5ICymk6!GIJP5@|a@tH9;lQT+DvQ26֭Wt\&ki2u({֞T7U̘L 0Kcs*F|ŧie V?U3S߬0)#HP O/ hlNTR= bO`I$T urVmeX0=sU)R?5v3ͽTVG!Ug* kRugXBw$T&VJrƠiIB9 5zgD vPJ:El+!9Ȅ5[kج=+PD3ϹH"eu ^*S:3бLsZ/҅FBtjyrW3ևd:1k ^Îڪ%K;N .vM#ڢθFr jQ%*Z_i#z+3^6SOo%Vu1v,l( hr2H'C Jn1c1'cΪcK )zZ?  PD0ʄ/cD!#T,ԕ!OEKF_FeLeP91E2ct=>H#>˶!1225AOv46P>4h/π>H+s>`=hѐtMi:7z27MJ{̗L9MR+Өr2jSեI#jqָεw$;ϼMlԺ/.e/nMmO?{/Ѯ_[/MQ~;/.n1/nM{,񮷾o+N+/+ ox eC@ZBGΚs%$p+sGas[Aq=9ƕwLt\ʸ)~[]HGү>z.v+8׊C\ OW/2zܶN9-B.x{"y۽Hڳ̳-"{*_/(8wϕ$Ͽxg ؀WX$18Ha ȁ"8 Hc!H*h+08-x)6pVV70 00 ,F2y=8o0.!!s ! v0T0c\x`sE(gnP48z pnw`xHnuh ?(q  N8?7 ꖈw(XЈrhEHƉj]I( CtmxgEb`XS֋ƌY/GX L8ШmΘtZ'(|s`xX{K؎zK 8xx؏lR؉8g#f" Ɛ!Y& Aņ"yFa(ْ֦.9&4¦:eƓ@Y0&AFLZRyDaXٕɣ^9`!debjH–pY("Av=d|:yAa٘9!7痢wə晠Y}ɏ#Fɚ暰Y)FئYa ƹf{ yA aٝ 9  !䙞aiYy9I1z*ѹ: Jiڡ $yΉnZ%*ڢw.ڡ,:6J5z:ZgĹ>0o2DzaHJDڤNP::TjVz.Z\ڥ$` b:ZfJhlJnr tZyxJz٧~9ʜzƙ*ڨj:Y JZy٪ʗv9 zjJګ^:RYʔȚF :JZ.y؊ں"٭ʑ9 z Jڮ:Xڎ縯*ˌ[x ذ{s8;{O{۱1 ";*X&;(0, _A63[;=B{D >{KxNP7EYI{X;Z׵^Vbkd x3j ln[lp0s a'9tarppnP+~!sm`+ }!;+{Nۺ+INia0;{}{ۺ+H}׋ko~++k;~; {{|0+| ~ @B}E6IH7PnR=VV}ծ^m`dMf-hǼnO=7vlx5Y|}{؂p}r]\G؊kعؐݐ=E'٘j/מm{ڋ6ڤ}{=}gڬmi ڴ}f}A9ۺ=p۪%o}/ aMI+i=o]\u=ݓԽ{==Z -p-д}zZ }ߙߨNa PjM=xnQ ~}W~xx"g'K'0=a 68~:m@N5^&H"J'N> PT^B>D~奝y\G6dNf~ j.girt^qx~V~m>]y܊=}^}.nz鞾"^>~ꬎuAn^>h7Y~<>[QƞȞW̞'Ҟx^FNe¾4~.k>~$/z.e1n~8.>UN_i~<* ?g 9ߟ_k~ _ "$_*on'Ϡ)|n2?e_UTU&EzR]~VXefZmݾWT_śW^}_… FXq]/YdʕfΝ=V͡MFZWK[lt1}][n޽}lm5oōp͝?^Y9Uѭ_Ǟյ^|SRG^壞g_|C__~?ͯ?$и @d0JA 'B 7p ʰCG$ѫ DWdJEgFwQҒG!$ʱH%Hd2J)Wt2((2 J-s@.2L3όoLDM7S'6ߤiN;s7u냠qZv֐}9mݿܩ۽w#}!ӇG^:>yZ>柧 z{!>|ag6ۇ߻+?~7K?_ȓpI@E gFЂЛ{*xAZ/`E8Є BxBZ-a[^Ce5ġRЇ!zC"0b#(K"'Fъ),nы9h)¨cD#F˜F68:cȐ5юz#xG>+OcXGAr"4d"HE6 t#!IEN%IM򑓝HPZl)QFUrta-ΒW-K].,/Ca34f .-t3OMi5yAmn3fNfE 99sf @ -'A -|'> ςJmԙtFC/^ ޘ>AP ܘAσ#iCQ45LRy^Ԥ((9q<%Lpt=Jej@BΦ ;rQz"hSn59kA\ԥ>MTZUq309I@֌V\']7*%m)SRM%]eiWʮz]Qϯ5HZԤdhӞ^ղ:_ WrI6T!yTUV1|Ui_3@tֳZ =w- q˿q}u_͗ڳ}_:E,<w6p`-sCa s܅1lUIpׄ O3(J,Bz%0FW_%ŀqUHCV3g3gzJ+A±9 A!5?>MY+Ut|"Zԯ6 8~h ?4B܋U؅^MF~6`]kY*zT9f91sPf3\՞N!,l11111122222222229B8H8W7b6k2y0.'wh|Yv En7i+s w{qc O G > 2% '39<93'  )0!5%87?E<R=\>c?i?l?m?l?h>a<X;!K9'=7.,5354545454443333334455555555555577<<HHffllppssuuvvwwwwwwxwyw{w}wzywttuz z { | |}}}}}~~߂х&/7>FHIIIIIIIIIIIIHFCA?<:73/---.39=AڽFڻIڼLڿOQVZ^adhpuzľθֵݱ H*\ȰÇ#JHŋ3jȱǏ C$IRZW0cʜI͛8sɓX%ѣH*]ʴӧ $thQXjʵׯ@(سhӪ]˶GMuKݻx-I( L@p2̸ǐ"8˘3k~8@͠CgҨS^ bְc˞ ӵB g^!ȓ+<\adȢ,Nzi}_'t QѼ_Ͼ\à޽c'XV'R_AW 6HviP9hf!ev(iH(&gb,ۊ.(#h0h㍎ՈPh' 3|O.P=)@S7}'5@g}9^d:"֖N˲+N{}ߎ;ܺ>vK |DO|sʷ|)?}Orw}o}q7L~ ~p Oo%2X|"(AXQ 5 :CȧO&!(;"%RN)R{V"q"'1f|(5~n|#(ѱ#=~< A<$ 2|$$3(Ir &3)Mr$ C).<%*cUҰbB`8X%0 $a2_2I|f)#E&6tmެ89qS9fO M5C=5o2|*T)թV]J$>`)D! VeYˆHkH"fVu skpWU}rR^ 0⯄QL2Vd_},i+&R6 n*0̒H3XC@aCր>J*_xCkY+vnPmq)5 dke6H=.oA-TR[&mCm롟 lw\]5Hz }{4^̗ji .+:6I.0{4{uaηz`0Eb g >2Z:,Uq[> eu{L~7=-o 7}6؁>@ pn%~pǸ5oEnFU>n؆9e^luiG>gbF:d9z>bkz_{v\EiՎYW풅cX';`Wo|Z_Vƒ\E|VoUOP|Sp|HAs@h~ACIFȬgA!X{ܾL'M!vħzz/FHԯe:}틦3Ⱦ1JEb4rPᏙ̟u?G}(E&h! a 耂a !yJGDŁA>;%8E5e2/,ł)&#% EeŃ %EeĄ$Ddꄅ礅ą$Dd҄ϤĆ$Ddć䇮$DdĈ䈖$Ddĉ~{$xDudrolĊifc$`D]dZWTċQNK$HDEdB?<Č963$0D-d*'$č!$Dd Ď $DcÏ#Cc⃐ߣÐ#CcʃǣÑ㑾#CcSy7.2 oWyÓC8@3D>8I;Fy|ӔN WAXIR6]CWwbi3Z_)6iCaY|nk5s DmqUYC×Ctx~I3iD*NY0ØIt2D7Q(OtYI2)E31 UT)3ٚYGCX95I1EaAc^ 1Fʹ CdI6qܙ&ĉnN1iLNB>CL1ޙBZZH5iàgt *J0FVI2 0!Fڡ\8pTʢsJvdyģ B|$j碤ʤ)bD¥"IĂdꩦ$覑Ħ)bD߉§ (iɨ){bD‰w©s"Io-š&zj&zRڪYjy?!0(Ы 0 p @^u G7`.p'$V0  ٪ ^~@}jSaǭF%ѮbJP m*:(~ J+4`*Zz{l | ~P%+ ӀԺt۱zlگ* Ȑ5k(/;j{:`Q0 J* *[pQU%[*5~pU 1R_[Esba"0G][9Ÿ WBVb?%iɷ}!rpA ?A-;[o!B1G@ۻ;KTp~@@ !: мʼ] K9[;+RP  p K~0Nj503{[ @ 60; { {̷{ۼ[6Nj`ؑ {ʻ a( 2, 3l@s;` \\NK髽Q .9L a\9  0k ϛ pܼPSR !,~|22J55xxdtғCtHHt,,tߛH' xx CmmHmmmִN\~twmCT++rrtCCt֩JxymғC\LmCxy,\mmCC$bLm3344S Ht^𥦦S]sCCvvt$wH t``tii^^n ggmCMM,m Htt\//UQQmOO55VV,<< H ::''ӳMSaCttt@@Ҵc%RVPtbTLn tc''st>p ؆$L ҡ5p!ͰM$$2,ׅ#tHQ,V;dHy\m y P /0 LqqCmmEEQXJ/ ғߛ%%ִM\ooI.` CCtkqqe!vwQ`W\\ߛH*\ȰÇ#JHŋ3jȱǏ Ct(k ˗0I͛8sɳϟ!LI` 1a]ʴӧPJJբPF &Yׯ`ÊKREY۷pʝ{:_˷߿eÈ+^̸6LTG̹Ϡ3jNh8ӨS_װcn:ٸs޽1q0P+_.۷V5q3tǙk}5d!Z>p|ӫ뜠&0|G^ $=%XB& h`|җ߂ 6~'UWfGԟC%hh u(!A 8'(h*~P|3Zx@fcDi$BC?&P ]k:Fi9\.e`ۗbigd暍pft֜v橧`Sڶ矀Y&hH.5 餔:of)Dn)~*ꢡj*f4D!P 'zQgTQ@?QTRzS,> @ HP"k킺Z4)@^+}JWEҞQ-"۽[QU@+-Gqz FpD?ZAJq7wsw LU)Y0r&lz*߬3l9i=,gAmeE4cI/aM?-u_QOm\U_5m3{hv"d)veMjXn r#!(*@d!I݈cTu $pV.($9Ep$PN;F)"I:wߕ'ҷ긧:Hq@9P՞A;.mHkE=<0;KU' F>NW=|P@z޳_< M'< l#HAM3 rps`B(Br;! ݦ., cpk6réO!&!F%2qgN|͢(ŘQ,"Q-^Ø1af<ҨF|z#%9^vD=qU~)Q:$"7Ef#9HRQ$&ɺe$(QQM*SɪRl|eb)8Ѳo%.פ],0aK<斒+1Qz&4$i.<6Ymr3Hf\)N(S<':uf"P6h-<[8nkgp@^;,| X;^SyXs l/yʰ9WݡGFTѓ3]!N:x.uQp:֫wsm^ߍ>v}gzګvogzܓ>w}wz{w]Wy=>w۽o7~ڏ?vy=yYW>՗t+yEwϟs<2˧rꕼ ǯoqG<{ מo߻{-0_h9tOfwg~lt?7~1ٗ 񗀔1Ѐh68o}x7|%Eeͅȥł傺!q86xL5ΰ< @5KFhR*!K PMUH4]KZ*^cRXgH]b(6H#6@"xqX8hA8b!ň刟%Eeʼn則%E~e{xuŊrol%iEfec`]ŋZWT%QENeKHEŌB?<%9E6e30-ō*'$%!EeŎ % Eeď$Dd널褐Đ$DdӄФđ$DdĒ䒯$Ddē䓗$DdĔ|$yDvdspmĕjgd$aD^d[XUĖROL$IDFdC@=ė:74$1D.d+(%Ę"$Ddę $$X)@@yԚ?@Qtt{CT ^  >c3uι ؙ;;A: B鹝YII9B8iBɜIB*7B zJ B6*C KzZCj5#C!:%5)C' +j5/C-ʇ1*55D3742 5{VCJY'o ]3 oa НR琣tDpȥJGk(FcJDgBæMc>#dWt3yNvz^6#ԧ~J 3Nz#+Ԩ(z2ZOZ!ԩ1OZ+uU* 0PZrK#իjz/zPz*.תP:Y< WN!L7E uʁz,:QSZz+kQگ* QذB k˱Arw0" -D pRn+ 2z!W+ p+))P1 `1p1.K!pK۴ ^!1ҢZ;pW *[9; p1A% Ns+ʴENzq]д@2A۹i[] D۶E al7E-AKl+먺K  G+ T+1 s;(ǭ!в;4+=`Ғ{[2[kw ;_9="*b%E( <) )\XS;I\!(1܊p౺|b ,̳!Cq4t#D @`D0ŻGR>KKYY eeppttvvwwwwwxwxwxyv{t}qlgc`_[[Z[]`c e g jmlnpsvy#|(ɀ/8:>ADGHIIIIIJJJJJJJJEB?>>>@BFJOQRUƸWǼUȿUTVXZ\\[\]^Z\VSMZhzƩlVE|3x-w*u't%s$s%s&s(s*t.t3t8rGqVpdorooptwzzH*\ȰÇ#JHŋ3jȱǏ CtأdZɒ,*#cʜI͛8sɳgȓ&S ϣH*]ʴӧP--)teѨXjʵׯ7 zٳhӪ]˖IdmKݻxF-Y) LpC`2̸ǐ"8˘3k8Y`͠C sϤS^ڬiԭc˞M;9o^Nu+CpƣK^G_w !8E[;s ū_~+uW[ȵϿ@p߁&uayاV|٧h$aDu%'(4 c8H:c{<(IHfdL6 ڒNF)cPNizU\e`9(hvelӚn)Hpi睜陙xgGu)J衂w*n: gJJ\Z 2Mz#j1T# "Z *hCTs p뫱߬ Z/+z6 l.kw: "m׆k\ nq&TEy# S0/m+xlt0q /l ?,jOlqh_1foc,ra!l2`%x¶/4r8{us )y} ?0☓xH@9S^ %\+0l颃j~Pݺ(oc\ w'.ᏛKV#z|o/~MSzg~vWMQߏt+g<`10{ W& 3 rpcB(‰;! . cҐ^6rCq!%!FH%2SN|"(EHQ"-^LTH<0OfN$TZɩRV&UOr*XI)ֱfU%Zʵn},*W[ҵ+^yӽbzk vJ5aؠ.VN!RX lLYͶ,@+k-mZ!cb-l*ٞU+ns,2 fhC*2 (QK]Qb h ՓP u`]a T 𶗼ץ.޳zw moyNjַ'𻆂wf]4 ȁ$R(H0aA+P ԅIE|2xWfxc<7A6l]@Plb <1 C8Olc*Wy*S62A'o^THLm豊g}3a:y*hqVu;cB93PTeGFP{JӠFiM7=vt0 &ԉVtKhcPVp5c (F2n]\ZқfBפQ+&8VTP+i0`dPJ-moK f7mr/%aGya7]O?yI>WWx1w]_x>v]gwwɽvn=o?vw=wX׽wt#wDsm//?wl}K?5=̮/\?u~죾=1!̨NA w$X~w (h 8H TF2!(%h$s~.^3]5\7(\9[;[=[?h[A8[C[EZGZIXZK(ZMYOYQXYSXUXWxXY(X[W]W_WaXWc(WeVgViVkhVm8VoVqUsUuxUwHUyU{T}TTXT(TSSShS8SSRRxRHRRQQQXQ(QPPPhP8PPOOxOHOONNNXN(NMMɘMhM8MMLӨLxLHLLKݸK߈KXK(KJJJhJ8JJIIxIHIIHHHYH)HGG G iG 9G GFFyFIFFEEE!YE#)E%D'D)D+iD-9D/ D1C3C5yC7IC9C;B=B?BAYBC)BEAGAIAKiAM9AO AQ@S@Uy@WI@Y@[?]?_?aY?c)?e>g>i>ki>m9>o)>q=s=u=w =0e|~i;=JQq٘GnĘ)>Y%rיuq#Ùry8AwdIs7Y=y ?79? HYi?)I5ϙ?љHө?y4? ߉4)@ٙI4Y@穙 4@Y3@ 3@٘I3A2JAk S J  2Kڡ&c4$*(*2/ZL*}٢|44*6:1AL<ڣ|SFJCj1KLH.ؤCPX ~\ V0aJM[fc0kPhF#*ئCprjv*0}:Qx鷧"b:/QAb4e6B"jꩤj-*Rz2Ѫ"%J'j:T:RzV +ǺRZҫ.̺z)SZy4jqʀ*#'1P+=@  Ʋ v Zc 4`0 B 0f`$0' 4  {xg/`!d;1;- `  $09:P+(|y [+ $Z ²=p=гL{ $=@WK 3 ",p3PGـ䪜c;Q k[m{KV{9K&Ѹa+)+Z+uYk[j뱃+K8p*[*ZKj,RkHՠ{{[J:U*{(SZzۥD1Q@;[Ɗ(¾~h2'qa od۬@QD'- \wC_ <\|e k " P!0 o%a.L=@þ  6` )5/\", Dľ@<\P- ,R,bL ^]\ޛ u.gglcćNvL2\E|upJlS< j*|"\mL%` ȉ- LƓĥzʨe0Ť, L}hoі@ɖCFHIIIIIIJJIIIIHFCB=;9860)'%-39?DKPUWX\`cflsy~ʰӭ٦H*\ȰÇ#JHŋ3jȱǏ C,dQZ0cʜI͛8sɒp\ LϣH*]ʴӧPeѨXjʵׯ!V ٳhӪ]Ѥ@SKݻxfT޿ L^k4^̸IH ˘3CLYϠCXӨSg%װeNX6bc;l%XMqͿ"4'?Yѳkvz]/LDx˟^`pVϿ T{hh{!)F_UI a$ڈ&bf(⋋4%c8x֍:j"DF&MH.a9ِPVi%}Rvv\d`IRTi }PI >I5ډ.;#K1|&:CVz#@Rjac1*|z@<֊JOŐj*!*gF+"EiJ-ons~+kឫjh+/rk/tޫoc`+p^l0]pZ /pw>,e OlqT_qzoh,!l2[l%WHz @3//S̮B1Ҹ4^-,;"14J4LwQ4u͑nRMxON/؅3xG-Н<[mTm'd(8|A?V!qIF]}P?z^= 0:&DЉR,EF3rt>cB*RƐ9)JѕG.NKc͙t`S)PӡFePJ.!19}j*UEuZ*V_Cխre}Wq4Au4*@! H1$#@t]I}ZX:4*bFFed#k* qp,P 2 ܀ҚCYR'X@J Ңִrk!6i됅".;\+@?l0״qhsA7DiKr$U8xS1Afo[W}I|o8׺oi_$@Ƌ?Az<^?N0`[5=wRشv{/ mԥ- +3@Ih^"8N2;&<.|LNXe% n9ȰmeaC5p36E='my|e1b(ԟQDy*H9TNw6IQ05 \J5`W an2PjZBCI`͎d6Ȯ)CGB̵}mc&'íɒ[+=7Cҭny7dy;E }oFNnކ%~mGƸ5NkEhoFyUeKI9e^c u`z|n^oEq[項:eY;:b^X}{^NWhEXUoX{U.U?L{RnT@|OS4C@,Hq!B<<)D &M!Ѓ6kQҫ^3a{-;OQ3z2}=P߇"o|n^o>rED_AX F2:DbǗRq??doW3'%h%m {T(sy(SRRRXR!(R#Q%Q'Q)hQ+8Q-Q/P1P3xP5HP7P9O;O=O?XOA(OCNENGNIhNK8NMNOMQMSxMUHMWMYL[L]L_XLa(LcKeKgKihKk8KmKoJqJsxJuHJwJyI{I}IXI(IHHHhH8HHGGxGHGGFFFXF(FEEEhE8EEDDxDHDDCCCXC(CBBǘBhB8BBAѨAxAHAA@۸@݈@X@(@???h?8??>>x>H>>===X=)=<<< i< 9< <;;y;I;;9:):);x"Y;$Y떒*n,ْ0Io80#6o89y6)ycC3kÔ0^#-ILc*>Õ% /C#"i+̓Ȗ'(#cNT<x1}Ez@1t1IEYOWԘ91EYu]XYG! `ty09F:1fT/Fٛ6bl4Iy/Fʹ, ~Q79ة)]3ܙ %yZ9/)Gɞ1uT.Gٟ_炠{4z :.G ڠbd4:-!JHz7ҢT&,,1H.S6&(z3 ,=H8bBzH*M:IJ{RzD O *YjIQZv췥"ԥ^JdU|⦟ĦR xB$KjtBʧ9Jld6h⨮Ĩ/ fB$&jaʩ]*[bD ;%Ǫ'0= p R i0('`Ztp_ړ% Ȑo* - p &Jo?pjoG?&1G쐫:{S®?a&ZÚ گ JJ iZ0, 4P !oۮړA5:J +ʮ: ˰r V2{%ʮ aVZǴ-[ۓ,v˫ *NɸJD^Z+}k$;U|K$Lk|U{##WYbnp+?A Da[b!ۻXbU1+S*1.;[{Kkఽ~0 b[ A ˲ۮ +, ˽ཻоk~Ȱ԰p \ ++l ~ À1 \  |7 %,<|›l [{+| 7|!,?!۾ L a,P0I`&#=,O %,J,$; cM,+ Gо0MlJ {3Cp $$p!,5 ꚮQ2tHtt\𥂠,ׅ#QsdmCH\ӳNym Ly qq/0 P CmQXEE `%%ִM oo\ӳMteqq\\vw!WߛtQ`CmH*\ȰÇ#JHŋ3jȱǏ C\!XAN#cʜI͛8sɳǓ&i@ H*]ʴӧPNZR(KRjʵׯ`i(eRѣaӪ]˶۷1M|6 -ܻxiɂ LÈ%(`@ǐ#K uƔ3k̹E1{MiȠ>ͺ_SM6e;ͻuNoƓ+_>9Уv.icνR7ӫ_<t/=?_Hۀ&`s1ނFVh`^ne va$Ԉ&N(#4f$c8Ѝ:cA<(AiEI.dM>)QNieAP@V$eWiߍZj)Pa9D ji{Yn h'pP睄g}ix fefQx)zZ& gnwh GģߤUѠʩss]e&)AXaIAq@z³We2mmGjζ׍ GK.goGo6pup pp5qsuqGq 3q$4r(tr,o0ţH,1\yC]*D>' @Z&JWэKRsz"%1\[-6FhF- h6Ee P o͐ B ݵބ'd8m#Ӄ8A7&AKC$5?ʚyzۢ>v[zJκϮs첷L{)ߎ{ɺrw |O|q7| ?}Op}n=oK~垏~mg O/k %ީ4x2pJ|"(%QG  CF&I}2$Pt<(BݩЅƳ'D#zωRTh?3QrH+*ґb&(JSѕ4z)( )NvӝG> P갞PF=xTm*PR-U 'dDvCA"կhYA MX]*0^+^5F׽~Uz=a0+0*X)8v?M ,;fظg?=eP*)(-e "&¶? t[^nz {v ƽ"T Ht-KAPwTvw Tw2Ee^Rm|K5Է;5Hvw N] XcN0_ݒ9 ^J8^Tqk %}?lȊwĻ-`bҁuaLYϸ.J澖>tbYIV2rd7Q8~K*ĵX>܊c hI @@ iNBDF返$:PƙWx~w\w=x'_wѽr\/v̹=l7wv΋\?u1=tGGsѼ.7Ogrԇj⛺x6'j:yV~ikyvgiS:z~pկ>,pR Ͼ+8CoO|` PC7~b>+0GO;AA.i _0.DAHo&53Z(0P R / X %0@pȁH!(X"x.@( ,؂! `~:1׃"qz %Eeń %Eeą$Dd焆䤆Ć$Ddτ̤ć$DdĈ䈫$Ddĉ䉓$DdĊ~{x$uDrdoliċfc`$]DZdWTQČNKH$EDBd?<9č630$-D*d'$!Ď$Dd ď$CcÐ#Cc߃ܣÑ#CcǃģÒ㒻#CcÓ㓣#C@4H?LmNR9nuFtFvGyGHIIIIIIJJJJJJIIGEDBA@ŭBЬFحL۲OںRݿUY\_bein;wztqpqsqsu{ݦبթѭαʹ H*\ȰÇ#JHŋ3jȱǏ CxɓG K\I͛8sɳϟ3Q%Za*]ʴӧPJQhJE["ʵׯ`Ê[ɪ]˶۷psLVҸx˷ג ӬKÈC0(Ő#KL+c+k̹gfLӛCװ۪.:۸sM6B?1M ymЏБKNr |@t% Wn?/0C?Ͽ߫=PG&n&A? Vh 0!`($>B;ߕ.4(68DR'dH&ۑJ6iL>)唔EIXfe\v ז^)fX`iPlfpTm(xyFo)J衄}*q: hJJaZj?>W@<꣦q?n*+:Z:xjϬX@#z6, )s=>mѮꊻ"m3 .#^H" ^' /12ܛW!g,wLl"&L*Q̺Lٌ͉΄@ݙF'J7Mԇ1MQYLi |Y+PLZ-7N36M6=4I/qWKT/xH3**zW L9?9hPӧP8jmw9Pp^_90n~+BLD׮{zł(D ;" %꫉N|X)Rq[VⳲ`q"M%1bf5Qn|#(D#=~$ yAR}3'1*c<(BЅB&D#j͉R4(73or(H)ґ&]'JSΕ4.})=<6s$yJ;|*T)9*RFԥ*INTR8VǚU eK*XwձƦfXZ#5n}+*Waѵ%+^=׽r~ `[B=ldX0y,d #̰Oy ѩV jgTЎL`BL{1vm^GBbmp&:^,p"ᲥU r;2*VK8azD+`)'AS$YCy{ {K̗҆-od/};>{`x`/ļ 6<_p eS ' :0f\a@p1ߋD&/̭Ar﷼D R :p@h7ɀX2͵CY Z! ?1cF9~4y[1 = v?nBe_1xU1+rǒ=9)_6.ύscӼ*-y`sؼ9ЁEF_Lѓ~ܥ3]Nzs.|:s^ î>]*c?{vȤoW{>w=wz޷wz>x>7z⇾x7yo>yW>wyWywy?>xzw~ܯv={`מַWuA{Kѿt<5ǯr|!7qI< W/pv߻n;߸n~޶m[;l3YXXxXHX X W WWXW(WV`vmv#h`&x,.1B57S9;[=?[ACX'EhI<؄+@(q*Vx4"#qli%fEce`]ZņWTQUPS^r  vx,Ň_ 1(XPXXyHHXXQ&vP# U:HȄrTTTXT(TSSShS(SRRØRhR8RRQͨQxQHQQP׸PوPXP(POOOhO8OONNxNHNNMMMXM(MLLLiL9L L K KyKIKKJJJYJ)JI!I#I%iI'9I) I+H-H/yH1IH3H5G7G9G;YG=)G?FAFCFEiFG9FI FKEMEOyEQIESEUDWDYD[YD])D_CaCcCeiCg9Ci CkBmBoyBqIBsBuAwAyA{YA})A@@@i@9@ @??y?I?? ?>>>>Y?]D=?yJgz5CzI@QStHj3ɤMcRIåOE#HJ?dA;㦩Ħ8 7C$4j30ʧ-,*)cD'%èR6eA!4:1Oکʩ!:UjZ1:PӉ:U0ÚP܉Zì uZΚ/P9y::J.ZQ: SzQz)qw*0+-G! 1**q a% &!{@ ͠,ǐG0 0砱9Q0SÐ;ְ0{*;[ ; Uà++:˪oGȖ)kflHXZR ]9' &"7;K ՆPm ;1pak{w;)p+!fGGp v &[{%4dk$뺭{! 0$)*hW!Q˰7n+%˺рZ %<++R&X¿$u{)|S?X*"ѹ  `,Q *Z &Y|Yn+j.\6|8:ͰM,tt HHn}2ΦJH,| --mCHߛHHLwt\U:fHHCL/0 qqsP CEEX ӳM%%tHoo\\ `ҨJpqqTe!vw\\Q`WtH*\ȰÇ#JHŋ3jȱǏ C0ɓ(@ ˗"I͛8sɳϟ@D) p ʴӧPJJjΡ*'}Ԫׯ`ÊK,ؔJԬ۷pʝKIڵ˷߿6Q$+^̸1M pL˘C(9ϠCѨS^ͺf[˞Mcͻo)ꎘ OO U!УK_|pdүB)*LOK>A˟O3#=|(Q~e!q=ރD_Gf8!⟅h≤vE8Xas((#q萇 2܃ "4iؐ 刜@/")T$CLV\&tBYv)T~Pdff&p9`)xGAvۊjo{硌6Y-褔&)AVt]:P*ꆂF訨 *j5Z+ʑ*$KȂdl6kѲF+-CNkUjK#EE rގI5@ Qȑ 鮫/TQ$ƿ&FҿPn",1 #[pwaP o̱(G0,ʥ H}p1y+wLtyA/M?-QOm55[w\WYu`udc8vhӬblxvpOvt6wxvw|w߀w6x[vx3x x5yuy望y砇u8 #1@. <-/(0d2  nP:@,{ob >=C/˸@rG@wK FWds]" Z"{_tx C=w>dq@i gu4alx#7!|&nĈNb%&J"-^"è1f< Ө |#'9vx=v~c);$"+EFl$#IRpd2ɾqy$(&Qƭl*SUl|eb)ˮѲW%.]>\0asfePjPF=T<1rz*T$թV%V*rK^*BQ"f%)ZJkk{+*"ѵn[+^v׽RL~%`k6=,/_2|,d)ɞ5Z_3Ȕ,h;ʧehS{0ԲVn}6c+nҶ-nǩ݆039* %q+Yecmmr]}JՕnF]&nF𶴷kӻ75}h+зC/~Ue}x>M2<}0* 3yhx÷> Xu%~U<@aZ;6*sL>V,R] RE,">,z6 J& Cڠx0\YBv/9_>:4+9!p573V=Yn^%'A Uhh7_̌MBL͕v%2M?Z 4' Gj@ jJz6r,7|6!rݥ]sW58F@PyfW es2m/ٿ8igLތḱX К8g\;H緹 iU;'8FqoҒ1Kw\&1Nr{,(5B,rk#.h |A瑯-;Z!M~Z;+@#6Pum!!`c=C^)0B@m;$vA]%Ҟs/0^ػy>s;dp@_:~o8/С=Eod!@=T/qHU{ھy=?'/V3?$G/PO\>gs/PgMÏA?|ӯ~>?/N1~%XAh Vr 0h ȁ'Ggǂ'Ggއۧǃ'GgƇçDŽ焺'GgDž|pe'UGHg;0'dž'Ff䆇٦Ƈ懹&FftƈgWH&EFBf?<9Ɖ63.&)F%f Ɗ & Ffŋ%Ee셌饌Ō%Ee̅ǥō卻%Ee H~ Ȏ|1HE X1"09! y ɐQ1 IY0$ &yg*i,ْU%Eeœ哖%EeŔ~{%xEuerolŕifb%_5+P^09 㐖1+fn7s)~u)w zQ)  dUUiU9U UTTyTITTSSSYS)SRRRiR9RQQYQ QPiPPOyO)ON͉NYN)NMMיMiM9M MLLyLILLKKKYK)KJJJiJ9J JIIzIJII H H HZH*HGGGjG:G GF!F#zF%JF'F)E+E-E/zE1*E3E5D7D9E>G_ԣ>CY|!CbDH{Gs?DeRjVC[FX`]:CeF_:"q%Ħnj>bddqtj}z7~.9}zϒJx@JGڨY4ZDz+~~1+ j9!ZzGh pp`:#Ye! Ы JP*ʺڬΊa *z>٪GZ=G݊j< HJ:;:H :Nzk:T*NC˧ ZK9O wZ#ձ[&{* $81{P,۲: U6[8[QuHˀA L7SQNxX;EZUV]_ RacVQg{Ji{k;WmKoJqۨs6wJuyW{{} KKK6+Xe 6[X5Xkk5X۲`AhPp;PCIP4Pb [O[KvK'PwP /+ 0 `0{+I[ (0,pP+@[૿! 0@VyjfgNj|󋻱[*@H؛ܽ˺qni# +  H`<wP(x¬7 7<' OܽK׋AQD`k# ˼1;` vл>;s3 ŀC‚ H`f&˼;S/0wȲ;b ?:ڹ(L'+NʑeJʔ >C˗尞|,3L짿2rCǬ7j 0ZGlw H }gH@<\| J L@` \ Q `@ @l*P%`% =9L mq@%.` 7--GMMJMԩ+}H[ (]A T G?p$oTM,}`;mU Cxm q{}slm؛ҒM H֞=mz}&m t]+}{Љ-سMA-d]/m*J`pG Ž!,5+wrz &-.+(w&_(T)D.9.5/40322222222221212121211111111111111    # +;G<* "-5>EKU`jr~vzwxwxvwvvtumnccWWKKCC == 8866555555554444443311,,##    $"9!Kdv  %2<CFHJNNOOPSW]i q v |!!۠&צ)Ѭ%̲Ź  %6=@BEIIIJJJJJJJJNW_hr}ǢəΑӐגۖ-H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ 0cQy ͛7 ³ϟ@ JѣH*]ʴӧPJJ՞-jʵׯ`Ê5)3&K8 ʶ۷pʝKnܱx˷߿\lڵv+^̸ǐL˘35ȠCMtcͨS^ͺ^]mNh۸svͻ+|55+_μ9TУKN=,a!wνﻫO׹fJ( 2Ascȭqހh`pmB1Q 02ړD=R(*hOTӧ<)Rh%*ZhVbi+VZ(-該qi%kJ?zj*IJTZmӥSAYԒn+/ɒ;YPOCs C@?`(ɡ'Ó j>Ż0;Ll/,j=Q|2*~1O sP(ڲ";*m{HL2ؖ|4S5+J+|Ȳ!?衫f}( GIlM+kW"P!0n"k#8 ? .8Ӏ_昇 -.2bv++;uPu ^<-cf˻ЯJrD k" `r Ao] -Ά2OЦE@ "^ć I9HRь\b`B\44U% KU U'\iTh\%-QE1(3c3N9U"Z&Aa?pUB[8 er<5OL*YBDq HQʑ!e,WL`T/3UYw .abLsld7;BRҤeVmH+pHMHhr-6yw" %*Q{W@ӦUH+OJIJJAX9[ 0G9ve *WZU(Bf9uf7gΞJiA`VJMYqdi%&4NU%B6[E4,j7wD׫zJy:JZwڤjzڬP:J{zVܚ*|\:Wz}꺮bڮZ ZhzTYʍ8{˘ [ ۰;X (qk[9Qm& (ɷ|ٲ#}0k2Wz)~:K<&_P VYk=;kRPǐ U[UlX B+h`Y+W[U{i $+\fr[:fh sRPjJk@r{{]Kj˸ jV𸙻{q[tw;8Yk˓W XP!ṟW໿ "!k"+Rл`;๴{؋q~{н~໦˽+F)!A勵e+R+#ѷܽT0 ,fppzP|,kl`{ l$1Yk"qDnF}JMn:(PzO=!(VmXҶ\ m^:Yb}a]vhC nkpGtv}Tzmsמ׀i=L׆-׌Pؒ-]ov٘fGٞ=ʒ٤c}ڪoڰ-}=cU۶MuǼۼ̠۸]ܴ}{ܨmwݯ}ߜ-=\ǝޱg=/]]fm=~~= {rr>,Rn Nq"N$^q( ⣧.0146~: @nB>9F>E?L.-tRH^*XZN}^QJGd.`~jl]pr>cv啚]|nlfcn~^r}>k苞j\n>q痎qț ~m^>qx ~'.q: >DY'N&G. N^ZFؾھ)N=~mNV>&~zÁ_ҽ٫i}=; 6O!#_%/')+-o/?13579O;=?AC_E/GIKMOOQSU?WY[]?_ace?gikm_o/qsuwoy?{}O剿勏_/䕟o?㟯O⩿⫏_/zlpl*/{Ǐ n/y7ԯ&o?x 0/iO_ DPBa1QD-^ĘQF=~RH%MDRJ-]SF3:SN=}TPEETb͝8>UTU^ŚUVLu:VXe͞EVY9W\uśͷyX`…bƍ?0b%_ƜYfΝ_RihҥMFm4Lѩ][l_[n޽}/oōG8xɝ?],OǞ]v*]xWzFR{ߗ|.N/@D0A4@0B Yb$'0C 7\j0DG$ IDWdqGJEgѹEFw1CʱG!$A H%d#?JI)Ҭ'=J-2+;ʲK1$/9 L5d37JM9Ӣ75N=Ό3PA#@E4Q* PETHF-r4RK/eqҊ*ŴSO5Ԕ"N?%TChTSWe>T%RUYg%Ոb5W]"\w6XzeWaEV6b26Yg%mYZk+[MZo%.pڶ\u=ܛe7^y3s q7ߩ-^}(~ 7`i` Fa[R'x8c-79d.d{"dWc>f9fAJyfofwC$9huu蠉6:雑Viv:꒡j:뇱ֺk:|lv6;qVmkv;dᖻn`;YֻoS;NpH 7^{  k ¿i ~,Nri~$ `7qv <` W@&p}1C/#4Ȕ"/[A= ag% Piar(`:a%!>""=Apb 6Ѕp\G+B{P|Ãg i#&YDq # -?zqa`d(E1҈f,)6&{2IP  bX#9e0]AC@_}gno}sbO ӛ7IӜ 9tӝi;ٙxӞFrYb@yO~S[(rPfE_Pe Y}FԢyE5:nԣZGEz#EBKʚԥ]mRNf`jS1&8ũNy:Թq&@PTQZHER:հ8է*Tvի_kX:VլgEkZպVխok\ [1=xX _tXl^:W$~EZW5@?QXmTeaƖ&% ڡnxhb P-AlkZ޲M=lZ 6CWJ֯mtQWܶ ?>!< 0v@]^7E/I,[b1.m Z7p\ڷ%QV~ A]q_mo,;!,5I111111111111112222222277<<:B8J8M7N3R+Z$`g~mvw dT#'0>IF@ < 4 (  >   $ -+0/213344444444444444445555546492=/J'X bhm opqs&t3uEv\wiwpxuxvx{wyzywx~z{)8DJMOPQPQPNKJIIIIH?u0q(q%r!rqpnl j h f e f i l r w }  ,8@DFGIINWagmu}ߛܞأԧɷ߻ꁶsopzwbZROKKH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲC#0c4bS8q!ϟ@ JѣH*]ʴӧPJJի>]jʵׯ`ÊKLmvMApʝKݻx-˷߿ L8YlkPǐ#KL2˜3k̹g39eزӨS^װc˞MaL=ȺMȓ1N£KNzTسkΝ6sq@ANû_Ͼ{;)UC4Bނ 6 |G+ O7cχ7($u ("d$ 4hIp_Ca>6|hO%&JXN%#TVi啁A G=,s$hfCAyԔX)teF\5C>` ٓPT"d/dOC14HJ)PfӢ>B0ꍨ)Dړj 2K??ꩭ2Jk"|:N"2N1Һ*(묰nji@ڪR-VlO*i»=)FY/Cwb'O{6 sC>s=60 L)ŏb`,*5FK-<lqŷ1gjA-)L$ܭJj:*Ț|-;t m9rPJM,4d+ۊ$[)j6kxET7=i$>s#O8`78ɗk6#ZlԤ˩:-y院}5۶r=٭-vT1$"Ԭ-*x=yT&GO97q5-俷E} >C>y 6S)8|@>@ |ƣĖ9L \1ܕZ[<oY1D';v@ؾug5Uܩxn[ Q00gs4F!ulHQ]]DZĬɉZ_H*|I ?=Y=Jl+ΈC[ k1(?< ZDS'31W,`rT5UCV!"9R8U@n":VS-W7{'邁K(s,%֒"ĂY ffH-JQ!>> A= [I+i x$6QI52Aĉbm5M*''N*)LD5-F -Ui '3hbwH(Vt̨F7ZbNĘ\Od4LEUHYFQB9δtj,mRZ[;]B5󧏓i3hS$o\jN4XdBy*1 U){o%.:WxUG%R/ԋ>9RO+t*8 ~ˇk ;$Xzu|4^eOHs &lC6nKKVkxֳ*Nܣ{?^ZkD4cl AJRUàE{CF˸y+sץWJ_U"Kg.W Ro%_*x]w,MIș & [5C@z m #r V$Y-prLJ|,ղC@Z$?Y8Z.xNАJ[nfȣ'N{:+BN!=VF^ȦWMZ+ոbYFM:!b;96Bj[;5ζ]#hqǝRONa{GnMz~`RM.; 'N[</{?N\|!?OJ)_gN'yQ =G·n_H@Q v0Gz.}F8WϦ:[ewz-v] FOgkt]o{p}(@ױ1[ʍ|vNsrg6qxk<絨g)ϽQ=O| O>Ǐ;OS{C X.?꪿0/H%8x R hl7׀87 с 8$H"X Av u*x,h p (eY< 0tp0MHwg T'X`0 ,xR(N PhWH Eh1R(SuxHkHaa8цGx{Y]X(0`JsXwH\8hȉ>XL@(xe(KXU؉x؇7腅XN̘،ȃFъxhP؍8ȍ8h 䘎֨Ў<ȏXY 8f  o ؐy{x@$)% (W*2|.3y/]1>{B9vA9F|;c=yLxEٔPrOTirSYXqW\Iq[ٕ`yp_docYhYoglYtIeKٖrYqk9vmuyzly~k}9j9Yiyygcy]9Y{6y}ogqIhiyɘ)kٚ k9Il#©h9Ɖ#y !ɹιk9mi7Y這iEٝmm koy ٞYY Qpٟj9z zo)q  qZ*"Z!:& %z*!*r0ʠ4%-r/Z:j3>*)*BjDZ"zHJڤNJP:TVzZ*\ڥ`b:Yf h칦ljnrʝtZyxJz٧~9*zڨʚ:Y j꘤Zyj٪ꗰzs@~juګ)w zPƚ)ʦ)7 `JZj:ں]ڭzQ:交zEڮ;9 az0Jzʯz2G:; ?ٰ39˒{%۱ [";Y&(,.2{4[x8:س>@8D{F{hʴN۟q9gёVX{!t@P_mڵ^arPPiɶXe [t+ z|۵ Q cpՙ}gи[K+Ikb۸+;tǹ[;KjY[˻;Ẻ ˼aKPzT;_˽ޛ1 {Z`+OԫۼQ |{p  ῍0"<…p'<l|6Î: 6cP:? @B42 DmqF}^9JMI P-L=)VMpXfY\[b^]Ih-ojn)n=g6;tv}\."$^|(N*.0<46~:n< }@}:WF)g ךrN~P.S~~U~J~Q]V.NfN\޴ia l抧rt^qxz~Ҁ-=B~5芎;>nݖ|}韱.B]^ѡ^H}꨾ԤհTҗ}닞N>엞>{i̎~grv~ls`'NgmW N^+'1_< o||>f!"j!_q(/*(J.oi-V4O6:<]@n3?FocELBxR_T_}XpK]_aoc?egikmOoqsuw_y/{}o?O_O/쭟o?뷯OÏ_/o?) 7/Ap}WQ?oSqP?j D`P >QD-^ĘQF=~RH%MDRJ-]SLdHSN=}TPEETi8Fp6\UTU^ŚUV]q:2We͞EVZm\uśW^㊅W`… F_c?Ydʕ-{deΝ=Z 7FZj֭] 8kڵmƝ[m鏧u\p(y{]\r͝>1sխ_>8:ٽ^G^z#k<^|׿~##@,DA.-b0B /0é&B ?1D_"GD1EWĉNd1FgE`1Gw,ƈp1H!DG$2I%\ȇd2J)tI2K-J2L1˄$3M5DLd3N9$/6f3O=̓3PA=O%4QEЅd4RI'Q4SML754;TTSOTHQeU9Uu5VYׄuV[oͲV\wuH]{6Xc?$Xem0Yfv?g6[mv[o-[p%6qE7U]wӴUߥص7_}ˌy8``"`_e8bJxb/b7&;9d>d+uX:Ofer9f_lfodwYggXh>hXiiVWjjVkkVVllUmߎm>UnnToNoSppWSqq'Rr/_r7Rs?sGgQtOtWPu_ugGPvovwOwow/2eV&>Wyn7yoz>ح{{_|} g?~/fy8.D#`d!P!8AH܋1AhL XDh:Jw0!Xv 8 q=d@6q+ SX°DC / <b롊F;P!Dx%&:юU" G)ъX0؈pzzD H\|5ɖҜT!iB(b@$!20+Y)cd.}G=4xƂp*9Бl ߁H5ĦP:Lq #Xz & Z0Yb5/ul֓'y'CM+Cgg4E6)zӢ1#?5O (Yi1Bf ɈE%BteK)zQZƃ5ixԧiOѝCEz&թYꓚTF%U*HUnd]kJǰ+_5kZVc][Z'ծ_뙦zW}_Uʄa^~Pb%ը%";YΆ0,f3Ζ֯HhE;ZӶ3tR&V;1ֶmnu[ַnp;\׸Enre /(#z vqjgb \$T'J,=- 2- % !!,,22444444444444444445555556679BBVKf RxVZc{iypvsvvvwvxvyt}mf^PE9+  5GWakosuzզ%1Ͼ<ԶGԹPҺU;[Ⱦ[WSPKC:201458_jʵׯ`ÊK̙5qu ַpʝKݻx˷߿ lLisuǐ#KL(˘3k̹geӨS^װc˞M;̂n->ȺMȓ=\ /£KNzTسkν{AIԌ9ViXƶcOllI6jJ9TtiX[g dFj'?U ɢtO >QjO2 ^€Ȧ?="JB Pj)(rGBkJ2jjh TtkPnۨPtD;)LMKvzlO۫PpEkID> 6 H )4A)=!𪗠ŊT, ; 1>q¨^%[=kw-[k1V:󰱮lƫ T"<*v;ɦ,Be|S?EdDC:+ƍ_gckh}{GbsM6@(t m}"['Ln8 w8My͘WL{֙#x2_r2MurxʎE)tyTOѲN}<ǾTPʩ7%>]@gz tMP tllJ̽)7 G\,ѐkFh|뻙.mS~NO}-$TR4]5 BT Xl7N\p/Ĕ񀂼))y8̡.II@OO%4Q-|UȢESeh{TM(plVbg0V&0ĢMQkU}&\[&*JT•LŲ0W!FPldJZ!c #6&5,: dNeRA Rq)kf=ЏJ$d^~l,N/hOFK*2ݦ\9]Mw.>lD$1v3 %' ~8hL!W Ja@Yj+^mP 08˰/rf,Њr%B04.)鱛j 5R0W,(t*Iӧ PZx}'A Mo*)ATTسn;#X]fi,ޭR0 JAq \QVsn%VU'xOԨC&K(~tܴXXd~tz& I:sHibS J\\c`ϪfvmHP1@\(۬.vmZEW 77+F7UU͞>"K ,, *VVSʂfӹͯ`.1H P|+($L8! ү7ᅐV C0_.L"ќҿ,Jw IOy5>r\z&Jc'[ʗ2.`32YbNE3MZ<6GO>, :5j3MhЈv F&ѐtv~,J[Ҙ3N{ӗ4GMR,vOV5gMZZֶεw-i\6}-b%6fPΎM/hS6mZ5r ;>ް^7#q[޷Mg8 qwCx .qc 7^_7N o|=B{A8FzExJxzINyMR(yQ8VxUxZxY^xw]bwa8fxvexjuinxumrtq8vhsuxzry~q}o8mxHmlhl8kxhkjHp78vxikH8xȇH8ƈxȈɸH8ֈxȉٸH8Hkx6鸎h/X'8{xxf 9y   I8)Ty"9!9&%y*I).-21965y:}>i#9BA9FEyJ =NɐMR Q9VIxZIZٕ^i`R9dfyJjilٖBpr9:Yvix2|~*iY"y[ %7,y0yY4)iɚ19y#/9I ƙɔћ#y ٝ9Թɝ; Wɹ#IYx9؟8:S0Yy9  JS Z9zgꛗСJ "Jt(J*z-/13:57ʢ9;Jx=+ AZ?yEjCI* JMPQꕃ@UW Yʗ]:[ aZxhj{ئnzps8tvzkzz|ڧc:[XzSKzZCx;ة #8Jz Zڪz~:g3::_qpy a :_JКp::aЊ`pp |JbZʮyjZqzֺ r|`ˮp`J kʮ  { ˱v0; j' ;0Z6 ):< ?A+( kꚴ8˴O|pIT{{Zk%۵ثjzl;kU۫ ʶmp۴I+v zkbзv*ثk`6;q0G+ylp;Jp@n;Knۻ1{3q˹ {˫O0;_˼k!\@㫷 ^ {:Wxw`(\rwL¨vh|b̆ u"̋1JD,@|JlpLUgP|OӊrT@ؐqS<=l7p٘vndٛ'n-cGڡmږںڗ<گ ڭ-ےDjە ںx ٿn ím}ݑ O=T t՝Ʊ܍v=]Zb}lޮ l}ߙjd΍=Y ஶ^T^F{ᤦi$i ~[*,-0=86&\<;&BND^"qHJNNgMTfS~HiZ.fY`e_>QfbMlnrcq^qxnz~t=>~o芾l瑾瓎^.杞n>姮~N䱾䳎^.㽞n>Ǯ~NѾӎ^.ݞn>~N^.n?  ? o/;2cl2 mr@Om8%o%`v8.V -Mm {-wMsmnkfb] X-UMRmOLIFC @-=M:m741.+ (-%M"m - M m ,Ll ,Ll׌Ԭ ,Ll ,Ll ,Ll ,}LzlwtqnB@ DPB >QD-^ĘQF=~RHL1YI-]SL5męSN=}dʕAETRM>UTTYUV]~VXec^%ZmݾW\RT[W^}XpлFXbƍ?ZXaȕ-_ƜYf˒)sZhҥM\j֭]:ulڵmƝlݽ}\8KÍG\y˝?]ӭ_Ǟ]{۽^+eni9g_ygZ&蝇6:iYFzi޸i[:Bֺkukf0lF?fmv;n{nn8x;pې]ncpUx\grˁ;t(#?OڜCG=uFt#Cugvo=www>x'xG>ygy矇>zޏaH7sp~{9GKgkZpTPzyħǁ Y@|C`f u!T@{\@ʱ> &Ѓ[ >XR9쇏p;Ao#BpMI~pC 0|1G p<@(H=n0|Q\bmGE,"DOGm{W@-q&BT$xCE$J̨Q0}* 9ػ!,x2211,,((--2211111111111111112211111111111142623;0C/N-X-^3c8g;uh8Wq8Co;9j>1eB*`HXONVD_ 6j%tv tl` N7% '/2460&   ##&&** //22444444444444444444444455555566::EEUU bbkkrrutvvwwwwwwwwxvzu}rokfhZWVVVVYWY WXXY%[*_0b5f:f?hBnEuFzGHHIIIIIIIIIFA?@BFLMNPTX[ɄbЄh׃l܃oqsuogZRKEA;88:99:76:ܣ@רDӭGϳE˸AǼBJUapĄđã´|rpuwx~ H*\ȰÇ#JHŋ3jȱǏ CII@R\J˗/I͛8sɳϟ@r\I@KҢʴӧPJJ՝DSͺװ˦:۸s.9@ No(@ PNLX1g@ξ9_:wʫϿgx@( 6 4@>ޅ sy(qiΑ0!Eus<،MH"br1 Hy>F)stdQ`~eedi&]cl^fp)gOoixTg|'D{)蠃J衈ih6Z梎F*Nj"V馜iZݧjmꪥ^j:جk& k,UA%lD"<$< 0D+MPX[@=;O>k>Į@S 00#ȹ"qK˰*qȄ ΧRlk .Ҡʼ,]@R3m5N_YouɽduhzvlvpcvtG:wx#zw|w߀w9xራyx⌇xOx8y嘻xy?yy褿7zcwzw49A988"k?ûh1=;dcM9_SC{܏w:MݷǯR?si<=Y%Y<>~?p$B 8ů Dx bw;z/w@<<@ 00{GYpNHÿ8VipT;MHDܰHDDWMN4D)Z{O,rX"Ǹ%:1#X5"C1vq#=# A 1$"IE2|$"#)IBR$&Mⱓ#(C Q<%SJ2`|%,(Y^".s]2e)9<&2ke 4iRּq&8'qL:Y:@43NyӜ290b?k&-h4P.&D#̉R03Q^r<r>PJnF=*ےT1d{*T&թjVVrlr$*VK<+Z9Y;56[ Bo,]?&ȭ}_}qr5`@.e#bY8N}eY2,dC FEb"JԞquaOZٖV"!p^-p)M&r2}4+jRؼ.vz 'xK=:ӫv*|rN~{wR+`:0F#N.T#8SO02aMB0*#&^*S8.~1Uc,ҸZ1>nL!LF>dc2))KV -sYsU2,L:3'Pv*nZ8Zp;`Ba|,a |H);AЃڝS<DьNtiMrΥDA&ÐhԍB_6i-y5pYl҇ƵAt 8ZbwttD]b>v,ٙu {Mf6A]jw\]mmn3-n;ke%v;tp x}G{VrO`;<@ᑎlnA: zzz Ӿ|s05Pd=i/|9>僭ίoSп}p>oooC_q/п>J(%xa # ؀b8n€"Ȃ8"i"9$X (*Bт.0>146xit:h:<؃푃@hB84QFxHqL&K"RTXqX8?Fԅ^Z}d*fx1jHl؆p(i8S{vx&r |~hX焈ueԈ舓X(ȇh8؆xH腳X(DKDdQ xQȌDTHZ&׈]h91( fRx6UX)Ȅh8 @xQpixؐ )-io& !i ّ*,/i@[)9 (<كACyEIGIKMOYQ)SUɁWYi[9] _ـacyeIgikmoYq)s~u~w~yi~{9~} ~}}y}I}}|||Y|)|{{{i{9{zyzy)yxw9wyvu)ut)tsrYrqpIpo oynm)mylk9kљjii9hYg gݹf߉fYf)feeeie9e eddydIddcccZc*cbb b jb :b baazaJaa```!Z`#*`%_'_)_+j_-:_/ _1^3^5z^7J^9^;]=]?]AZ]C*]E\G\I\Kj\M:\O \Q[S[Uj[W*[YZ[Z]JZ_ZaYcYq!pjzoZqsuzw*l*{eZYYXXjXXWW:WVVVZV*VUUUjU:U UTTzTJTTSSJSSRRJR RQêQzQJQQPͪPZPPOzOJO OO;Uѭ:OZ#OڮNDMjP;tR{우 *QD8{{Jۄvڱʱ ;";VX&(\,&+ 2{4[Q6{<H@5DF[LKQH Ѵ%PRR.[=ZK~Y۵H`kb;ȵfWKk[ShyTp۶2%iKķ䷤$Dd:ef?Ÿc $`Kcps& >[+Q- @0[;4Lຜ۹wQ䰺PW&pī[ [. Pڐ-k%ɻ#fn&[hKpZY{Z $p.+k<`%qTQ6ЛP ϫL +̋ [Bg *{{|̋YLk\ۼ9 {*\; ķ*[|zB%|ٻ.L¼݋+ +󀾨\@ ñOLZŲ1 [S Ǵ<˿c lnl{HlV{ȐL<[ɖoaɜ \LW Vʪʰz:˝+af!cdF [Pm6H܁rH! 6ڼ<Ζ,5 [k\ .  9 5P  l l  }p  ] p +}0\1@ D  <=|] --=+} ( " _NOS6 0:6r]<-T-p @_m`jm j=T =a)hܼ, P)A_؛=! ,KMOPJFED.,2121212121212121212121222221212121212121215'4M5@47455555554445444444444402 *.)$&9 DOX] b ceedb a a ] [YUOB/  !&.AS bn~"+34447;BINV_c g i l o u w x}wywxwvvttssssuv{{ !8EIIIIIIIIIIIIIIIIIFB?;70+*)ð+ǰ/ʯ6̯>ͰB̲F˵JȹOȺSȼWǿ\_abcdfhݾiݻkۼj׾ihhkpu~ufZSRNNNPX_fkosvy}ܨڮ׶ӽH*\ȰÇ#JHŋ3jȱǏ CIɉMR\D`Ubdɛ8sɳϟ@ JhE+ U PJJիXjʼne1nKٳhӪ][%¥bʝKݻxrM𔪧z LF*, ǐ#KXq(k̹<-# ӨS}װc˞A״sͻ7IqNq 7A |~& N ?Cӫ_ou @>˙!d@jx!߂ 6C%@ t@e 0ރv!{NX_|n,[T!%A'3<cBptecH&da?&FAܧTViZM^\֕e`)&V_ihTflGk)t6gxIz駙|)VJ衈hh6ࢎF*zNj7Zvq~*ꨧJꩨRfjʤqꬴVm֪x^kK԰&N*$qIJ.ԬBѦ =&@+dkmP|{PCA«4nKOm)B(F'M(J7'NG*բBgj`z WMJ;+ Mٍ R|ޥނ^'>4g#/h\3 /(9q1CO:n;`/#+[y:-/Oz'R?+o=j _yTy_/g ByyL /Y?Pb?dk79q Kaju'Rl )0A݄h l"4PL  ]H͐p5!aBp @␈H̋ &eN](*fЈVbZ.^ (2VfLc[xA5X<xʑxǜ챏,Ip@"ӝ?PsS5(?Ɓ"tth уN &@16hMcѐѣ 5CmTfh;_JDjҔk6)rSN)P&ԡFR곥2UgN}͢*UQ(*V=խJ^EXú^f=+ҪVsz+\%׹&v-^W~+Z7)b;x~L%d#Rv/3`r,h)*m&jS ղv}5c+5-nFNEpn=ܧoc.t$N-[urMn+ޮ=8=/zw *|KRߦP/*[*3~X#,Rh0ת +CL&>^S⾲ŀ}1+6N,vsL>,>2'%[NqW\(Ky*IBЇ>D `e}a%Zf;xB|3{`>lW>35{eg{~E[؃A"]h= vqpNw:NXY҅ty&ե64 YOlԸ޴;AVnB]=lb؉3l=φ=`}<{z'q}`;~wo-ot;u}fVH8A=p9/tgT77w'NqO3r ½f+ ߶Ml'GHό疛\(Be*;_Gs)[2pwl\(ё=erW-:=QlУ^:_Wz՞ B̋|=NA ^B1*5Ɨ4 [{S͏7/C)?Lΰ6=ObIs3JR/|A"> DS_Qֿ~}/e>"cߠ,Y//?788xQ ؀88AQ=~"!X'q((H$Ԃ.H*!146x:<؃@xB8GFX*HQLTR60DmTH!Z#\_} хc#ax`Cfdmdžb(v"xG|7~wȆ3%h1H8Nh(ȇh(膡x8X(M@,P t+ XǸ{RX5ѨϨը٘Hݨ7ᨍxqE؎88LHIhFC@Ȑ=:7(4H1h.+(ȑ%"(HhȒ (HhǓ'Gg懔㧔ǔ'Gg·˧Ǖ'Ggǖ疪'GgǗ痀s'iG^gSF<ǘ2) 'G gƙ&Ffƚ暋&tFefVQNƛKHE&BF?f<96Ɯ30-&*F'f$!Ɲ&Ff ƞ%Eeş%Ee܅٥Š%Eeąš塸%EeŢ墠%Eeţ!Ј 0CAL탏O*N:k$V{И#T\z^bځdZ xh:Xᣈ%Ee|yvŧspm%jEgeda^Ũ[XU%REOeLIFũC@=%:E7e4/*Ū&!%Ee ū$Dd꤬Ĭ$Dd̄ɤĭ$DdĮ䮨$Ddį䯐$Ddİܤn,ئ@{2[۱8 ";>X&(D,{j|Dydxt2+1ZTV !\۵ V$`d+EiKIf{Nsvu4SY<ɐ_з wP  .n˂-eA@ >_p 0 - _PM M  Gk')Kkv b໧4 k; <A{M{k[K t+ y[GG  +=+{Y٠)ab˺kG ̻* Œ˸rÛ+,.| l¸kx.\ƛcxK4|"K@,mkrD]I[ _\SacIe\gCk Ji|mCq`-|ؐp<4 ̯|| 0}   ; |̾|,s \ь7Ҝ< s | >\̢з&P˕kP  }͸ͺ - Ч,\+AaP%As <P  Ӿ, L"< Vb <I-]}+-0MR "\! qk0 i !,*!!""))++11111112121212193S'#vU:0z)v$q le`YPB.!  "-8CJ O Q S RQME; 4# 0&1&1'1)2,2-3.304243444444444444444444555555555577<<GG]W lcwhssvvwwwwwwwwwwwwxwxwxwxwxwxxy{{}$,6>DHJJIIIIIIIIGEA>72{)w$vxtruuswuvz}#(.3=ߨFܰMݷSݹVݼZܿ^dkwЅ֖١ݯ̸ֲݯ H*\ȰÇ#JHŋ3jȱǏ CII+R\ \0cƄr͛8sɳϟ@ Zʃ/eŅӧPJJիXm0)LYÊKٳhӚe0)XpʝKݻZS6)޿ LY @2̸ǐ#KfI3k̹秕^LӨS# pװc˞-uB״sͻ7NqNn*X6MYGνvdN@uG d{҃OF#}h#W~u<7Vh* A Ft* a(}ԡtڕ |k8[_DytLTVicHv(∪hW A[hdifZYbvlX)tƕeq֩|vhy)蠄gk袌^gF*&$JfH馠Jgjd"JjꬴZkZ᭺|*Kfl6KڲF+mdNkUV)Bv+pu&覛$@ဣRAR=+ۛ d$/87lT1 8[*(ܦYʮұì2ㄲ*,=.Ӳ94E'#eOg-lZw4^3bl "p=vͳҭ P߄'>7+G*Wn*g)w)瞇^(袗'馧>'ꪷ&~%^$ @Ā 4,2خq#T@ BLS5__:XܧO#3<8ʤ'?+Kk׾AB|'/ *aAPcƘ`D~F!=Eoz4 7B~ÓWz}3 "$ ܩ!A"Ptc(Zq}O׬ABbhRQ4b$;E-^r Œȍ} fHEAR2 !DcHZ,%7yLꑓ')Re˩)WIUdeXT1EEV)U^D0LX@)-La͌N(j.frn&8iqS}Ӕg(*PN<(B#Ѕ2=$D#*ȉR3Q8rk(H(ґv&"JSŕ.})c*S!Ҵ3)NMӝb>U PU}F=*1{*Te'թVUVjrUt^*V͑;+Z%ֵ:nU\JpvWp+`&b2Vk}׸)هR,f+b(hCђ6=-ISړ*}-l[*´)nsk6-O+ܟB=.r"]*tR7ֽ.UݫrZ.x*񂵼+zk7}/[+߷ҷr/~⵿+8>0a2}0+ Cl03 sػpxC,b=1ի./c<ؾ6q~sc1,!FF0%3N~r,e S25l-^2L1f>Ӭ&P~3,9[v2eym󙶢? zh6&Do哌 MHmҔҠ6,2LiȃWE g-fjP uWzaf kVzmp¯l\ îs_/;nA]iZ :64$}f >vnvǬ>w]w޵VmUjk~Oxy7yE%njW| W}sӸ D`<&ߛհ~x*b.I? ^IYW-F?zL77im[EԷtG_`?-l_]p(vW8Rн[FuΏ}Msx:ws0AwQ ieA`/ d<8` s/t"9 77$~Z< :!܃>>)7Af)c?Z}/~9?'SoӿX(+*Ke(Cx  CDЀ+H 8RCDȁ$"xb*+,؂%0 7$K8)D <؃RA($@hbJL؄4P"O8QVH-R\8DZbx ^Xqh8joBn8~p7t~vx엇z~a؇D҆88qQh|;Xbq.H('+s{EFHC c7&6&87&Ȋh&x8ȋH&?(Hh%XDɨhh8$8@Hč臧xӄꨅ؎Ñh8'QX ŽlXBѐ1iy)ّ "9r&% ,y.2yz YcA85ɓ2/ ,))I&i# ɔ )Ii ɕ(HhȖ(Hhوըȗ(HhȘ蘨(Hhș虌(Hh}zȚwtq(nHkhhebț_\Y(VHShPMJȜFB=(8H3h0-*ȝ'$ (Hh Ȟ'Ggǟ'Gg؇ҧǠ砲'Ggtkǡd[R'GG(( DKVTQh@ [ +P*a p-%1B拼SὸK*k-lPȫ ۾-ѻ P-ܻ ܽ2P ˌ;+ Ի z21 ߻ [K%-lz!g.'6 %l#DAyV7 <; .k \cL;l'H[']ĕ ? `+P`+{>s (Z\xLLN[ɜ܏dDɢMaʬ<Y˶\˼) '|lI ʼ٢h]<͏f^ ؜͜h. O <PrP;P`,  PPL <ѺA k  ] .]н0 4Aa"Mm `[5]7- 4- >0) 6mϿ:=SJMqm# =e-E<]!mZh ]  uH]xl d !,)21212121212121213.2121212121212122229G;L=Q>T>f=t;979:2+p%`O>{1tg, Y' N6% <BJJHB?:5.%    # '$+)/-21324344444444444444555555555555667799C= J@ QA WD_JgMpPxQ|S~W}_|g|kzoxswuwxuyt{tuuw x{~)7DIJJJJJJIINPOKKJHFC=832/¬-ů,ȭ*Ϧ'՞#ܙބy t q n kifa[UPR VY_j#~3:ݖ@ۛCٟFآGץHקI֨I֨I֨J֪JիK֯NֲPֶQֹSռVZ^`cefilt|Ճڈ֌ԕբլ۴޽ſʵЮ֣ޘH*\ȰÇ#JHŋ3jȱǏ CIɓ oTII@f0a&͛8sɳϟ@ *r%d1aBӧPJJիNޠT)S`ÊKٳhjliڷpʝK]+ZJ߿ Lجʁa&^̸ǐ#;<,0 "ɘ3k̹3T,{MӨװc=۸s4-ۼ N8C"@˛?7N녑+|ݧcOy\˟O?gzG~(D'=w`6X@vHuʈ$((k ]/j4(Y-;@cDi_71oG6pʒAiXF@qT`Ӗ&h j) Ѧ@]ҩ|rghp)YX&hF*銍:饘Xiefm (ꪼ(j뭞ъ뮼˔*찒j)&;,J FkeM[EB?؆+IoPE?ƫQZ-Dc^n-Don1cpZ @# ?M ,KEz,P5O8GEx?@9F'm4J72NG0RW/Vg-.Zwz-6\mveim-7qmu߭y7}-nx/?.yOn_49x樓w5# 9uy#cz$O5I87o\A z<C ;py _@Ǐ[C`# t?g=PGt^򦧾9 4.wN ,Mn At!*p>#HC!H!1"%2q"()Rw"(-rh"Ǩ#85Y1#$9sq#h;e# IA1$"E2q$$' IR#&7zq($(?)Qn$*S9U|"c)CҲ%.]j.bJdLCf*ΌfA)jRѼ&6m&,&8q<,өNV|'I}'#*PD<(BЅ#D#JljR(3Q4rd(H(ґr&"JSJŕ.})c*S$ҴD)Nӝ>!P*á5F=*2{*T'թ:VVrus^*ɑ;+Zֵn\uov׹o+`&b2Vk}"+YQN,f.;+ZO-jy*lc[Rs[Q-p*^*r2}X+]Ri.v٪ޕ+x[=^ӫ^}/| +U,~X^$ q>05`. L`Ȅ1\^~;-U%&~Sl8 6qedjC1%!'F 83Y^K~2,e9[2ɦ-[^F\,,h%4<&s|&a r@),A"33;a ~pyjZg@ sp¡ef4 lL:^fBA0@yvŧGf&,4'gOtk6 BjS6I:֥5mlR F9Az>;آxVc;z ,3zu]hF]kFV;ޡws{}C( ?A H4/siݞS4\-wy}3МX6ri<3yo O<E7'`yՠ{%κN #]:US@=ЮgvC1#u/Q1}x,G|᝗#/ä_wW^ )VA 4hCiAJxkM5 DVRp 0ħ-o?>ngO>B!YE/b gM˟UqqR +c(+ f ) hh*(x)ҁX*@ B W&)~b cN0HR 3Fb/ȃD@$`6A$F9H5RLxNR"QX,BX!Wх^h`Ed cxjDf؆†pr8MvXu|ExᇂHXU:qXG?ӈ!xG؉8oQF󳊬(d(XኸVыHx8Cx\h،M88AQؘx#i؇X۸6юJ8x8؏!H8QEQ yY9ؑq$L yUa*y)ْ80 /9O6y8TBDY(Hy;YM)OQɓSUiW9Y [ْ]_yaIcegikYm)oqɐsuiw9y {ُ}yI鎇Y)ɍi9 ٌyI鋧Y)Ɋi9 ىyIǹɉY)ɇәi9 نݩyI繅鉅Y)Ʉi9 ɃI j z:z*z*~!j~#~%}'})}+J}- }/|1|3{5Z{7z9y;Jy=x?xAZwCvEuGZuItKsMJsOrQqSpU:pWoYn[Jn]m_la:lckejgii:ikzhmg70EC `xJ|CJxz8ofJffeeeZe*edddjd:d dccjc:cbbbjb:b baaJa a`Ǫ`z`:` `_њ_j_:_ _^۪^z^J^^]]]Z]*]\\\j\:\ \[[z[J[[ZZZ [Z +Z YYY[Y+YXXXkX;X! X#W%W'{W)KW+W-V/V1V3[V5+V7U9U;U=kU?;UA UCTETG{TIKTKTMSOSQSS[SU+SWRYR[R]kR_;Ra RcQeQg{QiKQkQmPoPqPs[Pu+PwOyO{O}kO;O ONN{NKNNMMMkMF1.?=@ Ap2pw AP.1;Rq&@Ԣл k K‹ P. # ?`{Eyq{ ` %*@ڨ>$&kнK+6ߐܻ`pp*hqK˽[%>} | 0;ûƻRK+|5,l˿$J[ۻ 'ܹë`A@\ ܻл% 0[K +q$IWR.O[.kkȂ1M\qߔȊHd4ɔlL\NɻDʢ|Lʕʬ<4<V0- p˸+l˃1QƼF1 I1\|؜ڼެ7C Lk& 6p q p 7<?\ -$L] q =A ,"\]P \0*q %3]Qo0 ]|p7794 D-m$@# M6 M =1Qn9M8!B&, lwM l~@-m-Qnqtlڝ! ,/!!!!$$))111111111111111111121212477<6F5N5T3s.x)|!qVy Bh)L1    : < 0$  !)-.-++ +&!$$++0033434444545454545454555577::@@FFMM SS \\ddmms{vxzzzyxw{xwxwyu~o_ROOOQRRQPONMLMPSWXZ_chlot w x y x y{|{~Ԁ!ʃ'2;BGIIIIIIIIJJJJJJJJJJJJJJJOSVY[^acc^XSQOKMORºUĻWƼXȽXɻVʹT̶PϱMҮJӮKԮL֭L֭MدOٰQڲR۳TܴUݴV޴XߴY[^afntx{ૅ٪ͭ¯̇Ԃ܃H*\ȰÇ#JHŋ3jȱǏ CIIpZ2. SȜI3ɛ8sɳϟ@ JGW*[Bb&MPJJիXj RNmnKٳhӪ]k׌5ʝKݻx ƙz LY(ǐ#KLY`NV̹Ϡy^ӨSͱװc˞F4qhͻo5֩ȓ qlIΖʳk}.s0ӧcξD_ ϿYD_B]% `E"dxf݃EhF$hblN!ANbН(4rDsG Jha@)d`7F@HC6e ёPVi啵aXvSIP`iC:pfChxќ a*( )衈IB)裐bhBFjPNPv錚駤`jꪬ‡jA*ʽJPn9*HF&쳈*PVk-^*@vVz+Xk,+M4A̫ ѨQ>[O=C ԃL>6ܰg0I/İ$1G!# H>[q0_{FH,P=p@?;3F۬ =?C_Tt @O\ES\,{shulǼvpgvt;wx,\ތ2 '݊7+G.+W^*g)w(瞇(袗~'馧&ꪷ%n%$^#n"!@/qJՃ 8c:֗O,ӧlӎ3>' _?lG+ʱ {[xڡᯀhK!K`8CW3N \EO FA CCP\R!Ez{!X!A] p:2G/0Fh qmo(:&ṿq>:~ $a)B慐L$]Fd*8J򒃁$&7YMrP$(G)Q=1%*W JV䂬eb\KTQ%.w]%0)a 1&2/ZŇ&I)MiR̼&6m&8q<,өNV|'Ipiu?Jd΂4Mh|P:A m?&D/hA-P&T G JJt I1҄T-KOӀΔ5MќspO Tu,m !mF>2ڒd1N{2&)ìV&,7\&0x*U̮mV%9v&,=[Bß1 zmUE3Ў3c ieN1iKӝ\C}fzq>ǥ-~5a,YԶsݪ]zUj-l?>6eF2iS־vm*sW6,qwR"t.&쎋xe~o~ SY|wXou` aĹ0 @ث $NrK >i"\\Q M.q0D+I=WK2yI.62)sk`AIn)PjQ!%:ɟphw;=U-ֵvRPp#i{XBɑAYHH)J%yNGP8TiVyؔZ\ٕ4V`y!;9feVlKYrtYFqxq/DZ -?ړ<'[$k+;2J4[E!08K <۳rA+kAiEh!&Ff憵㦵Ƶ&FfΆ˦ƶ&FfƷ淪&FfƸ渎&Ff|yƹvso&kFffa\YƺVSP&MFJfGDAƻ>;8&5F2f/,)Ƽ&# &Ffƽ &Ffž%Ee煿䥿ſ%Eeυ̥%Eeš%•Ee‹†~yv%sEmeiea[VR%MEHeC>95ě-f`00!.Z5f8[܀0[6qoi<P]< m ^|y<.~Lf +UN~rt\ U,8@ .ɅL2aʢ<gL0,l_L!lbS`ʦ,ʇ lOm,V|t,˫˞|<Ȫ@)pʬ\ ɝAo_f8!^\P]lϞ))3b6!.K!~ Ȃ\сl<u3oҲеmR<"tl_5ˡB|e| /Ƚ-) =Qϭ^<ʹǧA}5= 8^q1! PI.Ͻ  HP:=U\`PMPg-֭Ɋ !, ;4;4:4222222222211111111111111-4,S-o&dRp3R#J@ 0(  $$'( ** -- /0 00 0001111222334444444444444444444444555566667799::<<">>%@@(DD%JJSS]] eellssvvwwwwwwwwwwwwwwwwwwwwwwxwxvxuxtxqylygz_|UG:0#"*/5;BL V `jw} !؆#ы)̐1ē8AIJIIIIIIIIIIGEB>95.,-/..-,./,+,36=FOU[^`bddegimszŽ̹H*\ȰÇ#JHŋ3jȱǏ CIR%^R Hɇ)bʜ͛8sɳϟ@ ^=@sҧPJJիXMjӚYÊKٳh645*MpʝKݻx)*߿ LKUc^̸ǐZ l˘3k̙ʝCMT^ͺQ ۸]˖:햶A>Bp@͠NuĽ/(Af3N?wf^GOꗲ7# }how7޽rVZC-8| "@1$h` !(4bP+@wnc@)dT7wɽrC6:SPVi/IXvi`i晞Qvh&bDt d;i|VNz)S&t袐FZ[7=*饘FMf駑mRj`Dꩬ*W$ꬴl+]$ T"*DlH&- RVkD~DvPm3PψKˑ.s4Kڻ . jF.A4lg4g # ?Ĺ t? t ]Q4X)5Ef[OdDcvgGpy+olm7mC|?7Lu-;XxC'83BW}+栛yBnzu#TA.m6wqnbRJlP(f b8V$.xOؼ,._3k4fw걏 p y-򹎌d*^Ln~|(KٿT,kl\&[0x8+桩y n g˙kt,<|F@mЄH4 3l]H^s4ݤMӞ6C-EȦ>uSj'S~5,Ywֶ3s}];u-l;{>6eVDݭQS[q6ܤ&kswfܶpKn1tzN=y[y\}%{>7~M} oWޤ3\t $S:8"nkx2.yWrI c @11\SZ(A @:SA 0: 3DWC|ˤ7e|ӷu5aԴW^ l(n. G?W6uOеe.!2%/>vz%SKd<t1pJ| c꯮.[/g_Is2g 9_ 3?L/}SJXl}ݟ?w<#Wt?5gP"w|R7wh%fxrvyz ~0!LwUt[v@Gp .퀂Uǀ,80'sf հ3/t9%..ЄMXwH.= 'XUhI8ZXDžUUWehOI D>rroԇ)G"Є)XX&'*i:1D N@y JFOyQISUWY[Y])_aɒceig9i kّRMq)udxYЗ~)2IdU锅)鋑9٘itYp陛Y(HP =[ĔmyI鐻Y)ɏǙi9 َѩi9ɍۙi)Ɍ噌i9 ًY)9 ىZ* *jʅ*zʂ zڀ!*#j%~'})J}+|-{/Z{1z3y5Jy7x9w; w=Jv?uAtCsErGrIZrK*rMqV U R oTV:Y*[]:_QaJcjRejWJi*٦p:r:vZOq{zq}Jqppzp*poozoJoonnJnmmzmJmmlllZl*lkkkjk:k kjjzjJjjiúiŊiJihh͚hJhgӪgZg gٺfjffeze*edd:dccJcbbZb baaZa*a```k` ;` ` __{_K__^^ۓ@!K#Kw!zJ˲ȥ0KK2;8腳女ų%Ee8Ǧ6 5۴/Q+$AxjdU!%EeŶ嶵%Eeŷ川%EeŸ布%zEteqmjŹgb_%[EWeSOIźC=8%2E-e'# Ż%E eļ$Dd脽夽ĽT^;];YMkN⛾K{MN;BqĿ씿{L N|;J5M \7{,%!TŴ܍\"!¿Xu(.盵2 K1\¹cE8|< V7IJdk5D\>HN|HVJ N<ŧ#R R 0L@E|p`.^| !P7oQN,,b k<uL! vl<}yz~~,qKL`!ʀ fLp|Ɣ<, @ Ɛ,Ŗɴɼɪqɾ蚍|| ǨyLQ-Rre8Q{UV Z}J_-W\և5df-JkXh ֜$חDזdבא׍׌׉tXykl`ŁpM[!)ؔǖ97y]ڦ}ڨڪڬڮLp@=]P|M܍@`-M 4}НԔ0@ C  =PA ְ- X <0ڠM m }- ]n}-p |0'3A ɝ *EPp>nDn):MR.}.R~UQ=~g}ܻmN.QQLdN!,52222121212111212121212 &,7>GMG@7*" 2072w)odR C1  !3@ B; 6(5.3355554444445454545491 ?+)F&2N!." "+4;@B>726?IUbrxsn|}yuslˏcՓXPKIIIILQ]n΍ݣH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\iQ0ara͛8ϟ@ JѣH*]ʴӧPJJ՞4jʵׯ`ÊU)Pd̉sշpʝKݻx˷߿ fX&Zlu˸ǐ#Klt˘3k`ÃsLӨSC̺װcc$*Uͻݲ N32<УC5N5\h<ޝ9O:wޙ34D'=Ḟ-hf| AO$ͅ$ ("`5H`,%-xw_Cwd8.\M)IHF"L6 hYA܌…"#`fB!YOP-JY ܄S OR*H<HcLk3S[q/=ӫ<$rnK2ʭƙV2@\鴚2z1jxjݦ`3 rxrPa iLC,*ʵ]LfPf&hfFe6įZXg&M D)Z?SxڬљNӫL4/ms֏ -j:ƢJEt LN:_Da {觽B<|92ovkG/` q> 7"PB v߇=Yn>ϔu$~VOj&3 Tο;TWm,2|TZW1fG;c`F8B=# wLK,z`t7؀R#z@ Ob`/_r7JD=pS+[E&N]L ,cdZ$__kꀕʆ;ȉWs`h:X-C9-uv3+Fx>ޅ}KTzP8F- 5LcZ$(eRxT9V)_}d`B@(ba"Y[~ٴ; ]1QNY09*g2pTd:RҚZw,Y-D2 ;k)sjK#<]6ue`Nf*<:-ӳ*hP P9o*NƖTd-* ׵hk^ޚD\ _qxi0 NV%*vJ\cO}6nLg9,fgπΝ>ЈJh +N'F[҂yW"MN{:HǢpӨNxFVk\9gM߸ָ6 "Zצɵݑ]kNpAjMj3nOYAMr74vc,QMz+~*ѷN )(Q'N S7w' ^0@1& gW¼$2y b-l.O$ dRKOѧuA}$RzVQy͗==)G:$|Om$gGȯ|k>=Gz?Ozp$/W$z~=kߑ49?F;?O 1*m_/On~#'/bXi7Kw ؀!A8HX$q" Q 8((*0x,X'6x17rm t ꧃7 tCF LH~NP pvDr`ׅU 10 ِ`D ܰ lHyn' A/ ARZ~x腂} ( I8W q)ExX(X} 9H}؆8%V5ŸX(hǸ|Xh|Hx{8؎z(8yxx؏8pHIѸ\|~9I ib yzّ y|${#Y({',Iz+ْ0x/4Iw3Y8u7:@:DFzJLڤPzR:YVX빥\Z^bdZyhj٦nzp9tڛvzzZ|ڧښ:YZZy٩ꗠy9:zmڪe :ZYZQڔIZZAyړʺ9٬Z19ڒz)Zڭ!ڑ:Y:蚮욐Zx:xP6YƩ˰kKƩ+o-ֱ+ p";Z w(*q,۲!24s6{@u@:`WFHwJڴP RzT[zZk\k{^7dˬfK|hϺ׶n+p+}r;Zwxz[|۷뭄;{ᚸK:Xۂڹ4ٯ;{ Xغlli_ ]P)A`YK_ +YkkW ΛK;Ǜ♽M)ޛ;䫽拔V ˼,Dٽ ˿=9{Jk<;mGt=$.&~*,+0/> 6y <&>BxA^}GHnJowN"P)T{Z\=_3 cN- qh^z 5Mq.=GVn燇Yls'{ynpG苧|.vg>慎O~朾֞n]֡^vMpS1n~f뺮yn>QȞnN^Ծ_1~zl4>)Qݞﭽ︆/_ qOjh #mXr'튭+m) /-/37-o;Om B/"_mHoG!FN/PSUWY_[/]_ac?egik?moqsuOwy{}_/o?O훿흏_/짟o?뱯O껿꽏_/Ǐ?o/կo/ݏOO_/oqf DPB 2aPD-^ĘQF=~RH%MDRJ-]S&C3;BSN=}TPEEf҃8>UTU^ŚU+ХQnVXe͞E6iW_վW\uu[}X`92[Xbƍ?~S{~!Ѐ)Ȟ.Ёi%Ȣxt"A&ga* Є Uʧ+alRCf5!ZHЇ ш)$.щwi((Nъi(Z[#/ь\dH,эF:NuģPG>d}O D@B KE6G.HM*d@B9Jw<(S?@>pL+;I|8rZޡeKn 'xJƁ2t 4fҚن#͂ґ=HE'/_ Ф9y,pc,H9jrSHI|^ӟ ˂t %yX&4$$G26)όsS4ix(%řRE dA):L?& Kt螤G}s'EjBRMjҢ\6 n@8zI%4ϐ2%MjZ B`+%'˖rÑ>ać'zPHBD>:֟6֙dZGKF~ ,%3{ȁj֒ ! iBsPzVdllwG"mn%[VimpO[ q[.׶ul]Niu]ݽwJ񎷏5oћ:6 /8!0ɤ&D!PG?ův_eF LX v&ψ)pfNz5P3 l 礲<Z,i'֣&7F 0k]!(,5356# -2.202111111111111111111111111272;2?2B2E2F3L3M3LC>W1n# ~wrlikopqs}vzxxwxwxwxwxwwvvttqrkkabNN==775555444444444444444433,, %)2+  ) Vl |-7<@BC@;.    +5@EGKOV]fjnrx  ߛܞ٥/֬>ѵN̼XǾYĻVQJFCCCEHJJIIIJJJJJJJJJKLTog]}vOvEq=k6l.h$c`_][\al)}7GMQZap~ݑݝۧػQH*\ȰÇ#JHŋ3jȱǏ CIɓ(SeKhT2C;%ɳϟ@ JѣH*]ʴӧPJJu̫Xjʵׯwlyk ؁7mʶ۷pʝKnܳx˷_b]ݛZ+^̸DJL*{ ϠCM1ӨS^9-~k",M۸kͻ!L3aȓ+_У?a̳k]KݺqJ )4$( ˟9t;//a\u7J,8SUhov! Vy( '(AxA:א!<`N 1#G(BUH&$x-a9d9\rY$PDFӒdifjMe vQ4e9hc <eE*<)@ɞAt'O;jNz!{"JȢ<#{RCOnj({~j,bE{BvR2~ji(ړtO.OH;(I j믭Oauk.^irdN&:S匣|:] @oO ʢ D'8ᅴ"i*챥J,q#ƴ2,! ㊩;)6;)_z+;MrbV*@#RZUb\w5J@c>89)8,skkNsp** |1Htr#*~j"d'K>jM|㙋LPs߭S;f/cܷÒ;>d_/ך0Nqbqߋ8>)÷|=T 4'W[w=ǂ꼹̱Okx R7RW*Q"A$e) zZbb EMLo~a*D;#L# W‚//ȃt` n@ı`)Qz/W:}J4xO!(*dj:)zJ#.DPw,HQk߲3IlTff.%`z#䤅7nА$Z; CvIP20P/QBB*8 Jh*H)V|3&J~|Z$7zt?r,oK tcEla5UzlMtȈ!4ɜ46] 0hxƠBQ$G0k8Ϣ !EqW'pRKA1Z]?E0qe( a{>>vLdWMcj&7PVh;Xβe.[Lf{h"2?J\5gpγC>!v LB#ψN@}Aѐ'gFijδ7XZ%GMRk) WV(QgMZ''w^&ѵMb%fw $QMj#n"ѶMrO!vOr7AY$tD)XOx+<'8-?aGq{x*V{wxG83}^qcowr|^ |F~ts (0xӧNkT?s|(Ggd_oH@ȃ!4 HoL(QxqS7 q15ha8&Wl WQ-(\'^(vpxz&@7(`舐xx ؇0L"xNgzX7؋؊AE8Njxgȸ8x'xmgظT%X明؎ƎXFՆ؏ƏYF ِƐYF}ّhƑR"YCF&*ْŒ.&F2y8+<@9"DyfbHILwP9-TyaXС\`9!dyahF5flUry"˧$t&{W,+.{v0:vW68w:ڳ@BxD[zJKLyN7TV+|X׵^ ` }b;Zwhkj}l۶' I!vi~[7y[H~뷊ˍ}YWpYho۸Z;oɹψW@ I` W{˺ȸ UÈ뻶 UKaҫk׻ٽj񽹘 +VozȻ;+;zYK K\X@P , yO ,"<l¹) /;ëpJPп:5؄=zتg؊}Nؐؐ]=ً]ٖݯ؜Ϟ٢ YZڢ'٨-Iڏڮ]ۈ۴}y}јۺѼyg$=Mwŝܞ̝v'ҽp]i؍׽HG]zCs}ґݕ==-' |߬X].o]hBni^n n~ᒑ ">\&N(,m`24^\q8n.͖>֒ B>'֫cH⒱ +N#g斈YUb>nd^c֪hamlƉq.?nLnwz|竦>觶↮i茾ӎ>Ҕ^陶 1ꤞ~,>լV갞՗>r궎 Nd.c^e~i.j ҞiNNdnۮh>iN.h>hgngWt ./g0^tڮO{OgW~w*.Nn.Nn.Nn}zvrmh.eNbn^ZVRMH.CN>n;852/,.)N&n# .Nn  -Mm -Mmۍح -MmÍ -Mm -Mm -M~m{xuro l-hMdm_\XUB@ DPB >QD-^ĘQF=~R$G/FrsJ-]SL5męSN= y0ePEETRM>(ҡQ^ŚUV]~:hUe͞EVZmo5J\uśW[TUX`… ;aƍ?YCENƜYfΝV&zhҥMFmtPѩ][>[Ɲ[nޟ][pōq͝?rխ_^Z;\^|:^zh|}}(@DP@DATOB /@GPEPe4RIs4$H'4S*RM?6N?4TSOlTJEUW!S#V_VbEiO[wu3\7Wa=W%6Ye26#d6ڥYiŶ'j/6[oi[\sG"re݌ҥh]w!x'^}-^7z`f` Fo~a'b$8d-nc?c<WE^dW6eTf9L]NfofflƹAuJWhx&:i6.ii*jFk:Fl϶lfEn;IߖO;oIֻB;p>6 7|7?W}w?W{w~_8@D@ŀ TA N Y`5 nЃ>1B|l)GX  )aJpx!(X P*yC;˜cATH',"ÝeЇW|JHĂpPbBCqB ~S2q1Q=)/U4`ЍHjX:VլgEkZպVխok\:WCDAx!؇@Q}kz-> }-&uSk]7z׃؃{c(u!Qv|6N[Xɢ0mb5Qij{EaQX#eYZCMl`{\+e r(.w }$^E݂(u7^ݢ q-[_.o_Jxmp u E@,`9+ w3@80v' Yx B-;C1M9|ֱ,AxBq,9n !,x2122222111111111111111111111 |e P < -    +4860** ,, ..11334444444444445555667777777777675829!.<,*A:%HL!MYRcVmY{c|i"g(k,j1b7RBDM:wW/l`(bg#ZlTqO{ D#9'1,(2 9;9 :?GJKLPSV{Yv[r^oaldljqpuuwwwwxw}xxxyz z { }~ڂƈ,+9K,#8;ïKMuN-lS}ɢw̓5a L#/,dL(n4L1׬sr7ǔ@ֳJ?mjCTLGK7-5gF:+cL,p# ZƊl-cO˶ԪVr}-b+[Ab\eon+I:.r%K9we" ]6#CuٺDiWwF׶ňw/鎗r/|;ηS}[QwyR.Ѥ# S8K02"qC0c$&.YCwWxŭk1 cxnc똁=~ !=F>2wd0Y- )ۦVڏC,G^n Ì-۰d.4#yrl ;yN3([37#ASMʆ~DϦЎ # IS:p6d/Ks042MiO Pz/~u^b-кpKu%WܺB4CaΜe]k> /g9^63mOގ q{u&%=tr춵] xZ>ݓ}5em3»w8-NCܾ8o/rOFA&ɓbxȹ @A 8PRs:O:u·sH):i/]~?FUzϓE$f>|IWDӊ38wî%нH1%+:WDY~𒡺s~"%uKaG|;NC:G[QT< C$5kF˵SY 2c++K!p@*Kô=˶njOfhwKR{;}Py˷ {R1  Kr0K[  q *+Jʺ2 $J5eʻ8 $J;eۊcü>]#Ae JXWýIt*LE:jLO7ʾF4 R%1J@Ue.:Xſ+ 4C[%(j,^$#a *Cjչ˲lA 0aڥ.$,,&\0%)"L¥nHt(pixZC 8ڠ]X@ d #@ A X* rPn!Di:hv><:%NjUC `_,*p0 _ - d`s\q},lO\0#|m9th=\ƍv.l(|) u|E,!ȑ^p$< ELog%ܿCX]\q<4ypŽ,E PlaƌCuK}ϬPչRYm\퇈&dfM0BqF3v}xz|~h]V@ - a ,B ^@,` -  1[1@=/P` g =p٠@-ܤm= ƀ c ۂ-܆ݓ=ݝg =ݢ=}0 PM֝#ݨ-s ߸  =ߟsȭ,`ؙق /څps`} ݣ0==>)~-8 ޅP-ٯs0 >I0$ ]<]l8!,811111111111111111111////////%%##[4  (3:CI N!Q#S$T&T(S0P6N:M8L4J-H*D'A#<7 21)2/3244445555555566777777777777778=19EL;K`>Pl?TrA`?dFuGqMksTcP^hDGIIIIIIIIJJJKLNRUUUVVWWVUWԿYռW׸TڳOޯI߫FB>1& { u u vvy~):K\nyŕΜӟףۨ߬ͿϾѽӼֻٺܹ޶H*\ȰÇ#JHŋ3jȱǂD)22R\)˗0cʜI͛8s IR')YIѣH*]t&O?? mٴիXjuϨ.YvKٳhv ʴpʝK.+d˷߿^jÈ+^ppaƐ#K,q̽3k٨e;M4/1^ͺiaC+`a@׸s[lw+_Μ`o|~+%n[Ư7}ïR7x=k1U-*)ȱ.ؗ߁ֵFVUUw( Vh!Z f S_2$UmԃUW%g4&E*֨㎺hQ<)h>VH&YPDEi|M)QXvYZFdUilCj)4 Щ/ِ 0)ɐj&(C.袐F*P =*饄RvqlzVZ֚j<:;;V2T.B̲9+6vtgsK1T>3?RknQ`lWt;Pۮ{Sr/Ak2ይU4l?3o pH,0f-hv+P2 flGw0n ! '6sn>܂(Dj;"ͦ%N)RjV"ԲE(a_ 0jcܛ/r4~x7G9rulG=qryGAq!!ȼ-T#HMq/LC$ ʿҎT(-ʽҏ*5ѐ3\>0aT)̀Nd-A%Є"siC ˉf̟F3rIB*^A"-H:CR SA$)N-ӝ&>=PU=F=*zT0y*T#թV Vꚭr5^jԘ)V<+ZW*;mrT+\?uzʵq(`mWGud +b%~:c*d7%jtg; Sv -mNڑvVmI*+av-n\v1-pI+ᦶu-r;[2I}.zJAѽX]pw[.xsJbYw.z6] |[-7?gʫW9N,.&"0 _H 3 s0~C,lĕ#1;.*cL6Vsc۷D1#!FnZ,$39t?~Ֆ,PS2-/^.<1yf&süf/yor0MWOևim[ۺ6N_OE 0lZȶ Pg?N lmj6m6JpjQnw#89Mlcg\hYnx'6iqcw?. ~[d?N{vQrxgqysca)9ˢsrV69."v ~m<,}Mw:WNmSWwֵW;ɰ!Jn뙻c';VBsZ=DONs;\/x'~dWxxROӎc>yZ:2siúCw+y;lS+}G@o٣> l{g]UO/}@|t z-e ;FMW?-8=5K_(GKq<^V%5PAW 5@ Pies HOp  HKeX85 J%'88aԂqqEca& ]ƃG=DH7xXFȄ8KU!;HXрOuWȅUq^8`xW [Xvejx/l؆5qi&Ff Ƈ &Eeň%Ee݅ڥʼn%EeÅŊ劵%Eeŋ勓%Ee}Ōxsp%kEheeb_ō\YV%SEPeMJGŎDA>%;E8e50-ŏ*%"%EeŐ %Ddđ$Dd݄ؤĒ$Ddē䓱$DdĔ䔏$Dd._@}\Ya^ R# j)_goY_1,sI0aw&g{.}Ŗ~)9.zi٘Y u_0Y0k(q蕝)i/iXGyG9GFF9FEéEyEIEED͹DωDYD)DCCCiC9C CBAA9@?>y=y&A$a ,O&j0p " Q )!@!@\ 0<g0@ ] 5 L̀  wl ]cF`ό@=(]6]2 ϭ* ^?l? 0| =L <zd`1++}+6]А3}? q9=k cZ 1K0 [ѿ׆)A1!,!!$$((00111111111111111111111111111111222222222222222222231415181<0B0T/f*|)u_VMJGB=61) }wpjaU!F!!:''/,,'00 3344444445444444444444444444333322..''!! 0HMRPNIC8-""&&..66>>EELRUU``kkssuuwvwwwwwwxwyvzt{pjeb_\[Y[bcei m i i pz|}%(,0599;>ܦ@֪?ʩ>@EHDIIIIII|HyG}HIJLOW]_aa`]]]`cejpwƣʢϡӟٝ1H*\ȰÇ#JHŋ3jQׯ ?±$B/(Sb˗0cʜI͛=KΌ+UJѣH*SϥJիXVS•^ÊKY%r۷pʵ8D\sSwLa^̸㈉}LÑN̹糙nLiݎVgG$s~zj^$|,V<J8}gCnvzR倴ǦD{w$_<=^{}dgT"iGu FcHT"-7ɇI(Q(?]m+:rqF4"dbX(dɆ(%_DxW9KULF)%NNfXfRX]`diqyh@jZtgUs֩gwR瞀2'Tjh.U行ȘX6hR钖*駜^Z*bd* hI(j+|z*6k۰2?쨌̓ ֦M}C|z+|KFnye:ˎa滯Kb!:2O%hk1Cȼa|0(j)LVJ-T-8{sR26M/H#3R='4EKTht}VFQ5`uQ_m6cU`=lkOpM8mxߤHm߀-xM4%8ΌxIR@<۬?k@_F.ɣ:@>h.:":Z%~ r3:X ,b +O1yuYWUn܃ v/J4$ϗ/QQ05@.r+W4 p d=\@ @|ѰJ`K$m)$Ll"X(JXT(\0nO* F+qkcGqMt̲-QU|ԈX@%D!12Dnji#)IHrdEHL2LD'=/PNd 2 h$35d-s˸|?eD~ ̜ ",&͎d*et3h6d$5\fwJ7ٲm.$$̩EScgB u*=" }~L'I??yO?rA.RA $P$ZjQUTF?z(e$ IєhiK%S tMq o)Py%ԡުFR2TN}jBCJtTUjr5YeVJmdWӪRz l-RTjPvW:n+`$ɭda#Tbu Sc#=ĪMd3Pq6+ZZm-sHZ$z-lE$2tKmOSyӭoIƧr 29}n+P.v \ w.x;#^ z1}b+_з/~ ,.>[`twpm0Kxn/r܆?n$ S+.~Ub,cиM2Pxz<ܿ 9>}A#+YiL^lSy(Vr͒FS=+%srÌfd1y3v9Ev6 ̑=9Mj"@qЄDΎ٢i4!3iF6zPt$? jh 95U'ծ>c]YN$o[׷6kbثF6]jfٛ6]ijGڎvMhn|wmgrpFwՍfvbwez_TdyVBR5:A{C F17c N];7(;!+%.UA/8Q yA]\)C$Q`}FS"H|vʋ~q\jJ|^ N\D8UN:(%*Qϟ?a)=%9:T9Rs=|I^I!z|Pα|!N^*D%`>{ozC+ɽ䃒W/y;rk}%G>_"v俸ϯ.]zR1AtJgPg|H0Qsc7V ' 1''Gu`sxׁ&QqE$G^`)+hp2 %k8(V?/$؄q`q5`V 0cax(3VH dsQ1a@hʐCzhT !b16ugbݐf][2NX~nk(5EX hH؉-QSy'QrXhȉh"!7& (^ X2ዿ`0!PŘiˈHf(x2X՘,hH-X&7C9㈎oGB=&8F5f2/,Ə)$&Ff Ɛ&Eeő%EeۥŒ%Eeƅåœ哶%EeŔ唜%Eeŕ啀}%zEwetqlŖid_%\EWeROLŗIFC%@E>>?¶?ĶGŹLŻQļVľ[_chmszΆыՔٛܡߦӾܺH*\ȰÇ#JHŋ3jh 3SɓS\ɲ˗0cʜ9ǐ08ɓϟ@ JhP sYҨӧPJJ"R{Vʵׯ`):ӠɰhӪ][Kݻ*[߿C%È+֘A#Kmih (${%0%L*,.l26<:>B}F'-J7NGRW=VWuQou^tbMvAT B@hӨ6TR 7]wGMX8TmPrk#x%>:;t9;Ϫ6t^P% U 홿#[NA "7_`B=Opֳ}n~풏~篟Eos;JޏgL<`.1Yz $ >l3 rpLB};a<3z! [$.6|T s<30}>v(Dw*!%:N)RVEr"(1.ft 5n|(G ұ#A=:~An<H1{$${IQ 3MrR1$bB)J9%*mUGL+c9Xr.%[rK!%0a~ 2Ia2s4|T)ͨPO&6gmޤ6)q(AF7Z 3}@җt$c"H4/]?ɁE+`V5U|AYѫ@FHmaa3 )īS|j+tn,Gul`9ڙ&5̀/ p2 uS@ػiB-7;Ak 81 W#GqsߡG;h'q8H38B8sT`r0 @6u>1c mn0c`󘳖9 N!QAձ^Pc hȆ:tf>vd;^n;;tᇉwx^->!<71$ ym9-(8z_m(Jwn†ej_ƽuogޯbd4F~aK ~O`}/_z]]ח5~/]u\ɵo\%Geǀ%He ȁ%HeȂ!%%He)-ȃ1%5He9~=ȄzAw%EHseIoMȅkQ>%UH;eY8]Ȇ5a2%eH/ei,mȇ)q&%uH#ey }Ȉ刁%Heȉ剑%H eȊ务%Hdȋ䋱$Hd𤌽Ȍ$HdɈ䤍ȍ$HdوؤȎ$Hd鈏̤ȏ$HdȐ $Id ɑ $Idɒ! $%Id)-ɓ1 $5Id9=ɔA $EIdIMɕQ ~$UI{dYx]ɖua r$eIodilmɗiq f$uIcdy`}ɘ]䘁 Z$IWdTəQ䙑 N$IKdHɚE䚡 B$I?d<ɛ9䛱 6$I3d0ɜ- *$I'd#ɝ $Idىɞ $I d鉟 ɟ $Idɠ #Jc ʡ #Jc壢ʢ! #%Jc)٣-Bz`x`X*LqNXGO q>*7!PǚJzZje gA'h#(g1Eү>tL1 (:Z t8!([: )۰* PzlGH@!,*E!뵯[s3+7Z\öY*VCjUoR÷sQw+NC{kM{ UJpp yNlW10Q tkwKn!@+;[%Ppp𚻻ۻ c& ˻AVP,P/ ;@  %~ /0+d[苽+0K ;%VkۿK > ܠU[٫\;{p[˼ LA6 1` A .\+L  ׋K @<{@c#A\%\;;Ƌ } P[ĹP$U\]!,5 1212112111111111111100A+1('%0/33444444444444445454545360!8+)<$5BGHWP hTuU~SSSSRNKE7&   ,<Pdn#1=EOUY`xjlnZxJz=|/w$pb\TPMMPX bmvul*`0Z9TAMDJFIHFL@P:V1_!ip tuutuv{xy|unl oz&6CIIIIIJNUWVQJMKJIHGD?5) qhb]YWVX\cm1HVamxڧәΐ̋΍ёӓ֗ڙٜڢH*\ȰÇ#JHŋ3jȱǏ CIBX60 01\X͛8sɳϟ@ JѣH*]ʴӧ6gJJի QdDLXBKٳhӪ]mطpʝPʮ_˷߿ JÈCjsǐ#KLo˘3kNDƎ+MiћS^-+0 MIY{dUM{+_\oɮbQ.xA0cSBU_~֤ӥ7ß hVLh 2`zE(n7u rS{{'$(ԃ="ON⋘U(_hٴFi"&?H%t5i5qx/|0MD%EI}roS%u/'#,Y+K z+b,Z*/ղx%VBXpp%ݐ9<CpVs& YȸH!6yRr)Iil5% Q y};Tޙ'+UNdfrs\JQ]ӥڌiC$,N mXWQs;ԢQTQCJ6\Q5kDt0X#=ZπfBЈƱAD;ѐ\-J[Ҙ&ڢN{ӠCMR:ѣ>Wj.հeYָ6s^ZaMb{yN6f̃fuMmc@6QSOঊ7!q>G2nvtM`{Ψw~WF7Jw x$<nvО8+ƶ.9W20_.<4wn@70ǃN;FOY;i:ԧNHXzI{}#\h?vpNwϽxwOxKfG8q3>o#uBp1yʯg1:2lg>3-=Wc_=C}of/l}O~_Sw=s>/k6?׏nV?oi?oh~8n&xTf@ 8%xd3~ 8$xh( , 08(4xh8<lDM>XHXBLG"؄PhOT8SXX(W\[؅`_d8cXhglk؆pHoq8t؆vxizX|؇a؅8YXXQ؄IXX@xȃ8؉H08Ȃx(H؊ ȁ8XHȀHXxʸ׌H7~x藍H~؍}8W|蘎·{zXwy׏x}7wyu w ِmv9gW9vrwy"و$Yx(9*ؒ.0846y:Y<ٓ@B9XFHLyNRًTYxX9Zؕ^`8dfyҘjYlٖpr9Xv ~y}}I}yzI 0 Иɂ))ləI9y'9ٚ9i ؙlX9ĹY)9X!)ihکz9ߙY8H䉞맞)9Y9y zw ڠ J :JZڎן"|$Z#(J{'.j084ʏ6z:*<ڣ@B: YFHLJNRTZXJw-xץ^ w0_a*1AejgJv ٦NP  !@k^qj*qejY rq S }JڧਠN ̐ʨt̰͐I Zʦt!0Ayz0*@'`: ʭ*J*Zs蚮 J: `⊯ƪ6ǯ p :+sp+ⰰ[skŚ<*ڰ"sk&Kkq+sʱp5q$+:+?ks70 p2ǧڴPzSKUK@n^rPq\E@n+  +7 з~[s ϶zsQK  {27Hn+D ـA{s57s{-rۻ';r;W;qț̋pҫo[vػnڻֽ n6m{ɖ[l۾k;Vk[~Wj\k~Zi|  l"< &L%,,24\877D qF|Jq:PR<)WVg@f\e^-b1\$Lh|ia1n,im%6t\p|ǎfzL^|9ǀLł,;L8l52/,) &,#L l , Ll +Kk +KkՋҫ +Kk轋身 +Kk闋鋫~ri ^+TKIk?5+" +Kj *Jj욊쐪zm g*aJ^j[XURO L*IJFjC@=:7 4j p逸nibm O_/ϡ!o#?%'ߠ)+-O/1357_9/;=Ϟ?A_CEߝGIo y& @Ƿ0@|z,q| *V y|Tp~y sPhA@TO_| {/eY/Y{nъ1/zn/0140 z @P,//еğ:eyoӏ̏0|ǯ_uI9 >q ^0@RH%MDRJ-]SL5męSN=}Th bND(=^ujҁqiOqZmݾW\uQyX`… Fގ?Ydʕ-;ffΝ=Z4}GFZj֭ v[lڵm߆}[n޽}pōG.r͝?tխ__+vݽx^z-w_|uǟ_~0@4@dt0B 'D(0C k%:2mCG$0KdE;;PEoe Ŵr2H!o%y( jI'2J)J+2K-K/3L1$L3D3M5dM7߄3N9 lݧsfp'$ ig <': v@1ĝA dNG-=TIIxv8:AQP > eUI5Ma\>p5t^]%ظpdMQUUUXk Y!= :u\0H4ruŶ]wk3maQEeWh}_S7]P &f-]w]⥕WT8$IfS݆6Sa !,~22 ~mmғt,,HߛHttHCmmҿtm\Qwm U\Cmm,t CCCCғCmm LHCPCCP LmCttx }\ HHJHҴH߿tw~ tt GHmC5\HL\ttߛ1%Ht6I'bP3TUUq6* 3,5)H |  \,IPC3F Fғߛt,\߿, ~ CC?  \,H*\ȰÇ#JHŋ3jxPQ C" ɓ(S\ɲ˗09!1sɳϟ@[ y3ѣH*]ТMJJՇ%غʵׯ`_3 ٳhӪ@@ٵpʝ[xK.߿+a #^̸qRQ K&;+_@Yt^zg!H0 6ָs}snyy/O6dzkG<[RNHWݼ ѿ\yt߫_onQ5mg{G%"`VfEnM$>a(zxb,Vb02b47c8"(bP h;bꌨD1{K"_)^V؟!r5[bHE)qwaOD~`f3â+0A".*(xE/bu ghq6ZIuQ47-})nb*Sl.jS=)gN35oc\8W8ֵwUc^ϸW2Ub`8,֊bb&6V=bd8 VևafqvV}ahY8քajAV`l)8ց]`nVm_K\t)rB\E@q%@̝.ub=ͮv'xK^0@uZao|]׾Y{^bW0U[08%` w 0`"r_PBVn]* b@f Aq  R;dA&UL*_rL.{Tkj^s Jgœm|+ܙg{nJ<@~ɢ\ mQU .4?N5D-\bZ!V_Ϸj:|^7kպz^k:y6^7lw]ol5;vv]W7mUt]-mu[ov[6hYCncX/6o;bvXoә"3+:pm:8$3oI 6qU_W~)|Wq<^'X |-7tռyJn^.C/:Os EЃ~w[:=ytJC=[WϞԧʪC:;uRzb'UڿGu9;מ(&a<(\B hcj;%y*U^[-0%&ހo铴z$H'RLg_Aw=#01dˎ@v>_;ט';퇘,?k%⇡+~߭_'Q~?_w~CeBԥLbHDĀ΅TÁo3(NDhQBǂ' bWDȇgŃZdE$cańcM^%dZVkS%COeKÆG!wDUG}B >%FB:e 5Ĉ2/%aD+ʼnW&$"E_xNJdA!$e$pNj|Angzd&x%%3D ereTeǍυ%hEe<Ď$Dd܄ޤď$Dd섐Đ$Ddi?\đjelnpŒrtv%xEze|~œ哄%EeŔ唔%Eeŕ啤%%"| l$isYD"9uu y)&wt{-dZZZ [)[I[i[[[[[ \?yiiiiij9jYj}t`Bc00›0A`#I=QVM\p&#`5V``ͅY_ўI\` }0<)9Aٞi:\Z0\I\ zilq:e9 j 깡:Y =z\C@z1ڢ+:7`ģ"FfƤ椶&FfƥFqYQ ajC!8Q1 j4!n Q @|ڧ~: ?  :P\;JP *DuppP:Q` 9, 6n0`*nʬZnziЬ ڬpieõܺ1گҊ\`Ӫ`;Я J : 90F::m9-˪ ڨyKj@OZ ]!,122_ d~  _Zee2]`||>m P  x _P Prr9_c~ a@XX,b.*|_a<5_2.r$k y`| @_Yyy b`UO<aOaq<`HM4)a$JH@ |PGnHbH K0&4mĩsgΞ0y shIFM)ӦKRt*ujԪbzukA^v +,ٲcɚ=VmڰmܭuŚUl|p۳\[TO!3QC1ܓN>]tLDEU}soc׏aG=veۗqgֽwgߟfxqW&W\qIF8WnOO|r;/=ĹO/~b/V/?u᧚~!؝9ؚ{)8ax_~a!68Bx\0zXb'N"a7\3Xc?(vc"#&*#z9Y$~I%YY%i%y%&Y&&&'Yq, @ ~.s p@ A(6j>)qʃNxu"Wy:4*xW+y IJ+M {ޭ*^K۪1Rjj@,& A`'K/Y> *(EAdpH`{5 "X+ռ,af`I+S,<,.M {|ЃIOt>*@yT~;gNA P<0̓N PDt0#J=x_-P_(0 [9!{AMЁ`3(r EhApDK', _2l wXC0 LaA4XDKb'ZX-jSF*Q]#x+ebɸF1qTcxG7ucG94d"(?6|$GJ< IFђ$9HLvR4e)=IUVt%YJZf}D-@Q)q9 %0Q6&/LgFs&1iOVٌ5`nS3usLg+LzZ=IN~Ƴ'8O6Qs\ nm[rzN{T4EQo}@+:Rj'5G Rj]@SjQ0eL;ST5}Ogz~:1BZR$)QLHb!U% H " !>,~22    곴@  .8Ć 6 "ƌ rx H"hdH*WȘ,iքSfAydhЛ=#x4:ijts6cXIUY8ࠣA82T- 80(A. n߉ $`8% !,r 22    곴@ <Ȑ 2|qD2FF =~(rdȌ(0؈0%, D fG)hрF@wh $>,:PJ@A XXj@c$ŶpᾍW"] =wou +]y-vܶa !,W.22    곴@A < |qD2FHQE=J )dƓlDdIlSXf4Ϝ)8x`R@A.EAB _Ӫ]˶۷pv.]vjwľ~lp0a'&8p㹅G6pq开C9m_w!,="H22    곴@*\ȰÇ#JH+jȱǏɓ(S92ʗ0cdR͛85ҬϟwJhJC*]Sӧ H2J!RVuӯhJVU ]keK'KTPOx \0@A#$p ` K A9>ࢄѨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkν[;@=͟GSz1ݿR|'R~ 8 x ) 9a NXna|R&RhA!, T*22    곴@*\ȰC |HŋǏ5nI"G\2J0?|fř4m\ǝ@gУC40ztgR 4 ҀJ6*T K, V' HnS AD +^̸ǐ9dʕW^ƜfΝ=~hҥ)Fj֭lڵ ]{w'|-!/|dݛ;.ݸr!, _22    곴H*\Ȱ hHŋPD C0@ƎG\I=JdI˗eάSMuIO-4QJ6:)J'nJԫŎ%kS۷oPmћػ]. p`R@\&ΚRpl, d= 9S@kg3 !,9 22    곴@<8*`JhCB1cH , $ʂ$Ub\eŕ+g2J: DSeCEU@g҄KU. 1)I2 h*iG\T@'L` X\0lMi ٝO$pZ ❨"AC  !, &22    곴@*@`‡8@@CHPEn䈰Nj!$iI) dI˘gҴyN<0@'ɠ"h#R Bl:Rui$YCR `ԸU Xk@@m̺ pW@7UAr\C k#2,c@!e, W22H*\0@#J(C3jlhqǏ-:IA#M$2ʗ[I̙5syQO IBL"F:򑐌$'I? )C"p(dbQN*@maJ򕰌,gIZ̥.w)H @`j<u_ӎ K8ʙœ#18 XӁ̦6nz 8IrL:v@hk. &-`MOaD'JъZͨF7ю f0+M a i0KzҔZTڄi6MNwӞ@ PJԢHMRԦ:PTJժZXͪVjTt ;j@`,4؂XwV~p\J׺xͫ^׾&0* -`wjSίd'KZ,dתӵXXHb Y5ֺlgK[&@aXveMr:ЍtKZͮvz xKMz|KtF.;؁N;'L [ΰ7{ GL(NW0gL8α%| 6=1L+xH&;PL*[Xβ.{`L2hN6pL:xγ>WH! @eL.}&`'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^_}bǦ4mle3{ٕMj[ζn{MrNvMzη~N\H;'N[ϸ7{ GN(OW0gN8Ϲws;@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxx|o|؇~({8(zxP؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙٝ9Yy虞깞ٞ9Yyٟ:Zz ڠ:Zzڡ ":$Z&z(*,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`b:dZfzhjlڦnpr:tZvzxz|ڧ~:Zzڨ:Zzک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Uj zp/9گ;[{ ۰;[{۱ ";$[&{(*,.02;4[6{8:<۳>@B;D[F{HJL۴NP : 8h V[#`[;]ka cKf{͘j˶0s[p@tkwsK|۷k0+{w{X˸tuk 1d;+X˸ 5P P1`kLຸK5+p ۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@B@B=D]F}HJLNPR=Tm%)Z%@S"P,!0RcMlH gSr`v-PZ0 j~]^@0=Ո R0@ ՓסْMר OCpT@0P]B1pfN pq !\ @RmhR}YZ!,^722  ~  x O곴} ~ @*\p #Jxp3jDh"č 'v G, Ud) #͈ 20#O|T'ѢetCB%(uV :պNJH; ȕ`[\w@0⃺⵸Eu@a *HW1AO hXĖ`&0-3^H!ТÞO/㽝q7oڹ!,Bp(+22    곴@*$8#" ċ)V|A=2H%M(K+!f̄3Dy˟Ili%Oh X~ @C]As|P޿ Lxe#xqƎBLw2e/Kͬ(7?6,siG䬗ue ^,[pcư!, VA-22    곴@*\PJH+j8"ƈCȓKDɒʕ-c| SfL 2ڼ)OtDIgCE@ғ% $@ӑ pQU`Wb ׳! 8V@pY"H oޓJKÈ+^̸c<Yd-_NYf=ZҦ'Nx5kƮ_+-1ӱqM5̽+<2L!,A6(22    곴@*\p #Jhp3jz7No HL:'H o06ZЉnl![A"Vx_8h -H8̡w@    ",p?&I,bvu?(>QX.z` H2hL6pH:x̣> 9 $ ^d0\la$p̤&7Nz (GIRQ,@ Tr_%WTc^,K- 0IbL2f:Ќ4IjZ̦6nzT6 /"8 1 ^`؀gpc (8~ @JЂMB)cp>T(E-ˈD˅(MJWҖ M'=yN@"y (LA |HMRԦ:!uhG!_ G*QrtTW%jhMZֶp\J׺xͫ^׾ `KM\?uzW?bm! KUhGKҚMjWֺv*%,@-nZ۴ @"pKMr:ЍtKZͮvz xKI yӛ3A\bͯ~Lxxs@$x ~sL\Z7{ GL(NW0gL8αw@L"HN,b  e)SQްe-r`L2hN6pL:xγ>πMBЈNF;ѐF,|yҒ41}JYCMRԨNWVհgMZָεw^MbNf;ЎMj:H!JJleۤ}R NvMzη~NO;'N[ϸ{g7Gq|V0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{]NhOpNxϻOOx-:񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙٝ9Yy虞깞ٞ9Yyٟ:Zz ڠ:Zzڡ ":$Z&z(*,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`b:dZfzhjlڦnpr:tZvzxz|ڧ~:Zzڨ:Zzک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;ۨ6pd%0 րakPP&kK .I%p0k` ,8[K5˘$@rгi/ 9+K Hq O^R;PHKY+t@[_: 9e (8kk@ qۗ@`8y˗@з8Kж@P~{^zIkWK{ 0kJ{{ ۺ0ꐳ ۗ.k ~9˺ˠ y[@  @!y,22?tmC mm H$ғY :oHM mt_Cқ$mғCm_mCCmCHCCCmmHMootH: C_Uo o ߛHtC  CHo ?t~U*t_  t,,ߛҴtmm_ t,\\ ȿtHCCCCC"T$#$mmCP ,œCmF,\EmCCCCm ?` mC\,y ߓ`x!ߛC6In ,v1m y6t::@Jw1t,\Ӛitz7gHtҚgt[ t` mPx 5( :5_82 Ҙdҥ<++| \,‚ҚhmmmH4\SKm 3[ mI _ Cmm<ҙgHo ߿қkHM ''CCUUUttM7SLt_ ~ қi\,H*\ȰÇ#JHŋ3jȱǏ Iɓ'\Rʗ0cd8ʝ8Mfpϟ@ J耙H*]ʴӧJEBJǖ,j:&9hٳ\Ӫ]˶ےRʝ;KxS,³KÈ-M̸#W}d*ؿ3̹H-w%/EY롨c˞=[4OU}Mq+'{s N?&=bǣOnO^+ᦢ~?&_B5_&h 6 &uNـЁv!EHAvWaaHpy1<!y¸ۉ:bO,bD/8ay9)NcA2aXREL0eqP~֔U9PbԖFפ Vdd|CΩKlwVI`&Q^*:6E(f8\b(ziHMZ銰jCLl ޛi/j+A*筈+I'drk* r%^lT--FΒٶ.wmMiKDz+ع6nH C ؼn/oBڻٿ!L\ WF5,G׊ 0Ki<1IU,[d(pDAQ=UEmш]4ZJP vh VHEm?Frh<$HLh!CGt`%PI|`h!#OY#VHT DA HSlK` \Grh8J\)JBJ3i (CH2 ̢iD,`{*d!>_8jdc4mC''@N`CCBN$5k2=*PQBbԢ,'w)Q~s4*TN,L/Ǚ'UN`)NwH\Li;@ԥ^s?C#P89њ0<ւ$3Ġk?K%((I #&" Lth--XJ|l0'֛\4/{$O;;Z60Q;RVF3&HA"be٣M~lŮ[IX !zӞUf4`hE!{ԤwQh `^ˬ7HץwtAMꔜʝm l 7 Zn4eY՗RE}; ߑ~N+ЦR_!wdܮv֭0~mz 68Q,'fz 3 itlJCN73& ' H:V-j&/tL;`4 %U,7gl$3Zyr̮)ʷ&iiarmkk],.3LL3{Ki =3g`6Ν3_LjT!,NH =Z@XĞvfFyxn7-!ekxwl7)Ne0E*q%Lfhêsdљ@&Vħγllr蘾}x;v2uD] %jp9?XܾhU2ґ-wZE.M(R YV* 7vw&śGKiC}kl{Ӓ|05>_Z媛yytOOiQy%<ٯTe|GK-Wj?G_Хo:&G@ZnNR|6{&mu\^2{{E# ! wpK#`dAUP D W=.H447TLcI"9Ax(x5cH5.75` a ?\؅NQ3^6Ufxh5`1Rir8{l8n-pH|؇iwyX-{臆x%YQ1fSXHA>33R& @apQ a9;u@rf`, { ^IL)NqpOU uP J@ JЕ_9a)cIq+ٓap\0^Y`9zWvb?iuِ3٘! @bOiy8syu \@09>i391JO OIə6i3(yQ,ҝu2(Y|u$G 2'92Ts{=1'3Ssr:9 *1 ' 3jRj60&ڡ9b2$3&J0(%*+ӢY2 24/6%8ңQ@*1B/D$Fz EҤNJ0P /RJ$TZr풥=\/^.`#b:Rr0j.lJ.n"p2R(rx .z .|Z"~2RJ--!ڨ2Z,J-j!ҩj+, Ҫ j*Z, zҫ)+Zr̚(j+Ъ:Rrڪ'* p2Rq&j*/=?HT /dWܓ9s.O-$Cڎ.OFkAEp,{= n$5K-O{<{>B k^F+J L xAU!:)\ ^2Qf h)jl۶1tv(xzѷ(k鱸Ҹ(={°kO:{غ>;z6'˻q⍸4¼Q+ӈᱻѻ֫kл1ٰۭX[Cڻy5 udؿ<r8:<21yQF͏5E>yП+Q=?Xۯ蛹VmqNWT `ևDC Lը m=o zD68+ETԎ6 ˁFm$v6 ʑ0Ck َm mٻ=>`hWՆ= -ڷ11^\j6` ۻ"ۼ)] H m@= <=},2-Cm(#-8 <ƀ }m0 =ም ँ yMΨxMQtNtF^*.%]i! ~4 +;~1.,CEG.I~KMnOnQSU9A?N_OMG3>n&ơqcrnpr>(t^xlN|eP{_m2Uί13=#芞8:>՗>ua=<..*JT>(&4"`Bnxؑj+lBe-~Ȟʾ²}=3R>N!Ͼ.o^k>P"T-X=K1\Q!\p@ ^7@s2{ oO'o1%'?I4= .o.s% ,%)DWێ%3G6R?-/o1!1[V]__a*F_nrc$nTcNeCƱT[sAa aN}/!ꪟǬ-i>ȊgԠOv[p?7ƏoϽ~ǟ Qo0o͏я ]=}@@ DPB >QDnifQF=~YPH%0`ReH-]SL5m8r  jNM>xd TU.Tie֒W~VXuVpM$X֭śW#Gpב[ Xbƍ6n vȭܖ "oh`).#ҭ]Wr2fce4p1d5͝?徭;vr?1ʙG^c%0hEU (oC0AkJ" $P31CóW"E_lH ]`s,@U\$$rA2PÛn,ɜs8Ҽ2Q&4UdM| (ibMɴsLQZ3PAs:UOD*M54R&`,TC%OQNS>%Tnkfx0Ә65Y,cdoN0S!Vv}yfzl6:-L㟣OiZ!=wk6fܕfnn*`m6+lang1;2qo{q/W0rzq7)쁃9{$ _R׾>|)ϗs1}-"l'Y⿿?eAD`8 }/tnV <@ZaAr NA4@PP|l!AV,p" kxQ/ :d" D&hEV2E:eIN箑pvbr(F(Ix'|LkZ8Ge#v̞`@|q^c̖G@Ro$HI"*΅ I2'; &'HB:%md'J5tT a9qxݭҖZSN9F^^ϗ뢓 NS,fj̽2\,A6MjMi.͊qbI1sm#颉BhR 1y`]d@ :#vυ&:y?wЊbΚD&$^g|s+`akS}2LrJ]k}N;݅uB6FyspH@nW{`FSpL6V e2}w {|~F&D lm|Xz+jU]2_xQv*"{._ˆ \+TfOpnٔQ;-$NwT\c7Z^ ?M\hG p} mJK`ȁ[f2'kt˔AVkQmZ/Z'LZ{WmoTL}j {lRAvRϰswE5گ˶DLn9-nu m%vzQlZjޱB4h] PM/{FK˫ѧ*{XMHrNxC \˴6IUlK7ggu4R.%W:Jz3uZ.+*y`k"ʔF;^0|1Ѫ+yN{GʀO;[jt}榠n7'?(e.37&oiKǼ,Gl﯃<$A^ui;@(w?$x>7~ӚO>c|#?c¬C{l|uCQ0?גI_‡S>cϒ:toS3@Sa2:z,y@>j ̑ܜd$AL \\A80ÁAe̋K;23A٤|BBl$D\C¯hA = Blc.)==2d+?$T5l0 48:<8C9&< 1C{Aˬ',EB CbFd ) $!:34Dx P>$Rď[<Q<>Rt8.DYE.5?u@ RABmCQDE-FQGH%IuQJKL=QMNOQPeQRPS]TUPVUWX]PY=Z}[%P\%]u^O_ݶ;<ӫ V]V\V&3VDdhf%gOlm nUOo]iMj)R~DtuvuWdł׽/E>[W1zՋwdF)q F#ȃEXر9h0rtXő׌ 0M~%LX/}WYm#$W ʩٟ-͡% ZUJ ם3Dڦ%pNZ5Z [ZN<[II[Y[lHy[[Z1۲]EôKR[^[鶲,Xu˖IM>E!˹)#9E6Mݳ1\Wܰ1K5X]֭˩̞% EMM ľ^p^^hUM]Mu]=MmUM>^L\c߲U^n}\{N6`ۅ\][U_1ͬ`-`_taaZ6ƷFЄ vF`aa죞j`a"a`Lb"Ybh|!⾬bbbb c(cx,h „ 2l!Ĉ'RhQ!"S&#Ȑ"G,i$ʔ*Wly˘2gҬYP N6wB9,j(ҤJ2] )ԨR:*V@r%+ذbǒE,ڴ"UQ- .޼z5z/.l0Ċ3n1Ȓ'Sl2̚7s3ТG.m4ԪWn5زgӮm6ܺw7‡/n8ʗ3ox593g`{X`p$o>؄ޣ/C @|x bv@8a`P7 ҧ j^<@+Hz! 9y!-"S{$`v4$Z#=cJ!P7M9ݎ@:$Q&"4X zMJ%!*,[_1111111111111111111111111111--,,++++((&&##j!cf&h-*rc$:?.lV09 AA3?A|Nh5`]J'8/4*' .N_j~(8;D0I!S QVNIKNSGTTgn r y }} ~~x*)##ǥ2՗D[izޙӔЍʚýzqllH*\ȰÇ:JHŋ3jȱǏ CIɓ(S\ғ˗0cʜI͛8sɳϟ9Y `ġEʴӧPrUBץZÊٳhӪ]v'YhTۻx+PUÈDøǐ#KL˘3k̹c5nӨSV ӅMvmsͻ͸rm=l@(Us_ۜok(;w}O'q*)5ٗb6E) q[vإhLZiVjZk֖F m*\KF܄BJH|r4댅*Ԏ+˒2!RcaQz)m&jyj@JZc裃JgйJ&S oJ!G&lS;4-lt-֊JAݲ- ;p  {nR\2kBUo j(,ʯS; s ',0-Rʴ)JQO 5l i;*(ܩrԾ **e6K/ܝ̭{)wGs? d0шiI'|A2J7x `yy+g˩y=qTbm5-)Z8}/;Y~C.R2?PKO}L?zoߵ |%+|%Cwr#G)q\=@Z@= JۂJ$1$[}@2Kxa^DzD~(|'BP Ia@ ,s P'&fÒ` t1]P7tIh @wC඲z$\!lC_ }B!+C doX&:Q#HakXF1])H~icrIC:%3> I˶$\7 X"VEFf.j$+iV$,'_K\r\q%{ED\U7gp^5YhED \R9}sg1) )|29~+$f5O·\d()Cu,9r'fV_lA Z(OS-0Hyj 1,fm{4́,,q Ii.M]H^Qd(U WpFR#աWSVtR,Չ2`zC 0-C%^2W-sKZԮcK^Zӛz0u,MU&KW2ԴͫKzֱg;4/N3'Ӟn-#>LP]N#q(VrkjCul2v5'[cIYɆצi%nAveYV3za.9/jKkЊ5K ߙ6@h `VDmJBd*B&&DcnX#Fi9ww?b>ӮY.)|1^Z%ĥ Fپ\d-89&[^r#l(C%B&sWz1y3 [##cTeUI>F $H@PW$qT7fc!+c0wo2KT_OM2[5a8v}mWz vIa-k$ֵNs]R:&rDk=_;!hA-BpX'HKwpG.-{vљo̲ըob+lҴVFX¾5}e$ o_q;IK{frzK2(Ŷ= {{/S3MRn{Zvw:^ Yt"Jb(QM'g&m*ڬ ZwEkKQ5Selg} ;W۹awG1w¿~Xw?zW>n.O>m|yٔYV ppb`bٯB%+w?]߱/6vLhX~un{f皼Oymg3C O(~!F4"E d*!I1 @}7R0_~ͣ_'sDe\,~2%܁xF!7x8W ~W XS`g'&{2ug_Gw㵁d XɇfreowЦrz#`z{f6G }[tDd+1NJFGayBy6hW|qCr/Z;у?PQu Hvw!(SkXfdqqz Ep__xd{q~|vXiY)W^sa}`W!584[UCX5FH\#~vFJK7DMfwԅ.!RxJĉ!}9wWu{s_e%pv偿w ֌ejv$_/ &HYZhkQfg }ܦThӋ%B7#f(Š+؊*q>*(RJcȏ9&i8jER=a8 T1F8>6y?(a\kCy=/ ɄnVyWuT#Q7A@ o"i%ZB"[AIoaWNxI6@~SՐJ8sWtїR:W%/9t;s'"øzb~3E$i9I qxXq \bBYB?(Oٴ6h7GWFB)xMJט*U^!yu'š2a#B>(+tiS'/i~1y #(H)B %13/7"?ȝ\ ♡ia'^di@ㆢy?BY,9[hd ;@hXکr2JN2TjJj j3?>yآ3ڞ/ZNY;ɜїw $F#f+Fh@ؙtU>q \C 0:Z!Y)^q4zt!fNg1:<ڣ1C|jJ?șjuR7Zj ԺתT[D : jZaJzJ\zF9ANn?u ӦIB)ڛQJJZƈ֎pXXY%{ *i]#/z4@>>L"ʮaZj.ntK5 {*$; ` 7V86Jy$H_w K`0H&_&^)|+-i@x[#[:EAs8>KZݗ'Eɴ% jW !' y*7UK7KIf;;0%Ѱ 8Am*G^u}}kp&hrF^ ucۨK0EK:Kq5(gKT{1"ҵis٦jiK~x;t:]ZXw&(g;WUr/Hqvj+-+dPb0 *KWYӸ8<[@++M ȒtGAob\ 7~zڻlu|Rcǡ9|^vZZ eWk*gˇ*9Qa1,JQ )l-@̶1JUZ:pNqO<+W!(QzS qN!kdLhb 3. 1㽵:YGFInVnR.a߲k ~l# $ ?jJgxAqKL%tY^DJtN.2NGR4$/KzqCyΤ}]8ujT(J ..٪*nm~6L SN&5c=u Nk^~~ZzAڱ)ﴙtKCe &FR ?B`:)O -'$O&).otKe k˺hkj#U#[c+o~OMaIR:*q<UF+njh?]8s?Ў{a3v/<:Q>?'_홿"a Ae? ^>!X,/zx~ 6FƏ4OK_&z}*gO}!D@' 4B .QąB~$(Ì=~9@)L4*D(%J FTK)%\%ŝDA{$T EyNU*U^ŚUV]~VXWzVZ"*ң4r49˟iNZfQ8/;a+Ir(MB\jNU"0mS 3ӎԴ5hNYOHʧD fI9!bZ5r}-jDrW%YV/ūrۢMOtӬ}Zi<k؎ۘ y֭*m)lNý327=4Uti><;ۦ;oaK`xv;Bl{%zOkc[_Ej9-77//w@EC_zw$`WN3CsHv+4K/87=w;v/;y ⩆Ny?3; ![8(@۞:sƣAJ<lk ? 93cOP%&'\>i>xȖ }.wR҃\[ģ`A<=Y=1A,ERԫï#DKRABˆBX8 [0AL>!&H64:d224;! hC5:9 \B$C>=f[".Wu  a&E^Fedؕ䶠dtMPaNjcNePOQW6e@|J4nU [Njuf_ff0"fyL_`Y~&eܚс{~ubsfIAa,g>f i\ԧEh_濛^1jL[gpóZdnjmNȄΈPmh9tN6ίv~wfx^1j\vJdiS6hށc^WAkvrne) l}\,u7X5h6FVfv׆ؖ٦fmnY nUk5ãQj^,Nl׻l,vAlV\nѡޒYjܩ1Ϧkӊ5p78@Vfvomqm'&8=n (^cHFlʮfWEnkk(X8pWgwNf_rxN*lv}n}(w WkXơEsh4W5g6w7q-O*!_pjHn&Lor>h5rRftpz#2Tk2Dh8xOPQqVfh0ߝtqRfYf>uĻ X7tFuzGzwzw/zM^Vgxޕ׷p:;ݵ^,\bxiy!/< xzЀwfzz70zz1xHc|Os#zGzpqPpWEoן'}$׌ f{>[c㰴ەt8wpH`]wh^tOW]qx_UHoO}z1) ,̇`F9j!Ĉ'RQ JzZsX$Ƈ'K6Li2Hwb<0bhB2Hh*#[Num5W_vԊIrK&3˫"Ŭ!(bʕVR\TNNm=Pc[5_Y;wSeZh {O Q7lvu\ =|Z!qi\OE+_c&+bXAP!9\;Rۙho5Fl{D [S|{O?~RTh}^C ]Z99Ǿ3ϐW4-wǢRL}uFUl?T-* -"M(b۞Co.|! !bP(a\5("ML,*1y .]P-ӔD# ZwagBm{1|#(džЇ>! ZBt?r*a|J3@;~,uq`f*$0/#` }K'SQh/fQ*)(-t($]&⦊"p6&7αAH|"Yf3_c ewSeB9qfC$w?P(QO HtvlQ'L< rOMbw<^?g4q-ڄrB^}#6h Ʌ@fAG-Cob68QTP9;rҒ[ɘԝk'S~Q $ՕEki@AG.q ۨBa*X&ѕ^(H5>liThTɚGz󛰩V^DS!C>MgJ OET-@ <Ң*HU>[62ARռ'YM׺r)̫a}-l)2V̬k,u-OF:j(|UiYկvYiTeȵgb׉V9uVhsSb*wl*nlGԄFQ!rfR1 |]`tsʍm5я.@:U Mu=Z{d=w3?9"֚;s9,!*.)+{[P* {D' FjujݵZG%%0}i` *(4,;5&.*Z~Xdzq $K(FU +µqaǼИf1YN 'brZPc[|/:y28e3'ovPG HAqDwCԁf麙6Bgqh$T+z1xfQ^vjkTkMG󙪸B))4=uqԶ}9BEC"֥ `)EhAW-Vvgml>;εR.SD َhooEj(55*&dNL-{ߵ{~ǶynUv,G&/Go l:yK#zW8s۫9i.IrsOon [gqt)o沗uZ;+{HWvv N>):h|4twﶏmL"_ꖾk<$0.Ώ<-~*N|E;GnU_ڛiCs?|cQ揝~9nQWD]Ռ|_9Ŋ-]U\uYEm9 o0AEqΗe}. EΨߋI`=EO MŠ h_UJ_^|r O`QP,й An.NI^ K9,^OؗAVƛ:H !a& JMT `aܡ+Ɠ=^J[R aaR`-u#VQ%Z"4&bE''.&/*TFv)#(aIQ#ab(]$":7:$C6C>$DFDN$EVE^$FfFn$GJ R#Ql"d#Ql#? T`>8"I J+Ρ=,£9~.>#1;MeX#:b2%A~[$U^%VfVn%WvW~%XX%YYvGdPdPf`@5!ѕb*$Mc> QāYOP :1`&96%>"T$ efn&gvg~&hh&eeP%ic/)bS^ $Q$tQd-a&.^Q)c1 K1*녊0#i^'vfvn'wvfZ&UĚIJZxs28&QmaeJ "pƣT~"&Q5JNt:S\Tv'FN(z5yI\`|!.yf!(gd8`=BlMb=b`;r .bf)&Zx~ʆI֥Iz]2h}*g]p gc'{g/,hN ieZfJ)h~k>D)gxR) VnڨM<*;Ui5=֓Jގhg: T`R)e)Ju* Xf`(5rPͦgF(gA&fm&ߨ>!}|u*kΪZ*6gQ+dJpvפg& +()б֨zꏶn m.#+VlJ+y*i(&Kkc鼆eio2-kA (:,lfzם)Nf'Ƃ>Dzn"rl2ljɊ;2,ln5dmqhmrZº> Z5Vyh\@g& xCfh&-5.4ťJm&&XR*Vbxm1hQE~*}_jm^zp C(.g("nm(.'>:n&\`-9:^ʞYQ|aKbF`Qnk6h*pFѯDzܮD?xBG1.>'$E  .f"j,l:ohQjMNU$R%bb"AnzBlĮF2/0 D "/{7F'ohq2@?qߞ;$C[W0^felӶ7M.d}*Z ;Rp?]bѧ2Q+q Ě\zHqr?`1pD? ̓)_;#)(벫0~`1!pTo Fgv鿶L%31 10rZJum'@?tĘO*o--.};N#1+E/W Zӝ(n^d2VoU\o1ld!r6X6װ1.J7St!\2-r>" D+/L 4,ӳ<@_,A4RZ|B"7QLtVE?-4'E"GW,Hp73sHY5I&gr^oUܯ](1w 'p ,+tQ<]PdvSO.ǠTŭFb0nFDӧ*Z4HOQ:lWPެksjG&\˦"Kwfr;5&vHf(/" CS#0r\l/6Il 's,5Wu<6j4w:M]+53tl%soaG Lh\=HΠo]D[-{hֳyQ'R?@80`AP)$1"C -:|(E:<81dI@zdK, z9L3qgO?:hQG&UthMO.F:5j͂0f-ւL6 V(~hAYY\:Ǿ![$AJg:u [i>hmR F@ ɓD- ]b=Z!"˧CχRUîF$}⭒Her$ qX}&V#kF2-z-4ۤV3Y?škx ʶKYb Նd)"c|0Q#mdH@!%[n ,VK 3.^bhh T6,O$gJI9bˆ:1t%e3<ͣ`GO8Hu GQ"I>t3\$Äx· bh:d\By#%,eM 8瞐K'T*O3?]Q.(FclDRޔF'HUBA阪$iZ ~!A?r8= g.YTW{UOEے.Jm.Un6Da]cj#Fe l S,'<+]+H}V=_WIpâW*z%e'O4Rɲ-g|} F-Դu) [xa 4\JwvIfi+r(%g1@ pWu~[U/-wt/EI7,J vu(y 7yGRRdu _F))^+CX4T[D,`bqE67a 'YE.LB+Qc><h?j^mBv883Wތ Ÿ955ל9\`R9+6Q-20+̈́New6f1T53M82Z1` r)Ke?s{lFW;Ix-C Q4\}a̩EpvU ZbŝDSj`[[X˪Y]XLCEƥՌH5o_vɰS$Vj#MI^Tių} ܂,RԺٽsV0ݺzmi[ ׸;tݼ<5yk{7Mp=86^64_q.mj8DbnG?Oj&OjT1dGe-]Oص!ojZ6G-lsluH9GHX˒khtjeh⯕xe}i#y_ϖ3};ܻ׉&}i[ŻfyyAUa2MJu_/?oR;ޤoi{m\{p,to/FNI*8#^- ndto@h8DB&|‚nxvhC$$J(į62E`1WN,S6.C p9CR$W.&K9jRLLMBMgM7޴.&d,t /l%KP_t >e(U 1QK?Q u,dvn)5,-0,4UG+S4*hjHITQ#UXxC\irS&-1U|u 59%XybhFL9U,2Z R,,.).MoZ5Z#W8LDV1P3Rcu^q`o%uk@dR5,rD`匮6[E1aIWN}$V\u C dec.Ps84$gLRL-OeWvZ^+βHf[B@n%uFugcgCIUSfJfP}eH#xc!@6d?tMWGdՍȌ6Vp `tr@ `s1sGãjvbmOZma Hh !ibvVp'ckiSt?x%VNX="W%'*w` .,`HWwtՏFN9tEuMuYKgS_T!vUw]bwUJ]&tUQ2dLW* .7si |u }& Fd|qDS̷$׃5}3~(~M ufU Ck7iGyl/* c4mstsx+ibp98:C"cI}4}3~ UXX8$4Fx-\%jH07f8tx sfHM~Smr)x+—S=TbD8"VhhbS!ؔoC+ql/˔3i"{)؂cY17e/#X7*8"TeXL:oQXJD /|e@887/Pk/Sr-`@{{| w"v"zy9~9Y|M+7,]//9s>CoERٛsz3J8Wt3s "ٝ8,!yL4. q0X]Pt炠r/ דY9%:)4]9&mye@:5halD !Ќ:mzpXg"ci!K "zUN -,DhKb2p%a:! 8" ̂5Ni!BHϮ BDB&Vg֪ ۡ`!i@8oosZ׸JwA`zn`AD[H%˛c'g| ̹̽+Kbi y29A{[BֆHUpg=<Eŵ͎[FBAh|),0=$4=9=-cfۮ}p2܅qϛ} G1SM׊˝ZG>*s}~%](+^ƞ&Ȉ^E<>՘};rh "kɯG>59$B^Ff>l[´ʗg%址>uo yn"_o%[33?r_m_j?>`Q?Wa^o_{4u(_.a>:_Io'ij?i y5B <0… :|1ĉA1cF5z(Ǒ$Gv,2ʕ,[)L42klǑ#1+)32"%yNL:} 5ԩTZ5V4= M:>R#2 rLk6ܹ/-b+-^!Mx S+8u0 :s[;{ :] N8v \h?mK6ٴWڭV6}w;+^x?H8R"fHG[=zpkls~zN8O_|3.ČhL I]H1@v .`:qW\ p_iynxz{z$߈&}y:8ʸl`:(4a~]Q c,yĉC%FIe _9 eb0R<&>Z9RIMf1AiAt (X"_Sk*9hYi)~ޠ%h( 9Z |Vi&MkإzkAd+ج֊lqZӮNKV";x:$):k"i~ n)tܨV oS]{lQ䪫o#A /k K{ gŒp:,CJ,<Ʀi\vz sW"$ (ߪ^Br\IPD4|E-4^O#tJ6׉3 Q>7Amж%VYhERr2$7v˕y]g5{Pu+6Ő-E@K %Q TQv鎨+t-[`{[VYETDw0-tka^7EGın+4^.fqxdܸTe^֜NRW~~[~6Z { 1z[Ɛ"N!6!! '"x$ڟ\.F0 "g=T]pUn X_H{6[?U*-j y܂.! 8Q//( 0Z܈r%aMF¼%{:!_t0tS4 zQ@L7DUI)ą "%»b] Y(GYBXX:`B xSjyU%823\2F30_dG 1&S\2ViSe{Ey\,bK"ϕ_IhSi$Dcչx35i".9Y0]f G*MET`Q-4hJQ!_ )ΈXxtI=EY1+IJOT%_iX88tEt^)XEH~AhDnrbK8YgXqU2 =M#;ֹTЍ)|Jδak,ϞI:@̶TVU*1.XEVUnnb\Eu* 6Ϛk]7'Ut,.5i-٢$x;jbk~jX3]T@IzaͬJۓVg_YZzЬ\M_뒜~6`),,-0 F\*{`tUj~󿻓CY۾DUFRL|nIrF- ]k Ľ]bPөcjՌ jnγYuu 8(T6uِ +E+md_zZwo|eD'Nb~ DqG?Rm dR!Qi`sby 6mWZ6dG>f|1-Yiukh7j9&V醅Y]Oͭz:1 7&Bsf(^O^8Ǟ t0ґH|d+j鲯r]SRaej7mww]g?SP hZ뺽i}ط7mx&+)G&3:~$}+i>i:ڛ.NiEZ7u)-ɵQ'[>Cl7G?=f[piQ*jQ;|W @@^Ǒ<'Dɋ44־g`W$RO@d=P*lG7K&r{3Ɲuq+{.ǥhEipwDP1,?#If05J6-<{_J]@rPY$1^æ>;uWa#}=b8Aߦ3ɵkBE|bGgݶxnnV|t}x8GqB']vT/=E~Ba~4{(ζDp4 {eHB3H$d߆I^hჯԀg@ gYn6dw$BO.H}}}1 3$E%({2,s?Lǂ%Ak85WPU3:=utXY*g(e#TBȇrvx{Nlcb&'uQeAUp)mKoHgI`$d5|և\:8nX=xRXggX0HXgxl(_h'Oj~g{ WڗwmsE !S5Zy8؍WcȏH"HpuF&˨| ~f}N֘M F $48m(EuBe&a1c!+okԐqBfsSE؏A'E e m/Y8y ~h59v?ufXCq=iH!"9Ulr#Z+ɒm؊1)}|fIai8h@fUO? g(}5wQ3q28OyhBɄ6u]W_9x!vX͂ovNgjT3Tx~jɇE@ke YnjPRYk!eZZYFIBil0h)t--ťp1ؒn(4yTI؛`|IȐzA^AJ)7UnJHI TjFYfSxGnGIAVT6p ;75zR֗q݈ErSDx6EZ蜅蟼uDfə.O]@^ !:[Y 3$i/H7'ۉ&5zV)QCJ*7YrGʂ rK;5ci1Oj*FE3}aT]:28$H!1*#RU2f(i459ʐm:GfTY=IʜFI9)S\)؉|UdxdqTdt#>z2a0艆FV/ўq ~hDƛ}X7 Sv)1j dKZ/E2z*Vʩc%4IEJeӒT`+ѧjd9֍Ipr"`;bAae̢dJ[+,^szLa!)++%D(*ʎ.GU$$$Zy=A'C{3*sXˤVך]X{ YۉzcKLf2jDk/+1#vN1Yq;h:cyK7{t"`NIi!*8ۢʰr8÷yuVV)2=["(Ąw+h$Ö0 *xr:rxSSRn[uͩ 8묂!>E N#'G;-lc(n<VTO["y?++^G#6/þE_rH|!0$-۶( DZ[?4, [,6y=kĵxum m ["B2RTe@?J¢Œ׾|r ZA;fq;Xl,{<A*uu<ȜRō,/"˺%stɅ <@'%!aDbBS<Mz,~q sxT!М|,B'b-pQ$K`$hekqHOٌ\; y{*Ra|a| <{"li骩v)/dZF*ѻ'lÆԍz&# [Ֆ^=]*ȗ&,OZɾZCM_l\=kRVfWNL6 m_PY]qZ N+=gKD̩a9w }nS1\*)X1VP$@W-ڨM,| NBk(=7w\)1@ q)lpr~ 0Vͻ=$ =NJLaBѝ:=2ݮ qQh8̊2kUvlב2(/ f-ޛ+$%^Nۆ߬ M3o 0%B-X]3Pf3hRL<,*tvU ,{9u1ތ\F>й̣v1Nkl/1jnZ޵s=%(;R#r !Y0FFkS>wk=g_ 9|}Œrgmͧ^m]DZ.M>C0f%>cTgE@oyE tb.!3*g~1ՔNg/΀l 8~뙇7.-er;Sb"1îŮ. ~IJNU:U^x鲎ot[{Sa?xc\o qT9tX~qO^fMTEa֑]?KiQ&),^m2El>h<O!ߙ܇&!nR?Q2=e?uWO~8EĘGD4BíXcV:;WW+vzSb2~ $XA-P-4L8Pŋ2ؑ`YdIѤEO6LȒ+eԡ%%GTFj2dł-ElhJ@ iPF YT7naի@D*؂d(ڬH5܉Q =勆_m8"\aĉ/fcȑ%Oد5o{ ZlLffeޢ!YkƲW,-&Ձ{VĬu8S;*]k)ݟ.-|o {^0A.+}Р,h- mӾJ;.8n. 0x=췃ZjC# z*6pAj 7.zСZN#=! o>K0s$ T .H' Ύ< ).DB2,2PT$cjP`4kϩS(8K5͜DޖrL EU| %A,- l02vXb3UdRdU#:%|M5ը]ݻ늝LVtKdr-I -k-SW;RuGNEUWtrSH1-壟6_-lWO,b3f;jY,(.F~NR6UYH ט2QtճHa딛w. Q:|]fwPDP oV79aXK,bpW z ƁLxoc}Y6` fpSꯌjiJ] B4紫k~[(7jڮ1NjOj4邗Vͬ33ӡ\vXK`Q)[ᄈǘhp6!b44Q jʥ'\S<7h|tyAzmgҪ%U_WKZ<.ԝqifˋ9+^ E`@ΐ0d"nJ wDaq{K$f /|d¾>QKcN$9ϋ>" )Ln:RR@Q*)QF nHΑȌ!`TB`)|(PzۡAt'DTKLdWLV\ )G@NjzsU)i7AcI@CJ-2`qzS #1wdNi85Mxbf/?5= $J -pa(b y8R[* Ur["-ObKM.eYAl[肄oԖICǝ`莫3`^hL4׸)-R@K̏&!y֓0ʠ' NpK-@OyP' +"ġ&hd5I(x,ǵ sЮtA$I dt`9Pt@gę$䕐^k֕oZ*=\ Cpè:ϳT@ڬ>[*jŽ)} a۪6PFwR ^'~P\iޫ5)bf؁yǣ)8 ufkR9bk?Z-)tPQ3zG Z{Q mk۱$e:Bi KZ^UͽI.%Ʊn^[SXvx9ם8 "{˹vؽ鴱K1X vaLxe)ebbW2(rtѵwMInuuz_Imo{Gս }-;(ǸȡSS`dq>跻j 6r=pq 󷏲@Z+Uc; p?g5ܢ, '<3ɸA{K!@@dt@̀2ǫ軾= @[7TcQAAx; C?뫻A#AH۾rµ 0$e"!{Z!$1XzMlBEC<(|2'Z)*h8BJ BnA2(1?Bꪉ^;8,Aԣ۸EE ?F^Þ2emV5gVH"^><=Ӎlr5)tu'Ux=]m7$U|{͹U9?\y-oJق5҆GIPM P}x4UvَX|4ݑ՚ (JOcK` TK:"]pUUF8Y%X Z+-Z"TԐR0XE|ϪeQCg8; ;ڴ[]M7@eӓ %eҺ5ۼ۟[@-J-!=W3 SZL\竣dXvwMݗ"zBu[a]jQ^)D5p78h_}_______]m"b2u<PVn S* -ތRI \-ӉE^LXY5Wt`߂-a@7X5haaaa b!b".b#>b$a`v̻xX2ˈM]3Fƪ6C ֲڊmc <*[mb3F)VDkb4,6ٽc@dAdB.dC>dDNd[&^ ']lГYZb$}e: BP^o ƭ\s1=+Q5Y : y-85V K#dSd_e`faf_YFv%%e nm`dSP@Qf(巣3U3E$T@mg<7.ՆB[.%f}g~~6FTXXhf߿fggjedPz(s. 6]F=a[>T85FH>^diidfb "hni[hNhL~`zVS%7J$n.7I6cU}jQ\6ÈWgւmDݜ|ikiSijweEmXje4kO$=jf=0E"V}=Y-f州kNm.fF>fLf@HУmE6v7FT7kB."B4 !p{†ҞD wn[9&~,'*VRy&o a6o*|V輰dpvq&mi{ENͶ'#/a/"(TvMesvX.r#k=?Fnrvn&cp_APdXE DD)rEXUX%q,&)HIG7ʹ5ܳ׈9aX߿W/i;]|JQORFj'G1y؋GAnv'Knm+VkM.F`19 sd XOCKZ]aWxZty0Vlu?*^*x{iEv_I/gدH`IdPFtthr 8ʏNumg/͸M#xmszeOrr?~/ zVXo's/Bk_PxOx-vvOOPO؋.XvpGyIWvfW{{yKjntkXz6/ֲVy1wZjY6;xאʷ}AeЭB|h{{H|xE{P/`Wf|*Vu|QǑ<3Nu5\})V;}z6/ zb"`  EK$Ѡ!&ɲă::DhbȉNDr%J1#\$Sb/")y2 0=:%b-ءLvyagؖhI^\œu-KtlVMcΤhŀYVHwLiOOQ M>,7VoX [5A|D\W`AYW_!A)XepY,7Yv8FysjQgt!!B t}m c[f[AeCgAYNUHK4b i݉imUM7y2ALUPjVIUU1 '5 BSO'{'2ڨ_ vt o8 AA4PCR8~!aG ZxPM~֌ FS>Yh% )RVJ#UnkboIΊu+H1f֯;%Av$ўU6OﺑZ烙& ﳻ ֨r-]X"i]IEՈViRٖ(+d;|YgK# [w%_9C#tWF6qi \j)AݖNKH6̷"fQXsZ' Q8#= G1iuV7}8ǃsj]Jc曫A/-/fW5[cC.[A+ٟhiYvspo, kGfp"޺Ø{3#%s8HQ&Lmb9 V.[RzI 8N[UF3F^O qYBќxLVް5! ](CЇB4(E+jыb4%&6w4hCCɬ"DS>OJ 2Ŏt\#KQBӂvrL-]kN3?1ϒz؋3aOs&eNғ(kp5j]+[ַ5r+]j׻3܁FB<)S#0uaڹVmdSA\*NW)PtqMR,y󉜝>-+U8>g 4mh[Y7.qk"7].s\M  dLM!Qh)vC h;ޔqNqSC"[ʹs+}bQO'N0bz2QB80+lJ^ @O VvҿUܟ9ÛH~^;{J =JZzֶUgoZIa8`#ƫDXY҆8X8b3 ݓx}}+\ 6M!n Z - ~l+LTc9;sNކqa[iM{$@׍*TҘvKjlVZ[WgT}X[ ݂?3$IkWlem!Z$OU#D_++Cr)V-Slx|dV76rzvS;w Zp\t+^_HkehY16,n!9&j-?A&3lOu, *)Z~?!WҲ f~0/ps{ΓJP\e`U~u;V}Kuiig:E;:QhQupBCTѦ-G117cV36^!ԉK!!)5c:ȡ!#ө#I!>f"c9]8^c99]!pA(#&XvecAĝa) be^Zy dBu=b CN D ڙUaZǷ)^ 2^rMƴOxUM+حĢ'v-VN BE$T)&9YD8f6Oy%pa3%&p5cSc[2ݥUὝ46!"2N9gtn][ % aZ[e_eZ AXD((vy8^DF)^fb Ik8F"&;q.$k`ijbHѨ ј]lfO~1[\ :!`rnl~cE`J:I^E%S&hjI7&)5iVv^yҧY,C XZJ*>(WUi}2e'b&j睓FdN\c%hpȤ/Nh eӣNjO ܣ.%JjqQi]qĥHn&H2?i8aFz˗)Yhm!}8Ǡ~ެߘJgfP:>R:V*NDzb ]XTAh)k}.MN=Q@iTvU&gNlkdjBY^\ڊV'l(PER,N+PU0\hd#:Hr0ȖND|+5 X+ƺ&]F JRژ }Xdv*e&PcfldaVlzm]uIpʈ@*Fޟ}Wk"&lԻv^,mf& GQ6(bm:㚄mm~mn6mٞm^j6EZ˭b(Ձhª[ܙhҪ0䊗f,cn24.,kĒ.sA7(nꪮ ZJboNȜR{ijZ- n$.Fԍπie"ѓjQ !l}u bmvh1'ro4:0a2Mߐݏ6@ܭV00.ZoJM>`RU>] pG}KcHKd:,~`8]WE,hG2lj(MZHPBcX6Z^9! U%! T!8'Qj&e2~e(qy%v&-Jk>.n ӧ+fdhq/jx 1Z өQo0{oZq0d,vS|/nf p305J!Z!~*Q!:+)<["!:@O:Jɳ̲nD1H.-Fw("yrZd8_Lsϒ;3kkbXNj6+k{Wut?[p<֍Sp0?c#wXG4n(@*1NZ I+a+乹I5tF -B/qV/J{WOusm y"% _4U#XΛkjhp /Xq]o%4.%XuWq'"Iυ4-M>wG1*NiP]Вgvbq~7Bei6+prqTBuq]1seksIpM_Bq34N\S1u u+n|7LwxCs23{d6ߺw}{v7 Tߌ399#[r p($n3f7($h(o'J)#He"'eJ9,Uk-0*y6uvji[Ɗyv3w7 Hj&79u 61/[14 Ocw;!hd{:bT? n7`lCHyt\{ϺU0ꪖ#5ӢiDS@*51s+G'1OVPхjt`UPi&A|1'kة9ի:k"L+Re<~,%.i1V' ia fб)`[\񔲯aXq m033J7J? 昝lIZP2RJzT*mlHխRCQU|pіDAnv/ƩlFelX Kh-/|A[Mʔ(JB2!B*zu(W('&5<_-}oJvsӆSժ} .97")Q@9S6 beۡKыd [A,2KB..VJ olк-)nxRwzy+'-AWlV(# mlSV)UFs~q/R5WIl0<諺aVXikk$ؽ11O0úf3ףZ[O٫LDjˁFP|%>@]nwzY$F1)νYe|wM- 7T\lfVg=Rk-J,^C ȅDo0]SڤqiepYNJt[6LțDhdY0_Ls%h /?p1r8]":AenwxK3'|mri<+oܭr 2QGaM`ަ%l~f|•Yѳ|FIzܲXo%!QG+95O9Bt=d͕s9GwIxwt0$(O20DJVJʯ(Dp[H c f* %$S(pGp$P '${0w\0L4j I$d mVvæ1)&Lc(r y% u@[X1" .PI{*o J" ТJq$Mo Q (R38* x@, ^*WCe$n+C :I8+̱ҋCD, MP&%((~ 2. 2J!Ŋqrr!C1q"'/0bR?fP묒YA.q%(Kq,ck.&'t ܍('/}equH%/S$2$"+DRDV.q$FeBв*㐛 iPeɰg6.S/r(5jLs(aB~39 64*Ce=3(А#73.Gm+(SSS-LqaS&Ҕ&`h617k'n0(Wq71Q$騱%NQ+.Bq5ͮBS51@ǾBOIΑ+Y=iۺm|fM-?mq?2ﰂ-'a ,cC STR+tAS#%[#A+)Ɯ۔ĿfKj4X;+,a]Wյ}EfUܑ;={E$|7 9#D^Y* ̋q6anx.$}Ju~9C-ȅXu7y靅[~߉7U?i>pcF[j#Çt ._Y՛$끷.?!fO$l]?0[[|_]6SU>|iF>EX IE<8U~z + H@aCWdɢ Ç3jl@-HbeI PXcG'1Id̛/􈳧FO@ J4h8*]ʴӧPJJիXFɧׯ`J!$ZSZ@0b$w&dKD*'/|˷ p_)7L2IY"^^(rs+)Y4$)^)f;߭mnҷ^7u9УI0D wZËTI,T@I ;]BkɁ*`v}NIsF!)#Aʸ@iTbTGuP Mf,}*iRJ/m*c/{}YiY+٪_*]1*dII8lrfI'1˭G*I:KjK`ժt*l`k9 zr{0P*?s.h 7@D 7,@e0}KG_^qZg' HlZ ʣ;rAKHv٨geF2 Lgŷ"]ZR9Bcdde7lMZfvMzZ\M}l/& GC{ǯ'S8yNn#g )HƟKiv$ph! ˼r+v^p%;BvVԣ j8h|b\e!4`X][{[d6ro|A,$"|fWA(F%n18RN :~A(0&bn\x&ܕIžV9hD-yDaA9C Pe! )b!QeP5$"k:2:H ,W i+W#r %@^N=@ $'g xi8sM =-TQ3$.hZO*Ø̌TdAUfX4:C{fCLjRp#I]3VU:e*z/|ܖ,r&_z 6"oNZQ>cҪ#HNKCLv$='Bie!j4r`Y^; 9I(/CȥI(ofD&ug%JGCJֲ)#$HAXT@Vzٌ6l T;T,iҷX$Q^8QbԠ%:AM(ɹ 1k^U5^gMj˚V6 \B&=Ll*CV5Zat#܀ƧlʖQ-pj"*AlaUsڊRYkMoZ[ޘhm;;z.b__K"~{Rꓹ͍ ]N Q.ىNn)*uו9UG<0&n+~6gȸ[ԝ3]x\ r^ք~â h밃>`o̗kYdSsS"?v$hf3e` P>dʠh%oUφq;^w3LN/;3EL90(QdL9a٣ %t,n1f5T4P:Nvq9dDB?>!b%h6L%;L.,͕*d_|~)!tQzru?Cz?HW'd'}&Gkmbv|w\f'l1rxšB|,,WxbsJ/A~3eYAO>i?/h}#8%G^meL(H9/7vzdEÅ8&J!AGgbafɁjaցa!TCXSvy wMz W&G"sZI@ƃ-Xf{IhiKo4&#3MIGMDzrT{C)L|l(bAyqa?d!xTbc (*r}hF[XY$CWh1wg^^(tèG ČI@*TlyP `l^h܈uhɈGyyxh5CS*r ^ m3VfU !Vq\AEYDHBٍ}Wܷ95X))Yx}8GsՉB^&`Q4IVŨ=i|;~VpySn"s}+Vsق#+I+>KcYnp26qRX9󕉙z x9In'$ 9t"ًY0i(&i:儙**ɇٜùQx^ qOsV2j={BYV᝽s5 ViEx?٠R|5Y{:i*z :& j^U(zNj(mGsџ!l%*}5zmD(&Ȣ碴2ڐ&rYɔH@B*D|F Qzb3yj ]jVV𙥧ğZ^֕wgrjjz "{ZeZ}@ 'BZ7!( w'AAz~*¤b Z e'$L|jJi!R*IʇJnSaQpJ:[zBtJ;%Škz((@Uzp`fv"kML߁jW {jDLk6Aa "K`Ѯq;20Pk#&od 1Vziuvf$(ncxGk% *'> !,)0)/Kd?-˺iޛMYpӺ LFQxL#p7٦w,(GaAe~ +,ٿ7ǃ<7%Ȕ<J[b\|b|.= u*+ʪI빈,ʨ5ʟyeʳ @E}\Ȝ{\t bwy3+U{͌ԙ\ĉ\||_¬A\"W<#b%Ώ˻Ȁk'wE_JlV ϿeKkZ̄Ѳw%_ 1[ +3ܞ *W4g2i߱'`DUد! (Fnp@ԇHEv]ϜmBy?oF&ڶ&|gt+#:K\zb0Q_\\q[s, ѮچZˆN9m Zl. ڤ,aFK[I؍3{7Ỷ8Y7qکmڌ&~Hԝ$Wk'! k+`ґqd?݀ko2ڮeUBMXొ=G-VtaFe<( jZho'4|vfؾv$~E'q~j% <W<:qťŵLqӷR<)^lzLn&># MAg\u,jE&a8~8 gMTЩ%7Ef|݈Q7IMMd:cD3Iݿ{~~~Ρjhn nvNR]bq醑!$EI۷ w'O.u>6yIނmM*_A|a!D )\eek .ՎH~~Ȟ>jnp ?_GΥ.Mn ok2?4_68:<>@BoB!:aQq g\XZ\^`__tr*!?C5 y$'bz|~dO;fϖI]`;ԸW_3@_[n96a_^iyt챟ωo `?_.G_q^ϫq正o#O ޼Ԛr9TяI@ DPBQD-^ĘQF1>H,IuLSL5mL =-DShE!?E2hRMg^x5*^źÆ]~VXer͚)HKZx<\nɤ&~A =!ðYA ^`dzϬ 0C n?c-d*$ks2 Q #!2HobZ` %"a(JG :mc06'4v;ӷ4;hSR5O+S-@2~$-TOBTVF/XcՒ*-ReQ55Zބ*kau($bHd]=Lƅ`Xy$m5b0g_ZeS]Vs7-b54"]=Q:Hׁ9Rjg4iUa$>Ng5J'\YN[ĵ7j{qt =1~(6Q$ 'IN=jsRl*'jOko0/t>=ZwdGNmgͽsߵvx/JþM49e;yR>Ɲ/tS>ʼoR99!$g^d"7a maE8BЄ'Da UBЅ/ /Yu0p25Nk !d nx0E*VъWbE.vы_c8,^5 3#ab&!e~SV7? n&[1HBҐDd"HF6ґd$%9Eq[hĊIQMuOU(hTqT}c;"6e,e9KZҒU4iJ^˓c%Vp'#}J<*H qe49MjV].Kјyc`I9+N^Y M<39OzӞenVěM8NRL5S1( +`!x2VDjE_{>OwgXЫ4K4udnN^:s +$FTJNt '6:L)jNJ RP#%ժf% Zֵa(}J҉^ OJ8gLmo> *H`ԫnf ƒ 1ԧ:B |@U@hPЎVSwT4mm#ͭm 9(r AAvau.s]>֝.\%WU"vlޥ3H8J{Kb[AJwIT%q CWbH \Wb`@>جr piawv\1H7x=cto9s@N}̋{)v)N+B~*AT>݌kRvֵ!%?)WDWw8=G~/~~} {>q:Q~hH~?|̓t?o a1Y_ǿIߦSd<ЃÉˊ:22m:: S#:4v# Cx)3H=Q{SW@$"(sK$d7  t|ѷ ڤ~̨۳ʻC DCGB1!B<5) * +l ,DQmIks+3%BR++E(F* 3b;+Hl*5̒67d9, :( <<٩}k#/,@̵'[ ;F5-:ʬF[-_t-rIҨp-DJ./eT{ʋ Iɔ(?<ɷXǝYɚh XT%r52˻~=TŎk 6|$ʼn)L6h,dH k6 c9& ˒{,K8˾IKX{S?Kg8ȇ/döͣ:WbJ4<S9lS+tH49ȯL$lМ”Ҝ|/'Er;,:;7zh;]lK3FϿK2/Ϻ<[4POt<αΑH?PwtSCz|{h4$D$QkNP uQNiE.X=A4E }Mѣ!IM!χZ#Bx2y+ !M"!$ l!әvB>8?-./ӬӮYӒ0ӷpK>N@)E*-+F@:;<ӫ!ԑӫPMq͚\5QG5U[QԌJmK/}CEΙ2,S(XijBrrP+3a  6ὠܷe`F_^ a<]f ]efrk[\ ]&>^2+rXbFN,"x,gzfm}9brIIr&3bHvT{ |"6V:c[.Dc}6i9EPiL畮q\& 5däh^^U!;ie6hPQ&ᑨ;h`ꪦlF_LFfOF%͝bV0&.v뤽Mks>.Q*b6nokˎF^~ 9NfnhkͦFNmYƉxanmnymglcFgm0"("kt-nfd"dV> Von0mP(#?:Rd n ]WVXV>+HFo,Uo`omˎoS~opKn8~7̖*hf̬6[OW׈&b`d Ǎv~3J*QO q;gf΍"_^h]zr r&/Ԇ,~fr1(͒*/q >pf h/me og(r (W5hUuss^Ǘ$ՎOD+/,!t@.TtfgvGghuM_k?+bLjn =qq_r73Jwy{v`c(@ *M~7hiLjndw fXW_`%O?VZjLOVDB֨JV)eyg^K xxB/t 7Mf0gw>5yʘqҥ0,psҺR~׃ײi}FŒF E֠'2FUOSFRGvXW^Ӌz;)w2i(Hdȴ6".{hX{e17ٓ˭H*U\ |Nw|/g=|J2t|+]ڝOld4ˤ(~]thCBkwmG*KLſ,RGc|ϭ[0?7c@K,h „Pp 2 "ƌ7r#ȇ_i2cņ/TOMW(8vQٺw>:dAҴ9Ńq*3ǘ:ڷs)Vv1M93fGb ,b"RH.S@{M\  `~-&b [%&b=ȕ@eN (Pj܉kDH[HQt݈-ho/K.q$t2:ĢA 9dGށxW*$QJ9%Hv%ubl[X9fB개ǵr5EDD9&yhdxU]U]8`z(uiI4cXL-"t㜖i*g$(:+ԣab"H_z+a:4!7>O@5묮,vGՑ޽J+zk)N &5,vhR|:dNrJ]Ӫᆲ < 广G2W썞,T*ު/!/|2)[fk+-,I-ʄi|3XnWeDl@/26hZ|X= RMi -(g/v'P-@˶iT<р;.T%Y [dF5>9Y$vA狝W^裧^(V!f[~yv?^P;c{,CBWw7䕗%#[u-L]yf祅fe٧;g{sely;R秳t0b' moVbFS I8+gwb @oW2H@j n(zT}w21) OآG+c + 4LKiPB,[;2 fBIA2Dfauz!H)iG B@я,Z(-E-& tיdlc#h8JnyZH;VGV )%!ZSvE̘|C8ɳ%3#Zږ!NC]PA l\a CRO66B1h|-Ko/3;rE9C"C?#:i^|f%*^p C#:ġ!HIQa6FQx" )HzA> 94IJj/Dĥ)Py9ӛR9NwӇ4jAӿ&%ֽԇAի~jUjѫ-٪C< R**=˟FYںU]fWU!z]Hs6dEBIK_cZEi 4A8ValB.{! '=R #IdK ƞjju7Z%i!)6-0g2&6#3 oZ@ :دJ7d`4'EZ 8I.v$Vj.^KH7:Dv# 3jnPk a\-  >p%/E+%pSH op^](eeJMKS V.5(FRf..]\r;d(z/HMIg(Z<LQ.nD5j [}vJ_ӣXg=2y~(틿y9!NYZė/&w}/=hktkOˬYBJon@ )`4 .èMnO}L_Kc=i qxI`5ށDuX-XDU J4VW| & "FՑ`ka!*LUS 5O g˅a12<'uXK,l!oap!  \1[!F!K"~" աPR"H"oX`b&I2{tb}bGb6Eb"i+r_=b.>]b!O Rq2,J 6BcH4b55KPaQ896,㈰c;6//v0pYa1b݋8H9?I@ $wdAVAZKBrB[7v`_C\_oT6KF Gvv}dF9g%W5EIFdv$^Nyؤ$F𤄙I*% %hQ2 T4E-RU;Wљ{}ؔ[S، @eHeFK 4`1$ZE$z%Gp(WƓ5yzfXH{LHzhh|ٔ7NQ!Gij&QEY\iv^ _b_:f7^e+ bbofcq>fkl"V0ag "V\(EumRkESaNxfxቹzc 2$#fn.E$'(s6\igf\f|fap'7q aǃP}`p`c<ŅELVqDT2dEshբd4*]T%ҷI aN)a|֒|6ccA8_L>Ջ@)I‡ԈAXgJz:ipb,%\.őƩzU Ƙ֧CbHHRikFU瀄=hfyx.(xiS8-Hh:971녜S=ejlCh$RdS*k*S*jR:cI+PBX&1$솷?)[kbǹk\kBkfQݨ 'ᨌkkb9lBzSN2a.WkSHRXBfNRnW b_߹lƿ֬M ,BPݘ)p* I^mH$Jf*-0m8B,)lbePцD(צ& &H]|H}X f([9jנSenTڐx &lѶZ틼-P-HmĂnTdK(&y&7q&dPX&9e((\Y6Xx /6 >>@,m2Qlin"Ej}hutf\oiL<{ٙY&,oMȚ žb ^oB&j](Z 0 V\(z(Tr.OJonHV7.FPL0&x>l&iwg8^lѡPǔRj+o pIZ~&ppYqA<0q$m jkiu>砶dmM%Q8 V+5Rs1!*DԦa\b#7ʓ J{*~H{gG:Q1nr(ʳ&| 0|-հ}I~!@1$]pL%% D&g➼a3.0b2377Ϡj88I9 9XEB*Xs>3={D>34pUf%D_6CGD-QjY4`G]Dl43*MJ{d c33nt# ߍBg8M;̮NMt]tG55mL#R EJ5\uQ6Z2M[uؤCZO@ZwűSwaDaNaTGu4MdGdO6eWe_6fgfo6gwg6h[J KqR/Lcr5lu?:D CD P]s?4C\mlWM:vAZ6s fCx2HӴ4ATu_7vgvo7www7xx7y7w6}0jUP3kmH0' ȃ|@c@77A@pD 6__gs`^,w0s4Igo8w8wDv5ܸ<\\v~[6:so!#{<ɗ7v<>WE_; BCo=9f'>΋~VI]{g똸>>/~v~^5LqTr?@?q>{>;?v@e[L0y{S׿ӓup 5W>@8`A&TaC!F 1fF8Ȏ%QTeK=ŔFfM7qԹgO?:M^&Uj&AKjy/zfFǾDxywε,zsǿ P =ʽ lP>< 1?92|@˨= 1C9p4 1LQIql D1: y\ e,IlQ)ɂ|LȆ8!\Ѣђl 'x,35*J*'+r. 'Kd>:25K'B5P?M91ʹ&:״S.<%sA&(J%KNjCMttUG_EH!JЌd]4MVM O5"QQ.k*%lZ)m[Zm57]%פM ؇ur:e͔0U^jރU` 6]ru@[gU 5_%]XߓʀgaYiRq٘Y矁ZhnT~硙n駡^裩qgZ뭹kZlԒv2N[ {췫f t!&!]RkQx/\#wm;(G;Ნ4q #G݆[vfSbBȰnޜ)iӃϨMJ~$agvDw!y@}1^}甛f02n{K7 0{kI"1qd2]KYPi(XaF5B$!!Q15tf?Le Є,l]h8!>P:HbAnp۠ :NsZbCJ|Z'r3D ᘗڭ); L_D خ(q%XDHh np(aP#왏sRDI2ZZdH 60DoЭ!dxh)dTB ^ e1~ĥ0 d%2<+ CI.JG#t Bvv-%tXz3d!m< JxG XŲ[W^OfC $&ǀhe@;0g9Y F>2Ւ% o4L؁@Fgf 5^+yiVsfjGoAF26ss <)<-jYϚB3 pk]׽la6l]Pf:XkiOs+q4\Aa5 !,w 22KK&}}>d / ݬCdݝ>ݭC _  &`\]OAB"ثCF&ݭD\Ր.HЦCP.B"_W.dgB ) a}+۝>ԏ-by&ye\7g .a\73},.Z`؛>(@`"(\ȰÇ#JHŋ3jȱG"<ɓ(S\ɲ%ƐtI͛8s^)Sϟ@ HaIH*]CPJPSXjiuׯ`?v KYcϪ]5-۷pKιv]w߿L8ˆNƐ>Lʘ^Π~MҨNְoMڸQͻ1N|^MɟC/.}z{cϞ{;޿/5ϣ/~};Ïy>Gί1`a8X:\!Ƞ^>(قRGa]vn]bHy&^*b|2X_6cȣ>`BHdKaS= eTRNTV*e)e\[~Tbek&WgYnf5IKvRzg hV*FhT.蕎>evYi^^zQViQ O Q**[PZk먻kjVZ>,&ڬ-Yޙ-٭߮.Y~.fٮN/6Y"o pXØp q{XcqK3r#X'r+}/s|3Wz7sy;w?stvC[WtGCtJA]NFu|]uJR#׵[5qcg6Xe6g{u͛vwэ"-ނ[8mXK8lK@CՀ3/yJ}NzR9p~PNyNھ:.>N1!Of2O*+ϙ7:S:ZϦ8qO=/@o?u_9Fa$ # `$ c_$ B 07 NȁaD'v*0ؔ 5p+T`x*! `PP":a CIQVSQLl~Xd%fŊX:0W=Q` _ê'@ҨFn,M`W4: hj_NX y3^ea5YUV`%Xf qj5]hEȦiղڳM}mYd+'ڳfls;O jy[M׸Z؈K1Z̹D.V6j̺îǴ 2̻$ċ2̼,C 3̽43̾<ï 4 ͿD4+LU6O^ U k„Bp4<5 7I@\TSČnr95Mu1dl6/j1l`uq7"NFr8&+N%v2䤌" Ŏ ;(_˹O(1̦soL-DSK=)B/t$RJ'ӖIA-;KOZCD=RR տ3uU?YcGa}<\Fy?.h5@uaMi/TwOy]WC}$4.YPs8!?;1n5!w~Z#yIZUa>[Cy qn>s9|({zun=;G ġaOXa;:77՞bh}b7},wsHvw]#[ˌ>}]/щJ*.p `u1 k % `-,XK( p0/6 F #KL˘3k̹ϠCMӨS^ͺװc˞M۸`z 4A XqOPmգ.]l 0~=g?6_/~v﷗]@uA'A`n!,%%22    >?I곴ɼHA \Ȱ!:p3xQF;~)ȑCĈI,[TYAL_pC&s ͗ JP.h Z"Zr Y8 `D@@ @yX_†#6L0xCv,w2e/ͬ'K?Yoʎ:1ʼna/ !,22 >?IGHS &&2))501; 곴++7𑒕?@J00<[\f` ‡4| ˆ (hq F4"ر E$ɐYZtR4H fNd)  DKOxIE8 Vf=@e9 ,@(K ` `A7+D@ ȁ;}$ʉ!,)22>>I  00;H*\ȰÇ#JHŋ3jȱǏ CIɓ X9˗0cʜI͛8s3fJѣH*]ʴ)ӟA[:JիXjP`ÊKٳKJE˶۷pʵj@j<0߿ <x~(_#KLLÇGرϠC TTgҰc˞MO׸sέ ?i]+YxУKAyvf>+]5ӫ_Ͼld/?_-&&DnF` f, @(∿(,"e&a h84@fc=iH5I63-Y#TViF& \veC di(Up)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgQ4L)3⒧RPS5EQKԦ=MSSNR[Y-0TYiS`=j.!,22xx'xxbxyxxfvvˋDDiiBB88XX//QQVV 33cc艉-u~(p40 bb1&"" ,V̘рPY0ADD,[ S SY`gO31>`0CN2(p4mz)%L'S (dt DC!,I22O;YsPeuxxxx{HyEdsxy̎uEnvvxx=>P̢|Pdv̡|ttzf z6,@OˍuEnXXE$$DDiiNy-\~unju3oowFx@BBx 88kk//HQQPqq"lPVV::EE^uOctE@33u+x߶ M|*c|,y .W,cόA'm`ӀQU]taǕZhq-Ia Y ċt b#y} |WpлNF/O }-?^_~*! @}4€GSZotO brWaT8W..V@Ѩ](X+6c9Y#Cdq|_?nbKRe<~F%YUyQeBh$SY&a9Zuyi'm&9yz{臈igRvꨨ訧**rª\UP!۔YպڭjA;Rb[qۂ;{ۮ{⻛򛯿b1G!l<2C\0K<, k\,{|,,,#@MoW?J?Og0@=u h&1oZ0zv. X`(z0Dg¦^GAoI; A@vgy.+[#򘂳9Dv_L"v3#9p&W!OqqF7Mo6g+s ,u̒!d42N̓'d(9IQ. De%s]т+]-Y֒e.q.]e0Y/a2f20e6sf4Y1iVSe)9JS.7X5IpiDg&pDЇ$00GvT'h@V"Hn0@ h_P'V$9pS(N h=!"`ʓ1,eH;O49}MOTu]gR7ym6O%Ry:UVQPJӛ(AVuzUgVɚU]Wȸdp \*Vօ{\Uwlb k3xQc;XV]k^5{XֲbAY̴!iUZNֵ=Se UJ6-Xa{Y eo}K5ܞStU+r76 sG uӀ+]sol'Eok\Wu݋]嚷P]{]noD Ez*/%,`['<`&r0S%C.źBqnaJ2p9la/Xǵ,|K"ȿD0|L&/τ4|M*qybC;VqRVN',f9k2B3A DWPEt ԆC_@qv }H&4ی;Yt9iO[aִI}jSK bekU֥5{5[kTyسFvMleﺽNvfV~6O;r.6}kSVE7V M{^Myۛwouh5~_Em go ':Ÿs5^`c-fxmfY$6Ukve^p1yK~q79|FO:ϗ~\MʥrCz~d'K{dGSF{~ejvnmc[?vs5tFeƗ9Lz>Vp`F ]?4֌8=AX¦L0}C\ƽU 2L "HF$*$ YL@!,'22;YsOPeuxxxxU{HTy~xyEnEd̎us,,̡|vvxxzIwf=> zn Pdvttr ''̢|65,@OXXHy^S~ gy$$Niiy~uDD3oo@AmFxBB| 88̢{EnEkk//Od.\QQP-cqqlP"VVQߛHx EE::Pu@|sEOct33@@cc̡{''GyEy ^.cˡ{PcdQ m DnOdtCccc|~v{CnHFyx =j~ {Qwˡ|++H-@ODnf~JsƋuߛGySXYxzeGx#HTUǠ{z@`$QT)K eҬR˓w6gAB eR=tTRV ֨XRzêVIZ 6 \ONVѱyśT_=[WaB g\dĕf7@.fe;%j4UZcΥ=YfI︞zPON*a0_/ڜHySwNahwȏ;`?#}ONȐ_g& S4b)1(6 P\l922|l !l'n*"t&7/8oX8#qR$F@,@Fzڬ\+.V(AK:z.[.fꭴ&/~/>Hooˮ֛PuS1B<W,"Kܮsðr̯ ',71.|93=CsAK=ESMsQ=0r5Mws64p[tr-Շg]xՉ޸h2vSiO^vo[N8݆9錛cWǒ}ẘ~u_L.K<4YQT|CP`{dxA$7kϽ S (@]Cg`!A2oh@?)`L\IЀA$)dBp+@ =0g R0{xoD4 D.` E԰<`DrТ6NЍf<#/ c xJ0P,b q( qM@dDqG!*҄3ۧDJ`C|q(Ul!H)0k=Q&7En KqP=sz;3w+V7օ3uD7Npr݄53g;xM<9ru;g7|B}Cg@w7PnSDh?Pq.ԟUhFQg6AF;m֓>Mz,""K0`P^*`MTa - DmjJY %HRQRA`L pUFkTK)O\C@'5_G# VJm (6i)DX@e @# B"!@ A"Z4D!k0щ'z+f IP>%hЃsmRwJ p-Q.Jgjjq]xV6J!^f蝯ekю24/I^ ~x&//ؼMpg =W p' SuqaU[X/ML\1{y/Ϋ:y|ߓ?oh܏?7wwJHePkx8/`u09 ~`u&Ȁ (,vHb0vpilTj!,22OPeu;Ys U~TEn̎uEds̡|z̢|z ,,PdvwEnfP''~  P,@OODn hg.c6سyQ )-\CcƟ{~v| FxEǭsc"yOctsn HH?oy̡{Gyˌu?P`IEy yyNtI Hi\SN{)dM=}3PE_iԣSeV Ju)R^ܚcX]zjZkǶVۺpʵKwo޾$ɂ[VpOs:B86*nS?x`kOK  ȮR غ(QNjt|(;j3wZW;u({~{Y<鍆ɏ[>zX~o>kL~ x 8 A9 }7! w W*!"#X"'BX4/x!+"9!CX$Gʘ"A2KYRQ9YU"ye>eBnybf$dxfR%VI%ms©Xo٧w瞀)(ahuzfj(Z*馤~饦Zh*z* kzꨳkö l*kJK:{6뭰݂2+nՅ ͻ`CƅQha$\Z/<LJC 0+pOL_u\-PAXp* Trs2;4یsLs> B]OҿO]U=X˥:}b{rsQ ` TPĝ )F U ,@ PQyxH^n0rޥ :>zꛫ:띻;^;n{;C;?/ +y=@0~lqw+`ApwsG $ʍ@ "°XvPA [qA ʐ L`#pT(`A\C"+`"A @P` AY Cʠ2b WYؖ@DġV5E)OxC8;.΋"h,b3XF4*pbbUюdcuG>я{ݨ9g4H:"rl" CN2\#/ INJ2$(1)RZrD'MS2e+g KZR-mWR/L^R19HO6Se2LeFդ5 HnӚtf89Nifs<:rb:MA| <`X J7@4`1L`qB5I:04 'A@T(tZ'V>S-T,Vҗ6XS@թs5F=Ӡ&UM*M:SRuGTԪfթ^UjTJαWX:ծbunU+ZV՜RysYV aXUkb+YF;.v_-\)Y6f=ZֳUea;Z~ֵiM;Yƶmoy;[VU CKlH=uo;:k XJ8 B!,11111111111111111111111100,,,,,,++++**((''''%%lfeeef&f0 _PWoOGDBB8DFCBEEDqF@xX%~f pjgia_\O_@e.gij]KB 4% ..103/>!VWeu.=>85557Em m m m m n u~~~~~ ~ ~ ~ ~ } ~ x iVTTTTTSSQPNJIIOaji]QPPOKR?dDiPtdfUK:"!"(͕>ϑAБBђCטJֵbklmhʊϐБӒŖĻtmhNFCA0plH*\ȰÇ#JHŋ3jȱǏ CIFR\ɲ˗0c4I͛8sɳϟhJ#>*]ӧPD)իXjʵׯ`\R($L]˶ԖʝKݻxu˷߿ Hٌi^X,ՕJ< Ƙ3ȏR͠'FtD k:|R-װi>Vۗ-͛礼]:iW{8R!oh"yN XRqĈECL5t!!.<\'`Hb qAk ( e8BX"#I;vT]6d}YYG2)GKPPZ Yc3T! D&Gj>e(fgǖ"9$\o^Tgc}LI@VI*BRِR(١VB:jN*rnfަ ѧVVV^d~ -KGJ+_E-c $b*{&/zB*~#vFnOVM{KR.n+9 1PP/t # p1b<kȕܰS1"3CIViisAZܚW,r"=Rנ93e;lf+4ΪLPѹ4#oQ,O:.ˤᙉ=de)ڎ'mWIAB@s|%%ԈӟqCvE"ԯ)u)FsgSŕ+T+Ј dq^>wjkf1[qWոrBN@t1k/84w;/ySԿ # w8 |kI601t;`BD1$-KΗq0JN.g1KncJ@&8"RWĪ"[*h2T2L4pCLIǐ  d"L܌B+xP)KE7%d2&Vǔ| F o|Hтe*i' )*s lI3L%AHFR4,`PI8۩n|5@q.7*bm ANAvtw-,+e/"OIG%m%1\!K& ̝7.T> Hv@s!Iu/N+yUW夸VAE GPe'n^ITkIv{!}<pz$˜1O : svj|ve%HBk_X6i@/S^'ZUO4nub}zCehI_Iy8fdYG;z_ EvcEN)V%Q{CvPyW4A=F/6c4<es2#4?m&/$wy h |×aVoTcwo+[1TdbtU}*x?h\cvQSzEvÆS @wQ] dbFD\xcEXG$Ebvq v2&x^qړ{7Znr_E1*1G#89gKg7#*%g)XtxڃW33xė@WGoG(B[hl&Ar;q&$' #Q8 (8*&7f#ZLjsQ"18+@/+"S{v{kbty!6_kLDEdG 1G]TWw%Qw0*+;ŋ4" i\]cy&T*rg!y‘{yafOrgw>Za(+%xZh20cY:94KXr4aqt&3™@?Rn˰;`{1!*1IYX6ۻeC 11ື2(H#+-bZ v '|5(XA+KEAX$,1]5,F9l𛵧;kBlD2HFJ QCtS\^zKŎߊ^K}b a!x+/wQ+(*lGwRE|]P %WkUHVȞ L8o ׃ZW Bc:a%=-l2ys|l@nj˅U|T䫉 <;l؋Ɩ<6QCl)ʧRCdlʧ7  {3!*h̎='2CY S{}Զ%]!QP"Rܫ-m-M}O,,\2l LR(ңsU2%H-#9iOHK=48}J=w-Lz>7i+B:-'Nߍ29?N!H57>ݘs-א8ׅ<Cx~2rq^@nsQLrU|1mگ{=k-(^_rsMf>>Q qLmo2'E^X'_̸`鞸(>fB(&8(12??B'N:VyQB'V`qpT8F"Q.$G-mf|CDznAMSCETRI RUTU^ŚUV;K H<',JW2P Sù_Kdχ}Ӣh֔cE<0Tu<2?U[3u /C,/s5`Am@ '~/3&. ?#;Ъ zNܣ1 he~(ne[?7ӊl51}uMvxpMC,s=!ԗ8!^c)(Ro[:DfFSbFgҐC ӷ2je(D|L-ɹP$eɣ)A D$~ }.Ze\D4*??u"c'QIQVӚ!VtS)WCe2< R\X '!y)=D8^IRQ |l67EqDW`'/Qe6n-hF)'x~4D>PU*&B$}p$Z~:o9GmDB K1!VjKoJGM*G9j٣P#)t+iJ7>H8FNLFEj`mT8:ePE qDV*Kڵ|.i fY$Vly:֖ŰZgn+Rk~ `ۺv* j&!lL1Ⱥy !\lY S,Y DzS&-ʕq7[*lԻ-nUB}hEX25e* X\<!ólID:n܄`ܹznm.b־V#[T6-}'9Y^$>"[)n=^⓿p'c7%uLrK֞@%9n?%'F| R39g.ɦfc3(AJ<):8iU_UIj iDe.&jnL} slfN -ߒ*Q3cEVpFމuixحZIJօ[b3^9f6*t[ilMuY…qn_^U1CBf09kk$"H(w/¾dJ ?CȂՌlg#EF8 5[Vy9ΨjqHRCݠ Kڑ7@;"}Ϋj4p0ٛNxΫ 1|1L*!n!!k!&Tk$pek9.A m>펡F/{ngg xnK~]ZTѪ:Ij˓)y {a!vj)TǚAjWV4MOw{1ȏ-_?tGNoy}$@9;ϋWS)V} #:!SDKt>K\VDw|ɯ{$a}r [jVqS*z Ӭ;:+s~?,.bᾮ>c;hS lJ?V9;% ? @DF;:򶽂[,ċ::ÈA.\AdK=r?H!8Qxg: t,Ÿ{ ̈h $ =; ˽C?,2- `B4WCT-Z+4$>do8 Q0sEpo0LPjEYE[O`0 HFC3;=;*\#;0D׳1ĨčGA۰yS>&*1:zB 8f] VtEXDE{Lo`[\V*HCQ0C:Hf\g4ϑF>45KGFDƌ# |TGKD LA' =|GNEǪLi64 |X"8N8 EO@EJHJelce4͹sOxqcpO;tD ބJT!ZB[Nkt1ED@Hm2 U;cωAuRRL>' aJ(&3, Sh>,MD5/ ,PSy7UdU;#E!iR3L&}SI@Eâ!-UTdTUQBKS&\?6E0 RGQ-=xt04NCҕ{^-[-8\UR0mWY@$S4Vdc eSr-ROPO@.3ЂEdS$OWSd:V76\ ւPƃ4R-qCX{w?C%O4ymS YOԽ(}V̍]Ylٍ?GE՘2c;.S1TDԝR/ XV_KIZA#iڧ]ګI;Y uU4W;RM꒥hTHUe[]-rTRXI[pdSk]C"be܀\mkuR5®ڱ%UT`VpX-]s=ݟ8KمIݬ[: ܪBp]5 @y1[j@ۣHW  A\8$6OͣB_K,_ȍ*aJVUŝ`)ZX}޳eUp` F$V%&6ZvA%uژ߳GjސRŊe+:b&U%;c'vIW_VT_D@Cr3bWF\{56.-[ɵ^`c<P`=>TcՍ،: IbR:d=20 ;U@ZVv.Gtڢ 2(]HүF .#fdNn&hFFhbP덮) ^jlVꤾ)6tfPwV Xhh(^vmmmDm&؞탘hȖfP>NejFs+Nj[4F9 77Sn˒vJ)TnB=k~}nMP>m``|K p?'Fnh ^yx܆mFmfܾE{qqq&O f>'GCtYW#|]d{eQPEvZsoIvkkXzk뵀9v`7h{H}l8$|Flp@Kllpl$p @&qVqOis(jO7Rhք u\'p]#uF66tnCnXrpen489,D !is7Y̙shqcs oO?@#hfjNFw t qnh$S'h^wixqi{xpxqGuk_7XblfivnhVe+noErrٲ s3~4=Ag`@ULN%zy.x֞` gVmgGg?tJp`?Pr@$w|G|y`hx'n>r/u'^O}xWWrh(.DmrW>#vZ^zpDr/)އs{ [Jرwo{'кF~†`ľ)X'PIK`c鞷yfiY6 pɇMA8œA 1`'ЇZ'׿F(Uמ{ Z]jE0TJ5X;͋bȢfӪOU5زg&ʄ/G7‡ hȅ.7ᤝw6g*XJ,{c չ:'?oARPQB!$NG[.)٣Sur xZGhܟxH `jd׵eqہO%\hW봷e5:7:i8%%>=ԸHdlFt?w&:$@AC h_NJg-9҃`T%v9W; w`s|(!Kcuʪ\VҴ+IW]5T χ^ +mq.ib∁>ۨ}H?dhM`9\ `m|<)ÁeĈ)>AgX#b d\Oˉx=0LũSʠ$19 ]D&1TD&VrT_ 28nqsFB|'K? Fq%9q;h{яyrI̞mO"ЎkL$ž3‚*9KNy< BMoR#uPn^WgB-ŷK. S cFt҄I hJ3|ռ5G PS*} Ne-ZJ!9JlZ2A"taacyuj,| ڜlVxĩҗ ڹg*lP1rZnMlAͤ 7}0_Fx=%4S𰤐ZcOɒfoTo.*PsCФZ =q\s3>`uJzc>$b;1>u2"D0g>bks`!ovFivݶGX^ьPyY[z ,E`$eͰ//3l1oQ 4Y:g:?ή`$[@2ΝS+'= 6OFpÊCZ :POk5\u'qC-ք*+ Hɺ,F`3ilFhIlWy<$'j3..wɭq$|P#d;4Ob%vfx'^ ?08 Ç>\_iˌ)n 9.H$i ^`E+\SV:ֳs}^VǙVÄ1tsmdE{VaaaWCQKiKJ{5ma'vަCRgxj:ZT<3s:ovMBԝ~P-ߠ_s }!S_ ]s0߶u@ = JmEeWщwY UT`p_GI_aN)M`!`ᜄ݄a]E˙]K[|eݿ Rgߎ 愊G 'Fʡ( ]j`ܱ# 6}&RIao\FsH %"_Y&!~"3F("4ʞbwbLZ+bp!"ݝdbA p_g :a3cD?F#@JHq_=*hah|Q!>d͗9##~:*dS2F, 4Nc>fDdcfZN F7&!6!Likbn\^&$֜hM2#IRa&$j=r7@qCqf^l¬l?+f*Z',Z))Xz.e"Uh~npHFInTeMi(+bD(qbCR'"쭁)Fjnެ2.LҶA1Jcԫ[v.\(=~htU-ɢc}Vr)j%r%OjA8," w76r/7Tھ/,AF|ɭӬ&~/0e(<BhK+ϞAnAf0O"I,b]/G6`Yq ܑ>TjTp2p1`}{(qmd OѺzx&- n1HgSeW#qw21F%WSEC3 qZ^Gxqߗ`XX*&O{2&^E/*ğIBy.e.MsZֿn-K_aĐ3OTm&.D#?IP<3>>;3m& ˺!4,2C+-=Zt(2j4Bȫbs$l/V"Gl4& jHyVgVo5KwK'18?Kش(X+?Xj,GDבoYGQ[ JW`StL>]qb'b/6,tK^ֳH[YcSR7osN+]M E q0HS_C%KT#&Xec5%T"Ot~h`g75uـne] Pk\#:V¶`[X0U6c6q' WOd(Bqfhvku5U/5x1`^&2=˷ΰ7wy- >t|FLxL hx.j'uE`ó sت nn8ϊw*wqQ/c Aw5T\7:J3S#0׶#FwyIZɑCc}4O6 JPt6oJڢ=O,9dhEq5WLk G/akDl}n,lxl֚^QNHFIEy"Wh[7os;7{0f+u^hy.JڸyEx6a y :lhӄSECFsHt/Z96gsc :rWtu'J";X]?v)9w˟k:#`Ӗ㄃ ֵKQĀlt|QH\#@#[{P?mu~1OS?,㿭Ks:@ 1p&TBЉ3C $x0,`8cQ`BlT93E>hԹ&5?Os,bĶ1Zw)'GñX戅2*U\:=zvz5V`ۖYN$oӇ~5VpB} Vgc۬ss{ yt=Hźd s { DQa'' B: 0,56sJYu7.4e;[R̓赐t`Mb/%P2;<'U;+[gHvfv"otٻ|9}/L=Saӎ= yv)ڔ}MYRόqȳ51${JS|}M6 zPV0gnXb_d#_N&jvIWYb݇P41yd&9fJ)n:9ؔx.'7ahankY?8?lF@g"U.[=h0D$* ^11Ƀ8&s*1$iaȦc7-2h@>\)Xȕ<9xdyER{Bh,MN.!QUm&7/r0Q*N tIGZp$-l co$>rfw,_NyuC% 9 h_TEwMoRfc6jNn239Rǜu)Y=15tLwR%"V\=:Rɉ¤܎9Zqta )Zz(Li@#(NL*,F2gMVu(U9̩:گ~n>Jrb.jҋDbTLo԰#t+ghHQ*_'KDm UөכEeOLWB@?HǷR*].A\~J!*SmTP}ؒ#4$URi4̖gydEBZ"JQ~A!Wۋ) T ޫ A E@d(mn5 VQp[$KRTpr*vTT}͐p zm0Bho;)ʦȦHf%67:ٟe/_v"&"0}kY-"%T=bfCgu=98oOy6fs w_a!$!;4Pw4H]Mvnp6eZHMNfr*-bd{^Kl:Eă8O}9̉uPTg 0BT\GaGY1_ rqCPzj UJwn[a9{SwI!uch9>?rF'HMqk_P:sD #K}Bs(V@r6#C܃\6Cp%0p:CA^,=y88þ4 }$9{݁}v>[1#I3¿vԧ|Ko|] 9z 3Rç/˝Ceɞb.#4/[H:xG"KЄ4Ut6( PDL/JeV/9n-%dpOϖ:f,/#@m;4Ho]cO%Ap(CtOW/(cRlNXPavDhВx I$okSO -n`3z(p C:pIzj pf }ꔨ DCʰp#y"y-дN62qF".P%'=X\.12Q@Ij 'Oo2"i7&l2po`*JjnM# ]JQF1(Ќ-g27QikjH˟QerO!؏.f9nxnz~ oGJ} * M UKr0m2'Q%Iq6J8E""t1B i KЇxq#8T$o%ȢeR% {r$.Mr$8MGx)4H/o6rN.!2 *&%o,fH"nV. R=.ےCL%rzQ)R(t<6u/AFdi!s 1oC#s+uqX"&>ĠRh8633ǐ AH44w,5b( P<2s!`(m5ސ)p7S8Ib y E4.4P2%Rr-P;k2 <1܈C/'wC0kB!N4734b|3b?S  1@ʅ$'['$,?SL!(T<4!j'JW)sPt5KYT&*C 3ԴF_2"dtKR<]HSTs'tP/BLSKKS4:-:"MהMcOÅ2Y2QL"fOFT;-{  uVwQRQJu#D'/.RS7u8/r^tn55`5VV7VU!F =&~ mU%]eSFFu9U9@EZSHH_9h[ջ aB}XDE|Տ(9 є^sSה!s+ZK?(UMU[T[!vgk!x06h5uF$ Bv$uS]dpS45ODDKq:Nlf5/guvg g!VV2ynV2%i;s4qdrHace |5YamMmyE$ cn7pRcYAM3_A#t&ZrO v'r*2$wƘqV?rOt7'cR5wL4Ze7N{VDCyC-9* C$ѾxFxoJ$pMnet'@K"2Ad3*Vˢ@w* EqD/Vp7w!*-(TLJ3P@rQ Beapضm +b7" F9|"YP&j8Qzj+@#hX#\̨=AHA>KJ.W X42_` (,҃raWoFIl(ƖU5"S13 G7p6*/0l+EA!QT#Ѣ x5qr?yӑzXqUqIBRA8q p0Y4|KXq#Pry9Rf8Tyٸ;B큖"!M$EsqW15r$DX&☑#*@a0VZ=5`6eM9,*/ƙ;Be @8R B- y0sϵ{] 9 q#yz$\ڇz4NDٚ(hbz-L+Oţ- [Ha& ,rJ7bADҐL-—Y 4ִo9Tf zp}W%ourNs-BvM "逑GuY{Nʋ{&!$a1[ڦsY(I"iE;E[efnZZqڃ(+X|tQ+uk+(}{a6pZ38[{e蹡N{"O1Qλ @Uk\_+q#ץ+Nl;w ȹ&Gz778`_Z|wխ.gUIy % UwOיڹkRhׅ >Y}P ͪ" -I0ҡVf!yE}ˁۭT; #Aյ}O:b9`zߣۂBxS >YVzS š-~11t\5 ۿۼ|g^<>獾p=IiMyUÇcW'~D /?i˻ )ȿ1PDǹrܼ' ƀ SSksaDIm &iTBג BBex }k--Tc٧/[[gox;?`  t. l |$bɀ8X0„:|1ĉ+N$Ɛō 1jpǍoƘS0ȕ Cd4OѼIs,b<9dX(%zOEA z)(OHc.w2cRyX!4e͜;C4/` 13ꈄ*덏*ͱݼnߎqs\A[2oNP&N8oh]8xr*(@mT5G;Aymwli?ܗiԁQ7ZP '\b4yFcc܂NH!AQ'Fqi l="JնVa\* cF7"t3 'MU7u8UWQD P^S(0C$}EVka _[oE'=6Sa&'!g$!m޹مNC|'K4hx[+g٘rVqQjYJ)UF5? dWL ETdVVZnq)iE:f Sk}yci)lePHmGۂ)IK(ў#ٻY5N0$QOWHSPIwkXu[zV`6@ >@_a9uf%mxZ2CՔhυ^\d&I!AJ`R J `8|ձ,Y'KNxbDgR3!j ~9L(P0?Lp tbϭ<ڙd 3#PSDSc 3 ǔU"N"|֞݌|U1Gq龊\ &kb7S ;{9S,Vt7aY[$(xڬ v6)ӢKAPi#݊Ӈ(9щa`D=B$얭* 1?DK4 d7s\1ﲩcD[Kt\f]B 1ʙ`lV;Z i;{c&)ݯ|.A.揙 DMl2`q %$ G8ٸ( "PCO + a瑹Q>s'eB"e193qB0j걏cj+!eY;`:Q2#PJF<5^37Caiۥ)NMi嚠/vn޻Q?`P4A:b!Kos荔,>@X\uҗiWM{^L]x;".el/K!JW_`z_V92Mz mliS1̓9M#{d?%NN[L n9jt׺&%xXf3 9 CfL0ZOT]2XLL}kzXȼ|-9Z\q7ԁg3]0*^躞PG&}$csJuU\7sA7 DHw:MS"<\)`/^5z~5۵CWZwdguāpaqy\u#SS8@I,(Le'mPcp)Rjyzi4):~=WwW]vv6^"PA}Fxx| &(KlQHyTȈaw|7zfMfq(vg{V<4PyNC|@|b /t"4؈qR\wPыbj|@Mz%>JF{!P}W-"2ue^#DxA]2z6`1SR]BǨVpGtψ'\h-~1ׂLB5_&5x8Ah>EݷY~DqI:^6a_Vq5W&#WÂdMWW~d]g8m25 (V@  ~5w`sfjțYw ]z_9ʜJ"6k *>u^Qh' +,h )i,3JҞiZZ!=:^~pQHRjs]JUVnU}`|uTeژ$CI1* 2kR m12+1ᆝ֧7r%IA_!UJ"Y Zv{UxB;ytbD>JA#jKx%r(Zw;"z EڭjYN׍5^{Xۗ,qZ!1YȮ(J'Gjq]z.25HTmlki9E\ Z>YD9U 6y jd'lYU'k6){+ 3گCHųKƭJ5^>Sz ndV{#S?˪#]뵷*: f;'in|OG<;պ5h Q jmN7z@c镶A\k  z!a :z᢮?{::%/ٺ};䊣'R a"{IKۈǛ5;!Ǔ{˶dHh8J{ C I㭤;);S3u/3"۪hl(,Ѳ.˯tkw><۳m饪BRbSKfL9|; LT#:¾tQ`9+A[vv pkp?ΫWbKỷ$R|A0?Ihkl_h 9/Usc|i,E;\9kʺz|R ːHLw{ܫCCy+{}# A2(v.5bz^i9 iYh ϽWLs,J Zv;ӴP\u4 $]Z *8:l0z9ѭy{ wtB7ǚΨ1fv!Aul<46ݷo\ 2ЕhƬl7T(/ GFF5,o m[@e=Cr{! jK!8*^ϼノ^vrţl.Nӎ>dN?tvn3lA۶^($2n]-]n˔/j]a ^ m d9aBݩlQ  ?$"&-+ț NQE7|8aŜB~>jp'O显 u Py,JRzOxpO[\c!jz+d:0 ҜO N:β{"LC~y~8~LaBynM,̾_/Ұ_N.6cVbkkNN?٫|nޞG!fA|$dxÇ 4<̘3)2\bĉ!8MGKDv\—"eΤY͙`\$sHdH9K  ^<倣NքHh m(Ɯ5aO%v,bBxX8XmAii99!cȏEd*S,gСoB1ŇeEદ;jѹȗ1 N5SQf-3]6T'4MZە Ֆ׏n`ʕ4?EhڛhBɩ?(9OC" HtkDi"B'ByB 30K30L226ttEdCqaa(l߂[.4B.,d; 5Ъ봒.B1mj:2 я̓'=ݔi*""Bϣ=ŃNLJs4 ѩ,ˆCS"\oϪ*+J3uA欴vzGg l0t|2%/یI%,2H%u۠V/ /n$8r# 6cU7v4C-MWMN_4՗DJ/@F=/OX}3n14)ASAc[?ߒeZAu/u֪Eb[zٶ~62$&HkjKq]K0kw[yk"$ Ek`~OOOiRPPxPI<"P|I'%.[ָ Ԡ҄6--je;wٵ$Khx6zf^i^驉F*/bzBJup—5?Uю^\#f_r[bq/Lv3TR w1!_^'[f3J,/wGlxu/Gk1yGF% 0cCq\a|xO4 *b֟7MsKÿ],)br19Nqz"WUHM6Ag!AyHSAL],+exHD&Hldd#TZE [OC3?n:GBicn (htL^ՉlǬ =[HӤ& syMl^3J+$ldC%L9LN⡲˙r%,lIswd">ڋhl3 ICVS hG=ʽm!&3uXͩnkUư3[Lx#:9GԂf> RhWIÙ4! !fF7UUcUHObrqJF 1LPxn s}bxЬҍsS*OK5qc;u(08ѫ/JJ]bM{Zd%yCrX*]e[U"Į?qgB,)$2)`[L΍~B(QE]򵺹d U[{z֢%myZ3,Zp7){#垛-\Stn{Y7C$~Ug(ąwqfʧ{/FHMLɺu{{cgaG^yfq)^OnHrS:_8l%p(LJtI S gdE]ui|oabW3( "oxڜqևrWaƪp'*U"ۓ' Tt|?eE.2j+YCY4SMk9(tK̽$~C d>FIt-]4f%ht95!6TInM}NOǨ0QLB!K]:Cy=f$&1 jzx(ÿ́qAmnq 'nogܟ/FBfacl2HmP{bpCY`^KY6&CljKl+C[J=Rp"׀D)*ZqI&j ".q_(FU^c-u\Vb'fҥq6?yTs `9x祜0dݷMOFicmӵMY~Om&Z/i`^$_%X>!NlI-irm\Cȹ߄|i/e>&po\q9sf^.=?DFPc [$ ;9,A10:T9b5zJCɃ]҄?@r3Vqʲ<9ÉX$c=77 ɝY8 L d3\ IL vYA>8ѹe BKKG++'K"̧V,KKׄ<&K ,< 3,%&CN)dtdGUҼ#ar<jʛ@MPMVd{M܈47Ljsޜ>0/˚MpȔdɪC ΠMTA9M+W O <ꤺK4*Î?IH=-LeO)T/̖4( 5=Bh|PKH нP)Ŕ ݘ4ϧԔKHtO@Q4bўЎd?˼L2$E\LMqNx?|K'-T`VpXXTFmTG}THTITJRKä, Sϱ>s\N+ 1bQ\wTSDVMtN8y99!Ӝ$T-*ThTHUHVe]VfmVg}VhViTjL NŮgSvry9V+MoeЩW& Ծ#nraeRh XijV͔*MDU*H8yIQѳr5N28dU:2mK' 2}݈Ä~GK"VYMX E;$VlF Ո =MUJ\d786:M٩#[]#||ڬƚ]؝m[ٟ[C+-pWӺM ӢXVؙ@"eHw5U[mɡ [lӍS)״e6Y ][-]h MmU=G:v eq܏Ch\Eԯ #1杺.}03bbq:7WBLU[=f[>NbdX>}ؤPV_Q]GZ&Y@MND^B Ju%4E\F;p=Vm0[rQpgxW ؈y XEdbw[݈m5NGXxI<ֱQ)h.\t\uHJA|`U,DpXgsY. ^g{|~k% ^fOaUSqK*YMhnfg(-ѱ莵ONI֓\j]Lhkw@.Hgji8SqƍuHg^Vg.؝i|^hlȶj<. aN([^R@POՈ~]o書ayVj(hܴ7]fko`u]P&oؒ>j`nw@VQnjn&o6X i& _ l);h+颩0cH_m,qQ]RNm`[fgsWgvnkk6wiqX!̾>X^olޗL; n0t%hJfݢ%NZN*d '+hPebѲ[T>Hmkv&sΠ?Qni 6rDotvYO)Obe{]UV7gdEb{=T%`O"&X9lVO] Vh~vvoh&tGWtFnt!;wt nlsoslumYA.u,O/7*?!If IrVR7v9MEgsdpk& ^@L5EE tqw&XtrNOo͆w*5"9gwCmD>-]dvFWXoP6%n]\Jxm@pnYx pnc{6brO)ܶs(~Ͽb&ڢ8.Z@W6RcDuGDDcYg'xrn${*ufzZ7fuzh.s?#g$JeDž/qC;_}֏gگ*%uczhh,s)sǛ\x>\ 3&MH CcqABc"dž;paGN *d||&1N5УN0g9p$ɡ^B4tqLF&9u逩vl*·\CFkDjv|Ġ1tz,o0/XUk1n8Y3NCd t-H,Uʌ-{Koέ{7E&E|-m\{CܰY[O~1/ւ9H;i׵7lłs*64%O8^[Cw[Ar1`y%DmRmarTqFQr rddn"wv>N.HQaRv9BA堋?)Ԕ7REGBb-8k$agyk٦TqY#D\BdEX盍5!S^i^Y`{} 9^ĉ\J9V'Bs]x`iW &ebrU1J*ګ[l"W!MaܤZޙeaɨ^]hCgG>cfٔ4Z6.EN-DD* X奨wjЖ8uF5&ԜIf +sܱ#['lpJV܊٢ 1T[4ST){d"I mo{:) (߄ 5B'=#11 1os]w]{6zԪ"7P Cs$FJ0y봻V:N8^ok AKyfFs4'fQ }Jh u+LߙN9Afc!n>AKyH2V ʺry£_'zDzOO/x-=:WF5ԛe:(US;֦5v$jgmjK 'Bn"wANpFt;2%!arBPNX)c,7i.~COOF/zy!UE?n/+ xuF`[&7I JZ2Avq1%OT)WK.A.44[Ј8o"ZvqBߪ\Cf ".H(5w#6Jdxb'(mle< rc4H(`"!?Oyt?ӡ]KV ]h>%y )'>QsT 72,A8h&8B3R\i'4uL`R0 P]S|}J KDN`:9m0%RN$`<׃q%%F%eO&gaLUq  Aɾmp?91XECgg?ڃs5gU')Q;M,L)Zg"q۶t bʗ֭e`M(oڒ*cWw)bOtCB)|J/zx[J(?_ZeV;>KdOj li ^r#Ĉ &wĚ0\n7(?]ypbquh_dƖ@E urm;j*VJ~[;[n2qJm`w9"g^H ]zǮD|YLddT~7q^v*`Ae8++ڐ,w^H\˙Vjtsaws3d.6puj]:O0m;/RUfq=`i1lḛl!{;phJd8>xuA9񁇆2.+erC;ͣ[Dz Kh)% 9 jd]砧dMь ə!7'<κSK8 ?YKZnqq[-p+lb ==AcTRr$;# % 7ZU,g׾W]Gm M^9>{s9q&2>(py9b%ġiP/Ӹq dEXDWZV1} yU%N9 帡ub~kw6~.?5 XWĺbtφ=lRjw0;Jȃq'o>~XOL5owE`z^E$/PBǀh {O-U Cp3W98N/M@]pU6}6 j xZZM9A_MFBG1E["AHMC͑IT(ԑY DZ eEY_fm@1D}~A ָ=!\V0`K pw D\C< >^|О9r8DWїSqM|e`4Ф  MĎ ,K*z1J<m˙Mb}b#.Q^'M`hJPA(J("A^ OOM76OJ#4"-ޣ=/c@Oc4*N2T3d B:D%5f4WP Y{b7^:#^W({ř 7$~Wc  \ dPDe('&^O9".bgcGeCaX$h+$=G^]Id>nVWk`<>6W-dE8%M k?@ _bT f}1+%aB5U$IDX '#afD8 J*K%,\$9.^^?J`AfoIaDLCnhNOU_\%6 \&F$$VrHDlMYfH92ZFE$$ȢMAr#Jmen*Pq' ;-=oڄfgu]] "Qrdb%h%7enWbznd vw·"jZ&ִLk&簧l$aR#D+S-T5E ԏԎH9DeaCydAiIE<]QAX"ӿu[ f!hpF6d*Ee xlWX(ph&PX1+t+a~6ɣ(t f#85GDlhu:^}AIj*cƢ(El8 ޤR*ZjDھE;m ?GZF*_ɬԺ2)yɬԴUfjl1!)vQ)GKYTNN '1\ɆG *,a8E]RmhjB"*܆m HEؾ9l-TI/R6] ^.!/RQ1,a,BXߍ)T>Rޭm2g)mgn].Ym S/ȻZ8RV4f(Bq1T%!p"g?`S:!a!1[!VB,ajXYn6D?)? 2)7aVœGT7 T/2:'!:!S 掩&2 {/%; FL&k&?g,>k-n2ڊZD* FiƉ,F mPz2B%Yr/__DA&"/aL 0/TF^CGfD7&MEk 2 8SatHVZOQ#&SSk4-Cz^5Fq|M紶?My'&1Ra(5rH4H#0KKo[uZ-VT5H|ㅯM21`uTSFִ|εPjGa g_{$7qr:`{Ha&tr<6EX( kW *栆ϲJ#vBl/j6iMv@vwFa5B{ڡB`mn9Vc6aT{?1dO*rcvf)E/b`V~NRLc~vw;o4XckQ`^ zz3'$YGn5op'oQ5Xl6,J4Cr̵\LG(T 9GA{(f &<4!wU)up niWuYGB9c2 Ϡ/}үg64N,i!EӐiRB9A>)^ΡK?y%.MEx-芢9QzCw[R^tLc#r!UO~I zc{l\֮9_w\Ol}j9n 2N?0i۰n3q3]kIWo9o+c;gIl @g!:֭)#. ߒwo>{n{'/+wmAl[8 s77Ӣ;7 vS/f$P,K=1||=1nu0bmTiiR߻'Q;0_71>u{|k<`޷q IZć,3jwѕlcjW|WZC<[@cTaJ꾖[*5.ɻ+QB2(s34m?4(Jn=(:}[}sx2pҢ=~wiABө'|x:'MIsiԒUyݠz'>}5kʕ:L pIè- T H" kp#J;C@FɐWk/q\=aS,fW|vڔUnݖ]~mvryUXCUbc(G|x =AEϠO3UֺVўK))umO6ͳFd֛h? [C6g "b;龀yzս,]ZDO 6eӡ 9@쁞fEO\"j~8aO$  .jMe-\ ྉdTTC)ba|'(81 cB;ɊcPJQT;lkc h@>1'TLQǸQqx+4c+BJd=Z%1;ICC2j#IgBe ipCP}_$i44-<0Ri' @(xG(a LJh2G"*:iٴt 5"d'DK8Zh?vk&o%4-28m6?KCm0ZZS) . 6]qo{;81bZ9= J߷C 䒧5GXȌ2H+m6/UqV/Y'O?=ytGL[lWD.ocYf[m."w0&-µ dBωi'{)OƉD=ዓpozx2b<3s;^+"'qb'P͏F-%fUJO@38-nZ;G~+H7?ɟ ){w35V~RDz[ReO^RK01xJ=D$S'Iuā僗OkO*܈ 1dcHLF/UƏ-iDo&vn!6dˎ:NXcR .ЁhfIo&R{/>i["ÏȏONPK ( _/>B8*_ېI]*Td,nZĔpPsBL20fBPPNj P P4V @fB4pUИ0bJ+ 1"ebCnAroC0D(hKɞ &,NF2LsC4 jϘ*.2jZQk/B.B:H (l"&&:qdQWZh[okXDWGP-J7ڂzzCNJ" 3j ք"f~o 3DEU?mq^ֱA}/ QD6n/!Wt Ql tEM12!q#GvRHLb)KJΎ2ãIᶣV207b&-/ݦ0'qn.m87>RkB <լ 1E*,ˆ7t+5r b7,-Nl#HF$Ah #iĒ 2J%}EU 3%:s+t)%> 3ȑB8ǐ  C݆ГTFs-vhà 5!#^"{2B72@l> 7 *s%%'99b 0W:3#? 4Dq2g>0&5t@4 GkpnPͼa6R?qdń؄1!j*ڌ,\fV%B2$CCuJ&q#1@HfEP0PNL+DMՔ uC35':NF:#T2qBejFbh*C dsQQN\l.ݳ,S܀'0 ]LYSST/:SETITCs XE_廈R\#s 2fUxWYuyCUDWAR3S7ZE99T:Z1~Ծh*J+FOn.js[7F^IeOmfbtXUaS&Taa(6 H:e(YUauL+Pef]d/eUZk$dcMoZ%Q[wFsfӖ&4:b czUцdσf;?j QgkkŃP(*Ktc۵pY` Jg[^xV+vm9b1++ocE@i]j׳Mvl#e592,bJ Ly!#z}áwH,xC+qq J *J|ʷX+Z\S$ s_4LPfGzZ=a7)2vu"IvoND.$v V*5/.-܂$..jvb5FxPe?}.BC ấu32LL3#X#I@*#AJ/p8F8|M cNQ;ʨWrfkVYٶz7kA;ucp1nV+LKVtx~c;^04!A2zK4.RR̮B..R4*sbxS}g3‡ 6DԊt71גX59#FF :ì2hy.,62y1 ز~Gg77%wLOR8Tt)W#h%V^ a8Om$x:OYL"0puy39DÅg*ۄ6FfW6Y9FdY{;2Wj KzG1R806c3Β}x.1qwk̡#A7lx8ҕ~w_.G3%~ B!A9*ُc?f)]'^67d!zِyG"+F.. 3ڢ' f*xD6 ./c1$5ڂAKZ# C+ 9+ L>5&̙}t#Mذ7~6P؟QgvSV8G Dyۑ[o̞j)V3%bAvd>Wkv "[5ォ1a`jؕ2/ )-sc7v3IkKz4(C#5«/#5+/.aZB6HLtA}["R%T+N%C";`g1$;ܺE)XcѮCZnjmEb{TK9eTQyBDIH xyZΫ<.|mF,͟+/¸ J KȌw)H(;v'lٹ'Xg>2I<3=&[_pqާt8oɵbTur7ʹKn5^ذ7zvq/-OwT_']DگZ`/yAbvW crς/U?/޺{I,OۉYYW G/cMoﱖEHPFNx{| H~{xWAZ|J {)CK|q | C^8(c:N  F؀P&QXq#G7vHɓ(S\ɲe||A 1[&l`|QΞH*]ʴ)H :tO:SسBVn%M2`*}dXby3ӕ[$s<ek 0 mb?yCn^f郚ϧ> põxw ŻPq۸s=pm5Ѿcݶ)Tb4w<×PxsJnKnvGHjEصsbIDRr#)> rbԡƟC@fRL3a`d`I?}qVNY6rT'uV!je8VcdTet.Vfؓ^Ad VBF8jOD!a5 <&Xᅕ) eI%AQZF jwI#=otYgov6[vQx)-?'9jխd(I OEjloxVTժ3D('/n(q+3:rvfg9K] HcXlmaKcKM`´0uMˡE(6Io8B-vwDub},r‰/0KXXLY1vsx[_p0Zci|&Oh|qo1X2uo =ٶ,P֯h[AH15^ك @rأB&@Di9;{Ys'!/7{D @WOӲugj;%5{+l _ `4M͋)rM4AyD;.6o˹%_ RH*[dʻ"T5R]DUߏѰk=fzM{QO""$QxEO =Ϊ+^;4VρfuK/(w[AmEe%f7i\|# R|7Kq!'ܧ[Xω9ޛ!sa3FxNZf?|UP$aI&ELPGSP0jx<ꛄ'6Y=T޹!cXQOj#^P$%~wEU2.1ϘIgl_~+o':F`\!)MJ\*;4z6SsX4E紸ƏwH\)NƉWogB{zi}(!EqW=z=d5tN+$}g,6u`>o6Und=GP$VW|uo7!uIgG}V]eir}GZ-twwi<;+w}2K<(CL!cdL&lԳ4pPo%ofx+K{=Qo ]~{$v(7 Ӷ.u0 $vb|)oŃv'avG~C~qyݡ=4dCq7x>Da3%DA<4)C!C΃M&)dy5U*4=5JxwXcFg8uvznNr(%<8}ZeYvf^5dy:rٙ#|l院$>t8lقRmi9\[GpQ9eIyY}5=?ga!Hm^I_[ɛa ZiJy0+pE/"YAXdFI9RI)=Y 56w"65ʜ\XV<4Ԡ&~;"yr9%Z^f 6*[ is# G7yw1Ys! 8spA,16ZjV9vyis磹ô2'bE' xiXS{8XGvڧ"ե8WbJ駍*K"7 u_RZ^{:TJEB́d;OӨ:C#b. z7碫Je9Ex~)AaE qAīyթ{ɭ2f"i^Hƪl#ѧtho$)Ma4Z^*]bʛ:E: -ɰ{?{I;:te&+b"˲Y2 ҫJZ cʳ-Zb*ɂ1Ge14!Z'ǖ1le̖4˴ۈ`[NZ7G'Qk:U1dZKj"'<3fKj(1ņi74blbl2lDkB믜{ZgPaKSi[mkb̌цA2gmob-m-X{_]=,֦K0x[;ؚ;̎}홁mZ_ve=ؗ[}֓ݙ Wu=c}I-ګ]Z֧--o SM:?KQ%-=aJaٵșjg$%׮ٕO@ Q뻩J!j6}FS;y 3+kؔ}[bnq1k&2t\S<Eimf/> ۉ}>FӃkD.lD# k;ܨ:H ̊Ly C ׬s)ἾcqKskMMJ P*̛j^n~>qsѡ[v*B) -P!p0P5&~K )Ly@NxKCCɆ*8qݴǫڸ&XS`Meg ęv-2ElB5 1&ZbQD}\txQF=fR)%ErELJ-]S̏5męSN=}f|4 ETR>#M:hSU>ZU]~Ma! lFL$5sEJ9S^}XDn%XqQu]֎-_4>-rMֵK-V`[lڵmƍYn_ C\8RI:q͝m7R5]VR^x͟Gz3opU}n>l*S*RcAdP"jBޫB /'7)3D4*#JF!DwL CC>r"گH%?JQl"rh1K-EqI/3L1:$R3R:)+.3O=ԳLs&WD@tP欳Q 4|tG!oK?K#R l@M@EcdQUSWw /)S/7TYKBCT7ZZ5YbU?ZkuI\ҵ@ PԿL CS56 #Zsb(Z%[uWЂ nX,Uy]*]c#w7N^ 4nN_~܆ )Y%=69+:Ȅy7ePDׅF[ֳALXNih!*w eeu[|ٸkҬlc\8ĞڦƄgP㏋&:d`djRj#zy̺ǹr n&#D~goQLP;wD'$E XuK2:)Jd /KLNj',r.rAG>z.g\XK"=$ַQts~HoXP{lpvr?vwi' o;I~2\҄oxa e6@LP'Ali[5EO D"#/*{anE.*ai+ dKCbn" ~6mP$"`Ů|QDGv FbɔA$&"C=,mbQC b "եHQ&yd󲲜IkO2cxxv*a)EJ]iS$ens:\ ^$&[RK쥲xM@8*ͭE`Nhٟf:󐹤Νr4ܑ0 O!0+2TNst:wSCd=M&sg?ρJJIA!ZM'8)S}GQiŠ,}FMQmq$Nz:TyQ'"`I3+*jZvի_RǔTB}r'c4$dծu-k^ Jnzb=Y(kb6ֱ2&P<_tXX,ֳ}Ȫ׳),{ƸmbC?nTi"lZlc #0_B,7*1.r>%7YIEdh[45NmLླ#q2u$ֹe.h@'?(`xCE;ӗqkq:axn |'H7O^,]ncpoY;&EVR-Hº*/t1}A>#K<yȷĸ#|Ј'%VɛLd8#Nۼ);$0X|%@O m07,2hCS".}fMc603Q3z%r5\``p"q7qk ֬z!? Bmeh=9+4o| {踥QaAy nӝ3#,pdٜ-\Bmkklv+;t#ܵK?o;kd֭u? iy0a^YNгd.s \s6?C?7:shԹ>s.KӰ.8.r@#7/ S o{.4?5\ LA 8@Ak<7 1!d? < b1b Mҥ7>Y-347 1kEx{10S1IcCzӈ:<24;+BV[DX[;L;Gs; y·Ȱ8sKCED:B$%&̕ÌJjt"ŽtCC_|S&(lE&˼ǹ\dFk_i!VWL:eEZfGiF;r4+`{lla%JF qGtϫ(Ukv\͓ytʫ{GfG iwH?RH*˶S,^ r +œ ɆD< )NJ c \tKɉH[0100 zd{su;Lʚ1V0{ sR4SIpII)U,냾>;3.2B5L3KAF6s32,?E4ф5F/7Ҭ/MCMZ4+R վ7 ;T 4 ]+Bk?ReGu$ w dˤSTS@| \S4|t.$A$J5/;Ķ/$8O./EV eu֔B3PVpԁRR x&/INJڹpMlS/0B2U43|XeDʂu@ Sީt<^=7Rd,t٢EGۥ)m tWUΞm[ x13ͳDLGMDTI[4`MCHYMD> >9i_^=9drt߃]I݅]Q]&e>4R1hTrK0|#;|OGPjhFDӋ`A2?.&BQTΥKL [)]н5fy7. I;tV3= QX8&Vc@c{?kG7]峅f ݼ 6o.53WnlXXy zصʧ\^;#Y;X~h3OѨ6,8;1TTfhj,h`GޝY֋ f&gu,[%56BjP^bjoƫ֥1.nߡFk=\V .%6d ]h֊k]4eipGiұ$d檮kk{ڊn;RS]lYa6V9AZ>!E2m(6˞k8FĶ)i]Ji`;8;;iT+ʶ)fn*_&Z nz {7"fފ t`XMQG6^Ȱ.lN:F4>eցc$~@ٳ$PmDdoDc 54+g#X6q=cLb;_tfyr .!35"K]ag&KC.K#4N8',Gʑl˒sp\.7qP/"gN4^{P44qq1瀗Զ@a >OJKwin%;sS &ugu@u.RvLfau(ZGa\ߢ]G#yvDv uuciW e!fɰEXvjulr n!o_ ]/U9wt?vmjl`t݈H(hsw+KؖZ'r i^Gs_ xHHN6o&GlFPPnA236Dp4.0209Kpv' x$+SwofU!o2w=sg pzxT[Krz0ny 13.-+f!BOs Vx'놏QE@NwIae[}m%G| ?lW۽31wqnOWO_tu47w~塗ٵ]K{+ُzw">5i;[>~MktĒ]˒/mO(_p?q „ 2l!Ĉ'Rh"ƌ7.A#S G\ʔ*Wl%̘gҬi&Μ7sgΠBmiґ?PA 4xa-)hPϰK#~ej,ڴj*HR$ɑ&cҭk.1z[ϲ~y4)ű%J QF*R/3hq8/vCn!`ͯg>kP+`mV>,l7ʗt;tӪSW:gvbO?;Yv7E'gdmVz]xZx!Z}]\j 8Q'ȐMXXcU]5.gW8U"=^!5a #",RN9>@)m3Y $VbP&Au8%")J$+RZ_>آp VgAM;J:*mvi?C%+1 }f: kuYh2*(   q2Ԯ<ނkV .m#qbF9<kx-J`. l 뗂HN CӋG郖iVW)X7rc[|@ )ÉN(Ҋ̆^N7J6Gĉ3Ci<X=@s[g]/ 1W4BL,V <(ݒ9./Ts(~8Qa0dhJY_]&68*5-bm=(@ҟ@s?>@ڒt=rКm R=S'n*<|p0_j<@i>vpd α;h 9WTUF#"W\yM.gfgs:"XVB!D,{s Ƥc͏IlI܆1 do ޢ;X@/,v29%XJQ:XJff7y\IxTl(3Td`s12ǀ9 f%+V}NJI 4[Z96*pCS H贯 `MۋdFAEc[ DB<^־ZAlĀd^H\wCVfUKu8{'RLd RE*Zf$g/rb%2]cUZ(i_'W $\OI׮&F z{BSYH6DSG}J|`NS{@ $P\fއ@yLN.K*繍.ƙ &2;$PIʉ7Oj8ʴ5eF7 K12RFMKJ$9I D NyTItiGtYX0ȑnDV=N2h}@ W`-fu_2 Y5r׹B:RžUeK]S3j_c cCkطpC]hkԞ%,^r_s، %Zs!:j;wm;er Þ1?䔕$prz8Aswѝ%G' gؠK5Q_͚JNðzYg}HS>X5 R@z~Sb=ud +7`v Ќ8yA`^:" `,Q-zٸ,$(zF[>ޓ(5NYR ;4J8s+H!;nV5 T$qYkyuغD#A 0uK4"BQ4!rdۢ5oژ )=MzKnTs4!QY)W&yUXh}*]ͷa5-PG;?DJzEm<)k^=1MiiyǓv'=LZMe9Jwc& pUhYa\b^3f:uxg]dlAG2.2h!a{jP#{ّwI ev{ZoKAEHe/Yd{xNfX_%r>a7QOe&"BF<=C4(H2Eo) |VvzL~x[hxA-iWΕSW W,ߞ /t\)UunЃnH@Uإ o,P7ks/ƬO^)/67WR+Oj_Bԕamɚr& jTV@k[Ub] p` NQ}]a ޖ qTeV_ .GU:lX!յ8xaBA6a8I}IP Bۡ`D5"fE "ڕ0J[$`%%L56 ͍,Z-*&uZb;R<tD^ ~$L MN?*T".d4%j<Ghb'r"C9=O=A[Pɤ!|[t[;*HR-$B-͹>ϫA.L$HɚH2C֔RM$F4N,=e5n6ncƵ=W@W, B^ F3ѤߐN.)O6@`XQ&$QQ w1JRƌM$8Uc\d'j&c7BRe:V !!9(qp8>SzY:p *]E !.eOJQ``#jRfJc"FH A(g Ec^H: 9^h:Qݡ}@\\֦l5d "6afsI2~^ *]eWG}rQ~`g2G 1֖VnVǂ̄F(mThxt||W(Bمa6wN(荪Ǝ*bP  `TȪa&mz Pԕ)d! Lr=aAA"bM)"N")i2b+bLK-I.N.i ( F醆fd =Ԅ#ALY<,RZ*V;漥("^!nbxɄکz^ִrکP<[*j!:gBkJ3JɝrW2E \:5!Q _էkmRfB5T !i6Rkf"ٽ֓r++ ,^䥎SiI9Ix^IĶ_)R(m>֘ ]Afρ,0g ɖr *`4)2)|RzDюӒ &fсF`-תHEϦk?-o-o%۶FےhE"ζJZ%l2n (-߲]8^hbŀie dztF| <^]jn 'DBW*d |I! "%ݓ|)Ĝ.6ޜSy GB`Q$ĮG3&&ʐ l  K̘Taޜ8yMؓJ1TL˓M+'v:ŎRHT!.tJ $ "\*?H>ݪp"ƿ^6.i!V4 19u }Yd]{)pQZj7"D/bKИHqqzcN V鉌mVppw$ [+yO =:X;ȋI&]u" H^O%?x䣝ZL$+[..b~hE:pl0ڰ" J܁%"S) pTPӴCqO!deLj&C1'ƽʞwl*KZ  T\0lk^1//+s9Ě%!2;*Y#4ߎۙHfΣyf(R؅4(\k%$E6GXk/:'_>т r??٧25/DY?eSy~8mja\̞UkVst5xNI櫾,@+6,ڈgƒʱ>?urln vPu/1^UOȖaadb/ N3_H`_iAvFdkVl(F=vfE1v?Gi%jT2v,>;hgTbB^5@0p#watm"DE,knݴ(}lGhHtK7Jv~47dJbr &VqW7 u^ׁ/I-3Gszrnop>˶d7mΐRA JSʧJLp/[jt*og):*޵aɬ| 3cF{uGmӕ; ׶u1*>M?1";29׷cU / )'Xq;L)":\ }cpPRz9=͒cvcpȮg3Bmy8[ B˷T\CLrWJ2Iz2)C$ct$5'& (7s*][NҳfkxmyycHz^B%3Φ {'4S5ӷ9{8y67\78p(Q i[<7liy餤y:{i1aB/ټ;J 縲{O34[dd>܉'vb)uft']EZ~ѳMiM쓻;QMcG Ee=@~u;ʫE3G;>M\h>+$7gNg_PTRFZ+6@(DhQ#c @6) rEaC!F8b1fԸcGA9dI'QTRc||dC *<b:hQ%#M:r2QEˤQDTzR5PH7 *zVy1%M :.ǵNջo_"fPpBV\RqcǏ!G<pe˗1g|b@'К@ռhҥ&U[ Gr1*s2v7)u%q,tױg׾=`…JjUyѧW}{Ǘs쾧ql\5+>D0R:Dh-T. QO aQIq,ͧ5rq@xK,p'I!&},xs6js袓)}(R5|'kATup%2taGBsPAEH` 71ĆEL`u*:s;#R(ď%\bIQx;ҀOFXMēQbG9vh<6@c55:l#dI30蚤&AJa2!$;"@dcXBu| Q¬re/I(M,ټ\!Lf~LT\1iLin$3Yh#Ԙ5M\7ƌӝ'A4:mӂR[& N}3r&8 j{3g:jʠDhCЋ KUJ n@)D)ZQbXq)Q(7LGuQI輑OsXb\i Әʔf_\vE*Q RCUSQz&Mtd*JV U S#ȥu&ku[N5e,YXŒ3g>XN -l$[YntcgΎeYӮjѨZ^fIkraHYyop}Ln ՚fgmm/d{#mn+ςqzx[nEZB nfc8Yh^@(OU޿UVe`Ep!ꋳsv#bS "/a-׆uqeJlgn+ gIȈ4'NF|LW"H@p 9 I/8 D`C08g"ӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h` p(X :8 p*@V _ P5,נ0nhXc5-$y"_9I`RyXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmxLVbA6Fx~=8~, #9.8~[.xǹ$ߘߧ|~}#;|Z@!,BKT422#>?IBCM$ KLW,,8((4CDN..:󼽑33?abl`@*\ȰCxHŋǏ5nɅ"G\2J0?|fř4mDOw 腠C)iҝ>(thTغЫP0פQ&`۳_P`aY: H@0 *୪` FpACǐ#KL˘3k̹ϠCMzs}~ [ ;!׵Ҟ[ݹg''8ß]zhqWZ{ >č!,96(22>?I# $GHS$)5gꨩ+?S $5t9M𴼽56wؤ&&(GHA 8Qf*0< @`ApHbĉZF ~q$ɊRl ʗZ|̆&U.03i&hBTXj  2AA @ADpK]W/߾uv+xp†3"Np1c,y/ed343Tٳ藥CN:#Ԭ65!,9+ 22M$mC GHS&&2$))5ғCғ곴m>?I++7CmC8CC?@J00<[\f+@A\A@… pĉ^X1ď nqD MNPD ?ʜHa 0if'(D0A, <`.p װ`Q,(g_}%) ޷ |V~ gl! r$(!%(ZaȐ08ځ/xɑ6 h䒟19AQY'F!\9"Zy=9bI )yvܙ'D|fz'bD'Bv&Zz厓Ja|>z>G觤醛6ꈝv*j jN@ժkXZ8B&kv"ԪeNkNgVFԭ+D↻䭸=NM`~nѷS_ @a,/k į[@܀A 0,|/#4$` C+6oDX\A B/Q 61WlFP2<LOL6#]3G,n& C0*n桟8 d 5-!Px|C 4.s`9 ! G@췵\_ubcZ0|Aj^7HO ȸT:sq iPB \h&2m K{+|`Țy7ar_g(GD/!e2HDAh a8 pycuC8`~yPet| ^7Y dݦqc aFHˊ8D0!R|\"Ilz@D+^f .jȜç5ьA#v, 幣h~ɀf2wGC RsSrL&1Sb|yIӁ/BL 3C HC2m Js"Mi. MZ'КT³l3$13̚dI%…&|Z-LQ\WNQ% 1N@U%j)uTӇF.-ϰu0wОms[ᒮè*8 SH@\V/L_J7tuiM b ;ͬPkL5Ƌ)v&Ȫ:VUjAJ诈e}N9|a34 eRPٞr]eoR*6æ_`b}hзl2)˂ŚOf95_U2qf߱,3 ?*ptJ@b;/᭩U${8d^0 {\\Vv&P2a)BwlA\)3paw[,)]>W?LJ/\Ed/J[fU)oE|Ʀ_X/" Ⅹ VĤ57kT8:nd\ZmD,E6  W,_8'ps]QD1\1k4-fQN (PY*gU_zX3o>ػ5T v- 48g ն*;ق4n ^@r'HPZ)ha-ܻ~y.eQCt6 W6٪+Dzn3lo~ˬXE( ,1J~s>*GyE0FЇNHOҗ;PԧN[E@ SL`>t|29[t\qy+GAv2߷w3}Ius~|Aa0~d!'O[ϼ?8B ȼG_u{RZ װgi~NB ã0"7-rxwZGp\3B;Џ>yB $N 5p}O#{fc'@  wc} RYkQ qH'r~&'{~57ck~YX&x(Hu.t lB1!X ~Q-MGjk#/L؄G P T(t1ȀeBX27%=AY(RC5hH_+qDžIUXvxxXwik&~8[h->*dȃ*gHLmer898Q}  uu t( r/֊G'obeX"Ȉ$)82iK{@sEbutڸhyDBVȌtl"Xe{-;8M_(~8hi{(>$VJ  R7JGtFđ_BȎXE8= Qa3O@f.?׌;eIQx@Wz Q!HJiɔIAfR>(4y{%y;!- ,('y#iY'A9K=WxsBY# YIEN0tM0CBGCDtM`AiiA)t DB@Y隶陥9G INٚٙə> IENН )I}ɞHQIbdi`Abc*jGaʕ1AtW̨uWqDFCjɡ*%:ٙyhI*:ty9)ڡ9:Yi/*.2꣤)4H J+z?HVRVZ!A'cʣ9J[ʍ,0Jyti rՊWy&98[ŸC2Z8j1ThzmWJQqY:TyYLM`iٝm@M)2ʙmJB7*yYE0jcKʫ)O꣓9ɝ֊1jQ>j٬ZKʭikڍ*ZtzOIM7^z&:( s{FbɨJ e=MPTJg#:uJt>Zĉ&;`SjZЪ.KO=*˳*'DzOG*窤% 99HpjMz)DWB˲jK.Ț:35+Jkt:FGQ.z1-) .{*1Vű깚ʗV$#Jj+CZ*7K2;qDjkɘD]괼+*yI Z[۴+`ڻF%YɺiU}ozΊJk퉯[De{30٨zdh5Q.ē۹Ld+!๡bZ{t`$L&%?*grIAgˬ[.٬qKXʴiaKd[9:J/| o&© ɷEFox_;/Ҹ))kb*f)4.(J4XIP|>YYZziD7^ |ŚߚĢDkzWz[ [ȋ|kq2v[z0JglDE |->k9$ǐ́l,/8:s~5('-~ڊ;N6>;>T^n4]9_H&0 ?\n%~QVp TlE]n|෡#e,Nmnr^'~g> 9FbM #^U~]3-`3N:&f8(ꬮ0a>޾+8~5}k~7C+Mm7.>* oeFxcKNm#nLn2 _&/ +,Hj+ /{F=ﮎ}H'_FO)_~D>4g8/#=OO@NG?d!Į y-W>qⅲp_b_? FCN,/o5+VǓwR)SXO?V~[Q_-OaP1is$zo" ?xK?/d$_o塿^>l @` DPB PD-^ĘQF=~RH%MDRJ-]dHFgjI΅5EDgC7POzltfNVŚUV]~VXYeZ6iԔOBnܞsޭ(SKA5VeZFXbƍ?X…2Լ69႙qnuj)[lڵm{h`]4vFӽ/{|=H:x伙+Ǟ]vݽ۸X뿏=pD5{0@ s/;!$*绮 pZ{'1DG$D CCk=9RE]|d JA2qA%LH$H#E:JſzTA!!r"JU1|J$$L3TKɭԊM:jH>7MRG0΄1NDPCE4юlPLH;'JDK?s S UTSOE5QFS-QsSP)RDǓ=Wo"5Ua%W}W`"lժKWO}ו%Zc7\qӴļe-']C\K[o -q_B(twRheg-H沍b%K7c? xYAYC KN]Nn!ֶzK?9g7y-xa苃>=+bK㝧o{&Q8nVaCWަfm.E:=نv&I{ߛ)FxS=mDBBD9޵]svzo{yg|ǎ>iz9[{$O}E%_&-̱e竞'K{`%h~(8ڍUB!:x)k% o#BMBlmB"шy!|:φQ W- c-ы_[BVp/MF31hâhFNwx-2YNL %ƍV n͎yd$qG1Y$I,260FzDe*OGV&.f'X"Gҗ&EXGKQ|$qbA.)WFӚ״0IɄ2K<>TLlӝ+Ԧ"yInzv+ 9OCNIV{WwԠFg@k 9r"3r BnSB&zPvt e&?G+Z>vi"9Ch%rGe:STt+m(3OIj"_J@>ԨGMS*Ra?GQj-r*nfJvիR:=KE)Z&&RX:W +Vu*Nk[[w7UuElb uWVd*[׽,C_@*ֳ-ccY߉*la kYԮ6}-fA;[zLi%Vͪvc`UE.nr tYZV`+]ڕT=[n%b[j3/|߂WD(p@0_B(~`  H" `,x@P@݅D:Ғy[YCii&$N>`ͲP&7Sûj~~Enp\vSf{!X8 CiYhBVc܋\z綯mow-ȉ@uV[//` 0e `:Ek5ֹHʎm!_^W46ul Ժ/mɛ|b|ed[gF1 Q+6X7xN!VvM.ҮӸ>}_Ol{N񀩞r퓒pA8`<ND|(;b̛(~>Th@6=տ~iٝE~OwDxqѾqBC>>Av@/B$%| S=|7t;ė<=<`+ń3:;S<-DU@H9DDJE Xl Q0]5^s=d\{f5\k˲3HŵFFG\B^+$AqJ4GC?^Ɠ@Ƃ=4{ c+xD4Bp"uaB,L =bv&]LaAM]&bإZa@Kb N]-,x֑׃i}b&`2b%(Eb-va6.RQcSV<&`Mab,b}Ajj 3F+.&Kf}AE^ CmauTmd/`cPffj!ܜ}S`Ueae9UNXre`cH.f*bIFRhNFf>~`,8a;j.]eI%V\.b4CqZvmlv2& gigJ-4LgYgokxd'Anʌ|U VgjV2h'fn}fdL6gPK6h1Fe}VГ~|NT8Jndi Fi=yhC&}Ni#gB\E9j fXbaVnjc9-f`%v߆j&jnH>kg`RVP?5l lD$8>Qd޺lYff$ɮ>$lꃎ@oމҶmBQhވ~%Uvn4٣Vhm3>dNnf-~΍NlnN?`Fˠ&BYα 瞎&pFdD k: ~? 䪎inBʨ bpB6q3WXgoS?r4r"Ogg1&G$rN ĮzForr\M c<23_ϕpr:3QloWr6cj}s"&5_`@>AgNtEH'uaSQLYP/[ItqZLؚuoZudeuW/6ψ_t,BjdmXtfwxgt^v__u^kupwwhos? jo"-l?6Qvᚁg|]wwvvw|`_xEQ]ttϐ\1/BuG{x}vr._wO qyyʤgyqyg$?zq 'y@:,Wz/xW;?JGz> I$^)xϽ@;_r<&ՇםnjEZ{M$_i q {b,_ú?|TDO{0 ||wuWgFG;q4Fi5oYwA ʽ/oA]կobr~"~$_?Zo2\=flMO#~8wN,h „ 2l!Ĉ'Rh"ƌ7rLc ?$I@ǔ*W8dK/CƜ3L-m޼ȳ˞%G -j(ҤJ2m)ԨRRjU!ɠYC*ذ?% 2̱)Ze۲hҭk.޼zWVA ~kX#ܵ㨑/f|2̚7s3覅C2KWs6kg&m6nv7ã_-kjhsvdM4F͕n=׷s=xOGԙpN3N=yӯ5;o0P%,PH0Vp9 ~jyl6[]qRx"-bv Xp%ꨤVzw8[ f cz+QU+Gn'FlRI:˙j%1֪zٮN츁jz^F.D;g{/{oC:iȂU,:K<1TRi%I1tz0^|2)\*w|55A8=3ya@Բ#ړr'<$uJ}5Yk 0ЂGoT}&iT6q-FP ͍ڮalӹ7~xRu ID;8K/[,{u9{i埋Nw}詫+ _8`&`\_ ?av!Fd%2I(ĒnGETq@Ģ(ƨNZD !HA c9Q(򴵼hG=W9^ǪQ#!F*Y$&DI~3I #%*Q?<Zc"`R39d]VZ+K^,(` p9Hb2I3SfL$3Ѽ&6l^`B9%7)qV4QIu?ҜRyҳ @5"O{9kNk==v6!8CF2EZ-)(HWFءqvksRBQ#])LSwH5+@ @);ҝr_'>PڪA /NȤΏ6 ԏAV+Zғ0zr+|`ʏV\ =Xͦo\,dէgfki%)"4-c72TΒp$@iղVm-lc Dce$kepȹMrZ amiV3sY7m~YR5֮f@ꂷݙj6Ϗ3 Gsk I_ҰȮyj `6~|%\໰Ɯc3"NK}5L!ķ' ,~_,1sGr -u},!/D>2)dt&ɇd(S"P\OS22RʎlÜ>d+\ 9SR(u}`ݚ/' \9^v3aIko()&]C]/o-`SEHu~ܧV`a=VJ"lPJqtwUcjlJ#{QX)jms./"nയku0-y+7].;/Aۮx~6[^K3ߞH7eޞu@b&]9>k.!ҏtg@Ձa O-ߗz) @U876[S+:jBszqU'UaxU~lmΠ߲y;{sYwE7m7oXNoH C,0g8#nv!!@κ5Ւ|+t}@ X ;56H\UgX*>y䣜a^}cӒI| Cͩe;{< {>A[sb>̏y ǟ'p[}t_ҹ, r_yҙ Q}`t`QS N_F` ֠`d` ڠXh2DS^Z6ᄡ NaD!faD xBjԒ@@>D!D!z`iu4FnYIa"MTM"F"i J%Ra"^"'U&Nv")h"$*:U`(*bQm (".N/-0*K #2Sc!&3.2C3Vc YA`#Z#7r6hv#9R&lb9#36<<ޣ9Faf#?ҟI#CPc?> A&)"de[6$BBEzBmEEvyHF($J69!@NcJ|(R(DM DQIN@$$RMOj@8(@V8|DL@1m T*A,@@WZ%Uޤ@( D@Ze[LN@%Vm ]F&`AO.]vD^RA`e$}9[K.@%$LH<DMHV8tt&ZʈvNddj\r(edFFPhfZLA|@JXuLf&U"=A0^^DXS"\Fʍ`. Zh`(@~ʖek6&wyVQOC:dZW&sڤ()AT)i~լiiSfOΦڥAFmg~h$n*~fBX)a.aM\qIW&Q*hA\(xzh|ee.R&h)ЈH\g4(jfA~f)*S:Bh )TY}D Dhڪf -r`k FVgGLr bH>+RLN!+]k= gdW~Ј%A|@@q&Og`LdrQA%PU_ lW~&fVP ٲk IZfgoB@rҥ(bV@nU%`jɘ̆쀶K]n fj! NVal(S懢$~gk*Uv$g\."JT-kU]J©Dtnf []M&ӒIvh"!{^xk (S{ibe'*ꗺfHWdJg>hݭZM@hdk~~&l. )fQh\A|IJiږW̮@)LY)P>ҩ)#&/Δ{Z^b)V\j (b(e 'AXV>e(AK/_Bĵf 5I+~0 N Y10 sN 0 #Nbb (G+ޚ@$jgA~Ј Ě D$lVZ@&vTh{gXF,#M$*[c͖b,~(_ ^N$f~lɪҭ1SjeA禫qm~.~Il''6iW2HlZmԚ-aF"*/:>/azl\T'Sr~g.e~fֆ1kZ.B0(.G#V:2ʲ0m$ױ)a'2e. hARhHo&&s "iEtATiŞ݂3܈}%%On"2ogzoEs^ɋvoۦBptk E7CܠWi.fpUBPPs NgU^_D綪*΍E;vWZZ pA\@-C5^G\5Y%m^ψ#DY50t`7ojB6_7c_@a!A֢svA1BTfvGA6vZI 9A,13n,cTMJ}E[ϰlg'' ksk6gl* Q{Q#cr;PmƩvgu?3~vL3`A5rwsL~kKiyޚ7j^y}wP^tFJnN8R5`|XXw7Ѓ'ijK7W~Iwtq R!cxb1ѵu΀79f/+G91g-2f9{.lVkKqK1ST..j 5Ɖ9|,o~l6nr[ mvow 8 DZnkW7u[s$tg:Cdřݱ- O4qMBxy~y:{{X9[oy,L~8:; x܁䥣gayBg?SBK_qAUiw{`pne&^'>fPUd6T[`a5ux 0!{:ů;os*-&Z=vxZn3%~_kºl'3[|bn*{:į %WJ.׺igl欋b/J6nIԳ..AX=QA @(0@&Tp!!F8bE1fԸcGA9dI'QTeˊ` yPA|p!%9?8`M0ȉQJaּRq~3f *$aXZ݊s` z&p.;s B qsI wd BG>R`4dG4dhm<#!9*Uy XDљ-Wh"fVթj{_`K[ַqEr*OGtLDA)^׮6Q+e2[NDL fy3F!zmcXu8 2kƬ"$r=3IdV erR}e,Gn0kѺB4lTlFul*]ھ% $0)R=[L/XErιtgIZ\>Sq6é GϽtl<HY`@B"I.עt1]j` L!nZ hP;0'\J(>wʂA_u.#qKLĀSmJ.< 7֑c.P91eZ}t9@ DH. DoB%mnUupи]no]nI[`5yk$]x_Η#-n֗L$ Tǘz8yl3-a~K%@aA O[ŰUAu˭R\հ1|c^{  Gj@'"KaGn_=fk1s|e--ֺA`.6fyjZԏVpNr, d/oAC@m|iP g#+dËL -0F+gzb(椮Z>d>3?>s??A?t@ 2@4AHAA+@4B%# tB-B)B1tC9T:CA344DIAGDQAO4EY?WEa>_4Fi=gFq18NBP( 3+M0.JINwPBL#Vjb nVr.XNAbJ%5EFe,R oc* S1BFO?`*Jo+u$(uVuN)̠r`c!j#8Rdi@Xٔ J#|VEVN"ff'ʒBs#j5<@w0J,vsײ8+_ KN,-c,e_o#0+Tbb*!;aT_t+d=_up(C: tR5pN"1GPfm֐p!eUc [I6ihu+뽔6j3ikd6kiiVk9+dAklhmݶ؛56k56-דݍ{o/#`/}B(Zi7GE2-,]`A`1;@mjbřhY't1m[ڥ<9'g9:c ȉmÁR&Eۘ˭zKoz86Y R±)LذQ [9{ZŸnm)VlSLZ;V۵W;/3mO)lws[-,FȢ v{JpZJm N-.a.C*ls'xq[1M w C۽4ۿ[ || ;]ݝYK[R%rPyYU ,8p 8|pA**` "h! FB2eAppB @Ԅ3Ν<{ 4СD=4ҥL:} 5ԥZ5֭\z 6رd˚=eƔ*h@A0VZ%hAr0nj b:&lsa we*aqEHa^an؛s)e D ^vQQbeFєkx&v'cJ#ڈ3) RNIeMheZne^~)[m}xj̕| 4&aEL8#t5WvхDx{uj iiI( zP!in ~ jJjfj: kJ֊kk lKljl.l> mTIKm^mn!~ n⎪ڸ}ѥ.-Kb}AĖBAd|Z`b`pw}pxFA0pd c rȉF.& *̲喻#|lU 9r[Ml634wtgiTY:F0B5[-ł[rSW U!"E5-kkr׼h%Ҭ5S! eH@Ö}%0 nrtPlR7_e@NLH)liMjt Vg=瀈O(E/Q1sHN 054`FWiѓtۺJ)FQNd:Q)St!AjuԤjJE$ -0BTZ96u\Sǧ>D' j֣ulm[T(ըO\x3u|R[Sv+]N*vh;Բ5iHJNH dz-t@T*iΪVl%F;B*;ivזkm[P1bpɗʴ1=*P{JWjU^&$).WJb2!E;r-H|3xv&kjEtjU2̮u,L/yڲD1pJB#0M NvVؑdxQJaDTL\9gRtBޱŕMAǞP.w{`ޝ* BD) /b䊧c>Q=^EJ y?Y}P'/A_#9j\h[^3CϟQz lLG+ .QP3N@~K )D4P% E4.Ԥ~ lc݋L3J$C閉b2MȖb:PjdKۂ4;6MЯ޷өw/+#| oxK|8/DRb8J=KO[J䵽 mݺ\w1omV2 eHy}ё2PF7CϦYԸ4Wjڃ9 @jR=i<LNwd+I~6up!sf4AаKTkCNvRKX24x >bS8 jD}*Fԇ0GI#QCr#$9 bFM _B!HdH R!Cn({2J}ҏ *"U7dB2ɮQp XY!oyCoA$6 ĕįfyYEr.6C>)`uRiI2'O`p> fƙr h*ϧsnɡ9Ju#>7Phl >Or i@"N+'p@ *D$S$0DMbHF9B҂^C vMh=H*bRЉ/$Ʋ6|b yn!qJyEa;.oG"k^_RDXmnkr;L/"F5Lj5/ƷiyK̹A|i_sZ.uptؙ g7c=H&ʤre|@ɩKrg6ia Ri0&<$&ፒ%IOȃNv0&>Mk`*D#Y4\w^D~.4t7GA wr\nD p<Β- !kѱ<۱ | $g%zvKNrz{?6C韝z^q:Fc(ʶ]s$9 ;T:\RUAF7$wvuawi.wg`:at-OfTa5-~8 [%g a,1{7>@.:C4-o~r>}wq|$VXXCExA8WgT2-t~nh%)(DyUf(u;AIG8z6w;Aq7fL|qpM6h}A凕&ק"crAaցtrxB#1hVSe[(KE!'x&?(rwzP'2B{H{GxbF!7(6;"H um؎˨=tHmJ궋0QHp8Y3PzEAIHk X;҈6|xNJz%1Xi(E15h HG-hAL<1rJAW"w 8y֙eI a/r(RG I= yTx l* B9T *O.Pa2&N ̘H 2$@zD1nb@pt/ڤ A(B<,⩋Qa9 NS J YJy ""A\j q}JmVk{7w-PZ#lGԇ {z>ڃldхŠug!@:#g!zl)*Xa?95(,Jjobj"jS)QTb%͊.# zK6U*;Zyj'§[Ʃ eыODooayvꝷRYjWa ǰ2:Ikڞ|xwʡ=* A8A ٜXqz;)zڴ:aH? J'a+c_Dk; i*⡣s8"=KȱrԪ~a%%[a+:H`ڶ Ajjt v(;3@%xەZV![F1 "UKuf[ ѹsHZH~ 3+2 BU[fpەf:Zpsj40 ˛~Z k S+Uay[ _j+EjRuA JȊjě+ºʺc'IU*C{{z+Rۯ;5S&<(+$<:룥K!0{ ;P8[?<-+L勯'z<5X[\KI~z.'jxu,xc{e`l3,5ܭ̫T\s!! d<.[5;fOOD®|F| ǚlZ̡#][ &!J$X9;wl -CW-6ݼP  ?qY=Adۛɔ<~Lb L* Q0-<wt ҢKLl}7GFJM՛ х ب-w\yLs _ݣֳq-ڕ ׇmYɓ1[+jڊC1\}*ż- -t˔Ϯ [2K:fܿ ݧdGOt=4" ݿ^݊ :̛pC-q~@ q>vQjr})-N}ZvA.  p^׾r^& ꑮLN o>>˼9ұԭ: Uy?PQQ^^QN @#*ݮ _n8oXޓ5 gԫ1!zy(p. N^!O~ [N\.mA>U.ТGl-AۖƸ.V~ouoin@ii1^ ;:ۤ͸^zHy ^DnjZALn~?c?F..^H~Fn!@ DPB >QD-^Ę@ QH(|X@dSVd9‡.Xe=}1ʌ8ez bPDjLTOU^ŚUV]~VWByEldzE/^jш-<~`nE =MIV Ľ # Wc_ƜYfΝ=}5P1DMNt99tm:mSU[d:uD޾%g Br͝?]:WԆ<{p4e\G5~]o".l6œυ*U~0kK"﷋ /(m;jH' ,)8 M(̓h"CWdE_40(B%&1K':(\>#еrpH)J++2*yν\Aw趗\LHD/#NВΌlM?t(@ A -h P(GIR4сŴ2#[96$u$.̴ >1" cuHDZ,_-TEKx HYe!XXHx 4T^Ū>S5'@=X*!FlUWT(KZ핱#`)@   x b6@`I:1-ɷ◸k(51e]&#bo^=gƕpanQ4`>c]P x`:lUd sKL/SI$Qn!UmQxqFR~qf>ҺeT#WNS߈D)DGȫBq !:eVs0xuu]2 q!Ca6qe.t8hZ[7}GIR㧖^JҝX 2gQc82J1"}Ɗtoq۾f6*q%LHDё+Q"~`COH,tXÃFt #JV4h,Xǖ/O!-ilC6Ӓ\Lf63-5ݸӑ ҆_T#b0L. C9C9i/ :ӝOU{Qp"Q%Īuj(T$AjMhD%q%oCNp0'B< JEA%JdI':SҴG2R`2K1H"[N7Wg*Or cM:UgVWKGyO &'Ҥ3|Bzo*!8.  ;f.oCuګUTlf X:1aǟ~I]Ilkum*Z`Q5l3Q25M-CXK%N l)KLd&͸U㷴@.!jFdRECBn!Rdezû_ˆ+[eFDm`qr*CXl0+Ww\Ht`\/*N[&3Htb,2"/WZnFƛhR+&f3TYѺHM%>bUtFA6nJ*2XW:ZGtNDxSֵ+n\25o'H*c.G74i66e=z:C$ 'ztݡ'dgv{^NKGвΆ; e wΐ!:Ev\?~|o*BQ6kuwNz U~յa>A_3яPg\Ͽ0e^ugDD_x 105*@½A;teCz1- ħYӹhhˊڈ꓾+C|TlFTD ,?<@2 AB8bD2'SEIQJ)Ƅ@Ŵ!=@,E b#(tY ۏEa4Q;AQ9TeaKAD"F[$@F JD8t7xC#bv,PXG@HJAyBЉiGDlƋθǻ[[DiƇTaPF,E9CJD |ŮX rD8GI+HLiEik"[7̈ ,J& lo2EL dlv|@@ 49ѿFčmo4^dFq8zFt/H2$Q*{t~DYUQI\T<бA_,a]͸lՃVWUչhmeNTt/[M9VKH 0u%-exe2cAGgKOLN׆E-S$̄Spt؃Y) ԋXȘҰQQ& 8JIWչّ 8̂VL ͌J͸R6c]mV٨LhP'O}E&̼uپ 8SZex(Pz!֋͌UZ5E]b ND"vPBccl݊-3>w3P([*S @JeT=Z\ڰe:qc\vfX/ _V`(3eRQ_g&gx歐n kfa ؟3d3Br皪O6vN$  %#d|hԺ65NeePM(V5(fU|Uf mmg(E鞎'#抡<EN!K? h*Vc[b0fjҕ %ZF P(6(3 =yZ۬VjlٖnpJaX~SFg[`U'Xpe6iNKklb 1iik /"``>l*ƈpjj 5d> 6mEq)l6 Dx*H$6fO朱ne۾&CxnuOoC atl>T랈P vond u8/ퟘW0ƺueN7nPp aocZΨ'jnn~f&f (bjDToY9X@hqf9tf!O GrLrǝP&7s3oa {4 *8(rHΨ8&grBJ^s9Gt68tl^%?F 8HED8s~먀saquRPuStuX`a'b7cGdlmHp񀼶Tkl q'o.vww8wߞv{8wq|ygX{Wo_X!'7GWgkilnw'w6xgzmCmWwGzgw'gnx7{Q9贯w闟kgkivzwvyyWţOgЯCzyG.|O|}Gt{/o|'7GWgw~0vF77n/ʿ'.O~bwշ@ hÇ&Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:wht(ҤJ2m)ԨRRj*֬hT+ذbǒ-k,ڴjײm-ܸrҭk.޼z/.l0Ċ3n1Ȓ'Sl2̚7s3ТG.m4ԪWn5ز.Xa nh `;<(bʗ3o9 4  0ѝqǓ/o<PzB=󯬞D)_B e_ * _{C-`vg_rj!zTPux"-H{^I"5x1b=#A 9$Ey$I*$M:$QJ9%UZy%Yj%8]9&eZ4i&ݖn@p @t'6(u]v}W7J:s! &64C }:*Yi|>0P*ʺ٩R ݬbh tQ,: Z{]Z#z-;.{.骻..;/&`PM8QB 8~8+8;8K>9[~9k9{9衋>:饛~:ꩫ:뭻:>;~;;; ?<<+<;{\N*|e-;8($ HmP`=qO@'j6@M!ZJbshS RF: u|xCd0*T!QPDgG) 'TZ" uF('+] 7:8D8ъQ+bf(D|R'?$Ӿ1lke00"_&)\ 4qiǂ*\ `<+ؐ IA}"H*)G!xBS+hL#(I K,kF9!GhhjDnj!r$-rKLRӂ'ؒsN/bS(ժdl,LDjjbvʈm( !O2I<"A!uЙҴ6)Nsӝ>)P* $ DWb~#!*奈 _EH~tR1OeP:x+ s!)RqPx^~0k\OHV eg}SCT ϸ=kCq"gj/(gfjx%fiGLԓ 빧TlS#H;:UsSzH\dTPޒ,Hk*I|;bgi%׳g IDeV:zSxoy  `@.#I ChJe:raRh[,}#;P*bZAҿ,ꃟjN-E$R.RD7eEc@!.2-s^2,1CvwVB#LN /53Qk& "ʐXt[HB4pel ;Ҳ znkɊ~5Jt'kpVAdyyA6'a-m0:440z8֯m ̍،MYtÏ}22Wz,JʗԉB _~i>7Ko L] 1O̗CA=?RGT^`\Wze2!^ߤ'_qL\ZH{5{T_e$dM/m_z)_uW?_W[!m }ga-ӱަ C $̜4ޝ1hq"@_Hpp$bJRo Q$KEY mT0S!Dt)BP Q>`iMV]PFL\Ц=,YD ` p0L+fqE-V-|ecA0` [ ԟk ux࢐U#TY&I%>C cNLI ,uѦ]b >JS4MͮL_bH.ђE$?8WKJa-_G~'ӉlXfD8@8A_qθemRM!dx|_a"G0 "TZY)[&bY_qy%"G& &a&b&b.&c6cZ$ ԐZUGVM]Eدя1SeYנ(9\c,Z ӌZIPbF/A n&#-uץIQ 9`G>De 4.Ʀhٖh'm#CQN#x\ѝW:vm<%7>QgM#x=jv>v[1E t9])OX1dL&Y[x#ML,j:Dde_OMm}6!%աE$އm&lz.QXS4ẻS@e>Qq@e]LfVhe≘iY@G٦ŘZ!ԄOC]%a***&.*6KiSf&Y"Ehb\&z@2)ULbhZkZ+> @onPeQ#S.b 2J`d Ht>#Iu(NA`֤yx:۬%7V$͗;ͣq+~}}^ `.kIFۀB DX 8hQG(8fػ+2 }̎v Ob@eDhîTKRím\PM žM =>*c#ѸY'r#r,Ovnz=g,ꦮ(ThI"Va|"2c)]_ٕf/v~/|IoYޭD&k"'*E̩Yì/qP*UYeh`&, ȥE q`#쯚_'y MŮB\ j`4Vp $ v@  9w|e&'}ϭ_ .l k='6 0$[b#Q]>G9d̰7 5WKFh]]Q#9ܺ.qJCwN$(NoALjwR;= ~aiȺlBqf1RQ\T"IĶ(Ag#D`I0AWԞبbY倥Yא6T\HI-E\1K%p9D8UGHrȅQ-dm78399ŽsԙtG(fvEM].`fEdib&AW:c,b|Uoj2Btbecw]G`3aH4o"ޛVäCBK͍zg B/ Duխ p>g0Qߧ Bt䜗?A4d!޲L$rX)1Ar$y$A(ѼL3UWu*"}=U9\13#!m[mׅUqaGV$75\5QO"^݅%)E~5,i;]b,@–^j,/-Orv"%OIyJTŎ6"\& K57lvyt+uW7vgvo7www7xx7yy7zz7{{7|Ƿ|7}׷}7~~7788'/87?8GO8Wx6Ga6qUމkFk"e/iHZ pGD/QPJRg牮ڬ5DdH%}K~*"ذ GR"3yu{lnU~D)MĈqpu\#=&=(_u9@]4-ҲƊdvq#dJNz&T~P7Ƣ''%J<9 \9zWZwy S1VrnJP-!KV?]DF2oRtLx7?;GO;W/Vݐa{h?'Ɋ8?sՙwclJ4-gTϢEᦍ;Ȼf[duҋ~q8B GHLP׹wy3|pEUĖgU'(dլļ)w5<_?MSֵҟWv8fjR: 0v@UCRDUMhHLcf Vi8׳ r e%x҂J̼S0cǓY-E KA3{go>w>>Oqϓ"(/XMn[D!]f@8æ8£KZP0p/W7^c U,4]'3V G v|8-w{ ywh]2I)5C« d0@pp@ FHB"8QnjA~"BH'QTeK/aƔ9fM7qԹgO?:hQG&UzbD 2n(`l zM8AYRzădH#g5K`T`Y2^qcǏ!Gz 2셐ކ f􊝀D~@@!v]ݓW/~v;2"O/2L t@P ) 1P 9A QI,QLQYlaQiqQy R!,#LR%l'R)J0#l2,3LSMAKJx 3LXJR v!1[SEmqc(3 ػ#2h< @7|TUYmU %$hРTKk:pK !8#T_MVemֱkҮzZWU@X5vTMWum%YO5j׃U֪ڊ\rEAw .ոtJ/mc3;0rK9A֤@.QnVHNaYiqYy矁Z衉.裕ⲽ|3<о)UtZ 7bz!S:έ&ܳ?PC3ƚ{|2 ".= ӷS@RF1K Zt@pAZm!v ^ w\\iƧ>*M#7 뭰ݕ#U-aVAۙoA_oz#hVח_'[`2/%as,!h-# $-#T!A N1A nAB.;}1>'# xIJX+hg^d>IԖ< CFD%,56m*p Bf'm!Zg͉bbVP8uӈي PvT<.}lgXڐ _Ee'Yay 6%{%TFieTJU63~/;S BW = ;)OHAo&M\f?P,KmnȩD/Dld$>B:xAOP4IJ4"SK?,OJt0e>`{3"Db)L ?nc ԺVYњVmu[WΕu])C6MqAU ;BipqIH_@&!rנ*]J3ZgA&АB ڴxQ-|ⴲNk-U[zҴ!ioOLz#uGqusҔ*NXhEH'@(Pt)jHy!VGt*[LuJB݉tҒh3trLN-.&`3(+HwiV/5}UMqaQ˲ *N_ϴ+qfOkAļݚh5+s,56߁^\KoNXF",MoF)=AU[oAZR*#dFu6M!S hi8s4O &`zɰ˦AQt? /ܳ] 碱TTJ6ވ+TyF-"}7dÑҔ@5I:/e}f5Klt|!EwkMSCeE?rLy,|4?Ksx%^;q{ެ|7|']'R7&/Q6ruSn^}SLoLr%!Lw.D"h7z/jȈC^jŲ^*5P Æ oMl/NpC+a0epimq0%tE0k&K-ƙz(ٖF/H~o4!iJq#לL%YoQxln͵nMvgz>"pˎ&f Ub[SvW.(p)+ @R)|:x;˾J6W%i„ ذ,ΆǪG:g.x!b"Ejn-pl4њ`G\b$őxIq0V#"L/Tĩ8 lOجgcRQBJb6e@(74nK~ޑ@$&6b ".cȶn!aLlzM؃>? 2 A$E@njpj2>G7Xb*ub*#(+=2,r,ɲ,,2-4J-2H|fH &0+#@0v&SXHzh z>* -%SHT%]bP (h )hCno`'6od Ȥ@ "$/B|pBRV܌5W( I1!3B 7Fޮ.Ǧ/xq.b6s mɹ,")AP|r;Et34iLQ| 都C/itB t OX %!CW棡B"n.-4$JVhR8.iV$A4HK.f.^Z|(o" τ)ѣ8(C{Z:A4Ly,ŴLLA" !,9)p22vvv  eeeB AAAHttt&&&MMMD( K ؓpppBBB9 HHuuunnnDFFF;a!  ߜ###=== 5, Kߜ 9YYY@(((666 +, aaaH@0 ;;;wwwzzzfffߋC  @*\ȰÇ#JHŋ3j1CIɓ(Stʗ0cʜIfɏɳϟ@- !ѣH*iS%.JJ*RN?Lʵׯ#KٳŎE˶ۣj׾Kʸr˷"^} SˆcKUe,gL礗 jiO^m2gְc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)䐄ѠHfK6yZE)gTV)ĕeY\Re dcZfg6)٦bo sV3g`{  Uz`jW =4:Lp "aiXPç}0KH @Є  %+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:xxp а@ y ra@$AX l`X PTA *X BQ 0 V26Ph`epIx2 %AfD)+@ xh*R`H"JP 5P6FGR))5%%1㿿//;II곴++7Q>?IZ[eQSH*\ȰÇ#JȐ3jȱǏ CIɓ(S\ɲ˗*;͛8sɳϟ@ `̡H*]ʴӧPJSjʵׯ`J bӪ]˶۷p`0󪃸x˷_IA+^̸ㆁ3M˘3kޜ40TLӨS/ \Ѫc˞MvU'>lS Z4lȓ+_2kq7NٻD{|fӫߺt˟O8oW/Ͽ'x 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'p{PiW~Sw9.p^z樻ꞷ`i.nhлc/ ^+O& ,H W@G IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺalgKͭv[ӷ p)\GH{\2s\*ʵnpy"حn?x7t΋ON/xY^3 !,922=>H" FGR))5%%1//;곴++7>?IZ[e @00Ç0|HQ @1ʼn7B1#"z$ $JW4YeJ2/BhY&̂9/Z MA/Fifҋ lr偏JI$ !UP gP A`H0чx`C .8h\eE0m^ly3!,'922vvv  eeeAAAttt&&&MMM  ؓpppBBBuuuFFFnnn===### YYY666(((aaawwwfffzzz;;;H*\ȰÇ#JHŋ3jȱǏ CIAL\ɲ˗0cʜI͛8s$` Ο@ JѣH*H@@ϥPJJիXJlԧ֯`ÊKY\]˶۷pMVݻx˷"ݺ} L^̸ǐ&4˘3knXʛCM4P6ͺװ% M6s[sZ ޻re@ ɣKNjSr PmB _Ͼ{._B'NO>@6- VheNxvWz($b%H"0(L.88Q6@.cAiCyLMF)eONiV\ c`ߗbifwlitfxiڝz矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:vSH@Ѐ$%*P0(~4HA* ;DЁxA><)`P H@dKbT Nc*`?OwQ `@p0@DZH(Rul H<LԗeAP_g?!, 122    곴@*\ȰÇ#JH+jȱǏɓ(Q1˗0c\R͛8)Ҭϟ;yJePE*xɥP><* SX+WUJc&i+o#S" K怿@@o. X@3D@f͠O>(!ӨS^ͺװc˞M۸sͻoN\pō|9'/t^Ǟ]v*~x塞>zu<}ԧߗ]~'{!, O&22    곴H*\ @#JxC3jlhqǏ -:Iȑ%Sf>;уW/=y_?}o?~'H&[r b`ya~Xa"AءR#bX'r(Y-d-@3z%#1`#]`IB:$?5dB "R\t %aC@H^~90Ee iPfEt~i | :h)) 餒 fR**\ C i0@ %e*@ҊXÚAlb ,4a2Jb*rS[$kK:-ٺ;{^Aܤ! ~~%Y4d@VBl| l, r'{@*S .^O5Y?qZ;|ЌG9뚷nݮ^;}뽻 ;O'7_=[=k=GG.瓟/{o/׿g;t/@Y*`ހ,`>N-; v`A< a U=0. eІ5 u5v qGN ' ,`(j-bB"Ő )␀!,`22xxxxxx  ++rrxyxymm vv ``^^iiggMMtt//QQ<<OOVV55 :: @@yy2 y T/0 qqEEeoo qqyvwHÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cTHM8sɳϟ@ Jѣ m*]JӧPJJիX2z3ׯ`ÊKٳ M۷pʝKWڻ˷߿0È+^"a#KLexIX$ϠCmq0ΤS^ͺ\ӎMDak]ȓ+OMУKԳk]+OO_Ͼ#O}!οϿ=h k:4 6`d` >h]vpm$hw"nu,8T\(45@)>*5HXI6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o篿P ~ I@4t  I XxG  9U@bP@@ ,СBC*bRPpJdpQ\(+PY<C n &^PF$b pp8%33333)22111122222222222222224488??GGQP[[ ddmmsswvwwxwxxxxxxyx|usqpqrx} ׂ ߿&ڼ/ֹ7յ<үBάIʯNIJTTUTQNKKKJJJJJJJJJKKKKKLMR[dqy~rg^VOOT_gsޒېٍ݉ކ܃}}|}H*\ȰÇ#JHŋ3jȱGBB)V(S˗0cʜI͛8sɳϟ@ ڐȃZD ӧPJJիXjђlڵٳhӪ]˶۷pU(ٸx˷߿C0+W+^̸ǐ# ɘ3k̹R)7uӨS^ͺh[˞M۸e^; yē+_μ"Nس'pO?PMzj«/Ox3?(`\ 27W F(V Ni H}1ʉ'jS\"Y}(8T_b@&F@6iчo @PV#Ȥ cVTilnEfim)tBlp֩|қ~*蠄.h&(.裐hVj逓^馜Zi*jnjꩨ~Vjꪐw竴j+\ު뮼Vk+d7&K.UtFk.lvކ+.k:nk8 @,ξ kzlpC+<',G|w_1B KN;qvzo&KM]4kpptxN3u)/}p*tsM_m/Yme 6;s0QwC9#_< V) &,a6G?p$Wa"5Y~ xm10 ƕipHGZͱxLGQIHJ \!HB-##IIFFk&u5Mz2L(Q2G<*EUrB|,1uI"erTd-t\ґ,/X f/8L3IMLؼ5MlL7INU)48 :]َ X:(!| DIİs!x9P. =G=" 4H*BP 'NJ|Aϔ#仄5P c'-.O)P84%M~ЧTSW 4KĻZ+y(B&S}>9LJajHy|R'Q>%5YZa~9ۙ u9o3,AІ2}E3ZɎ~4#-S.4UMӞ1CQZæ>|Sj겺հ}5+YKֶ's]:u9-p<6eWΎ&iS־61_r۹6g)q^%}u{~'-Mһޕ7#}7N$^ȁ<?x<2u|8(񉷱?#3ōs\C.r <9!.ocν{69rs9Б'Fғλ3]wN.eꀦ:[^sn=y`?ͮq"m?3'4gu>$|xY ~N/ϻTEO<׮ͫYJ.zN>=E՗G5cն}s{Z 2 | (*O8D"a Exʯ=҂Bha'Fl 08؄NA}0 :XTl x@'<؅Ԃ36cr}:}n{(PMx |}M~w`XX} G| |7} ;C(wW0/X8UXHS>;s!ԘPppȂэqXHZp^XwXЏ8uWPiؐ)8ɐwב| Ml7R&,(², ,.{2o4Yw8Yp:ד>p@7DqFyJyqLٔPqR9 WV9rX&\r^,brdY2whYsj8זnsp>7ttvyDzyt|ٗJt9PW9uVxG1Y(YrYL'z2I'Й999o瘳C` y. Bs A'ʼn9CI-ͩ7CƩɝdI$iɞ1c =Bp5#ʑstʜ Zc!Zr Z;1$*&z*,ڢ02:Q6L <>X#B /AZqHJJѤNjMDTJ*SzFZ6^=j3 jKdZ;clMYr7qZ"%wxz7R |ڧݳK*gj󧝠è=ڨ8Z: s8:S7~= aJa]:ʫ`C& NCĪzJgwڬ¬:{Qؚ֚q%z)Zkq@亮BkzKԮ:گ;9; [,ZOqK,{&h$ J&{U2*K,۲r0{$,;S6[+5<*;1B{a Z0)HJJ BNP1TV{Z[\۵`b;Qf gGzԴlhrt[.zxz4ڷ~{:;>{˸븁 ~+{Kxkuro˹li f+cK`k]ZW˺TQ N+KKHkEB?˻<9 6+3K0k-*'˼$! +Kk˽ +Kkʾ *Jj势⪿ʿ *Jj͊ʪ *Jj  *›J˜j•‘ŽŠ† Â*}Jxjuroli d*_JZjWTQNK H*EJBj?<963 0*-J*j'$! *Jj J&L)~K< zȋk(0Lǒ|Ɋr>zɟ tRɣLr )Ii )Iiɉũ̷̼ ͳ)ͯIͫiͧͤ͛͡͞ Θ)ΕIΒiΏΌΉΆ΃ π)}Iziwtqnk h)eIbi_\YVS P)MIJiGDA>; 8)5I2i/,)&# )Ii )HhڨԶի(աHR2e/@`? Z\-_05 $1 % ۉp!eufה}Ӏ P Po-s-v]i$0-`ؐmO"-M٪ pڇ/}X=g/p'f? Dg-֬ړ"0|M F۵Xڪ-^ 03M܅ؐذ3}_9v AĽ-ύ!p0ڰݼ( ~05cO]%}ᆍ_]%qc05= N0 "Aa= $}}c=] ` tbՏHh{rh]TM(FH=h4+! 'G'%!;$jN֍JaoΙhuuް_!KA{nIg~舞芾+ 1! t&0  >P;5괥 ~ UOu V@Q.1 pqTa >n^%nO;V`^e߮]ݾOt ^PWtVTX[.1OR^N^O^QF ^QU( M1NE p| %NQ \%>(V! ,}#//........0000111111222222222222226[IHDA>92*vl f _Y R KE@{2a H2   &4$*89S>gDj?}6y/$  }lZ$$B**,..#333333332322222222222222222222223355;;FFTT ffqqssuuuuvvwwwwwxxxxxxxxxywzw}vxxwrqmllkkjklmp rtuwz$~,39?DFHIJJJJJJKKKKKKKIGGGïHȵH̷M̸P̺S̻Wͼ[ξ`ѿbֿeipv|~ځރݘޝږϚġȷɨ̞ϓ҇zke`UKB<<H*\ȰÇ#JHŋ3jȱG˟_VɿJQ߽gQ|hS3(D(asVDfXx02ሿUHх$Bb89"#k&N@i 8g=JPhIE%dMF`"0`y~fb]BtgyX{М|*蠄C袌6С %褔V:( Ij馜v*$ i騤Z jꪬJ ꬴzj뮼tIg6  V;Ikvi䖻k춫 o֫ޛ/쫿 l ;pGWl_D" 4A ?l d&2H/ "6<Ƽ,24<"B̳ϽKEcHt&-2@tPt@Ws5,=njk|6[-q @rw LK7-'w7NG.iOnU#y砇碗n:ZW밃ѿn{W[hޓ/'7鯯> -C(-sS<ot>(E;8 9q0C0v&ºL4N©N: [k' q O C/pK& ~>0B$ŃVȀĉvEȑV1}*=LlkmLؘG^% O``Elj+?op'>j*k$(G/Q2%*WY.Ur%,g9-YƲ%.w+]%0*a2&2Y)e2r&4y)N"ʓ欤n ')r̚¦9(rr' }'@CgԉІMbC'*!Rh$юǢ i@*ҒJ=e1v40ifx KKv#y8~Tq̴7m@$B4$9@, T M U`TņT`ԤU!+ tt +Ӹz#lE0Rը0\Jq$c.i^r)6rWH5[1QVzcUl[JRMiAdAWum_Zط(+K:٦d0v\Z֘ -ibZT浯1S*}+6ʃ 7L+ko hu[6லP:Uͅi}E RR)>c]n7z͛]kO\Ծ5ưd; zuxHpbRQ.)=H-[_ja -zg-a\XCpdCEƣ1A{U @^LT٭^T' b jqX ȩ}f8+V~ Mh Ј~ˡh,ѐ.ˣ#MLҘ.-L#Yjy=KsT5a]Jj˅R;V+z괭8v˫yؑ@Ql2앦ȣ]6q-]/[Jm{;&=q;#>)uQMoMfd5|9Qx{Vu;&~#.quS8ŭ{6C쑓&?9SL~9#-76O4s^<>9.h=:KN(ԣ~ѩS}VzCr:)f'>ϵn:.rҽ;޻g~&~?1a2|(["s/;?ǧz?N;3:<GCgnӀ;spmm؁!!FaƧ*|,؂60h:28S6:8<>/1BHsDX7wHsJFNHOPh2 XrQ8XZhӅIP,Phk`@btdX Ah@xtgPqQsH ky/X7xfy膎uXX|nЈHPȉzXu^qwȊȊg H[H-芈ȋ䋿8(xhxv8Ĉh0XHHijd3不yxvhXxOxuzԏ yP؍ɏ(u PIy YIqxI$鐰H-$ D QD )d/ րQ)X aM3^5@;C1<`B{EcL;mFRKpQ[CX+iٵ^W d[f{:jki۶pl;v{-r|{e{ⷂ+;K[CmӸ({ W-۹b;MZ Sk[Ẹ+rċn{:bkۼ얼K";Q oÛpǽp(0⋾;۾[,[)􋿿;1[$ػ \̿\ ܾ\! #̽%'l)<+ -ܼ/1|3L579;=\?,AC̺EGlI}.Nб@5!/.&1`"o$->)N ` Q48>A. 7pA]n2!=E$Pug R^m[ ~]ekGN6 T>unpw`Enc>V^a0] +h |>k!^7a3|L,=ZƎȞ˺ՄҾ^2~R1—AvﭫALn!*/' ?_T!] ` XPT TD$pUBe f"APaK]l|tywxyx|yz{| ΃ ݆ } p e [MC:1  &3551{*f$Q# B&5/2222222222121111110000////..++&"     !1'C#M&Yak!s*|6?LZk+z6CKRYajw|~sf]SMKJJJJKKLOU\ĸ_ʻaμbһc׸d۶eڳ`ٱZհQױLѱD̴7Ż% -D`ozߔ7H*\ȰÇ#JHŋ3jȱǏ CIɓ(76Zɲe}zIs8sɳϟ@MJѣH*]ʴӧPJJիXjʵР`ÊKY.[në^ʝKݻr˷߿ È+%G4.L> k̹ϠC7L8]~+.װcN,۸s<߰Y#ȓkͼЙ+N:Е"wɱνwOӫ=˟/ּ7Ͽ? ߀QI0H( E(ᄢ*DY5ᇦ hbC%1CS$aTJ*Ph8<#DH&IP~7 1QTR4`BeRcQNLvpWA*` *eI9r&hFmr梐Fj  9|RCRCEjQBtLDZ*Qgj Z*Qbڅ2FKŒP*ƒ EǦjl5쯾0Q?:GaK뭩H .JfCke+E(R2GP=*gvCD)@ l CU2Ѳz3r̯jm 0(6pQ́΀& ~MpocVVk+pn!U|ŰpË$XHAU{W@ `}[{2-$S+.v_¸3h04gDQPQ 5@h7^jRZ,-<28lY$!$ I|0\+-zM\Vl^bHA/ĞwF(]YU6Z$'KY!L a cmМ/hZrq< b _|%.kUpYBB8)Is !a*(5Z*aI0\}`Le9iY o] !vu41ӤμJ3MTs0X6 b?ś|R*Ua"ܫW yTVVQ e(Ԫ鎑tG5eNYG햚TFRj>-P7P0Q^몤:F5ӌό`ҊtL r%1FRNSk\Pf9;4gtϪ;3ٲkXʺY 򒖴ha7S{Fxm.[5"BrЋVW[.j0e I uk˰&),E &ɻyџp`d5N^}CˬJ:OWO^/ڳo[Utc`7i*%F`@u`TDgi4{,M쳢6ŶWzϼ8>x'B@SrK50lG&U)đ¡L9!+cx`P@PHR*LLZ TjeS+G8_%̀6L#@:B~ts,g4D NҠR_1W=Qհ^gTHմuob^Z`{RNufMµe[6'2l{ Mn vCvsM!쮷~7 ɷNW;KxB[B{ w6~(O m7I{0gN4Ϲwsؼ 8ЇN  їQӧNշ C1FatX߀v1U}u{>yz_ם^7nKg.}|1yC?z!s=`}M'`@{mo#NMvu0^S;~WB }|{w P/@ L.Zν d^+|+l0tv~瀙zΗ|xN>pYΖhN`Ε^XyNPΔH9N~@Γ7^>.Y붮B뺻.>FNŞ̮Ү^Nھ{8䎏~V.>+n^Y./s^ <Oל "?\&o(,.2/4_|8:>@=DOFJ:P?L?S+VUN\ς^(bod_h/gnp8t?vz߀| _?Xz~_wjo~ۗ?x?~^踟_~?ʿΟ>_?^_*_xzA@ DPB >QD-^ĘQF=~RH%MDRJ-]tب[r`ęSN=}TPEETR2idUTU^ŚUV]~kiȚa͞EVZmݾW.ʱ śW^}X0ӺFXbƍ?fa%_ƜYfΝ=JeХMFZjyEs$ZlڵmƝ덱u\pr͝?]$ʥ_Ǟ]vc]x͟gbxݿ_>Kǟ_~W?$@udA0'Z0B /0C P 71DG$1#DWdE :_Fo0ƇfıG2;1H#D2نlH%2J)c!'2K-\ʅ2L1$3)/L5dMg" *7N;K:34O?=$PC AeQG_LԠERK-I/SO˔M?%TS uQOeUWKUU_V[UuYoW_#3NXc5- a cYg6((6[m" v[q%n \uewsC]y7wA^}W{?ʷ_&8#37݂fa^bseb7\w8d=XOFؒSf^Wv9fOyfofwO{:h@dF:˟fi%v:jqzjVjC;ll#l6/m߆;㦻n;oq{oƕьpQp,q<0#&!ӟmfDtрT<A P!" ehDOV9hFQvL8=:Rp'IQҝ/Ka:ӕȔ75I#@N43O}:T4@"jR#IJj[&=5WEMՆh_}UdU*^5YњV\u[WFuU]JTէ}+NX05aYXŢ%c!QNVE1Yn g ZiQkOծVu;aΖmř[ro M5.2\b.tsu]ڒՕuJn(^N4y)^BU{kHW_=v`VlF/X v!a-NVa ;VAlDX%61Qb4tac5FqLB=1d 4!d%3MFL@)OU2emf1eFߙL>5|mv3g͙Գ󝡗g=3}VޟmJ!Qsހa-kTZh4OIKk5cᴯcH(1[Mh#P@-m=ZM; #lylt/{ ζ@Xc{nUye{}n_ [6Ʀi[ VwMbK\ ހ*+{&:iskޛG}k`| c\p>".{ȉ $|&2Ų h)'C;Ϗ D7mo|4a>S 3b16>sW2Ϻ֏9ntlN" VC񢆶!ˣ TnZGzIAz{Q_w{m4z^Q}mm/)ϼ | 7␟we{Ws7on9b;2^vG?h9O?c-;>dt 8K}؀rXvf~hԇ$F܀pjdR@Oa @4$l &v8#Ƈ `&̄r4/%PC{B$rj,l+4B4Ah3B'C:|m XA h9'qI|KLKJJJIFECEBņ9Ӆ.~%w"~!48ޕCڟJةPػURUTPIC+ ||zyyxywyw{vui_UL@2w.i/`7S?M@EA@> <; 9966442212121212121212121203(-  ,:F!Q)`,l"z}%1 9DHNT_hmmkihfcZL' "*.2:@ DHIKT^f k pu'=DGJRXXV[ni^xX~TRPSX_cgnv~كڈێߕյϷأޙۼH*\ȰÇ#JHŋ3jȱǏ CIɓ(SZòK9ǬI&8sɳϟ=5 JѣH*]ʴӧPJJիXjU(Я`ÊK,ʗ.-ZQQsMpʝK.Ǯx˷߿KÈyqmͷ#KLC3k̹L-MlװKM۸7ͻ-9ZYc^μ˓KN5ˎTνXOӇтv˿XϿJ߀7K(DI2J~F(!h0DP.t&vއ$PLPL5Ĩ˄4h^+bZN#yE F/a nTJFQ k`Ur U;{AK7j`T,< pX^`*wӳ ֋o"` ˶:{ !Ҟ* , ]Gd%Eq3ZKydGW&6 GhcB ^eM1W",m{#і4][̚6FzYszȃٍyչ=kU<6ȋm%'npfjzemӂZs4ZnD\68jMm[TUd+u\RXUY-̲)Q7$FD -zj`ɏCa* ؍Zkwxb8ze1[D*\Am0N%ͥQۚHqۖV|B DSB\Hh=LeGP,ZT\S\X" qC^0Wb a B n"}nݕ-> 1 ->v ףxBDn"NM9 bMC `Z.߈xPxo恇xpr vm~}סހAz煞㴜ev揎!9xzNAo.Z8N>ZŽ^yʾΎ9~ڎ>Y掙>^yΗu>m9t|J ?u=qh)l_Ob$/&M*,90O/?@Y6o2L<;B/D_}H:NJT/P Z\`oS?,fhYlkrn_Lxzy~O}k8okʙ??WXҹϽ_Gx?A߃983-?'XƟρ=_د/[ϼ[GO_zoSOVm_!!G DЁ  >QD-^ĘQF=~RH%MDRJ-]SL5męӠ@ uTPEETRM>U*I!}NŚUV]~VXeڬ YmݾW\u ǵyX`… FrG!?Ydʕ-_qqG"2ZhҥMf#][lڵŪިm޽}\CM\r͝?~8H ɣ_Ǟ]v3Xx͟G|Fݿ_1_~"#@Dp-0A0B y['0C 7p )CG$DpOdE_>Z1Fo1SF2H!1"D2I%,Hd2J)7'J-Kʮt(K/$L3S!1dM7|*̈́քN;3&93O?4ЋO}S+g@Pt4< C!:QHE1Qh]GA:R' IQR "KeR 3\ԧM:TÐ DE*aTT.CuS}U┪UUR9am[+\@լg!YvV%emk\UծizWE}}_P5l@~.tcYƓ]e1{Nnvl7Al4iZ6=ka;L.q[o_\ᦒ-qI.7un%HNu]wG5ћ7kt{_}E'K4` !C O 1n+Ob%QA-vaΘ c=ߏ?!~E6-se)Uޕ=-oz]獙3󙏗f5mݛ;9ϹvuUM{Hh }џsh>-Z1iMw҅t FZԇ%uL}jŦSfuc]]*Xi]׽.k lvt3'le hm6iOkն6ְ=ۘnqƮ@]u֋@ rH8y[ ?T@IX6;v9('}':2ogr(q7H$P[r8rpAHGt@/ӛk.]u88@@NxaC<ys3{8;ƺ9o|'A֞9$썫 'rz; ̿z=_ݫ;';u\8 ~_&pkn{ E; ox_~x'ƾ?͟7kG'@,3@o*dB&@ l@g $&$A!2{XsXBPppB4z<pxCDI\8>8%;DDP=rD@ĄD~XEI\E^E~vo<ѓ?Cv kD#v@j,DDF$iCzTx[FuEz4G5$Hy\#6 EtE@$l7<<,vHC5DBZH8D3:C`TDucD=dFNlC:$D8e,F\ɑ4!,5k2121212121212121212121111111111121@*Z{xrl_SKGB:+   %/ 7(A0R3_7lB{K̆SɐOǘPƠTƯ]Ⱥegged`\J7)|l]QI:)x\; ! (6AFIA6''(* ,%-,0011111111112234589?=FBMJSS[`e lprsuuxw{y|sj[OD;.  $;EVb dilp}*Ą38?CGJKJJJJJJ>#ܥ (D]kzӉܗ!H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\(˗&jGfn+sɳϟ@JѣH*]ʴӧPJJիXjʵР`ÊKٳaMpʝK7׻x˷߿LÈ%iM#KLl˘3k̹禕CM4El׮?˞MۚaͻXrM񰸓+_μyУKΒFnk]o'(.{𡓟O}s(`eDҋBT 5~Ck5B1vX$5.0t.FuAF4hc^0<Q9(hvH6$JCP/EQg7vOb*Ehɝ#pIW5IaVr 柀~YfRdF&cFJС EFIPVRHSTʔ*QUELJEDR*4(*ZTDS2l[jc4[9"q2{lzFePm2+﷧"uº+UU .uk5(R2uGL)jRQIHUCԁFGI/J̩R`0, \ 22Ln3,lD|4;.C48kUwl\,Fᒬʽ* 뽽" Ti]wUV%w{w@Ŝ_!f]Fjn1nQ'SjzXnH{/UW뾺ր/v®*s{/?|Ǟh|3kR'We|fy2{j㳿~ Sn"Q\Q_BԞ`4h2=-| WW泠E5MY`ھ=5iB7=Qy:5zmz< +>A10rx >M `Eitp#2"F!Dvjh}ĚA A2jҗ Ņ+vynʖ(,*/Yd!QCkm4AObO˚+RI ldV\f `K-.ӋI7Є@'hZ84Hѐa mhUN+o(Z@uy8*~)Y̗+ Ho@qas9zeV E_̣*y.~1qaDRhNS"LjL_͂ uQ14۲&ә-\-H̗Զ0+ Щ/}YU^z5X!UUT֬p*j^}5K8ʮܵ+36XtK#":@dQΐӢSGR,ʣ۫;V{l64 .|],\XRCؚ=-iDUT;̤xXy(5bկƗV[V2eFU00Q(Z "QK%*~s!W<2oW(Ds(bWc2C ÒZaJ4sǻL"Q[w"k_"ȵXՐKdE-"-%Pi&#C0;1!PX'BB  -i:C6xBFmpNe5JN3e}]"5;͌J $hAvL#MHҠPZ$NWS:=fH_M댰ָεjkz!!b;Nvq~`+9 (h[5Nmmj{4ⶸGml{=t[2>ȹkv̡ o{~OpI o'NG7{뽈?N@F0ߍ!8\f^s@Ix.9HO:H;PWӣN[S-w Ӏ@?!}N:מp^U׃@8DxtBXH7wJ؄Nh~1d3TX1DŽVZ(pX^օ`8 s `p  :dxqQfSXz`h8퐆{Lb8zhm(xF8:zXFun݀?cg@xe'rNj؊rp88V|0rz(x1Oh @H38$Xr؏9y ِ9yrQّ  x"y(o$Ij&.g094 2Y8q:ٓ8ɓ>/ BY"IFJٔɔN RYIVZٕȕ^bYHfjٖcȖnZrYOHvHzٗ?ȗ~6~ x``z! t } P @I-0y1隵)MI{z 1 r~)ٚ@9ùЉi๜9)yvЛIYaךP񙝞@ 9ȉɝ ˹ٞؙ֒` t| )Ĺ*ĩ )Y) ) iݸֹjw)֩٤'J[:EjAQczGIwPjtIi F Pjڣpx9?zkmuY,8:fdA M *1*ɣ6)٨ơګȫZGƚꇬڬǬ -j Yy Wҙ9j͆V8^ irɭњܹ 4 Z}ڢP:گqˇ٢jj7.;{u" u!;&t%{*t).s-2 s1;6{r5{:q9>[q=BpA;F;p 졮G۴' аN;RKXQL^xV˵_; pd g+jǶh tvru[w!ҵzB m۷[Q'sk{tA׸ s'Xp^~kq+rpy{Kp}ۺo~;nkmk;lѠ[KoǛ [;[ּkkmûdн{5΋i@f;,KdEKoۿ?;m{p| , q )<|Lq$~\( ), +0/43\8l7<;@?DF!r#\J,sGLsIP(MQ\9OlZX^\]b Czp= Ƚf>`jݏi>W^4mx>` 0 pt@p!Q ^ᛞ"ۣ^ꦾ Ψ.ӭ N^3鴎{뼮,ި^Gzޞʾz9n~Nmα>,.^쮕V.^NyHZ.z߾: ??C("$_K('.* 4ߐ6S9:_<@B?\FHLN RT_}X?Z^`=df"j_l(pr?Mvϋx|u?ψ_{x_o?^8?+k_w??JX?/_:x?ͪ-8ğp~;+ Nϯ[? ?gO?o1m DP\ >QD-^ĘQF=~RH%MDRJ-]SL5myS`ȅ9}TPEETRM>4k<JŚUV]~VXe.jZmݾW\u޽8͗Z}X`… 9M_č?Ydʕ-d˝=ZhҥmJi֭][lƝ[n޽}h{UōG\ک=f]tխ_)\5qݽ^G0@oD0Adз5:A 'B {0/C? 10DOD1E]W1FgѠ-zFwo(G$H#"!dI'-ɉJ+R2)%2K/3LK1D3M5""3ׄ3N9͇ޤ3O=";³OA%? PEeC:QI'GJRM7KʴSQG%5O TUWeS JUYguW V]wu[!ȵWa%_-6YeH6Zi1t.g6[mrv[on%\s\uetۅ7^yWzw^{Wz_mk%v58aExaa'XX+8cV/ָc5cG&4dOFYNSfe0Wv9fyfofwYE{:hh$h/iZ=j즶:kzkk&5F;mVm#cmn6`;o!{o~nppGWp gNe0K@S,$1eLd63ʄ394hb&{PMnRuNreD]ΙNvXhg Oj< 鬓C!:ѥH5E1ѠhʼnGA:ҙŸ!iJ[ӀG/% K SVFiN-cҙԧOը~B(yTMjCUdUU Un]QV>5YsVҔm}[RuuG׍_'X>]a[P.u,>!xNeљY͒gAMю54Qftk[mqJ6m)O4q/\N}sHNյ ?n{w^Α}yѻFuo.ΗW}_>]|Dx6.7tga ^1|B oxA 4'b?-^a|@x5pd!E^ߑ|>%/y|MvM׳򕧗e-?]^ޗ|<1yxe6Мݭ͵sgg9u^ݝ:=yt}s񒊬@vK-4E-ѓs#iI7Е1]VMoZAjq5jUߕխaWY{[׺9Jia? 5ǖ걕 e/5Ї?eCӆ@ z6; Bxx~Gqε lg/[فȇ5$r35t|xߞôCzU!/P?nCz#[P8=ogDNo P RrD7q.`Ɵ#;>w#7 >`2y_$渶gD;J^uO8yŽ C[֙5V{̽#撈8#^xCtqw|:Ѕu#>H!tCl;x[ڞ{sy΃ݨYmtn7>}t6A o5oj>~&4?~﷿3ÿ@^lDn8zv=<ӈ lv T-z @@d 4%SH\A !$B}~p~؆zӃ$?@B~)DBxfxBz#"#{;w}p@0+LB^h'\$C}PBC9C~C^/ԃ24=#4mCBB$C~*,HC8DC>,CxCDBBģ=4|j#:hDFITD8CNCP#-DMDDMD_dW$VBQB_+D\HEU Fv@fBYEKH<H5 I, G"DA ?:4-)(-9;?A&B-C4I9N=S?VF VDK@89('5/21211111110000113388??GGPP \fkzuxyyzyv{rj]TQQUUWVVX]c j nv}%ߙ2ٝ<ա@ЪDԲFعJܿNZkyڛԛӖՎ։ԃ{vpjd^YSOLKIHECCEFHIJJKKKKJJIHHzIpLdTY]xQhgJuSAKA>A3A+C)D*J/Q3Z2h=r@{DGKQV^dltw߯޶ݼ%H*\ȰÇ#JHŋ3jȱǏ Cɓ? Au˖FʜI͛8sɳϟ@ JQ(O"eKVGJJիXjʵWIS&d׳hӪ]˶۷pU!Sf˷߿ <Ҥ1T^̸ǐ#KCV\(k̹ϠC״pWfѨS^ͺk~M۸s N9be6μУ3oسk=֗w j'h^ÞN= GGg鑜o!`_@ zF}Wy},ׇ5[X4W0*U ^D6$Uȁ?'JP!{tY `So ]'3'*t~DBf֩FF'{jCw&硌6"%ТVj饘"$Af駠깩Ajꩨ8jA*Aj뭸:7@Ҷ@kj6&lVkgM+#v-V~+n覫.MVnk/Aޫco|'p/ß6 7*q@?@<|&Gi ̀l͈.X8gDzs'1C='x4t?C4'"s$Og]Zʝ,-[Mau\Ϗ#Em߭/ sK=Mxh_k? u|͆ON[Ԋȃ[nr垇.hn铕z>n{Z߮2Ӽ/~H <*i@$2 v WH: Z! tj`40J|,4 $"(rlc$dG'!F4&\a ]!vd % khL&;R"U$QA*eЀWpLc%"]*'VŖC@B;6o Ui0!6?IHAVnlNVE> DEnU Db./lYK=Y*%D~NI[ eĄ.fzӝE?-RgY6qjPխib|WZ8IâBɞRHzO6b$:g==eC,mCQ;~q{ZwN֠_Q0Y>ըj};u<0Lg e8\0tтjA)9WTq9gn)ϴqs9.F8ғ3=Nz.cS갾:W^5鱓f?Ӯv };*v)ӽ~I/=<3W(#S>|A3r<)׳'Sճ>}9c/pҾݼ=W&??~1_2|>o)闲֗$Os/~#15XXfjb³l;nrh?hXiFx;zs~X[}3?x6e:؈R8S5aQgQXs 6cphon-7gmf(Q(b`oXy~bsX˘%"CQȋΨ(טoO}!mXhܘ`HthY`7qg` XɏhQx(z*)2-) 1 {iո87ؓ$YDiN3mJY YO xtɏ⨐Yxsp0beȓ-nm0q)(qxٖ{i+ PPyyaG{y Hp tə?%a⸗2POby 8HP$2ٙ+N"H@Y4ʉGٝpiH@SĝiN49y'Ή0IvsHى3()MuM)ZMiMU*N*N#L!'MҢ..024J.6z$:L9ڣ@L&:$FZ-HвL,NģRJ}TZwX}Zץ^ ~`7dj~fz闦j~lڦp +r:kTv@u|Hx)Zrj)Ҩk:mozclکéJ':hR*&j=y媲>Zzazz<42"z ڬsj:Zؚjj|(:ZB芈Ắخ*:zݑPگ6:Q " 4 K[fӱ1$;1#{*Q۲0+&; ò68"$!\q(*.m$44~!dN>ŮUڮmn>J^.nXNWnnUPF^ be^F44 _nInIE +M/a q)eIYiOD91( )I iϸ,?,dDҶdx& . y5A/aX,Ofhjlnp?)Eg%v V%1 kUtTr0h!.F` fa | {fM5cdh[u0` qX`/_uou/znU{?`vW@?OX1Uү d? Z$&o8OOPI@P>; *DA vK(7+$ѝNR RJ-]SL5męSN=}TPEETRM>])P ,ID7'QU&tӷhZEj D U\uśW^}XpH?$TUk NGUjah;5fc amhҥMFZj֭]V!,w)1111111111111111111111112121217&8#1+#       >s__xYS G @ :| +v ph _Z TQMIDA > 9/$-$ 1-202121212121212122221111111111 11 22 33446688::==BBKKSRZZ``gfmlppsrttvtvswqzm~f ` \WW\[W O B<0/<Vg o v} ޴ص η"ĺ$',28?HLNPPNLKJJKJIHȝH͜GϝGОGРHϢIХKҨNӫPծS֮VدZذ^ܱbޱdܱgٰkհnͰu²zi_[XY[^bgmxH*\ȰÇ#JHŋ3jȱǏ CIfW({ZEK#cʜI͛8sɳϟ@ JN1&SbѧPJJիXjʵ+D( lҫٳhӪ]˶۷p^+vSx˷߿D L+^̸ǐgsl˘3k̹硩(&ӨS^8teҬc˞M!]ͻc]вȓ+_)qƛKNۅ QD^k={ D0Ϧ_A2gyt_ 6Y9(!_m }'yl0 a{!U|}ym@**rߋB8ֈ:ր"x1H&IJ6iUxw@hNfNLneM(#."J)P"7~u 8w@tHX 蠄jO袌6QF*餒BJ饘f v8r ꨤꞨɡj뭗ъ뮼ʗ+fK&k651 V{faBm+榫 R*okv$@@?& W?r0 g<O;&+'9P<2)|2.5<>&,2C-3J&Ӕ@2Mtմ;FOW: L0b[-Zq$ʅ t?&wx zw\|-gN[ex7NG.NOn#Ugy砇碗nzA詯歿.n{߮{޽.<o|/|: Գ6tmg|NO~MOk&&дϪ$'$]Rӟ@տz$;Uj @O5D3`m CHmo;%LaFq 3R5P=!qS0ODq%1BMb(*V̢.N^ c(2fLwШ6Vn#s(:ṿo>چ~ 䬞DAN<"?E:R3|$!IZr1&IX%=FI - aA6 -WY$H/QUB %JrT=NM.[QQ) !q::WIrPeAܙ xF)i|S19Nzpӟl;PRŴX,%)iNs$e,I_dEIQU -K}1Pq̠eLJJs!hD%:' p$ QRR5);QJM"r@0LLedu2GX "Ӕ=,SS`UkYSJuOD)UvӔ7uk j#[X*(hAd,MQV0uI2ػ"2GM\, ρ(` j@_OR}fKY-iOk0Q(Q-e-KV!eXa)hHeXsY݆2r!FcL 1F ~`' |`6$'u*a&VaRPn~ԛA@LԶcr~tbl\A/.D3x  J{EҔM{XG ͦ>Sj3a~5,YֶN1s-]u-l=6eϷ6m*h[;&hD8Q{77Gmq"pDBnR xmnȻם~dRo~<} {soo!n+1o?8 A>oǐwQn+WannC־/|='tdE7 _ׂMәu[OUՁb]G6ıf?Ӯ;|;o(ϰvw!½~{/<<+/ #S^~2yq<'/?S?ճwb/Ѿ=_ݯ?_?t?~璯|؁gf>-'r߸sw>/~‘ ?#|`ӟn?i<7%4_Gu hMP (Q uhMuhZXd!jH_ׁdD"8$HHPP 0 h@]'xs)GHz.ez4x7(Hhz0 eqVP6Xjzp!RHyW=N8z5rH8YȄfhv0(Ȇm$cHr؄kj{Z8vFnPqH\h^(Fte]r@XFvPK8؉tFquEx| gz0X^4c/(|(WZȃ؉؁E8Kh ;hטXw؍VDWH/8؈ȍEzqWX (x누(uH)Eb jDӘ h_V$ <= IL Б4ВY4l u>"=pUi]ԔZM #i`Dڮѯ ! 6I0 ۪ 1aKCk뱞ڱ"0+%/'#[(˲y*۰F7ʳ颳@I9ڂiH /JpN6VbؚB\^mbd[;hCjKֶn)g]1tv{z(y۷mi J K[>K,  P)ҹ "Kb +;({) * ۺ +[+++ )s (k{(H d|["[CEr'\{@4 #<\`%R1"(!\A(* .03s4|1:36@< EGI|KLMOQSU\W,Y[]_la% ].x uu G ` =ὴ "L .L H J潖2 1.NN0⧑.>O3Z&hF2^QN2 e5حaD.]J&0&X5KN^5>x-' (qn%Q]_4MNsn>̍ Ξn>ޝ~N^.Λɞ˧H Ϯt!ۑ^"`qua"L1 %>^~^@]Q KPKnPpQ JpSNeQUa#DK% ϵPW Na.@K+% O]p7oـR9/.0 ; S@7 PYTX O_ (/4'Qʐ`O`P_/RKsO$$~oQuoJ@]bJ5KOs _r! ,w) !!11111111111111111112121212121208/K-T&f!x|kW LBA@=!4((,r, i)a$Y"QE#<+/3!=K UWRG>, !! ))..//11111111111111112222222222334488;; @G DR E]MgQqTxV\bglrvyzy|xywxwwwwwwvvwuxu|rlaXSPNMGC6-'$0?GNV^ f l pvwy{~~%-ޚ6өDͳK˸NʺPƾSľTTRQONKKKJJJJJKKKKKKKKKKKKZmrh_[UQQS[achr{ܐЀzussH*\ȰÇ#JHŋ3jȱǏ CS(O˗:FʜI͛8sɳϟ@ JQWL$"̗GJJիXjʵWIQ24׳hӪ]˶۷pevFs˷߿ yS.+^̸ǐ#K(ǖ3k̹ϠolӨS^ͺїMM۸sC]Z 7Gē+_μ7"N؝G+;wg vOG+?I}X|Mg= Vhk7߅BF!iyhV:, 0 4a G-P)ZD *#3ҊPVՑ63g`V$%ECi&P/e;6yt4De֩P7~䞀yDyj衈&ZӠ裐F*iCB褘f>t馠*:騨ꂥ6t*s2ꬸm.t+,|JG&lc*F+-[&f-U"t+N覫Ft+Bnݫg@l,P7p +Wi[Ɖb|, <"O?}O$SLsD sM;|6 e>JtE2= L2Xs|u * ͳ+Cc" 8 `Mq~PKMu wfik #4F/~3(FxsN+gzꬷ.jnՎ3[,w/|doƆU|G_Wo=wKE}oE䟯f/?Co߯y<EeP@}Ă F1a.(XotB*c.1{P$!(îܣP@'b^T#mEA ">5$eX Y(}` !D# N  Èo XF1A"1Qz#rp A/}D HlBb$#6SK%q 02\ <#SI) L 8 DY U$b̗L漐fΌf)jb沰n g)rŠLЩvjg)z*Qy~Ή *ЂJx"ANJ <(J F7z1Zʢ ?=)%LҖ.iU*&"(NwJ)P+ʦDMwԦ})> `yP A(QU0QAPU@U}tzVꀭp+\*bU:*_P["W,BG50A3,P@4Xzh6*.ĂVh-د4t+dv}m9գ Y^Ы\`d³i?J{Zc.6\jVP බ-osk[jvkqXnojmq VE> ``UtЮb֖xս]Qao00U1^PW0W3'6l%1\ۡz K7:ta y@FV]X$:NF _%M/Z-XX1@J_eAЛbH&~u\N,2gilK\[8ȡlbBh[5.:6F3, 5 8+u]=խ}EawK*Fmm!PHƼu|=ia$͎n li[{6ֵj/n=kYK݅{Y)YRVFѝlusfzIe!S&\KvVp{kgճ^ Oe[RO 9¡Gf w! >|8Lo%χ>ǜHϋ&+&[Y:ϡNHUϺՙ,kE׭u(L=%}S}۝ uo;.;3<#/SD<}9CrٜGؽeԻ"g՛=lC1oa}GL՗> [A7яz{>'=xz' 8 wwPvhy!y#Xw}$=|+Ȃ87z0(S28.U6R8"B(QDX uHhPJՄNOP4ThOVxZN\؅`hNb8TfMhڴlhMnrLtXtxhLzԇ~K4xIxG؈a􈐘D82TA x@?Xsx?ӊ?C4h/:l(lXs@ĸbX=ԌXxX\؍ōTXIሎtTS.:gP!"1YjNQ D0QZ B>fAe*NB E@C `ʤ0夦r`j ЦħadC@ `LXHB j>ZO!*6dzZjxچpت:v8z|ګZ:XƺȚzZxډںح:8䚊zڮZq7 -$:[z ڰKX;k{ ˰۱ +B7&+(,{N2*4[8;7ҳ>PۨD;;@{J )L۴PQ%;#V+FF\;SCb;Ra[Hh8Puk:` n 0t:qyK: "۷ [<˷8P붸Ӹ v#Kc˹#!G븣cʺ{ 㺇J ;;[1W[[C ʻҼK 1{Kuګ/۽k;Qܛ;[qT뻿Կ-1l|  TK;k852/, )+&K#k  +K k *Jj%?Dz`2xjCVk3pWx  ҧB-* 0]q ~ ~W``k10a}:ȑ>a Ӿj&ZE   S.e4.a*`0/(/֮U> o W Tn;O$о6~. >ߚsX(E ^Fw/1-F1kOoo4?$t_i1` p b\/> :`Ps/c?ݮ icC K/-//5&_؟8ܿJjފ۪ *JjƊê qE@ D8P >QD-^ĘQF=~RH%MDRJ-]s#OB.d(SN=}TPEETN.:y¥U^ŚUV]~eNevSZmݾW\ug:-k6ƴSX`… S^Ɲ^dʕ-_ƜYfΝ=ZhҥMFZj֭][lڵmƝ[n޽}\pōG\r͝?]tխ_Ǟ]vݽ?Z *o 0b(@Ѭ`|m煐}d@t/<D0A8/!cL88'b PLt=?BB>pSE_ H9Ͼqj˄=q1J)' cL0R&XXVNJD:0"#+.-&   ##'')),,..00111111111111111111111122222222333344555566:7>8B8HALG#QL(UO-YQ3`S9iW7ʓ0҉)u dUI> 1.0:@L Xbnv#|)/7:?EۭJشRֺXԼ[ҿ`acekrx~݂޼ּνľ|rhhijpv|܅H*\ȰÇ#JHŋ3jȱǏ VAɒ:Xɲe0cʜI͛8sɳϟ@ Jfc'!KeˢPJJիXjʵkף&tҫٳhӪ]˶۷p2)Lr˷߿ YJ,+^̸ǐ#K ͕3k̹ϠCz<sӨS^ͺї˺M۸s]Z N-oľ+_μ4 س~7  K i>?H`<$H| Q'~#PF(N6E߄-8af(U葁$,`^84:dJ֨d !ȸ;D&X~JF!)~R`4Yf}bfDti ʼnќx矀E|j衈b9E&裐hEFj饘7)Ef駠Djꩨ6D>jDj뭸5+DjCk4C&IrVk1-Pv뭷2䖛l kފB+AP"g+IA'EN;]O?]\ 5^1"c,/|m}2# 425K/;@.b$0h>@=' _"D /TSL}3N4Mw=!3 bui#H#3شM"@uWL"޸oD@u/In)y砇碗ngꐥz箻YU%|'7G?/EO/d}wއ?=◯:r )ri``?VA@=${)I k_Ɛ56ߡ$(G.QbDlPJyl,Xeop}b05 `r4W1f^kt4MjMϪİMdir 篾AqV9 tZD;OxQ=| 蝆h "(3ЁԚ JJe߉юI Hs(M)S무0͜IӚf6ippӞ↧> lV6.,=8A ΈS D"zPwܣGUW{Du Qu=*x5OVժ r9jUC.XIWʚ"r7صl"fy kn绑XDEoA 5gMjVY!1 kyWî`{t`zBv0{}V6L3(yQꝒ:#XugWc$ִm Y׾Ez b&Ď 9A߻YC~N%JmHXvmd7tYj ,nh"F,z[9۾X Z/?E5=/\THpY%|" o5\u /RqjZ,[E,ẉۜ+5ί:*Ї^DOzN++:ԧS:֯O^:Þ}f?Ӯv6;e.v?9.~;/x ?<ŷ6#oSؖ3yZs*(sߞ>28S6X>8᳃<=>Bx=DXttHSG؄Px>JH,L81%XX`-bnX;p҆t(Qs|x?v.x凄X:x9؈x98S8v6]4X9s2ӊ1B.d .HXk8Xl@AP'Ș(NP h O(HMV؍߸ Rx븎p"HdЍM珺8ܘ㸄  LsX yّH)lCc'ٍV,1986)8K:yN9)A<YN)L:9P KՉ Q Y9ɠz7/Y(x/.3$&0(4Ӣ.z022::XA8[k4ѻ+01+-{+ۼq *;Q{؛EǼk* [6"/껾rU׾({uۿ|' ܿ | L ;g B L)!'# %)'l),-l)+M1)`(\g*:\<È@$P`?I.0J~qX81:̑WU`f. /C.X; `=^%q#`~1P!bnU0i4nZnA^72找0 pnc3%> [#I;:1n@.nǎwH6*QޞJ>ޞ⣰ TԮE ^z>fPQu⎮膎>$I-Qnb)ځc(^H[hXSPMHE(BH?h<9630XR9 Q119Kb^3BJaP"R_M#y#2IaT?&fhjlnp Nb 1 2$vT6$}?i||&ء{@`{_P X/\w 8Y[}[{_ OO_TI@ | )Ʌ+Ao\[4!gaPB >QD-^ĘQF=~RH%MDRJ-]SfL|5`> 772222222222222121111111--   $')+.0261.+$%&$(/)9$K!W a k#t$w&z'"%*"4;CH K$M&O)R-V3[4_2c3i6o8u?}ABCCDEFHKNV\cgow~ֈӑМɥȼūŖŀrh`ZUPǿN˼LкKӷMֶQٵVܵZ߶]cegijlotzɂΆ҉׌ގH*\ȰÇ#JHŋ3jȱǏ `6Yɲeȗ0cʜI͛8sɳϟ@ JTa'Qn`вiѧPJJիXjʵ+£&SlҫٳhӪ]˶۷p2+Sx˷߿"A+^̸ǐ#gܠaYɘ3k̹4MT><ӨS^h˥[˞M۸#& ȓ+_μ;NˡۍwC <cӫ},K\ /Ͽƽ߀ 6Q{IgGvL -$!(paX}3H "@BZI.h 唝]8Q%rRn`SbihZDflfk)tgx'w矀zgjhp袌hF*cNj饘UivV~*ꨤjK`t=j뭸&jJꮾ+k챆lFVk^hNm~?Bmˀ?ʐnn;/9ģ/['+,'p ?99,1_&22Яuf $&r(*24r8 :Y<,UMH etL7NG-uHPOmU\7u`=b5f-5j4n-4rם3v2z2~1O1 T@,Gx>K\O:,N9|Y:TO3:dT>.ꯧzŞSc{q 3 d@<O}`4n1\o5.7O3{s֯%H@YL`@:^ |"!4pNJkX%< {V-| WW w8!hHd@-PH9MXd.Z1ô0̈6}np(:vcm>1 =A34ZRz8 p `@=aVdC-4IlX(W2SzAXI*W)JRv$,/Sd\I!] 䑒@ALxeAYz@3RIGS֔A4zެ55Nf:H%* L3l$# R!FZHCd>QЃ:Sd& KzRE6Ʌ6ԓ (Z*h=sϮ}& 1TJ4Mh=ztӡ<}R*})0iԝzȩDЕ6\'LIORSd<ΛUtdY*K_T2H3*"$$IiիT@ ~:DXӼ5Eh^Sw4ՔhQuLΎTAh>|X iUg "Z2L^mPI {&cSԒ*i:w/&iK]u,@K+z9&஼KC2+zñ骷=zY ⯼L+?:(þ#o~˙l"{S<˜ ~0_`R%H)fLm19ceKbИ-q,o㵱5Ǒ}Ld9ENrb+I_L cU2^.;^,2fN3Ь6n3T,.ӹY3=?~N2MAdž>31~4I,ISҖ/3MswC-j풺=5U/ծ+cY!skA}5(aױƎ#e3~-.RX6mCf"Íq{>ӭ6|7e(yV!m}[w.p <8'' #S\x2q8'&S.r.yb.Ѽ}9׭>Ѓ޶=mF?zْ1]{:VG4ֳs^z.vJ>;5wn5>v{wV;e-׺53׎|#/ybSǾ<敭76C?ѓڦ?}Szn~=-ٗG7sݾ}/|z>>xeCdP(8! Mp10E^#KH`~Ġ?aH0 bPvDD~7I`X8Cap L4'wHDQ ׁGT #8Dc`'()!}-D(xa 7CO;hR?hCM 2hHFx21HNPBR ~XVYBIw 3(M(chBAhްi؅Eh~m(C9( JU؃6x/[0 5}B%8+Bȅ hBI`؉+hxЀB' wЊl~hP/p}P/w@}CwP/0.wpѸCp"eq~(Cx0HT}爎aw xCB(`؏'w8dCQ׈7$u**8Dc"yB!Yr()*Ғ.DB74Yt6yH:t<ٓN@uB9TGFpEVL/ R4NYrX0TH^ 1]Cd1cy>cj&lٖmp 'i95#vi&xb| &~^FHY0W7$CFyz#ٙ:9#9.RI"49/|⚲Y.Y r#ע)94 -ycʹ,ٜÜЉB9i<,ܙ+4Yq޹%9 y#iٟ)ʒ:/Y*䙠4 jj3ZBrz(1$&z+*,ڢ\0*1):Q68,<2BDZqHJѤNPTz&Sz[fZڗ\ڥ`:b:ɟfjePlnirztZ^qxzk~zk9Jzڨ z+}:QQD4 ⩢Zc*r71Zz3ګ*(:٪ƪhZ: ZAؚ5׺ɡJ1 z_֭ڮ :fdJ,`D"9- . +EDjb 'G6'!#;'%{*[(,۲NĮ0 *579[; =?{A;C EۮGI{KKMOQSU[W+Y[ˬ]_ka;c e۫gi{kKmoqsu[w+y{˩}k; ۨ{K맑[+˦k; ۥ{K뤱[+ˣk; ۢǫ{KѻӋ[+ˠݛk; ۟竟{K 2[01{˿1~B LK{B  & %&,L%\,!#̝%'l)<+ -ܜ/1|3L579;=\?,AC̚EGlI= _}ٙu-vM=+,g VMם]W]$ђM*>2I.C cM@Rӳݰޭ'ުGާgޤޡޞޛޘߕ'ߒGߏgߌ߉߆߃G:B &+ABK^%Q>%KQ$#">$^&~(*,744EOpAJ4.p3?=td 0~C^ $t 0䬀V8?~[˱6 7>O` n%qu`f4J0tz~Z]qjNs眴@WE鄮 7~.*u!qCn Z.fbK]!ID c_}N5P].>L!B~I>0N!(,22$БBBBtБllHtHBlߛHmmғl mH,, BBmtlUIfBBBllCmwCCttбltCll CmBlLCmCmߜ BBmCCHl CllJ&lBғCHm,ҴlBlBTtmC𴥱,tt,\\Ex!\JBwt?Ht@I t5}6IE  HFI} ,Q9 ߿Hm d,LBBTC.Q~l ғߛt\,\\lleCC Uߛ~ \\\,HH*\ȰÇ#JHŋ3jȱǏ &[IW"ɲ˗0cʜI͛8sɳϟ@f$*lV ]ʴӧPJJիXZ$jR`ÊKٳhӪ];蚤lʝKݻx { LÈ#ǐ#KL_̹ϠCXӨS^͚#ְc˞M׶sͻ兩 N#_|gQT#0J؅*ν uP (x_7~th@r (PyX%H'Q4Y∵ixyq"ijXǃ)h#o-ިf : ! DʖcH&:PF)ENNiXNYe\v饋[~)dfh&sgpftigsީ|g*h\j衈^Uh6O>*餔if)m駠jti訦jq 무)ke+'lvQvl88@I4^fF~&x+nKf+ ~n]>X¯ebYpWlg1boyu $%r(*T,,@L8ds<>-4F@mLtPtTx@ވ R% ! I]`& P&3dܦ6IRo,'*a4Pe0G8>S%(g6qI=<0(T pBQ1o+ Gi#hYK2%@#JUx(GK4i\GI P@ T5C)RQk洦l*H$K3 +Ǔ$CWiQ<d]7P  }kL ծt%Z)SZs)HGRt@0pаGiS"<3Kfh=K$?O XfWVj ,&JS1d)ArJR&D) #\Y򳵣*v+lOf'30z]lK_9=+Oyɘ2' `ӚƼ2 |F k fpJOZ4TxMXLvĞGZȒś1#[^1gda321v*dʘ h!#cNʇyr%e˜처bDyhV 26G lv3XD睼\3,AKІf2}E3zȎ~#-iS#4-M3Ӟ0C]Q>zSj}5+Ycֶ,s ]-l3b<6ekζ"-iSۉ־m#rB6}(q!-uۅ~ -oһ"7=}k .܁?p2|8'3.s}8B.r鑼;9o򕧮.c<⇭O6#Sٖ3js<-{7SOճܮc/vӾ=ۻ7?3>.;֏8Os/oIcgOQg?tEǿ1ߊN8xD~ (D ȀCt$H:d?ā C"؀X2d"@ (*xC, 01hC,Xx8".A)'BH$h/SCLBNQ8S؄OBDYqH7$b#N)JTY)SyZ#Vٕؔ`Y_9•f>bXli(hrtYqxzї~)1yy٘99Qynɸ)YZҚDyxiٛt)9lQƩșhid)Y`qڹI$T1 3y6bٞM 9Yɟ" $zb z ڠ5::1Q 3"$Zq(*Ѣ.z014:6z:<ڣ @B: QF!ŁL4KRTZ^9XZ\U R*OJLjIFCʦ@= :*7: ^Z)ER~:)E 0B4*1J.j+(%ʩ" *Jj ʪ  *Jiɫ )Ii䉬ᩬɬ )Iỉɩɭ )Iiɮ鮨 )Iiɯ鯐 )Ii~ɰ{x u)rIoilifɱc` ])ZIWiTQNKH E)BI?i<96ɳ30 -)*I'i%"ɴ )Ii y ` (bscKbh()Iiȷ(Hh戸㨸ȸ(HhΈ˨ȹ(HhȺ躪(HhȻ軒(Hhȼ{xw(vHuhqlgȽ`YS(LHFh>71Ⱦ*% (Hh ȿ'Gg'Gg͇ʧ¾'»G¸gµ²¯¬©æ'ãGàgÝÚ×ÔÑĎ'ċGĈgąĂ׶}s_a/`/gpT\OPS.@G<`/apPl/pGzp;;a3@F>[\t[V `qȓ\ǀlEBppu P @ _|wUUl/zƿǣ [tʇő|TALGʠ\uD,ؼl~<+a\tȣϿϮ0ΛnXAJ_ z<ƻLGi x\WS zlР\ 2-х"$]ҋy(*ґ.M0ӗ94]z\:="v?}vAMvCvEuGuIuK]u=!}Q&0iU} W[d'Qa-^b $a(q \pr=t]v}xz!) ?J@G5``Q׀-6`@؍Y0!60 K ؙأmm,ظ P0Pjٜ رv بۨ]ܨ=ܓsR1 m=s~ ]MGށۍ@فڍ]٣]C=},jܞ}==:߫ =~p P=1w=mAQW M]ٳMm2!,022Vd  иVeоXOO)PP( ˶V]a ]d`GB4\Hؿ`\=/BB!a|bbe6ZϸVaDKbôVJZc~LηV,,[\³VAA"DEX(@`1(\ȰÇ:` 3j8ō C.(ȓ쐁\|( ̛ kĩs̞>] r(QFLT#ӦBisFVb͚*W[:j٩gmViۣo :gݝwyz0M?*xpWT-lLBܒrQ|-ԌW!A/,4YfQU5[naÕ-6]vqխWqCWy7a ;%yd䇡+8=/CPl;oXzGO|{L.,?s#'Xqx|' u ZGb&נw"at V؄xAGv8(h"t>\.v3BW1@6؎4@#۹CP &ߓjRVgZrb~YٚYᙛ)Z膆6s^\Fꥥ`>azimq:uzyº}'Yr Z(" ۞B)J! pZr[o~XFn_nK mM+/NF{؋/<QDp!D0D +7/G\B y @7rO,{\r- T2qr=K@$4A3G4`Dp5@Sw܋5lmUt@BgECBtX)w|_Zx?{Z3,z7s{' ?m"߫3OCS/cos/î;x;Ϻ?<_<6π)x<^ 28 @'6 "$!tF:No^ 70{7^0|?_71} <"$:1tEMъU=_!F2BC(A5Ѝ@6ZЎ2# hC>Џ:$CBѐBD$iDF"qel 2Ihr;, ߖE:rlSEVzqc,FWіkeKZQ/{K_Q$f09Lcdf2GhVSѤMl^Sf8MpN4g!yNuDg;Ie3o|(!װc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ@4 t ʴ 4!t!z!n!!R4"%Ft"):b"EQ6x Xю<.裇@!,a$22BCM$ KLW,,8((4CDN..:ɔ33?12j`*>5S!,XEb/22BCM$ KLW,,8((4곴CDNB(..:e33?abl! @*\ȰÇ;Pŋ+. ``Ə C6G(Sf$ *clȲ ̙8sntIfΟ)k J]PA JJM`SjЁ` =Sٯa<`@ ev K.ݫUH`0a hpB(k̹ϠCMӨSYr̒<]tZ6Jm.[7-(ƒ'K^y[W={qn]f/gijkjic\PGC>5) +=JS^f^ULF@<4222220I!1}.387?9@9CGIb [(V7K6?2A2C2C2D2_;ehG[3"pE5jyL<{ɓ7>"R3F֢f̞YkD5j⌧@9p3dS";RIV 1{l^R9zs_`eՅU&K 4kY91/YW#҃I9cƶiZe_55ywVwڎ'A=t_ۥ멗_Tͦ]Tl`o͛298s[!w|pOfSʦw4X>/+6#̦mAwvy.Ϡ;2*Oi: +gntN*ZE2KfSnJ &\aYg &Gsk=ЎΓk^or1:y]h!̋*G_iÇEse<^yt9Jo)]axً*,ݻ Duz;t2~k/?E}D苯>q_O?xo.g6|W&;$W[׀u~ghq(WbζuvoX"h҆%s}7ցFgz80dNty 'A`/>bN x5(xx*pqz?؄Sp68ƀ!Z8gN~K聩v~&U[]#4xG9Uh%X{g؃jx#Bhq;|]vxXQS8%HOfX8#^Bm㈘Xn܅HhL$҆T(sbHbh7\$Ҋ@ᇜRq(2awD"pf`<(Y+DH؍W{؉pw؈i،޸6(gp9ap؋vȎG |H}>ӆxJWFfy>.Mqt´xH8!nhx&?:9XѢc0Y'YxQ6YsҸkP%hRyFAbQQ(79ISUtø~v$WzA`ٖC]yQ-@icl|He=!7Sؓrbh{ٗY6ıNkfy TVؘ :ıa2tzqɔ)\#y $yyH7lVxę= njlӔyƃIu5 و?Ӛ^) :>6 8C :0)ٸ 9)2G`398ٞz j`I ɠ,9(؟wGIH6J4ʓ+ `Xʣ=zzF* > 5`آyT2JCz/IE5Zb 2*Y ]ڑ"*lZcJm:ʥ#p*/`guZs}JD {}:ڜ -ZmD|z # ʪ,:Ic -Ej#h虨&ڨ:7 Px bz Z{쩪ຮ"詭yڛzzv=# ک:rů:uRa*,㝫 %zX p[\ұ>ɬ~:&JzJG0+<#4|۲jJ=6ש謔GkJ[ ´1 N+V&7k(tͪ;+l Xkf2,+9T۶x;'ڴf!8 i%ko;hB#kIZ+Pk֭Yo:۹1q㚸K쳷ڵ8tK2[úy GZ5CBۼ‡6#Qk"[{ƻy;;XNIk(k ʻ'Z#T˹6 }} |640 ["T:i;,<@γX \l l|,\Q |L\M*M e<д:<z;E],j._5lÑx,Y ` ִ|`}w!d] |e

\ۖNM}Y{١4Y}w<qa$~z ~#.@ !aA;,ǚ-EMn<<փyƀzym^-$aژb~\\edKkmVZ[݃GwU=/ߋ!|i.If ދ蘾.:nՙ>$\ N G >ͩmijN*^.쾽~Ŏ>nslGog\Ǣƶۅƀ]\>ODu Ղ{PA߹۵Nʮ e=l˪|<|| ,)ѳ̽ ]N"o/oE^.=La ˬ-]@]"]%Aǜ Ҝl4 k =qe?An2U4~xzkmhm=c܁ObMѳ.a-Ɇo?:<لLlfO˚-#ӈ؜éث/?1[Nmֽ օc-?_nq!.M乽ܳ͜`X=Ň_y,MbaݲRXR{fQ ~ <8 B,h94襠1q'[b!ÕaRAZ@رti ࣅ (@a[B}᫚"LʒN:KZtլFyuXe͞EVZmݾW\uśW^}X`…bXbƍKB8*ʙ_8bRQ:fΞAFZu) .Il3 i%p7p34#|y۹Uʡmsƥ9s@q_ySS7޻? 6D0AdA0B 'V & C4쌲<MCIJ1DW|5 蠊b-FkqGmܱG!,G$dI'2J)J+SBECQD-1/\Ds5F!M%H8isF8lF>4PA%PC%4K454T,3!tQ)RM3[>(ZXJީPZfaF:iVK!чKx]1M2hCe('Z (oh& f#_b)o;F WS씙b8 rC6JB&l Eҗf>{ fLKj |SɗdMӚf64{kTf^zS5)uӝg<Qʼ>E͕ӜJhԠEhBBٓ^$+Og3PtBNvԣ &C3oBC&E+ G)r SԦPhYzT|TiEaƛըGEjrLX@W>%Zw3muq^-sTլ[e"I5\TdQ@b~[0@6OT<6n}[? .!,֏F'X: vֳ}UZՇqN+ZWt* Rr*)qw; uowg*KOmbnt %:gi#Vt+@he~; %7@.+_~SbFv1t<`SqTwV|ջY-І\_h,yXGtߡ!?H^_qekƴ V0`ExJJJ8RxiT!^݈$7yJc5y񌵼e.åƋA㷒s5;2%@ޑiR2@wΝ-MǦؕ"vq=hBˑ8c̢Rҗ4BeaI4OaUMM:ӯ57 F/њB-Y^hN3)PkbNjHX5RMvm"[h".g(-5dm ;܆w?poʭj͘HG Վ@=zmS7M,g;Z3wȳ~a+*S#Gyʭon9o(z5NXOv`Dk88׌EѕsI/-_oYrVWz/YS\K Z(*- _.%ąp[nk8Th7Y|௷uku-q֎Byfr8:_~_o~b*# Uzz_xqy,( a#x PhʻmaxOXf}/C'R5)M3^JɽGx'6gL~|[~.>K'Q3 3ȈZ":3;3 S |z>Ʉ @tJStAtAzA`AJ&99!$ #@Ry(& ").$BA&4w)w+8*0\2t,\Bv+9lB18d24:>Sp)` эPy,=TkC9dFL:C3DC$1pI #Ȓ%᳃Q3Ģ)#; Ȭ9G[ H+#1Z00 2@㲡x#0;aZER KPh.\n ]E$#i~7"E3 H8h<ʟK+j+?oȀl p G h V䈶iH##$<*$GRGȐI Ȃ)K,IT-qIJ )w+Ǒ$ʢ,IepłEYZ\u#d }IQL,`h׊CS ($ -D۟"#b'͡#,kDl]QO12Aqp {Mlib; `/}P! q= #DUT>lH/2eU0SMLdpyOLMSA:0 =בSP)PS%rXe STԻ* UL9ZT`գR, TIUTJ]UN|QTB)PЕ7 @2 ,$ #FVa9"GH+e׫kVHOjuOTS (Y {Cl3@8W; KCTJ]@}eٔ4hK%]Ԕlٞ=EOTMEә]UlmD٦6kYMݗTMU`uڮZ-ȼUZlڶu [٭Vdڷ۾]K=ZU,Se[U(UKZ½TĕϬ}ֽP0y@0 N8 ̸14 Fe56%][bݫVE}h1JUDqмD: 7SVh>kTJ͛UP_B] UTݔ=\M!kD$KWh<W# &`!%`)ƴ] ]QF_p``-Ʃ>JTݠ]CͼO =u ?፩WaA` ׁ^uPUuDpKCQ9a9M,^b/2V Y!F14SZ( M tAWy au %rm: $[S0fcp_l/˵`4R+t9Np@XVSY S%Ľ%5FzdѸ ML^M `V "cFffS^iu1hFdk^$ZjT &bn^7r6eY̐Z6dgJ!cU`os{&tHOzƐJ~g%a_|6胦}~]y~fU Kvv &hiVNf al]飏ؗ^'nxh,Zd˝ e9-=Ac:^fʚY: @~Mmn訝VcnǝIKF;˻k @k-ԁ%g'yӬ6:}\a=(ГȦ{L VΞ^ kiiUAy2W&H&1F ߆V m6ۀEmS΀I\B#=2{~^Nu^ j .$M ]YeI:ó=o/v֢]o!ogU$ΨS 7_FAy_VSVO gkp8Tlso^ ~q†%.p?cQ(4f!_<&-w q,o Ѷqe,NN.sUqr7rQo0n <ñIYH`נ @eWj*g^N; ŧTbjФkP&%2VPuWHMvucwO,X. #Żmg~Tsfp 3tR;f+,͈A7+2U߅Fh7%%`dvv .:hOu!C7W:'wnvsOm@ Ȼ=Ebv:^Έ5H.L0 *GA yAGǴȃ C;n3'ZVuҶk$g]Tȓ iȕwذ'nR)vubvwr{""{]ݘ0"ru?@&p?KuT uVWI/ꏐIy0}_d@6dxȆI1쉴H}QʃrDm,1ݬ/7Ύz @h&竱%(tھXi; o)֭ۢi\9i0x|Oyԁ^jaj0},_Ս޲Eʴ{2>[x;ʸ4Lh޴l;%Z#( R)k+\*ӡx"X)!Iz޸Dcf'A`m&g53p{6,Zlfem!Pֱ jC"(H5KpK[ r^";rA je!!P˨P7KC|Mza TE0}It2Ԡzx9.yiV՟8D拑Z'1.&ma#Eŋ "gYҲ ɈQ ysS8Gɸ-wOwfc$U%w9[b6$K]P&8 K]Ze´[87aagdț5DeX3fv5i=(B3NrNyqi%D@Msl8L =)JSR 2T2E:0m1d҆ˤGYPz\)Rԥd-}O/UјcEy'7G*Н;B'OZ2n}R@L M)Z:&M9UUNʹp},d#Nu+꤈^rYtNƝvox _=-jSղ}-lc+Ҷ-ns+[򶷾"e+k|4T)٭7E9!Rֽ.vr.x+񒷼-zӫ޳X].qzT^%7)qji/,>03~0+ SRmi1Y”ym@&>1S8~1c| 3GoȘZuZ,!F>re%39<4&p}Lry)8+ #^2&f͓^6/n;qVNF3=7~3f fq_#x3#-i=ҖR]<_ea4Sjcծ~5*[MuzafsX75bXUxZ"ݵ7 mGF־mZ+tpf.{ O`^wq C }?q;6Z@]pS73ds2f'DKGߤŧQ&-|Nƭ{[ެCi@Nǣ.Ak^pq#VpZ?*~%`h!r{;bGO?GYBrt2%cq/(aS|e_WNx7I5ٚYv+mc%*r$ۛ>}ZH_wzOx̫?AK%+::7ބwC(] q_Q Kڑ.M vy] Mi ^ 6] A  jRہXޛĞC ^`U ]`\]խa1oN ^a_iʑN,Q _߆q`&ѡ̂> KzJaV8"Zųa{pN %^"╙#fާjE+DbQ"*&"+2&v!"pb+"/"-⡱VL1"բdl+/>#4Fc‰1RABG3^sEy#99#::n4;5ȅ1".~6^E*|#p:n $AA$B&B;6C2F<&"-#ET7!Yن?F`HH$II$JJ$KC$LEDGW\]qEz*to/$QQ%R&RdL6SNL^.r1d%2f*eo/,X%YYSZfĨlZV~H;%0RHW:WY_%`Z&aRE[tdeU֗>cCWX*HJ=1\&Jjf`heaiDTRgeudJjv"hpdFev&I_&KJ2=KI Ę< 'qC,iIt1 fZs.g,svCtni'zDjz)LekޣlvVWfnLm. u@InKu wīN>Ӽqqrh ˻Ho Ų4 x1TKg2qzO~wB@Ș 5Uf((N\o~Kg*dzjzed]6fZ<&/1+a''g (8' hI'rf>p DIҋ(fķlM׬)|K]8E͸@pgIũȈ).ͱ̱jj栖i2)g"DgO6jN$VB~(D(*Vf^Ꙃi@x⃮+ipMP' *xjF P3yg,yh+u>Bhf냶'r*K~fRQe^ElR$]epi*f>iҪ)`&hzָ)+w gM Cn tf2 |3g,l揸l]xJޫf<'j\nDr\ބ.lB3ilPȾJ %)nͥAkqM i;iڭI-h@q.J->eDNң'6eDՎk"1$jFRv: >ĒI!UKs2,'.) "j(sҭ>rjh]nF.dL^jAX$k֔:}jhîoXeJT~a⡪fԤ(c/*e0.4n[2Rn^ R/ pcpwpJ2[֥rqZi0cp00 p0_b [|*{l /#ǫކ ۰/qp[.mdL]A STb$qfMh~&3+NnZn]jkF@pbh)ۆIQI:>q«+w "!j6(u2X1'cp1]Y7T օ&s.(q:(F(r-_ޒM! 3hM`&*s)3s5l( ..gv8W'p#e26kqqbq(,眦`7)xm?(t>ς'1׳©C㨘j2ME284MO1W)Kp 3m #<#<+(Ы=1G+δڶA)N+vu.*Smmq4X^Ҷq;!jɝkҾa% (QID$yKҎ54؎K4Hе-v^0v@v\sɏ G\fX%&-(3q3;v[/\6d*uxvFh =MvD_I%w\d+ wo5t6t7ўPG8h''[1>6bYkvVtMVNRtDj) R}lj l$x6}7v n* N]'8fSMPnbO, aOJF}9(7Vܯ{]8T먮6Kɸ3F0* A`DO9/iy[ebָNJDYɄĒ;yXTIaIXy4GŹ2y99ZI8=wjck'O ֝ՒyaԓVcy6UPUo_Yyyś9*Yv>8)æ:?x#4$7:HZ?@ֱWF;HW;*{y,ԭF6M;G;#3{O)VZiӻ97zG9[zexSwry+mM{:[:Am## F('g%Ř\L>]3v>'#|#R#t;Y>#< qeoGnBtI9ƓzGŻ{FB3GI|(@6`D](v2lBs(6 ޷Z6;)jN}J͸Bpj}H֓$-t=СN,bw~Xr:T4jh"2zě=[Z3{ZO'~a| ܸj vdΡ v>Rʡ|FɷzDMP%)9hLٿV>oI9le;vxz@+@ ;l$^߭- @đ1# +q`A!#GlHxФL7qԹgO?:hQG&UiSOF:jUWfպ'I_;lYTbjYfYIr+J*Qx /+d8J[<#A.ayZbIsIUޚ`nj2̦ fQLeҦV!,iq9QV`i:i{톹awfin!\:,.NVs= SLbyngp9p7@P #WJxc/^k\驯i+GM~\qL;':byW&-^[@$ax'ny.on"8(J0= :#@CQ " C뭐-t ]=is^9P}l0Jں| P1<2?9@8j;(*KoWႅ8Q!M"# 8FBgĉ" &@CC=}#Td5БMtn!.0B Ģ@G>"EHD@@# JyTҎl%+MiH&#| "B/ȍm=gQl %Nj6I|FSȁPHhD8ir3%Ly\`= ZhA<矅Tf %NֲB_D7(L.nt5M,Ɏ̳4IQRK3SB1.N2%fCY=n&y#**$"U7i-]QUU#əTJgPIdޢBNku[WlIw9вϦ^+h)&n(m%aX:C–_׵}Md3S.,+Bg_J+pba[Ζ({UUa9d_Άi{(nKE腖յuj[wաLgʱ&- <%Jn=sxچg| b//;l-zYߤ-E/=v&?[kտEupCk%cc^2,y\K^#X,jA2 K՝3}"#Qqy""<(;5񕱜ơ:4\0L kKs hT1-B oo (B6A 6`(R RTB!d#0! UeMoӏ_Ytlf6o[Z.6ƒh^ 'Tެa!ﵳs*<# `l6*ی~#4G|񎳰umm_Ӣm1>Kw%IRҒI B5D",hXҔ7*_ X杵'.Iko wt[t{,}A$``//B- L03"-#ǡF3,gr:ىuœt'm>=r"6>PԒxLmYg|NIbIX7&(zё0$Dnnюbt)zjnV3҄_mwۥta]o}fNWciDΏoՄMu: Iwo*zv8[t7ى{ ͭ՝a]{>'rVe3I.w"6ݛQ4i|w^G}t&} :gh7/ F{1Mǟg}z{ ׮CvK,Mdg$ANh\B pEp u W‚JZcpdu,phH0LP`{o Z DP@ lhF$@@ :ȧ-?C %c /  ȨBGy PɎ>tnk1q Ja0]A8 p !HHDH9TN 'n8FNH1$ ("a͂ E7#4SEFb2F0s:srү#9N;d`lC-m%E.~`}--DCɈD0bB?C§y@Js 40›v2$2:-B&qvϷҠ B<-/RCYE14C=>SD//C"VEH+q@4Edzkp/oEŒKTboBoF$DG?t4'JJoD4j_Ne´OKlOft=+m ^pfTk8PvtO9Sm@oP 5pƲCPDiâ(R=pStSq5WC 1D5,0QK}dF+XuFVLB-K?"bѠ&$p[ְ?}j?舚'GuZyLW^C6TUGPP'PKl֬2FZ?+8eaN 8Ir!.v#n%hf`t]HuM2,)ר  E3 _mf#bLU,uX cMGTL62`$"5F1)'v!)j؄F9ٌ Q! 3"'rdq6nv1+KT4Xh A!b* D[i6&Cq%#r.(m2&#B)R(%S&i2onQ7u"6GX*ML<ַ5 vosD. 7G*s(}121"D#13WH5B4"8\5BUw{r؄vSo*G;VNmdtc// 3#γ2AW x= A19rty1:M{܃`tv_Pv6R0pd>otid@z]~u@ TRAG4AQ$PB (t8+N6W|-oUՅy*ߵ\ + UZ 7I{$YNOh3+~z%RbG h:P^bo1&xQc[i\cY"D *Y.aeA)mfOhK:4yFK3d$2gB +ev evWP|Mmߥdіkmǖ z Y!VkmmM1L ͚۴I-욡kp2)o8fF3r;bs )k1,7?7D3YTXF;;l,vQO=0QfOِ7j7&t1W9I[C7)x8{t2I"m+t{-KSCySӀu3 XS&5DxqDJwE3m/%kVatFS>ɻtw @y?t0K|,MͪF52" dQMe^ofehy0dž;%үUƉc$,LY١؈ M2 n! )I+ĥ 3>L1j1tk{0INdݞOk9yD-ſ[H~3R"1ASk" Qg; Lޓ>O#.z8 ?C.S-{bΧĞ7fƨ=FBNzj8Ǔ U/ɱ՟*;֯ٝ;%M:NyU׿jB+UV%)… :|1bDVm1/jȃ %NU ʕ,[| 3̙4kڼ3Ν<{)v@=4ҥL:} 5ԩTZ5֭\qbi AJ=+1AhK$ٶ$Eq:՘޽|Ûoߖ~ ޛz#^_ɎW[͜;{ :ѤK>zׅ V[7Y"ʎi۸9ږ}7*#7&.'q, Gl9[ :vӳ'>˛?> i+Ϻ"m'v9 0=w VYqbRw܄i`"Hb&bV@c_ "}1Ց XQTb 6S6AMB59څ^FU`f BV\NHsMhd?*fjfnbD7fgB8)߀#"zXsF"dJ)BJ11a A䦠JJNiJJϨ*ZzvczIKo.l> mqќ0扟@da+{6|xz8#ܪlZ- xPDz(i*qK >S%pJ^7id)Ptآ咺-GrdR)[FtJ/ʹJ#ʆcyg#Iָ jc ^>)ޢAj̎zFKev@K;z}^OU7; g^{m䡲-P{=,2-7qY23Q7 {N{ɉ4A}N۞ֵvV{\^$j 찎 =wgߪ' K = [;LG{ƫ*>Fu-y ַq|lJp`N#[6!H# /- zTZWN{vg+~+RcȹV.CARL\RJ2dA+$-ɂd,ψFh&k6x 2+q؟x1-P! (F**P¢$emb7#$m+A,@/VꅣD_ XrɑeB'# GtaV@"&,m4Zd&S@K$&)+S4:RO ?Unڰ]v:XJ<_$pH|s'Sˀ t?p mC Q- Y&4G?jZt$F%YZHH) ^!b 4MoZ;tX`ӂX 2 _XX Ȑ &Ȏ$I@O  %Ђx plӂ@:Ӡ /ɋ)39"Iĸقls ّЏRZ,. U4Yy6y4< PZᘌ`S Y ,JɔAf9iwZ{\ٕScx.Xtyxəȗ #`IW傠Ѝn$iH雁)kEvȓ"9)+RIYٙ)Yqqaihy VII@a  빝ѝXIzqٟ W!:Jɟ] !*6jٙ67+ʢ-%ljɞ*J ؀";ʣ=? Az.J ٠6Q*SJUjWW[GzɓA||ikʦmo qv\JY饵IСVa *Jj|ux95j jmʐIJKʧ!BZa:e}:ztTsj_ʪJꋱjwe*j*}Qmz{N*6+2LB[U[ꮳ%$%JJasʯ5w(Jr$UP83E]!C4+}/B/5`?c 6;qC ˥32֪B^Ic>B_zq|I186<;a5##u:US1 068),b2X)E6 89/#11뵊CGHcr0dw|Aڵs2{c8kc;~kI897]KkشP@$5RQd&Khö_vrk^ksk,=KaEa;fL??l( {fsff>˻g|3*ڸ9};wQ6)QE{˷}*Ӻ*ʫ&kۻ65ֻE 껟_fs$|.E 2`3jR$ʩKWŬS K :k2(qf\mzц*\~[ 2kf!};2 ]Z'-9M8- m/2vN1f[";[;Zօ=3$|E;l2Uݲ3 Vm0D;]2E@+1-+H;7'̠M;Wkѩ{o:fdպBdC۾Ez}:9kB_O,E0k֥k9} tq1?ʕ+;Z5ɴ˿.c@<ٽ*ܝ;bmͶ{Ľ}Ʀ݇m)uIimMeޅ>_Ti9D0@L#)`kDߨ64lnjf&obCj1&f`mPg*" HTaȖbZd1NO^#>_ߖJ4o[wGۅ_d%$#_0U3#FN,B+j}_^=EJ-`V 9®qJۑg|Ǧnڐ$ܠr1 >)cءoݼ"X~O:Y"gC3^>OGo>ݣ:,CC=dfDg$n#?O*)wqH6CN/!2Ira? ,>ࣥ_W,DX_(IG=!r$x6 d˗(W¤YM9uOA%ZQI.eSQNZ*A,nWa>aE$iզ5+[qΥ[7XWF(1z49Ɂ23&>H[N`رeϦ]mܹu۷v}Zdgsx2z>O'n H䀔_+֧_!zppvhʹs,jA#pB +B 308R$CK4C4TqE[tEcqFkQFO$xLb9rȻq'c)IcbIO7 SP;TtQFuQHRGML3E5>m)PP3TRQ%5J:|SJDW5V=-V\UESQg4R`vXb5֨I; S-&ȼTShKMWkJY{WZEr[(նk_eANXoյ\k=^|w_~gLv+ENZ jUl:uCaz5q!Ƹv)vZn=^ E~[vecfG4xg6FPbU^'~UcM:e/֣c?9I!W9"!B{I{gvm{ߚZ{{o~ ΋ÚDj䤕Ԧ\=FjԠ+6/A)G]tOHG]u+=u=_Y@ppn~xW-uoW: Y63dyvU/4 `~ZH@ih"f%P d`iVeyͣW Eg,BM*D $"0XY2l k0 +L`ρC$bxě+cKȷh#07&PT|&"33d+ ć@dxG Ԕ! ~S$g9ġRdg(g=yO|:%8nF~ҩ=MbWlА=4hE-zQ,,LhsEr@I:t1}*DyJeG)FmzSQH}J0%`+1aEL!9jUf[VP3䪩qQSi^ј&qNӖSWFӒ^UskvNuH^E E3*16q15k`&̱iS`YІKki1W Mȋ9!sUٱtoduɤәuK]p;\&(!]?nwch{]ZsPkMz}9ە5Myۤ,v &x_g6υkc\حA"B@>s|eplvWvn2AEf>q2Nk chb*!uu4ñY2.n]x:q,V#$gs!OhD`$Edz^vtK"CWp]?dWҫ0anqNC'|KYto齹^h\pk. h(2LuAZ1U#ͳG|I~I$^,t/ 'v&%su^x|?_`2 FMĩqID%|gh=l1 -IY2>u!Bۍ0 $#2|8y %زh&ی X %cJ#ЈA <5s2s 1A$@*@H[=1X;XI 鈞 %X &@C8[? BԈ$,C3|vp4@ Q+ [B?@R´ [D3Z>4!D_>$5KAb&S3DO4TCnbC@'`DU\E| EQ%RD{JEVE\W|EBE:9I8Bg\LFelE^l5_p[}7y:@!UeFo]lF'zFP6sTx#)qFyG Gq r tlǚo#FxFz,H {GGh  9I9kHdǂ/i,ȟ#ȃITH 4*1c=`2(\bSFbJ@ٻҺsBy;l黇& M(I_kUcWիppqhSlS PM㴜@|IӚkQKלUUոcW\LVe-f PVRQJ] }"cpʺC;Dš ̇(),,8,& MCD"MIM-R01M4}{^}5-_%>_0\ _ vD*:lFR=FykSdF-m:@8x:Q=?v[UJSGT n[#`  wƣY8uG 6UUTExT.WH`d|3ᦲ`BeB=Ӧz6b/6FP91EaTNc )r[ÒW*n/cB c1 2n | [` TM-*95ّ-Y=X>ފ?f Y(OUT]m;&YY-d\F5NdIdȤ>M t\Nf/Ne<:Oee r椀`˛Pҍ#[l>c>fzQ 5#mEg|.ucvv8g67mh}F~+[5UUbg35Nh.GƸGy1*Qe\`4_eTv7鍎iqh hjda:cƵbc^ۉYNjsT) ^+ab‚b0f.obju"䉪 ÕÈsI0I9|W,Ȳhp]l abe\~lhBUXAK",Ā!pg d8{@BJ֓cQ3ɘX'AJ[d*j Gl6"Ɇ^ Qnk:& !!jˆ_q+ڨ%Zt=uZ魱iZY=Z3pSj}`Ԕ<n bM[k?gyo|Uy)@ Ǣnť_|$> ڵc Y?SqEҽow|璱Sɷ ʏJ yq,w԰-R\wrд&@*2)[k }ݿޯXP&84-ʍ{®][=7O+SBXXp"p`5A|X<5BN$OLr%˖._Œ)s&͚6o̩s'Ϟ> *t(ѢF"MT(INB*u*ժVbͪu+׮^Rk)YFvZ5DWi׆[sEyn޴z}j$ ۺfQx(6޹uĜVѪ;ZD}31$ck'.|8Ə#O|9ΟC',֯cϮ?6}ϣO~=Ï/ϯ?k>e-hdJ"ؠBRX!t헡rUK Dbr!"J$b"/b"#2#O8ZCYG"yaK2٤Bhb,XSY܋78ѕ9h:ڸ%0^ [)e`Vfp&Yw♧{B(WP"˜b֨攇'tJhxT6I &I3b)|ڪ8)Jic ' )YtZ*J쯝.{槗+cbr큱://ۮ[⛯ۯz\A; W|R9S\csܱ#\ + 3_947㜳;ܳ?C]G#GܴOC0\܍[sݵ_DK]gpT_v57s]w{ݷ-2އ#Cˁ^Ǹs9Ғ裫Jˊy{޺뜓޻ᅬ]_#/߼ϓmS_=Q'~˫o_>Kk~Y7n/=߿/Ҍ}h7B0,hA= 60Ku0*d[&!T2x0>!{C"ɐ4!yth#0J\(Dqh?4i.v> d㗻8L\v mOD‘me1L0]Oָ&M_k/elˉv,C7΅-W8mPC|6!]yҖ=pJҵ4mb Kg < y+o9ӕ?nukԑsinw嶩]uШhFvYcÁA<=[VߥM/ꧣ݉ ^|ƫ۷/r}׳n%ꅧ=[ Ӿ4}$e!>g OBcsՏ, D?3?ٓ_~D߿?:oI!՟_N2$`V`4 b 9JL6c; K‚!cAmA|#?x0cAdzp7NDn>q!&҃-FEAd]!,]22BCM$ KLW,,8((4CDN..:ɔ33?12<͡abl@D0!J\8`!A$>$X"R|"9ɐG %B$kt bAOZ 5y)A(7\(hP.0k  @U%6lȕpC L aā&PaU@Pa_ ,@ "HCft@0 !,`O22vvv  eeeAAAttt&&&MMM  ؓpppBBBuuu͂FFFnnn===### YYY666(((aaawwwfffzzz;;;@*\ȰÇ#JHŋ3jܨP@ CIɓ(9˗0cʜ#K8sɳG7{ JQ?&=ʴӧ'8իX"<4ׯ`v5ٳhM۷ȝ{Rpk,| 6ӦG+fjx%Ő#T˘sV9/r 钕O^r3װc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&$J$Za TeSfՖ\zaXYiShGjYPB@ {򹓟pPC@4z(=m+\yDY9Vr0n 2TSr@ZC+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8!@. 8 i@ \@"AJ@ `8 @٢P$A B1 60 X#Ex#AjF% l H*2p "`hD pEsQiCCZ׬[]zlk3y- Bp3 hpyKpOӴD/+N3 < Ͼ% H>N П3=!,22    곴@ :Q"B-Ęq@+ aȈ4y`J%řj43?Wnĩ3h̖.e )?#SJ\HbR@)A +ճT`J \0K@n]y ߃p!,22$+ +:+ fW4 2BoI) ?aFd= Q T3+/81 %+&,TU9 X57+T~e=+2f>U 3+:+ ɈÇ#JHŋ3jȱxpɓ(S\ɲ"Ȅ$[ʜIM/ɳϟ*ѣH rӧ,0JURjj5+ׯ`z K,ͱfӪ5v۷KWܺx˗޾ LˆNƐo>LYʘS^̹Π1~MzҨNz5kԮ_-4ڜo#ݨUpN\7Ο.=0}cϫ}{v;?D;`$:!`4 @:,:@ ,Ђ#6@0yAbpsrad(ņ*g,Ň!DH"nHCjx(,#ʼnR" (Ŋ!b+,ŋi{+1RI[D5ō/"#x9 \ch?L}wH< @j,$YF)c$H)L$%ɔm2M\S(472N,T*DrQlT,5HrRT./LrST0?5PsT,U2OT5sUlU4_5XUsV׬U6 Mu;7(Tb':I'0zB̞'i1~b̟(1̠"C(j2̡*($2̢2(4jIJHirıGR$6ʪͲlcl * pDK7ϳ!-L;6I|X;;ZĶ霩lGAKݏ $Ѐ`"sK+ugܒVtۭavc]~Wsy^qW`a|sXޝ b}"=n<ߋ>Q T|Egq ު80Vx6څnG?F1L3qQ,5{w;VV1!q5#mq#H וȖ1ؐI%ɞt۠N*S5r^Ivu@4R@fFόFY}H\X9TvsOS:7CtQ7A7OEtTYEWWtV}ZIw_%40]VMGItk9VQזot@DU'S{껚ں:;n&l?2N;՞_;nέ}pc܂47wf9ɍ *`2ˍ.I͛< Гϛ!X(j80$S`B֭N=dz&lTՈ8r>jnޗ5&-ȳg! $Ǒ%Ip̐U&)`|8,^&h!7P(1 !,*j121212121212121212.9-<'G$M"P"|Q sP jN!eL#]F#XD#SA"O?%M<(E5*?/*8*'/(&      -8BGLMGA<63222222222499999)A<MP [UcSmKvD#};*34 =@A A BBCG OZejkm p s{32@2A2B2C2C2C2D2D2E2G3J5N6S8X:];`m>~@͈AЏAӒ:ۖ-ߘ$ٗ*Ɲ;MTUVWZ^`cbaaǰcӱeݳjmnrzЁهڌ؏ٖ֒ܛݠ~zz H*\ȰÇ#JHŋ3jȱǏ C&ɓ&Xɲ˗0cʔ)͛8sɳϟ@ JѣH*H/_fJJ5ҫXjʵׯ`ÊKͦ&V]˖ٷpʝKݻx6jۿ LÈ+^L/#SeL˘3k/%CKLӨS^ hѰ_M۸sv7K Nq}>μУOسkν.꡻OcW>߯~}((Ue 6!!TVhZ(3e ކZ%(p$(ۊ0(㌙bK4KN3[(k {NNڎ O*:Ҫ0*}}}é9"推゙/o{*dSH/oQL $:J|E Z0C! zpA0?%< N gxڱ!w!ȢjH,P|*Vf.Z^ b(2o3hop :Fn9B| iHArS$ yF~1##I1B>d%7yKg$'G4OVG$*cJ1e)۸WR$.[_-} bjl %26IMh͖[5k8LJ3L'QMDS ̙w:(C 8qZ; ЂF虡1g? jІB &8Њ^iÜ=-щ`p'E;JR Mm+JM ѿ tn+Bf˅T85̩ёT<~JT̜!jQʳ}Z)]*P[FU+JÆլR*BjWKJnm1-+HETS٪XjыYtŒԧUpI4m:׿4bHeka Ј9gelE vJЈ?hGK~6|1$hkaoBߐ \;`%l ZlaP +⢁Mi 宖s/„^gi[юw 7 }h} P!'c ҠBrKhq\֪7oh ~{Q$~2p PnW .h%,၌Nx &@+HClKs"kRa@`̕zut7+\׾2-w+d Yg @;a`l .u['{,&dƻa}/_B#/BR<ٶ-}& 6{fJ7崡Zg;1qXJ-s3'~o݋l-JuEۊ,-.%=kKT^v,fysAdNs{ n Р[v\?{.܁xnmonx:%eņX,Kqu+xX|lONouey55X|٪on|c@Ww8/ ]a䄿 q yńfa%ȶ7@vsN7g{-9?%3^̭ gCv%myFWk]eh] |AuEucZx6vxFf],fiV_&] ~vff4f h[f? j(g) uNh^CdU&jGmEz^j׆f^cd^l u|lMJHuagwZx_{n%n%zWgUoxUye[6hgy]8!w4(RFX艣't B'+HIuB}&h'hHnv(*HgTUF'~`h~%&TSoRZTظm DV8v pkTE@hpTT4؎Ip8؋HЏ(h21L?DP T724@p/? D#9&I-Ɏ-C/hJ҈@9C# &@ DY;dHXW6#&iEȟIJ&jYZ(]tj_e6Gx2hfD-0@Фqz;`<c/j:XpFiƣlJd6iڎ`N;ZnvJgkf0J']Xb&e&G1y;%ow'b 0]]v/e]JdSj?>K>+6хb5%]\Ԧc7xՠhy|`_~6\ ]HvwIHgm+ZpeAh婰lIVH\[m_}$f[&z8}g] l*m66{ƮXۊ{Zckp%ho{[;yxYI=껾Ӿ =3<+6!kňxJ[KdGb" hںJp{#iU|vGVl%ܳ@J{S )<``J^P+[cZ·bgz!wW]5gbf%ƆuKiK+Ƚ׺Dh|s6*k~.FFEޫdλ_-8] =WlOk[̵mņ^iahEdlChЖGw{](}~U.E667_׶䛩nG6ɤ6Na=_&p;f[xxUh.mAh3>6~^[@V>$\ ud5K9lr?Ԟ@^9׾t>>8S9unt^>,3?N#ȞNb$?S11+ϳ0/0#$/&#ē2.4_r8?.: )CF?;=CP-R?iSZ_,\Ń -ElhjnO+p2tQD-^ĘQF=~RH%MDRJ-KJtJO=lęSN=qTPEETRM>-%fU֛R~VXe͞EVmY1g&Wn׵uśW^}eJǧ5 Xbƍ?Yd;<杔=ZhҥM'<U'έ[lڵmߞ[]\pōW+xp?]t*睹9gݽ^C>Wf̐Eeg唷9gy|Yrq9hU]:i+O[:j{\S.U:kkO̞vnkk&;m3;;T[;nkhzn>0;&p&8p gq/ rvs?O LF@G=uDkT=v5ջd=Xo3S=xS+!>yA*&U;}y駷y{CQpy:O?KG?~GV&S(S~?|Mw٤v3nЀ 8A9& f(Y& 88y&y U9y\a BІ!nøC<"| QlC85$hOLZE*LNb[vjы%b8Ǝ5dDH41ak408`wWx鑏<9HխPN$d"%HE6Xtd$yIIVRVd&SIMvrSd(%JQQ4e*JURNte,eCbQ,q˚Ѳbe0KasG4f2]Le6SDtf4;MiVSBԴf6Mmv?f8Nq=4g:[_Q,;iGxs?g>O}38g@$v Ԡe#/PC!:H%OBkQƢ^>Re%EYNRe-T^SbKiNuKԧ")~: MDEZfTdMHUfjVmz)jիJW լ )Yjխh[Wu]U5}+UXL5aXc!SN,L1Yn(gIZтiQ{QծvuCaۅΖm['&)\bo5RU)Ѐ@7F}s)ЃP׺͡v{0]ꖷ , }.z]Ĉ-o)_:pm~׭곯yK`[xyDYp  cqq^ar%Q9r-w`s͜慳s=ρ6=mE7ؐ-Ysӥu/UƣGkk\nE yivˌmgn2ϝduwj,{Ia7<-ryˋWцyUk~qWAHx.}kNԿn ~}p{g o|+_|Տ/^?w@P_/H+R A 0~e R@| >Iay r@? @@k\@r'ȇ ?lX{0R@(Le $? |؂);GT}4,@Q%EG6B@$>4E} l1@H/D%u \ÈV@(GW(C,,'CCI;t /ȅA@"dJ–A/ãI,B BtD ɱJLC@@ L}| ̿ ]|CXɤË<@D\K dAI$TEɜ$ɕDLL)DLB (L&?T HD@#?#B3B{M)T?\4!,*j121212121222222222223>2X9884/+x'smhaZ TLE"C CDFIIu GjI[GO>B#*.3BKA4&   */11111112225:>@@?=9 5668889999<#B)H/MA SS Yb^g_i\kSrFz&:~+71697=8>8>8>5?.@AC I X~i{qyuxwxwxwxxxxxx yx zx |w v w spnmoslgd \RH&B+>0=1>2?2@2A2C2C2C2D2D2D2E3I5N7S9V:W;Y\P'~3㔳T+#sIzs.Ǟk\郥Ȅgn;±'BJ.pH;{L(HR=ϺJ$ß" %!R :ZSl_Lw 4=HF_ Wh($"#d Bn0s3̡`: b|PHo^hD&aZ *rI4=dg.~+6El`H$-sb3pl#&JNxuHA.7@Dש#!vFh|#*oǔS/$2Vq쎀hZs:Ӝ3͔S7993LpDMM0, zAt=)@yṡI%))Z4R' zю.EGGjS$Mi^bm S0TF5>P48KN*ΜT<3{ӢEG$Q2ЦJeTtX=ZPBI\5`5ʐհuI[AKгSIj[JW0)s^k$VtI֚FFZKPW:BT+KY)VVe7K˒ BtL>KMH ԺvWl^_2IWmjܾMxok|U%.[䢶Ne,n:l09nOլw+ ^%oqQױpߋXB]7\zS #2.-^%+L b"q5r$1(axXxH1Q@2汏U}C 606Pb!sY  &.HolLÕ>,QMCqvYtfǑs b7HFb7YE1>̀a. 1$Y7<q *; !bU@;ɰ}d qSJ\$q b-b3Wq}Pvk5p 8r@;'3@)lVwMH *4:̌X5*}X9.`#tF3^ ~+Ƿj/Mj#ȼV {4&uqwO9~Q]&(?:3w[0r)/VG22?c'HO@䏣1HڧX@J c? yU^Sr6VW<fc K*J xi'JZ԰+ʚ&U' Kw,ʢ{i8`2:y,Z6HJN7 3ԓ?t ݀h:5`^K4hZr*lڦYJ\jcRf8de'bWhq( ƨGwnJ/6dxVxJPuJ3HcFf zfakV׳p#&twǗae)cgQktwswg'6x w[vvjMro;LqsKu[w{Ky{KN v|Y@"hbUje?Ʃ5{ǸbgK6c5fb[F e |䄹fx(Z'x,xwkRs@ <|H7g+6Wl16p QvwchS*lsųAp 0Kǭ7ȪD-p`ȋ촆 ~J],șNɜ[\|K( 68dGaMVn{l H 88dz ~Ȥ\}仯˂ ,l [d;g{dpH,PʰD䋫ffip6t!\fZܬ^ɼxLe6aHe(zc&oVw uʍXfUȰT؋Hf!!:mks0hN ? |ɥ[ ilݨ&QqK<,ds6զxΤԚL̼b" d 8voߌD׋me x6?U;=wH֣a\rhʧ?PЊIg},ٍ4?Pُ|٘mH]ٖٟGФ]x*̠S:{zK1;VۢKnٰ(xB,U'W],]W|G> }-ي>jgbf̌zflj㋮ lV=~u݇ pwmG?VRF_*?2;8irK kpYR  V؟LbR|s1^s4[FX,! !X( k m.D DX@>5EACӇ *^,]B" Q0䉔I\i#1ęSN=}TPEETRM>}ӫX4UV]SXžUZmݾW\uśW^}S*WW 6,WT3!Xdʕ-_ƜYfΝ=MW*YÐ+*2[lڵmƝ[n̬r4ZUK\r͝?]`Sⅳ^x͟GoVUS,fǟ_~:Ž{ObքA0B '= @>=)1DG$D搜 by @NFo1G ]Jí>D2I%d43Ȭ*A~I-K/u_QVw=wcIgmw'xa_YZh]ፇ>z9W+h䱷^9{7yƳ? }_s}%ފ~* @k!/y@ VPWG:YЃLӅauQ]@B* +aB۩7ġ; n~a%>0;;l8D&61GE]t:ъW4Q'E I0iXc'TCո@lfހF:uJ&8R"R0|)LpBԧv(IԨk̨Faթ`LHSK=ժNK3S_bTqUgaR:UnoaRӲ6w\NU^ ^JX&=\׾ ݞ\J־25fqED;)UV-DֺVŭ4;YҺZ4YV65p["׹{YKߦם^tO͚r IW׼L.8kWie'y^ 5Puߘŝ/1^spvVR 8ׄkclx\6:lbWK [sR2lZXY DE #8gޓ<'o~yf3_Rf\;Ky-gB+ $ # %<҇ti^8\A8ԧS;2ZhˊYHkQuykb1צ۰lpZ?T6mg3َ:tkqvź\s[7"=Ywa[u=*:L!#Qp%ₚx5 5y]pyK~r%ZyeL1yAUp:PFn˟yϯT7='C_ӝ> }XR:ՇnW7_u]#{ك.vu]j;In}gw]l)w2[v'l@s8? t8 ? 8 @<8<@D>,A A7,7|lA>774<7D 7!T" 7#$LB=&lB|A(6%*5+,6-=.,6/0$6122 C'=4\63=6|573859T4:D5;L><<5=4>C5=@5?4B4C4?DLDA>F D)AH 5Et=J4K|?L3MFIQDGl>S,RTUDkE8cXYE;[|\3^_F,ab4F%CdedFsghFj,kFmnFpLq$G3sܯtTGbvlwGyz|t}H"ȂDHRȅt˂Ȉ|òȋȻȎ|ɳɑ4IBɔtdIrɗIɚTɏɝIʠ$$}2ʣTJtbʦ즧~zʄJʁ:ˮ-7JK-3TK`˶J8˴K<˹P˷@EKȒʼL˭¬Ⱥ䊿 LŜC4L ČKd7L?Ʉ->LQ@BAEQEC@GFTԐ)TN5MPO%շ1S5TUUaV MMXUWU[E/YeM]e)^A_\֟!b/`BdeceVqgEhQ#V5l՘mVompV-+"tueWqwxWxz={r}=sUQuRUM+P]RC]XQMX~d؊1mX+=CXL ,P-YXeeWqٗmRّ15;Y (lً ڃp~8ZtvH"h~32o؂(~33~.pڬE@8`ŝÞ[(ې؂pۡՀxکۃڵZlp[ۺٓu>p([Zˍ pP[[ɝܻܽM۰- r` ڝ݃] .\ ZmLޗ^~8܃`ݑ-ZEu=D;[H%lv8[~pvp_tmۭZ5X%敾 - -ZpFہĜ5S-_>K9b&3 b@a`&aNaaaV.#!&&v'()*+,^9`}Zxݲ (06 @]9u[ޥ^Ѐc@p凈:M_]\xE-[ҵ]łpxdH\ =ܽEdNxdO]Kl@\QZe``9_pdP> `_漽^-fY~d[ve[>Yeb_jD>%l\-o.څg F)gse]ͭf _P^e]>M !,+i1222121212121212.222222222222211-'  '8?DGIJNGD=84211 2 2 2 2 2478889999=#F$ _-s 8>BEIS dinrwr}]"X&V&U&U&T#zS"rO aJ1Y:BE'S4^/ g. w29ANWfpuzwywzw {u~ndO+H1C5@7>78603,2,3(6{ =uIs TtWwV"M3D:?>;=7;2;2;2;2;1;1<1<2>2A2B2C2C2C2C2D2D2D2D2E2H3N7T:W;W;W;X;X;Ys?z@@ɆBŌDJPTWXXVUUTP8$#####%*9ŷOʷXж`״f޳hikklq{ʅՋܐtf[OFEH*\ȰÇ#JHŋ3jg CEɓ(S\ɲ˗+;ʜI͛8sɳϟ@ JѣHzt&$IPJRիXjʵׯ`ÊK#]6fٷpʝKݻx%ziTdl}IG߀hFdKD~⟃JSfBK W"xa(,.Z 8GHU5N$UH& 6^n'iXf,R%II"@hy8%2xgqNIU硈&an'UΉD襘f)WhcFj馤j7uzҧ W*무֪&j+,z6lRi$Fjf9FےV+ܖkz:+E;[(�ID, 7,LR*9'JLn4&\R([I[+lI*$ҌD΀s-t"!IO ~ 2YzNyLzL()tfJ1IK Kر ͞3pT9B9%uC=җ8Kc`/QN*;g\}<> sF))q~UIU87JSTd]M+Оf J׶\Tκlw&?>诈TؒOjb'[ł5WVO P7[,U1+VPQhW2bԤoka2OvcKr*pX~)-l;;r{[VU.Qͮju򞋻%-l}j\ȼuVqu&w/a7.9XXr,!%$RQGk `8K2&>\ SW#Ɩw'd!E^9OwYG\ ˅, XV>'~ c.ː/aBp>q80dr%Ӵ9lzuBhxi h(B4JmTA+ѐLZn45Md1ZR@mAO?ոO9ؽεwZtZt/f[CN3 Dswssc_9ml_JGz݌fśn6ɳ_,?nOxm鮙NN>'}{3yv*o(̂=rF|O]$Sܝ渺gsĬk7MN݇5;tP˂:|'!:WuM.upvt=cozT.j\g~긶ʋ8JxA~퉏m'*Jۛ%y,cO>sj|xӻ>lzȿQ9JO+Z޿8^:9骦[OKD*&Z6^{ >-_??Bc旿 Dw7G1zƧC%~;ǀW#c~EG&Ԃwȁ#.|$n7чp+Ȃ7聂ե3؁5h='`:%؃}CH({DŽM؃wG(%|[ȅ(cHU m(wl}bGppmetX)4 oԇ~؅V8Q8qoI27ux{8(0rL*JwENJL(*1RNw '#H} @  PI  ^  ֈ٨dӸ+Pq Ld 0&F¸ӇxX (G ׈9٨ ّ)~ЌL`XxiDP1I ޠ+s0O | IIdԐꠓH`SY!P])V޸٠Bhk^?[YH7phJIHh{wppUy̘x稙 Wɐe)8'h@ؙX ،)aFYP\Ԕ x`xiXyY)y&ٌXy-ɐI a Hy A)9Séjbg 왕Wٛh1!陕 p rI aHyxgxɌtx 82ID٢I IЏ^Мz 飹ɡ'ʈSKW,t (^5TjwBX+[^_va5eQliyk=mzeZ qMz@ dUyuтUy[:QW}.zg-ztJ OHs:xک`ڤ`zJjj8d'0:'Z@::v8ju uÊ, vǺj8:(éZqRN͚vꩰ`0J:*s33sixຮ:*#.؊{țQ,;)ؠɸ+ KqYcSKz 71@)07(ɠ/ٗq! /%i;֮#k8tw~: wB뗦ٗ )ڍ{39` C;*ccBJ~zyEzh ɗEyx˷%b9٩Xu ٞ`:ʝ}*ɜ&Y[kijCK觓A S9ٷA}{ċKVb +FB1kz ilY)ȏ Z;{^ۘI-)-Z{6D̻Z*\(8F n7l 3er\t|kuvC|lc5WҶ$lǎLV brRURkȝvd7B)\ʮ6ÛȐą:yj!˯V˜|H;W/wBhl˷L̞fO97 gl¬ʭ!nWAy !p&~ۢxis9=N[_~kߤY[[ݚ)>DzޠJ1>&,ԉ癞)@ڍ+𝫞A_9?-Ik* ]2?X>DΠ=cz_ϕ]L,?})9_3Q`@ۢX̙`Y'*b.i~-?! iOc饿 rTqv_ɑo?|/O"d%Π>Ϳ"_`zoO|[R?+H4+EfKKn-وf7=ԩ ,^HA H]DRJ-]SL5męSN=}JX EEJYIRxiիU^Ŋ5UpVXe͞EVZ>x;R7<8Ea=Zlbʇ~ چ{Zr/bŌEқ}m=ZhҡfEWRV=5ҵmƝ[nn>+ F7odesyIZO<|Qp 4{_a߇ gWo*#@D0S$u8f~,3 C.80e}ƃ+s% <~QA_1F{mR{R^Q@H#D2ɳH$Ä-2컈RiŏʋdR%2Eb63N9_15_QWTG^o*)PCEǬ+Q l>[ȋNN,Jq³@%u%ƬK=DgֵDN)г+?@*XcE6YeeYpJWr\m*~3X|t[o7\q%-h6<]r祷^{7$Ͻ*]"e[w VHnE8afaq)QVWv~c?9dgةx1b_ 9fgfA+98!Y(hE2P;{:9]zϢ;le" nfZ؟6van;od/(fm?jP ެ}e䧧+QYm(j=>}go$Xugv?B@ЀD >ntcWW8A VЂ8# l;he<rAЄ'g=hW؞BІ(TaƎ+ &K:c(].3x&1 2%b2f*'ÖPtC9"=)ӚRT]ryٞ.)KP@3cR+Fz8\fkktWχOr#bP,r# zC+D5Q"bl!A"Id&ŒC:*'& s(9Te!nb#NKKDeQU[LR%Zi)_!UGVe"nȈIshIU<ˉ\ȹria\Jή⏪AC^VElbW9%`$l4yXVֲb,/rSlhE;Z:N!Rـnvmle2ﳂZ\c8[ַ1mPL:V}o\>+U4׺,!"24.,i>z,fiOt~P|[CfE^$70a5iM52rcz8l`aq;]:\z 9Ϙ;qI F?:4ӽdU q1ۂyD_WNd!H⺼KB08$6#x(HMgA(|݋=YN-@fz% S/\"^9| xJЄ"ڣKm4Oo;fOmL0)S]"3"C/)ku .""]̊ Nw=u_tT߼o!*KU=psc2=P Ox5ξ20S6>r#q..四8j竼7[̳ڕ'?nk6+-9Rt{:+mrocWǺtQVY{tE=Ooֹ.Cwno=y|IFl cݕ.x7>N{G{uWŝ=Nڣ3v}UO[w`Ni|}G~b8#qw~NÆ|?~l_?/~﷈>/~g=Zꣽ3sY?óޣP*K@:,<k K@=C DKk9̿K@[1 Tנ:KD84:{T» Bď[* !8+A\<+C B!-$ 5 :,ƒA/ 6åA.":#:;ěCyB><;CC$AtĖY`RC3D |M8`ɳ3D=`LANDŁ6` 24*'LFLZ䷡x,S, ?5`CD7EZf,<ң;@|gFN;rEƩ;Bcl$G; #-D9LYr:GP,uEzdw}\H;":QL?HFk~D޲iDzLjt@LȊ-@?toGGȐ - )F8DdIŢzG؈ƉƖĢBɃɡ*IcD@tJ|tTpl@`|ʬ$\FJI$KT•EoGT9ʲK:K|J|˸K•\Bƽ$L\T.\K,Ǭ hII׋C? Ƅ̼ hI{HlCLsJ8Ll$,sAKH KM|K?ETsKeJ\GdN3ĤДl~? L\F:A\,lC4O4QlJϼ\tAqMؑDINIuШhO IЛ)ӜPEOT Q)K4= M e혒)ΠELбѧNN޴P$ME U)͗,eLwYR*RznRһ.4;1FQ5nr$ŶR?SJdP?Ox7eKQ$U-G, SUĆ-\ܑUʆp=[%]`V쬩ҽێ˕[m]mێ+VoE[4][YPeKUٺ]]t!ϸUMW\JK]MN=CQ{^%ZJ[-SM_Y^Mً_uYŘ_%Y[E. `XL6K`~Y`5. |͡aw͡9S0A%+dCSDNieWѿ2UZe\Y#k^^Q`Q>6faEf[fS|fh$ipklnXo.^>etfj\ݹbgg˥n|e&ܡh@gOfX=D-^fFuQr&hPYPhhKiߵ-i528fmygn^XTiuiYiRiP-F.&jl1FԡvjkOnƏ6_> :f>ffkpk~亶k>ell ]k>F~>k~ev춦ll[lm_l.m6fmvmm mm>nn>n}.^Mn~nnnn&mi~kNfmVlfNfolN^folo'mwMfOpnfo֎pTpYѼ ppp q)yx^4ygy'z3WKnozcoz{#G{Swp_p,xh, _+p|W|xl)ǂǂx;ʧ?ͷA}+(||vǺ3w)}bwן|8G?|ۿ)}Tqޯ}HO{ ~|G{|g}<~'ݗ}+~G~+}q_?ڷ~$_7,h „ 2l!Ĉ'Rh"FP#H id+*Wr%̗gҬi&Μ:w'РB-j(ҤJ2}1&ȑ%~̂%X(XuI̦bǒ-k,ڴjײm-ܸ +W,{R..l0Ċ.̔-܊/搌7s3ТG*dx)[73lgӮm6ܺw7XdHVz56򏼗3o9z|s8;Ǔ/?:X⯻Wn=ӯ=Lejw 8 x`|zmJ8!Zxaa z!8"%xL!18#5XpYV"6 9$EYSש4E"$GJ9%UZFeA a9&e^k&qY%0 nm7'}XO&*(㡑(ZzihJ'z)禰z**!Z*f:+BjT몸~`{,2*GKJ;-v1Q-hSe{.b;_.+_{/:7ګ/ ,f60 +o0K;1kjèkq<2U %2u պ <3+rX5뼳7,A -?44I[)424Q[}S75]Z0!{=6ٗfeZ6qr}wt7}7~ >xL8[hŊ;//ڐ[~ys{w; :3':ٯ;=;\ ;Iʧn>$~>?^5g'V< X*2x T#JJ#u .̘dHW}jG$ qƂِ@zBchG<@h x<6mzȖԃ2L /0H"H)cL&[ :KY)[-fc @-+KR[82{%I`,0 I*.3 g*df CF0I8D2bCo2aqIld7 73VNd, GXK}cdpP'Ff(eqssuO7ze3v16nͤ.S{)NәTHӡlEE=32221111( +@E#I1N=PFTPSWU[T]S^P]GY;\"\] S G3 '* 38898899:=$G-X5k=BCCC CCCDHOY f msy"~*19>ADGKOW]bgjjjihfc_ZRH;g@rYLgSX]M`WNiQOoLOtIOzFL~DICDB?B:B:@9>9=8=6<3=.='?@B BBB CDDE'E-D/E1F3J4O5U7Z9_9_9_7^1_,bhm qyrurvsyvyvzw zwzx{y{%)֗&ޙ"ۘ*Ԗ3ҕ:ϖ=ɚBMRUUUUVVVXXYZZõ[ɶ\ζ^ضdjls|ΆЊю׍ލH*\ȰÇ#JHŋ3j81B2e C*K+ɓ&9\ɲ˗0cʜI͛8sɳϟ@ ȑPʴӧPJJիXjhdIJٳhӪ]˶۷p)z+vlܻx˷߿˥[WÈ+^̸cǐ ˘3ks0Ʌ;MӨS_h 6`q >(V(Zfa (V}H("M&0P2h'҈<蠎>)IH&ٝJ61 TVVf喗a`闗bihl U2 t 2q6g|)蠄n(n& -uF*i褘fj2\駠Yj"zꪬ& '*;檫Z b k+'6ˠz:+ɭRYk܆+x.;bW.qB '\nڽ~| 7|˜ bpw! $L!;p,&4W&)Gr<) ^'xQ￝&DS@1'v ҳ: ZJmI G8$5$2! W!r! g !w !X!1"X%2KzؠHE8Xl`$HFތh+I1nms(:ṿf>V~ b)BLވ7E:25|$IZ4&ϒMzr+(KTQ1<*U(|,wY&.c]%05a"<2Se:*|4iZS ռ4gr&8)q%:ӹu|,)Wҳ'>O}$@Ɂ=$G2|(D )щ #F3ǍrԎ5g.R9AR #R{2h)DHM0R$})d  8G.Rz妄G.JԹ+R*5if7Tco:²h-[~$ֱl,+nu3*~е ZA ڕ4ةLiT IMh]6ѝnVjS^Wz_&ys4|}IQSaQ*SXu5MYװ-4b0 X )kRbվomAt{~61O\ ع}2^ӂ@͕a4c z iNd RdA+Uջdy1,f0\<35Sn~"9v;3o(AϰІ~!E3~#-R0{SBng+U>I T~өmJWԮrڤUF}ز@jGpX5hy6_-l~MzWn׿Dja_ay,MMX,ovjmnoܾyP; #H/uR*D]ŗ^SWE7\YLۄH석bԿ `W˃ p L nu]r$]ͯi ihojځTErW8FzQ<2c[)D\IdWB@7G{;?x1{<'ɯ7|YV@=*n T`2)CU+\7%)j~sZ_?>/{B'9}^ ˷퇫G>~~ %@7{}'I G 7~XtGzH7@ h}z~ ~"Hѧ pׂy(` ~;ȃu$$'h BH7GqT2|AC(~SHq{NȅPH{,yTb8[X] '1jhGWpx}iXyxe8&~~GІy(+P}xr|z 쐉(ry נ y+cHHkzW۵TAURwmTjTt7TEujKSn:k}wPER0i;*` ѶVq_~E[nU[e9w[Faum m V`V~u<٨&pxKA8oFSg\foIo5_eenuV`TZoZ<(!Ѝc Ip Id]bB&^f p ] 39d+%`EvHPq1'}`!3-r;g3W^b[uT[֑5`57dlXW#+ 6V)JgbYc&v7w_`actoVReBZv36m[7qR'8ywswZDiaIvgkB%wQr9x `vDIQEwyy9ٛ89S}4[zSH@wǜ)eS,LEcIuk)e'U7xemU_8UVl)n)mIFoXEyƒ)bEU' n>BaE[v[*n]_aȶoiGZysGi'[p W0IW.^hUiRSlՓ;?D*7/e67`6[#ebq١YWЖb5^[_[[F`jIxz4bvUbgjgCz_b`n|kɖbQJH9Yj+@YEujkXp5xUfbTԘL6|miQZu Rr$6Gryde¨n_<ȅjZAUkTSʚ 0 Rul(mWO' *X Wl 3D[_yVfɰkn vȶYJu0oiK Y>SL\6qm]]M^4 @ W\9U G +Z)s,R]]VPsU/`Ŧ-`r7J۫u{ \ZuYeky^~Zڕldz&`ua2evT6VeFZ &u\*A Gt;ff6f{lvBMڦm˺YhyCME*FB{M)6! dP6(3؛42,K2[󻊇ʩ5{KYZB͙k9ueSהFmjj&aUhXLlѫzXbzj**X ToPZbdUo *'_9FjVl%1{juF9ri;]p'f]RZx|x}[5?&%YV[҈UBgsU*`dsaUӵ A)p$ ĹcpYՐ[gŦ^\M #ٜXBŞ:W.SiTd%g]|ě˺|8t0< Sq|&͚V:xݺRv|TjUPʠɸ l՟ZdkŎ+ܦR|V`7VVϻ%u*ǚ[ @7jok:TmX _heֻXYZS.IeUSɵ\Lц%$}7 #]Jn.Z r`Pq)=mzz_gʕ^7tJx ֜ԬT͑bL9+:v|~ٚM\_ YkdיX]vt-e4g t(5-@(em( ؊MB ٓM `)4ْٞ C <'Tڝ ڨBm~ک ٩'/ڡ}۸ڴ GBۛh`ȝܐܿmMh`ܫ-=iHٽA ߽˅`ܡ]ފ&}۫{{iݒߐ]qbܟ0} $~ y.(^d(-dm˭  - nFFDB*D^rH)JN)PT~:S~兒Zn?V`'b>{Rf^'hsl&nr~t^x^&za~%t6~VN%d>6>MRBsٜ6%~8^F#;~#52#~/뺾")#>[nȞ3->:^|~ھ^!2^C~>/ ~ >RC￳.._EO-I<2o /"?Q&;R,.2/4_q8:^>/>@F>DFLJLRP_(?_VR\^b?d_qhFXnI[ttIspz?mB_?H_NTڒ|_'v4$H?D"dS#_yqʿ&m1ԿiI.O?"XOJN?_Qq@@ DPB >QD-^ĘQF=~RH%MDRJ-CBL.męSN=}TPEE &MM>UTU^ŚUGKknVXe͞EVخ^׾W\uŻҼ}X`…GejXbƍ?'♒-_ƜYf)ZhҥMF9j֭]۲jٵmƝ[wUڻ}\pG\rƙ?]tΩ_Ǟ]1^xAZ7^zѷ_ǟ_f0sK@D0SAP'#B /hB 750DG4DOD1ELTE_EgFd1Gw4 G2|H#;dI'I),"2K-yrK/.$L3'L5dS4ۄ3-ߔN;N=1O>E?%P54QE!DtQG QH't>I+4.մSOSQGM.TROEu7SSeVu5VYEuV[oV\w0]{6X( Xc;Xee@6ZÒZkZm)[n%o%\57]us6u߅7(t㥷ނ7xշt7`pk 68ahVacv8^!b[)8V1ָcR98NAdJI69EQVeBYv9=af9i95qֹg2y99ۭLh'&h>iRjjQkNkQllצPmnm.1%{g[M\'| Gg|#+3<;]C'KGݵSgǽ[c]k=s{~݃'>ߋGg囇磧~^'_Gg_ۇ_u%^@fDc@r `A Vd D.A.dA>B`% QA-t!aCΐ C=^% GJ[p&OLb<4P"UD.a Y#Ta aD#R"+oF8֑KcMC=r}I=Az4$H-s#II򎒕%1I;Mnv$@Jԍ3)AJUr+aI9Yr%pK풗/La197e.mtڠͳMc5Mmnݼ795qi4ЙNAs;{Oy挞=3}egВ !3A;Pf C[9  d`7x܃H@R8âeGJIaxP(;%QU: ? 8)))`g T7i25 7+ > HPW ^bdfdb!`(]0X5P3I1;-+)! 07888889:<>C O^m'{4?DJXUUU)NA>O+|Xu^ofkpc-T;IDDM?V;c1m)r$yxy|{}~~| t eXUUTTSROMLLMOQKFBFPa|mxrxvxw yx {{  !!! 'Ǩ1Ϝ<Ϙ>ϖ?ϔ@ГAВAБAБBБCђCҔFՖIיM۞S_gijkkkjiܶhԹdλb̼`ʽ`Ļ^]YVTTTTTTUVWZ_uy_PJGJR[emu{ޖ۔ޕH*\ȰÇ#JHŋ3j(хǏ CIᖭ(mZı˗0cʜI͛8sɳϟ@ J(ǑH+JcFJJիXjʵׯ`[*;)[Pê]˶۷pʝKn]x?RZԮ߿ LÈ;ia#KL˘3]'=?d(V g 6:!B}Vhfj h &(r$0(h-88樣\5@YUBiHDdL6- TVVf J葂\) zdapri睵щ|~*!!&Z.裐%饘f駠Ҥ*ꩨz~zhj뭘|믄ik}αt"\ZjVkmvۤҦ׬;s ݸ뮈,kjk3nn[ pwI\[wv,̡!ʾq𲜱4ǜr<&Dg{F7t\ .y1X/s`uRb,p= Hˡq˭9@Afu7Gd+ŽWn9D n_}bnK0hz!~Δn{En6kizսny7uW4H猗wo4H= SG} г_{ >weG @]g +$-~;Hk}g_ Wحvl*d {3DA/)8ԡq5oCLb PPDHC$F .I()FdL㧐=4B hE8qOH"YJw> )H4۫c!I1d2 RRR?EfOJJ ; RM#)呪d+g#TR}.uNN/ zLflAR*$b jh,XhnjMD 7I ӆ߹d9I0~&;9 >cOsu=)By(: O:B| @Qh RX@|g +&]F2Nœy|6|gG̑369qE!j0WG? OZb8=Uoհ"Ȋ,iF sAi#3ADg.Z̩ j/ps=jYm`CѺ򆤐WG;R7 f7ήX@t-d X]$߼)vHR@d~4mY|9G r,@.sS`bfu?Js([MXNrS1s<}@6BD1p`9ƻN8z%|F49ХכY\w8> !|>3 R I̓.t_ERL/`>y\ }{z9~OzsWBы|~R^hq|ߗRw~}?Zշ>|KȾZt%-ΏՒoi Z>29bvgcxӖeevqWk؀geha,~g+ykifk`juWhjg fis`BD6l.XnhFja (Won&ipu6؄qܖVs:"t.qtwoք Ђ>džwP{sqxGpg7i?)ehevfuBGt?f$XwHih&h}&8sX#tFt8-XvֈAYgvO7jjUxv^}xvhHLjqu9"Q8y!d[ehu`hwwo`9xɖrr+D8HYfeUzՏ8Wl5iVyLe&jl% ِYV.WuyyPcciQaK$\%)Uƒ+yPt)I1iJ~c2s=P` 7Q0!=0@i PFy$ PO @9OYf0XRZy0tad`g#9͔q9a viY:4=~rfieiQRᔍ阀u)P;"9b)pf)>zIQə Y')!pP9t9 ^BIe)"Pi i IP ОaPٛipis'o pxrF1pʋsgFq1pʌ2٘z~؁ij6vV@WjhDXjvg(HxCjуa6sc3JOI @\vFi7GooƌmkZlwඇأȈW})yspqp&jvmVqv&o`6qgVy機feI0~Z*pMt~Qsr1xm8wU:rjj}8 :/z_٘I z ĺvu8\xcWh ju`H]Gzx 0z0I)=2˲:-/, 4.*)=6,0* ;E۝RI+A@O -*퀵wQ7fx'&mdu +u'Zi&gf:ilxx)gƱӭԕ)fVMD+tʈ>xӤڹ޶LLՄ2m8a=ӯϺ`mF]RBMOK}ןzI|ב׀H=؄T!S Z, O8g sX,$b{hq4o[l6ԉ[i_ BڸhnLl%hځ3Vxj+܂{gzuz|xۻ,׾ZwpXw&W͜{:͋e p$ujtEGg=LDŽ8>܆kt\=Lқ/n&mMp4TFV~dZE\6!*Ahnh fqr{Ł+\<iiB>kv˸Y\j1ޭ8U|HMO}Dx1GMp g{-s+lޫe,׸^XK~Hk }FvMxjvM.u>#nlMi+|x掇>~)7wfμ|Wg>y>}].ƞBaL~Ki?Klf !Mv )o!?0J2;5C24$&@JB9_F/"?9:%BBIoB?Nj mbX|~Bn@,u.`_|7_Owއ~OO?ACG TFe/g?_/X/A"a_A"2[/F?F#t//HOxOï7k'OM#ql߿x//I׿M@3. Dx0 >QD-^ĘQF=~RH%MDRJ-]SL5męsb„fI3DTRM>UTU^ŚuЃ~~ QZ͞EVZmݾWn[K\}X`… WbYdʕ-_Ɯ9dr}YhҥMFZ5^]tjڵmƝ[n]X6oōG\9`ߝ.\tխ_ѷkBCg^x/1ݿ_|~! +D0Ad07 kB /0ùL;(0DG$D8l 3E_1FPp(e1GwTCa[1:$H#C6#2J)SK2E2K-2$ .$L3JRI&{f[n;nɘ;oE;pi;ZcGvw vs=xS҇G>ys&>o/Jm"{;{߾O~{1GgU}3履__?pq4`@6Pn t`A VPk`A vg`cV?Є# U2Ѕ k e8І uЇH ш*$.щjhNъê(nы0ьw*X(poS8G-ɑwG"鑏̑9e̒!' #!9ԑ$1h'A9JTYĐ(QꨒT+a9(-qȒ)9̌1L(<39M t5Mi<49δ蒜紌9ѹby;9j2Oaħ_ęO~dhPsEhVPd NVT'hFQv&hHwP% 5iHQҎuK+SB5eMqPiP: ըC%ՍLjO ONU*:UrnWVbe&PSgu+3WdΕĴ]W}_KK5,+XTuc-Xɂe1In,$AZF4i ZcdaO6-q[8ko\᎑qE.u'֖`%SUnw^!>4yu^ڐ{BW c;`gA/ vp!Na Ͽ^A|J}%61PscK5ލq\=1)EGȋd%o2Mݓ:)OuU鰜m˝1f1OeF2Yqmv2α8g=ύ}۟6Azy64p.ѨEiI'ҕf1\MoZtuA%E3jULͭFaQ:N5qk5*Ila{FaM_e/v~em+!$ ^^@roWY\qGܟ~-Ի!z׻ m}Z,^ouSʿp Y|yp;R3~„H\ G^{W.BI*gQ9 /]/ynt rusUձNDho}~Zzv$N"7v mŮuw9ykKP/Uq3 e2ǔ|Ӭs?x}c}?4k/))\H!.HB51>@AA?"g?<[ve-c+c@\0@\>hRľ~nX4@RX@ Kd3e`\sXAH\AF#An8@@;+‰B@(9 yjhv7d/5dB;498,phC*?!@C BDT(yD X* J\@JĈDIAX&B3(3V!8X AbEy[0\J^E`laąK(FcDy [`F[^\gmnopq$r4sDLJ@@[O? GOt?qHǥqL@p;D/lCv8HqA‡BD/? $\>lBÅ LtALjɅT8ȍ$tGt?QI ZQ]X^^\]VZOYHM>@4)"     + E R LD&O>ZNgbrp wu ww xw xwxw yv{u~qe#W)K+G'D= 97789>CFIMSV[_dk m m n n o p t y { } ~ ~ ~ ~~~~ } jUUTTTTTTRQONMKLPW_f+l2r:u=Ɇ@ˌB̎B̐CɒEÚIKPSUUUUUUUSNG:8¹<ƹFŵPñW]j|tefPYAR4P%POM LT] gkv/:@BEHO[ehknqw}ݟ֗ғ͍ƅ~|xxH*\ȰÇ#JHŋ3jȱ CIH'RT9˗0cʜI͛8sɳϟ@ JQH&}ѧPJJիXjʵ׍JÊte˯hӪ]˶۷pʝ!c,,ݿ LÈ+ī1H~KL˘3k~رX6MӨSKYoЪc˞M۸n=u Nݼ6μУK\ $1K.ν-yEnϾ :'v酖)o~jꩨ H}{i*ksXGh뮹aB*Ē+$[6kرfWVkmVК7g^ູ jIᦫ5++r䮨֫.ekGAi 7j+WCnXw챧FLq(2 ˒ 0$o.8̦@H{sH' OPGc.0-GKR=3"5e2dݟ=6lW`mMna6ހU_m'_\֊G.j]2gfMXo.Ǝ NSFxz`yjoT[7X#rܺ?oO0߲cL:y D>ᆇO[HD1[WømP)ܡBoH$ Q$:1q/HEшEMq`$G0}1h,X'":&-R4<0 uCQ;n"UH\$ׅG&qLza%?IJ~# b)WIS>6i,$'a^^KXT/I-]zLf9?D*j!gKhZSV^3SkzNr~*99)tn3쌧9ЩS:UJ 8OGM'9P)e\ ЊHE7ڥ i`T(I Jx=hniDkӞHOj"sDMjd:Г* bB] ժ*HMU05 hWJJdM{KmUpJK,ә+Kַa+X .JF ⰵkc'[NJ$bfWX5 :JV cԺ4,h_K[ΐujmw["%pג0MnV FVmZcFo7\z(it%;%yU/kԙk򙫻 K+^GXӋ;)~oLa0tG%l7 Ŀ:0Gغ$NML` *.o$b۸#,>o63bx?@1;!A5tנymnO8C%Qr^wˣrb XC1ϞvON6ӏ k kMV1^ֻr=6CHt$73@wx^6kS<$Hk짡ѯ}= ~P@RV] lgv{󄷛^^O7w ݮ(ɏ a_7U[s.mlq{xv1pw6'L{Jp6'luwm|P'C!ɷ|d@2%|r)҂13P 1dDa57B=?<38BEh6<фNbC!10Vx)…_#&$rhajl(nQH uhZ(s؇~`xX(zXvrȆȈQ._e^-` Haa`dȆ`a6X2gk&mXm~o6mܶm8.m|yӘ3SsqJGsGp{V{pwotqf mLoGqAXzQf sK@oXkgm stRGlVss ~Ngp!5&bxg Gr'rnw3xxnwג֌:jwuȆ%2(9Jsvz7 x7l>V]9pxFzvlx'u_9 W1%ESGxƑ+l UkJl̖~r^wEgtwIkz }ywWtq3sYM}kw֖kr99Ty׀ /wm2')rطQ&I4ȆU5S6>{BBeYvbT̩fK8ITxTV)_xa_Q֝ vEoM`5 XQXi^QO _gdٟ (&ef]V ڠy\Y[ z% D5#aT=(Z$ͥ|jfQ+6Y&!WFӣ9Jg5Iބ@FOQ WLXNz{HIQOPfjWN] X;QjIgzik*p1%wzykڧ~JV_$ɑjjk:V:F`JYগ:VJ!eکJzJFꨞqJX J!:UpzVUJOf(tw~k&n kN)HqJPJl ZuvgNz :P"w 0ohl娏q{~oʮ%ّk:iFQ=uG7k9 wj|FHkg;yM aSc&FlyvnRǔhה,lDI`鴳wrǒ߄S`{@y9ljz{{dɕIjtlnng{+S`hf􆷪7ɖGCg ǹ{˖f3}+O ::l@vy[81{뷡y/ə:J5qfҋjx˽{ ᫄뺖w%.rcں*j%j~j0u˽@1iA 0 dVdɴx&6wl蓥x猢z%s<Ǜ00d =\xWq×Lt%t nM c6v/yW~IלwI~'{nļ!̭ ¬'cy4}*L|׀:0JF7O+wP7 pE. џdE.0\@BWDm,MiEp? J-{ԘV=b\Xigm(nfþ&Ia׎IHZ_]GMS&Ƙ`6 qqnxa| Q,‘pZG7% t䬉9S7҅w}p},vuN6 o65k!5~ \ӗshKxAyc} o} Gl׺n][=-g7| xf z{'V{֜Xǹ!뽖;ғ~w0զMU)۱7ps~Vx{lm; 'ט.P~KN61Mz H3+z0^K'RR]>] UCN4}G"^lMTCN|9,.PR>U2M^-Q[} XUal~-% !X sf|W~^~i(MYs>]=Ysnܧ\u>֚ň>r>]~nTꋎಎ>m뷮Ts>Lm볎!Qd>>T%~ʾ=l޼n=O(HypzÙM·\f n+ 2Td К )rhs~mmk_n戓;q֏ Ei.,‡ /9]xɑ}KW*l0k8G6yˀLۊ\nŭ׽vдE|~hzl8]~l9tSnNl8MϟR\N/ο0ut^e!ߏgʙnlv(׮/mS7m @DPB >QD-^ĘQF=~ %Ms>~Q5męSN=}g[v 3`BF1Mˇ9fM0WB՜;.ڐ4UśW^}23fʘr)̿?Yd6S1s\G!WQ& vn'8-mTXs3_kȻnōGo`& Lӧe$+Ǟ]v^f*W ;W>vc7b?s:@?0B c:SiP&1DG$Q/!? ̟+&RD  3NVLj4̱Dž#2J): Obɏ=S)3L1! s`B3Ms;2L+n4"s3s.#t*!AOSpLEe*Ҥ,_F/4SMqR LlHCԨ]P b$4Jbȵ >;-%<-tScEGtR0/Zk6[mEnY%)*\sE7]uХ]{7_}w/wQ.-_F8aN_0Zeb/8c$pE`7&dOF9e::q^gfo>.)^e9h&MuBBvd:j>]n4k;l$5kfm&[i;oMgӮ'pb?npxog9ŷXxg>u`oz믿v{lC;}?}Gy 7wz٧~v˖>~ '%/D`5@N~ `%(|`5A U$>_88Bj$1Ѕ/O2LauÍ̐eKsy8D""t'D#6щND @'Vъ:+vы b/ь"xF6~QT"8G:z/RG>*@8HBfc HFJы 9IJ͇4 FJvғkd6/I~Ҕ ];TH2ePHC@f0-LnҖDf2K^Z0Tf4y-U{Мf6jf8 jDg:ETb~gT(GDfԣCX'EED*ԥ/J7RԦbf3HӛԧxST#ԗ5KSzRQjV1ZULZkD*լ=*cq5ieIY:Wuµkk^ W?UfZWi"a X\"VeldQ4@V$b`Yv\*^=;ZJ%mj XpVe#kQ [ںQlmncSĵo\^jq+\v1]ntwx\J׺9 !+^׻&ݻ;=~׼ JRرRt`z6^=׾ ~~ȮxQvz-D`7u~C_WzԄiaiڝ0;)= Ir\7e>GI;y!,mߜ:rŤMv b'{v]oNjv';wˆz{k^hx7>#uxT1+|GaG}CmqX[;ϳ}fҐyGs={^|,K4k__^w}c%>C455姟g_q_wxO_?<#>;>;D?,@[cs@.Q@ @@@] AS@b+AKA;AjܸAul\A^ 4!d?#:$? TzcB{B[A BBBB B <à+C]DU[GH:JK6M=ԄP^SRNE.RUVu'XmY"[\^'^ab5pd5eeVrghV jkm_`p=q%WBstUv%sW4zy=%y|M}WzXJ ؂Eaׅ--uՂ؈$؋X؎Yؑ52ՔTe2jؗYNuٚ5*ٝu$Zڠա Gr@6n@r0r r%ȏuZ%I`ZЏ|Z4ZoLZm҈hZ60yu.؏XZc @ZZ[ l\!z Uܴ%=]%f] ]f\rh[ڰṵ.]٠H\ݬ\l%ہuŌ6hU+EH]uMMہYh[r,GU߁]_5ۦ\m`M`TkDօ߄ȏ^^5QZ]`%ZN*^J|X8^^$V@Xb!&$ bo{!Q`lvg Vύ[MaHh`؀ȇ~~!FX`% Lh -_`!,*j229VU~xxlBБTБBln БBlxxlJBBBP,,P l~BBl6ғ5BlBCClBdIllIPQ m lBOQ''n Cбl~ BBlғCmm оXgym5dllmUm BBҤ6y n fV9mCиVm .mllCClBCCCmBle+++msBxy ,,tBrrxyCIm--hBOO)++PP(Cmm÷WBC˶V]0:W]UP˼XvvV\``˻XOO#gg\ttMMbmmtC++*)QS?iimC,QQVV55\cCn<< 0::ηVғmm^^ CCҴ//)@@%b a0BB!`mS9mooxmCS>vv"óV/ғm,cB-.!aUWS>O9V9 ,`A9νXôV //0zz O9/aLBEE$TT"Tvw||bXSTcBAA"/bLsBS`oBH*\ȰÇ#JHŋ3jȱDžBIɓ"wu{ g>ʜI͛8sɳϟ@ JѣHDɴ)=\eHիXjʵׯ`ÊKӳhZ۷pʝKݻxɢTy LÈ+^̷q=-L˘3kތױ琔pMӨS3ѫc˞M۸#v: N\ƽ+_μ ɣkνOJqRI!_ϾmPϿߝt<~ 6`iX@ fpG`}] $h(g هވ)(4҈R 5@*8]!cH&ġD4TVij( H<^`S>p]lS0nixDfgvd*sI袌6z'rgVjSA}~'*jdb}:ꪬFgjڑ%6Rg&X:J+Vkad Ŗ^ޕᦫo:kE.k/Oi4kj} 'lf HȈͱc!9Qd$H=1d`RL#9P[|OJC&)'[I`2.q6rlU*U`S]Ì'̎)fe3ɨaFQfILljvf, r0$9%nP'Jx_{SLK'4Jte %˃:O !NUЇZh e }V̋zTL=ЏkerT${vsg&Z8ͧL= 9 ",.SHQҤ:;Kg:Ԫh]SĥTVJ,5DkY꛳fOlkm;qk׾MyW8fƭ a VjmdXrbh+,xC-bs-? Ժ67NYlm[)mo{>%r9c%wнqЏFSІ&snsnFo|Wp7n Ai&stW{,-ZǵDxB0zkvȋq,'~&8rr)i'sXE-Mx;^hzkJgAWzv{$vq_wy(y\W{fjHBZ!a,i] iH'mmwVsXw3rxwn'rrqc?]'nzoXWk{}uGw}Gqh& {&qwX-ਅj iNAWka}v7ҧ~jizzhjeik&~Ƈk7xh7y( $ Ř#c"LD&qE%(%8fř? ƚ)9)b9_#;b' f^#qr2dVE^hƜEFp&ERc͆E#ޙ9R ]%CYUT\%I<=F5[&R(Z[Ā٠Yh֟:Y{!R`T|Q𡎡P ` @ "|Mq 8\p ~ENo9=ڣ BWDHKꣴq(TZ: ZV\jzp_a*eUgZIڦbZ rvffij:{rxq!qvmii!j)Ws:`w*KZ _AoknGX6ojoȫ|ȪN錷*z! ʦ^mR# r旎nԪx$*وk^7,z`* zt(w tNuIƐwvf8lXm}ծ * k縊wq'7{1YWp7j$s b E|{܇ipJ{QɒP}K몍'oة񆕆>Ь=*U'gvxW綴k|k~|7wtXLJȮʱ˺d qUlJkUK{Ϛڹ{*u*[{=g[+QLvK@u x&zH iZrVlVHI9ꑭ6+pnk:᫡Q"`"Rz@hм&ىu櫤ovHi(`ڿVo tNAF׀\:(mW|֋*کj܈t$R׽lqʈh"p`NaTZ`@ *‡2ǔz@FvA7tY7m|uZ|- yjֽK֛p7ߦjlxNQMQ^|wgoL}]6w{تXa{=BDI.NC>!qJVnXP=uƽK"R?-m]bh^I]avhbha~iܖ\Re]68nuznlfx.i>]>KrN[~.S T>s峞TH䫙!1ѠO~uZrj7յF1l:kН^MߥPoQ~Zo^rԨo]؎*`=ž淮6~7rix&u^ҖXڟٶמsLQ#{?lqծu8歷8s]fi:[o>j.ȵ\YWvayu0ݑmwٲ2/wi-Lll|-| |_zWR3$͇ޖާ"k hufyǎ캮!T?kB56N小05KmLON9_q(iX}N徾{ꋾ/{9kE;j)_s^z̎tƍ}oo :@ A >QD-^ĘQF=~RH%M @J-Up?pTI`J=}TPE@2Lx8Ղ $ꄧQ:RM@ F$hv"ZHX`… D e@dʕ-_Ɯy/|JB-H0ꐴi]X uhV=SszCT A$H`\r͝?N1N-)N!ݽ^|D$_J6D(=o~A3^{)*A0B:<&C?1D2Hߚ@ ,pE|.Md \(h)K "{* !AD2I%% Y1 I%2K-JI/X4V"+@sM1 >dJ.XA%,(FS?$PCl'W"C'RK/4SM7)QUx'+9E5UUWeUW_-ӕ@ LV]wW_PY_ C q 6YeeYg jh JZm[oeUZjlE7]ueELTJuTw7_}#xqH[_F8a7&c9ذ\b/xɆc['8dG&d6v)W*d_9f9BjwgK%F:i7hFXbj{uZ#6䫿;lZfm+VGW;o[^Ru;p'Upg\Nq'\츫m+sc\sYVsOG}7_=}Cze=wݕrw>xyk}xg~wy駧>o{1'|-{1|߇_aQL>~?@B?Ѐr6Ё_WVЂuh¾Qah?u0'D@20/V9І7 7Ї?UC шLӡxD&6qf:8E*Lbń%1C"8{p~ ո2OZSD8G:zˌ~G>.ˌc9gay$d"+3Xd$%٪Fud&5Fd(EYF푣De*7:Pe,e)Nke.u Fne0ɜ^Df2'KSτ&R$!:FD4MЍB,~Mr$K8qqӝԈ7NaħDNig@1~VhB9UhD7O3&D5ͨUԠ*.7:ReBLVuIHIaϣUDFY:YKh4zA IUjh?jTjXIR:EfÒ*U*HR3VGdϫ X]UVi]k\a>~zk^qHBxk`_@ExV6TBֲazYΦwmlgE NImjX&meR֜v- YR6k7׸m[m[6{*!lGZVWzZmoZYvt*to]P.V[^0%/s;׭$7uϭd-9*p{޺ pWpZE7[px;|l,b_B_<\c/%g;{rH6U !_y#nk\7_&js\0 zys3zѕ>&7KOG&i~utzN3 dTCi_{)( ]p{)@,z|f#:OT~f|rG>J7-DW|br^w.m^j=u\Vua^{ y/~W/o~bo'ӷx/rs\M~} _'tCgW9c5,:$797L@\?67l@|@ 6 @ T6 >,7T4Cܸds?@LAܷAzl Bs#"#DBlS%@t()!+4,$.d/'CEk3t4TSc67CL9:C4<5ʮܣK:˱d4K5B˴dK.r˷ԢK*˺tK&˽4K !?ԪAB5ԭDDEe԰tG%HԳJUKԶMNԹPQ%ռ4STUտdVW”Y*U\]U _$_Vb=!bEVQeefu :h hku kVnoW$qr5 tueWKuwxWNz{WQ}-~WT؀]Ձ%XW5؃ՄCph$08hX5؂XMYXEt? @نH>`肂P+ٔm9.hٞMMZ.q5Y@0X1ڛ}ٛ%ٞ5![-رۭsX8Y۲ۿ Z5ܱ[ZY[BmZZE٠Y(ܕH^\ܕ\D[5\ݷ-uZue[m۽ƾ>-2Y-ʕZ%\-[ڂuUټ٫-hZ٫]uߕ͂Y__0_C_UWPVVU@;yx`@;F#@ ~ a&! ԇ\HFj` x٘u_ޟM\MًYPڇ@YbZ[\M܊ن8[\肬5bB%Y\5^%b0]c8cc}p0F\ \}ZEeW(_;52؄퓋u٧UPQfTL>-݊Xƽ]+6^B^ e}]]_6!&HufU$ق8.P=d<~ !,4`222111111111111111110/2-<(JWam|wxwx vwwxww {s ~o g \SLGD!A$?<92 $|wq lkkkkkhd^VOI9)  )26788888898999 :%;+<1 >4 ?6@8A9A9B7D5E.G0J.N+R+Y,_$e"i'j3k=l@m=n2 q/s,x'"#. 6<@AAACFMY `eil oty)7@BBCFKRY]bgkmpv{؛ՓՑ؏ߍ߄|sniݻb׽\ҽXϽW̻XŹYZXVVUUURKőFʍB͈=׀0{"wws p i\X\H*\ȰÇ#JHŋ3jȱǏ uIrdtRD.ȗ0cʜI͛8sɳϟ@ JВHE:P:wFJJիXjʵׯ`&ETӰhӪ]˶۷pʝvlɲ˷߿ L0A$5̸ǐ#KL-T̹ϠC.|Yd;ͣS^ͺװq:۸sͻڽ NKGμУZسk^:;ӫ_?<˟oYyu?(_&F(apNhfYv a$hQ,G*(4XP6@BiL6NF)AIXfZv嗏q d9f\pri0щ|~*蠀ju袌hFz壒Vj鑔^9f駠iᨦꃨ 무'kJޭ+v*Kfl6ڲF+gNkaڇVm+k.hߞXn֫Ӽom Ko'l 70G/Wl/g.wl.-"l-&,*L,.+2L+6*:L*>)B-)F'(J7-(NG'RW-'Vg&ZwM&^%bM%f$jm$n#rm#v"z"~"!'>!7 G^ W gw瞇袗ޠ%骷,.$N-/*O"'7GW/gw?އ&槟$귟/x?r?!Lu? Pt?xDș@ zP8l`R:&4 {3A rЂ+!lZAP8LM ]hC١}"vf5$ DPJ$b#Y"H+\ cDJQhv,1p[>XԢбy#!%$#'i1& &KFqHYG7򔕴MVh$ܠ$]I˛ e-w)0EO&rII~i@]&AJ j)4M&?$81_ЙL¤)DtH 3 t8rtlSOS-AytMB'xDi9qшfBȍt5Iz2t,?^Zj@$rp/vS8#:ȩAl*N@:8Tr*D2^hC8Ts $=2 ^+D\Q՝FEHOA :)`0WC;G`ꎲ;_yj ژd@R0D:k[/֐u5@H;=,gUXe'jTĶf< Y^-Ef\ޱ4"m*ԮHMj;+xy!^TiP'Բ÷.zbS&6e[Bq6-xS+CzM@{]+`CObr56C٤ô+TOjU6i;*X `qlK&Wuy敹rPכ~+XR2Qk^p7UZ\U sZ-xL仳gϾ3u'AۮІE3Zu~"-iQҞ45M[ӞCQZq>R-v9t.gZVIUTWZc@k,l ]-sFU4e=\S]Ċͯ}_Y WuE<ݚb"H|%N_8P6]{lȯMn>WixV: zL\e \ޱyP~gkV2ˁGbܨtu9{o[ 䨸$~tWnBbቻ=z| pӭ᪖8v1=Jي/*zc;8H)~S $aq)d; cȀ?qX*xhخQy kcbo֫ĨjzyMˠ='kAzx`5-vccܰPUݷ?o?~ݒ1m{>&闭ߵs?k~/M;?߳?g-28%S2 0IhD70Q087P%hP*40&h(\303X69>ACH 47 GxIЂa^9%_fkUvVmU{blgrDQH@vExeWY'}unfV\_noG܅W5EaqHSVHEz\[qZU\4cva^`yX=r8)S]E e]DS%TFsOcOlfo`]E4psES'anu^we&\ĈeQ rgaa%h.V`UM8\Ԋ7?f]b'd&coVU׈ Q^-F18E%%sEfzfzW{VqcqdUvhdC9@7Ȅ$Hch X:?= ?98SxHAXLٔGQ *XU9?G?)0T ph1UfV6q_WcwW}gseUm){bEV6lbj搗AcIPC6m~pZa%YwVFcuTbW Y5W}X )FZIްrC ׆rZ'Zo4uGd7dfuśSUy0H \)t;w_ו8écƙkXrIye'VCt`ȅht#9 Н2rVbEw G(CG:Ɛi7v6 zo$q8 ` a C 'VxmLvbUrbYX/ 5k(I*aPڢ1zlzz"Xq YmP{ȉVY{cȑ_ :LK4oM+v@xZ z M @ZMP w*0MP ڄKl\1af`IE,U@]1v%l#aTV_jrvD饃olv Z؆T6'^iiYJo9u\9dbuq^$Y\cq(l4qQ7@s%Y:sɰAtYl; u;c_CD!z riGUrIvHc Xc̦!׬]X \&CE*&dˏFF5ʅxZVKFHZy- RATfu)gz{(eT+nvhdnw-'wV{Vw=+Dz/|۷>;R1JZ0Y#+EV t"YӠQJ\[ۺ-;'<.wruUYT%R%{Yl !TlHlTl5Em}yֆժwr0Պf^h$[xIqVvDF쪏HmjF8y=*w ;T,OŌ [EwyyDt7̳Cwouw%xڨk$e`H, zVCt|BZFwhhf !GJh̐N XoYW]A,wnG{iTo[JO"*7V$\,̲ɜ,/ӿh\ʄvӼ{SH;llxvSѫA˭g FS侙Ƭ՚kۚުon:إ2؄*}؟؊=4vؐm)=Gؖ6ٍٜ4f٢m(]Oڨ5}ڮ=5V۴m'}W3ۺ4o5=F#m&ȝ_S3_=6]6C؍%p32 287$~]8]7=m7nM ~ 7. >=f.7~[dq^*6N3Nb .8^6`~T ~SP\N_^fn~:-Mk^m[7dwd|~:V'n^.4#犾Ѝ^萮3Nj^'^pZ褞ݗ瞞n$O^1$>n.$W@N.~1~^:nSN.⮀%2~1ޮN/I>N6.^~0I> 2.2O c:P&* cY0_0v4_.~p TNFO0HEDP:NQ^ŚUV]~VҩEVZmݾWвśW^}a]FXbƍ?NHaȕ-_ƜYf(%YhҥMF-sԭ][l)Ɲ[n޽\pō~\r͝?/tխ_,vݽWx͟)zݿ(5|߯~?$@40Ad-0B '$K(0C 7A?1DpDODQSdE[Egqk1GqG$H#9H%d$2J)zrJ+2*K/K1$-D3M5=:sM7߄30N;IN=M>H?%54QEODtQGͰQH'TAI+4S.մSOSQG.TROEu:SSeVu5VYsuV[oMV\w5<{6XtXc#Xe+Yf-gZ6[mv[oWp%W5qE7]U]wCb]y(^zWN˷_S_ x`-`MxamaxbbqxcccQ yd?-d1Myeme yffygg zh,hLzilizjjuzkgkY {lG,l9L{m)lm{n n{oo |p+pK|qǻkqɭ|r˟r͕|sχsч=wt.tN}unu}vv}ww ~x/xO~y!oy)~z1z9~{A{I1|ׇ-tߏ}V}G~L~j@3`@x4:@%84d@'AHā Ё/؀v 'LDDA |(abB~4/a:^F0G/$6-E\8菊WtHE-nщ]" :4cF5m8A9qucGHAҏ!>E.}t M۳%IMN|'ASi{rց"x3;+VC*Uw*[|\!,:Z22dMm4d..d3dd[aClMl-db1i,da dd!da0id1iU|l=tBkBКMmБBCk1d1dБBJml?ulIl4d>ub!dBb db3dlBBla~l2dBBBlғB2dmmBlJlCClBllбl3dIk,d%lBLlLmCkғCmmKl,d\llImRLmYlmLlBkBKl3dBBlғJmͽ[CkJkmmBlBikCCCC1dIlllKmmddBdKkUUCCmʿ\CdIkPkCMl[[-dmCГҴ[[.Add\Ud)mCБB^Bajؾ_ijmCĺ[ʼ[LdOjl?h+k|Ľ\dVdғB-dLmd+l|@ov^TQ Pj1MM'qDmB7 _SAnQ7XgMtJpU紱\v^l/u* K:WM1ߓ-5 7Jxmzr-~N+l&]5%ΐǷ㦮J欷~3^!L}{e>.1 o+poL˷:"ߵwy[|d=*A ǯJNV? [GjkYv/^u3%47hy ޞ4A.qpA r0|>Jq6ɦrHr.xk%Z$A-*a D"Z1"&26Abs>@=*VhL#mȬ&'bJF,Ab\M2>Q0l81ōrV=L OUCBd'III`1 #IR 3mȒ0d'yһJ&4.wYIj`a3,qZaf:,` nG DJ%4$L1'<ri\ &}35S;NIςԞZ#5r2WD +Or4F7*)gWIcS+dNің:֜Rl>)@ fԥ@ @`BIP4:Γĝ\PRRդ?)ru2 oJVZAnp֬Dt_ T{BhsԬjYm1Nrd9,ֳIr%M-KJc/^g̹0ٰgP̖bIW N&æ[0/uY}2MO9%WTf` wri8n ڒI𨕘 ] [$joZ.՝Q[%J vƊ7d}o;wm8ޗjOWf{% iEE;!t >.e[;\Z^ >䊊+Mnܒ 2Bs=8T{ɥ/bŕ$XNsZ'<٦WrHVϺڟT@@Qޥ$-m9;ǂ=bABr;?mO%< ՗?{Owf_0L\x9wʿD=;]x>ięOס>2yۻSu>oQbߤ^?Wg''fNs[Xӷdy:{ kW}8շ,PZWzh3 hxi{|8hؖU0(#gs(wǂx@F4 xy&9e}AL1;Q6xKKEȄȆjRGAF([KYr䁯'pd|G˓}gro0CX2ixIXgHȃbs8lg<.lhB21py(h6Qo>`8N/rgh臉hgf8!4溜h|9@^8HXO-ywyhBȈ'XZxz)I#X-yYy rꚦel9䊩 Vuxj): jk٥?wZXՈkA#*֨z"[y&+KzK/; [Ih;밪.۳Ԙ>#cɴ>#J^I-ѱ X l`3(_ժcmkg؀8cJ|z*s P;+!E X:hc ۯke ?e˧o@T rڹf[/%; |k_-3*Ʋڑho-뮯K`4ڵ,1[t1:1͋l^Ky6ᛧyHkB[gHU  ĵR:(e q j[&|* b(b۸FyRʓ(,,g`d5l컜k,qöAx0(Jy1Eܽ~{JLbg I" D[,:[ g3%vYz1g+ @k{ |19WH}m:2OC SǶiŎ QY;RYǞ2ʪ\2 p(.(@5 lA\ L) ,̲͚]/ҺQ >|[,QFLa#@'Pm(\,}qе#-G M @d $mPmq\“쑊kɰǨ`A@%P|B ME}m! PpY\ͫlQ#P(mhD2Wjvl,2ʮ|~XU P ؆ˈlpYٛٚٲϋ h+jqljV6G\ӗgʧ,3 ]4p ְ01͌=܋]}' Um؝M`-ֿ Ͷʮ| @ޏi n-1 AK׉x]wZ&V+o}!r\a/<;ٵיLЗbP0m_۷E/'snї/Boq}=Βm鉕bG|TcΒ^{ّxɰN~;Lž?pOb1/.R7m3ٿBn@1/.R~[{xqh!.R~[l N޼V~n*x1r:},Z}g!do߂w/^._?MwF|I[J]?{~r)jU?:{w?o򄿰f߬m. Tx RCeӶ=QI"e[@ҭ@sbЭ$B ;S/"CAS_^x͟wx Æ}Wn@?܏8lD#cBP`rPB #P|08@#"N0P)@8P)sG2H!\M 3CZXr.(.zA#ӬO?+C&xӹ Lr /7au(fsAC. e3WÉpObx$# }@A<4JqոF6VS`s@25VMp 6Ґ$sJ;#2%:/J$INvu" N10dI1JdEIZҖA$J?. x%i/S[_,)2[6әόV. R!(LDcix__fBӜDِn!*oZ j$)tӟ: ҂pqXz.SO~ԢhxHFT!d<I| 3R/E`;E9S^sNK*Δ.jP] S`a4%OYsr}^0; BjVI-4A)JRo4J-h@UUu=DA;\SZCW2dWuk`{H&HjW`מUq_Vֲ8T +YvKlhE̪hEmj6Zֶ65-\U;[ڲ mn'ַmu;\jnr ׹ϵq\V7$h +f5r%!tEF)VUj@DD`{S'F._HWn&V`YhšrpU[0*0"NS]@@xN0Uw/1v%N,IP2)*#hΎ6$DB!L|,b!̗+0eL:7mj$G%)Nsj|_97I*u:QrR+gr:R(=U(GF1JzeqxD$B>PNPb#(sgԪ 4:'M1ݥ0:ɫY%Fʪ+jbDžԧFlS}N[ VUHBޓ+]mW- JV79vefqnzwz[wny p}& H xIRw5Ѐ4Pq\\'8 2q{\b,M%|4skM^FUKHjwEr\ r@N\Sk~eNst;N :1vū8Dj:<(‘749H(xL>S d=9XF$ KK){E#G˸\$KL$lH D4@4dU44O C/HAT1F{44t5|W &d|OZF\ %D۽4)|<;A` )<1$4`{=?`5T1tNͼ̅-nK0 U $GX#LKD A3A kP:C-.LBQl-{mRi$.'SsO\D94+U-/R0(}S';2  ;I<&8QSB]SxF N`ƈϳCO&TL-\%NMRtRu.=UԞC(dpHQ.UqQD YӐQSUsS`U-Є8M.,UQ=,[^SOlK4gJURTi:%WpSgSs/:%mje8=Oad&(}ԂWNІet=׎E[TWFu75׌TJ˄@XTw  s؇m8zSWk-e0WXUJs30YW3FjdtpѢ E7NÞ=Y4>E]mV+!ڥ SM.MW-OX]ډZ[{7Vb9ZH5m[UU ۄx[Uuܬ M\[e\Mz}+-l-N ;[+y5iͨȭW4]X}ݎ\ ] \݊(aۯmF^_U۵<^ u%Z읈]ޮX =;H,XvEAp# +/Ñls,RDS6!ߠ=m_5 Ŵޔ _'C4t>/|<0ύ<"1˰"<94Jޛ !3BS^ߌ"a뽝=.>+n,_bA WI&2"s=(cb78LUUT{M;q #Ca@VҧM&5dYH?dxMzc"E:޶]}bI<&'#a_ AђpڜeVH96F#\NdZd` SP> V僀_RcA 5b)AX.B= H]1ǣ95r^d]P^\Ռ^cRPp>/IAxMnN %SPLl:bijE^h@i5(^f$vݔfܕfޡf&:n]@iPfij^  ڂFmfOFߤ PߴUvk^.k^lFjjfkyv+]j4fk͘5M` .iYɪ|*::Anh%r֣;^l ,7e.J.F1VJʻ >aӦ%.l%k^뺦kbس/n1Nc{5@l4:7vl hʽn֍Fnhl5b?:D^d ꘳6CG&>ج}o8_oÞﺾoio 4?o. A' 7$vf]  G P>ҽIs5Ayߛ(d5&+sYLP2ƯqOr#$6]4ƄkӘn)Q sZhsHWޓ@ċ>`Q(Nr9:6m&W/EtrOENMGurgF 8Y>ux$TuY%@r[ _c.9/k8u_gZdvKk7nwk'wY\f/[S?rwYTPdmaSYvƨu|gxxwu>g_wTtjwwnfhDExQ'ՇywtZWoWywwzo{CضyRR5 !xmWEiyEW~IOzDiyE`x߬7{2iyF'gx:3mi%y y'| I{@w—I{'BWe^o|ͿH{LJxf(O/ve} {8~}b\Z/[oѷ?ܷ}ҿ>5g޿~~/Ykx Xd]&X)UZ75I8!Zx!'Pހ! HeUu[\A68#5x#6mx[Y'"R Yg]-IQJ9%UZU]]! J5 Y1^&m&4X@1PyHc b]é':(͉Ye'uJT IҠ y ,)*MYq)\yb'J(gj*,4kfY g2*Ċґ&qj*Κ{. bY.>d`X/kf{A΋:0_m![|16C0@Qo+¥-ߒc11<_;Dٴ!#철\*;hBDPҼ4M;We"jɣ%|lY4eMv cDW?ʛyw6} p qٶ`LD,4K>9'}\_XZ婫/TDn^z_# ?<P:j;ϋ {2E=Wwj|8Nuu{??cXT/bЇE:Ҹuw2p/KȡoK #`Cs`mS'Xx O i5NpS}(98Ǥ^+0f򢰔=!*ґ(7ЌˠWHq6?;d M;kyӥ2Yd'4$VLYJ* \MH2Ա>94Zz]@ڸI!W5M˪׽nEzPUc0.;X|},d Ujao6LGmђ5 U-.tF P--ns++r(2Ԩj fc[]N,qɫn+ݢL6kpr] HN1kQ ^HkPН.zӫC(2avɧ/tgbVrJU/ܓ [lR)ak \YnX<Ě 2[*$0K"x ]n1:wdS'm1+an֭L+g] TN,uj) $!we,(K5r}AKgƝekB,975hrc]NpKAG7[cՠ~F3F'a|:Ж&}3v]$4jhʈWN蟃k872iRk??"Ceיr#DP]E?]g ˙! ඙uM"6!R67 kkͳi^ySXz #;cH.q'ΛH&E>vBdO*` &;.뉴5%9]% E-Γ~GYyBaH[ޯ͕u)cK OHs7]l']Vކd~_]_]UR=wV|k6fI|t|55_`:}DcQ,;x=ם-lcw=./}>RU;ƥqئִ}%~wr$m2Ow\)9?+W?\>PЩx=5*_=fݚ)D%mKQAIZ!`.t^ I`  LZ\ BrA,[_6!t$%m˥w` z_ :K߸UNZ\ aRa!ภ~Jax!EdbIѡQ-Q`~pD &* * be`F dYn+ xbxDaQ婢AX'-I!0H,⏈L ]+Eb 0V#IP3^aa~9 5Z#:6 6BU #I}"".b:#\A)c"- F?6d\!!D"C:HDdH[8 A H$IFd6 -Ύ-zcK)z`bR^HIdU2zI[,d= JR~%l\(γ YP%%\ZXGY":b4"LrGvդMΥaܥH UKs[~_^L anf}%Y$E G%!+P$gt׵Wc ΘZF&VfeQ&lseT2WH^LXEpHevW'vq&r~E仰$Xo[`afjfvglfd*>'AL]&pqRKw~mLeyUrPF(a Wȧ{ڧ %¥L2zhaYWhxJn8>f,ѤW\Ov⊆"iV~Qި6i`B*׏v gip,hfmWਓiM@QM)W 舒ΩSBrTʨDhj%=σ.L%&T\Grg Ha')*=*J@)ġ^^aBꀉ-q&`EՄ&솟.jvWi-l&FwmF@"J`P,>2.˶TzG̶ )X0%jiWd,n&m fF*W ni.fI0 тEfVMTbQ"+mf~+d.<_m/dT/vjn+m 8-J ?12O堂h.0Z0fdZBnl藪pZnjN@JPjVrjvLW1GjOfD>o~+\e$ g@wP3{~kqVo 5n8/ޱ#0G$I3O#*Cn!;2\к|m2'P,2+r:r,22-[-/[.0/3J0"1332'&.s3Os=344S65_f6st7!83:# 9s:s3;;ó=<3 =3>o ?3A@ttA/n4BB3DWCgDO4FqEcEgGgCouGaIĢa4Kta4g´LtHMtNtOO PgtQ!uROR359S3tTKQuUUcuiVsW{́uXX5əYsZıu[[u\s8صRu^73 P,5N_3 $c8M"vbr`60v@]C6Idbc c[fsyg[Vee36 6/jsk6cvimj4lcvl`wppwkg `ros6tqv r3avkvktc6 6m#xWswvxut{7|yöz׷}0v~nc|w+.qOwr7X{7x7u[hPx;مcxt7GwxGxx|w8cx]hxwxxx{9gw<9XOxf7g gtI9#q#x y9ږ疙9v yi9WL hzyoN+:d1z~ 綗vuEzզv#zY\ӹW3 t˹W8ϺS[2'tCZ/4 /M5Gw:jEc_4c{.?#{ǗC;w6:.ǻ33;>;5?{3k3'|3-<.;KNjãsk<.QQ>o}cx~q-w~>dǾߺzڋ8~E8>z C8=''?ZC}kZ I?"ÿ>9>@H0 ((h!@C!F8bE1fԸcG 9dI'QTeK/aƔ9fM7qԹgO?:hQG"8iӍ$(048 fպkWC";lYgѦUm[oU.Gmpa]6naÇ'VqcǏ!+80Ta(JsgϟAF=tiӧQVzd]̻um۷fwo߿n5LEqϡO=zuױg^xtJ{yΧoW}{~>@? P ,CN ) 1, -6P0QLQY61citDqQy$bKj,HnQ%lI~ Ɓ +- [ |ŵ*!oOq)1ϼ+IA@=/EO]uH7uP_]kc]۲vs]҃'^2Γg^A]^rţ^[- }g__ϟ?(;ok C7@:̀t`@54\%(3 Zv`O0lDHBJ̈́'X WÛЅ q2_7)Cˇ@4"„8DoMW-&:b5*nZW"E1ˋ_4UǘFVьB)6Qo5G:ɎxG4|S (C.reL$ #$1+JVrp'uHNJ |&G ?S\L%ZdmUY"%UfAKz! ?GKZӞjY ObMl%[[ێn[.`[\hWU2KW>utKv]\/xA &HH&D}`)Uk2xI~A/v`a $L590Tܲ$+,|/&"$.q>/KZX@,Y U eJ mA-ո#&pc!#f1Kjr^r/ " 8FMc.m h,~0ը&[]$بuHH1qoAr%7Qr-wX@0P B\CBÜHDlzKOz tG!Cz-܅j ]GIǎ{Mbgb5`3趫=4^{Uȝ𬲻H<+{>h2/y(G1全XFr؇wB~4S#}L;~d^𨷽f^sg8q{8L1p{% !,@U222D2f=e=..=6#Uf>;2X<+2e<+2@8A9A2qQfX;D2Q6@2@2d=c?UUve>|Fn@b=o@`<  Z[`TYd=n@ace>rEeM6T(]Kc?Q H6}}Q`CcbyEFUIXd>@nOU(^K:6baMJTŌE8(L3=ZgiO_ T7q+]mD_OX挙#?HWw{bAQnuӄg7^dz2Gg~m'^'[fB`v6qGax!>x_,O蓊$nx҉(r`g#X5f<\E$,~1YOVdag ` rb[iy]N4dgɒxWNY'~jZfٔ䧜Yܞ|:&r۝4-*@1^-E @`w!Brf„a饧:gbDg3-Xg@䎶j_FLk5D&,H2kЯՎ_.Iʜ[ɞmzfJoݛnXy/껒r8f{, tfD-|YiS B6n0Gz, ,ɘj LJCb\V Bj?;4oP=sD6sSG-TWTpNz5HCuC/1rFm]wDAj ;@QvCuъ/6kS4vl9tN4Xx[?y1 ;zLN:[ט1nA;潣3/nBO_.|}n}BPŽyk7.^ACRc~zd"VSҚEv/) h_XH'!W- |Ѐr!i/n|^BY"!V~+ azo%|F(ŦLI!*jã` )8 fq}["lڎc YDpP=b,ķ8Fg;x8y _=#etb><Б"&7Z#4r@&=1-Rmz}IPlޤMg-$LY"'na/W )WL/ѸE:v&F&腰4'm^B*VªIUZ3J#>+L$5ҘCL+SCӍu UmQm:*%L:{V6_7RS–&5 ʿև5v$[҄g+/iWD5^+s\I;]ZUQW\G=i%b&dՅ*Niԭ/]{^Ŀ?S/СW{va2F$jY{{ٿc9'~cOZIVr8g6pc<~% Ɨ"ppu̒nؾS0U`)LFX2䐠02V],Ufo'Zy".~(s|䌚PЮBeg0[ɌM|VH#[>rҸDoeV';Ej/l*Ҳ!3 1W;C~{H~oѯ˿×c}~AEk%xgq~wc~}(vx,g&}bnOcguWa'|[k)W|ݕ{~".v,\wvev]сORv,+ U kkHK+؃Wm98~EhkB%r˶O#GKG{wG5rNefr!-JD"^UITKh8\x}H|2h!-Fg~r{cv׆|5xqEyP%p6tslxuUn-waPi\\G膌w1AQ{!)⥆dXv8̨Qu(Ә4~X׉>xi؎>yфXD|Bn(~Nا@sx.(^ y8Ȋ:8Rp1qo 1bw0A(bQGZ" I"H'98晴LJّ1A(Ksr1 UO99.$yj3IsRYo9؊3a7i("){k؍hէ/!'[E,NXi;iFWwh vmJzqAu>&sI})swb)*9't)ٕfHA2& WY8ɘ(ѓ?Cه_iRIt]љ`ُq)'ΉlYԉةfyYgF)Eɩx6@ ֝G >ȆSee98` y-!&$%dʍZ9)!sq8}DjjۂɈ<(xP.JʣGJ.ɔ=JIXhV'85,ڤhY8ץx4JZ!)2 1,HUz/ i:)kֹ; 4falD%|$Pw9:;x 9WXjȶ;2Q&zjRJsZJ㧧<"z5zNJJw ۣPI8ntz9(Zԣ ꚩ*0j El^ɋQq4gaOQXSYhtaڮ~ T !RE SŖ%, Čĩ!h:\xX\8g;gضnK3?' y,<,Gɛʩ ;vk</KzɨxDKk̷9#? ¶#K@ɬ,̩=R 40X{qls xܨ2#H,|%׌͙w |``6A ˝QyQO ӻ"{?},{ǯByR,)9/<&mqb"Ѐa4Bq. @<qBѸ1P^mD$@ҏU=l-c4'&t}x | ŀ= Ʉ}i׈ؐ،$ؐ=!ٔ d}ٚM]&- >M> ȍݾ%>N=.-,;6-#NMXD=P 3N C^O)22pCZwL) 0M}p9N& qɭ@!{p~Yn=?!ݭ' qfn?!@>^O<13nz~>歾[~7Qݐ^߽>mtpV% 1n"0qM0,~.ak~I~]^ fއ~.QNٿ"^Q <oޟnO݀ 3)on><>0aDn9pnFRT /-J~[o;.쑮o&Qh~H/eOv/,AM1=Rn!Ꜯa/+~ Zog_O~ۄ0A?ON_-IO.ď,o/^_~M@@ PB >h  F=~RH%=>`pMT/a@ AAA6;"TЄyVtOM>j0&N5Wjha+WE6Q+X\uf8V`Wp2ж/\r=VqĉRYd/{!逥{Tbْ-(C ʭ]E( aPbFӴ jNzr6HԙZ9p1ܴhY6Gy6{ŻzzG Ȣ,L= ޻*sxSc8 '$1=8c0)PL 1 @ E3*l+S Bt#BԼCo\(Ǎ3G+'*]I%@DƇè+ I%|, B3!PASsKNEs],ѲQ?OPA T)UhQQ<`@7l*>SOeL5 }rp/u!4#<\"@%c{#9+ՓH>IX`cM6e…g Btj(1YeWCUKjR?=CeJuˎ)_4$ˆ:Bz]wX*WKbxXA>:cONK~䜹 Wܖ8"xa{u-SpZx}M,j#sY)bVa0bj-{{k:b xSd:^)dmRLmV'~Fw^H[;Mj)j GA|5x㕋İ x[D_tbQg۲> t4.&یl(S$:ixCyX$zU{1>IYF؊*=UzQ !$ ^GsZ7+o\go9hͩZ?c~v-챗ީlu#wT'}<3$7qXAGzYl_L {qe9ίuڛ|u`W:N`> c6c(!?eS 4HK:+9-l!3 .)  q>+Ȁ=ɜK $4{?34 ;8(GA`3-K> ­"nRSdc@k +9w2?">KX65-I#>һ>K=(48.܈9>=%kBC4 Ž?DC`WDP"cDc0IA5ӋY %J{B+E3$BP>lU|čI4BO}j %j^1 ;`ORi, R;5hX# X<쪧k۲9s@t9@9E.KŐc, X$EwlÂŃR#9o#JiEdT|,zcHp:{3F\T7TƃlCDȺH6;3TvÒ\;1H#H¾Ȳ@:I2ɝ:ʠ+G4L|Jo!s [^Je좤lImȩcGtI1Exj|ȏ!̗8+J۪m$ H(r rSGIɻŽ,,ËKqSzDTT8dŇKdFit(IMLDJє p {ʴ ;`{I0MbBIP4N:kLD,qj T0cM:Mɰ>ȸDlÈ|MHCyET?L˂KPMHװ 3MCLQqa+O_=\=G*,0DD/3к꼡K\41$.D-ҝFA2=&'-Q2w\;{T|?;iR7 FQIQ Tڿ %`E!4K+kFʼn *T!4NE#O20`!XΐU\Lpb2l!X ؍ F-dcyeզ旨bN(d]Bg2无'xdmZ0f6dk^ChsaI@Χ e &*ge2&xA_L]!^'!\ H9 [nRA^l>䏐dlFjtΨhuP c  Q! VְhNeja-jviNjʨjSV>P珀UjU%OE> nfnGKmb)'P3[kƢLl~e\&U^} nk}*@6h.4%h-en~nv !c~ v؎'a:y_N7'i6nf PrS`w wh$p p+qCq89gYqxɸqr& 'r"G% $gr]&(r*r+G.?<0-2W60?4G5gs"w78s:;s=>s@GA't3CDWbFGtǒI;sK9tMO8R:uQO/N(@JWuA"WuY VW/r])^u[/ub7b4GvZvau`vg+u_[?phv_vpqNWG`v)wuegvl'wjw|w:QvfuG)xvox_uRGpgyxj)wW\w O GOWpy7yy7yyi_yIz'Gyzowzsy7j1{v7Gvw7tt'v7q G|'| :W(2{swz#ͯrW(|Gɏ)'+q֏gϒ}}o_Wswgwowԟ1+دq)^o_~>ogwO Wjxz;~ozsoqO(/Ws,h „ 2la!D8`8<#Ȑ"E`$ʔ*Wli`$̘2g6`M4w`ɖB5'Ҥ<#Nh1BƍJRj0hѬZ@l ,ZXuO< UNz.\/ʮ|?f 3n /`S(Nx+s 9rɝqi?*ZuZe®u묯mS-4*m•MtbegNjqB?y]շ.%u%R4\y%BHdl1!aeQ\Uo;&AZffU/&Wyg9f} qQi}Cӗtx(%:^)FhHn(NXha9J7Es:@JMJj{I ɧ5 jrziZLl^V-@=r6Y.KGz:Jm~ګMJlkcM/+%DҎ[0õ{n6<sERLEṉ4a]&j<2u2b2͈Z f\CAnB{[rF;kqJ3N 5RL5xVuZ_<6\CKfj6nC wcݲw̴x7 8rKx_xy3ޭ?^d䓗[;҂s^-贒^Gںn췳b{;Y 3?ϧR_=cؽ~}磗ܱ~uWm7 3, e(pie|/ j,W>ªpS) d, _p&4aCp$ѡ pDL$*Ll Jq7,zp\ H0d, ψq0lg8ptޑtcFAhT C> La҃.,axBz$M)A*iKfrNv@)ʓp ᤑ`#T>' @@!,022    B"W d9d e @ p`pHb Q7ra H"G0 2J]r|țjƼySNyrab>ip-炞!,c)22;&  ~K N/4& ~   N0% D.| O9x N.M@8Q K.SW>m |1+곴~ ~2,J.n VcAC )@`#(\ȰÇ @0X@3:XТƏШxI6V<ɲa-c2 @M6er'ϓ> *T#Ѣ"}t˚N36p*UQ:պ+RE ,O9| *Fn! u uoվ~WpL= E̒1Pt<r\1VTWAgtW_QU=uYga}` ='}wb 8Sߍ?na̕O^9u^ǝ=77ow_x#w>:ǿ߀8 X18AxQaq8x؛ɱ8((h "92yBR!b9Ze\Y-+95#9¹7#=9$A鞐 :(E"zI2MBQR:UbzYr嘞z*B 'B*JZ뮼Zޚjblm[, :4 \C  (0B5l@ Pp'̚pCٖ -z6t% o 9F00` p 1@@?#BL*p,U;;D>c_F;p@%@4uV'uL0r6}KuM6RflꛣkqZwsG{ݴ7~mx=xsDy@9p1\B{9:^ W:po>:]A䨷  BGx ox7>,}< =Wϼ7gwk_狟~/󷿾ӟ7)]ʀB)~ @ ~_/r_RЄ!'BЅ$TeA/a aJЇ'aC"- yD%0,$ 2 P8G"wHq_l`xD#&9DxC5e͘F:эMh>2qzl(8rrc"8<6" IFDRd$IHvR81Ґd*5JNғ*EI*S,]KXRTe0YK?.IKR„&1KjҚt-Ki6ng7LoVӜDg6YNrFӝT19Hme>}bӟ@IPzԠAP|.ԡ C%Q~V(B7PBԣF;Jҏ4'IWzHX ^X@nAnJT (BP% !,j*22    곴 @@` !Ĉ)qbrȄ?i%IY^L i"S'2}"\@bJ1 (-0V*S j zX$z2"ض!,^22..=Mxxxxd) շPxxxyxy|Fb=<<tt;;vvխMZ][Wqq|G^$$QQ"Y.ii.bc``88'TrESS"XX---)ԷPS-::'::EEtt(mm>>&|E//)a/ccaҶP,,ծM'( `COcFUBByEdIXmm@nO//ObQQtuc-- vv\xEeeqq_B''`]衈 2CF$4`!Ë#"# S(Z $18c-;&͇3o:̩s Ϟ~M4TڒiJ$ 4(URe^hף_i:PUزΖuڪYk{.ΰK6oTS*pY;=n㻆>N䆈1_Y`fΕ:l餝λzo뾯x6ڸ%^;ݎC-8i㦑NY9k管Ö.:[xߓ_GW?}u>|}?}{G߁!ARH&6F#VX'f""H&҈*:3Y7HKJFɤNR XVZv<>cnYfG!0 dOlR@  DG,H`y'`\Tàvi\ 6Z|0 V({@@)Tj)PC'%2Р륯@kð*:j , >D Z;Jk(z n @&[*{-j+@zz/ViC2.MqQ =tD^)&b|!EPhއ#X~'y&-33Y/|3+;=C<EI4O\Ws Be%uU| b@:e 67 VZ6}Y3ᠩ|QBCNF74J73NsR@匛^:ꑳ>8왫8>.徟>|ů~|˿|| =/>__ϼγ?;ʻO=/Ͻ 7>`=֏`$-NZ,p?Ռ#ax@&d@Ѕ-M?> a qG X&1B\!YH)Z1/|b 8C.Ћ7bC&Ə?4C4mdc(E1VюWchD>"яJ E=[DdEFѐwdYFAђd H4j|#'?HR.ҔD#CYGI񕮌%+Jk'qG]2/[9C%eP X`N*@D&Ԝ5[%L ;F!, 1111111111111111//--,,++++++++**((''&&&&$$ v!lgfggi"o:sI uP xR"T#U#U%Y-nHUWSI?5#}jXPPQtR\QOPJQIOGJD#@@+4;.19./:..;..<--<--<));866655532222222222222226? E J PU\ defgec YD 0  4Q m}-479@JPVeo~o{nxhzP$4.+2+2,235=7?8B:N;V;X;Y<]s>k>e=e=e=e2<2;2;1;1;1;0>&F IJLOQRSTTTTTVdm m m n q v x { } ~ ~ ~~~~~~4Sq~։ޗѦe][ZXSOKJ>'"!"!H*\ȰÇ#JHbF2jxǏ CIH(S\ɲ˗6͛8sS˟@ JѣH*]J<:JjHXjj0Ly:zK6'׳hӪ]˶۷njݫpu5#زKa6+&_ʍzŘ3WC22鼍o5ݔTO˞^sͻ7o־Ѧ\i! ΜtzlN:ַ_ZQp48=MQ{wW ev{kzpɼޫ=iODs{+;P}>Q3$7/uh#ӷNP:xEi6o*҈/d|3S>o~l| c!+%7G@ngB_ x(r  8U)0U:^E*h 0/MZ/bj)$X 2CЭ_ lD`)`1G n(̞D`n@r,%\LQ,ط0,nMG#{)cDHؕp"t̝Ǘ`Q}{ڟH$$V6d ÂH2M)l-iD9B$[ ݢI'A{<01VT/]IC(%6q9͇Q;K"ќdbsD1fN;%Jj(wThXfiH-K¨k$Ir.Y:YGv-((̩A=Gwϒ EffJWjt7%ȀjِnM\C Rj%ETT`nLGm8<"h4 iҮW)]XU [%Έ#uLBG4Y\!Qh_JS'N5BxWի5[݉W' zX[zV@DZM72]=XDl❐@ALe2o+X!U*VF6M$i iv+M"u=5׼~uiWk :0 mk9("oMۇBsU"WƔB(fVu[t+ dvglM?Ժ/?drd({qdM,b^ul 5݃ &D?0SaY8NSöU/^j! ^V|/͗@cTqIc YGU+ٹY$LZ 1B*T{mRv埤M23C^2!h"A_d\ԙBƐVR0~'3eqgɗ~ZF#A TwG)fB6[]Vj'W}7<'w?h%n- ~5\cV+P 3Haof|ZKWvG6pBу *4>zW.VUzR5wbuZSrBC{ jCA:WUo/u(Ael-$ ã';T777X H'E&fw(~557Hшxo$rcXy؂fGAlQ@6pC*8H^dH2igfŰF,&OOL@H3fr7FU (b'( 4% (R 'SU'0t'8n%:I!dW=kXXɆGzl=8R9Ns>0A2kSRHcJZOƇrؘɘ' ^[bJ9fl*%P޸=єРq YLqɋ1AvSEG&Z:'*ʊ:}`zQ1xz2"=`ZIjՙ<ÂXhڞ|9Eګ=a R $NC"Ɋ Z`9fYu91S5j5j?_L ᔝ!y1d9_vyQJd'*;Ĭ=+JQ1:[X(*4!va.B6y`Ha󉢚iy4 Ie*K~Q ң2!h7³hxXkSJ|y!w3 fVr$gk Hⶉg{YAݡw(״RfXZePLpѮJu\+2ٟm/a+Qg%*蹚gKA:rs&)G'ǧ3 [z'!&>cb|Yɫk2;aIA`wD{*!IwƟ囸ˊڸE%# &z1$AU\?|w(Tz[A:' A(j."l$dR‘s3ܪ:o +|lux8=?;o32( ZuF#ŋA`xGa;uuѷB|gh, ]z%2<ܖ;V{, N ˟zAŋK9"S!"jY WB sKMR9 ʤcєf V&,`d;ެ[, Ҥm*C>!Ҭp- %XS&~\&rxc {G!8֝~heV<-bV '9z(>ٝT)N{0x]5z˵y ޼Jk"(rطJ|(Rց.xY8ƛ芾蝲zcQ]x)7l\C$Q{%-ׯs^dr(xBqcrH엱>)%V^~j-ێdK!pxέ!Jڟ˶dyg斮}-VqSvW{CN S2 {7n]^þ<$[碦2 -^@9Vu?ixG83hN_kqyVO[G_ 5je?Li ,4 #0ڒO,oOEc h6걁5J}/èJ{ A2)'W_Pϟ dʔ#-ozA+<{Ǫ _Z\l1ҟ[\ DUB Ȫ.lxaCHYAJX" 5nDPGYO45męSg`ɖfL sETRM>UjRA>(TbV pJ,[fXiC XBHٶMٺE X`… W "A%v2E/a H+dVeBMg\A#Zlڵm߆3n >U3w .7n K`_̛'v.~do?6f3 RȃU~簥Q .qC0Ad!b &^}l+':(*4q SN<oDA =3 r콧*%ZPL* !@SԱK/(AJKŚ;)KCj2 -PQDl Y$@kƍj1Q@|| H!#=HH2K$*GPlKQUWe6~M3Jbts#G ݆CqB eF0FMv"3(t$] jTJQIV,OV祷^(cW= O:uNs?[k%DX\/k=nC"*4L y\Ӂu٥v_{wgwV~ u ƽr5 ΄2a7dFhn3G>FJI)URƎOXOcjJ4z8rgVUVy)^Cڷ4=`:3PL,a]8ſ;!6!mJR&Wjٶ(ʏ:N{*FpF5t'^pZjEʓ5h<ҋX tEv# rud'͐tS5-١ڝӮЀW潦$)g&^z{4(,vY88*eCJ5e.Chd?*}f 8D"6q1RJȔ1>IkG1E^ n:̣ PhB!ؾ$6:[gcRb2h̆LB)PEDd"d8RT=rn[+z@'|ە,oξμ16H.rl,(;e*&\ rS`/H<=Ӻ,'c3tAE2#)L5֫2s:& !*cjs[60 >Uܥ4?B$;N,E\8GD22z?HLdC A?OL #;,<T\ yB(7T<5„ 4<BuHTG>0 FbH1rk B| $ k4/Q6qFJ+X [[>E9.dnjwưadx{LFsGJ R*iHW%)4d=st>4JHI ɥȎc{dIz-~9nIZɣImt3Z$G Y43KÈI J ]K0(WC=98|JsZkFȖV<tp<< Ԏ%*T:̂4H@I{18IL̋dA$ΡO$̓xҍDh+63KF FG=|1qTbN%^S=TgφXUGCܓZ KFmԄpPۄW`%ae3v6d-ۘf>shuV? lA%N%8 ǐ9Vr׊] 3ިOx 4<]R #VJTدA%B\{XK뺕rE Vؙؠ}#P`dp5R2׆׏WHLl:PnQY}LfFRWDIY~ڶճO$e؅0 v#Yo Y3FSY=X /_UWFICU\X[`r=T6,g2OHIH L2 }Y\;,D%>Ru<̽\+Uϵ{ԒVLXY5:< /GJ=XL]*UEXݵ $u[WxC&u ϩIͩETC\$ Ҳi<}]Ӆ [=["_2_E_NdߢaQ_ϡR0bM@\ `ߛY5`(Y`LVҭ3`h\_e #5-F_]4N>8ᵲa्,Q%#M 5". f+ T(B)[p}HjY,Tb/NN0^#Q@R^`cE:80԰PEȿυo|<,?@AB/N_YN u -]sewe UG d%_Z=*G>L\81Vfln=Cd8ڤ]I,GMD!^ Za]'`yΝܤ,[t*~>0.V?f6ۆ6ghi&vgd\dձ\|6jkfDe]]H&9=]8"(L>ZNNf(ɢ.Eߑf]tj ޘ @,պj(eOmN Knk8CO6e&Avι#~Y1( q ^F66xxց]jIHK[*ΖF ;[ie[`#UmLrmkM &ldžhť9|\n"VoLxini`a>g-NdƆ<; {N*gKoYo`E.coTh֙o`&ƑЏC=ko)p"0C1mh{΋p u7^k 3^kMmiLÃ0AYnjee5_wAor$gn%o`Gɡ^f&8,Ǭ^krsoF _h 5?j7p.enryq[r?'Stt( q:ើ 5Vs#&K.و-ǼhHnSoTUqYoړu#䡐 L^7([X<O"`VetvU/2q~pkolnoFZ|'援YgcQ,bfv!euu=$Z?mnr^:IÀs'p(sdɎ\wOǧwS|g4!yflH"(BxuJ(c~r;A'k>`yR["_׃,Y7}l\ataw LAg~ugw^>'ugFG϶a ?iiCĈ(+:tWBXPgSŧxo>s?ͬFQ1YE7L/aү']Po|"{W䡿>}By2Y ~WImz.j_մS+(h „ (D8P`Ã=h"ƌ7r#Ȑ"G,i$ʔ*WleB 1¬yزB.3?yd$v"4/J !r+X6be YE ڗl5K֓stmޚ ?r 9#Ċ3m1Ȓ'S 5ʎ) fe %Zhӓsznjԣ.+lYְw8ٻ& p=`` &@fxx15/o&Zޗh [ߩd0NR.ry"fYOvmIڛ9޾6 pBvTP0IsdJOiK&Wc5|2|EOz+'f/`@<9*JZ<]yS .buO-3A~`jro Zɧ:Fwm&RaÅTnnC.Ƈn|#yȤu&cL_'%|!PpVJք5,D qbhX511p$(#GAv<]>dD_ mbypvDdJvgi8 #ݐUd$&K4lc()A(n7ˑhX"7Ę@1i2 &32 #f2IVb03mb5{5K걏% ί-zfXyɭZS@:L-  I&lm4oI iq5c$#,EO΢"uK1&^߶Nt~mqkrق`3Fh7]sd%+ln߼3AjZм}(Z~<͎awG>N}{/mȦV!p\3U.C绒8q[1_?;tJ,e yWٮ2c-뜃ַ9tv(kqĕDo𼟮Ui[h7;LYW؅=1+7o7ƔT:K^`$P Yw9D΋bgKr-FV;R0Rϱ)XG99YM35";r,"&Oؔ!`W;VdJh^=~l zh?cM\#62b@ du#Ad"&dc$$aM\0E$Fnb4v`= ,`*ZJ΂jRlϞ-v|Ml{(V2 vZ,֞m"l+&l"R6ʵ) !^pEa-Ihټn*0j"9hA0ք$V^n,D_ΎD߾d Km䮽ޫ|XED!,2J[n+(#BF)5﷩nb" 2jӺ AT7لzI,>eqyHjd2NLnRd0A_-H-J.Vpam:ɰHӉNjn0So|GnoM, wpDdWm [-n̚,:^p .'o1c GpOޮM8WԒc:p}Hecl"boN^g'!M 11Lğ$d,S|Eᢟ~^!3&.mvbMxz\OqC1%cr&r]~nI0Ir q ̰r+rpb26(B4r 'P1LqXб/EhZ0>&2/:sr:2BD<%,WKpn7VIJX 3;$)2n0%%XCƭ?zķ_z0;c98B);9Cƕ︫麢`GS&d /KT:w;-v;5y[{{Oŧ:?C9o¢;(!z5F9ڧ}(|?F'|у 5`9K}{$_#CX/)ʳcTš##{母ϸާy$ ĩz_VXٳ+?~c8?[KWDﳍzo|y؃Aع7`C;-[S?RKC:@0J&Ta|i F8bE+2ԸcGA9dI'QTRm޶p"Kmɰ< m{ mgDBaJX! "5%WfպB;@ RMxU'%n-YDGE)RGFg<;paÇ'V64!Hcb {-˘:&6R$b%*&ag*rmim TH#FMল*Ϡmy;KH"dP%s4뫐txB$\ -^O>D3՛őlVQzS2T@3%<7IC7rPJ䨬2 ?1TSV܆(2i2M %ϔ,FO3: =GR"0]@xtJIS9K= g}v8C0Ts3`ֳ5 W OqV=hQWP@P?Q `w!e$BdlXb.;UE$C㏽i1KJѣsE2)'[$X "@W 8$&u@ (!ɎHRa}jN %lA2$?Y䰤CPFulg;+l95%!TڷX:`B(^+xk t%sKwL.k,I+\tsܘiXpyƯo?ȭ Et\%`?#9K;#;s,Q"9ŋc:54l_s-}ݾ7K5AZ3a#LJZrE&H㮇=1LV,# 4Ϩrk%:GB7ckRfO#IacʵNt\GfxJ62A X6H/%),R &e%, ;}[ yF`Ô!!C@ Yk{G5N 6>=pPC^T}r?3V(HB82S`jHt2b/;y)PMvp>2s]E"1yBm쒘 ƍNnSz!iUH=rjCNM۵L YwyR(Hu#ʿ=,>'=@Mtgr#픬Ddʚl vԒj={N^vLqQQ4h/`R |]£{QQDVTζM#Ş)|l;A^{֓"^kG55"{7Ff˝Q" #01ooK/ZEE*|ϥ\PMԉRBo/.=fL;$&L)1NEmP%2@+4& *D8plBe$igpLBt#Lq0=ÌnuヶA\T,.Lj@ =Pb2a0Z KdLclo`ҁ,a 3&&ټ% H#{ 0")%,9//ԮngLjf&bm BV!& )"jBqٰȌo8%0 %I(TOt(0b\rL ܰ1Z0A*b f ɰ$hA G!*,} ϱnpMRy$2bL&04cӀ-$p'!rR=BCJF*|r! Fpr$@ F#E#COr+7%U2}l/# R& 'J'''mƫ)1Z"Qo)?jN" $# :pK+Mo%5Pk"PB-e1A3 bR#ZҎ/)CB1:2$J1[,{Q!L#"2ine6/|!N0qҒ}%-z$16 $0x7}3(N¨’'yJ9S"233%>M0 g.'MSC.5ϓ>)Il!!Lh.T*C"== Є2%Bq%8:*l(Us5I6'$Dl,ԝ2xdCwsD)3!>l&s?E@2JG9--CϴdH7eC]WO:C=BBkCoϖ ~DQKoP K'?d&2 -tM%CMrrv }tA N3bHKH4AC" 9t< 30.MQUK{28%3?aE%,SPtMr tNKuOU*4S$UID#t/_$@"lI=~KW@=wR9{r-R3xDN[HU$3V$Z]$ֵ"0&ޕ9MT^Cf%JQ}")LA_YIGSeL4.UV!jtOE"ǕP[Kt 2"@F32SX1ϤeLuNM? /g30+adUvV]>&"%WPoR}nW;=Q#.X'D.~6RBЖ%4uL*Cܲ@-%qv.׶.7PH}([$Tn$hh#6FIpw~X7piq)Xi4l{'leq 1ATgb x6UV")oqPb9\Y7t1vJ+Uvg7Kk^q3rR$&w&*C` MN`I+HbK"!r'2C[VSVsMZ|=6~WRt U~##7sSx'x4ar%EU+m$7{MB0UnGI"Iu1o-X1 jw,2q#´~ 'ȶ=14NTtH*r8"۬#x6x7Fǎ&EX p }%af_% ',wA..mJs|mDrszآKbu8]%x|8G}v#}KvdeS6$[x?-An@W'\ݎ/< %Q#^WؔoSy֗%r!EWٚDue&gQR>dib԰s/z{/yC7:هE⁷|]EE6eW4qZC_RGl)Bf`З3EnvGXb!iho;Qc|*z{0 u@?XUo%h{5M.ECISHBiQ58Zu%Ys8P99Y,@eu$څc%yge[wi&awV$@G`Z] z9vج[v w^%N؜9s=ogZE7bVt?{}cG9NWiZmʱ̸v$./me1O1uڝ7W+Bzoäh-;&[Mآۏ7طSo]{$ǡHAIݟ»ګ[ݿ}[9+ˊu1߽*޽ǪN;=O#g |=;g~s~Wx#|=i1"x}39alXIt;[;mEU]#^~,]-j^o.HC[̵w] 鉓: MGU5YZ߱#={O]i>1~>#|5>Z'~=<$&q"߹[k^'I/">_1=2Zܭ9"r5p&㙾:Ӻ1;5X;ggY>=?)wB0%}w/7j?y'=yW|D ۮTowm]j<6߯^eafiWj)E % FmgPA%SsmTS=RR)WpO!yCu2Έ6ވc:֐7'Pzry?_]UhYGSg $F=$) F)/M(S#]\QyaU#MyHb[[5dhWbZ%ga-9f>)Y:MFdAf y9&y¤fOu*jTqr2w'OH`u> m^]> t=ޥ>A Dni߁:҂9+Y=iQfe")o6 }V9lgKqٮ٩mҕjyuZa]e6*]C`ajpN!^BkPg.g;ʡsH3"=r$qզuZ9`|eMOf]dV(넥eD2J*ͦ<f]$9fKtfqF YkT"^0O'DzuEmugo zO`c WG6|ymp=u@zW}J=t%6/PKg+WW=z揞%)y{W$E%bq6-zM~-xƃ bB&A.X:yӴ)Pwb02Jj vBJh*1Dfo9!f73pV{\4eMhZ\\8= & AU5\`F,B x[jvbU)UCmHj4@&2OS}ZiZpŶTHds~J"mX?4M ƻDo8/^,ء8. m2r&I5G2Kl&xJWk]-/ƘT'i,CP,AFFX逄ӣMHq= )x0=S&)>eʙ-(bNIʍ}vac'[h3/'݌7?6⏜*&3(h =wėq VӬN}׼dBm }Dœ"Dd^ʂȑH'ANR8-&B~BӴۋN8PH-׷pK RQQv Brӱ9WjvFү3bU) @ ZR&̞VXd;#۪WK%B7dvJW(6j{KޱW,f]Z/ij#Kb3x%]y-c5\B;kH(:Jo#{3G6wxZᶻ3ktY v E^xr0فevDD i@sA!_xA>@ \N 悈/i8Ӭ-#Y3;D!/@3^Y '29?θ&WֱaZ5+4ָΕ΄v4rV&6dd@W^2A7B̙2c!ޑB4ZX>dz͎tTyv6hS Yvm=D-r&ni[Z& hu] 3W:Fɤ6]vGuaG-E-pGPӥ.k+^1;:_@LL"86Bl3 ȳZ,ۈs{4 ev9B0CW8=}bvlª$#xV8mc{kW;] :* /bJ%s\-a9]^x`^0!9_6BDQB`飇~}A }o!QD6x7Ym76aJ3~W@hZq~(qYpqdVM8*dcy6́ )IAwJ%R5_(X);81GE= v((Z!Cx /R Aa&GGEɎs2H?AM[R(`*Œh /=i3E8Qm5sBAEHiXڷ-I_XtMLՈ"sx62ѕG(-W6%hQ)W8EyEy0b3"Iqaw)c)d+6!)rȓ]Oh)BI"׹ė}I) _Arj6_oB+dY>1924ǜUZ>=q|evexs6&|Bvh&gZXO隠)YVyive*|TGYo×ooxlxm:ƭ&|ݨؠ !58ޗq M*;щ8Byer4p~07UJꪬC|jcoȈoчhpae6H{Le.ˍaxᗉɎ^ Q6J ꯵~y#&ڦRHSaְ5;xPf*%HF&(m`'JjlVC-8>!稳9j~CFf¦O["$'S;៨ 40=Z] :$kZVtч{8%[{n@jrbFyM!I!@Z"(ѯiAҟqaˏԹ0ʢ:Xgh;ьnivsȲYQBC:v؈|0g{sը2k6p鸳HF693HڛgۻG B/r 2Ux KҾ6= - J2uIĀk#t?X\R#웂WrګK۫QEl2KVM8);|l>ƉĹYEY|#Lj눘A+U׋H3*k1[imYLá&jLemU tJl*Tk/ L1 ûfH7Ō#o ̵w޹9;"<\.\HV :ZeiiȌ*LSi%l1%ּW:\9|²<˺H/\ȏ\e켵 z6!m#wp }A$IkȇAuSӚ;5x;1=Ì^m<CIJ HvTZ݉AۭY2qZ-Ѝ}@9W<-E#>=N)sM cHG}ߵk❾sQ޶p/ܐ= KDD; n#.y| N\Xj( mC23r㮌WR?nM>3G'@M]DKu۷`EfjP^܂dF#[>1A5^qn^<kO>]ӣ'H>=\~bl1J͘r[i lvd" k>IVHcVS~K[Nvھ#R TMڅr1!^sqaX>zz#~-x~iZf13;+ }1m?rqӜ^+&FFI>0bF;23#5s\͛w!bsn)jzaGpȜx(&3~Mߞt=XT35Z7T^, kOZo4ؾQ~]r[汜ٜG!+#Z_ń. ѿ^ğC/ \RcO$W^P A .dp%N,S(ndHjc%)q!B/jLP I Q&y {KOA%*QI.eSQN=͠OiF5Qr K֮˳*TCۼB3±zM!.\alTY!7T)rL4S)U2'̓ +w>pgQرe\mܹuzkބѼnS,ɲ-ŻOw5D.C{7Kˆŋdǐ.qd GZv JV:lѾlj "x@SnAtA})+ hs*;4( b-K 1$! o<S& M=m쓩nzJH*c49NI L?rK.! l88l/#nH*.o9MT,HMFBrVMȖcȆHI~IS^r4TTS*L &-kF7MM!I96T+I5[UwSYК)Zw]CZ؉]+z˯bhdǫSM~щ5*l6S*6!NWsSƊ][vA";'<"t 8^:c>j;~0VІ n%69G%b[+Z_:S=\}l>Kh*{gVuMDߩ^=8hjł^8iBKH܈m*I6H#r3Ѯ.i[V{tK]̈́{4_8):"Nk',T(M<=G5}{G=8^=__7\ڕmNon__p0IP=+*M2}FkO(dG^ʺwA {2dL|FbIw?o4zg<9SҺLD)4W[m(@l]%7BlE,QTcP<ɈIB4 ( )y%dL yH.IMoaRxt"}cUv䴐#bF, Q7QRyI0g7vs  DR RHeFHACA,gQ젴ّ~D'cI& Cc8YFG$2j1u,kY"#|c0X?3>3C^YGf3!L(Z!t4CıiDNG%1JC涷m@K ;8N9soqF zjƚz.K;B_$q&kϚ'y.j$D'I 6lC톈bӔ[gD@^@[,sq ^(=o&WLfV1,JeM3׺q?BީD\7q`#85McCӈBJS ".miZϋ64ĻEwn>g E x;T4E_Vk4Nv´WRrM9L\< }ȋ9qX{oƋ;8Oz'N'ɦuc[wmr_[W4[džHFjITV)iFt=hBkɅxrH)>GkC$b\L$Ta?j\K-mqBo' Lhˊ䩡$kDJ2 ̖aul /l*œ6 ɭ\,cLq̝FUt[ʄHnͤHOidGhkQH {NTɓ͗<3N#?DHDK@7CT47 {F?SB'JIdl5Ƞ iL,GL2]H ɔ`CR>J4I쉛\LT+JKfV|#4@˃Dm#?LN E[nK@SoPUs(W} \X[% K _݌xвԨbu!ѡC7WP<n?0=s?ru[?ֳVғDQCL=Є RPQ=*W0UeU ]+Y#$X霽K%ad ]QXvIMYol=²EB9 #I+ķm҂@B<[0ߺYUz58}ЫW )1%K3]@QpɕuXUaY [|N#9XoCԳ=3dCMKļ][4J+},.E\RP-łh-{5Ei#4eMҍP% Ee]E-} iՀ} rb %̕ZS95_}W`{Yu_LKYUeL`p`a&ܫڰյ%Nb `FOMa.uP0aV^Z\aOܩmþKߧ#Z ;༈)a0vd \bkC ,Lf"N>fL)_X<֒)_WbUdRX^3Xd1]._]5u_8VFdޒQ}43 4u8gwO3Z^gA`8#4Z `Z7`Qgط$m ]B3}Cx{6kBe7#|?Ӷ§&j邀'R"c fYLQfDZ;D矊6 t-D"0ӫ- i-VļO[?Ge7F{[7:SDjS`lfPk4i6cʔ&X0-0`CJ䉢8k?VˊAB0nNmi7n=OVi[=J]6nhtu]*Qz=HT屸hy8&!3ggu6t6"w~i؞@/HD3lJ?nX$=XKYs8SDͧXov>"TypMHm&)!xm3&U`̖`L.p@ҷ=lSϋ۱A'nLB3DRB%'aN6wq m/'G[5>o5M7:5r[CG%7a&ǍMDMKnGKO8CDB$Jc]תvԅ4OKk]R >RnH5gI/$ ZWדN[VOqkJAP|$_kitj %{ϥs`.=ZKu @wَWz_Ca6i/jotYl 1읭d w5'o捚،D6L0ig]}grP6oxRn)vCoQ߈ ^OXO`PP9v!xfoyw^l, 5'g$Gmy!87dX; DO1AwS2`[wq޶zX?_f_zy3y ҝGZq yg Gd?=13 io(qozQf^wO ß2dx|rZv)ƈGa-߇ |W4ILs !G}uge?zW w7FOy4$lV: p "f!ÄB(q~ 4m7h(TPm>`0yCl"%+6o̩s'Ϟt$s(' + IIN$E)LN'B ЫI 3gTMv-۶++w.ݺv;P wy l.]o8b3&%Z:"Fa&aިd֫+az5kcq"d*HO :*aT23K*])u+}:cϮ};ſu oJsh!c>=8nr ºQڥ1jWT$qQcPh72>rJTѷqopXŏu SgDɨ ɨB(ćEOLA,F!"^Fm};`b˚ȄIAxkdUqYE+M< HE$aF[˛ĭ+k Q!oԦ,&^YI I ЮγqCG&R<.v]hG:NQ9O3ϠȤ;[i^ȣ^5D8:u Rj@ Z2N5 k=jW־vM['ב5=FlP;~6fa#{nhٵ}mCfv W^P88’o`_aw9bIA~ig 3*dܵ>PuC9ލ~wE[F1}WTx'k1U)͑Vt8fE˝S/e/Z>j# $n!2b(DA&:$:%%* 'E"."*"֊,*6+2J¢/-'(B` #2j50.+,:6Ҍ2.-b..#.N8;F 8#< '23bD:0hc@ $D`j 8ҡt09.*H4D/iqcyc#N9Fc(>>EJEvd頤]$K@Rd=c(HDDL~KWKm$dH.:!I$DdFepep %DJNM>SNBdYveU%p]IfQ%pC.C^AHd\ZZZNDUd=% XX%5_0&CNe4JbfjRlZdFiVe&wԀke(clbofc.nBmn*ԀXg q6%l"g5t&$vfpzuZgfrgwTyg! ŧdTzg 'B9Cfeg]'uz~>efZ:Ā%^Ł'~^gA8`h1g+Q(YJ(A&ȅ(Klo&$r$XhQhDhrgB|(認(+(BFCh~2(p"{ȓFZђ:|ďihliqcxiBi)iMJ[fi"ڛD㓒ii*6樊*8ީEʢ2w6ᣦH#((^j›*?g*(ggph]Xݪiy\tªdCkmrjk*r^Gȴ2X~r%hjzkdR+]+%t^&J)wNBPh\b+lZORꝶkoO+u@lV+ŪLdLɻ:,օlI,D6D6kfnI. r@k*,m? -^<&:-ԐF[LmV;.-nj9~ʭ-`cךv,l@mOmTO.k!flA.,]m(*~fVE6bnn,-nQbnYnj~mSmln nTjkr,o^Jnbai1/驪+Nr/_jG2n//ҫ^%nr]nroU/ohӺz.a {0͠$p-pEgC|0z"a 0ov߰)bGHc' ZN!p 1 ' ׍a^c@c쪥lnư>11/ᧁ01*O1!!C+2!jVL2%po&w//5+G0o̔)  ";O-1(K-rrrmr&X*,?x1a 33$s1/C1O0W\9s/BCs(C80:st5+813dls|-A'3<?,C/5S*T+T"Ue7p?/upuWW,XoXtqVqAtڸHõ5;5e420 $ 3p_n65vHu!w(Gc@h!J b/VƷ6vl#e$5KGN6 VvZ5`NGGc*gMgmqZ;2r1wsOSw6yH;N3OW[vk\7w%77}R'r??z7esw|tkr6Cwwu|tGFj/cv-8dw7mZ\k8FBw+ 8^qu~Pr8u?16G8[x0yBSg6>nVg_ g~h25WokuvSPx'7now?QkR_wzQ zi~Y}?Gyy);DR[wns:t6r!wuG/˴7^Zj9=&{/{4Flsz̶37;{{{Uo;Oeْy^A{$Ԗ9K9z[g C:߬7?;ת:{7C'y?oKjY<~| y CϤ_9ߋv=rű9ۋ[Ǽ]_Et}}tJIjCΐ0==Խ|=}/K(wGxk&k*{^C@jk*T>7Կ}~s;@>4' ~o~̾i v) g.Յ"l+0BDN=V?i_d?Ax"ws>:Cu~hD4xaB 6tbD3#Di2: HFGC++YtfL0;ִygN;yocPC5zgRK6u*΍QVXՄS{^ dX 4{KkٶukQs}{o^{'V\q~ 9$ M2M)Wnfv-wtD¡I|wD.vAH#׆\wn7άxpÉW:6 "(f|mfWސoHw|x-aՊwVk3eBش3SƚK݅#-P|e N iDJT:lʭ 3cJyn2Wҫ=K٫6$_1f.bW8ځ$yY3?,y7'kޭR'1^7Q$b܏ǟ D*8󧜷y}̇0k G1~ji7,"7>nMI ƭ'ΣOT6zyF-,9sjVÄPD3l(!jˇXx6}C#R&A"%iNMP,"`5ˌyȐNKbȗ6juBGeE'YG*2/ $e51~ A"y2)d%"U)a 2Q*bM'/2vFZliaɒY"zaud03uL.D&(;0 IΔ/ HP6ڼ&)u)Y^&mBNUAgm l\_ <)wBcЦS.(7X4́'R4J)E(H_4PRuN 唎2tZ$MH(!T+FRי0%MuBӖG82'?[Q PԢ#ꄔoT'ϣUjN͵I'O4?g>V`5Gk ꇯlG&t+41( i 3+ft*e9{RTbg%YXAN/D \j×2 cK'޶s][qf6lZ&5.> *S՗n]]4quk^F moKٲB'zޅ6< U"TUP}phY.ňBlfo{C bniHrWY aX8JK12pF݉gr/|WN2d #IVW{cޘMmܕ{X-si5JS:b|f$TJDeMY"rˌ`;[k6WPs>Z,>t=8ͮU&-DCDy3ir<zpX`Ie::8Kh+jٖzivcL7ؤ03GzA6ДfSĿvnjkc~о˶k|{!K#*.VaDZ_:/({tW3jiY8=Y=9AVRg?[ f ޫu6,25S}c+g9]1Olvyo?0&R"6(\#I?t?3\>w}n?s΋vU.h#]_Mzlwpsq&87ΝXo{ztFj{O_ oDf;J@#Rky2lN/{_%k w=B+):M}x;=_<ߨ?Y_}ܞ [ 7pQ2p' n ne(tb0Pp 5O !Z \ e 9 e0Լpq  q*a a q W*!KA*=0*A?mJ@/¯#aٮ-d$xQ9'TY"!dQ+b '7CNrv"L9'Ӌ!*Qm3#Q##5|Q'8c"Q!ؑ*/*1" {DC;#?$CR$G$K$O%SR%W2<)\؁!ʡPq-X@&i&Q"`ԁ~( !']R)2'r& s؂('' R'B ޡ(Y, ђR2f.ϲ+R ,- "2N1-&3' = 34 3O=r1"5kR+"3))R&++2 s(34B4r4^)b6?37]M9,ے*r793+8;-A("/ߒ/_,-*;*b:/5]4">e-3;W+dz!J?3Գ9M=_r.53Ķ6:B? Q+N&] <77)RC?4+5$TKVdeeec_XM4    3 Tdin ,u5z5(2*1*1+1+225=8?:@9A8C7zF5|I%FB=7669FMPQU]dgm ihg2q=|?΁?}?j>f=e=eȐQI͛8sɳϟ@2dO*]ʴ)v-!өիXjʵךD"ٳ4Z۷pʝ+\;m6 ;V߿gղ Èb>L;yTW̹篌Vw$Өh':װc[ 2deC] : u"W|pمdrسk9ISݹy 5`ykO>D`ʎ &~"'JWy{9-HM7,_fxBx7I}g"Nj{ b{!{go'n㏻ !0!>4"~cIH$mx54e7]Ye\嗲u&(I~REbrE-fx.14gGpu 柀v"K22+ԝ~jJR ΈzNZӋXZvbǟ#㡓oNdjN}HX $ijꗟ\bjB#ˇtwҫެZ+#jvW $I69nMJM7%*ikTV+櫯S~,iv&F4h5`;Ҍ4#rg,w|P)ݔ W\z2o{81 pc}ج=#ڱpH/m.yTW]2 $\3 G!5IA}V-Cʴnr@Tt /MHc7qyGxzs78BjH }.MPM3}i? 0!,C^ :q>ĥ[+!]\pnu;ͺwF#/|D2|~o1Ǘwœzy럄}pz=DPKMܐBrSIXo7+DBY$tKA?IҐVO @x §0Y;Cg2&4%"l6  \8 r&YNPpf9"zȢ$ϕ]+>KO tTo$r }C%w%Mߩ(NC1$t㡢g_ok CVxUpYd`WCm,yWub/2ykM7Ɇ'MgwurDGsk~ WZ9Ǵc%.2GSCv߇g}h}LWr|շ~2u~|YWS—̷uu_|a{w 'Jv )x}:wX{AG~Ƈ}ww WoGTqdw}g.qiׂqxqy5kB}9j;|dn"nӧzfzlhL@7%{ {2,{asR|{G5a B }gr؊Hh7I , S(^"fp=|fu"с8Ky'/#%IP$Hwl$Y(^1'9C mi/YWx <,y*xX*f9]EiQv*9 !85tYIY=Ac8hV;iR̤11Xxy'NهP;嗿z[S9Lȓ(퉜 yәIiiÇ. CY1u@K` J_a̅$B0ٚKؙmp#q,멠љ&86 <zE&Y YX-I eyy( a/R?IYl&94Qş!Jy<11ZaIf!^a6ImbZ$ a.UN['¤'Qw]ay"1)hؑD"z`"*r3tU堜눨L!ZA:lj:BJoz*p:e :6 #Xa(y"9j;:=A*י蔔:%-4YYa2yx=bٞaIt$JxI3)ې1+w}wYJ6Zhɭq5#7*%{ڧ)۩B躴8Q!װtӞҏȝڍbۦʯH3;-۴Aj:TT {:7yۮyhzn mZoIkh*`q⊁G1{`K۸k&71G;{Ok`XWQ{{ >A ZѳD[::mij2+a[q(Zs.(+ !3qQ_VԨʂ %8rwKdk *XAS!EV|\kaqH(B3/˽[o3+y!ۥX(AG ˼\/ v'J/m٠B F'H+|:r;Yܸ Uk{?ƿCLZ|;ӷ1\њ۾h7}TƏqa(IBzs=21 EgzL 1gmGl!%Art  ~|W_TLrqca ၕK |R\4 ö\;̰!dgaL{ (r(LK|yq =*9Aʄ,g\p:ɔ|vLΘ|-j'vHk!4A :]WoL*w E7E5! Va3q<\z 1˃fیL]VQ+R [16ʬ [K*uLnLܒIqєn s}hV [ P|rm\ ̛*,כmו] v> LL2lѲ- ؐ'ɽpmT|h/,9l Q|[܁`-A]dmҽLjCKWЂ4m\, a -U}G V=1M_qK|~ Ýkmɭܫ[rom}ܳm4m˘ 6ܕu]$PT]1ϭ1Գ 4>6bn^F-6B:MU>g-P⎝ .WAouͥcNCq]qMދ24o}x} ~I-y FkA]n_ QǠ> ;?]jکn"K镮鵎z|.=nQNWa-]ގQg« m^]n -όɄ;+>~^Ϯ̻^} A&[Q*>FMNe1q ^##_ҫV꯾U q(NܭgҀ w=aX .y\L&EOG_-=̌m<_6 W+a/cO>>xgϢ1VFoxړk?x6^z^LV!Jq!r^_vo? \2΢Nۭϟ~g%o /,OO0zbpVs_q>a~,O_LH1@@ DPB ҥk*UhBuQ0%Hr$I"NLRȐSN=}TPE5(옲nds#0eU'=5H:zlL,Y TnNn\ѥD:2ÿ3!;`Ͳ?Ydʕ-L̳-myVmv^(i)ӫz@ko_|xۄ v&pκ%{?ftխ_Ǟ窳E }aZDn [N/TPRU &(34!iL%sҍ N? 'B /dh>BH)BϵR)ISD|60([(%ADH8LHNjh"I'2ʠثo'QTK++ ;p!DdQ IHs\0,H{ #ιd3PA%BXK/ Q1꒠E C&Et .? %hu|Ry:'=wR 4S;#jx1/̣ := ufգV]gin=|qf*~[݄G9#v֜R|C`aXd3ֹyAmVރ?\0v2׶W!gps)Ѕ/ 'Q4{_{.8?m(~T8Bao ގ`wB#g>+a8E*y? NPRZAmS &$T=w#l|N"12RJ-;HkU9pI>8Ύyd&T9qm!39wKdeF:2I>2IJO5K^R甥(2Pz$c)uR> ,Tz21VSrlF^Y]қߌ 3I$>Ι&FKE٘0B1-g@:Г\"XBD=>I2Dz iHгq2IeUj-љ"jPybF,.O', "&'bL͝ӄ7؜8ЁBkXS4TBɼ}s'L;Z#dtMN) }jT/?VŠ4Lb fA}g.P&~eG3>i~ꪵ6R^E-4HNr2[}uc4R.Y^ EUE.HVTI[WاNWMRU?P9ݪ-Y6Ťkԣ' QEY _ pU,KӊZԧEo[3#/K:_&Rwg_~vzjܟ* ?`ƭ&IPI]067=RUtlw3i<S9B+vD[8!@mV6`"gNo\ZaCVٌ$_9f[q<"$l=gY@ ,7iAD$-/4|hR#죟h)+I*N y9.u7ddXED)K9߬/DPN=lԚvsgud7I6X9gjҮv1=;Mo:6wkuw7t;֤n4uHKB*$31q{'}0ſw]]rŘn! EU'pه ٴǹڈvg_$jI'+kz_]+fz)4厫BpٷOCo>wƳΐydw!2:1vy|?n?P&/KeO=@)Xh}ꌋD1ij"73c;h+˛;!Ík|?; ; 93 ȓP@,Yj6x6e 3@ \;12A8`ں"#y3)ѽi<@.,cǢ= 빴Z>ppjsz* ۓKB>| JH32T*≝3D]6\h D?nA?D #c B.44 w'-D t[:FDL\T2EsQE)Sy88K*=Y<;C]Ơ4gFbl-~%,ݲEꨫAٶ0C.A.{T 32cF~<*Ǿs$,;?fDw4=ekNj š\@Dr8G;H[[{i;\ȚD@C8LD(sd@?fƔTJE Iȁ J  81J`Iz*K$ĎʶtDɟɞDB{8˦n t\@7IS KRʺ< _J|BQK?>Kk@dLRT2Q쉝K`JLɈv$*[< mP P MSP7;z5Тx AI?-@ :,JՏDUԚHm~l5S )CPZM=NeQ$=Yp}S= ӅVZMر_5>|U^!:^[C݉ŝ ,Ze 5['maק&=aaݐޔޤ4#@%rc'OY.2-IbMY;$#)5(]*_iEBNL<>t>D%|4AW5Y7^,6Q֙FdK1c^d^Ŵ Mj_!vRv TNe dV;%,FI*>D0eee`>SdSBNeYR)^[~]_ t]l~YɇzeXMN*0gzbbv>>oFf/r<肆UT6V@GȈ}c© hN=xfe20rh~&U܍Ovfkdc287riƯ7^|Vh u^gJQuAg "1BeӌFcꎖ]Pd v E2]Zj~ Y%P=.B뢸"eTj@l&R.^YHkl"l˦xN.؃jĿNlvR˾l.emi.WnkkK~Fɦ$]kVFnI nZm ~n މ!&(=mjfČ@a70~ 33brZ䎒7R_R ]Z2]J?xthtNǹOHY;>_pYOcrh`xD6tZ7]QAE/z:HFu isBolfEH)ţu^'/_Ba6coe3;r pfc6_ihs7G{ovp+ r' iW8(jx^xGIxcw]IҥpWqʐwfYc0ytǽkxg og{-'ٖ' +@Bz _zl\A7Ǖ7{C[Q{fW蹧ƳZ{v|#B1`FϹ'OLJ|AI|}/&o?WR@av?gٯڷ}4})}?ߏ?'~hWom@~LWPPS_KІn'MS0HA~OjG2,h „.EDFˆR`W,J#Ȑ"G,0Ƌ&C*Srr`uo'РB-j4lں-y)Tq0Ϭ!ğ]&:53ͨjF-{6PЪ,()}/Rj~ 3>:jXF[tʑ{UJ&MG f]g>*+n.m6ܺKze v7p-tkƻ!ySf[~4̽F_=(vMҶnuJE>#bTtVT^J8ytCq'_7šbG*y栆&"k Zh( S2Sr)#)[=6\ɧU=ٜ68BNZv._Gݕw@2Az6Ք &d%YyyLS )@V[EL+riEHKXְMo{luJ=)e)0L;[ӵMp. ZUkJw%CHuM-o/ڶ Nt[4r#UXʬЛ~E[Pġ\w7hjʢxf+?ȑ׼6 =ѰΨ-mؖ{Zԭݒ4l@U7?ydG&<^XQ-Gw{# vgE{MWLfrG`OthK=*~LClۇXj 8'W2 ,Ŕ-Jx$^N4IF4yi)숅[8NpaHVq`'mrP+蠐/ PB"d6tEh[d1jϜ>YP&fHqRC*Wx 7jkny=C ebG<b6(J%tXeuH q;!!(={bDD e[vG7Gn[9w =R94 mԎHnG%B7HFi{>>^$H%1$9\gy k1Vcr"]mZ(૽F(Wқ;<r׫=hfɿiᄈ/ɮD9}yAN_^Y}_GR^WL$ι_-P\ -K0K Di?`Bt1 b͟`  \XIZҀ T Nߍ ^?ArXț1FAz A:YP.WɬHŅH,_ ՆZ``䱅O%B hXLQI֝(RaE_A8a\Atm_dT_)D@qE6"nb3cjD!a-) by"E5>`.pye`X1B2 K4 _<桡b="~o 6Վ "̍a-d::b[)&APdv£E>6 }?ڠ9-zqX98#:Sq$w8!fd|$R?dadWAEFbL%mRTebZݤ QW ebE*%J"Ŝf0PF7P "]&A];KP:!eD$O4ǝ%[ZT@B5GݨX@n ^Wm@XfA䟈k2&ZJ_d^_RZ.DսSJbD8U c_V&N:S)&b&f(u%\S J_Ӯ&H fCڤr~bsVg>aɮpvVn#TxaMzgm$"_#@Itv|"b|.&_fA'9e^d!QH n^b'Hf˔QT~}$bz&-$h${ޣ*5}O}"J*9Be|m`SWv'&WI&$-!ƚwE fh0ĢZ).b8yfZEȕŠֈD`I𨌜*BF iE:jlY!mުFmOrLxb|kG~)Īe+ԩbmHinG$2v*+\!AV ƲN*P`,U2ж<,˝jw^ (ͣko6L&鯤T,%le.W.kI}vڬx!dnM+>Ŷvªp,,TROZi~KHkkB`-[mk~u.2$&:nڶt)5l,Ǡjnz ZnЊnplǢ .p,WmRjIBv 5v.jRBx.%/D]6/pȪUR~DfsztDjo&2 3\"! َ:/IFRhT3EEoU>Ee,iЫL9 o\Ŕ+Pn݆p &Wj  . y SJq.[0*B& Sm)&ėDC3QTnQȠ6,J1\BS ĆpB/Zdݓ0l"Gqd&o߆GqBmZG@!kTm2% Λ>1Q5/ ('dy2 S0v!1t.>rþ29/-I3pQxS\r4 D0SGo(;zӢSHJzbs6(sPNr +.W0Hkr! 24=sݚq3 NtS%I8s9L^pB)Ϯv/2+K p4dEDy4?6#yG Dt-ؼکL*3/sF}>1BІ"P}PA.I bsq@4Mctí=cWmRuY vuR..]e@tDt^EHb5aJ0*[GJ\?puMohoWjvi#4F`o̱D6Ks16!nK4UtnYur 4rKX{)6z(@A GVTD]+vVm qwuh.zZ7zV7)wlOe_vhUf;ZfsX>w&#xwBs(PKDd8eu-OOM<w1^5$xdcc:Ba]a_C#s+Poy|8:$a#Ot9B9qK1r76xG5;yyPP4x5AUg7H]9ow<3:kI3|G ôG)cx~tK͎9Zmox̃%`{O w1}O9m.4X:;hDzzB캷D(;1;@J#Kɺ_bW?7\ߺ~!눞o3 H {H8{ Ek xSQ_zk8tFw㴏˓O7HR:j={D=o۳)?ʟn0;6dv}m߽*vK w*PqGg >SGHFu듯}n3{DsYl I/,.7ӎw)꛾NUa0}}>~HXg{D< ~kPK{WO}A=an<6@JJ&DhjA2UA0tDNw 'QTeK/aƔ9fM6M6 LkݴuVfQ i :'Dr帳KAjhvF TtJGUvۍ*5H-Ǽ,2LUB+qcǏ!UA} ǧdr0OY|pQ][=|x}Pt q2ʗ/ٵUvy Aj#gXMNFݪPzʫޱsiweVۊwي)[NQO AAl 1"{ 0 ?A|,6}Z)QX3{^жG*Q>l9ńd'CYD}PtR61[jB Nk<)nrP:o2;.3jZϾ0U&>I"DqGM=)җF 'D.Qb,G9Q2gS}*1TC=V7%zWaE2:6eƼ(vzfc誠ޜ21*iᛳQДEQϓR] # p\4EuMW+GX7GK-NóPɰBFVaRߠLqvtuw=xuUSc2+ 0&إ3l6iNj7z1Z.t}Uupߔk1S~Я]zP:lZǃ >!N՞=Rnה+[=~GW縤Vrvlv̡f!R(-9Z71tܱ#vOV]DtdRՃFIoa˃ !^Bm=aCG9M4Ra jќ5᧊sh+` 9pMf+zMo5ÙLqaNn&cldÇt`3D9=e~t.Ѿ5ʇ߬+!Wq\g<%,U_B8&! IJ(IQR$5PɜhaNI сy&]>F&d{1Y+Н֮%uP [ :*,8Ҡw]-̒iWW².)F˽?=+f4ChPsf̜YQnlp]QϘ|FDX;>Kћ-i( m91hdM!Ƴ>5ȓꓔO~` ̱U@ sU>ÙL4ӔD`Y\5O[BRM4 @"[j}1_Y^]%^C,juwdʒJ2 !0[].s<8ٛno7ږ]MJSٯk8B麗^v=k"+d7&$-hQp{@nhoTonH 'l"+D,$h֧a/bǦ6@ǔN'e!:^:]ˬ*~U*YK|Ab>su8a"%.ժCƐd_È%K=`ON&R;ŋӋKgq;+rL z%w5~ZnR8j9ѩwZ\H69ܦo^!ӽCYO|Cyg }Q.O%R'sj ]%l=$i¯*%Hm0/-XO*J2ƃXbf.ď@]^/]0+(d*d.O֨d=dB^N&XyJ&J_0 +䏚j0`YԎҎL< 5P+_ZP 鰟rhb΍v/ пXl P sY bGgZj/o+p% cR 1L 6m+ 1%.n(nt*(Opy̽j Y KPEn`/,1]jf.q upU["O(kPP>"1!)HbVc+O Qn+%$R!Vqah,mIp"Q&y!%oq%dd&"DdG#Z!]Q0匇pcA%a*}f<"F'[l/"R%1@z@)q$r/55VDhP(J,_b#ߑ%ڨr`oʉ<aR/24fp*1(2QB$+q-u#);3*E38䡚 ʔ 55U 2SR$OҞ33a8;1dbK9["ǒ,U^&p&p)j7O%;?c S렌S[ 9QB%S0>).23U!?CcSu-ϐGշQy^Y rYhgwxh7lXUu h[ymbyՙ#ZzZ9 -n7!"t1" Z4tTYY&QQN0dD7!$HiIGMoT嗞75x3؃Aך )U8u*1vz6ssyG:P&e)A7&=ڬdZQ$YzwX7oNZt7~8lKpbNcć(DCM!}V":1fw+۹Oǧ?ޗ>űL[ |[9=(n:~yIVú*>(^S~b#egᡞr9R:2gyt'Pn?(1>k]ɝ7_sݷ+?̑޾Q_a>?Z来+ڊ3އ w& ϊ!D[8X!+93"Ƶe$ޥfÞP?b ,[yT!hjÃ+ZԩT92HL2JǑ,/F(ISVr૓^ټS"A7JbހAu%ۅwT4ici^Efۍ6LyIa!KD%rR*-2ws&Q %Tɷ(<< 0@Vbe]dM9Kdoѣ'o}eaE'g?-8@5 Q.yPb7 FT H#GAn5I@4jQuQE*:+HKkbRv%X58`!#-V`ғ`aK׶Yt[@zYl]ek!9ڡMUv#FU<w;m]"c¤vIDpT;RT*o",%Wl@_YY ^U3E@rg-"e\H"ji7՜UpUOp)Izpqy5TǾWٶaCLfMvd٣ @K%g'(˔qlHHt߿>]⻘nMk7Tr75%kwRēmz?=H(VsG+YY Ud0jQ1Fo/1U5_2x]WuﱮuRv5: 'Ocj_1p,lwFn,-v.Ph^~=0*9rd%;†+)Ę(,ݨ(p\MXy7O{eL4>eB"SM% ɉ$M< 7-q# /F6*eD$FLHuLQ#P!0̑[G%{Y?# e~"| ?V5E4h=rҝ9桦LzMBj#H*# W !a'G xk'@+u 1u9*Y̲ ,KAz0dpc:Qeb&x@uJ%eʮK1iK!S`G޹p:mI/I yJ7ќuh$uiX&U^,1=VS5rs9|ڹd+b  HYTҒ ]oC2v$>rMz)`+v# !.j*v1"LJo1fj]'?DcS/c//ZC SnuS+$;vs00I/9 162%'*a SR=HULb)K]Rv{a 2P\k YƵ%`dptupXeC&SuR9[^w3jfu`Xc7Q3Pkch. Yge}Ya_sACC\~A!pvʁR$rS\/ӱEV_h]7G$v8Vp1Ope y-J##+[\Xi2$I,$j;˜AfXCi*~8q^"kYz.}YO]nuM_`,HpRgOH?(.x_^'.?ny5v{<ºwUGΜQ oB0:P[5N["7';ItzGV"J>#;z|ikwݨSsF;w*,JVf; qrDHw:~ oz A=P,^>q؂ca_a37Lu4-ùw+pFMx4_93[mPyPy?k#~cĠ4:mn;}Xug fr(aOAF~~q'xTeUvi=DWxfb1TsDWogր7vg Q!AZdIz. 8jvVɑ؂TGvfr7U ~es7uAO^ +3`HxCzLvFW>wpQN167]~+6Mq )'Qkg;FZ5}qxyx{]T(/ w6q_y(6;S?Hx25f$%0W"=Sq~{8=2~!cBkHxmrFGq5P ()agcNa+0~!0K2@QtwN7:ԗzxD)(28{AP>OToRI2s␿fD!1QGrX1>Gk+5يӋ%WKYXx#2y]&o M w#e RL!PywɕOAk{(A6YW|y}MAfŁLZBLq$p|~Y9ɃCk@!y=u障a.Iz+5 P65p$ h< WQ_7D,CT-9'B82C,U^PG5'Ɔ^3mNلoyrB92}6|M#yYY*bՁ:S]%(x5n0c.D~zVjdx I4szENR2u)ɜc ; Za%(&*&'Y3pDx3hbY&[8SV>#@f!>N:X@YJOפOB_ &I_AkX^lT7z%yr 3urƒZrBpO |. Nj7AäQp=<7R3a3ZJUP}2T3#3( PuFjy/)K"+XAl 8ameRZ͖O8^J%٦md:ҲD&8Vl:)t8{p7˵_KY@[ e(Diegqۘ+m+w}c{;Yy p}?K%˸vf؃K+M PQ, uB+^tPa8n!^ 项끝Q;Iac傡bձ}qT2fe%ڡgyTaheYsH˽q L[3㦅-j O;PJub,]<][k5ApqjB{'QcZ)&С82+.ZL,2J*تd:b>2TkO\b9"\Í?|vI3[; gV5F7iWk<,a|]BP ɆPOÍmYm"Gl.f⋽kE`L3ƁLȦȅ<ȍ,2l:|ȓlɼ}#ɗ<2 tɣl7L! 0! ʩ,a{ʳ+ɡLˤ\Msü(ʮ<L2LN"˿K͸l#!y̭, ϝv7;+6\#[ mzɿϠ,=,2 W|<%}2mSwL3 ]C*MON ,9 Դl.A7C/MF(-/EԉB< 1mY+`Im՜=QVeCB]-pU l"wmg+v-(0( d-ؑ]*y=ց-ٟ> P؊]'Pɣʄ,aUيU۩fM,D%ۥm{ ۖڼ yٵGA=ٮ-݋ײيm}%M݌ܚ-{)(=α=ۚmJށ Q" ܧMEaP߳L}}X]|Oۙ-N̻B>]΍ߋ'~ =3*N oN;N?=?$A.N0~<仫5;$Q.SNU!WN>[R "挛:^iθkmnOYtvx.˝ش O2>^C'f${_K茂~o^2~Ψ}뮩%~lܑHM뿞6.Ćɮc,键ؖ>G^1(cᎳLζ^~잱~|^/wŞ ouЎ^CNjw><op^*/,og2.~!:6E4]6VCOHQ |MM<Qo?Z~rXOU_n%a)Oj5of/hefz|_HH@ryOihT[#];/qos|SO|Б@"_u/M#.>/OFǸp?ğ~_Lɯguf鞆_|w2+ouo[J/0O._̿$XA .d0! @8CNTG!E$鱇:2dJdK1eΤYM9u WNʝA;QQ7rDōN$ЪYnWa RlMFϮ8q][WUv_a*X\3`Hcx!O\e̙bPDO%=TTC'RQt 9B1RQK5!M1㴪$TCuVZO)  $u*RT/[5(3}uجeY7؛\ZJevDښՒۮ%! \ fw^zb$O ޣ__wV%4Ԁu7aSw=LVX^3a"n(Yո_G6?!k|y柇 ͗~^+_``h!}dx @ 1I@, ZP!a ҿ 4a p"7P $0`D!|;"KCЇ 8EU$(Őt_+Ne6 Y ͨ4Ď&cDŽ$1s|A2ҐWC$A>q# $E(I2IG*%*KP*])Vrfo#iOZ0D^,Ȝs$2ґ7QLNr4iKlR*쨪ξUMA:0zƕsU,zFB*E_b++%T<,9=!] gwZ(Sp6k{޸V{M~G#nqX Er\GLMtlk"Piź.yZ骯,-6^6+IP֋6&+ Qs\v% ɂw`k<0v~v1_PX'I '*Nf} abpc2~ d潰msBcuGFW B W qnG\~.>.`v*-Dʫ2!k)11l>{Qug@DNJb[":VT2 ,8&s&'M+p&^|5z26pf4=NӪn|Xnִ6fh:s@QZ01GlUئa60!Jh9)STϩ.vWJ*b9뮥MrO%iC8rv9S%foF+aZnyTytq6yЧ:}kͫ$QEDybOT:oyM% y6MὈwu:QB!a7p-{mWֻe5.mPGO_LWF|/ߺ>!ylG??6?_W#y~KO''?x?? y?aj;hIhyX %wx@> Fy vy Ը܊ y\@<,BXA|+T,'3BL"B!$# %B&|AވBѸA \BƒBC`$C-bP,DCgHyRVZZVLF8&sia `h|y_"V"}T wQ tOo=h&fedb#`'Z4U?REPGPGNFFD)7?-/=..=..<..<--<--<,,<**;$$:876665555555222222225?HJK JE=62229 >   1I W YZ`#*f$1j;t*7y38}98<8?8@8@:<7.3+2+2+19*J}`hh]QB;76;KN KC =-;1;1;1;1;2<2>2@2B2C2C2C2D2D2D2D2D2H4X;X;Z<^<`K춋F c tݗa*&hӊn4^5' F\n(}Z߶+{hҪ@K (lkET- $jυDcB,cWcX͆Zr;c}5'׹q/Kd6Y3˱Ɋ5_B U롟LICmm46͂L@?&+ߘg>xetF:Mwbjw7 w^3LIځ/y|'Cz:@"?oW_c =5Ԉ;_k<K^C>%/r[/؍mo!ۉE}?;^>v彉IcH<v:`/HےB ~h6.c~D,DtM0ʮ*d1l%F@.tᨴ; :GJ(4  ݲO<<3n..~ iʂ=wX7iD2QSD*|pBb-AS*e!r z+:t#+R$.N|H;t/]bBIGcvY_d)4C5F/I,N=iTHi$.y=CYVBca͈`jYA'q2RJ$4ާ~&Dض9J %EFO$QDe5W,+B)9f4LkL̉tfWza 1D:,"gTnmb&ILRP nvns88iاrथ6sذ̘S]R䛎tR=J-m8Qխt x,nTݩ3U&(pi.:*`' *_M@"] 5huV\h\T̾mЗXٚ‡0%-a6QjX)V!SrlEMYnN6^l,9wmvNS _NTV "(iۖg9ciVlNpa6lzIE}x~pdHV">#*e%t.C؇Bּ^9^cUĜW&uej|$ڶ7Nd\XDxnvub7!yqB8^5&PlѥhX4-m5_o.9π*6mTEЦLuV NڵbZsHSC5?*I92߅T~:R*jjo\{,8! Kŭk@yTxo&Gx2lNЫBVWwȝTcy{+p? vhu y9e=á!JU+kZy$^j8밒ߦvn^g[zv+~~nqa| -f\Ǽ4foi2gixG4}K  B o<ܸ% \wh2_.-5=?yuMh^ME^waۈ,Hً?o/M-}ۨlOCsKyu.ݺـ_.>hljml[vƗ1].cq͜Ѵ(./S?ZކkX[Q>_Coo*)V;P|,`CG䮞[xnP8 1DPB >Q".]8 L Ą]T%zF,' p%F1mFM=}TPEZ R>,B:M)CQHժD>3kS1eM AuVQM6fycL$^8lYdʕ-_3oEs-DzѠkkت½9:&Aeg-xpnf4I8.o7yS\ ;y_Ǟ]vݗҶ T1>:+؄b*Umk}~/ϫ;\z@M@N? 'B /ɽ2[=>l3f;1Q1(H"'$i:{AKY:jdI'2bEP Tc!3]KII{11Z7,5)@%lU5=m@i8b'5Qg7=GW^'E1X~yz{QoTUVkΙ]~0얤gq Z4-5H?vd,EM߈6Nk5Pf ܬQl1hf)&-GR6F%hS6ZiR.<,Wq_|/z_7_

WߙvܷNV>6ê^jFx9MyeOeo> q`֙\ tl'vuwuv//Y ]R 3J WN\Da }Ffd6su>b1p| ,_Ah;ˤQy6Ebpۢ g1VъTZCPDa G9N]3$׵zI,b?qbH(x]$c8~onS!y*ۨՏkӑVQq%¤2ʭx!!X/CcX. "Z{c06qA5ێB9Lb cZA6PO"<8RbBA:^T%ӜtYp o+P3#p#Vsը9~ w0`{g0Z >w:MF,h`P{e)-;֍vu],RժFٖC ;Uh bG;OSk#3ڵ뮵-@:}٢YRݼ G]I7FYnEܦ/|pن*kQ(|_:,3\;wSMjK\j 9ZB. q"| ^oqvP#i'/E !﷠>}XOov><#Z# :3@'鵪b&3.;k f?  z*;|<@Se@13<@T9K3 $7dS2r<Ң>Xyv?K8>ջ.! -V{AC c@$|>F@S; -90CQjSB@Cp*&<7[ժC k5 Fa ǿźvBZG3>FzHklB,C}ǺFNF y(9GD]&X㚔ȗ:,!p̐H)w dӐV;)\:;sG`|iɧFXZϸI`ʺEE8g|x qIt˨*J^<*dΈ&u43LKL.3dL?l?~4ɾd)|Üx,̢TF l4 Z@04LVŒCJdJTH4jCJ4MNK4F_PS価<Ɇ|D>yčMy'dͿ,MNv6 ΓL-}PNQGQTbQѨdFOR .L(eQ }M^9`.z/BT,HHWt$}FA}65TL849R}1%т`2͞3M@QISCk;'^@UOHʂIAE@T!T%5,(R5R/RNVbcP2dJDG4TstxU`EMTԚ2V%T4mP#YkMY(.l Rdףs؁-ؙ;X=٤{ג=ݜЙҖ}KMdUUաm>eZuVDWؑ%MbDP}J9š험%Ž!lNZ5څ>ۣ%[|DYZu[T5VۇU[Q{r M\3]\K ZI-Z̍H\z i-ݪ-? \{ݻe,Mٍڸ\aۉ.X5AF坹ImX ^\]żPm^P͐=&w4Jp4߮u^d^͂_/\^VEѲ#_TRŹ+L@_"SW'ٔM~ܡWTD FƪvEJ zU:^΢ua[l[ GI`gu!_e` ھ %Fuŧ.2f4q5U.fI&U FYv\2>͗ՒNRbB]ZUr-VD<%KC$c?E=㨂arcu"XIvס^UbLCU AB,E V{G}֜_;b"c9VcXX!B撿*`Cd8F]Y/"d>Ff=98$%\6\q >fU/>=o>q&g;A{?DXv޽8Z߃0dEag8d"}9p?uCxh(_y|.[n\sn@V68f_>҈MiH>ei0|<~ߪXhbvfKM Nijhơcɸi2ڏz8*NBhkg&ie;>lLbviGhk7]jB2% Vke*i&Zݬe~6ƒɞ ZNkj?i٪㔮jf 3Ghnۖf72KNmߦ nR>y0 + |B<0lǐ>Vk6 nloCo:k6VDjnNh ?k~Һo/p<2QlWN 7V SpۮH dhx?GL lnnWWɊ&, 7]r '13WV5oCr ra>J6O(Lxsծ8g(Hr:o.T?cOr'?!G9HE "GPKsB66Ei.mk_SSC Un0ɸ,oi%WLQ?t$wu_I?a9a4rzt9Ԅ uUsepնv \ocm/8=O wz2sspWU@xl+Ns swfdX/ǙVkKoxWxFk1c=QwS?tuvw>8@n{Lp+ L6uWyuy8DN67"X]*S)ww.fzi/u)ӎLT}z< [Gwps_t'&wpym SNm1=nzF{b(|Aw%SWz]{.}7Fd>ןIgz]Zz |ֶ|Iϐ/DjDHX毢}u@sIv'/W~9$C?Ǣ~FO%7~S?ukwC,h „ 2l!Ĉ'Rh"ƌtaN#Ȑ"G,i$ʔ*Wl21yisaL7w'H-j(ҤJ9&ӓ9Fj*Rr+ذJ{qٴj"-ܸr.޼=/~ .lx"Ê3n,TS62̚3CNe–}+%GHA'~(J Q,H%xgc\rvaxx qv>atWz1F-`7JrY#uvd!4d}&d6b2!>V)!9nye)qzDXaG[e(i8gSFG lV'4(bv1ԥ)(74dfd`ң )*$Ag^C:kX5I+LTHw& ^Z٪2J[Updr &A-{NkИ`;6KۈEff Y'(e'ދ0 tj/8\Ҙe"jSLvn!Eܜ)ng6v]5꥟{oOa5wc߯'yL.4K,AK\LoR!!|07:WAֆf:S -PPqf*JHNXzUr0B, Nw./I&61xJW@3 Q2?&RIE m)[TIAbISEuHR $(©|֎vRdb?/M5)(3cUDT"rK,mXUF7)C&ucj$Q=BԠS}LiU lW[ŊIsQNaM,YO28)4bRՊ.VJbde_Ǒl4!!t%ɦu%ՐXOk_Aw+=,r:BТ*m^QMtQw\[VtA^"1!Էh!)l'3b M]%8%S a3QP4e!,ϋF+C_ԾW (q"кE |[3RnGm",ok:Q3JrC>l^-(1Aǹ.Va4cDj2J5*jq|b&ڑR؜_yZP֒gqʬT*+W^/Xgˌ dOumg_tGwC*AE_ehX|c2xN;я~?eK_oҴQhTxi˨;CvEqCB6GxXpT5aB)e!.rvK ێ2*0m3_)sے6#G*$Gz[XٽeOfk>VrcxP<_l|! SH!Լ3nzH2"!0`$/vMw/[޴GWhqMp4e+U,[(Cqa4Č=n75EI|?Ϝ܀8w~gw5'Sж;7F{L! `6o|U[qK(RKuԫ3n۾j}+z ;Gw_?b)F.Oн{;0@}&cN 0~2 R7MޙJ0F!O=?=VaC3MD5t4ݝ_x_0M\ ")_.ŝ  &.G\ ~_"!\YG&]N޾(  ( a`A.9 UƄL ɞTM\a j!y~Y`^  NڑL[)`OYDIܸtb^a] J [u-qLGq@EQ",B}%2!]©)a>`CM+R!pbO ^"!Iaτ!M#cm5=22.% 1J9DALAb b7¢x,S"XEb֙; Y0z  pQ@T (?"E  n9>lT".#C#!0 ScK$K$EV@$! $"o@ .U$#rc|D2%6n16\O1 V>bbW iid%\"b"Q\cH/_O2QI2=j534Ҥa\"6bZIZ."O>W5# ^f;ڥe^c=r嚤ֻ饦9daLflzGXmKCbsI&lceodg*]i}iViLE'$^VlzYfw%-fgR~: qfIV>1s^T*?X^$doGff"zTxj] _lf'{}B'Jddh~~!EI5f PlK1`ݳcꨖ~rfo#p'-N#<,\ #5gJ)`EpisHb(In}(bi ]N~#HZn^^>@vv(Vo)iJh/Gpzr.]R(^ԪbknkƋlQhQt bjfN L*zeiilHaQ',HA*,]_fu$c! +ɌLj~  f:ɖM¦l,hZURijfr.%jvxؒ-y٢tr'Sd:c2Xg .Pyd+&L> _."F&-daS.nM.UH­gTƬU֢`Zlc.k|,.[i?y'$OJN^>ǡ"M߶.zN<&W1-l^:b]֝q.,߬}:ol,.iMb~kфg墬֚roĺ]'. [S0lX`mȿr8jo,힞⇫Oj ;hTO+b.qmJsz&0ƫ~nF a,DZ,F'-G6mj_o:jX31u4lڒ^1,ha8yEzpʱnS~J#nJkinrhqH2k0"!$d *L+Kg33fW(%0&&αW(s ñE[o[Cn|u]FiLnnG4 fnN'U5FI-L$odSGnu&ˊf2; pD/v}u߳3b-G./J1K6JCGhqr7eDgit:xJO=1-W? 7[eU{txx[dؚiXQ[7]hWO7)Cu)u 3`Gu$Z֗kJ䊱^tyvc8Ķl(H_Z QB4s8eto/g-gKkE0"Pc7Qܐtws'ߡ*Gfx䢍slbm2vomxsy".[;={9{;+;/# 39;ϻ_27MIiϲ=K'>cbzc7{.Ag@Æ͢=3iJW`7N|J5 @p7'@A aÃc– %.h⥉,n,ݐ]KW)q\9fM7qlWL(U r̢"lI^2g&p'/yCNպkW_;,lh*d4l+lqEBHpښ%f߼c,bIҤA:]kne+[r jԔS:ut.S>ikfw/ǖ=vm۷oVLk B}{qDmF"알O~^eP^ߺTџڕvK5Ry~|Bek10,߀;L< lI::*NJ.f2I 3RM\:۴:fenDĸK\ )p{.^d);fr\,=O͈kzJJʆh6Tc]n6zR({'?^qNQ̖F-nce͠U%P oD=DA۶Fl}\: F;肉Se)'t*dGTu N}b|~̝4M. 9=ѓ;e=X?3+#jSjc81y*dmq+\nqqg&gQ:!+^%#xƤs-q+ܶŅgTt&fp(Zbkf)| 7D~FYjl068i ᦳ#6bMk^иfFVqߕ͘eYXR 6bm>>oDClit$)SDL?;Wyf6<͌va's:gfé}G⁐=giJ2B`5~$3*tKu|kbovxf_>Z:꣬pEu!C]ZGŎu$(g)f/')i ְlRJfmo* ϖb4/fVj˧t: z`owpm zȄ&KȄfP<9_JtD X&/n-JK>:B;o'PDNo Ih t\O2!p`fhަ12)(lt , Jfn0 쿞 Bp€)~ok }PǶFD0Mʿm IP."^͔*ˢ&͊+^2 1 & b0̦QZ>փ MJθPPN\p ~8$Qr~0" c8˸27O^E R[l,!inرϓ21 n@ReC>5U%xH!k2+%"r8B'&E6鴬bq|2% w*)p&/w+$ '`$K V&rXb.D/E?( OQBRm3jΰ>O2E)cq%3SNLR!-+4G8 j{q-R*1iM֎2Jr3_R;/Z  +=k\9B*6 6s-.&rO𡠒<,r Ak/3Bqc-";>R+,9ӭ"s)g}.!.wVB%tFk傊9 30@BCSBSQ˶)a.h'2M7MT8Y0Ê/iJ¥ 0Ak|(Ɖ SeZ'd 4~fE8MFO+t:> _4?)&DT>TM̎%)$7 3ű28uTmGV +,n?оHDt~@̼ GB*k>4T2LՔRLUc5lk1RRSAES7ՖE EX͵2*0UY?S#V!uDU&̈҂II4bT\ \v,ҵ-oC94Đ:RhHRR}\`3jc1QYEo;8Ge~W;86Wwٖexyyx,CNUjYx븅os6[7ꎷٚ#eÙGr7>ל5ָ ׅ墚+3N.pS7I֛7:a#?-B:USY˰Kz;~ OOwh{ x)'zer#PPB0͸Xv֭Qw$~iFd39S5U\UG#BI?T~r K䁟تyo%wGX "8ڰbs%U7-q`1:[T~5xx_]O "47(YN{tzO:%[q1RZG5"Erz VyAT幥e炶358DTjQ@kxb2ʫdG2rڊ[M659if BҔ  :o:.ܹՃ iZ3)3l!3PqAW|uȯ$Q{Lֻ2!g[\k۶؞{i:M; []E]W)g\!V\?r̽LK:;ɛڍqŲEM[#|w}Y|\Yp̯ր{Щ~j#2S \}k -j Vֳx0ikh5};e9UtW"Doš>]߼ѭ!8e?hzIx'Q|nHxHw^.x |NthG<;<۳,-:s޹Wf<܁ӱli'@rȅi N( l|>( ~ "eQ>C[DD-#ե{Ž[T'}Đ* OnjdOlyT&nGw| H\ E?郖;݁/Ϋڶe[C乾?=ߍh Ԟ9g)oKsLGr!Hs镸QMJNޢ+깊+?zJ\wt=f|^jLq_x0H>J#Id|SE[!5|\ <0… :|1ĉ+ZX!ȱ_>;9߼ #K7p̘EqI PL @r ˂`B AӢf1֭\cn/lQ]2UjWcf3[0mWز]7`2eP\zX!Y޾*z*/]be"`#~ ;ٴkGvLXm-윳uBկ̱vĽuyYz^L.ȿ/&+aڣ ~{kKZ;Npu`kA%w F7FUo9\rq܃qI`Pgu} W.mwuJxuŞ{yˉ5߈>dB^D [uՐJ.$]6@\5j1x 6uqX-xK8x`Q,bFf^"~$6fzglE\}\Xmi 0]9u)!Z-W5ŋRK5ejm6hUo;)eAX:o`Bch*m2ǭVnX[tr'2GJ'C:HSA?`R=vΏMMwQvJ}t<<&Qx$Ms&:rN{\VX߅uagv٢6D}u}K-c<R`NPIzS_~l֯Q7:Kvc/C Nc/3\iyĵ\*C:&2$KBXZ]9ۆH>=4tZPfc&G xjA{Pfwu[@ TYzW鵧[!s\v_ ΤVyesz#FU-X8.s&^Um/2&flY=CF~m]c+uŹyWHxҎ'B\^Jk:gKhڗm1s3@6% 蜲t AYiE.#g1!Aؼ4t#hJO|f~JCb^+6fcv!5f*vHYI{r)M#kjCYC J9(NKujdɹ%=RȾE1:hzl  dOy]OUwl~#_." w1,N)z/L"\քޔB>8KcƂ L;^}G}U.h=ٍuy&WH,H€\$9L $??egHZy[oWam~Kp=dfu1e|'.F]ėX3MD6!}>M^=QgR;$M6Hs%?AR5>Szc@S m `YS%dE8T,hc{vUx|v'GtZy|z7GU87VaSƒMsh"YKA($w5Y"/soxrvE[r~"hQ!$9^_cpdBX&Wd{Ftg2P6VH.w$~_v=Hah7ҥ&E{P OFs&%o 8+38m`6?c$h ;v!̕ntt(R8H'WVZXwca%Ȍf1FRxH6}1KE"X_57`0{v&y9&2 ~8z8q^1G\^Pdp&r(Z,Yd)|pR?"O xǓ^p (rԸ)!H#HW Up w+ 6Ik:9˘VFh⥖hGt51a_HhaKBHNW94ٕ^ (.cJ AVЖAKɏ.y%9"L-{1YZI؉K'u1c\c:9!oy)k™8uWE*) Vw Dǁbie fVqvhY^h($`\-9`TI{ v 0{\Yҩ&I@"^hB#"D5' AYd(щYqJJI@ !o 1$iB.ܘ#9{ї~"Ue=9\\Zi;( "QYteW yڜ1J>ҟU?Y *YXqC058lXj@ )3\臭U aX_*mVHq(4(*{ (.u_R@ R8:?S$cz`Ģal "IWؠ x9&M$EFG9|*BceY R%YvD٪5 :5gz\bZlpW-vtj= fw^ʨ'AZcxʜ֋⶚ y{g211*(qWDɷE1"stvI34~ AT,s2+rֶ ([A(8bXGP4ɧOJzcblg7QsHgu9|nMysN8F 7#8ΆvEj v.^(k oʳ HBO:2E++DLô6}Vy8=ZH]oW{.H'˲Yjz̡ j{b yA{˩;~˕+DCuTxIBIARP[ 3242DK>DtpD/2' "zpI1K<;: v9a;$kty!x}8gI4gP0$fקHw80DOԡ:֛wТC J(#\~S9W}N|{I }+Iہ>>Q}R<+.1 bܞa,_j +BrV%9i&R:1׋"UQ(LCCG_ʮ|o<[n ɓ|.kJɎ%ə)˶ɝ$(Ü+XͬL[IS9a;8㴴_[pM+8,9 'jδ,7\4>?F 03@pp ]ѫ3B)qM{D=ۼJfݻ18$<ļLC?7u6 MRW=L*M}G;HHyL'3H~ҤauM.YװqЗN,L@oD!~D~w)4vt0-+w׳י 2u+%~>IǥQm "u%Xٟ\1m̹1-ӽM+--$+m:̣Kܰϭ;4*+@4M1j= Pގݎܒ+ ` `ޗͳ}:cP *p \߲ >~=2 .݃ .)G!B f7=,EF>'~6nE> 4NJING>N2~=Y.V':.vY'R~*N{bo~~ t~q's j(;y臎q2~&.ap^ޟw5NE>1p3~`.T^j1$@10m. ͞]@~N8^!A3߮޽$N1]P~^mC1+R~޾nn>O(NÎ>ϟO.L b9nn$-."#">N _:Ug>NAOo"$_J*,g'^I%Oh/J?_'Opos/E+jlO6B~Հ_Ղ/yW6rMKٗUܐ/-`JcQSOU_nN3 1Pß̛/XªvmWߞ??υ?O5,$XA .dC%B395n䈰!E$YI]81cA$fyP%s5uOA%Z4bŋrSQ! f VIXRě9%[Yi>Dq-ʦo΍HeZejIaX&\0϶JSrcTa0`ș5ohb &]Ӯ˼1siرe hڹ,5׺'^ٸ?Wj/^ue+y{eO^nfWL{ K7@TpAc0-s5A 3p)?4C +EkOXѴʜfqH"Ñ4~ Br -I*wJ>DO,1+=rLzpM8|Δ3Ϸ{N@Ԡc"OR6Nz̾Wsݯҕ믩y ~szZv'/ mW<#Ø@ }H !Pu` n,;HhBājߒ'M/u/a2ô԰.RChCWA!1&\YB1b9tE{%x$z0"xFV1xi 7±~r,˧-0zTɒQ\$d#bȱ< )%VLZ,_J.KR"d>SAI$ MF^SS!xm3%YX:xNXd'9Gx1'fLwFAP* p m@J"*x ƀPË́M=9:ňJJY0 H>ԡXH2Z(N3J9KM2T%eA7yML+:ԩ,RTbЧ)PJ`ZUUJjNUcT)*ֱ1\8ѧFU++\ _ծڪB&֒~+Y*LűPY2T& @1^1+cFq[̾%[5bnvP.\3m4875eͱcw_sg1xkraE7cA?zϏO]K/əkhOGf^@IMSթFϛh-֪5uT&E!v^:[Av2ΑWln6[@P.]0`ƶ i[TWA\w3HkQ:7Wn.`glu߂}na'ب5ćgGo8y;1Uʯz߈]m*y'VmoW祆8{ [[Rk ]8otѕ\P:)bņ|.xѱu!\bЫ5m/m9 wm}ts}jJ]c}:t;/d?p}/iiXyw]ʙnqR=I_="BMwz4>Ҏ=9ߓZg_̩' ̈́k=Gk+#v)zXFeOt}j+{˹c2?hB9@d@2L |;ჷ @>4@K@5@[7\GZe?i@/A؛AA!$@@˺k¶<3S¸c&. |&!,k?á?JJC9 :qc2bAB¼+̐23L&8|7(8 =3pB9?<8@>A91ÎD=DNDK,3mCEá;#EDeCCD ,^4,B1\D3X,7Y? ;-TFWA] bD%FzNFZDPF[FܹF4T\`-vTDw|GGbG{D|l oz>$lƝGLGC|:\Hj{HįH|kHN?r$$s<o4I#RBDIu3HII JJE$x IÁuX81J ڃx@[xǟ$=x# PH!T1GhK,˖AXxxpKKK,K syKK.`ˁh˷t2ɜKJE(L(K LK ̂hԬ NN,ND KQSQ NOC;6111 ,DXdh$m3o=u:| 2(/+011;6?8@8A9A:C9M0y^ylwm|gZQOI<88BPLJIIHKNPPQSRTTTTTTTTU]q x { } ~ ~~~~~ } t q n m m m m fT"=0;2<2@2C2D2C2C2C2C2C2D2D2M6T9W;W;X;Y;\;_<`p@IKE)!!#HXY·]иbk|ЋܨH*\ȰÇ#JHŋhܨq{ C޳ɓ(S\ɲI+0ctQ$H{B\ɳϟ@ Jѣ9rT&IPJRLNyPʵׯ`ÊkTF!]˶E1궮ݻx H-S W'K{u9J2`ͼAэ>4_NȖshTgCw(wmӡ1p^ _Hĵh {%+{{ G*FqaT[CkeB_4a:@ޅ41Q^i(=TDBaq![ !% _s)aP >_ "ebE(#52d&:M 9W)yL+-30_(g縒Rt+gȜ9`&Tf(Еf.y]* ,:bH3SI|g lbˢ֬}%Nk , $Й';7wF |ΰԓ# ""ظP\S|@N2o=*ek ݵѯ 2I`rAq*9R 3 )'rҍQKHNɟy*oel AN*ѵE "1)uj< M#DtvJW5UEDn~Zvz%[7W޴)8=GIXVwfI/0,iv,Sܧ1Ls!noEQc5J&֒0^a Sm@"E#(R*@\W[(S.t\+[݊l׭ vJ-4  {; U W)J/W[`FO- :ΘTku=ǷU Wv w7F!ͅ-W o#)l_BN&nY8ғŔ:c7~MSa ɩ)DJld'm]DqcQم,yV .rLl.RxȃsE|ݞg1pj&ݻ6,_'#їBZ1 5kgT5Fph칍njX8cuWIŲ{,<pL )cl 撙.>sui )|,@U;*݅D:۴et^ ,n,BC:0uܤ޿xiܡ-gCȵ(.L{@8S_ovqNSpYy\Ȃ"*E 88 .wg'gGWVw;ȃ%Vrtj8sbl|oXObAx5סQ 5v ! nPp"r4wP:JOJ\4Ir@K:7znf)n5] wϹ>31j*Ơon c᪰ڂ-yv2T u+M^J:Vc~$ aZZhٟZy1I~[! 䚗ʒ*fɚ$h*GYʍ笞c1(կ?S^J ʼnZpfn B+M|SxǚLjx4:UjTaC&*1Zfjwɭ((ȫk;* b48n PGؤUUJ暯g9;7'j)Jf7\ۚIDE{7 QnpවF{ut\Kትd;mv;}åih{2|a@ȡy0@*sxQ.ɮ)t8o!Ëx7qj{pU<s:  )0S{2VۻYZbk+5d١J &֋*+$ (AIuૻkSRQ{?iIEʸb_ued;++D|#唢ڛ{I۹Vk۫kI۸XYrk< Kb#<-ʋ3l^q"E|ߪAlĝGIlS s2}[\!*ؓ4\WVd~9i u,F W*5˼0o+(-WLʻ9i TM!f Ʀx{oNjۮfƜHʪA&ȭLȰ 1\ kxb,ʨ,b-;Xʽj¬|`9φ ȸ|^L,I\,Lmd:+֜ʀ&= le'B(a{kX{M0E}Cͺġ>җ|RB0MC:[ӐL'L2ljt<ϳcɠ VǬeբ*6?+< -*'b=h'<ŶRD}IPG;ͫDҁM&ݿ, ؊ZW=-d6,Lڦ.BםMu}| Ɲ\ްxT}~Ԗ]rދ $\0^2p$& *fNC˾Fa>ڟ>~-M)mmN*3|2\˱nSM߶~_nQ0eNg*L)u>f5'*SҲ 1Nn2x^%2sqm&Δ([!^L;zzn8nw bAѵ]NBHo\ӄ/{);j;HA쾕8]=BF_KP_.nYi[.Z|xQ\xsno|*=wOvOO MUoG 䁟븎9?ܒO].JOb }`ZN k kֿmB?mo)WL~(;q.qF {aƤ~/~̰@@H !7 EK^tSHE=~R$A+%KTTMe5E ,6I)Wa̐3uYmŸySgj͐"UZH1*DZ~VXe͞EVA#rVnūnimw,ւ ^ŇЯv%ɗbuD jCs=9pJ.aʜ)t~ -pʡOU*{йQLEk]ȟG\rVzS;EEqֱ{\x)3|nv+3ndjݴ?nm'b`6 ,走Tޢ.N? 7Ck,+P0,PYo9 !ɽrQ+>MfV(AB0(rZ#THJ˷ :1!$L3 :b.ċ>t>lHM6c4 1s-ZϿ4C͵IB$#)JLI]M@$UK@SMtUW_PUJXk֭lN;ıFdFl3$_y|n8qJ[C6tS;UrPjSpDКTBDi祷^4廋D{eU{5œ,``-Sιh)˭E\MJ@cc.)<Uԓ.b_y@K6b `Jծ51k"cX@-4Md<8dbAknE9NFi6^u9L XT>+<zgcZEqGVj)JťƷ+,6d,s?/fbﯖ]Xjs!Mp.@ пn\] bW֍i#SPu{oZ*,_2HAwTP 4|Op1BiB8G:Nu^^v3V0}r4x7+/?uzcGИKM" dxI'XVGRMw69a1M8&rtb= ΋($%LfZd]%Na(=ҚPJmQtD} ,qHtMQ/=ƯIџ4gn2,N~c=l\;cSy$!><UC0e2(Nպ^oM)BZ/bUw,XTũJ}GSU]&:@%Vi hX&P={}lD%ٜ]1Jͨ_qsW]՜հ\Ov֮vf5EfָǭLGP*KerS.E5Z]fAu`a;а:s&qޚDʞ])JK\"׾ȕ-;'o$^zY҈8 RcWgǦ0L2f}E\UmρJ-" Hl+'w]q"$hZBRo{e0bӻ9k\OMuvW<+7+wky KDưcX6{r erqg+}e.).G?28b8E؎q=m"WZJsɕ9iw^uS X⼼6W~y >sV㎷YQJ~H7~_9ױ.s@3bt|F&ϓQ;>gQKI{_vr륜ܦm8j+uXSanulslzmcvP{>;!|cR?2t|QX-.kDIZf9{lӪeo[矗>F?v|`l]sү?l}y2M-;޳{ CtӽPc/rI;[&릯{51ò3{lsHc=C706"&>S@Ľ0A7ɣں21˫5C>˹8>Aۃ²<04Dy1*4tÖC6@?A" :ľ DBڪJ{Ct 2#$= @![?ſDcU'<\SBW3\ xCE\+sDLDmrad8detǢ3OdE{?"o;$L 注<_c{kGػ=ġBǍ $4 YZLBdžLA$dFÊ=c) Vȟoc Z<ȕĮC;=#HTbKE,CyIKRxtO*\6zGʲ #2l-{D5 AkJmHG/]YJ!$uHxT0ͧ UU1VHY@UM@X7W W:1%TKVcԁ1Sug@H,l<=mWQX؆eRRkaz9,$CΌ8UbtCWu3d,D,:XGMX #kDaPRYW]֙ʐS-h2\DWU/{tO]ZYyW[Ȍ%A.U Z3]Qڀ-#Y UƷkCZxؽ}؛ƔY%m۠O="[l5t0:k+ lQE51[H}Xs7 WWW-ȷle$7(e\75 BiQ;h\αZ mZ ͗E?o[U_}^֐ٜ ٽֽW> ;D*\M^kRTe^&_(q`Reߒ,uM aG^iL_,PZaC^6Saŭ=_Hb^0]"W%ō%a }F 0)c;8-)\Q-[\#5^blb K7Gv5:&\c,<]&EZ1d!^ո|aFHve{YJn|+ _d<@EQ.dk=eTv}fc;_eos:[>QTyC$I:^B6vuu~9l.\kB[_v`1eB`l6Rc \vf3沁g&Dy5L~nr.aIhrFD.h,fnfBBh'F .ۆ h7ݳ8ϓ g {~.߁Fbc"F겞 hiIdD#.j9` Vfsf[(^h6{1ǧi]ޱvY.OO㪾.FB}b^fG>Ӷ, Ȯlob{lkжѮNd&DuFN A֮ e1nIZFE 4i!k&﷾+T/]k玾>Enb,qΒ6pn?]{NHUaouool珒I 4hv!`^eqyq ~R62 gU̧qqjF'dgٶ6o6_oJq.%-r]۵gl4wXopNgӨr{d r.>/&82{lV뻒/mNs.m{7oNɳCq;=^n>so4q 7ZCjV5wttt.K>B=ft|kX,D߉G/uf)'5/WW{;zmy!m3w4?Z'R r*'bwSH_WgNGvӨ=olWu4-&`_tFww2qW?w7g6vru]^PV>h8xVouxXG(ZOx\J$qso.u8;xy\Ow[g]OrHz_o+0fywƩUs[fu ֲSb-EaGt5:ӶY'A{ "zw|dd|~3?lhfp5[8c} m{0Ro(z 6w.}{7dҶGvS wz 7@||gXs腷o1F|l߸տV8%IoV~eWEZ$H „ i(ZRxp!ƌrtSAgF:h$JVV,hmd)g.fK`.Y3JA *MB(:ѨRjHZr+ذbǒ-k,ڱ@Ev,O^XH[]#f0)J;jR#MJuOZ&jP9\Pd\!Ī5زgӮm6n~tz{p/ ޭEKTpu :H xj )9fV].ng:j93yJs@]rvfo>(n‰E]WsE` `XytDR/}LSga(y h}B"k8#5x#1orqxO; WtfIX݆ٷx:V"MU(%YVٔ'cey&i$Qp#`Ij_DAgQ{= e{0 ꡗUg-Y&Y*&f3Yj)`!i^In}U]P]kQVZيLI6"YtNJ]):l2Q۩oJꝻ(XN7-P^>ʥ0k {,/v;ܷo(²vDkK!9jY][ lڻ*#21{fDnUdJ47T^x_1ƄZ5ljieG^u.,ɵ H`ܘ-O*o;zB:al/[a8{5J3.>g@nCslGXg=u{Zޒe/y}jLW@Yl 3H_49-Ͷwezh@/jݣ=F (ϵ \ bБ0é-nA 3-9]Fʆ| ԕߌeH8Lv!n,"fN}p^\T8&bZXelc"w;+~R`IvA=DBvtp8ݸ9 C"ȣ1 13 #>\k-$0)9L4'ч$%3Q B@d6Ƣse,-'Ion 9GUR|g?gnʼ_Y~bѼu+ZZ+1F*rAj8s(FR (x3}bH!-4WHMz+t~:BQhF*Mmy"F@*!u!J`:JU.胩@0T)ެfÝuգQ;ֵ"MiJ; jB@ZT-VDNFj᪽XUԗl,fk>NQ82y#Ǿ/l&iPa儋Xek^45gX@ԒҒU`f+uZ#\BWvV gS[R?d;zmN yҧ3mP*hj:!PFFm>оUiVj{V֦+/B](1hM/{#,a=3[C |/KtJZe] gCrcX (1}sZv]ɸz BTM= 0<,/֢h(+q1\B5O>/C+Zp1*:b&ĥϒ_9' ~2b5~Y̆>jLo}KݼPY7e-K*n5]X P3%ˀ~0ogf,,R$U.1[MQsa=QV.v r3}h7äG &#/e180czSZ,-o1Nbǝm0KF d Pޣltwjj yS\ r?;۾N)rs=Ew]^ƻ6g&ytjvManې2E+8-<<,So;pZ +U dx}₿&fNާ<-:Ѕ1lGBq"_i?Yi K` ~d%]sq녜Q|YPI u]8`)͟Q Uʼne`IV[™Rܡ &a&yB T`஥ٝ `՜Λ@A@aA&^]oX !S B' U',l#I"Wt^`'j",(m'@ i#KB4$( 6))!"(Bb51#,#6!\66c',Q8z 9<:3Bc;#T8J_=6 =e"?#@d CU";c,;FKCF@$G~9KaF~FR+Z Pj+BM U%P_0W l)%o ̲貅nFpڄi:+kWP8 Mۧ0'qt2q~H& 2E] >Jk뫆#qif2pjZAqqWBlez-CZ`. e2!Ck/1tf H/p1v>p E4K&@$s&00L/+F2nq8^/'r s1P-3@37ZZA2+Yh6#D*_um3Qң.HHF(AII&. s"+9>4Ul'[DjCr:4zF%|627q'C3?\4 ufi`^!Q_+]NlkHDDE[tcfKvge*Wfwmfr1YhiwUȏ5Dw-Vk#4`;Nsl_`O3znkGovwEq..K7r'XZK:.C86vHZwj w\;JZw EC6owk6d6b@EEqucw.f8ZE*IHrMǟޮ2q3x6,jU kkQ`u}ñgx3[t;x%X1rGx.vDdgo0390?9G9K(m%go|lj}{qw^w9Ba7=γo;wzX2ィ-'}E&6KO=Ķc=CğO.|;˳Gs2o{گۼSϽ@H;8þ*>l#~1>ѧR3D;|s<@ܹt TaC!F8bEZѨQ6-LFSRHMv<C/8;y7(~mڸQ-_zU gUWfպkW_N\T^zQ]+lűL=+׷dF}Z+Ӆif!S2*ac}9N,u1ƻJY1I cٖt:N'ZdVV>"1aK1zVPQ}F%G:&Ro>zuױo}[v0l_n|׻E a3t{|y:a63-|-6Pm7Z7d-ê~wx'Àj=iq12 -Q/QrO ύK S*2KTUJGAܪBgC$(7AP7z7  YDJÜK4MTElHHj?OJG„2 qo-2RTP31 62Fy(svpB6|$4aos#յd_ O?+{oMQKo!sn[/"2=RJ*˺ԗxr,˷[9<6܃PXi͚V3Z;UYb_)EI.z I&KEnL`涺OkW>58SMuG*63O=q6IJ]Hv%ZZԝKhnmNKfMQeLoMuT "@RRitzقZY2 a -41։ϰ3_a]v;Qv<ӈ\]~pQ売J{^\!g8 zuVs7$(s( !!je)E}_.mӽ

XQ T7Q TչUv՝zYĊ`l 29ظ2y(A!wE2m 7T)mz_"V:D˥pJ̒ʰG;3+aъ|V?_IRҠunP}[(k]Fo^6~h/ۮT)cOF55zbmׄ2I&\'28Yh"KJ3~dy֒l[Y4O4aH6fBT]87mr&kaΕ:vr)GϺ-ԍD Cך g;kg/ƈ=9'>'W rBg`eH?N%TmqD aq F3RB=mlwS0"9 I]aQqI1a?˜ʊ{-d\$R^K~v=3cY٨s !6ԩQ^g:I~Aㆱ22ӎ5o% aW_.TsxÏ,԰-TS0- .pmcFMer.ja/{Ea1>haO0./o殹dGymqNdBpkFC'4$D ob0B "habF0V rRyMDQH0Хzj/YL`N:BX,j/F!B)А$|KOgxZ@*"I $!Ԍ͆j %!pE@f )p 6uNln1 iP?@2|h0JT ULA.ai0n 1Q&֬DH{1qU%,%-q"@hUQ,z~rHQ, Q!]|O"#QOaB Q!zr%R, ? ,P&2j҄HA'7%q$(r{4)ׯ + Gi6$qZ%.2)BiaU;l}' ݲ ((3As0#3#*1s$y?3rG#=4 /1!0dsvp(Z,0R )%sc/$9B:m9fS"1 p as۰$NQ&m3+}1m0!zx*TL=3894?I}p23:ݞ,ό 5NцPn1-=3r $)C3vAlኤEKI/4U?w} A mt̖ !)GQtJGuC1m3MrD>=PIU6{dDt;up@STH"2_ IDG۴1;NTRsMTCQOSnwKF( jSEQI~)X+[sݦFo-8}ʇ9#ؕ j$~KEƝ?abJ|-"ץ׼Λcg<?Yo&Ha mrS5akqɳa:z[J'RC(8 zE3nx Բc JGa}\e؇!W<{pw9Nh Sat !ͯ5, Ph۟TI!e%ud "s[e8Aٝgn9/i&."1Jm'2qS^c2C<-(Y&>0 Ai10lJԫ3|5[aO!4\Fc.xH.S{"!IrlL"F'຾܍s'X$Π!{X=hQ ˏ",CAz阌gZ&KȘsiBvGy\|ܺO!ץ< H,(LWɀv2 /DHolH(QzDBI責y  ҷX[iO1Lhe |QL9 |\7HԢjZ_FO"|:;ZCdWo[r6WBC#VDD|"  9n@14 в9"#[SiWrd^'9yZ~m6* lj$ĭ2vBM $yAe BeA\t ia0L\Qw)uwoSAl,>ɦqpRs7g[ϖd] !X#l-D.7z4K-,q.ֻ1܃)5nl gm;}G@%CXn'mO.75=Xv5zT眚Z;Y%?:z=k‘Q*?cyGȦ4afg1i0m|ѰmiU45Uylej/@ZНm stZ<{옲x'fζ]2WR~r:v/-Fc8'*8f 8n36)sV)RnQYMkezȷ^w+pL~PAxl4b9&[[nS[oG<Ÿ~ռl9[?}xGqk΁X^sd'r&y9ck}] :WG1o+n5|jzo#}To/wlx >4Bb%4їL9_s2ջq^6DG=\i5=!4ѷ⽾e$=1}Fzq[Rw}Slg|&!o|hi&u hr$o&md;/x78}zw}&~utFLC{S?L9HL9`wx_#{)e#eHuv0ȅ`[3v7XzGfF"n% hd{C,GMy Om{–B:22|?g{iׅ/_H}=f=g";`iRmH}g@5Xtnx3Srd#xI!#)rUegQge#C2|(":r !O(ihv!q;g}+fx40bGS@44i .g9nَhIyrEoWQ7rəycku۸c! cq%"zgݨ@8{IXŘ9Wge#UvCcgsY)(w9??v^1i'9IxK(MX^ci-Qv).H[6 /ɜ耭5ї~R9g9~ّ 7記lYYxX5ɡҌٜs9w*d|I1~ZuL!6Ŗ7~6fɞ%x.@٣T(աG:8~d"t/ro>)e⸘#!ɣF1~iH `!D6\j'ehKƹ(TFGI|#j4s*ivYVnȧ )9v :yÇFp쨦? b8ʍ$zrY0tʺ]z v76 i'ueIEJmhRڬGုɍuX_  Jj)ijZUgil%Y k& : jY @ծtW'`S 28Bۚ; W°wFwR :EːhOA*esDz/Kl2H Rz 8+@<%۝*i7:N!i%++h9U˷X2 ۢ}D8t 6Z(GU9:Ї"Q(I;bǠJҫ}+4өNz%9Zq,1G*uR M+B:xʭE"{;ś1'*{BX&SFf{J}zk^8a;> 7([k@ @ Q nPLQuz,R 2ekK Gh{IszQ;8[紳Ȼv۾}kC=@= n@`z6yB?hy 8cRc+jM |3nY:cf:T$䋄,n v0 [XOF.&ujp"rjE(<~큨o 0N1:)e)/;'\l`_7xvc\Xk\ '1k:޻ĥ Jғ{<{Lk[uQK V\d! è&\˚ G+/5 4#7򷾤\Ă K\\Ylˉbxm{˛ Gi rN++ L-|eoz $& |L{2Lhs,A ƭ&8ꌼ;  gvޚC+lk 8zQ[!?LĸK#iAuҼ҉2՘'{? RCHwGmL, Ԙ|ģ9<_- 7g̻?,p$-b#!q'ͤM ɀ7ڹ~=QA{ɏښ"M|;Mܠ{9qNl=;L۵kٻ*L`G ߝ[h]]mIdFG(+Ԫ=Lg3_Jp9c< 1WvP݃>Q>sq=]!Phaa QRDZP "۔cp Š, n1n6?|*{,􌈀BV#DW>t`+ !sǺp{~}^~υN$C~BN>+ WWQfPQUD B'QE!Pq#=h8M 3@ urM. иlGBT-솎 mX.S%3PZ!!1.W'&S2]ca<)r/^>vx&{;9lϒBL.2跍ݺhVՈ6/غW&@){y?Qɿj I 2왽ݍi޹!V -m.dpNT(\s* vE$YI)UdK1eΤYI^teYх<{W1$8)T^N9W{GCJ#D]XY]$-Z)ĘNK6! hn# e̙5o3լJz zϢ~5,*̩pu+W7z ;ֲNJ}šN ŋFP-FZ0/\l_?$^yΩn_o'yV`sOTH۸ʗ{ .Ԣ+2α cn2!8 ?̫9#$*EcqF@[H j(c̑'mn)6/@psc{yBKG@.:(XJL zd-2e2LL\N<ԳB rǥ0a=q r4&\jHj;P@rʲ6OGjKC:@8,DP U$P\sNpJU@x~6 hXg':af|^P*"u%P75R*R@l72//#\+,1O3CLU 3EfAaԭ6[d0B7 `v-,iPB,vj{fԓG-)=6@ ґ+kH8̆>IL lR:GIR^VvN9I\KzU:TTJH4ū'֒SqE7kgu 0(Kg}gTYϿSNzXF T ؙTd-kJRIxRָt>݄|*Q+^SO^T%(M2PV'[n6 F(0TfQҶE쳿QQxzmZTgz[ WQo%~ _ȹy<`%.u&ͺKGrzαxZ^p^,R(VEͿ {s* L%YjT w㥪vbGXb(G}dOUB)SO)VX{>_̍p8f vǔ*x㴱9Skژ1Ex#rB,?R!Xh7gȒt?( @$#U":l'%8`D ,O淚c -Q#  ںl<,kMJ1FS!u'"h[Wgvq<]-)D/Y;Uu%եDwM.gp߲f3e4JX`o'=ֱ_axi lׂT~Ga>Y)bS3>';+-/U嬋f qZhʔ4I\3q_Ī,Ef曏Vȋy \]K짂!wm/f6U<.qho9d%VyeL<& Im\_\2#:@Igh=tX6tSύ~3 rTOڽ o<θ2v KfNo}Jiy|f=7i'ɞ?zq/'Ճ{!"7g .4ٟ?Tڲks೻bb7kQS0:799< h@7^>[k*<.Fy@'qK?Y=k8.C"#B[gҰZso{*o#7D" (=C 0,w ̛ ;6 zķ=h3 CN,4;{aN5 EÍ{!3TL @#İ  ?;"`BJŀ 8'Ee ?SX{*S)h?2lCH(9$[D7Z`\'uԽjHej n3?j,~dP#("`$r08cs'!)H\nj]aT;'>|,ǞɒFntjAYHd_| tT $4YǢč;8d$IBI H*U{ITI$$,0t'HJ<9: @mݖTbԜۥ0܎W`ȠVq[[}bZ K>Ձp-f`9  16Pk.ah9/MSeWٍ,<%5#[Kj^]ҎV`eS}++SC MQ2;oۇg# G 5ޣS7ػ0rJevt L]S]ըaS#= @#;ђ!{`u%pm`dKΓ.>"%Ӎڥ3}v"ӟiCs?~$ J]U{-Wn&6) hXh'Zr;8Y&=&9ka)l9e\j@2&U\V U}WqL 6 ImƓiA6Bg! F( ,@8V4dߊ*a):<\Kjk66ںV/k@k>l ykN,nlvXŖzllalͶ*lюJml m Mk(@5:_Qc({_R^%Ҷ^XRmΌys@2Rf}8awfIogə!7فg8~6n+bnn[6p #+lw7B_CBٙ;P^i~~"sɟUBRjQZ ^)FPQ ^߉p#4p!kw>p6q:81^5"L?]&/d_y>V Gi9hgazTZre^'o_>R(VⳖCR<]p4lvsisDw\IzhK1 mown/x&XwhvooB!xۈ/ yo@OuFuu7v>O? 'vyomyMqutzjqGv7wmwzDzPXXwvozo_{wxwzm{vg,gx{U!owď{m?wǿ{%S'G {|+M|?֟}r|wHx{/~1kۧWG:/{~yPzv'~FOs w~O}~WX g p "Lp!Æ@/b̨q#ǎ? I$IÊ .1'Ț6o̩s'Ϟ> *t(Q%R,t)ӦKOB%U 1su+׮^ 6bAx y4bҴnµyɔ+[ Uq,x040õ+2,\vV}ɞ?-Z0⁊Gt-֮-F/.Gz7޾,-tkլ#\._UcMRw֯c*q!gW:fS5V9@bŨuЦSa\#Y-|B4(nD bQb /7;j2%ΔmpL-zN U8ŕ?H @I J M0>QP~XKgB߲<`SWPTԠDʚr:sgj]+c*~麬@AFfɞz}(_ET k7 VaRmA6kzIfq%el~QkMmV;̰Yc6[ڪζB-GӸJA;KӕYKr/\6M6CG.?.^3#Bn"Ė]z;p\Okڗl |ݼn^pCk\BO 0BpW54{0 ֳ 0[ᝄ5K|#˹:0iWxc0 (hE8b;6)xfbxr6@"#\' )kXe+ 5Yc[/9_bTa89/IF3r|M=yy*DhkY-2sJ }hv;Z.9~4D%9-V:ϒ-M2pKmj_y f{h |um댨 vp>%7zӽ-=+n%PP#{^vp3 f_^sTimkj[njwms>-ybo;< i2\~ps,Жp7&n/qF9C.hf3my"an5A \ )p>t? Xv'>0~zل+u'7e^s]kU9y.qc$TF{ڝԯH'{G.F׽M8e{ȓnus?{6M<2Mw;w"W|!xO>ơ/I]b7{ֻ͞^J$|w^=gzi|gm ax(^"+:Ѭ}"SrX-ڢm y`,c#clbT!6b3$b# 62.Gxb`cc$1\;\Y]7c5 5a6fbVqBW@E4"`-VEeTDr aq}5:# ŕ@$A,1BKC;Q;APeD c>v#>$V-dd[=RBa1J},.LJ;i'[L&Ӥ)Qe'U) B`Y N#"TO"CZ"}dA)QMd $\n$P2c0%92[bNT%cQpJ& ].c5Pb&rD4RgZbb`!#1]#!rjoxijOPbc!foSfMU&P]!a'r&#g? pc"EkN/G&vMJ]B֊T*Qs bL&a l]bk!~>\|62&h*xhi'g~'8P^gޢffD%'%^(v&~ʠ':ee$zzrdm(c]t"&hvuc܅%'竕&VG^|Pr7eS'ecn''vh`(gcܬ) ii tr܈i]=vi=ij(^ik(*)}&R^:g) *Z* &b_Ugg4 wikk.*j* nܙJϜPzjL^k7=W*J:߳f̲"_bj$ګ뜫k4in*k+f++)*æ`Rl Z,linMJ'`Ȋll&Nln.j¬4͖^~r;mʑ.",Ѷ]ԂhDyjnЃґcL=uB=m(=܃=tXSlܮmA@v"hAnB$=̭AF y-VJy~.AjzD.:JGnߚK~{.mdQ@FGNnܮAnRoZbojroz*?C?CD M֨M@/#o?&ޙR:T/ Xbo CY? L@E@>|O/#0?pv  |pD 0+0 Sap @1ǰF0bo o?/k' c>cq_190Kw1 ר1 \0O o0 0;?ߎ;Qqq"KhAC(W +19#/NvDrT(0q$E?0% wq1A2#>D6oB1{2F @~5p!,2222222225:>@FVa[UI :76665679((;,,<--<--=.-=.-=/*>6I> SF_HeHhSh`hjdj]kLk/kkkdJC@9*      $%?99mFCHDDC;D%D CBBBEL\hklny +:@AABBCRglpwlƸ>X2222111111111111111111--,,++**)*&7$N#T!SwSoSeOYH\<c$edc*_HVwD2@7@8A;A=>;56-3+1+/,(0359CLORh {u v lgafl n q w { ~~~~ ~ z YSTTTSRQOKIIIFD1D2D2D2C2A2=2;2B4V;\=^=a}GXEtkKQѰTjR<*tOxkZAsFUa+kNn$'^Չ?8U J}Px0Lp a*! c%$7ǘeR1id,gDnCh ;m_NCוZ "^7QMn5׷ҝ daUsC_VtIW 5Y}Y>glb^V1ůpKb("l%}ЅN[4 F7e`dR6.ڗqnP7<lt&Cl_9cX|0f֠nlA9Nq$Ɍ76q쒋bЄZz6 398.^3*}I<Ac:; [":EA#+j\Z*? #]EBx-5 2?u+6(o@Kd:Εuuy\IϿa;ZNҼ-L/&5Cn-N8l:T)1XYE}8I#nq޺7CllbFy!HUQz 1{֎>Ntt! M/qQ䜪 ߹ZJ&~<}Ƶ\q^E\}%6f{qgC`pXQ2d:-] ؅33aBF.硗Fe\Uˬ>duQd_ky ޢ4ן2w蝮;2G_Pc0񏿏N)pN}J+>ɪ;f|աoҩDz*o#FKHc7~Wrut|73$3t|GNzVs}3<N,yVnegaYj~f' fiz LqgTGw'wooٲ_{s ^~ߒg ( fuf`y*V qG |8Huр(eCIXtȄbU8. l%q*yJqF&z"YuvZnf~ȂvX{{th.3aaՀ 4sJxրhVdSЈfX\1mDV+(P^"a'vhr㷅׌~s׵85n89wj(WEzAD.&CGaac>~#=I7XhAdX؍Ը~h\RoXrG!I=lXT\'F|1Y9~iR> 'ukUHvc~Qr=! r8{)i&ٕ2 ,ɎT}X1AKx`ѓQbI)h|.cQhrĕxHUw~)Znw(Qŕ L:a[a='HgG̘P ~8!㘏Ix&⇔A9GodSq؎`"])(uEgHa0‹SX j11qi@ D9Ih:5cJ9nx-Teb9W [' ,ѝhy%FJ)AQYsMɉZg)XjO}؜5gI噩$I٨>y~=q:? ͹i)^8K:[J湌ATVZyٛ$Z*J Y6ZZLTzC>| K3ENH}*bX+JM#e9yc'u\&gê9,KǨTt B5'n p~ Jy(,"!*巶4`:"UjM[$[+`/Z qh&asJbֺgK Z튌ګkh)KF Y2˼y幛kzu؛kkѠUԪDE)!+e&̠&0|)G(ZYzk$[Ɉ(XY TjJb-6~Wʽ'ǚl"I hT X,\^'u AĿ[Sk "m )- i ; A(HJ̭z<*AZgBPUT,l]T< Ӧ}e+-K{^= qbu+UYK_MK-Z]M1S֍ˢW>{sNu Bw@0{ƀM 2:l ]ѹZ};̢<ʮlDsMپʑ)]wڔY]M 3ݣpk03TEvM{ pYۍX='_pmznl .MIw"k1̦-UD4E{|YE}nS =}&c[6KMa:]mݟ*I=>|m=K'+[&Xn'OF '㉡$ΛlBQЪL~=zDzUH qf嵋>.wEA,nji>݊l}N|{Dn Xׅ.M)}O;}, ~f=vm>'9ҳs=M wJ̃N".8]W=nݝ=˾;>RsvױNa\ >>yN"8S닌^~M9 In#No8I7-7On ݋&zȫ&(_/OY\><<{˪M9^JQ`yBSnķE GoLxWKk̯n+/`T;T9\3#Q3/{gG=$tBOk =DRDy3 S'OV@$!i82]E. _3qGA?"S"F0. 1:~wRމ 1L9/~fa[@ Dx>QD-^ĘQF=~RHg.1BHDâ*ƒqI1Ac bN9)xgDU Zq知i5`L]RXeZD`Z4*FhĴKVj"\r=-Ef7oFANT+jYfΝ=ڠ(3t(Z'ǜY:%UMBMHQyN 3BҮn^ Z&LauvX`cue >Ff|ȒWh{0@G">,jdͪ;I(*!ޒB 4(áL0"93&J N,N;(o,:"˄k1J)J AjJ-#JDĐD'86<Ą*f4'lNŮXṉF "ňQG!$=a/ǖ̄~R>G%TSҸ/bi9/Wԉ΂|(41\(c겨$AaCsNQrqR }Ԯ$+!gCtl)ԢHHM#6?lb]w߅73X!5*E&<5%\t DO_Nub2!\%8Y\ja;l-4j%/ C\,LN-z2o9眛5mtmH##N\Pa E^A?\X≗ՙ.tQ/m=/H[;"je͒@zMԮs?>xMq|6&{ȵ1rZ͈ش''z󫠔tw][hO׶]׿mOh=wwOW`emoi$4ԌV9 J60W\< *ZIG?oP#]ƺ}jht?U$Ru[ƻD |bVaB?=~uo&n. %s­cFPj#aB[Gv7ubBcED%mWcds=V(7EM`3E:.D!E8Îm2[ɒhA48lt 8KZBHS4h@ qrT(Mq6VK$1٬^*cرqh#Ŵ#%D,h䜂jNv̋ȓD^!k"x {Ǭ8B$z .8i$M7v-z(8RisH{eЩϵӤ' ;?RT 9CfʔW,R i(,p[V)UMЍM+[i )J:VUQQ4!' W eiSFZ&'h}LS7Z:j:4UQYήJWc"Y5Ymmك48+u'Vsdm cUc84 So~kP}B29򯠎3-g;]\a--uV,tzԠ^K=$5O`nvcfS[Q. Ui]R.KZfY&fhyTo<Q;)RTNƷ`0GXus "%:c\\\ؐY/e;e)n M׾oilIb6˺GgtcarJdGhidl#]*qM}طbD)pJ77x kՙ"*XfE,~q 굼u'N/>n#QO68G;umv-{Ρ<8v5}]1``7F&@6Y#2s=/^ڴVLSB8;oʼn)^uȷ٪I;(x>)=:02ó=?8#%D3k?{cAp7I2D3:A, $+d2 $9!="Dc99?11۫z7 As$1̭3B67DTلE@䐂lMRJc»99 LSZSӗ=@ Q:QyldVm>(|Sٴ#1SPN^L -!%ءGO?QK٤'W4z"BY Փ-_ł5XCC6]F@Tc$ڵSc8Py-4/9]K}5EC1=l#۱}]$Yܽ@K 5S{C㻴dMbܭۀR[|!}%U^Jܰ^}\լ{ulW$ՌuLH߳\\ܐ=*-^uY /uU6%-݌ȕ`DtO"6̦,rd߽?B4޽B^a:aSUrN,Z-Ӳ!1m!MID"͑TFi8xG:(ɗH_p[c-9 Q1 ](҈'^7]3=ݛ-Ƣ=d@M(R&STMTW'A/䕊}na$S_`+e^eP1eQ]F^#ULJD mL桤,6/6ã{?elݒyPhceY ;FsfcMwx>yggk\TTҡGԀ^e|y`JV ͮC҇>^_Xk-e^Yn42 W]tNRNvηg !~v?w$v v=fCQE~U'0㯒רN/$3UT^@U(&iM甋eo2kNӵ6m-GJ!ϣ .աFa]l[v@6 %n\lm PӦgTm|jj+om۞mmO7`xF~eƅKh;n#A>Vfnvf҃x.]c抮?E)&<.6oHV4xK\ A hn> \Sl艩Ƕj#I+* V%'K~oq6^cۥJq@ !GUVUr& rְ4rD$eoT.&nRokv rvc bM"Z8DĦeU,X7to_Οl`s>tstJw9:ΌcOp. o. t;lBj Cs3ׯ]q]_<9fp9Gxe'*,qQw5pRkY>HAp6o*?jI^rYwy+fAwaJlUDtu.* vw 5!t/`u>]xs8'] `gaW5Pyfyߘy-q2nJǖ< C6 c?z 6 UuPazm>Fp'Cuv|y0mC(rOO ̦ vM{-U&y l_u.U|V4mOg\s]֊4?.Ќ *ѷjh͡`CJ.t iF:oc]G2 t,Nڜ,A+t"ih>Y+f.92UP-1UZiQl`+pPW-qbҲ6lIv(HݸQki+.mY@ќ1oU K >89+QRefԹE@F\rDU3Cͱw2pVްeg7Y/><yxD{m|KDEJRV>,at`͜._+ʰ-P~/v~)(Ny(yr d=Q kebݛ-uh˸\7.]瑓NwC6 !_=0Kq%95ā_Ӛ'zpj Q*յe*! gN8h[wR`(9ұI焘A/* >RQs HPAU3]Jocy[?3$Nt'6pSP "P*H-s  66TX'FkY<2͓I# mn$5c\%89VA?Ũ)T)$cP6e'զ66n&ͽ.xcN\fҐ6]-r@nMEO͞it*Л3F봦Femw S*/a {^_ކsh/k)jU^Z$)~Cܢ&GG]A=-FoBjd\(p{UVerH wi"k߰>.Ɠ$J:-BV= ~l.~>F(NYVM­nUwfte-'3ϴ˭cnM dp환U𗁻b.'և$ ٨6Dև4Quh欨={MW3;&Cfb!yvSm/abWy(lmH׫=tuLmQ60sEKX_Y-C,- bu[ǿ4cx+ⷵ;RpO+V8lo=pDw|R?+?B \8 9:>Wz wYCN!Ϝ7ʧҡK=;nbsӤ]j\Nm|p7勢:=/)..*X@J/Ӂx<̣ x zӣhӭЏ|*g=q|H=BAhIX9 [uIq[&5]0. cwot{S'y5Y!-<^CXڵA ;H 5N`^8pQ_;,56-A;Sy0#}۹YXSZ2qQ}D-ܴ%Y YD\1\*`1 ҩ]];LLM]ѕ`>!|\!?UD;98lD ^- -0@ ַM\_Cb܉\MX%CnW@aDhqGf^=Uav{荡,`A0] ;18*3r]ׅB1N22c L@35LpAԹz)UWm}I !ibW6f.~-b"OIQ9Q 1mCCR7^0 :HdC$ѽU^? #Ӊ@$j"> ${ #ʼnX *d{IģU[34+LE5dCH!1X ".D 4"rdGA!&"cԕOp]"]:@9£H p5]IPP`]Xf<",U=bY@2%ȍ 9TjgUj BnDm%EnYI$Fra[n%^AXm\& URUfjZFVͩa@nJp.εxfhr֧1g&`@g~Jg|Y'J) _tw%\>DDTy |ZBB-fAq'ґZ8=iv*\WeX?h:0mfBJ܅\Zob,Rhz.܇*UYYz!E$f^)l:`/HWW%YWVÒbaD^dv>).ΪD`MeD*if Cyy=Z:&W:DfRd-j+zڐD{ʩf(/)˪]&]ӊK>f,%^eMDaW΅V겊'{&ah䥪ͬjHjbF-ٙ=& F_+Dтܙ!IӱDP߹-ݾ"%] ɕls*(bba3('66He$JJbJ "0B8# 5""24$#&[LRr$N񸑛WU 'NwloChb-7/q 3҈gd\lDh7$_Lp&n +/ @Vrf:7k_CkUL"7.gir,#sbr1 ;F.2#/QO1Go12B3C3HoIew (l*9k2I(ǨMxb0FkﷴE;EpzfpH7xk4UF0M7ޅ4rU4RpkXqbDOc4P O5Q :5^Q–T-JwDJV3Ap+6B5]3FCmcgR_W[߮}5hנŁJJoM-K^aoN-hVs'ƶq>c{OKeCJeb6][toR,Sr^VJ~H]6aW+WΌz?C Z7c/Q#q]7cec0u7ry s U'nC6nq7ڴocq6o÷mzcpK/3mN7{Ȱf¡]=oڹG|+; ̝f+S@7ҽ85gx4Atgjx&"xLq/2 3%zsvo{ugіcyx#]kFЖGD-sD] N 5c-vբFgT/K,9. G3ߐDl+/8yz4YΕK|6p[xCd }9d7yǙ e]~ H̡۽$b8:#@9:.;F*vNGBsNvy)^grlzQ(yfdGq%o$D\E1zN.0eAb]z* =?J|Ȝt#zD\1h3*r{sOMiN5Q',&H-WTI Ux%CC&am( zL:t1 PЉբN]Tr˞TGXU\ՍVV,=xMօt !A̟:%h>|v^QUL"Vln]Yʐ?=HLeZLUJ$оihQ[]ui_fXHٳCZFx>C+_q {Bt<4 ;wtW)H{e^- ykoKb[b ZXe~Y]x=?Y<[ MH'6ĎvhqiOLX` M%xk79P6o}XqAjS1jW%ss{{ϙ`LCXQ6YjTcղ}-lc+قGgVYQk VRv _p -L81\d&y3l,i]/jVġ0Ȭsdgډ-|ǎS*%J^oAեfͶ:a:*˼,zXDդe2k[rpEFBz3[I%lI|@, M'p3E/N^rIּ -Kw56n!}7orX|p In~[Ev Ie2)P"3|,s䕂YMcDZ|XOGOLyZ5jP}C}i}ט.2-VQw &ё@'%)'W]{Ƿ^\Bv>sdŏ\76!}oR| Z4?0 M7)bW0gYʧI7j'_ƼWMv!fϳ'2{QNH9R7 (WLFζqbf*y֡[2QJtV T϶ܪ("/P¯)J)J5 ]PhX!@_(@yLa*0<)P$׬P8c" WPtZPt/ 0fUMcP;,el%(0 ِPjaz s  ۰ְG* 0P[1C "`H i.fum H<(`b .v! x,8QTCd 1ЃP%Ѯ"qa* |&Ϡ&"_mjV'QϺfifJ 1  πz krqFllx'bpa!Ѫ0L!0i ~ f* ud,қtPjFIDQL $;қޡ 4%vlf wBawzw Q"P!")S $a2u@'fbz+_r !+gR&H-ĉ-)r*) 4 O'`1$+It (s ak*h$sH#/3 36; 1i*3 R$,4y3rRaN2.AJrlr9Xq`6,S ; ~٤ 0aI&fɬ ^IF KôIq4K@TN lBpȔ,̴ pL!P?'@tJ[M 5q!*5(PSAxNttdO jh5aut#`sF"8?C TL+~!YHTE OolM}AY0NTR[4R"޴\?#@S;@ODuTY摉4 ׊f4W{o!"_kmTQ&LuHtZ >P%Nc1[]?Qe=u][f!fR gJM^(\2`4i &v% 2r!L2Orrn'-(McӴl5ZGP LUmYbn}n[?NsV\[^mn#hwgmBphOh5f/Rin`z lر2.ai%4y9w*RQt[ZS/%NZKL[md}QTx[g͕f]wx omMq}f^!w#"u}.i@vH|)"N'qq k83Wv2N(66w[x?6QS6$ey9S(]ap+guVqYNCUζǚ&:7a3`mr qk&. *iixL.𴓀b YYvnKdqn![6B/( g!qA+zƒ4qFyH`/V3nar>=TR=R~+>NW#{AMAB؊7d}tWd8p ww\K&̘)_qH4x[?"N4SzP oqcU ]Ջ5zoxYNMxiӖ}s"!E[ 9$ty]M6u&@5u\Eb9{Ya8$Q{Sҙ YoH%y2Y"]XJ O)Adm9n9#Zwyx%L؞՚A8$:FgMzᣍSZ<ՀmY"ϙe p:oy"Yߚ]ϘYY=!IX^)Tx^mM{T馡'xy#(zo/EXy;9룝׭-hZ(XiM} B9Yk5@OR r,TU*@Bw@}Pq+Z x+xm7hMÚOf;5]y"WlۺN+;(M .`aN6jWa( {_`(V, [z[ <~*OV70Bٙ5]e;$w8Шֳ@+$i#[`hgG<ŗ3%j|jfNtٜ'M(bJ(dCu Clz‘7}ṽO\S\gϜ0bb!`l T{vq@WV+511aWIGmi=% Ї<:55Vw#˯m*B8< JՁav';،O|(\΅}XC(;l}׵!TX5w7}%DcAQuHSBJt7wE%*며;,?pgݼf{:@cm؇r`)|_xj!97ix5/ A1h(=v!]Svo; ;5>%Hyᝅ^=CAw\Vw [9 ۺ;8^qs}y#^'*w?U=qOk?v.][ag3g?ri@g"vsg"n{ނY~5ݝ@[Y3"-8WCK/zgEO>&_!yayK-\+k5Ԧ |,J_WWSfC¹i}%[0{cؿ}0… :|1ĉ+Z1ƍ;V2;+>:լ[DisiΗu V:a{I0Gut"?N.hӶ/ΖCaǖ=";[}!P~]h\Yfnh/YU^>aF[uYa+ dnLBġCUqH%'rEB\yVIU3mO-cMHd[^yya)XZ0DG"ِi1$B€h =$0(.Xdn gU(ϙH.?wC"/ِ@I,FS0>dWhE&C=Hō7ta7u}.X*dbjFfg`6]QJlH(C:xFLFK+> Qaг4 a:Ф mӏ I^z!K/}P:$7+j%& kdd+'7 NLqG ;3pHKt tq>Òq*"ŠM tނC GnЋ2WAw[HKW X+֎U `;$ iɖ^&¼ rZ7D)<;1D* MXQX>!ͅ!`Al+AFqэnc,E1[$kxĪ Aݎpu!@89մmbJ`*eCJp&V l|C\X bAs |dC`>>˷3/fb&o<IGGAc[i td99Tn O3iڙ=;PRgCЀ taB64$ZV@3@ռ)r0xāidAiI2mqqd4cHLa8Mԩ˧7*2:˦'A;/}l'oҦ4 P*^ / 7 Ї/9wzս-\gpyox껎yQ p_ھ{԰rIk\"X%nz tfR.zx|UhW/݉)`mX6/G`4א@d93$Gb!Fʶ,XOj|c4R 1-tzF4c":V^n=m: }\lѸ3֤cH!0cw@rOW8" FMr:9SZZr^ eZ6'psb<n_l<~p{܃*7` ORlgh%`ȗ|/u[' |||ngG'3Lf5y!1?X ?3Rm1m? #wK#S''CLQR @x+k-7sZ0iƃ 6}5cOoAWaE#GXm=u$=Y{{!u-$3Xne &4F”,XCEVtXXRE`UwmKEaD`}'.Д8Fvv{rzD^ /WsXMZ7wK?gkIo.dSlpip#Hmt,8jl,8@̗pY} vA@QLIw >l2ިnT_ y \0E@$w#iԆ42/r(@ǑD1ǎ7RoUn-M- s8tƏ/d{`O'ŧiCu1i<8}|yyaRFӄ`8'}@@D8R!ɒՙ@Bh @%(90E25e+GNyQYFzhz X]&Ee3w,'wWX{ypِƐM=ԩu9+'{|nXй7YՅcXnX7-1Ll-2x2o?v@2RbX/8WHRf ffNY^A[yzƁDMTXV0؃f lhqٖ؉V.[W}9tiǛiaE)?Sft.Gz9N[ɕ0'ca9XU,p͓tIm=J:v_Bׇv*$ UzSjʰ_jr Q>k{y |QK'iyTTͲzfNS#xKur67b ӪKh.ED7UL[$\'EdT2g#wXvGx1%WhӸ|g$Zx2g%Qy9,poA\K(aˇ)# o)+VKP)3K7Ժvo+˦fXRț||Zv+*SG tcK})R凍{L׆c)#9#2:g2G(JjXS- eJfk&z#+ž$̉m+!&ʄRδx2ǤlLKԅKD(ę'XRx1[O?T *$Lh@j@. T®J[^;y`/k s_)1j*JEފ%5=}SŢ8 QK2X[< X18$Cx1(8Kʤ|FxW zEFIȍ!f˔1o\kƵť/ A1+)t\.ܙh|/sۋz{ZX< Lnw{jJʻbpBϲY?St'SјW=WK!qMXԔR!%"e8CwpTI`-]\{]jڽMI4Լ: 2j=̛X/|1Li6&WvX=Eyw["DLx7ڂ41驠?,㠒UM;I^(ڛvr|AYj,. Ƭ&x" u̓_8zӄ̳z{6$p#.7:-v'i< mJPbΏ؟ :ӫ%Χu'+MsQUS:J(PlqDްaӼ%< CHKcYsoMһ߄ܕXG܃J6.v،݉ N9 w#y3:9lu2\Ro^'Tϱ-ݸ1,(ޖ1\`.!Fnc%~Mݥzƪ m Vnmz #>z] </Ķn[Q@X~?f0~kn/J o L^k%>Ark ()4 슑n0+m+yX;: k<ƬXWB)|> ;&ϐ+i2o%Eӧ戮K1v2ec)6GfkO2` Àԩp2 qS#WQz"!J_U!/. U&\_2#<%܊}3/ R} .ýEQ$Lz o/?[~UqV)OhpV0@ ~S(Ç "H7O6Q#B/rdG)Q ˗%eΤYM9uOAOE*UI=JC.fB9ujW` +U`ruL͝s%]Ka\w P3]r!gCVn0a0.jW[@Yc~1;O'%d);PGǣn;kF6B{vzmz5 e*zf'cKRG;lyO2F.uȍNY.0,GW6l޸Bk'^`V ,k"oOjf&7-F}l3m4mYzj@n,Pu{v_&H10:n$2d%$lWVo~} ^7#TLP.&ƕt$Pn_ySA9z'c:ɽsgjϳK=5ou5K.6qXt;)]lۤ>EL{y+;ϽA k'77^pm68ðTЊWIv)K.DH|/i!Ƌ]iە 2n=mZyӻ`[ ^!S?8# 7+1Q6?q1w.|z`?xh:̇llv?BA|B0B@A# $<L)ɉ)¼* l@@* L"4 Tݳ@c>M?Kw8A$d t|IPAVJ|+DLJ|ANvԆI9 7ؾ+k[$I%A:Wlǂbt?BTʻLD8d|h |6J< , |E~|GREqHA#ĂHņ?(E+0ԶZԹK=E6OB/rFnlTI OǍ0`ːupG5`.`xI tPԈvxJyJJtv+:ʣhAʁl,Kʧ<L.s?\) Ի";4D.sI4r?\tm(J4q^DxDG)D~JhGʄ0xy`\MQGޔ|l{Oux£4AT|І?@,2=A^?§4STLMlTQ|4MqѐFb$mi8XSÞK!C5R>TPBXś3pL`,. C[ebUUeX')L+:lOM' W/9UbYsٔ֘Yuƅ>QWast SEZ[ȜW&N׬eW[EeZzZƜ4رEY=ۼ\ATE=ᶊ%eqe"jpZ-RU(U5U>5JYIٰ\`Bt$^́$^BP?<A/O+'nY-PZ .DLJ~VhvMz3We.0VA ]PA׌SE k2&kM|ARdI\ cNYߡk !(%,g~?Tn.mdRnXI#*dNn켡g%>oV=,jof8\#oImdϺOkk,)׳hgF&TΙFVw gep%NL@@#q?#2bq;:rEj*Qʖ /6p$ ϣ '# Yr:Bk݁rC _&OZhwVǚWW1s5gR e:8 :uhe̿B??{IVWНVp0so>ÓC3z|e_v yݱwqDAaw'#1vu77Hqڹ^|J #&ؠ~)TCl=5XM/ mk hL .W^՟uERZ%!OU]yiTj9cf-v7^9b\֔fc Fb/暌SRY f{+FR;rnP4^G$њcE?i-tQi'Ӂ^d^CwZ}^Y* Q4US( ZrҴOqar6֧/Y)0x7y)_:Tib!KӐM ZCf$Q櫷߂%s H;3'ۘgڹnBEṞC4D4۹E}6jmTu  DGŠZ8"M`~*L]*"4*rS%+x6yrm5-θ1)}cM878mT iFȭc]gTO wX%Rdx%xI3YyN 4qXꎗ}Lᇶkgw۽㟿}N%dG1"=Tr!(Xq73,@nQQ2΀+MSw$ |GQZ4g&/f>&j{%gQ0XwNa˂.Sh`Wqo{3YC oMH[hU˪$×IPqNcn45s"! iȴz„ !gb7)%xNy -Q,JZ.|I+'*Cs;ⱍt_pinjÖJѯ\&3ȣc $K;[ d+N .Z6me,i2KX~P&Ǥe U=ϵ GS/: $iЃ"HnCTdLd=RNY BvɑmT,\[?1(KTh]RNΘtV=hFrBzh ;e6"8s5g;88g9B0f4"H͍vP̉8ѷ 3p`6aNtU(2& lLLJRm3IQ>UtfԂ>5Nl7"避죒L^tH8 R6H9ޖѡp*=\+{0*/fBQo(Djr՟a=]ꞈ$v3u,yl[їCRO6xP+(Nqzl+ͦrn\se%zXU᫪X.lo}sθa{y|Zejg=8ӛ o=-W)M,(=es" [r\E)ln爕%]v;XjAV¿K@]d^@#^cS(#*7Erۂn9 ﱧyNei⿫X׹;=vu%ЍJeMM<{oZoz.[^;ko.9MT&-jr+9^J}`̑M9KԠMR Z_ ,L =^aqMR`؍}ؽᛦ$`i_exύޞ ń1 F=I rbIW|LG$6sVV M;Pd+ eeAmf0n!)$Hy)RirRcQ8۵kI$dPL|'xPb ,POn%WX6>,>$_4E"caZEĹ!P ba6 &B罊xV"ڒ,-}1R)Ҋ_J-Wjr,͛YHhX#ɖSi٤ENۖd~ϾjKj܊21$Eę4q%K*$FfO]~m1bR.n.J-L/BT r,v Rj[+6),BPt , >X!ދĤ Cz&UmI-FM4Ů z ~`pA6oZn*\ekFb$ŘfV#hG,T‰𿰢 /(G)ߧ+F)V+vWɢQUY0$^V~^jZ95pJAoC:Rloci>b0זdCx"in/>&c"zHGnLDj}$7 d}8|ha@r@ҖmUF/ ~skWs_u$.._++q)وiw2c ( FFlD;LdroDILRJ2E 93 JV;+SDGK#AI(9Q%Y%S* P\eمh03hGs1GsIiba6`#Ө\lLvm 7#sz\JVBF)LxYG e<2lĿy:N`D "{#t3R/7o&Xx|׷-ٝo禜*Vzx TKy00'lP**g V =S"?6uA°~w5[s Rxol7}_n҉<#@!"h#|M7=Ai]Ù~M!R>Gy. =hHԯ q]eu 젫۪J[ ܮ #^=|&ݾ;a$hn{.b0Ci3&G9XN{)a͈[߶E=Y rW罍PZKWvM[ko.rooI?o `ǰ$^Kd"sFǁ E/~Q#J# Im{TM5>0j̈́^2W5| 5lk .B#|qS|I8n+ߜl(I٬K)`B*fl )2ZtZxTf|\+E08ȃ̏8QdyXG",ΤHM*Z}'!AY锥p &4vk4ՙ$Z 5^r6g+8:"W$hcs Wf@c'= OiMrס |/b=g`[?MUj>9 &eyE\{"6ob4U-E@I]gX eTXGA*X0VmaKYfUqLTVP1a`Ko ѕ/<]i|f7|wv>7.yC vle8ߪjs7^ y~լWus 9N+Q`N` UXvule |@'MYK[k;^2;=ZZleg;"{GJlOJ28qoջ#1$s?aSr_6g?{׌w*RFgUx]b[ε7\";tF*oWG1ߜ o4c@|D^/1"p+hJBo: 9z On-!ĬTXprϒڌ]NR0FȭHr/#_:b.<~4.׶͈+!퀼H$vRfi I` ; JBp/.ˮ~=@. -.!(\rn ?7 z.3#CDg#Gf 17ˇp$-NP:Q CQ$ӂD,I[`1=BzjQ Hw1 jpN /aQ2-1 2#q'NRr#2. eI"9'wD?X>h ܴ&r {R]~rKc$("o(}!$#7"*$O !*5 %1R,/s#dFH%Ars3Y4[ *fDl t>v3 >..\R/5mh)Rn7$j2%'&2+1S;CS+ ,x<"?"ME(?./#Gv'q $7g(-2+8߮0RN&+11:012C?ϸ8@JD!E2<E@RLI>P61LcBL?1bF1b3^ӫ@ *-n$0sHdA-4;3T; efh("?K"EDFN0cG&o2>+T>m!5"GI?DF/TtHeA#9P}:'QN#K;SBXNDSK|BM4+v#ErOU]4O3@RC)+# I+4M3Y;135 YdWpW‚Ҳ[MTyWR#CSjz 3gjmrW4@9,X=RXk05)$#^11p$VaBZb# )eGXUu6`m.ٵZr.V!O@׬!1 HFa a%Y!fYI0;1QbR.vR26HcܒNa/d WSiu}L3eV6=`i$*ff!`a4g֓h@'(g뤑^"˨ #2e46_7b$UIm0maY5s5wX1nC 7jCH.idDdU^#PL/_SqŖ$wRos-WJ+2umuRDWyI jtvbcuVyA"gxU0!u)AWB$x+Qt~=fX:eDV6ljzK1Z n]#Ȏ{mw/fk$sUQw;w%#:ws1wn~5G@ B,g b z3tV b[Œev"JX%b,rXxHpb $`nE+t=v^6zWp_7=ew ͌9l?bx$X3I3b~Cvb4ASBDDf>6,(ظL,X 4sKb?Ӵ:s8XdN3Tn,n7- 518lfEOcՔ1ңcڌՖ6kK@s`5hAXE8Td,sںbDfTIlCP"ԙbG l21 =.S/C v=yKNzW]$Bayx_|o|9}Wxod+'4;ID̢Ed,έAdB,ZPECBvbD|gEdb -Bb8&bnsRY㝱EEp!qpi牨̉m o2er P1GY9WS$>!T'%WrVc{n-VZbu($yn#HOXTE -ycɚൕ:z@k3xת)x1}w3V9-čGC@F:OfP)6ufv8SY.Ϣe2"TQyF$/czg؟=*r0"u ڋKrAe\,oKW,ÎohbX,D}Džm;eK\[\ &i[D"+#qp/\han_sF﹋*{C2/h%0V,3@%>B8*9&5Ty.UP'TÈ-`,5[d59ܾU}oo*͗$º-^"F3+ڻ-g1$]W.3-m3=̏CIٝ=]O"%MC}1@Ae9g>ސDeF+R!.G>_W^[gVE^owel yfeGpLu:EMDSJ^ >VDm^[;,ɢS3h~IIh;/1BC%{J10!×}( 0Aʟ k`E?rCѿҼnU )*\ȰÇ#JHŋ3jQb=228'eg:ʜIM +;φ Q]H*]ʴFPJ:D64PE]39Kٳh3ւa1fڷp9椸g܌Y4z߿R<*ЏS#Lv5Xl˘3k1=&^+:4ۄdl^}ĺ7۸Bv;rȓ;aRHiس{1bŮ:,YQ˟$dOv8xYu^^ pqVhaf2Gt,dJ,օߥlHw$H )HTb%c].XI4g4wZr&>"r*Tbcadcuc|ɔ~fCkfPohZsVK[神a.j)\2T(n5ত6ըTeCJV }z[E*2Uqٞj j=$ p aQ~k 9Ҋ"0:H gUD梉ksV2I%@op>|J,@q $l2f|7j0“x1{l8qΖ۱@W*Dq8OL4-KE0SG2OC?unG{MAo>FMXB[5A;ܸt_ Y}'Hޙxj ;~1^c&9=pB >ueN4L4UNcǰ);+e;ϸwCmg_97tk_^IYrՍb/q2q>o1y#`_TɌp0@_O`NAS5pzYv>(La8Ÿ0j{`&XBZP-lnv@%0>!B(<ѐ"  CP[L@=#Iġ5ĕ=TQ"?(!D[o(vd_Uۈ8ĊH7,Ϛ#mȾ|ÓxA$̇A1<2 B(8@8<@s|G; :܄/N?\B1\qKs ґAևdd$q҄$5 W&dU6)J ,CqvA9!i~# yu#AVMe$+~LЁ")XhG0WIIft=(B9s 4HIiԣtgJi"K';WSWV.oGJ Kj *Iy| utL)\ 2u7[kC*!YݣR2/9kY&8cS( lm2?Lxx)M\#%:_L. J.6_cؽEQ5`08Ê#o!j 'CyRMg%YDDdЮ8> 9yaט[fas7.9W[3`g^ gw,W6@~>XG irT%+=R2+ujYIKԮΥ$ia_~ZʅrCOqn)ʚLX=)j֣'kjem]hH==pnS6x&Aklۇƾ_μ3bqZX]GɕMi>V[_KWjKUf \lN˿BQɭ(sgZē_")Ue1etc-G4B*IcN/6Ci/*"d6i$s<=%?Ȝ*8 4IsGX,.؁MpD\5i3LQw|l'1ivr)߆MuYJO3N0=~* j% Q?q.*iڸYQ}DV_f UɠAiD3/5YDebU`p/]EUTdTrIB9Sh6WCW_^cZqp(5r(<q^{]6N9SקSS*7š E*G4j{ceIJJ*-zn@87êz^dѫH 95ȚW94ଘ?!:gןz)CA#**&LydQS44j)* nJ;k"a$0hӰ7יʝ{&C ̐3+l"beiYif,۲ 񎀹~jKzm>QH!̐8(:[$DjiS๥$[O[Z]ԡY$jhPQ} |KqSDRe 6@^jkNjZƨ\ R_:0CZ^UIB2 `Az³J1-(=: [(xWgKS\.eO@l1 1Ra7h$dCK YW\ʗqc;!*IB+;S/U_Ĕ* k{ 1b$$k';[G&([9t]{ aanNwbx',>k׺kھNƄIA9:<>{5GJ=|11gӻDY-KH * U9ƭp"dg.ƵNkTHkŎg;XknMƅW|ZfvNkti ɈYWtWK$S|U|pAh<;8o$$`J4n)$voSnĬ KflVp[':˫!F˴ӑ^v7)%gIa[X mݪIʼnra;}١>9L\yq/oNJ$x#+\x",ˎܡى܋lli]O#aqx'x Q%%rX{}ͩmqlBѲfVO4 ck&VR!SIH=ww=~3{ɭ?&ۢpyA'$& "*?,pԞ]_r#Ϯв-`r mq#s(o'eg#=Pm{}y]1띠5aa&oZ?}#=%p;"%lO?/)^!x`9]d:O=mx}k^(^7|? ] `o;H[<Ĭg?ua&o&׼OyUyV=7ǚq\ĘQFtRH%MDR%-Q;d?-{Դy&GL0iH?=3D 4>UTUDUV\AVXeQ NLF"ϟ0.GPſy{޵7ŽA"\qwnx>mˆ1λt# Շ~4”)[페*Z44{0\r9vsխC΃~q`0w8k>@>;Řœ,>L3ZZ+;2q`8 .İ#J­"'8B.C_fjođ6@/{(wz%Ȱ8H rPr>̄$ŐJSp 't* sds IЪۨ|*8RhZl3PA Fm$4QEIR#Լ{ԱiQLh Ҹ:۴TˌSϮ0LD<<+Ƅ LѬpQ]zs82.DTOO?YljWgZAHI43:1Cp=2*4t{݋҅LcE~-=mM_zקܭS8ea?JdV/y C?qQvͪ};]!|Gyבy`M0ne.R! E,;p&q 8AO}`Xt%? g4Q kؑ&X/[ bb/ujM<򽐂軠[$Ŏ.#Ӄn05 Q|7 ֛߄π։ь4")>K"3Qg!E"VKFqd4d"SFA /`b:p*.TdI!${ !H>c/:+I- l &Q %HP|)̩(-3%3qǒ䗟C\CcJvf8UL6~ VR89OzQ6 ?:m'IпMN4I8`fЧB4mhHԤ\2Ԡu(l uXgkzяZE2п.BI XCgn\! WB?Bz9G3u1T(5*̫>؃XSE1}2FgVǩ;0׿J.`J&F4&N [#NNJLtџ,ꬮZk+:sTjB8.54Rj~F5@YUQORdĎ18Pk|]\y 9jT*D-nצd51O%{QjM&5%mmI]zUG(#\B[fwXE򉴚v5N@PƍM%N1P晴JleЌ@єqZp` - J9MM%닭l8aㇿWVм%sƜ铨z-˴^9h=H U_IglJh?Y 39F`-%-mYA4'Bq1K+ ̜֦Arv&#|"!`we[i?K.`anKhȍn]]4eoѯcfO#^fi ,OܣO;2̍%nqY$W$Wihm;# ?iof|#G9*s2:Q ~čSTY+.LLTgӣBY̪E/.| o:M٨fmNyF;w)u_f9h¾bXXFSgYe 5ٹ\ǒF+qgsRsψtÙ{z/oy6gVuKմ,؍c^" 3qǑsިA$YѤp'X~qkvh?(\qQѸd /9[;>C9ֳ i.{11o$T)$;!K0's)=!X@n1bA;=(@ | 8HR.XHɂ3YE1,>`jRN)C#J҈ٷ"D &c'탚@0:&) ?SĒ@)͛m1H{qLXrpXRL)5s&Aa[j+0TZ0c?\=@Ïs7!p@AiFFdFQىZ`TlFA?ľ%(|f\ :̉F!ϳa 3ut*G\d[Fj|GH9Bz77h‹xB}\}Hԑ̉ZHjl zIJ}G`9F1DeȋTgIEj$hxG<ȑ<$9%tdL-D ȥܜ$$XFmlJ"u2AetJhʳEl^IT@G\bhɤ0R˘LǓKoCTزs'|$ Œ8=y=&$=2Ȥ̪H\tcH'tBм̾LDDɴMdBM C$K|M(L\L$M,N؄H4=TNH#@T$N48Kf"OTa΢,z@/_DF]< P̹ FazOD ܤP+:PrΠT;9jN Щ  dMѨOPMQQQPMI[8tKHQ#M5F4!JݕTRH,%&={+*PR4=O, 34#e;-/='F!):9;SXC>Ր7ݸq$BUT< J%Ik0 ;MTLLT6 UQ&eQaNT3TV݈UU9PR<զUUb|U\6A`uZE?8iuռKg=3VdVkՕ G߄ԌRLM4q%WEloֿVxUuCdBL >`ߌQ(h[6`a  Q`au~HaF9a` q ` >aZ)_'(S16f)89:;<=>c}豧&~}:R;,d1HER$Cև{ȗKӐxGFA&%ڍdEٰZ9pFSXN䓰yBF1(eOeh_^!걈fYfdb>w擀ꌰijXkx.>Ȳ6XzN. & ghK&fj5 h6dDls>Pl6lՊͮfe!,F22;&2  K N/4& N0% D. 9N.M@86TSW>K.1+곴U2, J.n VcAA t0C $4PaË#"#,(Zх$1c-;&͇3o:̩s Ϟ~M4TڒiJ$ 4(URe^hף_]:i٧gI:PUڶ޶u0ܪYk5:~7Խ"^6E8m,qȌ gzyg熐=o:kiŦ&yYhaG쓶Рm[}2ožkޚ8i㦑V9ã}ؓS~{wyxї=yO?~y柀^6Yhz}W!1j B#RX'b+ء185x9= -X$G$K iOrTXNb&eWNiXv%^IfYh9@KigJrI|v)E* j} 袌 s靔Vz)ZiIjJK$"ꥡP*z褰Z"+Z@"C [m&gn[@ ~.VT@r T í;[ײ@P@φ@ @ d\c  Ùo"Y'3rm/CX<Zm39EÙɏɰpݠ\L VW5A@yuO |SpݖZ}@M%pnܲKʃܷ˅Ü=8GG8э+]9ӗ 9~ޠ3+^:;~:#:[;k^;{鹛;뿳>Ƿ|:;/Soc;ߟ~/'_㟽ۇλh8?epࢂ |>D?τ-ְ+ 8C=qG,aOpl CQPh.Ab}hE/ЍOdF5QdF<:iDB"ѐJD$: r##8*~1b$Mz2\d!EyHR&ҔDe#1JJҒo|&AFY2#-hZґ'ƒ( l` $3&93oML%D!,(5d22Mm4d3d..dMdaClMl-db1i,da dd!da0id1iU|=tBkMmCk1d1dJm?uIl4d>ub!db db3da~2d2ddJl3dIk,dLlLmCkKl,dImLmYlLlBkKl3dJmCkշPJkik R1dIlKm%ddBdKkUUdIk<<PkMld;;խMAdd]Ud W^()ajإijTԷPOjd+k|Sl?hdVdLma-dda+l|@ov ҶPծM,,PjYk"Ls=xЗuqv?a1}647{@!Tw!17P ,!MbjFbLםHl 5xHjE(dE wdw1|.࢑0%g=vJCU6J)j2iYн|}K x JP)P*fԢ,fIl&)Fe)QVZAIOq+d+@bAV`:kЪk,N4-KiRƱuQUkreZf[lܺ*Kno_&o ݺ0]G0RƠ;i:rjRv B$н?}sZ0VC5ۜ?s+{CumCwF3dqI[\5WRWgmcgL[jSvjs,wClMS}y4%8= ZEE6> Wnc~{M/B/A-vDu0eɰH_qKuA;n3+ƞC}>)_2Ғcb+1ϺZM]z/;ĽkiPwFSy {Lgn lo %~}(qҢa2=N.!6bn5i@6=|1+ -(9HK{KB&,,)q @0!`V2%!B q7H k?(f`7rdb/+vMTJ(F#6Tj\Ax(H"ZGGQpZM 9""-:#C^ ggG,`j{#'fIDxc)&QTX Y@)*!{)Rept9d.B2vDD(44M,)f^R"K9&s2zM2&,)fI U.>TFw!84K9ėSVL(D\nH#lCrE$?JE]̀zk y(C>:'r*.D iiP 3JQ[s6O1Nr:S ULͤijECDԖ첇UE*Bjd |[5-QN2Cf4_zdUӦ9߀X'[OWq5aOlꭍ}<j%^&P"U,C9mcPX+Æ! ͤTW ? o3Y̨ugj夲th/N׃\;z֑mkT]^?i\I+|[R -hvQd`si72P՚wcڮ`|{7Uxp{1bP;aoLlY-@ĭq#c_` yI6͚hAwĄ:k`#MB-xF8n'z6ʐ$,*"a.#Bc3SOQJ*sό!/XɂVܕܒ"T'%CDcNHDb9ckeY`ŘQjǪvKRWu ]-꙰l%4b]`?9׈&0aZCkT{aBT!';|b9##8+ F@y1z?ZZFTz)GOJ&EZVJ &L"&p_T7Iƥ9kbx?D'3 IB {SJq%I(Uj { zy:a v?'Dz1 I YBvZʕsɞ j|."Qʐ  Jig|~ZIEA'E@)uɫ~SáOA'ZVժW5ʠât^:jvʪXí tڤɁV031Q%Bl:‰Z Q,԰ZJZ9< PZDR㬂J%_2DZA$S-) :*id9fbIa" .Ҳ]!/:h?y+8˨xsJ#{>~Y8*nx1K6$Fw,T:>[ʮh˪e[.kjO[:G2dhu>WlsPˣ$zz(Z{~;#G<墺CIEΚk1ۤkۍ.6&%GB_<%*٦BY;^T Wh0!$,(絼etk+~:{Ӕ_CB6º65 .E!AnuWkxR SU|Xi= *+`ѿ(WE-ԣQ6'¸Ä aFY,%EiuQG +PܻG۔!\U  0\CA9{'⿐9J< 2 ̾hq"V<r:I<";0 ,'BȬcW̻!A@;/TL=k4HƎ/b,o{V.b2U[< 15w\D,A´/vʓ'cʢVŊ˪R0!*+ ;+A9ƜA:OЧ͟*<|a,\[D; HQ|15=|ܩ-Ht~ ZoDw piL( ҲR-QG#ҷI%J 펾K lL:{L- =[r{ɝLL; `Յʠ()H""\Í$iN]TbA:9oY, λn=5*u ٩3y`i{-3A؆M=ّQ٠=Lפ}ieڨ3ڬڰ=Aڶ}ۤۺ ڼ۩7=YSm3ȝܐ -0PPН=/DCP PxS޽BM-"}mB@A"-,Aa]^>Q !>1>p .2p2@n@A"4 `^AQXlC~Qn:N.v6 S^6.BG!u a<^ 0!NqRg@Py.(W~ߑ.@}~F^( ai^n>n 魾'N,9 ᪮^?겎Kkn㵞 00ݙ^@wUȮ9>-8~ AQ~َk<~~X^A^~aҎA?<fAvmc*_Q-O3!F/./<1TM~!eAL?2d_?o:7-aOGKyAr5_MÂOI.~E~n,1_Dp~aO_i.`?謏Q?do AfLnOʏ Ax޿._IA DPB >QD% $h#((Ǝ-cI \3fDxr`J=}4ǐ#I ] $8"TQS.e^P¨4RV,ЮLePXj6&dPaX}>L;AT# T`-z\Tܘv#ԁX_Νź|7,Fv WKʕ*Rgڵ@aD/~$ڲ9B] ZV4ը|1Wi~0 i#=wv~#ēgm#` A d1Ȱ?K.*tcĿH#7P Q(R# 7 o!.4DZ| ۬ Cv1ĀΣ DBG+NH4'Ӓ%G'mIJ I ($d)/)  ($$1NE;B4ɰ2§l?@ÇA 9բ=5L쨾bR@єS*Po.YbV$\UIW$VN mh=7qeO}iThy-XƼ dEFWoQHWI\ftO.|wc|6fӝ$Uեn)XHC'd.S__7\s X~%ڗT?A"Y1xbWЬ-c Id9Nۆ|pdfA#];jOK➆hbk2fVJ-d9B"ZFintn :ήZzbO<"ezmr,?QhWĢ)Ή{>;K/_jl/=Yimʺ!:>젂?{Ze'/޽6 …*u7qgp|Y}9߽$ zTo_!}'A9%!x]7ρj==}g 2GO^. DB /;!E,C_K 3ڰ64`I<!! 65LdqͅbgB+LT=,1㲘,QO"Y2Cp cWD;s̞Էq5S"pbܤ1P"H#'ђO1 #EЋK :2Zxtd^J%ϓ%EH[dirYV.aTbRq<&]:{!RY^,CM `&jIΉ̓,i2tNDd^HD5>EgPv"AKlϗ|ܧ'CSD#rH6:$]+O@ -))&*rb6̛>;)E4ҔuKuQ4SPQDԨ:hE;Cr $ W9;ԃkI"ЃNQ9&ZW׃]EJW |bk[W)ͩNGTɲt $1wYժENI-&fZVA6-eHXPrEjOՒ5͑-lRc'$g"c\vf)\FO,Dz[2EltN&MP&= ;WY+#ۻ^]S?@zW[#lyYU`Z!=t{6M(i+2Zo:_ÅYmmq) Xۊ8 8h` z<^ȗc9b8DݰYFHG0yD a[NW˜<qKyYFsl%nf-B&:Sjs9pN>kpFd2ֺ}DPڤǒoV/ c\_uscF05[kXZxbW^SwIJKW @O}S7׺.kXNowtYI_+uFyº*^(E-Rm:Vvg| G#B]tؖ\A.*%.Dh×+/? \x8^_&hԅr{=):C&?vxz{5;ί^;3ޖ'8Au3~JWEo ޖ@"6>:½s훺@{@=# K>ڳDB9?8?@u>-¿v[>a[((#*A ,@ 3j"!; \6Bs#3CeY1DCU|D/l+D?3#6=kä{ 47tk=ߪ]DD#AHsX\LT>bd>AE])l,@2tΣj +#IF B`$5{Rl'f DWt8FxGԾײ! P}.Ad;ȅE; t>#< LGH^dE}jEHX8YCP4oƪRHFl<=9wܵTFP HcEI_fBqD3 JC2:ģ;\u$Aôa.r ST|II$ĤH8CTsʑ[l|?pǴFqKAJN LA\G`L˔jiJ,6LA O;2$J{qJL϶;N-O_) M_NZĘ 6ijKѷΠϑOڈ u UFD -KҬ/\ʁXPbM AŹѦMt'%HpMPRL+LPd;}9KÕ,ӼŏDDS6u3ȸ1%N0lO|dI&T eTR,3Q|&u1 LlьNVKӑsJ+TNU e!PR90J$Y%V,e2]օT"մ$H7σQ>RUTWDL+$W8גQuUlOWLt={]QTlKխrbm ձpMg trL=_UUm^MQ_cXe= Τ%&^[q-(`FL3"u[ٽ^dJwB:SP' 0_+EሐО __ˍU'$ >a,`n(轍%Q0K__NcFf}(c ۰(_a?2>v_ dc"F-"`&cbCݍIEQ8=VC>}&I @ D>a|同NW^)ePaAS "AcP!2 0LF 7# Z֮A1eXHLd:cQ4:^^NrJ\)cζ50eSa4<{ xe nS.un35 R*I8u`X+=G\5&.}b8c>:ffYi؟!_"icйEb!w3`Y㕎#͌KhWR]q&6iwG. [aBgQ.k3f뀮Rjу+tk(f6koVO`ʶl"k}濐~:mHm(smiזٶmm 6nxZVj.v̽niMnGnnȮG6VVofvo6oop&wG S/wp p*3 mJЂ p  @L@VqGpqbq'h 'oq  qNo#*$!G诔rzr'q&wr?SBr%qq1WZ2/s;+Gs7?'Gh'"Prs69/sC?tOr't!XH.Gs0oqMt=Ps,PuEsKOOL_uY:u+Bm]utG @uWm`Obd'5mgrK'Fgjmr/wXv,uvghwEanK|u{PDv!?u~ogo7sOwTgyW7v{ xX x1y.lxZyf%w+xunwx;yFy z&y*JnOyjٞpyxgy_ >qJV{B$ox_kro?nNgt{U{Rus{ozqnħVz9/oיoo6}\zi/guG}''˿tog}# })/~@ yqs7Y~}G ߏzQrz|׿GGߧw7wٿ~os$L` „ 2l!Ĉ'Rh"p"G>@*C;2X<+2e<+2@8A9A2qQfX;D2Q6K @2@2+d=c? UUve>N/4&n@o@`< `<N03V% Sf>TD.an@d=e> e<9e<."e=N.oAbM@8n?c> U~~Q M6(]Kc?SW>}}QbK.H6b1+: d>(^K3 ɈMr{dyVbj҂]x0ڇaff1r$XcOe0d1dLdrWrcgRnc tRf~_E4¦=fd_DcjxJ9dV(! )1F>jn"QXQaP^G@q=)FM*ӘJV ZꩨJuZj{kBԪ0a+E} V{D&s̾+u f(ڱi=vnm[l UnBqӲ,e.E/ (ep$<0Ê>lyZk' a1Lcgl)-lC5_5*m =4v2qNPk)Qĵ 1VfEZ'K3ՉvE\[g2 #-[Ɓ0( !eP"ҷ,,ԖNxnj?l_3a B1-I!VApkц:C(VTaxEyϋ q!5:T1E]D#CzcB9*dze\ 0CI\#gG|P0|(FK]1= b!{FHDPa<ڞhKq2rq$?(4'i5"+"FLW2{t)KN-"YCz /RWEb"mR$@?6rOfKJT2!Ri=v3- $ly9&NELjsb,$h&''PVJO,htXrd|"ROS1ɧqPJ\ZTG6hCb4[҉JГf =`u =4ߔ UL|S0h\ FezǜrugRӯ&Ĥ>VZQEcbOӊ͍2u#6#<HuaZ]*C ګOh䥞!)[լrD(~jM)`'4rc!#k#Z{ӥ}`_CJ#B\+VIɈԔ83(Lpe;WD Pbw"eklC򄻎 w%2^Ζ0cKZb!?{osqjW*Ϋ5(8ވdx/L>ת)L-C"J,U z k/ɻոp/~/j;.+[[LݯF{S(~u㈈, gu,`Ŏ*DfaWKakV6ƻ3CM876h1rL( _>(qU"ߦh90sEE$6b~ɟf"XSO:#5IWhn!wӉvWJ6-;SzFlE اghZcXN]L}jJp b(.C8 j&{F|ko%,MO^eـ9~}։ַA|bՎ6ں I\YPRy֪Znxk{GlbrD8DMsX>1Oo>aiG",o9~餳g]/o#Sz3 13:K1"(_){)y$/A/]$Ȫ xڇL_ۏs'8JC>j?fZ5_kH3"K}Ȫ2DpL_+Ωaվpz=W5Ng)Y h{wgHv}B`g{}8)l{}')*wy[vy'()W Q}xzAw@|%nwgwg ~%8|Wqw hMDXW'Y*|ӶmBN'{ ;h[aNW,AST/׃XHOAfVNfALYgli$,(8&ȑpGbxhd| Xz|XbP؆5AXo VFez)ِ(a9b(I?*y/)s?zP6aL|?|9DyTΘ7Iǝ\%9t?&Is :[I i&Yږ9iѓ2&/Ywީ]yC )Yi'fF)9pQBa&%@[3Z:vn4JɢIyag7ju!E/BABx`IY*ra!')x"^Z7Х4xOr* ZxAzt {J՘ǹ2}zCKrih") zjʊ#:y!Jwc/oWBhڗ d |ʂqywzqz"*IN!WZwJ*guW骔ՊΊ+PjO嫪K.ixzzc:m _Z|Ȳ򙪪DI8QݪN"3OհԣSjcaT*H):ש3kN1$Jc; m1?[ {k(OO{G?ິk iM+ dXk:I,DcaYa"*:Q: "[Ae= x"Ln4ZpC{4W?[a"u *0ˈGcZWa:)P{~:W!g/XKV[>${#+kU !U R@Z";As뼼"DkĽ0b;P]ˡxvԼFK6i.Kqf!!i{w;rMY6Vq4{ 9 9qhTC˻@Q \6Q#j킾xY+ǻ@f\JY:q \eKp4( u{EOL(Qx 0ד/@ڦU ْת;5=~ Pm 1-ߖ=ym;`ܻ1.=< P6 1}-}S2xPڑcdr׉P.1#؋M&L,>,!脾 #߇B~֗~|~ٛU0~z]FdPۡn$Enm34A~N7^&pF^~Ӿ8/޻.떽>mqm.o>+!}>c后;^~K~}þ?KN/l*?#8)l.x;N A QF30b _P,hr4]_Wi|?a@o[o_/{P dސAJ ZVo/Gڲwo׶޹/خ>e}ܰM/ؕ?Ep>a@DPB xBnpx!D pQ\\HQ`SmwZ脞p` 4j]1Ԛ+e|a}@\-\1WoJU v4^uAϮ^t~[7_ڰ-\Y{Tϸҋ3yOJ{(0B+J@NA"D7ʋ+( kQ.Jc-hL1HѾrd-ƛ^|Nr ý2Kј )1&qa.PڱGRKK93L4<dzx0SjNEI'B;m“"7i&FX33;pQSqzaR1&iFK*bӁą- U Tai 4Ť+.Dp6+ah cNXm*'v(" Qn%1ũъ.i*ܔ|%z>|%Uh2`C`Y.#Gum\'ڊ"}aJe%UX|pen=WH+ gwA7_} Yb/{ՙ "묍neb!)^蓱ԖͦՏ.W䑽yԣ )y 8[8ު qŖ\N\;ʶ#ek;,>#kÒ$3ٵn&x?ȇʍRwbahΡ|t!g|;}h7ӷzg"]t`aMfF.] FMv 24BnH">2^RE*[čTtiHU6Dt͚HF^R>W̜5S!}Lqz"ͶŲ`- _ K`-d6øv^<La mZin";I&D1c"3a p.(aiP lQTӚLX bJOjnydAGBNͦiy?d6jQ^,YHYQ1P}DZ,9j;oҐv#'%зN\Cʛpڀ[=*Z'褥,jV +Ah41߹SB^pM0;sܔ#x>r[:E?!Pfϯh;k/7;==c?).zR9K>HbcӿP3EK{Ucb$d {y),?,=*ǡ> ¾KC‘?Ä7 @l,DzDSB:d?P(lD$,Aë?Pۺ5dÃpE3A h@y@X*ЫE„<>EBA@; !\[DI DNġL5#,CTr#|hzĺFL |HA"lGrǎ0ʌGx%al>AիJ@CGz)Cp5F KJiFdJqtJʺoƃPHɩCK |=JkKOLJIpL4\LDKI6 LKxGÄGuKaѝԻC;FtX=v &uf)[VyZb0⚵$D9dz hኮ !ᅻMdEmhxn{vP? 9fid>6*i@N啱cخiqp꧆Q~2*jHnNj9(έSkaAvkEi뷖k!빶kkk6~>Vl,vlENǖiɶllnLme 6FԞfv^ؖæ&6^Vcn*4l8n k@P 6oFn~BovNo XpVpf(Gp6pp WF ''o.oo% /qG.qNOp>w!RЉqyo"l#?rlm r_r +?rr'E2 /Xs6,r&8p-w슇qx.xkWԆrD6wyyx/OsOzz3y_v,񳇐{{8W{{hy`/ /vrwwGgs o|7qwƷ Gr| |7$sz1|O.awȧ}uoSG{}ߏXGx'zwo淏yg~ϯ~~{'l |/~suway8u,h0dx!Ĉ=H@)|A"Ȑ"G,i$ʔ*WL-'fY̜:wH0chcF =m)Ԩ?”(6m+ذa6RkƎ5v*-ܸrOux+R)/`uD߶3ntوxknT2,!4խТGCprҥInٴA|]Ӯv֊תwt˾ 8򹃩ݛrҥ.(lGǓ9Xon=%q˯o _} ]\*[ :ZJZZXjXz(W8{x_!bS*"O.8cK2x#J6H:cD>9$~%FF$& K2O7RYWb[إ'c顙gj٦o頜s*X♧{韟Z(F"䡋ר*)R:ZYr)Ye*qZ+z٫},;ud BhRK!JZe߂ۘ.Vftۗ[[K"ާ^pTH20i CܓT9aqs9z\2c$<+ۯ33,J: 22 +2 ."  : 곴3  ;&z% @A4 Bl@,P D>  !,22U~TV,,n J5~ 6OQ '' IP P~Im ygdn QQx 6fU5Te++S,,SPd--m n y tx tTH ғ} IH ߛHn P| }xI}CTm mm} y| n Hy mmиVmCmCCePm PtTttCUmC| ~|ߛCmCUUUоXmx OO)PP(x ғCm m H˶V]a ]x dH`CC\B4GҴHJ𴿿`}~mC\~ =/~Cߛ~ tߛHtBB!atebbZꈈDaKϸV}bHôVJcZғηVtߗLCC[\D³VAA"H*\ȰÇ#JHŋ3jȱǏ CIɓ\ɲ˗0cʜIfKU^"-@ JѣH\ʴӧPJJիXjʵׯ k"/2E"˶۷pKݻx˷߿/Kٝj +^̸R#KL˘3k ұg L鱜S^ͺװc{>nͻ N. 'Nسkqӫ_Ͼx˟o,}'g& VF(VhfbAᇾi($hOx*'4h8(#Q,V&` >H&TGccR6X:dLv`ٖ6AYBC2fhtix^EfMfueI Jhy&袌6ў49ԛXZi:觠**$iP`Ik*ch:稴j*ө@jzha&,zīM.)¦qR˪f,LD)*Vb:k}}R3J@c'Y.a,O%K$轰  1Wl_tpK D$#(,u SX18.+RpBE) E˨L7]+*ܒӜt[jpNwvB,Kljeh-t(6+% p'uH}un Q0_Y39Wn)go騧nGQ@~NN>^\ƺQyf6 4|G/^Tꪜ7Dvϗ=觯]uׄb'?KViP$x 琗ϴ g3 Z$`P̏0}Z*U WBh(ш'Cİ!U@ "A^hk+ԅCPb&aLH*^4Y`85a)0|ĊhLc8-"(Fmt0>2=5qq%o*=яA/-#uȶ |$GIJQ&a iȤ$d C)R(;JdIe+m󃳩* C2i1]vQ]t%i_Fs7#2nz]d i8$giLG2¹#^oR:'I)#ς4T I{vҞt%)ͨ{FituNdGѨJW3C1)ә.'D KwS$qt"-9KuKOTGQ>mR7T@/Ԯz5qPsն@iadH|p5=are ^zbi\`zFlӲ+\:V0p)JJZV;ViԠ U N\MN8yUBZK,ͭnt6)ibZ!Mr7䥡HĽ1~%[rB.q+Ķ֕5UmlǶx 3{rIS][?gk~ Խ ^<6@K"-E; [x+΄(2}}P=g*(N1U)  kEܘbش*αOK~x(>ơc,;N=&ơ]̸xXβEt9e*Ovɐ\j.ZNxqQ`όvH^,.brg,h波|ʱʤt~MLԼW^|J>X"ke„WS/[ZAJgV wSjӄ.L:QՅᵲ/LIBuuy[d _JR:e#ifI%M6]Jvya&V \J4wmm,lXs Hϛ(wmlA^/ H'W\~і=n*I, ߸ wKoct[+WoXK1:OzWDG7kQyF;=$p Bcv_ᡛ=. 3>m6pYiMK`.&&!b={^."^ L7=[b|"oIEIB_,߽HD%ďKJկ~G#L %=Bb,;O?{p_腺]DvҨA$ǏwnvW+B~'>rEoaxE&f!H}mXgBf}K0(.>/ (~ԧ013ȗu/؃ѣA ~d耛Â-JG}GQ׀Fx^Z:TOF78kr[xA2}bH\%xHuut8IMA#|HG7uXr#@W5(6=RX@Yh5Dvv&$ynasS8M#@k|`Xym8x(aA3퓇Ϸك83؋'>HS~XUx1y&vb"f}،803Z08@V^э0֓(yȊW-юNMxw=7(y5=b=SaA=xhwy,ce׈DQ(q(i+GFQCqf69*3.v@;؁xF(37s8wG9y:2I9wIbA`YFa;H^i@Waٖt:иه@5a@dnٗ^xfIhSᗌ$!iLuNHؘy$ipYu[ɕ{!i#Mi(?Y'8k YyygF9"85sݷIЙ+噟yS)ٝ 8u:I w i6U9뙟rV@<*ɛDX(j| w ĈCj~ !6Z6iZᘙ5$zC9c:,!6ࡂ8)x8hYǣLZbc @ڑ5EjiDMڥ3ڒ*JN)3z:nzPbjI9 8I-q~JPbBjrP2:vgʃ0)3!ى} ;,s%bz5JTWeiAک3oeRy rG3&j₥#tu!Ҋ,c\Z*z6 *Z2hGY mJN6!Z1Ю護ڭ6mj/#(\bᮿJurX{x1C ;Ⱥj{&/0ñ묗Z|:({sq0 }?V![/8{Zq077*RsjH[Xq0qɴO&kbbZ[H>kc)-:86=+`0ڴ'*cͲ@rrƵ]3klK%-g-ۭk۬J"-+/c;Li۸9*t[S+R[ ڛ2 QWÔ j۹K ;F6J}{(Rm%JݻaQ*3wP7;G6 |˺. |R LlZͻ "k0qػR-V s/'#1,<'mۺL+r<R+|/60P +A <*Rz/̹ >^L[3~+# 5{9">Ưie~ v[r?ø[h i:lx\$7/=O,Ń\{(3|qʦ <ʯʪ˫ʴ,|˺˹˕2XRW;څ0 ^;~t4Yʫʲl˸<;ͮ|L˵ ˽(/! .'.}1Ƥ,,"VMkLBBڌ`&=!?"L'-]A|d$|'LlM0/"Em栩kH+ȵMm d^sj׆莳.aܭ*$NƦ>1զ~b6A Sٺ=սYz2D >ڷCQM%׭M`L`ۧA^O,rOL,gƁİ]M~Z~2]ϗ[o1.͎瘞Q/όC]/BJ#V_nzP0gaځ J=˺n.>7~*.|&v3~봎4NOH5=o177SC ˿>vҋ^8ɷ})_M_5oont^1` $h@B>QD-^ĘQF=~RH%MDRJ-]S̑lɁTPEI E h' UkN"PuX]XUZdiW\uśW^}XFO٢|*%SA:rѮjװM3&Zj֭][lڵmt'ON/6ŔOEB]O\]μM@Knvݽ^xlzZgZ` ձRtE +<D0AdA-S@.3*AI,BWdE_1FWC1 2C**P"L2Gf2J)J+O* #B'G~ۣ:L5lK9i*"υ94PAK|!k,2+ H|ΧF*!|POE3F%TS4UUWeuU{ 8,>+6U+/4V(TR!gUdZkjž\pCFC{6DSA4bYf':5^yl^{l7մpT HR6\|=-UTf|h}8c7昦\ 1`{/Cq\rcMMcBs^M9gw"U1MɃ+Uzsa69ij?kk|Un:7܏LRn;o+ҧNh= m`Z?x5'r/Ůb@f"? s_=vb_,O]7Mjx+=ygyrᱞd= Noq&7s|GŢЈ&},0MKCm_K8@^Jz)pةV>mҩNbֲ6B0k` Uxʀ,d@ڂE=Ԋp.Ȝi0; VY2D&61v phTzH/4O%DŒ!C@*B5~!dc)_[vC1jـF,1rPa#h&B%*񐏄B7)/*骡x@`!I,҈B)5be,ez<1 "8 BYl˸X:Uʗ,bJU򃍜29MV&@/Ph;MFɠ90"3ԔKV'vj$ !:9ϽY1/'>nz ȧS+DhB*GH> G}Big|ϋ-BE:R/; _J"ɢCbJ 8 IIuS=!c4v(RqZȞ6թOڀHBDKRӛnK%T:V~ g3Y խoMZVftyBӝod%h0@ 4r0~-ٸn~Kq J\4y8-jRZ AL^kL/jNĠ` P|jb ыFيvdgM:ɰ܎,W:7ӚvW(* 5w;;QF]oYKtέoP3,{Xu7A9³`jN@.XYՍm6<}"0/k9"QKm@H[64Hsϼr-,Vv̥<8;7gU#o]cMgwP 0m{Vp-eh@Ѿwp( :lszP2{]z{%(宦lڏ fV(^~kl מPvlXe.mQm. dnnBnliϖ&ol qnff >,f(m\6(mƐo0nm6p8iN noio> / Rxi^~m Gi6b Q N7)ofp3 Oq!oWrqoŰq><^'^-/qC,"? %5_f rqХqw^,`=qr/>1 iVs Fwvr8t@.s+JGrn +0G/gsBljS^,-P97Iqp _~3G?ԹX?'uN]tiV OavlG)sC?HtE8dr>!om[WGmdslCw?񁂳wO58GVvg^;?Bo ^gm_u :YBuoVuT :o^~?zWL %pwioV0[y6>&릿WES&TϾcsx$yewgkWOy'?Xd8ky7^ֵ@!p?K?iC6gso/y ȟ7ȹd7yOyX|ǟ]ЯLv{ݕ|[yٗ,OCocno(' OqG~r~ܟ w Mw,xj [xWnjGׯs_ iW{,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"%(id*W @1ZҬi&pIL|LIdJ5s.EYUQ+0-9+ذbǒ-k,ڴjײm-ܸrҭ밥ӫIθοWro^@ d(?ܠBP^r3ТG.m4ԪC@Pg L['9!Cԡ{]Q+89ҧSn:ڡ\XM_uL({_[+x? 8 "_/4yנbA }?IQŤqas8"%x")x~=#N߅yaTTS!&PQ5Ey$I*$#xk(،ST8Xc;d?e#e4y&i&myѓWi_Uҹ|Uou!czYj曉*(:(wEwVe&)ӄfd@հN|";rÛ"}tlS$v@-gH0"Ө5d6Qb47a_Ͼ֞^&c")ARЍ+Ph,bK0"$&3I&Q HQc WPNY&c)YqZLƼQi|\M%HTB&3he2bM^KY "x`6Rh%)qVC1^r&O$)̓ds,' ˩}3QIa2Mnt$+YyvӈŪI?#*щ*-TzHM+J e äfmHѕ=^s\2ШJYL&D]*ԡ:0]I∳@5b}gnRԭr90^4=1Cwj+ӪW*׹*:iQ7)i^zHT%)U)]łĮe^3ֈ4IZJ,hIPJ`Wk6- `X -nsъ'W\*jr}Rm0 ٓX'}.tؓO i o$=/W{#wZVTH=֧U+=\U/f)ǝnOݑv7/#1cI`tY=*[UqkHcĦ>NЀ2d);X)SANiTóë=}[U>3'‘RYd$o2L4['MfIDĪp3#5 jQBN>l=iHg]U.G4S6JKfQ>  REվu(]] y0с]>Y -Q:!_ȗNֳ`g>7Umr+֛EhawX=ӭ}Glyܝ_|J51Rvle8]2IzTۧ}4C.7۷%xII3 4;6?tlG T|V[f=͓#'*>/&u/^7Pӳp<[ {2.W^䔑[!0D}%W2Strޅx1BOUYX']ya~` 6/Ni!+b&RxE4( 5% ` /Ң¼9)> a`)c!N#I>>Y%2O1Q8=ƏG#Dd!?c&6rI aŎSa૕I=DRd;^UdSdN6%:_ZSc+@SeINE`̑P&7\AXGΆXTTJ%RUXEC& R&% "] $daTl"P dHe$bv&ll^ep,#MFOk*>g&9#q`8^bFeIlfBBO`:$m&gľ\c]aJ7&IĦ%r*wFn $mEVfJ珸ghe~'}WwxOPfeZEfHvd}(Dh!czo(`Uknͅ|vscx~X_"Np&䊲wvgXsf"djg(o|ʨ2.*@__=_MjF(nq`i})BhEtK"ƀv֗)]UX،_`n,JPgdh"vGT*B1V*XVh%Z 1yP<%S*W*fABOx(@*@jkITqN.eƫDDH)陮į踖#Q~r&>ݙTTd"x"fÞ+BZɬ2,R"Ž8elwubvFM&(l씀,Gٰ+m,2v 5);jyҝIހtkѲIx U罾i)%`@՘D"|)m(`mn Ym(מThp)FxEf.-"ʮ,y&nrߑ;mhF]nЮA>TBV@nIxt*lJ,(nI~.QF\/vf-¿2Box\@\/ׅ/RzBp.lv^66qo`[[Iq7n5#o3kr3s7q'sro6\7vuet6xwqgw#_hvXs77q7 G5 4u{||1pkh~~vcx/x&9xu*p w^ig>xG4{7zg8 ӷ}7:a2G3fǸW8_縹R8.93y_#9w,K\Syxck;y 858yV@y#yY˹]r9ϸ6grc5ӆur3SyWv8WfO0sO_:N3ôۄ tDM>:Izt{kz]Hhx?_49W'E98wOC=#9㺵cB;_so{;{zW77;N{Cx$z{{:v7Vg&|bD9;B5g47<ƓrCsvw38{ɣ|ɷ4rz<3{2ǼΏo*i211BG#}(}4#@J {Kzouw}1ǓԛS,ڳ=ຽ.o6`,9p5r?G%~8{C>H~._>gr|[JOƽSlt~('y0߉췲smv|d?l(׽#(ot??s2Րg?o" G=_ݓ#tG?#rO~W]?@P‡&TaC x8bE1fԸcG@9dI'QTeK/aƔ9fM7qԹgO?:hQG&UiS+vX0u S BՊ0V_;6SgѦUm[oƕ;n]w@!E T) ,HcW‡'VocǏ!GhG~yE7N|yѧW}PKXN0O} P J N!p) 1PC.⭪O)PYladj"cEQc RH M4vt($o'R)M! &Z/R1,3{ :#BLK|SNЬ;J`q9AUCMT\$4PI)5mK1TM-/D*4QSQMU$5!/]UUi[qIֆ`׉r VaWQMbmgcT"A,hVm٫WkVq-6oZsmwBWy{(yWXw݁NXa| 6Xم!Xbmv8܉1XZ+׍AYdE;X֑QNY1K6ՕaYheIgY lPyZgJNZo3hBZ+si@Zj9[챕k0N[u2l.َ[Urm&[{ǽ\QyLw^!r%<9<5oIG+]=uX]vr]=qmS߁Ǖޏ QoE_穯/-^|O_}?O9TtOt4? t`@=t%8! n`A0^!HB' aüЅ q80#9wC&E4bL8eMDI,'NbRE-2Xd.zQ!a4#HF0LF9j9XG2⑏ԣH4C.~T"#!>G1$yhIMn5'I KߝtXWru -q9:[.0. Ka>1W!{SM‘5צA8EBpn6hB8Hs 7y5j.[qN@ @`(Bq -(C$}5ք( 5IyуT @8҄l6|SNF)N!0e)LRBPz4 ilSKc URur(JjV4eũVWU5@eQE5J[*ըYWȩT}:GR:S@j2JR8h`ÆEjUβө gNcmmjK Ud-ʞyWdq1f/͕rGnNյu]nw^񎗼5yћ^m t7>}_z0Hjv`/ v—x1a o HY%6QbHbϘ5[Td!ٺ9ߋ_c"/Mv2?$NO򕱜eFS]f1y\nyUmv,?/ko8oΓshAX2l_A/эngѕ iIJEG(iQњN_P d|;0aAC!^`IMޫelaۈt,k_oö\lN[N^6mh[KӮ^nuYȸ C|޽pE-ry^v;jw  wq'xR >qoljq8Q-wasϜ5qs=ρtE7St/MwӡuOUS(qŠb1cÎA <(rdĒEd˄a4)J'Mɳ'| D @ZѥI.tөQNZթ z:5X_6vJ.ܱ pTãz ]0o` @ E HPx'*|0T!,|*22U,,T~J6''~ gIQ I5IPfQSUH*\ȰÇ#JHŋ3jȱǏI2ȓ(S\ɲ˗0cʜI͛8sɳ'Ò$} JѣH*]ʴӧPa5իXjʵׯ`g KٳhӪ]˶mԑnʝKݻx߿ L*ˆ+^̸‡KL˘qF̹ϠC?,ӨSJzװc˞}5۸sޝ6 7ȓ+_.8УKN9سk'n}.OϾdßOϿ?("`&|.j`Vhp^a (eh(GU,"b%(4nc8Q7@bDidN=L4dPF)DINi9V\e`bidpftޜvtx 蠄&h&ڡ6g>*餓EJ饘Bdvz*[jmꪬVjԫjksުakѰ&,.6! JKZjz K /Khڋv o Lf]*V: MJLFZ?j8z /L(! L ڌ M)9 IMYi5 )M-15 9M=ۍAE I NMQ+U;YKN][asw^+Dz :>:멷 zNUN;^7z|'?<#/_^|X//vQn+ؽn|X<60|V;{a gwI!XA01M̝h%ެ 7EQFܡ~f"~ƉFu-?4bь_5CA>#<hH(\" Z狤M`Mzr1'GI NVt,Yڒ.R]0a+1`м"jBa6Wln A7I΍H`LgHЩvFĊ"]HCztp&=Rҽw{)L&ә6]Nsztl>ׂ*ԭW;*Rԥ>N]TzRuhVϲ՝q7*Xg&ֱf]Zzudn}*׍ѵ+^'׽>~]`{v`=}1z,d%ɾ]f3{rv\B+m:-jQulcvmrnٶ3-py%_q[2\}+]VQ.v1w펪mv 9S=oƫ^ĥz/|NU~o,~p#0F[# S`0,a5q 0&nS 5K.~qV,cŸQ1+FM>VgC>r0c2u$)VFY<-sdX2ȼ,feC{ì漲|}3*9 v.,=y~c-Д=4/Ekю,# ISzi3rӬ5P?-jْԵE5ά꼵ħ~oeM5VӺonqs}\^3־\maCD6 م6ϔ-UϾxM3jsqߎrý^r\ Ѓn2F?dt0y:#HV/rֱU:"f ~.n\.нm;ע~? _WX?47V$oS>+U2y0<"7_ SϳB=e]A=t'N/|ؾF>|02y>rGo s?%I/9?7gMӿ:󿿵'"$xqwA h ؀k€HXqȁ ( Hhǂ'Gg맃ǃ'GgևӧDŽ'Gggrf @e bcȆ`"p&\x{uH{w({yz{z}zhz8zzyyxyHy(yxxxxxHxxwwwXw(wvvvhv8vvuuuhu8uuttxtHttsɸsˈsXs(srrըr׈rXr(rqqqhq8qqppxpXp(pooooXo8oonnnin In n mmmymYm)m mlll!il#9l%l'k)k+k-yk/Ik1)k3j5j7j9j;Yj s%PA%CY[rHy%K9cO Q)%=)jU jWiYi[yi]Ii_iahchehgYhi)hkgmgogqigs9gu gwfyf{f}Yf)feeeie9e eddydIddcccYc)cbbbib9b baayaIaa```Y`)`__ř_i_9_ _^ϩ^y^I^^]]ۉ]Y])]\\\i\9\ \[[y[I[[ZZZYZ)ZYYYjY :Y Y XXzXJXXWWWZW*W!V#V%V'jV):V+jL@aScAASY 4chѢģAJ23z07NjSzGCB.6zX"<:MPC_ڣ&A;Jevmjʤliu*ptkZajHjAKWŨTQN%KEHeEB?ũ<96%3E0e-*'Ū$ed:;"zNW֥:ZzȚ:YЬѬ:* ժʭzz*:ٺZ޺zjJ抯誮ʯZ  1Ѱ ˰+a{ 1ڮ&*{ -a q '˯˱벹%˰79 <+!,B\ 22    곴"D8P‚ .( Ŋ/qcƎ;6(2H' ʈ.Iz8ə6sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶;suܥЮ^}kЯ`&lX0čGYp/ Bsk -]Y@A Z@6$ !,922    곴80@4xPC >LQĂ/.hq"G|yq$ɇ&O*L!ˎSdM"#$1$Ɩ7JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LG@\tōLQĂ/.hq"GPF",ir+YtR%Dh(SN8s :&ˁ2 ѦC %CO>%J@L%͖[. NE e됦^*n  N$p@_ k$ ɓJ@Yb@!, 22    BCM$곴H` P@Á:@C% E5.G!E HI)UlibL 2pRAg,&•C6pQC)04ԡj5Vi%a1 J]m =r]&@ aD8`z_">A%'V(b!,22    BCM$곴Hp` (A  0"@"ƌ7r#H"G64yA ((`5;dyf͟* 򄈳f",ZN|j5H4nS8* `#ʷL`1 $p"\ FAWn(ab !, 22    BCM$곴@A \`@!,22    곴P@( "|D+6 r cD#K$H'[!bJ3?6Xxgz0`Ѡ4pD(=PS2-I*Ǫ`ɖ#ֶ@s9n9-B}_ q0a!,$22    곴@ ( #@aÇ%6 E7 h F!rɌ)dYK1e$i&Δ+wƠ3,j4"ҙ<2msZC5Y>s4pAGȶ<9. K'ߔX+ Aބ sD@c%|@Q!,%22    곴@AP@'z PE.$RMd TU:X؀AXRpJ5e. ej [z@0A W@6$ !, 22    &&2GHS 곴++7>?I00<[\f @ 4xPC "QBR4Ɗ ?r( E2|rĖ /Pǁ(<9b0$P 5fåLB5ŪVb­,xEV@>OUۀW6R$TpUE  uH H0@ \, $!,22U~T,,BlББBn Bll~J56OQ P PyBBQBl~ BBm U''llIB56QIlgdx ly fn бlBlelBT Pn --m IIBlBn Im BllBT++HH,,U|BߛBBltllllBBtllSSlll}T PyH x~HUUUUߛHtH~n Ptٓx P|m ߛ| }ߑt| ~ UtGHSBlTUUmߛٴt&&2BmtБ}UCCB~ } B* }t<“̨x C>?I++7tC#} t00<߿ٴtCm B[\f`*\ȰÇ#JH"-jȱǏ CIɓ(S\ɲ˗,3œIB2mɳϟ@ JQ9*UsӧPJJիb݊)ׯ`ÊKْZϪuu۷pʝKdںk˷߿ V/È+^x0cKL娎/ňP#`aӨ]fN]gY˶z &`16}v؝m9ɶ̓> Bu kU݋W9>exqG'uU xYd|)ms 4a e}.\ b!!y'ꗂu\EF eG-Qm jAB٦T0zdg]y}mU bhEfsf՗'Y~v*Rcfɖb݌֡*8M(yr笞 Xp Vy?VhDiQ*Nm~}vW$> }yh)m잶'(gTJўz+0]"$`NeG"V2l5ok )V~H*UTC$ڻVLel1[ta&Jnx,KAl^tv1v *QFE&:ЃR'yTpo>T>)oyv /(1AQٱ#jH8d¨OCJ&D! B&aZP H ='JNo7URN FF9<=HN{ZRHZ;E~{5Jxp1S#TO uzV4IB~VkkgWxgSӢ-H~i0JV@Xvd6 "8ٚ|/L4Q-.Ũ˻q-^jԨqAR6ƶ1ej;ޕ N둱aZR3`a*oC'ZWfM/YߌjRع|!o_5|/IRaTDCP@*aK8EhUr[p-NCH$5Wx[t8@.M d'pBtLaw%f׀װ&ôtcyh"4C hG1'U&=Ѧ,i&u@[lbP0*O/لmh`zuhZѰe{f/dT(v,~E?ݒP8+(Y<:aݒ-$[ -e Ev5blؑȎ"uv*M`<%wӜ..ڟ-I5̦+kyG2m]LwN{wF3҂%HY ;yz~0U5\Ӛf|[wwgyhK[/.mT޻~kdȍ8vCGה>5 aaa 7{iuԧ?z2ܡqHa%ߖl>/,nw@;-xg4z'cÇ)'f6P~?I8>8L"?V0Qw.fnt绳o󏉽ez))F:ja-7$s[Jp 0|x˧gm>Eb8NV"hVgl"q%amw~7F;9bJaT;chn˧8Zqdvou _E8{$_ Xpǀl1c9xk2{5Sy&%HhLAp CTQQ8ֈo8zS&}Ӹa8BXTf}>[8q@p٥bu*Cx![m0~^LO,t@踍փԊSE|x?yw2IsUh8_orm#9ġO B sZb8HHAG`)I,9ffGIS.Q3\AnWB #nؓ."ถȄp9Q ɐgx9Y1Lfb94wTq-gyH%#G{d:ԏHvƙC@)v;QxY_2O9"HJB*y,8Nz3"D/d;|O97r< SjىM($ 1i:6siNQIX"wQ'@Qk)4m94k ? -Jɠ _ڜzbmggp:-ɓ3T6uvy37P@zvK*xNsyܨzHE5P5TZωt6-lf`jzwJ 1ki UȆk!N xړefENb,a 5i"%lI.NF(\ʪ*j}Guٕ楪:=ʝ \hj&p|Rj Z:2,t1ϊ麧 f ٪$Fأ E_㖚 zªq|KdZO-1Z7yEJQ ȯz÷&!j=uJ KL6Z ;Z B*$m2& +AaZؒC)>$$8Q˪ RKxEژA tZ&['f[i,[tᙋ+:sxkyzIqT5*'rٴhf *[[6QF{;=] Prv EkQj|paAAu r;_CCP!#[(c{+">X :>ȋ+qJԫ(;YEۻna+Y1md"9ØۯۤѸ Aô{wr;AwK_T{{N^ - [Dѫ[۬ٿ Al3 ۷e: *0Lv{8,~I{<){qQ%\=.[ɭ/ 7B[;/پa_<fOh/;\+\./})/v/&D (1/>[V?[N6Zzξ(V`7ȃhꆡBn/˗0@?z 娚"4lA׺®+,Ck; 4h?jlDξSJ4$@=c|/?,#1H!$R2 B`{pؚKlѨj&-Ut/-B5 c/4TLjdq)'16+O?! H8pIܱ(*/P<ѢQ:͛K.;NFS9,7UG^|҈dLӃLt 4W]w$JtVVL ';7RUÔU#=QSZG\eSٵ>WyOw8"-Vlk6OEt[G%W0V5<8!Mݸ]^G&{aōBg͒2=qKs8JN4J!l dZ-aTU\Gq[ΌSIEHk(O հ o?:UUu喫|llk>Lm."wVhJMW{크,V=3C;u<::52YUek/Fsf۰3 |,.auj52/ϊ+ĕv sYxͮ]OPsS-y. Pn=Ѐ^tpT8/("ltbߐ|7e1ؐ7.0k5 m@v@60B0 0 !@, *0We -eAM|W} ǹ9S]nЌgLՀ0@12>P5.ȡ+r|!1c=b&1A$.!2bhHm&Cc(EٕF  6*  #|4z爐$WHNZC WE !x $gIJ.F9MjBA*YWhj*Wb:&CIb'1i$?}2jԠ)Sȑ2t' tBBo1{/Ӣ7J"h9|zSp fHjԦ7M(( ݌h/ӴXT',\R=XIwiSE-fE/?*F̐gEBd[z"sf[$_V)6'QmbeԆ2-h6t(b\,g9+2_މɼO7gOaHBֶuY槜VRl"yvT&94 D%aa)cvB(GQujSZ\Ўg!nLbQ6 ݙi7!n" |19-ZgQTI[fd W ,mxͮd+`+ỳ%DXŬs2 ;#WA_TG̚ſ:g[` ã13êklX sdCؓ rc$yJV$ɢf4g gc,cRy+D8-F+u-vsgrVcw-Kǒ(V9N- ="DE3jIfj, ;g9m#IX4I j dщ3ܐ |tvHiknNYKnn@ Qbu=-tW(1NMAэW1Sk²fm_5ɽ;jލ+ʶL][Wsܰl )iU>])ykX3ϟeaxd>QP.#3hH7Ch ʥ.K̉b?:yNF'NpE̤c;$;uVވuv^wzvw˶Gg`zߢ5-GgvgwPĭpII3!л O27>ҙ@yėp}'|{ûӾS+mjЗ):rQxGY# pžg?/ocxyٯ"^ m2+>3;@B';A!>+ (1M>Y.䃾*5.󎩰(ٓ@m  "<6IM>S%rt@T)*(A0@c@44!AX lΛ@7)tA*dAc>.5-A C98 [QF 6|@,:'9zAôCdCC 4Oc*BCGEۀĊ:?9 D50ɑFc, "k4`$ DhFK?K@D-lO1,{ 9ƊElǸZۼ߫DV,^L/DfD{TG"/LwH|ȭFnFK*+1*E,Ġ>bi`D\ E"ҪG r J4O!>꟔C-.Lǟ˝DɴE$@*pGaJT0 ˿zɠHsK>"C $L n " S92Bk$N튓usL|֌yϸLD9OQM EҬN%mtQ5̵@LKH⬙P ck,JDQADH*V+βpNO܈X[vY^ ukenYٕd`H?V7d?CuBf.gufY捸mm_c`O` Pfb=T~y|[ vZc~V9]+_vW^ 9V&4 7Vzce&{aiH`b~EB>hhѨ\ivh<.kX wNklg$gufک^bk"G٦b^n~lʺ`z}lxvWKmĠ'c 3'r[6MHa6OOl pQl!GΝm=NnMFiE\R.b $ :U2o5H,&qNq N!6rԺ.,&'r~e}^jrގ鱘i s^N~$51w7wn~krmN,t 2IXQ%rEPrU?qyuI0>jԬ c@>t.AۯT޹Df bZ:0EtB=oNr_Qofdv쿠bV?qKBsBkݙvjkvBg.횮p?o]eRO% a^xWIVoܹwqs}nkmh;`&vPljޏP/LtDc4/p lr3? vB6xD[ Y\mmJvq7ٹx&vKٓPk*UwKOڌalCGxy" r0O{W [eOozyyAy*y{l`L(b\O87>ra6{|V}Mƨ~g~fNde- tۡ|v ~,h „ 2\€ hh"ƌr F)"Lq`G CjL!$dǛ: \`Ń#˟ Uv JphQ4Xa}x(;w,ɔc?8(KrYP+UV9g+&*$pZIɧiI[$cf+՞ҸI`4e*d9{/BYЕ& J;mBdg.C!FfL0?SP´@~:L.A 0-rgi"A \(ȱzc+ĨFutᷕnF7--= n6%5ax2֕IpMS=TDIfZy+7 VE$S7Vz**6;^.ig-nc6d(^Њm#=GV_|ZDcUvҏ;<., ێ5ҟ/ff&0{ûzH]T`W9|E;髯,p_| B^B=xoKRRG0"(޵@7@΂ͧ~Ny=v7ݸ< X 5yVBp>Ҳ%.s]2d(QfAӭ#$R[Hk^/^ ki h9ұ3q097X+Dg82&-h[T2:ߴ}dhjj{%taH:e!% UiMLԖ"bM')E$K8dUػIz 9m'*2}dXI~2,XJCxS2*WdtY/GGzҘ@ >j.E3Mo6ău׻Ո6qۑf |f+K;]NTIY[2 lP߫}4ǁu\UN%WYՆuwQԹy~awmpnr]u_JLNG]hU$Nl`u z'ɠUiazGrc{#}y})NOD.GQGBo䔇qMpgפ&һ{vߦ: 4>ڿwަ^x{ϏZoY> z_}~u]yJމ޴GhJmI!^eiN^ہXM  R Y A> CD5]ؙ䑠 ᠩvB a)R )D!~_a `px[*aK(z\ r \ "`1| !>ay!@!ApJ,eb#!\ +* a*'^"(H"b(ZHXUaU_AAʢN, "\!5`*}Ɉ'"W}c00J2n)$a"B,_>b?>-?6$%cZ!&$D`Ac;i]q="A``A,G" Htc,JW#;ЬDK:D~IE NT"ydDO"Rg_!x$NGJ{@dP*$Lb%XG֤,٣4F=D!76m_YiyZdRRbSVS։$M^~_N%W*IM]XޖAL6b6&7XЇ%qfqVn299NH`vhߝAceKIV]ZbR%xjlqGibib&kklDHcnrf[VAH&p2cz2#pwlQ'~izҠs.ɭ}^jtV'FQ mPޜx'LLm\'PhZ(ɉ"^`ij~&IGD`ЧOwFexVEN` I(8A*%W._.t">ΑBA,ՏnL |.9@" h\>[} T)%GHj~8*DhRi2Δ'Bf,)&(y)FiԔFi"(yd`iiVy^iei&S"B)"F~@: /\)=8MYXebf a& `# R^1jA}VlŰ+1!kRdpX<+yj(jZ"D~iWj*r"l)FajGRdeNkbfgBlF,Y j^+[)HBetB\nf)^n,uadl*z"6 dU,Zު +)Vlo W.Ԑ5zjlBjB-&DQW)!.EV&ޖ%rfmſnȉ؎mFaŭҾkӚ捶 a!44".,qF(`/A^v\'|n RJϡ)AD(N6Q.)n,`).{. /uooȆӎnQ* |7hbogBjV`Nr/>.X,iȈ>+˞r)-d*!.Oj}R:̊R[N5Ǚpb!&)&g2'g(G(iZYtf$Ж,Y1۲\)@D@b2Bn.:n+].'*,q)o1)9 Vʈal;3% h Ss5ǫ: @r1ADޠsJ '6e^r0?/ sHۗf~"O -)2An^3tF It@\=oBXrE2j)EQGWo8j w!@>M?jKK4.''2MMgC3P@@܊3_X -S/^Rfٳ 4Ö&sJ#0 `j\S*+rX6^$Z޺[2grW{E]uF:5CzDG4ĪNDKv2.j/v5a*pp@O]v󊾳B/bg6phJJu)l0*6W0(Y&(A+#o+6p*Fg4g_Q.5S'tóh1Gx, 6eKVwUaw7n\6pz x rg&>}p0@7X}'vF#gL+j:Uu.@,mJ!6s~wU_OS0($4%D˸ѸF8R:*77hv8'wcwwowybs k fowi.7^jS9QTj$v|9u(yD棠jaFL7v0!y p%`Vc@c:w{a8!LF:9Ci {yCf<y}-94Ā:dBxMX3)25,@7d{>a3Gwv Q?gG{o{q^1q}d:Wvø;<֫#;,Dyo☴\:˷?y#̛Gqg(C{gDXH@NtOwC@rYSjh;ד@mqcDmRSA'I2[oA26%-{[;C3K;-]/ 3zƒⷡ1{!=EP|:U'8[S&WHy=qfҖNߘ_js{~#sss{{~M۶CoT@Xv@Epl~}ùofIG@`^~t7kĥOT293?X082H@0@A v(P@!F8q@1B%6(Ȑ'EɈ%YƔ9fM!dH-WYp4X8P%]"IMfպkW_zeagibq +<6lAJ@*3[r+. 5/Ly :;*x`Bf! 6D̚A^M8UL㣧U鰫i_U^  nq(y n+V&Ρ+[W{͋c&c:}5h!̡{$In.4žG *%"^tă le8&X "kltS Q7wLRH@4q0޺fIP|a$3B+Y4ڨJ]j2Ĝ@MKS+Nȑ| KKR\Q&aɒ5]&)Mq,ALde1+ˏl)xqET+Cl2p*'-ĂI+ ]y@3=K=jQ -5:3$D4(D,\Ҥ5mC9҂JBHjWt8J9j[MOKH#Cj/Jڒ(\Mj%2ihR5:iqESjO25,)CQFt9UK_ a KN$1iVڌ.k]L2RɠeV6܏quzdbٝ;k3Y.%:m_}O}RipEM$ѮPՕ&ֶZnj\5vwaUT-/g']ӱ)M(Vm'w5,7DVxk6{\RUks/prp޷*3 ^S"m*I;꒽EXw^!Z a!ǽ IkwUiO`8Is0q!a1#1 íQ|cshG^HM?'Ved{L:tuRTlW2Y m Fv[8GC̱rD KoeH7"gz\ ȕ 4v6:YѐٰimIzŠ- z2?t['F90ԟ*B6!|t4( ,`%o = "BPC+E$"q:e5cEQ+$2_t[!lTS7`fP#tT=CyLRBS_pk0xЁ!:˳=[r-, >!P1 e9;w1wO}.Rl~~b!t]7x}'ATyO)6S䵈-g9g5"C;(ֆ3&Ԇ//bFU@$,kO4Fٹ|yy2\W&CSYmGv@}K8(ҀA/VZ5m9Q%W~)l߫(qavUunک  3D;i:`՜y맧q5 07??(Z 6ZҶڇ*e>vYo?9Xǵqo0 6n:ebb:z(2^¨4#Z8XvZک]bW.E2'-ST;5Tj>zCZ'ǤR)%IZUڮ$kBl_G:!H\zmPxζ[\W]ؼ;;q^iSH6g#</oh篃.;tG"0v'x[9)|PS 8"κan{T]ڀ:Qw^/uwF? ps0rkQ#p0Po sP30.otA3)s7;%ee|'yܬۺ&K1²/GY(#+3w31y7֓w|03<;p }G/ 31=1'O2 SCHw1>=#aXiy"o(sX>%Z] ,\uc" :Ǩ\@9{슋|{[[ϻ &9hExx513$ɝ Y &/C9<{wʣ&ss^s=F<5T]ف6{aWrѡGa\R͔aueQ Fb.w&&K%>E`\)t\r( qH&/R"F*>U5_uh@; !+NOfHPe}9TfSaTrrSQd ViSY[R9d=ahHyݢijZJHbX~aT:*$@B||(ц<)Ey2ڈ@ ^?Qg AwB)Di}(S7,E̝jOR@P0 SU0 X d"Y%x{rU#R~&[QwrZX՚A)l4_qL.֣> (0o4ԫ: P*4 a/oo ԴuTKHñ2Bt}%+rݺs~gYL|Bx^<Nt,2 V!MR;1OK5 4p*6E(W}O+  ʮ7%u;/y Qў޾A z^{Kl]OZ@b)eOƛ[͂/y{yho}A!,>z2N§냦QC8Ǿt;ٯ^{]Usf:kk[zr9dX$Q8 3σ^Ahsl]P[Y[D@25E}2rhhC=m!{*,~C_t2J-{\~#85Ё}K .6"A˂{ 52 Oу hE1+[143;r;e m{eT򍓝T"`[љa`4{Fȵ%\ Fp!lU.ӲD @e'pK! tD)}p49P42ZAL DE/ʠt0]φ OX3"R,O~ztK:CQL9(X)-vIS+)M-Q{Зq tĒ @$9JVJJitq+=mFO*TIV ׸"n5>{$·~M}W5;fH.COo@bȍقdP:Κ5Ck"" :Ko|1)5g/hc^,i`De)+;W\}N! we<Ĭ?h|@F'qOGrPSQ.U>}z]4'BH%NX] yRIv\;퓯}b~;kUggzgUC}}wx%u|5~7Jwp @MS|;! Sdc@eWq"eJ X[ 3jl( E:2FsӝhWazK?||뼎%B3}OŒkK-md:G[i =\պܥc0R)q`ꫮ j*:6q"$-&n<- 4뫓3-;U؞뤖ָ=v6ԜrMtʡݪ Z VG̕VX/`ˊʉ&ìuS. @uv z=M5͛m2ӀzZ^>9cɓMك4,,Q"qHڡ46-SnRDKm#nw+sO]c偃yQIhQ,ԙ!wA-` ;5]8&Ǯ=Ý=OA)^V+FL2Ē i. +Z*V(=AMWmrw~J̝-cxk@\a\9n現=~@o}I+P^w!ykܮAC`A.Q.釨>;6rׂ 쓊[4Z^+2A4Q%t>C14"[v --^~d/I~>-nL !exWr_Z }dF:O@;|d \Kq'oꡞFa $_,Q$t1fްM5ЖKDU_M/IB;/b/e<1 ɐ&fV__U['y\f[P&~ӓN3*N@\kq_pMAwcۮqٖtIeYY,|˱`/X{ٗ f*8Rtn*~t2d$.dC "P#?$P!ȉ 4|@@ 'C r Z O W2PAcI.e#:1cY*PDV (2,fp`J7dUvjիZ;W\#\xvձ^y0 ADpK4괠ăJ;ETi W 4™6cyrd#15CI.On{tΛ m PHؓy{{c&gOY h.f`*@+O/&k.p 01ht́24㬳 8=cLR9Pr#ӨTңt2Hnnh( 5t KAb@kD'\``tjTQ%4PM=HYZLFs|=h:!`<$dCcORiKr mن"l[nqJ?ɧ9QrsH]ʥfaw_~3L -PFCA8j@`.$@K҂ر+5bG$33 @8|L qefA~:geILӨc<֡jUzT\W!r3Pe3l;AO-#?+Cg?<1NgeWl2<zکZK5iۢ^(k-0;){H̗߅WNOܡt+%H fu &ukTR }ybo~+da Gʋ L,vAg^ZL+G= m HA gq` Qrŝk~q_\E0\pUqx8iGAdfGGjȧ9.H#Gn x]ty>r3QnV6p<{úp?޹:5$#FL FG'~I!+cyG)]J_rRqP$TMqe4YnK!e*y@ՔЍ-t2M, Q@Vh3|P)V 8VXMSq`^4? J,FWB+3 BK(A:Ϥ PNYGz:1@i~@kQhP9LDCEfAơ*Eoe+ɰ*UYIX H B ,M .4 U$[M*Yڴ"Cu< =@ea˵4"\mcluyT`$iʬ LrjiSVRa"!VLj4^]h%o:U1hN}vcb [@Y^6+9_L{4_QBױ(fhM+XeT 2A2/U #ͮa \=Q A3&=ԸnĉTx+^ 'D!ا^%e ~ZWmh{:p8ՠjM4|(oo3$y|X暼 HYt#=sc`䲃=(fo0%?@r-a.,7\Ԓ˥Q4=]OUIhJ;tγ>oj‰d% sP6`箰Kj){Zr[ '9WM(4k(MraO@Kkpw@D7i XAMtO ,,9H|:X "qї3ZuZZ$1mW[S42Q(M^!ScGY4gγ?&(<~,EmO*9q:< Zǯw^^.bzUFsh5ʯSev2ȗp5ofNtF{Mn+8nO*WHCYBh]k[ #5'B5)n=U HB2焇֝&F 9Rf7H~ [j,gFJ5iYu iEf P`*2d0 ?vQT@Ocj@WΚgoĎq<]s[ 9s=}@:^?쁼ȻZhC5ǰ 0%RdAVAx:H/H2)H)Xz +r=9 3UӒ|9CB8ēţ@@?Lçk+!:A,שڊKy ȝJ) @FDXJiD7UY1*"=Q 4 [_4E5D^ghC;7lƪ%[]4?K($B l]T /, @I p ` wTQc Y Pǽ % xq@*FaD80@#c|L4*{F,IF-᫪j4FcBHBaP9R`/<#!J¬1PY)ȃdAR[LHK02I4[Kl˔L?"5"yIL I1l¾EDMPɦhƄIOɑ|Ia]RAJ*$ȑ>9:C9\I4@1L=Cͽ8Sq/HA>9MN>Ø s Ⱦyu>a FQHLK\O|OOdEOOMO=PMP #\ЦrPP PjP P P] bQQ%Q%4EmQ}QP?`BLsx?Qx?EQ#C((ѽR,A̐ PAʝdD..}ʰ$ y“B*t) .P-m@TBuPP Ȧb-&O9TQ| RE3Zl&uBWlXR) LUBUmUWϽ@T|׺OqRGG&]qիx.ll*shc­M<[{WVj M.5Gdp0+llRBf%nJkW{ddD1݁InB]ͼZTLZ!WUJ-g-!UXخrNL-N 9ǁG\o^X x 3ZMڤPQZsZje0ZAZZ@5PڦZ-Z=a$[e1R]۵[k[+}[[?[[[԰ 7\MZ\\}\U]\˽\̵ɕuO}QAi\-]Mdĭ-[Sٕ&mQ۽] ]]-]E^a\^%^O5[ѭ]Y^<QM_p$u_߼u^y__=^_8`z_ֵF0*&8 ` ^ Q` ^]` 8 ഑Flླ^`` a_N>& aPb'$b6`X&b`/[{  ncc5*⥈aa^&v666c: 9` Nb>=>bb bJdS>e%qdH>#6d;bTNDkD?NO& ;e%eaV6b$&b8\n]M]di6fbfrrAFcXfs<Ne f53.\%$ 8҉iWHRSQ>cTgNg'U]e47Z0}ӂ PY)91%Wnz/thTfewRvڲ⊘X?TT4MUK\hOtUj=ff-bZג^+G stYsBP)Ǎː1) >VT)Ż |+VZ6/adHf ~effy/ώ"<>mVYeF VNXYl.D\.ke:xǽ1>ʘ1%G1hDfmMme}GnX!`q&6]lʳ]:[TQ_%{ne g^eNo>7b,aI&w~c^pA>b 68.vg`6n_qM<j/APafWr.qkNq_l!__& G>>eh+g I-\Y.?i(rs1?"r#a"N7ꚩi2BR8)>0m"?7fD#.(/-rA`Og>nJS~ [Gliu%έ6uT_%&woWrS/mljV?jcK-*kiŎUA-nuv!"w*Br:n*?SoY5猱PWHveG_i/|?VZ;T9_UelW^JgWleo|L?<{nJ)ZnIO)ΐ׀L&ql;xgrW>Hw34kRV`BKB*lvr#]"W7Hw۷a`A./b'\jGqG_ŧw܉Wl |{|ŝWqч2gs?[,j0NsEms{vsD!OWloXtte6WCY?/2-~(tH_tANOMW`? N ŗ~Zʰj!@ P ,ń`a%N#Cx!AAQR%K̩s'̜v *t(ѢF"Mt)NB*u*ժV2qB0+ٲfϢMv-ۤ%G6HhS"P` pCH":4Eb0e`A4Â-R}-֮_Î-{`k( N.|83\8wR :s0s Ψ#wړ;-TƛTB0?WX @W`Be{fG)D-!NEPsE@Gdщh!j$%$KA4RMYbWAYRo44^ 'D Wb僕9%*,~}٥w"u l]IEXbu&u_YKe: UG㍟M%alj)[CJZ)T XnUiZ%*E)d 21ګ*:Ea4eTR[C {-j;-vzݢfnܺkj h RSld /@Ϋm%.>kS\ŭ |kܟ.$w})} ,fV}ieq(Z iB&לG UdDǀz]dBKT U4ҳ|vZĸ# Mtj]7k41}f=Ji PP\_J7v3=#wQCS޸嗓USM`}OED-"h~%Pm㞓|NT]7=ꪳPNV+UNKQ1scVNF'ƅew-@ }a&Sҗ-j'_S-iY^h'104lTm, ĩn*3W[t#l 2• ,MzͭBB֭zBE F"i*LgCbk(+a!cVi 1r'E, {&E~1Y@!-ɘ,,f"%kb%IR9y(,3ӢFY k׬󵰍-4}>b%1`=߬ә6a\g8$n}ŴYkE8}6p1yK_D T3Igisy$G5Y!is>r;$v;ЀN*7 R0 4h'#%.p8a<(IeI9 IƔ-T'RQ 䔗p ԇ!hGKj  !{BԴΕh{"},~T8+QZ)"WAHP'8jֻ^SNa0ۊЯD4k.͠i?)b+Hh,0׍Q1+Dі:FJӴllvF=M-oqi KxL2YBu !kJAͿ=(@JR*ˬm-O4^ de/G ъp(31@f}ґ:D {"!aOBc8 DenY>ą2. {"2O@˞Ҍy2f.ɍ_坟sH1,.#CՋb> .ʇ-Rl 'P!9Ĵ(txF)G31"Pf;:XtiŻh*nM|cg;-nK_t1"ujل]hZmk8gu,K}>$Z:1v Z&eR=6¥? .(D|*Wu\8J{]hڔpoKU:\C[xjN}.Um5Daw3|,=UzQ{,cN W{T9)+c9sԱ;W5c݈,o_S mӳnwSgB.C=%Ӑ"}Q# &Q-npR*ڲJݽ E`*$"E9\dVQ+ ͛Y|/d(ZzùLsxW%DiMr"ǘ7qo$s  Mc3ܺi6Y{26oq} Qq#dy[4)Of$FqӟD IKBEKԄUq_Fx )PU m]\ZE,iAt~= `ڎ=>{xu\E୑`=M9 F`Ew4GPWxT%ޅJ_iOp9[w-@Mp `l ݛ̉\SQ'"(Y=ޛ8G)d Pm\L]]R_U%RPؖ ugU#ڐ]2c51#̹5Yc8B e7SU8J R7ƣ9۽c?#t]Q d$cB9= B>AyfGuޡ"Is+ uD޽q~ʒ.VEDNH/ LJEED4Ԣ(F 9Hނb=MW݈ I%ɐ],eXR)PN;jO%R[P앸u_Ą%EhBTMإ`r15!$x#.N#8efOPE=ǟ]jft5`ȋe X_ =NX2n/JeZf'Q%Pe a+waq2݈-JgL %bn"p#!$MbqPp&N!pA ~Z*lgC!^yhZaXa"bX<9PխgY{r(N%PY=\" bʡ)؉T$hxn C章g`#_ M:M iRņL3 )?AKAQip&ŻyCK򣘲Y&c_>`)Xc}jhIijm]$ͨ}CB)'Yj~K |VҒ.=&%:cI3 Wªd썐2QZiaH9@$TҜZ fQT nhJn)њ"ʪiRA+J^*Rd+k\!+"yFP)HQVٞkJ%H捋`.."NXji֫ l iiZj m  łj '+ʘ,,QϮ HBH+-#5EBk"E$AtYDtb@!"D$q2 4&rހYFĭC~.M*حZ%U2,W F6ƑǾx߭Jej"h_iӜҢ)jcZ^0nv.`Xgj& k&_pD=kf(xޔXj0dўvcޝI_>G'w6*NF\G:nfo`4,[ o8vJ(qH-!IzDYw |'^i`iUj%K+VF"4"Jy \5/i>\&-^qqN҂)`ȹlqGȶoêWѦ^kc !@ r۩qZ"rR`:L]U ܈Li:WKBWt,wD~tX EsB!Юx52b&4r$+$gqGT>m0#%]*.D@%,WWIXi(> .ږ ǮN-L$߉.)zj::nbVb²,/3Zk7;gYNy^ hp`* "tZdg/ !G)A830<ۧDCczo}JSp"|DusGG@wIiRaBgJ"g {;I ϳCτ+. M9z&Q#R#uVoBX FeᥨM +&.h\g1Y;Yj7IcOs@vewdۍZfk %XQshCc5a2i hhvl##th;lviflowrn6pl2cwjwl37lvwsS782e@?wusvotsx_7d7ywݹwzx7VN|#}.QJ{fZWvi38^zQK7Z?cxkمWs8w8n_8WsCo'78淉 xCp 4rm 8mt$cӶ/9R$w G76e3_9{#w9n 𲜓 ʖg6!9ynj "r珛:˚w':ybj08Wl๿V:gĆzzN:oe϶'-:,zl{ i\̯#{*{kz ?9K;qZ0;|[HFJl{y:{BȻqk$6Z̪; k<;G·žlgB |L.@{ğ_{ɛɣ|ʫʳ|˻{o<\ S"xA<$ 0v:<,5dBO}K#S׼B(\X}x(xہ7} " gk<߯}7FE ~ =>6~GAg~?Eͻ=K 2<}oN8>N?U$S߯G-4aB6tbD1!9vh@f=EM*Cf̼]|em0Ea} H s\&|(%h:E#)ܒ.̭$ (34\6Q]Ȥ7<3*`16B =ՠO' ٳhbM kp :ӯq%[ =@ÈUM64!Pb_%wf MȩK^Q-eյ؜SOLcpl &X2EDl |8tMν;{8~~{l) O~Ku?U`Yz{f=gJeh '!eHh"A,ʔs$.^x> T1J5#v c@ڷidKi)ge ZWdX7Yv R`])Җ]QK.ED`[^9ښ])((5e>M#ebӟ}fex6*[M | :fjTc:kZ:5Tj$qB|Y&S.1:_T.읶kCFkHNVdA>+ME e ]j@k ٮ.*bX&dM+#x&X$. {[AqJo\aPIV/V ti'lsLy@:\a|!'~1:RfE4EH/n 3cxE7RfL}W-R!ʶj 5fNuh,{6yp]ۀt]φgu͙ };8r~%֢ī{c|em{r/רjMr-Fn{}IkPDha^Bw]"( B01 ֧?*-yJXW<"WX %zMpђ=R;hHjOjk"s\25ASn-&RR'FaMMtMɠ822[g"q)#4(L}R2DCmIHNYL8v.TiPU3 RթucVP|T/Vb.Eu(yW9P(ɠTuYB ǩWs~`kYkeI&C4tH[V͓Y?ZWfvu7ډ@``uӍ>s$~J繶xQfWVB;nCF؞DՙU{Wu@zܨif֣FiHMP Ni5.z{#1k.BM{MЃа"Hf/x<Sy+x5Zj&LzV\bó+* {$!"(0'n c /6*8'ĸHbme<( Ne\XgE<$@P W..3a&ka޳jf.#e^3s=xܰa>gtD\F'e;S[W.g]E02zK'L R ıU'ۺ~k9Mf])=;6^-4\M[zt6We=(؂GMΨmo/7ܒ1pe^{c{Yf"W{ Y3~'ц@v#gc_Ǣ΋"M,pvO6bSNMI\Yq!/{s?m sL:aO>pUyE8Ns (}N ]{J_PAy^jL߳sG6G btA"ԵR# Ov mSg~wl2n$=/j~Gx|opMڌ؎}i!>Ozkn7q5#m'?crG 3w=v9'?qW]y9BO~6}t6t7-yf~nRf{wf;S$j8Q!V{%}T|`!3tB4VGG2X'tWoeKx7SYxwrwI%Q-$rUrE}&VDŽ6Hp|Tt!1XZZu+4teG~)dM؀|u!ņvqq(g{x}]2"(CQwzS(^c~&1XJ5A3wb|l4Ɋ쨘)@3虓i.ђUٗIIQ֙`a)= ,$EzkMi|ybhɛRvٕ+YdaY|]Ydž!h͹l) -  VshkYS)Ias;کOiz+quCSKyitіɞoW[ɕ-֝+wIGz99%ikby6ULPjE)13ÆKdZ!x!`30霦9xBz hxHI:|5Tj8=_2qqƥڡ^FJpZuf:#fWm7YqJ_"֥x789A(QeMI)Y|٨wtǜ:;:5FQ9 ARyE_%k63e@Y)')<_tʏꔘ:ɤ mj3m2Z fCyJ!Q h^O*.lWL5qa#ykO*+:g[z0=) }5É{eJw2 Tc3[lXYbHk[E(ƱG:~3ȖxeVN[r_[Lʢ/Yf0 jn˧S+t0: , FQ /Vˬ9~Z{!xK7;[h ۵Qp"SVAkI {#6T`ykPR0AX'*z{"ʹFV1[jtkXGͻ;:Oʻ["38{.E^nWvI`ܢ-:K  !g믇 >r Ve|1*۰^ _jtԫ;+%3|a” ܯ hĖBZ"cO vTNXD뿝CD4M:e/"` t9ȋ lClE,l˾!Lk Ẉaq|Asuo8ɚ <;vQLȊ?Y,W:k˱/Z4nˢVf)\ϼvq,M漘Q V<)i=kϭ&\S_Ɨl1c܍"= iJ[%l成ݬ\М)E*4&rW||Ш(GϹ9̴3_ `u\up`3i}|;9lF&CV\A+R|?{iOk E_,3du]σ]iuAɡ-O#4Df 3m˅+0QҀWϼv;!o פѷo: DoMЭ!l}PZ|!H)ـSuU`Y{9A'lT["Lt .[!~aU-o?m ܯ!׵}<'%n"=$-k~,G*}<ƫ>}qA2)vErJn P1AHMv9iIP.=m->o$ޘkGq 禲Z}3R[11p9Lt^ N@ljN, xx~h=me?AJցӬ.=dt,,3  qNQnZN+1 Xb^$Vnԉﷆ[Ϛ++ kޗF ^r+`߾e.V _[;V4!ȇ1>X3>46u~$8.GM/]֖ Ɥ憏2l6?5|".OTSE_-pwaq:1eo@|'30AQ>/}oDAJNqRI?W nPZ@}?2A 51@@ LC >Q"-N@@ŋ=&Xr`MDRJ-]SI3%)R_ִ`OBCH)t:Qˢ,mhԎ@j %Vmkc U\uM脜v R/^[ -\۸O"|'0wJr?/mYj֭I3„vgݽ!&Yv7Ӽpaj>{!Ns.v)꾽uF `͝/l-cl" @0B EKj2&,nî."ChDNCc*m9w7.A;EQ&BW;tN@џuJZCWC)N.U_s$S.EcӬr@,)ZXqma+6QrUue(U(@%,VrF]7%}E8a.m vUX]^{}q9+_i)F-B˽ࣔb_fӀd|[L[5x%~E4bt!WQNkMYt:UssR e|h VV5e-Zj"uZk;Z n ]xq86֬9%R5;Q/O8F@]єa]+FWn]hFpQG>aˋu՞ڡXsďβu^xhTGe:Uz59spҭ}M=7>XrCװץEfF,Ȩ>D6I7B0t3<5\#Gm1^lRZEHDDe*8+&$# }It-{ GUCO! 1Ho&nMzD dĪ̘\bH1ޱbnh[iNw'/q\ &Ӡ 9'^Cq8gbGnWĦ>)\ )a$zPn P3q!L=5ϙ d`ڏ|+iP1%4_Com1ͤUB/:!AeU_Qʡ(-kEװh 6\B Vf *Z(̺Tpk*fؖ̾m52ojWR^dtU__5 &@<:IV0 osFK _ J`<˽yGuj]E){e,ZGnŴA՚k~䕜]u<I_|rvp=׏^Wxx*^MK|5ʏ԰RC\\.7RfOT3ןWK?ѝ}g4,q\'l?/N0[X>Fhy,}MC c4 Hc,ؼۛ$ۙs ɪ ˒(7 3`c ޸[신 6`04m 5S?S!w!%;%`@pAoc @A"4BP(zI+⓪@?-mA?C9<@4H =TIC!ܮGD@ Cٌk3A4#B? %-K™ |J*k4osE NSO$BǸR̢qorUdťߢJÚ 4^ƞrya$F88C9\AP DCj6ȘlWkQ  X&t¥ ر*G \eA;Y|=ZrNJXd XkDVGYh_ AɔDș\3|A Lt49ʴFy ?d!۽"Yh՚ q@xJ2H_ţKh"W Jʘ,HrA̐HXKjiGDD |D RaH" q368ˈ'$y7Ȍg|ȑ&h4p².s|=aftO]z&lΓGX%M Hd(\IɯZH9x4вs-Ks̉p</}OBԲ@΁8@{E'#me O!ї%x|PRQ";3MS@ &S}P4eT3M AeɻyR+]95&;*TP=HQOݼ@FmV}Q%`J&e^IeĽSY>YV>d@ɃfJ fd鸾 jijKj~bNUXkcnl @Έv~jnDQ&Vꔶ{6*mKi:: +_>lNCF d.[;lly& nlg*ŮX`͆>f1k~bNkF UcWmnOmVr>n\.o6% mX~voflVemxn^|no ^py ϖ益m6 WdU Hhjc_bn:z/qf- jc hVp X.rm >r&q}Nl`q!gm.rk^@kr dr7/,b ioj>o'l./^ 7sNb$7 ;s 6l)*@n9t l0wpt=WBF:pXN jau@th08]I>\wRٞvUv6tl/vcG PX6G'A^?(nwO*n>'L1~}(tm-pFCz mxd&܌nXf͌x34;C?> ۓѹXxqgٌdyx8MWL:NjdugxvtGOwPrù݁txH.4<{ur^-NtyI: N|/Qo}GT%Bտi*1S5|_}h|K^|ʟr>{P̎}0 џ0jߏf`_ K }Wס}/\~8~Hd B m:e0pmJCXa\y;''/!Q)k/^ZU&Ùв/u: iZ0ƯpTJT|lIz.r,BrJ ZT',&bqBرUN$3gu]Cz-,2染v e7p?{xXӸ+ש5.:n{hԧ^+W_u` lU@0~>W9]Kl_#IKUͻ վ/s=$3]V3$M5񈗼:!I@GCᷚb;pr A/u xp8:CA}6# -@=Oq-, R! Q(P+Kv5-.O" Wbbو4w[$DG;۸d.=F%@xEM#aPv?FiraX!1@v|EqRg?(T$XJ.L&)  'Hь"e]BBy#YV$q/vJfRɓƈ3єE2͵Y|_E"ϵ ,(B'2# }%.Pxyʎ"Fu6QDDFCh4eJɣ <8l[>>Ԙ6h UClhzFK/*i,BH&͙LEWLN/%sW}@[@Qs"(kR!HZz%U7qMUnխET[^}lwօ1e kjEΐ(%ƩWlب̲x";YKU6vSXZa'SzzC^!clck]' o>VQ"" L}s Nf8VwQxWwҌn*@׿͚#!IWq^f`cfyY\QGDCfQBMYaL=K [`uÕ];l}>^!jouԛHfLjXKӅ;xúrc,cOW5c%lqO|f'y 1a"KH>Rml⦭Z]!hAA^ -! "@zD~;`|zF/x ;׽wK)˙vJgG;iTjhR'dIP^o <.#3>bEA0Nbt\A) b+(Fg]-I=Al#m=͝bA(cA1Ed 1YD[;~E홗4Ib :"%}C(:+΅-߹=#Kp@m]C=]" y eGpRvT5eV>@u ĺQDH!uIG9"MKdA!;mVMf8[5Fd Z%Pe)mᨘҁSS!ǡ\,el'zc( X)fb.[F r\e@Adg:GtheHYZ{djjamkDl2h5m -S&8&\A嘡fX$!{I0':sGd8 '6mLYJD"m~y`'ѽHauFڏ'|u%;Zg:eMyڧ;@GddB[eiF2n!Ҩ#B^Ap)Fl(Go"hPXav ~gqY`8BKZ&|(Ne:CaA_UX~ FiMc?A_Ni v"HD\(j&`Pqf:%|Zb(#|@*@@DAH#1=!j݁**#d & |Vu'p6h-٦GMfxЂQՇWAc^tAB:^`>^O"R%>$Vuj!F@≚kivggC4ġ*)*odJD8'z @+ny1z% z!0ޫ.#5AyPƪ鉞^nj(H l"Dj(g=ifТڱk=2k?&2.D2>6jAZ"j߭AXA^l{gf]NwQ~ fܦ.-"+*vi6Nu.{&,VYBiSkeM-mR6ю{QoʔX.h&.\-b(2mjoA`GI/cmpn_z %''_kgxjƞhe'TL N R j\)Fp'j[c~pZDoĔ`%+(^fݭI^=XqޭqAjS_W(mj~PB[o+",ڎ040]UCT0kc r f_A})`))3 2./2 D/m`o#F-l2X"snD(?')rAr+*Df^!N-$.89^q"60w@nq@>sR[C@')e*6U7\6Wqd빒kk;߱F ')BqFR>^&$LKL+)"'2K5c{x3n B\C;4#E|3BcTŜzp1fr%"4`Em`NuRu>~NsUiԱ2#GD'B_Jn[6n^^GX5S\EDzt #v-ֶI6Ahy0>t ڧz0W[pI>[@æ9Kn|F~S~AK6W}A#oU b?d[@(@A&TaC!F8bE1f,@Pиq G*ʈX @7%tgO>- (A搅-&5 ʇH!2X@O9K6tL0^UiYgѦUQc5ڣY+ :Sݑ:L4wXtuUBy Ŧdܘtiӧ!Xa*rj~ZĠDT@unfx vߩ͐3G3R\'Vx`K )"`+ ғ! 8IC'bP&CP{jƃz+.DÉʹ#BX+"Bڌ\Ü|B\1H/@.)Q*(01Ɠnp6Ҹ.s%A @JNCS! ~&4TOr$"s73+`LO4Mn<.GQMǑ,Cݯ7#c(rRU#L:㣵;L: z(V| W?k]h'YYC# õQa:]Vf@e)Bنr|pMW`UUӚݗ-pE"i$s2LTb!wGOw$5s`,tWFV^UeZ ^Las~-(e1Dyc4_7;Z2yoV%etNA0 XƆڬ!R]KjUZz]:k [m%<=|d] \uy6r9R|񎙺 '_=4;ux9L7" F6ou6uXeǙl)WЖ"_Tw6>"G?t\| ȿ|"@@!>(@ IA: , 2B`/ /<NfFaeKvvurfb; hxJK_o䴾xK"$6UHl #d0dE`XF6>b̟ $AT H21,эt# :.8i-_ yLnQ| A&hiAv Ytnş˜ȅD"17pR,H Yfa$$ȁo01r66-Es|OX3 PL4 |ą rg 0XM7MϯR!"~dЅlь˄GCJ j(;+xr 6@Yӛr@H) j FfL[t |(f4 LfčF/(cCTx|_Ke 4s&MH dA$$)LW$lY4rp Axⵞ*k_ɓğUTj%>XѰ*dQgDo,UV$_c|@q4H9&ķ\)ɂLvdZ{B3Deƫ-H3rڛRh~u0f! '@`Kbe N*ԈЄ1Yn)d Nv֫Hg) />a+*Ų^~6HI-a-vv"^mxǺsB&sMAn.dj\1d9SQ)n,+GR]&0cmm猤ִc6C:gI,2 !_^qg}ފo$4QtID A(mmZ>V *whB!Y'?, H~[',9PJ:\L>۵a9pݛ-' ĮSneIԿ#D*O.QwVʸldyQ\f,1Ja>NP/cDy~$~lz6iGXZ,?NXFbO6L֨-FR$fz\.X|OD@g0T|b%JiO)/) * + k>',-y$/<@ i ?I\ ދоoF""ݖOxKhKĀn k "Ĉ 0!j1'/p)p&"oYExi M #V#ne8K*hGLLjH(lb|E.'6K"B=qp&LD,FD mn "^M:VP Q$Hs`K| ?B|LL=P@f 1ӦK/$#( l B Ə??f4BJP!-"%Rk(R-h~&,u +:qG%![cFJF<ΰ&&g'C'}Hxτ2l r$9Q2)CDb)!%Y<2*W'tR+R#' oq,wCXKB(PH*2C^%R"=<-EIx&+bP1Bn13>$*)I3BHJ8˜(^ $hzr.v tӄK^2/+2# :"4$as(͒ uG,bGl23C2m2}b@j.?)k?7NJ di䎌0;6nև0L$ע~2Z63ݲE'DkR.ɮɝ +H983ԧ3"E\6,?(Q0/OCSӉş%)21J '3;'@HOJ̌IHOO#^M4/I's̤tJ/i" <%5Q `4QKizh!3Sr%TL۔ t+!G!l Weq̎M;+/M!5RT-S4ŲD2̼TC5XBEGD1=U"upb,hIN d++ Ѩ8|@ q\oF0Q5]ͿU& CCRFyBDGt[vE`GM1`Q!4Uo€6Nu#Non88Qfs*deQl:1+-YgayQ/Ja2n8J:DG"3'rK&K}x}1B@0U8XEa|sco7ZnHi×)8z/vƜVbb2b8b}bXKgxk> О"6vNQ8+=?XR7Z~ m`x6UNtB#˂boN,oRmjD'7 厩6,b-&kayOv8/ͷ懽=@ȆnoQx돷Ibp9Oٖ#3dP>:؃i8 DWFw<@ tbp)y3)l+i&ZQp0 sY"PbŤ Q=$"Dt(ƒIeKG=ZOzi",mmzBm+v3u IZ[$%:515:S:'r+uڊ䬿0Z.yz@ vzY0c"kn욮m#zZ]ZQ͙v! [w͙zy=!rP*49%"`aͷٙ OZt_[LCk .db&^Xwov âٹ .[• آu]{ay K<{=.v;NbR;% n( ;%:\>:ܾtU_dsP6$PN:.TVX xx ;9R8v. 6y \[ bfI<{kY< SA p I* _/ɘ\Aw4uiiBu)R7#6!}˹\&,KG*1Ë'H"ڎ )H}jT/B/55u؛)Q.a=ک70 @=2{ÙQ<ӼF}[  !z꧂ UoV1z=כk^3Ug6];VżM1=SU/!jYHn]e^( !l5OFļ@<7~/w>i6!W3f>3mS;v PfP_Y>4O$3^UmAҁ^҉^ďQp\~>l1 h bpK$,cveUykĎ59=A?EIMQ?UY]a?eimq?u7U@IpйxÒJf}֧hƉ ^!kǁ%Z]X=}VxB+ 9!kG‡H`C ȀAÉ2XqX Fņ?J1d/f $̑4kڼ3Ν<{ 4СD=4ҥL:} 5ԩTFU ˜p눗d , ]Z3@ J5K oHt8Ō;~ 9ɔ+[A،`,yw=y"#_GFBcA[˴yah+aċ?<̛O-vFӂrvCIkiѡ@Oy;!޹ۿ?XfѐC]vΤ hi Nh`MYeX h-4Bq_*b.c2Hc6ވc:c>dBIdFdJ.dN> eRNIeV^eZne^~ fbIfffjfn grIgvމgzg~ hJhh.h> iNJi^ini~ jJjjj kJkNiڭDRdZYJl +.l&+llRl~+ *;nFn)nIoeHKpP:e1 q.*0>e q30 /65q._mSeqC)D(sV,El] sN3/Pl 7Oo5RAK-oRDtt5ؤ4]Ͷ#BMT\2Ykv~2Mlv 4 E7M(1E{e877:ϑ-MSdʙӔv뺃u={[=;*n|/0#1ߐx74?-2ؾn/t߯/Z}C7Z-7qz+ ^g9hErgzw^8Ip|[ʕ҄~+K8BtOXZvgڡwꛡUh^]4$+t2愻 ЄJ"7g1e<<- t!Ϙ..+$tD 8.K\CԖ w3N|2lHD*WYp6.oMC3r"Zroa$+w5F q _KYՑlgk^ A\ Tt{V&5d)s*]<md5;żl~Pk3T8'9'sTɲ`;/<(N?)62(Fp{ã`B(}Rg =PcR㰴7etx*D * $m)IH͙1nKo&N#JizQ IvH1CmꙀ4jNJBZAW XハV+03dR;G1n5t-LwD*ci]#⌧Z mW*E;(ʛ pl`/<EggգV'cgOu ضh'N*uvǹ+J.q#NC9i ]4]paWj2PfWEzYݤLmTTB=ֺ M݋_yn->u6.\y'Ow)i'z'Bx6.+$fń,IܪDΠ-jP-X3&Jcֈy.b|$oؤMq(\xR%yeɬ].0cʬ}cc,Ҙƽ ]k>Ek[HMWGb1+ }Z*Ox JfH5~Ҍ#j:p\ 63BکݽYU0rJd]5AcGGYM"V̮')S+ǨpIZj[Bd˰V#5mZc)5!k@Z?KboO-se p\ϑp&x"kaB~Qҍǯ@b\ˁ2㔿|2ﶾhs09rssJyG'Q_[/aκԉ;{]ӡUNPWuWE;n<{+t:y +~oK~򔯼/k~?Ћ~/Oԫ~o_~o~ /+oKԯk/Ϗo(Hh x{F. *b'HJx#e %X81P1 3q6#,R=т53(5"81XHHy("Xosx1x-[y؏ʦ iixr Yao( KHȄ&#yrhi!X,y"Fv5iBJRxE3, )Ii=yVY-AY(YIi!qSنpؑ$m-!*, $22U~,,56T~OQ Jn UTTl} BББBQlP PQylБB''BBly gdfPIeIBx--yPlBBUUU~ Blx lBn Blllm m m n BII6Bln бlH5lBm ttHlx ++lB,,llBBߛx HllH|tߛHBtHߛt~~} tSUߛ|BUBn БߛSH*\ȰÇ#JHŋ3jȱǏ C. @RA\ɲ˗0cʜI͛8s"ɟ-@!IϣH*]ʴӧ"QʪZ$:JٳhӪu*Q]R mQz5 A LV0.V T,B,) aϠC"&(AiW _ԫsͻ7L5 MqCm|e[`}KN~[2X1ӫ__X_-Φ{v߿Ewy(GXWxIY 2}!!EHv!F|%8q~${4hcVV&@}9a#G.nDPb#c}q=V5wFSFQi晅%֒9]_xqb柀T1V) vE(j~y^d5*襘f*ӞYjy|i٣j4imZIaEve zvDgc&ݪ+B6PZgѢ*c mw? JkH[jk/ܶ ~E{)j bT" 7!yQݳa,rz \qavڑ U&8 :ʎ\g"C1ӝFO5fƪ d6r343GP[w6sxLWnAt**IK,߀_DgbrMs'˸r^S$ݐ.:Y-wNzqzD7mA5{W44Y#]RK=CKC='$3ķG!e}Sb9|c^󀇼jy3^z r6tW>ApD8:.k3L-( \<4 wDN G6$N5/d& K0,BpH.9^Gќ(ń4"^@Q)D^qx̣51[@bu|ђE?aS3$"7Hڱl##16a ArykeD4TI-bўƮ!*aIKa" $%X2-4*WY4"pL8N4F, 'A(l!7NQ%`\ @s*?;-" %!c]^K-af7zӟQY"`jĢM)YQ!9QQ*)yg4]SPo#(թRFwH}-K`IR1fR5芄U VVxf=k}ڽ_m^=ȏb% JX5*G_XL[M*5j( G)˲= 8zSzG ڗF/`PGv<,l+6%\Fed+\Z77HI;ܖWxnj{"]m)6$kz"ˍlـ ݺ֏&Ezr/O(sZW'qfkqW%́sRgU$u]ᔓ#zs2_WA;IQ'I'$^HkhibaT dI僽yoNʽe,lpHp 1+~1y\4wBJei1U<'N./ظ 4!pCMRDqs2 EqZ}ߖԥpհQf/ָtvI^;ey# l.+a;fJ-m 3[hC#.K |(a ʝT{)tH → 7lfoGi9E۠89SF{JMJy5 u69'+]٭Иyem\V.Ή,>Ї/$Ghҧt0:NfzoR'm"eӬ8EinW"{.w7AɈZ2jUr'q y/X팔u'DTļL4nzۻ&7H_qb~MGUMn~ss:woxz6~v`=.ٌ?~o O~.9>տ~g\B'dv^fgr}l~2hg_ hks\{4X!2v`EjN7}J%|z'*aǀWEFH 8}9(,`Smaa]"0u%8KuXPKgWPBUHTXSdNhG4XY\gzRZr$csyg+ixiZmR$`f舓$}EnXVӄ@se)pNJ-ixq(i7h\5$X5v1xpf׷KxrQIȌ8Yv(X}w؇$njXf(kV!{ynHdrP_HُT YXXRK&u_؃7؎]`-HAXC D&ٍ,Dz(Y Xm\xyB`UU%CxH6_8)r_>I@Ni?9EߘXq3i s8uyQ/)xQFT8ɗ"LhwP9T{e؆"Iq~y%3~锷XO68\9b7xYs9֝~Ce7~iT.i,()y*=HHXܹ&J:<.(ʞC 5 e|9<蹠Z=d,Irz&1fi58{??S3&1 ɥ*M dOxweJ6%F9ҙ2':p6Oc!3!J*9cOO10 $K^x+(*괡ظk= JZ۶t=iV1KgIkvzj֙h;K{#&h *_K >yvNjgCrY2'Dik싽!ad羰ʺ|틺[vpM#fHV[!At+Z#jnF*KvG{Ü; |m.w,X€+8L ̶$ˇ 1`(b ,KLܷY ȡR&象z1(^v~*Vz]M.$zsɮIHbl|n{YD,F>wvaD' =#T-.-鱌562SmSf~=noċ2@82(-%^k.Q"KfIK,9. sNk3:7?T9? өj$kNdNbJ$Vt Y{.s튿4Yy= {>Rf'OEPo+zAyl| a<~_V˲ɴ̏ O?ُSaT53e~|dO44nM@@ DhP@B\ )XF=nHp!:(G-]RX2ˑ,QB0N=}TPE[4iT# sP3^0H,U,Bj yaDc%Yk%śW^}V!NS"pbt7"r%Li-{r]/ \pN Yj֭]EiO!Fmpqnn}2ؼwf&)M;Β_Ǟ];⯛C}#2WVmO蒚+:p@r/*D WdEL,ŏ"\N=GEH/G&ÐM|CmdI's/( <Ļ<GRG2Qd1{DҢ2N9lS,k3!/.B#T2L -TOI'3JRJ?2!F| QIn4VY7e(Ē#gKS40NUULH}VMX^V:6Եi"5-,DB0t]KT6^y3(Lq}^ns?qB4SSu4e᫴D\2laOԽLW]w/ve]xq5XY'f]"5Cؗf']j;FZa& @~]d ^ wmm 渗]x:brb[zoi[q A*m:cߟ мtdt=W_KD1gTЕrl`OeC",Mr)o4cCCpG1%9x,Vw>v@}Y: Ez55|f<=}v@bW60mqA$.pe 仍>35,[( \7JFjn# "kpY& pzᛜJ(#>y"[^ 6Cp\Z$aN]^ÿ1R$4#_ &VCaa"V* Yd)i94!:ҭ6x`#>)y R^חKbkQ!eǟFdC% !1K}lZ @4Δ$95jRS; ^zPj%TqTB:-'3 UJk 'KMJ' q^Zp(}_3̝ʔKNr.gFkth3ɟT@\B3eX ҽv(IFʐztG%)#9HSLEvtP&eN6yU"-xQE2'\V.2t&>҃ԯ~-+PhSS.iBղ66!I@9MҲC\e3kTWM_E &er'䆃ull QVbmnuнlUU!.kUJUGAV7-NY^T}@^WMsû^q4}gQ&׾U/64UU^Fp`7p%Td ɏ$RoHW^Mrl\,B'4} |VvO݀jD"R2fv!:7u{ģwIy.e^{z9B^QV 7 /9~`U#"E})/OٍtQ ;l?R ?3c?Ԗ 3 24dC \ ? ' @, YkĘuѺdAؒAS$8Һ |;KtA+ĺ:lB&BtA.#(s:,ƒr).\C(1T2c;4|CpCl@CB#AD?45Fl@@\0#5CHG|DNxA:>'D>PCP| AV Q47ĹJB28+űpWE_]$Ecq3 T`AqCfŰPF[,KDƞBXEhlO\AnLpEkZ[>smf?h, F#kG2>܉TFp={GxG@-#j}DGSD|$Ɓx:B¤iv nl!HG#aÜrlcäql 4lO<ɠF0sȗ d 4 tgI, 9<,E@<u$ @L2ɥHć ֺbGJI?*RH əJd˶\BJcúd | 8w<-˭YL<ŰD wPLF ;L 4J+3P̭l8MtпZ<ʴ$ $Ϳ5KA4.D?RN@IOP,%Q<]P қRD4]JtC6m'"ѡPDʼsM7ѰSS˥<)/ CS>ѤL#ԷJȅTJ˲RSE|YUVQeT7U$$SSMUp| 3DZU`IaЂ ʩBg}efD%`uQn%D0Bou1r%LUWp-EdW$D[e =HV6t:WJjTQhML|fwEXJ sT }؇X7PS0׳׌uKձX-Y}CSTEIV8Dآlم1|M,Tq5گұ W}ZFtUK֦ GE Ne6ڪ%}5ԼSژ1Z XG,S5[ {~[U[ ßu-TIDžܿ%E\!\q5C}mC<ǥ?[\@XEݓ]V̲%1Z8U޵MHq˭U=3L֌uNL]u537Nac _ d=.zRQ(mcl@؝cԪcۣd@cf3H>n^cCd(UE ;eG6̃\_fZfsd !%%n5eV>[/&dt1BӤf5fK~XT08ȫt;D.YѓUG]~i5+`~axu uy)hЀ(P  (茨hhi ( @Fh6~VA dpF4zd>^]Eh(`fh 8Ȁ(.؀ j6i6뵎jnk0kQf&vZƳTvrfsfԣۤ6j%8ꀞ`莞莶vk^h~F^"ygCenls`tg65~^j΂i.&.h#XnVހ&Nz\fi2hm1M(ufL0hF6陞n.&=0(np6ƀ n`FlPgfE5?#-jmak%&h>/o趶l?lFj>r^mȾi6yg%.䁵栈ghqF .o0kɾ8ss1Vis?6'=Op Sd;7~m<خNSYTی[c?&H!35L6^<к}MFG73AdWJ0Lw]1 ͝ݜm"c^Tѧ-l`wd? YcF7u${A]u.@$jEcYd?bfovg/u0OwGUkgܼ>vwEovpGLtq\sg :p?脶is.h@=oxVxih6OqPCFbӧF0  ꮎf.'7zjP쁈k둗^ks L(g@ I LdF bhB2Gm?zx˖s7gil{Ubw[ui^ VWxN6 ;pjׇhj x/&~ (ʧjn>yFփv/X|6}Vd0nn-oz'jOwg*,Pa!Ĉ h"ƌr#Ȑ"G,i$ʔ$\HaEUҜ8‚e4@B0Aԉ〢F2mfP F\ jUzZC `@o  aNZ'yJB*}j@ǒ'Sly P0 %CX&J <IڱLӢgӞA H!@ %A+l7A9zKPwAVr)CGDxᇥko$= 2hgo([~#Ygy^S< : hfKaD!!r䧡wZG'=pK#mhd 8#5FDB ƙ"$8$ 182dIEhG@`YjYd!ĢO eSKDM'O50hyYb4Yd{zhfz&4 `Pk$ :x)0Fz#JeYW~ёY+U62cD+șᣂΚъ.QI&eXuHuTDUps%L0SZAr QeоҦhX*n0mG@lcO*)L9X0hp=TT@݀r Zճw\ŖL W@,_vh[NYjuʹGղ6^ٍ}y| e_ЍyBM % j]]0~\5E_>,bK{i(5z>Ii+ٰAyV> 2d v8(g?WXS|Q&ů% r,*iT :hG+9щt{1tɅ{ ?䭁^9߼3 gh rDO "2u/Vj0dBhI΅O Hy nu~Ջ_tP?G\W!A|']: HYI@5014bqPȑEB/~kD2w- bi$*<  yX B2IJr2{KkZ| (%R1AT;-)IT<ʙ*L2@ ~ + &Ģ'R< \Jy%:-z3JgcρNRbg=b 4.~8ɧ:C2%@*R`z&C+:=$y#}ǚͺS ҕ(4KS=55YO RNAVDOTGj?hYtUٔE-1VNQUuvU\/N7@9LZ&a! D%0Y,c2QpP.4R4iZMKJ1F,hVDѯgc;#tm)>UQԵj-r%Xmn S[ s| j^a+ݑ 2(lv©뎗?X?k*wY\[P-f!יHΒIer-3E@8'طF0 *D0%NZZWKa&B!05+zS}1dPݣx}Q|ƂǗg FNMDX߶L]}#] ~2rA ԅDɝ1u6h[e]fdd㰙=k2+c"vnd1Шt9+E[ZReggY˫aJwZ}=^qa|f֋uKϷΘ*5mmAo Bʒn;gLml}A)~pζMbZwBGgW%II>-ml=hR|ݓ%]c.IlyT5~tAxJݭl7'M:*M-ꊘaQ͟v|y6ih\@ՆN*~1Dp, ;PrK8jOXoU-:IoKC^!/xۅv:o?jzV#!?IɩvޛϺk\L}Gnw}ǫ26QͧO>zۃ<>zC[缯7tzOdW95 躍[[W·2UQTEM0\oN_}#s_2O~N),@E$BXќE] 5pO★D\KLQALɜ N˼ A  @(]9Q-U[M JIi_M e`]HEr@ YMXX_`! ŒBTY8jU߿Mړ!aIqN)GH@LG#2۰ ("x(N",Ri؋m!!"`XE1_FR^AYw\x1pO`b^,Lbɢ`% F}Ҽ$i JްM`0|5@۸gpɩoQLѼFwxFDyGY_Ux~q\bɄ}.J*b_4}\*$\&%tFgiSV^'IP@] ($ &!|(^ʘY ߬ ,HEӵIsUa̚&flAN5(OU( "NGMF,иaѰ X<ݰ*SC!Ѧ]%ՁnaHNN Q)) ^Y "V4#Kr^̋x$Ahٽiq&&p_9 %[MԜ^1"*QZ$cp,Eت3E - DKf*S(BA_ub. DMUio/s Z䑓Q>NDZ U@ϠhTŔF7qkaY\hs>hpipҩ+Ha!CQb u(RмwD FG_TR]0AhL0^kjJ1o9!)q6,ApUs%bhՀrEyjAmH^QJTf &a,3I&Q SŮd 'nJsΞZ-*3i5Zĩ>Dj--,,m. 2- m~jnyQBv܆4h.r4m.RnVQBZDYnf% 탬RVatT*ꅻKInDƭ'%""}y"'{0/m|.U*bVc޺ʡb֐YR"X\\EBn@`L:G7˼YXhJ\0NB JN hJo4.b-\еn-GF n{ʤdR4~ڜEʠ G) (a O&,ncR DRLS %G<ͤ/xРξ|L3NE1r*>RCL&F̚&U#zS6eDcqk 1б"-#Lp`H.Oz37$^v/2,,,)q*SRTR@,Z^i2PdEZa<3 ǖޣkV!ϥ[r8W}R66@Zktr:KDYXL`H[G%GfDWȬwfSKF ̶Lz,|$4'oFBo d4.n^pimld²P2X*o*E O?M+as;pE߲n>X&UY\uFn;P/E.u5F2)-\g1 j>n ]5_`L9 a_$F0dwHf$D[6T`i4=u %u i{T4cSL6^]%Y6S5kG>EnOGYiwsgj?f6E_6чHt#d8IZPLM w+u8xu<$eoQGx#mu?t|G`/5Jwou?Rz[RO&Z fg7أyxw'?L~('4Dq'a-8sx5ąsZcѶ?ɇǦ5_46ywD zQW5Gc.Qvg9D Kȗ*T4c+1qM{gWwvsxƟT-y8IBv=xe;6s`Q-jt:JRȀhxu&:J y3ЀX7S?X:y|#봲-'wﵓ7I-3 G:K#ȑ˚)6'&OIivj{võLJCHp)|QƧ3|i|4mzų7H/7'{<|)JKtw;u:JN?Ǽh8ys<Hk$dTKT'=<=!OVE;=:;{{+'{ {=bBWȳR7ܫw ًv/{꯿$]A`{u4Ov[~~tw2z5?̸'wEw=kA,!XE 9h/Q (M  `XȨnpנ)VzM_?j:.={ = ~?Jr=@T @PaC!FdbE1fԸcGA9$Ɔ 0@/aƬxR&"+[Թgϝ8X8aDnXD6zUks|0?p~Psۉв+p 2^H ' a K4="JϬ  Jc((.bQcmv$ L7 -n tvɩƣHT1W!q]{W}X .NXn!X)1X9AYI.QNYYnaYf|J^l#hkjx\+W[xZL<+wS$n歹k`wfjѭԮJjFӖӰ*"c:*O|c-` 9w =KX"GHŹ* ʪ3m)Ka]vtvN.{wFGƪe H.kg;奓o{?ͲƷJE5{ji>Jz'OHIX̱@4H %.=D%o.T*R[G@%4`GRӼ\+[Wԭv",(XYPL#&PU/U}}bD٪jdESկuHzsҕ#E-Q5XnH {؍ꕯ5S!kPs&EST|*>ZŠ!mmZhU-+Q76[P#v-^Xn_%nU JZ Z]niݖ!ͦekͪ< 8֗n9K|֨,s`ő3UxYۊW^jLS(ˬ*M+-b˽.JŻѼjW-^Cd ɦjj+2_xkm\2^1:C6MU(JE#K'+t]6s׌J[>;rE(CHO8daNm "+09_νuhIW,㭈N?;iMSZ'-plP6қ6B+ZTQ=h^wk k]7kiyZ Kȡ?XYVȭ edONH{] 65QX̣.J nu4T}Rl@#0kV|O pWr^Klw͖/M]J%k9X|q`-nrgD܇qF;3y߭xdސMg`'F+"Һ198q i7|m;Zƭz֜#gs~ꆫ&Ҳ~9ы7d'9_ t"ostoK;o>][{ij~\#sFz\f}t{]xvonXн~okX;ųT˿3WLS浿cCR~Yѫ?w-Dž:͆縧iwz/ j >QĻ дOX*йj._:o8Xw0BYo4JͲh/_o)M EP0Tp_k%o +nP Ï P m  p T  -$0s   Ppa'Q0 /16A1EqIMQ1UqY]a1eqimq1uqy}1q1q1q1q1qɱ1qٱ1q1q2 r 2!r!!!!2"%r")"-"12#5r#9#=#A2$Er$I$M$Q2%Ur%Y%]%a2&er&i&m&q2'ur'y'}'2(r(( ӈPc/̚'_RX42ck*G&+}*u B,,a'R/Ҳ'RF-wB.u,RBx.kB/e/Ib+20/?/a. %$.31Gb-}B2E12CB3A1/?s0Es's4+S003u35=6;B6G#hs#(.M/57r#n6}&J-31G)3#Xs/2:s::-q'Ѐ@_"Y /aB ΀ >s'=4&ƀ  <S/38!f4 4A7F«4A` " ?T&` V<` (?s JBG0DEbE`FSGw,۾Kפٳ4׭UR[ڻx*^LU,aeLû5!;~YAN;x ڲ5j԰O#!, ok ]Sqqa2"N,SGo NkyϠ%N[y2Z'%ZD6ڀ 4M XXv 'yJ p6yp}h"LΤ[Xsu&@o^-8VVkUr9鑍y݋o헡LVBV@$w Y `ZD-_`1%:5cyGft:%YsP['Wy驙DIRS)vV`GM'IoVf29fh :^irN/f)וUF)H6*U"9SkR4ؙhh&ubG tT [ڵ=ݶC%,=^ ܥ+vT,n.\d3MۯT+!)+  h0i]jԫSE:PiyiS5**Ȑ,@Od5AK3}3ZqRN׌%5ze-uy>3mO&vWOxgHaLCUQDVf32[JXDU~~ &QsQ$HH8Sf5"(F~ ܥ܋|4,N՘v)ndZ*dH+:nwBJ2ubL`3]>䥧eok2$Kр+_b:&εG݉8,]0EZ2dveLY>fT*5 mXUHo}qoQPJ }]Bz׽adŸv&fHmjؗYQFPSn|˚U,34-3]>zp9R<.Ȗh-JI+ݩou9IE/'fҜƢ\xԕ8֐SG$ Hz]Rп5Wz.CLY\տ d3, C,_^{} )"7I9ޭlW1ً0,7opw%/Fd}]솶C:PD%6!)x"bt^' 3I !ye̾tܐ2C;r,P5eM`Z"G2<r')yϑm2:"Or} C߳C\E]KgzDple{0/mx#sreozsj޴"NzNR2n#!Os!ܓD׆ds6Q)^n|uJt)jus 9iN58C^ 族 Sw^'=O t-sp h;y(Ea 7} oՇ|g&idgC h[['~*ĶxG~AVH$G)+ad0\ dWuH|.8]5( v~#Hg׀i2U-xfulgEpClM%t@y7u8h SIyPW]U@h(&tpօA(xq%q9(p3qU(U|;gc8m12Uf8Q}gǗ=@'WȈXA%|HdtHhqwNE!m96{XaKDBDX(O0c87VxT(Bql…hSH.qQxu7wly&Bc`Ӈdʈ̸ur9⨈ex1FYW a6긎xw Y+>c~HI"Q"!pؑx1/f}3IK7 :h~|"k3[Kr5IEaYWoqY#Im?:yez!e1ِ'qQIGm?I_Y* J!K M5qkA旓ɓqPouxw2c q,!CSyͥmin{M8[Ir98E8 cHٳy#4٩Q~ ҜF&!c׹Zuz󉃵k'St41bqʊꟕșUgi䁡Q j3ǖ')rN"vIu(ٕ;XZY_~y՝ HN>,IY?J9c3%In #wJեqupJPi9x  0+c7To0uיaAà({Fx#.ZbkJXʨMCk1Y`\*^XʧHZaf*|:ZbDD5W Z2]_Gʕ8ۈX:zj)Y 5ʮ4ڧꯂ*uֺj}a szzz٬ښ강WJ+A/ӯٲNdx:2hrʤ'.Zi.:عaZݤ83;vA{q<.0Iٟ!1QOʳ Vxj9jFK he 7hl˩yKEJik۴et[÷}ۋSK{wϺ[\۶ *[+MW{qJ&K󪹝{ө{jK-a8E{*͔rk+x{G&3rc۩ 1(@ڽzH,*C~KK'{FyVd+QƉukٹ*M+h++w\.KH s1̽ {g-̑);\)˾Ķ [.|!5twUZܵ&q@jW;ů9'"|>x0,.Ib I 2.lx)f[<ȇvkz3|,qP\yVV<Ǚ ɘQƏ_K'u2Y|uq;:{L/+cȍ LԺŪ˗ʻkȋ qKK)!9w %WE) u-+ɞ*óͧǴ ^Ɋ\0\-\@M*)Wʍj˲ t<3z̢ Ҿ s "_Blɡ, |͝<&УD#l9 X|\WӸ/YF ,Q|E}Wk/J5Mx6:21տL>-a'<]բ '1vmxI;d=  Ձ]Q RD):Ƅؒ AJ0q)* һ=}aҡ}3 gbq:j;Kiw%dlب} ŽJl= ٙ : g \.A"԰z<1nf=ݲj]9^1B->^۽ ~h|=@[W4N.x`V~&~Ӗ}H m(,Lc:M, :N `>*K{߹Cnpn髺0N[})~QJXjNlx^@7CJBFʔtN/mbdKn~,,eN~I| s~cyNَ읍WǗn.+eΐ6EV^ҹ~M%N?RKp8l Oc^,tŁ`L&jǞ8R/bm1#\L*G~w=#jI_uZ9b!#h :Zol7 gc?@Xn0Pl˅.?p6({`州,Op,Z=um !L?_D5ݤϤu^,Mb3=[]Y?d,/O(.;(E?؟z5\< ,; o7A2@ DPaA<|P?HĘ1aÅ%6(P%!ȱdIXӠG5męSN=}<DB)t,..$ĨUySՌ Ҕ" \JE_.ٴfśWo^wTЁg߽ )(Ca_#2 #f %\AԜr(֑vG_[l.Y``9 v)wFǯ.Bw3~,s%GxZZ;C0xZ9! \5j>'ZKs0@8'[Φ N8i(ÕcwG*(뀲ǜ[BFNJ;l 8h'jPI1<ơ ̄7-sL(̪"z&<2.}1/;3QE1c0ӉM:N.-P*O0@ɛR'H4<4%͊< I┵UcСP5&:t1=NTu2ve\uNOZT1i ڽki>l0O5? _qz99lUG>#K^y6&hQާ^l,4 Vs_y{*Ʒa&s^E8p|XZPg`Dwzr%M]:]t e`atų]v>„BuB4 OH6[89wdz{!b2|h٩7Ző}Xq D$5%n>٣ 9Ň1+[$hG 57 vk̤&ɸ]Q6C1D h4]ML'MA e62rG\,VMIif6咒qڒNmn_b#^ 1PDY KTQVQlV^@m7Bb~zf77 Bs뢞 jPgOXRthEyQ bbh¥ $V*TJ$ hjґLLg,y:9E@AjX:zNBjC4MNADIu+L)XcSJ"'3IaþձɧU$LJ+a"W= *saQL׎(-9ǶM<ĕ@2qi-OBZ۲vrܫj\6#B qMX[-:#NL|U[2C#mZZ:׽@QO)"p-؝8dӼokϖ7k$d^^ ;c+&1ފ~E$-|,"Vow aRHtUR(InjGsiԪ# . /6pBnq2W/mYlH&<7+1s\e VrY1)uېZX2F cT{CӕUjF4FaK`QA 񀥲e@'D*^՘v,}hL'uO[6Lחtx}jbMVҁa&0cg&.*z.v䍠Kƞ*}؁!%BNۃrlq[ nUhl NZY!>ZՆWϩNq经=6@Mu4ͨyUŒ^KV9njr|Q_Y 5 x-3_pmk;;zM;&W#Ni?);6B(:ySGHItg}x3pUf^\SLjH>y9DU}u5 3unPPwL?V=_2A79r&LSJGh:/ h^=l?6ܓ1'4 ~`  rysJչ5yl6 =v\ĊCL4;y?s;ߋ> ]@m2<X@Bc<@ 43(AA3@C,5[?8m;$C(#"B,vC¨7:'B'0S, ٛ_I@R`19DRpÃ>> -;)< @B9TœKD8q:8<@s0#5dCHTBsC C8DN$C FAs#R\63ccAƒE!~`/+r;&?#!a82|cl@ ;Y?"Ôs; 3 n FaG$@r,6^s?ODAZt Gs ዒ\ǂ@itH31zs5` Q6`Ȇ$1,AP7Q h2n4a)HDsEKX<ܼDQIitGELװɛFlɞD ʽ%>DʤƩe x<+lIS#Afqɀ亸,~ԭ}|7[LƬ3@L@ԉuTH9"LŹLړ#3MP {$KLDs㘁͌hbLD,լ4MMEH֤L_̍@Ih,DGʈDM_ɴ`MS?NDN&jN焊AD`KNhz$pKOdPt CPI[_IOb%)34F1 6bȀc4hֵ`&0P=V?d7 /Va[5CVDb'ndp%dhVd+La&F>~^E.dAQO aFX5ddWe#nツ2e13c [e'^Vc]daG-/fyl(_lF fi /+ Xgphf\cVevXe gG$Rc*fxh}`{gYdK6gZ.(~ޅ.pFS`{ev#6ctdbhfmViq$ia\jviNhAhgi`i8j̓f㭆zF~jR{)꙾jHj@dnlijCcvFv~`~k6{蛞kfSC:inh ~lPlϾ $Ll6TP5b9 m8^&>&n&ll>ж.Ih3- V`Ny.nk.mfFo`d`npn&jWҋjv6mFT.pv7fI`mF>ppqpQd9h`Gn'#p"grm6g.E Γ!..d'a d#"nnrGq&rwVn 9O6&^v.po3=qB7>tFosF?坾s<'g'_pM pXAF&=%pRt8fuXlM/YqQWuSOuUw6tb OdnVH?eg/tN)uW/"0nn^aw(ǰ)?7/0~ ynPtgZwv')xow>xOvkq'^w0k1ғWoq WF;FO1қr@ۦoxWݶa6w_FVx a~w8zզzye[Oiѥ)`lٶq7r>w>E7zy z/w{_Wm|{ǖnOxXP<{|-|۶~lW|اƏxݗG}p}}A~Ud/{j~vWxy_{ޗNFOPV䊛=|i}r,h „ 2<8a"ƌ 6L E"G,i$ʔ*W< i3A&qdb" ulY0(ԨRRjdS byeփzz20em-ܸ%PJf͜(V Fلh%1_P )YBmHD4ԪD.ނ6sW; p;¼/w6\-Z93Bgn:\6 ۦýWhko.z~})҇?h[UPlT[Tc [j6I \D@IhFVd!%Ru[Phr !XRvM1RS™#n8b6]$I`` |m`MIj܄M9fJ-fYCjt&qi#KMIxU ܖ4@g('2QhH'eo+U8f~ߗ`j)rVwnbitшښwZҕ,q}z+{+uT+q),쏻Bw/-_D6L/S#Y*2J\(TdfoL1hΎkF3l/zgHlf\J d 6%)9-^ꇎ33K5(Tp 8*WWd NC&zYb2Oɬ:Qk"fI沮 _ګ.U`mi[ܞ.td+;- eMZ :܌Ӗ8>5]gwq]Iݒ0+9ږ7!uK$^sP^mv%ov8~ /Zy9Gqr۪Qws:r[e-oZ"yC h"q+Ynj߶8Ts/ա䃏\褫7۬L4 =~/lkNjcw]~S;w߹p/ v$F)Bx!&6 ;r= $}E=dT+z{s|{ov/$sr;a#29 ƒx8 }l??   dA۟~@ _MA tII _VLcMr\52!Fle}lTBd@  V  @@` Al@J`A! > "a * AEj`_p]ӭ헁) n[AqA BZ l! 2b@y@9`ee_aʟ&m"&z*`n@Hݜ䅝Y]bAHޑ-0 hٞٵ<}_ BH# 6 77Dd"@(bf+^_ #(>?_,`|_ cdm cU0uZ^ٛMA5'jcBdI8d&#jn7ڄ$&RѤ ebRf@<6!^3^Ŭ ZUv1!d`A!CJ_e A$d$%L+'%_R_ ^`L_.@^!މ$Fԡu-٘]C^E\TbI2SZʠ%_&MlFI`EAd#A`KJ %+N*fdF[eee_Tufρu\TfxFBd]iy b՝v*#xW!Q%bRy^eh@#UDtvj$GX晍e'I$ 0AĂIPf5rewU(5sFYꞇΨBh4E a'yh5Rw'jrhd.t2D Ej~RbhAiq GTQ~{UiC4)|FE 0_Z%nU"A[bD=l_>ޣ%_MasJjZ]BY|Fȡ|i(Dr1*ߓ!!.Ơ" 8Zea& xaA $8r!!k*af+ `b! x.&Tv u\ERպ.ݧz*t%>JBIc=b*&.'#7bb+n":a,z(4NiBȩɲ(]&+T꽊AZVh:J@`dcڣ- *B6j9;b`@d?v;&B {)BiUG-­iޘ+Hly,LOAJa$Sj*e8Z,Ae:lPeڤzeS+ŖzլiB%D,ҥ@$$(d&bNnq &(].`^ f6c.ʦU E`g~$:A*.#nj>T:%*#;pꯩ:E#ea2 ߧ,""nϢtiVbݛu.lŮoN&LݮܲTo}0GrFwpl , KRTtƅ.Ju ^* n~)1v:Veu/zm n&1&qT~/c[bAp2cIRDϯ^.!b0װ[xm > '1Q>_ư\ ʧC2YVqDr +rvI|Mܯrj &2YjoV_9o:9S5U΍cD[r3T1y1ՅVa+vjbn+ X+:k!`AeL+&rG\.3rOOsE24JXA_ D–s֎lbKZl*f`^2F'%:KN!:p$82,K2'&[L1;#'@Dt· #5ؖBCeB:.q.lӦd굊"\.vW{W_&Ku4E@C9vx0Ts37t(en&.&熮S:'S&"n*`6Mr%eqe[2crcEK0a/h)(i/Mj12dBoK.n."c`#K*\FP|$^:=+c|Ee7[H.Svw|4][!N1B]$q2`Rp*`qJB6_.I?4;F$'R pwwڕLkrfNwod@h0&EhWYexY7]=vFZU]x&fc@费x_i09x{U+dtL }wD":Sw8 \,fRE`[9Ox׹ϲYJƓ;zwZԹjK{ tT{t Ǫ=yb7܆NkBD;Feo{;kj3{jzz{Nۢ{Y캷SǤc$;/;7]+Psݕ˵÷:MIO~f9H4<>Wƫ AZJt yGng>ꇏտ4W>L=3Smg>;N7 ˬ{ ỵ# ?@8`&T!8!@ ^Ը1aX0H'/F@q(aƔ9fE7iC"9n, 3@ ~xӢ&PTi̧B 2HU_;U Hp0AEfqLqa@ /djywハ!2%ȸa(t2H̙A=:'AZ l4YklM .i:8+ͨ )Ppb<8Bڛ#ˇg׾]lsS)t4jv7TKVe ;?]0KmPKP(S.07  "d&`p3q E6lI.Q G IQ)$;Q& ]<7qbR12,R84LМ *}q-R*9˂7LTѪ "8LC!,]EIZ/Sp?sY}#Ћ?i!B@d!@2h*?x@g@ KA*F}+ו));X׺eq J!҈DYYCsl.!SǑ @ b/?IA*@Pbx<Rt Rp&Q}<8E%f`xAl  30Q; f%-xwrH -7 I2оh .AБ`eJT[D (le8x{ ^ɿe"0}dG `I$Lc Ҁò [X%d.V `I 0bP BQ|, j{0ؿ*Qg P"eA$ Mwf@Sٜ5*i|Swt8SЍ{d&MГKgY `?tX-`3GIUrSh_21khQq*5hSx:Fq )rzʜbXa+ W 0f7^S9 RuBÞa /=e U6O85΍g $d}Bswr&%Βӻ& ٤s֪8K2S<4iH-WfEwHjf]}#m]/%HGQ4WNtc{8Ϲoj ktSf;ԲQx/,r]% ZDis^>t1{m,9À$121^}MOG} @BҌT <"hnWXK*ַ{vxw/+jb c<$E* ߲KLؔo O .vtVkl"A !6O aNg+i*ȡ*.h'4"Bzݦ/e" >o, +aL(ncs.PRUiϗ`Ў`˶* .ȴj  0n`"\MңcD,k&܆Oa- gr 5> $ *6'9}̈ +< hKyp8*81,iE/VI(McvM'Mp 5-'%8nq#d.&e;0֞ #%0QF,uDWF9QcPc <Ï"00oh> ph2%26!f.C&㱻H>\?2M%c.%E$O!(FM4^r,N,x"#"_M 5Rظ=2(g%K>Qrj|g)R1*2|&I-,21  -G.2+!1b-)22,~.8Ƕ0-1V.g.00((~<%JB5 JNf_o~<]2O#\, 29S@8rn 44!|/,b'!"B1*40+L*jDmI~^BXs>nphnn/Gi-ϱ14p.+tk̢:*UqJ3E?쪪@+E E ͯTˋ*<0?FͲF4YUHt7^6 PQP!(PSBkB"Д'z+IF o ڪT.8}4'фnUVvVHuv uI UQT5(nlxɖ6Vha"ܴ!dn\'\,;HsT4>)W3^Q{u_u|3A0 ^c=dpdCc* a"_X3uԼfl|V&GG 1gV.d{Bb(:` Öjife=Fh\w"jk]Pxv42PEg(qH,JpJ&jGoab:VcTjp9% I]?i(u^q7G_m7nOrQvgE6m]6 rGO1*q+WxrDt*3[xdIƦki! vz#WcQJ:c =7(J8ySD*&Y7zibU `1OHzq$|̴w; 4X;e.h&#R&}lD |r},DȋHDdp nyJ ;osdL2i##AJ񴲃UVEc.D,s\Z#њxo# 8Ohw,#֖` 02bt%/-i%Rs \I z XN9$)Vǎ]&b~ `~oüƖW犕 &?S*8BBHC pF >*E",C r0sA7~ǬdKfXEõ۸|0D”Qى}"xv({wCxyO0* (4zCy+lҹ ]"76b Yv{y7HIvSӆkyD9~ tٞ⏁!%9QP4t:tM,$z'+:ZW*Z"]M# yЀ X1| c| 3cdy4"Xe.LsAD,w}:!o} 0L:b&$rD\F.[5]RuLZ;Zd NDZZ%3@B. McG 䑙VT3=O:7: w퀣Y=&{| 73JIJp;̲;LT"! Yy%@g5ygdK+YS؏~@fQ6u¨>O`Դ\Pb) xς{ >ⱛG[Dž/C?P=6< Bȳ䳖̨SQ7Cȝ: ;0 eɡɟغ-\,UzEcӃ$C|Jճf Q_D N<SDo}ΨbcqDDЁ ]sB|ə<iɹ[, %(*]Ep%7z]G}ٽ`W򛿛4 V;[Ppe#aOH5&4 ]^ʩ'fM1s_Hb3.⺈ hb(`"/au>~빾>~ɾ>~پ>~u gM5MSܿ)nr3b3.7'H VĔ4!?%_,FR)O@Ʃ@#X B8< ?>'a?9^IOPJsCͧ(S">~XÎl?eu\`t`۴WՈCh]#.~CU@3ٿ%}*W[TJD^!bč`q@.P@ $'LX0ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{L˛?>ۻ?ۿ?`H`` .`>aNHa^ana~b"Hb&b*b.c2Hc6ވc:c>dBIdFdJ.dN> e镀 R^e5QiF%f`jIff~%+dd@ abpfrJF/iœ~dfI٧F+`(>jc 2 i( b禢ꢤF6JjfhjFikvfo`Pj> -ln;Ѫ܎K.~zh{iٶKoi/w&kKpfzkp#7mp.ppq[mΊ[Ǎe.j,or/L*a2;/p:ܲ<翨 Ls~-5VGi, |UD_6f9-3]_Ͳ v;1mWQ=w~M8$` 7ox+m׼S䂏w~fz]ЎkzW̋פ8zX"Lzjo£:KF-H}O ¤M3}yx'c=ا߯d_s~O+^磏)fxz]9*pu]&uq[1mwB)kR)=pf @-V`U o%.ek < Pi Clb3j`A,Is:TY EpwleHaQi{+o :p A=yJ$Ke1yDƲ)!aJhj?ˣdTr8,gy8 }4;cJs'V6߉OD.eL@*s.穓_Nmt˰&̬%QH36ЌTe2>s,FO2lMiϱut7'&o Թ쳆i`hJu/1h,w_3LjL :`bgհjDfr>͟u5_Dۺ^lKaNu+/&;^G>ݣ_zd5;r#_O*RQ( Y33ufwU_xQuDyATd(Uu$MʟJcbSsMTmqExRV>j+rh\첯xrXk:հtm/ Gh_}mMªx w\uBbx2a a!t Pڨޚfn5/R^l]ldn;?gֱ}_xȽ!p K$y ( eHkՀ\n0߅[)gnO.^79'H2gXTsІVȀ.HRV$z,^c2zhJs LLD~ִ72՝G=:Ш.4jOӱt%]TPCMk_Ϲԫ<egcfم|'_[ӳ6-f{{i6rfUwn3Ø7[{kf |/+| oK|/k|?|$/O|,o_|4o|< }D/я+}LoӟK}Tկk}\׿}d/ώ}lo}t}| ~_ݔS?<~;S}!$Z2t+?w$-!=lrzj.a=T\4}rd`DXHK8Ђasdžz(VuXq1Cc:Xh/s7(Qc8(^8P;78h(x؈k(ȉ…$(ZO81!(Rh\ϡȈxlvH09((Ё'81،SЍ/z8(؆8 \x@:ȆÏ1wыu(u1$=1h7(63 :i!,22U~T,,n JBl"Б БB!B~ OQ ''llП56PP 56 ~IIBBlgdm BQyBBllBUfn Px Qlelбl++lBBl,,TSSm n y --n BlBx IBlPlBn | TT} H}m HtIx}BBlylllߛllllIBll} | y tm x U|H| TBB!UUU~x PHPx Ut~ "ZHٓt~ߛH~m :ߑ!:t~ ߛtbuB5!P"߻!Bl}RUUm3,#J<"rZ{Xm58BߛUCC,BٴY"q |U OO“#iC<tC<U } r tБjt߿ٴtCB,#ha*\ȰÇ#JH@ $XȱǏ CIɓ(S\ɲ˗0]IM5ɳϟ@ Jѣg"]@ΦPJJիX*uӮ`ÊKٳ&] +۷pʝKnHv˷߿+xˆ+^̸1WCLRcA7F3G^R3hAd׸oƞ][%߹ :+p pei瞇/HxIZ _c")Vr|VA ýЦd ,_ȜAlSq*d#*Ja @epr۴,u"}ލ!fʃA:^(/4  70k\ /E*TVe@rd҅D2_~t(Q`Y'  Еm)RoW@ B܄X$V9l$! 0+JuюaXM"ӗFD06+r,Ás$^\h*N4 R3FeZ$uɎBBC6.Mmi5w9qchp HV %F @ RTMcUiL&Ks#KժJ5qtfK)u!Q D (GMW7%E2S0RdJːrC$':UlCz$cPAzۃD-l@| @QfM.fgU0o5ɱPKכuGHxk9Œ\maCB\ dpR_&do'bPbO -KU0- "QS2|k:r5P @/NܺyY$X'UcG K8z) =Nm֘Z?>1iϗ$9H‘ַ: \dK1o5P'Pgǁd3I04-o5TΘDWY+^f76sTK⇒9 AMv0Ё~p5ϪفD2s~DkD{+]锼y~@}k_Tӄ0=^Hn> U9="L){CZJThMtX$F=qg!!<3Hcotɖpt-=7mm' [e'\{7{x,do-D#r* T[F/DvݩD>8 B雒O{$d: *$VϿ}{^&_ ,RKo Cj>mNx5`U +vCmcvAq-s $8?b1|wCkt;-yL r [["5?wkCˮj v^?Ä@vU7}us՗B!}s&xR-w-a/I {~6Aui\ f@Q8Jkb@gz $9$xv1&7G1gN8{{24wb~ʁ~-Q8t4;u+·Y*G%*w} -(<}HvBSHwHtOQ-gV#6#+| `3肐'cw5ls׈'sb9r7%Q7Aׇ=j$FA#7:4J^[9qҥ>7j=0艔X/G8Q@s'xzh^He,,r[^s5ȇbAS.!W>Ae(Y \9A*a*4SU*]#ܘCG-xX(X8r<:]8Pѐ_sh>Ăr/Q!9u&5wh>W)9+ɒ!gW">871 7A}8qQBv&v_^Ȃȓ!тFY0A/㗭XuNz|9=؀ɕH=&PHgH~7It1|􈒣yUi!V))*hѐv1xLqsYMk$=Q4u.^yeٝ&%},#IoYYȞ%WRYI(ii“'A~ġA|GC!ّD:WTy$*"{@&jɜt%Ʃ 9)HkIyW7j嚥Vs+yi9(k6AM{赉5~RJtYN>$g ѰYk`: ۪t8#d CѺFa{ N{[ +h y~i W([[FSh@۷;Uv*K;aܣ;hs@O3 q}GlKƺHۼ8 $* @}8ī bLkH2!,*LY7' %٬ a/o1BH+0z=QBw{ >[ ;ǵ;f;- o83|Wx P] ATX F|ʗSS[aSٓU}A̩C.&ײ3aM^|L5ܶ;"=)pLܼ_,/YǠm|ޒҲ1L-Wލӈ"^ qf1E)rT{Q$f !(kkV.m|`ͱ41xN>8S(jKz+~l$^r.лͦ]S 2APua,y"2]K AҔ. --Θ˯aD{x"dYbNd2i&js>sK<-.lMAk0k[S.Z-Mّn;~WԧLv.D//a0AQa3(γ$i(Mp~"Naݠɾh]>"^cA\$Q0u^NN$2z|X^~}lnSyԁ?ȘҬ'U%0k.>ţBa! ;j,'Ů-O8JPrD.~"+ Vop~Zaq"^\ *5KʂY,(v ?557>K+#1/@~ud/ߝaFK⫟\U~T\!` <(a . dQF9:tqŊ$ɨwћF;m ni{6*r+>ݦUܨ,3cN9ft]pgȤV;s͙<9͎[n.ΖQqݍx͢SJ1ǩ uXȷ4^gw%߼x%|*6@W1h[t>Gj7bP#sYC!(JG {KVn˒_a rU]o#^Gzuc.CɌ!τ'E}D hNG=8"4AhmZtB4fPRĀEųըGW.Wa;Z "z=uX1l.[d9$p9UgNuJe 6C]ҩ&3j?Xּݺ5F iPix LpnOeLV>6ɉiy%"r煰W* k_!pü/rAR|ZqP+ Yb8 p[uFUp)*P貄\:і[Qmh2Du0u bwuʶ>M.I尬!r/27\{2($ ɃV? 1q[5j%OkGNXuUnk{;AǭpswCL 0 ,3@b6bb] K7Wq\&vupps3ƕx%d.SHAHWeH{!7jQ ڥW `*Gvk했-+WZOMJEHɮӈ=CՍIխ/1:Uv?xC$ p˘,@-y-yǙlwI{4j6m&+v}[g+nRw% 7do 8}Tv&M8{36i:ʻ r?[@*ݳ*Cю/3{> =k tܐ?[1os AAJwaئK.cc&;Sd*;лs@EZ+ r4l {;Chp ]l19>H>( ;F;l zBvtA@_>F#2:,EY $oGqDH0E3,ئLDx4:DS;9#ܴj//B4Z,#4Lȗ\ 3F1A|RƸz )Hn ?04FǨ W$A+D 0sT9H/"-CD|Hؙ mkG*U(>pT QQ":,A$&wI\ʖʫL0$n+}18̉"K {+BʸT3'+4 k*adžK  ˻$*$DK˗ΊoT|9*R N @JxTNyͥ?| HO[,N2Č~AHMFʨTXP7{JξBT>E*HO(OκƧe3N c n ExЩ:{5eL숙8QjEüe DwHɴG8lDu4-DR-^?tRP0ИRH#=R .0PVRl6(9]fĊQlSU)L:  IFeTd',HILbȲ R2 ՎU N]GDհUG*; rYI5fn]"R&mP)֫0[V $ פtL8RMI,Tg,’*MWGm(眉5W~]D1At}ݥj-R^؀MH^V* YE6%ViQu+UZ]Y ~ZRLMZHWyٙ-%2؃=ڢ"3EeI[Zm~Wq@r YXZρE ]@8ٔ94DD5zUЖu5)Y~Rۜ}ڦR[¼ݶuׅ+*\@ݣQdњ54\\,=qY[$Z?uWm?ZsݲWEmX=ȃݹR* ݚYY] ҍгJ]2ZdV-m^f;*mTH`ވ4E݊-IuʯfT땠-QVR+_@4U2WUNeĂa>ِ%,@ +"qn;bv&Y]֕UM*9a65.M[}Z& )!^W"^Q\- XW5![6^cM*&.R n㳀aZ8Km@95I_+5Pd$|XJNq PUl`E{M,_X\5]BÄUc.ؠeyXfc0FLZXzb!pP+f#D0a0deJzYQ=`l$c"gK2F+S@ƜQ߃ Cd Fq\Tc!i>V֛hvD0w?oQhŠѡ[nPgZZҔŻ|eCG~>f&iShAj*aG]ʩ%Ms꾐7> X5mq_he`/ ꫝ@vJZ 됐g~F6vӼGl(VNƉsipڜ YVGFIizuDZlKk_f-aԢ;LQ߾Cvla[3gjiFmn5i%V^Vji gn.KFE仄 hN~K7`] Fgh>vFD$oAU .k^>&z=`a 'ЦOVQppUl'/ʧz `f-љqmݵfن,rSip(/{Zn[tۚ/e'P^@ni&Wsfr7_孤:Orl&]yr*0"nks"dBDq^f3-MQ>r,;}{#rQA7ǂ<^e=QE !QXj8Wܣ~r+ Α؀4ވZ'aw[B! gvALؗX 1`_ vw?/ajv/y-ig_}.r@J{1@Q7w|"w4ťxk,].wBx]j<7`4uOTU yۥlΉ?̦ay atwx.Fx]/;ؠm7YLm~Im \s~o up.F-:j{nWZL oy.1ox dnO_ ]p0xR^{b{y}+ t!{dzd!nBV%'uɳ6ao{5~#}%8K@GpzLN,&wBX} bP?^zq „ 2<(`4 `bÌFHQ#HB"$ʔ*Wl%̘2gҬi倜!03 HI2 j@QK"9B(NA" MI0@XKt`Qk5V[vE(`\uW;͹tMm1Ȓ'SΘsBK@z T,Zק'&T RVa @PiV$YiZ$c ;NdZތS=qs;1B{tx M[{ Levi9 [C`R P_uSaWQr-D/uh.x")eug/y6Pgbk+.$DW"'?&vXA!Z-ףs UXfIB788\AF&mxAE \ gU Z642ŤJV[$hw TVI`B!ƗB6-Q(Q2Qo*ހީjx٧$d1JvB5K\^v鄟,Ag-v*+{JHjky!a 91l\FTmp$oA6^I*e%➄.{,QYoIo 8ЮJggK#T07f|#h'r(2E4aoRaN<,<5US$޽Y]gQ /]T})/ZG6sbC4J4wm5+^ȩnǵKT6!Il+IU iw6?%NyL뾻i5o/”Wkٹ9MisSH1PPҕ3\ bZ.>''1eG}з0 SEnam/KWI!}:qA` 񙟫\@٩l-o7s􊐢) {4T_渙t# \sDOv|"?'c"%KPßf /&jcHD:LH'moard1?" )D31I:$򴑭ʘ lب Y9dRUxqlSa#)$K)))YҒ& ,y`(E;#OcP) I8φ7·#IB-!IKr% ajρIUKEOÖ?)[3f٬ڵ]%%P22 T6 X!im\Wq;~)MjJ%1C\uArn=.rZrSנv|u-H KjR#{S֘FlP Tmkr+ߌvs'Lg=-v5qWPh ʇ(ư븷^UqayoG|u\ F\/giX4*C|q-,_KoEɯdɪ+nG`Ԁ)hRQBtm @2s@ `80 3NEi9$K&CqJ|'3d PjFz[e)<{{ jQNԠ{ a0IB@G^aBPU5ρeL926U!L.!^m!#"6ISVք M܀˙EK aB dGx"Ya#bJYYYYYm\"8Մ%~YܐྐM|]( @$DcEcp4jDp,~-#NDZ-#-_%!BL ~%P5o9S,-"L9Enuą۸۹<*D=cEGdQ$2?$_*6dU6."`aEFUG&]H|cx(؄JZLƤLd|Y)jчSPe$BD %QBG6!HܣhdWUr?_TH(bCPc|q#`L%e2\}IG^w4M"_"Qd(4b.f$Z^ct=eexddDd 'O S$e'Z|N hJ hkNc B"j•qd&y&y`'qz (*r&s)n( 鉪(o6)V.9)^q#c 㒖)֩jQeRޥ)?)jF)uq .*F\*].eV^\ffnRi)BoJHnꨮ*Jҩ韶*֪ɪڪ "$@<F+(!8FVkR+G(+ &dv &@@ +dk E+Ԅ:ƹ+ z+X@@\Yv Ajct+֢>Lc,^NlLd.ri/~)0)CbXM$hlclB9.L8,Ц,b$f:ګ)iFBÚĖL-$jC k @ҭm9Þ햽 -6>Պf-fvjF-K`@Z2$)AnXnB斣d~Rnd`.@ۺ29BvfCĿ2-J,ӎE+dxz-b/̈́B&@r.nǣJnCpl%멪 ;lE oc@,TJ?F[@gp\*pE.K@mF@0S0q>Wp#n/xF1{f7q@ q/*ұ:%ӯ.r_0ukŖ Sd)2[< 4rqJ0hҰlR$W/ ;n'Eƫ3"˲"c hn4++Jr cP^l8__o0s )37(HPKȮҳ6fBH2.6.ca"=_Ԗ1C>sn%<3M>LCqvb34B ?F7A-/3rsٲEC Fktdb H;I3'u^}1گ&E@7Aco2JVl?lEGF3Z~;fFpe6ID 3-wH`*طw}4c5i4j˄K75{s8ĎJȁ |&4_pkDx<9RwWoc9~c~7B^xJOݪZsyH"$ogfDW†^9X?:sӁ6_T7,˸?,yw:XyϳAw G73v:6s8CHA7:â2gyS:-C7u5U%,9q~wGǺ4zFp2//@84£x{n{B({C{@k00;SpHt{ 8Arɬ;72۬{B{B4 X;ȟ+D?;StU<5u;WRmR8@}ūzBǯ3 |˛U'{',y~2_On(#n+}B}N<-=+HL87ާSOw/i0Ć[B@7ͺ~[ [}r}1Kϸ#k}M>采[}DZ);5=?R5~ {Dk& : 1??'?@H@`&TaC!F8bŊ @p`FV`8fEDJ8Gg:hQG&UZs@SdpA&lW #@χ5&bPfb2tD[>@ĵ% d+`[,>1dɗ1g~. LFg0/@̱5?C=Cwo߿64UfڕWa{!gϨ' ":`/$/75asW8ĵD^Vi'`>p# # Ȣ i1>s6 =. ALI889a9J cHT̚%3 ho4dϰo>SȨ'C7JL&ҫIٚF +0|룇87mă*qfhb9n͆4 Lp3k<̄&"MHHʤGN:ԥV&&N),Ţ*O 5_ 9@.%b3ƄRF]ˈ(ERŽDHTJ}!=r)(=; aM p;͚R֤,+M<Ͱ׿-!"ؑMJIJCw# hWި,Vۃ.݌ RV1EXJ,5GtBn)2_.^!~q楙nVVÚ , vSoL`dlTst%ASe'>-Yr!iNZgo\fQ(V^`ø6G1H6BMt5\Džm%]U*Ŧ|K`rڴ/ ]jt7Hd{oу"!Y9eD=7N4{26F:@fX8B+fA_oF#ϰf +2")%7kU%:!!  Jr_8z(h`gA "'_tB!!NAHsC KD,ģ  @Dn1)]-Qv'HD,%ZQvw @E3 !g$1Y V1$ $QR3+!j+Qy;@N1GeY$t+bGu)Anԕ'TyW\[*bx ZKFխ5a^в 3NBHlf[ĸDѿ i3roo|rܢp!pRޥ^wEO>t`Ox ~W0`Tc2;G:lۃu 5\qE0bV1YnPߔknEe9{ Iك![e:~4ʺ嬕ҕ!1P>WDE%o!d3n p䔯MΆ*M pX$$ i "/ cC,VBF /0 a+81! 8 %,/0|61PF++0Qaz"-T(Lz"Q4̬00T\(pG#&o k,#:  1V>N^`#BA P26p !b p78̵,"pB| ?|r4GS 4Bꦮ1қ13&B<S7œ!xL7c"QΈ#+"9+<9/"J!!^&joi_ns(rs84#!CoGW5s4N:-D/Lgt52ML/TK"`TEH(d.ƒB٢X&.QSILr!Kt; 35 YT!r uFu"J%;qB=3#cf 9_MJnStTD-@ ETVJ4VœKE+cW)TuR{-)# /%JQ TD&I.pR!@DWu1ȵ`[u[03RŇpR+>FIH#B: bW>u^{Ld 6ag5"($p]#\b^^/V"F6: >jO#gO 5fl2dMTLS4kb[¼HҾ.ZG)cuD  o񠌖;Bl FBkuk[~llA%V)oACR;X#^#i=,t-_ppuRaMe}6mtg)?g ^!Pn!dCtv5!PWZ`V)zowf]ug>Alvk.P#ņv"me*mc2nu/}z1#ѷpB(MzvTŵx T<wq|/6.e%3"D2sn䲮d{r yyw(@"aTg,r6!w @C}C45w=5x_6.m높z_քOag+8sƒWY#"<"y ;gn' *8{+Wx1l 3m7L"wXz>m"i#5)B A8eՈ+iz V <k)u#Z7%"u-xC~[j79)31C6ǔs Y}bym[lnxW{)Xx7>Ewym1.yBҒYF+QPj')6oT;/,mysy>SI6dU߹Bp VЖ!h'~s?Uiy%Y:T8j3帣ppY/=YpCu甜S8kU3qnՑ+xu'xM:XZ#t%(ZKw~N78bs)7,vCfu $X)sO'z\ym6:Z['[䥣ƍbxgxة|Biژ 9p/EZE Z&YkcE{گ)'ZMo1#:Ie[5![꺆uG-1yBv0cD]Dλ=KyZ3{=[4ܥyҪ1܇پW;b_u)bKUmV~ۆ"MmS06\ąǸ;]<Ժiivm< ^ǧ2Gۜ"u#'nѼm׼ze{4s=\<͕zΗqJ9e+C#[ Э!t  ^O:~1hԿgxalbնݭx7"=e,vbi5J`MtЇY(<-ZK 8(8걾** 㪆#9)$ Ӯ8bƠ߻lgWǺC ۳CGSS979Gbo _ɖYQH\i"s+?R^8X "> (*Kh"!#R+it*|B6+DFrO]~d: !ܽHL+{U +jɝSϝ6ɲ <0… :\8! >q+bdPdTyC $M`2-O6&K@,is$:C͆!6p 3LQhiŋ aP ,+5[0Բexv.޸y+0HRp aY|A r۹0_ldѤ6`&+Es a]<=PZz+;[w䃸K6< 'H|ƭ\D2Hoepu{ [=w~>ytQqU^FfcFoF _~a`l*$ai1Wc&B%Ɛo*|X[J|fBmdf]~AxBe!9Ј FCơC%dB~ f=B5HdO4i y瓜ɞH\-RFFzIg]u t!%eVE]TpX`NVZى2*f5vVTc k Șhn)^ n9E)JusM޻L5PO 4L*;3+(YVk{&/X,FQ;ڃ$dPз!oGvk *2hn&l^ [(ZWe);čǦfȃ|̭u^ h`mZ/vEKvk3[Z(X2syЉNPpt؊l1A:5v,&+۠抏Nz76q jjwk Z6Kܡۿ"B Ԕ7tYfwĞnYX ={ڟ[><ʞy):O'b;Crz?y1ܨBfbU*{SA$hfSjg[Pp%^9V/+Ak[ skXoᄬls⑊F60-r=d/6\X<^fEЖDo4^1GvMZC@}yuzܕE}XWY%[H~hڅloͰua# I3gR9 F/ZkNb Ey"d!{1!WS&0,cMJ &Z**зHEo` J/ιy^[(-՜ Ƣ'G-80aOfͰq]׿4kkJk-/ũMr|Yxw\b:D]I+3:#MqEU*G;,N >}@|qRC|!f둕R]q&1o&QjB_L^zy'')WƁGI6ْ؞>q*&Ahyp8НsjqspQ?Y tiNH}.y06)p'dY;dH*dZ40iF0V: ef"Xdu̩, v ჽ2XA9-@%LqY9y&>qiDtJ[P|ׇx. b邧Az{@Ʊ +ZISQ2Y Jrc* ~ʃz9z|Z9t숄Y97ժ {Z}ʮ"YAk*s2$ڪ0tr*Iɩ g A5z튱VILzy*9n%*Ȉ}ҰԘjDZa;rf qAӞ\K1Yk|щr@cH֯83"LH?XBDˡK@kC[䭑EN<(UyȚ}qiI\:=zt=\L:m5EN&E"#$lZ')ɴM[rlfu7LC*+4c gۣA 4CK{SuxSƑȈnLapW1fg>;>Y<,:Qa+uakF6:kVxըlt &iYƑl0\CSm(+ &{뱷$kQvA k'dAl%:<1gE*lV5K6{g뉞֧[oƶQIYA <.^/X&ֱD|s9ک!f*iNAB (*Hk.\ $tܲg> 븜?;!H5ŚAqU&ŬEhxL$;jƩr8'̯1LJph^'FP;E660Ȉk c˫8uc2KgĈ@6o%'XL [6#wGl/A~3j'ʐkvVI{ f|3W㉅llY&6.[` Z1n6 \Υ a<}+B_\"{Wm6q특~p=sш! H=! h{ҥ *]e{q_}fnS{LN:о$m}A]߂iۜ K"9r/.%˥Mxkn>."4YM6#`Fd5[ցګṙ?:8R5}L^ΕbGf5_nE$1-<>fS'߹۸RVt<~,~~nP!ZC`R 3P p]qJٳUUN!| ;],N"xL3ud4m46ތ>Q "_Ĥ L,^<ثb]qMߵλ`^53._B<aq»!$ˡo}w gЗ47aG6Ol7  ̥ *M1/Zz~߮H\Ͼo0{-V^[7."m>nMtCU)  X$q]>L[ ج-N-\o=l&~4NnOihoP0dosq•@˒=\ 8A $dÇb  E5& cı$ą lB^f)! Aa0sQFwESQNZ5hp4ˇ,*͇kp(RME*Ae/ 4h|8Cq^EԢJ/(AQcmPҷ3 $,BԒ$3Ic]mܹ&`3>hrktuu}2F8kJ m,=0ͭC40 * ֲ)vkc̰ )0PN'07hTrI&17OD I .S*IJėBd1` "3(H܈[A!2>~J-+!TtQF|! ONˤK٬*p(4OPLڎ<6SS)~Ar=Bcm@6\`vgvZ`nf57tjq # (w}َաu1{TA|ȸ.%d_5@OF:VR')UV,GHj# uFrYԸEbIm⋕5ڡmm٭&Wmb8HNf مjmƪx@j>wZ Θ!_62}3WtM**ıY8E$=c^r3 s2QUU4H)]TpA(2'ɫsjGCVU4jJcҷ JXԸ$ZR5#ʋK @²ؕZ.0W'2}@q,yֹ/Ui3>Dr댄~;b9ea1 .T@:EM$]nB D*~rÛLCDnt9a˖4 $=Mnw`9 %Z&PGq__&ڀwnTAZ9$dUJr'sC8pm4cYQ1;7r]E *y&/BnOg}URxd^ԙfLgZ*%Lg{usLg|u1R%\hfv-WUv+ɣ3 _aI@>l7Ds5vCaȍQv? cԾ5UjΚOyTF  x|Ic|vmr{˶ﶡ}p@aID#͐AyF2x\]p iH72t;!K$m_8#1h9//|L".`W3Vyiċ}W<0M8q ;j }XHtAn_Xds=&tgǼ:1nrb(bHg Tzo~'5B'-ٙ/`s.ut9T%oCDHOǶ)]nVy}Zk=7l[?` <:q[+ᢨ89}̘h!sY=0Ĺ iʗ  L>  $s; CsK!XS%<r2Pk6R{C{bs;6ClP9&勚і:ʖ)*&i1"A#@c:@ɗ3r< Ւ#,"qr:R'C9AI>é<#k$))hb֣)C\Bi?DC58&)BQ=*G.YHZ 8ĬLty({T2iʜBr*J H+YT!RC cICŠ?K9¦n,B,­u!-@-RFnqI8-h,zF Ft< ,L4C!ʨ<G8$DkE9Q6 0KE/T$dK\@dBHLE+K'TM}| N\{>65Lͱ,BΜ3 |Σ YItĔӹz4MsauE 7ON*PznYOPP|X*wd4yl<~N0<ă | :!â8K0P$=A( ] Q lK"NQq?П? N+S#%$SMK"AJ8] ӀO"ST:-US (=(u.T*;ЕqQ#LT˵ڼmk4ذTԪ2SQNS^ 2:EI{YzM==fl3& l1āyv 6`W@UOPUT^F/T48bI K2;ES<MݯiAF<@@#ߛd$q@1 qJCF!&sdT>צ $چJ* [G-IX~R!TP][8@DCɷ!w>C- db|y8^56#5DDaL@rGGLϽ$!5P(5ݣ!Dڅ1+!Ү]+X2MhSLEX'}ZJ8ޒQUޑUF%Ap0fAl"CRobFrIy1\_>M;Ő~׵Z"9]Եk-SXPTHUUBQ[Tbuw` Y ƃ1adt_jlk)8Ƣ:rCrFcyQ.cإ4Ĺ,miaw--A6-iflTwmfLpƤB!j|H~YdM$NSжϴf[u[ 6nH*e> O |eHpg>4煅2U7]*g0/y4ͅCN~gY^6Ձ~ D^H g!Vhy եGh~~I@'` HoBآӪVu+׮^ +6dqP0 Wڟ ZL\liG>Z4mޔҘjpu=_r3z5֮_>AcӴ"!<Uo߼{1DI}5Z   wE:GB埒J'=SJr9>uN!Dyd[t^m\Q}! w]D1]zyG\7DM|4 e3^)E1•e =C 4PiPАO@A:$%K*C[ `i3Xف yP ddT1ФlBEOa`T}$BbE5)V!fDv4u#*:wx:n Qs5*U ]Hr10@ KlB 0,OjJ, ԂA'B 0+f\7 @^U?~cbQ>确; Ӫ= |0w`K(-PFN"u?OUĐ?zZ8`Å>0S% XƵ*KK5jQ,HL#M \xF,$xyfA2̈1zЈ5[Xs$nau1ZUIjI_2ڋ}RZ8+6Il[,h3=,E4Q.Z:$7jc^ZRZ8/ICJA8m]3Ƀ|[K7MuM -MjS䤧%H(%yX*#zr(A jЃ"4ܴEUğ EJыb4(G%ЫDUEGjғ4*])XD2)Mkjӄ&N{ӟ5ɩPӢ"5J]NǵoL}Qjիba bgmPT tZ`^uYUnL|zI>dDU'Z[$$eGU ,a kX/ke-9iP!j]Lq,U^\iل+e& `C)?-o{HRȢ I5mͤ*徊hlZqIJ7!O[fMo|[׿淾٭zző=H MEvP;Bhݓ; &鐑CۼzN1p"P.@0;l&dH%^B` KsX t?Cϗ vbxԊB2#ĿbBl,-?bj*_Jzar)cBi!0)e+Z852X7٪l &|YU;&ܕVƛ; )+S㪡iD2gҚ4VɴKmS i\ )RV:ֲTgR:@ZAvk= 50vn-lb3;sᵯd# . m+V6~ d Ywv R V턺ݭ_d67n#v}|'<U-rRٝks7O9epzoyj|8s|,9_zX 8_|3:mɱn{@3>W=NG{{G'_Wi'!;K\? ooG<}',cT&'1yT֗6ZŐW8ӐAZ~|mוOU#9:cM,̒x ~%ty @2JZ PK(b~e͍U~)˞""Zd!/#gPة!X) Ub\8:ZDW]?Z@|9Zt8!p,cPZU,bU `$cfrDYE.#D Ge&Ff&cgE`hfJ&ͦbd/apdGfO&AjGRgP%-%RV)I^=D VOKq&# ԉw{jM\fNA4j#;2"86κ4 t$('@F<((h9hbU(Qbi˻4&Duzu~f6Ѡf(}M( 2 D95hiO3(ݸO6W&j6prP %>~ cC28Z>2He#*ZyυUBIePMiQ]:q^)qErmmh NKIAК)0aؙW N*!P'gd^Pt&0$%\V2$UVzTVZ,< Nf8j)+"᣽*(dj鴢̙7EڈMn@`JR6y՜S: A ~kaX^S(cJnav6Ph+h(5g`vrX*vv:,AIQi@#\leml&$쐕,|,j,{Ľ]|,ak΢Fw"{2+̙&gc~g 2ə''"-y}g  *G((rǼd (5ed"Ӄ^cg]i9^{, YAd@ЦkFQ:)mHɼ d׻WU$nA,n{5n  \n$Zɂe-Oh𐋺h8A- Zr^OiejOPZ\.p]퉯h=!u*KJmd#h*@*P$5Vn&.@٦v:Y(ɐ Qj)h. ܪXn#}UXYZ; D":pU7ݙ6J` pkYoo0K[F0eomq\bE :''1qnbqu1]"?]  + & u,R2V1!W` z%&gj2'_UxE%v"kֿ$n#ZXrRJcL"~0M#Wߘ3?h."2)28[՗zopUc#M7ϬR=g{*R5d>5uVuTCuXJ=$\ւ%\ (MkZcU[F+Ytjo2jUW^V/00Qj\$GdPX50R3PXscwi 77sTo+'a9vo6~9/}r5<մG׵H3X.W|uqsSeE4@?̳au?F|5wSaY|pwCQs?rt[b_bWw!'ww ;݋?G~X=!CUx0]fw\t4j/5MtT}xb|xp+O;s{݊D3U[5˂i5O /Y36t 8+2vC JyRmq{ ^C#2_WԂzg~I}R625-7e-~hѢՕZ y"HykuJfSv"rAִׄhZbr(-lv 1e`6|l !k60`"CzT nF=a*j澧sζڶF3ҍm6nzx纮Ɛbr 0Xip{SA0 1WBxIB8Pwoz|˃ę[@ɵֳ'ԣ >~}ijԭ+&]8A4&uJ[[]nʸ~CqebM݌_9*#! > 2O:xIbe8e 5^ծRUbh LʹF" i}b͵Vj%$ܐ=)R̠C𫪮C*`(a  K0+Q,kIPE K<2h.gm|8圓NHŶ2h2Tnu*COBQFQS+8ej: ,ڲ.s4VWTWk!CYuݕ^}i;7%II-0#10(2i mdž5(Y@0Lghpb)UBW \4$)|@%`jSC^~x;_zU)`^)U%hKM>{8/UߌXW YrI%_ޙ}hU]9?-d~ꨥTV-i.?Xs>|6ANXӾ3d\s(X'ꈬWI BЅ !8Ȝ܅,GHGǾ.z=I; 0 ŅxdRpSZfQk >-~ +5/1 < h "U o$8x T {R4r0r d,y Jar$<&2e|`,fk{C0nA"⎷h=j.4aL:)JTH&NщW!}5%X Ks(+⦀XG; y`UE#LyER xrO\"jF"L HFTOlx͉9 ؙwwT*Vą .h嗪hSQzp6 t$Vj$G'pRZьR%nL#YMo,+d-_i8!K6ҮP!\W;YtԺ@8Tdf0%]TфS(?C]'qLM^by.ݎlDuһT/)UJUQHZr9N=ވR?^R0 IU*zq:[TZU]Ŕ_+=eQXQ~a=Ow5nCH6لR| P!>Iн!TZXÖqK՟H'r8@?-)fzbֳVsqmIÞTS]Ln>-dAa#`F'j(ZԴpD1XKyʘ3B^4_[TV=uV~[%r"17 Un=YwQK*S3G-=h)V VUj 2^A6Modk`XlF"`Qki\⪘ii> b& \dand'獺W\e+mǣ<-0 msW-vj], Rq\/e67FY/1)27!erβϟI8Kcs,*gOϙ΋}$ Hf #GxQ&&> *v}CuA =R) I%˄ͯ~_fcy٦ik+58$|:K}P,Z\! [&X.4 ˞3rB.) ^ЏaaFmrYVWg.՝,VG`gI# q{Ph܋Y:^wޢ-V`]W/t82K(Hd?$e3e'rj?b&j@AtAS,!B@/:; oB;N.T"sBӆC=DD!4jJD_TDRt!Tx\FoijSqlG@RAGHw>%E7=IO=37HJ@ҀJ'vsE٫ILFTMAM+TMfB†F4N"|JJP5FKK` Q#&F%j9 u UR%@Ԫ4uSu34@5Tu3ICTON7疔ZUߴ@0hVwW{WXFF-JWIXY4BZuYIYGKtSZoPkv[{[FWµIUN#C&u7'355'9ӕaֵ]kLv"V_|aoas_@"V``{]!06D&6"D7H$LbSb;eBeMeϕfkfogsVgwg{gɸ@ $c A a`a"0ivC$ Jatkq jh`mRlkVjQ6N^ !lSoʡ og 0h;$4 " 7"wts6o94Ans1o pWfyLr3 @m q7lrYiIvM^ Awm"r~7s7(~7vg7qGl( W&Dx3z{wd wwɷ!zwywmo}im674W|/zeWu'z|x[k07|w|fue7i1jݗx8"RAtwlmb6z7U|x&7]37!_\pw"Kj"RX{ dMxz"NUXS{qx{ևoփa4L |x뤉#$i5֌uiyAWo67Kw؀;Ѷhڦs)Xkx~"CkY&~sgb u"L!V2 !(,''''''''''))++++++++++++,,,,,,,,..11111111112121212121N+  !""¯(˚8ϒ@͑Aҏ?$~~~ ~ ~ ~ ~ } }}} } } | { z y x u qmlkk l lm m m m m j [UTTTTTTTSRQPPMJIIIIIIIHGE=7555557<@HLOOPPP N G&>7,9{CpOlTkEk jgRHD'AD5((  !"#"#"&!1 Zdeee\ >-220303.4*7%;H ]gl qx&:ABBC8D@DEF=I&[ ilmmq .;ABCGJNVbkntźӴtٳomllnxdžϐББђڜ5h*\ȰÇ*+ŋ.ژGFxHɓ(S\ɲ˗0cʜI͛ YrbE)7 1HH*]ʴӧPJ:tRV! ͪ(ׯ`ÊKٳ$u֬^ʝKݻx{-ڷVLÈTYS3L˘QͬбYR%sMzQ'\tTѪc˞MvͨYt}4^|m[6p }_2ӺY R94OHyi5NN?Nݤ(Ox>qu^d| ށ&zi6{Qv !md$}D'#*L58ZtxhT(`7av>V=ԣ ,6MLfcu:֐'Ai _%ɥmCE'i_H2&K>i@Eٔ*}Yk~ft#Uyd^|.XdAJxfn& jGʇ ! 'i!`VūfG$ dznyV.tcjvZ ٴPTkdvP+Fj2[hkb[!-:)ېn>zE['A> eGв(AfчB riAi'+y 3p4qGQie|= Z87?ښP43Djx tB7Zڐ)vM=3mf+Z}6;j%)vp ,@74ݔhw) AQHs5o3& _ܘǮ`òtK[C$:mvzjypzUK{D9/>g++yVferzIHoͷ?ͷ۷} ` x!Rx;9031V s(bIx1p/aRH=ըGȬ0j~.7-TlVAaJAC W 36 Gr DZMrCnn?; 12zI.[U ʚ#0Z銀MkȾp1-^H<*FZ9 򄮭j %2ftΉ#HNj OBNIEQd#GH-2I- Ck^#K`]ZK$ G=,$Ti $G "\rVn%)8ǖ][VNb؄=GBtRf'yљiȀXJn (t͈u|$p:bg,+Fv2 UTH'ECJ-,¨QzטHhVѪ UY&SxE{>ѽ]:M;'xN@W0xCN6KZ F=#DK%//pfėIs_跇 )ccgj .CuT|]7qS4ur"9yn,&z([I3r"szTb|hs~wIat< V}aP`^bDnE|޵SFjq:.SG'0+)rh1^]Y1)H\,'7z/2%&tvgP5[7ulUy%GhF"+NTv6&Fh8lGK !.U` Xccs[bXNZ7mr;U3H]:(y|ʧVeioPR}6e-#MC8VdȈhA7/xa.Ƙm|e ̧q׉vNJ*6#4xxq1{dJthxeD]ujh~3J42'IQvM􊧈ZB*x~xw7Xg |V9)b)I[馍f I#R(cȑYi樎g{Qe%0WC?$p5W9|%j]U?rȩR.9i %%ڑHCY: |/z jӕ,Dxjw'):S eSszH@t&NڟКzڂ$يg3xqi;:VX&rT@i:Mw^@zU$ir`c:yXQ?)V@se1Vr2? @y1hl{T`S6:x":qثBrڮ. WK k8 u-Ka,.dA:"ETc.:9Q@ktVV곤7*f,rk*P4Euu(뷥&=+{9QeB+)hdJ=۬up#WFBu izkZ$;1a W%Y78W@";Kza嶛aVFZWʁ:N+V{K? xXiax`UےL( &Bv! I"Y Կ.L: +'K8H2[!+PSn`i\yDn.t^z d{5[HYÔa=l@ȷ^ɦs8*Đ\Paы7|t+ "*jCU9Wv'ni}0ǛS\!J;9`ZJp 踋!ĝ+لC q۹L30"ƃ!+lIˋtV<Fw8l$S)īƖʻ;U+I8,{"Lܗw pJص9̕ J>˷y;zI;#MVbLC48WI+ \ Qɡzl;\"kѶu*3_j |!iѺS2׭K ]uςCQ@P-{ʹ¼Y}\BK -nA >KHbHi"ZH)n\EKͽymjZ| MdlX\J֌}D=H] 4w-f6}\}(t ݾr }zHD[ۄ ?ZbBcg۟=mΓBy?LC|ܣ\̪x,f*$"ЀA9Md,1-7/mV>KT*̢tCuKݑDs mSj{$1^zɲnΘܸ 1-J$ߛgڤDʭ=a}%bCE_On2] RHֆ KnG Ag*}'+_ .>q?~Ҭʒn!8Mߦ7rN> 2.^s vj /%PMPצ-F3? Mj/a}Ns<=qpn~&D<ڭ7df&=r?v /^iC%9NRK"MVO_)>u HQLNo4F/*lt1D.%zCG&pA@D(^>QD .ˆ'\E h92ls1㢑[JG gI C*9RM>UTUUEUE-\؊.l'|p.DK#<ň O1]SԺQg"IbL#J̕+1K9u'f4\Zlڵm jU-+i*m.Dž "+1nQ~ӌŬQ Nw޻]uw> j8ʼnpOi/@$c @:NLܪ*0ԓR= 7 j> q+%((sO )"\L&lC8B(0tI'2Jr)#-J .-{=B>ث1 .2E0SIe-hĤp)3iѕ̵; U`S^4lؖ3{vVmk^'"[ =]b})CVѡ<]zsӥى4>2!̬ :vb!V._8j%3` `ymdaM!aWT_Mڨ[Ǡ UآQ:R %Ýq)%o[~K \'WUHukRgS1]W?^ NT0ŕeq'^Ɂ>ʙT׵d~H^ӭ)MJﮢzgtSjḖ&kYQf6Lt_TJowAA.S@*0n̞T`>BQ,4{A&2?*3m!g4iYiZ*vfTe1;vT%\@!9!J*??C)S]E,q~no.SklfVyP\1S*ul =SLGIJOW+х |M'AZRTE@]ϭG +%I.KCϭR *][MS56 gqm ]Wq775fV#iw?Z AXymW_$gkl58LV\d_1s_x"B05*P* *DfSa{%ٵW: PAGNsLM $ԕ\gúfpSREJ_i+A@LC(?[=<2:,D=tEÁ@DC4DDd,꒘*B `FK6KZ>!P= ?i-UK"3Ik>>kJC2;{oXC@D@hB[<؛B*ļ( F0F"3Fһe\ r s:KwB V 0= BpthG HB [TDTv]l!DGKTlGj#ܚ3<k,1ۣ" ,I48?u13ܡsK2L8=CVS˲Ùtј8F4Jɲ/H|D SA9x!)sCĭD9E컎D|)@ѱ"4<44)IZ҂KJFŨ[E;e})yIV0NM )Ȩ URʓo%ثtK0y2 OS`/T.,@D$2<ڿP+ؓ,[SمNXsU=NsJC\۷-TFYl=0ED٥}Z!5ruAϣ[7wV9-R4>( W}ՎD$8Cu[GX1w}Ud;Xq k׈}͑35f{ɵ BDN۩[ZM5!u-e%hyN12s܉Wܣ=vd3_[[қK Y!ݟ6TWVI=N\lEʱbYٺIޙݒ} ڡТEڶ|Z!ޒD7"Mݜer_T4ŕl1۳Mixfm{$_\ۿa`y`u^ F]vyW=UO v]I5ՖrU{]=Ia_?mOZ֠`->c= F4;!Z$Ԕ?*;4ƐV,0-Dc(|]_983cZXm8^bmb%U;ֻ(^;Zj_y=aI53aԈuY68&JF⩱AN>˺%Qp %5dGYk+[ʇZ:#]c]'^W%I? e96C]Q ]f\!ȾK]JK.4nhsNZy)fPb`2 R>=v P`sYESL2-v!g/݀`X]J`c#Hzh@R!A{ {׈)gbFv(hveȤUZ.Rf& g6eΈ6襁ОV=d4W0ԃ) mjjї£]kTN4"k׈rą`nz延ռ̩D™n`͝þA.F _XqFE6lXl&2Eq6mhy,kVx>zF;&^꽞nȢ~_]k9QY=^f.|2.#i;|Hv.m0o~ FlYaW/>տg pXb4k'FV]k&ZCnzlFEn ܞ f&qf֊N4$a/alж=0W vo ֖.P춈V޴SS^, )W`+͖NYs )ňu tJgf8mYhZKr=w[>bG$K4r=9Is o%_tTt.u/ FFO6͈\H`|ZY IaWS.^sR'L-Oc _k'*ލ1&&p/,3wOG[Eh.b+3$.*oox7S\{' ixSqL.`tpgtLQx0nz8@WngJwAh7sxұhkt`1H_JrbgFz(K!mow\09g&'Vuu{314ߴ⠧x{$Xa F 1\|)DEoL&J7Yg/|AfIzcݥ=YrJK|I`7ɧ.zQtL#|An67gNrZI|.|'䠖2T†'Rh"ƌ7r#Ȑ"G,i$ʔ#P%̘E50 Pxtr%Ln4xP ÇO^ɈH fΟUQZ9ĊL >VJHBF'O#"F(ǭuNU+o.l0Ċ61E65}ˊ~G:nn4jh!hFJ-Or9V~ekB5KgzL79ҧSnzJ͛v*&ƿZ^5ܦa<~x+_;3hĉ^M[p)D9 J8F R(SpY[סhSjFMg^%]1}F]HP]+zT@]<yId QJ9%UV$@YxcoYzQp(8fYPak!4L)&Ef_oMuesFr>ܓ|j9)Z*O^ꢣJz%#PV1jtpL:}me$(pεr 靓i)Z{-I,G\,̚ʡlv$Q yn&GRfkL:~u#}zoC2gVZ$) ;0v<@X\g  qd5Qp|Qr#3 Cx%ޚl; T[Tqb1I+tLA-Lĥi_V' OTGTǾ.tvHBg~+XuS&3k5X n2\2ږ%xnwƗj[ltzN]DژJ 1/6酨d}83NS԰Ւ9Z;%_f DD.TًJ4cN`-\wL )< ) ?I␇1OxyֱԹ= z)Z:=ЭtK,-i6p+d[~&O"zA6:ehb0#".U% %IfSldD#rHC/{ѥ2BJ MSQ'R4gҋ4'SiC(=F8HBp N\R`FhSW<xQR;E,ݧK.6vJFW#+9I R wF=*`ٽ[z/BpYWM,LX4Zs!DJdb+0QrŨ/ERNM[np&-f+*2l@Cm{3uX_e[$`=^k.VM\U;@Pp lϫ]m RUL@G44|t1bW~"}ȷ֧n6*<»V61Ag<.X .MdJ8 ')ù MF8Ck' .>ų9uK42Ӭ%x>.w!d9pH|&(V RJ>"Wft̯-$[jV3k*tcugC!Y\lnIQ+Lz0ѝL1\ Uf1gƆ/ & /!V_FYOJiV WpV@Ħ@f*YݥEÆ>7G!eE'm)Fu CC!#oȢsD0p 1<&vMw g:kw59KVDdh[7D,Q(鞨\< qم=89rla4gpK͔#SUm4N17u3(?j~s*3z~3$a-oy57Bk(phtd'Pyf^o{w\v4o='? wD5|5j<3[S؟Q&bo;Lq7mz Q~.fK|uuˋo\?א2</%tH?Q8h@@-ьB(Ç~&EQ5MD=_rx@}ldΈՕHDk2C!D+l ڟ&uU)ߞ IDAԵI |JɅ@^RŎڡ Fu8@47(7ؠ`z(M#F2!H] ̜mDaB^I!!!v!#nDa!`-"0^I2Xe!M!DANtGqT!r\!`#"v<D":5a%_a"a}")鹅|3e͆eNM2,&H"3";n 0CDc"##f#ey-9I( 6E}ƶXu&ʥI!9b;N$D"$#; p6JcQ*V"5F}֙y: EXdv2NF3~:T)"4ZI#h$Ed`aE|Ŷ(P#\YQ$Mfph`9cW"9Z"~H$/ d[%eGvOaVpex%J% *ɍK~O^ V7>T8."VhHgZ `R`O&Ie^!4%ecA]Z+6&BB\QTugg҄榌fi^LZDb~D^bCJRF$a8į ĥpgqeatg5)kIN`GD `rۥ_s'.٣f 3:%'Qsf"}A<fYew&]@xFgX& c ` ` R(XNb(_yUʧfG舒(|c⵨^&vݏc"獎F$a=`.Ӎ(iHYfxIPᘁKztBWs:s$߸xڸHx,%Wqo|rs3`ӌ6W9Ek:Fhhto 'A Cy8kwCtH\;]z4;*F`7e9_0nZ.2H4zG8?l9F9+H;mt L~E(r;PZfĬoDWO{]F.wSH|cv{/G?sĘwK'xL[511v"b){O7;ɼ a$z7RӁEt Ǫo<&U89S9=HcvwqC.t >7DnOD/x&}Dc>k;rG@Cq=}z'Ɂ3DrC1K}g7tc3D+Qz0Dwfy{7@,0`A5h0Ƌ/ 8E1fXcGA9dI'QTiRƕ5ntEjSb̌8EM 2l0Łcxa-/Zb%BtT0QoAiE%-P]r _ [,uϟp!Gyy ?6 5n}{%gn,~;|qghϮK14a*p{jݺs#|[" 2ξ/ d* 4 #,h>2)gQy3ޚE3OE3o#ͦ3ʡ;H RLLlܫ0-K0Q CM?K:_!2D??C2kv%tQFh^&I9 \sT]$-N=hrڒPLa5MV4&Y0)޸XS".Bg~\ov"vVCm'#O(ETSbr2 vB:j,2sF92Xِ>;' ʱg:kd[o`Ufy aFAkӉg{h\UJ-WmȽ|!˒*iRrDu=unbc -X^xnet9puص}G>8^]\Ż\zp C'^Nn_ZIzȏ=67@w@oH4<9'#T~põ%K:w>U-M{v6I5S J;"lw嬣`";!HvC%.Q2#*Cmz"M%F6KBNI1q$rT-1v+q h<:./q@>)o"B4IyB;  qe>4Pš,ҝ KX#91 M TI $⒙ʹLiLa;IIIr#L~93>s--Hpu"9Yl$آI=f.c7eV25U,ڇ J&&eU{ vR;(HY!ݦyi 5+UDE-(!n^%G*OIM,TT=u('C(9M(IRvo(B:*W2%AJ 1F<ڤ!IDk9Pt,4@A̵OyTAkG⚳15A>|Q*BhvY*YQ{ƽTuk j<+C ٓ)=,ET^`=OPk΂T0 sOJU}XlmCVT i*C wFyE5QT.)NЀ7.FEumMMrO+fG$I~N@:Ӑ^n=e7~h-0x;HF?-oK\2Ե v}P^V".ݲbLX pLrBxAlf$kr:+9sibHjk c9GpfVM ]B05byL%HXcc2yXS:huSO4If&jAzH̾ZcQ*#`^Aw AR ; {nP#aC7ᑺR|%U#j3'.[9}.zc7۞c{A؈ߤIZ%" Co , .8|.,~ jo̊hIF\\E-LP3= #ot s4n"b.jʢ 8-Iȝ0T.DV/P^ (i$Np M&mC\0N85 $H ܼn@BH8ϧLo=)>KKd wA 1oմId#9^ 2-.a.1BQ ER(R0ESzk+Mџo81Kb)h[D2V[0«D I ' I bZ!ѱ+"q'IB"veVDŽ݆!J^#b܌ǑXzHLR#'O$ib8q\erP>Fky.C̾,r)#)+"V+=H#n5,O?d,0wQ %+f;\#B;ڲ?M*p$d;//i#2fry  G0Dcb` "oR}4o]o5  %"*Q^8r*)ky&!q3qd6K騑.f*p“Br+,oۊ0s09o!;N1.r*)7ٳ=ۯ(S7}nbM Gt*' 1&9O k9-2I<?c<#7#rr1CF b8IK?hK^b4G6K-G[G%AII:s$,;,(,5s1%o$͢G'tR%L+Q`As4 QO,99U}q4A4uN39UHOJ1Q͐QMRr oDʹS}3IeY5 X[NG'BZrouqTV=H 9*')jضcH}UO ^XENZMA"L7 M*fFups&.]fb:M Rc^M_?i/SOKO^1eɺ,ove jf1#bFR4N[sR?OiQH6o_Kn-_}? Y/o)O5VOQP]BgaH.J"hKzB r t9"*7woqZ57% )jж7 ;?۝C{UXf%?I5MZY;#7`bZ™~eVsK{;ۑ_kzS;֭N[#RśګdrG#b.p#,;黾'-Z{%D[{dyK܎x7H(Uj\)ht`5DŁi3[Eܾj _+B{ ĵn$[k:(tbŚhQݛ0W*V 7ġ-<%4`刪՗ ɸ,2m¯}\y9B]l?V6܆|_Sb_vcF՜m|a28_J{q…O•P;:?< Gw証ʡ}EԣK活o=k(°uv=,YQ^J&5:܇1(ոT|^O˛QWYI4 \Z腼4B妃}`ȿkSYժzp0*5[;'S~e}|襡#+}\*Tl:<ʭq+J^3ُU7{zA*nf#jy]3]}/H߭~Ϗ^( <;~nZ݊HپY vH_RR."9ta~n0ρ[ގ~ųg[_;aNywMXN>o.b9ћӇ8{XOS1o_*ecYKA˒GNrϊk.4[o>۹)?F{>?ϧDb <0ᢅ :4HĉFbZd4装%=~L'Ft22tyŋx"-a !Q &yQ҇M'E3֭Z]m#cөLPG"[, b$7r8޽| 8 xw&٠dJ/ZN5$v5/Â6hEC'ڤSC2Pl9c}r!ݣh1htjk(~sn>pH 1ܻ{>x%<`ȴ%~5k?ʿXzDSP MPHɖP{T)iBai9LAWֽ_EQCiEa.c2E^b,ݍwMGYVVŐ}Qyc N[xЅ3PL_-1b6GS1Te'~gzɧ_5r~+=՛qwugB_ax ZTAlyT}d99L\dV jbV~EzjK,n(El_f[n~v'Ifo:iAaJV$'DJUެ[,lTzkAֹ6pp0 0_bZg6$a UR&J[]^)+"v*+| ceQ"f4/g=N:MAOC )O=B6IP*8tvA4P]6V{mӿ1 W^OZ/s鯔';[lvZ]E{R28:Y9z(ŗxJQFz/^-8BO3KWk0!G4A=E0EX6~'PSt|Ao<ۧx??L%fXV&2p ZeV%5Hi1T$<5-")G{b;6Z !aw?-{ qE(ԓZ49i8G0щ\>$Ci1pj6/1bqR v"-TiExɆZ&?gi#eTv%l.ar,ILxeLa ͈+ -"C:4ට5}DN%ݸVz(L d4xAQ/ۣ3$n 6'.*DPFkLd*[mRa#G&Ey3Md&ɝOpZ[Dk4SkUb;DB.JQ)cLB˧a[HW}~ihN5N.լI=j ^$*T ¥urT q)#ܩJh,L MTQAlKG$zt0R1&BC5P$LKk՘4H\w;;Ec7}Tpvn6[QΑފlBH 15zO4. aհ#[٨V= @d7ZV .&>ukrĩӬ o\Ma(/X75-P9t(xr5b<#K+8lRO0ژHLLHuMqIzܹ=Mn/rh};vo#<OO6eS#9E:W!Ty3-ƶ!&lI:骒3 (grÈqq[(dM 's &F_KR";X8TmU9.!72T1Vʄ., SpAd' :)zL/4U'Av-F3RAa3SU-2Rws$+0q2L \ ʺWhf>)BКΊӳH9/ ~H]iNsE#N"r'BpWltS91Փ`<ڲG1dA_[3b|ośA0VoYWǐq bKn6a5 խ%p+]2LFb=fCa=1)C\R%{o[<镕;v?!zח=t(z`tzN9ArϏ.V`EdA4hE߄9r]46<@|L|Z:'&ges6.sӛ~d^{5E$0̠C?xD\Db$>8J\cD>E;\ˇVF:6c}}b2[%v/T'D*w7m3T06~7'iG3pDtv/FnAufe @45fJ҃ 6QjJLENCPbCdteLQ\ALX<˔QRSzMH0$7o¦H>eĄso3w;_ffBjm+g1diaq4$FPxaJ 7X0LqH{W3R QDDLKq腾LfLD˗PUT<|R7uZf#q8%;#N(~0F^jFnF8Iz/~8r芺Qjk|5UW=dm|BpPfc}e7>7CLAXjCX!G[rpx$hvjY(xZr9&4CtU;y:TD-(3utcZkRB)?*ojOEq9T_=ZNo(9M5,W~q¥b0 %TmfY3ripa+sD\"zߗOHz3ը,x0щFIaڤn Rk٩:,VL х9`8LX8>̚bg|As9Ժ߃Ygu`UR!gru_Lzpq^vIw3A8*GJz0Ak[AQ1ɦ(>jɪzQ6c]{wѓ>3\J<ѓ?#{ |"Q"Qv×~)*11H~MrhLcj9KT[ §C Ǻ[ EVCAiEYCJJlttJ|[ހ =Rt\kL#VLy]٦}z8}EO s.2h+TbKq^ "68 eGRVC8>Y A<րuS?a>lQh5DK;{!I۸hTվ*Ԯ::ۉK,wxzhBhʺݩZ{aRL~vV Pv aLeQ}k< ,bL¢dC>#A>櫓T+E\VOK9;`AKj1YX!>#G@/qIc2I H&f 2h B' ٬;,8&#S9cEs7*Q1mLoyza4y*3Q ϔ39鄳Nh-}h,+Lɰ2JJgĔܯZk7rs g5$=uYZ.ջ%Wͽ:0ak9jY>mgSLc}/J,rR] &/ś,Շ%[  .Pkgjx7? ͂q+WG-weՙ-ZҽIcو-N!leMeOC;SkGͨ'=\q׉2SMNb=<ѱR";,'ek!h d3 _G"ʝݬe͢ D-k2I 5uVX*2>؃\eۜ&W--Mѝovj1 \P|I5n3\P`&Sз8 d}փmg؂-m- +e1%_c8.X?C }WTH^>5%g閅V޳ ͈Q繕{%3JЂB*_rs}ƪ Uk΍=O-%a0\UC>d+W`ʐ 'Zo5m1ޛnRoZBTѴuAOloR-\lAΪW=~r=*9]Z\~Ǚp,zN};<8D\ 3?ɓPQ$"Uл +F!Tg-u]y(4q)hnWi+0zI3lȎ=o^fR"cM:9Q^,$r}'Qcj]rb~{H%ACؼI~خ-hb)Rg'y%ȆԮG.inň,z~oZ@=QNiҡ+32ȿetxܙo0 j XA .$(د }ˆ xŋE.dɒ#O.=Nq9ZV' "3>%Os*Ÿ p']K5}UzQ%Vڃ~_WK6+e􋱺 hc٤Z\`Yȣ,@]\%; pKv2u*Dž:.Zϊִȭp:k [z%f])8TB3hsa}YhX!YcQHo$tA@o65jI}px#J8Wd@r4zv.+ͮGƙسi@:ZҼ%SlQ:=MQZծm80c<m(qy R92I:hBЅi*)2׸uk3}^!EEϽp@)鎋Q+|:R*P[˲nu|x&JJ(SΖa6V!CgKr.ɻ`n`X5wuPӑd '`f`܏n7xܭoɋƓ`$E~(jо'Rd?kp?+?Y8:qWӻA?%'ˣ+Ӏ$ ھlA\[#/=?1T_:<(`- 3 N4Ȕ"3l;:M )/;>+KK`gz>PaqAKT&!w!{"R"Er1MRB<1K.*N ב8;<9*Ң#?V@TS2!D$̚FCZŒf>@F@| D47Ft勾h4 1KC9 DD`Z@0F(ǚ3ǯҭm@xGH ~G h0@G>BG|lI!';r@:G(0G4IሪT4񉑼p0Z q1kij:J<)J, #sz@#Jᐣ̱ @x KGuTDJA4ɰ|L\C,|F{:IPSPk4nKTOEP>dd$ LM Ň cLwĂMjFr/:d4߻K@odI &D\,bNZ}:ϰ3ܶtɺG?; Ͻ8΃u*KdIC|* 4LqO!!N2Q2iEAQ(SA96SQO\"mrYQ@Q99Y3I_*<#L3KuL9L:͹ԕj /XRҦBAR5\:25ѢSk5"]+*XK9hYBU?[]C}"> 6rp#t2i{z)/tLCyR雌ͼ++=FtP)0- z.\Jt@K%ElîN<})Ö%V{n9 (S?GXs59+Wc?S%. eȑT9\+,|]5UBK77\4 f@y{ӂmOgMN mV Vl@zغ VKd^}(ǀ5a?$B*&d0pȎݥ ^VfRXNnދ'KAe.PGƞظ ȳj:V[ jvfehfv)n.hXVDvLsHgxf`JƺF$z;Y̑bSuT>-ր>hf+ fbeis~t4vnnf\7$G{F88刘>G4ʴyiPsp]ЄĞe * j^vh_jXjs TZiZѫ6f$243RwƒDYZ8!2 -"'C$}i$)SQIH5IgHN!HP4(JV6JdVE/CE".cWe+6_Y;iSumH}4Th UjR%joelnmmMk/}DFr7FjKk-kcei$0aihj~B*ܾzj5k%pu5iyzzq[oБ|}͹6jOcYul0kvYϟ4?&'\@^?(= _2]S0d?e/_h/=c4m3 rE6J/mƊknW`)bk -ɞwW[ZuXwu1'|SP~šQn"E9)33ag-%~&x&zwxvǰwFnpOoJ7tgjo!{EzY/zȿ Wvz t$b &mu Mgt߮rrFt˩*qE0!΍/g9SrbWчH!oW}mPgG=`Y}8|*C85# 矘R <-4 Lp!E21$bLBc(r&ѰqɈ&?r>XҒ̍; *t(ѢF"Mt)ӦMgtaOS*KC9H2EʫQY\Y*ZaᒱJפKSmЛC楹pE:lSq]uJ6c ռ1ҦONzR͊f3V"UT_&0\S/Bک<1v,]Ke}y U7y-X/ŜMR_K?PrX n @E^DE~X74N!:8.Փd=БN)$loȔ4cG nBabvsveFI.&WEu[#–bVRCɉ28lI>8NDI) T3K3N-qh ,L!ʌh:h}Rkiof*EʩicymgDb}ef.Cxe^踍ۮFy#),BJ{oM%9)[Ѵ5(6vj{>n|MRzFkÒ! dWH)YP߉4BUj3d:.2G#P=k5L eSoc? U u4z7G)K=m}W>q"_cH&lMOO=0ױ#T): wY"$9)KPKS@rzH@M)~ԧЩc,RP ZUr! DCG5MɫIR"HPB6BRzxDȳ"–qKa 3tX$=?hŅNb ?.e~kQ(^AM@;.4$BEj$esoL-I@)6g" [WbDˋ#JІJ iXMeol*r> .G`KBt(=уp)9 o3F#obCKJ˙M[ZEy|עK Eee4Ű%S!6HnW$'Gs3X_&+XR224w͏<'$|fs-DJZP$yXZfFN0(EjWt:SqD}hJzU!rLCClƅ|?x /7 ɑS=*]ڨqRjKzZgTK !})%5`Jԫ4eHXɟʔQ(qmyvv4!>)mHԚThCґZjU3t5hjx(_ nyڡM!FsnTs -9ס'xTfcJVN +BDI20PQBbYӳ%-H1SU:`&֣(0G@8B@0%UR Y&TJժZXJI ^^w9fj0*-z嬪xdZ%%;Aj@R/a_9(C5H!DlPsՏxi`~K#\u}hV3CӀD1M`?*2?9 b"6tqT4Y1w )Zyz䵒[2+3/i*oY$>u{ݔ1KMYT kӆc';6VR6a+@0 ~ CHEWD8vDp&Zh%Z7Cj{5jJ?d.Dp1:KT!!ְ–!͐͞!`UB[ԥtJ!&I)FĶn6y_@ܫw ~4&n%Z׺X/Ζ }::9#!mRvv1$4,~ѭa\IT~kϸˮU [͐Ly ^5ͳ C Jjo():Ü­jv{εvDPBVSȵAGlW b Q#L>?b)9?o=~_ `kVtߥ`:B[%w_E`jҟ%r` 7 Ҡ8״BmInŞZtkn%m!nrɅqI,dC6J ҈i` ހјh@AXX؆JC) ؄ALN!PIIp ЊјP V !z'zYt霃YN^ZN+Yٓ  9@Zr$]&N  F'b5ZcT-@ bYb؁!D7J8K9p%ۨH_N]?d@ $FTU5"J]5FHXBBVm )DYdD+"1QL dJJ(& ]LJiL1ȠY!N H2?8^I:ݍ&F dVjch!_iXa$CЊD%Y^iբB[Kl\Tr aUS5nec:f_PeJ#k0cbff_d3a.&Vjh&,!(fi\fi_' '`ifѦ+滬&ifmZ^'8@pvjdomRnn>Fo&' @p:DUq>'!' )g0'[8gvpg<@pjH9xvQwwExg]Pfz KlE} !LV&y'zd!Bh^tNgp'ņ|Jhz臶Ot$ufRASӹgpTy:~~bD(]h(hSzR璞8!)i )Siy:&g_ȕjQM) URdi}R)=i&^e$+)6i%՟ߙPȚ&E*((>*!j(0*R8Ƈ'Jԁje*ltQ|jhui*jZjh鮺K.>TꪰUzNȫE*+[p*U*Nr^+9vk*k{n*khjlV\^^ҫjk8++QHk:+ r"ME:lFj~+i^AH}PPX*2)u4,>.6缺lRT+znwkn`G~&lΦ -}-Pæv.5<|DOLmk2f- nQ`Ur"͞-.՞R˾m -t||Nfl"^ᒦѮlB):bfՂ餦TBi¬w,xݎ-˸n_6:^^έV.!-e֮H.®n. /.|mKnBW 5l$/I,BD^ oB:p(_X72e1~dn|vfj.,mƙ9)!UBxI9S 6iRJIJgndƂiy)EW)YS".BH*V/S0Fb\"0EJ Ռxq,Bx6qJ BXbu㯙Cn塳 F 9Q SkgpE^#\BA5x%t$S\rL5/? /0۪0!OpZڑ%2Bْܤ1qJQ'E0ٍ( P4k!-ű+53P0I_CY]>MXB\BIG%Lsi?cNT/k,rFTk0ubjq@;@HAAcDB'0zEC 2^s6VJ4.t0Z3"gGJ`LEf4sJWN'OK)RkFk5szui7s8!X^U緬s{o8*ǥw5rOs"K =]!QwC ^=:F {8}K'uV3itOsWZ%%\<9eGE/%<[Z=fugz64w+uhJx}_9L7ntq'_{*^'pi#Ĝc-G4]/*k&9#cG;ftjrsz:ki$7C,̭MkiƫwgjXu*1HDU^%?Z5W+Uio8H:;J'B?vDv4)Q0C+0pv`".dsQlTƷo:"6kWXQ0Kpöڹ6k/kC(?@c!oqг7hc=w<ykxP$sk7Wx8?mPދKdwJ=B#D=V{E踜!scǸ3x߯¯g8WYes z1{9Su=2֕>;c觰:>)ʩ>|j5JĺۺV?^?jdagizp:@Cɦ" 4 ФbD)VxcF9vdH#I4yeJ+YeLE5gĂ9OZgP8w4 :x8jTSVzk֊0vXא;R lZF&]h逃Oֵ{o^ )X0DuX&WT.HYǓ;mp@St)wttp= k'Ԁ߸Zq4誇֢f}g~,gАJFmۦ ,4yv۹CP [o4PfnٲZH.; OS f/C"g~ȋo<M<Ū3 ".e׌z<PC80RF9kr"(N2c@*̠5Wp>Sr#L1 s')D ĭD]1<*TOI6,D %HOϢLOAZ@Ё5Xejȿ| P;RgJTatK͜dV<5WDU,_Ul5P5p7;Օ2j@abNz%sEw2ubWVauW=7O~W+uW[m!ޘc J0ݽbb Ǝ]~9Ӡ=pGQD kĘ>3dFƪ/8"UYu樥>6~X08ՠkb[BM7|N8nOfq=6H Cy7f&g#Om4nʵ[zTn ;=-!QB d/64N3輎*)V7^84-{MDK|=9e3ڰ3\:#[ʅጨ>gH)]u!݄3zNߦviþ9iܝ2>/QFLᵈxA SSc\M+ P,YB4yUEl \-֔΅AT`K;md3ƆXE+C"rȟ"{XƻlJJ<#˕`XG;MR]X'KXQՋVxGC*yGvp|+2@!ዙBj71T@n3 f #(QgJA0otVT" Z&Il#(\Yp>:L`3=mkl,9ӝUjnU@k*5trk?2vӛg8;3Ŏ8-.@@ 39kH`(e<5O[j !* 0 A NWS>xtm|E/XGJ A5"ŠF?\%79k{y'΁,3CE&I8Ё{< <%I tYsbSBh"ȓ_ rR|4ANNl"~*hd*n]]k@Mk[8[!Bj4kS0%SivfNvjpgjssmty'2g+wJȔ{K4:nVwJ[P!&C ?j8}650w@X8ƹq2j=cQqdi& c%'x)'IC]NEml3A:fT45Eg>3V|sT]g)twEBa1qw ˌɞ~哈FA{x}iۍJv%z|cC y:%b]]+Y˭dS)'/UN;BfznF+Z M{=1h^[}>_û.mu=Nٲ㛦sT OwTN>j[og7&]j -jP&~?|l}N ,pcl,o&`VFeBm%.n$dJP#sZ.lfPPXJrP2G ijEО (&V(* q&Ͼ@j$zɹ&b 7 E* % lPnfRB  P{ .ˆ>CbJI-? ۊٌ.:(nMmm:npH’h kqdh5-("" xTQ(.b*rNF":Bm3&bjtZ5a/`ĐtΨgp_b*QL&(!'ߎGf4+}"io-"nPQ>,Xk"2'v&G-" 0\/MvϻK(êNЮ$gb/ O'a r&0-lo ;"+O r$#$lf-&쬞2eG +EF+v+G־L,#SV2hS%1Oh(,%42g%o [6n`C5&c 3G.B53?5{7$478d&8^bS;fSEjS,(7;_;ig-3/9E"2=פ l-mm $Ks5@˸اCz< =q` rf03;3S[` iTD Q(d/`003+{"  iDs40+xR%%C‘3%r! TGT+ή~Q~r4:He&LbA 10KWRK41SK,; (DOc4lKxTPQ$P9BH\4Ot@=Q7S 5#Ud DSKTg*TWUQ@U4&\>BUo;HbUCVU"F WrP.4P1viҜULXIL,l$N oԒGQpWʼT!bP XT"ƃ4L'm i2_[g"ĆpB(أ3R0F5΃tQ~%S+v ^^gPA ǹ=#HI2GNcL&By>Yr'BBF ObO5Tveee%D~n6A1.LvLg'\iTykj f$0@sPl1(+):F [G$βz"**Mi1ruTTHgdϥN6[xPCCFJrSqbk֧*)rrؐ)vCjym/qN2H2vA&v Rp *3p7w.M 250K*/r֗Hi0ot7HvMsD(hNCui3ǀW+IpTȷ|/8'(ӷIeKb̂1؄]Qpp#XPc5-jl eG]eG"-pa"J8XEvScWC8 ’X;O W=Cdԇg#7$xc* ǐ&"X}[g 4d0. #"Ҵ6$$hA;W6PU8qћ8n>6>taUMavf+qLy6>cQQ?}cqE=8\"GkXy""2p6}֒Y$h'&HwUq,ni'Tr9jYTzx+ee$h̑JDx->"Ѫ٘՘QRo \oך_bj!Ixy@W"bs5n;n12' rpQ7%[YXw]%!LCK"y5'w5'/&rw|9(z֎VOFtHu5 z$I?biX~,Z%7tGq⏁./ZiM=̤GpNW]]518&8Ɛ"[;FB'[OfdLXo7۴Gּ)ɠzIKcP[`ke}G6V]B{۴1,?o{%<&ۥ"h[j{ਹ3;{[$& D'v̉۽[Pe'Z,۽;C9<&p#߭v][3rd׹5ġAkC\+\hN,+KB{%q=bC ~qUsGdSk]]#~ k5C_}{ o>3ݸ^9[@#TW[>EeN3vm{빞^Z>t?~b,Z~]sX &$7;&8c u}uA>/3_7QE+<ߞ/ɝwJG?wK*@S_3)cIY_A{qsMe#/(dA#8x}'-=c1-_hb'#~]s&0BWL~ C h-A *\ȰÇ -ċb"Ǐ 7jI!s5$m Zӆ} N$Ǚer4H*\` #JHa*j0Ə',ɓ(S\ɲ˗0cʜI͛8vibFwIѣH*]ʴӧPn*ϦTsʵׯ`ÊK6iֲ 2={s+ڷpʝK]l]ۻ La}UxÐ#KL2_ϠCM@㸚鹴װc˖mjĜ5֎h!g;nȓ+_=BnB.H u F޽oWy`\McTk$N^EހhnE\A%ww]Gaxm_C$g@w(gX!@T-H['|#`{%!CBFbL6ڒ_XSrFDP@W8 `a嘂a cКd(x^IYYuɐa^E'vx$6*r.Dc秠w^D?_Yn9Qw-ᐌYQoj\ׯ:&iYn ^ס dN f:u議[U b>ۜ[JtA&覘Nf*Tl0ZJ.*n Ik~ fV(t(gbbKqrN(CpD\% Jk1eQg16j eKL7Ҩx5sUF$SZ:;w`J-9WpS/ÌCWm `JEmТ7 1g9--wV"!(Nr74zo*9B{ Q UϹ.w u/c De$&7 #H dAKTLb?!ϖre\:ӄϑ(H0JaPorJک|0NV,}@2KJg"@!*. D<5@E_Ͱ#rx;`*~qRI.x?I~gI0@nvE,Immo p&-J! ă8K[P~GCP>e5< =ZFC{ޠ>??QFx\__W*{E1Ep^{5S4g%o;ӵG7rbTo1u4f~Kub1|657mGR#[-Ycn@oƀ _T~4;4 14_~цy`ā8|`*fwEqX|=h5cK%rසmGS'f7P3#햄'z g<&jyv?.UׅDEBX5FGf^hlkot5'CZ8(6wOhma=`y&2rfH[RPuz{M%':HdeM'Y7 (̓:[dWv`#X!!B6*(|$,'"VekbHF>(igMxK>(W88y=['aVu"B&xqT '8~Ma38(:3GdDŽ8TJXI1r(y5Ha%'9{ كTMoU2 i7CBɖrHo-6dҚdET-CN4 ': wl0k[*ACCCGeMjձڡBmKEɌ(=v$9a++Fb=; y?{gv.D{0FBߨ$;<J|AWKu ~qG N6 6vڞ.E~G-dǛM )iK[x]lH<4:I߇ʄ.@D J3B"LlTǩ[/{ʑ; 1q\ŸL}ᢔ*Dk iʓQrB3ʧ,:);}¯3* wek%̾2\sTk̜=5bDZ{P̢,~JOPd9.͸[( {n<|Xvju&l μ|\+qf̸  <}aV-!`:3r3z#.#- zv\GY|q&e^|mٗ8](tD8D&9H]3P|˿!FN|(a[\д&sHحIֽؕ5̛mJ&4׉QښɷGڇL2bmmK3C<Ѻ><c݇)Õ-}KĨ'XA%HF:QȬMw,<)kaP}D&1^߱=\ߩj-F@CNub$$]l#0.uaɊ 6  +^O"FCbϩ lgA'#^G*4.s !oTS3)|2.1U7,ӻ޽.|XᯝU#=S}#[]v qqR@fL_>*-A aq7]/Ȃpڅ+|~=KOQߎc*.| j$an7ӧ;T@Vl㰙yLL%8.X؁ݼ }٫<%8+l~`(MAN]Fߝwq m+Qեȩ.<)q舮p ~>׸{ϟ *}쾢.]߻^_ {2ORi#vyu2Q=c]MH!2[3V~ #n#%_ߞv~Cn 3o#(!NZ݀y2sRBBOS%a3 O()oQ0<.MdbY_C6/ʙaյėbl }RvIy m54T +ˍ^򭲳osrI#Y_gnQHtjU+,*0Ro﷬`='aÑAy~;[0a  DPB<|00>T@B #\ aF#(` C,H%&=STPEETRM>JԚQ6`K0)Hh©/`Մ,^IBL $3Ul b!FP XĊ?!=U /4Dg.N FZj֭]}бqbpwA;6sޔ0pV8{4HJe\L۠-o+9a`o-_+M@0@$1z:@pӭ?ೖ ϲ؋3t+$T(>+Jz/Ă:.&Os $H#D2I%9E"lP3,,p8(KC!v`"zjC}ǻƅV;$PCE4L@( 4!ɺ"tpK+d= Q ѻKs ",?bEATW_6G[&D"s2L Nk-NFl2e12Ӌn5*^{7_Jݕ]. }RҭG;S[Uy03bE-+_}Wfe#`#MceN&w1ZL,8!sÎ\7J j- ꭽme&brŧ/Tffu&HLڬQzٖ8iHj^sy5;s7(j4 {tLMMB#L:!((1Ռ;ܩNoYNQ:n΀ΏG>y.԰do6m;pDpY-7Naqcwk+ ~Ҡ1_>~'R(GB'ҋ%=np#H;Nb;8; %^1XG?ЄF \fgD 1A,H[[@1wj`"1 rS![cNE.vs+Y% t AB,RfíxqΔe/+)NF}R؍qtQAg(|yZ:V' G)BtձMZ%ε1!\V掮guR5dii{҇uQMAֶ=OK EݨF0@y.BRՠpSZg~(G99C'ɬyֻ]ZӾu, RhbR7b h겦R*+֝d/x<`Qe ܍k {Ro}+C aTub6#Wx6 .Ua8K]Er7F :a:Z-lCj{ 2V%Y|q2Y#y`:r/0V^'KܼE.4fͤ5%2d7Ib[i_Hv鼀FuA,S}=jix>%%jpR$\2li x{XVu}øЙQSazc~֙yN !}Ebŵ2ġPƷ$_$0is!f ;j𗌌R5Mirw+n|w;0PlE > .4%Ui>Y6 Mt{Pϧx j[bujܜV^f!c5asvgo?;RBG;jW#AO.TF5^ J7.qC<Ȍ=9ii%dk:%4n ab9>5SF_ ye?/iU1cRc-X{Ϭ= ϟWjZp># 3A ch ǛL.8~H@pkHL-Rbk۾56ѐ+?AX[{!;.y캿@)cs%;sj,+X!iл`sf#>h3?b7 ,? J:4bKĕ:G\"?J΁[d;BO <*TF3ũ2$&`+f3?A1>\F4YڻCą2+>dcF*m[f@:IL6PZ/o$Ȉœ8{%<2AB:>-B.0 Bb黆 IơEq,Ȗ\a'I0l\Oᓋ ~hz"4 \*9c(#Ɖ:C,tɩMTFE]se٦q+9^Y mDxZyeVW-V(sE#h)lKLuڹ-J6dӭMֆZ)MX吋jạ(8*K:_̵ Zb5ե=XHeW|Zv3QA3U֟A=\ۀuh3O- 4[:]W1]])/{}0ҁEƚdLUcZ_[5!3^[ UsE4,۷a0 (Q[(Z^D>I_ TI)MQ]^hgݘq8"΀p 8VE`m;l`%]aˈX3}^y Ez[|_z bG"=i]=!G لHHeܢd;ƕ[}(cVD|6+sթ\KcA`4T hKmk&"6I  F͒(YI^,fMlC;`~qTu Qȿ(Q)e4‰zuի#LDU!V[IV^JL`Ccܛ(u)g>Y]Э,PM6L~So1PenvaTcW^pXFN!^HfJXU(ag hv5/z`C*(dN ee1$!/5H+X)7MH"25@1ЄZ8Vx ֬ҙݍ~ȵ8gVꕝ NIٝNh1܋ߵ8 ꢨ0룆 (>^krmkʄj5gk*XOeNqN4>~$şhum;~lv5Ӧn{bU^Vl'.)([V9"7N6^.jc#,َ"~&mТ[깾jw  I #l\ڽ\EݤnonN>sJN3n^XT( -o&R,k z\ +o CJVY_4F /yi] )ev;P9⎾!:paoh-5/2/k_v`"3żpe_z^eVyXOf>hNv狀v[WO^c R0pߌpfjfft zwX/{El;-y=NjV^!̞z6E< tf{.p[{ew3rц8-BY{R_cMvWDžoH/iK`s:Yv |Ŏ'k;|v_|[iuBuv[8{wC6:V`,eV1۔~ ޟp8uG_wL S*(|/* „ XBRpXcG4@b S^@dBD DpO0-j(ҤJ2m)ԨRRjMWRLPGBU6F =[ˉC:LmS_CkQ×XUFAePu!PvDIyz!!8dXz,~K%8B[ X n0Yd0%h$a)@wtfa%x"Yj%XBQ^ыEixXݨQ:gZop"hB蒃%UsLY崠`ؕ&J:)V}9_g$S!=y_SPh$ BЂ%N~P2 ۆUz,*쥒fp1%ukQx))!&4FG"YGaƦJ/l)&fNQa[*EojG .nFdnBJkdlYl21O0bPrYEQR EloI i*lt>jQb_{S2=6e'40`e|Y҇j`*DHWt(-C 6Bs3F}`dٕ[~4YTG+r]Bo:CꭃolSO+䮨R9+/␒Ʋ PpJjQһ3BxfLBWT$=M,|L 1ر/?sw$FUz3ʵ&u]i "EJR.&Mqѩb&&F9l,7ϧ(J/zeИ 75ɍ:2;czMI ?p P1ʤ Pg6_[]UgXJtm [/\!Į J1*m!-Rsad~v̀Q$EEnD"O 2CHƩF1m]W\Glmڤi|툸ipmFlySMkxBmY]]) 0UyDm6kXXHh놱WOb6 ڙ8γ>ox;Y:Gs #򌤙@³j=_}t*vb:svY\^>Foxc 煰sJ풶g;Co?dC= ċ'T_~8MvzË>۱$/z7w93T8a? 7}+i)+wy2o~_ϝ^Ǒ!yΛɵ$E-eXt MnG^qJuieD/rYX蟾d}TjZ\*EFKCxU@j ɘNCh`eXaGvzrE!LrnVơ*jF6.!!af! "" b V"!&$N"%V%^"&f&n @ 5aBh#7zc7n*Rc"j^zD3E =7(#"D4&EA3AE=#;cҩ:&E-0Q @>5f(@G#:Q$Bnc72KBPL:DF4Nd5cRF@?PU#IC :6QT T2TҤB@dN$0 $RFWMrY"%8*MbZ"Z&M#HE\ePI:cHV1ry.^EQh^qV&DAGjQ,4dAf`R9c;"&1UdX& &fiV?Σj ElLKUJ>RDok%rQeFFfHfj[qF]4cfV>Zң=:%ZQm6%E*g.jjz|tqZyjU+e@M|vD]v&BVZexF;r&meEgk^,$GzgRYReDIzdJ'fR`f9 uezꥹ':(,Bh"w~"^'~"lJn'RggTYD i0&VnFШIz$RO+z\>%efgTGΖ=n)An@_g:i¨hPZ*cRR`vhneh)n (pc@Jp.?@Wi)BinYNA%" pf-Gt `_ gz%"bABmL)Td'en%6rb*R,CjH[ B]ld\rL6+>N{'$zdRI~(l*hf&0}":@+s&E=>f0gUk*Q|"KS4AlJ&jhrnRܤ:E~g(7ƪ&FtMT#2>H$z:xp~WA6f"r,UFV˴V,"׆(2#0f&jښK2蛾-E]!F:`qQ̳&n;?l_z5'TuO[[1B'Z 7_vm\5/)o_'5H,Fx 6 vGsPrbmF7fcJ3{zZ uD tQqgkʆOhd>]kNu!66n0LF'5B4j2T?+o{#qfonrcXsw EtEFy&utk&GLMB4wEy3+{EiBT@;r q~39[rsExdh8 _#5|4xw?!cl Z2L@*>6⤻A|MG3W~LhE:"MwGBH6lpHK8đt$u8f!(WN9#o~8ahyG1CE#/߸wQrs︛kʹ6rz 垟Kyq˴ zBX7{yr7*93J `kA6xWD/HC:}FWv:uph@Wyk-{A?䂻ų+D?A&hz;O}{;c{uA);ȹ{iS,Gx㓦oqw7I:yÄjگ{ETܧeGm1v|CG5k&JKx'DVV(ISDAxgwvSK E}Sƃ˻;Ԓj6\zv>&swx'LzLGx=BTc.O! @4` @Ax@81aE~ b'J<D/~0a\aG0%Ɉ&ʃ1 B8gQG]G7Q>@0'D! BU8*CB*CZ ;6m[oƕ;n]wջ.ָaA 8@H Pڷ60@&H)J.E,xqg(2hfW[U{2lϡG>zuic'[㊆RJ9za2q72K5.{Z"~J*8.8TH̃ ȳ&d(3A QIt+㎯jJ4B 9Lk/ϡ 1~H($#J ơDz*7v+ƒc#:,Z/5l7L>S4-rѨ <}z bS3K lN׸*0$' ))=#REPLm9R!LqWaUY9-WĂ,J7S q0[FWoG U-$zK 4Znji54jI`]qM Մ KlVy魗]µ;|էXբ=rSւ)˾ʌX$q `Z3(zԨp??=ڟ,, h^Yiދ_ 7zqtɊ`fOrubFѵ$5.[8ez5 PNQH=Є&՛k[N.}m4Āc`+zofuԪ5VKv?JcAsG@TnXUw[Y7m}-T8 ?\]eio+s֚z,V'ٛ& ZuՊ@/},L }B72>@xHJoxGw.Q "٘Q҃zSSBVNT*ڻɩw>yBѯ_={lPF<5!;! NCɦU6AYd)?*`HEXpS|6$n]4 hŻTB$XF娇J ڐWPy5AmzGl 2]%lN @EIN+\cg~Y^h'%̎5DǦ];S5 f E!`xnH5 ۗJ.[LI*J%(Ɉ,NqU$: aE"Z'mˢї3;90Efb/f3К=Ӕ;'&Yܔ|$17M (+79Nr%D%Crr T0K'm+$fAyT5)*: %r!/iB{#42ɠ3$Q-L%$Y kaR{bw̤AwHޔm[N(;QRdKiSFvӥ 9FT!DjqҫdޖXm0Bh%ngEWUW2˖%Q mSNm) pW( YpcIX[9R>vtrD ZNCe.igzN VQ'׉!:dBř`lRؒb 2bh#Q*C)ʲB׺5#͠uVm!\d \EHMsA*5R!Psi^@s-lP'yIC1x=Jqۢl)BjTAj:V߳*I-[NxqA*eNtc&#eef )CϰVmjF?]p;b-OJm`^ChΚҕaVYutBd:N WXxx$K*`/!SE1G6`L[ž[Bĺ}?UT?}lɾjPqcٙU{ZV7~MV]sG6n A]ΆOe6Ȭ>'PHbAwUfbmZZC 1f{oӞV(o*-+O8`?4?4yDvtB>"\V+Ur7>bYml=x/. 0D‡ZU>/NTCЭ8|i?:Lj/soo`a.c(,c//+L4pV@ Ȱ-+XB$m vo`TsºN4CS,#z+*㹦'*K"pV0elЋ!/ژ*C}$-b +. i'­Mx pm #Rr'OTnP2 @oݢ歷KxM,&jl0 k~OD_H1o#fobO&N\̛R0+u^Hi@% S U[1ٲLpnQH< H"pk| N#"N$"- $qF O^P̮q欭"[V^0-NH#b(߭ .$RQ -ՌХ0aJ/N했;2 N #b-5qW鲲*rPT-/7Zi&+/ibwk~/! N" BL)FoJ.25c%0 W%QSh81#[,Fw"q2B q&6bb 1*EMR_U:ˇ5o5_ٴ.pp6uD4ŋ&˲7136#n#RM"}$3@XJ!-3ų=,S,138{i"ۤ"#ڍ"2dv5={tE$ ܢ>ҼM''Dۀ3Q(2N l %2wRg?ET3/W <t0jh"At,1-5Z28>)&t?&NJtfBE4.P,4_80u9-Q"8)WLAB1)U-f7?ΉOAu5 f@OPTw12t7n,$Ca[rQ'H_ON44wSpQ3T5FUJoD2+bFot _U!2={-ދlvο*ӫ"k m9;X|(wEJpuYU6\T0Qڕ-m P5s'i[u=kV'rMMC'Bu.$ob?,OcF^udBLT3p%HU] VoGa358okU2 l 2T%  `^ 8#l@ d b ;zHIf7v{ ln|ϖ w1IV}(h PoP|P4an X m؆o f #ygk؆9Y3@p Kّ=Yx`I9)Xٓ;~9wU!&_Go^( Pb(uDR"QIuXNt۷"BVdX.\y“i9d@y)ٜYo 9r@9\` ّ bٓsOgxyud.dyi5EK%Ob2yCr/{.4vXE.""93`o @kZo~dvzsrBw8gx@}u>اƊCou8R{ mNq0^suV`1!WmR{7PR:c/ƙ† $؆ 2q_Y٨8ao 9EX"7 &; v.8}:$:mjzh"ƱbsbQtSa5hiaBmy ٟS;؇{YUٕ;ٲK;gXMx FXU,A͓by~Q <) uO[8.-sx?n ۺ3"H#:zKj8ŋR܃8 ud`o<dش bk OgWv&O0\+qu#u=b9w brYFDI܏ZSzuZ\+طe5a%)W4ZhK"X$편ImMolnzi!^WWpq8fq]fw;G:ͩ%u== Jy,uó Bd˹<> "򣗔&vfPCwۉHX? /=ٿߟhl#Ivrxe\Kf9uh,wz~WV!>4^C~H^W]Dr: HU_~ҽw(8x"\!z9}QX[< ^^ɱ>C}!x^_.@Z*9^w 7Ø8@CZ^!`CדQyb)c4e-$;99!{!yY)_HY b99o?oI9W9;-l)s k-;6|,we[_%<"9!F n`1A .FHŋl aĉ#H6VNt!FH†4kڼ3Ν:/นՒ!`|$@>eho;D2GF@ ` )g< >OB6jy>1U7=|~0Z6Yԁ4G_MXi 5H zcpQ7=p]E!Cv9f|5dWV1|ދވc:#N L4@9vw5TH5iSBq$ 8JH8K$u F c%aehDY-64Ee%g4Ҕ"C} IgYqbe"bf!)aeuu֣iފ+SdA-Jf@`K9X$H&II7I -@94,29F=sJnhwX8]P w BK 2Tf@6t)ay d5qXUܐ~bTʼn NN&PJr*Qԗ4IT I7 @6-g&v5cu*1$6;HE۬ŭ'T]NF;#m-WQ2]ZF`XN^ ੿SYmzq e/UJp8i\XYMuzhbiM(iڤӃ[ z6֚/T <X :5Ճ%bu@٠X2dqv{~Ohsl;N=SS3볿51 AJN3 v s،!1*Ugԓ'كʆ7|$, OBє}!>큰Óus+}c0gۋ 緢|G\-1)E|0})ZܢjbH C5v/.v[sb(<9I9#{8 (C)2:)M Fm, %/Lh\%+4JDbeF[@1o"J=Y=Lt^LHD`$&59⯓5Ӊ=fhw=yMF6WGd>3^mw[0Ga̛M>Hfl^Ș̈́/!Jx3$1t$AΌ)7YNv!0q:'}prG}9M}ݔ7oOĊ5O?UNT;+7y(#93RR fGUYEP@XiJa2WW D1qn18)pWcRr FWhe 59Yֱ5E%UŧFrYCN@UMA&gO5sO !5ɍ(]|j*3IL$9])& `a"ӚxBXf80hK*jl<5D%#q.X^Z$+1i+l!c!J29Q# XeBzOԝL4{6\A=EhK{;Ό"]L/ra1M DhHHڲČ&FOo92پ&WLh٫rR%e/8MvwΕOF oȄ'욀bU ~Zγ6Ew+e~I,Vd5کkBJ tqq;Wυmd>lQ~} /h N{<@78Xu5l9Y%x[v) h# |7AҋHQ7a:8d# .mlWIC.1T=H򒂑R}^_ ӌLv)Cx0Sx_l7+e)SəkrQ@;Ȁ(=)}M]{0?\Ƃri14DCuvЙLKbǑ1fp'骥FU-:,M9##ǝd,!9Ɩt749=ث]>=*DŽ+p]=[N$љ5n:lj{afװجm4JM*v̙i IP2V_JʎB_t1aMqz}mGQ;>˾Li KB]%5޽iumט{2| 'M^Y +mܘdz ~ o)q᜻BU~@Ȟjŋ6N}+n͝~ݴ/x|b yg28aB!ߚv%ݟU~^50~\><٥Td>7խi~)L=a‰@!/qMG!} u^ vNܭ#taۚTO<^ "Myכ |ڋ|\yݞ~Nފ5tә >\rżc5Ƹ.^ţ쇀Du/H`n hx,Tu]Ԡmn"$:/m.5{R AObؗ>p}r-JPHASޝImUIZJ.,Gq=hH<6PC y>I>yC_ AJ/e6T]=:.Tg+ǝ?޾_})/EbsKKђ;׊~9Vqw_zOJ'(Pg#"W>m033đAH;>ͳXŸI#05OJX/5h֔F  A  B %NLx Ơq@ @G 0@ UDKQOA%ZQI.eTŗ @S ?ApȡQW 2p6eG=q6Al˳G W(Q `6Z<d uQVUiԩUfP9Jsj\0+vHN-]up%' DsEޙѡ.K{1锥sTeZwloNڰ|J="6$xɞ@ l9ZP8P" @Ft"be*s0$ȫ*¯@;vpH"4H$ Ev5$F"@bz' %¬&R+2 4:@E 01j0ґIiJpSIDUtQFέC G-,J Q<ѣGe@ ;C/@{ۢp'CttXb5ئdõ`SJ4tKL..[/-diT4:R!,Tˏj]a?JTI_Xz%t0rZWl(ԭm%hX#MKNh O]#75J˜[СK2ץ+0Y`{v~JW>nR:SnItz"y" @s5)A+Xsuq2]rd{n:]~v5b\ډzTF1U|!rΠ؄W# sBʆQ F.}{ٺ[wbfmyYl0Il- T 5ԚqT\*1lrvyma7|lF-7}23k ṝ13-(YePʲ+;Do-kЯePD9&7X-1y$2]1A@6"v6‘`xp ,R*53o(Ԗ*C3X>Sqc=lBRA8:+ރ=?&284:93@:K:$+A'ûZ \ؒC,0?39 8;=-9DC bp+SBtO0.721 D8W|E2?)=LD^,*;@֪`DIUifd9_EkLS\Dl4*Š>;;ţlǟFw|=$Ƥ wG}3{LyZd |G,GDAHH|H(Ll\ HHBH$ȠHH,I < M֏=אő7KFkSO]Ś}YY WWueZ=ZWzԢEZ YRK%Aw XGMFɘŊ7ZڭMMdQEeZ=[M4ڱQ[uGUS͹[[d[wDrE{e܂\\`s܄WtYlܦkܝ[5[[=QϭN=TֽYSZ٥JE 9h1{۔]ސuX ^޳<]JE0^\͊-ϵ-^ ]uN}_,߉IN_JGZ>_n[s`Ȥ` Z] N7Q^^[0V4paJM &_NQVlT!b'V}b+R*+"#V7-./N0n$4v49vӂ2b㘬cc`U'?ddBBCn%6PAvGUa(JM)dM5R ~ P~"c4>e}67cZ~M[^eh'Y}e 6fgVUHgf2=eKfDfF'l[fg5g_N3ebgfuDgUfbU}>gx[[N'lh.f0<gh]uh%MhAұfg˃]ha&n.hJ=ig^nh~ifca=H)iah .jF`ᥞOӔ61li\E>ߑjHjF=kYfektkkh~LFb 꿾kUducu5FVd작pSŞVJ-m؆YXmNWR\vF/ޖ~6OO>m\n#nFjnnEmnNnognl%TnnY1&n ->͎hҤak n(nf^:Fbun Q [m~O0so Vqom^oFX'7qG7hV f?y\!"#O$Wܡ:\'7gMr.qo.n&*rՆ4pp|2rŞrer=I&&׭Bj3X4q5Ͼb&G7tȥsK1,M/u'sG7uVo ouQ=39uS38pJWuujaub'YOJWnUovHsxdW qlT^Okl?oNtj_L%uvgh_]FPzr?v_GTwuwwteH<sxG!xXxowfT OOww{|'^_tR>UyigK(]y_y}woXOy]ygxz"W~fl`SkwzfyHsFmv1Qu'[]}`7{hF5f{=A\{GtG|w_vz%d_ĿWuGg_7-,|O]lƗ|ПgajREտ%eEό}NMI|4ܟ˾%T|@OO碑TY'w}}OocL6W rXo//<IX(gB"Lp!ÆB(q"Ŋ/b̨q#ǎ? )r$ɒ&OL91K.6`%D6oZ0Hs(ѢF"Mt)ӦN Ud̙Gqb, N,&t*ٲfϢMv-۶Xj֛/;|B'~,x0tV8h][A xb`O /cάy34j^ݔxT=Î-{6qAgtB$F&T׶#O|9s/>x' ޿/~puGFܻeɝ W}<ϯ4]QgX6_QE!R[yQz+paBUX'ԅeцu&ƥ;ҊXo(ч%=2٤OTd`Aˆ[f4c- _QЋ.biё%IQaW )Q u[V會Zg{u'ByꙦ 4Ȧ jbn)zG{~]AUԦm駎:,L%⚫ŘXC$qT",1%kBz԰mNjy2J!˭ι*[U;.xEJ,pu[!#bjkeXJI'\.lM {>\}uӿJ#̡TV.Ra&TrÀ2'Ip+ σib6ϣUNYĀtiG":яf5KUI|!)K[җ42OJͨɇe3_jFe)OjͧQRh(jU@, XUXFVbTVIU5#D}'49:JkCBWNqZ,|r ,^Bإ|F9`9Xo.䱈<_I"Y5`y*Sʒ ,JrY$6AJGN;’s\Z`m)r*JjZv?}+sB7ҝ.ukb7 V((hގ.1u=L`Jz[Vd hk_v⦾hR7 WK'%10B;JAap=ZaIZPa_!Lq1eBN)aGB`f@ޤ\aO1rLbc%Q~2cd8F;Fe+{3A$6{?zW'HCK7:ENq7$hGdĉ}ee}Z $"^J?|j Bܫ%W%/ЏlsEyt}<!),&n22U~Tn ,,J"04#$~ OQ  ''56PP 56I~Im gdQn yQUx P,,m n efB++lБTly SSБByxBPn TlHHIlBtBBx ߛ} n m ~ } TBBllH**++|I++| tUUUB~ y HIBlUx --ȪlBBlбl~ߛHt~TR}ȱHim lB| t}%%| ~BP}Pߛ&&llx m Px &&lltllhP®BBBHt:H¨`|}}$g4_ߛJ>lBl:i#Oe ȱ9ȩm;l߿C&P§F)ưS9f ~ f:xy RБX4:|X4P} tߧe 9uPưH*\  JH"-j@ b ɓ(S\ɲ˗0cʜI͛8>Ȟ ;~ѣH*]ʴӧPn)dѥB^ʵׯ`ÊK(ղ &J4#ڷpʝK݊g TmOz L loNƈ#KL嚊BˠCM:rfqvװc^znhngK{ȓM7 &Ƒ:WN;IХSN9P ױp;AbW?E% g&h AJMgE8EM^VD@ ("AAXG(@"f8ӈ}h@7j+6$z-AމUm(D@U #fjt)\qMiJ%)^euAX2z@$:Zi禜'\zxh*z쑚և?4(H9\"i!vk2N[T9v,~XB%Q ߉&©c05,Z8Fdip蜊JoʥAo6*{2Ϋcq[V- ˥>:E +Mi\U) X0P',Cp^wA,R<6hD54eq]-K]r[PЁ55x獔b uV^d(+JA߾m2J+rΐ*ne7~{8:rso7v;W壋`'a}8 NivSo3m@G'`hk>v@{}~9=̷-[Li0{ ZŁz> IQH _⟐M^ ׭6H@[S}&RF,Q%[W):v=@k|lݺ%PMxW h\ǶHNn#7i6zRXC ȞMgQdC Z]k ._]abR@H JaLf!?Lü$uuN+^٨=[vQ$Kʌ%1;͡ik^3Ou'r,FJDaS%{\0멖iVdsn0Ѓi \( 80 ZVlUtV f> ܡi @l`.=JԖuҍb3 J6+<W/)B4E5sF Wd54A[ځ4䈄@p4J#V!Qc7F0L鄨.{ԽI#*TْQXVփ쁬p"SL F^5&D}-HUJ%$' z-xv P9>"ߜ0pcZ@!IbԢeZoZ^G&c^J[}GJmCt(=ތTWҢ^6bTޅY޻R b;j&EPP*31s&XXs:J 'Օvy7p? U)%aw<]Es*9BD Q.,BƊ9%(28\ast6~Ty;s%!7z"MgD'dnr*C&"F+>1>,kdwTZl-7zUUaMrO26YAǓ=ڪ1@l5.t;dE^Ekϋʎ6E J'$(h Mq:RrA>$[bN) ȿkp~!ݍ3A!wŇ>Ĥ F8َRGb{[;X,yךs?vW u~t@DS]#/p38&HFNakFdzݯ[Nk?pdcۼap^lNzDy&ءzlG,t^zZy۹ hO9`v] DwG詇-Ep-{L\oݯ Z*HF<>_ g>i> T^_{}S}OGXv^CD$wi^ #)Jo4{-&{hm?k%~w8Rв9/Vi4suCl6(&g{ui~zJ!'tQmD]f[wV$(%@(8}tB`^ V-Ba8Ea(A+x",Wv#0iȁ\SX1w'Ux81\DpSC"a>2 "͆Cbq4r7 "?I؇jv94Qhe,zA'-`creFU{7d>2 #X6]7~۲uD^{vtksbvw,}lg>%W3ʨAx/nH2:0'f\v#Hg~7nxwy0!&NA QD%66d>ԏw2 YdzD!p%('8k-Qo\S#iB5#ܲ"(C5VYzFו 6Q`yv&Xؐ[9M3`hfkZ8fSRT dI&/{iQe0 Tۢg#[W g%AY9%tc!ifǗa2(YŒV]|hgXթHH uŋ5w~iIը5a9 |i8Ĕ1Xɝ\E7~# I_Vek,I/RZ "v?Vz^w%za@bze&2'bvYu)rVQA ٟ$ *!}'G9#hv=5($ZcxN:%J*@q!^)W3Izv9o&k]VȜvQ}JOz{NGA]j Y#]D!:tryf:&tIZ*tS2ّ@jPJ@j@Tm )xW}%p:Ut ) &}yej1.frb? dKfPT0LzAaAk̪a-t.*\&flچ,$ ɈE@_ZyDwG5AGxz!U&V}jf#NA+98ȭ 51^&3䙰2@RPnkyM봜9I61d⥭ Yz+(䭻'o8hjm=S.9 { V%@[&˟zI#TZ#yڸz͈BIK٢cgpAټ&!=IڃpAdl u+.z{wۼ&HɋIka;>IGS76p(3;ic+76 Y [!<ˤj S_9Y8-((;4/;R;x]KR c&TKc[ϲLIT\g)w5OcByIlA ǸT2?8 *(H;oqkdƴOܷabI1&h|yܲâ2_8Cc:\*  jĨsI5%[#Ǟ$Sz8tmJQ{0ØQr{ ;44o,mL!k+] @ط\j|>2u4M˴I]laV ?{٣ g(c`#S'q<8:"Z 0RA<|k]F|ǮXm)*LQTr_j*J/ M6}%qƻYʊtݕ<JD|LM!L̯, <[&&իOQݾhFPGmWGs@ R=ӛڜ;a⢊Mmp1H!ը-ͣ6 ̟}e$ɜ;Tr8km[ՋJMܵX9d=ӛN\%R-qFIY VIш[0})]/+-+S݉=O!Z=)}D( 8%=5ot, ]ֈGȦ-Kʑd\@غ=ᠿ E}և|(zF|EšGY'N-+ASHᝀ:S\ߵ JD {y~Zw念ͱ횦=咞7K!N$O?vr绍RJ gjJC?#xBA!%NG!ϥP;nGwREۨe;Gk| /BOBjۡt/,A|wn^oo9,P_9*ߊ?j( ّG6|]OE^ ٚ\xU=Ab j1. +aoE wh? L>&IT@R9kMhş!mopiqJL_1@CRŒ]M d#Мo)>Nu4^e$=QJh|*hI묟>c,&kxlߛ5>,(! I ,$LX ؀̗Q1R<.]RSU^ŚUV]~Vت 4zaBdiءQZ'tL]GY@Wga"JfYdݐm.ʚf[n޽}|YV[8ʊS AI ߈MWtH?/~¤/hZjщQ7`j+}$~ 0B 'B Q"~R8#P/<#%;D[0Bz'N&Qt\: 19J+2K2j0YĔ4H bp14zl)i0*2sL tlJP* DQLPKK/4SM7eK{JJ$mȟHlԒ).ΉXjz(׋0Dw9%B 5#CRDfS`uC 1_kaE7-%}փ^Oc<;7+6׹F+~ "n_<WQ$zESh9NrFldAVI%.Hi׾JtYז n<8< Kղa02o5lJ6+ET "4yMֶM1RŝfY?+ri7Gn RqBE'Ou|z? l0qkGt(hݘ'2S#9RX̰w*~6נ S7%#jE.jˌtKbE|)UN1` %^uUNEtC􅯀$٥6rOzF3;\{Y8\ƹ%SYK4!oUI8 Ú#.~5˥˫DKl5M]wK;'%3-okas}:+\>}OxT?I(gKyCfWhk:cy/OE3se_כoarv(ep35Z{?tO 9z?#*<903 " +:'q$4>D}x?d6jJ;Ly+ӣߪ@( [hr+kc0s-!kz؞4xK`*D ȽB94Kl72#\I' A|z[9r>?<^پx:#rYDLzI9ra= EBS<9P9;3îp2#\C уC|ٱ^G6z#- ? Ce9Ch̊"!B/1`EKº6M >P,ǑIXš$4JFk4?&rDoԭKEMqJE$& JRS2JV$Jh@G0BSɒLCXKXyȔc ̐B h:L!dUaO@lΏ DL NLB,,XK +-̔Oa%4NLQdD& 0ݰ|Ls(u4$͔ Wl"L^%=vM̂JD9Կ+DӈWUZI ?K;%WbʸT!M4 ɑY 햠ȗz]]Yʜ5[HuR}$Ū rͿEZT!idIe%X% t,؏³uHpV_;e oa-aT1>- % :1F EVH{٭KN|8==uڧʼn@ݾ ԯ cW!ze]Xsߣ͵m(\-}GP\}Qh^,kɩ؝ W]_5bR8޾%8 WV_[6+ʓؕKa )N%!Hғ$;ڵZk- j<$$&T[MUUe\.@*ZQ9ٹ/!-\h\%v㥠 F\*&_e Uύ`_%Um {K7䓠=? ݥ㗑E> @ٕ<]ៅ~)bIh -fYMg1Ί(w]_e{0g}6K&(*踈 A_y )@h(I.E^d&cTuXCi7HF%:ebg@1H&VY:[e #j &jj/'ࣥdOՙ :c*c.eؐ`S>f*`!tmkN7"I4^QduiesɈHcn%B\N`FRvkz`# l=冠 8AHf/,{ !` ju^@f)lk h׽o&6!7撺.j%6 u$bg qwvM<7 /$!"l>r%fkmur.$ƺ.+gAk"73 ϕD rjJsIvl")ugy2=YCsq]L0K\|6E^.gϹ)o才nh:& u-NJ"eSOk 0umZ\.1n-,m86`{ upVv8s^W:vf.JN|.wo&b7wWLy_Ǖ &qWkOE$%_r7dP3a\,wcxrb'8s2/yǧ5?\ݍ-jxIK9qu\ƅa)72˾ S]Q^^6$=A; r]б R$(@E-> @Ƭe/@dW oZ/3MOykFBU/o[^ RT`|(2:$oc>#Nr;\^¹x+( ݦ|ƕedY'~H!쵏 )DLaWNؿ0'3` )Iq+SQӨ5zE 06h7iJX^9>*f %)u)w g3/DE!mtl$&3ɐTnEt$G6(%jٺsJ/ ]h5h%E6=# =]Ѩa34>ˇXXfp: BKE  q%'9J|g!HGL'^ 'H3pr_tXe}eDK³34\!È3 G$L4݇9o` xͅ"e;:&Yk(Pʱ=2O4m(Q<>HR18xPDvqh CS#*Zӊ.4\GeH4 c:TZ1 AmOVЙZhu2O%j},dV֞ )F)&&MY꘥a$&S*@KGdM-B|Ҷ9l@h%,+Stؤ9lA`X@D&cm)W@JSG Zx`W,DN++uENW&D.,%uE8{c} 3_* J#RGbWE0CY7,śylϑK+rվ[c-]"1Oeqoyܫ-vSB 9rQjې U˕[1y'C樖;U.W' XJnd%}xxi^Hַ.LˬE'ˊoő)Ҝf @T_B9嘤nbZp:~F {c}iҭ*bUڼC`~9/>39:adK#=CH%w ()"&pŒ.3j1?^ H_]}tx9ލf%sqEP̠)Bl@ bRR >^YE i ~F r H ~!` rIۓ%@%L]Z$aVl|!Hrla!aka0`"!ڈ F"#>Vb4b>-kP"$f&n"'v'~"((~$&&%)"+a)*N*F,-+G-,."0_./&D2 20"ƽ13F#Z,L1[]2~cYH@ @dm0!UcA9YH-ڨ9#>~x4 @@:\2"; @ 7#byiHDRB\qDBd>~ ;@(d $1"I<=fDTMഡ`DdYc9#aq|7GEB. HA?.%XtMVVjeTn#-FDWAqBN@"2*%dX$JBJc/@\^VS_FNjD[eA9e@a2&[ޢ,$WLf^Zj %NBjfWxLI`feBBmD<e8c,Q%GkF(VeVYFZ^B2$R$fKO@$)Do~Ipf+abl&ͣB$@LXdL$xD0'XN@LB}@xuRDIvb,t{leAal( &B6YR*h,twҤIΥJJX{~f{R`TI#A$m(C"wNi2eq>(5"{ZϨ`:X^)uQiv6i(HiW'Ti(¤BNzgD0)N%;Ѐ(bBzN)7zfƥfQ]W\HD"vCP(F(G(LX(f*]bb&dZgR֣Vjs@}"aꪬ"[*MX+yNy&H'kGu屺ݺ*OmR&L(V+o^uk6DVnWljGl~WƤ\ADkpdtf"QfZ~+B TN)d$fCiĎr֬k,6ϊij&*lA`e*Cjά'V'2ζǮXGx l$kBz^p^mXrFTjAd姂t*rt.d (jބe $a~F䮅I&Lv.6*-M ~`D.~+ơ,,rA:gNVnhb+nZ/LӪ`*J Ȃl~E v~N"&9&vm^t@ڬoC@%A,B*$oV0),dB 0h#hq*mA.6b sԮ/i G'p0yV$@ pkIomcojR / 1Bto?~Yi(W~Bpm0@$ sq^zq%aPip2ZClm.nPIo(ZrC432CwqXh&+#0++.M-XfcOg|o֬AsVT-#1.f4dž*Sf./(28Ifl#Zh2ިLǡe9 -2C4AOE2@GaĪ4h$z|Be6KM_S4DJ6kE.3O XP'&@St\N)@a gi;Gs$W]2BJqn=sf*JMqJ5JPYsue I%hiA@صHղ(5fI&?C.Ү66(/,&v44I[w^N6FW\nAdN #ufFl /NS1SɳF3>5ϦaV[g 4pe*dC;qs!rsExst|BACtG:u=gN=6tGnt F&Ow_[{weEoַuJ{R[J1*~G{2jvBg(7o2u~*uBlvo85Z7C 7Xk$N`{YJW#5sY2|Sb7č+V@6Y5w[ꖂCpsuo00¤20gCj7lz2$kYo?7rO@&JGqE r|Z#9YNOd s-_=R:8 SMv^5.@5r:z9kHNz7QzYmjZ>x'[ZbHqBWv6 zש(7k{9l(,'I{ql; yq2;t%z+7zDl.{ANū+{z8_4/:5<4:<lkϷc;%Fk|w-祊<uuB,BqB@.ik}h~!'Jk8/٧ wqSDWc]?[Jjks{>nl(@`@PhP ``…"48b+jT8RcI%D$`I/aƔ9fM7qԹgO?`A8%QS*=Q̑ )N8py4iĮʬHdz^Xi2TQS1$5.Hi LAOJCSw_ϟA=tiӧ5y@?<{x_Î=x \{` 蔹_o^7tjsCSXu.Bans(׿U& H>򶃩<FK,4i- \:D#ZaJ?(;= $ L=Ji %l'(g"n%%$\Ҋ7l08 "H,6c31Vl̠k6PM³ӥ4K< O9q' I)KG P' A=YLK3/! !̄ M:U2$S4p!\=BVaD:]I3Vm[MsZ!*}:`(ZTZH v`D>]$o:/+!#7€Nߒ`j>oAYt3VbbЂm3ժy'S2J TnߺS&w(QM R aGGƧ%q`,Ȟ-ui B'+5 %‹$B,BI9I4Z$T=;hີ2]t]^3`\Rud1}IGqF@Ɔ oT?Y9nNI@[_lb ʐbk%Akul꒑ 'M5mGѢ-H]i PZMjZѶxfR$V`:"Zru//\V*Wjyr\C>,oH!xCIҵvV:J#zhu[r˘=gIj,L&MjI;G  Nػx A-g ׹n$k* KA(F*&ncå&O gc&9ȭ t|p W5$9P7ϙs{/1J7c1456iGj晈!GVpb} &ʦUSp>ITF+j>|X2O@Fn)Gaԅr6#.DI0U%Bh [j6iaMJ8{ hD0VڞkVvHT -mnqdab1tJ.WKuOr܈h7LyV;'e `wU qL^{b^5{֖j^i}&%7yjiXm60@)ڒh.ߠQZ3Re!ˇVdfY#cB^Uwy7\A{k(wj(=b.` E[[ ҕ7u ra:'V7<>)8Aa\Հ95]٩`z6 **{x4`y˴f5\vxS:Ѣs"j`yI2yQߜf8syO%P\^s/zPS<ݯ_Ɖ}o"oٟAZpl'A5!#'EO*܂,a=V o8f40M^Lo&o]hB8l,j,;R2.:Rl,c@ 6+kBLf^"VL g~p P\W %b "nng. m:P1в EԆu+Ԝi.m  PF^Od0e h w ^BEp .6}"oP NTȥH=l*oa:R8oVj-Ëԍ.<%:fF[ he&6_fCVNPb᢯JL u1 UgPT i!>*$f0^F] yc|s0V'h}`01m$>gb2OK"n~Ɛ"oIj[/9rfE1G00Q2*Hu0ebͺp@!>IUJ "#-  194 !$5BI*2&~cn%ܠ9,qN,pʲp'Z|2h"((o2wl/S !: 0]ӂ. &O#hu bF.-)RɒҲO4aWok4Qȃ4s"5RJ$;Cָrzbm>nrwr҄(9I~yle2:7/s@A'67: R1dJiH%=uĶ4_P&-Y-.-C0?):sB6 EC&*a"ؚ6(pL3,(bƱ2pY4~(37;2Dp%AA?.Íl EdM g%`!Ĥ pH#$t8ޑVQ85 ;49  ݄BER!Tt PYc9CuX:M6H3']Z-%ߜTF]F4L+tLB!%MMG՘պHt^(;TN@AKUH__FGaBU+߳ī=38o"mGV?7JBW_K`bzW86{XZw| |gup]*Mw17)*=oUaD27k>M6n)l7$o"QxئwpkyaF2i0"&h(EW76y1IP&.A5HiMNJXx?|`,%` ", Rd x n 8 8 Ǹϸ@ sA @lV~ե4!|gS"x{b-V|Aw;*i*P.6 C 4B ژb, pY-| ` 9y YX`xtn KzQFhr%&J7-ǓFhB!6|"H@IOsD |tob|זÚ"zb z 9i{y be yysyOZSbBz fZ}`ezETXQ1VgF-yTҶbRW bxZ`?#h XQ 6N<绑8vm$\awy6ɅW!27wPcFe{!vǼ_⿶vV:J!;n<8G=+FC+vomi\2OpG+WwX0To'Q]\4f6ړv&R ^&{ |;h_{me9}MAb*^#U0E3J~osPJy@LF}9|ї M8/JNqCF 2|PVk[a>M!=WTLO"u>}>V!JնIcI('䡾*ETvP"WJܵh7p?-Wuk~ª45EQ:ޕN4kҡ' ؼ$85b e V_gs@ wCݘ{j,V=}U KZ87׬gөcMub{aY#juG#"qq YϚA̪V0s?ZWʭ18J)?^~sL)P uODOLD1.~:4[_θhv(!U.*%I՟Vo˻LZ`D#!1F>[ p[!AHf[2]w ٮ,WgJCUGD d!g'O^N1jAAԾ F Y(SYTY`@Z,n/̻YԅATьˡ@4\͘5qqx 1sPm9IiiޑlSCxo`}MJG &0(DAMlXrV KsVMӳ-<2sԃ I)Pc8B"ҕC|.m+HrdaԲIz!_%{¯?3,!; [QJjo/-L<*!(dp.vp,`y)p5gcKJIP^ ` -]],d#!ȋoSJWJW2Ʀ/E =QW/Xg^rؓQWVxՈr( y=!pce ّkF i8& v&!hT`v,(k{#2U5X4ix}P[ r%]t^.aY` (5cqt^UKNltohb]yn`+gH7W6GH&W>c|87h= 9)!6WRۥ'NoS' Ne3oú{@ j3`(@ގҒcuoK.j['5h_t,@7 4tbDU_0y`r.X^ }(HteF}MV! ۧ}ٗ'b 'l5wruwFZSǀ+JwvUZKEMSY7/oFt%XdgCׇ|NQ' BQ~_hp5`er`wm1d~k)A.7]YiSC J;XPS'/x~NI~ZOj"a&QklgӧW@v_舏HRnB 'f.Jv\/鷁mASPS~8f|g%<pHa苿Gn2fdaK%AGo68Vd05Y@T)R[qoTtnQxSpw77CXDmvIz o-XwAomqPahčH4XX**WDFɑ#iy&1H@+(8lCPyⴁ'PO".9ġ7#ّGdb8+1Xq-O,riv"y8I\7JgHKՔ"kIIuY&AƖĸrҍL؊)+IYu2=`n@ t"'h~"*d) dG&1/%iHE!@Q8[\Y`=BQ>PV"bY5霑WRu䗰XS &~eIXCpIza oOqi"?I'),.1 Iu17|XPyxTu eX*%jgy&g9o4[A* zd JA*/䛘YI7J {YxSz١ӹؗH*YTV _${ vqӎ@បekR(`Ա`h5n>.EAQ!!g(]a* *ȒFIȣsW3YP\s?:qZhn|!n?*$Z)"Jz=XHeJVUae6q*IMmƪf(ʭH cwpXEZZuƺ#QC;a/+T'D^PD݊Gi^+ʢ*ZZEu&IU@B'&9eҐЪkY9Bƴ1ۑ慈XJשHPe$zUɥ5y:Q.{#]敗z)dr9s-C뫩vSB񱉤kGx*gɯGQe$A*"bEf赍 e ڋi8Y$9!Rw+G@{qFj )k$Ѫ 縻`;٤ *u=*X(x i:8<anY ɬR;O A[ʻ^p ʨǛX +AkLI{unњJˌQ+|ĔoTk;_u@Cˌ>)*-k p|IKkA|)Ze{y"t0ii(!d{PN2 o bL9T,\+slld:;If;ٹ <ң6B٫"$@ h*0m'¸t,OO5ɷZ9!u*=z~H«uboN6lQ`Ҥ O}a 6Nj', 9p|_,̓v=e1JY" ;R[q"BͪאѬϸ\Az;lq8eAD©TMx"%̰6f ni)L̪+Ȳ< ZuK(S9"FD̖L5z'ƛ|XY&&rTJ+M\>|N.O,l.2Z^ۊ7Wk9N?IͶ&d*qިE> "ޙ o<=NCލ=SI܀r o(ܗ|^6ϳ@_eַq.adAҫ^CɃ' pp%7OYrӹ倮" > ~2o*7 p#u`<]d,SFlv['$I\e/CtIH;/'wxSjntdioQ\~$bz="nB/~QFY.dw -)vppm0,ʋY9_^O ծ CM<$*zFF]$6rZ-ouVA]Rd0neϦ]mܹu5lbGE{`ɷWVf:Sx4t ,tq+2*eU=/<> 5|\x> 4@TpAM,H*O+O%֠ R/9$<0B2dx,HJȪJè @릛< #p rJ*J,zp' Hx,t\o KQPF kvh#<3S>N*RE n8F㬨1D[s1tSN;STrzRR23T44YdCBh90<6'=W2JOXrâzh4=CA[p,K3%39DP|N B+:?ݕ3^թ.QJ*1Ie(sVj72q;cC~Kj/wsN.y{W[$C(ce{v>4իZi5.h՚t EjVPԜ sԍuklhZv 9,J BC$h#f9gQ\ҥ0fS]#|rʧbt> 'E$Z;ȶ T,]3X*2B7 +c`;p{kC<|BAZÌ1ļCc>RD_)$æVUC鈈 AED[ ܣxE̘ר<@[(ۺ-_Q9daAVlKƟIG^g$+[uj\/F(c0l<^Gr\HDt;' ] 4Ԝ :4A#D|c0IȐ,*ȖDHHIZ$dȀHۀ{Qɤjlht0|J<1Tɥ\wIilI,ÓȎ9Ap Kd dG<|K70]TF):=*R,FTK%(S+KD?@8M(L}2E.<PQݔRm DU]զ+YmT P^eV4Ea%ְcd GeV S#EiVUMUd4ԥ@gUqUbMBVVU`EIuwV1Wn2W\VUNTEW$,vDDXhW5RV\6fefN_`&g>.fiNjdfZn搐hfuVYNuY=g}gDdz>Wl~Yevs>x}p.A$KbgdсZSgS>>\hgȌ>4bPNhl8YИϙei|`Oi]rh^_5h`eOІrVw詞Ϫҟf%;nаS>ik/=k2.k^SѴӵjU,k]kqN+ݔ6h&}lV,jl֫jR|lfSRʞ]v=Ҟ>ڦ^r~֎.kB^Tmm罽nmvξ&6r`>bfQhS$oIѾn}oN nRmo>jU.EnO7p>^nP. /l. GoʉЭq=MqpfUp45rrV}\)wݿrOp.?6r4osses7/_q%9/:;iqr>l$oa%'nooyB7C?'0r,rW3t/r 2NtuuהoɓtTGtΒc9uSqHG"uUue`&Y7vMvrhot&xG?׵zfuwAϊa6gz2z zwoz{wy{_{Jw[U aodzofN{|_W{g{.eX\gw˿|.|LGUFxtWxѯcw縤Ez^7qҷmjMϟאigoo|~hw~?t᝟jN.ju_ȯ_/T}6OS}GwNڷ p "Lp!ÆB(q"Ŋ/b̨q#ǎ? )2" Fd`eJ8h   g+ s(ѢF"Mt)ӦN&,yjǟP_Ly'P1hPfϢMv-۶nJ};S#iuo+x0†#N1bt 5N!\}\ƞ?-z4iGw^#^8)`+05DBKέ{7MOt:yސΟC.}hY9޿/~>Mu 3hB5݂BXA22>|PY=QV5D,J?H,rc&ĀL8EY1¢HFPF](7 `fX.p mrJhǐ1@aH*2OM\3.G$x'ȍmJSʓ HC,"*ki*U6JGQ2#?%1ᨕ&G̗1mTɎ٪6ShN3KaS6 Wṇ@Dq“L)sܧ4^2 Bm3f=P;|B+cҔ>DL4HmKѼғj\IQea1l,C?N|)OSCG]oBr4٠rX6301ԫhiLɃP5"*Y2Ԫ6VXֲ54SQ&k\JDgϯݍdδE5(ߺ &c@eR<$YRP,iϢ>錨&Z6O** ݲ-n{{D5tg#X6n)`6Xգr9LLtZZ7Tf{3"Mxx|E_ҫkE⢪ԾY/kHEkW8%Iz0׀pJmw+$.ޭTU`821klc fԋ G80bEc X>>rc$W!B,'Cٽ TPeY@|a/O5BgPΐkGg6M#KR)Z눡粔FYkk|fB҃A5MCc+cL2Ӥ-']gϙU:mdP_Db]5LEW#^Σ{c#;^6gC;TP  JNxa-6J* |8D2YIGqXZn;BCnrgۭwC Nup@݇C@;1ʐ2/njQЈ{O݃D7QΒ1@* :'3ڈD/˛iNOpOexCpKcxCاnZc^:۾s*Vi.%}"vrdk) :_IHv<<@F^"vŹW{ሏl`S^SҢ2+=W/g@Oxnt7Ss<(m2ߒ+d_规[A6i;" ӻ_L뀟D^^UQ`)) rmP*j=-D U"DAGu[]a` ؝ ~_$F_%UD_A zȟ@`!VaFۍ!,22    곴 @*\ȰÇ#JHŋ Ǐ CIR"K\ɲ˗O͛8s9Sϟ@RSѣHu-ӧ 2JURʵ+T$lJO5˶mKpKH,wݿ+<+x ,L Dqϊ XɠSON@jհC8!۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjR@ze@V kSJkd6kK l{d2kJ9@QRKеZy!,U22    곴@*\ȰÇ#J483jq;IÏ /\ɲD)]ʜI ̘5sxΟ@QC.P/x \8p1|K ȓ3/|PQϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνÏOӫ_Ͼ˟OϿ(h& 6F(Vhfv ~@Hy&X^*b2(8b:];z Ic<" ^$ANǤ&!,h[622   D곴  B @*\ȰÆ |Hŋ Ǐ j@abȓ(+h2˗WI̙5sSO m ьBN(z)BA0uJjj]i (_V j Ċh@B Z۔o$W !bŐ#KL˘3k̹ϠCMӨS @E֭]?[6Cڵm'ĝ[A޽}\7ⲏ#W|9MC>qc{wq oGH{!,h22  U  B ( 곴DC  @@` ၈'R,`D7QI\R M$bN; RiɄ! d@j &`،b$ ן8+@ٟ(p(F \8!,a22UTJQIIU65Qt56PSSTHJPH4't@UT@T#$TI4I*RJUUȪiU'PJPPh04y ¨_RMȩ§o `JUƩ@nn x ~d k fw g4y :X4u X4Hy kP  @B#JHŋ3jȱǏ CIɓ(S\ɲˈT  ϟ@ JѣHb0BL R @ҫXjʵׯ]V}0!f%X ۷pʝKw# a( -ں LaR&:ǐ#K,Tj͛9/̹Ϡ%[}waШS^ͺȆM{sNz{B{NJ(oTn\#sϡnN:Hңn=NǓDouᛟo{"wߑG|!xo'Q8Yhv蝃aኪxHH,h-8 7H$@#EB;>)eMfdv G"`Jf'Yܘ]gfl^Y1ymIכ'e\©砄ڠ6Zז2Ai:[肙שx妨5LRJ٪'Qy놮NV+oZ4lb,k*lvǵ@nbf)^5nث;̲kE{R.*k?ƫtcH0n9Q-d~ \/I.{ɪbl+;2Ȱ!/#nKW(8JtC\'23V: T32xW9[VtJ2X/u5z\cڱc7.ʮޓH]wO?ufv+oxΪ'>k\gogs'׸߸{6jH{}{͋-..jy.?3V,J={g:ޓv_4P8PC$td,NfTʋP:ӏVC[NTb"JDdur j=$' ͏ʯR5RE5Q@AAjPv3ꢫZEֵn[9*{'~YC $[Y k5ֶ;,i/u]◳4IA MT(M4 ĩGD -nfŦ6St+vm[WԄSakkEgq;9]W[/J !If$<^lϝVt۵:(nXUl"->{/6Iibؒcp ,XƽUpp_[tyu̡ q>ޓEc'G$ &m`&ɈYE_,3Vmim'uMF <K2׌eL~NAf6:2yn-ѹ·6tygh3$]JB4Tg xAvtD% hSz&tlgVtYHǹ̵ i6;ʊ^Dc}T_3X{^λkcJFkCF* P?l[oɦ/j\g8w57GߌE;șmu[}K o{9򃙉:b7vqIP}"qЁ Co~ėGq /a"XHH/_-7G,d}|r8z`!ڴv]N`Z(G`bsjX,q(a~wPLJaSF(Mqx27wU,x~4HP0&ej}7i=(8"prxᆐ8q{dըHGȍ%H*Xgw嗀Av٧?_€wwh0hX`؋(!D$Œ؂('[xt^""BHQ( ]W~I`xFcchX@#ȒdnjIXv;$DiT!Q%iA8QA| qH/ɎxQ{WvɕTvvP1J)!ik!sI iT#Aި~)]iqhRވtxr|iވ-ؗٙ4B(d!אBrsao9gP8=闽 Yygٖ~ IYשp雿͙""('p紐)iPdIH"xן:Hl0!Q9$)e"b8q)Yi3:‚X,yW' z +JE8AACq` ё a҆8q9Q"$0 ᧃYIsѡ&o(ٝy ک_*~0j@!gXЗ 1e)!d>hO I}Ɖ!ޙ ȅRJE*vdϘa{W5ꍫH:*% 99_.d1&* :4220YljJj$ ثj:#qP2 ѰaUij!7ȳ&AV!1xP39-p,!3x!)cڢ|JJBHeeʐDz؆ʯ]Zsz +!*;)хDVAZ7(xѬ٭:j)aw+$ +fQjV)$鳋+c*Vʹ"!DIu[~{+ڼfĉ<''˰-х QD0&jjj˴(. ֦yRɼ3ǵn Z!x!*#bb)Lp2x{!k+Ck$ wڤ* k/ầa1aivBM̿z+za^K"ڱpƄ qy|W&D+J̬"`=Ⱥ MX;"Ln,;86!}Xm,`VQE1=b<3 3h,WHx,.ZOM -]*k-7r2Ϝuֹϖg! < 1CPm!PrѮm$wnǬ{=1O /1HM!}%:eHr=Ɣo=,ڄ]H!.S!W)\}l=wh1荞1,/Ha!W]Py-]{Mm̬"~"2J!sDwջYomywο~,Y>R.;a.9im&!شPZj\6anx "j {l.\q>5=9n{b\J}*pA+6}>ɦ"?n[=P2QO]ݫw~8[*k[QNE~+h(ǖiY]V,VJ|T$`.hTS䮊_A% X.fG_I {oKR]^AL`+{Od}D5[Kb_\NbGhNhZo9"Ra,`~w7R?ڌ)d,_-މfȵqJmOr~mlZX]-^c/@DP!`a -^ĘQB&xQF A `%GI0rN=}TЌ-IҌ-PO0,gJiMaEѪT{hX۩ s0Q X'V>!8PbynH926מHn޽}ϴ oJU @;޼:q,DR& ` Mh?MO]|~#_dñCwLͶ ,sp4KI =0)ڶ,DOLƒDŌ&ͿÎvrMqwԮG[.3#T6PK)4R)a2K;N|A{+AWL1QŃ$3:3> <4P@2rG/BT8Ǥ*@(ȅ\ TiC垌RT>YIPUW9q"1нZ-HWgzIo>{T# nW^KWܓbLe5X6ۍLˑIA#vQh@]s%rM+XC,֕bسwۼW[V "xwڔ%0ݙM 9M}1< ˫ѤT9Q?EIY.:x'jRf]M0UfoHPR5&DU+FBw]0tѶ%+RU9j?Ijr˦e)#@b\7#kLa9iJ\oё&Btk_,{>/5wi9s$zt!kxV#X2D7 w3޴DV7ϷIL`xI7ehf/bM{GZuMM ޭ#UQVX5ziAl bHfFZ+܊w ,C XtJ%SxBVm6pUHKw7ᇇ_ZBv5u׳g¿3Ϛ y,-Out`\ u`Rq`mL뀥`aAI`FgtIsb!PKI9JAVGWk̺pFk"Į|bNwJ~DJb?9ɱHvsV"K4s@?,t`/5 ӜDX..đ6F&fĐPE@8In㌙ i3 ӠLH71@'w'<)ٱ'壊)Jm9Dd$OXFԢ{#nɫrzxQG0;5reǚD{2u|*Z\ԑ5'x:5`)Lh+yJtT՞t@mVϩ3B_zI֖tFE2*qN5FǜRmeoT3c܂+ִ3Ϥ2B -V M2W#eb49/KQ[]2jUKFǻi43DF-HqTԝݷfi +FS-vYe=ӲI1ڰV5տe =D E~'e/ov0wN`-ۡ[?Ks?7f#ȪwZAC9ۢ!8L)OA;$%u WC況j?#1̢˾AxÊ?O;4I4' ہ8$CH RC+EXF 1S?%]S M%ԕCHŸtT+Rqܐ>R@Zbj U@՚b= jUTX M mAJudeQs<@̠Hc \R :Ҍ0* %Ujq}ZR4'oݙ꺃WVŊR`dםt !捦i`Լ0gca$`0jӢΒhN ^a9ߔ՝fN j&a0Z+qKኩj!,l+'`~lR6ckl!ll(<5hf֮vؖm&6FVfv&6FVfv'7GWgw '7GWgwnqfIB p~5 GrvT>]8(r-ڮm1wв2,75`s43p5ks<s-+=_pusm@Wp[>[tCwGHIJKLMNOPQ'R7SGTWUgVwWXYZ[\]^_`a'b7cGdWegfwghijklmnopq'r7sGtO PsF8wugp> .tz?h22lcKPa:?3gxlx=/xd튧dvx/v1oeD:n&gwln)Μ" r$W7=SO8Tw0YPSz$o'7GWgw'7GWgwLJKF@ww}7?@Bx?5A}qwGx/x!{y7GWgw'7GW1R\o:-U  2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʁU\%̘2gҬi&Μ:w>D  y-j(ҤJ2UZӃ.Rj*֬Zr+ذbǒ-k,ڴjײm-ܸrҭk.޼z/.l0Ċ3n1Ȓ'Sl2̚7s3ТG.m4ԪWnZq  ڷ_-:C 2`pƑn#=Buןs8vi3N׳{m1y{= ur%W: [vmAx!j!z!!8"%x")"-"18#5x#9#=#A 9$Ey$I*$M:$QJ9%UZy%Yj%]z%a9&ey&i&m&q9'uy'y'}' :(z(*(:(J:)Zz)j)z)-&@L8ЪZ]A rC L@*4խp>@#kQ );{!@_ !(^xY˧  ~*&n;/{/// <0|0 +0 ;0K<1[|1k1{1!<2%|2)2-21<35|393=3A =4E}4I+4M;4_nV[Nm .5Hж -Z\~gaB限6{͎ mMe[v|_ r] ~|^M!֋K>9[~9k9{9衋>z$OP* %T.P{k;zɫf;?=[=k={=?>>髿>>????Śej Ầ'og Bgo IVb^y[2[!@ĝ.(x (% !,g22UTUt5T665QQHUJTH4SS't@JP@ITTIIIR#$PP4UUy JU o Po'y JQ Pn hȩ S} x  ȪP04i~n *~ J| }¨Uy @~B 㷤hcy |( u k } u f|} l4n ƩfRx X4X4ǩDm4~ o n u w C ~ HPk§Hp`"LÇ#JHŋ3jȱǏ CIɓ(S!—VʜI͛8sɳO-]dѣH*]ʴӧa6$Zt!Pjʵׯ`%:aسhӪ]˶-ǠTcbuKݻx΄ Ӭ޿ L >%̸ǐ`F *@͝#Mi4@լ]vp۸@LY6׾}sy=6̻<׿Ͽ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F[Y%{U%YVa)MC駤)UQ-fY*+Iꬸi_}+Fp*k&67b&'~]hߺ-P6wݸf+fEWqb aoy[o۩[բ^g , 姭:lgw f#,R' RձlH2\VH5|.o~\Q]VU?pK@*W@E:|WA BpE`{"*d4\<'"gR "?L e(?"BɈ!x8&:!ĆITbA(̉oHQQ- KE1G\tv˜(u<]hE 0':D iG͑%拞;JR?́D $iGG"ғsKd%QcM4 AƈL D2Zvwɚ)kH {%KN_l tZUnBL=SF,5cVpW ʶmSo1aNo4g7L9ӗ'MS- \圓fB-pf8"&Γ<Z\)yr5 ?U-2hA:S`47ECRxVhnb_B*6HI:".5j#Iџچ JVʼfN}RSjUUYLz6ϫ \i(RTluEjYNXZMjT6UL$Jhu3]̓BJ\&XV T*YТOS*,n!gTVj *-N/+ۋ~ҷ=-Nqoe٫NHM GM`qq7Q 5&]/@7.[a+9t*א(c{%"6M^+\R2M{Ҍ]_S=zU72w > Wl2*`.ݝ:,b W6 WǣS *ǒ.F\__]1+46Wb?Wdn!MΈC9g:UF3lYn˯D2NYYʵ3̰G p3;MbЅ 5Fwy>9Q[Vj׬bN!>j]f5(҂뢷LᝣYG&PK9N; E+Ϙ;ʲD7{dw ;E66MmPuv׵}e;e׺*z7-mDXw.a@[0l.C1kU,At-V܃ (VɅz)XӰ1Hm'K~=9pkp0Awg\~ōT;F9Ǜ`.賉B/ne:<.;N_ b@ /yakOz}8hyýM梢yi]*e_zh;`]F|‡3\ί i_LGu͗|}zRo?u@}Pfev78o3e&{y|'W9 85gzw&x}|%}H⤁WW\'$}hzs? 5xz8&8sG?:(lgKdLH`ׄӁmCE }l6X&}UYqWÅGzONqXehcÆ@n6W=Çoy؀dH`hIpFZeGhhI(vxSK{_6d/xC8f&hkR8Txt؉t:x(h&r8㇉xPs<(xjhh5Ȍ(jcq㎹^%Wx8gs]ȊרhDshX}lA;6јȎXgҗ=&PȘx '%%')))XO: is9x丐49-yYA77XtZvDiiUGT#7ɕXHE9986ٌ^ߘLA6C$+h: yWBg,g-Xmc)]֗~Y9PYq)nØ; VRךF2]EYyh,h~]ᣚ蒵y^>rI]Dmɉyk9Hbٝpy=Եj 5,g+ѐ9)YYvɚX۹nɒyISy؟^XB&iEIf\RCFw^AF7>n:^V\YvJHȠ5s[x):z˳9'R:y)MLڤ=j}?{), S'[FN )jʦb% K3qfioYk}* ]r /  P7J7MY? P** Т˹\ 0qʩڗ:j9<秒: Z3 XDYÊ `0 Ppr94l\s늰DQөǭ?~z7:ww:ME`G* :+(`AqWCJMkӰJ*ky󣱒a۱[e[#F::ڶI{i'Ѫ;wз0y?˷;@[ f[`k+\.s*9K+۲$8I;(˴q5kk(`ѻqZlKca(8Z 5wN+Aw;+R~뺱gOs %:yv+EqGZ *ӋlP\Å;:Ww=JFI!*;tKUt)۽[Ä{ "E%0 W2 p@ʩKIɋ(\OM',Q},p :~$ŭ[,T  کƦQnj{{ 0ۣ# mw̿A7w{"2Gȵşm ?w>ܷPL ` `j,K`|p,|r{Ҭ*ܜ4?{[Pjœ&L,"E,lÜ0Cwir 8E\qƴ-ݼ2x/uq4}Æ7\<qy,QL tJ4WMAQw[#] pTKf{>}S KlA2d7ƺ!">Oc %Z~]Lz݄L6a.zq7aދ2#'N+tS[]8ط[!\-gq嶭8Ɋl 1mFL{mS-g(|A\}=n;ހy:r]┛⺃Lhވ!ֈ-{+9k>+=Ȳw{pN}l yaЮAu<ξ=!8.t~N"ƙ&x^N^+L)+>4 "0;A)>?52^=y ̓.ߢ5n!sI匤.+4.iI;Uȹ=+i&G)q# ?W@W3o^B"(x=t/M.1ZDZ_nMTH1!_I+>ɠnǻ* pމ"˴bУn,wAVj s["o.=/sխYtFy{%ၧ(ccٸA~g+T; ;Ͽ&C).AdP"Ar[cA\H5D7I3#@\D.Ɖh)9 b 2H,+"lLH+Tl-41! C* n#.(:B`:2/-*%3όʩǓ S"H:xr0+0 5EL^0 '/GBl;@OE5U<.IU/2ӮBq-/tZР<؜2I҉GW}Ut"?|5[m,mZkC~ԲZn5(W])MqNe}&d6Z63zq Чof8AVMBae=x4P!|2D-H^L TX'7!Ψ_CeۆoYR^8܌?Ԩ 5Vegӆ˱bl*:g& Ss˃s8b"å K*}ZGr)*s'|٢~mh?~!nF/H3[Ԗ< Il"#V_BqyHL;4yq밧:fݕʄ< ' "̉(ZA@hBu @PQkra_5y-X[ ,}AYʈ'Li' 㳌nfZFiBe a 6>61d L5#BUu"( L"4ҠU=X<խ%mcDXB 1lE:vꤖC,QyYUm91,V.Md!+۩`S+PȒ$_}S(}SK kV|JU"8j?5HیDMQ NxYE2: N*.ubې%V9)gBk]q*WPiKE5;qAHQoe:jkVmA+,d'w"R`5+)x[eMҀ!_" ?F}R9-kbM-b4c*C~֬dW?,N6 ?K8={ ~J/= Q)‰,Bj>G \*\=2+< CpRBI툼@ԉ)GT%-x IA:á,S LDBHDE-BaCw>\K'ىBTC캢9cTFi?+A$ R/gPƆ /[pE?oL#.1TKHZ4CEqQȀ`|,ǦDĝ`FX xD vdG|{b7,Dz Ȁ~L$W2ЎYH@_' I&ȓrI|; ᕖ 䚗4y0 >IJll!:J`aF @\IKMʮ˻K PK˿hJL춭IȔɜȍ}~$4DTdtׄؔ٤ڴ$4DTdt$4DMˆR|ļ|$ϟ4 Iτ&$Pc =P,T b1}Ȓ mO%5EUeQjMQUQe!5 !%#C$eRa9&R!+.0R,RUa-0Փ/Q15 53uHS*`:e7SS %@=m*؁(E h5T@eK T(`LU&S= 4TuWXYZ[\Ti} UFH`V,KUp̞VȌVA}̼,ne8lR ՄPdMVqsEW֝Iv}^xVgfW7%WVLWaׂ5؃E؄U؅e؆u؇؈؉؊؋،؍؎؏ِY}ё-PBϗUԖϒPYu P eO QXY ٣eڦuڧڨکڪګڬڭڮگ۰۱%۲5۳E۴U۵e۶u۷۸۹ۺۻۼ۽۾ۿ%5E\ IVL\ߴ)|M 0xWkWl\un]Wu5tVU]۝Ǵ}VLVu\5EUeu^SZG:K^Մ^DК^٨^5_ޠ]_ٺF_&6FVfv &6FVfv r^baȝaja~{5Ͻ &4]]Ea]\J+~(k=b-$ ^-W0$".E7P5cJc;9]c a' AlP>NPmdCHKLMNOPQ&R6SFTVUfVvWXYZ[\]^_`a&b6cFdVeffvg^6&^fV5߽ff-fɇPPg(.gֽPJtb|.gx̑}>  g 6}i^cuG̥e]"6d&6FVfv闆阖陦隶&6FVfv꧆ꨖur&Z82% RH0eH. 2` (g99T@ IiӤ pqc A,y+P8Z@ڈ&V !,g22UTJQIIQ5Ut656PSSPHJH4't@TU@TIUTT4n I*#$RJUP PUOP'Ȫm iPSJhȩPQ 04x ¨y~_Mn m xn Jd x | UƩ@Ry x ~ ko §`ey u m fO~ y y | w fl4m d IX4n ~m4y PHp ( ` JHŋ3jȱǏ CIɓ(S\ɲˍT Լϟ@ JѣH*hAĄ >ԥXjʵׯ`ljC hطpʝK])2lTj LÈ=NXĐ#KLЩ;q괩ٲϠC|_gG^ͺb(;mٯsͻٵmn۷ȓ';8ʣKN]kůc8{{ӫ_u˟O9s_s߀h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔AԓiFI`)|YNrjjR9F*T^_ 檒*TcfPȖd&+H0) i:v+k覫$j简&~Ż-z{y/ # %,:{,gw!4'"{z2&D @J$|;ԳIus+P2(u>I04D4@#}=z %$WJv'5p&M3%]=@&=5' N8)eXyI 0yxF3I[~R3|4͡D:!In.zJF^-RH֟3$1 ාλ"6-){nR 5ߥ4ȏ>)k-(~Hϟ$xϹIKHP<ӟF;$㣞$g? Gy|<>0z[;@Mԑ<8!+W80%ӊ 5H8!F's[caH0 JT mXC)TPTn%@f1;s(~$nUw=ZDv7J^Ps"&8&2,ZEb:*+tޔ(Яȝ(rKM)-CK..^fvV#rHQ9HP+ mIE wHeȎIw e@`(н)g+= _$V6h8I@J_!aӯ~mcPǙ%GB-.Q KU&yegz [&dDT}ajq؂-2y73p' &~E~$$o]!gXQo XKydI7a92{e]wnea&(1怦W}/t4sl7bxGoTHgauYW5.w{QHO~C1wD#ٓoGq 7'DHY1P1:զQZa0Xv*%I)/9 b_~MJȠÉ s!yfoX) ƤdM 虬:9y֏UZśI *# ]5ã`HUw̺)щhF !8+(JѺIJ Hbx Pj")[z/Y,T~G:[jk)6@!ؒ zb\zgJ[*tjz&֗qH X )Kd(g2:kҴXIA;+JRWfYFjk&;jYLX ꩔1 ZZ[7^2t/% ~>[նQqK~\[O&ëZARٸ+ukU*;& uqK&%p tʷφyKy&Z犸i;{3OJ깷ewA,X{پ)VFeK&!k#ٸTŻ9zc+Y˦&+*뿼+HUڻRx99bQ&]/ڳZ<kZ۷bj+&;k1ܻ>fl[&!# A&\6 áصiK+@ ALi m蛾VMv<;ÀHfekœo1U,1 "!ȪU"LˬX\QFʉA;K<W<\+˷bliz]ɬ|KYf{}m ,JEX V!Hq'<&m@+O*Al3ɹ*eӄ˹#O9t{ î &GdedX r -ş.ӶH N qm&7 ͗5{icmĊ͕ue&=gܑ g]w]ӆW̷9-&5m]`R7,n<ӧԭ\dwQBo Pmm:w!KqaM=Hp,-ՇEGަ!у]Vٞ<ߝ1 eMaiM!u<ۨ۷*l7 \M{M+Kkm-C,]]q+ؓ`|W uqq̚F1چӊkڽZL7Da%N->}W jQ=}^mՕqN284ה a=rQۆ!Oޮ @Z>+F'z^G.uztZ+[6N-EB@"M jd>+_nؽ\Y>~W&4^~.z!a^6nE ak?.{s>>As!A&jmۻ,WMV+x#aq19Vdee(]̱,oU6O:>΍=O 5)>I*j~4ln.28ilo,R_+80ڑz/,?mÒ#ZA&< 1/ bKo1&lrE@YQy?KBѴ/5/NHox*wϽ5?o[oׯܯs?6&3=Ps@@ , R.%Vd S= tOEET"\JQTQ)"X8ˏ !W t O0j4h遒x>p ߔtEHUMč?rÍ_fۊ=Jص `vhQg|4壥 ׶^|ugFȻc̘cG\iLvH؝m[@9 }5Qn*9|Qy:܃_9t *䣪1rN<:=rH|jM& hj# ܊Fo1.F4pj>L,ō .!T^ƕڠYuN}ԋo,bۋj&_[-ce᣽v!6ߝ"!>ϷnȜnoiryة ?}lʝޝ%Y$鹿}qKB=mrߣd2%rr:|\ലV*}QǾ=}8 ^U]GLgϣ"XSee]m1ؑu:yl&t86 ~DЄ6&[?5 ̝ҖL~πE@Q[5x9eRt"r%G1ƅS9Bнysc#kr=@{Q #֚Hѓ&ol~(< nr# z8<ѵneųe 7B>sd$-12̤_Lv^+TIeR$l-#`n2i`I iH F1 aӅ|yp:YΗ@1="tΊhM@*;b' !rB""v#&%WbR2extDL (; bIV UNeɢ`!e?P ɥ6/O32:jͪ22GSJp޴)Q[1d-kɣ&Ĭ5 :3_Z5BD'"atY`d{ۊ!8h1q I 駻"^X)pX++٧aTV$h\hOL-e$T*[ γ8jԦP-<Ⱥ"e"qV/]8NVYR,h^rի֫e'OE{"ՐKf{}R 2p ?j7 ū7Bkwa0ĝ, yLl"&.joW h U,N !%bl/<໏qq\ɋ9 J"=CݷsܻNad]m̭@2(nT~;U}yƻf _4@"[{ 6rM ƸЎ~]z-Abڮ+sEM poMTH! \%k bGB:ңJm˝ה/tEr> ,]jH,`wPvlF u(Eڮr/K9QrKgo;Um]J&PgřM_Mid;kz3q GK8,YUu3J:dGdA%9 3C  o2/[vokG0yM*;:Xr]M `=4e]drMFr:6̮\ 'Ϝ>q{Χo# Ue Z{uL͎ޱ! zc!6HeuwUݚM棐돴{!?z/fӡaKi޼NQTls?"ڳp{AG?gzC-()OS<+1<Ó+ȼ0?P;*HK;2=íj xk#`+8uA?,/,CA,8?$.Ш;ػ'A8j=l^/he5pSXT¬2=K{AL>p$PC[C3t>)SA,и`À -Ծ:Aks/,-iE$0lF/@DлC`S, ABթWLEU|XCЀC䶚Eۈ^A`ł(FPCTCB$V|U9ba') 7Q;cTFmqA&i8:¾EQ$ESFf2 {R[G m>@a\?U)DZ|Z1 AHQ„THCL ! # ȓ0w8|@t\Es<H}H2svI_tIɗGI72 H$J+~ħʨʡȫIr!|,4ItJgY}}\ Τل%R]Z؇WEY쉔 ZE֭.`̗[[MLЂ"5[Ae[iZGM[YTeT پE0X֌۽#Zµ yL\Fw[Y܁A *ٽ5]UՕUeׅؕ٥ڵ%5EUeu%5EUeu]$8EBBHߕS4H@F5`-S,^`y<n߃P .( ` PG h5L &CvJ?_ _ !&"6#F$V%f&v'()*+,-./01&263F4V5f6v789:;<=>?@A&B6CFD;Ud#NMGFQdfGd^RdO L&@Tb;uYZ[\]^_`a&b6cFdVef晚 _5n ?f#NXf"f` ^F`r>`m`cLgtv Vg8g~v{g.`vaiajF臆舖艦芶&6FVfv闆阖陦隶&6FVfbljeOvj%jݗSH֝ j՝+S&]ݪne]j빦뺶k?_jv.l.p.$l֭&.g`VXx>|}qNf[ |Nl&fՖ٦ڶ&6FVfv&6FVfFF֝vo O- ~6"qVatV`gHށgɖ`OoqqJ`r!G؆"W%g&w'()*+,-./01'273G4W5g6w789:;<=>?@A'Bg 7typNt_aF MA?Q aT_Oo 6.txU/U/ gP?[G~ r_g$'egfwghijklmnopq'r7sGtWugvwwxyz{|}~xnpeg־awv }gtqφv&tx^gz~q_'P\]Rg kwtIBJejeFRD4[yokdӀGWgw'7GWgw7nD$fhPxhvhy/Wha7Ʀf/yfOyVlo~;{gyoRyG)zxtWpϯjbWDO!,D:22  U  B 곴D@A < |qD2FHQE=J )dƓlD&Z,j_ !,22 U  }<# & ( 8  @00Ç `AZ1FBzcH$<1eD"t `eH 3S ǝ! Hh hشDF A J \Њܻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ NqM9s2.w:u̮֯=% '? U|ͽG}}z:N< !,l122    UJUU'4@aB " "C)VaE5~Pȋ?~l@ɏZ|L*?2 t $R4pE2IhJЩQ;D@@X^˶۷pʝK]ͫ-߾b(x†"Nlp1c;f<9ʗ'g.,1d˂?a m1}7!,G822    곴@A < |qD2FHQE=J )dƓlDdIlSXf4Ϝ)8x`R@A.EAB _Ӫ]˶۷pʝKݻp`wھ~,q0aL ƏG> sGjE@QZ>@(VgU#[i!,1xx22֗xxxyxyvv++rr// mm^^iiggTTMMttQQqq55VVEE oo ee``BB<=<<OO::@@@  @x* Aŋ)Pqxс `I9\9$nhҦ d' ɔeӖ,)S $,jTB5`X%Phk Yps1^h^ L/2P볱c  D` Py6@3 X$-X!,22U~T"n ,, J~  OQ PP ''m t~UgdQIIn Qy5656PHx n ,,m SS++H4e'ft@JPy @xn JUHyTT;4x ߛIt} ~ U**++ITUm | n HTy '--|UUUJ} H++~x *m PߛHt~U} }H%%&&t}P&&~ | Z R ߛ| m ~t|tJx rx }d !߿ߛ!Vk t'))@U@Irx ߿4y Y u ~ y R< n {tV y ko H P‡#JHŋ3jȱǏ CIɓ(SdСʗ0cʜI͛8s93O>D XTAϾ{K,kÿ7H~'6'[R4`ken`fBwU`rm([zhv_="]4^"Xދ5B$c@ٍ iH&-PF)ML~ ZSv%JU^^SrhzfdJifpIњ9Hoʩ5Ħw&'I'v堅6%9j) (颔^i铌~j꒿uN(*mZR&Vi!kl:&ZHlji%V+.Ob-Hκ7V:T^ Zn{ :-ԯ+pnieѽd g)zDyK$.^FNϩnk6əyW;v !'|܇V|o~v~<3~ >;nj} F_u!| /̙`*ha7:xF5 gݠF*\Z(pnwCꌀ GCZw# g YS"eoS"XRXA>As Eu+btBl#AL9VH+! ؃KE=nQ(pA:̣#kǠ;#IE~$ffL}gEE^lL+NdhF[j/aL.T }[c0|($j$9hsN\'NU@ĥ&{I'?OtF :>P 4VM}^3n'F7/rhdtW"Caѓ+~!LY/25MkR0l$OvSAF0/(Jep"z@P*Wt~^i xuq"ׇ ^45Px&EUYU8mZPUVZkKV3d^ip6?:'6XfۤAmzYIYZkp/b  rٺܒI)t]vJΰ.C: 4+MJfE&Žso[9◼Y*>TZV`ELs[V`y8X²k/ `^I+b\GcނƤ%OڟxW"H8F-*=oC7Q.Vjp .'ەvYx#3'nM.L,k?F1̐<~FOkc7!@fU8m`ueŘq{7 JlqrMҒ6`P 3|:)Xi;D]twj 7\ߨ:٬tP½V=W{P}qMm/mlP%>iAJn>ѹ-vNf"nIJU kluD%fs=:YN60.+n%@-T;W bziԶ -i~(kbrtDkebn(<`ӕ^+aM[fkr$rC\iCJt//s%]'(|mYCᵎϊn7ewp=7>z8{+qߪ'3:d >: 8>;yʐ\M̭K\ <;u8y|"WzчdХ}{itd~$$k Vgr~Xqx*bIa*%p&+bg@vs"y;ti} 7]Aj}5bt`y]W'*Wd&~Ay6xD@av%sgd(nm Vŗ\]UZWh}$V|_֒~#c{sǂfV] &|=Vh?v!zq$FcDg]p4ׁOvPv!f#! |3YćxoȉUYB[ؗlWUv%`rY(VLe2EX8Xdcfl]]Cz_`bI5/`)WRoS^T)`_ ]5qeiZ@JxWVs 4av5xҌ&jX'[0بF):*59Zz{ZM ReGI1Q BE6 rg?Fӧ!7 )lGX9*_ cet\z 9@EDFZLr:Woq± [X\e^!L ?Aȑ!pvۥvXWa4Gc tѝj*ֹyq^ Tuڥ^G$+}Z%岌)\^ؕ~oxGQH[Yjh`j#B۴ye۱z+G ==of Iu1߇.v4ITI=7I6mïZ8Y*M})lezV;Chdjk M,B?!Ik:B;1'k=V2-|P{j)6+J_FjT˱:NJ \8d*Q]U,Ljq7 afNBph,jׅc#g,1@\8;8TK`y-Jae 4 @퐟Erqϛ_·f Z=tO\ӽj(+)ΏYܢIp.bX?Í"th)*Me\^8ک-!B M`9 0`N/Vs"!O\dل+X [gYOחNx<*޵QU`y$#ǽMG,<^A5~:惝vŠPג8(~]dJ|>Y)bMlmIZ0.L4^룔6ݛ~a)癎Ѥ;Rj]H6m:%_Ni>n վn0f5>˿@|/0T@wI1̈́ 䞢}ȼ~ޝ(xڹ+`S1MpmhJۖ|./`߭*<]o^Fd{{^R N]d%1HzC^ /"\C oP`* QF%hH%MD)QÔ-],9 4N @D@ ,@$C,Сr"4`S8l@`#ӄ\1uCPm 0uͲq-(VhC (P5"S#bƍ$ cm&i3P`Z,*+A%FΚ-ѿTV=`sCȧ6 .Bpv0F&$,X, z'qN1ϡX(<2rBN&,C uSK(4$NQO?];P[ ,^DP# 4r( u/#QhUeE3K U, +SmaY}ԚDU DuPoPm*G=5l"Um2ٻBv)0Q|OJ[N/ F-w߅jAI ',J݄fųcᛁEPSW[4<- s}3h8-f_ZE9 .x>>$:nDŽNV[1]5js(&{NZ;_/clۿqS{t$tFjҨ ]w!cKnDx n6=zME$)NFm B]t}d .u-ﺎmd'Y)GWD[CȾ,G&W+xLv%(v7 2'?r .mJBͳT4@}ahw!sCTzB6% 0K`2 ^ tś-'4^ü"9;Dy.Evt]'įuijѡx RlO *"6hA{r^tFZYe?'|cH;ب4^'PGI嵉h. &S0_#cHYǑ6) dZk8Ah㜘ʝe[enT)W L[%iܒC#Zqa\ _.8klRFJ @\͙ahRMR]BD=q'X c0&lv(eOgË.mRB9!9Tf6*ũԀ Z|Ck'J clŝR'T^XՋU'*T=NQ9Ge1zX[ǖɒF u'@#ȼjUtY+F"5c^9QyΉϬ@$Ժ8WRJW.r^sdAqeLTN|b NH碳5F1GF} ױ ӻWf5'wh(hވGd9V]Z8\a}Tm*]I]mW!æeWKmSs >ϫGUn,ڮְej߫%%h`+Fj5"*z'.|)Š:n h'a wWEtu_uS]NWC}e2cMyge{gxLq$'lZ:fk97iz6y a` @˲ګա@pz=;C9I['>F*p%B Qh4`\4/sF3S&j$}k E׵9.#Qjv깡R맍;9Tΐn`9LlMF=h]y/N|gTA:ӷ>+$a7˒4Ⱥљi~݊%ztN#ag=1.wf&^\g@6k1'6/ӿ.Q75ʾ1Ͳmw({Q o7O}n(['u3R7hh%tA.l)?CJ-8˭k230>=Lf9  s@ 8Yz.)3BQ2K($JB ."@ +8۫cೡ㪵3œ-ps2& QzBZ qA.cc6;@a01L!kqC=8 ' ”.*s w0lASDBX;(D,A*8'Bi=+:׳EP$E14BĄ(:3%Y zD7uۛ9DC>=a$e,Fc1+C# cFO j􊅲ks{\DGUFSit!Cժx:rx9$7sE?^:E(HC`Hu 1SNGt>iI<1~D=&Ai p N,> Y3qLlɯrH0Jǿ:[ȵYT&D/ EREV *ǧdt?SQ4WI)J],  7)\BDC;H (K 4$F F Ks m'Z+xLT@| L Jv)#T 5Ҕ 9zRs'y|F `4dz@G$ 4T\ǂ0Z$ JFY=ƬjrlFDcd4ả3ω8XaO=ItC92Id G/1o\1O6NhIL ~"8B f;3H}&T1J8J5T pѠzPTcI3\yBOS!]M")#N.%u3'EȊXؤM\AIFC6I)-$S1)4EH;SȻ[ R:NRxS>T?P WKT4Z EL=5LN >aS1y"p NQ͔RU"#kVyU5Īhh:THaȵj, zkSBkֹPj˷#씞qFq聬Uo% }U`- $, 0WeU{PN02W2tkG ׄPȊ@^UR>m+` uPD]V$TXEC=|eeT$ˊ&RY;Ar-\:T?u-lVW: w^[}aC I|؆PK+Q۠ݰ,R(ȂX[m%XׅٲTEUR%\=|D=NǕԷ-QZʢ>Ϫ&8ˈ\>Zav-u߮EeLvy`%^[\v7/⢲ջF >[Z↙bFVmۭ 2 }&҉x=U5E7ͺ<wb8<^I `] a*pb6 V^ݕ:d5l@4=% QۭPښ&xDNdI BF[6\䜰xf >a61f e~EQUfJ`X 5v`Uo9id% uޡv. < K36˙Ph[d7v^.hp~PH.>>uF htzg36鶼:c`bTYK.ghɪihx^f^}S~XຄРvEjQ#fhQ?A状-nL! h䐶m&lKk)Fink~e4bhk읞f֔hlcW! AzLN^_& LN'u˖tURՉlalmRYk#;HpRs3fihޮU_Vb&C^ūH#gΘE2ZΈѣgƐԣ$N Rޓo~;~Xa-oK 7! 'N,aOҭ)_p}h֊ɝ 4m4o0Vcvkk q%ذRɅ8>qW+vd(go)_*'Õr,q\bI% a8 h=Gr#?1U6o&w7*s=N&rJ|ysz~$1"'fe"6FGXOEW@ (6rෳu\'l-ߊ&Xr]~&XC_ivWM 4 "&@vpevrH;s(+e#nᡜVth'uFvVXapx\sq>@ `;oakWuyV{'vGu~hyh'xժ? g oCsHzhwwOpd>bkILv?nz>_z7/x&M'IUy6[y|w|q e_/H㾔ҟ1 'ypn87g1 ℨz.;7ժ?,W#Y1?] }lo&[{VH X~uϺ}c^ lNyTwxl 4` „ 0l@$D 04dEDaBƍ*v P񀃔[N%v,S D+V- Pٔ%CnZQTc-k,ڴj6%&۸rrxζ<"tmIFHh 8 A`$#t,'JqJhLJ PbYAe()m5ĝUS%\ >I_@46Ǚ xDQ1 *ڶ쐘awB-j@ZDrQGEq8(@ 7vBoQ-mG\pQx x" J `rv%AD,&D5՝A(pgܹUHW_# \yRy W hCx_Ctu5F!(@Jiyk9dcXVCF"d7CH$ID B4piewq^$"nJBjǤ$ٙd^fUXujrFȐIRGSP >ѩfx#xC $Ő#iզECyBB &h-8FɎabʭA=p~k)ykн Uttv6ÌJ)!)WCj.Y/M'i v<;F+8/dWW!1|6A]= =A%([$-TۈBri쵶3C9kmmC ^ymwmu5۵]mP% '=xj3;7$|kkFhzs #ȯm{8*踶+8 `!L{էrL- P+>vA7_#{ ^oaE<16z8m>\" wHYNnJ_buEK |Z?ֈOILKƀ$m\66uF6p}"wbiӎ k(Ȁ!V4!:O#A,LwD&.dQJp",o? LQZx-эqRB;V#h/Ѕ|ͤƟ\axHjt\')3O`?ʓ$g @< #-phXH%MMo1.rUR%R"%_hA "ͮxǬcn^ nA̘d=@4S롥i%UgA4H?NГۢ"OBD 4kR,韐GC-_1+O1M|IL tD .RkFI /yHc)8n)BІR3(N٭t@8c:XyfҾϠ޻0D鞨Lb&L¿/XpTr/#-@7}b ̥>ժ.u[ddYf~*QhIF􁠳}(` Vonbαt0zQ!JbtE˭CuN Hj.7}`/l`C `DOrX(2U^ K \.)onqU'aPŰTLݲqd%oΌelH`K>&@,%XU崱YQH\3l!&FnfIG#Vb d-2$D. %G5H"VQ*ogܱ k J[8nF"oҭHitDCm b2wl^"Cb^*H3 VJu|nr VdBe t`2a|[HkIJdߝ9kUfhϤsA3#PGd$嶒 ͗o i˛^{3͟Ef͑0w\t# =4Zxn[緾hmmX,7җP[+hrs9F9/vBdUQ9V2%ON _ayqiP0ȴOKz17=F$DxIBstgh^ʼn',-Lc5t3"v]ӕbݞ.`ʯe;֝#i^ء |]beC\փz]2bGy;7k "<+y"^w )<me+Yk)i'^iGeHn]p_YmTi]A_u@ݗLڗ8YNN]a^,\;Y` s ŏ]ݗ^lҟQ1\$ۭT!FDr9|j՞E a`__|`±ZGx^ia v؈i.'ca0bD@ &"G=!DG<%^!D$b "z/%bP߳_p]uXX2Odf b"-6IU1(b Iaa3e#6a=zj)R#KXc ra!BTcCE1+9 cHD>>!9Mਖ਼M[u !U8!ݤ B@stM!bՑ`FA5h\ d$%9҇m0fa1jL؀B@Z֜'!G$ϽϑX\7͗|^H8!TbQeo`0RKHH.֍U[=KJGHa.X"I+e"Z^VGՑԱ%g&V}8R6ed>ea=2V%Aq34$`2&L>LN͢cn,Zf-qdh g[P3feTJWf|k [^nbLZR&&:At ~rxusS0#YH|M__tTBZuŗ(bJ4PnEexMf{g"\z\cotg qYGj$n'x GQGh8$z{yZX {Zc bg)~~hX[~^\ Y§uZ*,rKuFO*\Jr pDt*)pfrz#gS]ҥbϚ& TU )[0"fQA(y朖EUڑ"ީҧ@)JF'ShjR^#j>&j7]*xGDƗߏ)(ϩi`#hKT*A|&EԲREJ2N#N)ĜE\Dy&xXp*)6DRGH•MkD 0#+bh%:Ga6ѩ a)nm D [&'+ufrbd"kč~'e)j,Ŭjkq풊[ާfH=lS j엶U,>fw+I|ZYBm6jI ]h_6.H]{=,Ǖ-TArNjs$&kֲv郶 Z+E*n-kgNK+VznyFefmVh\ɊL(n_-1*ݖ]K|㒵8RdB$ o崎:e dj*tm؅b*,ŠdʬvCFn9kωZ/Q˄bAd>IئK!lKnB@f2ā.],29۲,'r#-J|<, /IA03Cǒ.5[5GwF/ s#څ. @sG:i (&\.8Դq0 Jsź4Vs# Cn@iGTmGGScVq?o61@ =b_@7sO_hBZn43Esq{m/*'4[1Xvt:slH'2alcgsP؅$j!u\Y-.~mv}EưhErG1v|&6qV6lOUEb+6\1X0eb[?4\032;CQs_%1IAۺȰKLvWSEwAH;]88y ]4Nr2wq[D7Zhe"o7|BKh]h0,J$[782ȂuIu {jlqpif_7*5rzTIcktREytr*(Nℋ8WAMk݉nvk(v6 C`zh\-g]4'w[..(ypdq8'Klvtҕ6z@(3Y+K2wb?k벍{ϺKIgqxz4:@ϵ#PGOhwF`@(i[ xq|7|\_3sER-:0w/QyZPRr7Vs]_{_`<|j=ţ @GO{R>fS= z~P= v- @v94IW;/˒.ԻQ >@8@$D@ !4("pc TؑdI'QDj:k-`"o7W87s`<Ɇ3`k0aJ-SD \K S N=EN1cmD;ќLcDBuJZ=e H)ֽ*d6? W$ToKUؐE`{=1#L>Quӣts9ymPAg 6XS^tK& 3m]Icc8{fB?sG2U i)M@ےoK~5f_!"*Gc=v0eWL* 4ۊy/ )JUB\< l9joLZ(-6z!8ֈiR|Ti yANR2 Z^\3Չ!6DsT;ح1g5J|ol﷕>vo]8OO 10G1֕,ا*ޯv JͶhݝ.nY^iGRWv,%'|h1)=ʎb@ʹ|2 %#~' |⃓XaM7Yf/Lɏ~Z?) 3mpfm-vB1!$5 A,ȣ513\.iɬl1A*{aHB NqPPb"c!jrTtE9 LБ #UjLHX]yj 4Bȁe}zdltjhHث˓K\)I8a$ Gˎ:y|d-\2x$$̛Pr;kC4I(Q(QuD 'N/8PuPi(ڬ吞G<p<D)unR~R>5e]ђi`)@DқBA35&pIh UDDn]^(@4GZePleL_*Pm(FbJ ~jL\)R TqTG^+zc=_JO-cS2m񧀄]<(.H&oʂƱ`Rͫ$J\1R{&^[3X1dW 7l$:?4(xئj2UIJupj.&AJ4) dcLfR3&>-?@]"wՈi*U@ƪTVeKY_unI\b|^ΙWBպt)]Zrn(-3uRr\+'Veb1=sPP☊I:dq0or+}Xϛ2"`DEgfU m2_>W)-Lc+c%2(ҩm2=N+|53D=>%T&:&3-hV1r]4CankȆsdQk 6Baʱ)F\Wwެ+:t*Z[I#G;vsgY.Bt@=igvRE m'Ջ7=G~1`I:DǶtNܝi{?͐P'yP֝]5P 6۹pϸb^b0X]lT͏SAAiRdI,׆iC]D!ShnOi%7#zvV$qmS}jszkx2׈4- *2vC]*K+5­?%0H{r5716#GtB=fL>t<+z>ݓ0HӇOǃ#5I5c0 Aq;`cmP imM37#GK,/9,3=S= TZ>IrΐP;a,(*4LL5ԲR3]@BSII4S V5͟&U!hhRE {J Q$SU%qt:?!GU}Ӱ^FUGI^ kRr_gwR#X#Vhlfr"tV'!\YKRp]7hk`4}(C8Iy6kdk7KuhJMCDr zuT_e-1C BYnXQQ8%Xp8 VW4~"~ 9J4&;sxt1uLTG#5F8r=IRИ7FzRg6'AYlB's&mmЅlV4Btww+prU%AvcK ҷakᷓB04i4 TXyA~beTiĐL(nCo'z k/YMU>xXs?rH,ytoe2%~zx듯<~RMbr~w DOY1y66iu{+4>uV))9-u6juoH.EڊISRG^pZC\:+-Q9ɰa+ZLO-ZPY Y W5 OB! @,DֺѨ:Ү'ymqv:81uYdd{z:+ͯb+lN zrڰa6S8X n2c,#\yVhTt 9ҳK,|*wH)a-1,![{*5}?92Rh5s9nY4qA+؋_Nk*ae:zyѕ7e5ޖy\ښ|9iKˢ.@,㽥仪aڡ}ML*A>e;/Tu ݚ^Kdj,*Óι9|؛n[3ڒ kJQXm5ѨK%w'$3[(t@,[}u|ܻB{a:'՛io['r{y]~{'& #Uqۗ{щ5(;xvŷ^%{6v"U;³܌H̦C/sڛ0UP<BשC,i v^=z!)8eW {Z5PկK,nڥd\35|2t]\|,fcZۊƁ{}lMf)ݗ[d+].],|܅cԋ]+85B }E0%o|T8ۻDt=cxi{=[81X%>[=1I헂HXPRADb&8;Qĕ 2'Z.G"hp懩o #/{ǝұښ&$J] ta?+>Kۭn= Ou_fr լ j_ <0… 8 PZ4 6xA"f41GN3Ν b `ϡI&@4ҥ %@F#\YQSTL91+ӱd:uhD* xڶv:E@e>p惐JDVlKX%JR, :·4Xt!RԬE5ɂANv(Ō[{6@Znq⾓~%>@NA^GC3QYe Q`p}E WJJ A#^PgD2ZؕYMMxzd|\Vumj~f]@if69rJ,D~_ & EYWE ؙΎ\yᖢW9`lk+ghC)q;&kб*ԬAJ=Q}\Z:5Y"מh (:D9~pj}Gl˲4 #'ILPmlx3Սl4鮘tCM9U![nZC͊DʧY[x P5jQOxf9XhȊݵukLzPpuD0>Q 8s߂x%7&G$ogC0yLF%rC9q/o V}R+B+S_ke[/  Y9$j2E5c^;x2Łsb Ccݧw|]n. N5,P`A LD=lQ2YƊb@*z3ACՖnL+QA>$^ر]±1[KxK"Ya;T䟫I uZ ծ|D˪1Kv0 h9*A ᷹3q/J20<Z *5YZFr\F~H+>D/STF0Qrlj3%}|S/[b&L0n(fit?x) C&O@R2و :@G5i}G*CXήܳph?(-,u-Gr)0acIdd.4/,ܚ6(uȉhNY2iQ8@ 3/:!zp.]hCJyFbC73A [Raԟ+]LP*E:d-˲nu*Y+KcuPF){:+y.Sj<`/1+(R3E,5IR&v6X=N*ieeG/fijSϞtc^I2oA3VT*y [26*42ͪǏ҅ly_: io`>lz*$%?q kNx$QϚd=ΟڦjeW3SʙF ڮ|70x5:mnxP!s8A!puض]mxVz]ZN).q4S5.Uyj]T¢f"rW"e~)}q#:!d7;s$}fO p{VO 9Sɩ^ e"4[][{I˅jS7kb2ٴ=\eF `m >5y .dϿj p 6BYs0׾v5L> U\b%!wpw{qY_q70|2hR@[G5hsEHuXPD$6{;XP BkGy偖9w2\h`uFM$QaYxhpw*rvVy<mU?vwiT-AS:FN Aj@BuV`dBCC{gHFA%3kgS8F3J7lF'ehK(דJ]}+rB}?Lc 0.֍H!Iex2ْЕ54-ى7{X"A!> k) \5xaTcTbqGcnfum73nXF'k%ވQ90PКuQXxkmIZØYwd֒EIV7YaXq4@adh,,8CV0F!W*y ҆I dD(nx|Z䎇.}ؗDyQ W^H98Z Lcm4ݏMDБHΗ7:<^>T>(hy5y^捎 fဎH(.N-M߽-ಮVߐMݜD]ጾeVV>5ٓоTC p]wT쐜ZT~nMO^SېT..NONT=nշ> ?Ⱦpݶ-=}e,3.-A/&@A/ R/]0H$hN] 7T?J틽-NL`o=bdA+/l_L_fnn.{WoXfn>?]o#1/eB딯=/=3yEqn,oh/^NOo02/-^\_ozN/@_ٯ$XA .dC$4`E5ncA2$HM fPK1eΤ 29uFXp;EI.-2&$\YْUY. psWF}[6Xͮe1Ȓ.P&] "ę)ځ?%‰:%,Ous(XsH?#7JH$ B.- C\JB(tDHC#|ZkqFH4q=ilJ6tH?Fs4! jPF'tr;qKL&4PK46c됂:.N<BA6l2O2F54,5UtѰk1! e='TMRN+].ON ,D3NR)RSWANM{u4(S[mӋ߂;cX}6,Ue4Hܷ~`(c7^84Ҁn j[ŷ܄js ylSzJI2my!zLYj+d',(YdAƜO _ĝT:)xj(XrNXlx'Nl/5U UsGޡ=WϏE"3Rvd '?1QWizGY~SݽW]'5 CW>eQAjZ5=P i7AEH4bq*}{AfkNf0 4ᇁCpK@hD!% گbEŤ%*.bT. cH&iNK#֨6vҴVG19y#&҉T^w@4Yda@A^[z5پL~r"E AGKGO!FtCUЊVI^N f$dz d2IK6sc\Hb'dZ$,$JhoCmАZ"v=(IOu(P\&nl%z@)yT謎Y-N48t!XFpd)*8ސ. MCg3ЙBEӚnpMlyh2"%gLX;as'zɡ>E3uk>$sXEXV>>u<}Nbԭ$DŽXU >þҜ+EJLh9庽2ɣJ,VGY@~ebI{ $=-_? ƿ2B4yҾQMֳM=oR3p5[<GSz:7hNS vEiZ͜F.Ji^2 /֖$ ~?zͪg^j|"XA]/+fQ[ vGzןĠYD>\nd2&WT*h@ Np+bOh*1v do@rv0d٩ŬS*7vu`P.vpKXJTsvLֽ~2„FdYQj;q>*Gcy炦 :ъFDx 0 +ut( w) [zY5 ARX/mk렺4~rV`kR؄Q0yG֣|.oVOՈzG1׶{&WۑomPگue~G0q=@PhË|CI?QGŸ&'0_ۡ+C*9S? #@ҿؓ5K(=+>ɾ@#Y?U*k<{z< A? ;س;A!b@!ľ r=$9"4?;ݣ@ (%H}[.,//|#z-3g>?S84@M(4VrM T|KLNsd6|$dINfC;1L|OOOOo$x3x.9>xB8LO@8؃lFPPF@2=cWSՎrK/%Vhc15EVT7V0mPsE]WuuZmU3sUxKInQR;V%`eM8|h]SQT3E}%YmX8׈-) Va% V@Y]-8@!P=PGM3іmF.8%ZZ-Z !,q22U~Tn ,,"?D#$J~ OQ  P P''m Q~dgIIyn t5Q6U56Px H,,S++m n PSfey JH4'Ut@@TyTxn x H**} ++TtߛIIT~ H| } |m U4--n ~  UUU++y }x *~ȱH~&&JU&&tȪUߛH}}Hm %%P'R| xD| ti~ Mm PJx ȩt}x ߛt|Sh X M_R߳M`G*ưD$ؿJd ivuJX~ UȱƩ@M_Iߛ} !KNo y ew u f 9vk |vcDEEwD¨$e fy ®Sn x ߿tߧe 9u_on { ưPkH P‡#JHŋ3jȱǏ CIɓ!"t˗0cʜI͛8o `'O:@B52ӧPJJU>}TF 84XWgj%@p xݛ1֝7J.ؔ/ɵ۾uv.w)k̹*OXkIb8^H lbm9ls'* XkSJjC֛߽C[6/>lVE0bOi<1L+0L>*g۬ʓL1,4ki03z:sY@M(l/53҉Fl ӻ }^=Mׂ rݒ }hk%Mr%7۔te#ixn]pI56\B͑[.aNP/ N=g%:_:hˬ6;4zfԿꆮQwؼ>qͣ:ѓgoxu W>w~翯oo_uUJ]e:~ |E!{ `*hL|@IA!$G1/g怃 YȲBdna DBp1Gv7 qM BӀ5zΐ<&̉OZB&TшIɢ~rzag&QbyDőL2d ,AD?ec~SQ@cd>V(QZTS*Z;r6ky(#/uKFf| U~ʤ3L92*fgIdb{Ӝ7ao~0iN];IO;i3T;빥y~ʙ&?sKh jO Cc P]&4甞F%>a瓏RA *; ȁ &2Rҕ2EDqYQj@@MUȤY Rɐn O0N*YiC EMOF4F7 jf}i[V= 5:hx)u1*C^ `/5 \ɩ&u}ljt M :Neg}ٲZ>Q ڸDBmkaua򤫼Nv+"A5 ^]K,7Umj2!l`Ŋ]U=-cv5y=Kx i3]bE p `\ntj enS>n~+2/}Xv'6dݪֽE ]mq`Ҥjb^syh|<މ19SSsuIkEj:P./qY)l߬ ةn,C.픝$ y~Ak^& +b5Ϙ!7LT6HI4g1 -۠__oUj.q7FRZ: w͔(z gY"o /x@D5rQeWe9%6Q՘_iT?եuu' n[Z9 iެ,x~ !ޱ}w:]{[kKF]o;e7noŕ^{B; m ;ы7-ҳP֧ۖ{7z{\|v`I.2L1[ KXpP>7͠7ߝ-! e={Ȓ_eq-E ,nV^/~{XeU}Fz~j7lzmfg$'ufds%8Z&i77bpvUrǦuWw|&C4xlWwo&g7hFPa 2u^^ ZWg&$vjZnV%iuictPlc;u8t9T d=xa( xDt6wluń%&T6Ƈ(8YS 6y#;BfH FSF G`Ӗ{5g3MㄽEUM!TWb>ba'lhfWgVc} afcmf$[W$rvgS] ggxqyn5iɇ_8q8z~dȌsXzhuBHXWBVHhX88h<~KbH|ru]xlxtw"uŘlmF]bըxXІvq˦(GZV5P&gX!9_GZ<јaHiѵu0rhv"Yv!mz[HSW҃vov91hvVܹ!w2wqnHqZ1{?}HɃRԃG["02بe:vHRu 3 >)YZl9y\K|`*:=Nxj1u8R%vg2Spy$KЅ);FP2|#)hyYqCe^z_Wt oa dyCj&;\KJPJ_ |'?X x0ehe\_hzȨ5pfIFA'tI*GI|4?L_ڨK҃zI4fgEYq>TFaXm:ثSkpj8=ACC4#wb'H5x(2GI`Y&~1!@i8 { 磸6G>qCvDӺD .T Ѣ~zMڪZ*WW:F7$ju WwnJitDF*Ip(ưkц-k!;SZpA֧^*gZ z$ Y#^sCT g*CeTVFJ.;*;C AK_ɱo(piʮK mujz4fWf4+0+Rĉeiz"L!K溴Xz{Sy`&bSj`AVTܨF`k@H=Z{u_ 1ץ+4jxMzRXһc* {~+}[ kv' ͙l̿)hmFŠѽ/,ݓ yx4\; ͇aܮemSVqČ;m oK-;Ŝmm~\}= Ӕ{ W %I(w ע{Z)LjWxRـmt{sէ-Y+T oFPI‰a*Boj-eٜd_j TEt-,ٞ^T:Ԃ袭i HnzMCcx睼jlqsƨ^Hlon}^8&-3YVN/^.gM2ϻfֆ Lf(zn˽Kg mmzM /9zRΞ:b(H3*SU^ŚˢZ~r +GRa>ʶ1wZx.#;c㋤ j#ҏK bp!Ă*ǜ]lyɚXZƺ&d<'Nؽ/'g:Y% sNT'joJ;sy>wݑ\_Ӵ˞L7 Kj+rήҭ :#9.T;V+ͽ =4S/*ZD0>Z!D!OD62,/>t?)rh% -TO8 <üRp%$_)MFIz/I=K/MHB/G- ?ί)2'34MTʦGݢ<,KnuK;6<5R$h LW=ԤPYMO$2-nRVб&}pB EݪsoRQ2R `Պ3tF7$WL,_EqU;-NXra_ElAkYqYL;mB7E*yc%x":!(D5ĐZR&` {; @ftD Q!qϕnKݚ$P-kHNLE+JFx'軓0HI%jta]oBF[բ7M+"`e]oa@4+ 2 "Z+3G>H͜HoS: 9GthjsH,Z` e3ؾ. oa\zVEW.mLшƦ%{i,-H tRfcQ%LpUW|[:I@Dzl%L3j*\xQϖrV4qH:2 ٘UL},rM= kj25϶ֱE&T{&vI )ũHj)_I؆}K.[lEkZ0ZrRb\ا4+$J'Z󤴰D+6DB`&d@ [:o bԿqQA#RA),IJacU3bh]3[+9x)[Q٬NjKCI$7/Og x`&X@XJj(ߞ!0PWT8)"Lm\9ǹ*MXsf]!N^0R9=c.Shsg5! 9)9uqJ\jYfٮeh7+nwUK4/ugvv7T 堌ܫgeq,6٧)!架6//ervJ9(SdHBHd(6TV4,3CI}VȽigW-ufkWLݸ0D!7!;oecN/el ӎ*eZSH|+C4KH0@\Xܭ $(vSr@C>3}>8%υz YmP{#",i%G.*(vr3,[{ X[Ĥ5Oz>M+%]W3'(.8Y!I>'nm'*FG\ m,x& M\Vǡx/ _@`coÖm&jQӬ_%ێM*셌)./|?I \` ]o~lJH6j{zrsyW˸$J 7#6c+@.Ȫ 'BQ?r0SY*F:3ɿ\sQy-4@/2 [8 @$9A'ٻc% 0;LAD09"]*l8k "ADc z-B$Đ"|40&@M[A! ?j/,)%A.2W(3*"Y{DC=z)("C>{1ElFD,̋ydNܞfA:0,# N뤺Μ$ILOQL$XZC ЄSOЅ0<ǼJMKYˣ% ]M<̝PΉ5AE1SJMQ`%NLTF Y:+j kʋ'Q,%-{*"U У3K҈)mFˈaƤQ.3sTR=1h4eO89E 5Rd裘%e,9lGE#^b1S"F$1Y 8M J2O2Y? ӈ>.eP|nȁ$_oKRkSU)T;MPA2ԣաr m< 'DI:ݠD6rO˓F#4nJ0 S`=W>RsM ,US}KIXz 2iA7]:{kU:I pσEXduT+V :ԈPJ>x X2jh\7:uQ^uYܰԘ%Xw͗XDJ9H}DTSN֓+ɦ3lZe%۬AЇŒ?N$TY>۹QP׹-+0XxK>Ƚ,\zӥQSmmNu[hXL;\+H[}iUߴVˁȸ PN*XEYDž\եDW2^v[i \%݅XcMe]?ߑu]E6V])c(D! fHIG^Q+^?&]X^=ڣ _83=ݷճ[ڝX(r` `p^J}P_nWN'#a[la%9 נU5[(* ^Ar (NV;@Zύ''AEõҤ^dH5Ka-PHbu?>5F=@AbQ%&dZ]0bF( 3vPM SahMYPK%GF3%Hm\#e{4TTeA]XjA; a"ވyO`DL\NEE2bw.@ kAM@Zص3wbUb=o]\ՅvfeHx^Hhɩo0}Y]^Pu6EChEr>A^Sxft7O(&0 ƥqe93F8臖􋛾版cgMp gK^LܒgڰaEj\f3dVf[>Ộxج"g_k;[Z9~E`uRk^>ˈz~l{iKeô6mHYDTmSFo톛US` ~lV3,idD*ZR*WP93$ <`B Zp B*J0 d[P!zU0+J#.'EI3/rQI,aP-̚7Zr;8ͪAX"s R5M +w ah3n;h5C9m;.(.TQǘI FRJtl[uWYEa!qexNdhL'[CD3qypJ͉@!T'MR # PC %9G@pbdgzT"A Q'ܙ%W;"t%ucRR=ԣiYo '(PU瞐FK. pӢ&9)f dՅSյR@T9Qe*1&fءIu)N)i}MRjn`/!>JJJMjEubJt jyL` .OFlT. d2A`rVM pb8k*lLtu0 _ڽݗ~R 3pm%z1ԟ*l"759aX=L e0o6 / TV䌐*BqiwǪ]}qy|f-g s4i\,=vYJ8<'49(hl^|9v~SM:d D8@}9/V4ISۭહn9"Z4@ӥ@)/D߾Ҩ?OT|֭rc/F &;rJZ(.(,-VAN%ޒP61ROA!~ .8okY,ط ]9aW?PlݏtT@< Du^vAO*{WD'2P;Qum! (`D Q )VE Yai3%h 4Eq#+楅KO ǎ#fG-(T!/ή4OsC!c$$C="BȡIDPiA$;FЄ)EDe$Gmo9| 1`ѲK.Y:&!ս_s988. b_)1C^&sU˴$ﶦo3HCM #&LRy,%< 4mBL~B`:A8d?)fJ{$8LگCSD#0E9G3ҙOIQ%^81BeVY4)5j<-ejgUՑ= j^晰(X|ܨSmNA sL*)S%x8R9'cgiւo%JQ U_F+7n[lG՞J*eO Zp[i)+7Vrk! Üʤq$l}ԐmD5,JgF#ϪS wַ͈BK4$UL vTW-SE<- "ƺ䍈y9Cw"a 6k,6T5mPs B^bj+bUbd + cL_Tqfaxד7DJ {۞r{OW`2]2#L i 2WzxKLHB.!b,ZX_qpukT")n|.G7>ɔ,H K|gٹ5,z*96qL`F9gFS?ֆO;$- |Eپs?Xfp6̙XCi:;uq \nI 'ki\W>J@mV%gn 3J>7;tЊ+wr8/޿fgI ^& ~sn.}JOxcnϪQz5y[ "[9o'Y<65^r959\ݢ~.ޥJp-D"MӤ$`ӦHΡ,U'g9B]!h]2Dtv{ze~ktmJE紲 Opmզ2x4\|k 5puȵyI=rbn5墳0-#ƥ[-U!@M@a띞,:O~\ŠTt1a6zua<%e ~Kd@xe1e< fqMxxؔU##D ZZH.es0H*r"hJ*|,֢ȧU)hkQv.*&紆mIV^ "Ž@6MVĶ8>f޻R"Ѽ(vUaN0U씪r"?i$2V6֣R' @ܡbzym&J >uj`l^$da:P@nY0s2"}~++2jJ-2nlM񥩯IcVd2m^Jlھirk^ZI)}KvJm=2nk%.׊-XΊ@XJDNnkhO>imHmZJ-ۙfo*놛r%N.Mo)Hbf-ZO ^RծJޕ݂N pnV!tp~R,oҠZ Hm-A* lVZV 'زpa-ɧ/-.phU3!E .T/i C/n/̩!nn%_1X# nOkmtct1'rqW9Jr S \]0Les%k~2G&1rAuJgt.N!.kgW-OL%Osd )Tسa'&P@r8 }1o':,-&DR¯@j:+C((ˁ R !tʀ>ndikƑ3 -HEJpBru.4 2rWyb81Fsp4\rW*14K x9>@ c4* 'Q06M,_3E#7 kM9++|"svh+OЇDTJXOM.T5*: #Uo.krWe39.G~1S/ 6%$F 3zq*VP[HPBDd@e@n6^hw+u*ڶBrkTDJT.R _.pɵvov7-7T6 Ys2Ϭ %NP1xDY/b)v:R?4VS:lnwI*6Ep8ۏQK4~4 îbNv[Ew#H#7y{_8Pt.+.5/o_5{1c4B 7@XsDtZy%fmlg}uC-8_s7586eU/m >cбm_Zc 8W;swqoaxǹ>l5F4^&~2pq`}{'f [9z utH5 ߏssRrm9k/Ѯ7)i+ zZ^(c{MoW,,v#oc,9/чn+;p#w2:^zv8Fz.xֶ5 zo:\-#|cSn/{jnl/#3Z:!Hcx#4x c3yU;ó[.O,/;swkxmCѸq5M˯ U$G|mc[h;;}H{wv 11R:~6P{[xSE{ݡ='SEkc3{Tē;!G0 F{أٳc徻}3gV>M#(xc1Xlx/w[w IRу|qrUȟUtkxN8⍻6=W=wS|o'~O<+8@8`A&TaC8"Ł pa ĂV DpeB{h4@ǁ ;@ # .?x@&6$I-Fp T꒢_5k zT*E(< <:nCջoLjE<`5,lCd|_yϐA (A/'k3}>V]W$F $ٴ FvuW\ ̎,pF⇁Vm#G#' -dq7±eڏ0m7|-*Hʭ:&1谁èL ( {K?4꡼KOC̄E:Gv*ɅZ1Êl@  EFSh F'PLS?FS;-#\%Q,pHRe/ՆB0,ݲ2,-8I-(mS My gbVSTCUHG)ZR& vW> pLWT+rmK3/ ASm, VTW57FW#k:, Q==r1 5` WmAPxPJ85u?ĴڞG bJwd %1:ݓR^*HF~ "/K@HX?2Yc(b,ZBSeM\1[xȨ_2" 2`ўuO{ cϬ;ixz%5ɸ 'QfYvwԖ#k)52hga{dzLJ9:^]?1 ȍ}Ho2\JH@#/3n`G%M}  N )j?mG\N<01 5(WfhL.t!"y4A_-VR#Njk!tcq% IEE.-qz^ۃ 1i;0XAbp|D6LEi[qa0aQld^U@B)e6\|| ָ0HdbGd-b}:!$B2+\*yNz2l(YJӝN\ZA7qb{6QQi'9FJyф4M~3̐$ "6=sP2k4med{uMћl9aA%ʬ,Kҝ-PI Oh9eG10; XL5f%9hEܡ,R#'YMrJ8t(BǑ B ܕGpDkGkvC_!`jݍIf($nզϨbUI*T $-09I$+'ʜJr0۠ )W\欍*h2U(:h 6*Vؖ-4" %-8+/ZuWtֵkU{KqSfmm)ܮTњ9fq6tWL&RDG2՝}b0aak+]~^GHގ"1{3צխXnBO$E-d7>Nw.5&WbKY7 b߅:(2p-.э .U7@<ߑl1&|]u4sz=*-"(9 #Ԕ}j*WQ~qNe˛qxvl A`(takwZicЇVWR#kJ?eh֙xE2gw \m`dm]]"X=o&2 G.-qN&~?}.ĘvSۓa A.M,rt`=?v.\+[tYzcO?8f'i52d֗ܡo(AI޵^]\@ՙ!tlP&x%lW \kmݕ҇7TʌMN.W-pnN8o#Np]{v٦ 4:oAs־vM?]Sn4 ą2ؽ-_?keyгUYՠP^>:~_7z>ҲćO e| Cʿ9NZPGq!E_Rq#4,X+QVnφFOe"XgOn/h$f kRKfo>*p#Ȋ옫F*KO2p~/0~KBN,&^".wP\ j܎=P7b Ι$PT* # H)HPs7'p0"G<S`nl,N1*pY|h 0= 7ew ] ξI\h&aBPGWR4@qWoiFqQ"YAGB^n(04-wWf^/J(or"yhļ*d%cƥ1C^NMR4N;̱r,O%Y @pukd <ҷ״u (62Şq!dЯДl&:lfe(-B"WF29FϞ/&3(ƶ˺DZ" p -7x9())2kMwDO]"b` @"H4A@ RSV"#20Ų Q,_uo){.Q܆SԄB/6tcy ҚN.P tv3;6slPqxLYT)q.5bn%N- :2 @*6lZid !az'0^ V3j 43"w2)&{+N$;ج1 o tLBг2͆2Ei+ɯD4 TAQ59 B+th:f"q DǨD tC%vldE0nFm"n4O: bG_AIHų" 0Nbړgȳ~ TsZ6Q FUٸ3Kgڣ A#RsM)MYf9KzP(# OmIzO)oT$8sQ[N5P2K539/<`4";;sX'4D,NQ3NHfaPHJ*~UDຕ@`ccˢ8"*LKN5T5q06B ,YKsODuZ^ZH@&@L*ܠ-x*R\ C,KYHxi07|[5D$ix`X=Bu 􂽘 QDNJ]2+ [)$QuWw[!F$ ixCz;+>E#/2mr~MzgzGldMG޸dÉVa3"aZr[,VPE_+Lӏ3 s;3I9s4I$:&e9  .h캥ϧ &[+…: ۜZ7/Ŧwdh[ Xy:L窶 # oX\ >͏FĞ1q6_wY津K$Cꚼ*,vEA|&.W6dp2/~DFn JћuVe稫)ZF9Fu5\嗬Wyb׈" "|PE g ۳Jd\卋t\!y%.,[<:>$>^%;eϸd(F  c19Ӱ|o]22`LL$םa=՟v:F/apA}Ii]9Vh ĚsB"k:ӟ<!e >cʑLރJ꽨baǡpSD`"Gؕɷ)N =%Gz/w5χMEwM-ą2eZؐ=ksbo? <80… 88 *hCH0BƑh8,[| Fbڼ3'CXɃ-F *3Ԙ=y6H~$z4)'@(3Z ;5i)WN*QW([67vhgɓ+ 92˙ kJX?̕pK<#6BՊJGE= `-o,:ߤz'O @P ge#хroQ)+L>}yܜ EH`u>K#,>P95Xqt$tݕTmŕ]%]0!tǕq4u9-ƙ`Ή_a2fD}U,XD`IP׌lAXp.EdRBS)u(9gHGH _ g5v4Sՙa51D%Y^օB`bMIlXh^Bt*7%hI %!ʚ!oE7,)Z:E@WtS\@eb]hb]h*Bv7ֵ`F:|WN [v9QH*9prQH%e^;u{9.fI%o0.{6ۯY#F8TܑIF֘kV,;0On4ׁ:蔀kT(Q<^u' +J]Gg\D4'6OOhD݂7f`hztGx`Jϩx~.v>`ם% ۨt,)7]5*ʋҳTod{4+SS^6ȹl <Ƒη-'RWKǫ}wJޱI=#'7,-d<P&-} Ex4ġ$I^2Yu C8uqĜfE؍>@^F?<@+oy=XPy!p&\^DB(u'48=$s(.((p*yϓ[H8IJ7QWi jeeQ%YUЊd[Ǔp1hJנ1GDv/0pCm#eׅ-x>V&@s<-cebS 0k yȽX/!"Iq+T?[UE$Lf}KXZi3$< ӀrFJkΆMgp#2˜#A'wrjJ"$0oKLp4PT&K;Tb&E MGEK(hi)L"p9᳚^*'bU9b8YS=3:,:LR3Q&P:k||DH A+랇Q CÔVeU!Oz2hE{C+u==q`dv>_Ue8;@rGUEL.zƐhK TQy_j6jS)>$n j)SH8atxNF+ HѸN1RYVIMoĶW5wV \+xUleIܲMR[9meQ]M"1Bla!Ӣnnwnk? ha=G=֥@BUxU{t"ipy_Q%SgZ}sݶ_qaW{xqgvt'Rp7@|t9KZhs`9K&v@!.[p[VC9+hxwz3xA;'U2uu7yu`']E({4{hqyЀ "I1^i!V-GVwu؅;u71W%gk`hOq&RA LyDŽqJז0t$(KSaj[vp|bL7W7W(MH^\a7K}[h~Adl[p(qKˢu {AdW gY˼Eۅ6:˲F"ٳk; p rڼi9˹ L-Cj6:۬6כk ¼)#%1k@d5H[.\7`eB뾥Y*,|:n?۽97˿lH%:<{Æ{T|3% k[|]<_ Ɔ,Mfs)btדYK^hjƸd\\ĮsJ̸ܴgȤH< r,ĝ“КɺNDjp|+ ɵ' †6<˱ ̈>ޤ|M ,Ql2 㿬Eq6.v2H:XΤjVj;qSZc#\[:MaɳOr_hFLw?ϯzY5 N,$Rҩ(^V4 XA .dC%NXE5X(@G!E$YɆT@1-Ȱ0M9uٓB=%Zhɕ+7X(2fLGNZ ^= `|&  PiF%[]"ܚWW`%\lAj&]:!5 O\kG(a+}6@ϩU`_Alњ.-td l7\*Hw[.TٵS6^llۖ32?">Lk@ U0:<3I}0#c@LKKSHMM&5M58M4NO#- DqV`5[K%1ԗ2Xf=VAUs%DĮYlW{Vb1P*KdGEC_\TH:VDs50Z"PXE~zzv.Jmzӳ>|#yJ=WXClI6UWE|GjAd`!bc&:P"}?ApMAP> "RBj xW,"0agBfy1B p?O 3ՍpLAQX:in')Vt DZi_.xؽP(8ޑanjцZs>,]$<41F"$a1I$6)Ne"TIYJݝ9 e11 "%8Uq(ܥd_"IY8 HpIUS6-&6aUiΦ3cO|bD zկfSXeS>D.(oyH׉Ɇ 蔨/]3w:ς1OTEʕ5X=uRKPԨRuhRNg6ՈO%KT*+f;\i;!ճԫƚ[Wi2PW0v FBqp TJR$Y*YV9T^Vf%Y ڲ{@-ieZXumA[Z`jwWHbz,S:Y" *mk*&A%X}zȼr vZ/yf^Ӊ{}(ڕj/Q_ifk`M%Rcvz.å;`wSTb85,| 3Px&q͍d![(&Yk<țpњ^s3*yqc:? 1\wd<YkSm<ޱzl9,-nmWaFXTlh9)g@oqnHG/^LiH(&u\jTC- 6ra(Ykl.o\3S mB+˦kɑH5QH< j!i-]QV[dlfuv?nβMo}ۥXcpp;/NC q\#'yM~r|B"l`6l|3G is/tAFLf9}O >?-Res{p9Dp:,I>F+]z=l B/Oq X!1 0{ЮPw;>wS}_0ebW} ۡ?B寎Z~Wwx {,3o܏~%=eo}z>G_}/ܗJހ2/O{W^G~c?p?<#3Cܿs?3N?+S;؃{=9A{;?< |=K˹9;KK:8?pK:̽1勺#,+T+%d!(,22U~Tn ,," KQtyzDD J~ O Q P P''m ~QgdIIn Qyt56U65Px H,,m ++Sn SPy feJH4't@yxT@H++**n Uߛ} TTtx | n U|T~ HI4I} UUUy --++H~m ~ RԘ*x ԧz ߛHtJPU}&&UH&&qm t| }m ~'|%%x q~ߛ| }SJtx Pt}dRߑs Ȕ`(ХN} ߛ&y dJw ~ ϥU@y n ϗk|V߿m|Vo YMg d s U% oqwo |Nx d wz I| u ~ Әlx tmlQ|Q Uxdko|QHA Ç#JHŋ3jȱǏ CIɓ( &T0˗0cʜI͛8s'> " B<`˝PJJիX JR5RFd:+ @˷/M]{ڐ#, SS +2պwZ̹> Ç{.&(% ['fs=[3Hu:(5?N:I\/֎8c6]ӫ_{aǖ=+_w*Od8]`n%fRJT J9`GMhAUale$֦}vXEt5~*\٨P @)=HH&ddFrl)TV^)>)aSZ5Jt`Y e\T '"v⹞Hv:[*'&%h(9f**f٩{稬NXj*Lj뭸R8iihV+ogYl.+f쒿Nm,-ZPUzm+B+n^unz nt/yooך9o nG<Wl1[/^GW0l2E!S72%C)p(g֜,@;s+r@\щv[/";.X+6Z5^qfGh9w鷞Vp-5Tt&mb ǂ Knq⟍bَ 9 x_ޙ.R9spfNr̺e(zΎgiW$Eİ)WaT!(R:;hP` =E}uVnotG>WuKvw"Pà')ЀSO^Vୠ @ 3`1EPPƲG|K0p%Ts>e>JaVX0SyC5EAC:H3t{ )ZVU>d+1"s_|EQebȪ,eZ#EFlr(3&̉z Vu1# C"O /G)Y*i4a"CIJ?}^DKIQn-s$+tJhUe\)6X//usKo-fn9&'q֓gFb 3[AB(V j)T><(i5YDrύ <2φe2$&;pw*Nf*0hEh@84r~ 8|RԢn;T#@LG*ԟT7 >O#@C?R0OmdO^`R])W!53n@C 3M=`x2y=,R:W 8O9Kųb CW9ym8}ړ޵*PjNw-a"4jx^~v=)O1N֛q%O[¶U-3ެraŧgA3m3vJG:Yڕ̫zC WVu>]p~?4+i<\.0u=[qWeR$v$kkU3v+Wd^>z wN{Ba"ļd `sK 8:OYdn7%I 6@ׄhzeG(j(ۜQb(szQ"s%j.L2N:Jf>w/i*]䕻ƺ,{٧-8t{SUw3N0iE 655ul(ĸ)V,Ԓ%AZ62}! ؚ5zlJ:l3}# I K$O90'sF1\֚yA:q+Ҝy [6{6>٩s(9Z'+fEiE19'pls+y |.lS*um bK_"):GپE8RJo89x搤 Ve:;i:C*Wwl9R:BSi h S=sXA(_ Od@mOݯϽ |WJZd~<\fTvzE0#L CiWʯOݪ8n9敯JdwsH1~e~ w}o}f:7]at{TMv~'{4VybRFIAbU`[WmaWe5qs\v_ BWoHhtV_x€7y~QEWOXWɧq[5VEHI:HH  dg o`=o|eLbu 'qq^xPR%v\QS'@vH^rv!oinIu@Հ!se#(f 9hqiiNF*PvX85m y=ni60ՓJDǓ#: 0P hXVVF^I)=6zI%JUiy  n4( gStycSr90X MP3|sXʘEg_ xL22x&;)0V71xy)~vE I#iK/性)X#It ي_A05x6`cAC{zjw!ݩMDh)= ir# YHYi1lu\ec"Yz٩v9(P9ё⹠јkSYt7Y?q}-Z6X j\7Jk5jwv_1H!sD Cea@vyE6 / x H "ꊬ69QYK#ΕU&Ph}Ѡ>ŧh?1>4>7dJ]fZÉieex; S5›HjxF"Cf&5 `؜[DazZW>PPBޑCAzoEgAU*{ɇt ɕ]`'SjYZzt@ e()Kгu*q2Auڛ*4=ɡ'Favwګ^zˎͤBǡ@cA14WM+Bʧq׮A0eRűɋidwaUE`|9;9d'nkʳX;Hz%YI;ONe_Y_G\md]:C?azȸwkȰ[aCK?ڭU(kwi\z/` ȴkwIZ%K ``:HtDJwiAQ+, JꃅhF =m[ƅ['׷wںGP˟EJL/b1pkRl:UwHؐS{lETyFȜT5QZˋy؉J)QɎie;j3nȡ \Q+_W \5 Zmg 0+TyH تc "\qqJ 0lY^UÜK!S%k0'kpQ1Adv9T-Q+P,6F&AwhT2*`j{{5.XMG@nnwT%QuIźCȲ;Ɗ վ=rGDLfQwlc"6 vG+aB1uwd r|{ Oż4\y,;DkÜu{?{~*[=A*LKV]曙}ʪ}]"9d OfݚeL +f&b=u\xГӻ jpܧ)ծ^;%љ$힓q>8׫vSRP}D=+ѯ>.bN#L'hIr^yB|S; ۣD9=ܛ8nԋѨ³VXkBIo`"~n2#5禖j4=Bڞ|cnT~.*ej  Fv*˹,LタZ->1^$L謎#]\jH_tFD^BP^m΃DZ: VQ`Jr@$J#Q" RB#Zl HcnA\ 'y):LIb>>XB"? LϬ(2/8L/kiK@RM148 34<\E(krMUS)BU?#Oh"Zہĕ -KDr4\%}Ȅu@N;:_DS&ZuMr3|( @h}r18 tWɜ*ZPLp!BMM&^I^z[9xA߷طXNR:vrhؐ}q3j8V9#Bؽr埧n&Fȃr/+׿Qgt_*lf kM^GhlEyb\;qHqS\d}#ީZl)ߴ; fif~V55Ui78bm©qo#'R /]ot!rNBcovxQo|F.#˓:&偕/{YWZ䆽QLso\Ix?Lw`z5:a]P[qNU.Y88tۤY+TY]g5!zwjح:!wx7Bsi6 -ٍQpnMs>5p((?~/l[(*>; ;3jUE:n͌9"%C9l>kVy%/KZG)YxlPEeQgCIHu r8Pfrj4&h6)9PvJpSk%4EX10=J#]@%g&ӂtg6<%lYȃ%L\x"BJ\! %#'@su拪Rx Jf.%6չD/> &heց`CnI0F(<1>DuŬ(GtN q"Rnxw਄![ܡb&W%̗%SOŐg~ Ss-$Q*fSiEy*FgS6b3"҇"{XJ~jBh^Qkb]}P 5hDӳX,[b2{C~Z\DL%`N\m*V&-̅&[NV\X-{-`~h^z(kkFeWugw,9:*{Wf"_U{UNjNi_0a4Mɰ, B#}>[0o )Á}N?8MR-l[76i5e+9_RlDH-PlMJe댦-9+v/IVjwoƴ"@4nҦM gbպmT^cJ8Y~]݇`~vĭ6fM5Uskf 54 Bvw5.ų͖ۼGx,`/: XKo( PVM~!GR h8,?dRkx'?-R/0*73iw 9e!b#6r 9S,#BR L/j83EA1 @`{-rz d-ԚZ= 3 1'Ԣ{> ̑7Z3/b qB$9+KJ 0.Ը=Cyz[134 KC=a89T@(<:!/0|C, Op<9;5\>#AAJD@"ҷ]پMDZfD @S> E$9I;B$|;[ KǛD<4 BSav2F1D''ZBswAGl̽ TWlRDTX 9GC D w1|86|lB}L?~GFoG/H#>hȮ5Ze>Yl5,H%lCd\9t@ +4ƺ QĢ\7_,4dEx ֑ƛtCCFǣl&X3LCYɖtߢyʏx(kT4*$K06"HHDKFR! 'yɌ͈v=T4#dTL˱3OY¶Ea8.̱@ά1F8[G yDLÔ_K6k2״,""AMaWLa EM̞4lMmie ʰ%NƐt9njHN=s`II(ϗ ?SũDd ]5YQY/"Y7MYO%U¬0SʞٟM"ZU=]z U6h>`؇x aPQcMfz$B{UM5RlSZB0l}S]Wt}п\=WA5۽F}X= T=\`ٵ`݅ زxҁňܪTEZ]O7ӍVUMguTG ?|ƸݐZE< DTܛm䥜>e^| eպ@ ]Ա ƪ_e  ݵrQ- &Y#]̍_ba}:EUId6κ1?S[y஝E}ANXpp'y֧˕$n^喉d 8f˂VD[6emෞ޽X^ue>,vHFӎ6 m@bjMx~^"Ӂ ɇ]Q ^PW,6ىd<~nmd?\#r d'p Im/NtsCs}5em n,9oOeW_w^p_O:iVQṈ 'T&1N'xOO._e6MxybV'ouw`~„X}7v yʟvoJHvs?@yrHzlV37٣AށN$Gzww_Oru 7x{q _{w@(E`[G.D!'ywN|w vpx*t7{H\ӏ=Z 8yڧrO z~|6(h5Bդ$_}S(}7"MI|zo8h_*Ryy>lYO- PniZr=FA(h ƒv0RXpD-r#Ȑ"GL*W$U aK<y%Е9O>p(AH$ppC\$P@ՒCsDa2g d[A.ա/ VEP&˅1:p"Ț7#jLq-x 9slB#y.)Gi@m>[ʡy3u(d6kЍ~P4Z@'ߣ%N:;O>=0sAdKTs96Y `Rtl,WEG^/R4kU(ޙgb F-؋A @m@e1ԐtC:2Ij=d`'{1B`KiYPHMgu[@&byfW 5zQF!*$Fӟ uVeSyX' }e^=:5UI|RvّU*ho l|:`*ZB`IJF享)} LBF.#)/Y-L|jmȰWUUp/Tp1USLqt_~59rk*-„*Z qk7k\hf")FlA `RGF0kq(ysmڢ(\s?wܷdW;s7im& vr1ၙ]* )<,w_xl37s>5J%xAcnP\{ o0RXz'GkkN,s 1kT%r`۫+iA)(T_&p'gwʉD8O"onj^SA n~@O2-P'6&0  {@s 6 bYȱ z'_@"Eaf2>)%ąt{Fx-dZ#55ohS`$.dLi@͢&+ֱJ<'9S|YXFA fLrL.46CbAFX0D0 `2VQ $HHSJ1_jJem2LL\iyύt#VnT#I0]n5% 1w1?T1 ±et6yx7Rcrw2ҝ$'* zw\SlbKydUaN4-  '*FNJ%f͛:&Ζa{(>tԣiEOɠ„ɡ& [,9tD,>3hs &"/#{sRbn ] .)UVz$' VԈX >ά5 XNIiՁjP{ ajO&0f``y9*v򊪕PؿvfSHd WYSl'9c8-RMw4.ZU1$*ntvrjcN-'avq r `p{z[&3F‡0!vΧ$P6i-?{mY!"1Bm)3K-f"ؔ{ۦ݈E~L&2 *ԉ"L\y\Ec%?B Rc,Ub+,A-Iܛ cN\HY1c]8 "u }ӷe^CZI9D:A #a#ĜD #FE2FN(U&1c+ _J҆(drd'6 CC5HD<";F=iJ0vK K3 T> ^$X@YFL^^ddi@9jZoZGe֣R1eHr_fDj"LUG/JmLve-$cf-U)eNr&Fv\*e .#l$Id Q@k( &fV6Wr#)dAL#-J0ΩNjAp'Z c<<%tJ!v# h̢w.'bx`,iaa\E sjbf& >%GvdQfF]T4-aq#qUB؊ҦezzcAxL"" YD:O BIrhΣ>ufm'UD"&fSf)ZaQ/6YfvF[e&%2 )0e:m&yަy!ҥ! 灤nEƩ(rf'\2iN✠6T*mƤif[AAD)% _ji8ۍ^cFjjkH$-馹^M'H6"%0!(%bPL`L+Gj j&Τk* rW^.җgbA)֫NEة"kP jI]5.b:{A8fadkgs~jzEYN+ʟr^&jFayD7a*$Ђ|j,fvP)D& 1k蟮.r2*מ-VbL mg-*[lFjs+F@ Dj+L>q"Zn斦*b/ZmҪ:c.0):ZBvxۆ䶕l)V'.P/V^hlV b/m@Z0j .m2k҆j{*oo6d fꎠMbAdBU)o2)Vn /٩cpM߂+t{+r {."$&eqqpc/qjPW6?*@Y-: JƆeaKێoҬm~l1ba0"q%$`.".(yYf+,~2N0<&5"KrP'?/d%/& 唢0j6[.*+v ^j=g"Zɝq-D'B2|B 8e09.ᆥl3D1:rg,$O)2JAk@< Lӎyŋ !3l;;O<0z>Fif"N!k!+t64DltD˒s g){3NDFR^Q#\)FW*TK85|궮;d50@'WiFE* 2Z+ u BwoPA*E ,D_WM<:"űF(~3tmdjXމ3rqJDQ4?^qO6Q@uQm.S^4TGu, U,^2"nOlcmX74Gfv3u tzPuvd]z6Gw4~pxn /71vUw= XIyF6fc AOR2huuJ7X.i46܀SA&n%퐌5={|_vo3w7xs!s&_F7Sx+#K'#nU/4Rxn [,Zd*j 3V6G"%jg*n 4i[ oym3Ly.^ۉYoxw1=2s2/r8}o.[w6gR!7F42vŁ9>x9Jcs ZnKOv߯_C;xSp1q6竬ryvzlbv ׆I*w}7pMN(4: kH?2nwVzgpgzP>756ěsN[7๫zN9[ _{vUOUID)£ kr`o:';f:i|<H;=%|ysJc@z>V6F?_y{shw|+|5HsrDH("fԸcGA0'QTTx #S` *B(K ]eB 1M  :ȓעg AN;vBO iUL̵X7maÇ.4yqc<.P/C P7ظV$xeTmu@홰AP]Y!(X<@uի4h@icr+bcLmR`h?x*/'L *" y{d~i5Z{m>j(x ܬm6bn$&hAi;3h aLFZv 6v +FzEZ*!I9nI1t(&*4'/S;Ϭ©|T0dJ1=tDr5lN/DT&&PcR!'$ʆ"+< :&MP,ڴѳ ;9̼볹V$`]9O^3PIQv jAR\;vŨzM펺 6N3(5`ɻ9m5&Btj5$((Dt_=N* 3ت `k!>$RWu[4A?FO\ dٌ%O^u-N=uo`mIM6N☛\ 3?Vu[tYޛ5Q *l i`ŤPI?Ʊ%" Ϩ\ij klc5Kkl̈́f+5|^ N/ͬkQI(R$+c[4]I.Aff?Ƥ\8A9er8E$)q%(껔BU> !0di:Bpr3ɾD/(dpT8A&:f{ـ4%dnN!F^aK{G1I[[,o%qCE!7qΧGQy0fI kN/:Rx ZBA-heJ9@d~Uj .ז0Ql,xMWo\R7Œ2TpdKkH&/br^1JpY6DB sd + 6n RQ!Futۀ~WOhl@Wёr^Jg: c6mtR$վhP0r̅Gқ f$v& EZI8js2JML{'̩pzV픡C /r҃Oj>`4ϢR)[aָ勥5)R*)sVRJ_Nk [k1['kU/{9ֱ}<[-ѱs]ҝgVE=!6jsjpT^{Ʌ Tgc+!poxn5O NtsyLlzm m$%D7z>{έj5/mlӳ $u\T y_dl"Ն6QU]\0cv2 ӜE2)ϒ Μx4f̮򫆨tUҢ^덹b-SuA \/b b|7ޢnZ&WoT'nJgChh jY-=b݀oŧw0ڇ'8^DW=DF-]ٟ"Lq?G 4ܻ-k:zqxOo6үA6HjDNPn.NQTMDFO5$䅦 Frh(V 2"0>vOP,ގnefT 80.ȪA0h$H0 /?i;tF;/IJ`_CP!O'JvMBH 1 nbpli:ֆ\v0tp:@I  -/TO zĪO(G/ˆ Ǎ _o/NPHDod>b1όqaګ/9~1e O KǎZB "E.N JnD@eQPYp|hPc/ܑK.!n C j.|2CQ -| !(Z$.1* I ` B00d(R b$.3PKSrҵh sj,  ư$cQP281*#_1ccʐ-S++r~r\0N ()[j^Ӧ$&b` @@ H3C !BSF!%r@+9KHZ"ῈP1'rPSM!I1W*2r,S8[E4*'QPSkv@b^Q1ToA_IvtEid\G]ƖMV?-c9fFv@w*nRBKPmO!w\M(Lj[sq%u osb2ywqCv^7ˀO3NjRNwvB5VF wDF7sb5/_HR2(1z3)d5hGr׈ ]IvjW|k5~? RB#!]Vp+Q1!,or){-,(Pvn5o0Lo#XbmN5s6bt+P7$* TM3BM$d{d4twրC oGlx7Wh= H[+xth{oF <9WMXswUcgKsrkT/g?k'ه7kL#T\0؛`"d~U,tJ/Uc"xXBGdg|Ώ.T-<@JuQ(/ֈ#U0ޅKx,]Xx-[Q~qM3KG`^kydqy-VVHwQXR ;YGW! x!xq5sE/8A&i [j xw_$7ؠw!(2uX~Ȟ鵪.x$& W׾ٍ?ygd!zYdAآ{2Zq8;.BD.tyO8CFy3mvehtf'!c.!CbZD'򠀜`r %Q6b"vaD?Ro U)*t҈V:&WغR:nwf1Y@n,j:! Xp7͜YD1>J(`a'("z x):˙DۓS"Sqb$7 c86l( wsK =2;W2[_bPy=5YSr.nN[)gԲN.8Ʒ^:kfyijQ({؇cY{8|"6Bs#|o(Z+IH1<{2N/ŬGZ.Y'&/O|6wۯo8bqV6y¾Ǩ<|dmۑO3D. "҅:Y78[[ڗb=o8њM%͑c(-ߺϜ(rB|ȋ߮w wz9cޣ<ߏ[[2Gz!!RXAM"\凤Ã'M܏] 7EyG ݰ!Um_~a<0 BˏfԥY2BљYQ'x}Y{]\^&%|Cn \]!;|/>%^=5q 7( ,I'{׵~돳xQ:lUt6~ʵ۽5p+ixY^FNWɤ jUa^9b"rާw =K4>0p;Q|Z71ai@+ni (0B6<0.XaC"1HDʕ!5Б@40C 5z`!} 5ԩ=ob@5֭2\E:#ifCeD5ܮ$pPA jpR A~P W9N0xnKkCsgԟ])F+9 Cbe ׌`"<"xf#IuD ^ bo,IVlOFAQ/pU=yCۿ2mSmc{1ԐoLvUC-H`}DD F]V$YE֞fh 5ĠD>p)_F~]{tTP|[L]և2Z]uBtriđDHNjΕaC馣fLXZEIe P~dCJ"6Ԕhe砲$]p$GzU[ۇC}pԋQP>E|HA*iܹ+EFcyJgZY%ym%i:@>`11!CJDtflu; ~콩dQֻZ &RzFD"96yP-fR6:fH\%LNj4'Fn. AL\Zyd78 cq̶#sk9t7%yu^mFdc=kԘi$L֓>騷9?k(7۴:.Jq?{C| 9 ޟ=ڞf`/t$Ma!FxĄ <'9nؒ;2ٝM2n@_ʆ~Z!?B O8k[: =zSQi||(1s3AVƃ'g@"#ms ɲ@r8G$nFʺeY3F]me̓b+=2He/.J%|$'sxz+23I%"i:{+&Z@ێ^/Xo[nl5x+"dMwWioVV>k2ɡ+V,Х\co'wgV3{#%;"+ 38&ST=bSЮF:,w rFE⹾yúy!^k#m;WW  MaMKt V}dʾu\jĴ/| M<6i#?yS ~n@|䘣V0B{6M}s]w{υO3L܍ ϛAͯ.C+ lz.s~WX~o'^yl{W7wGrs4Pp//B EZRm,CP` XcV×L@p&zxgk"2yyS~"kw@%!x~ VTiACKtr~T'u7+<(&"u3dĂ1!zu 慩$BHf>(&X#tf pydhc!Ҙ ɦ{%q#pD(tHnݨ!rׂGy^2~ؐlyzCSHQ2ynpy<(09ȋmX׌"'FB3)D% G釞Ɣ.iMW K䔔JFXcfyjt1'іEْgy$h Qz$h)I9އ 阏ycItCz٘vWcQgy)aaA9Y9Yɘ'ǚ)IE}Iǹx i ٙ_|)P Ixni)iƝԩٞi4Q8y֓YJ7Hœɛ`4pQ Z0@:ꔪש!j$*ڟ+ Ѣ*2Xz8ʘJ1B驡yHJ;ʣ*ФQz3a*~Ѣ/0P:%:m::ZФ=^`znzv:zXNjǦęҩ1]bfG iZ\ ijY)ȡQfWG\Ġzj[ZZzjK:OJtڣBʨкpz'ڡ*jstZjꮈՊm`gJI/ڤJ7밷 [j)*<ڤȊڮ2pJr*jذJ:!(˱ xf8@)pqqVdY8jf/`bnZnKkڥ>+6 )kĊa۴c+ˤb&b!eDK`˧bk bfhUFq0 hq}Eu۸Ghn[Kb&9{ Pfb\n56;+,rZXФz d)VHqP ;[3 ;ˮ}*K ЉTZ {˚?[ۭ{;-`+"KkK-ԯ ˴vit%Jk!#Lk'¨+1<;˽˿ ˸>,e,[L99;l086<\UCò ]LtM7cGI^8f#LKb"|᫲Tw,6nleڳ<}ꪘ 3yL{l}Ylǃœܚ촠ʯ&ڠ*Tة[Ծ ֊4M=Ԇ٫)ՀM՟FM--ˬΫ7hʶbӵ Gף} P˝Gm5}M6ͬr(}Mݍ-]͞LۢM4Kܯm ]ؽ ِ ܼ݊. O aɟۼ\}wɹ}߁ݽ[Vnz~Ŵἁ0Yf <='j׺T2nhmV1Rpe[el䝹h˹>N4>:s^T^or.13.N@K)k1eq-n~:,x<-B] }/ߴf̶n^.; T%ܘ "mˎ>|wm1C |Qxߐ>NƎ^29&Y5l/Nԉ[v+=->Y.Cm^\=L~BbŎ8"8M! ; ?7Y}\F?)+_AfRH=E??X?wb:ŝݤ~uq߄;Zt_STم{z!t=~`_-P]4TRK/_^4K/h)/?VOߥhhm{_ < P#mv_?Gn$9?O/$!Oc6H@A .d0Ç @B664G!E$YI)Ud2@C-e 1 h́}"QXqSQNZK1n N\JӢ'Zq[quV\ /ɲBHc"E N.fر_ >FfNʙ>;3mj&`ԭfԩU ν˙g(eoGN8Yسõ^Dpzuɺ2Bݫ6w6wEg}Gg3~xip@;h>7I; A ;D(-@K41/ Dz($Ek*/,ˬp; G$wT<3I,l (7dK4l-.A5(*+ҷ8SN&1rOSN ˤH@ՒKtNy;SQJdI7es^ж*>/t0 ""sTXLCUPPc5YMuS=930=Wf+*@)"aVlkH)boe+ˢpz]x\DW|tq"] Ŕ8[MdND՘~kZE/Rbb-5o(qclVbXdHVadGfJF{60 aW /=-錡6[tơZC7y߅kaVS_ZE`9oi[mS 4A`$trm|bW7t;=i[9c=R5%u*݋_mv@0y =<WiA˗ y7((T!͗_ ]@W~ި~ `7@~C:fp<5P4W4xB/Ĝv#"r)U(v( +|3k%a_s>K Pi+Q"8&'vb oSbBcb_OhF/,\y7 qpc}h:5fy\>& rl!/36Td"Y@R&vjݍ(YI>^57!)8{*JeEl^ji.򃮤󆱷ft E\& 5c&-1f77(Q)㒤7͉?ń$Cs'% |'3әKbgy!Dc:$_?CօmBН9(EgѨ=Sv6DMԣDAUJ tKF%k:jS4p:M , ú|F>j9um)SZѧ&jH%U*@p6˨aOzV7 gIϚxjcTSժr]_V0M}t^ѬF) {Ѹv~bӍ6rl({ZwZC{NZ+xZ4jfNiqiQ45QjXhXU)Ed8bej`^2 96d>l"h;ȴ aFic#FklU[ꞯ@nok2TwC}dkζ꽗to{C2GfxpG\x->Wpn0<*guR'HADNr;{=O :E)B Q9ߥZ,(1\ӣ>uqcҗlD ?$ <;`/}W{+k S~->I-2D>H2k^ܚw|l.W~Ẹ~?>A?yBlNaC~q#Ix>kyث^ ѿ}|BC x~CO׏?㟾x+;@S'@SY[;@:þ\A=97>K?@B+ڛ@~{SSŃ2B!,[C6pCH> !,/xx22֗xxxyxyvv++rr// mm^^iiggTTMMttQQqq55VVEE oo ee``BB<=<<OO::@@@  @x* Aŋ)PqC^t"S8"P "ec )u̐Bi`@eR $\IUgՔ:Ljj B Z֦퀸)1\{W. @/&L Uɸ1 "YrSPn&c<@DT M,Jt !, I22U~Tn ,,"VVghJ~ O Q P P''m Q~dgIIyQn t5U665Px H,,++n Sm SPy JfH4eT'Tt@xU@++**x y} n HtI~ n TߛT| --HU4Iy ~m } UUU~ |++*&&&&Hڎm JUtx U}ߛHڡ%%}H| '0t}R| 0~PJ~Pt|}Sˉx ߛtx &,~m y {'˚y ڡo ʉژ/J&~ U@Rߛ} n'ڗkseؠWn'՟d w#Αk sڂ]y sey w ˚\y Β/߃Սd EIx ՞t߿m&dʙԌHA Ç#JHŋ3jȱǏ CIɃ 2<ɲ˗0cʜI͛s'~R!@@D\ӧPJJǞ=y,5#j VR0\ڷ}hܻxŚUg )188` 2+R@n[uL׮˘3W0A]RkX Q)ׅMm|՚)Z)!Lv^)1wZpu]G\r+O􄠻~ ;vYqu6~WmE@R_\)=V߁#֔Yv`W7vYChadj`(bN:4b8M@)$>X|]8$A'.}E"=UYxQ.4U>d%!c&lgߚZ杗eAa:i'`*)f&ؠi埊F*:z(Jy76J~"騱uJꩨZj)&ŪdB:'l  b*#ЮҞkf 2{چ P['k㴄iت+.y /Koy o K&p'\ v qĮN]<^Cjύc&r*r˛l:Ks63j϶\B+JtmFӈtҁ. T{UgDRÉeu]O]'J+lvAϭt]zͮ~ x5͆)⒖/ Ê[xΎ?{yԙ䦧,ꪷ.q~o鮻zwb%VIPZHc?;ޗ8dWXw3%zag߶o7ޗ؟ɏg>޴ZAF#x]J:'_`g$% l`|  YPA ]5D2 Uy\B@iN(Zw$IAFKySMĨ|~͠4+D-QYp~S팧S vҳU%2p7=NZ+dY]3n5N8ӷvl%wMpU>LH_x~,5lN*OU Kd}HuOD4X7??Ԣ5V{ڵ Q2T4 M3],o[Yt7QV\V:K&$KNچVBS1M!;kQPwWs)ǒ`Y=*]yũ_>dY{ؿX )XFm]e-~!MHZ;N֖%+8 kvhZ1y\h@?^`mV|Ey,] XR8<×#䀟X0M:#Lj3`x}+dSmvsK"$ 1'aV|y@Op=@JW*gv @mm8Y-3.騚ӚnCapXζo؜s~`''`H%P~*hjAF,Am,w:yuᢠX)΍öƾ+}MrU'P6\ Xh[ю6=m!:f-]tǺlizӻwOt$~gXKO0kr#lt .L{U sGq/̖oEobrMWs~QKۘ>vJpp) {̗79m˛!~0ɳuâ)}OD#S c m}/&;V^[*7v5]Opx~nG xx}WE-ԛ:(G0\܊L$,q7ZnܷeΚ{j^x_ Rmc=(&Sp6V@|dnZ?f<NHbq }5xwV%mO]WPʆS7 M0hhbj/_#sF\_x\sRH̗ nnvz&{Q{[kk/p{p77'oY}vw% XMzv΃u}~6\{}GXFUd{8~~]wr'(Gsx;xmĂW₤c |5e؅q3q(+V]<؀=9qhz` U[JXb;1&X t:|cLe0e5PU8a XSrPha&y;{^;asEaZ݆X!Bgf_Ջibih\gՉZ=(jtX#o.m;GPxf(Qe[Agnd:qzYVThj8x\ 5s8pUgaS@YkG' 6Gi\ҹ捠E!CCQ>.՝ ylؐu")~U֞IRiRhHR:aזU=!T=$M̥kZQ@dW$Efㅡ.eY) ƙY5:QY!u)Wm hR8=D>ij^iT5Aj! ™šzhEc5BLees؝SzIY1?1qZf)/] J'jsBGʭyha(} Pvًy5etW24@3?;3Yq_B)7ؕ" KZd䡨&{ثdLX7}q !@ʚzF)ѐ 5D2|9+=}C\U i Sz&jjBYxڞʧhj'zE=-kSk&bʘ_2Z5DC_ZPEm:@۳١Vz l}cojWxM!JM ZQ(j6נp ʹ}s DfR+|:sUűupc G~8IyvMkjK=aA[vg[G+lҌE8lҦ!A=d$[;c; ++7-8曽;wTje{R7S# D:){:S[컳7&LJz@|wdƃL<µqԻ[HcR$7f|T[1ۼ;a,~ 'VQK#7%eVR,dN(Ds:ST(0yy̤VE _ZܺJWJ~7pX%ܡ Ɵ;7ūݪܘ +1|ɩ+KaT(fݥ(!?|N |jlTl9{Uz&̷ݤ jOO;!LLG[bdefy|-T+Wͱ,Gک:k|:-^4<ݫѸ?={e[xS$={ȍLoj\Zäeˎ]${5eN\e`[o\ͩk)`U(3\܄蜰Mmul]|\Cͼ* `cy䚺[_~ݾҜX݀ںx,mA} vд@z\QS&)1UMdsFb8a-M:dX֖=a`*V5Uo͵'k̆R2Fh(b]VXLTܽ X#\ _Q:, HUSF[>((ǨI6ܪࠉ X\9:pmga}@\] {膽w]F,jMXpzX=L(:K8-|٥=EӋѫ捖 ڌSJnG9-ۈ;퉹z>9^pˉ{;uf v=llڌ~N[JyćDZNgю}eJhQ;g>ZA[>Ry!"LZQvGߤ ?hv$fLNFW 9Nb T/]>.T~a],A}m&  Q'v=GL֞2^COBui%R?w-na<[Tf䋑%7;᎝!h.&_4<)<`ibJl/־﬋BzM?45FnMmT}]5b:/;m5nݞ\ֳ?ng6rߜ*i뗹_2{n|GX{D_r7DPB >Q"LĘQƍ<*\AC%+P]b4фD8`+ %  ;+;Ͻᤚ 6t$VO $ Q@ {GL=|0%*2 JoF+0.WxĒ> /+#+ïr! :4I$. +>|&,4Q[+7Q)TNG#)N͊tqQVSJ¯1.넯QpO/Q̣8Ch\㊠^͕t/B(fʹPQD6n$ND\}*P * 5`뵯!-ViKɬhrJB3^lo5p+9 ^]]\+'zD3M*ӽiRy+KGn%3U&-Ob{P~$gzU$TBF|0\ %إ~ᘐomk6u/+]4RE&M59J?fCĨGS%f}u'M11dV>vf[Eܠ*3 @|B&)&9.£JtPlKYӓFg&+&QI*q0| `q9$%LFL8hc,qƸFYmzDPm5G =6H>OT;EI)i»Nm)]4۲).r.%yg#o?8>T8R<(KC8ǂ29=ozTA1^qHV9g0gNh(9T}i._Jl$4!O fCOTRщ9|:& ʼ5RFN>2=NT(zK;5smܞ/5ׇfO$wֈq+)TđKMԲք<*)UPTͩUɥŝ`{YVszI1in5̫^}ShWL`hm!.1moTu4.JShRQlY^j$]ΎUM<m)jXc4 /'T8)t-9\݊ <ae LbwmpbC8:؄)aXۼ*VHJU]kk]5զ+2Ā"ABp, ` mM)Vl@[SW8f eUW1Q_EQwJ+).Q)H +AhHK Sڏ:RL›UjG`_ΐ`JoL m ojژDg[cpOp! hi}00$^5_w4,gud]}H1|z(SQ(Pahe\ؔ,/fI,zEr ?%(۶Z b(nc:wkTW`ۇEUG@:(+ɭ>Y4dU!7dREp0t-sus"RH&f;5x7X:Şxngm/no*ŝUʙіzdoH{@z3Gď'}6/f#hhGj>/D0c8݋\i'S0>ˉ{B">[>Y621@&;8 ; ;(@¿" A@þۛsZK? R:0D!-@ 2#:9JH+ B(1fÌA6B C 4;{P<-0ۊ3"ȀL6bAJpDJLIʥ(FCJz|G\;$Kڷ$G\=+LHb*L(NKh -?HHLnH!=[D?~adb7L6s!|@l1 Fc㞋>;l4J/dJ,/6t/NOSIhԠ>ʠLGN2,Z̽6LH(Fjϓ/(XpƏXIHk(,mHҺp) %$T5 Q?V X e4˵P\$ Q|Q!HQA;̉5]L,ȃ$&uҵ1b9IB;#t;.w\쐐 [#_,%z<)Țx^)^CBd$]9_OO" > !%IY_CEՌ]Zque؞f]~&,&Vf ~3^ކ =H̖J(`b3b:֜am^=2T+5Ƅ7~EkPą 19ٍ@.&?mP]M#&c0'4JD5f%ΣԬ >(9A.(U]0*\?v\ 0(Ԡd @^td\Ƭ?]dA\M C@D.ygJ`Ւb}hځC=dsFh%W`hļZ),F&6hmg~:Qb.eDFU+E 63a"뀛8h1&@OY }.&oaϒ&fvԩUxɝK-}Nck ~3()կL۵X #_4>bXc n˕j3X d5ha&&6fm"ש)Ufi0 Ķ_8~g.PtfVd '据Xْ.jxn8hx {17 (MI=0 S !3ns6g"$l6Y"6 <0_\o㯖}ڢpC5pFn'   p6MPBjŪpԍ\ r_ WF`F0?^-8ѐ0pdDw؎\ N'x:㰅.1+O.d+q;h s9m G K' >qTj(5[e\_ cTKu'*' `ԦH1`s7G4=sNWEǪl6vpopX0hReP0/wvIwgwps wC|H'LvK8tuzW 9_1zim߁T[Qxq1]?c?j> ps ZyZrݴ6PUeGăR=GĊmL ;%__wscryOe{/oG{+!}qo7Wx[;zLZ(N0*:FFd6{?:㷢kwdQw k!w!PGuDž @` v? tø+o4Ήe7~O{ޮHvpv7=hc8y7'}Vjg8 B2l!Ĉ'RE !BE3 ClD @0C@*@Iő| +_$2RJUX.j4(كfE jVdFːr*ً /m@)* ߭sq4෥) 3D9 )Ti:q1Fθݐ*ug:jʦe@fT Fu)`|l%AezP gSv{v.RmfU{$G!݋BF(((lJ mVũQ䊭LmǎqnCKTvxp+{gqx6G|I\)'szI+)?mIWih͡ev[f8і竤ckQfKxV*Bfݖ*e=H[uxQwxva}5*k6eNNydRG{D-g@:C9߅:/eR08#%`رmsNL6뎁JA'[x %?cT}PYsIe짚x7;v۷FnL5F nT|;c>]InR.|[VO)c qDr?6 oT <RDe$l r]Ii5 x6a|њR"!` qIg(H z0vD!/ <8"1F @c&!P[cYvAOf~FA)yb!/ :#ϖ9Y,g J(D$vL"-RωO7AP6[P"Ċgxl[P۞R5y 20tݰ/r7$Eo5eA;n'I85yq pIJ $3]^䞒~*D$B3&;@hc0ӽ%!yrCNA508dQb09X#.9YPyL H:/ӱ2I#g@NUi?]fCؙO(TJlZL &~O/ɧT@KZKbϦ av ZU[D^!@b<>SlE`.{JN PU9"W~T|TE($RX>-J*4[2E{#uYrVIr{tv$ItIDfD Z5w˻ SXV0XLϺ\IQXeѩd_^bv7 0\ j5,E.} VstZ<1U$ll&aL36#k PKxu}۰}:L%63#N;ޔy耹^W/{>6ܥk y,0@m{ r-Ta,w%Ev12RQ/,-|6B 6j$|æCZz&/y(-hElJ<;y\q3Yx0#w?a2b]_djON(|rzM7;}~CSvYe~Kok7pe 6saR˲w2yKo&U"t:NrjпY׷UYw5 r֗R@#1'|`Ww`~"iSz~̓^fY3?B $c[}οx SBEd`U kpZe|}{4 @7l KTLDq[9^c!O{$ -LhYXG}\=mLeعR=\6 !6T&ݗ 1t\UaF -^\eDX]BA!nUUF][!LbE^DBnd}&%1b#>C!%a!}@5 Y[Q ' "AW.LO3&H"^d/Ylq (^vSIUD n"CF]8ŀ@  *573E`=[vĖ)A@*hL66٢A8qAXA:H#v1&ߠ#)>`̬?\FK ".Z`<ރ>‘(bFH R ]GĂ -!( $$.U+ EvOڸezԥDD_~!NzaeY$ T!U\3eM `JeH%>!5dٚM?NzIfOO Zcd.԰ufűFghGbi&`#p"`dIIAfo*̹ ٦=!8\f &~cr Ty^RIjY}CP'4}A4AU }RD AO~xνDVq"!|&eE-]Ĥ^fpJetZ&^NF[d6)h~yr#.(qaj %p⧈R2f?ZTWv h(O]#Xi0f:eJRDoXEc2ۆ6'T_jZAiIxd Dz֒ޢf>Ofb&2))ēdAlf'h!~LҠo"oiZ:dg(E%Id\B@iha!9JTT凕)f6OVy֪vHP{ЩP^njt U^)kv.T&V&m+U*ncJ*)eɉkY|dII2_萄 `,FVfjXYh&n5gxV*eҕY,Wձ"k~~.[3gOI'k#$j*>Ql)BfLJz/KH[nFu^.gI 'Fp҄AB xǫDp3M٤dsA+{gy-M"r[Vi]DdՀAIA%in>I0cj'Upqcrm7/8f^&j/ak0bĎ"G*[82+Ƽ*0BK#f-2O ұrF:FxNQo @W/7quP12;Bw(s' fV53Xfw6eRs/v60춫;O pqc [XHE8 C3l&+A/PnćF0pI*ip9g-"1DMoðfwq3@X?s.4&&tt s.I|kJhKY45:?o;_G"oZ!b@&c@\2Y3ZߴtRNؾ>  )-0^?2 2u<.ڞa @$+(kobAGdvީ74Lߊb0uFjr4ZjUG flC0F*!73p]qWE/&o:uXoDNp QqV@1GykYN{=w6LN7w.[-sRWxRlt4J6z/--;'4ޤ'^3(gB.tn˺g=ͮ4tYw7G( 0-1x{7-"k~yt~x2&r6E4I yky 8a)?pJc3vc>u?1y`Kk\@#?H@RAs8Z;3r(Gt}75KS/艦v:yyxxva'I&خ:MMUۆʽ]26[8d:8|G9Z,;wN(Fs@zwؒ9}r MG:c7zzEgQG(k,[:[N*wI:5f*7Km;ێ8*6_vRrBt;erkEv;0g>w~Ԑz/:}O0>h#(|':VW}*< /۶~YW[v/xnLFX{|9@0p "daCpؐ@ H80cGA)?B 1$ !,%ȁ b͑PygQ-? 8iS@ 6\OUѫbFOڬ`WhʼnVDzcV5ǚ̸oD7mcPr/I9urr ] <IukjZUZQ~(zXWxv:x|]g\m>~KSV<է2o$|~Oީj 1-,=v ؃i?KAz!Tl™N#29 aT(08 `Fƾ|$ b<ʿLI26 xI1 Jp4@'{,й{8,U\Q*(s <:&4T ur 4Nkܱ&#ؤd13;NT4KAH/?ˤC@/i:렄lGP=xTJNC =vsf+%P6$ &\X8,h?|$(H, 48tu) Be A m9t37F{|W]'maVՅh2_52.3ugB UΥ7GUgZԿ`s։G9 05T&!yyhkߧGOU㝚?uuI[u /2y`TWJ-Sԟ>,!Zʧ E ԞAqq ϥd8hA~vpM%0X2d:?ʈt$CyƆ@d irǰ"n˞žw*Ap &t%SE)O^9 6YA.(S$?$bYDW. *KE17 ȵ'3dZrja2{7hr;X"怶AqVidTMUe nQgwAL+aI9˩QYQ:М_ EUTo7ZnFּ.vQGdgBNzҰX`EI![sM\3߳h@vSdiEqG/)H"uc\Y)cTkCQt=Q5 Vhi#\+~d<*\D[ų",+ ?l-G4ϫ:Ӵg&M6h!1˥NuvjcnTHΕw'?}jsUgrO-Xl;d%0fϚ8RoJ6ΎeZĀY0ٓ'pO M>0$ZRNUn)Rw-/DHJN%1zWO&/⦫(>BK3ݥRى1@(еNb0\4U!( T@S-u ,vPrJOVu;+Q7䝡^ Xת)-HM6Uڕo=V=-[A1yb=3aKolM G8TbjVϘ4-nGy˖ʸfA (!]xÁ>-`Z3-hо1ꃋJ gqp{-rVa5ӝ^E9sQM':R m#+^VvbK7ͲڭJRkfI ^Rip8itL4񚻬SkI%[7yEc}3CdOܹ+@#d[6`u~׹6zqAU,tzȶ$iK? n[uH_b8kt)Hvw}jflrqRNDV=.!\:9bDA0~ 7sqP'-fkGg)ݙoi/V: POǮE:{Q۹r!/oM"ȏ}`]~h)$k$䔏wJNN E|do%*>2.rokp%* jr6ODԅ/HpeC goRP;*jef pPlppޠ\o ' @, @l*fL :'0 cfmK. \Bdlu/o:N)Jԋ* v%Ji>OCpKq>$dD^g ayJNXdAP y6"@@ b1B 0Հd6+"haWNBn+qR%,% /-Fb-@p @pj$QR%Qf0F%lΈ+T!;ȃ܏!IK/fn*M4 -K80I@" Fc`R* +S%ѡm4 b6$072#RH/caɌpQkIMG+*2I1.W,Щ 2"s 2Y62YR@ j$'B1+#2cpo"E'43BmRoUq/Ñ;PFpe/"G% A@ +S+ 4 ( 1 -9Ҟꋺ14_"g:7b; "X2%W$%]%x(" St(3".sOƂ jq7qC{Ggj3 2>sKUڐ; s #5@ 0Hѓ&VKO@>E'D!Ϊ9q";T;3_S~F0bltCi D>)!E&ԛ`O'r5TQ)aRٔJrˬQ3u4.S)UPJTJ!-P?P^UGCU/)SN%2RmRg=SIqWX'FyCX#;P/'n_UZT -V[̻NqC0jzuĕ\36J. @7U5:4BkuSifl8@>]`=VFwJY#X4L:2- M4_,1b,-S.qZv] fBB~vKi+(b1@ZIhmD6[TW7"j vؒo #?RYb#fqOh%[@ߴ53A #n+]j`UjTW2oo5Vk5vfғRL1 ij,&`rer{V\WapO^\YY /lW7qRbgr81 gw-v`rwP#lXShsNKE:Y Z7Fzywc[#/dg8S{Me/\wJ7ibK Kio hiX̶ZW[6N&7|{^Pd6sG 8 }'k羢u)J,lx=muu 2E^PesM_J5Ux}OK5]UQqw_34p 7 m@-4\U+> YjXxcK|z"%J'XXำPʌx&tCyp{3,78lwb'`m79Wv02yrf h#mގuk5vQg@W &A"Q@Fz 6 @gioPpXILcŘu{M"RCX6ǀݩFDcm>-P yg?dXvU5dpw՛M9㸄SDz:)oC-ju؞W&db5~+B+)yN!1Yl?x4hIyHYyyLxcA7ZM.:xZ^+RxֵӊH"jXc5Jڨ5 Z3uD|T#ƭ!;4?L/-;b!UڛyGjy;YkS׹٫x㷬ǘ`|!JCx!Pi7; zD^f;80 D=7#]c7ZRe&H:GY}om%4LL53%k<ϡ &-Eip:a{M q"$; b.(=JW9uDy/ߜɗ+ݍxAc{V$+u.E$#m+ ^{(sb9I~qLj>+Nw> 4OdU}Kd;әyE SWAÙ7YwsM8 Jﳹ=O'1[G- %尿=#]V)Z+i_U~qr\kS6ݾ|<k+]$_;YYCb6nEu"4 H8 င :d bDD @AÍ%8pB 9<1@\| G*,/ļ0B  qg ,3 JR?:}T'GPZ c 0 pϑY;F, E6}kR" dAX`ߛ)+0m j5ɾ:@ڋbسiT 95aTU~P\^>zY*u"]-axUY"QF_M)HuX#7C3lYfPɃ,ۯ*;bׯ lpq݇@UgZ!4VbсXITe!G9{LY{T ^IQk2X-d)@IfHֽa@ْqy^ϥRD$%z~Y{BdfIBD=iTLtzTzf9_ee\)zIJӖGKČkxfRgf"bmWan) 骐ɠN6%%Jī_Uj[ǡ;'ZChbcR8*mڪT)lYԢ] I{M4W8 e:XJTE۞GUl)l$oxO}.~hnXqrI4 %QTjNDdN/F.iQv%WTxOybvfCN+jr6p&҉!IVC4v\Q(Dtɲ,h@c]II'sӄE\ȢܠZWZыX@~y.Dc*PC|ь.p~+ߊ09b6``a3<c?oۉ^z:9D9~ƞY'9xX&~멣Nv"rʧ2W?IZZA nSݖTdM\Hq/H1͎~u>/,hKD҇&{ ~g3YbQHo!*Zo)L6{Il.<$ qPg0 ja{X$wsƨBuQBTA<^X!F<2/ [hIJxLTp:#ίhV5, /&rO ,,iAR ""0Pn[ޒ7TQLF;X!Ze;i+< * KFh 5` &'Z'HV"2gOӎڬc~S,nTȿ2Y89T,rr{laD<9^@,ۼJjRH2䀃 :j9%CINQf QGd)E5ļfXb4@PDfWWwVA  hUk |F;6Pl] ʨ qRJgLf6\g\Tj`0(NU"e `V'yM*QUGM )B!(ZKYZCˍTJnxZ =,&!Tep+Օŋ1I69%)n,ɔvw03&_sAK%J'F"b6+U,uraX0N_z`VGf%mltңא!s'Ҽh9A PfK NSG$ }>*nے C@E8۱'"UPՎlG!_Ex$Qi;rE\ÀZp/OQ2Mo+l9܂{s(RA[q{8oSa̴;!%3D;M z'AlK; =,tuv/+@X ԡSI1Fܛ`aHikY I/iPDyQ;:k8eK%P+5A;M{%J]i/Dv_wOӷ rǪTɏ1 ŷuu} PyttFCip~Yx|x1'}WIGXuAp{d T~3׀gj|d !Ft}[r<h}2BSJ'f}G#Ē&Mn&gr-%d`gLqÁcLhrc{hW*pZ؁ nm=dv^lf7X6xsxJ?tvBKʗ%UX؈LBHJsTu4.QwHLċGH hRVDsX=ˆ(HXܨH%hehZ(yyxh8dhw qX~HRgXY iTi َ iH}(ɐ)#I%)AI3*鈄1Y4ɓx )=I-igEɔFr:MI;` Ӓ0ɏCYL4LO)pQ;EWiP@ĖoɓqY+fi. 9ٖS49 @Pߘ^ɗ٘* eyXrIf AIe +P -]ɑ}YN Su&Ii9 1) )9")8fٙ/9f)#6ًٟٞHi\츟9)3)`yl7Yf9YHs ɢN7iJi3j{dyfy9 I9J*)y١cٙ?:艥;ZYX_ :f\CȞ>lڦuYR;~hffl}w*^/ʚ։R kS58i& HJGYZPRVV`p*j jOZ$R.nE]geG]`ڣ9s \ Uf~@ Q]Zֈ[ʙI:V٤j+OVkٝ\*J&6V ߒsVjc<Ȋ: \P1nec Ȥq+@}Hz1#~5ʠ+u!;j kvj; tWy(W6+98EkV |Lꎡšf٠dJ~VkڥP[^+?kbKX+2z8çvePxu;RT;A[ "ﲯK`t}4۸Ƀu{*Ujn[p+0];{[d[noqڶ+I+wػ*.;Xyˍu,[&{ӛQ>ƛ;ᛵ㻳[+k;/Kj^K#Jjl+5;: 绷 hOK06  )#LNPB k | իʼf˿)lC[qj+ ,H?ܲ{ILFT5,Y\`bd9 ';̑3'KLU\݋{H.5޺!UW>Y~[٭K><,hN?j~ln,g.i\K|}@KX^>{,9ݐP\ۑ.鳝.̓>[-B~ ~>M[͒ܿn1Σ$>簾Nimަvh1'>ޟ^ <}>~rZ{H=Fꥻ^8mޞ︾Ю.nobd~2*n#a=qnx+j)cNr>3.OF) vu" kNΘ=TC@ _R_u~M)?go5?Ү9|ܤ^+r_/km_N;/=;^UGJ@m->̲}4oM.(/j/7fos_c\^/m\O"ӬRzo*G >_X^θ\_ (A .dÇ$\D5n$p2 6,@B<ΤYM9u3B=IPI;8 ,yJnW&#@#̆VۃAΥ[G'- w&\+S 2jY2帆5o1I.af\i*E1f @v̨"Xӟy%e//g5o L6p ҽ9N|yCD$A0+el 5\[\< o2o/*0 tAT+0np h2H#T5 uRL?\FL/`Z00,TTT$ĖluVZyܴVNHAW\WQJ{ ?C= Xh9Nt3TgLaC(5 %u!n],-h\4$Xe֡vGyw {5eGU~uXĀXM7Gۨ;.0⁍-wkAۤT[pZse5^jn]֙9s]`T[qvwgj?&1Pם㤫.mi4_IzOkkRXl:z-no`'Ӷ'U݅3n*Gϩ#j=)z9Sj޲NWljt/]׌ s_%Iw w݋w-<57pu?peS~٣_/V^v>f"{ ?wSG>=3n|ɜǽ/OSf#9ljdXJb =gDSzK:*;D) 91ReZ'&Y3LIOꪔJdFMl84F&\;=5ʛJT\A L{Dd.{t`,KjER%3rjq$?Ԯ"JB*m*|S4To6̷>3(+t40U+H|c?~˦ ALbJnϼWVZZ>Re-N6IJj[ozmp-&'\V~ ,&Q˅π'uW,ϭ!Bk~Qn<뾄/{PEU@ܙVob+ޟ]78;s y/2_e擘tM|bX+fq]bY*B!~6RF27q RDz !; 3)Rk ' `9LK=Ð9 e>s!:8c J@cN{r 0up3$X@5h5KpF[g# KHi>0:t GjӍ5kQ[!;}_C ޯL b$YٙgKyv4[ ` H:r5lY &qZՎ)w6qnv3ݎ^2Sn[:1Adrz5,Cq[-FD`Mq [6) 3FK69L)\"uȱ365SZ.4bdvG'ˀXn $wɋ gG ѰS= N"3$ !,{22U~Tn ,,"$'55 ~ JOQ  P P''QIdgm ~IQtn y56U56Px H,,++Sm n SPJy H4'eft@U**++T@Hyx xT} ߛtn Un I~ m H} T4--UUUI|| HTx m }~ }ϫ~&&&&*++y ~ߛHt|JUm UHtϠr '| i'Rߛ}~P%%Ӌ2PJtϟ| q x tS}x Ƨo y ߩn}2Ҋ2f.ߛBӊ2<Ԅ%Ji u d ~ Ӌ3o Q&̟Uj @y IƝ$} }0߿i ˞n 1h'k f'T)d-ƜI˟B˩x Ron[ Ӄg*kJb%sitz[{ފ뱛ޣ:F+di[B+:r6H@vf+n\ۺ(l^;W[ގ nֻ[v;몴R/}L2 pg»ܑ3&"1#*Ǭ-{p2l"Թ\#:r6sH74t>t)/-]3> uR;G5V_qmb^W vhjlO]vg8u{y&v(uZMp5a+nюnHvR ˅>e^C˺k{Ύx_2Y|'{ϩߩVi8k25@A5wVY/|?bmO^ P)8@5n{|[= /}Lt4&Gzor*|.>GD*[BIƂrMĔa/[xl%PHNpZ)Rx"X$ꐅc9.NjE1"dc8;z ?B"ȰFC"/ D͑/`%+Kry*#(G HQKl$)Iu\e}Ĝ|O zs٦+ׁx,VOFtV/ތg9X5?<͌Bړ-XKS"O.@|/u"lꄞ)t+pʓ0u L:Օ\)=M*n)AժS]zR2BךDZ ;VPSӧ5š!,5=jR5V],t*O>U5@Z[vJ.zR^'VBZ l]J_^' ŐT%WoACY؞wP #f?Y6*c=ʄ Kbw+x_V9~)JVF8#Ev[ɰe %8&@lo9_ #AѢ$ @2 ׌ oP)/q#i[fyޘB)IA('9CPkt(T@ Aɽuճ75qz<s-/)*ԏOߵIjRlyF/4\6_u ҟoVLpV~/9QHA nَѳT×/H[uZA)ceoX$i3]h)` 7Y'?at`'P!iN9" ?. y,Hf44'`v[Q^yHvbуth&։SE#3[m RIfٛ9ٍDB" e 攟[f'2#y|CGSD]e cpzySyL\ޗǡ|_~\(Jy,*^S*Pc?tD>A>4>6$HalЃCiHJQ浤YeX[[؝_Z&cOHT|Z*E?&?s%YG =uHR~Yy C0zJVzYVڏ$jy?AtE@tv 7 r֋aiס*q)ӟE9g XEIhA$A@tF=9c =W:*I 8\\B!/UG<TJjdW  jȱ\U2%}*cjD٥:v!ejX@m0C>QC5ePya^=Luy+CouV"Zju5" T7)wGڰGѶQ6Cƣ?jDE^V7 Jp幕 W|==x}K\$ګxbTV{frcxhY[1urƪu`yq%eֻĝ!Ǝ.!IfY&ɒካ3sZq>8k:iYzUib+CTPjM{"[p ʎ wz:v2(kS&,Þ&kL%mD+, 1 =Ka:L( }{\7xNL!Ec׸P0 kk7KE W U紕Y7|VcXo6!kmCqiUgV)LYR2ڜx̷Z|`Ȱ)ƺpO\(hW+[{֫zʩ%G´ċd7ɻ|d!(iƫh+@pJէļ 25\HVZ*j3LL Wf˜l~V~K㈣]{9ʩ$`,x6 P?t]̭ J Lˮ< :/}L 1h/zՄוO0'¤܄nlhR`"}bOnA#}vL/@  D@B//04I7#'Lΰ@M7M@4 E;Z>DcaTqL`%/TɚR0ѵ4RSDu?Y0955W9 r0ϼ{AI )ӑL\)D,C37^\HJ)Uk3]%֟ol% 9`r >bvʄ@Z8-3uVM ;Bmurmr(b۲ϓW 儍/um Rd?UZSfaV,WV4x;cY_UWG=6<ސ?^WM: /-jAYE&1WT 2>Y#JSeEnWsZ$kSvWqp'z9l=쓂*ơ֮f C[ÝukbiuA ]s9فjR7EWg<78D&L{qݛ>ok!>w7#G/'Y${Hإiu4T 7j{ Zǽ.v 8MPd[-d)k%f4-y ) &`tV#1/a 4Ypq[A_iWav-䭦w+ܪk!H -o{֙JK[ɐD$l8 T#ғWa"B]g:ėhJՙgഔ-'5 4;g9ƻ`OA!WijQV: sۢ4K׭Ksчr0r69Д2mG{QafHWz ^y.G\e^՚즾̩4y=1sfVT3 Y7(tb<cIv}ő8+U2"jˌ(IiJ-l靖J7f$gAB>KYwا~5aU,;Z؍$*Qd]!nrVVŝ,]AMvcm0YSز}&њ )6[Vϩ:Rk1]7u%[\"Ry%i;rJ wFٌoN+ }jXA1(;^ʻFm*WpxnUj5WeX_D!dJRdn2{ LJUjicU1Vt:Ngq@ 2jz泟M6<&qY3񐖢NYXRfAjVɪYᨌ Iq%~#[~/#uď2.ߤzٴ-\ZCWԧƶm&úR$@{It6h얜1yT: )7hm)W֮g'3[۲-M遆L` tX)c~1uvK}?zҟ::cϏ?>Z2Ǧջ/Ko'шKR9Ɏ/;.R (o zPޅeuЮ/b/! cH DebyW-wg='i>Bӽ$Qa,8.K{jss <=KD!Q|XĻ&U)(݊\E!Ȁ0RO3<P*k"m˺2S4/:eJ< s3.ArTOCE8DeѼPK\yTΠYS@RDM?*5T]BſVG7%%4M88-0"krb Vc[ǧ#Mf .Ug DLm TV&M@Q4Ms)md-+%8yg@{5N e9LՌLscDt//lDlXS EHp8$-\=%gEYq-blZ OM?SiY0Ռ0YG!ړB@Ȥ'͊5X%]YN=WU}qcPڅX"(jڍ͎bXaVՏ=ѹBdF|; tm@S*å_X51Аe`kUq\-ۼӘu5^եtAm " }{܎U1ٽԹLI*HWUs> eu޴\؝# ߖxbՠpm U]ۖXDB^D^i}_tT]ꍌY ]ֵ.7\9S@>H] wS3@i`a]ꅿҖ(% V _e8%S<5| ̑&^`A]]!]V V (&.S\La ,՚SCRbl/Sg< "ޚx Up!ǥԑyM:I*c 7>p@V E8kg2 JT:pVm]~lkN,@F62 /# l&( J >zb_Wz&dumkjmoSR.1ӞJigEVvnz]3۞F>;(l%Hh.~kf\o&l8i2#~ա8ɉIT#pnS?ot3\1҉Wd 'U6Vm=w^^T먐1+[K.%,򹒷m%2g,D,e8s-G])e})LqB?.p0O8 jn7Kj @[&M}!(@fFR#tCj(L * H?/p ^'2@ s+y* wKK/p&O|$#(wWCt-mU  QZsA{(r2(Zx{Ot>7 l;7lGgh QlRI0//cJ}9tYg\w'gy@vG0'h8ɀqdojf }%<|WXD&ϓߟ?8"Z8SvvRpj 2TC!@"ƌ7r1b  %Pc˗ 9`@B qBA84NTRΘU>trL r$)z|8bPrҭ+4bą8jᣩHPI Sr %M^%$TKիE>:*N DdQr!.u6ET0gGmz`y  b/@ >^&MOng#PWele9Sg@r>u!BP{3Q4߄%h[[ uЊ E҉1*a{0[{2X}i@?mG.vQnю4m0C8G @SRIY^w޹8揍PzLv V#($)pFѕLB$6Gou`O_.9\Oj(Lwf%74 CbFӜbJ\4kFdQӠfPGi^Z+ d&{x͚7* ('Y[zl |?jCvk2%k-g&@rK}!(y~d@ MiTA*J2&䮿!G|`. -;tʌv|FknCj3>@~I6,^FVSx(x5 C\e?ĶdL;. r/u~uUIu߂{k4ApCvQ#9+ƳWuF}x5_TP^>ԟǛoǧn; qrr7߽ B nzyU aiOQ}1do@=ɑrGP"?К@/0B=L=XfW ./|GL0voqaPtQJW!7-yQ^C."Zp=d)g8*)q| ajZ#k&_^C šB@qF3\Pr0UP(g{h.h @㌤ B2P8 +LLct@'] y./wϒɰ$LXȮ:Y6%P&dEURy $Xd,# H3$X#Ua. Dɴ"BYO %F񝏅$rib-sech*XLu3oIչhBlݫi6s ٿ!wDr^gZuSD#@bƀ1 dS%7c(Q Mg%š߉@7=JN\zD!P9R(^" E(C 8lBT4:1e R\gT]4JjBJf])[Qz*tX76T# + @nI|I {4 DR੒ Jd"ː'c,h58yYÕU~$u O!٤&wᣨ8Fץ&mjPjj#Ll:9%Tmmk%H!X nəwzZ~5ȆHLM0Tܪ&̓5% hkᛡO#PJZ.-l^<Ů fmI;^2XX@W1l3ebx 6d0v̌(!r7>!3 k$>vrL"V/l?|-~@L\Dʳ@wExaRW ɔf3M[8a(yqKg5Fse 4>!QlR>Ĵ2F35zg Ҷ15'UضrFI)hXsٖ͑^և{]\ؼʖ3Yql᭱k%f?}}@Wnty}ݸexyw1 znِiCmht 8y0Dep*x?yTukȻ y]yC[}wPOVQQ.|g;"vsozɆ%u ֭dOOO+-1,n*;h*+qĵćOPa6;sjC!yL=kp}ztE&XWj4T:wCۣ7qHp5\6">.ǭ"+ \_1Ddo@/&b8rj@PYFn Β=$>R[Oy{d.JJ]bX=XZ1:sR^1:ϙdHdTRIƎp?`+jBW,*DU[X@N*d5$!%f\2VU}'BT#eT_ޛZ`cVb%cr#wEXE_DdUYbL^ɽ!n1\6i2]ޡ) XFZ66&#Q X"|GpGeh P"'Nxc)isʊwfA# Kp~c B%YbZlebͥ%Jg&1$qR\ Ew&ptX{'Wp-&l nK>@wtۡD4Է ZR<|fN\&i}.TILb (}Aa#d"Mf^ ȥ ) h\FzN1yhngv6&&LǻTUcdnriyRŀO"gOs.iF':n,~a-rO^zUFD ^IP1eO榪MũwuR!Ka"8<&i-\Jeg'hB%ۅGT@[ħ)f*&[L+F.+,l@ܠ4U&fz>ƪ2&NœO2'*+hX!z,f+N**{zvcF*^+&ѬlƆ(JvߙR .g6R$V$JŮrmGVv)QUln\%f$ߪlΦ*8XcIͱ~1"kl*B *&n\|".c-l9/~.-ŧծRZo欮fQ.펎_cJ&M< ',n6qGV.{,{j>Ji>@D]ڦ J0 l`)^i.#"GS,0c𱊭:B%Bxl 1a& p4%*nMqm_Rϧ( w( k29FJn Rz.qrȧk&Δ$rj\dzSYЀ"K_D _s#sq Ǣa--FUܨ &n0ކr))ˎ 0-sq)rD3 O`xJsx|پX Jp2~62l,o9E35pd*rYx CtNJ3a>rFVLЊ 48^KmCG)DGP8o v2GrIM {E/ @@asGm?oAkQ_$1[ga*Guڱ7Cuִ_mEg!dWv~Gx0l'Qb{8n9MĭYWA_(=rf7rg3+ J_njψTgOAT@ 3##m(v))M77>rwmrq Qpu_V>K"bwz{]`:LQ-Q&t2tO[Rr9GqtSJRx {vaW/tbL7vpGgN#tz70*,귽9at[3 "2d|c' K׾z`E_/y&h5w5V4./3N{y;r@ǶRaqhqyvrݪ(ߎvx +-/'G؋k q,K鍯%oD'{rvAyE.7s:?u{ōSCømkd#@4Y5;zB!,/M7]~,jz0FcG~n@x'9ÈlۯI k#?;E$;qw6+^/lt ;i9{j\&;"67cac~dZc_z28&xU{6xO|.ϸ_oclXGdw)9߱Gn.k.`43Dy0x-kg>8(GQs=N8DTK&M6K1qB~ Ḝ?sV.fHrWuZeuuqǎ*GvЙ}bU6ƍ;ׅh=V 7#>*Z) D7]eڴUe8-dX^vNੇ߂5mv՜W\"PT&F[\a&3)sUHǣ,X@,溴ei]@%OiZg%wPg RB+` q87Z> t2x:c Y3#\@UoTjpN1sHC l\CNh"[$/ B@c&V)PNW B8L K8d& h 5J`e.c:!,yQ!H2,c+H c lhTJsPȃ%ټJ2zQjolȷ>~Ii%l^͌I zLp `# W y 3*WL-ek&?9>~jnG_Ѱ`M8D։ 0ݖ h@scUa`+l'h.K5MEꗲ 2,q縙j5@\VtttU]8:u9ۧ!߂yƺ;|g@{6.K86mk45HKUq:"4QmWX!.89FcNwZwR/ -x۫FX[TNpZq n2o&f.zr}@O͕}y\M:ilk;ާnh߆]BN(ndq9C.:=sۦxޅ#+a:GtT=z_‰B,U]vask9q>9曾 G>.f7_q^Zu<Ϣǎn/mDl4/ҮpZ'ߠO!C`O,hϞ,J/+|tj!/\04ଳFPBzHkRp hP7܍ jdIA ڌGVp# *:X0-Ⰺ !̲I MIN Q- f@p L Tf th$ n,1S2`  Rcf^`v)$0lLPsCI zCM+٦@1o5ß[1 +PM/~$,Lp'Obz;RP(ohPV¯0ќLFO.1:N%f  _.( ppr=B @?KP?9בm63/  "Wo;es إ٧xgD3z Z-3Ӗ7+"w#1a)FL76Y ͱEXby쀧U^3VY_VAxbĀh9A }Yy.Ge(S7(cYfD"T $Igb39+Y v\'N(Ҝ%]Ȍ 'uË9lNyZxb L9۶|6rgwwIXmimx"WtgwbZmdmE8y7G,In'$76'KM:SZWz!*D"(>cFx,׋oz7v8pbtX u9Jya|6w{9Vs%:Տ秫$_E!C¨˄wÓTv-{nYb 6٧ 46:bñlxU낖l])O:F10WṵV9Ÿx.E0Izz?CR3ÙfX oz qt\[)B/[On}k$b !|"p(C4 "97R\ m6!Vb;^[ݴ{ă q[[fo{;;.3Ed)ո7GWWEZ5B@ ӑ{L S\oiϘ{ ȍǿA(f.4*N9<Z5ˣ/6ڳ?̹_6{}xb| "!B}C(@ {Zs)tY›'=x!]i!$=90!@'pȗ_L\͓<ԙ}9?=1%IFàۋbŏ+]יF<ډV[7%=!"|fDºM1$URKk>{߯==Q]|>#iq|<ؿ 43#?]d m}:dݼ6y+1];|~ቜ%⍱LAD JG'_"@  … :|q@O X1c L$x0Ƈx p FB8@t3Ν<{,PϡDf(S ͑@'x @zR 8JuZHfۜoek[=*'KubŚ(<@kMt;4('̱9KjiɥMVf|TD!n :f˞Mv^V큘tc5jՅ U'~u8Vԍc axwrn蹼G`Ta뛝_U(zE5 rjq 4J3w@U)mלU[dQ~e7x=$P~&E_Pz*mcWZVH}O%h@a0m YWjTWZIUHTE%tebؙdҹ&Jcj'ڌ#9(S @k& %VuK%!E6U`ȁfnet\[c`9pb~WDnE5fjWvh(RqFRt[J6YU @WSEq_zkeҭގpi'⊔ripjUl!ǎh[%D[X۞ U]2 Ido'g։X߬ qkżfG-ѷ/I,^ ՃNkUapbXef]{R'mОp -ӽ*Ur*roL@@,]0dnZ+YVcl*jߡtuOmULZrmGaH( wt}TJt\7g {t8v[Ը @ಛG8i톒9J}(w2K7_)29n2p/^>{Bw$ s :Ч G-X];qZh}HaӖG ȳ|_{2' /vL"WL~A E!%A 6_*ن&bj=Rs2.J`Ba '"p}_}`8IqF i!Zu@ -V6{.գyL|(qkozEDh\!2 O,"#uF4"Itk ()']'>:Fz>X8.GXԤhH/B@ RK+ ) э [璨E~ D4 >S'$=ƲxCr"{%RCaKЬ/YTI;9R+@Bp"ş[ dd(&y =π/Q3;TGy~4Unt(AS9 @Qa 9JW *${BHUT<=E_KS$VYB0rYRXć#"6Y ̏jŠmP 8h*_;yti "Qe ~t5E.=U"vt%$_*|@ R[ߦU,?h$0($5J ON5=gMG锧r=x1#5H!-Rڦ5;Ϟf9bYV7УQ /pP[IV"rr|@hv8%R`8!*o[t[BmPI[̆# f]s+^d qS "–!6m >qk&B下;&}젚L= UZ%K`5{|2㈞5rX85,bƆ|Z2gR\#'3p ,b Ӄ۴W9(U @T]5l˱x*+͔L87Ym il՝ғ{δ[IrJ1| d#swc{CK+*K 6fݙǂT/)M+9;psf  (3by!3V@yZR4ylsN I9CR!K9Zpyћ 9Jlw7M Aq?[HsZ>˺ѭLаm]7Z P'=;8OnQKW i2\24̘"qr!"ƃA$|WkE2b>|/NѬVIpK+EBj'fB!.h{׶HF`^=< NC7~NszVuyC?l.bvOtSarȒp~y~Wi|W~V.^B?w$PR}бZP6aPQL9(t%~gz+uFuV\G.>y7Zx9=1Uyxad*!γw1:*RM]DE.qwfpXSv'+]6r(/jd"E 9~@Ćb$&y'j+U'RWcz7gGPxWG.A Up2dfYX^|HǃgRexap8lE !*H:ۖ]0aPh&x/h(٘(lEsъ}X"8Pw&#8ى%J IJQX)GgO#9Ց9H, Wg)HMָ3I/!u Q&)558U ٓ?1yΔ1iI) 7\9ixiǹi9B霜y9+ْȚ ޹ɛ׉p 9lIy Y 7`Ŝ J 6ZPziIYY wc 7)ԔtَvYH+c/ʈ)H5_J *`B:siɢHJ!ʟPp:*@&ʣٝ^: ڢ&k":$'9zq s#ڥw K+ZV e ڤBBǦ󙣊JX*LʞNIG~کꗻY@ʨg:3ڪt v0ɗZ+z* Ru8)k.hڞڪ9p 3[ X&֮*:~ &4e_F\Y *+*jUbbIwfbk bP_ꮜ*yt0U %O[ˮF+JZO (2!\ iꉵ\:[Kwڭ+j wH檮銮}+Rz6k귇A; K;lF;˰fIf:ڶ;W;ٹzY)۴jʺ4[i{{0k;(ZʼpYc0Ãa[;[%E 림[ ~u닿KӋ[ ,8[M )}Ck˱ !M{ {۷<;Z;‡˱_[.0,(L*ıIĤ45I+L *7+ڬW4Y\%ܭJ%~]m3 \=?|P:Ȅ|Hܴ L,Xu˿~̭,1p—]GI^>>Dn=̶ (ҏ ogng.[A] s>?wX-N-j] /1?3k2+Z ߨ^;,DFcLL_^[S/߂"fGGIaomtp_rt?sb^Iԉz|~oK_^Mnq)OΏ]OYꚯ_ۊ':e"M*no'p6_i۫9A/OfN_߄':m+9F[pC]+#P0lvbL[t1. !O@pʰF{CgG(&t)8 t"Ib$@,2(äN dQL4 )h9L5<C4M6I2RPFS3ḤQP`%Ų02* Ep?!?E+a>PsQ( 6X /MJ!O2SuH) @pHmtRXY5Pk'kMLJb?N<\b vxUlGRJDՒˉO`t$PInasDsO\/dm1]8][ʗˍw6ɞ.yș56d vBvWP,a~1i1nllVgai5mS%D5&n[>n=eNw|cg$.H| s$̅"ws]r1G}vTp NLwlw\W|~yoϜyr^peѹ׾sǯ}f㷿xo^2mHy~NG1cxZz8F'ۃb4{9IGh(8JBI4Β𤑙({͗01-L+)*{1&iy=-SZn.QTݧ^UXԠϺդVb*2 RIHHUUֽv}&J^]ȶaZ'cūJļDZLa נԲ;. j_Bylk[/q9jQZ2ێ$I)K,ma[kr >-e%g kY{h2i.4^iX*d0 -}y!E*[\Jn'ks&^qZBxU_l"8*TKԠ^,UKq{e)5cpb1N5>ڌa-1`|2yaE6eyd%YږFjLVbl%_D3{YlA3XȜ 2/v?bfjY{=$hAs\+ n \Es.Q]jXZֳum}k\UT!zЃ3^1Bzor/uy97ARF& 0;Mvx6l`` 0}Q "LybyivlQw% wݰ&@Nz@}ߦ%o\{v p6(\b2l(6AVNm\ 3OR r9/ys8]J͛W\?5[o 1t{SvK̛gvsos}4϶󨟁voK~m+ڋϵd[n&wNG=Mlˋy=/oܔx~_|7hwr+<0|͹/ysh;56C?::54CT; !,22U~Tn ,," en YaJ~  OQ P P''m Q~dIgIn Qty5U656Px HS,,m n ++SPJy H4'T**++t@ef@THyxx Un ;ߛtTn U~ --} IH} m T4UUU| y I&&&&Hm  ~ · x ´*~|ߛHt~JU++UH}m ht}_%%a'P| ߛPR}J tS}^~t|  vh bfx I#ߛx o y 5& d JiZ U#/U@TWrgsth~ ߿ |aYrZbva+ossk }nC. 곴sn[Z y [ }nRZBn } x tY~na*msnn o{ ud9*[TkH*\Ȱ 8Hŋ3jȱǏ CIɓ(S\ "B,cʜI͛8sɳ@[uP#!0R0}JJիXjshРfH==`T\\r6H߿ U.TbTq 1@v)״ϠCի@$d(dв@̴Wr曻kFRBVxzm }nճkP!oFxq(8c\i&MSP%tWHpiRkfoʩљcz.#o|jhe^掁9(vF*Cnw)8W go~~)䩧bgƴꪹj颤:);ӭҦ&[EAlUjBױ,뉳V+nE:hZm>:wX ʛmhډkp@50- ܥ  J2.g@b ^!gFqB-;220ꚜo;'s?-/IP8[s/ݴӟLF4<˻5׋V3lRg=tnmn=La>7 Č,؄Û7 WN2Clb#{ܛ VM?Bӎ:O烻.??b20"ڌxz],X  vW;}X&v_g%ASB*/NzY+&Rn? p*4x`Ѱρt`^e TH4;s] =/{VHC)%TCjܐ{ " >#:$`y'Z$QDSX+zqC/t8/#YI36H4C7QcqX<,H#6G 1n$ C"2|Sz5Œ##mG~,̃ ('-,! O:y҈rZfd1\`_ O!k@Q l0aZD^1C9˦SM  Igf0C)xcK")Sܥ75 1e~P9OUjRdt: 8TP0dO\ܧІ(!M^ȑ !EgQ a4I2ԊNG ѓjP$)MRXt2fkÔf%M(OySuB*}JuSrT4,*Vjr*\Jn5~b]Seֳ>/[!!Vj9-N ɻr4s+_}WUy)"Jm(e,O 1($`8m,g'Wry xQ],F,YNB n32  A-@g&w1 Q]uE5V*+*8@Ղ"fw(UJzY*(/o] B R(}~0a Ze0PFG8,;]0&Kӵ4(ek3` Uq8VR,|WI);Ůƚ ϸB^9.u %]9XEZ2  `ʕ\e5Rl^% 07+9f- k:PqY;i7KeJsc]{PgVW yu~n 6;S0v)-4uu+e8nijyR~ͫnKtc3܅_-&zyO9ՁBp ZTٕ2 >›afkW s^t+% aQt%z 7(r2mP~bs8Fl%v_,xd|"57uJ_|!}_rԇ}G-em&J}U}XfC!~g|ޕ_g{7nq)N|ơ8iuw7ugXg0*؇mwx9'U_-g'hpy%7\d h&X\s4u1A؃Qr%cjZp< VgQ̧wk47V"ra7fZ|PhX(rpXCZ("dx|&>ІmEѕyxVZwz,}т-8Hu J1Z}u9{^:WYcCv8hfΑysk&1+hY(AÎIˆhkj" FxuVqwrT{@Zk2 FA ns!N_-ÎeX9B:UF)pVy"aZta37988o 7CٔYYx2prb?{&yuWƒ='Ix_I%3xyQV(J0fnJ)L u@&U~ HaxuoTs]{_~5zV`KVAXz}$y`Shahvf| XRA1Y9~6IiI5B%*n76!fj78@뇐SR"B3]vtA8K)}dHpBŹgf-F[xޅSX뗟 5|Oc᜕i\iz? Lav)!*y`i (JEq^{H U8gf_yurq/9y١E"Ec-z~ǧ-gZ{0B&e;:k>`oJ}FL"Oj 8em(hv] zZ5j|t @Az2nwO&zzѪcӺ_H[yY(41JA4PdN&[]۬'DmN^AnOm&]hݒI!Ch(jE,.XJb]ץِcynv{[_ 7b vZ._ḙlp;ghnk%٨syeaV]q줞Xc ?\6K^a6ڲn\!q}=-mv94̧'~N^f -yn 1厓k4]ya o.٦znn.7=HoS6C8Yߓn1o3AmR.>o`cmV^o$fK/vmOaQBGAz^Q z>L8b կHHD*G]}(~B!֍:o@Jkʑ?*`_cK_>/_.u}*S-k(^~A^fh!Ԯ\)zdM|?ڿ!` 0@@ (P@@ -^ĘQF !Q* \ბ$#A SДL<(ITRM>ezNUup?6$AdW~Eb"НRs` Y 6H a̯H,p^_aiVҏjR̚`nK:bҥMFm-ԭς5ɾB #Z"N5ϸ4% ^|q8'~ ;Sp˞6t>34@ 2@XA. TkҸ cB08sB3tuN[u5Vمj٦=2yM EkQFd9iJ6hutPD,ReUU''-^r$%9v)y{ ~h~-ÀTiăQ/h=bT u/jXdvթ )SYZ9Y\?0j6С2XdWһU]5FP&jA: .$ZwYry$ޛn-. o{Y> m&S |xM Sn!߼ 9T_ݮw-MzEIH`>| %E{B *^qw s_Ȩǹ<8dtġ}CH0ZIy;T͎#9~k+ !BZUU/HxkƬ&AgxHYz?$ d &…pW$- ^L`W-Dc$IC|IM$z唕b)KV,,]$խ(o$$uJВ[+/h$Aw﫟H%|2obdd8Ngiz_ruTG;VPA cVXM8N+y\ "ۆO-{ $ùPƨLȻ0BH$b(xR?RLg)P֜LsP"Ρp'E V`5y&aRBZʤU >UcvS49rTYZ_FXK`)9A9S +1jYˤ (JJHb5UOVF7i޸Ȩ3sEB$;l3C@TsD6 .R6TaUKOvlZ^kI!h)`:ĬvsʆUVsYڶ2Z]mtYrG˚gTizQctT' atÄ Zm6f_PR'+ KDԎiC35 @F^1#HMd {kq׺Q{X:B֎xmdfsbM d,7:#q`!0X8I~wHNjq;}`W9S$pИσ8"Jf cΞZnd,շeZ`*m[&*|fꈖpСݼ_8O^bG~L*5cKa% S<hrL|v_.d6*P/r1]Iƶ>=q<WԴU:9nvV%> .6.{fs&8^yfm6BZE 2 [&kj3hO[wY%Wv-λ׈,KCj B\6@ z| '3;zQYj>ʦfy69l`.maސ@#0xSvL1!u KHd}tczȗ%~R#f4@ugSq;qn} ذsɲ%ke%'>A:{x}i&UB6qd_-+ RyݿK<V%{!z!ˮE31Ǻi/DkƆGM]7-uF;[ u\ NA37)@PsJzq)h=+K2kq,W`;9ڱ Êxh+c` |(bIBؠ"␑,-!.l/:C3j[lꉖcC\sCk8##S;B>-d77)C+Dd4r{HⶰD哊ݛCDv2=D6@D:A[7XĞ{@/?4LBEE’ȲkD2b,྆2A/Qij Cnd=+p#, rDe3a:E)҉d@CGDžGkG!HQseY=b T4my)5;ChŒ\H&Gm젅65bEQ *T(Io2zF4!ɠI| +ldQDKiQCaG|Hf?5lˬ\?h$Wy*`+YKQ|*t+ĉB&t!Dy 4DR\GDžN PE?u-z?͎@B =Hܤվ3GԓI8 ң4/M+SԆP՚VTX+$SkHũpNqS,vuB%10tцQ}lGRUZR!`' bVYWqw PV;k\/ebI P.[d9fT^eV5^Vxe|lZoG_qVP^mRNЄ9r y̑`aY;Nc\9KrIsv^hH(dcM `v⚀b1JV_{v<>Qi n(h1CjF>ueXJ^c8FT{z}V9KM^j&px꾍QE[Ƅj`^LuE(v^flK)f(EF,ek_F^΅9A}[lil* jxe'C g3yH,Ҩlm^kAcld]6"G)=nk&|m}65 `;ߎX~&nBk@no>7>o KoR| ]m>jVo^^~o.>hXHp#~pĚ(mAa^zz ,ZhHYڇkNwㆸXG>ropI7|rNW*߱oHTc>oKsAJr}Z7(p +wv>nT@AWKq03G舉SOwIswG'\Io}=/ VbY?u+t]' Ȁ P5)SQ pvhMꇀh6mX7>6ScdW N@u:??i? pW7w0xg?t+cfw9Àfmb{qUly yw]w?y'kk׋yv gmIǯKq "cpo7!טwwߘW9x``p;tydn _wN/| /w0wRqR|]x@2q h{f'՗:.֠7}}}دx&tʌp[ q~M'}qz/gggx(j/C 8/FĈzg.8H~Pڍ ,h`0 G 'LCR#RX1=,i$ʔ*Wl%ifœ y@e΄C&ҎAePK|Qz\|HҬ `i 4'X@ $-C.sA``u iܢ+[&eހR@ C1en2C8x_&Q-@WR>Ho~gSxi P [@ZE!M:9P  ÌO ZJ^ #}ZT &<q[Bbr%$2!ыa[y uSlxdP}Y|`—Z})E)%# )`q /r܄ *e@Lj 9BZAeePN7DA +d ʓ@G:8嚛кJ{n_(Q~H&i+它 [ t&[.jJRf+[(|1]m@v_yJ6+~u{~{BpI"˘r[/|Y=+zj. (ISk't4D^p밄ȱy9ATZz] k/L mT#k6YD7mdz 4| mDofeiN~8 4΂2=gt@w g۵LJN|9xM;2v9@s  ,x ă(@ aI*^ 喩b1 z !4Mpr1;,?ӊcĢ) B<(*QSȔ+ITrh!TFWRm l+_nzn˖#%`F4RY#FE 5$2$4G?zeh\Ʒ"ZQc&,=*$@(9;x%Ii20ڏLƓ:.% 36,S!6Ir]D)Ee+JՖ"m) YMdD[07gfZB m&^N(\)K[Hk5UB:U\IJ'\P&9CG5 Jf*i3q|,F - KY57t*2hg96T SY8UC moy]gB~T?P'V}KsXϔ{ V"O ([4VUkz*>F%bWΒPER{)JtNVNVb%/{vJUvdFA< ]crZuɨҤD7*~XXeȅ,o]JY6u tSkܘ%ڂ*#5A!kcTV G+hvmcM6*jz"on.OξoKsӺV &xn}/#a$,4mr3ۉ4[lc.eȅrM6نQXg[`>jMVIsc_WW~3dՒEw _oU(2Im1o#f{ 6߽`P Y:QC[Fk5Mc*L<%C"iq=P?G[Djj?& e@:4h]ZQcz6&¨O '߬seqB3pae8Is!XN[(Il~\Ka6pށ`IZa>g7n#c^1@@u՝tZ{ w[CwO:wwX۰k,ͬ{__Q^& ua%~*+ܙE(UrM󺏞$3P{co=W&)7|J!fE>o ,7~Sz7Z6$D@ ިi\uqL0Q]E4T [ {^| `< ~SAhv ptB@V Rp }`jI}hP SPN_$CP .QA8Fmaə߫Cd7yGj "[DaQ!S>ӱ$m {- OH>N_C^| q b` G!݊-fKFAIe IiD%Dŭ4B$ ,K$Qkx}bHb&0:"bF>ANy! [;J/}c9~-bqb/}#Q5qŒ r=@ƣA 59ش$Q0SJYdcq;"؉'bנ$ R9幱TB*IM Ww("OT9"PmhAZNPC ?: )Y|\\Aa%<d UZPQˁRLD/^ H3Fe_H]ZXafUc KXȲ&dYN ޾]f$f&lII#N1E4}i"S"_BcDk@1a~%$즈gQYy6pjԠqb[*& wq2"h!Cjj'ePPx"krlpgPܦf'!)Jo m%\ (g2I\~^h)?@d-!yv\j(]ׇF.9jNWtP$[h-SzA&`VZ(VvPny8f1鼶O<"GV$ƽBfR)GgST EIިkwn%4T<5zG1Zˆ.e=슍%rƍ> 2gL3h4i.츂-A-Ī`Q -"&-P:jj8)mei=B~OGa~gUq*kmLZ.&T22% ֊+@&}jN,:nk>,,EHlbDbh\. ݾ a*BOH^@t|9 nN&,AjnϦm.g^f,ح/N|,[b-,NP$BCq)"h.Fj2fUZĪM^N Fo:o&/njdRW D0od%]/ ,@Jh?*pMmCjN'N(]D4(m.'4j  Jƪ6po)۱"-gt-Y\kpL%q 6 .B&0 Z j { wŪQ0 g~X˺ۨ(4on'@4pBTİ,^(H$+)>k&ñ-Uijipb&rI)85j"jKs+"r j#kJ2d,-[40!1߰N~zf(Or婰 6[spOXJrO3p2#DЮAwCL9ײ+c*6v0.k &^0DO *Nu`1+1S85_~;k(oL2p:׻<*k%g([ wkK9e۳[@scL[8 x~%/ Q~2@0 &48@aC B48fԸƈ'aĄ 8(ِaɏ`F [~ P! o.lE&UTiĢ.4$ Вc  J"!Um[oJ( n]i_&\X:0hPTA&w"r& T×OMe̙55EaGÛ~mB@[1xQOXHElϡGwk!]R3kk41 `.BEƁvviuע &+3(B#?=;N-`l /:Io4`?p> ,J<0)8VO#n',16& ]1*mLĺ,3h3BbGA3c4 )ݎJc.p߸P)EH#@KSQ+ML5kw)A3,C =Mֱ2ԴJR'C7lWB'MY֕Zgcf9,-sHE[1F/uY?fᢂ&[N=TcݢtA ñ5oݳ SNZNAnM_{w o ?>5q͝bl[!7-!Q=j;o]_8CO۰J;/Rp}h-|vlVѾ?׀|uZ%KcYGN<.%、5u`xi|ַ Ob'#U{$D^ ףU {Hf盧ة7Z e:%7[xu1v籮k84tnxzpJ^D)w#K&40+߱ :ZRbLչ$b"_rL՘ɈQ& FC<I|%D1iHI&ԞnFN7 Hƌj 6uN3=a#M+:in3R7Mt2A EszE 0ɓ:\?G-{Jb$ez> $ڧ-h"_C|{L *OVS!&8ń@B]Y#D D-.aB`F)JF΄$;E6%6WB3<$EF4UPOY/%R=u#mr5Ozl SUr]UA .s.3Nn}h6B1k/D VKQM ד>UV Ӄ%ƞv!8i͍8O8VLA?pˢڌ&'3–AZSmۭd,ߦ5tz zNWFKSn̲ea=,{[~W9&sˢmsfar2kn  Ҙտ jQ5'"̰Bto^;W@ǡꍖڱ{T acW"/7tWw/e#辫_.}1y͕MX2eTͲFHҫpB*WKk&{Pjn|#)}Kqw ݧҴ@u-^)|.UIrYvYhbX\C,XSd&hyF1Ij5r<)ꞏţgM11r͚gi^&jB.iY$x]@fu%DVX9ŵWKV(˓,:wս w:5zԸa6Erps_V6wG瘱^^mދp2n+&v]*|RycΗ~s㙭\g'Fqs3|և`U$dmu \o=x]ߏ*YbC{ǧbR;3^^_5m0_`:\581[ oDbݴU]rW݇{kv}Ƈ ˋ!SKQ֍"Hy\z4=t?da}X5{ZwXvowSh^sb=9h>(^5{( GNinC8/OG(G\/`oޞ$Vg<>oie`mmc3@ny*ȆNzLPm( pC*hLLKJ @G0ELEMM p{ԏ o ! ظGj0BĐwpoC˒ l."*ʯ Kp;o O2$yȰ*2( ěZ` G& mT'd M7B=E*Sno'Oieq068tQ0XY$J?QNeF#"6碢 h^Ne;.{DV/S*1sZq1( uΣ aΣ q}zQҊBh'00zh"b+#99/ PbŜ䔪 ?(q2JN@ 0"xQ mQ.a)P*7=q?ߤ<7&E",-R2d D24Rro.G!m1rrG19ss QfKfQ&@. {fkXqb0$,++:_;#"b @"F`;A S^k6#P F !3.dn!S4%0#35w"q"0&ssn% l;@lj@B)Bŀr)sh(47Whv4qc-&F 1D# F 8}-4"1>Fq0+̖~6 Vh6 VnU nBmSfSgR>(rѪ(wqQqq,hKVۖb/nzFs?]tp4gXTuF7u{vJdP5[DyawnRi]"HDzoEn.y \@y z-=h5auB USL .#| e|/s-hk׺Rw0UzTY闛~NgVet-&v2 m3x&$F"XTǃ&}}Gʝ6h{!w0 uXP;nϵuxR&VR_>2 /lMb 2Ws%RuCt|5棔Lg`uSWg[FBJm+"Ē=xb옓1@R&xKy Mu禙e"F(=b *8c!YIҐۄA8L'M׹pYyDו]4mi4Xd$!,n:EҊdPLg7Z3g NAG! 䥥'1"|)72EJ1v9Y( w[A/ Kc\ª5Xn"S2uz%&RM:2;(o+W`TpYЄ* }Aˡe kAXM!97gÕuo+c8"zQ؍ wv dlsu;*wGla[YZqO:" 9{QŜц :c ȹey"o>;!z^q%5{8d{׽Wf?M `%RJ}?D]; 앥<(:\39\@[o8S SYMkIo1c{"P©ur\'^\f5+V<E|@dm?:Ź^\_ʣe)9ytor\Ǚ$Au7qk/ħK-=XwSZ["H:&=M= νcCE\)u"$D>#;#GG=SoC~yzG##%&aP2=_Dͤ"+'ں-Wy>O.}\!<&9/@7.=J_9"]m&#[];c;=pl78=v?ހ1{~NhHŜ񿺺[ee gLŸk^i?P I"'¾=~!,Z"?߯A?SO+8""iq<IP# #tdUSmO:ay #8Y">`$c+<0B `A+&\ @,zB 2  Axī&(pСD=4R*- X 5P3(`0K)E*dibJ={ 4|hNZM R턱(HTB](0Ԧ=}W(M Ɲ+r { :4h>v@V| !r^ݴu@s1wL7 yc1 C 3KeK0Iۻ?ڣi{:w]+<~hWhj6ɆWH\J5KMHAfK/t!wLeS5fww^M#"Hc|6Gf Dδm4QoSx `ȵ}bDuKp]IpmGP%)b|Fd6RgJމh8cU5rD~e['k@veeQRJeegB@ {aKY(0h *՞Y'@@kQ=m &iq-eUFMhjщX Yvbɾ Nj>lub_.h\FXD6Gqe az:V!ɪ'7ifo:*+kou鱼jMd/_ouebq0/u_|85+BhSO+n=@b2.-t?.؆k,f>J3_}q@ݨǟyHէr.~*to^_gs2v囋JTiSYҡ͍c l<䕨3'5Qe}s[zҤ\ /Y|Wd(=WWzzn#29,|M:BemR+H2$\[kj(#7e(rKX"+ U򣛠?Kbֺ..lw;M- I642]~,V u5.{2h$-XV4]?-*@ͼs!cBG4~,lAOaldZ5&S2A@ªި$adK(<RHT/uZdsr# ,הјT)ȑ>e*H4/Y3UsvGB_`h'H2Evj'l$I bј7 ֵqR^08TsGp\_#-ȒvԩFQ09T'=U3[,J)UaZGGjSC LI%b9T_L ayhJiVЭN^EIZZ$i7 ` X`DMNָu+V CaD_)*b +gJS![LzrS< MPql?95MY#hګRf7Ytڟd.bc Xx}Ж 7{.q u2 &P~t-PmyT@hUI~.|f+WDɽu׀8\fο)OJϊIZTL%L eaJ!#zc` =sKM*bT!%w`7V RZ/P3lC*0r9֤$(d PЁ Px3ʤ`ҲjLcA,Rk]\lc @ 4.g8wmn21A V ئ/tUEW"R!fA^N֙4z5Խ}`d:<>Z5&J}GD[]0b;[N_WYmVYSS##A}U)ɞ7WՃ{7ݬ®/f&1qxOhwO֮&7u_N?ArNY9  ҞMp\L!"_k·/ ky3tucDпu@za5ٕjև^'5<=Ujݲl_َc9EθKZ3ObSn3Za|bjHP#Wyo\?.;[kN@پMA ߉6kOĦ<^0@|׋U2Vd'W-GX{G4J-ABUhI*gi(May0C_#aAϧwr|/FT!)$enDr&7v ! | fS|DA2y(Hki"x,}U!%A,oX|8!)I`38v;7cDyjB؁u\e0NaAQ7{qrM8lBҶlQ)~fZ2hAzf:DEw(Z(dkS'Y(`h_Y~v`ԡ 26P/Xz?؈(j&W,G(xU17`,G(Wha?`4Ai__ f}7rg_זㆱB@B! רPbV|̸4j~(6׈(>}$OHxh_ jU@?`H>(!yFҨb`5LRP'h[7ց%␇Ƹ`A r|iCIfr|R= t(I-ivx^]#0AH>R);J )#EH PR)t)HhecH& q X*2I+Q>g%y4T%r JwZу'l,t)vx# aV7ԑC}D`yȏLbiAA0mbyqZə3hYYPuZOQ 阫) 23-y!x5#ϙ YP(e00#yI\멍fX Z#:8rB Jjyz*KhX ):."ʞڡ**3:,J.Z0z4ʣ=*zR$jEʣ8F(6KMWZQC(5/ʤ1a*Z*ejgJkʦm:Ch8:)njU &:Jw?GA_j9z^Z`zza6:Bʧt,p e:ƥǨgja < IJ}j깩;`*{ڨ:+Ъy 90<`ȚZjϺQŚj ʚP8pkJZjh:TJZ[:Zڦ:ZԮAЯ Aw` {y c֚)ʭs:o/I{5*p;-Kjh]t;d(ji趀: ,;J\VvgkA۹2V[wknKyGSj9;űK] r L\+[Bl^|j C DjpLƀw@wǶbƛ+ {,q?a[l˻< /1LaZ+mljrD zĆēd}2 WlI.Lǣl[zL\̔|#{'$L쪪ά@l<˭lλ'ɗٜ,-L˳;moRcXLZ] @|uƖ <·L=-Ѝ/!\j|,*輥lͤl›l*6mL̨ BB80f2=<L QmE}ʛKA--i} k+ssv}#.Tf ->*,N ߲ )*]&Ijr+z2j;'޶= ﭻmG. ai#\Q.=.[\Rlu[iS9[zy M~P^rd&8 ;]& O^m/MN܄jt!.>I-se.=z^~qgPh~?AιC$An;4 ~ӞvaL,` .ēnNFf.q'V{bD$'jw^,ڼ-_DDgGqVmPp&g1 w_Đ>]3H >6z~ٱN3/_7ߠ^Ʀ>!WK䡎~\}*ZMSONK^O#'#Kj䯊תsULd~o#j'lK];4RJ2^]Z |Kg_}ŕr~9He#O=ς_߶N/9ߝĿꇏr x.@А?\c~:2/o$XA `Ȑ+ Â5nG!E$YI)U" PJ1 6,@9u)A;s6th!D8. eSQNKYn#DYiծEk VqΥ+, ; Uj_uk=ĉثA8V"EǙ5o\pÝ?*X4U@R>:тEeϦ-3е2ySԒ+,ɕ/z{`nI0]fwM:QboKoH_LOc:"3y#(=rȺ+,-B;MAۯ1­.4 KtEoD3o*ҰF{ D&,?g:QT@VxrJeʧT܋ ^+K0J1L,E3ts<2ãwl;.7S# g:":2 tхo+!tSURCRZKONSS@RaŲTQVWE]N[]U\VOZ\'ݵ^B1-+i-d%1Tm)@EU\x+E? ~zT/}z `BX \@YzϺzj bp|׼x܂\;w@Xz^/Kg>54 =$-P`׺׭vMdm5d +wZ.tYЎ uP9nҶ3qZbE7@VKBE+1.M/ hfbdpD-1_lFHrNUAUcw ym? s{>Ƽkw@(_y\>;߭S=!_=[}/"^}}{_W^6A~ F:~_[nK a}xЗ~[Ο@}tT}0H9?.h7?l<]020/xA(?Cؾؾ(8A?k@A@U.u?3#쾖4A 4B2#ApB”r,B*L9B(1`6"4>{?\?(2.#t#B><8 ?\O2"#CD8k7K>@A6D|B LD Ķ0IÌsGT-(63GdA;.2FtB`|;<[| -E@AUl3ơc^LCYN$1?r4ECF=?nf4QdӧPJJ*UdQ k( dj ֪m[A˷_4JB>{4܅CKPodv.||Ϡp6Ú-cΡ%N:vyaͻwM5@Z%'FIFyo+~^Գkαaen2ї7i<+Xc}-x|]H7ƶQ18@I{FNwAWNa%_wxЉ2h^-:"\>)dN9V6H&dMEPF)%FM7 ( \vPg!e[zi`fݘPyR)&ҩyp橤;R^wIy%.'hl>h|*ve䤞: $*"J뭸RCvf**ld,'njl=ٴvJf$zkTrwɞ.,J[ڔB)1+Kj0I/og`wn?w>&w 6:s>rж -cFtlJt?Z*NMVuZoqן}]bbSLvln-wHkwfvhnݗazwd~oxW8x?l}M` 9_y~WNӅ>km._J{ {;ULJ{?UE GCF!8Ԓ= B "`)ZqaʻŨ0=┺/'bb1OZSȝ7qOUL;.㸈GYɱ)t܎ 9C$Y$#H@2;*yKR''CI )i2ZLZWrC -{c[n "KF2&M/y*`KJ@0p,.l @#p`i 8MMo&|  @)P6 }DlC)P@ 8((䜩.hʧ,̩ IsE#;je1  r #יX{l*j"OWt/#EK b҄$4ih9sf8t$r3IS'u9fjUglS+,DjpQ}҂Iv~\}z8(*!e]7!?h~H'`6WV'!vy8 Xa'DPcAFdg`dj\f`G\V~BVyAcRXv *ht38HlXgxG(Anv CV2K6vz(QX!y_m!x }TƋ&y{1vX$Y% qeNe^ODzqQXq9UhO!0@lؑ}QohV"k6y֨: q~hJx5*)ȓ8+nȀ6Rɖx0vZ8|Տ" J * }iyOK_5aAHXUfI%1O붆pxE9 Hkhd}9XAc()yؕ7ci)( cqX?X~Up5v`ETqȘyw3XU[ ij2I֕u9ǑYџ 1E"Y6yٜhX|+AW޹n1@CA=ɁC" z: Z gTjFaI~gș~q١*{$ !fni}&+CK>FM8]vH*!vnA-UvXʝɷ?Yu)z isB3ңIU5_kQU !EZ"Q?M x zg0bB8*sU)hxn.[ʙ@q5SZ`VDZy<Ȭ/A7AAB]bZ[V!{ϖ#X Xhꗸ= ۣ RX-A*D%媊lU#gbhXd9'%5znOkfOWUc3zCoZXlų gv|ENj92OVZ&zQ:&RYY p1z4 l6DV=Lģ 4s@:cP#8ZxT:kq#˧=^K)AVvL2)p+s綳g[eq$I:Jb.:Y "f ȶ؃Y+kQ:&k2z7ɲnsJ J#NBLRu[dy4͛r˫sLm"Labn: wcCa8qū9?+Nvj=xv}QZ}y;U*3Cw@_Pо_rkafD|1!%~ \(,|vӠ Z(zß{AɻFh7q&Hh/N3Uc=`f,XhTԑdldxl3*3jp xKˏ<SvLy[|JK<q{L ^2Qp7,wa/w=2@m$7& +waG;h,act6FxLQ jm+buG* F՘57A3 W)ϭ\̋́AN#HK +?5Ȼ*ah)UZڬh0E,Cl4YPvy H`קg'++AAGy׬o {$%:(M&,l'8w`ZG: /aG4I¶6$Qo}6=",V mo*M8x`񐦉sh֥qT m%Mt h7^sEݯHP}h܎q ֻ{-mu (.-v+aJk< eMb\{si1ܜV` "ɟ:R4v!>auLRsm~- \&QH&;Ղ2өR`&BWnҕm../xvZZAXB8}F[ ]j9S.^O]9~Mܨk6Ϯ.˜m75}r1>u4ޮ_{`&i8.LjeTV=Rm#q8=g]V2|=|un6am{{>~nZ]ZT姷G.w[]3qȶ2>G}}aMfTj&%o:sa.Urzj|NϹN>sM;ޥ'K+'ǂ7"!ݳ®!2^?. !o.h{TnΖ MQ7%("1>*i\LN .u\z?v}oމ8ާ^/z+R?{@ykd? io %7Q_ϳ] @( ;@ -Ph x@QE%MDRey2F#>zQL\YJ6]bITRM>J2cIQ^@IPdUXxCWS^|q"Eź퉹l%{HcE Bߞ+C㿏M-ЕMZx5F-Z+WA-vY@ZͩWb(@DڕO[@ ^Xcv-ⅱmRPR-l$/Y%l_i⒅I ڬ׎=@8"ЂAB zSȸ CRhCE<)?*$B_a$ `ad-Li|/ w!,,0Ir9j*.NɼN /Kti|q!L*׌ؔokХTBۭ:@9L#zI8RQA̴1R:KtRSms3Sᓳ5ZhW 3־ KH+%FISbi)4gF!lC4 ֗c[R[Z"hVZ(e};VI*8!r&wHL[0!zZ.O<'. \G#wOfu7Q~]enY@-g]XԲEO95 ᕲR/F:HN,,U6M6JIaQ+XD}vE7פI`UZ;,֝3x?A?L1SQhޢ]5sPE-G/z!ʻңA%PZ%ynez3RGmJpꈢ G>lG]x8"=淪ad3}.i`(.P% \ȹU0`;lDYc"Jޚ]fs*, 67@Lb64] {DC/qEz)1VabX/E(J2=-c锺||D}lutE|(pIl ERh((*Er!8@J*Ed 8q}%B *h0m۔ CF&,u8jh@%K!!ppR\fW*&"- 'l1)p|&9w =rdIP(Rfrke4>UⰑ; L #9lys!1.v>V$j7"IÊrb$&w^6$& s^I"VOCa* +GRIdjz1^dU`VҦCR;"=yO Mm+:jё]K^:V'nGtШRD4ςϏ* Y.Xz 4KgYj] 'v dkXÞal& gJC{=(JcKٶNe9MStᆭ{ľ Y>!ݨ"!D>`F~)mXRQ!#yܗxz#*X"zYG$۴ /|h @W5 |@VBޓ1J>xuzPWz/YUTr%_:jr 0F1AU. %ɾfZr7>Wf@%Y*)1NkXKρ> [T 9r(ɭ1O>Qn~? e΢8]^({K]E0j.v;tlߗL5M28>@o<ΑP_҉TIeo&bfo0} <>eH;15/xj˓91?ĨUj(?"@C ?6A?yAƓ@.Z6 t \$+1CZ|C.)?Xjk B(B{?p ,@tkaܩ©+:99"A4 ?R<)!3CeL8Q x*DE"ڸL\ ʑnĻ&(;&<?#Gĸꦡ u4(EɋzTVdb~8֌Wʧ̻]@ ZWR-ZSdALryxOZxZx6S K7u< u҆m_ZI0f.YvLZ󞧭_NP? vqsjOn6q3/1$5PǍe3i"F{r" x?IsĒ7$n`hC4j2z+#Id  $SP ^p?}WIiЪR:DTA8'RT$1lY*ZN,!1R` )[=H3%RМZS\Zב0 j4(P&mma YtYs¡ĖI-}QԃɴH`\6XVX pퟤ4XƯox}q:˺eEJ*fiۘ-(nkE՜6]e;MAR7EpV!eX5j~\aXyu8;f.D"EIb;S.!t)Pݒu\mCtՍ"nL9"7 \1FdӌH',}0)W:Fz4=Z.v5{e|VF'T".Q7Qʄ576[pͱS39'ytpl_xT/͐< PcBB Hb+dwWlvL΅F&Dٍ"K儠:>_]|]m ם5Im!&OXKuzj6}l`1"Y]}q ޵v]nY/q (8AttNt+hlSYН4_ڬ&Rla$n9N2=RJ쁉%VxH Da:TdP.$}^ oks_lB"8B5F30[a 8!iaΓWʝߘg\ M#=U -$w$CA|nG/B-3<绢kku \9LO~+'&wu-[/C.^8K*靣~'νgEGw)" rrO{<8Cby%՚/ܴɁ~^GW`x\敄͝>\a= uI~TS _C5DD%ޕ-אĠ%B!%()ߎuBۛLŠZw>+AE$]*WB  f  J Y:m>H\ Haa]a8aB 6KPH!c`!ŽiiPYAbH(߮}U&.@LC-Kz |abIĞ ޢQ ` *`DiYbЮl $0>\Iq-(a "tM=67 . }7~8\-S/:I`@ Ņϕ!: zc`# ZJ:pُ "˱mdC RD!y=VZH*ILIdJbA*{ +f%$-dHB5 IR`^P]^ |瑞I !֡HLASPMZC" )Y:E#"I2弜 #Za˕I=>㯌4ޜaVB^vabZbF0DĮ bdAe`ĝO!EɄ hDf#ۄ5R:ΠW~X߽SkTZV["[;F0U9M]dp:Ig6U^DUږXrk\lIXx$viFa3'HfgJ-P(ʅ~XrtWbMBzK,:εdho.Jz~fzRfip'`fh&iXfˊ*ε5"xJ`yDbA{Q~]DIΓ!gפ$ ju*d1v#F߂Fjd(' h<TߙȺ_׈f~W5ʩ"&X*^:@Y'ZdN&Izv䎮.jhjI0[:'K[~FˑK؉a|2cD(:j#}b꾀VzJ)vmyZ^R끛? ȔRcpv,i jIī&=*Mv\d9^kJVt:F̫N+J++Mf$(m ObjQ legXZ,C h*r6 HTK,+4%{OT,x`VV)F~EtFiߨZF¬Z:hm(Ȟ,ξ_Z]‚FbD:hЖ*J䢂N %RLmf2mbђ6'lt^ 26D.r*: vЖDX:FǍ*(-jfˤlJ4ܪ)%ߊvkI`לJ$#񒖌jm)mrJhH6و6oClkn.N:ƒ iJsmD}mxoJt@|ƒƖ jlo:*o`hənzЀBL$ɒ@$I0IYēl2ުE0-*t& ͻ}uj'T- k *Ҭ 51E d9JD1QoxnWwլ-ZvNv#; Q(h''Jg6.9ˢ $׹$~b4(bfcݠo{x rzsW%aa0k3C/EF %`vfeyw|i?I84yt94:d/Ov7څpʍքgM[s; EBhCM"vhǎ[JڕQ7FGSHǻH5sa;F9bOdS:cX#{y[I |hzaVFh3w|fGu<]yCDxf`NoWoˇg5ey9ğwt|(}?C颳+rd7Ñe3g#,e:¿:ӷ/f[%c k{sFd=y{3O}RϛW sTI&.>7~B DE|c qb~-F|_oã@@`AA0`8bE@$pPb A'4R`7|)QANbQG^| 1}Z<рӈ<=^\1BI;&\jRgѦU @@EkU@/ ɧ"^&0UC}jTIoWfp6kbآ'Y@ŠX#{ܫ w\m12s=g-ut)!|kKϩ\C5(ʽg2rSoSIS%gmx0[Y?ƍ}=kEzbgP]0'bƅ7~Nd 4%/r0W*$i{'Q솫L}{SSd<}F? R?N\ʐG`aY9,DNyK`0ƴI>m0Basdŵ/L pcYHGXqO Kܞ9/{O$:8;Mnb ˤFb3(^*r\WTY)IyG6)cNlWK܊ $rRfq$5i @14,-mS3|2rXm[S( .gy Maǜ(Z J*. Xpk4P+car6XJ%_BfAaUDNXU<|þe1r,d[TY.\27gd: ˞@\blas\-R$9e$`fDȈT\KϘ S-T=J2ߦz%J=CNΠNmV~Щ mWX[akjWjcNo 5.^<%9ҼgV}2hn7XV)L~%ery;3"˦6Ifѷ7^i}I𙵁;/s%k4.s,t!p1#>evNQWu4GmCߗjjr(6eQɍbΝb'՝W:uM8mV;˫c~TeCM&^Y{/NhV+] Sn[ZsR9\nQVzK6[ywF{* {KdjJW/,""Ma<`)Nl p_H.3ګf,O*L J/o&OI~.̯tدڈcb04jN7e> : tNE~6 t@i;~Qr=epcoNT( SO3B0/% 'PS\1P >b@R`S;7Qxb>q@;PB*4N*-X )|JLti sNQ=|?w"@ d,XE $ .a< 4C !O vnT62Li)M.,N%KRlhq%Q! -2#B(2P 21)?rq1K}I XR o,m-h-S+)\F<PnQK*-j S 6%@)5f$-O0=;<$, t9%:Z=S.S6/])4;s$k;ΐ)8DCH@S?rH 4 ,5s05בp 6+tG#,P8+ 3LHFD8."1MtB1)KG0*B7!%H#3!M+aB?ǑIbRe T4OUimpz9U۔<L͔2 &KZMpqTg\U.1S#X95 d#'Z$G)ԑ&0؃be!{h*bʤVPR3б)GB4F>OKYmR'U#x8h.nTr\;Y~.>H)J4A5ɰY7% ;4$cµ[pM@?m+:%B6(a[Ju0U^bς^h beC͕B* VF\PudW d4NNHQc/P]kf;BqYKuU5V֯@bU VVdeFEX6-h1-bas >$NflckBgg0:g5n]bU"['"HMi)j^fO9U;qoBsdg|o `D! {#}}eS4oa}8g;wׁK%Y)i X[k (T$`#6s=&D7Rqt%970B3Mr xM"XcS#zh`S(MRY7$^Ȉ_|%h8drBecB"EyA.OknRz،cYƒ *;ʒ3ĉKvnh% W[x40ΘB͖]XfOxrl29LBBv[piy9?Y럏Sbv/dKVG2hglK$x9r_o Ftv 9O3Z~2FX v%R`d!T u@g'{%:P&toZ w90.& Wuo{Ms^~$m3redTD??.*8@q_b 80B@Z07P2ȑ$KDI$:fM =@\~Xf"[%g֜2; ʋtPX O칱cš[.f N+T ՜HJ엱B"{.8ċGϗ 0hP ɴk(uˏ7Hۅ~WQjlK\bnnҔO`q-`)=6V FEUe!`߅WZZUuvh^|_Y*IU iQFa.$dM.bm؍R6AZAMIN__i}^~eҁR6F9 G藊B. 5i!t (/V~ѣAj2~GAZ~cGHՄL:dHjکƎhB a 54CM(p*-&ZTy%> 9gR;.+AIe7] =m,BlwS# ha)$~Q}{g']O/+dTRE_To e= Bjy\RA=+dTDRKtG{3gEx9Ұ =1ɴ$ALuVkm H[hsf~ 5u]ڗc~½Q-E7&}ЪlvbltVJ*/+dͦ#FL 軡+Pp+^>zon]R_T~-اiv_Orן~dpYc;M,^JT+L;p@-6Ҹ^-(/Sw)"Px$2$ab%V@aL $?|Y@>8<1Nw69*y #0df300Zʻh/Ĺàg8Hjp58A@:8Y a+\1!b X Oe ePʑņ CXvG@Ō\@xI"n20$@/f H@rmZ &_\&Ĩ!AR9ojcaE=`kHN)^,w5@/訂` kP=6i"n vN1.4&XmF4!(/"03ٙe<+ɩ%s)@,1 !^TY)fq Q(D?:vNEGqB&f9%E &%gDHAKcӘOz HDHXuԃjkyjWҞ 0$k^iVULڔbSBODG L (4pYC&r1 @2YH2+5 ԉv&qhK(UaȄǢĥt&6W{rX%Rqձ#Sfslc:ͭ2 ku b w q\)؍ dby򲐯|Q{M?V.El,eK/%t9ڵ&~Ep 'Έ=$z;a.'&HQl?k+Cb&nBKW!/bђ޶.jJ-He˖96-"eo)Y 契!G]Aa-9UǶ$wMn91?f1y[3D-E/,4  hĊXCcX;ʭ38ZZ˹;š.z1Uˈˌk];*AeYKkͻY+MkΉhp(Z+  #+){𛔴[k>ɿȬXyh *Jbk껌,wH+#̆J/[ܘlC˱'*s 3̫5K:<>@l;.Lv\ԪĔ9 3Zx;EYۋ{cLF|+?"~ $jYwGnR0!wgM^ZI_r ZjYe=T\慊ݗ-u35^[=oȱGk&8>m. .n)5~6WYN=BWL~4WN>q ᖎ 9>,^*CޔϞ,.Q[>Ǯʣ 󼓞Nӎƪ]n,n:vtn s,)A O=9${s /ѾOOdk;^_9J.D,:I!_(qr^;D7ok /6?:.AO^Ҋ^DTa+K>^驽9/s?ac˪~|6pGުdyFWٲvY+v:8O֗ߥ:רFxqZOg*Ě{mĆB6gf&]x-o;wծ>l#U>14%1%Lܣٮ?W]÷}btR_vZ^8q"ݳ㽢MG.ᛗx쎟l7_^˝>YǷ_E;}'oNOtGc}G~2Oh#`E7tt ؼ Gzɛ}@E08ǣsA Nyܔ7 Pu# ǫo8)TX(Ov1T kc|C5[ 'tD$M䡠xzK"H>-rrl1aU/Zm ~f1W-$P Zpwc 8b/|s|HP<&6 %& U;"ȧ$IdR Pj2Aoe ';)쁒m"c){J` k("$2vKrԥ($,(L\` f֊4%*Koz2Ė(H%t%I@i\<55D3,c) C:׉$p4`khGWF%Mo21i2Rl2-EKa,FMS,  z_u1B%j.-u5E"EP0uJ6ɮ"5aX*JT+SPZۺի:VI#ײ~[BVIkp*%X5V U0FI}m `eRI,g3{@%-RM{ZԦVemk]ZV!D{|r+FCV~#t{7!E >7MeEKi] wsFh80o`2f}/?k7آ˭b[ { +\! }`E^vK^l8AL8P آ,Jk+!Db;bvbYQ2BR|49MW /13b+&PrL. =fv[`ڝ/Be24JqL b.k Ί{\ø0x⚌ }%8yHswGCeG#;tB8z5K ehZ[E(% 9k.?҇!9'ĪH{S}<ڕx4C_}cUyn3q:=d c6hY6.nu="ظ\SD HHJǮ2^@s|ir@!,{22U~Tn ,,"VVghJ~ O Q P P''m Q~gdIIyQn t5U665Px H,,++n Sm SPy JfH4eT'Tt@x@UH++**x y} n ߛtI~ n TUT| --H4UUUIy ~m } H~ |++*&&&&ڎm ߛHtJUx U}Hڡ%%t}| '0ߛ}R| 0~PJ~Pt|}Sˉx tx &,~m y {'˚y ߛڡo ʉژ/J&~ U@R} ߿n'ڗkseؠWn'՟d w#Αk sڂ]y sey w ˚\y Β/߃Սd EIx ՞t߱m&dʙԌHA Ç#JHŋ3jȱǏ CIɓ*d˗0cʜI͛8s*'Th, 5RӧPJJթ;LH#=Q-j 0]j.˷߿2kHuP) @Z +-d:]xϠC  a!uuƝEGt%Z %^"wf dlIe8t'xf}i('xxE&ࢄ6!()}JYhv|Fi8|6yjƷjjHު뮼J+zn)gjdv*,_Zj"а-dنUy$yjIΨOIK0Vٵ|egI0 sEsq ,ǼM<",&Y,D$fϬE5v39,tD=3(-sѡ}cJ4hNu!OY-^uZ{5^qؘbf_vp+rm7tO 0}oln aᆋ_{x>WNNyo~lu}`J[+z껮~U [E{^k/.S`ƇT|LOA%{Mhs~S^F_Y00o>b[My.>Do>_3G1@@@]W : kP{WS>!c^ٯ+ 1U(}^qXw¨~tGA8#-[xq{h'1BI dƧ1>j\㝼H2jrYeǗ0jS؞8I !cC.)9Ydw$A'%+='$'tɛR;%JVʓ%XYSV'<-ibK2Lz_3C” 1}cc*(1YfoLUXXvHK"7M..K | ; qTV@'4?NJd8 j Z|J+8 < :YdIi ii=az iBC:0E Qft;$&PDU8TUUYnzsIY tJtU]קmp:0 6(MkE+ĮtE=c+u x> (Yt1m@NuqmW3"[ͪh6JR6=Ja ަ'2*N+նPnNY&l +S}aܕPmV`K<[/  nDp_^ JԶ{@_h 0-,i>nu=UelB`b7A7=r +njc vD\czɷ%u GaX nP^̍ȓ{ )k8v%MuԎ8i?U feVg5S!nr lCݶ :ਞC&gDhϔ!{1t qt Gg&HhA|@N( gi.ToH,55 k9g$ӓ>OӹJTI T3Z$oMkMv3t5> n#JA,! ?,}~ɩyێȿ9F8bݑdޏVxq@ =4-Ipl*]Qgg_N/.LLn{kιv,@*o[6A~O?kH:Ϳ2JH RĞ<όY8ks=dP]%ObWuAvwlݟ4Y̮ d1p"Dyv׮ ۖn{%IB3 ЃMC}mglm-wH'7$mJ>š'AL_jρ'r U7d.x-F8Lj͛0CnoL\iHh燻A}$lgssr&u#r7y5\r|WmUv7{S7l˗rg4tQ5p}hypfg!qT'R%ShOu{XCeaisUB-1jGgzuтIvX'})!'Pzb'!&f9VDH0DŽQPx/|G'?MÅGyPjEG_=xp.wo8i-g{MqO|uG&A\GlXZRڅQu5fUf=xѥ WZ`[u(nwL)0wEuh8Ն] TwXR˕JnӅ#ч yqnwxNvpAHno)hЁS\a !mw Y`AkT!yR9FU(>Pl (!W"Nd%ڥ 8d/dUr=qq :HHW) WAԍ[cI֐d!rX@XՃ;ѓՑq^Y"ೌPiXŔQ/n|1ٕDVڥegi%zEh_jM!_S )ct}I^nTz\L^)6`Ie!|זqI3&БY >HXᄨُ<njWԘYlZNjI41rיᖠe!cc2%Q[)A툅v)!9䝜r qALPjiG7yss!]ٔRvSVK1|ꆝ (kR@٣==3à1 a\WW7쉜1^h%Z 9#٢&qFU>?>>?FD?ߙN*PBry8Vbe1Y:W.Oyי&yB!"CGʤ_@my&'Q"W᜖AOYdpPZ2$^@C8vVK Uc1媴)^nx٫uب8e`QIq)ݪmAqA΁$`ªՋAA䊞zێRjf $ZѩUƢTiDi{1Ĕ&{|+geXWGf8:/XJ\, Q^Z11&۩$xkC`tyĺ:y&CV#Jծ {}K !Z;#jiBG~/-5 U;*Em=T4iP!SA?Ku$Ȇծ9,Kv;Q!-QSkUk*-`Kn1Q5\O(:u$ _ض=+1ݳ*ˊ`F`kcfƦuԶ uKu!{$ĸR*uAhTQR[ExRytJ325)k6UB[#QCԛpźh|k&ܲ+9֒KIT4o+WΛ źy$612Y-`zZ= BGkO{$Q u;/Rz) `ivRFq4Z~ ֓K|$U:Ec{l!}1*6L53 R!3,8oG Q3<ҴK R_;,AYWg*1aV\j\iCzmo|}̰}̑K.m1!z` "΍żymɲK{Tʦ,\|3L9Z4*17ac뱽1obx\A5T ,Z'+-8 x(!쪜, u>]U u alt6a\q3aZ:ZegӬuů4!Nc]='ōCKŊN a͍ڟ- #v~I}eq_ o=y^Sq^1$N0ifO~v-l^.Jm tR*H92`/e5ibma !LpG~\׮^ ׮oܞY2q;GNR-$U I~9Y{aR!XwÅI.'=G4cCE;.|ĝ%M^W:acd[>Mz9xo*~>K+-X >qֽ7A35ۻaξhlg[nBN:-ș w>J?Qx]e V-/o cM_f"3_^ʯX@@(`P@ `( @ -:ĘQƌ&D,`ņ( @DFZl@' H8ڤ&=}rDTҁ%A#У  ͪW~p!W:$ڕZmݾK(ʸu=X$"J)-,LJ~(Dž2,:3NC2C2ɡ"N3/kLS3LK*S%Fct-t;?AU*t4r#\T]KK4]Cn"KescJl$3O9SաAmKX Mj,ZWU(Fpx[yu^$$j\Hp1 i R1Hס[U}n\bDߊOF^IʂNͬ]aɥkUmV % /hk*2~&c1_݅7'$7:uV\V)e_Xff6#ows.(`]s/"Wܫ%ʓRlv-_"bcf1 Pv̢ >mXOU׭VK^=r!3KJo.5b^XV\}[2 Oz-u7k㩳_Q~oG_7{)nĮsvRw)}j?rۃݸtIN<7{9G;])N3z@@mp7\"? j[4F88}_>(O!z+~VP M/LQ "*|F~b$FpSG%1xHC(=^DӬ>mz+fx0D!a<=;.|RZZLr3JawGQ[13A(SnC^H=FJ!&2elVCLPCvYJCJ\*%BU-LLѰYFG U(YI=zJ䘻!&\3^bRc5K;/.d28A K[kKd)8FmvÌǰ$&<m^(쀩H\7 HjRD,74T_ H}rETFh%*T<'Y'=Ș͂ i15hZS(4QZDL2}B5B }p!MteFP-hhF4!*Նf_8I>iݐFE+zDPAZL5AfV{6IX])u+Aňm˞'åHת) (?ڢҢmyd}žK$R@2H>YoQ촯Q[#q,7%N.DiH:|Yn5?.y^` ;Av]v>9n/^WH2[}fu{fDkr|csNkܟӠɩC3{Ì{*㻰YR:3|37`?k9Qt˭ y9 9sl(þ`4r$A=ޛ?CT@A|7As&,3. 02>;! A8x;,~,BkBk=(B4T5<8R<1{sySx@MA}#c ̏j@38F-$4!.LK)-+T#ٸh:¶C7E!0~EV <;# (\?-LC 73GA#>hiܲ݃>kt8ҒnAeû_dCB-Pѐ<0IȀ1NɋӷPJ?,RЁ0ʋ"Ё¾RSϵ J4(2E RV2A|M θN"Jpʖx;̄0 MS]QERjҷ9qX`G`ɸRJ&m@TYTyN C`C/2 VRJd DI M5@\_4ie`9D-Ȍ-͉.EfUWo=;Fmԏo LSPҪU +pMp1MyTgU ҕB;PKSՈ`$R?Z|O| 8X׻K6؁S >-Vd YUubH1mͶ>NhXe1<d]MMMY ɋPEXf*ՙ\|ŝdٺPMؤ | ( L,ۧ]NW /UY1iVJ ۺ`ɤQULuI)QMQ\:ڒ"[sH\V/W\J<H= \FUA݌e}[\}E9nM^]]!+ueSE3w=iK\UYmBMUB +\YL^(ѕ׍Pݥ*8_8Z[Ǔ ΀^^YY:Pxv{klEV``>=YO$x8`S) Nߥ tE 4^  |TvP`) MbҰߕ9=4'\bNc'Xqz8{ֱ> ש@M2&=5v #c L xb IFadZD~  ί'2>cIcQLfp'aOZZ= @K 1 -E6c"~XF%]M~٘8^ )}T> BRFeEthyR5=jf]%oÍ9r60fz!慦HT>wW>dgۀ<~lF i+ ,v]?A C.! 4VVvx.%Xh7Db߉ΈJ+N6!j-RO 9)fU.(fw.XT*gJ9s vFSCi΍m .@`iOxcqۂ6jAv QjŮNs|JS.uj^f>$g iFǺ> efް lh1mㅬ2mJ #n |{ka'RԺ!j{#¢hOܡ.cNGn,<Ć@Ws3k}҉i6Htfo[of 8 @/{ 8 0ȃ,8>nF{y|qyn  ^'qQ#O%B(铨VXӃd l6)W ׶!pw8s`C!)0P_h=qp77ޡNx1ɳ/~,p 7︅M>s4w55)e >)_ p8uU3a耡&Hg5.6%8$?AN8e  t=_9us?G:_=sm'8[v׊_ψE?gbjX9g]jIsw8?kߕl'TWuTCԘsuTrﻍM)2_PdG_6ҲbY]]x)M %fxoq)TMs*) \'YSFjuSߥ}qv?v\yŨw{{f;A$xsb?zY/ 8g_ղwx׭Ms'x P' {>7}g52uP_OY #gq8jD _ߥiOR?< :0?)T~}QtR87V=k؏( „ !`@  Xh"#Ȑ"G,ijP@.OҬiud̑ 3&Њ7,@Ϡ!$ppP+(JBRjIk),Ћ](ஈLk둯CB+֤h {'S|rD1fHᘖG^K Q%(pjgߤjS D<Z'x5 |k/.\!i/dnON M&ߝ:51dWHK|| m!F.rǟI,xZXP^5_H,!@d ^xlLḦ́"G-H^DVHgEdɀ$<^5iy7'QMjI{uh/n9`NHxqљ?9h>y$HmD'qUp ٔ!l.5:ZRJ+Lhi91go^DZ%5_I$wJݕxғܚg:#ܕB\w)iil&M9"UF*I-IuV&zNvغhѻִ,"+A !V #\K MѦ5~"# z'&d'$Uf&#“di G`qv#i$M`yL}Mt,M47DVp94=q^D oT ! 9)=@*90h_Lb$tyjDe;;DSqqPkXf{3Rk4ņp؀njM7 Pox^:]%}z\T6E5Ղ]j5@G]I߻2%n5)g /J^ F{YxĮi\A֪QE2R-J:e ]vvyMa*Shr_J=0#&sͩpǬ3](0SFV+Ӗ9Sl:]]!VhnE¬/\4k<ڂ3sتxI"?fB}/^ߛ% ~dheJh E^v xEiѓ&u:˕LsYf}T'OYxg J|rM+Ƭ!Ι ;9'\Y)yݼD;9_ZrI SEDD͏XRVIT>F^bΠE,@F AB2&~U!-M&ϺL0e> 3%LfJe@%MD}]o "&Gg-&d"a fR~UW比LYnE< q:im)r(j$v^DjaiDjZ*8haq:Ij`!]:F):OfɖEj+x`&*~+iΞ~`%h*ҪҥJRfh( kp^^ zdd ^j#M(MXHih6 Yj9*0(:%c@h誯bj8lA,Fo&UbRIln&'GM祬H`pք'6l>_aMi6db~D^F38K[J-rbDdnWu-LHlIlQg砾fm}Pmެ*>mψ+*hLCini6眪w+P(jM-h m¸^X-omt~J|o,nnܪ:F&$wgD/VengnH,2:}2k󑨓%$C>&!ȾMk<(¯حlEdaJ,۸\l^fHd(Na^.eסh 61/]Zi&—^l#MʂnIZxA maRFBX(v4@lԀAgD K@J@g4s@%!0qdqiXJʡ"-˜vԥ'pM.l&y t g`F2PT Z[{$|x [<яJ?<=@8`A&TaC 0P0@0 @N4xq!C/Ai$p@1ڑ%Ÿ6 8ḮG[䱔GQWf8F\8` z0= y@ٵZ՛U@»{fQ"E+y(Pd5B`RY9N-Ml@i F= tFSǜIĪe/څWQ;! qBvߖ>e_ʩgJ8 5ۘ8TǮ]v^<<6(5FX` /0-::3^cOA N83PCh A"d=TPD;hQ,;â[m3q!P PS4Hn @O [6!(8 ۯC<`Mk+9D16-K (9*đlsSF`MF4nѴ #@#* "0'M+1[oL&<ĂԈQ+Mu5)RJ8aC}> QB)&S=i>[$H2`R4S,5;ҔuU>SO=hZ +\Lk=[VʍjH$Q1>6ၦBem+0\i[ vxcL"-8T+F]Snpi$V]A!C9GPrDžBqx8N)&T9L-evM \O@C쨶}}ZeĦV}^BY`>=Oe EV"{A, y,O3D?~Od;pWWvrΞ1&ۘmtR_vVo]tG5C 4-zYa3EuFö]G6m=WWuv|Hbr} inO*23&>QF8yy%W^;u)uumSXY0E@v)4>0}/a#_p\|WiA7/Mc^x2_NaۧJELz=XW`k.h@фeˍ@xB;\TraW8%rkd]5MK=ػKO1-3\w);ST5#b#C_BGWi ȶsO8ozYMr#$QH\D-y=<EU@ D{$X -1~d_4O\T->r/$`ǢKThXLv `Ɍ2Y6gv(+_@I]S\,o ι?E!%Y@HG?kَda t ̤s &ff8}B"HKnkEbN:n%TarDHfGRNm`X:$4n39YtMnrD)rNGke\RQw. 5hBLmb0pgr O%\ʡd 4NnM[- PŜE;kah rd!eu*aùUڮ kYǪTma3ZvkRԦ:Um9T&ಜKZ12Dw_BCETepݺYJfT#Kv(6̹:! >!Ee5>\WUw rP y޵nEV\IgT8le*nU1f6ZʦeZ Hx͛ل.]0Q@=E#/ఋR, cqp⮹xnØw:هXh7 :~7coH۳W|bSUԑ\t$]d]ʷXayfU}f*}&YvݗK 8Ce~@To{rt 4nn3F=Z6 6ϼ1afz3(a4 jњZl5A"wRh;+V2CڭOth{ নE $.'ɵn[ğ'Xwfj:Pk[x'$ ]DpZcJ60;Nv9U}CV*7xpaz9^ >ԙS6_@& X/-C74Al욂zXasZt^@ɏWjN 2R3di:ڸۻxX{/xrPOD[z9 a6哧'GQ]B5:>opoܼ?K/vm +y՟.ٶE]$Fr_]澐KIԢ}OH*;no teRdFpJ"[Npʨ&/K𫐶P&f EKߴ/Bb&//zgn/UܨEI!+B䬴ϖJ@mO¢o3Z+b|%&c< KPg@0G =MpvƖd }#{"HQi^Ї-#޲CŐQ9DF $E>$QR0$N*Sg1Q+'QRr!Lp=d֮bLETQ9 QS 1;q3;&q1* 1R41YG sG K)oC T14_1C[֮N/mr{~5 s\RTj 5Vb<9HzBN&Yh*va#,oF֗o=%T nk6.aB&br"24τO8{S<Zj^`J}xRxa#87 3WvQ4Jn7K]!#.KT|txs%n:a"(΃7 cT u˅׈PG!y C5BPCI w%n7'+"-}32]?PTP _"z+'s "|Af t&XJ6- drbf/*$4[`+d.8gcd*ٔ7,BYj/ŧ|sa}Xt<:8X-ҲYBPO"x9+vztT#<@֝%'ܠgᧆ --ڦaO{c"yjqO!Yy2k`qdFGm: s A I\q9:xҘJl:xu8I؎>٫2 B#]a99־y.Sz"u,vو<~t]%'d褹S4 MlyIZKlYVz&{*'̔ys Mr.د/Lœ8#met:ڭo{s;l# hEry!K3 _̎K"29/a̶ۤۨmۉ/?лc m''(ANKy!9OL8%9~8R2?<%pt((S%'ɍQF *bay6V.l' Xa14-m'uW+Mpw|!/Y^!B\!E dh墈:̑7<UM1 $W }<6E{Qo5]L9[,[Tb[ '^9:v04"]g %tfX/P>sd0ߢWշ(#\X.?o]RWDE5}LB^DcMiZ?χQ(2W*u!l޵>CE?!h%_b ` U->p\_lb1"+V48LѢȑ$K<2% 8Ѐ" \@a <)0'!xJ4jE6x6)$ 6^#_}s# Yۺ} Hڽ+U Ai uɭ Fb,]VhhMI0#ࠖ7vU 6d9w.9b'M 8q.FdfK3\uf]DHȠVGAsB_MG`CQy(т#ŦM% ALIVmQA]PiH$ cUKɶ4 I*iWc(9qee*U$teNqunJr I_A&h 'uE|MdgCV"'އbY晀EUB(Yތs5AL[[IEs1Z+FUhE\yUM*JlVTަ) xc1E+nyPxW F1bv"Dx$<mul$k=oYbd}*z>ؚ൩lT*9gy.&;o5LsJzUU )<1(}^%C8F%ϬR:2EZ峭_Doqlfl>1]b6pAeDkFVx"ko*Qi5=K/^.y+i350ҁw+ނT\&.ջў,y m^tRyzDC kYLҫ7]TLR㗿XIw.Y<3f/%г>5z9ؿMc#O@}!F07hjӃHc@,mQua{1daI.z&ZM=d/i:8m /`X#_g/o!@ab 5I7ę `J4Fc]?,jX`͋7BңSCJ%ajmQ'$(]Fvm=LlW$;@5l4$%+2B[2?Ǥz3$_ e4YRD/: NU^GJme-Q}1*EQr`mIvan)/Xd:*],ԧ'08%Tz]}A_zmJB Xw6[ K%*֋1*;q#ndC +5*)㋏ pY9NMT7͊lpa [mlEL ͣ+hhS4Ax9몸o2WcJJ)믩 ޏGn߱QmU+b \{$k()0Q$r?Sb[#[ĪA9.EK٦$v =re[m&iNNEb[X>=oԛzyᡣ)WgvcBWn(|F_@X柸q+{Y#Dߍ6e-C͑!+秨 n.:6G*HD'@kx{ҋtڢk}d# H6\|#h]V(BHj{] |J썐"w@Bj-9I,x|>U2Z]=|v#{~'Bf9D"z]2H:nM{{!ApJ_XGR g$g M~)A ZC1)s2?paqUGxz)2ZgCG&#PlPp~)jHP||[W.p1'p'}z)AYCf:';X[`S]yp]w"MJ׃4f}X$eNârqx~3 m?xhcJJXm|+\YA +`G~hFL@ixEYxHH(ȊAYd ֊㉨8XhChxH_X¨8xnscƈGXHXB6ˈ)H{爋@Ɉ?ȇȏX$)̿Cknǥ(pLm3 rKTB욇Bc e^d [YyqK9ȏBmoBnDN$6+\}۫J܉+S0+YLNޮ~>F)Ki'ikNmoNy9㘝N`>-.0N4P6ӛ6^BnvNxNz3Nޢ>`.ðM}Uۅ~lO.=cú|͓@)d* ;N3۞@nn>nĎ~=n"!n Ő.y B Zh>EOޭN.ݻo')Lk 䞪O6팦f$, .m 5OJ__)[L).5cqeogi?.npOز~xOn/~OQSL/]/zO,=W///)A*ӜܒN> /(l&?M/yj*_ɲX:oVN|N]Nz=bZY_K媏O),T}կmH>x; `D1f8p! 5nG!E\F#Ud˂f $OA%ZQG` B!f(QT LgɓSz%[֣U *PaSNfΥ[]k00!,>1"Ŋb.eaƑYj$m% 4r+gСE#mM *LQkţ: Yg64\K['^<) pZGg81qlEiWn]l"կgߞ% 2`/)ʀ@WptA?B" @*(rK P K4D&D MzLCUʭ.{ǠTȂ0H#qG$rJoJ#rlpK2$ʭT:lI֔sNĈN9C@ O@}NR@"<-5HA#3ByPKctC?QO'uԹ*525q1Ώ@ETZk%T,QN \I^eVb W)1M2/Al4$avZRYM-Ѝ7hw\E[m)\r\"-QE ^y^ pS&%~UVAVktXԆ/Nnac;8dgIV/JєxelŇSNCYAs6Zgݰ=pn>zjwF&zL-bvQ+v{ФO k|fm!$Dqc֦6W_Lf~.8Ɨ~l~pr҇BǿB2lf@FI\+!-/el9 @z|bϵ$rd%1Jdq)|cOwܨ rRs&69tcsM#Nw/qC6`)L<4BSrJiHBw5І M>:Qi39ATX0C:&ψ(UXE-ʚԴf'NOh\~i(Ok5Ps:R}=$6_BQT:ohXEγ3TYec@4jb4zZ{-]?2͕g̰z 2j*֑uc%XɎY V4ba6ld:Y΅6]ĝ)t싄[2FVMqx[(v^i-pk -)kۮ{&-ro["E)nvk]fr.jw1hfމw+Wm_X&p |`'x%?0D~ͰwA"ۅư};& ? qe4La!wV@  8C΂"sGΎTA' ,<Ѵ+DY,K@ 4Y16g ZQ|dJ`@ W;tM`hr1o@xDta6?끴mMh"6AG`Դ{F*uSآ3UF=M;:ӫNsL)seItmeʌM_3Ű',܊\:ld,ζOesߠ fθnz&,{#RV65P[8&ɋKT֒ap\Ki8Nks#%צmmؒLWD Vh 3:JL`|!,xx22֗xxxyxyvv++rr// mm^^iiggTTMMttQQqq55VVEE oo ee``BB<=<<OO::@@@  @x* Aŋ)PqC^t"S8"*S qC̘8pf ``Л $)PJS'1Djl (kbnܐ LI@߻'dUe߿w0 ae@La(:"(_!: lP!g.D4H#Z(1 !, I22U~Tn ,," KQtyzDD J~ O Q P P''m ~QdgIIn Qyt56U65Px H,,m ++Sn SPy feJH4't@yxT@++U**n H} TTtx | ߛn |T~ HUI4I} y --++UUU~m ~ RԘ*x ԧz HߛJPU}t&&UߛH&&qm | H}m ~'|%%x tq~| }SJtx Pߛt}dRߑs Ȕ`(ХN} &y dJw ~ ϥU@y n ϗk|Vߛm|Vo YMg d s U% oqwo |Nx d wz I| u ~ Әlx ߿tmlQ|Q Uxdko|QHA Ç#JHŋ3jȱǏ CIɃ 2<ɲ˗0cʜI͛q J!JF ɴӧPJJ#Q5RF7xeX@e .rjӲKA˷oURbd%Tp  5VB%%2Ux:̹g&,4ⵌ^x狒~s^״sMϟDi:DQjV;clʸôy.<ظb+?>yr2FϾT[~*Yh߀P!@HfW IF7ƔArTa!h"HHш.(cG)2[͘:#D5RDi$GAuL6de"LBiVSbi^鞖Tץב%Еyl֩7NvޚtgxJ h~ᙅE(&ڐ1*f:Z&z%jM 무*ǧ+KzfFȎbj^~^lJ4Â,f+E۶W׎nAVmU$k9jགwnmG,q_OlQUk0j|K6 2"KGSz2/D1w:36jͭld> 4oBItѡ[59NrB=ZCtdfm6ڴy#jknwhY=ލwz{Ʒ~e >c;8gxL>nY1NNCo^d~}~bIz_z>NNW%{P_q(Wќo|nupO7}c-fV~6oY_#amXV_[Pl01PC_nHyqJ$pJj Vם/%ڤS,Lr/l +W%Le{ji˪'d/{Oˑ.LpJ a4{˛-#~PQ6K0ISa < P4yG,CG<7gikV,)' Έ.G# 9zd4H~P51(U` TcaO\*ыT42RZ3O D()tHiө5 HR\*E4L QVd?YhV+VUGZ |%H^Gb(3Q)U2w޵!';O֊0 @f Z:qN> G%:B֖.m?;-`y!DSK+LyU̕r5_5+My!6 P] BļXnZ>25,Y`ʉ~ۥ h IѿuL8z$s>TTVQm}i*{//"$x^3;$fIfnu uS z &'"D[6@ŇҒ%/A{S\V3'F~:<] $ m[߸e%5!|!u<LG ![b`Dbt̷ugM~`{5~.aOw~ƃ!$;s U&tG#x]3xw_xT)_|ww8BzއlE!Ax{~3!#:BB&&v9V_Sm2)L1) \cgDh j`7=t?)* D* lWiV6a^'y|%WJ,,z8غ+d T1k{qЋY0 y!"PrPTE`X$k^JQ=ҩ1ۗB !p8T)!4Wd}Ϊg$m0̥") ͯ]ls~ 1،+FY/JVa}ٖ+π|1XOJ8w4 eﴚ!F*KZkR%tqSOr²hXޕMqu=}A̢@yUڋ]ݙk7ْYZ %^wvT1pǗ1q&M+حv, }j&N;{$- +ZW5=LU$ߴli T^Y; %r=DݶFR]|iA NN j2(.:>D>x<&گUKnQ;V^\eudqތ]C^.i%MjDMVY^&|^C XNKŽmsv~պ]-驛P*U,e^=%m&IMa3ёq΢yW-DsA_gV}r+ls(K҂#Ѝ^ۿ $^켔 ~f_A&ނ%:ˇVX5Uizk86k{5 R`u^%> hNUt",W,n4n/cOv88g!CuSPNĞ'g$|?ѧ5ʂȡpг!iK -mvSM:+0눢v[뽢؛BG\$IDQ'&˺#R2Ϊ 0B 2 5r HT"vJ` d"ᾔ$ :ⴔJ$%A1t8ˉ΁DHSIPO 6LKO1^T<93XhA/LrhW6mVZ>mQ"je| zʬ|d=5G[%!6{ZD-H>㵒5%cWmv[^U;_Q`샕+89[MF47h\[Uf?'i~;!ļ h-1|IUUJuCnw7Xjv}j%BYfJlH!xmKp&CQ 9D(zbVhd$I/,*e$A3') c~ѣw$*uS(P px ^ˎf4:[Q:FI7GոU X GÙq P+} TLa7^ϊ}2=z 1XVװpiiLӭڑojPֶ֙j??)~~rY\D:5.g Œ0편 B$ ?h/QMnx%؆-9(@E6hkXҺ@xYC;F$= Qi[!Jmb#o%FYnGk!/?Ց/Ɏ,Y)i,U)gTD9F%ev2Pns_}P3%9ʽzbVVHk}՘:A|m)ˊɘUI,XnZΙgG &YBkR*=[HGfnL^JZcavFʴSlyA!-0MQ&)SLfCTNP-)_z4tܦW!.&ġ~B삼ȚL}e5+<~(%=HB }vP7"v{X X![ oV~KVyVq;='R $2yew.H쒎&L#2fo{_`EƠ;&=P`@3m j8t? MSa@&֪^T'7q?ΑfY PGTVhMG MkamgЭ&>)﵇=0VF 'l/}`ԥ>RRpV,+vt=p y1[& o2wSڐ:rkq|H,=r.:7PG?$dcкA,Nnx^ڶy pBpdh3"t4MY.d9 hD=G8}brs0\sʃ@Kz=8B ; XVԣc#)ţ8@HC@; AՓ*{&24S#C];'&sZ?/ d:5R9@ ;HLC8>䃠A{ػCpS)44C7\89ÀKL:GX-CzESAU쿘HDE2#ϛJ,\C&?hɡ0TCSeB+B#Fsb w];@:۽s=AGS4v$B综W,H{ GH4%1DMs FkQA;t=$x vHx9 !>˂8NŁ$ț/CYIYCqbK+۾t9: | S"LM4u@.sl$@>TGYFWf Wty\Nt J7*JĒ4O\5lY te|GLC sb,˄Ǐč`!lK@|ˀ:Kn!T|yBIS=, )pKiZ:Z C98LXO΂ȿJ6/̎33ͱ{N}䈏Lkۋ(waHSH$̝8CI=JHEJaS@RSI9PUB)%BZĊ4=;C1? :Q7$ݓa&e#R:u" kd?>8} N  ETTl+]tfy$EIRd՝K(ݭ;ՉIBPF pefU$ͨh:J=^Ն o} +_hO uRĎT`Жc53X,}!I #U4WhdN N8Jwq Xj%EUq2tCיt ٲSL`DBMm֞YXOX{ ,Őeي:-YRSVM4u[ZxQyܛEbenٽZ/lJT%\审5Yعō (ٷUIXȘsCϫuWfXkK%̰~%ڢE[E]66dKݗMh^2 Kw]g5, 娖([^-ImBkOR(t^ݏ쀒>ٌ~۾i Z͆ߚ _8ߊѩ-]R }Ԅ)BQ DK=T? >4UZc=E6_'+C }XՈ(HYg5aoCњ9naarT>: 6; E^N0a ܾapM`%2 ߅8bIv] .*U5#W5E%_cNX(; bHYeL".Ud(+d)l] !f+k;)=mdh]^́kjX|n.lb=mo(Vm5 AEulDnl ifD9ezPPaM:9Ў,2݉&S4 ]6">nP20fb뙨sDm  &50*ĶNpɂ p&V=U`q 6HLo&?%WX5/*Rar0pUӎ rEp>o.- W1N&8"!h]?WTt=.'qfJt(o# No_3^q; YA7u :<7=_<xrfr u4Ltu!Nhr[w$scds )kxGp_c(f+moN]7^u6sCVǀut2)W F7Xo ,/w}7 ~m+3U|Zxgu/ѐ,҈qrByxW AwRUt |V'Znz^[ptxu|+SHwgObwWf2yFZyquW- {nWxBpw^oy]8K+F(v&scvGUAV''VX%xpUA_W(v&z9tڦaxt?Xtxp/z}GVu@1D.,Vzkt6k4iy%or]ovy:9 =jkBZWw㟉gwSk,h`!@rdb DqcǔTĀQc"f(桓*wYC0}Z/Q5XA4 #dlCEZ+bHa0\ 2-\Ԃ@P J8@Pg&\HiD1 /c|мB 1vĀnfv4na f3^ѹgarkS]8xAWHMݺBs8.[m?Uq7ZVrэgxIݷ}Jud@x1DI]WՆބ%^fj~.Xd囊g͸J (ЈgɘD t2 ^I6zLeVaĢxʣ &Oן8)X7u jzz)]᥈䩨Zv(V=9R~vԡJ*i+O_7hS,p)`GJ;B2vg_֓-A5NT nuWAUY oQ*[^f) (O&+*-6" Wj*Lu7&G_=gd*8WqGZ[ތo٧&u[A9mcӣe+hW ƒZ*9h޸L%^5Lv;Il 8GX#]P"Íto 6uVAnESHZS PPʴJ:ϗn),;;7A:*=:%>/Fхn8N\UlAg7:)ic* }WܱUn|[_c\`I'<iʼ߼HH?K( 8,9KC5YhfY%y9b`zSڱࢬ PoG AA$9Joʕ$  H+ o$Ojmd,89-ٳ[jN(e"M̲)%Lɑ%JL~`2w?C˃&(EI͏q UlY"v $8ɓr%{Lz]ғ~W$)O78 l@b@2iۦ:w'=ՉD1Y-Uid6jp*Kk23>¨p=55F5Sĩ&TpAMP+ǒCFA! ̓,YUcq=+@ͯr-rN"D*VP'T`]#B`O NREd $%ɨ&[=̹!x2c}\L_` $ad1-8JTT"Qz#QdAl$ZQ,K>:5e"yeHӰ$zE]^$\_ OnܠE$Y@YJ # b!^a؎"( 6f4 ul7FdxZX ["f.mkǍd#?Sp_UaVLYeS|elnn%[[fQe{}r&}p%Q5][_wRf\fO sЕ#}{g@~>AXEJd\ lAUi&FoDbhE1 b  śII 5؞ \[p٘#j(jڼB0m4wf0 ]:q`x@ nHX!k Kl^$8%)p 2hҎo4%ˆe Apr" @B1qn,'m(0So)JrcAjA1MHArDX䲶uq&aYr1&3\pH!(Yq\*'670.w©!"HY,r#g#fGi8vX^N:V(?PaTp+K+tGCì9s lq&hU0M3S1&-n(f㰼60 q$qIkpl/Ar" @: dV^s 1^2P ׳Jl/t44.4.'41ZKB`@O v 5Poʦ`wD{">wΘ>(xi. MJ*'4%q[BuaBۤ.PHUOpx2zoKKVvMvfhssʵ]r4[\\?G؎ksD 3V22x_)G %fOYov-|iV)@wPY~kjMNPn?I]%peh6Z!z{s{̢}4KeVasƑϘwW#8%xw{[z;4}̑8Oh8ܷkAښKOGn4]" Ow[NyHwTćOMOFn?dUxgcA:\&a^9)g;/ y7lFy쳔LoIKKa@~jx(v5{,ۤ~~S&cL:oWЃ!W尉h|sJ0{ԤtOjuwDUgpVaAL?[:eیzhx!ᰗzW|/{} &`D;iE&yۢc|Xyc>|`7E{JȻߜjn'='O338F9'?.=7Gv?̻Z${cHG'ynŤ?86);&{mzYWfz.I _=Qi)?;,67bvkչ=qtGgx]ዳD_P;?5G$pCe=:c?>"Y{gS1쀴{GJj}ϟk3ת5znh,/k頸g >'~,~#K.KSܑ qHt'WL>1j ׸'->p3 9pch2c6,+0 Y7L>&TӬ]LO7r!ZTʿ,RɌ-Sp+3@?j (12nEbDs=,WRt {S#; 4&7 m4&FI@3/H K 3MI)MSgZUS36Y;-6 TH3'1A$]t\;5tVF7B$ d WKi]je /5 zAwV m =Ϗ @su\{6 kڰ*aHKce-J[^ w#1(`kb#8TV_.8rbV&kJ,UГQc7,SN+VȪT]xƓhzlnлMRv: (xW)5CW!nFqs sV1'sw&'"{~ wC /8ܰ$_\V-(&89C6z׳tye-j#!#v+\ƙVBV>-Q7Z9#F)D$`9Lв.uK", 3H}&zWqJB)yҼ|7? q+גB @-qNp\BA{ !`C%a0٠NvܩO#= ) ʡ0'UU""1sZz`m6 $8MbbYD\Tdrw8 E~^\a\3Qxq~*eQai=tl!I"$7E*iDs@!w T+Jތ!@ ٸ v(CY2"@T"VR1<FH*D":gCR3Fy WtZqy%) Bȣmn:Mn*LiH,;[ǰQ9ҝxY1`3yb|JۿT7izˍf&R\\F H\vN^Agy6m,)+7ZO'1kMqƐvi3suo1Q#3Nz k,5̽ 1Xz2r[1;h&ֱ&ƛ.MDUzYK/<`kb=v|~ : 0;bŖś2(d3mgfYPr7-hEO*sm:t'Tmd;[4I2cg9+Shɨo9 ya%JMxwcIKEAwF*jw'mշvEzUmMt&+ JwcO?cki S/[zDI< d 9aE  +1,B;wědɾ)ٱ,N$8E ɹ\:OҬtXPj/8s$\zQ盡犿"S.hהݜU Z@Z>Fܶcc[ I;qt(LW8u?*5.nDhB6WW!qa>1D$:l/ ArdzyaKNXmY-ejՃ]fqQxI~488ȍj7jӘGLGNoNeægҜl7B&# 2Z; ƜAџ} ; DD 'Vf7'%\sqszכCḽ"] ]g}W3c{u"&0I! ~Iq}g׫/)9#mڃ6Nr)ossp#+;e>J^_=OVe; Z-O!pOHJ 4o|LF" .{:of@! 4x.c/QpNO'2pL(QJ FsTRp&־ohgjn|ZH) HtɊQv`gwI pg02 &vp# G'{LήHb@ @@!HC FQJ& 8< PݞA07 Q(BЎmP#@ˢn@z 1(ң,Hzypq,n"+StMpmJPgct2ĬZpI H  j 22,K[a y~ lpꎯz*0'PK(b⠱HTn Cg T$ m& -#"2!E1R'B (#a/ev/)̐w q<8%1`o!lC'! P" aCAr.א"$DkHv܆bR1^-2h`'!@!#r" /B52) /#+V|q5Abwh%[dh1IV6+S!8q-R"-.4" qzRSr5$*k5 Ĕ"g+aocղ,?ӒMP*V182.ְ3Ff;m f& S%4"2uPO0 ( \(L%DGK'Vke jA8EolRS50%F%#b" 4,6WU[j=?\lߤ(RrJǪPoT'dVoU@^U^7Ì ^cUytI?EMRў*<5p*pX(f(;P^ߤZAv5U[6HEU`eWO35K+Swq]$4G;mdW>դcsvvIyavŸu&jIPqXѐKE]6sJ kfcM&vslgB>vvʧZ@_pv 5vP/lAUKv <+V8ғYkhD_Z6J?ˇ`]o/hrIRK*A3kB}BS54tHUCrvpR0rS< @bv*@s+kOXw!tLw%u%YiRjPvD|C.RIy͆Mԗj{"]HQ{Bʴ,$_֤|!ɸ) mqli5Q~!,VbG7j%V# WCwF uas3t-nirQX#VbmCcpTooX#;Tr~{qCm~ A-8QHXd@˗k/nin3H*=ӈxtᴂ>( VjP{7Xl6ژx gKvZWwxRrFkb!x ÔӶ, Ygz!{whmO..VL|U9tݕo9fU7Cq)v2XgA9ndʼn:GZ%NGwB=BGuk-8O*߳(jF>)4iBPGot8jb1&46i5I (t$qTrs=y 4YǗwS%ڏoX&!:"',u_!3,,yHK3[إXNoB slyuD!kccǪor/#7:yZ)_֩jBj㋍ nY8uĚ7Z&ZFw=vഫA=x}<* (E|bCG,;MZ toڠyM%g*1 /sUVUQ+UeZl0CgZ6 ADuzչ6U mź[A3I(e:z)tG,;bK⵳%řC37þף#O;:[.DBPXzS2{'j][b+8#Sƛ"YI5ø{Y>tSo,m)1|Lڂ Hŷ~`iX&TN& 5T>L?R* i/|9#U|14 8u|7:K;c%C[A:“BhWS7^ϳ;.gSz3 Gs;x;abK$9`zY|DzM="{| :&SbyH͛LE≡{"n}>sպ%!4b͂<%\l!ۑbȿ}C_A"4,^ٷ?BY>8§"ᓧrȗ?|f~!8ɡ-Elu὇#>Ū.$]z=p?ЎxJ^*-@(=[G]S{q$Y秂OV|rPm)h$`(jg;2rkj*=}1ڹïͱ&-u CFrgwi#WCNd}{ GB E^wL2gj,# oLP2&c种ֳ}. mҿL勢jNM`@w4X%~mm$Z*{Co"7$`$C<0… @Z8T0#%x,2d2̙4e hΝ<{*Y%r R$%<3TL ,:cN0DU+MBWDu "BULm +ȖD:Pjpo2L8"'P(ޤ'@>] .1ͪzƎgBVO0Tt^$읲e2+H" sf@a{|$pPcf5goWadC]oXEuQ pH%W^DMȞT)`"]wQaHAA5F|%Wp46k1օ攅6Ѷ K\XnODnj}jҴJ {^PE'|\ig2jkyPW{PƋ>rݧz_73zL"ZW|-K@lQ,oD;RSi{kSq[;SWOÛ#}ё&wA/yjXݠOFrz[ʗ_Pg>B⫵F?d0:H}(#V;fLl;N/Naګ :E$Ҕ5{da{ZF85e+ `,i9 Xx=U&k`@@0}qID  }PaY_.SaHwu~M iF>Vx@)[z7? aJDbЖr@A( ZL8" )]5"c,9'&_imd<ӳv70Fڠd&)ܤ0aaG%3bL\L>H^QeR;8qzDlIR[KƐ @ ja)&LIz'e`WJSo$FJbW<2>YD M711 S02d'1 ff=0:ĈԨMsLP NI ]h=2?i %<@bHPQ !aZ}J"ړK`a QmKFɑpv"j-e–QxJs-}yDT&3I/k)u'!:!ʦUm `EOM0ΚGlDӄ(X;jk))زIIRҒԌ&Mӹ$D kH&2:@`_٤>VME>'NEZRسl0:PQ'Ÿ|wEF !XG5X-ݭy2څ*J P߄8vرz^y& ;pg=H[#$eaAT_ H&kpO–.O2E@_K1,a5NVb6q"5=|y'"0&V'<%pdaqS" <L|勀C96ؕY'X,"w˖n5 Ay&PtlD)!%̚`diK;g8sB)ީ#z!n.DRp\by>v7 VsޔǮtMꖽ22˱Ev)p`gjX9i*p׃4@K?hX/9)y0P6:IE97!9,0'p7<,.i|p$i(IN:PR9o#I㕎aYUgCI{ YiJœh3ؖك19sq~lcy@)xf)WipJIi7ɇYV>Y/W{( HRx ZX+tiIY.y鋎))1)5 șYՉyȜ)[,`4iꉟpL\tEץ]` Ze XLd7pIdZLR韟xF9t)/bRV!`LVW2bo2%Y99ڣģS%^`؍ȗ 2%RO5]ETSr.:u_ى);?LGLXڢ[ٗsj3H/z$$JZ(z+Z$XnX*UyVj]Y4ũzىzZ򩪱Jyu騣kJ:*1Z5)(zh= JrA cdꓡhZ.:ʮОZ]Kʯ j̊~֯84::ǰZ谩 {-+1*!5;:o(2YX1+IHkj AK*5;;-=ۃ?{'{n(DzIK{5صB$hɤ5˱*s'kmX{O;~÷cⷌxzYx^DYz{"k*[5Z[Ȳb:# q!j+y[Yh(@dR뺾ּٴ#;՛4ےkZ{׫o 4z[w#Q龌Y;VG빺ڿ1ky < {; ZHY#ɿ9 +ދ'-,a.}2֚%: =0̖>L[D<]K@˘N,PlEːGv9 aqJ,, LjX<1FH "|B|x<ZZR *lYJ, g4lv( ˤ̇kvlTzl|i&|hʣʆ5űJ<|˂EytʱvX$Y˾:@eE|ÿ<˼Z p+j,F EYٕS`^Dn[Ƙ߬Q :ZI*Zpڭ:$ظOԧE=-|ҷHƤ!ϕdU 1IͥK-Ǡ@1TT](]a;дIƻ;݇MLs4ћ`q=~Qєן)Ǝ3Y;Q-|M次 ؏mJ)u5k26FZd zmJF"Lتڤٚ}Ǹ-)Xo]M4K/ܡy@Uǣ3LZܥY q7۝<; .4yQP͙ *Rҭ=@ ܨ`{#~qͫ}Y[ӶM$jmϿߗ ~ߥ9B<>0~@.Bn?n@&`zF;&~(OZfqe>g^`|8I >dfݡIjjJpJJ-nNS, eN̮U>4<ǎ|n~p<ޅԽٟN~ U;۱n>-誛K,"~{)Qߝζ n5Kn_]D"a֎=7O7>a-,<1L?SRZI?:(!_k'qGcs/;OHO7=4}H3[.onW})jﴺf8Y3-DA\8  (kט.{΍lJUzT 0 1VU=S9-{X? OB=PL@JB,Os4eV ГЙOƼ( 6_r*Ϩ $XA .dذ E5^`!4KUdK1eΤR@”5uք(ɝA& fXР$ʊCNZUo"̙È~%# !0E@eΥ[׮ʭޥS^rE @n c:ߟ-S=P,0fԩUZjpNlŻ񍄶;)r0ܛ]έsaQ:Acmu?me=9uczP=s]6 Ђ:m?c[e3Ar褟a]':￟7׮w|W\W]sՓ~mWot[,&n[SLwW DM6@vp(MO;Ωyi8xBgi_! cxCPVF@Ȅ8\T #S|w"*@H Pb\ .b`J40gOUc昒&Ic蠕2A/Hkdb A R42ң~c)! 7Zq_`3hd %O~:QrEB2,%"0~,JQ2ґT$QG`bv&1hER pc;;ФLhjجl9+ bT" 4 [  z 15Z.:@C7LE0GВ)IcһTRKzX DS5vɐPc5FUp`JKzɌFA-'Q wթN%a SSTVEXiUAUL9PKQգnƬAjz@%K {X&VelcXFV_B!*FC1JJ&4K=$b=l !JN]cn[` - !# Y\p1(Ŋq\q*{@FV[[ⳬ} \BwCT lL{k\*r1rJ#aB.?nk 3;dIp{8 .U8<,\4\X2!1y2rn&e}0]2,`U@ץm\:(OJr%|a}orb!h"XsY0Rd++V̐OUn\b7!& @ e]8+Gg|=@Y*{ghpa^waLKWRpQ$ִnǻkZɡuKB]lh9j޶*T|WIVx4UeV4S]h"x pV'kK*"&[ ULidnmPpǬugZ@O)@ [$aig7 Y;FdKZ˚)EG+ !eqpFD0YH7#ϝ,a+VՈw ^d(iq)l f֧v A 뭞kuj1XfDѵ0&rG@\@ .8' bX6D%0pi 7PoK<欎K,$_*^qհE<Çh`3_T5M^b dWp2+bxE/#(f +~Bʹ"4|4_D<,> 0 1 ǩU+`u(*L7?;Zj \,0^GfqR\:Dvl;s;DJܲFUt`ֶ@ּkʲ"}^"vG$A %1@ waf!S䔾+wkl \!5QIgܖ8N(牀,/GGnUd#MO9Dx \'BSa<7u"Vtwݭ zKWH8 uw?D'u`5Ğ {@-H=%aG>ozF7<4'OS$ պSt+[G F %$w-s'ږҮnȿ}u؂/x u?*'(L[-OڹR7b|RrJPw%X;AA{͡yY,g 5Y~fXWac<wk>ttgMguZ5Z |tqgg~r%1Pg`xo&0|'Ae&(:pgSrvPe9%8u \,8YNWXBrgp]"Pvnegf,W9V)5AzxVΡiF?6lhBH^khUv1gV+UsQO=kXh5_h^0'Ϸc[ xoex8@v yq2x8~5VUF\xgijyaWq`6l[,?XXHxE}DAZ1tgx|(zt?8qoi%l,aG2 i& &vcԅ+ &dFFPg*ш׈reQ|5(Dh$eƥE9oTt@3.I(Rɋ_R)|=1^WQZ41,~hPyjtrxF)Tҷb]3 ]YXw)y.(g9D9YFkH^AuF(QG'vT!`U*{_ )W'(2OQR!EV&CgѦ!c9zbJژ&*y )z0ʚFTFrFr٩KmI|K*HGJ]'&!ʜY%R (yOQ*2FG#J4^qƭ &0@JZX8eHo";Q Shz|VdApT_p}ZB rܶY0[1 M#WoғW1-zJxkNWm1 2IqqHGtea٬kA%CkZz)JKڴFHVf)(*,iuhI{bY1^9A\oY}Kt;攃qPu(H %X( K!`zu+M_K/K&od.Z&аfdk7xXZvFhnJ4rdSdLz.v%I(IxAEkLr{v#\WT DL%t+63ƿa]I7Le5ʷvYˤ٧ڻaV8 $K _؂KmYkǛY³ab|H:uk75XHۇ];GX eA?%GbJ\Y!¥‡(e{{L7c;×\<['g0uñ@V1x]i3.ʎŊlav:VCge8ѦaӾ~ ^:Cȳfa̶͹șLJb5J }aɞuorѾ]j]u Ύ ͏aQй">@;#ѣ a**-e҃.r26#`,Z?!Ze"AѣdO<! * K KiԍQZA -[]m?6!*,=!Vt%ҡ;mlRp=]}7ͪ=3m`̍:UO!TX<ۘ '{e#գgmU$&\}ƧMھ$@a^:jc^;הk`ER-}}eȁ]* 1@ 1ٲ j-,䠽]ϿK.L|"7`q Ѕ}Wy0 h4ɔW8(lҦ̭Rm4o8MK=l ,kC\Y;dѬp?ʁ|weQ 2Ne+ׄD K4df-}~'n"Aa*r:<$ԡltX$.ڬl>A)_&Ǯc - >C0Yj!XSlzN͘v}+E!u+x -nC6Nyk5hN'Ob'JΩ> U~pbZmo]Ek-n,R?B ߷^q_/\*X\Sv_*t証sއvh NA8 OxfChNMWKZWw_kJSe 6DMF!wV mi.iӘEi'T@s\WZL\.|w'UuNfJ+p-[Eۻt6=$ݛLʲW8{Pe<;#'϶fhmQOӱ@I̲ 61ІY A W;)kz ~)L&5OpR  1ԭ,MFEQk !#x(T+E?4>J=jTt!p*^ܢbh<d<%N ktd,*=sTLAٱ` mDR169i)`4hI^LD&cٕ2DIFGqp4*L xҢ`JWIOXUC`1h4%"6u]Wx3?p"I̓`3^2BL1TXCDPpVDELgD JI |dʊ0('oF4 Oo\2[rq+,D%YIK 38t1%(jL#d'Km5U|S]uJCl&l!EfKn:Ґ܌Mb˜6RXoU΍RK>wc>TKAi,?&t!lCtX2fĤ 1:TP^;؟;Ƌ[͵D>̍ª5#UZska%TɭGԀRϷ!_66UA/tj_U2Ȭq$klVݍwZfʳz1U\FꕭAP7\x @_cI/Q"YPmsmbC`lS\m\^rۻ ybwLJQj/ѱM=yʲy{sn7Z7Iyi]k: IOM۲?q(`9>)#3Ƴ )ز?=H<λ뼥{089| H c=l#aAl1(\۱ a:Ag[p#3""0 B #B<4[ S[ %,S@`@s?#1#*6s33bÈ>KC˥<-q<\1LCL 4 B`0LD<33NO >=T4<T0rKEDBjM\ G592^|=,'pB{g6:aDeG$ tY:C ^F2~);Cߣtf8NFè%LZ$ңB( GD ȮzkCfdŤ2EEwte Dh 1Ď Ő_4S3!Ja1@qt=" J #7mDbQXL%Npx㩛' ռ T^HS5R|T `se]Ҋ@xՑT@ISQڈa=Q=︪0ݛ|L4 ֒PӌzM&:R#[ ۀS`Nrs5X,r,W\ `ɍ#I-ϼȣ Q G"ϣWI@mՃW|쎬Dе +=X;~YGљap)z?]؍$}W˫\D=ZZqX/ZY&FٟiA_?1\ *Q]m(p[=Lr v[3!F͈UAĵkι3&FHNŭ\޸ۈqٻXoy$KG}}ֽ芨\]JJYݖb$P@^| ۮݠuUj^ҭ|]]} :Y|[V]Lj{͈< y g I=^SUn^HX˥=2_ ^ӈbHIa/  pEVȁ Ґ _> 6Y7W<̀2 HR >ZMb5Hu2APdE [b-%۱HmbTwd]_ݏ9O[N_ S<5$ 8^@MWJ] 2~13nDM W5ֱcIΞJ20h1\d=Έaae \r`G~dF^Gl4f\ (kdI:d.`gHS  I9!pP2Xcp l1*BxP} ?;8ZVPN(e+ĽJdk?`N!E(Y6O[v2AbjfYK/nXhb!Kn)ޞDzXix0-VRֈЄAmP ƑTph4NmΞO&XjPWƈqn Y?ߠ(:J`6&mV`b鶈`XCGlm19 %揥&l&m.htJ'u;! 6ne玠QHk/n Ox5)z= ӆ 4FuY:laoP&^BIWԐ*؎ p̠$Tngi%yOrK;-_U`n!"G#.ͰD5W>d 9dt6ڛiQىȁ;: s12Gs& MŰg8ЍHOnJrS?VW bue+ʁA hA{H?Ӽ1F`%T'6OW Ѐ p2߽|w~ ukRPk uXqJȐP$xy]z?0iw80y، 'm nG5 xXd0 i;pO0y8\'hhv\QYzqTr]yW@c2 `H|z[8_n214ɑ?"LO5 .lh0y77UхO}y@a7a}W1Akh={g 믯_w^׉MZe|v؆~3kphd~xefO'|{  @@ 2l!Ĉ'R<(B@,*\X჌ p| 9d)vQ A +Xg;(`6VR 6B] uUG qbe),ڴjײmPDnҵy` 2w^YvXB$Ia';XP H?x K)~DŒ2ؐ^2ר -M .DynЉz  {L%d:&)D&X4mZ@pA{Rl1v.SѢdg肌ֻ1$ J+{~~1ϼsr0E4 A<+]sڷK;v(3$KV˳PR8/[uj՜4Cg@un^v׵L4*MQaMj%R9BًsA0ݚ"-M)~:E3ܤZEְߐ/OC5SnWq۠Gg_E@K?Q5N{{zם 鹿tg>r-R* |ljKy Cc]qd5Ii%*ED!;5J.'[y !zhea`yjZErGh$%9,d1q$\ӕǴ&9eBf<'S9|L*mry<DgG^P*eiemiFTK*cOwʑ:I|"d 9`:$ ӝw+ 4+P| *//$XK9ÁL)[1*N23Ϗ.VR@:)Rև ա<_940{[KG&u'9:A_}PD檻 ,xf+AJ!%c7匌!)FtWZErײ!s8\o9˝qEWŕaU#@45ImS@e\џX4j1-DE5E 3WRT\ #ڱ@(JԻP0q WРq)T 'a]E|@@ ] B1Ĭ(ٍ@ϜRTK [ ] `؍uAi  Xz\C8^:Cibto(rۥݳ8"!J\P)E*bZ`J ,cv5RIҘ1Xc`!@t,b qIVbZx/b#`t[1XcL4J"4 юm#)(#:Zpb<00Pzz![hc($ vQC8N!FDʢ1 a AxXG]$ʥG&e].csf[cN\T¼&igM"XM.݉z'"`'\ghg5I'[pU`+zULټC67=!Ŵa E&:Z-.Egĉ hgyhr((yohܡ2N: ƍMTXl"jYh…"vB% ؜;uLX&A*肂ilg)^'癖 oF#i]rgv^ȞNM Q* ӢK )z@EhE-[ iEEuީ 'EZ@2qk%lrNQ*)摅NaA4~nr6օ fiʺM 4hj@JZEħr+TI1)9tfR1X"j9A "@+~)lˀ\%ZEOҫb>Q!NhF,UκD*R+Lj|,JsL:+@i(bTT*=R-N,٢!ң6 {fFU'>mC!́7>ʈ#J4F(z`زEZŦE6۟Ѷ#J1Ec@w$dԎP>$̂.F'y@26M~XPZDAsfJuR $hl/+[ ,m5­*YAJ/ U/S.Fly\(n֮Z/[eypD\AZ޺⭪X~DѤoy/cY2f clPqMJEDZȉl),ʪ ) z^*.mWCDc yE豩+JY1NN q[|@g1nn,!2tZT<#8SDҪ mO jONfw$ 6!2S/JhE`rppq߀p.Ѝ0Ȍ+gFZ.Gu|oD`&3C^DrzVXT.YhT // %=h9Α 3-:W*0)r*64DԪ.ERoL&Ag%6 :ODvVn/E@bW[+|-M%tf Cs[QZ7DŞ j7vjöB'iDLF5Zl5,>'貉It4Z9N'x8Cl8u ^/Pa.i*9olu<ypt? r~ ~W> =?zFq7e/rC<;Gao~ ޽EԼ3Kr:D]7ǵ[׺XK>[Dg~{~(fv&7D˓+MH;ڛ$c~u;@8 DbE1fH($&xHx I%4@aȒJ0K?:hQ,4 )F =JiG) <*u` keiɘ)[h]-*t1{N*J aڕQVZ!ҊY.Kw*E/K[4-GYF  <#ݗ(Tl3]yS^ً'xgsko:|0!hxes,9*Ox#p b8 ,:" J Ӑ -ԯD +\6 /, >(@=)Q&Z,ȡT#{**X% Arȃ O zQ nFB)81CL)F{.09sPMϕW=EL6<\PV\DN.W(\a^W\=Y`b1҉hP!DUi +c]+I]:bfMSqUvilx)O7#uޢ7l漣o`ኄV@2AVܧ 4h(7ŖZOFjztnӠo4fKt/i; 7vAOf2݇&CHIV^VYKo}cϞ37n]K}}尳ʋj~җ%| 3ΒWsNV;|Kp@/,nJr0pw!aQǢ b{A-Y(^/`-!yoivCЬ FYFϜ_B\PsL9Dsh hA`D<%4Qb@do߮xH|bk +ꑺrr#0emGϬӉB9bȏ,k?Tdy˟0R {$/m3G pZevHJ *Z5h{(2X_.y-dy0Y9*OΔHCF=z G2;6v1c6G!J=gSYgUėJ|1oҢ75Ѓ2f^*E}J.X^ܨ>4Fs9#}h@Afe>%QFE<u<uck g-`˨Ji*,6kzЖet, d|Zmt#,[qVd 5) &*9c#c6YItY봬JVTI: n=l#}e5bK[ j[L׶z@+=^y ɺ/u̚PX.* Oy}V,{r?MZD߅-^,)5}Yl  _}{T.Wx1 k_gL%p;T-v PĎwfH6'{aq]" bi˽d4:ƮbXU]"w\/ND V>a,7*yfer}- `..S# c>4SRpe u+ +fgPST]}#g,(ohMXcu4A 0!9%L-[yB95sFTQPֳ}t2TQݵ|8.|]lsQa^D:6s;Mx#$kDMreVʷO6Iur--^W|½pXV9ff;ߋ\͟hVybo\u y^м?Z4i9OY얨W.y_u#B.dۅ{ HYz2ȑux=GOlʥMxQ2u5y%?Eȹ,|qX/oހV&DRh_9^Ho4ɐ~R'u6@K91pQ7g3캪gIp׫x.L$mfX-&:6ό:@4H:6D,+P5O(ϖ0LkiPkUpԏ8||2o Đ) ELذ Q 鋸oc,gGUɰOjOD&iEL0a p/!ÆTЕ"[qORVHguop s1lɁJ Ɗ3" q xmvlđ%bѱ@xh1BMѤ+$N&iQ3pQ r"!%&(#mp:_bw-2\V$Nbl#) 40.XKr)t.*YrqdBo12U0eFtRPyj+W0Pm*`(.JKZ8So@!/sr"wr02E-#DoV')G!LÚH.$}Jq0lܑx mc!eÆR'(r1'0~K3"/h*4i@I5#&s 1O$ 2<,( QiR$o(d @@ H =A "Ss/E3w.%4J333ۘ1 (=O7wIi#>@蛂$ tCo`C D?t։Sl&r[,o: ppEWnnI2vB23 H@l 44#ECHsArdT0S,n4x9{Td9UTi=Pn"E6D?Ŷ@oIjR+pK_9'`A))? r1۶;1f+04Si7b?jkJ-eV3vq2r ajg'(v"P(q7X X x#d+wo"x@5" ŏ v/{Lx踎~n7׮ȷuR5(%x8y~UWOofAc{'4@^9:7gyEy(bȒJg{vo4guu'C`Xۦ.x T+Xzme'`2{JR_(Pªt9<? :4H%9lSy~:)k"l;x5l;8PWm`Q5Y X?^*7z1+psRvJqXGDq\E|jGC&:[~G3YٞbuuQuCZGm5:_z [c5sCY~N2:0n1=޺U/ЩZzp#"ZI2S a!XAx:y+9C" #y+z)o%ͪ-O`J$t zZ@!*@my6O)BTk$f(:$)9miC:àz[2;̌6/:9 ;Z洹c荻*MB'Zڻ4E6hO3Y#B.[!`Tf"2!|w%tc[~O+zZY01"HbZ/gNgכ5nm2 0|bغwڐ*f"B3"t낷kr|i째eǥ&o^œ$"SҼIz)4Ε i~ 6x>K&Ǽ=|ԭ]!$S5ü]su8w/}Z(v}2QE"Þx^"Q>5h'Zq >;0aYѦ{2z/~)m*{2Wc^4ʛ>%T 뻏+tb.-P!~zbLKhh mL>6_J"Yrg_SB+^HDKwsB< Xxĉ)B; 04l|#6DReD,D1Ν<{ 4Ag =4 @ @@aztT& @Xuѕ:+hXxaCTu!D!zڰG.5s'HxO;{ Z"QC@ )t++C&>Xݻ4Ż%6fK޳wťG09tÅ3~_?˗^mHɅ}&M=xe}-suBTIR@LwI`M8b#1Mx%xl码6}Ոi t"qFDaTcX@0NtaD0(PUTVah`tf`y璋QBQ\cd+rNKEw6*o#ý)(ZpWP ]csxU[b|@;89@l FZKԕ<阦'e=Ma`cA%I/>/E#eƠr'7A6q%DaUكYnnHzi.)==b=%&>q'-K\ lM)XRUtg{G 'r&1KVAk `1Y7'MN6˞csيΜt9?=Dh@ͶԼInT7)лK-@Ij!Ptᵱ͸Q}lmtW $pj۶xSsn'f`;yR1@p;g|'`)5 "u3ﷲ q$Ӛ;MjQřp#$htF+?'piFޑ}/)ya"pdWnnumrF#NU}?*GZg|HӓNkHrW9Xgy{wKnI~{`aU<`d!SpGy7(}W7C`~I1goè'h:G`ag+[]r*a}mOIyvsF~|?C|Jxr%%}A't3W@rWzL8W"ZQg`4F'outL(X:r{m13k~0|~k{ll2'T6!hCJR3V-F1 ?j XB#T^l1bW9D6F@Ka x+G1N=QEBTu-U7RXx6H?ŷ^Gn-y1bˇ1`G\W{G\wL3g~9(b1iVXN#XȈEqt@EAWIz(*Z剾wXp~8sL sR؊qt7(Wv8UwZ1rb8bT}[K%q:vuHZ{X:qP pƒUB@Q_Dӈ޳4d((C'UGR|qPQ÷`h=bAՌKYKH7wX 1 9(yi%Ek3Ii-FT+9XeSW tVAXUYԓKYB=VZPy!xA[a:>Ʉ$/`/=F8pJXt@JXrS[d! I&7^yb9U;=/x')Ga{=! qXy@cADuvD9?WɁ湙<'KԹ:!ʠ '*::qI#U؞ !*( :+ʢաN-jٹ) z? 4t*IxV>SzMnE)Tʥ#jh5 uHڥe_jik2Cʦo qnjTX*ZJrD1 @[s}2z4 ʨb,3JdAf<ʚZ@%Z Cũʚ1*Cg*7*JЪ`*YtV ʊڪ-J^JYĚFj3`z[*wzغ͊ J *ʫA+*ʯ7ʪ-ڮZ{xs [Pkzg = Y:? k;T ̺!+F% kEJK*`D7KF˲ۥ#,A{J=QJ+L[Nf0,V+X+ZV3@TVd+fۑh1` j*Bhwk0+< }+[jnokz+Y{'Q ;;rڹzk ;$+oK:`c6vzck媩'۫AAjkm&8gnwbtBk'.\zUt i&tFtׁhk&q!_F&k_ z 'U0mgzئc\q[ܼ|jۭ ;[jUqj '{C ѵۊ{dFjثvw''\:Þ;k:tkz8_=,*:8`ƿPz)ܯ#K{t#vxjƖ 7"Gȅ,˳gl#|\F[:T z bWi ,Cv,S̫Vl=˻kdܢl |p,m q|&͋kU< K*,\Η͙̍(\<Lf̰m ܩLP̿{ |  c*ǐLѸa jʥ;<ü ݴ<<@,(- ,.͠ 2= 8>[ʶ\*6P-ɌqzμzI=!i VMk!=^#elr/Z]D}]zX ~ ݩ`|t[v=Mл ٞ!ّEI ؅ٝQ؄фM-ٮ4M&,ԬKphc؊CՍփ=ܹ M {jd˾L eí݂rܾoƅk֓ ׌_!},㍘띻 e=N]-m Kޑ|ަQ>~6 ~"<ˍQGaom1BQ㐄nW<| |]btQN MFYMnRӽս͠\1=,eȍ nl.n?hKNm%s: `nf: {烎#zI~.@ SΡɖm{P: ,df7&qz\cԊ퍭_lm`uGwsKLh)k^+- ڈt CgÚ:>봶7pq6m ٧~6Cppj^OfNFn9r^,ofilf{wJ >C23Vz^0z{CYz>?={_C/|>ޱ@\&};RTqKٝNlBWz\o AƎ ĥs^`O{VHnukm/$9 /Oxcs/:oO=Ow_ϵA)a(xrgh^3 7ԓ7"[c_=rQM9B:+x>~uA=___/olaaC.dC%NXE5nG!E QH)/.PaB1e 0iA<$OI.e)Ғ>ZU;3m@S%[YQE[}ҰFSE%C)01߭\U,Xe̙5? rH/~.8h? kرvF,chĨmS5Xw۹~{qcΩ|eKу |@Ġŏ1OKG?s^}{azϮ(kMt03@ |+'b;/qĽ"tBH@ ΫRTqF2A-q".qH"3DrkȚ2 RcJ,e1K.k,XP.4#T)P5㔓4q"{tQ2qN@ҿ;ԓ><uA+TCin|tS.#o8+MgȴQNSS@]STDSFULVsUMXA@ Vb]앣D;Xh;$5 Q(;9`$HXMcKe1"Nv\x+wsLע xo^klv}6xi"M+Bë{C1wbxXuW5dٹ<9_]e{YLw`?yvN+ۂv߄?k֡u;i39SjnkթZÍ"8NUlG&:n3\jB "\'q*hKw rn![BJ2sӛy{K'"!ulHaxO!l7 ~.}~`y@^|$m@<)gȫ@^6ߜ'*Cae&Z 3<瑯)O #~{` spҮy ǸE v@Q)g\!AD͏1@bg6]zYZP)͊c, l#=dO'#cbF٠?WFr!qC)IL2#rRf6jd)5Itr7[{iJXI*N<`~. 2t*4"+fCtKdQfeaQ2?xPAaIMXZs3$yw}fș?j:׉vfq"Hz e>1O1"'AiЧёL [E P1aTDCPѣit)%Jҧ|&u@H*ڴ/8jNA䄀YN]/HudRDHFbի0{Li*~էaEXR֔hӨim Xj?#1gPM[(γ?`)q^ $c{^6dC+U1Yjv}Y$ZL8l[{z-]ZJD$%&jBgm"_WMpR\M[ܮ9,Н\ۗbi% tM˪u;vU o{ެL}3beof_=jez`eV"b!|a(* xc`>uJ]Rx"ƪyTr 1Eb4vNm/?El|q)h/]sd$GKMћ\yQߔV L,//%f{3CG1ֶqVUs6σFB"Z14R\PhϋTyr')"4G `G改90-dVL:gu*B! G:n43l I);EB r4JkhxĆ#.㋎Ѐl񦩽^V[{H\m/}3as| xt̀56ťBڅSȮ'{6 LЂ@@PD Ds?x @ی$@81HBAk -"\D i %|B<'y¬s /<DBtBd,. !<6Ԉ5$=hB,T=2Bx!tC$C<9/l0C1A$@Bx7 NdL\³hI=DxC@@StB C. ťLTE@S\@!E6D V4BP @ۋ:Ťx1EB%FItG0o4J*|ƳPA@ft\GkB#XdV|EmFA}BAw\x /ǃsμsfӴNO`Pr3Oj gkm2=z>%ih`V=6Zl[sPW]-ށ 7$ gv(&%(݂JESUE`j"1}8BN=uL 7H*BDPdYvĤ]9lfء`LW`Зn$yY%ɩ|y,y'Ki硈&& yWqVg2h/ lfzjkª&Re ]J뭉ꪂr:y dkȂUr [\쮣m8kbkPEmNJKix<+鴥K,咺> Ԓ7LNkW!g[a L#ܯp(,b-21Ϭ^5x9,W=AtVExI/-u$+tQOUx5Yo-42 :div.ttx-z7|i(~וu C-7g+xo..j}9;$:'y_눾{߲Gߞwg |{I|lЯ|W%/s}C\zO3?sǽgLp"l'd| dr,Y`@A5+h r Gx82&P eŠI*\!4;`U\Ě͎t>d09cB!p.OTE n(bɨX9  SpGd xJ'82sgDcD6j ~L cE䧊"GDbPD8.`$i8UҒɒCuC慇X"!6ITe%^>bbKL21/t1c&JZ&3L@SGҜk(7M3zgXIs3N ;Iw FJiφ+Q=}2(B O|:M$CϥPTD(*v(}GcQ+3ȪV P9'T5@@ &DըZfHӀsc3dH}E>58+V XVJurT6DcRt0-N@gNiMGBP5 AV0YU~l9DHnJ[M) d-CJ׶ec]܍l:F^FmjomYx5L-@]5[5F2pΗD50Hx*ƮX GE ^v \2$(뫻*جi)bwmw'7amy<َ4upbrM|3Y b~(, 2Cl ޓ{Kd"eM9G9. q4d>GVkj16<3o-0k815gK7v9NqOrW]F6f'$7% 16)bl[ K`jcw[Z1HI9k$W &wIb]c]oO'|!nkݑFC p&|9H2[ Zw^=3녽mGfGbxzUA{NN3J|Df H~=`_oto>"y],1w2}RE g ;MgVw+31b~Q{6{b}s)~{s`tv9Xp#yFya:LZ^UzQG1Bccy:XoT\|avg7WB8ad,81W$UYE-0/48Vcׂ3e+m9%~#Yu>wGx.J7^.6}bf]1ZZWh-fT8BEo u\'sCȀ,&tv6@X87qx{8WUN؁UW61T)Ht]7BrZau_ A$r8p৊3YTQZ 'a$QiQ_&J6AWAmf2hu{t֕xΡ|Ag !Rap}!A&Xo xDǏ8( (JJxW*ё}mօqciQnʘ0ynh k.ItV![hA䁭d)hr28xn0Z\C[=P|7G9s3q8Qs=YQxaa?G"Hyro@1@L_6"A$t)h']D"$؈c*FD'"t)o4ձuɖ㖗i7YT\EY)v> uiv%1e|ɹ3QvগǗ~-D\՝C9Ușykwv#z1M 9W]UoSi u䁞qYgY*Aq uxZU;Hs֏nxHwy<=llx $aENpJ5H5 Z"Z) FWә8CVqQ*\|%t/F!PZWG@iT7CIbƨ T*I kE JpagBhz;Ħ"1'uFIK$!M$!OJ/6xwH je@֫ut [W6: 1qVIHq^H7ª䪕Z>&ڰu&gZ~ٝW[́JYTu{UW7_' ;Ʌ?HA>4`Xz1ԩ8Zzq܆+.{2ʬ`4C;~|Fo4 b,!]"V}k u5l+J"c pe{Ih,l zl҃1< K[/71&y!5ֆ1\(Iw̆?E,<.vClme)|w:9ųYr:X W_dl(:X_-!@yNy|Rƒ}XglFUyf^|F"pCɢ1!!xdT =МQYձAˡȰVrcˌ,m ZL ɨ1';_\5X_L&9J1!d2λ'tUtz>TMqp^8\Xތ+[I#|\ &l! }@[¢&;8ȩN'%WҲcjl1LaLqWŶCOLazV&xYgEXI5k`sl;A^̧NR􌗒=sxt T=Wփ72b[y;GYU4(U8u%)^guȩxN]Jh(w{l3+[U:!Lނ&[GQ.-ݝ3[;l&h%,->{L}|K!!~^`-͘Ό Y`_aM  VZc|]5ōكih&bi$8[sw@|| K7zUVUx܃1¹L 7Hna嘻Z~Uck u-5|)ŝعp?a=b\I }ӑ^|)th։A%86X.K:XQ衝ic;cbj7;є[qꌎxn5y*.֧>&nK.=tllC^> pn$->]YzxPT4́Q~x3^?1$>۩UvSުnKNgx7gZ>ʝ~MR(Bᩚ^z~a噭 #[ʜ^A\a)16궾t1. el?F8~y5wz* Qݘ?[a]7[gʍ`\a1ˏn.!]g)WozӬ 1b5֮6p?./;q㑬d;Oo>+A 0/M{hBτĹMoLN 0;Y,`?Oc`?n! `A`X05<1F5n nDRJ-],Q+;JlbHQ2CE |rczUUTUr\ V]S.P`є=`hڍI ,@#ٖ7=FS\ =>˰sOsc^$ԲVQ 57tـ(MYigtd֭]'Zl`z<1tE ӮhùmTd N;rql7ou-j)EV&mZfޫ=[ߏ;0~Sm5N0@MZrkؤA *(Fh0R' R2|11GNGQ&h[ KL$ `†*r8($CL<EbW4 I|H+3OxSL "> /\Aj˽ ,#HKQbL. S*;gF(LPF\Q_r5qC#AKYT2|Uy F~8!=M_ b@. j-\g Co,|C0ߢkc>Rf3R9JVm0o9n\q J5/Ŗ.0Y w 39rqzr4ŋ.8SWǝ.$@?T}8Fl=Oe6Rs}B4oV4\EJ\!>umPDJ5͎ͦ@gLcjNUHQas<oHS;ӝWвnW߽Cy`[5ڶD|{ɗu'7Q}kt "p;^ӊI,As'b[g"Q@!4{Yb4:? Ѓ7Cy-;B&,?Q@8 q=[K,2@*S٩;2a9.a"AS߸AQq.S?$L&[ >Y$ *̙+ı;-ĎAX;1t+BdC 2)*d=.~ 5 |۪0J+.0D<$k4Қ|=܉=BGD!c5 DΣcEBQ|xr6>h:;$?%)@ dDU8d \F8`gG4Ī4^'F~\NGH>R KE<0tFyDrZA16E]l.jD.ăt `G\93| ŠE&t'$}iZ=Cয়ĵ0Ǻ3!D>Pe<|Ŋ܌9DkTD@=,_;P G2"TU\FIHu$jܝ|¸!˃2H$ Jˏ@lBWˮJ^t4#)м uYKLRcBͬ-l-8zDZH=CM lL˭(H"GtH,)δ$@,Fʊh4j͒1mN F4t6 Hʛ>"4Ҽ 1LqM(qȮxJ JOͣ I6"&t5IRsSP,Sȼ3*KR%K{:>e2lJ!Nсl 8@ [*42̠KCS4GHM*bJ< ,+zaIxϤ85#EU0Q7 EP؁&5PU e9H #YZMBՓ䤱.]Xs5V<%;LmX&T D]3%$U& JԡT-eX)Eז44"XBTX4-R#Ո S YPXLiY{sYƣEYW 5VP>W֪ $]X Em щͬ $1 ETEuI۫([! oۘeZԜ12= )Y՟ܓP\K ۯݐŵl٩ՒOX>\۠}Pszɻ%U<`Y\ε#\ Hܥݢ](c^ή[P\mkU]}RXx.a[M DZ]lj6ݷ ^e[Z#[mDɜK]E!p 7 QV R\潉uժYg:ϒ"Lۚ})qxh`M WBsl}_'W9ݮbP޽܀ .^ޥY`@ pG7?M)6*nR*%,uߣ_hL.: a~U0EH .szab>RF @DZTaԀ/5Hric7Ǝ85}S=RtJa &T)c= 0\ָ.MdRp"Ď`bUs`-'D0fPPtjef\PX{NؔMg#p]^c b+^0\-big㊦m H9f|cEcz袘Stg(Gh 4.gf q2_KfX}iWizcyR^*偨hT6I^8oVɔ8fVv6:BŮ֩l` @=BoA`5.q"ۡp&[o h~S֥:(.Vkg>Ž u5pde?|+-8iޓ8iڦDkՊОhh5r~Qnޕ"E`c. :0i9H>j`mm""/I=BV#NFU1<~K^jnGfÅ^ё iic >4klכּ통 dG qpݑrT&pm?k q$kQ.dTXx {ӉnwSwxh}UAEn}nEȁyw\sf0 PM [yZ,~o޸GzoO[Ȱv[t,RWp ftOw"B2l!D PDˆNXՀ2n|Q! YR㇐Zxi&Μ:w6,&ϠB̤ * dڔ(֜ * hPMTjsٶi T'<6X/} oVp+t3ԚpskEYj+X4*W.SD;5uDM *=@1NR ;7DzM7bVwHۈsJ t=Vtxȁ3.} 8pe:g=Q̐Ѯ{:2i!r8@3&W@vaZn J=OmPS8?PK;ﴊXwRjM+>997᭷N]v6 .L5N*Hy7Z#ޡIpwzf=Nq(M;suGJPL!LledzֺZ/[-nQ=mf\09lk; s>E'+WTEtDs5a:M( %@&P_ CfUN.9a%z' K_2B `JNzC8,>R83\n( 1#ak(poM;X&,OYD=dhꋄdH M?92Ćl"~7䎜䝚`,p&lpĤƀMYT ~d hCO,3-(qو6WkiT,H>3BMTJQ /$idbeD0Ħ&QZeɛ&6K:Dy<qB!'-+{FJ$k# Y(:b()%p=MF:DAJTԥEN` VFfiD6.u$?W"TWd$T5iDΚ;b|1 ݢVTM)_[L%G5UrGI Hl:T7 'R3@@Sap̸e¢WgPAyiœ-7_N* 3YʚV#=\6kz!ݟ&I.}QI5p";=74b_ц!O)(F^j1Y (5+U%W:t5Ohy3ƪ?_E]MLhSoZ Odx.`b|B7wF5mCײ9 >KHDb8XNxfEK%ȫ6:lߠyʂR: t<: &&#¢!ׅ,Kfi~Lv38Gq !vfbjw쉀jVC5 &5D.[uߔiHHm7 ;fcx3KJ#KnPIYඉ ԕC*NSU@oB>mz9]A"Wk[%O5UjWSYd蝩7kuEo!1'}#F/Iηiiѷ 8Eٚ5F'@Y/q|2WTUM;1rW%wt/~|yz!d{4ZH]aBoKԊmz B/ާ?%?mMogThDf#D Te^;wu XĪ\}^4<5{l5ɧW:3OuWH#RHxeO{67CԳ}CimJ-^ȗNFT[𱇓YПŏ`KA Uęe-}&%턏I\ƖUveDD\u`Vݹ`DNďu }BZُ bIŴk0!z}&/U=Yމ# m,OL_PdHEu谜z !6!ީź$ !9Z*2v߽-O"`Ǜa ^b(}Xbq"N(:DtI'T!` BvY"!` fYO2`T$r _'03j"'v1:mϨ<p\UF@a tBAX9DH:DD:G'RR22 ]>OV*FZ5bYI-lP--CIOB D$P0ai\`rd<<m4cbM49BqQ|" H"b%#%%Ie'Iu G.T>&1u!Uf%YOLSX.D_pbJRd\j %Z6R]}3AYTK,ݢfJa LMBbdv& gF"]i&e]&WD "SP*&aT^ڐ!&#iCd:  h.EH(bˆM#ZiC+N(ެk%ވE;⚳h6]<5br."v&p&km2-*†*VU+-c> 9]gz-Z:.VXn> f_"Tg9֍nDDE.Dg!f 1EůbF9bZ.& ^VmHfi:|0Fdβ.sYdΡU\/OAFmCl/bYoYqfpV,*izV*b S*`^%ڜ>fo᥯BKZp&M-lO&6.,J 焇u ֈŒ^{o.ѐKjppl(WSnbp"ljB;Txo E E [+01 xSHZƧ$ j{dWoqP5""IB-Bhɬ[VF/.Ff/3B%- f Zmqtb2Zf15%D 9;Ѝ&}]DM0P3_Ƒ@ k5;TqIrBDD!8c /D (HHh4ØɃs' <,< 0RKm"*[3N40B+jg6"n7{N@ <̘I(5S HQǤtIzI~/2Qi@ !fކiQkފ-n(5tS+ R{;#hF\-\)0+sq"mO@b"q-ײ¢%1Q5Q7LE  ^wBI_иL#Iî[ vǛhMt_ZdԴ65j0 6eg)hMj sA6IsH믏&wC@aSF gQuP*#w wx@w:xPLv1s~Ƌz+#``gpGTdOk$@,w/*Bo,9O`h!.ŚO*,$ 774rw`fw7WZU7{cy/(ʣ3j1c& ~D!G9I4Z+!,A$z]'/f2瞪or~󶛃Hb-Ed{# Yy O^AՉO0 /c:߰wK?Gϓwc9Hl绱O-oCv+y_H2k &‡wH!Ϯ+vz_g?';;Aq<1V{ˡSsiAԅG_o++7#;-C[K{Μ0;*;n45ӷ{lU||h;{9bP@ʽ>M2T̨gz|`RҪO6:n{k8x{eTɏ;3ͨ~GjB>Aw4'9?lg1<BLy_'?DT6?CM3S%@ 0p` P@Fx@PaD=@# +TeK/[FpPBǐIA)Y" p*(e GF:A+Vպ lȌ$( -ȱk]BKNӀPfyZH#Lp/ԛ C~k]˗$jGYCj>ڜ. 4kp<*]֍kؿFhwnO]"x@8J%{@ߦ!Q/uω J0BĺqcWr(ϴy:OsR'궐+PzK>PhK bj*pAhJ.-;HHD,;rȂ&C$A[I8hd @"TJ q=P+ cB p0"2HHL7?3ijٸ$`>KNBʌ|3$.UI$=*STS<8LԱ _7B́܋Np2`=P"E4Tp(!ĵˈD1G\ X1u[);m#(R]z_vj1Vr}Au Qqq]f(|]΢~|t|Vi`ṃ! _t[ZxdSqEL׾#O(D%{לCjւAdYrdVYܗ‘|)g+"F*{94\2'$ګbAv՞8/qdJGJp{c ͸2F+hީdF2TQ,Sc:1插LJ>ڱw*@=f .mjH6#MZl#$=mT٢VK"mizZFT*Z{Rsx@[5j$)4ZEMY\oNFN\bH5[Ei둏gp(VOoWɫ7m'{iYwa>H?J- ?kIv[VjV w^V2fX狐 C~ܠ%4P许h}W݁4T5O*0uv^@ jGl.Fb ]P%TcQe Rb>+VL/d ŕlZ||ErraV>GD|ngcZXeCނFǤW؋fKo,Ιgy$RL5AJMvou6 /)*mcm/ro8d_wZJF$Ī]ی^l-7-jCx"t\HW?hu)#_rR-GY{>vHډGy \ݾ^}.Ӵ?Si7}fReSn&J3шx,Lha=:jWWppд}Ƭj!:.VEuf5%?9Nz4Z5`R!KmqV8xJ}pK0,o;%Dmxa2{к&u~`n.ּ.Z}yYu?~G]J eeu[0:T.bL fE8_<'.]aKwϲ=~iƼ潳Wd(h6bi~!_ >FLzOj0߼ gc$]$OY\# t2zjEZeMmx=̱C*\XH -\|,B&gpq4o zָfo&PNO=#S:h>>0g~H<(BBjr1T&'-*,2fp3*L3Ql"3 MLnLj/5`B<!n= ծ9RT-J8n(fp72TJ2F-hGI Bœ< 9-S:4Jd2%'m"KS?!nBX F(Y7IwӅ^ Y5SO/GUWs n]jGiBJ1t^ k4i"qU7sqV#i= V,Y8+ba۬F26Q^RX:U41 bcc yuZ Jb$eP`KK=/3&fsf2HTABYTh yOuciѵ^J5.m D5gnkR/ubh*M-UbUG-8ٕ${T.\\'-ic-6H<z6"KpGl y4j/`'м(Di[6(# <[ Oount;`vTwck1chDŕN-1N,aTUzb" #xo16^ESKsМ"_p8b3ܮFڱiJ {ww,UiCf6yMo<5Zʒ4rz_7,/rva;{U4K+4ώ*F 18zwpnfH8U'B{eia jXVsuýx}M?lRqX{~%i/r❶r:h BXwP3 Xw"0%ĈPw+~U`!@W1hyMH 3T)pvxx/PجN!Tr7h]/6XfoX^zW%p zMP \{u-}{ВgCbX+sy)AC#)rYi_ޘ#%xaYXmfGyyOYIyF/RUdC3?/@XGP}ۗg+So؜Gk=iiL;y9YY+5d2Ks9ч\U '7ٍC 8?O*%xW.##NՔ%VYszw!b cWx#"oMyy=YR8|RXV٫5⇅ }vۺz|U…}Р?{Y>KbXߙtp N:._S:픗'e Tc- "auW cF-g O1K'92?:EKcH:ָԞ8J=YFdz&[#dG+T U1֡qOs.|PP'{|og=5(ϙ)s+kk]lM[<R1gb_vWdw q(&p0q[%Ġ$UZąu"nXǨc{kMѵ; {W5H8}%`%0+"œ|cc4M;\J||35abz,?z,Ċe::#c]F%`t7q|@|5m,& Ӡ#C*`B Կف5{w=oplӳ'B㵆||]N=(U=="Gͅ\w9RRY =!^-ŧw/}2W_bW=$V:>'༛ B9S ~p"Li](w9蹴 a %F@k]:&ԁ9,Z(0lL Vzu)yNvnh>75D+S(wtߧUJ fVWdÛ_Yt?pkWσ_ Bhel=kƒ| Ŧc(LCrQ{e h,G1%U~"MAT_&6@IC-m_Ixy-ȓ _(L%+fpBeT]Ш\ \|hAvUW-TUbb:4Cay^H@U,~PՌpY~?@n #* әFԖ[X<N[j՜A'e:igQ^E2薎Yh}fTIh@竕ta4W֪S=kڭQ陝֓ ̀,IAScm/NqPQYVBi뺘psDβ=R,DlIzԖo^U*ZYS`jeLUg-CxZX! C*~|2,(D^+Sױ^쵰6|aeМd-զy)b7]V5͔aC`/$Gx/(Flѿ%SuEhwhm@-A~'"(^@+{SVvP,Et2X1CVAwN@^uezGOz5n8ir" LV'i8N#f_N2!Z޶] ~a1+=iD*%%kP"* ]2\dRqBg:/?"d7x "q./p}l='UӢe/R"г沶8Wr G>(l\LhǦ0}S[vDY*L ɿh)`ِB@=hc5O$E|GQĊ{"dB r6eu8)F1cV7)쳠'UِP"%w⢳z\@e4!ŹK8& DY e3%i4C>S\^6+:y@ \pˁ$ :[5l]R; 1}E" hwʪ3,IJV9qJ_2 M:-Qc]|yѽ,m@0ԢO!iKBҧz-ݐP*Ւ31WqUIA7 kk%Wҕ֑@@*,z͋ZW'I*U+85B55e<4`AKQ7|3Ŗ=;.9` c V[-w!@-̀b5dYb$]KW֓u=j0N'5YkDĀ'o{;4u]fP8²+ebXF!rSɢ~T"YI̢ >HJk5sjw_{a]$\̈ eF%)f>ay!siW91Fd|~?CsrapU~3QuSi1G]!yExN2Itv?g}t}__6#S9tw0ww|pNr"h]5sw&QOujׁrt>'e1,wd{PDQ2P/m!vv'nHGAR7q w_3v (r"Xd0gܴ4A}w B# Sх!Bx2OxdhGfXR7طEoE7oO{KA!Ag'V_7oNz?!}7ׄ'+nXR{h:'2}8vHGz}99lj<'1\ k棋tW%tXwj⨌1@ FT0'~MhD@8爐X'1vhŒb(&流;YX9wxx} X#$Y>2zȈ.e'TV=4!3V8Yc5io;i?pRiRywALٕaYO[bkɖLAdٖsiwYoLqxu闁yzJ|kIdUOyI Iəaiy)Iv9ɚyj{zysq pmhXjBZLO Lb*nZX g)Zv:I"ŪzSlI*Jq *QJ9!2ꭊ٢ ҭFsk*;jv5R#sh4):ޒz0t~^|uWnKKtqvt@^56P[kveh7bYk+TT huE^!Z*+-D:9O5+^ua]}}S+ȝۦ;1ۯzd@fn~ {^Y}qK[^zEhJ^Upr;#SG>k"{k&({h* .-jXFhny E⪸}ӵY[*R@ەBM3;K1{4Ѣ ~)BViך;kZYyқ0ۡ"heٽ KI{髾NʯˑZ˽[ ۹ټRۻzݲ;қ[l+,ԛ+ +,[<,L; *9x"H.{H 1R=&?AL[j;H<&JL;T,&V|X\5'Ʊ| +v'oի[vl"v,/+!e6} "so0M 5߫/*6޼hR eYDĮ ^:WW_.ڬkNn^ oN5" OmӨ:ԋG:P::JN/!#J%5_7/;nQ/&TO oOX>S9/Ub_1dO._i" Ij t;y.BDOP0 JO1t}oJc&K.r?րo]{o^"f}aKo4IFo}{\n{/ ?Ocخm_?o. /ޮ/.$p!.dC%NXE5nG! @I(`aJ1e>4`˔&2 "49QI.ez$ĢMf\f©Yּ5$ Gv,HViծe;CmVuyVݎ\:E %aĉ۾uWR]OW!ߎ`_PiDYǔE&]:"cFkW5b0op¯um' ܳ/gΥOJοASB藿_d}xK='fϧ;>*6@/[/d8 B;LkAp070K[t1%=q-: /${;Gmj1Y$I( !HҬhF+ôrJS+ Ͼ]A:T( ׸M0 ytQ@*TJq@901ɝl;OKj!U[}?H:SS[0/IWn!R;VpE/PAkڬDv[.Ueظ tUtZ6J jJAjx ecHcL% ȧ 7 ~%Yg܃ەNK`^nbuVxViMMFy dVmGLm[;Jg1S@{Wh24lKr]x)vQm?_̑W7ﴡZdTW\W,dqʥkrp_1@&,|BoHQ'uS秽7D3us7^)]e?~v@;[mz;ے ۏi|oNMl!_$_8<h ؑq)߂W{ EHF{ &HVP3+Aτ+d'#x~,SJH1nͼvb,tt2mA h":爈٠kg!>qQl B/= ɢ+Ex-0Thq9j$N'<pqω"G)CRHCQR4+j${Sɣ.[&9y xm|e-K݀2'vtaLi5Bj6jtcy)cIЦiFt\3ML8ɩ8si`'i9 v>Ed'AiCfsN'Gh?jޥBEP d^kn6QyTon3N9PT** #}8JQ:]k5֍HWuҷS qY_2VU9`A}@g[vmp[v,Qm5tJX0f"17caoފxB 3P ~pכjw}q aOhxR.ӬK,o7ebO X<"_9R|/|E9j ˟8؈,R"Oױq<1_z(Nw=SOrs=rW;^^3]1 'x/<~ 7W (/EzI 6A*a@zB8^.T3{A=ޣ~')~'x3Et=^ҮKb.|3 ;r˟}@'g3_}ϔ:cx;?<{79| <2 #X=hd Jl:#Uȱ@Ʃe R9x ߿m;C&ko `§F)ey ưu f ~ y fO:xl4fw y d y |X4IPn } t߼m4e 9uưPy HA Ç#JHŋ3jȱǏ CIɓ(9&T0˗0cʜI͛8s$P $!0H[ HjΧPJJիX78E#Ŏlx#XHHӬ.(`д-ܻ$h@.޿ iʌ$N8bIU;\n'W@͛CMaam.B]庲k7S%#TRDg+'v]~2S+Fqҵ݂h7#/|  ;h%YS)s|)=fTr'R%߁iaE $޷Aaz%vb-(h'8L͘ы:cm5w\hF&$^APF)fM~6XfMU.D""NdQ {fWom)Dhv9|9P_y]{ihY薉~'or襐6gv2Z|evZfj$J&:#%J": [٪%6)%V[I%vK @蠞 m}^mZ5.׾+ 0VZT5RK2Y q$Ȝ>!rJ(SqlsF1 7353E9=lCA7E4BJ2"X7oK+tOo[I~ bFVozifsv7Ix-> xȂFxq-co yeHy_>X2nιž zp遝b:`{W$ގm'372Y a =VCH}s5PB1@9b:Oc^ͽsOwg5^.~VbT#te6N?Y!jӘ e&E\ 0=ё m!WH\$*.́V#HD2eS:YO2S,!zSZK`)Z.9!%|Li('\/{_$&1dL ;\(Y+K~U3k̬%XeD9o`}y@?0SDN&@gS.~@ 0ω0ȜB=$s#}E PHtaۤ ; |Ptȅ!Lz.G BE'2sPNhUjӂSD<[ >%QM+Շd8FXmV <:PZd-+S/Vz @C׆@(V3t*#az=PPWHVume) 6Z$QjV0)d+2ZvF[[#WmfV*MI5Ġ-u[p?ZZA$vqruIۘ*N]jeض kcU6{ 0Tڪ*$DHk+v5Rnub:D踋]oA\T GeEԿ9ߗw*xenR޴![x#]E+d8.qU0Gx"&.2Me~6[I2`j1V!)8D6u~f(!tpN3dinh2YitYfr-!bKϚ.l#D.tB#HlV }ӭ25?țjqVl(6Jd{Tk^j:У5>"@Zaq;.vWe+x~@v x"iA}B2ڎW`}_7Όa_+dQp[AUʀސ ` ϸv)s(5A|T8-<@B_<$ ![֣A^fJDB5)ФB9|L=ڼŹBKMPpA/Ie/V?t: H=&Nħ|%A;x~=Ƹ8gp5Cvfhpltdۘ fU|*cǤ x@ԞGa/d~>{h@iM;";GO^4`_z }) 6~U{{v%'|!a|*QBgWh7``nV^-Eww`1uxBQ]7` {hw(|'y$!=W&d%P'Q~40Si+w%qDXqOe{Y%.QSGyvPL8|EMgSRrWyw&ZRSwz;lU TTQ_^/!W&4+w'"Q$(<׈Th}׷S4h+qn@l`Wm\PvQr$f1!mpDx"dr;&"xz6i˘tXZhS'6)ax2mrN7aT'w)W@#rrFAggx,-'zEЊ/ᄂwX\Mwl6:ux+AT\pq"|w҉+( Ӧo$ rX":)C4\iEQiʨa_V"(Z!yS9%\8esr…)uHˆ\tB.#xQ_w"I~y&A-oH2(yxhVc(7e_zvR#&PayCVb HL$Qeׁқ23as% kaROǑ.G92wwI 9a]e "P8S4xhgc͉Z2f9Y/asifȐ]jR(mi3՜iqHIe|YW09E[<*MxU3BQE>!P)< X٢r\Ij5^֜й!ki!ɝTyh(5&Q+1?Cd???$$N= Q C_e W1yՙy2Vsuy"G&GYA?4q@کOwzqHCרZS:ya[ UPsXI׬5]yU:ZB*䧑!EPIJ}!jgӇ^JPNYAb,z1Ja*6$Kdr#C%ȇW}UMYwQ#IA(僲Ai!r zɇY717'B'fQ(˙wAN$kcfU˥ Yk yٳaКPЊEm*DA sgHCZz}~+[y;]8)Nѕ .*6`^pjE\'>Xd:x!pf%PKᷕ_+kPKi1Xdѝ{лZ c>Bzhǫ؋:R[~պrNY kJXƻKjI+ 6)kfnz}!+۴zZĺWYvPbhg3k_0yPI\| W~;5X6l9 #\>{A|(l"B+\\HVG%W<ULXǛaf ƚŻ #[x%1[OqA6<PzY,Ȁ $&!ȋ۲=i B;lk\]qv!nR|Ū|!Yz|gȕoqѠ, ]Rَ[Ǝq߄N1再13`-n5a-]-㝨[ 9~^sA.-Aք='A1Yӌ=6^%̮ūN מL nZJW+؃,PX+jV6fŹFt6w`a2| Zz*ןwEou Td3p;Nly矯{M̼R ^XZnʛ1k+[ȵlf{qW|!(ޚh'tR<|f7w[y4OtyJ9[v[eIfqm+U]~>JeSӾY"$@do'Y5YmP2Spc)}bB"(9}km 9xp&D~R咜4Be]ǵ@? w99Wqc)Q!RLa\Hn&0`Ÿ׭ $GClٮ&,ZT>ad;48+e?"麘H1!4@}:ʇ ʋ4*&Xcc?NQ Y! +1XeD?0U6 G>rHuջQ$rL<s> &YVŴI_epN/LxT0B'&Z1B T2DPٺB$gƙЙgzѝq /(QmJl/Y͛!1N#LB2J %#@`X;繑pg:+եi2gDI:/Sm+%}TM:jG16^q xXj'ɡTM^K - :YeL FsҴe) ؙF瓙 BhG,U//#Jn4rm`s FBM+jX-A#&b)&mJ2SX}-$;Ut^JUZDTV*R-aٮ68l\&m?)vkWs* h̬g EdU+@WFBB[݆srmۈۇtExkV)I젺䦭|?kiE0Ԧak[zvt=-(1*^.akpaZla%צ?kÉ!+EܲҷC1d6x}`{yDf9ޫU^ !4ݷm6@@b(~REe.XkS$ƹ.4`a;:.dؚ \?eɣ,+Ha$M:lK}c6 `BA`!-wmذm e[`Cut'n#j%5^Sm,m,2y2&w t!969+ۖ]7C}CLi>/ɞ=jQܩi -uӨ,e(sN-w pi˥RBYpk D<8wF8{!j&W&gsI(06 >$T׼TqH۽wٳTN4Sj 77sq\фՙ:S[xLeLm׾Jmtȡho`'Jidb=5<ס坬կl!?Yև B$;O~hu`[w?C M+|i S`T t[# dLF-;|fKú')%pAz{2,u3r볉<ת&c]LUh2URG9$#UԳrSKT ZԻP+0kFCh%h#pRkp-Uź߉I%\Y Ş nbpq`Xacki3rH{-ʹk(VAz2QhFhiAjG}.0mȍmklS9iL鞁nlʼnnҖ\:ZiIΰ̏z6xۆb!f7č3HOTZL6( xk(#>`a onЮj/GB- 7CIY e#IOSOZWm2Ņ89 (Z&o  jc@&q޶} K(#nAq  Cc'!k7sSjp 9^άE+kЇDܚȯs8?sXKsm F@{4M?9O>$8 Omۈ"7K_@ nhR0Hg I% 3w$'Rt]Iϖ=􈘀 SNUUv&r7|p K=ab wtwPz8v @ScavNv(S? ͬ$a6M'xSAc(D 7/合pXtצVJ1c8u x.TxvnvE= n7v>! z/ĥCYj(xi/.J)ozݳ] xyzDS8yh{?T\7='A{p{g$Z nW`p{{ o7WGw7ҏ^|L 7T?xT|vKގ0iwXT8TX0: [@~xy^-rhvG}~7u F2trmogO}nv{w8x>(LJ" i``„ 2L8@6h"ƌ7r! D0`0CWl'w PxG H8ʗB]! H@9:H ! 80@ 79f b,eY΂[J) U@ \);teTZq+ZGz,zΞ'ZyȒ'q 2E$&aZ4l& $uTcӧ #p/a_{!Bp P^R E*#oP;Dqv .7CDJ )lv>@2%G0 C)^B$Qe~o9 UcE @G&飄 *@,Yb59F-WِYP1ܚy$|tzI=R<P%Ηk -8֗Pbrifb+:fZQX U)~CYH.#lhFR^롵V IpAZ@(˒]j*vj+Gg $Ԋei_ 0ڨ řֻ­ | ًzzQc|v rQ-0 4RIV[K[%c;-{["o`J-nɢyKkts,\3EDthBmb0HgtBDK+7ĥQWuy:K}WTQ$%=F dۄPM7K)JuC*6-:Ј,VLWډ+ݖe+9sd%֦{z{8^Qn.I{BJËTNVu;ФO/U5h N!9}(I˽v%I<- KUv0@YaZ#{" eR5y@T}.L[<,j[>X`l[ޫu{0 &SH⦦~@a +yW;aׂ1K]ԊƽΔa%|[ sD~]ol+J eK2Vv<կ  ]kqx 0 ٰDbHF03!լ c2^ˬaVt};7V9e=(wdKaBL[W7,Leg A/+sY3MEkSFó+\Lc$hd;z!zL]? #x֋|lʾl,7}kcqVJQy9C`r?j ٬mek׼#vc׳{井أo a_'1fyɮi Fpd L0MK+5[_adyBյ)D~B \̎k p=Y,[|EXVi1ӡލXʍܟUm$4IB_8ҩؚIU .Dٓ9ؓR2[`aNR PMˈf! J rdL v}ցa n_ME"aa5K~flb ]uY VD!xm!l7u JLA.N[% YVd" O$Z"x`)63bh2J"Q윆V0"X.!5`谡؝pNt}ؘ]3"C0j! $ EJ jaC &LdǨDeBJ=~d̬GIc D4F\q$m#5A$cd!S[BX|O,!QDL$I>G@``Jd ^UahKN_MG(yD!Z:DsUf#<f+ d"#Td])df1n:dJ'|+Lł7Uk 耆'aV)T݃~ 2 ΂扻f`JF%vlkk Gmd+}A`}MMV4Z*S"knK-+ "ɏɶGN"J.rtn*b۰bhaRZJ V%NP-m5gVD,J!0nzlUn&%.KdA7Nhdb eF 6ma&}6/goDK\h-P/>,,Mb&o\2|(")&_آ`bo+-A.ݦU ҶD>-@M-, i1E- ׌F>mNح@LnoB(g&ɛj0LD #g"Kl0orX.cD@0L0OP龱4$/[/B\Zg1|pp2Ӻ۪O.>1_c"q&\r؀~Kfe@4fn 'V%y!+o d3X "gp0KGD@Ʊ22DD} ~}@@D 2;)7JDp0c#;hp0=?/N/IX.t4GA/A/"JDgsG0lc4^ms%0N.tKVeŸgq0+r3 @ LAȴYtpNp` /OK'MP_eO0u\Y.;3k%sEY5JAI$4f]~2y_wKZݝ/ic&GdZ^GLS8C5E[/ׯ^5Vgb/j2.h[7DH{-𑤸GsnShlOWlm1W Ro߱Bl)_tGQ ꤸS\&#skNaV{K>n9@$%8/8_e9slq$C/8 96!*z3:ksyEFwOA'5ØОw;Pxs1nRkxWN3D予+D1cVzd>Ǔ.kЀbJ2!;sp@#R$:MK$Ž L mB|m2* XH JrH?ɺQA %s@LѸK,T+ T":ګ$-13UՃМkF qRRr\sF?I \ܑQU؎)Y]դ&(+P/֤ T>qBu=r\kĕ7Mbǝ Q<'=]z G}_]ޮhҷO[d9ObEiM}v'֔樅 &3.CsW֚8hUvH xYS'im|8GjigUn#XZ:[$nj"Rpr6F\_{%.KB1RsxL qKXܼ{ ]tt0Bqegȩ*Ь.sģGsSIZ7ӼaOw]fgri#z}Q?Io(Ƽ^|3"&`$+Ъ& lEMԷ }{' [Oj P4.X6eN Yp} ʄ! 0,P`5v- 0' yX->=$[Ĺd`O e7ExX^Bb0дDFhшl4-Y7P:j]W􈳊gCG$ɐ0C0@I=dc0yLl2e% J9g|R-A2$uIaќ5]jZ-[ O[ Y=4ƂveNTDE&4IXlo CYMЀDf6@[)dt'̄O(G!RN\Ltsυ$D^lAdF wҝ*Z$I$=ZR}2I)BK\ΥT 2SRZ08N2gPwLMqeKBU81cpO *:*[IF$ĤOe[vC4ڍ:dWryzښ5?M֣ Tp[K}m%HDӛմ"e[wYWR^Hm0SiuJ*FPu< πDEޔzV<㰜W:SM`j )D^tetȚzI}$Quf3#~Y&DZ%mI P1/!_g f @ H'E R2*60Zf&1&JHRDP r+?1$:1 qi\1tD\<hlOjRsh8s&E”,4+.r4c5VЌTU{4`Jd c`FzUd@a3${RϔѩBK J@6`Dq6&QdV& ,c|v'Ζ6i ^L |Z JM!ey%j,eeaU4~1RVl;pqoqjDumftZHOf=.0GD7x}r{m=vLpX1VvYkDbNrGQyADN'5$\vP+Ev+H+ 2c,wv75h ^XdE0WP~ v}eCV`Wt 8;,RXiN&7v^^81Vss&@n e.\+Ux8iXy/BQw-u~wYlD@W5r= /&5 kx>eցW%X+8YaSCY8/`ovV#5Bw8z3 dx$5hW%u%&Հp Wum=tMɍԓɤxUF2 Pxi]o2a,Ce$/7Ul̇|1y\R!%B}kJمH\֚E%%q-Sx|Y|3 “jMR^B9zrA a$8 Yb;H `4+j~7:џ)|( v >ZBy %QBt y3cVW@`#%(z$WZ: :|Pj'@wڝY7 BtOOpn#$E!Ֆ dh,:`fJ.iw'ZF~ ˢ}etzG[fl%YOopDu7TUt/5|zR/B"i(*ۛڒ(gF3۰H[U xjS`0zXwQ&qȁ$?dw(!nA `Oʦ% /3+f)[ٵD{ֻCNO M,Vx"^ [u[{,fIGA!u:ٵ[31{Y7cݻ*H«.!ƭ!(QaR׵S@[W=sN jt@ȘPʭ\!Q , +-VܲLNw T uą )%v2B#. ;"5=uJ]|w%m&"tl%LJSB3}ڝ0P%DbEHr?c]׫- @:1khv"vu@=7}W{1IJUjUZ~̯9¦CkMXyVp݇={ɯd~U> 鿅[[>v-LL$oo%N!/7b1ڣV[2 [ }ҶJ~&?2:%}ҷ;$jY=s]m_/mGF]۾ sow:z6E#:wkKGɃ% W]1IF]oֻѨ95?0_"<:4_ vg!/" <0… :|Ar @ B4X,ǂ .81eʕ C4fI<N I=0@P 0w6ъa&ЂJv Tt UhT,tG"MsUÉV9PᘞkpY7A{0em M AcS.de1СeZebN֗Jxedh)G k9\%iQňUPe X^. 1dgŪDBїa4I4%LӨ|zzJ`AhP "*嬜7xr ,.۴iG}b4}K:˛1~NU9욱Mk׶?xܝlzЄZ)dhXH R&t!-TFKLSV2t ܽIeoaPv5mwر!GkU-Zcf#rMAX?M3:_6yё)>(ݧP8q:O_ָ(3R}ސ1UZ4,kr^^;heOXk#;_=D%ZUuw:,4IB&G.ח̥J! h,0ć$ v;`C՛FXŏTO( AF<.ё峆a*;Ү!f{rKر1zY w;H}Yȫ.`B*d3hc?D-c`?B/B`:JĶ01$ `q[R$v.K&dA. Ȑ7Brrr@,HLDuz h"vg-oN<W~cn׹WddDKmE\2%['Y^j%i&Fr,BSx9zBeAϓ:ysbR1 8TY7(oחYT!lhFe6Jg ! UjI)Ua*Mf^bIXJ?5,J/*3*eIᨣL~+*_. i@<_Ӳ%I|ǒ;Tغl/IaB D Ӣ*^Q%#ʕȪ|ScK8B5)B( ׸G<B2WwmnP2, K@ ̗u{$\`Ninu5R>m *Op0y92B<0'$r?s;.%iX6C1or4F P٣ w!| _8zV 2eTYt˖F=`JVBܴKu*dBPDe*,M=X׭{b'vnx 7(yUee/֧#e_UQ;*2]m`~=.eYg,&Esu8=vdv,ժ5=/]E0-[! w!WN=YsPp֢NfY.!yD E0d6rNO{R^pC͓st џ9Ʒ WTsZ/(e,IC&7Hϗ:w=*[JӾ 9)Uz1.@Oj]0an\ e ! ֻYhp*$~!X4KE}<^,T ^MaN<1χ!WQ.dȒcyWQ.gVL~%Fw1Qbh4Qwip$QVZ' pJesmxUnT1 4 W{~02zr%kT}H|cWd{}(M@'-bv炏րgJA Ux* >*^sugiʙM S`*ڨjWjYJA@: ":Mhqayتj1ɥ0:)*7Z pj z07JWU|zgN۪OꥈȪ= < W:@*ʮ  zJխAj:4㚗:@4z:2Z[ !M*k 1 ++qS(0*,۲QJDc19 -`iaUZq寐YSF(zaL{ ]]q]F֟rZ$MzbUkGַ6aFy C{q+ б_{{aaFh["]ifh.O rJgPDVqP de1 ٹ:k {ҷKa5k:a[R*o:6e{ni+.VhfĈ;t{_jwZSq i;ۦ/;-܄l+a%kB\kK{,{ A+l7&|-L/:EQ}1` ",$ y2lM{H *JvL K ÆFœbA;:Ŏ7r*K?lxZw4l{Qy…{}-<,Pɇk{F<$m)lh,IʷʔZÄ< %ܼî\,\>,k R˭vZ;| lḥ ɤ-9K;؜|ɭ|Ʀlτl,dެ|\\ ll\κy:бZz M)^!¡ M }Œ,IӡjKL'}7?ݬA8vlԼ҇%9͜OQWS}Z;XI`==![^KԻ߉٪I꿰t9ZYÍ!+ )/q؃իZ ق1قJ؏@ -g]rkksWJMMڸC4*X$mջM}R{5llD7ڬ }va-d]m@Zvݕ{}]M񝗷MU߇#J4z̵h-﭅Τy~ kVKدy= %q{$2N4n5\D knF^˶jmMl&~ț_WYY-aZz6ddO3zf|gvyע݁% f惻˺;Х"=~ah P^gn+hЍ:h Z=Tj^l乾ľ^G .NW CD:Π&(^ɞ䠞] ީ:Nґn̎.^;J~:->o-lߐ  !(.ܦM& ^>4Ϫ܊/d[K7~m <$CQ>K/M ;0\ߚ`bo #1Ñ4ڄ.s/t^ln?;rS$ ]r/m g9:Cw/0/j~ #RMbQ볟_3[WĊZROٰ?) :Uү$_%ٿO mM$XA .d@@ %NXѢ  G!E AI@1T ͕9uOA|0PI.e\`͛GnWYiy|A!̚YU[ݴc9eqcA|4r\P tUn%O,be~9"ƬpJAٺjkΩU0ks?#I4:%AF@k)0IFܬ͵onfsIU{vw}׉~?ꦠ %?\4(s${= 'C>Q uͽ L;Dc 2KPƅRiqrHD< DHG1%'#+˂s̞s$TK1=Dr̓h7i*4S6'|sρTG PD?‫EMLR+UQ@%PJLKe9SVTScU75,O+=Ͳ*TV`4AUdLfB`rXSG:VgZ]?P{dV[rO[guJ"˕9 HWuyUT_,xanx#L!f9WacY HxxRPS#9X;o4-u䒃_$~Y T&pz_MwK}Iޖ}f{xy48߳+#&P^kȎ&㉱[V:yZMdUj4v%[),Xp_mZ&S {Q_aO u] EV%lOYJ7( 'w>2GP糯,zQ1X| {CҬk| }J+?F)s< 0j< h$Pp;4c=.a "Bo Y$Ap'0l AfBw 8"LJ_uȐ"QI"qL 3E0\!S@ ItQ cR\3\H/v΍{7UF zh $ E>&"p,`ȴ/EF2~#IIf򅔌 s?m'ld9%NHY)6L (JG%lhy:&w^_c"R3*Hg6la2WLXҎP1zS5L %ane蔠:SΡr1'=%i(O* >P,4X9!zяH2UQuMd8# jwHWRɜB/q#[R4^5CH%KKu=FF!G+*yIRƨѢJTGUX5!\)fԁ/b=6i֜Յj [BVr]bWz+_?MGܪaH YNc-;YDa k˒,tgni6Z؉M6]XkK>5V 9U&'_cq81pyҞ 29_%60ۙ3?[Zڲm͟Zok캽{>6b;u]͎/QӦ`vvCazz"VxZmi#{y2>PέoXHxۭ|>_p{V8M\( {͇{fYHE>wA8O\y}s]C'zэC aXN2>`ZӇW}:qdS"뜦 #eHA.u fm:°u]+]o;e! N`akPoHqC+S`Ƌp 3]L}x_<<ፖ!|a@'/7.Zeh4KOz8?r~ ?,?va>O8<>s̿8?=> ,< k cþPH9?`? ~A@<d< @8?<ā@=qS;K?ABk A`?c+s?A&d@MS c‰ +3 7`\A8@>;)l4\<$sC6C0c:;Ąx;#A F;&ĝA0 DD1ĸ@V C !,%22    . |*4 곴/ H`*Lx‡:QD -^8FX$F4Q@JAlReLQ|yΝ6 <(LC (*ͥ.!SW XCW $lODHɀ"X(@Ƃ@@A8@r/D@@d '9 !,*22$;BCM>?I ((401;67B!!-89DCDN56@++7 ,#FGQKLW00<H`*\x‡ :Hĉ^A=biQH&?,reʃH ̚(M葀ϝ,Hp2iTV 4@]L@V@;;% vV@\ %zI+`| hpq 88@q`@4@3 <X!@ -%x Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihliL'u՜XQD'($Oy.M@qFDY&FԠ&$TLUZjg{&5!,: !22𽽽$BCM>?I ((4KLW01;67B,,8ꨩCDN++7 ,FGQ00<12<@A  Pa &d8;T c VC$ %,G(L QgI4x (6Y с+  T`T aUԂN ~k@! -8|@v t XT! UA 2HP  pP"`, 02"J[h!,<r22db\)#kl˖ɚпiƗ aa-VqOmciЂ}r( *T: ŋ3$qqC^L0R\R, x0 ͛8m#Dj@H(t(΢S9A!ŦXh%Pװ79rXQ (=T -\6{SAo62M'ƒ##AE ,Sb_Bk_w(~]D_!`p@c:A V 4 !,111111111111..,,,,,,++++++++**))''''''&&'&+&:&v$""""!!! İǢɕɌLJ€ À  ~ | z x x x x x y z { | } ~~~ ~ ~ ~ ~ ~ ~~~~~TTTTTTTTTTTTTSQQQRR[bk m m m m m m m m m i KIIIF;6556?LOPQS S S QQ T ]rdjfggfgde]]VVVVVVSTRQ PL T< Y%^bfg]Q>! ! **/1/30303125. >(UadeeeeftJ{ ~ y }  %6GeºH*\ȰÇ#JHŋ3jȱǏ CII?N\ɲ˗0cʜI͛8ɳϟ@ JQ;*. Q+MʵWIcgVmڷp}v݈eJr-ֽ| L.߶KLYwpYc;MZgNj=]Ьc˖|yvWͰm3tm0~wdy􍼹sK]A^P9AHjO/лj㛼.'ϿKIb .HVjwf9h!{ ^QM 6aq8"p#h⡘4b8(ۍ>:#w<ih@А䓍% AL>X%eAH;Z\)hk#Ugі\Vܕp)љIX6!:1AQzyLi DI e꭮7'f+jAkjjۯ*,Du+h*;r,]M뭱ن+.{хb?(HnAI8/θ+lNŊW<8S*&dd *,JɌ{ >gqhǠ,0 1393[=[3att}:ZpS?RO=i[_^,K64mͳmܽ] , –;Mhvۈ?il>"Gn8l֗qc=֪ t6uo/x?;-.|c=ۓN~揩~گ]6OK )}kt t8(蕯C(*m6 ^~ C! iImc#L_LH?^5< Ex>VXhZ':xh1L\g?*62HM8 z:"󏁴ecTb:5才4Gюo#B&lcxF:r%|cX:-1Lg`e $II3yw3RWe"+UJ8Ɋ[ajFXҌ]}ʫSUOGd*r*5AH,M3$B 8MÐQL:0tVK:΄]#M$6穢z L%e)O~>ɟ89}D')Ym((TCS(7~jY*>Т.-)F|He %%iYтG>}Y豊'^41\#s92KD7&gƠB|;9vȂ8ʼnn2Kb6&=330Kx^H BSJ(L"-V,W &@6ȕ?dj/[nwnmi]atW_|5Ж7ȳT]+qwfpO/^FGΐP8tbsۛ^[viG5|δ7&ގȥFRqr@A hO ]"i 0Ǘ 8A }*DvP]FFv>kT0hݮtsot=wLGە$ >.|ub*"<vL>`}n lWOR]ɍHͷoxOpeoWo&~ҷpߕ}YW jFcglGwWlw{.Ry~]v07gtt8O h5y^,x$n<(}upAk\otIw%hq_'kk004qwkhtd(=HW'w{}w~|V+paJynwbqbwpfq3؉GdR8LJ+]|ևnn~Է\wH"iyaw|7|pщffxm17Z!xHjY6W 15ƋxH"ȖGlsUx 3l˱VX5u 荆k\h$ux9"e17md 3n-Vgب6 q8(wkydZj߶nER˥k&< D[!hkȏjP pȉph(a30mt~XtKIl}vX{ɗhv] wyZH\,9' "/~7 ŷmhn9ej  ѓb) ȉfrLiĕIG|x[_!_+ymdVsPkmi QUיthy˙pbr(ϧk)^8r8y!׆zՋXɇQ熵`9h9|(& iȉB)t:'o'u1HbGk5YcfwrYqm%*b$h*5)j&{6F[š  p;Zih)4ib0*2Zjb_2E:|)p56R0b[mvȩ cPJiw!j,^qeLƃW 9bz1qvtX?W29 Stz U~VH}Ia[bjY餠יi#Fh*g` kŗ[ 9cjӹ0,7{7-4Z٤8'٭Lj w©*c,ڢF:pi 5Yzj5H{9ɱzJ*T {fFݙΙx8Jh5J87q7.5kx 䞰Ů) K#w$ʂʯ!0AehZo۰ڲG1[y{qGJVHHpv`XثRXwJVjCbF|ֶJ;x`7#?;u˥]200Kkۡ!;+H,q#kCku'4[_yl+;p۳r˺[2u;2~ r8VZ#YamlҾ+^` pJVxafgO}qZ2˽11r z9#b;/6*_pfܟyrVíbM }4b~qg[5XXۖ˸`KH|$,@!( i^Ȫ±Cd,]i Z,s5PܗhHFǓ;T{ŧl}ƨ ē'&)CJ(`oʵ~! =d>Q} &G0\|J@leM@jp}ۀv=#]nǎyX~k$c uKJ9a6X\t[ʝ({IL[onFsbh-͉߅ml!'io+{ 鈾}ͶhэNد국A Gsm%Ż~a8kAɷi5n=؂{b^<:znɕ\W貾瀎<ަs('z!{K~ӍNd[ }^| N^ × ޮX'{ > vKNi/j B/t''Q Aa WbZ%!8nΉ>.n2G\vf*vo- }zj_ydς|N_^q2W-hWq+_n Sd~I)/ :BE!JvL}Ψ}eIԸwn .|țKY-k~y>u"%}5ϯs5QI yJ% 48`) )C%jŐ%;~iReȄJ(Y3D5mę3=}TВ8q/@I/#~1dUJHV4}$V*T14U$ٲ;r}Y&A mwpےs!ϨR(qD-u=YhҥMHc ~Oa,M6d&㒱3on\Њ Y$1|ǎ[+ew҉"TrC_-㮇I5I?s{b\#/H.I+)::>6Z?\ Ş*D3ޓFO3 b̢XO<0 U"7!K4d>%Î,& H3Hl[ \; iɜ J?`hԳO?ѿ|nB{ $;jJAүx+0 ώKH/] ԼŷO`Z7ɵn̬*ׂZHÒtR`.0E*ͷ t8 * 2Lús4_^go_S&rD%`!i5ҷG14Rv{٬,:ӖlWj밄֛9dVl PMF;?R\Ii\>Sz%ykŮ&SIqfsщ{jq$Xٸ/Iڥm";_tԐVu"g0;/ԖУMem$b:/f(1|Iuqw<1ə57W^ꐪ^'lzDLWFumvXV)ń)IxMn=%װ*lsH&_a;`:'to41߃D;5iIkh#%}(.0"\\ʾ6m84cqBE Q)#BB4&A ^ˋLU]C^2̐{{FIV{x!V$3%DQx`<ޮq%Nzɱ~zcGZϺ({\YMZO%x=!u"ʈT `*491\}Uŋ @,[Dst` 0B!F!#:io1`&~ǚ=;}@ 2 49XHE~ i1wvFhiW^gW)k͓՗tPڲ=OF Y$8\HoRli{EN.sk,h JM;GWW_*+K1C6 dѤMS27v*W[%eLm7jv8P;+gDbaEkZ|=-:h|!u7c3Rji(?B< ,=YPS1Ԓ=uF= 75ϥUlºKo%2븞 (G _^T2ah/f9Mo rdTU=Eכ|3WlkqZq-Z"cR;n)DjA %R[mA5ʧp|Sdc\y2ʮ5Ĥu"!sRמ %nǥ j E >"0עR$/˕l(_HWWq9ŋ1vʢVa_S'˫_bnl>[~(L8̋^XK]f^^: n;߸MMR/[>򬴠V' Yb*OsFO..\4_gb*l:[>Ͷw{YRQ㍵0z"\:o-զ:vYMdmoK/-i+k<mC%# k4.NEisMX@;ϵht lwj9ʨ:U~X_㾂J.˺"*9c;s;[$GӼc6 2뒄2  :Y+!h539 y:<2 C2 dڸ3<  BX0!AJ1AC" t#ژ7VLX XƘk7!A:EM"F;D?h@LEC ^ ƞ|4юzz> 2Fo2p4DKĎxAܣU<ro#Kx2<lKL(E=q'qԾKlIQ-6uS|H^U VQF YFL}S\)POPllA]/e&rO?q"#KD~|abٓچ`Yjܗ}.麎IZDLES5+dٛ`?ʶu!ZKUU5ګ%֬5}L\ AmtX׊JZMS e]UhWc=^=V9ml֗؄_yTb3LYȪ@ZP k:=QK5:m-ܥF?󿶝#%SEFUU4ԺU)j>\cڤH7m ,!aJ3.xK(uuXЎ*Ȁ [Crb&V?'^ST,c~[z)FS2f05v I>0Q=c%R@d*{G\dpzvdL W_QҌde|lbREf@fEX$2B\78E􋉈^ab&5eeV@i\dQÔE^l)-, N%JסR0<~rc~KWyvEwVCfdZƨE֒" p&玸# 1个2&k{ԂDh~͇v&3 :ωzF5Xiϒɡ6ʐ@( e9g^'cs .ț.4IQ#1E.~^H@8-3i葥}jf1jxdhFj!?f.0V&#,F\ΉAp[VYP(T.l ̑K`@kh MV뵾Ɍ+vfZkth mYi6{m?jm@k.˜ lf@T mk..lE8, /"͹1諞X4&mmng ɪn? &BN?x̦Oj&s>2h n fnU ۞jUg ] l޼∼Ģ!^K?3r>W#)%ߨu ̐ ➜0WЖqp5?23̰2@1::諸hj Wbo4rBAt_QEW>F GIItt()M/aqaA kJqL,2T?71GDqiO5[P6=#uN:1%ufIJ4ee?VS՞_g)am7 H5uq_rKn&uٕ`nڕwvqt?>} Yjv#ϖAWus|?DHbPr9cSrwdbAa[H 8.@I|a35ǁOdxXAO ?mDw7޻+UsAo7!I>=$n|ueh+,X罋-=ӯ#|sX}VDe Ap@_Qs҄ޅ5Vvwڂ7 J8#\x#GQO"q7_4V2FPD:MOd&yXYՆ]fQcWnuxx!.F&#X'DM<*?pcڗ`CXP0ZUGa6X~iArUill6}Tk*r',5C y7! U)eCqCCZ ™g+e)H!lg0t;+OMְ<1#Yl"0^{/G_~jqUYxLu P1"NY"W,%:D)U< Z1HMoO>Ϡ2TW$Z3 G=u^ |utU>5-#F?_m deXRkD[VX%Z BiYxm zPS]—kғ;wD?))3}? 61De'DƭUW`G>P3k=8J$u94f=!+r=qGtCS1Sʾ pd ;pQvr&*yބhd@S@^Az9$|fz\0}P8SS+R0SùASS_\ ]S$ TƓ&%jH'>AyA"+"fY/,GBpf$H N}b&J9YX$ R'Qw9C3&6Q%>+ȁ-״Y[xqfñFZba\?R rJeHGtW|pU Vk%פWV N)9BRw @631 !f~)a)>CdC FĞ5;H{E'@q&^EUa[iBw5\2!7|ʴ.jTs*_*= iADȰ]]D J~3,\JC=OW=H"fYA:FT)H&DAhi5!1i%*Q'E_"Н&["WOS_TWr2q#N;ny1iXzO5ed"IQ6nf/rJ/oחV Lq[Z,${AZSؽ&ۑ^gҹ. [`sE Z%Fڥv^'qG֪5j{QFy .];Pæ]lA(aT uGF`ղH}#38)Rq$O aFo1g"1nqH[JrKb׶|*v˴z1ŗ3Y+3Q> ܛ)4"-AKA TIij]i5W7S-a xgfeK/g=ϔ& S$Jhlh0$=)! ZBz$.)lw|utAays&teВaI|0p;K2kD}***Z?P4TM) o9h4`E 텙$QBAY֍YFA-Psx뚟m6=1ľ@4Lߡڳ] 8vHkfIF6-l5eH.ݡc3!$KK)5F6B)Az!N.*FdQ eLQFͮ) aH#I(nWrU^eKasud`~J+GUX UAl-]F"n%9#$eѴ5%]5feT.}de WWl+a rD,BVfC:9O"gd\.\&+q&$W$T6M?T{ l~m~m K>qeNTDrn$'9>h]veFRZJ~gxHޟz@?@MMcH|E:g: #@#\'~IԣVhv2vnh妳5h-GrH iQ(܁B02BR,oAt%ӊDȈiD{pjB$Li nl*~hzj~hZEbNmԂ݄7&ٖ*-AF>mHB })"B+r۶B\b+A6-U)}ƶX "flrB.nkbm,&dmݎA~_iLFaT[Z>:^Ub w6FَmٞmZmksnD:NWqo&,<^d8.t&˺@0'-Dz{ƮD.JꩌBoL2v!(+L/1pm(F h cZpvw'mpYk_q1meL3֪1gDG̭\hh)2ᢚn1@l!N Y ;g2ourcj HD(q"D.xUf(oRqzl#ﲈ%P'N2./E1+0BX2˟42.K}#Vr,{r:掩J#߆.{VC;gk`;Y<[/h=CIUI,d)UmOL@I┊ȝgv.m'3hNSxQv H>'̦)sfSoDJsV 6p@êL{ވ{60ÝuǦScF.޳Gk8kϕXrrAspN iM3}XiA㊎Z09kFkQ]R;a2mRNL3b_'Bw2,a Jw3NsҊMI'c[(1cvf_oSTE eϗUklw`YLjbд"vVFuqwe*.g4q#3Jw“LbuS4f簰4Xx+Yo/FvyTew{r|۵j~U_uw[nskw)RiN5tv22_b' ]ԯW;qfTcȒ+kx{s9v4 g+ ZN<_|<=A*ZRz\Ц6vFs |*6E G/{9 ׺cdF1,S*m37}G}MTK˿6`<|(ZzF=mqwIm;gNxz;:'w<·g$\Ti *yDQ\(;rZ7>^Qlu\ӄқdl;bTwHh9l)ɸ~VEKǾXDk#;At>4f0E?G0K_s||A8{~@Ǘa%N% f җ ƄG2c/39fM7qYRgO?:&f0rf 0"D&8^TJhD?2Ǎ&ez+F}Y0r|seSBz_ʭɑiۧID =U5a=Q#9PMLS58tJ4 3RqoK=sV8͈׻2B7N;GJ1y3u5@W`]VXZ26Y±AiUSkRP$gҡr+M@7ÎUygZMS=1y`Ualjhy>/+FlSE5=R:mersN]kיU?9ݎMheGj&c&>08vPTͨ[\ejػDzYr#օ_ӅśVi.{Tڔn`wUgZWZ]wo#bKɋ:ws\a-GH%G7ӵ>'Eu7iѥd+r'?NoC o[U?TUB|g\F+y4ca>8RXl7R"NHR7c&_8r3/{h0?yY8GB44lk!I@ !#G>ȫ4+&KP3BF!cꂵ9W=ywa< 0#HġQr|K%F6`Ү>/:D@™+Eѯ]$ t7A_OJQvj*(H a©҄KC󸖁QUb$֔ B!#Rĉ3#jD|\MxfRk-ƵwPP`$XgEʚ^ wg4I hN3xIk"&7j7BEy3+gv.)agv13=RTQ'Mℎ3Av T$i"dtJ ^J13ٵ^sTSYU>s)BhRDoi}"u("N[E ŽdOU_L*$_IQܫ:˲ޤYrJ4#.ݼ1!u%]r Ac}MS7-Ube&8c𞍭эNZ'%n0-e ؆.#1SDiIC)rC_a97e`rUA/okRQJN"%ZݏI+CE&ǯnXm6ᝯKw/ics7uFۉw[cTiɲsT d821W9_q}|Vsdh T 1>myXb(=H[ wif Cy9edk_FP~7f9-e Fοô9F;O; 4Bqg&˲_%IK#PT6ay"nHUzX]晾{N5V\a^`X#ԮY _&.A' ](G^v; 4}m)%Q\^q^[sqyg}u&'P7bYߺMK '[[@n匜O-hu q0Y"ZؽH?ǫ 20i(ɹD?_kbG~4_΅g]u}.DzL:A7u-k}úSGCkzoM-A)CtKcP8NUK=x{od}RΚѡĢxWNQm&Լٌ>H*=@moak3tn>Ί5سxه'g ]6<=Pjh=enP[  +/0j>O,OUnyFς(#@AԚo>RO~P`PZHr&.&t)  Fٜͼ JGpÒXնϤVER#p֊PP܉@>o P5*:D .[`r0/ .% }> 32lP %%/9[#+$Np} iN"𑆮?Hmk֚Z /gaN1P]VŰPx8NŎp.PB ݰϏ;$vHEܼ,CBBh!zl7HD| oȩJo֑,Q>b:#{1&1з+) 5p!Q p*"`nO80W $"%E$c1{1,i1'&(~ѼQ 'i$4XZ2e-r#!rx\l㘯Gr'$φ;Q r,Dr~QJF#.GR!r)*. HƗn&IRp'(pje>#F&4sQhC.RM6)dj5'D*|"116k'0\` -9r(Dz~3*DRZ9AD)g)S6{;QsbR:у7ґ&"3PnSNp.v4SF[@.Gf }Q;*dOl!r+/qr-ّ;{RK@Qpx#<$==A ٳB+HtC&e0.K?4E2ERX)]oACAuT.G+t4I/F0n &]3046rQIspu(ЋLHe2zGA2Gi/"sƔ<9ʮHCO4H@tP4mXO5jH)Nk%?ӓ6q w+*)u1BuOrSG~RrhQonp'=y.4R TFBCkG 갲AnY+yrN5V*T yF<YS(=UZ5GBZ0:,3HT9RHN>4Jtb2USU?jU昮aUGkuUtP+͖9 $%CPB'-6X6?I]5fNrg^yi$QUAF3ÉFpZtIǸC=J*+uf3b/{(7 Xc4{Vcְcg h-p>noH׳Ӣ3Et|6U\ Lp BWMgUDjbIWXxl,mT„m&%Gi!^&ss~jq  zw"w5joĕ25d8i˪`L"_S26hCv CvJ0R9u\3ײD! p}~xSkDht}vzQU_ !K7NnnD"+&wqM cK)W~W7Wfrw-#F-^5tEj'*۷5;Ԯ[&vM%|!x>x׉G8}M5E[HoԅCbB@^uBy8vTGqDtQz |k'Ru~4V-J8U5U. %*4Î'XL"Hle3!gwv=xwMُ84NEDofy]ϣ/hK3*o7?hדl !K†1s>֗}͘r#@qqqqUyS=uVJt=9k8}#9!CW[TT2m{7pyޕքXyYZxC=h:"[{8bxẒ!m-5XiՑUe<TU" m}/iX72x0_Z'QZ5ĚYvw d:nP9fѝZCmizH[YSpEz+6dY14sQuY-Z+XVMYr"p(ڤ[Q<VI BI/P*崮zrX:XK8-O3l'{340Z'Eq%ZeBEnEy%k 1iK3?ڶpئt+gwsZ۱1 d@:Yp;1cBI{u8g[00{z:}bK:urW̒0G;XH!ٲ۔Y÷5&Sj[-"'כIs5,|*re_'c-q:rQk#V>7aɁ}5$Ih2V\cχ1@+8[E\d6X#Et 4hzZ5 "e\I |$6#_? ȳË /hZAMÒ弽6:^&Uu~(Tf01]O^>lhy5}%>Gm5D WP*`~uG-ҳ<Buvcg??"D?h80J &DXa/?*~y#aC#N5n(! oHqG4k1&,0LK0Ky"s6Bk_i#5(ZGNť-Z/ꍕEIZ. ?)`j/d= d mv(nK[QF!JTj+YՈ Z_P !k(ww^@[ 囗s(#.[no2ޱ z2KPۊ򦷫;5JT#>I/$H o;8hx0ąmjmڷPcOrZW9[qmc#21H] 4+ji𷴉G'1qk\bƊ/ Vȕy).dU>lωYqD:mCY\d 6É`D__F4n V$XlsCϾ@g@Y R2n+FrvF$JC  acrq]I2 fGsG roܭ@FmN~nakAK۴6ju[!?J y#GJy6əY{ N l`iBPM~%)jX٤RwK^(E8 $n2ϱ~iJE, %Y`[o %^x{,MSy/!EI4cW}nWm8%w ^ EͼܦCӆSU7ZFW9vZrqcj5{vYr+Wkk\ 1CK4s1K9LSyN}+kWD+;%#E7Iۜ6{tú٢5yTr/ͽ .Mߺ\\-hQ+z$# u#iC3"4Y6k)v ~3D1,Iz"N4)*mD1+d8~cٚxU_rU'Dm蒞!VB[VF-x];VV{L9fјAtA/BVgdA֙iL5^iO;R7.g9uVbym]Qi;6fiiw VyDr?))q>rifQx!{ysH]SJ "Ta샡'!B?ʹyUfǢ^шd|a i )c4]\>9!d~,1`*z~Wٍ+]ZI5XT<`Bkrgs\#:'rpf.V |Szy MV|ڧ :P(ye-jltjnjySmxɪg&7od$CJLyO9v+nǛwi ԰:]*&t¡b?y=cg ܚ7 ڧ:QMsw'[a&JQ;$SЊ!z# Al؆c2f2ڭ{ Ԁ!WZ kgL *yڪLsf9kՉ^j}%kC{'EkuhP8KکHfHzMjD 4%b٫`3J-NςJ9<[c:ja#<۸c|ԕ9Ky@OP  kjas+[˵iѺ a ӫ6יZ&qĻ7`W _P2_#:Z fѺLI$dE{rk{l02j1RK !ܠ)\[8٧0|G?;\ ztN Z.\FV7OS> ;T "ŢŴa7+[ ]|w_g`LzloT:m Vy, ǟw[v,Ãȹtŀ,ɏlɔR}zȋI'> ` 扼 l/Tʽhz-Fe MEؿ޸dPҚ^鍉]lֽV1 0 ߅e ղZ$oHߜ6x^ݵ}ނI]гm HfN} N[(*f,ߦ46d8~}؜=&-ߔJݧ GQME>&^XINzKX A].H^mfO>Q.k~l`w. 0-S~d:~}v~wbaXDjξ^wN^Ort~tM˭}mĔt^̆m֣ $~tN[˿|قMZ\~qžȶ.Ӑ{ꌫoh~}Rz9x)Q%n ﮮԎD썬庎m=.|ǾsZ| ~l~z=^켬セټ0-%//9i;_=o.C<>_DiFH>BX=MOd_V_ldZ?MxXjrctN ?;xNMHJoa]a`ȓa\[~@oȨO^Koɴ^ylK8fḦ́5VXĖ [$ڮo/oHImO5aP$XA .dC%NXE5n#DY`IH@Vb%ˏ1eΤIЏc  E~**(5.eU3][6ZuN+EY%L@9Vʅ/Vۈ<}Kgp4@|GĪ5al @H["V\ٲL @fΞ \@Ra6]X2[ֱ|4ooS^͝;9R qB\xG_:,Ӯm_|x'gO/ĒppAcA˜4H@ /pD$A E8>3R^k*fTO&nFA&l~F[\O7p!M;r>o;)srLCZ_U3|v惘p[t{LP؝!]㓯buN=kw,: v{^ٰc|?z1׭͡5}Dy0qv ?-4srg@AP ) kf:HA)Yp0AO^$% _Vt SAE*_v?~/KLA&-SL\U " 4DN[V q1+a GF0Rc$` o]{ 9^Jv!JE>vϏe_6>"o{t" .3 >F>$6NbW(UJRGgIW i!6+˥HbΗ4H&R,/Rg.IO1!(KR!;d7cR3ZGx#w_<:W΂8'5Y%>XЅTk %-1J&(:TfjFQ}4Cu Ohҗg*)d2M!{f:5.Kz!*9ϧڪMujTS2<ZT "p[fDzVW5*3I49]+Ӱ2>l7ZְUe]MP:5G':'+E1g* L/*fY}v@W[UZ: S4ɹ6m_ChﵺݭD81pf(g}htǵ D g+ZWfZ{PA va{ûX"Fz.% {@JF7:1bBm}C`,j6Ӯ cM3iC`u;]3&`WW8^1|Ź ,ce_d`b{̵vɹiaEYcS_0 +[XͥsLjɋC66Ξ3UۨrYs䪒-tѯl2IOEoؼ|;fZ*t\HF桢u9`6[mN x@͓ b[>Mk _s6T_MҴFEٱK2V{:AfRo֖&#uj{QwC:\!-v|i^"8N-ײۍC7>]vJ 7?]Qg+ig=IU5u2~87;EY|m'KUu*P.7TL{uP{W o!RhFCDԔd^?I̽BCM ب67BGHS&&2,,8))5곴++7)KLW00<121"8fBtL0BԞnj3bc$-Z \q Lݼ8h.N0 $B !,g 22>?IBCM ب67BGHS&&2,,8$))5곴56@++7)󔕘KLW00D8< 37150404/4/3/3/00+1'2"/,(      'Dl9LPQQPF85546BHIIIJLOPPPPQRTTTTTTTTTTTTTTTTTTTTTUX[^aehk l m m m m m m m m m m m m m m n n r v {  !""%@~۽Ա͢ۻ}Ryx x x x y y z z { { z z z z z z z { | ~~~~ ~ ~~~~ ~[H*\ȰÇ#JHŋ3jȱǏ CI"\ɲ˗0cʜI͛8W8Û2xcPeΣH*]ʴӧP-.L(*kL)< dC+Ng($Ƭ۷p . (Aro+V [0ѪMxǐ#n zf.Xgǖc`hEXі=uڗfFhetͩ{pR$9*jt}N *!y2*)q8):z"l^)kF 9!ZA2ꫴ—Rfgk*l*n됱F+,9fmZT dnk*+u[ѷ6@ hB.E^Yo[ ;Q/Aˈqkj] c :,P-xhc\뙜1wц4_+/ Aą)3;CDpGCKt&KFG}U-}lEPldl?"t]llfvO,w |Pn95)]Yz~4nbאO+@{ -;/Y ى7^3C/vq֭k?.y{CO?yL^t`UM&:ɋ{7!?;}t`:Ocnjٰ…\k'-.XNvy2A08҂l6 4EAtysuNwUYwBqE=laԬ sFąUH܎&*䉪vHEY1!X/"$dLbƃSZ(6tKR<:ˎ=V3G?f a &C2VW_S9re=5ʤ@6yN:瓠\([@I8LeVJI8eh XItcN\~gGPѶ}F\9ap'8.Uw6S[&<.$i{,׵^MsҬĩ-f@qys^-uѩ7sNy]D\aFOzYavVҗrY2gg^ixl֢H /xX=k7[?Rޥ|-sٕ# "}>̟䝢?Gup/o5a/ɞk;gz܇+L- ]pӷG7W 7f} Ghsw|zQQr3u ,؂m-xgm,uG3y˖zigv6|1H .(z *3&H|ф.zp_Ɩy҇cQj`-@~xx̖ŷx+؄wfgFh08"YEvXJ{W,p s2 o Ȇzo|' x_h~'FXUŔ\X`8rf9({,XrVotx|GojȅFh Yu8Jo[(ׅ "hSm/w6xh}g^xBp&QHiTRI)xÄ- H ksV{*IjIAqCi7| }{XIt}( |@3Ďi0xy3iGs:7ksdxI9M!=~< jW hc|])QJEQ9JaVo&ɕub"c xȊoL1hzс7Y3fEi69ItIوiHi- w(cC癑rhc){lPX^8t֩;9y q4QOƈYYoWky&}-P} w)l@o4tgyk1 vg )iWIjP b8& pH 6栙i`BqF i+ XZ( |i'D <fI;k)_p?Gwg 7IƤѥ9[U,4jiЌ+|/k/z|٦>zjEH#煙yGLwV!1 Z1|f eڏzҙQxډ ֝F{ߗ둉z?A2HZ+;ӸZ}7˵c;D:k%)fKn{Yܡ5?s37@ [?K$Ⱦ{2Hd}nkƚ78;Z~bJh~7(tyh+ØۘݻĐ!Q $\ wJQ5n% -凙Rg"kE`+|jl|g <ںOq;u9tC}xҷ ᰂk,hc Kkظuz7~^qtV|,)}tó5DCy+)&'Z$^L[iIq2|8Wk+凼]LyvLbZʬź콯ڭ)1 .jq, lʴ6V~\k;je^xqyskajˉͭnTr}8 -G  \õ\PBLw{x[:ԝ#}q)ZȌ 5˘Yjls*| =اn sqʮѦD}2TO5lXӝ調8l> sM? Lqq2 ȹ W|Km݅~=n#I+'^g}G vSXYvRzA`9VիN%g f.NLؖ>X^qmQV 52߮,)ĵ= ^^n=Ğ||"G$Mn<m1INT{Qc8$,)}vq>zh6hOn A8o}jF;OiҎPwQ㫣 wa ^:>?qQD-^P !|8STMF#yiRJS5\T2#lQ͙b&2(tʡ!霔'ӖU|D$DTXhdɓ 6" ϢPֲi*2f]wl_ FXߍ֌X)?\46`#58hl =MɜQ2 :4Lƽ5I e{6(i$MLwq܂r37v^xwxrui{%d RO㷝ϲZ$&;2lM;* DI%и,c(3<-# 3z6:qA[N1^̫lJ D^k(Ji?T-H:I&I؆J܌L% !RI,.LZ`mĖZKL2bLlF;*3DB*{ tR.qB!%=|lKOBK%B! 3}(6Le1$:LUݺGּВ|N 1=w6X|5HXT5QE!tTVJT)4p6T/4SoHdYpZxNZ-vUu֪^_;%Y4#5q;&ظnR4 !IMUSف[ WKTZed.gGP"~-b9 g_,x\XaJrU C f`ӝtW[h?hzcFYJΕg*ƻoaU.U\sLm\sv%l)P0dm$JSRWc^x2' ^WU-ʼ"Wd)0g}OjRum !Sf}${C?]föKjvgsnG}hJ};7Z4|>&A$EHa )m fu>nsAwЄCġe6̕TZؐ-f@o9PxIZ0ydBVWVdSN8Z[CRhc)RLU$s`1uqUsYv='mR0⭋Ub#%i16pG@6zQ7 JCESCDs! B)*8=%e+"܉ZIb0I'LTGtM0"ʄ#=i,ęxiaь6` ̗,f;O8L$%} dw@ 3#yQ 7 4D2&B7JDfӛ-8UBZB$&ϐv2 mjF"j뤗8!Ćf@gZ.?-@.=䔠XT91F]y#Pߦ 8J]2:6YQ]MTШ+G7mbWuQ-V*f; ,zvhS iPNk2itvZ"ʒ&o[uS]hƤ|Qf6yZvL C 1^UlwYC: sunJ-ĻZ*j;Z!X6`sCfU…z(0 N$aibٯӮ i`j&)F'}=c Y"C M`3>+v1S⾺)[̧Sn[{ RA F(l+=焒 _Oȁ̧j¦SƂ5b屄Q!쮈s4yLnr`cZytMA:KL.T ez?<2OKM5[ v 5Sh=~딵2Xzdq=9XC??C}@ ꋷucF>C'k[0' ѷ3\U<D>lSB?PSWٚ L B,8[*J$2j6gBIķ#߳A;T|* <Ϩ6C|<`'=jX ٻ;;E"H!#{,lIMJ J *=Zh_д5%`z]Z eٟ}$-M-J=MIP| % @߽ ԺO_zً<1(Vh'ȃ)~b+Vi!Y$dھI^'T=Ks+u()ō hOhdȭPczQCb> > bDnEbtC/6?A_͒e5AQze㌜_e lǘ#c!2O 1J'΃bb/<eb\\bxD^d~Iȳ~²6aZ]g- :blLdY7k: >Qf|lˈV@T(Bb-.{>ibK'l>F`Y0A/Te26[Y=& 9G6.|ng%ʭ#> DX XXhnRe !E & ql@ zoqfߥ\n̶oF}LejԳ:{޿ O< ptn{˜JMbAnHƑpq,]uݨ}oZYGE >oXf߁\]q_Jn ݎh8mN9L6>=yB߷CUxEgFsja&mvpest#tD5`d6ATD@q!CPu {!2`< 9vZjeƣPn@W2:'dvDV?N&7ja J/ scWupt*Ut 'vHDB q@wSLW迸JKGpqpdbW/ҟ D4GxxTJ=8yshI.x4Gy/H7GFRFaֺx\H-Og$Z`RGr?&Dګz]Fje ":o?s畠ꁗ{"_ 6|O1U7wv<'gǷ_UuA̧\՗wNuBT%<4e|+Py/$X{7:`w4D|ӊX'}Ļ}6˷rh-,h ƒ2l!Ĉ'Rh11Rq#ȋ"G\cASШ⨒eAa"L䣕u9qT6ibRL:uDL'~BJIɾ$-ܸr' [pݼzqOHU8EB-p$IZY)U4Ch;ne\,Jc]w7]x/n_T,e.2\3ҧ_&xXbwv]Ԅ%"zzՁ&U?S5fs(W]z w \*`^x=Y*TUyYQvqW#QyVSA JK0ԚN$4!EYPy-x$MnD:9$Ye/8uaeH[~!gaZOQT6H - a^U VlRN9hqIڵ$2a"** qxӇNmv_fbD(Cd'onyK`e}` ҫ(: :,Ci!dPj*&bA&Cf*f|svkY撊?֯r;/n~;P"I{ݴ EzpBSTAKnBIʟˆa{_ǹڙ#K )_To\2D0s|!?a*h}|=_;ު-^5$I+]~K;VEh6{p5n(MP'T?S\ kV%u%TjŴNU9r,`~'k[ns7>rR}A1w8^*0NzjJj uWsbſ<"S w,i@ qyH-ظ}.IMyWZOͻdORYBYM1daɮQ=.ᣝbW`6<\LwAM L7~"Dg wM#CT&9DƑap2aNJӴ"HL^6k[SXf@ bne,$ *KGOi ŋH1v0ĸԠgশpdlHFƁdsMu$^"}‡|Ԕv-Ci%a[t b@A@p|AI:jx \eK)[ MMR}cP&FY ?\g;sy']7[L4R\lV:FM}Hd>˜ӝ#i9IM-pe(3Fʈ \H.$B*MUKyp\2 5s >֞5d&jBT;:яIMvRҰ:@h}"M3:I*|\s٬ {tgMq< <)d(HκlX…(9O;,pm0“I(61.>y#vB[$ !7 $hyweÈխD}lڏ#BFzR2xiEk2)h,^'Cњ%J `ΌQĖ :;-a#iTa.(Ya[Z͖]YEiOctka>w 9@;;DB=77{?}WE|CĐCLş= U\'q 4q$nTDsKK"5EY `( ^ `qQY us)^A\!9Cu5!"!!ʇTDv߿4ު ~>:r_  6!E\mLm$ڡNS>T&"!2 U("n]9!*EQ\DamY`!-Q@Zj/!L\5E!"D"9_>b3Dn5I["RBLAx#1&Εn!y[a"I)o0Ac=Uc5;p[bUa="EA4-"$3A9X1"ޔA4)<"D2cCУI>DLٷ `@,N7bd6"'X0WE4Zb壼lBxda$j@t^UVORcEh$]$ d-XD'_&[P6T~=a4" RR  4R`EWü#U $],""1$$M"P*H[`FX]]Y^SJZcgTb%i}+9ᕽUDcPM`LV&Q"I[>:rf;wci\fD0=E=L!;Vcn.$uD&Y^fBdS߿XZZĐ5&i'b2}'V']Y^`'D# f^HmNxVB]cdFf#ݟg+>qnH:_+)g<6hQ@tq]>a9gVcgaн_Ƨ:gWrFd!y7NUg"Hz7gǵmX `dލ@f'f6}"W sh:I@ez…xC؅@HeWݩzDd2~t(ȕJ +Y>9~:I.Ei;)BDcAO^ޑ&3Z\@`ho((Dݬ:i2jį6 P6زļ"D4+jHD{@k}盜ZԸM+]NѮjkB0l)]+BTkC4+YF+٥Biŧ u+Wݠrbt6'+B쭞Ů\hY *\Llb%bC4,LZ~zD*:jV} O2-C8- -Dl8|ͨю^eDr\*R.(+՞la L)",׮cZ^,4i)ijϒ] mFuY--\ Aj\:nCy>a&6n.iX~Lk,W-znJŜhj.zXZ "._).x-vRL]Xh'r.$-*QzMuj%>ަ`v[C֓Idziר:pZ6HڜFRnl(HZ5p>HoAaǶ9`yo/p.Eo  6I* DOqQX.AtE=f]DDm߱4kQST=)olo(hv+>2nIR&ģf'-Vp:V[Dp eb~NpQ&uĕ'míDZ{'E(C箌2qY^,#r7#oDr.I*-;v4W)5crq/!!51SlFD ge$88 @ 0rҰ<n@׮s^SsEȱ3?o+K%1qs38k-E[䴜z҉f&92%-"II3J',L+DL#qE#,HL[ɴX/"%H.t:STK$.t ڌtbA1]_rѕZ'J0ÖNl1r=lstR+?&:+bO3 Wݡ&)[G_w86*sp!v1nKn ֝HGR>DN5c64uu~%C gkZ;H<˘"hPqXr3وB1w 76qC1"7'ۢecSAe!3˂ F4)2X8z*5hSuU8{ ~7_7聋wOuaGPuf[Rs\i)Vv_z7$Q/Vus5szxu~D8뎗5!8m_y֞p˸>xۉZxR&WCWdvǒ7u 9qv)qGKZ\9+xy7}7~w{rO# _D_-u08P"Y4yq UEUl?h5}5!hov `'Pew'q렛H8>dןyϺc8\_+z;Yl-B`ØG18̸FC(v8E,=9A$VÕ^wvHo#z$(65>_UF9sEK9sMo7uzhj7FUyk¼/з#[4C'ToSE{г:N4/tuHH\ :OhtpFyw1z3~j=8jHڇׇ؇=BQOM~E㱿m4K5HHjS=bD86cHHy=hs;?n5=@o[C!B6 f<#C~,dCKTeK-1l@fM7qԹsC0TIk\9t('B{J]xBghTQ`QKRMЏY< +AM95.\#QG.&-^Ys滙KUiv=ti>"횒?+&&Vi,x$\_fDڸWEq``ȗlyQ}ho)5G4~%֯+gyk ۈ3>g׿_#Ir ՔzK&.xzO~KKNls,1?o/<qҗ!. -pe(7u\ 6&p-?&11;SI*^3=qoȢY/tPuz`{vIB!dBhhJ$C1rQ$ȆC%;8 Řsڨx)MQVL\9-[z'vHJ&6ހst'BhIEqc_nD%fpdFPxd5rGyRh4umdg8}&|gjWqG}O(PJ)djt'"IkZlh#GwQLQ3Ap_aE]'2XVD)I'Rh!'T1M̥ثeYE1l7L%Z|K] ]SBnYɯ%\A[v.a-Z{J+$#jU~z[ֺZ5 cփaq Vv GPʊ%`a {\tdBMגNgyR~-P[!+il ^^Zլ` [)~eHܗpW>|v}iJ4ͼɪ-E$*f}T3 -˖լ E^V}$n&l^y #*T7^CL/W+R\՘b7VrǕU% XEr[&#^+as%.#zX`/]ْúiC3_O66z댺"gkt#%tT+_ b^JD9^3FI`·j!6 9t~-/!e!}8"W!-#jZ!1V#v܍c/US+dRkRwWaam檖Gf8X=%=Hڒ<5Ϛ#%V< f#j=%ƶmfavfms!9~}NBAv4GXMd&'װK4nzm X1uNpЄ=iv5I^&Y;jlTf궦pSm|u)ZTe Z%9'-tIZ#Wql˗:W]#p2PY;?8bνTnǟ/߽~xnzG>8}.]&aj_d ~pd}|Ƚu0C=8i2]hek&mj=MfȯRڏR/(c7,Ď$"Tm c庋=چwhVCtvlJ0Y-:t0OB$"CL C^O ?CxP-h"d )KJ4"4 q?5$дDΘZzb ` ^)=ޤxs* !$0EV)JaZ;HPJqDf^ QI9/;‚.kǛn1.n *p`f؃ +քp w-LgH"q?NBS }cΛbIE}Q`s m3q/q>n?Ԭp6+%exP!KO MSM# DJRjDcؐ'0&_QDR b^R|4 ,)# >rmMDQOHTqָr$"B!2'' Ў2Q\o#.12rnP)rR/p/M3T :bd32()S/ #P.!k)3'+4wn41O*TC0(&sƄ+D'bR܄0jXҿ2q @8<3J99EE:bg5;80"e4BrtJuS"œTB.*ӧrKN8N8A?$S'3/Ȳ*Bo.;k rX2(37/F@C%W>/O6E>t( 5+>@f2SGŒAK,ͱ-hmsC!B3.)^ I#PKYT7 tEMhćLA',qAǯzBqF>ZmB֬3HLO_"$O/+3P; G#b"7M_ 3uMNStZV(i9Et rEMZ6ViBB\%;tP(RRa}SX;5ԈDj&)5O/eJ2 2H6!sF<*F \^['qP~4(ܴ㴂RS%[L+ 45?,E:A4*6/&!beb=*7:F{P֒% @M'c 0I֜>҉jUveò4dI^f |V=JbT1)[#]%=R-^fIeBjkMòJWs]AR?~ta$mɵ"ض6:F׮'t5N36HK`T00jSvp WrL:rqc@[qPb1-zvt<%,P3IbvX5__pcZ07h[R0q[KKiUUGV,F.vH:6R+h0XMkOS"G`Y5?wiTC`7"Q1tx{ps1t3\1i?5TH4|Gh_ 5PrуcC87ڈ}O2M[K#0xRD0oLw78hf8TPd*IyEp?C NiO|OW/x4j5Rf< zyl-aMgy7 i)giW Q 3jk.zGc0Ջiv"$.r⌁yǠ*!x3z[:vN;$cpf#؆'ٮ8r&TSl،7XtGAVSw69y '*y5 kKGY-Wx?Lh7yg.ؒKy3JECذZL-Ǚ~ccģ}pWwGWM7:7p SWZ'xŝXKy. ${8}y6&%y6vyјbl=UgwbW#ZeF٪w{j֋ Vsմ%Dh{%=S$ c 'TZ:Y9G%7oK$Z:'T[1E[Zy+3W bzLCwvbyO3*;zob : Iq5[9!G"iBz:-;VM~)E60KR;'́Oj7F*<[Md;dvy-0JZ{2/eB@ٹ+;z|z 3;lYZ7X?zvėrܸa[Y"}mˤS0ITpS_QڇGz?}ŻCդ܊2"'`-lcr=U[4Jcc󖷄o,q;?ryk72f(Zwr2\4˺]--}2Z aq{{=ؖ3[5t5=] =%e$,UZ#ec+9ۖ dy?cml9ruqG Z@ 5ڳ=ceŅ9*3B͋Y,byf0k\YIibK^ܤaYla 6#¬F-+܇9YRם3ݣYZg+w ν;?\ueqn:}S_ b}ۅ0z;էk]?㼿PK<}d$Bm" ԧZţQ苞 fۡCܗ.*H08I]RR^9g)Z߱i7ȿ7i O~6_=3۰?8B* $s7ck&?b0M#ʧOf8QE鯟/ekIM;/4h|B?UƏ[4RWҿے#G <0… zC-6HѢ xl1$# h2ʕ,[| G#oKYMv 1Җp˅P’MsBx)sC8O%+CK[sZneOM8(ϡ9*,W,Zp;UkŌcnϐbh\kb"l :/v.ق=H5MŤCl&+pןY=CoƁ ,-*ף9 ծW^'ۿiG"SR9S RoQG@akr7V9(YxvatmX:ut^xA`͇RcNs5%aB@!ZJ0Y .WA꽖s-4aGeN'ʩ]oB5葙zsyb;e0] IJj1gnʩJQp9Е%( &lczTp|@U8QzVJؓvE OMgW^J\Pji$iũk"*pznˬ-h(ȪR xռ BYƑI.yqȍ;Y/pUfP&0Z p)f hmgRW:&0!K1lAi mT:T ɪrAi{`YSLӭX\XW.M3=ɽ5o~ݨ muJ y}ce࣮->M0P֊7ϫY" LzcA\JHxsip#qY7h?W}" [:`hY7g h!w@Tuszl ")$qHHlq[c Gu`D SX*B6kDC 0a3M_&J%yZb]eSc7x]qvsbr)D[ s$NˍF;ND*!LwC&N:OtIȆTq C9m$zjŽ;^Ѐö| 'm]Bqw{t+D:4-=aqg4%㄰Zt1H++A¤; ` +K,l% _҉9qy)-J]U$C3,p{0pZ8)@*1_vsڧ-D 9rӆddMLl)dAB҂&F??MxYryhh( G}G<7I-H^Ug(:ROX.CGd u%Jk9ȧHZ*OѓTd2϶lZ.y$NkW2sCDү1٫JqN 6RcX駄tIYTA0柦o,YtPRڕbSZ%ѰCb[ݱpτUd\ 麉9a}w A 5qf/O(|4%WNA_plu.*<QKU$ K"%M lg,2Ρ A GcxJ.m7̨N5Q䲥IHDJP)` x)5Fɍ.WTxIXMw>7%:_#g.8@`9072#,,ȢC^>n+5|-9)K†^[|Lvn>Z}Y/X~K*>Q4a#Zb.6Kܐ3Sblё:Ȼc"CBsK\X8^rl1pxi0 zn9>tf]d-gnoi}TD6A(w%c+ bb.7 !OF8|DߓʻK>8 _='nR hP)2>THwc4$ \_׾eqDql^5%č㸉bz+ l=V"6>"h4X9g3${;B`7-52t㊢'ە(x/}!M?=~f_ᳬu ŹM U',BvðUg;cz6#4ls"suRg'~dr~305_wvf|xG3|#%hsӧu OBc+S)*bA{I&qd*sT&0BZC5&p(e~х^%XolojinXuF:y"5tSmQh\z'cy{F6ŶшHhV{E7EdzmE/euÇsv7F*8^狽)@& Lxõ( {w؄ܶ 1JPeKh6(،%,Zӎ^cMB2X|6Ӑ]r׆xsgm76)B:8wcuW_Bwy&(ǐhhw%$֣H=T's$*G;hxQ+>#Yx%IhS+&q?eyX8Hf{%)ғA$Se!giH05di (RYP)Vi#yceeH*3Q`=e5h9f5`Ao Q.C!E95ztփ0"2$IY )9)Q璚-3 QؘᘚșC1Hӣ){Xu9Ԥrqm38%6(9 hXvx5 Y %neP=ы BrM؆y&c!) \sL!Gfsc Q!by^I$jIp,>֔#.Ih', "(3P'@:bLJȏ7}lBҧ}F`Z咎*dڏ <+oũ8Lu9+a9 HNlG#NZV:-1FU@xz1xrFCPD"ѭM 6}:Z*:+w &wƘHڮ!:*TI)@Nc(|CEf\ī&R/Bئ!7ˣHkB (ap%|8غɢ3R8꺝J%F! j՛يJ^Pjyҧ۩Y[[ ^ۨNU+.R؁kjz;q+H8ŞT<*[)rcX  a—qQm*qJ{($["!Aae-е{`9jpq ӻlCVþ*ɫ+z+U+ˣS{E˽)+e;H>+b7P!Z!M yt*iN NWK6l*u+ |bho W_kat*VR}+ft.b+L5;=|.!QVN/A8TQ2@4,McZl^e ! + ٯ;%/YzxA/|wf2kZBŋ̰t;2l{Cr ܥm8)a{̷7RYTͼɚ\jh>HȥJc<ܲN,µdB]x\C(QSK}C{}ҎPv=xQˌ YRVeJjNS_#ҽaеfqzנڧaHgk[H7!Ҽړn}xQ)z&-t l7-c]{A>vaZĻ-<ЗM6bǢ ^~3ݾc>ewK ݶM.5L ؆45!>0gJߌ|u+jum\=<W}8N,ce>~m|"heGσ=-:kMˁ.W-m[)cSE6K͏1 )ڡ *D$0~nR5沕 =2r#(O SW+[SKz:-1~< AՒTաU}y8#,2hQ¨=Ľ(^,uN➽k0~2`[K^:24fMh 7[|r52݋ `6`hvkA,7i.0)1Ď.ʎLKI~R"FzO7E7I+hbn}3?ϵ2Vi9Ϟ|Xa=nG7q$wyC)j뿾\N^W7o}V v$pK_~orN$п/| A.dؐ!6- 6 E5nG!J!c߿\UF>>WYӦHg4tĆ31yPjDza>MUi \5UyWqS,O /0TvJ&\ذH2 01N'zX2]y1ӕsՓZv t萩Aqd4+'ޱ|[xAťOmLյoohjQ?Ky籦uH;{M }{ }'_ȼ~Do@M TèA * n6P6oA L.ɹ[0D[l!/nFsqG{DH -q\G$Q$ "rJ*kCH+ìiIR'-L6tJM:"S"3,O@.ι;<&>9qQH#&B2t*StSPCD.GM=5F1\UX4.Sc1U[7juMsgV`ĵXveYf]PدucmA2Uv[n )iw\r]ۛ5w]vuGtmR[Hk_VX/xiZ&lK[msu\[|q'mHH3M:ݽQ S}||}qo Iݯߪ@+ zҪg?:d|Fk&Mn{buA%"YGAsO[8$x=[f1`Dref.z)$A9Nd/F3Q"̝׈C/M{#\7UYn\2Q:YnRⲬHERfh(.I.&3Y%ֱ7d8Jq[2R6R5-R TDB@&  df9}VEQTnxe`]L涵p*Y,xÛ.0Q^5Y<ZPt~:Ve Sa }2h$Ra}ZHeu]v0%mtAӢܙԭrlfM{_#mql™tma3|E>m Bl{iEzbtfs}NnUۿ jFl#/SIԒK!|n|&bNůe4K薣X>(J\^7̣20 ps? sZhZO^;1g„$]'JYN;i}N.JٌMΉp?@7\EuT&V3(bKZjD*/4~`{e#m c{RAZPn!A{EST]M-m֒D#ҋ].u(|4γ"@ó,"/5I}1XAH-x"T1 z~'7Mk'.c:;c5~a tt{ 4w˜y2KX s0],9'x֍>s&=*}qqfGug|SzgwPZ:{BfMZ+kAƫ[NZ<".jK[tϼ7;Ac3/(WʱV׳_Ozk#S\G5ܥ1_u7jsnۢ_u8r.aǸBv}C~XC.{wd. B2MNDJKC(5SB'],Ljγ/kUq/rs0v/03;C}:6 .z%L5bW. :>ymء G1B~ S“|LVNjSO Y}=ٳ =Z:mlRǑj!$V厑+#H9[KmY-ncاb 9-YYܫ۱׳Վ}UۃةK*vޤjfEھ%#9E;fp ƥ֣Y: PY\Vr E˖ E)}D%!6ݷ\eդ5] ^q^R{Uu.卙mM-BpuE\,;eŽ)&܉`KڝW;_;ݯ\M5FTK0ݽ]f`^nqލT _t܄)T|amp+Ma>N7λ\3[F #-L$&'vV_)>$#W-^.SA2f.>c{}c86c9VU^0VP =^> >%e =fպbFBHf)M7dpd9V c39"e?Nd1TvZ`.v4ZCdcK7M[fa Ed~M)"g~fOe@@ð&X>MNM[Nf# בeh6eTJJidve/?T])}wLFyÂ6h~gpg 茰֎.USގVCc釆hh:eIY6NNiPbti@vLigԤV!=m6ijj>P&V&U\"i3mɾE;Y@4fM%p>M@vpL쯃X56`P `{69EpwlFqqqVqxX q3Z12N&A ߎ)W,*.'w/?2wXsU#')Osr%7-'2':׈<1W 3h€(G9$Oq,t:sA(t4M/Nj'5]U8GuWuXuYuZ#\5.2l &[]mpvp01vm\*2um:¨f`? k_cO1b`^] o@\avln@vV#ڎ2i7?xwzwxwDw[o?on ǃkpx׻5⎙ywx2hz@QtzgtyyWz ?z7 luz_ IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz i (`@@`y  )AL` h (` `*P%  ԥA 4@`jTi*Al`Ժj S) t`A uxA B`yjL rTTM HR+_@!,5Ah'22    곴@*\ȰÇ HŋHǏ7rIdG#M\eJ0a|&ə4mĈ3Ο{J4СEjQN)ԙVn\*1kԮ\zuղfӪ]m 7M7oݽ?Xm 67qŌ:V YƓMVsf4ch }cUy&v ޑ$μ$W`!,U22    곴@ Dhp@  P!CP(QƊf`ņ )p ]YP@0m &I T鑤ZSJ:ИdJ d9 @ Yu! dDbX`!,W22   B"곴e  @ 4xPC "QBR4p+hP`H PɔV<ʘ, 4xg t_ P _  o T M6r }B"~l:HC"Y <k d QM:&(9d {e} K&#Sm;v Y H*\ȰÇ#JHŋ3jȱǏ\)0e % pp2J0cʜI͛8sIsKH!EʳӧPJJL&3p!V^9JٳhӪ]kHO(t=)\, 豶߿ N[iHҵRǐ#KLY"!?pHdWb+MiāңI>M۸%$i.Nȓ+_ΜgУ س[>9޽kOvGOosxK}(`Yw߀&`Mw F(fv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vk-E]xh"q{&+A ;gas !X4rE]:Ʌ@,bDDYX`X FT}<[bao-K$0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngi`#9{mzm꣝99h໴9n.| EoinlK)O@|F1hK?ouW]'f[oFc/~Y}_?o?i HL:'H Zқ]r4&~:!D$n"$\N uB:FxaD ÇH&aCnh:0xbv 6 O0"C|8"L4N(D*8HB-&d@r"F*J AcqC2$n\w4GיQwHGXa;VGJxI,R xI1_21+S$1nhJdiDI`re-uKrFlPRӑƼ 33LaBSٴ7IcZ3v״d8LE"Dg,3Lvg='syԐ\yPs -B*PsMC{PZtFu@)CL(F OQ-%D_*G)hJ˘tNyLǴi0IeMY:Q. j1ꑪZiGjTaUJ}UiP+S>we\ݚ:gyuh`Sԭ֤eU!]׾o]A#Kԣuezı=3X22)Y*'kc VXM .շ|r۬vu&oCحRՏp#&jY+SϽu5^݊tIv BtOu{q. ݫGտIocK)_W5guPpe30vƖaI]< x{ajbX}ؾ}U<8x=1_G83&Oi'N `QZVX˺ԠtH8cu u32pͥ7}U' d?6ک]y<{v#e䞀:#c0wSE:z; }c;EDg0@N{xЎz9{j`vV/^\6gi>yd\;a(->g66 ugS7?"=2o7u{1`ƻv7vwdwtG gqzp|gqL-%Gކ_=f({ttwI8@|OzGwAgq58!XT )6sG}5TᗄYRv{~0|~Wou|G{VA5)@@brԆu_Ht|EZ&'~)X~,x׀TC wݧ\ypn肏sv:Q!Æfqp8qЉJ8evGMAv HpPxxdvb(n4uC>KPhqz_LH؉@،؉I8Bc ȀXywI6pr0VбgEpW{GM+W{fHF:7 wWƌqRe=+M7vW(}nNj慦phF؎RyQ('@hIwoNGy y PX\Y'1 Im!!pxg=&r M1|䄮8S!Cx8ihUMUE .aqq8 Y8#)XQ(NNhqPXy8[܇u_i]\o%sYwٖBh{g D70tqNXI9fdR~ȘP%'05׋陖Y# Ȗ|yYztQQטEzN[Q ِq 槚|WGgqA`P38t Whf Wy7p܇>))Z#kQ x1+V3pB爛'.Z٠7` yI?NX|!y^55Z8GXKh+yIaPXwHy+ՓN榼Zq\j#:Y k 7PR $G:H]kTw*VDӡJY01->9))~ / Ix%΄q:فEAI#LiIQ:V·h{1 g0m_y^Zz13?سau:}Z-drxQ|ծ,D!? >A>gYQګu%o8QK}*ЯKm*@F.$JºѰ]| {ew iv{gA٬Qtq=a=q16PAZutf:3( ꩦ.Dfe`Qѳip2qRcZPy+xJxzml׹Ӕyk>*i򆧚n$:BK!rvWk)|hRC[ekq# )cj qaowڴ6)P:?jH:5тzV{;U˼(Tyk? y[1{ZzW֊ ; E{F)>}7Dcoɍ-|*|^oA=ڋ;[6akX;Pײ"lC rc&KAt[ wqttE@G EL (nϫ#m Fs\KlW)W|IzK[hwuG;1#Vn(إ.iĦqY빷o iTZOqۗv['×?z2ڟcDzfgR>ܴ=jC L&glO O{,Pz:Bߜ\p[~'pnǢA˲V1ɤq.kV }F|QEũA[~ar;~tzX Qq;$ykhgja{ ֤CTl"u֏EpW^.`^Gq龖\.P҆Ƒ1xvTW]yEQu#[DBCRu-!JCZցX]lOM,tn$/p^%!,TKU E0 LW~VptiF/}Duע/nPT&خqq1!Bꕟ/k^dRW>,lRv[w%t^şB?FCZ+uIL;m>qPPPaPp.V筎Htzޜt~a@ ,BD  $x(QA8qH%MDR%Tr͌xC|l C <І (}ǫJDPuDRbʛr fś?x9tKFwnze0@נMZSBXX *m[i"[3DzG-́?]CS lͰvܕ^Xk[&Uig7z4ݠf^SSI|^) 쪵ɽL"(*Vz( Bp"`93=5Ok<*D1E"Tj˴R*.>T1"$,d)#ܪ|(s4)dGdp$) OdK/S20Kn.{ I,̹6L=21Jbø|$Ј(PTХ \r껡,.Q:G bQU#D+NoU;-PʝVM?.;(R$SZ4kE͒LV]6G ڑ\K[?KOPp!"#Un Y5l(T|ױ*s'}FWNyE\̕Z,l\߅X+êrHۍ<Ѭ…`.%Oųޚkz Y?>ݟSFz%= h1tRQTAa}]y.  Zh9iRmؖK7TȒ K׽,N'ﭻ X;'Ag]loLP<|3p]B3 J-i)?km~M;tYSc6f:5tAwH}ܯWIYq36J\6W~gkP|b~$__>?"y9VIȈoCWZE]^#T(!Cx'σݕۍISPWӕ/SIypZxո{Ƴ-]]>xjX1[Rr7ɐN23BCy*[T^h j&"ʦč`.f"(F@>YH)/5#zA\cBA4_ے"ӵ8ʑU*2 kf)Yuxi6H%Q6A[; *ɿy=JdYaRb(C@BTq#^-?l}q`B/:lddR]OB'$MJp0&7Ght: 6o\&Mqt}l17"mf!'y),$@k0&Bt.qZE"K:BY|!+v҆#;Hê4U @%MZ:74*JMv#e @"&!"Qi)2 vuKU&pP'ca5`ˎm*Cx]a8]gJ6BNOzO˚u] 26OgZF&F/"&S(@. D9+~E7hE+-JYt,Kd݄O)as>ԱÂKE9 RB{D%ūgMJj6*X+ֵԖ!RjvTmkf{~T>_\bOEèKcHEb'ͿZn  b֧,QP v!o~Ӧvς,OmbnwYe9&cvSȞ{+)4.[meJ*i:6`@O# rd({V:^I{!Fo/{ޣh! lﶚ'^2O~s<[Q˄Rfԇ3,j//q/[` ;yH>RSכ )>R>ۭܫT9"c.#?$ Ss$3=@27 B(kA{A/:t[OIB0,5%;aS%D[>0d=hF:hcOQ<ROt,**@;p;V 3=c:D# YęhBs9B;F+Ea,ɣd \ " ܿ$Uk¹z I oF%^$cGsGt ( P u ![;x4?P5hBÌ\ FPɕTC\H2ۭK< P3P #sl$PP,< ي}i}\Ʌ \ L$ XيMI` F `6dK [ʦI##B(T|}D2Q܈ĺ|Idˆ|KpK40M8jLl.jd?-p |4  ͘Ƞ5̼ɁM DM Mp̿C!ؐiN|őЁJH,Lɋb˹"O霥flFBh/̿<IĚL#OkDL%hQ %-QN|ȈdNt$ 4P߬Q?ªuѰQQM B&c ж `RQ )Ş#PPh"R)S3=S+, .Qĸ*1m:MuSS5(m< UPAR=@)F}N? %."Ũj!C]9-TSH]> 3"C 3{Փ'uTL\4SŪ[EӜ% TMѯ!T]efNTUdUTWEVhT cSgEd=oVRm;Z}l`Vp} n%Ox Vx<{KvMyeToW3W|]W%~ kmT嬉؊uՆ~W Vu XvءXru$aeXt}X@b- .$abvb]b&>VWb-_2&bablb3`b8Vc/~7b:n2E93B61qCKc$E]+cdLc=NeEnO>[WSkM~bFe]>ZF&cZƼEgh&UHdd>fcfmMYfelVmngobeH6@1s^\V_ffjoeggqbgZe.8wN?g@f{ˍ܊hx>.idbfh|^h0D16~i ivni0>ӛֈit^ӹCfrjtd~;WJv*襆j.k 떞Ոn/v0Ik:w~k~Ϲ.uk_j~kqk%iXhMaq͎&6FVfv׆ؖ٦ڶ&6FVfv&6FVfvȀ+0M HH| $I HПPF (`ЌppL ׋M ΂  p oWNq\/ (/$p?fQ#O W%g&w'()*+,-./01'273G4W5g6w789:;<=>?@A'B7CGDWEgFwGHIJlKlt6.O7kLu#u[STPouWmN?kRGjR]^_`a'b7cGdWegfwghijklmnopq'r7sGtWugvwwwR.`$4K|7X qxpq pgH/D!o5qWgxGxww?p?w{g'7GWgwzfu"rZw>uWCۮ_etW0Ok]'7GWgwLJȗɧʷ'7GWgwׇ5$o $`WP 3~oN?wo~~op'p? ")pq!,n22   B",곴eK&a1Z@ Xt(p )Z(0@dȅ<& `ĔM ,P!ʖ,x!d R&N e  B1LjEl l-p@ 0tJp!!,o22    eB"곴 @A(p`0lH)(#;>01h`ʌ-|IRL`ڼI!Λ$LI( t$)R"`TӤ \lpB Ճ] Dq5!,o22    &q   *&곴  (* ~" *H   @C $tȰCHXb'ǁ C$Yǔ*Vl!̘YvxΝ{J'P*aѣ. )TR.`”0A5Q&= >)- (ȝI] 8P!gGi @0 @ <2 <`@!,o22  ,,!& "W $ +$(      >-@(Pa:l0PA Q2(HXXt%,d_f)NWrP_.lT\Ai'L FF㝀*蠄j衈&袌6裐F*zi9(wPQY)z聕h*무j뭸뮼+k&6F+Vkfv+`'P>^ W.+a[QߺK l' 7G,WlgG~1wW 4'#L\Y/aҜ7ׁc' tu࢏!PG-TW.ZjW]{M\a=6Ne}vji[6tmx|߀.n'7G.Wngy^nzYoܥKFz:됁;fn/oV 4 q&DW"A-Z|MX̢.z` H2hLc<q"B6P7ZI^R(uCsk7{X` 1ZPvmbc/`wd!./O\&7kewȧ D[Fzʽ)RW9,hsΰ&ۡ" ޮwN5`o D 1 lv3QC]薜\^oW[A8zڴڞɥ4l=vYw\ڝFolSv~jDn.z\a??G9WE[A_oΦ|lث[ϲx*=l+M{᠇G|5~"lp h{a"|q5/6HeMj47"S}ZcCAUEsQ$cW5Mw&2rbwuH~<0msс$Dd39ȃ5~ADCuKp$Kh@僥Ą7jUhEMhU?Cȅ=GQ(csVb! i.R~-q(ie-u/wH-y-louB ԇgYh(~S|sHOW(;艗ȉh(腏H](ec`I=(((a(H(DGƨ"cpHlatQx((;٨-#Rf4rBSelBV(‚bŒ7"vjdhg$iԍ芳H iɐ 鐕HHdď)Ii} fđhtHa/ #ӁŽ܁AEI͡ɓ`cĒ+ aĔhO]ĕ_W ^c)]I\ieaUɖiZk)u)MIEYdb4.#)6qDHD't)5<$ X)5sPtC0#t ™z<ƀLҘ1@4i80Fe)zc/1LgD/IE~EәϹD艝 ݉EYpيI|yyߩYFyDɞ)F)ii‰;)D*RI< ?  :<:)A* *@zC!Yn#wy詢S9+zmy_9$ɢi77D$9? {-Yis AJ9$E*eFĤ`GsKJ)HxIF~Gb3ʤHH9tIS!,rP522,,''gd--,,&&++&&fe!! &++- a&!I))!,x,,!,x&a - , I!!&",!  -!I a! *$ ,!#!7+"&$M %%(k8,#_&, *&x!,&H*\ȰÇ#JHŋ3jȱǏ 3. (S\ɲ˗0cʜI5sɳϟ@@ѣH*]ʴ)#vpJիXj+#TlKٳh'v ۷p*QAݻx8u LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)eDWly$KdOxNVRfHRe^q$$lp)tix|矀*蠄j衈$@E% ?DuQ R|@QBEu*!  Czહb k6F+Vkfv+k覫+k,lD^y&]%)%[Vf WS{qojܰ&,0,4l8<@-DmH'L7PG-TWmXg\wg )~=]Pka7Ыo+Z``{ s8^,ۙnz8^"ZُWngw砇.褗n:Ljy:U_VnĪTώȹ'zT o'7G/Wogw/o觯/o HLSP!XB n <`l6 dP0(!_ S> 8̡w@ H"HL&:PH*ZX̢.z` gjG@c95x{'5owu$F:q#ljQk"yE~p}$$#9H>Rc٦)i T)sӛtrV:ۙϢsrf7Ϥ,Dg=N <Ί:x(@ѡhh7ц{LKR=zQ,Ppi:P.R`ң0BQYjԜ4|9wԞ yFʳ2@VJU )5(Jօ5fxKVZU,(jU8(j|( F lZЩV)FXniW#ڿ uci WeO)[ӳmUB6b'Tk,Sav:EdF:՚"bsdU̅2jXw[e}kbޔ0hmGv_Xىz~*?9߲`F u4ߕ,63 {x0̄Zaļ Mk09826o_[c>XQ+ӫJ4sհ;_F#j\_(34ժ\ط;o"$x_nmŌg5c溎]s̮̚`*'}soˋԾFJ-?i~_?><'xfO$ $ 9:8L6 `x/Ds>Z'V妟~(;qB?:Ǔ~R:חr+*w:uQ׷Ӽy~`]3[nם#wӮܵ'a{}ъ9Ew]~+ xav7|Fk|yCs]1Ͻw\̤=I6⮌ߚxY@#x`O[Ͼ{OOOϿ8Xx 8C|A|2g%'@PXtA@FGeY 5@eB]SA\Z@U+7@:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxh2 |:HjD%8솁v@!,rP5O22,,''dg,,++--&&&&fe++**!!++ &- a&x,!I,x,!!,))  -",,&a *I!!&!I~' a!8,,!#!~7+!&   !-! #~' %2&4&x!H*\ȰÇ#JHŋ3jȱǏ 3Id(S\ɲ˗0cʜIɁ#mɳϟ@ JM']ʴӧPJhҩXjʵVHKٳ^E˶۷pT3ݻxHw޿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνw_81_ .``!-@DM߀6% 3Р f ᇻ(}hmz'0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjjLUtUjjs$:Zk]W>lk&6F+Vkfv+k覫+k,l' 7G,Wlg?^ǥ080b}$ h,,+:v 1 g.*ў0|" Xg\w`-dmhlp-2*{Z+ނʷ^]~UwI[v;Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/Ro&h$S j`5K };@ 1XQGH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z1G;_Ĩ`[5{nUFѱ׻#Gяwd H3Dd!GF6)I=qz4#&IQeDJK6UT"iJPVʒ*VY i˶`B `(]^rVFI,d/pHj3&[l !`B6mJYrn5 Ni-<zp7ϱ&:khOk d dNȢFjRӢ-HIЄ"G}9!ԡ`1=*!TkċIҘbMK%NyM*SPHfիv(PT”dұR0ә50CEX֫*U mS:N8 ]cֹjbذBb%`Y٭,1M f1uS3j--jJԽ VV" u/ge9zYmT\g]jsܥa<,mzYhNvRvF-w;|n%bgnC/YB&lQ)پwÕ~Յ+cKՉI1y`ƺް.WBq:c1ckծXOmL0{Uq|ݿV#d*Xul #rS[ڄiykm:1kI] ]g' sJoYfz=[|dG;ܣ7%[k{g;^wCo@ &xIi7rmt\8q7OW>({:cRkguo})|9zv#|:}q;:~|ヷOw/ݥvq/wCǂ^24@>>x]ꣃ>>EJL؄NPR8TXVxX3tc+\>ԅHT13LI!,r622,,''gd-,,++ -&**++!Ife a&!!!&&a x,I!&--!,&&,,,x&&,!&,,&&!++&&%% a!!&x!x& - " -!I8,"W  7+$ +$(  ! ,!#!7+    !Z! > (k"H*\ȰÇ#JHŋ3jȱǏ 9b@"\ɲ˗0cʜI͛1`@JѣH*]* ZTP 5ӫXjʵׂN@RԯhӪ]˶ PHٳn˷_cVKÈV Thǐ#KI*)k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(vB0$,Peՙąb5H)`>4&"R`<.OYH\D.bPF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6hn:<ꨄvjV,ة&6p?hjp"#/bPiGJ褨fדk&6F+Ԓ^[-juv9.[.⢫rv.n,l' 7iNF%k)POqܱU#c qUqV2&`0Oy\s:;-DmH'L7PG-TWmXg\w`-dmhXM\b},PxW@:}ݸ*8z~xy7h />^@Egw砇.褗n騧ꬷ.nh_ OAY<Cj gQ_=n:5~|cF𽖯/o HLؐ]mb`af ae4 ,x "2'ry`F#÷q I ^/SE^a^5/~ /@.%.1-ݒ NX̢.z` H2hL6Q1 &7ڄ TxFI3@g!grp.@t%WA&9 ^ (GIRL*WV򕰌,gIZ̥.:j 43!rJye$82cFS 5)ɂ@3wrL:v~XKsq#ϩo^Sq<'D_nr '4ZPz HGJҒ(MJWҖ0LgJӇ@Vd %O7)< u` Bz$9:& 9o`"D( : sѴ@NPjJ׺xͫ^׾ `KMb H*5sHZe VH QΪD!,pB lgKͭnw pKt,NZE˓SmiY6"[$NMz|Kڷ/9]It+)`'%_s fr)YAq$wR9;4S&9=` #&ۇSj*.xٯ<4Nqnמ5ll~)7<:Q>lVRuE]. 퍝J׷ѡv\tz?.}=ݮ']q=]<[_vM=4о-_x\.1wċY{&9}5e;aư͒|URE^>w͞D*OǷ=Jw}:JEiCk;:qfq₇6k[Qq#8(cцYg-M{|WYxXw2ZተErZJ2C|{*lc!x9m^Ȇ7Xt(3Ǩ9u,hӍrȍ8xT񃲈9(ce(8xS7sPrX7{'9 w7Xqx|gvjDz86'6)1;&#{ 73ؒ7f|}(7\ѓN]qF3]ᔝqJ 3eB9Yh)HZIKHiT#^gqQc^(a9fOkٕScaAك@6`: S%vU.sڨbe鑔d5Y\T94q;H'4A<.͛G,fRFJeYuxmcaӶA /HC govn]t[#xV&}.n'7G.WnԱ9g/we~<>Y規oun4in/o'7G/N=[~}Yo^޷nk5E%/o HL:\Ժ +R8 DM|y&| rdmz\`iL\z B `GUp#[ O.!H*ZX̢.z` H2hLF|k4xy:>c/0ԥ1^b7Ԣ4})_Ow̐6y{MuFшnup=,YZ:ʷ3lWC&v|-d׺hBӎϢu]Z;״ köFhn,h}G%nh |!X.wb뚗fW$g3l\hD `ml{Ha3lNqQ _(a=zʧ>[p^~wq|7^B=\?(_|wosWQ]|'\>HQ_:mE[*~zDw~}@Jgx~'~>aew)7*sW*8"ZbX('"vG{'v[W+*h!mj(&!96w+!H6y2%rczb$ƃ7!?NNHc!d.؃tDbd$acche腊eąĆxDkgDaWr'Gq"ogn%xOU6tV"LjQg<%|\^hyH_䉧ȉoh[䊯1ŊfhgȋX$uhH$iHeWȌrf΂С‡!BAѢ"ABց(ZU草$HLȎhȏCYV hq~Đ 4dT)H.đ)@c*㎪x-1iC3`A5.97aפ~@)(4* #MK„CR8?b3cRcJt:2y4?&!;dHsؖ%9H'Duɗh )dIĘIș} `AAIIa3 (#'!"ΣBÃ1 D)(yɜ dɛi ]MD( ɝ 剝SD dɞψ d DyS>%G ITRI!,rP522,,''gd--++&&,,fe&&!!- & a&!I!,x,,!++,x%%-&a ))!& I!-,& ",!I a!! &,,&&!&& *#~8, *(l x&,!#!"7+  !(k#~'8,o" %&x!H*\ȰÇ#JHŋ3jȱǏ 3!C(S\ɲ˗0cʜI 5sɳϟ@ԱУH*]ʴӅ *HիXju@aٳhӪ];kXpʝKWu˷"෰È+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiQ `I^֑/5UM0J H.&)Rj f֖k#V_"UXidUM>硈&袌6裐F*餔Vj饘f馜v駠*ꨔ`ꩦ z*j`+:믻*, j6F+Vkfv+k覫+k,l'\)DPY| qqp% kyp%ao)4 DNҙ (;yְ"1M*PP4+sM]H]t<)G"8 Uds% Ml- *k<&RF]OջƣVi)kX*IJe\:6:p^2xm'\k,D)MYͰ;8'zf67ZZl2Y,hRG׽VkT-i*qjG:8Ϣ~/[V (oK\a֮I +5Vm.wЮՋonr Y.uo^·o=-k^j0zz7Dhk,.akCK&浄\C,BLo ;ͮSaX׹;Ƈ1C ex?e#LUxV%me8GqaaS uf肹ǎYV,xrX3*(_&zrid8Kys2[[LbW&d=@':5=0 FCh(]jX_=$ijҜ5jt4؃@a̫c3Cw[=̆էL"'3˶W lwf[t-7Sny57 a:Ͱw_F󵣽w_fj/7~nMqpA{n8YimI6un|<6'׸$\\^99Q~ nϧ].87?8u[6F˓G6?#Zokv.sm4 ivs.,{y ~\w/NUO^j]:c!x_y?_EyǪ@ASXVԫ)?z}1g`{ޏ|}w}'?&G|Og}}___~_}O_~?_GXr e.A(AfG ؀xEQ$ARwAOC37EAhPUxԁ-A\=h=70284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXf($x:ϳ'rU$3D%j(c<01P*C&$twax@uc$7׈w؉8Xx؊8Xx؋8Xx73B=:d;ʃA|A#s 8̡w@ H"HL&:PH*ZX̢.z` gjG@c95x{'5owu$F:q#ljQk"yE~p}$$#9H>Rc٦)i T)sӛtrV:ۙϢsrf7Ϥ,Dg=N <Ί:x(@ѡhh7ц{LKR=zQ,Ppi:P.R`ң0BQYjԜ4|9wԞ yFʳ2@VJU )5(Jօ5fxKVZU,(jU8(j|( F lZЩV)FXniW#ڿ uci WeO)[ӳmUB6b'Tk,Sav:EdF:՚"bsdU̅2jXw[e}kbޔ0hmGv_Xىz~*?9߲`F u4ߕ,63 {x0̄Zaļ Mk09826o_[c>XQ+ӫJ4sհ;_F#j\_(34ժ\ط;o"$x_nmŌg5c溎]s̮̚`*'}soˋԾFJ-?i~_?><'xfO$ $ 9:8L6 `x/Ds>Z'V妟~(;qB?:Ǔ~R:חr+*w:uQ׷Ӽy~`]3[nם#wӮܵ'a{}ъ9Ew]~+ xav7|Fk|yCs]1Ͻw\̤=I6⮌ߚxY@#x`O[Ͼ{OOOϿ8Xx 8C|A|2g%'@PXtA@FGeY 5@eB]SA\Z@U+7@:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxh2 |:HjD%8솁v@!,rPCO22,,''dg,,++--&&&&fe!!++**++-& a&!Ix,>?I!,,x,!-))!&&a  I!GHSر"))5,&,- 01;#~'!I&&  a!8,&&2 *곴,!#!7+!)++7ɑ!HIT00a)$f)b{B r(&aKb1W(@,Q2(ڱp8n`6#B@x @.@@ \+PVH$ M`pʁDVB+gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8Ir3xԉ@T<8y|i' 9|Ӡz$hBP{JC9Q6Ԣ<#OҐ.[AYT KM h$ULR4585MR 15JLB`M;CӴE `!䍩j. I`^[UjZ(J+ԧj :7Yݪ׾JT.b%Y +7ZէYu:6׽ʵm+JςxI]Y5.mbM˶5+mfۿ:ue,o{ԱMq YZ謻=rj!7d{^zjW 6eoYwlKl Yɪ[^w0JkEmmxw%p`T;V6Kd\άuܵ0,0غp/A Sy 4ƛbſy#XQl`xD-ZZ=/LCLo,QyA8PU `=Qte;YQrzl =ko)ל ͫgչ1 6rȨV0Wdq g057}jt+j1֟6u+#_~w s wֆn51duĄ-^/c>[jJC3fFj8VXc6{ל6='Xht7M1^t_̞GMs-r W*ύi4'v>s[jhc<_*_Ko93*n^;9eXNj\蓉;XӇs}N5͍^/;ɫeXG_777[WzKڟsËC縻,)/!x~2f4_whwi#}\ߌE/-z2|y_6dŁ87g&&~_\^܏N'W{:k{=Swk{='k=W?Ws3Uy@ d->wx=Ev[qgqWSp%r.]GՃ}W3b*YF>hc6BxkOFGX~aׄ}7f8VYHZ]8sh>88ׄ-\Ȇ'X?ȇ>5wX`ӆIXpx?EғjtXyf؇F-(FD Ae@5i6@8@xNڸ؍8Xx蘎X#?(@T8x?Nh}j+!R,t22,,H*\ȰÇ#JHŋ3jȱǏ CIL\ɲ˗0cʜI͛8Lϟ@ Jѣw@ʴӧPJJRUjʵׯ`^ٳhӪ]{pʝKݻA˷߿t È+^UaƐ#KLYc*k̹3LrAFͺPUM./ͻo N|R_μ(ܹ'>;&Oӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L Wm'0!# a q@? O!Fa x".тI!O8)qL"t([C$gqX!,e111111111111111111111111E)8^&6    &" (1%:/D<IO L]EcBh@k +m-n3j+Dc?_ZW}RfUVh}|Ȕѐي @*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sIхϟ@6 JТD)§JJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ EEn≈.Ge3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+b]i?w9ikh~Oӫ_Ͼ˟OϿ(h& 68!̈́q!Y] фS!h(,0(4h8<@)DiH&L6PF)TVieƈX4Y¸e/nYb ǔ9"Belp)tix|矀*蠄j衈&袌6裐F*餔Vj饘fi.hS mijjj*eJj&fiЦ뮼 )!DyG)+VkfKt1몯 e:+/j+k,l' 7GD" IPL.{,$l(,r.Dï l3̛34,335bL7PG-TWmXg\w`-dmhVS n7w` )|߀.nYp.JGдJ7KڴJPH褗n騧ꬷ.n/ĿnAq|˗qaGpx~qw/o/ ]X~jאHL:'H Z̠7z GH./ 207= `%̡w@ H"Q{ ҐEOpp-z` H2hL6pH:x̣>jA,p%,( =}o[! 'IJZ̤&7Nzl p4[(K $OZn1^v] 0IbL2f:Ќ4IjZ̦6nz<~)NDa/oKf4e~8'3% ] e @RͨF7юz HGJҒ(MJWҖ0LgJӚ8)@ Tt`Οb<ͩRԦ:PTJժZ&uA'F2PA\*XEUNêZֶp\V^ԨzJAJMb^t!uUN Yr hGKҚMjWֺlgKͭnw pKMr:=VW>,LWսnjtxKMz|Kͯ~LN;'^Wp;bx5x((NW0gL8αw@L"HN&;PL*[Š@ Q@a,k(\.0H6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7hQxӠuCMOԤvs :VհgMZָεw^MbNf;ЎMj[ζn{ӮMrNvMzη~NO;'N/<ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻIO;9'O[Ŏ7{ǼGOSOWOgmϽw/ryO>ЏO;~{?ze Xːi־{vw߉ϿGj?wXy ؀Ȁj "&@F@@` *mHk-؂j84X6{2.'Ep+8Dhm0(k/hkxL؄NjHIjA(Y8k &BH!ahCpij2a8Gj01e Іf=)0~(ÈX r؇o8~z؈c؆x8ȉdkӅl|GkIXkKh'gj]PjPEv%@hNpBjHr؍xt<8؊؆qX8hN؇'wX~nXehwPH#ֈyk8.Hx(*t&&A@WH?px7;$p)@)&@jw9:H؊xC yJ9LiNS~w]ɑIH6C@󘔳&*? lZ|"j$95גj"IpE0@hx`z9uȏ I醧hIɕƙYdjKOxvH9 DxoI!V7$`u7=J(ٞqi8@@(vxlICp')j kʍO9X \؈uISY織 [ٖpwX&X C҉1b{{j}LڤNڞKYA㧉y`?19.z]ʚa`_ڦjmgyik j ` tsJꘓ:꜄* |G2Oک)A ky%Ȕ$z,EzCJHȏ7@ **(J *O0:jGp9*gz1yǜZ~ن(ZWY%ɞڮ(jGPv](؅Ky::YJIj*xr9zh pdnyۛ*f诛 vɬȚ*{Zڳ>'jjJe(`%tQkY*|@B@B=D]F}HJLNPR=T]V}XZ\^`b=d]f}hjlnpr=t]v}xz|~׀؂=؄]؆}؈؊،؎ْؐ=ٔ]ٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڪڬڮڰ۲=۴]۶}۸ۺۼ۾=]}ȝʽ=]}؝ڽ=]}=]}>^~ >^~ ">$^&~(*,.02>4^6~8:<>@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~舞芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_O/:0p8n+/.035o79;O=?A  CApIiOKlUoX| W`[0 +cflkom%Pj?Y nn |%ՃoHw!,5s22vvv  eeeAAAttt&&& MMM  B"ؓdpppBBBuuucFFFnnnW* ===`###  YYYe666(((? aaa wwwfffzzz;;;H*\ȰÇ#JHŋ3jȱǏ Iɓ(S\ɲ˗0cʜIM ɳϟ@ JѣH3ӧPJJիX+."E֯`ÊKٳ< ۷pʝK.Mkc˷߿O+@N+^̸や~L˘3 ϠCMzad><^ͺrM{ հsͻ0໸ȓ[@lС+N4x@OKG Ͼn#l'@Ͽ<,z% $A VhaD8ąv ($h(,0(4h8<@)DiH&L%MF)T9X d# `ifcylm)gxo9xWygk{砄f&b"裐(Vj\p馜uhէj*Ti橬:*?J뭸dk+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'L ȨF(H@$E(D*`0)8Aj IP VYL =*t@X@jPT 8V* _W S !p@dnPX(Z z HJ" eANRZhG!,S-22xx~ xx xyxy~ ++rrQ mm }  yvv ``^^iix gg MMtt//OQQ<<OO55VV:: @@H n ~ ˏx}} /0 EEoo qqvw`" #JHEHȑ#.IrSrT˗$UQ 8s|@:'M !*¨KJLh R |QY9tT civ05-lVEР'ܸBE̵x;̲ur%\oǯsReܸ:D0sP1$sgHEIO)sk;0۝qr`7SN7i!&Ll 񼻋ӗ&+O BPu{]$/P ?p|NT`~x_ .uLР IP'Bb*.%(‚1$@#' 8KI.dBJIR(*`Yj)R59IR?#u9X)҉)9% Hs!e,,  $+3:!>!?#E)?,<.9/61212121212212222222222221100106-Em ~ɦ՘ؑ݉{a QF9'#54+!rfeefcY: #4^\"ob8B=#iF:&7Nz (GIRL*WV򕰌,gIZ̥.wY]4d0/P*\2=f 4 ;9uq4IjZ̦6nzd&%)M<:NM3:NoS>~ @Mejr!J^tq3 JъZͨF7K“=?JNs i-!Sz)6AXMb:d'KZͬf7z hGKҚ̊bp X 08d kS pKMeY5Bnu.t#ò!vz xKMz|Kͯ~LN~y# Wxlhu{ GL(NW0gL8αw@L"HN&;>1:e(( .`L2hN6pL:xγ>πMBЈNF;ѐt|#̔4P. Lk'3ARԨNWVհgMZָεw^MbNf;ЎMj[{ȶmTs6Q_NvMzηONO;'N[ϸ7{ GN(W0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO_ E%o[g<6{GOқOWֻgOo>=!?W^nO;?Ï{OϾ՟{_zL?䏿OϿq7Xx &ZڇXxz ȁ $X&x(*~.y44 zP(<؃&! H8}-L؄ry4&7y P>؅^0dXc'fhxNp8t(vGj 0䰅`8X׆(zmXxr8Rw{yP`088zX~Hw؊BjyPy P pG?y y5 yH7EpyyǸyPyAyሎ 44{;g(yX̸yyЍPyըʘ؏y37z}ٍ8yyHgiؒt.2)sh"g ` :yFp'FOḎQyHLMYiN XdYHh zaYfISyGxxXalpiMS|Y3Hpxoay׈39iy5)7)䠅0HӸV?@a闝؛ِy(hɹl鐙Y'9| I7:0z}Iɘ8Xɟyuy zx"0<,  j訙 zII.ʝɝܩʙoyɢWj#)5:Jꡢ>0%f8`WZ9%9ΧP:)giɦ VrZؠyy8I(XȥIx~ڍ0jRz)S E xPx:g9 9j̘}F<Bʤ4˙7 $THXɩ$:{H9y*my%˺+٦v:PGzuNy9\㪝iꙮjF0>*qJFpFڣg ꣆ٍP`jƨڣźY ;IGy 9iG' غHg,HyPy89ZH"yøPE{99zyoʏ,PkDkYشy?zz>ˍyZېg|+9ڟ;|릌(0[5粆Hy5{ H8sٷ)eYeٕ80˛ 4qYK횬l ;jU ysˏ +X zy y7 [ ȸyyk`@køsinjZkA{)ː:J k{+ YH[;":vؕ',iÜ<W9PN,DZ^Ha `śa@x^?`"zěw](ukC+{rp. >0+M"^݊Ll pa=C},@m-k~}bCMamM}،P-ׇ]SM؍=]٘-o x]]@Fmԁ ٙ}ڪf=arو0ڴ}۸qgۺ۾`=]O'Ɲʽ>-]}Aؽܭ޺]]}^]=>^|  >~.ʼ" >&.}0@+N:,>9py8^PBPB><%Txaa 14>E^rd~Qw]X\congt~?*7)9jmskgD5 m41 `g@}NYNnv~ꪮCz0MN>vrA.amǾa~x>~}WؾܮS^~}~Wt^C7s/?^]' ~C R7BI"t ?&6W(,r*02_6O6-:&>B_OF JNR_NVZ^^ōuyo?VӘ/Pp?q,?m<4,POӆV?a_oaY@ʿu41%?p, (hBd>^4| d-' BH4Y sX4B=}TPEETRM>UTU^ŚUV]~VXGEVZmfeO^΁鐳ݿܖz)x&~7 ޿Ȧ1<4ZȿL馚 rI`)6C?1DGl 6OD1EWdE_1FYdo1GwG2jH#D2I%dI'"I)J+2K-rK/3L1$L$43M5dM7߄3-4j*A@|pPD4QErNFmq6{) 2`R1N7v>4TP4UUWe=G[}84'o^L_ WRgfi6Oij&KjkIk&llf}v;n[Q;oƒ -y=~y矇ͣzmz?|~|Gg}A\}?O`֦@Ѐb@% `@ VЂ5Ae!<By#4a U;Ѕ/] a8CN5a%wCЇ8ĺGDٌD&6qkKtbNъW4E.L]c-E1ь9ոƚo#G:NscH&<я[9HB"Dd"tHE6ґ7b#%9IEĤ,INv=d(EYPҔLM)QJV~Fe,JYҖY-u˧䒗fQ|LbS!4f2Le6Ӗtf4[ MiVӔԴf6;Mmvf8 Nq4g:Nutg<OySg>O}Sg@PT5hBsP6 uhDSQVhF/QvhHR$5iJRT~,uiLST|4iNSzg}hBυFhFweэ4V iJ/ƴLwHty4N7"UT,B_=ŚַQq׿~=lؚϮ=mHN.mnFvE3(ܠ¡ϽnN ozWvf}p/Z6pK w!dO1qo/Or%Q`-wyasΜݛs=ρ]E7zt.u}uߖUձZo]:hvΎ5)vCmgXϝu;`wxWoV/^wW!yNV奚y;WAoTя^7OQz6ue{ٻWqoR^G|5%|;WoPO_շ?}}n~WoN_w7mΟִ;W@c$4@`Bd@]r|y@ , @ \@$A3TAcAALA| B#"#DBS%ܹ&tB( )B+<,B.l/C124CC4̺5dCs78C:,;C=\>C@A$D3CDTDcFGDIJDLLMDO|PE#RSDESUܼVtEσX YEҳ[<\E^l_Fab4FCd̽edFsghFj,kFm\nFpq$G3stTGcvwGy({$-|~ȁ4BȄzdpZȇ$ȋrȊ& ȍܨhȐ$ɏɓL&Tbɖ`zə$ɓɜ%ɟ\Z ʢ+DJX:ʥ|tRʨD%šʫ%ʮ ˱ܩ4L*˴d˟B˷$˺q˽L$1\T?JĝDŽ̧b#ɴ̜8TͫҜD3"մ!t{֤MαM,t)ᄜ4NA<+dN&Z<εr$"N|+LO4OAtdOqT,|OO%P1UPaP e P 5 PQ!EQQ5tjїmэ]2қ!I#="ERT%J']&ҤҞ*}+R R/=p!2}3E/ 55uSd89SV;U>EAMB5:ADEe7GUGT6JUKT?TINO0QR5-AT͒Ue+qWX)Z}[՘]]U%`=^%Vc-dUE2f5Mh}gajkVmőnVpp%W1sutUWvݡwyUzW.b}~؀%1؃ݐUX`؆u؉=،]3EX.א%Y0ٓUY`ٖe٠(w|Ȃٛ8 Y5: ڝ0(ٙ1``:-tphZ:ښeUYHE}A۱u۞Zr3M58٥=&}[t[۳ۺU80\. e[X[t[xčYY]ܿu([u\ܚ5۞] Zֵ[]]-mܽe][ǭ]]e\vZZZY=^[^h^]e^q1y`[Y%\]_ڤ^m^EU^Eu%F Uv  6 fa ZFa9Ɗ$Pa.("66"a a b!"6#f&v'()*+bА(P./f1cc/aq4~c1&c,F-   }A:fAC ̨ ?~;vPD0d<LdNMbIN㊸: 0dLcV.8hhcp@dA60VeeH1ZXudĘZ.f 9LDNY]vfeSi6ijZ ܐ lv.pSbN (}2 0L~F @v(΂Ƙjg!5N}zp7n扎 >9ve4 !*8,[_$% s x ~.<MSxSnLbIWDG9530,,++,,,,,,,,,,++++++++**((!!   &&##--111111111122222211111100++''&&%%$#""qkgffedd`T( D5:<9=9=8=8=7< 6: 46//*'% "'+ > hqqpol#eUJFB:432+ != 0 " );$IN&N4 O@ QNTTUUUUXXaaeffgghghjdm[ A/14569GNOPPRTWb{ ȉʒǦ!5j̴ܻگ͕B~~ ~ } } | z y w r o k h cWPMQSTTTTTTSQPNKJID5' qH*\ȰÇJHŋ3jȱǏ CIɓ(St˗0cʜI͛8sɳϟ@\IT/&NӧPJJͪX.TӯW")ٳhӪ][T˷߿DiWRǎ|˸ǐѺepԺHBP, Z4AS^ְ͚C61ȸsxʱSb+(|Ҍ:̝D\KR >:riJ նy<䱈i8`r5u_Ev5DG^KflU)V| (ce~w`y&F؝Ȑ*=h:&Tji@m#6=։GZ"@C_(uU$J>FXd ښlj菒y1 x iQCW.F H`tIir(n^tNaHzf|gp+0ꨢZ5\!:iwpݏ&eݜKYƶ0 -+ 9*ZMhuV+au [uYmB΋v7BDmp9` diWMb[KEtokT/2;4pl1x0` + F,ѥKLzfl4,E O-tQN O ϖ 5+x=bS,\AfL̰Ռɭsj_c#{ O_]يKN?3vA'7r+bޤ~ަ7T$밻nY*@A-p,]oc%{-ouc:ܩWo\){=ѳ U;H. w do{-h߫v&v^iGtk27.{rYSZ9b r~ l p>ݎqʃ؊sgCӿ8 #d TYQSȟXS p3_J6})| BM3H tû81OA5!j ]w<:xbڢ*NOaYE 5< #_tD茐S}fȹ w%37ɉrkT?RW,S 12 9LK!F։04IDwHZ'+ʰI $ٞI~*bYY^r9q) ߆N'̩Bg*!y:sjVj)(\@1Ά;gC~ɛ' jjMIBUЋ8N$'6ҢAhE40rǣYiHM2Ҕa( jdTɥdJL~StuVBTMH RJֲffUIOQVm\%"]:~tiͫ^wֽd|͈#9 ¶DcmI$8Wm.ve+^3ԉ85oPT;W !R:K+þ@9bW* $*+0l^HُV!)OyšC8 R`+ݘi #]a{W@!wY[Kh1$ܱ=qaiE>q sB/L+籑=7ކNyajDŽN{5\ vZX}aqa*Sl+ 2C ƔlD[Q V̈́Ra cch^y'CpTtg1?/%(c]$Ǯ}z2ȩ2ld 0qJG9`mh]޲̱ciF\\Jֻ|gyD<N}RXȂ!eŔjըM 5vFMR;LjK%_ZowvaLlLVCg3f )i7ڥer+kz{]ns\]jcɰ)Ywd7moB"!ЫT?ۉڟ8j07$ 6@]9;[<ƨ/2ΧS-ʪ՛|u/˰fA/Pw];~/AN`=KZ:n < h<2vvݻnpCɻޏ].G୹ g"0⥷Ư<_&?/y|$Kco:61 f$Aq_QoT{=ImOu3T/lgPo>4c#^f4p vKg+GjS xu&C~o~2~ ' t p|'v1zp p}'اvR-ޗS1( VsgRHZe1 h| W "8 8M38U9(y"')7;0=A0A}Q Gxgŷ ( |ɧ#|' 0 +}hxTZq $W rhxRjlQxXw؁v؁Nҷ 0 80Hxl2ĈY&A&{WCv؉~tg}%X.}0хEsaCNPw 7π H8FH WYxc׃?8LF`|nX 8Bّ#EAwiZ Stt*OJ׏}1hō䑾d% I'Yqx24i^6Y8Q:">f6/&qXєœRCTsVTX-E\Y^`O$Y[ufWY˖T2Q;Bx=z=0i~vmIH9)WZӘQqzՙ:i=vziK Ěy嚏ŋrUiKYSyabN94S/33N=6yF֙:)ٞ(EfCi:If%E@Y:ٗ) yYѩP9Ssjyğ۶*L70%r-b7sÝՠDg%6$U'.)3+jx +-4*06ZS8:L<*$z@2 S&  3ʡ\8OU*q>ե^)`j-L璭x !#52#1"&顾'5&w*8yJ|h',J a*+ nzrotVvzѩȇP ؂Q0"Fɦժ(@ a, >ʼnt|0 Z P#K*PȬ'= !Qz'JPM 8Q + HZ0 x 12:&6qPi!bHaw"A}@ |в/; @ ,K ʰں t:ƀ|$ŴatQaj' `|tϰ 1ˌ-` [*zp;UqKPKR.*p{|bۺf PPGi)VQ*ZIdjjHu=w ;y[ԗ5 @ Ϡ ]vː |[}0(Ʈn`4<7 " v ۷{]0Kч880FI z[K+4[¹8˻P˵_%8kNtڜOgPTk;;}{6K0;x˰ и ձ X+|"뻹OQxMѐ5 L̻2Su#?$&JJ ѧ|(l˖K;r1VR6La]c\e.RL~&=!٦ >ɁķpVoq0Hg Z.^%&䒭3M:!'}hmhkp>^t\bچ>Qm}輎lM&mMm 鸌ؒKe. ܬp֒,MT2>,5eĸ'1٦~]~)nnmV6~(:&~Vv$nN ?^!~Xn0;ľDo7sIFoSPN!BqF 3ARp pB0V~k_/mqo&OK!}E'+/O5a dv\jp]M!GmďC $PB2Q"CNĘQwxQ@TrȒ&큄hH5mDNN<᝺TPEETR՘0STU!.EUVXXU<&ݚݽZ$r; |w/ߗw+&;oLx2x̓מܓlT22]۸~>[lڵ:0d޽b[Wō[Mzz[ܶ/S y;Tw!ۻ3ozqs=K#f M]9ΞsrC0A wS.Bh+ KB CH83('n5Z{+䑋¨$M )4Z/3 Eå$2 샲+))$JR|K5wzA3D3M@D ̈B,*d*n:zɤIq'ƑjK%* i0蓋Ҍ-y+ۋKvK2s2Ղ@$ CLYeYiudMM<- %[ ӛ̢>[VqH'JpENZzRP+ՑG}Gԙ(_"sы=`Uխ,5sҟ(ޯt5^Pg@0#7Z*edsD{V\nāN8õ9N3DIDyVZdҮ_Lz%U$, AVXҏ{,~{V֘" :𐺧F}pɈY$ٶ{gr% sNx,^ݴvK#yS[ᇶդ|}sr˚TԺj#{F%.mo*׳ޓ©5|cؕӴZ|C=>沺ͅܪ9ahnd4ivv{Zzzg%@o>aD\&Ӟ7yuυ;S6ã46sևpoҳD2Ym`35BWfEJ'_\ <ScAh:I6_PB>66̖#9OJbX&!cqg#*^ʊ,(wA +W:TF<,cy6fšX-HLUakq#R2/Z37ܮZDfQpxN=X\1RxdvsFy:%(~$I쬸|Qi%k4[de+8]&o-ضgavW)&)pƛ;eISЁ͜NB&i|N0/ZڬQ*`gMU /+R`**\J+.jGA8^H:kO:$d yVAoOHFC> `=D W|jz, XJPT򒥍F9Z+w'Xƫ +YE R@ΆlEI)RԎoMJ ǽ&HעP%u0e"8E6da#mkF==ց-s'Ьl$6" :іi[;n tBv*qNoi4nj0"CIu[}9PN5bbbbxwTP fg{eXSPjE5!xAol ߮WC%◶t*ʯ~wʻVGڀ3~rG* 2.!2cKf {wH]DV eg'YPQIÏ "| 6CNrU|!$gwKve<XZV+9z ~6Y;S a.Fԩg-X!sU:5edLU!r+eRط^= 硖G1I%nj>L{ 8|ڳLdṽcW#cW8 ytS'~)Sv9 Tg]\)Cp3PgȲ;yXɓUB7K@.Ue>:1s:EBVzYNpf 7_~`W}$+;.[ nS`Wܦv>|`Si+OcXN\'< RFw*=ȓeàޑ$b(TyO_^P5|S>Q뮷wݷ'#gC2-S=7أ6穥 ;386p1#H1rI{Hk6Y È<Ї#Q@tBtX?aSW52# 1 ;B.Wܰ.!#C {@ Ӱ >>.S)1}s!91p+Ğ+A°APR 4D@D`LsQ/J)|"A;)ܯ-S[ÏIY&$ a8l4D3(c+D":3ߣac";z ձ&v;< @, jjFcY\īHIrr,oL]L(&l…z ]+/-,-ʼn XT1dhSM̸%d|bb@']B q ?AƑ)rGM ӈpCHlI[ǓU}1'\d{=ܵ5\d@G@J#`$QD'ϒ? $ɱ K{ oIhDYIszDIKLLKCIa+xXϣE-K]sH(A=E"#3lC$F|B|`̶P!4̓0K@˺ā#  #dR|ݓy,I|3EVKF(qE@8=6d5lJEGʹ'WI:̈L `<\լKLJ(F3w@tT?fͅMd4,N*{BqHbHZ{ K@\L0"˹<1ā+ *̴̲[z '4MT LKDE--PK2t;$?LLLbT3T ;4&N%Qr. %I -e-PQ RB%t"K3-Hä/D3cbCs=LԉR"T=r7>9:;=+S=EI>}P-M'UNTz UBZq撮KL'ݱ CS4JP}VLf+^ݨS>8E IV= WU)X=ƍ[庥[дa5XETy5aeTku%MȈ #TԽne.M2Ԍ NnP>W#W@4ף@דTWaגrWx%ѩzUt%iSWPUʩ[c-Xv6PLL؊ܿl X-׏5uǒ 'וQ8UP=Lz9<;,(mEa՟P,|%J}XGjKcVW]rڬMUU!&KQ{CTeĂ۠Ӂpԉ[e0eѷ 4ۻ4ZK%µXتeX];]\Zm8oC\'M$QXP%VXXTec˸USڥ Eܩ@UMZ^mk^x =^tXNWSR"_B d+'ٔMٶK_]H!PK^+oZ.E_F+ ]TN5{).eŅC[Q 2a}Q\ 'X2f\@b04 6^ !M<eB*{ #bՅ_E_*,.]E:v"O5 6b4ÍڪJCa91:<1=!>[?6$7Ce%_ M,>=E ;1A>SXQ@i-#;aPʌlaF朔H7LT6/U ;FBWV$XvY7ZƉCAJaY]j%=8E73q{l1yưmE4Up-q rAstN{fv6֗dҝ+`c{օ~>3mfNhWg{9.δf}g>Ӈf^荮\V^&'_4-_B^$56-sHi*>N6胾o_Qߕ_Nߑkk\Hn-0CgjM6ΐ$O%? /:  )HZ>nbgЎ%"> fa{35G6M9y-p c[e4usyR!ꮄ drZ8b'N޽MoXn!&=8gc&n4.<y&WE)zd ҴK[к^v~V|mj2GљtiCV$wu@vw)vpY{ck#=d8Gn`Y1q-q+oV-qNSvG^(y:u.\)r)fGOPfL{sLjSGx>1?"74T5z|W>vY[ewVGtH9gwo-N'{&]Om#uxxy|ʧ 2hύ_ }{p,h ‚ؽkx R4"DN,Ə!XȐ*!G&|Dz) SVKS˗8䝴qH.48=!rԩӨRuknԡSqسu?6Zk.ӱM.ƥrҭk.޼z/հ0Ċ+.eJlYgǗKKUJe4"H)nV#UyF;v0ĉv² f}8iU[֗@en_ ?2f׹ݴx+n=L?aKmV s[u6Pb9Q9"On͖K$;hQ[N/u<ZtkPu@Zi7(Wb5T^EmZn?Tn5}QJ9%Ug}%J&ba &Uԅ9ڛikny'Kcb5ݔ"Kʜdtҡn6|Rρv1_2y9.L)!)Ň֯!δ* Ui\a =&p` R2 9a@Jpƴ +A:R$x$FIՊz 0Q)IeF׆+!|S *rgt@#% = dqcbRMb,-hfN= s%֎{yX{6h2 :֊)4fZ뾸ʟqb^Ty/E&lo 'y$3]DIv5 k[Oga5k6%9.y]) pXwwR A]ZQ9kGqTOԆ]3=>EvnH%F,I?*817Oo,ȊpRNmTNV#on'Cok_"%q_ A=d,^_?zD"~\RGIdCZ!dDV*DE*QDxUr%8Gj}abI&Ľ#u%TmDJ!FMm&vgBųmaPǘibh'!EӚDD% P;'Ahq'f)4]Z$ %)\fb2͆*bNeZz韠IhvkH]'r٪\(S 鑎FyhHFiŠ+ tR[ vriVPHh`y+Fօj j3XkTzYJ"uV kY\UhVh,BVqkvEņFF2Ʀ^ȺkM%FlNdhxZ,XXku汩K.gКEnV҆d8Fmϐ29*a צmdiDbȇgvj†(z*جiLթTD Uߢb"'A8Z 6 &`d-iI*+j[~)cxRK"jݒ\N!J~ana2=(F/DDEHP.\.ǀ2۪R n.E~:WX.F.($n&ݟNDNU0 Bmư,.l6pH7'4&5()67*CoQsq1 ?2;; Ƴu~v%'j.QخUMiM Z´ꁨHi 0C&E;gWHrr|t$͑8`0+oJC4K4BXrL؍,QA%PBMCCKݜM45:%ĕMe;s`ɸtOC/3K9o3C@[A'5 #^G8~r2.!d,Ovb^1V?l3uR+'2e+6hu\PgAukkXɮTFƖnqZo˕^ &d[F0L5d 'r0tahO7E6f`wPgw/5j` HGynjq&zKoo7XUtY ^6s[ro^ xBf6aش^2wGxle<)2mP9c Hwed428m?,DCM86!B5h`yJt㸘ĵזS4;8lV*7TT8'yvw#M#uEO/FᙶmV4}ToPp(8( \9¨^ z 8#N5:Bςs"92T 6RF>ʅ P_ȓW楶~U[ZVkDFO/Q%ԃ,滧A¼^K,BzS76k5_tukFf|.Cxy$ڛߎ8#:r eT:K:4$<Լ{{;_ hG}@“c={o&t}5d>//|e0PƉcr{^zF=@hGAF8bE1fԸcGAhG\Q]2dʕ,d @t،!aO?:hџ~Dfiӂ9:jSUJ *vٝZTBe:Ew_9uSrc ỵS}7ӆ "P(̰@Dh I<9_TW^:crZ{s_ZRT&:2yG2L kЧ!ۋ-p/(T6 2PFĪ@ m /ȪpQy:zB!nH tډ%+Ϡ *(5+("nA!h|-tJm: 9'ی8ā400$ʹm|+QpK1TS@Aɂ UM"<L2s(1me*5CY(Bl+&VM蔷$NLJ@XI4ЭkŃ<UosMW]:TjTJwxC]˭d$tIB+WƪQayOהųٞ /f25>8֠_oݗa9vq|ߛT9PYI=X?r?Y w5ffJj&U:%=x1T3 E*ۺ *YeאlgoY(;>յ3Zu]ŵqxM6b}ء3x?&lJ2C},a]._q}`J\ :xŲ2 !ߚxcT_Ը US41Go駿nT]~gmx;a54-jZk0ZLLs|hZD cp}1gZ4_^{Aܦ֏5TRh*(Coq[ 8ðY@%NKCF[UBVHm\ieC91S8yK٣JL劇AH.Pt^.8ErAQ$@%Cֲ$\壊R+a#;~$M?[Z$~C& 6VD&-3>qA* ,ZcgH!5KuS7M-w\櫏,'KqIR©A a&zJ-8I>y0[ʹ9*] Ͱ^rY(4I9NӞꙧ8s<4e9LN頲9Q8ӊ`dX=Rc[ARNF%d=BYCbو#,x^JB dɎ2. {NS=hCPOLUZ`2l~eKSEuD[W+oaaftZ/9䴨JC#ǴZ2d{z|,УjguhyuYxA\e3f3eLB\,ً\tl\NktA CiT.䲀РB}ʦ!v97ηͶ_A=N+zFͳR8ħf@dB S0x]_ء0DbѪ.H7L;^-/ Ѳ\[_$cޡ[J7P7"+l0h 6 m&fp GY8s_60.5N5D` ~'0hHpQ&Q+jcf:υi{ꭽv>nU{Qw]C;&wՅ--D^!d,f},s/ZxH|⪷{2x/j{K[ ڄ:պ{2=rfKq1.o7}{31ko׋3a]Jfs1vtU|Bp4AL~t.m4/V./"kN{84("/6B)#\O.!O"l/L֣z=B0e 0uDnC2mYv&D0*+&0L@JP BO$0b6Kb'&]PpKP=Jp o!~H0Ԩ$ P?0+>i"P /Z}"c${Qa|& ;O="n3"ڰ)0 FO/eqLb1!q >ir1C->q=>,7N#V7poӮ<'tQCqb|"QB@f@qq Qcwp*`oZFq'ʎGq9C"qyfZϏR==* QG8 MH2(z* A \"Җr*p/v# B# "M!OH22(&Y%Q*-l-S w)bA(h'(1)b)(Ҍ+ r 1)$Q i2٣%3=p:&4cGz./+R)Nʪ61-!B(1*UJ',2{'8J8s)Ms:K.'z'K/;.;Ր0B0R7e1=3UJcw:"R3z<;;]6GS(ӏȳس=C='>s:"SVs9`S6 4ntBTAAA4#"&(/CK(t=sԞFzDEyFEq7gES:pxrF?:(vAt~TI S .y& z6 kF@N>ثJejK{KӔAtLmE)E'UAAC4OQQHO?"';5?TBcREuT'@I2$5_R1S%BPBM ( O}JIWNqWOu*RUUVUUQc/h5lGM(tH|o5XbXX54 Xi'WkST!t?4wUoU[[ [!`585JKogC^^^u!ԲP_$`t``q`gpa?a!b7mYӞK'0W5g8ocAvOSRI_THV-vIb[ggjvwng%d=md{Lel]TG_6W败iij\c)XsQgkhho&lelTK6mmmIZvW'`_goAo&pҢT'4hrItKrMI0w4wsOpTteqSvum>V7VZu vC\vqq;6rers ws=vpzwQ xTvuhYkOyyyWOt&dDe7c!o7UWUw||1$0|#Ebڴxm~M~~wWIחRWf ww8T 8QUgg+WA3n6h; >TgwFxxJ؄'|WXm[=_#cnoj1gy*7邁Vx!€uvXCT!ׇUU&:r!x(\AZ |5X~5ej%Y5Uku3p=D!qzN].Y:oP*2hיkO@z=N"KWA=ˢYбQxm=1Mw78U:Xz']u`Z~e궦Acq*-~3(=e/!zEszC"W .7H?Cun ۰*ZCQ+=c""k*EŁcA4Z .2eG>YaI}Z<=099Bz8;(hmP{C֪L(M_;./"9d2V<a͙y:z4a(:á([ {OO:9;ڠ۲.B\LoȸQwY[F{s։"M]KO=|#\({},YR w}=},ıแ>ډXY0#q@D8sDQ^=ޝ%ZcG^*ޝށ/Lqzǿ!#i!%)^('^1#"q ~}YȾ;Y bͽ뭞-u {*|><|H5e [bC)+"q:PIݡ^%G<;֗i7q;R?[*[I뛋֙%:9N;y1Z .]{6ƛicϰ1G5Z^G}| ^= Bo8 0! :,X`+մ{… 3zqB$K$ 7k֪ux2+qD,1GWZjcȡD=J[ˊ=Y4ԩTZuЬH5 6ؒ~1D1c 7.ܑa7QJ6m"[M]jkڒá [=&i #)&7qc)܆7Q6Y$؛.)%n5ɥwuݒ[\21ǚV>DdDQ-o?H-}_ $g!$W~ݵU]b *(eN҂ h 6OwS+Yui>ۊ xoAf0MwT8 dxWdN>WcuVZk薕^EaqbO>gc ]SՀ`Yf:uHCJjV QDZ:i}?41:bsYPZSjJQibaUvk!gT i79lٍc)'ɡhԣ60*J.jabB+E+N|Z܏wltj]FtBq> 1KՑՋI_H[lv)]4Ѷi]Nf1 *II6iaG+E臕Mb֌I:)K8Z+2I뭾\ l:5EPi kv1"Fgxk}wI: q?1\N5\3cdH ]xXEG:≜8Hܛקm q}dh?ڮ>wʇ7wuu.r{N8R!C%˲NRʙ3^z׺9\П3M8W z_ю!V4">8ڏecMgxi9al Jr3q,ˈ# cbT|ˏӷ2d&jŗ-zA0ItcydB1r*׉EbGnpkK"؛0Q`>к8icjE4">2&MĈz")6Zud(V$ :%+7HpC\Ö虖X tv$/ȳ1cep`8,*"f>S XVw ]H @jsvŚ)HE )Qd+ufD_ J]>ڟQu#) պhNO-(NP @H/ٲ`M"撎 R(!$(Hz s⤀HH8jl>|wyi{3M=Eְl8*7$H! 'i^.lDhB}*Um**:_"b!FaJ1t-#XAYDH^4X=ݣ{8P  ;{&d8y>C4 3tyʍVenTNwsomL,WĭkZFȿxU.e:8lqv|Y=@B:Trc[3&tANLMssҒd&$xkC |ego$63.IɸRU[X'u&zAǏgX3y, }[{({`{xn'p|$QSB~Q ӖwA|W||E+Sxtx@_yTCAW *6q_Iw~~ic ugC'@[TIǃ&pzi3o(h$"H]|{soRyw{gwxYX3D3fcw,fujNVm᷆ւe`d3@M_Q-0X7ovYw'DpH(:zLp5,W8leU(Fh}rķr-r(sfEHC(nx,f$Xx{8t8D$qVi,PJYJ& jEdK'9/XT*/ȎWQEqCrwm֦X(UTax}g'AmW}qV7!"8Y(e@4nP;[='$'G툓UDY5 NS>yCi} y207vEO,n &yyeHa fAuTNHIwuYM3)LX!iiwqr?7D19IG;9=@|X>N A}xqI8":pTY8(8x`T E}BS*[o–xpىX{iQa"9wRy.~B)zx q#YBh7Wvpvc*͈d"3a0nr 8w*ǘ嘌Vp2h}yNz}wx6_I a,jy[)O.K)2wc':$$|*N8B9sh;T3~#Xɖ z"KÕ&Z$9Z.g Hf晁b J; MBpmc:  Z (l0;5YX:*K-걥pU[Ntˍ\᳿ 1wE{rW8tN]+{5\U`{K ~Ji˳Rvo1{yS@뺻z񳳲{yэg[[«V% y) [ Z̈3Q콦Ugvkȫ;09EÍIK:zZ۩B>szx%ש-6Nٽ<X\6kq+sb\d< 4\|6lHnL^雼cjۆB^1 #J>a:[iBcV|" 'MiAʙxc8{k,Yg׷'q!{dq,˃̌ X\b hqɉ/*Llc< Mu(ʎc̭o2}P\j'L<.QkBeTB)'< d ό - |î_3Y,Vk#RΥѫA(z-BJ x1l,il1Vǩ fM+)}5o,= &ļѦ- BeęֹDk% bt=*3}--;F=A~w/ 3N}OH탶̈-&Վǭ|,Y}K:HǼ6Q֌hӏ\? ۭ%j}yjΉwԜۍ|k@ ̵])@ ("Wmb])M ᥂D;#0%n2'.-Ե==ф;-i^S|Zm Q\}K\t̬5M*]揢Zq0ၴY O@E I ]18-4dNT1Mz<)\7{mf-սZaBUkެStM1mwі tUӛ~LIR53鼐f}NW~f5(COwG@n~uF~䚾_оy\.n=^X؇ a9LivX!nC#@t0oFYC *䋬'=mNVp .$L]8%iR0%<{?vB@~_F?KM6N6&m^,j]?#J OLfO*^+looni4_WA힗E F?,zٺ}'NOj80͊|lĔTÐ8_QjaoO,(SixV8 Q@@.d!7m֪icE5nG!ErT-ΐ 5YM9u'eh";K M@F. SQN0gÞJ o$rZM귈Y Vͷ<^;O֍\z*VYKƅo$\]|"jg4]٧?67+t"ʌo AU.8ZH'^ܸEDX 'E ]AHѤGt:yɲznW$Z,uҽ;O,?k.K 龥Zk"qZ@ o؃P!8qS&['T[jȂ+lB(ZT8"4H$;2#'4pR&y2&VJ3(<<)1˔JDlO.\,+*&+D:G0˯/$ /IB*\t+E2+34;6]*FIGM8ՂǐB+IZkV,O{N˂ .<_=S6㉛ m/*!_o2g;[K }* K촤NkJEe%]WYqES+Vej՜Bʶ"\+b[u%W;^ XŦwY=VÕ +ZSE09մK=%_fRK T3;tv\^ 3<MYM'9ߠS4B"krkwN7mN8o圳Z6q qp&\-}Sw'uZɘv \k~pyMq ']@XnCW%UN{*|&,gx'Ky#Et=`Ӡ piKNmgCB-KB;nQ-fVh.c֬烅 KfqQND^S{! :3qs zk?aA?;cAʻ1999 bp۸+Bj5R@Ϩ\r@Ji1U%YcsEyDZԈ[EpdA_F`o3:0T3D \HvQƸklĬB *M|)$ЈM C엹*CesfM +4LL.|<c:0AЪ3T%ڲvaOʌ Pgdi%1@N!OԟD$t@䣦k>ؔKQN1<0\%yQ#MM|C~ }R}J@@pR(4`PsP\[ Oār#BҶP ̅0<;@ͅ/K PQB@$ө$F۴ρRE ORMJ,HA4 A1PDQSuGQ'oi{UrsHHipY?@@тW1PUdJXY<؝VHJLEҺ3M>v45We$ժͱS\USQmyY ]DqQ&,ٺQZ[#ͨZܐ<ҋ R\Z*)}(]P[U>%H98STTEնE ͙,@#j9mT۴չȏ?_Q%qճȻLƭ\yXGQئ(#=K~$ޕ+ WAMǕUy 9[3} ];Tė̡WW+M%uGHV5{\ \\<4P+-מ+ -wE]h})Uv F[Tj`,M<>T $3jC?(͇z`OE-'Č%8QB]1ݦV'.R  ^ȝ_$N.3ԃ^@Xczײ8Z؆eXIb\].5љ`blL !WVL9~;NY_HX"W@n@)dc8Gv^)כdjvNfAOL5῔ܰͮEnuVaRXΉY֊!eVÇo`^g1bLAf-sr&gr]0fnk #=; gY4DYQG?1&Xmgxg(,{nWgV&6؍^h@"\l;:>'T,huVgw&X9i ]^n[N߬jc>Oy>Íϥ6ئnhj#)-+^ٰJ&2U\\_lz&vjaNAVVf7T]뤥`bΛ@ [01 4&;&FlԹ>Vz rln=l~ai{UmԫÒ^ԫ%EZn 詶~WᎢΉ!n98n'vannU.KILW<NmQ>j= EloZ6o0SOm͐o pI7@SdQtjb\8?&1틅pl/ejj6>uQZ+r\C; /*7%^jhMDyd@kfurj \ Np@XpQkARmü7Ή©eiPs`scdY(;NDuHs2!҆kgm*cřiVB guD̚ 7vtl m׉{ۋaoK[wN@wjvw \VJ/oh ogyGvb1Kne^6]VVxxh@sxy rII ?pފű*y^u[yHlj6pTy$ٌY)Ok(ٸˡju-ng _Y7E=YC%(n2{C{usq8* Wo>%zfk}8|hz1%7B Eһs`h}h\$yWhh6.w*W_DYVz}q^ {ٷ%}߯k,)#ӏG7c "<7kմ}[(q"Ŋ/b̨q#ǎ? )rdC#. j$9jH(s&͚6oypٯN΢ MtъL)͡5VLmPUPNkQ@⨲x[h.$&tt.V ,ߩZq%ؠ?6:fuD !WW¬Ӿ -z4ҦOg4RuKc.-,ON욀.X8nNoǽ7rsUyeVx=Z'AeW ߲pQHkM䒀`pe G=i8prhSyIu8[eÝ(y}&nM3ʵb8?VΎEW_s&ߑWOBeR289A8&fۖg]!"&g:a/ƉugBEʗr'~UFE7v'>he% fg] \á:hcljޟ*7'@:[i]uRF`E&[h&=RKNGZ"&Q mw>Ǫ-Y˭ el-Mgk."򫐿DQnWhѯR~^7zıDf³kY%:enx2uª\Ҝ1*$HFWtiFk??SyBJ\gP߄u6'53mctCoÍӦR)㖵eU2wAeG{ !{A|h]bq]Kʹ;w ս8R{Iգܾ l\ߪ86nj_|Ŧ5PyRj#{pk;_"m"?'e~_Wo;ц0Jhַ?L; 890Oh 1Vw#(y<`'Cݸ7+FNS1hzD/ V5@BS`^G ai!he-;a]J |+!$ˌPkbE\9MsIV+J,M5X4?t{c2C~>ԇ)O]A#(36ʒoܑeGE<҆NӜ:H5 ;GHj2),W,IOr$?_4L!Gr%pKEQ'obAB? n4BW 7hyr{l;ɲ'Z\W9$smK!kzmIN8Qp3A]g3Z6pȳ8u~N"nusmNwV:aү6Ym2xVai+7Y5p JRrG硧  7^}~U3dzxhr7;Pۉ KiI:ږ^ 9?/[ ߇) 䵝۵_ _!%i~ LGœȽ^YH@UYaGa%YZ L z%F 9 .՝}ΑSՈ8j.aNh-۱ ȟDYm-  !}! ǩ_4 aB!x*ɡYPGa΄D(`!!b""B#B# ^MrxCL'v "+L}QQaY&n% Zj@& -c5R:ʢ4R"V#x"JN7 2 #Ab+M;NY<_O*ud(HY8 ueDLZ%凡LneMP Z`!`xen i df u/O^E "9%aeAq&egnVlc?hR`gԤU܍xLv#Z\`al[]^cfe9B &!4oFXpp*SbBV&Z6 1gm_J~{>rn"I֧=h(Nbf adg%:|e.("X(h({2{*$'uUi^Xf(6 dDe明265e)$_^dF> tYi-5);%jViE)$)J}vg脩Gՠ6Pvv n"6Y=@pZ jtjNQd:Ʉ**癢*TieԎ鬆e ꘒ*iΨS%d-5+dUh~)d\‘ [0"j1Xq6Q1h_X7!.",/ E$% ;iA)  3*(lk"p)"Ң>o,/1E60,*[r0ͮ'N*/G9N30W^sfnsen^8Cs9w/R0:#k;;!"˳__LuoSDA8E=hjBT?#?s+&׌& A2"[q.u.3)nx%NMtA)P |9s:Kn1' #OL*xM/ْnN3+IJu,f<K&1rSA U{VHTXX'%PB/\36.š-2S8W _Z_c%\B̂`sguoc>6dgYKr2^ nf3g+MOgtY5Ju>Mb /7u^'s81L/FCNMfo8B uPwQvt 4|:1?Lϔ_󴾝]ϖv3h5~gE=h4G{Ywjz4²[!sUB_>#wQ4R?L=tys> f|l#~nqw{8x:>\ o{(JokmEIZ.wWH ߥ/\g{ut]oOypby8Ho,RYޜJ$+3Xgc5.tUy`9ӵ*9csd웗A4V#՝w͗]b+:Ө!ȶm{J7'{Ș^++Օ= y 'Řzk{8ά}S5x;̂I{ Ӳγ"N6 6:g H'Bus+1\:F ;s=¿ cǔr/$s<+ u/v|z}<ɛK)K1;)L L / Z z[&{o}|#<<~Ң;T|˯6ѧM;&?mxeO=Wcy#6{:;zQ+k3MC-i| -P%&#tu(ϧ8>GxYsVˮ=_S[8 ~.:>Ӕ}9Dk׆S؋py; ZaF I?Q?gX6~'q?三TW3[֧< 4x@@6tbD)VxcF9jdHIrX!JpRBZ Yg΍'C 9Ш£B2(ԧ":-*UPUjU+U^ɎtSE5s&\ p`1IxI*Y|r7W2Ҡ9wthѣI6}ir3x7k eW>XJM*sO4{c _r0&e Tj۹wYS { 8O "XIT?s {%+/H=0;ć+Q)k 4&[q}; F6ġ?,"D/EVdqJ^T5(13Q4\3$!#RLL%,,KS %L,H%<7sќ欭L|=tr*- EP%zИK4:OkԶ(@˪Ϯ޲JW<۪1MC"R-Sg#TT5-a@FXd=Zv#E0al,vq3!Xp5RC}4(Q6jK6A1/i1Vz-bK7bUcI`1G`OBD0r=,* ؞X;e:nJL=8PWcxY'.bU݋whՌڡeZcx@ok['L.m>Sn!@nn&!WkGM]x^rWxG'_Y}ݴnk?t jMB2N}%v6/T(?9uJA?sи%41-Xvkk+=W &)H QIuڧi-MP< Dy$EkJn& Nm'Nn[Q[^Ѯ &H~ڵo*DJ4JL%_U W ˦vK{kvʬJ푖RKԈR.=M[/-0Óأ-AEc#Y862aZJlvB;Z^DT++BĵyOlXR ln[-a9cZ LqRBXQPv[_p0 x!%hQg:v:}2ta vS/JꙞ'`J5G n0J|Ox d\\8bn҆ae~x!^s@K(捏W|:gNMv:6 AB>Pӯr9bHxQ&xIfvYLIE|ʷfps\K곡 h&xU3 *zѸ iYN":Kc,Ƒ!u <I Z3-&:VPH{dPcQl*:0Ӝsb^ &Yѭ%,=˦k^hB{R2v[$ױ! ` =LZo#o31 Yv ljScq&dﵸ_0Ao\g9Ʃ `z#WrLHU7慹9 |Y!<u1  #L_L;: .c"y)wA(y{-DRtxhz"jGn7 qB>Q tbG>&>1lhrH~֕*'E{t :|IB@<# ~vV0R 7쥄H;_}r*J'6$_}Pf-dɍ\/ӏ>2"e]/."H@oCo6.CObȭC+DKz.~TAO^X^'oRТID"(ҜO RPL| "IEI9nju C pЍNO<`Of4͕0UxρVPQ*PeL*Mn|# ;cO, qE&7J ~!c M$uQY/Qil#igb1ԤщQQqP&Y _q~ԑؑ>ܑƑ J!^Qe+ mIK g0| ѝTk$$o")0rr/ ib Qd%%;"" W< ܎)/49(G$@_2b<jG&{=%+o>2fE#2r2-%s0G00 !D~2d"V&"n@G/%BJyNSdRSVS c!6aT(e6q6+7/{grD 3!uc+ie2<󯦓"r<-%%u4WK?L*_Ho-A&suho%3=C==۳2>2sDaf?4Dq r A4[`3o2K 'BgBB?G1ts>5(Da! D.AIIՊ'PE=Rn(5rF7+G%㢂]ʈt.Ig4 DT[ .Y4M" Sb9a"4"?jjOt~شNtDga CM(c@@0"F0vT},x$z.X!Wsu4SSoEױJ.EL!1SrVu?U">V%HN[ITTO 4Xq0FG5!,|TDXgHE?]RtIIGXX͵\V]1b^:3t[GNITDcXQˍ\ Y?BYKLHn& sg3c;4T;y'aEOhQ$WYZTff-Vq cCS4 k7eW; O7\6Y.9hc17Yծ lV36g!dHQ)`kgߦȅasl0PPZV V!pvn +osorTO)pY9fPmuZ+qiJnUc3s-su?SvZ^JOJo3h_V6CpA7tW(qaqM3r}o5A7i5Uus#L(tEj5ygyyw!bSzy#{%v{^W'c<vwtAkN~74&al#q7nՃC4'}g{yk~zxM"8OMVa0-b7Ԅa Ry†oXr8Sxxgo?wlw)v^8xxEV/0X6:7{5[{ؗԬxo7sWmWW x혎X8Bo'wDX5 Y"7!l5WT.JVQ4Rx[8J+F x?59yrKÁ_Œ'8]y-819QAW jy5y׸w[U)t t~O_**,v)mwK[L3rkk'9hqØseSٞz7yٟ2f Z'H;+!8x+͢3p6:zi1QU~X\br5'm:;y;uژ>:u$1(z:jZe*9EYr>mzz3bdɗi9zfg:/`y:m٠麮'Epڜ^I뤁ڰ[Ԥt\:QV̫ /:R5;p[{ [ o Ms%?AIZڝgۤk2;U՚+9-۸3qa;:T"'[0O.;O1F݊E,P{ھ۵i[;kaIP <dqHqpvµ-ga|R"&io;e{CiG|,K?jhr ŗ,pŠ;AAp8;yQ]4*5\ã\Cq[vPT>F O/W7\gXrj9Ǭ'=Վ~'T,| q =|m[˽Yp-J~[o9ݣƩoܞV)ES M2_׭ъҭV=8nǽLc~{KuL+[u2=!\_ڻ%7՝})d1؉K ^}$sl#}}39zw¯'I/^yir79,bEw7;\]nf_jo^',&w&]_8[xۍ]]=n|y>nޢbQGtx^êٞm^춾~ǫG~}dwL=9PWߵ7MMֳt3]w[;f)5_BNdRz3jc?J,ͦnS笢}FA1AkyyZ^^y%M}t_;?_Yp>K?p_'> pHZÇ#J)3fdǏ C ȑN*\Ȳ˗0cʜI͛8sɳO~Ԡѓ~Dv#wMJrjB)XZ*ׯ+^#ٳh,VTpʝKݟA.$ڶoǤKv*׳X>yxq[1LrDSF˹Ϡײe:~jmc[w|-*'ᷡ N軥yE-PufʁkF5:DUή;O?Ze;Y8qwĮv'H5Q%WW{J|lZ_](eׁE1, ]҄&F"Jޘ8eLYD~DjFP:Vw!V $oBv9j!i_hsA)&FS>fC\6uZna9 i:r'Dqη裐F*Rzkv!hjT jvjH*+\*Xyug'nZ[d Ҭ6SBzj'h*>[[ƶ,X:OҚJH7nU+0nT{ okK\ZpOp GwVŽY\<\Ȯ,l0Vkd7?4Aӏ\ҕ*<`Jjr%*X4PJX nP  U @FBGqP$D{ ah ; Yt0i Hq0q*,nq" " "@:/C5Q@bІG=D4ߜj(ᷔq:jCz Q2G$6HIRbS9N~r %:!j4@J ÓE*lbR4(H;H,drFob&y%jFSKhtHHP7Pya4*YNUl)-e'A0d$_ӿsF> 1,{lI5(A P)E3ZRaGUNIfӫeZtfLzNRRe #1l*rx=Yi]b8*B;u* W*ʛuՖ`Nz͜oqbHh'EV\k>t~vVB nJAI1↣YcmmMv !hA0r]4HRqbrLl%#3R2@Y'JC4&P1bNïlLbN5V]կ ٯq4kZ-t}MϿ5U}DPR>Ș!WfʰHЎ,j[{fodO9Tm[ n-\暼G NqYm4\}ͻ˔hC)7A縧A QN3~yb. W~wnWO8&φMӣN,df; i?m#:j{_qttwS?<L}]wOt %cx׌!ʥw]rw=`q=&}{_ݻ&]| 0sl5/Cٓ_O. Ggg<ҽ]}! ʣ?@a~0}}N}a }w4x'f)bDeH,G~g1y A\:8<#'Axw>VG3')H+"cBbǃ烸u`(k'A>v&A„sjt_eH*Ç碅…}Wb(؈8Xx=w8xbxW؊h1x`x|7{:(:'%OCrRHp& 1F)A80 STBHE%h.X8\x68\8*QeMMJ=*8* >꩘JA٣͡P b:B^4DW8 y5t:؟兜4A4Y]Ў"ij)B).6yD *ߪ T16 ڟJ NZ TxGG LD*[@4 ?I+KZT 02 yZIZJꟕj˞8 )Gy1p ;XZ+5k!`AN>:z੯ :fNI 8.[;R]vSQdi9ꪯEWzDYI:d) jEڸ( [ɷ`{ W\G])Hjy]s)ۼH^;3i6ΛKv{x!,22))Pd  ӰPӹSmBB!AA!  \M]YalL7̮PN X>y)i㧼XTPaaRb22b dKk`RbTSh33bفзS~cSҸSKЯPiRmPcH*\ȰÇ#J4G 1Ǐ C)ALh ɲ˗0Ĩ2͛8s.YaΟ@dУHB@ӧP4JOVj}uׯKvزh8WnZ+Sv ūoN~,0I†DqDƎ#3,Aʖ3 Ĭ2Β?v,zҦ N-x5k_-.rov{޾Nv8qƏ{M\+sB'-}Ucz;w޿/6ϣ~Ï_|>}/ϯ9q=G`xW &e`,=HNR.`Wm_~x">b蟊Yd'xX2b݈A:HP>nFc>"82Y2B,R(bY"r#T yTejf: goyvYg0%`zjƔiD/%.%-)1$dp)Nl :ڠ z*ڟz[!1A;Qۜa{q[;ۙᛙy( a:\(A|6:,ĉaZ ƅ ay'}<ɜ\y\lCl'}s2ݖ9ia- i]q fA 'c wr7n'wfV7}xyxxUSyT9S/ظR;'Y7GWgYan> TŸ<%4q;,{}ӏZ}ן}ۯ}߿zw; }>描~4?ۯs ` /8 8?! d (@@p B `AD AP-AO+QhƐ|cBDP) e@ P+ X6CC44 +"!0E@<"6 F6: @$ _9+BʐBd+Fj ˃@!S2i2d%=JO /Ȥ2 ,5aղXp< ` o[ٺmrej\j]nlsK̮ nˠ{[bWaڭh7^ITxw] E{_Ɲo}!_rU17`ͥRHv߸zt= : .p=5|O<PE\0' UqY0?pQ#]u1 /3SU&O=sZ X(/Moq5,U;ټX0Y~#fl85_ʊeܼ]3'YΖx9=Q3m:BЪC4:FѲ4$m;Jo 4wzp7j镚z^j{^7kz.dDznd{i,~ڰl0%xp | @\1RlmVp\ I H@!,*d22    곴H*\P #JHb Zȱc2zIr$ȐK\$J0ct`2srYSM:J'PHe ѣI$* ȧP&*AFY*`ati@@HpϢU+B*&] `߾i u8h, aʈ/E@ʖE|QϹ-'hھ:N4 !,22    곴H*8…0"ĉZ,1FBz(QdȊ$;DQeH,# !™!8 ɟ 쩰 Z4(*8g‰O L\0jU @AZHCtMlB ̭6჆q0ᅆ'LlW!cIFX.Ӎ,XyW !,A22    곴@*\P #J!D3Vǂ~1H(<,]SfTҼh93@,SҠejӤQaR*T46C!*J+ړi"dە۬55]gV%K_ ]@D1W8@ģ ]0@i- A$p?% !,zB22    B 곴D@*\ȰÇ#JHŋ3jȱǏ Cq$S\ɲ˗0cʜIfNɳϟ@ gND*]ʴӧP=իXjݪp*U`ÊKF_ͪ]˶ۥhӾKݻ6Љ߿ oÈ+V:XKL,̹ ͠S^بr&`M8_`sμ-@سk@I ӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgy1̉<2|2ʶ2ˬ2̩<3͞|3Ζ3ϓ3Њ =4чtB/]NsuO TSf&g^31A!,Wz22BCM$U $((4H$3@,,8:7# *$( '3?B;-..:KLW;8#"*#aW<'?N1HW 3> @*\ȰÇ#00ŋ3j|Hō CYNJ$S\yI0ctR͛iɳ';} ǡHUhҧ pP j͸`*U^JV"f@1`pv` !"˰ $ha p ƒK  0s`H^ͺװc˞M۸sͻ ND\qS2G}tA^Ǟ=v-~xG>7|_B??]B M`.F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,o5`58`8ۼA 6o'Eh BMT5%j=5tXۧAwaR!,}U 22BCM$\\,, KLW,,8,ł\((4\,ꂠCDN33?,\,\abl@ `‡ 0 N"nǐGcB+!tyfL(ODhÜ: gBA%*`"B Vˑ  غU*Z`cpq :Vij W&B*|H! ȏ6x %.-Xa (L 0 HK*dK0 !Q,cK&22BCM$ KLW,,8((4CDN..:33?,,abl\,@* `‡0ň):`FCRE%MBDRD *|̙>1@‚ X(G("BE8q* iiق8Pa-֎gP!L {PnXA 2` l(N :~\0d8-_,ɔBh3<͹V4\hp4턪 !=,{ | ~ ~ ~ ~ | +6ڕ8Ԓ3Ʉ"~{u nf[MD;77<yAmEf8T&KC 6# 6DRUO>(  5v!%(./111111122222222222222222459;MAQE]GzcTRUOTMPEA#zvtssss1ss>r@oCoDoHpSrbogmhnhj m\&wT9NCJEDF+B4oJ>ʧ/do''ODr}oKg/M?o觏WL/mNQws# P10yp*> O|X茂 `5y2a!BU!WBEЄ g(CNBA2vU HLR! hX7gxX'áq?2rVD*h bBPp;6:jb=3x4-Y#CE@;{YL =Rg$ŵgdAɜ-`d)sMꬓd&yKKn2"j l6r?rg1/JZge5Gѥ4YLd@< J-j0s EĤ99bMsXMpQrT$iI<B$DD':E.Y%ЄXVb(Gcy3җR8(7+6sK}b2'-iNqvT'Iً_V20w&TBҨ:JA9ϏªpOiT|2lfSɁFF%<Ӑt<Δ:֥E'p7 &3A ^P#dbQ`! ONjZH26xu2d5 ״S4mNC;s*WV"gc*`a;J 55u[Myְ1lnw۳67ik^QA9b*ʰԝg }3:f~ & ٙyfg!֩BvpVIP s,mgo nZmvgp%S]v^P7c\ ȕJb *0ʳO= U#6=`M4 o7u,.;Р)42+تA_:͘ՙRNwu|qR]Z8Z csvMVъM8hF똩\4qdDSԀeC]T)ֽj h%8&Q3WV ~p$e;jO&Ϩ f99NYZ3<…1[foG[ h t]jAqY>UUnr.w{Kj,yDsN =OHl]G|r%sJB+}j_'^Wٳ⦖B/.IyCf{aڎFrp≠Wr==o@]j{/]usP 9dCnX37IcXp7 yXNmB7OΰdzkdVg[v hqygJm`TDL*Rg|lG|WTtPEij!HR^UK#R&L3HnYd4P%T0 XFlYO7Ԃu~ObG0WXF\67NQ7Kw\Gh4"4xO KXG<T uts]؇$B$dB(*$7CGI<%4asonN^yur8X燞>=D1@x3 ^xqHCUӉX#? 4 ȇxË،hGhxӌܨ}uҨ eHؘ-Ӎ8xlg꘏gÎψE8IphG34=pI. 8T ieX 0yב. ) [>@=DYFCyJLMP!́ !Xtg* *b9dYfyhh΁17B&l)@f 3Yy٘9Yyٙ9Yyٚٗ 3ٛ9Yyș)ٜ9YyؙI̹9YyYݙٞ9Y rP0I@II(` 9` JiɡK$P _ ȐcӢ%zZj =Ppڣ0A rKC*2:60J:p* Z>jdZfzhh`My mUjZRP\Z$8ڣzZ* [g:e@' /%{xz㹞xڶz*N;lk۪ Zi[ T{k KBIj멩{˹k I k|;Q$z kˢ{;ʼ룰]˰[i{ѫa^kz YjKr rz޻{ ٝ t8 MW ۴5۸$>ڿ"AJzۢd{[<꾖+v*0[.Jj PR|ɴ*VL{.̳,H\`, a<]*̪' rk{=ƈY@J ڪ˰@|ǚǃ; o;Ŗ|ɘٝ.,KۀYƦ_;|ʎ˲{;yʚv=мcʥBk/JO*ߊ;j<䬝Y\,왠\ژ==]{; ى=]ѫ ц"=$ .T:č)p.iӌ ^ʩ8}*]1όy:6*3=HJ=`Ԝ鼅ӕ̠J[Ҟ|7]] ʣJ9ZL*xGͲ| aG:?Rܚr]ح yM+ݶr=ʼ`Vכ٘Y{ԡ͠ 0j\=ڨ͘a˥m'ڣjȭ 2qܘk҄ݩRAϺ kJԖmٔi:]n:؍:Z:B mKZR˧{}υި۪r ݍ?ǹ*kJ޺]nlliy!t,۽=^Ҭ]0y p@F^䐉vz䉙Kˊ1*YXǍX^P^Vc.\͘m~nݱb "kz~|^,s0lB|>}.}L +l 6~iܶ| $dmܣ.W: ʥ-ʴΪ箳DL׎{m/K֚+JF ?\ȼ=_, C/0*δF.P[-,;D*ȌJT$FO{4|5C%:yHn? tk.kC+FK̊;;{{3;V[;>[Dz;z}[Kٖnc>+B|<,un=l_-prߴ]X`b/POgָO=/|]a r y~<,n~ɫZ^:om\K3a@;XP d\ɄRWl"'H^CdA bd(ł,Q"V$Qc$3AyhL&+^\ذD'3n\)0ҟ |i*V%΁kbdJ -Cӓj*K'ujWR+L9Ve׭}Z^"eQRjA]XjrXɥEѵNE4ר1Ӯ^:s]=صsK]|fj_-_?)v"ңvu|I~&ċbi" P.A@zςK0+2OxK)"*8 &ѣ 5*h-pEas,˺ci+Lj'2I9tr2+ t.qB[L3D3M5dM7߄3N9N;3O= ЏKGPm+>=/D=pR9H43 17s?=tGȽ->Rle5ԗv-d8m;^aHza6A9&r)Ý%cy؅(aqg)-:{ Ar6ۂ%ϖ&w/>尜{"{Ƈݢ<์Yೝ;H|>}S6V bKrT P ?IRRoR PV*d e(k,2ChLM`!o-̋ճ>pH%~SEK:߰FS#V43R>V0y4!*W#B }N$$Gs#ۗF2m$fWGJF~iH7JRҔDe*dձhS=X>JX.4,F;Nm=JM`A1 JhNsc̈bge'&؟B:BN.aNޘa {ِ7*Q؊,ZQq]h~S]~K]v6,g+sOS& VvDgAWˋrf8OG>Ax͕Mlp;FOEr9hPRaZ5/-E 4R43ҩZOjjQ,VZ<'IgvD .T^(e<*/sbʭ O:j(bh*@Tj bb ECr~`zGᕇ,iIUvֳmhE&VVCbZJчR '0OumORی$=K III$2$&=(tW#]f q9DsSpDEsnPOVVMje!ź.@׷DQ=3WvW<ſ#ư j3kg8ɿ*vÞHs͡<&ss7vf9Ym5iNwOtE=jRsuOJQSթWWַƵgk^:[FTFv]3$t{ljW[ӶvAX=jOwwhAmr[Fwսnv;@{H~9"3 {wK Q[Gýp7zw%.iOx5Qqy)ljQ'G9rOye>s7yus?z9 GGzҕt79zԥ>RVWzֵuw_{صiPV7óJ {{[tk{}|W@|x7|%?'a񚾀;-5A@C=m@@/zѩ>G $=u/??|{#(!|7χ~?}WI@Di 3x X=4Ѐ g}.P&P ? оS3 t@T{X @E@M,3Rt=4qD%"C`3#t'p@o*+,-./BCH1CM(7@Й 8<<8C79lCЁC9ѱ8T)]=@T<A5CUBEEeT-UFHeGJKMeLOP%RQ5TUUDUuWVYʔZ\[^ղ_a`%cE֥4defeuh֘ik-jm֋np]or5$sUutewstxzy|W4}u~؁%0-؃EXx؄e؆u؈؆؉؋崊؍؎ِْ5Y<ٔU٩#ٕuٗ5JٙmSٛٝXٟXڡeX%ڣ%XEڥVuڲOZ=QڬY;QPڰYZZUے% ڴUڵZ%[۹ې[=[ ۿX}Z…ٸ5UUƥUu]Uȕ%UʵTΕT]TT5SU֕Su]Sؕ%SڵRޥRmR=R5PMQ4= L$Ť@NLNNuߜpMAuϻh%A=f=NmL%:Nu f^OfU6@VaLvlaˌaìab !6,#VbL%vl'b)⢬+b-/c2064>I4V6I6v8H8:H:<>OO \hwˑgSVi:͐^.G>g&6eine6jLN꡶;[~nCXBK?QrQGNIkfCkDn빆vIkVǰS&lе.ľWfӀ]Ɩl~^þi"͖"4hF#jN.jזúFΞm&FiKFnk~l4nN羓{lln9qߦ7nHnnjVo5Kޜ^o/K Aeo~^o͚WoUV)6QN7omѦp^޼˼lxƺȿǔ`/q^PgiD_go;9 CyT$MǤQJ&CPN%]z%^:WAi@`&m)Af駐o'}zoDg b*(ߝ:q9z)jcUP`Rz*>8a&Ùi:+Jdt+"K {,*:,JŞkX(-jNR܊;.>-b,.kP Z{*XA̫. ɣN;W ;R?<ƫw+l-<Q-|kgBUQm=cBN[IYԷ뿿W$[<,TpU>IY~pAQa sDv;!e$ q \#ΈN|p^QyP"k2XqF>"8V#h (9gt#屏~ qAR+' EB)<###)I$&e&f̋?)Q: n0Sx<0s sx:0x8#.1us6+n1SӘ431?s2;1 Y0C.2r$3/Kn2k) VГdy^J,杄yf.,2͜t39Kt3H=oD|se ?:2i ]ZE?~]-iǨϱ<3~Ҋ4@:Ԧ a-Htil-}AWӚ1~o;zs `yNmd+[n m-K{VlL 6Un&YR(nBDH=JJ)r9hNp{ 7eiSުVaUVW76q$.9Or|$nA sx4ǰoN<9t }.wLǯӟNߨKT:{uj} swdǮNݴlo;sw}ĭ݁v|ǭN /K5rZyP//Gu'?G~-)'v _/Z*^m +uOkG~-+t7/ߟ>{: 8%z66= ZN4U:f2m ~0 /࢝  0  1`̀Xmk` بUJIU\%a1GUN-P(SeaX@T[![Hj! N\ʡ!ݠJ q!Xڸ%b5#]^\ $6%Jb&c~bf^b)K㍢* "6b"-Α-"7""//"8 c#1^1#9)#%!,W?jE22U,,TrrrJ"9>VVghP))6\6Ⴁ5\#QӰPPIUm5,>?I&%%\-I !! a&x,PQ,ʹմ,-- S\HH\,Sm\!IlғC&a ((4,m!,,x,\,!CGGC$\ғ,,#!,!..:؂,,PPȜ:: ̮PiѭCmKLWT1133?iiI&x!::abl` *\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜ M4sɳϟ@ JѣH*yPJJիXjʵE`xKٳhӪ]˶հaʝKݻxK.\ LÈ9ǐ#KL93[X|ϠCMZ%v87-ͺװc9 L,qͻ |9ȓ+_μ9ROwNسK5vasbx!~}h(ZXؠ0(㌁բ\@<#YN(DiE}H6PCFiXf\v`)dihl&ąMD!PKix|ֹ<Hp` <&CPVtM (0wGvzfjꩨ*무jfJp뮼ފk&첧6F+V kNPbF C覫.;`x+Y*調 l' O/ĭDVlq~!pizLA!Ϭ&/*?-ԽLXg]j<@,vA t?G r\kpr kv}zq5'`+~!/NC bu+PG0@@jB 륪챛3ww-n)ņB$lBnDϿ·,Ozj.@- <*·{*mwjLp^Kޅ |2.9ϥ/tI72l~ +!v2Foz$ t6Cz0.6.$a %ęHDV&ԙ^pUND &?^ȅ >0}tXA*x9p`ă~(+9wMGU-tmŰh@rqVP`7C4a+8_W/ՊCɰ=<*O6Zp,E,x'u!=5 )T2Ą'űQъ%y/{`P=^IF`Vd;YLhk3O{sVtH,봁5@{g1Z&8Iq}c~0jV3GCyg?ϕnp.))6d t)'MJFUVK*? 0ѢilZpLIKjSIuHj*hW_EՅ\;*ִvYWTUmU\K.쯤k_km],bUX2,"MdSUف`|ҬFֺ6k}SY{ œjEۥutQlP*BU1#ۍs]V}ڙn~Ɲ.tAm5=)kǢ PW8(m wIWo( Yl`* T}|%0 s\! q LE x=aQ.3~[IDZaȮ1wLNG~2+RePް*ku2;17˩L[5׼YqW:&ef3|jF).A.p;kfc]CVEf4e-'jtȜ0s.8-eIf]i2(>tOhV؟73uQ=Q{n2s]R ȀfGF’]+hKi؞v=G{a1VMIlbŻfQUn;Z.5eUR?" .`,|zϽ/ö }ju+/iy{8`1WGgczϩrsd1G븪-< 8m.ٝmn%\A};0'Y#]bԱG5kӊ:5+[=GQDS֣oh"XkN*PsOqV@*'YE7:ٻ}fO}>2~(_YCMïπ˟YAǻ7XG-v,8{0 Y {3, `|gyX?'uo5rV~w{~,/s-X|RrӁCrp%RBT{w2,GFW|vqv5yF,8Xǃ,'V:?)+~O){@3H)pȇRhH%XdKfjJh~n( wW~ԑ1/($"1Ut=!A ht0wsXaN'F! Ae(2( Q@~͡})Qtx3r8x[?θ( 'Q ˆ0P$aH#XX_< ǂsr؏/(sQ :sp :, qa<!,cK22vvv  eeeAAAttt&&& MMM ؓ pppBBBuuu[B"FFFnnn  ===8= ### e YYY  6661"((( aaawwwfffzzz;;; @*\ȰÇ#JxP@3jȱB=I$F!M\R$ʔ-cʜ%L8sySϟyJGF*E(TҧI:JgVJS+Yrl֯^ɪUy5l۴ktܻ=ܶ~s+È+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNj E bCx;8p~|V.q <n` V_~88݁`t {dHY1 ]A9%PAPA8GC(qސDiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp=,0xm@5@A (@pNj&l ɄXhɗ&=G8-sgΟ{ J4СE8T)PMSO<椪)ԮWFk2ҪdM'۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCs@^<@j\F:kڱm.\;m޹};7ăހp} &zr+`ppZC`=$(O8`8%Aj !,3T22    곴 @ DPB>(q"Š#b1cG?N r I"QVlؑ%H!„fM8sɳϟ@ JѣH*]ʴӧPJjt@\9@Vn5Wa͎EX6Yiݮ6-t㦍no]@`[f (.W*`q P &$p`e 4D@jJ@!,/22    곴 40B >q"E#xQ"ǎ?bx 0@ʕ,$9pD ys;o0P* =2$CG4Eh5m@U j'b 0pL m-`ss \@W@"H q-%$ !(,522t$$ :HoHM M: o   t__  otm mғCHtomCғCCmm$mCCMmCm:o7mmCCHM H*\ȰA H 0pсÏ Ci 2  0ɛ8spb!x,@x8 PJMړ*DAG 1YJQFp݇U.[Lʭ)a&Qf乁p=L.D 0œ \[ӨS^ͺװc˞M{ "؍]ڭ5 ͟#ẃu #En? [:ۥ6q֝r3,:Pn Qt-xyExZwyi}_XaȜs.ޅ0P~)v MBpUx9&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜vg]6A4*Q/{XBiTSVmVZu^%WD"kUiQXp%PM&yUh^}]kMEpøڤfИM%Fl`)jf l6Qh9P'. 7G,Wlgw ,$l(,0,4l8<@-DmI6,."^ tknPEq@ilOnpԛcSd_z). 7SPUmD5jht+O#-Wngw砇.褗n騧ꬷ.n;`*<'L V|jw^@ %wQ@mmWQSTwk4.K/7ljB2:"qu0|E1PGUR^4 u/ Gi?80`AF8!,/"422    곴H (Ç`ELD ŏ3jXG E4h$J*WlØ2Ҭi3!Μ;y(Q:tO6.eRiUZTi(gÊMY TT2.07l]x \K$pb^ "!$ܱ2%yg&Oܬa@!,W!22    곴H *\ J\8@ĉ V1č=~@2H I^<0ʎ,`eL3@3Y(= ҀJP*eJ T*TdE*.R@AvH@İ+H ;W䃇.|s1c$|b.ysf=O\gz!,R&\22    곴@*@`‡0ň):`FCRE%MBDRD0c2e̘hxf;G@Ђ $Q p@QSR L\0*Ҭ@WjWp˷߿ LÈ+^̸ǐ#KL˘3k̹ϠC ҦNw5k_-*Goީ{޾Mrmiս5׳Kwj!,R22    곴H*\ȰÇHŋ36@`Ə C8@@Ǒ(S YҤǕ0c<̛8Uִϋ;y ѣ %ZSJӫ2 pU`QjРׯaj+`hʥXӀ;/ݻ80` \~3,@ 2 Aa)[KGDzX8JZ '|m͔wБC_.}!,22    곴0 `0a:D1bÉhƋP$ǐ"38PH%ptfi,ـΕ@ @u9@"*h4Ej &Db`+ͷ_p 僅uX7eBe#tw$F# !,422   B   곴 D  @*\ȰÇ#JHQ@3jȱF=II C\ɲ˔*]ʜIs"̘5syΟ@MQC]TaRM2} UUTjtעC vٜ m6j֭~ k٦ko{n<;+ P PQ $Py 8@A@' KM!,22xx xx xyUxyii++mmrrvv  ^^tt I``6PMMQQJOO::@@T DD--gg&&//6612 55VVqq\\ qq))SSII''vw>>  H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_^u˟Ow}(`ih`|& g6F('*Veᇁq("~ h]#rx,%b `a4XhMF}4(ԱwA2u yGH<@>0%+QI#`( DI,~D IA^byAVt@, @Mj&J @IhA kт fB3II "('<7eu;* x%(p0a !,22sHH tUt ߛH,,ғ&C9HtHғC~CCߛ /tET\t߿tH\\mCmCCtt .,m m6 \,XF,JmCߛߜCQ $85975,B,<mmmO}CQ!''Ht6I6tPD$tx .n x Um ҥ,Ŗ,Q\- H\d,,CmmCm$Emt\߿?CCCHImCCeE!~ S\\tHCCmH*\ȰÇ#JHŋ3jȱǏ 1@$WXB\2d0chI͛8sɳO,LqѣeDʴӧPJ 2hIT"U:Sׯ`ÊKUeӺ\۷p=ܻa˷߿*8Lˆ+^|w~CLe/ϕϠ'f3ӨS[:ְc˖z6׶s6o,A +_\?MH~9>7,᎝çi=$Ͽiuu&`e.n?d`Iu5w~hbY(tH$(YHcC,Fxy$mw@ecGH4dPNFiMdXvCZ&dYPHi_yliD)Ix @2&ʡ7" 2JVڟ3Rja*ꝧ**ʑz&ꬰZcq믞ʡ l;PDPQY`촴! A.L-%l>熫nr+HPָ+/NPP;+V^Xn@ UʎFLT=HTAAȠE *KϚ ~k; 4|fB\@͓m7!LG͒A-Q͟Xwdri=d pmmM|wxnxڈc7w-9tW~eyԜ3Kmr 'u4DAP8_IbN@ p2@ oT=ML@ {^?8A6OB ;=S >-9uIP›ʗ>ۥOĚv#+ROy;":bQ : `!D@ A>PPÆMP7<~ ^D$fL e(RkEhqbkF]Q5d,#Θ4UlD߈8ftI ʽ2,thTpVJ2b Yn &KXiz(ڂ9HA;K9,l0N^7sqJT9Lq]j'c +s1g|IL?'tnI-Y@3ЄiiCdP1!t (a$Qi0h*^KHOjFƤ,"IӘ^quM=tai~ T3 PD-ڨ*LSZǨfjTգU?լqW-Ҿt)+_ΊVu/lmk*5QoK\ e|]ceɯ)aXvil\ H.nN1[)VfDgYВ e(iQ9vB,^ [N PPRAmJ(ַMTpAwͭrG=7Yĭ \jWQew^O{ moZWNH}˦˾%=V|%ۂ/fa34xˆpY.ah,FK. XAKO̗e,Ƌ]c_3cxqW~ +D.pl0+9s^z֚ k:ʞab۴Omc:fyM?\;N7Kۢ4ͷB~cRXG8N89"zsS wk8(y=!(Br@5 ӼsE@<@z!kZ@IoIjlG]Wy\߲a~ 7'Yٳv{2n;~vtg~|7ݓ/yOߧ[dRi)H~O_|nj+ic6߶f $Wj⟷Zra9!Da8A7{ f Ɓ恊!6}G5a~",*h{13{57z9;xz=( /XA?(zEGyIKyMO8yQ .8Q1'AgsljhhwsXuwwHyHw{8}w"pYSxve3(9f!aG8҉&(:׊7:X a\Nj W !QG aIE(=xz8>[pnn'[`hnXF@Xer8cAA:bAH! r_a@XZ $gQ(+X>yP6P::@*DY6CwJiGOL)SBiWU[~ДFqb^diip=׸Z l94nI^)614|IIuw@wGTؘY8qٗ)gE Rc4X)%F鉬ٚ0m8vq؛8Ĺ`viQϹaYhYwxIyG9WtlyQǞ5y{r:wSX JǠq7ʡ  )IiiC )Iỉǩɣ飾 )Iiɤ餕 )I|iridɥ_[ W)SIOiJE@ɦ;6 %)Ii ɧ(Hh爨⨨Ȩx)A gǩ驔&Ia񆪫F8/ Ģ/課i&I1ʫ")EhȬ҉  %Hi髟ȭ  *% Hj/ Z-ʮfhkǯp'JzeӪŰ E9Kj%DZ걓'JeŲ7t 0s';˳)'? ('t DK:9`2|.{MaI[KQ۰SkaOK}[a]}_ ba{cbegbiKkKcUK[ocmu;dw˃yd{ }+ev˄wq+c:7wP(GTh]ǹa蹥e(jGiǺv躹{+zǻ~G}#hGʻ} };h偽8ּ'Ƚ\7[{uO ˜O {OP K{?)ȿ-X,l  ,+-[F8JN›*RH¡jV(<*(|13ܪ5<79|; n/ =^;C:tfbExf G*|HfjIŀn K*Ƅfhܤjd|ko̷qs,lEXǭvǀQ ȥ(ȢFȄkSȩm)vIvǎ\܋i|Li\\hLhܹܥ܌gL{ˡ_X~&̥KajΉw̭cq&ͱKejcjͽgM"eFki@ τ _kJZmluqKkoИq n UKѿI+HDkks@u< ,wJ7ky X+ԷK.lԾ{Բ} j, 3 @Wa=1j]4`BdGzQgP\Z p3`0؅}3`- d}`Av=}UWMeQٓ_M=ؔmqMg !u-tnMm =\];͝دͶMܟ-hƭ-],4m&ݔ} Ւn6ܣ}^uMɳ]۱Anv~.ܜ]O-kq}ޝ` @\;\x]>-bM⽭-&M^m؝JaY\ZWEM!#%' )j*JjㅪLt *7z.`vIEvE-jV1eaγ~.i#!$)Mꪾ>i 2T'--CCR#<210,D "na0/Ў!>12-0Ϣ췞-3"^r.2Ϣ H 3-Ϟ TG22^!,22   n Z 곴$   @aB88@ &6hqC9Z\2œ$KDɓR|i̍4OByp%Mf 00@Р9x"P$zAAEBh`x! TL@VhVD 1}qoT~N ,!a5d`~+ b!,22nn7ZZ-d  7=b-5 ba-  5rE߆->i<;vv;7ߜ5Ӗ4ߦ=ҏ7cI2c1w-4ܤ=GH'VW/я7zCcܒ7ے7bx-45K-Q|P`AĘ1# ;fAdGLL!ʖ.Yr&M3kԙ'L?}:TJGDTHOMNŪծJ5lٱ_2V@o^MK.ݻ;f wn^V '2[e ߦ3~_K/ x\ywi!VHY!6VC 앑8 e)H"4#b:"#?i=9ЋF>*$Mi$̐$Z %%a(&Ix%&L e/"'Y @6PW(8(U(E4(KjakjrRkwN᭵ګr8m=&롳2,R뫵b+J[q)ޖ->n6n^on[o/0;&{ 030 z zV Ā$|U 6YL 6B*I>cO W 3Mpu4VgKP{b_-]ermv\www{S [;|׎;^<<;8K9[/z]V~Xq{~>37~ïG^7}ܟ@ Ё"P lvpt/ rD!G(P&L W3ZI҃P&[ăP%ED;D(D !,22s  &9 /E. X,F$897B<n !6D$ .곴$ ,,-   E$ZH?E!XXȐ0hHQÃ+jQ=V CGLjDrdʖ Yd(s6q gK**ɗ6]4gӝO{F95hաWf=V]~uv)ٮf)9Vm[eҔ;pܸx7ݺ{u:ja&kc veLaψA+͘cӐQKL,kՕ_=yכg=:coG`tDCx} 'f~EA3 ( 0̀O)ZtQ8awbx!yq]x v 0@%H<\e p@xc#E>dCX$G"P/6@P(T9*)W``f dh)lY'BPbQ9`'"+( HgE/JRbM\@@`D*#v+Ί⫷ں!VkJlpjҊ6[,:kV;-J;jح~˫%f.ܲ뭻+/ {׹K/joopۻ0 DC`D`:`'U"+(rRl2τB0ysKRaP$1# 1M4OS#[3|u`-vNw /\5R}i T 5XӽVc^߁7k3޶o+7sS^f'☇n䃣^瓋^꧳wιw7: ߸8+9G^}?}W{>SK?_?aq? o ^W" h= bA & D> `PBjτ%$!XBꏆ!\C0L:t a8C 1?#& (*Њ-b A-Ћ3AXzpd"fDH=r5#AF!,22nn7ZZ-xxd7xx=b-5xyvvxy b͔a- 5rE߆->--iii<;vv;7rrߜ5//QQqqEEӖ4ߦ=Yҏ7c>>``Id""^^gg2TTc++oguܤ=MM14w-mmtt 66kk12 VW/я755zCVV<<cȊ\\ܒ7:: ے74bqq))x-~vwK5&-UqHPAC ,b-j1ƍ?PQ@Yr%K*_t)a̚6ixs'O;{(NGDTLO:U*KWĺU+I_@cT mYn5ƝvnEKVn_p|#^lV/Ag ?Yqckܖ3̗-o]tRMQGU]uV]aVsiۧqֽwk߯>x"_>:_ʛ3==w{g=xߋ?.# BNGKSXWZwPoc/g?[ -ܭнZ fi@O StB5LuS 0 ]:0:;nOnϞ{nؿٽ_˫<͟{dkϼWoȳπ_8?*3Aρ`4? `Ex@&P3a)B^Ѕ ae@~Ѓ!auAvІ9d C"Ј5XB&;bC'ЂED*.ыME2NьUll {@q<~ o(H5rADFF3xDd% HJґk $+2"&Id(-&gZF2%.wKST%-oL],c2ϸ4\d49G$4)jfҖ6Imde:]NXSTg<9OwS5df>N_f=9P}&a T CQL# eE#! ,5121212121222111122224455??CCEGKFLDP>S5W(_gn~ sxtwuvvvwwwvwvzvrkml j f d c e ghie"[&X.^5}f6rk7nm7nm7nm7nm7nm7mm7mm7mm6ll6gg3``0[[.ZZ-ZZ-ZZ-ZZ-ZZ-YZ,YZ,YZ,WY+SW)KR"DM=H7D/='5 !," '12" 4 G Td(m %r1v8y AzG{P{LIIJLL IB%A3@SBpF܇MR_ab`[OLIHGEC:2)|rj` RI6%   "-6#F0[;lD}O`vֻ}wnaZULH<*   H*\ȰÇ#JHŋ3jȱǏ CIɓ(S².*!rIrɳϟ@ JѣH*]ʴӧPJ3իXjʵ+ɗ."i3!ճhӪ]˶۷pيKݻx" S/Yn7LÈ+ǐ#KnqY3k̹ÓCMɖgװc6M۸FC Niȓ+;KNسk߾99pbY_Ͼ}_ 鄿P>'/c pN 0ރFVTh&Pf}(∴ ԂC- 0`hG}:!@)d^&6"k 0Ȣ-ЈTNO<2Ӑ\vUEu`I 0-9Eً-ANjSN6$N3N~:yg`r4矜P ;SvN"*v~O3BOv:cNnrh9i*(OjDөZ6D]ᲚL:xE9πtLB;[3ѐ^IOta6ҘQ7 iDkEљRYWjnF5VTZ3e}k){=ByA9FvEyJitINi*U5TQ[SYZoM^iWycYdIn]Yh aecn9mgrmq9v)muyzly~ l}mkgm9Yhg٘kh99a)cٙy[OYi9669FxCI"¹9Ɖy%ŹΙY"j9iٝv9kY k鹞lyyymj|mz}y yQ :!z1ڡdơ:$za(:*ڢ.z0:46z :j<ڣ@B:YF &I&Oj&&ZCj#Zڣ\_z&`b:1Zg+ ʦF[joJ`js:*Ƨ} 4꧔F*.jƨ. ]0Vڥw,/*G*Hzzڪ:YZW@<MWpךKˊjNZzݚ L0j犭늪 MPJe1Z:ʭ H0+; (۱:j')+.0%:BlD\1yH̒J&N P9TLV|Z܍\`b<ƣXfh~lln`rt\TxxzH~LB8Ȅ̃|6ȊL.Ȑ r:L\DwɘĚuRnʢ\Ťx|XȷʬŮ ~^ 'm^D݀@LFMHTQ͇S}Ս\^`<ָXf hjpmrݎt]|z|-~<Ԅ]ȁ}،І=ٔі}!ٚmҡق$ ٠xV]vڨMjڰ]m }x}іۺlKٽ=(Pۯ.7m r;(Mgݟ {& -M(ދޔޙ mM(߰8=}>~ ]J ͝n=FN]M".]lM(.*D.'W40~v:9g@.?>=F<@'LnE&^ .R|G^\dCf~jl,pr>v^p͌a͏u>4ڒn}ͬ?->tx"1o~~f뺮"o>Q~Ȟ*'̾>^^ھޞ[>N۹~ށH>יִihbϠ]^lif Y6 oh?%Q&l"y,.24_)8OXu>:8DnCJLPF?8$VX{\O[bU_z~h.dm_o/qsuwoy?{}O_/o?O_/ﵟo?Oɿˏ_/՟o?߯O/o?OѥK DPB PD-^ĘQF=~RH%MDRJ-]iP`LięSN=}TPEc4zfRM>UTUZEtU]~VXe%fmZmݾWnXL}@W^}LnR FXbƍK6cʕ-_Ɯ,"jZhҥSr&j֭]zjصmƝlu\p&\re|tխ6Tuݽϛv͟G/UOݿǟ_E<0@oD0A+P0B qk0'0C 5 71DGD1EB:>[1Fg,:Fw'&$HH%drl2J)ԨDr2K-2&,3LK1DC2_23M7pMڄN;ᓳ%:OdiO?%9@WPEPe4RIYs4%H'4*ERM?U1NO4TSOkTJEUWR$V_Vb%iV[w*\GҵWaW%6Yeq26$d6ZYi$j?6[oŴ\s.re][wގ7_hi]}!~77`kXfՄ3Za?}'XҊ/8c آ?&ϐ+dB2+` UЅ+i e'3KbCvd="F~D"NdEDBD&>JM"I$NEE-]8C1e4 ј!t;G9^u@=} 3!HEΏ|#!>IN|d0m'JQFl)Q-B,D+E+D-<07121211111212121212/A/B1>86>.D%Qbm tw{ ̨֠ٝݘߔ{ tmf\_]ZUI8$ "|*h2]1S0M.F*4  /!-@/55>>)IJ)SS&XX,YY,YY-YY-YY-YY-YY-ZZ-ZZ-ZZ,ZZ,ZZ,ZZ,[[+\\)__$ggmmqq ttvvwwwywzw{v{vzvyszp|m~jb[VUVXZ ^`c~%hv,kp3mn6mn6mn6nn6pk7qi8sg8tg8sg8ri8pk7no6op6ps5rx5v6|8=DJPY^ſabcefgiltxlh[`^[dnxWH*\ȰÇ#JHŋ3jȱǏ CIɓ(S ˗{V*ܦMy6ɳϟ@ JѣH*]ʴӧPJJ*OXjʵׯ`W|v͛ڶ)h۷pʝK]e˷߿~{Zw+^̸ǐL˘/{0ȠCM4̨S^ͺ5E~yl۸svͻöYBȓ+_iУK.qMŽ7νwOص7XEUB N}(zu_!*\0|=9蠃}f!\+ zU!H,с{%xN5EO% Tx@)$R(UdBL6 0%g:) 9 C)HudQJ>lNe^SC<&p%p0)X4=hOaD< Z(O`F(Olj>J꣥)QT)E&jj Xj꧞60Ol?JF뫡@٢,*bRkiJm^DƋڛeũӜ T9pO—, aERĺ0+j-$˼ u1CTvԪ-~3_{Neufd˫lEoX6;@NN9)85Q48lxW[$#|xI 0˸ʙ;M1.<֏۸mz靯,P8qN?5bX줎;G(ؔE uY̥?LxH@cm![ h>Aavv$W#3+~`T08b3Sͦ=@|`Гk{;9z5 L}LY"V-n*i˕ q*ʖXeqBwR,Wu hfE/QY٦ƪE0ebjU9D20W 7H'gkHR ܕc>9"Fn(P Mv%ث40e]/5!flYΎt/ I3rL 'GJТ]'9NRvJ~ @J Y{8ą:SU`@j> RpBD/3w!,fW900NGet <`%ia#5YFCLJF !O_!'$8Qq ȀX'A(@4$%0 Ђ@,6hq `(B6z8(:ȁlg"Ȃ=@V؄+vWXu>80k腚bh774.(4`y8q~׳~+pq$ i؆4A'Qu1<NPW艌ljH-x@tJ8HXx" ' 4H5(xXH֘؍ǍXG明ˇ؎ǎXG؏hԉ8%rǏ ِXǐBY-G ّǑ"YF&䆒*ْƒ.2YF6:ٓƓ>BYFFJٔmƔN_RY.FVZٕf]^9%d/ƕjٖÖnkrY/gv$x)cSUrX7Y ɘ D`H9{Upj )Y{$陱YLך*񚶹290)ęf(!9!T@xyUp&Q YpYTٞ]Q` 9tٟ*kly lzmZ m zʟڡ *":Y&j(߹,.24Zy8::٣>@9D FzJJLڤPR:YVX\ ^{bZdZqyhږji٦nڕ:c~vx*ڧsy @  +p pN 'wP zp' zj ڪ-J@jz ɫ*y` Jj # :՚#٪j ڭ<10蚣꺮" J0Z0G J t*Kz骰ڰ*;* [0 Ь0?Z$Ѯ +K겼Y&q(K6{p:z04[7 Z/[&K +[ D F&z@ ʵQbPfKP"(U{k;pn$֚yzv|~ 2Q0 P v{1A`w++k吷P 빡[{A\{ູkO( ۂ;][}qx̻Hӻzn`ֽ;{o;fZv蛦{p۾ls{c \xl 8l| l" @ 8D t{*iLNNR,Q|Z܁TuVb|~{[R[jloq|a<YDM|tv IIƄ<}|їȊ_:DoF}#9JIP}L=(VnX+Y\[b^]pHhMmj3ynm6t}p}hz-l|;׀=عV؆P،ЃВؔ]ِǘM؎ٞmƠؤ i}ڎڪڰg=Oڶȸێ|ټ}S=|]Lv}Ľܷ`݂]|}ZݽP=ަTMJޔ콏_=y]ߚ}zNsw`NyWp .Gmᩇᚭ. g$*YP/^v=KR6n|2W<">yB.rA^FHqGNPfTnJ~BMPmS@^mcne.g~inaqNsun~1"6~.fY脞~虑芮~>fmnQ>m{ꢮg^騮l >l\1봮~ 뺮k*>&^Ȟ#Ҿi^F؎ھڧ N~=kB>>-nɽ/_^E 9?P zm "?&(,?+]2=79;O=?ACE_G/IKMOoQ?SUWY[O]_ace_g/ikmooq?suwy{O}ꁿꃏ_/` /XOj`~a. y4_ߘ}y$鵟o?{0 @4 %f4 ȟ_& .Nn~yuq.nNkngc^ZWT.QNNnKHEBB@ DPB >QD-^ĘQF=~RH)q-]SL5męSN=}fУD^ŚUV]~V"UVŞEVZmݾEJYuśW^J W`… F?Ydl\YfΝ=^{gfХMFZuK@D!g"0Aej0B /p c0C?ѷ a0DOD_*1E_]j1FoQ/G[1H#DҨ!S*2I'2%Kj2J+R)I2K/3-G2L3rLDM7T3$6ߤNiN;Cd}GA4H5.;b"IV2(\$3YI=elDZCe ?fԦ4fV#zՈ^ (BZРԠIM%@VP՚T>4&/JIrUbJ+ReV7éQ:AHI55}kU'Zպf֢_53 gR0mPC9Z (Mղe#qkD\24q]\妐sANյn w ^y82ךGS(kHF~G;:VeF0`E:xd0 wqE enȴd: G!,""&&))++..111111111122222222222222B3b6kq6mn6nn6nn6nm6pp7zq3o*kk zؙ{zxxstllgfbb__$\\)ZZ+ZZ,ZZ,ZZ,ZZ,ZZ,ZZ,YY,XX)UU&OO"FF ==11%%  " #.'5;1DH=RTH_bMlpf~~y}yuqmifd`\ZYXPWWXZ\_acfimrw}{uqnmkihjlptw{ρІӌؔߙٿH*\ȰÇ#JHŋ3jȱǏ C9(OJԦ˗mHʜI͛8sɳϟ M+@/*]ʴӧPJZSɢƤʵׯ`ÊU(ւ0ɪ]˶۷p:keܻx˷KÈaAVŐ#KL/cǕ3k̹3{M Aװ 8۸swB/@ȓS7AZ B ʳkߞ@% w ӫ__Q//߯ؽA ԑ0  I$B f\=_}9B "(g灌ĭh8B$zaDi$C;LNdPF)@ONi9V\je`ޗbi&rd暯pvft ٜv'_xm 蠄z%h&ԡ6N>*#EJ饘fdivЦ*jAjꥩꪣ>㫴kCbOy+Cj앿.@αFBr ʮf M bYڋ [k# .!U믗oK)*9 ILYiǷy ȮL,7hr0Wr4ߩrs5:>mߡ+)c%PtTFW5b#@ "h?յ/v7K:n $L,rwO"6hߌdPN?w+~v?"g.LǢᄣ2:^ !Fc;:s/}{_4u;z'Ϣ7_GWO%g;}~|~y7Nߏ?vX0j< @1B{ }& ꬂ3 re B(B ;! 9b. cҐa6!rCzЬhy3"x5qτūMړh=-r1{^b(葱;#5n㈻9quRgE=|VDhE W!` " IRr~2qd(=)QEdSɪO|%c)Ҳ%.#H"TRk88A)4ӗČ ydR3aN3hD5fniݔ7Ε49}VNt;uvXs-;ʼnO@?Pq}!B*Å2}(#*R>(FэK5ZGYؘ"e 5VPPcK_ ӃA3=iM vS T;WKpӤXlB C`P}ZTVl FU.xA@ԪB \rpjֳURB+ U $!un= "2Z֮HA ` UBT?8[GXfDAgEV$(b5+u h* dmd׾Ul*\O@E.m06S*r)KإltSEv\V׼qNCr_Iv4[ܾuKZ}zO  _ І[ W)b{U& Rs &--Ԉia 6~Hs,)LF?1 ӪD~BscG<(K BA ^khXv?1~zYTSp>V"Ln~}L(K[8@BOj v!\Aԝ5ٛ>դƭn,ݚy7eyKI m3mL7-mF 8 Q#S|h8 q8C&g S|,.yXb.мV+9ΉtO> Ѓ6==C?:St0?y:g[V'9^.sAR.v܄49;IG[n!}1pi;5W_3x /y8<#s#IOLCѓ ?=@z<-'mMg{W}O?|?|7|7ϗ|?}W?7|}w{>~?w{׾~{>?ztxtHtts s s Xs(srrrhr8rrqq!xq#Hq%q'p)p+p-Xp/(p1o3o5o7ho98o;o=n?nAxnCHnEnGmImKmMXmO(mQlSlUlWhlY8l[l]k_kaxkcHkGwu[cEm膺r&tXWv|hv~!Ev%LgNEO㈰X#OhQOQ&FfƊzo^&QFDf9-!Ƌ %EeץŌ匸%EewhōWGA%;E5e0,(Ŏ#%Ee ŏ %Dd蘿Đ$DdӄΤđ䑿$DdĒ䒦$Ddē䓌$Dd{wtĔqnk$hDedb_\ĕXTC0A8egIiI{mc!Љv01B7Ytzybt٘Nu9T` EDDID DCCyCICCBBBYB)BAAAiA9A A@ũ@y@I@@?Ϲ?щ?Y?)?>>ۙD896ѝL9s幞3Ui(Yr:?=Es F Ѡ]j:FZˑ**=jFڡ3$&F(ן.+>-W6z8<3F;DzCJAGFzi?o<*ԤNvX\ʟb*TV*Ggji>kmJHdZ :tʠoq>y{G}JZIvz:Tj9IzꡑZJ JJay 1~㪧jꘫ: sT6*I1TJJ5:KEZ֪9 5jKjߺ4Kz4A4JA3zA3AZJ3A 3 B 2 ;B k{2(f@;/csR;cC P# [cd.Q 4+ Pc07m8[c971!Sji RF;UGc JWC6XJA,;6>4PP;i{W aR9pmX G{E{еGQVdf{m @m[4 G{X?۸:SBd}qm۷+ tO $S[DԷo.);r+L1+q٪j2B;1KR1Pk{1P;;1 Q˪S CѴK@;aFAak aDB]$W/!L <(0$\&|(*,\Pp@b_/r :/-\"." P "4,,`-_,P,?<A!,5222212121212222222334455564I1G-W,`(j+u2}:>AHNNMMFvAl>c2M'5* ';A;'   -6?:63 /)$!}u iVH>/ "3 Z /7>JQWY^`ipyuutu~vyvwttjjbb\\'ZZ+ZZ,ZZ,ZZ,ZZ,ZZ,ZZ-[[-^^/dd2ii4ll6mm6mm6nm7nm7nm7nm7pj8sc;uZCqUJmOSgH_dăAۏEGHIJMW]gmrw{̘ͅħ뺻ܽϷլ۠ܙtqj`տUӹNJHID0 H*\ȰÇ#JHŋ3jȱǏ CIɓ(Si˗~VI& &8sɳϟ@ JѣH*]ʴӧPJ͹իXjʵkח/YY3ԳhӪ]˶۷pzKݻx}֞ثd KÈ+^ 0CJS**Aj\G܅!l$-`9;v5ӟ^3S'k'O`J+%U[`׺cK8p@OhSIT!SߋiBvڲލЙ",Lk>xNo^9y1x{4{(Vײ,Ӓ*'U W?Y;ȗm#Ʒ0%BP] b -q|\ 5H[wFEYJ<mLPu6'(rȆFd!*QsrCQ=1|O 0:FhJGu#T R͓zeeF]-quT} wVCpsKܧT~hɌĵɉ TZTB vP%082:2eD3?YUqYkPy9ai +P+8FHuk<L4&ik mb*Ee-@Lq+TS;{~헬FOJWs+|cduDqY*3S'Ci%j Zzd?e9rj+D9ɫOJuOXT?e8cP 0Z֓MMDۓxCψNtFD!᳢'M8Ҙ A"J{ɴG}MӠN=CV!H^MZc+tp^&uGf bF9Bd;Ц7h[ؾ5Rl{3p^޸1Rt6xϺ/|7;-+R39ȁ|&'oi͵`|cw G\<3> ͿT@aa`<@wtyKS:9z H;B8}BHUJ؄N(LR8TxXkFX6Y` 0`(We؅gp8x_huoH@ߠ sh}r8 z8(pj_XgÃ08Xpb{8`Xahh׊x#1ȊhJ˜8 Nj( |'؍Hۘ'fl {}9'yg䧐 9'y阌ّtg"Y6G&*ْǒ.2YF6憓:ٓƓ>BYFF৑WőJ׆P9&TyfX\Ɣ`YfKjٖ ƖnrYDvzٗ&F~9*Ɨyb`B☐9""y-/&ٙbcOƙyaaFcfeoyF{fٛƛ9͡y-&ٜaXỴƜA!9!yٞYaZYFsٟ9z홠 z ڠ:YZѹڜ":$Zy(z*٢.5 1ZQ`:. 9@j.X ?FDzGꂖPLN QjSZ@zXZ5ڥ^`(:d*NZ g*I@kZmqCjw={J0uZmye٨[9zzSکIZ:AYړ99}Oj @(觬s*~3O q@ J Z ߹ Pպ  Dj0 zjI:ZjVګZ蚭皯ꮼJzJ pʫʰ6nI [V뱾!+; s4ѯOʱ 9- [$o4jz ;˳Kn D۱F H=[NˬE;u׺ڴ@ ʵ^`+ WNKi˚U dKpf˫(Ksu+FΊ{:k!q\۵,/q9ڹ{@C+{@[5{{K񷮻ٻ1Ѯkp뼀 z8 ˽;0 zK苛}}п[qP| ,;9 } RW| ! kJ!,T }`+.\XçBD\īxHlJăN PY8T|V|SZ\M`bln7r,t\,xxz$~쁀8Ȅl|%ȉNjȒ\xɘ Xi Dɥ@}B=m\wH J]Ls RmT=V}y\^`<ֵj/Xj݁8r\O-ׂnH׀mk=w׆~؆X،Mjآْi]َv٘ݕي؞x6ڤmg}kڪ f^ڰ=ۢ]۶=ۅۼԠ1-n]S]ĽSνO4O}̝=">Qʝͼ"$^ק !+⻇k0~2~5{79^~;=n~?NA}CNoE3InK}M~O~QSU><\ubd^|hjnnpi>tv~ozy ~т>oaz~|'Yn^@H~n]႗@qf: W]>r礗뤮nm~+뺞'^>#QƆnב^-M؎kѾ}m~im><:ngh^q/ _/o?!#%O')+-/_1/3579o;?=?ACEOGIKMoO?QSUW_Y/[]_aoc?egikmOoqsuw_y/{}_䇟_㏟_●_5X Ol͆?l?悥ר`/᳟o?཯@e @d p噘v6/՟ܟ`O_/o? W DP„1QD-^ĘQF=~RH%MDRJ-] S`LięSN=}TPEQM>UTU^%:SC]~VXe2պsYmݾW\*\[W^}ݜyFXbƍidʕ-_Ɯ9!䛒5ZhS9\Zj֭]x:fjصmƝlu\_&\r&Utխ__h%rݽ_Z{K͟Gxտ_~W+ǟ_U/@$#R@dpQJA 'POB 7䰹 MʰCG$K DWdIJEgѯGFw䱬EʱG!$C H%d?I)#AJJ-Ң+?ʲK1$K$3M54#4ׄ3NM9SE:73O?pOPC4#BeQhQG';H/RM7eR24TQu"PGE5UJTU_U3V'r5V[o¢ĵW_kUZ%ظhXcev,d!RYi}Lx6[mzh7\][qEM]wM"&lߥޣmh^{'|b_>߃&8~ 6abt%&b748di=Yd%YߓW69e_~egYfofw&XggvWhhVifiUjjNUkkǞTl6lSm߆mSnnnRo&oQpp/Qqq'Pr/Wr7Ps?sGOtO7tWNu_ug_NvovwMw7T|7>ѐWyYGx٤>ޭ {~]'5Ggۇ߬?iwЀzh.ЁAi%ȓNЂ758naB%%DaHNBrd-E^CJd5ġBnCd=C!E4" D.(tIE)UhA-nQ]FʭB̈Fp7̡H` 09" ޘ\8$/4HF.|dȈ51!c;xCv7Aic)702_6iĐSIŽ{L-|2u#/D JG!e1hU$JYJeOdg$/A=v2cӈ7 3Cr'63lvd QJ ӏ$ nhDf@GD ϔ#QHrg?7Oszs();Nb 24H2*ы!'4ћb"=L1yLJT(>cӘLcJYȜV58NqSkdGiɰX:(V 4=FGUS_,E 3aӗXŖc!=Nz0YmgZ򎴥iQK;ծvu-`[͖mAg{,b+^- y[}p[FTrK@>wэwOZ׻ox;^׼Eozջ^׽/Qd2rWkGAxF5w:ߗ o 1`ZFE wЄ} `sCkHNJgH  A`|cIrX2AL(86 0S6q'ɑcoH8&(cv3eyUH0&H4XL28lgE3z |׬c9l.Hgl~*k_.&rP!T!jڡ* ! BSJJ)jzf9z#Np'E:ꬑfjvcvn솶nan7ovo o5pup poGp[uqGq #q$6q(+|r,;r0KlL-|G=FFHWpG'-5DK7}MO5CK1Yo-t/4GԱlT@t Cs]GF ؂uOxI/8Ў?sLy1_y˚or瞗 z!NzǦqWz{òϞp{{oK||/nΗ }NO_j}~e/~9~cH)ޏb(g<@3c $ dY3H rE <(2 ! 9vҧ. cH1p=6fC將!#!rFh%2Q:N|"t(EPʹ"-z^Lȼ1yf<Ҩ걱{#'9zv H=|~);$"Eگ$#ɿIR3v]]$hB)JkqD%HJ̰9%,/8^%.]*D 0IaS`<&|~GʄQ3LfFEӤfyeS& pB,9t2d'mS O|Hδ7 =AτGPCPA DHgEXA:Z"IKzftӘfR1)M[zSS:ezjџT Q9Mu̦Sg UMsUͪVjJdf=Պ cu)n}kR*ףеE+^MW赯9+`o"*(Ma{25}K"+ٖP¬{.ُp,h7"fjS4Dz<}mfV+ۈжvn[Ŷ-pV60t`F΅rRI½`xev{]R׼Esի\׽Å/p[־om+[ֿpjlZEpgYcd%X 3‰Űa5ϰt+JBХD(IFwњ%%MIJGҎ"5HNӂEGRvDU GVjeMFZ ^k]l5qpa'#06p0ٽy6sdO;7xo#4lPS6{-nڋb*[~b8$ۈb[ai8܅_aQ6\`98 V܂`!v\?` 8'_\~/_7|7_\{?^Щ7yG_^ґ5]xO]y7UvW]au]u_?]I7Еsg\1ʵ]ro\7pw\=o[gm'3>,[eZü*oyh^jo;ѓ@?TB4C. c^d}r{P~? ??>a6_^ϟ->'[l;~__G}?O+om0#H5xA [^ 3H6h0a(%3A`wPv.XWP&(#Dh ヨÃ,$HcÄ5 (Chȅ>#GcㆽÆC#gÃLJ'bbA燈epĈGh$o‰knቫd'n.5CgqkĊGt$fۇweBz$2baŒ}ȋnB'g\`J"G8dY4䎞'0DW,⏒ď'U(bDS$␘Đg b$CLJ⑞pőb D⒩$'3Ig7;ɓǒ"Be?|rg ĔGUiˇYǕ4!m唴B$g _*4H`pP0,.{)QNSzpZ`L} {?0,CL3a9`np+4,ٙsքps/g3xE 90Yi1)9T _@?隞yL4>@YP.a~&Ǡ)Dꠏ'/dǡ2DG#!1&*h+[/1zP1QO8:%'=:DZFzHJS+?r(I#$"Pz$?$Yz4,$#T Yajd-jZ(GR$"dj<B+#?fz)BN $f imhB+ y$opJ+S$R) p,"%:@&)$2@%*Zg§ګr, `#0-G2+˪) ⨫*v)"B& Tj!(,h522t o$HHM :t__ tmHCҴmғCmmmCoomғCmY  { Y CC Y d mH$$ | mmY mnv t$$: |  :&| C"#o mmCH Coo$ CCmH*\ȰC h @ĉ pEAFɓ(ST@ |IC`: SM ѣHT4P@RDTg>etiS`ÊM!2H+0T0Wu-˷oҊfѪe ԂuW.]#Z  \RUyYj[:1QF_"vGt@УKNسkνF 6 ߓ7{ Td 0x^(`z&X6`z(tX Xy~Hh(Zbs6%'9v-Nx@/Ȣ+xXH^4*H{J&>&KZpOv%,Q'9$e9i~Xs(b3"Jd* VSRI|M>۬39#m%oTtXRxmlZ[7A`_Z^Mnw?mj_r80qByݤsM U!@9NstH3@ H"HL&:PH*ZX̢.z` H2hL6p\re3־lIUp]2ٿZҲ+057Aџ^xCݰ%T3tq̦6nz 8IrL:v~ @ˉTb `X t`h@Z@@5hzbP% 'MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:ysRGYs9~ٺpkd!i4urZ5K묺 +zJYr*(S]pee?LВ%^'? doƌ2L Tu49\s=|hGKҚMjWֺlgKͭnw pK0ev+g>5ք;c%;9ƵjM[VH`Ժ%W>,uEElaKҋE!~E>.^fE2Cφ%;'L [ΰ7{ GL(^EոZH8vUI %9U]v%<5pVKһUP$[u%Kde^ NLZK2:kGؑ\SFr;&6!,22AA!Cd  %%YڰHz!*c  ^_+ڣC_?ؐLڢCbaL\S3ڰGR ֋(PWXa֡C\ɻFS3P *w'LcϪGa~ `ذHW<(@`(\Ȱ!C ŋ Rѡ;\(Gő(@2)_r&M6/̩'φ;)TaТF=RBFSjUxc_:ecf=翎v蝀(!hqd]d Z(!V_Gp{ 8|f"h≟]b+VPs2Žb#`c pxKb,%!n`@^ @11^tbI[RЦ(0e|`~:"z "5@stMJ. )hPz j~Sj6*L:SO)^Nj.Ȩ&;2{BR6F ୶r ~1PAxg}6xm^[L # 3K\117w "'c/)2/2353;|3=,tDL6k/:3ͳ>+3CS]@[5Gs4H` Q_ 6^lt@wl?,&nNu?ø5|mWY^/4[C޵x/s肓铣^gnG_>{o{(ھ迗ç^^~<뾼K={^=~~= _>>3>ד_} ?πC?@bPpxs67:o_?~4aUBЃ+tYk}%ai8C.;aC!ψ9a XC|8!D)V"" v1_,b8#16^8E3kcxE9fю[mDH>{c&u#$)Jђd!yHG6rlmnxRfҔd(J0R$c,IPR5ITL%/)Kb,,K8slfSpt$HQ@ l#PiqD)H L!,&22    곴P@( "|D+^(F;FtȄ%;2890e,ClpRf f4 Ϝ-8C <\0aR @p  Ht#n|PDV-۶•(w.ºv⥋7o_w ,am1[r!, 22S  /)9U  V ql! 4T eC)곴eD)6#J5d(@`(\ȰC :, Ë#C(ZH#K BK\)s&ɘ6ỏ'Ϟ;:)thТ "Mztҥ0"}TjQS zUO[UlNcD{VLkݾVKs҄]%Pp`: FpbŎ3df勜A~hO7,s׮cfZu_LaƽX7_ڷ}C[oޚGN¡?ձ_Oџ;?c$ 0 h >`-dJ8da Mh` ]a!Hakx"8izB2X[6~P:b!A&7$!A"(ЈDXAЉ;d- Z?bB&Ћ3c xC-^ODc]C3QY8D.QgcXD=Gc DAK4d"D::56 >>vwY '' (  ppB Bx0b(0@ 1c Xpqdɒ lDˌ Pq&ɛt `M9(R[4Vx!@[8pS2,p)(` "- fnFb &+]K5xo6@'Fϟ Аgʟxα=H)PCܕK|MDq Xǀ!,5 .)D0N1C2A2?22121211111111111111111111111111111111111111111111111111111212121212121212121212121212121111003)5#7<CM V `io{tywwwwwwxwyv{vqlie`^ME>)y,d@XG<R+W#SKB4    22<<?? @@ @A!@A!@A!?B(7II1Ri-X~8WzBYuX^kpS7ڎ ۛ)ԡ2ϥ0ǯ%¶ (3;@ABBBBBBBCCCCCFLR[ȶcjptx}}tk5H*\ȰÇ#JHŋ3jȱǏ CIɓ(S.&KT*CM? ɳϟ@ JѣH*]ʴӧPJJu̫Xjʵה,_UM ]˶۷pʝݻx˷aXxLKÈ+^̘hǐ#KLY_2l̹ϠC'LӨĜCѰc˞M;v۸sލҳ4NNy+_μyKɀne;νwХ י.WN1SB Ͽ|ZYP(D4H|F(a[`ZUvx'$^R׀y uT?Nh8P;%)䐒W8`8 VTR#P=:\v%WF6] BM1 O!-;oܙN{SsąaP !(Ovfғ9NQʠLAlZ靔~f(6hT@:yꓩb鯬9kRJ+DJK*OWP@~]cVNO:ShD@`Jt`/ƣ|to}:[<9o9q {N\\OZ+(bZ*zi*:91 ۰Lul!. lmVmx6 @bD)gK3hp.smC h5*žb2\ q-&zx *<1}'Sjg:Bݓ?R]H;^i Pa׮q5q,clzǚ2;s{O1ϛkJq-78//O>*࿾|OEW/ZC@ViE[\L79]o4'a*ZRRFH/.ˉԀH'A?)g\p˵z>L2 2;btP]hfh=R6߮`6?鏈? M翚%^JT>UFY1*$%=5Q $:LNX&v*ja~ocؖrUaVy蜐Jo}+=Bs {%mJYn?$xEaUod(QS]\(U A-nNm 8ȯ8!djt-AYyBaceL>e&MzR: )PLPz9gRoSJ֧}6tUb(,\sV2ΘyF`:Ԏ4ו¥.ftq)WytF'aK-o+^3 K3_5)1rW z4 ")8MǜYЧR'>3Y*VEɪxRhM1GXN0K>Εi7%MZiWxjp'APd԰:\4h|]݇($*mQI-5!ʰ\ ?EjWTU7[dQt3n1iզK1NYYڛ^b-ҸPT.!.ꉌ,ФU'M;ŋ B'?񍰄Yp :+DF$ ޱ'f=Ri$~ʄgLcTx+&Np߃t@a,0B5NKrcx G,%[irV,*{`Lh+\no)p^ș6U,9ˤx!B*hXFtJJ[6t%4kӠxzԨNWRԬg=kWִεwmh[׼]c_NNc̎-gζkǝN}o쎷w{5h2qa`jٷfx<ηin1MkƇ&o !9>a_wG P9?Nq\7 Bgx͗sL_Ё G 'x5ߜ>_y׏[3{S8 {p;;{q·CE^xNx]'7Oo?Mu~KAa@XFBDxL؄ N8E !T:h3Z`/S^fxO8Uh؆_ȅ nXՐ 0 v `  7!8Wp P@x ƈሢ XЀP }(nh v( HX8nXъXѐˈ xH1ȊØ  θP 㘎fH IpI@jhal%ъ.X9m(؇ M@9xyؑؐ8.9f!4g!>nO[j#z"&;pfqXvd ;˦]}cۦw:kŠl* B. p 3:k$Cʺ庯K+2 fK˻#'Jig[;;z ۻ؛ 9[{ۚ۾[;Y;\y< u9|k|c "<[Y&|(S,.K2|4\Cy8:9><@9DF|JLLPR<ŢXVXn\^fb d\ZxhLjNn̄pF8t v|>z{l`ǂ<\-xȈ%Ȏ8ɔ||ɚ ɠ<^a̖|IȪì|m<6˴önri`˾ʻ<̿\qL}͌,t\K|͟<{Q7L~W<]\w lc mM}i" o<7X-=uJ "$]{|W*ǩB](Ӱ6 5BoD]iIӁ.yLJ݈.TnV}tی^M`!>00XXw 2~}#:;8@B>F^5HXL|K&RzQ^\rX>$Z H^`jd."f~1\@j= n@gpxxz}ޕvb{Nn耎=^v܋.0Ǔ\`a9oi頞>⦮l꧱꬞敕.F붾թ[Nm>/ƮȞ&̾|]^}Ѿ[1~W(n>$Qޠڞ悔_y Vjo/Y3 o6>&( ,"2?4_v8~:>@CEG_I/KMOQoS?UWY[]O_aceg_i/kmoqos?uwy{}O탿텏_/쏟o?뙟o/꣟o?魯o/跏O翏OůOϿя_/۟o?/_69 sÉI }qA@ DPB >QD-^ĘQF=~RH%MDd*'&RL5męSN=}#K&)TRM>UT V]~VXZVZmݾYiśW^}"_… FXq>/YdʕĪfΝ=qǡMFZC3PCmP EQGWS#F"hRK7t1L;ҴSQGSB%5UUS.V5LUYou*Z55W_Mj׌zXcu#beYZUgVd/ZZmMZǤ6\qe֢lE7]ʭ\u]܅j坈^{e_7_`` FT~a'b$8G-nc?6c<g[%:N6Hh~邜j&j끴:ll>l FfmnRoh6<Wqw<!r)< 1׼s9<AH7=PWXw=`h=wp׽x=xހو7>yՐW ǍpOyꯧzz>g|@׷L{ߗ}oK~'~Jc>P,3`@6P( t`{A V'`gA v0H\=8p' QB/4 '$B֐$.aC ӛ_F#8z<>xn ;)r*SԐf-:m`c\ӯ#YiD]ޤ(3k5< 8LNԗ+Za{6'HQz~j[ou~&' _R4N`QyP֤|%HXƮЖ5iQ 8ծou-`۹͖nmі[݊ok5j5Ґ\->ssq]ʌeukK'35`4\4ў~UzFLWx|G_7lͯ~CFp`7p%1;Y otH?aPĞ=L Nc BfrORW:8̎SI.,:y8s9|oY\f8{Cld%dGmg 3L $*?@LN<ɜ508;14iM ?X k<25,8c J5LË2{VFQ=3=Ũ״N;@0AZ6Vݢnn8o=+= lA /\f Bi l`0Fp 3=%/q-pr *wtB s4'-3FNL| %Ì3+p.?tT}9a͑2=hʹP0N6r'Z"l2v.=/Aэi},43 6v잃BDFҹ:ߪ{˿1ngo]6vq_ao[Ϟǿ4/Z?2DL`ܧ)u1 L D/7x D a8!#LO/b gX@I4#ɆO¡xA ZIDLb%$*#ae ?wL @(AUL$ xGs17pG(3*ʃ'aR>N!16R,!8(@~DGYd26 X|$# `G0ya bdđWt%,Q4iIF cD 5- Ӌ/Le,K)R$݁Kbjr'7ʎR(԰A(qy㓷ĸNvN3O@'Ρt,Fމ*T# mJňE/z^dG-Ґo)IˇRtkiU S%T"/)ntwdDUQԤm iSUHu8*YhjU!WjƾdEHXjdl[ ׸*k]׸u@ ^ V -;*6VucWٿN3$rC,h{(水?eԲEjزtmcJvك-p7(V} rrrRֽ:wTԸ+z$%p9 eJ^2 _MܢU[^=aw/{ M$MpQ =*a ^;!(pY(',8 ~a֊($]pbjXCsbXqe0aV= ')nc&KZ<☿Q핕囝P&ˀ7eΘ/ X)ś}9gY_<) =C[;O)-YK[gC2i3`@.#T'#|E+WO:ֳV+]c֛P妈[ߚ/ hG[Y0Q|lksshS]oWK ִ͝'l@znEqCr|y֒…=[Jph9 669sex0F6X8"kH~h18Wc,`=~2K4@Bg'@p]T7կ/% AcyԋXTz쾒7m ܇%!#`Wn:e5ccyc!?3o$_ K|[-Z?\Iӫ>wq 'EU,lWNj/+YB'~|/wyC_|fg3j8k3_~w?>>{*) 4煀 H_ )_+H1d2 섁7{B`"!u`*%,؂X0,$-&8!8$:Rs>=8,RFx-@3BՁN!P2TKx5Mxa\^b=YX7[Xׁj$d؆p؅g8:i8Qsx8?z=|؇!QnX?؈AlXBhщ(&?i2Tx@yъAAXs8؋8xQ>AgθH_ָؘ1Tܸf1x޸JxTa)tX؏/t9e YCِ ŏY( QY7Cؑ "96Q&I(E,I+r2D.yHe:1@ɓBAyHI$eJ97LRNTiVyZ89ٕ.5`:b9Se)_x8El\r=tsziB|Y{G)iL)QIiVə[Ř踖)ɗIɖY ٕyIy)ɩy)ɒәi9 ّx 9 ! ɚ}9w! a )vٖ "yzMʠ?Tڠ j :9HXjP ;A $'9A $FA I:a/zA*7g865'4 DV#Yڤ[X_:=:ѝɦ )Iiȧ(HhረܨȨ(HhÈȩ詵(HhȪ誕(Hh}ȫxsp(mHjheb_Ȭ\WT(QHNhIFCȭ>;8(3H0h-*'Ȯ"(Hh ȯ'Ggꇰ槰ǰ'GgćDZ籯'Gg粋'{GpgcVHdz<1"'Ggƴ&Ff}qƵeYK&?F1f$ƶ%Eeڅץŷ%EeŸ帮%EeŹ幓%Ee{vźqlg%bE]eXSNŻID?%:E5e0+&XWW``*Fֻ1ػOջ( ݫxY+ Ỿ3CYRQ{Q+QPPlHLDUZPq>ŤZ*`ƍ9:Ƨ5d4ƪe .D-dDz%'"!$aLȁeZǥQN, dͥɘEKF %CLe<إ96 %"l?Tgs{ ̛,K"EkޥŌ' CUd,̜l >[l=\z+57z;?Ρ=z9nAGEٜ!b`R>;?q+vZRATu,$begZnpr>t^vΒ#9 26>0cXX/ ,~.wp.`;.e0n3? }.P6!8Ai6;:!3+4*< #~~#4>ڮ~:^{cF^.4aM>5Խ^ n!,b$&&$$&&0011212121212121212121212111111111111122111111111111111112121315180>0H/T/W/Z.d.l.s-y-}./21.,%}qg^ Q} Gy7p1g*c#^$Y)S4 O9 PASBVDSEPCM@IBCC:D0C#EEC :'"" **00446699;;>>@@ @@ @@ @@ @@ @@ @@ AA AA AA AACCEEJJQQ VV [Z_^dmixnsvxyy{q~nie^YVSQRQSWZ[]ZURPTY_gpke adio,w;yH|S`hyk{dZPJFDCCBBBBBBA>93.*('# !"$'â-ʡ2ˢ4ͣ7ϥ;ҧ?ӨBҭEҳKշRؽY^bgmrz߁շܫ-H*\ȰÇ#JHŋ3jȱGղF0+(?\ɲ˗0cʜIM!G 啛@ JѣHigҧPJJU9ʵׯ`ÊسhӪ]"ZKݻQk߿ È+[Xǐ#KNڸ˘3kXyϠC#8'D) d&kפR" uDtB˱׶[ȓ#wx(N/s?i,w}.i=2wU}{f[&gAWsʤ`V܄fahnᇒu$ &b(8׉*"X,(RH8ec<ӎ>)dG@iL&dPBdT9eXxe\޸e`ed8fhzxflVfp"fK۠4$!?X'?P@u^qP3͹R9Eԓ<'?HCxVz)j*$J 43\禤"jʫ O lrGjC0g)? n&/Q`n~-C QjjW²P3 I ѹ>].Q<~r=|;7PL QyK\+(J.CD74TcUg=ZwM^bfj=nMՖmrt߭7ކ7`p-8LnJy/X?.yOn~_9ToA.ykzR ` XO30?tC,{M> |2 M 0g6?'oxگcE /P3F '@ ȟh?,`b@#5p(#? z_0Y{(K؅P}{ 5!rCf!&!zFX%2hN|"ɢ(EQ"ǥ-&^l11Nfg0͠y3@ zE/6TGOґ Ikڂ{鄧?PԒĩQͣЙˋaܻ̚q-I'zD5,5&5te?F miS(־Pmp66i"qKHOuU~w|-oлޜ7s}o}<9?x p$y8qFZ3sIf<.rЅ!9.LW>s׼7y?stGWxt7=Ow=u|WWw߽uvw=_7w=vpgvگvj=owvܗ=wd׽wvw^ua=xVՇ'u?xM7ҏt=EWЗty=wΟs<3^̧r걼)ɯ_rɸ=˨<;Ϙ:XI 8cSֈ8:Hؘ#8^эS6؎V#Hx9h9IxɆ(988 yJ8֐)m6myۖmّ In"9&&%, o(g2io4Y897֓>)p@DCy gJIٔPIqL9YVYX\^bdY$yhy7#C$nIv)8{7}7Kxzcwv4ɘq;y)mcˤ mli-y,iÚdB9YyDBned9›k aGhɜ]Je)YcMDbTÝP_?#S\I#VdYYĞV B\$Si⢟_PɟbM)beDJ hGp"&zTYJJ&!F{~С:(n`+ڢ6A/2JP'z3! #&AG?CJ&G^ʣ`wT; %8Izd52ɥLZ`z`b:,/Yvhrnl*%jʒsiq:wiyʤ{jHu$H}ʣ jzk Ѩ2*&iJکF-*#i 0ڤڑI@:#Jz"JJڡjlJɪ"ͪJϊ"JǪJ" l:K:!jKz!l Kzj!KjJ!!ZL L:{ k nڎ {+;o k {o;[#K%5! '{!)+p-k/0p600C[9SA7(OhKFEFKFFFEFPCH?q@=a5D!AA!AA!AA!AA!AA @@ @@ @@ @@@@????==<<8866 42 30 2-1+0(.%-",+++- 5  "; &R1e7u'7+;,B*F4@=9B7E4M3S3zX4t`5gfAVlJEoS5mY%k]i`hc hfljsrwxy||pcVTUW[\VWYbm||~ |}"/8?BBCCCCEJUZYTSQNKG?<:86433.////.¬1Ƭ4ɫ7Ϊ<Ϩ>Ѧ@ҧ?Ҩ?ҩ>Ҫ>Ҭ=Ҭ=ҭ<ճC׷IܼQY`ejov|҂ӅՉ׍א֒הҗΘ˚ɛȜǟǢǣ̤ФפަH*\ȰÇ#JHŋ3jȱ$ CL](Sԕ˗0cʜI͛8sJ)ItIѣH*]"O0ڴիXj݊s̟BKٳIC۷pʝM˷_vk`È98ǐ#s]<˘3k 1͠CLˤS^tLU,$PA> ͻ7B0a3-0 A<9^ܷ突n( @xڱ_^qʟjC}+$v䦛@߁՟G%eqj^VՂ5rY(JaȑFiЇ@!`[ H4dF(֨㎭wZ|<)$d7jH& WPNk@FiRU%\v9dEbiQl)GSxsIj]"*FA*HR vq$ꐨJ ʐ j᪐ $,[,kBfX9M[ ik-͆[ӳE9dAB+1{.AP쒽k!o FdpE T EL]f/(G@ O$2 N9ݝGelL ,P@`84bB#@P3QW}I[u\Xo^]-66hkvlvp_XgmQo߭wZs3XހӔw4xse w7.yǏ׼xgtxY9n@Wt1A) O:zS37 |3 ?_{U8<>L*4Lu=@:T?d@nGB/)'.{>P<(@m@QV@dzBT(yRQpz]PO:<"㒨D1{"')ꭊV-rm^"(F^;#5Vn㨴9ұhvǙ(# 7&A: "9E22\|$")]Q$&_MTP *S)UQ|eF٤R2ee i&[꒐D/y`iT1d6rj3! DIs森MKjRf&p 9tjI\ҳQl<|j=jJOQ d ~cPT@NhE`9Ku'<;T$k@@UQ npCX@ 4U{8iHRo@JT96)S& nhR%u>UQ jի TncRBO6(jYJ7hUMSOVcd*]ꆤOW"\u Ķu܃Y!7sJ^5WBldJInԮ,p-X6mֲ݆)pwn0q3us+8ov*xJjw܈y&wmsZ^nė3KZNoQ߫@oX`2C-wp]a9-sA 7(1QQ|8.dlpc ;N#?hэJ>dw~0/7#YIU d kL4)lf/)߼vL˄gHNǙ]&s Fh43K}ãzXWb< 2z]$K՘^QMPX661Dm-"\D׼i`w3)kbFPgBWDȖIldӴmp{i.o._xt.{JJBkogJWυ|AjZ!!5xkl>|~/+2F^0KHTկs,^X.rK:om}~9;ܫ"K,{}Exϩ;&.~I'Ϣ7\3sqjhB/O_.?ɿ~?_~7||{{x{ H{ { zzzXz(zyyyhy8y!x#x%x'Xx)x+w-hw/8w1w3v5v7Xv9(v;u=u?xuA(uCtEtGxtIHtKtMsOsQhsSsUrWrYr[Hr]q_qaXqcqepghpipkomhoooqn!'yzfw8y:'x~Mp wf H舏~x HfyHpS׉8XHvW؊c'xhv'8wȋqrHw7wg~X"ŘIfnjV!F1x ȘD1Ѝޘ(x鈍ᨎHwPxxȏxsD1fᆐܦƐ&FfƑ摗&FvfiYJƒ<2%&Ffœ%EeŔxj[%JE7e$ŕ %EeĖ$Dd؄Ӥė$DdĘ䘦$Ddę䙌$Dd}zĚwtq$nDkdhebě_\Y$VDSdPMJĜG8($DdÝ㝧#CcÞ㞓#CK4i&g8D1QT{ ڠ8J9Zz*"*:Z(&$w.4-14j 89JE6z{Wԣ>*Bz7GEDZI7MEKO6S FQzU6Y:FWJ[:6_jF]a5eFcg5kFimj5qFos5w*GuZy4}ZG{*zJGʡ 4GZOjG:K Hڠ1 L0Z8*x 4zZ ת|8 ʫTZ:Q *@PԚǪLjٚQJLʤߺ庫zQ:JM*,M+Mzj+;NK; + N *N K*+O*:/")'))JK+Ok- /J3ˌ5+P79 K;k=;>?;A;K1˧CEk@IKAM{OKG+Q+SDWۊYC[]'a;c$[8=Vql"K涞HZƶjedc"^Bʷh\¸XW(BhO ʹ Gh~Ǻ{,w('Jꧻǻ'Gej^Ѽ #!=p:!vثp֫[?dPd=KI` [k]`p]0ۿp ̯SVQžk=1P |l=4=(PIĊ̽$l+@:B . \$e6F|;Kɜblm<Mlm{ȌLcjdU̼ P |ʨ?{;Ec Dk(Hh (HhxjwlVl}`A|*|V@UP+qW=]}By/ P @;2P=` èm1 a0,ׂ-@FM.Ю[mւ_=r t#cR cl}2%PA_]v@,2-B,$Dؒ <-"!ؒ 0-].r0nm1-n؟mSQ=2!چԴa=ٸ aڴ-> PLԧmܟ@1D]',Nc ­> @(mKz--Pm-=! ,N.-'!'#'%)(++..212121212121211212111111111111$$&9%FX`j RtG:w-mcXH3         & *%/1388<>=?? @@ @@ @@ @@ @@ @@ @@ @@ @@ A@!A@!A@!A@!A@!B?"D<%G7*M/1X!=aJh SkWkWlXm SnMp!Bq.9r81tM v[wf xnxsxvxwxwxwyw{||ztkf]WSX`js} љ")3>AABBBBBBCCCCCDEEDEEFFFFÜGǝHɞI͢JΥLΨOͩQ̫TͮWϱZѳ]նaعd߹gilnopr޹tڸwԷ{͵óvnmu΂̕ȪԿ׵گ۪ݥߡH*\ȰÇ#JHŋ3jȱǏ fIr[RL ȗ0cʜI͛8s܉$Itܕ ϣH*]ʴӧ:}TeQXjʵׯ Krĕ*سhӪ]˶-s2궮ݻx(S{ L־ŀ2̸ǐ1"8˘3̱ϠCyѨS^Ӭc˞M댰9` npȓ+xcn@H:7{6)@.,]{>bpHI'W}L~z(ᄙHJv6|H$>fD"qr8W4uD)^ `{ҝdD֍帓p p ui啇MEbXvHBdZiljCj)県Pt'^v2瞀V )衈bEB&G-PVjL"D饜vQm騤FAꪶi*DꬸvZ+A+@6жVK洰Znm:/!ԃи H8 ~+Y2N QO?ݛN0p=<\ջT?oAKBg1 ?R;1A%13,S#'r @'U3R73,A7GMq&w܏ Y\5ORLܬ0 }]-`| 1캭wLpr}-8mnxVx㐻kGnh_yco`.z^n[zZW.{Vn{S߮;R{N.rO{S.@܀z M7%}4h~y?"(Q&G% X Bށ}3χB}'`! І* L};b82N|b(Qͻ"-^ø1vf<Ҩױ{#O'9v=r~c);$"E_Q4Hbl&3ɵMri$B)J ;%*Uʫ,cYҲZ%rKe%0}%a⪘Ɣ2ɪe2SU|&)MOQ&65IUrzf >SL,' ϙtst NCƳ!g=yOLBdd?V4U#dqP5k cBшqE)2bP9 A(?; B%@ӚA )UX )$jJT=a := O(B-*Q@qLmh UHT6EUU2 v)%աuXMY֎0m[k*ueBPԼzu4\:/D"YEJ ~UeXȊ%!s(* ,ֽA g?:PXǮ. * (˾"&Do7"mZBm V:@7B J֫|[~W[õq2!P/{k WEwC Yyӛ_Խ =%•*$(\!p@"&qo+MM#,WQ@> w}eB>2V?(K-%0RJز q/OYKXE'Awv3.lWoF?7D~aC0l.ֶ G`!AZ˚ n- l~ 6:k„x հngB9ʸ&c` 6b+UҳWM[Vܵ+doÑUnk[5\o{YnoqϻX6ouWܿwWW}u{j!mۛU x3Ap{3ǻpOr͙c6 s1>y`* ZDя3tIҟ~%S}/V:.kHY].vqY^/{Ȯ;w0ɝZu+~{&.2;3f/PB<曮c CO=“F?MRz홾#b=ٯ=so^@}G/O!>%s7OS_"ֿ>D}p >"M_j/o~'Ggԇѧǀ'Ggǁ灰'Ggǂ炘'Ggǃ|'yGugp,xGOMOȄQO UH8r7 ]腱a(\hgjxmdrȆt8sxczy؇erwH1-1-XȈ7脒81l-gz牂(w,wqXy둉8Xvqnz(hŨȌ؋xVv!r8v،ߨ38шXH;PmGjgeb_ǏZWT'OGLgGB?ǐ<96'3G.g*&"Ǒ'G gƒ&Ff熓㦓Ɠ&FfƆƔ攠&Fzfn_RƕC6)&F f稜Ŗ%Ee~sŗcVI%:E*eŘ %Ddꤙę$Ddτ̤Ě$Ddě䛫$DdĜ䜑$Ddĝ|yv$sDpdmjgĞda^$[DXdUROğL?5$(DdPyjyZ >:EO"$Z8t(z,ڢw0;/:6Zz2<)5VBD*=IEFz\ԤN|8Z7XW !_D^J+dZrhb*p >0+k . ?#kWi<!!P mPA;  \Lp\&#3m`"pp1A6<=\|f®p} &3R8<U,"°- >SgdT*R<YnXaS” $|+X|m ʼn\wyli(Njƒ=&;l?, Dl=u L>˷B0Ⱦ ˿ۧ|̭2)۽͈"H͂́̀{byBtb4'8-fzvrY,zldA=<B-ʓlҳ#ݙPW=VgZw^bݚԦQmGۄ 2M!ٍ  ޑ!dS4NφoN6 0+nOsn"ȓL.PLzF#7P.;W7:.ͳc=._}?_s=v]w.,P3rM1o E;A=⩍ȷ2o| "(AQl ͦ Cj&Y.2`|2()VN#-s^,:x<35n$L$vg3i3,AІ3]ga2zώ~#-@S҄4M+ӞnBͨN:ns>L궁ub5 YOIֶ sM]:ek-$h96͢eoRiSkоvmYN6"q+>[=$t(~r-Ż77k}nOP?pa8đDo3Nus?j*.r:9ECG.c<339Tlsog9Fғ^'FХt:͵Ns.Ŏr"Gqgq7 NpoFnƧ%n31/{>z՘G_~ԭ_{xG짖{>mq| 푟|/qSiֿFzh_wFK#h!Y ؟w57(AP, w 耚a(;À8؁X8A&x!DG<1(/H=< I|ٗQØ㘙tyqK8IÙ $Y({c4Iy79A 97iAY6A;Wiù6Ařќe#ytyJtܩ6Pq6aXq`Yɟ?:I}"ɠ]%)Yc(DƉUát 4%B#ʛ'4+C)Z-jP 94Z/*1JC9;4?zC6z٣5D:Ji:#3N@PjTCMz5ץ^CY:[Z@`1Y3vhjڗlJTnYvx޹y:8f|~j:Vc:"hE֨ZZ8 a*AvZ꥜*`LZz^q]ꤱ0d9Kz.ƫDK7*IiZLNF4 BQ&!jTʭW*bZF®]鮚"x ̚j) iw ѯ"qj( ki{j [jji;C@(ֱ8$ۃ&K(-i(&WbF{2"1&F c睴91vcy?p s?p@?3FK*Ca%᝷ U w b[FM۶e[j[m˵_މ4#1ikyrK#z8};]cOaQK8b BK1p[%@PP.RcP= b0bP;UA j@Kx+ ;;[;Z༵۳iCe[KQ fKΐPċ ǻǽŚ9 ? w T;SC<{8 +8''!Hl#''H4[)k%,-L'1)O@i.LcPFRVi%BT^Yn%]~)aiei馋m)gq4hP6VG <=D` R@bhFjؠMpBgAiuJSyBx jEFi*,\jd)j̪UlFqh`=ѝ؆;[[ +,'L 7G\W<Hqq lZF)rE-,3D1_ hA~3+\sE1\qCG?B0tCSC!30ODprX@w--M Wg1i/MVc @`wxCw 1UAHhYx@< y*ɪ>r뮃 {N;ƶ^qG{ <ԏoCOx7%G?PK}^}onޗ ~Ol ~?jGϿ(@5f: Ťz#h RPJ eK L& Su.|b(CѰ!q>!xG %2EN|"(EQ E,Z OZ-Q\$c¸xF4vQ;@ (7:@@G;:G?PHCj@8ёtWyI|d&ͅEVⓡ(IRҒL*ͅMN ܢB`Y d hҎ,~=Df2Å'2p τ18MliC6n^klbiSV-vegLAV'9JEV`'L@rYDBPsM.d;)ZtU@|FQ(Jҕ֫.Gc*/T]3i'iToF5WT |*T(թ>V VZr^꾰5f=+ ڪ+u]i}k*Wŵ<+^ ׽ ~X`x b[2VW}l+YbES,ffeC{ђ6,=@\y-luH nsa텂+G9.r tR6Ľ.]X3.xc"NuzӋw%}/H+_з/~Y=lXP>b0y0 +3,XWHNC| &>6bA)nqU<ט7q=c8?p'x'6¡k6<jħ:qVOjƍqvܧio:r<'wiWr/h+:֜7gss?fГ9t_}G_eGL6OGd9uw`8yV`yu>_7z}W_Ϸz>|^7{վz^{yW^7|x^{|5vϧ]c7}UuG]Kuq\6~kZ=;eJl$O2\5X]xإ+〩 Hx2CH28C_H2#hC!(`'(%1+C)X`/-13C1`7W9`Q?vE҃F$IxaK1MaO8*H03T`VxZHa]X\ !CB$h(bj%ֆnbp+Fe1vhÇE(tB#qHHiÈ^cnkk(ˣHhhhb#_H}g [f (`h^勻h]#ZHcWÌTB#QhJONÍMB#Khآ胎IȎF(beEDÏ>m%;Hc97萒"1Hc/s⑄[oBđ)hk'ȒgQ%EU!cTe !_Wœ([ZEa\]Ŕ% HU`e ȕQ"cHML–heg MHBk%ɅhF—C*s%G-yǘD=ye'9b8lB43ř'/bpB -šM皓'PDgt嘏ɛ#BBaœ!b @P @#)@9ٝ4҉ O#) 9)x ExpکI p9E ye@`ɝ[u@I),:y 0&JM;@sEQ ɢ)a f#O^zp^g*oJxb `Zj`zڧ'*`G k:dʔaG!扞 4BZ, Y 4:wJª"F0f榫⫷ūBa @dѬ5*]p%t#,WNJH(̈N$0׷pKm9˳y!߿ʴ1X0w_%Zǐ3k̹ϠCMӨSZa=umۭqK`18q_~{9 &^@`ڃ@]<.汱/ ppCEyV $&6gU{\ K8O|,d#;ͯw/ES$ Sn* TETw`'^ 0IbL2f:Ќ4IjZ̦6nzRc6 m:L9sj~\*(.{g%Gi0n81;'KDN\jq^ D'JъZͨF7юz HGJҒ(MJWҖ0!ӆ]+3_tZO\*K#T&Wӌk_IgzQ` 9PZr]_͜W1Ƹ#0c!,22    곴P@( |D%1cC#:QdB܈R I6`4O:989-p:@Ar8P <͚W 5kB ٚE(w.Ժ9Jv/_yʥp^ƵD!, 22   곴 @<( ‚4T0D%^HТF5~Q#"5BRc-,PPr$h $qAC APGPݪ4\>@(!ְhӪ]`[\nK܇r !,22    곴@2tP@ą )B(1Ctt1H-YQ%A,4L F4% $@ύ8QI @\0'¨@G0JD?$i⃄R$`@!, 22   곴u <0tD+.l8E=nRdD% 2`-62X`Ύ8xà.` (ZI$`z^|PBĀ!,xx22xxxxxyxyiitt vvΕ//kk\\""++MM<<qqEE`$$Ql^^dTTpKKrr66QQ^::m56 V~avw >>''(p 0 @AB .2fTPaā,h 8cI DҢ˚EM83>NATH"(Ҡ pz3&H![@V;Lh-p )3hCeb, `.x8W@_%p0jd@%IB!>6LگG\G^j&MzXM]8t c/l!,xm22^^/jj5xxdtUtғHHTߛHxxmm ~ HCCmCctm5ttHtxyғCxy,,66\tCmb,mmvv/ߛ<ܐ5/tCiim,>3$$``<^^TtHn ,,Ht\ғm$Pҍ5KKҥmm!Ә6++oo8tH666| \ܢ<4rrm mCbHtHҝ;;\QQCn,/fy Cmm::QߛӅ/56 S''{/Ҵnn8ܣ<Ҟ;Sߞ6;~ vwc`\, ''H*\ȰÇ#JHŋ3jȱǏ #Id!Xr%0cʜI͛8sɒWhGϣH*]ʴӧP3!qFD eq䓑8PPMg!q\vi}dYQil&j)'xyb矶 蠄&h&١6c>*zEJ饘eiv騤*iωtjzѬkC 찹 K챰첥*쳜:VBkmfҪEv% ޖ{Xkk նBII)x떾hiK7`1YALZiy ȁ롸$<*\.Ǽ-,͵Ώ_g3D,tHsLK3C7-aKOmWU_VYoS]-vRamNeXOOpWvoe\ܰ |`Y7iu@!pBQ#'иHn@lƒ9O70F.:5XS驫>7uuދ:t;P>9nЎ~ZWcт]`"}'od@ ~z¤~L A@2| ( T3 rp B(Bf;! Ŧz. chPj6!rCD!&!F%2eN|bʢ( @"9-O1b&.bV ,Q,@,xģ 7ZCzDB!~ AAޱyt>@|u|$& DRrG20IMQ }$B[l$$TAV)]JZЖ#^X—q&I RӔ@ڔI5 4%3BjܤMj $pqk$. N Ȁ;Tgk@  AhbwlC %aZAEAπjtHpTTK Кt]QH&MTUi3*P30*43hSIAjp Rm`HBYhM{ a+RN$6.+ӨZVX8X idXH! 0ة͵EegXKxS++(;Z0gQ4Za+i A̰=2kex@njObKIl}d;e,. 2W=P‹^jmպ(_Uѷ/~Iz\8i>0D>v0KgTw6V ofp?3T`$nQU@`l1Bb51Vc =x!l0.Sy # e92@,k_ r,5e:3Ǥ5wn9Gvg7E33$AІ?3[~x"-iP!s4uM'Ӟ.C7!NTwխvu~a-e5n ]L5n=a+d3{W~vWlikwkeboǷ=qc uR~w-oŻ7)E}K~T^)\Q?]0N+7kS3s,0.r:䟒8L.KcӜ6ss9u9,FʓN3Nҟ,GF:7^:uI0?LҮ7b;e+Gv󾑽]*u/xC;)g7<#S^4<,d <_F?SSճޓ=\/{{Ǿ=zg}S?|};|7ϧ|#?}WG| }w{>~{۾~'{>zttht{ŀ ׀1h xް(A  {P&A0*wA0X2H58l=j)vB|PTvq #,ꪽ];+`#a绸#qQl\l۹+@ˏz|kg\ikk m=жP% #,}]д<$mаOm aҳU6\)dmѣp!,51212121212121222222211111111118899:M#snlv`WMIF D 9*  fS8 % %5<@ DA#A. E8 JCNNQQTTWWYY[[]b]g]j#]m(]o+]p,]n-]i.]c.]`.]^.]^.^^.^^/^\/`W1cO3iI6nH8uG>sM:rS9qZ8ne6lg5kh5ji5jj4jj4jj4jj4jj2ll+ppvvwww|wwxzy~rnfb^\\^cl sw}#ޔ&֛*Ν)ͦ&Ȭ%˵"ͽ%2L4N+V]a clu y~+9BFGJMU]jqw}ʇЍՒݚߞH*\ȰÇ#JHŋ3jȱǏ CIɓ(S^<²#Iʃ-rɳϟ@ JѣH*]ʴӧPJիXjʵW/]RVhӪ]˶۷pJݻxAeLÈ+&ǐ#K2!^k̹χ'Mi- װc>M۸+dk Niȓ+{a!ߙKNسkn[ѣp</_^s=t_=!z\%zM6TcM75k! ÄV8!UY ڷ߇ _'x6d5024hTA#P@FA&rD:yP7/`c ,hTRO:c\v^CTY:S7ռ% 9EMz@5N"K0$N:2N~:yg-̐Ĉ- hO{ԧȳ6rO4©©j-(* vZi^Jg9Өʧ*O (J Yֺ,(tOY knw~}݉H5xgX >a /bLo设VZ}&/b /&l: ?."ܓ^ij8{Բr&W*:sK̀b}F(0019F]5 S9y`Qf뤂ds5j ͼ:Ep݂x+ Bp.'*x:; wj3ߎ3UK~Pj;뤸No.k{8OG7xwz3^tMeZ*umN)HS>:Z*'hʒ)~6I~-op"P|~S.[)@`S_ݸՏeΆ"%1@=P!:7xwYC KӖ֨GQl[Xj9+h 6 odt8J-W010C>\zEd̊=է]E #8tIwmتVjarڪ! qCqke *WI! W9bBtr mIhhIS}%" *u&F]JpN &4@׵ 2U|2Y8ݨe̔YlbcaY,_Y,bOJp )wMh\XZE 74؆*Zr$5֏}JVva*KNڠ\9n+a.ͩ6]Ti@0zbxI|VP^z8Ҭ=BV0ԡ7(Ntъp⪥ 4sg%k++ { TvsZGɟ)0bا4YII/XU*tV%Y W勪@W8KMK\2Z ngK>Jƚ/: 6j!([br0w?ʲf8NZŷu"jGW:5SWvgzBL OzzLVV$wkuWDO4nnFv3v(O|R 9!aH@ !O1іCP ѣnm'@~q S뒙:A= -I9*!Z?4NCt"sy6N@ԾvW/5i:AKcB/-y}IJ/۾ߴwO?{OY;n>OK>B{?yg̻OjÿϝXZ1 hW XX1 z̀$ 0 '(2p  :;x 7t5Xq4Xy pJ ͠ =wVhJJNYpXXt!c d wtQЅKr;x gP(0 c}XGhP0:ȃOHp؉)q j()s.o؊X|{XX{(z؋Xx8vXuǘ̸r،hqpX ؍wXF明熎؎ƎXF†؏ĶYH҈ ِȐ()oxPJ"Z0zA: DpGJm9H ,Tm`ѕN*E@@,;DF|2J\L8PR<>[V \_Bm.D]ƙH=G]N=q;*TmJ}gZ "\`Y='feهl]krB{u}0ymp{}|ׁ=p@؅oP ؎M| =Wٗټxs 'ڍMgڅکmٟŷ =ڰM|ٵmz0ۧwھmÍҌm2 !>ᗖ>>p"n$^(>*.no'146~:{-k@~B>QFk?䫄LIF.CN@n=:741..+N(n%".Nn -Mm -Mmݍڭ -MmÍ꾭 -Mm렍뜭 -Mm}yuro l-iMfmc`]ZW T-QMNmKHEB? <-9M6m30-*' $-!Mm - MP~PLp r#Oȹ<.Fm1B>m?CEGIKOMOQSU_W/Y[]_oa?cegikOmoqsuOwy{}_/ʁɃɅɇOɉɋȍȏoȑȓǕǗOǙǛƝƟơ_ƣ/ƥŧũūoŭ?ůűijĵķOĹĻýÿ_/ɟo?ӯOݿߏ_/Ͽ響o?߾Oq ,DB >QD-^ĘQF=~RH%MDRJ-]P`Ą1męSN=}TPE΄XRM>UTUNEPU]~VXefuZmݾWܘhW^}.C FXb^/,Xdʕ-_ș=Z諛 v&Zj֭]w4]kڵm=96B}\fG\r.o]t >m]vsc^xG^zٿ_Sǟe}P"$@@d0B {pB /0 3CCG$qKD1E(V1F:qFoız1G2$H#!H%$2I&RF'J2K-%rK/$K0$L5OL6߄s;73O=;44PPC=#PEOd4RI1KtRK/RL7t,M;5Ԫ>TSBJ ULH ie(UXWUWXfUjgdkbS֤TkzU#ƒ#2 o 6KV釘tW %Z{l!ZyWc؂UV=`y e1_/vh} :U_cWiV^y͕^ b_Ev^q]aoٮ;V(ۑw46ցO.V=ai,Yq}fXxv&jq.mIvz f~vڰs#.C#ud[8QEnOx&(f 5 ̙VUaqE%uuouq}vvv>wTx⏗x?Tyy觯SzgzS{{ǏR|W|R}}珱8? ?27nȊ^z_*`*ĀD%H% `'#UB!H Є'Da UBЅ/a e8CІ7auCЇ1~ Cd2X !^ )jr !Q,~u22^^/jj5xxdtHtmmғHHmႿtxxm, ߴm tCc~,,tmmTCxyHUCmmCCxyғCmCߛ,Cbt65CC\vvߛH>~ ߛ$$tg6``ܢ;~tm^^PTx xn 5,,wBvG \5$nҳKKx !mm| 6oo8tH4/,‚,66TrrHHmCbHl=QQ;ɴfJwB;::mmmӘ5߿56 tHttUUUnn8Ҟ;m>Tvwc'' H*\ȰÇ#JHŋ3jȱǏ C" @ C%"cʜI͛8sɳǓ&8ᒥH*]ʴӧPFPGjʵׯ`Ê< *bӪ]˶۷KJݻx˔Dw LJǐ#KN8"ɘ3kae;MC^ͺk~M!c74kfۦpJN6 ]A_O τ~;˟}BXH7g:dB F:%h .xP `b(ihǟo@TH4gbA(: xjX@v#A9i$9PH6$}J TVY]Li\҆])h_66hVflٚn)cpi{Չ|g՟jR8%裐hVjѤf)Cnu ꨖJ꩏ꪆ}SA% ꫗UYfS7HíF+d &+ɪ*$Imj:.BA +8.B1BFM{lB`AoM[). ľ W,45AhA"<&L*L.nj26l:lD`,ʖHw[nG'tk9` wDB$Pn:XBC+A dS;ܳ72P>^z#DŽ㋇y*P;*=34@(H#7-$; ,.:DN~@]3;=|DR/y>/ Aa =o8sC찇@!F깐D$}Idb- &bK&)}p FbOkJ&lsiQtAeTRGRUJFzPf;[զ6tm_y-H־8x$F ܖws-rm mnZk~ M\zܭvp׼CI*Z@c|͸ n< `%:0=k.U qKa)ixÂp> B8h%6qSX'&e*6 s<؎>q, O1%۩N)SMV21qa2$1[f5In~,g ѹ53g=~mAA>b4KIKҖ3mMset<-㐺3 5_uUצծc}*XZMusk5%|aZƎ5d3Q~vf-Pڑ6Vm{12-nÐ܄97/uIYy[wo,[7,'3~3\x#.q$7<0q tM5ЁOΦhA ^1`ஹ\si8t |i *h3:'.ÙVֳ.xs2[zy.;9;sߤn >,%AtD7v'w c95#/Sі||p<+"OSOճٙ}rP/{N=  ?>qc|$'~?}W}k}wg=#|&&hISC+Ha)) x` )PGWQ (tXЁA $&@)x-@0V6z;hz=8z?zAyCyExyGHyIyKxMxOhxQ(xSwUwWHwYw[v]v_vaXvc(veuguiukhum8uouqtstu8twsXᖃT3Ї~(" 0%e` H8Xb7h?#O艟8m"V8&bpm"؊&P8/'v8n~vZ:g50,nj'"'Gg Ǎ 'GfƎ&Ff↏ަƏ&FfɆƦƐ搽&FfƑ摥&Ffƒ撍&Ff~{Ɠxur&oFlfifcƔ`]Z&WFTfQNKƕHEB&?F*;,33H15k39H7;Kc=?3C2E2G2I2Kk2M[2O+2Q2Sk1U[1W0Y0[/]iA[_+/c/e{iaˠgK.k-m-o+-q;jis+w+y +{juk}***{l(;K*;*k;)k{$;MPps0 00 pK DkMۺۦr^\J{$P ɻ $9 k՛]+_[JҚ 000s;9оp;k,K MNQ@p; g@ P%qŻ,,$|P[ |1 g#: <| *„| @O ;{),|J>~ tJ7ҳ3``$$P6t^^THCn wB6J\$x m KKҥmm!ҝ:oo89--46Hrr66l=HHmCbHQQ\ſ;ſttmmC;wBfsDCmmuF::mmғ56 tnn8Ҵevwߛc'' H*\ȰÇ#JHŋ3jȱǏ C: @S\ȗ0cʜI͛8s)ѤO&@TɃѣH*]ʴӧ}eQXjʵׯz*سhӪ]˶mĒ~qKݻxҜz L._^̸7L ˘3#LϠCyѨS^Ӭc˞M;k K vnp&μs?FسkG @7oOYD6"A! gFB)[~ F(|1xfvnu$b'b(Hۉ*h,(㌐H8fc<֎>)dW@iLLdPFғRVim \v%y)QIcWP GI>ډ7.)PP Y`E$I4C >@3A@**|.@ |W*(:9 a(Z(C1*YkKi*ނj.Vj oo6pvp _p;p6quq׵q q$5r(our,?r0+r44s8G%ba[7,HAmtGE4FI/D~@{$b@hASP`d=OdL\vSh}vW-HcwVDԠ@@b  @sȱAtB/' ` zuu0H'5Dcn@7Ln m}![~Mڢ;3kW=CQ~BϾsL0ߏ?r#c< @1{ & "$3 r_ B(Bw* [,a bI c $ЇO kh=?6qnR!I-$p?|B7(D'rQi^- D2 CԃO x|BX3/@7r~C"9<$)FI^2f 6H,ᓠ7FiGEf <%*[JTL2+'1K,ҍ/XJd4.e,@nD58`Q 48qӐyNutgB(FNCJ: ib)F(04P y0gE/ M\ G)B}2r ]PJt@mJ:TՔpT@h0*-Ş-: U_V` QQ*h ͪU~S!IO 3v- UפЀ62`MAko|߳lNY)qq,h̎ց=ZKwe-l Vgsbm+> #.re-XsRDֽq.x3$JMz{?}~+_ A̢/~ߣ} +W>0 f%b0# S3" sNplB,Ր0tH.Sc836`c+51!7F^ l1!3IK~,!Ey2 C-H^&MÌ#0-f>ZҬf/b3"9v.=y~w-=4ϫEюn/# ISz}kiչG4mQԦ0S"QZg~uc-k@Ӻփ5 ]'׾f4a[>vlL3ٛ-#i# 1mms;-ng~-#u{a2[>^Ag(8| !p\S߻j7Ə+oC/|#?L,\N9kY6Lss|?y[>tG'yCt7}Ox+>uW]W/xu|w}_ww=vtgwڿvn=ovܧ=wh׽wWvޏwb=uw=x\ևu_xV7>Տ7uG=yPWӗt/yJw>ҟwt=zDЧtz>>ϯs<{8׾ͷWsϼ{2>̿r𷌇-v0b<|}ԯ>cF0k03)ѯ(ޯ'S86 7hÇe Xe (e dd uPq 4[ Xݳ=P8=I*s,/184I 6;d :a@3>hLrXIFFfC@=ƅ:74&1F.f+(%Ɔ"&Ff Ƈ &Feň%Eeㅉॉʼn%Ee˅ȥŊ势%Eeŋ勧%EeŌ匁v%jE]eRF:ō*%Ed㤎Ď䎽$Ddď{rg$\DOdD5(Đ%"$Ddđ $DdÒ#Cc惓壓Ó#C6|RhF;K);My:Oi:Q;QN1SV$H2#Pԕ^ d)7i6kEfyDp m4u4w4yFr9Gӗ~949GZY;qɠyg uq ݃`tʀp   9XwIw@)>9!y>tS3 ? 19ٜЙ99 œ%NIɝi?㙝)YFI:S9iIZ9ׄЩ䴟Z :Y ڜ[١%I (Y&ʛ-@/1[3j5@7:9 \;=Zcɥɤ䤜 C$i҅ĥ#I d~#Ħs B&$piࢧ)gɧ"^I˂¨f[ Bb &V©I |B{bx&Rts ƪO(oblkh«,FLd"iHH2fD^¬]\m?(>F;hU6ȭD35DVJ$$$ eZ'j$jeZ*$zad 0Wp5aT%G ˰.0HS} r W &;RP@%`+5 a1 .-V% B{IGLSѴ1{57;)1WCZ 1 M;KOд VKpkEZ@6 Kn_M;cWB@?0KRK[P+ßk ۶ +K/3Kj˶k7p!k [Wl˼S+\[WC k+$ ;#;\ề[fkk\麢i{;#\Kg \ " rjT-3E.!SE@Cqd _0+ |(*,.H0)). 0/Q  /*т:UP.2+) I--)RBŗ3.?O -M `BN)*|$(2_UB})*/0>`.~P jl-b)RŜR.\<j,.*j,)`z\)VLɅƈiU*L./@, *,,t:VV`,< g!,22HH$@  ғtHHߛHmmmmtCmCCd_CmC~$ܭEH-CmCmtCCt C[ܞ@tғCm P[ܮEҴm؛mC,eႊJܟ@HH߾^HtB"Y5b[^,,m [d@ ۭEa\ \aŰ{*CCa= ЧD.ߛғ,,\,\t-CC{),\,t`H*\ȰÇ#JHŋ3jȱǏ CS`+"S\ɲ˗0cʜI͛8sɳ fx᳨ѣH*]ʴӧPJu tЩXjʵׯ`Ê˰UhӪ]˶۷p<ܻx˷߿LÈ+^R`Ɛ#KLe/k̹ϠfMӨSװcNz۸sF]{ {ȓ+OZ|УK|س'OsOǣ_Ͼ{˟O#(G&Ȟ 61V蛄f= h"h|,H.(OH8戓:!D F&H.:6 T(eXfZv饃\~)IhgflIޚn)upiՉ|gڟj(h袔%裐hVפf)[n_u ꨤF%jzԩM*-J뭸vdk:Ѯ+lBkl.,>+mNk-^n-~+k垫뮜+okޫo[>o" F  1HOsT1IyQr̲FIL%ڌsDn<;s! `q* 5;MZjPJ Mᙍکz 1Myʍ"߻ N-;BKN)iyYNމx 0c>_';^{.q'zI߼wZsO}>g棟W־od> b>0ؗJ̋ E{+7 ҏ d 20-#!OBN+l r;p8p+( Ho&j0% DTbOc=-zQ'\|HՑf<#Ө|#(9v=Q}~);$"E&$#IRv2q$(?'Qn*S9Uq|b)Ѳ%.]09am<ڒ̳1c{&4&inּ69mri)N;;':ou4<ٱysb'O'@%ЁʫuB2\}"*QoQں(FэJuHCY; M`J)L9ҙ⪦6LsAU>)v*:*REKRd@5 @ Gj*J)\ *ճXbe[VNsk]rW;U{-P\WW)X5_ І"}b 6r,pb6NlA@Zzv#l*:0L0l"6`_e¶l: z[AEX@4CU[]$+J!FF>򌒬uAc2)V~',-s^2>,}<35n>(9ӹv3D33*AsІ(-E3~4J% 7)Sdf39NmӞ.SC}QZSU:s~Pe5W=u{r5#a-T:d3;S~vv-PqMks9r-8܇"7u }sӻOwn߳7c#'3<5x$^g+ 3s3fB.ː99;w儆T.еa9ΝDKJ>1ЃF?t!3E~:oO}Fdc7lW:y@=WqVm;.wYuUwj ?k§O "3>C|X"/P9<1s7Z@Ϩ态ZP_(ͳT}e)Ӿ)Rr{ľ="Ƈu[嫩wO#Sֿ~}bs//9?kO6mk?Xqx р+V%1'"W%$$x*X-(t/1Xt3H5t79t;ȃ=t?AuCHEd!xJrL؄#PhrR8)WVrY",]_؂acxeXg(ikȁmoxqHsuwy{X}(hH~~~X~(~~}}x}H}}|||h|8||{{x{H{({zzzHzzyøyňyXy(yxxϘxhxHxxw٘wXw(wvvxv8vuuxu8uutJ[7 "70"7@x"8&2JGDǐA>;'8G5g20.Ǒ+(%'"Ggǒ' G gǓ&Ff릔Ɣ&Ff؆զƕ&FfƖ斴&FfƗ旞&FfƘ昉&Ff}zwƙtqn&kFhfeb_ƚ\YV&SFPfMJGƛDA>&;F8f52/Ɯ,)%&"FfƝ & FfŞ%Ee녟襟şes7z!ѥ  [XzYZ{{uo%hE`eXQKŢHEB%?EQSbKc#:!$kYYe{0 q;ව5P.KCñ'۷A;`)Kh '˳! Pp0` 1gj˲F`k*K@/!R,22U*H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\0@0cʜI͛8sɳϟ@1|ѣH*]ʴӧP"*@իXjʵׯRKٳhӪ]˖رmʝKݻxq߿ u/_ˆ+^̸cT ˘3kkϠCMdgϥS^ͺӨ]˞Mmͻ5sN;#_μsʟKN:fƶνq)g跒OϾ;ßOϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz9 x9،t&-n dǞc@VΘt0L_JR D<4m'QD%DQ׉T*.)IC4Vg@!,1111111111111111#={@\>&(  ! 3EHKRb puy (3}:<AD@<7=INNKNNKKOTTTTTY_jv ~ +πMBЈNF%I[:ҕ[xӠGMRԨNWVհgMZָεw^MbNf;Ўv@j[ζn{MrNvMzη~N;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhO|pnex:<.)A[e wH|zgz8 Xxq# tyx'!*,HF+؂2hq.P6x5q7<؃>}/x&1D?8x.EL؄#2N8,TxXh!Zg`8dXODžf'lp6uGjrx x|؇GP~8(Hxpxh8oȆx؉dX8hxYH؂XN芶؁D8x~ Xʸw88OlԘט{θa8׍xyqx؎agXx.B,b2yhv؏~7gH*x W yw9"yisБ "9$Y&y(*,ْ.0294Y6y8#pOhxFyAJLٔNPR9T;y=i?IAڢ1ڑ-jJJ%1 ;ڣD`2TPDB*,09䰤&ڤ&zX_jWڦD?0jLڣ栤=@] L@٤W6 **@SZ١Lpڑz+J쐧Q jyj::BکOJʪq*4:YJJJZ搫lz*:t:z*Jݚ:ZڑБ*  sjj.WJj*tc]z kGk:ڬ*[JTJ*z%j4Y  ٱ PzrگR kP,z\p nj:if{nq[ۣ8 lڣL^*:bKp:44[Tzߚ"a{Z맆*`r)oꮋ G`z S;wYOqꑡ躹:ڸl[1:ںҊ& K/ۻr*ϋ)jۦ+i +k!)++7ʢQ ۵ڧ}K鴏:I ZW귺;B;*[DKH:{a*ښ \+GKk*BZ !9ok‡+[z8ʪ[5L+: \H zZOrQ`LCpzzO:nlZk{4Jjk3+x/ڼKC<[h İ]ɭ \ zŲƨ,:q:1* 1Z ū,쫵<< (E̸lü(æˢȪZ͒  |,;〿~`V0GN{ʩTX̲.*J:P|j{{ƞ, оܪ ЋDZjk mlm̬!=kۣ^V<9l\_\lE렓8aG@+G@ \W޹Z Ofف&gL &ɣ ]m|gYgӸSmGz]؆|׊؎k؋=ٖ}͔٘Mٜ٠,ٝ]ڦ(ڨڪ-Ŧ{ڲ=ېMڰ}ۑHۺۈۛ=i}ȝ=ݓ}֝ݝyGg}W,Pz]=7}mxwz ~2P >ΐԇ^%y-M(m}*>4Ύ]8x:>wD~H>FLMNR.P>V~XX\Z`b^f|d~j柗lpnxnt^x7vzvx~`>nu^舞Lw.t>8~řnt^mhꨞ;7>붎~깾뾞.>ƞ~ɾΞ>~~پ~>~~^>N~>?O  Y_ :tyui*^y"Ot)*]/2M.85x4@*/>D?J_NV zw^}hp !N6~>@0.y'O׍? )h?(h?(h?{(phȿeZ?S(Ehؿ<+?( h?'gʧQ@@ DPB >GD-^ĘQF=~RH%MDRJ-]SL5męS'É;}TPEETRM>hOU^ŚUV]~VXEVZmݾW\2śW^}X0ٻ FXbƍ?Zdʕ-_ƜY涒9ZhҥM|Zj֭];ijٵmƝ[ִy\p6\r͝?߈tխ_ǎ:vݽWzx͟Gxݿ_@ǟ_?0@'o@D0A*pA0B jpB /0C 1pC?1;DOD=SdE_dnEgFYFwGb@ |!!4}dI'p2 RK%3L1ǼH3;H5$3N937, M<<3PA%;$,QGԠC<7 Z2RM77r+CSSOEuF)r"|TgV35W]wW^6X%XcXeevd6Zi]{vZk6j[o [q%7pE7]u:w]w߅wv㥷^{q^}|8`-w`Fфf8b*xb/57ָ#0bG&yӏA8ee-e=e=ӗoX7g19g5wfh㞑i~iijWkdžTdF{Cf݆;זnnF/o;'7t"tW7u_/-ug+k=wn׽wߍw)xG&gyw>z9~z77锪6(h'|/Hg}\%2KP{Ș{b~D&6--# }$ @pH@奰}0?`M$:SV(03D=eP~Da|jh (i%"gDl"\XQt"aָ-nqQG0(3PaTlczȎ[1aD%4#;C! F'p*))dx v %z'OĐtL {A6 xKp@a&yi#Dfv(P L&w"As}NoLvA*cU?p, hs4IdӞ9G{f$O, ,hB/ (QjʚXdE5*6T$hHe4)ARiJR4[,uiLSL%-Mu*5ԧ;+:TGuNT^̨Mj:Fժ .be\뮼:аT5[Uͺ&owծ@ #w*M:Vְqj#6vLhm%J;Y'ͬ 0X*e5+&s:QЖE'h kZ֦SW[;[ZMc%+mudnR ,0g i/p^pR2׺̲Wnx$%Ud4UMvXR!݅ }n;* E0^EkX}Mp9#!pCjWcERdct@(ōBD01/1&*8?d/2)OPIrW!@(!PWR ݞ 9U15*-Xdp<4'}g>fH n!gvЇvAbD7Z*FKA=iK)5Ib57=XGMjV %̩Ȫ[=@־TuIkחn؏Q*}i@lVIYBچQ,Ǥkw/y=3mrcA ]nv%جr=o+Ʒ[mQey-m p<x> xƫZwA%#GyRrbG83"{ksܜF9y>t{&zkpEݚJ$Q/ruګZ'XW}cGJl#ǹv*xw|@ L@J< $"S#4j12+lA۫:AA>jx35;@+B 3\{? '+*t2|:,:W)—àK1D 3d;4t9q;C7-C:l :C{C ċ0A 7D+1LDBFt2|Ě;|ICDCI}NԬ2 @P=#E3FU88$9DHDYt9L<>]$QEʒ*$l`+DCƉ*f7D3^Fvsq=Zl)?.FGs4-3/'TGk::Bfpܽi2p|4@rG HKk!3CHKLJȰHZcYc6C5 G1IhĔ,[\3;lIVӶ&_3kÞlI54JBJXJk;|JlȭʴSʫT(L+l9 - Ëp/qE$;PARqD3*@6E4/@I#! $KGJ@ ,\LnAULA2=?7[<+ˈx˳ Mь+dL13DS7M>L" LN%Gڤ#L9Gh2ȂtN0K+,IN̮$1#M"<$sMTϢO +MOr Ы5ЦBEePrН P uP%э2UшbUт{}t h""#E[R%M&uM(E RS/Z/./}0եMJ2--jTS5eTՄSEDHN=Ţ?Tɴ$ATI8+=Mν ADTN*SL].(CPȤSQe.JeKRV5qT뺓TKHU ^E_ab5Ad5eeVqghVjkVmenVp%q%W1stUWavŝwWڑyzW|]}-!؂휃EQ؅uXʁ؈XDZ؋]؎-ّ5ٽAٔeٺqٗ])ݬٶٛMٳٞZڡ՚5کAڤeeZqڧڜڪZڭ-ڑ۰=]=T)>XU[˱}xC ,2U=L@ۈjL!yT7~?KmB^-܈K{l[]\p*?Ԍ[ȵP̅*܃݀5}AԽezq׍ؕw]t=SߵR[dڟ9U-U^lJ rt2S^pum#_l!EߙZm_Re_e5_b _ޕ&\1VYaF`S `M .Ʀ F&&aA1V9a1a(va&! &b C[=bEymb'=끟V\Pb2S Nb,cTX4E-b4c)U[ce"2?N@!B.CFQEFvdud IƐJd LMdOvPe!RFSFeQUWcXnVYeZV[e\V]e^V_e`VafbVc>fdVe^ffWg~fh.WifjFWkfl^WmfnvWofpWqS>,%ǹEtn^Qtw_7gix|fsPgN7&hcj儮v>6!-1T&Y:ˏ{K%ic3*?۔nƴG3i9JLiiQYAд>t{=iYv߀ލܰ꫾ꮎ X6Vv뷆븖빦Q,kQX ,l)/.,@쭑l^5 쁨ɞ.Ђ..llX^m>.X`56&;lmV65nl5k5XV~/؂b-Ҷݎl.- .&0lfoko!,5L22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ#JHŋ3jȱǏ CIɓ(S `ʗ0cʜI͛8sɳOIѣH*]ʴӦA|JիXjʵkT]ÊKٳh~۷pʝ+v-[x˷߈vLÈn04ǐ#K00 )k̹g<ӨS հc˞MW]5G5P  +_μ9ޠ $h=ݹسW ޓkO $ ˟O*Ͽ,ph& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k/Fpo <|0 +p ;K<[|1kq{!q&[q̲P,s4Sls'@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJUL;AvvK̫^ApVR` ++V:ui[oWՕvm[sɕ_ͫʶ5XX2 !, 222BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ#Jp3jȱdž\HɓCĈ˗'UIM2gfN= %УH#m02ӧRh ӢP5(V tSҦ%'A"ݚ!H߻[ u+&)F T,tMӨS^ͺװc˞M۸sn+<0G-q̛}֣_jv6ڽz<ϋG?wB/>ۧ~ހ&_HGP@!,%22BCM$ KLW,,8((4CDN..:33?abl@00Ç`AZ1F)~tؑȑDa(K̂jZY:0)O %*%PNp`קPhH`"<@,`apś ޻} ܗ/p V 1z7ŗ-f2bP_O~ܹjԥ !,r"22BCM$ KLW,,8((4CDN..:33?abl@A < |qD#^HPcC-Nd!% ,H!ʂJ,@I: i E"#`LpA  @c,`mc/%W !\b+X/;8غ2~\x,dZ>|rXx!,m22BCM$ KLW,,8((4CDN..:33?abl@A  +P (HlHt!,>121211111111111112.> }{zzzzzzzz{{{xwwvtttvwwwwwwwwwwvvvvuuuvvvvvvvvvuuuuuuuuuuuutttttsqnfb\RJDBxBwBwCwCwCwCwCwBwAu;n4f1\(.O6+C?(>K,8T.5_14i33v54:6?7E;KBQJWR|[X{\Zv]]m^]b^^`^^_^^^^^^^^___aaakkktttvvyuu{koci`g`faeaeNl|||||||{||}~~~~~(:AQam|‡}ha_^^_diwgĉjћqߪ~칏žǡʥǨǸӪ D@*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sIqϟ@6 JТD"xӃLJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ ֺÈoipdž7 Yrc2?݌9ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μ ҀԭӚ^L9?Oӫ_Ͼ˟OϿ(h& 6F(V^aQ iȡ{E,$(,0(4h8<@)DiH&L6PF)TViXf ca4R 3z ^+hlp)tix|矀*蠄j衈&袌6zg"#/$w6";v駠*ꨤjꩨjI+)鬳jHڦl*yk&6F+Vkfv+,$鴁@-Ԃn/Ţ;4c,lS[ԭ0Zl2+ĒNĤt,A,$l(,0,4l8<@-4˝J /Jr#AJ-8=Xg\w`-d\Xԑrvviv# wx\|߀.n'7G.Wngw~x%RzS?SIw-LA#H//^Ep<*B-aK  & TE̠7z GH0B{/ YH {3!@ H"&Dц*P`jp-.z` H2ʰa +\##bo C#> IBL"F:򑐌$'IJZ̤&7NҀ X9ָ"i'! ,gIZ̥.w^rcf-b?L>9Mgә|/nz 8IN_2Tb5@ ~G! ŗ>~30 ct,(4G"Dy(ъZͨF7юz HGJҒ(MJWҖ0LgJӚW4# <0?aQ HdMԦ:PTJժZX%iaBjLl]GZ-<@s9;FxH<8QJPRLxN8XZWq\b8d{^X`Xjl؆wn8tXv٧x~k~'xH;Lj(xH舜؉Xxm8؊(X{8X5g؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙəd Pyٚ9Yy ɛx9Yi0yWYAI Yyؙ۩ ׉u@ҩܙ깞 pG?hɞٟmG>hөJY zvڃyԙ zbנ<ڡI`:]*w֠z`!Ҡ30& 3*52y> *$:Xg)W 9sO&"Njף?DڥYg+WMzTsQjSUzZ\rJu`rp Q@ * zPP *Z*ʢ5 Zzp *j9ʨzPoڡq:tu=jg Pz w꫞V*OzjlxzJ< pjZzjJ }:*ZzJʟغHYxY:.<>@9XpHޥJnLG8VΪXNZ.Udnm[>kX}^lsw~2.W,\ 0Z 08qQ,cLS C>h38L6k舮 fPԙ e\CW,|ϘG ~{gZ|~?鴾2(=ȅKʛȘZLɯP!Đ h@@ PYf@e@]n>B.s̋؉V;,+ﭑ-/;21MΙ ,:ٞL JZ,0 /*P^ћ:M64?/ҧM&]$,JzpVMtokm+%+o\7m / >O]0e-ʴpl֜m u.0Y !VZM='M`-,-?~.` ^o4s؈]8܊ђIk7Z_̲筫Hoڕm]Ǻ=kpr D4~1P!4u&v{oBĒiIXA/t 3gdepTLm@DDTRM>UTU^ŚUV]~VXe͞EVZmݾW\nÁi[/`)kB:^r_yr É,n"㊕/ĚՁvڵCˑC"/sc҉%i_`'SlPcdZ#tjtqsE^zݿ_|ǟ_~wo @( }\<A 2*@ /0C 7C?1DG ? $ѬknI*%7dP ɣκ4'R2H!$H#D2I%A41j1Ұzr,1K-qQ3L1$L3D3ͲTͩlpK9'/3O=O?)6uND:$QG4RI'TA+ D7jQL?5TQG%T/5HM9eR5VYgV[j]wW_6Xa%XcE6YeeY]i'hZk6[m?^5\q%\sD WmSOՅ7^y祷^ҵ?vM|8`_ۗ9=a8b? ޒ7c?ސbۺ,59eWf5]doDfo9E+g枇&hh~ :j4X8SM{jF;3 l t[>W;-[mo&[_ 8͵nq\=p"o 8DzB25kM\q.u_RKFEy(:0xkM]uby~r*,s>24Pdzg_o離$$Hx"M>Ѐ={6nx iȀƐ4WuaE.kz(k`tH؈O^TGC_%TCшG&ıOb>&6͉Rb'%@8F2BgXF6э!:h5юw#~H9byd y/*rpfL m$ldP8HJVҒc8o021:I PN%UJV51"HbRRJ^җPɤ69\t1d cτf4#̨ S(L&2ՁK% 5kl$.#Iӝ<8VN䲔) O~q<^0ض~6$,1IF$wOV^ TP NTh5QԤèj4TK(D:RoԦ7U_Jep8v!C!g:}ԩON?S4ЄhCnowHiBլgu S?Ɂx׃}O)He:VlTժR&?E$`իXNֲuNd RXz"`RC:n:mfg>Tvahzo4LmXZW6Eny4zɅnt\5wSMnv +ͺzv;YuhEvɻ^6ʼCC^RY|^׿e¯FS`7p! -i[p-"^+J\Tv'Fk)qbdqul!;zs,8TyZ]}ȼgF7ifQ"hRp+RIeGwa:B WVz OUFSGF{NO=x=o|_S?}>cw=[s v~_}QG?T_1g,ĝ) )Ls ,)d D'V5(ˆaJ X!;5h5aÜ94@ pR;+鶦6 At*<с75Bh@I8 u-\ j8`/BC$FrC7+C-192C(Cux2@KCdCn oC":D6C:;/,@t!;>mKUQF|It-DԸ.NzL0bP!Xs*>%'-%0ϦҾR1EIR{& M8p:;<=>?@A%B5CScE]T'eRwfpiM^}I`ethZmb/rZ⏉*i:*Hn&J^ʉgx)7cy ꚫ఩i k6kY= -  ؆+Q"-M`ju.\ƻ[{ @<o_ܚdD 71T:0^;S~zl5@M;r3\޺IuکtL+S|Z)ߓHU0BhX P!@^1* ~_1~'`O/? H( HV>_N  |Nw|<=yNДP9s@m *d!ZAr#S`ۣC:GxW<ÈP'$4Ʉ Ȱ0P"ҔFI9q2sg~pbm(Y0PWZzvU,Cv*_#)]2E@+z~EGMBqc />)ЉR {Be'5E2;, W .U=OrE\ I=!sdx >DXX6>T,T"jR%0` y}@}R PKĚN(WH}ƓS3* D:c%~ei0N-+#$(<\AJ#Rp aMQ8ԤEM*O_T:(=iwJUͪKUz5%\WNJh-UŚֶFlu+Z:Uڕr^z$PN#Yǒ (EJ4 v^!b$ )2젗ž5}a!j{\PH-k٘8 f>+ZӦ4-iu7nFqmr[:g= 먫}I`2D0J< VIRۻH~+ru*@{@ P'J+9G>GH(yGnXGJ) n7%AT"'JIp.>N [wR}dt>i< i5~]wnFofK }Wwgi>6'%q5H!~ u xyXy87oS&H6(U,4.204Xs8/:҃>1!yA8.@Xrm'H(Q#{Tϡt^cch](=fL ||+ XgXv4}S\8IhX~PgFzx;qjpĈ>w){-B NRhXB^G_k8Qt|r] R__(Aw1Dt#9M"1FM<‡NFN7R?PƇRkGkh"CazeHF+ggjLi,stbTT Kg`>0CO`F_ikz"Wj`&F'JTLnd'zmXo&CKikN6)ZU,QbcO:q>_rwrq+(8~x-oٛRzǩ*9 )ɜI}e鎣qyY"fC,ُzY~xHwِџ ik,^ b@2!?U(W]璹 *CYF b=$CO"`!,022BCM$ KLW,,8((4CDN..:33?abl 4!&dQ"A -f|aNJ;r(raH L)P$Ɖ9DH1"K !liΙ>-*(͢H*]ʴӧP tIU עZbVT_6Z |+\t>W n*0`a ZHeqCX !,22BCM$ KLW,,8((4CDN..:33?abl@D0a… .QbA^ؐÊ?vDp$IC,+CB8@LhɝĈ҈<5>eT\-X!"|U,B5@P[j (P% p`a I`2<@,``@!,$22BCM$ KLW,,8((4CDN..:33?abl(0@4xPC >TPD !f"Gn,82aIKjTY!J"YfP&Ɉ,Đ&-l8E`4%5jөUNUѮ^' plVZ"|  /^ DAE $Xlb&@6P@@ aT &!,m)k22BCM$ KLW,,8((4CDN..:33?abl@*,8@#&ċ)V|A=$2Ȏ%M̈ʈ)4pRaLhΝ$2'A(UZԠF")BP $`UY פX  PnB .X˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺuÎ86o @k=lǛ-B22$BCM KLW,,8B>MB"((4BC=e@B9M C/=..:33?Ⱥablɛ @A ML B" ,,8w,,-B47KLDwC?N../332((4eLKLWBC=Ⱥ ( wK&"abl!ɛ@@`0aB:D1bC((cF;Ԙ"Nj44yr@*R‡83Р"%5`$q$ 0'HX1D h r,C"F*IV@* `. v(E F|D20 !BhM!!ōMqQǏGL!, $22xUxxtUHH4t@Jʞxxe'&L@BCMxylxxxy)&veJ vv$xSxxxvJiiUKLW*//kk \\,,8xSJ'UƲSL<<^^""L((4x=ݵ&QQ4&::TT>>rrqqmm=ĩțYCDNKK'tu8..:kko=2tt\z33?=MM<qwEE Ǚtabl``++vvg55 H*Ç#JHŋ3jȱǏ CIɓ(+*\ɲe0cʜI͛8s鲧ϗ; JѣH\2ӧPJJ&ӫ jʵׯ25ٳhRvڷpʝXx݋-LLl1 ≯_\ KjhA C*"U c \U&m1͌P ^<ɻCL &Mts?o^$) /duU=:^ ' $5 MdrCv6 bƃ D޶$`Cv`v(#s#FTmX(H+HcQ1㑶э >uA䖢)`ݘd7h>h-)iy]ۜh0'V1x'`h^^%^rdVrEʔx2TwRPjj֪?bZ>GrZ%![~EJ**vV.kBGަWkhA&% !GF Qo'Ӿ2H!} ^A %w,FtBC$0'{#5C#@q,sG rC#$AH'=Q>3}G8+mL7P#0d#p6g3GPbxwClel:AAC\pxxB80 CC09嘇 訯+N٩nߍy6l, o| ~7G/Wogw/o觯/o HL:'H Z̠7z GH(L 0 gH8̡wb@"HL q|{H&ZXTMQY DE}_׸-KcH,pG+ޑyHH$1 I "74" 5BZ2L$HBI&rDD3⧒$d&͈Q&dِW6*gJ1Ma0ZʰĴpK:|H''K`.!L&ȊkIlfVv0$GVs,7I9^49rm읍tg;No3yȤy0{:9PshEKYPb3CŇv/ iG5:QZhHg~$'4XOѤCnS-TU#, SNOc,N+=zO$l,=6T,<{O>OH$miˏ֑4hl+ڌ&i֔ UdpyQk@[&.(@@DH7ս!zғví-? ۍ"U".` }EVdT)Mʌl[PD0 .Pvh8^TTmK'`[-viQLSǭ(Ggbv0%z4gGaZ7,ֱ5-#1 cC>VI3W2b6%ag78]HnLJw<.|c>8.6o,/892j#2hD~U}JV+9*q-g9{nq)R7@ҥu peyͯimds)uͼQۤ-T}mUM ژ*YhV&r{y޻۞6jǞkzp1ɂ4xpXQ_tS8=K#'yX݅U+79aOb;֐M/qmk!@*}޺kN2ݶOd\RcD7iIkvw9wo˯#j]gˢ~2Lׄ4s c봖g#Ȑ1ofօ'Z8t?qKmWsjQ,1tXRvmuֆ0xVo؂(Q}0Sl(o8Gwx {*sEG|Ce_%pzr|b7ikӊ'3'WcHNu|wtǴ2D]:e`Ҍ!78q(:=j(W@3ǎVXXhx;L"hΖ]̖$m"jU_6؆bfbVrDafl>0X ifyI0hIh/I3C(\=gJ]x/ l5A]Ey(uf'IHM.FHYmZ-hD䎘bxhply9ny`w!eXwWGphG/)W|8܇gn`YVxYoI8< ާHlgfȒ'ț3v X(I^OٜɜIgy)Hhȝi-  ɋbi9HuHf9KqsYg)}íYcUPikwyښUA)Hiz]7dw h~$I cw~wcg1iowY}{iV98lJjm@zKwb{nkU:y6ѥ?jjlڤ`y#ӦpZW ♂:zJY9YX z)%z_ʉd)hyJy|Jz^j vjZ*J1*w<ע]کX9yIHeѬy=:fjw{:lȖjxu:uY:}JzXdggX}ᱯyDz*ѧ~;~~Ȥj Qtuǖ(yIRٓAKDPDɲ{ѱKS;I6KK'l)[H2hz7`ɴEس$B+EWTK5;f{h:t+KA:W]Fۖx=NZxDa};HX KH`;ڲq귃 *)^Ħ;z]JzF0[ vZu -ۯX˚cG'DǯI *~Էw 旵rꪮ[m'{{6w[lʨh8ĪE5먷럛 j [yK: z9#ulY |w#j7y TV+E+2<4, T5:n%GOQB@>ELM\VlA|\H1 !,@22tHߜtHttHtԏHtHttߜHHttHHHHHHHttHHtHHHtHttHH߿j$ttHHtBCMHHtHWWhߛc!HA$t0HHtttHߜtHHH2ttHtt8ttt:Hߜ|||'(2xe!1ggg;N~*8tl$ttHvwztHH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`Êٳhɪ]6(ZYz]Qݻx_xaϙV؛ჱY{W LBhLaсʒe LaЀv^9r]r1M,j1Ԑ 'k ̏_497СJL YrKG{ P}O~kO?,gV ~`& 6F(VhfEb 9`(,0(4h8<`B$hH&L6d?I&Xf\2QYe]ih`F$'Zti|f'w*蠄h{YXA@@^h"dZ訤ZGȨf@b *JڐvjF5X|!ǯ  AZRZm {QmchЊfq l".*@++)D;Q?X Qfo@m ,0\6 ؞+*{k! @jBOG |-nls*ܳJ ^ ]42-Ӵ9!W1~,tĠ9[`;x@0U2z &HX` uHă<ICP! KhBR D?LGHC(,ؿn"(2->E^^ Ҿ L"F:򑐌$'IJZ̤&7ILh}+d(D8PKdb 76>Ga%R%}R҆;DeZYGUQu*ci*jpt HBXX&贸@o4% vv4cNwr&7K2mǀf (ω\:7>ӎ% Y9Qnq3jŝ3%E 24<%eR9i|jJtZieе,]<ԏLix< e q.U{D0, gBjvDP pmkJO䰅VU \եFv}Et HF\` O+%ڴFLc@R ̵]Tڦ@^ۛ[I6s㭾U0!Pl 8A[}V* vUV*~]fnq Qzƀ鬽QmT;wVpVUB_wUl/V2U_ ][y7,Rȸku+؆j~{jE\[XR6cZx9jT9 g`K5brTw[L(\bgQw.lW巙Y]nt 8ImY2Tl8#/WPˀ*r3@2Y^4@kg}82L4Ø.v!Kрlկ&XFƯ{˝^WZ]=MЯm.VZul$K]|j+}2ypv2@<骜]m%b^am[_o̴y-6~0BZp}%.p;)(G5Y.Mf|s̡rSd'BU񑪼=uJrҁڣc0Ӗ|cb w<=2[<9q}O_: j󒯔C:Խ.h਌vJm>{F~b3V}q6\оNV6!D&6I^el EZz¯Sիlֻޢ՜)/yyg~W+G(?YN Horâ>Tƌ%յoZ}ToS>\*9mjZt5wjW}NV>+_bw_wZ0E],|']6hg_7R`&3;(};HE0)^n4`b_Vhev2)_|i`/c$c2BHjۖ,8Taad[e$Z:!f$Ffpv\ 5cCNvelgb[c^ZVhcOe;ba&Y|c8U#6=5^HYMH6DYddWfYRsi84vfHXfk[djtb3vczv:|+DdyӉ76GvX`f"chirh56jj\}cgjɈv^a⌤0ј5x39(e{FiHj6+6wCXd奄f9JXtj3)k5(]Vk;k(}$bk;ϖTsmXcciŏg:)6c8WYS{v;Ru~>vEEg{y71TH7g喓w3qxC#aU5InYǔ%v2eڅkz\i^-`D1 Wlٖnpr9IhEbR| ~*fy]1R v@LB<QqH ,3lM,OQ,7|U|SZ0"w:Zy %MսT5ilchUvW+PQ.ATkh-yb |[j\y(,-ȯ~lVW\2rR~h<1]sfF+;}g?k;k\ 35E(ʌɋ2 ց4:hcճ8;_xE W8I˱K`-8`8R Ҍl4lkcpsav\Jix! l۠o;P#=&SvK^ϛZ{yǴ%e;8p#d]ˉ+8А Ӓ{!jJ{eO0Aʵaʞj7xlոbO]Ҽ%Ƌ^ 8H|ْ>d+XNj9"Iƾ-'[7\9ㇿ)*ԴĘXuG== ƞVmuA̦UzsڦY*q=]=KIҚ܂܄ͭ ݇IJ܉=Qܤqܭ g᝷͢卲=]/1NmLM2s즞]=6]-&jݎΩ9~[20е/-~~]n>l,^9V6! Ъp ]8~k {ㄘߔ߃5 @*&{#6F=HB> 0ۨ挣H׼{Y>VR:׋~%;7kCو;I̚mݥj=? K}ޝ莬ltY~阞^vIސԒŸ͎ץ.^z١óϭNNyd꫓LS5)~>Ims ^, I^a^^_~1S~F4Z뵄 JP1X7*K,Ckޮl !#o%')+-_/1357O9;?=O?/ACEGIKM?OQS5gz\Q%˞n_s}_? :'[\r~otvg>V`vO mȠ_ikmb (Aّܭب?rrY_npnUo__O?ӏ/?ߟ_쩏ڻުo@@ (xB 8D"F=~RH%)@RJLSL]Ҵ1gΎ-l0B5E&K*o*UTOeݸS΃?V +Ue͊lYmۮUŁ jAUs+_v 3B ~4mSMYde+m@xC.`|Ua ָ팏'DXvE]zLUOǞ}u^8  `5OTwpw[Yr/@,H,>@!\h8O"L@o%GDqA2lí2&z8 6í81E%*ѩ%4kE,˸HHH,w .AdP/L>Ԕ J;j2%)s=4lI EԤ?eQ #uҍ4SMKTRJ7SPG%NK UUWTVUYuuVAc5;kՕO6Xa%XcE6YeeYg6ZihO\VD^]r[p[rG\uC3w]u7^ڕ;xŗIB7)~x&z_&i`Zv,~l˨,m+"S%{',Vj咩xBZȬ8jߚd| l JJ'̱+l L/\+@i>Nx_Jϔ< Ɉ!]|s6c/@27ٳ96hi2X0C<>D"#$*hH2NKrV^Ť8xS8YAB2<(t8õIч^lq9GFc#q1QX$ oK߾A܋5!z裌}l=tڜZ ΌL]ȗ`G=*$sFHAS4q9`=h!OEwD%2M)MU|b{u)fQ"Yc$̨D4qUkDb݈*8Qs$UxGwv?!$>糿!-B 'T~Q{6qԔJ^t~.! LF҅bkZT94O||P=fE 4`jhʦUHTʧNZݪհkUkYt֦Zok\:Wծw=SVHMk_QTV:jQ {xe~+JQ/caʀH fVfs\P0n;qNr7\7).om3HG~PAjC<bsL*t&fBY;iȩ_X(CZa(EoRN=Њ1-#ThRf۽;<H@ܤ K$}ļ g ƽ:rgCYОEt%LfZӟ<鶄f&8mIT,Y]MU3Rֳ~Txk\몲`]2^)Y']Q˦ #lhDñu j k9n9ea\v:]aL❢va^KtזwY@_0.{m zo 9ozr7GնlC'rۦ3\viHA 0k^7++kn0O5 Fr(N iJf4VW>X|Y>Zd[>\\\H6^T'U bD4Ae f,sJ8!+ yB .\FR%, XR.S:Y0p0tDE;B:';Bˋ1v3;$#tC";!'DŽK552 09{C$3:=:T%*Gh r"4kOMI3ŠL JO4L:F*BzYJKjJa|I@JG"#˲4˳DKӓeJGiKc{KXJĊ KRKIKKF`D)^;LDɶHƍ̟ƒȉg촣 z3c( IJY[̟҄ƫiC }s~k.Xoԍ덁 #!ͽ<pY&ܛ;9fґLi&ʜ<cA${5Cm4Ѕ)#Nqj͍ ;Y2#O"is ߰ k|zӋO(ż%33|&IL@>:DC7Ͱ2 >mI@Ҟ=1"ԖE)0/2,1*4-5-,6,d58 7},: -954E,F5 C}DuI=5)C/O!I :d|L aUJ7HMr2\ATtJVH)QUkdlR'E;Hs$lzZQT)T8wi[]8[P[L[[QRS[x4EM[}5ǝ%6}\Ku6%Վ4ϭ4еͥ5-7ӝ ҝ J:G̑]_eM՘N 5uyՠXyM=^R]KU}[]U]-=S:n%k֛De}!tZ r$sĽYҍjʌ#m8 GmN_ބ^]k^5 z&Q=S`VO`(-[Dϛ{B`]^`' < 2dP>4YⱾ#u:#nXU.`dK31DH۞+`X *,b؆zؖ5eS'V)63f4/#3Y >YA&3B`9a6Y(6:橱=xZ@3Z6IRZIOCQ3PTH ZIֿFeYa]^n{dlb&rކ ͊fԘf˪ӸffQgHw;\^]gtc{gx.g0gfg 9 ճ*8xg-Sh,.\tηÉѵh# E~ (U%-揖;R0{%030K3[9G*iDg$A -<UXFUjvihS20b6aؕhZhA=>PCYN*.f} >OV PRQ5kCkRk,fťv]^}zJ~?Ȏ6?ʎ쟶Pb\{l,e3Rs=R d 7q)ܕ'4.F@p5 n>qir泘]]~fSVTu7jzFzLWǩ͓#i2˸XI]n1_= &Wt Y& .ft= &jS{`Ǚ&y@gt١>c %^cN-#'۱]l}2} Hf݇X&q'YT_T{{k2+d0Y_qɫO]{k^$q1*d8fDTX`’A,`•j|0R6$P'РB-j(Ҥ@0m)SJRj*֬ZJju ^KQfײm*\]ҭknйx/Q~Š/Nج`4F~lḎ/suТG.ҪI^5ŧmpۺw6<[n~ /n8ʗ3o9ҧSn:ڏ > *`P(o<׳o=ӯo>)߿w^ yTA * : J8!Zx!j!z(AD(%.7pQ-"18#5x#m9#=#A 9AiIDztQJ9%UZy%Yj%]z%a9&eB i$wmEID0'uy'y'}' :(z(s1R!,0122xAx囒׿tx_ CHxx$KHt".U1/]BCMl!('C!C'H D-JaB>J3 7_ C(>M@*\ȰÇ#JHŋ3j,x` CIɓ(˗0cL9˙8sdM{ Jhϟ@*]ʴiFIJJ)ԨUjǠ\Ê4WhӪUxٵpmܻx f޿72W-YJ勑b̹sEɞC~wӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)di\lp)tix|m 蠄j衈&袌6裐F*餔Vj饘fv駠*ꨤ"i6z* Dj뮯Ίjk죾 l⚬<.,P~B:m kR. /,ۛ2P ЗG~t{p: qZGh0X<ݒq<"oz㏷ޫ `> 2SՉ0z?̿{pq{G/ :{ /Ar&\@0@T:-@ "~2`6pl̠ 5@NEZl`60 A 1 @ HD9!,1G22xAtHx喖ߜHttH tt CHt_xtxH޿HtߜHt1CKt F$('C.HtHHHHHtHHt$K/]$HxKFS3lUHzt(-H $O)'C58_#az_#3 C74H*\ȰÇ#JHŋ3T PǏ CIIO\ɲ˗+SœI͛'eɳϞ:WIQAUzӧ^$@U25I@]BK6Ta<֭$ӆ[ѳ%.X/Ŵ:T@]QXu0Ppl䁍%aU͎)sϯ 0< Ozy bT#X;:WV[JCG^83N^g/zw+G>>wxue^yi`_A`Rh:h$ԑFQ5WyX "*$~X3X($IB$ ;!0C=~Ș LNވC R-ŗh嗚pHoigsT|}Z⟂jB 裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,`' + G,Wlgwq,$l$OpA(0,4l8笳LDmH'}tJ t,7-TWm5L[4Ww`-@Uo͵h1Mg-t{v App2~u7xwx 8(.4QxȌǬx珇.:ؑ9!pPr\B#爏nSnsBn^7,"0Po{ͼm_8ጋ7˞˼=ͼp{t%  +yD0}I6.u;7( E@\ ԕ u؀7pl  c{CX2c  &n4. Z'A ! xYXk6ΉE]p28*-HB1iCAPF񐎌$uIZ0$&7I}쓠 (GIR !, 22x C_x$K$U1㛒AHxBCM1CK F:!zt. 4!C곴51CM#Clȩ_3718KD(DPB>D8 (CG4@*Wrt 'h@)l0 8`EL@ `ZU@.lrݺ #"Jm[jÑp y P0B -X, T@@ ,x@A`@!, 1111111111111100,,,,,,,,,,-+,**(('''(')('5X%+*$ }a= r*O4>5;5:5:5:5:69:6J-] ceeeeee"c"(`&0[-:O0=E.:;!88888887878652.+ '&#$"#"# J{ 045559HOOPOLIIIJLOPQRSTTTTTTTTW`h n s w y y { | |} } ~ ~ ~ ~ ~ ~~~~~~~-LU[hXݫOڵLͻGù8)""!)DGGGHQm˾λԮ֤ߡH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\IP˗0l$&M^Xɳϟ@' 94ѣH*]ʴӧPJ5&̎nBׯ`86ٳhӪ]˶۷p%Z-1Mqݻ.G| L0ߗ `-⋺juil0fHR̹BA{MTS#O cMͮsN+c N6Aď(ˑU%No׫kν;{g bsEV6"O>,婣@RfVj饘*(CfD*ijZrY&B\RhF*E~6餳+T¹A6*FjD6SojP {Qf;@Y*+ nJ[Yk-BC-Xg~轋oe}{9< {:g zqAo\fri.A! &D%\(nx<@-DmH'}PG-J#W-@16sD5<[Flp-E[6Z5_ vбghL'n7y.yqi=Fws?5y\nk ~:cinMC'j7QfϺwzn|sm{+ЧKOzg7cl>vcHŹIDO=߈4ֆ(6 R*I>s:KpkgI0DZ 96]eIBaFHhB0 )bŤB/,@<s,آ3YE|3kAʃgLnU05Qb D,5* ^ ?% Bn`93*[l#A#1n<<4 @.x|ɿ!ayH%#yI4k|#FG>RP'O5E,a*qE.\jҒ1K_NRS0W?bQ3t` LBF2F mR =uiI"JR⼛Xv,<(2MES#gw9QmҢ'/:f( G1$8Ж“.[4͘D61nŹypw|[dqZ::wxG;)^wpo. +ZSqm#ew^~}sy(C}[w2rB[#6Tb"65tJ=nvMnihpH RBtĤ+TCnxg1srcמGY5` |Xͷ{E =Y``}_^Zw\Hxe|'p\%jk'z U$'V, &uR!R@8R٥vv'CW˶r8PO mq\z/flalcgRQx^S UXvv7j"UslCnȄawwRTMVi7De0y(E'5Nq "h(KdF^4!Q&M%dh)ńVXVȉ hQĊXȋ^s|Sugg,Q-DMtM܄+gDK阌Tጙ2V"OHըH QĎILjԈQOiS"ErX8 D9FQ  y8 y!y8QTK99IRlc(i:P( y#YGyQ/iQynAA=w}ёa,ILp2iُ/ hU#YM%iԕ|bidV$⨔ f5I*jٔKxQ9Zi)W>i@1QlF!R'؃¢I9(?Y-YqfQw 2VrY9i( >1ؙӱѝCE( )7 4"Ii<>SWcU524^ȓ9:a]G` 7:Iz vM(.BJ1S@vUס] ڇq8%jS: ` mAǢvŰuo~(=?ܡB #pt M:  @)R*zT)0:ـ.$C~7Gi:` d$ F Ơ1 sz%bP Uz| :8J˨  Ф 5%.Ze@ِ{ک6چKTlܩ1рtP1 İ P PR jb`ڢI( #U<&JwE*ЀjZ֚bfzzEʥ|xN(I@HFHȱXSйfZfIzBD *vlBUpz K>7j֓^D"81XaEi&ʭY;Ѱl %]+'SG ˳_:`:AXNH다Դ ;8hS#Y; ,XaTk-J~,VZѳ vxK׈iKRIۍRy&YX$(5*+R?rȠ蠧VpuQ"Oٖ)')ګX˖{k,]͛+A;;4U $;*˻KIFiKܐs{Gz6IE)3婿B QYhY[°|2lXHN龿: !̿vH|܎t'K Y̾$ F;E\"cI軔1%D[)HI dsƆ1jl@k)os;u w2;l{[ܥ ɴ!\D0z[,KK˥!̈́H\Ę켱 +ȜqH?DLlČ_",<ٜA`8\3#;L̑ x }ܣ+Ŋv3m&]TլTx[m^3ceё0oЎK=.L=W t]\]M/u dmJ0A=A5Dn h]=ڦS)} q3:ۑ a2-ӦmΡA--Ӑ.1x%2ܧȥڕ۬ ԮWMp0_ݕؑזAt-HM(1=H<~}})}L 3fYۉU1=M">JDq"aԍp{ǑɣYM'tӢlޑ]+W-"ןH-\9ە%:K-N*Nx I0vMב?]L%'. ⹭\3Mx}9~!2'q3J+(!ȿYG|#Q=S=؈NV঄ޭ]v101NGДߟ-TK8)آ!ڽا"2>A _ӈf#aw|!1Q9M|<>]>!$Nؾ=MN}x -^áNտ `^,:o>2a_F(TÞ!P+"'oLӞX`EޣN*Z ;/7.ӫn ߮0?CW{yoL=&boJa^SI#rܮEb։?? FcR3>tr1>D=F_cN׾?- '!/hÚȒUYwL+#﷞^6j>x~)!e?~ZAӽ#9o/DMi@ DXPBEȎ-VtQ2RdH%I!D-#0I5męӤ%yTОt`RH*m`ԧU^jS\r]֯G͞Evmmێ$V\uޅw11yI˙Hw>Sd ʰC](c$CӒT uGXv3fo߇ F̕?>֬UFՊ*Uڻb+քGG [x;W_>}H< %HCJȶ aȰYT˳zABoz`뇸ëBL4Ah]} ;?9 |A@&S{DaQ7!͆lL< m. VH"^PZхPS4r6F6[lcFmPaI w9*8d|! rt|2 22e P0Aq&H*\b(4<,~)LzqK_3>2`[*YC*GaA=&E%ӊx> y2EI]5 ȟ(P. mV n%L`L`JhW.:$rM0XV̖DO=sc~)MDFsB!F%$%͉FO05(г8(0%-DŽдGA!T~: -j5啎JꈓVS߃B:UoB2%lr5z)f#E(hMש-.UiSIwU ŨE,2&Vz8ȆN]EtH:rĜҽgSIu9շJ𰓣4tXYJI-]|JǢѱ89qv;" Y{A2xsƦ,|&jmXZBut*H{èQhM%*.$vc]tδLa$x;_UVq:h}nMa Ko0aX3$~7Ѧ.8,yk7-IݼViZfwlSjBX]4잗5 c;gb#cMGCVK) )`ScΙ7Ek5\ǰU񈰢#M!vÝ5Z,rc5qKeHY$$MsLڂsRUGţUmZAܷ5ChSx9Zs]&}2.Mg=3{S9BRsX5uWNM%cXܱ63[$Sp5{n# Rw&ksZD>öUnwW E܅fHMߥTteyzڳ{:Gv)W8Rj`[ݦl*Sr&MJEqnxt{gݎ?.d Ԯvzx\jl'u6z;}JCү~LGRՇ=aownC+nݖjFaj^-mA[E}ɇy(Tͅ=]ŧOu.etɼwv֗;Soӿ?@`|S?S0ӏZk4+{1)7P+C1h@4> ,/ҮNDc:-3ĻaD SAP4A dz(FFe(OLPVB)E]B:/,XB/<@E\\@E'E`l[(9L/08q;iLkDl|6hAUz64_ tHHo&$iGH%y@z<@sE?Ի;ʲHJ,l¦4GQKJ1|Ja.H9#K$ڳ8jFh9BBɑ_s>IB1 I@Yɠ02Ks 2 H&=+̧E:L$xȮ ]d,; -Z6?[j94;Bl;'d-KHL<&LwsL[͌P,C,LϜa%>ȱlDĉc 9< ,ˏuM͛]͝0K\lKYθ'ƜL}LԼ 8 τ=FT5 3@MyIO3A hTML,ϾKXA;PEP8Q,-  YPR!QYkM,l4c+\ђuO<7u^ELL|L l]`Uu iEhQZ/Nvf\RNH6r}0^Нp%QNZ%_Lh୵Z- -[b-k((6dM #r #Q]6vq:U1^4 L!Uc *r8>[eh[b1ڕdH,sLO}4aVE_ǨfVDNd[dkd zC셮,XOv P(Nn܋O6d߭dȈm~5EUf>~Gl~U 2_&^. fVf+~ShYhpg2fܒ?`KfLn\Vސg$] p5"SQ5圠WQe R'66 \?f&N|cŨE{~愛e'i+e<.dd1X6狀tu~њ J圾]R۞NY˯eyNBj^VjJJCѻJN-jLHc.dDjnfBi &kvKhI*וô~4j)gF^bGIaX ՎWN4@\Je+e۷^EV4J̦Ef6H l\Yh*NPհvTJv%;}ܕ^Bmz[9nl. E@!o|YŦ%t+,Jq{DGR>=G|I_Qgq1SFwӍH.&4R/`|U"jf9gsy'^xy0"XB]6Wb{ D:2:x ԕ&%LmEfבk 6*N3 MOd蟽F#Q\{Vz.ǧ:C6 4ڙEm|)~Dv*gEv(OUj]nfS"%bH҇je*oBTm:L+1,[pc "))^-Gn+T{nʜ)qJb-h=7J-)8ڴ׭ޤM!G4Y ZGUaWqbgqu60_#ZrC9{tFeax'JB&?׭S-o !Acָ5 }$ESvf{8g:ϒl꭯[%{-:"%ݔۍ%wzH` A8iՎI5B:N( DE.SR>%gc;@ Br{+N3Ixq $_ Vd${MS 92OCdKMNS)gMST9O{:>5jLe.T/7˖[oGH Mf!.F6YD蔌F4^Q@E5PTZ]R~NK׆4&B,T&6DEP*YsMg\-}d1G2P8#*3C"ʫe)#sRPsxqIBĜ<9Π|V lCK‚hFelM#T3.t!\`6r g 2UkK K{QXL&82Sn4[*PfoD|Ӯޭ~נP%r`ҥMk].p)XN&ݕdծͬ4<˼g>G*|"_;)~jdB$\)-MB4Nk[g-ɝZCp[ì OZEUB)Q5!kȄ"k'=4%7e7x{7d+Yvk8S,6 @*#a*! l0ZDKy]Yy$ xn.#ݩo:p6GzumQwDBVo7=4Zߔ9gҗ6kS~.t>O/|[uؑ7 ON 3wM93/V]ߙ '=AI&_QXI\[搗J]#A7^NWdYOe})UeHR5uHzqI$C^T޴%bE1$}cO[eW&J&ꬥeV%K T/uH&SFEFeDNSI_ V֣=A8.?YYfU&`f@ 62#aաce٠Rnoe*6YP]k*"gEx$c ]FLr %pg'59bgf_s(RR]i2_7:7]&bz"@'uJp|Vg,ԩYeu(Lg4g?]~FXz&z]+2ʀ^sfg`\E=(4a>ړleXf jMPFQ`B։ىNFh3hؘbf^thF^`E:hbԴթ!lgV&yrYRoOtrYv%C') G-]EQҘ:Ԧf->eIj4joD?朮|%DdG(Y)`j!<؇}Yr"PxNv*hZހ]S(EƜ !Yx"فlSivMkaeڙuad=kB<%FBDTktt*TH+bj XME.je(]uډ.!ŠV{>d@#8ŶM$CigyZPeޣNfn|bwhP٫jX*DZ}6RnE0 m[]25(U6m*Ǯ$V+a~m-قFR.APGH)̭@a,bu+ɋߪy&[׻zSMzА%+bv.cty@nAb(M͟>Ҋ:*"`gZ*nGTlBIz }ƭP<-_ \Ft ZHNĕ/G.K,IA I>wA6Uo莅/"oꄖo\+fJ!(*3,g*JLU(&/ o q0UH0붬I.X 1K /iJM7MB/kOsV릵&O`6aaV5FGrEC82-]j2Y1Qs5\+[`m.)iQ1_;cr+b6nnvbov}tVʂPd ^&FBa gqzph'Di; @ZC,Dkgqrmo{7|bc fqGPRPi$Df?b xsxtvbO/87nGw7)2`v|w8|q6dKwCsW]Gj#BxE[;Ձ7]*-œeЩl8{64CGO9Ox#Qx/3(IK.8\AܴSϷosw 9AQH^< 9t 猋i(S*"3ʾN9ҝ iخiOys&6zuljE+v?dӧ`{mͳurLJ3>=%.TRnҘJ;#FLA UQs2.(TU*G@VK80@1!%,qA?N`obϦ-ܴĎVkUb 92b-\\*Cn@y%{w*SCUuUAum6'U'A;M&<6UYşP{?#7_7F\bD-bq"%X?-mHn8Fc-裓_yn:' oKNL|hfܘ4Lخ ǦUsD*fee[S6fm3m o/v r)W͇ .s61/H3j-S㔁#Yvk#aԹ]E7(trG~~v*e/2GU fۖf(m4U҅ :ʝjDC*x>ğHRaO#zHQI$y9™FB~3aP(H'TRp\T8cr >(}2mIưխ-K|Rmq4|@;5' FR6M #47!3"XJqq3A!9#` gZ.L-k>9vbf*"nbDcs(J1$|sQA0HJDduI!-eT Qh.?27#@T̼$zHuE 2V;}wlt;2'S5<5FpVKJH3-ʌ-+hϺR0OUYI)Ů}pxMfd' 9@Z gLH|^)]d^;ްQ0<=ɔ)k!9"5rIv-U ZK&R;U5IH] ƻT  TN!OMӠ'd[rӎ5GVE!!VUbkღZPvګ%IEᴂDXIÎX5#^t"T1ԍGzj*iOVԮVX#h=l3GhBm\_oFsAP-ň YAgqճQۍ c]V͈\g^uT5b(vؓ"prթEף͇ r"}JJ"xDꭚi%hiAS;Aܭi~uRQ{Bm`"Tכh(I Vt" >'eC0 O&IUR8Y!P&O2$3K2T %Ԣ8'.nQۅ83A/vgf2:Í" 8'=6hc,!7$$H$jb [_Vrx-LJ92R,gdWePXb&d3M&iR3}`err6qAYNmΎ\^%Ot/jKEj"-W9zBN1;{nc M$v1K;V.N[HP2/+)W8q׵Ka !vnW͛?I_]o6,#X'p&!щ,؇FaxNrMQ-qe'wٛry̓n,׈cn3i@'Ⱦ+ЀyW n))L81o}Zy淭qЋ=.JR|vG_4dx5Bߞw~x&\%F߅7uUQ rzYUݼW4?=s>z]v;gǽ_[= w7UQw#A-#xc6ZO`,іÌΏUӰOnH<.>O/Afc!tm,&d xIK,0P@LP&P*0ʆ뾏.*J ;'onxw 9ʴ**Pj`b-1 =0)sQ$10RP nPhp3BUon"x`nD#~Ѓ0F:}2@=1Ьl bORx!L&nd:b"n wqq.QO mЭqig`GG %AH/Ȑ `11# =0QЬ|Lb Q!?QqP"!p9XjBR6:(G珴@@)O 3QX,%2*qW 1a&%Q]"p+#**(W+)p}1R}L+/%+*1-,!rwj&s!t̕0R3插/-0YVp <"61{b,,21,68IB39*)ZF2[#R.S9e/rUS: s$~;] ޓ}LsPs5Q?)=Oh=M=s>0i4\9oWpp,BۘrHY55]uFa56!hVV*W +n[EoTT[N Pȕ %DR4VPDWEPUO[w5(*-h UKu^ITpuӀ\'@P_S)UJ?]Ya6/!UXuc-`Ub;^JddYdee/ue^^cQovfUg}$`A6 ,]h+UhS/a.SSeIxl`նmk$Z}Sv[#6RnvfUnZL6G6$vhZvpm5pqkp=pho!n֧6sBr3rKlSlsq=wF77:7u H)PR?bano]7){?@Ew-WSQ7xGwukuW'WH pywR{#zkGxs7|MBdLkMot3{7ܸW49nWL*N w7GwU 4'XzWws#.NnmK*A6)\.V "Xp0>8G/'*؂x*EqN1!8G)>8ǜU.f8gu"}"x94j 7fvPOaϸ C8ckSlϴ0ًbJ؏9=yKSibMK.Y}xY8aXew9+ 8Z#Yy`4yz9-sc0Cqu)4!$bYUaW W3 71b9iJG(؊Iy1ؒu5f(1Z%XC[ٜ:ѫLtD*1|~C_p)qz)ZJڌ$ Vz9/T#Vq6`U_3,8֪1\.dX1⑭8πחJ(*!Q5yyZcژGA "SìxUٟXY,`v\Օ[i\1oAB5zlGڥzOxuگ8\)~v SƦ={9D/:>ST_qVjczgct'~}`Pψ:?eP b))jmo[蹐!${Gbj)[:_'۹6UUg !и"z$g{R -zMKC@/9EQ /SۍyW3i#5 fZȩ_ZC[ECDže|FS)ؙkP<W%\Ȼ'[]*S8|=ð1a[8[s$u~]1Kw麺Iܐ9B`p ,9 +\3'穽?C^F^FDn8,^Y~JC+"RsWs[ +C ~ z,+޾bAž'O!ڭ=i`9);ݝܽt,qTcg6{#}X_'\VnBGg!Gc콼[]Ci?ŝ!өR6 8x… :|Pĉ@QJy,ċ+qD#AL$#lijuip!RY*Y'Ʉ4s@P-O 5VKnmJOGT(|U&şv̙тg\7/FU 8p\e>8;~ 9ȶY|ɜ;{9'yejx@Z*ߦVz_EU*-;^.Cb٤f@oq"*`ȢoEu-DkEZ}GY]>Z Vk׾^*PBGJd]+s^[R7SGQa+uttN!rEKzez'fIhxB"pS.7}lL ސRx]D/ߩVi=Db-Y./_ax`C$nk ƷYS p ]CGNzS=J!', 20-'CYɷLH 0%/0SpaP (/@(Ŭ1p!bR3.0J=6$l<>DCa澂:j21ቖDFC4Qc,Y"Ûmn~R"gLώZˢgLP*b 82t>XTnaFa!ɋJ.8M!̱ǐbit)>`.h\5]wy\D"JYK9ѭ22\;EE+N";J/~ ElɚqD;U?#LWŽSWMiОtMfQ$bT|Nq41휩MDEUj).<VȇDQC z"7C#RNsdM)>6J{&4zN= ) ƨCJ 2ѥt(ESt1B {9)DBAl`Chp7E jSŊW~V=h8.t!ޛ+wս6X!:H6n"[u97pG`DfZSC;bIݮt'ٻL0;TVӑ%)i#N!P=ia5J~CNjM˔ju:q`"n^[%w_\P ub]`W}b[\b6Hjo%e7ha]= WR@ϳ~A%Rrڒ%X ^Utqr){U1X7E"`x2p=H<爁wc8 NrSvx> zЊ14hFێ6I(wC*ӛ{Lɉp* "W~%m˾#͙ʯϥ/ Üpfu4o{jT.&wH,r/7^3OBy,?:9 \َg$.H\ 1CU1Aqku! C"$g߲ vuڸj/rwқt% WPOw=V' q2yH;V4~_?_PQu= Xg[JI~oUcGvC4-d#qE{Bqq|5=hwkH|zC%|mW|wXc<}ׂ&sh&8Uw8H %zM'{BF.rk~ Az qpueb;qsvB C7%/$y!6mHoFTr{:ć"jBuF6uK07 _KF.d 8qF)bEæƦOat|aw ԊLrwI8x}8t~ԃ]r(s"uzV#2zEH"W2sI㉎GX!Fq,g|t, ,_yf8SfyČ(lXoB8#R 81=' Q& 8eS-P2zOD5@(3JFz|RaٛCzĹ{g  Qj.Q‡(KBH )'}eh36~0On pjx!ZGd 2I9xؐ6ami21*P٘T1,y,J7"5sG}yziyr5iiE"KцHq#ed Hqau$ffLZ*!9(:Sdϊ9ף &x*Jw$6hMv:9/7cx:VX ٰ\&k$DKJ4cKt I1[}:({id@ZmS)H.{|,g+(Lګb {˒E+"[OQ֡RD&f yFESb0Dڒ4yL6p ;vU{{AZF${Y+͉ ڳ!~#nFS޵.6w}ΛE+Zf;BUoX*<;!^*Zl2+HHNz|+=hO.ck*}I{fJ; kY;]N.G*Zz0׫ckzD1ȫI:"qK#dFjˌӄ/;պ6$8;s(ۦ/*wcb+KRjKڤj)̹y+<+UBKmk뷿 1ff#fYĀ!x(}h)i:g~vXⷂx64nO4;3AP{pgs#Kɱ+s ǰHڤ3ѓ^ѷWh2ݟ_mO? Opݲok9ӯU}#Ś V b#Ə .dC%NXE53c! 8 8cF:UjÏK<9JT^jg“( (SR9,UàbfUQFm8a̔H[.ԣןV*PeO[eMD/%YBL-Qmmà*YyM;N\2սQk~g@&]iԔmc͚A "L](9r܆bjq*|Ɲ_|&)ĠG8 ^6VV4Uu嚍K!{Zі<:;T@[0"p+DpC;ТZ5*ST1v/cȼ8 O) :Šz* !1&BPAĢbP#!$„*Y.*&G̺$JהG<Si1zSqEo,EXx rv3M)s;;ϸB3}VTO$#0%셝rc~ɓ93D%2̕=M0COR`AwF"Ԡ Eā n$/?GG+3]8Fsk4NI7D3!Nuh1x")#jYqR|dG6:#"t T5P&TOY H \h.ʁ.I)T2z}Fӝ,tJ:rT+*FfNʫePS&;3הS)V.v"_$kY[^F UU:Z:ΗQâZYe~*Cd>tWδn',FjJMD;JnJm:NfWd:dgjBniZьv-CO†H,bl'je.<ùTWrK&Jz_T!U~õTÑeDqegϜiۛՅ7X}ϼ Qǰ/ `ty?D 9ԥ9\*=DŽ [Q}d,RȘ4i^b5w^jgBwƎ MZ%)>^WRL+S 18v;ຓ;+tͥ鐝4).Q/ u|;".*WOY:o]Jr UIet+(bwGKeniv 1pNj>sUP!R,Q_4ߐU;zD,ʡ$, .׻K6>{d'(s4,Y* >d4B %#L5-혷܋3K?hF=ÈR V!8c)[?33/Cvr?{ۈ=Ê < 672C+p3YʢRҸ=8">*+PBj%|[3#%B59*4"!TB0881h:Lj>郻=0$TZB=1""ڍXt;A,>.B dQ#zJQ 4\AQ C ̂l fl;A>ơI`@Dc {?C|B+|h삀 Ez,G]!`2'q,|CTE)Iȸ=$ >,o<.#0ܴԬ˟ʌLd:EYdLK MšMSBDM7T-<4ξB F<|\$* N!B|24NHIlLKB9 NHXpO *OhMb{-btIa'8 2D8Lj'OL[jѳs|L;/)fA $0 eEOC %@](ijQOt# LX9E&;L ҬL4RAT0&Y3%BŊl˙5T.-M<T .2ŨWKS*2jeySSz3`E"$?І BU$I:GGEUZjG,E-*T?VU)Oד(SFp2 BS:S\O|LT8R,dԛdMTZ$+II jk#l5-m=oL]MbAȯBWQR 3+Wֆ|$}D ԌC }y\ [UL.Ra$-9(umTXw}\ gKݵRnͱ4*YX ᱒Y*-A5>YWSرJL爈uWY)\ԑ]PM5QxZ\4nYRf Cef ܾ;X,D;[%YVVu5[#=@ vR\VJ0YSB öυ\Q N@WE&-݉iWT㱩bͩ m]SRabUNbUH2U^ V}.& ٨1=r3k<[c6V=7~6;l;d(c[=K1 %VE&WhsWY WXޥ8!e&ԈBTUf8FWFXFnT>JYA;]6JddNi<`j˚+10elj`@Lll?ES[6LKH_>05j܈ ɭlUkH~\ʸ=&g*! sRLHjfn)x}gEb p p p p pppFn`ƒ돘tb>?RoNr%n"U@VܴK>>(69qrM,n&fP|kF %bSGajqP i?3q 7;>s[APp^׋._H6Ck*PrdkPi赏1.튋H=rp :4]c\_ >sHAI?ΰtFSET+ GfH(Zktt\JkT5Ƞ u(2Ss;/&!n\ÿn{dfPvL^/_qbe CY.yq̕tOuvvn7g"t?Z} ?Mßrz`ߝI'k$wf?&gS8YOWŁ7Go3gxxqsamlY7uwy-TB u6m%wOf*wBO-k%ʰyg*1y,5%z{OoU_n@'ww 7 ~u EJPh| nT{ < }!|xq7 > +z_Pk|Ykq U}OGTt~c{ss[Oq 綍fg 6okl|y~Uˀ"Lp!ÆB|(FLĊ q#ǎ? )r$ɒ&O8qJS)s&MH9 M:}3ВEYs)SȶA:q?" jt+׮2ײfe)ٶ v.ݺv5IA( <2(QG .8⍍?6X0OnKN$9?~ XOoMq-ꥣOm-{6ڡ뵭0HɆyO |xQ?#/\p}M֗j\}{W Ks{GE6<]R>|!/OǟAr%e4Y}f]'DZ,Tu,B߃:DAq螇"D镴+"S\y4`1x~לs5R2raf1^~x#QiQW"I*rcƇ[ؑo:A&c~>ٜ9SAW}n~eE[H`"RS2&ty g݁n)%ɤTA*{%k`F(ץ_=娧'xhg *յjڷm Wۮ0 Bi[Ij;U'oG L/?ov C\ŅRQsD36sWn@c]ojv"ӵ I=Ya\IˁKvBmhEqxxu7x;nkG,gVv!1IPRzg';zwKv?P;;<חUKc/v=I}C֋>MŽc>xKo" o~ 73}*dlg>/DSHhid"D/p>S؞ky.J Ґ c-peN$ƙ~={ ]ن>2 8̡ wX&!kz':OjW`BV$ǿ')"Q5N* L?gdbQ.!M^UHDnxcEx n R,!* ' ,j^|S=tp BJ^X4ʧ)imdVEOJԂz$3N*J9 Lnrk'd3I6 Y"2 eK`6G>-q p)i'PRf(EL?=kkV,/&zЃ"圾J:YNxKɪ{21'H{s0wcBLd&4@1%g{TRc08r>O)Rv=ܬ8βQ< WW1=2fjW߭9["~{Jbp=,]HVn[VcXѭlmFȖU)\jb=-ʤǒUnfe#iM# "tbmWV)i;օ .j\.w7/yݹNӦLnd)]5׹^F` u:RfU-,8r+Y;2ӕ0_a2xI g NcEu7U ~~#_KK\IP&6=n9aTE~eܨ>l6\p458,h۟{\ycI NLc E(#LSNI\沱7])9 "̾e -c7#*s^p|1:^,a|?2>ri'cJ•]8\WR}B Jm%jz.v%3*btscŸ֭|,1|HS-RdSx-sϥ]"CdVͮf5vJ"CoU(,U]oY^HG+nJ$2_iBmk];E5N|[wk1(9!lB ^9E. oZImSujY.R^ʇQT(g7!wNa~`q\1~]`W:1ʦ_"=D%uԺCT+}{JZKV2ݵ<5 Q|b^6KHsi<:e>]ysloDk;svŜ|If'ݝyUo;AڽtXẏ^`5yN̚N0?u4YOG4?:9U=U蘷itݏ}¹ګ%٭ũ] &y% I 0 bG4Q ^ڠ}L(ܞvCIQ\YaՅ"J ZEB\ aU{0ጐ\_U<ڝIQ]*D"YqUya%.!y ͞<1R׺U𰟽[n!WU &L:R2#$Z$Җ׍)!'N>(K#bE5*2 Μ ,2--WW)~vj4 b 1V%"jX9VMM"RX"ډY'51b9:9.W/*E^ma==>6?6^#*@V6L^BCK>:B@Yd`d}uo!'~8HDI^"E:J˰Q٥Y8Z"n$N"N:>a abQTTT-N%UeF+v2reWZeP-Sx$ #^eΤ1Nyd!e\\Q1 P^_:ړOb#PPj"a%8Zn}R ՄLDqe^`_NO;2FQ#=`&1TPݵ&4$a&$#`&#[VR~kf&M_ 'EblBDffttTufIdbsYpp ( Rd&FzblmmJ<"h"֢'Z#VZ*ZVfzkc"kyky1+\ܮbRvv4SkAj*J Iԧh :,>kb]J(c+yĢ!_zȠEZ+Hln(*zw,lGlZl5(6ůZ1"Vm|Xj>~g $I |,2-~^m\M*,l.iO+9>nĸZƌ &dƢ*`'lB.!f--Vbr'햑RnhEԢXmK RQNbj-Gm{p~.ԧzB,]*k~xn(oŪ,Ft,H,,R(Kx}}bg'䞮Ҷ+'.үMΪ ;Hmޣf. ,j,2P`ޮ ^hckfzxn؂ӪpMpowtR;벬g,l#fS'o ۊ /VW)G"p0kG$"ˊj 'Kc-j.5- S-]NZ0_20!!Zή(9$%oho .a:ran,1/h%1Ȳ/P-+7n#m񪔯Cܲq^0sfVq4+*_3 f!p߲Ge[3L3T>sO"ra&j=s91:{2:lt!J370BS=C qp,;S&̐jF GKJvLtMMt3>4s"32.WO0f GK[LGJ>N:rD;`&\2R'R# S;S/(TOVF9VkWW"XXC?Ӟg CVfkȲuRI\-]tI@NQVf_[ \"aC6OFbC*_IP#Zg$ +yZOXg6-6v6`hv,\k_kv``7t?v0wҊVn,pjl3fEeqG$ 6+cKSEK7h \awK&,Gsc{w& jKKy-z uI0a||vi 'iuEDoC3u{{ C%7rIN8Ju4լ8kL{xa!8x*8oH_&0/P^ܪTO3 884)Jr~Ho.yGyL5TQ+k󋓋Y\@yBq_yK!e9lw4r#,x?o5[ +Ys:ƈu\K{z _zS[fߧ2º?ΚKWW[vyCkgѮWS]"%E9O2B{8& Tc #ɃGaC̲ܾjcj;t:G'w;/{f{aZS|WMⱼc(cPKڴW|k`;>{ ;kOb:~׾g&[:L>>SLc37?D?e~/mlP~aWPD%4xaB 6<(FC xcF9vdH#I4i2I)Ut2ῑhyS&NjDNAhQCmM(ѧK´ 6Z!vjXcUU8kي5 _UB& `0D+mY*+&vrdɓ)+\rf;CNuAOjtϜ-k55gκuܹy!Z;Rw"8aH,1׹w<%LJOtG3}:ziG,?ĺmAKH, 8ګlA^.M<Ei+C#HF[j˱G4jt1$E$8|I E\ji/¤l@trA,4դI\,=6l*!̳vԓ34lS#%scFjqJGc2( /-0>D̓HRMMOeKΎ=$5x䓿d 5URRaմHb9t:I դQݖ4Sncd5Ȇ$bexaRl/$l/=T{IVހ.܍ XV[7,rDq[tˆ-xf+֋/ 0LČw$1>hm bb\rwcCveuŽOp12稥%]Vx7Jyg- Z(ŀ:,L郘dnoN+p;|9d:0z{ոC#λ!1Vs!%pw ,TA<<۝}?y>vnz>m7#}!ڛ>O?_&EyM?0JLv#K#{ŽdS@>)#`dg7%mxv] IH YB0+c*h ׾|PRgXp%D'"OF\K /vfQcZ= !@t9BD)AHF7QDcX0+ }I\\76̉jXQT"í(qlGƍ4IO~2EwPt{&AJ:rҕ%4F~PҼh0U"$+gYL ҘTfI6leVש>Bn˲yb.,e8YN

w"*N̫ï ]Yp9t(7g*w^;oyE(W\>_t?ȩ^OЅWXLBSn Ε|'x<@.̏^;yGUa_yf_ jvKfO/Ǘu=o?Q^%|CL>U?@>߾?~wP#?/O  ( BٮЌ.<.mg[LB0,n_V.WpRTPcN¯k8@aO.I~h3.- n +  8|P pݐb F ݪ>DѐM  a0 YP" &k q +%/1,}l 30l)QTqEWJ1z:ѤCj qod>`x|Q)1ˆڌQݐUڜQ~1ڤ f񽰑ʴ޸т&*QYA)QQ5 71RQ!5 no"+ /U,#!+#."CRC2FrJ 'R%$cXܑ#&?!wR\ҫN#S'M&]f#C 2f)*)L(rz+l**(/(,O,,)r,R-c,2-גRD.i$N.1J.].*-22D000 '#˒1rӑ)+2 (h)ׯ)3?BFSK25;K5ψ5&;6cfSjo(OS7- 3N33379m5R8S:s2[7r:E77g-2:Ӝs`'S<ɉ<<=wR=3ӎ3As/>>g=1>i?Әӎs @m?K(@q@cA4T^&+T%/C+BOAD?DC4J3=SEgt SFsk`T>eTGwQC%9G Ϣ؄EQp M R@&`,v&Ab!t&` KiBKI'\AҬS9IS3H#pI%"A,%vF`!R`APuPbHT4GoV8t#"F`KQ"5R`A x@U UBTMK%Sq.-<<1AuPt4ŊչΔ&+ULcU f5 bV[ R{O!Rqt/+RYYOT3u,m1&\)Qp"XuW͵ KtUD_//25"SeUݮlWmuU d[Q%OG TR6UܵS)>"16c7XT7U.Z[VQa![ud eUQ`V@e<,b3p֥X^|6_!VKO&dWiLjRUXݲfS}ksV2Il_HQ_ Yp#0moVr/N)w-sps^Ds;-vBx@ tSWggs2u_WQshW'vq?HEWx0v?uvsqSy u7w;=%zzO{3z^wwxyW %yI{>M~4KWwt7w5U77ߗۑx~~cNxEy W؂IҀikT;1AvVKdA`1=8XxFXto!Agx"҆o " fRtx5bT=XtT8$8rŠB/*$8sݤ ޚs#7%\>Ȏ{hph#8x 7WVxWw?#? yXk ّy%YcosYw{ٗYm6La.!L7s[R["oזv,v5_1[t1|$Й\uiBaM^F`QIMRiM V!uG%F69w,4XVYBCM5b y6.*`W:#T#bd %r5$FgkÂ[ ˹q"~joulSl'mOB bWwիE73"VvA\!Δ8b'/B K#dz Wd=c'1yb:`o¡wQm.!9m-L,Oڨ92~Q햲MZ_m]ZӒj[1'+?c$JV/:r"n?񺙋g{6.u۫;?Oj$?i$tQ ,J561JiZ3{`n,eWZ|_Է \h#[MU:&!f%_Ȥ@C^Z![^)昋UK#Jana8Ԣ'|9M} Ϥnϭ9殳ҁϞzZ$bW&q{n:/nQ+mw>Aa_}WC͸G5m߁ӿ2'@z>-΄Յor+\?HõĐZ|`IP?9!-Fa X&% |_!UBVDFt罜ܐZ3dD JO,#0^~ >^~ ">$^&~(*,.02>4^6~8:5L>QrWD*GB KٽAKQ$rMVŊ]N~ā 濻'-3K$[}Rߝn-um]>Z5} M~tִ=l䆮f_灞w~֑~\抾1>٦c1EN*JoFҜ~ZP|^+x4Ԣrum ؍# =h8Ԥ~nj..\϶SӒ..Mтs0uϾNNI~M.f<&DM*B87\oN&G?"O<@)m,/qX-Mb?/5/-Ȍ}O﫨I`$o gP۳O@ D80B &QC'^Ę`ņ=^|xcȏI*Xrɍ)USL#4h3'Ζ r$РEETRM>(L?zUcV ,ϯcE۳հf,״uśW^dn_qSlb ƿ߶]+rȝ=Zݩ*9_:饥\lףmMk{pō]$kG~un3ӜNntxѷG^߯kNݝK;lMη˨;w?dA\I>g D#t0> B1F CdE_{kj@܏slGuD:@}I'I w,%oı1#1(RƯd\I,dM72k\+g0H0;<|S@=SM8S:eQGW4CҳE74RK> sG1qRՍLROWeԒQTTNL{L5U++SQ`Wee;X=\;մY=MSd4ZF Vg%ԹKE7]uK-Sos=uZw^{UUVe]9]`!t^n_<5/a``?~SSeXޒ6a#(/7v%coƹI%2^MFyۦ ᜧIaFдZߣuofT efm7뵁V˰o5k[vYE״>m'nzLZGFdq?y.zܾj\I{SW?Kв+/a8F2b#٤h'gDcE'I z%2}yH8Ѝ,"H'c GJV>9@JYCG-J'dd!I7&ғ%GK3F%+S2ik,#YD"o['ALg.&&TRD+%3(N\^sin3t6К gCˋt:YRs/^GhD*(5iE#*QG/i.i R{Qk>-Rh˕,5jVT*UTS]S5u50UUoeyme+4U@*&:تpQ(*52nR\իZ%[ת٥!R*hY6 Obֵ1,AYO(^:Hk`6eW_;܂9e:\u0&UxڼSk2M:&VPЕebn?E+w+B-_xܒ N0^bѾo[%)‹W*f[VPG>WVp-dۏ_sU\"\+mV%u|9'5Db -0Y5,V厥̞dHXq9.ef w(,dڐD.O5erfBˮκ/mbvgg>&j9BwEqE^.[ %3ݾӷfcd%ђ*kdz!ݵ/̸՚h5k!F~%]K9ٰLf]Ǘs]D%ʯNr++[V75M"r#LH>;Sm|חLA̷mn6:YLD%\f7=D!$xrw}=u^v _vS|`:_yMr,)9#x~1y]{zزvۙ5UY^1[=4K6핏{W,6lT䯿>Y=]_~}57zLep_<}٠1sR;o?0S䳿Tl#@, T"wB@St@Ay  ȼP2ľ |@ϣ3#@P#y@;7|?\@<sA:!(9$,@%?&l?0BJ1>#< *أ5Aĉ L @CBC\B8tC<1{> ?e2D|=K ERܫ{Fi$cu$/kFpf +GsD`xdǮ{GwTGddd$| $|HnǹȝG䍝ĔH{YȒnd:Ȗr$cHH+ɺBILq:6rEI],RȋA?tJ$4J#J \TH6«Ȫ,: J,Cĥ6Gt $hʱTJ4aK˹ ̬LK <+$JLlLB L<”hSLˬ,vLLm$MC BJd׌TI1BK؄6M< DCeNDTHDN<n$4DTdt%5EUeu %5EUeu !%"5#E$U%e&u'()*R<,R\F0U/I15ӹ3eS$l8U7͊5; 1:>ӌJ;A.=NBET/]MHF]4 T>uI*C-HIL})KAO-(Q:N}HREuԖTu&kWU&JZB3U8^]U_VVLcEEe-NTdhS=Ui֢UFm(jSn'` rM@eUc5umUSuexU4YTh{--Q}Ut r׀# ؃4gMW{E؆͵zS|Ȃ׉؇z،(VؑU e%ٓřEٕ-.}We٘9Xٛ%gXY 4ٞZY2ڣ]mYe2mڨE5X)Zڭ%W[j ۲)5۴}]ZuVm}۹u]Ud̼[XŒZ5ܙ[=مYlZ [-%[\>#\E[5]X=-]օ"ɍ]]ٝݡ[ݘ\ ޣE^ݠM^E^wm[^_BFU%NLD6a>bFY@dCOKAd57IuPِeReedTSNf~eU.R[YI]S;u`v\&fXVZ[>ud;^gf͔fO5f(l^OfnfZ^pnb7frNhF\g^ne~U-gG7{Wu~XcrFVo6nUN%UomhDK&U抆f`!,I%22BCM$ KLW,,8((4B"곴CDN..:33?eaabl@& `‡N0EV hH2c$-<0%F(].D L+ ^y@Nxi8 (QM(PfJ ^ fX!TX"|`C LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ NAps僛XtzS:޹,#d.~v Ϛ^}֥3?Sr/swAa^@!,2*22BCM$$M ,,8KLW΍CDN..:((*((433?K&wa14P@ ( "|D+^F Ȇ!F8y0%B ,D8!Lt@?w T P JN` AI H@ \(Âpʅ1G %@ދFac_F`c6X"e/Gf^Mɣ\4j|/ !;,16*""#$$$%%%&&&&&&(((,,,/////////911>12?13>1281100000000001000/00/43'20(0-*0*+.'<'$[$"!!!%%))--///////0/000000000060s121212121111212121214465H7^4sk2T0N0D/K.T+^.`.c.e-i-l.o,q/u0{2579<=AK`klgepܫzұʹƾ8A*\ȰÇ#JHŋ#aő CIR'!˗0cʜI͛8sɳϟ@LhQ H*]ʴI;L[)իXjU(Q*eDSQwLeٵ۷pըYd.}ɵs LκG՛oJ KL2VaeqZT-M zs lʞ%9rrAhO>Fă6УKNtKjϻ.k`Oߗnoe[|ӷ_Oecvh8Q"_~o!Vh}c6*J',P-n$Ӈx(s(+ nv[n"w(4Jxbb,gnHPF)s6^z$'-3Q<-(_fWs7&ȹi|S*hU2u%P I4%uԑrꩈaD)܊(z fx;fLkuj{3*j*yoۄF+-tYg;tv鰀~rvpv)JB;ƾ(PLkiftY$&² /T'nGFv0,+1l0߲lHS'3pK/'|9c *5d`Ӵ5=4apA S\5hrvqf˶dHmoܭ[3筷Z.\P}E=£ZՎr&7鹎z@x{l Wyt "ߣ_Pz*d1.x$^r^G' vu3`@hr)dA9zɞ58BhuӜMp Ex%1٨9B(K\L̽Qq\,! p D/u_$ :t֠ Dn!JxH a6=1aq7O;6Kb %/Lbҙ. Mh2s´/9a*q֬f6yMw Mj$1j^̧>~`My DAy08ᡠ`B͠V4ͨF7ь,)<`AB6pLb< 6&GɾԂJ)sN 5҆|<+L\x`=22wKRPvPS4K8a0z;ɘ;l$R,dPɪJr~d)يDPL<*U*$RzPv\Ţ!5nbwY 5mR.rk!(UU J?L t[Kr/ 5,)\V l`*А믂!ZN 6QynzzWPpK,pyUQ(A^~:JY }Š2Ijkт3)AIӑ^>h$Ro~f#*n o_K]o/-a^0p4!:'1u6i3"RRNNՒ$؎z+_L2VѢ]Bq\uYF&NU A]єuc)0~(>v|BR"cs M >V,MILdU% is1Ͻԝќ5'hI#YBxt'2:t*.ybX)Rf%KO41L*zr iW /r}8pNE2k=Bv{R}m?9Aoߴ{5pX>'DVnwvQleƥz%ģt'JOl9%N5I\ښu/H</q=~PW<%i_nȁ;rtB^0nu9pGLԒ^1WTƢK3J97=*Z}z:N/u= J 1 N;{\Tϙr3ocԋ 1g2 ʵ=sK=.j38,7.slXюR#s62aoBIQ/f7ǖOsgGGs4jsVjt?&aCgw JXWYvbu s7v̨2*1Ùǡ8£$#'8*DInbfdw_6tvw:9wda`!tqwI x2iB(w,ӘHo1(n y7gR/ ]yڏȧ6bwZx-rȦzZۅک+SꩢZ!:rtڪeQQǩګR%zRRꇬJ*^T٬jʪzڭTe:1e~4Yr( 3JQ1n¡GmjN hZd:I;0ְ-hh=ɟ4#'eU#3e9 D)2FIhm Kl a#'~nz`"kW6kv.F/0KLۥ5;<{qppx &]暷n*9%ɭZI*yr,1 }˶`c:,aaƤ|zha$'jkV{p_[hb`n)Dj,x*B/1`nd7+rp %"SbTHa%z!˶Txyky{;۽{;Zˬ蛾Ǻ++[zw# dg(ҕ+wf1Ļ9 a}P+AY$ a _ۛG{_:} $L ;b KZw -ܱ%&y$7m1&uLlLú-Ax-;xO+,ZC"*?b s!L(/AnCj;1t 1%Њs٢F rуD\ω }dws)v͒ N:]ӹe.=6<%:&@:#GIMG|E荧Ղ^ܭx6g*aCLm \\umnF%~~ء-ڮ~/ o^ ]? WUmvX/oGʉzi>'Rכ.0_*fɔ5$ke2"T#+"eI>K򭫘D+F&ki9^Y&]5?!뼒YJ p0˲yv~Qz8_N 1qsMi.iOz~@a.{I7?Z"XO?O?_S4;jQze-͇ԏ/J9Њ^:zPҭ>o܃otٟħzC4 PB  (UD-Rhȱ%GY;2ҤRQqټSN=}TP: LP҅#N,GFCt+Ky!11Zmݾ AuR@8}Vd..?ҌWN`{>YsŜlVKI(&EѤ:[l-'͌yķYڔM@!E7.^1װYֆ]z۹u=-HyI쪏Vn4XO_y~Ͼ?D00Bd!%0C B.0DG$)<;WdQEgEc1GgBw2HzdG!DR("42I'DjJ+\Ҿ*,۲K1u200 6DkL9KDjt~r=SkN1Lͧ>3NAUlNfT072RI-0OK/AmyJ:8ᚋ=U' Jr>A1ƞ$HYI`jU{M[+ KS[-"pkԳ1ϱOlYn8S 9dWMUYmw4S 8F<2"OZJ Zv_U4[?c;=dedWQ)Uf9fP`of`ƹgtn3nYUy&:i]fjj h*:으ShFm'3$n^/t+jͶz[3(o ~,p6qu߉/w7!JrD"iOC rw(UqSba`YNL}i;O3r]]k+}bº qijôO0tW|1}I{mT+qIk V-o'\Tw~_ЗrDvF T@bB=O$#01Xf{آ8ETb 0nBFP"&'ejF7&B^#3Q_$;9HBҐDd"HF6ґd$%9IJVҒ4*4tL@'E9Q{Sgp#7T2$%(&$$S/L;, Q*LfBQdx3j iT2 TsCjusn%afElL$M;)Buq%}%n^d9̓>> qfգ(Z$>9b4q;ݍP~]5b2Mv͒(fXE^3zV [8ɾ5FoTf jzl4.TU̓OؗlI̫z'bQPե#5?EKgvL:BTMGZ09Ć8aRӇ+r5R׹-5l<U;h}MF_ƌ]Y8A`#یo$pB惣aod尗4VY)G&r; ]k yjH^qTC[Y`3LN)P|ch]&Ҟ`޸2ׁ<.g?}&9eVKVVJ.p~Sm9ւ1~e5YV}H[SVUĴ1'/M)E.yC]ҒАeYd7Ifqe-Gz[XOW=F?_25(p+e)ؒ4edqs[\⸑?ޥK<"DyUr/d&7 Rr 5)/< o')@G@&4]H e2@rYߝ_=H BԩZ{ŗ֕0; oQ1t}H^2:EDP{=V' ~7&nʼd+?Oy޺?Aqd C>Gw]z i3Z1y~nE8dye2#-)4=(nn,Ai8z}[ZsMT`"!ed,"&3~z$-56?Z\x슽hQ#y3zÀ5P;+$5RBࢼh@J %:1('?8; 㢾 ԭVӾ>"8\<~ s?wڼf#hAVۗSt7F9ꢖp CK@*+j/d,û,+b>)8>1qXb:AD;C!#:üF$^%kţD?6&2&'P!i5%@I< Il9W\{@ō?]S<eWL/"%WxuXX҉|}Ox؜P1o4 {T R؆.}<}l+7:sR-,VKJCL dW]F\e jUhVvWVĩ#b,dbN"\RY7T@7df=>YLYv(14b;BgZY]ewQ#`FL݁X.&lUhIK(ᄎ0ٌ_eg_&hU-EizVD<|Qy;~ `-w%@YvfBGaf^ ҥ>arj@6®/L&}Q26&Ʋ3R⠕!;8ըkjHhn=U KF yӦ Bj=Ѷ l>,KdEE7V -:LY+LeFQL&޶&mf^? fe($! fK~6Ls/hof! ZqNjs^\ νհi2g`XjvWi(`]V鄐R\XFip}"2Oi®Ajq^fqpp^$q) i?m]_r:p(nryg Gh$Rq ׋%  `ssN]^f"}ha8a=*WF52h}rtt"ta@skkbsd߻/$skH-qLk\S/N/ \_=Kk"ڈu0E/_{H4`ll? ʬ=Jli/NZ4$l*C?v3ts-s-M]!uD4L$KS xdtuӴN;K҅Ewr|׵ gNkN[d[<@^ۇGa7@7*ܾ_FH[-bsy4Jp)^έGWΪ-0JFS*GVN ueM̗3hv -mC]5tG#5]5D>[woڶoʗ>Z{R;T3n:v¡G/;ɷsO*%_^y=S? 8 x * :  &p!j!9U!x~'")Gb"̱1xl3W#=ؙ#E$wC$9! MJ)EI>&W!Seeei$2Mf]9Yf:GqzҝjIs%w[44'yX~fvҢN٦io EX~ɑ&LᑌiMbeMRJC<TD<$|kybRJnjKWSN7שhZI>rd갗H:,.eP8RЊ%f1輇,vTg2inwuFYZDlzд`;durlLٵO\$JY]"r-Gxalz 3=E+ 42VlIG}uM_][A0zR/[r' ja w>edI#(h/}Õ`TB^p_g18WGEe/d{$?ʉou/3`$f;Myde# r+!/DJnl#HJRp$.Iir^'J兊KJX8GuqeFɓ #8L,dc*AkxJU<g^8*|bV!"6a2+Ǹ(C0_"U . g9O;!\u9; )+^~aS" #ȃSu)Ob|`Ie*,%}C"DK?c++hfW i>? 1K% q)<7E*+cA`4I]MMX/[^;e*T7JqPt)OZ-Y YTGP vdU +DKv$FlXȲRkMТ>9-, ;ĉ|*fW5e*{cLd0j/e\-d]uƫ0-ζ,@jAktq̮4<Ӎ2IJ]u"yϻ_C|+ҷ/~/,ؿf`,3~03i@c83 s0C,&>1Seha, ¢1s>1,!F>2% F0h@i@k2-sYAfHLC2Ӭ5n~3,9ӹv3= :4-AІ>4E3ю~4#-IS҇6l!,16*22tHߜtHttHtԬHtHttߜHHttHHHHHHHttHHtHHHtHttBCMT߿$HHtttWWtH D1=+HP%0Pߗ#tHtصPTItHHHtHtUttth3 խ!,8ߜ|||[_89_&,8T..:/Ngggs?#DR1:CMB;3((4B2) 2 KLWT33?S3Qtǁ? tHabl! H*\ȰÇ#JHŋ ظ@ CIɓ(S\ɲ˗0cʜI&H;ɳϟ@ J$ΜG*]ʴӧEr իX֯`Ê@ٱhӪ]KlٝrʝDݿ &0ǐ#KLeDIy,$rgJ;VMװc˞yܷpVa\ִa+_<)7xp x#pp C!+؀wxn\|8Ey<{`KY.^㟿g W khAқ &gB:\Bl.V06A v胎boF%МMҋwhхm589;ІO /c- lG$w(>B՞1pИxSBLNPባum&Soh7摄# t/&7A@($e: "PBja@PjԎLT*J R.Иl=BRe&@R߱eXQQh&R;eT(Ț ExI ) !g]њ%afK}޸If$Q*e&SsH,<5$ѐҞf2'6AQffy0@&}~:O$If2/5T'Xь#}#/YJV:2M)R(=Ug)%%G2OLU8U)4S:k53B+BnDxa")MA 1WTlTBĠe8OЊ.;  **#Ѥӂlfr%DU^,ԦX-u (,IEJKmd)E +Pn>n%rռ WmϖK]f}StgrH lڧj-otxVT6.r]7]rdͷZ }ĀMpκ[wWv[{5]yn}<?zϾ[mћ_ aa1Apl.ض֖@S쏃O!>ҟ l1,~IԂA Ed44\萍,0/gqَ>$PfB1 ͼ 1lHH9slH"Y9DtoeY&r6,ِR+ϔHq>q#}K?c:-&Y<\8Vv5aGYӏ $ESjV֭2kRJ4.@&7IP+')tJ_v{*f<" RCr'@](tG-.k/„U,r+5ov`v,oDCtϧӟlgc}&z:"7TJ8:3vMHdؒp_(@;Xv:>"ķg./9˟Ԧ1I.'7ǭJRfL':P^';o%Qsh 7GSⰹ#IwG*UUo_R|bzTnAUj̯g1EI*B_"zLG&\Y|滘k5e !iiE+2KX7ە|ΫѠQ^WSׁBV7Lbj~╮՟_zZC7eUB{u$%LtՇ{Efd~_VgFHJw"ơ]"шbadf(np<NtW aŗyyؘɘ 9E鈕"`WhIY1$} (%uwg(]#GyB8UuZmhrO)hCE4ER) ۉPI$xy~r(#D^6Hr'LVVWTkGLr1~⋚}dIt֟wYׁ$?Y^uNT'p}"y"B8%&J&,oxhnAWՍ$򍮧M'R)Xʑv=X6,Js8}I+wt! %jU!fZ:/I٥h|lcrv myJuvw]w$gc"Xi*gŦ橤 h7ykeї9n5j2}ZyxMsƩxZU#oerV}xb%OࡓB~{ W+|Jt|rA#ҔشXj#*%~U~RH:ںxBZ3IXC'*h)ŹPqJ3Z%i ʯᣇc+? # E6Adf)^$[u(\*ղ.[054 Z6{:A<۳ @@V+E^6pQ)q%h!t;@h+yD 4鵴˴syf"E9Z@ԕgJ"tv[jgMk{kq~()mPvIJmjM jHH&~YEovy춢'FL#3:p@';D~'wLE'zq+K9hB0$Uz}:eBPVf_v7}VnkZXZ{%dv_V{T8b~ Zvըsvs1 k勴ٗ꫕<(RʋÍ77zDɫW• ³Qvr|X|LA7*m{Xeʬb^:ʕxˋw-zX\f/" ۱TL`ŕʰLeR=T]V}X 80O^?p`MAN= ,8fe4nMpG=פ5|c't-v]ҋ`=#i =+}xDΝk#2T+KܵTܞ}NQ4KhP%!(Odlgݾ0mW箫6Ǿz?vIA  8+QAY}RsN3 / ?;&%%,. 2M^w;4ϙR=eKnm-=} (PP%J0J{.v GG9t"[* 2Ġr!^o#~/gn!l 9N PDPž/Nsb's>vˆb6P&p ;7=ۀ*7g$o^AN TDTxR^wE gDIԁuG_c<}OX_$?_}3O'oM6@@ DPB >QDQF9(H%MDRʁ](rL5męSgE=atPE}Si̐' 0)JJU[#zEV,ʥe3Zq*V׎=\ ͚E4@nw5)wZ@XC8VVYhы d\`jǔ^>95ҹ Vix)bob lPj 8\h@Pw5Եy8I"sL64P1D@[.xr>IOKA #4Lп4s 0@Nj,Y(ĞBҋvŁ6Jk9pLPI&[ J tHȟF,D'{BФ nCd(3P|HA+B@CP e4" e,M7@9DL?"3TSOmtԍ EUW-RuR_VbՈU[w%\1Oa%XcE6YeeYg6ZiZk6Y{_ݶ[q_6]ErM]F ]yWyﭴޙP}ڴ_7(4oESk)*8``(-6ZOcIdlN2@|#7~v64ܐnOۍ Ɓ,4e[p`b$:$RXk >3nn(p^yT蠲7c;_ٍH f; ͌ d4ZsX"JI;эv}~TSPh$ "A>-QZ ŧFZ }]bȐ-=z[߆f.i?m>VS^-oŌyFHpX j 1^e~p.0ysTdMK\&hbPa2EKf𞳀nKܜɕt³{P>Py܋TiFjtBw# ڙEЂs JT c!viʥ~^^teh{" hVԃ"ՁT7u3UiB3 ^05zE#^4YVʎm[Z25cWկl`,mӮXa]XW⋱c!.N6]0na6&!#gRY!GI&ZT} IڣTR CΏB-i͚h̒i 7' 7,iTKr.q{ta֭*M[ZdQm7R4 :֍xgV^sMb@t-oQS 29`狾 !LOf1nýWPGV7K. C-v}W$6 mhcA$>)icXqC^(ҁHw2:F6!B 4rҷK*qqCs,e`.nJa36Y.iORͶXm[l=nr.ݪm[v̛9S$H7Klk;護+VeZ+^ mhQpq/n76mqb|MIj[‰_/v _&sIA"2Q )'U {Z_+1ǢZjz:[/ezul{XGbvo\Kh%I9]/vׅ(b-ԁ"vR֙tX!72KKנrؐ+Dߞ95iK>ޕ=ǼՌ@kQ*(K̵Э}#ṝ <y/_=T~Dmv?bo%?; "-Cac8P 6򼓻+%K9 s[?²Zk%M -$3:A:.JڢK-9, 㺑47A&{:128(7&=4䠮q'˻94+y 8l5bM=p4gz5& C {K˜CCE 42CPK/Ы.{** Kד=N4)k5V9)D>T"5z" Ű/\|Xt*rƴCܷS7dVdFЗ&gzAosl~ơ1O;r4sDttCp$?)Fw,2pGcSvDZȿ~cHXȁ4HF VQ8xHk84zoHBDA=\>H+ 4A#I}G3:@$B2${5n95NA%FTʞs zAʦ\Kԓ3OA?<˳f 93DR6>ҊM*DI TE,T>0Κ*5<54ͬLO38ZIQPշYU?! G^F_F`FQb5cEceǙhfŏgVgVfVdVH9b$iEܱc&O W )KO=b=4MCw͵kW$ =IK }%4)u2b5W:rB%yXxfȽ:=$T=YK%{$dRpIKOڬ:[ \v\ϭX㋑4)29BA6]*˶I,NEL<ӾULLY+^MUħk0-L+qE,T'yu=OԲ]Il.䏬k'0mﲇ<* p9oD[Ѧ (gz b%DmjZۦG5 X(AFت_M~,,T@0fԳ^u ` @10[zM*ծmn HEEa*UH:a4=o"%E-ac3tDE0I$0-uM[\V$uVdb9",Ru2QcMw ?LHX@bRDz$o JWID,RZtQ04́Ɍ4QL#%2À69nzC 'z  8v;6`jyN@>I>@N@xNdA1 % !,1G22xAtHx囒ߜttHHttttߜHHHHttt CH_HHHtttHtxHH$K圿tHHxHxH Ft"HtHH1U1CKBCMt:HHt!('Czt!C. 4̛W5WBCKClH_3 ߿7tHH*\ȰÇ#JHŋ3l PǏ CIIO\ɲ˗+SœI͛'eɳϞ: JƠF*]EP $*WZv}@u` R3HHUa%V[c}C^pnCÇDLpct5@^`YA11d Wl+`Ϟ~9cg)=uDmpxUӨSwh\p=`$;@ ^Jup5Ew?{@DB^@qtmxvfmgpZpyaehv[r FiW@Vb@@oPvU^8jeX1rAn}9$I#Kb[5X܂+(qZۈތ_Ux!"Je\5UVW`wp]^d~zf$z`h8ע1x\uy)nY rG^5x&8bFWW  kYVZ@[tG*ZJj[ B޴͍y&e)fb59 =&YH V$kVV"gWuJP(̮oq*b񠰞}= ߙL\01+<1(tseWV}CVF(^6Yul<+L΂&&CFG\as[u_+v=}cWu#Do]Ud_碭L~PmҕE8DG䛇.zC9裧C ,.z.츏o'77/GogwO!F:|$;EJd!I/v(GIJ3F  Ƙ(@|? JKf1,.w)S1e&EZ$&/MQa$2ya&ӕ̦65 W Zƙ%eЙ@ş>M5r 1(A*ϩ2 F *Pl^S̨F4~T@`QYt'At O$ LxFgJS-v}eJaPTAP𴘮#0sNW@ u(iT"t0A@QB)\R,ja !eZ%iLEl`>(8Є0t#?Y@fGK6 @ X5iXN brl pבVL/hAЍtKR1 !,xr22ԇgrxyx~x\x#rwx|VTedqxg̼MxҀij;x%қ)yv5M}3̪r{iԍv{~~)l ӎ( ! 0`qBBnh!ŋ5Dq C^0"SH*S&0C1tHϟ@"L*00ӧP`իXj`֯[/Kje(`Dk6ܭd\5@b5p޾/ j@c8.J O(й3(D"Ο/ DE%J <@* t(F 1_L#r8r܈ЀF:t !=, 121211111111111111,,,,,,,,,,-+-+))(''&&&&%&%2,I6c}CvG~A@AA~~@||:vv-mnghfgef[[WWVVUUQQKKHH"HG GH#FH$9O!%Yaccdfgim)vMy r n v '/) ; gTJ+C4?7>8=8<58,( )Tfw#2448DMOPNNKJHIJMPPQRSTTTTTT[{ } ~ ~~~~~&~9~1}|| | | z x w t p o p v ҁЏʢ """&ͻ@޻Xit~߸̯˻ͿH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\IK0cnC1,sɳϟ%dѣH*]ʴӧPJ2&̎7mNʵףBCJٳhӪ]˶ۊUez̊ݻx96߿ Eȏ5Ċ mf˘33ϠCMaI7ebUGVMY=ͻﲦm;]?qw 9GdH}E^l~K^%Xc9.~mBϐ{φଋ65(2ANj'RBIFFHR$z|Ad Z~h51d!ǀH)4dd#I&%&6|Bh(=5Io2eu%Ur䕶H,ZC l MeZImx6o,6MqzdeB:N?2}*:.F:](E '2eOP_HD# uSbmhNizS;(CjSe&U^;NG&f'ZRHP`UoAJQF48-+DVo-jJ*\UD.3/Re^Q䫝*AָU+YԢ^r]si , Z6(źJʮUD}kʖl[Ӌ\m/wجW.D4#s㓻C[[b< OwW6`zwmorջ\՝CSE颩 . A*.H0Q1(ݓG R.B/ b%8~ FKN}p}Ѧ4-Z3':tӋTLfF%c]FBzh@@+tcN c4I^ Y ,id-+ Ѕ.KeȈ9,W4x/:Uk3JCc-!rLdIYDD,M#dr9Ϲ 63LK"˧6jd#xE=]lӬ낄 {PbQ0)aGŕ)< cJ@[D+ W6ިNj!ܲ@|d`_c 6Ȉ X}37m.0/nw:6he+IOOu%F-:ޛe10o>-fz3A+| LWLL:YBFr3);\s1 g7a߸:IeQ^E5w" zV21w} tTX钀Ś}.DoL]K]ԋt-{yC= [Hz R4G?a! W`Wr?>Cç}H9WUOÎQ:u =:Ho:G~B/cߎڟ_c~?`Q8X P0 hG x gEWL+ww|0w~gnjLoxsO'o8ox' GiFVevF}xli&v@{v%)o%h>g1S7|1r烵yftMt6=XHoIƆpFkmk xFjwy8j=n@GFzVwti'` hgNbXZ`>X#d(}2*Ivo؀{FetcPyioeP}{f6qp@fUiu& s(Lt l`W!83/R `atQ\\ō^![%] D|$C%b hq!Qn7aWa4r%BE wՐy!6!Z#i__TwkӁN!tRsD(ٍ޸~я>2W8y!6JSuVq^^C[PYNWY)Hr&r!aE GY$U[j9KKZg޵]y]MٖhINY [9h+Yh-yh/9w3da7Mഔ}d XL[tɖoYMÓyC e#٘SeQY]e5u[ESYC%Yɘ>֗63y y#RS險Y[E֙Y5^U^IRו i"6ҜtYٝUYYLɛxi[ ѹyj[aYិ3Ǡi[䩟[i ^t=mb iH !j[yU]4jV95)Xș ). rp98<ʣV7*leV)Y٣剤l Nt1)K&y(\{F rtqIOѧq)%.Y;L,ꏇZZ"F{z5rقq2 =؄x2.كۺ  =&9ƍ&tsʭ" =^]xGcgݽA1t9}]؇*E Z"߼ 1ᑴ"a$#1M֌-(*,.02P% s'B=@B~4@(!rba8YXrQ=q"0-X4M o. A =p#1s^hN#P# VXN|i>G.njn#NN{+Kj  .c 쭎u.$nqy~ \^@;Ǟ>Q] ;dAS>..~~#\&qd_d.!  Q:Ru6㙪.U?U&a.*Beʻ ^ߥ~`B>Ѿ1^Я]Ē 1BXdmr$O9O * %ulvX"_F_dOC #a>.rt,ǡP.!>geo^L/lϠo\SNa%:~؟p[??iA1!BNJAؿ2@@ DPB >du VQF;Z8p#Ǒ<ycƔQ|i0D5m92<TPcrETR[HiN:^Ŋuќ].PhAHE:O(jX^*.{ jKXt.Cث]Uխ-_|Y]= L9<3ȖSV%cƝygeE}[pzX"ɋVEnȱ]ԭCǙwot zlwDrw]\Nz '_v2!Wj3:DˉVjM#`c B A g"M P'z.D:$o2ʘKJkz;9elF."kk-d*ɱУDgT1Ŭ1@-DB0t$E;3 5 MSrDsH:) 1?;TG -:+-ZѨNFێO S{R &l,NU*UL-qPˏ+4W̸K]EH1I*5 gSMO2XaL )OŖ&?/5 4YEj`I,s+U@i",ITD] Dtd)Yۋ+o* r*l'Ήש|gb6=^͌Dk9e_-:2Cq--ww^_y]fHB}S߮>1UaԠOɁIZeV9l,f c+ Ex/ÓC;eAW\!B Cdtڝi4i>*:'_E3n:%fhaĭn2;u*C]Fvl6h^L?lf*5ukpB Fk\p[*Gjz;mrkkڻx^]/v/v}_W }/"DH1;|89|C4IiSaZN\թDk%#`rp?i/)c!tCB~#J ?fP)k"1pQܢ@I9O N;@"$(Y S|>O)NW%fc9QLW8ʅHaq3C937h"Jqj<=MGQ~^YrvqՋ8+d!ӰQ{GT^%S):}H-)e{Dw5G- BD< U2b2=aBYxGwl#U愕:yYR .Gr,BL ]LP "w zBDV&!J/"Ej`_ge'P9qrN*%E)BI˔毛(0H+A3,ђJ&.& )jq6*Ȼ-%HoBRUmJU!{@s$Jt =bN3)*(NTTf]Cgo2%LL^^yEK'2' i1@[j׽Ll{{Y|(3A.MDWN&mGkВ31 )ݖP#EKvAS~I5MDw#e_}-OXQE<ΥASei 6pj;zemKXSM!+#rm=%z_pa̜r;ɿ[-RrkGHc|"<3"/\8&o_<W&J;K;s g@7a lɾb9 ?˸<@8?:1c7x7?A{&Ҫ9@5 c3P&P#+9B4@Ļ.6#@9B 4Kē,)i372b Vɩ#B#DD=X3E&=?;D*+ı,2<893A>飾>1 OC C39 :/K ;RP`Ƭ!]S &L3_3B܋Ma^3]9#CN/n0nEk9fEW DApE1@-6^qDaeeE>->d6` #d%fZsZJv]`D_)$eAgifdLSu.T4K $7qVAOv⽓\ef].K w%xh޻ed]I[ۦt3*BW<]dhv ŭKr>ŰFmttEOnWEcc@5`Ukdм^V( %[edOU.ƖBY_hsλpd1&rTiCGrfhy;ZgQ5b^EeFbMʃ^JOubIbuNԝ 9e\IY&I 쾉gv[G9@fM mB~P[IjG~NohƉiG=QlnU&Mnsl@Tn!iTN6-~3NW> :Un7 tS9p!oeb:d6VEmڤZ>6*#^ATn.%Oގ qxf,kvqH201*2Gt`Ks\CϘjP wg^}k`i>.t&tAW*^>GEF*Gt\s%vv~Z}qoRr|( %yw@fdOv~gnôvm@guNFx0m\y]Q\Mٰy}N?vxwwf?yvh˩\CFy,5qzہO q-6k?:$uh)fzmWh\h{:npn?={ՓލW͢=N~-wnA|z{Mwl)rMsOuz 4rnz\Kۧ.{:|ZJa7MObhcG|\CHrxQTWy~{q}O ~yLw|psgؿm'OvR „1',p!7r#Ȑ"G,irl%LZi3fǛ/u'H[ˆc(ҤJ)Ԓ[x!DDqN"蘔E?E:?bVdRю.*.Dž ="a"ÌM>f(/̚7Lٓ%Т5TyWԦkn=Z(eLg6S>pO-j-TEZmlڐ9Qnkr0a#O!& o}G8AïӬ1ο>'FTm* ^fm^* r{4D`]d!Al %t$ kԠc]G-!G!&rj8҃WDErIdL dM>@QJ RF9FzЀE8&w_)҂8 Xb R v]B>בz҈3ަbOkB$#%~c":vTgA-]y#Y؛j0HtdewjXjj`iହ"fBTFj$rt Gcܙ5g)bIF4ދȞK$m꒪koֻ/Znފ+򊐯fM!I$-[">Zqݵf MmG~L˜6|3.;~/B ݟG}/Fܞ@KuusERxZheЄbq8P^}mEiѶ6IZL5υLDҎ#4*E-li5AX['&^Hv,7"o=-aswLs#u"Aqq9RsxH:UJ*MP_nts9Ky."]|b^! 0^Q޾ v'?BR';I 2{ULpDAdm^h>%XP#,G*8&I PX Rz $acX⧕}L$ϊ1}! BSBP L_GA11JӸj7@"BD$LubEh QHHv$mK&!DwH߈g0JM(J$n\#ǦHvc+5G5(e QA$d()4^҅*4-0~Ė(K9Sb$*TUT6-s$ =; 鶶ɒ(QCIDbGlxn; )nBt#J8[UQ3},},&rvc;:)s,"#IS]DCBџ>P迈 @JIHmsD!$ BCf LJ 2dQ3[l }JMiޒ7'_ʑ> *Hj*a~+`+=,b5&QXҊ%t֡Q=ٔӑYjB*i]lc׏赱FuJacۚrN.y@齰Vv#.eWyOT$VY1sVRmDʘS]o 8[v=/zӫ«.yvQ>dvǍI2L$Kɵ=)d+ߧ#嵫{3 s&l5s烤\A~;]mKڙm+ .4 {]}rzF>2lj ,*WX7NCo.߭n?i\յꮙ "\ 2e2*̑!+Uv3X& ?zY.h~O)IVq=sZKprgzy>5;1u$%hOl,o;(O$-Yxivٜ]fBnvR$/Ҿ6jA{#QtIeוdވ^ȗ@tI eړ@JF9.VᪿTFBl 6n@v:N&Iϭ_qv0~-f61ޜԷ#֔+wgh#s%3A|n"ޫ1xo />j"ja"`w$Ya5_Cho G n od$VS6}"Cx!#YcRb f9BM}"hߨڙpspa;Ġqwuy떺XƍËdMzL|{tyVܽ\*_^wz|_wWr3񢑣ի)[$,;'cW? O21 , YXr*H<"}tyEmdNHэ_6a(. _YN+ք! "-W"*F]GK1 N&~m!n\r@_.D ɢ t,"8-bM5W(ijBrS!QfbT$c"9a6c)=zU\#Adc7m@@-#Dc=- B9⡭c1;~=|_HĠ TW_ɽDd٩b)$BDD$P8V]bIG!$cOt /XS`a)vڤ@ $6mN  %%WDUF>K\4J# 噐@e, :O%g\B!\2Pex;jV\Y9 - TBfddZ@tqg %eIv_uSURO$ad\%CdʝnbH&Pf+\0tq:$A8'ek(dMTFOY%`h mfuv%=z'pvme+M$Egf`#)H*`#PS8wa"5&df̕` ~ʟՈt(I:u&4E(uFҩčj>!PLyf闰{R)ω~ eh_Jb"D@~uOl)V TLǘWf i9)*(v$vJI$rDV%MxBPhNY 4B)H#ЪjA@*P"(5iuOW~* ~i/v'lFEc+n B( #@kG j2%(鶺)Xĕ Du iaD;*>n%ATr]B5FE |+)ǶAȪGx |l +6F~hlP$9Бha`CXbR N>EcM90R,jDǚ,*A~mAkSx RDJ_!&FehN(i&H&0q#3jyf-THJB#mz.N--Ǿ䈓- ll&~jRR)>B-B` Y+CfȖ췢2쯪.I.޺iSin.Ȟ+0bڢ&~LlO-eLҐIұ(BiĎjp,yj`kM@doF0Tj*/F¬dJ0%ˑ..’rF~ ajж.pn?E K4ZeȰ Ocz^]o,6Lp j]'`nLq?Š&2/G\ !mU oDHP0P,+SWŤ=])/J0V!3+k'Z1o1r{*҄8+:$r.-2ř12[&ukFK*<-3'a47?nb*64,[*ǒ³s~_=sIc>D`?7PIDtnhsN4GݲG-/g$i>F27H)gPQLhtp*54c2RD:o;S%FaBU pJ MSSs[ 9[$U2:]$7J~m5*!_w,3I0D%  \/5+Ù+OSuQ 0S^7PM[IdNߊvTÞĖ.W)OIHRc6fu+khvM 4 `*V skW\6P#(l5Q[6ge{k@uoep+G|65iru8 s_ O7 _}wA6YdnWv]6pCp_z36IxE|aiWl?7I5u$5#v?xoƂ7[w8UcSs% ̳7`\sS2X/vÈM8N8! yǗy^q36>+jЏcRXPH ?3u69Ix}gpwxi^8zk9w~>xu;uxJ 9x[zWyy@C8}ER:Ҏ9߳ta7wAn2OHĀka:TpYlXoKyuot}jG$S:鍩DO؝g{G8*WNm &Wu/y{4ĶWF{W70/M 9H/YlX̸A4B.-24~j|c< |L,!IJrs'k⤙bؘ㷚vZZ%:'wu4ǜ :K5"}'u26빵,wBZo[pnթY| ZNkwfn n./+Io.UoE2u]2Cv"WVM݉R/Q1l硏^驯Ͼ*ݤʕ? wޣR>'UǿR>}0` M@O㞉f7 8AR@-PM AR=&T!U4/q1I?hC0= C[, SC"V{_ؙ\Ě!"ĝTQ] cD*ы_DBvetKE u,a" ю >Ҏr  Hq%z *ͩ{dAH:^1^!qK,T#%IR(ZJd&JR)K!MX-D, i( 2HKGҗݴ 0I"L3PNs dMYRSd4gMy'H9@r&;'Ns!XFS/1flJGϊMhC7͛V9ZAQ4;!'2j,b(?Q"R&=iM74Ƙ-uM !stʃQ0~Nx&܆OP' MK"?ǽq/R&i哸l n|7i$(Uʥ~N,G ]qU׽'Udc)ݨ[=;Y{!lW:!C/ykB_<ÇݾbwW7J_^y uAվeDpF}I@=׉T'ߓ=h]Iف̩PH}>q'1QR/7\`?QvB0G~ a»~C?6~N;N>a?Ro-"0 *G0 ,H)N0n&"ƚ$ x&~B/&6n$A~np Ϧ6d+зR/h*p0Hcb/P@aD-(2O6:6- P{ p!0 + pf/: [m DfCeNb/~ 2! %п~p**+#e*p lj:mM Q'/J<4BMp'"kPSүA0n nDmu(0Y JPAH&ۂ1׆BY(q=#tގ۴.#}yL΋цБ1k*zpp%Pjnq<2'Hp|''} #N250 ! O"i Q -p'q0A$d(&KDN )u@o(!.r.( i B("(pR'G)7Ox.(1jO+k"|2.CF2􎐜Е2.L1QM.r Ng6)M6/qB"S.21I:Lm2_TJl`&m"2U&%Ap v5'/O q"r 5u6/05 O7"6r4s9uH9(::kB;:c۶!o<>B$yMb 0kS=2?{sJB@@9S +Ac"%?NQP@14.rbAbSD7n . U?0PZqC^ b/ UX527Ud1u`mRi1gO"5 59KɞphQk˕HU>/6vIb^qddK eKe5_X3MiuBfT(6cgcw4hOohv(`$* UO%:`%VOR"pkE[k b6$7^v$67SSmq"p.VGWanbh%&-$j4k%" .7RE=} @= = pr%s)Mpi'8tobv;.J7~-%@{ {5|wLMuv2oSu}Ҵ|W/r7dZ BzO< Vl1 MutoBF׀m"~.9 |IH`S IA}{ ]w h}}Bt8f~C/llx+a&t3Lglfawjgz( H|  `@~%E@-b@AuU4v+B`,zB6't^s5Bx+&~L5{73m[(ָ؊ ي | GNBUw5 y!X5rk"Tw6 ƀmYYif]xZCY|YQuB*3"CJ,eȒN O$|5ܘCW”tJ6l3!T%Lz s bQςM~Yu''ƙf@Q5"֘#,xqGw !I0]8ڈV=/)A=58ʝ97,@hM0y9>~3wYw9!Wwdyxs%:_R@|7x^0%S*Ii*NZ27~:B?:rѹ/1X$A۪?V'C%*ѼOQ.*:[a+5zSZAstR9{F֜u˺$|FPwV[9ԑ%3˧{Zp:E&j`QC &$Q!wL1c=KB;A"fv0׋G˼3Ӥp@oiHv:&3qHy%Fr ,w%HE{eW-|!l~ջS$˵A|c1UMi\!:Y4!/xO6ݓcxzvFzD5t5[j4"<0[[[ѮN8it϶&lۺ@lUjK ;<A}c T =>'4i&#߸"UJ) KbY]>&nQ0P؄K ɚQ^ $@bǀ|1/~<$Ukb~澲B&X\EX`We ->&R݃-oη!߱Z|T_ƒ~0\_bec y38:|ĉ+Z1ƍ;z2H[ bCxINǔ#Y|Ν5I9HNGxvjiSqC  r*LGw♄3Ƨ5;%ų.aʔ7޽|e7;>8|m `?m Z8f%Or#&<~gSOR둨Q)[E8j*Ꝙϻwl vܽs/^uÛ??0ov8!|ٽ~QToxmIu}TE+5q"H$QUkU`.Xo|HO NH'V$ވDT^>ʥޏBy#|$D.W~EP1YQw,v$۔y#WdXLqQgC6V5eyUҘX؎:hih6A }Q_Ih zъ/yRik兩uۀh^Fȉ&]MaisIi\N⥫H$.EFBV 5TFlNt{QFGV\G+n.HjZhѫ}#v-E(g.-^&me&̰::F 9$ٵP6\ŊѾQre*H; /!&*/mziy 2 ѱF뷰N< bP7pOuGv[XjrzWn)(CrEP}G]wH'c$/_H4aNk*с)zTuքYhWGl^?T1؜3IsK9SyӽȪ+E)׺Dgw|Q{͂G#6OU>}A=xyaaW?N[P`_ >i6E/&:0؞+b̂8iKߌ2r Pŋ~3{HŏD8$BȪF.F), AH;ZjQ1!BhCZ*>OI$D}u cM~uE"N RF3rvCFVA`CB-eQ#pXHvL!"H{Tf29<SY$1JFb/Ixc,Trn+[ERU'jT&%ʼ=4gH(,.= 9]f:3tL&2Lg^T͚5hNS߻3%MCi!pcө%ϸ~J"UOѤ&:t=uP4FNmR S")# ͉#%FzVfmkH7ZÒӚġ ү5ҫ4ܙ)ZV$c^Dvtf %3Ԡ'^i"S-)ǒ |eV/~ =6#`zIַRԎ+5)a4bzj#ӕӟ#y^ 6$<?&F'KeRWo؅lh7w:NkԺi/HYtbN:+YDЈz)w"w#pQyM72v1v_c (1 3} 1\ c0ҥqfE7ѲV5Yz2#D, ^xA|ܒޝ;l7"N/1A|Z4x4ex [fl*oL~|\m-% 45R7Hdi ŒVaHktMٳHwvT=S:,ˠL\0OI=U9<6yDIᴳYGK-h,Eug^nȣ. <_ث@GO$Qn{|ԦMmcp4V8Xr/C^:-Z/I%mT+LSaYx|l?[$aFM|# yK1RO;x<7Z] ;nUr+%όf?\#*NՌ_ȘP3P}}| ~"n:]$F}DO׸SX{9yuƜPҹȇdgLbb %fqkx{mu DГ4~{o=-V>bS;Iu?ay'ş0޸H3X}-y_y.է7~'}W|@s ~A~g~>_#:F@7}9sQRu&d'u8!5AA! ˓`wv7,aa8iǃvm-CHF1Xuzs2#?!E?a0 ߥOtfPf|H>(@iBȆt6c`AŒ}FӇ{D)Iwt*(kӅMeg8GvW'x{8xFS }떃#c]HAch@ qP^wz hP|rb$ q$qƀ!!RX5hׅ:` fye䌸o6m'$F LjWF׌}k9jR |OBlHSvIuQ?Yh| p(ix(tZr;щ.%c"Hfh+(`a` O-V+ ):=97(˜RKHfmcTSH*h4YIN8 :gHވX]jԋhX^\IetYg`If[1<'}x{Pawm bc;f kDy2)0 i ^A>i7(\9DQ EC$-≐jSD|?ek~Tvy ި_Yo39ާ#In5IL㙘aQČY6/sc0Y u:3i+I吇+Žf>q9OɞٔwR9q|Fș FY5FSwknH:o :F*VW^?Nh"j&[)Mi'i#VɐZGF` Al"ܑ}zYCjYUyѤhuRVoU|jXZqD >JJiyϩGz r .cq1vJ|s]u 2e[EyR|$:>1±, ~ڃZ|a6cRWj٨l Z ꯒDo)aȱ6zK##Ʋڎg{yUd*I٪ P-X)ׯV{I{*:h^x"a[#I>b᭶]UX g4zصt}!o铛DB4:E #o cCjNܪ4ŸYE˩Z;D>\R _!/3+]QrCTjVbaJ{u1TA|5KܺU*L|۰껳+ 箎:qĽ˹Wj:j:nj񸍘u9Kzl ݿ5A}AD AFWN$%)j.*o׋wZ)|_=wa}EVqxj u,5;eX1cz2!ƍ,+ү$i؈b l9d'1­m;[u?{/o['{*qݒP^[ܑҲ`Q[ 9WiR[z9M,;[)~y\yu?MqZdRϯq|z&0& ɾ,`ݡv7\aELtÅ&Y4PM]m^Dn7: ^ժZU-m@,~]N M${ߘM ]H--9}% 5U=aNֵMtVu*=s+[>d__32Ίghln;?n%A!}tۯ[ifݨ%lHdM!rnԗ}>mF~<^bn֎ u{vUԶ@BNٝ.ޝ8ߜ.N8l&=sNfU0_Hb>Ilo|br;쿱9%ˑ܆.8)s풽+A `'o>+W`K:+3_O% 9>P/B/sD_:{ŭĞ6N?bӥdU8Ѷʪ/a!Gm.Em/cM-x^vﰨRo&|/T!a2 }т/zJ|ΨĂ1L!?T1y/(Kmkל+0z! ۄ5!̱C$[mOB)Hx$ A .dpCz4iAxH(Gp$Ydċ&i:RaH\Χ9$n 0{GJ 1 o<Im:*MC"#aR`Ŀ,Ʌ rJ*R0+ J.9J ksB+%ID3It 0@M{u?4XBؠ:UfzgKuNSk-Ӱh0RҖ[,d5 t4]u4Lv^4=V*W*vUw`JvX@n/h#R>pHD:Lj,Ti= Q]kH'I_ögo 1&~1&9hԪNgYU)zkԎLrIJyڬsZlJ;]jz;m;Cl?s٫zpGJ?lq잉fr 49}_9/ß\~жR87JR $lI7e`PKdA&-)< g¦pl8?,vqc搇Q bD62'c%QsOㅐk!SHHe"F&d^C.\$8Nd&#ؓUgQ*MECWcaVNj+T:21}=0Q.˜V]\WjvZd {Y%]`1+GuG!Xg]ۻӳmNhEZk}ZV'lK8+6 ::- *qk*.nC{0} sEKZv-knwM1oA|/~K- ~5_rPNa [-Kp_`880Y.x޶+VS ⾂#" a *n7`oWK $q/YFYB95]hx@z 'J$cMrD>cΗL.@'rl3rbGpt)!cFjrssmfHS΍~؄9z^=xMh!&]^(4!˹E3ߴ"6a ?wAx 6Y*#8HX06;hm\Rѳm-6LrVgTٿv S8#Rl5! ?n߾jݛn!vyBҹpu# qjlٺD5}IoFN'\Z8K9 lO/R)be-ӒAg3N߳zBC/iO35$%mfМ{s3!7]>Z^;䎹Rf~f[\SX{kCZ;w;o-sUdy +:3ey TxHWo? 15!?{XـBz/ϝP_{zG~CL,Wtm}W=l6%6 |z2_ R7].zQ/ v%_k_J4xp.7;;>?>c ȿګS5 @ @@@ A T"㲗,?&t Jb8Tds D&c@)EHt#.[BxL\ \;<5C@7A6t)\*9D;d/<껻ŋ%l&B\CTD+ԛFCR, >t/lB (>H Cz?1534AħzC*<ƠjK۵;q3DkDW,D2+m*q1(:G; {<[?lgC*1% DwFDGǠpY|2{3xGdtޘ***GC+hi\83'|HOH$ ǎH`+z+HMVIMN]AQhij͉kl]8feT"(4CqQL%Wysɭe1Z2!eu²efeX(f_nef0C4MFg?x\K ew.f)F7 :Ms~FQhG?vw1y2fS(]d&48 HBI ?5f2uhb aC+]rN4ș~iiiQFahHHh~6k qkh6j~䅎(!dJ&d>vjh6/ <i$iNhjQLSkrnEl@k.聆mSA_T(& |O_'Q`~~P*}:BSmX@kngS[Z,9#6J+Y=Zh*ξNoCG7!zeoV+l^e'7YwU$lauprPd}idNLF qJoP/f@?(`c k{pW.T+'*NZD/o2E(:W0ktP?sQԡF QR~lPfuƩt2jU/RZ&Y_$6z2&*UʄEE+r긢;:T+SH &A~6+\6KG wZD!&ŌIh.SQbe}yGiZdo(68,U,#hC_N _(@.C;Qyr|3,e4WzStJ\0}-^,4T"5lIQR&diS*UNt )If,Ijɨ[^XQɚTnD )H`H k&ԫp,><:֍tfFz0^l>4J3U\QVžq z5u.ˮfzU bA-q5Z6`-.Yl;V܂Sffj#1H0USv[^$Zw܌MΙ֋6.["my;f m$;p_"E+l c80; |YH ;r._#2ֆ8:1{8F5 D{l rl+c9ZrC<=,wD{Dd2iQf(Nxl;9z.9T:mfx=N,+g:wϒ4+>bvW[(,>ޛ Ѵ{t,WúҘU2[t:mMVV:~V;VhÆ'ZJrh:lYݶf{;܊6P j4ڎt-1q/vG}uZGcԝKvKݎM5iBͪQx.?[?ϗ9 wyΦ?vM:ןdG_2'zq`M]/v}}5>_7sm;ߝ-tX{N7zu_6;>{\Sj΃~S?gn# >i ·έI}\KIJQq# #% o;R$hD@ I< >ůTd?l>M:T=Կ)"m SE0_Hpoߔ`I ){H`Hf 1@E YH P`^yp` S`b f\П$H2a# NED&aFǽJڈ j!h azHֈvɴЁ!! j_1b "Jk ɋ!Nb`a'XD{]!&'"|*̴O **".L) ./I/*c3~Ā #Q3b 3Zc6bXfц.j#`c9cdĜ 8r89#c=f#b5 LF!@Gh%>H?b={ST@ZDN iA?~f$`d WIdGG""DtEƄP\dMNLv"M$s$NP$C\5*=R"EK28vAUGQN&WFdVVHrYIJ$[Y ZZ\DVd\e=%إ_^= uebdABf3.4d6bj Vf1£Pcv&qpfiJg e6^j6i¦ffIllfo]fYfpgqp"f&ɣkrdR6->$Eg$]aZgx*f,b!$fng{`vmw|:rЧ~~ (gg;ug*:)ng/5,(G]hBhv݄~Kj[z(Yth>zth:> [ gh (GhibĐ")Ѩhh-R([˓N\za)hpOTizۘK"ݙ>Ě鲹))qi [ʞFz 8)%L j6ڢJ" r*Y`tj}*ߩyzZdž^Z餪jN)~ .*jjV(ªe*kְnʨz'2zj`jVFZ+Rak@+Ȕ껅+VkܸRJbN++0jx+kVҽIRk,j+[qckkΉ"+V\N,~ź v朲ǢDvlʺCög˾,t-,,l*ȶI:hiRÊ6-,ǞV*bzn-BYvJԚy=ʨ۾m1-pm+m|2Э`2nZnVrn\L.nnz]ܖ,hgĉi-Š=.Df.nIBkڮn&.{m.Yo[|nnIkJ/P ontXoZ[! r[D@G70@r /1p DEr;3Fct.a!( RHCq_5ðt+S1BgmİܴVc5YyZP,4 7Y QF h{ETjp@,X10qY t{\H1+ڳڑ44[,r#;һ~M{~/BOz HK ҫ2GP>+Ǿ~~ 7`l| sCzhGh@(ٔ@ N]Z ^nP!Hؚ"tx˷߿ LÈ+^̸ǐ#KL2b73? @4^ҥQoUmz5JUf o~{&iΛ{Yxٞi׾]\p;{.: !,a_22BCM$ KLW,,8((4CDN..:33?abl@ 00Ã0|HQ!F0=~KLW흝'''C؛),,8v1:˝y6:t:((4_  w1o 㛲Ӛi͛NcccCCxlz7M///rAx_Қg斖 x#no;mmCk&&&_m&KKKCDNҵ.ҘdN..:rO.Қhmmmr//Mtҙgq33?Hťvv$vvoқkCCײMTƛ•[ ;t_ ablқi H*\ȰÇ#JHŋ3jȱǏ Iɓ(S\ɲ˗0cʜiq͛8sɳ@ Jѕ"*]ʴӧPJjԧիXjʵW+v,YI]˶۷pJ.Nx+YKÈ+^hqŐ#K_ ̹ϠCStLӨS# |s VM۸ޝ3|+lfȓ+_ ?KkνyOJ끋7Ͼ@a4!Z.K\s( c5d߀6 6I%(6CVagv8(∧]h O$^*lP06BHN<BiH69NF))TfZveV"deh)aQ tǦs(֩SrYR&(hD袐hVJs0ɣvzѤ*W6ꪬUjiꐪj+Kv/Z>&,ڵƦV @Z{dAD2d{`ڶ6 P!7+/:нBA +1c` w, ,$l,0,4l8<@-D̐4f@2POY9x5(wE-dmhGw4 !T|߀n'x9S1}g.k砇./C(00 ;׎j縟\?.MknZ̋#/WoB}ׇ/r~C21(t8owP+XʴG.y/ I Mw Z0h0J`G(%9d{p&hY c2lBe w'6dyHDf3|YP S!C!.#A X6+ - 4H@ȘF*E8f\x2la4# *0@X!D.l#x@re#( RN@%9` H(ɲE+K#9X %0/JJҎ84^fx! <HUq!WtH*/-cȠ2nzPc"?1I'N0Sl9Fv~T0($@dLH t[<0vl@F_8 m0ĤIqӤ=h* z:YP(< M.SeP@h갚P5͆ vyFrNdFapNe ˰tGR)L{Ћ3(XɼͰ:q`8C98S\0P1%=U?%biZ5fI.f>өQn4ՄT!, u5%ngywfYqiLKړp"Lnq=KޭT B:LJtntP@D7Ё8-qQѽf'aEfe]|&A弰Sȥ3K'V! i,ng" )C{\tl_*ֵ=r,l"N)?I5-rWJCycprC/[ n$=0YŁyhg9edldAɨPJ$Ç@$[:ec".Wy#,&a[04ul|+q\/MYƒ42QH*Y"Hf_P]զJcpnath,_5C+j[*; &p Y)@RXuݦ~_sې'_Jp(^QyϦNyakJGG^I]$pPIpVibTuׁ"{@083'HLՂ.-3^*3[[279MF1M=zz@`6O4SG5:M8E 00 V~58(b <+ ss_H=wp_wІt3a8xe;u(Aqh}86syxﱇCqLD9X?S0XcS(uhh(؂lc(.HȨ7X=xO (8ט긎!V0(Ko` `r@@@ȎȎU8h UP@؏p H` 9U(hU Fs9ʐ B0A4YP q K~P`Q66qaR)r葔 LpX |p0G\ٖ`p0FI;nʨq c Yf|hXH .F遘Ah 1n@x2ycxa  UZ)9QtZ"SyC)EƉΩ-9ԜYɜCɝy+9>9*#ry#y$I .ʙٟڠr JZsʢʡ +C&zQ(,*ڢ0_2Z6 4z:D<@z(A:D>ZHqJڤN LR:BVz-XH\@`:7*dz0jh'lp:*tzix㩧|駀:)zim騐:6)zi詠:(zhbP(`<4낙6;B[BFJ۴´NuR[jBV_Z۵Tµ^Mb[BBf9j۶.¶n#r[Bvz۷~+"{ӡḐ;!{aṠ;!{a|rẰ;m!{^aTO;H+!{Kɻ+Ѽ[ bkԛܻ۽k[盾{۾ ;K{囿ۿ<[-k < + <աBq L;$[!G9|,) l- #,+38ô< >ìBD\Ĥ{H JĜNPŔ;T V|ŌZ\Ņ`,b<~[fhN{bt0:\~,c9JȁL:yS\;p s<<Ƞ|9i 9|+LW 9p ǩʰ].òK ךmb!|.yE1kڟ#(QڮE]ԡ-'ۺMгMܓkܿܐ ;}؝Tܭ>;=͎齹pmMk}m] ]-MPa ڤ M> ^٬#)~'-1~ۙ&`1- N=1b;4am}QMO2C݁_-+Pn0 Im A+흥b@YNn!.A.͚>.]磮.~>( ѸNFqz~~豮~~/~PN1;Þ>>~J.VYNGnI~n1爛*ۓMM a^NiinL/!>K(_N/Nq>*n9/~l)*1B_&  XxE긾뫍LOL2O%_S^/ R3k=@EWDqfoMcQ[ gpR2!m,@/]?/œUUc.N"nf/K^}_1?w_߼_^>?=o_z@@ 0PB ,C-^F=~RH%MDRJ-]z(pKhęĕĘq&NC\(%O1U2mT}Jl`VI6,jXe͞EVmU }@AUkVzR+VEjJ{ zW:kҰ㾀_ƜYfΛ a!$ oQh[@.j[d䒍)|4׼%'Mqp%6Mp򑶙 k\tխgθF/(.w !P!ןt^vnK8޶/=[jx?dAKH;F. . Cb);>"O9 ,E@KFLDPE2H!q[4 t\( B8lr.saHzI|\˛Xlq?2+l͝LK4N;J .ZDI(9λܔN\4/!G RQ2RDcSQG%uH2P%9RtRJ EB69;L,tXӔ]eYg50&<zeQe$:9{V;]]5wF dk Zًf:?{K ܄ݡmK͖jp#mG&6޾[o'w0JT;Bʍ;w=twDpXztF4i/u1bf[ڽ]p={3 kP@#)}~/{䟾MpsKu\nGπ i⚓Anuo~s羮~L_Da 4D{ 6kk '83KN KHЈG2֢hCN]~@6/o"8Ɛl|TaCY@E,a9A(E'шK0ꏎ1!]~^tcHNr5C&vml7)HZfI=Je'uyȧxD$KUjv$9I]e]VC F!f1&j$ Lp$5Bl"@G qSFC*iUmΟtZ)Mrӏ(/bm2C9F*Θ^($ *PQ5̝٧0WH҈ŧEGq3G&GoH2B39 .E*=SRnAbӡRgV*OcG4]G:V}e LI>uND8IR$THH4Wٕ%Tj!T/R9%h3m-9j\KvY\(*jtc]K:uŀ>,wΔnln;1SmڪV6\ [Z-|JjrV@.7dkq\v/j/k;_Ja)ޏOocAf^1wraZZиpxݱwrLE̺BͬuvvpUܶ%b+-rC.2F3W<䥁6.͉%wƱtŚǶɕe 3_V*cs#JeY'İf\"hf"J8V蕡\D Kto:BX>%/#.d֩݌s2ִ0٘>IG=iV( sE[ެyšODMvY@-a2Zۺ6om3=HТmldwY ,l@.)GbS;ъ̵n.w^Vߥ-[u?8JT#v%n%U pLǘ n4߶':5i!.30Oܜu|VFgE.t3v^(+CrJ0 1.C< $΃ȩNW_R w= p P=r?>Lo~(j(c9sCb>@b˿  $<ße>`#6+<,y? [k*: A̸-";z'1òAkLIL&e'\ Ҡ+;';¬;!TH;9-6dK5[C5|. B!,BC1(ǣ&@7Dį)@;ÁA>+ 2DCdBQr KPmnŀ#J S^-Wsir\Wv^@x]LyEVzW<+=}e-lX!X-ԩTkM}S0UL>7ݯE׉hֻ PeթE}Y=YF&ҞW T--Zk5ٟe=ZIH٤}ҔYMmy؋Z] VGڌ Qՙ]-W%ZvR۴]ѹ#M3 YA^ROER7γTM\U\6 U$>%pJ@b^4\.] @aaab ;6McB]<2Ebƚ> d|ޢB6:Ieb e6d$<^XY^ {eZ]Fa^`fa6cNߘ?dvgFfJ ahjeivKkmJF InqY #ufgR@tlygj.z|(8phD䋓VHf艦hɳ1#h|~9&iF.Vv1_~陦ikei]z5j@_FRANvjRy5g~ꪶi8jjI 6khs >v?귦뺆jVg뽦n lkFb&kvޖÆɦl#WzN%wun'm)rh+rc-^/Y17sA.3WN5wsm7s9sm;s8=?t A7t>DGBWF?EFwHoCHJ@JL>LNҭk.޼zҫTn80Ċ3n1ȑoiaɚ7s3Т'-ԪWn5ˮm6ܺwvJ7‡/nʗ3o9ɣSn:ڧk;7so<'-=_>g~? 8 W * ` J8!&=X!j!\!!8v`b}H"5xcn P!#Bʈ#I*dk)0"RRLj%]$UN"5=吃m&OiP@˨@'"f\q :($V%j:(fe?9F6*)z)/袊f)ꌫ*H+Zᬷ++ ޯ{,,:۲J;-E[-jصz-uu.+ո窻.A.Kһ{/՛/ٿ T(6qFRDY-J"(JX M)-qW/#.FMynU204%jLщt$#IԜ ;!}:vIrA%MZd.E AkT EP9 (*>jml%.i\2<%0a~e)aٳhfS!P+z-ݻx;>l_* LBsߊ]8j#Kl˘R̹s̠1{M4Ш5^zsԭcڀ۸sͻ Nȓ+_zs}<.gw/o觯췟c Ӥ{?޺WjW /_Ҷv\f7@p#-@QE2Ar -B)$ E (ɋ 'BC8̜ŠADs< B$ T%'1M"2Ickj|bj5+i%ԧ"R0`UceEdHC$ +eZ"4Q#pxiXKD6x!%-r#l!9,a4 h+O$S)[I1]ZT0}I4b"|l:c,AͩQ<@ piie1HDe*Ɖy<_`YB"3UH3F#"|u,X1]+1'ZY([*!PfB},*LFUf?B)Ē,2)*U V[b,&勢`WH5)^5e My*0>) ,5VZ]O5"=YuՕBԾ*;M25j06kgZp:pv ay}63vE,B\ Ld-V͖g U2mVWOX)eSً A8heUrZ[mUR`Mj]BZ.-"4TE̾*jcH4jňYۉ#0{0_3BH &,/*(5BHV0i5ReJᤍ$x"4wc@]#瘇E.%$ Hv2&KYse&oTחmd>&f,9~|3MܢL:3)>D xIbģ?3,+ڏē0HM'xy0g$t뢱z2bݬG r #-l֝搖5W䭥C P_vQ}涌@QV.q.%KH;N%u. L3:mNOk6ikY@F$O~&9:GΈRִE 6b9ך#qE'0qdMI'ʨY`R(2FKŸ`2hΣGfyw3:6hHZp{[:洦=p4]*]v}oX aW (_ta]w{3v faد빬N{btN<+޺ER=U.bu KoQ^-տBh7^+[)-ז [:7wCP@ n jI x|mܴDR~b|A~;^ [դ+ C@_oq޻KOG]@] g^UG^v5W_7H"u4md^t0uL5XavA'EnEVve4'kւ}pGkwpR|^jA6af?hƒ7j;&bhE&@gtJC/b~eU6fITfc#ADrc8/ĆC3tXvxxzcAV!@x\eWdeChvքvuE#kщ,(FK(B~(Hi )7FjQROfHf+'|(64(xmp)/"ou\ȘsbX[3|6w4"UuP[&Kbq8S{R+刂8Q6@8wKDM-HCTLv25gFsT[T*vx(NkvWwd%F\"Ņ(fE$HuTP} 8Mq1'QTueRF08RDEi')5'.K9K,hjVeD3iŽD2aFf˂65f(mHb2"'Ca|evYy9KԖ~9YhQYٙX9)"6!q.7j^'#tZ艘`dn7GF)H7@3~䃿Y`~"3@Ei%)iF~3jj)'gd$3养EFX;کp$)8b)fUv$B()ZdMn붌F)wN\wmnxo۸Ζ2YtBٔ.B zy)"bq%qu)XQe.uHvI%z$Q&Q\Iop'KHufIJum.V'Ta*yYzRtA{nn7vw']fU?#iey[7wiLNT SzW p/5Xzz$uy iz10ǝw\H G\IwjP E/Vg2GrQsrr-pT<|%j͵_Ŝ !\PuQ:[U B"p^9KM-OI0tI }Q0zEʭځH`v2o:2JY٬ũGfh$fayZ:I]8hha"1zjy{zɘIQ,;3+*ۘ/)649'=A8D8C{a.([ಚA6SybZ X7tIC ;NYhKa%oU%f)FZdij; h$KEFh#FH\9&מ4')bpmm"rV8m6$VQ ڣ*`ߒCӡygxuj }*%U|753 (J7jqHq ţ3[JHrȚ\yַۤKbF .X Y;vԥzyTUg.\$ҦéL#6s+Fb'0&yty@`::y@(%zl\j+3*2B"ꪸ%~+w~Z:|>D)J\8,;kmoq~sNuwyn{>}ׁ^~!!2|"Rj̩G\Aͬ~h (4,.M ûI}[^y4鰭Q-ǣM_A6y?z4hzB.z%u%J^N. C=}/w[>ǫSߚݺe΀Py_N`\\zN(%2]EQ0(~*eo4rq/%2_IaT !VxbR eWW/#f 契czO2@Apd䝗E2Z&vŬEQZ$p.>lJs(?Ő9D\-u[Q I#NM^xTƮvѐ?,ןo/o寴O߳8YBb2_εgΰ@@ DPB Q"ć-^89ZQH%An4RJ-]FlSL+RbHC"ppJ6$X@DPX# OP곀QQj >ƥvխNuBWނ91;ӧd!xʠÄP4XZfs+Gl+/y=A G^9qЃs<~t@^-Ë3t"wQ._Aj.)C,OdJ[1N9 \. QQ0WAUбJ 21 5.GP쩣XR)r"̲K/a2̆L4L5YM\K 8O?m3PC 4PBeQ5sQG'MH$TM7SO?5TQG%TSOE5UUWeUW_] I+/msV[wU%\sMWa5W1u%6Ya YeY*ZGZk-6\;u\4l2Ud3 z\U L]tK _qEwA|SPEu镰Vw/K`>o&="*(#C#K1j-b)˔TL#fh 28"$ ɦ*a16Oc82,|DDW;z(l_lAΈ4 bbn0X-{oݟds|@*빳8ܺ甥;7E"?*p*_q2+d3msH3.)< xKO,1yǓ{|hÐWo#Q*r]Ɠ,jS9UW=_|H"2Ỳ v@)z)`%X%`K*XfЃ+ M.A",2a UHꦃ+Z8ІBRx!;a}ш⛊xD&%6YbD(J&ѰT={׼DŃ1f55zbKFy6rCe/MELd朠*)}+d͔3H$e4c%_6I c03MgZ"f(qVM8uMl*l\GuBN$5ؘj=[-Iak MN糴gms4r fS>{hB&iG;3OՓqPX:Ev!ЛJBs3jg|^C! rv_6v&8i4y_KIyEp@ =JOkӦXƒ@+$9*:N52CӰzJ׿ H4hJ*Ek^ ļls 2q8)l++&VM $;YVֲlf5+W"ֱF\_> Zvu-gOZv+ EZƖ7m'2[܊KHJU]M'3l~ $suvKR$4Qb0"fpHYt[!$y Me/wSE㤯y<ו|-vIweDp$h,Ӏ8XE7IHj!uh_@ wƽcv2_, [Eב-%/ZMvr|([ U۔w'k\֕u2\W"f.]QsK"vm` w0#e\΋3ƹ%%҇ 6r5LIs^N?!}Kj; hӬuJ*|< )d0"ISmI$`%O9yUꧽL]5=!#ZsD1w5noہYGx YVvx 5MfſqwAJ&˰Eм`uXqhM̕.guEv.-u<1M,2$FHK +Ih+,tv@G%Au*\ʙ]^.u-wUj&߻L!=]E9vMG\8[:ͳ+p:5Α> n!GZ]1z<'7.{":}42C5Gb'!;V"7bN!j΢*3R~: )Ֆ܏Ͻ n#@8Tcĸ $2t@$7@7,D@ 0Z:H8cqjK>[A?Q"": ¤&$>@3wʺ$BZ$+4!(1X/霸1T,&FI/c eZS$˴%"Đb)JAzB>O5(5=RSһM>{;T³?5Kt(SݓX=\=hۨ~2V|8,a0CC>%>b=>IS@Ed 9>b|qFj0?ŠB1Dw 't\om\A{UNj~!7~$H$ǃdStȇȈ,2즄Ȕ0Ȍt"7t7ɑH,Ɍ@I+'R./}1MI<ӃLS\Sl~DXB Ȣ(ĺCl:|$4P:AJBXKN*Lڤ,12TFU4eLJCd"Ӂ j '(52=TRNKBǺCa.g)LF0|>&|5Z25?r6%*rVS;V,{SL*ס s]AuEAv%AwAyzyHS2}} x@@@@@m@+=uV=@B_&T뱩펝,^[ YY-S0QTp=YXYY،ُ5X*mقUDsǓuY%5UhcڑZӵ^-ڏZLYFO퓊E۵Yq *D G[۲1ά圸.@ДX6hR%@MWR9y\W׺׀]ӵUݪ,]}m݅+\ݎK<˦DW ge]$J9f]AMrMtNt]643DՊM ͠EEZL ,T}2O|߫ E^_&ِ"_]j`dMhLf{\ɘU=M]KT s=#seRS۝]BsaE≸]+acO*%$0[DD$,0KA{T G^++Ȗ=Ó!f DD&D4ɔFZ4|  dE[jU,ElN<~M\[T4ภ[g>[YW5fg| OYTK=@!.^lVۜc=a:̰K\(zq /0APp@ p,rlrL7ͫ2 l^}4Jh2-wu?i 7kJv{tJi'ڧf Ѐ ,6.MRnd/⊗0Zsc-wo2d0 T#% 3}cʼ<‡.kA,-_{~$` _-i#0x0>XC*'H@ (]Yt( bR(L W0DT@!,1/22xAxtH뿪BCMߜ$txtHttHtHtHxtHx HHHHKLWHHtߜH,,8tHt((4tHH$3HCDNttH..: .M23=33?_ablH*\ȰÇ#JHŋ3T PǏ CIIO\ɲ˗+SœI͛'eɳϞ: Q~@Tӧ1fDa !(Au(VAM]1(FT?@4ܯt M˶_n/҅üwk^#K." .lBVz "bVJ0Lь| y+^,v\e5@Y8xY񯩕`u.4c/ ޏHvEO\3`,fw~}\{NIB WUXvUHVꝅ$"U݁՛UqV!YbvV@.cL9`@{=6 _?"dIJT~SVEWb u d&$fhlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogwo觯/o? HL:'?Q̠7z GH(S0 cH5!wp: F0`M,DX HE 1 t8@(g+>p[a891ḷ F6`E0@p"EC"xXS rc`GNq K$шX:WdxHьJt@ IQ3d3e/ԥɘFhrx@*Yn g@8Й4=K1$ XO~ӞɹXƱ'$Jq iPzڳԧDajӈDBQj Ĝ@G(VR7W:і&KgRP4ͩ8mJB)PJT HMT* MJժOUծzB E)ΊV6m}c8+SW)Nʔ"peJW,c0 wVN@hY l`NA  # 0!,1B22xAxtHזtx׿ߜBCMt$tHHHtxtH߿t ÛHtKLW,,8tHH((4HߜH$t3CDNttH..:HH23=33?ҙ߿tttxablH*\ȰÇ#JHŋ3L PǏ CIIO\ɲ˗+SœI͛'eɳϞ: JƠF*]i"(Pf Rd5R30KӋ4L ,+w ]w݋FkUM8xݸ|'>[J] pPػp`U匸aŰHU>a*Z@;ވFBјNV쏎S>Ąrd'ں{)6\q}׭zS|X[Wx^%Vv`~]֞ ΄ EQee xBL'TL Ui祧"7@7"L?ibCTLdPFѓRViCT^`@dihlpy& t x|矀*h9Р&z裐F*餔Vj饘f馜v駠*ꨤJ*ꪬ*무j뭸뮼+k&*6F+mNkfmnmkJhA,햀@jx@ +Ϯ+k򮊰@0 3’*O( `zp%L@>Q @'H Z$S1z |%(|G\! aHڐQ2 w)}H"0&H*z.Vp'РƸE/ Lh5VYG1,( BM0 +P`$ ̤&8! b@!,.1<x22AxtHߜtttHtxtBCMHHx$HtHtt t_t CxHH ,,8HH((4KLWh $3CDN&?..:.M:>ttxaVF H*\ȰÇ#JHŋ3L PǏ CIIO\ɲ˗+SœI͛'eɳϞ: JƠF*]EH@U*"PhztjQ,^=V!g•YGd[ U<.޷'&˘QvX L(L2{,ǝ?m̸س *..|.y{&n;sݛ3v΁ b6=:rXq3=0bɔh1]ؑۧC'^X__ 6[hOF[dyX}}@6w@E_YU4eؓVADk89BiZ2G%PBDdTF9eX*\v`)dihIÚip)tix){矀*j衈&袌6裐F*餔Vj饘f馉駠*ꨤjꩨꪬ*무~Zh뮼zkk&K6F ,VkZKmvn+k*@  *š~گ++k" p KG,*o /@! PA2sk/|=h`?'}NKj\O60Gi_]@mjqj0X-]^׮=!vo/dx؇C - t{Kx4 yEOMҥN Վ3L * 6g=ɼgBrҖ!jiW[ /'ߏ%U/~L H@PlF7|i AGHQJa 3& @0 gH҉_ m@HLc8/ KH25K<@."q.8F/h\!\ "8HHG!R = 2 AF2x@̤& (D L!),XW 22xBCM$ _  CA,,8$ɚ.(( $3 HHCDNt.Aj.MKLW[< 33? (;Mabl(4"F't ‚ 0+Ul s̙jiM< sd r 9jU`H!0 fZAfG0 H` BA x`D`V8a0 !,''''((*)+*,+,,.-52;4?8=5:5835330011211111122222222222222222292OEfR5(" !! &KRTPRTTSTY`~g}zߪod]UKF=1${obUG<()Knwwwwxx}'98($"j| ks hr gp _h W_ V^ V]WX[Oa5g!gf!b)Z.K,5+)##""!!    ! =!L7_>jFl:q'"37DOZ \OJKORSTTYan u z | { y { } } } } ~~9Vapۭóژؕܗ݃};H*\ȰÇ#JHŋ3jȱjCIɓ(S\ɲ˗0cʜI͛8sٲA67IѣHtCA2)JիXjݪRρ@k Jٳ[:uڷpʝKnU?o˷߿ l È+Vޡ_nӦN䳛H`t9ZCMtkʭf;&2ͻ5QwP=5pϔ-/:rfw}AMN- I,2anP(k @|3E4Wgt,jB'O@~xtлO-QNrCB%P X6@Эb Ĕ?.aZB/d ]^jw.RNe1y B'8 SD ܵ$nD@V( !qjJ,Hv@)E(ѥO VBo#LL/"k[2 xmR\ X=QL޻`$7Ib (lV(#!(u4*<x6DUK1ьQ΍Zֿ7Qr<Ȑ^e/H%^#dȽ9 q `/Fq&Lr-0bK1E n͓ 'ɒKr|$ 9JVE%Y 3qr5ԑFQGQ)$RO*"&e %+!$=VLB`p㲚AZ҈T:6z6KWCHt \SS[ U*82R)0񶰅2%edKjPvIҭCh :W:khFb`t  MbŨ^@,x 715 !=e8Pd9Ӷmmch?1kɶ Mekq Tr VC ŚhV{q%atE2tvtդ]ӄW,*OUMyrź!cdXYZ_čQjV?aDolˬ7/lN"ܯ`ڟQ'R퓉+O"ðrJ;+6ۙ$aoT[׬K,&nʺ䔷y|##Ai{ >V @p_W\j }{[k.*.7g̪t\7QJ+g[1rDȡ]4suv uvu:$i XmuOd*v0yDLeF9NѐQE!8|X'aU:u{;W&j[OC}i^bqk{v=f^U s6-cIx4Xt?b"xj5yֹ/mq -c:p)\!:[4_VanmHmz.Û ϩ!CHv4jL=POE|*ȥ!&vm)h$Q7}@_ЇM;3.]eT'7:~8-"1Oc v?eD//c&L`폿09w{ ~~ ` h gv7tW}!X%(' Ѐ  2H68?{)wRFxH5L؄NPR8TXVxXZ\؅Txlb2~~587)CQsl!ChI|x'^8Xx`H1 /h jm;ȁt職)S\ч؇Q/FiL 8OR/. Ku.TSȊ]",Ǣ+[5Xmha(Bs3-#X&F#`\*S x mxݨpkXHXKSkSSӌ()RR3\W8Xe"S97kI&ƅӒ I9Zh?~~yՁ>g8~hK?^ɑ_2KCB7dis㓻Xؐ@ՓH IWɅJ<i~ ~gXeḒؒX3XAr9$XxԢ69> HhOٗ O )]r7 iF97c`Cg.4`+-˜\ٙ)MR y:_M{7i%c8{9+`[]y_ɂ y)xx.0 81sY٤DXI B4EyOctÚĨ?7dT 靏yodZ+Pdit#Ğh֒Ot+ 9iǹȝxOjjxٔ Bi:B1u,ɝiYaY)16J)uf*6y'ʡƛ?t6?ZC9Ndib cI +#*R.ؓ-ʠb>W*YT iaNdIc0PJ804٣%&^H?@hI\YZWj]XSI :K>{dz5Q)Bx:dz=iL7.JR-|ǒ: 5)6aF&8)*O9i5 O?%ZJ`I bBOZ7c ڦ7c{ ,5Rë(ɚ,:\ jzI*4d.(eg^0WO,s.Ĺi&r_h{&83٘"5Dۯr:iĵYښ**8!?9 >{=_m{/G%̊P(,Ag粥13k;c[۹5g+Ƹḏ3s ,Z넾%;},[m;o<Ѻ5M;)A=h[3kJtJEH{蛾kǃ Ž;QҼ껿ۿ{ڋv{Q[eQ  ^^?u\7AðICwU l| KQ7`,A|Rd\+Bh\i<8skliLFklxlIdlJLH=||O|WKvULs8lYpat@]vaԩ$D]^.؂=؄]؆}؈]ΐƋ}^- }^͠^wٜ٘ٚٞM ڌ$ J&}(G J 3JQ=۴]۶}ۈ؊^^kP ]%} ȭQڟtڑڪ]K2 g Ј-` =` P --]]q 0_M}P  `0=^^^{"^ - P*N ` ~^ 5l `ḝ>ޝ^=z90Tl˽\^{}Cн=}tmNM z}wp,N`  N^~>r^^ =N0n.HNH~^봾 u~^춞^NƭႾ~^Ԡрč^`>]s=5@/;_ C/.S^ :p^V~^>m\kӚn 誰c@=?=k/~fb>p n0q,m#O(?rp)-_&5s.*^>; M>/=EoX> ' PT?m[<^x"}^Q@ 잾ƾgo^Nn0oOܟ/Ծj <(`5LmdV;3È Z9UBpH ]DXe<E&$5xR'SԾ1ETP!54st4k<6kfEVZm!s\uśW^}X`… FXbƍ=Tdʕ-_ƜYpΝ=Z2[%CZZ4V10  mg29!ȌWJf~FݳkCMNr)&H͋&eR6A]}xN Lz9{M6덻4bA4&"dS+ ڊB z$)렸F$DJLK3WdE_1FlFo1H㑳f2H!lf4Pc-I2%;ɩ"ɢxΫB ,n*/I/\Ɏ.$,?TJ)4r3>8 s!9Î$k)>2s30/Azr<0DPD5UNTu_l<ڨV[okN`W_Wa%Vy)g$W[ 61$ejڂ=5Sۆ*P%jUHjJ@o>*W8v-mVjӈ=? Ss^BE͒=]ntoLGnތ p-T ԃr0RjXU_eUgmԕן vhFڮcIs&/hkYюbPvԁhH)Є҅9(*Uԥ/iLrQf"iNR0$K;wԨGE*(?˛۔%v$7E"nI`,81fS:Af"h+/़[Äކ*d 1ƩB"BUG:fVX2Y*Ji&\f),m/YmFClKdA?+Hn~/w_R^Rikz3Z<P2HJTo3-727tHSxy?1M,U;:i0[3.d#J@ۭՊL 9Q<@;R ,@* ApоYkA43jh 4577? ˿¿'ӯ1z:h<ɢ,*,()4COB­2s8L*ݢ01D0Z5R?6$7DĝD+=4+>lB?$m ĜI#C(FN+Gd*H('D@CRT"M*OtW)P)Q(RMHWH8}JEUF*d b,Q2FdƠZU2ggTơeF:klƕbFgheFkt(iFeSAU ox sHթE:D ԺqToЁJ%սQRũ1V6US{ʫ#̌\e |5`a-Vg%Dn0ԞVd P~عnROXjȁfOQRSCUbR՞bՒ׾klOPUVG}-fXI5T`AMdUgnTԧ ox Ts Wjr=YSU#vuGwJWX =b$R'&f ёlUyXK!r`[XPN]S h^f"ƕ6g8Q} >)otKsd tNaN @]`&3.4m弄jˆW]bQh.f$L @E|B=Tk&XJ HJɉq$Nʠ4lȟg޽1Q:vQ`214'&Q1 Xj-bbPVmbUq"(*)rvDnRhl&g\Ȍ4J>GFN$vLtȣ%~ާJ6 'Y('c@\^We|e+ & 콑#mқenȜlȟoll,Jה.dDǖI!򝾴%v^"ܖ\` j8rbaS6hiR:T׋̿Hsrsqqs qtk6l6olUjä́Gf^6zFr^mOCOpťhd&F4p3~ ?s7H5qn@^ gH2p4'LU^t'ٽ}XM>CDJ_b&Ir'6%̺xtP /i~,uos:u[Z.XwslglzgukH';lq]Wl:fˇپKvmPd`ŕĐt%B̛ vtPw %?JY׋\]^_%&r(*cg^h!G PUhXN/#tyQ"?yD˞&'LBy/SWz(KdFWhom<\`Ipzr$iGW#>bl,xfp_UaAY|.x{~y9}i I'7òMy&%̷xFעO{gx Lk};B b XJumH,C|5pgҷKg9WJhr,h „ 2l萝È'Rh"ƌ6㦐"G,iR$&bDJiM-_$I$NwIqS6u|FC-^UTGNܔtсL+n"qAX.%*vTo+fZb7fLj9dJ$%]+1 }P6tn9P;<{]t <5j^]RdD% } FO!_Y!% [1HP{^!Uu}mrHuuqi5k# ώ>#EH;iI"IJO.y$>W*y%]?)ey&KBymb 1qJt~GMN'iQzCA&aTG`"hQ^U} DF: -)CEPA *\ d(*Dc"v\~Py#HٯHT iv+#e1lFǾ  /ܩݹ+tS#u.A gUTP1(*igjA"ք™[p덖:c$m(k'Oi62h!,+3=*2f.Y7 g&d3l贋KF4l`i ܏ 1-Eov3*S4<6gu}+]Iu߅xwRSѷ^"xyIڻ^-pĥrʖF,H)U쨲F7;M-fu6bt昋Bw|p6!oPw+fFٴm-eW?5j!J>j-b(c#@mYϜ׏i,h/ c`1 HAU[7V< Ld:q 9}!esPE1='#Frc$n+yEpD(nF9^YdY0db+vqY;N{潍[;YF,n3A^趂tFr4Re̊F)/q(fCv5AR)EA]4Sd`)jgn=0?lbi;g&j-3H3v^g6lqК"W6gV6cZ1ꓑbV]5&ݓu9W @ϸ(Kh\;*'c*C?Ǭ &GFpfÅ ScKt@밇ͶU-]V( V.Xނn.q.FO/06%KC9$VUJ*\&"BqH[,s9w1cb˾jI3aˎtT$H!WbsC] I#R֖h+-OX-sЅ:TY +iT}YYls4zAJM$.Ώ뱛6ݔRET\Ӻ6RamAxLyrLj6i[@jlDfu]QX)ډ3]PE^Er̴Dw<Ӯ%5۾6WL 6/V;\&O1BkH)>&@ɾ楡mCvsr&[>o)m{I$k݆ӣ.o<ǩ{ָ|C.I^ [\η.ws;C>w:x>_3>usmt,)>&3kd##d,t}8f( 2HzɕTZKe," W"^aFJΓ9FxCVԥkJ&%F&meeBSf&mlbALRhJcPCff8' .XNb&[ڦvfFnnaoˮ bT:UQrv^{:D,d5lJ}~f]8dwngvw:^xb&yaz%Cf-_%DhN熜Xa,Z-‚r#w(\(Rt2Yh*#EFXF ^YE~ΚZfS烪hm*m%&GehǹQǃ$&ViM*祰cs 5brYY(}*?~&F)^m[Ix0>eQq*h۩{2|(jn NH'a!RءA *ꢪ_j%*DpA\J.&V|n%1Mh FS*nv +n:V6nk Z.֙!mʱ. oʧbEE^hUdm()p"^] gnc"ͪ)b!kƧҪ5r~q. ?q0زpH0p=RF.r1iWO6i81Q/?q^1jq.&o#vQ21+b .ڨ O,uk!be珽s#0"VfF&\'g$r/ )f2Dn#fQ@:rF"1 Ehk000@2(ݰao3q@#akmr\3O8 n839c13g.cz*,F35OkFgc:@'@tO@30=Vbe<0(,re?s1~psOH@3I9tB?^Ʋ6s31%.WkFGG)$k7`5u0u$5ޡtlܥ3NJtгU_MӇNPWE/5 6x""O lNu0Cs+uW_`B+,L"*(36ݡ5513]geLC;sE6U5,6gtjs6jj2kkJP*vUe^Sc4 au6ZHwr[rqs?IuB+PVwsΛD-w7V;pc=yqz'61 K!om CN-B)7y<t *GH`quv776pWDa'n2a K7ҟq__iix0:6"imSqgKg%SJ}H.8Sn?38xN8ry tpaH&Ns4O4gوKfnyvl"p"êɞ31a/=/mt4VFroXo + ~-Jzl[g9\y"snDw$gyL9):z_7.]Xbi;Nh}}t{ÛuBDxx]$yO}Wm[h{q r-Vp[1gzcz)ۻέ ٲ'O꒛zB_<̗;J|zS|>E:V|Rz||ΡG}4kͷiDΛzo<_~3}zԫ 1뫱+Ck}'}}[{\|7'b=ۛz*9G ?{6͂&5z :}0U{33"\ogYou>\ *׸jO8~Xt/~TySgs5Sє2/ 1ۜVBu3Dg9O~B y=@t8`A&TC^18bE1fԸcGAjddI'Q$جZ˖`Ɣ9fM7oùsJ?MnJUCZ&-)Ѣ21ЩP6|1+C5|֨\; hѲkƕ;n]#ջW!Kx>|y]W|Ky澽~o fSߊn:;j-#3ڤ m )BһPú m϶ -FcčHBFH@BP6I#H R!E"H:QəDȥLď瞤h1~Ѻf$)ݪE-LS5'̐7)Jr94 ND(DF D& +G*3)G! H!sN%R+<6hclАk(IQ3YiIm]K?T\촠= u1Y}T442z5^kg[#w=_VTa $V4gՓkُtT2\t+qNm][oo|;ѠѪJ]U.iMJZ|ߍ9_ 9D.dG6w"\\Q: 0Ǵޚ}X/Ot֖3e hQc֘{ ].fL-\w곳 馻JZm|X m]x⥶D3}BШ]Y%F7lW nN)Z{$)\ +r\0)Uϼ&ۧv\xG!sGNswMA]ݎ߂nʭ7lQJФf{t1ZQB|Ct^5h'o~><=JnˉŽa)h9:03o)ber>xk] HвpHcڢ<-/)^ IBs0t h٤uj>-)g8R$1M}pQ\Z(2Bع0 M!MvXYU"BTED<;w\*co H~tb #72IaGZ s$H1+H}/.G?Bβh,%+ Kd!%~.Q^JpZa !e +[Ns-Wf^p]ʤ'8&9(vdqvw&'YL#Y5ks.٬6cM.s{i PV5AUNq9VMN?tePOm @ JS&HO9SaXJ$JWή53iGqj棶aE0BA ]؄PjT&!cyg8kyFq, "ʏ'- #(õjz6m4K 4'EjQ:T>noސ_#mG#seltg-eʮǛQG)olOO lEn ,L:b f$ml<$bPzNpmM\|D.ρe2B@^U4P",$ N ixOqEO⏵Ctn"G A Tp{E M>nt18Ebn |+ Q6 7; `cB]nr"O"f +%Fo*VQ2j.qU .?OHG0u8!4g|"(n.}^Ŕ%sBMӋή~qv%R!&)Ȱ.R ;9KtFS2T:?0KF9/$;B- za ƒH#ltO" h0&`!tR1$O^0C1OkrDQFfNMA)5UQJK7 _G&T ?OBF5NTCFU5Xo iCcSg&V$WIlW%Z/>ibC{TL4ДҨ[["?&;T\PNuZU_s51tz;i;p!^VXX!8YH /Mx/87u7@[ײbVfc҆_HKI|34NrjAW]KXBxu[!~iCn'+ge"47>wMs=B}3zոZMڲYEѺ&zt{ۦC$>K"k;-?'@;B.58$ºc;n;%$v{5K5J;$ 5V!AEi[%&z[:?9|=;I;PW>D|#:_fMƑ8_ݘ&oC,eJϐ:׺J;ཞ#<-':*b>>íޜ:g~b{+t?[ŽXK؆zXpwJDs;?{^#V^9b)~$BߞԥZ<=;[IB3?#}<~z]7)|S=ck^/lAR"{C"G?]~!g-ߊɃMU)X <8V$0ĉ*daō{ad؋HH`TbGGRT"_.7ŒɲC5t 4(B =(G2TP\3J5֭\ 6ر`U;{v&J36ܹtڭK޸d)O: ]WA-VUqU\\KLIPXaz93F>y6>}U&X5[8ՅQZݼ{;͢7r2K}s',2K:Bj:De~3aU|].5,N_%ErDխ/'>ioNO; #H W4k3"l ƕpR vɐyAP+)t8nC9V CoW˹h#iЅp5q!C&@pM]ptF!Nm >%FĊqbd@q!tN(YЌ<b!rȸFQ'X>DTlsY 펃]NFQ(j\HHD#+Ž`$T1ur̈$#\aӸ%5qB &IpHlv䚲X dk,"!q1"yDrfd[ rj29La{)BkU3&]B|neJIVxDK_w޺I;Ef']9_R=PMCP!nSbE&\39gi3ADQ'bF:'S"Giʰ|dDhZSk Zָ8oukZZ׶:LxV5ҨI<1vCQJUgX5@TU[͊BIV.U"xmk^WV 5=][kZU9W%թ'Tؕ4A'1*ϷyԱ:GǐJGjggD[n$ʉ@-VM\J[5kQ[󺷶Ӻ-nj.j3bw\4%J[Y]9\u5Y0x}Y^h2Z$Mm{KSŇn (X9^tedىKR KΦt$O6a~ؑ!W^ժ-3{[fnyItKm[v?i#w$@c=2{tvT`+Y`sU$>g\ t{'ˎ qRn$#+J mdKu?wIZq!)H+<|wC>&W+sѽOHWm^.Eu8ٱ"c>H[<ᱷИV-z1c[tp?tJ| pMbtyk{}Wdu,G|#}vX(/w'm!uhChLGfg{d yy:wWt~ᧁ5hɧQM ).HpZcp6&y gp vmNH'ƁxlWGgAy>9G64}HsY/zuxVVwrvLxkq*k;ƇHȆ6k@+a @'&]u >҆҈q:PH:8)'zjx8g}ƒ)XXDž9'0Q~h4{h|kafb=8i'UsH3mVIut&jHvcqhwWy:a](Ș&~H{W(8(RO0B2=($!(t9exJ:Y5% <$B!)y1؍BxKxo$0z׌?ɐht##xAfٔ 3/fǔ`[$lvmjov_ _=X<9茲gFd$A)h8q]yo:8jLh4+3'WP.#ؙW }ɖ(0\$vOEEׄ^et^)fFL 6Y}T%XB.YHYAFza¹=0yI7^bfSWW^bz5fv^zyX!*B,ٛ8p|[EVFD hb*tf΃gjb(Ffvezצ}uYhIq)Qvegّj)MzpB.f.:%g^e^/rH8$!lAǠ+Gu"xbUJ'إ(4R "ʕn)H[3yb.iڦ9fکu9VXI{j@}ɥ /Hܙ(WbÙNh yzf3jʦ1ڦyf:v U#XQSy !y.LtbɥUx ꥞ yJ;JJ)ʦZ+_J{12A㠻C:ct8Qړ$DZ,~`: 3;~[B*Y%{- 7 [|𪙛VN)K 2[*j:SWgڠjV0f )&k׮V Z{.YwÒ)y~9q R J% zˉ'}0|N£2xdz8?y9-ۙ{Ά +EzC,& &tDr0ϋknpXGsvN ex~@ YY{;:Zr} ` {u| Wi +Y̯h;{@ zzI* l0 b yڣ: X+uK'̫ Z*$|,ܻk+³*Kz8H.]ۚ=쳭$)&yow!7N,/,)d\~LY4[ l= 0I8,Ʃ2bnGlv+və,YB,HJ ȁ5<l=9C'P C NHnQ.$m}:,XJZkn5杞bPs~œCEɘN7Q!ݣ~"..VEv[ӥw>]ߠ0:i׊Ҏs 1=N-I̍NnŠGY']',#Ξ_8%]@>^8ӈ-&~?ΐO^>? 5zSǶ~.&av?>T6-?_7r6kP(*OƸ'p6RJ.79D0c?]r3J/ |f4o5MywB[/N9 %^g i? &3/81,7Yrɸ.O$rOaʺ(/+_?Um#ޝ\? D۰Oha_r ̻۸7yEVw {o=Ot oO݊o{m& I:,W>< =$XA \E!U %N\(C\5*,a!E$YI)Udr%;1eΤYftӧOVL$ZQ>%eS&7iSCE>ĚᯨajD#B,Ee!Ht[!ݱ&ծx.A:aa 5\e̙c9wV#JITMU&uQбR/d][dٳ.>L311Wg'.P/K|2vl+Al'_|կ)zgOMa}dO~jUbΦC˫p{n {) $&3nm|ApE[|Ec,=6O(oǟOFm LT3Q\+ S(OҮ*O6--ܮ"\rM6LM8ɣnG<78+2 TO˚$QDl*8 ¾44Ұv+3|HIBC7G5ղ9 jﺧJ9K*f(&̓p&3 iQ RG2XAآ((5 ,jPb"1/{aFjŗhYjFU& u ց ZH5tt_4 U(`iҘ%7Y(֡٨Ch8Wah5] Cp1;%;iؕ0$9}As˶4}fYj柫kD+oppZ}aY-T˵tanxJ2ݣg+(Z&wGzFϔ.yHQ} ˩6 @NS_D,a+M),NUbY0@YCU،3>Vb922KFj(,rA|; 7YE%Orl6uJ dEcfɼ#9ݎ fӉs鬑#y'k ΃>xʧHoL\HA$s'^3'hBgyQF뢸?am,io0iXwӟ>QESbڬdDA٨DOYJa3ma_[iRnTmm0 򙶞m:77Мms3ڋF@=noj^S/`Sߵ&}gA{RO;З[q}GZú_7oz~__2)C]]oyuk?߿?|ܓ6Jhۿ? @~*43L@<ۼֻד@3@ 1 A#3:kAˈ1AA$D T#L;Ax<0@+lC06Š5ðC9{˫sCXBA@8;DCQďb¥Csv;),D2#DLC Csk:8SCO78PPDw3ëCCS8cMEt&Rt R9QE;y9cTEG,ᢺDI D]?,DS$epR<4 q\e`/JD=(A)@lǸrdZ?y7lI7);UqG>BACʐ؄?h%l:9W҂Ǫ4£H@0hC@ LCDG`ʶ$&˃3ɩ4KDKJ@XJ@ ;KilLH̄<,2&,͜2;L!#C J,ʭKA& bHH^̠iH{ț)MbJȜ̈́M L?dHTA?=DΏ`;i/90JN=)ۄNיNZ˽K¿J{uMb\LjO`ۄ,P"L3!L<"\< u U|Dɳ,QNL u/TEHaћЄP,B\D=ǔQPG%ìKP Qѕ;P!|lR#ݙf;<\ҧC'͵Ք-0 Ml6. EQl>R4-SA P:)MI+ˮ+7 rIKȸ;5C~KGgOsnpѐFmU@UPdMjNSU!Rt , F0IwEm69ՍE$pIqWr}Ms]C:҄`ˁEV%VWWXS 3}1|?}]@ N}@UMxTFY͘YYYIO[ϊyS82WZB!Yd3X[ ڱXXX~y[$۹3[DZ&؀[C]QM \);\M\]\m\=0]U%\YDUɵU5Yu\MڜUϝeʠM] {ˋ\ ]8]*]ZX%ݵ0D߭==ҵ eVMXk^|ޅ^^j[m=0O]ZFM_b[_k߽ii_ʝ_UJD_5Z]]N,ulF445^5Jrl˷`< $ S5Uf&EmW`BęG`.Ue0^(f^,Hk7-v.ZUsXSS׌ aa}``m+mH`IbnLIDF+R}[i67\8_9nZ:3S@>,cUOOIK3Ibnlnyߍ䖝d˭dK3L>-STeSd0Vn}NHda&"VnW^XYY&]Z^%e|b]V3NeUVcQgRfjM]bpeΓfg>/-) J9fe0~0L?f@f=؅51hgkgӎRՈyNO 61K*c PmyLL!hnc9 ^&LH @bmT %P;iVdphAÌŕNY\1৆ꊙjrB(ϖϗ>W^9Φ]@+6)kJVljOҬ5YXƬe~NS+M M5VaϾ~ .+QХ]G}mN`MlӍtgtmy߃XEⰕ0nh]=k4VNhi#2oWkeo-.opFnRp%eepf:7E> o , ז`f o.i1c qWqrk͖|n˨  &?;^SrvTvrTj gzMdnNrB n1ߣ"?h,WeIO%WXXڰ3_4V5oO.Rrr :.q:l2ss^~rV#U4BCDϖN._gQ@h&Mr89O:;oۍ@a]aS?/gJ'cOet5\&p5pٕ ^Ǭ$~uBtk uzjo Vbtk(s?ͺvvG wOtf_g^2spjvt o}/~O2_tj^)xnRvgR/o&Clu־(_2n\/z?zo>W&Z_[o_qL uyeyHxx_ifnW痢mmTU*.wWNOZ}jaE{z@{/6?ێϕG?|8{FW8y|ȗj}R_}"}f2}|I|phؗe}nzV8& c$I!wOwaF-{}~|+?^~c_ŊkeDje p "Lp!Æ*lVmM/b̨q#ǎy "ɒ&OLr%˖._Œ)!93; *t(ѢF"M!; |T*թUv:+֬P~t,QLv-ȵu)O:qK+ w0†#N|iˮW>ʕ1ʐ'cVYn?6͇5}5o3նoέ{K+ .Yk԰gmsEE5]ӯll@;6ϣOӷJTܕ`ŭW99F~Df݀_x dbm|'}ƅHYr+fg(T i]x#3CI w~J‡߇`YFdL*XnIYNWc^8E#xaqkh`A'(QYW5C[ixP`94ih_)' ix5)B|j؟C1hAA9ZiLHz*khT*kD惿V۪j,%ğ:T›l=G v xI~[{pbޛ9[;Ik:F<or#\'+ܲ1pHwqj TqIֆcgC0w,G%LRnaOc5/sݵ_0՟n̑jMR:xU mw{cݷrgkFk QżR;݉CBS^=8VK8䘳޺?uo`a|zи:_<ز^;FOw 'xGmxJ޼D߽ߓ_ļpBqf_ߋO8Wp|W;A=PiܠV W$! 0seZFeq y[V p1f"%#G,b BpUNǴ#uJA!ح&1&{bâ)*bYr-΋rtD&*Q$̘*4kwh`qqLF#/QςcErUe#%,JvʒXR'- +eH[&xOHRbΔBT.1 %,i 319)c:; q`O>3s&98CBiRݱt>,SS'=-9&uF9AxNtz̦8ʛ*g=:~L|'DFM; ԡl\(%n)v*2Et`&ENnAk :4YiPRk-eQF Tr45dQ84 |Srmwz)VJGq*p*ճ*h(jȄ"2A.ʬhk*^zEvͦqؒ:qkz As3TِE`SI U_[f(jdeUbv@ 굱Pf+ڒ%̭zȻ6⦵z.q;˺5M`Ki;'Z7NqGHRDx.h;'˲Va{ pJ[,Ku\ERy︸;KD00;LDRf`@/% faP:<,=lcDN$$zRA%9=0"qi_'-Ɨs~j|/+$#1FL>C( B;\g&e5|Qq*.; C1"{^هɏFT(NNRsюp|~w VⲚC:e% YPv4̤'j.Ѱ|=;lԕ-uP= irk3I)Ne%%=krB-+ J0&-ozHiI4t ^k7οu-]>\Ć՜\(e.p Vb&@.r7dۍ:H a$Wwqyb&< z=GDSN+'%f|8wucCg oS,-*D!h ե#WwpL97,X!oycf?zڗ9}ߗٻrsDw?RhҰ/Hӥvay0@N@o>[gt!}:xa96w޿m˘eO{ڿөu&<뷬.c?_E˖M`ݔUosHOg_ğ̟@`ߐ=A`V `n]^^LbUTM Iz _` _ RaM bB`3D5ԠWz:T R  >MaW2SaʑN!ZWn R!!zv "v!:b$"2"k p$zHʡ J^l@'P(`)H*b-K+Va""Т-b "5O/ZM'2 06b12f/2c5.3Zc,SY7 6ic4vcY)#8cX#4Ώ4b5c=I;%^R)B<^=c@>F> A*="BfMBBDAFAK&9U:RG2E";.? H 5d%#FFb J"DMކHL?&MMPLK>>%Q:be.6"G6Sb5F%1N9`pydVQ$)&e,X~eSdެe^JI\\*`]]GSea__&-fcjb“b:&XNfedY"UUreTm3ve`a gs*hf#<ʏrs:ug;Ŧyu'@KiΦ݅xgߕ;n' ~gg{gcg>tgg~ hgA7hV^^B(PdL&'PyXg.H|˅Mdžrhaz(LThFv&gh b[Ҩ\h葲ďfGʐ^"iV*)KhLF)Ni$B]Uniz:DĕdZN)NJ)]r霮dj)o~$*jnB$ĝeN[:xB(eLZ*aj:BMvc^p۠`Of*άV_j*nk` +k:n~̞BeJ%kw-lnv+'}@}jr6k jk:湊N.R&Nnk\4V#& %nZzg(dnFR-28AJlv,~Aq+},MZk&lbMFj)&* в`rŚҮ ӦӢBP"Rmյ,b,jdצbٚJm^plܪ-޲-ƞ&߲gJg.AVXl* p0F0Ѩȹ.,/Mq0g؎(f Bn00 /1 op.')&~Zn r#1DZ/bgqan> o.;0p!BF1X(bp(?op$cR*';).ʥ2$;s!n4F.S2Ns10@5W[60zΰzd3l -~2j93s_03scnn3cssbsgo3?Tj8s5'޳jq"sM*BGbCh:k@'EEc)F<)GGLtIIKtKWKO1iDDtt>4S-4StP?P,HF (S25wMW*TW L5sdUsހ W|$ufXjY\^CY DZu[KU&_Z]cyla^G cO_`k"[ 66@n!6,vsilHvA!Tec[f\k#l/sAmëlnto*k,߲nE.;7 s. /r0pK g0^?oh7o(|wu v $7ڰCP}B۷{_J|[րocpsK/ |Ǖrqs9xuO q78}8 E5pCT>a+|Az[xփBH8eP8;Ċ[BDx2C2|Ø!'y5*y2x+14nB,90"wo{o!sx[9:xgy7D5y5Cx/båOc:ǃ1P0"x+;eApXGP@(=8)`*JJрC @6*E` s˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ_/}3Np^Ş;Yڿ/# ?{w8?p}gb<~K?/}wuF'!,8"=022BCM$ KLW,,8((4CDN..:33?ablH@@Ç!0ŋǁ7VHR@%S& )ʗ ɑ4K`fN;RbP5Yh)SF(XJ fb@ n(@E 0*` +^̸ǐ#KLYq^Ɯ ˝ rgӧ3&sɯQvq͔kֽ7kȧGomY ߒ?'xlI^yzi)!,H22LwwLLBCM$؞wwLj ĩ zĞ̫oۂ3KLWw٠o,,8|9y3((4p{8x3ءoy$CDN܇8tn_=  7 hGN=up ?~@kpAѳ8e[)'\y=iFzQeVpA!h\x 9"pQWx48 V'"H c::`yz(bn $)"y2B⓶ )tX&Hqicg5eVtaT%w 9܍`ݑe-:2Ye)y^G$mݦ:\vJ>4hXY a@RKBEPizp뭌P6+%xxk䕳nwdxjo誩@f" );z"f$gAeO2;gV8I'6ar!~ӱysjz9iZҲyN Ŗ1`j-^lygGޯBrnY-&_;O # AhlX̚sxqFܜ?tV~zىY(ĨvݮC_Bt6bMͮʴGNtkS5N PnP=k # nc`Y _Hv~-}DːfOo@0COVP ְo>Dh5Q`-;'J A}"VLa(%դo֥:]kR /¬ps9sH@HݞW|iWL${4x,0G`QXI)n;}D&n'$+Q0WCerLdrA!"^Fd)47j&d\$H.ԁl4D҄l`$CMN`6by YB Ss 2)Ђ#'BІBDD% щZ(F7Qh iZ>*Ғ(tL8OҖ0LgJӎ3De85DA7i>8޴%:j'E|G * Ai0S7IL5TMFpUTI4K Pw#DȚJ̍W+R7NVi]KֈUڨy4Mi_(A3٨7m Hݐ_[t&Wi_v#[V{CLMFEnz Gj6?{956MR񑦸X; ӌi_iКކרV ZvC~lacHU\v 9ǩf. tn7 RKGrN]:d퉫K d"d/!ZS.uv=wV0nkWԸa86eLd]E JV.킬cʃT 25?CL<3فYCbySV*!2 )Ћ.u;{W ԱLgҘnXsE.+l,k+ 8AHl|[10뷞 )ɎQ98&+m;K^T1EtI ^0#Շ^2@9>t((SO.#Wo&.&25oED6,5ɀc?< ݾ*BSsXE jV` ďI߃D7Ks@UY$fkF =9җ;PN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8XxPx0G@ƘxȘŸ׌H'Oqwڸ؍|(zG`爎wt@x'!v׌!>=wX  (PuuX0+@ɑu('u iu:T/u7yw9;Iw=?wA)CvEiGvIYKvIiOvQ)SyvUW9v=f}iBcIXyBZ`gɖeI'pINy!,I522BCM$ KLW,,8((4CDN..:33?ablH*48‡#Jd(ċ1P1Ǐ 7rG#MHʗQ t &C4m)AN0y J5 @Di`Qh@h +rY&֤ ,@B]𷦃,^̸ǐ#KL˘3k̹|NZhC.hZj^[vϷgF}sң{8m{ݺtS?,]nOZֿ>9 !,22$ >?I GHSBCM &&2))5곴ɑ01;H *T(00ELxqaF;zȁI(p`JXH$3_Nbjd$/>I BBM 00;8PA*,@@Å:1ć^11(PAB2@Ɂ(S K1|4`#I6oTaУ6 ٳaß24U,k$UInxČ ۾;Pt0/ݳ{a}gzqb7~ mɏ_>dΕ+J8eKMH j; !,22xx'bxx)xxlxyvv qq33 ""TTII$$DDgg++~KK11ttrrghrr55rs |'' .\ JQ1 p1Aāy1(#`xHbDA \8@4k(AN>}M1@0]*D:* ^&0` O ,@9aȱ*@Z*wԺ#ՖPYHe B}sH N,q0,Jj5[V4-Yh~ bkKU$ato4_4 4w@ԡUQ*ofpY2 <@c@!,22O;YsPeuxxxxEnyxyEd{H̡|̎uz̢|zxx<Hvvwfns}2PdvyrEnrr=>y̡{ˡ{̔,@Ott55 ^zs.cyggTT>VPFy̢{=j&&ϕ^_ˍuHKs#ѳECdAcQQ-@OJRQs!VV/pPHqq[{"EEGyPH~H{3Gx#))Hnx iH*\ȰÇ#JHSxRǏ CIҠ+L$HR˗0c @B-dɳl鳨ѣHJ4ӧPy.04իXANׯ6KUfӪEv۷1KWkPcP.߿ LˆNxƐ>L9ʘ^ΠyMy됭_ˮ{mo^{o {w#O~{9Ο.}5ꦯc}{3_y<7N>1,}ϯw?gE`k.hVJ`AHW^hلragqby"^&bb|.H_2T}O4X>d3HFJ6d-= %IRN)RVd%%^~b…efDjTn>f IBvzg @ @" }2wBJqRꦥkber*_ʥYjS MGJA꣭;⊣5*/ˢ)k#" 2BKR렵 br+˟k K락ዝ+̜l!,i?\$_Ű~WeqLe"_IrZrTrs',3E4Cg3n>WBItx/=Nt+M5V_}hW,[md]@ZFca]g6P+vo7sx}c=@^>Y⊛8}?ۋO^ևCޚkMCaFġ y.vޓ7t'xp +D :撇4Kdp;xR A{37Ёt#,,{N<;#l|8So~$U/HA ?~@Sa_'#ܮ"@N[GAvK!7? 2׾eayP2X0{x0C i= 1 "LX4 h PC,` t>&0XEAO$ܛR>;!QNA0GPxtB!èFPϑҒG'vO|pF+b񓟃dnE&RPъB^v 2]rСc9X;e3S 6 Hmr{ 8 ojsHT·%+$"HV! l@(ψLK!BDCC'|lX%Zl#D`Ԝ4")H҉ 4)LUS!1eBNꐔrnD}HJ%Ԥ8hSR&Hu #U@ \*A `U ,֨Nt42HuZ4Ư[!1, ~G7s +3Ɋ+,f4K"9,@{"ϊALU2Ƶ-b-VaHSD[2N-`k Kr.7oE]=՝KpWcQnŲk&JHO.ɸ{2ߴA}}˲_ WK2`0J.+X~ fلEuQ~T#5IR'T3MS/TC5QոT7>USUU?~Uc5YVGUs]5WOU5aUXW>VeuY_~V5iZgVm[oV5qչ\w>Wӵu]~W5y^W}5_W6U`QD|20`t  @}ӤTpX_͹L`֯ XpkZc 赯V z؇ =a 06 T @vZpDm]MaBt >.]▂Aoaߛw , Hge@ fp2 chxWMcCIQo]xC+fX3>X򅵼a%r|3wJΓsԼc7gOjO?wYaV(OQMrUt]jmֿ6n=m_ٵv֔kwiw=jwK >&>N~l;n>?Ky>_m鱛׶>_k;mn&ǯ#;|6w1}.շO|tdld˛ޮ?G2oo[g__1_ _P2wZ (`H`h` hr``Za!(a1')83#ha(s-a%8^1r3x^5Hs7_9s=s?s;HaAHt/sEtCaKaMbO(bQHbShbUbWbYb[b]c_(caHcchcecgcickcmdo(dqHdshdudwdyd{d}e(eHeheeeeef(fHfhfffffg(gHghgggggh(h6A'l'P  ox 8lP8l&Ffƍ捔&F*g,.0wBPRF'^g`jGNǏnǎ6T'@GXgJL\xoǐVhGZglǑrdGf'vާǒ璆gpGgt|~Ǔ'Ggǔ甒'GgbǕ畞Gg疰ǖG'g'꧗''H·ЧǘǗG''_\J@m }  )Iiéɂ)Z`yS0+lTb! ,x''))))++++++,,,,..11111122222222N9CDD?4' !#%ʴ/GTE~~ ~ ~ } z y p VTTSQLJK`k n p h Y OA72sfJ/  $#%#&#)'B)n-#  !-#8#a?24?6*>= >@?A7c3ْ |×C~nͼH=ַ\ $|3,w s0&unV_ǚAEG{Vn;w !` a.] pic%B~!_'La"A)NJ@dFLH2hS.ugh:Ai!ꯈCIȜ+QE:Kc!'II RdH7~QQ O +IR&HS+g9Tr:lJZˑ/i[9Oz G6+&1cZ>22@ B՝|vAW z+fO^k۟p˄۲r(N~*$*S+(uu, FW1nPVOw w+c߉^ݏ{a*^^z,h{x=h_wG<`.x f|N©=/Ǽ/ F$NǔBX.y@L"HN&;2vm:QX^Γ.{``Jpe2m><-tMh0'xs FkА' er`7J{ӠoV$W$ g-fH\I豭oͤ\7c6)yN-TŬN6A`# Ў !C!-%LۘCr?!<>wvYD7L VXC*xC̭|=7cBwkсᕎioV@a4#Q.T|*(z̈G@,xTr_.=fyu{Kwī5/<xe"sWB ~h4#)fā܈,[{ E>)ySހS^xnu;>1舧|QSǧ(z=0yXc"y ?.HޯO6ܛ S5Fw8yAGD}9Ps'u|@{A{Xb6ȃ>w@&qP|܆\ކ};u6.M>Wx8H/wu<~7rCH[h=VMHpjr.v.rxr"0 0cvdvufXEfz:nsP'tj|E6wPkwZAzh#ٷ7vrvxTs;yW{G5E8r(BuݘzX|؍Vgz(؅ cG8N"z|x sHG!X46~wȄ~p0PxG?8t' xg菰(vyOƔ8!#h&g'Fx. ~؎"ɊU*qraz8z訍z0>DŽ~xzw"WI{v`؊{HyHtAw <wշX}G_^\i=~tVu12Y!ْFrh?7ssٖNx/'ucY'B8zaz xMiu,~_n{Y dƔ9}IUi2 86xlvek zk62QqegY(Ɏ5Au:k  zT%OZ(i !$j6*i+-/ $13JxDJh9j;z=a#TBVR:gGZI*K#?A 7` gUJWY#[]njhuX]glo[6Q-F2jwڦzZLƧ᧼q(l:I'⨩jEf&©᩟iAFa%hګ=&Aa$hŠ!Ț~ڬ 2Qf ںj :YVz Үc* گ.1@* ;{]˥[zuy r";q:^&+ZMzWlJ#  Kfz]q x*nJ} ҳ{J_LN+PR;TTV+_{c[W{&Y۴-_ڱ-Egi v{z˷o q [kt1[kK1-fFmK[$mѹ2Q{[&s`uF/{{ a} % g˹;;/`AҺS]1sekKѻ/л1-P1[ͻ4+˻[[۸+ ,۾; n>ҿ\,<`K.V7#|1lvWTFF L=@sv `qc`H ]<#*\ *h,[lEɒC.-^^ԍ9|p N} >> ~ԧبu/y$`?Šoߒ / *<Ųbdץ_t߆_仟o p?ےOǾ)FѢAc4@PB [(hD \Iņj$pLc M.$bɒ'QF$ Z)$NSFl$M-^DTRM>Uԧͬ^ŚUV]~VXe͞EkU%l3R5r}2I;yXeO.88qТ;rc4 q8SDKQǓ{[JMtЃ7&C'~\pōVr͝?NvmK离.rz Wu4\wlI˘ fQ;-b`-~)x(4rS=NC?F$DO\n촻-D;+е8B(B5πl69$:2AאM֘z"FrH,DRF7߄3N9BN;9ݚ2zF [>u7G_rBc&rrP$u~:J@G=3 ECDMk۲X3E˫ɑ"ĚTVuBÑbY@KlQdi^U=u p xa zTygHuh! lq.%a^bQV><@xMѩۯ/^PV m(>پ>Ծ"ty$s4\uh!7# {4IW3#|u 9&"J<8 I;/z TeMl}CR]wIy?i gj]g {248~{ 1:kIrkOcS6g9 {=== =C],[$+A^S㼖[ <*"Kc=Aڴ) ׻8 )K/%CpASL|3i ﳰ4?/dcӼ4Ș#A\; 03S[-M;hP#h,ܭ, Jԕ1Į(@[ 4LAT̳]ӎ?D#4 +#°A@.d4s2)<3E=F|CZDSBeLtF~7c OLcCr7 >!Æ+7A!vE·G#Ɗ5ۿFCfyƁlMjt<TTTE9,/Y4Fz@bEG>ut\|1c@ Q$[H۾ g4HfzgFcDvCcEwGZI[@lBʹ.))ItT I8ƨE$IgɁ ʄT~tȭlL/DTE˳>Ft CĚeH6|Pta `M-]'m|OEMM|9BؼI5J](TKNeքTP,7UV S ܒPHТ<#\Z!2Ud\sn], kmϜRESվ?Ud}]m;dQH%3Vzؒq=W]֔ Om(uabai;1Y*$6FnF4[c6& ^WVSğacb}blR'<"N>e?Sd]`GeVdK>(gdًl^%Y9Y<]=T c] T&2*ZpKNbYo\dJd}eLNܝ %\>_v/fFjn =Gd`(N` `pVpg #g^e_Fgll*e$X*~gF^fc 9i?&dWFfFdRG]~g nO!r~ ҫmv&V)N uLRWMWdj&$^ ihONF f%̺M^>|ktljAP&[V| kh] ƹl^khC1 eQaF6ujZs:Qk1h~.W kcxPFw6P_JIjo>h+llNi*mSyinMf ~mkIfRF/=@&.\֨=\C`ۃҝ8Lhd.mkڣZon퉖]ufV]%ו]oyk mݮ^қeNf.#ƫpʳ.p9)g 7wp^n0q,p`%qrG >Ŧ@rLwޡ.'>o(G;^R>Yp$r`A-j^@wY++!ǥqpCS g.L[tz6unzK>mmAW BnZF]TNVeho Z"ɅʫlQOG&u ^_uou:CGDgtWS452[ XroG @vP%gjg_wi2UvlYNa$rYQ?euw9y? \< wa@}v?]hFMRixyc?vˬjyyz+;?y~b/>~YJ~ہqY21̦gW/,hA arkۢؓ+|ĊcTOmiid`A7E-4^ Nz!!z%x"IVua'HuwSmyL~IFe H.)]yTJ-H ŷA(an#ey&!&m܊j%cp٥3Ҩeٙߐ@Yx$};eۅ giZQ OLٷ%P坭*Z&zYQ7g"7~)\cS?.ᣡ͗iK.ߏEƦyR&Hm}.j- *+;oq{/Źkk! [@Dn*#V :zʨvŽt{aN 1-2B;35koik:o4^k9a !ګ^+!i)=nܑwniQYDyW2cU3mݲq=3)"w7Fh4 ted-1Hg5EFtmӆmnmM?ضo~:0ν:֍x4 a`.9n \GqMhyb'ݠ3Y=:z 0UO؛>sN ?E-ԶWeŮ LStX HAheħ rP) U+n}yF?4UkLr=.(P}X=tJ  >A[()*$VWЇ· X0RVx4_L y҅ʆca BCL}ac Q Ex3En|dUꖑ-B=;Ǝ"F)` Ӹ,2&HP ~oK@"N"vV]FMLi))at$Khb  K;.4 TтL-6fR}L"K4HOJ<21d6sgb5W8NL5 =@k7wǠNjb{`nK&=)>Rc_? ͏3sq(uPRȸN\='0zWևӽ^{9.NtZg: X5hSw"CUV=TY*~ƍ8^FX8cۭ񲼛8wݐdjMےW2X!^[G=gi6)yw9?n7HG 󭑏ɹ"__x`IO`vbqQ-"\U NݏצxЍ+v~J`)T/2붳\] YvHĺ:EBW~2p&OXۣ<_c&w;fA Ml1V_׽%֕-b~!` I L܅ M_Im1R ,A%^ pNeI]/U n`j$ @@RA| sĕd ҅vl`R{XYJS ]? Rj"U5E @E 4#6#*5ͥVD! M!џyL@&ګ项΁b%TR D"#c c ۗ ل b)Z+u+j .a1 Um."T0"0.c1R!2c^[4J#qʵMX J(7vVOH9Ơc:v#x!{<<ң٣T\B>J Ԁ?c@*AT%$Q<Tc<6DF(C|cqHG PTџީX K ^'Q 21*b3:cQ(4n\P7%e ,6˘b\e!͉S܍QMN%RSš<%T`MU G$ %Af)nUVDqN~Jrn$ 4s~Od\VBvg[aCNy`c][vAgg`bWk8ep.\dV'Ij$A3l&ƌjwv4%%HPi&H D|DXb(犲[]B^@B'3oH x8)ʟ \ڠb2N`gj\)=6C$)(U $BŤr~©Q(HS&r Jb0)gpJ*6$A$NY$Xho)`#hJF)0שOڙf qgj-T*jǭ5壵M". `] 6.+S`'*bH-Bm|dŸ2uTB̥X%DLx HX(P*SXJݘ{kE^_&D~-F.ÂHĆ>SϦ~H,PLNt,p`LEKU6^6S<͎S쌪kцQTlqGM$Z(R(-4f@+H@PX-l>0/,>|mmܲz ܂H&~ -~)ߊw Ym- 2xb-n҉B.NnHQnk.mpMBTm@jmޱ,n;moP.Qn.t.ΟD/ǚmaL p.i֦lP@gpn/d*E|%>No}ogPo]0JDٱؖFM{Lpj/u-8Pp,C GGCmH]V0d _M /Ňm~8 A.Za`plDaz~.TN1BL4qTWDSy7 r킱";1fp$;~  氟{xfo"/r#?#\QG;q@y3qXJ0_bLRl1B0TlQs,_3rrW2ݲzr/TG2DIsq`L{戃l*1326C6o37sAɄsAGQ p(#nbd֚߸2;rq???s7{頲At4;{4TFC"k:ҒW8&AFH7?JK0L4xtPS;:Nt-j#FsJRx['5\\/S$Wuu5ƊEʹĖii vCnZD93gP36LC`d_dSv@@fS g/h+ĴR_+Aޱ&7O_T_}h\mmLgM~3k.DG wAL.Cd VW/>7 rVRpvvSw@A.w%NPРw9RP]ĴG75>M7a>ElQ88$+D4yZƴo8vLFܭш[|lز#U6pnS%c6&^ێ7J y[5vkK5E"C9J92LLuCxK]!80 87OoHb}w%yY7+cc@8B zt:m l6z=D@:'ySS:QGy[ѧ#L*x38G]k9 ?|m43oJb:UUk8d;GF2?uC{^sC\UUoRЉ4;zJ{KTuv:RRC𻫫R8oOדeԗO7^=Vem}u׷=܄=Kv⼳<}=}OHx;׽o's=㻊߷F @rE uQ7>&;៽s=%m~篾|꠯75"߾܌}M~?ĻX4G??wwӽ?gپSP?dy$c˾I?=?@48`A&TaC!F8bE1fԸcG9dI'QTeK/aƔ93K7o>y"P qG2gJA;F:!SRT#!kW_;lYiUm[o_yI$6DY6%oUUqcǏ!G<+\˗1g֬V.κgRgёXukׯaǖqsm۷qj(yz6R҃M7ZV͡G>zױg^s.]wy%^e^!kǗ|{}.p{<  llO )LI?I,!P \I, QLQ ECi< EQyNʚ(G %RɂJXp+#GDR)j'LS579h^.BFh` J# 8ߙ[fhe 2B# J6Z9*=fKڢEZ#M^늨9! [j]浩mrƈh|v0![b>!iқs7R[Wq?Y):?f[.]H9yHpn<:@6n;3R(q:tF^hu{sG"]L޶jc?xw](^vA ^kg6}YCB/#+x7%}%fEv$L]D޵@ /f 6ˆ$O!4EN8 O'@IerA\O|`7oSїLZc E1fm_;0XJqT _ C쪗lPyBǐd Tjf0^[Ķt!/:=,d(oZMT ~z#9eUY=t6e6%g )V sjQ! QaL q_u!}t aQN](1եUDֹbjzӜ(#dd TS hU_[7 '?9Ůݵ8Ѻ_8!bg#A8muFۏ6D̃X6 Y.ΝA5:=AvF洍kkyA@8 [R[]lCzf526ش,޹!Nz{q?= ON2B^^U/:9ƳۉH>.CMixe:h7.vn^foڛؽEnȽI47kmW<7 ö2vG| %?`q_Q{]i{vRh ~(MOHK<ĜȞwՔ.To"D6/FJt.4LtO/O<pXORO Ċr ,{!> np v>4z!&”dK*"F/dͺ]NZҏ L\)Dkh0,L&|nh0 oMRp22pg2 O (gJ. rOd܆Eȍ:" pUhân- j90~V&n5޶+(gL" ~<|î1@IKqݯwonNjVk1q" !$0) {D l`(*7h@ QtKTgJ#?0loj8uJvJ$’ #"  Pq!!q "QR.2#+3r#=,1"Dp.$O& -5igx p /֌&)G'w+(§PRc# Le)[*)^DvH2(39iƲl,-RG%US09 x r1h p-`70 "~znvP4$(t:p.#"7R$G0Jӓ9 3IZfT6;p7p\3 ऎ|Je&ޏs)2:'l::3s K`'Q>C5Kp@k1=3 1y&hR7%8bѮ481'a&ER@R~2"P0#3Tm\ 3C430^O)@4D> 992E5l.QvLa,ʾzԝJ !Hr`#bNAI 0Lp1mp<iqP4hEkMcME)S)R?G0-MHGQ@l$(iVqNUt Fq6<1&8}UI]L"@5pkZk0/rd0GTYT)@vbKwW{m7Qe3!X{jRF= %SmOcZk5Nt[mԏ_QMz4?}V;b%u]U] }<43^S2!buQ I!FRБ3H/A_EPb^V6G!ʲ`5c4bЈғ]EvdIfHN ǏvXvd)fZ TheXR,jM>s8IUXM0"[BI'HcE! i:PCvk3kvp"Mnlyll6(\-LtARgLMgn1+T7Vc|N YN <{FqAF!Jr'rrJwQw +Hm\8n4)F!g uғ[qvgv$a!RWzTFW ļ 72JyNMv[V5^ tz/s|X/n#T׆WN(ڲdzCVinw+W1+B߷0_7bs+tFfo%59)a ~M3v}sFbN,Kp4DŽkjexiY stwzxD@Q6y7oNkYsFslL j o`8u2/syzS6C|C uA"mj >6ؕ BW6#<-g֖%\U՘_T'2wlUM?W6B_فe ;1K|.wi R嬄x1ͥH#O[\ {?E;y09gÏ9ֵus؈/ 홗G5G!pӊK`yBOeBW hʢLW.."4:ebS`=PzRZHVpp؃}/tQ FY3Zb-_mn=m`'I3S5+iѷZjR!eiy.nF )Yn7LwfPK; YǚaŠ SWz#Kp;:dq /SF)=z9wZE3xK:P|ٷ9ɲoX:){ -SZ99^XIiyˢǩ"{ُ_|Igu[zL]yqUю[P1:9znng2YZPFwƄe B ls:7=V[/U!{M`4;՚cV{& 0\xb~=\@l;T˯)Wieh܀|:VXUӈ|yd "e˕@3h}YDZnY&{\W:-i œF1gReuǝ&ې8oÄx|h5<ßQΐE|?꛹v{q=ձZA΅AأKU$\p`sq;!ísH fdΥε{~v ͥ[z~z|}a;w9M<ݥS5& oGۢ`۶+/٨ >80|0)yg)>ZPI>ϭ:f<Q}y$6%*g%ڭDhp;w>Kes4 >]|҃Mef< ]Z4U%fE R}%dD҈dƴmfj)DQd9, :'5H2T^m.Bm~kUw!]&Ҧ-[΅lAƥѮRdh ;[jJY &LU,n k7g*D%fn-\o( %n*E sI:nQ7W;뚑oYrO_fqFKK+&8-Ejri G C:q VjJD'~l/!tz]~ R4KEA@'|O,ўFJ{(>m9ڐՒ̤K(^bMS%&Ae{vZaj$}$Rw/6u;/⛭j; ODW'CD~c~#͡ IPxy '=`H1$u{)͕HW1qs AOQf(D5yaĄFի|Ё‡@~c@(ЂT"0<:E>(I,Dj /!jN\ѱ1cD39u?_˦B&\`C$al#fHJG""D`|dDhz FP'HG[%ܚցeml r%f^DNaQ' MMrt .#B>4/1$xM t'pfIL2ab}nBĉyPl(UPym19%ݢ шʨhQ2ċ<7>s!b KtC2ebC63;!D8r_hqvθS^K4j/cmS_dѨRҨ6/hJ,&)j ugV4j-r585]'rSr(CF5O-/Ŀ>uT;I̪\UJ~4SV^=c[I,9<۳B9+D${6pGg#lq(*=*D͜EY7YTξ#NWy}&YM:zO, 3 qE-wQɶз-}fГ!wr< -QFq&Y{T(mx3v4tJ6ὶ$dl˒μ]oc*- 9pā ُ0r)\h͍#*+c'M#y^.pzk+xeOܝqb9U@ h5vM26-.wkc^;a11`4i\t{}grz* Yq@9gh=D"mϼq .rȬ>=Npc\7KZN+8m00z6Ffėjk> Y^#kq V!lE.UvHnӯ< O3MQӶګpfK rmPqZŀEP!K\u{ͷ5;8XGa{jAOYkrz[B^M(~vr&L4ȋK;ۛzHm0c$#%pI%/9v"5Նrf VO,*n"B|T+$WznP/u7 j8)`ҫN`aQ~Ge"q {Ozo/.'1Կɂ|kmuk}e:O2r6f7zGP}X'`@U}*w7yiN~^$_f|r64>ŀ{t7!,UI(EȄQqMN”~F|Gjj'TXeAxim.%|vrxl4a*"gL !t6JԄW ˷1hBCetϷ)tmg%0UOe(k4WiH1wAXyr3hU9h#T."an! 2SZ{׉u[uui>kxa@׃+ Eb8@BƅH)u~ьnx1kKJViNI-rՕvQaI2EZEx6Fmi:ER ahDziW a%釕OucWIrhhWǩ)ӛ:kX*CRqKx'Y{yi& :,9Q "i_)yLhg:(ʙei!)E8tFb*)&B.ܩ|da/^1AY~T٘mWY6ē1Ÿm#Q4dRhW=?G~Tը(I|FȑYi[Yٹ$9!]:Q-ڄg)ᴝ:i1}X!h43K9:Nꦴ⡮hj#r*nIT=楑`A03F*4 z+j4c;Fq{qx6ogOߖq}ꧩQ؆[v'I2kљ9H(ʄem XC%:*@iIX!wxZSbқ'2N)"LU0*iRX:yJȜYC'{%hTJ6:SP0&zȰ&|İ,@UZ%F683TwF^Qtrۚ>/Wg5LJ9-QJe+&ɄNQ&kmߗ hy Hr9f:AeV'[CkyK膷Zۜ SayXYzbg ɪN=(7[mA0 &ŰxkrK<4D@bgX9kY5b1;BR %h!;k*a>6cx !KP CJ[ ?K{z̙3Y.*AރH^Jc'*(xq暊lgg>[;7/ k.F{(S:=S 3r'Ydub=\&4fM˺m_6 q5lZP"KZjKc;2!L1qW"bXޣC/L$JSꡯ0rD5'{Gzh6ѦI htߤ3Ad\ŇW|sbE(<;cwwj,tƕ:jq+QKiFnj(wAĄ X)OLZ:ȹLlss+ ;>cn #ʥA9Q4;$u"jL."@FμoTŲ_f+ B~8*o a\d0aofCy:͜|WMGOcs·VFQ,A̷J;uq!k!'Y?ͧ)JϬ̏B->ѩшQ,.F&=DA~U4;{7V%Vt;y \gsJSšfY=ZMOh9SV@/:-!خA3TQ540<BkgkWk2՚SF []oQQ+ u(#RiNol_p?^=QE 0kS2ꏤ/6?c8DO@V.|$TzH_?`?U_$ۿ7J$/e7aj$4 XA .dC%NXE5nG!36#YI)UdK1eΤY&IAt|DE?]h'ϔ=}eT CN(UYnWo%[Yieygؠa4Ԡҹy+BwU&\aj/f1Y;$!e:6nk۠6nd+C|6&fjtd |r|m cDZMr%Ɗq'/}Q9K|YbϿwuNsGQbxyxyyz?ח=J˟8{Ϭ/||FxOo}AaꑎLP2vŠ,Sdm'nqex Rf`=x:ɪhܲ4PG1^ۢXQ2@nr0P@W#XBc|CxILfnl  ˹L:j62#4@gḣ*RR`Kn.mK(U 2ͭv[vmml[[E0R3Xo^X5UfYJfEx[63l\KG.im]|^7^fˑεML/zR}%*XU tG Q1_5qj;1|΀W|QUd78].qkO<r[a+ :r@%t93c(1.6ͦ[\E^8:o YEV9\`R.c8QHk_&K3Q&jNIQCu&BLFzޔQa'֥uH0jE6-j:ΦA=arzel =2nEf&w̝(tDaw$f_ˎH$'`d7m29+δH)+ SAoJT9lȸw`9\+ /ȧD\#ʼ3Hۺ|p0W(& mfuB\<6wWZ 8][NuY]KXֿ$y]5xe)hڱ;pSx&go;B+et)6 <-9+e߰?/h)s#ߚ_=W-d'̦œe~>/k͹_zB* ~FϜhI c_䳻>]ko9{1C #È[+ v {@{+jQA@@h!<(?? H`~"B#lA˱,;ӿD#1BN:< ͪ4K‚B$.D9B PJsg;M>>6A7d'"Â!?โ˻+o:DDÈBFL94EߚDO\D;+*gA$ ) tt u\xƇ8Ŝɝl;Z@Ӑҳ찦tʖ<F.Rʯ˰LUHI$lKzKF)D[sGd%t5tdK`BLŜԷL#Jo3Jܒ4Ϳ"˦p\MlMyͬMˊĻ ZyzMhLxՈ`4NKL3M41LHQQ9 N#M?$E=T Y+,M-վ.m/-Q[Ӧ 543=ӇJӚP҆`RpRĠO9%?EDSe? @ ܋jRm=mEnŝN2X*םKBU1Ӎ`v]weo]pz5{%BE֐~-g`⼊bJɅEՆmW8Vð?s%U25՟`؎MU=qXBpסpٗ%وʉ=˜uTTػؠEM5;Yʼd ǛZZ%$٭? #a~ ޑ,Ĭ%X'aVEbS,.&b tUM9;J ))  Ջ㈡c0vTP ;.ZR?@WQP6%Cc83!.3(ܵPxEG.`QF-cp5eDvQeàSO.XeJ{S%eLF޿WHfx!5]e N圓_aa~ȐD;}gphMiXh̥cfmfhVfɟ~)0괄NnilcԀ[8v [ji {H(kEkn]i'fji̋ Mky&!N4|> v .6kZ>D즨l.&akBƾVv.f\s~jhmH f Ҷm?9bޕh(nfNlp`Fڍn6iV@ 섎>+ovoyZl{ͣ#niPe Vpk5iyo='GبcMp ~E~jGf.fPqe:.'$U$h]o+rdx%/0/<`cdpRD'P`rH %3BqPdQ8&g0w?pAϑ#'Ny#|ME>}JK'͞34@TBn=﬌dt\UO&_mTaɴ=x6[nf'eRAiOj-XuVoGpw^vpsvH v4{'y7AzzwwI[`,{o{g3Ï4y_z| Wz@&z˷tG*|HWyg|7Ӈԗ"|wW}O^}l|}}}{7~|'w~#G~lvn~kg;WjoG6ߏ}֯7x_gfh p "Lp!Æ A(q"Ŋ/b̨q#ǎ? )K&M>yp%˃"ZŒ)s&͚6o̙0Ξ>s(ѢF"Mt)ӦN*u*ժVz,yϧ.i'ϔ)UM;!j}+w.ݺvK+߾~d׷/[YĎuhɖ/cάy?mu0J93Ul0꺑[߬ {6ڶo[{7$r50n.򕲛C.}:c^tī%Z8x|~=j/>F~}מzX:D gy!!M7r!u nz@6P+a+X~(W~ ދ?YLݘwX;ZأG6dyCR[ʴ_ri\r9%xXj٦9ܚYYsofiAfiB陨?Bhjj'b醎rj#O8iRwa2W"(*NgjjS(+Jgk"jS(FglblS(Bgm$*rIns榛Hg2.ږ~9_/%Sir/-91V+%ƳY#LLIf%z7P;2R1GqqG˳| m.FM4{Q95nU_]Z}EyD}fӍjwn?mu(އ76Qm6D7x8ފxyxmS:ߍOǹSIzڦzul;kM{OS;ƻ˯|zPrJSPNb#Bꐊn   O+ ~Ã2̚`4ቃ4 +hC#:Qo͔TtfD ;j˃t=RIIAp AS(tϴ x0kf3 4 T:r<$($ybUR!=eWJYBD&00a }MxzXPyU@kJS;@6}zjP8Ҙqj՜*Z:5uE)%r0 씟4L)qҺ^[ u1a4epX6H=,a 4)uRBUfBӗʔ ]kKπNW =kiU+6:-zX%KUb[WUUMcNҷ<'sYuDMZuf 6@[^mE%JQz[F\FvEnd/_n0/J1qRƕ - WF,7M3}Os2d"ȝJCBRXsO).;8L7̎BsCԜ)w2}*Fљ!v ۣgsA_9t]he2OV-#P.%3M'ӓ4zB=Qvǰ< cY ÿʨTG+>TDu^:mm4Kφ2mlD.׶vm3=neQ~ֲ,7w;Vҹ}[H,7Ⱦov;.cr ]W!=5o%ij6H 8b,^E 0QΠ$ U34@||A8W9b8 2BJÏ+h:QȃBfٕD?mw̻ސ[Yvt&I“V~N^Ƀo&){c0_y{Z<%rxR+~>'y/ڧgɽB|я%wũFrw^?k{_f߫??q`q`"`*2`:B`JR`iUR/]0yWC@Sl`Y:.]X\]"B$Zy< N_, Z՘ V p(2a:BaJRaZb!/i]`S uD=/} fLWAp|E1UDLZ!^qE!ޒ=`ea$J$Rb%Z%R>@c E'&JšYEZX'>bMx&t\)YU,&1"c2*$"G0>MT(Z@c)`*1Ue0ALVD-4"5^cZ "q#-=c>%6c^DN"N4NXZa٭"MXDܡ hfK"9="e#(&d"XZ5$DW/Z.bU-Sc6%M"Y D0~ GcXM6aa6MLc^L6b6&NdecO2V*)p܀$#VNff&T~II%#( fV%^cE..oBVM%IMeȒ>XWAx&fK:&cd.KZf|&c)TSB zfj^BfkN~n~"e~^^BO"gbfRb`fW@'uʄ Od#r &<c(>E@لz/"FXbxdBKz:fd>&a{|:%IDse攚Pe.O B^fTz"| gw`zg2*Mi'*%F)h#&JBtI(QNB*QmgpiygA)ji栺**VU~*vO2j$fz)QnjixbR&B+{꩚JkN@U:eiI`f#낶i+%fNjmai⪲2kƟ"aFV+ )r> hg\%ai~)%`D.JQF,rlòlɪl,Ml,&2baE@!,22$>?IBCM بKLW01;GHS,,8))5곴)++7((400<12<[\f@ A *0.$8CLdH4.!GdHI<ᤀ)c.|%J:F0%N2 @Q (Τp`Ր2|`lׯ` &@`>`- Pk5] 2$<$  "^`A .pć/ !,22$BCM KLW,,8>?I((4!!-CDN󑒕%%101;ablXaB :<8@ V,qFf@$…PPB T0C1gtHN4>` ,j *\H),jp 0P lpp!,]I022BCM$̹ KLW,,8((4CDN..:33?abl@*\Ȱ:Hb"Zȑ#ƌ;#H(I<ŕ,]d3̛k>Ј',9(C4 2M" (jU.?"80XJ`ASa[iS 8 @ (ř@ {oBhCÈ+^̸ǐ#KL\Yf3^Yh>]0jקafۙ  }ѩK8N`׬U=scݝ&!,b22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇŋ!01Ǐ nH1ɓGDɲeC+]ʜ 3̛'k3%{ C2, RP 2@@T,-h_̪UH"@,OY@K Unp](nWfY| (@$6l0T^,`sKЈQ~ꤪ]:u(o[ݹ`Yy7Ӷ>nx -Ԉ3M/yġD3NDjG%B)ЩT"!R,22P~S@*\ȰÇ#JHŋ3jȱǏ CIɓDɲ˗0cʜI͛8sv(Pϟ@ JѣHWDʴӧPJJ5ʔWjʵׯ`f]ٳhӪ]0+VpʝK.Mo˷߽xULGbUǐ#Wd,X˘3fWϠCT%gѨS^}4Ӭc˞M{׵sۡd{ NΙ~j* %3 ^,8 5΂x ^,8 5΢ZJFƗv9Xu15"Rsd `+ق\b`ͬY5FE/x \#>V>s1xbOfǮǮb>z1kpN9b@X?}gs5 lc_C53 ݩCв2\uAa"zGz Yx{b$?3mFؘC6Y2*1WF}Yݚt ]s3̬ ;ҳ3]YdkVcchK&L0a„ &L0a„)i#'O?iFLtWsD)PMc\7rexb 1K?k?1tml:"3=30„ &L0D~5 fh?Oÿ1WAM{h9_^4|0L0a„ SNׇp?4-4ۦNJ-ɺJs:!P,4{<mdf?J #nFkeh3vSH ,mb$>X9oXcWy,G6s+ל{XдO?y3N?LXAY8{mM].gPNG?qadQ<E;=疑⚳֖c^~k*/ivůnjz=G򆦝+m^YOc_MWlH?t7_nVM9O[k<:Eg3 \XiZCl_I?~GM~rKS{Og]{#Y;LyG[SNf9g}L0a„ SL7h<3e%\o_ $+9ڛjڬ-c];1nbȯ0YzG4u'9+{Ä~gi>/ i3G͙v.}C @>ml~\G6p󿺸ֆx - I"c o;#Kk^'4m%|i׿ށ6m%_b_C@5\4^xRD8%R;%l~xBŹb/ր gc?|x͖-[ϺE,@wujb!Jk>vs,[Y,@(K.9^x5΂Pj905559O(9>@ .@̙1*KNr7~Gu0iӞ `%Jꯪ kR/\,7|5N᪯)80iV`a->آ^5?]zƽOBנ;#C!^x 3l) +jw_ɀ]4x ؄3 73C}Z'28CNug-SZa|n7Ⱦ]lpY'ҹ[; Z 5!kʻipЮ[IJ֎¬~bx ϋ/n~晿e#/쬬%JJU8hg#HyZ.޶F6-;y'}oIcbx @"[$MƇʞ6Uy;*i0Su0Zؚeqݘ;gXA-:2$;bjCAj2>51&Ν+w]<+'C|C73o]rex) o+++>ֈEf %鳃|W z!5=|B?5.R4^:;ufs{mD HmR5u kq"m/ZZS/;@Jˏ$Jl׮sB XdN$n,wvYܻZyT8Yɞ5w a99M3ꇣĦ ׈|߿yivm4w^&ٌl,`'L_å({:T8Yɞugspp\s5'N"axiBNd3wW[b۱Z6mzW<Mc5 mxXd"ߒ }-/=W?Z]9ԉm`N?!֚] (-Saz8˖d~_#ַ7հ"䙳Q]g˕ | @ޝ; XcY s;'rt}3AgiS}NbSHuܦLjn$fJwNSduTpi<5]&7N(ւ$dĦ>')ȖիWر"e:o8>g KGʵ'Ŭ yd}w_VZm}'Jl Bo=Kkkwoy魓]2o>s3ȜLGW '͕3xU#E4m¹/ ۹ҼO48І&(p7|sX$Woyx7a-u#YuHٹ(6,Ec.O6ϥ>tWV_Q Iu.؝?wYn>"=؞6@pG!Dk.]s=52<א,l?3s׶Qc':|uژ̀B- ׋S Dehy镝E7"8`}l9 7h'E9-oiczILٱa?m:t2yq%wEC0ᄈsecFա9CGuNߥXa/ٰ*by_6w$/\L<#YpWҤhaU`Tzѣ1'49z5Ov͛^!ܰ˦zK17 --C7G#@o'/'XF[[>L,Gsژ;\hͽ>džC<񓻏0g+B9n!K0X+VWOK2[vP;C{\Mp򁷴ex \I;ޭ_ѫ&:`ڑS.HE4=+7۹_]YBn=f@n5fKD{_-PstxM~'NTVVƜ\C$o9Hw,u~K*>5oxZfv'f~KVI/1wxRgI_\g"ozhv -3<^NokEH+մ8ΙY߱f 1kٙnhv37,768; @Ƭfog D^r[eFiI`q0;P?Č& ҋ [{knᆩS>^{ml5HPVZ'ficl2VvЂD%=fˆN''{RT!{1Gm١Y=znx?_K9 s_'|sCYx8^L^}]+dey]록3B ի}actvڿ{d p,ʯ2C[,B3T|䛚; On9m]%9@phr=|>04N(Zd~g>C;"-?f p[J/ * 03vK'@E{3yj'f`K-;8a''ᄈ󯢴  J^{Mɲ`9sp9nCsRh%c>U\հ/t*j9ڲ#\:7? sWe"YxUfXAY6J)J3ueיIC<|(WU_Χbe􎿜'v22 {!.[oΊ-`3Aљl&~ yE  ;o̼[ZMw _[[y.P#=h3' -=6J@9!m  ,m١+!s!O|v=۸i q8H^wG9E,B_fhϵ0C p#e;',%߱g ?Toc{هL$kϯ/|V7h +(䎹XrbADoW} _WZ_+x{ 1~{9u7[h& }$Mlq%~I#6ZֳF~̧佱3zda^\n1?ϼ6evtW?wA_j-[-[,M|_.PWWWVV&‹dſ**RKonB1}X-b3mY`ќ?oبd-/=v-ڴ>裦&^AAԩS|y7/ҋT9Q9P_rB,D {ڌVuݦ >#}=hHu[]lGrr\)no7+V19dѺֈ!82μY4$f-Zt^g7eg+8wL*-IXt8k9xU%WՋiW3;#sM9^ƄW#kr^|? =iuM7c{J7_RCꋲ,Y]W8uf[·a \$ = H5yZ^/oՏ.~}Zׇ⸽?o?֗ZOM74~Ӡc6_7ǎ7ҥK'OWGY57ںDgmݼ0'leӦi[;6rgD_2@:ujY"ĀYeVQQe~%R|GӜ*0JwnI:;wLдo}ctZX7!g{tXHOΊH3c7_q_MD6~a,MK$#9clP.)43BFCek M:chu[2;q(@OhbgE!59.Ɏ׳?auF]t|3C$C?ݽ{{s=o1ߜ:^Tq<ؾKt>>8.MTN{i?ksAu,f ѿda^2Ҽ/=&X1Tίyrw?e" XbGP )i;kOH=:Oeg+OgJ{yŚ;`tGۢ?躎 ׆ٞ|v-ݬDdFߘ%2g={Gz1=5> F~&[K8\֦w̹NMtHٹ(6,Fg;k5qct֧ņzN)RQcꠇP=1|عfM -#B6;3 =]ye]GskUdqnmo& }KG}z{!%%{g*"e>(fx @vm.&_C۷=sWTuUc6jxN=϶GFpB,.E/.O20z(J/LKhӻY&lX0Ej> xXD ^)buQ֒įd +/;S⯔8H ;r)-re %ņO팴!srt/A=G5!?44q2nZ }wJr?v_2GtQ6-3{>c"}(*p~z( H-ni.spk)0e^Q<ȷ'SvT_ϨE1SfYaэ<("z^clOP?^0/ -uDC' qId/KgEk dH]?z3xs~ue'/'7hWv4!Aj^]ӻO|Ʈ.&=Bo! :JȢ6RlXzh;Gx54זy"y%_+Cpn*X8ޖ0GgZ\~F~QO]Wn$%EN#۳Gh~{Ȕ>\E+krb.ߥՊi~?=D5KuFV!W߰8^tƟѕLi9u9a#⣯ZJF`˖-˖-knn˦>/ 7߼ Ă@̅\)h?rX@?˻)9<%FZdhlSFcwӑo=gQq(9lٹnh>]3[+EoxZ5YjѢ:;=?I,;ؐ9w]FV7i?ۈEϚo;y~|^Υg.Xt < ˿H#b?_Gɪł+u~ek<˯uOxŎX`ͼtɓ'B~ xaH$/}]wӖy #Ě[fE[ z߳ꒃҙ,zClNJ5G5,XC/l sG{a'#xI_/Vу&x_X'%'AdE] 4j'Q]/jeVŌ{GfgƬyK &Ӓ臆IU Ad0/gݹZ,PҠ?x6h{bk^'_I3.-膴΁_̣k`Խk|8u7>Ǒ?JUxNIj|U,&We;[6-~P԰ wM;WYi;?[-:G @ 4E]eȾXrZ2Ҭ(eJJN;N~Tc 'H>4WHWL1N7bx @Rzr!_]7 &.o8Rvn 5t.vѲmnFqSQX`\9c/dt֧ņ9>%!&qIi ,K7úbzH |T|zt߳N[hޢ?r=08xMRbH)vWcCtlK!*66tC*ȡ{si{F /ΊHĞ.M?PO}ۤ%_kxMMbm얆<Ŧ (Kn;!&xiD7Ăe#_u]C]8U'5-w41PV>dx:Q]F]( 7c  =mQeYzqh)"\mۍ'5 c=?5hh#E<|Ǝw]'S菽qMq#ْO퉌gO߰m?|Eᏻ1K_ia\`Fg4m[I-85ۿb^5ۢnY6 t7 bݸ/bUt^"RMǪb.2yzBF.Bn0]t,PQ*;` P"Ay^FġgnPk'p?&\x(!rp1hjAuN'];5;Y)j@i?k;dsGy(N k8qbGGF{2)?tXnnXb{d ;Ї>?yl}C6ݾpyz޻re:w-=|Ƴ'&WqkJxP$bXrvCؘ uېu;X Czljus,ƕ;Gb3d}hp-';qx ay76#2U8lŤm3,5_ԴW2~Rc/Y8y?4;]gj=c摟<#^z;v\wuZJyȭڑ|SM{NfYĂp2ÚJ6hײC?]k"?n[< ng _{ Ewv([CfxRD |-"G<۟k[Ow͘5!x ucӿ2D3M?8Y|Ҡ? sdžGubQh[o כ}em]\sO9U54=Cw{:keakI~C ^OwrOg[DD!-%CDY6U`u"{yju@# ykIy4Sl[UsUKܿ-AZͪaowzlok=&6t2~ey;NK#僊׌"xaZӳtҜ{;)?Gt6̘?Sf6koɑuε9ތҾ߬]cV3{}F~> BOOh̎ ?.LڸXT Ç"0 ȋ~;ֆ.8ӻ2Fj4K#cáۗyFimz8S3 O߿rt_{l(˓k͸%s262uY:=B֬:(G:5w8;5pkh_<_x>G6\٥sUO޲rͯRlE=HCzٝnJKIDNeyI .f%,E2/կYpO,ݻrl ߐy[>2 "x͑#Ge˖E\`PK@ cxzBgYm0F-10گ٠=e/ei2 z`cMڤkbH6$\LrbCw݂"AfhfRxZ(/$ܳ*f*E]N;|k bzχ=γ?cX,U*DߵӋ|g< ˕׶ãkrbOhQ%lKz5IW b%$"|V۫HY Md&3G=WX0Hɽ =T@oe*=#ϫv4:WTzO^Ω'bz"ftex.3i*sʇn~h练vK~>z衣G(RNXȐ2M3M`mdKA- һYX_u^D~^Y?gkazK|㿋 /QdWes!'DBcjG$c䥷 O;|joaBxZ=^Z!$ޠ`^c4]W{ZZ|5璤KܡW>i?ytO*=[_BgXYgJh iKM>zʤ:'=U`$S&Pn1 ׎އL赔҃Ҫa7APc;6Fe%ϱCeg_|dk?д  [gڧ}G&qXTײOiow?LWCX [~'N>qDeee̝( *Ub ve>|55X܄6J&D-誷DbvΆˎD~^bT`9gk#RO<ۡi~}%zc}ߠHdoyޚ8tD:cgjFS%\#җ5|ܽ?ղE&zVMnZU8^J; kÂJ A!wyb]:}ĵ5+~ES>w?A҃qHutFCb_,ĶZw_uCvVJ )CKA-אNW[-Y -ە:mzו,iUi;==tѽ+6C`ʡnᆩS>^{m59NMI<@`chD"9q m;i%KaɆFRa_s#?n-zj5{ԕ=_}E?B,  =w%A~P/j F9dA(_Vux\NLĩDZZˆH_1h/||5vsg[ku;v;b>+VKj̱:OQ2dx0/#zAmAds5^@HЁDf.%.4YSg*t]ݒOt{3&b-{UԾR}\[dM Ӈo,y@N׸\'xǘ\CMd3+Z7 ߟv";7H_ۺ6 mÆy҆i|^88X`ʅ;n[Ԃ\8+ L1Fi#U ?[]|?~4)  V?k+~K!V_AzGB1wBOkCe6Aùu:]6C;"}#P4]f뵷Xyı>3c;fo:5o8RvnweF{L(UH`9|meEik\:ӹs 19B2!ÙLC QFnuÄsThJKu^d2J k/[o=묳bKz=fV۟&lgE& [a>@дazD 7䖑<@l$]k? evDc=x+vEb#j5qY޺'3`DVng+OLo-^c;F_dsSA! ?5o0s<_f 5!.ݝ#b(eix%kh/w(u{5Cbcz䎕| 8lAj8u{K.UYc7J }ժUb6[lYlYssX6}_~XC]]]YYlҹh XRg۾bM\M.GDy YLZݦܴ͗G55=lAAԩS|y7/ҋT9Q9P_?(iU_Ub3kY3kzy:ڤ 2μKi?z(ڝ/`Խk|X`O\绛||w99)6֝Ƕޅۿ~`+fyMby\r<] 5 Ib3bѳCyh&qLH9[;+L;(ֲmu5ĨaOؚe|9IE/BJV_U/L](@2K.C."Q\GԕgN%pPWa+ka1|ѯ@|R9^IlJ̐Mѝzf؈^:'={pEf9ih8CYI`gb=mݲDa=3e 58" voy95(0A]lNߞCNڮjc PT'"Dtuȍf;H /98 y QQ@Ydeq54.tҿӃӿ'tKj9ٱ(UD.U*uC8=UZ#C_lMXr =#.p"Z15 ˿IzHn2GvV0u[ɞ[/#{C*\e3;sȫOG#rSJ{ZEWȼ #CY.Q:9 ^y wku8lܕCDҰC_ygΣ.9(R!x:ٹ`E]Nt䚞lV"ņ3p@g z0< [7C4q]LNDwMޖ UHUT̗^fAoWvtRo[ v"wFS4l| f@t:pܦRvA{,;,e%lHkWz;Uik\:ӹspחikR}D_vhT_)|]Jю I()vmbqC27Vtwն''D5=.uQ d N\!Rjd. %ωϟ:EO]r6x D'{ڌu ~R,˕t5bZ2K H>z{kjG0D}0Dð\W,\ެ*#Mc= J'‚ >Szzwd(J=s ew,J!suq|64A\|͒LJR +w RcPV=]'F@@"w̅JÞD.] :ېz`Yz 66Qug R 9:4l~n8gz{uUR5t0cZڪMHPq4u@b`ņ`61RM)Lu.1:0o(a@uILa+V".5U`eXe拓GJf##@Gݐ6'{ٜ ž9vzPzj;Wwi|=@ R9^sˊ.e"_sx?.d31c#C{4vmIBۧ?UQLݐ6 %ˮ[W;[`Fg2 bgqVF1Տl7ߛr"?"c0H]'N8/d3C3ޯHY! BoMtTR9OQ\F_r3GLvH=8Ӓ8ѕ]g]wN5-G\t:~hѐs>܏W(׌)Oh$ǟ;zzz暉'vttUьωlV_7x4l~һ{N~kX 92Z|xmDmk:V(Ǝ7>9ɼyY6S+wFCNNvkT׈?Km!CC$ކ!ԝ|Jb1K]3E!A^zn~M'[F4HÜ=@m7i#&`ͷtͶ]Ϸ Yz;(f2=m/};_߿w..M/Kޝt.ܺ5{>,fɇ;~|qOԆ)dq֫~띇#q0%4fE~nf&tHٹM!eps7Q+o}$Q~8=~Z?x"Oy.o|C| -fgIjLGr =mкM?);Bwryvֵ vڛz{kjG/OB7諪"3@i }%ޢb -]nr\gnsmn<9`8Jk坡-;h} N}=ѣGcN! L}{쵯,.y@ $Q;'\DfoJ$f(K޾CEEԗQ>'5[%Y*`-J-bg1~єq~niTde}Q,P[[ixM~'NTVVƜ\CоNA4!&xMxS~<4IfojSD ߵ%BxwD`Ϝ"Egb{H4n/Y[yٚ飾iDmzUiY0}YEhKtϣօ+W&]uѯ|4OQB B'qCnR,b(@]TŎE~ 9 Q euXeИU ɛ=)ۼӊpFw-@i)-,(pVg?G|XIYE5 70uԧ~k-&x}o#_tY+a~ߓ-7ZfxG_WϾگ@Q~Kԑ<#*H]qy$A^zN:Qǩ!\j{ {7|z "@6!E5Xzo+Nt*ȉ< RU†]-6۬UĢRj{l*O[%7\vvd<'6mWtc-d p$gk$Z/o߲kp^&߷)GZP{~g(ԩS"@6!FW;_L֡^"NG@ۦRGQ7Jεc0oHOEMF =|u$ogV(Z $6>M,9+^#}gF:Лke"|̯ꟊ)C4hM Z ^DNhdYP/a[L u匕&F>ҹ"I677LIvwcibN![uJ,%aM[#5r=okݾez6k  үKʝp1_366 fhF 2؂EdOg- ͮoݕ1 |%l~U}畃x:pܦ˱s_m.QeS) K B3mmKg}:w^']D FRh*FBk[ѫÓ_D |fH^h2[l\ iOF)r"6`_~9x5(`k X(ھ'lc) +B3"bN{BISe1*@_f!!,9smEdXa>kD}nQ>@1k :f Tb9E_='>cˎRq5r_|ehY( aTEXBB2+ Xt9?K k.W@ syH5^4 ]mb'.;)!Cy`83[Tr|d0Q] NOņ=͵9ŏ *^#DhbsʉPx:4eAQRGQ %``{I q|[ɁyD(6LpwRM5(%C[kÈ?KS8-e0DT8+C^_EC^ŷ?xM5Z% AYps)-4.$gL5d8WRƕ3VjHf3bs +(I^-"rFSw1V~ yc,IyM.NBf6x :Tx حpbM׮$+RWWae+ ]X!Y)-UHL]'ouMGX?0kJY^: ~z1C:E _G (DCf-JZ^fd z!+icˠ2%Cz[[P+%y<$q[44 %cTOݾiz򦦦-Om_NC8D?KwzL6+3H,z#S_U i0<( Qԡ`YXȆlN*d𣐧ѿLO CQ[O}htwI*աh]:śr^QTRY[Wx"W<Ҕ=UEUXCj663Vزe˲e˚.r| .@, J`Tԗ Ȟ6Uy;ĪȌXlfPtt5,_̧CS Xw a[Lp5>f)'vcb·̹3dyiVmHNGQ0OyMb9/ZbQ"^]o^wnއM:|}/=#绛||_*^,H2QSN;v,if^tɓh!l,Ͽ+6f RhFrCD |<* }YQ$eMPl~ړ*OuL}%%K\PP0-k&j&Iv ;nSDfP кܥ+鰗je C[^DQl}nņk۶H} $VW2XkXvvfeeLl|;[l\E!gBkY|"˻O|.&1G]$(/Gweo~M֟ %4d6J (J V('_v޵|_VaWV:wӸGY%ݠ ^xÑs-^ox[zI]lφuZAV5b3&<4xM$ED~/1[?3_QCۭĴEi;1?408xdՀ7=Ƃ5õCo?;;@C`q(OW[jk|XB3 t1`D*3*-3d؂)R$Bc0ޗVKڎ_ZF&SMi-ovƍvVbZAY啰H@tZ'rdh36 "wfٜONug-")2r<%t+ \2cͯ*eͤPw@c'EaӲǎ[|P~Mh _ cEvNx ؁Y4 ͯ=; 3Di=4FukߙxtC7њرTQ.4ڬ1\8yX`nj-XظzA[XyneVJ*^,=d9V{ٳA,GuGk9䳐Cfnmy#Ќ}f yti.W@.g>pʌ8!HE-AwiuVf7WUm&3,Dc-JڔƵmnҥ)uuS|mvr*`n3\TbIXۼKU+X3f=+kUZJvEBB &x٣6Wm/;51B< "CgAuCٶu #X4@v"J ;'݆"oWV 9#/#lNueC' XWTq9i]a97+\sۊFQ{?Mx2Q.aS_YQ&SgW=U,1ķMRjX_3,)+V/(ZQ:Rbb1VwL#?bDmL6ѪnԯӶkm }U>ga#k@1ҺjFJ 9(ŸA9%|l18>,L/0PHŶ 啕$mڿnE94|^vYej is{&xc+n.i=\}X&vaB|=x'ۄ~/<!{9Sk$@ <0;`wBM`E]%i>Dyg͢J5|V"$qt"ʬMJ]U`HhOl ΨVE Vox\?El(a}_^ mF-2HwBxw}F_MT+sbBy5T6A{.Y^&Rh'E!sB=gcO ^jPaxREXd/+Q87x6 f5UqRWeF0,(u-H9R 7%tǔWm]WD4dJMf"$EN,./ 7߼ Ă@m>~F@} i3 ~ZwCUѝ]34OW{ow^fuuѫ|Fݻf犅^XlfP6{:O5,橜kۍsUL;2μY)mu"?y`E<&l#-7Bיg`aDRFs˭u79w|Cr2 Ng5se:&bV1iW3juAeffeGi`C's$ͼtɓ'B~ gMsII!,= D(rx,;=iEY43oEY0f~[P\P\#t@#eF\#5pO15Oo&fi| XFg<4 &rf'LVQh`* r;ʛCi ZG+@ ,^8ШwzrAG'My1XR5ty2f:d"D3l>&ێoϚHI<9ٹGyp:?rkߵ}b }ɉ]rMZ'rH{S_5ѣWK99םvX} b-r 3gDy~ dgQ6 ^ܮÖw׾GѽuE52T* v|6qKbo3{%ٌ27DmC*8nVD+kBMpkG-xJT93ObYW@Okc11cI_Xg%2dc:CVpbwP~#R?8ɁRrD9u/\W7yFcY(Z6-oV}Xȅx @3\Ssi벊 Vd?Β|˒XQ|MQvpmW^JJ;rbfw9zSX dyEnfV^h3,fKd7:0wi[C~ wULi$6Wm/g7ZVTɼH^ݷTѲtzs_SV#M*n4 N4`bL+ 2.\SaTWh- [6P5oSC*C /nx (a`MG]3[Wsс̕13SV KpG|h}`} d = $V>؆07t@t:pܦaaiQװ˝0j 6ϥ>;g/_87%Ql82@\O !^JgmdjB6Kx XlNEqBJvfUf'S 1 -v #SWEweO 5DT_CgA#Q+Ah,2t0_~E%#O&;n?HBmmm]]]d-||c.dF@-kӀOĚ/( @<3memXCr^֩D9yԎ zmC_1_;{  g矺!Nvɓ'?󦦦&nVزe˲e˚{~_~XHWo\ LNV%'B(iU_m*{^Lڲ38 ˿!~̹3R`&O鳃|W,Qb!2@Q O붺?-qݘ;g؈jbo|l20b8y/i͇>syMbYVfe[9Lە}=-f?LwȈEfƇZA<!f%Jꯪ &Ү g yoKN<k@2D(Ք4 魨em_%a["F`?z Y0m4[Ɩk ^UR§ I#ƙkݔǶ ^> Ea"JmqIrTuTr8KxGuRQ^uݬ) |f~mۍdwpIŬ.pt D ̬NJ*؉5+w _'kð iKcwaRfRn(1ա:phmߝ2~Pg޽k\®5 D:qZxlԍyXg(abܱ98Q6.ioJr^Ea佱-0*9xdՀ7Lﯵ6oK9k :o8Rvn/ņL"$]!W<4p D\}P)65.<=p厛ק;f~ [Cw1-drpm7jSpE,@ҹ0g[a_+G0atw'RKu}KϞ~Uknq0-!Ӯm8|++"Do/ bSx ^2YϾX 9~ /:Dd <%7; WWfX {߉9/#;B'OqRDcF^5%dx dX],C,MQ!h?/5ɱFlQ8o1A0at5&~ }|}TVVt-MCJ-%6Ѕɷ[wd*&G;dS"XR_ »⁗Jsז"y^iP:jѥ^2N8ExXS\0ÆNXJY; xo?PSWr+@8#ZzkK_;w:bjq҇<5kU:ҝ^6 ]ra,߇? }םlƞoknn_C4x H:>%l*(CTƱ'ۥ8=b!WR1uUf FI.Iy)sˁ)0v{j.KC)Ժ]!X-"?'G]5sq/nz9?3Qƒ3}pHk@k35P=(]Y U:҆\~Dc'/Ll @2cC($Ah*LSm٘91E*P$QY*O'Xs5]C9:$9k@3|5t==r)E[rQs.b 䰡?T -} 9>FnO +x3 ~ XYEn^ _&Yh́{TzL$ 5 OfxFwu` #j.?+gl$"ۅ5Ŝb#)TKy]Y"!j pc.d2MC[#`Y"?]tyFsX"b*ѳJJzQ<,ɻb)3wjW{TW'J;Vstx D Gmlt_S;7iZrGM0SxKͯ-]TuqŔe$ w̅.mzגNf"[PDzN5:>PG[ηn$ ƺ02W/3,@jɞ6chݦ&s()4ς׺_j=7v4[2̴XVԃfVa0oX*3i&y i [FieѱHҋ C$fs=`֎Kl Ag ,ds=t1Gܗ%4s2.؝?:QXw):Q{yO b Xbg iPT@L%S$&vne4HD+gt1s&n&QlX]CQڎРgN/WFnX 52e='b1v`lc? A(* =rN^Us=@crp_D2%6$;rĵXb;sY ydÐޖ>DD~ ZӞ6A=ݝ|e 3A]Mz#HDo,6a0o^Vزe˲e˚Ų>*67v.\5RÛoySAӓʁb!f/6Xi#=Y07]>`Խk|XҐ9w]F2:9kq{1w^3&GryHS yi-:IJTw9|.5;0>t8=ֻ;h;}6Ѳ.\^n)'rE/BJV_8:iW3juԩcǎe0b#߿K.,//oLܲA$WT ںP^ EZ,֑l{Mi OX4EE#C쩞0- n/ AqݹYYYd&-:"aigWmdaQf;ٿ+g,..-3p>Z2EDVjI]lCA 52ϋ~^tS'|Mtվ(h44u~ ~eh:f/9 +utm].tqK.Ql<{gɞ^*E<#0Ą)n7~ ) Gε&-:kyѯʆ!x`';[uCl2~ˍvTuҦZwmda2K\ɒ%|]."A%_T)Ĉr}AYx< Jgs+ R][j]:MJ)ɠ]`h  C&P'x{ ) $k :f Tb5eVum2:j ׊2$d(zBuKLo\z"}D"㲩+c>4wã C̯n!!!X"9:%k ^>*04YDE5dA۾ҙvUgr1cFͨ/!"DŽq|w*3).*ʢW/(Jy,HG@\RM"֒*XgbǺĘVvK"HWT5l,c?h⮬WɬvkûrK)]¿J8Z$G7z{vKP_!^><,A_7@lN&5LrЮ+} _Jؘ9wfQWw/ff;;)!oc%%q1UO,@tHٹMAIkvaUOW;ꆆBzu"ޓ}Ui]nt{M61&띃'xFkW 墑&ʾ̠^۶xrq#&UHx ^Mx Mj3Lu :as7듢=;C!7U6 )/;/jRy'@dO1nSOyQ;m;y&}BF& M. whTဳ:;y?M?XG Dm`T\+GU44a`G,8pF&Xj!\6Ճm?$Dam%%4L[c־E:_b>" F;c/Uwx18sKBƏl xa3U~}I!asrXV`ީim7n9bpQ1k F;*BlFMУv1'}mbb3+e=sD/^C'(2ctܳF"P=~uX#6dՐ!}>OAbm:AbWa -"0lFw#6 A+؊Y^UjR23}#yk?zBʬ2#7a½zN5{cL_9Q`uc#F!^12P6yh[a5.>; \8LrC_yzD 22ٜ3_3lpbwPn>"18sA^pb]}u ]RQWW1ŷ.Pm= ˕tϕՖX0RG<{؂ 8 - 5#uOSi½4Cr%Wq+ܱnn'D~CasYV #ba)0U,fR_YuKJrò;uBm\s߀[}VhV{?u{Dc">z9홮] 8I - 5##C6iܱVu(]wN'Pf~CaxlP]bFu0(΄PV>J]GŔatA{&ʪnfe?ŋ?C_ r7`:ǃh&C_i+a0s3bc Ef 7,|hZ U+nci:vR}1f(fC3$E5gqdH4dV`%VO1‡T6vڰUa\լ-≢Qxl`Xbe%}=9TBc[2 ^,@t:p\;z$Ckrٜ4mmo=^d29(6yPv&|6!走tPjvbN0*?%[`~̑< [qV.J{RS976B'`[QE . ؈^1=9"hV( -5 H[wSM|%NTe'!}&?_(9̞2 x:9>o=+񯒨&ÇYkiKx\aq^Ʒ!G;,e!?;<9䞽q8L:~@tZs-XlW qQ H2w$'Dh,6L;_`~2`*El ԊL ~)!l^*I;a7M٫Y3m/"e&c''>4$Rn ^*Z)lR5*6FE`C&Gh]hS.QZf6_o'\ÊP . F0\r uH1cFnX䎽PD4]Ii&7mKXJUM؟;B6ֿVۊ ڳɡnppa섕 ^q0[)rxAQCM(7 ֽOVKn4&w|}پHHfYfn ɯ?T ?@Ѷ;8&wg3)ZQ[upb"1kvV%^FincQ>D 'k .C½ Cg6&jvVL TfP vu 4Tϟ_ ~ELhFT_=ߑ;uHo;\";3*#zY+? z!@B3W9B͸)ұ6_2zX3<*UG|Y1=Hl !u] YA hݦլg!CTULBUֳml@o>5΂x D=H)|`tWn>`*[{V:_92z=,a o. 6K7WUmnT$7!v@5{`GaxN51Z`^EmmKg}:w^=+yh ,CS3pbCL0^EL(  ,*ilV+(x D&qR ,jTN$h}G 4к=1ԽP:/4l hnW]_#^njΩw5,Y*99םvtCv5hQD†"%&׸\'$KEݞ sIy 7\)*X{?Yт՛HjYT40MbjM\N|5:Z1*V\:kxdCbmow0'Qub5 [[JpR:8H w$(6*h&)ƇxGRSo!^̦gjoЗʂ_/(}=x X;CzcQ\9c/d!'+Zތ:;+|\5\C, #)*LsIܿ zXdznF6dީKs1{wײ5oWB ^ kHXQ%7y<%ɩH \ctәaQ1ט5UkxQR!;̗_c~M r&9zdLIQM`5Ótb_m7p#&Xؿu[ۮA GD$vż\/Ys={>#gΙNI~T1 πCz((@4ņ4u{_:'W |΂W^ټ4JA`ݻϵw3vv9>1$FvuJ2je etک{^ ^N;B7^L˻O|F&sJFeJC4-3X4ϒR ED#}hYe;>~ JwrNc#E_kmrpYw5wo}`1Dd)} >øv^"x ^@Ǽ+9x@Jv=y:D3{ E[?v9J.Ud0/Bh3:Sx0VwX֠9vh?dr@t:pܦZoXj6ϥ>;g/Ufcr~;*Vu/OM _a!4 $+^sv)+̯$7 GܹltpǏҊ6-;^8XQf\hrтՍx @E,Wy?]Lr:xp~st[ O=~=HgY t|v0c%Ϯ&ݬyiJ͇jѻ` pi]|T i7:\CTֳEZD ({e'5i3m*xI 13vAyrr\o;cMhzf6 rAF32(:r'8U%۳ekjx|>X~~=8T,p {l2ԒYZ ^fUɸ.;Yfހ1dX>vZe|KӊPnoU4.P-P -Čʠ>MpͬW/Ŧeю=ǛB2k8$2k$_s3Bw,ي^M@wmqw|.h&ݨP;>?5rO?1:ʒܨ QDHE/Qv=fݾ]%V|h$uHq9{e3+Oz'2 2O?݈?sXpNq\Cn2wD`E>Q䇙Q\FV65 BuLr~(|:mXLFg;;yvYx{IٹF5&w !WLvNqlCnQ*Urera ھ5dH mE¯(]"fx @bXn=f?.&=\z8x*1V7dgx7(=vJOGC swspbwP n<>T?λ08HVĒX#lJ4,)K@"e5:BLZʄ:[/T5ã~T 8gL(/Lxg%ULEZ<H!^8*C*ʌ<~4dcЋ+B4l.?uo-4=3T9gL(/Qb%wYS4H5@YH 7 K\Z'V gy+lk1,IHy$Lcn:ҲNz5V4 mKt<+! |P1쥴Č.KJoox D Gm 9fgksO+g7$KͲtOli%19ưWRno4x @jRݐDg]c,y1<=-[v`7(/I_j-[-[,M|_.՛oySAAs*rX@?˻Hqk k XNo/bVz`"F>ؤt5aq;JX:BnQP,`?b+,\^y~epk :o8Rvnwep6ϥ>;gXdx ^ɞ6chݦ 99םvXdx @:yX:V@kzZUv)hmr&~Te^| ^C bA&kq/\O,$p{'ҤViMybсk2DMS g!oOr1H~r֋W刵7\X)zzv^(;mn$ᮙGLboimoWVS3f= X|4C?_]_=kȶl+V+`{ȼ`|)V(x bʰ E]e:!_/ցﺮ.)eo(kR,?ˍύDZwZ>y~+<}|^6R[e嚙jF+YDd޺}Ȍ'k6Wm曘+)LܦV4~VhBb}|A;ަ_&te]<axHὬayvHQnZyoᔤ:=f aD_kmZ8ବAw6gJ515u+Y7!+vJU,QעWӔ:``*PT<.Pkl9{ =t>UQl醮w%5T&F%8@us= WvPwUt~Ӹ̓ Gݿ\M+/^mqFV D)_Qٿ{"v4Ka|7TW|sU[CuS؞5]C;A4\"raiV AU$.\3 %w{ ][uEc4NӔb^gomu{&us;(W \V,lmn=Ξ$dkC\%:B-{Ȼ!F*V]l,!ްX,B3i6qCT!Cx셖[yxòWo72ğ1wd)sO+,|}_g ʐ'|hY]A~W~~ӁOS Bw7{&"BkG|I :82Կuy,kJ/pV#SY6]ZmlMeyz ~J ^`_U |g1*g{rӖi Jw5eߕf}R1 fޯ&w(P}uN E>q{y_+9D"K4_q7{d_tj .go)ޯÒpc#߂Bewɼ=kLAw{6=v}IYŏw]: J 6nhrr\o;cMhyeuxьn]nAZANyPF=,վeGky~-UcNo!.A=ϛpCL)Hk`}FgOk| uVaSPuC3cW[H<4? r&?k+A.qߞ=}ݡ$\$@ N=Z9_Ml?$OnQ';9i3g;t$%CzOvUUY|Q|5<7H~b7$Iy){w}1>kbgr2#jI<ɯa wPZtH-;%))ܤ+XJv'WMilӆP'ɞUKʣ@@N?5,$W$U[j;B*"D̺{C~ e O<H!DK@4SֽS]_lQ青{*HCVM";4oikPy_;@(%FT:޶(Dm/ W7S%ذub;YdE& ؐ#ą%g%)OW]v_O.$H7˒ܞVW.ݸ>=Cir d# h1hHe=@@NY2k5FZ-l:l6QT(.fѝS3wDeQYFfb] Zþe ְ^xݠ|;߆XRG`';N5|&44=*RUSfݹ.= L,.b^а^+5Fp[U466n^E ^8{.,:pܦX8/jk\:ӹspHk5y唷e"ܹ*9(}73"ư\ ?(tTW14Tl{JtXm~hƊl#ʪn`QD԰~>5sXHsNQ7T3A3uY*JwT'+3w_W2-CV{?]ڿ[;h۵Q\F+G 5v _ӯΤ=mкM?)%;=Iv¯i~rǀ'$'3Ԏa-,d,ΐY/ydCO/I+C)YA^u3jlPM jv j'iZ;^w?ȧ&(oE= vtd%Czk&w@~*,늽>k)_ Q}_ot)kPplRDYSlx:*+Jfd`qA_tøarã6mhZ$5oH0Kf] [vd{U%f"MF2[&x !ZXrn¸!^`_U2k^:-Xvf)Ya 5,jj2MOk&ȿ%dUTVԍMXַIȞΝ7|@Pi5}KUvYo:/JU:'q^Hln` S՗NmC6Z@*,y[)w`()Ļϼ* c_N,qޑԐ93V6klfU$y1]=4:l$G;#}N (LQ==so<;OGJ}C8їO&GФ<!O=kї4#XB^s(A5J4hcW#-! x䤾dWi RQ7vJS`wQ_,9 [+iqjRܠO `)\+_ FP<On/F=(ڝ$)C%'Ȍ;i켣 J+??4țKAX54XӪ'ԤViMyb%Sx_Ic#V7jl |&hH5΂x - j Nҕ¿ۓev|]3GVJK$PRW]se wb}XE\Ŭnv#w>bX]x_`S,{J:@T(u͔|(J ^`^ =bӴ,! ōy:oPNbC.8lKK|F.'$ؔfWRrTd粻,=V?i$<2<6?CN,:Ck];-qU*\#jphMт AsKdi@)l1F#g.)5\IĦ(ČhBNog$Z.u홼ai\K9RLﯵ6oڡ]Ϸ=k /$ϯL-.n';zs5=\ˆ^EfCnҝ30kb'zQJ*U V(~n4H) Gݿ-Z^YY3ie*V^r % _c(i1FѕN |EXܬgG'{|_y;g u;kbW6M K{!zB^5sٮ[|żͶmˎw;oAdD HsFI`'Grt5%B JJ+9iӬJl&0CrA[ۼKUy{5 5 sż<2wXJo8RvnwL+ʤ-IpoO2b7_?I(sO+#@+(کDz%;_j&9m%%Qomɮdw3!ϔyty_꟥e vZU2&t~y}ɩRRW4 ,|]*6K ҝkcɞVJ^֨_CUomnu`ެҰVuwOl+3.t 5i3m*xI/H놲 Ha*699םvX*0Jwbk8D<|!9;q^_vHs W7⑑UMWB H!%;*0KОeltb$lr˯_$Ҳ;Q 4bVN P2DMS H k[9`yC;bwkBiEȱPl5U0cc1(CnH m'l2O{QhY^O|rM5mi5۽r^Pt׾NKԾoj_/짱5?r=0l9Rl[%vTZjH8a]'n`orx]TVs)n~ՄDVMR}J;p@_pM7#`VBhll\{5TAYHf=>Df)ekѽuE5t|ѶN $rOnO ɆEL(c[ǐS#o+EC8s=%b53f"Rx"] 1j#=xX`ט*gfI,ۇ*"ȱPh\u=Hl'zt@9("j-LO>bE(>uC89dp("ᴑ_(p i##` PoXz̷kQ[Ob><"5frMHJxCٗ 3QAM %"31Om"KWO#^z:x!XZyy$]@x$!:p 64"&n$zT;Y{^nTbɳM,0k/5oGQ0JN/tx3!Bm~WSZj\T:KLŸo e8'sS|_]WW1 3dJE]6KL|HftV杵2LsWL$bC_#.]?cs0,O|xD=']?9KAbȯ,s HCCPn$-(B4/Ohr͋'4BHS,vE V_7"5zrQOnqG y2{]ίZ!%xC6QAC#2DOVϚ}-asF"Jؘy52%CzӫG#t%%3~R!;O!_fZyyѢW桻 UI 5dɉٟfeCuqc=NxѯwEoO5qxÑsC,Jh'1ޑG+R K0{T9zN(QmmKg}:w^1e$ c8 {]׈AiAn؄t!4^[:N A>_dzIJp‘I{ІWB㥣DrYD/KegCeEy" *}J޿(lް * ss1} ^`4R̞6chݦ˱SҢ-^Ò ҩa';z̐M\AXS;Z,G.;bЁ0DCEx]䖦R]&94\d4x =X=Q2IlPd KhЁtE%hwAiaٻڈ`SRPWJȹ&ٿކ30]HuM(k65=yYJ9c!e$sHTxAZSbD33 f:'&5)ǶNORU?57E),/e֖LJT5a_C]{XOGH t,pRS )wh(q;Ã#촌$6ydc=3`̽A(;Eİ%uh<æ%v1AM'/)9)k){cظ*[uCkM5rrcjw 0L2{ܛeL1 3^׿=GBd$ t&OI+m)lDDZرc˼gϞիW‰B~ @jA 9ևD~45QK%odoA?;?LThx?o76:3מɱO.ʅ%vl(p yJn\V=8߸&fRChRxY)ફ2_o[&w"ٹsM ܻςlP#3{1Dn_9*\rUu% efΊ `#B3p]_x ;Cu{.X}fqa.8Mї@|65h奤# WνAKKߺ}{_$mwS= fc.6<<53$0.V몑{&@ n,5dWϖ;Cկzu!B0yMLl5Ќ$x묪rz{{۪mV~2k#d<{ ~F2JE;Ic_/վL?Uޮmsl+6ٻԛy2-%8/h"O6 VPԶ9ʻ:֤E7MU mYpt<$Jw/;tx%-c>^{Aum]f+܂4d0,v);5:VgSuV2!^$l5|Z_9|?md}]/{}|q|x7tWuӹ [xM=/|a[^gɶ9K5\O.Ҟlrsޫ ꦾhmWnk8\7%Y^ձl;m6vME4.4,ڋL5ugw߱.\s£ op^{|Kiɟ^XPf'7<Z##j141ň`᪊_G\ȯk|JżG>=yw?ؽT#pFYRBo\|MZh zjۜ%Ds8T~L=<ֹ~fj K>-t14;L'tLԔVrm \zY,Fc1YK /\A yp}§Vfc}M5r VQJ|TvlW%v$ eo"mA * ^ZDxg"EUx:q8HpJ+mlvIhTr>} 0WG'Nυ_ua ? `bks:2y Rd'V'f ۖp'qթJ#F)UW˖VR7uL鷞wKs'c;cP ~a>'{]qLDwʒmb>`єh*DBػsـg^ 4"KVk}-ި8K.Q4|Kr+瑣#݋| 2,jHD mL 5ɑc85oǐ ,W>:|{.I VV- F徟1g'oZKl_p-_\`Si֧ػg ה+IiyBY?Ш$SL_|Jn$ ߯%~’|z7 0X@t0f mN"s#"7pĉhoo߼y8PQQ!wjH&=GS BesgY˝8r{H;r+>Aछ|mp6ưs@ wq5}ED"LZiKgk$_1]PP3/ E;vL|ٳzjQ8QȯHѫw>45*/;.Og,' i9D(*8`\PHnt@re2+ )k   Wvj00@Œ7p,=@n}-4-&:du?w.p9_j/p]074` zJ_E=_Żpޯ6m*o?y#k]=dbpMmP߬(mu&Y~7|&1-|R0߰&7KΝ;7E)k #^0o^^#ٻ,}-jCumnWj!yVDdȒ=u|aeEizHe<ńo8wWD7b22r%Kd%/]bp=vtt`:| - ^ck҅ePř+ JGE\N%|CW׫W}(x!^Zvi 5 # "+oUtC^"_ a¯)7"+L5ɑ^]^5YayW4)L| T釧7&h^QAR=|!=w5\E^ou=w|o칙"b:1UUFuw?:FUKdR>ёnrb!wo, fΆk ^J;~^ ;d}4n9o,9^wE烜1ڙ ڷ쬎xkvoRmcWۯkă/o_U)Z3hcͿoV{zR^yBO܋>ՙ`PX7 .$CN_jދf޴`0i/{s7^W1+Pbt?^&3mPu5f'|J&lZt+"-(]3\ڽ ^XκO#,j5:kDc,ٔJGEϒ]B"?i l$oG ΂tff:r`(@a=o=G{:?ps]Y0B\u{C)l ȕ9/p+= B9>e$:Q請=,rU-.9|W#]i]BOfDXm/X,&o8E~ Wc] /nVwu (}(Mu@p3cԉDIX+LCjzfz0%d=ok&xM拎y;٨[S&0x }v\`r טx( %٨ @ B 2vܫ %^3u}($W>"нix @rnXJ}Pe \ܷ0n^a@j@ 9s̽Mnt6i_3Idh((f[ɛG#ox~ƋBܙS/1svbW컿DR ~+Y4T\0!^,Dbv,і6J /;ɾ~+yQ.Ve__ԆqT7]vŌYZϲJ\R@=S\'WvCEy.}H-$Kv54Rjſ`FSlw\ц7Vm8cTSi3ܝ>,7bze`S\V}x~$GVr[53}rRPrF42`3Vd0烖89j\Gcx~,lEFC19$ sτ' RPpƥZJKkՃyQ Y'ؼXa}Qhj*cfqlXŚțj~MϿu(eɞ f:ky{3)<*pýy,L#Y_/[xNCjZ3kr iyWH ]BxI瑬%&.b6?Gw>Ox"Ԓ:7>Q,2\:Qg}>!)ş.l8xߔ3ɝ fk#W(*/ )j8tx%cy̙wpp/^%. sDM"T1 *u kEGE^R}#?>ճj~ǹ`6B 92n3#}0Cܸ0\D1\)̞+w C)@+\;Kg. Ɔx @d>lX| h*p61'\`X ^[3 k_!=-k>6Xs§ ng[󿕛}22n&<!Kz{Ͷ֏t?ɦ B&fӓr RPPn$S|1o:wsgDk&biiiq8qDCCWo޼YV;|S{[_ Ƚ Y˝8]s}òPkrssޫd~eY0eVk[Cwn9#m ܃;{}j_]rǟڸ_gkOI+m)lWj]tܹss8YėyϞ=Wx @Dk=z7,^3˽ ڦwCMg7=FWf>d] GH%}B_\[r+ ٻlNŵ)y,yY7F(b&roTٵ-}_*M1^D=4vU-)',4濓}ϗGW 3uu~yކK6+GWRSQDC;r+ 廗LQ&TjXk/Yc"&F]׼_oB/]u7:K{~1/v"6G,">@~ëY83h-U ~Oi!|ۏ~8-q=881T?B|n5트E7G jFk:;;VN=^Pf[3ȧ'5/tWuS|m9bn9Z1uuXɱ+k뼡੊OQ^Yz+ݟ 9;ߟ }iw5տܹ {.ty^Xo9w ~:d{MamsXG/( C 廗I~4Kbb͐rXn؉~md||(Ƨ_t}a^n !Cvnȳj6}?yȻmW>ngeLr8Q٥|/jݷdwGu897"PnZC76gɶqu*0]ڵ%۪j C}K|L֬㱒1٣~s;Oo-kۏ9^My@YK߿ dM.2&V^<}AOwYgG彏^Xuyſ^ƣ*jw-Xx/dQ_x@KmY|җD:9 =F_Z~EP;/9PϵYrbpFM^]~U(k^P*s@ "Kcg/]<ǣWyC_I_+04fCrʹY9 Y=z4++K) 9&wy[l)9uK}jIQD,Ȉë,sxɼo]#ϑa^{5KȈhNT@h%6] ]|[ !a믻bR.2а' }xY3wldJN{.afۯf*=sxWy!>p?'Ua󐗮~IpIy{Ry֒ёno|| bI4~y4哼?)%DܖcR.xKBaK{twZOHkҞO_24w;ҥ{/}'j8. B"6X+·(=8E~;QCED .e]/&p']0]a%*[{(DxB;HL[摛3,h.1n܊<+|^Ψ|y~ EmƢfVt,h zj:\ՖAxO? 1J&Ġׇ~_f̻Z%@_{2dbzF'oF '{'c[Yg(j35=d5:VD (zrb9;R~CtdD_2kM3vOҩ"ܙuNi[dp#+pkY&5Tnw?:FwܱxF5 ęcx6~l o?̹PȮ;/_^y 9:XN29J_2naKD4b:_{Y չo~BGGB c |%)n_h{_Ƈ4!u&u.x5fxyьw5 mzb31R֝ۮGb$٢]il/_OOD5m^+tS"a )FXFƺ ՜PFtEe0Wp2ʒmQ7_3L 廗3;v.nцO|6I@yax L~Ó "afn|r#c]u6WnlLG]LQsۗy"#݋|/N ## %[7>mXvR]Fԓi/p [BVGrk稟(7Gy.Y1[{Iq lWW՞RKvn,\ͨN~]kU#PΥ 9G̊RǀQaUU]vgى_ruC<.W!fQLWouv8Qzv+yVTu(xR#5Q,---r3'Nhhh͛7rG/f~3ُ|xFLP]܉.&wX@bKJZZOԺQSsU-Ebs׵ D] Νk޽Neƨu`vZ3WkOI+m)l~ǨVwwwAAX2H7д|pҳ;voڵK7Va͹Xe:|eb+-ѩ^n{zpI1.XĨ2`MU&"k"95# ;A}Qud|GmF Kl&uD,ilZ={D+}""رc˼gϞիW‰B~ Yrk2_,8ݯv/%'~>dׄ!Ni ,=AcK9pk<0YSE5ERC8}E;6CTCI'2]>r&uvnY2Uv[6rp^c㩣k# FgDE6n\1b厄PJ*{2eȨ}4q\F 'yQC"9(Hf֗ DxgSxۑ‘O -95/k-rsSbkrK%ר/l,/dIxqA0v(ObTq<{Vg\^g,_ Bn%:dr0o0;;"/'`91Q $)%c }G-9|e犪##(1=J4vvZdwâB ^`5JןD.5`Y$6k^Q4xDY^gWkoG\x<"&UbD&mJ e(=%Ođi z]5,Hfeԩn°O]06(RB?@]I&,/fIIc}.5J\+΋JXD~WnFr^Ɇ'!r RՊ@5Q$&1Iza"f101q.L0J$iHZb= QFW`v=_xEbQOlLRCwQ=@D`0(FuJS`(Jw=\NQDA1| &j}(\k摗9d3@r֮~G,)jxmw`d>Jb3f1n#H1X Ex0fl#i2v5Ppӳ!X3-VDxg%+lښۿ~;sx奀|?}d}4n9j͠}W}tPM.N35f\4>c[h7Yf[~16u[Y,%/5 MS[`&C,cxnkGy`.9ȳx#i>J_3R:Dg%x @d>-Ww?5hy%1htlϸ͠f&Du\:6:|yqW2#$u֎.G៟+|Q_Wr[>q9=)7zҪ.DF%SuE`Ywl)GtG\J G;^'󒰽WN1l j0"Qd%{jI0 Q}\՚z۲IȼWܱX =owpIR~+ˣr_q׵vZvh/^џ/o"v\=. D"?h}69A23בNWn-aگ.((̔/z-#;&{Yz(($Y{d[|iҜ%OU~rSO}={e bxmٖ{K,5_Aȥ{Nopzzz.nl8=~&$/.Bk>6Y97cp禎 }??hH5L@g)6 ŨLxxeBn۵mΒmㅻo޽8@ldP^#}q^dMCD* m},{ȸk{>IymQA zRK#B>9k'ʯ~C%X(yr2vׂŋWv+̻e y?.w6 v- Wmx45Vn.h_yum(u..$VkN`(i#_ev^|):&V݆Y /{}|q|x7tWuӹ [xM=/|a[^gɶ9K5O.C~Ҟ{.y#rR%%}lXj|ەX-`|sޫ/aEn/)|qEKH_̙,'3]"Mѡ5./3S rYN)]xyk _`4A>{z CWqzXKy}IG#4He.!<ξs[ e)L5ɡ.1.Oߙ #/D-,$Q9&;Ev_)/Cx6gޣKDz+X* 넛=W#JWnW1h'jאm%i^IVX Y\xq抣#ݬeLjc=3gz.s26H }p3={?FzXMf(,ƥW}IHb-&H'+2iD| u}ry s G.·ߺ=GiiKi9p ՜Q"u.Ԛ+K3~8u9t1qv=. jڥb^$VR1G:f_ݕɝdbz˯n`vO"(#\6p4箆k::B_jk묋CqE[mY=_`RT4U ZJW~LC_5 gZ vF&~Vq47M]::ț-D=s1ZV 7T>{.ztgן+刦#>Y ^ZH2ޑ4uP`.6i "f^>^ХnB}7oԚ%^svKY)~2rIl\'ژl[͊MK6Upw=_'f10%֧yqZ%;KlA#%|wɚ5wK)Ym(,:duR)⎑_'@w=UPDGI"7pĉhoo߼y8PQQ!w|cގ|ߚbx,Nr֮>aYqv=g!)#2È$R]9)R8 ߞ;u[޷:[-j/=դg@mxSrv=oy,_I{#W+o=}IKC}֗yOӳNAk`fC~ @z;Cu{3֗XKN0# Y@>-b r3xs_m9`[roci X32 H?KRy>WE%Gl L8wT-OM::c|MD|:,.oSx @R=q̽M?אS3k{Iꩦ5v!3kH|Ģ,%H|I.Ft)&WY^9'BMd4~Xc=C9eHWS_ 1 NuIK'/ ˃4f.)^n[_A"vVM:;dQ/, %Y~ͭƤWMWO5 Gxs?H_|/`NBx7C_i0ݥHȔY=+f!)o&Uara0mJΰlB 2v+R_3j}(^¬f J`J>] MnV=2--Թ5 d H$$y)*YSa`+VcHCxjҔӰC<H_;gx(b6+y 9B|`K5Hm֢|O fa1iPLr<<6ČՎ0Y 1I! *3#EDɆe"P27 "s#i5?K"'5k 5/ /ک."i,%kbQe!e;胐Ϛu-[g= (6FjֆOB$$q\e_0[oo˝DB )G~SJ ?zaۗ `;ah(q;RYσbaIhA%( ]x Wnf ^/MtDSbKSHviwYV<%Ƀx $y://%' yGXLB3#SoV۩/gO<'dZI~zZ3^o5$G{u7=#QJ_6|Ұ)yWL y7C$bqb9A,orUo.զY *61{&׼HżiJ[=t0w1 kVJN!Qwf+7ސP2'a9% &y 8Դ*\l0}]V1ʩoG\J~N\mmbO"03xFtB_W Lg1T5ojRbaä̊9GOr[7R&J&( Ix@8؟3/$+A u/L~z;q-Zv1ХrÎ!K v_u5(gWD%qSx @d>欙rwI&M{PKEmaU+ͨJ#Q,hZj<~Yn|&L62mؔ Z~>'>sY97ʽRd2p[u5ZMA롎~R,c"Sx @rnsְץgDه,c.ZMl2ug.e7L]-$/JJqbQ˦ݴ E)#&6!.|{Xƅ#?0k`֚8<0ThAŤysC.eH=du&dE>XWߥZ3wt]]XP'>dVޝ{䅢f*kQ拎yfnkIG9<({lO=KD7*,"vO`(I\ɑl85oG|;͉Q/ a "<.ʍ2O{zI;xa%_6v9 K5%q4`x )5~gf7˷喙~8%~`h(q;vr|1N0e o{(9ը&q4;ܤӯ/ap0>}ZTnh.G\vut]2n",6 AuuE\t3 ]if3mƐS*80E??!QEh!7_XH(x1"$e ɫ5}H<\C;ݺ p G8w&`D. ډM1>WĽLk"?š¯/G{t7:D;/DVH>2DXTw Q%b:C:9>|0T'e(άMպZT0Ǽ!ex6NIdm._ɰ~k*^@eehN:cľ ^ۼ†$}ZY33$;kmzE4/ S'3@ %Q:S篑3hٵ{g,0-mbq Oaef$i{n̖yڛGԿ48B]#P(>\v.B7t┎i,cvrPstۼIj8tx+>ؕdŸ5(@by-Oȿ|Y`(E 9NdBg^fOx"YrvfҢg!+7-cDzRkYuQj"$|[SJ Jkc!' /fi5,KӝÃ;r̘+Dyy-OHT]4%>m2tߕD Z搔7T9lN`WvUwGHI ੳw:T}%?hn%7G:J\xz~Yж|Qo,oeyXYb|YD_aIKJ16Y̝74'O֙5 'e f5削J^mŴF.M4(g!2v-zX63Z7{eJž#~R//r5/nN!WvD=0wrP3Rlxr G ^P&qXa_Hʛe܎2,*žfRT^;[㕒<%tC.jQaAe.{#Yt)^|v8ShxlZmՍ;d솵-3M0C_BES%޴=J 9|s~_s뇲4R}9"jؔ9J )̕'Wr˜%&q0e"S"D)Hʛ%x(W ϧ`1RܶhG-.bGƘag#ڪI8KEG rʔLċvoݾ -v*AEYX mɠevw1jI2vRzKɥLYdW, {}(s 5_7nN_3Blb`+\XFEmn%6FI N`(zU~KrGD:8Ur lU27%׋[""F3ml&]>!ت<\zd5"s,@Ge!g#ZbB%%4)bJL^Ee΢_LV]ȉ%$R89hzCQ}=KnMY`(1CW>/<yMF~C&,*gj,[C,^5?ln#&1 fnp#urmyizTSى^k[fOr*HO18(#3#}r~֮WWӲ2! $b` qS%%D$>uM1/hJ[=ҫŀ۷'Kk3/|JnF<S]یP*e&NUxmobsSl4H( [j}xHEgy'N_sKc: =uOફz:O71\,k:D 47bwI_gP'\9D}jD)mӲZFE•"Ѱ&n~SE+\gMd@ In|6t_A~ʖNr_/ք2el|g,0W!dI|Y*񑠩` ̫# =@!<>ͰS&AfKK`(z~2˄:e`?:ũr :{+Wbn[^gU/nZbE8*؝+^nTgPG):;N[= ^X;kSUD,pjYVz\K\GxZ4B[uٕ@KԹ<.;k$f^E_bxzfIhHJyKrܿVxo %~,p%ۛxbE!{fEDl39:]`ɠ|e!4Y H$/m֢9/ znE- ̘fyqRI=y%RKƨ?*qED8%2H;;lrGou6ѳ۪D|NAOE;x&UY/ }5p7QUVY>5$G ?|ƶnF&9=.lP_gWüSz_|ǘB]]ۄա(f2#Aff >Y7<1Ҭ e͙sq.͡|ğ&faD%4%6F]ʌ4xY0qg9y8gڰtl9 x o(%zu 2<|nrP[MOث4E\mՍQp̘zY.6@P-<,Zk#Y斛FwWftJoܨ$ݤxC;k<Ɖ7*K,Ae91oV$$ +OMQƞA6&&2gl?Sk!({9EfVšDR'0,"Lq{\)61bG( 6_D6"'*iou6UYM~WY6wգY2L|Xv#` 4&Seܘk T˼I7M,E|"rn*c~4Qk=U7?܇04ܸ[}Hgk`br֮[>srR՚q}W}Hgk`n*הۋ{q6ik 00[uXa*o&fb*ݲRoRb̖ epv*z4W$kLw♿XRSo^{{JZ""?F(Eewd6yBIJ]Ƌ%;br觨%誑%N\:|h5Ӥ^yN~o(*ZG /'+1 K|oє!^`w^6?0zY S?"!Ln4Ҏve:74!&? =mJ#ǧAK{rx6}]rgxOVTap}%^eh6( tG} Q:+5ivIGxғn"|d ^` 5&8W* s̄Q#DDMú1Ц0¨=ؽdntv{hbV:QGĝ-suA3Ee}WFVd;VL1[:!Sbtt)g7їD~=,H܂)X^\"d,2;`U )y3LzLx,QRGe_hoݾ)y2cNL^K2,F@3x2Gj"3tu9YH$V >!ss#}ge)Lm]3/Il?51:5:ˋj5Cݐp^XfKűan&tRSJ;hQE 쩋щ}SD&NBU2/Fw\a$Dea!^0jZ !jNW|_U>6Nuؔ.ƻTpړWF7&1 yь1 Z(*7ȑ2c I%gJ-FGpJYx@\? ,X/\2`iԳ5:AZr U;vL|ٳzjQ8Qȯ$1iӫT5hсٔSS♥KWתeL5019k-v9j8tx+>OsM, sκj?eIxG^;y=7b5 rjtG-4 {dC_@Ι39x @ԜoOe.{,8Q;B5G}AmA;:"x,6lDYB ffPm` bJ`bY%fu(Qd285GD"EvVMd&CZھg@yjDt׬;;!MDd[y.meNtAfqOJ!Is,IY^,RQy*5= w ̯8rK:,br>S%c[oy(,ž>asˈzt&VVJZ^,^!nGi=q.ސvUu;kb=U7?܇04ܸ[}:ODjR( 1RrS;ÆhFȣ*7о>j]CtMb\NB'M6>6qF]=Q,))vlS3uWkGӒb'?NͭҵcP'rcj,---r3'Nhhh͛7rG/RU.R^h;w {0"!B<}YIOҖR WjuwwdffDn%ocǎ/={V^- ' 5019k-v9j8tx+>Ġ&jnd*j f}k`S>EOUaYMaBj kR 5095.XFS c'HY R, (B` T 50hsj:UM²ĕ+W,x "Fkjkttthh(m%Sciiiq8qDCCWo޼YV;|Buyr'9kyw?,`fhx8t3tv\=.ai5t#DBF!&~0i-JQK.;wn'RRWW2ٳgբpHk`!^kfw^[;1/\2 5Kx @PS`<%1iӫԩj2 3թj005k 3 \#=7F!k`b.~OM j7`(DNvnOb:ahWK'aYnx}H Vkơ+_!f}N ]ԏO!fk uP_}> x @jAR ~(̆x uaS 5*S [%8DN _}7G$50Dfӫ•=B (%0ʲ~߿rї$50ԡO9Ȣ=7! VD?u;asfx3Q컿Dd˄>HTx L'r݃b?u2]?|0X=~U6J|~wԙ;?|Jbdg} PRpV0 %!^#jtO*ݧ~| 950OHTL!CEQ>ճp{,=U7?܇04ܸ[}hWЧp3K-쵢PLUy9zG\cݷ#|ݐ84VGD~ 0k\jJ 3U-K%%䵓'H֒G}%?\1;S7;p Yv߳wQQXRog*|T|b} @!^vb'֌CWۿBL75Ft\{Ol Ƚ_x5xb0GIÜ44+ |R'VjE)U~s} %Ɇx @jA,S킅kC|jȬ> 95Ɂx H-bHmoЃ=ĠΤΥaVB`aUOR,Tj$.ꔵmmm6kdk|ۡ ZG_M-QFM8S'|uUt-Wpp%QEsA ʒYMsM,"dܨvjaY Zj\B}%UjзzJ^U(sݎpY4:uuVM^9W?ٕ)e?eVw:QaW.*ivٽ8qz2jJ#T֋PUUriDղ[b^z'\ZV%v7ewFF|x l]{ALU'Du'i]t/Gը'Ȟ2cpb:n_ďP񜝷(o9x0Bqv&HZeHj% =W%s!J ~ 8J'w:*=J_B[+9ڪ䮑ǚ(:jNM 0X=@hF԰PA'^eЖ*zz+s+hAήj9ܲ$eJ]l턷Lu'}#q5}›TK!E]l"ĸnV$]Oe}WFXSGoxR!^0\( {\uөBN eH.'b |N#;ʓJ #㟝euVɲxvqVM&hjb.F4)䵻x@MNMQGHX|'o3gfR!^0d{]by,YJM*3~"ăvNGǰ2xDY^eKɯ mJfܰaOJ" QQG_Sq]fP"cav6z\KC%j2lQ?ث\@t= 'P(znq%ܡ> "C73ⱆK!OEnĉ r_޾yf0[8pB(yn{f ?8_pa'%ZP]܉Cu?w^=, Xo+ݹ,;{aВa_"P(dQjaJ[J=[{ô_1]PP)g-?_H* ;vL|ٳzjQ8Qȯ> vgN_^E_rgO@T̃x Lߙfu725(f0jVOx @zcܛ]N]{7g^&\|3f™jZhfDuX\{ uh*Tsv&׭҂rK`&O-̖->^'B#t*N(,3-;/2:Jrt;  Zx 7éjnj:܋ՈAvˢQZXurp~G_Aˬ(u&SKU#KO:9vZݩțZET}%-;RUUr ZֵԸD(z>dGJ\GcD>DA m;U(x 㥽n3ىث+}reT M^WMuݾ.?}v5ZfEי n!zQb+*FG[uMӎexQuG[U<ϧpja,i%䵓'w.`K,@ ٴCi5b SiƥW}O_fsgVi8sN'uE*Ȳ(:QcѢ:evH=JmG/ѝ=ܲR\DlKk<*i0:UMnq(j`<^Κ\?"55uY'v;x\ߺWF0fuGs{VYO+:NىK9|Z(E|٩Po}%՝VsRQ<ʠeEewtu0ADکjJ7@p} ذYUd=pM$ΔnzQb+*qwv-9ugn&~}$ y-|.O]V]$w ]A 95VHYoW60Vg#\FΰU7:;< tQCbo8?E_$ 'DEt;* 1c$ӬzzaN VH!)#}22UUYF-U%F_~ ҝ&y.>(#ou6ɡrv=g78J$:)Ysᚈ΁ -*9"Ǐc̯Jn l39*ἧ~D,,&r.{&qqRIQaK 0jؘ91ZGwԂx L喙> rFC駪 `._J&Tn3`}(61 Dk69³P<ۆSG9f$3^Q`nLrU"Ҟ]iOr#-ESEv"&o9ϥdiiiq8qDCCWo޼YV;|Buyr`F۹sM ܻO1Jl_2 bہ?,O4-ѽaگ.((̔رc˼gϞիW‰B~ LLuxNCjZ3^o i5 P2T5~| 950iL:0!Ч> C !~ X  15 0<@b!^S8F킅kjBdhrDjR_^x5 s/9_9k t–le 0gGӭ#FɞگuI70 ZG:;#6^" ^ SĚN95^;!EDOq؍s6qDsG%4;ܤ3wD׬VY>50کjtJZ HQE}ͤry1u(Um+*RިPV׌EyԂx vOT5Gwtn k&(Y=U7?܇04ܸ[}:UX -ت۰Ƕ^%:ANq}5uS,\#jLEٛH= lenOe.{cz15]}<>5C^y^'KTGe&FTֳuʈq㫎11@}"yV5jSCLUԩj%QC0U k`&NU1/CM'He "BC]C9DfӫԜL5&8FY|AҘv:a5Lc!@OLWת˒D+GH&Q`njɂ3r(qUD=^|'lE%`Mġ[e ^Z$A-BOkS՜)6(tHQ=x L'5tC le,?+ .,i@S`MyxZImImG=H_nZ9L_GS9;/ AeЎZC-.Ԃx Lb 1U s\%#<V%5}ve>>;;yE~.];uts2k~HY*9p%ZX1ptc ^dSe&}m9"6>)MNHK'+U*J׸hg߰C?h{PY/JlE% EAs xnחSeTRD-*a\SWsU]E|.};:Ϯ\FGq7 d ^s{naah(q;)I&YS (F5ӭ ذ0 א.EqNWRgnq;3 }F1ElՍQ t$g7URY;ssg"[MF2yQqРsšJ;a_D@̥ 10L`ۛDֆ򕈐 G7ϱ\1%, Q[&J3?;Td)II;;"U%K%fS; (DD.mmGy|F3b >4B&&gO<'!5XܷOjNM'K'50%'uæ00uY 50}Sc4.XFX%8DN !^dVj8:IC ^f8UMCL- u9#^qQ\Q5U dԉ5-eZ hZn+-^?|{2F01P.j)euO\QGi>fPK)RKem8AƧW2 3մLUӣek8JS"#w?BJjXOCԡ+Au{-F9QbLjGT;Ȫ8EUsR~cyQ-J\Υ?J9SUU\#]vRM2}Є7/C-_|"Ј501?z7s jNP#->@()n؋}G#h/^^\ylmm]E;X`pn=G}n+*7lb\TNC+9ڪx9oCE<ܾ.QiZr7RZVY>5@4Y*5FPC ~:O0܎2,*žfRT^;:|RG.6pEm6J1,eo!.#T֋qNbx SkݲaWsݰeI~Ktě"Sx LLuxNCjZ3^o ?ЧkrdQdB rj %PObxm}qGюZZ\Ď1F6Up)&y.>Iߺ}AV[T:q ' ڒA,2(cRT:I/&3e ՜mB 5:*wDcY^\%@˶^%sCXR}u,"b8F{&mshQcj1ΥMfQ1,2tZVrh8e-/I[2^rL2k b:a5Lc!@O@Jv1pNxq2G|+؛P2pdnx:IGo8> C*v";7km,&E\Ded}rk+u,a8G^nLEnĉ r_޾yf0[8pB(V Y˝8]s})S՚־D~Ź 2-92b/wUৃ3,Ls@ wq&aJ[J=['~ǨVwwwAAAffHUǎ_={^ZNkf/5t\ YG?UXA }H"LkȩHkfukrd!FۏaP`GKKY:_ ^0駪Q?`GK"r`n߮_O>Hg7=S3f'K=J`PsjSX%@N Lb??ꪞSM x)<,8ڃ֖K=:"!P%Lxhu"5*5qל*\:chʴ %5욌΃-5͹/@y`.%Gd*)=U7?܇04ܸ[m}N tǧS0LOX?:ũr :{+Wbn[^gU/nZbE8*؝+^nTgPG):;N[= ^X;kSUD,pjYVz\K\GxZ4B[uٕ@KԹ<.;k$f^E_bxzfIhHt[?[[Fws3?6 sj( }R'-;{}QiKi‚"3Y^\}TpkFfGǸ1J\} mh.zE<ܾ.BlE%[M%E6SSivIG'{sU֋h@_btMt`UO 53 o>{gAoRKusK)gO<'!5X|~s,tS"0x'_ }s}M| Kq&`B_YG R*syȣ&%ۤ/9hH]V̌%Kb Dލ񹘱> U2âEx @;#'߻7w,^rf!vS0;b < e5rDW6&^䵻@VgCnvSZ@7jGql>o3vqLmՄe|at.FwfD?E ^f}kOOp~[ ^|H_ Erӗ@SyB, rjfDWɭl&ľ~ìOr DFuqk6|n6l)B jLCcXfVwD;jGq֔mJ漰dzsystK"USx @:chiߙfu725(@iV=JNUSYHu2pt95NjD)3CQ%g)e.7"*>3oD*D/pJn)? }:#%gXC!.CFIy?kCh{\Ox L喙>p WI 7n8}3roݮL_Ymf3Ӿ L~L' $<"yd٤EOʛ/x-#`Vĝ|얕B};cдuT0(utPף$A&&gO<'g%Y*uL5fZZ3^o 0Ѯv -W"OV쁋u?2;@W:鲫OԵjOp;xYC?E-FW,(*ZG /'+1 K|oє!^01Чkrd!FSR08Sb'ikgve:74!&? =mJ#ǧAK{rx6}]rgxOVTa0y>xw^L>(4;ܤSv?=٪$rGqg\v]LQY:>G8`d.S̖yݧ ],mY u%:_5KkƧh>Y%@N @-/ 2EFab0K*&=rg&OMAQQU\FR(#2L Dn_N1j\&%sZ#J) g_*ϻR0L_SH-3Eagns1S4Öp%v1?I'/)9Kt)&1K D3arSdMR ebt1p(W7:HjV+wo~BȦږH FlSm0桅ɂ" [RrZv!T"%BӰ,DↄSYkԎy,,{S㸏:*ے)͑ŦR>^zw;+d9FFŋe2}Yb˞پ>]ࠚO"WQ9|46Hjr|3/?~zUW5xKMy;Ox0Mk롯o\[ u@z3әTphr[[[SS.Q577̣]]]^T5EVXSu8Lg;] kʶ>;{LUƬ?@ݎ7??r_x3@M-9Ѹbޢ*ZdM ݻ7u>k@}߽o7FЭOWuHӧ'kD˙cqI7]P;5SēqUST5^=Iɗ0uy#;h ][15N-ο ]ojtOߜez*؝tkw[i￾ UK%jxE)4oߦ4*U\r`y@]q6{x 8(T5n Gލ7[mi9w,1sv/g{,C* V fՔsWuUe5ŦRC_8wu g7&'o2r"l[g32+͟Ѡ嶶&] C557^/bnnN}GGGTeX_13U ?j/q>({}x vx @5B ZD h!^-kx @1*Tj IENDB`asammdf-8.5.1/doc/images/range.png000066400000000000000000001574251502633300400167630ustar00rootroot00000000000000PNG  IHDRY0sRGBgAMA a pHYsttfxުIDATx^ |a{ςx%)%"E)& oVqJjvGU#z'&iYuGhy b,7֕< 1"h%,,%H93ggϜݝ؝7'sffwggbV", hPs@7'6%Ҍ1 XژUkbjVŮYϕD1T_c|κ>:+k26G̊ESgX^j 㪒ETQkYqd{Wm_rMÊ_oh-m? kdSuzGUũJZcnOz *C-'B #E4zl;vl֭h/TH2]nY]SSs5͝75TK/5wugURڦVֵ[SB$pG5iz8'zƇ{'mϏt/4\.hvu :ee˖->TSdW&SkWYs7^{gv굫ޝ89 |ͫ~05{fjҕ٫W_xU|b\P{ҵM_~A~zV I"{kF̚W=\{py裆e>㎊dz"kshhq?$6dG B&k{Wn^e]~۵g'G^8~u;s[w]qyMwW25{'?8cb<3O;[!I.j!W{U50&WtaÍ=zYab|SUήqֹLVh9|42fH4~p`G@$-/*͠4}2릾_;+x|DO4n=ٸ%S]=ʑ||ԻsWg>8g.2FZS_G୅[mttk~zFd<Q1\!~ylth^+у693˻# TޖZQ s'W}cm\:z+W{#>cSNjٚOly{gϨ^#X{i 5j«*<<!lgvCq90Aw{[&Λ?yqТ^(6m +ʟ1S?啚3gVzz5kx]Ҫm/ܺꛪL#܌1<68!gp\kx }WLŜu̞D|<ڛ?>sq,Q _04]0k~;mᖋ6]jZynM^w'+LYAw;05wythh"aό h ^A~7^phn\pG],~fЙڼbÇ] j6f.\U76nxo{n~;5ߪӱMΟXbf'ߩAHCyfqw {#tѮA9Ǵ=cHBdTޯ|{Bs^+34ED Xjh%A X%A X%WxR`֭[^IںuT%gԟH5۠k9r瀞YV⬯?51&fVլ]W_:+kc+b17Oמrmq~E̚չ9ҕkL%S4z LJ&TԒ@D[]C$@I#\Qr67vd'2D|en25vk\vܻ3W'1g_J}W~KNco9ltuuyĎ-SK@&1(h|'ξe}?|enUu?=35sի{U:?oraZCmK6]_3 C3U V7 g`ktTOG-=ݙ3XT&TRǍeo_8ABQuVH=z݆75jb>B|?췳 ~kgYmi? ͚|7MΦ:-_ڻWO}UW]{rt]:}ڵ7_z%SM,Pwh@`b{{F2hWϽ& vg#މ㽃(Hi~A z$ze=iog|pG7%vPi<:;!ݹ>og~ksYw 3^ KݾVgQSW~_|c>ѸddN/v]+G6ןk|+S9py'3Qdak`ǝb|hhԘݘwFʰZ;Z(ZsBNh1tq܀iM 鸸SvIr8jl Sk9tn` ϹFL=o1}}taqRS[t"m .9Xܙc1㶇Sg}y>𢰟èAOK"/LNQ/etEPo_{ +ʟ1S?啚3gVzz5kx]Ҫm/ܺ& &օ ZQGcb ?hٻ5I;/gfF s2C rBYdM֒ey>pGJo-QȥTsmj\[[&V' Nqb/X3kDKҊ\jAmczq%=ڕ/ugO}aO;g̝:@xa0ӽ8٩=4{Sn~%Gv'"5u xS]OA~K77E< '5xkYw4@Bܽ곌b|G5'ָ"6}MUj,^]*W. "e4",9M7nU'}$g%Fesgz-wXRObxL%6?|c ]pA-P<'OEH֮]T1@o޼YՀE;u49K$K$K"v͛7'>/b5?[ҩS֮]*tՙoyŚ9kSkߙ]XM Uݗ_u3y9Mh6F-7TX0ujphմu21GWt54̾=zkaxջNj-fYvKc)gjŮKدwV4_/XU(^jk՚PVO5zPݣ=v9?s|iZͲTevbj'z 7s1e/[ۨط؀F:9CVU[LvK Vg\{.+ݸ(bATExɊe& @!@O-gρ\zzz:zgWԲ':32N^wT̚]-OrocAN Ëc_bC]cnf\G5!ݢG{E_9t:aأWtϿu7E,h/u`Fj̐Uj+f1>44թj6mq>]2zF]O(F{wY΂e8 3XmՎ=3+ヅlCh g[s`l'>6`ܣjckT&M%fh!h7)hgfL:뷚pԞ M8aGr[NPe﮳]ppG2B/Œjˢe1ħ0޴vmMCVY+)Oy0al͆?#SN]VUT!\ZG f,}ٖnpű᏿̥|ߺ\_"D}띧r3"c4GYTh , h ,ɓ'7oެj:uJ-Vk׮@ԩSQpBfqqCe SZTfo]#_K$K$K$K$K"v͛7:uJڊ*J%*BKKZ LMMşNZvSu 1UA`uvvNLLJx~kff}O伪/-[?~\U*ڑ#?O6]_|aff^՗ƍϜ9*XFsΗR9o-?\/7^f*Ʀرȑ#e_Lw;/_8i.\?:W̜hfgeNA$oz*uM._r+e>XRXZƝ;_ …k{]ձ~ zvv~w1 @?8Gc=|ʷ5_:*<鱬ѡ:d T(=&}.=&}H3˗>U.]]51hT{@\B /\:/ 3DA_f}>U.xs tqVϽ]5RY}ϾE pnvT@ 3tY @5vQxXf.-@XBzW>qЗHB հg?Ph/=Պf n9{hm/*gzy{ܢF5 @K{F@HFQQ㝝Zȟb%oN#goŦ^u>-٫>J HbzQ Bk`l>M vۗPpMY#SvْL;dr/?5XV{SFV{{{V/{V\ Hb$zQe&yr*K~w)nDH\lt]Y 0~<2 :X(F(ho`f hT#HB>Ӆ#@D"nDŠA'u'RbxתSQ&gA#IheňbFQ2j Nf}x\# Hw?ڟ#D_:nN9to;9#K;0{R]rdY/Ft(n<3Z'#6ۏcIgs{hUgZ/gR''|,H:(CY*~uÉxB%D"i'U-GmgwlN/y48Z9X6-K[zyj4X #Y֋,Euns:}@Mbh\q9yb xŒ=csyGqi2.{89ZGn39WjoOy9k&khlsjX϶6XV ~r:Ѹa [gEHg+XVZh6HXyS͒D__0WMLvI!O(L4._p2{W+hc a- `F1ePM1>W5I.h3Y#2FR$ɤv':Ol_[hx%Qhy d]i &ܟ9~?3NVܮ%qqzfa$n?B-y^X(? Kz5žzFK6#t"a ēޑzbsXqflZngޕmD}HZl.]RVک{6vD\༖}r~ٮ+G>>zV266 sBuCJ,H?nYΓÉxX3f~9?PdY/FRzb|Sή }P2J$% d|JA7ҞvU?ڟK'je̟qObb'n3Fڇra;5N"=N$9wh d3Ot쳇-dj{_Qn$ߧ*Ѓ`99Qto%~tʦFLv*?la{".JKY9Bm_pF#Y֋ `=}iUA @f;r 8=K}vaN&/ {we[&v}<(6)g0%VBcâi?fjwtC5r^XewNLL$C c{5ϪЏлeL^Qg$z1ee$֧|N !2P81D<؂d(W5Moe 32PfF# 9T$E+?f|8:J+QH:?-eb$zQ!Vρ IU5=0 K>=>A+SmmCg]UL63;]1{z-x/]h&~'?b,Xn-T^5?@?ۜQp>[d%}Q98k,r2+Tr]ڜϾHz%N%\cwrz 9bqӮ/h*™Îx~1S1c@>Ghl@u1e^Tg@dNzWwD<{7.^UM,ɲ^dY/3@ߵiM +j&Sײ9mUǍ׌&S @ɲ^dY/3+sۗVT4ƆƇnkp|7uM]?:y2h+HP"9BM={7gzuu~M+vu7$j`F1eT??{˪5 + uaL^|޺2gևoƦ̫T#V֋+E k^GODх7=HbzQ@^9(vݐQc "[]_`ʁ,H:ʙ >|Ϯ_/yj?W~'R'oN&۝>єSOaZ@Iɲ^X(3@qvw_tig߹ue*?gLFE!: =ڟ?[d2ۋEM.8-V{H$:x\ga-EdY/FT#?ڸveCy㻯]rZ޼twWb wrL%3]<㍝A~Iv''vCP5)k-2?WCGD]2beɲ^TP5؅ٹ7/]} Nw_;W^f@p_-!fIl6m;K,^h<;}񑜹uhrۉ>;ό^F#V6%ͿpWO6mO-C|\0?28j6BWYN3iG2ɨ-NPOG@1e^TgB7?vS*^]7ݴ.Fe3'NfO^9"ڈjU=} q<MmG iVlmPadY/FxȎ^2UfHr "G+xb>OޞUfb_^kp3yBZ-N@QdY/?̧U/-[?~\UƮ]?^ 7nu/zmٲR5>_~}wǷ?^˓&oܸ̙3eT|9/J:155eznl͎;~C:Ks~jjJ-,#Y֋,EuFl#Y֋,ɓ'7SNks9MRNK}#_L_ssX޺uбcR,/?"BqkiiQK{{oLU"hЦ*XFRњjySw񂪗}|p}cWvkWu?ƍϜ9*XF[l9~`qΗJ%~}ߘV2V=76fǎGKO= "9?55rpZ7^Uwr*='FUelah, ҹ/VgG]KsTKTKe9ꝂO)}R,wrN]Tg ":X{h\U3F{cUewۖ󊹑 y>&9Ŗ=jrt=\ݣyȌ}J2vz=/yɻ plWz5 K[,y.z v~ 4dY/F:teUYVWAOaGjց]}{9|ZLJ&T|/Р@Ȥx=Z+UnN-f ~5h c=s30[t]cZ#S٬#G+ybzb\`g? J?e50pQ&q$Ξ̹(,'zs~"v> &V[o$n1be핇KO *Nx;w깷Kƨ* uuvZ9ˑ*ӝܩ`s{t>r{zu=pLKemwgMmJ}W_M,9$->3& 8)=W'&,g%OJgo7_5eTN[o47}޽{jZ XV׽=N9k} pY/&3=9Y7>|;UA}O@Sp&93:k@ܱO= )@dɲ^XY/3dR-'޻woR[yZɑ٠|Z&"ٙH^2&WȉN ~o:#CpZ.8DkY vU[D:\->s:eyOh|Cs$;2;=93:zrr~ t)8DCJTSHb$zQDV:9ENU5DSSӝwީ*/VV1Y^9r:;G3!|zdfLms͞yck@mƺ~7{"qwܞk0;T޻#LڧB|iYDѾ,3$PKLjp\9ZgWwAR>Þ%/=BQEɮ ~奻P1beɲ^T(v͛7;SN]Y^s9MRNK}#_L_ssX޺ucǜB ThOIuﲞ$:Dq-/?"BqkiiQK{{oLU"hЦ*Xb}idYmOWU,䦦gwꥶe˖ǏJصuݺ~UKaƍgΜQ,<|T9iU/c0;9"! N#As~jjJ-Dn,b.[S=X)MPw3A 7wrvq-^U@ntrxpёl#X0F@;]n23PՌХ9_*. F@;Zp;8Xj;zx8Om 2\.: #S TX(FRȇ&oNZG'Zr}/gQdY/?Tp%?8HF#V6U/l PQdY/FWɓ7ov*NZv'җh?`s9MRNK}#_L_]]XG?4sϩ%@X+W#/1T)GT%mm_zZ-e!M^Ή UhMM<;xAKm˖-ǏWkWu?ƍϜ9*XFyΗRsSSӪ^ƪƦرȑ#β3YR {OMMşn,rȉ7>_޶>%u,0V_(XUZL@u@sG1;]T%%nŭ#L%+1<.Gϛj Y X^<ܞy a8*ˉ}[WںfUT-s#}L.sۋ-{}-x6N$ߏXwWW uH=ȕw}I;l k΋Y${#ҫǵoO(kioT;F2)1%~ ·|,ƉY'==zbI뾽>';ѡ*9*ֽk8Č|C.;8҂QS^VW<0MN-%(yЙ͋NrbIe#`rSaxt<(>Рǟxb1R|ib2 V5m=߁*ebCɕל%ggq2v*(W7 `OvnY.\ax K ;:-u:WQ:<=l6?1CB'=!N[Libs.y;rP6B>5EYps@'e9ơC>ONNNzg-x:=!6o6[~}zY(  ̄cd.)U ߠ)gN_僺Li߅Xo3(cgW)8Üɛ5 Z~'4;'mнۚ; ͻ7Xj2pn` ,wxb{Lp2{IG')j%Gvǀj4gg"{y !}N ~o:CCpZ.ڐ)9EfX||Ψf}(]ͪw<0{}ނ;nXr>צ?Q ͽ @g_p ,?gh 8*{&S&4ٖ\y>5+sۗVTpt2nEDSSӝwީ*~Fǯ/jUKk/NW'e+ s0g lTS:8`m{4{~ڔم|v7ߑ=C>h0{ 8 ϛ:|]3 WȞ8MZ hߠO uqo=X:[LS?ut;˾M~GqX.gwqsFW:{9 bvj^u3FmU9;3QUl-mNQu!v͛7;SN]Y޾=ٟ[3;wl* *~} 髫G;u{NUd;t>(/*9"O-+W~y\KKZ* F\G@ompEݢGT%me911*g>u/zmٲR5vj]_URظq3gT˨:r9_*t>|}}cjjZXؔ;v9rDUl}WGUdžSSSj)f9ɍE]5LҒ;}^f[S',|&ľ[O0N=Us!nrؙw FcQaԏT |skܞy}s陳e=Göffu-Jvۗ֋j-trx{a}D_KKy=j:M9e?0-nOOmd"͈CE)t2GUU=cc}>iIMʪ(\-rgz1"fe C}-9Frx{5rK-C.TS"!XBX*2|a{{{2O!Ѯ*_[.s ۇS>'ZB(-#V6,EPABhG,;Cܖ{>rgF3Wt*Ø*,ň:+L Hb$zQ4d$z1e(ɓ'7oTN:vZgyΝ;l6J9-Eկ|3}bb%@X/?"BqkiiQK{{oLU"hЦ*XFRњjySw񂪗ږ-[?*Uc׮u~UU/79sFU/RI÷w7UUύMٱcǑ#GT%͉U%ZC+9?55rhnn񲨺ˡ r/RR,g}1[:'~P8x?ww(c E!.R!+R/ .ty37.\;3USdx&O9j=6˨ Aymk߿=[1ʜ~|Nj/~ ㋇U-s#}L.sۋ-{tf-)qf}0r{{أ^TGo_hH+Ny1N] |ڂgkP';G0 E-~x+9kaNQ!<=}iw7N].Ɠo_/Ї|,?;l>gάGN=u^ӏ=r[K@zG:ʊ-s0ӟ>z1I]_|9#5|1W,&v9aqd -8+t&}`#_=tc$A-c϶/% N]\+mepK=f~޹g>v/qz߿߾}>/zsw~TNm\&bs`ӿ-UnN-f ~:oeˑ*ܑ]s{tܻmNFyԂdouK2'aa/h YGVl7Gn>L {tceClt}EYOŇ2d+n8KHG/l}*'X¶2V8nRuU t>RKin{nմ*ñ;DvGWcl"4gt~-9Jd+p~vqF.f<ve(]\W=Ӝ{[ P`!3٤Ǟ-M ~i#m ~irwRBGOC^Qz$aeM^S~zFemfMmmz~+4o_it8yeRʵBvP&BM~p K݊تڕ5[[Mݾ+kgwwoڴӟA=}stcefN ]%uw:'(Yt^gX#n{,kG3?/ B?\*~{4>~>[#9Em,gx{`tA+T}.jHJs짛;3 ϵBvP&|ws>QpSU!Ϯeo͊~pe D|ɠ>;>:GE5=Us#$* Q;,W4D=G%z!Aߦ&p9(2דa~L0qɹhSќ1W&`O 22y!>m%M;gW̃\l'冇B3}..Qrf{oKM=˧}.+m'̼=cRc/^|pZj i- 5} R n}ϖdJOJq2e~=ji9Qaܣ}s 60]dhgJy3ehOq|0{ ك igd3F]N75zoݟ4Й:|ELLbrv r1zu]k߿t&ySSW{?US[VPK%d{ >O)j%GvR;'=U&L$/s>;yVX?QPl7CpZ.NG Vkc'-j g8v-,{pfzkYi'#mӟݰ]؛zevZpBϞ4Ÿqeo{΃[VN?Ay/yHy>|̂78o#rRoIFNqn qTyQ38yrrZia̽8gx"O8 a@ي s3}ڤ.g-bڞ7ϬFڹ񾶦@s É\إk@Z՚2LQWWrJp0)8J)8JJ)8JsT$TTb CCmUAg׬k -e&h cz ].F PɌdY/F ڌX(F 4@^X(?B菆*#Y֋+EuS #:X=j 6@ɲ^dY/3DJNq>jg#@HFl#Y֋9C9oU[PՌCʸjU{]bn$Bet}~{y,ٛޣlXdz5uZ/!eE]^Y+#1~q:ܗ漘N7+{\KnE?H?o_kJ_9Sez1beP">t˗Ue1N{i9߉ ;b\lYrsj1KsՉ}ŝOIc%X [7M"=ǴwLPe{?؞\}s ѫci删Y1MR$^8K."Ϋl>^KR;~X #Y֋,Eu&]DU ?;w.>M;ԡ1twXZ$jˑ*ӝ_sp"oj",Rb6ۇىxrbIe/yLǃc O,&[1Ml[&fg]<V)RS8kΒ3ݒQ]_ Oʑ /FQIG%+E:rzK-ݻUbŲSQ=z#>OajyzqTSV*p~vqK]bO;QrgNj%W > K ;:-uR7>q΄23O>o6ȱ='7fsAliVwm|sWK@eU{ @F,,E[Ї'?999EO=yulMGocyhUZ?8O"ľ<3@0F,z\-{ӦM 鳝wysC:D%eT{yj}*@UznBpcL%Jʘ`mىmEMkcFh#TߡNͲV#~ .Oʾ4sWi>x`qgjc{k .î/G%m*a7a74vt ۧENCOӓ^'z_90S^2 Sє3ve'v֟\lgmfW9Y{^YC B @dTN-8޽{;yZɑ=wj5f#{y!&O(ŻUg0pN E쫽/>Y.w# ; oQPZ*;X[b >{ @WK|Cc2'TG+93L<Spsz3CO@8E ;SUr_E*Yj|zdfls͞y:c_ǃr6ms}zoԷcj'FU-ώT(k̆~8[;|]3 WȞ8MZ hߣO7pzhq驏::ҝe&#s,=y^8]fßM'jDCNpPb'OܼyS9uTo>wT*W>Չ~ǎs ںus=*r9t>(/*9pz"\wʕ+< iE-U1UA` ]p;;;'&&T3TԶlrqUv[Wïz)lܸ̙3eT|9/J:155eznl͎;9*XFa)CssӍE][S',|&ľ[O&9Ŗ=j|ˎffo*{ŻciV}w{e^܃Ap_[b;ވ8f۱fR_1g^Gޙ#m%ϖmٍcY=+2zvK`dY/Fs@J?t|,Qk|' |ځ 뾽>CC]]b ~/uvjYzsӥρPQOO82'&^d\Mc1fJ`2/ v _^2_.q@-OŰߣؠ5؝):g.(XwT\Luuu2o+sd:10:4h<93>g"Gǻ2Sπ'ejSYBƇv Zcz`s@Op. :Lh)O)G{{GǴ1a' "!Cd)cL-&F bK@!-a?_׌K|^X(?Jd1s@%d C}򓟜TZu 9yz9d(x tqGn\@lMj?B*}gr(d} vԺ$cX |),g] gi#w3AGp-21o! 0'*\#38zJ<[z?zcgWW_,M?-" >'_;m20e^TgEm^){ӦM #ysC9%eT{yj}*@UKa o 2Wژ$!P#Kіx(ZTо=2<5'ͣY Jc&3o!kʖ:v<,_o-E8z ~wO4_AG{oAL=>6гPrnW]v,EuF [{&|áRjMMM_W zxxC$E5=SyZɑ!rT! :_g%6uT2ܱǏ[u8p]룑g_{bG3Yj2%-Y ~y]ܯw! R!ι9V}k+/F s @Sp&Oga>XY/FlU/`5%twJn⫯/jUEr٩ OβeJqT6{^o9kֶPQv ސޠّ|Y#sِ<&5{ Ar^ <䱨=aUVtaT5 :ׯħsp6{ڂx&ݣ=)E$s]βodg1#;}=JoNحe,,ň:yN,[itym LuP9iF/D,gA[FQ%xtH6cX0.F@ AKХ9_*.hwbj)KdF@JY,aEl('@ ɲ^dY/3R1eɲ^Tg /ɩ^Wuy#fQdY/?Pт+kcկxij ňbFQjt]_{w~`2eɲ^TgpY3soj߷?Zu7}?ɲ^dY/3,Z'g_~ת1beɲ^T AX9yq鶖_Xߠ^ywwVo #ݲlh_k^X(?TqMooY?SM +T#(ͻ[ԌZ`;hܰ[-HbzQhPmgONyͶԅu >-0eɲ^Tg@^D[CVGFUeؚ5;E*+HHkho;mmXڶw&J=rĆ.QJ͈gE,h"m9,{Ϝ=zυk%ZxvfZUl-b$z1beeG @I]xy6԰ᵙf$z1erB @Iퟴvwwtŧ'Y5[JHb$zQA @oG7&I9&asv 3beɲ^T@@3beQT@E#ɲ^XY/3@IG{,Eu4UD= @HT#V6+Ex#V֋+E`Y"Q@E ]X*b3e^Tgʀ@-9,H:PޘeF1eD4E`z1beT"h2e^Tg4F#Y֋ 4jd$z1e h@e2beɲ^Th3beQTHbzQ@@ʂ,;>(4e,@`QbC֨ 'Hߜ jdzѓ B HbzQ@ 3eɲ^TghrF#Y֋ 4T8#V6,EXPt/v (#V֋+EXL&`ɲ^XY/3 @'ω>v(dY/F Naɲ^dY/3@D,fh@ ]X*ҌX(F BdҌXY/Fl=<'g wWW4[XY/3@ 7zDbhH.^e*ۇʟ+H Ptrx{厂>Olg ňbFQP<d2w'hE1e^Tg,Pt{{{"yN&IѢjP\n~_w׹UQdY/3@N=C,+͔2vŭ:}aܝz@Fl=V6 @'O ^X(?*Q CG<BlUA2e^TgTpt2nD,F#Y֋ hBx<$b]UD+H > t_JňbFQE 7ڝkĝr2e^Tg` +,EuJ'}6*ce~sZ@Y 9a{g[5@PFl=V6DM)8ɤZ+ň$}ɃSSLjd$z1be@9̨gQe T5uM1Rf`о!Ȉ ]X*D̹xGJ3"ňD̹`@92e^TgKa$z1e]:"lN: sqdY/F@9 @G| @PFl#Y֋ "KˆbFQD4)HʬVPP4t>oօ}WfJk󖾂^T=z9(c?s]6l5EG&[?XL8VblC([B5` @{o,bֿ|_( SW23*(>yk߿e2h@P9X\ڤVx#@;Oyp s_440:X:xccgWޤ%S /XS՛j~;3=wKώj>|4SQnmEn$"G?R,!c&:h>;<( O|m޺:7??D, D3 ?;ᴪ@Q9Z&_ƅ,]Un:dO+# \@9Xߘ( XJ9SXYu,NbV@pQG@µ XʪhĊ "*&zɝQ*>tX]":Mz+XMU*!(OzLR ^_>fEtTP T+p.[wU DCQ>x!sgB+ GZD;=@X,=RM":=w&zFY!@NbEhDW1P3Yt}UXB+B+ srG!Z&U D;=@(IZΫXl_HU CQ,b H#IJb  @ CO(rbg ܙRJNWU,~/ (ܙvNbV@tp!ϨT@+B+ srggT0h顕j)\@s gkq,3>W$jsʉXZU T<"QPĊ "b ܙՆ)8 V @D**YUDϨ6@erȅV\\@1J'VV@qQǐgE @ĭomKh7MTˆf9ZVU DsgN u [[[ͻ7XvD2pnPa*8lT>U^Ȫ@t833{~rygizyͶe̺ :*BHϝlTV*%3贳3UŖbkUPĊ.b0мaoskgT5):2nbEhD;sQD@@T #3{Nׇ? L-@t8ϒXGϪ @s%E⽈*@@ңrj%͓>.<߼f\ǰO (q+B+ WX ,h%T 3euʾ ngyzrU#@$E\@9آ8@DL|r:1cYIUL-ʗXj)\łxCP jY <h 5'RcĪC+ ؽU+`3Pt,JCͽIˆf @bD~s!Q3(:h5>)q '"z"}m @'Zj 76WNOseϹ Y?aO?xZ(Pt? @3}jݫ\ N(rsgF= dEÀh@c A93]\@Уg`=2eNL0=":'w&zC|,QB>09]|>g*ּf[SpETH*ιKwrgg$BDhzsJ$HU-C":wsZB:looW omK2XZQU\\3BϝrnxjU'Hz6045w hD֝ : D{M D]:>~"q XO1P嘂iulhV5%D@t9=;^.]SMq$T(hf&qzo2j;=QD@9W{!VUƐg Hӯb.ds.\Uu833]NbE\ +hUA*OWgg__.E @ ,=w&zHO(*O}une O\+b3PJ5baظ3\58=Ϋ`3uNbEhDW1 -k~M}ͧ>ڧ0xylCL[AĊ "b ;jU)ЖlXko'79;'gVs@%=$VnhZD W1uerG@g&f65S /q_z|j.\jFkN's@%=Q'VV@9W13]u9D3FM̺ֆ_o_{wɅSw }W.ػ_}TVw :*BZNLܒ F.|SpDVwZm ;Ui붆~E,veyUySp!9wjNbE DW1u|G@7[K u?^%=Q'VV@9W13]uFώpt.kkk]2H8U9*(U̅ D~G]79hc޸?q˟h+Ӈ^>vngno/N @4oHY+̿^,D@D9ZVU TQGZwa=~Ef19{WR{O58+PR_5{dJ CKE="::Zѳ'y?[_~37ٺjC]??|mXV}iM}QTmπ%p顕j)\@wQC<}ٟt>ʅ55׬0Bk*_Cg[w %^fRs+B+ T k?\?1h_aa}R֐@ʸKXZQU DsG]179co] <*.BNbV@pQQWMu/\os?ٝռA%n=@uȻdEUL DsGTJ@NO]}{vS#5ۼe2e53%4D%U :*BF[;q*XbuTwRv_l~3L]r۾ K*X=U D= @=[WV~|Ӫ@tEUL DsG]%ѳ#CW% %'=q ӯb.d ;ꪺ&@N]23]NbV@tp CK&zHO(*ιA 47oSKۚQ]2PJ5b ;jn X *47L*1%ܼt!9]%\@t7ժ@@cc_nްͲmikH9?^"d ܙ "*>Y :;jn}@gϟvwwgNM>H.:'rC+ R塀E 5ۺG6X m#mU;PKNO(rbg-q(nU~;jZ4 Ӽam[J |~~rGgw7ׁ]2u$V@W12E57A@@3>Ϝ36wVռeƹK&zIH*;!`aR)OPdn(+B+D8*Uù Y玚y*w@ N(塀^0h]2uNbE DW1PjՄ2sE6]2uzbEhDW1u57ekDmKdTfX=RM":b .5'b9p DXZU DsGTV4 Ӽ!}- r7+B+ 塀^R,Y?~%]&%=$VnhZD W1RY^f,=~‡ˆmX"]27@EUL DsGTV,=h-c轭 (&#N(塀^~,FC^y+Q@8wjNbE  U){\@qG]X!Z_2ϫV`dn(+B+ .玚L@jV64pܳd Hӯb.d ;jn4 LxdJ]2uNbE DW1PjՄ@ @15f4B.:=":玚rF Bomsuv;cu(d yezhD W1u57ihlsj9}uCmcɟw@9]\@9wMjE#`aOϜK3ϧ2>_|p Dݭou+B+ ܙ"!ΦRv dg JQz n_}wԑF 5opŽ |#<~̍2EzbEhDs=Q7ժQ2Noo'-+/U)5eI]2u$V@W12E57Q*N%GFv-o%$jmsc T3{&p DX=KM\_BS**wԕ'\L U!ֽAw˨&]27@E\@9wD)TXaB R ۬{ 7fDu:Ճd衕j)\@wTWps@G%쩠jذ~z欪Ѯ*`%Q$VV@tq@Q}QW!NJYo*GϪ {yQUMO(*ιvn0Պ$NN@I=oݠM ڤ]23QzhD W1u57#HQC1Pf[ҹdH[CbtbFJ]2uNbEhDW1ubb0G 9=sßUI7eyՌ]2uzbEhDW1PrNXJx57U+TnwCX}ۇ%MgֽmffgJKVM@!y!h1G. )gJ¹ n v; Sp18]Sp8URE8w9Tc׼{_/N4n];s %,Lľ%׼f[ri̺;@97:H2^ {3ٙ Vnw )8lnQ/Bhf4̴£PhqF@X9[E[zgA#u5RöffVZжv0$TdִvLHj[Fmex*nooO&{wdy ʖ|%;jҊݴc $k&,6b 8ŌlAN635. baaLنSE6)0zjS`;&Le2ɔDqLV dmH)]%c}}ttC)=ro_Gn/;.w^Vwc>@j,>p؁_F&l25lQ t@.%[?ڢ RmD46zjjddP=~j Ke 3  *3`U #-剑vW ## j@(!`t΍C@~U7>us|x`~DSȹSɹË5T w=p<1r,.F(LLHȳ=CCb詩x葅S#2gXFc!! ߪ{@O-!#vm)OԶ.=+[?nh@|aac J#CkO#7W(rnM[py *0@,ѹpfg*a#+ ծ@ߺpbE@P9<>T #Ȼk;J7~ MBaa]8 q~-CW4.y!4Si-8 X&7z} }a;LJgŁC2_U.U3 ȏϕ*SC#;w<"`zToocqp~azpqFXMUߵ0| țJFBx\* {@(&A{!+_{uVtq2ȋL 4V -\z:+8|Xihbz]_gE/Y܈c|xWt@+}Go×@^$ѹٹa۹|rR!?᯿T4 SCo>8P}&s + ]DO BH@|=߻>h&E#BW@ ?;|sR:) E4-!) gp֦2S\<44Mi&hB ^@$ѹٹah 4MLJn)I@ -I'wz!$4#BW`#;;oQUi~ `m=O-aULef 46 a(:ȹlZo}k٬yTr*@ooo-MJmQ81!хPC#&қB@ :Ν*ON.p`#;pM;< `m=#mVJ] 6 գRxl26 {biOq~Ri16 sXy+33k@(LUwhXھQfΕ#SVh@ @i#;LJJay'Y85Y4֦44>=,'(M>_;1b8T@$>/1lT8Xѹpjh 9 @n!jpH4@OZ49:S5T Sw>pjj* *3j󒚩 ۂc՛p؂( W؂St" lkΛϗ''Gf<R뀞h7" <><|p88pH1L>0RIN!BxZ+tCv.>qghNNg뀮ٽ{wؘgWőHw5-ݝdV{~_P;sjbP˞6h(޽{TDux1)F''T ͝*ONVJb||fx|40yO|m2g ;v`w-[>!`{J㕅hRWOv`T¨jva~1 j)) k؂jq0_-mK{/-vs4tT\ߣa㕸{oOmns&m&.Lm8P}&F C9fhHɹ!tH9hO+ A8=@OML;wn|0566U=oETwGD' zn穉TxLU~lHm  *>sd9W hZB @Khߺwg/|ҥ˗jwOjNo_㙿^8]p$լ@:V8yo~^^~_[,oo߸4 apK _Sӕ /].<{T .y' m\y StC7a]8rw_~a _y7.Ǜo}?t .~Ȏ Bu˅3/-|'|,@շQ}oaÍ囿ᅳoޱ#?x޴i_[{6 ^*_·Ω͜ߺt·._\WoZw/.dR  Po^| qչvj~OxvUՆ ?2 o1>᯿Wl|娢 A$Gwn{W2tuYLxK/K9vúu}߆ەiXnBa{oa7Gwcc" ֭;6޴y\mŌ[nX u[nvn~ێR]jM?Jnݺ[6s/}ۻoiÍ:Xjl{n>p-muOQ^ V oٰz|-=gz]9&hZB @Kh 4-!%@hZB @Kh 4-!%֝hV*xD/|\*cc@ mٲ%d'k€6O8}mӦ󞯇qw}/B7pm7>7a ;v8}tF{{'v~sa6/\nUBtG;E)k@@wSqͲzR?mΟy3S&t;E} hB@6N@wz ͚/Н{)YY#Н"5h tL;E)UܔPR) M$t; yϯw2e+|9OW}WrC 2aT1p)\->+v*\ @@pE&̤Q`M2o2o¥4@~e2`Z&* Л92_T:{2*\@/@LlU& A˼iʼut%4@_Is.p̻:W5-ȄC@LĖNߢ A.e~2?,"H !Z&b WKd~X?GQhZj3a&J'e-L JE Wl [n=r׶˻T 8,tR'# 4CCٳ][lۺٳI^8,pzOe`>9}2 ᙳgmx+{i?֨ԭzry럇=Sxw[mΰVR58Lp- Бϋ+`IVU: @I~?a4@|&?$rIRIVUB;SXP}gΦ:#ΐkAȷFغ~5I̔KO#"0 ? w{in9N)$Q%a 7ۂϟ?s.߯w>OQ:Q ג|nğ$q9X#a=~?{_hi5?IJ΄iSg}jU:A(4Us& sG:>>Q%aPh?/O0zItd3a$OD:3_) s=zm&Gڶxy:I&L1|pEzDCٳ][lۺٳ@7Jg7I^Ui['ƇgΞݶuk|$1M: s)4K> sݧzry럇=Sxw[mK$ }$* s]:Ry#w/Q%Lw^I&:39m#NI$|*OI|< it j;tyJ$j $fTa ϞM'w:=}f֭gΞ Z(P`%L3S4^'OA!>+whI46 Бϋ+h$ I‘0@ $ohFτȸMI&h7@*\3Ϗ?Sx$??^5=L#4@# >| G|J95@={]ɾv #:%Fq I)|n 5@oݺt|fzLt&VI&nvI&z#dB`UITU_9zMI| 4»->+H$*?L\d@(>8PWkTZ @K$1DL T&j ]+* xpdr0~ලB2KT{JW9PLs8 M gv>typ#33Gj,=L,zu$ kpO*'-@1Wněrggt$U#{@k{rg$LC[p,}@OʄrgM&g^Ƈ.Ls8 ]LC4Bw /;9hI4F+pL ]M @DCoi!I\޻mw˞+ɝI4ot3$nCwM:th3gτIsDCj:Iq!N;J$=־G-Bhؿ;@$qgFUjH?ߒ;@$)ug {j0G:9- MIYe Ϟ=uk:~DhY gf3^6k^6.;O8+Pgmﻷ>?39BO 'q}aG/oCg щ6#w.%p#&rg~hI4M#4pЋ$p=ZrghX4$w7|/\hk]Tʠ`rg-I4d… Os7|S KeZY $ѐZ~m۶A-7y0΢g M kl1Po! Y IM]!k֭[_u4y @2It8 td``o{&4}/9E3,ɕHAA- @_Jn_ߺ&$%zuնw{qOۿ0LLH"aBt$Π3}/KzPr 6J"$L@/k ~%7{aI\*Ai |] o{nnb3.LtdU s#͎/_<77w̙0.n桡o1%l]\&YՄ nuq}[w_>+%wh=[Mɪ&Y JuWsxx-~gVr?ܡ ~sOnrznn^KoY3](* s+Y$k0]`:y^ ZwagGrzE$Y % 0Z}o}[aP(lڴo> ۪F+L^@JLanz|;ozͦM;oYMTr[&X"Y2%0r=7mڴcǎR$}[&*LPd,5H6KJnk,k0-p)J s4Iz,4$7BaK`ɒ,Lu@IMNr&hdI,vKgJnr] YWna!M[~&0@WJܒ\:hF%u d9, s4͗'InT=.YE\M @${0@?JV}R0L@l$aH00G X_{f#c0d4J<pdŘ^I9!@m}ɭBrU:WauUyw7%wQ% aC39}? 0 ͖9k0G_@Zz hzYhO6w}ĉ0k6>|=;{ 7n NرcӧÀ6{xwJ??wp|w,lΑbm\ LJ U!z _4=C 3䩉DiPH<88/=]ڥ@w@@o+ƹљJEJT-,V,.sZ!zA@O@@O+mS8o1<' fàf陚ҞR\a E@G GvƉΑB%crtn5n\9^+e zĩj\B8Tf7èjqva> j>gЫTh%4㥁ڮ΃l^=+ k>n^Z2hh4ʑS=9*Vt 6@@[]>57Y\ͣW8\cppW#ҒA@2 :rÍ7OtU `yq+'_A@=а8^&Tj4uF@).49$v3e+\}G mnN ~%%aq <}8:/#GR2hzTAgjߏ`Uzӟ m!n+Lyiv@@/9odz R9g@@D%ȭ8nT44tCt\a~qN{2 qɠI5/0ݕз ziiX90S Iɠܡlv^(W=Ibּ,4N!:.4@{ O Tɠگ%HvHW:wH;r$nI%Vs5G+t:Gy)4p YV͙ s9#sx4@ΤۜmܼhX!:)4Cqܜ0htC<?6ͫ@͑iJ t@ @o4;G%qnhLCtT2hk 'ΠVLs\'* 8k^Za %@MЙ sMd#.έ#BzGYL9Z@ té÷ߦ'Xts> B tWYʼns"zC':0Pnv*s@HzACw>hN]H LCtT2hȏt; ~nG@4;G%q hdA@H7;K{s2hu{ȅdGt9k7HJܻ@KȑTLFRa$rpmkL9-2QȯtCtT,yts\a~!V4;ca%"U8 \C54;`E{?^=АtsT,9#XM oZ|GaX%Q9D а:p*1I+tR2hHw:KI -e844DG%ϬB |2h~g"hdGY}6>4@KwK @/Jو+$Π&;d8sn0!,} :&Π32qIi:4@'Ajqּ44tI9pZO u qɠXC;9h14@oH7DˣXI9.q3$d$,}';m=)nT 7[mHBh^ޑ#.4@ĉst 4@_I7D&e6$t?4@4D%Nt14@3L9R9*q3=J Qt8nT^#ȝDGhts\a IɠrQi}hH7Dˣ+'z͎?sSjn 'z{.^د?#jcxA޻LCtT2hJ9K4kџzDzAC;Xz5,|->s{}g?P>V _z5~LK7D&XY9.39$zb|KKR<W`zkԫ.+}ӟ}) `uqּ4Y;}gJ}[L(Cl{Fm3Wg̽g=\xW׵?MY%c:7#l 5jq|W$Wߥ?_} TͣGq4@nwHJ3$@/ే_1ڳo1ji|W _}*w>"y%ޔ#Σ`':N%ّ#0qּ4 zώ?ɅgB_C}6j[g%=|՗Ω3ɴ?/]2ߧoZ'IwN tsRf&4cvqDMs|{Ɲv} a{mtpx`Gرi-Ac׎|绁|{͇q,l=p8J7U gJe@8\۝c }$ڜ.A3t'4ϕ*#?7P,J GgNMl_ ~nNWN90t4W6臭?^=Z8^YX\ ᕛ@t7K E =mantxRSs z`qc,=SSS+_%nNWzzOqdgmC#5NF֘ WW cȁtCtRahLwsRfh= >'O/ 67W^canm!,n]g 2 Iɠy WO `480[9vTn 8^u@}͙ W}M =23:qУ3ԑBΑ#]5VnTGȴ6g*\/4ٹS8j@ǧ*3L5^ аa96mrL J7Dg*\9K?2? I[O?_y%&8#ΠWp)xiEop)r4+UzD/^RM"UZ,[Ze }Udд^/^R rF@JMRɗ@5l蠛ovB$-TRd _Jpغ'Oڵ+gzz:J%>D/|\*cc@ mٲ%d'k€6O8}'~wp^x! r_ob|vq0/5]=)KR;>۾o8pgamx{. hFΝ G+۷X @~ ch&'i?Cw|MGtC0~xj[o]`-tsտ|d=W?OJ7_җ^W0ѭН"5h tL>mt|[n)vI0.Ic̠q"n{iKQyo`Q/&h? |͓9[_LgN@w4:&fm>->Ǻ!UIcʠН"e=ڍYhϤϱϠН"vОYɟLYO>0ƴҲsdÆuM78h?o-Э9iӆ_˿@ t@džLJϾpkft@ /4\-8:hZB }O_=/===ᘶoMgTxӷU=o6?]k|η͕:p%zҾ.<.2OUhD=nݣ'Cjo_iSy+f]/ms4 ԫ6=nGk/yգG /x"LZ<ƯuM[E G mk(@h߾}GGG_nkvު ?θݎ>לxѫNW^ /~EwO8,#''w>pϺL*DsݵV@='ڵrp+#jm=}GqIa} A_o}Q{“!./~to}G糾/WR G=>⿢}t8}}4n׾}76[|/~ڟnq?'_'G+Mkɓ'wF3==JiO~z<Qݶl}O'z:pmHANx)o7Uqoi?w\8ZA.<==}xd $]Zpvs~'?z (:N#|x s{C+  >ZO9aG\ #&mTݏpe{P͋' /{t,%Nxwmu/WC!|5޶ehhhrE4]G @Kh 4-!%@NIfgrݚOKKȑ#% ;v,##C۷Z ߿ԹzKug.a_{%߰a'MiWg\tcɂ5xl[9+Y;fܸq&Mxs b6lԳlٲ4Y  0D _>*k:'S$JҴ>.o/-uE-* yE q`h?Wz YϥM{H:Qؠ -@ <OvvPXXx /wyG*SmDE n2y'\3oR9}khQ͹0Ƒ`ˍeZ^+>jkf:͕c"p F9[z^2\FYSNrS[BO:RTO/ *g(޼9|AGd[*;iIVT#)n/cI`kEloD,\uǎ?l~oT$qQCTlVn5oM|W/{NL7}vb珶}e״@Be-V.RkG6O64<تhZy#GsМڍd5Hl%kׇM+\w(rrkJ #\:R`UoT.(XkQ\ l2_6u+le-*:wI&7QT̜N%ɋ;{s]/ε<;r>߉ _g>.3?mm opym?Volϯ.>A~`R<[lҶ%| gdl8-ZcJƹIw%ŜRҩvUZ,lIi97}'E|iY79tI屿:UQZl#NNflwm`^ƌ~fyU 9meڕtiG:AGf}uMF7u_9S*5UZSn;4.ךJծvqGkU@,= }hW厷N{y9!CXm>B wwmply'YڠGm"D2~Udey]ԫ=U$$yQ"oA%CajjjkDa sD WWN~yQ9s̈So8Vɿt}~~7-ݾ7~xL'7Z]|P}d>!eqbۼc"xX/ZI{.%͛͞vFmO %fm6ΩR>?:ocOqy,I?;!'Fxс/e s^M+ E&5 wG~3ˉOx`Q# d~g<"nQсMǟdI'in ".M*mpk}\߷>xӹ!j׫jjkonAWqeZk+mm*Q*o?.P4G–*pW'rI[FZ5pl0z[VSf~gZ+:#;>AkB^Tk4_kN9<Ø/+D sjvEHK"1p)6-J6[N_ܐ ئ6ۺu$릛nF&36P$q.۽aIoJsiFBE j14Ve"qnӟ+nZѳ3[lY;5E!J?֒@f ǻ銞>~>Io%2_x)=2]B럆HHS(S ( PcPVV&);JB` v$F]]&??_,<"(##cذa9994`̙Ǯ]쁁 Կ'O6X}}3fPSrR!*PL:+ rZZZ)#RHE2jNh dܫIWc@`T$ HFv-V.PG#ĐGC`XΘd"ll3g˖UM;*Os[!.gˏﯮ.eufBΕF$&omm=~#FdddI:XjAsIxΜ9sIIѰaÆ 2zhIs"@09ٳg4?ўyQjeUg{d/6=dGK#EUb=Yit_ֳ43Gr+?zWf̘!0/K.eeeIqȑO8Q>^x1~ g TT~c{Çg p9|pĥtOaĉܫ>;DI⁧1}w~8.Þ~p f͚>0:A?._ dffp:3eƸ|6v2=RcNHfc`ΝWV`w[oU82M&y #0444L0A ~m> O|pӯ>S*hԈKr{v{7u%Ml_i_]2߆acpwѩпzHzmi dْJ1'옷H0&rYġL4*0xWc 7L}XBɢM~nk8z;5oo=//Iɠö)ռg=*TE?7tfbr/`-i7o]띺T鍇ٹݿ'% ]MQS6}^A\cUO}5NNH}bIO^đvHs8 i}4EͫaQTR}2?ҷvEUSJ$B4o޽۝;t{[KY^EcSް#C A\jE pKLnBafp1 0 eOi!? -\=΋Tff%R^o{8Kur7΋TA)L u8,o`W\$n\\%͇oRj/Iodv$=wz.g=~ncy" )fTbMQb)8VW_cK6؏NY̵9 Bўc {uꂏy5FW3A%}13LE?urpM+y!nTQ@σ$,Iˎ-"mH;X'v(?=H="0xGyU, KBvɯ^JuPuSuVQO%*ʳIB>o-*Q>J^n__'*_JXH;|V;GbK^X:]Zg}bh1M˩?l}$c5H2c'G}yT%C[{Y= #K5bܢI5Vμe,2!}vp6w;!T2Ȕl{P͘kDjD^S{lm.)v^+hXN.w16wM̰sh璈a2{PҩjРA(el_c .12.oٽOa@F?[ժ_eͬqT+̓m^\e%T^= 81P\%85mGc zˣN3fLy^Mupݠ`Fs=9H{Q*,6S./l8VRIE8/l[ g;g_~LΙ3'ҟ O(V^W:>jV>pcw{t_17'՞{ zΐk:6X~9Æ!-v߽Xܿhص9Ӟ̕^%_V.Tf}Ymʋq~l+U3${# Ӗ x&HٴH +W8}jl_67K"vb5R,xlD)P]mc}8nLБzl{~Q"g>tk_ւL)ϩG(ʓ)R&P~a>eI0cS;Feg㎚AQ6t2]y8G)K~M ~0:qD۞[n%BTH;p:{βUz%7#z7tTG @/:7D1?0z 6.w' ql;$"@}Z/Yƭ}/_ qS1)Oy$5F(P]y=ڳ7mڹR{0Gzha~)diOFE[h܁ݫ(f/H{]}u"ъo|)TU71g&4y;k?vv> &D{x 3쵟FG1+ Ё{/ Jd_@(/!)דO=;NYc~m o*c7ڋd>D-KF8 {!Ui#fgo'13ncpmji)aC|?R>Ɯ=?ڣ_G-NߎL-}VV6~kT/P+>.,LbskODAځx(UPRݑ M&E(#V\r1Ͼ{ 5Ɲ칤)O.u&w4T5)1 KNSb&5$}N2vj&D?dE*pگ0'Qwa nztwKwq2IQWW7sLItֶmϟ/ t TFUVV%ko2y7$7_כoY>|@tQ*@ئM`^߮쎇{[$2u{YW>*WhƗ%WўMw_mvڕ/ QZZzE1@Wqr"I;U\/;霞;rmH;X/ߏ@>>^KM ׂnA` )/0,?S#&o&Kzd\zuⰠ[$= 8@~nGtH"L2_ h."UTOs2~20$EUSJ#Ffdd[~OƗWΗbС 8eZ. U,OO|{X|x6|6|gAߛ4\Gㆆ .x㍒FG˓|pԩ &O\Ɋ#I~1?qDc {df5Ӽ+W VPH!0@*Qs7-jCVk>[Womz9ոqzaNvԝFG`%. i641tfY*#35;[i+v\*Lu j \nLRa͜9S@صkW~~$|%{UVVΘ1CarHp4HE2jNh r].{)AMYvDH9Çoll4c^LuPuSuV7s|XO<*(==]Ecƌtx[  0 0@`@!0@`B`  (.]VV&0fΜ) yڵ+??_lkkkiito1lذIWZZJ`10PQwfw\cƌt*0`*RN[[[*Dʔ)STg%RNKK7e8]HF)@: R {5j  d@Ξ[$zt8"5wϖґjC<p4@5׼-[X,IH.wϞQQ^{{-sZ5gi^ZYT^UtC,;vHFݣyvm^i?T}OмZuϜU=:;j=UiD{+zᅣn$(##HFݢydzzdÌ F2c6C%U`oպnfNFw#0@*Qswh޳+4g`~8$gKUWni@x2j5;v/}xu5h\Z?}^rpccqqN5J&HQ2p"h|PEjݹC wxwn_2o;}[͙FI Fݳ}=$L[Ӷ4m6Ӛi斐뎯ۏR\Q1"Թ=C= HF=$sm}{ԟYO<^`GC`rdKnJ#"0@>|xccb\nLRa͜9S@صkW~~$,>'OJ7JOOWQ1c$ի Л ` ;vHuW]uJ,ܷHEr9K<{^65=>Mi-s9[5 >V>'OJ7JOOWQ1c$m[o|/^\zuLާ_~_30`*TH@jy뭷{H-7|sȊB` "B` ")>D@O(@oaSTaST/aEqnsMiii9r$$cǎeddH°}vYKW.;sȲ?dIID4(gP>.Ik?߮Km>'Y?0ƍ4i UD#d IENDB`asammdf-8.5.1/doc/images/range_visual_alert.png000066400000000000000000001744021502633300400215270ustar00rootroot00000000000000PNG  IHDRNOsRGBgAMA a pHYsodIDATx^|}ȶc qVrMAJpRӋ—UCn{@QJ W⛀-&'&*7DvvaR ksΜݝIVz>}왙bu5hZ"*OcnSMbi+tme$a|adV@#]*JJJfgg?^Rƛ?!,ˇU+.c+/9_m[~1?BfX]t~Y R>/s_bU-Fڞ k}̙39]Z_vΊN]_P󍷭#s%o^~?x=~˔_ԣ=?󯝐͊=W~ْNEvC?|>y(Moef_ǩuL\CCq_՘S6-KȻű>tu:oE<6=s&zم+Kyԫ3c/>rbeIzL} vφ'D3}6A89K%_V c(H2LP,KkstgC"WkK_x:%yj6vlz?N=o?oձ7fVXzũ7j%j.]; \|ǟzV_i?>%{&3\φD=_8nu7~^8w#85sб7NL:w o\~8١z뀗yO#Ok=?5ܱnjeд;.cOj'cpj*&:M|j*E&zj~y0Tt_41L)z.8kH.\;u*|TWv6;_{DۣCOk?穏.07=2*P]yîšXDW]vh梷:~#♧K^+w~q&Ϲvqz**>0KΫ_cIˍSk>[Vj[>AFƢڔʈ38|?#.꿞H)|O/.oQfSrxLTKfVUκzr_$nydio?V]^q~w;W꿾j}\>ÿC[?a; e(=۹8vrU(?z>sÇ\nPD!v]sA'#+7Nӧ|zߵxm'm[?߹K޻U7>ïE/q[3 5yk\ƾ',sر_?̻Ӈ5"n~{_k!SN=\cz]۵%A\ HɢIŏ?LMfmuN_$GpM@ȼ+7@;v$Q\LFm|њI:zq2Shn X`&#j9Vf<5`sH4넫jzU>_jn"jN)@-Tzu]}rn9°!װu0"o0L{_W$;GL'>UI ;ϫ$jcatV]@ @pc8AªѽW5:O>Dc~z#Ѯ:L:\_<*YG/j>`Y `(k_X]u!g IbQ_6{BUkQ >`ۮi~LyB#ۄ#FҞ¹n'<'_q[g}6ţquW:E3GM]M)P (,4&=`#^zYB{CfuX( V@B?qj;Ąj[N$4 h@^@E_=NWj;j@z;%+֜[jl%oϊHͩ{mi44?(z Vz/Nߘ8??}T~ύMY Ѕ,ҦKmJS9z5l\sVF4:J[U*Yart'sIĤ;:$%]'s'mX7y˜FTx xf=~DǺqCOxMWW\+^h| c4VT# G|б~-Uiog<>T;5{ӆiZF3p{kkChj')M}7n!Ҧ7jdG1]wk:iSGL>_bcZmuFeOy?VnhF' C@N eH\;ꈖ3c-uf 6FeP^UZ#Ѯ2NIX&"1&Fz::nlh=XW^^qewMtFm'DzC &c.=1Vzm8E/9sTWoV]0Ʀi<@L"a!h3)M[WS$Lյ"U hKrzt/2Ҫ Up\daM:'DD3uWL{g`K1?`O\'>Ү9^׬R,[)\@I3 oy κ ӬWTHHe1ET8Vx jj9^S;x b!sa Iy\2=/|Mz[̋SƇ06N0䔯p6jɋE=$\av5Y#|"PKC 1. z6^D\,eK^wN_-l| c4T W"XVYD˱z{AM݆D)cYOcW{@wY)/kÍaY6OyCgИ3V@c),C 51gn@rirr2)fM+`!yڵ.4c(^ǏW-i ޕW^gT4`H̿ ׫ =3/n馯'ND>+K.l1FѯF\yGOq4;vo_Ʀ6z~sW]u__Զh@袋ozO>ii_ꫯ~Ԇh@ذaWSN}S24Fz /,*PJKK/aiNF Γ'O~_64ڙt +h@;~x8>v]wݵ}vOmj'&&'''?U|d;O{ϯYƮ|С'N=O~(P)'V2]͇&''׭[g4֮]k ţ>Z}L6zj;;}`X"t5'F455  W'bjjJm GoC|##2QɌojpCN.T8qjqj>,򵚿:]_5+Vi1_Uk˿Kղ<9ٷoWS\hhg|t+Jz &k_QP$P 5P 5Mi=A6գ/~ :e@VFP9b"wt.| .9.|B9.|B͇p@o]MUԍMT'<,Og~g 4 =CZ7vHgXkiB̠I+=ƿf Mh,#Ù3w?!^"j ѿ=K{x%ȭkHY!V˞cԬΕg^ֿ+}/x qC^W3/zՍp`{yA_j3z&}_ XwX,sHIhyQ=K?_SAjw yrJQtE\Rol-~٪;./} ?бh|($]Z༃޺Pm+9q ^mw~/珫ͫo|j8}2h0_׬_еKV|@GGksv]"j!X&kAjEu5<:JV~$Z۔^ƋWU~B"FNަ5-<}~A>oڕhzX=Q^fcUÐ4:Sik_~9on$r5/1c/P%8`J9Nď0wɇ9J?j@{5^Qi_z`Gט&:dhhjsdB joثM&}*9u@:~bw,XšRɓas>9p'*VQF?%2h^EQH|HKs$:ی\ƿx*?L}k*r{27r,VYѐ~h|I^=$fg:ZwgZ]M2o9h4v $3݄0;\,p w9uWY߸FȔϖƋET }Ū!KElZYmwu^ԗr-h%4.]{]ٖv5"5ؖr`)2[[AmZrm/T Ai'*A/1jƶ9|,}΢=:v& J9`R X&̖ۏv3?sg/5ёmu I0'bdB@.-QU:6?jp ]d0:5 4hU'pq:Ń)_X-g~VFYk ^}OW%bD<ݪćj٭:=X*/ZV&Mr]C,vchA=ƾsGQO?j$`oX_#\IS5^%[so^2̓źw _:6O'NTw.P`PH5D$cwժR[k*3$֌ơ"~bߦŪg>V~kM_"~XC\|r]"F,^6aniR"sVJk앁vr4S( /Q:)Ru(c|X`?ϑ6r>jPU0m!mD꬟B5:Oď{x; Wkϩo@kHg UwMj|7jn&V?&h7#==1N8`&GY8ȩ*⿿NָX}yt꥜>_6s[k^"nXlD*6 $NJc>*D@`I *Eg(W Gϋu3d9/$~46s5 `jhmEaֲ;/k^m8▁y{utia#mmIcL6{D26eN!\ (Vq 6RRrGI_EC:y@V.`ז([ |UpmGo5fOx?Jh:{l'm:Pl-~٪ꟸ4~; W ;DiԚڪIT5UH,ibWNKT!kPn^sc\Ty@VVsrqO.Vը7x!~FT}?m(j׬_˻G E8%0D`iIy///Wŵ8ňFk^RMq?OVEEԔ@߆ikjzz"ÅPj>pj>p"_qnt]72>֭3k׮H3XBhj^/REjIй _|]X ?L%+,$}6@/||Jͅs%9Dž\9Dž\lHƻ a{GU+hʅY %^. 5Kr 5Ps 5Pa9f> h(N^_[EB Ps$P 5P 5 "s`G8>y@G:ã m8w!}27!̝ҭZ@| P(lZvOi83n>p)sxqjqj>D _t*<6|KB @w@R@/{mltw$^. 5Kr 5Ps 5PaM;&;Gzno@#TzXd ԁlP7_W{l"w\9G\s\s\,15zVo=hR `d~%^W︼T+< ^. 5Kr 5Ps 5P h?7! FGk>}=7sxg'_ﮉη0/*=I  ?tB'ϳ0?S@ #mz6Q?gp #mc]ѸCKpĺUwDOj"c 3P|]E\5Ke>mEόI'vt +ukkZv`}ͫ6 !C(\mTm)w5cf9*sؕ2sRSe4U5̵Y#e`qZU/?qyivg`@{TQt9]WSZ)Fû>lCp [s xgs댴U4{g!)`K9/n 6cO~5@aQw٨(&׬_ayX\(xYJp7ksNxtt"R i9!<-UIu0"*ՅjScіɚ?SIxS; 'z'GP#/5T"aM#9lGq2[ u?ӉH[KcDL%shUN{o6rg"ʈ{m1{\v&E;C DAdKGs#J챮ka5-*7li1{r:qh ʞRe#~u9lq:zM. d0mgiOق^C%2[d~0e1jb06SVU?^b@b&*([#̸$vDG:/I_Yp kH-M'њ*u0Lv ` dS "I+~ ia0J3"6wu4Ƥ8I!Y1"Qux>_#յH=Ccuf`Zw<T7D-5ThxYm($EڪDqCթj!؋̝"z-*u׷j}PVI-[mp.f0Y#T0IY dr:8\yXo2 Eu岵NspLD~u\*iՓ^^b*ןΕeV◃, VDI}1`۳ Wm>EG ` s@Zr$)3 vti78X蒍f}F2/t<$# wm{qRKa9O^0?wRyGfrQDY4Pl-~٪ꟸ4~;3P,6?JܨN.uI}Dn:L0mkgr:y:GH8%<4>'B'q @Q}\Fl QLlIMRɢd8Qf~ 62Z@D*ngZskj=-uabM |ZZJUͬ9`щZ]PߝR'N*| c9=V/AԂ6hN:^;P/1" q-_hk E3qmЌՓƟfy7T50{L|^<}[םRu_kwdƎ?Za_wz՚ վy}m/f&zQiʺtu>֭3k׮.+y7'^V3?M|Àuҳ95N~gEC 2R˚F@MoFs/M2b;NU{ g@ٰ튋g/O:~~?NS ?10rZf3IeF;W3]Zu&z9+u-Wo~ҏo̚*e=3fYHeF`XC 9ϛ筫g^=rTuIYvE<™\ܫDʛEgFυ>370_m犛 VܴMi]~Gjuźŭ艴YYSx3N|9gkف56,|` 8n ?Vեi~/z+;~w]Ixm07Zz"mڐxCV"h[{ml O\^OLLTWWONN>>'NNU*~7f_~8O,/ ᩩLK 7oZdcL^i7労ky"ƒqf9ϿU[qLǏW-i簯o_ZsfH~SUkq-κদAX`y_W{l47/U\1 Q9vWE 5q9.|B9.|B͇EV%u]72>֭3k׮9o<^hHiP7ekP]SRR`d] 5ϖaש WzLN)gi.6]XchmmF+q(t &ꎤ2ہȉhߢ? >YYWVS޳7Ψ`m箸w;?/~חNMM=7,6hx'TFÝfu+DWn+ 7}0H[UKTŇ4{dƘp,ѧNX1c@<5֘,Ҩю>W}Ni yVXU7V^ӑ_5sJO[δE~5fgΎLOOWTT=QOV6I3p]W\AFUjosj@Zd qky5#r,UcT'I8e)|iy陸WTۚDdMgǧsY%c5/R;`["]S}s2. i5INβr 8,9MkՔ^IZ޷;ej{"ςXʣfX+*G]kDw"V;bݻ- *.#U5uVpKsm kjy5XC ,Qi/:cW086}iy],J,{d=eQCh՚V';4YEuv+=Y6!ZG 8(mV09 wԎʑڡׁ!MѨ :gFϤ2˞(_gO3/>or\.Ї>)>bV0<6cmkHOψ:̵3,"v}H6VyGW9Cu)a@rg> |/-/]sΊu4o=wsVlX&]U˟٨q"V>mU~>裛~*5 Jׇ%cֲ;/k^mI+j׷\\u9F5n=k͇Ζ}KW^04қg  HySdZU/w\^,V K-ұn= Y.Mwio:G5E~AmyT+/cq_ȑ#`'P"REgV"2AÙ$ 3B7 ?c p!uGsrLyXW[f468뉒;N'ǀNg'Bvi<;##𒚌gD\mZV-72j_Wz^h2vǵC3|!Φ#GBʆ5/hҴA;fݩܫGTg0Z N$kuǘӉxڐ1>4+~JC:yFCݫtIR'vRʇbψǧ XV%W5jA+/s=si;{:9F`S~MԎ&ܭ2eG>t?TB2c2QȔV{>)ɞ'FǏLPvf{vs|'j[>٨dϝeeewDZ5_ K;T'ÚfZY3&tZ׽2!vCLcޡժV 4_M@6+micfmY^MM^z"5uwGc!/_֚jW-MM_-mJj-{Q|XÚ!(d!zP͚jfR; Ky*=I ` xQ75Xx`0xs3WapTkR 6jj-IU UbbD.mRu:&t/hDu)2jHHURѾB,767BLȏ ӊlj\Ff`Ԫ̬S+*fbSZ߅Imb[^TW3-V >c]^@6j/Gᳫg|N%c>m%@wIɵXww&ffNq~o\khh BG\ω -40C2[ma0HowjX.ӹsHpcEw!}+5WhM_zLON4Ozjü_RWZRT27{bxD^rxL$Pr]Fzg&J8~ˌI,|[o7Tۚf>L=EUJ6CYB8[:;; :g}Fb^-"3 01ð2s2gLtrczi1f{VyhLi-i95OϪ DH?~Wu扙NSw)mbc~+jߡ69}`i`3\93g~] h=?9,bݭڡx+sYW =j gA*}6 j!_[e^ S#D9QN 2q;]'n^4KyުV '`hVZMh*Ƭbz8rNUZI9Sa.O${ 4jڃڨd/M n"ԾV~^F ZmcOUm ,s^-(58`_Tpb۳ Wmg9t+V}ݿ;cfЧN2ggƣj\GC^FGUeRZaR+dnk s4e.|ar/G(t &ꎤKMYYH9I U`aд֢EweaQ[ \U6;[FMT vdεn0TKĦO16bCZկx>.knܪvC|N媵gqqSS 6^(oe8JޓfWEEԔF߆ikjzz|wB͇|\E 5Ps 5Paո}t]72>֭3k׮K&+Wܽ{Ljtܣl]Wl!ml\C157ڿ/u9,3694Xw9B&㈃XϩKY95NZ{3 EQ:l(2k.;Ի753g/Ct@.-`f7xwߝ9R;{bb!ڕ+~Ң.;5}sp_0sҾ;+S;xHyP˟0;Ws3_=;}U/B"uyYr;VZE,m)+ՈfoZwwZƘp<{{˪Dyj誚:ksdh<]:ĎS$}s*ƺ0Qy ģ]c8Ukj]:^;[p agHVmU8(lV09 wԎʑڡe^,P5S@1[*%8[}Dƈս=VѶƍ=\;"a0'4icZmuќqtZ{{zk:X؍`Ϥhu"oj\tU%;ε~ORgPhUk#5zuJJ[ Ēa{ZgWiZOTOKz޳DZv`}ͫ63T%8" VƊM9ɛJj3vQIKϒgkVmPI,*h?J޳lxnKGf"vHPPw.Ɵe,hG?ew>/|Gs3q;ZA67&''׭[gѣ/}]m%>OX%"5vqՒv5Z W;9<_mZ>뎕wޛö8Նwe>4sU|p~***6rDmH[Uӳ<_m.|DžZP 5P 5Zk[n>dk׮EڼEaj@\MΌjWgz*=I `Qcbz}wLmes|3FGߟ>*r\=Ӯ=P$f΁H{@;Of,M7,Egpym8x&,6?9GP~ (p^=;ZE#Ҧ7j*]o8VCF^GDq)Q{88w_Tw=oje ޷o0VՈh<T}hx6ꭲiGÝ2nU{Nm7u6#4-0'ƕ'k{N=O6&YZ&cciCcxT< Lbѽ;y9#d~\O'ZGHCǨ\FLK_W}*~.^K>jAά/A<`36ؒN!=Σym:vt= cݭڡ#~Wnvb,闊q1nՀ\ha~ Al_ A8LJjyӴPhZ=VW'Iq9ȩ5T>t.x D[|'Y3 Zֺ~':k'ߖKHhңxg/*¹ n05!w CZKpiwkOx:>'KZtV} [?4H<._ _DP| k5% ۖQGd[[`^ inQAo3\b&3&tT]DljOm2_Ms v$:ֽ7+5Zƚ!{]zҜL[#ݭ-`sh[rmuﮉtԨm[d5cD}wX6kqH=a_4_Җ@jt9'å"Pϧty.1uBd&jpu_ +6թOۘzweb5nWGLmLSo*9$8F5Uj#hی3imZSl2/+v>jUaQ(a&Y=U5uvC>.mÞ}Zppeٖ=/@@k[;(+B˿ l8`s$@Zr+PaXNS)ϘjG|9T-c7U7E[}L a{׋iM*N6ǵ3@sOʭv~Y{쉂MFK`hCrpΑT#raj"%|5{ c\N'G8i3dhO̞@r ,nΩpGW#A>Sتn%eΦ3M̼<<| f jiҐmtW%h L<]ب6, YBkje~7c. NF.WoԚ^sP mՍæoEԣ0c4ȍP,Ib>3M8Srd{_pY@>cg;t}Y>Ysc~R_9ڤA|Őޣz™7}bbܘ\nNp`ӱ-{?} \޹陽NI=j_Ǐsjewz՚ L6oޜuY=f_fO81,Xw}ŲF[IEPd~Byyj-k;}g!2{#mmWMO>~]dP!jB.ԜB.|Xk5V2]͇xyڵvo 뺞Y~ÃOzey #i36giZKOb9H/śϘUٞUI2385X^Ի75PPV@Ζ2ji+mV@[>A 5Xs\s\j2/50_>˷wPm;+)~-FqiOw#.ǚp/ݻLH]qMRH8}Z cǎʕ(ֽ{,۝FcP\LڱlH.'U$F]>aJ6eVn< 6EО]cr`Gvg{xnT80jivj`ѢZlt|lۃfmT[ Bj#.guk=L*]66iյ^]^mG:õef.%8:7=s̲CFM@# 6Fí+FJ5jS6dF8hNx*M:qU,A#ϫkS%f.%87tvP%'=hK,>l#at;&:EY%9ȰjԆفvw'X3P|k #lbuh1 {2K+g->odٵ;EY9yՙ]uV0]f΂"_S~X|aˉCEEZʫWG6ާ٬#y=n#f癦ǰNV[-9`ss6&5 pj!d-t[Ill_kd,?V"mRgzІXwgYY|2KOsT&Q ;=GbSIoXր, R٤Zi wlh@@o #jg>ve+Bs~M~9=祗8(@]ϛ(|>O.~`cO6-g ݜ09cQKgtb%q9-}:etAͤ$գys%Q%<= MCi0$ɝT;>ZTL_c33J.ݹuS!j{-p?T[Rn\ekgS_ ?=&]O}DAU.roB3 ,}"QԧGI%@{?{{5鱚[P0MSʍWǯZ6dr:n3^*~JC:y~M=z$+3j>%w9k?GԣW[#ӷ&L"̓9|8ӄUq0uo16TͣP~.Ӷ}ɧj~vg.Is0$~M*c1)wΧRK'6?Ϟ?gL-iBZd[jKcY. .F"h(VoBx]m(٤jLzSB 35?v$y5U*;HoOߺ:kl r|JJ~V.Vkź_-Eӹz<ۗh?axkΟ9/_Ed޷|}΂=#mQ&eJz mźu;6ZYgQjm*Nwg &u;ʦx[#$O"*E&ig"tщu v'2Xw}65v\>RKtGUEh(>06up8BhQIg!)꺢eN8i<ۘ{w]h]}j"vKxXm̮n"Sr&zj2- 2t\ؙW9(>f׷eʄunJ-V[nA<:ҟTR! ̛WDV;,=к򷮶j'~/\0_Y.sQt1 k--ZFGjv=hFJ=P-GN&5c;R)z!ml2y1c3tkwhW] \r뷴$OK/Ӱ-]r)INvt3M>[D՗YԜN]ޏ=Oj˅ ^Œ` |v`Gks>Oe.H~+,q:G/<e ]fTH<)hr$Ш&mTӱ^l K;ՖX"宮mWOm3P[J^L@OSɵ#vrS#DdGQ 790tbw YqJy>KL 9H T#]IԕXm-fYDsm3r1=5ZY.ij~V@'^ԺwѷPв?QsΒ0坅~yRyLH tO<_;+*4CVj182ӳH1/4U9jG?3QQdجfEMfG?J ;2t"H7z۪]kj{saSj3{:(OahjՐ![O#N.N|O$z STzncڋ\ Y?B'HM[\E\~zl|.SuOLLTWW֭3I޷[V'9?=z>/dSĺ[>3_5U+\;$B-r\s\|qJ/]ng]-mc sq7UQ-JDO.:R.(ȊUg g9OO92۳H'^ F=]ZG&jpmFӴ?4LqW4nWhkdHn ϡFUuH~6>9:ٟ yزt_{̧uJ3q|hRw^|ފM\]J ,oK%8l!SC>~\9/j>pj>pCA@xj_ԅ7mi\EG#Pm9DW. 5Kr 5Ps 5P l%8<Li @,]߯847]ťsĎ?82}50/oBzܦwSk7Vsj֝[/Sj\AQ%~tjg]~sryE+Ο>^cy}ӦۇՆItH)ǥi>iMH˱=fvLmdBRgbl9$P\G~ͤX_~.\U] eȑ#`'Pۮ}cr۶o$C}YB[ ;rM)\qEj7qMg_~eVn<^y=|sr6k=kȡ_Lj#?T2 Z÷oyRsbo0 X\+积43k݁gz^z]xZȑ#PAu9È馠fgڡUiZ[]FJ=?xx۶mj#.g?{~>f.Ȇkip>> WXCUvv҂6NWofR 0/뫽#'gEqSɋ ;},+˰[%>eݶϧu)UtKu"cˌoZg޿Z;}N94F+dlKIbgq_ZVD:R?Md֏++?l¢Q%t͊-c4NN^z_~=ڌ /׎Z$<`ȑ#NeѪ.Y;b,H4=̝ngW"4d##Ni.+3pi~q4pY,bg,78Ww=ojІmU[R^ FCCCeee(:"MB`:jElh&oV٫H߼7gp3{+՝Rg<,WKXwkv(T۶`O|6#pM$}:^1?;LQoYu VEܲY3h&kpĊT,{n bm÷oxrmd.WCyfH9-sȈYW7\Z=$"fsLorf&>n>ڪ[qiv]Z| Xl!b="mn-dD[Ik.s?gp*++WlI)|ZӺsSM]-c Kigwu0kn`/wYiiItWKm15k7kUF* /NinQ9q3\brW4q[:kG tMǮڴ<صӷ@o]K4fghjL,6rwMtFn_f(3_t[.\6X]٨(x|W|"631hOoأ ":hrqd)Nq3)bsS4m U2˟:Tg`h;ߤ7TGU̟3ւ=CZzN1obcf%P];a79sV077]ߪ%B;% E9l8` ߀opEZ]YjTY.#ڥwY8)U1N1S+ߪjX_ zkqHe{Y]JP*,ZP#EoFAdACތe\_w'*&E8^-y@{_KR\;s":n|Ym? @Z+:_֘o1d Pt4lۡ$'ȩ5DF̨pU"iyN=C)kSvŵ3d"8lH\˶~kH}_0&9P2fVa쉶[ŕ> } Dꍚǂ阸[aY#qKJCg( Ng h7ѓz%>}ZkU%-`Uը/Ūp,y`#C nQv*3zR,88 V= 67S1NNٗ:T'0}UېVuٝ"QtQ8EN͖_2jg(^@oGrDқi__g(Pe^So4@g8%~(]ϛ(|Duu199n:=Gt jcqll߾}߾}fۋ/!,P?p?~\'T+׫\ūPwݔrZ\;w_B455 㖯UTTLMM{vWE 5q9.|B9.|B͇EVj%u|ڵk6%8cMnV&eJz mMKXSnJ;62!mv)DZ7]J*oN'O @! Nrȑ`0OmW1m7衾߬?!˦"g7"|rwbʍo+yoN=Y{mRpm=ߴvgnPC#GBʆ#Z𦛂ZV.{+*UPeT]3mۦ6rC}cV鲌lv6,Hjs l{Xe߼f`I .:Daβ2BްÎ\m|bRMT.Vm%52ƙo=EUl#j/Y,G6^PRu Qx`0xswl@57ٲY}misg5)2*SmkR f~{aV'&g`) P7}N E.XmhYX#n3K+g->odٵ\̳r)3 +Ǯ] ǝE~7H貲N3>xwӖ{k)!֯`6Hxؼs7ٍ]lJLc bR4%Zss n\ M wɪj!d-C?;zL'nZelݱ@X62bm۫ n>%xhCYYHg3MJ  W #n ~|evvyׄȡ|^p{Ȓ}_D0ދ w5#,U+CƧ،׮]ktl8|cmhu h@@@oGKޗ/﫶}[EgMnV&eJz mM;6%#.ǚpU1% iK9WP}p8}Z W@rrȑ`0OmW1m7衾߬?!˦"gW$F][bNL|UaYm{1i'kMʽnMLpc jg;*R=(jYm)//A+oF5b8rH(lhhP]n0o)E~h岇쿢RZ[]FJ=?xx۶mj#.g?{~>f.Ȇkir4.6z˶U={o!j,a+yuBp:M j{%=Rj J"5\t]_.L7l#mv{>mTy-թU[|L?qۮuO=g&<|Kd*kőtXr^JoDFߌ]TR ]'G17}v*i ]{-eG̑0w~F^"Ӭy8զM?v.2nfohzqn",igӛ>%k|jN~lZ!X9eg}]Z,=|@744TVVB#9)lbu;fc{n,gp͖3{μ+`t7w=k]/_^a~mXuuB aYYYggAOeZʻi=vCWU0u\VZ]EkE(nyyj-k;}g!UTTLMM{vWE 5q9.|B9.|B͇EVj%u|ڵkvR%X(LQ5>cڗǧznmhd ]7X1h@~Zv`}ͫv@fͮ4 l-~٪ꟸTo@otGͭW:K>?\~w^6r.Ɵ}#M뺎=vȱIE vh8{:6L˔@H9.e_M;M>wHmJGz]5%6cJn#f>#;xXP wU8 wɪbZ4#1'7.Z]D/5{|f*[y.=`;~Z.Duu199nݺkVR\bEW~sSJTžz̙\} MGt jcqll߾}߾}f͛o dƎ?Za_%u_Zsqv(BuSUkq-νDUTTLMM{vWE 5q9.|B9.|BoZ{ Pu!Sn:vZr捫u];f|7!v^폞s>Rc@k~ʛ^es6jA5Hr{,m+]S8kc/<қO|6U#0oF@NO 7!ܸvnZ vm>~6)9}FhSӿ~Z _oX|'KמSEcݻB݉h4]ߨ ťhͤ˦R{"QLoE\5,r1|o++U~͖種"Z::ZA+T@{{ljk{"PHm$5pPǚY22&#M+о+ԫHgvQ3kYm_H@ģ-U,HS9;`3fshXJR ګQfEm \6:Y U =Rvt72xT"󬜼GѮ:+Ǯ]qgA)Bgkف567IS@ωW j)!lOYGe{FZg7vq*3MaUMj 1:%Zssjm`I۳le6^}vA=Z+Yˀ#Vw O4UƶHcmd.^{5!-uV#յr"N/lѿXwTs.ƟI@ρHeR`kqz^+\;4誳ǗYig=qYCi՚"K5y{/{FyƱ]>~UKt"k3h}HOLLTWW֭3pQP^JЮ6Β͛7۷Omx3KSk%S׫\,ǜUkq-ί555  ,YR]{#mmWMO>~]dP!jB.ԜB͇e|o_sX|̍V]eոu|Ȏ׮]ktl8 +uޓ>b F@rj@3Pes@[uXHKp fF(V{yA_j>OրV(V{ml > - YReK/Y)[蹋u v'Xw}65v,>RKtGU3gs.7ʍCƴړWkLL]`c?PC-.6|hFan,6دtthV.2ہr)&DzCHkcݭڡx5?Jed9Mf9F@uW}WWeۑp.f,);Ws3_=;}U/zd*49r`sh4ܚmTӱ6uoJkdٍ39d3W[~ ]eb8z ,>;NU{yH@ģ-U,HS9;`3fshXJR ګQfEmK=s G,rd->b8V)H!eVZ|ԳkQw̳r)3G`tnǝE 3}VX09UQ-% `6H8b{OH.pY%y1S-!69VDbnt<\ ,*# QX-䕬en+ ;zL'*c[ͱ@X62bP:+rZfi{΁D9jav_|* `l-;vgrzD*[+ZڡH`GWu?2L;ˊJ`/wY˛{15#5uEr[s( ɞe/[B}=;CDuu199n:=Gt j,ټy}Ԇ?c4eƎ?Za_o+}ׯWX W;9ZMMMj f~***TrDmH[Uӳ<_m.|DžZP 5Pai^v^Bl|%^yI](Z㪕Lu!;^^vUp-³952Mf6|hF!]chю>W}NiՋ@oKyy j`\ykMǧ7P@[8UyI@oc.S@0gn98W 6u;<>\hulh[v./>8iֲ;/k^mCX4~W@w϶.i0.Si#帔}5-]1)uv9֔۬Ҏ)LH]L\Ƨn$'gkVmP)| φ-T(ֽ{,۝HcP\LڱlH.'U$F]UxO2+7cz#h]ZQ#cZGj0G׬_ayX\,@o #jg>veޓ06دtthV.2ہr)&DzCHkcݭڡx5?Jed9M:x@u9>о+ԫRHgvQ3r3q;}8 |&d]tcoxHAT)hrh5uEHcWmfg 5俊d3W[`ʚ"hqLzMցӺ|%􍏟VXt>Mxp^|Ǟ lT[E@ģ-U,HS9;`3JfshXJdߨ K"Y6NA RD'I.O}DAU.rXoBE.XG2*{);YKPzvmt<*NyVN#ehW'KItnǝErLDrpThC2UQ-% `6H8bށOH.pY%y1g$fŃ!u|;>xPw Ur^Z鶒`Y1l2E˄l#.v & twyfH9-s8e7DzHF gGt j,ټy}Ԇ?c4eƎ?Za_J}ׯWX W;9Z755  ,YR]{#mmWMO>~]dP!jB.ԜB͇|\{]~Sgv8EVj%u|Ȏ׮]k}ĚO²95ҳgkVmPqyCΨ^,=>>W 7<=xhd1}k֯uҵKV"+TvQX$OdAx\> g KB5;Ws3_=;}Xz'UH`&1pޓKl埥G `6j4L &V-6UVRXH 7uc:&,6]o 2%=6RKWb^Sqm69B>Ik4#PƑ5ج]kTH!eLQp~N=IY9UgؒKDR_13~mJuM;J?zQPn֧͆CFZWG|Vd}*:Rߢϕ솳tRN}`sH>G+@ P w$25똫Ԁb"jEk1p icz^#dư|؇N"mz}rVu kdIH՜qwXxvs\'raj%8 {BEq{pH{sS.4!QQ'Qݙd/dSY6q˿*YUK9M5Kj1riﵡ;Vv뽢Q֓dq=4886`gbjjJu!Go@F]5==vB͇|\E 5Ps 5^jܼ5d]͇xyڵvHW@oF[l6sͯb.mLaӿ]z\dW m1-gBZجqIϟc{ڳ WkH1'R?"Pkl\pG^TYJT=79yP֯Ċ?o.*Jzسle6^"z&}^\7gٸC n8G=,ZGTItd6zQIڐ{,7Ԭ2?6P|YRE1X6]Q,(^W\Z|Fm#3SgbƟÇ2=^B<"D,6/zyvLmH=,;WkW}NiՋe*{923 `JZ<=[|hլ <; yA$}.*>/ ZgЛϽZ[ճm?L{m}n8gg i0.Si#帔}5-]1`z:V^_;RYSHCceq-ή3UI՟ݺ;_R sqr ] XPhlw"u7jCq)Z3i#ԞHg8/醆#iSg #{v%i?#8CH늊99PHocr1fivu]Pw빤%g3!6دtthV2ہr)&DzC!t8,J=f#2#`sHLkL#]-~S{}m7!44I$S֦@ɑCJc'RM.{1L,hV[bcvt|蹙+?u 5h3/"s`vh=9)UC@Ȑ(ҨnGOm8挠#m h;о+kFX[*=I >11Q]]mnLNN['ߜ5;[Y}}QP^JЮ6Β͛7۷Omx3fQDĭz c\2_cǏW-i簯]^b)\P<_^^Zx^555  ,YR]{#mmWMO>~]dP!jB.ԜBB͇EVqͺXvvYպ ²95nEIJe1E oU#Y(D%8}ы*#+([zǣn.j?ȍkHA1gֲ;/k^m@eֲ헭xK㷳@+u]4?s%TW`6j4{&cx\>4#LP7.۹P ȅ+}蹙ӪTg?яfggvźu;&z"mV+os'=]`.[8UyIg$xm0Ybݓ A`NYm-ZEɠcݭڡxOPmkv\%cUM|!}Ƽ-%%%AGC^sTUTؕ+6s,ѭza:jg8Z[-r "O`bHDGkj ~g,Dj}t!櫤tjjWPWSZ)Fû>Q"44`\mqY1̭3V}!91F,6i0:VcL'v5z˂5hQg#8ձ|`~l-;FیIPّ銊=7Fǣ],6I3pp;cchJ~Nc_}WHIu-Mr8^[d}XJ&:"-.ZU/?qyiv>#J ᩩM,R;`["]ߨѮNkDE rd3ir.Ɵe K"㋔> bypo*s+:Dh˷@u(cuv,ȃ\0WCWY #tu#]3qmЌdIк-oYY zʢ6Ъ5yNvtiFxW@{D-fm=C" 7j-6q5UQQ\G2ta@so#õCI+Ŋh4ӎ>W}Ni , ]vه>HM2A$ TmkHOψ:̵3,"v}H6VyGW9CM)ᜈ!m(v-w $3re,0lԸ r2g d?j7b荽!V&`ё># 5^.Rt,[}[5+h33({yA_j>cqj3 =[˶_jKzvFxW܋/bd"eV&6okȢ'<7sx߳7>~Z=_[zCCCEEŢdбpP'@{^A9k(-w $37;xAtII"eбPWU*J6mPenk sW#7wGkk3^b!QGU+E]W_{;&7bkntu]2uKMi*91~]!'յ4ȃX+ϩKFGDxߟ=c|Rn]cO4hhh()UwZEQ돣]uo.BeaQ]g(K gkف56,|3=0tM`ȹx4#>0}ǖ "H"ҘHޒlۗNj\q-pvqpgKvM&{⪧I?MZ䔞D 6i#h&2Ā&I,4Fϝy/=GҼ|%k,l_kGܒ.VS?tՉ~r{z,̮(?1ml k}N(_ڣk[I]1w}`KQ)>' 3p!g`=htI}N'PcN w\q c6n"nWq G|9Hgjܩ}-'Z3沓CmԋS-; 'Vh.;nD;gio{y[UA0kPN,ov>q+J8;GQgAptIkhpsfb@۶{6]w 䒃cGfg + (nWw;oXrm>xەQ,9$=Ի-;sKL沓Cm4 GpezZ:­hL`uayP/LG4bg( L5h还>apsfb@۶{6]HO|&vN\rppPȌLY$@EesZ} /@%9@Y [xsoԠʢvH uej> aW_;;VK_r?,>}8y2P i䝝g:S>]M<}.S_=ybFsɡ X},|Qw~^_՚>8h.;nD;gKez1O7կ:[J[hn?=;Y>8bg( L5h0,ǰ? Wv~ϟzoo6e'ܜٵX8'MW9,@8E_vm<eqQW^e~uG]8VrC#33Mh'|gߛS?{_gXh=;x<}+ޒ>T I3,ׅ}pŅg/vH4p6>ÂEϟyÆ9fg8\vrhC4Vh$}ևzn[NezZ:­h ǰ% ˃}a:׀ 79=Sx H |3 ܶݳ*`KQD4,Y4ܞt,FIҳ %@T-g'\n}<|%Fg /@Js:NI[Ύn>orޗJ -ryz7}̢+4\vrhC4VaIhϭ>J2vy8oUFsف֮pko&ڡ>d%k-j[t;q_:+sj^_gKt:>@ oN?7w ?y1sjbg( L5R @&ؓ/?M鬬sݥ'N\n n[,svϦ@epZscOuΛ,6\s]%;=2>2ٻe(/W#] #s o>s`YhJߏπ?̽+9r> u)I39^o#=Cۯ phh.;9!V;NI=]`o&ڡ>C 4Ζ0GaPPM4Mj|1s{PM4Mjpsfb@۶{6]GD%ųϰBhK]rVApǵKmO~W<'/XaCw϶ }<ҽ 4uE}UVaK ԅ\vrhC4VaU\˝ܗNFn r԰\v#D;gXeCrw>xە7[gjY_gKƣ0(LGXU_0kGܒ.@_ EbSo< r@ ܜٵX8'MWUtegD6AP䒃cGfgX+QtsԨ$= Ԃ t߸m黃>"Xk}r¡[>|^Z>C0@oGx8O{p%]h.;9!VP* s烷]qwwX8 1vuh ;㟏sXXM}-a 0#T{ Z_ EbԖJm焽͙]{Q~bnt%˻!h=ءjVGpt_uGp쒃P@Hs:j#83ԝJw@s烎`P*3=yc#8XAІ|[t䒃@";M>`=]`ofDQ}:>Ra`ua< /nG@ttMɏI_ =Sx ?S>zcr߃.J*ܜٵX8'MWzSak_lܸ?"T%ųPזtGٖ ՕgQa.q7ʃk @U%9 =[ܶ76RP 34q=wk沓Cm > e7x-{kWyt1,h.;fvMghT/>8=sK2vB% Q\}qK<P޷UX *(3U׀Ta._=4}-lǃ/ݫ@,3 ܶݳ*p* ГtC783 ;=2>Cc"r=!`쒃<*=z·.|+7n1EX>9T| ֯MsK>Cs<@沓Cm¡C@S @vc,m6Ap\v#ڛv8itR]wq+spΖ0,J(^i7]_pܣ p2QK{Фxr׉caDmgU)U19|+`AzQ-;?!]r8$9hΔ ,J`iFsɡ 8=Y}#@@OkWG7p3p* ?;3J4Ζ0,J(^Xi((GJ4(C=Sx `q 5voacaDmgU, .` 6C4;=2>H[OӳKKQ 4>,5JON J}!|) G@cK}Ve9i;>s[ Sh І|C3t>< 3vu]t`YN?uMũn'OQuɾ0xL' G+sQV_Q왲8#菌Hg>4h}psfb@۶{6}`Y* Э^А.988v{dF}\EES״gtP%44;X!4@g`Md4ڐo+}N:Y=]Lg` ͢% ˃}a:V ,8;L5$@4͙0 ܶݳ*BzQ!@4>"@48X+4@%2_n/}t+g y"+k, O@&~|l}7_.Oܔ)=| e'6J$=:>@_x72vy8oU\v#ڛv =GpT3w>~t!{s:rčZ[:Ζ0,J(^XK4@%ޕ1۳qj|1s~ϔrkOX=R.}f;$v ܜ p Om=o9+o77'ƞhWr3'8t*v̨@*Ko(/_l| ^kWVMR @*diTr> jP%@ԫhn>[}j PϿ!7K~wh.;9! .p 8ezZ:̮b Ph(w7?|^$_ozkgl xW_j %ox?'>+P: *(3e4P*Ѕ;Xr o{#4;su5#>yfb@۶{6}U wƗrM}K<2K*4| ~A!&,\rppPȌ ԋ 7]ҕNA} t%y~EX{ T\˝ܗNFn r47s$]5>u3|OnorvLyÛS>|/?!Xmp Ի/Bt#vnIۓ7U5NmIzVzw}'}@sd"7!`=]LgA:@oٙny>M4w=w UA0ku#8 w\}.?] Q*ku]7ntwyk(Aw?}{py8U epsfb@۶{6]s}r¡[>|^g7x.^XM%ų@#0@o;y܍}n+lI}N'o3tϠ|7?y,hl[v>hP~}KU @ëpǵtFsɡ 8I3* ܶtshJ=]LgYT~G(% ˃}a:_Gpt_vezF_ Eb7gv-DmgUF\rppPȌ 4Jw@s烎X>&S p3*akӭ);N*nWt‡>[ʗ",xJҳ PX%=;\\vrhCgS>zcr߃.Jhv@OkWG8؛5QLW^֯}֮߳qO^:[0#vGٖ @#tghT!ܾq{ <3X8'Mhz-CONe ;=2>#=xbC43ttc!мv* Ѕ;=j}7^{G!4$=Ua-/y2K*@se'6Jc*Wamw|½_zp%] =]LC}X t׭_;X_= h)uayP/LG0@}¯j38;GQgPKK޷=@ܜٵX8'MWit/hzz疠p'-}8H4䒃cGfg:mwz<.G hhI}N',iton½_:*E4h]}8s ]qƍW޶[c-Ж %I3;E[6Yn[v_gA沓CmUTAh\@OkWG7PIZ_gKtP48;GQgP47gv-DmgU~᏾>\M(@CI.988v{dF}詃/}G9vf }`O{g_JPϒNX' d.QO<}gUz `gS'=tß|p:IzVV"z> WW^zG^Kџ<Ӯ Ժ\vrhC4`5-i/ܲ.[~.+ [GGIL4vu[{3`U-^m'{=d}k_^M sw}XvuayP/L jY O 8A^ss3JE bg( L9M`U-L2s/}_R =pݵPu{/+P7gv-Dm}'7Z$@–)_u0 ~xp~uap~ '%ųo. KڎñևfٽhtZX xCUk:9e[~W$GsԚh]}蒾W3+o޳ 'k(I3@-8iG~C{˛:Z8dچ6}nySҍ6>5gr}֞?{i;.\r<`Ս沓Cm Pkԫ\v#D;g#@%La; Q<@_ Eb@ z59kop Om=P3h.%;=2>&3p{R9JIg @ug"@k4ڐo+gs|H@5=]`o&ڡ>ԟceg&}+pF( Q<8QA(3U'4P7gv-DmgU Ԣ䒃cGfg:%@%nOs:n @ Iҳ h%Mo]UfoΊ@b+ `hJ} ?ۂ/7g]u) pjІ|[2U P;w~=,oGܹ|]g҇sݥ'N\NplQ~bnt"@,-o)r3,JQ k6o]s*j咃AX'g/xwܻC9n#Kҳ $h`Nh4"Fsɡ ءIo4i{3I @ua< th:4P}A(3Uh:4P}3 ܶݳ*MF)nO.988v{dF}hf4P5IzvA4PI}N' @U>p"X\vrhC4VX ,h.;f3%l x(h`8;GQgh`7gv-DmgU8 ,A4ܞ\rppPȌ )@쒃TH*tSX8h.;9!ߖLgG1vu[{3юc4pΖ0,JH}`hQTL5X8caDmgUX:xY4#33gHR @@YR T  沓CmQrA!@@sezZ:̮ ua< /nG"hh.ATDQgD탛3 ܶݳhhKC#33+MtBƧ>&hhp3kEF3NmE3kH2vu]E5$@@Cl xW_`mP<`T1^!@@㈆7gv-Dmg`- ncGfg֜ j uO}6 Pgj d4ڐo+vZ&@@ezZ:­hGz1=4ԍΖ0,J(^%@@_\3Uv P77g (svϦPhÏQ 4ԁ>4::%@@MS_4Ԩh]} PCFsɡ $=5jh.;fvMU[4ԊΖ0Gap- b|1ʃ( L @&D탛3 ܶݳPhX{ ;=2>hXcI}N'@hXK3 L @5TQhl4\vrhC-I3MU2vu]t % Q\}qK<F&@*_ =Sv@hX p̮(?1ml4.V%ų4 VVR 4V @3`ED3MNe'6JC9 P@OkWG7hΖ0,J(^f'@@/Fqv.*kh͙0 ܶݳ*47TzQ` g$8 ˧>)|e=Jn7e]9|Y @T--e>|শdoLO\沓Cmqg85~]NF/?oOf/9<<'[wUp e4if6>@Eh oG-ct%{s:rčZ[:~uayP/LGp4@^ o??|Χ;ӥbrKԏ(Υ=S$K27ĺ/H'e.}f;$v ops& (?1ml pzW]w]ϙKln쉖WmjaGzQr4=t}p|?|o]s眸@cHs:B_(o|ov4teᚄ'Pg84,"nVLpd_HP6Nm9vEr}i{3&*pfh:[0#L tuATDQghfpC#33T @ZJhFp +M$Y}&@Fsɡ gX54 n4if3A0kjhpA(3U @7gv-DmgU` 4䒃cGfgXe4 +Xu4 (nW` 4$=hh.;9!V C=]LC}"@P:[°<(x 4m|1s{Pḫ(?1ml :\rppPȌ F^%9GD3>:gj @= @Me'6Jc @ezZ:­h uFvuayP/LGP7hjbg( L5nԮ͙]{Q~bnt45*ء @-Js: @mgh 45$I344Nm6>@X3@OkWG7PΖ0,J(^ _ Eb4539kop Om=B`m$;=2>@CXI}N'@XUp MB`$Y}&!@Fsɡ gh64+e4if34A0k@X)A(3U&"@R7gv-DmgUi䒃cGfghN4՗t4+*~0nO'I3Q @$Y}4a3pee'6Jc8 r=]`o&ڡ>XΖ0GaP1hc|1s{1hcpsfb@۶{6]8 %;=2>'#@p{R9 T*I3P! , Fsɡ X}A`@OkWG8؛vr,% Qx44_ Eb44ܜٵX8'MWBx%ų ,nOs:84$=@ T ФFsɡ X}V ЌFsف֮p7P!@4Ζ0GaP@ h|1s{@ hpsfb@۶{6]*$;=2>+Gh"p{R9JEg`l{<3X=~x)tVjHR *pǿ\3>۳ >pS[\u)Szʉ+kh4ڐoK3&h |w};}c~uW-fFsف֮pko&Q X4RttV{s:r/9l t_g`|}-_} .brK+c|1ʃbh e2>|u>3t;q`u<6A@۶{6]Xu4@:?>ύ=M-<3"+k|v̨NܔuWWu?{lpCy|?x\9')>5B8}.{_ w>>U-5Nj PFsɡ 6>L3@OkWG8؛5QT%@ԙΖ0Gap- uf|1ʃ( L5Z$@ԙ͙]{Q~bntucᒃcGfg !I.9$9 ֩@jh.;9!߶ps@]jh.;fvMg~ % Q\}qK<K4@m_ =Sx . epsfb@۶{6]C4@Xءw4@MHҳKDX{I}N'BXc3ШhU5Nm%Sh`4ezZ:­hGz1#@Ζ0,JH} z<(*k KX=7͆AP8'MW JQf @z} N gi +H} PMІ|[\rP} P5@OkWG8؛5QT&'@TM_gKƣ0xмh_ =Sx y  n[,svϦ4+ ncGfgL%9p pFgO}8` Fsɡ h]}85R@OkWG8؛5QTNMT_gKƣ0xI _ =Sx ` F&SܜٵX8'M$hK7X Q*!@FR NE}X6g3!@Fsɡ 8nWΐ P6vu[{3юc, PA0kl|1s~T1^e3aDmgU΀ P`QE]R #@MM}X94мg%@(nWV 4\vrhC-I3J0vu]t$@M% Q\}qK<`e @S<`ϔA_|̮(?1ml+I\r`pPȌ jh-gV 4,`m @g5'@`4?7IzV֜ Խ\v#n~hB^_gKth/qv.*k={3'/m=h%;m=Ph%9Pch^5NO4ܮ>>І|[ig @ezZ:­huCj]_gKtPh֍/qv`T1^@ܜٵX8'MWy4PӒKQ Ԯ> ( |ۮZG8 LJ3@*ruDm΂|`x37e]*7NmIzV P}.,oGWޤܻ M p*3@ g OVUW/s \vrhC4v@S4vu[{3 l t_5 Q*k4 XA3 ܶݳ*AVJrC#33@t@S*gJh>P"@gd4ڐo+m|h4|@OkWG7P8 ,__gKt@Jo|1s{h`7gv-DmgU 2%;=2>p"X>X ,M4ܮ>P X$=TBNe4ڐo+m|`IhFsف֮pko&ڡ>44pR}-aX Q_ EbܜٵX8'MW24䒃cGfgAt"@LjgB^gT k4ڐo+gN o? z6vu[{3IuayP/LGT Mj|1s{T Mjpsfb@۶{6]%;=2>Bhh.p{R9HgV gV k4ڐo+gV i4if3k@A0khhLA(3U`U И7gv-DmgUXE44䒃cGfg֊ %nOs:#@@Hҳ @A @^沓Cm|w3utq":](^~Qoȳ{~R3 ui4if _O=wDZdmw>ܳ}?-S2@.uayP/LGGǒT҆vGs)tѳ7]咽Fj&!@@]_ Ebbzyup_ޯ|cˡ7?|pK}MVѳǎ } 𹱞;ޛn_ߝ>,hK3 ܶݳ*tuc3‰Nx|/\Ougڤ#۟r.w]4 OrC#3ɕgzKNh|o +w/\t1g< =G/<X9ASШh6>/Qc:j|GS'sht4$=4V4'o4ڐo+g U6vuh @:[0Aa:GЌh Q*kЌh͙]{Q~bnt Ք\rppPȌ @ we3cMO^:??<(6+3-EƍJd:Y1_=ܓN׼5?Ilb%+TڡD:[o}KΛ̉Dmr>QWOԪ|U\ůnaP /, =܅jhX[4@+:__4d%+A.:+'jD] >QWB]hGpR\\u鋟I}ZaԤWۣ+4yTkptT ~ъ|>7'8kZ-#8U-w]_55>pdJGp㾷q47g/nΔTp (j8|J Uu%D:+'J#8&@oM'g[qv%QՇ`^U W[n᳥agͿ?@t:_@Ok9wFC:KUB׭ xߤGW]D Z.Y rID] >Q'JũGkA> j+@3~Y4ܞO#v뭷c5o~+ξ\hCK~OQߚ7炾WE\,zT=<?_ ~;_? 3Ug+e|?:,z>x) ^yVѕNfT:^U]h5q|r|Gb07_ :˷և̅7\6()+$ G~URz1'_ Ὃ"KCOAigy<|b&x9s? G '' Nt)#aG?Rޕ\{xB炗Z%??X.xo)??q SGaWKO>Ί/M{.~.}+K|:NL?-#U77DK[ʣ6\q@4I0Թ/_q8\?W?x3zN; ɏ|'Szgr)g9\1O_=:8S%`Sav}Gmӕ˧p /sߺB.>!xYjg nhKWW5ćIWk>t{1g=uP}gju5#״*;*ժxeyZEЇOhBpd'MR=^-)ίAG#_«7b _}]W۠*7诞Pu]~&Bxy19qy|a^o>^ |*,9F紮0|͇fɧq/'itF5Ÿş;nh\9?`J_o 9k/#o95_ /g ʟssßJ^SWK韨G|0Pa΀>}dE`z){rl0sntQ˺/;ʳ-Yu^<>p쿀膋_ZȯߝǨ;O?+OC?.>;S^i@e|#Qᡇe_-/D?  OUK O4*)}q姟},k6_Ozϖ+O֯.WMo#_xX>@GGT>5-0:}+-NυO K{ `{{?̈́X =t|d. rQfw76:A\_}*ol6ݸ ˙u Ouˬ+?- putyb oѿZά~GǟHIxJ]壱Ypc['z&_ duxCcO>RGw Tf|+6JK-+>WS{>tk6_@QPA_TUS?y^*ʧs;jHp߾}]vY:;3=X%o_[t G;_ʢ'/D$&oN''sG)}/ {_.G|>7'qhox]GMraWCH|GМNsի_}]:^a`LxѺ0#]!x"%}yh|9p^)h[|`ZK,۳ 9N)kh)'~/*Gtt߸qc:j( _QpiBW1xc~/*(?[ΰ //%ri{0}KzG?>^7NK=? ]G0?KΉ^yVqfv4GXA kGk&/Η7.^|)}|󇃿IR\qSN^}.ṋ w͹% }i/RmkK[ t\]p*X_?+gk|럂s*E"ˣ=? \g_+@Y}ͅg?>N|'~'#>3,1喞}*~蝯>ݽ5mxy&A"aX& G /{dru>uLϟ\!-,<~g:)7~Y-]c;^,lq~?o*|ۿ4"yVKPj|aiЯEhdl[ݒU_]%iŮ"zֺүd G&楹5]G!|˿Ej _wvm .۰zX9kK^llNqk]-ñ'? [i_g_ ~Չtaz7Fﹸ|3tA[+:7S>וSIfvQpѹ-]g`-~ctr꼣+΍^$j't Ե+#эG(nC8*=+ n|}pk*.ɫGt >)*=me}}'tօ3@mh  we3cU/jxߝV-o9'|Yjy}LGt@}:7#*Eac=v{x t91֝Uj ph8=!@"h[[t( N#@K'Xo}[~zo|ńٙyǪ`<(6`::?4[[G{ /, =܅ Z4@;Q&Gpw.f48U#89TM+FIENDB`asammdf-8.5.1/doc/images/single_files.png000066400000000000000000004246731502633300400203340ustar00rootroot00000000000000PNG  IHDRNOsRGBgAMA a pHYsodIDATx^y%}{^31Ly7z^y1c{ƶѤ/F-=ikN\7MubS??]-26:+!;r_Q$sɞ^c̿pɋ:Kۏ's hF1»#G.A3//|56䋯=˿xSϼ ꭏʫ}3Ͼ+ۧ{?6o:jIbgO8)]< j㼛M-ri_QmJ2&lKVnlo3nv$UU'WBW֧nS2+-B9$%o>ҟxG;y}O|_o~cw>/_yS?jIbG3ekTشU1tcHzk&6=j/}\TM+2 =}m]}[g-_kx[9o;+~ϟ?~ WK۶` ꌬ ;nR*4șڝڲAv'fsuo#CUvI)L=6NW#/U)ɈIN8;IKVn '2{qlxeS_h2W mn'~#So|7]z7|eC|6D2a&6jVPqPHtS%U }.v> [-Sl=֚E=Q7|m^TeЌidB$aMQ 峊Ql,ߐW~i'O_w'n>_ϻZml Q&6ӳ D!bϢipg1WgJ:Й.- ݟhvsZ g[HolYi3gۤ}HtԷd+U6'TvW% :nп[~돯SpOn^w/?tW_+C.sZ&PQlE͆Bb,RgvUQ,ԑMn^KhCxk;ER8V{l\Mk:(uݾCBGKͪh;CTmtzŊAbm]W%\s_R_}jB, CBb,Rk Q4ߑFStmfySg&P@otSXKWq{;uHU鷽T -$|8fkjmFt0߼BbY2쏯kN!\s'O]g+~8ؿB&@ʱHY&]?|-4ⶺ3N( رiUK,dYT'} q8ԘGuD^VL@ws]Wd|͔WöckN1a>/~F< ֈ4,t! ;4`Gl<  ;4`G숙C6Z&Xm!0;m|nzӯЧ#tme':`j;v4,֩ "7q{,G9Uq,ռVO;.7qZn|nT Eߙźig]@d5WF信rUM澃Fhf x>ҲUXmk.Q5,~]f۰kY65ۓޑS܋k4ɡpQ}{|4U1JaG_W{m9j\m2m,4d>UhMӒP!,vU)K F++_nL`:2K؛6 F쿲nЍ-M&on4l#~!d5;2RfwW9H A8Bl{ؒkWk(Dd g‘К rkVlY[-ߍoZjWYe0w ,B@C@OoSs" E.u~ x=쳟JoCyO[) hvQ{;;~?}sccϚGu>zv h]o'?t=A ܰ6NG]{~WwF>яs<{o][JoK@_ʎ2m\Qj%hPqwDw-Sfv&"]G?ѿ׾ /H/_g7ϣ>sGJ?c'?yPnbqڈY1cduE`|v\ТJ0uWz4vR|AYӍ?Q6Yl$s+w^DJ?ygQnCi$[U7)&96Lm֬ JbIBW7#R".;y#y2{&QxOobO#Ϟx=-jEA\Ŋמ賈jICِhbi-ivՉhM2@IhO _',Q&0-c@?C?[nw/__`y&_g?>uO<Ͽ+IK/9r_җ\z78xǥmY.&4U{hDz! daaaaaaaaaaaaaaaaQ,BHfRGUEz!,:YXXXXXXXXXXXXXXXXa=4ddaaaaaaaaaaaaaaaaY`yC@coJ&JpFz!&@,$/Tg+Ivv$7WT \4)Z`q=s-ب:K&DmSfq! @s=Gy3 6v #Ln$-ouV|m F$e$"ߐI_uV|m "e$"# `wJf@Y,- 7@؝jf@,&B.L H~oP@؅f}X h̹˛! `9`y30B3>,off{[nPzߋm컐e$@0 8_Xo{9r_}~v LN܃JOY }wll KɊmmnrOpz>79 8-ow9`L\ ',>_mmn`h=š&op˹W_` YXXXXXX&S͒T%)г$eI ,IEY_OH*_%|o+(~C_Ag xZ}>v;̿^}>kg^λHszXʇ,,,,,,,c_]t"!o^{m_[1E 5WWPƞ{6m[ @ ungp돿,jN5 @XXXX_#W" ˌe߅?O˾ %SW{n]r%H<ka%`/G9] [gK6#ay'~Љp◶ç.%#.'/~&Z`aaaY~\,,,3~<_]NXO]nŞ[|e0b\rɼ1RZ=A>\o@'?T4TƟu7vs?{kzY3%rz2,EșWO\$o7%y3'ݪ~}כ&Z`aaaY~\,,,3}K3}KzYYW#~Twka ^y>v>+&r M 6-7q _zh1_8l׀Q,~Ʊ]nWE^~^~o|ї_{O?xW^{WGO>o}w~^Wy}) ڗKpG2o꥟9]K}fⅎαj$YXXf,.3if/q ]_P,uj1r^R{n]r%_#U%t]^V]b9nq @f _~wVɷLֹMIn+ k x\;-~r;~X'O^pIz8m"/rvϽ{ǟzջN>z_O}z?COtOpXXXF]y2~إ3wm̥[ zs,BReb˾ EG]Ba&0ˬU*'@/+X> '*`sv,`BNw'Q5`$\C|{suN[|EY }wMxnVmksI/_ '׻,jk/UUy#ȦPUk6錯צ>*F}S.:x柾/<ׁ:qℎAKZr_]n㢇"/r7=yЃOݧn޳_ʣ}E?b'n~߹Ͼx聧韾ne4;|Yz6%K}I|7Hzm'k+Ƌ}:E?[{?Fakם{rSxq˓JfK^~eRG<.nlldv6nwYl%@ox]bcL3]d>S/ \նF lG.-d݉MtgB-V5]1)lʆݝy^hnr?~ ._%s-=gK6~;a{gz{um|ڣGnk裇x؝]Guq hGmlog7hic6ح7\Pץyeۯsf,o}5Yso[ܦ+wቷ,Tdaa.9f/.nu`Q-"Mf uU֖{n O\jX~PK.y饗Jr u766|JI2:6,% >KGg:L~y$ 8○X^ue]2е 7:IZH2CZ8=ۉ̎zG/gqIYO?X.ȋܿCW_w˵x'?~s#zn>[M]vo?  hco>u^^i_^j7ec$k!=cgosN~x=ݗnm)iγOW_ztVow|4w_կ[̎nl2KrU{n?ӝ?*G%+??uţwd[2ۅS?%yL96%ٷc %\O:R;Krdvu,% z0"#Ж6Mv /<N3VX>MV e R׽ d҂\HmTs\zu/oS7>3)]ncȋǯ_>o?]nw//^O>?x?_tˮ-f^;gsO6ml_xs{3dm݊Fqmi9R/ ?somjnwג,,,3Nٿor ]xueWpDo5KrN+=K?D'mSM/MmmO8dFdC/];'~pMGItq`RGȋܯ^qӿ_8|o:᛾|xϝ?x_8߿w/\s~_-fyƿ;}ͧ7yLO4~B=pcon3CfoэIzKǮU[uŋ~.2\Reb BʄfwIݐK}]PWlmmQ{ni?-fQfdllE &̶l Mr w[>toPv%<~igfK<.)S\uB }EY(}x3_u/FoطB~٬zGvM .09r\BnAhukeՔ Ǖp:;Cnx[J>~Ʊ]Nڽ}7o^r~K>?q{?s~XXXF4{ӷ8o?>syر<66Doڀ矶_sVQr#YlgeK^]0z gHReƲPqabN[Wlmm=,+X+8.}s6ο2M*py^eiHPsY_ǯ[??'ǯk:\r%O=_y1͖T9yK [ׯXyN@mmnQ3ɻƇ O\{=טEx#.꾟u ,,,Y~i ~GcOo~ +?ۿ76e|y󾧷<J4b~~[zc#Z4?7_ߎJRebf/.ozꪜb-257wwsLH嘕K)mFi<.hw+. @=v@K.駟+uʣ>k,>,&{A}.s ˿:tk?t]W$ͭ?/mȽ&t ,,,cZ~dž%q_r즿m?ow# UHhvG8/ڟ~6$YXXf,.Oyٿq]b=uUN^Wfi׆L?_ŗCb[&Saْ/Lb3gθZ%/h'mmng}V3ɻ}+,UmE²曷?W٫n%YXXf,&PٿqU9[[[+I+*}6JOZ+]|EY 2}a9gy)N'r~+,Z[`aaaY~1[7?BE+o" %X]>zM\dnmm ^w៱j\,,,5|{KRQ@ϒT%)г$b PWP B'|a͍w\z̯5,,,,Z#W" n^lϻƪ',!h#34 U!²- 8 whB?2'(}_[CKOY  xGLlk0 =s/r`@IةK h3"Ə4 @?Btmmn7xGLŽx6w\zl090~$PG>xmmn섞90~$Puxsccmmn7pk090~$xZnx3"Ə4 @o>+K+0ENf'0*&=b|n$PfmmnEރ'>O>ɹgԎY.TWv f}fĐφOpʻaͱ!'-=Ag1O}c75YICV +3 0bZ(5ܽߤGnXs,r@:;t0mܷ~CKOY c#@&^/yk>OWv v`z>ЃsAF 9B5%U kE>υ;Q:t`cv ~΁Cs]_ѓ SNYY7_t7_Ѯ?ql5C+bMbۗ*bfcD}rVk0J@ w7r}zFf7_}&Vzu r䡥'gMwo{̯h׽occm2]=jmfO׽Ϧ7i4}rVk0J@ w7"h8Å%˯"sLۦ77!T[gbv%{.K#/GW]ޅil'Bv29;~Q)BKm! zCKOƙ/}w$|/mmns߶kvߗ%鹜bRّbm LWGzp.(!Ghpʻaͱ!/ aj4>ӄ~|VmjQ)+)]Ťm9SI϶MЄtE\z 5Cݸy-*VHZz0\c#?o&^z6.Ư(\}+Ne%嶖ͨbvF'&g#=8`Đ#ZQj{IXݰX @(Li5JX._F I#f~/+"^qWNm悍rlT)-^5ز%M; u 3Wǚc>*m[<{=@ gyIK~e5̓oR6 i5.`bz澽>_mgmGo3VZaSϞ+0MNʛqQ^+\#uMu^Q*TOKmڗP+d%;;69IS W* ̦oHq}$M<* -=AggϬmmnx09=s9f\P 0vq (.Jz.ROWVCH%cvMP3U+BAWUFmr\R#]iT-u|vڭ%;'i~iomtMwڭE;#ԁ%w.5"\nW_ 4?79.')I+Q)4'ž-kʷ]Kש~aC&c D :זvN;.(G,D' )"r;YlQ{iy{q ,- w vhFqS}G 6Jr^(7ϴ}mn =.Yr#SP)][Kc!?iLhPzbN;zoڱf,G S/;kMzݰGͱ!q`$-=AgtIZܷ&LMB[468>ɈiZo{w5W$KC;tz2s?^~ں0ۻ>3MKIΏX2J83/lW#]J<% (}ls$MQݸvuUNk{O;w]K 7l~ݘ^Qn7Vt]]1Ͷ+5&=bݰKͱ!&~Ր3%$yh 8@}{:m.whk\M0Ҹ $#w+Q^{sqԸh6^|kM|/X^ZIG'hrl5ӕhK?+ix{fۻ/w˔j֒ԗtleFi{4効N 4C;vTNQ|vVy踥GvVꌩ]}!^o# jː 3a  [M$.(nx% {w5t.mRț߆eš$v| Җk(d?NTAK(uVo=ߗ)ahrҥK=e$Mٺ~Um+"낈zQXײ UBmsI_Ѯls#)׵$VZtr|G"Y5&=bݰKͱ!'-=A k@},箻j=sV0U޲lo`@2bo%Dt7%|ZGZ\v g bMnTqFi[Jڤzu%;n5eƅU{Q-di/X0uNhGu]C"(znOLF+UBRk tRfY[2:NWՋ33K6m~.Zi5Xv*lWJYOңh~zscMM3~`ꄍ:7d( *^o# jE4?yh 8ԹWک\9NK=Vmks|D2L#z澽^҈uDz08ZE'F 5&=bwÚcC& OZz0/~~憓>5;Ͻ]pG1izΞ=S@o~(Vn`=0bJo{Z.֬g#=8҈)a`4OT^w+-i5{5&=bwÚcC& OZz0c/ O?{{ n8u{=«ǶLz좋q2 > fSX{Z0}/rS Lid"Vk0J@ w7?9rayLGE@QԡCKOƑg¯xܫGj^䫯nۜC#y'[1ї}S AR6QMEnJusAF 9B5%U kEƟ[XY2wu~P=:q@?^u7v֭_~:o;cK&xk|XWNr=_Mbۗ*bI)c뻭f-oNHD'KhV["Xj*ڵd.7%CFgOo5鶌mƼKÛ7+j3Epj=`Đ#ZQj{IXݰXmA:D @ԑ S~7~kgzitv卛z7zWlksyDsh|gu[6]Qn#mL">ꋹmfOۛ6r hk6lP ҦO%蠥oIuN^Ԕۤm;XdZm!i.g#=8`Đ#ZQj{ItR:SͱHĽdS_qHCKOƑv/p꼫?JЧǯ9/xWeն6>#ך*mVJfG٧.fܬvJڒ^huW,5%R\"5 fm{GW"'1 ByЯ@/(0{W:_}O{Ͼ?~͉_}CVmksg/L}Y,\Ίrf،.fERkq#vJ}75EOCmTN^Дd&ҶO54.Jm yckz9rP鍊nroF{m{W_y啗_~^z_x-m dO ]SGb~4UMYVRy4inUj򢵮=_V2J{3lLCj F 1+En# @?O>_ε `PoYW@!LM@Ͻ)y\2v| X !h^&z#s"kP$y|U@Nn6&̈!ChԘĕ"5ݎ>v"2>pyp[+UVYe SL~Pø~-l\~jtM yh 8ҎoUwȟc~㶵 8z0ۼKO@/9Pׅ"ɦ]W}'7~fĐ!ZQjLJ[a׫/|hyKo.}6$ss-p .1ɑ|_!SL~PÐY7tLwi !LM@姎<ai*-^{͛ѿ±u|XdL෱dth̘OGzpr1gF B5%$&/~?c?&/u_~N-Qva߿m'^1d]%%\Sd96"[=)ߖU}X'N@%oSdOJ4{vi 6~]૤SD<"*]PM>Syoy%LQ՞nJu6`ɩ#!-=AGq @ߺWa> ?}̶67yJ]s/)+z>ЃՄ1dS(5&qȭP]e]hyKo˷䆤?f]gf$\K2D ?~ ._%sc2ED %= ׻On~(a)mETSMLg2 4 o˵Ԗmi&L yh 8Ҏ?~韹$=N]gO&Oi˹}We1S3lLCj F 1+En!}W{:->ϯ(GMbV&c":!(ԆoBE'i?&Ѕm)/ukb.uOk2 O yh 8Ҏ")wv97WB_3^}fcɈgNdԵ"W}I'C]LQռ~|F/Nٛcw>C2J$0)OV?B7o{̯X:G{]%MF^,`dOJ4{D;d䗿ݼL:$%_F$Œojj5 `]SGBZz0Kރ̴d;x9tI좗!1$̪qXPb\z> 1!5RIGn6&)l&,ϓΊRg4KJ*hۼOViY?U6a[Ga6U;0ҺNApĵ%|Y5!P8iTbmSk7&?\<<aiwom𹍰{I ƨ;h>BmL KlLYaY%14)ɼmCtŒb}m2MmHf3NR˧)eh+0ʣ} F=Jx=05OVη>}[~9Vr2kX&+l޸.Z0^]Qh%B:?2)SEuO~蘚Bvwպ<aiwD믿27,61RvwMd\UL%G- /=ۈؖklLYX[Qϙ%[ʹ8đ7GJ6nBVs+)" JdUi#+&0?SVsNA(E4EDFJ\zLb>[( GtE= ]SGBZz0;?EV%o.Y*vC"DZ%lɯR3ݾWKBM[m50_E6FBu;!mYcR&?<hG:ؔl{,jm|0f%#8B0FLKfcqzֶsqBȭ_) EQ_vVtn+iuLݗ\QIwފ2ՊIr)(NYM>*%R&g tW Znrs{gt肍 4M(,6{#<aiw\?c3bt9jyȄ<&Lb>8ꋹmfOؔ6%BNH>ٖLHߘg9hl#i[]lUM43Mҥg#j#hQTn6&G /|u4+Y-͔uZ 5y=%e%Qfi;TVUGgt"+S&0\vg|L> XyS3DnW_}wqr[-&p Z!+e)fw)jK&yfvd?Ux[+n A6G^3^ HMF1٘s4bmLW%(@&%R䅬dOwURIv㙒ۛ~F4۲38֝1zG1l^OVxw7n>3O@F&0Q$=t:qn^K;b!Y*6nYQZ܈l+RҾHrTQW |w;fEMS!oLv{KGzA6e1-٘s2b&P4^V,rL]=dzOlz@Ů,Sg*/d<᲋m&0\(6ƣ>FzZʶx]I'r+L+ #G|+_wEL2EDf]z<aQ-qKA.=C TXgfkb)_naU8IcR&ϗybmSY^1mjV:p-[l#mKz>Ѓ ?3bL"`vPcW wuM7$osɡ'䡥'H>}-'ͅ&OiY6-L<იqO[&DHŊ^LWkH¶Xۈljm8k?]hKg[% Ś}5YfGMR)_Eiɋֺ|Y({PGzpr1gF B5%$1 q{s?)wv9GX휲-I^w1&=sƄ1d`RVH5q7q- f)wv9wy0KT@/dK)cHi?3lLCj F 1+En^#-=A yڹ+=/:S,<m,O]*&"33lLCj F 1+En^#-=Ag>ӧOy睾cXu]>^K Fg#=8٘3# PcW @FZz0N9}wc:s̩SOԷa ~Z Fg#=8٘3# PcW @FZz0N9}7/} @T/}'7~fĐ!ZQjLJ[F XOOZz0Ƕo:QW"'s(*g6F -~VLbn&A$OO. Cz&Ag`|z>^1v; 0J@I\)r+$ L»a ]Yϧ'QO!M؅z>^1v; 0J@I\)r+$ L»a ]Yϧ'QO!Lz{s6b~jc!0'6F ]PcW @2.xl!Hd)Eq@ hn*i.ܬjmo3"78ƈ! ޑVQjLJ[ЗGo}쫯g0.xl!Hd)Eq@P:T߁3{bcĐH+(5&qȭp :+o,&w #<̢~>0?z0u:;g#=8ƈ! ޑVQjLJ[ПƓ8kot~8k~&w #<̢~>0?z0uM0#.xGZF 1+Enc@7_~퍗^{׿#}w_u 12c^mb7Io3NQkkD$d08ƼʬV|.%E| `~raK ̐ 0%vpL\Gzqv[:b,׈J)RUIc*_WؤdXu /}g3,#t~6U޺H{Crgfţ? I'r+C7r?!|>3_lqo-}EG:.զۛսWa1o2kM7̢~>0?z0b+8JG/>G{' `z>Ћ^E[-1<M͞'Y%e{٧$/tTJ$yy7%vGmJ6tUor%'%dsЊ/{:[%QjK֟Vٞ*` kOO_w&/@<7%L/.-'ݮa*;EX}ln^1o2K2" 8CϹ_q&>zLRW0z=s<ݙǼQ=E#&r3"g|/'ɼJce zSPCf\WD+U8]T(:>tMb>[8m?w3/Eۏvl3f"ŧ&M8&W3![Ozt>\AcT6 P4p)0=-qϛCtIfQ?\D=Agыx$v̓^|pOlz̓cxnܿ. -)Lp9!e,I/{9#6Jg%Zg~*|"1KryY | =yU<_O{B6!)RlVsCSKr*u]6sF#['+|N}6>;' ~m2 f` c6tٷM$OO. 3oքwu RW0z=s%Ǽ3myP O]KJVKrhS%+*Lfޯ-kmn/,:_*)9=Cgg^G$B1%9J*I|"Q5'on?=_ͯ>C/w?7hfS:Z[T=Wm"܄шa,[]{/3aӻki?tyQd cvWP=(U\sI%E| `~raOpL7b@/<χ }lcR"~&=u*EKm^OhR#ɔ;.)#zfȆyBiTS7Dnc@717 o6_vc ?[K[2in)pt%]&06>~K{vmb4;A ÅAMxy򮅼Ƽݡ[Uh~.I$OO. XgcBk3^yKP{bGLJ6UҰI2ͣgZ@BVwURIvLL,]5zGl>QiuRi2s]PdMb>[Я^}#,/f~pWҷY 3鴷|fgvC3g'j{˷ @<؏nawp6OlJzͦ;|lk١eMeŗgVwh'lzT\tIfQ?\D=Ag盙@K{-mdsӥmJr٬i'S?\jSܢE6w#ANkK^}*>TA*yj\ܵg Tt5b*Eu$U$[զUǤucDK5ۢ6'=S#*j]Su-9~=s腨} [:bm3TJmV]kTIB⇺e;_,Y5I^09q/|ҼxvˬOLb>[aAhz<,z^x츙$̴LH"rt=[iD.vps cf+;Jw86ܼ6W(]M os0\n2螇zKO$OO. XzS;U mm0/i&Mf$ӑMa~3wZWp\mrTvX2MxIk6uGtKXU=THvf6N2ISMA7 V5H}1 %$э7(/=nG79ﵿ/s6.xl!Hd)Eq@/AsQ 1FƎ0]-nMxp#ҧB^*ViUq S(MCcMe-`a 3aixoQ*:rL:ks9HUIvs4g;R=s'6F ]PcW o馇z^t My3r džtIfQ?\D=AgыQ?9{)@fk]%e%% *;)OoCQ6otkBW@w5ʛt~FªW-5C:v6VRFuR I*iL?𯕴9^=s'6F ]PcW Porw]0C.,S󓋨',(|s/Atu.'^5+l9BW/ViEq ݚm_V-]>l}ʡ_m󠴶I6%:IFX5uX̆ͭx< Ng]W[TCu^1ݤ %mWNj#.xGZF 1+Eni]x<6K2" 8tKBte|^G&lnB]f{+1Tbʝ.q\BiK4Yf2tk"64vam6$zFHXUTْŕv65&eQ'uUѫD|:"aO.ݔJ'6F ]PcW @2.xl!Hd)Eq @ iY"]Wѳ7|"}"1TnJNgD"K֦mC.W2UMn3ZvXU#̃B( k='/Wg 8aq~%e];I)H} =1bw`RVH݅wcA$OO. pzNqM8o{KMz BCa BqIvZ]Rmt@So+%Jfn ۮWB\Үd&uR[ s6tf^ H";(}kΨ10TKi $6_x{bcĐH+(5&qȭph2| `~q @7h\Q=#nJ-"]>e#iO B!!;-7;q 1*hڦtW6LvC7f$P2=|^Ҧۦ/d/L]冭zzIڷԑrEL|#3l3#PcW @Io믿ꫯ+/K// [i<a>_yF7!\8tXe*}/r21bnc&5} 5pn0[ 0,2o@a .`z>Ѓ #O5%$E.4u87C-{hI_.q}zi^RW0z=sFCPcW @"OM:!L ={;ye}'7.F 9k0J@I\)r+$ L\h>5pn0[ 0,..!o@6.v6d%mOڟ]{eFWsX*zV f}s;*g\mk*["*ܴc3(q=/նgdi{SGzprbĐiԘĕ"BȅS1Fxr-.}W{:->ϏG/>GČ4Ƕܯ& mma^E8t[ܷ}*cZM$ރCL+/iFD5rݗGOI_>-u‡K?WJ%p*ZZY!kWϔͪɼU؛OhlotRP:M [aQOV8 4~P91[ 0,2o@ϲ׾/Q\҇L+%EwDI*YQxM V\M6ɫo .Y*6w$<߂P'*I^5nFl@/I>ɇWn62\шϯv|zKIBU'_ Œ_YK j\h%{i[hM' _mt@]ϲ*gIVW~1dRVZv6lSR>Rߙ2%upԫLrtɴhJz {G6Vr(s&g^E2~uطOKrU[|r̥][>x[(}m0n2t{пjul^˥zK6Mc>JQMEUF^u;IZЫpMᨌʴʺֳS[': Q+ ~#J1&7.=brcf%uvjk?Ri:f7T^dC'\nIٕelzT_|7gΊ;ozQjh ֞A]N\zLb>[Xm'U3rI_a}R_R{;LtR%I;aUՊɆ7yu;uMv[%USf[j}d^%ѫ^HsͿ%O@霥ytmKRԩoEgL=:o~ES*S%m:N =tW z{9_3]y*)Ӿn7Ӑԗl5{契 fJ絽'}w-tfoːijov*3U/DR^3^ 泜ldO\?(ӎ\R} U9=jJ䗕Dj-kEj2MJtm:fS ͧ(IhZtzF֟AxեL$$C?&M(yǩͲn4wDӘORf,"i'|SQ-Hn'iS6z)Q_YzvjtDd;j%9Y|dQ ͧ eqA_iԉ]3&{:D D$n1ꫯ;nWnkڸJ7z0ayIjrM)URod? ybV|Vi_Dmm~MZ^9U%C͔TnҾ꣥6tf^ J^{f) Z0e5}$U[4;Tf z> 3҇\n62\шEE; P7AƲ5y=%e)5}ޘfbN!ׇ7J " 4j3OV^Kn%^:X7e^eȴy5d;j晪^)Oډuts Bu9&xѾ^Նi 7沏аNλ 1[ 0,yr;J-v~j+c_zK-^C~3K6B)avٰuNlov4k:S-Ow%trbݨpGAuM٠,'Et{(ϩ-s\PMb>[(ih:3HWIAm0Y% [ R-M?&b,ɪ*mv=PT-3!TW6+M ]Ԃ)[,I0$bB١ڟox6T_I.4Z#Y/sޤ9\,f뮴1[ 0,yrH# 袽 h3^ jjiL+JmfW}kTIdd1HW2};Fm|Fٜ)GIB8k?VdMb>[idƘg3%sYJ ˆ-[t e{K[LYәjmA~p+3u]F5xD;zr4 WkYcUh\څ>\h>>j ;`'@{/}ʱsAxziRژ-<9<]kBG$|]*.`k,c%z>Ѓ #O5%$7T ͧ&br!1L K@z>Ѓ #O5%$2/:5e |j"&h`>@zwu RW}'7.F 9k0J@I\)r+$ L\h>5png40yrd7{I1_3ld1x(5&qȭ40-rDLù$n1a*c5\|Ԥ>S@{DGzprbĐiԘĕ"BȅS1FxÒ'}ơO,@={֧* nl|w7K~P+E=hf'wv@Nn62\r<`RVH|j"&a`X0 :7}'@/>y2\:KV!C:9ХgsMa&p1b4_QjLJ[R7{<9L$mN7 @Ǡ @wş]u| W(z-smʶXmn)|Km$[6?#ŒWetZ61{4z>^v #Q?fr+ȅS1FxÒ'OG @|#>۲rLsDLC5 誊'T)M-mó.ښM["턴)mɔِ<߈J۪'*͞hI1WIVE5f#ň!| F 1+Eni ͧ&br΍&q%O#]v7}\4hռX)ӆf[f%eڌRkqoe]j%5V[FX:IvG?Vֹۢ=]z9f #O5%$E.4u87C-<9btmuM] -Q7Ŭ(Zj-nD6NVaўbM>+kF;Q$ud(_\SIn62\r<`RVH|j"&a`X@ړX.m;ǶL6 y&~Rbm9Cm WEs۝)ݓq"B9!mvLIfMz9f #O5%$E.4u87C-<9bqSχ8aӦ.XńUuYg̦榮et͎ͺ#"lmrBԝQ`!̫Q$նx 3ld1x(5&qȭ40-rDLù$n1Ɂ"@.ma9ܖveg#=8p1b4_QjLJ[!h`ZB󩉘\s#ґG]{@EW#RTMREuNXm[QeY?p(*gucDK5ۢ6'=S#*j]Su-|j'6g9kpn)1[ 0,yr7m*WEL෱du60BQrF+vV5J)E/d'M")VqjOkꧨ<5ٛOIpBV+W}r0}OV8;p`ژ8PKp#>.T ɦ48p@FWӺnҦ돤|ڔi*nKZ P;($\z3i6G>{iޜ?/5}QjHO>>KI'r+K$|i#/>p#~hmF#tbʝV,ЭImsVٗF;JkdS2dUSlȿYG$%W%mk%gLk7BI ͧVN9ZkpnU i .2h7)s%D&q%Oc@_ysHtZ>}Y0Dڼyb7K{ŷ%y {5M,uta߮5&g#$;wDעldI[a k]LQ^44KDWle-A[rӖ꤮2z՗OG$ɥRI ͧV*:1q5<'XSs;5ެntV.xk}=gA>}/r) 6Wm[84fm)xVzM^OIYZJM+S*=)>{ip.s=J9Rf >d4ׄnJx 8Ov*Xr3KJ"[kӶ!+&Z;P`Aiz҆굈3Lyq2zUҮρHtwr&w|ù>M:H])2 S5'q%O %iGca^QgsM!!Wa.ԑ"iM:-R}UCõeոWѪͧy9,I&'sY:9DՁɛ|"QKj9t59HWIAm(А|yN[+m%YiuI %bZj"I z/ѹz%T̅.JΎiR7+1jSKgB$2מ#iJ<(€,@.4Zu)9P5t8CЧ8%"|Tn%>-<9ymt]ݾչM&ȅwAliS*kKWvmͦ- vBڔɶd˿4rm#^8 LSqUO U.(S儬@f#ň!| F 1+Enc#v( VY 0<|j"&a`X7=}G5G>h S,V߆٧.fI6Z[`Wt;ZmɌlP,]6j9MzF;ʝ3چhO@E5f#ň!| F 1+En{#~:p/! L.os ͧ&br΍&q%O##]vo@방+"b3WKō)*;h tn9MzF;tȉmHZ3տȹ0ld1x(5&qȭp~*|j"&a`X0o@qלU}mTS֖I¦!O]T3͵t1ǔq=1{(thn6{ͪnܑzwVf_r d{eCw 3տȹ0ld1x(5&qȭ40-rDLù$n1ahKы9~Y>]}z>Y 6t9bx/&5$*5?mDe6667u- mvU= v ;M?BWIG#7 _Gj2=sFCPcW @"OM:!L K 6lֆ !]&ڪþsR-t {KGzprbĐiԘĕ"BȅS1FxÒ'Bun_+@=zT<`{OT̴Dz06¾M :=sFCPcW @"OM:!L Ka]~KF[ @in@Nn62\r<`RV,M!OS @_y6_qA v ňvŏ 40-rDLù$n1a28~t/)+z9f #O5%$E.4u87C-<9L"}Q_Xf#ň!| F 1+Eni ͧ&br΍&q%O|;{OU"~r ~Cy?\fԅFp_wjV{F~?Xf#ň!| F 1+Eni ͧ&br΍&q%OS 4,@V} z uc[[&6wAg4p-_W"LrbĐiԘĕ"BȅS1FxÒ'gX>}yVe ztV!k Cs~T3տȹ0ld1x(5&qȭ40-rDLù$n1ahgm8ϒGRn߁QX|%[lFq4qm$۔VSlsvHn'm"Kڑt{hs-v=v^-P3տȹ0ld1x(5&qȭ40-rDLù$n1ah{Ϣ#l6AM:*UliS*kKlfSB;!mJd[2hpR7ǣi*vH4;M5=E=sFCPcW Gྍ}kr\0/+d刼Npغm;爼N;L K=a hv!+exjSppvJڒ^h.5b&=U@Xs V/t}/r)(jTף'7tk|5UMgIix~KR2:Vz2ʆiU~-~Ie%嶖ͨbVh(7"nT+ݷlFӪOG&=U$u* t_\Sؿ?SЦVg\&GV6vLD.mJ6]l(Œk|CEs2sNevL$E.4'WAtl3ڜCK6pn &q%O@!U}zK;eҒ^t3u.U*֙Zcʸ=[-[f6dS҅(KI:f_r =s_k dʧldhMKJ0%bIg6UR[_YI4C"|+ӧbɵiSœ?*%;&m G>/7lIV$l'U:dɅSբ( ׊Mzc=XEXù]p*OsÒ'IŽ=+bp/jNB)g()+f{1/XC_FTfSkcsSײfwJkYT^hװ3*#yt4bjkQj2 =s腘 \ͿldRR5.rImpi?=KV*M=> -)̰&Ni7ںX}-xw©v9"Q'=DI|"}:%C!"d.ju~smBjEo9RIs t8 aAuD$n1a\es =Bs:zѪKw23^umRe(7.=bZm,-QפP.E{[Ґ]%ͶfaZ[aYUͳ1}L%̒Ӽ#g%)לGGMb>[yJ J1` ͧ5WWo9s t8 aAɁÒ')t=*}I St@ϼ.ںhM=oS7i@ϯ}IL+1{A7ezbIE ӈ M =tl4y=%es*5XJ13[}}xt_ݣ$f0iOV8 {\h>UO.Zµ)-RQ|:i,\¦Qzdq`'{y]l,X|q!v@Gz)ZO'p#d*dXRvDQSFd`uTERtfg1S11*b<7ԹNK(u(O̾` '66#Bz&~颗ouS9m;~-.8H\IbaɓEu]+3H1_3^JrJG̔tn/(f\[d{*,fth3U/eX}]xo϶:'-ev&m 6Ä|B ($&LHK$O_cBQQI_UB 9Qp9ւCX@shI&q%O!K vf#ň!| F 1+En# @$OM:!L K&J?B`z>Ѓ #O5%$E.4u87C-<9L }c軮>/YgϞ Cj^ 졭`Wf^M a.N}'7.F 9k0J@I\)r+$ L\h>5pn0[ 0,yr{g~^u\->uo @V} zŶ!c[[&0:#ΟZCfDEHgsMa&p1b4_QjLJ[!h`ZB󩉘\s#5pn0[ 0,yrOp<ۛħvJVzwq G|VeH ftгl~rǶhk6lP ҦO%s#9~[Ka$Gnm$K*淴e{NGzprbĐiԘĕ"BȅS1FxÒ')ï?򮫏o~DȹGe?_=߀NC6ݙ62,V-V6NV[ *gQR-<(tM\%K(gsMa&p1b4_QjLJ[R7{<9.}3.;֓~r_v]*Nˆf،.fEQRkq#vJJFڜͿVf.WIH~帟Kz>^v #Q?fr+\c`&yr]#Q vOm$ha2, @f==s/r #$Fk(5&qȭ4?yr]|=}?]uw?rrbQO.u3rbbf:g|62ZӅ6; ? &m E>&m?BtJDWs̎a[ {FNjf#ň!GhԘĕ"B`at:O_wwNO~S_@e5Ej*X`z>^'7.F 9B5%$'Oc#98x[b+@=zT<`{3@^Ts_eޘ|yoxld1`RVH<91-iYx@"&X2Tz^'7.F 9B5%$'O@O};J!5x[HF+gufP^2@(4|>qo3w̹d U I#h_~ZJ̓Qm @' k,>{OU"^+ vѧ S`}') -wtm;ـ#GGJ~~/FUr~~ [sugEn!t]SrGL7bVIn) 5$yKMV;KfU1Ѫe%JOKme`@OVH<9a>lڼc[[&=-o+E}ˀm-ptK.ɝz^:93uw~}o㒦vu{s-vȉ輢f#:ov g@}%]U,*ҥ`̖*)IAo6Y~d'M$F+t 7vQ'ݔܱ!zOVH<9;"oekؼAw{[j4Ŋn_l%oM[m567%j 턴Mdd1 xz~;;`2ñčkͪn-{T՛yV.aOK>qUXf{zxMEOf">RYTWԺgx[[r#fϮ9P<ޒ  R5LwlYks+|PWi-]R%قvnr&0ZsGzfk909OVH<9\Z|#Yݖ @_{ą7H[mlue6{?V9^[F]5MTҦOשׁI]ْ DRJ^7,rqvLҦQE[)`ڒdUEUfozYx֚d&ͩ&-iӦO%Mv(xM z>^eUtRf#=͉4g]HOן CQ&diGR+Ȕ]2#0!VbKϮu~*vL$'O=}G5ڿꩴ}\NX)3y4,)fZ{+nT-=z^.OMQY*MzCULZfB %C\a{量оJ7j.l,ShX-iQvt3"$9%9 W۱-ؤCysR6SľB[kjJe}f67B6 sͨnpawy§NFtڴ;Pl'*Yrv Sf.|޶$̬VS,aF⭡׾(4k vuky#mnow竩톬۽+*?FCncRVH<9b0wXH7_bs9bx/&n5$*962ZO ߋy.m-Qt&0Q"@*Ff#n'ut}?~ϘF*]h{@#К"m?N+F5tkFZUEi"i5kfwv} Nn62\rVk0J@I\)r+$ OF;Ϟ=L z\@PwpN+K b˞JkF֣)} Nn62\rVk0J@I\)r+$ OF~n^ӧNb=zs)+LFR%Гvҧ5Y꣸FCj F 1+Enɓ(;}vQ_}sxTʘoc~P9~ֈ.'7.F 9B5%$'Oc @K|JvBNjf#ň!GhԘĕ"B`aɟ8s4xld1`RVH<9?B#^'7.F 9B5%$'O`Y=s/r #PcW @'FCj F 1+EnɓhXVNjf#ň!GhԘĕ"B`Ɂ4,gEnaǶo8mܶڋ-vi5st͚5!I?^iYԟ]Q̌ h @'Y9%7xLq_ڄzBfŒlEa8BoJOe*vI5I)jQ6Wk0tdOf{*bffGI'r+$ O|㜋܀45x[duf#v!U`&U@$-yX2PUT_YfKH&)xEgj䤵Q2X G粜Qk @'I^|Wd! `z>^i[_+iFKz]Q&'ۗ#|W#o+l-> -)@r+FdDM"` r^?~(ݜrfAGI'r+$ O&(|s/AF=s/rpqNʲiՒ 1mj3(ih.h:\gIdOtl2lYkstЖ\Ye.ʌTL"` t|QR'=̢`&1ȭ4?yrXW.zkqyˏ>~05'.~Ʊx[ĶG+Bn62\ш"!gbɨF-jnkzJʊn3Rjr$33wRBU9bQj @')t}( @&`ZOq,^bZ>ldBM4(4qP-e{W(\WIU$U*2jܥ(i\IVBNG8%)0LɘyA$'OS @@z^G4_4O?X-3$*&7trIkkBTI!tŮ,#nX(-L"`"IOM(ai?Qָ>`&1ȭ4?yrs:s'64߀DO?X Nn62\rԘĕ"B`ah @ZW8>1vq,^'7.F 9B5%$'O . 4?cYc"78p1bZ(5&qȭ4?yr71 >>}aLHNjf#ň!GhԘĕ"B`a"|zy@cz>^'7.F 9B5%$'O@Dzo"~|c"78p1bZ(5&qȭ4?yrJ?BDG~01?X Nn62\rVk0J@I\)r+$ OG/>?M} Nn62\rVk0J@I\)r+$ O  `Dz9CQI(w3'O#F=s/r #$Fk(5&qȭ4?yry }QNjf#ň!GhԘĕ"B`ah FgEnprbĐ#ZQjLJ[!h0~7`Y=s/r #PcW @'~3"78p1bZ(5&qȭ4?yr xld1`RVH<9e} Nn62\rVk0J@I\)r+$ O@z>^⬷7rJG~_x1WV,ٟ4ʆlR29]0SG$|hCu]u >/QrA-$'O@{g>SĿ:t_>ɯ~B}-F¢ h1mR&WKJfSE2}MR>S6К:Zed-M!~Mjj\IVdf[ES-f{y&n @'9'z꼫v)I[OC'λ'@XVԔ W4bR)e`iZ)BlY. I2oPdLhscIP 6fU=/(i:Rn􀩙|"B`aG[!h0~0y'~Or8|?45x[YrF,*5]2IHVmM^OIYZ;)h&0ZQ23z!e*/=`j&1ȭ4?yr];y'8QKڃ'ϼN& `z>^d#cldS$jDwI#:uTERxL1b[ލ2jK(Ov*渠 |"B`at_>|Bg<#&CGudJ ֨gEn1&͒ W:bxYdjeC*T(Y LU᲋L"`}ce?Q|"B`at^s?^/>)w]}\a~|?{9nV=s/r #$Fk(5&qȭ4?yrao6{kgZZ `z>^'7.F 9B5%$'O @'/z=uQWtܫ'~㎓'ϻĻ>GyL& `z>^'7.F 9B5%$'O# @;>~3G,t Y @XENPTb;Lnɓè@XFCncRVH<9e} Nn62\rVk0J@I\)r+$ O@z>^'7.F 9B5%$'O`Y=s/r #PcW @'FCj F 1+EnɓhXVNjf#ň!GhԘĕ"B`Ɂ4,gEnprbĐ#ZQjLJ[!h0~@3"͍`sgZrJG~_z1Z-VIo>lvDh;f![.g U/OyܩU% %I|"B`Ɂ4,gEn!&~a6ChrG,)FټXRX]R>O6Кٞ\~%(TѶ/mK+lSdR\IV!>T%SfsSIɦmEI'r+$ OF;Ϟ=L 45x[jXIF0pE#&eT4TfUW%-yX2PUdm&emL6Z^1s &0Z\G+%])TJd43&c @'QxŠshk3"mvldkKGʢm8⤀GW(h[z eWis.'":bL"` 5}jQ  UQ)ЕTťL$'O@x;y > hk3"MBr#&omK 'oE:6)o[V)Ln+]ز@·MW oYbHL"` 8Q2gӗ4؜0OVH<9%=֢gEn6#Y6d3R!NqfE[j)f2c1*dgRl5JfS"X?* 8ߥL$'O`Y=s/ra1iKn62\m1]4YDM4*y!+ٓ*Z+pu6dUO\s*%QRuZ97r곭.0DnɓhXVNjbLܫf#ÕX[!2ݰhۚdR%՞J%AbWY|;dL&0Z}p(IpN˶ev&m @'FCncRVH<9e} Nn62\rVk0J@I\)r+$ O@z>^'7.F 9B5%$'O`Y=s/r #PcW @'FCj F 1+EnɓhXVNjf#ň!GhԘĕ"B`aK?{ˏ<@X08/r #PcW @'1o}-oMZ|7MZ$3q,^'7.F 9B5%$'O#@+̫v[~鷼5z8V̡$ňvŏ @'OW^d3ŋf#ň!71J@I\)r+$ OF>'#/sE2SEnprbĐ#ZQjLJ[!h0~0?Bx3[Җ 1? 7d3ŋf#ň!GhԘĕ"B`ah}!߀0>=s/r #PcW @'K)! `-'q,^'7.F 9B5%$'Oc@aE4SarbĐ#ZQjLJ[!h0~0ȳ{kϏo8EgFCj F 1+Enɓt~hk3" o1F+c[;g|mn2CIo>ݷHJefFfecz{5BӫϠR iLI|"B`Ɂ4,gEn6PBa6f# Ql޿u,)ԕפZ38WRIEmov۶465 ͝o8=BNVl)3(4{vL$'O`Y=s/r 0ɊV pE#d0X1T?S$̾^mT2(L"`3D#'9-fCv1 fzwL$'O`Y=s/rNdkKGJˊQP[z"}'9*PѶJmuDhgӮ\(8҂0iOVH<9e}-ij\HlssEzV!3+567J(#vv{_tG:V8DhgF_VzQΠi4;ZI|"B`Ɂ4,gEnY&(f#)"_Q$CL!3 x[X-ۚVjrڙ+5Έ?r*Q`/0iOVH<9e}-'o9rGL524 b,,$/d%{2T]%ӽ(N&vL"`3"GI7Q>"vL$'O`Y=s/r Q.+hF+10s h/kYnK1մ6YSd1HWT2;}M&0Z{^4OR v|ؽ#`&1ȭ4?yr xld1&0Z;F 1+EnɓhXVNjf#ň!GhԘĕ"B`Ɂ4,gEnprbĐ#ZQjLJ[!h0~@3"78p1bZ(5&qȭ4?yr xld1`RVH<9e} Nn62\rVk0J@I\)r+$ O@z>^'7.F 9B5%$'O`Y=s/r #PcW @'ENPTb;LnɓhXVNjf#ň!71J@I\)r+$ O@z>^'7.F 9B5%$'O`Y=s/r #PcW @'FCj F 1+EnɓCAN=s/r #PcW @'+;]qk?mt C.3"78p1bZ(5&qȭ4?7`)=s/r #PcW @s-4,gEc~U/Ysf#ÕX[>j ubUB Nhf7m9#9U+WC,EA+36:m鎀I|"B`C hXJNjL!~D:J:rGq2\OL6KkI!YkPbm>pmTRF曾-=ɕLT%t[g &0;yJfţymiTOVH{h! KxŅL+L KldM W~V3TVܠ2%ד-TIv9;T3REG &1ȭ4?W\qŹc; @ =s/ruu: ؖkldXYSqkFLb͔z}'9*Pw2CirDXeDhgsxgPVc=`&1ȭ4?/~Q/2 }q+ ,Ͳ2֒ 1)k[f̌7,ZeF}dMmYD}5fJNiSdz7ʌ\IvF8r^\(3hJtG&1ȭ4?В/߀Z=s/ruL dd>GLؒh[ HYvb2%/d%{2T]%UTi,gTf=ٹRR9ΒR>Mb>[!h0~?BKxDҘldk鏗%s[ڝY=QM*T*i˦Tz3m^qk2i4Q?5εţO0uOVH{h! Kxld1&0Z;F 1+EnFCj F 1+EnFCj F 1+Enk @K]1hЩg#=8#PcW ָW\g!CKO! `@Nn6&̈!ChԘĕ"By[KuԧnTC C.3lLCj F 1+En @YnvQ?C AZz0hPGzpr1gF B5%$+zW\S y))%a C C.3lLCj F 1+En @}_Ѓ ?3bZ(5&qȭp]hy|1ve _̭ޚC~y$+C C.3lLCj F 1+En @˛ >eIy)-@~O)! -=A4]g#=8٘3# PcW 7g2RZSLQ^g!CKO! `@Nn6&̈!ChԘĕ"uMY-RSLQ^g!CKO! `@Wؿu̯:̮Rk$|m+GCvҤգvӒa ;Lիh{4]逬^ f'8/( 5ss0}OVt R v{<avL!~WLGn6& 蛩,Mvچ|JB7LʹOMJ*ڔjimm"qK}Z |zKг c0X1ӓ ?M9˿ q$z]zzceD3xR u]TdM&0;/(鳙}fLf_zdLb>[!hCKO! `@.Śt [:ZjQ6_؆9*PѶ%2Úh66tEJ\)s+7ΈOVyGTld'P뒰Wɘ|"B` C.3Dbf9k{&ﬠuTwik*fEW2ݻ-kmnC%WiloL}Al̶( jM"`38/>^s^zdLb>[!hCKO! `@ɂF1CkvԬӔ=Z 5y=%=$JMhf4ɰ$ԛo@Vj=Jq\I.=`2&1ȭ4k䡥' }8V*f:TD͢Y)SMt:Pvuq;mOlZ骾Qϵ%Ej|${<av,&ΥV1ӓ ?'#ֈfi,imvW*hP 4Yyd1HW2UnD]|TV7 dux:>s-lvGk?&1ȭ4k䡥' }'7~fĐDh%$1}ȑÇ*p=zX<a{}'7~fĐ!ZQjLJ[G9zh{ %GyvlZR5aU;w;7fcوэٙ#^f5[`IHN3{W`uKaU9QNVV*3ON*O>>1 "!BF- c&l zr0(̈%BJ`(\M߶{{{DB!Z2@M@2}`Q#T%0JPEKP.v:CmSH!QCKFЌЄ!Q@O1AZDH U 3~49%Gfp.M!|hH9d> `3#F"VK`)z& z `G,)A2̺$7! >d$(b&lzr0(̈%BJ`( 3|+zի;x)yfk4{W~AN9BZ2`1R@B6LG=9l~fHj !%TR0F@3IOtġ`ϳ)Eb)|Oh_s5>3<Ǯ*]uLR|Ϳ')o~2y6ŕ´WL\8ǏE3w<)BUNn+=FxY4:+c{hW>d$cKM2}_FJ Q#L?g0D@U7{6jSJ+;xbcrwSyZs@9}9%QM=vͅH,a'l1&{8#q7oy[~w9 !s=TxPu%ݽdJo\rx4|hHbhR@B6LW.MQ 6J?3b$ av%BJ`(g-qY[Ei<^i?AP^1Qytp]8'IJ{!+{>0(bc7oy[>}B~tI>#M#di(aYޫHG%#a F/4!ds}ГFgFDP(RB-Ct{zXh4q=I'rw4Qϒ~i zxMNl4|Sf?JQ@Rpm6?Ø-oyE wD?. y4~+;+QIb;tc4׀&F'NH7 í Sr%x}ݷ&hG%#a KM2}`A1CZDH U fh~Q Β4@M(1)^1v卑ЮU1S/h~FN 9!um>Ji|;6%ʣ1)^1OUHhbxކr!<~zvzmΖG}%x%' ƣq$Z2`1R@B6LG=9l~fHj !%TR0D@kk0jӽ:qЉ8eMǩna{ٜ3IWU砱r'z) PW~xT?/ǼM)na{ٜ}h9B!>b%PJr1&*Sg%'r H>d$(b&lzr0(̈%BJ`(vS=;4ؑ$M|>я~#yZ#ق'|GrB!CKF"_ hB(siGIN 6J?KxBJ t3$ݫ, r6S4dW[%lExd:V*wH'M;JM>+TE B 虀c<mࡇߒ33!B%#a F/4!ds}н8=JwuSBfʔTNwޞW=8,{Hs_Q2q]T!Ku{ݎRtX4 U rO0R@|I B!dВ09d> >R+l~#L6`T$ʄxg@b\dNwJ=mRYmη$Fh9x7 du;JQEϣ⁜A#O0K@PO:Ow}B!1P@B6LG]^NcQًso&!ߞqg6š|CۼDN>~],с{ЧI%Gh9w^Zl>.U* Gz!S P39 MB! - c&l 2j,4Zl~n ٔ8N|HUY]>zwjvK9WQG+7.>9dB-;QrOotd* ࡇ/R}GL!,>d$#KM2}tJ}K%t&.Qmw:WK62lZ&'^ڐ*rxURFAݮ;J88R U' ( !B>d$d> 2 lgFVp*ZeʐIV* % HT/*NCKrWL\U吸ĝRtVn?!SREB!>d$d> >+Hk[1 6J?kNi+ЗE ]>{$/_^"gR%dʯ#qMT!ƻ s:}J̽!SEB!>d$d> `3#F"FkQ"*Z B hB!lВ0 hB('όZ-Q"*Z B hB!lВ0 hB('όZ-Q"*Z B hB!lВ0 hB('όZ-Q"*Z B hB!lВ0 hB('όZ-Q"*Z B hB!lВ0 hB('όZ-Q"*Z B hB!lВ0 hB('όZ-Q"*Z B hB!lВ0 hB('όZ-Q"*Z ПͿ~"űi:& B+В0 hB4PRό!eb9pm޷oۣ]5ś&BZ2@M@2}_6E^0(̈*a)p]3ǮZ|Zr^+=gB|hH4!d}ГFgFDP(RB-Ctd&nMnLv0e5w!UtMsejTdeTiRYbvB!|hH4!d}ГFgFDP(RB-CXUV`je!spzSz[Moƫ*2ݻx'd$d> `3#F"VK`)pZ]or $vkAp)AV;v'&+&B>d$d> `3#F"VK`)p]Z][g[v3 g@&MӤ4"Ǚ-8rUvM}^H-$=u!W5R!>%#a Є $Q@O1AZDH U пZB')kifΰzuUb{}7?B(b4giKgvI+Oґy s!TwBY'В0 hB(ſ:!/k0(Dġ+&dmNV.9(N;Na֕5&+D/-Sad.lZQԎ2t>*M ,A!R%#a Є $Q@UR_)3>FVT.1e4ad2‚Dɂauf7yz2'Jro_Y"$ m}9ծw a45'oԺ!AԙG:,3EBHTџ`(&Bȶ- c&l =m3 %B9lGЫU7x<+s+KP&+ԹP0ZS_]9*BꥊC!4!B |hH4!d}e,Eh0(Ey2Sʡ~?͒ȨogMΩP]Uʯ,&#:F nQAZQy'L Tџ`(&Bȶ- c&l  L 6J?C{hn*:׵Sϝ٤: IqWQ9]%{BpꌨB-"{7cZQReH>*lU' ) !mCKF( !H.cK@~.O5i94/0r˔niɜ/_Y{_f"NUкVΖb~* ЄB6%#a Є $Q@<@-`s+bevNSPa撂wRxrJt{4+KL^f:Iୟ*r=zuQJ=BPYZB*CWO~?K!0P!51P@B6LG݇6e `BF b)/ љ MV/Qaxؤɜo&+NpJ8 FS*5tQ2Ʒ_㝭=*TL 5 {챯B!,>NCʼn'>OGn%#a Є $Q@O1Q0Z;!%TR0Q@ӟƿN!2hQ|hH4!d}ГFgFDP(RB-Cg?Y hB!L>Z|Z2@M@2}`Q#T%0JPEKP^կ~UH!0hAM!d> `3#F"VK`)B!4!}ГFgFDP(RB-C!4!B6 hBɑ('όZ-Q"*Z B hB!l Є#Q@O1AZDH U ЄB( !$G 6J?3b$jFh) ) !1P@BHLW.чB~f!,3 ЄB( !$G+Ц( 1Q0Z;!%TR0\@??6sPɇzH*|{B&]+ j#8pPX&zr0(̈%BJ`(ƿ3x<4{P??|B&< /<>pPX]ۇBrd> `3#F"VK`)pC K=^mB!ݬtsA8(,&zr0(̈%BJ`(?;_T&ڄBAW+]࠰ Q&zr0(̈%BJ`(~*PaM !,WAa$CM!92}`Q#T%0JPEKP8L%5BZ{;pPXɨP@BHLG=9l~fHj !%TR0\@߫T{ DB2{;pPXɨP@BHLG]}:!/%cQ9؉CTDɺ'n s6ˍt)~ʯ,Ѧ'6'U&n&AUbnl\N&vO0R@O]!o|E%$CM!92}t/_J9DV ϭTqe(0̤^4ɂaHDIm~+Kjټ$=PRSP6jBMM4(":3|Pb ɇMC4 sO^$y>T&%.F/@!mFu;(Lɏ+Ɓ&U\4!t(0Li3 { 7Fg?bls) X'*^dN$+s+KTҐLT-ЙsT!Cx pH;J81Q=TM ™ hO|=f|K_ R.9,**,U@v B{d:&ǕV@.B:}erY+꛴靡+}!|?s,^ZG_%ZA8Qc<} T!Cx R%vNWX?_PR7U' g.o>?YyW{ջڧlɃ=<\9恪Ru$" Vͧ>)$홗2f`ÇKLɄ=t2) A'xi)JS@qAW!% 2<XjaQُ: M\vmќN%z["Y% KC2рt\)Uܡ;Ҋ TUT@=TM šP/tyիQ{eB?<ȯw+H1~6g3$%tm=1  轥A3l睍kƎ{#\",HF&N2}tcFSPF+L`s+bv-AL/SoMlNivWh*ސLF!E]w%ex_ ՠS * 37S?ƇξkqLj{Qks/T{ yOttGlDC2[O![BWی {Tz+}Q;`8;OykK|ԑL&E)s#UTB:}}(q6X`0(D)&˂Gdl(S*g훼Mw$IO&zܓdεQ0-aSbSJjNzCBC4 /};}N>7^]`O[.**,U@"c?eO$f>vp]%tpu klRAPÇ]oƣ-fB2> hB$Q@O1Q0Z;!%TR0_@2|~'~SBڷOj 'f@.^;tm^bIhdOw'-mFu+ ?9`҃Ad)/qǽӑ|9jNM!d> `3#F"VK`)={zO!CW;=OE%$CM!92}`Q#T%0JPEKP8sO>Q **,U@"BM!K]-IbQ&zr0(̈%BJ`(>u=**,U@6!ewᠰ$Q&zr0(̈%BJ`(Fݐ'A%QUTXqhBYfXAay$o4!}ГFgFDP(RB-C>f *Ru$>C&B}< zG KvP@BHLG=9l~fHj !%TR0Y@;5Ŀf* \Ž+Y !L֌\AaoBrd> `3#F"VK`)pB! hBɑ4PRό!eb9B!4!}Ez`3#F"FkQ"*Z B hB!l Є#Q@O1AZDH U ЄB( !$G 6J?3b$jFh) ) !1P@BHLG=9l~fHj !%TR0R@B!dc&zr0(̈%BJ`(&BVɃ>xYCI3fKM!92}`Q#T%0JPEKPHM!|zn"P gꯗBrd> `3#F"VK`)BY;"P=KVЄ#Q@o߾NKڱ' 6J?;qI#YR t%yo_0g뽚RI6 qMlZM܂7&AĘf2U' ) !qȑO gꯗBrd> ^RSvn`s+b^~U\ש>ݙPRS!Mz6Spr6{ʯ7{"FhjnRDIdb ??lU' ) !qȑg'JѳdKM!92}tF).jE`Qُۓ>ҥʐn^n%ikꜬz=Tb4$qT!G}wXhG ۖLLR/U' ) !qz1zBrd> 2bm YB@;fJ9qg3do̘7ȩkoz}S0Z[n"l@( 7!^O0R@B!+xgO='O==_P@BȢd> 2Jx.mZR m}!;8oLԩf˃s6*NCR\&:pTx'*ђVi۬Șy~* ЄB8r3<=~їO~[^{y{_~R^wP=KMc>撿o#,֔\/4!}eu <|)ygRyRMos/Sͦ%s־HV~Eo@4ĵP0Z[{:֊"zIBjC!4!29}i#?}䉟)x|d3((Eϒz~׃>Kc>)'2ڼ4\/4!}e(h 6J?"\6h 2GlL%u\N TVtfwk.Fs jhG g.k2QWވ?PHM!#Yyˮm]/]۵?FMMY e<Җ)- 6J?kikЗog$ܙWlSqЄ#Q@O1AZDH U ЄB8rȷ<_>~?4,BR,ޮM#g{/G\/4!}ГFgFDP(RB-C!4!29SO=a_yo~`S'M6BR,Wx<k&g[F@륀&zr0(̈%BJ`(&BVƑ> '.Q@'?)) !K!Q@O1AZDH U ЄB8)w>|:}K^k>p7E7hn7?5yA@y&E}ГFgFDP(RB-C!4!29O>Q%;P gI\z) !$G+CI!J?3bB B hB!de9rԩS2. BR,YR@BHLW.MQ 6J?3b$ av%BJ`(&BV &E}ГFgFDP(RB-C!4!20b|'0(E@)zz) !$G 6J?3b$jFh) ) !~7)cY륀&zr0(̈%BJ`(&BV< gÊBrd> `3#F"VK`)B!4!}ГFgFDP(RB-C!4!B6 hBɑ('όZ-Q"*Z B hB!l Є#Q@o߾NK͉Ch`s $V ]A.7 rzp&+&ӦBĖծ[>B"JqSAyNBC!4!B6 hBɑ({I3-ZӁFVTvɭKaO Wny$I-/z6Sprz4{Sz=0^+d^1UIu:GTξ94* ЄB( !$Gè.ͥLV`1OS{5XK)+n\6cEN1lz=$$xgxtX!UvތvR9ջ7=BC!4!B6 hBɑ(k hjN ^ĜwsY0wF:7z/Ivq^mf9-M @&' UR0Z-]~ZQJ|*B\FR U' ) !1P@BHLG]FrW}jaQ-;dg1> 6^z(1d9u>ɫ=.E\obCx*_yJN]=U%Ѻv=(uO6=BC!4!B6 hBɑ(؋{>:3_JYv֫xL6ɉ~-RE?1A)B-Aj+JٜSaaMj?P^cɿ !B-( !LG]Xmf_GZey]:=bmSֲwdu;)rrzYBRo*U6*n\Rx QL,MHTџ`(\?MM! G |CKF( !HC.k@bQ9X=e?fg6Dż;/!!U_owEMm#Jk a45F)3ThR5U' (?O8qߊ_%BY| |?.51P@B6LG=9l~fHDh0JPEKPF|哟?B!, >T>`Gn%#a Є $Q@O1AZDH U kЄB!kZ2@M@2}`Q#T%0JPEKPHM!mZ2@M@2}`Q#T%0JPEKPHM!mZ2@M@2}`Q#T%0JPEKPHM!mZ2@M@2}`Q#T%0JPEKPHM!mZ2@M@2}`Q#T%0JPEKPHM!mZ2@M@}?{zr0(̈%BJ`(&Bȶ-I CM@}sr>3#F!d!~`(&Bȶ-I CM@2}_6E^0(̈*a)B!>d$$>.$0(̈%BJ`(&Bȶ-I CM@}%8LQ 6J?3b$jFh) ) !mCKRP@B6LG=9l~fHj !%TR0.C@cB!dd$$>.$0(̈<Ga)pB!d$%4!dI}\cIP@.VK`)ak!BA&n_'8 +ڜѼgבWY)^[)q3$rWk3JIm{*mw-/L!s[1r(@N 0>Є $Q@aXmKI%'4\JOl2S7yarc7.;qJGNwJWvlAL2r{xG(Ȯ5gIDATAnHk#J l ^\@?k1B;ο@~9B!&w@|3rЄ-%q !6ZQj,'3[Y_*<%rZ;}e8"~N,g{孍-Љ M:J4O!ճ{{>rݏ\/]Gb^WR_~#r2!Bfmʋ2p>9sI CM@}B$ɀ[ !)!aBBJ{(V>au㹜EᆰDkJ5DbO\,]⟺B*J=oH&*mGأzϣro~{_^??L!sm=3 ggfg-:Ƈd> 2lPI) v~krh*_-˔nix\jCȥ&"a^* 2rt^jZGCR%rZfЏ=*|ߣ7}Wүel1/%q+׼[e~ɄB1Fˋ2ps c&l ɾKp Ay4gJk 2G)ky i.)x'WnWN/KH :_R\eKH\-)ؒ8EIja:rA=T6 z\v|g|G_/g_:k~=o}'[?M9B̟7.~>) |n}{ rq㟋#$ÚBsA5Ƈ$>.Q\btjf_Lۘ,x;s$y> I^NTΤKv] V 䃚׆0JgR㕡߭Uf hew?|{o};W%9R~վϪO&1E(_nɜ;_:3r7O^vmO?(_ݷoy]-[;lFP@B6LG=9Ф %BJfm~ǿow{{>x}>߿?o=˛L{/L'Ƥ"UOfN+օׄlvw]yQN 㟻o>5h,H;ב0 hB('tAZDH ,4ew?>ءcGy^'^_|u}cлwKGOGdBH}7~w!~m@.WRk% n ggf?]y]t"H;l_<( !H hj !%l~㲻}o}9{y/_w׾-O߸o_cz?ۏɄ x+{PI6I8.'>QyMȖ`D(ݷoy][;ב0 hB('tAZDH ,qݏ;?|}uo˫/_W9??>Կx;dBH(lymZ1?կ>oNR {$ƿ[A^5vm7W*=A0;Q~!u hB('tAZDH ,G#~w/^/x8Ʒ;8oۯ_~/ow7w|PN&Trw$QS1g̱ןlv7My}#|K_2;Ӟ+/4q;ב0 hB('tAZDH ,Oz\~t.Kl)v] !W%bg+ߩ>]M?:gި?mnyQNG s&Ńd> ɡ&]P(R{;y~#?wTs]GA.9Rym̲ɦ43m0yߑτl%DWUs c&l \@~1B! sC2 ɡ&]P(R6 oxfp !2oN:u[1,iu!#a Є $Q@O4jFY@B![Ó r9C 'H4!d}ГCMZ-Q"mB!dd$d> ɡ&]P(R6 hB!0 hB('tAZDH [+ ?B! |hH4!d}ГFgFDP(RB-C!4!d*Bȼފd> "v18tB^"IAN: [$p9ӓ97'+9/5J ۻDMRpZRnBtVۚx*O0@@1yH#x>'NzyC?_|aGB6 ( ![K%eϔeLf#9'sgCZBrzЦxJZYw ˾]/ik a45ww[u;:={dRU' W#eo3ܸqd@>+4x_{{?$xםs" ( ![K-<^ $4,Ju.;k؍FbdNw ޽hWN+;TʩB-iQJۊVY* ܸqMhyд(f 4!dk}e셚Y%`ps͔r78{il2%rZȻDRA/yz5P0Z^HGɻ՚?(Y* ܸqMی"/o?b .޽7O]+ˠT="4!dk}e՘.%ZR G ФP˟4ղGѯF]>˩o!z7]YFqU^}&S0ZgE*JE(6R U' )q6n|̛??_sѝ %_@/,Mz&CG?"4!dk}e6bo0 \Vi/0'^{/Sͦer_fT+HīJ켰P0Z5qDr.{[qpH#"O0R@sm7moV藼wJy\pm%'W[(=cfޡJ%uފd> 2 ,_jGsd.k 2ES9撂wRSz'szYBRoDJy|$Yf2 a49ҺnjVl@ȄTџ`(ƍ۸-nZ̋B}Uz៺VwAI- pׅ-c0, ;7Bn8v!t4!d}}hS O +XsBۤ%|=87Krzʙtɪ,1Y%ӽk|BMw ;F)tV}ts_z+? &@$PGok\ " :&l-zr0 \Z-Q"*Z Š4F_9U~ul~y+qhC[w탽6i1\1flK@/|Ĩ:l/-\HoEMZ2}`A1gCH7!%TR0V$>˒fKv_<ِِٜō[Eo3m)qq?=wˁ:3rWMbŗC @( ![K 6#FbVK`).mO|G69!g?r^ynȆ,n*چ`?lq&YC;;~%b dYawO[?zŗ$Wdh 4!dk}ГbH j !%TR0nGG~iD69!gJ@?˽%çO?VS>Oң_V?{g]Ń'%ɓd2;8sKjװI"P"9/J QPIކ`?lq3'(cclw]xI+ae'C,2J@3ݯ6I&l-zr0 \Z-Q"*Z o}[OW% )8K^c_Gݐ-!pS{'='XpZΞhD'LJ<դV7lq ž K鋊gJW5ACjp$E69l.[ܴߙ\#F-B}/S_7xqu_|٭am~(c c&l zr0 \Z-Q"*Z Js=gv=y=IA69!g?r뮼KvwCX@x'EWԢpa?E,˙xw5Vwlq žK&{Ov 7l R!1^ue*I1R@[(hqc m8:/{@8r HoEMZ2}`A1CZDH U {/}_z}glrB #~]??Blu؞ ]9vjd .A9O=L\^F7T/+c6[O {i. lĽݾw_ۆ [ ^j\"Ж ݡkq(/Վoz qtD6_7_I];7Kn_~P-( ![K+CI!#F!d!~`(N@?S/| =< MNHaُ\qn FԼTWHԪ j-`)$][>nZrvnUMlF!Ρcwv%o%Vk"Kf%◰juO@56z"#Ւ۪(;;r ۵ /gip2\j.BWfHoEMZ2}_6E^0 \BFh) k\o~3 yWӟ )8K^w~ +?OmZAؑY\_鮨9]kO[wU2xa2(ЮVᩘtfǖ [hf"|OQl:8reV_6ƻοH|w/12Z&Ao2Ћ/|owЄn(ˁe}IMܡ~#4!dk}ГbH j !%TR0(%/yd0 ˆuts/}z7dk /-Bϫ|]9Փ;f]YXԪd3ʴ4 hw]9l@f<,$ŜKmQUi7CD5@_N9mDTFM/>ƉVn2Ћ/lGR߰uX ha5k˙S#4!dk}ГbH j !%TR0V#Ϳ$F% ZpzV>+Q1ɜE`cݞ7g&S(ͬO<}2[ DZ.uALV,xC1A<˞1c;M'1y\+X 4!dk}ГbH j !%TR0V$x`YMNHa_MM,!ËzYl_۹ ~"\i@@{/_t։k:H Y>7my>.ͷX@y2okB_±ZG^?Tzbpf?q(auwٟGQg_K( ![K 6#FbVK`)"= Νo=#.!6 lq3nysO\|FG8%^?M^9/sñYoSQoKE[:T wۖvqͯ7Z=`Zۅzq} cK]>.ά/P*971[Q@BLG]Ğy/:EJl0b'IaQRw["&szu~aNR_}NW&Tnw[ǺV>WB(ڧ$*B꧊C hnܸ-M[9sO=R@^7 h`lMے@ڄ7RѧNn hs|;Z N]W[YzUfVBJ0Ur0PSӥ-_VЄ%Q@gZ륏1udR'dQc LŇ͜./(ɽOV~eؓ4M&꓊hmT!&}273J9(3u?LH B hnܸm>/3^3^cܬOG /kzye?Bh<2C3zꉮ3<bf+&#JP7)# %\|o \ Az+ hB֒(0Kit&BjE gۓu" NnikꜬ=TbJntXREhyww#[(lw,}!RE7n㶸ics?=墳 *Es?Bf}^/aҿضF8:Ybbz>H?(%* J ^ .pvFqKp@8ntCHQHa%t!4!dk}eZ[- 61L)&F^%r*5}& +Z#UA)ftZ_=,!RE7n㶸i0-&ZMy6)AJ \ȬOC3 :ɧ;{I=SB{<*WφYaZK-1ftCHQHDˎ_x&lRB) Z j&Ys#ga#eD!躒>0E&&Fz+ hB֒(趗 6W+b*3_*:K0meJٴd;ʯ,ѽ&u*2ܠ(!wX2%*BjC!47nmqƘg \xa]-m_#4q"I=SHľ+;̡KC ɣnfhO ފd> 2J2`A U%gHsI;)"R9[%ӽrݕ%&/3X~Ek a49;傣(2PnAy7})?PH͍q[ܴɲzBfm2@fG-lO hP^B+au >0K[.Ml0 \aĚb&-|̑&1&y9wJlS7Y%&/4Chj7 ]#+3(Ei%4B꧊C!47nmqӖ` M%2=wz?ݏ'7QG/w \ I%y'N=s2nŗoKC ɀb671[Q@BLG=9l.FT!DH U ܸqM[/Kbez;'nхZɁq+܂܂ Ig@JXdph ]X/ ҅F= -171[Q@BLG=9l.FP(RB-C!47nmq s2amU8pVTj7u<ƹx`c cu)!4Q$0 271[Q@BLG=9l.FP(RB-C!47nmqͦ ޵Y]a2"vX 'Zz%ݜ\>h޷+l2vb =NE0yUh71ο|Ly( ![K 6#FbVK`)7n㶸ifwȋNM8LɁ@i5BZUAZЯ'F'" @[w `p1b$jFh) )q6nn6R@w^oφp ǮYy\ r-J+Y7 POڈ5tuwaP!Iϓ 71AdLy( ![K 6#FbVK`)7n㶸ifz%8w3NPIpsmq? 54Kpv%MĮIPە^ƭmg+?E I;ϓ IW90( ![K 6#FbVK`)pk^}^32t/Sqhd}JܴẺe h=WK7Axw_86khZAWص~<$7!il )8eg?w߿z2qhjM[ϜX7ybqN]N90@8Sk rN@_q__"_mYа ' h/Ո;2Y8U7'HoEMZ2}`A1CZDH U  /ѧ~/MNHa/;?8z]л>[O>}jKr~yYsóO|C+Qo:HQDNj0M ɓ%EUC6zC}Z6I͉OWkzI΀%LV<ٰ71[Q@BLG=9l.FP(RB-Ca3;f{̤ ˆ3%}ۻo?}_4%@-SĽ}IMt|VAo\ʃG[Kz/g.voxDlڧS ~fs-gN,O@;O6L5 %Ȟfuw85n .MZ%jHrfC.qy j4\gC뛘ᏊVЄ%Q@O#1T%0JPEKPX~^җWN&'0{~oW"mm`3uۗus"\K9 mC4|e.7_l娷 tjg#MXDyU.x˭)zjMY$&~vN GG[@8z :z]|PRIlЅ. Kh?B+;uVlh3}&l-zr0 \Z-Q"*Z SO=s}F)}׍?K]71}<5/U)R9E6KgH6_';SL)4b#lKnͯ*::*UNjrw6u9-\96q2&e9$mUn7ԕSoG%u 8]4%kh̀;A `R3kfC.-}\X[0 WG!sCꖇ&6 `p1b$jFh) k\o~3 yWӟ )8Son %NmIi5V Rߐ EmL2M-V]cz.i7~6~TݾI͛V؆`?lqzg^ hs_"/?r'm}*8W,j vIA om h0'?;.,!4(,$+6/\ i[Q@BLGˉCd<ٷҩ 6W&CXvMM 9dWhSoL]ќJq\rtZQH˜|P*BCa^򒗘# MNHa/;w][_޿ڶr3U]9'sW;oֆ-Y9-yʠ7MnXeE{2oLqZoF`8JԳn6'O= {'Cmr\iV9+!OevCb>RiQE@,0br\0.RhRB).,$ĬfhJ砇 VЄ%Q@+S/j_lk`p#2ɩJ8'[H @*'Jrus؉+D졖dL U%,+CZp:Ԝ~ zIHeTџ`(G?Iӟ )8SW?/yuK@?6hUV5)+IB?cQNw\^7;N;MRHvp B%Xl~55q%4gilDpn+ԉ69l.[ܴMXߴ^Qx[  Xp08OdeyTŏJ21K쨅Ej6_^z+ hB֒(Q*K2%|6lVpah.Kn\6c/ە9Y% *{ـI,3 a<ڎ(g$=TM J4+~, MNHaęoųoo/e.dKw0y/ bn;;0 \~Ĝb3't s'Q;:oh7ȩPm_Yt\ Wudgɳ ac;(&PR7U' ] ˆ]_=K9 6dxۥlZ־EۈSַ.ud#B[F7m=ϋeh-Z|v*ZӄGYZ+{j Dou@\aw9Y*NEhrI +-o[Q@BLG]Yu9!OkaAi5lƿ-FٺV]>QnUu} jK{.M0 \aĚr5|̑Vm{T6y_Qb1zΈ*$oVӫ 8ɺVJI#~O0R@sm7mĴz ֽuwQ1t)pO=.]Cl`8N0 I /ꩋ|-!>*4k 2Ez+ hB֒(' ň*a)7n㶸i h?\x2 pL=: nv?iU,nw{KPoXY< h쥭_~]][Q@BLG=9l.FP(RB-C!47nmq3'}JqeVk-U%3SK]W]ujeymE~o 92oM@&l-zr0 \Z-Q"*Z B hnܸ-gNL( ж5ƣ%}L=.vaU/d LG ^B7]$~o * cTVފd> `p1b$jFh) )q6n9+y~P) *g%˧0'K$q3f`v_ZVE#o)t;Ћ@MY zr0 \Z-Q"*Z B hnܸ-gNL(g8Y1a@w f s߯&Kı8YY{9ShiA%i=w$_H7#VЄ%Q@O#1T%0JPEKPH͍q[ܴẺ عJ4n1o _.Yx? 7ftKY$oo'Y qoR4,=( ![K 6#FbVK`)7n㶸iS hVxFd8 ~60Cp%8Agf͇/4h~jXj- +| vIgzᐛb/MRBz+ hB֒(' ň%BJ`(ƍ۸-n"xTzwf4s-N|pfUgv3v{gdw`k8{ؕLӒ Kϗ;[ [#cVЄ% h#T?g0R@sm7m `p1b$jFh) V@u; ^x+)ܸUW>%n"xzoV]ShYw7]pmp Z"2%L6aTi3φPVЄ%Q@O#1T%0JPEKPXF" ˆooE|w?po_t-WqhC[w탽6i AZׅvM !3'[wxúAT䃠/KQ7SW`mO @( ![K 6#FblQ"*Z Š}'{Yٌ8+W}K?~ifCdCfs7nmYl~M[^zk:vܻj;{WJX\@к.I&/SπVۂ3^NE&3%?bc[Q@BLG=9l.FP(RB-Ca]T;7 lrB #vyէ^򏽼wC6d6gqV6&eIٽ}B h]\|K4G^ vvλKExƻZػ\r^8LaΔP;:^AS \27SBjC3[Q@BLGˉCzJbwO4{j&āC' F)%>dȩRz$*w=M>E^̈́T}qw0w(?IsRU' 7@@_?O?4^"ˆ3%??ݐS@O|C>|;O? q' nO'9qCx*)_p9'.>cߋ=7͹3%dA]O{}1-w%곧+L ̗`z]kzZJg~Lbu( ![KcoW`֔9;- 6W;b\9U8,GqNBtTŇ!-QR*gSMTW^YQ0Z"ͽY(5xOEDyNB*C跾_W&'0l纝k>vn_ޛH:7N8y@/<9{q݆'Ԯ;:2_5)Y69l.[ܴg b,qJ[Ͻof6%8.gQwAᘜ\.h]?/1֎^vYYZU@ʘd'P20 9#4!dk}(%̈0/ Պ2|J9#%˒ˉݸ쮓9K4{ʯ7Q^`%A'٬s a<;Y(;-YTĔ$6O0V*{9c??y{L )8۹n^?yYltLç6jnq$d%pZ69l.[ܴ1O1;횳%ehgu x 0]wk ΀nh曏 'P20 9#4!dk}E9NQ`A)󥽗9'M3 Mϩo5%r*{'+v*ђ B-uڷ%w(Vw< sRU' Џ=K_׿ F\sW{7dtE)3BU;Or^RCHC5Aвm-99ۆl-!s(wCmr\iOK`KptE?={) Hz ]ny[àZ//xkĭd|&;)*uW  {1VЄ%Q@a|Y M'ˏN>ph%8ׂKJTNoմGY>٤: Iqמ0 HN*}17'Y(mS<'!QE:SO/ `p1b$jFh) +<,&'0Gʿg_l7W^iZަfF3TkN6-n"xh] @F8:)̃:8f -?g٧+ztQi&\ @j9#4!dk}ГbH j !%TR0V$'~纝̆ +ܸUM[Ϝ`goD^X*)њ.Q%}S{K'P'b0U8Ak.;̀N/`HP>U5g&l-zr0 \Z-Q"*Z ­ܸq[p91N@;SFvռK80`!V59QRk{VY vzZ͗OA=~v^},AN%mE3[Q@BLG=9l.FP(RB-C!47nmq3'-Q kҗ]' ^9w/Q[Q@BLG=9l.FP(RB-C!4!dh-"xD;;~%fc&~fX8vag@>[Isu/ +\5Y^XqOKKYu]~UA8 }ieKQWVЄ%Q@rOIZ:р #֜p IKrrdU rWlLl;`7e&lZow[KUQJt'$B6* ЄqiK#x>' hm lixTK,h$F95^15 ޟZz5,6=-AlU_Vd͞vPn]uEHoEMZ2}t{b3L0 \툩lK -py_vDN-lHKTNwޞWzhGi^T!Hs3W̉~#BC!4!dh-Z̋Kp ]wsiYBDW@|+Z^BڸG(P x`'˫ej-A/Aa"3Va @( ![K.GuʼnlV́]oNIYϞ23FK@ݹֽHjt(u?x¦GHTџ`(&M[E8ssOsHg\ xG _wk%/,k1AufUg" ˈ 0b _][7/~ 3FdWVЄ%Q@ag i}2WfUuN%Os~@y8}<{CΫ=氮7^&NDi&T!H黪ڎR.:=>0R U' ) !@ӖFnܻ,0 T;ze3?&j CUnZ޹N/$00zV!5LVЄ%Q@Wd ՊX+gJ;hk5-ڸC}{m6-/2[Eb.J aLpn?EjizTD B hB8д[ZMVPEpLatW5!fw$]$h5kUqf@NavĤt+:Vy @( ![KEYHt% lvĬwk*ZLjMDK INrzYBRoDVYQ0Z"AkAmE#gijP^R7U' ) !@ӖFnzg^ 荜y\heDk7ITBJi±IxkhEs] >*.FbW^v/B6q 4!dk}=(V2т #֜v _ά^l//S %]M"ҼBMwG= 镩V'?PHM4r9w"9}'.>X%ڮ%}熞Pp_ſzؔ3d5MVnusu_N7Gx?)c7y]!`:u!4!dk}ГbHLh0JPEKPHM4r̽[V_;_tKl^Kph8p9;L/K"o>bf*!Yu1AKsO^\Ѻ8%E}Ѭ=q44!d#}ГbH j !%TR0R@BƁ-"G{|kV\@:sj-+Z#W:ĴnUp7?mqE⠦b,N+xߡ A$/].&l-zr0 \Z-Q"*Z B hB8д[D8.:v?N$hYWaәcVB_EఫCjA81 "4ӟ=E;wa`00&-!Q!.2O&l-zr0 \Z-Q"*Z B hB8д[D̉^ vvλ˕U>t\.gKG/Ny7PCy#vSWLmuCI0q` I ( ![K 6#FbVK`)24miz$ԂVЄ%Q@O#1T%0JPEKPHM4r=aBm?+77ώ[;ZqG2.)]cuwӟϿlE1&^xxM! ( ![K 6#FbVK`)24mi \Yr hU(FV::Fa9ڬv8(ēօ/4ؖ:k"RmؗVЄ%Q@O#1T%0JPEKPHM4r7M `uw8m4}[t{iV qU2“w'd[Q@BLG=9l.FP(RB-C!4!dh-"x3^sEbߋ:1x h__zf;\/{|A[W A0k:KsᵇQy .׿SEQԫ?trk.x їɿ@&l-xowOϠ.Հ #֔r IKr6*~W;I89[WzV0+~NI.ݪjfZg(%!̛<=%dWЯvy\OLIk aDvsOhR9U' ) !@ӖFn1~Dz hqٞFiלu + #Y+o֖pJ #P߭ڋS G@ۈ8eqw ( ![K.Gz)$bAZÙ6>HyGse'OikꜬvqX|pОdܖZB-fwM;J*HoEMZ2}t quƏ lVZwRѩZ-̩}{m6-U5"Y%6!ȪB-{2w)R+gmM ^@bAޭWon-ʉ4;=U;+]YI)y.MR0Z"Rwv~&ۊ,SgR1U' ) !@ӖFnQv!& Qf0:NiCV ? ]a\xa-v{){X7;7ݏiT~{̀Uj uP[Q@BLG݃eZmC #֜Οe>戗dMl&%OOl]Y7Y% ]Q5&sǵ*$oh/QlݷUi*B*C!4!dh-2[\|kǭ8 h/}eFx̻ +zᵇXs3j\aM8dk_E.&l-zr0 \BFh) ) !@ӖFnzMI&D+{pt!F@~yq}~j*"iP۸/Bz+ hB֒(' ň%BJ`(&M[EϜT5 F@s>^ q4v~"yK?_|yH. H]HoEMZ2}`A1CZDH U ЄqiK#hs5g]k{BL8 h=#XNcF@/A$*-޺x.9y8}/lg@+ae@Bz+ hB֒(' ň%BJ`(&M[E49/8}:I4Uorvƣ+A^|YW`ˋ0꺐ފd> `p1b$jFh) ) !@ӖFnz'(sfWk^{Q&}ƶ şފd> `p1b$jFh) ) !@ӖFn3'zV-aximtKp,,%=/Mo<e/[3^&l-zr0 \Z-Q"*Z B hB8д[D p+5JO w:l _57HVVЄ%Q@O#1T%0JPEKPHM4r9A=&^&l-\@% \!b924mi/,)ˆ g&l-]cZzyL>p@d0 \툩rar縢I &TN_Y{i:nK\B-ofv2)pO>TTK B hB8д[ߙKpW/b͞|zþn%8I9wu=:Qb?!T!= nĸ LF!:3&l-4/ hdsF,˰;/'c ە9Y%z 79p\['*owBQR7Sn=TK B hB8д[0w15У٩X(mT!ffɪn=]=?TK B hB8д[ߙ⿵Ϗ]BI7I*H hū1>zW-_S­7{v .1>.WVЄ%Q@Wck[- 6W+bYKi^<Ŧ%sZeʯ,rP@QjB-sefԺMSAHTџ`(&M[EgzkΊ>^,1ֻ-At Iv%T"U _I& d%8N,Ujފd> ^]Xx ՎkdTHsI9yTVtfweD$]ڨB--(Iq?ՠo=K B hB8д[瞸 y&P_cw; @.6/ EBp;$uk+2ZJ;(wWВ0 hB({P˧ZvL`pkie>W 4*N~7Y%zOC->˸.FS;"RsW{6Y[FHTџ`(&M[EsKEHm?B,1v݀'_L%8d7}e)O] d9; ~ CKF( !H 6#FbFkQ"*Z B hB8д[D.:[KϔkW@_/y>t[ǚ;%=֎<2YoaJ r[z>^|VCRgVЄ%Q@O#1T%0JPEKPHM4rր6zs&ht h5Xwї# ?yrVȩP`뀿:KLg%#a Є $Q@O#1T%0JPEKPHM4r9qzè9ԋ ?m-pt hpV>_0n 5:T^=cѯ@{s+ `p1b$jFh) ) !@ӖFncP/gC(;;~%%9cd\m#'VܭKW'a}|-!%B;+q9rᣟlFù~fy.[Q@BLG=9l.FP(RB-C!4!dh-"xt>ι'.>C]tZ(QrhȻ9ڌCt؟% &#h"BzY|$ϰr+_N~Rz+ hB֒(' ň%BJ`(&M[Ef1&ĕrO+/Wxe ӮfS:'s%8۩_(%D[U5şۇҐwgc0/g!]F_`P[E/(m2'&ot!Pj/ 3btVZ2@M@2}`A1CZDH U ЄqiK#Iiz5+7.#g}IaE9LJa h]D }͘9U@}0꾛FFsm> CKF( !H 6#FbVK`)24mivʯ,{~}uT1UeK\zB-fuVЎw[N6-ꩢ?PHM4r;I\|U8^t։[I8E  Vֻ}*6Jg.~EPWdS‚HFDoOu%.䖍!wC `S*)&KoEMZ2}t9JeV1d}h>)]m^Ne']KV~e*% c]}ؔuR0fyn%u\ u w)(z* ЄqiK#`޻읹w9_osMٗ8%ׅЧSz1i^{+kag+dHbJX|ip\+k uЅH)lwLJN]%>d$d> b-`psq("Z͐HR4šv͌y3xi 6Fʯ,6S (CxVNhjR7#N'p:ɇz?PHM4r4 8x9_t枛N\s%^6N@/u;ub&u6Iн7ٔ`r:q5y[s] 9.orF̀ӟC V t2' CKF( !H.CIZl.?bڂb/jukhմy>S9TQ!)8*̾kRC0I62"DhZnv[[@pS ["jO0R@BƁ-"CEg+965y$n8%o}O&Im x]0wӳJMM &AZ%D@˂ A@P%ǭKG h̪"&y73[`h5x鿆[Q@BLG]2_]ʷb 6W+b=#AʩB0meJٴdVdW^4U\N iR0jֆVT:ICEHTџ`(&M[|\0vwV :'qX7)!.l3\,n `@0 ٛ^4MU[.] q?BW0zxT;OqHQG}+ފd> ^BKy2\lvĐfv-Ar wʉ4+%U;+]Yb2Ee*hݬmmE)L:bՠS * ЄqiK#h >sY,!/AQ,O1u =LTvlڕ%?tz$oV;%F{q%BWe5n| ē!T>= bIӟVЄ%Q@Q[r" #֔ _c$YGN9[MV~E)KI''*oVQnq.؝?PHM4r}9>5V_tN4r3`֬1w3G咷D@q@Fac'bׂL=q ^ŖP;}<%΀6Śkފd> `p1b$ av%BJ`(&M[EAc[zKG9e'A)-pH:b 2tOk?ޢ\ hU%8|?;^:] b5z|<O݄ayGz+ hB֒(' ň%BJ`(&M[EϜuac-7KBƻMA2[XxE*Jg@wH<~ _S P؆qk!A<;5[B0 @Wo@z+ hB֒(' ň%BJ`(&M[EϜuaVxN@тK3!X@>)]]¢ tR ~e1BF0W}P5bUhTN[Q@BLG=9l.FP(RB-C!4!dh-"xxAs_Rnͺ MM6ŸX睺L[8 UpP6cGώzܥKКX6K$ӈnO[Q@BLG=9l.FP(RB-C!4!dh-"xumcRVxAͶu%uK8dg6cG̯3!C>./k S^H^CrV11P@B6LG=9l.FP(RB-C!4!dh-"xg]s7t%843O-sI;ocܯ v_%,3?0]p\IS^H-Q$J- c&l zr0 \Z-Q"*Z B hB8д[D̉^6T@/i=񳙒\>w45zA *lÈB`+>*nJ^> _%,BOf>ЅˤW#f•a01P@B6LW.чB.FBR1CPHM4r I?/m7-#JX\a)DW#X+^2A.r|\Xm*΀n~S嬝"4!dk}Ez`p1b$ av%BJ`(&M[EOTORZh3ac4EP] Bխp2x\`fq{>D?%-ljBb~U>d$d> `p1b$jFh) ) !@ӖFnn=ӀgoQ"Or~x-Ih[?]rwE\RC~?0goVsܛ?+Y@C3n[ UTZ|IӟVЄ%Q@O#1T%0JPEKPHM4ru SS? h?k!^[O$߸;^&":՘?+sz`^X$owtK]tVZ2@M@2}`A1CZDH U ЄqiK#Q.=Oyﶆo 73Mx*&(AVxah5fNf C21 KےFA][Q@BLG=9l.FP(RB-C!4!dh-"xD t܁q픙U]gLE4AJI$[521QUb#PT5>ggW^ d))+W'oMa5|V CKF( !H 6#FbVK`)24mi<8xS{5RvvλKzs.c=T@'.AGj!rizy{/VXă*MVЄ%Q@_MiaA9O+`-f΍Ԃիm ^Z""xdWhq ů>Ȩ2*7ֿ1rSҊ͓d;z* ЄqiK#sH^^V. "O{e{'X#鋇 ASPlJ~+7T߼c|9%姟{_Jc ]ڄJ- c&l  |f_}jaAPgB_sBl2mg|}<3FH+D /=Od$d> "͕zDX`p":ȚJlrz/Sͦ%s&(Y% KoO@VJhRԍnAx[<CEHTџ`(&M[|.\@AMP]y/FeƢvкީCT=N, 2A0\^s=w@ "ksOȄ CKF( !H 6#FbFkQ"*Z B hB8д[Dl ^sʽ7sӟ yQ;J@ hܯ,vjpkR*OY:A_ Kj%ǩ2>-В0 hB(' ň%BJ`(&M[EϜuaf@g(nY- #g@(u͐+/솮 µ.w5Rqw X|@b}Z&l-zr0 \Z-Q"*Z B hB8д[D^t NzIuaCg@OuL,!#jG{Y gJX|A59uS=~dd  jJ- c&l zr0 \Z-Q"*Z B hB8д[DnV޻H^s_9kY8QpF4t+NW"3U9r]o]@RpSAd<% n. iފd> `p1b$jFh) ) !@ӖFn{<N Ӯ<% 򦦴]%O*g13iA#| J1넀*rZVЄ%Q@O#1T%0JPEKPHM4r59dua%KptuM,!#jG,ԚLe_*O *M&JW|tQN|  B4eיY|hH4!d}ГbH j !%TR0R@BƁ-"gL2c &pv&KԎ .r47sƠ%{/Ti]"SBjC>ʕMg%#a Є $Q@O#1T%0JPEKPHM4rJV~O?o_ xf*'~"Vٛ-8N@Na*A%8 bύAӄA(Y@#SBjCjq櫎iފdr>p1bB B hB8д[D8s3ew%^-Moe@{%⩿Y^d* )̙-{HsӒ.)d!S=W)%#a Є $ hS ň*a)24mi<9jf %%z&~L:vU,-m[={U/YRTf2_Ӓ©)AY.^Vj01P@B6LG=9l.FP(RB-C!4!dh-"xr9xx].oY-bU%oJРd s#@ꖁkח_2k;.=s_YGC@ ]vխ@z+ hB֒(' ň%BJ`(&M[EO+x?& or}G )̙ qo,+)Y4'<{%Kw©!L>d$d> `p1b$jFh) ) !@ӖFo{EO@O?sٛM=_}G h)u0$Ţ6m%]%]1#S Ói>d> `p1b$jFh) ) !@ӖFo}[#'GezڕNu յ?hZOqoRfJ爩X-#gpl)[2qҦLi},e|hH4!d}ГbH j !%TR0R@BƁ-"gߙ^ܕՑwa //z'~⸙k{sJ5vH| }nT Lj }ηt}j]TiZ[Q@BLG=9l.FP(RB-C!4!dhȣ%8v/=5gW)+" ;;~%ɜX=|'MF)4I7!rO0R@BƁ-<Nj:q{w٧:Ȼ0CF@O'~B-kAaT c_d4~᪴쭃U8F̗ _/{fvۢJ~YqrϢ&l-]fZT3H$bAS$aa)8,Gqf&sC֜QMԻk$L\-Ueon (yGQJ|{n+CPE24miw|ܻu=^` -+'Xy`?M.U^˾߅:8gȸ]A=B^*œ/^zs8]W./o=CTϗ ©b,|!/lR3. CKF( !H.f/hE GLq(?eҘ7w>k%r*;ʯ7Q}Cw8<+ a45=luOAt_ZQrgݖ"Tџ`(&M[yGss]A(w'Pe }4!dk}e(2, 61d[9[UDrNy8}_tfg0Ө޽T֒VZg)f(b`w[˲#h5 ̀[“7ͽ%8!2?x-kxuiܲ A<]v@AX8b Ԇd5'K]2>d> imN h M2s$yr2g6靟yy?D/5ik a4p'{@*QJ~n>*0Y!SE24mi--{dV jʈ9>-=iIAּ_~=h!Y 5zY|hH4!d}ГbHLh0JPEKPHM4p IY'Zy`&?Gt~ sI yZRL>[++`%6%VN_pL>d> `p1b$jFh) ) !@ӖF.f ~<!p偙L[cA 2SKJ8nO/\uZ P3Q)4 z%շ?IF, hB֒(' ň%BJ`(&M[ExY'nMqPZٔsgե78${t hݤEWt [cqQ%%dNupx3xYuaPJG Ԇ0a&l-zr0 \Z-Q"*Z B hB8дKpqsH>qЪIn Vw tFڒ  ^׭Ϗ^ 7uEeomǠ Ԇ85pEa,- c&l zr0 \Z-Q"*Z B hB8дKpfUdZHo$^UapporpIh*nI rׄ,)!@)h}㿮QN6Oم, e|hH4!d}ГbH j !%TR0R@BƁ-"WF҅t-1f3s4fd7o9OR=zl!MՒd$d> `p1b$jFh) ) !@ӖFnӬl~p1AjL),: Adv( Kz $fa >hƊ`_RG q5Ɖ%!4!dk}ГbH j !%TR0R@BƁ-"gN., )Zy`V?Gy/<)YHCMƊֿ #A85p~P Ԇ=-В0 hB4PRňB6zeo!7:MȗY㥹Vze-/kK5-=:!H#wآ@4%$B 46`4 B Iܧ]_z}:>wU*N*jo24BT6wr <&<t1ݭA ?+V }UDd8P.'Yˤ**|={E ^m ov^ 6c£h@gI}* & "BZ!D ZSh* umx/@׷@~~ŬW Eq=4֋}b~l֦I|'_.l/V/7#jzjYW֯E!ȄbI;_Z"4`  @M6.D @ZQ V !@A];]zAkkPP_M !B/֯*,KDFPiaA~:\__`>bO*7P&'K,{K#PA$Dh$1Al(\@)4BT6wr 66ζǭ5ɆG(elaf{FWi2zMt7ȼaiU=E9@Ao=2ʲrZ1TP 5<\|͋g~ZX]M#s@+#0(}J)WWE$Ulp;/U80x3&9V 藖 $>нc}L],4'e+h4P܈y{9xvJ&:"[©SVI5ZhdB0 ģ؜F)x]*մb<4Եk.:܂cxg'-8<2I{نWR˃W "ZEe>]8ٌ;J8c?c yZ!˱b1Zx ,tOJdCr#f)VRd.g<.J@6cj,EO‘ũNw4lZ!MPs)=kyt(@ixBS!h@5ks'Hy8tb⍟#haexDo $,ݭ ?諎7%#$CDxY?+. L?&cS~qůC VҒaSBai6{M6.?bEGkeHvSV˴+xFEhGk#ѤAO<  Ypcb<4Եkx>}G,C- On&\Z|O {A]hCɣ!ʐA ''>~]/(bb?Lj"藖 $>еC !F@)4BT6wr <.B^еC !Vs@ȡ=BjPNaiFF +#@;B(z>+I}3an<Gr% .a|I0AV%*A/Q0U?#ٌF}%!( @ tdCB@%rhEO4ԵkX/!d>!F+dV_ĝD л./vI~r5sX[_{X ~K(CJd[ L+^cU拋V*HG+Β @M6.D @ZQ V !@A];c(ÀT9'xU璧Yb7kZc2V'UBOB*ܩ(nPkz2 TYzL%ȶ[ljD#7&`E/- F0I}k& "B (C+z Mՠ͝\OPZX#@ײ*vڱAVPFo dK!І2~T͛]8^ + K)m4h@gI}k& "B (C+z Mՠ͝\OPZX` *еC !Vs@ȡ=BjPNa'Ƃsf5s [`lT]ᩁ%@[K+} ! TW(!.~ τ ,=V% S!žl`E/- F0I}k& "B (C+z Mՠ͝\OPZB;ȅX]<-PTO=|/ $6cJpqQld56{8y ,/_1dBBL*jo24BT6wr h< jv_{ [az"l7(EՁA{˟2 j%X hHH}k& "B (C+z Mՠ͝\ӈ8*ڂcн~N O\8xEpq U+'O-QvV^2wV ^\-U{X:hHH}k& "B (C+z Mՠ͝\ '9'@b!Il'@"}еC !Vs@ȡ=BjPNa9ÃT9'xC3`B  N-+U N.J?')" W4YY$-&m Qр+ߨ 'c 4$>=ټl+76ζͯ Vlf& Ūd+Ҵvn}_V(PL ?A$(9tXZˏRQh?Oh* umϛ|z0Nr bZߧO-l9r\۟ *aW䝼E|YK%AB;max ,t/XWꖣdCr#&2bjyS>#G# '_gS,(gcV#"l&.{Hn,۹%/m Mՠ͝\#fq0o 5ߑ[pTU!6{l!%﷪+6X jy;'/|T:8OeR}/ɸ精uL;8 Z78y ,t>BʒlQ8dCr"F9^*ݳdBmcJ3%C$AnisC3 %2IDi;<}XO۰qM:~cC9urCjCsk:ř -o 4$>y(3"-+E ˎe^bJPRQl)@X zܳ Gi#Sa?e l$%QblxG!m2x— A+ !@A];* ˫3o{g+<1|wȧhYcU\M6.'bN~KeKd&:mtj'(~zhe#[i`T+E=(Qҙ+#qN|oSV'4BT6wr=(eǬ'K:p"!p9P*E|J 'jh@gI}{"%4Gbp-M6.7bKH3Ĺ.y:%V9ErhF"ql& $RI3JPUӊBjPNδg.FzY|ͱz!@hڝC4x ,te-rIBE& Wveh~$ W,OSSmЌ ݅1c{6VF\G?D7Jwze%RbZ1TP 5r6 | L @| @g0cڡɆ…VF#Q V !@A];%@sЙ@@4`$$>еC !Vs@ȡ=BjPNaւOGq+rid4t#!1Al(\@)4BT6wr <.|%e%qYt;4]XUTh @| @g0cڡɆ…H9 JЊBS!h@5ks'װS._\"º}o ޴v|ujphht#!1Al(\@)4BT6wr <t\#Tϔ)͙W /Y)ZSxrnAT#:-/dhb%Rl5eya;VήCvۢ chYX @g0cڡɆ…H9 JЊBS!h@5ks'װ$r8cŵVR_#Rl賂P-髄\YuЖEƒѲQUG~ֻ1ϛV%1 4L(\IEMMBjPNa'NCq{]}K1o]ȠO`mpdldg۩t !Kp; {a4 @:KbUQ'4P1 h JЊBS!h@5ks'װmM=賾'7>fəC4^.T@{5|9)?FLAm֞Kp#Ψ-7&7mLvs>x17  @:Kb];4P1i5D ZSh* umxl hK/K@;ߺaY3=O)]7/M 4$>еC !Vs@ȡ=BjPNaItS6+y%u6aFcY4e|-~Ӯ?M7Sr _N£h@gI}k& "B (C+z Mՠ͝\O mIA&'@%8O) V%1Al(\@)4BT6wrw7.dNuS-<_KLǩןJY V%1Al(\@)4BT6wrw @OM @|jK=陌rI}k& "B (C+z Mՠ͝\#W>:%@vzcV.'\ptjU п׿t(ݙgy%=+x ,t//g+(ɆG_b3bXڞl de=-J6~Hxt=C'UD} J1ϢSB'M Mՠ͝\SwpW?zy"1}㮾@ Wz "@,yV/:V%1AGVœ l(\nĄgB 5)ʢFYlyUZiJтk'(Z! =Q)c1{QzVz =h.Oh* umxR4Nv8sJTc)-9\pYѯ#WDWYm=ȧ[ S  @:KbP)S~*4P;1(^iك̖ae%E=uKMтu,Z!Mi>X\JOA'  Mՠ͝\CSv/'@γo|_m0%1;iEpЖW{4'_WYw6ҳ;%σK  @:KbQ Xⲥ`dC#&݄ʸ\%vt-[&Y[@q-)u5(i%JlFo}gk6~hF򐍦oӎKSh`4x*{ W%j @ixBS!h@5ks'݋-5E ZW/=7>sʵd 9ĹG]Y%g;<9K=x ,t>l%4+d:ipJ -jH6cj,\Y)d)C3ZZ!M X<5JeV'4BT6wrPwFԋK DZ\Uso-4./:^0yhYcJX/_dC#V niLSl=jtM]yӹ7!=kgh`T7z~THdS' Mՠ͝\SW>9fr S%4Wӝf;qR<{hYcڡɆ…VF#Q V !@A];i._,]A>J~˝<ٖ8I< 4$>еC !Vs@ȡ=BjPNaG3vehucFs @:Kb];4P1i5D ZSh* umx\ x_]A>Fugq e45y|$x ,/_1dBBL*jo24BT6wr <^*ž;o[}A ԀG+ΒhU M6.D B099TP 5,\|͋g,PWNO{@gss>x17  @:Kb];4P1i5D ZSh* umx @OE @|t#!1Al(\@)4BT6wr <9mt]@@4`$$>еC !Vs@ȡ=BjPNa'Fct&A>  tdCB@%rhEO4ԵkXi4t#!1Al(\@)4BT6wr <Ӧ-8gy锖k阵duq@  Y@vhp!b j9TP 5,L;tb-7o D#8C^ @g0c^ۿˎU ,XO54Pm^;aSYQe4Mfݽӹݢho46X*)sDtRZׅ%DQ"YWhvZE+ !@A];n݃5/8gAK"}'Ag^qW_g@4`$$>SU & 13WPб0RA"i(o"*[ӮҤ)a9l#F#A"Oh`T7\"Oy,|*nTv[UzU hOh* umԚgi':/=fӣK"3ggӣ,Qw. Yȕ8 nZ՝d1rF6KyQ觝xچsn?lhU疟REE&yX;o["\p_QhDJh,)5V E+Ss>¾As t-P{ZUZ>, @FBbPL!c:M6.'b&KR3,hiae-TC3Zg6"Y:\Z!MI!SU,J#X@+hxBS!h@5ks'ДYnlmBнQө3h# +z^訑k\ $w}plOפmЌ6d,15 VFu#<i0%GX@+hxBS!h@5ks'oM"g 3V\jչ|~r6-&N_ׇ\ ̩Ky4͂@`Uȟ3uc`R;θKꕯOYb0GϹ*3z(4$",iRZ.Wis22G!*^%q<#̫KqSlPͳ1yYW!ЊBjPNa'\-8fykWߺC|T[fOJӊ-/ }X8MNE/E lϨj;Am Ѕf1FJ$hЗƻ7@T<.D*d^KL.b\4OoY g:WʸV%1AlZB& 1h2:RZ}MJk4i[i>kaf4'="=X h2G@OU<%XWţ<;- Mՠ͝\#e>6B=tz ŊݫƅgPWJ%.1jW#Fm) )^c  蹛gY[&)Y7%qe *OCEp)M7^`XWPic(nYT(,ͷzܣ^MG+Β @Va.l(\nS;ZIAPh穰1lom1OD*HMºM*sTB0<"L<WE8,vъBjPNr36/i;Evš-+g^]qbXKD4D 1EQBɅveN%@=]iT60Eo',?U]-5o 2=j7q5P?CcRN@J3h(j]T^3(m,~";D pvͳ3ةdv&IcXt#!1Al(\i`4r%rhEO4ԵkX)(|ΡlB2g6~h)TFݯCK$DK})ԠuiZ, )V[L=n-YJ_(3N tsrS2nrRdW81CXȠa|)M*̢~{@PK4+M(o茱[Z]aZ4  tdCB@%rhEO4ԵkXQK4C+f{aty@b `𿄐Rf_; , @FBb];4P1i5D ZSh* umxܰWL,@s f9\H;D4 4  tdCB@%rhEO4ԵkX੗Iނ:  @M6.D @ZQ V !@A];zB, @FBb];4P1i5D ZSh* umxAo5w,tS%ķ-8phHH}k& "B (C+z Mՠ͝\O)@γo|J hHH}k& "B (C+z Mՠ͝\O)@vXqU9(4ͳx17  @:Kb];4P1i5D ZSh* umx躀 Y@vhp!b j9TP 5,4 u:  @M6.D @ZQ V !@A];&. @| @g0cڡɆ…H9 JЊBS!h@5ks'װ$ @h, @FBb];4P1i5D ZSh* umx躀 hHH}k& "B (C+z Mՠ͝\O)@v!@P/  t/x6ul*l M6.?bE+6-U.Y_4vn{}OvRQ[@G({`:V*PUӎD)XR̙Ϻ4; Mՠ͝\Sw hHH}U4WɆFLPzc SDLd49M"*[ӮҤR\B̤iC72Z!Սz.|~7J}UyϺ4;- Mՠ͝\F-8[p| @g0clR.RkɆD,%K"Ϣ`Nbih 4ewʾV.i GB+ԛ@khxBS!h@5ks'Д4z Ї}[}>n_#y8#7?r;"CyoiOw|N?ݴ߬ҍj3] 4$>нQ ԩ9"@Ly-Ir"Y +9plOW6~hFX ܬvje|*V%1AG i& xE ˎ-X1N*sJ~2ˢYU("M^{Vk?4.8xZ'ny#$"Ģ?=z7dz|Sv ͇hYc>WU 1-\dCr":RZʶ@~ak*5sSִ-4MD?4#:g OR:$i)*UYT!],2ㅳPEQB.%H/{CS @:Kb!| GɆGSDt1j|-OAmdyڕG<;+|0In[kScndB0׏%ʯyU MpLV'4BT6wr OM_9oy!C{- ~T%;%lqHUui36k]nyĩJ`jh@gI}k& "BZ!D ZSh* umxDEZWeVȲED%S"ΜJhSl"ItW3TG+Β @M6.D @ZQ V !@A];&џ=1jճJ+'ςb ~n΁]I' ݂Ci4)V%1Al(\@)4BT6wr vV:Y.*J(Нe:~;MXUkX=؛W h 4$>еC !Vs@ȡ=BjPNaI;%[pVTy ˎW S\ V%1Al(\@)4BT6wr ҳGG|etܼlh%= ,f ɁG+Β @M6.D @ZQ V !@A];&9( @k 4$>еC !Vs@ȡ=BjPNaI@ `jh@gI}k& "B (C+z Mՠ͝\O]ԀG+Β @M6.D @ZQ V !@A];&. @V%1Al(\@)4BT6wr c4c{Ivt(5;*:)<,yRA=Wb<4Եkxn{cI>G-(VRcQl3P|Kh?g2>so^2S2\i%rx ,t>B ԪH ˍbL(_V e*229ˢx7=YTiQ&s nknTvi.Dg]b<4ԵkXi؂.-8 ,cyu+ʬ, l/\6W_rE G-SRrPf$p6R lѵHɓg) @:KbPbJh=^(2CEV&,䴰h2ORhfI1 nJz(xxUbij2Z1TP 54e7 u~}gTg[+Žѻ-FGsyՅ>CPNh)ma]SM5Ѿ @:KbQ ,*jdC#&|PWJi%(P' ek,{S&F?4ʴ* nbKZӒ}R(O8xU"ij6Z1TP 5<7 uqꓜ #:)qGZW-Puh'Lv,[8 ˌ2%+B tH ˎTQg ^hB3sr7}9d{V(m(wľ0ϳB0D%|@EJx5PYU4V'4BT6wr $ @kN#9M|9*VBoC!d EBdD.G(,R[\g1ЩSJ膁 4$>}(\H ˉ݌Ȑ'xEE4G.e.RZ31eMۢN ] ?4#yGQi`4"ǢEWE@hxBS!h@5ks'_ZQ*]`űsh>̲\tɒRKk, {wJTTAOx ,t>l 4P܈Ƭ ZjHoey:%V9Erh;28(Z!MaU>VƢ=>_:szY4;- Mՠ͝\CyӀ]t9ZNjQVYWK&BDɌXnl]X\gt˸UJCI?еC !Vs@ȡ=BjPNavBӡO`KJwO[pV%1Al(\@)4BT6wr 4hYcڡɆ…H9 JЊBS!h@5ks'װ$:.@o9S=ѝ͒K= @V%1Al(\@)4BT6wr AGEI<¿U{hOh* umTlg;,W9k9DB.co^y|yQ l{E(<)ܴ; U,wᲹmi{qN+ol6-?L le~EE)elފUBKG*?}\шh@gI}{4*ѩeI^l(\vĄ:.U=V /)\@_cJuq7VFu{II'HĢd}U9/@";- MXܧWs(n4݁6wrsV-r}4JLJHU?9<7t1\( 00ʢ_ =ej=A;QIՅ쭊BKAP-zΉ[FG+Β @#4ɄԬDSXz`Kb X4P =yěfe,[h+h[i>kaft io&T@,J*/@4;m MU A];F-~˩ם՝m陌Zɩe[p(P+H6b,TFN7EʣlϨj;Ad m 9#JwLDBkY }9+n{#N tIųQBT~B(J&2)o'ް)"Re,|F\ 8⸰x-P^,mn.Jo J V%1Al(\@)4+oUPumxD3޻<%j ^z s*嬐|В #*.MK=%a7Ŋ#x)PHS~vesL~ AGP1Ȍ F̷XҤ+O,% eBm,ф4" @:Kb];4P1i5D ZSh*P[n[pPNaI4Mn.i[pL,kG+Β @M6.D @ZQ V =-܂=iks'װ$z ĉ'jչ|29b4>itYck>6 V%1Al(\@)4Kՠ͝\OWGs @ 4$>еC !Vs@ȡ=BjPNaIj %Mj  @:Kb];4P1i5D ZSh* umxD%zloq|-67~ni ny|֝_[/竾/D+ڗ=~LРhYcڡɆ…H9 JЊBS!h@5ks'װ$*c E8P#W_nNSK,O;|Jgɳ))]tmIX rW_ֻ<\ʪPibQX8AVOԀG+Β @@SLUZ/:&W[O*@o#dݺus FPw!(4b~֝.yl t 5,4a?tg @er1KNذqB>pYtU}#GV0$ƾ|>"0I0nE3[jBVkk)/~񋷾_T,Ri-ZÆ {POƷ_?|WyhO @)}Wҽ~{Y븧.W\q4bm=@SLof=}/j}rjԄ}Zf2Kw뚕]ZǂbYHˎnRG653J엝DZhm춡.I쓿HshHczƣh@gI}t֏Po-O GQӶ4u˵'Z`$) u%Z3[DʎojG}veЦ^Jx(HzT@X^;fMXXhL"j5!>2*W3Mg+Eqt: naå2LTmRa{(qW7_ )$SuyX^~/Hr{AXivp Mu @).@ ?y^@ 5TxՂbyY(ud{{ _%B aEs(_F cg6Nc_M_Q"-&RX\] ­gAXf%\sc#QA]a.T8CGDȔccri˓cF'"DJ)LJAScǻFJVYvyfBt).١2p 9^sQBF6+* )$o#$78{씰{A43qꚒ̄0Q~# @h@t/F~D5m%CG|\lcQN NF+!@/?'h!1 eœ_:/}d/Yl8KO:R'3ٺu-P,|͂D &Zu*-*mTv)oP&J;KPT~ 0KiRQ10 J4b&%ĿZ?5*D!f%yXWiɾ}̙3{;v˟M5~*2s0wd%TIbc fγJD)iIMkRYQ.Yjc k 3՘QrZۭ:BgMNa鮅vVm=KvmO; S<`iF3i{#4'L%^`W1wtRMzBQ. &DRbL]|m`~Qc_M+I|N$O6¢hc˖-_|OJՅD &ZNE*mTvpn h92LU+esA?6 _5Meǧb¾*r !Lv[rIXu]G>򑏄˟-dBa;)aNEVkkncݑ]d{5mdFʫ2JC .KI nlJ'$c mŶd)2 Ӷmg-)\gY s"y#*pc gw,oJ.A},AƷ@- h Z-mOQNL^W$C=<xz%#x:n m_5ņyDP7ohŴig""@zM6S ۓ\(s%ĹÌh_Q}{%Qh*QRR(C7m)l#w6m]Ω1S8Z$v!$CsYx NnģpХd4iW:eiEj9Q<grFt6{/{#"So-6w.Q8zI0nEikeOxNSq͢  *OSJ1 ?4Q³^mf4'/s:W;#nF\5$w .j,"]H]aЏ8eSf 1۱Wˡ>Vo#nxѠoxl_CElR,#]|睋jcrwj' La|d>t U+{S5QKKb#^G:;#;@FO]3$j7Ѣ Ɗ$]U>QOeDq"#,b`Xn[r..zޭJH5IFY%@O [!*ET_ўaKWG>?)oW{m0nYZ0zKaە)Vf4a㚬dO轢h8:U7[_*$sʄdv6tXc]6D!}Ė,v|LNI]U]];a9m'kľ1m /qm \)l| k~laLj L !SÎ$Ô[eG)-<@S@Z!@/jN QKKbKP/Ӧ ڋMxR\||BOc*}s.2ѫv+vuT%]L gPP$@OQZOn"^Q4\QɓBe˾)ݾ/=KvBδεieW-D`,=}|%ڗ\7:;5\^Mc43.Oߤ: ".mLD3\ [>VdA_˖pc;hL}=X#u^WTcQ_GdVBxVsG{ &$h;`*Ƃfݼܝi_g~iZЊڼ-jTVkwѪ-R]-։ڭۿ SP_~d'9]%jqxk?gE~-[wĆgnK|@l3s_C/Pd>nەپ{^}/髖Dk%1UCGƵ>!xT7f@n2&Du `PO2иk(d>2Xi c, ui[6)AfonTӄ|ڼ%ӑjd]jZCz0jY݁G Ww;Wd"l%w?'&'^O-x^ F*_'2kٲEwmSTAn[wVMlڼo;]O?Ke~{Ͽ*;$ȯ%zs{5Z@{I}޽{4 j5hѸI+) 5B~_lE#D۶б*7nO55n 4'v`6)w5F hbM kaXj,ӰoC -ѪEk' Szǟz12b펉Wؤ;Ҿ>oWwۓ/5IY Zz.Qg*ɯeq/ Wlx/Hk||]Tn!D򁽯'~'^@{I}4j5O,VSj+)0(nkӨW# @aXrnM+5m=NӼ>ΆU+ǣU[^{UcyK}>} {PQEݪcoU Žwv莭|MR°4r֎/\$NU9n|bg٥xQ]Rrl3#/5[_2ȯ%d+ݵcM|@Yغ2„SiY-$ƾr6l{1a lmIٴi}ٸq#Y7z 9r0e@&š5L5MiE@udմBmXht"@,8m?ݹ3XPQE‹t 24W~9lkY/lUW-RǍOZ>_ A_Gm;~>׽xKTo=ݻymJEY-$ƾr?<@PcI0>h`k[M" #*;?1n6諒/ݏx/6*%ɽEK4{ࣃr=}>w!PchZjҡ`@ڴim ;c||@ݡk@'hu* k+@\]H{EY_HƦ$c*FyDOK0zۂƭUm 2JdJBl5mClV.Ѡ^5"@hY_L⻶}rӳ/Ɵa%w?d3MBE~a ?[;g/ ogrl ۷ `o-/JB/LY>X ˾/rf̎=!jIpJЍČz`е?46BU҅-XزfQ(Icf j7ɗZ%+Bp – [V<~dhJfFGЯȻ_1z7>'*H0 g&)kaX ԎG>kq! UB6>?_k\|/d}I?ZÝWo ??wKSVK),=ްt3>:*94РXk -ۺVW:Oa>\F3[U Vm |nJgÝ|"[F 5[/Nؗ:vݿm=7;^z]?)~& 7>gߠҰ EAD&kh[nzbOl~abS/]^||yv*!ɯKw6R|C?Xc>@]'.@ D^N+WԫX,OK2(6s PiIwhe@/ =|.jh /YOm4HZ֢Y:.}?~,wU+rzn ɯUqcbtH_g)6l\_m޻]]kyzO4?߹gKž},璲Z77StsI} tD[Hd\m+R>lǯݻ F4"@߿oW='*p֏'I>>0~(k|nNW Z?Zl=nxtZ[ e{҆^|={w.erP=.Z墵[_bEw9OrL@n.G[% t'ƽ1*o*䪫)&2C[!+>†'YՐmh*I O$e- k!nO?k;論~^a_9Zgx%z.sKgb#k$*n'wteQR|{hI4Urh>"n_BHL˿FWE +X^-]$1wnN MG cƟݱ{ 'vkvM5^;>|A[xњ-|")kaX4)uȯeybb/5?I(;wO|gMBvZܟڇ ۖ}9zsޱg]>-/-Z e@n b| @qX£U o o/D;9EOz][$DR°-?p4/rkd=@MG{ݛw^Ů.TTwp][/k+$̟x0íZ<쮏]W<^ s9av/QvX"v/_[7tsI} 4"@OLLp{.n>nڿmJp.]s$e-~|nT(;^}-+vZRW-/K+o죃/@@ V/tbd7 :pZZm-Ք  L~Qi&j={v BEQ\tM %kl94he͈ص+kg4TEr51(#oC}h8J /t(c4cmڴ< $ q8-D-!Mo'СԘ[G.@$ፃkآ0Bu5'̢4` k O`Q_+4`㍉ '/0FF`' )N@to|ā8p8pQ`(q8p8pT8Xj4[x%8p8pl @7t8p8py.@@Q8p8p(xRt_i[ٲ.w5IENDB`asammdf-8.5.1/doc/images/statistics.png000066400000000000000000002415401502633300400200510ustar00rootroot00000000000000PNG  IHDRY0sRGBgAMA a pHYsttfxIDATx^ `}}ς"LiY&iQK,'% cSS˭լeV%9ZڈJՓWv豬HDnFrDr W, Mɢ( ٙY`w |?9vfMOO;TZ/E h@UпQ>v˵f  Dlx_L84ŜMKV.ZtE?W,-]A4^&^(&692_^Z+;͋df @ G̉ybSgpXQ sAR@UKkfW,Xbu󢥋b~ůs諿sM]6\q%rSCku *Y.=`CF̶P fw8pm3hQ 7oZWyESSG6iiz[-ob+Ko{zWj_K֮\zi i^wX fs@(RwsO4\.f3B}L]ٺuk`B N_bQ̹|es앩.^x[.f&y?|5˦/_>s_==p>L֖0KQ}#==܉'z}ՙ\ B0^,/ٙ YN_|Wߺ(w ']j^;qҦ+v+. sU-$"Da#Ł}>97d~~onl,m;+>kXӝD[32RYLȃqFv]Y?;u長. ׬tμǾ͡u'ɷN,vKckgN<9ҩAx*BD*TFz' ^o觯9i%- ض ?OV7#U3{Ge 6YQ# \2{9}a4%8`T=?brv}3zH"G̉ybtc3,x[V&]dVjobI-]+~+ğX$R\w++]Dn 1u \nQxVekAi8 &lDgb/!&:?f$y޶\.;UG ȃ @o v[`Nv3;=V^Qg/Lo]ˇmSS߹S]귗3o'*<5E\%)eJtu F}U.ݼSՍ0a5+ =:CW L"/Jŕ(2;O Q{Xw[ws`g}wn`] 2~[aiǫ=3g\|#㗗[rB|'`ߝ8ִڳN֧c=V Zauݚv<3Z\%rI,ƨ|wWR]gqi}a^TBNe0fN]Yy+B=іAw5gUIC7(_̎R|U%8.L;?xK+~i;>/t𢟾򳦩ז:v껗/b')*"MKuG,(\HPƒ'VZpUc6)t,zRw@2~eo\~WM\oyjן|۾}XΟz/.:F3WĒk)fKȭ|XMu:?D /.ؕo1H}&a/yQ REjz Y8eҴ_7m<%8qqٵ?u?w)ܒ_{1aE[~ƫZ|>lsFfʓkI]g9]Y|_~P- :'-X-Nf!/^vyõ^NYjB.%ʘ6 Tӥig٢ؒEE17Śb+Z뇮sW-KԮEMKWʏ]5sZ@,DAj<2 ~*}Nu#:rĎ| 2f=4MU =ztܮ#RjiՖȽ M^m"ox/<?D@O5 !P^)S^O=wӎsY?e٢KfqZ+N_+N?BU8PC]/x!@n,qpٻgAhHDp,Y[BrܢPUgG @44G @UN4/-]pWŚ&Ī(v5\V"A=UA6{Ǥ-^ղKYwM;T1!d׀rg̿-Q vuO TY8$O=-jR4 VFY 3U~= >iN~NO9NBg(DŽ#mfS[qkw tA1"em]mP\уQGBts:M`9|e4["uڬ ]cs]8~lɚo&Ī(v9|ahhtXѲ~v9mq$z{GTLl9qKm4L~?2,её\,6=jppw؝^l $ߗv3kx#AbT\p%5vrtWWw^uUD bUl10 Ff̐Mj+U x L$̚bM=.&&9QxzzsPϜM"UdN19::`[x F0$W.WH"_Q=K^g?}%Xb\4G@`97X2Zkw'40s,e9}4zzFzLBTc ͗;;zzg9GZWV' )|26s-6}K|V4 VF@@<9蘊R*|sÐ5Icf1[C,ߗֳec!ݴtbdXYDj 9ru 8ޱnE'$6u\n:[D4 VFYf:6olְ[.n]骕"q Ssɉ]j>ɒMSGy׭[gV,`e>r̛c U5|e\O-:y}slbA禾73N hT3hu50@P TEllllf q`ZnPIYСsKKK@6+W1+6::jVƍW~ܼج[._v^~?'U|[n=xYiWue O=Y7>|ج \#Qs;*:Y YF+onm߾}f"N@Y!/Uͺr+g4.knOjo}}}/".:" ˠ*} h7KϤRQ GGz:BIt@GXkܗA&}7.eUMˆ#⎊n zg: f@Gy _$ёNmh4~9|R熶gϫOZL$-1t}ܥ76+W1+6::jVCgN*ۺuJcz1<5uɬWƍ>lVnQQQ~c/]pCyt23a|m(;M h@g@˪:N&(g3J^+Gy1r;K&T^,jF+gRϷ^.kM-ך-@o|)nY7Pè0]Ԁ(ݝd+TrJfTLR=PŪ֑z#OL.u\/qJ yL3<~[8-w]<,Yv]2p.||)n`S;0_zRzQne_i&/ rk~;YnrW3+qra;ٟ˾mΔQkwL~V :wͻTy]-z\e9Ν]߼̬([3s͗˯sM@(g֖0K`kxX 'u3UKuseFVF AnP'֯]eysy;Co^vYn&_6_ʬk>dT{Y)ȱ=~s͝;r1B>{wc{0R1y6{oss̳?ݘڳSn/6GSmgEC\T?;Le?Om}zؽV/3;ޓ0A}Esg%>ޘ2Jpx@S#Kj]{Z^Ҳc'oY4, Cn<_Ĭ/bv,81YaX<74s{SG}~qp^h_aQRc>GƝ0jVR}>'9rޝ*)~( U鶸3WrYQvgX^>Y(c)4sh=Ǘݕ}Iᣎr}чeU-KuE̺4nXMĊyV<ݰ瞓m}f7ªn}sTj5 [ƸXg&{۴?ȽRfG{ <;ehM̀]b`7&d@%艺7zgêw%ztL!Ե0#S?ԑ oiUYL!<-W{a=JUoo~L6!sajqUK{gJM}}#j4_Ĭ۫2>fOg6xohRPn񹽹i~߼.הov޽jsrϞcjA:ro[r}7Jb<U|_.qӟ\҂+ިt["1::"3:(Ko%.P_|)nY7@YVO,TBЅzѻKީ#Gf4eu}((Ly}W7˕m)| X²x8Wg--]{%g4;DpOBs0%y!sϗ2Ku30|Ǯ IHdw: Ba nƽtfborͦo CsFH}eL7Ǟ\A X|˹̊]g{Uytӟ-_ʬ/et0KS{{AgMwo`Ѿo/Iϣݫj->\{$eGy5?:+ zwn8' !~y5Uؘ4\:coEAmJfev b]4_6_ʬ.s ,$?zv;sϑy~c[o[#{r~>6B1 7xZ8fo~[y^srվ)}]ޑUfB܀H?P}0+A s^=PE̺"f>Fozd2Swojpl<-P.-х-6f{[]6wmrԡ7ݸcUyZƫ)txS~3Wۼyl 6,?t4K4V4_J=U µC7?١W[ϛEᵖu}tgO E76{.ho?M棒ts{ |MwtfedRJ*c6/bv4`(@wυt.f3'T-.tgRlЄП4f˽\$A,߁3%]=/w (C 0KY7_6-R X{߈YT蹛-ӆ/SYT#f䯯q:Jf:uK u͊WV"7kE Z67mTyan&e&NReөLR ],',Y7_ĬD GtzIUs`sp*Bg2NP~Bp?ϴ'S 9}X~]eރL&o4+{KAuǪր%uLJ1TJV+A(rHSu|s򺞃|gv7X87 eX&WG!.}5Vxl:Iv##0KN̺RfLYztd͎DbtԞ]Cl$&'$9rt;Pw6Kj̟IOni}x:mw'ȤUjDnؒVdy$E_}eYSj¡9CPC')n`~KA,K3sJv9]e]T ;БIQtw{~K{FhWX||)n(t`JJyx\8!ϤTKg]d2Q<܃|'ʂrHnkk>Fn?wfW@hZV?.-ȟ%өCλ\H2ϼ_T2+1`rbc' `sK*%~$3\q+1Wk3=9`3 0@=En̺> _7+Pgbccc7om599iG&՚IVFFO3fihoN zҫkkk5+㡇n~CC'zmݺf1=vd֫cƍ6+7ڈ~G]Y,XoF|=Y; W^-]oރ7v0K^_zI"'fc{LV|бSo]~ًcV7楋N^*[,[i0;y`E̺"f>y| #{U }Ӎ8rlϽol>fX@ݶk|>2qћAk_uѓysdа|)nY7PeVtۍ{Jг!. @n[N8[u.!_|ϘЇn߾;??t/^jɿ rg uΗ2Ku35{WQMz$g_QU@d9/[0;m ZxOO{ٚnױfa~ SmY7ݓ {; <;0@µ,m8/_ܴHt\<h-_Ĭ/bvhHޫ'#MUFcm d~ON3tlUj@J? Ln^jK_zĕݺw~᪘JKuE̺ޗ{̠jb2Uݴ*եbccc7omokNJ;_>y?S/Mj"#䤿v ,éaROzpmmmfq<͏?~vhY[sfOgvA^c'tL4;O65Ћb+|nm`>n5]y0?&]_Y/_uIX׮]m_~?7Rf|)n`sυ߸mXTF|#o>w٪lY|UqLn,/e@ZX|%M]DbI"S ,hmHgͪ`)͐TFoPr3-Ηoˢ>Q:~MW6zٔ7iV 5`>f2N2d23-TkI͚+H9Rys6[&ؔIc)&l a|)nv6e]_WN?yᱩ ֮XlO:+YQNPwAdd2Ś\[x\d2x2l5zΗ2Ku3P Qg.wu+׿iuEpB@@ǻ!9؎J.|c=9(}t,:'v!52Lf`En̺>tS,v/[W.օL[ :DR fIHOVŒgq(1ŎeRdhn]6yLJ9y1拘fʨw\tѯ k]8eT" tjʴ6&PB^7%vdZ(cʓė2拘u3P?o6UKo\z%eP;ۯ?=Y; W^>_1+v0K^_zI@8h`!EWV1D sv6_@@/ef:D 4_6_ʬ\llllO&''R|~L}3)YkkY/ۇSf*fFGGJx衛I^e[n=xYiLVǧsRTw۾}_̬#Dibb,y}S?oVFZZZğ֭ӫr3H _H-@7:(+.&EdOܳc%^ą@GtDQ@GD Dhh@GQN`8G]?#⎊:"(#"HM h̾h@e"f|L`^f ;Y7_Ĭ,H&ެuO 4:_ʬ/et`|Ǯ Jp/bv/eP4_Ĭ/bv| @o+/L7 nY4_Ĭr s?(Vn5s4_/_ʬǾY4@-^(2*5&sy `. | *o@f`C^7\掫jw%T^6[.Oj[%SS1oY7_6@X}Μ9cVfcA'|~HHz&f/EF%wYA;)6Et*J{*/6Nę# Te_OjK5}0ܓ4BTr vw"UN6l/0 ý]ؑuz|)nY7@ݛ?{o|f}z'z:GzdDoO>Ȱ^J"(*Og q|Fnuzܱs! 8L.=Uw65Nf]Ebatk5{)>(ao.wf==msn7[(yuB =O5HǷ@74Ku34y@?_W?OرlD'2F5hksFFFZ^ZV񄧂я*:`tik\Ļg.E}b` ,!+#Jw<қSd0QTnZM/(pn`}wjS^Uqyx9NxX_=nggV k7)xy[nQEȧZ]Lnv1o$O0;sys 7;A+9Dyc_Ko pYe v/½,;_6O=fƪn17/{G> 17u@u7ohϺ= _Z[[|>6+W1+6VtƮ͒W5 4UuփOoǎᩩKf:6nxap k{ϝ 7m߾}bA[7Pibb,yTʬxZ;֍Ū\VIfIMwCGhAg>4H[7) T98Z,,x/ϨdQ߀u 8@G(Lͽ9gwa V8$k,/=Q'_{<{tx+F}~vJ&M ]]^X7]F=KЍnfk<0kL%.t]!;*" 40oDг,fR=X|>k׮(7Ng+A,u,-kJ[_! ;[%V-T#6*_gՕVpNy]Tj]8Zͺkʹ4g,IVfDPK˥k`O, ϑlK/^׻ǭPu+fE,>Tް:63F&ia3"tGkkk*#'A:9N,_#Y W\C E0Fnm0-wj^>2t-ALJJp%zdMk^o穆\l˩ýrҭ}|yAxlzd0Fz iLÂDQ[(Bh;nyk!/-,612v)y9<,2ox Ϯŭɕ?3 Η2Ku3O (:QQ%Jp4r54_{ŋ ,S\+;*"JpDD ((%8j_#ζLBPFT^gT4w"s_.>PO L%dPe j<:3\9ט/L7"fpL{̀NvhUe̺"fLhX̀O]̺RfL_|a6ё:l5}5x%K:Xb!xa\{*O}"!,!+<0"xaD<0 B!CT&9v2ZX܉vs'2 Uyt6Nxw|)nY7U^ d2q;Ih|)nY7AY[Sl5OmY7kS^NZu1拘f4>Iv7lwDИ 1Ηf:s-JeC~ `*+Τ_|L`^0#3|)nY7GAkǫsT$箪iY)ց&챋}x?!0k=_kzDf:8Ί=*R7ut@"k|f'ьg%M uLjw{*;-_>WHs{' ;!P P?Z Ӝ/=bs D[HtY͡ΝK70Ӗ^ͣբ7 >ż,0㟝Kp,vo[rCf5oΕy;Fp/%\z$e/9|AWQFKHq^Knw$Gڬ^A |r%{` v_u!w5l{ >$P0w\UW+aVْ7}R*mMIwns{Mq]i[BWUrNCNh1 g :۷̙3fe6}meˡ}_*=sٻ%K zhC[ܵmk#Wl!t^g}; qg=Crrs{/˳SOеo8.ZE[>p`nBz7*wwosoT8EM.$c)a~ݻw0볰o.g޻we'&Ж{v;ư^ʖ-[ әe>Cwr9`G;yceWa/UΚ:LC-rqΝsxwUn6A]ܳ%o2zm>DБT̑_gGl{E- %o-;7v-w?UqC_bzU 4*]"S[1tZEw֬g,ʪ;ؕe^~~ԧvXLھ-;>E-- ʌ'<~|'P+%l[>JU*%?$)WQnF}>wl2j|92 6km]X*c};Az^Ԗb b2+?fA{~ܬ _?xB@wtJOYVᴬ6vl"̘MݍxwwRz+E rBSOx wu4&~qT6j0*o^jn!2*9+)TbA"vwayػ'&L2m"Ý-/Cd"ax_GY$뜰q7s(u}m$$qh׶ Lb 4n)/w_yU?{e'B 0[ș|m*ߪpZ$"u7r4RzƠ{%.ʫݝ_ԛ}}Weo(y_Ė{Jj77$Usױ7nٲaWEh o?{n4,5΄u U'f\ GEaW*rB"+NgUG?M6q:x\bBoz(cT=Mz]^R>UU&J8"" ثd0U'\K&2Sw#0\3K|[ƶάJA''^b7VP~&r[FuɸQg >' };$x,kGNvޅN7DG/_ :NW8}vTtضK![̳L4׎qd(*/UB)xϨdF}]"T{bTr)(J"խ VBvӶ&AW,V_8ZO u@Y*$l>Z1B>޻%ïKqM׍׶v}Y\VmQA[rk@gVZ 'llS8ȴD#{Xu]NwTor^QN(U'Z"N{5[vҫs܂WÐuJ(fKb_3T Ͷ] MJh+Z,A\S痍 H%8?ypi--/ͷQz ލ׶M _̜ZyX..8nf 9wP2c= z׮]Q E9H+_P>Q-}*)CfY%NP@5aяY2S^koqJ:O;/]jҪ5٬{y,fuuYWtjvxwƒ~TGAbͽ{S}@G,#yo~j/=?y[0|Ǯ ̩l6tnēɸb?򑏘p]꨹E0r֤?\-5D/3}!RT ?meMιr?.5 _{b4r<\uӫzE&4X8ETy%{;Αc1U-5I]8Ksyi[:˾M KQ}hKo6 1 w-z CyekwhΝ]߼̬([3TNllllze|||ݺuz9H6ё~kĬ #Ljɒ%bmo۬(oʯ}R3ׯ~Wp=cioN zҫkkk5+㡇n~CC'zmݺf1=vd֫cƍ6+7oq^}iпjl7+s3+D&&&̒NJ'NYƬ, YMn,Vf@ǻ.>ضLavx۶3f~G`:K&'-k^o֤ˎ;kV-TY!L%'#}vL7!v_R t5syrt'&O>߲6:oiY1e|cK+Ωc[/|nf+@gis&Z_ `a|5wLN>|ԹK>yòF`eͺ|fPsl&twͪOff0Wgx8%ڋǏ-Ghn-@̺fLs-jv,-bY ѮZOOϲ4WmY7@]m޼Y&,Mw!hY# kNNV~~Kg[~mOa[ܗb'Z[[|>6+W1+桇n~CC'zmݺf1=vd֫cƍ6+7oq^}iпjl7+*mdV ,Y7ĄYҩY qĉ5k֘Eᵖ/Uw9 xwwD& C$ͩF {ɷ+cRF~eʃէ/Mx2<_O'.9s^?V-h@3#3 /e͗2f:`*dR2#њꭳ1IhZuaP2VK2G󟬫dRJImx#3jƹ%4P:ޯ=х:akUSyoyܥiiN&G8sE񧎛357|M}e8*fxbD3oֿXذa(&hxd4'9P-̬;u3̺KMEʊr5=-R~ת?7yډs9ȣmPKf5;b[ߞkw Fp/ե1jBI>^(2lz{3f>ࠫ(E^ˎ_xʬOu30ywEԑSڣ"Q*#^/'xFh |F0*@~U8|Y1v aR(w{ 4fv`^&jV)ˡbhVO TA FI-l:fF|(܆A# 6J"g/M?'|֝Jls6:bo߾3gΘ{'il𛞸MzMv p$6S&Qu`ߑf/EF%wu=vn8Oۡd(w ~M[΃:?z7=g垃>8b^XiF;o0]>7 ͽ]Ⱦk,#g~|&Up=9*UN0ES৺ G>c%7isFDGs$~TOޮo (w 0@aZV -2ŚsF-)N'vFGeOfQ}lFh_JГ.?;f0wSGOO~Q[Qr~x7,<`sw2e;t{ħ?>MfQ l!!E| tq|^z/;?ZT*20ѺtKO=97y_KtD+V3wt[_/_XG}+}ΧTa6}OyGRN.$͝oGV֦ls9w~ŽI|!v%|uv@g,1JAx6u醲 !  Ad _͍в#uku@+N})5B{0:/iǓ_=ul9?կ~SԎ;̦|ćoI놶 Kf@H/햞O 0kS}_vƒLJqprln t$nh d[E͘| Ϭ.ٯ܏+:~ޗn)]y%2o4+\M~JQǟCT4 *]xKy҇ywQq?5lN'̹?7ݛ ;3 huE02LxYh.`rgZ*/ {n pg:^FeܘC7a[o͞y]WTy~o)R%RWO.(QlתtҦ{uKzŒűE-'O3jdB;Gx wu4O >sCo87|ÞHQi` - 39Ol0k2*BY9N;Ou})̪#E3v_܏8G%׏~]b!o E{SNy _xil4H*G-UA`;O /=<*O!mC} *fܟ[:?M*/#/ݐnMb >#̀0gdU B+excdAfPIdǓp-÷=sD@7E=֌y P^=sF/{_akUQwl\$wYxE+i|/mwS߼hv׊#۷ѣGP9 )Bom\χc}kU%\De2C (\{;em UHΗzѿ:~`Zsrf,k,#Αul);ڿ[7'6٫~6]l\Z_\q?a$f@PKh)|p{+e%b+֭hڶv?K翰+}p͸9G?M6q:xrC/ڦ[:nOǒeڷ34K:S_+Qi^%ɢƏlfÛ1.i㑧?!:ܧt#)59 (!Sy(S]B%eOllV4_-'yNϓ'z1+l*!?E *yQ/zv@Kb4@}+􉂛Z_ZJ9s {WIn||Pgt /nPX x-ׇ?ȐqOEPQQmNlrFdQ_%r95R>ϬzDX19zuC]"ma*d,zWt"P>7J}";k^(Ll<*QSygSdQ?ΥtޟohTuog狁ї~B(w{ *:԰T@G'/O-KcyZ9M٬Ԋ#O>YQϸ6KO=oՁ#ҥcEE{J򃁁f9/(.jw2Aem#ٻ[ޮ?2YKZ?VQg]A|PλVZ IqvħŖ nHd?񑗪CcS?>YXo}s{v@gR@}Œ؟I#_GKi6xRrAڵ+JOoP=욜Ӫfж?B-GM<>dTJ?Pm}0"gJ~z*KrnV;rc>/ѠeXiw 6` |BX?He>kQy?/9"v{fFK+:l܀,-/L >`[?5 qk*_EX}+oֿdmv@gRllllfSv|||ݺu.O䤙鼨)lsyzLnsSٺv'6-[8f6xi''+K3ζf6lpm۶=ߢ `Φ;J i;n6gtfs) Nujhmbww]]kXzݪE榘%+YshPJ h5L:N&M1LV{PNwa/tX29=jMe/y\[')4b1gs,7/69;6-?_,t???3|s TMɟZ&ՑIM<}rIQ](M3N_www'gWu

l։A!ˮ*@o\+Vugeghڛ?;~kX8d7TR *541,kлRUP,jY~vUW,/L7`v|)nY7psg;v\tS7Y&4Y7 ƻ9\3#ʽ{USw2GUpW;:UM͛7uYzi''' #Ljɒ%bmo[,-Ew>nVuif X_%z{th4_J=UʜYm,s,[/C7?١[n=xYiLO?;.ظqÇ ̓;6";ۯqW{>w۾} E&&&̒NJ'NYƬ, ?xY ɟiw"sfJtY޶r݇j޾+v3[^KйI>^(2*5&syNUxE{1+izy J*8W#_}#]ְ%΂WRx@qU] fȾڞ}p7 f1拘ffdA;sYC_lrh<͜rnzڽЖ-f/EF%wm۵!p"]vٻcβ«쳇vHUy"C0/y?,2.Aup9ЮcxY*|};p*r[vW*D;k[r?}_sm(9R?['/e1f:*j?ݻoYط{c;m|' q3RlRU,(Qڽss;\ܱN 8L.;J`:kE\ܷs-22AͺG7LsxB"H9/5$"ژUh{Uu|es,Rf|)ny_ԧ>cӴ}_۷eǷȰEķ8V$K+*3/n8X9]"VJ,f5EKWKr[RC̖pE{gUsIYST3A*c}}zISP[uxeWPOrwTH*<E~K$0"fRfL?oar2f/JEFE|KS[=`|#KN,wuNuEPR?1J]Afiۇvo N_@ LS s̽@#Kw XhJ͢Cd'?yQ^ٓz#-w8uGEzirƬ;7¿,~|QQrJtqg .Ls; wMa 5D, _$߀Y(%~r) la5 o{o֞6w{-[ʏQmU4o71S0Q~c#h@c9 憞ZG?M6q:xR\b"=on(^=Az]^R>OU%&J8"" ثd֛pî|&JʘQ`fz+*mY41p/TWP~&r[FuSR?!w}Gj4N/K`0ubNW+˗/uN+>Ñ)mXCO3L^;Ǒq84;Q_ǾSK!̟Z]?"/v*rMlSI^2=ݷ'.9G0p|بBޭe 8.d_ury=[pP~Z|)7@jҪ5c9bVwҷ7sLDv/:յ&Jj9gK2*EO'vo[t0`+^?rSAyJ\ȄމuOT_ x^ڡOW}@a9]>G(۽mc˅>~ mْ,61-e;G5;ʮ袩.Q?@N/@m޼YW|kO;99TЗgRK,8m۶of@};W~"EY+V/EW]kkY/ۇSf*f^=c}'r[[^n =t㏟2ڶnzAҘ~};v OM]2ձqÇwTmpGETw_8> f}4_y5}x;MLL%/J`~÷?xYaLػ3Cm;t73ft\tjotP[y5syrt51j@4*!53C5Bؠ(xaD<2."BwTD<0"B!B@"D&Jeƹ&U7A!<4ݳmfSɦ;LڑΚ%'PjȨh46;kv[q$jH;C*OwRD|mOd2NߝOe`>!@E̺"f>& /1ZE{Y;MSDY{ENܡ(E^+h$v͢S~X=@-QCeCsm+/L7ė2拘u3dww\%L2Gɏ.ykNNN-G?TKKX޶mہ܃-E_+fPfp_]kkY/ۇSf*f mmmzcy衛P֭[ԾC]azZ7^r3SGA>uH{f8ɝk\f>Ț f͚RE:ӂH*KK&}k)'f2Y'Y,hC|lǎ'qUL[ɤsF}gmig0b}#f5o+5hTs=}PdTjL._]E)-eGfMr*c+.~ dvl3{Qeޯ es޽{7 > }N=#v22H'?ux"^J"(*Og q|FnuzsNϊ 8L.=eVm3OՋ[Ioi]]a+씩l=FaVHI5>GD<_D.2._}x+=yB|,}e u{5#>3W*y{oy[7-P>_ʬ/et@YyfYP֋wwMWpQ^扇}dk(ĵEN(3AUCPsYDe1$e{(+Wg:6~~ԧva6` hksH/VU;qVCGej8X9]/] N+%VTOO+%u!'3^MW1 z`&}Bsx|^@wbДAz^5'Ԗ-7Vܧ g)̗2Ku30{dƔrbX"%ƪ97.K9i~OOӭ eGE>LŻזXJ=ˏػښE-PNԇ7x,]we6͆ ^ы <1%&Z><<~|ȨXPEO :ɴ9&G-/Cdr(Ϳ(z/9I9aC)Nh,]:¢?PrPHYYRhg]:O2vXphRKѾ"ΔbOywwZY~_"fRfLTր>LmR> +x==O#ϵB!g]I :auʟC"֬g.!Qʚ0O~ѣffa]$֞Xŝ+_dTEp]ܙ2+9c:w@(/*k0r(| *jJqeݙLCra[Wfѹ_ 3+8pO ##i'k |]#Gyrױ7%E2֧V4o ]J/b1 RGe͢tw%sMAW<}V!Z.x177h=d/)%rUUKa37\͔I\Q)Le̪t|}E"Jݥ3d Y䁀ŸI|ѧdKh1*wtrޠS >' ;V/nKNdMsޗ|gg4拘u3!=ԟ:Nw,M=CN)˗/uN+>͞"+Vs3<-)t&ثבq8]u(-3,?'Y*C3,VylOuo93\vP=ЩnTߗ@#fp?;͢Ve1f2nVd21s͠|ʦ&xOâ9QgR{@׉\{J [4"H ț& Ϣ5V>;9nRUPd@Z$ zXM IM?⼳w#*v*ONN v`0k{iEE>Co S<2/<ߊg̈< ?]zbzt`>En#f>PA[vRtk׮(}H3i^T(fMISTPULO&lߝ6xQz2p)5z]x{6\U'O/YP5Ut5S(zoo *9@8>]:(G]܏w&xyP)^ˏ>z%?^=n\ СZPGdȿ 勘uEn3}qD Tz-_#Y G?W7sff2zQsummt?,5aD/3q!RT]7/#FuX{oog} Kz*uBs! fו?zRYɓx^5%H.>S=C,FWџzorܥ3*`A}5 ޝ6s t#ޚ택-"ACnD{;V]5ESS¿٨ i(qY[hY7_Ĭ/666yf2>>n:I-kNNN-G?TKKX޶mہ:J v<['Ha-p_]kkY/ۇSf*fAXmkk-O1Cgj?nzAҘ~};v OM]2ձqÇwTmpGETw_8> f}4_y/kdj}x;MLL%/J'NXfYY^Q/Uw9CeIxZ?QRit`K4΁3+k}e~G`:Nd5w.LXH"B{H?ORqBϭe2k<YL ~u2#3݀'_fԄ/ΗfWN Rf|n 4X|)nY7Ph0"fRfLE _ϼuaڬ%_Ĭ/bv̩lUHeznE W,퉋_sd.Rf|n0'2)ڂxtN7I ť:>ny%A|;P䄊6tS,eO^|qPYY߻BKu3}2Lr >JeAỹIkg2:0f2Y' M3z~95^.<#g "]B~cnؠj5X}+˾}&]t{ł9uDXGޕWr\lr%MP'dfg2xwwՌl\ I埾/(|)nv6X LEXSF8BΣu)9fʫ.OV7L^EF(=Y1l<$76S /`WȤarajֲ0U,jI&C2r`Ż ?59L~:RajkN?ʩ/+=_,8K Rf|)n ?!LdpsbCgZCV,%#5)[ bfOhZ)r2 %-i$|4]ST&"9ʒe$7Lx%Šuiχdͦ9c%drpTNfM.x͑Wh0t=kOAeU-{rl5:M >zKkf•ͱW|׬hZdJ? '_gK~~nV_X+⭋>z*0+̈5m룧t}:G =RWʮu<^teEDښK_uq)!**FV/Fp/UrBO>.H5B"]qύWN|ޱMKŖĦK/;'/ȃcزE"fYL5P2&,]"KKeWs6!bZkf#'rU\tHeBW <%%f;_-TH7Χ2m޼Y[N/lVnQQ5w4Kʷ~c/6::jVb7+v0K^:2+!N8fMwԹFA<tTb]])朻,D ']UW/:Og*ϗ2Ku3C5+tPQo[|Ӣ}L\-Y7_ʬ@@/91ǹpY.Xk"fݶ>zΧ)nBz򦫖5=u?rr|)nY7y-j +<[h}Z]֪[oo+h _ʬ/et`@ W7+i|y"̭:é3ˮK΅[@||)n4lUHe:P e4'_{3&^}ҹ'Ͻ9` (1拘f@I*٭p;sFRT LJ&JWa2xtl.8w{NeU@ @jN^.rױsg7/3+J: /e1f:|~dr;'RnW6tGG:՟&0J3_GןFU@Р[nlnN^/;Zۼ~VϠD󓺙u#_ʬ1t P&$+fөt69k6:dnS;d2ASUx 2`vSS @РGw񞓗.Y߼عfE)܂Ɨӷ{VŚ4&O_MO 2XKTS(˾}&]t{ł9uDXGޕWrFaȕ6AJ2L3tjFs6X%w=!`ޘ<|R-ͯ;y1拘f@ʤ<2||% f^.+e ST~C #{bnyHnNm&_ّIS;nWdz伌;F''Uǻ z9}Y0y v$ŘN*LCQ=ujoo>yòF/e1f:@I0Vs^CZCV,%#ѧ5[af/nCwlZ-,6MW^&I03j>婟%zu tul uvѶNF5@djvQ]#u46n~Rf|)n4TߤT+fUaaY7LnC6E;0Te Ƭrc!Kfb^V)!:9hִFu@j1͗2f|RToU G ̚SYl/nԋYgVX^|ɦgwC͖ϞoJsUB "_Ĭ/bv *!KMa%qT(MUJWizFR/SuRK:Wo=\,sۧV˞[ͽztlO=BaT42|ys싘u3`󄊺fBWJf+, qjkw#76x|57&0fnˍzX۫T^~p0P67_/wqMXL4ion l:)`͌RY955҈impܵԨE3tʍbF/n*i}" (. enhE|ﮪMb]LO.(=yg4 m޼Y[N/kO;9Y'}~&b(}/JJd/i4_J=U µt4wҬ7 h[n=xYiLO?;.ظqÇ ̓;j޹,Y'Qu8Ϋ=Y;⯼Q۷o߿YAĄYҩY qĉ5k֘T]6ݡR K^Q/Uwɞl7w.LkbN?Y7_6|z]/e1f:HC5fY7_ʬPe ,wrgY`"fRfL@ 1拘f h Y7_ĬP|)nY71@@"fRfL$ɨ/!jn|t1jH'd&~Ůc]VVzPvj"Rf|n2wwI_6JgI^G'Zy.PǸIK.hKeӗ2f:DIJMY5 5/@5:I*&:xܬ9jcQ*Yw+ j;:+4}J|*wTx.3a wB,Q&e(țh+ckMEʑӣU2h /bNf0jԟ GױmdKtܲߡ}dePU-_ʬ/bt <ISşxPRN:V\dz@8;Zla$S]UC `>̺RfLjW|aYbUXvbZ6ݡg+di_hUe/bv/e`g@ע.*K?/7Y?-2Ys#iAC>2ٟO]:NjcwU4:勘uEn3}3*7Wi̊ġkr@:4u*+Kr 8X_CMVe%]Ԟ*+K \YmVKuE̺45Ēj'jkƥ>YLgLC{;@fOG:ngUM@_ʬ/et%}f]vx*&Ĭɏa>Hf}.Od-*j":OeȀ/|tI U u}3ZRfpnɤ*3l2)gHg%Z=siet6_6UQa$%+Dתknɮ*+38.:@]YmVP7|)nY7cI@gi?RLY!ۭRDsMy$SxvJ-Ք#'NNvUYy![dI <_6_ʬ\—fr#qU9ua!Ud9%=Al# *+Q':i:ዘuEn3}x257DHirn*E6Ѫ[9)]O:AW+uj `~̺"fLY´ʠ$엓գR_7N~LXUZ'ZNedfFKu̺XZYV] u=>vUYy3^5+̜/bv/e`)j"Mͤ WO׍ww'MϢ]UV 47\~e/bvPK2vrT%a^F*ws1s2_BQj!UxvQ')Oz[怛/ |ꬻl:P?|ܨKYO'j1<9'Dr{ ?)uj,1O\I95'@fY35 _6_ʬY#&wg;(YE̺"f>D%8rh,PY7_6F ?_ʬ/bt LUHg@-Ku̺(K6ѪB5nR69禜w(^yZuN:U5dD9u1͗2fR2:I\ٟh6ёE|^:9P#O dW5Q`E̺"f>l6NL&W˘;2usdD"|3FH&M3zjfp]E 0ɚ dRL6s.v<%fk~zP)VJyNu['` k_I@gi?dRBCCrz WT:k [,ٮ!<22ѕ7⥧_#9qZuԿ}dawN~s Ҵc :t'%3@#oer~j>w"étVҞ#QIT*),<&EOrSZ6ёI+ɮ_pKӱ_fj6)Ӟ#EG%LfM 9 Smm%Y7sE'9a3| i<0rQc~Au쪚H%8b_[6,mQ,ka" @!=yedp[2עBBMre+$5=7]|lR+J}ݐN;SU]U)/ػ9x26@eQ cNsšQ9M-QD}F&GjYn,F>eu=>vUYʼnolVDbiS͆VKܟ7Tmvaۭp<[D~^gHo+ZPK%-A0 "\~ 4P *eYa) AQ|Z֋@%bd} R*ZnU=3}:eM7|]')4n5K.78s&ʐQ0!65}<ӱ`fz-ގa{ ?')ujh,Xˠ_?s'ΒAJ c1橃k5}}<UпaYS̬^w󠏫Z̃@X.}֮^{]փerM Ŕ#Y]a?ԷI45˚ ==YQ@|iڹxyzzڬbrgg潀9oz'g:*p38,DXE3+XزV#50̇ʘu- VdWqVGO7 %{,fxoBཧOX[z m}85lVe3l;.k6a.,6刏lKO u;+-L51]Y'OSG:nv'3)S奜d|-:O(T B&/味8tP;Ԭ @^l{ 0_Ϥȓs W%hyxfZ|TfHAqR-yDurI{4}/rքxSsҥKgΜ Ǐ/ [q tsɯ8[+:s[x&ٳ/^z[kk/?|L{?俷 /z=zhW^8uԕ+W}F-qNIϨ9?yJ內j}kJ{;of|3 h i3`ɾF׶G <΀QkтdpӞ=k73Zғ[,ZFf>İ,^Y] jħ5yQLxQ(쐒\iTΛwJ@Pv28JiO ZIvuuMZf'MoR;AmJvsmH\ƃ<QN{J(SR\ɊN1d"AkkOҧ>dcLxa{S{o p[0bj޵tzڽNT=Yɶ\n>h8o(!=%$zfdYX{IjV#PӮ r)tfN^u'6.Wh~΀JO>=wRgSɹSϏ|Ԕ `a]zBXu-]7_ζl]zҀ-Pj28JiO S"inj#d향KZ={{ȎVvݿa5ÌثF~u %Ķ;ZwX#K res3͠;m:t82۷d/%ဒQBN{JHȮ7ouhNޑѶӆ25n^KSl7ڵfq9r=ەv=Lj)@[>_ߊl^ KÁsO(M;`BgH6zG3 .BdoJN4<{e'DvjtuŇ =:c@B[><ĉ׶nAf(~53JĤ\CK(Trؾ @a9+\Ӟ ySFࢷT}^/nzfJ:anvw#n15hɬfr؉xө;qtOΧkK痗~wkk(4On"pEL6(,iMnWWj,̌W9b4Wuwuv isBkBsOThSoպWq݃GϙSSuҥKgΜ Ǐ/_h~ce*إO7>*%~KbKmӱT;}ֽV͓/ͫm[8`g^x1ǓO~gn{-dyw?a} L}=+t:uʕ+qpyF`wgT 97GT^x+/$ Ws= 7;7oƵ^!!nܸq8E6 6aVr&_.9 y8kӞ:שzN 9&l^^|jF@ rSBgE$]Z:Kt̔ rSB}` `wnu[E )%䴧7Ry,n`L@ŋ:@m|҉8fLG 9)!UDtmuݒ@@ֵʱ'Y+@JiO Wg` Fݪ)P @iigpb8iO ѳ`yOlّQBN{JH p Mxvc%-|^iٟPJw_҂MG 9)!3%s5 A D+V לLMDtQo:eϵJ5y#Y$2i kU?Rt:A4k0ͲAlZikNiݮVqewi028Ji$?~<Ijs*{iD7^vJduu0ˆdj&]d<Z:n=)~rcKq ؽgpҷr=SBgJ(Mzqeymax%w qG5'SS6YZs8Roe-kڪ:tb qPpzey5 6SPN{J(/|I~Ǐ%i'XvBV+i>ZQF5'SS6E+յKH*k@)m|R7qNom]`"y'(y5t_n(!=%$zL_] (vzHg6Qw"-_o7f~b_aF5'SS6fHV=|%ZiTN!PJ';î|={dp=CW_4c~iEtxG"F5'SS6f@:ټ:|8ˆ??|B=Cms%ԢOF-֒ؕݨ7ڵXokNkX'0΢ FFPBgJȿ]Zge݆%hdgc,3+jFۍkNi:9afs0 _#(9k Mz;0?q;e}#G+;x hfǖˏ>v"y!<ܠkcе"G3 X$JHL MTh7V.5PZ'>k \N,!.#(3%_{4f [?-_7FPB=_?N?[qOe rϧo[8kՂ# {ߒȱ}޷+?_҇~h_<:7OjQBN{J耽i7V$8ϠmUOoLX00/ݻ}9}o}7KyMPC q %ധMNnK{j5Mbj͛<lz_yGG̙S381ᴧMNVTZެjLP]]E0`z}=8:~_/on~7^|}ۖ߶7q6̷{E W8KEϔ rSB &g@ݟ?182 a%+%+_/_NWw }:rO{)ͫ{mxgJHG 9)&g[ݓ?\-N9N4qNv!:%ǐNaO7ެ~{~ߝ;?Jǿu{r}omC9qtW3sKL (!=%t%н#2+VO5%ӣ9+Zڞ#%}VHyf-Ar39V[_vŜ9iڍzg'~d]!34PN ow~?o?ocmMWmw|xK_h ұ=v-S/gJHG 9)zsc8ѓ@n„յV?;Pon4Z1WTkRժAt?I)<QN{J or̹J?G1fW49NoW&9Mb\[8tko}?ָ6fo-W7+ZB3KӢgFW뛼qPzN{JD߯g tvsxIr~ɣo_v!&^yϏ@ ?x˟=swKQTv/]=S28JiO (z:sok׈'bb#GʂAm%V-tXᲅ~zN#G]e GT wy{cF>ו(!=%T79Do_WLk{m^fiHCnW1Qa6Qة{Jsɞ!5"3%$%6O~AyD+6Nw}$X>QB28JiO ykZJR;@̵&( 8pSB0ئ$'}^0hreSq-Tgpb8iO y"ImV~ܹ'-abՖn!.(!%'~ӞR&JH |j}+6ϝ<_?yyz8S%$z߾7AMvGϝm]_7îTF )!=%Mvcv\dc'v(!%䴧h7coV~ܹGGOe rSBJyY3յdݚ#VH_˵Jce #0͋|^!|A>TY9NM6>JD>QB28JiO yCV֌nuuViZc&ЃV=sGҪ >`^You5Z Z>U|l[N.PvR+@JiO y3ijG_=j2Vvo3_ܱ3{2d5\wث@{J'de{?a;&S> 7:tݖ|lVˣ,z&,ޮ^>|}#IںTZQX*~&T,qty'<79S7_'i욐"mͷ}Rym(#avk&Ѩ%3ګM:5vw#J0yadYp"p 'n>1tC!GV(~|=]hw/h.QBN{JțW:Z7]xCպGv({ךY4EÝ"5024ҧM߆NC+ɱ$B 0[V-o|/3'dK:8QF>QB28JiO y d,G=CZ!/ \ӊn*qYooꛆ#Luad bp=LǙǭZ'՞TuӷcݡVkVcglǽLHf@ t]rQBN{JțEUG =XO*|vr]@::p`JnQw8NX轒'=KwON !;VJŧ2JHG 9)!orM!mAcF;;+NNIXd?K8QwӅ(yi; `wbta98|*dpӞ&gaee1:^ej#yN:HLݨ7څԻ:Zt~;RÏ/;o1gkcȽ4Ljj|ru3ހ+|ِq %W1Ӟ&gu gm(bxsKv;5[bxc^;{gQ~ŝ=IGwҨv[]VOCrYn#+͞"#0}&*]{4EW<B2cХKΜ9Ǐ_ w??V_^Vg.}WI-Y~dˠc8swޞg^x1ǓO~gnSv?qhBW^y=nSN]r%2ɣ'Y3jQ3 xQt@.̰Vʱ'Nn,%í녦3%$79CVrq.>+-WlOv J-(Nuv<ƨHmΧnt(Ӎ՚CSSsF]]] Ik uw)Zן̊MRkrk+N3OkSW1,LN8iO yspJth- \ b,K>;{M0յdk{5IUOf{Fƻ;ư&j%oU1 ] +S='+Β5a g_%$Jp5ꅸ*K ?;=pӞ&砩/6\CK^g-vwZ33gcadi6YV-w[Ҵ>ӪШ#>3sj:}R71l|o,{1?>QB28Ji]I޷N9 (z=cly3nۛpZ(w{C)lVeǗ]obawV^>i1& n4;QBN{Jț,ZEG#XzB vs#9QV+S,R;%ɣ&FWcеZA>`>QB28JiO yse" qN.&:qelBoxI⏑ djw& 4/1O[(^3h`TF (!=%MN9Yo6@;nBGm.ES4%M/WҽKggisbܷHMV_Se9<Lc'=~0ȖQBN{Jț)FQhIQ]mvzT9Ҩv.)ցɲl%yޫXQٝfTC:Gl Wݟ+kμ:y xzO=Yo7vXuҥKgΜ ǏB^|paX}y|vӍ%J`l/vP6q0O'-g^x1ǓO~gnSv?q~c{&)epNrJ08f59?yJ內j7d~>sqpcN7oތkB*CܸqѣqeeuXHmBT0_G#}1%紒ϔ{Q pyHsB Zւc|*޸7o0orlRVz\սo;BdY|ܧ2 pɁݪi0״lѓ3[O>`AiZ>9x}|͗/k[6޵m]8g5Ytւ:=8}-m:t8Bk'MV#,ڢ m]Y4,Km݊]\pmBT@PJ'n+286_|tmnme[ً9 eX;٫֪zw,lr==+ew֕cMdЙjڍؼmE\݌7#O]5%n՚UkՏ9qލ~GKz%o5Nw7w=n77t#-ݶPN)ƹcB7=tGڵ$}b\bUzg +JY[btHn%17NY ë<֔M@ךJ=mh$aft0?O[C@+<үiD]|Bnݪ˝@9ȾkÕ)Å*wsFeփmcMۄ1JY)̋ ˧Nפ(HC%ы& %G8ˋs}=7zkC;P\P(Τa[@ݒ쮋Oyi0{T$9bW!ZO>V\l}]͓?U9ıx 5iݣUwQNֵ߭ Y+ /oX:tu#3t\A0ИtQoղkFX95BN,{BhlݮV Vkv# ]ڼZ_O>/W7 &[hvAZM @yE40HHW8XB_ۧ BfNfstɡ}/@ ~rcKڭVZjVn4&E[#V7N^Jc4@Fh\~|"j-#ZզyF7ɐ1'SӵjZ|nڡm [ݖGzz -VfSZFB$Ky C |~dj;VܼG=jYn4bܑ7DTnW4kYm`Vu"Nze59bNL tG+WoujHkPC8Z옐",d"n'njkt`R.BXgj#-D+MT2&l\ԪIcAs255;׾7/T0BuumH Ä͟F_ƜLM?.Yx#(s͓qA.\2hd+d#U7Ԕ@Z~{,TV.vY72S.^02vۺ=9B ݛHgE QhHt@;;^x#`|i2]Ӯ4A /uRnWkl򗷚̼LMX~T _Y,ҍY'޴/tТ7)8~O^JoO ߷v$;ƻısѐ9/{Zp@р뛯}}]-I@,뗯;Y;vyzc@}ȝgv$;ƻ҉[[ҵ ki}M]?w͒fF}F]ͱ(員ǖ~M!C /~֘Kr|WimUMhh}soKr*G1q7(N#湻~]4ssInw/ϝzkׯ_s=ڍ#G4q\iՓz+/z^D8^Ϩp;Ԍ[曕7 K2nbj@~^i t:sf-nm7VVnxo{ZI4@V$8_廚=qlı{kKqnWWWkٰj6W:'a\"c|3}PM[h%-=#dj on;td'$z.B SBPjk4~ҕy9m- fSj\XͶ:$!)7>}wK2@ղhU6:AĈ&;vhmIr+o\챑Ywˮ] djk^w h`Z1H72m %Qqzmv?;:/?9'SS#I]/u q  4L*w5ϝ{҉c֖$!]˓'N!@|E&T;vވ=z`RK+V6y. 4 `RNںɖd{=YT j7V$V_z+;Ztsmr^#]s`&9@#ں޺u쉓''!0DjVWq)b%rzy3hakdF{ɸsJ~TsSLǶ5ϝS[Ŧi\j5 \hWZkZ3g;4knB;jW}:s:TB ij5DrJgzmڪw撵|> Y37$[y*vBJJdBusYN%f4̥돭?Y9qػR6{BttPMWW ? i0]]]K!5cZZP%qxdZu5Q ՞2Me?DөvY64L҉[[ҵ˕ ikגF,͋hP@T0f<Nv"FYIkQ%w2N9FC$sL;>VIBb .On=:M%gIvM )fix0[[ז:,-_u-N* P4 P@sֶ/#_oa}69F]_neEi`HBnjڂcjlcHʼ:'+{!'}Si#z;m7L%|T(K jhTL_qoZl}{zaq%w*< =Yr*Gtgtҙ3g`cca6n77GX}yy9`Bn|.UcK~MǵmjOn]_].q0OÝ={ŋq8|C`EW˭YSu#Ɇtr[*=M/BLVW4qqkZS0RBf尽BL0#{nEt1jB#&ѓ΍SWF[]l1MyK 9Y"̙돥?><(P#1lku Cⴎێu脼;ǒM4?9C,P]t"i:<#Y&{ i ı `p;k+"\Vغ2Z&R:Τ3¶t-F%k#%G'M>>#Fɣ'k\ ޭqg` cOwc׷FѲnkVef_NTf`&۝P(Y$FFj:k\xC Z~rR:Qv'jQ1P"V~>z!n(,ćڳYvo,to>AEyf^ FZ(<=1x#qoM@i2^4y+ 8&epl^ۖ@jj Z~T4ӂv-4NR*09ɰUO7}#F)ޜLMdЙjڍY'̑4}4Mt c' kV|ڽ,?zm:|2^`?[,Gk$s!˞uN+f-v^SdݍV+n;'S4Q]VvG&&0Jdi|cOmVN;m.?1 W^k%]ٖ [ZZi\]mV%sU_inmu+҄:FL n4Zɞqj-:bNkzu-}Q?j#G4kL/oerVvmsZ=ݸN,/WԵ['Af10iҗv$sRB'LM.ZpRYH0_nm][||~ֵ4N#N*=UGsb˛?=;m^ K{/i'X!tTAViߏ#:/SS6E6!qJk_?~>}w&i'UZgn.gM/B|ylKm݊-ldu!+^z6f`Jc@O9j%e}4sތW] m8qtOPYݭ[Yi~)^73bjd4RbNf FdhHEY_0͔+KǞH;rO]Gߺ-lEndvi{ѨtN0dj&N;?Y6̡Y,wzݼGXͫq- 1N?WH^f'-15PQ878'SS6QNSΤɓ ew\__ֵ/9ms%ԢOF9vT&vFj-ڍz]K/8?S5Yn$X7JL+MmN $ًضhdm#. 9jZO-E3ySj;ı-IڶѸAKxIkq\e# '럜,^]kVBFH/89'OE`M@' !ic)W~YG(K0ԘtժLv;kfVkZl@ts4ղ~C.@@WV+vnZ( }]t̙3aqޯX =k͛Z /vss//4?r>\$vȑvPk[ӳϾ_y8SN]r%QӜQwկKWx74*g./s淿[W6_{ I4 /n\|7ןo[_y.`}xr[oCooV*_?{ U?`m@ݸVַo_[?';}oT^}[qVHxWqj͛j5b 6swx7+oV~ٸus[Qy*h`vcHe7tʘh@5U*y͕o o\}o*;*Z`VѮ6;ŵfm C88zo 믾Qo~y7|3Yވ+dOjZjVmQ*v;mȑK6 k͜lOoԝ.NfѡԚ@/G޳xo|_И}Ͻ[7 %jOotnϒF[dj(nՏ+7͛Z:싙jU%kN^rR9}o9}wHwqOg>H@i"N,kNK?jzѪf뉾[j͛l:΂lkJyވ?Q|oC~݇6xqv2Gspwr43tb3m1NUW28ַ(Ʒgh|;x\}ǡʉwo>ZPU?rܞ!fy/(T<5wF9SGCCޥ~'>=?v04i흑Z%͟;wGG6fiT{?{g^zgإP_ X;wF?М#NǏ´ Cxw;y 5oVb?F5ruϭFRLz-YqruZnT{3Ym΢x11] rCDIDAT: ޗ9ҩ^|ϴ΅};LG[*>)@0hB T 4S!`*L@0hB T`?+GVϟ?B֡K.9s& 666ʞw{_h~c8 }WI-yss8'gΞ={8XO>grObz?+qԩ+Wߌk?3jLso#S_f|vwTx5'xB(iVط|f#eX0 vccaw}wXM/%ЋN=ąc3Y^;3jL1 !ЕeSgg,ōmvq2{ ?7z] NI=$ւ`2Oa_{n%~;aKX\@)V֌nuuViZavWzZVWV+0#!vJuC?w;X~R|rKio堯AB2ְvo3_ܱ3 E;U|=%ۓ]lpa;&S> 7:tݖ|2%nJZMnof]d90F/e ƺ^@"԰孿z߸ó{&5oAHӴACEZo*`;ڵtavk&Ѩ-ɡWӛtjt[DЬx<&8lrUw]I:NB1N7 BH<{uѥѧ?ggU]mONr䧫Vݔ7XOϓeZmM(/B K)[~{%,!cbJZBvRb:-Z{DiY(m5h:H뉋 tݗ=h6tR>*da&gIH#,4OOj;VU+E٣ow}/!7e:d{9%`*ˉ*tnqd/bn*qYooꛆ#:a)lV!q6}WZ6HXՐ<_YԟHhoԗlEa7e0@W61`={N~𭴇G.'+=+in4*bq'ث1FaP7GsqqJ8 e_o|{Պ/h= In7iS>B9dNyir0$yNSl=jX tc<-ݒTIEU (][Ȋ/hko@? {nB#yNUCgkJoDhvBro)q{{o罂&yG.dYncpF ?WyzWa[d<{&&I1,oAZOd7X@jլ E /wnIQqMeqCĘivw쐺wŮ>kٳQs~W/ Y/iHH.`^g^i6*)>Y'):a69*?ϰFХKΜ9w}wXM/RͰe} ͏0O7>*%AqynL0ٳg/^'?3^)8XL>Zx:N:uʕ8?ńk|Ψ٘5?gȤz{*~qWތ==\0ܘ͛7ZJ7n8zhڍ!1BTq0U@(/nMuEfxϜ8 40/a1R0♓Nq940YaېN,pUW M'h`֊i`&KV<͊_F H8R}_A=,/Y/\Oԍm(~b3wol8z7^z)nJ-O,/Y,8pе+GV^ƥ8/t|.Y."I&%{>ثZƵ2+1VyŽz~V=n(X}Pkg\HeqyH,qIqݼysmuj7VVf4dZmw=-t\=5i J@ H ԚY*Tw5kHZ>2ޖ;TWl:[K닻^K,NSjs`d'Qg1j'Jj[|b枵C#Sؔ=L:+ǫeW?U%  ҂UsfcY'^i0X]L0OˡK.9s& 666>Hszq{饗nnn-{_h~c8 }WI-ss8'gΞ={8XO>grObz?+ǻS\ wΨpF)? zz{*~qWތ==\0ܘ͛7ZJ7n8zt[Xƴ+Y<3 vccaO??Q?_ȏPY,2nOK,l oIܽqwx饸 }s `cd[`aMZ}i#VoQm;+3,oq:NЯV(N=k\H[@#w*{-`AM@'Ҷy_Hs D:YV{З.A3V̝EPz14bH,N r_A,)V|1tĭ0& _z47}^(΢g MDâk7V$8d KVoѻ[=\z;?ɝ!]^iҪNj\cWq/ Ss!3'SS3Q}z_?GM=p4!Em}O nCKa[Zۣյ7o Eј\U?Ro՚ɋ̕J7i(Nm;>ylR`<[nljWnZYdiu~dȿ4Xh b,q+m(Вh_Z-T>ZZ-c D8!ܱhЉTV};RP9_i~X.KDǭղh#o0&XYif7hֲ8i$EW jsĜLMDK/xߙ3g&[H1wN`jа/: _muj5!Kuu-vLHKWg2ZcFk7VVZ%-(67-q=MR%0KZocɝUÄ͟Z#i;}NfT&͗~u`ly#z](OV`kCZm&le_74f0dj&П>xsĭsCKFkt ]4]DY{YJcj /E۸!Gϝ{Rzy\\Φmf't LIt ,A)S/K;qmݞ!Mڅ(]dj U}A>[~ܱV\?Yyj}~ui} 09YV'IJv bxuZftgej&m̑c._n/_H׶.lnkii`sh?b?~'Ϳg%nv,FƬo_hћvx?/IJ7'djjj|>u8lߒY>8v+΢g GxƟ14#ET;5t>wcK'~⮷[M`fX\1w=ҟ/>Вh&2f=:.B3պ^=_X.]ߺvc/oUX:|mVdongTB @_0\|?"076_|tmnm 쁐;C0[pJ3|tq+06Zy44u-(΢gc:8SKy߸U7o^ M9W;a-n(yCKnʞ(;F 1hK!S1w=I @]^C'%CKn9rdюJ[q~ /Dr'2zFuiNfBW !w=C+jŸ=ρVHҼ4kuuRZn4ݒ8$dqmI'i4v8;kZG6lګjIs1Lsμ94{'<;6^Gzqۣ*gJcj ollTa}.mH7Œ_=n`A9`oXiOUCgkAܬY}pY{Iz%%"{3^R m[35]c/ts*ْlw9n`19d:0N5Fx4&1NE:1r v^T,tF :})=ӝ/d1w-va7i35L`CWhW`vCp6 (8Eώ6p; {Axz{n韜3>f//=c.B=x?KA4"}3/W =M`vB,z(14;N}(~`?sg3@ chI4$}\D94.΢gC34;CKwo~󛯽Z)y`B `~@ߺu777ʠ;Mbh91*~׮\r|;2h;bhJr$h [qѪmC!55ߖQwy82ygCK?V][]M,W$nȵ͠YKyV;|V=&=r*ASNO-8eR-`OY lZA4&͝Z& JvsmP\klgfͭVpG5\'/}qSfKgڍF63e;_xСCao}K xtP` >Lko~W*=sq68h1$Kӿ/MFn:fSOޘUCgkCR=P?GqZ #_y0:;~;ۼo߭@Isd[1$ C跿NZ^^>AY ~It PJ;ЉyC psd[P%@9@p0%lDǭ (b,q+05Z]*F;N+=xz+|P{&>3'r=Ws~C İ(}ũcTgvF %+w}~ItʁW]]iڍ0j$*loՏ4*n6+NFbzeu7ln4EW'xQNj|qSw1}V+-gA ʢ;'K b -.Z'vZKȦZjD7viLdo+͵QsѮ5{4ͷԸKH{:";25cz&4; %eVBBjk4Z9*|Nہ8}pa}ڝFز22$D̟PZy_V|BO!H:B=t蠑Щ&Ƕ4A#wV%G+UBn5bBt"I `g}ߒ;@H^ jE63i㌰-]7Bi !Z.f;8N[rqz3b*%AqynL^y2lϞ={8XO>grObz?+qԩ+W3j6Qc3GT^xY_y3?V_^^cЧK~؎9ss8'g`?y|ً/x=̭x>ӳϾ_y8SN]r%QӜQ%KcU`-STJL *~R?>%K`<ŷRŷXq(4P^ODOJqS|U|,A'JcOQQ|,weA$doߕg4p}z)~Ix#I{wtFb@ K]^ B ,O R|oAQ|,}o㍀y%@3F'd7 (K)0(~ƈ`[<:,q`(}ytXа/|!`VL@0hB T 4S!`*L@0.]t̙8;n777Ö=/4?r>\$vȑvPk[]R 7~]x޼8^ł"!Eպ&iOĵkNQk[ } ܞbAtqhXX/_X>V˺:X^>qkZ宬nӻF_AtqA94,ͧ.o:r<]p󩫕GC[WJjl3#ŵutkaK+t=ͣl Ex 4bG|s@Ot*?K"43JۿWgQXdp O![쳼:_dp0Gł `q;}'"`|VhX@hC :,2hsh ŖwK 0_ПkLX`ŎaA|k 4M (|_8̊ :n'$%N3$ oV :,q8X!}@p2sq@P..T ]9YV`(bAtȣP<@Pv!..q}"q 5gXhX-+vN3,(4+N4XY K Q v8ܞbd[A c)vH nʟ @n|v[MtvW,qL vM3h9YPhłG (bJE Ӣ R h V; 4̈hbs P W ` ,bsĭ`Dǭ>9Y@/4jA$2h9Oņꝁ `^9D0Wznĭc@< gfE3'0B)k YR 4,P N9nmhX:,q읾gU^@l=jhng`x2hvA30hXl g`D0&% @A0P"(2)6ܐ>E M#GĭIHK-4pJhJ30p)8>zg` \DŒ/<4hC30Pj |_9Y@@}_嫡 Z 0g3@P `(y u"wJ&FQ 0cJD `B80LW(..q*6q@@(v䈛=znإ<"vX-g<)Dˣ%@ Q  $%N"@ &@Ӣ (!%Eh`vDga($%# 4?B)6qmёXPnI ̅hy40?<łG 'S!V ̞zg"旂h`JVvE , 4띓%n`/PV lk,q&RȠD`f8N}~~-[~{Ƣ>;':_[+*C6L6++xaȣ'l/}h Ww`f8~~%m)➧8o>3zяt4ŞłG gY@:|W{yb'>3f/Ķ8S'"oFl'5v?l>˟{?Ccc\#GXV*ڐ>;4,*9r$q0OÝ={ŋq8|C&2g#\/-9s||u͸+Rq'|j766? hԊ#g`N띥O m}Bg?3@(D<:Ndk;,(4j0=9_$`b5~DÔĹ @L&Ao_4b|Q p &7ȗ8j#,qE ısaɸr0` SAeqJ9,f@Z:˛ןug-U*ˏxD\ r.w+g`p>pyGyȠصC.]:sL흍paX}yy9`Bn|.Uc;rH\;(5ϭ`<;{ŋ`믿yG?:`qwsԧ~;ԩS\ gm?-`1<܏ogl~|瞋tyf\R8n>DǏ|]4uҗ>'C'Oo[u~KoO?:S0,}N`T@PF*ss8:%Z*)mY&`*L-?y_\g>O7=O#K|9F)Q:Oi¿L }My C ̋Gӎ{?E F>izF:{t:t;>]7⛟|kq0_ԡsd L񗞧i}\$>׾v1Nu'_ ϓx$:>Z->̒?tkK_;{֧X~4;*_L}wŋ'vNVȞx᳏c}S7(ɯVy}gU`ŋ>W3Ww}"%)/d9;M)1|-=b'}~4{$*U]?t{9'j>wt-9s:pi fI4K4 hH`~  4S!`*LšK.9s&FͰݑ#Gpݼy3q ǵnll?~< u4K %1,@kT`T@0khB T 4S!`*L@0hХKΜ9G{gcccw 8~x`*X( 7771rJ+*؂͛a {R%8RIENDB`asammdf-8.5.1/doc/images/tabular1.png000066400000000000000000001340611502633300400173710ustar00rootroot00000000000000PNG  IHDRg=VsRGBgAMA a pHYsodIDATx^t#}y=hJ-X m2cKahb HdҦ$Y tlffO310&Q<++= G̉XQ )#[$[zz5޺@P?Xߏ'ş;nE5fd Y`F5fd Y`F5fd Y`F5fd Y`9>>wCYE|W/|wDȔ?7@"<3'f dʠ=u'w_|@r5Tߙ=ҽvAA7~A7#nNݿHVm|gՆ~^+KȔzq=e+3+7LFOWz^Sd{΋=ݿ2rm `5/kfH|w}k̑Cq2+yꙕ˟^yFeOxfE3Oxys~?e7nܸqƍ7nܸ%k__za_қa|<35}%{<9Ν7}|_o{ۿ~m?'^U[z?uW=7'_{_6ܸqƍ[ofjqZUyO|?3Ly>xymnoM՟ݕp񹵳oű'pƍ7n rȑo'[kƒk}%31k?kןɽ/<gV2{Oju_2O}s#7nܸ]燻;Oxm n/?xӭ:?yݷ~x7nܸqʛ4Q|sqɬf97MyG|/Η^sk\nܸqƍMn󷿶ny4xh^|WV}FO_7wW:௼y럕xY~+W3pƍ7n6Xqyd~3v3k}Y ^+A7~;=v2Oǿ?[o_~p^] O} /?wƍ7nܸ"Z/ϛ+Ͼrww}OчD}|{ |zԓAo+UNy*G?%7nܸ&L;c#6k>9Q_+A y׷}ev|߽+^yWx|3s7_<<_ӏnl<[yO~=T7ծF[$rsqu=7缵||WtS?Soo^[{%]^z/s;ook~)z |K[~/g~ ~=o3 ޳cjߔ?0^hy"kv޳˾V{OgoG{o7>-ŕoSm|F߁7nܸq&n,oD=syS=kΛy]g?u>;r}E[q\?wVmg~?rƍ7n鼍anʍug|tS mS9Qd8_k+7|<⧟O?S/?}cF+Gށ7nܸq&nW5kxu69rWy=Ppf\݁o+*_Ugrƍ7n黩٫}6x9SO;z[Mu+V]ow}%3?3/3W?47_?ƕq?_~7Soz>z+k׿,Z5sTt;/~q_ ߲w~[C{yV |[j9{Kmf"%4M?c{0 xmx"3e2rM|.^~ާW_|[~o_'>{՗^tbWWk_-{5wƍ7nܸy7EK?s-w^Η?;[)m%m*?^[w~y9ܸqƍ[jo#gxS+O; n6a Bg |^x,R{_|cyG۷)ޏޟsn_uY{Z>_Ͻo:u2Ͻ~?|:7VSȭ.9oO]_qƍ7niyxaqV ^Jf0X;2cG Pqw}׿0|i^|gY2kEQ)HeNޘm{/k{Yt^+}-3k q2 ɖ58<< 9-//t!k30#k3,s||]\\^]]ms}<);;;E>99ۡ-8kP,}'{ F Z\{@l!5OO./k `F5fd Y`A-RhWl $ʸ)#W>{`"*Fx>[_8I2lO<OϓRs j/ /弄rӳ2x7AF[2co3&/s ߿`xTa.2do<''ёB߫F=`ý0y##eQxf_5|`GOz' &?dx?#|ȧ1~.Þ {ł/N|B߫F=0g*Fx>eW[_8I3 y+W<ř'~*=0Y<' _7(-GVU_1/ T K}xC"_l>n"*C&^s>eߎo!ϱAۮ?zPSi־^.oԋeD?srJ{SjtzT!k^Q[ABilMv=p:\"0佂BEQ?i1Ŗ=ϼ#p K\qĮ B`G<%B  3 Cv'K0=%#J%5G(L)wT b:.U!xP=mл=}6eŪQoޯ{tWIq']?x__TRȦpǫFZƠ|ԁSLmmOOݸȾ'_8`"nUѥF'}2(GIA{X~SA^m/c;jڨ+ၛTk_a6"C8O'Uqz"Rx0xD n9gAƿ= zOs 'g5)1oX5*WP WzK%:7k1y}P;qpFwЙ4| _nGGׅ`LӇ =4[|mDCpkk$~Wlm/ f{Ր/3gk4R?/ zO ſoՐny=>R3c}Zn.BBXAg=نOR=DM93r#U}k6#׿+i?q4,1SSEc^奮8bm_t=ngb8f S[[y} TvS#&sA/ۼ=zE- ګlUiYs5 p0M5>Vn)g[8Vue}/^A `3YO6)1áh ړ/Q0F;RJ},5RE#I_?03NVڻ 7ЈK31Lpzd.GcIo1LBnF# GAyOY j4·y'L'=E޹TW3$_goڦ%[#⺎wzt ?Ex|o9{dOV/I'Ke#0/ܶvB?zOkw"!is[Bdz9o"8ъ?Z:}YxIOR \Dr-5RuF8mcl|'㨫[.x;HͳόU cIV \%iJa*z$D5!JrDXu%C`>Y"A3H6 iDt^ C,1ʔH_ N,"^e=Rΐ6ӭyVQ3^j@U vc?v?;Ge|!%Łh^{ZK |~P+LZb0ӟ946pJph=~1Z}ZYj$Jw!p|kK9L3ZR U3wuN SŰ Gt1vJBcj">gk`v{o'f O,fql 1Wqӗ Ha>)1_ a'L!ܜ$DecѶ3o@ЂO\[Iv| UsF|d#g0;<J~LhX)>1y"!JHLWzZ?|tu> fd֝?4xItH7aK8z9`9j9f蛾'8āyQ^a"UԈac9m}kuuU9*,upd ގ<ݛBvl$O Q|'r\'Zb<@D݀t؆Ƞ?ǩ4x4^GfXdq?3f8hS80+lȻ(}×vӄ݋<4&7ڞj1s[q .1fZLjǐVq&G9%BC<ɑ9>>w...yX$ڟNݑ8Cvvv>4w'Vt sew "]3OznONNvh5|7ȕ6GwxE{ jziZ*Y(4=rհx1 yۥx jziZ*Y`t 'ey!5 VVV۾͛,}o(WX%kW4B ' ,Hu85d20#k ?OY@ }hwO2q@`yG݌[muu)U0{Z?,T[LCH@*}[1Dlتnk֣Oz{D`I+] 9 FTe#ǤpSL(8MY5+ dT*)jJ=]vJ%5d+0V5JfrM5Qˍ;؏?o~x,G^uR)ONCFIzP/5gAũ @-/K'⸧'&Yr.MA@:w'Di?қrc,UԭVkK:[-@"k//{[ߪGe2^xAҢnlook0{o}_R/Ey~@*5`}+~?N~@*5fd Y`_^\__FO`RL~yqYb7H? @ Xb 1Yf(30#k3KmUww3Rː,wݣ. b|~Hߩ`+6QC T SAu+Ad{U֬G-KҪ M$FGIs„3Y&5+mlR%jJ⊦4^m.;dHF)mf&YzS$[jKH@* C0ҝ" i=|[ՋZ+d UuWmrx4.i8ܴ wnRIoI3\Y5H%qRp^6++l?ʈ-@$=ɞE-KӨThVD&k(Rj{~70ֽӸ7d7K#N $hjyu?⸧Cd<'gzQcdk:䙇Uٺ@^[ |~ZWT<0>x~Ubʕ~@D 5N^g\!xɄƝtf=jy̐5x"m%WO:1S?2Y-|-z;{9V*R+jb"`p4 `QL }f=jy5X~4+2U5qrA_P-|M aGjs )֪ʮm+ `! UFN3@5QceH G=_ۨIR%jb0R. f 3Re@PؚC`IO3ehedr |+6)[U R(L!g[St32r-P+C (*̀ x׼M WjNid{0Of<9AtjSeTfPe$B YZ7c}Jo[E@b_8Cvvv"Xb qeeecccuuU\&l5i0V YDN[rL_ cӓ8 bYPa[9zdzQ㇬RǷx)% KELYL*, #4JPraCK1k/8l-=s Y7)WjN؞?knPX~ mDa%UidzQ&s||]\\^]]mb7H+?c0gΎV@lA]3lllRǞ5mnONNvh5fd Y`F5fd قyq}}]o`?cI1g Ţ@ ۛ{ F2P`-@"k8d 30#k,KQmÃ{eA !u.<XPSf=]ՅJf=jy5D.\6:=pʹia,4JNi3;HR/Р5@t3tnRIo ݣ݂Vf=jyܐ5X>DŽZ^!Z}}PqwDʁzOv\>mnD 5 $Uw o˸> Kf=jy5LDvnݺ:^qD-=_ EnNZދ֬G-KU/)*G-zfMZ0Ŵ{v/iRr29W\QC C7@^WA% YZ3d -n34y{ ;$ ;ͱRZQC A7[`۽1.ԝPClzX!k,H-buRrNA催g^p]Uj|hf1==(jhfӨ V5WvKNz[>w...yX$ڟ13dggGoH+Be WVV666VWWucښ޶h'''z;430#k3l70ڟ1₳bQo Mq=#~H@(  5cPfd Y`F5fd ۪fݣ.Eb<|tPmR5@8þG՚c+75Qc҈S+WD҈ \ltzBs.-AX=p[*zNQC #KtO@]v)֐|YZ7d DZMu2Ke*Nn`nunꃟ퉷nG-XBiU J'E^i?қIf=jy5XS/gp?ON$Qݣut?d}~NT/F/5' ɳ,g >QC }tTn8rm6[YZ?d C~8[êO[ˣ)m*,'11I˙ͭrN92褥f1d2T$pD 50艖6o"@LkJ6kؚ1C`r]k֙@^SC e$/i55}wcAD B5pw)#AlzX!kT1q=arA_58@ d~~^ ^CRМi5Tr!di4j]c|llz!kry;ǩlfcg0Mh{yԉa{j 3+' zc=rWf=jy5X/I~NddS1UX$|l~5|O?Q<.y2୒Ppy1bV$' by5X|ӨW.UdGQy\y9u޴zAe3UGPadZ̢qI?xBlzvWWWzX, JO72[DP׌+++gmmMo[퓓mc Y`F5fd Y`_^\__FO`RL~yqYb7H? @ Xb 1Yf(30#k3=͌=G>v!ec爯@D 5 8tM7>ٚB0pN)EEɝyŢ03PhVt {tJzk.u%ٚqC`9F0y~9NiS zP/5{,Pqw\Oʁ*`,9h΁j PcZN'V,3[99ۡ15fd Y`F5f uid&5(zoo;1CBe 5`0#k30#k4Vuw7V Ҫ yGW[zS3z6 )=A7:WU%[7;ͱRZ 5G7[Рqg;圗5Qcr_F[ej催g^z~l|RGbz@{ѢB Q  W=wD+=P`ak֣ YPG\Tٛ[%qF0U5I%g8ҩܚ!}$PfvryW(d zcӂ[i[<~,w8Bs 37_@"!h+SQLџΣ4+NIODWf=jy5X\ Qo9J3z!|Әr洙F:lN}ϗԏ&q~i1A7X H!i[݇niYHȡl݌KrkJٚC`)>w...yX$ڟ13dggGoH+Be WVV666VWWucښ޶h'''z;430#k3l70ڟ1₳bQo Mq=#~H@(  5cPfd Y`F5fd mUww3R<]Qg2VW"AZU}3G`HA2"mR#zDtG̰c4ID7Z\\w]9 N([n0aD.\6:=p񷝽g{KJSP~| wE^l?T*# .=f>I5SvR4;FI({eqJ<ԃt^jW#PqwD*CMg+nG-X @$YG~W˫[=}Jۚu$@`NY-?.+nީ7怴A*l{t8n;kP0V}x]'r?[7CvE+t@,Xf=9KmˑN(MY$\`|4BABsRg@舲EXc%/7nYq/aP4ɫrJ3^wcAD jj:U?ESiFVs˹āh u9|J@l nY%ALr-dUS#ˢf11H'jF3,M?$_kV& [jtB\6IH7RX-%f%@5< @5Q㇬`QڔUXNbʵ2jDz@*r2{*~j8Rf,0]uGf/mz!kXyW uxBITkrS;ͱRZ 5 kis@Bbd1ӉoAƝHYZ+d \W-26/V5WvK1YLHiPle0 @|YԂۚ1C03}.ʭY0R UjHΐ$#뎫d2$f=jy5`f 0މd+GB,bMWa9H5@BZn@f=jy5SvvV.kB$M}`Gw?ڠu>[v(#K*`d*Nn`hUe}Soj+;[zsLv SP~Y˫[=}Hԭ lz[>[<~,+ԝRcD\6e1>Ms)"!Xs Ei'?F~LV9gp<-]5Qco3U5+2͑4h1A&tNs,"B Pw#Gʺ kj^.s֬G-?:͊LUM\W-26>)4j@-$HV5WvmC[5ehJ&Xؚ1C`r ;hÌ}ѥS=' :?1߯'Hi 3(5:@٪Ҷf=jy5`f 0%.x],bbWa9H>?AiV?$WK(84K"G Th)Y&Kg2'ǖ*"5Q㇬Ph'4\y9mr99ۡ15fd Y`F5f uid&5(zoo;1CBe 5`0#k30#k0n먺-]6=Ruu U=r"OmN#S@ZD500 ! _9e=3~[ĒMU?_b" "7ϻ%c?(Gpe\qYZ7c}Jo[E@b_8Cvvv"Xb qeeecccuuUt*sF݇niY" }"Nغ%z^BOck֣Yݣ)m*,'1$uni1O^DńEw.+Y8[<.5+NIF L^ؚC`J87IƂ\y9D2GKhpIJs:JH@E 5gNX%,=lzvWWWzX, JO72[DP׌+++gmmMo[퓓mc Y`F5fd Y`_^\__FO`RL~yqYb7H? @ Xb 1Yf(30#k3s붎eZ$=R$F^=w"QGO)=fNu@.@z3Zelff=jy5S+뮫7}ٕ+A" \ltzBsS/eU?ifvf^ oSP>A݉JS?{VAΝy HٚqC`NJȋݣeqJfS zP/5?8ٿV4aZn`TnG-XlN]z9yf+5QcZ~4>ٛ[۞xfɹ|DkPP6D!ѕWdA_[9Ѕv/mz!k0~=ƴ]oHQmnݙkZ^i:/)Qqgi2TR)rDKrkolz!kl)ʔk& O;insLFFЁAhYL1HeNt?LҦ3Am]f=jy̐5X2$WT&(䛨Jr*'òwcAD j;0N5pw. ׼ /p9uQok֣ Y咣NhPn ΏO O$)Ѫ7+a="5i jߝ'/05.Ww 5Qc2 XO 9m7F2i:B5㽭YbQ=9t6k.nmz!k0T20f'$",& ezd[B"u'Bu? x 00vO$+M,+[<~, &oS՜6H NFG޸@U ߨ|ej֝u?e\6:"V,D=5Q&s||]\\^]]mb7H+?c0gΎV@lA]3lllRǞ5mnONNvh5fd Y`F5fd قyq}}]o`?cI1g Ţ@ ۛ{ F2P`-@"k8d 30#k̭:fjKIV8٭uu1U0v19#҉WHƨnX1vKLkU֬G-sjUsru@vaX9Bvˆ \ltzB8v*zSQ&w罍x dϼBY8?tj`wRIoy&~if{(bU5QㆬRّ_8ux's(#K^T_Zpz[gB@>nD0n8?tj`R^i?қ[ QU֬G-sjy@eo]o?v<޳B|*lԇ{t8n;kZ^Gơ2RPeM} fk+TXlz!k$ZQ)˹\&W'^S琐j\ǔk& +˗3I9I/8?ZHZB$E,u^U֬G-Km_ ĒcV;9,_(m9圗|͛XHE-h0Q 5Qcr_F[ej催g^ipy}G`ҀF 5RH-hxE`A؝yf=jy̐5XuaVILUM3L4v]7A] UjWz@c&S16 @5Q㇬3e^e-xDY[_@"!ڤ*晇r#C(8@TGYqJw\O7yE`k֣YS4:-H+o54aC&}#A'#N7|%.@E 5[o|vBdk֣MXߵ8<<bQo Wj`$ΐ $f\YYX]]ե&=kkkzۢnlook30#k4jbˋ E@7!e2[DP׌q0C5fd Y`F5[uTHՖ.*dvG]]$iU9ç aR%bI[1Dl|Fc5QcZ\\w]9 R^qY4.i8S))5+ '=Y)bS*![9~ifvP=v[ π|~,oK:\TARjyu?⸧yfɹ|PPZN"j[9PmOYZ;d ݯ甶xonmLQ,LG0tg-gklQ@ Z Wn/mz!kgd\PSTs j\̔k& &0ߧf14@Jj@]hTCr@㎯Dۚ1C`9uKFCxt3zxQm,^g4ǂ@jj@.Qlf'DۚB`YZ:s) T ya7^U͕RGbz@HB Hj႑ @ 9FgtOYZ3d :]y"; >4oӕ JCZ HB (rJ[yX{K9@)m=v[<~i0E:^L⑂3 ߛ0#a~ ˁD%Q&;SBhr"J@ `84+RNO"pK =+[<~,]I#q:y5GSe,ȕfܤcO *XGOiҔ)1e"mzvWWWzX, JO72[DP׌+++gmmMo[퓓mc Y`F5fd Y`_^\__FO`RL~yqYb7H? @ Xb 1Yf(30#k3s붎nK\<=hUjKi#y."mR$bI["# `e2cimzX!k0V5W(]9}  9buˆ \ltzBᔧ@q NS>kVaඳWћ}3l| "0.;dHF)mfW gS*YZ7d 政ӨT@7uۖ{eqJ y9N]$i=U`T 6UqӇ[UL8ۿ=b,955$t8-LQelz!k0~WZ^)Gdt[N1 DTagݣ~B(|mL>kVaඳWћ}3l|r GNF:RQrJY qUdkm=t)Q4ՁnΠ.(^jW!Pqw2~VqOL&1nGA l jI{eq`Koi;9LfOL7Z^hy3]$Uٺ`n}(_$lO޳-5f  5ҫU-pR53@ʄi=t,J9DCKrHFdo=Ш4PxW(;tOp U^7Bd Ey嬗i+#A{י:ZOH F5krjK;ͱHZ3 rN"2#5ؚu[?ЕXԝRCqYբ'v-[\ٍz&YLHi4SI\WhXefeh?!s u55"Dce'0Rc3P+)"D79#6|?tI@xSloU?9) 7[0a& .F1\I޹̔2[hԁ4 5?YiVWOɤ5@UkG"L^j}=tf2[i3dnR1'/p"I%l45f QC ]0;\eWJO[uk?)݀kwqqqxxxuu-ϋŢ@ dH!;;;z@Z ,Hu͸KM{E>99ۡ15fd Y`F5f uid&5(zoo;1CBe 5`0#k30#k0n먺V^hU0>=Sm2\=ҧ4|ו>bh!aU$O^>=jy5S+p>ضr$F'tN97^ӔzmNvLr5';j`BE3*#RQrJ2ɞI.ݞrMgzQㆬwJS mL#)Z}f*Nn`W*{{/Yr.qX*g7v_Pa[ٵʁWmٺ$QnnMUC`^Z-#D?݇niYAIAlf՘-h4J­jA\1<~,J9SlVKrRh2-5)Wv9F3{O'F'E[x_ srpsL eU1C`QdIN,2V^x8zT<_SXziԚ)4L;7;#Zx@.DjB[ՋZ+d +;FgXʑn J)IMak8rF35+ :9I`dDhz(_RsӖCU1C`nݣ\^4;`ʑbDceI&NGV>B O*30!D!9YƲSWUC`>25 W-pzANwHs[9bdNR;Ɣ[[ 5B`r %jB{ /zcW<~f2[i3Ԣz[3pkH~+ݨȈF蕕/  "O$x ꕩuVMXߵ8<<bQo Wj`$ΐ $f\YYX]]ե&=kkkzۢnlook30#k4jbˋ E@7!e2[DP׌q0C5fd Y`F5[uTxvG~.v~9UG0;8OT[lTQR~G 504ҝE@Dh{=?jy5S+p`Bx4.i8iGP)5+DRU>xv n;{1gYUF7Bukۺ+=?jyܐ5SNRiݔAa#$ .6uփzq_SGW*{p͒D6ZUW<ۿn0U:[7I[kʹQcZ^h'." NC$c=[$f}x8l|mW[F?t;RpZwd=?jy5Xֽ8[~P+ԝRc."J Økt f+N?<ןL 79Qg~L۞=Sm!u* ߨjx pz?^#NGD`_O~ lzX!k0V5W(]˹=]֏!iD.\6:=pʹ)aB4)5+XS*-)OdඳWћ}C LpՅ2N2R`XǷUW~JYZ7d 政ӨT@7egmN%34kE$DAԸAũ 2 P˫[=}{z^i?қc%є ZU8ۿEzIvdon{lz!k0~WZ^ A.@*< ݣPD^}`mO޳\ڠP}GN!0i# dϽԸ3K5Q㇬mU^")kt`|&,@JjS/x n-m:,k%49Q_ɮh֬G-"Rrb8$W(RHoAK2_S[ziԚ)4L_`K5pw,L%b\`26bk֣ YEe,NZfߜ 8 '[.RrS83A/h0%YL8=4)|YѣdiTr^ $_Rpz9De֬G-s RQׂH0nzex&1q Uf 5`$Ch<:2Zx֬G-)9qa5y槈Y[_@"us (#gBYQ'x\a9D C 煐nngSxPtzBc_"5Q㇬`ye,ȕr>j1!pF3ۚ+~/F蕕/ 3<%R̛_XTlnzvWWWzX, JO72[DP׌+++gmmMo[퓓mc Y`F5fd Y`_^\__FO`RL~yqYb7H? @ Xb 1Yf(30#k3s붎nKVUU[$ wHF9=TP~G 50fاGb mXgl=99ۡ15fd Y`F5f uid&5(zoo;1CBe 5`0#k30#k0n먺VmUwCч>zjKiݣaX$?xj` `~&T$mj}5QcZ\\wՆ[/:W!$F'tN97%B]pٽ^R/jxN~VfTz> :pNmg7"C7XǷ"IF)mJffk֣ Y94*:MtbvuRC=Hփzq_Aũ ɠR˫[=}ުfnGA D$p%A7XnunzտѺWv+uf=jy5WvV˫-}x ǐ4 CGn}ҩ3yL|mW[XNt3ice.Ը3^VzJu5Q㇬쓣O%r-^`|$$3r@Rh2gq*6RKbʕ~@jnrpsuF 3^m20֬G-"RSiLKQ8^SM_ڈS?zI~:y*cӕ5;ͱRZ3,lr%u CN5Qc"t2u^ֈe T=2]+3A΋Vӕ7ܖbi0Sn^R@W/af=jy̐5[RQۣ8lf%H! \Ӡg46=IC`)pjn07*o:)Z֬G-) r$yY]MSX&QT^^/b" ˁDPx32V/-2y"X\{, {kV7XPl?>"5Q㇬kF*U&.&w:*+o54Ra:QQ!$VxÌǼ k_ 8LF 50n޴>˶k[ YZ7c}Jo[E@b_8Cvvv"Xb qeeecccuuU>',Yx[=oy[xo~S~5[uTxvG]]x|v")ZU}3Ֆ.3 Gpz?^#3SF[9IHmzr~x9̩UuWmr|] \ltd4rnJ4*kV}"dTifv|5';j`"=/zg^'C${5VmՕzi\{vf=jyܐ5SNRiݔA-OkEy8g zP/566Pqw<䵼UqӇOo+;Yr.MAUyųz/j"+ɤI:[7u}t݇þlz[4u-wXas+5# >S5Q-{ʞwz׻釗XV_xH5@NeʵԀdLxɁf1N? uf5 iJrfrpsE rmy7YZnx;Ld E&2I_9x8&avBXHB qw?1m+`!b\pli׼en;rf=jwzwO&e 5X\Ƣc-tfAB催*86>ɪU͕]Ù ǜXO59F3h_VzO7A9wXؚv{b)ܺGBTivѳ@"ásAN<H4DPÓL|fArd#(5Q˧QYD5Lx[zA ]'ldSo ˁDC-ycJc?5WH.)j` o k_VՄ#xqc 壳'lz!k4,piLVsL##r'O?ba[sԯrzAS&#?+s9VěgVW^\C4Ҷf=jyd]ë+mq~~^,}'{ F ҊP`-@"kƕooӫ+e2^xAҢnloo5|ƲD%ʓ5@T@_^W @}\__7{s#kH__?ַUo,%g?Y}on3g V뻾Kߵ'?=Ƃ<3^xޠ7IK_7O}S+׾VoFd}ߨ7<$ě kvO?'Nx;ޡ=d ^gL<$3&k%1e +k %2?]iM__nܸ1 Kd >+ beopܒgy{å >?3 0f &57;?yo9E@<ċC s||]\\^]]Kdɍkpe:OОz)}/Ї?7MzVԣ?^oŘ/KƧ?[!,GKnONNvh/ECwf~3\fǓL}Ǎw (^*n:?-{+?fx){k2>K+/er`l7w_RG &%B=7_\]AGŭ7ۻ|-hH.70=ҏ?kϏec^p]3k!ƻn#7RXZ7'g;\F;Лmc >я~K~o޼G%OH@=7f z#;pa>򑏈OZoWW{Q<37nܘ!QX8߬6Nm$OHax?`dXc1>򑏼⋯{6p|c+ z#G}3z @\yߪ7b9?! 507Wo:(7 z|>7"j6T @$\ su ~w~Ƒ-ҀHO  t+`Knze廾]O~sm}cz#xDگi>~W~~ F RX ו__7"2vp,LO}W~W^?@7Y-Rc}Ki>0?#/ :ݖ`;KଁS~g~7^*OG" Og?E{MsGez~+zcn 6HՏ.?e _. 8~LY]jM#(dؚBl*DDkM.A78Q|EOljƇM1 RV1 "ʪ&{vn7) =s={o~xv9۟~]]m_wO9rƮ*g凊&*[e9@Ts: ok{B,Rgw_PNӠgU5eW0o(H*10!Ϯ#a7[p+kDz޸.;3tD}z^VU%m$k{׿j-vpIGVFFIvmӒN "V4Nȡ}bjZAR8x@vecAc':[@r3$j A$Oޚ[h!Eǯv͎*(XX'v՗Q^6ZoܽٿMݵs:[ӯ>#ܳE'"nOɵ_:+e@pAivc[r7Ьjyf˾Sζ@{w ')~hG|篟'o_xW T+!>:.޳vNw;@+PhC3/.=R֬G}txtݠ~n-jݯ"1"Jĉ'^wFlM^]]*j ^п>-gڬ*?(75.cB%9M%ֱB_.L_a\syMHxţh9h6B!]/wM)ԭs=~sSŪ,|L6uԦfP'JV7,#;Cգw3WΕZku7! /s+jYV񸊁K xs L_?Z-FB U@uykFQ'='ڼ dF]i'C 7]dJþSkgΜ"m?m$?m?Eçf=k='šw?{YSRj.Wlm?YR&r^SS#7R_CZ6@lP Ny}\ j C(? 1KKö_jۗ4ܾ+EϋEMx=,-Oh_m#iev]Y0eԨQOz!_eUc=~9ަ*urwCc6sȊ1o]uj&X/lEޣUބ - MfRO̧l&ZwS[Gפum~0Uж46cEckm*eE:0nB]oco קK捦g&O||;F&oPd@9*!ON''ɐ{wNmms'LNIĒ˲n5棾Oߏ!a?EB楇MI_?)\0%SSw۪'ЩAvo]ioLX`2NʄmۖxJFcPQ.?$WހA>r)o ZT%նCr)Zj:AAWӥ^7lذ뽌B>24!`7U-x;CZM^l<@VkzLf:ʩl&/#gŮ9Ʀ6^]'I`0Qw{|=]ǾHN!KNWY }N/ދ̑b ɑ3ْ /|GAacg3bXS{-&qZ\}:{R'  $^'fu ێ+C8Jx"mg^O}?v<`aKD'\|jߩCtMM\ƥ $pH-x>/ )uW)B'TϫJO֥B ƤeC="=fLZVVWyGٮeW/o3BUU) I-xxiۃk?j҇Tz9>ܰ+۬Yy٥Zmah|Nت_Zn'w6! s/xu@NJz&'U)OsD//`T@_snRΞ ճ:H+e}@՝ǎ]UԳ`3+\9V=# ̿s-*O qը+ىAM}I s[BpOX"J&?:yU jPooخ&tWiй'LY }5BaѾ}䚐1bUkl ߕ-(K..T[,Q闬rUܰD޻6]Wu_|ž禅aȧ.Ű#a7;>úQC=yԁOӾmX“i ^ UPFwjb]{lzBEuqS*ݩtp7%{ތ^%Rŝ?ܮēGi}O*濿o)/DW.<מy7ڕBĽZ ?[߿qƉ'J51cF8k/??k.(VU~a*u۶mάAp>ŝ&` j@Eso ̜XKoJqqE:;;oRE R#g`444NdpWMv_r+9۷owf )4Z\|TL^KXggIJ!xoH-Eg ˋL5)wŮ7]G/֤ .-\q}}} wȅr< P;_v@q✃Rf Fw^s.39B9N9Z; .yNp/}c߯ !ۏ={;PDjqATH>S>(]qrNZuA¥ i.buWۥB|_7n] 1YW㿫vtLMPB8Biũ߈tv?#$TSoUly_/F{jZ[2pj0١NƠCHNW:;;A׈D>;!`?fM@^tݲ/ԠMw>}شMwg$.Rh~{!o+3bD9rЀA#?_PgCơNſF9_׾uLٻ:ħ'ڷ~ɟ<Ǧu\t걪#LQ 5gu:y?t(v?B~Ġ7үGؼ%/&'Wޏ8"wVLҘ$N}8cپ -&?mԱe3/`ֱeYFGnwu1o1?9g>|&iָ[>IC3监#BMa4>aHc唝֕vŧ'ҘUNR}3d gv| `Bz0˻񾝓AvIu}SbӺR2"8a#|qhAEЀ~A#:;7wG 7?7>́wڌ;ڌцqa|d覝Mv ĩ4&qoAGGGGGGiu7 橜ՄQFT[l9 >'|q3:::::::Y_'fh۝<_a9;J\ 7~u&/6\lM"udKȑuTV{sQeX)Ȼx@GGGGGח;!.%eg`ĥ{.!FnM&7HTӺR2B=_0k=p/쿷G 0ى^Ҁ|С#_wg=5=0Ui5'L^b]h 53Fw9TO_98GOkڌ\Nr#I5(jQy´3~%83U}$}kliX 07>>,n"5ZDf' Mu{3aIG҇|zovŞA/9m[_۲M}OOp /z@GGGGGG':g?;M\t~g1x㝿Xyڷ_[i|x96(ƾ]8עI1l.65(s~Wo"]>%u:VO\w9 ic)GDba9r~ٯGl;wN<ǼCFKw~/1c|-Oǻ2 (;љJ>Vᚭ cqű_>6(']OP{T ;0r Z]\brV?7\+%#Gp4v O❃w 8hp|RM'C[tLO15-HtaF{͗FG_)7j^<ǫQQ8X g +5:^ч>BG1ۛ9O @^c Oaxoon|eڇ/@GGGGGGgvȓ*2f8~ÍCڣ S67^: u8cg3 tԞdqwO4j7+sQƆhqQCGGGGGg;ϧg۹ `&q:w&OqMK8^:~vӃ:;??${D'zD>_lGLa#s3;c=b;+`}}rj^#Gҗ7Q]#uMyH6c-'b-=f^/g;3/vg|b0;&ȴH~/2<`!&cu0{?;i@GGGGGG'uV-_ȭy]=!rXj(1߹h/LV랯MM:ϮXPs;"g3xq8::::::4ڶu6ڿ8r5`W/CS}m)l{o]]ֲ~ 5 G0~ɅGlY{He붴}znZe/9pMz՗Jbc=ؽq]@#|}q5 GKK˚5kJJJp##].@q8E"tETo5`֭t:KhiiYfMII ***ڞl1GHʊ@GU [͸aÆ#\E"tG#]}:Tj԰U3d3Vt6>|7WlsN;5"DJo*573ظOqN_!~1VvSpNJeg'q*S5$AaN6|VbNPO;+/ML'qޯ>p-gaM?If%Ybc\# xLdjlLL0T eԴB NRb%ǭ{ǚgb>Oi|fƻǨ$0>[RrL,*PR'tMM%ƛܙyf)6u%g>E'9(g)]?qRT>wsM" e19b9I)q2Y5,U_=E9[}d],4ڞ]UѵϺWEԇEUDD[\#\S$b$' hO UE~u|m!f!9TuO5=U'n=.&WѪ9/%[6Coɞ rekg9jЪr^KimggJ5L6k*MJaS8gѪCANo+0`bu3dh %x=W*j?MjL~#6u\EQW CBEAҩ rQUE4 ROy@DeG=YCTrSJG%xB|)`! .dScZWL)$f\Uj()mlJ>KY3׶.9ʕJ;3_ק]*I16]2gey:^:Eudm'z\M%Y!7 ޒ=SZmoc% M+T(^I$21@WJpXKVAr*]BՖNH}MȮ? q 7xuUI5ɚNQQ75,X -ԾoÎgL89 P PXշ-ujUcbOnMQ\n^Ho'ce.SB[ 3hqo}$v9UmN9+ֆ`Qɚ%\M݃-&!ѝBmnT7 -5Um/aVYPWGM\gMPgL)BL>qBD]|WZi.U[z&O&kBEH!=Օ"h^I4$N\1cgnKߥrSϝKgR}aTX|4ːp~]Y JlĨE m7Ǩݚ@ *d[*gW fV#e|̹IV?dV:6u'w S3'ZÙr$/ Y8m2==n̰>-a֮NLNk5lDz -w#lYxj6%dǢͳ;Q6S7iω:3^$rnIg\l;ӳpr:$ҩBcCH;R]Mu|xo$iRS'@A"%;mVSFʤ^6N[d,P!#+BNǮCːNdM5S T(ҟ*{Ymjd05}A;mJ>e'+5UFRƾ~X9Tagw&u]Ї^sk}:L*#N{{b<1t8$VjH; q *~'w0w89Ζʕ+֛e;J WZ&ZOxv|hǪCʐ> Vr\Ƅ.| Ic!/1cJw\ZAZŶًVǑhh%1$@^<C:j:Zp9ԛ1A˅zN5Y% >a,Tak ;ڶګ)?]2UAU1vޭmP\:ΔPgrn_ll5F\͐'k{:SەqJ M&$J;x~upT7fi݀8د 笏a"0!PX@LxUޅ>U@S)o2"ohڮ~GVg[mƄ^ܦ;!^ϓ Qh#lm=~' )IGyiAg|%;1d`iDz -i00xЛ(ƹ~]|ٝ('M~3ufl bk:R8S8@I=!*TC0ETo5`֭jImemOXo~wRTjquYj@_{.S]EUL øB6 R---k֬)))Q] S\lٜoV.|%$m`%۶֝4zZ녕*q)=MnXr#LX͊\!l5ճZ/T#Yj . gQҝY$@.߿k>*-%8`N(wP>H! @GD3.@qÓ&5C# _J%u&gC iU͌iFͪ6Tc@ u`,{IIm!y譬>Y@r[PN$i$fhݺuOzgI t/]TSTVUuUEj#oSlV+*+M}Q揮t6Vו;<((J҉$Lk̮VU $V9Vu \j]YiTN'Wgu.MѦ :¦ WVxfRq.*0b[AMOU\a}ιڨ+i!Rj#Y3{P[Jc @/T##眨maAiyUik'g8N,Nզ :¦]U85JG~'uh[uW]CAmϮV>O- @oTZDݺwPi3Ϙy++jDϧ# #d\A)jEޤMV ~&i*ÎCsүjTWf^Oxnb~[ fX= #d Pp JG0赳[}F "&\ ^Z+|lW-}VZU H-E=/ns=`B3-zaӃXaDjtw! muFVJG^V3 ;ʇt4UE}xPz) @_VU JkcDSG <.aF<*5u^tMwٿoLogۺuM?ͦ&mՌVkۂґ̗ZĂmox4EsTJnjЧU/YX[tȨdyS. 5bĈM7n;묳4}k_dSt ]#FL>6#Ӄґ/Mإ>7|.[[x"%j@YoR[4W U%;絈U~\ z)]#JkqCQUqc'iF ,f*[[1o̱^ Yzg`V!u 13د2-Ny.zas_AknnPnZQQVd8B:,5* -@^ڌC 9]"ȁԔZZZ֬YSRR.@q8E"tew =bD9#TTT$ea? @* -@^ڌG8E"tG#hkkZU3cFDiRin&GfԬjSOV]}7՘ceU8D^ſ3\r[P~̃CJAæ8jʪQ5P@Hk̮V)eFk,ueNP8gjIzC$m_*O֕FU}ju!ShQ~ÞJa?T%pBueuckJ[Y-](/-AFV&眨S /VFtZ)Pil=!@ \º/sKQwy]A 2J{*S89kK]%FBG(u*-a=6Z9< uQ|:VUA-@F=~J!sWE 4dU4YOCUv@U9AQ梖[\72zp5u B͛T q*qLi)4z;Q=CWV>:{mZz="a; %떢΋$ ϕ'=?lz# muFV*jk)!POHzhUH^⼆7()mM 2I{*S8BQTV'_h~ 8F!2bW2ߟvSpAB,-@+sR؏|>U#hrd1"14y "IѺ"3р~TQ1C1h<`n[5*j]'@XfRru DЕzS)E>OU/U1VAAoF0`V6v~8@/Xu֚ -S @J0rteT qjAknnPnZQQVd8B:,5* -@^ڌC 9 UE")YD w#].@q8E>6L k{rw3GPH-P/~@U [`s3s @q8E"tGmՌ4cUҴJ̨qReMGwI&“Fz@ۿ*Y>[@r[* ]zasqPVͭ~KSMQYUJU/d3b)^Jgcu]Y(*[+H/3ds>Nrk̮VJ`U`.Fe0U"ShlJu(\Ʈ؃N鹏8BVzJץ^鼕Ս֮oqе0*ՈF9A]ދF דgFoQޅsnV-7YԖFFt 3Ҙ?T#C9Q ےWM˫+n)VEMOU\a].D2utM(Bcy*R8`#JO,#T>ܙAZ<7 @~(uC5Ք9qH:61OT@\zaq]M˭(Bè>_( +ͻs4HQE|&Z~;&C01b$ <.gK gzNwsa t[A^|@!*oU@.S ?> e~3`V6 اvY0uwAPU]\~D]6#|od= " 7Xsss}}}GGu֊ 5Ķ'[ rYg}Ulnf2dgn^ D8 Ҳf͚5܏tG#].@q+ÿ8l05T$}pB )@E[ agUlnf85].@q8EA[[S͌eFͪ6*rhrVYf@~h1Ig4P>4L>JUA\NU.\Z)8tЩ6=GTSTVUѺ"u5aj[5"lϨ4&?e~X]WWCTCRVn+?/H RTZDs 42cU@"ٚk̮VJS/lz#m]uQYhƕ.y5-qʕVn=e}+PLFik'hKjCjKg]Łb\qKS8:K W*W snV5p9'a[؏S/lz ǥ'Wfb9F[*!y++혣Y)>O!Qb=>ڞ]}^hD2EMb߆X_>JkpAWzaq-͖2 Q9A\Έ{;3q@GccqUf|R_V yP$irU[u:uyrLVKԖ[{fttЩ6=GS8gEc[+W<8*3CՍ։(B~|J'b:ͧe(tv^[Հ^-YU`:@uKѪ"0Y;5#_}\S/lz#֪מgȧdH>.oNX/v?A*':\$_ *vĝW %Ս]/?ShT#wVNQXOC9/뤪 :vOtL6L);h+tЩ6=G|uS|P9{^3-F\? 6#1J T*ƪ$Q2cH25{okizUAbi%-oNO4:¦ԓHQEP+ɗ ԍMs.䶲[A^|@!Js$' K^|~qQY]uc0jp}($}EU6#Ӄґ/Mإ>7|.[[x"%j@YoR[4W U%;絈U~\ #S|8.?*SS=dN3jM`1+t{[[LU5ࡾ*ĹnB9as[~WQmSQt  #žJa?T%^aT(p ; ת r(sQ-Ղ@S]y=}H!M{*=]#TSV'D)(A"շkx" kg߱)y^u^%Q|M>aOa{鷿l[n݂8BmEuFV^JlM5EUѠ#z) @o* KZ@8ձ{[`AW>aO6l٦o|_uYgM qmmfɗ'Z1"ɏ&طmo Jdbn]=~ܧu;݅8Bu 77`++2sX?,4b](yI^fw0[ , \9H"?="qϧ*qqx>AA[ߌVa&l3q^ (5ZU7:A͕`V!u '<(=>OHCC \__ѡlݺB )/quYj@_EU [`vvv>֭apdiHVb5k֔.~rڅ^x,^u .q "VA @q+ÿ8l05T$rcr#>5qqDzֶmT_R1b={hޙ>i$ezC~ߜ}jxS}]8B.H۳g?35 4hK7,((P|U_;v5j=7nݺN:I 䳸&^bAlz'/5l"F\;;;}C _|2ĠAWkZ|u։w!X;' %6D3W^=q8 89t4Y#G^ g}C oΡ#oOz&I&rez wA.H %̚5JG^#_J Zq߿;:0~xwΝJ#6`bA8x2D\AB _o}qG^ D# ^~qA8qM6СCˈ#qDof!Рz577wttadȀT_R۶m4i3&^߳Ҳf͚52GH8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q+Рz577wtt`ھ}{=5F9lذO[};v5J wAGPU6U*z >34lj$`:UY& sgL_B7pAG M4Mj'PC+$A3OJʹlb[=j$Ae;[>-j fJJek..SV}/6_UI@mjz2A}[ꇢS]]4vUZXj[tL^ƍ/ButaƆ^D֭[W^^m оz6øٯԮuw)ط4& YL M/¹瞫=sgqDp2vޏdG*GbзKǨ YUy˺ZvUJ,Zn7_{w޴G ƨkG[RS%y!!ٚkN\/Nθ<`"1Ʌ:Fsޘ#F:S9w/=JN~)W'C\pb<֝[ eƌ1vD[UZQLTu}=0qGZ^ -:9TvY,jm0*d KX G%7A şJ@V^O ﮘ:>zƟc~ZWLw"+\䧟.-Y}Fr$'byqcI~WKyȘ˳p`Jk}Ѳ3[oyyO~+E I,VmlFX/OҜ;n*,fV R)5~njqQ 2]}bs6snx׏n/vu֚=ggwDЖw/l/:.!J KGiSe(?ʗjl-US ԧu ?GjGBCNoO%dj*Y ccjaӭ~&r&5Bf}},G.fy}ʔO^9FwN\hl|Gh[}uםd͙_Ut"$gzsMSUgJX%G̷vFj>e5 ry uS|`{&Y|ϱ)$g4-&sƳ7Ғ'ƜsyƳ;&&V%4:r35n[iqBg3;E5KL=Ymx>eҨҳcFt}_UZZ줈<Ţ9B /O'2\ǸQm5(Bvwqyf$aVEL,6}-~Dᢦ ԧK'^ox?JTNP)!Tm*YI}ħ 8k+]kw.~ACLnYa̽Q$z`6wnmOe7b99RURe+-cZ(_" ӷIfO|f^fثlqwpj$*ٜ.;7ň%*95ey7uղ'%-9\΀7~=yi;ǜ4[F5Q25 jF&YQQvES;Fgdм쥙V}{M2^6*#go,}ޘ˗8ؾa"O-1g F0'wR\Cٯ+7'o"$w[)=$c˓,gv$ȦtQ˸E?@|y'bk"Hcq^N:>XxAV^ *P2oSQ9; 4s'XS3(,?` ?bO=.E?ǔ]M Ol}Q>zns̕?c̙fR1 /R8/#־BݸO%.ݐrnJo[R~2;+Wnu{1L_mNcOP[k*fdc\gY6S\b_ܿlƅV qLD׀%M]m/&&ؒ/w)/_f/eyM.Apao]%f1V]fq 0ZǶ'q޲f;]{H³7.|hEpJj&l(OklTCHE8y|`6٥ VELFr`;܊$Eyaoy2#{whS]Hㅖ~뎌1˩jjݿ%Er >^oN9S^QPmkL,rmn&榳'Fff>V$afעfPO3]@>nU-(e٥FӺu#^H K$ʣ۞/OP+r*; Ֆ77}ֈw{μL2#$۪v?~I'$zߠ  ԧW?xW1Dđ 2{A,X/|2c%LKӬ^ GǕ%uXfFY!1W޼`?,.߸+1}bzԠkp`u%Gb6*2[T,|(KOVGwk87k8vc) 26e|hfu\G}i'7n J@FNZ_ W!O7vsc;Z7B &zFS='I?β_6W_Sڻb{`dĿd#ɬ)˓UbW]DԈ} $$gh=f>+.S, %dPȓRW}N/_NlH{$d}I2#nwlр3}NpGjz2A}>LE GX1xW,>F>BTOgqRM8ΔRleu$iYkm﹆oe7r'_|˯1 oHm;>2>s>hۏ}_j̿Ż'3{'O̼B[+.&3~CyĿ;L-5H7p fm kJvoǒ0 &GI ѫ ۪3^HAX{yƾw&%MUlHFԋ. KT aL!d0!b>Va1EKoo=->( Wyt@Yՠ$~k[k{ʣSg}7S~UvE-H?nUza 2#hw87ވXOxGjdt1M9=Pu"*m@ĸ!% d) bԘP29=gW%6`|TVSF܍2\Za,QSM|j"fLUpE cEs)j&qv{]a5$LY'1{'/DdsRw^tJ&OSKLmwZk s8 .,[nqjW P@dֿd\3yH}cKz~q0˜";iKjDH^83@ 'h~f0}(ϨIDۥQzW%tMMdaĈD^KD E9EiU]e$ T}u; hgk&Ç߱cs(((*KB_d7B/zU_!z)zݔ#ȶw^5F!e5$M@JAouqǩ0N9|I3F Qjeg'R{?M&ܺI MV}τ{\m_=YP6߂IGkZ|~@$>;To6N=׭jgtѝvJ#lZrM*!!f%$Jφ7l+{\䧟.*-n&sdZ˨#a[4J2EG_%9R7V6x"s ijva0/nݭq>?XDO(YM&KO?XiuRĵtǦ[?NYcQ3UmN !ẍN޺Idc}dI{X)Ja(¼Q^xoWo['"hhBAϞ6[l Je-~3d{r/Y2X{ұj[R Ec5;}~PDO(Y csT4N+NfpO﷈oc23K c Mo

]sqLџTEeJc 1f7>XP}תIͅߤ =vJ4`ro7N)f`3 :[_^W]̍uja~:(r^=CXwO bk;dʵ.7;ͻ]^w|8 :4b-Q[6Ʃ5cXDO(YSmc7!e#pqx'(=7UA9'Tc_nxC,u1~֝|~g9{R~S /"w՟$bl*ҭQsho' 99X*Ac<6Xe#3go278^%@n錡0wwC[DO(ig ѿ=U^~daޮMcecĐ!/ U>PM^Rr mScy0v5>qWv|̕O|?yȐ{ ~{qcw~j\J@L&gsi_iv FtT_Nכ,2y ҋ:_y"1ϙ5Bb XO)jeZ fV{\55] 鱴)D7?FsTicW<.\xk1QDp^9,KS-vy37O>y?l%?XT!(˻<9$ŴԷ?(,X,7'!{>vvK6`)*9*X` ywx,tyk sszUjiRg+"]:e䋞yA5$K*d>?yp;+h)*l~Ӗ]9gȢ@ߓsqQ?(щjSfZX;oUrIN=Xė;̟wa3 Jm#cz&/EՀKPCfx.#k;0bĈCE"<&QmЬaO]9Æ ۱c@EĦPlFA=v_߷o޽{0W`O85M)_ݹ #q8E"tu5l۶MT&M}ܶm[EE6lؐkqk~Q{;j8{#G,..V.y*+ 2nw镃#_A/8p0hР|+jؔwk r**,,TȄVҋ8B6m2e?9眣L*+ ƥ # -ޏNgI7@V~E[B -޳tXa۶mi.꫱IU ^j\nPe@cq}AdSx|JGJTis :tWYUmPR/5.72o˹#ufӊ6,*.*g%=ysRg3'rs3 >ONh1eab\ҕrMΑ#'߻-7W?z!TQ}eغҨ*iR#лD<=x˿ @~)d➍QPt_rqm]p;=q.I֢'>~> Gqąj^p 6>5Q{C= nC(_V'$TH7? Q8[=m= ՆU!jWb9ݳv$qr}ȉ߹̖d)<;ظ3sqA;=JsM? %K@s㏧G3Xv`N/U&m_^ߏpW~+Vws3]->c!5=w?rsOE&1>vP})̚5m^R~Or}ֺO.Zč2uWLj% ߷TIh,,X/`"vri=3jx~}צ^JlVF*C.B;%99Bvwqg1'?5n=lӖF[|_~sկf՘61||L}.az+no~핍.*Mf׸qT_Un/5Ζ|-bK˧Ekkw^fs5G1R7FB-) Iܹ~=3nln=+zFҋr&M{͝t0 b00%{gk'>r\h9|$dp|Eѝ^ c2=GL2w &hތ.iǟ|LJ.;O{Fbw3~Ndl}7_FHM.!Z 7y3;׽iKlqj&A)Vlc|e 3kO[Z6mʼnSnus=詛Λ+ћқZsUb?*|-Dn5{qS(^u/|MK.uGnT*1cb36Wa2o؝%DyURSpOy8c(~9,rz9-;);A+tHp$];ZJ(G{Oye>!SU.U@WGZ?ضjnra^ÇNȦ&omҸjk5NS?QS^9E)bLDW oYp>eMM ~dT._h_cٱcumD9EiEUm*+9^PȐm۶%~;=({&5ľW_W԰K"I ?@{꫸,ekyG8d#|#壏?~j8}G9x5Gk rHR7Z?㎎}j]3laC*[` GW jzϊ Lj~#l25''L*+ ۸qé_mgޏ￿3$ޓk rH,!3dI._hEo);MMࢾ^jTU&m=Ggh^6Q9yRr4Uy=\ðUV/uU?T80K Lrw3q>L%j_=fnWʦ[KLYoJGw_ \]x[u7cgb/̛ŽL2ٹ–'d`˜*~kVr5*)؜Ռ5J¾\E_~(;[\ᝩeȜVL`挛UbQL;hnPf6lMJ\8kdr|f&VӤcfjSiW9GxG^~.L\ѫ꫱8m=Y^TŐ_mnjOH9 7|v7`;-V<3V Orv./mD6YYdXDj\nPeJQejKU3ʶlI+"W|('9x˿ i(s'=p&[078sOʔkWotQS?;rVpbg{-%@r/4]/D銟~Rt;?=-cl[]s$zWJYg̉g_R&ϲLk_:YJ"^BY!$jZ^eN/bee]ܓz8gϞ/nFGeh]RSEpItJtܟ%{lH%'fȑ⯺9 X'wZtݿUgsRCZ.޿T55aˣ?msn\X}_`Ivho|l"KxMj.%6-g {^IK|PeȤPFW&FF8@>8‘GuE;7#1M뗔_\6sLT%/9ےwqՐ3gΚ5K0DHQT/5-p-\{_/XW>VŦ]kމŲ߾;Οl#3wqq_Kvofs]p% ?qO@rgiŝ6\}GDV`nRYM{?_%y2hsk[pƂIvi*T>2_QdZKQWރ<`ތ`)Pz80dȐŋ۷?eSq_ { %=Q%=lS`ܳq; NK# nǗ\B5%Z\/g\?#Pr yǟ&jogWuظd <6U9}hOofI$[n4~bJ|+zqcyb :NR`ko.1z"yw7WWs6H= ֻC& Q|^uJ;^$ qwn%YJ8ZES?8=\qMMs Re P8gX]W~bsC@#\q~+ָǮc!=w?r#ۃ3Ǯ/YfUWWKSʵc/xCnoZE3Qj||陼] {ֻ;lyR<,Xo6Mzgo(/O+H)^imykm/A=$v S;V|Y}T!ms u^K bOԦpmcX j@Boz>Я_{|3&6dZ9z1WlW<7ιJ+]TݫqƩ^j-ZL󣗖O\),2{k7>kNJƎ;'I@80eʔsN0AfuI7>̴;>tٱ|37ڗ)&?3gDOg,zaqJpw}?S^{ J/4zYb<&m395ˣ_c2)Y>mivvoy$M3nOIpOx$w?Q7'V$I17ɼPJȹ&Po?2Eћ|l2pWc{"PN_uU+nts詛Λ+ћқZ4Y%t*CHHkw/5n /iҥ޵N?3Q Qo.vծmfb;FyBOOM9gOXh= 2$m2R|$w?Q</:Jd sg6'vsZqy*1/nSl47oymII)117c6.7QZ%TGL^/cEM>kTiϱmՌʕpAѪ֨Us |cq#MM .K#ϫA);M~zPG΅)jTHc&JX|ħ[)o2nZx֓Һ^UBrkG=7Nj,_` l_{ dT 1IF s ϯ3_=Y fwn|y,޿mFfz6Wڰ+ հKQAGxs_W8xΠG/hs׃n}JA-pYNբcwg͡1hkGNQq@8BoFxˆqAa- _xr^eB @wmg *-^0R @r0ś ` $~Ga  k~KkNxT>5WGD mG0Fқ)?:ՃJoq䛯r?mvl^0 ذ|/ߓgZ l 5@7#{ϢalUvC3r*`6,>h~FqU|O!&5G1^=zr k d!˛\ 7.uږa>7Y@3q։VI6ٟ[M "\~ܫjisj:ɛm/k%|:-߂‰R[RB}jOvSYg@Y(c{]ZeoA1 ΞIw#Ȧj@wT I}0BH~@R!1!h\} !qJ!L? M0,RWg{pdI؃ Dl*kdژXXUKޕUvR R1ÂͿ+i4@qݹyϓ }$L׭c: Ur't|B %ȃFz8/oo6IǎSKS/ڳR,L[_}μ -?y.[~۞TN;\]ҞjΫW. 54nmlM+!ػwѣp5k֔.ș,"/lqB$!} <}Y&8?SUd22#@~8`|'^J.M#G<#T#uQ׏!qСO??3fJ'oG-V@ ./x;8O3|~SNQIcǎ.|QT#dE"tG[@E/YA@vmhbnQҞj&8t"~G7@ߔk >/۸ŕQK߽m54i%οT5:.T<2;xI톫OC>7gϋ,}5bҤ"āEW3W;3[N>ő)oVܺ8!|ck>Rl32귘:h钚+.k|n]J^AA ݾTS:14YSkWj<5;:$}"xd@bK 1L?n;U_&V_KK]r(~@ѣ䧙fXV@ vJ6b~,Qokж珛Ķ7(Ϳ/mV'p#..izCNߙML" 2}KS|?l-3r͓qNSK+97lęlBIR\=z͓U9AR)ֻ/wݗ4WA-܌~Tt+{CvK}|gЋO޽Keuj套lɞήGNŋ_}hfGw\yπԫkšagRO=+v/m]ْ'生z8p6d@ȭ8l0n~H\P.v(;eԨSOu_r%$֢KLra]f_dRթTodM5`su=J\`' JO.|L~ȥ8Ry$.b_\PEw׈p-Chq}T ;uvWm7g>:]9yS| U՚)s.o_eliKz >0GZy |ф0Fj#V4U`9weXKnK5g߿ٯg%)qwAßAg y^ݜ^L,E.#K~lþ2R[SxUPz:-r( /^܅tlkܾn o^0>6y .$ 6r փ]:usɤR!f7Rr=7N'<ѥ2%~uՋ?4|@86ÞP6Ŀͧw_g#J{yϟyt|1dR= :2֤X,3k`yG=Ww|L~ȝ8l}!p0J4^'u,`|$bWyN+U7qn1Ѷ^{䋵|#/f 'KzWC&m7Skr5#Bb]mP TSO3=%l9{^>˻CFίL/oucDa5薡z85$ ]{LA\60l]8cE&0I޵ #i=~hkA0 IRD;{/.tm# 3 _:+qҽ=+_-Y_L#:-g珩OAn6}TC3;|a7ׇ]8/OE(5^IЯ72d)y@' C6-%>;z8kN@#qy=潾r.FK/0E\A_WCY[A\V*.}r$%9߷ąv6+rJr/i$+\OhSzY5nt9jm)-7#+ *OJp?)D|աNAUH> 7Zn(ǓJZ"/5S!Q}DXɥ c(m@;NqC7);3b`ԨQ*ՏȳwѣG---k֬)))Q]@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tG#].@q8E"tKJ#aB@s>ϔ;>NՅH3j1äoUUCwt KGZeYج^7bovwwwpp2`*v_OOO'''qZ77UUE|AG=<<ىYpssn77UKMx|~~e~EGL&[ q2[8::t:qZWt`%Yd@d@d@d#ϴgwl$*2fu]zh{뽽vZ+RtvڠWUUE0LBO0[8>>t:qj};ݬ# KGt KGt KGt KGt KGZeYج닋X(blG >#Y:#Y:#Y:#Y:#Y:#Y:#Y:#Y:#Y:#Y:#Y:#9VNIENDB`asammdf-8.5.1/doc/images/tile.gif000066400000000000000000031127001502633300400165730ustar00rootroot00000000000000GIF89al½|yw{sstqqqpppppppppoooooonnnlllkkkiiifffc_a_JWc%Gc9c9c.dep/799:? V`adeeffw"Ņ4lj7Ћ8ڏ9ڐ:ܑ;SceizЈَېߖzlfdbaa\=987(yffec^D:97scY Z%b8\9D999 9626+,*'(%%(#$! NETSCAPE2.0!,l;u u'|@ \Ȱ{#tHѡ{2jx/C]S<)*B>YKMviΟ@84C*]teȑJ ƫX3NIPN$vըɤFO$MKKx˷߿ LÈ+^̸ǐ#KL˘3k̙CMӨS^ͺװc˞M۸sͻ Nȓ+_μ/݃NسkνO/CϾ˟O뇭~(h&(^ 6F(Vhᅥ1v (jH(,⋤4h8#s2͏@);iH&ڏ )%0iXf\$hBf㍘di&]lf_$6tih|]isi(y袌6D*餑6Oяm#M4`c 4Bc5tM4pNj9;ψ̤*ijګ믮iZl8Jkf)sb:ZvBh34M Dc 4#5ZL=ԐLzmi phX +hswL۷\[yL .`sA V@g4M!\t1b_{k.«0+~?3k]r.T>h X_,ɱFVkV9[ρ?!ni۵2V=c{GHP#N hRAYiq$4/zָlX'! jpsS+0-75$aq[/.RA1J L`60 c&(q^,"%` W=̕2D) NFrClpC|&)M4C߯2&#ҎKLuAx04LKVnnV.ibhA_._#.% }'Ʈ>9jZ*$tCPp$Ǎr1鯗q;kC%_?*揱|c;iI7Rd-3in\h, b-7ĦHGJRh9_m2o ⴂ8qb#$4)O_mg@ޏu|}rk@QYSTQ5LR4-ZV\*-dJ&凷 Ӳ8J u<('FZ諸(c,@6uh#OrY]=&5vYF]KAlnw[kq\aSWL8_(~Ppga.UnTY Jd4%3e9wS&w I .g9.FIvL}'\qPH)K%r\T@:j'0RjG){xI n)((N_ 8H+gL8αw@!HNj&;πMBЈNF;ѐ'MJ[Ҙδ7N{Ӡ5CMRԨNWVհgMZ|5w^MbNuf;ЎMj[~5n{Mr{>vyη~[s,&ō08 xX8E:3\R^ wtp<ǢNW\MB=2zx$_0:3=;vA3wNqzo@_8Lw?S={'O;qt>* g"㏏=ގ9Os)Og?H'>sCv;=t;3zc킏O|od{o|ua_>Os]E{_Ϗǹvӽx>O7 ~w|~vg~ xp|Hk'}%7s@ t㰁70r"(g@'xh 7%炓WwH~ {qаw$hvvȁ(}~(p4q7R8TXVh} 'Zr#7rq (8[Gyf`w# w6z(gXwsyg7sИgh|ԨH8Xf4CCG%~ߧ7~ɏKgÀyD}(ww@gIWpg帏Hx}xPv*,lxu[')(gH Gur|zTz5igwUGqƇ{{p=\AigyFyJ |dWr {גb9dY[xĦfٖnpihuYllxz6+zhlwɗY~y٘9iY(=9Yyٚ9Yyٛ9YyșʹٜYEYyؙٝ9YEٞ Ap`Yy&EaEJnz6 l azjJa i:a&z(h#*a%.0gJ4Z6z8:<ڣ>@B:DZFZ-J(:GPR:TZVZIʤZW`b:`\zh ^Jlڦndji:tk xzz rZy{Zz7~pD N*:|9PS705JzJp 5 LRJ*Jz7:z c+F6Z7:Q78@*Rʣ7p*)`ږ"Ѫ@Z /4: J抮J 4 P 0z*YaA Z v#45*ժq0 : ?"wA? ဲ39*КJ* E)P7C8J9+0۰x45K *5,%OM;p;#{h; P Z6 n :`VK#0TGqCk6B=D1HԜEN}J=T-iL XZ-U^hWb=B_}hgaMl+mirMgkv} si]x׀|=؄gk؊MDpْؐ=ٔ]ٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڔ}؋ڮڰ۲=۴]۶}۸ۺP@ؖ=]}ȝʽ=]ݥ YB=]}* ͪ @=}>^~ >^~޽JM(^,.02>4^6~8:-)>F~HJLNPN#&.D-\^`b>d^PN\qZmpr>t^v~xhNAn絝>^~舞1VXڊ>^~阞b0?ښ>^~ꨞj.l~ת>^~>.>^.~~N>쎾Yiݑ]@ο=D=M>ڝ~~m_ ??Y RL ,ML(*,_uSZ >@B:񻁜X _Pvxzos~wO_u}ĵỳp{/?P|?䊟J  }/- ѐ -p_Sʿ̿?)2@ Pp3?O` ?r /Bԛ`$O 1!7ެI@  $񂵂ޮ]Q†=6lRH%MDRJ-]SL5męSN=}TPEECP]ZT\ŚU+]2Lv]HQ6Y٪ WjUuśW^}96|8A *F0xBaPr͝;pq2d&u ^PMYc œ>[|ǟ_~~*ܶ`~IB8R  ~i!駟p0Nm g Cl4垣F+;o"K,"k(b"/J)J+2K-"ppA-c[a+,mFŎ:$fg:s HSN4FE1 ,4R ;;0T tR I2t2UUWeUW_5VҺz<4Mjq8ts B ٜz2Dv^JQk+G Bnnǵ@q-P1`2q/(JY祷^{7_}M7[UW\D-ZADر(M SDlsaNi?[?wCEWHqG5ގؖ[J`v-ʀS7gwgju]k1i&a,c 3S6 d. GkJ[ٚeWwo h;o&jV׷ 0,/:bg&SA#c7Vl >=t ZlOsЛI71ȠfDn=www+w6r*\Af@~FKpY'3_sU6{kYu3hvmw秿~ xt+U$8@4ul{V2@6%(%@t& V4aE8BNU 6tC@7D` " І C.xC:0p)a8D"1U'βB6щa2 lWb ` GUbE}ĈgDcոF q*j5D:Rb2>яd ?= Ґ#!FF6ґJhpZc&YXFrXvgG{p+]e[yb1ȁB QN_ӧbcn7χ~?}W|絿B9?@A$B4kz& Ed کZ8B1}ZKLMDÃRFPHUdVtWX)rCQ[32k^_,'\a4!+`Ted"gF@;%klmnopq$r4sDtTGohtwi̊iYײ{|}~T%hGxȁy^GTȅdȆtȇ<-46Ȋ,Hc`j`hlY2ɓDɔTɕT.;ɘIb ؊j I(IɟʠrI-ɣDJf0jɬPðбXʬʭʮ Ť˱tpjopʭPlJzʷ˸˹/\@˼1fxJ@l FTd1A4:ي kȨK+m3%qDTդ2Ȭʄ0 j @%4mMDdt)sۑeMd kg@j] :^ӵDdt茟dpbf̊ `JlOtsJQ5@~(OUQ 5꨿PXO3Eё'f &%09OJS5 wӅr4t-M!Q}Qq9ra()*R+QJ-% &Iz?RBNjkЬ%(;>kqSK=rTݳC~X@ETUUAu/CU\) kp$t\s^kvh hf eՓb9fx9Va ^fafH.^h>>b+"fm胶f"hgq.~~!y+u ? hxhfx圖fmicbo.gn峠W>W&>bpc_&鮶~Ii]i{0hfc矞 o1(꺐en⽦ i7V:fk(.Il?jQɦ~ar t 9bYb~巾gfvæh؞žSxm>m>x>lLne& jFl!xf#T ~aFj>=am!n`}j\~k֓fc߆okN `@Wg.0 gxﵞ)kk;b7vmK*c~q`po6!fNȞHWM()*ǁ!pFXI FjFgj.~cbjqho2.fAXo:'q%gtZ"X+Ir,͞DjVe t FuzHSr-_. NE[?RG]KguEY``Yefku\Wou^?u_tbid_kfwIvPajpa[r&gHvJvqxgk7zo$m_*oxE vao$zO#|T_hou&"G'"_JWKF.X'!}~WW eMc O)n NrGBW`qy23Uj:cGu UFeKދOyszһ){}_GzUe oa&76fd_A'ri?{2Χ{{'{'r/uwj_h&6hNh2k^q^h''&s gg}&ҧ{{rاwcZ8m.k w=͏~9g„ 2lX!ćw q].$92a2RҦǐ@"vȖ1G'ٹО>er /4v`r7VJk Ԃ=!py! AWAx")"-"1hb ^|0, |90_f$2p߇9e$<3-40HX?dR?.vQQqDK\`p.d Z?8'($2'}' :(4wc>?^$DzhdSԏn!kb8*1RPI]e jQBƹTZ:,{,*luXWk?D3xJۯ骸z̪..flz86hBn\}k.0K +0 ;0" ,csQ!MB7 4F8`L&#bs9/!*=% á.CzICarx-S<4DƂ+cOl$5.$BE~09"UF(ұvVx/XTKo@TCk$h{pI4 #’GgáH9f )Ĥ5)Ԥ8YN*T9 %.sy,=z!eb.gNdƆ$) $Um0\ 5Lm"13Wɐf&2*ꐜlQr! -}L/'S>|2}JX Q @HZYsfRC{T:HQSp&Hk‘%h%Ҵ6i`<ؑMk`J#¦ Ӓ ?Ke?xLեEE%Jl#6JV T*g8}+\*׳T2È/ab1&24R2E: Lm>Aw(Ojw>W $kRf_r^zuԊٶ2-|G{]*I"Y,&W" \8OPbbhC"0wc/9BdLd("'8ulTDEf.\a(VMvU$rR$zO܏FjnU;*9[r+9KI2TZ胵j$I̦>5ii l Ѻos]+˻mAںNHye3[PG4@~(s\玭m%6U51'6gu?oz>e.tAF?Ӌ x YC$Y`*hJqS\o::P 91YH/@]/ɖT+a\#~Wl{fWe6?asYCĉfgլ4ɺ Cĝ 54}oRDRl;-TV\,dB=QhtTHeG=THEY bQEi FvhTu%IvOATqmhVI X 6!M]icRmM iQUAU U&5R>S PaW`ms}Pa}%V9! "zOKLFŸ^YaaE k$P%bUC@VReEaIs:Q"eH0׭M "-Pα9 PީoEו$3&Rr/2Wv2vuY#KJt92:La-~#8-Q݀E߅=闧WC.%` \CS[J5f `Fd&57xaSb`Tfc~&@d&i2K4\&f:EB%Xqhffi&n! Xj^&6XC3̀m&'fn6sl6'u^0)v~s>w~'@fԍdH'ugfAl'{r_'|'ogpb xf&ɴ'f{'hwf4f345\a琨Uhlvn(EefjBF3`CH9"ϥbgjh(΅ed&~ggI]Qij% )ՉDysT@۔6C^)΍xbdXd8uGh(]}FъD9uIuHuW#V;"a}Yi~~j\5`Zf澹&bE#PY_M NRQ 6j9SUTjRMÕ}P܀>+Xe&܀zC4'bbک08HX f4+COC"`8YUW`5$j+o,BlW L}^5jbnb BWCD` r, K:G `ae *넕i]lEl٦l",,/@ê&6q^!d UTJ~]a^UmVqQ7,`X&ړ+_)2,g@hb*cj$,e6%c&Z*'J'"(b(<19XkSU~٦-zN@3XêFl.#]44b 11nr%a3NerpSkk]Y2V.rh]k Ѧ}kAZI=Bf9# F4]!!˱.-*(ߚBN4Z@ 5\ǵ\u\[os#.=l j .UD\jTa#VPN0E5f0@(v^P>.@ӊҒ!'a~Ԯ]rU21Qšg-pl4S7MYg6rfw6hho1/M5MUVv E'^Un"鶻!HūpjY&|k[5]~hSi7c6Wo &fn9YQ3.^´Ɩ$nXs{+9Ϸӷa@P5'ot;w4 _/m>kH=F*L#'iKx8KT"0{6mqw79itUd3I~匑V2Jv!FΤC۝J A?sB_0BGooJ./;9Cw^'ϙ W 0 eYp p?Bm\"i7oAvqyzlwoxvr^kFС:{.;lc7 8o*z+7;g{Sd;t;";빭;ߒ5~{l&{;;#KK+.;{ NJ.;O|(Ī;#%,3{ǻ^4G1Җ|а:66 _7| X$W;:6ޏٳs AK"Ih5o 1*ASDsQt[<ϟCxϷ;#5R_#nmHOJ3faCmX5:ģ=Sz<݉ = ^x3VK5+W{uqh5'ޫ>WGe8Q(Q}~;y itu45WT``FvbbmĞLf^cWㇻ>ˍşQsjv6S6hvV-mOWjˠN:i?@Տ2a2R \X@a!"XE 09dImPTeK/aƔ9fM7qԹgO?:hQG&UiSO2 |,FW_a; h`a̰cIK>ƕ\u=^ !aS\X1-ĎGx!w>6lk"C{rxJ\f*ma9bҢm3d4CђyglcHǣ&WysϡG>zuױg9լ 8j/ x{xÏl? '{2g. H m,Šz N"(4:0!IѽS$`QiqQq*F o,kE[.ڰ6ҦoCZdBC/RR-Sʃ~sӣ(jGF|*m8WL:+硏^znG^'*xTt'?H_o__=47<+ \ ? N1$AB+v4|s,(ͰuB qC~dD!)ᐆbka,XLUbxE-n!IF1eNU/x1x(Bu.PG,v}834(8Q=0+~[!btϒX_,a )6IMO:T/*9 nlFƑXh, _E$.KF HMmnK"8>JoG3?PYF“k;?ُ`@&>]3d'e )dSLfUvPhI!ydu#M-f>]xj'gR{+ZӆTfkh:X.}Jak p|KP MH!C-cwV/h #doKVfS5 NjWj~׊TWm}{R׾5~;Ӿbӹ1\~X9*$Xul=Q^sICWbx: 8tq״r(,N e㮷GB,&nxp5f)뚄KFe1"T.mf8\6X}y?-R 05:ZYf]I?XQjn+7XNU`= 6.2ATbBhl+DI`;%nkUp dL N%ݻ>hsΪjuBduWjkyn\wtFի>f[((!\*$Jp^/&SimŰxl-z֭7^n|7 F'6^㹫,uq|>?/4:R,}Ĵ<oCvpԬ[#rϝD㏺6f4`iƫA󍸜F.0U`#+WS m)O orVHF[&,qjq?>j<}&zEsڒ8ھם7~վwl\8x p`fo<J8!qrx7? )yqf`75?8yl0P} Fx*ޯn bm#h(mh90EpnAjDI<mmjy}p)LPߏfbp. Ptp '^np*P g p m 0 _/ GG2p6  0_.dNɊ!Q q)://(!(MQUqPP(#"i s)TbJiHI\Ҫ 6􎑖, X阒I)~ ")Y1ű\`q VL*͠Ⱬ*ڶ*Tj|J+ *dl+.(M<-^L, $h"1ޭ#jͽ *-ʾR┌ & 1뭾! "*"32)R^nΌ@F"TPK(FV+ M9ML6xR:Nxn(Ó<)B</$rmv.ڈ >>V Li&@Ȃ,.]..M//j,H054=G23.nJ=)'3K}.N*.L'JMnurIZQuSFrBw ;pVgwv?0k1"2 U}I i](gzq zgz 4H=PR+}MMCtw~WÆp^ VI=WPTRX'J&&8M@K"MtnkVegw`o0NK+Շ,k,AN+YKW8|+:wGrMwEeK01{s ޫ*(3D23x3!Fy[،?W~xe3IP7}S&c,3.s8ò 91S79L&8F3ʐ:kɔX׏eq=,1S8>kdm?[6 8@/uG6@UwC9NWYAHQ9WImCu 4MT@cv EM8YTHmy,>l?s'M7}Vyhr>s-V ₉KStUvߪLKtT-M1<:yQwa45MP!Q9XuP#&\+qZS%S뚩1[Q3ک\9:co+oyZ}uYWU󊵸U~TYZZ5xuM,lͤ5btڠ=xH:^7 n;WmƲ [w5ٕjkAgQ{ȁx֟a{Oi1ҶA|`fz;{ƷYD[hy;۹)Qѱ_(u`G;PIn֖mH{жM+6WTp \qm߭ gm mbf.e|FeblA[b[>Lead,"ࣝǥם}BeJR/%#Dݴ}}娵+paߍ&{%"h%w1/b#]w>P^@rDO&7>bW]a,e#Y> ;xs13zOiH/ 2*B1O#=?D۾7p4,"cB|>z?/S~žG]!]="i<{?ҁGi,=! As<$;#AnAl~\^_~死=DNKVK:^!W6$?M_Kd"@]Et.0~xBc ǻ@J<y{V5VV8M,\ %RXP#G >+ԺqdaD _֔if`tqgϐ҉)03ܨ!S oBtZҢ&d˚=ˠڵlۺ} 7ܹtڽ7޽| 8 >8Ō;~ 9dd0eEV :Ѣg1%O[~Mֲ Pk~FUGN&bD9m<*VfhDa.\u6ZR02RajŨQQbg8jNF`` .`>aNH]]f tFhPN&Y͆"m)2Tۊ.c2Hc6c%Ua>dBIdFdbYYv,!~&%i##Y'ۋ-r fbI&QԊ:fIVn grIgvy:0C5*hia\QD> ieNJi^li~ jJz6YP.J:ڕl2(ފkҨi lKl*xO8 3O4:k^mږ~ nKnt&˧wHlZmދXen p0h&*&>쨤NLqݖHpoqivxLl(YD . s_VLs͹^<:s>lXBa;ǰ*3f< uRlsVso@ou^#J?4#"+7%luHz -vwkuq{Rx~SXpw`}خFSgߕ]d#ΪMz馟:b{t?=eʈHoTv{CCXWU zA RS L>k_=Jo8NPi[٦M/SYzO grh βF"a8[cpY^{8!+wڃ@N*lNO* >mHae$:o4 oh`U"KXW(wr|2㤄qw#cq"MEޤHuX&K|J]sb$ QH{,qEy01ŐG8H4.)LmLU61=ţJ&J=K &=QOXKH` n?lcIgKK&Xetx@ s,&9B3T@n84Oq#Idr Go$yE\lJ:d5Lw.N?hb̀ t 2ELDoK ۤi=r'D8śFqY5h.Z|Q %V96DiaZ1B JbZ%,FKn-B\ҳ ,5v-^֍5i]R!V$9pqr9QnsB\&%q!b'>Rbv$]_NfwxŭTh>~n>Yq38p?hv&>=3`g6&WQQ#{ѵ[iA b `vs%,0't<+Ʃ4[qV씯|YϜڡm^ǨFtiFӿ6Q[Eo:qX&>tgZ9ؐ$ͧzoۜͿ4 H2M{)IlfHcGe+}ّҲpuÐke,7}Էolon"Ӵ\7!JyNx dMK5Z/Nqutq"DO2rw䀣T'y1(3efyXnW#QU1Q!%wCe9BhVLgS*8>6RY!{r'N&^z3(cS5!go QՀC膑UϠUWMthUUsU"qFMYWx^lUXw~XZs)aHńL/P0hgHsKSx XX|x`T{8ՉYs=IVe3U|g%7y(hcq'ug A5]&]͕<ָ\#1uԅE=]:]?>uS5ZZxR'fQ#>_.fU0ȏXC*C͈j8⃶_Gq&b`&٨ Ԑ4(vaa"Zbyq-w_/ i0j5i7r2T\擻1)C3hGYψ;?2ReDiW1F;(0fcY)UgbZBojfsIf<448L}hrY)Җ◉f9uR~r<""陟iw9gz %)mFm5I >i}іnnɚ隱雿 6ihLp bSpspRpN9Gpsx9G9Tq9`ɞ"VR}lUZsasxsCGgSqM=Oǝ-YT'Vw\ߕS؞ʡ{%BIw5ŇTwz@HwxKA Ab&+xZ.қjG﹗y#YF{EEQtQET({VhG7{`GH*s:J[3Gx~gI׀MK7 *ugqkH~iD@1v_#i? aהDwxUhyԪVׂTKT@ګٙZ੠ʬ2Bckɓ=\ORER8FEQGܚ]RHSD9U8a#٭^Z8#EJ[Pڬ/!A+` kBy$NhUp5UYzu5W=k5bX(Uw/8+\Ưk2 Bp= )GM቉%YX@Yz7GSUKLx)uuJ_3K7ߒ;o[@ˤ65a.э҅w`]ykS]&tH]_KŷX-ii+,K k t;(ِTQ!akaa̓O&Q: 8+Q!+b5K;*z; غ:[׋ګ" U$jEDOS/Kc+{'ەmok+[[qںLن30 '\% o+_\;Fi3|+Wh{;/BYabY46W3{Z ?,AĤMxůM, 0e#UCH[]|WmpDPf$dCKp9ui9pyDqg޹9qcۧ&D@\a\>@{ sk;sStotӟ; Hw=w> : R>Qu^[H z퓡Bfʭx*;(jN+j-ʢ0U2Z[{@6*,DZ=J3yxFp] ,\SzYKѳ =[qGU|G!,pL+-}q}AG~JLuQ~6J㮐zVgK> ;R,-2dG l)Wt@u4c-$E;l= ȫ䠿úOŊ1;}|I pՆՈYMIR:>uv̄>]R隭@hR]qݩCOݎ":%~ږe;iņPֆ" TP+w/kۡ.YXɋb^k^ ƽPҩ 'Wviإ~NkL>ȋY BSAJM.KѭݧV1ŷh}{;]*ͫ]];>jMފ,y)%>o_f p6K ή+<+h`^KkKaI8y!$ͼϛ U&QmSm 0 gSHn(LcfU-Y [>i`>h$Nujf h?.~6R`yp:%vneU].菎ߛrnh5 2lې霙%MfU +UkǝT/.nd*j>°L#kǰraw7.*Ȧ쬢󄇣f%ˋK+eV@O++e=$籼%D̬=Ѯg]{ݍ7 O'"}mzeOo지:- /#u$BI:}U8h3ԻN<ܒ UNj:w߈ֲZ AhMNkݪ y,זDk[K(ߟ/xy20q;F eaE}I wL+?C+⮭Ԟ-["{˴sȱf $@[{A >.A^ GaƇdEfyP MΤp 9udOA%ZQI.eSQNZUYnWaŎ%[֬XP@wI-"+`̥Kk0|kV/6p YxIMĉ QɈ21Z4씶$)2";|1L˘Wi f\ Q-Ce-'NFOogON^uٵowŏWvm۷ W/_tsc)/bDh"`9[@,`A+@Wx908Lq8V# 8b;mƖH(e+<$TrI&tI(rJ(c˭֋﮼+>#Hï1K!"c42b9|;#86,͈iXQ!1^t &n$?=Ct34&̉JXcuVZkV\sJkK3L\5DLYduYhvZj UW{u[n[pw\x_;N+$Xj^kw_~l_%w` 6`V;srX3[z 3x cC٦qZdSVye[a_#XyxdsyggUzh6`Fw㥸gzjk&izkUie:>lVm{na˱i~:ߋ7<6ۮnwqȳ[llo˞W"RsCqKWq"W}u[w]1Ys9`w{}tӃYԏ|xW~y:ܰeky7tU[l!ˀ3ԃU|N-6E||0L*2 hHhB^R)P/!rVѦh'̣`-xA yWrؼa P3shq *=r䦇`N-|!B(D{akdthP g|d"ҢF#,R#h!eh/%VxF4r2kw&{qF8>bI8Dd{p1"=,_ 76GUEM10B8?QΒNxJTRDc\8^8 hYZuS9]bHPZG.ԧL(Vę$YR4:03-a͝%1q1LjR'g=yOpK-Oz,輔d.hU_8&ʙ D2 I,Q$.t=aD O&KGF!9TD"-&)0|T;婒Ϲ4cv jQ*P서cMtJI G0GԛqƪTTSJnR4d`? hRPTEM(Sm՛\'XU{kY~ ºvA^RvЦdR5 sD" I$Y5d 8)4Y(>,fZUS3HVYZid}mmm{ۥ/eOo`X!3QkLv lG({g45c/թf*JwɍPS|)3SVw6%#n^UQ XZ]r&jMHf xZ`r"&5kCI?x9.i ch&Hdɶ%qM|3ok&A5dх\b A7ܓGԠ)BqN"RrX"}.OIQe/ >ʹY{O|f4Yy)hyK\Pbp3*G]4?4B& =C(TJgQb08 #SgrGOQd-}4%!fM&Fjfu]͸l/;O׻f/^_k`h5\k:huݘU [Ӧv*A!78&7\mt[ݰ`F]o&v}E{w{6 ~p~ gx÷Oho/3-~qRxωׅ'n\j x]<W~Cws!T;as'2ygwKy|\SÉrۇåIju4p|;Eo|Mh}p-Ajdq IU'|}g]'HwFSpJ̟CyA0E"2D(B^EaKH^DDj->"YyJF(LXfP͸ {OOvql? EbHJn!зQ9?ìm")IwG)dRU#25_&74oFMm hi*$?0jw&I '&,,ðrӸA|Þ#eSeҨ)Ѹ((̨tA( )$>BA+܃@ /*/B)ԫԶ<˵++ Ӫl.ʒgLc.# ˟8+qbICb+!Ѭc R+2BADUB:B;>UYx ҸD# $ՠ|l >L*@&'plH|/D"36PIdH^[P+j2yYsx=.dTK?ŇLJ JJʩ !8:ȳ@Q4(:+<)?1B3*Ek4c3\TTMw :DLegfBHQ@,K_@Գ$ L"=o.쪰glLJj>3IR$e@fѻ1@ש=eP~ X$PQAMGXGxǺB0nO.wG$~%vPaX GjC%U]#a .?M@eRHgI,^;4AI1KA㓴57}_nlSUݔP>=aąt_XHE\{a"&a$&*_O,,b$$odY b+b-AuiwݬP0ncάa2cZb(>O7n]9㥤5TkOʬb<N1cD*$pb5~"PBCNdLaGFiQ: ]:JdLN埋_ZHQ*;-;@Q]f= uQ?bNUBR8Vej:mpVeP#'('!,աs"/ rF"r.7u"xM4]56L*АSSHj>qaOPfIHҾ[4ED.lIh/KTMNbcFhMNlkق}W0^?$?EVV3%VȈcd員4W#i:?夓hu}A*'pArm=s4tM±AvAw-z.y ^qEyưdjnke՜^\5D3<؊eXp>X¬_mlؕH3+:0lWlv[kؒH,EDt-OĠզ~0Z0?S.T@ؾWcl..cWu F,LƊ"edL[XcMCh,׸iەrn߸vn]\j Ɲ\zL{&ˍu \h}=RIEgu]_q;A<ؚklh ޔE^DKFLH$g\Vzv{TdyoydFj\ed@եj)cdEe.f;u?}ewV_hWeE(NkծnAnMڟ̏וk:W^?YrTI] d= LK TD)J0PSӤP?.R2Gդ9i ue{ͩR[bۺ9gv~ 1\ZY h-͞9@7Jho?RJ L.o \R-ƭ <:;M6kUD%]?  q HA;7㜳;ܳ? m1DSn3 BB$Wc[sX c]gB[xH+}t4 mXS {ݷ j^#ز .ᒎҰv{Ds޹A裓..ꫳ޺8яC\ u޻v_#_X4_;S_[ ?s߽߃n?(s;w_߾W_Oηv)cnz ݞ֮y.- +h lxj΀ZR`0y{ [2! khõaBCk=v!Tg"@ J\"W'B1k0$ h+b1vѠ)z7>%l]@1Y~1S2,4r\ZV52@.!GAbm6"%+iK揋bjP!1K1( i,%&F ݣN,301'@uxf#URT]1036f uT5I &7:M D"p ɐåpP*jɥy^ Q!i,OI4H3AvTDװ-ob4ݨY> s6FZB5J*BP(̅,cj)?{8KU:L)KI%EJGF%i2KfQb5Zj<Q՚2P߼NyGE!Ϩ|K8sCU@ZWg!fe3֛ǝhUB6W͙1rڦұWvW@)OW*95Ƽv_m)0,%Jn,4UfͲ)"7 e+ enWK==JN"K%.oRU <sOm3܎=I (>%nqXu.ti3V JeG|HE:p-r#H0w/o;;]cU ^4219k8:"DIօɭJ_$B?5c" IeQ1#ʀR KR9jွ7Ùˬ:嫓F#T%f/` &!wUEXXϼPJufyU}nb*H=#f `S:16ZV7-}=Sr1{)le3X8) Su pL@HZ^'Kk1vUl"՞Z^7]7,5u{m7oсG#\Dg7m8]ݴd`Ҝ< YKn p^9WˆR2H<8 <=@I#=p9ӛt/HҫnuZ:cÞ;ιr8]=z{0zG.ֽj-X/|EOcq"_֍ C4=Hx H^}Y>r;S13;: ^"RB3EȴžeRRP9ϲ7׉36MK~UMf?4ɺM}C_  ~5:5uSnhs3 U !b).C"R5pQI. Ì4'Bc4Z=i\-~e|xG," bosv|yT:.m0Oǖ3J> Q#XEXDAVJtXX끇0!!RՑ||P$=FPbݣH'cI#ġ)2ӗ DU SYkAM6Ȕ)$YxGja#>TRd d0ᙤWbpo}q yX:1"8YJX~C0JԤD\D YHeU"fbU& aKduD ٥6[- l=L/Qf!mA06e`*,ȑboc¡cdbȢm4!asBgŜqoh쵞v[v^׀'m*FyL'XZٝ]}sʧfz}vT]h|h9'~hJz 肊܀B( ()'Z(9hj.ȄgV\ט{nN|^nyr芲xUh֔@hc0fh2i@ PiZb('zH"wrI^5v B?)Vnƒ:j^0ztC̟2R$DrU`mMj jRJkixb BK>~Z**D#=6ғZ"{i`CMՑt]I+Q(+U *JikR>})TR%M8TM ,kaU0QE{exܑ2Ė@%+bhgVP[, [n,z "jbjJB#|ɾXc=`⳥ f"m[VK]~;eHbPڢNw]-Cemd>DŪgޞƞRf3}XMPJݩW8ms+&lJ|>4F,ETa4?4GGtRs g6fի-@bT=b~&dXlTED+ U^ބY"RueJ5a`[ɕnֲLc,6\,W0R n&GUc5]{v-&Ufv/G23Բ6mmmaۇzaעn};l4 3g3wuTj;;DxUb/+6D&b#ZQb68 .Ms÷=3߯@";.BήDvrwrGWSmNE醯E~s|SxEFI4tϪL¤daL뤊+4yoD %PJRtWfrW- P'+t쯨9~*p./y};z'վ|;?,/ܰ[_^0@{?逿?>7$=& DV3WV8 &#EM u P`F9vdH#I4y%% XtA3iִygN;yhPC5ziRK6ujTSVzkVVYBa%%,qmZ,rS{v C`]czp`{xkbŋ7vrdɓ)W|sf]ˠ[ѣƝ{|G&vlٳaFRsnݻyxpÉ VlФa;9 toT-8H۹wB|xۮβxzٷw~|Ï{Vn2UЙO?: ȼ[|%p# ?|I':䢮M+(\]|e|ϖ#9t';OSm$\&|JOrL#k 2<4\3()1¥f| *">PDD]FuM2RAKK PERM%P]V]}V"RK1u+C$ԼDgNXD/d]fu`iWzbWTrt]SWmyݫ#pW\saj`BI]Ww#[tZ]r馝~]屹SlQ/99܊m:Sh"F&lF>S.N|7}$u>NulR̻-[Lvsl|sFhg/ܢ(GVm8Oa1gf7uWzFzf;ꭿvO q`EN{Ku+^>g`p?鳿j{xhmW1HȾ#G? ^_25*At A…p1,ORXCސ`+Y õhK[ ITt0ڥQ<XE+^oCA˅R㸨E3- f43`{8F;i%-Mo7IHlX5 aC1)I<Ԥ0Z7XV&iYK[2fw8.q/j0AXVrT2)Nr4.A@xq1ǘf~|3fL֐cLx)N{3y6 i L(P$'=iO>Ty(_pf`V*]ȓS E(YDc3BLӘ7~RF P`A „.l;4h+})bJS^56-5f koP ::Db#:M \ļeh!7Jǃ;T5q뾪ZW>6{))'Nr%5 H 5İH[B瀺~T兖y+iZvk _h͗ ڑknuZ^*]kˬ!wԈKzWo^l{e3N]U^7Yë!Y_Tg~;nP R$`K!qX )̃Gb+F*U\㔰9bo|_1|3>7}2>}5L?~[5e_,~Q˘GnO插Њ,|Rď --!|i\+Ў 0W"_`KPOHYP3bh "3wP Ć"P4LPrp 06$0 ) P &|P0p vt9 ݐPr\P GN0 O! q"q? Ѱq91&W1p pYEC`-Lf1ksqTY~VDq'P1vqU +GAPIp c1vqM1jzpP0 rQ!/2j4p0Q-Q(z#K42@ E2zH$_Fq!2"%?`R'%Rnr$-r'Q,bp&)QR-1 ekR2*ÒĬR-|!ϑ&Ur"Rr\R,RȲ,P51r.r䒃r(/ MJ&s0#3bIC rSR2?sB#2$93*!4W$)4Hs4_4 2Q3U5w3&!+7M-y9!1+T39B|saŠ35Վ:EG4WR;;S=#=O=3S?5>>3?S@+??+@TA:;B#TB'B+B/C3TC7C;C?DCTDGD14AE5=GS<}62nfFkFoGsTGwG{GSH mEia#GTIIIJi'HT7b,<0F KL4L\bKMKɴr̔KNM[LN`NMN&O4OebOUPDTQ3v R#UR'R+u? S;S?TCQ5UTOU9TѣtSSV?uUTcVGQ۠UYVoVg%zWQuVuUW5=Y)CJvv<`I5IXYB[}[GuWZB\y\["]w]YU2^_U_5_<_V`u,_[@aau,+V`"V_ v_.AbY% V_[!,`d]Vf`b5fgbergCJ͂Vh\fqV`9_Vc!*`_kd^[Z6__'_[Kd7dB_%!dVg{Jll+_]oo]lug*~vhWhdEeWT VTJHIv+(q' BwtCesEP7&lVT"`Z2`urtIdbrkAvp҆Vzz{7uAsGirrCs5svS,}+{?mGuAuAywv7T\TXhq(ԗA"Z"'8jysy;*~6{CX{7B, iwsEz[nwn؅~jz8OzewaBGX. 7Ww$7!񗐲Xp='؎XXJ y* a؉aWtb*ˊ׈{m3{1Xv/s{* {5a\gyWg4Y)~v*٘y02+Xْ8msI)y8'ٜ-{-yI9[rWaSvvz3i*&+ ٢7z+8E)%Ao+]y_!ؤy~_혟6`3,x_X2zW@Z!vɖÊzZ:Q.:2 ,G)rZy 9Gɯ59٘3@Ⰽ+yUy9n[ᦜ7 r/`+x+Ī9e+ ;źyzٺwژE)6#yj@l۲YW{q:O۰!Z7aȴS{W9va't/ a /%EIw9_ۢ+`| )9/l'\-|w"|2-»-O?ܢ*!0 J]ķV]aV̫sZg0@-My }g3R^W[U>ʋk˱`H65 `Q6Q4&4ɤy$ZxA_.&Ef3uY"v.Isffi4&袌6裐F*)6:f馜ve J(Pjj|ZhjT*'iJꗰꦡ&N+kn6)#$Tkfj+rBKv[6Kֽoz' 7oJWlg\1Њ1q"'Iɸ rJ\02.\d\V砇.褗n騧~⬷C);A{RHt'7G/W?XkoXT`觯O/θ `,p>LGR:' ~ `zGHbT2( P gHC8̡wZ!H"QsPHXq3IlEM`  8 ύpŸXՌWṃ8>d50kLF:M~9o̤&7Nz (GIRL*WV򕰌,gIZjg \2H IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂ$UtІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwS\@ PJԢHMRPtOG>JժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾5k@!,:22AAL))4}~ H*\ȰÇ#JHa3jȱǏ ^ɓ(SIR˗0cdR͛8sYSϟ@Cѣ EʴiQKJjTXzUׯvKNfӪv۵Pʅtݲ,мWH{ wa+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)! ` 0$N2%@LR 0PM d]fc>Y&g%k.y$pI|9|*( Jމ9bb@q:(Ji_^ q9VX*N6!,tL}22BCM$ KLW,,8((4CDN..:33?ablH*<aÅ#JhC3j@Ǐ 9IRȒ(#:x)c\i0elgN 9 'РCycRK4uj&MFR'SH;ZlʖfM+s-۳U߶+ݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ N0 @>B\:խCή1Sp0}x'>4`~W\ DwW!0W$0d$=4!,^22BCM$ KLW,,8((4CDN..:33?ablH`*Tx‡ HQÉ:1cD=hHQVDPE!W.lQeɓ#KxqbL)}ڄPQAoDiĝNJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻ:@ު,pFEX*NCv)@"+9f:}@@ Xm#b" 2`L^ۥ ,@BT` H!,)322#?@J @AKGHS1F "))5Ƽ㻼"'&5HABLꓮ""++7>?I !/E%%14;I00J]4Yr&̓)hN},"ϟF*]ʴӧPJJQ*.@&0 @UV튤mPpU\*0Dv@Тa 1b0,(hfؖ@ (ֳ0 mpLHR0 !,I22ABL$>?I #JKVر,,8^û((4BCMXq,-7 " "~熇dz..:#q9=Im33?"#4G"?@J#df`aki@N~9Ȱ ,84d8d h1# C(ɒaɉ0XX4lqĊR\X!B)#TQ@8xF:t.P 4Q'3I%,}Ă1߅TqZQY 0  w1U U&F@ , %I]PEP) `H l,8G&k@U nlGPa⣏uhj,Y 0=GSZ_a]> !&-37#"3&'-)))))))))))***)**)**)*. /9 :=0>?>?????????@?@@@@A@?@G22222222222222222211--,,,,,,,,,,++++))((&&%%%%&&''))++11::BBMMVV\\ddkjsszz~~~{{zuttokmXbk:Zk(WgWfUlPqLrKrIrDv:~78<E P W ]ehlsvvvvvvvvvvvvvvvrnns#|19AMW_fr׸ĻȮxɃْH*\ȰÇ#JHņ"D x1眣FQ¨aHKA+NP q@1_)A:kސ9DW.Q/z}.+T@tb'<HH?7:cLgoM17<7@7޻!䗐eS"aO0P%lI8<.q`]$APE<͛ !P-\!=h{ ]8pΰ$CzG1 ckX1፮EN  Cߥs.@v+`ĥ `h 2.9x X|#@mL$rtІ* "n$Xx6KFr1qQbJT81 y1s~D^8ϩzad.a ?rF}"шx̉ΗT-mɺjЈ+-Sr9NbhwH-페D Bch HE$ YIJ8<[fl0L@ :b.hF3 cc|h\IRŝ#Cxt%E#&07/=nhHAq&P_:5r`y@MS]Su*9nw' UNYJ׺JFȫ:$׸z!^W<ؾaE fã~+20 Zhb5(]#+Wz˓ⴠLwfN݀-H[5З A.ζ}S/ΫR#n\1v.n!TU|\\kZVF V&=_ `ŗ:0y߼Ϳ3ffԢ=e bv-^J/w7KG[ںԙnTHW@S_|SRB,K`U$_⯚4K[i.XbuD.{L~>6Xі_0{@pGq3`8#{ƃBE. CUlV?LRƘW\tAH@Nϰj)"IMR ЭWM+VPIbr -,Xp&3A2gt UWgv~%'RڮƔvtC1ĪT}!mvz@bZÚ梶kdwoZPfE@ 0 pE8ze^ߏ†< hҡK=. 9WUڞͥJ;*W+2ӗy=s=-5q.'G/C ` |Av-m(;;vmiW{r~9,lvyo_=Kl׼W&Y:fgu;׻cKwJ~W=.iuԻO]O~|;5}[@x\}CI_G ]7F}Az?D#X'1~%;n}u70j㐁r8"H$h~0h+21r 46,j05h.1Bx--2-Ehƒ,JH,2R8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍H6Xx蘎긎؎8Xx؏9Y^x ِ9Yyّ "9$Y&y(I,ْ.0294Y%6:<ٓ>@BYFyHJLDٔPR9TYVْOyZ\ٕ^`iYdYfyh(9jٖnpr)l9vyxzub9Yy٘9Yyٙ%] i ٚ9Yq 4ɚ9yYŹi霵ٜ))\HiY๞ )9 Y.f ib9 j XPy)[H ʘڡɟ Z9ɢy(*^*:95jؗz6ɡ>Iڢ.j0e 2T*&$T=QjC:E^o8"* zKڥZj(KzcZ6jY٦%:NZj:Zq%f 驗y (:H*J`3J٩|z8b*dɨXZjʫJ_j;:bzzz ڟ \:yʪ񊘳j*j 9I!9K 鱘jzj ې{K;۲  `;[*ۘ*^I9WW0yʲL.1ۘ3[5ː7k9+E=i j @jM+K@XU+X JK5ڣ 9Yqz晶˘ i#+BW>{0ET``y I\Kk +rtLNW[:[ d [d ~&:y\[ZU:;륻 {9{˚ˠ{W{t rH \=G{l iϛڤzɹ)<ܷ;r*Z |D;[@9:kKG/Fϕy{Z_սNlbŀZ\zV\NHbW'Nddl[M8k, RKZSzpKkÓ*+3 *l`Cۘ;̣]˘;(nSĨ%:,%nLK%t'@ULL9C [C<]`,:[k.ʵ5:F:alǁǘdʷ\&‡IKKɫ4Ʌɶ̺ٻ̜8ƌ\LkA<ƻZb0KMЈȌ\rΘU>\ӵל.>MT4Δiײm%}nvr.\xnϫ6:8kN]͖.৩I~*Li {^^>.K.ÔoͅMuў珙+>8?Rϙ<7}W][{A ңk Kߏ%'ߎq-s1.cei-H/:YwPar͙tjn[>}˞p@mOf/ =?/^y~q:-ʿ2j ːڿ?_IQ.@/?N:!N $hB FAKÉ-^Ę }%MDRJ-]SL5męSΔ"} 7EETRM>UTQֆ 2`dFxVځ35چiEf(נ`f-bvEW[X?ZhҥMF s˾[lڵmƝ[n޽}*kVָCr^b'Dzԣ[7a`1v;JYa쵯]Z~P&rMD0AdA0B 'B#2"64+=P0<: ZϸڊB_::ŋ"JODϳdI' *B+2K-l HȆ>/D\-v|LLeELS#6qƃl! #źNLQυHC1RK/Ŕ)}KO?5+Q"=3׊ԃN1LbeLUB7̳4h+btԵXQd.ٺ*Sk6[6SQ7\PI%NEQ}qP52yM=v;r^G%xceRtsaqG[HIm'b[6o9?cqG&ʎCFc!{=(U= daQ#MhEz7+8|ڷ#Ja ҃_mYzNbӌA*qF;KfV;nayRم ˑըukj2Zڡ*PbFY#FN&t#A_]uW.=K\v>x'xG>y[摉^ko^p+վj<_,>A+OzaB?:tF?=)־a?8@B#{0@c$8A VЂC5AI3C{}= c r9Y N ,C0ٯ _ē5HDh0! .vQZlŘb 4эo#G:юwcAxx+ f,ʙ)DXx#J&Vhxܐ}.DP(+J~A"&ҔIt7@# % ZֲøDc># 0A`5ȤhZiыfT.CLp!Vp +Ap [Ԉ󧐊T,*SIO2rcKSt/45M{R{մeQD@Sb"P`ֶ-aFtWCZL# -0uL6lu[X _Dv!Drb7yR:vՊdkHJFKԬ '`!v$h8 axT} `n;QY Xqu{Uݾb|%?yW5;"퓜bIЃN.!Y\'Jͨ9XǯM>JV6X\vluF$A@]w8ލ`^[-Vx_ (Żտ~DǸz!4x颃oջ7s:*c,v=:"ҽگÈ+#;#T?3TA{:2+=SR۽ֳkʄ{kZ+‡b \B_K%v8v03D4T5d6tC479C:C2c` @7>#JI@:A2x'[0'?(=L#@{k‚%Bv@Q,0SDTTUdVdC>, 0\3DBdt <I 'E|KB㜏bO4PBR2EWlmF3E ?EzB@}F0!FJA)LGҳB@lE.jHru4ȃDȄTHx(s9D[Zdm#*,udGFdxy dԵv|ò,~ ȗ4%'ɚɛɜɚtHI GHHA]TGL"LB2:{DJ 5h! J&ɝ˰˱$˛IɎ[,\|HL}E䯧4,O$ʠ)<:p8ϻd{ʧ!M0MNȘz!|M;Qk;$QQGd}ee}M2o'ii0؃%i "#3Ҡ#X#jvK9gVU?W D$ֆX@{UO[οȁxIazWCNםgݣ"@ء5"Р]jo 2XBZ؋8, W4GvCl]T[\TľR%5ِlF–@mWG{%ڡ5Z:_8ڤݣ-\uAZVǽ(TBVZ]M<#LY=۷L[ySY)%OB'Y׼]4[Jb;ۃ \z(o*n) I2Xn@u\nMoE _Z\SϴO)̚5_ɠո.-|[Q ge-ׂ iX1 *`Z^](ޫ^]޽xdTPʈGRaN0WM SYc0s #b\5܋"#"VX֍ ,}`W69]D5uF/ \]H-R5k >\ &`? Bvb2ǥb+E[5Y c]2L蔽] LvM][HüW ak3c:$>be=2#m^+󔷔bT 5~aFvfήъ]X6g8%/x]D^.< }vvXg楽c`d`e^f>mkfTN6aEb$>k ofpccgaI=^tV;`Mu翽dbY8iag@.a NH^f Qdi5ㆶh>c4eW1qNrF鱖%[ TPԘ#gb}>맕k`i_6a %G>hNh>=Wh休h$6۪n]j le$Vt>fg-*6l VVl-h^l-_S>eѭn.e]]˥_ؼ[Q9=2bQ<ž&I̅m#_DhGMTl˹j mU܌ܣnդ. uhr.[l.Y(yc@=ԬFpoخġFidjP]E5nUǶ-napX pFlTpPjVqF|__pR@ȰMNUo72!w Lƞl&ojFԄYЩsmt=Ve+o6faYs;&s3WDsSQsr$Ymm~Gs.O?Wo@*rCD_VߣFG#ol#sv54=!1ސV1oWuCuZO[?uu v$*+v\ 7gGhzߠjkgKZij\ waWN6Hvw?xQy_VwW48wIo/wL[sP7q|lwB]xU'UOx0lg~U%pov-6 AGĕwnN1Aa4[KmSy5eӰ?־nY'Kty¦_F_TGWw!z~TTԖ>@ȃw<C{$ӿԯ@~}}qۿ C0B'-#V#,H 2lp!#[v"ƌE#Ȑ"G,idIF(Wz2˗#QȬif4HhPS7# K42m rS=GNXRW dhҨ:ŒdՎUd{t%Ta˒=;tF5z/.l0Ċ3n1Rƻ Ņ" ТEʓڋ vQh6ܶ3KhFeTuL6 ov,Տbيi(qI;Ǵ fU!W\VwϏhʟ/_&}/wdx * 8ÛAA"6h%t/GFP5-" Qof~F9 F_x ebu؉RL<G}#[W,{t5dTJF }F#trqiS:&m&q"&ceR$ƙ:rءia7D6; Рj6 ZF2IґF#O!jq%jY[:GaDGkMҺK`Wp8,i''J;-E'ev (BٟJ43iA`DBâڥˆ[2 P75W8e*SӬ 3%E-5LZkG0d7 *IjZ;35|`ZAjDA8lBr4H{XP1"kPOikc@z  I,7 Cdep}F~-7e<,MgB], K->|9ki Ln4Komb4M#NaM/uyDWH}u"=2ٍly+K"XtUkI=/OA=˟s}1RO§Ayz q.wDk?b@ܮ^z(xg Il`&3Z[)L’X, j+YSde[VͯFOlS7`!/iHM.0RhJAR,^֐a&HLeXЅ2T2,H4c!D2<—ٗlXDyP 5HktEfƙgf4F v}M9/K~~F9׮>IڗԄ׽yN߿^:ȉ/__>W|_]ߪdUٞy% . euޡaDM _]mE !%I \!ס_9-4௱ ҝXQnb6re~` ^p9R~L%& AX^xA!៚ٖdB<`iE}RE>!`1X >x"!ɸH,NB ! (DQ|P"΢B5# $γa'N_5Odq"P ٬GGE YP}!"7-""$RT!aLGX!( 36H_u4#u]]7}#8Ɵ8 9)/EwaUS%#r ?҇!4V45+#,j#AA._BB}d>$;'ƣF Pa4'e)?bE2]J>%dKKLLD)Ҥ/c( GFXO[%H e,Nu%%eT5SB]TN%U\eI<$W[NU1#<[n$ ]TXZa&aĢ@ޥfVT%%IأV:`ʣW2$^qcVcLTIf#"Ff&gNhh amRE"N*"ĦX|H4UeJxF pg ' #Y"pg`kNOVuc*KQ-xgn^fx'Iyg簨R}:RN4IgT}'g u_~>OV#Z d(rNg"#*(05䃆Nhj&tb(OJ׆S6v:d\eވI&(ۊh\V*N;a%&P`W窄r! fh(B _Ψ Eks(kfUc)~(@P}'(>*d[b)%&!n)f' jX?)a^ &&"jcHbYɝj*IV#j [j|!)*b9FajحrI¥rj䚆 ޙ\*fF6k+aPkص.IV`V1[6ιJPk*Pdƫ*+Ǟ\*߾H! blFvDxRÊiBl(ILm"ҥ,v^˓V8^ϲL\> ^h&ͅvjǕ҂ƂЦ^ѦH:9m*bPF'-r-riFEGk6n-۶mjms̭{VԒL.RQ:~{R{`2KjvBn!B*m҅$6G~X,u||nnvpJk.LI|ܩɞl%..IA/x|[/ R.+jisF/N/vGf,H&zD&ro\:بj&.B+Fow&Ezq#+(O&p>&/J[6eV^0{;f:lKpl'_ξ GO ˰ڰp3¤Vp6.JNb~T)oE$f*gqK"#"[j3 m- l9#%യ$3qq2w #k{bcJ 0282*JjqHfOfRqj'?jmUvnOd/W"n.[%/{10Ӱ1),Wk4/ Xv$+]7;7P8O ߄әss::{)7M0;2,SOG? G%28s3O"4*BG22o.J4W>r)/=>C!p ?<4 MOq0.J3JC4aHDrttEtWi44钴nbNLfu=g,mR7R35thvq-G`V,8S[NtH|4]*YkQ0uB2\\ggs_s 4_vO_gw3LYQsct]Bxd+DCۑ-i3K- pU3V3tvWO-v:/˶xvmaeE7E\8}S8w;5~0r;k/w_7w^t)%Ow~Y7aw{kM4wߥwlqYM^Q58O2xv7SgkJ`a}ljqĪvx϶dxɸQVNu9opDȏw0ܤ7s9$yt8k[tc5Vo8;u}y&PQxoҚy+o 푛7Z0@ɝ7ytryow;ٸ38-+*w+߷{63j,lCnoC%mYG7Q{9)6@tf_zFf8yv9 yX#L'Gi56]>d7t]ڠvGtZ::r–rߴ^MкC&;MH5_9.!O]t`dB|MHaR<39p;K3%lװǫ$M]s{|s3XնʏI%<|J`c#u =ȇ<[C'i|w6&䌥<]}o!qGypJ /ӯxǗ=ڏO2z2=};O#=~_x6W<+禮YsL+bCGs6"Ia~s`V=?!}ۉp~͇:/;7?A>BG/Ym]%'2@ĉ0`AD@qР-!L"C1fԨqaCn0C/R$yƎ-#9957qԹgO?:hQG&UiSxh{dtFWw^1>=-n]qjǐL8'͓9"Hg]>KyM ,,*~3!p8O*zN" Z?5Ych;.{"@,ÓTDſH 6ܑ:^KP%l'qZp%+%09#-kI9d(XlsKL+S3.;ă!jr71"R#IБɴTI)()M94,-{k ?0=#SliuM+%UiQ 3%u>[Z=P T4b "-Vi Ө4Tm;7fm?5YQ5A3WsY7P:ۍ#ؼR^2CLE\!kkʖۋ1~%/^+=([4a YrSxKhXL/+K~9)ه*ߊW_q$^F2/{c-|Ze i=^v;̏%_?rK5H%4R#Xn=D kN3:g.aeU>Mlt;Y'¨U| WE&/܈rV}:xb$ܫ] Zu(HTY6HAV Z4$ 1EJtz̨яrZc@>qTE%ᑍCҤXA*!a).*qZȸ1/`%JiRP$'"L.2#ĤJմ^KmVi2QsAxEL.)$&9i, ~$%KDxJ34?ln9F?e$l[&W3/m31q |CP)-KsЄf(cY Kr-1zJ8nTE5͔U%KaUȴǫ#ٮs4OMNMf=< ,Lj;>s&V_{U8j$Λ՝(*k=z%^z0Q>"|+"2!tT!XVuY K,.U`N_Bv13eͶfGlDB@W2$y{ޢUfխjk_pU4b|fݑO1h BgTh!r?,,nP;Xծk[~ae,p2ȧId\˾wn Z-D_bAJfvGb&0SOvS<T[I21vgmDZ1Ϋ{8ܺ4ci2! ^,}gOjkj~q}!]-ts&`В5'y7d79$-wE =Ư 9y8h o\ζ|Wkowr? 1_wn_ytJw@olwN$7-d^SnV5EYgqKvs}]Ad5_O;tQʕߝx igVz`0q;藿7t1|T<Ry}D"sMكsދ}>Fs"'\.~'d+.Z~*~=wa;E_l 0Ao,#f,=/}ZW ^d0K܄o]@CɃ{H%T,JFP|ϼelp^0 dhP>l:p|)w ʮlx//Ƿ2A &.ꤰk#bl oҰ:鞆n:"'/fP wXp[^Ppo 1.*apUU uwpӍ"Znq RDqO6fV1)bӰo|N .pџvqB}[/F1> B , 141[==qh`1_H/ٱ#qS:1"K2 SR E-+ wp80 "]' 0=2)/CR/Nr FCPQ2 A &믉2p9b' N )RBO.A)d$!"*#.l/Mf*jnR s =(-q("pɈ24)R!r%%_RgR,I^P5hp!""''21o3o [P4&4#4"*=0Q5%s!s.c,!S2TD8Ko,(%5/93:Scr.RR2&(!ς@iֳ' >3"p>S+/Is??b[@=U; 6s0hTT3pBTB3MC+e GD gL4c]dAm t<<,Ot2B8*%hoI;L?>+JCS?8ts`2dKqKLm7;4aLe/Gؓ,ݲ8S$C}O999NO4PtB*GPu!Gu2HsM89/>495)=ScOO#N1òKvP9N7= -S(1(۔Z3W?IC{XBX@4AMT5DB#S')V/HH"0uW#U\ǂ\0KuKEU] 4LW_2]HsR/4[Sp[[2`wq` S F[eeYD G6W+ޕR$UH2M/^%ccUW_IV`Kd0e!Bek0f'pfGO/P *5b U9s#~VL7M[V#* 5UvMj`jjaX5jYmcVLQP^1leR %cV?ui>dn`oKX뚩k-vYŶq3,$nuHuV5Hn2UC.E4sn9w+<;?1uw(}64`TrvcqCmwN/NuywZejATѵEȴf=zvUwl64z_}6<#v-cw99ww7|E1a /U]x>tB]ݶ:㭝Q8KӡνI>ܕ^TDzјȯ{Lʾ{i^E~{;c~?KePBFI>}#]t_o"_:'׺37}Yt>Iožg>U?m!~BigCO~;?iA>יi3,Ks-ec#Օ?"  :| lQG,WĹXPC ",p"ʕIF $K.Q|(sΆ0Y 495D=4ҥL:} 5ԩTZ5֭Iztٿd˚=6ڵlۺ} 7ܳ݉aMY߈li&C;*nq+KD`r,\y%酢λ"jשh'ݼ{ aRMgWr]a6'K*HPeG"C>`m&6AX_ڀI3`+cbK,P3XP=N JeZneDQIfv8A9jR)l?dAt&盲E'Cq7IbK03I'}2tni.WbIjq~~~VjХ*PY.T$g6&+A aݞ&ːein˭pz5kjQО+AZA[c^7R :*$EҴ> q+Pᒋqۇ!Rp@'Z2b""{R@$[SLڷ0 .,sùM uRg[qX_sە(<'- x,&QY8'},Oj<5yc6Q@8P=yG:Kg3!Oۗ삶-YlOX7Q~vٟ _?!4\^w=&^<nf꣠_,7 |S>$`V 1Xa_, Ʃ5,c(j }XQ$V/{5QMAڱo"%-i- #ɭ1qCcPNjD"@(D9L|c Sd5mK#C` NN%Ւ!CЂgvG8&_1)IRr庡C2lD;Y]ɑtEcH#uYϑ$(~pS_Lvdi-^A?)!e2sd$uM˔T7U鑜Y0Zϖ!Ԛ%`aK'EFz,mGИə M::ऍ85HшGHRʝy6jp䗈̧0Ot\@e V'fʲQzstZQ\ A}}la"uPm XS3TImTe 'N͝HJ3AHR$[z{:%[mSV.%Xʭ+gBOeHKU] . ,N}Jivnϫdtf֤kDJ'չKWiU7;Bvrݥ&m? ƚ.zۨQtPE`s+nFe0c;Lk5<+\ 0p_5_WeM^&6Sn0n1O2׻^Dִ%fS2Y{w3-o>5B\ꨯq&˷Xn^%9~O,7# xx=U2+lc>rY^-G$:FouW} >~'uݯc[z!̩TGzp2?T˭}Mه|NMhqw\ Fw6{oMX7)oq͂|gU'fsdn4[f#&#l8DepWH{ݷoO'!uw"|u~pW2D'_g)(v(\}<2PM Hzm= ȂWXr~Tu~x>#7g%Eh6&  Pd^%"mv؂.1(r5hp7|:}$phhhk(9Hx J U%aw(~VwX7|Ss%!k_l78xkH5[v6ppgFR/=U(w+KD|hGxV#d#H6g{7'ڡuyg[YȉyјUYi5ƛ wi )LF_*!y`Yك qةj9Sri8oq_əy+@3P]xy K) ٟ!VinR} ʐROf(ɞ٠WQ hƘء z!FEyT1Ri2*~+Eƣjk?AJCJZӝo $0TNVX؛ ԥ^:Wzdfzҝ5('SDID$2x 4& Z٘b ˑv*g)JڞLڤ"uř*68 ?jw>ƪl骯:Y[q+i fvw\40g Qz0Zczڈ͊ qnjZjpvl\)~:D Q0bʜY3(:8n:zZoaAT}x [H4Rګ {e$(I)b+۱m!#*)zv~Ԛ.;~*h46۰)ёgAȳ=?1MYv97 AMc1֮ a>Kը ':)ZۊoZj rR{"I;6+<[{hk4" 2[J( 0OY *[I{Ⱥka?d ;|ۦIuC{a~ʼ%ыKdf$3HZگ(d +雷a=*(K˓ƫI;`zˬKп:!sp=*ViL  xֵl۹Yr*Y^;!|Fw=׻^*6TvKʧ!L6삶/;k]HYz[, ][_6j^"9لO ]lKO'vKY9ǎXk%IClt-l08bȳԸƃ3ƀÏ,ʼn,ja*@Ll&[r<:t=Y<L5Ɗ̠>}<k| +Cɭk:*ÄTŹPi=2k;;í||ܼ.= ,c̝I@& ^$cSLaMh}mZWK˰Yq|ćZB·;°w@(Yf#Jh|\ͮu'F.e }2]9rgde5 !Mp8J,np]cQ ٜgdՕYb5;Zjd]>}B60=s * Ή̒ }ӊ3k:Q-\$=g| (gkLʃ]lZy~. +M2[z8 J|ݱlltvM7TBSg, =l˝9ݥ}; |]Lɿ-M-թ!Ž]jxu}ڇݧ(Ao<Rz#\|ͻp+e.!! 5Z:"z$&|"qZ ת].miR>41اD~xFHθ4 -U;3]d1N_E}ɎM#ْNL2'.IjRQ=t^0~rjLMm=Rn0؁.H3l814tZoK\}ЁKl9mCͮ.܅,ouc3moO{eEfSXޥ@\++kt̹oNحιhO=Am`5_뢥/`D8G^O6\ 3ֻ, /sP'㐢7 RkBB+CCLD0CPT*DrqG{Qn@"4Ha,\2)r)pj'(-.12߸TpM I7G 2!tPBaJ4z꒫&BJ.Lҥ6t+|P:,ŪL4(Lsե\>kV\A@ B%-Q`U'7FT4,X*:5=ƄTRVNZ/j[\u]x^^)uYjUױUx֮h6]FDK` %Di0X5U[xCyZ^|SV&}CRߝ <X"UX >.NnK۲HċqWczgh%jP^kUj&f0m`Q 7-ml%NӲR3ssv0npk߲a9-8K3eŤ}n'*iĆB-ӎ p{w7 r≗ܣ+_͓&XY&uL%r]٣Xݞl+bm/+uwk/~`H6K}_I\G5%z^cw=0_V|IN.}˻TG~+da?QFa +\gby 51 .N޳ݜntw1X>vQza ؿ$( 6<=QmqSDBEcќA(.M0S dc,j%Ծ1FRy*-9&)8PjG QsͫcAͭ TF>iO,?GEe/CSKI!l-mJ2RHz$"*u"!B䄩k%T^XroVpiL1e;ݩ+ODM&: 9v }c_)sJTf(& A6ƙڤ忸(5Xe;X'Qf$j2 0;\& 0_84 M%YVU9$ǎ1Ke*~YR0K m.颬>7ir \+4Nr+EwTH6U{=Hחؓ1EQIZ'W)eQKYv 61uEJjlz)R(ຘE kk[WVl2J>96r;8tsd 5l%iZpej9zd#nSa+[$Ŝn2NOT4: B4ne  t}fu ˈsq]i1:@z w ^Eb2娇L˷j1U)DfaiL`GaV#Y`IsEM|хR;q/Mh_+_"y_Xpd]'#9&$wؘ3k!*Sbc2YzU!Su5dTB^>1SfHhcV|i48?@{Lnm]Y[.:v#}M$4Sp;ٹS /g[?ʯrCc(y;xi7h=^esjEwMO^.|k(^QէG[U~gQe<_~W8J妋ls7Ot/{ѓǏNjöcQn?ē?㡭8?dcy D{;ʲ?ÿd.S$7h/m3AmC[@t)?|7 d#R;`3ۼs;;+>Đk?c¾AףB:H,CAd#BX>$t?%俉|l BU?{(> @,2;A#C3ĭ47č҉K?BZ?CDykChz{>q>GD_%JąD{**,! +&tB9(/\ްB˻,(l bnF/_|@CaLr{Ƣȧ |cpj< SܲLFWLGB.C|)(k:]\8 Gy{!ĊCK`SD: E[ě켚tQ)dGNQB *3HDHȍ,JHD |*:EGEK4U,V b-} ;S3J 0"#Lf 21M]N=NUSEW8On}VQiEjԘ toתOeWPOMY<G\MY~QVXzV)<RI]XCCFH?kMX eOx_ERXU ~ HWe庁5WPe,d>_KS9uW ՍEVc?MW|5zVA5ڢDڤ5CǩJKV0I6$NZbӣkȧRZ:eTU۷d۶5= nԳ۰Zژͬ׊ɥϑJgʲ۞ u\y\͜7lܖY5UXrտ4}^`v `Ӎ b+E&L#fcx 76 D59~bU*4gTNgG!-ngzgVLu_|hk5gI&`i>_ޅfM+ unB>/~fVE a|.6El6D7&P9\@hiAuh&Uf]fdgO6WÍk~d.CV^˧E\N V℮gjfE9$X.l&拈j6~k&餞kL~]%lN ؜w6d Vlt-]:&e̞ell5e;F혖Xfm ~ض^g>{^vGA^\TOtenijn ͭTn^%忈hk~gSM$Uoj>PmږnVci5p[Cw?9  _noGQR.֎n Jq. jdp}q͖k]gqֻl _fv7k+WN _r-Wo.ph/1!%*!OnN?D$on^'h:WRF gW0>-\ {tt !Yt"oh@Vr7\jnTw.u\_KLj\W7sZ__A Wtgo~.gs.ic6dOZf#dmFҖ[Es_ gnKs^'9?f)_stbue?skm0yTXs|r}F!snmK&Gvr.=1{xq7 (zϘN|'r/ǿܞ\ywqgzkyv'YrkJSDžDm 9tXyDŽHxv{JwleO[z tx0ϘCWx'z7z#\xsD|`g{ n'3V{y9O{yҏLJ|I'ۛurs7oUǂVPu!/z~y}|grF{{|yí}}C}p&m~5_o}|J &~MwngeP#p "Lp!ÆB(q"Ŋ/blxn#ǎ?[o$ɒ&OLr%˖._Œ)26Eȩs'Ϟ>u&hAg[RQYhR~B(*ժVubS^fFe~튖kպI#Bظbu*\ui˔&<kp߫"^Unon̨y3Ξ?-z@̦CLz5֮[<(.[o3:ʖМr}7ITq#_|-tdN,mέl޵~+O??/Q3F+_il7 2`kH[ov5T Rar9Use^$TT|'ZeGe~IvuP蕏HXA5XAWSRYRr٥\B(OB\\*ԅBy45b8gn1EYvc\N眒Q! !JhFШOzEiZ啟&_2yO©Y'N'r╜i,ٝ=9? Zz>YOBũZj)碛і/SQ5k+kZ,Vh+! vjSNKU lXqs["_ٺ#\ ѻrboe:!nl_3yFlvG,H老WatTo3Gz|4q{cjkMcX'qu#TZWUgL!tv"Kw XOb;7X7\_y v٣^gs6۫6IZff|{nzǩyKB>_ ;0b,dx:Jd2W`qq覓_ꭳ цm;3xcWb/1E|68"MLrI.,,{U<ǻMd ;X}"\>ω%`ß0)3DbQEys{WFA(k 5#"J^+*⡨pEʄ-nCB/=! %3-Z;"U,( O#R1bG}~|[SZx//r4 <ĕ&`)oTVX,]2.ɥIt*%0>D3_Hϩ'$<[Ăy*ЇƛhhowY,B`b 5Zr>!8f2g.00H'6\4џ54(QdQv2 ,%uEk b∰wi=SR>ԥ' ЀFst jǕ˧A+]/2Ԣ5GjHA5'R]z01[#:N@l$Y9A9d|+\ͺ6a^KWqV~2%ZlYU$>vj*=^VH{EMta #u+7z:xNCɝz҇ceUwe?G(nй`G`f @-ik;}Q]ofw~t3USC ZQ-p;+*b%*[ ނ컼>2g]mJ´pu𗛏 h;≷[\3ؓeK>ç" }@|1Hkqan||-!q(/,]s;c5Fޤt2z+,:˖u^jO i[yN,𳃞jj[sH0>xEAsd| ѽQ WqjN"ّ7V-_dꩼ ety|GBoS4}ݣlq'~F79^~Fo'm{Hv/}*!l5sO}8Z۾)ے!`7%啈^RNs2ɟ5ɱ] ?yӁ k_~M~卤T ut^d0-FX6|ء=b}E/eO [Z&Be\V!jNeSSa:<d`&ca^-n"NX$ Pm3eAdf:\gdaB|i& &kCz`WҜ4 e~CNVo^fp '(msR؍&i.bYcuJuΦ  =cZV&yyn`{>NeTV#&}ENg~FE!vlg>gZ&&k< {Z* |T}^-TSfF0򧇞\2wrRfoo苞V&NH&"$F_:̐꧑v(vʨm(#fFRj]f^9"#ǎF.[fƦkhF~c&.Π5~^aO'Y%NGEB~i|2&(v( hV]fj!j=h娒_^WL*~d)}p嚊*h*d6G)DR+B|f2**bdE+<&)BXXM!nk f)dzK*kMҤ:Ve¼:.)^:)X~޿,΋dUާk빖j'Blk&kdJn2ώ1.ȶȺe,lhٟ*¢B6kZ:JZ+z<m>"m[*ҮR،Q Ÿ-¬Վ˂hƚmN Ӂm+Vaeۺ}5ttaRMEӎ犭+j6lL+++1ҫƆ_*A9H.l垬Έ!L."޺Ҭjla>klV."$Lޭk֖.{ߚ^^a؎.-֮v>R.ܺ'\Bm<z/zEүn6v.n qos"\^s܌'@>,j6.#. )U ?(0Z L,O-"lW|Ƭ.rqjL0GpEQk0s]/33+A42 &;giOltONrOX3k6aa ,b[-KW$[??N^_ue5XfWc_D=h6ߙ6*vvX2D_6Wv$5uӵnw/#oDJp7l-w*tO3U755N7nSv#oϱw7u^7qTRKEY<{>[zؓ=ᗾ '|z?>؂nME۽VK|=@Di 4x! 6tC)ڢh E -^0GH4yNMJ+YtfL3iִygN;y˓C\iRK6ujTSVz鲢EEvcWF_2QdȲЮY0n'-Dt~0Ez5EÁ=f,r@] thѣI6}sgbuvlٳj]]1h13D}G+idJ ''caˆ="E.oXap_u|׷ilӏk!| 2%/$\2oҲq"Brh:SlӔĈJKʶsHE% g ފ*δ+bEVO0܍{tbN.=HC[bĖzy>ؚIR6~jgva(ث9i//fPj%i^5kƴ01lZ8|E5J-nY]wľsc,R"7e\Q6T}B`䕏sB"}4B,Xo&pώyq7Se"{?y߿Y釢gwnw''p7>1]KX>V!IԊg!YWB$KTf35np^^%/+jV "d}.'B'>X$4BP$u#O:42y%n9o67хh/Rw""" cn#kHE?GR dḘz#-t:e;!.vCiFoXوýqz$.\ؚHW>$,dH`#Z ONƔ%k XIFuZc'!ɏ1a)=üҗbaMoFlly\^D ,ͮS]ډǸk{d)hGCfO)=#}Bp)9)yֳ|MfL+<yo]A@ LiЈޔ*Ed_g MGE0NJs1Q4ժVmSmt;]!|j8ZY%}sL&J*SeKFs~1`9}JiJGV%~|EυQRno5IiE6ҮGj^>lfr` Zv5],TA&%ֶUgKvF#_(8{"VlZEl1Yh-l2Ys,'Y*Esғը:\e`y]2*w} @<^Sl'ۡȲF fR6\J =`ߔҀVp@~Xct1ZiuZM[j־'TRutY]61DsbLn} dT>Yp6PzՋ(+I[Sղp2Qhy,s`nX/7N3zvLzwuJDru[z@Wimfսt/ohܽk6_I $S5؏(Ǹ썗=I>̓\>oxU.g@wV=?{,1i7_Y W -7wKs%S$}j~DjªFɊɎN,K(2# bo>>+9 \Ў *"k^<0mFЄJpt/,B,mߔ/HD/yoMt|PdPF fP Q !P0ڂ']DO M!4{ lְ '4D0O/_ Pp;kKpG- o(Q'"({/Q` m4f; P0{$&BPHp`OoQ}"uYx: /Uo:k1/oqѡ˯㳂5,5o9/b OQR$ Nh1R$eY2}:< GN+Nj#1%C-F(C MPrKb%Ǐd"+b"C"#ѱ~r!t,6r܎R-g$r朲2*R('瑸v2#5]M/1lR1- ,#YkO*7^ũ1²)9#9R1W%1.7 20).!2/i23 4{'G 35$X9U5_?S7g2%CsQ37+;s88c Ri"U9W3:?;:kA| s>=R 3'Sx>?>GȮ;2*-Sl߾s@81oQZL3Br>/Tgbs0CӓD!SCgr#D#&EEb 1F2Gu62TD74?tDHDK3t2E3.I3Ԇ$9t-K%Gδ%=TLc2 /4/p|JsNANMOBgT7P5 +?KQrM"(10,t;&*$.G3US1H(JtPOT˔T;UIrQ, R4a)FqtWS_SKuXC6F!NUMUFZ+V=[GR[uRzX,4?YS@]#@+-Z3qNRU$U_k_,2 v\m3XL\zCq}DJ8_(R-V1VKuucc'G?T!C5&AJpr6]l]Aӯ=W.biv")uBuV5g[1[]{P_Ti@iiU;B!^ķVMZvkEW ?`UU˥d R@RQ+#nv .^q^7pgs/h7\V`/ ]ZUd6q_jN8bktkAoyvtrpnl avVJuAr]vVvs !PY{fyN}E7x!lpxa,fycr[vY!c{7z;7N%9~qwo7xWmuCv?N4|jwe#I3EPn~G4!{WG׀xU8(U7mC49%-Y]7%V?R"je7wEV 6lgmaWfיvX~ej#3A/v#xhGh6-nXa##Okx7IXn۸+7} .-N:nNr؉X]8M% لkt_ɢkSqX,9{3UrU#Y;X0ՔQ9p%E'IY\WזdFbj5r?~2Vgw/$Ҹg@+ll y-~!y]}xQ{xԝ7V"مy&|Ÿe4X9v zZ=1q/X>[+g94]8⣙|9%K8.|!=-׻=Z|C{Z?Wˍut<ܱUܝYAY<ȗщc%}ܩ1؃=׆B%l]{٫F'"Pn۴ɮA֭#}o[ܿݬ]g!* !Qt@=9ݚ<8՜7- "2+(/\"!=u]kH~(Sס_3%s!ŝ+^諾{˞})w<+|^[R/۾Ƣ1~}u~.j?=ɞAm[v~q3+*05߉W0yMFdciO͝qT .ag?k,-ui|˽$ޚ ]_}3bYec-K "H@,D% #JHbdq?D!Ȃ&O$q˗ ;8`ʎ7[ܹ$O5+b4e)7+&9湧PSCիXjʵׯ`ÊKٳhӪ]U۷QKݻx˷߿ .\rdR(\rE 1jԈ95I>ٙҨ#3R9S^-4Hbي5iԴU~ʶȓ+_μyLس-jm)2wGCXTFʻn:b}٧ Qo$A-bJo)5S9'Vh՝ai xwhJ㹔)8vh&ghPP04DC1cO G1Ȓ@6gӃ/ATViXV!\`HbwFwR*e,dB9yҌ)i`Lo&4dW arrBv7KҠzKRfi饘f)W[e*_cFhAID%c'5ПBJQRѯu敆Dn*V\n}:܊Z*tKKyi$e X1{bDD,h2;JZ 7Rip*Ъ'eb˹o-nm*WOlH*2j+d7emћBWL7ņe'i(h'˖A+5O:< ;\x}PI߀aZMu.:v\'xS8c D|Ro_.A;.n %ꬷOd{^P㵂@AS[~/9Lўn0d |C^Q]KZCf %"#(C3)W d.%DIKK|J-DUv@d(IhLzteUȉJfb@"EV8 |.IknLguyaVq_ k,3g 3T.1!"HnӋ;< .І܁3#B='P0~f47H3Yӛ%-MҲtCgJӱ@T8 ;)s)GO¦JJ(~% M9.Б VږsiEٷ"BM29OgT*Fe >PIH22`M(+Õ3@[)ʉ0Mۧ]G*=Rs^2#ȕn'e`{h:-]M^~(Q(&+ Sy5JtH=~VHZmli++2-qJ?.+Sf65ˢ^#Q,c*wnbkZ;~_/{x[}ZiAJ3 K/}ZvŪ8KHX_%s*Ҥ$ aIFXNUq+laI$ǁqՄT2-xbTRe4(ҥw䍢{^rÄ|o I-ȊZT䳆R]d'GԳmq[e> ͩ1f$RU] va^,2fYWg;;8J6~ e7&,h\ G9"ߨl׮봧} j:|O-To3̙\dz֭vMၜW״VmrMîdQz"xe͔UKЮ~5 ְ62_F[H~4t;NұkLp4|F5vԛd2]< 2 sÇqO-rq!O7Ur#Xtζ=shIԸ[K3`usHy|nPs8=Np -H4Xy5)flwr؇aXVSfH獼HwhSHDd*  0~֘lmÍߘ{8XRxkXpv](B'h pHa7mڸy`jh,g؆;/597)pYuȗH >IL^֒*Cfؐhѥhs=A)gFٖTI%(ȏ$TyȒ28]e8Weu\fiCyn9jq)&Ku9y)z||~x4Vo>[b)oHni "sI9(=+oӃ9f,`y9(wF׎iٛ EvHyUhظٜkvr@wqCXɎJH~)HIcFxi&;{A(X7oIEK9lTȕ9 }9hAe*:F ":l{ Hr p1j3Zo:sJ.; #F{i􇢜RTZqH:t+xyKYhkZ E.wzS)eXVq2r,: i0z<:ک?W﹒$Zꨊʚ9gf* $H|G4ʬ9G&$?7ovk>9Qڭ jl卩ىJTJ*wEaV7QCcZ 'jvkx^JcK3HZfY?,3 |D)Sڠ%{[)+nUfZr8Jp:*,HEKGk*1iL+JPkR9JVf3Ac e@B>o%N &*Cp34}S;@b>@~IkNY~](\ :AN"4$OsJ OθUn儝u8}lb B>S>Q\[3wxy0!hM2~*= Xjt阮뼮 ð렎->jG~O&t0ޟ{.h0 ` ~#n`!>"". 0 `~HN* ` N  nJ*,.;cP6 . 07?#/zo[0LNPΫ3C Ű5_p7_+ ذҳ0 `x/=pңuq~?m v1 mOUb_߀ B/5OtHo(+zOp3  ?Py /@0*`9tO@m0 T_i1@ p /Yb' q n;p~ p ?#@ DP„ C,^xNF=~RH%MDRJ-]3&1aęS'g/}T(eETRM>UTU.:V] įe2\@Z}UVa`݊ۑU FgamlxC_"v8o٬~ZhҥVΘ! Ξ}v}U޽})/9B_7 bs}˷ao+;+'}zqGW#j~/)uB5{6U*.e&B /0C 7C?1D3Т KnE2ZoIJ>QR)rȅ<,H3KJ+m-RoI0ҞڮD7߄3N9礳N;1b+$S3,FMIB P<D}+.E{h9n|4W]Wf&.$FU0r|J_%gO&hF:iӖz.Gy$.5H*.U:lǾiF;mf큜:n?KuծlxNWxUBv]=pjuz]>{~h?|9ɻl>)mhm>~~?ƾ񵑞G1@kFQQH@ }_%(UЂ`?vp+4LQ` UBЅ/a e8C©7!HB1([ 8D"шGDb]ЉO48E*VъWb(vыAb8F2ьgDcqF6B0oc8G:qlmc=eG>яd ӨQGB?Dd"HF6zd$GHJVҒd&S&INvr%e(E9JRѓD%PJJVҕTa*e9K\Җe.u髎!,`22:ېې::fff:::ff:f;sff:=v=vt::r:f:f:::ptqq:sH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\B0cdIK8aR g͟ { )rfâ9B*XB9pkb(؀T۬ ƔZTׂ>8 0["b4 BFn` @"x*D Pf$@ \xy7\sc Ζ]-@5.q3uG}ad\``3|S& @Q~e^o'rP~7@均n$PM PYA-\ 7 {&@AxAl dʷ\ u8fF% 4%Υf9*h#eHa\w]gE@gep)t։Q@!>,Y111111111111111111111111111111112121212222222222222222222244>>LLUUYY__bbbb``__UU==55,,,,+++++,,,"v7eQRiKqLsNt I|DCBx>{5*uj(^:| nlо/6b`@Gt o 1mC0 2C٢\Q+]*֬xZtmцo&ܲJz .x ўT;AO.#AƉn#}[t8(Kў-@[!qܪ]VÝk4Ҏ=4Mk_t܅v?Ogܻ&!k/ ?&k#G?ҵ! #V]w cV%NeӘ-)4w,9ltd:uA|^6ukv, kVf8 ^<y61p\2 /X^Aa3MC`9!(v KbG`QYQ!;OЂ#! ǹPO,ߊC׹QX9 c`H/zo N|&EK[Tm#:Siv48YhͮvabY0v79;6dmMz//Zv9z˛wͯ|'It4": %jżկ|ަ捸 +[h2f:7+U '#NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZ֊zu^MbNf;ЎMj[خn{MrNvMzƻ5! ~NO;'N['Dx GN(OW0gN<r@@ЇNHOҗ;PԧN[Xz{`NhOpNx+O;z>o]^'7{GOү}aG=Uu]OgOϾϽwG"O9υ?w؏O{cOOOox}o`c908׀  8Xx؁ "8$X&x(|"|!Ȃ.,[6耚ǀ7؃>@B8DXFxHJL؄NPR8DVW؄YxXchjx(pr8tXvxxX10+-/4pplhx8Xx؉8X'cHce؋ȋmwyXxȘʸo؇Xh؈g8Xx؊艫؎8X3v wظ9فh%ЈqI[WY؋؏ "9$Y&y(*,ْ.0294Y&i0K>i!-c,~:m0PڨsJJzp:*rZjp @ J ګ:Zz:EZ Nںڭ*|ܚ| ÊJ溫q亮o ҩꪰzj;[{ ۰ ,ҹ25*;2; "; [ `i *+!3K(= @ H L۴NLkк ۠JP d[f{ڮɚxPq[mp+ʶu?>CۋEG@۸ke{{F丘1 o ) K/ ;a+(c9;p p P- xh;[ 0V[ C M:nck۽kǪ::[[ ۿ<\|,[6[ "@)%|K\,l~P~4[`P Џ6\F|HJLNPR@z~W70RPÁ v|zċ [:npr B܏\ɖ|ɘɚɜɞɠʢɒȤ   `>1ˣ\˶|˸˺op ˊL̊ Œ|8 ITn<\|̵OPń G`0L\} v|l ۀȊ<\| ͊*,,ʥ GL Hʰ|ɱC.B=B̵̾ƼK̏Im͜ȯc9Ȼn Ȁ ({;ۆ jl@,=l< ~׀}q0\!ѓ-Έ [' - [շՋw{o٨ڪڬڮڰ۲=۴]۱m; ,0˛Mӌ۹ڴ`ȝʽܱ' нٽ}ݩ= ު]wo h8,]UU<ŰG }a,`: MmِMMј=].}ڛ콆Ν*,⼝ڼۚ ­ۭ--:9ݨ=ݨDKW cY}n޽k`~iLzM RPbrΗюMΎ}ѓ0x|i>^~阞难霎韎ӌ@8 ˕>˝~o 0넎n븞 9Hx^Nx<- [p u|n煭Ꮮ샷ͱ~ӓP6 q0=} >^p? .?.:~*N0+S8"wMٍєpPLNPR?T_VXU,NG/1L[uZjlnoo kȔHLOv!}t#?x& M؎ [g o /xOx?_?_` Qb9J߀?_؟ڿ?oog_aI@ d' "Tā+bQF=~RH%MDRJ-]L@lęSM=}TPEETRM>UԢ99qUZ63ǛKe/DZmݾW\uśW^}XBo2]"0bO}Sdʕ-_ƜYd4~IUhҥMFZjZ)`5I7hފt\pōG\r͝?]tխ|ͷ;͟G^z{f_|(~&#g@ >.B 'B /0C ?1=COLDc/FgF1 ?wG!$"22$TI! )J+2K-K/3L1$L3D3M5ܲ7߄38:3O7F?4PAAHCE4QEe<4RI'RK/4SM7SO?5TQG%TSOE5UUW%>5VYglA[o5W]wW_6Xa%XcE6YeuYg6ZiZk6[m[o7ji%\smTtv)Ũx!y=wҌ.W~ߥw_}~.w2V8b'bHC]7c?9dG#E9eaU݀9`{WaK5ҹaF:iCX㥟:jj;:ye:S9"fcmnlnq;%:omz駧vگǞq}/zǧyG?}ϰ[Jyf8?/vq# H폁`7VЂ1(AJ́aE) jЄ'LQ0dta e(І7$ q8pb0aHЈGĀ8 *ybzEP\SKbENq[%ƍQ#f +g?čdmwܡ5:Ȋx؈V0HBҐds52UzDl$XџiFyÊ<*Fԥnv aͪ.XMHU(Pjς&֧h;BRhU]هĥR+gVg3SXײm-Z! l*oMýj.CՊ=DS¶=d:ҺnζtJʷkF ^d|>sܯw45R=̠p_茄 apo>;eZ$nTi`0 c1걓jԮ9c`}{ж1Mk^\|Y?hC^FPecyCh܉g~F€4!ߔtYo&«v;$l3r g+Ό'ψb tu >@!\b<Ј؋=pB85BK ~#tLZܕGFs؜EsV>XNU[(QNw9*Rzmdu*5:j3x-j6MwmKI1Mc;R{Kb[ϸ x4D߈g'֔y}1yLji˘Ɇh//'쫝ro{L >>d+uҹX #ҢsZ{?02۾@ 558/>ak80"+.es#s?Hf?P::M=A @ѬrA0;</@Zqz#72\>[99<4C>I)A7Ry0hX7aX8F7lCVC=`#B)|A['7rgks0 f l!",̈>d7/Ȉ:J,$~N2dh\J=,mDM@9l6C9OO EO1J5L/M?̥HJEͦ/CmPHaPOOϦPl FPB%=uˑyj#Dy mK%S=-[#BD$OLPl|OO Q E-QeR}E+Q  PТ, %Q]T =5v^l@D]숒RTUWPXO6j'm[-U_=A0hc}NQ  QѮQTd'{D̔""kMDQT',AQEE4U %NQTشM:} #d/@A9zPmEXU7 Zgb8VpeVk=Gg'pq W7-l2̚7s3ТGc'.ҪWf45ɭ/UlV#Mnx` <3]p¸}1$ څŪLq˘Vfbm]q> o'Ҭ׳oԭyrY-jt 3n {1dv}J|siafF\ An&YO1!8"%ȚiՉ-Ay%,Im VWfahXf!cHaiIvDn1y 5y7&eٞ|`~(E!naJ5I te1$E8a_tawߡ^UV#Zz)يPeig0b clZZ6uA=v.)gE&x$E@.v(6Vi%j%N\%a,F|kFot&+. ׂīJ\JTAJ/輦uTAR nDc#^zqp_gMFٔvxld l\)-5\Y 5e{A1}iȟrkQ+«bЛqJza=6٢|j%TeSepl 3{[ 'f+'ᠯC1]Zu,|0|͝{69j=h*>\F-#_6e\ϫ2ybB}<ɗ}eic.K?},TBL]hk+7AS?=T1LAlߩ[[ ƷNb+Tu wyr˽/m( zB3ґt ꕜ;[ɚ&J]A t8)ĀAg)>aWF<"hqmܠ! EL" n˛6 o~CI\BYpC^ظm9Vpc/[`9+f]"(.)b1%E]$⥷U7Khƍ3gD?`-\*I!J̓Iz&v%j oBNQE$6"jY PJn#7cnG~!WmlsY))[0LYBDIĆ%i.ǹݯvWes0K^!z 1c@Ad(ʀT`PW.H/e7Ö1]A/EVʳl&kQ J.$.nv`f ^oӥXP?U,k:]iZ}U#Qz v%Nj6`E3 Q6bYx RxRbs,Y {x܃c`Y-BoW}5}79yVS'`G)Pbvuk{ p"v x;qq"4QxI !L]NFVhy<ѡg+/~K5O/68?=sl6$d%&} @VM4h[rq[褖ޑa}\ aFŀS[M(:YAEONz罕{AR8R֩^RAs\6AC)ES^^LF<`_I>AM߂`_V^PIZ+aF#@X`"  &B ]%۵PMqR\66 ҝFkpI`u"8٫xI` FyU)` bi*q|'ޔ"!!Va]=TH" ~]b&2aS8SDZF""]% r`έbfVl_``b\5$A255:L-E (2 !D16QE3A%r!]9с9n*MIQ>.y-/E0 '.$8$_2Nd!E^bF*!D#T$$v6q#Sxc7BH!LL_Bٿ)͍ubܣee_uQz?XA>&dj\D݅4DDZ%E"A߱8Ad\X(A$$A`&KNKRN`Nj +꼢ToN &+ abHb*f v[9r%/\AT#DJD6#DSdeT%%#nY*ZZ[m&)ҥMc};e]RHE '~ >bXG9=cVd>(ndrޞiRԁvAB"pg!",VBijj x"mRf~F|'\}jDMXO"PF) G(!sW)c cu&EUnz(EhR5a6UcHFfzBZ{$ݞ[.)hTy!~ZҨeԣap 6vߣԦB8hVjN(he$h?$A"1aiZKۉ)B(j]׍ e Wu(d:VZf"g:YT"'QbLx(`=16HBASZVj#,qꈾ+y)Iݘz.88b¤f!*_;ii*K|S!@0jp ʶvZEgcZ>(YeOBB/b䪈iaYK~ۥ(>p*pv.Qa+SV)uނS,FbnCQvnþj\r))W}g8EDT,xKЁ!Ag偬 @-n^Jmʦ.A,i*܍&ׯ2 PPtmvaW殢Ep\GS'nT4^9eamF))7A~F.^PrZo!̀\քQH4ȦB* oAϿWR0d.1+m~ 'ANb.:ip־'g3&1)̤ Fuˏ܄<L`lX.5f7=:jLqnTb\l1t*'-qǪu4gw2؄LDf U+Oڊk,ϲ|ĺ"f1#V3-Am%W{6'{XP8pEC|zR+vBXx9g޶\Ǖ+QOP;gNp>+u 'astt|zd[rB7 _:[Q'kt_þuz]21JʦJ==ۅw-{{Гsx<:[Ӄ6lm3ZF~>NzKX|g% zG+2H !3/2ӛ>@`8`A&TaC!FXζ%1š;Z1cRSPA2i: \1D LD W ̋ٸd6x7bݽQ/4V.A/SsgT9BS*[T 'M1 ѷq6wo߿oQ6\;#|`\] ~ ;`eb`"m\+[p.a _`Vλ"Ɓ t 5cN ,LPB0xÊ.:TéfFh㨡(G"&,H rJ P4Ƴʠ0H0R$LȊ ,cMVYeBF$82%AfC8qYZmu1seYlǃtt*u.!LY[23';yŁsrٷA G=:Q]ɦj`ҋrjYR[x*i@tP@*mqA $BL71 qH`CP7D,,6))K4UtZDU:vpwUE!XՖHځ-ay2c$8td!C6q!Gb7+l`==~{QљD>wI_~Ljk,>+?+W>+5,.4)@<8$*t)Zȶ:bl "$.K q`8P6esQ퐑)čJH\s9>P$劺.z3"+Yfpyn q\dYofG푡^oG)@H!De4DGi\X6?Ij^]:%?uR6JTΔ5)EڵJܨ#6Qq!\ɝ-ԋRmc&V(f癡dοFf!3J?o 8aXpGw/< hE*0Z*M IgT3@٘<ԡ~ zM(> !-ګRJ ٤XZ*7o{@U>*K us6q!ˤ*e.G7WZUgbWu3ul!׶A]ՉW52|-e~jDd8aO=i̥AXHJ AiV}g% vveuN4p|XK4ɒZ fJ[0lepd%hyT;R!:+psW"(?!eq WIe(la4ӻ^#WY]bgikiw-_aN"E',XDy Jpe6dyPVCMFfcӶpGPgĸ&ZFƞ)jgZ._c(9W3rZ!ےmiO )@$%'Cw[dT/(bqQC+nEFa ]fq6tyٚA"ȝ N:̱ET5\I_DX9qsґ`;"#JonDwRCQݨjUA1UHzٿ:3K)\>z[>`ЍZ/d0=vA;uWAn1[%bpmxك&Z;onQͯKTW]ny|y6<;\%AeLyAݥK.ԑG#npG~ ܴnG@]> n #ֻg !gs|4S 4s\XAic>}1f2j3 %*f|V|dlLb9k"nF੾o+# O (oycQHfo~nga,oH//-7p:#ϸ/p gjGAp P mJ( p s,vz^P&(Mn^t"4LHPvkM\# W Q ZP^"}`krLzv]q 7Mi4 MYp " M*,Q-)S0 K1IEk>j+& H><.4q'%&.Bd6qGJbfꪑPb.'h2YbѼ, lv9P*QQV'+€ b'-*nw؂5n8CUr%.Ck "%W" %>Q0RMҫ  )@ ),$nq r&&! :e %6O#k$-0$ ATA3 9$T9)Tc,/2 'FKK.>u3Ȓ(]G^M5E_EAb3Ð4k=qT0+/G]Cg fB;'@b@+71J-5/3*rTGnfL3H2DCM7MV RNٔNm@+?gO2 n0HIӀP4TOQ#i UIyORSRu%359"1SOKTYS.@+0;DS.;/sW5p5)_Wy++FMXS>Iec""Yp!9BkU7 )e5Ad[1cSSMS탑2:UU ,4UU@ٔh_C6`hiP=۔F$CaKBb(bu]b-^32-RjSd4nV ?//30e;btbfɢfϲ:qlʹgYsV`ug riu8s=sV>wt=tF=g=QKk"lS-5^r^I%mJ'8Ph@v[Et=nxs89cp1 BalY?QqbUw}߀k`rW0!~w~PwaH Eua~xMWEuGOa!XvbvTvHg- Z'I8~!$788Cy4z#t!3"v{MUwP|9:qw27i}n@ w8s Dl8CFeKv%#eS)X^-8*&Z6iݖ.IG 䉥XQ8rn W|[\W']oPٕTcl>c%5_Q5ٔx*؂XHEQ j rb'bb 3m jX3^^-4jv!KgWHmE/j=/@5؍+px;An4:BGKS5F06E!7LJxGY"q"*Y5ppf?k굒;1y_79a1KnٛKDb"E "ejSBْ-ofyʼnbm?r`ag xpM3ًx#$+z4ePXP@QمT0O9Q=l:f +I'2z9̡‚ ڨO٢[N Vo`!S|Yk^ Zvawe:=;gVvx4zz``Z^&Qz7%o鹐Y#<fy(+{:r :xFzBۺM&0zbz!e r,!D [1[ z  q]UXmqQucyzxInFg$1ܴcpg8pqR_[ob]1_<4Q}tۢ-:D0vCϸ3yYZ0@1Z 䨻Bh",i&HkhjG@z b | 0`|}o?z#gZUk|7I=|3@h hgA ~+[, 9]: .|^$#Ӹ3¯Y4|ʰ8}~;ީR.0  z1kT9"i>[+ ouQ؁إ$-|~>H܃u鉿XGp丒nBO>Ђr˾݀ | ]ޤ:YZJȢKa*x/ _@ N6+tsۘ(z3СDht"R\!| {*w`gS+PnZ3wܼ. [Ƒ"lѤK>:լ[~ ;5q Ե]+p(!%PyhŞrwbH F~tmd{~[M+f73+Y}ՄV\%~8jTYv`S)Đ"$Em$.pġ0r-WKEMhN`LI IH%Ԉ6T7ГA|cu~ RSfm TMvXbFhJveTEy~ hJh͆Zm$n6g=w֡ 6%$RZJ)qjˣ@T /E%'LR@[ +{מ9\`^|_kmkacJ>g> tB)2-Q RO  4usʪǁGڪOmz+U;VyP 4[ŀXkgE250ǂg Qhaea7˩ 1D-9AMV[uq\G\Hp/+0Q;Z<yq<9G"E'6_+[.#hPy6Wx[lߏ_6( 6n 37 d@]Vɦ1 O^T84n.5 @`+*Jd51! hp>'\k q+P= |`% J>~xp>xID>aqx@&*݂ iςْҳq|죡fC,! ǨЄ<# l2CplZ $tك 39qrsɜ@԰4-SFd"|d!L"!/ I[NV3Ől``t)ƗBP^f)Gd񔷤$Txs Kz4.[T4Kbz&UAO&!L - ըɧT~N`8uf+hR4EeS.uCJ vDR)RCVָ/դLŚzMNT=@m\}̙g3bummk:Z%j&P*cY?;Z9 ;+~%a*sb3yEAv2a@@2-0y4qtp؏o[-nbz)(hNJ/ Ez=[:UܼrKM iu=Xx4l2]E Ph1j}gGT$~ (K5h`!8^nkQ],cyfxff=LoՌe#!bꦘ|\<"F1f,1,G ys{96\}j P[-?E,s?S0qfX.pMPޔF/sH2V Qd+(aCh]O*Vt^vqrsB)d(uXzxz* A$Si17W2V&6y{8I^('zFF+B8||P)ՔGbRDxWN¸ux[^kŵlQyI6Mv1S1Fنwo0s!RqY|8o-(^^0NigK)+XH|i9ew4așUcGqE,Օt/ u*g<bjYln iŒRx Mq 8}HЉ,t+wnŘwY'OyQR(ki9{H~hy ydyB*q")X05}8r,= u*[Dx؝٢mH馥qr9E:ӂ>*5xZ踢&)1)#ZVC ~Xo`?ʡAWaC~Is*{V6o'y5gȕ(ANԙ|'ږYYZԥ$*ʬ#BJx?*Ȑ3Jg ˺Bz(z:"KKMIF z=:3ĥVq؏+J?XQQ@׫B#8.;= Ԙ:Zlʤے-KkRHz5+ۮ9ӊ )lq[(7kjrs*uƷ3Ny|ZfE{2dqJɑHt:ZV+X곙صQifkh۰jwԶj (tˢ+;a·duP-{C{L%Ě;ٴ:m򇱚+{}=K7#];:9OI%XikŊ jB> U"4*{:{˭vi2^ة&{Zھdʑg+7ZpOZ 6/wB; lkQ}̰y~+:T lK,$ iE(Ħ;y@JyF/̲jaJX<&y{>ܻ!;VF ĺˣPc)Ĺ{[\,^2`%8sʂ tmɆaܪ%zz~Lj廀,BlAIxI%G whB۲U|͚_,¾*Znqƒj l xit xǻ\Dk"hxJF+Լ LVCA8UBw|̨hCP"]Qg ٗnTAiڌi +AN ?? r*a <ހkP48}䙭mJL>oP_a ?Y.^3ޮ([|q慢=l=9rbaSD^K.L8S,]2%C63'>Wfn߱h.Uk`uNjm,qsMlFakPC1c뮄H.N.&S}S80jzq ^\k@CϘҾ%#n*nv x9;ꄲxpn,~ϗ^Oa]k)GMNޟlF$˖A:M!_#?(%yȕvrV4>}~XO5f; H,N:jsT_=Zo\߿sv&SM2-VA^٩J䀜[[ <"5/g#Kˁ5oϮ?z,~Ú^/(f'/Nyku~ћ-<_՝]: }}mXbyI~$x4V 2%ja+BTxq`ƇT4I1eΤYM9uO7lӹR%I.ejrӧHaā! & 0%Ib D/:L#Pb6GL C Z8yXaE"V%GW U+]\ٲ'\P5ogСE&]ϸ.CIv^^Zd|Ҥk dѪuK-Aq  oxBoxݻ|ncUŏ'_|EJ==/vOsU-=iP2CF7T $-RK/ôS 6OK u"jlض[}6qɽP3<MV?8VfeJ[ގWw%.yg{Iٛyh5MzAbb >`j,%H~MݛԽvqzWлV6C" ڗ~ +`{C\!:鱷zm<67ɐWej~ȋRVH:vYn]gH Yvu؍&c)μYFvض=> # :+_ݍ @|wm>m rH^ !o;w⃇8H巧H C9G(K}Iȕ4+ !ú]=A̮&a6i-iXIJZvKzSv=@%a\Ont"_2U*}s_h0]F~Y! ŇeexIl#F7;/8X?"XtCx7P$LDHu'ML &me{8 k"6ѭl79[}HDr.RH?2JwE\5Y Hr뒕dWDu"i4 *qr'cZNc#2g$g9Kxș$ҜJmsHAɽoѝ\gO}3tD?EV;ΤptƫSɵTbyvҡ?/P?!"s#"$RKwB4]EV`42$T寅tYI޸ƙgj즡kBث=bǡ;eQ-{YLMˮZ➆8=d9cRUQPNՙ ͸Pj%[' WUE*b-k[D4IJ:MZ+L:6?nuo}T6q־@ٓQ X]+RE% wƘQʅAAZ(mrc`mwk5q{\.4iNg8`o &˱gмagGN'vbU>NdzTWSN ~eK*IaTeA%e+aXh0{ya=dFЍҠOĕqob@/`tQn^8!nwLUBasPy~t vsI.rMm+MҖ|9CvylTsDBls]0ú&IccхKF d^ 9fv3i%ˆFd\YV[I5 -2Jd ϑ2U8MY֙+6/I t۷]"im>R/̺P^!X3둙Kz.Wz#Ş7isCؽj9$k,'S5{@Z>k> C*/Y<9}; A< *T  Ã2 BA()a[>AËAA{ /{LBCtGۻ(,۱PBJ-./ @j:x:i \0ê 7dc$=;EѰA CÿN= =)YTIFtK;H G>|X;Cuv c񃸉lzIE~G ;{Ylɤ#F*QŰ5 TB IqDj@Iԙ 2<+JIP8, R d4XX}t,̡T==܊pKlt|JXYfJ>(+K ̯#^cʵx2-A4J(Kz)) +9ä^ܚAE͸t4|ʛ#&pJHJwLMtӼTͨ`DI`CH\Ǩ#xǼMGN{ 1523Ţď M#7dܽqyϽS&ƠAMplA4Oρ͘H=;VONIe;ΟNᰂ=T<BҹR|LTaFGļU!;KP4TJ= Թ U8 QV5՜ OQYWU QZuO8٠ F*R4Cab<(tVD-1jVg\Ё~T2UKC$W,-EטXXp\SHzٟ1QA6 ':5o͊_ݵ=5Q?4 /mE0ԅXEXC HZ a!WN:YYb-U}'YYE5!%Q5Ղ]^ɱ9:.MXͩmC MV#%̬%B&]>ђֲ#R\+WնYxG3[}{׾-OM%ۀ=+]am̃ 5y|\XˉI>[\%֮G@υ-Y^O=sM]Y]H\ؕM_[D[|7=/ݪ` 8X4QX{\ܙ^ހ%UT^h]xY=a]Y]]-Z nJ ݁%``B_9UVL]`>=_nuPlδ5]E,;T%HDa/vUYS _eGŀK !\-b#ލ}pމM;܄b5)N*`:>-Sb Vc(cƃaޕa]Hvc_1^:& `]ճ=>\?#AvBsEQ`Fa`eˆ,e0JLV_MfSNO%WD&C`%YU&Ef3XCP`:eGdc\h&!<\DF b~pbԵb@guø-ẝ٭f4f5 Cf8ǹ6&gW$chxkg{!gyVzc{)|v&>daRP`vPf`9v[5adM'MOjbCi_"`5K֑N\ #əP v7ce{ED}'isi0k);9f8 ?Ȕ⨖j@M+kύ}:)|Pݐ n&RM^laImXvgjl޻gTk&`e.js>„nj~ꆮl3jN#],%dӦaOe7^\D:׀g팭N.;f63Sڃq^~ΘRgKnYlUkͫhnd6_ n@hoVZBTfk`;kUTo@m]kmu ƾ0`;/$n6`זg|nipp{lf _?Zqm/"qyq&bG1PpgqnAPl.4N1pvrz]͖_ճrn,m3.žNo.qO%6iRqz5dsZּ78f4s = aBs.dt-YnrD.O~ZОt:t(/G?StuQm >UOVWWX'Y%}&l9uPP#ofUrbwUEj)9 mqX3fqlSCn#@p4?!w7st/xOfqЊw|7}G#-6tUeՁOтWȒ1ruЋWCMunYPx}'u6gw()sl!yagrk z?Wg r5IkރiO:O 9gïuKߺyE|7zb3z\hOe *t(ѢF"M'.8SB%u*ՉP=IH g v2H&\0 V 6Q$` i5LC,y2ʖ/cάy3da,z4i>CG]\qZXSv-<0yAV49MuȁqàI& eczcwKkJb0e.ΥϣO~=Ѧ]R>uV\/[wh @B)]u uDa^AKѱrءHg'bvTHPkQlH x̠PgmtRPoa\sBTіs t-q{WӕޕǞ_fz]_iQe@vcxc ap_؃EXЄ.Ne!|)5֢BYbnňq;cpiY-E9P xUV\.K{fTjB:a:֖FyjeX+TjE,^h[V ٥[ڦPzT3nDpj~+k91QUmuR]i8uɬ+|A;Q | q݀xW}"I|iVfدWcc>_GoJ4hTj=$e2fc'IOyrĬ$Ӫ$匙 5QtJKZ9{ӬsEI3Jxӄ mœ24ʄP?Mk5q88)#kCuHt+]1z\3MS(JO괶LuQ{ƛ2t Mm(m˭$*g;;rjQ*՝X(UBuy-}RXA~CZ \;&$E\&xj_ZHƶ~"w1&V+eipV dX1nt/7SU̅pH:F ,`+H%(Vⶑ-+7Hn|[(vݚ뻁 oHX?f)Nyś2jo~ld̀`=2Z5a/LZe J0Ԥp#DWh5m8tDZ#5aeVqvkkǓʚzf;U +mؗDKܩ?S&r0_+I,'F[$n<7*qjJ @؆<"r6H,GlT.0ij,9M.ғ z7.HìbQ9_MHס4M$m2,yAzm^0(-ICǤ)恊- /I~kD*lb\=Ǝ]do<_|aU{׮ ͅ71xJMXܦ=375Tl xgt꩛5&\ !\d9ݗ2"z#>Ǹ떾a  zgEt9𮷩n"7=UCQy^M\4Y8~rCFT]}5A*n$b׽=aO̽7=Nk E2;'@j0~gZ|O<yy H_.pOpV7'=ሷՄpwߛ-_T䟭IYu^$-*ޚqQ zm\`fߚԇ^޸!DJInuҁ(`= 4ZLYJƽQFuW P01 :!ٖXސQZ Qn&aSVZUeQ&U ra'2ܙx`aK" , RD~ɇL Fa/2ZeП:[Y !!TaH,9,`vTb U!NE`LdD%'na]1R]2N_faMq)Z!]c@ ,Δ!0$# ANF1P/f,ci\ rY"NV$f$Et*}c]au9J:>kI( c!f**=dp ,,ڢ`1RKBSN lD<#X#c8!YH: [e8DK9$A,&J( ȣ)OfOb  ݐb0AedދS2dFC~S ]!JpWNE> `q`qeQZ[[n \%%AUO ^R*y툧` i?a%.BeRgeTfu^R:2"mmݹA hR#.IG]KkZZ:#,fj;e^vm]G=!'IaBs\kQt igeBf"UexY3mA΅ftzR >{ickgl+'smg/Yo()=ᜂnGq\+a&HPP%ա)BiA(uVXE݋FVjX->N^Ghyhb%b_&!_呶2X (C4P(q-zic*cn虒)*PٛnBՉvf!(܆Ĩg(_gZ& i*K"j`*)2EjzN)>V2GRϦZd>F'Ng+]dbf흀 XF2fFM{jD2TGfّ;@^kb {.p+7j `x:RkNƩr磴!r]e,IfT<(PsސIZs%I&$zܳ"ovEp~Ǥb댺 l{,&lnMvͺ␨ȫ3\a"ʝ.-("LBk^FMNm_ZRj|jjr[Ȃ-tɒيTlʲ-A\gg܂$ Ǣ&||b-"-.2mڤ-)V"%oJvA xrH*%쒥&$[Dlg#2Uo.ӺOZHfKZmOPjF΀c~o𻡭Renbjڬk,ZΨ|oJ /W FQ S8BMT_kD*ʖp T0ѭ~ejR 1.[q'*b;Za `PqY`fena 1p"_vjoNOgptnqi% oH..5ǧpyq66sh7{s((kg) 9+3aά+2Q;̯F̼`W􍫵q{p)US}}:3ӳsSJ5Fh WM_>{N=9 <rwERt&j~G߾H$|/gu-I BOA +ҬPD`BiRQDRh@!v$#=t/:ty&m;yhPC5ziR?qęǨSj(jHW*Diu+1IFd4]^,dZENոrkƂo̔26vrdɓ)W|sf͛ Ҝ gѣIb Cڵ bň2FW8eHkDR ޑ)L4wsixɗ7Ow okI*-7b(^q첯 +K ,f  - 5pC$E촨T; $d d/-j=o kS踇~q*zc$ɩ"nܒ.KJJ{lLᾱ+H܊ЪC,A$blD]F@|RGKLMBlEaShFQ##S*dž$(Ln։kS7JaT*f}Y042U%4UeՏzsSV8oցr]]FNAye)ӊ~H!-4%CAh >BjCl1xշ7i7r"82d yޭο(CV=eu*Khuޙ磤ˬ%X㺾͏ΔAQd HfuOx[ aLiʖ&4^2#'C#_Ce[+a<V|VǪε]uC7:5S y&+oΩE}viViY=OŘ?7]<7k((z5w=xϾ[N_PoRՊhXG!G|ꊪ^!#~0.ށsr&4=;L>{ ~fW|sqܺk W6O-z!K6ћ͊Ǩ]e{Y\ @ =pI*> |s.둍ݱY@?'>q<t9CPiaԂCD9Zz5: g|B)H6u 7PDh 1PK"RǸ(5&;$TÂlUBܓVf#&Y"]?(@SRHUkbdhHv%BHA=ˌVFA( 2;R%LOѯB4d8#J$h1JĒa6!ZDb?R~''OVy*'j[v1㥀Ƙ2 *l'1Q 4^QSGEM7Tf 68#N'I^.ɔrvy'F}h"YX4H0{$ttQqrTR>+6ɞuEh tâjX|@vB[Le4T ݵ±V7F$M=J{CfpC7ׯ͂1Z<φoKOj;|3C9h֐s]]dF9E.Ƚ%o~Y$L;msu2 IE҅PQd7§C-gR5xe.)@6[qL|){R}<zl9[ې-`g殮C]|~h:/׮3tWh֔әmodݵչI[_%vsV;G^O&fb^||*x'OVɐVK ]ws|)ϟW/۝ޥw aށ{3ج˜ڸn(θL,ԥ 2&/.)/%oh*|%^AbX\00P #0̯~3b w&CC~ g40 4 Pа^+ ΚGVfPOT qkڨ 0;q0K9J  O  !c$P @&~,(NsLq(2hZQaM,d1eHLkn0wQvB.FEL3JQ24$q0e8jK7bӰ/'1.p!3pY q{(ѡR>"$ q_O0 AyMSyqT1% Hϼ"qW7l/Ǧ%yfJB8 c +0!r'q d$u"r/>,r'.@:?p,tй(Q 8%mX%ulz $&lc'gONq/r԰) rs,P*;*3*4-2T瓸ƦpӸIJr]LL-k2I0.7/7&A/6$+f\7qWQHS(Ő$Ӏ^0 ߎ;!?n8"&\"U7Dqp6WNfjJ%?7?`<{ }c kmE:i%7v1%(p33<s4$:0i=ч2^d3uo,6$}p@4QH b8 . #FAAwg5s }|*112M76" 79;7DQ<VtPPF4% GJe4FF?u-yHBHu8ldG#9f9cЀ S0j-. KK/ rLL3LQEГE[+m5۲]3-4=|.=S07wSPu4X&GOVr$s:{hSTC5T$Q N5SW1cSMNaO^SbFFuNOO9G`7XV QY ]YAsdGkZ+Z,0u4_W)N#TsT3T\1\1B U1"Z "5# (!#uU6-[h5c` `aU4URE flbBQ0[{uK5״BT톑LKN"RiI2֕_GiXf6ZN qոs||tup#h6iuiiaU0^uBg|qHJo;:lAVlIlMlm7Me1hu $E*W^1T'63L5Q Wx%p6qF ԖqMv##h}qxxCC_F*Kt5PUVEѳu*v;fjhFjuv"6HH|O݆xx3-yU3vzPzg-ʸ{%K{=7G~wDwN7Q*\7dVW!$w4c{{wGrp "u?YtWr8^Z"S+3ix4f8ɃBuuGX}_#!4>+wvq$kWE 5qx7ӦQa')18z7eD9,l-\Պ8SeWV]'~H#XjֈݢrBewcYCa> I0x{}ojo5JSrG"ttI3wkԴU @rXӸy6kX7oX y̚`!7XGLِ-n1yUB^>C)xY&O\ a(YpTF^?ҙ~ d6ڝsxmP d 9WRZ- 891@+(/{EI38|4“K=NZ'X^]Xw cz_[lac9H/N 9/#j3W1 /ࡡ ߘ-J0hKkU6)YIZko'pZfXYhH t|!gV %B8q{-':Y\,˶TF<[ }fK:w!Ǖ[X/ys;x!trr!){"Q۸[:̒0 UE{vIm٥Qo;xv;`{@pЀ7 ;A"0I{9|A8+{*šç7Ok\KWϕis.ɍYH` }zth}x=8Z"q՗|Jءz6V ƀVӎXDI]tO9UxWGv,M+9|V{s?WtA=%}1#[|EڿJb (g{y|S=mW=[_]-}T$~"]W&~${Ì=iYRlَyҀwX4RKŧl ⿜ &B+/ ;9^Ab;eێiV>[%cox懵y3i뛶5C{*f@{]H>v " `izQέ5Zƞݵ_X#jYR8 :%D~ >#QݗyK_i޳2[˶QiܫU7{z^,Qj 2Y Mti흷\օCe$ XaA i*\p CO#Jm3jԈkǏ CIɓ(S\ɲH\7͚w00pϟ>hENO sŐ0+d0C "tŊVb0у=$څi* ]_cNxQu]jν'a^8O羥Sz/k Z}p4+f3VyXVTuBqR ^Uhf6&c(bah7&h02'i j G}A iA~`nb p;EXOHQ >xa4uف'dٝx_.{=z؈7$i9 [o(X^ke9#PI#Vj饘f)⦠jZbfFx8Q$6`9G'M=~|_HYp IINUfu%Z)yeLaܚx;*Pn'IUH.I.YA&hinIބtj'p} _.:Pt)Wj$/@mk_  ":ԓ>)/ɝ& l]JmDmtJ^Lٹ|7E`''oW ϞU0lۄ1p=>ifưhn4ߚBN)TbrU(3P68NsXM{Ao4Ѩnt1ķX]).Tlѻ0uU`oPaCG(vG/ g;}К,q2y#A5kr@M~Pifop.X>翽g*TruQ71][0I~GIe<1@ <O6i8a0{Cf̳|K"=6):5@\9OH40;̗9 /)KScH:~1)yX. 8*)ZYX+.zq6(Rq!{O0$$C<ˍі5K^t360thI, eB':qV˲.9DwBOc!шI H'MIЂp{)Aن7*4K W8#%l7)桃켢%LtŤSMr&K%ɦNw&cFf;+tt e"3F:ɑ_$>Rw.s_-$M<.`BM\U%DbpV(COVBB k*5LKX2͜Oh(͛"dM쥭rJTIUj;*(Ψh8YJ5IӒ/Ūƴ ԫfͭn 6VRUsCktJJW͕P;w˼2.~#^,QmNj`Wv}fmk<M5+xӸ|@n,xr.I'άn/ySUp7-l 7Po'VLЛ@+ 4aӅ>sqH8l}BH*zW1b͍LU^q1;+R@+w! ⮵! +v ƭL8on@  R؃g^ Xԑݼ0.\`/:㝤$3#15$~K`ko\! ;3@Z\w B: ާP!"8y~¨{0=d8~?<,`cX'bQ~?__:@z>5n~{ ~A~ h~u>G{GsM5vvO$`ցWfvlrwqٗe}w*1tFV~'(xF~:d~XpQ|Wv{\3XZ"z>XIWX5H{R^$׃$\en'|椄|vN8||hw|P,Hq.؇}@L#xu~co*ϦO0x&=B#ery_t~!8_1tcTiVdYw43Ar|Јv1OPF9Velǁ6Bh烇ׂ{(IhtW$Uq|cru|ao]X\Hg?8KA|짉e(dg3фt37zH犰Xx- 8*7qXqj~XZȘ;gF< )j*CרP+xHu}Ax~h3Fhbx818UNXNc؊fVI[Me(XS7IYsy[C"D6`z/Ӓɦ\"6}`x;YmN7]v o|?c8SUHzWxYy`ؕh)_gx"6{r^&!vO:6K6|[hguV|Ěz+Ș퇛s14&E0fc]q'(ӔIt%xt^Y)'^ {6(^ԩeC'CyjT.՞|w͹ ї9Q#0{8)h5?ČgDOk'pDv)Hv1 {Pv+ vĔXKx )J9*o5nN,8$y{9qjZRzǮ1<g(j g~3WfIZ鈱ih!%*#9D,!ڲ !#WD:m~vxb5}!k9~뙈n!8gkO !P :A;gG3㺏&vyƉ0p2KT\7 9;SQ{E;Iryت=津P;dR5oqˆLB ?±~ Yffٛ#[Ktyf }Zs!p;aƓݩy YKyقYy8LFSVY~^s+oIr) Zq~Ao;kq?R>/9r;[(F ǶR*HKKK3LD5"+,i{J*,  ğӚ츷my*42LLʻ̻۴ ˨\z4}peɽK|ZrqF v* -,×se`:s"I9(/򙲀XNyfWX}q {`w꫸+Hf+Ʀ)l)n hR6̝'&f|{2R'.x9 8H CSLG>E,?!,8 %L'\ʧ/ܲ#5suz+VoQDLcBLD̮B?̚ʌz̜Ρ|KpV͛J{Ʃ yu'X$}mlj)rh Q|l`˻aϏˏ2L :B8 L-}z GL+p](ɭыC}g[%}ҬҠʔ=kG7C1!=EGF*KgvQ]Sۼӟբ¤`-bͮ|"7y}6oϸ{?y'4n$\l<͌5w}QAݼ M څzL=YlC$]@n~- $YFV8UB}V':}+Z?J.2,o>_A%zBP_tl[QD\,^ĘQF=~RH%5џRNęS͚xjY3M  3!+"j4hO V©A+RTU_:,Y i)  śW^}X`… }w!Í?l0#coZgΑwTКrLS֜[ l6Oi[m0iNRraÇҭ+hRvݽz–,лoB~ Ses>U XsׯʫI8߈3-oB /0C 7,10D ,t6LCAL+՞鵼jKN#\)O'}j8$ҾRJ$O'FRK/ŔR1SO1-qVRQ3\ rmTӲWm =`#Hͨߒ,HX2Tn8 R2jϴn%5UШ\@< %O#< UAG!IBI)4`&xM`+ DvB,NͰJUcUsNjkA?js'DDv\&ln/g6ڔg Z[\č\^"ٶ$rWAm'a^@f _]8mf;Jmj2P, BZ5DZ8ur h6ڥSAYe3r֙"G'mN)́É ikis.kP_;kiҹzQ ;OFe Xwwp9CRrMJ2]$\l<}e\<,t)t0n"wؽEšb>OkRa+Ë0 kNn6!І77r{DvXoA_SYXaU䷠`p>N/斘f)@6;LIN" .=E_A ʧ8nq5+\ƊB?Qc@8d&üPs :"ش$((/b ?oHX4إDJU=@DcՈ@76ә cDTWJ<2- J ^s児; {^rԟ#bS>O~xd?Jo S`߰TrULt@urUֲH]r^DIKȜH>ӥόB u)z'Z$=dI '0b;jVϻT#\]Ђ<)Z 7J} ,o$KZ]K!.WE-v" 0 "2ٳ[RJҗ61Ѱ`PFD@QlKQ]xԫ!GTFy!1jɯֶjZz[O5:f^hEiEY.15ƉeEjΑ"Fpѫ!Qv$` 8JT"*]&cA6!ӬK@W.gGN!+i2~_<V2pE[QiO-W0 |X\͐4C*4]u]Sj R)MbY^"/н)؎o4mBc2Z;q+ds0Nwa61vb[P&9(NɇLv}&qphY0ɭ@1i8a+ˎsWXL[k?>o"ZG'B ?Oɕr{6/6]̲I(.'ˊlLE.YIsM*9!c*;,iS>?/WBKӘÊӢ @x :ǹN"$$!+,Ԏ&4=C B \(D>/[0kS"A ;{>*+CȈA;>:c l4c7Y:BJK䥈sB #9~[=+Q I DCU"Я LC@6 7Kĕ$C b!@-4(D EA³BK#v!q[X]zªDERdG. h$A|@A3)( 5<-ZLr4!8T>^ G:\(`>5ӧedBF=TƆ f\3 WFInTvwyM7b;DŽ7udǜw \ +H b@¯2{}8~ @[>EC=`d>ȯ䞇-̋fDI` B8>Sl+7jlDk|DĊ*Ǽ$odI5M2D u,IH˾[KtK3ܦk")Ր5ܫ̀L-1;C)La$F͂˘M0GL%m[ƺɻ䜒\Jw)y&᰷T=tQk3S|GIH؁4t8l= 6d-0@rͅ$ٌHBA@E ρxK,9 NcDp1Nw*G+XΧ (<a4N{̜(ܖH=P,tJrO;sqWaf S{mU?ң1#¼4dN3XD rM@hYnqz=KN @ISNT<^_z$FaUa.Yޛa,nM<\Ơ@ޤ5Y#kKxhT&V^,(6I3ΰmbBS/2vLE`:ZZ8vV1h@@` "&NیD|zE ba^J>NKdô䣢d=iP^%SP 6~5mreE]v^@`v9BFC.Y#R+P=fIbCzFlmd+/Z+r~s.veCVCw!Ig֭[X|V}n[~^\0T&C6;6if^h7~x7f ENV"7һa`ŏB2i2<5@U &w{ih55M嚈8iah9%"%> &vf ˇ~ -R nNN: 1k4JfG!T8~ 3~CMUxfX;kAq-^3cv贅hĕbFȾbMZɅj̞bE,QVNԾ=xZ9ie*zƑ VDFѨ ~+4\hN<=SjV:EnS\fFNIZ#εyƀϛk]LƗooo直)SBjVꁰ^_p3f,fpspC&c #H9/Z!ئf_P?~[T.&p2#jf]ip/Ȧ&7SFqObIrr^rS;c:GvD,- su$Waq5]6ԕedssCqqGKrJlhoCD/59/UẃJav>[hO_PߊuR[ST ht oCZƖ2jv^bu vZ*w(?vHtRp}(=v ]3?4vw%m[dɼkuHJw!+B2~~/&yڢk+u$zV#VLюUxS9jXf4GN]zj(JVeJm &* 駞jI(pTV$ju`F {R+bl|*j)껯VF)w)S/ct#DI(sY19Lru\'qTJޕ~w-P͒} [k:gyq[Kwˮ;/G[[gbݝR[}5Yk/ek5fGǴ4Sq 4q yqFjܧ& $A[(0;8<^UhT5߽0r#ɳ>.RAe:~30::bIM/;d^>|FbgD~VL\|0Amd]ݣK{SjZ8:e25E>̪ ͥb9*:R:N b]:7`;_>Dx U</3^rGh7pB&, nYSb5҈m% ißf½v&w>įNL侃:S8mS(!tBls7>@".-jq$2!~,#?~ Sij0\!lyUFj< g%Y a@CG`!&8,O%.3*V_0s-`#.MvʓB_B@(0/L*g9cvl`!GB daiN] cHAmW$1{كIE}Y^Ȑb7[OVQXJXˍ2JKjT2dJ15dbO$hL kf!P:BO]ĪF:]Tf1;W-],KyMU {%4"((GD."RUKE4,oJī k\YSi<6#R9iM_+ZyUTU/ m2%9"A3wئ t%hY+-ʁ+X6)/:֘tc in/9;4 gC-j(xL 9a3q`̢s$& J #\:f!af'iYF.1ꅼ:ݭ ~+w$5YI<,>"!ۙ?v9ZTӻ )u~l:RßG,3ɶ3IvzNikE4}Cf"ʖI'Q~mf&۹}p7*눚۬8ZG:.S{!7CC;wr<5ݲG Ë0$!k߅8Gg(&w&O8`ZÑkiL01ia%~y#/M߼jo>:F;nI1UQ4XGٽ8ljSC|QֽGӧѲ33K&cn#hҿٹ/!.oг.?'+U=/wZK pɐ`MZ\[! MY-͝uO ~9hA 9ߌ1eYfs^w`h2]aj^Td)5Bh!$ۃ-v]65D Z]9Wy .r a ~Er Y\$fZX % )!&_e"h0ae"U; B!x\yYב..B8`+)\!5[.ˊ w-b+" y".- <_Wy"9b&S9Z( HlY}caAx}4af`b$ڡU8c!1C"EY`Vc+]wIbU#B"`#7 82%~ڼK9K^:nlAnSG(#- EJ42 @I^A5΄.>dA$D!%ZeJ- #Upd`,8.u$|qbL&RmhȤ`N,NbO~%A"!L,6A$eeq_SQ.QTTUDVVreyc:&gX&%eax6 Y^e%tLLtRFbRU]DfM&lZP.Dfe%xҀ&#:e&3%jfjn\׵&x0&qXYY"w[ RZ6fvrRKJV8fu~(Tg'ha$V|)$=bfegH3NYgKVl ԍ%Noobel˄VqZa]\JJ]K&JEMZa `Yb)bNDh׭'ASB8h|>UGm k2Nl"&iFaeVL`ͅ!VRHvXޗz^d_Aݚꇤ*A2ϴ$OqAV봤"PJ\@}ާm).0':ORI*+mk?qE hVDEc|~v*z&B)^b.M,1)z'gNU-Sζ$~V෾壦D̤Yje؇Nկ:Yln6#%B'j]\@b_ B'`2&aa"lv:US`e:rȆj7Ee2*Bb&̎bTl>U>k *e6ھ\@R}*AvnhT\-f-e.Tp|p o @4T+F61S@PJGȜ-Lm.[M;/( BtD٦BxW85ڔYrq}ajuruWCtHf'Y`5H+rc}UX4@8Kzj:^םv0e6-ca$/׹jc6T /OuH`ӪfsvC{5_jWy&.$b M[_A\mRvMso\ߊ7=)JagY'&Fc.dG@\ Uuoe1k7rzwQ~XΎujC>wl J_7>0|~?̂8FSjC|ĀDGr Ă#x IL Wf/oghi3,v 8AZ8Tx]@lc˸.Dr>'ȅ\^48qKg~Oxv#uG0y1O4/kkHX/Dm':?94:@] 5y׹~297o 訇QsĪ'9.yE GIjSx_gn:wzhz(";g\:BPv2F9tlw2nZM {yInj'29y딏3,9gUKt c S{L}csu|<YvQ›|zķ9c{oĶSxΣԆql$o'1S q+8f8<7뼸 ~2\dK/af6s&ˊ*=Y!(OO=dPgP,! =>XlĊGN2iҰ!!A&r-Ų,ųÐt/C' MÇ'VqcǏ!Gzu'L&vK>'hw|;Zy#U뭱&M0d8|Э.벅 1P l†vNHPa*f,?8-@x3@4Ѡjdȹk'RJI,jn#,[`$Mb@2J4tM >*G!4C?L(1/*&J+h^N / Ȃ~LhrHL$A9- Va+M:.oR .>p:3BSThV褱[0VeuCO#L(Q:[TF%W}%tB"M_TE-IP HGl]64VxʕcW&-QXM吘Hz:j J3Bʖm<x#r <eWPwyd^S~'Y7 2:n S)1 <.wZ/" ى~}!/%+rb&oq6io6k{~]BC 7O{ia=}]P:{\LtJۣ(ur黖ڣiph^Go4,>PwYB?)NFWkE9%@&YJkhÂ`!:10HHwÚ`~gBO4$eX(̈(=yaKh3cch5?Ip`0 &W#$-SbFJq} if6#Dgd}5S9iO P׺;>~Џ yCnId`K]# ~XVs&eB.vf⨾S^͚?Wb$M--L@f`2!t'ZO̓(AF *(FXl-u)b$/WuNĢ|I*3VCeJO43S* 2BτAN/[!rk F(ǥ&̣YU3 d6 R2HWw 3zKOt0Jj8JR(䘸ؓ>!gA{^UP|Iy=u Q(di;}V=v]B4#&&F,$[QjWl{u!Y `NY}[y#\,;GVsL_e]|  UV[+2(-}Q)J?殂sAnPmتmͺ%dlcb8t*YoZ-KM-q @sZmGX 0|>Ӳ R+.[_S+pᜯ'#G9wӼ;v`3 .up?dIOZ"G})z).<H ,Vy*WN'ôi8A׍m:0?ݪ4ͦ}s9fIŨ;ktfAdMk=eJdS^D1&5ds[gӪtH mb_n,ob=apͽvs!a{B"9_b4el$pG®] _6FK ^CnaiwVZy.u); :!!_[5!Im t\7! e:l_G쓙EJ9o?u?rLXwW͜AAs5/-*XN" BՆުNVK[?]v6ٟb'hhi{W\.vR{\cw>+oM?$i:ezS~o%:+ʘSU|^,) ({ް/*!M~/N<,MȨo(j%(̾ @3薊,O0P-Œz., ^ b@0.يG{jtm* 0mVmp2p l# :ǺsvSc0.MLMRMjO'v/D.n^V|ʐ p )bOR|rNcΟ# 0PQ$p' =xⵤ EP IX0%$?j̬AQqtpQ1eK8z Ob_ F:Q&Xx71=z`o . Nf.O+"Jnv#im#3%m5D1< 22'E }r"@ZnHr 7 u8pv&W woF1 $?) %G%O "*Qp*2P 4rMq( 3K S"Ry Om(Q* ,(+ 00.#Ͳђ1ryRr.%)&F`/se4u11J3!IP@w̮G$2(:D 4QROx.5-&a2E:":M;5;97g0kt l0@#9@9"x)6s)2"Xn;}F?;IPL<ǒ,S=!=4-l'i`>-A.C?ST0#MAT: |ºB) |B5LG sN.47=4@TsD4ɒ0PUI]+ TVF2n!4G7C.S?3tPGHYP1(+Ԟ>#4 B/G|֣K3 IQOϴrQEM67/  olGOmì T Q# U(Ύ 74"t4>(/R"S?T`o)k/2dc V ɕҶҔqwek*)+boSӂVFj6W6sbNw@ p7!PלލiCi#V2-nk6@5W[(:VtMjh,@ 6/=WuѕDwdwLPf5+wTpt4wSKn }!M w yyCikbzbUV?"j(4tS|A|KxW1uy}ˮuL,,aTzdK"wVYĎ(+xw,3x!'8I!xq'(18J5[n"7u`g)ďk/"7V};RT]x="fq]^nvGvøSKH\8xHao)$2)wWݨE6@xLEԞژ/d8%#ԎG ;yRU"jB1f}X_w_ϫMF7y'p+Yq7Ɉsl җyuuwOP&W"ЕI@b'f^N[ VsHҗneًwxyO7c89`95h`YA/$v`մqS @^VJU٘<ح3l6Ub홛92u"2zM9: >$@F.yRn Zwx$xp'q-/m'c=armUzsa#?c9}e-WȚa^mNEwz}ZDX]:Zy+@/Z$~ĸ9f/Ei8:|k0Z}o9"B{{y)z"H 35:,ۑ:5{zy:ݲ%jfx8N'3`;&+[\o{sw;w!»0GCWRk:/#ݵ$ A(iirϻ+ dԽ/4;bRi+Kb鹿 [Cdxܤ)u䜆[G{FƉbx_š1kN9|+g\M]е;}Ó[Ql4֧xD^IM>I= 9|\zi~}S 燂1%~z+!2g[H6mp9 !k_37aEe\ cB%_5{.tluysy7o)-?&" V<ƒx9(pF9.bmY ۏčwե,II\ =ԫ[SΣ׻{E*`436 dm bbmIa`}HYat`mFa^auG&fdj&܀ihP|#7[ AZy֎ádnU͇{H-dN>dv.%%V2I5ZaPCiAUq|uPhk7#D( X`w sMMa.vXY#I^(&F).P:fgptBmsWk*eKTJtY"l7@{{A5To}[I|N'U2Vjhb6Jo6hR%bZ$= HBv{J#v:`5nGIKr&S, r1KKf;I4fgkkp {^{Ng+V_f6 mzQ=AZy1Jduh$ALxӔθI0,@6 !H }XU,J 4q= !Ճ͛ugg]x͒0J̩j9q˝ݶްn,FR# x+ w4S;Զ ˖s.mt2nnד[$aOP fw*^SLx;R'Q&}}lNJ==I`US썬|,l Q">;=$9Z-D۝> =W!˫>'}0?@ x,p\PIlzcKdz d~; $ raJfHȓH"Svx4V1S@(" O P=kMsc*^]YR_ K|1alIX`/<^>HI;(E$Zyif?~{5OfH Z"ǤAN?$b\nH#g}rZK!-a^br}, SK(J53.gWs8a{ܔL0C+~=@syjw'T;zϙ_̋2''Au|G2vk?ZB}|mL v< _XO1<̷Y\萯~f͗*4oueF-~棗=m~#9MNޑs}%@y7idqmh~wxz}/g}}q7y7q+}~ND5gs\GG Efv q=72M/it+-w:A8es x|gxd@xgY.gPUtR_8Hcwpjy.prwlUs)(z*.=6+ Wp׃2:(S< }rnBqnoPhk|yt|(}E}`H!yG5f@hj{l(*NΖs-d"ӖAї~XX,i!,IyG#(`1{w&xXttD2}^X blHy, i~GH?B6(tx؋5(HLBCg(w%jkxux]XYD(Əh''w4Յ煎税M׎HlhX7%XwR `-ocB!y'C$RDy jIw~_6? 9ho֘< Xj$$$-7,V.vȒe3_H_G9I_TfGWHIaWBȔP /y|eiTboqV&y`D}$(Yr;yMthg >qZ6FvIyIYjebޘL?h(Xvv{cؒnIj8?łVp8җ)V jHeA^h uSYGLWؙH !91V##-iIJ? EvrN *! ǩ;ԠԳFV)zؕm:W6(yg扤*zآI+99v9ţ{zCiݡ{_QKMyO#-) S?>YɅi_Z}%+鎹4ʢ9z_hpr:R;ڝ \zʧ~ zjieӵg X$Vɡ !" 虞#!lJDnj~Z|ƬzboZJjA1Qڧmb'[iY|Htx'Qy 0un1=iv'#AEjMj]抡ze-t֥^[븚&hjhIm(q" |֮+KR6{2iՁWƤYBY]z~`7G{It uM ȚQP)~3Yk`|sܸ;LOkMV-k;ƴjl&)tDs y*zۍ ;M54J+pjyO+ iU{ Ew!k5c+*KiT ൯ ";{{( b +[pC̫C9G~iI9ʹqmK*CԶG󶫵Ѹl5)#oYۻ(ṿ;cd:i3:FKϛjt֓L*˰g{Hi / n:Y;I1VtY@=)uٺۈQ'yY+Xy+F\^ac|u<\>|c%:ܩu,jIܢgscc̷S\;̺F8k:ɒ\qb{?sFg}LK^Td<ʬɃyO::Q<7 KįD\tʣ{Y<)!lǴL,1L{L̆t|le*#l庫=F^UHJ>s.b=V]C ]>+f&>(unnEL*!~ܕRn4TB™nﱣuڢN4~AxGq"겺&sl6{?i|N).ŎGn՛~`"Ҿy.gmi o-{M2ZyQzk^P.T |h=ݵ _ k_hZ^Wys~옩A3l""&$4- U(y] xX-0XC`t=G|WBW Xr<#L/{?&>;s*W>}tċ܇>K<7$iFj`xE(0 "(Q4Biيw Jgʣq$1YaKR FK'ZPɥǶP 4|c&oAX3 0ASJf yRAj%&`Hq:9'#dك;"p}. uHj}TK@?T;lB;,4SȌx$I+2IetTe[MJz8y' )XR.윁OGG>dh,ZFU}SEΦkѼl:ƬF#\WbSArδ6$\(8εw%nOB0}lL15maIZS!ڭG۳{RuuT my h;vxLW#麑*/]! [_5%nqܫyahq겜5,u-_MpAP eqޮr+_FaIF5sGXjѹln dS!v!uʀkd` `kYΐd< ո_;m-{6ֲ ~LJ!~R(&l-=%qʋ-X]È0Ȝ3giVٌHx5a;Az~UϠSh!EFu+cV{r*^"ePqU~\]i}|6ǚwho=3 l;0b*k|d+{EsnhNG*}m,Ӆp<NbXIM 17fw˒|bxR-|׼2E-plj5hml`_qtҀxƭ.lM䫷 M{pr[Dorh (:f[snk-s@8:>͛+ LlMᭊvzKtzqu+q^޾qqRB4!a`ےD>?D*=9~b'V>A D<` w2>31w!ޯ0%OkZ&eG_B_ Lrw?0+>#>,26s#+!2$L<ۻ#{<ۼ;K?디;N 66hI++81#,\BA;&<ė>v1)AfB$=bE"'d!j+?|l8H5Lj3X=A0i1,,*@@(3C5I)_B< *,.B8s`(3|"FcsC8|CCV6S>\2P9845 [734=%DgL'g L4MъO4'c<" %#Tl .?$;X:JYZܶ ;F= @?$Dn1duG7FhćPG *F:DBƣH5Qrsl6C2I(W6yE9ZGr$aT+4<;HHԐj1Pپm| E[?88J[I9ɦ\CEH ê=d:= A JADd~1#5lȪLJL̦3kH! K>N d$3aGDŽK KϳKK\0/c=E `LsLE"TvdfLL J̫D Tm< 5*NTtl4MHwDA4?t{ qGG1JlpyO|ʬ|ŠL(#-7LHQqC<4V\F͙͛A}%p31 ĩa.XODDPVTƻaƃpPmRÐP $;JPn " Q!G4tA&+%a [S=EBU,4dS7]9;ԝ%DDQEDҷlлcTc}뼚ҊLmD$+J LSp;4(StTKIK]ՌSxՒȡNmաX1PtSVD}§V=L>] d@).,bR"~FGfJQلK* bOv-f1CfR^f~f,Z 0WXvd3Fm [K] ΢ ff,\_h")؃'؃@>=Ȃ!E6ȟSi4cr\w ]Lgu hRhz{\ ik~^֑́1[F_VhaVa,v xi+j+cCV*mM..c|Ȟd .h+߽u8m jgFe~OQ[ c~l6Tʶ<5e^~@/Kj> qbܲ o5g&hooh c}&x_l]`&oehf 퇮cԶh+ lhوno게kJE8N^pj qp%%G>._;`v ^1&Vmxvfhv>&i /E08ɖ8ޮ:rEpfr9n syndl̓,-J1`Ft3gTg6ǵ7h&dC0M5h=sosR8tTkG?[vNi \OeΑV sNoݝ 1;QV_WX";#Ǝ5%m 6B'fn]hun.zp+W_jp+aNM07aw6w4(uwsP{blS_cJ&y#ov=ׅWwiggO, ++xJxQ9y/y'XLyˌU{r/q^Aނ7? '$H/mhz zz}}_8Ow%{_JOoow*0X نvU!YRv;B0gߤKL6}v> N#%O}˯H~ ]?XLүZGj?oJ@śj+}KЧ}?]S CrpB+K0XD°)O/Ѡ-?q&͚6o̩s'Ϟ> *tN:zl(ӦN~&UҙI=Aݩp`ŁrN*0%2i֤!cSl3 Fؚ #FĹnEu5\yP!a ]ijd] Bvhʖ=ᚪy3Ξ?-z4ҦOuNtBdЦ[kj}]!^/n#R JS &0}/kjY1W#"14N/cSds\+)`L0"G^F bz@<Bx #Q#BːPm&&n.tXE &.ְ{9X>#|`O~LC(d iEptxȍꌵLccX6i>lJ#3Y?V&q 5%zS.X> Va%IG,'Mwl6)%Dtz">Uy3Bke^LN5U=NzKJZ3ҞZ$Szt+oW$5ywR B^ ҘRPW ;4tY1/S$,hLzo>u| Mڕw G*1vaaحj]n{6 -]YEUF&sD Po7T8E\(+-]6;l@_L.aO\jX\h\ݩ:%mY`f޲"c6e]'R"t4iq^ĮV-獘f63yr,7ToڠαIZ+`Fyr\g+[&_ `N,{A<( Up`B SքX|9IJZ`j]Ş] rџ ȸߓtFz!$y99es (>IҙUbMe|y]vFZ 19]ΟJ%` !c1N:(a)#* ZөG1}mtm Ζ!ȅ"{u ]t+[ Ĥ!"XE+_#Rb52K$5DF~On]H((bY] 4_[-֢b8/M9bT[TD:!+*4" iEz 6"FF%[f7 8]ϛm`ҐQ;@$AF ,][ ccCs0s1㔍Q4.{!Gjh$neGN yh7B%&J=%#~" c$؁]NaO??NtbPeWM08eέ]3eD&ZWjwt$n&Cp>MEQ%d%1n[ $Dp"DcM^N~N%& $^bc$ATmD4^&HfggSt&fAfSthcj~OJZ&2\v @"Hv# bo-gg]ց@bns6(t XTp^gdN`yPny7{ZJXlʦ}~~v",J$_`pp&(qr"h 6焊 P]l(-g~ˏiv'E߉)Qh(9_-#>GWȧƜN}(Qz̥}a]䐲&nN Ii"1]j}pz:e}gM)ifD8 | S(i:)X%^=):.gEZ\`.ڐtn*uv\;*" ^~DJaz ج*MЪꆢtʥ+k _# ɖ" w t+NБkǖ+F' cŻURpi(]zT,2ia5lQ>䄾lXh8i뗂i$nj,rjA,YB@ʗ:Me:|,)E,l)ۉm/%2o-tBZ,Tv^mJnז׎&&%Z`ܨm*ĭ]fD!fRlvޮ^PY{\>!eVl&zjbmVJb冧GYhq9_.D M)ʮn6=:),`ZrKf,r>.F.vG&훮Ne66+nN-|j$J-~"/ # P[b BUM/mp/f+&:,goF̾vpzޯjA kלoςpgBEۼom,Ac>qZP{gf 1x1ED.l(|Vl{p)onϯ/qcc"'~ *>h$p/kfmcrM'\"#D:A Yw_L>b$S}qpǯur~2:@$"1qf+1Ώ3bVHADHdq2Fr4F1͞r㰜p02/35sn;׳MdGpPvmKu1fKrg{q\qwiSr?sjOjko'6\sEmApK[}j+66G7H12^3Xhc wj7IpMtS]utk7Dw7o3āF3Ejo2k+q[3梆7Jec^fc䀷FD@Dy7x?Q;6ttkHT4vsxfow8xđi7*'8}ܸ}rnnys3uy'LQJӄ Vy0__T U-[$8i6w`O 7\ᶇyo9)y,::auP3?7H3_8Res WD8vy_~yıY?4` ZQɶ4ωT~;2Mzx E9'xHSF/;y;;EqND"_:eUgUKL:{ [<梬I_k{Sckcc O&< ;6G[Hrm0`O\+au2YxAfnaKWz'h<Sp`A V  VXbŊx\J-xD-$J*-RO <30$̈=5z/:t!u)mSVzkV[vlXWqA:MIu2BYSf ;\-AmٞreE v{WfΝ=tQJwthѣI6}ujFkulٳS[-)mb+b[4hҠ AeIi&n!`А /ęOӁnR:~|ZQi*7*0$"Nl CLɿ /*H4;3L<U\EZeq4ۄʍF,H. (200"s@.*| CK ؃<%5(?OkK޳2dKfp.$%kG ,j%N2K;OQ?H%R^,J5FFTG2CDɺ$Mɖ,hV^Ǐ \ i"b1G $_DU5" !r1 dW[,F'j)1D؏taP"%dVHKHǨdR͖-\O5rMmt|7y٬xΎNSūGz I6\#Pޫ靌 Qh1Z"jG<';)#I~zdn~e3 \MGirhl:Qm`[Izɡ %Zp\+cKιyWg]ϷsBui7 :-z\AyOdl=ZG&CE޻t- *-jz򲬈$wJyPPGѢVdyMU7=9~wgZw?(/G&|(v anm>59$_B\w>;dd/µ|.sآsqzy?iFI.{&\N6̃&ol f=;i~Kj 3Cmq{4hSޱS=mg'Mtfkk u5Ͻuwio@ﵯQ/rxC%ġX\Ktn_+[D6`KO=Dk͗r]/i ͳew{"|+Ԧ.hn^OB8o}ď./"oTLVPkw*ƭ,$N&U/O!boIPJjPd:r,D%t"d&* eB\Gb e Z<ʃ"O +Kl+Wx q 5Ү A ?oN²Px<3df",6 P5 }mebjCPQ0 24N3.BBSq F@S@W @i2VgIDrB[t\S3TCs(;/27'3)g"4PHYTbL=cFFUFM-D HBp{5/56471ϐ!=JsЯ>SU?/Q5bL-LS`.MYxz%uBO|*>[ Zwn"Z"#WwW%T܌os<۩eQ"2q]ܻ÷5"sO"L\ėoe%Z3bp/|Ɲ6m#\ǜ%F_7Ŷ֜u~x>jK>^葾f^ߺꭾﰞ~E׾j@^WC^4F^W 7߼'O/_$_;=#C_O_MWY8cGog_O{___ǟ_ןh)_ H*\ȰÇ#JHŋ3jȱǏ CIɓ(bX! !,@!u22w[x^$u嫭xuϿvwuwvwvbuvutꌳwwzxvxkwwvtvxھwwuwvw|wv}%xvvv~vx鏹wxu$xuvwwvy~~ ꇶvxu謴wuPP.EFLwxvvawx`v..8ʹjwwwxvw^ȵwwww~w}vwwxw,|v:;EwufvJJHpndQ: D@bZM>ȱ#D.R#˗0aѣ   J4$ tV$Г'PrAJ@ ӞF:PE4Tثhh}!P^VJ UsP*f`AK8u 8XbL@M㡒<@%M܌h0R Z bY**Bװa&TM*p-f瀋0 >h3f*H Ќ"3uH "(}tr,߅TqZPY 0`w1U[G&T><' #A]PfDP%0G _4@"Wc@U RnGPZ|⣏h97>;;>===>A5=D*:H7L4K6A5< 32*,$()'('%%!" *<C;3,! )BFK\ cdf#p-}3;AF}KtLsLrKrMq\jce(deBhi^pnmsqpsrkuvWv}=t(vvvvvsnjhge d c dmvvvwwvx,6c|e`cl{ýǰoZF4-~~~~~~~ ~ ~~ { u p n n ooplfZ RPJHINONH*\ȰÇ#JHŋnbő CIɓ(S\ɲ˗0cʜI͛8onRVg39 Jѣ#e)ҧPJJjPN<Ȫׯ`Ê9k}MǪ]˶۷9mݻxS L$Ҷ^̸cld˘3G5P iM4Qf4-ɴװcC4D&dwd{=BВMqkCbV篹@xkسk{5mO>/j> _ϾIG"4j^L_GT!Z&S1 4F#AdxfaFt8u($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*oNO舃Nꪋ0" E#έ$Ϋզƨ\JT>K[ЮF+QlIl0,{QAkޚT#UAҰn[O(5[PBR'!ɫ@˔ #εBgzKoDBQ0,>ݨH'MP"L@$-P-ZP{+~d PqLA}#wq?E R~lug;&3\_G >p"«8j$x2a7B  2d|% 8{$3QH0Up %Vkdc7F䡇&l 'zp`VC!dēm"!e#Uhjuea AƂ,jl';_\I<@CW7r%Nyg e( 1d,(C(0#Q2QE @%'bI>^.=IL}I)bQ҉DDZ |@(,(EA\s6+G_da^Y1cb!$ 53bM=Xl/$Sˇ>!KL =";yb 1В'KRP~~0oU'CG&qVt!DpiLS`#H +$)Ji$']Ӿљ jCz9|M:j{?hu'%( VUCNз PZ{;"p&HN)@Y߸Ye=%ó5lQTP!H6pL:ۙgv5Rd' ':; X@aq+q* rA(1 7N{᳟Kt3U(&rDb]_vJxV- ґ.g,&/KhN3&p<`N5>ZBIHU{cDiTx+~,ZXKFK T4B0~NxDPg+(]H@ԟҿ !n \Fp7ukڛ!&Bc =b=Їn7 fIā/fb턬Q ?\ֶb&Q[.'m󠣂9' FGIG'* X6І *e0ϖ]ur4k9OѐS!O="qC>2HgO5w9RQGÎh#JLtCjj]'IM>i6̵xOӗ>Ddt da!$A ??G|-2FS(tGV} 8rKyUS*4}a%ehkRiw~gz܀s6c;{9Fz"74H{(\A>t] %XX/GU2h"~Z a XZ@ׅ  bxgzZ~#8 Z 8tXvxxxX8!D6 х9Vfx؊Zp8h؎g '+wxz]8y$v Gx&.&.PݷǏYh 2y6`k~h x"/"S*YXy$ nr>5>ΈGU* Si7"P Q o F FIДPszFيFFIQٔdYfyhjQ hN Ax 1a#Hj2vt:S<}PK=PF єalMyZٔu~ `X\Y ^Y `{mpr O$ɐ aIl0v(4".IU/8))># )Yi1;i riXx@5>I@ ypٟIZj@ Ab|f%/֗`q)3A)"y&z(*,ڟ @hn2Dz[,aJ@c+ 8*hm5**`aָ(U9uk+I{ q:K4+UêEk3Z?*x[kK.0#mPHÒ0e#}9 Qj?<֣IIRh〴۱R>kFL=~y٭e<-j}^ӁL7r9{ޭnTRӵ΀+U=2!T䏎ݏ ݳ ۪n)2DЎu{3yEQk럮&Sr" sn캒fۙޣ|nОEӸ>1s^݂ ߾j}?N*e3.%Iս\}~8nH =GɈ5Z n}H=QHޱyT'c]}NLF[/UE;mg*en~/q;N9a A||M?H}Zjӆ>?zlpMxU?I6E|L>qCҮ>vjFwS`9~_ ߗOﮉqL׷!KnLhB:XN?Ai"PB 4"D( |(È=.ÇC~DM"F4Xra ;ęSN=}TPEETRM>UT_1š_ $됃 dC-E59@Fqd[ν qc`?Ydʕ-_ƜY^њj脞uS1oM a$!Ҭ5O˝-cōG\r͝?&NH: ׳'N\6c|2{oMg^|ġ.|0@$@̬*.ኺʳ'HI1=r&P+q^/3Fo1Gw䱲CV(☂2 $ "hE6>Z*L!qL<1,k(+q1{dM7߄3N973mAFT鐬DA08szCď^',P. ̙f4iSO?5TQG1-JQJ%.:sQOR(ы;,UԕTa%XcT /5>DĊċ0CZ|Vpu҉zUu&`%\sE7] +@#kvՏtЏPZm{/Jh)^q9U`F8aQ 7ל{ͷ!tі<1]`"o&dOF);zв 9`5ì j2FߝeDڅbtS&h>F\z>.x7bYg&lE*{9'w(7Lul lH,{%$iIy._o iW^e|a|yԥ/'Tvoxۖvq/&6ͬq4kz+DOL d DB{=)3F[Pj{;XN%?u/*Ɖ))4IFl=CөB'w5|eogK6%% 3mu^!|Voz'\4˛vr{">BShgwҲ"|TVg~Ov`'NC1qɸ2"Cϲ+!4vA eɾ;o9Kc D^#+s@Xt>@ꊖ@н:; `oTK|'2=FB0SAjU@=(O+ [1BNr+%LA0((SCxˉ"3h ,{ |+<+B+>2988D8:D>RD7DOkĶG<6k*c>4Y\.D{D\K43kA0S :Z1{G|:cgl[ܽ+Ş?T1J>כ)S:hTGrEŅyl? So̍p<9$BW<lu4HrjGBLjG$%AK}DEqC?>s<ȏ<(;0H|W K URӤL$Uk3@O(@7Sg\,u-Ni RRH\0z*4e92Fя KS{A<,. T-?#ՆtFu9;CZ xӤT#OQP%?K<.uWeVIK(5 ңՉA<'Q!4R*@@SUlO${fuWyּ{zչ2]&_>\r-VBXI cM|ׇ5Dۓ" uآ(k5=+_UDzF :K!dVٳjH-82NWn--L-X={ Y٧ÒH`"I]-Q_ `.m^T1&%T 2=8bl䅔@bUmF %?}:UT*Ct>]{"RU[ M4>}cB>%bI , D[&=A u5d[\kFb$IkB_Y.H-\f[y+%i{-uEcm:^eۥ.*Xxވ@W{.^nn6?XxAC,f)>Md,-)aV%kU}މ4zqxzֻ[8>g~`WKQ.hm%838*T8PvsNi'ʥTeiݰd^f9 . `V`f>`&S gR1 ei(k.g>em ծxø݌"pfx) c<}UE q&W]hHX5h;Fi;/s1nC}g@ 8:6%s$J_X֍fݶjFVJrKt& <^8vruەrslgu*fM[Uo_?4Cf`Iak'd ~EEuy~t<_n`!nS  /Qsql?]ǻ\Q_zt;Ach::nfw:*+\)pfW_))x} wcx;7xve$yK?TȦXagwE >pYSV5rw:/xԞyul`ut?yUA)7_^|z g7m{&hӑ>{nݢwhpywwtAڔ0kEg8nT|_ Z=YyrTߚcF~}_4z ZZs՟y7n~tU{_P6of扴g! xS~'owwU,(@0RHM"q8"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬifLU4ZF!ў&&jXŢxs`  PaolQ/:ȵ׶'ΟZk-T#Aq.l0Ċ3n1Ȓov9HdM|z1:qUV/4|עf{Q5Xl_n"&*wʗ3o9ҧ֙Q)#7e绷MomuukR6_/"Oو3~: 8 x UQݷp}UyXk}&i}=EV=~Yi%8#5x#9؂\ԈUif7`W9XCo6Yeh8&ey&i9WEHGBLv zQ lr#'NUk*(:(ʵ']on`qUZڑ]TB):+&VYRfA^$٩S vj:-Z{-J*fe[ +E#&q,f;/{/-mX%\ A yjM;1[|JGy1RJMC1:kjPSM fþ9A0h_b3=|/E9A`A,ڬd'P> h-YD:<6eugnbL]Сb@|Blx#pvOvʹ_(ٍ;8ZBr`SeBvƤYu,"^ uìa,G>;.OOݟG[ .V<-~A\А~=kRe%qFݭwkZ| F__;_jU}?Jb'#ɐ"ds#WiՌDfq(;(d&qd#$ 汓$p*XP̐>z$"h5 Lc[&| #XƁ<' Hz"6G.۹.nS SuҠ;RF'Hh&6e n&.%NMep;Mӝ(FiDG"*2\^FY|xa!4;VYpB nUD26=*RJkOHQumq? &0e$H)/A_P*vCI%kcG5b9W棥[B s^PZ B-NQrV#=JLe#&I O; CH&.G>uSE,prSt Vq;>WvӜuY[jU{jW5}}oKVᒷI{P~~Nq${!d6/?13AY˘mt|;Nm~g 2yr0C31d\*u@Yb\࣐Qu I1qRX Ѭ ŭcw79v.x ^V9 9Jh4>m2Ĉrͧ2=LK) X`ƔdrqUs_G^ْ{Y;s|4EQiIaCW@p|dM7]cX~$KYV:I>CգK@TП> nJ?F ^/zB NIOvHd,#4cd!d!OFFcV|`(ecF4/JZXU&7*&n Q eaM-JUAc%`Y[=V 6_xpW%^HnDW#e&fJ&g@@٤7dG呈eckb@efmKA' FD7hik"ej&e^s%G,&mF'y Lu^'vfvn'wvw~'xx'yy'vJzuD *{uu-Y6C- NS{DF Җҍ44'^rFUfI h(}wf}&}N(U(2A(^>8(Ax'hH+hb1A)+(t^'7Z'֔hf)29dK$C'P)l@D˜KivĔ Ɨb)%i$(_)pBj)qY(I$C2)!LjUhGȨz')~ė fNrrZj*۹' j&R'6Kq™ėOiZMW,FN,V^,fn,v6j=J8.,,+eɨ7mlF.}*h(Tkjii=i2Z-&.-6>-FN-V-ӎD~p⡔~9*j ƚJmGmjBA,)mTZ--bmh-kĕ!鰂>)*,VizDT .붮.|,*iԍjju-+XN+rZЍ,-3;@4t+B7":4*3DW4BZt$SFw4c4UH4II4JJ4KK4LǴL4M״M4NN4OO4H 5QQ5R'R/5S7S?5TGTO5UWU_5VgVo5WwW5QYYY5ZZ5[[5\ǵ\5]׵]5^^5__5`XYua'b/6c7c?6dGb `XYfgfo6gwg6hh6ii6jj6kk6lǶllue[%d&6oo6oӶp7qq7r'r6%4s?7tC7gG7uStW7v77gmYxx7xy7zz7{{7|Ƿ|7}׷}7~~77%6%LCywj7wwY+<+6W_8go8w8888S*x4xC%0xÂos9'/97?9GO9W_9go9w9S+hyÂ4gyyYBs&y'9繞w69::3y/:_yyyYB,dz,9'wz{::ok:::Ǻ:׺:纮::%­x,{#OW k:'9(d{'s{'x·';;{+{S4 ;/(#{BN{O:'|B+*B'*,((B)\'ogo>w>臾>=DB{{>7hC(B2&>>>跽, ?_~A?Bh~ >^w(|B(6T4xz(+~(ܾ刺?2?(t=B?/?@8`͢k L!USQOE1if SӪVKֽwo߿>xqђfOl9!ΈMq?^8%_)Msf4K_GKS P;9 >餓DNl*MA QI,QLQE:i1:Ap@;Q>L[Q!,#O4HQ@JA&*BdA/ S1@dMΡ$S=?1ad~W Kݿ~ŭ|^HγZhzzG}\|=Ɗ"ᮔ! !2LT@"̬Mn"O*8P_6A!۬amA@Hud*f#;P6%JZaf$U$Ds1_"a+VQicI3] >DŽ,8^-dIjQ\& .`fK bvfesg/aPP@FvhuAR+vLSPʜv39bpK k%lguDH nˌcϓ)5pfpi7v3Vt-qU>m#u/*rGus+nQnuoiVFeouZW^7cPtwrru(ίs}d$7GtQ7wy7`la6m#to{m6HVwQ}au.(ʰ߄(m]οַ}!W$S}xWjM&s`nb;Vaյ=xw#i &LO#| 8샿JJ OXRb~?Wm8 &/8tRs}m|8B9y 9eB~~gs. 82Sm7+VaXY1 ,]#i.ь؈y"? ؅7L7]yy&dGAC{֒3oJb8U̘Yyٙ x*™w ߘ )Y4۸uX}o8Eze7&G|7큆=ɕ|̜@؅zY%=CaM.x}~w9ڧ1:ͥЮLOBwC"2w3F0y ڢʎZkڭM㺮ߚjWb `:.o8> {;N4=/:4ZB+;׺Ȥ@{&"N[%%W;%kW7x<^{C.k2> ;Wٳ;U{{"0!` ({ǻe"Pa%RDD@DqV1S%йw#>Eb{(V)θ=z |ļGx!!W0;$$:%`V;[%:wP`!YC>!_4nz4{ '~N.#A˱<-p% ,]/2K"$HTIf/-b<%e/ޗ:hCn^/n~ü- 4}%^N0"F>%">˞Ðg ؛E‘lm!z=wyR- '_9y¼[#$"֟쫠Ib=eA]ce1 ƒ~'.8 )V葢CU>P'.‚"IzI -n\paΘ<{ 4СD=4ҥL:} 5ԩT^HJ:Uz:FSdjz3ǵU"-TfSO{n !74*[U՟ lA;)DYh@>tб@ ?|ygt*H)VX'ݼ{ <ċ'^׏) }l AdG8ͭ{7޾z /{TfEq]+t,rmiI$ P>~ ƓiAQF& myna~b"1kբ&DG A 2y#F(չ\E@ 4vׁ^LIŞ{lquV@!aIFY"nH_ AYg@HfH1Ee&ҕi9bzg~ QecG6a.F/ dvcwki^DvW(#.)>}# +# נ8^8) l|%V ZnK Κl{`OHsZHhOm~ n ʭ7G" ަ2Ӷ[PH +A+it/ [Vj? qO5\qyyZqST ƛaRtb /nLp=Q[aGqFtJ/4q F/ms6$CWCLb;/lZMe7vn wr並 l5S&Cыl"q,fLV%όMy_y=qu3:CߵaMr-DY+vz보k{|$wG-h.E󙕪z!.|柏~lU!⑕numS&}w,#ӮTq|2ʆB@)p l.=Sԯy߱&X)ў@no^aj{@)ԖOL'T< 'mD3L0/"uX#x!CP`LC":`1uG"qleT@&2-Ɍ' 2'dP@)Hp0C0Y`?: &'=&$M wA~QLe\t3]h;^|z9y ! a" b3U6h LդjN5x@1$1/ kP0o yBkR Y]HDd^RwkMlT[eiX!0݆g? Zz(:Z<6cJ@\Ϗ蒧Aaլ~ =aWV+(qlEAe]]=@ ^C!pA&ZJgSKR!6?m[6!?-Pz#o&N$s%ْ|Vncv/JUh^Ў tj9E)hm 2)CU *8r1K@0Zi y3]𭆺Ͱ]Hwx;x>N&#n| | O gS_ozLm&+i6˜ҮҊtX TZFQ`- OۼȅSʨs|_Y8},y8 +Ġf /Ԡ W'D9L6 n Uh3寄yn5ځ̈UyM"Sھ*á=  Mh2%oDҍŶ.j8︸ l.WnP:S?tg 7H qGog$i7DkS/y1mc{|\Sa{'Ou;ŹsGiLy(E d)CTт"G^KYXSB `e w}A3У-͏t'QB>)Eя>UUkx:AZLDyXԯnJt"܀eD#%G1'4ũ͜ށK j 6bv񞾢鏲heix(TnPy^}wdx} A(*R-}RZQ)Gp))Es~1~ kFo-fgV{K%y s/p7xtdjT~mU%((WGQ'!g 5!zs{"h7`#MCx:Q%uϥmJB(ENȅRHuXK}rot TwTiKs!+`؃/eyŇI=MmP$B0〆h(gWA!_2X?8|"!tL7'9':u@@8(gwBP2h &wJ4a! q(@(l5_cŊ LDN7'ph7Tȏ98!=ⴌ˶@8PFXuv2}G$)hl@e; Y["CFsE@9Q _4lEWN+ш:a.hL6@ Ui uU[*HLjg&VbBi8lM[ rqRɆWy C1q[BLi7֗cy@UubrtqǗ2Q78%t;M[;5T)3vPs{u!cheBqkA8x=^m3J}2Á1AM@TMlٖśN$TiƉGTO$OYOT>9] 1VQ+:xNli i\V98i/BsYX N3US#uRqp)'`w S# yGLg`OfS_L6?IeJr2:S5FWZC]Up_-9XHTBt%ScBY`FJ*ֲIQ >A :CYa`^jDbE㪮-9J63[enJffhvs)AsPstsj_}ɟyw mBJ$Lw{kLꮞiK z$g'Kjojgk*AR4;sgLl O7B9VstZq񠴻Ǵȧ2f5zU3nvn%'뵟o+6oGbo+fk0o2*8jCDÒWeYi٧[J;0A;hr"GZk ;]ۯ+zQ/w^1ɻmۅrhwoX:8Xj0 GiR ˾uZ`6Jk$j~m3Qa٠&}Q㉱wQz۾,7zzzz緹iz b!Azqi EH;T,ļ;&(e{R~w#w>+vjMÇG5ljXIu:o\9R(q+(ҁb))iRŝrnK"k],`WbjXI*ӴÿeS7lp G#FZW`1i 3y!:`jƬʹ6ʩ1~"*wןBI ت3[bIM*UIjR<ќޫ} YGNw@_ IȄ_yDњAV/]0/LQԜ:8Yr߬0Lh2=na2nըͧ;l:cOk3ӥ!َLXkl AŦ0VALpܱ%G܌ ޣh0[jdWٗ]h]5ft,-&, ~ }7 ZHq* A%AAM`JD%޳-A൧ή >u1c*HK}K"5&>ͣ+GOΝ2'=nT}Gΰv\gQ~!BY=튷k_nrш{*>_$-ްy r N]ۘEy|NL啝^v~͋.}6*ӱn(ؚ'TfL:]>޺CN:"}u&_Y-ymx%,qf "Ύ<ײAۢ>dfuN\>xar9;$H^  u>>pICbD7.]tZ~! %n~!I=>XNb}ua3tlhnnC]^H.",Q@Տ67?{ARIv-"D[ꀹ+V/Aʳ.PRsWt@X $}ϫ%MO  B9tgL~Oׅ8')U0#&v}n+OYUА2Zu_>/g4+&6iDzoojMͣI{Y@/]}E_dΆOcJRվ1/d3_`& .dP  @"=MnGqU:&h#d(NB0?~\hr8>O7%rτ+9'RQNZUYnWaŎ%[Yiծ=#qe0aCCbhBd:͎(U>ϙ>̹*c 0*Jқ"17e[iԩUfkرeFm!욡k20'oTBǙF~:q>fJwŏ'_y+W.!|+R u9WrzCLht)q)mpC;CCq5ʷ. 0>f_暈+A0|p 7<ޛTiYA3Z839;::wnneY>tSW}uܰr;k2Ӆ֖M_}x7I,juD|S۝Us4?S;|gKKW}\s]zk\z=1AiO)ko |$` lԂ=n?<Ǧw\ߺE`ѩ?/iBưP 8bP q|4: m`Sd`f k.[! C,fQ;_x7LP_f^'A {I*q8-"E*Q+؊m$-Ъ & 49>3+ o _g?O.- J4dK]BȂ$d'I*;zN+$|j·$iIM3ȅHIoէ[/; >HрY+Lޓ$!HOzT&5+d[%t )Cc̔cD1Qi̋->-=KJ zJek[= %f鏪2&Ebadt#kDVFV eCJPЕVd:z`Ti$S6u.Jٷ. ̬B`Zf4a BlFѭy2dBt C X.r@/Î ! p)D4;R$+ 7ԉ8=J,d[CMd(zA\Iu=HO53F$<: yxL0尔McI5-5I& Aɽ ʵ%[8X ld|s`Ɍ!2| iFJl14CI8ˑʝY\ǸlL[G6ĝd^J TLh,lHVKZK,Mu5,KHhCH*LXJđ0)P3iR7]=rI O?̔ ^=% :adS^ `x$d d7f jc`bgSeA`2$NH`&LFj9ΖP_]D%CfPKecwCq ]fvf%*AUXg8eŲdx<;\n+prKB~ܧǐn 7nr4 fS6p3;2o#QO/mm=B>"l*\_'sI牭I{_T\}y#P}KD}pw]7~bh #O`Sfj?G-ڞ͟~hd߾EWe`o"Lpᇅ d"q/b8M"FXQ#ɒV41:q)s&͚6o̩s'Ϟ> *t(ѢF"Mt)ә] 9xH3q4HQC lqă22Y' L18Yͫw/߾~,x0a_QÉ:ءU⊐Y)Aq7-z5֮_Î-{6D1bȓ??J4ۑcϮ};޿>@uEYxxÃff2IW'n<Ҙ}X" 6#-f^걗sxPy75K.eTqdj2آ/3XaZĢQ@WFŗ YOBSxz]cF#zsO%O<0ŞKqZ 5Ios2|QuqUA=DyЅС\@A#]٨B)ɷG|qVT(ΎFrYGZDr#&]][#ie7KmJ9:ZbMG;a^W=UXTEkJ*Izn֡_Y񷭿+OfFFoKD>i@uRU$# 4 f0B:*:1ɧhuCM+U|nQ[tM[[suaʲtYd| w㝷ׁ̂YvOo+_HʮY]c.T[U隍P.Gk{<%Qj7Ny^ !QzáP>$N+N<ulS_Bg:ȀjEBok;e'܅NSǞ_9gd_ȼb{HH=q G6,2i eZ-0@*hVH0 hI$ n!U {ia\U8̡B< B1RѾh p)lY6fDcyS# ,'¢yR&f#!rjD`U:LFv$! <>$4쐣Nh8G4$%+iI R!~$JD%)Il ᣻%-[Q[vX'2k8$&1\c\&3JLE4kb3&7YA e63s3$';N3|'=i(y4%A JNl(CP*h) Nl }(G;џDԢ؄(f9 NG[җj$D'F Q⢠XiA ӟե*Q: QtEMG X5> *U*Шզ+@1RbS*Yΰ# EQK P@5CYjW\"y'P"z,a K׻"6$,F91B68b+kY267,QB,iK+ED)xϺikk[-ou=&<6_nw Q6 .+^ O"ǥr]5W]*( X]& ["o bԩ%zƗ`ǢE,N Q 85"]c8%3\ZXx0,4l^ T%F1k<+XlQ1uMh8 2 jFƦ4`jZ2~csµfL.932(uklWri\7WCt3!,4.22$BCMABL KLW,,8^prwx}-.8'-=1i..:V$Ea((4f01;y @A xÅX̸bŎ#D@re2k֌f 9q (8  !,%422BCM$ KLW,,8((4CDN..:33?ablHA\Ȱ!:p3xQF;~Iȉ!<0J,7l2&ƒj|Θ. 2s`H*(%Z'"M`ժX W$X PA .X˷߿ LÈ  x1cC(c^Ƽk̞ nڙsi>41/?v lɵQ|jܽmW9r,!,(H22ABL$ JKV,,8((4BCM곴..:33?`akH\Ȱ!:Hq@32xQƏ9v RHMDPJ ]:3f8PY˛x (C4pSSIr4PB @@ h} d @@@Xk‚  LÈ+^̸ǐ#KL˘3k̹曈qtaҥQVmZԫ fZlS[ݺ3ݓƒOJrޢA?[: #g!,9 22ABL>?I BCM)( $@BxH#J8Ѐjp  AȁXʜM.Edi J YtD<(GK9D!QXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞ @oͭ{,a*|xƷ"Ou9sΟS.]!ѱ{ڼ {w!, I:22BCM$ rrrKLW,,8((4CDN..:33?abl @*\ȰA:HbE"Zȑ#ƌ;#H(I<ŕ,]d3̛kBЈ'.9( C4 2M 8jU.?0@XZ`ASa[iS0  *ř@ {oFp!CÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνÞOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,Z06$#C37.($0<6J.icO2BYe]!,0i22TTT444---P*\ȰCJHqaĊ3*#EC6)$B&S"L2%_ )sf6C&ϊ~V@B*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿;`u0a#FXa>+922BCM$ KLW,,8((4,-7CDN..: 33?abl;T@*<B#B$`3Rx1G9~i0H#MDE-Jx 3Jh)ϞO&$3AP*ET@\p0 @huW 6X8@ n!.` CޅÈ+^̸ǐ#KL˘Yx3gƞ?+.@ЛNx5kî_--]oV[t޳c=3ԆK,mz $!,1 22>?I#KLW* ((4BCM$ L$@, ..:*k 33?#,?I9:Dabl  KS@2(!Pp@@P4ht8$ő$M6Dŗ t⇙a¬N h䀣B *C&(>`Å$x0`C( " P`w[}<aa/7LPǐ7Ly2eȖ+;,yc= .Ϧ1!Q,&%"CDTO`YXdIn,pt.xCOT[nuwxxwx|-KPRUbptqosw}艿xŖaڛUݜSؗNϏCŃ4z"y xvrg]XTRQM=t&k#g/]DH&2121212222222222``ܠܜؘŁyy{ĉοH(\ȰÇ#JHŋ3jȱǏ CA(S\20cʜI͛8s4ٲO: JѣHy\%ҧPJJRXO:ʵׯ`^tkسhӪ][,YlʝK*q2LwVwb.=LÉQ*wiɗC 63ěM߼\k%Mmtzq-'ɮȓ+h+㋒p⒍/ν{Żyww'ξ}止Ƞ;7iCo$<}2G$HH=6-"ȷ u >c~̻_ z;O{Kxq`3 B b[݇nn=4 Ktsǀ,1¼0aZa`t|`X'm(?`$@w4lsD'b^X@,Y "+6F 1r1 ȹ}>>>6Qg8p} uY.jdz=z P dX8PLL3, sbJMR Dx@>ZE ցvK<^ >4JݾQ4CҦ k@ wN0x;7j.x+h?El=Gڊr,mǸopNwz/$I? Lh?fi^-;MSZH#ԓz?<4)м8T9ռTp Tz`H135hE+*U>rMbEW8y,`aeW,*qX.<3Y~#x,P|}khg G-mwS-oNT%r{;Z"]tqi\Wn<\^Wau[A֬c~[^G6׌!!awa$ 1h7 ƛ_yy!X^̼ '8wm&ozCإF`C8|mĉ vbJĆzC<"'>cC\7CE![~qJ:AeM{l/b!6i6pL:xγ>y͚( `Oמu8(ٹ{ncyЋ&;/Kg:-^O;񐏼'Oya#8Q{w@V2 .D7ҍM-758`sw'ЯIoz)c<>SF;O{@QͿ~+o+F-W0wփ8zC{}Px7j~GXx|zB%87z'w-Ei`imX5{$:@B9DYFyHJF, , a>fFpqaST]d gy\i>@ א r9ؐ =~9A)ԠRNp xFD]ْTɒ`Yz kՙfAe |H s Yyٛٛ  m ``gsa 0Ɏ @ \\i;Y ؇|Xx 0t П:ZY Dٜ kpP*ic: <7;u? :I(xxIp{3{8`<ڣ>ZG5ɠ)zY@0Fե،]a%Tbȇ fy.j1zf@@@ڜٜ JL0 HZ*dEb[:b nz 8Zaڙn` g mzfX4(ް `jПূ:II@ @ @ Y` ZO:Z_yT%{*{(ꪩ |ꪯ*~|| KZz xp@԰ۺSX1Sڥ琮8ڪ]ڱj7 t#i4[?:i8[۩G9GYA{T:[K;˩b$ZR*|,.6r|ʗijl;ڭMux qd 9!]J:jZ[\[Wi -~|9[Kl?` *qWJ  ([hy >ۗ{듚PJTۺG{[]mzޫۻ{۾H9-Y;W2k# Q qV$ֻCE>7`QT䪀[*&K ˒껾 ,) |u46^+ r =.73:4 @:Y k 櫦~P+%P̔"$ŝ{ b[_ZV80 C7H;,$ ByM@L,皌 +PI,뚓Nlń\? %kȖ(5q3$ Yd0EsLD\,\"},,(y1s\˶|˸,r9WM˹\s7sI\L-7Céʳ+`,+<K,H+:eƬu`l õg<:Ǫ .,E$l,+\aΐ \ΌB, ʣ@cҙ<drЅΑ aE͞\Ѧ>7-R%QŃҏ| BJ-<.> Ve IXZMIԥ0".LԻR\enVpqkfxd--w X_m?h5^Foh{݋ ?-DؑXmؒ]\QfٜYٷCl]פ]}g٠Hx]۶}۸xھmֶٲ/]}ܼn Q=s=ݴ B-؝ݖܽ/ߝ޺˝M0:]}gz?}nic]/o^VdH+DB xpP.€+.bB腞0,݇H DD8~,N> E "/ h0 ^RKB^2ZKGMB~ztgϝ0\.(*/2뼎t+4r;6=o, +B/JoRo n +TomYo 2U/m _B)܂+p؟گ$-ÈTN>TN0_8_,$O /Ja/L+̴gX`1L=,xР&>HVs+~0$!:QL5ęSN=}Eh+lE:בM{H l4m<**kI͞EhVmݾRG(3ē< g _}Él1̃ O!;c\ǽ%F$72GƝ;gСEk\BEv.qя9ώ Q?,v)EanfL=<5?ϑzt[(/$K/AdA0B 'и.\6e+ɣ_ 04뗒E軒z{2Z`(DRC H?'ӏ+2+IK/3L1$ 0FGF*4џ$OFNj2ӳ6F >8Ghk:gǽ{' !

x8yN K) n(Cޒud0HHvdn$$1PJbX)D5{%R&k6LHgsQgggXsg|QlϧQN6IèG=$?L+OlBh~(e‰ 6 GE98ə֒Sj K}iϲԦ"é1sTDURI5El::6v((;XNlf5O\vmhEYf֯S_6ZѤd([= >C@ظ<͚5;\tq'LYW,[F_Q E"pG/:ď)iu7L8:f~\ӜVSUDF8CI2Y;~ 0'БwJ+ө:K`<꩐_iu"qh>vbX5?XKUo?ܞzַုRXW<:fǧA;M_|Z׼^mI*~^( OT+gNzBռǺ=QhLSo?<2;=˯~зp10(h{\ʂjо )S nm"*q8vC9PT?cA??#ks- "\8`(R0 t'tC9BAZ$ Bp{)#T8$T¢@ރBչRNR:;<=C;@A8CN†RBB!L {h$"6[7%@< Ch2O -h8}>Z!tRPh Pד˄s)C$%ͥ( $PP/ι(R(R(2pbN˃KьTPgJ M]ف&KjПk~@25FQE-:86ݣ؁ Az rSP'`'#']c/(O؄EeMP 'PR /)j/+ Y\7SEUUQEXT)V>v&m'(D b5Vc}H;)^@HLMQԂ/|ϩBR>%`'\Ut#]-QoU?E'\U^E_ ` O`~}O)DNLGUtEkόdqt&c,Qbӡh(0,2Kh8JZtJsH8}Z2(H~h9D ͩXѮEՓS]W7]C(8aeFHۄtrL Z .5dKTK`bFM^# I>F]j.JnXodNhTF=0qAh7zI{hM E%MMvNPN˒6O">Qd;odOpd&ܑ1ܢL"NcLcPQM˜KjI @fP6$c.݄VF;VK9K:d뜠Rcϴvchj> I~žn.j;%Eb̎J˶~j.&Lm66K+~m>ڞKݶ~>yHmOFVޢQ^ӶX6[\JRn+oXeVx?$"6Nteem.B< fIȁkh1I>f#oC J8  ?& POL`G|N:ZH/7[d2$$-j(]$@`v߭l')a ( Xn9_dv@mp%(R3_૰sW6('bj m%_4&G )gt NtHGgRq]o4ʼoOZ-]}aN 5aґ"JsU%NHuUH(@7#.F8YWE%ZGViJgwPHt/rp-977˭ u $h^0IuLsU'u]ANc/D(6jkt:/1weXsʅUq&LsgDDu:B?@]s1hEv"W>hhpahAf7dՍ4EvQ6hF4ETR(04FxoGct w**PqSF*bt 7u7>`pEqvewY$rt/2o prMϔ%k2s|)>'_dzb׉pA)\w0]K *7ܜt(_Tŀ7}Ŏzd{cݡzkW fOe4i{<+\É*1'FQ (7 ? ޓ ("NTQ' 4ۑ&9C4D5dA(e:`)ɔ,rFHjG9fb0=+7:)SD!8~Vrǒڴj׶ܸrҕ-a7q(.lRTKD`x8>v̸,YNR3ТA!lxnزgӮmvIu,8BѢŘXώ݈(Qg HF s@HN*K bONar.(/ָ5lBi\Q^ GyvQhtEjf o"a!&'}&YYj1(QihV\#mc×lBEnxDБlqb\Gq2[PCVzPOXl^MQ "}t m]F`QE5Xփ5!<^#&QrE[~ I..㌝zXh\@z[1[@t)|zkUCh vD!4J/>0t:eIg;D6 @κuV%o+[DXrX0ăQКu U\fmlKꮫsn:25ܩk3#Ʌ|*(tI/n$)sA[}93v%J6a=vX2M6bšG˽.i}wZ up17{#sc݂+ߋK>9~ymS͍Cxבs>݄9iN:z>h}{:Wcꩯ^;3<;^aEw$cl^Q<[sֻ%ϳy%m ))0`pJ]Q.&.dОQ D&9&"X֧F8_8@)Q l`{7,n;\D.p>&{DM*\ 1ڋ^W0H|Aov$|Lx¹ ,!K-0H-8 4 AȘ(3aCM o! ʨ}i DA:HS#t$CEŊ$qS9FhO\J\"A kI&يeD# Lc:Fɗ $ JŸ8ؓsThlsEқ4ʂ`+J %OjΐFR@}cD!LxB#Cb,M~86XQ3l= (&V* (t@Əe\z5sdGax aBҖ!pRC(B3y.'` !ى&C\'XEpdO60$kWN@ vD)  w$}wj|&dR x?e8c+۠ѕLZ6pSCSpR(4[͉\rU"6Jll4$6^:Dɼ(p]68e֞$hbE)#O!aɹfqGl#dY1YLGBl#%2Q} 4myT9'B@Wz82K ?-~F8ǹyStHLgڜ8϶@GBM%ty[!0cUii.GAfvlNH6u AԦAuW83F.6hlۣYĊ}`w5Y)1w [!t)/(vv-iOؒj;lnE [q ܼ\8veiS8c:Y%ol?-~pG?[BU: c5/6Qcr䙳hPH&Vv\ e O3 >j{"&&G: &rm"~oWNBuΡEbZ<ɗy<%Ew^? W[c~6 Seh]*뢙< mvv:7'|W W5~'7}T_6hl RCLtDm"RSA)qHF&,y __$D$%EPM(UB|CFq%Gȕlt_6A` S %f젥t+! rŖ NBH U O 6` iِHɜQ(!hP ރ/5@MTa%R;}%@/ X JPa!a"_4 20!Ԕ&gaI !G&#n$$:=}%dd|gGV+6+¢YT+ l쟜-*"b#&c#*TR3N,:Rm yUD`R]Y^z X_:!fQ=cLB8Uc%cFSafkY$fXh%`>MhVF.|[Zm١]mޖ &c:D4 hXdY H%hT&p gB(wJDnoJ@\ źY!g&p9$>>XXH޼Ϩ'f簐gfp&`zgWݱOPH.=g~حYHmPuXhYHp٥( 1ܮuZIZoz<\\=' AX"mRݽv(~^XueHtڮU]]ѱ[u}}):eY{]S0菽i+8h<3oR3N<Õ=|BX*YW5\N蘍iśDDA(MԨN0FV PC\&A4E&@`IF\ހT 'X"ḿ`DEXH;kvU#@Pإ͘x ZZřoj@N\TZYұ:ر%eX)]PkQJn,`p@ D#} ;LWǵxDA \Uď%B|=bTWWܡixJZl>6iD"[XaKfz)\0sRʫ(Aq<͢/ma!YWX(@țx C0:B@-NUfS4B\ϩx.MYt/\*ҭ͵I+jD-R! &ɒA* J/a~R4@g4mi +[g?:p rT?&<$UB $Ll@5808Y"|]qB0SoN ĥ֭29wr[a/E'껌/2%Dn&?@B岈WFz^&@ Gϲ/]@wQ'ɏO X`@ltގ7 U^Zt0s0(5 CW[Q($u\/M\|(r A0n +'XF..BF2>="#d'F>#J`*z q+fˬ,lFd1*c#/kJK|DQA59MٳI3#Jf,ͪDͯZGRAM{T=F#0fjEJT#hld)ZH5!S >u]U b:@ 6!!`M$>`|@VF2F6aIhҕpDz%W`0M]K!^^LVPb2E %We0R*IkaX"5'65r6ZeJJ:6D5^~t#C]ݴDwJS#dxcwx7\z\R]xSbZ7|?aot}s|&}7aBv~Y};yRz/8\A87nX:$c$s!fxeR84!-&Y%Z%[eK8z8X^+tng F@ h@`Jk)7vϛk54H._Kg &Xv8&28[>G͢T!B b)Hgk 9#nP%.b R۔e8O">^Z?9:""d%Ay\w֕ok"z ήuF@ `$3x}vOqNoir6gP$-GL(Dx喝g>#Tg)xaBLGBj!sBg4cI:!ߞ pz}'Y-3y rliv];;_;"V!rE`vpE'z̳:?/0c*j[3 {|y[ '|*g\xGmhk_L.BSqz OeHOP5{* ~L!X |;SXmF itaVQ_F½} [^tj.f>-EniywX(D'E GFd}kX{'AlRpHȤpG$$Mo )A m n} ;=86'A`ľW&7E?*형^Y+h@ ,h ـ((;4DC@Q?9dI'QTeKߙ0J!@b$i3>mAEx(hT<$rjCS9Zœ#JV_1Br0 C#h0#̴g 5b外/{3*бρw|G4LjH`a4 ic9MπE!?qBrS! ? 5:$# Z%oeSCgϫ|gAt9|yÔIH#yՎDhw"CFeT$  )"1Ȇ*1D5Ej(a 2Eu>0$&(Md : ;l @-CO$t=oѺgJ Tk, PA$ BHUB2ؠ Mf -J0E@ Ĉ $UJ$hi"0K,7 pڲ -K@ s2I9"5`v4OE&/>xч!X%~ѐ)>~L7?J@QDR:5$R(GZhR (>iiz/c[w8wm阚I=o8F(|9$OS~V!ѝzا?V9P֊$6`*Yfhfpچg)fh{sa323>s58u+w8im{s 86vs zWk^n {e;ݯJZ_qQ[dmԀ@`"Rt# $ 609  棶jn!&ⵢF ``<% }=% 4(}/$ Q d PR%p"8rj1HXǷ,c#G|4!HD`RlcIKё{1IBy'1|tHPIU?ad+Hqt&qKpҐ%G܃41iL}ؒtfe95)^LP(NqSєfrJkffϯ=bsl?6ʓ{ .>)& hz{hD' /0P'MRQ: ȨUCpPKbR5ݨ-@ҟt!ݨ0QaTX]T}≛r,3*M5gHZ-9͸r`Opz"Y0a kŚV`,b>6 +<ֲg'ZVgQѮvWka Z`mYo\5k3[Ȣus]Nw,k5XChh\[lEZ9T-VըսzkO*UdNgJ_Xor{ G4Rozդ`Uߨ x+axUI`ϘTp7`ܷhqZoJ]mV28ZiMP5Bvʓ[4R4y̱2Tza&Dj6i~7(b6w'G~jTm0q̟" ℂE>~JGZҍ١1ofP"~/QDJ&hYƍQa8D}_Xzݟ@3׬b;.g,(5b`rH{}{6޻mScz7=4_&y)r?2H)=xyp'8:ͧzc\Mьm}<܇< 8/1>Ɯq;qLA"" ,\NPe o~}"No0C;>p!;L, VzZ=bo dq".7O BP|C`P, 1i i)la H@7 N LM u &3n<8 @N2C Bl@ uP~aEyh(NQӌ;6H{cPʣ oop2''Om-1QJ ʊ` :*10:Bj.'zA#,%kX2c &ȇjJ%-HRm,l80>ِ %'q% -&2A'Պ/2#ǂl1C ɺJvl˥0 0lrJeAS\:`9=,*Ж5km}6k2i--8il8SRm٬ !b*M1OJLÐsH$1J? k?kK>$"Lg{ln~,m!K'~+hci֝Up\_ήB:`s6l bmm k,,M)򶍞 !aPWp1Wu?e̮Vk?q{w Vl)`0l(j&p+'x@؋3J)EæO:`J| J|H|aD'j!|Dx\o_2v1)Z/}j=/l9kWrǞ!oFl+b&( o+rJ{{!!׃!",;|:`VZ7^V7{L`;I+F]JLwkxrO|~C!;j\A1 JN.jJJ|2ʋ2o,uRnoTWCin17=# vwk3y xx164by`{y@Fb(X{d{R`mox э~c36.Y\CkI{] b/5{.kv;xu)VXXȻnJ~[;_PZѾ{z{W#~|pk5QÁPFA|E$$cCH-82DG*6E2yDV{E2B36—UF?,\^" XrJ;GG" ˣv04CBDGڠc5ļ$<$E|Cc ‘Q#?~B~s[$: 4c0PV^ ̓A $$&ݒ~߹=vAAϢVd^3J E/RLbI׹~$0G,uB A$BPJ/f~4C8 GӝG=僿}Ё/a?Ҙ|ս) 9*OBUZUr-_I8: Wk7n]m%|>ަ'+*d(Q8!E,L?yg`‰ EZ^FDL PuJ8qN]*xRNijYR懔&UhvÐQDҐKFٰwbc$ Ք=[9#l.<l Q uCct(7nLXdȒbތGTEG-!$EA l7\"UnDՇ"w\rC[o'r([0~cqZ8tH{IGT|= %,X~_FQShfFD fȃE!anԢuwjrkrЉ\Bs֠<h?jxdJdQnʩ|-)iyeOU1f )!Ԝ֠?'T积{bDil9i܌ZdksOV6S;ըwCv _Y~D-rCa&z:[ ꢟ} ќb+-?B2*-K~R2M}nLQF!+Ơ[#'pU:MI? rǃ.~m(rb4O vTT6R7Hr} L)&Z7 ND8%l) G!&.)~ڏoym^#V׭5K*z4QYYm# |+ʋlv^ oyi!ȉ EӘ^}y҅ogz':QoDqMB RZB9HE4NE"D9& !)2h) 1 4BE" `BG6نR"|,\Yʔ!Uc[\~Q 2 8x|`B"maC$!0p@`QH/N$HŜH#&-\X>QD\-,N-5U AUTD~d?XY󬉔\yeu"? Q]5kؖ(VbP?&zЇtH/+`O+ 5-^jq d{:IV{ww[̶b݊ QRI-I5QQuCV"Ek9VʼnKZ "w_^f{pL$3.lחHLOqFHEģ._,CD*UyA Wx'PWH@C5썗\PC͞nAP٣<˥2IA+,"F&5c*i9Y>{6(dᅡG:R& xFɔ7Uji/k(YR0yg`64IXfkɖmo q)sIuiwyWVY)IɗzɘWP(@iiəIbbbdU9(.DSr*Di_yKhO89NYj3 ? Tn%iTDpi_p dpUR i)N>$YCO>tD,WwLLD}u\CUTňLt'">mc*q1]Y'8L䞂DsT)WT5xTn{"T9^\ɚigFѠ*bMGz`MWXL9y@;Z9m) %fG `"4jxeNۇNTN%5@XWVZu1ɤsVyjl%ޤ'`G'щGRR饈5Z+؝&ojf֠i֠V63:\*SYA@EdtT`pYR=]I )HISc-Z* /pderxVFo$!V9Wf_e Uf-զc4+<P6[zqY WՊ#B6%!:ZZhUZ5%9旉Bk낮. &2[Hŭ\fe@7?ǕF=_[xO8hE);]i]]J Fu3lt*a5I:3rJr^Y@^!%?9p7{PA`\2F$` &xEky@BӃK۴g6Aq7#8br6H#6p.-OK/E2(s"AbM; ,XB|{~˹u7k"{<{I&)1,"$ Ӣ7'<,Q,qx$ٺἃ¹lKVYYk5K˴皐;j2#.sy־K 6w;Ë˱YB9`8l˻|.k,KlۮN1^Yqf<Xy3o" ( *ܱ- `ģi8M|+Ud?z˩ G\**IYF!ܒ JiW uY<@ԟ*FTNiKxxŲ68Hģ5}Ii *AăaѤgyk$jz$|@ IdKBʤ5 װtlǕ4ZŠZzN]ʭ,Eb:OwqN'̦D̔|\Ga:͇t~j$t&xZZ|JjlhªBCYq9ͧJE%'M6 u'TV }ЭЬ ʭq,@VrNкӔݛݝk­3l, DcT~Ƈ ~e&%IZ T7 !(^#Cu=ݘh˺L9~Q(!lLfфtsc =h-"Bl ױP ^Wo5y^?\Nb~*‡Cı!b̨v z@0(Utq{̤Z-RJ =Ói.jenNSS(TIe}\ѶznSП~jٺI2WYM=$ fLQ/̼J;Rbe瘯(RJpPYRmKk0 +FY}]&+EhW*KlM\p]>e `ΉLոܑߜΉ Y[)A ^]FPIu{ڼ`ݩ'M^.P]ڣ//蠟2$X(.d!mQ$NXE5nG!-n{X)U#iK1eAB 9uS6A"4YaDI.eʔQ3DGKVZ嘮4mlZٟB )Zq|̬WUee\5'ޜqSj kc̙m+ޕyW"fb5f1d+?mJtJ*Zuոg~ [ k/\Q\ oJIO5nOM )]l>ۗ~H>D j&"0>8AP9砋n8k/?C̯"qPZ=Lh?>o7(4A'RGo̱' apg:LB4iDЂ R$nE>"N2=sG>w(|pP.'-r@@30%sC3T.5KmD{3N ;,lȊjYaЈ1PdzMrBG),$!wVCuA*+k[wTMSr-hڑiͫ ܪ/ n׊ $JcaE2G6bk'x`|䴜*!2+w匄U7 @Du.b"x@!⍊^gSI-rF $ 0bB#Fb$6@oV;ml-BONYeۦ-$nn(睟Ʌ*[<-z2ñ((z/EHW(vXk ]Cՠ=핃2@Wc?ΖqƽM9Vh\+] fVw޻PzTI ab^ϯ@9VفGX `RarP`m\X ncźDql} %C5CxYEV3asDl:$*,n@RK.1QVrE$fh/=J zyeV 3t2MLgʚ-f0SQsP>$jYѓuuÔ݆w(*Zū_],ۚf5%mm  Ɔde%*^0d_BHfզݱVJח2Ѵmmrĵml\:$;qnaic,n;"SzڑDs^C [p%w{^reӻQ}9C$0XOE@61[l{RZ 0:p/a7fE-*&&5Tzl)ރDP'&%=E1%iRl`kv:^LPߌJ SpeT Ye.ka]|.j^s+aL;Ϲ{8gAЃ&t Mh3YыfthHGZҌ¡-dZӛF iPZԜo"mmQqVMÇJT8+O!ň\2#oJ)=Yp1C汑9܋uȖ W D x]X.$-}PcmյvghHR0K5Y[rV]%uk֢۬Y5ʷI>7n|![ĸ>JulmPVGdM o=.F{oW p^YSɽAzH/+U}JM6[޻Vku! ) D/V* P}R(C`EBn?mQOhK e> 'lW6 Je=)Q7*}'n%nt*t$ /.徚߶u3RS?WW0ذO>sÂhKݩ}R$[ڶݢ'kq@Did Jԛ2pvˏsJH*C )EvHszY@T Io_*Iyd2Dc ;#/=("!*!I"L>  Hy1$ 0Dh0uYJl͙]2)lGT%tˊE …ƅ؛@lTă(7?Nx0Ar%`aD5aX16Fp$#t R d8V,>BfγdZT<-S6HI[VC IT$ ^9ClD uAqt)w܀MJ^ ؀=ϳ^ NC B YАȈO|ˍAa$H-s7h#f%6gD7+Bko5 P5*D).Da%Su3CXͶFU7"K69`MKZ˗8JEkVWjA%Y8EZɫ]e^H$ Vּxølj 3T˺?GQF9\Kԫ _%Wx@u:>:k{6e.W)J2@ ,"TՒlE:V+ٷԂBXV J;Ws;8s/a  sŋͼaG]XNAMe4qY # 0=c98#n[=n==[niK w-Ӽͻ?ZǠ;PP\VAF ǝ e!h ̝|ܔ\\ܺ:\݀Rٮr]PZfȊ-Ǖݏܕ͠]=B⠃ ]= )(\5Me^u s c`\b]ߍ]+Pe!}Y^_amm_ 'K$L֚IIU["7DUZ`F aZU`o^ns+LIa`̛i 3Z D%!U%Y&OQj楣wp +ĩzsy*^}`Qαf-M!RO6Y2٤фBi3.ŊEPHg: #bg&Ń꾲xD(h/Y9f͑{$8p(h$0iF@'RZYim7k\9ea?@5v9vaf׸ Á}曈0j^_'\GM9˞xS ;Y% 0pGf$D Z78|kI!~lȼvJkl^lBf9P-Xg mVxElqlMPeAmۊ84g*[;BX[l$Lf*F"!h0I1ݑ6h OD%d oʺLMs̢aI>͞#j?_ Gtk >/b2S R^?aw/R *ӹZ-v`&f7vW[~^6 @q9:e_a݅|C/\vEW½z܏;KU2>`Oa^/omEaD氝 a+zyTezssq `yîݖOW?ǰύEIy[`{C˫㢌{<"W0i^O{jy[t|ad1n$?!;#FZ$x<ч\'zo-$\pX<}DE[&X1V_zu]?]M秕cQ}]SeRXC>O}X}S~ST7fik Vȷՠ_x&p EIp!ÆB(q"Ŋ/bl ǁx>_?ItBLr !,L%O! o2Tn!02iZS-6Kg\XТG2'XR3*j-۶n[YqnGhͫw/߅d)R†CTӬ B'G\֥ zNhѠ5,W\*<֧Ǚ}{m\+|8~vx9BQMvO)qZfh%v?c.{zW,|Bƛ{gr5`EA $%_IS%DB坆^zJ&aXO[De0ǟnWW;#E?ID* ִy^øT@eB;$=dFeSfB[&Dy_$}BQ铆q~n[8ă9 RJQZJE.CP @$dxGHqAI2 %'MND pgmT~qbB;`RB%evA{y|$m8ʫFl:62ZP̫c&:v Q(PȨTd?1;멷]!K:g2ru4o;\BGFq0`!6$HcYI/rQLEڼ Z&/ج3!_Cdki6"_3YSݱ f_ݵ2[W tH( t1\q@Ц ޶-@9=xk4+QOԒ,@X" ,Md[3PTƵlb]BVh31wVɈM _+ȑ][#mP%1xZ<(g#O8%Cb3vA0[ܓFV̋#ȳC.9pwl>ҐpDD$iM̒*"0 CS2"P =Fĉ4\%WyB_d4.ɿV$1 L̇FT"85+Ji`& b+BT E"gpo#o%)҂Rlֻ4dsw^׹]ӾpR FKvRQz/af+BWOoo}:=>,R^< f/8ipG"@rޯP5^5$ɩቄ 0p[f,#8 ΑC2#-Òf kʸ:xb:39'x|r0rv}ѳgr-^2h#e@VŊ0KzAVfk)l<7;%Eu}fD"mIhAIdAfE3  ?xIBڷI6D}%z1_أ,bg%>m;߶vd1VmSܚ?nftؙFgX,*/\hOJq u2'/!$|7 Qc4MlvY4qR.) ڔ?Xl''9J/N^t i:nzNh2̴Gbawnw! 0aJ)ebBWxml %^}ٯvL̮b;6iWޢ1QNw'GJ$vO}؋?)tlHΞe7Gb\\~=Y|[~>W(~k~SrTR.|[%s3\Q9کHp`,Q`bYbP_IAq ^LO: }\4 =`~``E p DD٥u] Z >Xu` HҠq4ىW-VЉ%EpM W OpB%?Lt N@B,@;LLV( x`Pb߼pdYBDx` T<`,!F`ClNdGUPF ׋W Ca BeԂ @|CX ևS8| A ,@<6]OaTp|OS,LJt 8ut 9a(^9LiQG"ba!^-X`Q  m "D IYP%D|iyBl8I"&ɒجSEZ$iXQJ JɐN E,8Q&%dYy-C5} x#yP&@ zJ,b6e}MD]`T}}f:%jfdd-$˗I5 <. oU T߼at?-D5vN B7z˅ p=aj(![<z.T{`UJWujVY!~`a}H4\@MP &5bpilt:`UT `dtt?"J;$ *X"Xr8ҍFh &VVqf,hX½\\d ˼D`J!\ ͕pKHDYKb ]C0f2sR}pe4=,².IþZ-LQFsܑ Kr:ߕKaHlklv ʶH$׺[Ee $,͂^ boD2iZтD~ܦ-˶٢-vڎ_"m-nr-nœݢ_R^.mBhnnnn~hAn®nonf o*2o:JXfZarbon˦_B$ۊqToWΦn|da/xm-(Ahou oU}ݮjor,EO}lVH'`pCKh\Ffm{/Jc$! @!Ld袳9Yl0SФ( po%B!x0p@4B*}X m]XX2]1e1l1eB!15X:pt3G[/?NJGdq0X|@!@O܃#p€AePIi|lY򽎲ܛXD 2D5M#Cm -`P؂ɶ J+ r9w4?q#ER8%0'0F,@#ZR\:xG%]?1tRQTVƿq> -??@FMc3 vBX C!430\G6RS%p2%Y PUG vH/l%O-؍XH35@/mZ[K\;uBp"<9ܬ| ڮbᖐ!@!%@ vatp bfEWRClv6U д56]C#8ceeea(gt 2z/yotB#t/38,`w?뭙FA*;7B:\5ù't)t/c+ݒލ?@dlw@!/ޖMIz<DSk.'}bYN,#!D GCAw̉||c̟O Ͽ> <\p{$ gSC颋 6 $b# P.tpDMDQE]1Ia,eQF,rwD>H2gLq_T,dAK- b024\6|8匑3ܢ<G#.@gFA $ GqpQEuRI)MtQBPF)Q`R T?I=DVGmL VBSppXUXOd]hZiOlݖnpW==] 凤8c~?P xa^}m߀Ov=F#wbz8عŁ-c`_ᇭu9蠅hp餕^馝~ꨥ^+vV7 !F,05,95O:>>3[1cbXeu5::<DSbegtwwwwwxxz|}*47=::88;@AAD[deefiqvxvskfc`^^]]YBm5@2222212121212170O-xj[MA<:;?Wceffffkς(ڏ9ڏ:ڏ:֏>ȎK^xgggiz֊َڑֳٜۺ(*\ȰÇ#JHŋ3jȱǏ ZIɓ(S\ɲˁf*͛8sӡ7U%:tIѣHtҧPJjʵ׋Vc*ٳh*4۷p Vݻx"[W߿;[E̸c>Lr3kތϟ9ӨS^ͺװc˞M۸sͻ]lȓ+_μУKN[ νOu_Ͼ^zAGA~(hrqS@@@ >āfr* ]|Qha,H"!.(T'@)^ rA4hKB(TViq-!Ǒ$F(>7hzCGL3]͐pq (eL't5X @хhPu6(r>֝yY@Eha-*騤65VBQ'y*VLibh%h2S j*&i::GzBj~l)(Ķ#&B̶+B*rR hiV& 5 s[(;,SZp–.Ή <{jJPbr BqbZէP DhZm9̱dž@ *B}Mae2$s DsSj M&*SPXMԙ(V=?@,zC.S뺳P :l4?x3`)J@̝co<|'`@.pԯ|jgOO /}] tx/uk,r;ׁZh'fiF#$bɠ7z ]6x0BJb0 gH8̡w@ PBeH!I&:PH*R&J.z` #,FEhL6ސ0@n:x T> $(G`#|D@tH:Q̤&7FB&DH'z `F8E:!F,gIA!%)MJUe-Ibӓ|D':ш0b72уF,L1n AA4g9? BM$$ 7& 98"`:S"t@h#I\LJ!|BO i -ZO4i4X"FP4ġFȥFYJ#R l%Ebģ *NzQô! [JEZJ4MD/1pEwzni;! hU9/!o;rp~hB,J䫇;)ƶ$#BZ]p"^3y[*5& [\w%ْnlh{m@vlc#C-Pi1>SҝY/~")@┧0(rf6}[/xCbt8PK(aӺZ8hDobnNY-ۇ+w)rWGt\P!vq5$mRs9*/V[t!I61Gc">M =!hq!qGFtgy ROX;P|Xjy;p/  I Ӛ` A!@[vbz;Qh|O> t{П8 h>|oTUlmsO7ҩW!hѱO6ddZu^e`VUE`tyD%7}G7J݇E\F瀀QdOfzWhVw][ с!x^΅' X &u4CG EP G f%w'Z Q|x?lN<X@>ڑ99m>GOYP2IhQO6 F4Xڄ 1cʍejSikʦRoʏ ): xjL] |ڧZK&1 uz tHVsJ7ДJ75yʥ;j2p i{f:'Īް9 iPЪs/t 8' MUćTDHa . < P 3(Ym9UUh & ) CWՆhްa{ǘw[|G jJ.D:YRkI~%Z7}`eQi(I- ;*h =0[u\Z&)B˜c}oiD&˫Yj2;W Z[y]+7XHh7jkqlKڲ s:0& CF4}ZkR 9finSq(aGKJ q9VBXK_^ i][KmĺL&ԴWG<`Wѧx88[ ȋglżluһnÔ@M τ1@z8'< )Gg~A+;(JȉZ met:dNX&>$“w%<'lH*9su3Ib L9óy?IALf猻iHʾulzu,JЩ̲|͌Æ|Լx`lbQ:9WvL΢J!ϸ·F0Z˺ʫʬʩϦil=]@=  < &5 Ety ^ !u$F~V~>[ -ئuluC'UdEN A4=\h-ŵ{8b]x`|H*ܚ-Զ3̘۔t'VH9x K&CEU݅]>}˖Mޫ\Qf^]bOkA-aE]ߪx| /Tzc]N>`{ʻ 1M]\mFQ('۷<-Fn  ᇩZy▨v~W.*^,/.k˽WXnkk5 7O5=Hݴu%Jxk(~FyVQC-p}7 7a˼CÎj,DΡluδ Z*nɫm>V+ χ~Ӿ6L=nF_n]*όӒ _b~F#TnO58 Oҫ7oC.ҷoj}G?!;-E_CS_ɾ+Y[4[P_8?_ ӝalI8R?ZoOxoznGco[.I^zw; ?&" ֮.ai\܍a~j?NlX>9/#&}e,¿ VNٶ^XQG1VesMFV%wNXm`WOC>ʀ/LoM@# D8p Fa[) lPʈ adq`AD(E?:PJ D`PE EPBMjtҧC*4a֤]~kԯ@EVm6Ar tkѦ 2S`dAK[b uF|5תXe}zTTDn:X֭]|lڳ"|y̚u_4l8˒<Ckq72fSHnI}tjU5^O)r_w]^j{ V#-<:KAH4 @ޮzMϬJ뽬Ƴ?24Pqh)p릾.$ pHɜ*n(:A!KdmFE;MvJHtqFoӼ>N~ 4i$oKET?USw]&3^b8, dG/LR3)}ňO$LYO޸Ύkk"d :y&+ZrkgVa6.zsx窷c/&U^fmM^T/fMŵoo3oZ&ɼA6ц!@CJ+z:a"ɥaUl8&:񉵹UЅaH#e\ G]oaV˝6iC *A%̴yhPuc G6n(TJP,"`*[넓PfL.=1QH!M#-e!f4 !ő";m>9ݼf#X+ax9&;FFud0J҄:bk &l`\3:` 6t7Ze7Ey45ZS(Hē *"IB=LXQtfD@Id:~NbM))Жʔ"!RP}DWѳ-fGX&9b̤AO{zd!JS.i22ꝚbZ%Gъ$g9b6Y֔C@y%f'/tiRϐxQk^4+!-m*a0ٜTbJWnyPEDd-^Φ51MtK^FKn5TxJ!Ķm[ICmg ܦ.(l!XKۉr]f#+9U)JFHK_=Ik_X1;ko}"+Ή6> Rѥ.K"Tx벤VV$;!"Q6߄v[Cq%Td8 /BJ(08d.J 3s̛cw+C_SKt.jsቪeOέe]V#FʖEYڪ^(Z.C HK-E멱ztW$FA0\6+9M:OZ@asY$F~gZc|Ta.p)Fk4.]9E15ݯhۄD"A6pN"%`g"|(_Z.ٛ z@F8bWn ީ\(rcmx>JS le ҝnYQ]qzǜr3͹zȥ[pyoYpTIE7~IP<J=@W7cc=:Ps`7{^Fb<ټ%+.?* `%G7#:??Eā0?^p'}/`#l/~u}P2{~3UԙlDvhH!X^DD|FP"K  k@z24sہNAOAO#j *3 -` s@4 R?zp*#08cH&\':A#Tt $$%<2z/-:'01Ypn '2 )%D(&!* 0!B+ trAR3ěj) LDX*,\:,*ꉖ 쎧2ŋ@JdB8tA>d B 1gb_a$b$FW>!p ˈj g|. h.'K'+ѫZPƳR. (,Mǰb1YHY'a@\0d 1"͜䱠1Ȍ$N[͜XN,>J\Z1"\6l*GeD·`K7D 'J3 0 (a1'|G&lf /8;6‹d3U0 Ѧ O0\O~2BMIAПqG86P"_z:ӕ{^#2#:ѫ>>;* rұc/ 434ݜ5M̳$k9RY<=<`3S@ӁxOPԺPXԂ46sc{ mR.% Lm;})5_`ěn[*[4AeuK>gTf;i5VkݚVn;?'֑pU"Z rqEnZ]šV{CVpWej6J?dOעԻۻӁVhu}ր%<<>سX 5qV3TUݡo0x?UTA;u7mғ˗wmcWs6Xq똕X5A6!b7sTTI%9o!{UZةXZ BY%YhVCY ([.-KV/jҺ?n##Xд@NS=ȿ>Țd @5um5 $[[e@?@Kz@˭D]U)=@ ,A%rYm5!15s1]PQ]#VM؍?eݖ RC'KW)AC5J>H.$̅t30,34,6<AhCpR`74-9V;a|MuT`#0C<܂5aŁCbSh}_TI̫hDP\޸*LDE|R) #as2ŏnj˔Ҽ|LĔB`F^lI,'L9526ެ.`Fcca@ƦYqF%\#(l٤DȇQHN 1J'٘ȸDd@>0Mf ̔g , aQdV0F &(0UƧVa" ,mC=k٦||L1$@˼hG8Ǩ^ΐ$hj1[GD\2mK}Rv~SLAWNf%L <,İc=DM"$MY0I@&הfONɏs65ݍ^jU & `)2d \@d#s)Oh4OA$; 1'^.ˑG!fM4kPqދȓrjfnc5 .D ΰR!48#&AAiB1U]B=537Omj]},Rru$Q lqyRԖFgꠈw BmP 7^m MڰY}aҵPʅ?VNT(ԵHpoڀo;YTO'P3 p[k ԍ7pp _ZC$Ѓ !'"7#G$W%g&w&5gqvBZrrFJTUOt_P@w``п<~7sC~G@~x~<'c?_i6uo4b „ 2l!Ĉ'R ƌ7rQcm>,i$ʔ*WRfdeF2gҬi&D:wz yp$ϠB%ePJ2mz(ԍ> j*֏G:׬V*,Z[mm˴Cɚk.ʵ<)^t.Qο;5rȅdl2M(!k2L̢GLVA$AQ{vJ6n]r[tn"3޸#G3p7H&zu* ~zGNq˂Jap'x hrs[4F {Z AaQ!D ^9vPx!X2Ň!F$p *{dS3BHz7xma1  zCa(If~9@ pQfci@w扤@# Ħ~oZşb $^JPJ?e ]ye| b=_+%(a@"'G~%GHN߭'za~z@.tM#,n<n}'Ma@un+vI^n?rXkD rli^2H@#혨o&;1ŵy7?¹1;$%.P L*gS$a{ WpIE\nk,1O dZMPbI3/ w* Xƚ:rELcy N7^bOա{G_nx虾Ej ɩz^껅!g0 郓C1;8S@w% ~Y(&Jn!I}/ϋȎĸbTq)'$n`>UJIl?$;2E @Dp: d[SMp Aup!280~TaoP;F + ]#Æ9xFD5G9GEHĂH5!Cz>i1+b#*ъIx5"EKgF`q4 ²qft"/D+ ,):1nldf h<1g?a#LQh'Qfq<$#>QAcCPҔ H?}*rK1KRd/QD.)0ǐ2?FC2sid!N^Le lNj$H'FdꉚD-IBJs0C L'f: )& Phs()LE“C?Qx.u)#ރ0.Oq{/7*Pvg,ȪxҎ۔bv|Oo\P=SQ.+HGGI5I_0Ц&Ta.t:ȏ>ó1!l[ԄU=èBԥQAXQ ySdIO|A k)tVx% %2A LZFɱ)\k`GV#V7ibO ׶2֤i 9dE W5xUٻ&7X nQOYɱ?OQ6]Qiqv6( {o[.u5#MFHB+5 ^BuX5o6eJ+9gza*^ {uA,q-=ʽk+a`/ -}<7ȞlRfP= 4Z8#)N5&t?LjؤܢR@ cX wԗ -%' ɅY_aj>!# jKZ=Z?َ7aEsn=Ś8W+;L ˌcUgճ>VΤA^v.w#I(֍3^dQ}1KwRS*'j:yPst;{=8ݵԂvGhjW_ďZt#Fgd%x7 k?r_>GFïSl?=9ko:?_h<-n=e1}O} U+@KX'\+*1TR|C|X#8$!CtZMY`4]P(,B#"{oۄ0XS ឹd_6DLa|`bpU! ៉Xƕ@7LvQL0V19Q `Qar}t'/,D)D5\IQVGrzm⊔ס׫E)1b(b VA#@')"!y',YH_1#v,P9ir:#)#0B4a(]IV\ПFx Pb"ʒ- ]!#E@o6!#T;S:=#pc7^}"m\%QQT@3^#mi MUVE ` Sj9Jb%']HO%4Z$P?žR7"6b:e/NQV?mc h@_)Ԍ8j}VB}W#>i#@TY(FN(V(Zy}z\Ƈgz߈h~\R_9!5إ'=Sf(-lSw6 sj䐒iO"imgvBi(WZYY_kR%y9)pi)eաݙ]&QiVh-֦́)zi(1gy]⹦RY\^8."rjdIvޖM(ejn*e_e^iiOS饊 Iuetjl EʢTA#1Wk pa)5kѩq&Ukl6a+VdலXk eVW߿ʁl:!~5H=DlakW$axkj I*eWƆƂ+::ś`xbՉinfĢrZj,Flh6z+>LQY 칠Ѿ,1Ԛǒd<-SD- +!na +IszlaR"Bۦ,)&тچvgFblm#D#v':nQ"pȭ*f(.(nxWͶh._.Fo*B_fo^T-*No Mi)9e)/%{g"d&iigΐZQ}N /}Ko3qo/jrdo95Ik;f)J*S/۩yj¦E*GkY0 w(ޘ&¬*foСV>o c*p3d&W}/B0 (%뭆^ KeN\a_B*rq 0G_Vj t.`"pܓz! nCm0%DRQeSI/2 k/mrj$MZCY2 luk̾iM[,Qˎc}g&a%iP0ϩR,Y,ja&.H4"$XW83M@x ΣE" /hqr7/m>&orȄb4F ]e%3nNئ<fo8vHRa4GiV pfmqm"sMRi [Es]N0,;PsQ+mI.6DOAE4bFoOkHsen2V疵O.N/*!4\Q0 W®)3.#v Kާ*Sp64mq^k?+筮uk& sH lG Uv_V1kG=Aw1n׬vr+7+pߎU7jO1*)#cʚo&f5#hz7N~xr};" r%x~ixl({F}+8Z8c#\Gڳ&,ް4O#e_6tg{.h˜sFNSZ CxFGtxSwhWwOwo ac"]g#_+lSCA,uWZ~H9q]a9w{&yj,⫘̘LZoGC6fOU0n3aڲڎKhu]HB߉4WK g ܛ So3)yۂ 6[m]&QlqZ*y+*˪ $xC)֙0a9uywBBxUίθI9) vmIB6NӌC< ̍[\+=ʛ;jϥ;޷wmL$C3X R )tOH5W{{k傠Pgó"r8/-hAIX Ƅw .ܞ4ol~:E/HXR=3C%Pӷ;_+`?X}+EUZezeZm6;Ǯkjַ[F3r ==3PK!.~8fkx}uzw[|p~ݣ契羥{$xvcWw[5n0K@XO?W_?go?'r?ﲞomk7#gשn;0Cij kH7 @H $@ HPBfhÄ+v0aI%/D9aK/UƔ9fM7qԉeO?&!Q&&Mtƥ!=V<:!KT#bDqʛ:lYg͆UmKېD ĖZ*5$G$7jʮemmcǏ!\<˷+jg5\^TzqLŕ[G=Xط'_6wdӧBd4tXM.gy\zu5qg_OԯWtz|aпo{~nOo:,($@c )+ ڏ0Mj Ƕ8gzp*l-:`\->,#lÂ>P( #G?lpPɘzT+qI#($U*J d $oA>I4I;*O$3/e*$038lS-"0*C-tʂ`1S4SX PKTOu'=GluUYؙ$wUAQՂRe|(JބKL-B #B 1BeXr 95]D-ws+UCDrO^yTDԗLtSc)C<]u)L)}֡o6,H#y&3=.(r}~10c?Z}ƹc+Z/M|}GHOP+Glu+'ݓO6!/uc301p'"p@.p6*KG>á4Jʃrp!U+9+ɳl82+i\Pa02dM벨'y p1r;,lj kOP10L3)*HP22p20+pAPz¢B*-Цd 1p 3љ=dCل _ w͘c07aP B3Clnflp 5џЃ xQ2,3*+^C˞8J0 `|B m,f/캅8ʸHzv "OzIT P  pٮ𽼤KP0%L[$OD N$o" F!!!ǐ\B#8IDIJotE%`LOvl ŀ,UtuXZNM{,ɠDE`n&/2gZ\' ((2H/&t'4*K$jnTV^/&f&H@LQ7%L.'RIBSHDWQCQ0+rUpȰ"3-VpİY WY3 +1PX,Y3 Z,D%0@բ\ pU;])uF0 ?2u>@Pruu+cp`%``j;Y56v01M-'Zi65Hp5Ұd5EJS6EVeYpWa=1fbעgug^YU9J+6Љ8PꘂjO0 k gek}cKliORʞ&mm X pVbהD 6rvr)q 1k57f97?s6tp;wMwbP7uQq$QxɯsMNGOGv3?NBre$z]vddR"%zO0-%7Dy;R(swW&x$Bt#w!Wypmd1mx-TU'U t&jed,6UǜeSvȜ*X+HJM$-3+RFIJĮ|s7j٘,gL|%-ST [#.2@3&ߖ/ 21,ESS.2)l2슳߂mEw~NH֭ ~(R3}5mG6s\yV{.Cmd57M8?k%Yh1zxgڶ;UӈTvE@'T!^;ݦ$M;I/#c1'yҭ{e.teȍM֔sRD2T4;-y+ԗ)W2LQ*TN7JFW;2Xަˉ# ?MTEQ9̒rdjY|q&GFohS9A{{/IU_}䍩 U+F(VMh6,dZH3Kԉ:Lu(ӔȘ:1D9EINOO1Yu8+Pkg:bɦџӌ z05e h߆Uc8E1dziT?3|WZC|†:k8jr^qmuv~%W%b}VqvDhwgQf#F3W%pg_;bG6W袭K\ Y*AFZk}i[wp^} $Ȃ90{]GPuI="{oK1ۻ{g , | <|!<%|)-1<5<寽wֵA;S־YR+ moQ0uPg6XdِGay˒1a 'VXv@n<JYZ=i6PX5gpC7ˣ>|x@tvB~ BA|`;hYə7nOg3|2s!QM8fQivCUܼTŧ\ >n`z!#|`A P| yoV8<% llȝ!$Ǥ"Qp+ h6y=WFN~S*nBA+~!B@v  *OXv l >x񽠅/0R#TTVMBvJν$~2%'k0'V]!^'|4: rS;٭k$V-=!f~&̥aa|wt0C?sŒF E7Ѫ^;?! ^eejL:H!#0* @?QԪFRNp XR2Z$?`= wbEqތ7޽NpL `bxtTNѣCXxp@0!:BLm *|!;!JPV0̛w\!; {IGQܻ ҷs˛?qz#2FSNI(5 H _htQ5:8xREiHނmĠG~∼y!΅bcHc^ޘN'~'ܠ88/Rt&iHXP:G(e\/B$s5~ r8SzdJ.Ye*$Wn%JFŸ^~I%zs&.'mFi.8giC]6h*hYf"pvy袒9)ri5J&tm lKll.l> mNKm^mF"tKin /io;e P.[뮽 _qc|@g| r"r*r. seL A1t@ rGrq!,PKMG?L_td@dWb XY?U w~] Gx#?yONy_uoAJ" H"X![1B"LDx1꦳:Ӟ{{!鵯>[1| |>- JD F,I=(R~%'|% H.@5Q~BH P(G'\Gr@iI ,p(Rb]& $ R +eRC8bH8rށ `v`ɎLQݓWI4ni#R"6=hA!ܵޖ y%HYb%퉥v:( JH6!!D )u$2"sGg|vŚ'g ;~k;IC5V Ob[F*kR:d EWsaℬ}ʺ fnZ(Rr&1u)NܬF<ӻV# tm,r_ W 5G 0|dAu%#ECdr2-4Rm$ H#H$ R- SԍR:@s-,yRdvHfpMtmw2ޭ|߀.n'7wHG.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbsH2f:Ќ4IjZ̦6nz 8)ML:v;E`y̧>~ @́І:D'ЂRюz H-*ҒSeIWҖt$})HQR8)?cӉҴ= PR?QԦVtNE*8ժZ4j@0':OyXMZՁn k>NQ?Z׾_WOӮxY:P}[ Y͒l uvv9 McgK[vp@ t ( +;ݦE9u[ߒ2A x oDo (9)W{i^η:_򗽼. 0 MJW5{ZRxH{ 歄;ܻ@ dC ;C7n?a<9kWH{C`;l?KUdL s_Laȁ @E@p6i:׷amt=g͂p +_= keϙu0Hۏ.aAM3ԟέP >k1iI9(KZ͵D|NbΧԸ5NeSfnct q1&vM!,[22xAf۾ޏ׏:xxfxזff:xfې:f:ېZ:ې:y f::::f CH_FBCM$f My ̏zH붐::8:KLWYXfTF۾:POzYᏧ:x ,,8F{H䬖۲*Z((48D:.$VS8*SxG9*$8MKWIzE#CDN%>߶!ڐf..:/CM.MYFL|&PG33?Z*yf)MOVzy!NablLH*\ȰÇ#JHŋ3jȱc=Iɓ(S\$˗0cʜI͉.o$`ϟ@)t&E*]!Ѧ*"JUO:Uׯ`7f kWhӪ-8vmEgʝ q6Kav Fh |e!KNx #O|锉;? #,~[0ـl CqO+_1>HP„m_א]@gnpxW,@ͼ3nB! AG A؁ԙ0CA *WN^ݧQMǟW_׃_!th 6#8l7 'H Zp8Q@@a8T`(dp't0t]80Bat1d " ({pO:]DaыHT`I)DHQ1CPdKW;V$X;*vQ bI7H7c0("A4d&{3R)pDoxbM?V1]8V,(/Qd(Z@S~\f pā$Q]2fr ʹ4ˤ9u~Qpf M@D83 MS>9u1tf,[LaN!$AV`h.0J˗"FS$7iC|*Ew"U͖6t4 NrsITt]\-DRћ%LOzUSfu]]'-{E)UC]|J` δHE?^aP8^zM<@:Ls},ԡKl0#N(*U)P92vEb;k-=@au¦kk)N)Uɤ۲ʚUZXf3-CY!f(S%Ŝ@ȥ$1Z[$nf'wv!`Y&JLwAQkNqUvHO?4ԣNcO ̲N3XL\^`z׻Q .bW`Ϻ4NX?U֋6zX7qŴ*V.h.4CPgLhLhDiqP`0^d0`CW)Un&H(GKۑٝwD[qKT K`(\i`秓+q]RG'Х]GƠ$( 0a +(rl1(wٹ(o0xBuw? #KW]''Oyå^chD7{d %G=V45h1 t"8{(:[hEh.q,a8'!,Z1121212222222211222222b42) sg ` Jn1A&    &# 8#J!b "o0|9 Vrwwwwwwwwwwwxxxy,7;>?@AAAAAF_fkw养ݗܢڮҰ֨מݥH*\ȰÇ#JHŋ3jȱcB'=Iɓ(S\$˗0cʜI͉.oɳϟ7s$I%L*] PJJeȂL XR栘/_81iճhӪ];N(A%Z9ek'Z˲˷_n&;`%wxǐ7xkႇkM|'WFL. !\X-&_LBq- Zc`3=xk i >>AU@\M"ٷ/ĭ;q WEwxN'hUTwuЁ z5A AhA)H'`Mu^RH8H߄/ƈjb!dbJq7%!!U1Ync\ZY&UA"DM)Bv^ TɁgguyMdl5P5 \M$m:"{ !{Ne6s*ovj6Nn1B䣭*a#&iU& t砂Fea^t8ډ xᖈz [G&Iݧ>zZ+mkxIni&/†:hۼ:-AxʘO1ж"RH4^g[ jpvdw'2cF?/sVrf4*m:1B1˻E ܠjVSP$*vf]Pׅ]{nwbکF'ttyN7 uy I\CmDCf/&ěĤS^Ik=3ϧֺB;o~Wktꇓ>wS.Xo saLnk2(A}m!7F";K@؋uB=mR$nJZR &s,rC!fgw[rH(}m`[@qJ70Bv9, d́P䠆ń|QHƫM.]DHpdl%Ѕh(HY %"0r"|$I>O$:I'Ci?XLV򕰌,gDjŖ.w^ 0Ib@NiKd:Ќ4IjZ2nz 8l6sL:v̌;Iz\9~5eJЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZX+ծz` XJֲhMZֶp\J׺ڵ*ȫ^׾ `KMb:d'WRͬf7z eCKҚMjWUIXKͭg]% խpKwoaЍt;շ*`sz^ <z6Vy%oy˃I{?+|U _I}JW5B'L62ypU0 ,А čqQ ^__ Mp`(& 5 HUqp!=1]x-k |5.+u&x!5s_6 ~3&n}+c_r,.k9zsfޅ3WE/`-Cx=FrlLigz04KiAzys_--&<Ҕt? hEԣn SMBb[+ϸ GƳ)kMKa؁ƴ_:=sW෫n.aiL CA4!,LMsmo_h77b18HJ 񦌶9B z?s@f9qܶ6@/, P`稍rck;7|~܃Mvrt L)+c6Z.ٮ]&ï9v5;m2d.Y {׾׀3  ;\tV7Qd`xΛ>BOz"o}E!,Y22xA۾:fې:ffxޏ Cf :xې_fxc㶧:ff:fې::`:f::x^_oضvs_}if1((4b::f4W:$BCMmpa 3:!Cf-z|dn..:fxykqKLWUf33?b`xweunېfaablm H*\ȰÇ#JHŋ3jȱcB=Iɓ(S\$˗0cʜI͉.oɳϟ7s"4C%H*]TЃLL\ᩩիXju`FxٳhD5)CspK]] 0P& LXp^{ HdS"Hn$#O81q (Qڵ9ttFF2 E(q‰DwvB+00LA43@10x+}ڃNB%CUVvyOp j gRWs /wp"|&0a|aHI3LjԢa(vE@[)iB2PH81.( znA H`$XI}D`1(-' IxPIPv]rIgSwY1 Al%uí怡QgmM**zWN1!C`=,jd j Ȃ"E!j+JV UJ) rAb*ߊDkm4@-(RH [+Ab pF<"-\_T!|&CT+AMH'L7PGtAsV-Xg\w`-d;MVlp-7=9x|=6~.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZȢ.z` H2hL6p(Fx̣> IBL"F:c#IJZ̤&7Nzr (GIR,$(SV򕰌%*W)Z%.i^ "y)bȼ%1f:\# <̦6Gip`& iMlR$'Źv7GuޑD'#iG=G|S#AQS tg7g5jJ htiM, z@7 js16 .S;.Tf1. o)3S-@2\o@Ld.RAV@EL96 ^p`W^$lM{l8B.H€!,T22xA۾f:ې:fxf:xfx:f C :_:ffxfې$K::ض:f.1Uf:/]l::x:!C곴f:fa3ې7::f H*\ȰÇ#JHŋ3jȱcB=Iɓ(S\$˗0cʜI͉.oɳϟ7sJѣG"]ʴӧBJURjʵɬ^ÊKcȑ \p۷ BC ӮmFL8"u^‡ /LPrг")\ t gWcjr(@Aj?ުbs88dE] |rICCPp[黳[nwPhn^<=>3f#|,!UfyG^Me"IQA&5y:%т$ׁDa)VĂ ߆ hΑ݋1D0hҊ, iwyIȓmET vFDd]:ԛh1N^SWifjb} & ܒ¡ڍp*|^ga"(Uz(~NTZ[2iiG7jD:j? +n͊kzf+k&lZF+VkfV݆+kklA+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmd\w`-dmhlp-b `x|߀.n'7uWngw䞇.褗nzꬷǎn;8o<xpoW?@@^@^˾ӧϸk?c8Xz,'/ 7{=sL x@%N}K ]?qPKBn(@׽o @iR(t$,f o G /n(Fpq7|zAPDZ@~~нe(EA- ̛ iǿQv (`tO%W+0N4dYHU ;1921oLd&,cގTҕc%M)Soh`)6໛L]V1nLe51J ,'6 ȼr%BHN9 =$0I?}fRsi'@P@A _}@]:عk:\<@SzA<;OISoɫy5o]c3}'5o.@6[@V@ {@"O؞'X- A LsW nσh @ao @VPv6ġ-1p O{f@> ;3p1+`;,:vu,cҤE1mw& XX>2фT46EA|t"/Y=8*-$TZy'6NY# 8iz*uIK*$'6a:ΰaALR&zRv4 j҇he\FP]8H̳ri vwQ~KeꆚvuiDkʜ3ik5bkV`~sO mJ شAv "a< p֮&7ՉQiT}h?xԺVpK\Q.rk2wj}tZ.vi o+6A @eWc&NN 'L [c~7{ͰAL(G0q8f؊0@2w,)XHN+Ld K& #e2s0P ^$!h5Wg)A >9 |L@'}c@W7# Yഅ!,!Ex22Af۾޶ېf:fxfאx::fې:f:xf:x:f::ff:BCM:$: _  CKLW۾۶f,,8f((4:ېff$:f3̶::곴CDN..:f:.Mf33?f붐ҶېablH*\ȰÇ#JHŋ3jȱcB=Iɓ(S\$˗0cʜI͉.oɳϟ7sJѣG"]ʴӧBJURjʵɬ^ÊKcȒ pआ 0(]j `l 1ڶ3nK_oεXw j.>NĄ33d1M5`fc劷ެ邢& z6C٪! X5@-߆ >=L<0|`?=\2vv=_w[]WAL6<Di7A` Zly"6Іq|7WX"~}\`-0[e`GrIifM>BHpyYsY f`_mX$Dd|Mt`*Ge_ڡ`yaIxs>v&a5:e]z[u/}R'Zs*HkEǖfɊ\ꞧiV(j|Ėoi*&%t$E8BG犜Y@q"\iPbJ.4/Uk~{ZX|xG;HaZp",,5ANWhs~yr UVqI)r?@8kP5",}ݍ7XJWә!Am5/wOkY@_`:D8~_:nu5;);3se+tOdtMB]/nPGUWnX_Ue'Ee褗Δ禧.n/o7G/Wogw/Cz觯/ogO HL2'H ~̠7b GA@ # 'CЅBB:Q!"0!@ Ă0&ؼJqܳb.D>dX k $<.zzS`mHEiX/1T#wF58#9VbA2P0CP"@9Qpy@BLRҒʫW:1eK!F@ hȁ^R#87ZV20L%Xɼqyq#Mhz'A$"Wq ;O%γѫR']ZMtH2kW0UԫbDRTYU]uig!B2U?КUɶU7MJW U+*MB IFz*l=֛RUnO,. zѧ*UNCpդbcd ujFR9V}=6LY̍ƒ,d%"tRнB `mn˫/Llp9U\`*jyQ8b*V8ZJ,d#vd5#kY]x–jLO XGGx7`Ee6Q |1A x^ 0<~4g: ڂ>GB/Zȋ'MJ[wF%\Ӡu6MRԨNWVհgMZ^ l^MbȾuf;ЎMjkץFn{mj+l{Nvۦ~¹Mz5M- ohzG;ئ (ϸ7j\K;CBo`+(g`p*@mlAHO҇ Kx@! ,=8xAff۾:۶ffxז22ې:ۏx:xf:xf:ې:f:f:: C f:_f::$K:xޏ۾붐:.U1f:/]fl:f۶f:!C䳴f:faf붐3::f7ېېfH*\ȰÇ#JHŋ3jȱc=Iɓ(S\$˗0cʜI͉.oɳϟ7sJѣG"]ʴӧBJURjʵɬ^ÊKcH ]H`źU`eUvak dx9f9 d- #VDC;$pfe͵ vθ[boE&m낪:(71o罜y3c/Ԡ6;Ǘǭ{tBj%x]@mc~at#lPUfu q=jݗ_v-|`f$FT]!c|sn`Х5#`i"H!kȟ*ȀJ 9J\ϕ f abКܣ4qxX /?^#$6Le=VRsp9ǀ' ':G|A)I`Rc?9ŧ>( Fp(CO<Y=-?ĞYvWEǒV5Kzs\)I3?@9DU9JjԨtX#Ӛ0!b]0yØ^@HA'9Fnt@Жuv ƤjS͟dc4S!˧1*Yڿl$5dV3 kYkn y)npɈҭruE.kIGݠQzerդ*A9UdlݱU_A J_IqGA Ѐ&c(W{iZs-5jp%/3PG&W}&w?;^cDKGƷ&f*; ]d2 5e+C=lY`=K%XX} ;M3(ɋ]lTɚMyW|e`:jUjy`Sh v̊]ncx ` xdlۏ,r=!1cS=`H aa={J(1( 01x! tlOh)[S d.w,OZck\r U t:ON{'AȈ2[ بz0 x AjjY3A@F~7ƳRb<6"ADB^b3^Nq+&g#]/GD(OdM9gN~8Ϲw@л!S,[ 22x _ C$K.1U/]l!C곴a37y  8Ō͚pP,x:з_yVhPam1~,2)\(l( @z  [ $[ 2?@@???===,1.)*)#-,++:?C9Y6\\G+ G `0;BxJr\yktvu daenttvy~ 49@R_afqvvff____ffkokoooqqqqqqqqqrrrzzz~ݜۑڏ׍̓tf^SA78ڏ9؎9Պ5~~~~ } v o n l fecbUQPOM;8H(\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIfJ8sɳϟ@ JѣH*]ʴGPu:JիXjʵׯT ٳhӪ]˶۷Bݻx˷_sLÈ+^0\Ɛ#KL |8LӨSΪYtDsͻ[ O융oμУqׯ9Z;wOyԉ %}OO{zdsgyS|-߂ 6im YA (V4ۅe8 40(/8lR @)D`cg@(WPF)yG(:aGv?N`yccih9bpQixR矀:} j衈&j$8)裐 ʤVj饘^馜v$.*ꨤjꩨ(*무j+D^(% +k챶 *F+Vk-f멳Ir+jk.źl-k㞫o ۯIk' AR Wl7w> oO$l0(q ,0,)׬f8<@LDm6'mfL7tC-T_>OG]`Qrm<{lLD5rvx}0|Ywws*Rz'x}7#h[?KΘD4/;.z?[:SBL{Rxk4Y5nȎ?cq8Gz@`1# (.}p8֛Ι KM'# 6EsSAN3m x&$ h {=@5@.ΐzc@EwNP4B8@y`3:<#̡tJ ̇>F VB x&NPt!; g.AT1Lژ2*.hO?*qgppP*@"5h>>/ q\#4AưHI&7Nz (AIJrjLiFV<,Z^數+c9^̖.ILOҗX0ɘb:L4j"e4{Yɦ8Yn3_L'_NRS mT*ҚMjiE06)ͭma-BL:wЍtKZͮvz xKMz75ȍ/(qŭ}LN;'La3E|7`hmFLW0gL8αw@c8çᰒ= bےF(B,*ضDβ.{`|c#ɫT6'sm:xγ>πMBЈNF; I4K5l0b#(ʞV8=e%lBWVհgMZָεw^kzҤ|j! h2"L{ oC 3HG MrN[ SUZO+'R}2oM)(QL( ϸ7{ GN(OW\ #Kg!q#O!NHOҗtB" sb8u88 L`Єm3! S.{ewpNxϻO^:l=(pBܛ8d#C;C!+D@l`IIE'U_Oo=+v! G} W$fŅ_v&O;Џo</=E;(C=RpI\W `rB>%B P qWqB ؀8Xx؁ "8gr`%s* r 9Ȁ= рGI^EG^I8J P g evp0 @ Q8dXfxhjl؆npr8tXvxxzhQA }P(PXL( q  (xe8SPag؄  e6efG` ` ؋8XxȘʸ،8ppF< ؐ!`! _R&vif P[0bhE0)A0Q& ّ "9$Y&y(*,ْ.020h " ٍF6ް> ґ  LYJ~XEb2qMb~g coeo0caoɐ&f q ` B3yxz|ٗ~ٗ8ɑ8 ɓ>!iHٔ.yQI9~Y5hPgM`[JgJP[kggh|&FP[F } P`[ @b֠ Y` Y0 tișʹٜ9Yyؙٝ)b#Ή" !i A 9Y~f)lgi[Fgy[goș_0͵yڡ ڡ♜#Yɞȉ P 58CŸX~kjvojoPiXVHjPjR:Х_`*^:dZfzhjlڦnpr:tZvzxzjQ}ڥ,>[c%1hw !]dc ^2,#wWpppशwqV\F`yz)bUګ:ZzȚʺڬ:Zo~XqxpW :תi 'ƫa_֚گ;ɊϪzWo wz[H:wo qWzfw w;Ewt*,.02;4[6{8:< Q[ҰUy pxp شZg!OۀQ;𵁀d[f{hjl۶npr;t[v{xz|۷kx2[F.-,#Y !L{Z+]{OKivuʵ9_d+巤[{ۺ{;KD c/./(u;zpFÛ+;WzwXˠ˼؛ڻ۽;[{蛾껾۾;˽+X /XvP|vzvP|iwvpY YQPqСX%G۰[E.l\ D\K,I5D\F|HJLD,# 2{˰.~up^`d6IaxPde|ƭ$ ž(]žAS|¸W̻ [|n|ȈrjȎ Ƌ0PNAQG,d]RX=*m`="'L*F^,R.#>=Չ&.X^,0.D5N'hM1O~K^M>zڽ\Np.^glnn.k%>~T~ ԴUd6Ncig=2X}>.A">=~⽾m]e!`ή0Ԟ?.~jM!I;SNiUoM  ^WN/ A$njdMQ-!] /ޒ /M EO=>r=i_In_TOP:XZq)dnFk?Y%/tvzB``-ՅDJ?KpN`vg뫮faOnp*j?G@ DPB >Qą!,^ĘQF5EH!H-jտKc:n];~Mi :QΝIjoLFZj֭][Ը Wk6\8i(G\r$yU k9E!on@4cZn=<Ч{Q25ڶF~! -+辯}0k#𒚐;sl=K/$ƨ,1hg:ɪ7cɰ$s"/8vG2H!$H#D\rk&!m8)+9+2K-'>PB䢋ğ c<ž`1':о0/oPCЍQ$P-Yy B*,̕3/)B1I}ѿas35 BNHW_6$'r*dYg=/PDO[2dqVA?Z k1̉>5Pj(Q|=k,:&̮L'teLrq4Ĉ;wUu=gX1[XW[5,W4wdOF9eWfe_9fW^2@6g~VZ0EDqI6mK RKýaVT³v ޙښ꼀CQ(իʖtuQ1?BXZaQ!:-,$6i\LL9Uv#s7s?=tG'tAt9r֙J〆=vٓl\ QJhi`NjF=w׳|/{?mm|ƈ{znL;TVu0ZYZCvN*]Y; 1yBv@`@6Ё`%8A VЂ ZdzA>@0VH  hSKz'фn@I$W3+q[W0x%#%>G{rJ"#$j% PA$NEO~ӟg! D'!d6,yMAɟEJFHp@EFNs1G +CɒTb:p.`&3sEX}+<怺r 0`߃<Aּd"{8)ȜPNe ԺVխok\:Wծw[At"4@@Kc6@m  Zd `n%F`ܲDֲa#[cHK*`&T<ҔL(Ʊ9rFlTS{^Z'|-K-`ԴΪ< /UZ$_eQ:D:g0TN݁D,I |(c+D$G>X,A, ,vǀ*,&Gg ő||Y_ĐySb̠k + rC40ip@ DR68Wu(Ck[ZֱWuW_J$|eZ` +b3#Kf7犳8)lZ23ųK}6g@kmp zC0ե(y*B^*.81{Uu6N˹C2r 'GyUr/ye>szP]'V6oҢ r$MD5&YJ:1RՃu;ڡŶɌFhbsO ],}RKFw^aN14YLt_>i!r8Kq!ҀRvqsXmG:uԇSBa5rꦓ 0EMZ#r.|S z&ue{{?m{,ԴN}i6TyVYw=Lv[#0aQD~ #mE;wc2Ha07#ᴫ?  DTdt\AU 18jP:z6 :.ppsBHr:5=t=僾$>$(,K:Xi 7s?u@ v%R0/k}ڿb꿎`eǻh" KoģG; 81; <=*#4x82 YZ[\Ԗ;qI7 <48. yɤʴLE.SfSJYGT80Q!m"-+׌SC`,Y% )=/}\_͈\D](_M` (ݜ R.Qe [Օ`01&263F4V5f6v7>c 1 :@ض.VM .ޔfIY!\Y7JQp|_"^88bNIbR_.qYVb ?ClV4ؽ8^_`c9eDdVeff^f`>ڴa;ĕAB~ӹ|UdF#vQ]QK]!~! .8P Ib=bՋ^3bY~(ӕI\ ڐ艦芶~ bc^W܏vWf(1C^=>Ƒ e&6fUdaj%g$/{fgt MQ ~De!ew<̧5 zD즅b. 6F봞hV:鸖& ~uJX^|û汪iC8Uq>A4Z\Dj,jMXf!vugwa d Ai||Ӽk amkk~ki^- n!BŎT8l^nîS[~^& کȎN?gЎT!Ҏ< Rh^%A4IئPIEA ~& p/1.6hÍ8qHqvk;XE=S?fma ^!lJ Q2a|ogٖ`5g6$ _59pvΊ/9./?/.0yq9n._ .~Lhm Yn2yr!86己Y"7r|QʭEjnS8W~Gϐ1Gl^l/ a'b7c'89p:wvs qq0@?:BSZD`tRqٶo- svYQcoH u0or\c *YOR4P6 :+~ d'eJf QPG?gg v0yy@n Nis0a*vfY)8R7uvtVyzǷ{W&@w grjfT >0xDTzȫ'|yVVB`w|oo|Uy< Bmlϐjz!mq|qj #V%=NoN'E(ՋʂQ9턧?|5uEH]{FF;pP|Z: ^h`_ɏ| UUWj|ܙ$0,>Bpp‡ CP$rh1@D";jhrB $QNTRˌ'gF>> q̕)8oy2m1RRjΫZpTWۧ1*բ[1$χL6R2[VdٳJ[̈ڭkOޓ5w#PA#k34ԪWn5زgӮܺw#- U,Fa!C0o^dH ^Sn:C/^8/UWK !N^=c0Sr2IMhfׁ@d`#uUV`P Vb#Em!!NWpSNaX;@UZ%vVO<%Qeouc]7w]#1ȐJ(64Ta>WD3c-)E9f&X\AfHVB}y&i&m&q9'lk wDBzC@'DT$CiΤw}Ey5Wmu K iE>%UGfd¨:фB@2Zdm];6E"N蓊VԋiuۖTQ1 룅=蕎 p؏ GYa9\EISuJ<1[|1w۞|guTL,B\ mAI0(X)q*ț}J[E`P7%0: gR5&8,]:l5۠}j+b2vUܲMSb5%7U:VTߖxvZf>}m<0 [jۯK!XCYv}5L6怕2:饛~:ꩫ:뭻:챧ƻu1j P!sA?BP=?S61,??LC .UKI,FvG_%yXs&[&<'ӖiYlOɘv> [(B7HkCx Ek!"ɻx1-~ |- `~'rbؾ53v0>!(!F<"H 8ݟ g!$G-zHB,dI?(Bmh b Ψ31{'ўlU pGb!J'mhjJ_OT1f0 0ҟ$ m-m-"A\~rH` :a}nv*(d, hN3dSгvn;&6mr&8)q\"oD QBz;-nx[8(3.!tQS8j&Dž$xTLGQz!+ ?X!r" HbUl"%ɒE.2PZK)`_@8 qJ'?ٔ(LbDtL)`_PmSPfFUa0XLlG"yk[*׹ҕ!謝:q"DEz3]dHP64[OmQu}^C;P4=.`EI}uXF)C_-hpH )=3t EmL?u~5iFײ:TR7eY)҄-̕FCZUd'U[Y5*Ih*#S\ҷ걽!h<ְl`# =IbE|ZVo/v2۩hKB۷?])]8ڏnεy˺v.DqT톎r짂p-eUc^2Eߒb̔iOjjk ѪK.L& !9jxar7߅vf'i[cS%KdRY:B:Pi"x14@DjfP\La'kNYPiӭUDh NEk!R {-mgR+o^rGl!S|%V^R/L#͊9W戞9ͨ<dF)fHd7  reTJի>mWNjO9U_ 1sGhRרFxcm})QXdO*ˎ+EkIho_H7p{fa1n8[1'>QDE ^,6 1 @Բ tvyyU6xHZ5jY^ϴՋf΀SЭka-Rl4p*?[гu(SfKG5lW4?e\Mu*վ]fI{qABD8SҿcQ켙m[Hca үAX};@MaHEhlkXE|LrP4!Aފ\܅㑙X-UDU DUMUUU^SHak54MlC2@ #cZV*U`: U>fSBh`ւ8 4 A~ARL(ui)[E@I A@fUA?bP&4_gNL"iNe$D$,%dT5aRb#O uD҅#Df"LVbH!V%$j[>RkĵR- Yuxyb_d^Y%N*`&L,2e9\b韤U@JFh}R>"M6ij&h]&g2ɦԍ٦_&2%ZqʩTޘe(r΅HVH=cuZvM"vf]DeYQ֥guD~.%>HƧc 8 (Q_Eޖ>~*V5?a-B1rD#) mV(\RN|TpqSpeERE#ƨ FZVJbi҅wvxHyrV\8䈚 &]ejIigNiYaIT]ʮh&jV 2JD^666%XlXh贆 c$m4볮luDkk0gߵO vͶDn(RlGLpĠJ" +k"Fqq!%[զ^" 9jA*>St'H0l`xegPħhFdʭ:.T|$_5PZ6u,k,DAAzh\)V%eJHlSzFfNВv9 &'rHZErۋZNų}*E2!\FWЂ'PTFQ]")u*b)Ud5HdEf*R$ t/ʀFa:FER apeno),)!!f6N|(k:J]TâpW^Z*b*a[q#Rb؈ְ0o?:omaצБp_*2$hԯjO.E <g 0pl$4QoN(C7jpҚ\p:*RDp` 'C0p _l5o:Rt(|mG# V$cXb1Yi'r/^HqJ# s2}L0p1+_^K*bVpWE׫Сe&2ۨVa.Pr"K/T0riTsJ$ó;ssS?21$S@;uU&{aȜXXA0D8=Z:C@LVg*5]5BMD].o,"_Frqk_\ 3mѮЍK^K3uFZ p]W玖WpGOgT^nT:0;;uG6%?2=W5$K7w*'B_> ^-oF#6oFb3R8pR 1IS

Dm*t]G.֬wbRrI}3 tmvM6Th'MWtΥxf yzDPAxR (7n [BĆeVT[#w[e;:V-7zȔB7z= lc L#cOAGlw{wE;9Ea[GN'o~ ;[9f+4GMcP98Zּp5O]l9"c޶Aw%Oz\=zGp׉Wzpw\a:jDXx/[;T[MQ-`u/:}ї&G<ڗEf4تD]Ց7(zn<\v4FwV}FRnї(w^flkInie\IE<=hOz;iDcG 0Π8G]H}QS}X}O/`&y U}Ts*S;**t͖@!:&̘.L#Ŵ'꛷ȳ/d7 "{@| r޷'*V(9^0gPOFf-=(:!G>zШ=S=۷q#-߿@U})@$-\uֿ[X@s2n{B+ KfǗ_Zq_ ׯ'f B8a*p-yl6Hid̢'(Aľ" #N"I%zХ2)"(&Ơ~4FZ1jĚ |H}Y} l%},b̨^:FL*CP1%58sR=6YYpr/L+t!pBHOSN=mi="Z/Tl5$$ïcV[Y t075B%S‹p$N$lD RK.-R]iEX*cB1~ !q*rW$R1&]]pB5! Yyp}aS2:˄AKB n4'ŸJ4χ<&(=!sVWe-P@uCaeFN:p)h/M(e iN OࣹUXUg 1\֢`b'I،ʑik:`渱o& wpUpm5ޛ5_0)bX&~I{,'7!n]34K{Xg3nj:[d/AbwY6>PZrz?j&HBT[""֛zMՄ⧞OköNnd!cQMpptC`6·NK\2#Í+/܊Q8pmM䵕$4ܾ#-R)+2d`%1& nM){?`y߃/'z3cw=AF{3B&9<$⫔uG*a/PF/}_՞*DQ>kt W&I,6mNsvd=0mzI@IQn(%=@#4,EL ք!B:"ɡ/刯 +-2ݔf;Y'kc9 9Fj8-ҘEDxyl'wC!xyIO8R$U.$@ j!2eIűeM4 tMұro &'HD*iHKX (iT2p)<17-e ]iv/Ib&lnlj٠4*ZL>ϽNFpc9IRΥ ٹtlZSS).؎i ]6ӫXVr=aHIA լ]Z76=1ӣ\,fWnHƿ7*Л^k{!r7Hl1A%W;eޤl-Qj[KSE!!L؄|mb+`ZY[ZLk临VrsSe ܲu\2"ܒRfy릺["wg=΃|^oá(+_X$ )x c3{Hc0rg: Eaa+"3b3 *\"Lab.5$x1}cDȓUsyB^-w72yDdqj:eުi'qO+}NZ Wpg,q+[x'9͌ 6~vooQy#/ypQ~/$nd)^ }'ЪN1bPnv8$.ZL͈D1IēCD*oOL('Z&Ə) - F.L&a.I2/ tz+8̚%T/.!pO7ʮz P$$P?ڮL d401JϓFFZƩV nDsl)'/v,_/Bq-ŢNPvR 90 OiJP F1[" c ֐J  7 M+Qg g 'T vE]Y$CnaXv"1L%r,ѫF-gUKtopG[J1Lj m@ b҆QCgo(љst0[oN5&pʑm8YP}e AC}L 䋾K( +)RzFˈL ̹;P> ur &R!*T\4r#q#瞱$'oNR0.8p,kg$m1'"3|+!Dk^53N(mc g4Q35O)KT5SӣP+}+ʦ 1ݱ#=BBu2%\-6stP/GR/gs&P21א&@G$< "f졺 }5fOe b?Wb??Ti4T3=D4wgB14C`@4D@5gF24EUT6ma 7/F{sAx!g]*8 /9P9i)b&ʯ\Dr^ĈJJ;&ʒ0F2ijsp(%}tB3>xÝ~"NF?}f3Tx0CjOOKe5>G OAW}*>$4F"(@ !!TOTDMU8UKgEOkafTCN6BqBQBJUHdT!3@?c!_PCfU#E'6N]iW'W!qQcRZ]!B"Y`YSp9\إ@x bbIĄTb52[VŰQ%YтHN 2lmsO,QCOBpO3;TxC3 o'5S)b5c5wq2V>%SkfGcc?9bda7!VMNU(m"pV8\4&`&{6^Ҁ,5LZGP2i iQY\T(-*qJP\|h0Kٖ֦/e]Lnϕ2-R^1>,"s`Oq@SB#I5"y*ʺ2_A3J30W5NFH>6(Q>QuadeW_)lTwwcVi` @jxlxy}u1Hth4$'j3qʥ!@2\җpTll!(  3!^~7\ ]Mƴ0Xo$Ivýs32cO!]=ݺYkThG"9lw$;I}mo lF !, a0!ƒ:|ĉP1D/;&Qȑ$K&|&ʕ,H '̙4k|ePC[fID`С  KXV!TK$]?l$9V6%bkXlMH QE'V|a߻ ߅BT08q߿]<\rjKJ s戟#@An Zh!kѡ:8@8G6°%c=z2wb޺{~Syaw}OTB[8v/-~W\{!@fN D=|0l}ia~!J-Ks8Nb.HŅLr%U^{M`X{A`CXYgY_~tH lQ2:̳Vp 5(caI]p)v?gIwu%Q[_I QƆTZ$o&E0 kHbK&ֈ*Jګ#l[$W1ݥcc=NFF1qPyBfte=jIѹf&]jzJ省F !['v!C),աC%!B̳iЪ#UVJݻ J*}s ZJ:{:Mt: @J+#z֞࣎Pme*\M!5${L.7- v;oBhvBlXxG0Cw~CD;hN;~ڥ"lkS2L{ણ\tcs%tЯߎIGf㶝.yfj{_=Ah/@i}o wn݇}1 ;p-x3W[9E't꣐jǝi-d 9plt^A,&#Z0$}7!qgEZN RdHu3Ğ 76rqKS:ĴpXH%,uݮ8Lr0,@\4@=f vI|a,kʭ0)Ye-Hk4I2xpv($!c"BqQ )==WKa&ɄϓA2nN* J9ѕ탘3y(.]ZPFL3J*]3S ~"<a)3 AZ8wJVA"MIAA:wAK=8 M UUHe(Zj+!'yts0J$$rK5/9iR#">6LdēU^|-/:nT) HCKSq@Xϴ1!b0t:ViIXo3+ĖKiQ`*V *K [rݧb*Iq\2=YrմJ*-[GWBʕ]OȦu%ts2,%) IČdu' Plx6E\`!_YY'T6s!j1yMH+v2~Yv,/klx<#&QLE2F6ߧZ=>LYpjְK'~S@f޴tM{q+[j]CQFsR !:g*V<ŔK{+ML l@jL+o-:h\wj :'a¸h?ҶK%S"Fۛ4Y7_;bBL PGܥI;O|~^*`2BAxKe, `) kL*kSx+1iSqw&ܣ}rLEb: Íܫa҉Wz1ɕy˲|H,ˌl qRL9mGbޡq”tb͈-,^˷9 ͉H9vE1ƥMLʀϯ8Gѡjӗ ׷cXDW}!@"8k w'#ݪ%c:!.[`'rD9(* =}$U]]vTLVAvȈ8`B祗e \Z6m\׆TI &Xmbu0LО$}qxa}Gc YQe0"!EKaȧ܊\)؎ WYӸνq=OIrǕ\%]e^!]Qf]%U}zفkl3UNuz|[rԯ=B;.O]͎!PջƧۻ}pd >fv;1>z[d+ncպz16M$54厍=I*,9HG6dOAڳdT^ߍtp]୽m^W"Di gl -/ThnfSE.I%9n (1'֊aw7AJhR#!WM {[e7Fڍ_y76'elDs+$z^]q- \eHnng33)rNG!K1@-?/@f~փ%,(Λ垛+8b ג QF܀˕zF}X8.X?WT*^"HȘNQ٤(JTvB nymniV]."4ǚ?0vn7/Zvi*  H0@\ȰÅ!J("ā 1^l#D 7F ɇ*p%Ă꛷oG/CH l\L?֓(R gb NIk*0Bq±b#ֲ@{S]`_[aĉ/f `zN6d̙5cnK&&J,z)"ύ9H܈/t@@99f-Cz<Mzoٵo'hsHױl{3D[#LXzҷ.6N;RfNғoXp ӧu٧'"o2 è2'Æ> q,?b"*5D0: kȊ 0TrI&|1#Bˮr -K<b>/ ? -8įT. Oςa~E ;CλsCSgw{3w&HmcU'Pae 0,z@j/"۩u!gj*& ]Yt-kZ^yۢ(\q"ep/rI2Tw]́&.r͌d+ᄘN̻bC-R0Ad;Pnc_lSM)5|U{_i zPl~¼'kWחu9,orKR05Ox ^tƦtTW<",j5;O&CF#p:Q<jK\U'zy{]ְň!3G?(2 p'EQ[\0C"<,()&LEN5/tr=t#Ժ%ӓR8ڑd$܌ 'L ir^~4F0y!&˜y$H{X puS U R7jE;ܽm]^%׫1~q'{IR&yx,o\SEwf[hOz'`t i Ԍwӹvmx [ ;;} 5XLRt&Gso5tIxJqJ4@tLw V5O DW |.FOh=|pZHRȯ8r_۲'r0LA8Ӵ鏌:t4kաd&zl|oXIAttF};SOk]ݏL>7nuK*{?fSlq4y7 kC|8X( m@H`+ۚ+[ l,hs %b 3! 1=AQXkrt=k5=)C[l/K:" B>7Rìk J>b7*:{S| BS򣙳ˬqI+004fkk0 \/ëC, )h8DFh GAܖh@L=cAɵ8A2Z56=.[9# >Ӧ7J?*|>,Ĭ.0C [x446L7/:R+7O2:JGrʡǞq5 8IąGԮD EI,}DHT\Uyd=Rt5S $D1(SR?[q7+O{4b;L8qˎx8;jKh l]ٕS}ʻӁ  @ bqoǪ55&CQKZԹؘ͔Q͇Y =*Ґ񶥄:+k R)*{zRo4A-U.ݔ.D01H4*\S6@DVd꼤xmC)`Ys}lĆQ#5\ Q=K׿iMTԅ]Q&PٯlR3X"zNZM\]ՂxJTCaMb'9;r0g]?jO!\Ƞ%銢PAE1yLw@?1HW,}Wּ2ϋ5BgK‚5Qɞ=G1QU 3$@KPbU>zF<uߍRŘZ:;3 `04DJd d2ٜ``}[a?Jkυ ɽQ8`Jn Kd{ ѯE䘈@! 7 df[nIzdVdf/d il_4me4`-d"NШjj+ j[xb" 2gWR.i*ilkklF}ik˥i8g֢|Mn~E1TlvlrȒieZ>o`R]GTLCqVjfܞk?B9ܕFәH(k&sZn|iW) 0ҽ]$j/klF.62v>0oNc{NÝ`_>ՇّH`/͏0fG4cGzjpbpvrpnC -V6iq lrPf,3FӦ)ڰRڞo 7;Vnv~rIO?e+2-_ ,GE b.ѓgn)FTfKl5R͆shysd:toBw}ämatK?IV\=PoNnAN&z)@TwQh3CsXnF0ZWhvN4^u_Fܢ?NBoCWf>wt.;Ys%P+D9aaI=\X$UFYEYfLw=-„ Gc#e`evtYvrȿ?S '@Z S œޮP@%^y|tT$Wp07Qx|Uje_芕@ Xo\E{'rc'ք"ECG?K?OoE{ZD7Z?@؀"N h|_||N'#vE޽Kz-m!yN|9ΟC.}:;^g캸GۺAήowF>8z'|Gݵvj/{MkqszS ȖSP"8!8TD7 a( 8)ꤢ,Jű1hsHþA^ .{K mmq߲WZ lTngn%<gֱ}Qs (mrٵdމoF}}`:Mz;M+fzOeX?Ք9rUXUh"4 {YL+|W7Ø3>3|G@N eGH7\9=' CݺpybxoB [F[u"7Jg| ." pFfޤFZcE#TK4 g)&S9 AFEMt4rx:F #K F AMtUZUR)G+@W< yQgFAo#(8 .Xm6X֖`DQ\R֟Bhc(4Ï'Xd|> :N퍞Ԗ4&l-|fiѯ3 A&&Q6Lj! i': /l6^Ps-Sub.2b2cZQAs0hCUaQ0d, 2qz!Z(='P\-gJ݋ WBvOԆ&"Β4iŒ#+N򖭱 wAjy l"!> ش0fZOT~*rTFSFK|(53D@k觙YU)ԙ6ꏭuPZ!-[WY-TP7"X|)2KZ>R}PmzԋKEd vH,gG.E1y{7/}k7o|nd˅'U6KuNy@- l, 7v4 eKBGk5lڒ1Mh,Ev; .~"I3iQ'nvyU!yAT<&v$v^k+c9Z2cZv䒵n8qI5[H[:T/xV·8ҳ%--^~hn52%oT q+L'-l/3?h4kwW'}WBn>]>_~k~wkP."[]bLΚ`*`< џy\zD9!Rj_Aֳ ^O1y n͟G,O` ᐌ}a!=I]q NbE"F  .]޲Iˊ iII!`(F :T 4_!b? _C e@_>|. ^!:e&^!a)%E *aI]fM+A!^%e.bğ z!) Ea 11!HX ء&7@@\__c'6:":㕉)2Z5*X+8aq̢n} Ա"/&qL UZbU!բ nc'?8N#:$c">PaA!??:"NR"SZYBEz5dWJߗQ$K^_[^՜l"JnJ[E%d1]c_d=fcUFb.f4fP"Q";d_0e&SR?"a=^"e"$)WjfkfHvlƦHm`D_A Qrcpbgvc=EpQaof#QgNhs= 'i&j"`ngxxbllgWfz'C'v u"S:'OrbSe%fe$NVbP$f'@~"jBRhyzZ(zh&_pqcOh>vrJ|!! >Bef^o*!hv'} iahhJ_*ijHcƀZ:$6tܧާqgJj9ƓViʩzi)1꩖aTbNz_ R"c*jNg?8c rji2]j Hd@66i<((x)wb%ejJkzbLjkmDca~U)h:hXjzT&?|t B(Rh*nk{*y2:ÎJlZlVk],EizzȒe,al^Ȳl쬝,blFq]A#;#Cr$;Sr%[%cr&k&sr'{'r(q1r))r^**+r^q_qv*'b޲di!1o1Of#pJ*v6q"&3Kr4K3Ss5[5cs6k6ss7{7s88s99s::s;;s<ws1Tq1533@?S,k#gpr24<"''st!ް9.W0H44$tJJtKKtLLtMMtNNtOOuP PuQQ#uR+R3uSt1N@TUGuNO5Io*4gCg'`geCޯe/GӲb[胢f0A^#A__v<^vaa#vb+b3vc;cCvdKdSve[ecvfkfsvg{gvhhviivcT?j6(6kSku0Wnh=ֲD)jҨ W'!GsVB(^#ATwu[wv#vw{wwxxwyywzz7l׶ldv|Kmu0DiDg ~F(h"'#w|*p3ie0t#Ccxksx{xxxxxxxx18&|\xWD[Ƒ…Y!VM^9f9\3jG7Fk5894A_Pw+u+yz z#z+3z;CzKSz[czksz{z;?yG:ne:(y0jt"F4du*w6&0q9RgGfU2+O]Au3DAl4AuCH{{{㻽':yy{Ɵ:+]k7FV|>kg4ҫ2fp/GK<=X;HALx;4`7}#}+3};C}KS}[c}k_=>d?^==כ٣}ګڳ}ۻۧ}1Aje}ݿ|WlAÁC0DA;DuK~H>u s~{~~~~~쿾?&>:~8>>#+3#1A;@_OwE$~z|+,+7+'5=K> 4xaB 6lχ+"B\V\@dH#I4yeJ+Ytd16&}#s`:ּ9`BC 90K6ujTSVz+W`vL09c)%TrEJTZF0)dp` 6|qbŋ7vrdɓC;чc 1_z@#eիYvvlٳ]{Ӹ'9 lݷW8٤Y7wz[VLSvMfbʈ#E5+U]Fի~|׷~ Y\le!em9tMw]%s'礕^馝be OօևU4o5b1]`y%]J"|&"te ?_%-+pM3nB9@5?U_]ՋcApq]4v3VbVzw>zߞ>qO%ަKȋv=q߾?C7/LA&)zA Lr(=,h>PKp/(0/IhQ=Pn<XD#ITD'>QXE+^Y"DvF(>D#fCZTF7qX =LhyH͏BC h#a Nz T/`S,f0R6A#MPRR$T *"J^2L*oє4YMk^6Mo~8YNsT:NwNӎ,#Omγz'=$V)-_胁n,%yM &?HрZTD{ˮS@iYR)UJYR1LcjlgNmM*s9 @(M:F.5PSVp!JyZ)LjpՂvԣa!X 1R iUZVq\ZWy^W` [XUbXz ! +@P6y,Y3*hV6ܨgZR%iaH> F xp[\Ur\>ѕt[]^v]~x[ -z^޲׹mgoVYaTaA>uFK ^п~z* oEj^ _9a!I<;)VW|1f{ c߸4n0ZNzR5R,d KQ -/Peщ`5+N0e/a\f3iVf7q\g;yg?ЁmCщNtF3ё6I!75,Sǭz¶lp Ld ;GJRެi]k[׹65ؽ`Vs!•BЖ.!<(GtJM}5e -5W_]o{o ^p Wp?)^q_o`(;K*9(p$W3i&{ I8r^>Da0H#Љ^t9ʯ~l?HM_:ԩ^I=]%%ъf.|<0 dY>(Z |4LcՖ.ht uI{@ _x*Mg:}x7돗y^9yH_ [:UOPQ|W6zI?|͞+7Y^]|_?V *ZWU{+/Oy܏O cׯP7CPWOFV,/;_?pgMODsa0dcNh 8! p / 8 h~@(P Q@& p`(Ӻ p(0 NRD FU&?Q=QA"#[_cQgkkFO'}Qhq1U6Aq.y/hMA 0 b.p + ۰ Q( p4 B p11oRa("/#3R#"9R#?$C2$$9#E%SR%?R(Q&+r%g&3$k'sR%A'sq&{R('(u2(Yb(u(*Eh$`   ++1 0 ǰ,Q `-q!!8"-(/s)1&_r{/l$ 1&_Z1K*Q\3U`/1C4YJ'cq4;3Raa 1qj\rq*{M3q`TQ!t3a*{E3:*`{ . Q.;+ rL1TpL =R( >L?LR!S/[ t0A1A/:H166qB8KK0rC;2Q37T:3OPUEO5FS5]hnA6ہz9/`TR'SKs)B5H4Q{mJbDJ{UAZ3Z52O.=hMR/MT<O uPT_QUS3Qs4vRWCG/0=`AUK!rYKsFu/SPWEIAVaa֡Vm59MW%SkR@TT*WgWG3Y@e64BSZW4S0Vj- `kku;#>\pO+[plVO./U<Qh`eURa)!6S;2/6&CU9oKd[d;sQUeU5Lf1WQmg VAu8x8|66MQYU`s36ghZcXjeW[oTh zӤWN_n6\m,w|M/o3@TvYup5Ye%a+q%jb+2rT4(r""/T3747WE?EYhKHWQu fvS[Qo6#a v gMXMqYUbs3GsVaC&#2 W(-z x>{Op7.P0-o}Xu!2pvwj8t~qXq 8y-րMRO/84;iST& 1tI4itv76W=6TSru񄁶x{)(/8Weu6WbSXT3vj5Tzkz k ku|85|7nv(pYmk8؋im5Byy`su(xW/5=q Cmw1o9@ٞ[Dcwiy[g!7 _QeWXv3FWOُ,Qyq?Q&<\h \]VyuS g,vzj85'M@@U~W91x(YsBUBK3HkIўbٟ_QS:$cxG:Z!'fwkxv1zws!/ۓS:%j{wWٚ fUzwO嵇y"GXzvV#~+[حِs4:} IV%5Ա__Z3hv86l٣80Z[a&Ye;<\/\+ Q_ux~ 1 {K{#M;v3IqmY9{Mc;OF eE::f987W9:gֿ/p5vaճJ;< ܶ'\Ϋ׵\|eg{s[цĽ"'7BGUY:eqbFW1[5gQIQtCcɋ&֭ g9R% Ĺw:xŜYO[QRٜ3<\ lM<HTK[%ұtpq-%!ӝ[33AԯyW:gt[O/׉פ1^I?Uw~YKiKxُwa8{>w~s<۝89}+ wa;7q38Cmځ瓞Ёۏ^煞‰ciݭ"BH\^BNmsi.@=73ߣtߡ1}W+>Y`㙾c.r;a? -6; B@@ !8@0a!\ ѡE#F8D._LPeD/s6Ћϟ@)gFM їJtTaЩTkWK,i]˶[Wh=u=p*c!D{*уnn^*(ɖA ;aĕC\f> K3f&he 5ТUmkӛ & YtɼohRgEj cV2ym?):Lt&NXbC+…yQt>^& ,`sAat.0wsB7:C`JНMgމQ:ĐNJD} ԵXP5T^A&+uGfbA5=tՔ[=TJ=EWVniTYDST%VUz%eRYpqt]VZ'41X@eEYjŅXoz#Q&XdJ]Z{Nj(~JڙBzGejR tJ‡ݒOx>>=V#{HlH*BY@N8 諁@ \6]xotN;|FI&Lc1 y94p.A"l-J$&ԞI^kQ0U/wrR}fWc U36ӬUmffY+qҥ]u6ګ~6DӃ!JevcyI\3ݛ׃6]6 GGzk! *caˢ!lauA/X#u E.p72.҂.:Gg/sۨR:T m nD41/D8r€Ћ Kd?(o}OMgdhD#;)UTh(Q1jg(s)21(ԃE7F:m9y[B#dXJE(y!H4LeizG$=Hī69]S1|YuϡV0!]05d2 dBPAֿUrE"ոU/'HGp̏ ۀ@H@5$lD~m#`'Ô/eAPIJl )-=tKAFPֈZ0Z Y6F-]C<М4997Fs8>ɂ1{7NvYQ{"+aBO2jTvAǍ6Xtz$jQXnxL#1gwi%ǩ}K`pSJ2K1^nݳCKRC s-M6 2mx gqBm24X&Ġ ;MtɛUm+0/ݚlY{޵8* F&h\*DŽ"U8q(D 9yHktK ("5Ǝ @UHb&SJ#c1ejpߓ=&A ݹ]~ˉ0^QsTIk] H-GVX pU} LX$k[A`֡aRt]OJ ,gvkj ǣ`tYacP Qڱ}bϲ18c޴0E6-ׂ ղGblkBu¸XtzZ\\E% 7 ΣΕt(7UA-/^Z/l, | G7PJjp(Ɣ'Dja|%.U5 Wc!TeW;Fh#)jˎZ3I< ɬ&˷Oə[Ύp/^ :sly*3(2Ѿw gxi]B/-(2P2P® oMjݿ.ؗ6qy'aS06ݱiG."q3C;tɈmj{ٳsm CQ$3:Hwn7}o2&uR9( :~ߵ)oJhav<"NIَUjn%W-I9 _NʲD )`2~ éP> N{}kC@yMQmfu'өwDr>D~*;sw# OCwSk'29](2T1sIUEySz s@l!Sl/av{V{ssqr$XLBLe|74X5|#Vg& ٣iEv#n}jn7EQ~Evm.D~\&]*p ' G0-%TE7v xq3hDH1ah H0h_RLhD%@? DUKKa&arV:ag% ^W4d8ht8e׃WPRE8Q}r fڢnNxRQ])W7W:\h^:a(,U ^Q_sh"kh GZw" . R{H=2[y IUd@KCUh7V%`HJVTeKLkXzgXyI+x|@X?DH}Fu}\P\2gbhQoY[h.߁]xp2!s0rHCGxxIWEӎG 6>-sX@?fI>׀z @8VeaA YVk @J@0(Ay+f$ИבZ |h$ Iݷ5t_ Vx8g:=4)/cHfTGU^Ky$M <Xi#EhW)"y'@g8Y9ڹ$.*q.9(hqbvrfJtED)$l} j@6w5~I 8:}f]6nbHJ2"rܶ1S'"Iڕ'2+ 4Jy %92ȝ8&h%gUWR Gf-;i11ٟ Bњ+*:!gj3"w4SV- qV,X`y[ɎDʜQ-SL0Z*5L:́. DBZ QH* դ:v* wv;sz`\ڥ`*;U! ;IfCi#t $b4@ (QZ\y2^,Jgq :Zz蚮꺮ڮZ7<ꣀD5CxJjiǟ Ϙm4]cDwwjʩ m Ɗ;ʞ Zy3qyYvjܺ<7z4B; *c:蹯*}4ǩ)fM#nD9(0+A| cD;]ؗ0#es61)ubNZ2s D;MAK va!SO+P%S˵),n qo:6 b$Q:0wIhidE{0̚;xײi+2cr%rŹLiCK0F{4?@ԣZOP‚- E  \X[GƠ[ ."5;Z;v)Ъiۻ7T9;E3;DkFJĝa{yW YlmjKž v$*ҒoA+iQ{lFs5!Lv[* %GqT4akա;0EWB 3/ĔSĢ|&k7Q<rdB@a$8ƻi[eIf֒\g&[;wyܻ{Lg~l!v|%\ <' ѶA,s۱- E"Ӹs0=aI>>|>2Da0jHOE|srU:sbUĮL V V|˺˻|ɽ\&9hdy Prڬ+Rל/Zs/-]P\{H^>^I$JI@%Ą%J?K>a^0z>zwi(zpmSLb+ ْ=ّѧ3<ْٔ- +ѣY,OT!`\[#ffxEO`9_6pxE ԽB՘cSpH#²֪;ɗ̵x ,>UR5de3>s}=>1s={;V{ߚ n٢ P Ң?'_\#]1 l. X+;QpԠm,Խ1 #<m$K;h7uKX3Gaxl$6}Lׁ]aW~d*p~uP+p舾- ._}. =<˝O#$\<.J͕H\[HӮ́BiQ~eqD.ݏ|H-_M0TQ.A[ x¶KC?o>@Zk߸k'hتKO`az/xzN+|@QCPE0;ِ%~>$:\ZX,^LPa.5`ӽV^_-qL  ͻ ;r7ΒZp9^)8:\"IcNVR(g'h Usm6w9U~U*tnKAk@C0Bz/w !{C~" OlZNf"wXN;=`˜/B㹮* F4wܷn[-q\0c8|†.?{VOJ_r-߻VGzԐƖo_7q/@+P{?EذWipP+3EU  >Bb ,:HĘQF=tq0ACP 0oy%t)L0 J\Rj*dIBw-H M8z@ԝ7kJt֌BHVXE"kۆn];~_MkǪ:S(ҫ6 dѴ"тSof43d9nڳl3M6 XOAa%/dFq 2`팷H޹+0ݽFZ;|E0!5B#BH YqSk @W+Jh V / A#h;)G6I2N&l],QÐrATx*{²H!2R#&jg"$@ H3 {b) `x 4}ǫ4: L#RR̢VK2 f 7C`-s Q}R(}NHm59MsRn>T^ngEO=>qf 8>3H* BFx+T[6jV8 , $dDC)I:@KTEė2:s|G04}\B"7᱐L8܂,pl(?K3S5$Hq'CØUjN7hMk4Z"6-(58?pJ86 &i= CG46R鰧>K4G8;X_Y ` 0+H>aͯ p3Bzv4''i۝;"LWslcqw$/7{3E_>^&7XIb;RȋmNcuDf0tR%w٠KB1ޠՏj hzm~| -c(\?њZkЮ-N$7SGjkkF̝n E<ЉW} ߂@'TKC\`, ΂h+mAr mt#J80i&v3I_``:&r# [A·tnyMl"0/bؐ6ƍ4y|')0>DJv2|(S]r>d18˙aܗF. i E9JQM߉[ sB!hC҇$ Ɔ0V( 2[ ؿ U̐$E"śQ'%{&ϴ.(`H3Z<ȇځ7>r4Rn;bDesG? <$# P}K,\Wαt,15Q(+1)JU>`٫_Ѳ̠D˪2 -QA!%F(bf{ 5{T=xYӋQ1΀3tbbMQ}? wXWOq(V6Q.qXH'(mFU]]WAfTE,`B*R!'%H302˂>@lf@pZ ,ֲjzjL,:TZ U13jN\S)/JOk+NŌ̜\=Wc$fZ-\ / :ǻK-Y(]ޝWeo|S6ֱzl&9% xixAxԀЦi5Sħ6b CJ[WD po.D=Ή#s7L.eI8.[%VU-uW +\q/3N$ʉu2d."cc% ԼAԟ <*j1"-6bv9pBdnR@l=oV%-75#2r5atc#X,tu;ьb5[DdS}ӯIO$хuieZȰv=mjWvm/M^IWmֹսnrcG kc%@Ϥ5ohďQxv=/ 6M?׾~DLj:,M5[Y.fh&sk^_I: Y/k2ɖsuVa.)D DyPEE)+ p*Z4!U\w>8ՅI#ЉS\, Ţq]*&ZHloj0~m_W"W^ '\]ϗnDD0<쒦J:EmoxU/w\{ qȧX\,|և/AxU!m$_9/ɞd#$7}]tY !:7x 8ࢦ2ݫ&/C.sz;`()P5;>H> Us+>?𺾚s&ù>J:ͣXLA0)Ȉ)0 "||؈ Ɖ)#tl??Íqٰٻ{4T.*Cr@NK4 |* @>U.$53 # (9yMb{OGی,;HK#4 B"!Д-1&鐎¥{Hb,IAd\FCgI(pG6,@C=q)C1M Px"9ۜ?8ޔ@НPJl Tq^Kd,ԏ_ԉ8p /DR8C(-Fۺ* PeMzAP/% eںa25ӈz9XyhӰԋ4Qp> =%֍Sl1 ]:۠Hэ ,lTI ɚʡ朗cM-R{Tף:RLX8ϣLVRWR+- \)&2_7Uӕcd:Q֓=Q?V!9LHⰔ*UK˼rKŜWzm"ڨ}|(P ڬZ?XRp{3; äE+e,mƢx1K+EQ6N/29eRYk]`9tv&껯s@wg"t.:{=j|9\)8aŚ O}DkWVYg!ؚc \]ͳ&u3ԲeAihY-ZfA]WOףFGFg`TqZjy/y7k'z"+]v1|q܅8xE8Jj7v"NC}2~,POtWɾT`=rvVXST{B 4w\aRSdkD`a)-m_cg=-INĘ? r ƕu|?M'^9,.=;{@6ULR\P$3htt;_t kbEW2BD-vR񖂼gc1d:!Y74 gH£_ &6DjKH1pE{?LT.oma[CF^51RW0 K[*H*=*,#[T)H85vЃ|P7!>A(L1 AX"D\R)돭z8P$L*/S@EHdˠ&hĥDl7`3ijH7z1m&6F-ىBޔ Qeb4?6*# +&~d| HP=2b]]VJ-Q$'+e Ѓ2P+jdW"q jJzR6ʖIW$DDŨt2| =@}s5l2F;<ĜD#@HHOK)q< UyШ'@)Az~ukRjS.CLh.*ih"'c|X4⻆􆤁M12+ٰ3}L DYVC3&USs[l9q8Ru ;oQ}Sg)ug(c`{+Aj>E=cB^ Xv ʍ24Ѩ;m[moI\JVծr"6s(ωW8Y+Ir%HDʔw\V&^ *dF4Qj-G[!(PkyxD~5|V![0DXSՔ;S'Dno̓[Uﶒf%]Zʸ.EH I*]FScʎVaC&צKmzSi\b%*2S\hYt.LVy5$)vsAٺmK*Vʍۢ>K˅QHX+{n‰tl.>7mG;>rW.'(HJ։uBf`:b0ɡT놀XC숇e)VufWX!9EwsL,DD4Zo^x9u ܮA*o˛3>C ,F_A9ԣzQʬòZtя\1= ΐ:2c׃eJigܕ($Ρy\hN2^ΐ/}o6oͤsNn AF dpO\y#'Q:t3rVDzlEI*S0NbJS-a٭y!t>JX yW0׿ [&VE;6_}mkĭɗd Ȉ4_W.lA@opq4鵟 @8]]uYvA,WERLG UEBXQ@ vzׯ=ŵ qDy @5_p5+dB$/6~ak-H~yA=e@̉$xfMeKrELj\&_M>hE500#P qRpnRMSM%_0F5v pyu !"⾭VYD!Z'5E =-?[$^_J)&D -`F1fcBD0#f.#aYc(hZjjf (jCY i Mmd0Bx@'@Odo2 2T`PԨ/]11sޡ5@N Wj|Jc% = zZ"H ĉ\ Cu? AC''C(C4ZkNDQ 4ig4id$i^q$j,IRh4ɦM@3&Dof1K`Faj趔5sZetf``∣Il%N 9Dx|N) 2朗<+'X<%Ɏf>֩yBDdR(-NDp&^ѷ* lh X0zph"㋎=Of=@Դ֊R#L6v[Xٍ:]b !LqXc~^ҥCX V}")>RX(" %fD[PԎ ` 4(CyekBl T@O,ꂎ (l4@fC(@V3h_dblDT!6ݏf@heu@7r,)w#z#>2DDblvri"*&>X˙~Kh+}.6mC>_M*cRd DX O"hkkFm(^paL@D ia%68KO SWrF@u ,0S^ᘀWNXzVuix.>;&_:ϮNb) +^/S/,vY-p_|Qjm┺`vVhe(kuϿV؟ -H,pofL @r6opfFkt^ -30& ,8WMl$"YNZCN[0%%W{ Ң )D\jk .O-QV.`09 0Q0a3#^1P*KI1"qjsHN#R@I3 . qIPrZ;@kzDB (#)hz*[+Sܰή+-Rr;M7GTIoLVOULO93T*d% OI.! o/ݞ/yZ\X*ڬF3W*99:3EnJV2 [\ G '.4E}5kȅ#*oҨ7)Af_ tp_ AFRmGmE.KWefA|V2C*iMWsN_iiVnS@ 6ةmIr]__S|bEH cGAz|dI'QTeK%_`M7qԩӡ!R PFԡuU곡Q L.-u_U%C=Io9utt:[׮N'VL*^oޅׯÐsƝAx2]ɊYLeZ߼}?/fiaBK#p I3ñd007|یH3X! K^d,k58 󪧣i-O13Njĭ%xb#taA+;d hk;B0y`cx$ .#HHA6Ё!6ʧ&0@L vj!\8A LRHQ$d:C:UJFTZp.G "^x+""GI~u`2͉67L|k%wnB>/#c.\Mk*7勍t, t '&nڄ|{ EG8n\"N9 AJ@.`,y:HTQʐC(cPNjrhX٢R Ӥ_6.^"A{[lJgⅇYa~+!wCMMct8Nvk\jʥ˧>OJ jЙ Tq"L^*eG=ČBDRҕ%],bX$:Yb:Ř3D)6a UdM^sބ%ItsLzu.p`I8.-i[!8V.M ;p-$me[׹7Qu5]kHc|]h цhM,'owX:=@ѥJumY^3>(Jy5-h~)"<$Y^"BA"xM Qb/iDX% GNm4Hx߸:9Kٍ@Gp~%&1K@q_E?؍* 0'1Zc 1 qWtc0-k DG)]Za؇ U#ck Ka5*՚b [c+EP9p~C*6I3rk 704T*I[O^;oTc1ݤjw^[2|3LwJ" =#!vg;<kU ZQݤ@wAyxwy&H!<2k9-=hQ oUce5䅢y&z\J` 3v/4HTL/!fof\)LL0e2gTamhn}Fh4:/dJ-"HUtJ҂Gpb cAH/U"2& -"Ҏ"bLEL B+PoQ/#CBBbO~80}A cM -֡V% βNZO2>bdֶ&(x JR pn"nS^HhL\bEoP%m0b!q#R&(,۰((+Sv).D Y\Ҫ0lrҬN=Cq1"HMwQH$0)E.`! $M'l+t&qMb"B.2"Um0e¬&I߶P gQ O  #!bDx$&R(.+Omj,0V>/)%1cNE 1޲.!BAOdd., PHa)(% p:@PӒ1kH""փ*p #S oFK*2Cj&4r0>$!!}G|m!HꁹN g8,I:$nQR;(%o 0&$*J"C&IF'{noH1/4*(p2?2i39:$_4!Ss혯TBZBʱAh'vp-7$hC7D7x78E &9SpL~kMON6 7c^O'Q E&e/=g2Sk3BKDà$ok0b*FԴHh=$0U,n*Q=n4r>BUs5[SC!Pdv@2Цp7Sm+;ܧ8{lÅG(7InfcHdC6L5tX۔ =Q%)40k 3f.[pe5 "vj\wh;5]wriQ]{2jWbjOU%ovmGD,(O܉l'xs8τmC_+nen\x%8=VoOd;B/`Se}bj2t#prr 5gFWXDG\JNMQpuOT1w A^Hw=%7";*xVn6b<`7Pv;{O|9b.VdT:ojZ d/Vx&gQqgC)$FF.K8PqB+Kh78}A5=S?Xu1Pرr^BvC`PKbf-Xv> m v:sN6|ayC8ECvp^4bx{]Ά;&(,XO5oSw$xO1%(7sgwJX5n/ A7t 'MNob-!r)3t3_adX2FՈYu2l8Ιu:<ċ๞*YzV\Wa6c;ٓMQzДwXNm" WtIv7N>_g.ҴrK6)H%΂ڬX)ABٚXI&&!Yv2o]_·2Ll}969ΤF}$c]H#Md̀""{V>Z ow0W(]7K~Wjq~uLXbh[bX|I(f2LNuqf>A^q8u_ׁ8A)" :PXWbz99هx37L= ~DŽxyC$8-&v:Yi5}74ևSY3r*OǴ14|` ;'HNz91GCB<;lڨA4["}%Χ 0ĵBkX⏳ IһI|&(ecr wطQZ0-'7z[11u,y.0[y5>eNCs74!|uuMP[wZY#V\5K%'qs"s\YzƁb37Nwǻ5Z gsOCACK:1@TѱR*܋;, 8Bf8A1'|bا=cݭexـ 7ztX 4ПuR*ۛkeT#қ2kܧ |3!RݨYD+5[eidvjv}p?nb/$*! Qϡ;O=(0E:=1zT[K?yz]车"ՕG/>B%85VѶY~5,u:i[)>E͖] +@^V@IUO%zM=]ѲC M=1L蕪pq"s#iěw"<͎dVo '}r¶%.^أh]G.Gj6~vVsLZyB6B9Џ8{豦"\&k?]9ES=?;ຘ¥vςs+d)B_u80a t!ZƋ^6zhыH#Ev4ʔ'GlL(M2&ǜo СD@ҥL:e ԩTZ*J8[X=!ʖ`ѡڳi} 7\ ]X1xU" 5f\Š;&DÔ=:8x @ 7qGPv:f۾;.٦Iit6Nx9+U#sbr{jFoNwq;?cĆO>UT=noS6V8qE_yHAŠPHSQGa^xUaX2 u b]I_`IxϹ(fc+BFeiFnPi`:VUەZnYn6` wF̳O:>؛G\=)Uvqs}&ޛϞMv'{ | ~ ߁Q.&т NfUWԩJZ&0bY'c{)$Zv%iיi3]x Ygp.x',Y l^FniL+} AuQ2H(tv~ݝ )Б:{P;T6YSLQU~$CBBV SE+S=nDN0T"|een %7,x5@`*bM6z׹E pb{aNJV1[Puw-@0E6.x[`Y.lfyV\ez *)ZlBwk߁ǙyZ&8D $rE?}Sc&s,/%$Q?s,_t[m"qO~K?7m=KkC$T*UZju+Uu.Erh^d#.xn$l!lR ?/%\RKd#-Mp.!:҄NteȠ^s:Y؜ĺ*Hæ|LM>^0)~DŽڪJĹ4Dh$h|ԇ=a73?f/hvX&+Kȿ4RVWs`LH$O ? ʏPCJ|x!,bBh"<"?L.[NHr2-r -*cg At $iPI%Y" */RŇGY|m$-Z.c"gK{.>2/mD?ZI$c Ǖy~#?7G!~;HZKtIKd(_ SMmm*UyBSv" bY" .-S;V9q 167\M1i&b5b\ \⼙+:&F"Ĉ;atga8Xpsg_et6RLg=HF%XQ1[f؄1,g7 (Rzp)Lo4BlABD>!PG"pnH]ÖZ#|]D#7KQUr6圏▶DF& ޵Q.w^oeP~3, z!zƿ84aFG=ZD xzhHqyEjkǁ yO|z6"DGgхɶ8ˆlmx"mX#J&/7nL!rfpN|GoU1}R}bt}"G\w>7E{ v99Cuf\9[wָ-R(Ez(~s7?r)VBؒ7 ԜJz"fmq^zI{#vWtJTB p 6!VbL9zy!~7CEnEXXVԟB$4ɜz`o.`"gJP1hh٢uR0ue2z3ZYd%ᣨ(CJ%(gH\yz%S1tZI,o v~i195e!+Uʫ꫿ *JŚ))R)3aFj !Ȋ٪ʭ:تjjhr+"M{dKGL褵m9:,ٓLTĘ06Q1N&ve"U/Jh:{Xy6H\IL&j,J#VF']S֓Css"#&ɲJHZn:}ʼna/#Up8Y׆EY4{x3W5j3 {[bJdJ%;nȦَzz1ȷh}zʔ6Jz?˸e'x:gaoکLKsMY[#<#=yxpu6Q=1?.Z擇~Ec=i6y8+:bS)2S6S@榘 4=uB<@SV7p%>:=Z!Hb{  6hG"42֛+hk$5a#GSG12VtqŵHq^w*HVrE*B`!YVq>+!3 ۢT(D|["eQJ+M $Et> m8xɹ1kKyđ^W{o"x`t짜A3 {KąO4VYLa\bDY&Yva?,%6}?-v a0O =1w!5ʡSx˒z0)3Kd(7?6DvٍU'O;|2 #[FYJaVhN>&A$)}4܎%BC`7_UA>,>_2ߤ1ȍTPDkǛ Tq63q{4phbL}t;-4SR|p3CLI^`ΤY&M/2o OAEQI.eSQNZUQ5Z$aŎ%V!Ct8mʗ-9d9H.Ӣmݲ&\aĉ/f\!K=ks+*uV!^~-K\rrd:!f3gk>)-@Vܹuԭ(\8qnJ/Ϥ=Lж[D [tEc+@JD>kpL- H3\1-H㯦 @(  *rK.q0`ĐG<15Gt>H7C5qO>󰏊F1$Gl;؛@ԏE|%{);Լ*.K5.D406Id[1=SW`JC/;"Mʀ/;rmDKM?vBKTw\r5\t)uݣjw^zݭ&Nw_\{x` 6uj`}a#>&rɜLXb+A sшd!"dp>9esjye1臒m&猀hs$vi:emjz8kn&k@Xy9m Y9 6e?l/:.znan-Yq8iʕU|s;oj=G7=b|/ֹz~Y[]dѹx}ygo~v!om/vc+zi2UN~{] .=|MK$xywڟ☟8qn ~^P8l^ɨ7=^,x}j 8 {{_;[dH f.Tz; tdQ a(0 0vK!븈3.p0D ח3P2p@x" G@* m6z K<%zxG^|-y{l9͛3κ2Lꎬ'#vzM{[&PM&P P P PPP QQ-Q=QMQ]Q=Q`NxQ紘Kܹ %o8Q R!R"-R#=R$=R3Ѳ%P/( &}R mR*]؟.PR1a)2HSXS09 :m;- P!(Qd%8UHW QZų$Ե$TJTKTLTMёyQ"X$HnЀ͝LTXUYUZUJMpR )_u]  M:u$6gM!iSkmPS NցhVl-)6gm91<<WT#V`DŮ܅YHTRHWmX}XXXXXXXXX YY" @YsX~(|,hm, Y ZZ-Z=ZMڢU`|Z}uZuؐXem:euM׸zVׁӓJB .ӻz"̴z2ZY[q0M*t]SW} TW AR,O4#0WWp`c\\\\Еܙ Y+%YŁ ]ڭ]۽]]ZZ W}ZxڒحWe}^*B7`>Fm" ]_-_=ۥˁ0|=+}}YوE___Xލڣyީe>ު5`^ v ->kC][]`>aNa^ana~aaaaaaaa66x!VeaU]nb'~b(b)b*b+bCaI,`/p0. Fb2Η ~c) ^ȅ]>kЅ;._=.]bB.dC>dDNdE^dbb"Hk(f8@IodFeR.eS>eTb323cn4 -X6c]9`&Neb.fc>fd.eG`GTd hNfmfnfoUaYcX&I6c51`6fg7ex.zûg!g}g~gghh.h>hNh^hnh~hg gUΈh.i>iNi^in.`iz&"}i蝮gwg~瀋~Cj7nj~jjjjjjj6Fhkizn-;j(zjkkkll.lN(^l6hži^ &ʦN.6 g6<.m>mNm^mnm׆lN~삞j)l6ޞ߶m{m{m^nnn~nnNmm}Vz>ݩ.]J6} 2&ڽJS/ܡ-J콻30nNnp/p?pO,m2op~nx,ss- <6@q.z61x |3W;0nqq r!~g#w;$Ogo[ ?9:&0%a)',6&B)jSX Kӊqξ;U:s;ss?s@cՉqvEsppķ [6Wo2ӹatGZԣQrp6-4t$>Ӊ{3U_uVouWuXuYuZu[u\u]2Bm&E1lSzUȟ=9V;Kc+:s wq բq?'8w‰/3%0ӂhi7*ﰢCLJv1)nkWx}n;95pWwrt% svNr%>U>%GuZ6l8ש e'nOso(/p/w2zxyg%y"0%H 8z iWS-Zy77ozG-gi?;S{zӬ2UtXdOxR{ʯOwʷVzѬNwWrVumVF)RNGwV.E7OoEk%~|s'~gy[3ܽV[ۼr񶵈(Ҵ-ֈ?/o}W?o|\2~G~yֈ#p "Lp!ÆB(q"Ŋ/b̨q#ǎ )R$&Or%˖zPt)s&͚63<%'Ϟ>!QDZ(Ҧ&_*u*U0̪u+׮^SaϢE4-۶nW"Yv.ݺvZuoԫo,x0ac-.Ŏw2ʖQ[/Ξ?}ĢO'\z5뇒/Î-ifS9]s)޾NTd{'nx(+ =̧^};rӡǞtϣO~=?wƟ/]^|Αg\~ןx%WH^PXbrءf[_^L8 H.SԄt7☣6?2AYG 2OB9$SR 2UBi^Xr]]GdgcvOWh"n*Q#0#y5_yڠvGIIө*Izw[ƧO;봳o9I֨d"kUiu{:ˤ~'ԅ}ty֕m{nF [G6't̳z?M㤼uւ ,k*K*\Y <Ӯ3Ϯ  轎Z#ڬ_N*ΊBά-]qFHO7ef[5E7H? 07U0ۙHjsq2%2֩jǭڛ D >d~˗lp.15# qтNqDG/%W=%$1P2z".HF;E;pHdo?TO˞A(֡hMNW:ʡrrU`1QW/Qkt2ڵ71 \ Db\o=  Tv!^'21^AőzB1'D,&XE|[B xլ^CDr8\e*PX(uo[&plȢnldp$9 .= &1X) >2 [AxՈQ ?I)%HÖٰ:p1$.na\ :ӊ$$wLa*3" =mDTQ#Yv ^{ӵ!F.wzDyaA+5KX~u~/2 @[h⑏R)U%ﻜ#u+Ol/jE''E{eI=ҩ-^>Lj b=e/فsn{=q礣>pf?{:Sh4+NrCw96X OirVN$`m5TNi\S0IEuX :Yx FQ u[CՐM@՝A_t,ܛBYߟe{lߟtozGG_ GYKAiZ8GS4aPR!&., ˍ^PŜl&UXH9px%Zb"" ĮUQ b F`Q J\?A6 +*KdAb.z02j*-+%a)!.1!@WMc$I(@Y3Gc%oe GnG&I.uaXlΘIpH"EFHLDMdGrFHEBS=D82fC34Jx 43:@0ބMvOnRp@ZaJ5Tt TH,,@D:ةcoc;ǂ9ǾIX=_ScxP\RΔg%%UAAXBBRAkXdTF cJHF2&yG^R,$de\-v N.@021l@N$QĀb ,fN ڤ7T".0VQ-v2"2&1p"0l&-\@p`k/ds Hg1>oNpIQl' tCeI-e@,_^A![7Z8ڈheH9^zeX.Xc%"ݾ-[aYȋj]]^P Ae`&^/aEcjbNfc&:fH$e^GJcdN&en#ArfMf,c b.CN.fknf&&xAbif:iƤ/nN i/4iiG z Lz4G{zGq|[|ʗ]i#ݧ\de9_W(( G&5hpW }TuN?bCesX_AGåTS*l)duVaIbDhJ&Nf&&hݏfAinnro)Ob'rfqi*c"1z)3붪«lm.)#j@:Z֧QF~gUJU.@a]*zhF اǶKȥ_af(D=MpR_ ٮP:BNG*k(j(JޞhJR).#Oʠ@f/rR-1f횚-o 纖mF? M׎z)nmkw+ kl%_72x`Hj‡=VZlzأ aV洬~jŬG`rŭLEff.-mHHhIkBJ6D+)A45ثz cN)mJ^ܾkݎm/rT*,0%=.!,UP㈵ #E~F]] EH]nLnOX<(\v^Q n oh$k^H04I4/JKd3$k8 -^Nd8Ȧr1~-&V-ߖ+)֩Zny ` } !~C*HۉFLnqpga >TlJ{P`ERУqpn\_㐰𶄪 , ,uM ;k=- Q0il¦ *[) :&: 3V3"n/2'4o1RsX39ogws31r1O8p-Q(-j&lW"s=2|,$h%%GPdžZzr_(DEޕK*یD+3_JЌh _ҰrrM9oXfO~1 ** ?!@c@gTB%C%DzE{0L6d z #6ʪ`ϖZS O=5Qw8QObo HRXIbQѰ!v P` #^D3#Pss3L)ef!趂ɰNl7CXn`jy\h]ptǩv᎗E},H7^z'2^V\WVQ5REY"WTU]U0S99ƴy5&`J]?o8n~T_1ztGp_ł3:.ZCZW Iz], *5RzqՃc֫Spqq;512i'['㴙;8cQkyͥL'NA{xOyP :g  :{{~>z]Dz|uMax{,ߵ aO7n՘RXXUo$~k"cTHǃټ5P.>,;|b_Qr'P4zxz8o|F;҃0Kzc4UG{{Wֳ5N$f*/P"V{9Uچ4߽>{#DPr@H 1=NX˾c>v.\aB`0DD)Vq_uU\QE#I4yҢ+O %K"筳9Ofɏ#lOCBl(RGHzq A=F,ЅÝVetauF* ճ]:MVm&x%˶ K%bN߿>O{!S ePXWYf^xz68tl١_}wn0ҼxpÉ7~yr˙7wyCK ܬd2Ɣm7&+wn?4TC]PET(Qu#f QRIAcC( l"[(.ÃC 'jpF>tXorQ=C8*@ Z Ϛ1РJ@T9Pp#jN=*䨼LDzd,HO,`bAOTljV!1uVi])&P ae"Aֈ`PpѫHtU^]~eN9+wmGQ! )a) t\M\~>>QU>خOk\RA*W}ekc)rcC6.fuQΒBڞkJGHPFMnuGo]vm5_}SsvX1 /L 4`r]{7<(asĕŽS* 9ho9y2 AXD#ITD'>Cd¢J4V|G}Tf4AozZ]m!֎n#8G(Џ$AAD.Ah? h8ƹ*+ъ0shRQXXCb+j{Ip,i.&.yK_0YLcSSa9 494S~OADer=65J}~h T9DYYDk ǘ̉88ԳA@(I<7bMyO?2ePI-1g`YK%2iZS92u̸ Q@wFb6epbB>BNQrb|:?qTIW6rGl+=!T,2"}g1pgI;]IxR !G44HVÕJ2fi9S~mMyCf, 9ղ6gŦUTEJUa6R[ewD'I> !B v%  «!˯p(p@hZ>#$b_Ql}$M#Z$8u]~ώphKbgUk; [WmB۩j哌m|KZAq'z73!H+ݮ5lo@ܺm[c~0DҌ^j4=| Xŕ k^eD /^6Ø\f3iVf7freQ;O]` "!--ڈt[D'S>3"&P'1B(!8VX` bh|B:Z+;pk [>" JL gJՐ%ذA O16P6Dދ QGd#{YlHfQ+C6Q |RJ1v""]eK)Lpq pPUL?.&Q%̰@ю0|ѸYq(&/`MUK+ @? !0` ` !r-7 r 2/R/r/"AB.|/S111g*Ta /;#) WFK$Q:ӾB!XR)\r4WE\`&i&0Ƥ"R$Ⲧ"|ޯK'Rg),())C +)kcZi+s’ $!`--r4 0C1S.` !fd@>@T/!($2c:.S2S)Cd CRmxR%y$p'c$%6ȹ.B7P$*-B0TH"B@=C<⑥Q8K;T!|!<-<-3r>s6>!=`=ײfP@M@@u{Ƈ#gZBe-NE2.prn+ABTDEDWȠREDbEYtQ!]4)")CRr\JjSAq"Io54B!3KϓK!XKq/!1r./Yt nMMt(Y4 OAO]OE3?,)PU3bRDA"%O'R'0պm$7PF%!b`9xlU(H68`c/W?vڤEa|54@ SKtTV "|faXkgav!U.Uv=UvM ghhhU(Tx\"OǵV{\( A 5v'Vvvo5jw\W -T(oTWP񔘗y#"m-'qez-'I"SvS3n iS"io*7Vh*49W~xW!lAfA!`vNWgEfQ/(. ?Ev*XXe/X!2X6ҥ& ):>41PE氅_x%b"&%j8CN"wyEWHl+7|}K擛1Њg9W-_7s]׎m{P6xĵwuxQ+%XSQБ-ȅ_X#DQmU̺vnCOdC7SoUWHH( ξ, Zڡ:A +ڢ- D! j(`|L`CVªvFvb$"kL^4!uYy9(ym)RǹA$`?+SÂg6?V؜]wcmǚڬڡ=z(' ߮AY&Q/I؝ꆚ w(JO1 yA0_i>_¨HH^N/9+A*ySÚBc[g­lQZz=kkk<϶Dm1k`vcu"jZ'[⑄" pK}{Qz wNw״YI 4ݑ6Y\N۹^%-y$27;P|`Y)ƛb|9UT}:]֚jkn{|o9zS ? 4%9-*!9 ED:'55FU|V8”[YS|7Vg֙N8 ;ƩX31m"=6IT$\'ij̹b@:Խ" 7T}| ;'1AѮW} Gh:B4;]kXe%9Ef8Fہkl l<ì"7p3V~q3Q(T_UA`i~9p=M߷>%|Ql ^-K(HAD3:sw[+>_{aMI=$Ydōܮg헉Bbmm^ʩ (0 A%<A t )* @AVE×0c N̛8s ͎*\y<~! i3Х3DXH1 )Ne}IM9-I]Pu˲Փx*ܚo߶Z݆%;[+^̸ǐ#Tup ЅLi/V* p1]q0{ Mq،S5rdޒ'5UoPcν{N2.SiCܛN~mLwk#_n]}o,Ebw@{%W]uց$Bŕ%JevXk C@}͉(zh"Z 0| r[E"drgaUՂ YbA:Rѝ{mGޗ 6K렗wew($]e8CY$gDs0:΃$hpY)HRm=dh饘f*AF|#ꨤxA4$AJ9jڡlQD> Py2)QAh ɝgv;0IP9ʼn(T|w,^{PF\Ԑ xh )<<뤮G,cTLp7ts6T@5 Dɥ3CST3b% +|0Z%' q1IA&\HҞԯ\{]z5NT߸_粩PKLsx'JsTY MhrSdu{Մp3'x5{1m!C=*oD\rdX,ib7ks<<1йt\!\mݻ N? AijRYo|O2UZvw6T…ἵMуVCk7[6xb(ޕn.3kX1@&`I a"L`T !&X8Rݯt!VN ~lWv^(> ⼆-oy]֦L/=gWp4ݍ>v" f׶ob(D?hOk`jq `8HG:Vn P(sTAd;77ȃlVU*#AB*|>7R]d.dRF6e&$vϡ3)@<5jK'R4SB]K)l*KC4Ky#j)X25%[ԉ:XI m"$L8v[Fu ~= Rd\GX t3XV?UuHBP.D<|k]0QzN-rfخԎ4$ J+0 &KNmiqԊ$4( UFhH"psD@P\sȊ $ b%w^sCVf@djw|0/إip73^>lN.{˒ p"X"A,攋('y$[ڔ$"ptdV"l`V]VW8FB44bZzcn ,!D!,Q9BZ/{d(k;KH6[ZP|ӝHOyP8)ٖep 6}óg<[Hc h>## 1a⮺! *:Ox956Rc/BJcN%&}/-g /+ {e%#Мm;'1nnN{Q|wngSftrRLNak݄TOk4(xׅ7fhJk؊ц1q8psh5a$c^=8xdÉz{@xK&f7Krj=DÀLG#C2f/1`w ZXzhVh;)ǎSփԕ8Xzʔ˨H{r„Q3eQd)qL|xIͦ7X](4Y6!ؑ0|@9;j'k/JQhRxS 4!ELضf yX66g'wpiDB,Hu<9>* Å:Hqj"gȔ3QO '!Hw YY'(_*w-rV(47r?t8vɇ8Fz|BW`S"]e]cR&2/cI(I͗+<UqifQYmG4} }&9te+wiy)sZU'5E m"_E%YK;9q:y+I5qKdI]a,,mƒ9'E֞I'y7YQ6xrP@A#q~=P 9*/Z+x89e9T  Ñ] X8<3B"l)Pʢb&z Pz*z>7II#rIzdxRjU&aJj\ ьQ9J۲_񒦏AClaFMaYBtN}ҕ,7LWQ1Ƞ pغ A3uJ'az{+թ+ZLi_:I:R.ʬ Ef*'*}y`v*yZW٢,4h}謭X:""Ȑɐ P%; o> j+Gx/iJZL=xoCAX*ZZzuNgR[XhwD6etS[ry'{- u}78# v{0 p*o*ҷQ5@8,%Pi.(z\[ [Գsg)Z[wݑƘLJxij'a|ږr0GI67֡!om73NɀЛ 02%H)3,3/U!Q#2HZ臛2K|a|zȐ's(SF9ѦhjBV {f+C"[țw8G x+9ڻ99*}ޫ?zfET滓l٤L<8|Q_d e31;1Gy |K"<5ɡ;T "??Լkv@)A|g8uL1: DzFmF#<%y;xiaG%i<Ȁ*n$t sæ]zwc{JxǠ`rxŶ) (J䓻b/qe¼9+̌gM4NӌzNxO!O.,cSEAAGc1A#Q8 x+flCl(Hϯ?SʮyV܇|13Hq!{Ӳ3ɳ,7"GTK%w5aJ:^ݑQءZ}zE'UnG#g|v՚#[ϻ4UdhG؋>o'b݋]؋A#&4IhïVgMDטjwM4ON$T^VDmk&! `N9a65( qgk?@%!ܣXvc~m՚؊)n nn>O2m㚎O>3Q#%nMW'cׅknzK.Z-JJaNc~Ey^˖ܛ(kfjS皤4*ty9~HO X I~j p=qMw~&&JJ!]rL ~`;tgs6_IHm>?T:juS; =:3IGyH?K/2 g;]NT]ecJ!KZN~^gYk:2?o0 !()hYA'ys>*OÄ"ȗ`^ZsGl,ZX^洶vQ;x"D @0vڵPbˆN(aF9zxcB!9rt`uyReI=JѦL=}TPEETRM-BT+>-B,v֞ s&%ѵ'-|NdYh}Z["]ĝ]4YrA -'_T=Cv` &-ǩ1>X4F*XP2NwZ487b&8[q̖Wi[]5TxG^z0`%|>1-En !.k.!YlC5"lԶJ!k1L;mWcM`k+#ɿb.}j*oFrN%KP 'ko.+=/3L1$L* 86ߌMLh?S2B `tH )@|ϓ3 1"1 _QF\MSr@ 8^R3O#1vǺ&U%Cst9{.(( Yi3X-Lk6[muJM`ʪMr)<쨨a--P]'r_.%=ѡ\|tˆ*7=-CQ'SUEFי'ԅIcS1GdU؞R.eլdr'5ɖsXE9Pe}w+q vv[&hvLu7b7g1Y+RePuF`.|ٱ3x RG[@1NuGɁJ)SeȬsHhu`橶)Gh7s7Oi%ڏY?}7»KѹNYAm 9 R]RB*)*2(0%RլлRU$'NW(sΠ6"NZWh' W#fox2DN2hXś;UHJD0Y,}לXwv2|" ̈Qi=\-wW4:y;f[FjNB<-"/dzo`0 *5Uq<ֶtS~eg Di3wɘI^hDYʽClbF[NM~c^\)C3i@AdcKJt)N宠ExK'N㨃4bZHϜ#:}ޱsUnu|Wm@l4*3- 熜%tGG %1GPм|I}zЗ4[yXpXtqxOѮ?{yF*S#Z GPTr3;iA a9Ygu-/hz Er Zp&݊~vű+;z4}q?BeuաyyiT soHgb~oD2s>x=*{4e+BצmD6UO湨@z3Vކ@N|{wObvn{d)UYuc.R9#I3D@;ؼ(Y-q<  |Kgs#s=c: '#+ǰ;z'{!4#bD$dp7a &@8N 1@w$侮Cj 䐱KӉ, (#;?;J2rSE b3B^389@+CCAӘkslK5dCXsC kaC=Ü=A~sda ķ04?FF ] HĒɮSJ@ cDN$EbcƝM9N隤/4t쫍x42ČGy\IzǓ2!<. ><6FBxے-cȀ԰t5NY=mHoFXX.GۊL&t,&+ZaIŘ" {9\"2Gc4gA0aĬb8y8 Hbz 1JRlDJ,KJY4貨²̭;>v3$9QGy4S%i F|˶"àFJ8\Q% >FL>N n<8)Jٺ}BT-W[SZ9e44ͨiLf܆Tݱ``P# V5]8xaH0ج)2#+| Ӓݴ9ꉅDYV>$b1n]]=UDYK-ux5/0 $c`&q0k{c֡ߙ<\SZ֖A^#j1&fZudC՞mZːY- %M6N1duEdASh8&30g䬜nbVN<Үζ,l&H8o,mR1dId.e@md<lκ^jX6ݙE]HhZ4Ľ}IdaFX6cjC=R<us ,O\VKޔ_m=~q|1 m,KhnGʨd~*n:O. ܗ_d Bx쏙Ni"(.7K:akgoIِlo>6+vOn i !ܿTly`{Y]šˏ~ߒom/0@(^_@!>dWM hnj!S/_N;'aԔr(c9dµj'^UQ/׃;6qt>bRLO2׌{mC< s~:nJ^IerrXt=]U*bc\&r^p(]jwx:Zfo S瞐#q?ƒ *JxĎzGJ2g=`,f(aR'zΉl2C~oogx&w 6w$I' w]/P;f{`ǞwDW 򀂸)g*a!csc.ō1Q R*%>uSzzƣW Ew6uUuowJ nCy30uI6E?0`ч;߈9AsȊ? J vs:`wK|(r C*P}ggC `<׿{WߊxO͌b*գT̯s!,h C0l…*Xx"C an<~G,Yҁɔ*WԸbC.fVdɱa}Xg@šP)сG F|TX jpׂڭkjXKjD -ܸrҭk.޼zo,:0CÕԷet)R}ɓ3Tq%SŌ.i]H;mG eΔ]͑Y捲7Yv1Mȶk+cI+C,:jQ_Mz՟ЏD8]n#m1ӯo>0&@aVjAAUZUZN9wZ׭`yU tiyBm,Ry$'"($m6:9\|5h{YH]Tq7w6P㕖>[{j%]z%s %]jGԁAfcZC>SdAzZٶ$rmg*oJz"q hCcuZ&@te{fgAEL,:r'jQ++R'5 )Y {eAYy(y!Qe&h1ϤFZ.XL2[qifYm:TZw|ӇUI!+,K<1YYZMaIz% ]j7fvSQ N8p#/#"zpT -zSZoc\Ij9Dм߭:.ԺW#=QNPֻ*&[JHy |QG-,^t*|bD!IJ1^ds{! cثbR12jPYFN{+!UR=!@8pPbHn̞77ǃ(h]!tβ|Pğ-y'>}'@*Ё=h=P|Sb }(D#*щRhBэ.g~)ґ&=)J(Lc 1I6KsSj޴>)PY[~)RJ82N}츘 ^B*f%b[*I `R"*5"zrC=1z!+V*z5l.Cz$A]u9ƇM1DXXV*V(k~PWQO,CDVImlI"'VzKYͱUJڪcrm#p@}npr\vi+vv8H6=nK^[mWۚ4.tD]zE%~q"P 0t#,`4j!!!^/r\vSU͈`û-}y Z Oe܂XǾ'pQc@S~Ö'u+Ú5ro} ޸ *DrZC^2.kj{d' y<%b 6&nے?~ݰLWPҖ43MsӞ4C-Qc:{,;(;+HKvOn}kS΁M\ک Н}u|>S|v^1dVKZbz6-q>7ӭu.7&_nqWյ^­[,i5֟ҵ BbgG򰩽eXM㽻-7ďr_Ȯ!_ .].WqFNQ+.<yǪ7[bsC-s}R Smn^޽ejWeLyϼ\|j ~"W; ]{Mē0}떇PCDU<-cmS˶i3[;7./{s0]=O?GAzY /i>,c_29nq?ӯ~|}14?ӿ%ߥ?J J & a6> FN N ZEn v~ ~` B Ơ ` b   !T&!6>,!N!Vv^n!v]da!!a !!ɡa!  "!!""&"."#6#>"$F$N"%V%^"&ad"'v'~"(("))fI*"++",Ƣ,"-֢-".."//"00#11"A2.#363>#4F4N#5#6f6n#7v7~#88#99#::#;;#<ƣ<#=֣=#>>#??#@c@!,.@22BCM$Cwrrr KLW,,8((4CDN..:33?abl@ `@!,-s]22$BCM KLW,,8((401;CDN..:󑒕33?abl@*\ȰÇ 00ŋ3jD(ō Ccő(S$Xʗ03tM?ys&A< PHCPhҧ0ԫ`W- @׳ K( @h@weY ~;@E 01\p (k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlpƉ`DGgIgPZAz MB (wf{zzB餡橧~!,2d22d9e9^^^ABLd$9dd@AKd֍99d d׍#֍eҎ99IJUdd9e999++7e9d22>'d9e9곴9؎d99e9Wȭe99Ӵ99999ed--9''3dd׳H*\ȰÇ#JHŋ ȱǏ C)Qc(S\ɲ˗0cʜI͛8s$ϟ@ J'EwLʴӧPSR4̥Vy%ׯ`) 'h8quWݻv޾ LÈъ!c>ߺ-;Ϡ/f S7rZ,V#RhT^xӰc1 xX|Ȳd7سk)t8gSRY6\à`.(Bh**飀f hDX$`jꩨꪬ6@_Z>zC ,B ^$kK:Kh( ^ 1j *+۪0Qz^K:/^QJ/1BsJ)C.>H w ,$l(,l0s4h<@-/#0M( LG-TWM":X-dmhlp-7&/X [n'.vYPma{w 8 DakQ`ꬷ.n1Tλo'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z`@!;Ѹ3`lğ88֯pYG=¯H:r;Cqd#H&6n4#*iIerԸP|*O5r,(cIE !,2]L22b8ABLc8$\\\a7b7b7abЉ7a ӊ8bЉJKVa8bbcac88bc7,,8aa8҉777((4bb888BCMc8,-78cb7bbb7d8ү877..:8cbbU33?[[[bc8b8Њ8888`akԋH*\ȰÇ#Jp!ċ3jȱǏ/Tɓ(STyȕ0cʜIcK$kɳʛ8} J(CA*]ʔ&ҤMJ)TXj-hK/[ÊjcӪ۷nфaݘeBp_@Y@È/db -HK% G @9BgذFϨ'WpA2C䤞~h떼!< Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(hB 6F(Vhfv $h(,0(4h) $<@)DiH&L6ATViXf:`)dihlp)tx|`!Ɵj衈&袌6裎 T*p1P駖v ꨤʩJꩪ*무j뭳.0駜j)j+&2BD0ؖ`c< %0Pz!PQXj  +P쮋-\ @ Cƽ' 7G,Wl1`l=PD0 <#@D * ,r,PQ36sL7PG-TWmXgt cC̲:23 吲2M3$+ #]$Z.n8\k5DA!$(@pw晇_1W1M|1駣n/^U^@4< |Ѐ jD/ 74k?=w_P/o !`%4pO \SPA0HqB Nx!# IH8̡w@ x0< $Mt b&M)pE@ $ 0v1A 6p4"`:x̣> IBLdH8򑐌$'IJZ̤&7Nz (%I L*WV򕰌,gIZ̥.wKV 0Ibȴ/W0Ќ4IjZ̦6nz 8`;v, `+ HOf!,D",22BCM$ر  ,,8125CDN56@..:# 78BKLW((433?"" 12= @,0`‡ 0ń):ȱ pȑ=%D+[ĸc3gNv~s& IBC 醏`paSP !Ou@#A(Ѐ6a JEE +^̸_x,yrʖcΜx3羞?G9蜦4Jcˆ=uԷ7Z2h+Y8c!,<22BCM$ KLWLLLر,,8#((4㉉```III@@@:::&&&,-7sssCDN444ggg ..:>?I...֌PPP """99933?>>>;;;ޥabl89C%L@$! p0#^P4H vrH&~x+pQG̃3Tq`N $pQ"0xjO@PժPc,կ$ 6~PD`.B A( Cp$E \2 @a4! H2AD\0Cp8 z!,&22221212121212222222b^uoxm—X˗PȔNNzMuHq;k4h>f@ufPlf]gfcZYYQPPMNNLJFEisM{kPUQUaSvNx4rl ms=LR^åɮǮ̱˺¯įǯȯ¾ϽӸԴ֯֯ڪفwswܾߵڢҘΔ֑څ~ywߴz߷}޾⬮Ʈ̯έίϯѵWH(\ȰÇ#JHŋ3jȱǏ CqE(S\2 0cʜI͛8s4ٲO: JѣHy\%ҧPJJR)]@*\tZٳhU׷pUUKݻxKb=_ Lڔjb)5.-3kyǎx rn~uÆװ3| d5LNZho^VU˻=Nkh!BN 7zӫ_1^2Tt [o+^:bB yM~٧_yV_ yU(∯]Y:H_~}5$(a&r5w ]eVf^73)d]&6scKF7PRŖJU#Qf%QSTWudiS(}aBhp)'qݴ՘r'Ftxjz66&(D5({褓"Dx.צ7v9Ĩ:ꪪfJ*E뮼+k&6F+ A1Q,Wrx.&k覫+kQ-EdݶzM3 7G,/CRԌfۭo S$l( e̐n`]7X*-Dm4,+Bl44"IJj8ssot\w` D># 94 L5:WphrxF;jBR' 4AnWn@Tq;3x;Atdzj򬮘.D]9mӼ'!$!\KVDF,g;дw=x m|.EPх=co"n8ųabbWK!ОbGd hpҷ 0qE@B,(@[WBvAB > = ԋb1,`9\K#oU.Z^< +XC1{bZ5„3aQЇ˜ m{7 ?x#"71F񑠀Gȁz@|# $frtD3,pEr5\DKV-|3i J#cx`UP09MN^8>)jMeNjs"P2jX$Bڛ+(A &xN&S1 ChҚ6!A[Sx3*D ? z0TG )HG\:i*R 4d;wʀ M(B Rx;PD Q P$L>֋H>q# 7Uh SlX+YR}(-VfB)?ePA*A 7&q+,H.Xz cEZ"!sŬ[yjv5kӰg +@ Uw=Je1TͪjH9Bp+PK*\aMal܈6mIrBԮل;yM.\^ϭmtoV;(&(SZ&ThEO* ՕrﭭCa*Xs~FWA+̻V&BXB7WgL8αY:c-2 PL*Q2A9+{Xֲ[8/cN+ ;ͅÙѬ:ÔP1@D6psf;;Zvlf b|6$"vs+ C8lX4RS.ғnE/fMsӭoLjS:o!Q@:fkEϺƵi8;i8ކ9W5GKs|{,HDB؇07]@6Nb܌Y2G=~NO;D }7n!C(BLcISҘvu?lۻ>gNq!C Vx$@1 o3a]@UgpS@NphOkYwq3sݠw7f}{o 1?D;񐏼=[A:e7m|=yRƉ?ePx˻}AϽwpw@p|;4a16QǶ1R [׻?Ʋ},Bg2DԁI}r޷rr3f L c~7{x7~#3yB vnnn`nno5~x见灮 cЃ>@>DXe0ȀWggl66J/'HHmJy:ȃB_bdRׁcePA7.#kvvFl`l6mm 3 =00ihs;?h ȈX/ȇhekX f #j}f'vbȈ؊؊>8Xx؋P0~prikhkؘڸk(8XXǘzg~F6hPhvxԨx؏89Y!~qv(Aktp "9 FP ) ,)d piA n k 0 $YFyH& E7wh96pvRYcTid ^ 1) P p  =Y Ѝ_r9tYvyxz|ٗ~' @` ٘9BcaS3v=9d]=I   Ԉ9YI(yC@cyl)c)jdÚʙ̙n yؙ i*)@cyl)c)jiqyd yfcpٟQPI29g c0 : @đfzҍ":$Z&z(*,ڢ.0/CS jK@<ZZ 'BR:TZVzXZ\ڥ^`_59i5F d@k=d'Fd c@*(xy@(bzڨD`p  n`F @$Qڈ@h0iګ J |goihJ:zЃ@=uzcw(@P&@N: W {wn :c0JDyΊC0 6C p0 "z:ௐNcxۭ:=x@z H5xG+L۴NPR;T[V˘X , Z*2냉6+8;PuYBv?Z؃W;[XPh  C?sy=mp;rkKtiDF k֘۴`1+uN?tt +ڹ u)4ٺܫ˘滘Yɻ2iȻkk˹ ۿr3ҽfv.@23T{=?4ր`=\zWwlkכq r,c \. ̺n3<8:1Tn# ,D#\=}P@XpXL0|`>x#ы:,s1/l.H=238|g~;mBD#.R=6.ӹLF=m{K$ ƍLH}ҏȦj  T0rd5\+QOCQQMs0uMdwגf=ِ;,c Źq ũccEKOithڬڭtPoW0fc0Xmڧ=n6j}7ۛYǽv۾dݒ-dfӝ4VmMx֙8Am2U}P-mc=$~^+WM*^ n.(Hb^J~m0((3#38Iت'B3kJLlP.-#3V[E^-_Q8TN1 .$~24j@no> a.1fn3JW~Pt^sCsyNIN,P7 |~~܎v60hrMKsNJ}难邞ydķ^1~es.*5ΗRAnsIɒNDu#E_َ֣{{9xMNQP.hɡw }H  E"3]ޕ3 `4ɀK)/1UbN5 4_4? Ny>m/RDɞJ&A։[Tָ2^j^'`5 xk'-\kr3|Aq4ÈsBZ9ɰmQD&9RJō)Ju䵋VevҌ3%ʰB4T4L<ж&M¡0rv›F0E-e~c9N,&6afa~8i" Rt*;-ti Cc)Qc,JDOV"eN឵f~2_ (7f`7 :j(sVkhT!A;mfm߆;n离nnjF[8iʽSlfgqǙ'u rS4OqG'{sWg}=ogVN_8ww3EwlBv_wuy+sUz>{{?|W>aG?}:5+ $>z~?/`8a !'?n`%`{a3d`CHs Ѕ- .Ap!eB@{Xxaxhr)[8E*VъT,MA40!B(8F2QlC"XB6!ec8G:юwcD==1B`U 9HBҐDd"HF6ȢAP$:AXGDqbx4єDe*UG>"ˏ#e9KZҖ<$$3CI~<&X72p%5pτf4WJ9e6MnRLyh>8*4 D vӝXC 6D`k`(9PԠ #P6ԡQflvӢhDo% pI $IONb D$"AOVvpC!`ԧ?O#k"EjRm[v'I0TTJրB{s۸IPպV Ur+:R:D2ՖN TC3ҩVEUYZPKl8hHp?/N`lC?;0B@Ę>ֶvC%D{öŭmۤ5"mpouhRTm& RAKCd$ 7;ueIlZ+kӴ@ZZI)qbK׿/o|QBFQH&x L%+LXN$9x"dMERxżЉER8"TW'z]HUrYNa]"Hz691LlFqI?cq~_C y hF3Zpr e*'V&L@T RWsb?9`+Rg ?7/p5p!UA%@D0 lAbr$/Q\.mIҋtYs.(nT'"!Dxu;)Gxm{+uI&*N~"BJ8AT7i*@6jR p2&0cØ7DMpB-1 B'-a50Ӊކb&>zֵC1؃3!rcx#RΪ[.7U |+!RA B(4y☼y i<$GmoC}eȂ*"p(D/|G;P1_8daBb6;DN>w@FdJ򽁥qUa4? Â??We[A 8Ae6i{>S[$v;@AC?Z$CA Vlb%I8=A0@>@k@EZ;s>@3jS?2`AZ68%BY¿kV+?Vh;5 eP ,ALTBi3'> @6Lǻs0I?Q42JLČTHq(ĤTKd @i6 Ś<BT%MOV͏NNSJ:Ņ,Б-\Pr$ }GDRW'kW/W*W|غ+D[&37 W?pC,V baY{E 6VAYkP g&؜22iXuhF 6$k)s0\.!CRD0X;0١ 8{uؚV$\=eX=FB24eʭܭtZVi >ׄBRV/BYA|b[6UBj؈0UE\{=ZŅڝ]HZPzUe`]ʝhSkKL^Sz@ EEl-$BBbAوݕ=}c_ ^|í]0 $ރuX^u^eX8 ͑+Ts;m]e9}j4 ֵ-V'78@:I^ŕ__ ^-1<Vn`V!TQ4b^YHuXНƓ%ADZAXC5*b)F(Vڭ_bv)9Zfƕ=C4I<-bC*m5DCK|KI+ +6YUAjD3@`(4* {Mܻ_V[ x_eWe <cm; .d=dѬ< ЦRHffe딓kV롴. $Pø#5@AjDN>FZh(dhhHM4Gc@G .BHw\ mlbFVRO DWخ_nY!mAH/P_w\-njA:ެ]Y/@ Hqc8^5 `b(ٺa߆agn$j6bgOx@z/TDjAp0}QB$;*0/f&9g/zw[?pe.tXCE1W}>,b4?h!s4#чbP#k%ؖ"$`(-x(i&Zg+-6-j(Ry@%R*V_dLNuj,ڴjl֭ICRbn 9r/5\ ȱ\d8WYN1 }DNk`8+}Fp[8-qD}9sELxL`a&ۘ;2)T.tKEUwJj5k֭ŏh/'qWT SRyoU 7:R^b0! EXL+|7̈́܄-dtOQLrvY`YD؄6E&fY{oZ[s2I]H!G}A!Eј`y!6Is =9aHo#QyjI Ĵ);I'M} b4cI 6ëŅ:725P+^T6]YZH-L0,bgތߵ֒_ŕ]58.ԂB '2Dnm !0!0#; =Aj D!mb"!6p1XsA5#LVpf9l)'@uv Ks1uzW*zh|AKzV:Zg`xZuSGSDwaƎR_eSǗQ>pQ]_<.b Wb/696]^k@5eLV[UV/oғsriIz~RvKۖ2 *ttMixW4NĆ:/bG_V᥵y\91okr֐XUKp"h$Wa/kE#*! ,Iݳ Un2gxUMDS+ғYSMbs&ʅ|lꮺ2` ؐ E%_yLY ,:y" .,y8ԅV!԰nDn{&/.dt:=P Rj6&sM]66X'w ^269iЫ ߄E _x#"֟6: \&f`_ԞnWj$ToF3r1pKcȸ l \di8ɫSRVYp&i 2#Cv|$$VKn24(G0"y +W=Zb`gxK8fBL9h#*ƕ^A125A9LEHSC.X`JxhF_4i+|wn>k%:y[)N&ONu ݄]ϐx`(x^AhȤ*B-aKүu\L&| '&9rmPOվ Nj9vfwa4!M"!P}M~TMj_D`1uxh6G}o P8+p%<^! X` :N򊷑sc"Ҁ"jLp!| ek Afbl/(6& }%888\ he`l"ylj j`߰8r-эnɰ{zNk % wTH86Vݞ`7 7*#Gvc=;%aS(QR^5EDM@ooD3X@CĄIT[iņEJ| ImJn,Jt OfS:H`>=/yAń>Q GlCXo@feaH f  i|rEm6R \ޞG'-.H-e#."ME80B D :[I%%~  Za%aTQV!H: !"ʗZ|WZ `'Vb}!/ )Vy܌! Fyᦀ DآIb21t JEY5UN )#ZElHcJt&Z Ih?*Z䏬Nd ^a QMOFDj#M }%Q: T͢:aII%Zf`@QLDMcaB I~U$` ^ 1Me#]X9]uU`PLɋY?liYNdUNY`)_d%BhNXhV!٧5 .&B%%Wb.f5dUe}=d]Vfy ;dqp-v5h~qlx`l>lԦmus]Wc؜ X GFdHXY| j ' DjL^ ʉHnkFCd<@[D$‰lCFkdLp{ %6w&̈Qo&0 sKQj4D" vd.?6x..ct!y"2|@ì 4ua+>B|XC\̩L(ڴ@O3 Z eJ#/"lr#^>'EA?W?XW͹"3 K| }Š1T *|K4lG-s>+m!Wͭ?o_gwiU2kcÇ'?~R??o+?Sg "_4U<Eb6lɦʶ,@8`A&TaC 8bVZlҸcG=9dI'Q.&%/kȑ9S&/qԹgO%@APG\\ظiE;2uJ]N8@v[5큰blY8YCÈKؒǐ)'Vq9)'O˗1 :6a$ƪPU*U~V͵/'y+{es]m쀻}[ݶIr&82Í?^.sc3s@|訦!zjU\M2f4 NΤKk7in  s;#QtȼxC*܋'8'OvPĘ?@&6/<'/:`4N  7R2$2"`$hC;G($3SSφQYOVaa&h=.aIc >hh>2Q+qa 7?Hȅ"`C "J LV3 iAEYU[MIᑃkN9ΎroN@ڦ֠AZQE5rF A&˄`47N498$'@+֐!U ^j+&nL#A9K_- L/r8h[;6ܣS =8>:ѐcL`WƗW٠!5DSm6Șپ Z8/Ap<A1bc`@.el#GIbj!adЕLfO%O ]6dC? 8!G <jFOjwr/܂l -pdHRb@%,Osr?S[3H@gp 6T?b48; 5I 3>-q^6B`jdnsp!;.m_2'8Y 3u$#`D+qj9z (QWEaxJ#6L3uNSF1g:4¡#ZTD@9X2m5O4P .$ Ibfȅ,C)pXNF !Ic ҁ.r8z"vz;JiF]KH34B5:nd6ɈdjQg)׈FuDG\7]ѐ䗿iȜ=XAJ0-B4]Xf ?1`9&; #؝ 56|yW48KUFT!Yq"Tvt28DK63P1"GPB`ϰEFot7f529'lom S8k O͍Аʧ.O k1haD!JFI ݼG)C:Dn:G>m`H کC6P@~LULL``&PJ )E:P*UFnj}5ױUjdH"9 ˭]8hGk5%m_Ý/ @X'U,AS !XUBNS`&z`[O`\t T7a.AxjA:'\}@Eݰj>" }X˰yd!E6򑑜d%/< <8s,#ړϮ~i;dP<xC)];-<=\Vn^tG% 2"4$NMpW5_O:x_ګakYúꍨ#+7K/VLk`\ <67p~Dץ@K2.ut;%yn3tRv읳/;z,t^gnz~ޡj(:3v!pFux z_nf5_端=Q\Mv$q mF6b,jH0Bρt}֒Ieta qC Dx \[WvD=Qa 8!ϝ#YAu}u^t#pސx/ "y=h1P F3zS>[>Qou{ S>Dq?4g/ 82 ֛DS"u#/C7tn4 E#ewω7!A?ӗ5cϟ,1:ezȂ4 'F!5ʯ# 0Pn##/ .o#*% /9c *B/h&n"z}`~p{  ~  @ P 0  } ` ٰ ݰ p0p q  Q'ѯjv!#qP2'P/1oC%F:#4(aIdm R#&U#KQ#Z֎>1Ap;"/9>p[^oqrq{QX)15ق47O <1=QgM'!!Rґ7p152#7/QCBq#&q2&I3#%X#V %]2Kr#%9)q?"c&s+#v4`N# /--o?/="a1/r%r+"2, 'RO Ԡ/7*' |.35sMR72//0!)13-qU[06 s,`#-@4E N8/@2MQ'aq.Q#!O6 !{73'R>`"ҳ%S#6s@c0?Yb?a[@> BOA0 t=s#$ ΃Q(6>KD4D1T)R==A9tËRD$tGeOG3CgtC9` ,6bɛ'|h^GJk1@QG|SH;F9t,%r#4ցjx NoKaOOO5PuP P P5QOa`Q!5R%P dtL#,=A%|HILIKTQT `5VeuViVmVq5WuuWyW}WgXXW6@uS9L7CBUyT&F52nKk3ȕ\\5]u]ٵ]]5^u^^A^_u^@q~ s @h` $a iy fܛl30#v Ò p45Rj p$ ymw؇>~艾~7&4C7n&~~q.`uU04s~29]rgz*np~u^w>~^^7C 2t{!4໖Q~*qGv #!޷%©E~#=a?e~᳀a7^`Q $#!ů/Zf&.:ʊRtTTPQ |Og#NJ.nӘ#\{}RMl8ڴi7v2p kLTpӺ?):%TXx0 F]i[ weMĂ#$X& 6]+"DBAkJ5*Cty(tJ$I2k%LqVtڽ ^\A| o >8Ō;Fɔ+?RzP4P!53Rh5@/J i[ŦfU3Kז2l${̄6|if9uǙ`dѶӫهA)l2gVsڧײR H aQ=k%FQZ ZQEGI*4+8SQQ3! 4At楘u}s{s#$T2@yɆ65NYvQ}_^~ fDRIta؁]vul"CvE5wG@\ BlJ4m#S29̗(jT&@b\\``  S T (4|7[Ok lKlXF> -ChCL{0NBT w΀34 H5 %O| E[qG@2M(܇ 6^JHhrʇErˈ&2D F!H3 ]DP>9[0SF!, cguSpc|NBVLO}Pq2Mp=EM% )'YhGvQÖ[Y|W.?y ? МM!wNgΔ:@`za{nx`m i5^CvJ豵n8u9>y?i9anvxvŌ8ݟ~OI'FϏV~,W9(` lJp/ BP["?B%P$, O2`_P4 oXADž1+3C qD,If*qa?X(Jq 8`3l`sG&`[RvjLO Cۦce. 4k̀j ]r̪z6}k [V>`%f68}pM#شF5KDT,kpDxjc8jэ Od`HAGNe*ݤ v eL ̲]_;"/x?AN+4 mhD':~ _YT@F}# ~< }@@klJke/@o;$c)D9]H#k|>5x5yCv a]\_ ^`l[•\9P mFp˶RPe+Ӽhr)#K.m?(5s(KFk #xp>񋋺5?t%ma`3;0 O.l=5o85/MPS&/rݼfmZz^җ.B쐏wyctGM}Wy{ Q{mCw@A/ cof?f D 4?|iAi}:|s#Bѣu>շFtU(~yr2'&׀R S}7Yjg@7} 7-Wlz qW7]ׁ4wr)~%8~~fWpѦzQ*·{acqW÷>q wuEN0Shw{@FoB3J`hx/u@`xw!q`p(Qt`h~iX@fk vK'lDFvbW >RGdGrLm J6uCƉ[kfir3q5";{r4 sb1ׅۢ'2—N(QGMͨ8XMWcU6^@b ]o~h'lHkٶlБl_0mW~&vHp Y&o7BwGY8؄ި[W%)|{]2'Ʉ0.y§XySXMؒ A>p4J4$Ƀ "|Y9@CɆH(yJɔMVt_DEJT5X[$K1LKuRAJ\2FA߷dqYo6LQ!88E)Wٓ)IЉ;xw'xFOtNVNt՚QQDWuL8WGo$a# 瘉L ~(HE.А9 FY! Eمʃ#)Tj&Q R5%XURvc:z< #BL{,aНy5sx&JؗE7cP99`:|+y4uU YJ>_JbX?II1s3 @\%Loc? OUUW5@Z4^\Oz>fMz|槨]G:LsHNWxUX|gZ`05XyfX#WpspMz%Y ]ǚ'JG5duXEZ쩬Mz55p2h[{$yH'uW@cp6`ՊUjw]䤿Zh*PVucu`x4NG_m)]ZJ*:&AĄhʯ{:Ea Mc9N%LDcc3fJJ]tT0Kך+KVMiMRFecFvvŕDw[Fjfiz%g4GLFyV͵Y;@?{52c|Mjm붒V:[D ؀cAr$  ok$KrAb;O!6|'wgAp{C۸uIe KAk˺*+Kk˻뻿 b Yxvֺ+S= ׋; x[;A[֋˺{gh}Ajo澇+tn`iHw z;^h;A`ViF9L—0˔eS9Հdq0;E eeFlWŸ1C<2m]+IZP4 Fp[7`kP_npŚP+0 lp".$5dS+IەNa Hiz2ĘShTo~ J J{@ɀ<l`0Le cf  $3@R!l)`e)Kؖ'@" 5]*ʤc٬ҫx,aɗ47S|R<<$   CA}9pJp\A4l0JF"dZ` %m']$/m`۱wߛɘ|H|P_)4VoR'A3PN!qb0maLCkbʨՅRnՖ |p+ r0q-c Q$U@j M2}saԎV|YܷeH0`WT@k@ױ}PMb0*P(`)[9 U&uƪ{=AE rwMDJ,q~mA~ ؋h]6R,ɭ @i nRLJV* 4(=RxGzDL1 T $`a eFU*d+m[$9jS%ZDh4~K0}dJV~]bP ̖14 P:fp{ֱJEc߃K0tuJp'$ e }4=I NPZfEp]!{|r nkei7WY._J>f]@@H|ZB׫ A_cS%uiŤf$G8U ɔn?r;>}@Em}H.>a`jAsVwku$Hq  [aۂ ijP_в9,N0JҼ̔"=[7_ ,ۭߎ~..ӎTvFX>5FJ4IPSTJ("NUfG۴ffWhH)NA?`WTuS۵|ZĎQJp>?탰Jk*We ھ)A+Xೀ AŶ   [qW@ 4a/Nٵڵ I?Q L>ӡ>W>9my /~0W`_eOe頺@/ZU$b;H<> cQ-E_Ze&N~%?@@o=-k qPLbDOLW  $XР6-d&%%NXE5\G!E$YI)UkKxXfC}wr %:F<*_N$xtx(: mvXrTU-ȝ%*0c1L廑`G]&\aĉ/fcȂ@.e̙5o<ȡECvBciԠ{5cϘaDvmٹu[#Go'^8H1Y9΁M^}qtH‰q(!1zw `O|ys.' 4D/P8䰂> /p@K41?ΓԫB ib˪sJq v& )-jH,v쪌t*NIKʁ|d *k8?d&G6IR˧%) }PvIRy涉Mls$]B 2"&/҂bEPa"]mejm:M`#ap  @cA%X|-SB0OD*A&oF'5~߹_!/>y\KDP` Xo hC?GP0\"E6>%JTt}H]8R,5`Wt'"R}T JT{ HG2fgiP ј:xuLܐvʹKL=5D|cѦ"P} G pĠA> "bKHU(R((%()I68!2|_jP1 ,`D Ȑ=nU9s'xmXB<0.*"Q0ir2|9JW)(HAhrBԉ9 g~Le $(i|)QES@ ;u(;U:'+-q6E'*MSTH:%pʘ8CYhn;&ΛRGw $;gO6-M/,&%H9}`*Dj:iuGZX!&#s*Z>Ȃ*bS(s>JqIb'PeUJ5VX9Ve}jEi͌jE,8+qUhAPzj] {oj[Ol)88 F28u& ^V%@ʙbԱ[ޚܥ'GӜvA݅4J$Z՚L)/#ٟUL sЃ.{Q4-{`%t-Y'0I` ﬢhz@ނcrWT~9E iK)~5Sk.$ի =Nӭ 582IF֮6PkHh%,u)UH JjwHsEhTB">ZhL#|ҫ.QE%k2=% nɰ%ys6p>)Ui3Q"lbL]T;"4rځ>@O~2NRUeĂe=8cCb;u]eقe]oHYTE6] ZWخn y$vMɘUc]]p 0~/x_T[&B "B =qK'!걃0!(|ȀlLUG`X,fZbV7\m=aF79i@FId_/kwQ]ۗ]t5=[coY 'r3p6_Dfky5弽u >b~},%ؽ?9%J:5?K>' QS9/?=P7_5)([c ĺ; tA j A@>K:Bz"'ٷ[""Bԓ?i(B#W ;(+<'"?#lc($9F(Iz)& SJ% V9h:!l{C8 Ğ B[>N=K$Q 9?1QID&~LSTDEy<ȓe#{2򤈸.!qGnhihow–g*j44K--< s(:Jr**頻68Š d4@䈆h? (LR;"8aPd/|LN0Le;p$3)O/:+J< #t@*pj:k 8)Pq8P>U,jPx񓚨3Eذ0NK5B1D!>TA. *i1ek M0KnL0;v;_ xz$U>}Y Łḵs*S+ / S132+?S-4,jS" Mk(FDiJ@#ѬᫎPEX)i;<ÅBRP4NR/ |"Y4T=QUL1HջY]QӬPĔ+/ e:4c2eUT/RQuA TPB7VЂP_5<]t :u5787M[O&<ͪW1p8qJS=?r?>E"g.dQPs#P`7/I0y%N7|}CG̺Tuk<]RԪ6 >}6qN6%Dʻ8<.E>~hbb(VH`08]Ub0F6  n|5<\6.~ ocK0A/D(2^>nd̽W3!d)]EdLEOUIel^8VyLL6uMEKa.Q6\^teXesx8E[8#{8)TiM˸]匽dfFg%df[gC+Nt^ufgXesSy Te2 P }~3JZ熎;=F {d/- $|fא| H 25f5=y^)hUV_eddNi t"JVɦpi\͈@#Z1ցPxeC- R3%hefa $,JN.Gm걿M8xVơI=hc u`OW!67KM_]_+yH7)+l Exh!=c`F)_}qZbeFqGox eR,3626X h\>4) rHE8w2@e;'6q=O.3Sfnrbbӑ[- [ uhU\U]n=S왦iMd v:`j*'f(k6=hgi` :Y&lux#ǐr/[_xDѤJuwje0mtgXNG*FEjA(W(#?yO cƖg×B~*yMeyƝʞ?My1}%zOz ]z+MhAMCz|z5 xGy ڳ@ og[k{> ٶ-F׉|=w `fjlkf'@ vؘ *ژ_\v!iqVj>{C6{]C!!¸è}'}h3 rW~G0 }~~ ʰ~P/?ܰ gy6Kf܂LS XfсP ChPbC>̨QV? JˁM&OL._Œ)s&͚6oԷr&%>UbC F"MDPXܸ .^BXU"4CîJ1C Q[#[`'>K#·EH'a-"Nx1c: YCʔ*ͬ'ӆNw.ŻGC[Ӛ[׸z3tû|ڱ(k ΟCn򞛯c?ڹ  f}@c͓Kճc\t>+'vr )WOI 6FrŁYv+xT\r9!P%Um)FB} 8`%x CYLBvqT6OZXUA'VX6$WbIT^y _iގRAf{da@MvYU|Rj Á&0s =Fb92r#ZC mdՅAA!/'0`87;3bf4N 4BCJ}(F֐GAۤ`dL@OPo ֚q-]8k96:ykmk&-|=/YSB.xa;bKPE=T5cY̔>s1tg4)S7&67wAל37ࡍ<=0r=vNt4_:yJ$bs%hR{9F[8f=@mr궧 ft;tvAp%\kvCtFѯ~CFH=Rl3d]Rb@Pc=0#x1lnΌoa-<{#Uw Qu";bÒē-sJG*$W\j &<<s,I&I17fԙ\]4 x\oZɒo%JCHUxè -Ox ,|;B\TؕEOQq `B. ~@K !{sp FlC [Qǿ=gw;ET+i2R=oUt)JG@K:\h`&+AIJSр6 eڶ1B035@K9X1,Gx|4 h,.}gmx13CPshL4Js)Z ֐5fА6e `ŗ8\ "'#ѐᴩ<[#0 p PC0mUB!`s$} i8?Ps25803xǫ/]nV;}l-)G_&z1.*KisFX"ĜG|$dIތC6y-C˽oŒF+5ywky> UBp7 8;3<cϪ~IV8i2\i8lLB 3-hJH%d>.3STNyrujZ% dm 5%C4rDtmrʎ]vv5燨Fۮod;%@$%-3JSDp>HėmiaItp)Nn| 72 31(',QCشsMUR:T&]!FO6ƺn\Ѫ@wJ^$XS&e14vZj05IOEs+>|9^.t.r'!%!ܼ.~KyvB}aodַ~#&Zu]=m˄ދ~_/3.~fK?W󞅟}~5rH>wm??pm~)gҿx ^A _1 I8Pa9Fi]iDj,T`axI*CW΅xT0рS[Xљ/T 9]1E<  ЌJcD `MҜC\ԼdTӔ@gUei\E]\دyQԱeF#C9K rJj ެRKAe :S~~ JtaۺDPBdũ l$ڈI& '6^J 4-V)~Q2m`b!" X!044LX6߰@}>hDV ;BOtXOF<ۈ@&X@|ɡ@46D>$)rc7I6iL! 8!<#6@B=c鐦HYPpCWR:88ҰOHFN I$]@LI J:PN)LM&b=w0㮙ԱFE2@0DިH6|@E3lUT:@i\z=:Ԍ2Ҹ"5Y qHGT\NHP )j>0gs:sBgtJtRguZubgv^';|@X12X 0';C>y8@$&|6dN=Y:Q Ue@XHWb>Y@xI|̀3X<"24}Qf)рRĨHpGh$GN@$]H^v](%ynBLe]nN!5'b֧'=E"{8ܗ ˺ͅWU&FYu #PqO""/x\pJ99Rp)]GnB]V&@c2j:jiK(#H]g >"Jܤ ۳xX1@c;!r P5X@ZI襰:0^|h@A ll&%>d׫g 5Z0GpL%>jޏkZ**馪!7:Y MEKiZ"84 ؜ÆXaԗ;ii<.xOj (BWX+aA( .@E*|+]hj^m] Hͨ+JS2VҧOb\.]]բa.QX݄yimCR pXidG VI5rN5T"ޒd9`KU|nj6 RW_rn-`nn 2jPD._23n5 /xBo(*~*6oroIMfl/t=䎯s/orB`b`S`Uv Jg ! b̯Rp+?`OOP`.RZUz,!=aN =3*PVZ$!!!bŋP9sYI W0[oNzq$L/+[j~Hqha3V1q?7#s`8Εq!ıљ0ṯCr$oC 軾~Ӿև;ӽ폀 ~>3g6W ]vO,QhcbmJMhG?uKwu @:>o # $"C`j\x! 6hBI4yҤ,ZrfL3i֬ h`CP2a &`t`9mFspA9d&5Fѣ4裓+ϯgZζq DBV4 C V7MaAtrdɓ)C!o!H"6|<$DʫKdaSr[l۸oueepM\&ms˔#T>WŭMw{y2zQl~|ϸ}~ <tp"8ʼn?bEOsߢi =Q k2b; -1&+ C\x.aIS*,ܒXQB n?Ę 1}LNM״7oP$2=#C&R-%J-TVjŒIL~Acrǚ(tWm:5UeVUYeTe X%T C%I$CyCLl/Sl&37CsyY\tI%TusvvXb< IUNAXPZDZZeY 5ޘ=EM>e5]X74=@8mPo %v\^r4aҹɘݷ<#e%Cj EHdQ2P %HS>^^AnWzk_qcezWǥ.jAV0!%#e$$M?U_]e=v[ao~7ϼ ^F~Gvg_2FD$Yr3D?_mo!=5nw㛦WM)xiJhB=bYOr$ =gA}!IXB}/!uQijC/ZU6!B0Ӏ8P, t"yJֲd,XF3iTF7q(G`S-PFu@L .%Oή~4vMI`:t"iF?z\8Er[l|#DiYK[.=20D"RGCє4(y6M:5$8YrsHd:Px(Ք=1B>O@ ZP U(Bs>: OCGF$y\HIZR)MiC(Q,.blOAAPZT;T1UR8SS0TcT^Y-*RUNtE*OsSG1ZUZVr@U`dx^6_ue1P;E.6ְd)[Y^f9[ِw`0ِx gB,\#de|nɒį k+Yڴ>}8.c\>ѕtG; -e?S! mda;] n`W&폂 (Ҹ]Lr lY^ /fpe eB!G N؞7 @"i4`}h ;@8p#0P`"@%+[@z!@ (^Yb6H,1Ul&6Xr\BՆ%3aVf\:mx!\g;W خa끼ֹ_fgC`;45<[<3i F!KGN`!>>6F0#8K5THZ)p 8Z$@SP0@mj|%/b*myVH`Q{:+8!7,^=՚;M0#h6ذd%\5aGF$@@9@q|_цX!]!.e3y0QpB:<HgPFb&+)\ݖ1gF[c0xY0~>ڡipV {' ""3W̰B*=6>OJ^c|<)S(7xiRߓo}z|F@KDUгQ#/w^O O>%P?ї_}_׾BÀ!ɰ>_ |~ 4#@ &/+D Flwn(瞣 <dfM("F:Ō!l, &LPOUOXObana6Aa"07KvP  P YLyp|P )00   !VC<(C=EaAa6\D6_dT`OvN 6 Ρ ܀ eng(b-$z,A=SXv::V8bn(Fd:YeV&n ^`fbX.Utgh7$:+V:$$k]d8t8EZoj7T6M f@ !n" `^ʖjbp0hmnMgUJGvSpp  aR@ AW:vxM֤i(_^QC6uGuc{/Nm YgN.fAgd!Ѐ @6wWfT>]_wz%oB־{&7|WNkhs R(f6h@ Liby2VD&~gf)rQw\ _XTm 4ցi d rBaf :crB# zhJ&H x7lH~]6gXCsq7˔E2`25xj x B*xabBCHVThcB-0Wܤ @fh=8)OTXpxLz4fE5(Er83qs8y[xG +!r` ܀B .'b c˂b.+rb'h쯶ZlGUL^CBgs_6[7!33A03a /Ӡڠ#`P peBf#a&gd&&,m0'DL`ڔm\` "3 "op?: P L3yXqY.ɗ&6?Z&BiB,k`=.VƔ1c"炳H?6r yڠݡ z{czUY$sz nc9B: z*gB[-{WYocD[ l/eJC}{q# Z]5 f"h<0Y+Y8@VU|B-c0x [$ :{{` ZAܼ^; [7Yz v,X-:6 z& ![&.ygBMä:+JP*K{ \[[[ [[;B;\$;gء^I|[}e@d£[&ZG٤ZB/e^,hȷp{o}.Qs󽼡5ߋ{ ~: ^\ZgB"q4>9>&ZA8g.XVZ|˻{3ΡA> 6|-_o\י@>QCIN^{٠"X?Fׁg8 s[gs! R vf6\Y]L]{CF]]gU _T^&@]~O2Ae ԰atJXPZ8 KC Uᡨ";1rGep5LY!ȑ6H1Ŗ8s.תϟ@[i9ѣH*]ʴӧP)QbԫXj uׯ_kaٳg5D\1DB q7"*1:#^ eI MHr;┖x/wXgACʵӨS^}mرcV![rY]]^VËܡ(7_,ɝČ!q-:(iӫ_>ldg/[{U?Wx؂D~|i]ErgIv&^Ky($6߉(NUlCŋQ40Ë6B%袎P#BxcCdD)ODP8%`fiD& @ěp)tix|矀e jh &袌2VE+rB|›\*)vi2*jꩬ v窭Ɗk@0IJ6,QĴVkfv+vP+¹ꮻPQ}tq9``  VP¿ L+/- Z1!q`0 L@KO=/Ik?$a:E Z 7h+]SVT`!,P UQ4c T،0BH! C) U#VcX ,D +D#LdanH(T!WhP"6pT:x? IBL"F2TУ$n!"XFɀ!,*222222222222212121hfeaT?:5|$ j `3V?CO;R8E37  LYcfn6:D^e lrtwwwwxxyyz ~0899::>@@ABIY]`bdgpxv〶ҜȋKۓAJ_gr׍؎ؓϳ̿ԻڳަH*4ȰÇ#JHŋ3jȱǏ CZTH (S\ɲ˗0c,I3 B2sɳϟ@֬yΠH*]ʴ)ˡ{\ʡQXjէ1Rij׳hӪ]WAɵ\itZ5˶߿up tZlǐ#K8 ;LDu1G'M:p将^Y/hc˞ʹ;k i;7wУ{,>85ⷸǺ- Lj+m x7Ͼt`:vOlPöϿ?`CD6 6X&)aU1 ( h!bF@0(4h8<@)Di5ąL6PF)TViXf%@(`)didvIВhp)f9 1Ğ{P|)j衈& DDJ6d覜vSq!2ai4 *무* bb*1JikZDbʫZ -Vk5!,7H l Fz h]wQ+$Qc+mBހPa5F,qM O "qB 0I1oZr%qJ '2aU] Ɔm&s ]ȭ-[QLQwb\!WѐYeل6=1GMȃݕWvMb]vnFhf/̼2)@#ߌBI3el'$HQAagGٗZʝN'1z MA|0Dէl*T)Tؗ;'ǘ_4|uWYoHYŁ{OSTe0+RC0 Q=:^7\3BN׿J ^U ]a^1IJHvCtaUrE|@T@ :gb@/'0!<.z1LBTc40hL#xxfY H:^P!Tg>1[ L"F:򑐌#Y(h̤&7Nz (GIRL*WVQ%_IZ̥.w^2/IbL2I LrЌ4Ij*z]`nzIr%6yI#( oh%,n(;t @Nmp  (aD 7aͨF7˂b eC!*QJâMJWOzJP7T K- PїjEHjH5UEj&n\,`` 'jկըw1!eBV7HUsV岈"^`{U}Y`*< HІJr)iEz,%hYŊ6 T!4Vvf1 (eU-:⮴%lX~t U84pKsKoY׸(wZ\Ԫϵ.u>t ]\Pխշ"(^7~ tQ (6eI*ۓ_Z񆘽 >p5" '{@P\8lD;K~!ˉI[.8+N2@diX3^mkVU lCM]i,C@}ߪXh5䳦m'TT]g,b"5o]N=+`q!2ژδ7)vS>t]e絪(-GMLW5CU4'nsؤ=&g=PU-L^>I7g?fGSѝ,7IoB0cɭBD[9-oGVN1moT$JvG{-w|WoʭP?n%j,>*?͡ d+8=ސAHw`r\7C#2.pyoN|Ҝ'E?^|С.sg@:CaD0 Ղ#^,q( CٱlAH}pH }s4El}9dx ~ eJ A7Q W| p/pvx}U?'N4_!Vzda+~`ߧ&>@/A`o ~sH, ~\8ߪau~7]'obG`zWd~~g%afaHX |z8Xx8G6Zā'~!8Q'~Ӈyd'b~UfU6Yy9L;|AȀU_ZԷW@%VNH9R(:h&|(`bH}(Zi8T"(?jh\{Vmu2`Vr҉rmwpIUm('(X؊Lx<p(x7-vRwnO(ØrhȘ)eqX%ͨhdON8XkZ؎khtKq8SWȏ揭NxI ِ iYdjgI(%iv$}wa۵gTE(r!Ց]L91(J&ل8n@B 9uIi{eZDfX(Fxœ_8ᥒU_ D$Y\(rXY1WTbFgh;O~$hZYVeW}x)ْ|Q0َ(d@V3`gIt:h$ZwjekF_) ^IU^*ɆWy$:J*Iwale*QvB&bg\fe[rE&`QI*I1a4KR*ڥ@4]wdyg9PrqBq<K+tIS|gȲƴְex2{ꤩw[_y>;k=˵;zn m_;UdV3dP[`0KiGX; c7kxeתIoP;T4]GzI( `_tS;U bH([g$pv*2 }oI~{ڇɮ.P;뺴+9[dk锡TEWkݫ[[IkkhTopoJJ۵Z[ +;n[eWSo8`˽ < ܺ\Nبz,{I!  $'\)LN+6k\ð۵ۺ;|{*C\EGIlØ$ N=|>?lM |g,6<\%<×5l7fN;Tکz ;D|É [Klx,m؋,Jljq콬8FLJJR ww<9,ulvl |˴T즭lʱŅ;\[ɫJ,ȵl,0ڥ,L,̬\h|(9;S<\\Lj>qβlPX],`<ͨ$Ђ)Ep[;ǺKýTRgYܽ,Ǯáհ[S2j| &w.&@N-rlO/@pM %ҍ[=k,?\^`Q-Mk+ߑ=z|уoΌ`_ԐoΒr|snҞj"U{yS+ iLwCY`:͍t<_mOtg|mwRWӀCC.?~<U 2Oe faG$4׳i>X0 Zae!#Xd3rA+K90L TQ$SS"]zTfΝnXR!Ru)gȫ+\D/F," !Y$$q}}mkIz'΢ƼxҘjYx5ƞ>釨.}z:aG򇋠" s@.7 .@{:̻lBkMCCq'FTŧ=@)CoAMG ? Cvq.S:m.KC4*(DLLcJ5_ Bl6lmTӡ= IK"kJ9tKȲ1 sH37U4ՠ6xg|OT+Ȣ-XX틊\-Z@#2E!s4J2KSiEgC]sLDU̡R]5I#Ջ?A]R.]zQ2!a4R2̗@t־mV2o3l;Es[nRYV8c5T\=w, bSGmb2<O:h$љwyFk6*ބ@FᧂidfRmI`֪M;ZzXy-;sKy9+ /U7>o,KWQM3gᓯ|')zY@#aJJo\.2 Ѓ) v26-i'$3M0#8pZHh>Cs# Q,: ѓ184Vч"bG"K'k(pr߂ᔢ)<"iFEp1j_bDE}OZ%{2*:ocE-2wJr,$P kvDBegki9LadbG?te%_XCQ#9 =d6Jȕ'  ^e/@B@B6Ѕ7w2~m 0H\PsvjYҩΊԟBNx. אEmaiήJ!IA \dD5"*o8ʜZf0VH!{!xJWBh *RAHӚ$7)=wz9yV*: "+'17UJY'痼&j9KZ&֖v,Z,oxͫ렿Hbrc| ϭo|wcUw/F<zx͈O9SjslWgw ^8#ſ[~:&Pyw>pT2p=sz÷ű[e7Y=%p 8 QJ7_ ﲷ]m/@S ?po G>ԇ\ڛ.&q(B7`ΔAq?/IǯSW;鯿؏=')R0k5O"I@×-U!)ZЃ%x#ي/0{]9Қ`^zp`@ T; :SAh]+A="4#=1KT$d tB11HpؒGS-(4T*(%6L4I4ُ 4Zr)~ѧ:DjC)73 , ³1$< AشB2ATx2ȗRă*3+U "y+@0+ Z+SE3*E!#6i7Qq$q&xx刲)D JRxGƚA.,xCB,G,oD T!H,&1j2Šť~Sr'> Ћ!GSѭp.@𑞀4IS I G21/$.E.&`<h3I$Ib9Eѭ\ 1(ɕLDG C ޒ. 0yDŽ 1 *J* \pʥ{˸*J4ĸFƘCE"">И` p dGMmUi4ؔMDahT)%T3,5$ 1.|N&AAZ*8E;LXvx2M Ԭ/P <13/l >yO\ 9xJݴ @BA^*3 x 2^T3O^F9@9_q2%wK2懶O{8T@,Ms.৲*{qAQ- A.J4NJj( O܊ P˓ Ո]ET :zؗΕѱ-dD@Oh;ᎩNc??R$SA=R]:"<; T/v8O P AAA@U#hQţ;N>E}u-p}X=&ͽ3^<#sM׵X3XH˽݃>ב}Wl>? T8'i X|Y #?L};ָ˥mtZKdg_ޑAE)*ӣ@ϟ(ބ~CB ԯNRf.r j%[-'pm8Pg.Bep8է0U%ppp pU_ gҥ8 '#G7%g&w'()*+,-./01'1϶DFr34gs'C(#nsU[:sy8_tDHAB AAIMtktCW7(%XATtJsQo70L7>`unY[WtWtui̳u]W\'v@uG_N<p_%zowPf}zIz y)/L%h7؃i}t [ъ*p1 Pz{rv#Pg+0y?{V|?'M{g/n=(ag V24аO|7mHG}gW|ӿRu%XQ8'\҃8}bo`}BȄt%@uSuRGGBQ| Oo um%i,h „ 2l!Ĉ'Rhq`*N'%K h$ʔ*Wl%̘3n,̜:w'РTyS(ҤJ2mT"Q8Rj*֬ 1tT+ذbǒuԲjײmKWrҭ蓮/D9toĊ\bƒ'Sʚ7sNz9P%;.m`3+Q`6|NӮ];jF(!l‡W A!BNҥ\aNEP]ca "/v/o=|FoN0Kr+4\yz&o9H|-xMA~ه^dRb1@ 1X'Mxl7fbH,BqaDžB1'PT8"Lxbb|.ݏJ~YTx!wxqX}~!ǑIzx^ w}~r!Yf[0ٙ(&9wJdܩ*Ɗ2݌)+ J*f *exJ4X|}_8 豴r'T)\X$YAY.2lYknbR+b K^A,ΫuᤓEQUHE\Z~w@r@9ElIEZ *bI/3&}|7 {U+\+5ЖG~-T˅ZjNBj':nH}M]ԋ۾U[17%<5B/Ks0 p=k={=?>s//n>=?o׿'@2L_C @N #Hrd 5hu! 1BWO+5%$(D =>SA X#q8}C ꐅ[?B"~}Ll"x=(Jq[,#X1r=aؽ/ю;#EqSUE>2҆]|"H0cD$ p#"hH*D=F1&7YNАXD(H,АtG9IV~od 3)2ђ<ڐ¡5T!2yEc2\%UIO$N3m B>A TJ`j&lKT9d:}sCvH13g>XF/Z\?5ȧD>$@Ql)T UdCBP$eFyEjܦHeA-'= -Rb ބƃ V-H3HTIRPxkv/iHxp]߿仿9Ҕa?:qm]@Χz&x,u妾1߾*O~п ް> >u!4A o>W}񳿇rU'/<$=P l{؟ 96}OdW)`vp XD Tӣj{y m` v[% [`|;ga jB ^ 2`6aX@ J- HC$T `m bE4c$wZ읒a* J8zI-lol!4 eA#qI_Ǒ^Ia!bme6i( \O'@Si0ȅ ׬HK%I'!(F_-F!)B`Т sA2hHPgIʅSa'*W%)2[W)ZFcL5(#IݠjiGj#^Ȕ#c1E&<AJҝO2Z>A@ -},Ȫ/Q:udQP0crY!O: ڗN~GZ҉$1 а $mP#7 O_Gv롒OQB[RfRV#|`a 㜤B.F `aNX&eNʍO[]#cnR_e>]:|潞)^%:2١fYBMEѺIfef }SXdԙ&ݟ|ٓTfIYҦOMeʽe# fmB#P5TF!+YPd %6:΍u#L&#n2ݹ]dE~xr( BbF:`dPZirp">h NU'L cV]Qf NV z`M܅:%r=.h( &gEvv|(Bls⨻55)rn_R)))Ʃ)֩)橞))PiB>#6 wjBjZ)b !|э^&OR$~Vdz^j\kjsadn+9^H'kFk-էwhlBDM%oԳqe㉥M dhZ>h&mc¡abj;"c묂Yhݙ]'=fMZlkΣΝeԐa]zf0&٪+&4M!x(dt+$ʶcBd^&ljυVbgd!iSLQl]!RN}V,FԊO z  pec0'-ATԥ­N-c a͛ eA譱t6_VWbOVf&PboEznA pPuz褺jjZRe(9n\ٗoPʗ9Hn䖔R JQoY]2/ڀ.ނo:ajbA)nO_o{unRa)Ogtֺ}mc<.qh-N[otp+ wĩjݴfd^jo}`"ՏVE"r ޫ|JΥZ؞8 @qx.Z.~ f'Fov> ߘ+_&u) k&&.ޭ* ]nb2jN«F_ G,8-rl*/db2Z%rjmm#r+KrnN2Jr-.2l${ƫ$]kv8 uoVE-6v^,C/^d7+'_ kj>s}ߍ2˦*޳Al?1ǒ)Wjlr+Geʦ Gɞj2.Ɔ-7>Ӛ%sf37&tީ0GgGW۬M+Ip%4K{\žPK9t5!OG6. 7q--Bo0'ϡV)Wun*uIѵ9ra)u\u/M v^[#r(3vbKb0fZ^>VsKXop`05a cu"co̹zV;vZNcog߶lo0y8VqM-p?o22; Zdm K@ fn/.uC#ҶjSfj6ϨR0Npkz˹$z1nZ#Qu.'pwz>/t7s$zRp&]i$}i93Z/^-%[~2q2x>?/տT~M~#xڈ#d݌P83ߓQV}3 9&n8VMps ȱ'xKO3%&,':lXbtejp0Gq gG@۹;l{6[%~vs\]GtswCw~l:i7ԖdA@JϮʞw?'7@  .؁P4:aC1fԸ(U||ȰÒJ29  ;&(Lf)8`9":si_8,PaJMD(uʕO옱VY;lYg.(bNa),-}o߭TSy+dbM 6ɗ ?l*-_p9'Ѕ]^TjSum۷q3Ȋ/dy݋zV@W>: =z" ?podSl \Z*W=׏7y;_8CK>\RJ2L@ABҫO>Tnsϯqj L݈" 7XJ#3b0$1M«+ L<E*v E#)蚄Q:CrS7 (*""%ܯӻ)C(@I0 1g}CٌT@50A{Pk6n0_|ZBc+P#}qes ;K֬rJVńŏ/ZgE/_#FD:oe:܊v`CȲNoқ E j3p=lnHHHS5)P~$IE!$!"uba*X^JK*j؅GG2QeJܜ)*Гmq'l1N,@DDH2}א/GDamJoؾugMZs~zl㠰'lwLvĖF~6Zs,|Bޭtط$QE$uKxD"*(Jw>Ǧ%qLv;qc!7nrMTy~>sg<^5Hy/-+Gn^w1JёN5l覛Ġy]?4su~"Aޝu<&Ht;\`ߏص> =AɃIzh-3mHVc0R۝!|TU[FlHK11x{Ă/pU' i^opJ$k*{g*̫"eW`J(l =2J+nDᖑ6 oHA&C2ŒtvRFH&Y&OKl"01$=X^ ERIƶˏD%[ !&<ʲ- T /p&P - )" [P42L2i\N,'蕌/%15s322E/Α3I43413L5aSPsjb6a3%i7}us7S6828l8  af99s:Ӯgz,rO}73;S߶:jшJ<-vV/^0M :3tE';9tuo߭Fݍ< xؓ8YGCE!E!mG)e@4JGfC sԆHI t4x6/TJTjj*qMMmSM.iT@}LdMe3?3Ӹ+=P35z3OTʭF%LnP5-G)(N CU(hlҎ&_)K ;B%sPm" :24bPMMTī(Q5UK NL# Y/jN2][*NfѤuYO+KZIRll-b4Lf87ҩ + .-6qvb_BΉY(گ#\ӵ/))"8ˆkYLV ʀ ӕRH3pPr J)Y-X?& 5*?(B# 'M ]766T"XJ*QcXu0 ec[ _oQravQ|cC;vj;#bW+66Qq$q$mw>H^ODpv;J_KwT&Xt8&5V⬺bsqc1vp?wNhbsߨ:KnG)wNV Gr*Kh7%cY$ZyW9Q+7%ZK`l yy9TK)b ü+zj!nIou`JQjnHQh.6(@>@}vN~ysmeRA*z0V,-A'75,E4FdzUffא`,w#U./R(2C}2pE~y Ht%--YbJ`Ÿ,L/8 'E[~›]u;b1e2$7x!+j yQ`XS9?S! WFZG yMgEH5"Փ)ya47MMNtL4TAX=naƕe% N3@QyLbgKCdB3<9 ?xY=M]Gg蛑B%y9FQ}JiW! Ql! :/ 9]*|{c3s|p=0߅V=AW MmpI~"t'g= l)SÎc1LkBw#w >AS֔P*Z".OE+H.Ǹ`ۨ S]8~SRJ_Yؿ1o>#z9t1N᭣)hrT]zcۯ#L/ <3z^B͕{L_;PH={~02[9u:Y5f#+핯M;R?JWc$19[Y:oW4wQ_39??YCnLs3X4EKMD5DNIEy<-TE;ן.GBJ#@2s(34WjEj3:nܱƞH˛?g7o> 47ի F͖T{]_vAy=a`GR|F{|D(IB(b$`w-l:V)XnI# |0GGLBbGcD(@}G{GLQA%E^_Cc~w6*r;tEEz&VaV~4c__!XiW'J@1 gt '~KX9$չ'~A+wJ+Ğd1@r ykV5` c yŞ᪄DKDJDQvNib%^8*e"r< NLn߮1Xf@zbn [oBvy)&Lv(56ORr+5AlG -R */٪<‚I3 3 EMnPQ>[t$5B%g9sfL Ӝ9.ۖszޚd7MLl5BSQV<Š8AX*L3~ys%zٍ.@ {2"NB 9j+~ !{ v#{,/?{F z+ȐzD^+x6e4}D̓YFP$'!i_z ~$! 7aI PED,:h$nOF[.4/I#Fd] KPdG+E#ҔTX)[Cb3i:s PmdָLF , Pψ3]=9}JtG9*Ta$-IOҔt,mK_ Әt4m)B<@p! 6` ch'<@ImRp LRpBLԤ>5SU0UXujY*V$֬5PQP֭JV\ X+vN*vmc Jve/Jv"0 <ٝ5<!х A bp@X [@ a@H1(elik[ꖷ-l 6-o6q0LXok{ֺ-u`^ZA ch{ w}w X  n ā X0!0 c0-a s8f09` s X?0".n `o^@W\a;1` 76 e#[+v\ 0ydl|@* \1bΡ`Bȡ:"p9; z泟-h93t#4gșΒ\i Гnt(@Sz s(,A{s1?x okM 赯 ` ؃d+{n hK{Ԯ6Qak IA"`8c$ !,?22xAf׏x:xffx׶۾:d:fxZf: _:f Cېې:blc`f^'a$Kf::ig㶧e:۾#h8M.eafac㐶kUe:92D/]ma Cl :f,,8:۶f"̳趧hf9CJ:kf !a1tfPf`3w:3E7::ff:eېfg H*\ȰÇ#JHŋ3jqa CIɓ(S\ɲ˗0cʜI͛8sϟ@ Jѣ<*]ʴӧPL΋)W_)š/Jٳh֤ I ܸj˷/Qp-]̸JDl$̹E%O#(Ep[bаc˞R!9B5N40Ck(_p"hK~4GJc0 b! P$ F,rKDDW|߂ _[#=`{- CHB \(G,\rEiYؠ.~H~t b$PJ%#4t!!X]§C}(@~Xfl2U]~4'!hNF˩JMwX2 H`:g *gc6 _]‰U(#iG=AIH<$Cjol27g{ l|+GKC)'"De!jN֤w^*Hnl\(\tJ:W 1+oN'!B#U -~"졯 y'Zע˙:2k߽p]BJIrtڈ(%pCIv7P8%Yw1H YsH'ݔdXhN72Xg-1`5L^mٵAShvdj-8Px|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8Ir"pL:v~ @)MBІ:D'JъZͨF7юz E'HGJҒ(MJWҖ0LgJӚ}CUz@8 PJԢ:mht$pTJժ4 ]*\: V XJVbuZ} W:|p\zVkuj[ ֹ z׼6^:d ,H+Y5(e?8ࡋelI;YfSг m R ]mGOЊv]hpYK\궸=R`TnAE]B@Xr#hHZ#L7`@|[P༞:`]0(yK #ABW/r+NWn%\:7n<ˀ X A~Xz.}`Nkj]B~_{V}b뎸lELb ,BdЕt՜TA(/\Ϯx\脞BV#0IgYV3یC> ]^w$rAcb }Yꠄ=Tҧrm5'QɊVq>/ ĥ&tZ&`pqPg+}}u,tֽ5,6,3]n6 Ehf!m.;8Umn,x 42@ uV㚾崊Ml!K~xW: ?Zs+@v,dp߮>[z@'@r5Ƴg]qJ\3k PKbvv~)綻mІdU7 ^9:xKX"OvA泧ݯus#xzToP܀<gO{7* pV,Ge_?qW*Sz#? >vX2/,E/??׏@OϿ !,22xAf:fې:f:fff::f::x׏׏x:fdې::fx:BCM$۾f x_Z:] C y ںIYKLWf[yVYض4,,8yzWڲU((4 (:Y$J[F'\3̏{*&\9۶f:$5)Z"ڳCDN4 ~>!..:5ސffR:R.MZfٶ223=WZ33?J*(*X5 8ҙF]V3'::fې?\z!%ablfېfH*\ȰÇ#JHŋ3jȱc=Iɓ(S\$˗0cʜI͉.oɳϟ7s2T@*]ʴL  @ӫXj1$CTrK٧^Rٷp㞄TK˷/δueXL> Th෱ŽMhC?7AJ@BXVY'`ؠv8O`+ H` "B x@Fuha^y=w]ppA!tP݄q܇T)WspWf \0]Ӆ5 v } @b4W^iAwj_LG5#cD6geaӝ@+b ~(A_@ IВ5'AsnRi-7Tɉ~vtdz`6@rv%nY^hyܚ}'Gx݉z#cJV&jhK&*godihHbvXɦkT&-ml,2,lAR%uTKPrfe(|ʙG~ ﰫk[/zU6BilD@AJikiVz$Ƒ2Z5:C2@z*T{83nKcy$|XGO0Ǭ;'+d ptvӭ{{̧}4Ya˞[U9]c#|ZvYwCd_nv騧fAy갧ADm;.cN/e|7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7zx HGJҒ(MJWҖ0LgJӚ8=vӞ@ PJԢHMRԦ:PTJժգVͪVծz` XNJձhMZֶ*Iః)0xͫ^׾NGC2O~MbƂEe!#ZͬfYjiB͚MmX;kTD *UlgKDt[R p$)n: !L =Jo{J侠,Hv.g!(S n ]zw#K.|\ h `En~ W@"8ll]ʴӧ*>Zʵׯ`HmճVg]˶ۨ!+˷ñT=ׯÈn Z JX@yAĘ3\恋ڐuŪ"V#Y c˦zk؟C#*5xFX{ f+_x5naaq=By&yXAЀA=Py:H!-!i T @ ^e'y&eƙ gRE8tq 0D@J APG\erŊ)9!z'(eO-dn-U2i_cBM%AWJxd]ae95i'`+5a(z`Qq#蚈Dzp)'xVb٧UE\K(ugEfk:&*wY:Sqjjhّm^5bP"I"f)lT\A®zz^e=fqhEwtg/Ed`e gCLUfWb-`&aɳVY,rS{(ThrPYV4˴r֬sK@-D]t H'L7PG-TWmXguL`-dmhݵp-tsu|kSrAn'._G.BwMg}w.褗.nꬷ:ۂ.SNx/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'X̤&7Nz (GIRL*WVfIZ̥.w^ 0IbL2fҒΌ4IjZ̦6 mz 8Ir L:v|~@ f@P\ƀmD'z̅*90l$H)erԣΌ j˓ޒ=1::K@t4-HLiQf`-IJ̒8U҈2M4D@0KJ՗GMgQMZ:u|k.:ճmj;JZ~uJּsESl@k5icKecӠjT,Kz#0 D@t@jtDGJ °zU4VZ]-HG{֒LeZ͉dNW)gSZUIP@e/+؍[ywÛT2 ,@uA]`ngOzSr֩-~yEu[-,=,_:w;l{T")z0U$@\UCv krFz"&h+ {3qUHKڂ׾+Mw ?}]x72.YYѯw霱yJ֦m.XkcV L2Q` /EiX+--1- 2-3vAf3k`4-뜺EB~g>˓4;adt5=e=E&;uƆll1|l*rެh[s5Yw-.j65]: uNYeysz×eih4Yeߛk 6z``ۛh;nB'Y7u=Mz׼lc>M@GkYEq_{%s  F jr~-9&ǻ/0qPO(KTl).0M`O v Ovڽ$Ag9!W>zXEW˳[$cϽeO !,=@x22Aff۾:۶ffxזې:ۏx:xf:xf:ې:f:f::f:f_ CBCM: :$ :xޏ $KLW۾,,8:((4f:$f:f3:۶f곴CDN䬖..:f.Mf:33?f붐::fې92DablېfH*\ȰÇ#JHŋ3jȱcB=Iɓ(S\$˗0cʜI͉.oɳϟ7sJѣG"]ʴӧBJURjʵɬ^ÊKcH]@ "X`ź)ރ!ږVm >  = x&X 帹b:d)",&b 00h2ӼY7Kn6ҧ})v kf jP D .:zNy㿇?@ ݦ|>( b]Wgur=l x5}`fFĝ]!d5tnץ`j'#amDj"e B@sMY"296"-fi@"%K']x8t18@2.VqWg\ƕ׎vPuw j!`ZN8'HoktI'_~a&6Zdɉ׋{ qo;gk5Aؤs)ڥ=wXb|Φձ֗vH h:ƨvH籾ࢲ6[ cܾ~JNmbT.jPxki*Vqj2-yln&^/K~B֛5dgjkDZJlblߐү1j;isiYf59|pFf']\tj>VEX{F|fK5yj@qsќ+0-2zk\rwW6kЃwT]P;TqW$/2|O?/}JOSgQw}W/OO/o H~H:'H Z̠7z G@(L W0 cH8̡w@ HHL%PHE>X̢+r` UE 85`x#5тttxƁ@@$@Qt`C8I Vҁ RMn0c($ $l"򆏤d)r ,Q8LK"+]TF#c1X[ #@PӐ`3؀'`&4Gpj;XH,Hc99N58*$K'=N7@z2?& olhKf6ˉ2\2  ST#HJxAȞ3)9LL3G@\iԉҙ !O ȁy\+Yѓ>`a.c kJt&Pܜ K9S:9EjNu6 &UjKaծhb Drlh;MU\ UՃ+N̛r $^S}}6}kzY:%b9ȿ|> LR*d-f{ UayY[vk1! ߵڠku0m.=3y_FkaG+Mҭ-ں:Wac~#:27)kM Sq`7ũ=pFm릕6-cO UcQypѣ AAZBUN@ ib6edTD$Vg w +X(]W(T`JBd>y8:[=r 9%<:hxNڏ&A |2 p7 [v:@7+||1[XȴFfaPX/ɴN6,l,qMh 3[|6Xgj{[6 mq>7]nu{~7-&[a-Dz @ 5xdpH NH'N[~ ϸ7{ ȨGN{\' L0gN8yQ^@·NHOҗnr`S~[XϺַ>s?=hO[. [x;Nx' fP Nxt 0$񐏼 a ϼe!,Y8xAff۾:22xfxזfې:f::ff:xxې::ff::: f_ C::۶ސ۾:::fU:%=MB8Ff C;:fr:x"(2۶f%&C,,8!C $K $ D$O-_䳴@LU:f4((4ȸf1μf붐3::fېablfېfH*\ȰÇ#JHŋ3jȱc=Iɓ(S\$˗0cʜI͉.oɳϟ7sJѣG"]ʴӧBJURjʵɬ^ÊKcH]k H`ź;ƅWn٣iնPAG@ۂiݍ}+fN?kO•P lXf@+Z˜12G^pH7}u사J0yBܺk}/+>yqAx>=nWobC@omWyBox& (s3agacT@sx1hA`TWwܝ'Ƨ]AG[̅|=Xc}؏VIEW$c!9laXb)6 ՞lUbq9o8a 7КxXe5;*Axw(k]f\r&iɧ4=v֝fH/bZk&d}e9c׌&餇b[ڠy&rJ~'li\^vMtjԪJ\JС篶'r˦ Kѻ+}[39fVfbo 0e.3~/dxpfPm+IpDR 1[a%GLӽ֛~kmH@.+zhAZC0IXx"}M}xqt1[N[\U pPRaNUwГWO|i"M}Q7N>RQ>Q/ESۯB?L:'H Z̠7z |`FH(L W0 ghB8̡w@ H"9TA n&:P" (*Z*T.z`,!H2P"6Qc|8B4 ṭ=hL#B}<"ȁq$)JP#%7I! 8H08RU KybzHФ+QI0r ,MHnFY]^d CjК'@TJ%+fC4 fj_ئկ{ZZWiSl&8 aה,;{v8UV1<|+ s`Y|k;U(`!VUJ`Nvb7MύSq_ Zxan4/Iwͭi zKQ` bfwM);h$U>2;O3:nbeK<0; O x2ae97{ `3 mAyG~l-nS݆5Oـ-FoMJ5=ll`v6 d>N߁20m0ԝƔ4/ rOX≭,I\!iW apCofSa5 #6ht7~Nw&\/ַês\忹NzhOMxSo;Nwʽxϻ$CO!&,Yv 22x_# C $K C9CM.B=H1/]BCMl$곴CDN-_ !Uaȸ:x׏37&H_f@A4PB B0(1A8fDhH(xR`ʕ,;\q :@SA*LX @Ѣ TxiHlT@TR"0Z _ADp@  vȭ  D<0w'40`@!,Klxr22ԇrxx#x\x|xvx~rr|eZy^:Qr>rwi~Φttԛ)BFh)xgm{~{1خvk}/`FGM+K<vw$:ӣyNّϔv&jŹxLxxǑx{ 琑zekP4ėdv~ rxqxjx^͚6|lgqm&x`1Hp Hp/#JB3bEJ%d3*0fXr`%5$Qb gb@KfУ p)R* Lq괂7jʵ+&^Kٳhh@˶mE;ܻd%w޻ an% k7F|!x dt\y;w5oL@(]@ % h:"<+G`1T=[7 @Gj`:ӏDŽr`n+[)uk|Md0 z:祷St$@.gq>8XP} 4! D<|0l-ܡGK!.,&NA2222222222222222222222222222222222222222222222222222222222222222222222221100/,-,*+)1(4*0+,+,++,,557799@@JJ\\rqkc`enߕې׍ҋԒľǸzke]PćFFΈ;ڎ8/~~~}r hed]V Q L=9<S0xsvtturtvqrsrrrqqqpppooo'VmOrbruutuvvw"y)}49-{wtke^H;6 H(\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIfJ8sɳϟ@ JѣH*]ʴGPu:JիXjʵׯT ٳhӪ]˶۷Bݻx˷_sLÈ+^0\Ɛ#KL Ǚ]9LӨSΪYtWֹ sͻ[ 4L융oμУqׯ9+Z;wOyԉպ$Շ}OO{q(g9|-߂ 6im YA (V4ۅe8` 40(/8lR @)D `cg@(WPF)yG(+aGv?N`yccih9bpQixR矀:} j衈&j$8)裐yɤVj饘^馜vd*ꨤjꩨ &*무j+DW( +k챶 'F+Vk-f멳Ip+jk.tźl-k㞫 o ۯIk' AR Wl7w> oO$l0(q ,0,)׬&8<@LDm6'mfL7tC-T_>OG]`Qrm<{lLD5rvx}0|Ywm䰳'ΔRz'x}7#Ќ6[3#8ΔÏ2/;.z?2:LWb4 nȎ?8Gz7 %.}7p*֛:KM <%# 6E3N.3C<%$ h { /@zc@Ew?P=8CyG3*<#̡tJ ̇>3PĄ x&NPt!; g.<>.CHFE񌿙 GE6 s'.+L|Xb<4q7vLTi0Lz$AJ ̤&7Nz'IʩY *WU$*gyV|e,wi2Zr2 09K^cL&cLaL2fZӖό6EnTe6I|y| :EYvf :q4>B~5>ږ~MhдtUDgЊD6юz HGJҒ(MJWJ*+LgJӚ8)8_Ӭ@ PJԢHMjzԪPTJժXmUxի9XJֲhMZֶp\J׺'_W]W㯀 `KMb:d'K֫ fհb>j"`!}lEOlgKͭnw pK7ŬB6ܧЍt[vj:z xKMz|ÛNA2 KsN3 v'`X7 7' SX0CXwݰ<0Y7n}w ؚ킐WLd HN&;PL*[RƁ0qp#k9\^ȗq\8EV|2 Ͷt3[fiV>y؆MB:n hC#Zэh6}~|tɷs:Ї]׻ǻ]`{߾.^yI908UE@wHH   x؁ "8$X&(wce+H}|o}ڡ}u (tGXq47(G|5Ȅ'"G~<8BT(X@\؅^`xgxw/.|dž(:Wx ȃ\B]DcP]B_X*؈'Ђc{ A3hMbf 9vC|臀(C@EP&KoFg}XoWy}XxB.?vBp ͘|7Wpo8nwv^T(* RI(pK9PX<ioЇf ِ9` P ё9$Y&8 'P)Yh|GbȋuXN )tNew  gFė3f5鉸x:qd 9JPUpr9tYvyxIB గ` *y٘)ehdyx)Yp..əU{pٚIH93TJ9py@p I BR:iЙevɥV  YZ;00I Ħ䦙$=7@ЇEy` D783 yIZZ癝PZyɟ'J&j1(a;|:|xJ~ A'Z i*vw{ڧ Izd dyC.BQJaXpٮzB튦j=I=eONwz > ŹJw۱ ۱i#kX`" !2;48P5{7:) ʺ| ۇH KHt%; %  a >+B+o&- XG(Z ۰ zz` dI*R {W J:;:sTAԯd[Jv𺕰nD kt?> _;[{HP Q{!ыڻ۽{཰e6໶MJAG`F˻ч+̻+q! Dp"kC۾~9hp+[۰ۻu"<$\&|(*% p/<Ű  Ⱔ` ,\F|H|" K|WSO%.(#czfja<ƥƺƔ?@ wۀ ( ?F7l~Ȃ<Ȅ\ȂkH@ lll aȘɚɁ \F :o*vn rCҢ7~}{?< 9l<' א X,gž ,||ٓ-ڛ}Mij/%e\o}0HoI0}`o_VFWv?nAn>@8ƈLjk+-]:Ӗ[i}NHfMD`&ɽ-œIP]; Gcie 'nMM͑L# |#>@.ŸcڀٔM]\.#$\ڤ]q5Ʒy~_HzH_}Pza`䫗~izQNn_;ín<?PFH{lnpr>twn D<!(R>^nv`\N ^|`~qc^?p}w.}a[.vpo^ꝶ"'sbNf៎Ğ ..,G 8l,`5>^nٙĞ٣9n$M\mЪEίGyU_H0EP.GEWzYJ9*v76@wIֱ[N"?r>w~ .f;a*HfJޞ}("|>̝þ\O$ .PGp0.8e\F7n}],qa,HPX_D(ρhp(`?_ %[q~~HoLh|:vv韟f} \̟k.?8Ͽ/r0_doQ\8H\=~*dxPC-^ĘQFm[D2%t#K<1Ö,w"@N*uTPE4i1e:mCT H8=*"m>T)_*5fW.|QWo޻}X`… FXbƈqiɐ,exshMFZj֭]Fuf٬iqygtIRpōG\9K6/qn$ gJ'z-@Ҳfߤj5֮n[,ڭEoܹu.2$@D"pv6C?ѴVkp$Qw I[.FgF;9rN:䪻.;r(v:* '<#j5%jK)*"4+,Ԓ?rأ=^M9N;3O=O?4>qxC=pBgC7rkt us/4SM7uNԶHuͷJ1UUWeUsnGXY"DIH"7ܲ3$"b=#a=*$s 2R-L*<Լ%\sE7]ue]w߅7^yy Q T4q`F(iavXEImr5c7#`XG>WzU(Pu^]VevYh[+[lg25EڮV.o*z:jw!k6źknFM;n?<;m֩n6{fԦ;&pk&ggMq|r UN$ygy矇>z駧zގ5{O{j|g}?|Ǘp?m`(@ Ѐ,lsPv:tJ!-6ؽJH k= o,9C e8CІ7auCЇ?b8D"#դD&6щp+U8E*V`w$2삣 JF?؁0crB+dᶸ:юwcG>яd 9HBҐHF6ґ\$%9IJVҒd&5INvғ䂤+zW]w2J1 me,eҖla|^9?ᖶ-sB.(CFDf2Lf6ә!7 ef67jjӛ9,sCɾFΕgqWx5qSsQEngxmy$;er;ký?>C<@=|Y<1 $4DS[3;Kp{A}9d7<<*d2x>M $@þH+,-J/C0\*B$|tB?:B4'9!="D>:5%d>&\lC(? *`FtGHIDGfLlh3?t=5<56gg>ws]DA9?P4;>B,SLEXVBCY;;A@[$4SDŧ]tE*d;hijklF,DMjL;C` 3QE3kd[[^|E‹Er<3Z4 \vTFxGzC},&dGwlxzD|ƛƍȎȏnj :H1s45R$kpiH]ԅDI;Ǣ@dI,HEɅ<~ĀI|ǡؙʭʮʯ˰K䁮qLJ3SRcIuȀH8GLIH ʸ; K:\JNK 4IRڑɤʴ͜LLAŒhRw|G]`hƛXz^殾j}l~k|^!Uܳ@EcB^ay/ggvkmmZv}hHfmgzV욶,C9hlv`Z櫦!,-m=`m6d:髖6F\mvlKv/}b&d>f鮡NdJosJUwpc1?N&JVLWPg XthVf8UH &qخᄍVhVavvNG◎qOmt,kNglI$"jfp^W7qu>bUqΎ!dr+߉qnkn֞ViK]r'']Owrr=q F-'O/gsq6 q5qdko8OkF8Q'fY >hNY[B'_("xվd\߃^vg(ou}akqrr!#4^`uNWo](^Y}u`t&%Fvvwepoߔ~7istt?&[ndXyqrWjsMtXxwwmi2?wsw_sL]M7ijcpR'*_SdV{qNl]!\вnVht_vգL'FxxwF%'7GWg7{n."rUiyhmz:v-Wj]m{s""d2Ozoz_<c'75R{f%yiz YXU73_pק;4R*H~鿔UVwCaS}S@v~`TdGUv[r:?#|7`)hMʔ]A!Ĉ'Rh"ƌ7r,(#"G I$ʔ*G^;&1\#9ŋk`խYR;0m)ԨRRj*֬Z+ذ\ h,ڴjײu8-ܸrҭ;K>gy35>_Ī52l1Ȓ+lYI-_kz~Y751|vzK{ Z4i #V\9ҭʗ3oyӮb{%+:r=.^{i~ιs`B)Z;9Qݝ6/ j-| *Q%f"7^_"Ԁ\!8"%x")"-Q'u x#v鸣\&\o!h^{#MF!4!o 9^$aEJRBY^Uх v͖#5rby'y'}' :(|8#X5(>Y^hY4HezЙ[R&dҦ}d4j*Q l^`*g)T{,*硈VW. )Ijj򪡪2YmtLkp:P-).6ʊ䒄nbzrc|0 +0 ;0K<1 7묢j<_umko9, 2"ɓI;Q+ݽ\ P1M;4Q#|1wD Yk5]{5a=6e}y6\0+3o쭁6y7}=^4$h`Yw8K77|sLe>:饛~:ꩫ:뭻:S=9;)jͶm:ظY\<; +AKXJ#( Ruj`JXO|4 w Wśm6!sꉐ" GBJЅˉ,)a N|"()RV"-rPTB'R@}P*, 8 n|#(9ұv#=5A DHJ-n7)^GݒMr!"#𫑏E$Q)Qi!E(YҲeX|\#IIMH#֠e2|&4)iRּ&6GAn&8GPBDc5џԢ8$\}=Qn|2 :NQU m)0}(D#*щR(F3э:TQzYRst' dԨ橪^W:֑*Nλ1/OO+p .^av07^`l;B̡'(D*_yÉ3N:ԣ.SM:>uK$^52΍ʏ6qYjn;.ӽv;w~gZ>Vai?|*A M /Brbm(d{g\ER跀<"$ɣx,G4x;"!+a}zFy&uy7%]z'_oi0=g{q{G>OKO\e s<.ӿ?U<\}#; <^6\]95T=:L:t`4Rфy䄽Ch @<,`=`2<`mUE=[pDG5๬` ρ5_]30# (}ӽ6!aBXeHa:YHT>lua%^"&f&n"'vb'<J?a**A /l/4 #$ ;,aed(:8@4@;0l} ύ\*n#6+"|-.O RHYF; ;ƣң㾈XMLRPK$LƤL$M֤M$NN$O$(z %4|3*-,=A}6 @#?T b/z "41C\%>WMU#5P!Rj#Sb7.SFaV`0|W%H9_:\[[6";<ʥ[camh )%Q@R&+lR<fU&pgpBV:#@&X 's6s>'tBgF:' R}l2HB>HJ%E@;cg~h h:#2+gJ'= nY ,((h0d bτ#,a:ieRe::Έ*c j<Ċh@\j*ߞ(3>p*(X(F'p;)⦆)&t6OuD| ZƕCn)h˗$轝H<}cc%8%i+:v%^F,~U6㙪HxhJDW ~`9cf%4^r?ږ hT0O*+.#di0Ef$,v֣f)iWH@ޖ^΃&knlzp)CfBA*#좦2g2ϣ^gGkjgJ~*(Zڎ(r<QH6<-B-8 -*ÆDN;(׆+Jk"  ^2É1Jg?&l 6 h8mF-^8:*JϹkޫQif#9mhfcN㙞5l- .ҩBd*pz,BnȖʶlZ'GU!Zn#.ߴJG4~Jd?(6mNEDE>G-B:nEhxRlzY̙f/.8R>6kj+bĥzg#cfV6?-ON0 Cs*dnɢ&q")/aeHph~gdmrp/~Qߑ߾I0G0^eDVF~Ʊ~/" \4+=:k30 Qϓ/O32OO0-7,pb A)ijh; H#I$:ن kH""/_:HDlN4̦n"1n&oBo#q*732.p*D0$Vy! o/seqNGP[IՂWfHXTm&?^؎qZ:x5@4+22b >*,eG󸳬3#dd0(alp䂲_er#3azX$~ZoskąP EFF Bj>AQH<VV5=?B6+C+(VVVaX5^^5_u_C@>UO-P P!RDScylv-/+1\6[P(9_9W:DC)D</q3 Uf3??㕣gA(}{iV$fI.,lF+,TN_i6tLkrRHH%4t+44 4 !Nq_qirsCuBmQLwuu/u$0 1ww(?+=%N?K^@XVtvM+4zFY]`ћ)32=2:fps{\fN)?"3h?G(|c+kZ^?-f7ͻч]$g:3O}' X{WO<ٗO|N ?jLkb:I֪ZzTv;gc+N^3({E?HԻ/}Q}{f+Y`=g9: }N`Ǿ>4g~H9wN[|O*}+>bkk{jESC>Kˀ Н>ԫ ېַWf{= >?@\8`A&TBRq F81,fԘFAx혀Z_Pqm/Ւ9/ 1gm(&e;v\ТD\9ȠaBwUTb`Tպ%6}j#[Zj_-"g+Ow$Ņo_(@pa&VqcǏ&̏re˗1gּF&3xㅊ/cάyVN%Tvvmֽwo߿|h{'WhҦ5)M6qRH\6mq?|y hqOZt^tYOB2jz)!*k+-*,Y@ BlBŒxCH i/PK+alq̳`s:jE;' k;fF{^Rl=mš7J K+ /3Nj*ӵɿL"B$|ت rѱ 5Ҍ>*@^25*+;1EV\"X[SyK[j"lSR։ڌkBWpΐcN%dYAMi#6y=oqr-e}P𨢴2ms)S?2Pø&bSWRYf[כyTfcH-BS͗oWǫnIgs_H~$iy.서(ߐ~ߪW:.)([ [eC:Z o|fK[")QgG8Y%:qQE77]fkwV|yG]m_As=Gٮ-АA,|+1 7p_5O/|O8b/?~5%Y2mG(҉-|y_;4_&Rjx g "kdU@90 4aBHO@P[pU< C7o"^TRy̼2V'9(E-Bch-'Zj@ہ0w O pc?A*jbÿqkj J'B;Ƒ"︇<;R 1XAvk^r%zA\ T/p+Ҹ$jjpK] a+|La1IÌ`Qtf 0NsG04930t7" G:sh/)b:l ;')A]ɏ$&6͹هvtuw⒗f: v2͝mfR!7N}S*tdC ZI\KG7ijmjh:,v5_}Nu^geHZB}𭷈>O"GR$]eKMZzV,iL25$bGG ΖVei)㈺ףz;J]*PA]34M6&R{EkI[nmA0|wxI_/I@ i<1aW["H?2-oW|kVh_m">wh';#m,2xS$&p P<P \M+w _`B.R X}BX.V< _,'Ov,2Ra 0na O#o" r'FfI vs* L 0p&) v\o[8#?b> >s$:7`BHm4S "Ҡ T&/LET&M1GE2@N@Bq3tj.GD%+4/ c*(!# KK"'LARWA1 hS=U5rGy‚TrloU%B¢c<9G-@M3JeJuM `{J# (=A*HIu)!=4SnR6F-N=O COsdG%\YfD ʵ"]iF;8"#*s96/r3wS3$ V(`_ aAG5J#UQ`b+.26d']cdEX N5U_/*TTYVT5O7fmvyraHZ9c0[)ؖ::;6/`u#fFk5&bA&fA?U-4X/Ye#f#7U3p[Cqy"|vČ"rSq Y'T!ssp ?<7q֣H+Z3 QAб9[3tkV0AVWy37v3lqlxGwyIr{uWy1!Tr-7Kb%C{ g{W7k׷u{-B~ӈ{oÊ+ғwDٌsSsx665Dz7zYZ btQ7(F~%94/gS8wuuvC8ܞu8qw22_2bdȡy7U5 h8:؃3 tdӆOtu8b_/;Xgw$Jq|x&zx/jXHG-Fx+59W>3gsPMX ]D\#x,&،IГ]AVHyN Xղ'.E.XOq3skaXZq\ٓADdḔAUyD񸕣ajGmtOuc䗍62yzј؜Es+y8(]8f9=c[?x{ HT٣=m$z 86G?GFkR9[_Z)ZY-}S79ZXG:KZ;(9?{OY٥:1ڗ9CC:L59yS8vtKVکᙤً*%X`ј:㫷V$`wFc)yێ9}ڱ ˭3"{K0Bo:|^[ژk&Yڳ˪C$:5wڷۏc-#kgc,"⧻qEh~ /fvV;Ӏļ[1f73>δ{໡;{IPᇿY 疇ezHO˂E5mo)"隷"C%{hZ#}J|x:jY;@D:{ok*u2Dx2u)!Wn_ǯ22ڎym\2fQ`l@*\|"`3}3PI  џ|7ѿ`qϫeesuC)=[ ^kX+>n9A#-Fs" s@ +̼n~Ė`T(nl׽,mk@g l.$} k[ , < ^뽫"z"uQGuMZ翁]_ދ1ة&*U5t>=5V(l+ t׏}1)c/푚#Jo̟EzoZ}֑Arz1ۧ-7msz\C"7mLE?.~ި7,'"+h ( &W 2H :|1ĉ~XRq:z2$K4/eʓ,krkjEEk"9ŋk6k9m(Y&C:I+O>%1"~ Q#X6P4u/z yq` .` V-SO?PEEPTyQMe _X]C W`GYmA]:#sUH&_')aR؅dQ#ux͇dTy^*VY 8\cnF"E@`Fȟ$V!c:xiƙgwtՇZiҢ)lw6MrÏ] h F%~i]ۅUdI3bU+d(facBeWT[ ҉+["eX,Q1YqE]0tf 9ќ≠I[;Ҽr5˯O HJ#10b& qk,F<&D*W`w21M6{R1ӳP*!ff}# I^zŵm xrN[>(nźݪ"y z7?#+q Fk$O%Va׮ml`Fn>:Τd4HO.:y16TQFޅ%gպ7K,uA,lΐY"[xA,lp*HDz# n/fۇJF1_h+!?~O] DE< |!2 04 `'j{IB>5|xK_ ŷ$p&])(HT[fĉVb49kiKgHȊ$JӵPu?Q qX JAäB QJ)Y<ぞ+$PGԁˆg}NEh$jav<y2&eQqT7X@l:V6!IKdZ.e$,\ Z0&b}T&$Z2AM*?ѱmh7Vوh(3X/tՇچ/u>=BϘ,a2.r$rd{4{Ξ̳+ FQŸђYaTW̄-E}xY@-u5F* .|)Q6# z#S %|ȩ $ZpUg<(>CkZHĭ䁫+.Vt)BѳU_V(X~zVufn3\$< Kd]VՑrRNIA ev[x@'y DO=9&Q~H1 * rU,ڒ:_il]ʓnIO[J iXA5IDCpTZGo$+-;M&ȼY*:(x&if V%# <[tR(gJlFqZ8g5)UJzTbny23 LX,Ҍа Tm&! 8.?SYЃF* %8?yq2':vIBLHA}_ߵ7qy8ԆܛCxDn\'4sLDm_^}~]s۷Dyyj-Iէu.)4* l7 {,X.qnT\vPmsg]1/=x;}<v!d7 ޵M@V!4^z-K0B6̕=ck;N RyeD66zޛ'Mz9.:_q׬.RؤDUo?LȮ#&1J? fv#ajF)1Fqs'bu7Vyw} -Cc3{c "OgrW`xds})$*C}yisw\ї2Yf'3TEQ9tfSux*x-/w3587 |<zSs@B\g}-asHEV\Hxj6{uq~(xJW:+GȈ.{< Xװ/#K!q B! P>dovl芯hzzFx/06'R׈爎`݁\: (.{f&ȏ V(\qytB 61 xVx؏;  9 A(Nڅ Uho9y)  pCh%ѓ&~)i{/ђ族Kh:&UL)SYl|7Wix!t-f(XcI 1$iJ/h YU{XyYgm9$fǕ8IYHuN+$ØٔVy'f*> t9oƸ%|GZk Bt{0 l$7@}sqȚ疴oj&y(QPɶ9yx t?1iȊIFj2!Iy ɝA3VNi'hE 0i0() uY"ɠmy ։9Ox ycuw9i&c 빚 9 )'nY /j:jxHI:͙H9J cefGyCZ`.9 w> XwB3ڥa a*t1 Z \z-(cFlJFlk')^f iĦ Ńa¤褉'SJ:¦D"$Jsj1<< 'hڪ|>EJix*uZ$e@Z K[ڥ(59e`1Vi48ک`R6ul*m,DQ`zꎦj W%' zȪ -ph9 ˱@ J iӚmA#S& ) X/ 3ղ jlq`(G꯮16JតA}zT[gk [;![~'T'A5, Xs1? a81<},?Z`JӴ\[BKlk*cW Y)EP[`;k,ړh[i+ )Cĭdi7zk*ۻsĩ1ߊ֠D "KVL0`뎪{ƞ~!۽Bዱ#*jK:$$ܛ;uMm!*HjzMI0e)ŋ\D +ԋbJEQ_Z*w/";58ۣaqq@!C\FQ7:Gi6:o)K%VR$¶ּv[F, +/3|FH,}%̳z;'z床wHiy֖7w#SIzSr;({< >˼Q_rWW1||Ȝ3ٕEI%&Z֌Q>\#tLlÔ⼿˿Z;ҟ̢ Q'^0p|UTdd#UZ] vH/u곬&wtц$2'YAC% '|+2KdMO+(D<,p]LJRbRi6]Qikj8l865jd*FDGC$ Aգkl9s[]z~a-3kjx-2 lnҀwȭ۞}];|}~Ν索}ͧםݎ}k:8߫~SS=F@$ ۻ})ۿ!ZB!]m= *]iPyʽ--LuM](n}gTUWg8~jA.v--15˽ 1==Ve}$x:ފ<)a}-Dnu( >}~=QYxX~-|_c.rnrqw,ܤ^t]E}l7nE~uT쁘N*OfI m"Ѓ.К>ќ^(}IJ>n65^Zm =/NdIK~<Ɯ쇎ƮÎ1ix$[2i~!/2Nש'(_m0Q  ~KCO^7޸ ߞp,#/hޫS_B^R{Xξ 20L`nP¾ 1vG nƞOPT_Neq|n/.N敿.XA=8)|XWzIQZ/y?O<>i]o{m-9ϸ?uO /ɓ/φZ?7>om/fPP@ *ܤLٕ%J$uE5nG!E$YR# 3Jd|Yk4"Ƶkx EVKЃqnlcf[bpаsM,װ-ygZfF֭X:W&#j ({0r"zȑ%O,jJ I5gСE&eflUfks m3PgF ]ZŭZD+ds?NYuigC->`c^.{S/slKO zN8⬪phB*H! bw 0C :䞺-2|*dDFЮn*-J Xp(2co?$TrI&95آrJ'i+x; B!H>4TS'3N?ҪlJ߲K K̉[sPB M.- o쒯y{FmeSK}P[b^Zp^Vf/~9׺4fhn&ʐn_S]!u\M" ӓHo#a"(̍Is 2f|:\'̞Mgj]'/A݄AXAK('QĊn+nAK*G Ng{`ݘRP)Ҽ33<4=\uc= .j4$e5۝ԩTAa֋:ҸmEc-7A[-؏,iJ$.֯-&`; SfyYreG NfMnMyx&mo/ښ,i3v|\p6H0WRXèw5g=-c^FDb Ѳ q FL)^Ȋbc}.O&5WF7W  ,r}a-CFLiiS[CN*K,eu9l9mj) yO>Oy#^hSZMsbNl~Uٜij: !U]?; $Ú ~2T(G$Ґ{O= 1X]TڳnOmb[꽵ǭktܬ|Mm|.ȲlIo;cIIv] nPmǚa!~gw{=l.~n_ CX@pqF3nҍrTl:}-SAd0m$f on_%xe <^zF5^0b/*`&_kKn^=/ -0bg*͎vFGU6 ㋙MY~z.S]I:ď{q%-N6=UcؚŮz`"5}/u{|ߌ/n|[葖>ngtk^ɃA^(ǹ|oMK;Zv?l"! =+@}Sk샾<@O#A4A+SAT[4?bkiP }(#L*`ۖÿocS=%B!0k@/\š{BKA,&>.!0<C3 4PCs%z"( Sċ-Ј `GD G. 8>Į3<<Tup0hv "D_ a& (,JPFAT#_S;\TlTG󙙢SGLD)+T*eH0D- D t9O(L,:8PTAL?6 M+[\U&N-¢$ʫ=53 T)T8/֪tK>ոT-CNCtAۚ`Ww· }Fc[)VmXǹ+ ,%Yi_%㢥3+VД(ֿFytYd פYksJ׫QWW:n_LY=54 Pבc*bF-X@Zq }<6@% Wj%D.@ X.^b(\2.1.:I tkS. ] ǂ}l0n ~X7}ڪ(\:$C`sTqȕ\ T\I}-@FЍWӕɥK~CEұ0ހ VˈRSXϹ[(eUU 3i\䓕su~Cꌜ x)_B_IuQJm]L^͔ {(̫Z5 Ҫ +T"+Z^ˆ+t%a0b=l?߻ݓ]P{A )).I\!xQV]"V#}aUj~b-68ʐ:Da.K. i+QU[8^a{aa _~HJI_% 9)d(L]dB黩 9 (>Zâd5%dc[62٥d 6GLd ^GW^|_@fe&n-%dLU~#T&g6V,%"XeAq_B$f^K_Y foebuldr&մ[ih{ִj)lv$~p[5gkr&eM֞9,x%g.,i gezWZ(D艆F\6XreVMgnbu_(v\ye5Uihj/C9ree>"rf[3!iNNNFVVj+œj7 k j9aHmi>>kcymz5WE&Hk" 91G̓k}*e~ >a;|C)V]6lZuvlM k(mtS^mVvVbxX;b>N.^&;;1=d_%2lm5#jn6ffAf馻&[fc ̼ EV4.kU0#]|4) 71(yð"uOqթ4 \AYvCkF۫䖗pʶt#"{O{tz6U"+uLպVշXY|]֨O=b5o?٬zIs>:qnwy?OG}tl^ǤgL'u҇+"< ɢ+W.|w|"R7' |/}`6Xˤ@:i>A߫8k+}DigoA}z{}Bx񬖀Y p!C)p"E`̨q#ǎ5"(r$ɒ"4r%FR+%͚6ỏ1qQ^5<4HSNwpw֐aɔ #/r K+-V.FGnE-9X5pW.iWn[Uϖ"`d\;25"z4\]yz"]W-{6ڶog)]fv8O.&O4.y4Ҧ@)1xq3ϣO#pq\;tґ*%j]S{x" q7rAx| eLJIUU]=B 2^8VF~a\)8F(, [lRd I0ANfd(l..R)kyi[݀/ƛYgfY)g9s=W!Q(aX݆u E "jjhd|xRy5y8ƨʒ98M\~nv<>N( +Č'VZ1\U>"Y `XG$)fF.UPveW\r) YX$f^e"*P^Jݬr*hpj/ LqIy1j 2!0W2m)W?!ƶ~S;Lb/J%KXD &.Q؅LJV2y+aVLi eXig6G^A/k4[>#xU#&l)䓫1ZʲF\k̞Js\#ޗ:an_*B޻&LWZ̹ Vc6.㻁t%HG撇o?CRN߾fOD ęu(1. l|v]n\v;;A5uIU!`n"z |c`\sC_ƀ*GDU9 s+&'y_њ@-Yt7:1U\H q1_D:31z4"'jR_001{w'uFYIQo׫dCNKH2$=)>ArtB( !ΐ#eH {`ʽA. yH_f&1Rӟ 'ȏfΐL"ch`OaD9ʈSgN`{ %p3K\t'LY3$GI<7d?_ЁZiٳg(AQg+'[җL ܩz7x%7;/z'^m|yKYߺ*H-1s'\,N`Lj8%p^wwǀ4̹ F}DF/ C4Y@rV88PBXǁ֧vB^1 5}1j0ϺiZ=c{U|s>ăIJ7.1i2玮o_*@wrI6PVkxd\on5]pNV6n[tsy3uܦ6K)EᆪQzP=J=sint~?ߊԮB]E&'u õk+d]85eר֧Mrrc8r7W^'1Y& >ėQCw6v"DŽר"x&@G|b[C_a9SH=evr>oR<5.OxgCDĿmYݚI\X@:ܙǑ$5Ӎ`ZIQ`m` =C5/$-ߡ2;_lР z?`` - l-`I``B1AYe:_ V 2l`4\BRB,_Vچja%al@ ?P%b&2aa5bUl*>%+aӪaC`L%#?,#)ׅc5EQ-b#c=EN.j$ &  b-cq4J<&>"?c c>a@$ F0pYGfA`5R6BHVD!۱ZHj$"•"9ڤM eN(RbSSJ$=RTг1[ÙZ7Z!ΙZBAZ^$F6$=Xex$\ETX$c"DN.=SR=5 XJeMP]0e%Nl%qP&]efv"#(`hhDi2dWVW+fTzb)Yad `qq!>ౡ&c@K6pĜaBL"DZ86AcJ& e ^C5ka)ding5|=V}"a~n~d<|roVhM؄Rbg(fj&暲)=!Bj>*?DVԦZP{h2JRꢚ**ަ])ojvvW&џr jDēI98*5(9L*;4Cޜb*^qj}Ңbe^j~kk+İ]j*nԪ ޏrꃸkE_,1ǖƒ:洦R:e֮îäã,+j,"Zl$*r˺,ʬ^lqvj-C*--n el”ʦ C9L98 2+k6ƾJԂLvm-fj>FmQ.2(.->.E߮:~ׅ::ޕ⢃34*⢞n.Ge-R-5.o:*­Ւj>o/nboXoʤjjH+,-:$/.f/Ĥu`ko=pooLLsmc,//[.ٯol4r,:-&-0 \y0prK0v^e10-'!D6ٕuvqYXLDOߞ%ch&c&G'Vl(W(D))W Ł5qѥҡuY^uN+' +W]Ck"#O.RT _39J*͊:cj; ;V<<'o=j7l>k9o+?2@ @A߂AS1hLb"[yH135Ҟ N3i#^b*s3FNsOt=7+cGٓD=~@ RHޫCCXf{C$z-ţȧ"/i,a!Gp|W/ÿD $uaB 6tbD)Vx! ݴzI4yeʒ׎Ok/bԺVX/p95Bg #MvHjTSVzkR\v2Y :zmZkٶun\s]IsTKUiGWL.D) ktn&|+=,Ƨv?{kA,sfN:L Z'"%| z<V\8BPZ%hu~Fsޯ}*D(λljЪ ~FAzWmߴ[|A| ק/y;[ن! Bbhw#Otv/!8ue_!8ps4 *ٝ' hF=Q+ KxCCR.9uxYض'-kS$F:H̡<&*/Oz:%lHY%^LJw!dA| Lw$9 &3iB 2I ^A8ɩ*nG9bfKSVsֲ5V"L~d4I*)=b>COvF`8q&5xq=aTӆ3knČ 7Q)9yp=t<'*ńU!=ìZM <(RZN.jɊ2c4;JFk#niI~N$M&HjF&t+y9HqA BCkhܣV񩲪G='bvF%<YN6*@3;Qy>) +5ѵ`x̙6SoeW?Էm*?SN>w. !,ihH.ղD+kyUnhqXRE,x)4AfK Ш_ s&K_hΑOaI*\ֳ̽s[H.D*Tp1(0@&ؓ0\La*6o~z#bW8.&Rⷴh| .Gkaxӎs 1Awut02|.ôrWIGxLEE."],T? [|_Rf/IW<6:w-\_ήS3?a; zWwп%n (j vN`1[wj:MN0Zz)4n9rF7h+/y)'\uH.fh}g^/cknѶIlB;α*jmw}oqgiG+ALZ@2}쐯1ޑ/R{ozM$_~ޖ1ut*Ӣ?5EW{$ru S/=_?VfzoTO/$r"p>M д`B^h'1 ^nCp.FJX/ѯ)23&EJ%A44W&3"7"4GS^S3e3) P)Rj* -o΢ ):/EF-.+ J)ҲN!2p(:\Do4:BG+{4?n-6-s@+JA?AϢ5A2Kǔ45-KT7 88?TBtlF-.sfJ1S/ nkb4_f.jOq>G"HQ,)|h}4RdPs,2+-ZSM 2CUa6Yr5_5KRTuAatCBB@Y%4U;20E,@Dfz1 E4SGQ"-3>-UTujGab/1[H9-I4T!]o[ 5JrYG)sMu`#V5IVajuK5$W`aDYՌYu=}OrZo-5?]5F6uQ\dD&] 5\^HqF_fvIMvyPfT3#v-h'j 7guj'JBMmLSsVr(3 -zj`?2X3c!cMOfdhZTugye^-6~ov]+U .uoB`$ܯ^I\ 7]1Q46-#$݌s`%QkVsbU7W2t3V3g5YqmAj!?aA^6PIuR\q'fxЂww xsD-'No$p|q.,zW-B{sTTe @mMW!$s#Mrٴ`QKu$vm74oV6`m}vYi}!r$w}wyTt~B6-u.E$ҷ}@}SriygkWq×)qK†59hX\sxIxhwT~V QUM3$3V!b%4Wj&'ɘ5X-ASvsSskBxj%-ڱNN/80jIB'H֊#Xg(^},"cid192gYvq;98;u.BٺЂx{ WrSK?2a8! #pRa XAl'5#vu'V?B4B-6rm6 , vYٌ"yCFbI85vWy}9?JY-sx{RUxz8wwYS:Ku?"L:YS(yޙCvQax.1!Z$3{.lȑx8ʿ#q*2|I|G<ěۯ]ŭ_aM:+ٰǷӛ-ֻnc {mxE%~._ܵ{孻g\%[|Ǘcߣsۉ G[}:K~-JxW=޶!~g껽9W"^']սY[g^Y:=6yo(W1a-ʵ^5i0|ɼ⯾0)]{򷤄<ձq|[Qg]}ݶljnjOnM=ةQXaA??}_KJܾ?{E+\g|G#)#tuW3]:lR%bk(=wlq HNB v Cnȱ+W<^$ťɓ((˗0c$%͛8sɳϟ6Ig isӧPrva-^ĸU^v뼱^0+C07)Svݙ ˷߿ L}uyh=KUZzvlZgתe{2r.K װc˞-XH!;hZOi1o3YhG2;pXn CUB.2nE^;n!Ո pOFh1Ήje&,aثʪOH⤤pٯTv[eY˖kW4;ԳJ[c-qɭrQݓ(Gs}MQS0rG(C?쨦z'*JR8+S@4#khgn"r2.&t,H'1>kӵc3>O﷧Uc'+-ذ1 ER34Tνs2!R]MZ0͟}hĕ]DD|87+"`E砧lK0\7嶋=uB{-.qM'v2G]U:֮Cky71kܶVC)AϨ/Nm,嫷Cʐߊ—@˿~Ϗ7~xP29pd h!赤t3;R'gjz04oyOvD[Fx;~'فMLϢZ56G;8ʦ) GOq'';RB($ GD .u%0&F#,K3)BsMADA:/ TW -bzdseF5 EK[fIUuA׆ncI6T+#ڇ\Io!b!㮋!?ut7’簫ZfI[:d狤]V[38{@|V _H /2ľh[Is^:! \O 1*ʽ"N1 +Y@V`9Î,? Z 8]Ld̦E!+WԞn|Ky7%|T!pܖc6I_T*TYsд5/YxI39e>;˛aJbFm^WJShǫg=}qcӵ%s ѭ s̏|Rڿ*3}ezӟ%mL'{Y?բo{Mow 渆z-=,Yp$hmo;l`xRbpі<|ݜI~{:50U]o;%~P[Nsz ޶ ؞dD7U6u 5|&^ P tR8MngmH3y2暇$N\R?; KYl ]S !/ԯSYxYΌg=v_-=֮tj/u(w6^[\+V͞cZ6;*/zȏo4OO|)U;-<53ϭ^,v~EXKn~ Ct{3?LA5{5}W}tugl}p"aZ=tG}Wy}1yǀDa5mca 5prjGLO/M-=qoO{}w~8 bgt'Ɓ;!׃$8/ eF x[hEӄh'4I)q9Rz.8Mb!z(W GK aa]%>Kn^$3F5{HMx&<(yG%y}CHUqyK(s}Phqlxw*"%~('#7W b68G'W .'ouU? "#UWc13+gx7:sTyQJ Bw P tuTiCFHJx`ՎDQT8BZXAi쇂wXn|wvنyA(dX ^S{(!9R/ ԍ27@oar (Ƕ NIy_E9uJ}NX~(hhWyvY@/' W1 ]Aֱ!6d(+Ш0ExY9b7ٕ޸k$HY{Cd*)ea<HcS&)b蕨k)HiFhyvun?M`1ŨM4(*8 8CRT1(H@ؗ|1C\zݕ q?"UL\v]#ƍ@z;ov~W!YC`i%F<:fQm\GAGu ϫǻ,:XS򅪅L+kl$gr^j5*zD;Ϭ0|#p`{2YE7MLf{F˹ !TjXyЀ *eM_LE}֐Hfd%0k=Z^ ֹEtMN] 禯RblbV<v"Vׅ֒QeA,ùb, iŶ ldݿ]֚ړK˔>ɉ]U?ri?ȇFW-ZK- ّ{;T,]6l/ ۶uM֥طލmLކ!C޵+mմQ0H1µX8ƘeSWQ4˧(E^9ֽ@MgGsVҿ|hWrh`L߃a ?QCr◜}M24.6ފt-HP갚} Â(?`MᎩ3/@n ZWɩqŽM?C\?T]ZϘ~pb8g #:S "޲ 'Cܻn8N"zOKOyG!PkFN{I,yj⁦ꆃbK]ڙW*DgL{zҵ2+Ov!J?۷74H?aulyh [N~! N ,Iَ0r ,~-n+ȋB+bU4 dAU #cJxă9'z8Q<$ERM(8PTU:UV]~ v+ZGJ$eUm.Pqڅhv`-qZ-…(ּոZ ]*YҥMFZj֭]:h"5+#V̸ǑSƯҎ4vΤb^x,;}opwp}[>X'WL h+G2(`r)$4 X" ubЧr$pbC|p?Hİ J)꼵z1Gwǂx: ٰk.䪫Ɋ\.vȁ hqoc* ̕ZlhF+/N9s#i ۦJ,+8üTL1L`PDkͪ3SM7Nč,7@>;TDS2LS:p8PE b!$Y*LY:j] xd=lVxf~/h5ftAYiŔ,r_ ʖα{e&笔Ρb<ߎ*bmmJXo nlhq~oP%kRHwe87uWh Wӗ~ު7hg}%#_du<(/i{C".HB"Ͳ: z][JWAvG{4eկ*q!G”;wCF4yPߤBSχ?t *=><>IFh qx}E. q*ÉOqDu2[ȴ))* S kH`z9 b)<8HBr/J rF} ViQ+i=b(C[u0푤πC(jc?4Iy}e.HJ1+L%YJL2{64z\Op`˟gd΃FQ&)BC.S&i)lԥsEMZzMvNdYĞ䌐d)֎̖TgeК`4c:QZb#]eWF0_WK9֦`RN I^W-.&uOm%}2QU*P4/z2FU_ZfշoYpEJ…;#ǹưYJSG  -bm=pk;iO2t/fzިMCPgkyA c"FƢ pnWOvva*'׏L0w.\e. }XƳKZ-rI09lH10韊8PnQ[ V9vVL*j=7r.W:,&]fYjiNe.O V/ٟlT"uȅ3Y9sebaOjFzł~3Kam(׭A-gkGyYdWx|-$i\JeDs 6-&KsL-w.SUԮ hÆ+xL๖ekx#n-c]ld#^Ic:^q\;XĂ(F*H$q:ְz5(&ϹE- _ XзoK8tN&ԱHdN^W/6O.fo6?s8wmvsO2'4 `}488=Fwh(6ӁCwKxu^t[Mѽv#96.]|W{_!x,q`'9WΣknCCZ.|om&=AҢ&CHߢ˟GW|73@=#3 \[kH8?kA+S ec䘤| s; ->%ke+5| Up(ۼp37Alc`d8ª2@(/csp;FêK0B"DC:tZxT% %Ί3N wCEI F#%܊E$'MΘ< V15Q'Qܤ!HCM+%$#EՊH)PY(e)+S=9܄G+24=Q̺̊3ԮS56]ʹTL9=1|/=eR.i 5UԪ4UePșEU&G}Sr5 4M=KOȍp<[x}iTjEV$XOݜ=*ZP1V ܜrڪհ]I-+EP%ܮ୅ᥡM!}"]ޕiҥQ E0]0E{ց] &ֈߕ6\ Uc{U`ZKY_:΀*5`A`` (_'`E]hz߻RV-Ϭ#W@߈Uۭݤ ղ ]=\e{=EZHi\%6Ab`Ɵazy6a݁jIG=I&ftd?C~aff",FۅmѝIL8JK.8Mii"|56Q\vuMHIy~ܦ 0^`j&+՚EHkF)t%$]1't!]"i$y^] V 8~n$eǪoNo"mL} (>N9FcDK\ flcE^E6?tBDV2ݝnYHQ]#ҦVfp9!k<H[g"tv15-;`J8In`w .m%?M™Z[d4䤧-qZfow#x8bN_YOdtNhNyGʜLhg?A.y w)D.=K9Vx\{ouzuJuQ7~f|or JmotxMM[_}0׸ Qlнzܹ)=v>NWqeQ~9ۙ[$QޓSW_mm}Pя.@TJj`}+H*„ zA'@]4}#Ȑ!;:vagמqZZb&Z 9S,< q;m)ԨRR*Zr墌(ðbj,ڴj~<8!쬽2cܼz7G(|M13Oo"Uve2f r3ТG.mi>;gƵ IeN7 bVB|yͨ3o9Ъ3okn$ |6¹1`"Uʔ-;~֯ȓ|auU `vyՒ5ՠP)c~c)!8sNVk kb%<08QToA K LN'V*9n6nr_,liVt `wKʬ #6:Gi'ux݄B^[f.<$VX}OY} KW@@yS Epus$eo4hfNL]QOJ$|zEo&_[xs^8AvM}t?Bm ^*G9-5-_+߫c>Ϟͯ@r$TИ!}^Oe]dE5vMB]- 6؇lL ?I!ਉėi0`Yqo 6sy%yD@5\>:U}_fğ A '\0`%m }q`Bx xiє3Z|fͼa!9H@:  TJX(QYn!y8W@;XS(\*2 ޮ,yX?,=}W=WSXant!}ayݐډ-+DUcb'%8]LYkY#6j#tV-tc!Ғ869&9# f;@6>;rc`"IMS5/\ S\00SQ9̚@xU<7Q&-R?BI=5$ 0N017N"(Q[N ?H4!aB-D,+L]x#8\==JG] %R*JSJE%MG[DVKR RzK Q2z]ڟL$_a}Rz ?d1 c)XO".&vh :r[dr%be=fl&fZheW e&{&y2O`zWMaf_%٥9注!n^"XjjMEZ~]SL"i#!^!fp= :Emxfi"3eHZ]ngoO>[gfg}Nr:[(sE94&t ֧Ԅ ֝'znEzmXU`efQXh%bh&yfn(<&Z?pʊR\fer sKeB`FĻMey&j!5()?R VZeѥ(e(r Lɨ?iƙimn*'xmkD9֒2ILM̄M[,ilg0jU)wZձb}jhG6*#ۼ?Tj-\^2b!f$(4Z6꣮H̜)enjbf!ꮮgF-Ķge(+Fj#ZEp꺚ie =, V+ ڍGrzk!+4ktY%Vl jiHV>zgjG(^,Ջ5(,l">wl[`hX<%lliѮl1m8-EqJmpȂ(wNg -^->.* eKB0mj^0jVkjx&lvv 0pE0E@pEš4\ Ӱ0E6qt,Ɔ# +"r%c.fa[q,_mvLp~HG\V{0 DAfOIv*7ZY2ɓn-U[9EU0U0$p ]1Ne>0w+11d^lᦱIN*S1+;O ,N{0ز(H2UmW#m#2U(%V~D0.YjzH,)1ߌ.Q-,{,/mrs<#I/=oq3m57.DnDRamVCSÅ37263!Q.9ǭ9C+Lk60t|qC? k23m1BsMMGmN˳ c:ˆ3 >PCG5Yܩ#_4G3a%;Ur]6y4?%†r0r1k\gSCZuBF*`H0-ӴW&v ާ8_.~^H_Z$?v1X?_V5.'>!t\i2Ju95ހLO^3%f;_3'Rnd6;#6&s8v͂waOpuf A FWF>=vtW6o$Z+7T5[tm](oL3w bC7tCmrr8s;eߒ oǜfSw/eeo7f&C'dgXgu~X*ʓ#뮸UE4n;eSH>$rZ<$77EWBEpݮWƭv>Ñ$xKa0t)y'3ynG::xG>h=oO8j೾W?E]~%A⭃ŧP`>Dx;{꽢Cx L)_*?eMzu*AcÄg=2i}p~asg#]>x>@8`WD 3bEqedG.^F8dI'GvL`knZZj{fy5^0eg.&I+J*%jUWfպkW_JjqxA3-A~m l2̞8}MB^3tDN ' qcǏ!G*6q3Lk-\pL6ioСEN- g6pC  -5cUvXYp·29ͣ<x`UCU]JX6f`h%ds rjgy!U8^FHlΈ+i>nv\MY䞹kUY!q #}[xa>~yb?Glp+!~[6%=l$5Br9f&sxlzb;Bku3"˘7˼0$t^[rd&;aJf*h$bfp^8=T)8^-CixR*8'5?B!S[?lM`H{x-#["R?"2 HCZ dW~0p3+a  މ[ qBM%/b-ec4Y,͌Mа e0*bAHELqen&M`QӸMٓm{vMC엾Gx$i~pᦑNG|n$HeP 6%/uk [+K[嶠\sa17QEtYW-3_Q/S3.7-NQSmT2TBaj8Q0P-SͪkK@@4l(H5 @Im#bhA@Ual@ǤBYYͦ1!;CTP Ya{ȼۤNbMhU7ٞZE 53~öMc+V6o:qA(BV_شom{$荚yᗾtVy*˦ˊp6l:i㟌h Z 0c`0X4ÝnEb(5 QZXQ6LV'Ɗ-~'{O El|\69ʐdHngo  UXQ)=՘Г@@Tg3J3g㢌]hM/Ћy oķޱ}EZIGJC nc䤫XzxMmћ>iǝݎ&=]AqHAP6 M-lpͽ{H݌VI;xLCw=_PVmydplx 7/l_́$y].oNvJ;܎ϋahۓ>?Bq{1V.FslĹ)5{>dJ 4N\JEuÜzk;πEr׸ST>.^8w96ắlKټr/a]YkԜ_~sG8{0]Q.0OU૥ OSa=VɁ[H[ Q_eiѮjLNH{am8%~YqH՟~W &#䪯fA(,-0pjO1>Q$L%!W/QpNxeMmpqqoemfG*r qEP!ѭk)A I2%r+G4;+3q,-fns$..t{#N&,c<{>_?mB?k?30tN4% =eH==KB>c3U0TCC3 "CCb,w+ˑ^!rZ2>,lo)S7eqĊsITt)YnJt iG&3HyT4%T=H:attf4qL'rVJO O6MPPLaU(TEM,P jmS+d ˾fTgMn4<+HЅHO&8tQ1QTWtR{:{6../yXP&Uu;l|OG}d\!lCLmjH0 AfG)VW[d`$<n6o7soKbF)!.]K j&ʱD!l_`l JҖZ`m!3-V"ICAYwYZorY/ <1eGyw[7zAq{&w{ӄ[zVz;My7^j5*Iv"  &9*!*㑢ZV c xMHxQoύ%wPL+M_@VVswJtyN&p5eyis,)JZ/f DR37q]F:3G?K8XUY7}"+@/ؿ.:郛JFwMp֣_jquwekeWYԗwF@Ĕ]G"HsyϗU$Xؓw|-ֆ# Ch 658FR7}78!2خl\j$4lE[C[8n'2qMoQbz،1= /FysZ=Se*Th{ rc.yw> w՜ 0#b&xá'j8,i!28jC׬e '_Rɛ&6AezT9|O>Z)w}e%u.+6ZX+NTh&Bn 7-2k'o8&~YfxdaeVIXmE]y: z Cg?Y'ڪ+#z-*~Iѐc3}rB&t+"Zr{ n~|/(ḑ[jtvս]޲gked7׽^6 ~;^߽?w+^ 4<9>]Իި9]ݝIB[~Ⱦ[ yuw< >1xՉ:I]C{<#5k}$X.]ל;#j4:3ac'sz3x;%VQBg_Cto=B <0krbkj]WKDa$xqEJt=T6^JTNO&@$kEKhE:in^t oirgrIص\AXU4#b#J׉ '߄qZaNӛb5~*h``*&j5ߣjWXj}٩$ ֑h2k( kf?*[,fHRiiM0"ڃ#=b,kzI1+0{]i'Ioyg 3Z+j 诧* qpAi 롣"\*&.Ylq^*uej[=Jt;G`;ٲ.=;EZlme\ÚEnte[Z;jjvogoS3̮ZS 08,!Lx=}̝qz݊`Uy#~x[8],gŸx-ބY70RK5LTy.nϷg-e9fk#_ݙdgn}ڣo^3 ':`ը^+rߋ˰%Nᡗ}#UES>Oa:W~ȟȁ*Xۇ9 v m&v!$]@5%aFvHkKH2&TP)By р=78Xv0xu8 鷉`8R||gx 'x}}-8x%TRzlȇ.s2.o{gl2{(j{G3ȉhT(ӸzbȍkvHwsẏ|q+WhҎ}ȸ=GX:uW?Ȏ?7:3Pdэ(wrstOxÂ"`IN_t, q_Q2%"._NC&tCFHh(Y"ǵ PEH{1)$ҕ6Q3egWmYn)yt s;<%@BC#;r`.!#S$7rHC($%F&1rҐesIyi 蕸a6_-r s TwEV~u!1c.9x })R zA<4WBY- ,N.aSvMs2?TL{X5#j7St! dy2i8Swǟڹ՝A4S'ATDrT;4KcU"4 jHF5)sZInӜ|c9juuyؠã;ZVA2D0Ӥ£QCԂdH޹$~ujRNn.T/V)5ܓ1b^bmrIEEGQwm|2P腨>@ Iwhtvyd]2 ʱմYCC*N Y`!N :C'_zg|j)6n??ZuU*7j:ںܺj9!Z '®!58)|qT3ƒH$6#%I13t#6xz*(vo1 {V&²])0ڒy +-@K3ks6& {Z߉6DԞMi!Z;;=@?ۺZ{);۽J)jE)[ ([Â+WY \XQrlMq}XB@4;'Ul2=$ݚ{+=ԿiCEфԇC8Օ9d4̿`R|̶|ٷrѼ9(`=!՞[-V]i34cmV ;|m^U/X&~ Aء2p4 6 BA1C@הIو X} آ-uʰM=W؏Cd}3S!7e-g/Z51Sp<Ϫݍ,S+ٍ9˩۩ێ-oSm'=>{Q-R"q>hqߦߴMMխ $߱MbE|gz1E >O6 _V,ύp --f1>ݵ2.#n5Q}R 5N7~8з- B.Bqa5lO~ۼ 5Q$ q,1 fkL[$lN71 LZԼzrȗ$ǞmxR6QWmmv2mn&uGqNNܧ t6Rܳ3{6 "h<[l$%<ЎX31$,q=aBn.'%N + ]7nno&ۻ(Qqy^ Nn6Hﰽ燝X; ȎB뼿+, ܼ#/&l};$ҋQ}7!*N (y^N "b9^< OB?޼ A 4Jc͛ g_4DS(>?!mm4):.FI(sF]_ب}?EM^SO=P- Dc!\!m* ֒y.j>cXpl4A >XO˦Ve*#> NiT\Qo(ER4%/wO4TW"'sdh>~ *hP# a\ [xǁ떄d ).1eΤEٕ89uϥ%g.%ZQI.eHSNZUW~/VZƒ-[k^-͂ yݤ^bZaĉ,8cȑnXfѪx۸srlҩVkJ+vZfAk.m}w(D+:tdu,yE;wa2hʡ]Hݺa&T} 1bSpA[s @p7ʌ7ꬸh; RcASTqِ* Z4P84"N\qH"Ql6J j: . q[ӈSE*s4 /x=`CzߜʹY?lF[j҄v/HdSsS-*c9nWbK.d%Su(x7V{N ⋎O>zh!ꋎ!|Jסl${ĵӨRZ 47jAri?}gx8grq\Ņ9I-5ӣQ+_Q1qOz\fhM0 m0Ɓq`6* jV& m M "cď!Q6d^((*R8X5i4>0G3<-~b<+PJ-<]K!Ɖ '` HEqdV );IR'R&Ǻ1:)UCuғt2X>:]MEKe^c6ulkY" uS-O1[cZbɚW wHčCmZg*m[;]o{{I}o}Z7xܹ(o9[0%\ۛн$7̭˫=QQ`\q+ar 5Fଦ}m|&>j4qwmrZ#Mtа|ݲ8 _R,ŒX؝Lb/(6/xWۃDNzg xUT=rRhlD*ܧ?CсW s8} dTW /_m2 ƅpSlXϵZ'7ٮGl"kZx^`Mz" |mP n!ȣwswcht:VF#j'|5HؖM zSj]eK٫1\J-qj|8U^jSX&{ /!/w^nv]F$z}y@peLK߂g\cG-ZϬl~xxk{M䴷vaM=;E[>ye:0.b>ީByEZsЕty[ZgB:}EZ?K[ނISNvDxC NR0bS$]>Q.wوOo|sYMfKMBocޑ7㹠k ËC7=0@w3V= > &+c+g k>x>S ?;ֺ;(Ծk dK9\&)?ʨk#۾),A+"km>%(@'B-l=qA:ć}p|3B*̳4X@1A9 #b8Vûǩ|iix;KAar: ǣB4i@6K>F;2DKCe,\7xE萓@ |=]$:9p;@K,54@:t!;<;? S<@;2ľrDՂD!,ll;$gDG\GIqŲFT?gж:,B.I=@ ȨTC.D:[u1*DAC@J>9F{Kt˽1C{FKi1FүHD/p">!Aro;Iz-5;?2I 8Y4n zS-<S7I G.r-s<̲##LA|J9$d̖|64Ȅ8JtBzliMCGKü4:Q˼xEk7l67|?yyfidJYɾF*-*_LDl02丆_OI,ϛtT;2*L˄+o+U0P|'VFj3x,l zťMmUV|U6YZ ]|^T#V<<9IX5ķ͵ Wxܲ ޤ}. -]rYu[Y}T@_ڝݡ]5%;|݅=? %6ީĽY;ޯ J^*3Z`$P6yUu.a˓Aπ}uk}A܈6_tXRk`ax`Ϊ)6.Jf %b"6bNb^b_(`y@1a(3c5FeAv zt`abO} )mu*7Fbz:އ|VTT?F*+BcD&_GеeP~8DC RvKcp[L4A㶩84NF+e{H䈐D@ 4NK4156c6C u9V7 cيdJdJXCvfBCOfсGalFa1d"dqwP6Q^:Pq뺢3€vCtô @w;xsQ4ΝC΢ab6cΔekh7fBv^Y0{Mgu`h-"ia%SrVH6Wfu䏑鏎g$iiNٔ{P==Tu@leν>V޴c.7H;îƺݻhShLAfcd~`ga{jPf j⚲9A>dhXiOs6OJҏQlD-~E6Fl_@!v@cKa??u3/\K] V4_4= adbMc]V~ln9k0Vlmgfx.?kYXqNlk~qx&cjAT'++5/xivB@C,#8 Z!r=8~0NDc~5A؟9o?;=DFo6A'BJ> OtlR;=wW@AdYQށrsZZ?\!s  :hהP[͓ 8`NA辆vy^r-KkޕOXĮjv-#pwgWt"/ُ9wp#kwx7ڋu.axXs1a,ͳ__odivtw RjkUpt9'EiJGi̭%jBFtyl(r-Jhz\WE1ioAxddy~vȅBy/z +)yq?rw[Y(ˮOg-qn0':S}pPp||sa }|?7{x@{wJknyw {wwwu||_hP\G__A^P=cϋ @g 'V~"p "Lp!ÆB8T/b#`#6 r$ɒ&OpLZ\DzV-5enlYkkf ) #8)RtiQRB*u*UbLukɏ\YlX̙5o9ȟA7bx4iܺNͫwԫu5r+º)SM8hMSݱ0Ξ?-z4JOFYH֤ u֭9m5^UƏ#kf)!xۡu'|V\aw 5"(U'QHӅՈd:WQhvWb[r9Ђ9w!IF6YL޷dģ>^Tbw"SXhȦk ىT b cK^V~yJe}'Jf7*R0fYO?5(V.jQ{ZEIN`V߅kRڰDMj!hNlSVI[R*ૂo{޵dwcgy{׀x1BNwO7𡵞[Ƴ̎۵d-D.Jqc:93I=^S-s"kKr^~,O.V^}" I )$2Z2`DlY̺ز> jﳒҲ@灵ɲNY.d 6m5^!g\!GR@uU_X5NBcH#CTk], jG`NxG3!=ac.4ɼ mĆf~;>Lx(ռKTnP7Y+uEYݢGy 3h$h?meCɉ?k'I% cKBWhy}_VTHʋ[?l8v/P&VOU;:46؇ix"l#8<~oY%1Mkt,w.RvBRnH9@j?rMEuyol߅e>^ci3 %v$W"z m]*U?kks9+x<}ܵ풟<,%,ע{_d+knz<6|6<{/K#:Wj(?៳F sG-Z,-U@o~%@, }U{vr_i_k,=A9ȝD vaŞ?Xz]~Lؽ• ziXA `*A [s 5z 繛\`I]VVCa=.am@ ]T2G8X4L&R`va ƞ$hL9ӡڷp$z \ #r#]I]!*y֪F,^|ȍjoDbB ^'b'=F%T%"׈`Dl"NBB],)^(3NtyE(ƢNIAԢ23FWRXB#McVQa8Nc5">NOlu#,v,`MAoY;;f#qd<JHIJ#CB$:{\#KV$B "dD}N^$_ifţ$QT*LoWd(ށCGpiO,4ep&Oni~ݘ) `2HH'}A)IF*{fpi ;4Q iΧi2d}dr*6d  ڥeFnj *A*X^&jnIV"5&RjLi- ;LC;h:|k1k[6fXgt'ez뚂zPR:ɭOaJ@g뷆+ !WR&S6m:ʣx>r(}]hfd+rKīrj2\;Π76~nd*luc >E㮦9Jda,ɂͦEήlٵ,FQRŢU~(lO98æj*:Ȋ*šzHЪ,6ٚ++laG\CҰ\)Ѯ%gحڢ->m}1+**ul\pjxn=mnl-6GDnɎnk@nmCejEz5Įj)^>N"iҵ}!&IɆښnRǝ+Vi,*zD,dTOm bǿnn* 'JLھ.-ʡ敃 mZ`n*(W\0vo9/; Sçh<.;Wr[. j갛 ;V+uVg7sNn-% oG,P/0@/A°1ń.MCcq[qÞq$]'(rAqĄ0o#2B9qLd\ {20a)_ZR:6$2]%gϡ]r .!rJ[Z`c+!%0Q .רּp_Ž ) @ *W3NvrF33==rsBs+5QXs2~is?tEpEp+r6taG{_HH?/Bt;14.K.P[EC);5MtI+cyeN4}9uL{/W+ݴ{+K_ ADERqG05 :36O5%CϽ*/ u/vL5&_cau/ ňP^n^:i u2?LvH۳e.fhd3`weWnbgcOfzo1mTFWWm M>߲5uFsNq#k'4$öB mc{$NQ.-_vLf![pCx{b+"whwiKius`#yOi2??|_hJCXOb¯aCm=:p/@~¾~Z:/:Cw3E3/ax{_kR?j=>~kKZ~h#9i+i C!~7+oos}_9}{-?z6 4( + dbB BhÉ N(A#I,)$”#ВK+s&Θ]P\TQFk)x,Tz&eʮ`+cɖ5{mZkٶuːX+m4Sk="Z@L*\Z*v|U[ɓ)W|aVoiK@et0ENPդ;@׶}wnݻytHwٌ icrvr%ʕkYnytOUĴAEj+jK;N };?$2,3N=oMι 5O( //1#7Zm,T,IJ wCU0ȧ^sO ]f}uFSUk V 1LcsV̼tu +͒J[ųHr˵\uMݯv%WxJ: 0\0%f}t4[9{Tunt}O.+XyPK_o}YzNf?/t6ĒdS⪭mэҞggFc畅[ITI.kY{ƞDž[e?njԤSpcFVjEټ xFl Ju9;fѥN\elۨ]yZ:cv wLy>||™+Zwjk?a?w8X-w `7pg՝ݲ.YI'~s~i ԛ,l3x?LO}!Gh:!)M[<++nd&hD]$cٮBiQZVtDT71}#*JH:fԕ9iFu)0vRTR.VIϘJXҚޮJ-b wJ bYk6Ժ4աOi\j-Ī=*WXǒ \"IըyO2Ղ";YXm%f JFBhQ¢jQ(+Ղv=^I&selm1Eu&^ܴB=R[`7(U9DuQdZ~,X8KM{ZݫK=dN[抟HQ|9刾'AXoZ/FOI9\42뷻 n8ՍB88jHa'?yf q/T\8؅+N'] Y昿, d>ʫriTfpՐ'/sT Ѯ6E*N,4/tʀOLhڨF+='qDҘ[MC3gWoa֘ofLeeFw:/f_J@ZidQtKnz_=ӉzҵI3}fw&FZ̈́&c!ZߕvPl(Vy}v3i _ж)*uA\nC٘~m|5Uo{tk< v.ɧ}jC8ƶIJ 圳/^tۅր4!u(=8{~i\GE0JgNsܣ+Iқ._#Nw1f1qzu5yدtC]oXz&aD9v/wxH^;kn7o_z8Ex.G>!sS?I"~}Vy{ +b(D ء,oN 澏 Dޯrέbk>-mF0jNP ;2p%.Ҏl(ּNI&m$1jg NޜM/ЄP`NnPrpp7.0R0*Pe0 ¤ P]Ul=-C xNpSq7>/i m 1Q6\ Pf M1qqndwe1og PP1 \ YeĦ Mlg&Q됑n63~olq#u&DqyNZ+*22.eQhsp  602#a#O>2$h$/1% l %5 e{ G@ oR/-*yCߨ߼(|h)CozrAT,*0+qur- &ҭ,,r&r/Eh*wCߔ-1++1(g,J0ERR1.'0kJr 4/u!Q 0w-/zS,Vo5#6"61 }qJ$g y5E3/I"OS:'5s*N^01yr8R, S \r32<818<9o:Sb2P+=Sc;Wr*<22@s?4? As261A!O{d/(@j)RE@c;)yT=s6;TDR.FiFFFM=QG2UdBH%:E?#*kHMBQTEItJ**ƔFLr>/(MUشD+LJ 4TPKG3 N,; t=1;e=W6ڔ22!NrT0NǐR4(PqPWuYpP~l =7qAwS#A Ƭ+Vh0T-4WtVѰfFQaUUZtK*̔ԳV5CXdW'[o@5SKpS\=SN ]sEEU`}$_2T^\SBk`VV uAuQVO! aKF16 u`[D E[KQscuC=c]ӕ \LgB^,_gfO1]jYDboVxƢ5\V V>DRY,VcsTgCt2d퍶Xl95:p mqm5nv^/pEpp]PN7L34"rofrTZo4pOpPYMTNM?s-slcws%>wBvmvŵQWAn7"hsMXp_O?.xGtu^%Tw}droV#mfׄ7gW.vIWR.ss{ã{[{ "|WlxBs*Vu7{Wz{OWrfݦa5bG*|\1W}S^t $*V;~Sxu<(@ DwesXu;P8wY( AO8sVwu_WŷoyQs5|w1lZUUxO|{_d Hv"}w؈q:Kyootz{0[Ӆ&NCVMsew,8^xWeBM 6&/jґgUxC%,mFa븭︥ cE9fkZ`׋UZ Z) F:x^q3}N`zeAC3A"3ŭZ(["m-/0X7*:)ᷳ%Ia:UZ?#{qCFB 臾9/yqx糴kIZV`}cY^Ilx3εFD*ЗG]}~'(dIݝ;/1-_]zl_ii&9'8<A]*OΡ !uEmb#]sDc%.V?xAȁ%_ H(\Ȑ&eʮ4H"+3jȱǏ CIɓIUȏ.ʜI!#c!̗-kTXB*]ʴӧPJJիXj=7hs ʆ#]"ʷpʝK7J YV&W`'Dg)pǐ;%7ޤR4"LӨS^o_,^ÈGͻ7\"'5M2Bؙ߆x8EУK?)me>HR3EcO<ӫb^*xݸL¸?_Ͽ?kVg'V|is߃Yřg4`S$^{ )$h(,0(*ؔv TP `C4)Di$F`v%r>БTViTVay8gqQ6ihڀl^A=6'x|jsfʱ&袌%y `If馜x7SO:v6ꪬ:N<]V檫י7먜JS}&,֡VkΙlO +6n+铖Rº{֛Nk*/a6lˮ6Wdwǧ}0l2 '4,,4i$s5 @3Hw,2?4CFsXg/K4`QmV |l_-7cOx/k!r-n\,s'G.8ғg `堇.zVnzǥ뫧N훶m{{ė{'7_GO:Wo}_So}R/XuOG3N?߯?_}^H; 7:y |`"(538 ruM&]SB{! *o8̡p7b!HD?oۄ&:PH*ZX̢.z`bH2hL+pH:q@> > IBL"F:򑐌$'IJZ̤&7Nz (GI!,"hD&22>?I# GHS&&2))5곴++700f5"9")"AMzfbK!,222d9e9^^^d9ddABL@AK$#d֍99dd׍֍ʳe 99dd9e9·699&&2ɿ66++7e״HIT·69ddGHS ,,8e99\]g؎9d911=9e9Wǎe9999999?@Jed01;dd׳H*\ȰÇ#JHŋ ȱǏ C)Qc(S\ɲ˗0cʜI͛8s$ϟ@ JQ>*]ʴӧ3B] ԫXjqb)hE˶-[gm wݻx˷߿vٺtE qǐ#KL˘1;ثZ_J@/X4 gc"-j\a,@ ȓ+L!(Xz di$~={y^^ @9hvǦ춋F k,l{ 7G,1 gwo,$l(,0,4|2%ج<@s )TH'L)F UmXg\w`-c3h5jp-7`px| nr@wG.9/.g\Wnݜ.{no~:.{֮'v̮o o<'Bd-gه/>ɏ'1\@oVo`1FEPȾ98(kZp}aЁpz GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v "'@)Ё &B˅2}.#*Q\R(Fi#|PPz"%@!Q:Jj,iNWڵ!,2uF22b8c8\\\a7b7b7abЉ7aӊ8bЉa8bcbac88baa7c8҉777bb888c8c8b7bbb7d88ү778cbb[[[Ubc8b8Њ88ԋ88H*\ȰÇ#$AE3jȱǏ C4(aɓ(S\R`ɖ0cʜI˚8sܹ&ϟ@ MsѣHeMʴӎKJJdիXFʵ+ϭ^Ê vٳ"ˢ]Vڶp"|+n[ xk߿ LÈ+^̸ǐ#KL˘3k̹hMӨS^ͺװc˞Mmͻ Nȓ+_μsHNسkνOyϫ_Ͼ㇏Ͽ(h&!`F(V(]Hav ($hbd,~T A hc4ި:X#@cDiH&L6餒hP896y[>`)Dd`gd "TCĉ: atPgqŸy Ġf-@~f觠*ꨤjꩨꪬf*:@kLN,C l!İ,!lf0C5plN k覫¬l i(@4k/;Z*ԶƐl8L+ngw{@<`lPD_|AB<3˜4,38lN <@V(?7PG-TWmXgN3qU  A4h` ́q]vtwno7!\w'7G.WnycD@ P@@C@ F^0C~{괋9%a;O{ 97G/Wog p. P;ŗ 9O ӏ~ H@:'H Z̠7z ` (L W0 gH8a @ H"HL&:P8DX̢.zM hL6pH:x̣ѸI`IBL"`A?F2+&BMz!)e(?Iʁ *=U^2;dbѲ3fK𲗘!07#afZ11;0oY49@!,AD22$BCM KLW((4,,8꾾CDN++7NOT`af)*433??@Jabl@ 00C0|HQ!F0=~zJ*!,@22BCM$ KLW,,8((4CDN..:ppp33?杝abl @Ap  6D @ĉ2P#A=~\谢AH$` <%̔+ Nsd〣@DpB >t,!U 2HB^l@ R@A $` R@0 !,; 22BCM #KLWر,,8>?I((4,-7CDN..: 33?abl89C$@A<( ‚A!L`Q@JrH Ez !ɕ\pђj#mF|9XZy'M硈&p-@iB0~.aKævՀbjꩨb*무j뭸뮼+jC8r6 jA4 Hɵfv+k覫 ?֛ܳ2I,lP묽5D%0gw 15\7d0,4<. 38r 1lH'b -৳B<܈x:.`-v̀삋-R;T3Lr5\A^mx. S'3I.$0XzG.!83S#1(O8@./T MEHFFS)0û1H^8 y L49LnLDȑCᏏ{O xC@8XOLDG>9$wKžzxGAA @.vy``L aJB"тa ` pj .pAx0 B H!CK(HL/"2f% C a$0 %& q"E9(zŠL"kߑчkL^D 1 !#L a tK4` hI{Eo%hH/2A( H/#" KЀ`G<.D4Dq2[ה6g>E! %b ‘$Bj4,[4Sy$%LY(r/d!%m4f,c$YL=(Bi.0- c1F 1ύCh'Z h@P(h;򵴔*mAY#ы)-K($ᇼPr D8ϱ!~() `qD j 3a̩# tp%PwN5pjS  Š +>@:+^7W:u:Pf!̵t!Hf T;&#jW1ͮ :U=BN!^x,ЅGR\k^T<<Ý f5Gi($H/&!qK^n%7m) v,!K-tA_裂 -~oQ~E,RA z$ȅni'L [p UGa{1W0^[LS1P#<8ֱ8CN]c SPqd$+;_1 npͨ e0xF76;x.ьԠ:! rCkpLYg>Ё MiiL#si OҨNڡVխtZv0"Suxp#१yIgnDlGJ$޵wAn{MrNv A,ۆxtKxj̹d4?g~ˆkR[ϸ7O 1! [xKw>ބC|Mo8Ի88q` dacҗ;P߷ΣNuy;3{pة?ygvDv6^%hcr+wGOқOWֻHBTw{6,hA ?aD+:y^^v8K>{G7} z}h|9 t%˻ԷoH}'w&GGAKȦlll|PvWFǐ*,؂*H0Xc8a{Gr&7|[k>jX Jv(}nmqgvg.RTXVxXZ\؅^`؅B(>O}axh؅'Hc  eiiiivV}GFBDŽ U؂@ +xXFѰL +p Ѐqfp~ ̇(b@H؈j؋x xȘʸ،8X(x`H`~pXvƨ8Xxܸ޸epfa6fPff}hx9 i 'eY]nPjuP .u\G &Y6y8:<ٓ>@B9D X`° (PɆ5I yFggՠQu0ӀfyhjlyGYJɔrUt  tw{o}b$iTIffjPgmYiuP>EP eYoIH+ К9Y x9a 0#P@ Ӑ lag = `ؙٝٝ>IW 0ߩe0ډ0yIi @aZjF h bi iV 0 P V 9 ٟ":$䩞ɞ)lP2:ɟ":^р0Uȣ>JOa@ FJ iհ  @axVzXZ\ڥ^i)FJFʤZj_r:tz$YGM :@A: H eu`6 €ک:y9` `jV hP𪤺ګꩬj :zڈ \F,u_ ðy~p :ʪ* 1 /z* dz*jUѬOŅb% Za  Hp ` k ˱8 }$[&{(*,=Y Q@10yв@B;'˚&YH'ۯx f@ 䐌Ja=iaKbj0F `@ @ D۷~&;%;5 7:+*[۸˲F[IYKڴɺ3М-ibX )H 㐌|HJLNLlI,=l>GʄPb˼̟lɡ ݚgܽ0?Ql"A% [}@ G* LWjj\ }8:m}{@=9 -[`?9 ΎGBH; ,-;xG ҳ#ͥ2kem W*h-VֶH5A~״ӯЀԢ{}Դ0|=K[֕߬R/`U;QxcB`YC]{ ^ʣW*X* tӀLA{ ۼ۾=]}ȝܽ]н>ۢ0]mݧF8PU]k+=E Q~BhJSy|@Agmݩpp mݤ= t}pƿV.6JnElLvK-= BޕDޖgGJ@kԝ(N-`ݓY P {<>@z;wfH|^ +w$>g0ԭ`nݮ c p/NbR2W_ . 1Ֆ-@Z^>72cdm>bo"Bc L*SYk @0)/ @>l؂ã O៾ QDD8;Σ/.鷎bVD6-BѠN+6X+:/ݾ}- ~՞dtrp sump r f_o~aQ ݧ|)c 2Oag3V6MtBo,/b<H3R?TOt2:/ S`b  hj ~^1brdokxio1sq_g_]po aɸ65/y{o ɎΐYu/7Yk0?Ü?ߓ0ȟ/ 9!O0_&92,я1SϝFrBK=(="=ד`KY8טsFuc}I[Y&nW1Y廋g҈5I\n @Ns?=t'8W*:Ny-8sR=%=Ewwx9mVm[e3g@Pl9Gk־*Q;qzßz hʍɤ?NkJaNƶ!nV@1Oܰ1iO=Ƨ)q@@Aʡr_@0/a e(І7auCЇ?!/?QfMm.z "Ma牸yPg"E6b :.zT8>%boo󙀪hBAJ?A>6d 9HB!(8L0o32a"Y8MiFK&INo=@ƚ_bx$<e.uKCҗo?@p1Y>HILE49MjVӚf6Mnvӛ߼&LL⊇AGNvw 1OzӞg>O~ӟh@ ql=Aw:GIhD%:QVԢ$hPv? mC/:RԤ6Q0 P1N(b,s3åЇW77s,:+sTEQ&I33}D괮Js>$4XMsRgyC2:E=`?n4tMlf ;43+]Kʵ u gDTZy쀓']kkcк|I'Q^(E*o~Fr ~|߽|?v3T+W' %Я{qCǗDJ'V :zc(g;HA> 7H/D{9fOA l'Ra؉d:N>uIm\Dx)uMk3htA1w}Rj+:7( *7³?0TPZH FqLATH9}LZӷʛ}ː~ѷHp L%d&tB~¨r= xb-$  P@H0@ <ˡ3 6 (T?@DXxZYx:jDGɱ؃@$بDAHIH@D8G@TbD$HtWXAB˜Y`z vB-BB4Je.0XH0+HÁx@5\&.7f7,?T>8>yz{G?~x+L*H`Da$EcFk.  XHP@EP@l.n.ofCGts#gpgșZ XH^E,,=ʡbCkHi|Hd\ƁP)h@.6;=d9Ó\rIdKGB~X X7J$J$2<R J(ƿdDƶd6L8 D! Dba HT!TKMzK_'JˣȪH:Ĕʶʎ7ʴܽL!MbJۄHLXo`JkT=bxF2SЃJ5R5"P$SWcmND O1]RU e\=c<>'UeU>EXVUTU|ņ<LDϤ4OD<=4\QjMs8ק4OVl.%bLj;-rشT`mVMLzфΩu}P̪hșWא.Y*-ٜjqx-zCdEiوtՁYXuQMD{[ڸmڝUWՀe FrvMC 2 \s=r%L\R?Ml|۟`׹Չ B@.Ձ 48}P 1@H}F{QÕX.}AEʩ`\\Ve\Zg좇gX^ch3:ޞ+ꕃtp},.qxuHu_|Ү"_%Zb9*T@^%%"a0TfCT5㵌ϼ.En]mb)І#XݮV~ :' $" '7<.. NraqX ^@Ɓ(="$hp$^m%(Ub(Ϡ9MD0`6#@ІY-"g Za"$FDHEF"_H.GbK-b*aߝr;$&F@TNe"c9DJ:7}8LŮtx嵮 dbNNHd@f.bdVgP։Q&*#@Ep^T6ɝ؍l/ XeLTŮj].!xf-&("bd8hbbjbk.aLSRƿFfKf%K1!ȻFyz΅nx}zqC&de^袦hvhXhmhOG0Co 0J;IaNfkcbfeVhFlN>Ɖ[]\M^E˾EņUƎ%FclIU;sa7緮d\rjih |d$bdnbnE&nMVfjhd;KlJX/nծUeλ^fmv.~h]4V_Cb+b$%3ngj`)VEb1V)2ɝ;[wLN1URVCc+8[agive7slO˹˫&l !#.]JLc  PUOHSE?\HM h lGXޥ&ޅpH';c (\b dg]>oVq0.1OS L#@.\N'eWegsfNI;}8uPX?uEgr;' 4F hhtPkFaFNUPUfQoo+%;Yٍ\x-u>O#yr=/)x ݄wp[my2_w۩z `*-{h{Wm{ S7{zG2{WWGWG|}|{wOZ/y.7T?EM>lB|͇۾Ca.{RwZ-uWo8Xow`Ə[z` J6~p5h}5c}9p'87p>|}oj}kL&SF.^Xf1Ċ @bB@$@'f,Kɏ9FOf艘`B!nDh%LѬi&?& <'PN2m(ԨRRjjQYIذbǒ-kXJ90&=(5e(` +X<Ȋ6KP0Rv] /*䛙3⾌%ReDL:,_5M^g +Lz)4(uۉIo# Zxcr9tU:b.d`cGBz{ Y 8!h'iKਁP cHʰw<_gEBf$Ph$;Zk$[uنKhT' &5BYvHr 9QtA QQ"O)dZk%y&)2j'%:,o, $I8,AezIa؀ 0",SefjEzB9&85}h#$HzbLiB2θTUP@tC:KEb%_1v)pj~:J\2o9&aY׀10A4R^kczwAd UBAW55jm%0 ,Tz)wGyʕ1:hp*TG"*ZWQGnp_&!( ^WH^_2"vC*,&r N I y,'Z7ˮP Hv:BSgJlKG: |p +lQYT NW1e|,wuDB5k]m%^gh'EŲ j([I{ vѷ!Tfm\ihB, k}1)*kݳ7|wuc8aO?wjoVWN`z 1샟ec PzDGAA1Q`?v/+awى~B<~@K[D,u)eJjH9Ѝm6^Udg|u W>ā  7$9X֑e jЀ;t*5L $&B "ܠYC8Xè0c\yD8.0m%Sfte-x#^r'y͛B,7)JTQ*BK*G!1pu`\X:8,kC A::Xc.‰ E0qHfę ƂhF,'{$"٣I)T!7fSB)-ĞYJ"Mg%Y$(,ND :G{E+јP2]&Њ$NPTЇU&LC(E"^Í^%C4P;,4, uh:QJ%49cTRU& 9x&LL0u +77s:qЄUaMWh)TDeP=lU:+},b} KofQPRl ђWell^emiؚdmksA#Zp-pXQ .rc׃UM.t6\IǍ.vܠ6wU.x3]FeU /z[vIM/|2/~^޶wI/>0U;w-% Zσ\otK -fOaJt(4_7F0`0ؿkiAcT3+rGɍ6RtaF$dr$JVY1Z|sY*3J$ڛ„iAeSG:fř5 ke!aL|7`-ˆh*'0&C5_I_;O]S'7j@WP Zf)C6wn=Důw_=,թ=3|-S80OM%X<#)S/"{ .7.cQɼ'4? w>S)Ps$۫\vg\+6Ļab̶'n]zYHŁHF#". +fa$Tft$נ \LÓ9~',w'.{DKbx">'mUx7;vc`gw|[^t0KFyHaOh@ &%ЦD,D 5@b\J\$pQ]P= D 8]#< fD \ctMdB1! VT$*$-! F"6b>IŹK J]BbP5B`"*!+F`+Ѹ`4آb.3<'ʘ0{?nى?^5rH rԀCF-Aa+bhc(rc(a֌6cLa'HFc#Mc#?<<V="$HD>ٝ5A"A3&dd+)CZ#LF+bt4tcM!%69c, ;6}a+e$ݤI䤹dT0J&@PQ\r]0e FtD8᱄!-!J#X֕[j\\c#ZFZ:[BEfJMbS'>#gDDh`EHj.E" -D'JFlgF"a $Wz]&Ojj|%BfiZFnmȣsW!0c"Jvf]wjw^ug|yEñN,`LXD`LhX9U2E0Ѐ0]%|}'X옕4BPٜ Iڎ4Fhui]IqMبYnhxuy>хDiٞ\KAR(* "&m\z\Yzڒ"YeH{ЃvڎNxΆxvh})?2!iܨRZIRŜ&騼itM )^JKi@hΆ2%SuNARxe(j*vqY:XY K(>ENꦩrZnu~ܜ@1(X(~*#]:@4ٴWB^'OM+AYulOۓZ"WjZLQ il]XTLVNYq\^WFf+AՍ<h4Pm5p0-[5e:8C58C56gl1."N?Mݚ1ni½I?pa!kB嶭Fj#.;}n̲.b.3 n aL8k!^.L{FԢv%(3ﵒ&-~A To(ܐBTNC5&!^U%/FT oXH2&-PfoLO!y&">@?NP"cB." )Ub-cnW$5"##*#ozKLgS " $Fc4n4^ F GIdX1qU0?ޡT A30(A L {B Wo! gll i1"$Fd1|'"āOPBﬥ 0B!g^p7dg!da\!DPc#KnE"u!bBTp>7L7x4/{' 'nG&U* ;#W%#AN!OPe}8ǔOǀ'\&Ml #jnCj@ 4ЄREPhT hXQŒk*"IMb*'o4{qO,B$j_a\$5^%01WH2צI1P|qG^(R|hB "XIQٹpR`N`ae]lc BQ3GACa XFdPDg6~c(E_4O,+{ 8qt봱4Fcࣦt>$KTMu ׵$6ic8hJLReH}d 8\jG~A?Gˁ,vj X5^t'^_ ?'6HDD [ӲH'vg:cz%^fLB|>0Le3xts)CAwD-ơv)sJ|N]L@BLqxX!LxA* T k^SvRfJvP~Dx5DGH60ww%o+&'}EFe`X /]Dy*sx /9<WAB  ]&e:Ċ8P &DoЊP6a'v`I(/_!uA`G+xw b y^ylCnhoWH\T}G*yN_DY R"ޚGkM%_iWo"# fZdv[r@6@>Xؙj@G~FX~-nBl nǿ?ڿwοa-@8`A& <%TaÅD8bE1fԸcGAV吤' 'QTeK*!LB(dM7q`OKeQgQG")tKO)qfRWA_f;lͥ_MFUVLeUʵ+P%ջ7ٯl*_Ç3nnм!Gi`N'(,^ŋzmLqgӝ) eQ{Zm۷eswϠݰtoVۉԜ9:qUsVq ~>wrS]ܵB4L%t1'N?b.ְ"A(0"!DIdP"RC9D S<*Jss oq;Kbip,)atx0CQdG*Mr-1Rʈ2J2!QLs'ZEaS'I,GBL2g <27'tqlsB+(PN{F9NSV2@tP$,E%XA @}4W1M PDg(!TTWHKoMS-SQ$($ *wVQv)މR;"%I %$hx-#@0%sW5dFQgĐ5"4 8q#*8+^jSmHuٝ9ұw㭋š^2A߈&_:] v0h )@qN`g!g;!Lj4 'gX!PRN)d%Xl6oyp M|p=.i݅W^^)ۢ#+ahmWr{nvmk/co"4>(Aɒ ^X"XFdC?DVAQ(JOP%h#"/tiB1HA\A/N$ ƻQB)hC P0)aJHwްx px;L%5AY!8,9HBtA0a^DI&X?[tsqiД0B 绬!M``K8#rA[BI$p ma i @ֲBQW?$QwE:2 ;=q8M T LO,b $@Iшa*"H$0QB~,6_l^O魌*,Ts8 C 95Q2PP` jE l$@ `Bă)݀Ox U ,#lgȦGx>o!͢hf)$!vhanF,`D$&ܠzx47e wlRԩj@dI/%nK]& P/L"GK"8X2+"A@$l eȃ.ܠ1HLjcj( T. . A 0i` H` U9E , ";Sm7[M%VDz+k/FsBkLnng\VBy HLH?t+$ $?@AM (+uK\T.j (C7+ -mmuR]_?+\WB]n 9at0a̼q](S$XPgzqs:ǣ\ Wխ,y^TE#-Fu5D|=iDSm}m/fS"] j#2? \(SրL-#&^>/i9Tf~}<=5%h3 :s˯.cwE`BYa)aZ$.Հ׵d턀Lo+F" K$XͷK%.u);NkP dGB-aP^5b&6m9 +e >(duat&Wy"s3(D}3r7Be=ܕrM,<"*BW~P"AAܩrdfMCW;G!J7  ER{l[0ҭ (iVvSs'V2DCAZ F0὚oS;!o-3<1y~!@?2=CPF7dhGw3i|{ƾBჟ퟽o I>e%VrB,!@!p 0%r"P" x`%O aQ/%Q Ooƫ0C&V"Hab pf"w$a p0!$z@  Op VXP\`P*VP0y {y q1p#QQ; 1M@TqYupelq1uqy}1quf+`1&/ Ib~^P01U #pU Bq!1 !0d 1;N3/ʰ! ߑ!q 10 0 k|B8R _>$Q0&M 55'5 R!|QP/&B$s$W2j%G. $y kr+P+1wPP' =+òK) /*%5dA+'OB R050P)%#+"q-!-m2+#1R1pP.T/OC/,b  &15269r!-k221 r!63Ǐ^@r4I0&P'`Q.0y;"@$5s!v3Ir1p 36I!L':->89C4odb$aƀ:QRB`r0r ?1}2y7!S%a=}BSp#% p!,p>8r3O?$/GuT!1E_$FsFFZ:wtIG8wHaDHGHHBZF㇀$4LEOJƒ EF D%MO"N @@!4!RN+4QÏ8[L"kIBJ/ M5 `4 ؀SOt!OkTP"dHQ]uLG*mOt=SsUON{JU!NU$hmְJrߴ|hZUSLsV"ϊR/cWO NWWtXXjYKʘ`xNN k_^5J5)-'2UF@T5W5^S^U zdJd `cVat'nu9Wߴ 4XU.XkA6/P9L=d5e`R5!LV36%_)'60uTTSGfUX(Bf Aic(3Pnh'!*mI7P%:Ds(3 }oj=j"vff'b?5T1Wl! \6cPrW@Tl@nE$xX7aĒC76U pxerl.Rt]@N4S%v]g>M`mvR s@z`i&ʠvP%aخ&@7aySWPyy"F>" 5UN%xҏ7!ֶ@ ^`N!u/цR`dg !j `241R2Xy3& x8[%?BBgV`][ ,X`. apmg!uR 2{8S)1R#}2-x3JӉ%O350! Р!ug2r,sS(y@(wA;twՎ##k=h *$+++0!(R"RSxx8e9YV=0@Y//lObC `C39%"AR8)r1Ӎ1sْ1q3?Vwe4WaEe386x27D=02ŲwXC4J9:?2ÓC;𡝐qB3:1W/)cdM%]C@E$tAj:BBB3C00u3=t=9%R0OUM]T?0j44qzə9.6ZĈQzKdS0V.L=Xz㤅"zr:%z/{Qe ;. Zb9Oo;:9b/{2{ICó"zCQ/fVz ]CY":!RaWVzko t[{BV>-!%AG P9:B'CԗӺ9 ɚm0S8 v` <+})" ˸32xS(Xg:ֱ㛶{љO{,--{Ҫ` W-+'ӱ(7<( j ԦI´"m{ObtQR=! @p\//$N `'+Ÿ\&9nKdUyIC˱b)XFd< ԠY,Ҁ pwF@p. ѻz` FZ 늢im(a֗/ ]aZ+a<~C7ܕX_Lbۥy̯}! @> p`6 u,` lc P#o>!_!F&d#9rǧ0 f١)JYyjT# 7Oĉ,@)'"h"QkHfI 1 1Z ZAF,#ɌDqŠɅ=5ԩ$h5Vx 6رd˚=6ڵi+QcK֭ڽ7޽|BF&L"GqψkƘZ;.XPbG\\!prd' uXg 6g\FLYx:(ըcT2oͷĶF"w)'F* SZ ?kWۿ??}~_gWjW[c44_SG|G L A\FCw-2Pb "ZbؤRFч8>RVrw51R f^{TWa|eRN)%M^ȥ^ z`V8C VRdjfM2^:5R1&WTg~eeQGZ].Z d*Ii^ꤝK^e~ jjv(j:TxRꩨ**kkUgY.[ ln&km~\юkׯߞkwrZ)+lt;K%vjۦZ[J˦? YmZ%]Vx&:aX@1 |`y X]zx52f1W@!3p{ 0N'1V}]j !{W$,г*%6"L G^ì2$3 -wDM_]WB}7FM? ZQw5 qX@!x9c>t,L4L}IxGλYkTM%dCǫe<6+ٴw7!Oϟ^{xϿNP/~jt=pXwޅ^{*<v{H@v諊վ }|W.0pGg.0eQ6uMNiլ\(G N6.T&*>P01F`1i>~f ܬEXHV3D0!DM^QA*Y`ю:ԕt+NZJ/ PKE`/l!Klo^%R@gP8 SUkj3x5oLfM{M35f2+^k?W8,4bYX}|=,钚`_DrQ\v NBYMʔ0jihZHHQ̰&KSbZ,.2Y5wv ߒD}9rڕӵ,6﮿B=qYkU:mM-l3kY_*2LBT!T"\縴WTi7K(f2!h&`N@@1:kF h &pܛ۲8C.NTXb#9of97z>osC":FX;7w=*UBaL(˳Zj͇+wlludc.CL(=8H6ɣ{s<)~<0vW W0W#?d=F7ucI0EM@ >IADϴ8i$@b DMss~壆7P{?:5Hg~<=2η.bhzAIz[RdEUEzsE~CQ:ES:UIuXIe7gDM2yQ TG5ESggKsӀdPF=~tI]}D4Rxq$TQԳL'9=ΘL=~L:XU4LhFȁHHAEH1N39_98PHPx@Y8`6 .>>x/8|H015S,d[ut{0Tc2NUFPE|hTFVuXG~CY$|#U4~9~8I ~qw8*4>Bz#xؓj 6W%9ACy.M3WJI | Xy@iABR_6ss$efpmzY-xup}fAP @ey闀bmԘbp_&pu0:ŘjV'Z($4Ii9c[6VIu[FYewKm"[Ex8liwJGC؛j4&0T%G[)M͹yQWh:IY1Kz0&Ӑ@W{6uq`[v\S p46 92"3>c|_C؇YYxžВ5[N1 dXO[b`8 UZ \<fcEwagWwL\v hr95'+s2 ik0GIC%< = 3a^`@'F;yo\#XJ8hWh*d]xa*cZSsEwtBwx#8J^jbpE;K`[7( BS:F_ăZo}iιx bzj"D?՝6 9Є2P>a Vw3} :Np+`QSh{jÄ䃈WzjFbHDE {5i `B%y47X5< Z3 GC6dISBsʗ\u]H5%<|66zces YqPI JctpWze#"a'BlF( v$ET43*K 2H]y [3^ WȊF_;/iXJgJ(`iEh7TLVڍ\4~:ȯ겒'iK/h~ WO`pD8OgSOtw8jP?[8?յ5h'M!Spp7eS@]99\h6 3E$t9ے3}'JKp0- <%s S"H%lk1UΕϗ!ڤMFN D^Qݼ79؂L<=Zк8΃*|ۯRrden>IB .vaanr֞†'f]t0gqVǾPްfyə~.d*7.rcxM‰?9"Y^ ?ϜIL(h+ˬC=WHPz×͸$19} }\<6VYoI~67朥HJN ɗx]rh = ͐ &$!=E(TPАoB3M,np_ʉ?z?DRLTȏ]FHP/|+O.gHBm(hm>OP~n@9ysѹԬhHi0SN׈M2כZkF݃?IMtڎ  PР@dH`A  TdtDh!0$Ɖ&1LxÈBN,_tS %Z(_7.eSQNUỎTހxXYf!`aƓ 5rQbܹMWoܔ2BzqQ)ǵw^6L5AΞyhRˡE&]zUDr VXie. )Ͱ@2!XvW8IčS-⾛//K Wo)`刭|G5ܕsԠMϧ_߾Tb6gM-K<tXŒ$\.C3"n8j!$c( D/…RdlA2)(:> Ҵ+H$kc!trHr܌I,|V*I0:0-&w++:;wJAU<ꅔ=t24KBP.F"R %%R@CdXW0"S43 N*9N\UXmeYWrMa"U5LVD$$a!aUGz`5L06FeDtlBe*QiMZ sVM-wei^e^x~=y}Іa,a_fYJv"b#abb=9ڡJc$Av`F-Yݕxxf\ fNeӨotX9h}I-:P`i 0;u#tg,-2kBb|h:O\²BF˴rNf8l"Fdn]bY}r;X6J[H}cXP 8 =v,~#ĠDqFO{ͷ+^D<|YܘM?}ݕTdfX(K(z!@KCvA\B% <1zIR}& _eREt;ڡEI È0HMvE×5☡(03)Jx$eE纪ՆǢ0jT-(JWJ؜lxt2ɎbE49ʑNMģ!af.aM?ْ?T );I׺h2_G.XBָ( 7(q5mk3ݜ8>bK$&ǿcS'Ax6ߙ`ILTHYs' (n fЖ:d9bTDӘ }>5u3xxPճoRŶ,/-C 0Hat+à$h sHD p++#쩣6zCA*{+ x)>]*ëś`c ¬ݢ ʎ"(PtჍ(JX#Ap\yqHb9ӻ ɪ? @8A@˘9$|ºڍH,yȩ"2l(&'Eh,@L.p0 , ,\Bz B'#Bޣyq8#)))B -Z y" C2Ćwy)( ?!x%xwk. ZAH:sBDѐ!:BF! >AKd1M7 %hL4ĈypdT7Qj c"R;:$*+/U 6=:*b+,m6CS B8@ޔ$4%3`RB7e'Z;icl;2{1'?ݞȫ KSF9CݐSԘh9oɋrxSLJ͵)}㿙:$Ԥc)%Z Ǫ;(u96:;],ۨ * ܪRk; A5"P-V$)UM\Mkׄ"nE* N -5B@Ln"U 7 %V"M!J]McW|JSʮ Dc)JE!Ц-n{CD%DRY"AK;P˒SZDZLڬYTKK]X;ګ푳WΨsKoHIĴږdguyu 0fiڨh:%!Ӏ[`09@j{G8tHw蟷)X%V- =eȕìӹtd͵uA!D; K˭%L=Mɜb9[^ZQ'%=YGd!:) JȁiR4"T۠?$\D`j#.__;E[`͖r̙Y܉)di[hDamh_kUWyÕ#s 4/1.E]q lY5%]z%NuLH<|_l+4ᶑn@ F(~%ɬ Y 0.ш>`[aZYa[LI5;CJ w Hv IHp`aʵZh9r]5&2e3)W &h5M`Ih@1?%ԁ+hx( "ݜc8Aa+8c)<F5TBy-\dc@[cn%^2ey6rMŇ+RcxQX oH2,H`1x= @mAi`;!h#L 85+zٜYɕd1[QhIni{O$awagJ]Y$}*$'7|#R$:tb\듃E-aߠkAD> 8tP2Hh1Pp84oV (*c'1&t9J΃rVd0_^NvgI\%HpmNԺP9U12oGC%%Ve?Z=41'xݩܝ[CjUըHMRhzկ~ɩ%)J52*KU5?I©Hլ2\3ĭo_ SaCaV vk,egXu҇]TSȶ')fgCV+Z A{e{ (YfdZ^v)]TFY ZhH Pv;[ȍEV>yh7^93n "_ !`{&%ZqUΰB"۴}됸4#P`b;.AaF63b8.pVV ){#8@MfZ1-!vPvmZ h`j| rb>ї_Eb8qAZ,|2\̖ͭ݌l?y K31.6cLf,7u(kn׈}"ۢ7 KmK;2?l{ȗF'l^Y,g$5TW΄q\X{d`T-I\WV Ms}F/Cm'3yz@& Cw [2a~w۵mUq{Цxp WYeȁr88v3N>1_)|h TkEpa}-Myы=?  "Dt//kK83N1{Me+Uc*V}.:ͮ.2LM3nʮ(68WlijnV>mDPGL7xo. 6- ՘v|n?s#.Qͷ{0 HRfc`es@2[ј"g)C S>g72J=%YoR'%r;6 eBJGZ0.Qel`o IQB kJQiP<1|i@@4xB$@t\I ߹ FnzG::UE-mg_ JHPMhQ y-VNPDSBx&T' ”Guܞ5M NReҏTMP (yBM%Tفែ5@2UDdɌ+8&bbE@!TEȞq[J, ֡'@˔ PxR"Iܢ'\@)}@Hb LxnG%C8,A 5n_ Jc^+N,ТJ.bD%~0pM4W#+$.a P6 #㈢2hx!-1!Ȃh(HX,bI-fI܂0Z>_O?,B$IZBIPe3G'n0VFNH@4td5Bt:d;z d.K֣-.MMdPN {2ΜT(%  #*rap&b+5w@#4naha0]&&XCJapP?! b # Rp >%v\C\FQHA($S@AF#e&,J!-)A. #/5`LsyȒCSrnĄ0qRGLfphC8?\V#^Up*fxn)[[|^EVe_tFqٶ[d{'SNIAX Ÿ} mu%!LTWk(VDg09 ql~$WdRz HnڃIEJ赍r)iޖՒ U.㝈 ր]ٳ[q "ٝri)%UԤ_ Ԁ٩ޙ\̙\ڞYjy[FjMb1Us `j`q hCp vZ.k^K*iέiR]ů\a۟ijz^n~fḶKٴvA|婩Y+˙Sie,۳^ ܣښXI֟)!^Nȝ[@\%hM=\0(ςlL\X9*>N¦) Ḻ,$v*۠0AYk1]Hf]׆7^ބAuj ԯ8VUծ(^C`fd*^ЕBh5Dܚ--bޒHl^ʜk3nގ.@.ITPap֮ю,ҖƩ&$z*\*>/Q19oWJ^%Zo.R%o/oSqoV_:avMoNeDўfje+eNeduSVEcgeL٭Au(@1dZgb]NS+uow/ 6 uPc  +LAREVy@`K A2n ƨP H@%@NidO,!FA1 sBt c:*  TqtL L@6` J0 L>/ jpɹθ5 ?ǂ @Xnx]A,$@2 %@$<TC!ǘb[,׌8&Q(Ina]1 Kx!܀ M#;KK ʡA% El!6!Ed]D0rB 8*{+# _A|O8.A`.[ QZ2 x \VK{Uz 4I,dfb/tVf>>T KChD* B7A'%@F@Z9f0d6P X]PFb1 &؀3Z1Hq4|Dx"K3Eca$O 4`j>$|S/TǕT^dtD 8D Ld[%\od'56r`EvpR``6LG$E-66{vhd0Ro|?根` ;1@AiS+g hĈS -7@ 4pC@A>ʨtH@00]eQ8K `LP4M:vLbYwu&vCo\7H+5z??GHUްk6եB(9.aR1f"f]| pDd(KPHSP"_NVfdxdD s8uoP{ ga0elf&8pk6({w)8{s) ~94DJ`b2<Բ/vGsA00m4s R<$S52ӌ^s4!G|y;idO'S/|nazS$x©?%R:lΌi-jmFM ٙMd0sRKHkh]ڎ Ȕ+p\D Y؛.UcLPw X;RU^jn%&kU. k1h2ZăFЭ/o<z Y|qp|/GunVp}2=ً==/.}~ ~#.0~;B /P~[cAs~{~wd~B~~O=ϯ;ƾF}~X}~}ҳoGWG c#nozq8Ոu,uWj$DnHlqwpO$Zw?$?wIjKsMO\ 1{KOZ5>|7ҽo{c3ID 6P4$sya yl< |IA ' ~ | Bg A~ `Xh nqƈ  iDI4ĈH#N >gbXn8C!L_QpcW‚.pt#uȂ7*dcMXʟoHp 'A!3h 3Ƒo$AHF)Pfʣ)y cNV%WN=5Ed^Pp< X1s=qV̞3[hh,%am椛E&,é=Y8ġ+jF4}+CNjŴ 3tP(N44,8΂#)A ͧS*]2ԡoVj@SA c? 3洪VeD(HHʑ+a ,` fI!G&`4_!"B"ij0 iҒjl QDG2(gOZɪ_ykDMQU-@r]F5Xq ,gQDz!$jbK4wE7 K_[LLUwvv&-.XX*"Pf7. /aZrBG9 b2^p-': _E[@nЫUX!8[c ӜtƹB~Cf8jHFTJ56eB,Q ~e"_#X k!4n^p8'qC*GiԼxs>9Ή^tIWҙt QC7 U <@Ћ^Ԡf7{8wվv-q{n}|W{  !j]7qvp;!y} zt^WYz׿=^M$A Z@ ~ @ I0 |W>_|@o|Bh@|_wɯ~Lha #P'% wA$(ĀBHBIO0Ia[c0B0!Dutd=QuP op[C <M0q HƐ  P א PP O %F!$!$p@Q!%*01$j@-q91 %QS,7QŠ'Q%rQw!aQq Q%q( !G,+eecQ?::8-iL0%%:3O7]9V;DE9X5_ c\Ubt59DYegou uuv!x19:;M]^_bcdeglnmhZ:I22222222222222222222226Ց9ڐ:ڐ:ې:ې=ڐ?؏?̍Fe{Ưܡɣrhgfis֊ڏېܑH*4ȰÇ#JHŋ3jȱǏ CZTHd (S\ɲ˗0c,QCɛ2sɳϟ@ bifZ+]ʴӧP[YѤJjʵמ%MXcYZ˞۷p2DXHE7a 3mު% M( k_!6Lf"~x1ȗCMfE]"dҰcˎZT!bQ6^MhbyZ9O[[>xm<Z_w術_{c_o>瓯TV h ƒF! HhaŇ (D ň(,0(4h8Q -PF)TViXf\v`eIG"$!p)tif @S")蠄j衈Gã±d&馜vV.j 1 LZdk*무%`&`*NRjVDZ&\ 2kZ$*ĚevQƳ4-)Y$+fqr Bjf`-$@YpG,+ ['1\Pdoq/>_bY"$2_lo\LqCGFɰ$>:?I1,Y6M=챖irHAV2@$"R 8 Gmߝw\weOo^!>,ˏtOA8ѷjÄ<"Q+߄uZ0 DV^~'D#9>3N>PJ3nyK w,oY oHA<ݏlӟ?u/tb `,-|g(ŔKAQTȠ !Pr;a C5acZP3ZN6bI:տ¦-mE:c8}vX^pʢԶH$RNNBf|O%A'ybC<$' D%0iPL% RRE)+P%,gIeɲ%n^P09`1fRiΌ4iZ*MSt(s7!1x9e7 d89qa1hd  @hO|ꓟ4 @;3dpC 04`h|дЎp H2u{GI=)l{l는8x ',z?LovIPJL)K)I{4#,Y>ͲOBQԥrPeTX*B,nìF$Af5]R9>cVP8`,dj%YsM@XJV6uc[(JV30mcI}an΄Bwkǧ Ha ^[Ӄz5X(PmY%! ѕMhU 7>а.qH}>;]0La:զ8NyJz"D\izx=ֽ<0z{Cj oIZmfo`fѝ/0ZBTE1΍l+z!wƴÆD˜'0LAV;^*HWa} [ \˛*WSh[ytnp''UFZԍfbD2XOb# Xj9uG5#GwpBsWɈc40H2^YabՔNPمJ LIȅҔSLAMiLZ\HI?x/+:%-1 Yv 2J)$3ӏy_|(0 X#Rl.:VBE4ИY$z@E[wMi2Jԉɛ҃r*:(SuQb ckCB:<7:<#Vj .+"g2psZq2J+pp @$`]*_9 1,ZjʠNb #HEBP DZGժ0ĨNʭ J{2 EfRc's~* tzv';Acdk*8 $[,w($/0+2WhU*np{ zQŢ:VkWPI[%R+< (\k\ qZQJUek[%*˶!($tsn[^~0J<{P?sKk {Kn[$kmkOB%{(ûP!gK [ &1:{&+kһԋq_\AK۹KS«)>k܋%*f۲k+z}[*;?,{ [ ۲losݺ)L")lT%',I\Ji? AYGp0| |TK6&\aC Ṷ̊;=%ll +<$Ʌ;ۭ:+j$\TȘ3m۾%6aGr|(ʣ\4jl săGQjjzF& raG0xɜѡR48G7W~]lS̀ aw%Qyia'|uPЉWwZM]l<{= 7\߻KaX ѥ$~B7R'4~>̫!Òl(#]wc' y~<#Mw~:y?- \FMJPMzOݫQ,)zlWУ'u'֦]=>{:%ً8|clH?{ &-v JƊ_0ٽmӿ:ѥz;C;[˻  sF ڈ9Q%FZpXGo zO4u3}~fp׭M;Aۀ|Ýjp{נ5 7+n m>0ՍM@F̢;̲L; pNQc3׽|r)GPreܛ%ֿ^twnMsk;6 ҫ^ o'O ;oh\Bm.䐎S=&JWQ756}W(SozpH{.5G ׬\ ~ +2Mw7@7sr{ 9سu?ݡBG`}ON,k=SLdZ۪ s~G~EBwQ].8ٕ}Onif,4sE RM0WoW1-Wtw0~C፮͎/O_n:l@Pw]v-w :Ƚ źoqD1hB >Qà LQF=~ A\2R䈱bD |$NGĜ)waG w4X>EDUEE,WZ$rB 1TxǬTUkX D]śph=Xk֝pXUhTG9xAN\)WNB։xb;q$j 5Ưj;صn}kϡrF\/IKL\j0uLo`Є; |wg]ۮV`]m'B~3K8 ".+TB#!Z*xQ,Dk<7 @tOr g$. 0H%2\2J)Jj쯣1CF)Ds#S8;Ml$2-LpG<Ņ´32+ME5ZB4RJI/tCr"4TQīӻpT%7UUMBP[VNV]w]+Xg5PQXcWeRb-l6ZXi%bRj[qzqϭ[EM6K.scL U] UF_lmnpA.px9MQRs7cxYDeDzux.naOFyePc_e+ȓ~䅽4?Sޢ#NPYEmoڷgg|ZyUf &-ڪߎjwxkV{awf90yo/nϖ;އ럽&;l\aAqZ]tXi` s`6uʱŒ7]ןE}6տfnO _lP@N/w;]߷xa}c1K_qEw`&.*2fh Lp@9 Bf,lNX #Ԁ>SP@ؘIP0ɛ@sCxF/@``0![ f @5p `&PZ(zb21M ?04褨(ZS(%=RӘ#8ᇃ\f'*Lc(QNYE#yQ `3G)" L@j"K('ȥ@7NN12RM`):Rv%\G@e*!ʆQ8َ.s`5d-:2fzHc$a2%)&%ILIjZS58LinzӔG4e׌h"(A0Y}(gc;I@Rz. hB7h5TULz9R'ŭ勣 :YPCwT*}ޘ`&>SAh]J~嵓 MPF C;bDԧ Y" K9tepHW"cݙ*QB[PA7oۋ Vy 8kkn+FjVv%h[Tdo%%(+Ȉ&ր=$d#t7 E[0J2wmp5̑Yi]"t*F1ˆҞ F[Ϝ!oˆ=P;Cnҁ6X]j:Z5s%xPV ]lcJH'␃ F7q7"U>`(d|n ߌp րC p~km}|qᆟŁ"!r^M<x ppd|@s|Z ,q|6-jtUw~3,' s <R)dBGڌhF@֝^DW~C%/yL!\m dU;Y.vaw\xqFR!,B{!H<$<$G$Q@r%9˿Ӌ##=("x @@UXTTq<i&h`Y"²;E)4 &""&[KhR 4 ^J,'N+dz:<\/K?h;&Ȩ,b: C,%$"D\'v%&j)L$){'Od /dC+Cl,t:)ߪH ˘Cj{E0CBt >D@lʩ󞦈2E8/|DeLZ@DDo SlB*gP ; d Z2$: H `*K4-hjJ9H-(8ɐZE-CD {ckVC%*G:nGй?6a$A9ҮP ɜFB̻%{.N|.А!PM8EB7ѠT(@KMX"C[:xL8:#8$i4mii57k:M;oSxN{d:)a $=W8OL1:$18@OD,jö댴2$VC36IK| 12 Pk kNLQz5  *#2Q%/E'u5&P)-$)7.+RaR. 62=04M/O6ʹ[S87e:U/8kRSҁ88hKSRD EFSH k: Fyې4{<:4M4=4OeU+UkRk7{PSX%SS\M]u`ÞI՝hõEf*]87퍤۠Ԉ{ݑ [LH"-`~<+:yDI1 #vE&8 ъ<;u]cW0.V6 X˩{m5׈0L\D.+ ?V" !ĨɌSĠ#I|X}.*`[< |!Fؿ)][/DM*܃?H d3@ϰ]CML򌶒JT*6Z@9 :jAZ]3d=$dA@<< !t'(|}qD ,-,+'d I3$#?y=^̂p]B` A}E`EPfYZJE!YMZ̒E?# - e0R(bJckK!ŏx,± f;'>G(f_)>E* uK,FEb:G+G[E,.]ݲmS㷘N(7Hߊr.n4.(9+<,6+V-dN|I#Id|e5.e `U/jeK"Ђˣ t忼K쬯$͒S~ǵd0,fٺE'˻fk^RfXthc tƌ.Ȅ"LaM}&ԬLb4i {֬ eK B/ fΛ.iַġQ.èjNh^e gxe">mZqW+׾Ј @dˋC ݺ$5дV9 n;&όPATŁkOklrU]ɖM{lZmVɦk2lXNl^?&վ+>m1͈4ڶ&6FVff:m֖nצȎf~>:nn?UmlRmnl^Z&XNo(NDoVˁ/o pI7 ?H[ p$ ߇ :pLoSq7/P}8}EY X1op JTPk -"q>ٽr7#O87Pr'(SU ;썸P%&#)|!]Ns8U1"\7XC+9 /6 <s6+4ψU8@0<8`R6(*BhHGIl+'r,׈?xB7ATN[8ud*q0dJ/3g8UP\ u^=PihpN8ZNwgd w^`B:,8~ sA 8yY= @89gxpNhyzF񫧳7$zװ7BV?Ϧ僚{.7'G#×k'T7T|_Vy-ͧW8я7(LJ]ljyV7$o,\A }}Ym}zc} 8Ǩ@~^~gf0ݏ}~'m$棟]<}XDt}M`")$l5jӂ`&iOV\†x/'a0b*'t S4q*ԙUנ.ʇgMAўJ7^Yl-Su&;‡xKleT%߬ϭfrKƮt xmvSHם nnrʋ?zWHxsG8tHG]uYg)f-Kz-a͖^g eIHEo5XRw w %%A :8RR0Xl[V_CTW$ĚO8Anunwxi a;fJ+\ q` n'|ZG %S^ghf4UHdZQ**T|EG>i^"b3& ' 8'u"xዚmu4Я%d|)ʄP*z[\B8FB*.;_IItb// [0 󸭶;D /''xåZ'*! 1"lLj|2!l`12|sF/3Ѽ= 3BxDQH= 5PGW^[+`k^c|4%3n}c^^W}7RKSM} ѧ}EkQ 8~=Zmu]ӂMx%#>Q8T^ua?Nޮc'Cr0٥2x^ͣ9wy"- Or ~|o XO G-=D.5'\zo_>9ɉ/gvW M~hCvۚoyW@ۭ !<:0mt'? >5ծ <w*] {81%308B/8\U7d|K '0ߤdmLі*%"* 5ucr^Ǵ!k|~LƓ1rD$b;PGE L)$EٴHdD/9<:Nd"(+Ld)IDES<9ztKG1"MRJDí_)2()Hl,gD򖹤PzB̝*LO!S.U@,G0K2I)24N)JHV3`\e#qA rJ3A93镚T+DLCTYbDqZ#H5*RG9.Zj4='ь5O gy+\gxMP-j׌5*X)Rwz?t4'czzB (7 1BDGՊ*K،LlHƮl<+k8B"ijy&MDQJCj. OY@ݦbEvz[dmNKx/|w"ǥUs՛RU*UV6J@)%hhtjlV"e8P"'>Vb־)\Qc"XZ[jXR-4`8O b[Ē[찇E}mk(^`.|l!H p|(Fװ$+rj ։*ˉ72vld*bZ6dؒmV=7|C!'*PfZFX9EɫSdiFonn#zK[,Qɦ= -o=BY׺/b[mfM9mm=jeyx6[i?aV Fyѷhzp~]mL3a|kD]3VMKϫ^ $!i|Go;,oLNp3zi._ -+y䳪H~43Eنޖkw܃\5W>/ e 4\Et 'Pa ʻ#>[҇r9I#A'{@Xvhr+-m=A 2݄xӤvxb3ܯ^" nil[,dF_n&Z&h INDIGDŅETG\ŝZv= 1NDpL>1\UhCS,`Q[XߘIU(Lğ'TL5߽0 ݀En0vS.5i!{D^ ṁ5@AFEa Yqڹĝ^ՠaؑ BlMtYt 2"ta}!N`vُDdp`1u_@ sE. t"ٛ9 !+Y K]e ,ޢ0}"HV:]PˎOy}Zr1OE]b yB\½[ٙ).Vc`XY"#im "ڹѠ= pA;-ap(>2ZE$E~۴FN't@#IU9Z$"(2?&AqM@ReɑQOvVF%dR%YY%ZZ%[[%\ƥ\%]֥]%^^%_eBl%TvV}%Xn`2`aabV%cVR ZBdUe#[:0NfQ֤!a&? Ei$ f_P뀛Cf~c0BL&)\tp*ڣ&r&n>%s&j>Kj'Y'=&/^vj!:~gS6&}ڜp&8~& 8gw|R)!3~ɝ'Ba 2$0rhDv!flM89Br囼)c^h| d3 "6Dx2-ňfg~zz2ZrJ Rpӥ:euԨĴ JP(R-:/Y@)5)US`(2Z`9~Bg=〶( U^7ES*aE%Q]j %&Qݕ>ӣ T G3R=uELU|Ez*2BR<*dEjL*`T>րU"9~"k VB O*V`/lޯR +d_l+x9TEt dꙹ~AҌS) V*5j2,Bꔦjp: U%Q~9Hd*:~B@j 9,e蟆"&î$!\g_Αd%0_7#EƦ=6-d *zn8)Qvm~-tҙЦfrܛ-etaFUf(ݎVyd֪d{mxQmؖ*fH~(''lrinl&(i+~[Q&i"n^Hwd$uPݞh ?mU=B$~®k{­N.jZ).px&'Kr\wPv8Vitld+V,1]FnZ b02%s*pq*QE0Sen[R*.]^F&E,2 +I K‚j% h/He91c$6-*8Fiְ[)q ;=@B@jj ȋeZqzͪoiaz&jhI0/ [1U pY~~RLh4vIa-rmoj)k@ 芤d-k1[ѓk~C%K@9#q, " af7t2/ s=C\ת(+(2Ŧ "x8r@2,OyJs%g53'9>]Ğ뿦)1}\x 15:mf3a5wrf곌31ZjynGCt:#>39c..c>(I~izcrtb/.>/$Oc_9k.5F(*&UIR0cWjc˵[5\5WY۵J[ 6} 6^.]bg5ciudduMdm&t.4Gz9Q*w6.)Oq2rl:6bhj2rb2L4gP'm6j3m -H;ײq6rpqG162~s7uGu7*Ҟv sh w87vkć-!N{\o<7C(}1eʡx/[X_j5aǓowc󡎡wsZ7\*GmE~E6B>?Ue'uov32b!_t rh.݊J b՝Fqum:(8Jr޸h7FyOxEq4STPU{{R(j97)j$ڱ܊^ :yjT^`NGoZ|c9r>{TlqPxs}S1C 6k(9 ;q;Y(qqR8B;f;k='dEw/ep5ꕼǞ:-4V>D{6KVC{ :_7ro?v\Wsrݼ/ۯf[d|ūc|Ner/3sv4O 5["cm-txzgU9^D_V_=go=wX?;YO+-BCxw|hkyE]Mw&urg@S-޳7=[6WFnC o//o"ࢩ6{Cُ$)Z5zԷܿwE>[&/~mz" #ws/v[[sfӜgZ5̗˛?aЗ|pwk`G?:baX(q@0qϑ#&TPA !F8>. cG?*@Р QDJx2JEDUTxPgϙ?:K- r%$GĩS}&{fժpcƮEQ2 V(K0efάB3rk.!0̰.bkפ*  Y\nP8iL; $oKkFxŘ-ŊF0rc%5ԎR!@E8ݒ}3dCdF <̺MoZ"HM]Sc#ܨM8bi.ARls3ٶuz\ITt s\:9xo{q 0a!'(wTwRF?x};T>.}z>_Yu*?wr@>N+~'7rwݳ"; &Xh%T@+^= ΐx_ Ap} 41Bkrǿ}EwD(JhbFž$j{T`vvr1#qpk]]0ޑӊGA%f I)!?)dH;*Q$J٢H^'ALgT''fJP2dI*MN)i):Y/ewpKd/I)2co[ y=]5l(7D$ʐFcH43Ld4BrA1(nn󐵤qGLn3U^ʩA$W4lq!NiɱrT;5##ghQ:, BNLԈЁЏcX4٭"iH;ʫ.$y->ö\pJA G}lR[4KO{y&*fz,(nJ jP7e 9::ˆⰪ/F$:HAyQў5aMUpnTkHڠ_ۻT)9*ᧃ*Jȴhf#;cDuD݂ժE ֗Lt/븣Ԭ M큵 .dFUkMnOFđm:bXk[-~Wy]I؇5M;lK5djM:ۭV7*'<(1U&xf^ j 䙖QZW tRxsZbpDF G:n&&,&e(ya 2vJ?QZØZu1o>]8ҵ,fm[ KQ `"<L;~/;9[ւҽ^Gàf\oLT<1z!cRQX_YNd(A贤%@RuɄNZA^'rzu *j|-ls͌;3s9loi$w3uN_<N1N3q Uk.c/bC<%d83ѹRJ+q\|fɩQݐd*rkHoٹp9= o 1z>LSdQOS=nOL:]o7H;lOL)оFꁬثTy]oT ىQ5c;);nv[/A§} O>uӮrsk/hCP"}*Io%ӟ^GmWg0!gi?ڽ](SA% 5œGxwwEvHxk_>/pg9~z" u8(ڏOԇH2ώLzǫ/J( 0$Ш&#V:dr:lگMJtC(C "@ LH l"p8$R$貆p P#b* g*j "̌;(l.`'Pr,0J p"#@p;cL0 Cp-0G5PC5q#؊2&-*:n4*Ű8@E7܂0+^ #K/&+k<IB?أ}MAƵgѯN,Μ @L^f`$# K4P$EӬ F&DD5*PI #@^c -EK+оrւ%2C s: F tcW6%\NdoHDtg#?BJ u:SLQ%%gW k-H–>Y:&b!(5ŘVl)̾2 Ո?/3p1Qa,%f&42e+aL$ drSIӚDX3klԜ0ӆT318{g$v מ،p8+%-bDhd6$CB* m#$@/ f*P. ~Ԃ1p&qq,m7p0l&9ݢխ:ov+ps/\o N_("RS+J0N\R>bAp|PCOПbiD>D&".EXlϴzjIt4'BNdϟ^t\P8K4JJUTHEU/R44²t.L4Htԏt1HEToOtZ~:pKm S!U oP)u\pP_TyԙBUTM/RRSut5PcStfuGWTiTii P?WգUXՔ+5CTN ֌'S/[-XosV4uW55^Uu^u[5[GUF]C_5`}p`X ]N=?aa%L.X?c]dg91W 1I0zB+;p ((@v3Ad0VbEe!Q;jfYM15gv(z6;hV]hh42 i&/LKe:6#6\g;:{ \Rra~Q|Y2TzC~(+e͈jmܶ:pvijlL+*hL@ )fK=؃e,` =kf6^ 3D,C$*ngXFXLyehlIE?657\3~{8{='{-,4Hq ԌȨ WAoX!*MBcհQ@obb~4S.*`4Z\ doDI ]UT=bPZ4K:a%U.fd(#S)vb;zaUhaU6Q-,ک:w^_^缺k#Ob㱫:]Ϛ:z麮:z;{ ]$STjӱb+UrTQEt0Noz&49[K7A{n]5ia/\iTTr p @id~RMfHIIt:Ib de`qA I XQ㏽5z5#q:L! p!uڴ[/ S:5|{Tzp C/e0!|Vp<c}6w6%WuZ|1-==\@<p_} f6vџh1Mͩo*?DUcO=anN<dﱚbr+nM@OR]tr&F#69f:c :r@dNJTkk?~wt jw}C?26(=]#9=,gOJ&}OtIv^֪^ /rf ;Fsn}T8;V&&%b#1"ԵqU/cTAH+ҷ;C =ެ#ϭ~9Љ\%ld~>3^^O[R@x۞ߞ`W! 24=cw%]$D7 ^yוsq«<< u#8 B#C7Xq@SM_VQ_&cw;3;;"ćso׺|g ś={HU[µ_#bߑ <9dxUR %PnA @e F|Ab BVb%^.aieUf|z)f9f[vezhR$biNJ2ini~ jbJQiaHQ %r 2 :@ 1 :kkP$K밸JlJZ܂Y ݮn`ۮAoދo pLpĂol:'& @&H &T "GDs1"l[{l2߼8 0]2̆,s[EmIAC=&ZouךH%bMvf=jvn wrMwtqvޗ0,Y@"B*԰#a OB+1*K JrN8s ..?Nw諐J/|*RIOO}ӓa|o}~OdX~&| !,>22xAffx: C^:xx_!x۾d $Kfl`.U1`beBCM/]cam Cl!C곴2Kkea37_aH`# *\ȰÇ#JHŋ3jȱǏ?Iɓ(S\ɲetI͛8s)qL@ JΙ1]ʴӧFe" PjʵkF%/}@D׳hӪ%:~Kݒ`8+ݿ P"Ã-dHwǐx"EG̹3 5Rc\ϨS6 @}MC0OͻkƹeN Dm L7tJOWm,G=qD@L +5hZ}a0vo |DMqu=@s#lvwu+W\oW~q @cޯ^[_ .ȏK @ pww N| ,ى1wq@lo=o+~9D۾_' 1)OwR-t\bp:վnGh0>̀K`6֥ rP8~7@ &oFtrAag=&..q _ pwc>'8;a1[ǻzS&FkɺEv80aE u@ C 򏀴 `|}@:@8r,6ȏݰ_7T%:@*0IZjlu/D&J^J`` Ij.Ӏ3!8c͖9d @$^,'<@0"$Lr#`Z"tz[9a!iћ;Lm-3ڽ20@n'|iGn0/>Wr,ZjͻxM ػ_,Q7wwށ*FM7@`Ii}ݶZdavQa{!W&" jԠiЌ 8a} ԁ0hn-fxIȤ}m=s}1cI9[yh`בdV$FFĕp][ŽI%j  lLfjnW˜3F~e&ag^&k٦Z@vbm76m}4i5JЉ wak^*Y=Xb嬼ʚIkȒkQ&,M,f[޵v-G~+p覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡e6@ H"HL&:PH*ZF.z` H2hL6pHG0x̣> (BL"4$'IJ2̤&7Nrc$tF X^xqhVJJVrN.{ _.πަڧadif80:ǓTi5(BPv>~3]SU{; 0. zx+Ag 3 GhMo$v J@Q]-9 ߄[8 d=9Ǧ|9p;.c949wsMb@ЇNHO!,22xA۾f:ېfxf:ېfffې::xfxd::f:f: C _:::fx^:::$Kf::fض:.U1ې:/]{l::xޏ!Cv糴ۉ::f:򐶐ffaf::3ېfff7:H*\ȰÇ#JHŋ3jȱc=Iɓ(S\$˗0cʜI͉.oɳϟ7sJѣG"]ʴӧ2ĂիX֔ٳhrUxׂ)|HKݫ\w/x!wA/cBV)$P3sϞ P! Z+`/b۸r0ېL2ǯ!>Hvw#Lp X&H{H o໅'F^ #"A0$KP/7Y( t x@ep `z ݅I7gn"ifq9܃ۉtd|هEb(6#UcA( _P$zĀwi!`5ƇAp|8 A69V`pf}v$1fxg}/RYmxfRAme\WLi&Xj/8unqo(xPb+.~(]Zn!A*:&mgljBמ#ل~@zdfkYr[Wa@deyg{Ng鸆*f?k.fWf.,r_ý*{i%h&(" 6f 3GxoJpr7O'/NZnƦn,Uk%B jƀ/'/od=b@ C꺕Y8NU DXa\<]r.7ᔛeAd-5d*mhq`Q:Sgzn;߮M{&7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbȔf:Ќ4IjZ̦6nz 8IrRSL:v~ @ݹ́MBІ:-(D'JъZͨF)эz HGю - PҖԟ&}LYt8)NcӞ³OJTEjPoԦ:uGh @> `سЩRԲSj<*ϩ#?*TZm(]q:VĪZfh^IWZ5r']J:t2_ X M,;1ذ^id9Yb \ tzxUցhHRnOANXBYQ^ElhO{qحiEV AS*Vk;\ԸR*rsXc]t+W;@Ytz@TaU.sAYԸ@~zÉm0vku*ؿE>Y kmm:lNg #&Pb򦓮5ii,Zr1 [*d5Uaώ,1`@%uMq}b To|^H Vg gDgh8n&| =Yu~rU{9p.[X'ث2pS`]@首Y MǸw SN[ |O,A n*RBhf%rwQP[$MOPN 9ph7Dq%77qC 9r?.|LW0g̀!,Dx22A:۶ffx떖f۾:x׏x::۶x:ffېې:f::BCM: f_$ C:ff :KLW۾:,,8:((4f:$f3:::۶fCDN..:f.Mɶސff33?f::fablېfH*\ȰÇ#JHŋ3jȱcB=Iɓ(S\$˗0cʜI͉.oɳϟ7sJѣG"]ʴӧBJUR^הYBUٳn,Р,L@  K_"6PoCnT0oM)پ% 0 1d<gt,d^ƜYA>{޸~9upW&4x @ 1tH\xtCh:ٵ1 )Zq7שqr8%\x\ylwUԟ\[(|-FHuAk.h^㕗n!aRE!^3Fb|gPTE@yxu 8R7SVAM'X[%[OGZےMvsaU9nxT^~Tb. tnY'b'DaXcZ~@6 B>z@BXT9:Ѡgcׁqje}U{Fn8ÕjBvhI&umĮSIɝʥg*Jqж궻Թ&.Bk/PVTo۔o'X/P5 hgv ,$l(,0,4l8<<@-DmH'L7PG-TWmXgt\w`-dmhlp-tm?߭|߀.M'7چ?.WnGwk褗nqꬷz窿.wvS@MAv'n< |dvs{j>>7/߿?œ0_6=ړGխ|nC~_1l7 \`~^;n迁~'0^[ 50Rw³ D*t_ <\AQODap|\"8`k9_P~z4VJ$ݗAx#}XA`xk [G/K$(Ow`#@CbϘ͌[>}Z;'g5@>,^-XIҒl7]621ro Ǽ⏔64".Ăe!8H^`eDfhK$a9 2ND33d1M5`fc劷ެ邢" z6C٪!Z5@-߆ >=N<0|`u?=\2vv=_wW[]WAL6<4i5A`Vly"6Іq|7WX"~}\`)0[e`GrIifM>BHpyYsY f`_mX$Dd|Mt`*Ge_ڡ`yaIxs>v&a5:e]z[u/}R'Zs*HkEǖfɊ\ꞧiV(j|Ėoi*&%t$E8BG犜U@q"\iPbJ.4/Uk~{ZX|xG;HaZp"-,5fNWhs~yr UVqI)r?8kP5",}ݍ7XJGә!Am5/wOkI@e`D8~_:nu5;);3se+4OdtMBtdx%.CnybT^~kyJ睋nGN饫EnCߞP/o'7G/Wog/o觯/o| HpL:l#H Z 'z !9(/+0 WA Rڰ.p@ "rXd@ oND&>a(> Q%4@x @|U _l 78ot"X> pbE0q,Bx5F;:pTXD=d IҐ|d$H5Ve%)"|\#^Ja`  VJ&BQ$1&~O]{S,c(`M5@5ͼ#3wU|#vIT^PhM^bӉ\4On %>\F@@$&,'"R EpqlChQ s^"т&,Eug24x,$SQb3 ɚ:1k=@L*$ǗՆNѪWhH'ՒFL)XӁP. :B֊TF(:ѠU4jC0b5 "OVŪ# ρpPUB*2>zmdC͔m v NCЭ5\,A`d ڪ2Wl8{VׄgBSJgs SփW[JR\b}e,U1uhD՟4cmIU.2l mMz^@!,JC 22x C۾_fKLWfx ((4 8$BCM%=M3$p!C D곴..:/,CU33?Pҏx_abl@A4PB Ba…Ȁ` B  @B Kg`qKt  A 0с3H R Z֬L5pE5++Ɩ5׵`D l+5B08!@ $ȕ`C ,P!9E *x pZ0!,?u121212121222222222222222CCWjbjmsx~{rgea`[L<:963-}(x#uvvvvxwuqlhfeedcdeeec]O>::8720 -} &u"jc!^)U*O1E8K8A8<;?A ?HAW ?^8a5b&d c`YLA90'   '8L]P5"#0 72"e8:::@PZaccefl ̓-֌8ڏ9؎:P|ulsrpvutݟʂmejɀ؎ېܑ H*4XҪ#JHŋ3jȱǏ CIɓ Tn˗0cʜIs%K(sɳϟ@ }ٲѣHkVʴӧPJI4իHMʵׯ`;V%YfbŪ5۷p-9eڳd﮽v߿-jWo̻+ǐu&fimeFG̹g =sϨSˮװc˞MlͫsԶMq+>#.N=vس뮮׵X`[r{x㳦-˘ -rIC'vN cc  fmD`k1"rXcqɅSP62H!to!&HT;-M9x~["p!&cd`QUSe~,Yo8(St<額R`m81FrdiH&,ک蚭A:)G%}-:jJ[aQ1%v t .a%{!& _ѳH"d2-ưc 0$ȱv"=+k蚋> K+/L.L C.āAlS\w f]($L<4[@-DmH'L7,TWmXgPw`-dmmlp-*/b݊|߀.n'77ݐ}wfg9^!ZM騧Y/H..;n"ᅮ#4ۮ7G/WogwC<ŗ"ʤLo DHʀVhKƈ1 Z`4 z GH(L WB&B-4dC]`2PA H`D0&:P c8)R0(#F` A.hL6pH:1ư0~Ġq'(Є:8! Nh/Bюz HGJҒ&\Rpth1aF`>pO$A>!}@MԦ:PT Ճ3 ҅U죩.A PhMZ`E[u9Ё*.,KNۏK@c?!J}d'KY~`ըe ծ~7hGչJ6s]5q9{km`K=>HKT#H\ÞMr:Ѝs~m tBmnvKMD/ЛhBPj1g[pҫ/=_7]Ȅ3 0#)@&=L [ΰ7 4 lG&DoF;LND(p<`heBǙ|-_G PE>rCM8YMT@$0 <`L2dbMQ~hbF4π4u,'CK1dͿAR&6.}1@jRo!VհgMZ:}? p@u-ldNlX'blLlٛPtZ¹E$DQ~7 {^0l!FFP_#G@ @N׮浯azimWOOվ6=x{&E#=@>qFc@nF8g  2b=_5#z^AF(bȹҗ;Pԟ0&s:/NLO=юhvBPt=oV[4\-c.RKAhDhϼqw^)+5@ͻN;Ss{_RdaPrzg_?zA^2E%L"3pzh{OU>" ϿDG{ _qEK З $Oȧ DMŀ|#} $ $;%';<)P0284X6x8:<؃>;@ D ZdфD Xx O(;V}O"@0[PTNU&u؉ l09x(jqQd\R\ Uh 5 Xx\NpPe،8Xxؘڸl8lъvHᄬ9GH'U%30 e (s@f.Hx ِ  m{xؑYQd` $Y& 8`,I & - ǒ/N<ٓ>@B9DYFyHJLٔNi R9TI?I  yEwQdPT9 fI@S )8k >Y.3GRWY\ɊMGwbnRjRٖUSI`  uxNә9y8~V{gaid 99;Y9Y2 雹b.rymaeYIyI /Ɖ-4a 9EF 9 О/ "3A扎iE : ڠyI. "刚W%à9ᠮš(2* ʹ9_2> ¢.ړ0*y%: մ44.d (a 2C*SB; t 4? O4QZ:JXX*ZzE\ڥѣdZ Izb*0զn]kwxz/W9ZLZ:.Aڨ=:.t*:qz}Jک:@*.J(jʩ.J&qEC6j*;QzqGzȚʺEgTzT}v*JzJz*Mʭš5ZP`! +A ijU[ʰ +K[q쵲,.%j-<۳>@B;D˳9I6[8PR;T[V{V۝Rn 6_Mhjl;Z(=!bz}b>q qF"F; e{۸{o.\4٠ (P:ARqۺ[#1zQ˷)P a˻+^K}+us1"!K{6  b[뻏P_; [2"Z#ug»u;G v8 ^zu+uU0۷ \,›,b$;{;{0+|klk֋۹ۿĂ<,Q z[ l;U ;\2LZf|hEy!ä  zc{#g:<;vxXR L`,b<ƶJC&P !cP_ >LŢ{ Ăʮŕ˭]lʷl7yfZU&qO \0QŸ ܬ͠L˼,ź׼_aŒ6t! [l ~c] {\QWƅ c[c\[{< +*A<>@B=D]F}HBɀ(\ !7}XZM[ѡ7Rz[}hն"AӖ:t]!&v׀xz|=،An\'{؈zz٘ٙp+{MŪ٢=ڤFMAٕڰ=ۺ4=]}=ه-O].=؝6 P-׭ޘ۱==L-V9ݶ^~yߢࠃI On  "~9n$,.0>!>8%~'~1B>C>$[޾`LPn0N^f *$0^`bF^ޕ`RQi 2e ,)lZY 's&4%*(^~؝I^\ƪ^.'H;/q ;/}R#ž㤎>d]ƭ>$1),P, K+q n#`G kP$@)N!D@+ӡ8_߉>>ڎ~i!rJG@!:?i]0@V68"`°pHU$o@p_~R#@c)`NiO|nO<NqP!*oIKSpV cuPPlFa'-fD@j;.Q 0_ >D,{0*Q*A.~RJ~2Pd/PN@OH?43aP!Okn4!/%P-_AdE1DRxc@.|C-^ĘQF=~T8H%M3d`J-]l9IaΌ14据,4l4 ACoKm(O lۑOᷬ ~HI0ͮJVZjהvt|^}()~)ӀX9"Bd)#UQU*UX^X5F"vVloʥE1@X]wp &|0l؊[oJz_!ŃN~bla^)gQVhzf[k||%mkƘ !K a z=0AHJ p#+i9rG"X`E[ȏ.ϒ=3= ߫*C(?cIt(A/H--TęP IB I7߄)?BtD.1A%T<$C PGߤ8r0 0<Ԣt E11DGDuQ4O?cXckRe A2c)RyjZ!O2e#Kۻ WqRu a]RL^}ͨIXKcCWH*݃o$a 3wۆLaB=AUd~]2`j6g5#mcI܃ȩڸJuaRf-M8%dEUeމ܈>Yy9qJΪ͐x%a;o=z٬U{~h~qpw*׻io?joLǰk*5³x7^-#0{sD֒50==DGt[~\]9SWO,rnMw^+LM4F&^9{E^ yG_)e0#􏨢М>׾`~700T0㶎XeK

Pr`\[=4}ı9uyg/y)L鰞$$5xd泓4ވJ$Mj&B!U6Jl!i|rhLgE ټT;#IyT l)0~n1L1aaLT'<9hBs͝* h,BjSG^!6RMYJsf*<}ɫb&T-}w=Ls 6)71ZҒ ]iw3uSx H`o9jIթB#>O593] $ hK[JI*JݷqOuM!Zl ibJ%=r6.j糄r@η4We{Tګ*Ra)JW-e:S$';yHvlZj}rXoGYaLݚEmɋ4T1;$x5"% 1W!Xqi .3AXf.$&Cz OX!$ؐwgq~'w4t"1#@t#8n1s a9-ylgh3qF)D)7G<&z›֍uF^KL- YK<-g߇K]7ժY[Jآbه1g8sAk!ݎeoЍ1\L~w{%= hA8%xf!CxzK^p^ofO]us/Do[Rr kJ4򬣰Qufn]d]_9ە];fIo߽#-{%`^}A_⩑ŧ^wH~ăTU189w&_<4ژέ'O%c{$] !HG8q~P5G>vP\O!Wwh]g&4';-"BtT39>Q O|'iӄ!%/3@#?QP!Ēu8,B`bjq3[/Rп?:P=n4@v@+:5S;@q\q"\# $ӈ7Ի.L8p((p@Ç;:s.L-a[ws1 Tq  ;$!*{CB+1$3CG껶78<CA5!$I ?đAs@U< A0-H|<*+5.KlL++ pVq^y p$(QkTٳs=TCDY,Z+x,E`bҬ*SJ\fDh,|XJCAPAZ"8Ё I 7s N1ܳET | 0b2H Qi1)Ň?蚮ZFftF+Q7l 8tD @h:0 A#ˇ3eZB@!?"GRD*$-0jA:/&+H2F~,0EL3Yo$Md˦HCŞ [mА>B&‰E#$ ~xDE6pZ h JJhI1T4Lot!8ϖTi:9Qɇ^SIȃ1ӖHO ZI L7yE_sȹa̳k *2@dA.KC0#@JFMp 0M8Ea#|.@1 pp(>ؼ1  `PrO!1,iѤҺhK-IĂHx58>[AtQR1cRAȏT*=h?UR@,π!8XpL,5Tjyӷ&7lJANSDm3JUUxи{}IesY T\};V[UC cUObMKe8BUV!U {Pp[<lY FT#Ff=gŻh}p>̀({X/}Ps]N~?U@ w x- QMLBoԕ=6mYLv<͓cm,R̊ ‰p7)԰S4Eu`&u$=Ո=uʟRH : ;L!CmD/X٘YGS]}ڽRd"D.]adS]Bʣ EX37]VzT}[fڦ֤eG(<ΫIwBLE!Gi7aM؃FU{ʊ܏ʋ\V*.$0EAM Eڥ%bZ1y] &ˈ ^>? )]Q2;\ՕyבMs^MH -\8K]hԊH^pm<ۃ_\5__0ʋyTΠ> qDJȨ1E "@a.;Ne ~J#K F1'y*",Ĥa.bI*&0"#u_R.r^i*bG-M&*:"b*䚬'23>9PQ,zc&0(*|{rwK墈56^e,v^|BKb%euONeXQR6V,mdUeg=n !dTtP6/7t8o>M N[bM&uaS^PYt_v#Ś%]u>shc*ƲZ| &h}$=dFb'vgWj>}Vhkd?&gzRbx}zeQ_&uɭ9w Gs<̓ͳWlLJxSxb+q@Uik|eywexH1M>uISy5.cËbĠ נLǮhj[0 [-©kQyYdZ<8\O <ͻx{,@ס'{\gz?wLY'Ged4?fFC$Nf{DIaEQ ڡYzJ/jl EKWo;>oUc|}<$|ĠH߉8:²ٟZBXz]|Z-}Kb~ucw͟R?\c܌('%oYt0`ƆQûoK!ƌy`B5 $HcvxPB8sD'РB2(ҤJ&sI7*֬Zr+XPy$jWl-\kJđI$1DVwo1WITxbh1+'on 3DߒnlUưs(E^:6‡/nkI2oNrn]i^tEկoG-͆2Yql~FSpbW6&iV6n)q :  RY$ha]ss%|`,P9ulfS`y xUipfЌ[km6K򣀫vcWdpu n RZy%Y4%[ze\}FM mcAb8 dQf$, Qљfilu֟3`WB \%z\r9*L4A)*NyNNRI sC]ZwWmb"6h;gbc}WY른9Τhg ).t٦_V#B;_rxVϠo[$GY/{ݨI2 MW/1/fJ')`+,E DTRIXaY.|{J+a ƧF>2L%Nh?`\"*VȘ',R&,1lZ&0/a.3ldPAiV3Y~W @DLlp*1Ud#vFʩ%<ԖFJe'[ԖF> jˎQkAHplk;q5x{M_RڍU  8pHs;ԓV7-mOHZn\✦8Nh&?9S޳ͭkDaH;xjo(7hU6ɝu w^f;$JqxuuI=*[G4N\c)M?ۓ"s;_2)/s}vv NpsZ4K-H_A8U!_R`P ޽0`J5  ܒ]ܟHAi^, Ze޺՝ҥ[`]u ZY !S!ae a!qš" qp⨬^؅L^ "'ʙ"!# $~ %Eu_hu`&v,'[(=$^_cw,cb.&#I_^L!"#7Յ36#=pE%l6v;a83r.F%#`dc^;|#%c #H#c t0#]\!)mަ)Z[t[Z[]eIA:ABE)~4CZG+R+q!ŴFڠE^ )_1YK:K8#4)j,f*db!-I)\TfT]e2f%n%W2plbnHtlӛ)R\Z\dv$ѩ]^^~ݼ]7- 9Wd"\bMyՁ\Z\a_g šh`ifa[&f1opqmG][lgN&q'#!r&̤^||=vV^fEuf V|'K2'cEH.[Dvg)Q (^5zv 0 eI_dE  q(}i!h>̈Z`&h٨"5V}`5 e`$(pU~x6ǭ'2bɯI#AB5a٩F$Z')Vڙ_`<b^ YR@^j(Fhb(l#j'rM*)FțcZ*jjA*L5*jis*b$&B6>+FVNk(h^+BkƝq+W\X@z@k@jk`q kjI̩x2Iiv_E迉Fd5a qk$9{O9ۆ *nb >%~JF)ʖIRlaM/&ht"[冢6- )}.^gbd>",)fsD?Q̭Q6 zmM݋'p6f,laČRm~/Hbj t2m[m]v-^olf'gl-9~ !ڛA-I筍^~eUwBࡒD"EԂ"$r$Ʃ)R쭛^q mgmg onir*%ݺ [Fi˲.Z\("`F.h\΋[*ba'o֠}ʠTƭ>L+"zan) J >.no-LJ!p]nd/ik`«SnjZj2ksR9*W^1s\v1a[dq7pRf* n1q711" 2WkWW""0#n \$a%[!"&a''0$(K)ۆ#, VUQGG!LN$-Q/w+ sr+%K - FЊj؎dHPArfLxTP6g73T2r3+dK-:89/Os::D4AsCdD#4J/ND>Il VgI@Zirb7x`4 BsQD6 xlEMVG?c{܁9Oe-MZ>vo7c&ÑʽW|E9aڗ1Wu~99}g +Ӏxe{ C:$D793S~9IWyy9 S2Ǚ_ȌE/F$xyTH]]_^S-GuEU˸%NG]bvw;:Q=C#vQtzvb9#橿E¢"&GӎSysWzWD{"訓TqUOyY{zG|thHu;|;aaoy|s;~{aE0oVXKk纔gWR;:C4ʀkm]xAV,Os. @6zuis {_qCM4R*W6N;봛hsCOh H:7jN7ߎ;wW,5[a*VQB󳞰JXV4Ƿx3=lC=>W4`gJwto4F5N#ϰIV4G#7,}kK7?,>rM6YtNoROs~/w>>)?},CK{5W5XXؗ5bk6xwutt3aش}^36|Y3a'#ug|?va?@L20`A&TaC!Fxp*1f\5cGװdI' XJHv视Ae9p~sG>jl ҃;&Uh́NHp=_gȀFg1 ܺm[oVI!GջwLJ*J%tѢ:.(0TŋCj[W<9cO|ymW:m\ׯa:Ex6ҧrTfaioY, 6U)r<հty<ts⚳2%HhRglT.jԪkV+~}i׾-Rw)I .:jã0 j身<ʌ38*kL= 0ͽʏ5x/wp RH\|e4!l2.W?ҘG "H- s?΃G&Y?{ 3jV;Z3u g/Zz2|C /#6rlw6OZs?7wȉ%jG1]Iobo˂sѢ~O-\g-sS4U v7{zDv(J_A (8HKSբU?NQtO2ďA΋PE;=*1gx؍4Tډzs`)ksJTȪRKDf7y>}piNr< 1y93E2Y(?;ZmӬmH"dK;V0|`ZP!HBYS^d+9C 4҂RKh&/]5(:)6tcl~p i[<z2LϤ*¤^SOtjIJB5F + ҩ5ΊVtf:I )X^cX^ۊrbuc!YN;:ngAXĚ$*a:ע_ݫ_׆MlfkKM [D`Jkڷ2)nLmU[UAA1l3ddfĴF*͆7n8Ѯr%Kbsiv8QZ2#oP(X!wWDyN;%\;yպ%c. +]#@`+H [L)oL\DX8JBc23/ RG $_CU(Ts_p' yIHH}*N1b)|X>;>*GSX!cZ^W K"ٯ~b2`fdqwE V; wgIj*"t9-+;PKT^&0$ nl433Zǎ.bu?nA8 r8gxL|g' NQҍցE3_NZ2:#ɐ .dz$)Jz6$=`V0((FrdoDn;apx )!|1 If☦HfO}(&ty:^Qo$sI(3ڔ(EV,5_ /F W| 9,=%c?&{Or Ɯ~s)3q%=!&EKO(፦9\*lsPAZͯ R$QeӹtBjSGRc"!;@,%5;p]B׳],l} ,{7_mIC6.ۢ-NM#T{`=N绹'9q]*- q׊GhSTX~p}^C9拋A}Oobܢ~Op"lwX/P 6EOگ&pS P.2p-:q$PǀLO#ˉ|/zLj d O͌ظ+LmϘQpL6Q8ZfРpila6(`E gSrތXtV4P 6ඐ#Xc-ˀh0t(;{vpۘ;͋j] I !R+(ɑM $p"IC-m H & d1N Q`)!ǠMXBF.:އ3$ :媌cn(˪(%%Q78Ni:2|$Ҟ.nۜP옂İ$,5~a@N03AģB@i/@$)"D ,0wrIT{p6" 7B1ώd1rx66+`S9'>*$.8S7:6n;*O6K1xe|936(6,+pt63;݆>.Pͼf/@Yc< 7@PmjAM1TC=7A/0<9Brޖ 9Ծ)v+_L k3kF {EErNF#FJi 2!0n FHHv'< NP qF@&^"&12,Hkg@.M9$!tn  ;E JA.(p,M U~Hm1'FC+/ zQ:A?JIB9n1!MMnIMԾ2GzCWQ,ф15 c?BCt9G!OK_ džZ!qՒzpQ[ofsXSt=:T =SbR#C2EmWqCbp,eN 6l(?Ԙ|G_V%Nf6n d['0xo@n0o|V>id8uzJљii Eu^fh4Kf1cBkrXl͑O_Ϲlm28N0v9vmVmƝL)qAĆ p_5 O{u>CO}eq'j3FrOԈ2 4KXbfbC<tItt%Ѯ7w3qw?DbhJO՗Jv!|=/?CL9uuRۥ/T6;;yٺ$d@גoDE U;JN UM{[C۸WZx*tYļW4[2k w ;X`S 3\#KVC9ě2IL8Q U8m5Ԡ>k)ixy<#\™ؾmfL'Xyjmue@e\|~e8Z įWudEQ:MfGK\mG-ZnR t_f{.+B+}< Wc1*,8tGbUiC8(́ѕD GԬvw/+S.N Zpޏ{|WW1;rqr%op8j<*4sDs鱫]2<"yR\wI`޵(Zqs *=ܽA|N?ysȥ&-'?H>^04K$UE]\/-{;G`ԷF^YAOoÅos6i.TF$QJR(!TsUbп;Ubu; 4 0@ T(`Ć#JXqaCr8cIJ)G%lm@uWoQ؜ T`iF!t)5JՑvHcAQEgUi@B+P^Zq G_iN~8i )6D[>ΗreObi aEVh E,hҋ0$]\m!hHP ~5?$Qj) YZih]Fїt1Fi8IF{K&(\::Qh=JM]:aZguiMk[Ei $Azӯ|9L 0ؐcQ K(:$= \G$hJ~L~npKr»noRߌ3aՏ!cHF$ek7ʹӚC^#N| [y<dX>.g ;CXX'5jSÌah8Jv(| n WŁ 6`J(' bp Lgoc&cFQ\lcvYfn㱼0VuD:!,,!D*rl!wq&%/LjxtIe~"`6MrlY 'INf-oyND{$#Z_~å1L|.e2 h<<MYJR ]7HXE8ωNMNS* ;Q(kqH |S*!$ͩπ lJ h4ץ/hS9Ј*ьOV &01 gIQt0Ҙ>a$Azi>|tli3WS Օ4ynSĎJa`D "ҧZC-%KSPn.D%YBXЁiͤOԡuEeJCTrS>P}}O"I钮 ! &}ќ8dV*"k,ZɷsJ#3,uUR%B6]ԔJJVA^t369WR$D.\8J4EB]A,`]O7%ScT}hU!Hps{++W>RfñJ!ꬋ9JL G&Iֵlfcs~ARYtXXj -[ v߸X{%[v9=Luf}/T.m턧< TjɅՒkfXCPiж=x/]z;_ںfv)Z[Gꏗiϩuw|z9Ls]ޛz u׼t<9Coo?cELR7rijiZsl6|9 A^aiت3Q^P>Aqv3g>u}cؕ(P  -t6'r d"ED_AQd-Q g~ǁQT%0:Pwt} 8%'%&#}CK0&!g.&dC;+9$Wj0Eh=_!$?(sB9/9S3N@#1_8J5"~1q q`@G?g Kmӗ/| 9cR/;I`CӅσ+c%G(gW@2Fx%X^(%(Vѷ1CcbS%Cd5*Op%H7FZH(5rXȅ`\CO(6<39c4%gHhyc6}}h9D;8SӍ]8hg93]hA{-&@CF<CgC.$#LXԆPTA%x8u>anx?.&~ f?+>oX )D@a@4M@@StCH崑StbWWF AsF!K*1wCq6tQ87@|Hu`DWUKD}*1a'XK97faՅ77>7h4(yܡ>ј|ٗ#V74B$u/FQuIt tbQIbyB&)7*rmc>LaJ┢ir'5qƩÙRYy'REASx]k'1O)a虞t$&$yyBF6BYRntA/ßvI 9L,rUYIi:9)bɠY~jY#i@ҡ9z9'7cAt;j1EќI 6B0QiǤ1`*ڞȩtjMɥ,i)y3ReAg}3$Ę}iY8ӖT+|'8Cڢ} jwʁgIf^׍̇C!8dVX*HCѪQɩ@3;բ<8$Or 6j61[G$Z8TĈ۱]ګ;ZDVcSIX))Q-г`tB);h8|xs;X+W1ZzvC9$ E\)cI ?hw-6>4 zu}4O{|6䊬%K1xX8cÅKkSv:ۭ`䑻M۴mV#S xmhsxotZۧ% PZ)DT$냒?nкR$/TيE0”7]PO|OCg]*|DɕaYUqܫCwT|@Gk[[:ѷa౶ǾTYT뾯hP;(ꋿ=ƛi]tݙk,7gq!<#&|3#,:#F'<1ÎYç+7Mi,,6,7LI79|;<*ܡɞ׹fhjG,Q ^|n (R\)qŁ~DSZr}QUɱ4W%&gK8A'!7DztCp6 죩IPm%+r`V_c&ʲZv"|5Un,BC¡PYQ+ę{p=~ QT<,h68$m!b2F/  25@s˿,*0b$C𮕂ǡG5 bcBh ] LܦpUZFfb{@r^y(.B.g! AUr2]_'oyсDXѬyI+)M) (acӗVC4{ЍDKtYY07=w A 'UqԎ/5LÌbTsi,'!tŴ4V3Ola6=Zh! z:V\\C+o{6ՎMi)*gVxY_YT`϶_Cnʏ[{6x͂S=gc\k݉@ͱ * /?kÓf/2 mRw==))%bƍe7q=ݭ)*01Kԧ|`y;Xqg5E=i,:'.NEo$<ƤUqQ'{1>B\M,ML{5BYIK?#P3 L+Ē'lCMf=zbSMGF5OEo>LpH8yΑ[(~{9ـN}W!C7?m59p쬔nVB4Z,NN=6| ! )N/Ψc`5⡞£>̐ɕڀnhDyDaVCH}ANLx`;Ϝ|&D̶.@HӇ8A5v^{"i8xhE5Aו=6Ί3\9Md,?1'2Y0ފ+ѭߒ4#9 &(Fq$J&+58tR/Q w->rٲ#+NAxuJ /Pٜ@7+.6>.cmo>'KJ]MOo[8֜&~k+?)ꐎ_`)=D,F]IXm+fމ6`Qͅso>9o͈Յ>eYNք&א R+RqN\Id%$XLUd[ ܁៱~T>ݯc$XA nw(aʼn 1^(qG=vtHqȒUd$z1eΤIϐU9us$A%ZѢIZ:UNZuÆ7BܪD\S5YBrT Z(q˴k6YWMy{_} KԩޝV/m[oj]*YLAB5gvEgԩUiҵ:Ϧ혲ɓo {٫eg^m4hcC=]'[^NۺbÿX;ʛn&Nz\{.z8uSG|z#5^, S/9#p^k24hJ@O: вpTA \q+% 5񪅲Mi{FdrI&YXc "J a+yTS I2[p#\E2IĢ .J.J/F Cy1,5(&bч }: UhЂ"TH7@ 4#A !?BQ*BHDM7sND<""/mdPL#EtՇCMǠv!kF%(]UVCMZrԀeQIYbQVnU4[aUW5/_VK$aE\*&MKTyZI1WtYYM=׀ŝKpU5c_ g` VO.rV$>N+Ph%Ral:?dng^hyKFkMwd[3S3FO览.H1(lOUHkw jnw`f5uG'/wt)T֍3^)=(Gkp5:}řbO6"#´ghdr~lx ggkvBo^ϯwZ~gjɐwpOP$` x@w=^1K2crͳ^W=uσ#OZ⛚ wy/&̞F82KNQC$b@p$ Bȥ`"1|G <ٛ! "#aG2Kf2ߡgC/Fm% "CMˆ{c@$$WR|Jy2D:4P[ReFV2~K:ɾZ$hǻwzc+]J>R'@FO2]n їhqF٬ep0KFa"L%ʘ@e9y2'b?hpU"ILEϞ45e🅒XXI 9h@wOb?NroDgG=jNuBW!,&NA221111,,,,,,,+-,60.)%lA'!7  C]OEA6?w@ b` "HD" n;"&I\bHE#J[HŚp` Ņg4#FpH:x̣`H?6\ |H$'IJZ̤&7Nz (GIRD }JP\e#a`C ᖸ̥. AX%as#/f:Ќ4IjZ̦6n.3Nq8H,<9IXzBP XPWt6.P҄D0QL(E!юz HGJҒ(MJWҖqKȋ5iKiv睌'?JԢHM)I OE(CZ"TժXjUzKDhD-QbD/MZֶpNq*WҴ+)D}= `KMb:d'KZbH%U`= x.gUP#0LnqUmw2䶹mm#\Mr:ЍtKZ΍/[hw x9~]nzi>~`5Kͯ~%+Zmj S-!BP0!:&EGB +$(NBb A1E8αw@L"XE,:)V2eWJF{߿׿`Jϩd6d:Hp/!+`/F`LX>x %8BpF/z _02Ax#-#Lx'?mRԨNW) Yʼ@1w<:W5gTo<0yaNf;Ўl"3H8Gx`0@ҀNvCxoa-c>hg E F/@gܒ@/ U#$qd|"x;$/M0o 19Ps@ЇNq>ətkq9Mk{vN<!6x{@-?xϻnz{~7Oy}M&B1~ "X5} [|&`EGB+DAEozHK}oz@gEm{x&O;g~d}V֧~-|ٿv܃]/ׅv6y@5`B\"]fuww7XoJpo}xl0Ueaf`vwKa y21{Azz*Ȃ q{1{|g|7|+0 5B8DX7}~H}W{J}7^w~~;;Z؅^`b8dXfxhjXݶ7v; pz6`4Ѕ9XxiHD8;Ye(Z舐#X eyV{z{uPpVq4q 8H8ኺ(8Xxsh%Q8s8<2 xؘڸ؍8q x gȋ8^xh!o8 ؏9Yy 9݆Dpph ^8r ` ~$Y&y( H`08I1ْ :7PFyFWuzP}8@ !W)VQٕ^UdYfyhIk1@5n rY@i9Yyiq0 䘌h^i_i⁏*9YIm?p<0^)<ٛ. 269©(:HKvFapFxPvtq`1 9鉞y !)Yy!1Bw)5:Zzġ! 9^١82:imڱ蚰)i 0> IDZD:H:HzyL39I1ZtPUXU5``JVKt@lʦ Asrnyvʧm:*x(¦ʨڦZzک O6ʦʦi*zlʢ99:ZzȚʺzɑ Pڭ⚬,#ZʮH 꺫iF UXEhw*ovjo|{zkꩋڨiʦ["^5P";$[&며ڦZ:ڦ粱*kڲ ʫ:@B;@DG;vڴOKZ\۵ڬʫZca+ci_ PX㥷ZݙK D ѷ A뷂{};[Ba[{ۺ;q G۷p۸ [ѳ]ۼjjz5M9p;*ߚ滮ʶJDh[Z[dXKD3k ̸<}۟`}"ۗ 뻯ۻ[%L`+Û˳[6 püȫ60qHފ{:k+Uܶ@ [Z/^ a^\f| c,_ki|r^+tM>^]EUNEO0$^&nq*).>2>4^6~8:<>nB>DN'^HGL*⾁8T^V~XZ\^T(d^f~hjlN&PVr>t^v~xz|3A7>^~68s]b|[T!"v>."/^N.Q.0/nNR.>.j1rȎ>^.fqQQ..>^q|^,O'!# v ^&!^XO @&(o(^(.O..o2542&[>UTU^ŚUV]~V֡,{TgёHӢE fpºu2^1M 6oԥ-_ƜYfΝ=L9dMVAx˝8%KZ(t͘pܡ!E42̙4gXioH([BiV)iݽ^x姦=\-N1܅wD|y3H{l4dD[ AP5 `;'LR (ÏP"# ɀ)I=^rvD˺c) $H#D2I1ޛ-/4LL# P5oZ4L2dM7;"+.YsH0RK:ږ(>D[1%#Fh<\hGѭ|J;!$TSOE5U(tGW㪒CH̅,22mu M,Mem39֡;5=;` jAB %1њ~S0҈Tҫ(mjm(MuI&|+&QU_xHVV)ףUW0X.X+*McϜ8Z֡_5m[sUZ1&b&>4IDy{NU 8if _"FD-wUφt(LǶb31J5=;ّ.j!M9?%eúNjTU.vo#ި-vs?H/ozg/ku!18KEߖ;xfAn]>Uiq&u\gt{ 5G?}ݹң<9Dp oLB4ȠX71|bر6&<x2' eiA;Eo\ {^If4K~bφ7aWUmJ "G.>g;\j }%Wt!O!`a82q\ PV΄RfF08gx!0d ־tPgq͈@g&k6|FS<.Fˋ ɤM3FVhƙz(Tr& vt(C%sDf2r;!R+I.Db5 E9d CcΊlZ@ٙ?D eTRI+!2> HD&.2GԱ8A8>jhFmBbZn~~:0;S6[My pK׶I*2rJ; 2 9(^  " "x!2/ aAA*!U`gtΣ(^rf!ywE&񋐝)8 G.X0TG@ TB=u'~Z wB L?&įumRèeu'\S hu]#8 m+ysMt'lkO+'\E`oEC2gMGs,̡ݙc>p@rG9 [h$Ub|bjم!Odڣj8u)nm]f.G(B׽y/릺.ʏL@Oӏr#ۀ BP`b@`t?-[]y┇@ĕ.{K?+#Q<`/!&ؙkH&X {Ӭ >(Ճֳ Wb5ך@vj5 *:ʌA:K:[e[>3$£4-(; (,B *7ې? `2x3R.u}[Z(=;8|Y@q<( "T"ƪ@|Ҽ0I,JK#'=A$A-5psx*-A=e{!Ar 5e+k5 Nx ,S'm¥#FՋŠj#lkEb3"9z> ?¯ۀ)¯ӠG IC`?r?ҍB4T!Y6sqCF9:@>Ȁ<?+DDz8u r <"52hs'#gDi2%оl$0.|4Ub`rcn5d{zT:/éG L,c@08,2tO@ $+|():38J4O Oj--TpR%MUB3]E2G U%@D2w\x7B8Pb<=k 1Qg-D1ոZBHu)%`jOdOPQMRSMqYRS1*U@ߺ%S4b?6G]@ĉ4 ;Ơo l%>TnTA Cd %pUWobׁp(lNz#\)a4XdueظZͣ~3:=+ٱӓE1״lXl5tMOJ%zW  Z XI7/UIk[ZQ%ڻem$ZhS[&Y4[@[,TƕD,W0O/MOМ׿eX4S Gٓ-]%Fׁ܈XtAVU ,ZGN~]еE_,ݣ8hNC]]}[\إۊtĻm% UM̤]%|σ3ކ8%#X u7X76PxZ_M.ε E8J_]_`-`{=`p>;dNA{  E\ .x`[˭I\NEa6ccapEGVTFaqu ^i_ s@A&B6CFDVEfFvG~d&S%RH8=vs)f4qx-ޚ\܏b:3d(Z[\]^_`a&[FIXcn}@`cإ㚍;N<~`ڽ>6d;q&r6sFtVufvvw>pv%-ݪaatۖ.yfr^96XEÓhݓ ]YB&6F.d6QV@+Dpf Q:ٖfN[> fyFVfju.zVHKdHbظ V.bxD脺XxƘ0a=蔦뺶v@UpBHfnF%n;acJfX͆ld&K8ͮU] ( ;qIk/F hk(h&6FVfv&nnVnfyͯ>l ٱ_Lq潕^ lΆr~ϠdK&m*F^=/=SB*k7=h%e nnAun^O~УfqήooϠj&g' o1^]maJ34Lc%5kvpcUwWXp73G4?(a[ZqYo欻 ȮqdWDWyo8rBZ$-rrr/P+y\֠hhr\X1Bp> g[\]^_`auZ g`sn_u@:gP8Gjf[AW*BCg>ȃq'rEGDoqwswwrq~ttmt"tEזᤉ2p!uZ8EwUYo/9hIHH}E*N7pr' -q))BGtTw z*ډGxG 1{+b7`"F`ШkUb5hJG텩4-i;6Ԃ.&㳇(fT^ tIK l*WQPj ;<o+2 V0FDffe,}رihDb{ظ ʆ@F8!9Qp;cir.qZ)FBMe,Yk5B(c2_6c 1 d!+m6n0q}7y筝2r]D%+.(jfT]حlxJ9#U.3K7Vıo&YD_Wk0\s;lExW u|P!|euYҝ=H6[Jy)oEҭ$a8ԝ4u?Ml i)#f/d@ ^E &@RN 0GhM#1m!hr!" 3 ^Ү}d^+UNCt^X:#PUW8Y`CpAl`w]iXK Ӽ`v (AccCF6'9QO"xr Y{aZ`|J_ WЇ`? ,'7Twf@  5 !6W֊lnH)L  DcEY됇@40\C[bs]%A4J/ U98Dnu">rk1hvk _QR,f4}SdXA˂ !ґ3::& MԦ>5OdD80^Le!6koq5ݏq9s.uβ1‡ Q sAB[,#'PɵUXۯxQo HKܑ9 KM 5L~o_mBwVVy-y4 ?Ws<ыn42Σ(8_t׀L5՜Fj 69KVw91a)Zg<~uihrA XN6vE,1~6Sؕ.8DD6+*G7#P#'?,+fdcV`a%84 6l&gZ4d3%~RjDx|{z91#v81l_cO {^ݾ>/O_;a8_ئ>zjX73D-pحV1MKY{9[Ah `kYkɝ]]ۥV%흖]Wn4Y^LWlҾڟhHJ1 uAYsD^ŕ{m-1ޞUEB8A1`!!Z9\=]P_ LEP )FX9Dgg!R؉]Wԁ[ l"'vVW D=AQ 1f}CdLrL= uƙ<7 c` Av"1^Pa{B)9o!:2:;:]m_چl猟 ȋ #tLQS8bhtݍ$_,V$[\EօF-yq/ ^%@ʌYdOFr ЀvGK !7.%8#QP!1,%S6S>%TFTNeSU^%VfeV&u1aa  qX)#΄ϊ<]ԑe!$""A_H`&a fFΕfld`c&t HVf7I$trEK@F36RФ٤D0҄6Oz#`YP%njQj%oo&ppF%XrX\}_ZYJA%)^Bbb'yBMZH * bg#lfAFi 5^Ǥ̆Ĺf^&^n.R>(FN(V^(fn(v(gr:Z>Is%w^dD"nuaCTxNdy(nyz {$@DMxK[hv~4rGu hP1( )))Ʃi8_cJNgttuCf9EhF*yn -^)I&l0RD4'DNIeiln)PR^*檮r=VX ,' |? Nʐ%F,*y_Rnkh] f.>~AE^pFnwM*Pl* *%MrkЯQgs9EĆ _^_ƘxrB ѐ.ƧbƫȻ$@ʫmD'jfG^fbm.-6|%=)ѝeJ&@<ݟ%Rdנ zfNlt촾ZJb6YA_,Kl "!)g. GAxA kLi^G]zѪ:^.&b؉>,&\~Ib=HqsmCn6ܲGH.-ަ޶"̖ @xBRj2n(Mkf&7֦Af憯/x't._i* Z,cķbB:$th$n',0JLZŢpoP˸m&@o*n^F)PѦ(/ 3DJүd .v Rw}Yb+-'1"pO6pkTш0L0@Hj>]^K 0qOpN/.kL/>^qA 1q_>j6cfG2c>cF?_X&H[% fԬfT nsH6/@uGDZ31;-o߉m/3c*oFswo$|387GS8s8&[Nn(/O} rY̳r=fk)p&i1g+mt0JJ PQj1O4E)k 73 r1v4h5.nXLǴL)xN9FL5Q3Z&L@ ȉ53 >`?Gc]O@3cA$ Q0$wiҾqE5[ߩԫ&sr4d0+˯HSsY]./^"wm3S⽈?ܴc?AO΢FaIRl JTu*cu@qMphu[6o#ڝI5u 2:GMVD!cJӮKSd[wwwKvܥ||$&Fb6e^41e$}O>I= oOjHV"ϓr,l5v5¡`/v0joO8Ko/Hf 7Pw[d^'590LJ/Kus (~7bxE7D*{ۅ{'KWq`x6wfZ5}J"mk*l+r4 7tP6ZV8]ጶ>Zva5 ')d}I3kre!WӌӸw۸ k[[̎=L ej2FmS+S9w?7kGEfKvyMR/*xhClnKN sns̹>JGu$/w1HϏ`S7[wx9QWV;:wC:Ŗܹy{A@AmC+d$W=<=Ili˧D90ޥzx5fM@TvZ<ʗo2w21Ha)7+8#k 8UlX|ڂjgy'/waPKjU}*>3N}ۏF.Ku_yI(@ ,܁=:~ >ɫn_G|ƵXXItQ dzI&e@]I&ȤIÆ %W^M6, g՘=^EiVL>ÚL$-{jAOԝ:Y"UMdם[[`mdN~:ŌTłVǸ?1לEɮ!?6Ӹċӈ<$V@4|KH# 3i9\X(f{I MrAd 8c+0:K:, %\hK.ؚ+7ntn5XMYžxV'+ȯt%2-VDWnUw8B /_5 U_ּ p䁑t$#YIMܔ !Gn| HFU* AJԛ^,n_K`E\0HLlBs͎֣i~~93Mi/"ݲLpDG/8jXl) #P iC"R$|=F2,ԓ(shJ%TXW qI|CSS> ۙ"kn8̹5oGIK}:=O̺O8)y;F-|Mr(2;ғXtF)A6d{bMVnzk^z/#FkO|Qа H/"FL o/ߔ‡|(x.oPjc0  !` P ՞.,X䆴4B` Mbc["BX.oYW(Z2n6ϺR01V fO+hp$)W &O,݊0<AH QQ pԠa1˚TdGU% 0B5p'$0L"uIqL.KN.H\PЛxߒ"_,q(o<9@8g"  V o#9Jy$d@ ndð 1Z*Ў +P򐏲q:'mC?Q \V=@Vr=B0ǔ,R>k$L RnMe..NEĜhT&~¹OOBP]EK7Q}e[vc&*\yP1U*dS B̈́Ab tG{4UUU_Qd=`R2wj"T<Xg/lX۳XSk L+s,S"LMBO 4h|[tRjB)ȧ\QSi]K'5jvZpQHU_fng8 `w|Uv5:̈́, L; T-;R>( ~gRF=Tdy #VIMe+BN Eukf?_b:cguOz6DGf_/i1B[*i/tjav0j^_K75fSlRk79lxնFšcb B6ocri@į ˲^4%GYY1#!V2@+$ COy/VJIu|_>^3v8}MQՓ>~gJ/e YO*#[>ٴۏ>-:߽ke<)sJ>|> pq*DҁF!! q4$%" ڡLADIN,zs]_`HKpc۫3~_h"L/ A :0 %*I Ƈ#*2H|l02Jw{ 3̙4kڼ3Ν:լ[~ ;ٴk6(d oݶܳ5cE Is&LCП7T;w5z7܂ё%O/%ۿ'~y^RQe _O A[z pBtb.` d!F faA Y搋hd[>dBIdF5y[µ)ĄmȡxFdlЗ'Ae I{(ѹ|g_xvb O U]%WOYE -Qf([NJvJ$V~ؙ~8Bu$3]QnF+i; lKlZKbԛBF9ܔ rwЖf[aV'+h:sl:fwqzvj~Ko>)(%ĢMt(Z0NhY^oAsm UKe-_PŪhho6D8FٯLs6ߌN,=rŽĵ2K:\iv Dm;MհV+$]2HpmMh%C+,ӗ:lqiFkCuXb!6r؁qoUe'h2zꪯ:;"?CTZPRʹDN[!c^+sԮ& HM}=m_jĠJ@u Ko|1P O,A8eq&*Nn^E+$PN^"˕fd:7ЭF.+ģIpe#,PFshQHSVsxg)"i޺ Ogkы (QmP)E9zKw? Ossd PrsC2/8q eJ24I]qWBqC+ 5+&179CQ&bD @Jd)DO!O`@K ^ɺ*QcFijJ|F:*slhpJZ)@6Q[d D˛]Hhxy f{xNLل#r)LA)σ)3qJJpeCh*/(aZd CiNv2oiQ{ݡ&K(wB_nPS;붼f6963'^Ik`+%tɰ׃)NTEA{9 4jcئ/9Ð/MxkɜNٍ/X)5M/gwXc<b'v*98p`7\'7A+c⪾xGl YI{Һj#Ԅ@\=FPۛsiঢ়ӾչR7Z2t{]VE?oW {f^_7|ӑplHeh? JP.a扃H`0g`27QA)@R&m8iw&X1\# yt" %{{ƟBIlȸָj}\=TЇmH*hLo8M!ݼ_!y:Љ)MTz!ľ9H;-]Pܙ<.`c]֟}W+-Ϻ/ ̔qw-sȨ {-}I 0EɽKE^8]*"Y ;bٜխ }g< LDD}ӌvmBxzmTۻ]^ݱ TؼX!۾-FcݰR}LHB!-t$ڳjͯr !ڿh́߶ߏ|WM~=} WغUʩx̒ݽLҔݨve!b$4;}TZjR1=UD4{n=}%ŭtPC1|]ܗl,Q>Z^_Gd$xWGJg%oUWǜR繍X Bn#cii>G=Yhm\vѡS-Nȩ!˪:ܞ$ގw%~\-~L5.+Ȗ<գ+ )0\Kq3.-]#ё+}mܗ鵋z6P$?>nn_nbz,e:7_69OÝ> nHJm~'+\H } _:ꥪ0`j/+Oׂw tv?6xYaJ =Pc0ohP" V?홎SwÙo|ⓙa4_0/4nHOlK)us^b( <9(X XӌHB'K P5ШD45Q$0il< ˌ'ZȘ!͌4erNlYQI.eSQNZUYĉM=_Ϝ)tX&[2 ޤk"]%%!؆w:dw~g"p%OJte̘gСE&]iԩU漚;3԰Bc40ALawBLqr6 pK(iQPpO`Rdȓ$?L3+˶ӥw ,}J+ 4@TpALO,+ Bkh: 3ȋ/̡:L: #H?N,т;,^ѹdl |2\3H$T֖!㔛|SBi; ߀ 83 C:nrnzb;%10<4BO$::iM2O,4h >'rRL3tSN;t)0! 5ɬ %UKES,eDNzFtFp4Q$(JX!trYfu%* a;h/wԍ7 ,6*s3=˜1![…;qoOAO@ ^ /TcԡSbJ?xc;OC, M5Cp-7c1ֺRƾIVj ךs{XdeSYV5f%6r-so:mnd.!4Șm%/0/Z*\euFs;;-NAvq#|rF" Q‚ ޾\v1k m١ә[{r袍vi{ibrJ-y8uU]֭L) a0v^ܠC#>[xp}_,vr~|BM%Db&:!Cz)uē+v]f;p5KӄD ]aZ^ f&NJÈ"5F{h>DoDi/?\)DqbxEL?"2 u@mkx X'A^a΂톄^"cCCB$pH)< [lۗ";&-{&ކ~7-=$p BD)de+] -]D > f"/c7G5Fw`'G?F< Dq-yR"G ]a_ I@EL_-D8%TJR9WT%(-9'-;;B,* Ō#,SHxt&)M.M%ft)oa!:aO5z~[(eSn(S,hUzUV *gh9s-cQdRIA_-&uHZN@3{MJG Xi756զ:-'N{5z.AU;I0Rh*,ŒNBUV}xl?aXzJ!ZmXnG-@ĺsL1vi3WU%^F%M&ӧaz+Emb'9YU}_J8Jo5!26mX#US6-E ފ;zBqg\5̵s醘jlΨ+Ha+^.fM(;꥛=㋓h}P&YKΊka+"W Ψ.3<#ro  qGX]\7J'Rۼkj5cpvzǗ@ {J}ۨ"(-}iL'E*}r/el<.kuuqdj8]Kf74MMgmy35gs|@GCv\?Az[ĝk_/f[هB~IC=,@(P2;>3{@!ӕSPӷ:4#5.ͻЀ&:20{Gc+ՃvڐMr"s;| =;|B(d<77[>jS59|˰k8>̾8A>6  7 h53t?,6 "6#d$t*R)&<-'BNM; 3B 70+þʓ8?96,9F:s W 368El BDLj4?K D@-OLGu\P ڲ§::EIE3kEc+賀2F_#`1<4Dlbe;Ą46FGFD,<;p \IBp\G&>YzOGyǞRł;} CÂPP@\,H] [Hl:{)aAld8K~qF)ƪ@ i4I,GDڬ˚DrJI4<|8JLJ |8Jt렫JjHxH0n) - $<>b+D,6 KkK:8ƌ#M1h#zqI+LļND ŜUz~i}Nb6+hDm hAh5HUVu蔚; &%l)m^>g[+f %۔FSDxUyi*>3}~գg`\aM[Beڙ&j5jLFjRej ηѹӳecOY7jmI8Tg;;ql3=t\k&:kNdf^Svܺ ]E>d F%̅NfU$oMS^FltXgjg>?:k|uU:~"3f%>*WmfmgmbmMXjFk.LVcjWB}j8PAPΈo "V.X&VhI￞,6o0:%H[칃,hfq!r. , 7SK$†Z S.z;vWRqo5@^hq%XlO 0\]!ARIrYrq4P0Nk+t tQr A`.-%x>ZiV1RL?3OV-s9$6qC%\'AcFے/u@け#qpեRJ\twD `pnJvOPg0oRGmmtBsJ Vlhu_&r9$(e#@f_@tV X#lpnx)gAo76WqzGA{缗q1&$^& cgp#جO۝>yoԶw^hy2STUG횏X!:n.&k,!KPV(2&8zHz]z3~/BW(9I9¦DjtO]F`f޲OSkysUپ^󷷀]{y0Opa]Ց/]ng>kz@qnU˧-vNZ*4GyQ'N#9uJuǎ{6{ywH߇H p&J@i0p!Æ 7$ #),@TP C,QBBHlXrȅ(X s';ܙ&(P:9LGIZ gT@mV=1ԁ!}*gN|Mv-۶n+w.ݺvͫw/߾~F§Qr-4\0ilxsJ\ŕ~ܜqd&Újҙ1,{7hyƏ#O|9ΟC.}ԛ#\8W]1~ߺcfq J XqU EFZlkU:]5MGKpE Inٱ(&|r|&!}.}iiCS:=P)~DIiGG*}(RRbLΗIOa( nviB(!)!>ɨ4!)֩$Z䠎\Z"UM!+"R dfR(jJU1.JQeQbtF vTJɌ\}(}Eb`k$ncZvcc b @#5kGUjY:iFfE0ݗXDϷcc#kṵLjB*1>$ ꪕh}")bn>lq;£ZL+5,ǒǞO\K!dʶl>1vfW+'φYpZVۡ ]e(LZ2IRK)׆l?ضS|jAm'ЪErS'*+|mІd5mςmNmq=-rD>A|a~11Ĩ.B뮟"cĭ-m5Ͳpk2!S*m"Yl ֓ԕVo Dϐxr z R UƮd ꫝja>Y + %-':'>j.)RmbjHPrD)@I"p+23MC,i*<5WEcunetA5G~3r*wݪo p ~>#+06mZ>'[w/{{Pрn/j;g5!c?վx82?1'l0#,p@ɒi T0a1rxS'>[>4yeJ+YtfL3iִygN;XKER:bDžJZ iA6MCiVP-TmJ P^+NݪU(Y X6UB[V yoޑ$ 6|qbŋ7v2bsC JT8`n4  2VPH+4[ðIs&hVb%lfƃU*0̙4m,8)R֏6vThQu!Gt~|׷AZ 2h-K7R zh*8OÊ- L-"Ż]|&Rī͔Pbl4NQ dZ8 Ȱ- 2~,jA  =-t< ;?M߲>z?FuƮy 50 a*, iPŒ7*ԦRkUiepJ8.Bbנ%g,/kv9Ύu|]rQp0ds׫w?gmNR6Uh}Eh~붽裃vAN{\ ~[1KGR(?AtZ!&fhe,uKG[ωKu5xw"\n᥄lIX³1v &=Un CAŽN}O"P?!L7CQܗI\H:#π2 x@!-4Z C=:ELtIՃ5r!R)A=] %!4G?SƧ!h|eh%v8L_t0Y dU/GT(X5EIMAjָ b"7m1Ub5F94l׷bƖа>͎3&Kbr@n;%fY1A0dsFqKC9tbԂ /D-l f~#q ]b4=FS=1G#woL2HwծHI/f2@㱞RV10J9J6*įK LpL0@iI44.Nl=FOcUd>.CtPPP/48Q!ɬR dRgbSILqdBF5M.*L#eU]Vcs3V1W3eWq3uSI{sȶmDYGIY 39Y/Gz7˪ZrG[9BMgMLkZuN]Ud!ؤiTH7W aAP5IgLuuu8 4 b ѳJI5-g*"CE+:ȕ82dGkϻdߕj|@Vv% gOgÐgVol`opBpa8 WD1vI>gqv<3wk'U+V1WzLsay:^Dd^EC]smt}mm 捖Znggj7hoWhȦCĬwNBUCcUj>Ŏrr[dwwl#ly{Ee?'|)Wy}wn'T'~G~~~hQM+z+pEi$6q[w؈\_N#]{#f+k^Am7_nwn^XcXCv7S h>xW4c?V\= }-~ܬL2N3k̹gB7<9Ө j FH&.-\ {#܉3|Tɵ5/9̛SJrưƤn]"M8uJOӫ_tV^ɒbE.Le@r5] b 1buiY (bg56s]bDLZb6TT[b1i 6DQ@GEČ1G@6i|IWdFҁNu`)d^|XQ`WO5Ae1F _s΅_ ڠn!و}裐XeL⥘f馧5)_QaRtݗt%j*e*무j!fqi}`_ZqYvچ*'At6m)~+{b&UTvT"}iӫ,lIU{U~ş!{紇 Y8w|f|B.<4⻞iśj)H'L'uj&NBɦlg9 /L wDM'B\5! #C OmWC\JH΀\`Q'àHEig{qnL>a,Dnغ/\=ceDާأ&`EXF:򑵺&5|mr;_2utRҝ`XAjz%?|er) 0#IT%# `w /X[ST>|-kFv, )1)L:}HuΗ $^I-oS.N):aQr H3+|>df]I#h C-u4iXiWΎ;q5=D8: |NOK,,}KƲMB5ZnsNJ;sJfѸ[iK,7 dAQ-ZNsj4tDq(џUQ@KZ~3Z<RPLU2jؕE`Uԓ5MQɮ=uRZ(͍n*|ԵnP+&ipUkmcT:zcezf i[<( u*`\WN0Ҹ]$SZP[wZqؾ3cUe*1͸Cne|ZLh_LZ__ӊSB>|30t''YI+%Ʃ|EX/)_f}6 AsI"F U46AS&匙X6l;bC-꣫f͘δ{h y5ܝd”)mPfĆ򈭼VE#tI7W4Ml$d=Dpq26Κ >7ex2,u}kGZ~vMWPCvlbDKeW_ pw:v'].M% {G{cځk J8e}߇7|gN8Ϲw?ЇNHOҗ;B߱ŧ>uS/I rB$R%%8e}ƗsVQpNxϻKOOx؏ꐯ:=MI(,uCOă.kŞpvzu{zgOϽwOO;Vl/uͧ󧑶*A_eB/}rSֿ^K O?~ztXlGXYdfl؇:y1os}~vTzmz"8$X&x(*,؂.0284X6x8:<ȃs@i FAo]7:E%vS-t6~R~s F\؅^\؃b8dXfxhjqІnp%tHsXx؆%A؇=6\QT^Iqy\MTrEs ؉8Xx؊(q0q`X2xh|¨]E!V`}fՄUm(_,'boms` h ]X8XEЅߘ긎؎8Xx؏ܠh I`8 XXAl(Pgr(hofz׈b٨bs * h.[294Y6y8:<ٓ>@B9DYFyHq` CyMiOɔB+N%X1'Wm8r}IvVp)vp_+ْE@wzwI9YyIPYR٘A锐 VXYOńY1ci>v`Ȉgae&(y y vyFPٛ9Yyșʹٜ9q yP8iةI)iy´]ف\w(oYrw>Pd$ rys * HEP J}Zzڡ ":$Z&z(*,ڢZ(zʝ0q2Jp:8j95yv"Qv.p&Vj!i~Jk&syE@@ Z`  ` Ȁ vzxz|ڧ~%p3ZZ꣊zBJ*E\)oTXeN*f9QXJiF[ʁi  a PE@  F:ZzȚʺڬ˚:HqڭJqp zP jŠ*T!A ZZF*8WG&&gNXђVh20DP DPƠা j{(*,۲.02;4 :kp-3 ) CPHJL۴0qp /k';U(;;*˵z#Uq&}k==^~q >m-5qa~ݹ %rGfdam-)eu֤=:6ӽ%}ݺ Ez=ޅD^F~F^<п- G`EHZ\~n ncaW^g!?Ր. )F+[\YaT֯M9΍莐>^~阞难鞮g<顾벾q  DnN.r1Tí'{o9kE2sн(  FA~\Z>^~?_qp ^PS= yNܠl!ھkrְ6B^^X2?4_68:>@oJq 1[Q"F1!F3m}9>0fodjlnpr?t_vxz|~p= O`OIoMsBO_-򀞟~r%r(oyao o g?_??ڼ/o?;ӯӮ-T_Ûo1NYz:t/O?_ yG@,B "<8D-^ĘQF=~RH%MDRJ-AZ 5mҤ 3M#b*3'O ;X @'Pl> ;&U:"SJ.}BiW Z.%YevW\>[h›W^}X`… FXbƍ?9p(ʕ-_͚9WKҥMFZj֭]_sRAIPb}*Smڼm8O‘CUwmMYsǭ;xsCG^z~|o|~Çk$@D0A?Mn6͂$ʪr&;"Ú-Dq oo1GwG2H!$H#D2I%dI'2J)q\J+2K-l&P +0 k*?,."QFǂ.EXnlShb d?BE4>E)QG4QC#>2SM7SO!&/ *LnRͬ M8|My񪧚;1-;smVZ-֫KPB'4|/%eZd6K4[m[773y;ӷWՌ5O=[q[kޭ`7FaLAZj-YfNZo'b90\s:ůV%u-uiMw֬WW~E_ tR9hyhIӋfiS8 ӊ"YlA j(qŗm #0JybW p6`Vgi&p(:&ʬs17M횪%X[Vn^|Sl 8#3ֶYkxiVnuoӻon܏>x)V-ƙ cߔv{B tf'# Ɉ]Yu@ڽׇwO#߱>߲/XżuM(z .zS!ҙ 3`'>,gb7N']Q/a ]?PFVeyV6}npA :o|o3N#0oIE,푘 8F2P>ÐiID4HDj|I28Dnn] Ed$DdydHF/i.,c$%9Id)ap!uMo4b3έ̈Dk{]IH$eK󴐒$-IS\JOP,O(b#X'qjY,9IBg:չNvӝ <㙊Sl6r`ӟ/&8f5r3g,u,[Hk<po)HN @iJURR/e` St%++kvVT^jey/yaFP@`,메'p|dT5٥Muci1%~B+*SRsyL]5#\C*շ: 'apzLı.2#Ic!RQEX*>-<:EoΈXr6aW:qsiCXKVmmj Rsե#|H:Xl3sS'a܊DW*Qu-]h׹ew2'm*$;c_ j0 ੄cTtVQ3 p{`vqot*IF@=Sf--ja !qHL\T{/g%a$HSX_"a+Q#2ќc倽S`\V{Wm♋[2p8LVDpf,O qsw_ʢǞPlPW˗tg`baUM(65=N;,.໎ن &AL`Ukֶ^us]rc2Fv%>(#x/v*i˶{^<vT^Fn[fˣONUWuMXZ+"HA2g@dV85<zֿe&==kiN!љ}Žo\>0:V!<y=:466;jՒ4 1B"DA$|$%s24u t-.<p>ȓ2KdBa3Z<6ůCPjƵ @ 2A=e-fi!`/ @؀Ax@B@!E!IB9Fn櫎M'-$Gy1É@4 jBë®zt{:9ǪaH^$tӢ6cHB4F!s2ar7|-̢?_hIXdDnDodu%ʬ Q=+e2JYѡhQ`?9BQ @\@:,!E5K&KtӏfN˖dS0SlV0d5m*S"ESB`Svͫ PD=T hWkѹ3pМ{>T4$0ԉԎP KC UCUSlՓ%=;mz_KMPcTVsĺLRhWO78RoVFFRwuӒDV*U(eZsWZtmׯMyDwE 8 [=Є-܊J5r$h Дa}D#UX|=- ?ۣayQ`%VMR $'geVRilgW0%WZ%u^w I}w-׵\zͲ|e% [%ԼM[USP\XؒyUuG$8k5ǭ͡}<#ͽ mY%;e@3]U% ;=j]XKK@AHIXvUV7FuV45I0=5%US7X/7haUa=m޵mI Hf5۲b뵈ʲ P{ހ+^: TM߿u U%0μ̥5Kc! Mb>Ų{Zó-,ƙk "&-|#)AVO^S,NaBXXZUNS<ҸH]ָZ&!]XeeSj\Nt%m[ &`Pa]T%X؉0ۅ:5Aa=wL39V6X]ҕ= 9_ўuJ]roh'TdV+fhf f=ʨt ;pcX jags=AyiġfYgZU}&\dm䲬QI0JM`K /ɯ}H(fjU %_>rc.cX+$UlGU܍0jit Yzg>~Ϫlg[gF]iCF%t91l} nm-T%Pmb,XhVPj if y(T+piGʂ,xFff/dQ]CECF6Ep#VYH+^T`4Lmy)8%>OPTnMb Ji,fc7L-U 8vC`g3fFƴ lkmLm۶ﵖ*H)%Мߞ7Xӱ>ppgp{<n rnidrlKp&V$DFoU'cqIW)`P r x45prF wXrSY'7(gtOrU6j-oWoyvXkcqyNυY7MW zxv͋r/snoop; GWgwׇؗ٧7}ԧhxfn(|u/+ 7?c>/_vlxi1~:Ap{JKǁ9l=\ {(@ „0pĈ'v`Ѣ% .r#Ȑt2EGI /-X#˖c| @%J b*m)ԨF4$$ÜIs&L̥r<0gJmϖrҭk.޼z/.역EZ Vk-he&țٴ|Eess'KNY#O"=Hv'qq}Ǡ‡/n8+TĎ4pmȒ9N˘3={Xz> OxԣwYv9v$%RBd+Ft*X*+vv0yXzT̢4Tv~gAi!bd /+)遛2vz$jf;zѩR,G4傳 [J C{|2 =R.UJb^~)^jYYUS޶Q{W;J6&ւj5]{ |GJ)WpgSĩf1G >8EHO>P>s.{TV:dG1n&VJsst9 [ O2\ʐbmOG28A!PCRku<%" fǑ(z1QLb4,{,"/|$()Fq}VL_E*rQy? `Ɉ{c4*A؀{fmta8İc9nJؒJx CH *MuY[@@] c_-$(C)J (r QfxZc:à٪zCa%ȝmB8&6Q"Hʃ5e9BX i G"6E sFL:qk6?;)&lDDx&A2q=Yy%a!% `HT$"Ki1$`IΎ#*o5&=)J.`̔1ltǕs%wZp'%AWS^1!rL!9B թN5 &V́8gG'sĎ xN`j܀Z (\] Sh=ZB%u (ơ `o(GCZMR]J3ͮ#XbZTma,uCcIPwGѨBYR"H:wRA ch zfUejq Fbu \uxr$}YWvky<ZǠ T[X rO:tTlH(2g=ꡬ6D4Mڜ^de-p7-jJ.U!q@"D`APb ʥ?& EV]ua(tj#p9p91!^# Zh@>hc6`hlI`~3-aA3G2, {n~T--ε,lO8i1Bzk8ȸ5.npL1 a @O W=Y ֲjzf{H27MA$%Q_Š"gt;m:w|&iӭufЋ)ZD֖ͻHP-˝J"ȵĜXÛmi-bF81j̚?"$_l(zF_c}k\ 7n≑|Z l張Ff;)TXSZ&MxnOf?{[!xl.QC# NlNm}pB,ޭ8D!28/j%@#g - ȶ]q#ԹρMۓTw-IL s/c^LHJfq1>]yB;#%;ڳubYhZioMz i D` e a^ 0W-pp^X GȀ} D|+] {TPםTU{QZTm&uhL=jG4T{زy/tµ8@o9^ @ZGB ] \E Zjѹ x$ a9 VP6DJu҂)A \b8,F)x"OEYy  ja)n T@Z i^SpApaQ9e"L}$e/]K% \S$^0>&)]*b?d\d@'@,:$FNJ-Mh/HH(d1eψV3zC\6!rr˥#qc㐕b`ph`pp8i@"^wm#($@>W?HQP@VXyB)ffC@H\d?DE`ʅ*܍/6#eT$$ݬd}aQ$d4 #\)4Z@j$@A%X R9œ #ٜXQQ a%͕breciJeC@PaQ/H)]a@@b+z^"&yƧ%"bvDZ.fj~"AJV1ffAAAB@5Mj 叉\CP~m6Wn*%:f !v tbqbrތ$==' %"AȍeFzq~fO*t%뱚X #K#&De,_"RR%(Ŧ%j`'_ED0_ &*MRc6fK\h)1-%Ū4.<X2ԍ V ~leY&e]e۾D+CLdlFfP䬝EpfY l2~Iw,liK:lLB^jSjv,X+uXXnO~zP-zcFPd-13q1qvͱ;°H/kH*߰ܮ!lWx;R#HlT%tl3a}J'ߒ]rG*e+{-,,2-ǜ>.O.Ȭ^s*eKR2A43[bqCHPs<5[V67ㅐtفU`q3)ii;9?8 buvQ[D)Llvx1sč2kB9X4NC؂FƆĵ 9_/k?xLG9lYtOlC@Z湁;yr-א s1)Q*ɲbslHLwExp}g %n-EFN3`B luY/qn:oD軃U8W4cKwg9 -3OOzpX!`g؎adմ9i][:k+Hxw[D{%jk;V L4m;zz:sJ |'/8(_/)_có_8?4f|oګZBJ oZǞi<=7}SvtzD{c UDWV[ QW;n;Z?+kC|֪ +luE|}o@<\ =yE`BtrA-vo`=Hk bSk̟G h/t΋ b:Kӷ'ZaG?27yS:@X@`T"pHh).c%JF&*49aΤ9dʓ5,)m4hѢ|l`iӦwO XBƸ;1_1"_@6Zn6|yѧW}{Ǘ?~};|v*sHDh5L∢'hh4)*("# ɨjd2RJ CX*:KǹY@.Ri HaR)R0{,X$j34PL(B&,ͣۢ@H5J6ns:`#mc9r':nڮ;E#/(D1“-cXmYSHh,]]: k9951+cl ,l 趵ܯHR ??U RX`Ph"2Nq,$XJB A4%''Oc S:r'capT&9 SMqSY2x=4 4 TLh2iLgrL[jX'I )i|Q@5^JA@ DH ĕ3 "UdI#JGxp7<,VTT0@>MuYn)9ӅUâd br*kJIVU-rUls]턋%q$ 1-sˇ-m}hP3:+E I>N"0Q1y,h XzW6aeYNw˄h,iQK4QJlqM<1rӷ5rQ>8d܊]nWBݭ+xs4U ބtiq_(v PQ(ybi`-o˙u.*:%CQiT k`U31 VNֆ9vE*ݸxE+\GĻ4_(" c  gH٣%'S~JW;fkYZ*Ӏԕ9P+ ˌ&5az:I=u}AO7p (4 vu\D.\t^f5\m;XӚ7 Zp%A|}Td DГ`l<1TfcQ%rTj1u-py;s%"9v9Ճo]apU-< u_gd5.UK87SLg(_)ۛ9ku3l_⛕@H Ɍ!==JK81,Nzя<_uČoj)'7ϞΜuOz$6Ww?Ÿנa~+_VWw6n,t71W5=!:/SwK.x `|f/5\{l+Vk,NxLŌ/Kbfú b$,P  ٜO*3p+ަ6/7LKPcM u:TPMtpi-R̀",^تF1L"zzoѮxO@~| $3j@ blp2ÐIʐo. 9co$J j>'%X0= J(egcb^-x0%q|Pz)'bD.`϶0MoMMPAFdX6(ϲpϺ p F g3( Ldo3M֌5Crd1&1Q*ѧ.Dж, e"BpDj mEm ¹kh Ӫ pPzj 3%nj%$b~w&oK/q^*"1q&i1Α!ґ 1y(p 1YC&ZQ^er*R* *1**Op6cd,!")#gWL Dr"ӌLV7L%Lr&1y&VYZ?Qq ]z3x \5aH+6qS RZ.`38+Ґ B K-Rj-12 -'# O/$7F9N970]%Q1aR 2s>GvlzΔN⠍VPrYS4"4æ@+*5O #B +j C5 `7{3~SJ J8e`-":@.(7J"S7t>$I4TnR@ !.s45j@?TAMAB)GA)BcQB"[0 NC.žb7E}0ƀ"}V.D8s"h@ flLEWt,4ٮ Q4ӼnGE$Wp< LHnBJeIe2JmV#1 Rh?G@K-KK@=);M!DMMȋF + t[@J@+`%\ CF+ETQ_ ,P ,g D DSc4S$#SsTTGg$+^s51]]4 ]]ui5,٪__N;y4eok1!/}/4nU_(HaʖVnwzd'?]X i()e`xűT pqTq#E*"gbg)N+b"nbIJ-R5Kܵtqvav$t4ww+wxHxғ\ԓ%ѯmzUztwduhp@LfwffƋbdFjl ~II/$nJ7HXP"6׀Y]]RXFo"#We;qt~W&>'6XɶlMC3XvTmʞ=ncWxo`8oY&mXtdxpvEطMZE~x[hhӂ\\ۅ]LD^XxQ.? kwl#4Xųa#~Fep%-$lS yӐU允KenYN|p_v6j)!l&r 蹞ym/y7Y/_XrQ#Жgvّ.YoNFT֘#F{K=8@U2sF!b'h{JYFjגy23(6yZG + Oۅ}s'5/ڕW9oDxQϡ#z'q0:l<@Ej5Om/m7W峥4IVMXTeK#x zM7ZfBТ6 @;7nHg}Jێ" a9i[7xXXWK=W aX:x<<-s/:{?k춰F',f{"ԱeuO(X_ni6s7=-H"ܩ)}:()cz#؀@;jMTң9wmi5Y|[&p(bmZ˛ Y {6ܶR}h izĬ֌_k4ˑ$ [?B)ٕHųm \Z @2ι{| p8\4mϙ>E!~ɷ + i;‰[>rMqtk&N>阣/YcxQN\edy#rM$d|1y5Ǐ|W}O5ިh%>()5)H˓.'b<\<@Xx%>g>k~u^|A? ?O㎞y5y1RpQń-U3_??#-%o4 ~}W< >#Zc~ny <0… :|1ĉ+B#9fŒ4K\t!ЂG[Z!вȌL3`0 刌3cXǣA3mhFFN\zg_˚5{l} 7ܹtڽڼr 9{% %+(@mZC eHQCdBPb#01Z uS$@LAL'Jz?H2WZzGQ\kXԫ[=ܻ{ޢʌ;"Mh?Wem"&MOcjo}ǵtZPErTL}XNUZ|]an8^^EcbIFYFcYhV UݸR>HAfp鶐HJ@Jq @9GCҍ^bIfff=Ryiɇ MGTh4SY5U7IdA^iza[xb&Doً&BT9j@f@H&y }@MfmV.fKQE nm~ .uͺxr$'Ж_i@kF+FkA O,kn>()ri?z i *:6`fYȦ! OȾVl"$A*4lk٬mni%eJ/tN?-^J )$uA3/20 fN?X*zcHY*V&J0~-2kL:PhVlC9aX͙jU'B{;gfKYo_ o3hLd=Laxwi~7Aj ?n㍇<2T%walm.zJxBGN 5rl{sƓve)k۠ӻp$,!ѪEdxʕtD%OjM-'dz2Z}$u=[6>oLKOe p w@L2UcXT,ҐF$U,GNyiMPp)T@(1$D8 dvFLD*ri+e/אx5 a^Cָ1`W~ H/[_Y>WE}$+1L׾qVeи#{\cgQü$,?㳂&;}J!#ωts"|S W(I (a&Gȓ2JN OJ$VrLe^h [($ _$s=*IC5tGes2k`ZؽpvV;BΜtlgxP=6 [Pzm͈*ЮX\CQH#E铿/&[DCn"trR <QҞtC`M˙-*v՝O&%2jK4IPs((\Qu="Bډvu ]JT4+kЊѪ~z#Ԯ`^SM 4--K-: $RnzjwcUTL.a1;(6cSiU2eF*ZwSOH+fC.AYkKt8M\.)Hڒi@J yd`/ΙV2gwOw绐x9Z#a6ҦrmoV7ݯw)ؚ%34ow>C:&< !p`x#bU 8˙RKaɒUޞ.5ǝex|R/VQ[#K"%T#XgVimx00<ٹnfk)sm+z#>B+%u^=`0Cfe' n'& L6ݘ~k-i1QTj~Zu8LaAl,4_ نus +|,u좞᭳lKd&@Ѿ#W=-~]p.J.XuO3=Gyhl!xBVa4?ou=]/|Tipj 0q}0wGhrF>K}-+K˿˜d1ox P-8g j |]Mwݪk~=ӳL~C *^.裰B~ԽC}摛2`!w&`*b^) B/30 Sp]/wa?cuc`1ɞ >}*z7{"viii-2|W|~Ge7g9^pUmls7GjC}6f@%1yk&-v]k14o??uR?\g^7lMcGho{hI5rPrHdG\qqw#>dҀ'jw-QAAm`R$+G vh(%!Wat&xHNR6備'BFbR:{lc{"rYChWEzTfV6vfvwQxdS`[X/R9JVCzp8Fwovooh}"xlp$wU.O!~QG~&~7B=AhgCwJhC[FjMZ\_{i1b\n7bq'sHr-1A G ApHa㴌}(uЈN(YȍAzZ_ ^`F{f{Os'Cha؅v#aji%x\oѐV.ŨfDʡ-h/]6(ys*MsQƷrzEv"G$ҋVQtcdV[Pgɚ vR'qYLuh^8$^gZNm~ɗ}t"蓼1i4aט™||y[x5KodP91ywNw|~ؚiX̦yRԦqp>th&G n "QɓEO"#0R[V6O)(J@Va )KGԥji% eDѹE//Me5{wO Cttﺋ4G++)ڑBZ˝Kkbʄ*ۗ${C8ꆊ Z`6l@A<7"qoūǫ6J GKN;p+R#'lؖʹOJ" DcۭZ{ιi;j֏R%ڦ5=+HLٳ˻u4  GJcO%;(&Ÿ KaJ`pW,d{??D6K ;=(j,A3~͋\Q*6*T/V-R;o$0#c{] sl7.\+4܀6,`y|q`{C|l<Y{F[L] I>3ŗ{T^Ofesu :~,'`g4YB'Ҭ(\o 1vi k<`徧>\Bɨhh(GϺW̞E%<hY߄5><@zDNF^+gZ Ƶekhhrn=gtt%H橎~}q0.2ێ Dr琓ў8\膮{n N֝/RN[&fݭ\nȻW)Skh~O ~ִۂۛ&^ ?R>C^NSɾNOA8aRe]=@[.4#cI bkn!4a5}ރ>hW/Ab^ep`C>^շc.Dż,1/}"X.5Xx3+OLAxǗeC㿎.þt_SiYi HGXϯƙ\ A\Y?-$_<&|͈=(1i }2¾<+">%RQy*K*ΜqY3gN֖&Tqڰ}Oc"2,W(|7ߛk+$ny $X`A C,LhAJLD PxqH 6vTGi:&EPic7kVD# PD4OPb%.FMTD}-VŠOmDkAԆ|[]y_&\aĉߺ,Ű& 0iX ϞXfQ7ĢSW\-5j -ҸhĈ;ɝ+ܸ;.gsѥOr ;s f 9#TrKDK5TTSUuUVrIƊZj+ !ѣh48#37I\JEMJ- UƻHmb3xcY}1 [uUN;{4b&#dT'f-@H!34c)aaEPpoI\xF4q@@fG],[` J+u^S>`ZZ(ډ"$l| QNm{ߨF`St(9sU}{.Q|lDtc2&!AcMvV""G$MvIQ*%:V ̕d HERƬb!hHzW soLI&MNЛGTd᧿p vS R*!I=jgY*D;gBWFLIUO;_a/飌DYUT`%Yp /SʘWFW+2 E%D[a͚JMysBb,kDfVEl}{-U SZy|)l;X&ome7},%q'Z](S/2]XĪ1;5֒Y+mgb+[6|&Ls=##n&$7u}{dI7!RjjPk6]4f )(mhrDrrfaD7b8YΈ)1Iz@.~fGb\`^p tL%;9AH"YҼ+S~%zFY,d|eS2mBR*5˾ͨmk&\Vsu}:U2 #Lo5 MC7;qLݑ!Cȓs@+ '5xO+*-M/it#T*,fȄ1t ~pۺ-28xPOӉ:?3yzeĶ}rH*y!%OʝiZ~vV%l-$ʼ[X8o1+"Mڕ pG] ?1|R=+/NMלN4{;:ZC59oG'IM_6N[&lM؜2`)[&3\{7K])bc{NqxjvN9wձ4i仛GO>ĵ?u+ =_}W4:-4ϴ~Lk]y_ӲA|soYήA^gahgs w{I昻/9(,,S@;0/s>ċ>{0ȻZەè]?LA!?$i8Ⱥ19f?3hb?6FG?L1Q9&cL)9A9 @US I@;YN*l:<|C8lTx' 4gq6i3(1@k=@%,IĎk'(x*~, ۪ +.z+3C:(k.8E_L9d:;̰ɱneĭCiZ? l#D$DD'&@ 9ш:Gr$;,BBC @kU@2dV0"3"͙\2:_LH\9a3eO0EV pBMOg5M_QDiXF%RGuKHVcBsyҩ! LW ՏtBT}CzȉIJ4XUHYÑv Os=QDXyV+R$I%+٩/tDR1}%O ʞJ/ zE{M5XQkJl9=^ZU]YX s؛ڎ@Ѱ-g=ͲԎFT$K۩z$ ӚB\D6XP\MLX̧\MmΫ%d?܏4T] IR}KF[Aƪ {XX0ZE^(ťr\6U7l^ʍV__ ][+ m:ۏ5H-_Jsn;p]Sʠ$PA_|P4,@>Q^n`'޼`a^ɡ`>=ef yͩ =$_/]ЌWFWc(R=S{8i|$3C5>:]'~d^Z 1)gCѿ/&0ɴ+=cJ<_Ldc(7'%P@A\d#{A'BZ=4Kj3de5I+*~c_eb*;OmMTFcUG6^Weᚠ孓fM8Ǭ 06Jeh8kffºdMf։Rl\o6epJ&tf%p9Xn_k vԽ "l6]c{#Ч~5}NdEVF\Gh+Ʈ.hnU,-]PԈ؉p/RnG<Œ$gND#&ug}ڝ~գ<ɷnL$Oިi+ NdPΣ|$]]oN]V'.Yt>kyLqVՐEEE~4Ψomm] hmL&aYft5w R#.kN@"V" q1^Uqmq6&v&Nghd$ rRhVrtpoN(ǐ"|W%"6Hk@jw >yyzz$7'8Y$ǩ|,N媰x"~KNN1`3 -}9Tweuڸ{Ja{Bej"uOb$o|/7zRz,MgY N}zy`g֟>0w}oO7ꠤ6Pa?~e &O˖._Œ)s&͚6osΙ~%B JT #S2X(Q ),h@^biZ"1>B)Elx!ZbT ^iE7L0}=AOppG?-z4ҦONz5֮_Î-{6͐2֌/c [3Ќj*lBuh-e@P;;_hP"IOQeÏOxhJ7VTiUUBYX5^sL1gA KDYef֗d{ PdhXc1]dŵe1Zg$CYG"E Mdaaoť\YwbF-8E[".t y%Y{٧'}yvMD5 UuQ $e&`SQx UЅ]"DTJ d?C2FdhC.-#3dr.][OK*gfdo~R7_`,C g0Yzi mu כܔn*/+s3!tCŠFlѧꫳ~tMkg\ Fr\{vSZwu!.Bjv +6|ߝX] ivBjU;Zr_$F~fo8J1gaBP6M“;J.85jh5xkBim#֣=0.{4a) 1Uw0!J7;plr -P1qߪw/ZUo0hL71rdೞd3H8l݇820{N GoNbH[蕶Fo5uhIU'>TOQw(ȈbBXD9Z"?iX *LexgX'efcǘ53n#3g"P<# `9Ȅ\)45E#TdB%Izz'&>E)R6cL6V"Hf-h5Y (L+sEdg)IKjRgUFJYmC('+Y`& ͩS0KB5$#=xʓJW&W7B%BD"O)K_AB*bR cW-+%EyE6! u~Kt"=)_gJS3͖G>ΏS Xq]Iu6wH} Rmn_S|6}8n+ZEuwGM-osg[f#ᴚ+GMHrLs%?T‰[DP2^Íw㈶Iɭ<T @NF dڼ]YСa/*^`b]m!JV"ġI$a,$E!5 9 '( ] ]ͧUZYd,:I~MO vf,0d@&0b+%[!b)"E#Q"6PFCJ~-J рZZAY৐b=EFEѣL`^@ P A!B ˜Fw9d3B3."X#bAFG% }MIFJ8 IJZ@K~ sAO@ʠ.`NaO߅b?rea&k`qR%ݑ2$TZ_A\c95rehy%K%H\ Ht#(qW!Jj[O\  ڣ]E>Vdfa:sF0~G1R"+Jfgf:]Qfp&)_uhR}xd}ϨЧHIkJYSmFmv hnac!^%Erne tZVQ uVu*e[2Av';.NSʼn矑UVVFb{J{GD (EIlgvLQeco#g-h5藝tP#sR(r)J$xcb'EPG1hZnJcEf%$b$֨6~A&Z?RÈU㥉di~au &2:]Ҥ \Bɋa)r f_c*Q&&2&Qd[ EQQ U՝^Ƨ-D k)jZN_bM&׭pf ,jF-ߨN(/Vh+0 ҘcI̪v*j*(G)EE'{F|*DL&Cz⣾Q݈^&^@Lʺ#akk1ƈix]'%fƞ(N PQlF4D5 &,=U~ ۷c˙"ƎU.2i伣`[!$r.'v5mli^,~hKRrgw쿶JAj⩰6m=mi힟*6 (:ʱ%:#N(vo> d*NrjE-fni ¬ۺ-jE3k ik2"+(gH*fT^-j~ bf/&Ѯ\ZZ nD"O٩5./ :'g}B+&NAL콕h)n.m_<)nN"`)-+pjH q_1R Vօ0h"p*Qfʦ7}[段vI\TZǺ),Pi/qb馮p2Z KW '%-n޵G(gy1&3ڱ.p] 7$ǥoٚmAĨ^b+-:7fP${'O*J¨/2i.qd'E9)\AnNז!+axAa/})3h++W,/Uz/'.00*2V33K`)#r*؊!7ۄ+8w*˖sH79pa ;,O1/f"NDp>#y14= t &4B Bt5JE? ct'on䈳tW?m 3IW+3=rtqnMr350Ϙo{SӴ4}yyo)N~%̀EܒIq,{ךּz#ycGJ6g\o@B\NjD{͖{=lb{lv똜綾Cno]UVtId~EoG¯4X4+%oqVhJKƉ\d(gɓ}xEoKʋQ "Y{9GһЩKL3N78W(5Oø~ ^ $7F7cORX7ksr-v}qr؋$k+dt N0,\AL9ޛos5@ITФZN%c٦m& f^1 ȟMhM?YjLR:ܖ`mo /ҸG;앦<*4m^UȢX#n|/S[7EW֧_)oؒvV@_vt)X⨮I;M uvQCTwӮ'ɼ< mYAJb/DWC@t!}2LǝYu_.#.DElqI 4ɨ?ɩq;rt4Q1P ,4*H,4"HGfh Wv&D_l[c$KDSy$Y|E "$F!Q3WB=-'Gm>dҼLU$&&HeC2ԨzYpH0WƯݝ'(qEGU\>YB5%hP֝# WXƁ"HD3ۭ!cJDz%R[RS*I!EJ!;: וJvsJ>$^* 3 E/U?_9h,q/pW#TقC֑_g & /#S"),\ ZN񩰻o]YfF䍑H+Xt\y8H͕BlE<7a[lmh88Iܖ3H#wرdž<6G3n;=w%d]Wޯ,9#S61Y1/N jȧeI/\sc/|~e=0Rcs oamK.CFn䲨҄7\5E Ovveʁf;%TbHb¤o! VnN*JN&)~܏{c^(ADdKjL0ns {J yDi6h`Lj+p$F0q-2z\m"^D>-}Q-UqDX<&-@ !j !m0mud ,"bLCUp`l"d4Mo0nF)R/- m ɶǠP & Q1ϴL )@d1#BoP2 /(  b46;Q#7/Q#ʇŶqq2 {&E!R?1HͽNAKs Y#b\<% 2Enk h %7"O#,#&  wN N/+ Yhr& .ﰄ Q(٭(o(e1^B =)sy!!2"OR,,;3?1$1[5;L1/RT/kԈR%FrD8RR'2fE2@( Aί?M23;G$*M3.5=b=g&k6&/w,R  LƄ $j8[&QS=OӦK:c0QP: dbC;s,Ǔ45Jҿr>=. 3&WT>>S>2Mp?j\:PGe dD9Aё***T.td#9Ct#?t44GS%tۂ-QEO&3F7'ed#,GH]lHP!+BABEJ;KRq,'D$EDJBTLה L˴ZI iMmFIkNJ'OkO xP,I' rFQ1J#YqRi$$s!b5=tEDWUT%_ q1U-mUU]uT C$j$nu-IOJž4 '@55Cup`YAL3U!$W= IU[e}\0NR] 8]5դpW'U_͌_Wi[{5YV'6`vQZ5P$Lq~%c$RG[T5&?րhd J61qBbP5u!obC/RC h,D qi%M?sqi5jPSk%dkkK sly Wimu9-fBnnӮyL YBY;vmA#5O*,+5QT;[55"7&U/76]7hs?)mIeT1)PhwFpgǂoo}lvٖZcdxi_S^nxEyC zsSz wMTBE {QrV-+X'4+:i*pgv vWk#wIf(~ VjUj 7\9v\=vq2s#4X1\^)-#tal3huxJX #tﷅgbijmjG'ks>wz؇mSiSVo^X'Ƭ u(/>g LISqxM"-bgMaԍ JzUA$6xT,`wfm*kאNoAQ),y9pbHJ`9ɸuK6RG XNOGY%9pіTIY|mS /}C8‚vUl@Dwvt?^$OMK9ɰyqjUqj0YK.VWuy$}G+'|VS2 ;8- .3fZSה66:6 zSFyء_$W1C%p2"W-7Aܪ^_ >4fс;sM7'М}[ۢly&!_%ؽ2d~{˥^'`7Dܒ_-ZSK=q럦i>qַ-XPgu<.iW_BWaĻ~g\}k|)W| 6c-FF #\H 3fe? C9ɓ(S\ɲ˗0c$%͛8iJɳO5 = l҂6*"!RgaΠktSC9PXIq˷߿ LÈ #kN""FN.ѤF7.FP}j\^{veͻ7̜6qL؝S_^ݳ5f8 Eю>W5܌Arξ˟Ob?Nۀp'wQ 6K)(a]4ݵfv衇( Q"8$(;}$Yh<@GDhmEF)%AcIW\v;N)|LfN %pƙ])t|jHַKɄ6:WaBj饘fJijvjj4(Hx꫰:ةi0꫃^k,8V[ܱj*v-O~ۡjn{Ѷ o}߹*z 0n'% 7?XqopwEqqLm,ir sH/l3_*߬sH2\DJiH'}JJsTWU;3V?IABL Xp@@@ 0P! "`bń,ȱG:&p8ɗ* S`+r2d΍$RigBa2(0 !,AE"22>?I# GHSrrr&&2))5곴++700?I GHS&&2))5곴++7#00?I GHS&&2))5곴++700`2X`Ύ @PIA ,`ѤHhP A $@A 0\!>,VD 22>?I GHS&&2))5#곴++700__Z~뷹nzG?.)-o~/'~'by?zj,k3ߘ?3'z.o?wĕYYfӷ/+oofY&s׽uyk$E<m羵WtZr-%6jyK|]fn:/VZ-'voo|_SE??ǾїRlR|FV3VbMl=d,Bmzoa ӲuIX|byoKx_?>^Ї?apd_)-,ɚ7, ~NKvP]ɞPkV{uXj-,Y&HdUz߽P/|g5ad/9-ٕB٦%{bo]T[[\eȢ@G察7h~&㵯}~#R*ٗgk{捳0W6/مB=e.G[_W쩕],t['-g_@JBq׼qFj%R(s_6+h+8ے].]LJS{˥•}u{ݎ]v=)#5)Rq_*MO%{o]|)/K`;ZvZna+RN|{mΝ;7NC/Sʪ/ɽu%{o]y)>UmJv-RJOd+^tAhdmX,ϒ.G.G[_jW)5Bp ڷa.JoK%D].ٝkzeC??hkD4JW6xp7lsr {H_qHb cN!7+d{oX'w{_/]%{og-[Q,ے4fdע)%ݶWzBoS8.]঒*$^% !%ċ)%o?4n֋c!n[dnL\ٍ"0ٝ{K=6J5JkE0Wz. EJ2 aE%R()ka]It:`JEJݖ#EV䚿ل+YHHJ&e!^DtuI .C" HRa=z)&  ⢀TbPEnY ' 9,az1aHW\?.E%R(}(٫`]1e1. ԊMt/S85J_?[ߪ1 ^*"ĈbbĀ2ip%{"7Qk:toU'C28aHpEf1aHчZ>Ϲb"c70WvIQb+dödW^ eKvq2ʘurw)ㅔM--/^{ߐ Wgbhy淤iZ% *& )SgK36╥~]Q22%{oeɮ[VjW-/2 q%O&!%{mU0c%RS(ۮdO驖>+v;Z.33Yo,e W0dO-)013V5Jdv^[VjW-/ٝ2{•?q2Jܚ~1!c(W=fJvզPEɞ.k|Jz8t ^R0dϰ-)[2F]UiVKvPfdOiv%Nin J] )NٖJCKvyɒ])*u%{9oe8]4wUf,^7i,-\ٚ!%>5%S(3R'Krn*h G+$};2 {{V Z_̀aHA%aŽt0pC3b]Ad 6bˆJ 6 nLmq@j5 un.7th߄L^(-Xl,.ft{"*-Xl$a=0L8jZwI~NoT~hӁOz H#3">HC$Z_taePlD 0|47N4@G+'z駟~` $<aO} @ }'|0$Ȅs# 0y >FX ̙3~@He$ >h NXYY9xT}Iɓ'񵵵TdsiiI 3% w"]~(蓉u8k 2ޱpc2(c&]0v$ Հ$6Z&mS+' ][o5~dΝ\[oY%0wǨz㚺^jLȷ*]q2^Qe<8lt0x teSB/ıcǎ='hBԲ[cis#=w Ž Km+]йXZZ.&_?o/\p?4澗=I=&M Yy^ިRIZX_͊!gR fV%QNL0oܒ^)㖹 w:78>`M]/6نG^ߣَ*¯ֈg"lED CHXZZ:vK*y~Vб-3ipVVV:t%^`HN af G#a0@H}$ x? g s{$@) "a(IhC0d?@I+++Ò61g GCL0N<Ǐ]"KKKaY^T]>fȹ< $ Ζ$ oұno嵪(g[ED]qI!b'E0*7xu]i>fvBr.5 !!?a]❻TO=XETcalJ%ͫ6/f4a%7AEP2HН(?z]pP}[!j,,~p*Ì& iO}0`0Ғtzͅ 8j"YcuAbBbD0TZإ:ck .K֟d4^ $ N)aeԄ~K"bo2ya us*D YDjiJ"lwZ<69' sWwt{}j@ƌHOe{ 9A2dw\,!ݩ'^Q tرUTdBm$OBVH ꮟw9Ҫch s|_WT|ENƏ~60CiIg/0 cےs٨7˗/0;$ lw0H)9KY;ХKH~ߟ? ؐgC=6ߢQÐ裏)oyyskqlJ>^dﰤ2vH:aH2wuy;oVo+_reXR''O߿kkkW-ҒtAy$ 0^~{W}7㧯յؙs{悄?y.,r q}mllWdtm$ 0$\yX_'_n+g?p fR-'#NݽcF7@> CKW ŕ'N^~WVju#kEj3a?~rcǎu+I!a@!c{7^-?$GN\uL\[[`uuСC~BH!a@qʵ^e?[\(7/gRm&;ի\r;2ݶ۽5m]cƞ)v^K-.۰ln 0t¸/_es$yݸzz:yRjYjv>l?H;>MKӀe52H:alt¥+ү<~WW?٧7=NJ3zdRm&KbB rv^WX 깖Rcz2{ @'xIseUR+=rF*9{g\MqEj3a,//忧]Häza}K/xr|u}q/\0-N"K0ҒtpМܹ Kg/\.aHw:l,rpqKz+/->G&86LJuv{"%0^ /Rn#7/nT CHXZZ:vK*y~6B>$ ϜbkwMwR]% lw$ 0Μ~ߝ{Vi.K0PF> '_JH({0j.y{/\X?{3',m.Ȃn刄cyyyee?H.Gq^zN9LEn,_u+G$ xl{7`> G~{E A#a0@60N>' $aO0$6Hx1*''|g=uL8@'N<>FX儱SOIy` $<a$H}$ >h G0Y-9g9-<}30[Ml s}ńaEC`NƀsF>.qH WTMc`Nf3UӛiwA\\35ڥ{O@C¨ݖ-s7Rsgu콿VUcUke1*ƆCJ;W 􋦑jNuMhR-Pz.wWn<2lyP!9M^\S2z&wcc]7%LZ}P!9M^\3o+Q1a{7$7k6,ߚfsWc hh 0ןzꩧ~$0HlcUNO<ĉ'N:u3 $*H`xg|I#r0"@b#rxgH`D$<a5&3gIIl a0@H}$ wmn[pQwۛ4~q ꏾ}"15:zMLͦ~TcfGf/M#0~.aV ?NaoCB@Wخ_nl/ﴸ1 w:Z6ٽǖXw3Cmȭ. nS |A€/ՖT|yٙמy6on]H/Pϻwqbؕm ~~m2m~|}'L8|Z(.Ffss}yCR~iuR:jt32iW\i돴pZϫ @)-/&wTO`7>FCe>*f6*$}5vi3M(H-~ŀKqCjSRCdmmduTQ#nJ+OǵG,uuכ=)j|)4+E\eȉמQ ,wIԫ5!lP(lTj j_Z_Dm{5\ѥƸm6d3 8l~tLRz~drۘzc}nóFtl3V{q7⛤f''Z_}b !)!ΎMv;; ClM>IEFMW6c% _8w޳JT=^> ϗM;U_U:fdxp,n2W{鉮3]^î^XD3 Rݽ1/*f*Z1x lO=q7|8lg vqUM^݋dt)vifXuB~\5-U[4,SUZKb_d)ݷizcjj!HFZd!og}5a6WH{KM+Y,Q_+=Y"_?OQvc]>8/O)}T{xdtHh^9[:Lݟ u-+C{,U9QvW\ď%C*k6~¸;^*1ٳo|]p7?^\rw >jZ3ߴ eVPit|Q}5-<ԩlB*Iȱ#6ǗZ|=0Hik QJPuE>ai3]+ bɴž؁TZR{GFK*O-fY74YlB)++9n34fG(gI_jiZ=T-?qJLۺݰ1^,մ?Sl%I{~K%܍UL՚^z!PsJ-ZvwTU[P0GYٌǭNjy(KŖR?sfCouݤ]~]Mw#EӔ7c4\=j/P屍]/;x[\%ی1z*) iKr뭷ܹko. JjE{<m6]خ_)iP0ˑ&E~]5+Ƹ)YE-?Q'Pu7x'J+ّaseVU6~X^^?)! VرcGj^ `1W`]qq}ƌۂCw+x ɺjꭌ3F]tl:>qNkE3 ޝ?v7:HǤ$NS(/ƭR/A2U^ F%K8ѐ‹ʴ:?T8UtmmȳZ5Q!;zŒl8p_ ׽~ hդ YYY9tНTE{ھmw"azZmK_n$ @l߄f _"=ݻg罛o:̝;0΂!TT8M~&7[2]00Pn+wf7]f`tqx?zm;=BwrsCy\hLkm?sFzaE0!jji^/7K꯻4PE€']9DjrU7ޚ qvxB#q}۝ƇZ+9 KԾ˜ 6=lZZVt~®*fՏ9mfZe}7@RKuF@ ]m ' ʳixZRj%ԏd\ŷoG;Лv4?_ ei?*ϊ]Q-mcv纺uecEMQU/؅˦6Ԑ0YȘ\5+upj*#IsC-(qY`RL5=F˦P*f 8fGٻ,?vY%n=BӲifhOs G@"&e֪^sãxuiM6LW;JZ4Ӻ%+ݻ?nCOdsԳ] ٩' qJjf2FVϖM;UMpz}+ۮK*gJܮoUeԸڐeT00蚋暖TsF~5ZG]K7no07;.W#I+WGDC-}^v-Jզó=qOsU|V`*t]dv4:c=a帗S eQN =&n޸[\F `\<@6 $ >h G#a`072ǐqk-?囊d֏ZE@6لonl/ﴸA0oHag]ve†߯do(.)U eHl~v|/oR[ʏ;͖K|Ov*q%6 8e d w[o6fN> t5I% 2mʔE8y,[LE Xע?JuRi ܲ=ռQ]S>e c!a0ҝR0`⠖ j}7ٟp?БC6n|πs:f5֍qkKY,&QduHZʼn2K >RmY3B3ukKNit;BmjHI00PoNߕDǮTۚoU=m=E48Οek,1ꃌҒfBeJZe-f?YmEbWY%100vSuQ}yFT\JvzwU\D1ӀPu[?5Oz)MSRaqmbgዸp02ݩ3lgl0{I+++Ò4i8y?vՒl.--Izf!ظ^#Sk}}}2Qؿ1^82kii? }Tlv0A}GY0>cLr"+Ca`O+++Ǐicd0=[x'à͚ǰӴ&(CI02]RIT~j!+.+9n95ŖzWCa*a5?4YlSR֊]ꅑjت_ʎË6uzUUYYTmMz\?TfVVv2k Þ\O|jRKotU=Tl*C0Wm9+U/r_UWt]6f`\5(*q@ZjL{Aw{FHRvN$Tc kdv()in U>7$ta7jWǸEn.97B*vOo'bqjV^7 3Ks_C_BͥF;]qq|IZ:7&UmɆ;VkaV65E}5/b Ҷ[&8 ]8BWT=l_ҴP=84>S١ .jt0, fM岍-ס<5fDJ'Ѽ#a0@H}$ оM$ӧOIIl)a<$ 0" | '|gO:%4 ĉO<V9a?SFH >FX0 h G#a0@ cdaa<{Z]̦bhw5 0@FL%me`,1:i1LSH_%T\:0UWE\,Ҍ`=ą, &v4lC$ оJ{N.3ő`1aH`-.P qh aC 3iZ$6SL!a0@H}$ >h_9a?SO?3I` 0x'N:ugHT>>FX!aD& fΝ o[3ϐ0(\෭ƄqLh í߶N1a caaAg ƶ'y꼜|fG&\7|󎛿[zF~E w%/]}7;G_t7W~ꫫ~+;'=,PAf;a8 @=GuH NI1п/=X9qXNJT]GBa_U$6UigqoX%m7porm;n nbe4M tȐ>E:aT/W?r>|oX/^rWWK3?}Oe}I(U"҄ںjlLQ+k~ze0_M֯/>xoXzea>\F3J Vl=ySr'~oX%KGLt &v4 C\'|_]Ι~3.͓|Ͽ{3~+;%&m=Ն% SI*#$ Y\fV #$apߝ_ OSnõcaqq0DdvqOK'mM7^=,{7}^m 5񏅟lZ$օl '|ۼpq礜9Zk?ZhNCpzF~/OI\ z;rZ~xo  C3F©lgr= xy?w~'յ_ygn[hyYQWvHsc}_?O~z~f!a`q\'/ze!|AyH<`;+\nm^eCˏ=<ؾJ.s~yVv ?&a 9r$ӻۙ\ɳ彾('[I`WLoI`|ńqH+&wN_$$`ń!還G$a[ܱcqA8gaaqqaaa߰$ ' 0v}#a0m'-*NkgO붲a^weYղä%0Cn@{N)X͇ Swq]ǺYԬ}f0Т&@۹]7M(װuTi7aȽz潙tRj>liYP;ɖ gt`"a`VT$u+C󛳹˝7xC[FH#K%Pɪ)W8 #[lX{^UΧ<&Nu6׶_lޔ['X&+`"a`VFWr!#e#^/ m)q,cT=UvvUz5!ظ׬joG|FHTjPă:ٚZ\+:[TG6FoJ.S?ğClek000+ #]+Wbw]/;KyC[F#%jRұU-=.}q? -xRZnadmN7͜@XS}< N\7[T:F+ޔ}Ŵԥek000+ C_}?1Maddp/AO#K:iDX2Wqq 9td3qzZ"qSSScdkjfcYgsUћ~DQaT&  0䂛ɯ42^%=}=ҞbhKq;:R*/Zۅ\4?Ñ87㚱";uvy Yhf|Ǜm9Tw1#92˷ek>e{)W7깮5J%TW0׳Mq}KYy-7_ E{HƘĿmY1Q'k/F'0+ضH30C+ضHYlk$ f  󄄁YAyB a+/ 囧.+G6v,E0`!eg]/$ /.H̓ _[ԟ Ͼe~3vI coqo6Gy$?~N#9﷭_C+W|K,50$i,970`!q|֯~ɳ}z ~g'%v?,qHob0 N ^z>~_YT/?/\Õ3.]Cd.= #R#a 0$\.yGso7.߿o7]?wqY]' !0._13/OK"a`sH0Ot¸t钫̹ s_KkՒH̓IxS?}Y9,6D' -H̓0|AIR9?1YD C0`ĄcI>ALDdAC$ '1a#GDn++++60EѣGIfc0Eb{8Jn1fc0OZ%HBtk$ @GHFtk$ @GFO,3bcēq-koY@n>e8`r% .-MS5ax{6a-2bh f( /ѹ#k0FHIa|4![PifW[:+*,Sg5_C*QXtm0tK;*j}RB7%lW豻SiN"6ZQ۝AY2TbښYǭhoqp~aH1!UYvXđcՄwTT](diA;QaTh7Խ\׍gF"#-e҆Q8.ls-a!U9ls- bvFh@1IȀb{%>Xj:pՇ t6r3nƸİC82*riiX\4lHsOSU/[0,3T\~ԝ9z`0N_-p{mX*gӆeZӶl=aÜ6d.ڢ Cp#Kv0(aRfO18 ilK;[l!m܋8릲T!=5-YMϵ) ?Wt~k5G6X?$=)Nqz00a6]<{*SHcCȇBWNm1n0`0Zb*a!Y$^VKx#3$`"a콇alcO!0sk>"*E?h_"a< $f @K䶒 A#a07/?@HFtk$ @GFO{o7Oᷕo_NtdaEi0 1I0LHbzH#ad1 `ϷKclFsuӾ®Bž=ٍ&kZ=&Yd 9 ϤrlT`Ѐa$ @GFKaXVenonժjjUhfq+{k餥3>-^\KGφAkۤjkv܀cHLF]]vCÊMn,hi,61wak)+52̪FE&؍CQKw0v~7O[-wVȊHF=0~Rm3 _%T:j#W|q[Wu[|tԑ}*nOM U\=ҙWVw#jTvMf7p+GelrWe8v$jJj[S13*C-k=>HNҚ t6ZY%VKHraCFzUSm v~>l)cF W/[n^ &٣}=rGc5|vr.ktvׯ>.++KcbIW|>ԟ!猞⌾FKElw/iW麙[,uLa49mz5[mixiXccj0x=hCViXel' G] ڱ٣}=r5!;IH;49K󕖰}Жw:y 374f!`ajx?006H:zw8SROy|MVS9lmK 1zSnbS/-a{M*5ofMuSY\VHoZ|^/[ ?Wt~k5G6X?$=,Fϟڐ&ե#$erQO9&/ZWZ'tiuiWm +47jT6{XҞ8vǬ ]8B pW+3N|9%S&!eƧ-ilǸvI#-#tz^ήJ&dqCSMU∕]x^'[SkecYgs}MeslM 1rhaFR{%Ǻf^_\N3 :73e}5[T1U[3Y^OW# @mJԀ@1fZ]8BZuVP0MvSͲ&~YGΆݩЖw:y ԃt,iUKze_nr\H6jY5M3'b:nxzƹn>@uW)u;+iK$^=1ä5\/j#0$#͞\ n sH җ"j)N]k2s #,ܨcN`Xvq0R,۶ԟ m)qG6Ыu҈e6}CC&n"js&fJR7Ej7HO]]'[S.75:Zl#_'W51 ׶kH뀞7JqTKutTsK߸Xj/بcN$tM#ы^?-#tHdjnrhêWZT۳/W78q1:ōMucd@id 3d^EzX7#*~Bׅl֮qHڧYO,[lSjs=FyYg.ldng{qH #TGfih4:Jm=o;;C׌[-t䑪R_J_.7Vf^@EKvv_oĉuqYR/'vޑJtc}@lJL=뀹9Rjh/I|(H6B@#eu/^†_iX^AX"켙e tH١ˈ'= FN'Q#+cڅ_ZѾXCyOsJ~82H[\>ÑvuЖ׌Q#uK@36C>l30́ާ_QI'N̑Y-[ˀ(KqQuW*"ڀ=lJ܌[k!fF}k}կ 8wů1@ HF˜r{ e lQ? 0 Hۖ~cYD9JB5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#$^#a:B5#Yx[I}Bt$K?o#a Б,ao%a Б,a#YtA#$^#a:%a Б,as#$ @GHFtk$ @GHFtk$ @GHFtk$ @GHFtk$ @GHFtk$ @GH&_~:o6 I~{:2S3Gl/FFHͣc|BTܹytҁoq};,:BcC:>+-nh^MO\=a4TBPU[`vM:)9M0&=k}etɺ0UWK!JCL~>R?7}|9w[M;bٰ̓CTҨIi1Y3{tiz}iQL8&} 0 rI7oǏ!i(MRsv4u˜aWxdC>8&} 0 %noҡ65%M7fh=aP?.x\MW;0Z Gl w4c Ir둰֐1!;&aN2lBMOT'(~#(6VȈz+4ugE$  oĊ(~~ !8nOsB2ý+ARdJ^Wvfһ߯~օ}Δaη|gޡ1*׻}m ;o~ضFyb6d{~)F߱=}#=~_O>X\@v׽5y gǎ^5IENDB`asammdf-8.5.1/doc/images/xlink.gif000066400000000000000000017716731502633300400170050ustar00rootroot00000000000000GIF89a߄vwqrwwݙsltz~|ihd[O8/(~~~}'})r,MRC>R*Q QD / !''&''%&'$# .! NETSCAPE2.0!, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S(˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJQVjʵׯ`ÊKٳhӾĪ۷pʝKݻxѲ˷߿ Lpڽ+^̸ǐ#3E,˘3k)eBMTӨS^ͺ5-CMЮsͻͰ*u*ŏ#/eУK6)SQi߾O|~ӫڏGLzZE Yfɚe+Z]0+`; $zz d`?$ 7MXa 2ŀ9]XD1楨'M{.HN1* l)`ԂJ'# Lm,I p@<4MY%5MAS`W*,暮Lؒ3)R, 𨝞 R)HBbƤLhƄE<:"?E駠BK.e#uYd-CŸS5Z-k? x ? R3ln8([zQJLXDY醓l?mo8;cpKiDyy\ &'8RNK۠ņ*U+%@Yg 3Eb$-qDE0s xWmdžփb"/@r')?r 2L&j.rfq7KK[O&W2.MWm7uE5R (>w2-IRq-H +F9!Ps^8; 6=SڂIu.#ҽ1=+~ηꒈM7lXnYyթ 2rK33cJRYzJ͠]|ߌk.LM$:| ~l)Nb0yl̡y}Dxǝ~r])ӹ @oszVzwգR2mKTK7{!BV8!1Vh&_#J◓|NɡRЌWXĽRCO8A|I X5/j]<)сUׯ\ _.L׷8=aL3探>Q1t, qæ6`ꏈL"A&M"'IJ%8̤&7Tu (1)R.$%*WVL,gIXenl^%0IbF H2f:Ќ4IjZ̦6nz 8IrL:v8)z̧>~ @JЂ*MBІ:D'Jс"ͨF7юz )A/*Ғ(MJWҖDYz !|B@&1#)7 WT@5LOu<̨XͪV{tVMfX) VM T)xU hPǪԵ+]ձ `Kح~kib)8BYPb:kfМkeϩٛnVTf_7šMj:&BJMaíV٢'mrv({2 }C_ޛ wm5;΅bT}oN^N ;h zئ(O=J3*; ڝ~ Mծx?Ծ b !b"50gÊum;U8m+mcXؔm(ݜrwA~,V_52n?R= ThNYjc"B&Nu )yD10"7v2kd=?u 1Uq0gN8Ϲw@ЇNHOҗ;PԧN}A{`NhOv)@l;sE8eNU)q;L!O[^ 7%-GrOWֻgOIoO߽Џ{^Ͼ|{z!A ~4w?Yh_788E`w7Z +rzC "9z# g5szH-^58 S$H{s!g ԀXHu7Ox@X>zh9ׂ 4'0zY-XMS{#<v ק~Wń%Tz%g"8B70-+*x/%xzzÈ7%Tz԰ -{%W3P@8(Zr32*7)¨TKU,+;،X"8Jz(}ȋg ؃9˸\(S, r ؐPtzZbȌgy ygԵrx/pؒ.Pz"3H%3I!zzsp ؑ9zohsD9'ԥG 0;P{b9ďȍI79P.CɅ(8hhSyؘh¨ٔp~q(AIgE0H{aIt` TH I790853) pܘz:X93!`whC;0zyO9Yy虞깞ٞ @ ;&<@ ߄yYib0 :zZMJڡ J$Z˴!*,:#j0(ڢ4Z6Z/:3z>@9D=HJ CZNݹR:@ڤOzrI\ڥ+jX~^ZfʡBvjlڦnpr:tZvzxz|ڧ~ vdzZzڨjʐx޹CIک:Zzvx{:Zz9ПCp* ʺڬ:Zzؚںڭ:Zz蚮꺮ڮ܊ꝿڝŊȪ`LKj {Ꙭ;[{* ʪ װ$HD(*,.02;4[6{8:<۳>@B;D[F{HJL PQR[PKV[+ . f+vD f۶npr;t[v{xz|۷~;[{۸K 3K 7ж+{m˵ -!) 0ر6A ;[{ۻ;[{țʻۼ;[k{ݫ˽+ ] z) оp{{ۿ<\| <\| L k7  [p0|8:<>@BMpM 1A= I=DmBZM=L+++` P *Bdnpr=t]v}xz|~׀؂=؄]w͈ ׋S ْ=ٔ]ٖ}٘ٚ-ԀyM 0 ץ ֠-ڞש UT2)Z..` @ 1@1Fp1Iʽ=]}؝ڽ- .0Q]4]M@ =]}`m.ߺM ۱Z@85-p-` p ja p ^&~(*,.02>4^6~8:<dWm`- ?nM =NPR>T^V `Y~p_[^5&;T@rs 0 ͠13~>^~舞芾>^釾 B +0Qr` Kn^~ꨞꪾN $0D.rj~-LҠʮ1;Ł?s p ~؞ھ>^~} پ? *p F  ʎn˾+ (0(C&CC*,.02?4_68:<>@3?*?䡀N DK.NPR?T_V>O P(\`O]/k{P?t_vxz(#OT0L|c?԰_dO/oa˅@'P'`d?_?_ȟʿ'/?ogƈ(&0&D?_aB@ DPB >QD-^ĘQF9adž!GIPZR5p ޫ9 aRPH%AJRM"UTU^ŚUV]~VXe͞EVZmݾW\ś7v_zC]e̖5mFTO,,TΝ=ZhҥMFZj֭][lڵmƝ[n޽}\ō?rʙ/X&LiB_d,x͟G^zݿ_|ǟ_~0@$@D0An.+J /0C 7C?1DG$DOD1EWdE_1FgFo1GwY B`A'2J)J+2K-K{H#a;%bK7߄3N9N;3St 2lM3QEeQG4RIS1?NEMC@tRQG%TSOE5UU׫4zOAmrU]wW_6XZsHX%PeYg6Zi$W#ti7\q%Wj4ۜPo˅7^y祷=ôLݩ5ߵ7`&`zŴ̛8WI պ Vɴb/8c7c?9dG&dOF9eWfe_9fCbu[[_ C&B`ٱC@Σ9:jj:k:lzl짡`m@瞛;6?o 7^]3޺q!ى5]ٗ8޺+_cm&]&Asd3=|𱙦 #Zq]\X\ycz25<(x!Pe,t 3UBQodf0!{+!M(Ew14E}4_ 1,9!*k_ډ^1FL @&M ΐ3@BM`:nj0<*ȐU^+Egw yFlXu)MUQu1i{qbɞ^HJ*C7uT gʩkK[7e5f9S~C7!^BX0,pi↋ىJXu/vݖ8]I/RI łP~~b16haPjEZҞ|1(S'CPbe,Ra^Ӭr'a/z4m'zuZ8g`fgaDƀ~ )yvs')#+͹ )-x!vb |wqH)4RэFJ:(1jÙU̼ٛ&۾明#.0Ze}0ú 7`+^f[S:U;1m\ >>oO=8$#Ahs1(= `. 7*5ks>bb\$CQ;kC?q۰Lǂ 8⪿u"L);06<6ɾ1?7CCz?{l@̔FD%?YһCXZ2˿Q3:pC6.M#{ic'= ?ö2 Īc{'2zHt!L`I"Ș&S\@ƺ$ʯ&l3h|B|nJJtU4DNIs,pˡKhc=l='DK>KS)Ph  \CĔȧ:C|b$J!>}[2."G$2IHL?))քJej#?a){)I|<:Ȇ<_Nl1EJe{'^_cT쨅SP3n>c:?[ߐ_ ).aUT7Te835ճZF3]%ɵbv,_9R@R3U4Nc{ yu _9LٝaDLa\F^"^&"$*E: ; va8a u=baaDaY8Q PQ>aUV(@ z>m>AlX{cQec;.Uf">SUb^c~\Cd5}9&ԃsk$a.[&f_.v#yg Xg8H&6FVfvj~WY_=]jL;F8re_[i@v`-`JDi]憪WPAi/'Okris&aR@xS3N# Ѐ ($]^hjٮm;%Uof`FhY2kc_v^ΜhqNlF%E(RYT &1l9T#}i)a47ZRȆˆ$ol6~.l&6v_X6[p[&a$퉓 n>Q뚈Lg*x.=ky9"c` l!oD&tO.SnY xV)rm6N=FO`p6~hn A[5#?>9#c bdqZᎾG&9@.^9bqEFnb62LArNjS( 0R(c(O)U+,p./m.ZmFZmYO7WqtQύtn.I/g}~L9-dp;Ft}iY@ Z\wzvue;HXY/}g[6kyX8xqZvfk??c۪vwy hPkj+'wyr^ "rH-U=Z(v@SG-r;X-&1nhsemT)^y~>-y=^>IPR~nͭf4:˔_׵rfc97*||ȨQ6r0f;:L „ È'RhbC-橸Ɖ'Gz$)ы$`ia(Ś A:Yӧʊ3h4ъDFnӛӢN]tF\`qmbRj/8[2b[Z+,x)ܥe/]lS!{8PV9_>(`Νeբl4= f # 6ntv7c>,\ae/lPZ8;N=w(_d;EmdHwN8}K%mDOQV#mE|W.0Yy$\&qf^` pEb`abaE`UEQfq&Z"Z-i(ka$HT)h)ۆa9ESVdr1t=(O+~g'F㭔_80N#eK@Gzie9ټEѡD^Wb ZXThiJ!HH5&Xby.:j$ceeVِHr,$N YfN>\Q 2 bJ).i;-sM#CX@v0u$_ay+ ;J_5EV\dh2+C 2XƅjTS i_!QDE)^gfV$~ S$FN2A2;hr(p -.i e[3!:)L#aO?PO+c3Lbm7CX .J)ݛs(RG #j0N oTլ:)\NL9ƾ%F3%Ho/Kt94E c IxaU!3tU/ Gl01?*+$UߙשذECڧ?-1 ` 27I2ǐA`<EMnzEpOls&t0"CVű hcF%F}gvL\塩PE%4!~Tk1+TEw3UNYϐ]-F)",ME5m&}ZN6}`l-5R{)1c&BIKJpq DD^Nj`?F!J,c !ВDlLpN;y CWsCC&$sbIc H*^v̯~6T9gY62)VW>.xfM]j8 *y#**Nu")#j-/D:L3z:'9i:ڛo3"!P ݎfoː3gզy=6 ^#p͇9{ 8-;â.F\AB`%2\A2p x3p)\^NF`{Tb۫rցxevMmn+moGd Wc t0XH}&8{o&$}%dX"8̔I 4ğ$q<o$wc]Rqt%+|;T"8aݺU6vktߥjQnJ4~խ0{D3_NbzDE}U˽kd/^X4y mM)b'-Cx`mmF`Q߰^ݲ%%[^a\%1_59_I\B^]xol߼u|ȽKEV?QTO yӀ 9AD {Mo4 = SvuWnGa`FLNF E\ؙ0]AUD]઄]7`>Rr%!gѥn"'^JN1Y`ԉatI m6#>٧J 4^a Ķ]D88pOLV _/!IQ 2l#7v7~#7ʀ@Cu9'^RGWB+aԑe`oa*f[֭Ŧb ĞW +/j_0J#b@#!zϴYN32b4-i܀. J.|M&n9&@w*h)ڣ)ń* )__ }I$ RD! 81N@d]cEMDuJ,Q "!%[@"kğP \%]e]$9J!LɤfCQap%\@ DD_1U^L04dDdpe 3XeI4b`5F\#e@\p'q'q ^B!_s`bv1Q`Ec,I@H]LUV@jfHB*dF&O'P&|fnKQbᝅ!"G n#ZZc[:q6h"r#s>'Bget#u!xK| C}e?H\S^{GCoV-ImZΧF2NpBr:TsVItb yuvhP$I(W=yBц1-99DHhM̍c=ao(fbG6Dd3Cgy) f*ff.(RJ(nI㱡.av=)Yi„ViC%)e.)LUihQXo0UANje_›g$z*j: RKFܩƫ*Fb M21dп @NvrD4ڭ k„抯 @<k!^SS9Ei糮hhbGg9j@Fm^қePq+C,z+)*ICa^u,mlEhgnHUDR bFgv,T: ޠh,vp H`Exk^Gj>ƹQJ'ϊֻ*>npD+LpW-ul(Y %,cnÚvmX4'zάUE ǞQXtkFLB„͚F&p.n5.DI$QAfoI B>2۬zjcZE2~y@fS :h DmlV+ص5V6$./rBJ&RA <$q@p0`B2-D8D@-EHm0o]+[`#|.| R]â!no$*ci[DMwlQ\pflrqz0TDHq 9^uajEю1dl$PjSVDxLl%1(B΁{ \D'rqom bH*,1&t˷0qT5WA #!O(r}!.ݾȪOE'j2oYáS&wj0In,մZ\FbWZmQȘY&k5+G/q@<Ђp΀ұj \3LSAٚMMGWL#`T(-N]!(/~<˅Z= s+|Yo;VlPgW#mYfozb6 GeeVGҊ+:~:݉ɷwTњ-D/P+RjC9+kA欳|'-.-BY-9|#RK$-@=MV}Sy3L洎ƻ\ѣ!Z|VX5v]9ǬZqy4t)C>ZCfIz9(}J#5TfД ʌTΞOQX!}6r6*c8woKgo (gkչF?+C=7B>ңjd.}\U؝l ;#]};Uk+}M E^Z83D0(lu4(E|GGxC ah6\@Zא~$U/-ly=Lp6xٔ|:n4§d~P X'`1p.k h6" =Y2ȖM,;ڬjeَVXB/tdfMD2Reth5ŇM=SYo%o$f* W@Ǔ.ĈL:+6gDbd 4ju/GOcH*H!"9F>K$g9rgdJp}&*$rM9b0]S *2~  ȹ5.}fsGU,тKoݭ+#><'uE KpK>'eYA!DлCM@T ؟.pJ(.SX,&*NUlO➍>:ivJFg~bHaHK0 Gxb~B*lZi|K}:/*9 *E8.NŔjfNN 7N K4@|a.&!HTp&ҀB"DlP(q,OJGvzH4'o.Z4hmT-,'>7 k #fؘ Ӱ:c p"k<J(0PX&`'aqx ")JE-E'H-,bXd!BqFQ'n$wdy"/B+D4 (z(ʤnJ20T19Zi) Cd'lQ((J޾0ڰDP`-аU&ZBrl ѲG@!Zqwb &bC"^+Œ#A,q͂+^Fb$nFr%:*2$Z^d"' /Kl(EHa2C1LҬP$l%}8RIn'8qrb4r-~U\:T(ݮu))O<*2+&r"'J!x9u#AE2(-E)p"1'boF/.111I.q#ق j @!Nί(s{f2+3}d@PtmxR`5C1NN 檏(fW)cV<T`*9S#X;YB bH!8"+H9$Xd(BbIBx bF a;"'sk 0 `..u=so0y"1v"AӢ$p6rB}n+KЮf2xbᄱ?iODDear7[4t'G&RJ5(W߀"F-R.BLb :#B e(dh&̴LMr X`D!5-b a iAuV'@ Wc7o*DSJEg'-'M,# HTWtqLUpFGFR!*q*S+A\b;$-5(&ghahBXgv!D5M@=C`Vj+BN7 `T^@Ǫ_-_C%v`1a .N!0f"g3fLcgcc0C6.Wƀ܀. P6V1=8yDwtGB+AXuGIggC6bhhL$T.5%PhZBy:xB<jCjms79n v δW{Gtb"Q}H~n6aǹƈZTpKIOod)P UуsؤAW!'d',u%BC4CjbHKX%69W8%V8wuB.M)6DrxMEx_ez΢1lʈ. wO2Tт3`|Flex`yrGUIȸaqG4@XEۘEEWCi与7FGob;J'ĹYt?"ܲ^vʜxfR-2n˾55Qi3bS̞}oClnlTy~QÍGvU 2p r9۹9;9-Y;Hٞ}vAՈ#; A|͂3Se+@aDBSb.:7<ڂXÚK(͎9pjNewѢqڔ.:%b{%t.zom8-'4OuZ8/q.w19-Ydd׺5WU{6F\ (aNlxz|4C}n";Z{k9-85(wF[&g Z7c8([E{ͺMU1W;B`m!lVKO]˶3r:'ey (1(>4JRNO b$~. I6.|)PfXI;rۛaudhm`@ӂAyks[u;}:$ Rx=[H:6,|gQA `NS\7˛Fحa|Bm]u|,!>7-mfzw/м7p~;Sd{5%~L:2K8y%mς|dɂɛd~]q'k\)32d\G,jQIY%q13" &\_1{f#R+~U=(Ԝ_}U|>j[^*~ᷘN\/_Oz oڨHMɵ[!3U~dg<~ˢ >y%%?5]58_I nBORp]3jd칻 bT-ޤ…-RLղu,*V =>X1c$:z2ȑ$K<2ʕ,[<"Å̙4_H1gGUD=jI]put(jTEk̝sz2p=IDc4Gא3h|-ZWXŋ.^3.XI=9ג92윎G:1dqᔇ7LQ~5&YcODeG; {U UoYj1tQbD_(ԫO=[x6q:ϠC2YXuIuHQNǭiV,]ZUVY؁֒ZuԖGڐ39ٌT`WՅzE]YXJaUk$1҃!eC PYe!eZ(cH,$Iu-ḆyVm9C06- tC-WyAg1ajLgSxTST)|*Ǖ} T#8bIZ Zj;"HvFrfGvc"m]yQha`g\E8%dj2㦹J[1 R,JNV[IT \ٛ- a}szjDH;K.n o'1ww$SD(K=%T 0as:Ҥ+j(b*iuѧXd^!UHj`,H YhYJ2w/ֿ!8}pG9,Mo*r,,0 )LmC^~)sGfDj;+2"{gfݑ'ߡA]4kQE9Ȗ[يz" `]Av&wò*"/l#H:sq,#Q&.#%SV+ AR)]\s 3K n#aO?QP+JX؃D<$!/`/d`*XGc[T1irٙ\)L QGB'#RTcH*Iw*Ƀ14.+D!mG-= Ld)b-)k-6}d 0xo g$;ry_SoP}$s xoa}&sQpv.H p/`>'e0v.#HA~p5UG~7z&ȝ,=K^Um)sT<)%7k")ŭMzU,W `h{^l7M1zD gўqpG?uѕ+;Az5Db@/ ( S0A‚Hlbr/|@1jHX(mIH )IFI#Tmw k)wˍq8 t5lGBaVX[] PE ,1frKefM[z^HK61gבb0__*Ƽu#{9QD&2%mFE(KhZe1jn˕C9BGr-qKY%#wVqij&u{'Dtˮ9&4*ѓ&|E! IgEX}'#ptInC5w{ְ>ҧC\(c'ѪF|hT?Vػ‹N#ߏP8ce2פga/Zq/@%n( Ġj@2YsVpPZ+H-7(Y瀙9\}4{ s_Ҙm'KQ„6T o* o~c=>yc7EBaB "# m;x<㪆l{T1 k1kw(Rw4bb9.8w`zwz5lE \U{=)\jBtLV-MgV|q&i&j.7y$a~YyAP0P5YP_a,td+cy4r"V\z[+!\'rz*2tc lxsa{ԅ0lZ+TfGTE|rU^A+QuH#/">'.A1j4{oycR2DBK5zxYhpkȆ1CDdGulFjwE|/xttո2a73W)qX(]%T7%z%ka\,:}X{"Xe&f(m)]9]F|HEXe)/xp t 'iuI7#Dr}jQ9rh.FA8ryg1Iʸ͸mE'(O#y76;!q=‘,)Ic'yy8Efe>2zw8 RV/Ge*#16Cyq.V7HiGYTHaDPGcY蘀ȊI"83$1v2'+C_0T\BIi<)|i|!Ei9j:i`>sƙšnhD9L{I& DɌv;0'**-򐌘 GPpa6`i<;$ቊj7ة9"2׎# 1&S)~s*A##h"3ɂ6%pCxE ʔb ʤEg% W:_I%i^($\+)$QzDZlb!U=꛰'Dj7xHMNQs#-$ٙbeA*D2,ɕ+h19ɦI%8ArQҕYTz9% jzj+ B˪CΚ ZYpPX[mcEW0 ^0 FE,UR] 1A{Jg39`1X4k]mIHg4xG`*x@QqXhQ|`? Cy1 ՝YJYj$QQ4Kz|Y]rz課-10>:g ِ㲤KT iA'ͩZә\5#4/e9`@!w)Z"1\D+Lx{3PZ\ ^^ `Qze+ g۱ "{ u)*ؕ]8Lz +xRVLQk*tvʓ+4's (R! ;{^ O ` KOtk۶Dz:Zdx$Ȼ#a*!'kd{+'mBo06MK#*/bS䫚&SbF[Mk @K Hz~ w@U lkR:+I7Q|멧$XQLjW$?&lp? A?tSpW?w?O?| k[A`iske}PG~>aMW}DhpF H 0X oQ[$Qx m#]p3d:4 O\C16*+M71ٕ]+]?ٞ10-ǩc,LL'Q<75 CXxDH=J}rM$؜RT]gtNvXl◜Hp'?`tOLs7w}|ע(E(2 /z؜Dӻd0=ٔ}P+" ` -}G z*eJ8/0=.\j-AlK/ZUO }}ViUG 6nq4WcvΆ%Wz% foy>u"MgMwvOX W0m. _(ƥa$; P=&C1 z @2P಺Z2ZSk$k@vu[۾G0.x^=!8^Н_n_ _sgXNeϯ`΅qwwg]|YN杶-效 '/ }ǹm$T)M1N@OP$K3Ҙ}C`D1&s/w$n۩ۦ,..ͽA@ 1va۔fn&uͭ|zv}VGfhcH.A?~IqRca.jrB.1\$WQ1!yP@;n&_;aڋ>"]ki6ۖΗ¢qrE?L(,;,v븞:oFwo#ofDo `%`oJ_hm-u77{|!IQ<2Ӆ$c+˄Q*Xo /Pٝ}Ήّ&Cq~O0 CzJne $XA PaCm אCu %t):TC $Kzq@|n4rBO3#ZП+^1NuUY*WaŎ%[Yiծ [q"9LݫC7 ՘;a~*`y VD| HWzx.Vxڊ@+[NWF|Q0( 5m@ ` p  Ne |{l)W6m"k3ʹ8gNx #8e! U8ph>; 0f&erɁB bʩb$qDGDSTqE[tEcE#\FsD?H1CZA0c LmHil-F 5ըL"c1F́O24Yr2`OOA 6.$A =P>t&tjB i~) 90ȩ0uU!VuUXcuVZkVkq[qe̱# ű@nR>6%s ?@3M҇(s3,rVN97;߭R40#ÈԽjM4DI$L!z&L#Ԕ'00H]TP* BeF@SVye[vecyfuuWE.Ye`?CuLh- TVzivizjjzkk{l~L'@E cnﻅo|p 7pWW |f$ #vtt +̇8O #91:2FU< :9JTRde+]JXR8S~{@0*hdD]D!1|yyuX8f Ml,?}mG,4Ӝo8f:FʏBP.)lv 4˸@5!Ԡ ehCPFThE-jP f PTa >oq s[wˇƐOEo'\۶wcoG\xeTB )X`1z#'yIb9+gy].n) )bP;yIZc\C'zs1$5ΩsG]$7zխ~u?E-bqӣ:u !t g]s{ݍzf<)luY]_~x'^g|xG'k1-NS;֖|Mzԧ^g}#OyyX8EKn |]{_'~x؇C1-N7}g_k@-Pa Pg~_~S溮 @@׫?S 82{7|@@ @ 6 Jڼ9߫@ AA 9H@SH?[|AAA;S@S(=ңA B!B"76"\B&lB'|BT9B$,b$Nb%^b&nb'~b(b)b*b#_v_LzpUhI`Fb5^c6nc7~c8c9c)$VHc c=a<Grl uFS[P]hfdfhdMdNdOdPeQeR.eS>eTNeU^eVneW~eXeQ_HF^2FV4eb.fc>fdNfe^ffnWFFMVBhfdlndjfPfpjCFd>vfxdkgg|g}g~geFHȄN~hhhvki&gogjqgs\iniSHiiiiiiiijj.j>jNj_fGȃ fjjjkk6j;ij^NTKO[IIPLìR0NRll.l>lNl^lnl~lȎlɞlʮl˾llflFlItО`Blnm~m؎mٞmڮm˶Smnlm?kXJ~J^nnn~nnnnnn&fIovEDVnoRXooooooooopp/p?pOp_poppp pWpp /idavpOq_qoqqqqqgqPFP_GOr%_r&or'r(r)r*pPr,,o-r,r/.rٙ;'F*os7s8s9s:s;s2L,جDn tAtB/tC?tDOtE_tFotGtHF@KsBMtNt#WBOuR/uSw?P2;_Y#.^nqie^Z9ԟVmkIg֫G.[P+ۙUmV#˭mvZZ҉5N j*/[Srp.;YzSkL;N'd{q́|f;4r"!o4"8* >t$ΟC.=z_k6$3^yryi2xbKӛO~Ire;,YfӪeOt\wTPR6E7&@wfXcD|Ӄ-K59Yh8tcLYZlfnonp1rMSRY6U6^{WQBRM8h_W N`=AkXyS\rU xUڄ5_hㆤuU<4d% vH9/~"&aݸZw([=Tӏ 9rVګh[ZZec`z^QGyV<{&ӈ/IH:y94}ex҅>H#I߸ bKju8vQcjm= dm۫3\r# ҾV^yeEhh[iojbg!v8޺WὈM|'D& vcΦhDD=wA`vr1N\{+fM- lbz!Q+*@?sMss>{YsK4F{թ-~TM l35i/׺ s",a=ن8m-ܭjloNqy۟tu> ^MTKgS,Դn&&sL~b&isXHkN;rwΰkW27xl U-zF?f5 Jړ;d,*aI>&{Qb4d De >9]ЄֹPv5`c hnZ 渇NrQMJ]DKW1 g D5Q܄=PVHRB1$`Dtƀ mhcd'GRʏHf5*H,'UR i()d xg8)LxF4Q_Ot^bb]Kаx-@΄"M~ 1Zŏ~cgR vfr1k5WT UNmHR٤d pD@A5qQ*u'9%IHڑ, qNd84,0Q%.CX;澆oY~NiiWVa 7#IPG% 9gAo&Z:Ri芧&(zzkJ g>3T[ jHn}dIRnPx&˃r4,E_fsQLbd)CXʊPP+6*pG 5lm][=L1Ա1!'9Bךbݒ*z& -^lI1:b|PMGo7*K<ƙ/iUJA|"҄2'MvQjoAIi芗PA!)k#03[FRFiZ,:4 | PUhIX8G*lPӥaLe#[ĤH'bR~`ͫ&|\N:Gnr-a UK4yS)!!%8eO550],h8y"њM)G*B ^/$Uc$M9N`y ν`8U# 2fO[ =#4Bft*6r|ML^MT^O#&f?EUI+Z&;H[-d{5ebD6#bB)xBBx]f{s&QfiwF'Tvʦ9%7`|fvgeRrNP.qhr&8'w@gA֦WT`u҄"T%cJ )gBzB{hDKijZ& ҅\]΄6 Y'єf$જjLB-i’v&D|ڲ8D@L\ht@$Y&/O-.V,k[k"#CFUkބJH s:-Xn A>^yl"׶",A(ٲGm*.--IP O0v|OtuhB8U!ʢ zţ^A`Rƣ9}vbm[b*]I`rft1&2M=S ZT NzޭZ:# @bU4kZ+ wG2q4C$^G KDrd4^0JJbgL5lX eʇSm|taUU l.;Nt5ǜ5ÊDvm6munl6m;[04teGLTv~Pdž6rK 6*']4c :rH⫕ f-vV-)B[LyuAbx5*_0oI$.:(C nCM8F,s4 K3IW"8r'`cdŊw] YQƾWU !R)+ z1;c{[UVy)4Bjhh{elK )—)!D (Bx™yӄ?H[]o^_˛Ouxy2RgοWoϿ=Fӈ ,: , 6~ ~))Dt `ͣjj9҆q#"̰J*&W3F&9:0d-tIkCI*" ȻH!2G%cƘ(l 3FpL;1[c20Ȍ +2Gb #"4ԔQ5\RJmMzStP~`>8j.T+h@N>Zξ6ˎFVr;`LދUZT#p /PCN;%@,#s2܎RTiŕ#Fpª/rt27 kG \22l"'^y-53(+p3s~q1qȘb ΅=ӥŮL&+J<*PR[-I+K3ՔN#|ST]RNBpjbYg>\ב8 XD` H%B 3,s:dq"o,)AJF&=Yߚ)rKG87NnB  ]1IaTj#<2;}$KQ[{ 蟅Δ7; !3駡 G?YrUOA=nuvЏoXHݨkhE BN\>)N`JB9w[.h&Cs9 !OfY[þTPpH3%+AV'0 ~bC/(?H,zЪg=xJwr8]{g D,QX=!ژ7WXwꇝ~y3,>Ǒc!?a)@n[@X !r  AoNّ' \V8BHQF4I G±PtY@tK2 KIHm( !,"\1$fH\ñTϠELO7]D] '>ȭ1}j?W=}v,D(>U}HI3(: dɂ`Zy< JQ>Pq\ *6΂异kn"a#u `NԵ-s&K鯘 UX! xޟKOv89Au(h;csPW޵E WÌOO ⵮ 5&I*QԱ(-%SX1Hhj(R ְz8]kQeJՕ7ljbҒNNUՓ[ݝ1 hk_;{ [HXZE* K+ӭjkTwiUَ`h59ֳm6` jV+D,5O9Mܔ.;7i]+[UVushƮwŘtu@AɖhA) $$n\S2Ueøe=pnݸF8UM8+Qf1yAm:ۜ*sD6~hǣ4 ٥oIgs#6\lLȪ>fZ`JC]>lyv,~w-nzmMwD0 B@d?\ej)*br̰oe ׋xH->A6Q:1$|rB $/ưvIB4%.bSDˀO.O1iQc"1ګ[+'axZα#0ev.P@DͿ(Nn+ #~1.t PddI̪% 03n4q1S?1&/'-VAF vN ]*lo#f1fL-mJw֠ }Q .PQX&pd#Ԣ11$(oe T. .%MFnrsؑ#L0gd( ",+ H[!?0 12.,Ut  P^!#;UO--Sc Ơ 8` .i~c//(j!1DԱ IQqX)`'rr|RQ4#GKwOb(2K&R6ɲN#ђ"n$1Lа#v Ā .C149<*ۦ%x|#@q/aEE=1;q32.qbkM6ơJ #,2e)&2n6/7t7;d$X7 &r)e*qk2wm@rOUb.j<#hCPNt&] B]e]s`j>5kGk˶3FVk L>mS`U=%.a e" X$@3pr Rd7h8P [CCYc;ʃlC>bW'?#Yt @:hAN.3ʑv5.?6 0.B:bxBܫ4n=q"o=km6z4#v AI~M)@|oWηWicWXCXAETr ƘYE;( VcV=ln}>B`>xX& *Ycnu7rNBXFby#wyT^'s%^%V-:v{s{mvz 4Wn $xow7gLiX-qUfiWXxeskc~TBfn&AXW됗6 bP#6r !GyK$b#-hKMf|iXɞs6++* l{#mQgmK-Q5R }cAwd!T{JŅ@ uuhc }#hh盅 D yYiU -ع%q"+\T79Bt_)Ui N0dfob|qSЗR8>cOZ7ThHV . `O`shꨐh=nȳiب(il2vDD"*52>E)#bYE4UWkr*Wb+!O5dV5]UZg'OW%WA-Y%*9[9几p:>U[fJW*jtMۦ:~y\iEd2 Pcj nDF+x7(`z "!IYqQ bk{Q2Vgðǧq}%^C "2B8 <\D@Ao E}Z9-@= BOd?U( "N2 p5 Ĭ.PBҥ1/̢{ /ѝ-[MSUs$"KQ弑{m@Ԓ]|Ր _\_)љ"9$:ؚ/G")UDwwYh M4Peu~y>"н~_]҇k n+; :m{1T9xnɗ ~A-#js$FsܷP5mw + ፔeٗwʔ)6DeWA9 G lbߣg?eL!Us`,[  H I CIENhtఋ u$.A))ۄpAyvHE3ט9G9*#J/]VH5H͊ȍ'fLZҐ*.l+Ц׊ĒƖ懿ǁeCl #K)q82Bds6HKը4ZD_X~q +"F XCFѝt#L)^0( DRtB*^BČLi8=YJ dҖOav()SJ-}DH@mchF1Zz4F@H.G2%ėD9F(@c/Kӂ,!Rs𤬴<GG&H0_ i05IRYB/DIj MN&*(I-(]NI z!H %efd%N !5 ` 㣈-K^ 2ґ).4&ehQ)2R5!9}3Y"g$0TTkH͑JNDˉjEFeO*"ZOyA3lAT6"|i:R DmJ {+dja FsCQ0| 9Ani#@PD `E H}A,؂41ILG)U'L[+Vs#-G\k~u!>5MG ٝrxsjLjJڶrksl̖DikvAu S»qmx3V^@ {G ;!`L!BLg``y.ԁAς>!-WP:&ȅw^f8+Ĉa1jQdriF2xM<WjKv*<@tr 1-ӠsQהMs㸺n(SA۷SBh!n~3|"B[@ ?VG+roч@` '3=MT7!bzCBXLqpD.͚J* -Z:=0kCM,6upBɪ*!}[Bv[HU/.bm Y9Lnau݄BhA-P1>4.KV$߁?_ъh?hCb^*w <#MqX9f 0dD3iczr$3)lj1Nc&܏6:,"SRzڲlϧ<:ΥL!jGpZ6׷nb>)ɝ1m]9t Duw4+nw@"wV6F P_ 1> GGoyy"?e#+)SY0HRuLDLzz3|LrtC@E;l{{bUT hz}hH9:yn3@S77}sYs;b5O5Y|Iɣ&bZB*SwF:J`bHP},pWDn:ytr?p@M4QFL%4NcdH.Oלرx!꺍ڍuag Q7Yj~E2(?  a pr:tDF $88G1<ɊAJ'&qU_j3QU˝!dmfT#ʀ^ EGp?157,(j*%3rG|V۰*c՛ !0Tk[&(W5X;rzl4FDQ5$?]KֱѮO ]e巨ʋG ./+'"9 L\LܔċJlMsûɜ,^š4ŤlʹEg#ڰo@+@J|w̢y4ѻN8=L1\lȝ,C8٬{n|!_LǠ:Rq @`Z4苢,CsЪ;׈Æ3./ҙ#J|LNiݝMuTv ѡ$?s,IЧ+.]LϺ|A|esPQQDǃ\ m B'\˷!,]|#^,֦adrg,k` KWKL]F $^`~]oRK \˜Hؐ<(hKk̓qY][kQE-+* =]03wouL뻋#>qͩ}m\3T'V~$z- ѵ#M{eҝݗ٭ f$^n`LsK`:HXPhsaBnى=I~4̶ ԭZ̞1Q!Kr.(c.^0^C;"-$ݴG:]>>?\BNE~׸m(!M>VM)@\ĽcʝS mYW|(Wǫy{WaqNe<{ѺZ#y}C1,3lWB3*L8\(NmsNA.%Z{P-Sxͤ%r;'-qx7nKU`Ə%gUVơG`!pNzqR$h]N˧~;r=>ބ/b[ѹN T^^ል IN"U]ݲ]"p߽^z?qfv gsggkgiPhQgv %o 9Ƙ JI4ꍎb(:> 3CޫBL^NNTPܷGiՙ\?^Rn Miooo)poWĎF4ё%QM K˞~VLCǎR4M6TBc{|IEG/.. !@@ DH0GB  p  ĆN|tp!GLD̗e;PSΝ-x`EL"Ј_n457 a5"5ز{%yNׯv߫7zDb H)#2\\Ɯ$GS $h҅`%J@VT$-"#P \t2n4B/ =~TXDZ0bA(.\@q̋`.:129s$R̞_HC8(Ò oA"Ycr o BI:LZi&xIWdEWxZ`)f "Z@-K $6+J̢2 t/ ; ),3774hbj@Y O$6reDFSd8pM"m.:l.!?RNS0OX=0B G +J}I /BO5m0!P׆45^5H؄( o*ǛomhYl %dʈ\$\eF9QGk*!"rBS1$;ݷ/$)-ǘ 79[7cLn>O# O?K>mClarm4AmT1o̫Vc9 8eWQbr"U/qbU52=(ׇ :?m/#g"@4#hʦBr4nClnG,1q\sgujw ! rzȬ1}%s(`K.|d;dRӱ..(c1cBMXCy5ISrn4R۹gINh"ս-Xe +Rm~F^ QwlNn~G-xDjpCIr|P fxV2vE.o"1z+t/ BV?iLIúDv\P;9F4~ O~pCZ#PzԮ@u(T{J[V4aj bTckfܙCiZ!P| F@ hVa#DE-)pj`PH!LhC&$l^$c&1JC\Z0.baAF/D09/iGHgD9Pb * d6fl5<5:d YA6Td dziUPKOr@! R"C}p?CDC',r 2A0YE89]2o'IPƈp$p#ԥ/m@`7Ԧn0C+#懥0m45Fw"bQdNM堋1!r,Bգ= )dꖶIq~D_OI2dS PTf'GlZ>z#iB G~d0K'n,NDǢH>$7)lU *qU`{fuVB`W%R;5D ꯡ\'OHf׽/hMm@ff#{ybfdw!st8hUTcG,cs侇 qu>̞AiZ9%s~[.Qײ}6f|УtEKg h؊YI7gyV!$Oe3{$DmV J9㬮Y1֤b( *YŽֳJ{.=곡RqGVv9AN=T˧kn:A쎮t6mG*D gŹ& 7B08)kWF\6j~T^<ƿCkV{ e$A7 2!?x9UM'|x)hZ4Q?)guw^mZûc4SIxް e dBus^%5-6j!)|ylMyek:rC(>: ş,oF쇠[=>r q,t} > Q32wa4<׫s<}~c;&Z:e4L36X8C0B;4#hTY/"aa|=˽8R2cRCc6l7[>5=i<:1 /]4/6Ԕ# ؀D?+*CDC(X$۩"aȿWKB6JFD;))̏sP2>\1d23d@{1= ?7TFŀC9;=C?,c ܢ7D?2`K-k@*L&+R\@kSC`XT B4ĠB`ĂDodJ lKNDEt EQ@S;[\BW(X\485P?(3@b4FCF/0`T?c>3gHi ɲܦCAJ,.9kQE ɠDI2|ǟ,0dz|E{'tVitʋ/yD>`t ᾰ\ 4 |K&hFetNfIj S,@u:L:G9¿6x.DyPŁ,(M JPͪ$ E8C FD:<Tc1S"؇ 4 㜱dN\NHDN"; O #m,!\JsG*T>Ѵ+ʁL#U >i:YP\CLi ?(6"c!28՗`Z)ؒdd!:S:*MF9 ;m*I>tr +,+*#ğpTTUpPTMUXU%؁hUW]URD+7$ntR# dMQM 3C~+a$FaPԼu1%5eW7=wSЙ!> |0=PW}%Tx!"ECTdԈK`%ܕTJ4} QX&Cm<ЋR- _BF``XgHǽK:*ԲƂ8Kݯ*XH(cOхqQ 18WHUYUW%XU aڭYmO #L]V&eS^. Ӓ<#Sx5} )cґ*yZz zA">_ &Hht<㡊CbMtZ;9ԏ၈#]]60'V]WaXNიG%ZPg=JRD [Rbxx _1S(+Ysơbrc:_@ FTy&==AFNf``LdOdy(e%X%5صF"$%P忋Z88'&ROYkfd35bMX/lf}^a< YuN+jv?Ffzgig8c8qI"hT &BPO|h(-]]XYaFvՀ.΍Bd@ւ䡆*hQM::k ͠@0<1[dkV/fE/@Ww7Л! W p"m̮iptJQLfOcL"NXج6#?`> `V,!RJɳjpӤF/s!>?@A'B7qw>t kJ,-3 䲿k@")D*ߕr,-tQd)H 2.NϦڪ Dڣb9OP;b7vPc!PfwghijkDWt`vcOvgwt靊KItWugvwwxyz{|}~'xbÇmw;PX)wCИs<;(`ܼ:Ѣ/z'zgwmxoNehXywJώK&gw`FʣZpP7q˲C  GWgwLJȗɟW|Tß?#'7/ \1+{; Hڷ!'7GW~ |wd} |viy"XT:,ߞ<ݬ6[~+2T_Y `կrq,(0 1$sg! BBh"ƌ7r#H(i$ʒ:LV24(@_v,&РB-j6a)ԨEc@*֬E,=0ְZ (شX۠{wU-\⽊k(u5چP߻fbخ٥b9MΗd#'Tp/|H.`Ǫ?$ew`k05ܺw7‡d&oþL9 ءUϭ;v;!4~XA;??z5dQe9hG(SHh&jͤzȌh0!x")"-"1r%G(HM uLv~Bb埑R!Qf$T $CPO?VeQWfR\>]b}eXeZUvYi 6HC 륳R>%خbeP'겐++~]pzb]l `J"o;; O<+<Wn={=uΛ>髿>BOg{֧w?oSPr< uKBaڍ~2 rN|RP m&N<$8)Ё=(B÷GNL(D#*щR\*eZ(HC*RaT5#@6ҕ.})HKϔ6,P>)P)Sw8*RKӔ1N}*T*,*VTN^*XJv&f5FՃn}+\*׹ҵv+^׽~+`+=,b2},d#+bl35*R3YR(UB+ђ=-jSղ}-lc+Ҷ-ns򶷾-p+=.ryvZ lg?gPҸ.vr.x+񒷼=/zӫ}/|+ҷ/~Mou\~ӵ43~0Vw U Z s.B,&>1S.~1c,Ӹ61s>1,!Y;vl{4 RR2-s^2,1f>3Ӭ5n~3,9ӹv3=~3@σ.4ld g釥I'юF3MsӞ4C-QԦ>5SUծ~5c-YӺֶ5s]װqL;&vE#'4& 6}mSu6-q>7ӭu~7-yӻ7}7^ojD ž ~4mRpmж-` kxOaԌ&?9S򕳼.9c.Ӽ69s>9Ѓ.F?Ω1 Jg t7=ovF=YҸ/S9)®n;.ӽv;~;/?<3Wzݩ! @"?_~YW2mB-" [X*j 0!=s=/?>3zH_H7__!YRt޲DmRzЂE-. [`Xڡ?|*`W`G 6> F`Ft_Gpa@BX @DeLgu4І) ΂,̂-,@,Bq  !jC,$n8k1hă+!fn!v~! 5\pPC hF?†!a72 :مHCB-,@A3B-B)Ȉ#>"$F$N"%V%^"&f&n"&'H(\'"**"++b$R5ȢÉ袇-bʉa )3$B- - ܂Q}6n#7v7~#88#99#:::< #*ȣ Q? p#Ğ?#@@$AA$7R xBD?DDDC>IJJ4Iiq)0)0#yܵ-4.pK$LƤL$M֤M$NN$OO$PP%Q<&dFdN&eVe^&fffnfcc c]F<fg&kk&lƦl&m^&5]f`?ma]ogf \NGgp-)L'3\g`^3X-w~'xx'yy'zz<;& ;M}'~~'5@ggԢ f` (gdg@hghg4g u~݂)l((((ƨ(֨(樎h#.e= n ).)6>)FN)(5|R fvj)ZSnsQ)›V)֩)i͎m= *&.*.)(5biJꣲh]賡 | TY****ƪ*֪*檮**+^* (2* l *q+++++ƫ+֫+櫾++,*d^),"*2,Z j H l, xsq,ȆȎ,ɖɞ,ʦʮ,˶˾,Ƭ,֬,,,-z-%-.-ӂ: dn-vd؎-ٖٞ-ڦڮ-۶۾-ƭ-֭---.bJ*.2.VvNX].fR,^l.閮.ꦮ.붮.nmb;IWSm.=Un8.//2v]">/F)/2J/fnPo2r/>'/Je/ffk֯/ޮ00EP=0Gs/W)pO!hE0 0 0 ǁ  ǰ  װ ߰ 00 ϰ 14;0 W_$1o1 k1qð Da]sFXbgEχlx wPx !0D"K68C6EG"GE& @##'#% 8Z8r <Q$r'?&( E(E.?6xC%߄..܄ P,E*E-E3-T i\Ē>{NB CcE*\AxA ;MD#2|CICsjg6k o7w78G9K9d@;qPsOMx]3T4Qd$SrAcQTC CY5PDE[XPt4|4Hs2T5|t\cE8t8l .sPд2NX v!O DNZqQoo0O9px1=AFXA;w=WW[6\S5)/EOoW ߁[Iv!r6ص]E^Q_[;3wrE0˴$9.ĴQ2PL6}3O4of8-61jۅj;3<{A*=glensV]p[B uvGE4ZsgN7Q@snvPt70x9tc{7Q 3^5Ees8|3Qw~JSGS6UUHyVԶ!|4/;wm+4Qxn;8t)4P8RdP8ӲxQ2K0#b2.?2ct*od3{?Efˏgf_}}7E kk/PZh.C6ŢmYtPzQz#!Ϻc @1#.9Ըcg^tN'(L y$01Sdz8<;9^7ŨcsH:@ kūEŬņ8d/TFQ: ;0 "! ?w25 EKE7f祱+17qvBGCŒEqU{U cź:;`7H(pFKNA y=SԼks;<g}T =ѓ'Gſ7Zqg>sCp[2wd?}/<E0?r4M(o3T8r}`?=||1Ps1Q6<> C* ˂AxEoۈ  #*H~!Li_:3>@\ /^ v"@- Fƌ\Ԩ #)dI%1$X1c)O rfLmIrdɕ: rFmƑˆsc͘7B- I?5V3hטu P!)JdvP%yviL'k:QW\564Çǁe{ 1cv2x2xqi{$V Ӂ͚6m7 %ڿWMn 5=NY:szTa~U,~u#@ naS}mHHbJi/^fcJFBP"-ɤU%țqHÈ(ȉŋJf0bK`-NJ!#A2/h(CD~[ǔl2*LG14D#ʹR+0Snwx3;))lc[,y<0~3䜳FVNS T#[Yy6C8;LS23lnZYk{һa=VÜ4hق+ .)־vI({ l\#t/jAF,y=7ԱsM'<=% $Mq#qLݤZD-/zu :|rJty˘gFTL3Cfr6,Jz7BެUH:{}:'/mj_T=peYze,33Ϝif6[wANCa#^1p8R4HVp %@:=R &GɬmSaz!: u1T8D)isX@#hy&G<:\+#\f/yyH{*ܘ!'I"K-cw=i3-Ee-S.<LM1ɶFJLW%-,3s*hV3M9sl萍a-kkDQZMjhbJ-<E4 q4:9t tNkEg]%0$Q ?:_G,YMf]_MPDWOjI9ػsx BxSFE>kc: _P5#%orU܆ųL -$ϲ0H)h@RʢnJz@ikl`kTMjT*:ˆjT!!(<긺U}uv_(V$YFohwW\꬘zNd_!2/JrCHDVDP?X(VwRADŽ M߇4C %6Qbdq0s2îs͉wխ qށAb/Jye YmrQ'rEQW9& ,`EcÞ ЃnxVwڦ}|]&2ʓft$e (@2`6[q^ghnC ¦\*{?R^7~Y_?H;YCa87Vl&[v]O1>UB:1uh-╴\:*"];}O#(1/8˜T՜j-f-w%e!|oMX4XuI6͐7{NhlG̐+􅋓trwPĭ(w<_ޕ@%DP{s}O}[#We_VW#A<^XU⎥[d9qmwjsr/Wt`N_ ԅEg[$c^emw5.W:2u7*z{W& lvEᥴ7foqg(M=|Ϫ$m c4 G$~ 5fA$5HR}x[y};^8׽o:WЁA(26. Plq= $o=- @-Ҏbr/>OE.B$/ dH,-)2\g8f/M#/ KnVC(.f 4 M0 p C" Å J }d&/O{x3FFD=/OH(Fo*6BG./Oxn`)&BzF/uu", | g# DqIMQ1UqY]a1eqSQt\ڮMײ+&Pr -=/N _Cʥ_ơL].II)~p{.ffg' 2 / "`,0@6: Tx`xa cJ:=J. N +oEQx$+1"N"&$**̑1)rr'Qb *0/d/1gQ 2, 2!!"%rY0=,F.a..la/m!($5-fb) dXdDC,ln}rN1"zdp,BR1%O)O"C!R/|8C+Ų7}\ !"#r"+r2+xqrO/}A"2C*0&0in%¬&Ls@$ 1b&˪q`# OaAq-(Q^1K*!bZ#6o6UO3L>x7-B"8͒88ْYBrj#}D-:7"YH'oFl-2I1&+HX0R`%?D“Ɠ!PS@4("^ "!@AA3QBB1L4&4t!8rŢBÅ ``ErJ0FqFG$GH=KxRBv=2q->qHu45bFSIeEO5Ws@A rKL/:niL}W#BC S-'2/- -Y̆"nt>o;P |Q/dГJu&m2E޳-* C?'$V ,1PG$ (PXUb %[ds>V%kB{X%LsXCߴ6-52uPT#oQ\TI]:?= [Q^L($,֒t\U 1[U[/vp_.=[tE?h?.Ukfp2`a=qL#`lɶlvb6_lǖ,-b4Y?EUF&g]u)Ve(dl&e]HbS(#hDV6r2HU'6 T$\ urR`aal!Cw!!wuawcvW#MX=NC"X.o`^V'$$%΁<&HW*X8&腱F1z{K^VVMbz(Drj ,7"xXr`Fh)qwG_t[4qVu1T rk.7A18x#@"O. A"`|^!"9"4%B |T @ x5%Kۤji( #6 W',1yz2zu7IU#h+!BE`VoKY׀1CÆE|kyuv@!ИZO::%b aY y ڨ!6ZP$V  9Y"4tCxcs"ў됵3F怋~y-d&/# :'2-$Y[,:g-d07s[Cg]H1@Wvr vjKdji5aWVwU"[!yMA#!,Rtz@ !C#:"@{[͚5$nbRf3T\3DD$f&65>o~*7s@RQ]]&Bz# 4#JZv0P*]3OVbm;`Avg;X[#ހ4Ÿ@il|s AOb ź6H| @LWǧ aB!'G[{g=Ǜ=ܚ1ۆB6%Ecd0^e~\ !&Dg%-I KQ-1'4|U{!nY#\a!j\BS}Ƈ:cBShm}롫7Lvk8D/(Y?_!exMb[\׉ܜ] 0}̫=ܔ+Νq%Ί89"T"zw~n}E Y JE֯YƙZו3,}L"_BoX ψ p! 0h!c;z(/Xx $Õ,[|y<2ktJ/9tp\6oX#rЕ9[ʴ'ԩ簴*RmDT,5t%CzvW++ qIČ:箼K+"{"-*@?ǁec k۾}{ {;#pI* Ѯ̙+؆C1׏ӫ3X+gUϠ,ՙ><DZDQdF QH#tRJP4]hc:!TCbbri!hYm5Xa6(RU kZ"/W MB%6-N5 eyaEd]СgdMR!Gƚ2l`-" զo\'F,h.K LJ):d,i ) F4QEeF~ !I&4 eӆ M ޺WٌHbRUieTWTMތ778.eѱ!$@o@.BHִWKi&;b/AX d`\vdmf!.TRh6okY,W8%WMRO29ÜA6a y۬љ޼ P8~LpĹNtdwKxÙ0 K)n ŀ>hi Z:isRt6:!XSQ]X7d!0~$at2ᝑ\µx/8&ח.~dz8t•lOosZXA\)fq>AF}H(E~$blM)$yݍMP'_4%~4 E)VRM<#ka'(`㒗"#0If-aKĈ.֭`m:Xz7"bkA-W©b+T9D)r7g9 [H@dy&`&B@YQ2,h"k̚VotIBֱkٖa3J24$uǔƫ>/_9bIF'!6ED Pa lAV.ѕ%-/ц[ZHxmt1}!k ON~+( 71=9tpED_ČuUXJ l"/IS{)KnzH;LKX&ԥw9KUMJ;%IFo?ɧ>Os8ݛVYn|He[&VtĽh]=zELeZ$i_WY(.5QA(cWҬ:8ZYYdMlz,t_^)F֥ h(<%: (5wƆUTyRon .Ehjqǵ"^9d%)Ӣr\|>@Qi"2` dK2L;GOia6m|kBؾhC}RUj5ۮzu©-(0A| }%HQ‹`.BKbˎ |Bx1bg K= tuӬ&ǔlKdh}Qodk K[5ɀn[e * @a. lǵ<1scr\@=j8n ]!o Mj4a^H[?=fꄃeH#s O/Jeh+ZFu'&aX* /Q$ O}UX(%@e*@@H(Vȭ-nU)P}ڽJ2P?~'N'ƴM?u%kzp fzfqh;@ b@{l952DloAb>q #6wgւ{mW!F}և+~:@;?V~Jrs NGWTtJUtUE.e>!uqcCOgu~'{6qp 1XoUpck A|t! ?$bRbȦw3r?Ahw~Q}aa`"ƒ";sxj1^s,7sC+G&/yeg<)x`'[\H[z W|m@qT1ŨH !)˘Qb yHS.wMBmQ!h"XW;5 XQ~xhfuH_dW0 V/T9}>ucuDc( h-PLjp 1A S /1ب)QэAr cW7 g `l0\2bs"mRN!#Q~ZF'濾ƄP_HC)(9X fv` !ĘV-b@)XBi1q i:Y@!z PAKW2Ϸ94H"X#tMs^Br{iS6"Z^٦~ -aUu )` `$xyHe_(g&XWU9)T@ q 1Y#v *WSZ A){lr-/aS9;2nAv鈞WetY)P-BP)hy? V) pmPXiz##ZցaaұP(pr: ȅW&*Rr>:0jN]W7 iaYfBz,!ua6(Ф6S^[ʥg'Ygjʦ0bQw2!  Qɡь"* agZR9mKA %4Jy d&jM]qS7/1,Q-j"1MS9٪:Hegm`ӪV! @@ q z q:*KFA)r *q?#bcį)'t77@d3e)Tdl~;QHeFDYɲ[ؗ]c()d1")wcW+YpX@! Vo@oPA 2 ;8,o*\azhcFeP6wK kN } 9E4GTPEږIBw]IIKqX{TZC&jtr; '` -5k{ۡE{ف1#<ʓ(šY {f rkq,!O )~jfY :T !yC:IH_sP/!) aj:;`[Nܿ `Cc7vhGNjr<\Rnj{7njҵpTkL/EhS>6p:S-{y|KO8kUr_f6KkHJ'q\{(7 襣ilUE5< 4 3@${uٛP!;mP1Q£Â]:ω+<[sҤ(~<2Q˗̗ \ 0̾LSq! Ew@C!|h5M!笉]XF׉72ʌz+^@OIyST?О[LN;"3{Kq Ab9 } <1jLAƉAҝrcl\ RZԂk3Լ]K&]ZWՖ*՗3#h#b);=!?|c)5Ǜk=+$BBr`/hI]7] qP,zkxTO>ذ)X헏 [*xkm/E}!]B)h~ݲ2缩75wl4ϝP`rD\t!˭9 ݮ'XMex,JG#\4֖:f]"Tޅ惕GT9Jc#k]SGsC.!,Rc}+}M8Q].!.&l7.><'3㜰-)q 1?ڇqN4iL]m7); gɜnhsCbD)ޥ,Ynn ۮcEQe66aK $MZubہx" `S>.GnnV.APR ٖΔ|EerʲRNGhA4U#' ð^!X0=un}/͞G]MZE.Q?!H*^M`8?e_NgYl^TsNz.EP(?WOE@C~4CwoGNXD(6C=n?D9/.mA|P /|$ <N .dC%NXC#4n(&XAÆ)pd!_.*?J(&LZ-6sbA,d+ K4̂p;,Lk! ʫ(H -̋q ,Z*&\ȽF|AȂŋPn-&j>mڔ~xSw4s會.@ g ;nQrPB !BR`6!~(Q ?M/Pt()2A#װ aI+DDԛq K |"/ LAL1. Bˌ#JTVɇLHJ)\(-i 788B!(S9܌S!fCssmY F¢~y%!:V(drj_6!iJ=F{azЧ0S*mej[(eu"=#̀YJW%+,3լZv"h\z|[JZ}"y UBt{"ɀv^/Ս}3}cFC!;ib'bxg"]w:`|z`d'}]W9QHᰐai?T&wȰ|)CG(V6 axH/yDئ!%$n54F6#l)ж" k& ]Ǹm0!D\#asD&ЅN#޴:I-5ҰvXB@'3uv8L (D=TTHޠ<,iD==O&C0D+4riG?!Dp:hŠT E㢿*Dț@-+o \C<noXw٤Rxr\ ]3zuKᾲѕNꀨ  b7;%.PM\zLn^1c9) 1p ;SG=1E:K J8 @A#0bSf)h@(*"?Rm2) ,+uEh U†<['?Όny ߼`q+n-(BRni\>ilP'RC s:C=o`g8ol?2Ody&2yCt(k:Y8+$QC})8WBA "MGHk)hȑ F(Pσbmنx$ |'7|;~#_Bh#4$[x -Cy=8ɚ[ڳ#:C >sT dI>Ѳm#d)l྇`;eK7 A9`;j~79IP0Y'*# -B l Dua|;[1:0B(Ai0>π2hS  6I ls+!$2*BXAKBXBkB¾/ , Er†rPBH$._3J)cD2AC7L2ʩ: \=% *-C;.떙 @lpċH%%3&b08X3)$Eu\ǻ#0"U\V4FXd䐕ZC 2# 8BqfOE: *@$!>BsriFԥE$IJF*@2GNOdGɊP$`;#xX1[3$aL^;ëHCEX CDDdDt ;DFa$%> ?[%2XAR A$MZrEd*  r?O\PI(2 \>*l6KK 85S$ɊʥT|ڗ;(DLdGtLtȔL(N jC}  5=\JRM:d.k̈́Pő ".H,KD4JdˉA9N Nλ 3E;' ,lt(0GG} PCE$͈@72KͪTAt v9QC0 d$udEJP\ШlP < ũJLMtIDP]S4ќ8 ,M-5 M5I ]*)bMMR\ҢhRRJ*QZB.cN 3m4eSWM@7EE/LRц5iO)CDM܋ZLԀ PT)PUL=)*%BӀT*FhITUV}UvXY98:G[ \s=\X,#9(LBNKe-6@ пq,VvҮlA0MHmN0cm-#qաij,UtlW%wxe=0{12}  I]0EXDj+5@28$]ô؋H~(=>uՌk.ILYSreJWtΚ[BnjSTl-X@QGQ50s0Z@ڋ ]$ 9L؇xEHn35Kl74]$[sVEٖPY P1YI[u?%QW\Y4̊qXc[ƕ%a7m]!-S²5vDoA0jʁ#Օ\)Q-M[m\?!(Mft(CV+++dVO P]5ekR}XٝA'+^zP)5#u(^.^mJcCC}ObrȥAf? Pڗƾ^fj)m=q r#$ ?j%j*6jbug"2"g}^&HmVmv"+"2/"-",TFk\~ӉɊlj+}--ŕk.PIN7k%kcTg[v]f ($(ii xbw>1uNЮSij'Xmw+o2v*'yBJ‡<q`VnhЍmoOlڔo}=\gl/-lWJ+a7HpWm/ r'V+yQl01ߞLZO $Bq;@M0 rn# z5c;4)W=Bg܆pz=oWv0Esۯ8}9o:+B0Q0k0O80C/0'ztVk nz]q$ фnd=;R"/੽iuf. - 9oVD^xOFj~lU ԝndD4p5_j:@k8Ho4J{K[@gstuʧY4xUyYxqwH& tN&~V߆\xv}R!(ŸHW.˗y{݅ 8jJW28*괇S78ȃ9NA/RGEVf(LzLAn]dŹG JWT ){s溗i(v{G׋o!H=3`F4o5&ho Fz $`1׏6 <0v^ Jx:~(` ~( PD)Hp&͚6o̩s<"ѢF_Ha)ӦLuY P+V IװcgJ3ڶ\6/4q"@۾jد[tŊ^lhe ֌#g0M8 }'+`Φݹs69k9[g~Wv6oz}{u*]ϗu#'T/~ƿݺ=Çd #O7aY"W}'QR5EST" gA`(R%4[lVqY%]vs r`H8 cyaEbՔ7ixբMՄ6G5 t8$if؆[]9fMY$qi6}5aeERY2ڭx㍱П*{i|f2JcB%aKtL `b[( h&N/dsfpx\1b`<+LXea2ަV5wLIesEjVNDv[n˪E'֤&Aތ{fj[(e{~E?2(w{ʇ,PeZjk12¯b1օI6+o{qəJcil_*椴 0G^ײ\@ٰ),n1q[{wP? ^/N-_8)'JXX tY*æl[F41Akș3Ƨ꫏%f5:k1+M4LrlӊsM1U8<1+r8IDu2^ sR4r&{S?'P"[-69Dfc 8Hn!IIjA$4J @el9-P'8:ڤ@v4V٧hY52:v60UJ# 0А`=7ָͬCM$ׁ,=+:aq@ZNy\Tig],wt8,p h`@e'V*D!uYS'ъfe>0[,ojYS ZJw<fq_}3SƉ^u ALT j?kF}75/zջvPD ໼ϪX>r dP }%ķbmX-UXZja27Lld::UX̉S,]tY^]da6nQ b~n,:?9oyϛ *ws< 1K:[t dc{n”2H߀b&9UY43RܡCb,V`t{*uUC?A?;1T#g;3Mnf6C uD 6NHu0s45>d.MKl\`:Ip SهE FMv@@:сtw5ɱ23@fגkK )Az1A91]Ǩҁ,|L6I\щj[#o&9)ͬ*WD"=\XWvW`[kspk'6>q=郁t\*&nӗQ;։hAٻgh5JIWqQe7c&L/%vh9>dG<;a;!A> ^˩LJ' _TAkoب 3'=@60AIDC`FLD ĄN@H`ZB<n`̈́^2\ڏiMx։(_MNlƂL([ڲ @(@̀ ,*0@`B*,]}A \]sDܳ =U JBRSA@p?!AL;@H"6DJ `vW:&r"FxO DOF)ƃfxQ2$CI] Մ1!  Eʐt4P5݄'-]x|̀F؀CXa h@6V-Zal\q"at0I!Q浀X@!^". !@E>DCKXbw"A(bJ`EbAJJ@[" ,c$=pF Ŗȸ1 AP2a@4T<%6j#Xa)LT#Vcbea@Axa)y%#9?΅stߟZ%u> b!>$DDj"+,"V GV@;H<\C'54bVH5(fDKCfdFbk2BEZlK @Lڛe]ʡ}@h$/ n(\F_H$`,a–Qcwn'x"6"a`E5.!b4.T)˚ @RZad5ދ&m 44dMcDFc&0]e&+,KB\JbDIȎ0k(&JJV$n&"By!0ԿZ~'YT*aJ4ys#t.Kvb#I%|W6Te{ ,Tcx\ԏ e}'u~敭 ^cuo%Aʘ`.9>(!J(6fF.ܨA|hd(&)&E*fdfmhPdoW)蔙MFbeMiDʊe]p)~' @A!ق \nez&:{ @ yMyؕ0ġ6׊@Z[xB-Lף*(0B8$ML(&"BȎA$DĄFh5`ĩjlH6 lDll$꘭ IM F I,1c U&S*Vg{E{f( 0zBT&y+ 8(+-F}!4E0"h$^a_G-)A@2n:BnJRnZn*hrn"(nNV.ebiH g2aR< -TIqM mz ziwB2xjX!vިٞmںki-]-^N2x^",oo op AAQJ Eg5JY"u /%뗕0[ lXT1 <0+d/liM.Kަ(x@mX$98qKSq[cqk10?W13Kp֗oQ|l[̝"D v#jhި A K >=2-@<(<벢r^C;CCtDKtd̡_xX9 U:kyMGG4<{HItJJtKKtLt3-dzH;2t4ȬS nUD#uR+R3W%3`vXVcUsuXXuYYuZZu[O@M{Ws)CXO@OOWȲH4_v` `Sddvy]$=c[8dcvfkfsvg{gvhh5[d?]2`|$BKEpRfe.Ebp`f(q7mc`[vGbc2:'xwd߁w{Awywzzw{{w||_iTyӽy_kK^?ׄhŲOi`x4xel:&r68`(,8hQgEuaTkFov,ĸ`xxy y8ط.x270î^HF&\9`hd8TdGInLx{(HvyTt^4vO5VΥ93Co y z#z+3zk@̟ GeHs_zh m_o{ popTKl[8y vzl{#{+3{;oS'{_zDr9yzt&㯦z~~o a~>jw~?P߄ u#/u{CKK+ks?R1>OEU\E~G?T̶3= 4xaB 6tbD)VCF?i +YlBI xgN;yhPC5ʳ _jTSVzkV[vlTATFR&Jk”9Qsֵ{݄ p` 6|qb~ 9Ll)t;ͼ9wbѣI6}ujՅ6eeʗ1; wnݻy r蓀c Z}yr˙7wΰ㳑A@[Kژo|xɗ7}zٷGOV:ڙ7v\?q~W|xKS3 <\Ӄ, -C o϶EM<E |]|ںKmuܑGVCtMF{<$\&ѱJ"3,ܒ.R%Jg4\6sJ24K7^~%-5ޘ=EM>U^Snmuޙ}蠅z9$e^馝~ꨥꪭ묵ޚ뮽>^~iHޛ ?_%-5ߜ=5EM?U_]eluߝ}?_襟ꭿߞ?_域ߟ X@ !,22$BCM :'( Z-AKLW((4 + $=9:433?abl W  0A!CNpb)* F9 xPdȎ#Yiq`\he 0ǟG(BVF%(`h :uC )4:„SYr8!Xc-qv+S eYۑ$Y ,\<Z0EYzئǑ/F"a#!_ ptY*ł k !]̾xy$m E",$( )1rf{@1!h,$U{7r6v>w@xBvCwEyQrwwvwvwuututtttttttttttttuuvwxyzzzzzzzzzz{}~}{||||~~$3>AHRNLGBA>p:D6;22222222222222222222222121211180M&W$pkoF^)F6Mc*-h;<]FFdXRntk|~xržqxˁҊےX*\ȰÇ#JHŋ3jȱǏ CIɓ(S\h .B͛8sɳϟ@ JѣH*]ʴӧPJJիXjJtIAKٳhӪ]˶۷pʝKݻx˷߿ LÈ-00#K~L˘3k̹ϠCMӨS^ͺװc˞M۸YGrʌc.ȓ+_μУKNسkνOӫ_{*˗_ï_~$ĀBg& 6F(Vhfv ($h(7a ᢄ0Xŋ1X<a`q=)DiH&L6PF)TViXf\v`)db0qid=Ü;(x|矀*蠄j衈&袌6裐F*餔Vj饘f馏7(;x*( *vF*무j뭸뮼+kFă>TCDVkfv- ᪺:n>,o4KC0٫,l' 7G,ԁPAq5;DN#4sӄ/^ @gw砇.褗n騧ꬷ밇%̞% ,>*q o'7 SW>}\.觯/oc,0QAh#0S`ǂ̠7z {# p|P_ W]+! n|hw@ H"HL&:Pk;}580 `aYCuXIhL6p|{ ̱amX;Qg;# BJL"F:򑐌$'IJZ̤&7Nz򓠌d-H @  0N@e\e(gIZ̥.wNǐ:;W" @ Xd2 ILcVBf4YLfҐ6nz+ F*AA8p!BІ:D'JъZͨF7юz H'ƅ4G,C HgJӚ8ͩNwSǢ|O+ԡR4-:2PTJժZXͪVծz` XJֲֵhPR:gͫ^׾ `sa2 lp(Zͬf7z hGKҚMjWֺlgKe{@~Ump%[8πMBЈNtKpF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~͇|$'|'NqDގ{ 947"OWrr|&[N>>s@PPBHOҗi3LԧNu;9Pַu_|YNvra/}]iioܧ~ '>_w,!y5}4=~wο?w%ҿ ~Wx{~''X W{ww{h@z xXg&A(؂{Wz h}xww }.Hl*(,DXFhACxL؄.0N8T~PRXZw\b(v^(`8hLWwtjpulxqXvrsw|hsy؇xqOx8p؈#GXg8oXv؉m8xvf8kXv؋H8xi8Ƹ,hV8s (iX  ӈv8s@`똎vvG h>؏7pW y #ؐ9YA Y( ,ɒp &Yyqơ+ْ-- 4iBr0<>ɓA9NɈPF)HU4.UJ[Ii@VJXɥ炤`:  s  {vrRsU,pj/WQ*Zd7P0Q~ZwPhjvJ8WZ y:cDwЪ꣢J*h*wQ pe uŠq*v{` hzKs z wUtWw庮>wj~ʮJs9:qz*poo;;o{ n |?GhEQxk K w装%x01+6碥yH]ɸ;B6+q0 D :;E*+XEr`ETPzw/wХBjshWt:҃ڳ]` T+jJ>;(J,s@w iIz&,';tpf,+Bh@ s x,qvh_`F9WQ[(XH溼;&{fȻ;&{fػĈ_[6Djk軾jlp;+fHo׹C{nɿBqPtƟYlq5ס:tkluX%پ&!\֦2|hw8ÛtB^~.ކ ">$^&~(*,.02>4^6~8:<>@B>D^FLNPR>T^V~XZ\^`b>d^clnpr>t^v~xz|~>^~舞芾>na8>^~ꨞꪾ>^~븞뺾N0^ƞĎʞnh`084~؞ھ>^~>^~p` onC ?_ "?$_&(*,.02o`P7o 9o 0=/DHJLNPR?T_VXZ\^`b?d_fhj@Roo qQDC|?_?_omp PO|0C?_ȟʿ?_؟/Bz/w/o?_ڟq5鐌%@ ҹs'A >QD-^ĘQF=~2vJG`B, LYrt4$h8T(ОEETRM>UTU^ŚUVN=2n΀j_5[TRش]ݾW\u޽ԓs4pϾL8UQ{Ycʕ-_ƜYfΝ=ZhҥMFZfum9vPyƝ[n޽}tOz#叏':[]o%Y;ݽ^x͟G^zݿ_|-muVX^4>TC0AdA0B9=ELiBC.̰ZDt%EXLE_1FgFo1GwG2H!$e,T X@H+2K-K/91S4U$c\DlM6TQZO?4PA%PCE4QEeQG4RI'-@˴:P@RSOE5UUWeUW_Tg3!>OEVZTrNO\)esse6ZiZk6[m[o7\q%\sM@EO]6,Υ^{7_}rfZxVUrXZ >8aeze ~V'_.Y0c?9dG&dOF9eWfe_9fg.Y? _8cH9h&hF:igViŗzjb5ji;l&l_zfи9Bl;oEjoڐakygy矇>z駧z>{{?|'|G?}o)`8@ЀD`@6Ё`%8A VЂ`5AvЃaExn(„'D! Ѕ&\Z:FuCЇ?b8D"шGDbD&6щOb8E*VъWbE.vы_a78F2eDϘF4P'܀c8G:юwcG>яd 9HBҐDd"HF6ґd$%9IJVҒTN4INvғe(E9JRҔDe*UJVҕe,e9KZҖe.uK^җ-!,w222211111122111111111111111122111111111111112211111111111111112211111111111111111122111161;1?0C0F0I0].t///.-0Þ1Ǔ1ň-ă,)}(y!v"r"l#{d#p[#_B"I1%/##"!        #*18 = @CFIK$N'P' W"_ g's/{8BLZ a!f"k#o$r$t$t%u&v'w(x)y+{,}17@FKNSY`glrzxspmmov{҅Ռؔٙۜܞڠؠ֡աңϤ̦ʫȰǷǼ~|{?H*\ȰÇ#JHŋ3jt(ǏB6ND "S\ɲ˗0cʜ0͛7i"d8@ Jѣ qސWR8)lca9es.➗T#zT.9M,W޺QӮ;P^TSDDb=P8G$;(S=@/Q_`x d0bCXCKE &Ga^lQm*]mr8%$"7{k.$ ׈BX!H. Hl_3qTFC0n( 40_zvm-Q20c9Hdԇ-/Gl81ڀLn2cdK>Pq֍RdJfq pG?pNl%`9yۓ?[~a!qiЃ~O CݲmJ4=h83Qrt"(qYP )3wҙx\_Hgc!2!^j:}!SӠ bBJazO9^ ,C FHkZ @T6XT#(OJY #tկxmTuuk`Va )@_?` .v|eHe`XB*S#a`#JO qkIۄv2[-Z贌 e{XB5 x[Ad,YҌY1ADnfjSdؙV jW]5sLj傏8"N)ZoP"֐ƱҾSWbˆ"8`("M1ؕZȃlNHA #J/P["9`YP=!s#Blbi*Y¦ Eȴ?F ;dT ,n Wfxw*@ΌkY lns8yYt󝋕gQ[ q}>4A+Zh0 Hz\iJ3Yo(1uZ.vs2-VYW%֎c$KikK}Z "7ν^H60qXWNYlQ)Ҕf{^hb9U0 ܯ-llzX `Zww߅ _:8¹[ǷE3k_7 &S~s +;a"L9uB9"Ɓt[ I_:] 3b9Ō\4݌qafڥQ D/v:֟p:s_#)ၮ.Dv?1wf1;I ޤ5{U, _|s c8fQBw$4 ٌyOOs`>֟-^{[LN'mh #a|Rn! W_o{'y{`31 ~zu3W5TY}ZaO~yJA t"zNWr`5p~Nч#B777 s uJW}g7uЀH4L7>S*#Wh5!,w222211111122111111111111111122111111111111112211111111111111112211111111111111111122111150>.G+O)V'\%b#g"k osvy{}{"w%o*h0c4_7\9YT@TAPBOCNDMELFKFJHIJHKGMF}NEvODpPDlPChQBfRBdS@VQ=EL<:H:1E6*F2&G-"E''Q,Y1`3f9q<|DKT^dk o#s%x'{(})~*,-/1346789:?DHLPSWZ^adhmrv}yv|p~kgc`\YV|SzQxNvKuIrGsDrBq?t:u6v2t+o"midcbd`]\\#X+g5q?}C׊JSZݬ^Աcεh˶lεpѴtҴzӳԴԳӸҼһسܮ H*\ȰÇ#JHŋ3j1Ǐ IIR$Ǔ(S\ɲ˗0c?r9ϟ@ Jtf`7YӧPJ:ѦTjʵ׋^ٳh=-!YpʝKW![˷ԻLa ≯Le .J ; |h 4j }m nkѽqh};3xqwb؋Vlsf91˛?oo˟gw^ٷwx̧*WnY\ST oگfi]0_To1${q(tr,D0 ErH4g AG|pA}Ne,;D߶So-wlӆ ~S_yնݒߠv@>|?K$Tjg .EO V D`YŇ}N!V_ Dk @O㐡7VQVl @ٸ09oXU aW&BNR! ,*_d9H8s!јF#\E 7Yl`yFq}E 9Țϐ)1G:6dw!c ,},yɏc&A;X)rCX8QdcP(]8KA'29Jo=А8qb^Lc`8:(Kp)C8 fL1')Y1 gapAZbЎ c4U(V&тQF7^n)cu/I1V s"x4!MK@ !G?7D: E!T4dD+']7P,--KLWui+UU+Pq,,8S / #mNvȭ()/B'\((42+?()㧨<CCww lNvxȠѧOB,6o f7   ,-Ȅ&]'_sDCDN׺CxS ..:D[OOBx'(B(ZEȓFhP(LB78B ((qwUUUrCQ33?NN ȓȓ+Uo,-ablB"h(PPxxH*\ȰÇ#JHŋ3Ǐi1ɓ(C\ɲ˗0cʜI3 2 ЉRe@JѣH¼7 JիXNd ։RKٕ.:p*۷p՚h܄?˷Jv +Æ&ef F% #5,W: x4%褂i !Pn0pRj8Wݗt7\Ra cz9@cF7tA:c/~uRj]zI{ &fAUlZm( C4"_5[U8ሧzpup"=p(X+&9WzE 9Cl@'Ψf1ygI ̀bC{ yb^r0%DIcUbE [Saqh!v7%zשc *YG4ꨨjԜu,j.h `dk [+6K:+B8V+msv+Z.6֫r΅_֯\lcU 0\ 7,^U1['@n|Vg:l1>3\ k`>sK}d Y 0A4Z[W+]oxuf`* Yy e@],Ͷ^*ۂv͍GN 3.GQwޓs1α褧ΒgN^2nK'ORd ;[5h`}7@WUDA hnm~BCUCԎOq~PPIaxT Gt $' A Np{$ P f aO:D&j^Cp`@\Vݐ& #xgLS[=sę4KD SMeAf1(,X_&CI1{W-pQfC9j#G*1+`F.dc%`  5 q$@.a&7)JMgdAfVf|沸U" eĐe1,0a'FԌ2'FLi4;LJI+(Le4#m=A,r`4/3r, 2wX=3#h= O0 ehYSuCbO⍢",G6CgH#ĵ I5љtyq$"&qbA>0Sth$P DhgM%HT ⨜PdijӨz DѺ50 (SN1 [! jױ,~@/].DT:pfl2©U*luPD!DL)\kҶ-h˘Vk+-9Ls+շncӜJfԵDorJ\/+)$@BA^HA ͘zBh ׿r6_P*`]3̯TBP_n@aXi5 X`$e%&gBi:o doEޗk$;ȜtrL&eL*bр!:ZCL<P a3fXbF33,(y3X=B$ vHta9Z&ixU.W!1I T1T0!mgzF1'uV Ughd/٣rvZ ,D ԯ]rlwf-鶷qK ?n{ݏiJ o7TIfX06P x .p"Pp@d pdF.p?\ @ Hg h2P` `eq $AA ^N Ƞ 8x'F$LGM.@Q14hW  {<`xF(#]OIu0G1l3| ?o]Dx_"%A޻ew)Rq/`3]@^?୏J8OCתɛ> k`v^ :Fun?SIe^Xq?Y->{,{{y}ya7|Bqr`@ pWq@yxbp7rwv'}'AB7r7gX'/L r  D|G!,22XXBCM'($#>?IKLW ,,8((444%CDN..:Ë{K33?  ablHp*,x0‡  A T|x1Í ;A4yF%AH2E/a䈓`M=}T8Sʍ"5#L>]T"MCM &W`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘7*X`VAd$i8 º죵YZ)Bn#"2x|( H uI& P,o?,$A,Pƒ<@!&R@!,O,22$dBCMp #ۚ KLWl ZZ,,87 Z_`g< *++656(j\..:k7((433?fABJ JKScڕ 53$41$ 8 8`4! *(`.V@c6z$aAƊK < 0LxA 5p aNzԉ1(9g=S)ΠM>ezӥ+JxräÊKٰ P@Xھ(u+Q]yz07|zB⁋j bMq 2+2&.$HB%F  X F!,h22$BCM'(pKLW ,,8((4DE~vɽavvCDN\()..:*'\`4-_cww33? tu O41$abl8 @A\`@>HPaC 1ND$HP"A6,(`@  (@ "(l\YvҬ`Њp J05x IN%Y/`͇ AТ5|0lk@`hfxx 2@a24% "XDh@A0 !,$U{2121212121212121212121212121212121212121212121212122222121F+G/I*Cl785"/%    $A,T@rAvAwBwBwBwBwMluuuuuttttuuvwvvvvwwwxyyz{||zxwx{}}}~~4:9999<@H]t΀UI7-.[+FWgw5*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ G͛8sɳϟ@ JѣH*]ʴӧPJJիXjJT_AKٳhӪ]˶۷pʝKݻx˷߿ LÈ]4pQ0#K~L˘3k̹ϠCMӨS^ͺװc˞M۸Yͻw˾.wWngw9⃘܄v u6nݤ](@/o'7 ߉Lχ`B·zt1>}o觯 (^>+H)XiL:'H Z̠7z^)*RX{z('0N0 gH8a7A,H@1K XS8|H*ZX̢.z` H2hL'8zp!=Qqzj̣> 8c~yBaq@9=_D'JъZ AAbGC:ODgFWҖ0LZ΁jO*'$8T@ PJԢZ)@ђ.TI1ÀVͪVծz` XJֲhMZֶp\J׺xͫ^Wn_5V-H1[ 2d'KZͬf7z hGKҚMjWֺlO ?nm[9paMr:ЍtKZͮvz xKMwQXømoo;w75nALN;'L [ΰ7{ |'0Wlbx.H5fL8αw@L"HN&;PL*[Xβܒ.{`L2hNpL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrH} su{ηNl[Opa'jO|ϸ7.is (O@Jg9gN[6Ϲwm@}.&:җZNԧ~iSXϺ{u%N͖ $nܽN;w[}i 7yo|񎏼[<7ywk}?/қ~ڤ?WԳcOzϽ+nO=O|OO;S؏i5?u?z8zx y y x8wxhwv"Xv!8&u%x*Hu).t-2ht186s5x:hs9>r=BrA8FrExJqIN(qMRpQ8V8pUxZoY^(o]bhna8fngpqntqsXxpi|Hpe؇l8lXkt׈nkXXqz؉lh|XXlXi؊ihXuh؋8vxufȸp&8"x0aظڸ؍88丌xǘ8؎ȋ8XHȊIYxɉ x g0vyS 9ѐ$ &y|*,ْtx # @ i8:)>/c8DFy[JyLٔSPR9KXVyXC\^;bydY2phnkImpoqyos9ov|ٗ~9Yyu67``ي6~И8qH901@њ4x)YY iىɛɉz@ˉI֙4qqr)9Yy虞깞ٞ9Yyh0ٟ:Zz ڠ:Zzڡ "ڠ̱i(*,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJLڤN8 0pVzXZ\ڥ^`b:dZfzhjlڦnpr:tZvzxz|ڧl e04zڨ:Zzک:Zzz00j@ګ:ZzȚʺڬ:Zzؚںڭ y: 3J抮뺮튮Tگ;[{ ۰;[{ ka " [*.02;4[6{8:<۳>@B;D[F{HJL۴NPE 9k_@8kX{V`d[f{hjl۶npr;t[v{xz|۷~;[{{ okZn˸۶y{t۹;[{ۺ+|p{ ;[{ kW˼{4{̋00;Խ;[{蛾껾۾;[{K"v P@!⛻{|`) } <\ kSܫ<5430*.02<4\6|8:<>@Bq}=AA`@>^~ ">$^&~(*1;*P8A`~/+@B>D^F~H^0NAMnO.I\^`b>d^f~hj>P^RpVx|~>^~舞芾>^~阞难Ny.NxnꄎEE`@>^~븞뺾>^~Ȟʾ>^־xpx0n^>y~>^ﻎﵾny ?_ "?$_&(*, ?02?4_68:<>#B?D_FHJLNP PVo JWoKW`^_O‡G8 Opr?JXvoxB|~:o_2x ??? o//O8/??y o )vdʿ/vo?`` //RK6DAB >QD-^ĘQF=~RH%MDRJ-]!Mh" D%KnnTPEETRM>1B?sdf]~VXe͞Eq7b5\uśW^6p&} FXbƍmK[›:ƜYfΝ=f8m~tj֭];e^2}l޽}YV-\r͝?9vOɡ_Ǟ]vn<:w͟G^zݿh|h~oO]$@ndATLA'B ÒB 7C20DG$"KD1E/TS#TUW+UV_,Wc֨f5W]\pW_- W`%֤I(6YeDe6fZ6[mA:v[oHXpU\rυ\t=U]v]xT^zu^|=T_~_S`v`.Saa'Rb/vb7>Rc?cGQdOdWNQe_egPfofwnPg.gOhhvOiNi&OjjnNkkMlvl&W.m&PmNnKooOkKGI*Iqwxxs/Vzk)I !?}̟dqߗ݇ ?$_8@ЀD`@6Ё'$ ?h` (At23~ƒ pNЀ&T dc'l Cg5D!` h E(z x1 2QD1f=ܰV50_|8FspcѨF6GB/}&,=(2я qC"Ѐ(aQ@!,T22p'(d,,ԀUU+Ԁ+DEUU;x((xx(xVKPBCM+P+ww++xyU+P+ۚPPtu+lћ)+UP(vvx(UP(P$++wx(()ɻ_UUP()o]P()jk4-KLWU-~(xx((91{{IIH _/,,8OH=-- wlxPje((4f3SKl(PP(UU+(dfyysѿZg++dݡZꣃU(xCDN'ej\U+c..:`P(UUUqij=33?U+d( jٖڕc+U 1dhhablH*\ȰÇ#JHŋȱQJ@di@\ɲ˗0cʜ0͛7a `2A%#4 Jѣ,q挹OPJJD4jׯ`&)$ibӪ]6-YoKݘo{߿楹7ÈY8ǐ.8˘UNY+,@z ѭ\*!ŀ4Q ߛavFVÐp`iCڤ@_J};A)&(/%ܻ8T v a^  &|vtex-HU@@f@&˘xi!]}P_y b8!KJ Η@ D!G #(eXJa%TP5b1@i @$&*SUp_]&tgtbTqIF*iP((A:馜jV饘9p 1`&jE7Y jP䪫R+lM6:+Np®zd0dHXj i@ ߂ҖkkZ0ƻk:;F pZC0DaABJBmVBDW+,8e0@6皃H[ƳM0t'CXk C]u'dmaKPE Px5CRBK-y'^JDB .@}☷UM>;D3K.@1|s樫iv|)E#.,sr긇%kX*EO®[`ٴv@/3[mQ`[`@}@o^/[toZ|u܎Ϭ.ǘ\jl#Ko`7E F!49!k r@!J bz W).dT:.R $-X! Ip YVC ق@Z@E*' #D)Ѓ/"W( Ѕ-ξhÇ@q =VM AqNt Y xJJ&-i )@%GI:Z0tAVĔ)L* h0%E^bD/yLGSL&d*D jD59Dfvș @ m|9ϙt:d;xr =oυsB9 \@J"QY5Bɏ~ CQ `PbFݴQ0z{7 G%-#젷" |)xrY.8(R~')PCϨA@NzĐ,mhQ3Hm$@HCr^ Xz< dlŝ[׸nu+ NZJ^0,B}%*uc[yNHv+fIZ=$hCђv=S6* 83$&( H#KD 6V ?GY8$| 1] qiuUkw F u;PCw*^(e"Q;— vbd*'DK&Kܗ( U\@Hʢ+  .pE@6A1Hbx(bu)!bؓ j,+%EA $nЃBSk)r,ky(Ln,愑:3˥5Sn9\[lbc|b%8C)s6WE6'm1mբbE3pBG`z(ΥRz.*_9lJo! Q]k^_HN]l$NhmVdu mLc[xCe>x{B CZJi "w5y~HWź98wzGJ #S\ag/޲sC\G'O>p, 68&  +tMG@!4;Ap: b^(Ĥ-M 'h , ]h&@$B .w&zߗ8`q @z‡=sMx9Jyo}{G}J'A=_}3nk :h>XhLtouW=?m_#9!3.+)$ x q h ^ O A ;4-%        " &* .1 69 =>ABD>I:N3R7T8 X: [<_>c:h6l1q."s,$v*&x()z'*{'+|&,}%-~$.#0"2 59=AGT%\*d/k3r9w>{CHPX\_chosx̅xnƮe˭_Ү]ձ\Ե^л`пacbbejlmnooprsuvź̋ΗΣͲ?H*\ȰÇ#JHŋ3jLأǏ=6CԨ(Orɲ˗0cʜIs$8q֜OUQhJѣHJ̩Sž(E uJիXd TSKنM5۷p9xk[Uw L߳ +^XaKLy㲑+ke/2\eRՂF{xytK!n޾; I1nَҹK29胧:D~En1!Xs>:}T?wsށ2^WQ^:6o]Vt41tI( V J4jǟf JoxE)YXQMW@N #<Ǥ\$VJF4ڎ IwP>ԖsWXI坝}yUշBct}Кm9t#VwW|P!jU|VŁV**ZLi`*)fΪkڊrkE;q",^VeҲHZ n} R#=CXB*R:G<7;w\&@nljQ(Lr@#.KPwt+Sݭtb&7PA$gM̉Ne&lg7pzN&'js&҈<Y7?$"!Ȋ"đS!FeCj'X%=iMn≽.}bљҥjS`Ib<(* r0ECcQ09iTMfmuSIUNm KƊVɴQTK ׮ɵ%t+ʒg|_da7FlicٌHv,F.qi",>kЊ֟f iZmQEHvzCъ𠉢-8r"l^ &ZMIAmm:jRtXn(M4o)tֈX7PnHV#_$EH\X估қP >5t˙N$-kz@`PqM9X"E"|4h;̥GD%U*o2w`B.fqR") ĺYԒw'!F22qBZf8P0Kle63S5wivsf'XWniI<3d|@i )(zFj4B iin ƿ괵>gQԗIۅ0.uKK܄JN{1e猜u P-:*jL\jΖ{kc[.>ȱ b]&ÈK (}udݲg;L'kjC()p/N OC5K|}Rq؛ `>>|/$O틳O_^#e4K?e=yYkG t(}N[ah/؅ցqk7х֏r^6>;P_4GwXW;Na pЅҎ]X=:x[qOV#Ҏc $yly #z| =9+/z @뉧~ #\7:b 篇}&O "[^ﵿ:k7]\f75dĿ 'kg6F/3z˷v|}G|} WG+Yw ۗ{x_Axt | }1{|z*cw4{8v'a "8rW+b)@˒` ?у0!,T22pgd,,+UUԀ+x;IIxUVKԀP((xwPU++--¦(UBCMyyP(xwwo=PP'({{l+ћ)x(++ȪU+ wx(Ux((Po,,$P(P(Pqs+U]PۚUkwKLWqɻ_ܛDE(ح6 /,,8]Hd$(jje++l(`xP((4l+UUxȠUU+fT()Hvdg_ݡl(PnD?ZCPx[xȠ\()'yOHCDNc+..:4-dûjwwڗeij=f~ff33? tu(xٖj-~SKfx 1Px91whzhabl(PPH*\ȰÇ#JHŋ3j "(S(ɲ˗0cʜIf0*:~ (t .Rb=H! 0A1= qV+ 4@ Qk2q+ -:ս+l̒ȫX&Yn;/}jpU)lc_(035MU=:%m8D:N3t8 Iʌl! ~p ԁB"Q &Kˊ`  >#*D(8R>`Q&Lb`vl#*47NJo9I<2O3d<IP3\$ZA OTc hCgFt,zQ4+hGј/k@ ]n*)L7SY-4<Ѵ*7UP+@jB|=`ZHUc%CXHiXe2TLh-L-ȷ|  ㊫&sX#V~mQIJdc{WȮqeӆVvXlF4 ڣ#-mN{Ԫdk_{VdUm)ko\w*nD\k)"mJ@-g6:z> Dr)y!W×AB 4u:b{^={b Ҁ݄@0*ܕrg`!0 !}!X;r9ZAn0P(LxqH QD9Bdфb0!s_wG [n^*¢.kv89kV3g@N.oݨD+HojҔvn:Y-PcǦרbTծ4cm-A|`N1\K 赯ot{رNٕY5K-VLŨ6\]l-Q%SI1wƲPoވ.YC8{˼+ n(vĹB2o\V??wx$ϑrS-mC(9fP >Ѓ>+E84CNWԣSՓzuI&JY3@@ c@`YCv oЀBjuHF1 wR{L@L7 k ﻀ ` &H`n|N?̀7%7A `K|l{]qd خ+ &]kB q!(7{DOca|ṝ# 9qpw޷wy}G JxW Ssrp}՗xvv{1ww>(hbSÑ ؠ`%03!,722 UVK+ԪU5*Ԁ+UUԀxx(xUU((x ++(P+U+P+PP Bx((P}}(р+x(PPA++Ubbx(P((UUUU !$K++(x P']s^P--B(P(%& "1]U+!D'(ϭ,,{{xyhUU+傞]('(xȠ8ԪUII*r,` Ov"E()fyyѓooZqK.&'IF-G ȮK..fd)q'tk"82UƦQ * PkPPj`n V)l@(1g^K@< "ۖ 4,Tdf-\#uL`0mhUpC)wH'Yw{7b{08}oTxއ=܋3xWNd]wɹDr*Q'*p:눹6r~\;fi9O`  cIӿ~U @@ ϖ1_V@5*\ٻ?_GL _` H^`CWA<}<@Bq-aZ@+@ ]xNvv_ZLar'HWL;&B1PS lIgf2uA0.Aro;!t@Mrդ4TmZwPc..VۗوZ2Ru79A.\_Qk΁|wepb4ep%I/jDŽq j8 .[NjU^v[DjYӭ]p}I]z%Q{&͓bٯNH m8{g6L]lk;/2pz,6wRAu#0% xoCeQI@m{To\$ԍzi^G)@,a b `@%@r xB/ LAUFGtZTIm_k 8EY ?D  p@X>՟OB]Eta7. ̀K |]g38ο^fLޘG'۫ێ`` NǀJx(XBj /(;v'K~ Em6[`C&Gr$sXFס?N\^M>G‚/yGD D>K/uA}= Wgyg~yHvTt;F !pbgop otgw8 !8m#g52!/m28@! " m`!,x22u#>?Ivutwtwvzw|}~ xCw&&2 GHS+$"))(^))5  +0($5I[\f@*\ȰÇ#JHE ȱǏ C9 Ƒ(S\reI[ʜI&˗0mɳ'C9} JT%РE*]1ӧ'J*hQjjYk#’]WKW" NU ߿ _NP"+Prp4XLRDk H("C @nCcu ٸsͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈E^(DjTZdit@6 ꨢ#jD*H뭵x+"c6۬ DFۣCR-CV n!,w/`\22BCM$x xP(KLW(x,,8>?I#PuϏ{| (yXh00p) .`pJ@@@!,j%22>?I ##KLW* ^((4 >?45I?#BCM$ 꼽Ӏ++..:x( U+33?abl9:D@ 00CX0@BpLđK~Ԉ`ď/4D&F [ִ@EΑ;yșBBŠ<+ @à 0:iSY`TaD1 ";6 LhBEA{`jKpP=!\,f 2^Lxdeʟ-<ڡӨS֮_-ejg}A0ZD}!,T111122222222222222206*6y'7]#8G!;0 9&!8$8(:,>&4I7@WKN^UTbZWe^[j_\qbazbhdifhlbs^|XUSSWY\af}fzgyhxjxnyqyt{w|~|{yy~x}x|v|mybvZrPqBn0q'rok eb_`acfkqvwwyzyxxy*=Wqx}ցՋЕНԨбʺĽ¾ôŮĪéĠͤ׬ݷ~ƅȍǘͩѺHu[߾u#JHŋ3jȱ:~ C2ɓ(S\1ȗ IM`ϟ@tSLH*͸hђKJիXʵWO;قXʨ]̋pʝ ۻx[6-^R a|+peXeʀ 众C,f508绕E^XL5eĸI-QBxmMΗf޿NsqǓkϘyVx)G}/|#uf)ٷ맘i#EB&BQ,߅gT.4!+=8-iXFt toLZh$AGw[Few~ݙVan0B QHӥdi:a2` Āi/yW`s)>LF(ucq)P>9iy9)ruF2(?4uvzaE` k:֯b*\챽Ȳ6쳁{Bkf&+k[nA${S*#kn®7lp9.5]r@ 3<g T+ao0x $&LʤO 5 J$2b",4(|@,³@mq&ļL?46FA_r)xh%\ + AΑ,=s>Jϛ}wGn_$v=3+^+Sb޳̂&\N(@X‚c""1 p =@El4r8Fvﰈ&Xβ.o9Ah\!7džwD"tٛ":@,goVFUؠZ cVrϐKWxҋh,»>w(Ob(Vհ5?fUc+n`"zĮcf;Ў XIC-;~'N[<GC!{ GNr(W0y(6a`1yOr@zg^sjHҗ;PԧN[X:AR@NhG;׽NpNxϻvD&j qO7^׆%A[ϼ7{GO[(*Tq egOϽw&LO|13O[Ͼ{ǯ}L!>5`H?ϿϿ@ 8Xx ؀` 4 ڰ؁ 8o$#*ȁ"x+-+602&<؃p* 29F<Ȅ,+XQPFxX0 ( ' 0dXfxg؂h#n(jfs؆nHPQr|؇oH y@ g `H 2p0/( 8sPq0/ h0X/H؈080qX/x/Xa؊>>1eZd3dCFe0M<6cUS@dQVcJeeL6excȈe?Ƹ3fbFfff5-r8/XXX XQk / yP ؈ !$>H2x/ЊI/( 9 I8В3)/4?8 x9(7%92')() 7Ȓs 堑xȐȕ y=ُF99/a &(`" 6`d/ 8R)H@Ɋ 0q9/p"( qcIz)F|\cW{㚲PYIR9ٛyN밚ٜYII9i&^Tj9.#y9ډ2 //y5Yٔ& ii/*4WyɟI/p0/fMSNUM?;3d> ?{I>.Ej.kBBI-,|klYP@ Y3 k@. ꗻ@pPs@lP ~^>>>@؎^ P  pG撝Qp  p*W 0?H0 + /G*pN*?$_&(*@"5p p Hm @A5Z  ULNPR?0VXPp ` N > Hs2g P r?t_vxz ~_ y@ 3z23NqVqvPwʌc W P 2oVv`  Ԑy_!,T22xU+㢢ȇԀU+___UU+Ԁ+U+UUx`+UԀ++++BCM$耪UU+Ҫ_䏏_Gw++׏wG0͋䂂鍍 ++֌_+UU00_U+++++ԻUUꚚ냃+Uiii_0WWW,,8U++wGsss˦Ux0KLWU0 CWˈ_08ĭ '(2G|||*n  _ CGwwgggG0mmm  L 'x=󠠠00N,CM#I 4ŬG".Ns) wۀUUUaR4ܑW[o.znz.{#y1+3N% `34C99%N@85@8*Iп~ӻsH pak*0AvmMc𵴦i!`? *^`0a JXi P wb 3lCL!, 8t,dȁ - WWT4+X|}c@(=~UDՂآV1A V6"H*OCȳ:p;Q!Õx PB"#$)`Y&MN  0YҔS~3,p&h.{`jP\ ^`Ss ^pg>rP'$Xf#`d|@a h4:]хY.@'Tz#h'фFOdl^y7ћ$S$ooE2a`6ZaD%dEŷRk>戫C@IS%)B"ӗ $J~xy GJzHWUbBN jYrdJUiCA* d[ 6f]`}1,\ xT_ee"D *2Oy#٩Yj:e vY z4$Sai&V&SU.BLceȩQwSH @ϼo ьdDdV3FmoLvYбo VƎJ|gUx-wd0HR]V"FzFV6z%`+<̩qik91iP12!t3Ed.gM~2d)N2芜e-s^\D:>RgbcnWPنf j͔-0ƌMt3I)hͼ򔎘a}~Rd4JV0o(B 62XŊFPZh>*Pn|pb 67;M[ݎ)RpKCgG/Cr+mFsNhZͰf]X/6Q5## p^0k-vj5k6ohP.ngW'h s_*ݍ"wlR[[9ۑzg/$om3_\yup1.:D3vt%d:)GV:ֳ~uds}pM֡vs\6aebU%rQ"; N*oSmK]ջH/rx+?H2O"aV g[u%|\z>ꮼ@h& |i!> C! }3 "8 H6q}i#Pr'u'Թ#~Lϖ5Iw~}ߧ@{W~!Qv~H g'8#^v[w}(x*W+q9Ȁ#X)؃~:h (Ȧ!TXVxXZ!E& pp Ppz; phF uȇ= [(BP  vm ЇuȈz(xȉB 䰆@gk03N RHD@@(* PxȘʸ، 8Ը\ؘؘC06<` ?PU Up Ȏ(H4 ؏ Yy} 5P~0 pGp700g 'r24W&y(*,ْ.0l294`1(`M/PoPFyG&c1S@pR9TYVyXZ\ٕ^`ٕq 4  aZ%i r).@&1!,T.:O2222222222222222222222222222221111113350;u(NG&V+%T#D3' (6"Z6zL^cmrwxxxxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwz|}~ %.9>@@AAAACFJPY`gmxwxwxywtqnmprw~z}qyawWrLyU}]lt| H0`\ȰÇ#JHŋ3jqaBCIɓ(S"˗0cl1̛8sܩ2ϟ< JH-]ʴӐ zիXׯ:*ٳh;H6۷p!e5ݻo˷W6l^j7kw+L9fTC~E[S](ӨK-Mѩc5 sh(D Nȓ+_μУKNس5ýOӫ_Ϟ|˟O_L(h& &HaF(VhfJ_ ($X,a}h4h<#Y0 $#Di9L^dC")TcXf%CL1DYdߕZ憖Ҋ,_)SqG*rgyi R! -&TLu[(YVl%t"'[rx੧}'Ih!h8ih<:ᬔI(Ϧ zL9*Ŧ*qz揓6VVh 8 '2*gxhF CNIS)£(K&>jSic ,"X-Dz`M پH'O2z9lɞK(2o[D( Lp][h-hP!†p`kV  `r;{Ivu('4[s:9*q8zrPqL5VkQ4 +su`ػu[ǑoMZNfk'\̺J;i`Fw>혢E1n3rq罫ܛaBn٘C̔ Gj^Ic$C7M?0#H74@7P/fv2@!IP㑡(Guv v\v1BD*<?)%ˀ(>0N8 5[a w(!h(!mADb #JLJdĈ'Q5ۀ@xE,n+r"/1ъeRHG ‹Al(| I̱tOij 8EqII )x,iH! 0INdN(WK4# bTTd&^K̲ İnp J]"0AbQD2! XӚ|&"ui iR ؀( PqZ8.TI[L7}Yp>ω ӃLYړ 9I}B0؇Nw V( 2a 8E0,= 72tB=T &j+B0Jl0IaEHMtq@+a[VP`+D(HU)|髣%F5L(I! c7n\.ÞT;LPJ!VbPZXj%-N3tm]eTBD)4{SS1iZOPWUk ƂcAt0mlimmo[7(%nnqenNFW7X$S-q~K*PB7(x(0Fͯ~oL۷o!{_x/O! ?Ȱ=?l E&N7\ hg^DDX:2V@f%"HF2dA0P\| @6!y8O8hN\69nvs Lg:bg.z-CjG=ecG>F;ѐIG:4ak,Zz |pԋN<!,Y22xBCM$ _A C KLWU+,,8&:$ 3CDN*? .M((4UU+H@ *\@ `0È)4"Ă3jȱE!',i")lI͛4V3 H  :BA$4(ѧ 3$j@ % *A XlYP,@Cx @n$^ZVY~4.UD@)"8Pذ8A`L2x L,ȀD#&]0 !M,TJ:J   %')*,,,.+*, - -.. /(..'7+>/F0K/Q-T*T*T*T*T(T%T$T%T(T*V*Z(_ %e"j w#(,17J~T~Y`is|sd!U#O%H(A+:.21212121212122222222222222221212124A/#z%y#yyxtqmkhgmuwwwwxxy||}}~ 3=@@ADGKRYmy邨݂҃ŇݑڋيߓH*\ȰÇ#JIMbűǏ CIɓ(Srl’@0cʜIfM5ɳϟ%[IѣH+^̸ӧPeҫXjMԯ`Êjuٳhgv)[dʝKwڦoY߿fLdߙh !}"> 2Z\kDzӨϠCMӨS^͚,4&1dɷN\)MbKݼȓ+_μУKNkٺ([bwy=U&9{n;Y_m'?t}?eyԧX޼XE^y GqevH|5 7vR߉ʤh".ޖ]sMX+5A 4r &@)DiH&L6Y$]`u7C.S[c\Yxք)Up)MTWu:?r矀i0E~U d_$fn0[᧠*uDeYS,O6 Q}6jߪH떔VZ&X#K:k&6F+z7‚%@nx;*2ƫV +μk[Ykpx-G,WlglVDyQM$J-㤣,0,4l/{692ɐt-cH'L7PG-K"_VЫ9`-dmhl]Z$h2,n|6tR1ٽ,Ō7G.WnN8Sd8.褗n騧ꬷs.n{Uo'7G/=Mbsw/o觯~/c?t䛟HƏD`:{h@Z-6R \_ /(L TЃ& !Ȓp}+̡-XȂ pD4DE-?5@k2=+r}^[PA{zhExDi2V8HN̞&<*X!)20C1vё ІY{llc<|OG=rn |d P_,7Ւ ̢%%ICpx'/<%@-%"h@ DԄ7w "v=+M0}^M$ L2&1U(ȈhDtr+KR0e3MVܦA/sC=q9lII1"-h^X ^ Kj/)D3>UEJPU_EwQBP9U]ժ:9HIzQ4:==G pBWVroh c2ikM. l'QmTWկZߋ?-;nԫYv~Q-#>j$"jMaU_ꎥ$&VQ/RhXFP]E1,6 V55%mKQH![&=d큗- L` i\5+cL}*3C %)X MN g?U?3:.ߐ0GxP t!$}A9~2Zf!`*DtSr7 K *B[&/XᒭLU'Q&CTAB$rYYNs| W4U-f<9| p =}&χJ/ZҘ6N{Ӡu:'LT!5!oBj3وwZh6%bZpڤkc;Gg[2mյӴ}r0۽_=i^6Mo[~ zP wj9i x 7nm܀owwpy7{ _q#P oo,y:N턇yQ#>X?,IoU1Mhg'wx9~6}--2HgP_1LA `<:iNn۽O:wdce08Zq9Uc$xJ`(TcѱO].Sez[%Me;TEuutu+|zYVҍʳG}ͭ>L>-S=݇B>򼗿ꞟoxo~n{|WwspWrRC{r· umg8~8HoS&x(Ӄ~#u 0R405:<؃<8>>DXA 0-hw P ]p R ]32_A !NWg RtpxzrH 0](]z8 --舯  W0P 0Xx   V € p 8X]HЋ.00( .c7  `}@ph,V 2 rЉ!,c22x_ C$K,CK.!&C FU1x/]#,JBCMl!C#곴!#UxadqxU #+x3#q7@Ap` 0lH!)(D /vR =H0%Ɋ(~hA Op(2ta0/D`AbB);HtCE 4SvP`"@@yc ,\6<RH@WB@0`X $CA ( !,dA22xBCM $x_ C ,,8+x䲳UxԻKLWUx䪥$+'(2CDN..:!,-8((433?҇xvwzabl@*\P #J!D3Vǂ~1H(<2$X`Ä.s8P *$ੳ4h0U(`HLy [V 0:@Zjׂ=ݴ¼gpE0`cǀ!0aeCٳ_ǢHQDUuC0vD0xq߷3(!q7`@ > k_8:A!Oq/O !,m"x22Ax_ CUxԻ+x$K$x+.1ԻU/],Jl,CK F 7CJB=H Cw!&C71DaU!G3P7@*\ȰÇ#:@Qŋ3jHƏ C\ȓ(S>,iR˗(Y`͍2 ɳD:wJ4@H*3RK@*MIj `կ`ÊKٳhӪ5 upʝKݻx [uL|"{X&K\S)@ϠZ2ΑC,aɧQ=׆ ,`! (|6pDޑ:p//؜s҉c>섷{]7@z@p D=A~!^`TR0Cd6 @@unAk weH HH7 } x %xW H!vlPp  E9h?Hِ 6_T~("Xx{6-@59dH܍uT=9q|8)!0`%QA@#A ;j"+k%6V@!,(z 22x Cx_%&0 Ux $ ξ !1,CK Fwx}-.8 ABL $A33:_(AS (I ?b#.MԻ((4'-5(odq 򏩮 &몥@A D B <0 Ndp#E  @>4 a $P@6_@M7vĠ? X2jԩ X:֭4 6_˖)U0XM]&`q" sHE,l` &^H` >ژB0 *( !,wxr22xyrx~ԇvtx#rwx\/| +M|Ѕm{ToyreGE ҋxπgɐx%xv5gVQr½̟yK h˛ LO4|,gl}`D7 D@M=D5P Ydl Td)d!T#lUvUe% !Ia(ЈFw(c,5ָ<xǏ@)Di=&L6PF)TViX2:vi9&Etp1ijJpԦKlq韝-'Cx ,gI(Hhq.R4X1nwEVgsSl2C|) {1zcjɺ|6|d\_S$OB|S{tx)]mS[n1:pO?<42e_L6A Bʞf=Ng"LFJ%o*+@'$oS/Sèj;Aݵ8@"∡ gH8̡w(lXauЃ%z q,tx(C$/xX@f*Y:JCH23"O$Fp ոƃ!ṛH:ʩ{ yG?"FCd$YHGBrc% yLzqȒ(GI*uL*mR򕰌,gI(r%&!^ 0IbL2f.B=IPּ6MlnOHN @JЂMBІ: 3&JъZͨF7юz HGRH.(MJWҖ0LgJӚ5d2vӞ@ PJԢHMRTHPTJժZXͪVծz]u*XJֲhMT!9p\J׺xͫ^׾`KMb:c!Zͬf7z hGKҚMjWه ⵰lgKͭnw pK!Hr:ЍtKZͮvz}"KMz|KͯzLN;'L`Rΰ7{ GL(NW0gL8v%v@L"HN&;P5A*[Xβ.{`L2hN6pL:xγ>πgGЈF3F;ѐ'MJ/:јδ7N{ӠGMRԨNWVհgMZָε_8y;VymNtmΜ59Χp3|9_z>[NƛNoW _g7Im\z= @ӄ.FQ~ 5n=θǍr]\/9ę3$|"W>wOƓ[jx ;s7Hl6[ă$_S!` ı=SS8I ۜ߼&dzYMq#\~W=͑Ft(Ni2; hrW3#q6~qWTl.lGzdz'0ngr}wynP|+V|Y! #1&a|1Q"]]S"x 3a8#!(A4({|&BV} j}p5`&yznnO8~g{2`5@ 19 hl˶=lFyԤg~lO b!1(؃I /"## |g-8'itMɘWtW2z"nʉڤ)nvx){ny ')sM2lW9ni;pTitl5P GnriԴ7z4 Ɣ{ipnMy~!i:nfh놡 ,- 1hT Xlɹnh9Z`jQZ0 B:vM;lIԥ0cJO:pyy1wk0tZvzxz|ڧ~:sʀWFTp zJRZ I.C ː 0 o9MLVY*p}V&sp"הAnĩ-᩠*j ʀ/5p@rMʚ zЪdNP.(Pu+1n:zĭM@= X`Zگ}t9jΊzGl6<{5`亯 M &*nLM Bn0 j%H6`=*LJNW1:${9O=)䴤Cl!:8˴b=0 UKW۰b 6A!y({hlj{l n p_;4Np .k9  08a !03#5z]M 7MGs4;&᲼G#7j qнpۻE2 ü9kq_̛7Nd cr઻* I0- .>23Z)!0L>#r+Ak/ S2  I {G֫ˇ0+02A*5 ۾"s{49; ⊹?F>P S}C8Ơ S/B8,\Gtd2,K>=t2Md7|>}7p9wYt4Zn106nn>Ȝ:MɫD3\/ɞ9s_S !!,7\tvsG9ۭ,P1 7;ƻvw\;ZwqK٭8}ЈF=]} "=$]&}(*,.02=4]6}8:<>@B=D]F}HJLNPR=T]V}XZ\^`b=d]f}hjlnpr=t]v}xz|~׀؂=؄]؆}؈؊،؎ْؐ=ٔ]ٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڪڬ}sR;= 56p@]}e59TF5ɉRU7p= Q5 4Me@@k]e>p u]ݚpM=m =߷]MR!,K}22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JH3jȱǏ 1ɓ(ST9ɕ0cʜ9˒4s=  Ӧ@ ʴSFtӫXFլ` PJŪ], /eKF ծ߿P6/È=pTc&lDXе`UʠٶL@V@`mT^ wPJ`  \(, ^UyL0pzZ!;]Zrw >{ٟOy?e@!,$}322BCM$ KLW,,8((4CDN..:33?abl 4 2QB1QFArD(rE&7v4 "ɓ YG-o>"Ί!XsѣH*]ʴӧP tGU סZbV,вf#Mp-_@!r*0a HrqBXp !,!22BCM$ KLW,,8((4CDN..:33?ablH *\„ #.LPE+^aǍ ?j9HeTl1g*|R`΍4]S&ǐC 1äJ6tJ!kVH`;yVؕ &5Z-@P=)ݕro(@ s]KX HجHt!, 22$BCMKLW,,8 #((4㧨   9:37  CDN..:=>?78B33?Ҭ|abl@@0@. AA%p#*xGB 0@”!hR$Y|('4CF CPFp҂ YW:=X@BȄɱ 4Hg p``һ3/8@ATh!Aj@!,  22BCMKLW,,8 #((4㧨  $ 7 9:3 CDN..:=>?78B33?ۙ'(Ҭ|ablw@A$JCo8o,EϽ |ې@}.n'7G.Wn'6ln6̲Tl89.n16w8C!?$4O9/Wogw/o觯=)q1b@A*Tp1H> HL l^87A=0Sh )@H(L W0 gH8̡wBfx R@HPH*ZX{^l0aA/qg%"76@nH:x̣> IḄBh$ D9/̤&7Nz !F-+c)9ҍ\% S d(^ 09JQ~>, ~Ӎ$4IjZ󚠔)_XBD%.Y3@ ~ @JЂKdK0s-B8ͨF7юz %{'`,I@R . D(Ӛ8ͩNwӞ@ PJԢHMRT(S1}lZ 4` XJֲhU{ZRm}O*ӂ1!^׾ `KMb:d'KZͬf7zV1lIcŽ-^ "@lgKͭnw pKMr:ЍtKn`quun7w_ Mz|K_B!"P}!_!mAf@N;'L [ΰ7{ GL(N y18αw@L"HN&;PL*[Xβ.{9- L2hN6pnL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNv v&MozAηos<]~O8= 'N`w7{\?N^֟q 0UgC\8ϹwN>|@=s>|HO]=}PԹt=?}X $ `Gz1 xC:̎ Yu|@ 4T0Cp<0?v4, ;{s?ObDž b ?@NvϗաO_=]? *o>Uy~?f|AjFx*z@vAgp'tf gNPxk' Qyxjq`3Ֆvxv!VU`{v/!wtv0}:ij7xsOXVxvS\؅\5G^8d(j`aXjŧlru p8xBW[~1LJwX'>'pht؈8Nmhu։|xl(zgX؇hk(|֋xȸiƘ،Xxh8g8x(vЄP ,vЍs"hh Q"`==Xψ3v0p/78fЄN,}'#49.0I!ٍ*h YaH.i;ׄ302ȑGh@o=?Y(MJ)!7QY&9#VW jpyv ~pp\_u&0e9vl"vIw |9~4IuIs9 =阃 I9rYjɈiٙYؚi'YYd`y?90rb'0əw֩|pGY]oI :)"'Ł0}0ٞSYcIys'Y@ *٠c0||ZhR(Jy!}@ᰑEv)F*5J> @ ,:J*c,ْQ01|@)aP\) ))*sj|ࢁ do ِtv =P`2jzPWȤ<ڄ8;IqPWj jyz[ɩŁcyo߈ OZZ% Țtj 67eZCS0ZP js!ʭ :*s:eڭ ЮrJ p$8PdȰ{rjo[{n+۱"[n!;( n% '.m+-4km1;3[:m7+9@l= ?F{lC[Gy 'y8cӸ9Š _B)_(y/|&ګCy,o,@ujrl^,uKa&G:u˓L蔃ۇz&p{{P9 暷.G'Ii ry`;;:)ٺ('' 0F6a[z"kjһ6+k{[k黾 z؋;־{ ۿf\F 6{|w6zبISlpϩ' MK;Lأo˼$Ls*ZIraʧ$*3LRps 'Xw+Lĕh A\vQ,6L99XCTg7 I<>Y|fnĒ Qr<|L /@}m7,3@BM M Ώ0 &C S}3}Lm\]Yϙ.0ooHs1r.m pK7|(ӈl쟜]Pg r '0L ,׳MdwϵҚ= ,%r"<:1|jlҌmV=-/ MPY =Gpg=]}>^~ >^~ ">$^&~(*,.hW2>4^6~8:<>@B>D^F~HJLNPR>T^V~X>P^`b>d^f~hjlnpr>t^v~xz|~0qP~舞芾>^~阞难>^~ꨞꪾꬾW0W .B^~븞뺾>^~Ȟʾ>^~؞ͮ>W .B>^~?_ ?W $/ "T(*,.02?4_68:<>@B?D_FHJ?0/ N O/Q_1N \O "`b?d_fhjlnpr?t_vxz|~?wҰZ `1^ _ "T?_?_o_1./"?_؟ڿ?_Ԑ/!O4(OKW$QD^ĘQF=~RH%MDRJ-E`0y&=}TPEB-BJ Ӥ>-8AޫWe͞EVZmݾW\uśW޶6ݳ߳r0_ƍ?Ydʕjv=_!usgQCDa?ľZlڵmƝ[n޽}\pōG|~~~>`ʭ_Ǟ]vݽ/E^o-o Ϗ9[,~0@$@D0AdA0B ', )4d ?B(BWdE_1Fg|PY\qG/G$L KI'2J)J+2K-K/3L1$+5Ď zP(2p DC33O=O?TL\(AD,PDM{P%KRM7SO?5TQG%TSOE5UUWeUW_5QE`.p[+E# 75 d%XcE6YeeWRӠtKSh+p+R,AL)J]w߅7^y祷^{7_}_8`&^ հ[tO1c'b/8c7x`-nIwZ-ϒCdILݑQV](u'9gwg:h&hF:ifiZh snS((Qk;l&lFj-p!Z N(Ygfox'xG>ygy矇>F]zo^uf|G?}g}߇?~秿~?`8@ЀD`l侵ok Ⱦ!`.ƗAvЃaE8BЄ'Da UBЅ/a e8CІ7auCЇ??0D"!"1JdAŠWbE.vы_c8F2ьgDcոF6эoc8G:юwcG>rd EA4d!\4ґd$%9IJVҒd&5INvғe(E9JRҔDe*UJVҕe,e9KZ!e.uK^җf09LbӘDf2Lf6әτf49MjVӚf6Mnvg89NrӜDg:չNvӝg<9OzӞg>O~ӟh@:PԠEhBP6ԡhD%:QVԢhF5QvԣiHE:RԤ'EiJURԥ/iLe:SԦ7iNuSԧ?jP:TըGEjRT6թOjT:UVժ-CV2ȳ mkXzUլg*±VX:Wծ:m+[ ׸կl`IW|Elb؆5|eld%;Yӭ"*Yvֳ7>ϖִlh9ZԶֵjZֶulI[ַn[0*H4p08 0Dͮq*zW,( X`:Qbs{ ;ޅ%p%;ONN$] iz+aB"vjy"X',ļ+"/Ĩ0"F `B%s5}TFn$cD@jɇ?āh;3jZαnmk^+u=lz&vZcˆv)t>[v`Nkg>mpQ9}nv.=oz7w›wRGx?Zpq\xENG/Yqw889quIkrjP]>s2yunϛo|;:@ #"ᰃL: CP:C>GhF^0 ,[g]׽qwa'k"uMk8[qoAw5u#w~]'|:'nEG&l]5ZwW'馇=)=j{;}&G'^X|;a~W$OlK~{)/K$y?#@ ,l\?tWc8E[c@ 7İX˺Kj@lphC:@ 8 7b;'4*Էó ='zk;';'$LBw[B=<#'Bw˃:{.< C($=3tC+:7C*:b<Ӻ?ADDʚ'xDtD hGDɊILLK9MZDLQB,C$T@TV,+VtX*XZ|*Z\T*\^,*^ʃ8<(:c4F)P+1e-{9 BH`^HJ`ռtxfTO%_fRSxSI`5^^VYA{T0m+;ȉ,]r,SWsSO}XiSt%d8Fx5W8c2E}E*XUT<5<5DW[,7=,ذ VYxךeHPJ}R=ՈX}YUR+5ҀRzZuY56PPp`{m{2]FxYhttӟ-T *m@=X5m9.[AeuSzmVb5W>xSV38Eܷŵ:ZV]> +E̶Et%5EUeuׅؕ٥ڵ%5EUeu%5EUeu&6FVfv =2a`؊ai=Ja[}a^᪢a>a:S-C&b2!NbZb$nz(f)^EKDs.蒮R.1;?,a-VK<:4hʯ^0;/H3?6Ot$'0  025KA?䩪Zt'|1$s21C5>b*vc\2h'(Sa23d-Se&^DB0p38^dneBrBsdDS4h4x4׶ؖ풢횲ܞJ~ᖩ6BR憩,֩v)nﶨf&o2Bvoo&K HΆj<לB>Nk+dW@0Ђ OOR4콦ANGAp Bl˦ ?0mTpbpMDCb~q/7Br\rVmh~jR)?*;0M,*-);8P/o*0)1'2B4/(*.w795+=>?}"BϧCרDW{brGHǨIa&\=eDFOgƆs}oqj{mtN3ƮvQs4r\ȥ#ltG"g̬Grun"w̢뻳^H[m,IMO_L#D\]GQ$8o?ECIpkoҵ I qj'JIǤt0ϩ0`GRxozxe*xw./wy&6h/i蕇7yrڃp)=O'2zOzƒ*V-Q˺.G/PT x$mG*+ QD@(Nl{?]q O@(G+<<gOdP_=o҃:;ʷ|||7)(G}P}׏(֗}}(}7tg7EG^oV緧o~z~Z''.365m\<5Sȅ'/^+80ۅ Z,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,irS!p2 A 'pfMxjQL.\TS)(SjԜ+ذbǒ-k,ڴjעTI$fCJ]=bgИyTO"7:Xl7s3ТG.]1%aR}7[C(fFH +܏W 0Sw,fq옮n:ڷsہG$eĮWBvQ/ϑ/p|JZO8 sNFw * : 2d`{ɶSl61*9fn5_H  +>UjP_9#=cGRX!(!ou\t,[:%ڈ5ear$_2W]$m&q~&|c۔(.a8m!abh3)cT)&f)'j)"Dgzz*u*j`!,wS2222111111221111111111111111221111111111111122111111111111111<1F/W-e,x*&$#!}yvtqk c ^ ZWTRPLD+;-6)4(3(4(7*;,>1B6G@LERMUQXQ[O^LcGjBq8u2z+|)|'}%~$&)-3;HQTTUUVXYZ\_adeefhknpsuwxy{|ݚۙۙٙ՚̟幷ǹʡѐׂqjoy~-H*\ȰÇ#JHŋ3jdǏ[6 ¨ɓ&\ɲ˗0cʜI|8slyJl JѣHNԹeOAJJիT|(*֯`ÊK`ӭ]˶۷qT%ݻx;3U] lL+^ᘈKLyc+ky嗙H4tDM4)) 0:ڪ-\zbHu e跤y&Xi_"l͟mܕOOaAqiuWogٯ:'Rzm{-z'oZhJ]$:']ф@9B4ȟ}!w3}(RnX|3:($L F@5ڑIیޡ"5epOj%Y(NJZVhnghX̗xJfFczQjZ^D行6jU-褔iEV0]JQ**qꨨj^}RDjJT뭼kD*,BZC&묟:6mCV-2B߆kng*TRnB+b" VAbc!$jAbe@LL'l5\(93!1T'1ASEHSXp?#r& R1s>3ӜG@/'sgE$_ x@R`' B` # dABw@&LB_0P`P!@Bv/, 6l8Jx|<B1~0KĘQ|,b qC,H#B/~Q~yϒ/餍p|AŊH$+=4'd#*^b" Pwl߀3^z#hQēSd&aDQe'6*ȰJ)C`H;fA- fXbMX/s9%!Ĭ# d|8'`ͰT5i-ð*p!e=obCYW1L>!Ћd5(>PNi(1!J<3 ^RrrDf9BϹ#fNl!,]KIrd+:vӜh*-wi;)@,Pu|z 9i@v@Vru^o,Ў#;xYΕ,B_er XsEk]E҇8|8/*.m*Z=p, kXpc>!!Zѥ:5UB!83`t[ép^;̙8Y3b/SpDZֵeJ j$YFmW!.Y $$L譊z)͉4-6(J5oukjs.F5Lf1X b`2X*wR$hu 28P.k)V`Eli}WbwS3ʈD1>4TZYdwI@UF$gl2}@̺"sif(k\8knu=9"osB,hY;4Eю#BXjt@Vindj{tӣb1շ422ދE:wv Rcؙ6[%/MٺV5c|k^B,KK(t85z[c nƠno[ްJCuo|JVWqW?pX1 8qM=⣺8}%q{Q|8-q~}|*9NB!WyX4Y'uK /7#EQ\"ѓn[Nυ?jNݛO@Zz|C'zAȑ $4vLvo2t%%D{ }U ts{uGu4R8| Py0wGtt((8w1u{O s+!?88)#?q>HJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8X q.d؊Њ(v01hs3ȋ,S82wi LjB،"a(ӘQ֨H*荢AP% ᎹR؍x I&Aց&R!QXHQ aq4"$Oh Qi'Sp1"%b I##"@"0"#R6#:()V2F2#I=I 9T2$r%5%[B#]b;4b&6"kbm"'q&hbG9IYCjiUٖpr9 Qvyg)iwЗ~l9RxiM9 vYtu6!Y) 9Yz0djYsj@f12fkcXx2-\tJbw3<>3DiScJٛ陂15F)5a36۩'7֚0~ɞyv s)pImijeabCa`٘ Z0i`J5 ʙʠʟ)2d4Ěg`DLԩ)1v%GyYHldX5aBJflfȣ4ᣀKe6Lem!:aNNr30Tڠ"*_ڌazc*eʋgjikZmJFeY襀yd@q:ڥ{*dAj[̰[M`[ [0"⹥Uje#˅k919ro]]9^5^թ "^*bCkeaǪm7m%`Y`e]90:vaNf0Z:Kf&疛b,f^*Bd;F`W3!R6dڤcL&NVP0SLah(ୌ)WƮkftjd~BѰ+[;ۉˉg=ʝik(%KZCV#pAPDZʲak\]:<zl%3YӪF+ Kc5fBI˫΄A[&[ߕi~)iy9vlkr 9kkȷ跘(Hhȸ踐]vC:ЈsKgtHGKgWu+VGdz緹h }mGup'wtWtxgDw{Z|g~;yGǼGyǀ7[zeǁzg3W{ {{Y{gĻxz؀W;}· |׾}}N7Sa^w>MQ[tl 轧u dN%+zy/H  XuWt&$x*ׂD6AaDKF'*1O6CZ^TޠY.N5hBAg2~~.q*.YN۩n ^5{鲬1 f8+>޳բlU^MԶ>d%C[nf^MjYٞ OyĮnY!^%j+~s('[Vtu[t{ہk3Pg'tvwsw{w{翋[z+s׼hkyW}'}[wΗNlڽek+ g{jg| ku=\v|׿tl/E}އ[ہ >~P|OmWvHÎO;d)< x+WGxÍõoƛ~<+AhOgH|2AIJ-FX˧,DHʴ<!,wS22221111112211111111111111111100....-.-3/507194:2d>:m>;9Mv׸><SO/K/sK .:/Dџ~/| :壋?~D. /`I`}vCJ?٢ HvK?rF7 ^J{>bBPQpF(d^Cz|!lxC[p .zB3F"27&FK8KkŒ V|Eq6^c^gXԄ506х/ȳ#x.8G@zp,/ QwZYا8dC)i,%#7iC"d(_F7!Ә8y>\nrleNF>, I0WK}H&sr6& u)w jSb%;$'cxNt ċɤG[/e'Ǵ|1_#\ YyPRf5z L(&*SP^dDE 1"-4WM#רMk @Qh@!*8թC5Ք x|u V ޸?,5"zA K*zUpS5TR 9xsn^aaыp ܻz2Jp < FYә3!*L2Y+ 2l#-syW^r,W̩:3Gd5+^3ڌ{AW E=<+HoO8mSXLhYon5lsh,OLkZҾzjOeӦSUzM~J,QZƴoM\[k׼fS +_s ĞYc VҰmeS־?;_-nܑyF7AyxhG쑍#~7:otCo 0YAwzhn{Ky: σx;".)/ uar{e`w>qc29NT)P\ Rsh;77 u%ƿ=z;H>}lHr}o% OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃ @P DXFC# FxHC؄O( LXU$2[hi4 \H0d5siJGl؆r0t(vAQ%QkQQ1ա8Hq!r# r8"p hy{B!ŠQ!Hȑ""%,%02Ũ;ҋ*ɘ!*Dtp$XPd%Sbq%X^WBf8wkHX&xh1؏1iY$ i ɐi 9%'IQ58 !ɐ#%Y'))ُ+-o=(sC`)Huf59T{h@k .i7)/VEw8CEE kX BCj*X3 ّ2`)=ɑBkImoqYz 8viI9| ~  ;iis1g&ؘPhIC52q3DUi/9.qF[ h ,$雊ɛ. (I*i)(>HPɑ6e IM)dIIyك-yVdVkmV` -\vșXUXXYbcYI/h1 A\ /5kM[[A *k \fUAԅ0eم/]I Q^q^%^UR^Z__V-06)W%h vb-q@aa'V19b%f%bqb1b@:d<;(:eAjM_ڹ4YfjٝrH98ȧ765(4H}Ɵv*E815C ;:7]ڦNIB#bPJQ٩9e a zꖕچ ꂿڂʂúz ʖJ*ͪjt'uVw vp*p'qxlxUp0'{$Gqvq6.Ywr"Gr _pW-x1׮4Ww7{;{>tCNzt9{9t u|TGxuiu_ aw#7vk m} rs{ww8w/NbHxڃxZuqg| n 'Yy7:{ zgoGzz z{JYH;wTV{woF|'{gwq+З|g[g٧}ǩ1MHd۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ!%!~&}>Q?N1}/y1nJ˾+{ h8q8H逎!A{UĨ.1슒h { .{P!B"B(טͨ˨!\.QؘBҍF.ѿ,a&%ZҎ]%aL\2̸;atj<&f 'qs,rLhx&i>} l|klƌ\:HulȐ86B|ҨwV |kɗښȟ̩AA2ʚO7X A᪴<R{ `_t X˜#̕2ˋȍ[~x̸͍iɍ{Ξ΅Y΋<씔Lʘʦl:l\ }&\&,ʬ,, M<%-Mm!Й+=)Yˌ˝'m\7Il5Biu:yXOXeaqYPӌw棎  ` :51\j!]3JեZ_"j01e^E_2!1@_Dɣ>Wg FwVKZa夽 9$fbW cYjb/ԧ|ͮA\ s:dɦ5ܻ͸}>*-Mܾܿݹݻ,qϭZւ-ޗI;LE-џк.m߱\+ @-ɩw)m .M ۭj MnHX uR|`|.^pj8piJsZ;q wB^Rowo@xz{7atYqTrnwz&rGBNws{=cH HU~\.]~E;c.v:0gw>zwyYky$xeQXkFkPM+o"ryxWgPK3Xs4{ .pѰ{r$'p\a{.{P|% wFpL[;g?K[{m~֋ !,w S2222111111221111111111111111221111111111111122111111111111111122111173<4D4K5P5U5X5[5]5^5_6^9\=Y@WCOWGi?|920.|*v'p%l!e^WSPMC;m2]&Q H @ 3'   *5AH!L)N1U6\/f'p! v&|69@CIH A#:%.!'$'#//AAMMXWcamjxu봵ڿ{shcbccfimp~Ɔ{tnidaYMD;1)(.?NXcmqrtx~ݗۗۗۗږۘܛߢ H*\ȰÇ#JHŋ3jȱcB0 C!X(SU˗0cʜI͛dz?RУH*]ʴӎ;}D*TѧXjʵWRVuٳhӪ]gSeʝK]a]ċ`$NZzr*9a*gX*b\pꬸS=5-*>+f&GKVkmGDv;Q2m&nL▫”vKk/ToK+pZG'차 wJ WlҬˊFlȤ~Q$LfD#&˪sV,cFyqC@眚7L$7&COg?wއϔ1/ϐ/?k2d TRnj<xZzQh .x9 3Ԩf@+*$\48cja<\3PkaL&wy gat "LZȷ)qdLlX,!qMf7ȓA#tH^h9i#"{.@H )}'EΈGq>㴰!c㒘1 3Rb$ 6q#)MiJ]Bce+C rC..i\%(_}X,f.iLcSyd\¼d5)M`zd#7KaR&1y /sz;Y:i^TÈˋ~]DcC;4z10MKӁ4oʽQԦVSUzw~5Q-kZY?)aguh ޵ mO ˆ0c[2qUcq L5:՛~X7~X!iL'>~wcgZ,$w{ [|χꁰz֙nu=QsȎ8(nh鸏O`GwP  XÐNA6Ia"U@aNˡӱ" !anB%Q(x __2 ֱ^R& VN)b)n)R$] #R&" ("Wה98Y6"H(@ BB$r$<$VaIT"Y%acY6Yq%&''tvRx#zr#'H(JrO)1)r))a)B"`*Msٜc+yybkڹtÙ95Q<ݙYyH0imYvy( ⹟AFA0c`ʠ !@3rY5ԍ A34IoMB({59d/z6oSa j7fFVʲbBjF8Fj8D_vcӤIet::i!;]qbZRj[giڦŦrVZnJx:wv & ~zzF aJ}è ᨇ 2BdS9C% 0B*A&6CbC;djDC;:aSѫ%!ETTF|J`FcJ?AG9RjmF6Uڬu~{ʮxjr *Jȯ ;c{ڦ [+ pSY@Y"3JŅt%;!u5:y1\/\UDžJ`K!&9ճ:H^->me_*_6vnzy< 7|!.eHʬV~I{o6@6Ga.Oj -S`evYFX *Jjɸ )Ii㉹ީɹDWgmעH;K˺l{a^[!m,c`4MA`-W}ϻ{3;ɽ )IiȾka[#^{{xtfЧ|u^7vv[1HXuǫۿ)y[tqzAwzwxzwxxx: k+R hy[(zOwz9|~w7.ǺT{Z+|wwG|Ƈy|7| H}ַy:ˌ܇)8lƶ;z~]GGŗCh;89M(L: HzXvGwnK+i \0~v'6y9;؃?GN'1Œw'f@tgƺ@Wu;hw\zZvL\x }_WXyG=6{ԴB"&Y31PQ)))YIV,b!PAH QkT}QT q) Y{ٕU$K##Ib#"Zݖo)  y#%<◒$]:IIr(Si % &b2dj-Ֆ%y'- '"MqLɛᛖ%Ié)4H&ZIݽm ʉ]@M Y >.KnLSZ1!M E1áJץ$ B T9Pâ|+k5599 6:-@AZEJ%H'6OZGjMX:8 s [UJk4j E sNn{}.y9-NY@"J$R5=jD.j6TTJ8DX>W:bDFC:SBzG~ոH\.~˞Nop &~N>~^nn4X屛ݞQxm; Y*ۻX[2 e\PW^إ]<]3;ƴ𕚶u_P_R_ Ƶ!.]e /=ƶd3dtW>ω@KMO߮4QS/W[]ϰY_aUgiH5sn߉pL|Xqfz/̼nҋٮ[+{khH?kO,e/oocO/EC<l~aLvXw\|e.*8L+#{uww7|W„gxˍwOMy!gQ@*{@O קCqQF=~RH%MDRJ-]ShHMyyϝu#PFxM"d%h.( V(SZmݾWܶ@uС#>&<*:*5+0*y%.n1c 5[HPW[a$k)r*v,y-|3:DKNOTY`hotx{̷ϫѦӡ֜כؚ٘ڗۖܓގڅЇʋďĶH*\ȰÇ#JHŋ3jȱǏIR ȎI8\rɗ0cʜI͛8sdO;#c2ѣH*]ʴiҟ@"JTիXjʕ#ԮKٳh~JڷpʝY˷ߍvÈ.;8ǐ#;]L˘3kH͠CMsͅAhZyDa&Pٰ&M񆦹bApMɜksG@G\9V3Nœo]tBn5^x^t߂ j&Vem p7yV&]ّg~L؛ 4⊉=U)%tz7#y!z2`,i^.bu)huh GvYI^eA! eww\udv&y']_g]5&HVPpAך@ޖv礔>էYV]iՒ**J㨨YNjSjrT+Y.+UJ klR6+2=Tf-`2FضV}+VdQئ뮻oP֫//ۈgAg"찶,|ZWl:lơb@m%srdET!I3L8(r c"? 4tHM/W3KQk|-mS9E5;cm6ZZD?=t }jMP{Mo= ۂ8%LGd[{4]=Sw0q芕z|gu./.$βW~'ߔ !H1WQo5aߑ܇/o跟y_FP˫/U @Ln V;R&@/#|B50|rIhq l OMɨ kUfBAcl WWB4} &B@24M G "T~r% VMkC!,fqhl> ` !x`: xT>Q b" F D0HpŽ IH&H&k(>R$A%-I ^#@:)2Ql#uKde+JYr%>J[r~9G$%sE cjRd (]0NQ~tBN_ $8He ЉFVगd*9@c>iNZß7G@G3L([@%Dm B@0/J dhԌ uh?qBjbsK_jD!ȴ#MiIS<}OTvM&uKcSgrjR=U/iի03 %CdNzAnq2(A+ַRYT|X/Z -,I*UKruHFa `@('#[k+1X!Oc y'!c7dվ\g6k[kנUmFTݶ htX.svBWp*]ֽe@|PjՖ]֤)%_i7wl!Trm' ݯX֤M\!r! v4H-w #4ݺO+O$BHPkZ"^,6ݎd+l̆h?dNl’d{P̹mm7ޘxWl o{wBAܺa`ӵL Unh&k}k_Kg9hy@˻ۧA @mMsQ urlǠ t=`*:H;97}[BՕWq{ˉ _/>=[l>3`tExwW{+ᵍ)~:GGɓ3sq(x{t.7s޺Dcpb8!wD u o>z9\$_ WP~!q' vE{gz\aB'iQ*{ XZG -|  xwF@qz}#8}tVk, H Hp~갃'>8[XZGDh+FhH(_2džLilqNtw9h~8^x(~ GX8g*E MXez2%(2G>?3H`H|YȀ烸 e(EbvzM }؈9}Ƿ{;h{—{7{w(UA8RH*o H8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyiQZI^`pH[ `b9fyi+mo9˜mYtaw:P zix6v7ii5јIQ%(Vá q'A b쁚Iq ! $o1!&!"%lB":'r )R2 5r#M#l&S>ҞY"CgAqPRI%)T%6BfQuP&Yh2(&o3tb'V'⹛3a"y Y("!)iw:2a,ڢgћ1 ,.4Zs0:'3j?A:6ZFJfIj٤YPj?<L:L!X:UzWB dcg ko=] _:94!2$c2(SK3\5Sg*21ce4+55P#rS1aa75JDzM7N mfC f9 qxzzBAaZE Zz*J,ÚFaw*=˺Z'תڭC:>ߚZB v2Ю{z/ 4Dag@ ĩj*AKtbzATcEK)+4I5A8?ɭnMts:4AE8`fubگ$ !D*d8A JaX;.g]Q1JCkqN=n{p׶ts{ڗzKy{+Z-6|Z+ZHBL[[[5\kV\հh&|{u].dk4BkuEgLge_ +۶GdFF6Kf&e1b+-1c.5 3IvKJ_ZڻbVsPj2[&5vtdD9;}۴u۷ lܵ,̴Lܯ!#7V̱p'3򅋶h((zq):D1|7|ŧ p|{ )QыԧEק}}'g~~w(\(Aʺ3&l*8X~P`H{(|H苗r۷ɀx2X X~H:ȃ퐅@H\'߼HJH΋hqHV؅Z <}9\enD}qI y,~(MhyiHz0ϗ ҉RxȈ(؃(!s,]tȧE|sBld8X{gf8GXiMk}px _9|~׀؂=؄]؆}؈؊،؎ْؐ=ٔ]ٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڪڬڮڰ۲=۴]۶}۸ۺۼ۾=]ܞ%)MY!(iҭ-ݎ}WwfxwgrmqCH !% A¡^'њĉa߁A yY#ˉWҜyY!Qqܙ!F#ҝ%$9##:žXX$Ie4$%-V  q)Ѡsbp]nuJ`a(1$j(U♋p)1T.wF7"xv0>13>..wN.!n`mZ~؁N7- Å˨輔됾z.:ABN;ѽOVȡu8B AԯY@Wa;^nfa>֮.﫮f"0?d9q@ Ϯt]Ů t;*U3/R QJ6(Ve- 4ή?QԾ9>+7.(Bמּ@! SMq=e􊍶HOlmMeiԭIoQFĺZ}Kp[빜ƥ OQJ' R+k5%}Xi`{aKh,b+cKcA?Pj Q?Tfg\Uo?hq^o/pro_b& #B >QD-^ĘQF=~RH%EgR%D[VZDŽ1@VEK=}TPE4e҅h2TU^ŚU+D[+.`ӧ^͞EVڤ]2ҙo2'eJ# X Tl~ ?YdR NltqTʝ= Mέ¼4Zlڵ> 4'R;\pG#vY\rͯ՝tխwuݽ[vwvyNv{Wv}/#@/ dA͒B 7$B20Dp+GD1EJD_2r1Fo/7ñG#$ȩjH#qB锔I,{RQEO'0a3dL1(314TMxd'2P XK# v4éR&-(RNDTF:ܔ"%dA@"mP+5V|CmlR44Ղv}ׂSOK5΅Vm5Zd4Yql4,RVX+R3< wr?)w܅=sőm>eZi֔vEZ+7U]hW}*TI^NE݅DM'O|?Q_xPUv|(xRV,]Tc I!qY͍0kGP ef !P1nXQWIᔴL^۵lA.hvu彤.5pl:W!ZXUz8}eVN*W'sn?͢Cgi>Gu% !,wHS22221111112211111111112222497?9E;IQJzL~WXZ\^`bcdeca_beiknstuwxhxUywDzn5xg-uc+p^+mY*jT+jR)mM%rF t>v9y3z1{0z/x/t1q3l5f7\: L4?-2&%              !*2;@ F HKI#H+D3A>5C-H%MRT WY]c$l'q)u+x.{27=D K O U \aems"v&z(|*|.z5w?rLm\fgawo^m{YaUYRSPOLDJ?G;B9;9A7F3R/X.]-\-U/B29121?>KIOLTPXT^Wg^qfwmw{wkbbehlpqvzݙܙܙݚߞߺH*\ȰÇ#JHŋ3jȱǏ 36Id#b\Vȗ0cʜI͛8s܉ϟ? ^cRϣH*]ʴӧG-8QXjʵׯ"*سhӪ]˶m©cUKݻx=\Y޿ v¾+^̸1H ;LeǐJ̹g3 Өm6H:%(! 4`JxAȓ+g`, h.Q֣VāC:C!/2/_ϾUh\BKy 駞{&L BGmţ_mP DBQ݂ ("F $_r_<$!p]P#RBϡH]}[ǝw XCK("_-, $@–5cB`b,T&{Vb Dhni!f>no*(rq堈&(C>ʹ裐>Z"EjRNZ)vz*ˁJꩨfjj٪*+ajuՊ뮼+VkQj(6SF+mGNkUܾldv+iK֚N$-B@N* r:0#/]"ȯ Â,qK>)?O1>Jà w"?M1 8/rCE ,{;3S+s:P+WBF@]\6u`ud 6pq ڭhD;ŀn⟍9M gؤ`q5+v + J ]N7eB\?ttzp@;ֳo0[V5CXf-t H† E@D7;FNzy1_G/~\f`ݷ;0d̯ [ bQ/@8]ART M)j=5 T0f,l+Ik#7&Pk1dU'01Z,d Ȗ=2%WN,&S9sS2βq2%&1f 5y]n~,qѹӆh~lJ=|{cظO{ ;v`~4|, A J4,hG=̣ѿ7oW^=zʜUsBy'6S>YΘ0SV? 3?S>AS2N>ICQ/ZA&ْ`0g3x79IZѓ@5yDYO!JLٔKP/9HVI [1);`ǣ@ eYXі> P! ;ctig閟<ؗ!y9==H@ԕ=# ɘFZRi]d? Ai@yY@$ٚ !YApAZCYi:a P Y3BH85s)5qi!aBٝzA9"͙ۉY?1!PfUtPh(IWם(iRa -uڙ;uV?aCEĉRb#fQYŞ23f1AV"> zWV涞]4+Y(IZdZ0Z0ڛ9YFH)LjBFR`TZSX-ZVڥ^N/sa[XUʦRBP pj5Yj!b<~Sdũ1*:4V#6JhʛZ*ڦ`J5Jڪ\:bz CISg>mhuhhi rjZVWkhdjjoFmAkm:6@llj%n6p?qrj[ rVn*jznnnFoPiEgwoF;pZgkW pۦokDqWH\װn!wr$m)W+7h1 חWWs@s6hJwkVtQktHjJt+gV7s+u@hu=[tbGvfohjǵWK~GP/g;[{۸;[{۹;[{ۺ;[{ۻ;r}&1)wvpwfѼxKlggd [:0WB)mZ۪k $ q'!(!|.d".؉0QB6gX&N q"bDh$qQˆR!; T8"![!{!hWh!#2mŶqWx$y{" \~h88QNxacFkK|q'h(p aھ ǃ+ǂKn|kW>9,A5˖J<@ 2&M:m2ԹJfJ}̈́,G=[zlDWYMժ*B _LL 3꟨JzOƟڽt R*ՠySʟ M*b ZЇm։*g(\-j#/E-5S< 07^]իX`ǯڭ-۵ȷ}ɳm۱۽۹ې]ο- 3lܽy\ սiнɽݚb ) ښb >*޴9[ަJݤ L]ߢ*IJ_ l mS 笻igKiVjov.[Vjq#֮kXbKtlz㴆jn&@gX&hfk&fX k{Au j;P'pH-r.o6+wqPr<[lІl#gjDkߋ nJ{u9AM{P&tU;^l4tƦNۛ^s^ dn;^qkҦiWv,1WB1;kwʫ!,wIS212222212121212122212121212121212122508/;.>-@,B,J-P.V0c0o/x.137BMZdeeffffc_ZXWWVUTڸP۲NެLۡDۗ?ڏ9؊5ׇ3׀0z5v5s8o:m (  !-%A)L*S/ Z/b,j*!q)&v()y',|&/%4$:"F!T!_!g#l%r'w)z,~/269>DKRV^fmswz}׶οضة؞ڛڙۙۙڙڙۙݙߙ݄׀~~|yyxyxz泵۵ҹ˿#H*\ȰÇ#JHŋ3jȱǏ 1qɒ$(BK!cʜI͛8sɓ9'Kh-ѣF{*]ʴӧPJЋHNʵׯ`ÊEXUYǪ]˶۷piQvF*w@U^xa:gָ$xIOTsGJEG}ޓc/zVjii|RBo2m΁q D*+fN鬸+ it'X&Ȃ &,VZ*ѯ܆+ng֥ݸ覫.DkPPN:R l _0C 7, =Pg@+ KqBlr##T,A+,/3rI AL<F?:}iIFx@\q]FW &IFAQ?d@7o42stw@cO.MTO-xwGwA]]Wx6!ԑw.sSd;~T.hx:ktp4fUg^)%Qn9IOY"'܇XoCǏ9oas|> H@T|3F G#tP$(x"Thj8Ñp "tjۂo72m86#P`Fߜ":[Ll'78ΈPTRD_9q\X|V?LQPӥh#4`PviYB08qdjq $E$|t N Xq">)J2A"HD2$'AKp!0BEnQFI0@@Vv2%ĐBZyG,\qM&ҕΔ=bde3Hh:sf-MKRe:a1Mњ,g5t>$;INyƱg7ASD?K45>R.|g:qhQWhE$ :ZR“",2,m>Aj˘o4uHMbO8 5 \WSe;R ;ЁXNe["PMU8pQT-< Bl nA \[ZXՙ`A,QQ*M+BE`{k$;ڳ%E98Kޕ|ZB2wlMn2BkWKkZ8 (G:ؠ[Ҿk{Dpb9e΁MNkwж:x,ъk{bNs=CK^ϽcAze1GdlKu 8,{fH:†wXSB5bh; o/Pņb%OėIT2XU \3 HC0)%r cݲeJ~l0C3X LEذ@3uj86G6HdE\#s(AІ E3~4#-Q4MӞ.CQ46I3SCM',Y=;W9)õ/UgWuG ~ ޶ {_֪ ~6z}?J ڎb% 7e˴qhVƸ-ѻ޹7kP~.pq^.p1t{8&W/3˒8[&򑟬&Sr@?(;ri/$Qs~D`А>agEF?+t'Ud84 "DȆ?.#UG9>w4OCj֩k>5^0G5ֱ=g>o(mXkLdy9WH뫡ԟ팿/3pOofuc8s=`~|xw 'sDvgeG5sdݶ'O Ggt[z s!r[GFgsxuG@aP4BC4繁)J4fBv 5\Z`sBEY5tC *ublfYZw89ٶѡtU\FaS:M7gĢᢗ+sn6ʡ?8}CJAڜGEBKʤIZOMSzQW:U*[JY_]:diOѤ飦k >nM3LQK^ʧQM@ @D@9Ѥ07/$BrB*6 U/dA7Wƨa> D֟*VYDa:ax}A+ʫpJMJFfD!FA֣ڨǪOjz/YXyު zz@jj *z a+[q jyc~X XڰueYkEkc9Z֩9E_1\u\ ]0[E\<@(@*L`e1{93_VR``ƣ){EMR8%b+4-ƫOЯ/N{-c1d t[qxkzѷ~+뷅[[+{kfC,ha+sFWl#}[lanZl6˨ eֆmڻv>z뤲)nʽ *Jjފڪʾ۵؛;ˬ+*stGx:zCttKtTP:U{\xuvbGvfvҠvlw n{ 8wwuw'x}xxWsg8G{, s9܀K6zgs~X t?,gHLrQ ÷ w|#Xs|j }$,}Cx}8vk@L}7~~K6~G~p<Pgx\{v"Xph3cv(Qp'vs.\{F>MޭRC7*A%>A:B%6\̫-14C ;CZN3D%īHj:N:E~šEbΫ^T:EE+|F錎D~n}i .[)Ii҉ΩYh$Wq7]UѱDJ膲++Ͻ7ŶD3_s.' 檳>=]@+^Ě.Gk.GaL[ΙCv=v1\F‰`+&bbJΧ'kNm;gnp+d@v.n%/')+o-/ߚ13?5ߙ79_;=?/Aƹ f {.JF.#?ɹ6ݍCvne-1~Um=JsC{}o/O?ߊoy=GаsF'gL%OZz'^cgvk$j )O±w^GÅux:|s< ej(.Ey_ĦGPLswzg}_z|fL|Ƈ|$(t|(}7O`>NFp0@*l0D-^ĘQF=~RH%MDRJ-)>ɴ/»l*ҴaYORJchN Boaխ.~VXe͞Ea=)ϸne*a!MJyf39Ik zիZݪUc-_ƜYfΝ#JFKMQPSSTSTSVRXQ[ NbEi>q :z/4}93C6LX7\,\#VK9+       "!$#%%'',,22<D'HB:7JhУH*]ʴӎݶѢS7(&ND;"oKFNWEo;2G2ހfhetm~ Wu%U0_(b[^E]aAÎ@6uwĄP2@Ɉ@UmHQE$FXflIsIscAQ@YwDZ)gN\DU A"6!W!mg/dVjiiz ^駍ejꩂ#tI:jjWu魼JUi,Z{VF+mDΒf{P_]r땷ˬ]kâ˕k[+ィҫ멾Y'T!@2WLNQQ?w$eTT"sD ?4SteA4I48D"̳LEtf7r1iXcur2 UJ YXaܔ a|5p#e6Sh?$Ŵ=r|}jo$P?mxPs/UጣR7.yW'䘗wrgy]#uu騫Q:M봿N׮{Gc;NoDGߔM7/BϫأT}g=G_~㗯D}Aj0O!~>A> 09"}G2pli\^9@kh AM% MU@l`B؄e(@PB}$M0͏54 ?~3t[m"Q#D)ľ #E$UWE]"! 2 @10F2h?2"q.o4> Id"D88m(<'8IZr dA hct̡ KRҔԄ96Ddm%!ISVD8@JweQK['B63$>J[2E>(n&0qMk^g%UMA >Jss.fBڹE33 5O9I<?Tr,gA' !ZhQPeb$FJ ?Ď Hgʉjrѥڂi59rb3IS wᩍj>jJORʉ^YSpnT1xL;R-VDEԫ>Z+JP|OuC@a(H8/ A)Wb[]* \~} X#dhJki%7 't֔Ug`R7v1P6`ke̒t%щP֝<{fRpOFdwlKk)DEt.ũb(-p,,AdV`b_5P:Z*V+J"C@~XP\aՒE' eZ,@@]m4Vc0GQSn J Q'8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHMJpLٔMkRN ZLȃTVZ)adؕUyWzd߀[auriP`wMvɗA{ J!dGKam  ! >q"aWk1qғ9x$I"&/R%9O2Q2%Q%Ҟ& d fbi!m2ʵ͹'{'(Z"@$[ГpI4Zg9өc #_Jc[WʫgS t#OJcKGʬC #?Jc:6ʭ2 #-Jc)ʳh5kE?qJj=QC2tJ5 ^tA% E !r@`;-B*9T?EȕdSYX+*!$ /q|:JA(a犴R' V*S^AaC˵b! dfX9sKan w.VXeo%KXpX63,o8׆cjZOc8cJ\x\  nEs7&e1z`x#C5cea`65~aK\1ZanalsBbJb{Q] cc^dx#d{ b5VM'E['+|h+ B +[j  |k; 1 !k&l(<*\,&V?&9*cpGNz s<i;qڕ/\q+2qrrNL±j=123|Rs?'Z:D7otW<-|O,GRŵZ K\&A&i!9ٱI`k(PnR! :* !W $iY%]ҝ<$$&:=.%/B%ٓjn9&j2orY *( Z(z( I(=)+r1ɛnʟ^"ꓲ*"關~ u,-L&l  +K|kxqzV5j2OsA;7+׾Uj7BZ ^7讑 tcN^.~} ^ZRJ> :+Jjkgc_[ W*SJMgr${j =@ϗް*cS^5q^&T.T0N?2q>޲9*14 7&ac?egiok/mߢoqOsuw_ET|~~{/ g5Wv Wri@>t YLŊۅ߹E3[\3fZ5h^ۼ;B3>כy7`1f1a;?k㓟J1=ݺݻc=փRpcj*ĤS^ŚUփRUXe͂:6Ymݾ%VZuSWyx^}F1ᭆ?,c%_Ɯ)嬖GF!CwT4xGj֭9cT r w$ŏf0h\8Wc]wJ oqE2__ҽoK}jQFg|_C%1w 0@{*?+;dt@CO[0AJA? ¦$( En @dEDdDg1̒FwʑG!dz$2I%Q2Ǖ2ʚI)2%*B2K/4hKL3's.2d0rM7d3M3/, O=$PCe4R RI/R,Ŵ5SOG} XvAUi*0]a5UXO݅[p5!Pr 1 b/|q &vJ?]O.IŶ'|h q⁕x v[Upf l\EaἨZ-iw_QEX(r2wpU=Gt b{&ttѕ\o\wa2`R6kXwy g~uq)Ug \tŦ D#1;iZ?gUVj]>8fy2נ2W]|`fara[ZE՝S ii9u}6Yڭgk-h[jz -r C7 oSfyeΟ;pOۊfUWVUHuVuu+`wUa%cp.@Wت]ZW:>Z=7ucuڇ=پ֙WobA0j䑇zљeҪ>9xtSߣF!,wS222211111111111111111111110000////....--,,,,5*D&X#hw vpgYJ=. ' !        k B, 2 HT_hn nk e)d6%^N*X^8Si=OrCJLBQ;W6^4m0w.},+ρ*р*~)(&$!~|{yw#u-jy㸟@JѣHԶӑҊA>JիX'2(è^ÊKl˭fJM˶۷aSA['ݻxuyjn^{ L`_ +^8KLyc+k廙/F 9 b޼I0CN۸~Z@ޤ!6PZ z4.G>IcV&sk^s7ZxW Oؤǽ}߂E.'qf yw}FXQ~nk3̐ZyެgB:xbCeaxz7 :dJ+cA-bCMg'iӁmq v?Vbi ɐ$4r6kY&XEk)SmsgOuu瞀_x)衈^Xo&-*VaQj{bꕦY*?Wj暛U믛J+Sk첅!FJA+tQvEi䦛G8d.]2S?]?kTq̤1@AO#lŰLմ@S|$KpQ4NL"o#,3/M?up/3A3DP LDPF' =Mg==E}P*Z 7ym4#&.pτMjm7AsTw|*.\72֐$MW Kw>..zɇ("㧷!/d칻:⦅NzKw`odto@̲|Ηd8ALT|} +⏯k>8:r ˻*q=v?T!b+] &V(D]2 7( 0VgUBL%<ːƶ\E%"ʗ%lӈ^hfd4$_~9$B|D)Їb-CDAQÊXN_J -rq51q R"nŪ ۃGV|3ndLbfO);:pE`xAX̋e vUj_GB).V}Xi]7`*O5jx1.QTU踮v Rnt'K '$V[b暓^ wf yEs8l Х3 ?h΃n.~[/\É4C4@ |k`V$4zRkQu0DxwĊ8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِs'Pye)1 &pI-Iy" Ui): '`Q.2`7ٓ <) AAi˦K M1h!%ȔqR2!&aӱ^8! 1B35B#;8-tE ֓$Ʊ$1N• !%T"I%%adb&QYm(NiiRqv'ڹdAYY驞EsI o`ɐt 韟 );4* Dz٠"Iba :%/b/ȡSq32060&)Cp/11>799,q#A(93=#r6 RC?IrB15U3 V`S\?sIjJKl9ٟR*zJi҄ gNF`JEF*`Pm:Lƣ*>SpŎ>Mj?qbګ3?6\h$}{ʟ0XRAsJ.R#%:)٧ĪJ7*77J䪭u 9jZ8ZdOpnw1%%/(R6-E\0%SUH"@U{EU.`U$͵U]Ua qc}W֊Xj/;fX^J\5 5ۦ16>\ރ^5eZDb=:.&` 51@^^5^%0+UR`62 ƥLaN{\{b%b&v d7ȱQX=f@^˧ ;nڟ]ZI˳=Y[N k2ٯL:Ԛ k9 [Z8AoZo])ʮWkLۡsxkw?Hk :f|؋&Xڼhkq34K<;7=﫟;Ǒ, l l \ܐ wJ!JIa HG F!JEa9 H'GG{zyޗK"><^}GMhV7|@\NohGzX' il{7 BLw 8z.`=( [G8؞:|=(ȣw1 #.y$9I6In|n<Mx7w}Džk+99 .ڷYyh|Z( |׺"by kH{̗dnvpZz HŠH勏ꌒ#eF IS=]} "=$]&}(*,.02=4]6}8:<>@B=D]F}HJLNPR=T]V]IMAd+I20Ny_N bɂ˒Xݏx={ݞ}Sa1MAȡ̑ұq=vx1}1؋٘f x!ə Q"ܨaI37# hqGJ$$!T%c" 2ywix|SmtTm-ޓ.N-c=%y ફΑ.p!:/+0 C3p&].~GSkw!⵪3W;@Z@:=,h2x@{rExBjNi~4 ][ޥϚiH^a؁1{@BX)Ii (Hz*W^6}^pB&5R+ к- UTUXsZ+;0` !~Xxtc|ua?W%Ds۴{\_pBV]Op {u^)T0m^գ~F`2rK1 vAb׳$aT8ַ?b5by~9LcK2m^{ O_ 5 kjOxo^ol~Ώ>o|X/En9OO72zr1پ׽ɍGO??V?ߞ>o hxoЏկo܏?XO?OC,zqї˗/yYxo:4@" q"=~RH%MDRJ-]SL OA,x9` 5{ q͓֎CX QH#JhՏk~VXe͞E Df񜈎<oAKnsef5At |zqV3zMYdʕ-_l'{uJ B[9{k^U]%M0[ n]QDŽ2\pSDWz~qrij-8[*Fgmu#͟G^/G4ڍ>Vg?%ڍ/+h6/-+|)z(w #maTK B/ # !,+<5G:Q ?V A\]=\;Z7X5L7K>MGSMVQZTaSiMrKyJR[hs{upnkhfeedeegjms|чՏٖؓܘۘۘܗߖ˶Пڏ~{SH*\ȰÇ#JHŋ3j\FǏ )2٦d.&7\ɲ˗0cʜI3K %Md^z@%ZѣH*]ʔ͏;1:իXjӨ&Jٳh"ʠjʝK.KNV˷߿t?}KÈ#ǐ#KȘ˘3CqϠCsd,fUO@Ou6SbKT%h H:ө(9h?9CfV> s?Kf}z2j9<)US=!}5mϿ|)g{^J-["U=-`L!KP~Na[5q8+8 8\|%tA@F#E6'=t1<&P"V䕘 9Qf`AR&n蠈&jU裐hCFj+MPvD.駤`ihꪬ*B*k&문BZ+B렻Al,AFkmTΈjiv+ fq d)Ps$ uKfF/H+p G"B Kp! SzC NbmխcYR8-*L:Ru-l`V.Ve]iS;znqU{ƠAt tFM s1ڝs[TF&n;8G7RP^ .]n]  Jnc 7A3={66pʃrz/7.]}7G~ԃ&o=9.r_v8qrzZw;qO/ t{8:Ousp{B'=iȰ-A0q1Hr;Ǯ} OpnsOpF1ѵCǹ~yGvwۣ^{ lڠl}$#|XH< LaOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXF(oPJLx&qOXGMHBq^SUhZ[HWN-х-Bfv@.!r[np8r뷆qtz8|uxk~A!&jW!f@ءܱGbA$ &8ZA _B r$Y 2Rh|! ""A"Ń"*-/bx8:#)#؇A&HbJ$9%P"%R%xA&Aa"^R&g&!..y1 2 ɐX9 I4iY# ~yI9#I!)')%Y:+ɒ)i/-d3 5f7I1;9yg?AiCEyiG=鐡9k6IiAfQ)SkOOs3iCh6;eٔ,S=<(;H:h9&ڨAKlKK N:QpAMN7MNDNAQQFZH:թ#ݤ[uE/M;U7}5Kb:WU2u kWuU Um}g,W]W-]]0&Xa>ׂS"}V@[P>^i mR*1-2.+n9^;N=>a;e(~TVIBAՁtІ^0QW务}Tn"Xg' '1joYjz>hf]"iͅ>[ϋ艎͑n『ӕN͙EpW0˺3|W C'vO;ڃᳪ t[Gkq,Ltek~;Qn{B u׵Zn`t;nd{g i+Ft']tq;R v[X]u7;tR\r+wKnw ) qGn5ğx˴ s\ yVDJ\' W{wD v N?oCe'E {z6͗G[}Z,_.:VI~8lEZ!,wS1212121212121212121212121212121212121212121211202/2/2.2.3-4-5-443<4G3V3d2y0/)y%qh_|VwRrMsHu@x#%fE]LWOVPUNTISGSDS@R<Q:P:I7@433)& %3?MW[ `! h)q7yEG S"Q#R!POLH @71+%   &!.)61<8DEHJNNTPXSbToT}TVVVWVRJI݃F؁DςJĊPV`ioxyut|䇼ߗԢί˻Ⱦø޿湭﹣ Μ֚ٙژڗؓՉ~rmhfedfhkpqwz}H*\ȰÇ#JHŋzű#GWCB,"S\ɲ˗0c.n|O,„Z[`)'BGvh-k-6xGwJMnm8K'.+5Ґ$1WSHw^!.cd~kENnSu`.ݏ#D1?A,qM/"av}_̽Xou"]1/_ui?<Yez2 Mi !RCո@oP U/ |H>(tHF0Q\$y$: _.jC_Ҥ1&цҸcF&:q8D)R 5"hC`V\Lu 18<Ө5n n|U"cvxC2b(@>,$+ B`#7Hg Q a͘r3d#;906A$+@R%'Y)0L RnF7F.uJ^J<)pYbȼa0::V)my@\qX nv+߼U lЂ,Elӛ!i{O. yNO0szCDvрnħ zv4 .3A]SX2 *y C:D1(CR2eVΐ4(H:~b.6ְ~SF6W"9 @J.9K*A:(oB+ C`HC2P+Pu986`snU Ket6,Ū2 AdU&hbe-rH/B2X*بl>A8hvm2lC 2nvL5`lN= E_7]T # Jg{yU>Q7{B/fA0@ K`׻I-#"H"7p%\:VMˆmT?ʅ ; &qu..)YȒ SR$7J 2b"C|*r̐#k9VT0̷\eal."YUsNpU!uLGQuπ3sT|N,=Y)ExY&+ IStL2ƞ3  1HZՊ&p\ښêTk쁬|) vEV͕V{ձI}Wa@D v0döa(n?i[ rpvAtn >TѰxP lo@"jIwmr7&|/Pj7!~♱855l4nj84.w\W/򱝜-nA IHY(<0F?q | 9<Pt! /b:x%4J ˘D*-BT41*@A(Z5I2F%ZY٦ҹktJv h -@zh*o0~P{bQn\16թ-zșRR4JS>bS1S]cATFeY՝]TuZUH`:F!YE^J2JDAT2:[ǖ"ҬU͵%'&C0!^UY0U& uVaob _Acqj):|j4-+8/1{83ۉ5Vh<[{F@kgV&[;+Fh 0TKI*Af[Tl߹ʵ*kFk`kJ_AjkFn+4 lmKSqҶ=jmٺm_n]K9TnBqoƋhPw8u뉛8{|;ˉk99 :[::{:kK;[Û;K*IsLv;s?'?HtwHtL}OWwP'WuE[x8a7vegjwvAyrWwMz])twxx;yW w~ywS7u;h~Iz{W{@8ׁ|&8|j,wGΗ8}^7}ׇ}W W w~' ~ yLRȌL5[{EX{)~*,׀P+e8hx"H%(|ՀW,5fz;b;2ؘǃq6Gq7tk+-`,PX X(fcʰ˲<˴\˶|˸˺˼˾<\|Ȝʼ<\|؜ڼ<\|<\q`S'WiʶxblZ|w1kHtѹpڋ"ۋra$hn)]lL*  #6Iq Fy A)BAF$m~ђ@6'@ D9&Լ#z)#>"d$D$c= f}"+""wS9r=Qv-$DR5b$AC ضlُ &t)wٕy׏d 틣݋͋ف=ڸ(۷H۶h۵۴۳۲۱ܰ(ܯHtA0Agɛ/6j-m0GŰܯ 4C--i^&Խ2K6j .kY4ُцQ f7}{~pn2n]#ީ(Hh⤈⣨Q/TA< {z-=̆C`$}F+U[J14>a STκt c^ෝ活np=[!-R9Nߊ 2e.֭Y5.~YgC~;v5<Ҫ^LeZYź뽪Y*~*A\Mߛ宵/e ]*g*aY؊ K軍1Mѱ^ `"D댈(HlMa`E{GIw(-6}u:p5M&@;Sk֞p !3Fm1>xzGϽӦdla/n@/~I&ʲP o\pv?wFn~-!G| ([qchtĒp_H/AŇP 5 w]p%}]fwf4\$ uqyŷ=weɂ cЃz[,!J$C% פB$w!xvQaBsvAH%K %ȕ&YSL5męSN=}TPm$(P!AM#xi%NiD S1*DZ.͒LyVXmݾW\uiZkj)UQ7a҄p`IaWdKIRFfΝ=MڪWT!S6NVIͶH;IWDHX2ږlMG˖C?]t_]7 $W]FɠgW,xPZ-3?>|Z0@ 0AdAi@ M!,wR8K*P)J+21212121111111111122222222<:@G?IAKBLFMNIYEbAh?mNJSOXQYSZS\Q^PbNiNnNrOxB|=ʀ8Ą<>FOZadfiijmqux{||zxurnkh˿bϼ\ԷUشPݱJ߮HFDCDDHKLWfpv|ݖؗҘ͚ğ쵩趫޹оÙΊҀzxzެݷ H*\ȰÇ#JHEk2ʁT0GICIɓ(S%9)%QNieU^%qYn%c]~)&kژhbflfpftj5gxFug|gg4hthQ>၃>j(Q-ţ^9iQx|iSnS)/)OS8^4c*ZpaB*ǙC,%.jN`Z䓲NLrGئTQI{Pmۭ%KNҫ.5kP"o 0gpt.0?fIqb^qOX rȍIM:"᠓u\*"ܩR_6"wt8xKwڮ*sܪSx#87x* H*0͍tz"̖ε-:쯧2˝Bڎ(J| ȭ9oֵ /zܒW-)S$o>+ʤ 1ףO8 0P`y TGG-'% *p+8`4XIσB9FS` *X$/7XQqyCW>$h,-8"Js^Jf 7+b?<[ъB:p}nSL O0,ٚ\!Xʌe#O8Gnq܌ 1@|B5 %?K">ׄw xO` HU|?ڪ%(GRnCqNaLhFoH%/r)BaXz(%.aHu &9(۝%pE6%G1f(.Iua'3Ny ,GV"(6C EkUKJQCeT y5$a HVҔ RX@:H6h{ Hg_&Q"UiOwY UG(6YNM}j06*SR'UZB!DFV Q׶V"`R_k,1}+YPrr,fگeyhY\V"`YiSrZpef-?VQ-KKpۦ%=go}[>+$nI;$W.Yh ]0-vsRU:>QI+ĵ. ~m{\ex{LM4=j`00 H&5 acQKpP9aaC-Ɖ?5X]?[开2 `#;VrA qaCJαit8F<CYo=X /@>Xa{g; S,Ξ#8GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhO] 2=>^w}/N^`Q/4xAAEiaLg4D!i]ml7y&pX]9ԱNs=w`ҋ Yz_ף=OoW&A Ap%B U~- "'"#W֗vgx Ȁ(~gHfgǁ~ch'(!Ȃ)OU3a$[%s)i7h,}փd!35aB84Zv\3JcLr4IkQh'NS vQZ`RfPxi.cj7.0gvfj/p.8"(v\uyu{u}uuxuhuXuHu8u(uG4Kx_x`)"PH]AaIx6:ᄦ`F,UȃɲՊⅡhattttxthtXtHt8t(tTkPb@j?jg`'!0XxdLg$iFm{V8GX%H&I\`H:IpRHJxHJt*dKP)ILGHLODPQ/Ndo4ON$9aQLeNfR9R1UU6%!%(/hvIx~蔀(HhȕQW@'?G!!ZfL%Jk T[vIJՒqYLY*\Qd;u_ǖd$dDfdHdL$dQ6-TfeXiـ]eJ%fdff)h)g gtfgp{f1f0hPhhYph-i@B;DK #v&v(v*v-v(,2k4wXZ\۵^`b;d[5f$o6FHK69KXY2Kyu KMtL*nX2"NZwŷoiu0QQT89u<)SASfۺ;+&hIZZtTOٗ  X \jX!,wS2222111111111111111100////..---/,:,C,S,])l('z&u&v#p ke_\ZVQJE;3,u)h&^SJ= *  ! )6=!D'H,J/M6Q;UBX@a ;q/|'('" (#,$/&4+;4C?KHROVRWPZK^EaAm;w6}.Ճ(ц)Ή,Ќ.ؑ29BIMSVX\^ټadfhhhjjouƅŔţöyogbcgnsιӬסٛڙۗۖܓݎvz{ۈф̇ŋͺH*\ȰÇ#JHŋhȑ Ə C 'ɓ&\ɲ˗0cʜp͛81'JѣH!ӈ?Q }JիXa.u`}[]2_LE~_tύC}R DMNS&E3hM9=4GI &{ͬhG? ŌJ)ERE+Vt%PH  f1JxR71݋^,+BlؙҲC+Xѳj2P ڢ`\:&mlek2w3ِZE,$%MzA Ak׾*j Q C(DKq a c)@v 7UkQWwPe6%_Ll\qbXBT[0f3d/h4iO}c:#(=~b?-2Nz38r#z/xr @e>F_)@%.3] ( 2ol79xƸ⠝ˌg/uL,= EpN]BB[ЌPͲH܂3Tzi4Y>Bj;BƘw4% 5ѵ4}YXZM-%QvWAvA,VŸ;׸ύis>k=xYyoF Ȱ{ i(1Ck _L+xL.~k%?N-cf$.'LȫdTr|nܙ•o%I+&?qwx#!ahȺv?"ԁ, ELgA vsgb]cԇ!p=#vwB:)hb1WTv5tErzX27 2c2 :20`T3!'14**4+'Nw$S3pwqF5ZB#d"*@jj6g#16Y7Q S:y錇s~GYYhegJ9iz(Ah 11= =B)' A0=޳3>SjyqT0?ؖjYSa)Z«  5Atdy"[:B]cwQn-4~eᩩ(Ah(@h*ȭsXHڌDxZ*TH*+oST!Te ^qTTWVU[5^ `5`ud%k$W!WUWȅW0krWV [8XmEYvCEKE0gsZa1Z[ +,Z gT][]L]ҡ=~eP^AۣQS8_`e^m5mԶ561FU{x\`sr[yb+ȶlѷhiȺf(keIɻdộ+sajv >ekky[qֵkKcaalkp٫41W7ZWmU+4˿[8qÈp, (++{+ll\!L#h3q'7t :yVWuSuzqvxf'{j{E<E6H$vwwwGGwݰxMX{Wxa/(y6yqy04ġvI%zǽ熰wiW{k{al~TH|DtkבW}zgvᗆ緺~7dO51<]HwfgvGɪLuw{jxw,{ W܅#S1|UفT x{tL'8l}ǂ.˻,\cƿU|R0i8ihఄCzRHVZXg`,1LG,/zluvq8ytuvhvxØ,Y!Ơ "=$]&}(*,.02=4]6}8:<>@B=D]F}HJLNPR=T]V}XZ\^`b=d*/B"_!$q +aѺ%|ks[sxr¸⦑y،#dqi+!0& s`<1Qqf5ה QQ&ۓ]+"a AmbR~ " Ru $7܋mٓ}y#%(=RءWyI%сqM=&e*l""-ٚނmLںY"w4)9GiOؑN . %!0E#`-@6 J1> -=*TZr12e?Ί',1'*3d;?4r44MþSW5K5JziV6OJ Yh&vإ޿b:7^$B'.'~qN^+ ,caji;J,*[r@N?Jr?alc>B3~ؤ@˺%ӪDjLnsM׎2%+.^4?~j^vRyD Ό Ǩ޺ ?=SA52[!ITT˲*U ki;Otez%BӾ3qY5o?.UkZӀZ~\KCo%@\Z=W o vUW_>[c2V!+` a&x2jZ"{A|/(?on&鏏JΈ2_/K2a_5o0ۋP7U!o_y뾑>lٺ>X_ĸ?~ ҩ|h/I2@@ DPB >QD-^Ęqi9~D@GHrDZɒWv^uvf7c='pϠ|`pUTU^ڰeIE:Ah%̬SiԕM݆Kt(wB @`EXbƍu`}Ė-r`/Cv<@`&mp\t558O,l8gh޽}%#X;vpU[&hɎ>›4#}mlK_%V Mjbm)ݜo)d N,/,'??1$# 9T$9#PCAP $<3m@(PD#DIJOE Dcr%( i B(83N9L%@J-3+c#K 27q4SMsS%POG%T,T UCy !,wS2222111111221111111111111111221111111111111122111111111100000000////122537485<383826150403/3.u2,b.,S-+A+11(:,#B(;%!0#*"+$& / = "@ (A 1<<7C7G8J4 M2 O2 Q4 T/Z,a*h(%r&&u%'w#(x(y)z)z*|*}+~.4; CLQTV Z ^ekqu#y(}+05@LW`iosusqonmlkjjmn|rruqxgid^`MX?O1C/@.>4=77811,-&' $$00>>HHPKRRSSSRUQXP[N^McFiLsBLt+}^tJN??0BɮVmuˆ"&kב_M[h-6^y[q[wewlLwh%گ2 Rn!>ya#r' c*?=堇>:|v:Ϟ {N߾\g~{,y<&;C;c:w?WokKܾׯp=AwB 4 5)3A dǂ2` niؿL' 0Tl" ah7. {ڻLN}p v38CްxV;i`f) ш#Db $+b8bsahx%C,#\8o1g쌇 Pot *Ro dEa<  =G|(@:`'.#(*Y%Q *,cyU2l\A^ˀH4DC@ )cI5dqL dӝjbkd9.-'?ť%s*014P}h"*ڏv=ygWٗgv旽yei*u<{2C\\곷-T~t69S]\y%]HuG/)1|˩H=}dW. dm(#Sb7\/v=a_w:az3_XQzyY756l7˦6 n{ͦtA|7^7GmWTyT倞w#"؂(Ȃ0gw28 Qio8h37؃[ǃ@BkGkIkKkMkOkQxkdJ[c@Dy?8BADb8|/`$JB14Cxt|i>AbCdfDHzOJRTFVTD|k(FTGx_(DsIo(5TI1H.dHID$Jhm4 E䊯$8px>8(}8ShkXkHk8k(kkkjjjj'R*H}4(E5ȋTRh}x }8X+N}G8'zogY|؃ոjjjj yj ij YjIj9j)jj jiiii!iDY*ZuYuZt&^e*e~XEZv][\Z%^ހ\\^JY]ec=]]J9U^p^η^^If5Zg_6`Foc!:  q9Ca#6 ca!a#Vb'bwo\vn&c@cU\8cLccA6dEoIdnf R TfeeZ&YLefcVfnf[֙p&gv[vf*xP{gnohVyșʹٜ9Yyؙٝ9Yy虞깞ٞ9Yyٟ:Zz~  9v`I4:PIj3a ΀ +Z3,*0ڢ/J1z Gw AqHhq qar!g4JJ'qё.WR857' :<.FHBW EH tn!R'!u!ZwSj^`",Bv#(rvxlv?bA"wpFs*9:`Z m:j ʩJZʪJ jʝȈThz@X!6,`eC,6;Ŏ&Z7ǭV.{8.yzR(zǚo`&9t v`w`## Jiº )zz|+o) 6P*Ǧ6+ڮ%ہTV8o8+yԩڰNJɴKiZY]өU 1a[ basT\ (phGnXz/QBDq QB4{+*Ć븇HGzK2Ĺ{Dgx JI8JĊ ` `D(;P Rod [fk+Kz;|+3!7Iqv+ۻXQnۼ1^w"K⻴;+Kk ̿  ܜLlSYZY2 Z/ 2~; [@ @eEIH/f<]]e*e@^Ֆ햣_M*)E*iřF`[*jc&auaO xyazaZ! ib(K'f;b5F/3Vca^Q)dD&ơ#jMk)^elvUbFf؅oz O)^sYْkg՛!j ?!?,l22$BCM KLW,,8/((4fCDN..:33? habl@A<8PB>,p"ň 2 b2(PA?_>[ATELHHHEE5522222222222222222121}~|~~~',/4BU`dfgfefozyywxvvtuqqSNDDBC@B13'('('(''''(%%!'/'A,K=KIMMRMUKUKVKVKaYzx}}|{yyyyyyxxwwtyL wwvvvvvvr/|7<=958EWhqrqpprtokykwouniggggiy˿yH*\Ȑ࿇eIHŋ3jXaÏ CIɓ(S\ɲ˗0cʜI͛7DOBmJ"<.ځ(ӧPJJTlʵVr6MpgXYq8뵭[Q|YUӮ+soҭR/Cj=8WN>4E3kxt#B;pBPJ(Yr668[ āmSm_!^>"6c8qc+xm|C<b] =j[v};]y>207%Tb#?+C{_%aA]NX*l&"DiYwf{ $jDjX RJ[pG2 'ٍ톒u B)k!6tMW?C"ԥneHz9x@\1$}]dK rClԓ!>Q? >ё QXz aNta#XbF'"f6}Nurh3 ts/t$AlBhY;~H內?ΓO tTbBeBckRѲG+ | I\Ҿ*}*F±fF<`(Q"!N2\T(|م~@l}wS! V:{[YBbD) <ЉƱ sZ/]3 KW;8 *8`A%fĸ\J4 hBqSۇEى*$]Hnj #5sd7KsbCHx$=ڊwcUp!:?&g2zD60y /p;(E|]*hVQX͐H*o 9sBcBFz9d`ô94ɞI 7ؽI dFpIM6h@ta"$YOKʧV#9=BDo=am%n" "&BZl v"EZУ Hyd$e:5 vIu65kfGaxPԢBaDSwEyb07>H7 ȧ|gI|gkr[́w@E}ekXk5t4wyGyVS&<`[&s~_l*`"Sly:C-(n0j%lx/hJz0&c6{ IqI7_xvYR| !> w"ϗ*$,Z`'Z}C@"5!A{>7'I.jq~@}'(~w57`t?(GnX6-q,9M'd0QReݑ{O7ReGpoIևrZ<rd&a"ev;}xvB ȉsU9S焊eMVGLpo[*݁7f(^GpuX?&Aq=%BAXD᱉~syhs?`Ar~c}j$IH=AMFa۸c.YQf/?qOwP=HG\^UDxi(kHmHt| D1$aw!.x%xX28,ߧ(i`pnh4wĎ8`㓞H u-rXs{i6уnF$ƥ_.:闱TE{1bFdlQXhdW 1:XbX"Bj`+yK4)I<99-LQ>Gh(q-~c;[kAIEi .U(|A2. ({IS`$1RehY GNc"q/Ĝq$8̃ q;ۙ[sYͦwB'4s2 Q(Ky/X/SIǟՙ-dآzQ ٠Q8# t(JSr!ڋO$ZIL1IH>Ȟv"@"0@ny1yY@KT?"I$M)a* ج}꧑s>Rg.AC3"fz>/IzEh0m7`G)Nb'zK×"ťĐ|0_akE 6R^GX"'p/º\'!,d[QhQ);r|%@"'K$9kb³fPCDFk$ٲ4e aE]iUKj@PP  Y;|)@ X+(9cfQ9nz, :2I !I#*KKс{;jUH³Nbު<q1mvR{1V vQq:; лKp0?#a|X0L"PÓ`15|S@kܻ,wЉBwK>!`El Kۈ`;@5* :o DDm/_c mrE$>%oJ?s7e[¾{'k#02,mی[8>+4W&kvPedhM,,kpul9] @ϸj5=[ dLLW{=K>Isr!HTWt\v\x{fc_X~ p„L&p ̛| Wt댵, u,^ë:ʯ`hsNʙ{V\-:,ܑENx\Pr@ !?̛v3<&!ZEL#4 0Άlg)0 c[K{imTzoӶ tgϜ ,ʩ; =Ѓ[]~Y!urZZaAFcgH4ߑe(Dt1o"q9,-Ψ #B 1< pZ[lBU%2j0>x=+4׍4k`]r$T6Ut >glqaQW64I<=ȡ߈L&c&g %xM5*derm0#!g-Gm[o.y*'nEBZXlqj'VV`0( ~"5vrC}3]&#^2!G~. #<5rte/LGwؒe>l= ax>qj$Z-X`׮%oW[t[Dcᎊ8CS!MuS2@-'߂qK1ǫ] )T7[)Wo゘k^,mB IEmgk^8.nVs1zq13V/)Q%G_7I aoҡM-=y7P}]rޛĒSzs@-Lj4N,ӂ k@X.qZe׿M/QC@8Xp =x1@-^(p0%N`G2DxRAr2eIJ#JcByfF^gK "dD%J.%RΚ "+\G$Z$q؝cE݉V挩b}:,XF5AbY{Y֚[mK$tv-Y@g,9l=% |BsŻW6YŎWvݞKч-<~R~˖U҉⡒̠jˆ#.LZ譌JKR( 0Fb/<2H0P(l&,$-XtLr pLS-Jmz@۲ܺ);߂8DR[<>2ɿRj 2@BP0#VKL~ʈ >0qF1K#ばHnxDGYh"TIpyR(dAݸ/LW";TŖ,zO45;7S 2?Tt8]GT^bʨ33E[m8ȠEt=N t@H%$*2eTZ@9y`P)Q^`e2(KL?=5g,kU[#Ir&RΪZh2hL'ƗU}%B8N\(aC5GA}rL6'I/ta0HӒ4@Ozb1& fK(I(W i,p>MHz޲W߅{U6o3hEcYplqûuڡLы ZbkfSBDR*RՉ6,WBdGq$_@%d0ʚQ\uη偭[c{#Ui]mkK B9:#x6@adqJ `l s a4)0A nHTLB*ptqCA2R[6/N4ء͸0kǛazj6oM|%!Ƌ3"=%O|-)0gW nܙ菰d!kˁo&Fs݀DGJ)/c[F&9>^ V(2KSfd%2E2B.FvA &2Mye^(1JNlSe6%s;eFZ8kY(#Jg(lVmK1yRn.ǪC ;^3h=C{`;?0(6c󾼡 Hr A *")<:h!I9 *:+,XsAY2 L 4"{ĎzƁCc?_T ċA$4 T6i׸Ak>ZRBST5pU:(7s\[3IZtz۔WPŁ1,, c F`©!C`F ?v*\/+3C;< y|TAӜIDKLGCo ECn3WS "BЕV2BTZt f=NCQEҗH팠AS ̂PO(UADl"pAY6ڣ5E嚆ßH8.S'T0N(gNI= oL-a$Ixђ SSB֙ АZæ%>AtKLRL 9[qK04TM%.ܢQ_&q˥߲Sܠ(ےlW$GuT7}&V=%rNݙ)hw _SHS*NK^f&}fŬB!)A+EZI>bJ.`}>x\lL7?R iabA}I%jn5 l}e'9h_^Pe_ke͈څ0h̀ k73땋wTxAI+(3B' 4PkiigBBy־id .'K1@5^nIK9T܅Ƒ:BYmFkMhŊ4;۞eͦZZ1 9^6enVkQ#%ܵd-)DPlV'j>.ފ8oBIo[Fb`W9ꣶ !˴5T}FN4dCpFD֘6nqKIfoqr$g20H 6>4O:'#Vdj劳8u 1 A>deW'L7UnB+?D+ͳ/넠94,f?X5F킀F-Ns^3dBhCp; K]UA3[fKYvO&gOiPeQw^@Rk#DX@c,[5~z`Os KPjC* վs8lggo.F]C)!o%vxthW u=p*oGRg9vus-|Gy)UpJRoo\EtA Ȟdevx]hlt-HSn;r/Ey6JCҖsߚm. ep`T߾[51 Lj ϊg![+,<_WV-ʀ  ouO lK;dyk po7%r_y{J|soLY,ï *g~ddz Gq\Vzly `NibcJ?a 'a[xg   7DThΊD&CЩĥ7葡CLr}+_=zХ+GN\8p-ܷ㙂ݦi]ۗ_6}90ώLaJa5VT`@-\C Q*XQ? |2PrXu S0X\1,yaŁOaԉ3RL" 9oߔ Gzh7L0 oI'JSsMGKHY)bݻ1+|UXcuVZkW\C^z%D]`nRa- [B뽧Pc?ɇoGw )p{YH% 12`sZjkJmxy]^O 6B%֓qB>tdQQHcu fv )LW^BYfaP5}h_~pxBi*V$ģA+EjhJu>$G[Ҳ &rд&Rn[ѷ 97nITwB D.m*dy(oW^Is2(%ǟK$ Č"kB(ɡcG˃ -LvuwcڌK&+# KCx|iPt*) Qz)azyĖRV(j\f;[|~zEH)2Q?uqL|$88rEc`1wGLm'xQ!'= \L)"P3tt"N!@n܍G!(}s 3@,kSxPMv4RDTi{H6>'dž!1̷M2y&M~#Դ3(4*Oq)\ ,uJ~;c->eDL0BƬd)T*`UE.,'y8jTd1]ɻ48uS ]k\yW4;靖8z=bkJ)5LaSw唪UU'VdԾcsIPw-[oÒLn:zPu+ؽxPo~Jlu^ ԦeU_,agnɕf(EՊ9?,ui'[ 2os(q_o2w"4W Kr"jYS ix0Sp"opOF)yr&7Kbә~n0tfru{;#5)}Bt᜿.s|_GOf>` y3"MT؛߿+rxs$ȋ'vI)_wza)B!P"$ Sh(D|^_Tݹ4BUk @ۇ$XR^AO4^`pYFC"HP4!Z=_Ĩ%^P=Ym9Kԗ a?J)$DB ~M4P өT\^ǡat ́`  1!y j "!蘼`LduP=SNypJlc 9W[)AE`A r[i[$O\ !^AAE""j] V ]$JZ!aE'yy_`ǫ"))dXNEhBD!YԠ A)b0 `.Ec5Ƣ5Eh#m7 86tDFǤcðR[CdaxDm\jx(IVO/|oUA~Pt!BaeZ1G2%#GcdieE!@H̥N$$՝BXb$SЬGzj-Hd^J:? H`ѽ +emF,Qg9f*e?\$Ie$dI^E`?*\db"JL^jf_XL"YEDRc'aR)Vfe6!Q5efB%gb&~f e\2DƋV|CR@-ĖaqE]>]ff o~U*E"CULMMZs fBXPnZ=uDK V=!qxJg$vSeCgE]vX w^RmBKFl[-.avl]Cd7_b*B+))+B8F#T)iFV&A-ǕĔ3@"mO)'泩 $k%N pu9ꞕhvEV B10*"1)E],LB"`fh}\t*VgpRv%W*&'PDe:ᵀfBjD&ПZ%'n)(^˝ hdޕbJ `X"K*>,3*Z YZr !.aAGNΞ,8V(,,ZBJ,LB)~:) ´])S皐#j1(Zq 8Dj%k+nx8>TQd'eꄅm>ؒmVׅk_H-Rj\a^vpb7v۽ 86Gͅ䊉g~+yh%rrG~s. UӀ'L`(bLjmk.Psl^8o'BXo7o d /;*Nz>/FX쒭eIrYۆNNvd0fj9apĹ\ffZY;1|u*. H,r%W~ ;h^ind*лBп>Cl/].礰4oa!AlX`aOӁ>"]^r1@TqG?=b̒T(~>a 2?1#'#nIDNrAeb2Jp2(AD<X2Xd2 eapQ%PipA0+擰 *tG ?H{FB*%(Zk]36W6*qڅs٤!Aȭgcmo<DS$wc3P3|B$hnˊd[14212]ډ3.4t  .7[C.K]kn20og < r<w2,ݒ7J^OD2|EvV [0V'3m|W[dmXW𡔵uQhx0NOot٦4%[.V" +PJPIkXH-Jcn >\u5ϊz|6c3TRZBUCg4QL4Y6 KZK4vo5 w7w9^s vRvDzv%6kf, vuO\YDkЋz@z#z v ʙU,}GOFktj87oBSI+$38]sUle2ꦐ]xIht穑F0VߔbfrmK/AvDd6|IToaXC[6`RCUZͫ8m׶1mk9躝oWp\SrB#:3A.MF ɞnfB34cC͛# w7'D @ Kƚh/oO˹#ez̤0YzwgN8eo_ʧpZ25W Ǥ }$+7cvZ1!|#vqQ#2rEl7Q`ONy,jkjw"AZ;wI8K^\Z#F[HS.ҖS1pACMôAtHs#BU/CuGsYvoրGLXNGX4qG/scf7k3Sc;{Aodch11]c/EFx 1W4."I%G|O@Q'a$!đ)!J)3 ELpC -Lɥ#."3RP&W5*Siդ)-z+I02qTr֒w՛0lղ{O%Y*wyAyfrUgɪ3ϟA#3J[iӧMG|lj!I!B}ڻMٞv;7bοJ Q+[+,ŁȔ;vkmڒ潂O(% Iv%h蓒O㔵H<Z dc 쟶&:BlA dj Ì,@.F8MGfD# Ih5BGhA(.*JQNjJhCZ.30[%1؃b$ 8*/LC@ \qdBLdXlL.G`&*$Nt!O=L08ڀMLbZFYoqzG!Y+2J%ew!T$GGV[nK;5STM4 vSկZ3NbM"zOh/ G3CR9蠴^M0&Š#,R.fW#XWUЖ#5>KFtkRiX3XGS5X# EN!̭YWe*۠Uv=~HM`l͜5JҷN5=">V H^d.H'j%fM+V4B.J>]f9SbiJxn^@Lc5:5P)rcݤx,AWTZ*|K1FDQVd\㷼e@0CYT`诈kN(,!$ ؼ  h>`Ba k6 Ķ𮓁}0qRt.ȵ( 6 7Q Tߢ"rRLUVͯ Bl%^ XKX,-Xj\ 0aMFR3eQ< Q:Ѧ&Cy V>y Hw?J>iԥ9f*8S)D񲠬tMjδ|,ТV٤]oj (2fT#h M(XABD7ĝIcTPw8d)SIL:IEn۞FNsPHw5ɯ"v6*ŠJـiJ񰫭WFǺb}0ؖ!BJW騲B 9Kkɨ0EU' B^*_d#R *{W=GM*J!UH9-RˠՎqFX Iٶon'zVRͦŚ\&}. D 5q|EN/0]8͉:SDkҘKhUO_YXQYtUWPfM Vc>U)%uF7\3b<]+Ar5% P'>wPf5uePw1oo"Cy IFɢ@l{u:Z+.J TĂֵu,` c1! QA d yyjf&d8IAEE*+^vHh)NIW#A4&? ͲЪ宗U[lyMl_n!㵨f`k@Qr#Ǯ=ʃFZӸ 3L=#S5W➪W9y&$7xH?XɮZu=?ւүU:>fDIj`)&K0Yp#7.z\K+]ǝ#6Oߖ}F9ͩ{@52*!6|WmQvIWz[M~0EeyvWŮDP4ua>^^vX5[:щC\1]B|M% gdRDwX>R~-3)\U }!^NTEE1Я?{kxmd.L:p9ix~ONB֮.!Dx ج뱤jn lL/Zo=c " D|⵮ "‚|/e~.\,/l Z h$o :"0!ʌĎ쬃08z6qPaQ.@N"μ"ʱh/)lN dOie'.o/OP6&0& {&( p"Cf_^Q 1.1 qL`!L"0 #9K(|N+nN:ڔʗcMbc8-&X'xTJ$B12cd}LG0 b%h#i#x#105EP1$+R1 "Q#nB(j/&_.z31>=$\-O a+ݱB1k RRhs"-/'NL$0 pخ1E&SrI2H:"0"Ob|P(F~625ո3 BGUf3N-Ӎ ]8{P"ʒ*UJ6q809F\3e9:kCF"BN$ $KD FV2<SQjH<.mpŲDy^1꓈&(nR?/)=y(q +fj@[J7!1Ath&2hM"CP&rĴ-At=D* #!q"iDNFE$GAp<5Є2 Ttt1 k2>F$`Tc*X"SFpenC N T=LEm!2mct-:ԛBTD @E[;Q ĎQ?Rų1'!-[γ&1gS[m+"hTǸ?m%V5#tCMH}:6UX(, D!fFFcpЊզfe6M[G 9duArTG&=;P ^T~"cT3IJ4A`kUWv So2d2"S N!C8Q%BdLoVWTVv!ro$@ < Z#0ZVp7qwqqWP$wr)wrsr17s5RUYju!U`&-_l"QUUkR<VD2Wo&6%bg\dlr DoVTLm'2n{-=te!E u~,}3b*`64b5@we[H+!XUV+?1QvNU-|DP"Z-cApOB*^{k#\V"RmoD95g/{o$ȷ|,%w}uxhW&747i&j78JHO-VqW:,Xw^O[K)gݖC΃86BxxL¸G}hdmeB[|w8u‹5)(KI7~$y)-195Y=A9EyI?$Y !eGAב}C2QLyy}99!Syc]FD"druh9yŹY9!"~̚5Ea9yFY}c!!"YYOt5"A@iU &6L#Z$@ab`-Yz/@AgCK:rN5jDliEAٱۓsC:Zzk۶AڽYĥե UzI°Fz-aA"9b"4dٻ88|baۚۯUxQʾ][(_@#5Q>U~Yu8~G5RK^[q>u~3G,ky>~陾Aڛa~ۏ>~빾᷁ת䯞>~ٞ\Á~>>5<;\I~ 9ڻbF\HK-1?59=A?EIMQ?UY]a?eimq?uy}?????ɿ?ٿ?? <0… :|1ĉ+Z1ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{ 4СD=4ҥL:} 5ԩTZ5֭\z 6رd˚=6ڵlۺ} 7ܹtڽ7޽| 8 >8Ō;~ 9ɔ+[9͜;{ :ѤK>:լ[~ ;ٴ=}[$ܼ{ |w9N(дԫ&Do;x>˛'/BQۻgRNB ПQ=JEP ~F Ğ7yy C$Ab-t/Qe]*pٱR\\AI@!PEE d"B4@ t!iA#+AY!"aT2e E*`.DjgBq_L6t'Y(񆟚$NeA}@0R@wd$v iC`ى;X*ЬH+n- dI*;A;#i8مZQNiМɐ2D(ʒEf2t ]AIbni-B*I&g`p1hwrhVk<Tj t%PuЩR-jJz'_`lIōL(PYaGIRːom(`4IZ4BwP&2I5Am32K2]4RDBG]O-5ZIB$`1#Uˆi)"B rY\ /ìwvd#< fL4h.*.]7Bim+Xgc~ 6 eG?:@mz䉧| C'/qn])dT"cd ! d*)`pTNhQ3PvA@Rgx;<Vi"s;4i$l wekBǐXX/6"H'BIbDrO_ %H[c:5_APb?oUkhgf֎3cLdQ ų΅q BEJZSb>O}\^Eo!M cbҰ#mҋH ˇRBU9ґrA561fyb93^3(7=-J E6? 5f%:k!ta;%+~3DaQF3 ~J.=@BN3 RTUVnC-.RW u`LAfc-y>+'K9GX@'+IO߮ X.@ou0"(iD~,WD\pϊ;B;$B_UԾ5j')EBZ}cR/Z**7gʼ,miAi13wR"e3@<*OR(5ȟ #̗$mV[ĶNM|Aŷ>ox I:ҁnuL{LG;Dcl=FȀ>sqɿ D;wV~$'BrD '\ʁs#y=fDǣqRm"F3Qh'1G{v{{+FkmI62V|1faW-w"gRwͧ(χBk1} <fpAw7{#k'~G~g~)a1&FvG3%'cWDT}'Ts4A!zx&,Qy8V;@VxuZ0cX"8WsՃ]Hi,pjGQJEa^$>;6q ge_1RW(!(6&Mc p%92(_.d8 fixk8n"wqt\sXjbvP{2AVL gQVT|ՂѷQj C`+U*78}/8?Hu~~ɶld$UBGF1t(Y7njEx8:4<׆1*|R{b\=b-I6cw.J pHw3i@!z4YxeE('eo{:6b_rMy'W-)Iaz拪*[L#Ӗ ӑ˲4 Q%sB1}%Ȓui~I⍉699x"`I@|㉤~t((XSsX7pڈc"3YXZXihA1{c{BB&tB(xiҘ9t4I.K0HSL"7.i7I:7oʏD7(eڨ\Y6?^Za _2nes[)>ZvL{jiKml碀c$/٢Kd!#kj9nvSP2:YZ9D*pZ}(1:{ WfGpz!ZI:Kh+(3:k  1KzZ4~I*W㇌{'7vdH%ݚer?1+h+'wJT3uT8ڳpV4BRTFϑ1+(:aa#EIKsp@(i{"^;W aeK>|J[2ژcM<>*{#%MI8j蜢 wXR.jemy*tah[\:+pKZtܛMOȦmZJR9^Kf!dw*XKz';R!۸}裿);MY $6/솲¾A j @P  *@ gf<[y Ы <?rJK TAL8(l+t}y&jƻp5 DVh$%q)IrC f+ǖrü6q W/HaP{*LQzQ}xͱq2oD-Eq-Z!v}v{PB<ר Ŵk:< 5A=ߦM-g)ߋf ,nIK)mrS]4wf՟Mۭ{!5.).k؅2׬|U4,ŒH@рmb\&ٯQ+^XڳΫ .\Yڊw(_l>E5p5!Ci\-Kڞ(1!֤2eEfL+-r9T݇[&=V(˘@!Jn`cAw|*}o=^nU32*?yq>y仉}kn4(,j`G;)eA)E4袕ܻJj?N@Rp>#6o~,'-.ESAz/Nkv,EnR/+^%@J-;/K KYLl.L ?CTAl hD@;!^CoE˛NI&3 O#V7 o< $P چ߼W*Ni^ 4mt]"LrӐՎeGiTP?tHr#ieh|_H/̞n1lL%!(.Wϡ26 !DXC%2܀ 0b(\#D0MؑB%2Ceʃ)~HJzdO\0 %M*ĨGFQi*3Q&<ɕc˘_QY6?Q8 ++έ9jX !% I,^JrN~uHh5o*_=zХ+GN\8pkQTW'>Iv ȅB?Ë=ZʒTFAkP Kϴk'0mSh)HU5 c,  T7쨲0ZRe[nXX!kUWT70RL־bKMN:Hs` V(Hô= l>틇X؏(M-@Jض Q3UŲ{/oJ̲ v}Kq9ve{!i/~,ks6B4Prz@T.^/S^S s3Sc'`|efz(s[4v;IC[:Q c_91rjFMBJjr_ 'ĸP!8}c-0p\ gݻC )ݓI'NmlO I;xn 垗|ى5;| dVNY=C"!rœ xl!W=SRAQE+lDŽp3 %-{ҝǓL!(HbhAW(,1%AaHZ5AI5*6f=SU]!D.?Э'Q,"O ki Z2̘=8H#{Ȉ+SUN竭7.\ I l#KQ"Cj4hPդq3WړP.PCYL}-_0{(G`pVvL劁ywa ʛ,s"BF(DJ| )&wb2(`lČG&c:ԔhZԄCvM "gcN-%TM NAi۝!N>rnPJ Fu5gWd+NʓRaM聩zH1Vt1ITbp8ƬiglU\: eHt-U[L&/ m7]Y|!?bsUqr+ʇP)U1dUFN9TN6p1Y Ib[B\OmrwbH#e1˅hsg{ݥIKȒM=1TSfrv79eov JN-UEDR;)|Pv8'"ۙVNo}}o3U<n [|V#>^dmYB-#bBƚF)C TJ;mN ]ː)򠰔XBfJ_{7FCGVH;%r|N.وQˡA+ MjV|,,ZP!u(IQB CG*!$ȖЛ^{DO,i؋C5V}M-IbQq=J WOn95VJslwM/hv+/;^q@ {"(SaDAz JhRۧpD<=;oDBZq`ђ{Cd O#S>$vZS+ӕ/<ӈS,ʮ.^!NMᑓdj=0ږgARyL%~CՎsҭǑU\%s5xƣ+5>j}(TG՛L/ 88C܁.]ebeU+{ ` C-G"{-[xkO.{4q{?9Z=!86蹔 cX(L6?;>CAB0=vCZf ,r+{3/DBcAs4& T=X>C03A!ș#tA>Ц#>~ QPA4¼PB/$, *t#/$ GĘ:J4x );B&B~18*1()1 =/ D8{>8,-s;^#LC!L Dvxy7xGzD5, Id0"iWr ŋvS3(3*2ttGPŲ`"K7YĺZs (SB ^t>Y ->fCF(Cb{?Y 3 ^ sILR>v*TD0FGW: Aȏ  TXܝta:+&@IYxpK/`/z q7 Nʉ*F:Iȉ;8MƇ8kdlt#<~Ҟ:38O;d#ZGpwʣ?1zL{4" R7RI?HʦF10lTE Tz۳br< FA":Fb,MJ1KFH4A- 5 ,EWx62LάIp JG,N:JATפG+3 &J OJ䨌ԙ$ò4? Ν<}zQwXi$#XzTpPRJc>LN},,R 2i,ç.偆`<(}-^Z! i(cִV hh벱=֬єWtj\齽d1._1vvlxލxl l|!wluKۢK NQ⡱.يF=ŷic0䡽o1Jq}CG֭o G bm@3nk>ާt|x #6_(\1BvNU5>n vc=EGo^oN &N:dQ1IrldienxP%"> Y!uq"'oq6">f79xI=+be3%&x (S^7_Epn> vuWzrs*s]PItP)!8=X ۬J 'IdrtFKArO %-]RWSoT]4\xpEpuXkCxڄs: {U]jtaL;vAAE9ݍj<È)m&ھێrXr9wwrgdtIQ/|rvr d;ev%؝ 8HCԑvGMw+Ŗ@ @Oⴿv%_wn1R_ x?~CγYspފfNUMqXggZ}z>xA>,*i'jO5g︇ʢ 6dӉtS}oB$9|Cwjܡf|F|͇-"S/?̞fl\#̀q۳G0v!?<~|DR@1G~<%Ж,'3 1JG"󈂑GKδ CzL1Wl%2O{v 4$Tї`V[uUXcu[NBdF$ ZJtyJv ȡ~\BU5 2U {9fD\YedHuh1diPkQ^EU5)D\o9\KdQYU"q@y$vu؝z'DAOvI\ߗMɘ}L:}<J(#lQ詄U@#q& $;rO#n#IX!k\˸tz&%y.VAUSTKց}Je5R%3[3tnN,<~>"zG->CQA*sP"*̍s"#B'}tN `8]OJVX,!=;Jx3pFhs ) (CƧz鹞Dgm!a&2+TPUJua^Aeb\A,w@i *XХ 5vNw bE\WYЂd"%+< >K)$F)!;/!lED[01Lz$wID@aєfE2r N%0Qyac Gmh ̆ZGDD& A8n%"gWY \ aE7ۓ18L1!48ΊPcu@.M:bR`$]/{vj%Q[J$?r3"DŤ1ҫ,S ӢYTtcK87<x'qִ8b:՟Ԣ9w$V9jOGf՞㪈6Ji5qeCJВ-kbB{C'h*6&W;AI _yUY{8b.U.dƲ=JfxlJij*!ZTHx? ,a ʒyQ͖Q*!mƓf YsYqAR/! z-#1O>&(!"zEI]NoF:*/B|QJ1r/%6DQa,7iG#Cʴ0/xp53OČ&H^ m֩e.p3gM"ݓja*t9o[`!q$uL?Urq0֗["+|5V_|4#\_Ҝ%.^ibf7ȾvÓ8 N7۱ i؁P = zml43dŘQ=)()wo^L[5v|ZpESD(!mǐMau5D%a|Va3+;9ȵ}QQE0*L y^-ڤmK7>7ߥ:|j;3}=YhjCoTCB.ʸ}F]M2L|gs̎?sp&2| sjaA 45"̔-MXEX^x\!Z-ڇD^V<+L}VߜܟCJs坏1I\PDX@ DK$Q˔TYU݈ JY`_B<រϓUh^D 1ОCTIijU ػ!IȖLA}Q 2>QT` QMtA))hD|N8!b@.mq4\JݗA|!JAdb!bQ!Pơ)HlH.`ܸJPY`\y P0Qf'E(O?N@)(-EJɤW.ATPP_YG/.d䉡K2AS>KK$$:`cd'Հe`ATԱP4 !A{ߠ fOidF#_hg\b8FFDD])טZ.ğ֥)i1qGu.S(7kj 턢# BjW#JXjNڪh*Ja6D/ݕnUnn!+C :G,N \^kiui&ĎT" Yx^*td)^BMf:fHaUE(A9 ķZwmjV|`-z]GXTHD]jT\\2GLM?tlv_>֯ 3,G2m*Bٚٲ+aLҤ<7e OUP VV:>D^"c&l`l͏lĿf!ѭKA J[EZmjQlF<Z֎YB&L^+3n.2z ȡ,LB"$m-8YFrr oe pIt BhCإ)@L?axOJ󞒽FN)B՚!raje!CPZC"CJ030Pel.x,a{ƭ81*,#'"J p/]IYZ"֢y:fp~j3/a0}t_2 (Dr?pBDndgZ0kIeef"e[kޔ;2a K,.pÞbWEd@.6Vm`FqRnb^1dd . D1ooNiqžpJh0Q:[ ?&q|])31͒: $#Ov+%_ [DĄY))(*+ĎR2Sn؞-1.賢a"ͳP+}kTBJ3dr+5Wbk@49{:2;E؇>-R=4Gsf>05㌘t#4gU*tf#Q[5zpwttc4dw7Saz荢 bDk5Vm,3~|Ukl5>;"W B EA`KB'"rcel4wo4\GTw\7Pf2X'xSf+r*:hS52@@q_'EÀy#*QܶH38millP1azt'BJ5?'r4UKQݛ6TKK8/6+{3*H ^g^~Oi8K7 i[zHgo]wSDn(TVDqqLSdYȯ+ۉxu;[.*1SOzV{ꅵ6m'kƲWgT{_;H'mJ2FeZGp:Gc(cMH6wO19UoC(lXׅ[0,i߬|>"|Lǵ89KAbGQķ(\;{[~EPx-!$8 4A5GaD<(VhǡEu$!F8+w,OI #:Ez4"0l͌,=͡D(mu[n;zbH+ (b"ptQ*O=Jwo;e1پʕ0q-/i0U H]*[#t4J,Sz6s^|n4RN2aOP1jՂS"=$e>^;dpz@SrZ"Y|5-K_93ʡgS8ŝi;+7s:6OB$R[Jy,/`I-zǛ7^o+?\%O3P:RD0Hn*VJ=s]R+R< A jfefE BD(LgI`6*zi{ZW# e]rn9DQG6ܡ{0# EhD.A _ٰXIq"Gdg;ׁcI0/(\OC-aJR5(+yZa`(0#tP,/:]z(u"mS ,$ ?C+iF곚ht/K/hVB3 EH $~[3*393S~}zi(R6&O{6(L& }N&WTMH YKg*h4E[U]fxyK@\ [DwJR( c"7c+E< :Ǭl/9z:5?M H7=7Z~eWTa\3ԗd|)9?z\NR\CJ#Ч͠`MN$Ib(яJ7Y"29<'+wD|Q+e_ ]~v=5k5 g.y;r`r EfS>10K>`zbm0`i"UnF+'i")A!s|]%BM^odEh]WMkw1xƃ|뻥$NēDq W?;φ]r \&ӼnEܑnluNݹF%#t"2{QHYIY_tUKS"d$Ӂ*'qK1vjtoovXNh˼E=*0KWؚ{^C`w>_۩L\dCIRݘnjL(-zEpL,b3Pc`~piP 2M~H@ͨK KF DD! ngKbN|d)/&O^ͳXNA()0ʁ!>xd,- qɄlx`^rp)HԬᶤ6 k.*42N QL\ԉ$O^FK 7<*?α0aͭBP mѻ("i"1b"˴L 0Q|n A԰0y/ ]/kY1A(2RF%&lm(K(#L2E$N#n$bvB'Q)lmfBJ$!f'vvv)@T^$| /P)ChrQ*N \Nۢ E.u!ea2A׃8 ! AR$$" F%"&ic%V0*"dr'+ -upbI(Džb)[(2,'*3.FQkXX`$! ð@r- +"HQ%$#H=x. Qa;Q1Te6-o*&S002nȑHH,pb`.:sj"BHVN(Q 56 S6J.$lRD7k?HH1V 9o0&(@iB9I"#AEJP!;^:$Ӭ0P# ˳-aԳi3.)]B4OB&F|% 47 .$zI~CqA7THHD!@E #aFQ/m4 ;v"xoG&G".R43>DÊ.0 I2*7&jr3va2X3W[B ]1P9>4J y-tA )$ K0`J9rX QQa$$cDe|S#z&3q$(?qSˢCV3UR0D1 Ku[p4gvadSx(xpAe!fy`fuBK40iDM,I.$КC+tD -$=QK^^F_՞m1+`&`+B$6T4Iu,*(6Uu=Zq[@Ai!e5r%W]"`X-A*wtvsSW5#bM[-)6j8?i(TJLcbZQ̐`L¶VPvj3GãRFfc%n%,VS"nT;Cζo36C44 hoGpH3rr-ryr5YyPler`1^t!Zד֡xNvfIww "&">bEcwL^2NA:mWp7`5\.rDKnV6i$gmЗuŴ~!t_јW)bvueBr*r!"l 3.Z7)l[#/p!U}ȕw#P<#6ral&#H:VFtu`YbSgp‚\m|cKFX40|/ *w&&Ws]46$w5Wma\@:[c2f#Ҭ! {\"qMjk ( Ebx:QylPPՐRw(op.?6=j| ~SGUޖb0 BrL.,7e%l!Svry!Z@)lB*{hqKZϬ k#΃(@ ,ykW:VAךڭWPڮڮ;PC8""K-˛ĉf@Lq;Sˉ*Vtwe 喇޲(cZX-8uZZAhDub+Ԫ4zLޖ5O@ ^]HJZۺ{#ͯ!"a Ca/zD;~gf:> D!n"Mͬ1:IN#.?WzD}SdcgT&5M(O\o[*{8ۚB9 O1v)abyM]9dܰc "Xވۛ\%L x3~y }7c  뫞^8h r T*g %>!ȡ}>ׇ٤/_4 Zi)~K+a. [?~L4aMbAҋ&am!M*AmO%+}}y )3~W]3~XZ;wkL37Uۓee˟TФ=ί-ԈX6l&ZaHM譵v-pU8@t*!RZh\xRZ۝7ܕW\%םaF܇7^-\=EşGFȓP Vi%Pg=aRthȥ|w\޴bzIǩ(Ucg ۙ!Wnh;8&Fti5Y q6 XJT^馏v駠*ꨤjꩨ).p6H馴*ꭸ뮼믩Jiji&6F+mM346&kӆ+k\6 !-S~+o[kﲑnË<' DžҀtkW,hgC{RJwl(d ! L<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯$$7Ӫ? %LMN@9L:aRDA ZQ H\`@xPIU؄ E 8 1RaTX!E<~sAWQ0,p Bp$_lb0D(g' ]"+Br"؀@7~]BxFp]J >^B1)LM l*HI,& D HD FyGh2#F,J4[J_ q XɤP҉5r /;F8m@0~bY/9謣騑HRE܀ NSln)S(L,qg*cf䒗+3N ,E10gΉ^@di=Pf5 J2dP?e2ә7NyjfC_x"$"Q"&xfkW M'X?M{I|fv7O4xLHZV6b 7{{O{<{ooidWj^KJ`F^2rxvKpK9gz*[&xax~K!ɉ:6F?s|n]q:WeVع=)B4 ०'IGK!;[M髴ۦ{6h`pرjp*‹z9[Eys<᪯QJ,4A ?BYΟb+sJZR L|%=uti`_`}SMl:uhK 8l}=Q=T-Zټؽո,:*@P qd 0 \a<ЪwӪ<yZN$7W= 2XڸKdA=ڜ[|~J&Ʒzr9&<S lv8 ]Yg!"ĵ!7<@0m?LY G|wX3A65SM˼6F`~14u f'wJ헇nnߝ=eقjЏ)v֯Q̓jt^&n۝qPj"c 2:=ADNFLIaQD~{Nɷnؽb=L! .|KpV\ZJ#?w^X: !I}y3Ys k͈wIŀީ;pN.b> O*_ꪾ$Ѫ<@\}tnzocʾkjV u/_ NAw`|"6(JB:l@`reCņ9 $ljyhJr(#% I,0$TPգՂą *mU^*ݦiDKD(48,ڇ Q"DvVrJs=}yOEx%^U-R+=I8xF'1^x Îe%+GBKQ 9Wd+y\x{h\`LZbTi%B͝WrNiDB?C隽(cxy#i#u`kk^,JC971&iҸ.Bj)J*Pr@Rp>- :>T2 VZ4S6Cc"2ί': &ւ>|~QJܠ7(gaO2{Msw(zz6ҘipruSD:> |ݦa]<=w\X!fxX\˗%8 AiiVg恪wP37o[d (Y탮ؒ2@A=;+vIA*>)+@/ 뛴99#,_3"1ijkպj &c #H`=¼# .tE C#KT94l2Z5{僻;; ^M|X4@F , 0Q9Q t /:zoDki%LN1P . @tbbE-79CYE#C ! P ܯtC&,C<: c$ XTF?CD19Mn9,8"=FSdؗ`?rDs$I$D͐%0Y/rBIKż|>74@XE@j~ T5 %3 I@H] 2yEF !=ď<ˏ(׳L6,h1ˁCO|/EI7ͤoN"*lE%7R0ӬҁK 9CQ{S0}18:ӄP@F6~ Pe|AA,xN<& D3 C5DEˠ:>tCp3(38'Ѫ# bRzȥ_Q\q+F* Q׶P45eXՁ]4 6^M9Iˏг >%4RWw%TVĔeLLU#oR: 61qYw}R%dUW{L@ͨJCIYxکZMiP,HïMM!I[= 2ENؖF F0Vz# V@[׉ˡ@$W3(̍4_=\lW5Tz%O}Yx*ڛ9ZS58@p م+%>RM-@ W-u؋Xue5Nr6QmW پ\`)+\5ۧ];_04Y Z[KJ]UKڥhI]}B U 6@ѾskMXG QHPk7={ Qѝ|x`= -]êQ5-fm ]xMB<ݏEuE 1Nؒ R؛g$']*7FC\ ;?D[B 5v䔈;UPsۧaH 'Z(ϥ!Gf81$+ ]|ڝ]k5]D2X7ed-OcHvS>FU[^+K9@y>G~6d]TNC3}OYsBؘ֓Y@b:PEV:䮏STh/ZڇݭDPZO%\\9Ff:0\={ is0969 A亱T \B (ߔ;g jCH d~G(vjSH^ :VU;}#kō&"n6K[3Ok l8Q9ŘcgTq^yJ>߱LNwn(gڴt_0Aւ<1mؓꪶjRh#詔R`~“ P5\Xm̳P!!T“N6=uj!F,&יnfŞ.XY;@:z*P2I_pBw+p~SmoeM o Xt 'a&׌ ;vޞ%봑 Bԃy@- 6*I̛Oߓ'_EgU). .QcmlͤT8ОЅPf fMQ0* 4y [xK}=H3'>@~!ttFn K#we+m%o -p.m/[~=-m/*iіp͙urydu'TyޠscG6= ek!gV\U l`&95Gopo>bj\t=`Sh(lC{w|?=>V"rw 3_iKxIJԚqW"rT=l܆G^Dnwy!Ȱh_8xOAū|UT1V?K=o] nM,{'u畴זKCug7¿wo#{!7*DvlR+ږD ujxUevj] 7xe[;q _SFmZq} Ӣ3I(EB7(lС%J"_)6#ȏBN$ˆ`6$RA9)[f͜:sW:tʑ7p1m괩wQh4*DkCB`fjδ,UYDZ}DlgNXCTǸ$G~Z$UhjUCU)EĈNavIV]zxR2ŋ #+QTD؅1D5J\)X"<$)CE(Wn_3k\C^( \Խ$<>SMy*QJg !6_U og6I-EA&pW\ @w`|x `pdicT5!Tv|_yP{Y8iE\ZWx&KuePx6b[.=H^p q%Qt=\u1To!WdAtRa[{2)S|kiPO?5TQG%TOm$ !`G(Eڱgf =`V!iI A %bAb%R:,tkH z!d?-8Vsx"@A8 ynGFyLs1Fy$]/:t_s _ݖño, '%.fHdߞFҪ,2̅OriOﮖ5HP'{Э0汎HK"B1&L3bɄ ?f ՌI#EU*}4L>DBB7- "(7ᐈ" = ?΂K- ]$ /iD<0c`86*.Be29wt^(5њT]EgZ` uZG{!u.KJ7А;6͘25:!`\IhHE 3'?)ѮH;NL 5HO~bg" Q VܚdS=*Ń$[T%Jva=(H6$b ˨HV"ieeن ԩHbdǍyT0bc*tnDtɀnIۍ< T4+Z/U<A_يungppks{_w>Q|(m)N6FELi_A'ޚ/yuv26R^pa:JkCaU/ .?{)DI:gb`\(cy@t@gy2d$ء {&R|S)K]by5]fЈy.V:2.2H8%1ֿPg}ȟ_LEH"; qv$}G9Y`,inv>}4X"$hI%jk0g}enI6$hT-?X ]v %z$5ϔ0>^ispm"+%NSl6R;Tbp*k/^MrZyŧjQ"<p>{bLQQ".sq}O˨@as0l.m!&9mYm+oFMh0E3yAl݁qP6Ngн#|YUMO< }TL*?|F"Ro׉#LwP,:6}>+M2MndAnǟ,wkE>+2\Մtg+#nmgK6G{@Nؤgd}Q&JD! fBVX&JəA|D蠬Q2hhaGK]MԥndU=yB$N( !q5ĩX@珲t^B0Id_%Lrg3zynDcK>Ec*)HBK {§|g,\muĕyJU$Xxdh?:ժu4*K,*FhVoHG)()HJTM *J(XmΥ@XFvv(hZ4ֹW9QOJC"$ K1) P8hfѬMx⾒Fh+5UN HA+?FCB)_qqW&>jv$Vɦma wĽ|l}2*<גI얂$xj-k<q0K2Dʵy;Ep0A4A^fV;: &~%F%'(bDAX-)a-.iSTnfnٝ`QĶZlVu"­mUy%W,D6)4v)b\o\"~.6v'E.M f:EHT/1Sx.j1FD,'Bm]a(iϢ*=m.$>/"ܽa#U AW袰ώk^nU:U/yi~L愐JEVN{."Ě'i2[r Bhq䖰6w0]] )vk zqoGx C% pOnn(FDTg+ǗjQ!$NK7EA@jvjCfpt>FF \.gJn'iǺ~U S 2]sy&ft IB#]MZ))ED-dʄD_+Cݹy$2êqjM,Z 9 _D ;h0Kos8rp2˫G["Gs*I4J+<2DlK) ~uF~i*k9﯆^;?,()'(ڳ >s02qĢgA ]eUJ24 ;`20[t%q/ stթn"+35_52K}$$BRMkdB8iME'C 5Q+D21S2 UtQqkiEp,`5GEYbz1.cN]zmH+Nj`4Eu_773u`ԗ{NL3@ ZiClD(:4o:){"4ˬ;w3y$/bxË\=@A8&ǹjG!{Rue^LVqd;2ʥz3btC?K7Gn %;%_pؿ{s;OY$u7l=cgсAl$d9GP7s^Xz!zDЬp<"f{'x:3KT{+uy\[z6_T\+?<2FdS88'BEx5]g8Ws~pM qR{` 2ܠ.q#?o (A=jEIͻ >˸gл8;V Yؼ{~hikm>)c#Z(Z@I"GTXB!:p0a QԸc‚8j#ɂ`2ԓa=Ap&EYcGʔ0'ОF*BRI#%&x%+:,VŘU1Uƕ;NAo_UNӲ -%Tb M<0cTًSgćA'(=渴ϡ, RR0wo[l1UϣNLaKP֗H[Ս1k~N.<],GusSMz`++:ki뭹 &$TF 0 b1*Q(l()/'.<[N2 o3 Vj饂H7(,,+j(j#;p4H|O&3 = =4Cp!5>n1xG?RAB?; 3ȎC/CTTFV, lƅd4/:I*D-k H{)#tˍܞ,( '*o r<"#[T2dL%T(xJr1zZ"msOzU\mm!tW0'{c R$A,+w6p-ATӃ8rADMTTTIc?]5F̀–F0y[\CGpI&HJm#xZ29!m1Cp.k\r_5)2XR(wgZ]"ta>ZX*Bhb/N35kjxJ##-NWo7XSOI+UrYlsҌ[^l˕>WBzDh2%b"d_X8:IVŚCݴ926V"[ }s`@;|_b*lIR($p kr' ?nqWs"B0'D8k+BzR|3z"f>{ Z` hEHBJⲨlxfJt5Ll&A9n}2gRCZ [샢(ɯp߉*t%] IChGr8J䘂rbQuŴ)1P$)k#V}!LQ>tcF@hd?@AriP}84 !ȯxQt6嵏|v[cQkMQ=)vxqWdY͏~k S yMSDA6CYB03OK$#&| Rf48|%BX;Q=lDR !!ab*+)v n6fyFAu"t(2cLQTuiiֹ\—'iJ+>{(Qj0EʜZƅQ/ʥc ![COfo?^2IJ̒ruQ JRA*+-uǩ\&7zYklK\۩l .[=Zd+Ddo;,q$/PbXǸJ#u-HZr5xL}IӕCPeLQ'N~2?qN\p\W\bX2>灂J[-j֯Yt_xOyqoUf^S}7NlOF_lUc@^L6*!{}~_$P ʛЏ#~MVJԷ{#f!~onn|@Ǹ!Mz8֏~N a:[7+4?Kі+±ox|EXBX# تPBNx2t X+)L /Lqqo\C\2P~N n]JK>7L)Bi<ax"PPbp(^OkbVЎŐOz [og~j, 9"E0$H~BP4c4v=vy 3x %&L|)8rC!CzP.e#'GRP 0׌_ao]ގ uOLx,|$lzE' p#p9Dp!,cDMkH1H6M(1dN:$(L/妱',>:1>|nf0HqPql{O0]h e'/Q{1 .ֲD 'VRbI"n.9mԎdKrnZ Py*olO5  BcV0")QM+q0(##A$jߎ1o*2" o#q=#&#ԥ\t' {2 .Ek08),2.?SR* 6pKEg~YD_F "2,m%2&D/q@ؒ#F40Qm+!KkdQlZ,Ji{P!;3`bN!y@P33 4,^,4)ԀrP^A DD! ZHHR:JH,k"mBk</7I/0˞0Qtıf1eK(BiF]t,()Y!FӡAa<qr!I0).R뾲#XIh`RNV@a(b8A /CXK7OBUBBW:X6)Z䞆clJ1UO(+dEbdRr(FmrtG{~CBdA/"Ę4i4E$&JEDۇ/P@ Tn-m2+":Wzs&}Mᗔ)2>OTwO{LkP;ZOdF!BEY!eFkGuGART$AܨHM"QLz4" T >7J@Dd" Do6#3aˣv3W6nz}MIL$'A9ƬUGOfbM*!L2QRuR=/!C TӭO_ "JJ3Tx Sd\#ܑ8_TMh&5O;WZhze9F1!@b \Kjd21w!4X׷sy8CA+#t$Yl?:"gDKtɖ ,gr>a ܸ XmyuB/bNs`iDWbÃUhbije=ip7joQgyxr۷~5S9 Y'~!IQIWiv Tu[Vo8m@8wkav9RB!Cyg8"ъ)64d9YdemKd _'1c:ٞv0uӷf%y%SFb1{c767^hԂ$`[rs 9\yc\֡)b{ :z٨8p?7}*C4ik \Vn/bpQBE}'Wb(édl/ܗ(3twD%oJlDTOw)MOEtyUwmi!by y`xݘlJ8%KN"Aẁ:G%cJN "py@ w;YOIoIຯ)zS=•{e^$j&X7"Ue$I2qCd*Z0Bmc96G7C:!8Y'< y!u!r! >y8/Pvj4S>$Sd Zh"Cϻs$Zg30Vc>!٪ TĿC跍\:**4p 0´5yZMfjL\9p+m,dn_E ǟiy t d^l0BQG.tܲc+!{qqߦXJ峧O m6> ZS!{l۫yh;}XܹZ@I=lo |,}{=\Y/Q ĠN@T,Pa!>%~)~XX!5~5><=A"_qВ]++*"ff!Du-ba(`D^.N>hMLL^EW_ö$pCi2O&PAP@3Do5\ڛq5"!l,| ]5Yq,pD1Rb >)_c/~kT!0*˛"hSt=(C^ 69X>h~Š9PYiAiCflEG8",]%[;gZjEJt]FD"+Cj"A$NIJzkN-m5K$г<$\  RIz索 ?&NK8c/b-* zD 1] ѕ06mI}ֲ zku玹]ُ-J8 Cwvߍwz 8sQ呬4p'֝=9-bұru-vf$ZbLN{;,~ζUI -#ږܙi٢P4i[~__]q}؏ pŠdrz:~r[y ZE->L(G[D@MNe QFhjD DO@uUp3?4(#>k p4 oxb.^ qD,=\p=D>(JqT?M7i+qd,(i^8qt$b6*@@ rs:rl#yH=r%Y<^$'sB0^r,%!g,{vighhptrqonnjdVE?=:.&$!{wwv!vvvvl ^T K? /~%#u/d=VBQGEA4< 8 +  J$7)=)6*+++,,,,,,,,,,,,,,-,,,,,,,--035;>7733222222222222222222222222bbvvxxy{y}z|yyyxwywzrjggfggo|wyqzukhtf[~ZOVKVKUKSNTNyRLhNJmE@y@37+-%$(""#&''('('(((44ABCDFFMCZ9r#x}~~./2J_cgvosty{zywxvwuuvxՂǿتܴH*\Ȑ #JHŋ аǏ CIɓ(S\ɲ˗0cʜIfM8sy @ZnѣH*]M8HᠫX^(`y+Ȫdj]-Վb%hVd!Wx]Yfۿ[~#pK =.K.: Ř̙3ʘ83}Lm焴0B5кX5ȤǞw5C5C ysp,n 0ӫrF_x< @3UiRY?VF˼!w^xE^z!ouPY wM2Hq7YhbE=%NrMT6xw}nm6 z!T\!܅Du)41@qaB㑧ZV`BG_|$a$Hy&PRIڛiH>4xPXAPThmaHGܙӉ]"2"꤫٘jk{dɝ!d)bAF$cq*A n`z-YॉW~fIAq ɢa%h:zmTU!TfVXٶ qy"JSwOUr$&4ZmDjr&2BZvZi, (YCpiWQH##D ruVlڎn}0mz"FB}P4ws!ƍ+O B腤e>M p:;cbx[#׊'?]մzMmR=er4;!+gWW^%4JZ-Ё%; r !,$,0Q]___Smk;!nz MnlG8A!7{@Z_M}뿗Ί#OsBh1o`È?;K?BO6c55tSTbg-FT6dGvFt'cx%x0RtUWbKLet\'uW'9fq`fntVnA^x}lW?GzaUY a"g%e@xjbut$(r H3WpUrl6PsLv$"T"]GYCyGީrğ]Y©'IG&a#08u~9h3)n6J:+%ijʩ:ey!)yu*:8~0J u(wHawZ8APwquPɎEQ1{"*OꚿX:Z8ѥ(w)UbjSl.*dzģ;Ey ! qąpȘ*D GSU:J,Js=1l i2i9C%s(ArrVv$å^$! F8V%'Mj AZ7SJJǬVJzP%sE@p"8`%F׭MyBK2;aӟ`ɧJj2ΐcD%ᯅ'k8)x顙fС"$!k_±Cz,fX g@M[xDe723Kt"q5<۳:\ ۥ!K;AQ;kS'e)miy'w[[+8][ohT2%v[jqiX}U]b(U !(v[S<~>j/90iDD%M1AџSݕtJ7 ۿ 9g *Kz &n!ˑa[?CRki6rKs{@PU?IiڷP1\\DZ\܅\^Q%{GcʫM"kVKC@`p  0" к:܄`Rg@vLܛk;䉫Msj ғ3l$GkF?Z4,JR )kPz>?,>zaCtcȸɏ;4 r9S\Vlņql[`,dl܀j1BI 1ajXv8<RSS}oȩ#3M | < ]W !Lo-8&e:QM|h8L۵M YX TICH=&JacwQP:C=vؒ FQS=(d 3޺ ޴VxP]2 MY Ԯ qj*'7ϸY̢rJd+AsFUALYq%"rK0e{M%c :t=^`>n)=D^̌JA!͆TkwyL߂ Z+ 4ŻMo+˓sۿa TJs_Y,Z.0GY6{Wv Q \^ IKn#q'LoN'PLtdgi ռтm~|Y죦WHїbs 23&1:WMsg3&Wo524޹8ӁC4 @79"JuN 6x}AK*X 9FQSe?( Q^?u/(p J9iH԰ b C&S16"9wn0|/a5 =5r0 -$de*Ҝ~V!Oq{qfР33PB D=aaC@ ʚ4R, 'Afp•K*$0fF`,2g6y Fztr&d>o:Xjlx 2_EfIdjyQѧ8.%1Z< qcR| *ġfnaJ-UY>2jAN!؝A嫡/z×/p߼q n޽y7eAj˰ϙ!1Y|9eŔUGxk-%퐊]u,Ly-.69zWy,hyb#2꺍lbi*: * " 8 8",ˌ-&z!\?[(t/0I1Pk/U i%nD%IXZ ')A5XsdͶ|#s@\-\,iL-銫ʵn rj%ro<8۫$Ej= OIXC׬9ˣ*+ N@K q#3yZhŹZdL@JNF(V&QPT9R [#o:x%W!'ϵ@1M!N0 \Ha`W2}Kș4шrzs҂;XNFcA4Јe4&UvWĈ3#֠"*g6$ У\ Òj\a:Xe$E7jh.UpfU(m$IJMc.:m\t.Mv_8^i/g͛1 ~`p.)a b/stJ'ޘ,ZeG7v-rs&hN 4*3ee3'  6ЂY%#t!9|-jdjnÊy, &Ik Ҟ_ܟntszEo ќ"7vo \bC8_3*4Ђ].d%?V[7zJKױ텊bŮW͈dTY]HZd +JT6,( ٹ|?N | Y|:pcͪAWS]CQ REEJ-IU-cy 9]b$ PZ2BXX|UJh:*STtn 2'@_S_$NXZ}μjuׂxY Fr]]׬J2}eو:-0TG21v!Ջ ӏ* gKf'YQqIZZ#VW=%cI+El~@$p^؆ kjs\ɚ%)/tcow58׺y5/ZG/f|١ ]}AXFMR-@}CRʟP-$׼F/­e4ζ1LmttjD+,3A^XR4}zq-U9\(d1f _he7!沒|( "*zvyb4TSR%Rj-.L`n?j%,Kޤ=j8عhr J;ݯʹX$^&W7dC*b` \,N& zL+xR Vr _8L刟Շ4H *0dW6E=+%X`[5P\@$P+ .M h46<`f-Z0~s-G6aCDou0X-ʺ^`/Xvka `_=LTG({Cb_+8Ò0V`xa{2FB3%H@:;I=CQUWE HNlT56 |o 9nVIAFFid"9M 2DȌdžyn;-҆VllPt7&Z(tƆ`9yqhVL1jÊ٦@vNm;kID̝ʴl9cbya"9dBZH=oc3֭ne W'-jNUcb=R l "%<&ކA= 6FG־6F37 ,J^ql^%y}]+`R|/Ո&h4Nj~}KSW9?r%Ck"07ŵXmP34C :$qY6@)6=!4/L?w@tv[9A#P01]սpI~~"#o]-I\N&T> o ldf»y5Ǹ`3(WWDQykxJ.\4DA(]Z'b0W;to)vG.w\j~,N,O4yc$$c`i܀/pkƑlJ.y ai,/;Q_Ji@>^W%e*D`Ap(x֦F!rKwj{ ;͗-| 6>@^iSi"mӜq[oFXkFvFh\Z£>DKW?gv1#R!LE'nP_j3UK>@!§g%Q|bz@|gp)n_Zý㡛\=BxV*_5A3+Xy8o`PU(T3JQ<3"y&d‡#U UiҤY#i&B@l I8|8P<ʣO~2ʜiaue#8Por^yPb (ʼnUeDyksSsigEgA5g y|=e6UJXbeZjظg^}9yIV^RCSk4y0abYBib̝h3UE@<#j@aQoI"n/tprFk=WUf)tFuE$(hN$F%"RI1O ),0Uz&YSx"GU}Gmq駁J t`XcuVZkEV/߄h@*%YաQy(&զ`"e,,dܫJwgfW?d|Z}YGtoTӓ@"zTW@e+NsD;əPElZwG-j"j=ń }#o% ᆹ5餴Bg" nڠ @!8JpHZ/5:Ԭ:'Ōh<>4CѸ߱vm`ZR̂lnQѴޖKRpMU{ܕ(H󠋕Meov%L%ekIEG&PH_D(,jXPI'TKzŗ~邜:[%qA(#=;7CVө+}#9,M~R4ȜbuHq[H\^uv#$鮼 7HƏ3̛o8\୩n_Cn[!2)uA \>Gqn!]T\g~#ᄝՉ% A}"9F+Nw$}A|NB5([tЅmJ!)*aR&3%Hov, sjN+1~ dk B<:1!U?D! -#0%HFX 3!tdoTy!wEdaTE%L{zl5!@uR['q+=T̕YӚLact5"菎$zǡqc\\DF3 eά @~ L S/IB AxW`K̫/P$R<Qg@,ծ׶Rt/aCi)&E=ms;.nK3I+hh!K5 x9!p djǝ7UҩU6ͤ`5y.3DHrO $gP $]H)$҆Iш 8rjf:-V(O*1J0Q:beE&0fʴq4 rv9\eSiL; ļl (!kQWSa+ ]25$j3Ef$6cU_{VzIe$̔wĵXJ岴(U|Ϯmד c. 9Ӯ jQ3\im:`趞gNKN9Qqk1A~a.B SU&Ku=ƫIel+) "J{DO 65yx/h@ڑ S CgX̗p V38=P@0MY'Ӧѽl)NJj:*rW=D4b(WΔ"MOTbDU&S˫>cR<[0TcL" # lv;ҹpʕ6/>\!eqx4zWyTrC>C0*Նvmo{0wR?#CuG/^m<ڋ4eT@AE Z0|,A .C9e4T}h+PEWF]É^Pur1B-PU1\V*Fۿߝ #;Ոu\iζk FZwt ҝkKp1$i'_k,XJ`|??hWK 䜍iاbH`y1.dVmU BR%i#kU4%}mq(3J=!1(*Og5r tbMoՓp pU[^L i<pXUTh!@I RݐJiDU=KٵEQoqD1ڋ^)MLQ|mוaZ+@ʥX6vdc tN@ & Pز%х jqR D PVuՐ2neD*R_}#s@WHuI / xA"#z!^ 8  $i2.&8aT:bHcV"V pdƜ@(/J !$L$IR9@dEJ$GNБ FDF\A-TaG`DĽHd$0-#dJ e I:FR(sSt e@WF 3ҧQG.ESd=Կ zr*2+d.і> l nc*i~a҇WjE8+\jP@^^y $I%[K(l9ɹ x\Ɗ]Qs:E̫Up!Ҽ,jG/ i(yҵ E LTN(V^~+:fQqr}uB<cXɮD(Pb`ԬQH'_N =KЊDFYk8%>-'MU(i7o"+aD b'ދ cG 5dQ7exI0HiƈXDggcO>V/$ j HF+Klfk$ޘmh\%50%Dt% 'Qq`/rrwI=r*sH0IK;o3HuK6vGSqD |$RHyy\HY/K>r" wL3H,m1nrxzRQ&Lij@8JmXCT28{~p+ϐMR-*_"gM8c5h#&GuH.kN C"#*D6Za \W? ʹBėXWmPl+jWֳ #Jց-Ų0[UҲ>á(5q0TCD$rT:IG"ㆦ//גXħH54k@oK7~yjHHo_yx&ab:5S8MTW@:zxωq|wKTㄇ̓AAjw]H[')H<(sۺdO/&X&R;W8rsd (LfKŶ=@AEBg8`'Ag|A6bhxaӸƇScy' T eɔVa-x` ?-4̏o$%z:ӨIb=:#3z ݊&U@dJ#2,MUJRJKY&UjpР޺H2";֡Z[UǛ%>#ǧ/G>:C7!?qI8BŃ,i(N$8:,?2)|*>~z@( , "eH/ϓb|/̓(Co,> |BPJ1bcKlxPUTD-@j-JDt%lT220M:Fl<]cCJ̖'x+Qpwק$#.  >\ξV7ꉷsK2C+K2 pS$/r1I.3=sSlpM>fIc(vԣa .3_ε?Lwf(Eh 1/F\´X/A[ϰ5 -k ]>QIXoxR$N/2,Ne#:kAԤ84;kC c=F$SցDt^-! !-ࠦn&-$QpA d[TJP;j 3T$dH2Jy{OXɛd<YhB ug/! *Xš n- 3[,i) `g~=aQA(sJrAC{^r<DyAD!tNz)!CuSGͳP$qIb$CEq x!f则y D%QG[Z /fRVWjj)KKt*3-ˮb혹T/=3]aOlq2q) DT8U=llI vXu\ H@YO@(A2HZVȴQmʎ!0k F4F}ʢ-5_u_V$䖅Y1#R4vce`fw|$>Ђ1xabݤ v Z pNTʍc <t<*MyDvAwe&Aˈ7`8?SUIn̢Ѫ[bnwIe46),:`ҡ}}M |֯Wn7\×]!pOz}tY^ 8ҮAh ;kD<%D"a|ӻ 8AH.cbUٲCTKh4zX7̕IA.7uSEqbg=.M'o.xzCuP77qflaCԤܒ= kJ9mTۋN'nn/13ťQ9(_=jdF vo;􆩽m|'A#^196smN>9{''V23%bH]Xřd2!O-U(g>v M:xl*ˇ.)Bүj. |eeSJK7VWRBD ?kv=orҾqtr 9k w4ٻY~d"K1ku\[=&ALQ#p ?cF򫡼v,=k[s矂úz`G-* ^5dom.NI a\"Xl\/"L}l8 W Nd$#U4n+OHI̓5 K ,8tNBO*k>ȼd$ `$.h&4*D2VZP f14/Iu&RͶ漾-ΧZߠv=.&֨Z"  fi50pc\%-AN@2 NTb@dVH$ܶ#ieq3Hqq+RM$nPKtaȱ1,&&,>8$J%LXIgL݌RABAFDg\FR(^礂Lɑ܂v( 1-JbDez0#d`N A51|!A֑>GsNl)ɭ:>jj c1. fZ4X\'"mlE-p6o)/%劻vG$1? X) k5q-r+n2'y'R((ɁI`N1>n KG"lI2*x>8/’DnDF:G!|%DϪ-.$6ҋv*A҈&ڐ$Qo d$:F1 1_SB0xpR'{'2(9(,GR4P*58Tܢd@OcfB2~h*Ԃ.'lh,-3?s3pOޑ""KNmP5µ>GDd/&124gn9Q-:KKNt10ԏ1Ϻ(|2I|nFFFGSZ8-l>v$|"=3= H1Eqb2uHTsA?5sTtdK@&MaLje",(wvh8c"W 5Oq8b|kQLgvsSHtL <#=`CNuT@!tTM3S UkZZ#M.&Z38(T!WRC N[IRبPOkPXXI.FURFFI+%d\G-^ҼE=( ^68l % 'PoH P^>A_sAJoB$4ڠ*Ab&+4/rDbb+E`A-Cv&$Apw&p!wq.A,VVdUXgFG%dSR %Lb9hi7nL΀Nxw%'s!.UsJLAEl7<_1anZc8 GN)/rn1$涤FGVn %O{!p~w B<pF!~ࢴYdnն/UGca jVư"5*U1 ]Gf& cLPBJ < EMhxHx>wJU8k8k o/-&{QҶb×)D '5d5s. ~"ǘpŌ!Op_$V-ui/k/_6m}9tcc@l%Ug!ERu%hn\x&.y. H;v8J5y` kZ8&KEH MmE$!i|ЊeI cbK)% ™ϸp!( 7qpM zaI;KZ=ׂAw,r?pS&AYZMB#֔Cr,@prprڲ .s}Z(IxuDR OeMtӏ֋ pup$!ray\! AVeēI+zHQ]"ΟkԒ$bx=iZ_t2!!QOf7 &H/{S-bGG\m6cX\qʩ\*TDN Њ[s08\au.Mnʹ$`YƳ \bwwsr|Wkv:rWĹ:#j5\a\%rQ6,HFaIMQ=K0T]=)b^a3%#IuUBib晰 1^8y}zWm&VڙM ;Zx;Kވo< ܖ tJҧ W{B dzRRI)'=}0=c]֧an=r=rP("K;s6N1 qMY=hLQÒ=8bD۫=$恡T*;Y&o$!-]q\~!%>se]}5=%2H% 'V>~w>~>b'K~ߞptarށ~!?%?&-1?53 ,!8?E -Tuik)'q?uy}?L_>T\N`_?ɿe#[_ʚ=|Te5_0ltڭ^ѱ80uL 'd$G" /zƎ5̌)WFxLEuQd+s QAMӧFF9qqLT},(|qv;=6WH=vȦn68onvcdgj5l n޷Jq2GbD!CvB"5Fr6}%M*b.@,c6w}L8*b8GzDbs1, K.Ï !(!RUd^y$fhܖ1eC)HKInP`.vKJɐS#7h.ʨ5 i~hM ID*""1L.D%lYɥyafujcٓDT j딚! !al#쪌yhI;wLkE0 KkٚbT6[HqZ&VO4"- [Т,^E3 ض[춭ݓn70OX@ U$&A&@ dJ hGjshxJWQ#nq ƂE@]L! u3Yf}o@qoF;[p-F ؅ж}dt  &; L $Y.HP $¯Bv˦@v w!xyだS/j:0}={+K gX!%R DE2ᅠU5匼Cpֺ<7ɷ)e8K̘ȍl̐wnjN,[X WhL90rMzRebcf=YLU8߿40KkXM@ `MYPErh=˔&,:o4SLls3d~itToX2YL"%@|b\UҎW1 42hptf W7?r[m]veݷ{E5ϳB}n/p0ܐxKv=wr @oLEqi-%< *p@|$mI{4mi] jQ v X.ˇ@d́a]7 X>t-BX PES[dЍ|; 8|<୿W̽ \!oCg$& @W&}j~g0XvW'd|(,Jea08Sxi'v7G a5fW30ȸƆ8x6`gZ(]Pl1l>׏f&6jLj8m5qU֘=ب"`*,#!"`6k{f112dHGؕ}5qǑrq L~89wa+]a#IyuqC jɀ7UOY= v!P{&.I )Iڣ'Փ>5?A n>1XVWhydLٔ$ZF:V))Ycy` 'ye)gyiZVtm1IB(nt*6IF(ő*օib [h9_t, prШ{Zy񰿓$ lxgpHK' Vh%+[@UιM4˕- rJh^giq;ٮ鎳tWgiPy2ryfȊ3+Fs6^szFsg`zޛq 0$JK$)j f,[Cj >]iBۥYo5^YRjzֵ[c: IgS]Qy(]˲EXvsň pmѽA\~GЯː[psKKFW6kxb\D UF]l]+ CQ=ªri&lBZ(9`R mh^Ygtj6g&OXf˪ѻó-@J :uG< Bn+\^t([|)l*cz`r!Kk,۝gYKJ5my|*+Lɒϛh+81Lv~zz8<;h`f\`|W;ǵzfgaѼyJ!П k{ g*8_*Gy%u82]@Eq*Ыsxm9{'=n f,6"ͪd&ܖ]ק=z|BӼ7$1ռTutZ9s ¨yݨW\MvF}b_չޑ}M)1^* X͂&hy[vN8X^nJ^w?I5.]㩫]Ϋ*݅ ⇗.v藍Cmq&ϧ79 >~BN;DڰM-^&[-mG,R!j|V ֌ ōx- AӢm&Xk.C('m ]V<>UY+)`g6> mծEG E=/j:zZ1ا !d~z@iL6\g`ӂZ%6',Mjfk)]Nw>N8 vt[ԾY}+FER =Fn^^LNֵTѹ a>催`}LcN~]N0J帒1Zp|}Ͼn>}-B 2QqnN=MW箶NZ),N{3UތS 9 _b(AU_A6_ ;_fu԰czgΛw7qy6СEȏS(i )`={3Z{>N)̽A 5kC!6I´>FtN>KTɽHwt 3>,LX[hHb) 1RSh+ܛH pc;J&! ƻ+/03B E$+r,2 2( 38l4$A+-v'֪(ClM7J/RQj :YF yhzC,#QY:E:|Ŕ|Rԣ'<(3욧Ϡ|l@`R|j6@M3S־S84‡0'㚫Nd.TLJ1RԜuVoZy'*,:,,.iI+Mv]w7b; #;3(rsd:`+O] ^DV2&iQ{Hyt7|(+!];B:Hׂ .X$``s% .JS;RV-&ekTQFPdhlZ%n%p\r k2 3]3 ,?Z` B*4izYsѻKJ_Q?٨IxCCBW'^hFwuO-HէjA8=,z&\)*`#:V MQmVF R%qlksmG@ɥHq~0 ܜf5TMt10 Vո rn(74/!Z;L tB:EgcȣK@o"ȐE$5$$CXgaA链#LB6ɫ$N$R #Kdd(QxrqdZnc.!H\ej`x)51,rS).9dfrJǷTK Gǘ t'sy"rZdLf@9@Fr-!JV(i/]RcAĉOդt)F8j3 hRyU,D"O>Uꡁ0v y(I$0I&(ySf b|O{ pZHQԶ3%T&rũzg3z1 CHYɈHL%GX -ͅH\I~ZLzQtx@AzI&|3E2r,+؉YvjR`#U4#HEgf6QaX;~~qkXͶ: L"L^Dʼn+ ?2i}DJgСI'[r]`*r$6XG3dh'ůӾis`M<-p‰ xpD"|Tpv"k $8խSE -:,u ?/R.Q hPZn;^O2>%C2TVNj\FP7,b2C5sd#9VkfԾ9Ae %3DjԶQXVl #"uaxhlpT3(~X>v>ך0# ;Sk4X[?3b#![C?<': !+dP $ T㡭x dA6)XP![o;::;!$B8B!0 'l`Þc=*$4U'ꑐIh8ED+$ M4AR"<VԾWqq(;\4z Z' | ȹ!p!CbPFػl?|<[7VF{ 1"r I@ {2G(>.e٬xPkSGG)PBQlAt8A;C<{8ȄL…0Y'Y)ðqұȏF""ɱe|?ƒC1Myt3hcS M 6}:~ GS>& |AuBCy8a)ÇUQR\D|5'5 KK O 4GG!}20U_ 8C1K& yl.FA }PNU\Nyy ?K,jkU0Ou,OIWѩ1X:(:]܉ӃWp݈{UU}=!.5, m݉J!DۼD[=ʟM9+- eUBXTgYUE gժu]ԗ ݴ|Im1n 3j 8F$K =(ُ(Z|[W͢MMH/>*:qӬ bc;}ykmےȚ4p GR[q?rL :-H 0O1l@ `Dу_ӔTܣPr +Ա,3թ^ ͽڼ\8Z9S<ۭ|H?]Ȅ;M = YE㥿QXޖ]aOQM;6?^Dh2٩%RW RƯǡY.KT:g_Tm߉M-U `5IY]x`+BHT1?n Y``U",F֊aa/=DPU.k=&#] I`!N"~_$NB:%[SfM&L'NeXi,ˡ`Z2FƿU8Ɂ1 568_ޝ4%=` < cu3\!kJҚMM_j-^U]3*Ji*ǡqNFf܊+4 Ӱ#zb61T^YmiY0n們\g`l^ZmTV D O:cW&_g>&Fb89Dd&aG3a%tV3ZbdЅp%`'H[ Qj+gR.偝-gKRXO ~*'T0񜇡(^mip5#j:ZkLSuk؎VF>>/FF LMxgRVņd"i&mfɾXl$ꁘKø,-K @}jINÞ?QB&pNm#VWV&d }norP)SAr2dt Q_po!N*VpiǓuqG&YY>RA~v!J 9Թ&, gs)Æe)eލot5"XV h|;W坭^n`\VJW3F t/?XI :9O9ʼnppq+XS*_fAIB@ z6N2̂~0^xPT܁;%=X*zB jgp҂a }[qU](`%8Q2SYj#E2 fhFڤ: %}Zu.t=[&&ydB 9,=2رӝY՞eE^zKE DB>v\d*Uj˯a(*.Zl53 v_ VNHNC@ HVTH*@Yfp~D8O0B5#|uL tpI ]b;L΃| (m}҂}Ե]N%M˥拭Bȑ-`֮ "$ t_ApHNL9-ڝN&B>2u zu96:;ٳeiy9wOto]:iJt^"[ vs!$qY@ UPs]):8O&:LdIR2N.yEz]n*V@!?NC $؝Bz DKT92ϫFHQO6[5>hPIkƕo"k+8 iHӍ7-[҈ 悐)1h\.ƺ2Sۤ2 KfzYmzԓEd*O`J$%tMZM[&W>ς7D88Lƒ\;BZj5J(A]6yz Ȓj|WKFx$7bZe}ZR}%_Ȼ~VJ- sj8 Y@^UIX;bbY!&5)G17u$6S!c)ݗABh`sK\"KHSJ8M3W)II|0Iy{{"#'9M/<#+?/HU@ɠCJR5y[.xLJ?t2]b[PoX] @ tG_;STmjI,|1tll@\52(A;EOIu3k'7苝xtw/h4ͣ8N%zPwˋ Dh]UTzTfTP|Q?eI]mPM ܧd_S lNAO(U LĞM9XQFIS(r#[A `]FX]F^Hթa)D S'\B`e F\[qDYbP)( 29Oxv$_ FXXOė 9A[Q5"TDZyIE- B aUI*JKH,0DTx8oGnQD qd ( B4Q4<"E9}ECxX䌘|. OHI'(5nD7G ha~v,Q UVŀJE.4@C.Đ0*da{ZgBwٯQq٥-V ;ЫX.',֠FfUqM$brOh`*K]{ *F0ڒ. exjP%1BETEW h.J0@?j;*iarDOP*fgv1p( ܕ:s^h@4>DeH8*5 "!ÇEExhGR(nQc%*`:(d2q,eb) CHªLBD[ZiTYgi-nnRĽI@8k. #7/ B IZ%K a/x/b)s΀k_C;-k&'@(8~ 3Nĝ J11THc0sS4ߐ tڈ3HbBAB\,?-A2B1Y 4d},ORY"EPm /XiX&W\J.FFK]#1thNe8V1 %~'b29%I k[;Y7K5\ES[bb#R SY?hO˂ ~>;U}DّЯP,z'23L-ȯ 5 *,YLf.k*KAJ; 9"Vc68 ,耶Ȁ!dp@;cJ{(ԲZΧ*ޠƄI"nP@n*;v 8*|(7|b7O.-]'F<0G褋rNeG9ՐT-mD#D'6(LԞ*,0jHԜ*3x X@&$P=:7 nT(_RQIÉ3l3d9KRu﷎ϠĤI"ZBJIsD(f/0 );V?Kݸ SUuDZό 50=CI*X(B)-cq[LKPB*zJQW.+勔a~S:ꚠEK4F:cqTcUYYro,]r*Bf hmܐTr6>CԎr)p y:pC!5d3-%C$ٛCHS=ߞێb.mJcԱn.A\)[pGEԟq^qQud. QBvƺ D` ZƠMg0] ]7D O0Z-xN[DK`6"r<ل%6{2+be4ZktPgc)Js>AQ]OMhDJMiML-BhZҙ.Ke΃LfrD*RӜPKxla? P(w sCsR*Qq N!G ZPAu!`PX,vUfC(#Yrvjqo˛ MHF76)WO#. ;!ꔐ}D Ū 8ˊDu4n[r;/jm4u[ @ ~,@( c^)LVQr<^)3I(UQl^ F~ zw3kL1jWzY0*Y{{<3xvK}NAȨ@bQ3$椭SG~``gP)6.كR]o,ZJ@'n`<-A ~*o&68\G.[C(}Aww@7F[<յIPnM4Cg @^сW`EO$g2ȅ!3 _sij7Z e< {7:;>7("Kof[\4OwmDW)F!Ji)f= Ing+T@Y{vvĝզ{OT2 | 9TËa|O(MkvYiBBC؝!ԧhSȰtRa",`P~ h %jLbMƭpƘ+/MX"-.8l¢ 2'oKLԎ nb$Nq,ޯop-!HLn΂ 4 zo "C!耠*| ܎6@ -N O`خk df j,^ ΍ ԮB@Xm/0l R(pa bI`l.|ưd"(J cJnC t< j l na1,鰐nAq0ob(nP,bކH0 L.0-lvz/p H:\ͤ4VEQ!OڏE(:u1#.Q fmAPOC:@)&MTA1#BφP"q(I?!o!:kq%bRȈlC34C  r"M(1(1&%c Co)-j j<0){KnȲ*&$76c7?Bұ$.$2q35ss P+;6;U/=  p&۬*b=3(io(m( .!ANR$0"?g AFZT}$4r|#3432p/A qDɥ %Q|P1[T-PQ>/WVI[r(C npRa;T5U*k"~q洷F){W* F?Q1[%e5OGk/.@<i'F5- TZXZ^_̊O?4$4BJ?jFxZ `E%,<)Ea&XfAd̖uG'I[)OZB`IIc?B*nERu#JuU>+U B^5JP@2?&WcǦzU S&B BKYE隵U`@1c"8vk{Kf1*q55<6=~P]nB@ggqYǔ>6Vi!hp%# k>+wl5] UXت!PlE6@Iv[ J 2A{0:ncfkvoKq8 K?{*!</heWE Z& dxVH)QsbDWGYkQi/xSb74RmgK*n%jfۆKUE|xUl}W#)!.hunPJTWtiDbK7WXn|73uhwjuc swFY bSITHIFjE.!dUq$boWWMJ8Mum|cBY]G5t &v)&pX_lQbg.`SUء@7+ta"Y#9*S  /,uk]:%_3x+/XRABA%N8c(qa8HW>XX k=KvG6'G.s5\x `5+|!A0y!u֋09E>6Srvm7cΧV sgu'e~04=ܩ ͐m}xXK-6al@ Ϡ ă#TagK ѻ_Q k!NV%S|jx:m"-8Q/飫;cܣK߃-ͱ˲l\3zL0ٕo=Y'ayE6 A\J6|:'u<25};]^c;uW8&'V/ A! ˁ ^9'+caCP͕bg]9&Fs>yP@^TCs!nZ#k;I %*!A {oyg*\pޤ3eUT)Ëg%4Ǐ 1" ɓG&QP |pKpZ00ςQ x@3&J*ի,PgVv=iBBTʞM;G_ٻ/_>qyNȏѣ1I$ Y&Lub=3I-2HJJX*ת`7 ̠+#gR!'nNF|INl|qcW" ѪUXڹ{ߧL`3s^`3t$yn]!'ZH6q܁ˁՁ!So 1CMU-rC<@AuPG5 T fŒ-`XV uZ>[qU]y՗`L>sX@nUB>B$!feF$`2BvFj kƜJtJCB(\O IrWF!tcZ%V`'Oy ]B A$N3\j>ǼLwש1C+I#LTv(N-kNeo]cADQ&*T ;dV]}U Ze\re^zW1 NگYR)0lJ5GQ""[k%vAؠ 1O5CVY=devPɓ4ޝ39"; u7OAoUʲ+-H>|5[Hw%R*KBh%TVdM;H$a OQO$AQ7,*; 9LRT) >32˜|j8_?W2L9Z1.q\S={?nE"[ AǬ"TqXA{0 ^L`/| _8|`0&H V^sBį40H C0Pn%.qPFMPg(:"N'F{ U`ǹp3Hf3w^XN%O Yy~< @JP}J0 jNvD\(cXAPbр- +ysMAjhC,{F1`L#a ɴ=m36iL?yayKLHbqQ#BrTӥs:UO `K~Hv GV4]>uOv2^upG,hJMb:9d'KZ]Hd1zVo%1Y@²v ^DؾGlgKI p2dMnoZ*.i{"nL0D8,rԣ xKzUzWhs1#Cza]|a7_ET;{ [Xp/|׹X/7TRB6)h 6#쨒+ŦMg䁟>8j:2`J rHPc¾"Q ɲ Kg|qhNf5+ i|fww1ts|I(| CQǖS,'9Z]qP1/(}~,ӳGJuD#a8OO fAl=\#Mb Ef[m0[L5AizţE}XqaBoڈnQY̭FAb۝Wz0@oǎ+_;wB[ G(<GmlG ٚ ]&lؙWk髩 )U,]9$MaqΐX;CcryXϺַ{!Ǟol<0׿1rO>(" h`F#3ݰ@b- j K>:<\EGgQ3qhOsy豌қOW77|}0zo/% ȻyT55C-V} }uK 1Ŋ8w[Л7N"cȿQo7 ħP ՠ 7 oV,}7ix Piӷ}}<~Sie"NWW~*ycS҂iEG^p8:<؃>?8'Xw hccFcBwXY6#xlԄUMx T意w5 oUwòxR'U1GL_Ow58a vr8t$8wP @ HwG8X(VuIw}P Pxx浈ш g| h؊ xG P0waXrx1Jʐ8e֘AwX PwF؋8Xqx(LJWw|8ȉxwHwywY^x'7 `0 Q2z79Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yy9 ! l&X!W{Xa9}V19ASڹ4%V9YNYYɝɝQ9➏cINg@S|y5Xz"Չ!H8>Ŝ*tA| 9z2TU+vST!CG:#"&2'C 9CD B0U r +%!GzG;cK$e!"O@O=2P:VU5aj@JD:MgZ¦XL*'t2:vB a(*sMբ($DO@]50F8cqO@-`9s fNjQTSVX*66j0G>@Rӂ-g0?F68'i *qSqjsZ qT᧳7eCQ L Q"ҩNJDzDo0G"5zs;FTT qDYS*05 a9}(ꬵJMJVOѰFګVQTaO˲1:mA/o*aZi ߂9zi :g ǡ 7$)*@/ʫ@ !: A Rڱ4{&۪ &T8ˠ:WZ0kGc40G@@"sf,0\#:5+ZoLdz 5DR5 8K˺>/SP :ẳ ᷃2R_, 6*ӦRʨyGѷ?`*X;4G(U<դR; Zx?pCR%u !1:: S:4 Z njMT:ZU[CB:a ѡ;[ЋoK,;ƻr"F.a@6fgd軾B+:cSauDK7 `-|љM% Y [,,xqsD,1`NQ&|+kLKCAL><\Bn D|p|91d>V}j^#2=NQ假NHalT/N>^>ڄ.e a~!%^m%~.p0JřߥV(ЂR$_֐Fmm?qFAx 2|xe P Œ 4x<z҅ a"UyVV7G~ [{/_2"UvgqJ@ G%kЪ2r+̑Ʉ9y՝E¾o~_׿Bӓ;eKwahQB [Z!TYrhDmj.]U \- $#SF&6 KO̻%n jc %Z/`q/,!HgEiu3MR#-KRgkŭFAR$ ҆ed $٣ hcP[UI\Pl"8m`ȟk̎i|HAeG]bRZI=jW'd6s7s#sFRb: )Քc fc(]{tt&瓘&Iyb¤GQ˸3u(Q=嶩q_ `_QE7:>tڀaf,N{Yd8C(B,C{?.lYlv7-g_}v`J\w?[hyGgFćSYǔ3y-9zؐ|r !;%ɍ\\ɸcѐ(r|8+/T_ƿay"(Eϵ iwnc)o7 pGA ݕX;kߍcBh^e[o}~{ωyx<#$\(6N9+_C )kvTȍ9P9b=X{?y1+3˅\6I7ʿ *uhKA!47I>|{-6z-󡡲-@(8}:H8>!a2FrB@㨭pxR Z?ÿh V@$i+=ӹPfܲ 8^V=]@ȅ[:pӺ, jD=.>J(A%K\h{(14`"~k 7>{+.+I[I :ȳ"6,90AXn !H$RJ8lP84գ/=@ @Dc:  JLLLAՒD6|yXK!4U=ST+ 5>@388:AQ G:#F/4 hhQ$z+}i<iCg9,:oCJ=<9(_ ʢ,2;GtD\G A [ǗGH/:AR>(+ӵ%Tq)~)AȇEcJܪ>yB4p (I*ȔGPSL ΃Lt3=)9 l=I/C]B=vlLE6\j<Ȉ8!c<&5r2zQa$XF @IȻ&B‡4I$2yDhc+&0Lf; PI$ACgp\Ը(m#tJrH7rM<Dl=(Ʊt3HVD΅T8xK!gR92ixBqȢ@d|;̖yEܼ 9UPX4L6(P8cJp q[ЌՈ׀ A'ĕ{ N{ԴMdѶ鴤ٙWB`¼,E-`,`3@/}0=M 5]7M@3A5 UTM]ȕ ʭܦ֗zvd.hJa?A eJuIĄEHZ!.iUQ5GZN7, G ˿< Է -+B>&r[%[[ض UݹZ#؎\1 }x] p܁ D3LЈ)ĕu ٣WYku] 4(]Q͉6- !-޵ %ў -.2R 2 _EƏ LۡTהr`^k۷} h89IL+U^|<ҍx@Ee_l`u$ӈ Hd&76̻[%K NÔF壦%0|^~:^<`Q妓a`K B X\:B^u6< )A2[\\4 f3@c5666:c]5h^`J>N:}N<]Ҝ,4`F~G7ڬdiV)+dx^2ᑌA~eⰫ|exLfcXTI9])K+,f^!`5>eN\UyPM >7P֛-?o&8go 5gt18UuL~g+\3޴}~L}+'ˬ%&;=P]3φ.eG.2UcW 7Ԝ <;ӓn&;&6C^21dށgdYqN鰎SrW(K(Y*( mTqgRֵU[7dPYdH䄅4h,h,оkH4U`FMv,<3CDielql|Zرl8K%E6}#R;nWU(OV>= !d` a6N~}E6֨ QX4kO-F^&%Aq1nlGxNidŠR֘"g1"w]#$5T= )BmX$[.>"j f 6=IH瘴+nkO;֑Ι? tE8]0QS!7 H7EIOĻ"'lM杻{KXK@v0uS^Wo VWITl 27U4ɠ>]ws+h!v3,#Ŋy47jxv$t3TtF HRAeTwnՃ>xyWrKX@1ZnT\N26'/_98`of4*AxxxXxwEwR/g@rtaV]Xp+'_T?*LB~ Fpcu`gzwSͱ? gL̮|ogIJtoo %z9"9=(-p÷Pi78ἐYO&>s(>k\W6Eۋza}~-iĮceت}3 ,h༄ I׏rNAO}g^\NJ:{yT3Iu^< XQ\GrISB˝; I7$5%TӚI&.mgB+,:"VPtR%bUNl@M,0jkY $ϓANs. 1+=12H;`V婾}ug ?-@g/i|A0JyQW~,-ZA8vbkK&ᒼf˳ô `DKO͝7iB (4Ch OkuAs:1* B XV2qr1ōs7}g腃Q;鄎 bN2 ÔQ[$]@j_\-k6;& 6R.bDPñDg@'(uyl,`6.)6 2.Sd@ *H@rldX4'xׇ ,*{@ +̉ p4mF mRG9T3%KefLW^s40o0sa[2%T07ED}*^O *x&L9-ݪ9*ozxwc 8 'Z-g _+>jq@xd_IHgu  #^Jۓ8ѝҡ L_WTU힢^H$sƾX(A@W8_H$4_P= D]dXA ൚F{@l p<^ײ '߃P "YpEP JU:A8KLOUxb4HhM |]JIDݏ ! I X]A t_ Ʃ@D?`4@ fT! #i4%])NdDM e R XA_?ܯ=c2AbNcbɄJ\.uU$ 8ݙaStUL{hU9I!ud_[t ("AqcA(dXnJO֢9>Pee`_tDR,T.Dee+#WAz\dpIZBfCEPf%6D\`>ҎE#QF"L lXJ\ha9jeg~z; &0Z1(fm@ \=d!f]1BG`^|́A5YpD|˨J"`( B!I.g|HPF_|%}"%BݲAOb!H@;ldH aSIhGmE1hMq|ݜ^R1JV(I0B|D'>huCv^r J"AxMhXv 'g(fW(1g~.p Nb~jbi椣D!Dl$`bYڜ(,naf̞&Ebf#ALPsv7&ńcri{>{.*%Ya*Ȧ.\Ulre[,_5ijjƗI>Ɇ]PNYdOdMBDv`izZ`ʉD$ yu^$Fj:N꘨ bDkpj҆~\PSľ~r HfBY4݇2@DDU(fZ>[ZEfXNP*e̊DU< ۺlRlf%%E]EHm](rJӦĭJm$s:B,J"ExmDKtݘuACs֙,ܖeŦ"۶`ʬN7.q ]$fjF(h:Q.~x<\.A&vD.Da# NNu崮"/?A$(ڕh9orFWzZ0+lnHLo_Fȟ-nf ʖaJ\`hA0纄W 8n S%D`R̰]_Koޜ'":0ݞ Jie杺fWp  0ζnU,vI1͹/+QFbB _npHӉF.Ih_|xrW_Bm#n^+=iUaȋb[Up_HǦl2nD0N '!I]Z#~tI R#'WA.H>ƪ@n*P~Y̍JoG1Foi{ȁ l1+"M2Fy1hBL3K#e#n$ 8[rWp-TsGy`._#U=d@2D+[+PAʥhMij [o"WGZtԾuosAi kiFxn)i/ۭ޼t@Hg2mJYXHw6+1Bdr,1rS Ngr@SUm) j/3WsۀuZFFs4 W5?UB ]kӺ!{ḨS+PRLswR lZmIfcO# *@E+q貱nDE- ߒJ0f䂓׷XUv JĞms']);jID#lf X5XXF&-RAʼn`_ġ hJɀw&hhq7ZgGud۵h_y1cܚMlZc5@LPBMlš* >$/Gnh6cl+*뫉_]d2ΐE30`)9}j?y1?0ITzմ`l h+3W/G$?pp7"AdWE$ KLp&&o(_ ^lŋw tzA,&ˠNQV:p*ZBMh{ L@;Ga)}sYUBɹħOI1/ [ kGdpFpQ\D FK'aj 0;7-c&iRueq ˶#iSGus5y/:,|8|Gh|E1P<#X=cAԚ:`=y/xlIH(/=0"5F@pkĭP"kF`FG{us 6zy(Njf];C{-fʍP{(D;;p<@%#ߔCܾƩ̦f}!GԨ1C|H/y+3zElfJpPA~: 7BJ)J*ªoG`,~谀pq ɽz |4H*ĒB"z 0 ʐK' Rc&bLRJR t[*9[: 3L-$Jڛe@t"C(<<@PBTUl›^ y VvΨ'J$ 1z*R g_jUG4FsU5fE݈; ` R2-4 {Q=T'ԨMU=`tL(%=%9P4SD:70i6MI /9k$HTvfןi sizv!aG,Ddj~0\,@j˕]SM |PKt;-lRO/I5˾z#>M&aD-=cI ' lK[mR$&$|cgjZ@|$S=SW-lnBE\ 9V~E1XU^MlnxW>G箻su+]i](i%r@Ii Ӳ`r"K*P>)9@5Mpd*!w fn$n)ь/+H³y+t_A'xiAixB>D:#.~آZŶ4qn蟘ʅ7 @1mtz^jv&,H*It8ٮIDs Rbc;- r$ [GM.~ dIX3i\7vDU "D, D]//K.Z-}`dl#\i N5l/4 GùP T@e%8A,e}J `g%1%G:g) ښJ0'DC)zFc(|‰.!4P@ 4:GV>0t,`\J./TQz:JtdNTn$eNKaѳ?? HB$`\5P$|@CL$HUw7FY$!N3lBգaA8fjUC֌\LNb ; UtA6Yԛe-@A%gh;ZV+@öMU,d ɏ9 @"NKp5ܑYVM91'ׅqvAFG揁)mkl \Hwe#\8ǗgiJPEɴKm}( 6#h (A2UÎ9ܩx"DqQiQśz`ȅTa54q lE3/4@jQGBΚV`@l6Vy,&s`l>&!:da%* fm1/wN,΅;[v4~5h[nItFyTz%> R:Y-zWP#Wmn?i57vfLbc>&@;7MB '–]Q7ZJj=ޣݺhF7  4{M<GiJࢱ߿Sg枩'7P1H܁P4D*mt<#TLL7DŽY:΁?VI|ޑ[ݵ%ᬥν+dv8tQ@ݑ'^|Oӟ:J>%>=HjZ?`n[SwqpsUTi#2j7Ŷ|&t<بe =on nx, "Mhr/O%`J`3k%֍>kyɨO$B,$&gbeTaT%rϳSZkf=l'Tl[XحlR"ܺ b/2eUrAl@ 0ʊ2C@LF@&g4a ,nt_*"RbHg@CpGLq ,YԾn|쎨I!dU]&h@: E>B0 1"Bdڶq;6s"273y}1$:R:Y5T1\4kDĊ.4dM/[# PBa OPsM)>DQ?Gu?ˬP3QUqU&<%R@VXVqUt6y.xsXMN1xjCdJMGN4bpP#` o.,HFɪt|ٗguMOplw!449lyWVX%n.yNہvH|oقDYeP!3J> 9 Qf[#t5LZx4Ise:qzc2Z}ZO |Q/wlՁ nEC!im,l$yAe4̐D^ 7 ?doRcraلx@Ǻ˺pq9Kܺ8S7d=!{zvP۶ *o/WGXk9lCD+}OܐwZLqF%%dE}&x١m@o03jKak r{6ڢRk.47М'c$vx afcRQ1ɘO<ӗBz9<‰{)T S6wHw5P oU<]|yPe,'lo J1|ܔIרCC Yf 0"h*%7?WXM7a [q X_@\bM"LN~On!D}3{?p c9[oNM $|*뀡3]ӵVqbdmK:ܭ>\vn#Z]mi#6CM;w&K)-WY}빓]V!=ܮQf =ë}&$,d!kxw#fwNBSWMCbg$ՔlԜ uP0%L~z!MCUqxch v9ǘO]Bͮ}"p4}iIgc#0hMd=MC`ZCٲ)˩#e󮽹ފ hH w9g_7A d+ >u[GpUm^߭W? d}YKw8("1UV?/Se;sD%)~29aoIɲ2=w@ 0… :D8/ĉ+ZHFyrZ4h<$~,qaƘ-(,OŠ I4ɚ4Rg $q̦Q>SR%TQ&yƠ@41!ɬPUm̙TW"pZjY̶ ݾ.zfР!pBȃg{ dH\Jm{eʭۡݼ1dȑ%SP4a4m|#o^ٵƃmOMszJm=j,(PdǂuwԅѮQVKצYn 6M)u>APB8viUeTC \Voa'vѲ$ph},f^Sn c8#@X XP9%sX~12IY%L*z*R@hb|1 gCݱU6`nWB"PxBraC^b~x@8gkEeRyqXP'cP95hc=܃O>7x#& J@;Įפ Y`L694_u"$iꪰ[A^XzyYlF !BrY[(9)7B(&e兛؆^-N5 gp_n1j\Eʹ++7(0|eZ&-R,g t"1x]r8nS酲'cޚM+iT T[ Т>"[R!(rWxPx)09U5ϻeq5 &K%||*8&̓K馛ޚ72+s,B -e@{-}ߘvѺvu(fWJVr֩v mm`~98 -_{_ǎfpOn>TO`)BK47_>Ǜ.*ngXu4S@XB$#Y@q^xĀl?11 /S*Lresf&I)#vR㉏T 4%![ צHn!s೶#87ux?L*j#Mb<@.K@/&a/2]b̅fA,T s{/TUT$y0jag=]KN1s?,2\Mș!y׃p!]cv1TBio8<@3lw@)걄|܍:A2f tZl+_*OO@Ӽ%Mg"rI8eJiyW S"T PD)FFbq- < pt,'*HTj_PтL@ HU*S C`;iaPY#*³JTD*lf[ F@ñ=BϓQ\2#F^Sf2W mv o rFQ@\T@e/g7! ;{ALk.)%>)u5x u|EL; iD3VDr4pG<}f3$ &hFl9ߏ/v?pT听[&TC婔%BD{Re.3\3GR2֝9쒭99("ډmw^grCX楉%\eT4U&NpΈH\Ӑ:NَKg4b! xvCZ71UR`o|։:[{]Rr0 9~*w+$S:x' !MN@s؞@ >?t 5!xPY* GCibpagbab&igm@o a{At c{k)͖,4P~luppJ|m|̇=||W&}^gm^vp}n]W; @rlC2S^D>nvSte|i1qo6UQccQF"S=Uxmiՠ $wzPjx Erm qpnp$"k8{+ZY81Z|ddPwQt)":"Hhà  c#ɨ>v,j'fsEq'A?2Mp&5tUPj8цOo=tXex(qa|xf6yxYfy9YxyCA)Z `0Sc|` [=A%i')+y/ &A1 1I@nhfHI'lP$׸n|UdI32kqgJl!x7Y z "1w{q%1/{؇,L_ y)$/IaWd!x"ɘᘑ)95)0ē)Vq3B,Ud7~gKop2xw5q&`ҕ,/ _g4!lɖnIN9scq k/a " iw-2iɞR ИA&eq83)4)Jj 9+  *ڠ 6頀 j4Gi38+ʢ-/ 1*/5j79;a A*6zڡ@+5:H0RZU9Y[ʥ]_Z"cJejgj1mbF ð:PHcO $QHDg``*Jj:No*jڨʨrj0w:zz|Ҩh)@55!52uIum@T_V2$*.v9֪E`Vu-`P6 :ej@j׊٪:՚ Zڡy+:He6sn0 _< -odI 0a]% +**z\E(5T\A m;A\ )+˲-/۲ 5k*+Z+) UŲЮ)} GV JwWf%Be ۴eO;r{`P \[T q+sKukw[ }r:K+q vCJޗceX ö26du [m[2ʱv -֩,; BjS&]˻뻿K ++ {SH [7"KI+]X{A\*0 HJ۹DfKT@8\:Z ˿ !l   S&F{$LK^u9$Jk ;A\Sk1e0l\[;ް= Ļ @ElGL\ jnI*+*z\;XX K${ `;Ʈ;)m|i;k۾m+{} ȁ,Ȃ܌(UzzGju{*T؋sFdK\x̬5⬤LMʄJn,˳fj˷˹˻˧B˿ 0lnjɬ,,avȬl׌lͿ[,Ll\߼| ,L2lXuJB,=9  к<  --BBG!,b22BCM$̔g fز((4KLW㫬z80 B",,8jȉTCDNl ))/..:Sɕg33?f=( FGHhablHP`*$xp𡀈 0pR@P Ǐ˂'D pBH"p@c 8⃃}6qb]4lӊ+ VPa†*"=')zpѫƩi | -Bi ]xbM !<ڤ#(b 8 Dd($A !,G'22BCMڗ$ KLWڰH ,,87 /6:d((4fB.% +hڵReȉTB& #< * CDN..:B.&e33?~12<*gablHA\Ȱ nఢ@ *P¢È T E #V &2LܰР<2eI!(100N`(P`ЍC`pAD,PHAh`@CN+8@dX!,c22BCM$ڗ KLWڰH,,8B&d((4e+ڵRB"/ CDNȈR..:ȊV33?f *gabl@p8 &C&H$ *ĠQb @ :| b@7s(``šA9$j! I2R"t ͬF֤ QUk6xuԷjH0@G 8@@  xtJPf8p'!,\w22TT[,5)6Ưdl'; 5iPy7ԛ -? Ʈdrl9>>%.}PPīioQPQ5ܼTVRn+eؿqr _ ij=~ΰXĪiQ 2ʡrqƭfۼS$ ۻTrkLBǯd zȰ@ pŁR@ƍ9*X#dHLvRE._&͚3o sgN<{PEiU4RM]>UTUM^՚5V]WUlρeɎyg[iٶkхZŃWo[Lu8 3TCpb roM9ycÞ;e6t[>j(:j$oQ -bۍiՍ7SP|1)]$ "10P@{`p,(aÂK_a_Pc 痎É@3_d`| _Ap0MpasT8`lQ~@<"T@Q p,0T`4Б@$pGBnptv̀%ҩ#D)u$lB)w( աH' ; ' X06^iu~9ECg@&E@t Q|!=m|Q oW[i \ fZj+WVloJ첿&T جpQKZ:R[ QRON1&AaD`E!,wS22221111112211111111111111112273:4<4>5?4A5D6G6I8L:L 2 "  '2AGIKL NPQQ&R/Sr%:u(7z-512439381:1:1:2<4>8:5;7=;CAKIPOSLVHVEVAX>Z:\3])^!`behnrvy | ށ! %)2:DINֺTѻY̾^`bcdfltwuuz~qeVMC?FQTYmʄȓƭȸ—Nj̇х֋ܒH*\ȰÇ#JHŋ3j☏ Cxp#H(SD˗0cʜIܹ͛*q JѣHNٳ&9JJիW|ׯ`ÊVdӪ]˶-LDsKݻv7߿+È+HŐ#Kɘ3kv[e)CAzKFZHE{цvyc>,)'H*?u(JVĜl9bCdt"jaH6h]裔V:VMj馜R)G0騤FUꪬtFf*QAbEklZT̎lE6+mRZDfmJ"nD㖫.BCk/p:TboC+b2D ,qR/tO&F(焁BDȽ!qzFbs^IAxD~C 'y qP!ɏ~# +Kn0"9Hs@,9F G/',(GIʋ\#b~!Z&2 ұ\ju\`)}tA YDV[H d?`8֋\[bؑ Q,`JFQ^+R@cj8ʀ O.oyY&yPpYF6Tex@B8DXFxHJL؄NPR8TXVxXZ\؅^`X_"12Qlpha>iikȆTVl3a4Qh4A2~X0w2Q=舏hCDa9X#&b%1؈0q"q"ޱQ;-AZ!Cb>H$a Ҍp""{R:=("##"E"0"#؉$#ax!Bb!]"($%%x%bBt%DAj2y&E'{2'u&ݱQ ;Dk0X'$Q=&ɒ- + Si!!: <<>DI7A CyL7NPVXK1 Q\FW9`InhYNjQՖnY^g sEY32TB#j^3icBƗ1(5BqY536jO8qDV56lT7I8Wl )ubQ\S8lIBmLxquf+閼va;ɜ ; !8QkiIi977hyɞ鞽 q)1)K0ii9">cNAi?TSXA)@(CTRyKɝ2N*MH ZYEB4 p1R)xB-/J57ʕ9;j=sʜA:! aCKiOZO 7qqV֤]AWJ^:AOtP7'X =LDYNy:MQMQ8jcNPsW trjatPS zWE DVZ UR$'RʨE)U>S5YS8eP:UUUXeU[A]URʩ%WUWu3{F%kXYvuPzȲ%HVКڤRڛխe|*j򺤐Xy쪮J: Jj5hEi&8ij)%H:j/$ȱHj2Jل"l!&F33Kw ij ۉ6џ8ڮjN5:FWO?ʔ]{_Kacekg i;sG|}7rwr4r-'{2Gs&y6TkXODyq_Nt ugOTƈU!}] Pc'{ vOv ۄ{'t |'vWxxכ7yy@Bcc̲ݒ98B7;m-!_MXcm͕ډ9^ּYzr uML448z<\]M؉hcWH>> EQEw}ZQl-* CR8ٛBZB7KB,KaSCЂѽ ֦m-BFx-C܅~ M=@Zݐd6 0!U:Cmzo+}-uL癧L|JRa0uN2[z*P M:UiJ}v豘~k$馒mv@$Q_/A#B0۵Jl]=،=sL' fƾr>Nqq+mqKwr^kw8w5C}|v:QKS5)׾{ovv:qzkYv7wp˺Gy|'zҠxnRu/K{gLAz˜y6Q Lؽ|L +v} ug}+|W~ǿoN1a] Qq!,wS22``,,ݞ+UUxUUԀ+x<((xڪU++(U+ԀOx((d(xPP+PޠPPPx((x#+U(>?I'((PP -Dwwox( όVKfUtuO 0$h 4H$/kp6tJpݭCIIxȠPq()vΌMP(P()=e w--dwP(wwKLWUUȠUw/DExx(PPxBCMjoJJ딱_,,8|dd@zKЗX0 LLl@KK= ((4~ݳP iliPEmAG'sJpiTOf@4ږq 곴 CDNfgBe..:ْc?z{~Ŀbv()3cbb33?`Mڕpd^gahablqH*\ȰÇ#JHŋ3jȱc,Ył@$I^S\ɲ˗0cʜI"<0I͟@ JѣI'ҧPJJL9yʵׯ`Ū سhӪ]Vi-lʝK.L˷߿LP#^̸cKLQQ%:'pÀs -˞-3T@`$HBo[]|'m?M7l BH[ ؓ_ґj6]#m{s?7(QA6Afvx UhaX[o'P@}0bUu jA=0 3GHk8Pghwd~@F)LpG*Sf\"[)y0!-cepƹXLx矀`j(WBc 裐 hVѤfiDnu ꨟJ꩖ꪏ zJpڊbS* )r0X8VD!GWhpֆ "D X0vrkKUxQ W@0yKR'U5R+, Su;WUdz tLkbz |LOٌD? 1 M,)9 IMY iy}=fE~6oWs\7E̛2KwD|p3xP]ƒ'x@o9ϞsLz0:7N(Nَ{|I/3JPD`^Eh;@ZTcЗo4>Za@ لH4}^moP˟Ge u@m5 D楄R8irFSPX@m[!"CP  7C "!6qb1DJ5q UCl0H/DHt|d(OJYJXƲ%$@-wKYqt%.RFP%0͈̗)Әl0i 2SgX1%xbsfkr3U#fi}0^bEfi 1 oP ʖW/n(Lܖpy+E0+j I0V,ڕ5/pr׺}l}-wxu(d+LV̼4UJQ1vR_xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MŶ 5dSXhG{fmmOF̶pfƶCB(DXQUHhJIwPX4A8SV(FXM\x)^рRA緀.dMh?R./-H}8Nzh.1t(vX5؈<(Hs0؉,񉠨8Qa<Ê->`=H$E3#ȕ1BcY4HAak28 ~+?JɓiɍN<ȜŞ?I$ ǜIJUBCM++7''3@AKYZ]^_i45?11=z{~()3) --9@ \XP@ >P@,NqcĎ?dҡȒP 0cLIJoM<[쉳'Ơ<ܩӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^X/O ܔ@ɕYb>jY3e=c -",9tXu $*0:@""xj`M, (Wn<81sD C X !M<ࡩ T !,Y22BCM$rrr KLW ,,8$<((4^ CDNZ..:  33? :Wabl 4B >D/VxA Cɓ \@BDH͛5ɳN QѣG#.Xӥ H(Ɓ:*PV`ÊKٳhӪ]˶۷pʝKݻx˷ L|W7`! 23dBt<c%&$qzZxP!,A"BTayH!x #( 0(!,L"22BCM$w=  wsKLWqo,,8((4vCDN..:qw33?wabl 4!&dQ"A , l`@4&(0C#-Xi@  $LSB/kDtЇ6#hTpI)B PرX-Eq-[n6 لtl{0/ |J @c(.,\cHpe 4P"pAxp-B!,[22$BCM KLW,,87 ((4"' #CDN $+ablHP`*$x‡\(D `qC #ÏGX%H*W&tr`L gfӠ†xiP$@( ,~ذJ$['i@ VSL1X#H_ SpL3(Б@x BXCf!,^22BCM$'( KLW,,8((4CDN..:33?abl 4P l`NL8ŌH'+rÃ$c/$X ͌v D5ǂKefl @$ غj$8U% @ͦ vVH0!.Z@1.P !,`22$BCMKLW ,,8((4㭮  CDN=>>..:9:433?abl(0@  pA hP@ńCPaAEd)"LY|9@6hNjCf0z`R|z, pWQ, du 4HP] p4X@@\8Z6E00 !v,$U{bS=~~~}||{{zzxwvwvvvwwvvvvvuuuuutttuwuttutsj`QF??zAxBvBvBvBvBv>j!> #CY+)_80YB4MJ-HN>R6V1^ ,j/%x?+A#ALV\#a'i0q(x){+o-S5>522110000//..//111111111111111122?=CBFF^\ߠukmiٻintuvk*\ȰÇ#JHŋ3jȱǏ CIɓ(S\v F͛8sɳϟ@ JѣH*]ʴӧPJJիXjJWAKٳhӪ]˶۷pʝKݻx˷߿ LÈ30#K~L˘3k̹ϠCMӨS^ͺװc˞M۸Yͻw˾._14B\s& 6F(Vhfv ($h(,3͋12#X`AH́(DiH&L6PF)TViXf\v`)de45hIi2ecg6@Jv|矀*蠄j衈&袌6裐F*餔Vj饘f馜vꩤh_6:jzgAݴM*무j뭸뮼+k&6F+Vl_7غķ~+ݶ*KK +L+kSK4@7۫>HȂ' 3[fkn˭TnjA,λ/l(,0,4l8=,їo觯~}XB<~__;jw;;L:zKDM/WǴz Gh ;b *6̡w@ H"HL&:PX(zxQo㋢H2hL>x†W7qK#!Q!mXC<"F:򑐌$'IJZ̤&7Nz $H,jѐ]$"'V򕰌,gIZғ}!-E%/}I`Ґ&1YJ8|4IjZ̦6nz 8IrL6A=i %wRP>~ @j>}H% P2 f3MZͨF7юܞL.oJWҖ}656i*?T⧕( PJԢHMRԦ:PTJժZXͪVծz` XJֲUuj*֦L]+P bZvͫ^׾ `KMb:d'KZͬf7OgںkAπMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;&5Mm0|ȶ}h{rl{NohMz&1~ߥK w4M`Ҏt$4|ϸ7Gq $OWo,gn`04y)! Aع*b E׹rOyNBl@8FxVHLjJ؄PRXViTxZ\`Xh^dX{6fjg.' g&uh{vp v0O }8o:pPv0xp6W&/ᆚp@nx؁Xo41~(nh&p]l8Vq؋6A(Vȸf_8V(xMhظF=84(x-h踎$8(xhꧏ9'yw/ِ hi0Yi$)i'j&*֒2ht5ɒ iu9jpؓFBIhhȋEiDFaNiM9VnUyZYs^qYbla9fYleyj linkmrikq9vkuyzjy~y Yw9:Gl~/!ؘ il y9li])kߒv0Q 4?P G0ig}){i9K 4Iq;ɐ˙fpYH9z?ٛ9g)90<0Il؜fsK !ٞ7o997Iٝ.'jFɟ §J١e wIi4 jf@.9tx'מHi+f->ʣBʔA:Fi=zJ:wENڅMRjQ:V*UzZ hI^jbg]:ZZfjhRlnJrjtZBz~.ّz8Z +٨z 09 J2 ɨj6zI 2*꩟ʙlળ:*0ѫ:zrYz ʬ<鬯 *Jʫܺuʩ̪WתzPj8a0:Pj `௭`0 qz0jr* Z v ™:0щ  ˮ銱ɡ)j=ks`+"jCKK" 萯>:7 0OK&kJ+ ʱ+Jk{Pz⩱jrP4A /뵯kzPlt;< )0kcKz[ Lk5k`oٶٱ4i˷簯 {{ 1;wpKzF {10뵭 ; K;j4ֻfn{8 ݛ[{蛾껾۾gț@+s0۩6 |hy|ș<ˇ0 ;! 7 L1v ;$|±+ !\4<,â > 4q JLNPR%X&>(,2>.^x8ހ: >0AH]FރJ9PT^^2^/9HPNl ݩXJij9!ع)Zc:癞~wΦy Ӊuj -*@yV?Y顎"js课/ny#i.Z޹^*~ʾ0~8Ԯz~>y >wWwW.u9>s.b]աmþZNv O 廝﬽>_/*!#%o',/2π4_*8oz7>~@7D?}FǬ[`J/yO~L/Soz{ћ{۰gKvPWrvY %{4,{. (kNƳ ǷFKH۴5S O햵g˵6ᵬ[N{6˺ߴn rKn橷 ~ +_Xirt? {h[ Kվn {ë Kp+,?nۼ˱;[[˴?jCaG@ DPB >QD-^ĘQF=~RH%MD!0-SfL5męSN=}TP]̙E>UTU^ŚUV]~VXe͞EVZmݾW\uśW^}X`… FXbƍ?Ydʕ-_ƜYfΝ=ZhҥMFZj֭][lڵmƝ[n޽}\pōG\r͝?]tխ_Ǟ]vݽ^x͟G^zݿ_|ǟ_~0@$@D0AdA 'B /0C 7C?1DG$DOD1EWdE_1FgFo1G~2H!$H#D2I%dI'2J)J+2K-K/3L1$L3D@‚`M7߄3N9N;3O=O?4PA%PCE4QEeQG4RI'tP#2M%ҴSO?5TQG%TSOE5UUWeUW_5VYgV[o5W]wW_6Z=OR;HY6ZiZk6[m[o7\q%\sE7]ue]w߅7^y\#7_}5h7`|W` wYv@"8b'b/8c7c?9dG&dOF9eWfe_9fMW~9sf% h$hF:ifi:jj:kk;l&lF{6~`m% o $һox'xG>yw x ]dy{?|G^ۮ׏jivկ  $ҿ`8@ЀD`@6Ё`%8A r\ ,@UBЅ/a e8 Fȁl?8ԡP@<0D HOb8E*VъWbE.vы_c8F2ьW`.4FLeQ3юwcG>яcq@.Q<$YHCT60 Hd&5INvғe(E9JRҔDe*UJVҕ7K,r Ka=#X^9LbӘDf2Lf^9I`d4)LFFA8m qӜDg:չNvӝg<9OzӞg>O~3ф~0}0a-r K~VԢhF5Qvԣ<48'J9Ғ .9'KWj4iNuSԧ?jP:TըGEjRT6թOjP3p\`@- jN\!gEkZպVխokSET`5NjӺGi]j1lbX6ֱld%;YVֲlf5Yvֳmd *$Ba2֫0mle;[ֶmnu{H,_W-p%Ap kXֺnv]r-T }O.o|;_vpe.kX ,ȁ`7p%RHOrt=h1Kˆ6t-C3:AO IWҗt5iNwӟuE=jRԧFuUjVկue=kZַ5]ӽ-i ȱlf7φv=mjWvmnww=nrFwսnv[F iodGx>pGxp7| Iŕ-!tyE>r'GyUr/ye>s7yus?zЅ>,`!7|\Bzԥ>uWWzֵuw_{>vgG{վvo{>wwWw|?xG|u!7|%?yW|5yw}E?zҗG}Uzַ>'`}{=\{={?|> ~]ʇ>[BGgIAڑw'?~у ';o~_<~*v8%?X}&;%@X8@ > | t P@;Їp*,P x.PPA?|ȇt @ԇ'A;}v W"A/B@B$|3A·4L P#,APpAt%7dCX>,,tAA94A3|%' ĵD A}`=AADDS }@T@x@,%@U<-@^ aDF(;dtXkgFE`l"(0$XJ)XJ'қK)5*(B -EӔ(-R14ӒX.>)H29s S˿7%7TPJtE]BRH(ЃԆʰԃ`NMQPO%UQ=/C]H|RmiU%[eUlՅHM;Xc6B` ,f /Vt&`;F+.؅tEf 1vB%>B=`AdqacY~Mξ86W8>eUa{(6W~Xb4]nc;deP/>dj`Aʁ>d.m 2&?Ncf\e6>b6vuKs6Xe4t>jd[aw6V#a%~d6ge;>}&6FVfvAiL}雬a0XR)PR Ai%;Pi%OAf6PRj%O J%.Ȱ=jQvHJ@@깦k kXHpOjA lk^k%kp촆|$jKp%݁^^kia6^Ji;8mf!,w)S..--....////00001111111111111111222222221212121212120;2H3Q4/'{"y xtpjc^XRJD>:!5"2#0$.%*{%(x$%s l^R C0#    # * 5<EK*N0O9QBRLTOVNYKd:m.s"'v(y-{2;MN$R*R&P NJE@84 0 + '!  +!6)@2I̸X%˘3\ϠCNșg` 'ٺ_ `cڄȰȓ+o~l,|U$g 7\˲ Pt1\𭗫_MMbP' {ݫ$M`: { 6XaWI wݦ qCP[< Xl2 88⋃A(K*қA8Q@X"5Q BL3"B9:U"d8`z+ ad9vDْm I4'm^zG f*hU G<Җ@ y]i\VW\o DӡjꋢDꩬ\6ꬴ^kM֪뮄JS+,\&+V2.lLLR5-LxڜQX´KΦRkAD֛I+0~g[G' w 1GWqo ڱFl (P6:m4+J )\zB7>l@ Te46Eݳ U`m)A(Pm6Y#gTFJ34Q<|GiU~qI_4wF~,4#ktyEgTH'L@fn:RSD.;^K츻U{D{YCkC<uCGo}Q7T۔=Cw/~L/3ϧU+t_BׯD#lH9f;@|6Ff Tv ʻ`A2+l)1VjKi傜#(}8Co99OנG7YVΖiNX_S@f<9UƓi8hcʻ|Ae65LmXa=s ht :6n 2&?8`d'#d@ Tn؅jVk`37.)Lu_%;鵹wC9HuA<6!ǜhg:M1B͢u1Yj#ӛw50cvG w{AvI $TqݜCM,l,xʅ>`|ρxd@$q|%,/T#q8\g܍3mn͡vCE6;!O@vWR;ރw&T ;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OO I_IǿoigacC7Xvx x'sA]b R#ȀH"x,؂)-/&/rǴ)7~R.Q AqZ@֐'~1/18hфa qS" &5 '#G]PU!!c$"$ ' *$FQ#EE##>"&6$0$1t$I-P4X]B%)%(^'"&l~h….&&f('wb'6''!~w(Q(()iS@)bD8 ~pAԘӘ[ܨ8ÊxxUHb1xÏ).xIa y,Ð y2/2 -1CAx3'y>3dTx5hu4OB-y47YZcP`dI6C5wCHL@c8Rk839vC9p#3@cFh!#I li[np5Qvy]xiz!yF9Sٗ91 GIy╙)@) aٙc9LK9PA:1<3)&BW)iC$򔍨Z=dDiDP)EηZEYIXE_IwlFcSf6IkPɗ i?ٚ9ɟuZ:Yɟi\ ?vDơ " ʠGHKKT$LDLjh[M]4Qe9քMD ܴyQC)UQNCTkNɂ)B)APO@TsT'EPdFFdwds7 KdpFwQFpjVZnepcf\[vfifbfTfp>fgxg|g&hv !X;rn gs]׵ii&jj'jjlyaـ6B'i6FlR{l(gjj&mfWmmmVp FsֵunvFtooo֦M; xWpAQ:Qj1qiGAoqr rʖi&罐kj+'d8`u_kn&ssKvAq;Fttp{ OuSGrx[׵xFkccied?7eldp=vp״Sk`wx5ax 4\6|8:<>@B1#%>L`M 4>6Q#>ך}A!En3mK e]ِ ^wG90 I0꣮.~?:` Ȏfnꫮp .5JP ~Ff.À 9&eJ P-[~G8`AYYKHxɸMA+3)u3:PCT O>7T$PEM$$:4NOw/y_CNU^z-S8o*\hPyڦQvZ]Qԧhԩ*<`eENE\D[JBeEE*!UqTx_/UџՏd}$4 ~ KQYO3 JCJzZ_| DP…1QXWQD=~RH%MDRJ-7Ċ~l =}TPE*|y4Lw2xo yP~VXe&˴hE~NPtkV\uVڳIN'^… F: "EY8fΝ=9l㠏NxKj֭]kڵmƍ0ٹ}G\ySƗ?]ndOǞ];nFo^ǟ?e@/@\o DAS(B"iB 76 }ҰCGHDW-Pd1F?so1 r*61Hr1ay92yfhrzFz9RˆṞ٢GR z:80R̃Α}bsq#L(H)͹PmGD&@ͤ@4J6,ȩ)=':| z2U fbƊ d5kf-hJͯǃT݄3ӊND+!YlaVs5n;'XutM4S fHj ^<c9h. r+%v.$t;"lD(iO,e`2[j5Qq9Mx9BB?I=P=R5R-T*T%U VVVVY[]_b d"d#c$^%W%M&;&1%+%&$""//<TvC+p6 [0C'p /B' gI yqB#$?i&P r 47A0'L"s7AT1HݳtJ_PtACSFhST@}d@_ ̖][ @pםtۭ7dx7='Çw'~ [2WεU?w[y76zvzz밿z촫5{{1.1(g0biksRYH3zRklO 4oj[.]JrMH0{As{t%@NoA+c*{!@6Fmb87H^Kɺuu|')Oѳ4ЉOݳ"@Ozs,Px*` m<jJԞeE/ 2G yz[% )H d,O .m[JJldfәg|Bɟ,#zTbټ))UL]RZUf5[[jUqՐ/6Tղ,j+[Թ"vW_Ӽ ~e`kֽ⬯`K2a},"+YQ,f«UhC/ }i6v^kkD}SY!7 5=O! Qh!(D{@}@щ|@; BO-DV@ޑRpM2 ~c; j|"EuQ_v._;2.ĐjGz{ 7l|PC@0[sۡ8>@$`1*+<>nqE\`A}ߋcbx+/A׹hm' .b||B @C1 ]QtwvklyU]Fei 7zSa~f,!.0 9ȮeϦnn\`򙫼,Urs]SJkwخw?aFuh Ft{R #;&O5\!kX`ǼW[#/Mzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;Pԧ"$}{꒢jPaGnv*e;^+Ąt\ag1w#/G')AU@(c{؈p6T(1؉x2Z@5x6!7a`艔X񉸘{׋ȋ~[HXϘ?wj1">r8wH|膆XHXx?}(h@8 9XR97R i[)}7 WʸH 9!y&I% D+ɒ9fD" &S^4B/`3E3YEWYT[$F^da3JlFpTEtTLjF|aHHB>HId4EeIId4 FQITntGd?MPKƄA6t/H$LILhGLtB4MѴoM1$KMi%N 8 y9Y)9 pR7ɓfi-I)a;RlSX5 S VHމT VdUɔўٞduə$UUSU՝ؙyJ j㩚 ʚ *Jjʛ! J vu[*l[%fmǕ\]mӥ`e]BgѦ\x刧ulp^_Zidv__!_`1&b vA*Kْ&aBAajhk &b$Vk)b-]c[}Y7n+A@B;D[F{HJL۴NP.tuXu wul]_acaf+zfSg;54&LtezsZ0$#yzx%czٱLy#e|K%! w ׆|B%$VB};}G#p#8%#'~ZJbK!qU+_2arx&'%(]n'Of85zR~"XW((z p;x+};K{y?"{L]2I+k +[n Sh{+"b (\@blT{3^ܶ$clD O@lTC >(jƌƖp<Č >hǢܶȘ {@iQUl˿ ,9x\Ƭ \T&"lƜ@ӜW \ P< llT J@D|P8ͼnlLLݠ|ȩ DC Ms[$= =Ķpe9|pŶJLHp ;0< 7 8!>\T=CXd gPQC%!-i-ңE1` ! <@سCכ{< @qْ?@ Ĉɸ͏4,` }ֺ}-!TqBȽ"bC<LK*+2+6y\VJBE`_<͍m2N)NPJ!HuTx]YGJa)NeIgF[֖ ~$2$TqJz9M:TaٔaBFB+NM̤GD͙d#)Nd;Q.S^UW2 .]N_na&eYްRiv peihv15iyɝ~>ў&< !~ UyU 1b!<ޟb%^AI^ΔΓ >ݫ.^ܳ[孞Ͻ.~~ŎѿN.Pa^2?Zg!ub;]e^mD:+HAĤ>O_aUj]6`ﮥ2vZs8)JAa?jd`ZbsFt7hcP<}۪RVae#f<6jZevel!oC6zfZr)y0VfT:E&zi nlZ0lk?ׅkV`v(/^ItlFq eoŕm*ecFYnY!,w6S22+UԀ+UԀdԪUxxU+++,,UUȠڌVKU((xBCMP(xPx(((PPPP++(PII$+Uyy(x((xww--P+ix(р++?;Z'(@\Wgm[ᆱY↓ H@K*'aO#j<p-c1%$W%0*\pc.ǜ2l'6:>=N"oE't Y8ALOWd0(k+ᤌ+h-n1,mw_8gwmB+W7F*xC s末=ygt '.# jIQn 2.v|U?Ot}=o}UtB\ @IqXt^$UњH_2 .): x9,>HYfEsqL׹=`nI5 jp^'  DV@6$TaXऀD  :lA~2Br) Iܡ/rn2,{fӈ51bn|(Gѱ#=֫~d IA[<$He1z$$k%I<< f2ƣpOrsq+)/RFk ZFX2#!kI/=,%r@`ÌH:yLa޲+L&4(i l6mrP&)N8s<':uMLY8㉧yғN'O7񳟬j'@)RdP:0(B}A9vH p" @ & Be&ȠK3ӂI@p.RR9&@BhVpИ|ADz('kZ 2`mW:U:QMϊVuKnHI@JD8U)@ 1e ѝj'\E85OjM+ƖV*NB<ʼnIRϤ K@0~ )e[  <8.P QA[$'K=,!kC >5@߹Mo/`%;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN 38yt~d}^Yh? `^١mhD3΋~4dpiI;Ҏe5'4)iRc`:#mr&:ApJmT:6RusXO:סPNg<"(3IA!vFSg?T h'T BM .h!D#BN?)zQudn:B )yvm$/<iS|g 񍧵C<.?9A8pI9"C6GKsN+>yW.739҇󋄱k\dnJ19:D6D~[do#{.JKSWzE2XDqc>|#e;'? 0J!@cEr5@B@b@NdD @PHu4A4DdC#[t?KCDFdB-B?KPtCdXC4ĀpCg+A/Z7QDpRDEhEXfE m`4FOPE)F%:XX(~(ȉh8؂I wz1JTtČ7v؋{GKhڈQL_xT8'荴莶(HhT;0IEP80H5 ɏt8AI!|䐓dDTAPUQsUQ1ɒ_9Q gq *%'RTPS SU8u:\SA5TO9 H@Y0YTLR,5TYYWESU=U`@VH[YTVuPnvsUWPxV{UXtP_rXX XHaYYjEYYVYY5ZcБ5К%Z%[Ru[C[[[SHAh%c  eȥ\\5ҵ] P]\]]9^vV(; ` I&HX^EUy_P_1_Tlj@ 0ΉHUbP;0  V ` 80 ː :$Z&z(*,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`b:df{v|ʼniʢk h/m60:ȧ蓖k|jj!ka}kf&8`l!!ʧfm" ¨nfb!~n"o"*"Vf}##jp7$ʨp2Gx*覎᪦ z몮ȮF(H ȯh*Yt2+Y|auB`~H[W7g+J~HCpvnGgPP S<[g/G %5/'C%pCȴ紒5LxGp2WB G XC`y%0d8{`(q+]˶c˵ y3;9{#*Ci}ۡu{Uik_&jN@Np{d q@릥 |Np D j ćD {K {}Sgu ;M,8h=u{/[7+~j[/x;Z 1;h1*蛢 k>X>s3P~F?t?Ј4@}htD-\wj<1}DjhDlhB8tB0Tvx@:|AUCTDFeEȈxE(#<@( (FdLJ^|k|hl+ǩjǡǴTܿ|\,|L7p(ϸq#i,:=ȸK X%Jl9|ƢLƩʨq|J˲WP7Vy_35Q7Q:_=Y^Wb9JɔuS9EODaETKىn`Tc)V}eUUjBlYe%\hzV}9ryQW XRəp噦YlUyoiYESW9%?Eeӕ]9E^%Uu{hr\lڦ!,tC{22>?I#'(DE xy &$GHS()&&2^ 곴++7)¦ww  b()/00<)?@J@*\ȰÇ#JHŋ3j8@ CIɓ(51˗0cʜIJkɳϚ7qJѣ Eʴӧ$.JիNʵםZ'J٨Ҫ aٷp:Ԛ[x󾥛{ j Ç+^Xe <&`"C9@ hװO ` dͻwI M8F6x0μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-Dmi|@ AIZ@PuA[i)-)m)qӝm)#l}'Z/=8}xn D~@k!,AhF22$ABL JKVB8,P,,8xx$Ǧh7CMPBCM'(xȚ ,"#G"#h((xP𳴼..:((4(xd33? ((P@*\ȰÇ ,ŋ3  CQ #SYR+cʄ(AM\`͛&QM*e &Kf4zTXR)j֯ ބ@ك-$ٷJ@@Bpr[@l c hqY LtMӨS^ͺװc˞M۸sͻ Nȓ+_μnPt_}ޙE|?I,-7++U++C  CDN..: ((4  Pbl33?89C<@H"Ç0E'Vh/4px #F>,pp@ Y| ӠL\,x ;{P5〧O Xv򜪀$h%X*NU뀮X"pq`-8t8\0 $6pɕ @r9{7ӧ^`,Z_î)کiVuٷM>6 !,T1111111111111111111111111111221111111111111122111111111111:?BJM]Wz^}`xbzcxewixlvnvpvqvttwqwmhieycrco|`gx^ao\]g\\j[XmYRmWMnX@mX;hP7bE5^A4W<9P5:B+97(>-0K#;aAqKS[^__`acfimquvwwwxxxz~ a$rG݁)AxLҵ'Yn8bœ1CC2w2]5$dTYai&W[V#ј`)AZnq})8UYsYU%"eZZgJRC<4aVLG6Ԍ6Bꪬ*Zɜ/뮼뫉,ɰk&"[(, C36DIW;+k;&%@D4ļ*vf(.AC,bXIG,ԻWn//lK,R,A 7@²7`$<&l5(4t16'-&좳(B,|B0D$bKo4+-՘I(8m -5G|.Bؐu-ka=(I(TvPR5AZ7^XlQ~+- #{'R4BP3~Az>];B>*Kל.zG8&_Dy6_pn8-,O0+7r{(@`C<39A. 髞Ԧۋ7{s@2TP5bH5^ Fw> /sjE3( a A"x@ :(k@ 8!C@r >Š,XeUPl`g8P JP@Ԃ ZbAF VX/*^0r`(- "/Rsx ljpOJFEk@@8کv1(88b̃#dCV@ Xra dmtWAp $myd F x!r `a@n֒ "&'9!YA v} 9> О-Ik3ć8U0 l]Nd'yA,B-9N 8:VyBeH쒗0%*2̧̀1ǎ!'IC% E.t  Bq~M+gSQ4D4hI-6 &D ObVڒIݣ\a9  ^x| ӭKb:G$j|#؇= F\ a'V +,NֺULle/ vtVMk[sWЍb\bOnhKj¥.wHQxuui^ͯ~/$:!|y˿}Ml6ZbEykX/@ňb+gL}ozF;74Őm-/.Le"а8{`L2;"6h#6͈aYqsf>@{#13ЈNh1V9K%E@bǨK[իP+gYyZ8 ~*:m+  "^@B@=0Hh JDPDCFPC;Pyf6n . 5C DpXjF 8ڦ *z@rT ګfU_9kP["J 0[-Dڢ 1@O zs 9 0FP 9P@ B  XG  ,[J[D ~*|pFza"ev+v vˢpT#h*@q uEL j#[ J1BP 0f0F;C`;0j@ڹ)F:ږF Fi㒱"o .< o4{ʡ6IȪ 1 f  i~t +zPj@s@tпRg l9v ?*<;"˽zʲz0"1gJ9! +t [4;K-JF"/ĵ5,DĠ. PY?.)j 1e*mVEKZG9H̱"B 5"pJj˦J:kj?Ll|C%ٟ%Ci\ˡi˺L˺.L˪l\̲} <\|؜ڼ fFkl-pJ7<ΙιI!`m`?,qҠ6j;:ן /(; l@*aסj>|j=؁-k2/ umӕM=wD٬-j mѝ-=&P;5&DM ;P5`y lj1=%%$ٶ= D-PDk uޖDD]ܳOY  PBXBuⰐ dO h@LutES Q}tT0}y  %GcLBQ  5@LU-NtMAaV4KTYC^1} Ml%I >Iy~BL[NC5ܬT4N$RTE%- M3v PީeEAL2^M$EtE< Iqsqo"L[ . : ^@`njʯ~.^nBʾ^P^`e 1]acGPA G =e  C J#`n+/'_4_68:=xpy` w_C!qP vXZ\^& `?d_fjj-8 yvh4 ݠ ;?_000N  (33?01Rlґ;s뀪UUUH*\xÇ#JHŋ .ܸ1Ǐ C ɓ(Sv ɲ˗"ȜIL8sigϝ@ h͡H&5TҧPa4QfBSQj(@BWmnKVbׯaŖ]v / gxuW2M|髎m=ku 3`p HL1Ce %l.~0ڹ?ov:_782X׸w&@nhe$;@R4L[*cGN<ͫȟOϿ(~ G Pn6F(BT!K aG N :x@# B,zXbPȵhҌ!@89C0=fx\P8b4Qz(`@d D)bHPR@\ccc^ppW '#|6hpFL  dglB%\%la&ѥ#lAD飴FF**&*~ʪ&AF[|ib %- ;^yfQ +掉oB2-F o e,c.B~@ BK r }}Q1#q!'8%6ӫ@ȳAmtC+|L'MG >KmuT_O`-dmhl tmxM@y߀^6-'|/M8Gn4ygoAw w6꠷^%s Az9g9=ޔ2,>DD?N %|QO?<,`|MN}WU#{OWfz%aqqccO'|~cd X*`aX<L?&<8nz_VÃď1$rG @/ꛠ? >` H>h7$0_@ 5ip?ΰx8y5b$#&q}KƠe&HWy!@%8F&oN!UM^$CޘukD8FdtHa`C!"8(㌔ % Ct^R&q@rqP^R Un\꒗ /9ɤ$*@ofVjB 8I)A98C`[X ]\ak;Ϝ D!&Vյ@f9յR0&͵ p&*M{)ڿwXmf/[5B S~E-kQHCwۊZ1,Lmfec͓_%^OpUz$JָE$6ӻr3(}r-s +FŪW)FYKCZ,-Q18eث<@U cRcUڗ洑-uc%jYi@4cU'n 'UI-T!47!(y?PNgtA Qb XhA']Fa C)ІNks;v-nhF&טt}˘ljGzX@cvӪ31@xeC*n,o@upJUƽkpJ2z-GwdUVےٌ#>)l+1+y`i}`?+EcV-Ib³^ \F]mW,ee;Vj` }x@>^+]vؕf~]vXЏfO=`Qח=PG}Ek~'KT]PeIFsU:Oj4{lޫ|\n;%Ht///>}f?>c-Ӵ(kզ ߈_cgF5hxB1!4 h;1! ]Xǀb""+an[c5)fȁXwh sOW,7Œ7R`X$"qbGF\62w1y FH^ǂ x\wZ؂NxS8qE؅2LM-! !|U$ R4r,[x4h2J؅i iwM$)D2(#DXxq(M$}"ȉH"xXw('%#8He h,Bnx"y8h(؍B≤x"޸ȌhVw2XxVg N N0 9IEҰ MOYaMɑ  ')P 294Y6y59;y|P>^0c`VS00PQ)(A `b9dYfyg)hlٖnYn`r9rQA0C J`f fp Pik&VI? 9Yy@@0 0 UPBxYI%VB?g9Yyșʹٜι i+pZ9S  I$FAdKٞ9Yyy0?@ Ptp  ʠ8p$!,TJ2a22xAU+xתԀU몥UU+U+UxׯP++UU C___U+xxԀ+uuuc++ +ԻU_++++ ! $KLWԻ뀪vBCMUU+,,8Ԫd((4++yUU`_Bdަ$'(%&p;Brdz#++.N@H}_7=HU++-zw C보fU+Dvjjj~~~"_71D..:+++ !xxxUU+UGGGvy+U33?(U+PyZePOr,,CGPcUUUKT&H+U+Uabl H*\ȰÇ#J3jȱǏ CI2@(S\ɲeK%cʜIfȓ.sɳ'B6 J"NH*]ӧP?eJU@j:tկ`ʵY^Ū]ٷp5M*` ޾l3mgR"[z|<4EflXhbi/Bΰ~um x`YBoj۵ n:u%6GN\ % CGoY`T4O4;"L`]@Ł|UMAg!Z=`AnItY_  eL6!8~Ws|@g[%cXj-Pf+?\ .8.褗4Y(Mڍ,C:v <{ҽtoY:MT"_!AxLiP;@A]C+4||Pf =|E%kP"߻ ρSd`I}C w:~>"=ojLH*Ao(51P}M*gChh3g,8@x;0hB %t; %LP14 n8=I R=z{VPbtS뒸MVjdua /^H @ >w552`nl_`#?]OU|79^;6#Bh8bXk# E͟K%7yu 7q^>N0}c]x1p{{Ɣ@)tO]յ7z > y%B F^5D#-ED`ԽwȗqqZcnqG[U|T vgvwo_Sٿku95W}ƹǟϙk m;Џ~T|#- ` m>OO?ˠ~ ?Kv0Zbd p ؀ 耳X =݃WP 00$( (*,؂.0/2X6肚C;.Ёea:?PDXFxHJELR8G9Ӄ>.$@O phjl؆kn膐tXm]!,{22x C _Axת$K.U1/]l!C곴UxԻaԻ3+x7H *LH`… 0E)>0FHPEVɈ)Un|#GbXy` ١bϟH,*rã,x)1U  x #@vɳhHC KZ&0A.ݴ ECq+p^h0Bb 4Pe /8BӨQduds Ɲ!,Ta:J121212121212121212121212121212121111115487F8f8oh6uO0=&'!xl aYPC 4  # (' 4.A0L1R/ W)!^$i,u 0 8BH S_iotvxz{|{z |~}zxxxwwwwwwwwwwwwwwwwwww w!w"x#x$y&z(z*{-|0}4~7~;AEHIHGGGEDCBAAAAAAAAACGLQ[dmu}~~~~~~~~݋ׄ}yuz~҆Ԑל۩߸H*\ȰÇ#JTŋ3jȱǏ CсI{\ɲ˗0cʜI͛8s`ϟ@ JѣH*]*I;JJի=jʵWNJٳhafʶ۷@Þݻx˷/RP LZ5EXt KLaŘ3k5KcoIhev]Nsuk;tˡ2/Y#ġ<|97hif[;laru$9ڕkyc.2Bg`?E[MTvx"tW=B:JݷBqQd .'vO7++H;h7 lD#p#-a/ⓑ&[yv=շ=Oŗ&!0tϴy>q %"a0qJA0ci.Ζێ8Z0%kC(i楥"m4W)rTsNqZ4:f噔)\ (U9:֎5&xAxFmCvZ,rl8hy>핋~+"[r`֪\$Mp͗ԙ3-衯MYhKǕ>R2jhl{M|hyaܒ2K^v"`楅g\/t6GO'D8W!k&/2VhRv i՟.]ilYҔzv^ snY4p4A=|h?A-)^> nmEN~nmCZG1{\onjpقbP ߾v-xP# 7|[i_Mo87]/ 34=o0? '_ׯ컯N$8 %$s)'H Z̠+WBGHp %8I pBO(!CzvS[)PP _[Ir`ÇHQ8"~HX̢ŢexH*V\LטEVH:Č?>t):A1юx8@:\OH9~KOH@̠ +iKe, 1PP IAKʎ_9Pt)C'IOӘ{Q>9 ͩ`4a9Qֲmdu0 rL 0)*G Yb(t9Mg*%IlVO١p"fωmީ $ &!ʊF`=K̒d{67i4Udz)K?:ݩwR܌tjO=ʟP-ν"Xmf1`9jl&MӅӐͤe!SJlz3݆Yx`[sԷ]koSZ+C@Vą Z5XI-H cm:p+\mٶg7g@4)s.cP E؇grՉ2U*j-\ n4h:)?I|t;nQݕxh> \@ͪV)ծ~Epxdz0$)n9W Ty+biF7"8uflKcpyr'<-xьnmVٝ$-|W8u\e;Kr9;IViT;`3n|C*IC ;{CfN6-6MI*G4'EDɀiRLR11 fɈ;[+^)(jz{w*F h8KEHf;Ȳ5BJb[ G0hqKxnMr6w ҝn;x7sk *񊂷` O;-x1 qc@@%; MrP+-00g>|gs#2xa j@5ߛG=юX^1 /GI SkD~t~JEyԷ C'{}$UHh5dCC }  ЂTt&!{I'~8؃~ǃ`W:ŗ|×'A}tG >x\w|Ɨ|?dKq*k_A68[GVl(C@kP0JD(A~T؆~AoXliTvXćAkEk@8DtaȈ8O\؅PD؊4I}hFAA~ji(I>QSIX&&q \f8W;~$zȍ}荐J[hAgȌȎlh[EMͨ؎i\ yx"JHaX ك%~AZ yiL"#%i?' }),._\i!I:<=*79YEh|+IKHA!,p&22xBCM$ _ CA KLW,,8((4$3CDN..:.M33?ablH\Ȱ@:@ X1E5nТG!Erk]C޶-MSP.*?Ǜ?W ӫIͫwH.YyڷBk6T.B`d!T5dTeU !IBP(шFw(c,5ָ<ȏ@)Di=&L6PF)TViX2:vi9a&Ezp1ijJpԦKlqٟ-'Cx ,gI(Hhq.5Vj饘f馜v駠Z(hJQꪬJjvꬴ e믙rƥyh0GZ#묳Q%9ʖlFvcMitXS]jnmFZPJON5A5Xi x N[aLB"ƻk֘'U,l_Zz|r #[#PZ0h 5poqEP[ſ,D)=~S@JЂMBІ:C%ٌZͨF7юz HGJҒTHJWҖ0LgJӚ8M%@ PJԢHMRԦ.UňTJժZXͪVծz` W*ֲhMZZUIp\J׺xͫ^׾}0KMb:d'YIJⲘͬf7z hGKҚMjWz!lgKͭnw pK}&:ЍtKZͮvz tMz|Kͯ~އLN;'L ؿΰ7{ IA(NW0gL8αa@L"HN&;PdVXXβ.{`L2hNf1pL:xγ>πMBN F;ѐ'MJ[ҍ^7N{Ӥz@MR&WjVPugMMֲw-[6|ka؉"vfHv<1ozMr{?(Pv݃xnw5`M NƦHn KL,$Hv҅$t!V"&x Fx "bC k0bNp_ ǭr&GyTm!Hzc 5? s)x3ﭧ¯y3D_q>CxO/^t/ͣgɟD!AujD [(~C/SVxIuIP~'y!~;~ |aՄ儁 {:1~G(߄06"a}4a&!q5s:H%bA$wԄ{tt~;(G(|aۑ'g8k8#jrx!su_otކwn&&S('wg؁$e_uXS@3F/hЉQ6Q_P^Q.QxqQ;Aqh w(X@&2Em*H}yP|{;Qq`֤1w!яx;`6(QxYA5) 9kE/x>1 EqpA'rPx|M'W&hք (3c H1ȐfcSxyA`YcyPI!)m i a03v9ۑu 2JnFn@9h[Xs8LO9!5XXmٕYi`)9јfh#7\9w ؛eVAir<A)tU&\դQ a x?^YY()ɖ3Y_c䩞ɜ !2iёAQr #Y_ Y ᜃ''x ]ȝ9hqq R}蕆!HI* 'ڇy ؊/ "gx<Afك2C+2;o\j@ѤL5 V{{HI4;21[j)\UPk$SC3\ss!z>@Ӌ,3jkQ5M/1lbP,'9XLœ5a\5Iϻ˴C|E+!0tt/Y\maQYsWlAqxRZ=ƙy!LP3!6œ>R\L@ R8sq65 !K, 5C RSqʤ,̧<7l9iopՔ8PM]pm2L?k 203Cp> χٔ4ՔȝM<<2؀9fmlo1Մlj4|/G\'6l0L+] #2nPT@\\3=D}+>KEH=MVmnM Q}^`]=/ajMY-*I!,n22MMMBCM$jjjMMo .w>MM,,8>iwdKLWwǩ٭?B)!EMMVïi6pCDN,Dwwdw*qpPPP&< $+AwXXX"MM^w@fffQ\H *\ȰÇ#JHŋ &ȱǏ CTqȓ(S\I0cʜK8sDiΟ@BSѣ@Eʴ)HuJjJQZ#֬_0lAdӪԷku;ܻ[k_{Kֺ} +Zw㣁KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNس7p@S{Gj@G˛<_{=ןy-2ȒP)!@ 28dP*׀tx!(,B TވD@!`C(xR w @ 0ACF,!PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤj꩝)@Pª* `@  **pp&,( * l4X[&~ `­ޒ *Qs4В"9>,z"/~ԊU^bԭ etٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nx̝yOW; a˔t0~[| n~L'GdW~ Lh^ A%@ x A_8!, l$!22$BCM'(,,DE ()? 6:wwtuxy7 ,,8}vv~C#.; *CDNT*()fW@.$#SX()( "(!H\ȰaB #FTPŃ+^bG' !D0鰠+Yb,H2 J8Sϟ&=XPԨƜDaiN("T|*Tn(`W)R4 Ph5ne ۳P?k텼{%8}=<ÉJx7sZa@>z RO( A6`\u0!,z22BCM$'( DEKLW,,8wwtu#~'HgGvv CDN()3# ֳ..:`d((( +((4~a1\3%xy. @1`8A8h! @cE !,H0@"UxX&2peK8NY`Џ#~ ( J 6pЁ <0RWi<` x@d ,`  p@\ BH@ 4P| 0Š(0(F!,{22BCM$ ,,IIyy d((4KLW㧨f,,8/ *,,CDN..:78B33?%%1?@K{{abl @$ ` *\! HA9$0r"D8 ,lY%N4 z82DxrҖK4@Ԣ#H82j†-zriph@RgBە8"Xy 0Pƒ >B$D:P# R @!,{22$BCM,,ehKLWIIyy,,8 --78B((4#~'B",. ww,,CDN..: `d +33?ҧ{{]aabl @@`a . `C% 88bălD1@ l`@ #/T8p@AM8aʖ"p-4q%F#AF0@EA "8!Bƒ# 08b `Z]  8ߛ0XL@"@OF a 1$ x83 -Rn!^,${ .#:&4=.?83I):WBhDoCsCuBwBwBwBwBwCwF{cstttrttuuuvvvvwwwwyxz||}}~#47:87a3A01000001111112121212121212121212122222222222222222222222222222222222222222A:N@cKuT[_cegjmqswy}}|zwognu|‹ЇچۻH*\ȰÇ#JH"oE)#F CIɓ(S\ɲ˗0cʜI͛%=fÚG@ JѣH*]ʴӂ:7vիXjʵׯG14ao`Ӫ]˶۷p h˷߿=K8È+^̸~tL˘3kNs@7Mpzɨc˞MmYy\woȓ+_μ-HC7N3!SνbEF/ea_Ͼ˟OϿ(h& 6F(Vhfv ($h(,:0(4h8<@)DiH&L6PF)TVieX\v`)dihlp)tix|矀*lbAР袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ *A íݪ뮼+k&6F+Vkfv뭴;.JĠD+k,l' 7GL0;TlC0Acqs!s ( Q,0,4l8<@-DmH'L7CS|3 T[U ` Qdmhlp-tmx|߀.n{S6.(6㎷x/`y ]w砇.褗n騧ꬷ.n;ťS O_ ̯ QG/Wogw/oZ%+ϾSuoOT[Wp+ؼ6* $" Z̠7z GH(L W@5*QAT" D$ZH"HL&b TPTTAF+R@Q 1hL6pH:x̣>04 &0#LLҏ$'IJZ$)GbE9FO2:9'K y,gIZ̥.w^ 0IbL.YHf&^4 nz 8Irb oҝT';_Z3>- } @JЂMBІ:D'Jъ0J@Z#@$&C/,D,Җ0LgJӚJ2:-hOpNxϻOO;>W'O[ϼ7{RFOқOWֻgOϽwOO>;!z[1~B s{/oC-FQOBN?7,Qq ( x1ꇁKp Π1^p` ^ #{Ł# Q6,(0у?A.;00+!Pȃ@>8"(B8` W(a ?( U!R}TA!Cb/Cp!m:31 u`(_c؅h21 <`4IBIF! 1% >oPғT9K)@9ɕf ?I@Zypy ^a)CɑqjY_9z9}uIpI VeIzyyz H~)zmy +yzx T q<@9sIɛwphiٗA1f>ٝ9I)H!铽XɘqB`H99t (vX큞##I@!tpi$jS) jPY2!L ,! 3!ia ` #@*T0 [j g01UZq^P ^PuqO h!fZqj 1d 1 *Av:yСsJQ^ @yᨒ@MJ90Т1z )qZ 8Ț }ڬҺZiƁJg$ZlYpjiڭ!9ZZIJJ:oj:갨{ka^Y| [1}j, -L++6(#{Apc zqn[k Wl kzPh@Kk{: AfyK[Ajy }p ۀt+ q ෽;g{Jj+:)`h IHK@˳[6{,ۿ[;| +g1ˌ,{8,2܏ @E G=Cĭ? ĞڶTl:(x]L_^~ >^ ] ">$^&~(*,.02>4^6~8:<>@B>2АLNPR>T^V~XZ\^`b>d^f~hjlnpN0t^uvtzOn^01~舞芾>^~阞难>^~ꨞp VnF >^~Ȟʾ>^~؞ھn0P nɎ0 ~?_ ?_ ! ,02?4_68:<>@B?D_FHJLNPRo` P9YV,0 dhjlnpr?t_vxz|~?_rd{/cgdd/do?_ x qO _O`??mo_؟ڿ?_`b(p ЈaO@ DPB >QĆ= dʞŁ zqŎL,(r`F\SL2_ęSN=}TPEETRM'R꼚sLO~VXe͞U(ЌԾ 3˶oo{K_… FXbƍ?Ydʕ-_ƜYơTr幒hWmNeҋzXs[lڵmƝr_yroޛ0^D`^_Ǟ]vݽ^x͟G^z݃JTS@szHx/@$@D0AMPi0P# -4:` DOD1EWdE_1FgFo1Gwb XDk!aP2J)J+@ QÓJ-<10MKM [e3O=O?4PA%PCE4QEeQG 3KLLRR>SO?5TQG%TS :4 όnIuUV]5VUlUVZd)_s_%XcE6YeeYg6ZiZk6[mtXIn}$\6]ue]w߅7^y gq%zwf_i^F8afs[ "E~5-9dG&due6XߕQ^Vf_fwg:h&hF:ifi:jj:k-7_&Zlf~aej;n离n;oox'xG>yg>g>z&K>O%`'|G?}g}߇?~秿~?`8@ЀD` 6Ё<%NPc34AvЃaE8BЄ'Da UBЅ/a e8CІ7auCЇ?bi"шGDbD&6щOb8E*VъWbE.vы_c8F2ьgDcƀ!,T,22Μd+UԀ+VKx_'(UUUԀS(x%PPxBCM((xU+P+^x(UUP+UUPn>+щ_P(?(n(xx((+$`+we,,PѵoUU+Mz~@KLWlDExȠ| x(,,8P=++ w((4wwUUU(P(-,IILBLME"f~ ;sыr)*~a~/"ܵ#:ŝ1Ɯ0 ()Ι8 iCDN-,iy~~-..:ɚ”p_qڅij=y tu()oU+33?ҔjzHvDje{{'(>Cݒ"I)(PPxyf%ablWH*\ȰÇ#JHŋ3jȱ CH2(S\ɲ˗0cʜI&#m 'O@ Jѣ q@OPJJМV9ʵׯ` )ٳhӪ][K]n2߿; \/È#ذǐ#%pcɘ3kj c%! X5AԪ8pH@ڶ78"3i%t0Š ̝CoBXλw~#ܮ:E_o?hٿ֖dwvP`@ W >Ƞ F`߆x=l6PR̆*ڃ%8N!!:$Zvdh.'P2NH96$Q;)hZ.%sU`/9h9SMYЏH h8gݩ!)栄&`n_0*g9|PVYڗ^p*GyMޅ$*kKڕ謸Puݪ +]kâS6+8 $$ f=:4Ѓ[Cp rnJ {Iĺm/ZHD (@!poIp j9p H{n +l,37l/ 27 s3ln PCg PcFQ&6㠬FudE|pנ[r[sl+c [U0 @mn$tLxKރB <߆w^g"xӑ=ē 6I5ϔ<%G^r@kz7oSV _ANKE֤fQ*V= ^jѱ."x0 σ8 h|"0!4,`q :AD8AQi-B X.zxp4 /Qrͯ^l .VƆu KQ\r(د $dG%-EVAm==(' Y*UIS%GJ,!PWPI)m:V|fD Y8E@ a~ +nd@!+Β0F q0Hma( bHЂndlA*H &JAh-ю62ƒ .mF[@"k@Lc'4-xIx4@yK_M=xSH   A T> `XF@vի+ZӢ%H'Ćk`+J"dq^װu,,XXI*+m J6e/ regpV)i UQkUet-Ud[v*m~+ sčqkBems~mH!f#T(Nbg])ٴ(:L77FB ˤy{|ڛhw ѯ{}w.|rbo'ڗ}}}Ayy|Twgv~GvnGK"ksxk{w-(/~7y@P~4h{&Ё70 ~0{"L$XO&xGh~77Rgy'X|Dž@ gX5vBJ$h}JTtLHNȅ2wwxXgoׇ=8),n {gxhxG/(84cN)h!a[$!,T22d'(Ԁw++UUԀ+xƯdxU+'+DE w^х=VKP^P(((xPPU@Uqosx(Awwtu)PU+ڷ?wUxyl(x()$qUx((+_BCMԪUPU+P7 (()++UUU+U++U v_*} Pȳn&((4((()PwUU+.II9L8j yy%%P֞lgI,,8;)!!:vvrcs҆TђE]ڈ`{iy?nz~,D^a? CDN-dY:(x..:6:֟m9U()2;x(xPY”e&-n03:;p"$&![o 1I@nG\k>k|O`NttsL|Ʋձ%|"C#oPǪ3\H4Oz@/1[.#`tk^AW=E3C !qп;dXvPnЛ, 6o |6@lm8M;d ` Kc}/ Q#ӌA+W|*t,P44s}:z˶^1` ld.9kD:ЬF>Ԯ ʱ,/ =@kAH_]p:t$wozI.<$o*`i9`>`Yp"XElu厰.b|$(A'=XI.HÈN ,^QUo}SAOzf+] đfۡïkrQ@@7c)Ѕ0lbV>D#״X9  a2?:%IDIBba胿55<̲Ǐ)8#Vrc D3bQʅ-cQG(%>2$E􉻀I͋A8h {_8E'~h kL'EQW`#5B ;ʭNus"]RgmS9TDu_1WӚcrkx5%aMe3;FѬhhnlC{9k 'g+i%=1[PbwfZxGI Ql#|#d淍mIwm6 wnG3sNxP!?I.(O)b.Ѽ#9!ϧ>Ѓ~}6F?zlt03(@  PEP B!`։ lGNϔPLHd+@^ , )$KɎs 5}y W=)=?v=‚by//P޶n_Q=Ɏ"B>QJ?/=vC6yq>ֱn,Q>ꗯ>ߧ}\m>;vW# ~}|'wyGv5}Ӥ1zxzx [~ x  yry2tuvXx7~,vbx@v/ XG 5PI1d}c{V%X(+&!,T22ttg+U,,Ԁ+xxUUU$8gBCMIIU+wyy((xx((( w'(PwwPo>?I--Ԁ(x{{(Pq PP,,(=#PPx(qw(xDEUUGHS+UE+I++AbU+:6RUtuUBPs&&2x())5VKȍXO!jj++>WPxȠ+Wv]rP(AB/P kCx()++7AA+++P(dwwjB?@J00|R9򲱫_:{A9_t|8ijX:^ѷHK0kh@E2hY1   ӂlܵV0#0!Lp 2,ʕ' 6BxIHH&Piๆ%%uKn_v dj(fhYݙjel)眈Ixeg|XnL)_I衈eh6JӢF*JNjU馜2injӨ hJ6:Xb7JĪkzC]j젽 B]+ɒzmvf6Ї%" 涫o +!o@\["h Ի.@ :/Jlo+@"LoɃA*3GZsjOPa'<^ PQen'.@K ʟW`"Fx ]PU?œ*Ij @z a">aLh* c2Q3TnvC;z,@iD, 0r!X#R=")+r,"(%#H5n|#(G2ұ`#=b~"  A< ɗ 8#0&IB&T jTIQғX$X 6@@8 -iMz:HL9[bt$2#q.?0DdY̌)Ә-IgŕW5jrәI-SN^V.1pN ֳQ?)%Ё2rD>[ Z% jfD%Q9% )񑴤;)Jҕ.LcJҴr6rӾr)P&ԡ~FER2uaN 5D.!ZU!sչP[uLWd,ZjJ*F*_hUCkb*$uvQĿޅb˩2VV}l+IQ,fSͲ})hC+ђ=-NSڝ>}-l*=*ns&aK. @qˀ=耹6qK@>@EA.ۺ <0N,h{vL61B ^׼9M^?- xY_@p[wEq{b v̗n $Y&@"0*dʗ_odWы̚(<G`ns|!aEtp}'= {~;Ě#!~rx]X0 ]%CwTz5I<`:nIV^3: &h^MbN,{_耳. @=lk mq )Stw{ݠj7nxsJ E})|淤 ;t@¨`8$d"C7K!C/6p @4NI R6|B sn/!,#F22BCM$#>?I KLW,,8((4$nD?CDN ..:33?abl@8PÇ HQaÉ3lF;hqH zDI/lr%L6Q ɳΙ}zP(ODJ(LZ)իXjʵׯ`ÊKٳhӪ]˶۷pEh@Wn5 ^~`X#JT10dBnx43B zFaR X4A .13n 4t@ <  p:၇!,)322 BCM̌VK KLW,,878B((4㕖&&2CDN++7l"B",abl@ aÅ J$1ć/:(PcB= 0I \%M8sI5m,xRM=oDI˜ E*Q&.K)իXjʵׯ`Êu@j Zn\W⍪w/ʾ 0 j4 `B 8 .q.P 8H]4^?p (5JhA! ,$2{*1212121212121212121212121212122121212191?2C3D.@p'KM B76    % %!@)V6g@tBvBvBvBvBvBvCwDyNanprttttttttttttuvvvvvvvvvvwwwwwwwwwxzz{{||||{{zwvvvvxy{}||~'9MXfx̍vlkoy*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ G͛8sɳϟ@ JѣH*]ʴӧPJJիXjJt_AKٳhӪ]˶۷pʝKݻx˷߿ LÈ]4pQ0#K~L˘3k̹ϠCMӨS^ͺװc˞M۸Y7ͻw˾.~ @JЂMBІ:̜=3тz HGJҒm5j^pJR{ӞDNwӞ@ F9@y PTJժ4LYU Z"Aa4hMZֶp\J׺xͫ^׾ `KMbW~p\!+ٸByfz hGKҚMjWֺlgKͭnw mwZn5f[Zn ӈ4(Zͮvz xKMz|Km/6lTw f-3;'L [ΰ7{ GL(NW0qAkL"HN&;PL*[Xβ.{`L2hN3[6pL:xγܒπMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMz{ȷm~}[Op'nϸ7~\ GkRT(OWj08@j 9ЇN\FOҗn3Pz.[Ȧ:ַZ^njhO{ͮ&)NrϽ|.?3#O|ϼG{}O+/?w?~?}8'xg W |@ w؁ǁW &8{x*(x).w-2Hw186v5x:8v ;}@8}'DxvgHn׃LpP8>'Tx7gX0\)`8!'dxghl p8&txfx驪|Mwz8A'x燈ݦ成8&xfɦ扠8&xf抰8&xegf8&x㧋ȸ >Ȍ(lkXبkטXk؍jX(瘎(؎X8X؍ٸXɌYxI ؐɋ8IyɊّ I"9X&ɉ(,I.2Ɉ4Yx8I:ؓ>ɇ@x8DIFypJɆLٔhPIR9`XVɅXX\I^PbɄdYHxhIj@ؖnqsoXxz9|o~'٘9YDgpɌ9ay7QI4A0 :X8P9@qP4y ( Piɜ6᜸(!Ițڹ? ٚ)깞ٞ9Yyٟr+0Zz ڠ:Zzڡ ":$Z&z(*Z1y02:4Z6z8:<ڣ>@B:DZFzHJLڤNPR:TZVz@ +^`b:dZfzhjlڦnpr:tZvzxz|ڧ~:Ztv :Zzک:Zzڪj +@@:ZzȚʺڬ:Zzؚںڭ:Zغ꺮1ʮ : :: ԯ;[{ ۰;[{۱ "; s` *(ۯ2 46{8:<۳>@B;D[F{HJL۴NPR;T[V{XMAk@`^;h l۶npr;t[v{xz|۷~;[{۸w8kk0 [{ۺ;[{[6AiPʻۼ;Ki`ڛ4AK+`k ۾;[{ۿ<А Y`˾o  " zk%:'fP*L,,WpW@8<>@B>@p=t]v}xz|~׀؂=؄]؆}؈؊IG>oo-3`G}ًٜٞ٠ڢ=ڤ] :1+>pou pڭ M۳ڳp-ץ=]}mp=>0Рi Ƚ ڮ۵}8ڬ=޺ھ]}ݖ5!sP w={}n}-jn ">$^&~(*,.02>4^6~)0 </T.W~*倀]~+pb~ 4f~hjlnpr>t^v~xz|~>^~舞}q.c>MpM@>^~ꨞꪾ>^~븞뺾>+PN~>Nɞ>^~؞ھN𠀰ޠ>^~?_ ?O*~>c"?$_&(*,.02?4_68:<>@B?D_FH+LNPR?T_VXZ^`b?d_fhjlnpr?t_vxz|~F / 0 ?p* P /o ? ? @._ӿh o Oɓ'P DPB >QD-^ĘQF=~RH%MDRJ-SL4$K=}TPEETҊp¤y͘: 2ŚUV]~V،NάijՁWɾW\uk1Y3_^… FXbF X-_ƜYfΝ 9M K+}e(. ]|qZ$, L0/-4WlȞ8P21<г;X' ',@rӘ$pvSS=oqY-L`8i]$msnK'ʹNϹ `HjgvCڞC'TOk͆>N߲ m=3̮/۷S;'/Pѿs*9@ `.>L @"1H[A|I_\#ĀAA'~n'@B 6)^0B0W?2(&2>n;dX;6HqY {d3&y,q2!|0` WWn,0Y ALL3y=Ӵ~n)mA>tF2 }4*I Җ'3M`k,-Gv jvc -uKꈪhEj˺Ay[3nz8|{_5 6Yhl`e|k'vlwuRl̓ ՞ZtGmsZ2{(n53pM'{#OS<ޅih񍯰 C&?Rr{9̓'6sn" ?(\s5`/b"D@ AE~`.Vp_LA@0BɁx`E B# 88{.ql%rf* 9P* l Ȼ@B0(^S1 ?o{AV!G7G5>ҟC:OO $H x>O_O,گv8 _,N/~ VdA #D09]k}qB| 'zw|G'?QjC"a}e(vcA} X  0F7 HzC{Q  wsAwG׃1WW|s?f `,(z8@u@t@KxA5=yA ^0.kѮ@1"ƴH@0WlB|H @,+@(4척i3· 23hM1PHH"2`[֋uh*4كPi=*ӄFO˭,PAU@P{.fA(rG>$KFn\.|uTKsnWHF\k7a\ۄ 1nf.|}/|5OGYyOzpkbOWُRH851 2 q ' R 7xq/ G[x!1$L!G`*aFDHO8, 8a~HD<"/%NN| )RVq" ;ec\b90F8Bp@F@9q|L€0 3 !HC<@8 K`$IHI@C& e h+ciRJ҃ 9(GZh%,mIS% 0KE$&NI0dd3YMi~|ddZLZdi4#(!p'<ݙNu2!͛AĞztz=P1{(D{'щҮ5F3r4rhB*RA%= '1;zt3lziO r#)RԥBN=T곩RfVʲՐq*X+&ֱfZӊ5]n}*jѵź+^i׽ʪ~=<R=F1z,d;(@ dv@fp>X]$  Xlp Du$AJa(ji!H  P@ X N`[6l*[`W "'W8M$2p$dv"/x-`ݽ Yآ h3X(0mPB 8UrxraJ .!Z7 t%Q46om@0U+ & @h ȗBx.8K0qW\o9JJ`O@A 3Q1i[f%2{zfBG}4ZX U#ĢybG!,B22$BCMKLW ,,8(HY8 D8C gFx(!!@,|bƄt1ʖ%GVzR̍9ϝs.d}G4ڳ߀!=,@ 22BCMKLW ,,8$= 3.10 (for Python 2.7, 3.4 and 3.5 see the 4.x.y releases) .. toctree:: :maxdepth: 4 intro api buslogging tips examples benchmarks gui functions_manager Indices and tables ------------------ * :ref:`genindex` * :ref:`modindex` * :ref:`search` asammdf-8.5.1/doc/intro.rst000066400000000000000000000131551502633300400155700ustar00rootroot00000000000000------------ Introduction ------------ Project goals ============= The main goals for this library are: * to be faster than the other Python-based mdf libraries * to have clean and easy-to-understand code base * to have minimal 3rd party dependencies Features ======== * create new mdf files from scratch * append new channels * read unsorted MDF v3 and v4 files * read CAN and LIN bus logging files * extract CAN and LIN signals from anonymous bus logging measurements * filter a subset of channels from original mdf file * cut measurement to specified time interval * convert to different mdf version * export to pandas, HDF5, Matlab (v7.3), CSV and parquet * merge multiple files sharing the same internal structure * read and save mdf version 4.10 files containing zipped data blocks * space optimizations for saved files (no duplicated blocks) * split large data blocks (configurable size) for mdf version 4 * full support (read, append, save) for the following map types (multidimensional array channels): * mdf version 3 channels with CDBLOCK * mdf version 4 structure channel composition * mdf version 4 channel arrays with CNTemplate storage and one of the array types: * 0 - array * 1 - scaling axis * 2 - look-up * add and extract attachments for mdf version 4 * handle large files (for example merging two files, each with 14000 channels and 5GB size, on a RaspberryPi) * extract channel data, master channel and extra channel information as `Signal` objects for unified operations with v3 and v4 files * time domain operation using the `Signal` class * pandas DataFrames are good if all the channels have the same time base * a measurement will usually have channels from different sources at different rates * the `Signal` class facilitates operations with such channels * graphical interface to visualize channels and perform operations with the files Major features not implemented (yet) ==================================== * for version 3 * functionality related to sample reduction block: the sample reduction blocks are simply ignored * for version 4 * experimental support for MDF v4.20 column oriented storage * functionality related to sample reduction block: the sample reduction blocks are simply ignored * handling of channel hierarchy: channel hierarchy is ignored * full handling of bus logging measurements: currently only CAN and LIN bus logging are implemented with the ability to *get* signals defined in the attached CAN/LIN database (.arxml or .dbc). Signals can also be extracted from an anonymous bus logging measurement by providing a CAN or LIN database (.dbc or .arxml) * handling of unfinished measurements (mdf 4): finalization is attempted when the file is loaded, however not all the finalization steps are supported * full support for remaining mdf 4 channel arrays types * xml schema for MDBLOCK: most metadata stored in the comment blocks will not be available * full handling of event blocks: events are transferred to the new files (in case of calling methods that return new `MDF` objects) but no new events can be created * channels with default X axis: the default X axis is ignored and the channel group's master channel is used * attachment encryption/decryption using user provided encryption/decryption functions; this is not part of the MDF v4 spec and is only supported by this library Dependencies ============ `asammdf` uses the following libraries * numpy : the heart that makes all tick * numexpr : for algebraic and rational channel conversions * wheel : for installation in virtual environments * pandas : for DataFrame export * canmatrix : to handle CAN/LIN bus logging measurements * natsort * lxml : for canmatrix arxml support * lz4 : to speed up the disk IO performance * python-dateutil : measurement start time handling Optional dependencies needed for exports * h5py : for HDF5 export * hdf5storage : for Matlab v7.3 .mat export * pyarrow : for parquet export * scipy: for Matlab v4 and v5 .mat export Other optional dependencies * PySide6 : for GUI tool * pyqtgraph : for GUI tool and Signal plotting * matplotlib : as fallback for Signal plotting * faust-cchardet : to detect non-standard Unicode encodings * chardet : to detect non-standard Unicode encodings * pyqtlet2 : for the GPS window * isal : for faster zlib compression/decompression * fsspec : access files stored in the cloud Installation ============ `asammdf` is available on * GitHub: https://github.com/danielhrisca/asammdf/ * PyPI: https://pypi.org/project/asammdf/ * conda-forge: https://anaconda.org/conda-forge/asammdf .. code:: python pip install asammdf # for the GUI pip install asammdf[gui] # or for anaconda conda install -c conda-forge asammdf In case a wheel is not present for your OS/Python versions and you lack the proper compiler setup to compile the C-extension code, then you can simply copy-paste the package code to your site-packages. In this way the Python fallback code will be used instead of the compiled C-extension code. Contributing & Support ====================== Please have a look at the `contributing guidelines `_. If you enjoy this library please consider making a donation to the `numpy project `_ or to `danielhrisca using liberapay `_. Contributors ------------ Thanks to all who contributed with commits to `asammdf` .. raw:: html asammdf-8.5.1/doc/make.bat000066400000000000000000000000351502633300400153010ustar00rootroot00000000000000sphinx-build -b html . _buildasammdf-8.5.1/doc/requirements.txt000066400000000000000000000001401502633300400171550ustar00rootroot00000000000000matplotlib numpydoc sphinx sphinx-argparse sphinx-rtd-theme sphinxcontrib-mermaid numpy>=1.23.0 asammdf-8.5.1/doc/tips.rst000066400000000000000000000053501502633300400154120ustar00rootroot00000000000000.. raw:: html .. role:: red .. role:: blue .. role:: green .. role:: cyan .. role:: magenta .. role:: orange .. role:: brown ---- Tips ---- Selective channel loading ========================= Since asammdf 6.1.0 you can use the `channels` argument to perform a selective channel loading. Only the metadata of channels found in the selection iterable will be preserved after loading the file. This can yield a big speed improvement for loading the file, but also when performing operations with the `MDF` object (for example `select`, `get`, etc.). .. code-block:: python required_channels = ["Speed", "Acceleration", "Force"] mdf = MDF("input.mf4", channels=required_channels) Data coupling ============= All the data returned by the `MDF` methods is decoupled from the raw data found in the original file. For example, if you modify the `Signal` returned by the `get` call the changes will not be seen in the raw data. A second `get` call of the same channel name will once again give you the data found in the original file. Chunked data access =================== `asammdf` optimizes memory usage by processing samples in fragments. The read fragment size was tuned based on experimental measurements and should give a good compromise between execution time and memory usage. You can further tune the read fragment size using the `configure` method, to favor execution speed (using larger fragment sizes) or memory usage (using lower fragment sizes). Optimized methods ================= The `MDF` methods (`cut`, `filter`, `select`) are optimized and should be used instead of calling `get` for several channels. Each `get` call will read all channel group raw samples from disk. If you need to extract multiple channels it is strongly advised to use the `select` method: for each channel group that contains channels submitted for selection, the raw samples will only be read once. Faster file loading =================== Skip XML parsing for MDF4 files ------------------------------- `MDF4` uses the XML channel comment to define the channel's display name (this acts as an alias for the channel name). XML parsing is an expensive operation that can have a big impact on the loading performance of measurements with high channel count. You can use the keyword only argument `use_display_names` when creating `MDF` objects to control the XML parsing (default is True). This means that the display names will be available when calling the `get` method. asammdf-8.5.1/doc/v2v3blocks.rst000066400000000000000000000031111502633300400164220ustar00rootroot00000000000000.. raw:: html .. role:: red .. role:: blue .. role:: green .. role:: cyan .. role:: magenta .. role:: orange .. role:: brown .. default-role:: py:obj .. _v2blocks: The following classes implement different MDF version 3 blocks. Channel Class ^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.Channel ChannelConversion Class ^^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.ChannelConversion ChannelDependency Class ^^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.ChannelDependency ChannelExtension Class ^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.ChannelExtension ChannelGroup Class ^^^^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.ChannelGroup DataGroup Class ^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.DataGroup FileIdentificationBlock Class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.FileIdentificationBlock HeaderBlock Class ^^^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.HeaderBlock ProgramBlock Class ^^^^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.ProgramBlock TextBlock Class ^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.TextBlock TriggerBlock Class ^^^^^^^^^^^^^^^^^^ .. autoclass:: asammdf.blocks.v2_v3_blocks.TriggerBlock asammdf-8.5.1/doc/v4blocks.rst000066400000000000000000000035641502633300400161670ustar00rootroot00000000000000.. raw:: html .. role:: red .. role:: blue .. role:: green .. role:: cyan .. role:: magenta .. role:: orange .. role:: brown .. default-role:: py:obj .. _v4blocks: The following classes implement different MDF version 4 blocks. AttachmentBlock Class ===================== .. autoclass:: asammdf.blocks.v4_blocks.AttachmentBlock :members: Channel Class ============= .. autoclass:: asammdf.blocks.v4_blocks.Channel :members: ChannelConversion Class ======================= .. autoclass:: asammdf.blocks.v4_blocks.ChannelConversion :members: ChannelGroup Class ================== .. autoclass:: asammdf.blocks.v4_blocks.ChannelGroup :members: DataGroup Class =============== .. autoclass:: asammdf.blocks.v4_blocks.DataGroup :members: DataList Class ============== .. autoclass:: asammdf.blocks.v4_blocks.DataList :members: DataBlock Class =============== .. autoclass:: asammdf.blocks.v4_blocks.DataBlock :members: FileIdentificationBlock Class ============================= .. autoclass:: asammdf.blocks.v4_blocks.FileIdentificationBlock :members: HeaderBlock Class ================= .. autoclass:: asammdf.blocks.v4_blocks.HeaderBlock :members: SourceInformation Class ======================= .. autoclass:: asammdf.blocks.v4_blocks.SourceInformation :members: FileHistory Class ================= .. autoclass:: asammdf.blocks.v4_blocks.FileHistory :members: TextBlock Class =============== .. autoclass:: asammdf.blocks.v4_blocks.TextBlock :members: EventBlock Class ================ .. autoclass:: asammdf.blocks.v4_blocks.EventBlock :members: asammdf-8.5.1/examples/000077500000000000000000000000001502633300400147475ustar00rootroot00000000000000asammdf-8.5.1/examples/mf4_demo.py000066400000000000000000000137571502633300400170300ustar00rootroot00000000000000from typing import Any import numpy as np import numpy.typing as npt from asammdf import MDF, Signal cycles = 100 sigs = [] mdf = MDF() t = np.arange(cycles, dtype=np.float64) # no conversion sig = Signal( np.ones(cycles, dtype=np.uint64), t, name="Channel_no_conversion", unit="s", conversion=None, comment="Unsigned 64 bit channel {}", ) sigs.append(sig) # linear conversion: dict[str, object] = {"a": 2, "b": -0.5} sig = Signal( np.ones(cycles, dtype=np.int64), t, name="Channel_linear_conversion", unit="Nm", conversion=conversion, comment="Signed 64bit channel with linear conversion", ) sigs.append(sig) # algebraic conversion = {"formula": "2 * sin(X)"} sig = Signal( np.arange(cycles, dtype=np.int32) / 100.0, t, name="Channel_algebraic", unit="eV", conversion=conversion, comment="Sinus channel with algebraic conversion", ) sigs.append(sig) # rational conversion = {"P1": 0, "P2": 4, "P3": -0.5, "P4": 0, "P5": 0, "P6": 1} sig = Signal( np.ones(cycles, dtype=np.int64), t, name="Channel_rational_conversion", unit="Nm", conversion=conversion, comment="Channel with rational conversion", ) sigs.append(sig) # string channel strings = [f"String channel sample {j}".encode("ascii") for j in range(cycles)] sig = Signal( np.array(strings), t, name="Channel_string", comment="String channel", encoding="latin-1", ) sigs.append(sig) # byte array ones = np.ones(cycles, dtype=np.dtype("(8,)u1")) sig = Signal(ones * 111, t, name="Channel_bytearay", comment="Byte array channel") sigs.append(sig) # tabular vals = 20 conversion = {f"raw_{i}": i for i in range(vals)} conversion.update({f"phys_{i}": -i for i in range(vals)}) sig = Signal( np.arange(cycles, dtype=np.uint32) % 20, t, name="Channel_tabular", unit="-", conversion=conversion, comment="Tabular channel", ) sigs.append(sig) # value to text vals = 20 conversion = {f"val_{i}": i for i in range(vals)} conversion.update({f"text_{i}": f"key_{i}".encode("ascii") for i in range(vals)}) conversion["default"] = b"default key" sig = Signal( np.arange(cycles, dtype=np.uint32) % 30, t, name="Channel_value_to_text", conversion=conversion, comment="Value to text channel", ) sigs.append(sig) # tabular with range vals = 20 conversion = {f"lower_{i}": i * 10 for i in range(vals)} conversion.update({f"upper_{i}": (i + 1) * 10 for i in range(vals)}) conversion.update({f"phys_{i}": i for i in range(vals)}) conversion["default"] = -1 sig = Signal( 2 * np.arange(cycles, dtype=np.float64), t, name="Channel_value_range_to_value", unit="order", conversion=conversion, comment="Value range to value channel", ) sigs.append(sig) # value range to text vals = 20 conversion = {f"lower_{i}": i * 10 for i in range(vals)} conversion.update({f"upper_{i}": (i + 1) * 10 - 5 for i in range(vals)}) conversion.update({f"text_{i}": f"Level {i}" for i in range(vals)}) conversion["default"] = b"Unknown level" sig = Signal( 6 * np.arange(cycles, dtype=np.uint64) % 240, t, name="Channel_value_range_to_text", conversion=conversion, comment="Value range to text channel", ) sigs.append(sig) mdf.append(sigs, comment="single dimensional channels", common_timebase=True) sigs = [] # lookup tabel with axis samples: list[npt.NDArray[Any]] = [ np.ones((cycles, 2, 3), dtype=np.uint64) * 1, np.ones((cycles, 2), dtype=np.uint64) * 2, np.ones((cycles, 3), dtype=np.uint64) * 3, ] types: list[npt.DTypeLike] = [ ("Channel_lookup_with_axis", "(2, 3)I[h$EG|͇:VZU{]W{ժתwU-;44 +n<˖x7C'~PW'"RCL$ΛOWv}w|WNub+vm)тd5w1Qpn6Q8|7|>w|@rFx@;v_tV[Bs>w<ç>O3}?{_y} s; zy[$77n$Fܖ"dj`*6+֧sdEōPu9&3<1v} UѣmC p-Ͳ:}&BW^W?x/> _o|>}>O]s_9mKYpfGugko޶&Y6-*H-KY-wC|UFщvyFnu!t}S&e+MOH?'_Աsǟxѧ^gO>onٗs{/=_vʖ* ]Rn[;R-Wйq`wҦn:FCNg{S:BĽ>du<%SZeE܃^{>y펣ںGz'{śORlU  d-.8S!4wkC|2PQ"L﹟^Aq;mH QB9)eBYfbCX'IfdVbDHϘV,7/HQZ=ٶpnhV[nG9>[g;ӟ>|=_9pmm>tX!tCu/UӶd/؀2Yl6ҦZ#}Z4UI+$1*&CZ $bLU71P+Fڰ՘Ejiy$a.eQYFAQXF_P/ܼ[o_9}̻w}>E R&,pP!DAY ԄKŐ~GꣲޔthMSBWڂ]R+߻ G}JuJ:*bpTcX@|BI-Zarud/P$AeŠCnՇOt˱Nmz;O/ۮuh>9[*`‚6E"mddG5-AQ}ԔAf[ qnC!R"ݸ.SY1P ͮQjUЈ[C(g"n^J :~+o|_>Jw|ⷾՏ~Kt}_wC$1v>zg{mР'$2QFuD!9",8 cj9a*7$6s s)q5"'TOatZ2Ź"_ah#J0QewP)ʉƸrX]+ ۚ)˱tCl+Ҹ'x7]4P预I2`'eCBp7\e5EBXE7<^B tZ5Q2lp#7ن$Ds\!FA9$酡-SUFeMv2-1O{@Wj\dM V:vUp b(iIʧsQ.<~t^h|rwGnEY&*E77ݰ1:_8@gre5+m_Dj^U]nf4MQ0s3RoEf,oʺTFГ4%RިM5&T. B>ߴgS >]յ 9ߩʦۄQgԄ'7g|V\V`,aOtT/\E~K@+E:zvUw;]2mDҴOiQ{7 ' >5imwM5ʶAHh_޾@%薄uW>}Hq: & 8җ_yܴuI7k9;b] ]ttlmZ->ucw:\yQ dsl4K.vԉ?E(A$S@`oo~_HwCxLnvIdQ_ٶkQ[뱼/22edU0u}OXuP;FпO=iί=}.x )ԟԤ@?/Á&~)#@#$>jpP'#DPTɈDZ ܇;ZARHj"W&T)e|7l}fܱAb8Kw"+QT7R9Iz1iZIQTH*(Bv>yܙK %薄4Dtǹ`~L0]0(a\SYZɷL$$rӛ\R'4:7l,7{Mlc1u0CE>BYv Mx50V& [ , %HW%#?v~?+tnIHYEhS91_Q0uAMp=RUIm'rUVkvf04jU7m %8TG$oJt*MI!Q P, 6!*DI^QR|9 '1h{@`9#ͨ_S{qn#$SCEʖm2}HUu:„|`(ePWȘ%0i:Xr4蛆B?ws|7~;(A$!t3 rp}%?n?C'cט~"Wo6%-iW &Ր"]|mVU4[W ]0 2YU"uT!ynL $~tп?$5)@}& LLy/>_8_8q/ĻE /+7I~ ꣐t+j^5nkuS5qg~~_>EF @}`q4~06@@"@>4E4(@}lp W/P@X>&M7]wQ%p뭷J Ĉc.9~›pIwuĞ77`sIĞ77`sAJ@J@J@J@J@J@J?}u].@;::fcոp… .\FdCي9$ @ǎѣGS2Kp… .\h: mNLe+@ܸcoc. 썇]w%rEqJ><… .\pctm Z s9؁K/QF'qEzrL;n<1… .\pw̫ϕ+Q踒t% WR.lxOqIa7R@!= Pܴλ  ;8 5:`CO9y{%垗/ .\pUֵz^7/9lв{uP~ۍ'~ԮqҗŐ A=,4!\m_9k 9o6埿ğw>{u p… .\\{z&v_{_MSVI#{8xM'~W~N[=I5^u_(_q ) P]wncTGQzŇ%ـݧ^9C{^8֜t p… .\\&T*\> ]C'sm?#.o>s' @Ka2^{5g,1}dw#BAt {l;O|`o70鞗.\p…k?Raoq* p^Up{n?iḂO>#预wf(~P61JY|ŋYxj-~Dn$~oܜrB:l 8+^{N/MA\\pr=q,?Wem>|Oۍ~jtRk>o$}uFcvy"љ׉ =W֓slBo&^\emV* p.(uo}W_{=oÉ'^.ҿOᯞoϽ>+뮻x? ].Ar4%g5hW/Яtp{7{P[>,f$i`vG 'o_Gk.y^yOvJ.\5\>cnx{o4dy΁_۾Υ?$6^">›ۗvMu湨o/o^.K.\e\&D*\6ʙW0׬[|Y%i/^}嵣^ξk:|yⱧ_g?Ǟpm'OpHa19|x<" ?9e_ֳ΁/?؛#+/lbvG:EN:uUWl IH.|7;n<˷z7sW>g]Nk _##{k;_˽{voyc}7?ϒSH$~w]]͚ҥawq…k=W3s᷏ۄ.KW*l)K8"t|Y%+wr+pۣsw|ٯc_{Ob|>s#~箼mx˵MLGVBM 6I NW_}UnAEqe*)E"l+K3od8|Y*G6Myi .Hg +q˘$oMdt,.-a‹>mRKPkQBw|zFFpuvjx'^|/~̅}O{/mo 'H>S~'Z׀ K7ۍ6>xwN~.>Anۗv/dW}A%‹wc$xϽMS4ofcxҋ|t!)r'f3.)Ջ;7-6d\pZk?~T}oل.KW*l)k/~I|Y%ˊwrr?'o|o=|mǾ7G<~'ӑ3oítd%dH=C׾e7%uru]pAnAENsϱGzx?=|ί;qmy7`W6.}~冐u/c()}Qɯ !}WaC`\wuO?<6GRDV¯0AD _ֳth jBͽ/n}ƻoO~XJOIc eiJ lA4,UW)"fWŽ^G>B}rB:llw_;Ooy{Ͻv^S3q:Ԁ >qvÛwR&V{68k/эw.(|gxiJ"e7D\ЧZك`r"o1>'y?stA)\CYjKJ…k/~4v_{?Mi–t'B˗U:U떓ssz~}׿pϟ<Ϝ{=wO}g?tg>0^q5GJlH5ך^h*I +J0Ul XnAE{1e%)E"l+Kid8|Yϊ?`s/K/bwoI'dYH+&h˚lE(ըPVҬ!߰zZsE g ̄6|^omK#g{y.\=rͷ5䏫o1[X쁽vHO\m%eZҿatiz__^MٝKm8c1 5C9g]ܥ>VJݾs,\pe+kM$e}_ZrJB''?qG?g>/<ϟ{_owR )>撂,Ҽ?ЧB1v"zS{g'-@*DRVRe-[/7mQi/3[jl%:HY![š!"IIq;vN~⹗._zg.4.\^ןqO_bfL:L+xǍ~9"{9w} ͐Ihb;~'.HeJ"\om0.\5\stM,JBY%9Żn>N|Kscn?ux ?y>upoyn;k/gvwKa0|W7~ϝ;/ XDhЧ{V Rz)su=rs/H6CEN:e-+7LSzV>}Yj#h/K/B6Y?eJS`U'$_D]ꪟfT´Q"A1yUq[-gu %|9{4%|ezjT:Ԁ J~ܓ{ÛߺsӇ7.ݳӏo_zcN~S&ث$6xxcs9mxKgM?&mFw .qO9w|s??ǣja+޾/c:.\{@RaMSVIs^K|zW:HHX ˿y["X_S*#u]sM?O"?b$?Hg_r6'QY?v%X%oWҍ޾Ϲ??BODt۪ps_T}lbJЉx ~Љ$iJN~YN4%0'~W"Ď醥.LXDΨ1P-`~'mbϻ@ 4NF6l@y.\p…Kמ=jU:1Xʴ]e7IMا-2,Oi,jZJO+ˍZ+}dc߀~ WdpY:G@ugELv=}45YciCn>#ǟO[2dX(@YԴ4l Vv eI5A3 0Gھ0.D>jgPkatWyW<_&wt{I\C(N`t+ہ(o1b7Ί{hjXc)ӆv@'}6 4F?cdȰ>jgPkav\F W8+S28,#v:["&;>1Xʴ]e7IMا-2,Oi,jZJO+ˍZNYo@lyğoͭ&:|r4kRA ڵ"ujYmb L3t WdpY:Gy`=[}j|G35qfL:I1r%C> E:m0Jr :=&h{&#$؜ y?ɟr9tƆ2ɫY@'AMZ:t>d Wd&pَ/[;"꩚b_yN8/{Y!<Ϡ/oc)nKs0_~Cy"[;7tpbvI~cZ{ͬi;v  n&!ا> TGZ̺ ~Om1.T˴ljgPkt>qX4j9iHaڌ|0)) lT;,.ނW^.:/K>F9uݚfdϏlΣu1fcv%_xLm?{fYnaW:v@'MB#ǟOˁ}V5BcwQfXJ0xUHˍ$[6Z9pvFcF&!W5 3U"[{StХͩ(jrP8D6;[{v涒{)l tW@W!/BBch}X>|V#<ú^֛ae]-[&N`Zܤ e%~yq-,Nm`ΧZ 5XEmWfbٜǺGFokNئIG~}MۙE~lAiZ4/5LZ54Kz<&XIWpe06sڞAכjfZYPzGyQhi6gcW t7 m9}iFn*0اUKZvMhьr#r郢[A摋T;ZajOqfQϧ<ه+lLxWîr :ɖM&h{&lcɟ$j bpoc2kaʩ j5VC(NL`CygPWlRd{qI#vByd9)cT٠Raq5[~vCӥŴw?ql^ҌC~O8ioE6nZIdsSɾҔ=\=&I Sɜ)4S R]uo\n(L 1ikEɛ[K*aқn 4'[~vC`͈_ku#l`'vz:M$"fEM{*JhL =!pgˊ*Iʖⴈ]FABt-@MLj-~V?c3{;Ft>Rigo+ɪeq+n Y))̔6ueA$"#vBe7atM5o=Lf!ikhD{ m4IB;!Yrɻ0C&I^tf׼7=5h绤m"36-5Z&Eanu9d<JM:_ QU{MW|F8]01im)h"e5s*{f}fT=̍'3ۍEڜ]e7IcgӰOs q6_O[C`͈_kS z=^iFj8D5=\A!z<&>:zsQ8ÕDpi(H(Ne ڞI@<"i 6 38%M*`ui_yNhL-э0 ݶeM|CZ3tYia:!CXrɻxшnK3-بHMgK[q+m"hkHd>̭%B?1TDΒ͛4umn. Q7]4ǤFF5Y^5C1gmƮ褱I@c3iاfZO!fį`ͫOGh"F-: E\(T>u0&瞣qOEZny6ˍ$[6ZEC`c.؈4XO)l3CR0s}b;-ݘ5[g>ްˍBib|C('w}V8A2Z }w?a\t.mMwi1LDéZ Ojk+>/g ]j6GTefI񘴵cPWjBș iYvH[s6gcW t$d1r4\C('SW ֦B-ihv>%#U5ŹvPޮ18LRHe.lMBgXWS-`WyQPd&P=Z @L: \m_hOP6|2SH`TnnڃsS lq}W!ӠzW|%a_uXQT[ՠ;"6E7Q Dmk $bT> OfD4K(|ɍȑhT0w<1io%ck{\>f4왍uMR=~lͰ, n&اaZu7֊V5Rc(4l{ je*tÄbC92d.l"}uˍ$[6Zu"\m_hOP6Cc_ynz@{{XqVdޓO^+&ok,eЮ&gӖ ' 4P5- ۂa]FABtg{@MLj-rEqJc_yn-FaYxO 2!݋R /Nlh>mɐayOeQP-xZ U^n$}@'}m$F@KK 8%ұ EMKCi`i%`WyQPP=Z =z&I|y%@]+S28,#v:["&;>1Xʴ]e7IMا-2,Oi,jZJO+ˍZo<| г7<.ڸK2NHM (lX<|܅:|ǚuA(N`t+ہ(o1b7Ί{hjXc)ӆv@'}6 4F?cdȰ>jgPkavw< =[|߹,xwp}9ڙd#Mпq_}c'}Inn^R 8%ұR3iKڿ0$䙒O+ˍ5>RZ~xn? 6L/3/Ա3/г CZZПyNCmrI ;[0_1z3WM{y1;8-77A#jJcdMwerEqJ,`c7ا )$R-{n?/=w `oz5+jBÐc>}F-!͇nL45q\ >М7c67?~Z鷎Q)w8% RWBz_c.^x…Wjhhk'_?|6lWH+z7薫 XZR|K_z[Jv_yww~♗^};KE-rDh7}w޽8=׭c&m@(N?`&>2o8X^h%U*#|㬈'&k52mHKr ꫯe_|oO[:dXަb,jZJO+,Т]Wxo =[|셷VrD> ϟ~]G_W~c=7϶[C.F e{ ,rFm^)*a]OsK5Vhfg+.Hn&+EiyW{& 6KGd.Xb["&;>1Xʴ!-@i(Ҁm0J ; |$)h;PMx ԚWєM3M`[T:j=I$$rGd.Xb["&;>1Xʴ!-@i(Ҁm0J ; vt⥋7|/'/XK.KtM'}n9I>}ؙ'0; (/ 7>21_D\mqoڠmr)"7NTK Q6"(!Wd>lݰY eMyڡi1P -FaYxO`MMk,eڐN.2,o`1P5- ۂa@vh_VՆ;w_{;N_qS/\7|싯擿xɗ/_p}Y.g߀ן=ů|+[!uӜڌƬ* :GhMtGe4M,ot\Q`QDe$A#2Wb1P-FaYxO`MMk,eڐxCǍٟ}soۧȰM@YԴ4l VYE;4[U><'8.G^xM/WyOyYj]J}/50S[[mQ]L"*L~YYZq6Uab3Fsn4cL8@\ie'a֠v)y6b&_w'+#|㬈'&k52mHK>|_=_=%@m,ʢ4`[0 -Kߡ٪7νxQoo|șw|sX WۗerVo>u?=CC~_z+bM$TʗVMH+lnЄn)8KWGZD ]B#d+J0tD*@ttq'!Wd9v!mǟmRt\Y E{{XqV@_'o&k52mHK?p W\q>޼oУCm,ʢ4`[0 -Kߡq8ox+n<񅇞fI/[/(Z#I.j:s+S2l8,!bf8%nnN,> S BN/d54n&'ui4W5o ›͖N57rћ~=ѣ%_jD4p=&'Dh'5<5cmƒd) }롥?_ƚ-Gv^fԤ"/ϼ:}{>@ө']Lג<sM!-Rz"izc9ʲ$51h DFٮjEjS$f43CА67o\![~fDyeyMgqgk+z{ZXStr1k,qm̲o=&}ަb@]oy~GЋėg^R\O|,!JPz WdllqƄ䨧&641zkX zbL8FXqD Q-ZW!tMiAK )(7U-kBZJkXN캻m=ڐz&5f{ssYC pJHUzz*2T ੉UN Cz鐎})WJ,Yc2X>2z dT"w fCm,ʢ4`[0 -?ݏ3/S;\m_@(NyQ29E4ŠI-= \ż)fGXyXζ$Sm+z$r@(U z<0[.MhU#OblMJ}4-G'ϲw?-= NXvkC&ld!sQi,ӭ{݆]D4xjMJG Qw=L鹩1k,If& ̻$ܳW'KK?Cm,ʢ4`[0 -kGO?|g/>kWr@!+S28,zZ- ;Hy>#/\ʒñ)Z /ݼj0 3Yti:DZ~d 6SƂ 'ɳO'-! 3Bi eiL9P;X([biϐiEO>YӠF:85=&c%ۮX7g?Rs騨ٴ'Ǜ:\pN8l,jgӖ i(Ҁm0J ; /}fjc4!\m_@(N`t}DjTۢi0gZr3;.7qLDYvi2DZ Vh^ew?(rn׆h63op%C::yK'OMbKNH2o /!ͮ̒5=&cZͥZ3SO/{q㫎j9iԣ@fQ(bZ!6 ;[P5- ۂa@vh_Mj- }ѣ7 ;!5)j\Q`bt >N|: ˫TptL#i8}Mij,uTI 1Y:yionzmS$/Kk NiJggDxjXrBIR6_5ku.NMXcim8w0׎ 1++θ MJi6+_,}'N#ǟڧ~*-=IDn 4lAYԴ4l VYE;4 Ç:!5)j\QY`[Y8 %_&HTC+E5RMx'@cUs.%#ݢ 0v?-='X^kj3mC1DLB*-45&j"[xڄ'XdD5D&Afݼ3!nnax(CK=ޜԩSCyCKD~ 4lAYԴ4l VYE;4 @K\QY`2UL{{XqVĜߎB]UL1dR i/% ȼa'cЎZ_?)dXަaʢ4`[0 -@ Ѐ Wd<؀v}D*ň=,8+bށO_DcdcL_7W9($ MmG\iyyfAκdfIV''S"I(߿x_%-dL(7lMMKy6$疝 x v3#=4 ixŮ9̂ЄGd.Xb["&;>1Xʴ!-EiLhlM;i>͙bئ߰i=3JT 5[`¸}15- uBlۜ+KG&KwC`)<-@  rEqJf Gd.Xb["&;>1Xʴ!-}4!6b'BWʔp6IlevZUqsoܒo@H:zG6FoHn8xE]w%}a$@9ھrh@+S28,z`)o1b7Ί{hjXc)ӆ#]>dXަY1pMmU!/Crq_sHEuF:jZF eW$q8xEdXަb,jZJO+,Т_Dַuܹ?5Tٳ7J,u@(N`t}D*ň=,8+b 죩cLҏtayii(  <@~FgϞ>}_B ǏIP# 6KGd.Xb["&;>1Xʴ!-@i(Ҁm0J ; >|"gb;su/Vմ#|㬈'&k52mHK?Cm,ʢ4`[0 -z)%` Wd;4䪨t3Y7>"s%5Qbo1فdR iG|ȰM@YԴ4l VYEhF\Q`_jn:3gsY+oBO!M#2Wd1P-FaYxO`MMk,eڐ~ˇ 4X EMKCi`i%Z`)y6[[!"g5C#2Wd1P-FaYxO`MMk,eڐ~ˇ 4X EMKCi`i%ZGxgBjR8%3ĕ](IT:D>tYL} Ʋf'|֌PRgȣ3 1.M-A&V{kn NMDoD 86NDsmһ}BCdqO͂Vƒˮ"'X+~ˇ 4X EMKCi`i%ZRF)y6эBrS[NF}D,q(˦3vƞJ㆚u&iQ3Iu"ɪfBC F2#}bkn.DVgxE7fKɭfgMn aOM dg}~YNѷZG @> o`1BLC>C3tݐ+S268cBrSI٣ ȡam[,`)V>q|W6=G e DB^&B X yY VLG'Ov]'Vв׆+6i2ۛZXNfSBoH. B*"s OMrh6c44j\U/NMXcixTz dg "S{%ҏo@i(Ҁm0J ; #=4@x7;p[TkcYT8%3F9Lrf29+7 3;Hߙd7mZD.@#gihgms]ѪF6ɍ,VcKl &#G:yIzbn=>^0VqfOk=6\b0@+:\-Pq Sd|HAtjqjzLK]0o~QQu)iG|ȰM@YԴ4l VYE-c&]sٕ%-җ$~&6v "do,ݹ@ WdpY:>"s[Q1C2Bccj3"RC(4U-kVh^ew?qOnzmn?c2Y {ZR_UШd<xjrV sFOf}˦d@6WtTTkf*)Z@SayvxVAmv,jZJO+,ТWn&twX(m66hQM$ yh >8 1.OCC-^T8%3tA#2W?e̹ex~|yUQR%#u*R Svi*ī&b{iIHS,<=1w=0LrkL}TIؔlwfKO+a4ѓU[dk˻RkGٕyg\c&4CyZK駲ғDz  4lAYԴ4l VYE+iC ?>=3L,N𞐥hCkDB"[~Gw :75I@Hrڶ5MQϺB(N,xM}D-fIyQ;Hshnǡ\c\TMf_[% jys+S2l@z`)o1b7Ί{hjXc)ӆMm5[u7*Y7dXަ-Fac@2)V#|'4HMTFN!.;b*%-d4PAB5- #umSEO0)ha"B$e` )6c@z|z& @\QY`UL{{XqVdGS5K6= u6B)O$H@mZO,lCb*L;֣:߬4̔ҤNG\\h$T?mǔ`BB@LMK{!uZ$R==T\Yn>eaO0xZǏxgBjR`%'QL}T< \XŔgELv=}45YciCZK4hBmZ|8b0"$i3u:jU[P!٥$y@Q0<^mK.OivРJzV1ą`SO0dΓZ%~# ( A(N`t}D*ň=,8+b 죩cLҏtayf1:#mTI0^k 7TMgE[fu w 'UH]LAmF.5- #uʶ&+hdv7IͿ NrDYE-ǮLE; ` WdpY:>"sbSbo1فdR iG|ȰMkkuh4:j(C~}_^U8-GXuZ]. &Tda Ŷ矤#Н~ MU$$,(1Xʴ!-@i(Ҁm0J ; #N,#]>;;nE97zPbo1فdR iG|ȰM@YԴ4l VYEMW= eC2 Fd3`J(@sYa}48%3L뚟[ }DJ,jň=,8+b 죩cLҏtayii(  <@Z]s#9 ;[[*w^4ս{u-ت3!2r)y6lpt:Ifwt}D,ň=,8+b 죩cLҏtayii(  <@Z^E]sY%h5-j&"4lhu[ڂ,ݹe>+S2lejz f,b dѡ+#|㬈ίٶ5d&YjXc)ӆ#]>dXަb,jZJO+,Т8䜉?#W늱RG&'#Uam &В yZ}q$榜o% /reI[Ks/)y6+#](GdbYv+fDQCMYSEI\ռ%o:6[: .$NLn"z3'רȈt,2okO4pѤwhJ\@׼BKndlQc2XvU0ҏtayii(  <@|Z6M$5vYZ66L$$鴻Q o$9m&ף ;rEqJf n3&=NYLCƈ Ħ3Ԃƪt""4$MWONT׿THV55~{9[v?FnF)Qvs5]-Z#lmEsg.^+F`IYAWFMXcm,r?bAOxbweZ3AZnٸ;1(-u=BU}#XIٝk诟K(5/Ͻ WdllqtEVIT9T/>"s h#OېD(Ud- 隂8W` y.^?Ѫ[+`- f%5VLG'OvGh7KD 4ޤ^IsM6wHֈ -$<}׋-Ӿv-NuTSpo 5<5Q1JtKu5=&cQ m}#'pj=S.݌~||ȰM@YԴ4l VYEMW7hQk;4'>}TK4ܷUPݹB\:i5[ ̜AƩ$PIH̕ZW&}gFs۶G"A#*a)#WCxD$7~[-emR2C9O< ~FM'^oR0qg&ȜϦ(֌ͪ48/_QJ' Ӧ\ M/<5TWoJG Qw=L鹩1k,If& ̻$ܳW'KK?Cm,ʢ4`[0 - c\FRu5jjooڢ^>h9U0ZӴVlڔgӔRFgidqë́\QfjƼiԌ;#7Rd WҙV qKsu:T/]hUˏ $f`X0>:yDr[̨ 4$^a lInFк4(Ɔ],Yu*Ғ-} Eh=fM5l2casߜHͥ&St郜'Ü;\9\4{3IEmEK[Ү!%< 1GFdTL()l\SNfY!JPy#w|CR:_ҧxDZZFF32,uL čRW[4kh63o1Sfe[(A<#q'3&= 4t[52SvNH2?/!.<6jzLK{ dsKGEfr4(aYn"V iقii(  <@_"Dz&=+S2sl@>"sZ{:g܁2XGA|yUQR%#4'i1j.,^?f̒K[AjR{;CiyNv?IjrU(M7zaE26Z%\r%Mie&70Ό拞|fM~ũ1k,$fveze6XI)fPҾml$%f!* 4lAYԴ4l VYE-; ǏfBjR`%80m!Wd<؀&>"sS< ]2؞ B/63dT"/>Zd7sMd.I'u-QsxOKA컡uok@\O5nB~l)Fr7?$xvUAf[4{&?6%GhvQQc2Xvy  3nޙe/0W<4"z*)lֲ\lȰMEMKCi`i%Z"BP bGd.Xb["v*&YjXc)ӆnYd0Sǩk 4@YԴ4l VYE-гA̜\XŔgE;pÀUd#KMk,eڐ¾B˜WL3&iblO$+wy(ju45/]`B͘킚qhmcWc 4._H34Xo)6 \XŔgELv=}45YciCZK @@ʄdXަX1ƚJOicWrNRbtuLh;m:iiV#rECMx(v# +S2l@z`)o1b7Ί{hjXc)ӆ6G$Nb)dXަ-Fa 9)m'z sD/;blu&JRaڼIm劔*C p`O@yghGz8z(j&&@+S2 l@z`)o1b7Ί{hjXc)ӆ1(1!ºі 6-٧qa c0iN7+ >;VwWYmw Դ4 O m;]q{Ri_?\Xnw{{w;![v ڞI@]dh2RT)y6z`)o1b7Ί{hjXc)ӆi-l{Hz0ðoVT5D(MH(.0[m_C ͇ @JMKdΣm* u dXަX,tmr(Ԯq|_^Uԙu@kݏu&(85- cu-M\"%}0)]?#N,6sR{77N7Z^ZNiҝT)I6oXf18%`C &-@b|$;n/腜4\w_#N,6v1Xʴ!-@i(Ҁm0J ; c5MJZW\E][Uص-CK!pg\+H7ͽiyo~\da&E&*-͙"cπ\QfUL{{XqVdGS5K6!6 eQP-xZ dg:.ZIt&Dnq8Q o$9m&CygF$Wbzt]wC(N`t}D*ň=,8+b 죩cLҏtayii(  <@}GgcZЍتEGV]eD$rUVkvf0dE6TW}wB(N} ]nNG:C#2Wb["&;>1Xʴ!-@i(Ҁm0J ; Opˮ9vf5E%cLZmY-rNhRVAiv sP$Wtwse쮿rEqJfP{v4j%Gdb&["&;>1Xʴ!-@i(Ҁm0J ; /=_v1>a'hUK;[[&|T50b"RuhMӆ4ŦM)\~6M e.ͩ*L_`f"\Q`T-pv9CB#2Wd1P-FaYxO`MMk,eڐ~ˇ 4X EMKCi`i%ZK@z>xe3 8,)p RS2MsMj:kA싖t뷤]!CcP&3ܙ<hTR斫h&b)y6{}#Kvm?⚡+#|㬈'&k52mHK?Cm,ʢ4`[0 -e;! =j`D)y6&̜NfDëGdb*6/[+6zmc]Lhu檦ȷ]IrMg/edOQ}?ݍW4pѤS+!TOM,d5=&c%m]EONW[-@i(Ҁm0J ; Opl\v5!MBL$}qLHM tYő|)y6f|  M\4=eƮ aJly|lL|k1HV5 |}0 >wQY̵6;s5]-ڟښ#[jYSc\5]5e9Ezh1M'M 2 -G]s x/C;&@(N? QO%=Fj&`?V \&md4$YkKMBţ (h![`B$e`ED4ڀ$]WmzK:VLG'OvG,zz&5Yi{ssYY{1/0r#iμv6mW4*oЬ} hy2ц M~_U5GGʢgМHfL)rOxnFK?]>dXަb,jZJO+,Т>N8%3F;BjGdbКL"s[mQ4AD_].7$W9TTgDs 7),hUsHcmEB=٪{'n8hzn?c2eA6ͨ7NZ!pU dM˧|H+3ZMXcio77lVs騨TS8 6Ky֍Uk 4lAYԴ4l VYEuѣdB(Nu]j1:r'>fFUԙQv9Sԁ_>[`B_f̒4&3ƘѬBa=[e3 &gS:$&~@ e5a&kd K|fM~ũ1k,$fveze6XI)fPҾml$ia@%]5dXަag ʢ4`[0 -k>xe, @؝B(N,xM}D-UK,?Q]Rb "[Z[&YjXc)ӆ6;FNdjwNRay-нn1XYFnjƋCsfJb1(qh{IR]'Q<^AxZfu W ! U#wTzWwUSF{oi9혦KwR1pvw\QY`UL{{XqVdGS5K6ہlFCDŽ ۴4AF2geF mpd5KmݝwILgEԴ4AsԴ-l]=GQ:O OY齂E,YE~#3Or iQk8NJȟ'ꂈ%X,jKwRYNSB(N,z }D*ň=,8+b 죩cL_!Lf&p 6-oH$vlE6cV(A$-6LP<5- #gH?8 ds9._q{"ET7[Ė4֬󔦮7̂ЄGd.Xb["&;>1Xʴ!-EHv64̹\7ȰMKif nퟧ >3i4'ѝzEppeS0 Кt['di%r$n&wEOw :79)7{Mlc"j}ZA(NsUL{{XqVdGS5K6 ȰMkX-ۡ|-I:KMG*4-9O|"۪GkgOLx) t <Ð:Gvh/9h:rzI7r+5s si3Ev9,;)l\XŔgELv=}45YciCZ.2,o,Mn#6@ mf/Im%RQMMKt=qڶ&+hF%:֧,IDYE? @\x… 0/9dk5A3[U @'rP ڀE- ;N"cٲZ徝 ҡHNR5w8%ҡ #|㬈'&k52mHK?CmZŒ-6݆Sn2!ZsBfqKJSW6ʤa :6ے{ӓK@EBr‰E,Т/;8 NZCMLj-2-JR[S_۩8ÈkKk6 /kgӔRemo9N򅢪qf38%`C &-@bf-sZi6SiFDg;"[<[8ҍT3%Q ZlKXOWT>} x!drG,ТZ/=5]jdSmQ1pt hט;"US3-oIBhPpârU뱦iki&Z WdpY:>"sbSbo1فdR iG|ȰM@YԴ4l VYEk.>7?EO50'} WdpY:>"sbSbo1فdR iG|ȰM@YԴ4l VYE߀^'?N I ,,];7\QfUL{{XqVdGS5K6!6 eQP-xZ dg}C[ B(N} ݒxfC#2Wb["&;>1Xʴ!-@i(Ҁm0J ; ng?\Q`qxrKZ@#2Wb1P-FaYxO`MMk,eڐ~ˇ 4X EMKCi`i%Z߂D7` Wd9ۿi9+z"(o1b7Ί{hjXc)ӆ#]>dXަb,jZJO+,Т$| hސ+S2l엙ܯkPtU Gdb.["&;>1Xʴ!-@i(Ҁm0J ; E58xF+ @=zl5RT)y6m<9c 4\T9ʇZu"&kjlœ890"\Ք-Ci]"ieOQ&'8Gh8d֩֗]a&1k,i*B}rBzhG|ȰM@YԴ4l VYE-ЄA;14J IP*<sFBF}D,q(˦e|X^!,C)pЭQ7Y:ŕwg4PA IV5 ls{{3{Ǩ6&b̵6kt D7k-0ũ֘?5uYMXcۥ^XSФz4X +Т.L'-N.rEqJgL@z*1Q-+zbL8%wJHEw(ܦ|fGm Ө\B\\wdYUJ4Zvi0.%DA>CrpzKVLG'OvG@M4dmsgMdUBȍ9dw/ iv5JJ WO6'cmo 4j\U+1ZMXcixTx,z d&nbxO{»w3Z !6 eQP-xZ dg}׉eF>>&|t}*I>5z@mٱ5#3,rEqJf΃La\p/c2Ak:=h,>3%4w1 π1e41Сjf9$>]MJD}t,7oX& w6Ahk16}6}E9Jd )ը@5]@ S8|9(|Fz 3sSc2XvL:g-8wIg.WO(Y~ˇ 4X EMKCi`i%Z%}Je2tD }gkKCΙIPKwrl/:ΐ+S28,zZ-9y{sx~pqleZ;FaL82+bɐH`ټj,m>:yDrwg^o0qOk"#HCdʁ)N-Z924Rxj 4'ҬiP#ZƒmWf,LyntTTdlZ.2,o`1P5- ۂa@vh_k.SQ΂Ehyrh' bI˻iҝ\-ɶί3 6KGdvu̯qc&On F)d;M. & >DѪm/$ ލb ٪{'nt_& @;[ɔٜ6Z8aHk‡U3S5ENH2o /!ͮh5=&cZͥZ3SO_Fz0,Aw5^dXަag ʢ4`[0 -k>xeq>veW&=j xh/lnCI$RNpg\+H7Aȸ7_i x+㠲V4;ȗ 8%3tA#2WŒۆ0Ok2(S=KNKZܡPY<ۥpyī1Kb/m gIGS,< ~F ^ocHo ^#,4>M鬓4-R!jOM9!=p͚fSc2XZ5])̵#Hʼ3.mBR<-}SـoIr"5 nȰMEMKCi`i%Z!|p i @'OJf"!swA#iINIPVC;5 h8%4+lNns8rR/ӊk"D9Wgx @v#/ƪzCߜ}usIb߱yDv)0 V =p=ՄObȏO/Zً/ow5iRoVM&K|fWcgS@w΄/ -yCBfG75Cmv,jZJO+,ТhBE{ִ[6wJ6N,z%H>ɶXIٝk诟K&>t.H'%C(N,v}D*ň=,8+b΁վGe&k52mHK){P#2oiӰ%kay}(Ҁm0J ; Kz@kZ̞6moD32k˶co'4H)4st(҄tl.eC(NyUL{{XqVļmX&YjXc)ӆ h]1sCmGބkMm/G N͠]<|]'j$ H8jZ!LζV[=IS&)=@e7i[NƉX'ʾ൦iCbS֦fw_?D2:v3)ˇ\QY`UL{{XqVdGS5K6E_IrيpYdXަX%VBcdUTCNVn.]W=.٨+ۥ o@MKty]ӶQ9%eCe&ROPy'h/9v#.5~U7_y.}shט:EmEK[Ү!%B (c)+S2l@z`)o1b7Ί{hjXc)ӆ=et0 jswQ2,o#t;e ɢNў ucME6dpu)Ѩ(ۥ |iiNKmk4(8-R <睡Eo@?>Hd~9hMO50"̂ЄGd.Xb["&;>1Xʴ!-EiLhDGLNN@ ۴dL1ڸj7^7+ & v).lcMBnTW`BB@LMK{!uZ^F*z*O0yh/:-7 @?~l5R+8/y Wd9؀N}D*ň=,8+b 죩cL_7A2,oZ,FQs.ч27{Ib+UHM]J{9m77Yt<ɚ]LA"5- uڶ"-#ON>)ϻu@ ]qA5+S28,z`)o1b7Ί{hjXc)ӆ#]>dXަYp49A!g`VҥLq"vi0ai4iiNS5Y 9lbL-paO@}QZ8DT8%ҡ #|㬈'&k52mHK?CmZŒhtʍhV(QtF0kVqҾ/`BEV8yjZƠZlKz'8V x(vӢ?o@KgrEqJ32,L Z.;S8dIJiIiG)\F{լ.eg1( $l72`3%#Lm'f{a\%>.wZ!߀0* 6KGd.Xb["&;>1Xʴ!-@i(Ҁm0J ; eA+ @V3!5)J\QfS@*&ň=,8+b 죩cLҏtayii(  <@~h?7 JRT#B(N`t}D*ň=,8+b 죩cLҏtayii(  <@~߀t2u ]>;;naſc{o>"s5-ň=,8+b 죩cLҏtayii(  <@>2ñIbDh8occ!1ACXӑDze6drEqJfMbL6`z(o1b7Ί{hjXc)ӆ#]>dXަb,jZJO+,Т:h!*gϾ}{tք!h#i @{9sKwr|g 8%39Gm4zd@J(o1b7Ί{hjXc)ӆ#]>dXަb,jZJO+,Т:Xڄۂ&ldcyW;m5Xs @ww~+S2llLy| CW9" <)@#2Wd1P-FaYxO`MMk,eڐ~ˇ 4X EMKCi`i%Z^' @ώ?OF"*@ N%}q$ɾ}!jMda&EZIhJ!Wd9pHɷW9S@%>vʮL(ju4P_<ٻ~4W55?mJgkn:{)#o$~rcn}Č&ZYZ_xjtda) }롥!6 eQP-xZ dg @ѳxii5!K+l303] p F(7n롬 >@2Ar+1,JOicy h6½ܧԿjd:Nn%$ꍆDbT؟v?Fwgbk ^Nn-NƬ1ujzLK.M~Ųo=&}ަb@]5@=>NnqRD ִ[":ꬴ- XU+5s si3E4zұ B);Ō QO%=FL {8zbL8c]e>۔ORn 1YX: %)[+"Zդ$'1j[ҹb>:yn?Fwefכ+6iJۛʼnZH4g^;vHh}_V5 m O>iKVbHY,3MV"w fCm,ʢ4`[0 -?sct'>w=rAZ@r!u4#lrNhGufw_?E,rEqJf΃:,wN B#2Wj1hac)69k3Jy'z6b}&Cw'm+6Uлq2UZ)eۤdvG'QM7W B[+ʁT"S(MFt0bƘG4zuiɔƒkfRO9k̼K= }uzBq.Ϻ#]>dXަb,jZJO+,Т_t}ߝ'mY_|ˉ/=pF5-h?? 6#DК i‹MYRݹBlAf~^VC#2WA|]>Y?|VU5D(MH(.0+b~u)4+X!ѪF~DpYLy>:yDr{߳@M8ΖiMdiL97eީCZK=tkITʏq @2 Wd:؀.}Dj>|yצUEI\@թ(s~s0D=Dǫ1KҠNOPcjo$ ~F ^ocHo ^#,4>M鬓 .)rB5,)z5:dk˻RkGٕyg\c&4CyZK8'2,oӰeQP-xZ dg'#'6?BH9C|HV3!5)Wa~6)6 \̩NHw8kIL+NĻ/3s@n4V~[@:Db?n*RlaOKA2s5]zz w˳.|-Uh:Hv7}LW7jhZ%EO>B1ZMXc3j)LygBڗ\P<1.˅ 4lAYԴ4l VYEC'D={w*frMO$ \QY`2UL{{XqVĜߎUd#KMk,eڐR{*&Iοrk 4@YԴ4l VYEG9s:AݧF#hA(NyUL{{XqVļ!C?u,5YciCZ thw_s]3dXަiokMe./֥f4[$P&*)ʥaԶ-O\{`b)ϻ@~q?yGx⬄牷xuK rEqJf hB#2,V1-FaYxO`MMk,eڐFmЦ9Ii-#3Ґ͚F"a061Mf5urTl5Cu걪)WMMKd8!zN]ckɁx(?-Ys<˷ȟ{N0rh^+S2l@z`)o1b7Ί{hjXc)ӆ6GF|m$Xay١ 3Aٶ4|$L'ΡPUuR0O\l[(f=`z)]<->vFׯqAO$M&&[̈́Ԥ(rEqJf hBO V#|㬈'&k52mHKh{k{ FDRȰMKi3̠QZōLoV:fN_G_7lcUJMK Ŷ5y8kk xv &-iqO7MT'=+S2l@'>"sbSbo1فdR i/Р i-lx9F's$ve)wk HWj_E>KUJMKwdXަYN=õљׄ|u9 !`USW'N|jSJMK?qDmY<&xb;-=n1Xʴ!-@i(Ҁm0J ; #N,dU\-DCK!pg\+H7}{yCkVffB-^8mYIPϞZk} WdpY:>"sbSbo1فdR iG|ȰM@YԴ4l VYEubtq,DB"78&] p F(7{MV$F:d w8%ҡ #|㬈'&k52mHK?Cm,ʢ4`[0 -@[":ꬴT@VJU}#XIٝk诟Ks8>٠$\=A71Xʴ!-@i(Ҁm0J ; #N,ֱmuX-eD};AJYٝ+ϥC&m5 F7l\Q`c S >"s%5Qbo1فdR iG|ȰM@YԴ4l VYEub4Nu)Fb}5ΰ4hkњ i‹MYRݹBlA8K|NPI'U$<s{X^["&;>1Xʴ!-@i(Ҁm0J ; #N,&8*VQ14{uC+;hI~K2D/tdZ#NC!Wd9o8ooA|9*WIW\@]gE 4_L1dR iG|ȰM@YԴ4l VYEub h &:=O9\Q`c6$) \Tl_ +sH~(ju4uPx!Um1UDsUSc)57Srћ~=ѣ%_jD4p=&'Dh'5<5cmƒd) }롥!6 eQP-xZ dgRϟX\L$}}fBjR`%2KƮf7\Q`cN>@INJ}D,q(˦e|T!,C)2rg f.9̐jj&4d`$c='FNbyY=ʰ׌hl{i9~Yk{V4\jzLKn#,[-#IiP!vWE}wܹEb @Hcq)2&t G=Y㨖SzbL8 c]# )ّœ0M8i)˖DRjBDZl7Oװv[1M2z dT"w fi( LIeۂa͂ݞih/"#|[߲1 ={v9) T&9-:gj+7 ;9;3i=1Q>3h(-lc4 ѪF6ɍ,VcKl HޠN캻-=ixѨIĝM,$s.`5<ʁ=Vbtuu5hHGcm!dl4zuiɔƒkfRO9k̼K= }uzBq.Ϻ#]>dXަb,3% l V4 ;E4#}Nr@!+S263bH >.Οrlpe+ǪCӈڴ( :=!!.QʉW5c^:AjR{;CiyNIkߖڠIn ^ɋ1o}4dR=p͚fSc2XZ5])̵#Hʼ3.mBR<-}Z kl9F`\3% l V4 fOC~hž>|XRT#B(N?ḠGdb|P4?גzV$D/.膲3nij̵M$Q.Ea;-='X^kj !_KEfF=TZ[hjLVD -EO>BdMXc3j)LygBڗ\P^ @d*L=ȰMCym0Jfbh/"}Et2u ]>Lb0z`ɮjE1b7ΊsQ(?:F1Xʴ!-CDIhƇ);`&>"sb]Պbo1)-꘬cdcL_7@{x'FoAay-63,5X^muhbQILqP.䙒 O\)'+hFI 6#z] h:3 vWEub4Gx<Jٳo7R߳g~WIXR~kҝ\C\QS fB#2,V1U(FaYxO`MMk,eڐNbzϙ i-#c&sniݼH,4*6Pڔm=..䊃!ϔ'.zN؀~t}:[|B˽OPzA`weZi&v. PPIuiCZĒ*wV;wه 8%`c̄Gd.XbZQ"&;>1Xʴ!-ish# AՐayX|$i2#?74d+RBJB#j( :B!ϔ'.LX]_*[|B$e` )6chLC>Bhyd<ɈC)RɈDZ ܇;ZARGYfx+H}n!f+S26vL}D*&ň=,8+b 죩cL_D:lA nI6uBmZr4sam*b-?` 5TK%b;vB)){ڟ8Cl[됇xybRIs)hLC>Ģ趍OJH6L$$rtn@9sR o$9m&ף ;Lb0z`ɮjE1b7Ί{hjXc)ӆ hЄ ۴5㭄m`,wUtJKC^hEUvXٷ_]AgJ 'նNJceJY|Bax^Y2 -_{w;!CMLj- [;:ilZXII"r+5s si3E4DYd+S26vL}D*&ň=,8+b 죩cLҏtayfƆ um(3{lCNLR )vB))0O\mY<"t7B)+:hLC>~ 믿s .¼䐊ڡ&h{fjX( ;N"4ٲZ徝 ҡH ] 8%`c̄Gd.XbZQ"&;>1Xʴ!-@i-Kt:tNv!*}vv@н( eD7h).Y2 -I"ꫯ+/3/ /t,f_)_ #&җ5M Vٝ+Ϧ),Z0 -8%`C &-@b$d+5T .C0JoPĢh"m4&~dl\TMf_[% AQ Z2t=Z}^);`&>"sb]Պbo1فdR iG|ȰM@YgJ , <hLCZ^)ˮ9& @GtA+S26vL}D*&ň=,8+b 죩cLҏtay ϔX6-xZ ,]}⊟c~y[z W`9veW>LHM ;¹̆\Q. \XdWgELv=}45YciCZ.2,o`1P䙒O++Т/~QbygJT8%`c]^?n6YihV\MjȮjE1b7Ί{hjXc)ӆ#]>dXަb,3% l V4 vWE__/| 6}ux4`]!Wdlk`2G\k֬zȮjE1b7Ί{hjXc)ӆ#]>dXަb,3% l V4 vWE? @_x _?huc\2tF\Q 2g :+V#|㬈'&k52mHK?Cm,ʂdXަb,3% l V4 vWEuѣdB(N?Y &~b#|zfYLïњ^AgNi*W+\մ9IS{kn"#&7uFEFcI̼M=>bF :2S6YMXcIeWS,CK?Cm,ʂ"sE8ƒF2B!j*Bڊ;ɪ! mnoo#>1r5tNuwFQs5]-srks1ZcVԘ:f5=&c%n&?xbYNѷZG @> o`1BLCZßlc:hIut+S268cBrSIQmf[,`)]V`qB!tiÍWD\͔VZk!o0+ab>:yn?Fw{EF'Mk涹&bSIs&ZjF m O>iܯFVbHY,3MV"w fYkŋ/\ CVy3@Gt||L0`T-}kcYaȶ2+S26&S&*wN345kG >ngLTb1YgF79MFDTO飓'7yBM7W B[+ʁT"S(MFt0bƘG4zuiɔƒkfRO9k̼K= }uzBq.Ϻ`whPkaǮ,э5j|2-kw fӿ7:gc&9t8jt.eyN)uw!bgxq>Vr$&iVPHӑ ͽ|Ea?JѳYL  6,G'O Q]hѨIْ> );tHkTv Jɚ"+4狞|HAtjqjzLK]0o~QQu)iGbMj-Nzʿ-NZԺ'=v"d~,ݹeY}rEqJfxH}DjXi%M j1YvhᔮK :TYk޳13Ȇf7uб@M4pv) 9-mF,TCN݉ɚ"'$˗OfWfnn~\QQܧhGbMj- КZ)]t̓&(C0fǹVo$qyo(20j"WƑ5w\QyYwzZ-?kvJg2!ZTQCf钻ҔWO0fI쥭 5?bj=43ѬdM7z/fsMϦtILg e5a&kd K|fM~ũ1k,$fveze6XI)fP~*$ h:{BVf"!ィQ o$9Q(ף syN)uw!+͚#=Q4[7iH3 b<["sbSfC3b7ΊwWd#KMk,eڐǎ;rstqb2\+s )8z(f`rU$UhEz @;w(GbU%QWiڐ&ؔ)ٝ+Ϧ)$h3 8%`pj}D*fo1فdR i+MF"9z(M:(ϵ6v9|vɣ>J/4q/ (=WICZ ?sXt#:kq4&hט;"US3-oIBhP.lnn&:!WdzlN\XŔЌ"&;>1Xʴ!-c9""IGVswP&T*iwhPkaTfwc~"4Кj`D)SC#2,V1e>4#|㬈'&k52mHKXh})tTQxk%;8ray78rlWv&Zw hȳ 1Xʴ!-#_/q>Jv.X5pJ\Љ_(rt&Z@vI M(gO|Uoʫ=w*Wv&/`Ґ+S2=6TLbIʈ=,8+b 죩cL?bNnӏ`PDzǹF{Qc0qO%ۓ6*il)|{6@6Qb}D6]ؿfzdKf`n|ϽWxxW,W.|Oy9a%rԕίa ]f=$c!d㥨L84l5RT)SCO bIʈ=,8+b 죩cL?bNfp;> u,{kgZS$ݧw5%msA8ݐHYaw7ttc.`"մ Wzi=:iEo??}W+HHY2[">eR][*M,~ewhPkTfw4Dj`D)SC#2,V1e>4#|㬈'&k52mHKt4gcHBrp}ٽv/Npևi?-]X H7]gzd<_?Cg'Y;OI50}_3YHfk%ӯMj-P=]~Zş9l>1]PLσM3W[;F)mVdGd@5Ќ"&;>1Xʴ!-#Jlۮ} or-‡=q&rG2_n)K`eۀѐdzdxꩧt $1Xʴ!-#rVs{˵Q!:gٔ{n I% 䪫z[JRZ1Աq.gN76}7` OGm)+،NU=jt32/k*lE;Xd.>铚O󑧑=R1N>Pj|-nm7e a>$\>L2WKgR !l@ZVIBԔ/Yy=)Ο?/3 Kiƴ4e_מ٩1-^ҵ.eiRn&⴬$q"J,=$c!?}\hMnexG֨W=vka=э?SZV;wYvrw7LσMN/?9; @bҵB#2Wd1Pe>4#|㬈'&k52mHKh:8? 7~zOLJX?}'7TY<G_o@̴u8Ixrf8v ڈH*!*@qsO VtsŢDfYJ&HKʾ9Hzj%)ma2}P=̦uq-5:] }-'dzds9ZR_o6sXv ͷ[]Z]Hșf/rM;Q 26ҁi izݡI@ ]"^0c(2ve?˻iҝ\t[jkx!Wdzlp&o4|(:*G΅Gdb. |hFaYxO`MMk,eڐtpz1p9h=h-0)R_22td3:=uْp33$57AݬB_F MI\:y\i+q 6'8{F͚}@ (4:CD:!ag]SL\Olh 葑.i{i,ʁ(|9hǭl,ꑔroyQo$dWf"me FWv&/۽}2ū\V$/w6;ε~#񿇕ןGT[t*\Qy©sdFoڠ+ϊkMm5Gf N͠]<-j$ Hs47w(57Sd8:5*2b֤06DgMz:2S+,d5=&c%m]EONW[-%I++>8e~sv9iP ÀZS_K36”iT BёL|妒i+q6  كLVӔb? "{@gf{MǕ`%M$}Ȫ)"GA}*43?$6k(=,Y=猻fzq~ӭ7ϯLwigN4OW7oF#Z( ((j!-noETմA$X$ d vT +FčK_yʃ덛%ȥ-sU!eտe -*))2-P7}C?̣0, >9 ID$T:;Ыh6+ j9@= !4%UEQ]I88Y)^͐5W%e{?Β& ?` ܸ 1(%%76*vF NK2P@b@_eye *etW<ͮs)Avҥ`qcu]']=[q 3>ɜ: z \iFWNk—;<6Y}<S]#t45],j YdC׎zC81˜* t 1Z}dS I::"MIhĦAJ H+79&@t~L BӕțJ=Ah#6iuX[8}| !V>DWRsͥev4[N:+UV:щUս9)K x  .OPȔ{(|{]ē0s<CϲSOi-3BJvΤ,q~CCA-G?BHTgL4%UO'g+ErG$݇ű ,v⫂Ci15z_d˯PVbAUPĠrpGa3[5XSQp_:19 ^^Cى `f$Q_K=pڗ̴+2=+F)'-ͬ BÍkx3.Δ$Y# <Pku R8=R_{ ஡2Ca\:M_JWURMQ-,gԲ넉`"&ߠ}ԩau x}FLXp;9BVɛJv~saifL CvJƕ uk,ymYihJC7O:ElҶv!2WC鬈oU(s_*-"ƕSɮ 7`} 0m`=w3.Π~tKƳDԛ 4 +'El3{^L5H>*vi`F0d K6CA'e৾x 2yX=\V検nܨǤ+$d)F04 HCYRB@k+4J]JLJIScq3I'),ļcRϽ4Bdey 'Od̯ n>Gj8 ݻaȆG.j20p`jfL CvJƕ j߀$ukpM]AyGwvA5VK%)&YU)*R>0 *B:okx..yn4EDE JIɍ'2z#vtK6G/\ͱ .ŹB"&J΃wi`F 0k` dO m2y8j]^+4=8Q!} ?HWz:KSAΑ$@2&芠QX3u̇?Y ;Unlg,oei(9 .ãh+c}#o;9BJqh(fxcPq~CCA-G[D6M)ZAԯ Z8uȢ%4 ~_8NZX$k1gɴZUZXd?BRRrc+2=Ւ*U;kk;]9SnN5K@kK3Z@IE>l_ /`T bKfa7zWhzhypt"ϩ 7ژ`$pR']tE6 }l6t45vCJU TnRoP>qı(s19Ua m6\V f}@ɸRԣ])E4|9qܕ1{4,<1:`ӭViSƔvi`FB?lC썼YEjPJ /ti4pCn{*05@̂7ːP$d`0&芐l'1͊~I6ij,2͵&y质GEgߔ +]Ad7-sa m6\VլC^2oh(t%}w}ɗ)BRRrc+2lɍ [əYנ/df5)YH; c'|dߜ}=`6yl 2+hf&%=5tt}J:5Do ׄ]gTd|#kt45]3k q}=,mv3cxVoiDعs'l`%t;JϩR0 S7{yꩧa4zzV_| ka??%oh(IE JIɍ-2Ezb%LSKyaΩ>ni%Ek#HJhj,qM ݻuDt`/gSx.n ~gv<Y}??%oh(YfZ "Ɔzb%Lu}Jy 39ZARFScӇKS40 0 S774r`aS=0q {sj/ 7K>G? 0 0 ~CCA-U H>,@3 "Ɔzb%LhK䍦40 0L¨PPaU*" dL@(bPJJnlXN-A.Xc*VaΩ$JJhj,q,@3 0 $ XcS )S=0q {sj/ 7K>G? 0 0 ~CCA-~?.贁PĠذZX]채S4SxI?X!G4eaa8z׭Qonf@5YRZ&IHg'L@(bPJ΁IkXrj)Y^EDN1,1ix`wNMv%aPRFScӇ]\t caa~_˾]rM?IhѪ?B跙$N,|Z|^ͮ eFPĠ"@+)yLh#Eg_ 괔mx#G 0~Dk^%%o458}h\daah(Z¶ͤ"W*LB#v˃Y^Zg('`|pP>ϒNFĝ#DL'dǩ ktEzw b]Sk$ۤPAهK(uа_~z800 0LLS,@ %P,@P4zm '8v dL@(bPJz1d::Q`ɜ$sy$ b!p(̿LuJjWM;MDBwmXva1߯([ ȏaa!(_~e,\Y>+?0"ZJ#I v.cBN 5m3JR9ũ!gvTP>loe()t̝WR&O~KBNO)M nTt`3θ8SC2#  s93eF(˺j5Zj64lRϫmXrβQw&Z<LH0Gh\ |hU4u3n$; 9^G?~ 3 0 =[oI9ȁT_M pA)Ive jB1\Mk/8L\25'LQX9dtu͙ l> <$&=.$^A oI( hnzhpBBc@"HS) ~ 1j5Qf uaItϤt45]1tYJ;&K.TOV\y_}po/~a|sܵOh00 0Ls=.\r@D#e ,@3L) 1(%= L>cwzni;Z%]#Te))6XD"&Klt)Ae$Ds3~7=48Q!?CW gRf]46+`mXeSl:m%'ex!@#Hz꺇ļmocp@Bq|[D 0 0q`<)yWT~ ݶG~YhfȀPĠw`lTKWpvtHXiK:[%|%+4/_{wsZDtߒd+Zcf^!\h{QaZi* ]Zrجiߤt45vCJU TnRC>Kz g<?9zcN=9ysyf[o?sĹfa{xR(e-,).'b+@2<Ԛt3H_da]lXIE J } pWȓhȩIE|q:ۂ-|8ޑ3HJiQsw fӓ}sc?طkLOp`aa\jwMIF״ ôG.yUlTa+@[cfKt%!a*d6fHPĠw`=&7 /l $gfU_M֮9laM9'M"E~*=VskzȠS SrwZCƅ]W`oD {-ϨȜG,IeRMծQ5O8̾wI6e;1T<+:37M?-o ?~ 3 rF.n'M,W4\L-" 0 C{='"T Z!Lc^Y\4LYCU"Zk7aA)aKţ{sj/ 7K>G45 Wo?#7o/o?Xt}K7`3?Xܹ|S _x蹯7hfeݚn.IcY'LrV3\2 0.JƓr@^{M%hّLc^Y@xAcXN5Zϙ -]채_yܭ{7|g_}xp_o2 Yco)1"%![ g| 0>s 9ˏ^@7xC%"/*LY ݩ$@f0iX߻3׳/y=h 1(%,@1c x`wNMv%aPRFScӇC^$\Um__6zpqZwߝ7ĖOlO}v~ 3 Gދ'm@ʓP} B~ 0{رcx^@%J%[O$Ŕ5ݝtyBR:Il\ E J }v.X/5SxI?X!<4qur,/~I,0 _|<#$F>W=&CE2 hmOEUSU^Ĩ j9{Y@E J }v.X/5SxI?X!<?qSLJ7NLCꇦ}4$00L.RY6!KLka( GQF,@o?]3xRHUƗWslf@(bPJX;cw&~hK䍦_ [W{`aaa8PB0=zT%)k9r7wϢ)RU+&rvh<4lc 0 *_ {Xaa&[%Isesnth@#!KaZvm h,F_zЃBRo@e% L1bhK䍦_B0;UXaa&N KkC$@3 A)Y><6Q;, <te& 3c# G 0~Dk^%%o458}:haa&*PPa40pOgC4 pA)Mr&2;Jm&`[$%`r<ƤDQ=95ځCIM%N£taa~CCA-^h`najߙ BRRrccɩ]dyY V(а,1iAi;&Z;()yCx0 #Wanw 7KNUo8okQYJ̖}h&>( 0~Dk^%%o458}~a~~s _'#׼o xz=h"SLbz>w&oW `RBRRrccɩRVF-H̆htZt@sRr`i!˚ץ `3`1!\';Y_']p8yr{X/kÄ5p:"DKz ]C+i)&Mm7|@P% {y`S00{5xbHo(гx's@})]U-I6ij,^DY3j7`"&?CU`q5 <ʟy fhL1JNP[ H`vlX(3)&MiW$xpֲI=h Փe^xF{kxܹ}*ĪZ9SXA@k} 4S7]>uСEn38ä{gZV "$T&X][bĎxf+U9rSun6n⪼D"&fUXl~fVnKQZxv)'#T83DpvTs8 e_e]5@VCul`w :h ylV4HNU'ۤ˦<4[t*JNųVk_=}^\csyhz͖[: .e+?w'jܹ^;<84Zs=y/,}b SCx<>?~{W~^zGg2v'6|\,?2Yf ?23Q8 `qot8]p|XF֎#@Cga\.@?ܕ%}VFs>  "$ɕSX]jIvَ.cZgNNӥ`d!%oR%|F Uz'koCR =1ѐN5ä75Ίl`6U*hVugu2&8l'fkOJISco744N[Ei@&A Zul-?=1s/-t̗>ry̤i3Gn|lɳp,:ɳ'Ϝ98+p6vzϝsۂ|y̜<'gzlp Frp ŕOoqV~Gn}{fNc{̜Kr|햙_Zb}C`:ACU;-^W;r98 w<=WN9rs/?ydנVg{-\<~dSy<> S;r 8#\ }Ѡ_>jt'^YFk|aw=sޫAJ +,@3u \tyZ$@T"2B>&Zs@&2")S"E JIpc+2lɍ [əYנ/df5Zu`H; c'|dߜ}=`6s(c̪ 1;_C8j@%1JhLv ׍~^wtGkTdN|#kt45]3k q}=,mv3cxV;vtˈ_ϟ?{z_1J9,@jIUѓ wY“*=G7SE)U?nyf 8ܹ3sب>䓨4s, :XϋϪSH)թ ?߱1;魳W]+ئl<4' w^^]s]C^G6 K;Vx햡c>ZG:ahnpc$Ukȶ}Zuן%"ZǖS"`=w)< 0~D^д2 lim`IM%N£tuܹ3gμ)9uɓ' Ъj {䊻<[?SUä__?O;}~|Wɹs>;DRr*_>y?88ܹO<s>v킘2 xY4I<@mx,!C;SOx<Haf:RFScӇ u]W|a<ӻL,j䊻&&`T+j $Nyص5]S7l`R9TtgO>7{̜ٙ;}bǿ3'O2;w:Cn<333oUl׮]XFU9sOWʁcdg9g=vJ{SeStꇦxrѓo$d\8lz4H}95t,x" 2yO|uS̯~׮4,@3u  %&@K5~yw֬LdqMjU?@(bPJS=0q {sj/ 7K>GB~$@v>W}n|N~a|szhڇg 姏ٓyHR\UX3ڳ'6thCĩP{Wj~_}2GÃȀY N*W(ͽtk?]y!+yffZaDʝ+'ߴOOa98D 3~jB̽ZXfhnpc$Uh@ gF" 1Yvm֌i̘ aa@(bPJS=0q {sj/ 7K>Gҽ0y#mʖFs \@QrŝENYW^~ $/0W0?̉o3{lv<9sfӁ≤JU*ϫ7|a۬Z%N;wt*߷oRwڅ&FL@UՏO+9 -3+B}٥{,~%9#GO9kWoo@{L.dx"q*x*E'6!em%eU斏9 *! Arpz FT Xfzhnpc$}BRZX]채S4SxI?X!<&@ {;Η:`K$)mSPSSSJ &&U ~m~<?6>=7}ߒ:UTR}vI 7?>&SΝ;'&&K/4P#@{`.`T4U>}~{[ϝX9l9pIuеr%@;,^~ %JS\O~%8dܲѣ?QR'ݷZ Lݰ .p,@d0ޮ@6,"$a9<c Ai;&Z;()yCxLy9xBɑKi(hlVyC'!`T+_ז{f/^XSTQrJ^>>&SΝ;ʍ~4r`ϕ}5jʧO^o}KSǮ{xffY}r7Nl>]+z3Dހ>fAf<8 _o(W8:[gzCn'_Y]:Xɾ#?yaJQ! L4ÔBRZX]채S4SxI?X!<&@C PU(MxB$4Pج uä___<~ͦG]9qRX:G>cb<<釧}#h8ܹө^P4\xCk9*G\ Ǵ+k)_W{'_]6{B5'^?Y 1TSpx͒M}BB [v¡U/loҏ-E4w>VQO^X#3'l @Yjԏsɣ dlWoQ?R> Ы:XN&*Xf*ݻhh)4 "$Rp1%waU4S_MRׅHyku*7 I,u."^=vͦ;w;q`9z׏n9+G-K+W@[,m='7O.=qcOr%@5ɉ'vڅ S|W_#@AmU4^#(z1qܯBk~]M//ut'XB`?Hʃܽ{z ݻ/uK;_޶.Ͻ,@OlOOV XQ',@3u \<Ҡ{ .,,sk~%_G1iA) nl|baAmAc SXi;&Z;()yCxLzN&U0r8;9r4[anњ㛦_uv*߹s_9Ooߎ tGbV=٫orq؉c`K7>=Y Nσo\_;r қ^^2ݕ_#m?Sy<> S;d0N dc?x|Q_\?r5*.9XN&*Xf*4pGyˡ_j6Yd,<Ƈzb%LhK䍦?0*aR;l7}Mir1Gt6̼8hک|3z)ԛ=_T:Xo,p|\ ezҳS+ϼq7:j8#\ mcNy,aM5 S0޽{>B?{䳏'8a\* ГC$@C[8B  (Y+]8Mğ-8Ƈzb%LhK䍦t*)~kE 0эzԵgM//. |p*W^yebb'|ǟ T'X٫v0gyA_^ܣ3/=k+Ǿwg?_av*/f7'dfp@N{sl߰~3SP!Pq́Gu2Q4S7U'''Ae'O ν}뎅?Y?cBR|xloѱh;)7G[z=$ChK䍦?0ĉZ ~x2ܹ;t}=ʙbpGr:dhnp"@GxLO:i$曷/|k9u,##7n4wn[bM291:\񝃌!o QZ몁PĠ76>NK9 ahi1hթq {sj/ 7K>G`G}1zJa0X9hA$Ss=ʡBY`xRkL1J hnp"@o۶ TtE'O>z&@x.Aη8#I<1N[N'(@CvDdtC##CڑW"$XԜ'?UiF&thX]ǘS4SxI?X!<#@OLLܹseeXa0Xv_R哓/b*8U%~L1J hnp(@///}k[w-8[gn̶>|Gl,f!X"bQJrs* M:w]!) `%40 }Y4!)l1"G G.cLZ)|PaΩ zCEk#HJhj,qݻw?裰I/kU>99 TBg':6wjUqbOCh"Jӫ4jmc \#ҫCP y]C+G)&MmW >E_Bl=0 - 4S7S @c̙xw_ ߚX繕 Rw!ԥ~*)1:˖gԒdGĂJ_a&M=W B6L=&-rb~cs%"X[; mu$!b 6|;IEO+M+Y:maq[!}d+3#|:I{:w]W)EѼ0^OM5pQu/nr(IХ*vRM.L~WP,@3 Ƚ`\<,@3u \`>{MӐ7=7ra Ⱦj!h\i6%j{;NuN㏝sC?Ab!i#ةj 1(%%76v z$@[D7m2G.cBN)BuBv[[n0x e'pIZP<},Vq @+F)'-ͬ Ѣ0 wBÍkpx3.Δ%}N G.Oy#)vğF]cUfL f1|Ȧ/œ)&Mŋ(,gԲ#QD &$Lha\% 7l_ՁGu2Q4S7% @_{tۡ/jt wNgLCٺ5l1:] šR Ŷ+ePĠظLvenW}`Ws7qD7U\"ц'LiмĦu%!L5y%|OBIIO*qr2yX=\V$fUhzqBB+$d) gL13hN]#}Q|a uaItϤt45]1tYJ;&K.TOV\y40Xm q.Gu2Q4S7 ]^}joX~B_jd山 T\V^8 :`\XY!z's{fB)M"j'L4Q2:PqYxA\/:dhnpkw^sW  8r ̻ؽQAIw} E JIɍM z=&7 /l $gfU_MVR\#KH~e4#o aM9'w0SUoV=88W)"lQԽN:p:Հ>gvݾinXy8KBҴKFX!<gϞ=#9_1Jha OYfzhnpSseDuC$@3 A)).G.X)|PaΩ^nާTR#$%o458}޺usyGy+ԟYffj,@3u4S7)@[c){nl:L#,@3"Ɔ<c Ai;&Z;()yCx?裯\!333SSS V>0F?0̐j hnXf߀$ukp'8BRRrcrjy`=w&N`wNMv%aPRFScӇga Lݰ .pu 4Ѣ '&& ȆbLZ@(bPJJnlXN-G.X)|PaΩ$JJhj,q,@3 àvB.3%8BN&*Xf. X lXdZzvų7m5ZsbLZ@(bPJJnlXN-G.X)|PaΩ$JJhj,q,@3 àZC:Ĺ^uD LWm>|:hL'@S޾uz&@x.Aη8#I<1NZ1>CvDdtEmwcvH;PĠ@)͘c 0 *40CʖT =i(j#OnGXc;ށ C\jA}]Qu҉3o]ufl_9}çb^">2&wpxǨ~%99d&~;F.dN 4"Ʀ e% L1bhK䍦40Ckwwqcv˪Łj G^@1 |T?~wnƥ!.pu Ѡ+ p7ybԅ7>c^?u _yj!WΕ>j#|B+؟mbiT-Ygtǘ*u֍b# zLZ&{@6gD.҅u6%7c/RA))a9<c Ai;&Z;()yCx0̰k敉}KJ l=X/. !pWvQ'8ͱ} V_xϯ@oM,փTUO)dGKlJβ:ّ, aWIDBPMSI, Q PP69}$; Q=0q {sj/ 7K>G? ϖʼh=?JIL(0eO| 4Տ_9. !pS^f78ٱaع4 G{sS+g |BJBPV/ I!|sYB$:%چ+9)B  vLQpTpc*PĠ|xloQ*w<٦{I8J=95ځCIM%N£haw6vEl#F)y@1 |T?`A!.p aG:O йRT3Al]h6I]? & Ctq"~BJw 1(%%76NKI9a%jѩYf!N`wNMv%aPRFScӇgaЎ8Gh/ESA3x;g;i3],p* YU$OK3T5ޙSP$;^DU^U dVEOCR}LnX~ JQ# X쪬lNb*REs:UJ׫*0pvfÜ:M,"[HY:*itFR=<.pu Gv tyUmb h|9YT]~"-qL)D6L%2ל/Alm:thwDǡ۠D>+hFcpը`͔eyI8J=95ځCIM%N£ha#U~՚Q`I!@3LWؖ߀^5 _޵6LMeb>(UG!Ui'{҈k乾*N,'&4}fa8k^^ 5kG)&Mm7|@P%~V)@2qL(0$ L*z޽@6,@pיw{ 3}FC(bPJJnl|#'! $G.c.XC#*Z3YF]g`qRF]M#|:I{:w]Wn="MF]{xlS|vw/)&Mn7WP,@3 3 ͤ LWy'8],/}Pi+ "`!V$!8@?Sz=!"Wt 0TQ-1'3ŭ} ` >loe()t̝WR&O[N^O~7=4Qсߌw:LyO8G XN?RFB ற*P_&j3@NGdߗUɔnE{Y3jB`"&40 Lj .pza*A))q=vo<.\MkP]t'SLQ`y]3# x1%%|OBIIO*3G>ezrzcnzhpBBc@ğ[q:U8^7(p7 T/$ S ̮{ K{&ۤ8튙ZPb1^MuzⲼ ~V)@7a\Xf@(bPJJnl8+ctK[Z;^eYp lF8WWdViy),#%7]VY@Fi4At޲!ϨȾGl=L6ij,VfFnu2*` bhnpC~]?nƩO?2s׮g^˄ И*$O ν}뎅?yŘPĠ+G.X4%q㖔o%Ek#HJhj,q,@3 3$8pĂo SL .pg+O]ag8i8r\ <TS'|o]2΁{dfyܭ㝛Gǖź@ydLrx:L9 eN}$O@(bPJJnlXN-G.X)|PaΩ^nާ0$%o458}~\Y=(-}jbƂ)&QXf> г G艙OgN/UrhzᎧť[tu+,AWrSgGϿy|9,RvylLx=yFh;G"u:w!ME!֫BRRrcrjy`=w&N`wNMv%aPRFScӇgaF݂E TkbƂ)&QXf> wsuAȆ}k[w-8[gn̶>|Gl,f!^ <uxMt ЇwW#PHf@h׹cA4S=0q {sj/ 7K>G? Eto3jMLp0$ L/~oמ S^%@e44M=uax_޽ύϯ{؇OWZsO߈P7veSA#M,Ő8WEκQ,UbaZI˄Ɏ1Rs.AOn/YQ{E JIɍ ˩K8J=95ځCIM%N£ha󷑏o@/XY7  4S7K0=9K a꛻Q:g,phŋ d=ϭl=xLeP,,2. .Mvdl0̦4,[QK " *V|4A\- ud0ȉrfzΡ`m$; Q=0q {sj/ 7K>G? 0 4S7K#7=6-5#O?,=ymϊ8>GEN`>{MӐ7=7r~ɗ*$-e/t(7KI,7TuJ 5gWszd$PatH-l(#ةj 1(%%76,#p{,a>( 0~Dk^%%o458}~aP hnp}CS_}JO|@6LAMGe$@_{tۡ/jt-UHu:d`֥f%@_iP4Q"CmWA))a9<c Ai;&Z;()yCx0 jML<,@3u \ۥKBOO АM}{ *@6K4Ԝɬccy.t?jʖktL)D6L%2qF3iΗw'K1~@LD#֊n@(bPJJnlfLI]1aiga՚`:yXf~ П6m(+Ye=Ǧ!zU$@yV05rWT*VT*t:}}B p80˖UBȺ-%tg Ľ$oK(C ᎈSnp*tEmAc SXi;&Z;()yCx0 jML<,@3u \oO^~))< as4 :x`ZHH. 4m;S=0q {sj/ 7K>G? 0 4S7Km[{BٰїXl_g tFs;QEXA))a9<c Ai;&Z;()yCx0 jML<,@3u \h/?|Bן Up>BRRrcQG?ޱMY>+ q {sj/ 7K>G? 0 hnp=7p3X?3߰ű/?9>"aE JIɍRf>:: `PJ$G.cLJ)|PaΩ$JJhj,q,@3 H&.XN40p{8S63p|n̕0{,ahfPĠX,jΓRB]𙔡#p1&->( 0~Dk^%%o458}w axIjML<,@3u \hKo,|w썏M,/lӗC? c `%w(E YZ(M{g+.q {sj/ 7K>G`&&ߏQ>6.O$ 4S7!@g+ }ŘPĠ Vi8ފb$ey =(iN3cșS'2[loa<ؓN*N,'&4J3Fcq^zKE;$TZa.K6ij,n2Tl!( eG? L a],@' L*:.akم3޴mh1iA)76A|#'1{5) -X](]*0b(/ 5e9uBY̪Bۂ#|:I{:w]W)E`HOM5pQu/^ !F9,>K6ij,v0YeG`  o /'m̙m%\4j3,@' L6S П{|Թoݱp'7OS?c`!V$!Xꁛ!u`=wrJ;\ݖNv7Yp`N6UOK'񃇤פp̣L0VWը9a4*4=ܸQ!tg!B+IO?VHR`.[iHyV5 pWhL!L"$06, n+fNz&@x.Aη8#I<1n-U`_c9ӹAhn?w.a֫BRol0+ctK[Z;^eYp 0u'ȼYT<},#і)c -w*RRD-O|i+N0  M7tvc \,xsoM `z|@B  kyݬYnƒۮ.J\k2]^wNzQHNxV [+Fۂr$08{>'v83C"Qj T1: [⊐+{kh+FzXpy8s _'t;O-hnpcڧ@63/Z9>5xs+[ST)>O1ђ2lyF-Nv>K,(tXfsP+ac"'?i (zVN5lɍ [əYQ/M1s5J9Ќ P-x‡77,S0SUoV=88W)"L4Jzj:Tޞu5vk:~yǏ1Z%@ "ϨKFX!<#@lrrf񚣲IS̤0LWΜ9≌,d*"LNIc1މ.9UWj |xy3DiHY{*|LXpyjLjW%c>%hhnp"@޽{qq=\0ޣqSӧh!}߽ NgLCٺ5lKfWRZvAUDs(Pl{]E J RG.X)|PaΩ^nާNk#HJhj,qO ;^& ҈k7bJxS qԩ <9q;~D , 0?c;ӱt8s5Lk^X@CLXpy҈_iA&@[3 ,@' LWE>p3<4垀 vs(Pʫ@mo]T(@K͙̺<6BN T] e5:b" Zj&Xk@ޅKF[c#8tBRol0=0q {sj/ 7K>GCL ȶ Jpob~Iߔ.&q\)h#DpaicU:Sԁ&&-Xf*4pݻwo#( 0~Dk^%%o458}И:qwS}w\>v3<4s(aUpIJ@FwE8qh܌N"4ư3kn4V%Аh,J5o@3,@3u \Ezrr}N~Q f3rs %BBvIiOE J үnc Ai;&Z;()yCx7'@+ sE}+DfeRDP&=8tN-hLO ,@44S7U'''+~caaرc+E.@6,@p9f^-~AwBRol+G.X)|PaΩ$JJhj,qa!ٰv='_|-2 \vB3u! 0]8qݻD!Xa(BRvš7po3zgBjU 4$jE ' >4x߭F 4S7UaGgggWVV&@WїX,^'>V E J C c Ai;&Z;()yCxFD]M19nhxc[?ףqRP"@}p,`:yXf*m۪ @(bPJMzb%LhK䍦46 &Ysߐ{(ATkba\* ˨% pA)76AfLI]1ai}aرcx&h|%\4 4S7] ],Ƥ"`KbLJ=95ځCIM%N£0'm̙mZ,@' LCCA-D艉 sW  8r1iA)76A_,<`=w&N`wNMv%aPRFScӇ aHw= 4S7PPFp at! ]K.ٿxmFkXI E J b=0q {sj/ 7K>G`h 0LTkba\oh(后B=p۷Xq|XI E J bF}h6LYQ#p1&>( 0~Dk^%%o458}!W/8OKheTIS!׃{`:yXf8 j9+@?*tS]~/=uH7o_%sX,ᱻGFncesزXh";Fq7wі!3f9 eN}E J b!u倞,_~I+%ߜ 1)Ai;&Z;()yCx ç0x\yťxa>Q&]w=J hnpӿCW^Y^. fjO|L~7/\oq`1ћG:xc"= bs$"[s7ݴ!֫BRolXXȗ;6U_ieXf N`wNMv%aPRFScӇ.S?/}i&8za_w= 4S7PP!j]p[w-8[gn̶>|Gl,f!^ IPD.r>cTF2rDDm2wE@(bPJM %4!ނ-$f0H|CG.cLZ)|PaΩ$JJhj,q /s4#M;\yf,Q5qd;##oY2*ƹƴOLCCؐ0&XNN:>ol;:$F|XU!qV1luX*Hô K"]Xg< ^\}8"+cB~ddV#@kdV 9$1Y^c 6ߺJˌ А$P‡`OqE_Bl=O@^?N>tm맖| 9H9Iv:T7r(H1:@Y&NMzؐ82XNNZ ֌\vH2Ѥ: m3gO_8rŋ}^wvߚX繕 Rw!ԥɎdlJβ:ّ, a7&Z 9YNZV=\KDZw=d !^R#p1Jm,תe,<֠,lE!)պS]F o AfZqI{:w]W)E`HOM5p];֖Ԯ9A5׈:g)&Mn&?Bl=oJMn'; Yt f??,=Ňm O=:6, yM85zm)jaH+01+hlXΥbCw1t .p74ѫ-%=]YGvl>vk7MCz{Rf=%=mXvL҉G g- (1s/P=YqY^G0t,>}~~~qq~-t^{7D  _m&~߀a I.K1FbA bt2CF64z3dE`p ec U6bC,@' LCCA-hOp*#7Ǘw-i S+xqEJ@iQHUZ(2O7J) GlY%ĨKRO { #pUU_>!}|X'PĠ /L=Ւ*jZN.lHQ_Aµ)tƢc Ao #A8MKݜV0]J3a4j*4=XW̼BxPSTϲ4Nꤝ8kf|O洔nƒnh~3Wi6ҜM G/^տRw3S(:j3{#x"F ֨\TTeEa[L YSRHUfbƚF3I7Kr ף!*XNNZ}׭Q !@,6^ qUM[/8"`ܕ1{4,D#ҮB*rTt1ReJ[^O[nqE##/gVPJ /tiLn  M7tvc \,xsoM `z#,9p]2$Yqݯ:)&M%]\&d188(H~<맖6k޾7xxɩx3.dcc>(%Ycł#p1QU{aK 93+1 )pC9g5J9Ќ P-x‡77,S09UaΕfi43nN:p:Հ>7rݚec_cVI7k®3*2Ob>5[RMծQ5O8̾wI6eňYx |c{ 8k6 ou[Ͼug.\|.<qk6Ϝ{" :Dzڧ߅:`H6KNGU +0fC&=v`45+ xV@ņ]],@' LCCA-U  ],/}Pi+ "`K4S=|} )yCxG0WN^A‚3{`aVOE]<w= 4S7PPˡ7;C$@3 A)76A_,<`=w&N`wNM:p>ļ )yCx]忪Ntۅ>3 Ӎ7iy*6z𷚘`:yXf8 j9*@_h SE J b=0q {sj/ 7K>G 0}p,@' LCCA-ukF|hfPĠ /Lc Ai;&Z;()yCx0Lw= 4S7PPˡW:o@3 A)76A_,<`=w&N`wNMv%aPRFScӇo=11!n@6,0؍V!׃jML<,@3u z26,@3"`K8J=95ځCIM%N£%4l7@6,0؍V!׃jML<,@3u z/@7aBRolX0yzb%LhK䍦S/M/JW͔hw=( 4S7PPˡ7;,@3"`K8J=95ځCIM%N£/nm8-TN{r ȷXf E J Q/F xcz=$ChK䍦߶Oph˿;?O?a*]K ,TPNTl!*WYWK_d˯PVɠn J9d tf.,@,JG苗.[~g G_LV̓wὁePn$L54Y|)?Ί3yJ]_6;Pm{AeXBE]<E 'ka\Xf@(bPJM+y8\%ZsИ4,1iAi;&Z;()yCxן\U%6n&.`)TcQ觺 S(2WiH8_tB". _ *.yn vly:F֣>QXBE]<E ' 51t .p `kBfPĠ V+My -di1āeyI8J=95ځCIM%N£4ٿ|}@%=FD۾>{XN+seCܤ?ʁO_EFj)Ο m ,3?91%4t~耞{4}e,SQ.Oņ`QIĘ`:yXf:Пa. 1(%&BֺLC2{+hAcz<<4B]",/|$g^C~t$x NFrKh"Jӫ4jm;(Q{CA5 ஡Fn+Cf/PxSΣ.0mf`7Zņ`QIqL<,@3u \tRXf E J b@Afꌏw2' qrtq"\iFa4"=5/Gaer޷% !F9,>K6ij,v0YeGK{+ 54c<r=FwfEHɶVEN 7˝W\uiHB&-|8f-h&5w&_h0̂FB 1 [`.C:$B'9+BFy|C7+uV'ۤ+˄R6ך"f]Ӣe)/G{hLyy7tu]aL;V!Xpy,@' LWؖ 7c<lɍ [IɕM53I=z`@3ײO&60KͪJ3E4I7FIOM8j@.|+nM1/oct1F5aW'1Ți)&Mj̨luf_ϻ$K*GK>t0㥷iEy)߬{ӂE[';^GW=ek+o~c+,JWw~:g┦oګb"sYj®%[SjP_/y}o ,J |"8<c<c Ai;&zyRbLFX!<(@_?/}uU}(3DX8py*6.O&&g?w!=X+@Op0 ".G.X)|PaΩ$JJhj,q:y{޻WyUE3u yc'-UK~1dU_Z<R rʴŨU)gy}P7~0VdNE]<E ' '1'@?X/. !pS^f2#LJ@(bPJMzb%LhK䍦*7'?߽֩%g ,WHx%D '\Cq *َ ίz>yCSיhC. JHC˓՚?oNc~Y\BWEf2 1(%&py`=w&N`wNMv%aPRFScӇo'8=k~n?aj9M^ H#O 8b.)Kes_J!q)L{ߘ1tXpyҠZ'~κC΃h>*?D \=]~tÆhfPĠ K8J=95ځCIM%N£u߀t?_sp8?9rbqg+x}z,bۍbI!y*R>(rvAߘ#sPtE]<E ' 51Q @3i0wcah43@(bPJMzb%LhK䍦?B桝Jv^rU-R#`t={⬂攢j,ʪ $gU|`<%߸5A1|>( bC(A$&XN743\@(bPJMzb%LhK䍦Bu_9?EPoI1pxR8+.4ԲEC7dPHP__j)Ο m c{`:,JGK{+ ԂpGfX؍V!XpyҠZ,@' LWn8$! pA)76A8=0q {sj/ 7K>GKha,J<6aˤN5qeMX]ǘdS4SxI?X!<["@OLL  0 zvUl%\4 hnpY pA)76Ar@NQ[nq {sj/ 7K>G{!ȆY=*6(&*XNh)"X'?Ux$GhK䍦SG&=u1i3%7Zņ`QIjML<,@3u \4!3@(bPJM+<JP`OȪ1āeyI8J=95ځCIM%N£ۗg~ߞ<ZS~xShk}'vy\*7EZWE)VFy㖁ăEE]<E ' nba\׭5[}hfPĠ V+UY2 hK#p1X9-q?x13:j2:Kw:ocQ.iA{~>⤰8Fҫ4jm@G k?FvT`P /kh,ۤPAهK(-7WW?Uvx'?x-RVϕh] lM)yAΔ&Lpy*6.O\ca\ˤXf E J b@ɜ:"z \iFWS娺9A5׈:g)&Mn&?Bl=o} 'Q??K%G>5bj߿oJ&%g/J牀]J4))2m uob ;8륢.\ ˓w1t .pu hSo@3C"XH#IDH}1U`=wrJCFp [b0 ^v.kmB«(إp 5a ب ꮪv.L04*FWI7*:0Ng\))IL\P# < ,-Z}SXUhr( C?tU8-ۤxR :F-ܱNj &R0!a N/}2:?aHzY;I=Sg=g.sU-ko׺-N태")oitnKYz޿:[1Rf=%=mXvL҉G g- (1s/P=YqY^G3wbvZݚec_ w?h&<"$Y8-ۤXXMydiS3Cų2o |qy(Rt2+XCWgN+вeCܢ?ʁO_EFj)ΟE+%mJJ?B-ޟ7d _3 bC(2&XNn4z 1(%&py`=w)< 0~D^дϒ$%o458}v yTŘ\wrd؍V!XpyҠZ,@' L7@ =c<c Ai;&zyRbLFX!<["@ݻP]lXvߌn+V`e`7Zņ`QI 4S7$@7$PĠ K8J=95ځCIM%N£%4ܙE ' *'1t .p|: pA)76A8=0q {sj/ 7K>G? ô XpyҠZ,@' LWm#^Op0 ".G.X)|PaΩ$JJhj,q-'&& ȆY=*6.OTkba\vj1:4 pA)76A8=0q {sj/ 7K>G{!ȆY=*6($*XN>:/343\@(bPJMzb%LhK䍦S'^~*]]c6S~Ul%\4JB4}p<=XNZB:﹍h& 1(%&py`=w&N`wNMv%aPRFScӇo}+x<ZSK{KL94 Nnށ'3ǵoi O2>^^ G9UOObb`Ȏ_BOJĩIb(xmTԅS!Xpy()e]4at .p ,@3A)76AfLI]1aio=~i5Wٻg<%~}7ϼBn~}$.\Kՠ(_-#@< όo֞|(ٷ py*6.O) w}k>2yt .p5Јekְ$".ڂS`wNMv%aPRFScӇo}??_=,9r lq{{{S_4)o^^mhS,#RdBfQ ƓKP&sA: bC(ʀyϭט7oF,@' LW1߂,@3".G.X)|PaΩ$JJhj,q--| "iujI,ރv7 Ď=Sg=sߧ>οC Fh HgJ**hLτ05bL\PV*,J( 0~Dk^%%o458}V oM= *K\.i%Z`Y?U-^Ub8d ’I_|R0iO\q]\b/Oj*6.OTk  .pC *&/JM?8:vmx3LX]ǘdS4SxI?X!< x?}׾o_rUT惴,Vk b,*(?^%_B<2]1dzTl%\4 1zӣZu~{/5,@' L4ÔBRol8,e8e(Qr& G.cLJ)|PaΩ$JJhj,qm/]oOp^r䪼w{w+lQ3ۨ$gU|P:+y%ZxFڱo1\PN*,J( 0~Dk^%%o458}£w+yUv73 z{KiS4'ufQVe 9"ӐpA/X%ƓjjlKpy*6.OTko7- <,@3u  SEC cf Bl³)LX]ǘS4Sz )yCxPxc3Pj EO,\7sW9uVeˆnߵ?$("#IZQ6u<ƓrN!KTԅS!Xpy/&XNh)"X~V%Lqh7gz<܃d' AsLD+quNqDM~Rs0瀌Ya<Y_']p8yr4צ ktEz^ 5kG)&Mm7|@P%v yT F,J "g_m 0` NvEНy(e򄱥wCkx3.Δ#q!lѩZ ؑB  5[e6tD6(]U-L6ij,^D e?-tj &R0!a -a (U2&XN엞y#O¶7N}y43\@(bPJM7ɮݓ;ٴ{d5YFaf\T֩+pf.NTcPǽUFӥ%u6, 5J3 cYFН 9P9 $?Ñ8NښU8cwbF}Rf=%=mXvL҉G g- (1s/P=YqY^G? ô Xpy҈92XN_8'O̚M?2ā#bu[Yf E)#pW薶v(+U9&bR\簋 \!^ J5#. h&u,#ܖ죴)8R&OGL' 1CS9J\*mt2Sb]O4 k6+`mXeSl:m%'ex=11!n@6,0`MZ!Xpy,@' L/ NY~mf~pԟ>1 .|{7L2>k 43\@( X]jIjQeG)iTqWVVS3Z]rM*򱄏`HP}J@sV]4SPOr|驪kJ֘W`thpVgq^ q\fOɔnƒnh~3Wi6ҜM C$@&k,aanҊ 94( hnpэS<Dġlx_ b^>~uRQ.Oņ`QI 4S7QV<~`k6MS>G7N7N?y`~k7 %*&5=0q {sj/ 7K>G ЧVV_x'?TFg ,9ן ,O=tקގ/SdՒ}FŖjLd d^s3py*6.OTkba\.@s G{v>uz#_ғ3_鱙?=r *&8X?c Ai;&Z;()yCx}?_?ck3K6yr.GHg2. @;ty`QIjML<,@3u \ՙo<=S}fϫ G:'O||Ԃ43\@(bPJMzb%LhK䍦?غ?aio@<%1-](RO.OTkba\{_gZ??6>,@3".G.X)|PaΩ$JJhj,q(@_tg GrtWսLղ~Yk.\ ˓՚`:yXfhŁ#OYl`. 1(%&py`=w&N`wNMv%aPRFScӇ?B +yUn>Y `HaZd@o@%o@P3py*6.OTkba\#@43\@(bPJMzb%LhK䍦?4|#w^)OgOBKaZ~LvWC1P;FTԖ,,n9dpy*6.OTkba\Xf@(bPJM(Sp{aaZ/JSL .p,@3Ly 1(%&FF;6`CM,3.i q {sj/ 7K>G O\G݀l|1c`7iņE w~1(,@3u  SE J jښ$Dzr<ƤDhK䍦?D4lTd3EAI+6/JR 'Da\Xf@(bPJM+y8\huU#p1&->( 0~Dk^%%o458}U}NMym7)MZ!QB&&bhnpcaA)76AVjxYRƬbY]ǘS4SxI?X!</]||4Wz{\⃏s/vTԅ%嫨~bIZrO c `9 ԝ5}: `=wYS.@xr;`*:JnVy |x0ns.(MLQצk?F 2VRMۮ $}Bzџ{G{iXr057|}|:G FrE]Q!Q8&bhnp"@޽{qq43\@(bPJM+.IC^Mq}#p1Jm,ZYfW)eT%k` l`qcu]'.G 3AdNԹd= sJ?3+及 FSL .pU<3J^cǎ c`!V$!8mP XSFoKts, r^vn`M ,sƖPןkoSDt{U@w1%:1.\ؐ(OL14S7U޽ӞXfE J 0ٕ{r{(3´zlZ8wuVon+']/h(j]켭vqz*B]j> <$&=.$^} cpuXfABÍBw"tc,沕Wi(K^hUbwpTT)A`Ò@I6ij,Nb&#wL깗FS],/£ϽOɳd3E/Kx 88#J{ ,@+%4DSL .p43,@(bPJMz#vrs+7zYp*7d[.q%1[.KV?%?0 <2y8j]v,h4ThzqB8G~* +2 tV#QI`jewMAf`A v:)&M%.X6gʦVQr(]G0~cn+>t_mwm /tdPZ||k_ 'Da\Xf@(bPJMzlTKzK%ZXo]9X|W]j 0ӄiх4S` M713.#T9UA,M#:i'+BF_`9-ۤߌUM4grG0 З.]}mg|Y}[/+(@7-k_QOL14S70PĠ ܕ1{4,DCUSTI:"UʐWv-‡p/y9h&5w&_h0̂FB 1 [`.C:$B'9+BFy|C7+uV'ۤ+˄R6ך"f]Ӣe)/Gc(yKNd!Y?Q(fOih>_ɵuGņE ؀~bIh)".G.cr–Ar+%93'P`(P9]jaM9'kq fw {pp4SDNt#ht Ёө)nEcCy٘藷1|U +̓d㴔nbkfT`S6:]Mxf Hh`/t^r$'!"#PÃ?=^o@ӫW8tq>_=QQ.Tl_)&QXf8<c<c ӔR{sjǁ[/hgI7K>G yT׶ގݤ%Tkb)&QXf8<c<c Ai;&zyRbLFX!G |}9E ՚~bIh)".G.X)|PaΩ$JJhj,qUs 01.OTkba\Xf@(bPJMzb%LhK䍦?Dw@6,0`MZ!XpyҠZ,@' L4ÔBRolp#p{,a>( 0~Dk^%%o458}!mۆ5ٰ0e`7iņ`QTkba\Xf@(bPJMzb%LhK䍦?\4<8z9m1 %7iņ`QIjML<,@3u  SE J \X]채S4SxI?X!</^OW oi2uzoGLJW0)o z-SQ.Oņ`QIjML<,@3u  SE J 6cJb1 0LG;_~{i2p>m><ӽ&;[?k0L4@d  ъpy*6.OTkba\Xf@(bPJM-({,a`1+ 0~Dk^%%o458}!/]„z3ʒ#9w3oDɾ_Jl5+,JG Чޗ}r=j@Xr?B=cZIVY`AO~w>eaDpy*6.OTkba\Xf@(bPJMzb%LhK䍦?tsoGx˕>qKN *g!",c5h-47 }B=/2hE^6XpyҠZ,@' L4ÔBRol|xloѱh;Iq4& G.cL2)|PaΩ$JJhj,q ~pl3ހ}WAY1{ټM0`Z %\4 hnpcaA)76Ar@NL'6Hа1)Ai;&Z;()yCx}ҥo_o HN9߀hܴ $/,JG//(yUw3px/jJA&j(UNUJ0$ aE]<E 'ka\Xf@(bPJM+<&eyY'"%hE^`=wYc"N`wNM hC60䍦?4ί~'@2Ea> N'jq|w֌?{w7YQ}ߗ}EQQ@@=MT\XO IY .1jHDPD4"'2,}~:Owu^3,uNuuחto'80YE|5K̅-"tx*/'}Vlө;rpk~ޮP]Kk{~{\QxR"˚ȟ{}_wie>og[׸S}˒K=|͞nwU_;М]|ڽP]Y.2dZ9\Y{9Ϲ}霿>?W]}߶v監|/Zz^s~';G"=wh{JJ;U7;/=i7jȞ\ï/'.A ׼z:az؞?f4keEݤmCUÛ7Bگ w\E/7٤ƃ`Y=+i1i.syVyke+,WTeW{,#7-Fވz.ECUih)qOw4e" (ޝuJy[JO*i@)gLWw/)SS"_7OVvs3^& ^tHB黾tWl{n+Sn 6[ =G '6Q2{fJE-/D-4WjkTf[7uI%_ ݞeKn{)k.}Rpdh&VX7?Th jOܶ6Y??51j4[n2sikzryz^m^KH% :WrG}(,w^zRee+uhH']Q;Nljˀ=ɛ)3WfY2IsZ̷4V)HŦ彶u;S]Rpb5VhG#JzjZF=_w5LhѦ5-͍^0T]P{-\#m\n)Z`Z}GiUEK/I=zP䌪SG(W!HX J:<t6^azX#b҅e8\tSZ&ށMtS=oU(d<檷X)Yr!] ۶i5>~xm];gVdU6kAKjVr)?KuzK' ^i.[W˽[_0\#F~ S^er5Uݪn(}jW8ZzSW¶^Bӭ+LlBhiﰯxlzz{9N Ufgn"zj 9k<)l>kOyJhVue2ҨIƫwPjqmayyv_y'0kdP` w}eJh/x7bt#IWNi(:p:z?hNo Wdɱ7-ke5vN) /i/|Hm:j5pw=׈fQ^rKfW}n%T=4Lіk7SЌȼTo]q;ypWʣ}{j QhJ+viB^ue2WXuc?݊ڡރfy'0kdP᩠cdN#{g#bƅe˞St#IWNi(:p:zLTSbJ[D09p1!n2k8oKSajGqQ5qm%nEދ]aILz/[퉻Py4׬;RV3Oqe`ߞ{ë&cRV>biK~ֽte2һDC=#'/䭟AIOnғt hp@:)pbEN'4WgBJOA5jD,rxɔ;_ KRmёYS]OUjFi9pϤw4F6;5]-?V[FYV²Zojo[w*^UbGNמ=ha̳ru?lϹt]zLt+UPWUB^/of J:<d| t@m:@+j‰M8G\U' oOTVU\e~FQ9DK1g[?4Y#OMkrByhp@:)pbEN'4-ay ^aӒ}h_ZcR%6~hF% 6tSZ&JIsby'0kdP᩠iMN;mH']Q;Nl0ź ^aӒ}h_ZcR%6~hF% 6tSZ&N#i.Z >|%3>.ƤKm(of J:<4 t@m:@+j‰M8G\X|&x7NKf'}|]jI=

+PC2^5KlqdRϥY*)FR#of J:<t4֟{ѩAyhp@:)pbUf_MO5jL#iZƓ#3n3Uil^=n+rWcbu6gD#OZh~aaj$z=n4rkӌfջҨ=qlsq:5>D/fK/I=zr}~T"3jG*s%k޽Wfq%>-:zj4{żkiȵi9U%Vl3RUQU(whB𪩍Uf*Ni4o:}T6_.L&\]6;Z+WlӖʞE%n&of J:<t/-9[.񅇝&>F@m:@+j‰MT{朼6fjͩawx$l)i[*eonRmzs*tUqhKC$lٖrݪnH'v#R&w6!snׁQ5ڞ朦 pB𪑳ӛASdEw/@+"GK/I=FN7^kU2]W{o Sn[?4Y#O3 Y߀<hM8h tEV8HgŠNnĺvlpN֘#'h-%͎Z@Z0-h@>qhfWbOUOF0R4Z6\TMwTůYdUS'Zi4OjM>dR%ZޱxkCëO `ȠSAq"yhp@:)pbEN'4WjbQLiR;.&ĵ\DK1g[?4Y#OMkrByhp@:)pbEN'4-ay ^aӒ}h_ZcR%6~hF% 6tSZ&N#i.Z >|%3>.ƤKm(of J:<4 t@m:@+j‰M8G\X|&x7NKf'}|]jI=

|%3>.ƤKm(of J:<t#Ft#IWNiFas#O6eAl ZWM#iFK >|%3>.ƤKm(of J:<\X#Ft#IWNiZ_jf͍BGMYHe<檵%7+̿qZ2O<RkLنO `ȠS5Y!<hM8h tEV8u`]u )-4luܺ{d<檵%7+̿qZ2O<RkLنO `ȠSAg9!<hM8h tEV8u`5(ٮ7R&6_j-v ߳\EyjHQ"-5oٸKc6l Qm/yVU3 *2BcP{}zRD;ë?aM֥ɤK^UTuS+G tx*h#Ft#IWNiZ62 =PEu۳d<檵oiYLKZYe9;C}$;]^] h~DCOû\|HR`n27bh&I_ UuԞi9 ۸n=Gbj9ͺ2s+75Qu[?4Y#O6tSZ&ށMtS=oT@'mv5:?-V1qJVn`+\h۶99NdN ڼ<'^ f-hI-JR.gqn}^\|)գ+%T=ݚb^yȵU PrSycW&](NZ; GmëoR}(B7/UFdR%QKZ0:9m)X]fO `ȠSAGɜ@w4ڦ4NvJ+D5;7+i`UܜvG\+bfŮR+5٦7-G4#W7VXݚZ!5ڐ)VuCy}W*-$ZBӭ+LlBhbﰯx(kZ-O5&cx՘(L4*[Ԭ,sIhfQJM-TKzO(M (7zz {Ptë&B) ZRӿjKץɤKzM*Ru Uz{[ź9+4kޞO `ȠSA@w4ڦ4NvJ+Dсx$Uo1;Qu¹p-JukUUaY;p;{{0g#X䩅ul 􂤸){_evg4OJb2PUw[-^)Z,ygwJƢWM)z:UK~WUm;֥ɤKTD~q߭jDK1g[?4Y#OMkrByhp@:)pbEN'4-ay ^aӒ}h_ZcR%6~hF% 6tSZ&N#i.Z >|%3>.ƤKm(of J:<4 t@m:@+j‰M8G\X|&x7NKf'}|]jI=

|%3>.ƤKm(of J:<tF#Ft#IWNiZvQ˝zAtً׊ͭw--n@ȻzqwlbyPk؍H6l4TD~ت^f4üBjzU0&dRϥY*)FR#of J:<t4 t@m:@+j‰MTY~fYlHbE2?\7U,Tg}tMʊ*{ ԺF mL O3I4͢jM[ιWuczt)ƜsZڬK/I=zr^UH=@52(Tд&'НGG '6Qly,Swx$UoS5Et]Tҭ+ns-<{mzTT=(O +fB-O*̕؟{:̗O\=Hh7&FM\W˽VZ_0\WW(L) RMZPv@R6W@H Q67?ov+~_8U+֥ɤKУe#2y6;m)X]fO `ȠSAGɜ@w4ڦ4NvJ+D5;7+z &4WY m림 hrc_spLN!π}Ԃif[mvAj4{(eVifn^argBM$}@F\[^Ejq1ë4E<}}<)~W[֥ɤK^s'޵CŽb}孟AI3Cyhp@:)pbEN'4Wm9!rk Wdɱ7-nj76y2_+/.n#쥁4\?0`Z0~*)5A*fn^ahK5)hFd^*2ީҒG]TЪ1jM-4]ӿZSO/j2s֫wnzPAj@52(T12'НGG '6Qtt2Isn1&Ŕ(jf͹ZH[R\7N8DfQiU]F.Ez)Z,y[{W(c)_5UT-_U4Z^&z.z;jSu~}0vxu@52(TЁ2'НGG '6Qtt2Isb6%0iɐO|Nَե֘sɳ 孟AI59!<hM8h tEV8H<0iɰO>U~ sfcDu5&\lCy'0kdP᩠jrByhp@:)pbEN'4-ay ^aӒ}h_ZcR%6~hF% 6tSZ&N#i.Z >|%3>.ƤKm(of J:<4 t@m:@+j‰M8G\X|&x7NKf'}|]jI=

DK1g[?4Y#OMkr+nO,ӻ@dѡ!F8h tEV8H<0i>DK1g[?4Y#OMkrBe$ 1:@+j‰M8G\X|&x7NKf'}|]jI=

|%3>.ƤKm(of J:<t>sȠez3VͲyKp@:)pb6lnʦ,ȘЕŎ(-.3M oODz.y@52(TYM^;/=I׀vG '6Ql˚%f~Wd<檵%7+̿qZ2O<RkLنO `ȠSAӚ@w4ڦ4NvJ+D:˒י4:80i̊j-n3M oَե֘sɳ 孟AIsByhp@:)pbU.jv]o!A!iL!4W^$̋}s~=;mY-j{ >^P󚋭Aߗ>4h&يzciR{6wHmu^5wue2Ҭ7N1zy'0kdP?g?Ch#Ft#IWNiZ62 =P2(0`d<檵oi̡ì?\7U,#kZ&:(tk螶ʞŮ9VA5j|re U#IQ6uk47bhfx]IԣzԞi9ZܸnQvj~ݏR^&z.z{dF)R#of J:<Y. t@m:@+j‰MT@zj/3A璔d<檷X)#ݴJ㺵rE996ZFޡ"4*qIc+Ha\A~KʥؿNa}QW=5b^yZ4+ܔ]ϿbtwȍUc"jfUS7?ov+~_8U+-٥ɤKУ/.^G津cQv[?4Y#O%sByhp@:)pbެ,2-rZx$l}sjE)%ë;EUǞR ;8zIc+LAuARg:H{Uw٭IO\ GǕsJG]h ;ZZHG@^{Fu]h?1cxضPMa )~W[֥ɤK^s'޵CŽb}孟AI'~C0G '6Qtt2Isl1J۟іb]-gvlpN֘Z"MfKl=S }JR^ kmkG-eіkApM)5%^IF]h s]CfDu+녍źVW8!cxgD Min/TӋZ.L&\nyw[^;{9,of J:<-k/7]|-;Mg#<hM9h tEV8HwD51(ԥx`Ei_CrDqK%FYTM]:{5DO$,AJz񨫞'ByEDvMv0WMiX Tl׿/dRϥw[nw+k{FN^[?4Y#O}+o:s_v٩sMm^z>#Ft#IWNi(:p:z?{GTE4f͟uDjm_'~x)qWF]xuC,l3-Qt'?,e%~w&h F8B)ӓru?lϹt]zLt+UPWUB^/of J:<-g?S@7Z;maH']Q;Nld<檷:\px{znTUiYnhyݳoUY[-ȣoj<šv~;3X+ȣzOܿբx<~׊=#;²{x}_5(*tߐvZK/I=Z5jE?[zyBU;:F txZ'8=ЭY/z6@m:@+j‰M8G\XM*pI7+̿qZ2_EG2#K1g[?4Y#OMk"N\fKdn&Ihp@:)pbEN'4-ay ^aӒax}JflLjRkLنO `Ƞ"?Ѳ|YOD0G '6Qtt2Isbg8-'u5&\lCy'0kdPi߀.7_8@dhM9h tEV8H<0i>DK1g[?4Y#OMkY/Y}̿l7g4ڦ4NvJ+Dсx$EuXoWdfx"ץ֘sɳ 孟AI?qO?BoKAK6tSZ&N#i.Z >|%3>.ƤKm(of J:< гmaH']Q;Nld<:,7+̿qZ2O<RkLنO `ȠSAӚ Uhp@:)pbEN'4-ay ^aӒ}h_ZcR%6~hF%zsz ]F.6tSZ&JIsby'0kdPiџఉgd}8߀^t@m:@+j‰M8b&Xr5+̿qZ2O<RkLنO `ȠSAӚ& S֯?Qxɹ|#CG '6Qtt2Isbg8-'u5&\lCy'0kdP᩠iMܳoYOp h4ڦ4NvJ+Dсx$EuXoWdfx"ץ֘sɳ 孟AI59!<hM8h tEV8 ;usB[,ck~U+ԲH+l1tFoWdfx"ץ֘sɳ 孟AI'8 FmH']Q;Nlʍ<ٔf;N#iFK >|%3>.ƤKm(of J:<\Xhot@m:@+j‰MT/?YsCN3M oODz.y@52(TдsG !Ft#IWNiZv_f^gmhl>_j-n3M oODz.y@52(T_ScEyhp@:)pbU.jvy]oD˱ G\bkŪ8  WWG0K5W<n/v# *2h3z՞mmF>+$ک^5 3o.L&\ڮ/b$]!vUs%k޽WfR4Qr#D_”/jݤ Ik(mcx TeS~fSh]zL=zI9]6;Z+WlӖʞE%n&o]w̽@tx*(O\B 4ڦ4NvJ+D5;7+@D9S8-VOs7Y)ٔehR?AcvS "ϩsjIK V-UGY W)ծp0J~7Ptk ;ڵm";+^G5<ں'*V0S^5) c)Oiݽ؊=.L&\;xUw]--,O;Ou=+of J:<̀9lsϾ81Jhp@:)pbEN'4WNnuj-̗vlpNV{J>qn<<}ҟRGԂpiFRkD3Uj/͢%T=4Nіk"SЌȼT6eS-]%{ UcxD"ZhJ+viB^ue2WXuc?݊ڡރfy'0kdP᩠cdGo߰oqhM8h tEV8HwD51ŨM EL4 Xp]vDB;|llkL{{Fs#f+v~}obi՞ wLy-hը:RO{/b6EPʶ(VZue2һDC=#'//?S VomL k2(Tз@w4ڦ4NvJ+-IDATDсx$ճ٫hLYqw9 E9q.ӯ]*w^=0h/uJ\(2g^l̢FYP-?zh>4ʢ6aBpk7,Nb$A=c hS ,hIO*5s.]^&z.=5Jս.T%n<Ьy{W[u]}z'{Gya~M͟ dM% 2>6tSZ&N#izى΅kgUf2),W-,g#}g 7jmM,~*үj'{F3*.#Zh UuOܿբx轺/kõrY JƢWM)z:UK~WUm;֥ɤKTD~q߭j4:ef;FTZcR%6~hF% 6tSZ&N#i.Z >|%>V-Ιَե֘sɳ 孟AI~ t@m:@+j‰M8G\X|&x7NKf'}|]jI=|%3>.ƤKm(o7?G?Q {dP᩠iMN;mH']Q;Nld<:,7+̿qZ2O<RkLن  c?dP᩠iMN;mH']Q;Nld<:,7+̿qZ2O<RkLن֯_o@*tx*hZ#Ft#IWNi(:p:h3M oODz.y52(Tд&'НGG '6Qtt2Isbg8-'u5&\lCy'0kdP᩠iMNrqg]wcvۜ|fZ0n;m3}X𗰔z-6ځ=yW._EUO=`S֮|J-U+V>'֛֢Z|c~-(?:@+j‰M%/3$)O `ȠSAӚd@~AS/pk^Gie^Nwv;+;z NjŊ~enuølfȲvG '6Qttn Jub]0i>DK1g[?4Y#OMkrg*ytR<˗7.`իtX- @orecW6-x5m,5.zs x O H']Q;Nl({Gya~TAI593C79~sոV5.`m.>ԓp؞c _r 8}uX<mcq^7.324NvJ+`$d +<L/3@wɛtr(0 pvjF&n E/ea#Fg˲媱~ Q,nnFm,p։Ǽ.u#@O|5N6l7k0 =eZvY!Om\vm"ݸci6}<k/:]Ŏ0ouCp@:qnI`:@߬C(@ CxqG,g붱xz}ʢȽ? nʠvh.nvخQ, ?,-#p˲[Ebt#@o'> ]+ȜV`:@oyI?4@=F%˘|Q,mnF~xaQ,ҡm,r3mcco\,m,EřGܨ]4z<|?sAA洺ӉxwsyOu!`LAnK66a @XQ,b8/!r趱hT6e9j=t[p@:Yǖ`ƛ{Cwv}\}C(@ Ѓjd^nmkm\ eJ? n_emcq'7j Ѻ}8I~znn_܋p@:cdUh%x0]d#F5ެw-d0 @yF"e9˟}.g <:>ݢ۷v4vnn߾Ѳ¯-W?uE~ZJ74z{ʺ[i{Ŝ_,*nU~ny~{J^pa~_/J8h xDG?Q]dF #4:fx7/>!`LDKߧVZܣkqdݭꈽvk]/z$neh)\iqW6kwȯ?붱\[lWg!n=o(t!#Ȝ6eOȓ`7kG?4@kE%w~Yc\v˪+Mneh)_[/9Yw+v˚mcjm,g4ȽwmcsRgEG #>s\ʞ';NK|}C(@ )~i^nk?wskc pSey)OmE /:06w_>,)ѵvnGnvnGOHG=2 M0>tZ~hSzQ[ZȼdmVǮ~nS7yk&˽Oڰlگ-<ԵvD#%je'fIï-O;p_fI㗞_,<(ݖ@8h 4@LE52/Ya;fIï-O~xAH]/|_,gQ}ZH kuO?^YRk8x]e Rk-n+%#rEǗu[!,b ϖp@:h@ V/yn+H`Ջ|Z%#E’A _nZ 6_ү-+W,)ԵQ[o vY^#ւ7|j%)׵Q{߿Ey#W3YWݖL8h 4@L>yF%nD G"Dp$XnD +BI-+7,\Fͯ-[^;n=RkW햧쿏nK4 stKWm)׵flnHT4ylzп8w_,nH+Oh~muIF)kmuIFvkgznM6R;m_,t t#@dT }l^zu[lҵz12 8}ݢzЇ_[t[]%guA6U3{eՊN6lj /44y~nu H7t/믗|+z< m_җ:펀r-fJhSF%8?Wm\&]y_,{nM6hWK&])jG鶀lյ9ԓeŹSt[@rXǗ3u[@iE H8h pLŏt-ȵzru/}K_7u6li@_д{atxktth#zӎm٪ks{? d^;l.On V]V@oz_[t[ϦXܯ-}{+[umD?"WUFǯ-[ #[umtݲV[G .uڔ%tm~[j\BvеQvW|zQ:@Ș\^'kFCԆ tl 5;)T nXnaWe_[ZJ6FW]Z6"~n9pu[_[Y>6 3eyޓm=>6 gۆ4n)Y5׽1zCM=4E; bP574Bӟֈ1/d]>˯]^^IѵQ8ceYwd]@r~$BǺ}e'jRI[UkKU?>?B8h 4^lذAJܭh%v<:75E `*@?=zK'њvv8¯--d]V@n4Vv˞;,!kKo{tmifU=vͽnd~nyΑ~'p@h2=%0+\Z]Tm銠GvюKFͰD[n@G7CrrY7|gohaRYJ]bywvnܗkK󆓟.!=umiCm}ɞ6,@^~um N#;X"v:wԕػLh=vmd^Ť+WUE-&}>?= KO~:dg]V$~Yκ6h Vy1-_[IgGvֵ%v˳YۖF8h L\{3ϴ/3ߔ^k7 Щ6lڴ=e]JtG.L.O/fw/)G*[mPMQIbxRfwV^+[߯UHrݮ\S8pD, e++{b}oyëGzp2[ nKm.wy\==] ;OS:P6)ǖ5&v<@^2:<KnͰD[{ŻaYd,ЭJ޿o[fyjo[dQNnnڪ'j݊wRb"0F%+Wκ~nwtbdg][N_,n[kúғ^pa~G k '?E%umXkvޯ]_-kjuǗu[vZ'(uےG :)CkCV!3, q+j+Y~կ?e]KB=k.._WJ/P>gX-7cw5ڵbְB-{Z]Ĝު]wwUߍ4UUi4e^]zz@^͕yvle,e9Uq9nbdSX<+eErv<@^2:ͰD[V?Q.jdwh>)'kzQT?+zSAsky"_b"0rF%R,d]_[vLg_׆ NiG׵ai!6_;ů]W?kCyI>KCtm(9v4vntC2ezrb}ݭLnVYܟvaɚ9jB=}ى^pR_>{KJ̓|ل_XOn%3ڰEy)mR?R {d&Y+ԀvLm{xrw /6r &H 䟶+JQO5aʇzO-}[{GIl_p+p;cҬ5.E `*@c׹/kCkݢ -}t˗nK6!h?ןkCvu[9D׆W\Ctm(~nYNmt#ҍ..X̟wghg\pA0ËLk"FܱzBn~[q|FSlյ{z;ꌅe,7'i^a)^L&6+UiMDkTI2')X=_ȭO`$^Ct7948\|}Waow{}vY@>Gz֫UET:Y:_+-eYѧk{ٓkCm(]nGҵٱ0ȯФHʧ_v{z?p<(whIzM\^*/n~/ Qm-L#iVU{$}?yI؂bFK^L(XbVr Bb{{ӈh[s s n=֫Cj,z>;s* [jpUfWT%v<@^2:< (1"Ġ榿}Wyow{+wg epU7ߣcu?WYJ]Œ=gqnK&Gs7vY~m(]\yt[29JwZ bW6챫_[ BҵEp(]Pr <":@xU){Y,J>*]907]lN"hgyɢۆ2+W秝A}m2ki ;/=i$'ѵ_~vuP Ư-kvA EΠk -pܾ{t-_[^tậ:@0Bڋ.d[6nd^? /9ӯ]CM EΠki~g%|Zt-nғt۰$=vkm~nD|N KNk }va tK HG 9hS!r%@Z0E k3v~nmK~0{et_[|᧜Dj j^B7KNkYf9vYZJ7KNkvˎ[mۡ4 sBfY/\]lv,x ,[c݃=V7KNk r޻%b~ek9G<گ-o8)m <_[t7^_ 9-F_[t[kt#@dT*>vvnd^%b촽_[td+ݢۖ&<џlٲo_[tytm1~nbJݶr][_[+4GW햑Wt#@dT&>sI^W-wGW행'-_+ɩtWt_,{-~3Nke]vmK#ҵ`yG鶥SZ_;o_,}ړuȩt-W5 7>+-t#0?\I}h^8dݶ4r*]kߝvkW_lݶ4r*]Ƚwkwn[SEmOaݶd)&+W,K#ҵޢfW楑SZo+G?o/J8h 4@L,/tY:<.ߝsT֗_[Fg!ҵV,_W]Z7/Mz{Kk刽vs@u1~V{︽_,[ wvkvYڈ>崺j*vsol6 "䜺\n ta <ɇ7X)d&~nm_붑sZj\L ?uiunE,}mtiu.kFiu-W}ntuO~c$1p@\F%˾;FGNkj>mt䴺xkm#%gֵ#ݯ]_^#QuڣïZ?<ݢFieGjWhRG 212Pf2zǭld^趑uڕ+"_}m#봛~`?șuί-Vmhjlm̺VWݷןYrƑ3Z_[z6F:@Z&9+nbуsY2=ݐ@ @:@72/YvjK6Rrf]ݗ˲㻀/ry9gk)~ٓkgqn59yv~m&'5ϡ{.˻^l6jrr]٩ H (@uWW.n\_L4Ev7GNXA `*t5cm,mԢgϿ;D<.'ymЫWvK#!'׵B_A\<~nFMNkjmt#5h@\WF%K#'5_[a;6jrr]U=vm-Z |_,'n @r~'uN;ӞZ ׵[n.[{WDn;taMWo6]M_W|;z0@N.\CݭL4u2>x]o9r~]+6~nm-OŪ~nmho9{1}Fnr۽Gοvz0w{;> )9#rr{Q0Ap 9??tc4u,Q*tmٲWF~bU-##?6[Ztmٲ{Ŝ_,mnag.˚vmZtmٲ=xvYv~5R-[v#!ڲeG쵻_,96!:@aϛtݷg~/|['~߆o=߼?|5wfԵ.;3]x>v%>w9te= |ǭC<^ ;y 4u,~17bWpnkԢk˖{I~\Su["kwԪ=Û٫,nSZ~nYR[Y~nqZUֲ]4. MnO+G ˧of\/_O]_Ǿ?=u~;`3^3|7H^V_se=# i&+s]4 {"Oyl@@OԢkv TT4-WrZ%+eqaW#mjTT4s*\i,w~vt\s>߹ww'#uGoyOGؕz0ɷ.;o(\~R׊>VfUEzVȆ\vwg0{\!݊ Vi:VȞ P["GYYt[\E4{'u k!u?[mvoT_[1uI]N{_,m7GB?s!~^nHw{tu{ |wMy{{}u[ `FD[eL(KMz_kV턍̶l)6}]v郻Q%-9;[ikcC’4u#bUdm퓺& NjFn|JݼI߿Fn9x]ts_~i~<us 8ٯ]7|n4ta}Wozr{Dv;←Qmٳ?{$•oܖ^Z]v-Dw3'V0s.2*4r=2cK׍yɲIu9vYa;<eO;ey-кm,UEEj趱hT_AH?ncReMToz-fT3tQbdmorb[&IsҘTli%w}[ȱ%h@DxA4vnzmi.@߿^b7jeW^Q,onn_y,r~{ G {\< r}["ЍKJEvYu'6o:婍 xځ궱xᜧ,1~I5.w^\6r@dmcqn;7jEv[nѨ]ݖta-R#YN\`̸`7 uo5;ȼdmcn#_}mcY,秗@7jem,2ecmuX3p:@zdzlnKmHG 9hSahth`Q:@2G `*@#hp@:h@ 4ڦ4 s4r@G #4@@m:@2G `*@#hp@:h@ 4ڦ4nZH1UL]FӚ@w4ڦ4NvJ+Dс!o6.L T.ބH +Ọ59!<hM8h tEV8@-܅iʁ܅0Tpӛsd%|Ѵ&'НGG '6Qt`@倻0-S9F nz~N#26tSZ& pw*rhSMoi|$]FӚ@w4ڦ4NvJ+D/Ż/{hѠ6-X=T\ЁǣkCMGͭۨ{s7wK⋵k BrhSMoi)d%|w@w4ڦ4NvJ+DMWmzrc?֢At.jmS sa>$C^ :`8rhSMoi)d%|w@w4ڦ4NvJ+DC_KO7~w?>t)a*D65ǿ n,ݓo"R]L7 ?1]Ƽmg6tSZ&?~??#{_>#h~ |˦5Нr=((@B?L z6c#C]p7!lH.M7^&">^ _A F nz~NcN +Ọk6tSZ&wOp~WK~ wq}uJ1Բ2(w.#!WvubB #"Ug\B٨gr`)W[`"ꦔm]4Tzs BB `*M992m;3НGG '6Q~>;ܡu} Gqda~Vq^: A Lo;իRjA]PEWlM)GR8!D^/]kyF nz~NcN +Ọy t@m:@+j‰M߁v7~,_-{^ZˇTha-}b vW* 텑>:ܺuR0`BJ.Tʡ\)EnJ@ ِ(zڶ{5wu;ہA]L7 ?1]Ƽmg6tSZ&r#_,7,pCcpuwۿ݇qC=qFsvCsMa_ E5xe/l\][;؄AwaZ+GWT@s1ER[k j]L7 ?1]Ƽg6tSZ&~jrmz*ϯ}{OXș|AWߣ2xك_Uzf#yakB 4)D 5[[17<08 a474˸7@w4ڦ4NvJ+Dk߀v|n|g\L0Pqw*rhSMoi)d%|Ѵ&'НGG '6Q~~?yODYw=;>_q'C-:@-܅iʁ܅0Tpӛss Y e4 t@m:@+j‰M߁g|Otocy'}F倻0-S9F nz~NcN +Ọ59!<hM8h tEV8;;_Dpw*rhSMoi)d%|Ѵ&'НGG '6Q~=_;\n΃Qj9.L T.ބӘSJ.iMN;mH']Q;Nl PwaZpr w!0&G2Y e4 t@m:@+j‰Mj9.L T.ބH +Ọ59!<hM8h tEV8@-܅iʁ܅0Tpӛsd%|Ѵ&'НGG '6Qt`@倻0-S9F nz~N#26tSZ& pw*rhSMoi|$]FӚ@w4ڦ4NvJ+DQ2%0@wMkrByhp@:)pbE`4hZ#Ft#IWNi(9 L#}/T!0wMkrByhp@:)pb%G`$VoB8iZ#Ft#IWNi(:0 F09܅iw!Oa^rӛsd%4 t@m:@+j‰MD99.L T y 󚐛ބH +ဦiMN;mH']Q;Nl waZpr]Sׄ&G2Y 4MkrByhp@:)pbEQN ӂ;B¼&74>J8iZ#Ft#IWNi(:0 rr]ܩp5!7 ? @VMӚ@w4ڦ4NvJ+DсA´N倻0 M9dh6tSZ& pw*܅܅[vpw!Oa^rӛss Y 4vQJku߸?{bޅeoС!F8h tEV8uZPWmw*pQ.'io3]w{yXor]Lf'tj3ʫbEMz^ A鐍~^}Էs&;5} y 󚐛ބӘSJ8Yx @~2KA Kn˚ԡ!F8h tEV8u0.Iwj<4ʽJ{j[7OS{f'')KV++\@ׂtַ۪s&;5} y 󚐛ބӘSJ8c h}~~/s. ew~eo?F_ˊ,\s|kvO}Mo[׼_M Ë%,]y_7/퓮_/]+o_ޭ|z7|7Ԟ o ?aٹڟ~ɿ^x߿|ǵ^9wZ$W/BK,?n;O7KOWSFU1YSr6sŵycWG[/*z#>\Oc[NlO}yFQ+V|VEn߿v_}Oa+bOG܈ 3zy1_6fOXe\sªwr!|z 5+warSӇ0 M99߉/3o~ <hM8h tEV8t`:l\ב=KEer՜?^_AFIJ<+=~Z=ګZOha`r!|QxSV>.Lwjp5!7 ?1p@s Byhp@:)pbEQN ӂ;B¼&74>J8iZ#Ft#IWNiv:p9pw*܅J8iZ#Ft#IWNi(:0 rr]ܩp5!7 ? @VMӚ@w4ڦ4NvJ+DсA´N倻0 M9dh6tSZ&*ց7ӗⲹuX_l~A (입iFu{G3~Spĝw!Oa^rӛss Y 46tSZ&فmZE׭Dss~+m[}:Z9v } Ӏ(gkJ.d;)B¼&74h 7НGG '6Qlb^ɰɟmtjbX8k Nk|0rL^3j.d;-B¼&74h6tSZ&ց娲&ߖF^"+ nW5eWVW8)_ڴTlUg)c kz6VD9c%/j Ne0 M99ΙrByhp@:)pbUAP6;Ql+-?RU/4x} S(gL.d;5B¼&74hv#Ft#IWNiZ~UKomaΪ0TgFudJ8iZ#Ft#IWNi(9J^f`wd%kBrlL kဦiMN;mH']Q;Nl waZpr]Sׄ&G2Y 4MkrByhp@:)pbEQN ӂ;B¼&74>J8iZ#Ft#IWNi(:0 rr]ܩp5!7 ? @VMӚ@w4ڦ4NvJ+DсA´N倻0 M9dh6tSZ& pw*܅0LAPR?F= =Ҍ<)ºz=;L=*^[w!;ܩq5!7 ?1p@s Byhp@:)pb6|"ysss~aٹ9?6Ҩ־^gpoq֎"#y] w*k܅^+͗w!/ܩq5!7 ?1p@3S@w4ڦ4NvJ+DE: PCK4C:&-;GPuWspkx-~I{'%6]Y%~<Uh0 Ne0 M99T#Ft#IWNi(:ty䀻0-S9.)kBnz~N#59!<hM8h tEV8jW_f+5Oid('܅iw!Oa^rӛss Y 46tSZ&<"t!waZpr]Sׄ&G2Y 46tSZ& pw*܅J8iZ#Ft#IWNi(:0 rr]ܩp5!7 ? @VMӚ@w4ڦ4NvJ+DсA´N倻0 M9dh6tSZ& pw*܅ #Ft#IWNi(:0 rr]ܩp5!7 ? @VMӚs6tSZ& pw*܅NyrƱ?߮iOP3nc?,|a;gǮ}ǘS}cxǺCX+ wCO}~-1ȩ툓xс{>sНG uKXSzDNuGO=u;Tw)W^+Wx^&;Ao:@+j‰M`$¼&D `*59@$]ڡ4NvJ+DсF"kBB8iZ#Ft#IWNi(:0HyMT4MkrByhp@:)pbE0 @ ဦiMN;mH']Q;Nl#5!hS!4 t@m:@+j‰M`$¼&D `*59!<hM8h tEV8DׄLp@Ӵ&'НGG '6Qt`4h6tSZ& 0a^"0MӚ@w4ڦ4NvJ+DсF"kBB8iZ#Ft#IWNi(:0HyMT4MkrByhp@:)pbE0 @ ဦiMN;mH']Q;Nl#5!hS!4 t@m:@+j‰M`$¼&D `*59!<hM8h tEV8DׄLp@Ӵ&'НGG '6Qt`4h6tSZ& 0a^"0MӚ@w4ڦ4NvJ+DсF"kBB8iZ#Ft#IWNi(:0HyMT4MkrByhp@:)pbE0 @ ဦiMN;mH']Q;Nl#5!hS!4 t@m:@+j‰M`$¼&D `*59!<hM8h tEV8DׄLp@Ӵ&'НGG '6Qt`4h6tSZ& 0a^"0MӚ@w4ڦ4NvJ+DсF"kBB8iZ#Ft#IWNi(:0HyMT4MkrByhp@:)pbE0 @ ဦiMN;mH']Q;Nl(~T4MkrByhp@:)pb"0hM8h 4@LhmHG 9hS9 Ft#@dT F6t#0hM8h 4@ץ+?=\~AFE@#hp@:A}_51WMW&J@$?y] -}!F6t1[n6I|@sM74r@G #_0FzrP)os}h WO|B 7t@`ZD@m:@pEI dA |?sAᦛn5,@~02:hmHG=yig+4@xT\q?Zؒ}\~#CJ{?ddه9 Ft#@D^LL\]o {W$mO-'y r"K=$C1(ʘEC@m:MK dB;Nl61#{@@?c֯_Yύ7 % DG׼F-dtx*hZH`)tS8O^2WVipiv5+??#&z{=I|@?裏x Z[ύ7  223t2ڄUҵ ]Zȿt#Nlz<}6[b{zJzB^2WVϼC8Md7\s։??3z%$ .ͮ7=ruW~?î桇[vݮTTo>-r0_v\Gyck^}`>7pC'ЍDFgG!^:GZ @ ̓փU27AonRfSVt$ .ͮ7=C{ ez!O|),wu7?pf|7Е,s\~(я~T,n 28,@Hc)>0qhZh]8I%g+ F?{)rݣ@ ӥ^} ZVw2}|w^zC=nH a:q!0 t#Nlz@P]eKfeG=Uzxq:SxyRfwN^(*Wy u5[I^2W|r|7嗔#-~ge^kKMQð'V/Ng /P#E*^~b6mgв.%# .ͮ7j=?]?,R~{uW%o(|w~w=(-4̅)!^CP]!mO>s\ʞf ]w% 4Y40pbUo@]IS]6\0浧uձ;ZXG]Vy9apPK ҖCkL)q%gVzCߐkC³ sWǚbWk.ka>^SkN\)Ro{~WZu-f^^i|-K=Yʇ^ݩƼ*| IYLan} Ne d<Ԕzߺ)mG~V>>t E7-*DrnMO:RBj MpbC斊V魔Ze8z\*;{uzkdk.XvUX~IbXv5̖YS&jű^9G6׫^~yx^-~?q@\]o {{V?Q.=9ʾ |Ixg^SE+.v:̗6'TItpS@z_<"r׾5= INlz#ھnU(khxaIf~("ZgK[W嗔J)$jWfK̓PzM1^aFXR?.Ȧ6|===orۮ7ok÷㺩jZIOlz&z~d .ͮ7ixH4)iT_1Vl9-?s `܊T F5ecM0n0&3FH{:MQx݃<G{G}LK1҅Wxgp?Evo=|7|n(h;,JV(>O#Պ <@e÷Wkx_^Syw?l¦jI!O7߭IOl AroAIK@2#os5S`~A.YHh÷2n/R+T ϻ 0-1iNʤ}Hz$lEZB) _I@weW#"DPXO#hc˪ÇiײwiquQJZZ20~Cy4^Vug~.7p8۟B~`ǻ[ņ࠺YGaNېUߝʨzw$! ~#tWl|_-GUbͮGXAo*ټ4.fń&m/]KU-'oWO%UQMghT+#T WnL?`285K@îP͎"#~6, kݡƿc/=hAs*v䯡Mu\ CPe!^!r>2/A ߿cO@{.-dgfP],#m' _# fJٹZF)UN6Xq}Wݶ|+<ntΠ?6.we@@.t3xWvqohjn{ר=+XO6?wޭ˜UUuޕf@%Mvj4 EYro*ʍ|\* ߗj|rAݺbRS=vN^\?_WeiƁΟr*__.}:̧s:sW@Ύ7 9d{?Z;84mDԭ{7IZ~9v[Ҧ0=b^e1:j#(^C=͟;.W| JM ..s.aP],<=0TI۲s/W__ӟnUrRU7f0hM*=Y'*h~3lxCyT'+աt#;3Bx 76 @=2.0.0"] build-backend = "scikit_build_core.build" [project] name = "asammdf" description = "ASAM MDF measurement data file parser" readme = "README.md" requires-python = ">=3.10" license = { text = "LGPLv3+" } authors = [{ name = "Daniel Hrisca", email = "daniel.hrisca@gmail.com" }] dynamic = ["version"] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Topic :: Software Development", "Topic :: Scientific/Engineering", "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] keywords = [ "read", "reader", "edit", "editor", "parse", "parser", "asam", "mdf", "measurement", ] dependencies = [ "canmatrix[arxml,dbc]>=1.2", "isal; platform_machine == 'x86_64' or platform_machine == 'AMD64'", "lxml>=4.9.3", "lz4", "numexpr>=2.10.0", "numpy>=2.0.0", "pandas>=2.2.2", "python-dateutil", "typing-extensions~=4.10", ] [project.optional-dependencies] decode = ["faust-cchardet==2.1.19", "chardet"] export = [ "pyarrow>=17.0.0", "h5py>=3.11", "hdf5storage>=0.1.19", "python-snappy", "polars>=1.1.0", ] export-matlab-v5 = ["scipy>=1.13.0"] gui = [ "natsort", "PySide6>=6.7.0", "pyqtgraph>=0.13.4", "pyqtlet2[PySide6]", "packaging", ] encryption = ["cryptography", "keyring"] plot = ["matplotlib"] symbolic-math = ["sympy>=1.13.0"] filesystem = ["fsspec"] [project.scripts] asammdf = "asammdf.app.asammdfgui:main [gui]" [project.urls] Documentation = "https://asammdf.readthedocs.io/en/master" Issues = "https://github.com/danielhrisca/asammdf/issues" Source = "https://github.com/danielhrisca/asammdf" [tool.scikit-build] metadata.version.provider = "scikit_build_core.metadata.regex" metadata.version.input = "src/asammdf/version.py" sdist.include = ["ext"] wheel.packages = ["src/asammdf"] wheel.py-api = "cp310" [tool.coverage] run.relative_files = true run.source_pkgs = ["asammdf"] paths.source = ["src", "*/site-packages"] report.omit = ["*/asammdf/gui/ui/*"] [tool.cibuildwheel] manylinux-x86_64-image = "manylinux_2_28" test-requires = "pytest" test-command = "pytest {project}/test" build-frontend = "build" archs = ["auto64"] # only build for 64bit architectures # skip pypy and irrelevant architectures skip = ["pp*", "*_ppc64le", "*-musllinux*", "*_s390x"] [tool.mypy] files = "." exclude = ["build/", "ci/", "dist/", "doc/_build/", "ext/", "test/asammdf/gui/"] python_version = "3.10" enable_error_code = ["deprecated"] strict = true [[tool.mypy.overrides]] module = [ "canmatrix.*", "cchardet.*", "cmerg.*", "fsspec.*", "h5py.*", "hdf5storage.*", "isal.*", "lz4.*", "mdfreader.*", "mfile.*", "mpl_toolkits.*", "numexpr.*", "pyqtgraph.*", "pyqtlet2.*", "snappy.*", "sympy.*", "xmlrunner.*", ] ignore_missing_imports = true [[tool.mypy.overrides]] module = ["asammdf.app.asammdfgui", "asammdf.gui.*"] ignore_errors = true [tool.ruff] line-length = 120 target-version = "py310" extend-exclude = ["./src/asammdf/gui/ui", "./ext"] force-exclude = true [tool.ruff.lint] select = [ "B", # flake8-bugbear "C4", # flake8-comprehensions "F", # pyflakes "UP", # pyupgrade "I", # isort "PIE", # flake8-pie "PL", # pylint "RUF", # Ruff-specific rules ] ignore = [ "B007", # unused-loop-control-variable "F841", # unused-variable "PLC0414", # useless-import-alias "PLR09", # too-many-this, too-many-that "PLR2004", # magic-value-comparison "PLR5501", # collapsible-else-if "PLW0603", # global-statement "PLW2901", # redefined-loop-name "RUF012", # mutable-class-default "RUF015", # unnecessary-iterable-allocation-for-first-element "UP038", # non-pep604-isinstance ] [tool.ruff.lint.isort] known-first-party = ["asammdf"] order-by-type = false force-sort-within-sections = true asammdf-8.5.1/requirements.txt000066400000000000000000000006021502633300400164130ustar00rootroot00000000000000# Development dependencies --editable .[decode,encryption,export,export-matlab-v5,filesystem,gui,plot,symbolic-math] --requirement benchmarks/requirements.txt --requirement ci/requirements.txt --requirement doc/requirements.txt --requirement test/requirements.txt --requirement types-requirements.txt build mypy~=1.14 pre-commit ruff~=0.11.0 # Aligned with .pre-commit-config.yaml tox asammdf-8.5.1/run_ruff.bat000066400000000000000000000001121502633300400154410ustar00rootroot00000000000000pip install --upgrade ruff~=0.11.0 && ^ ruff check --fix && ^ ruff format asammdf-8.5.1/src/000077500000000000000000000000001502633300400137205ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/000077500000000000000000000000001502633300400153305ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/__init__.py000066400000000000000000000020301502633300400174340ustar00rootroot00000000000000"""asammdf is a parser and editor for ASAM MDF files""" import logging logger = logging.getLogger("asammdf") formatter = logging.Formatter("%(name)s - %(levelname)s - %(message)s") console = logging.StreamHandler() console.setFormatter(formatter) console.setLevel(logging.DEBUG) logger.addHandler(console) logger.setLevel(logging.ERROR) # patch for hdf5storage import numpy as np if not hasattr(np, "unicode_"): setattr(np, "unicode_", np.str_) # noqa: B010 from .blocks.options import get_global_option, set_global_option from .blocks.source_utils import Source from .gui import plot from .mdf import MDF, SUPPORTED_VERSIONS from .signal import InvalidationArray, Signal from .version import __version__ try: from .blocks import cutils # noqa: F401 __cextension__ = True except ImportError: __cextension__ = False __all__ = [ "MDF", "SUPPORTED_VERSIONS", "InvalidationArray", "Signal", "Source", "__cextension__", "__version__", "get_global_option", "plot", "set_global_option", ] asammdf-8.5.1/src/asammdf/app/000077500000000000000000000000001502633300400161105ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/app/asammdfgui.py000066400000000000000000000026131502633300400206010ustar00rootroot00000000000000import argparse import os import sys def _cmd_line_parser(): """""" parser = argparse.ArgumentParser() parser.add_argument("--measurements", nargs="*", help="list of measurement files") return parser def main(measurements=None): os.environ["QT_API"] = "pyside6" os.environ["PYQTGRAPH_QT_LIB"] = "PySide6" if "QT_ENABLE_HIGHDPI_SCALING" not in os.environ: os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" alternative_sitepacakges = os.environ.get("ASAMMDF_PYTHONPATH", "") if alternative_sitepacakges: os.environ["PYTHONPATH"] = alternative_sitepacakges sys.path.insert(0, alternative_sitepacakges) import pyqtgraph from PySide6 import QtWidgets from asammdf.gui.utils import excepthook, set_app_user_model_id from asammdf.gui.widgets.main import MainWindow from asammdf.gui.widgets.plot import monkey_patch_pyqtgraph sys.excepthook = excepthook monkey_patch_pyqtgraph() parser = _cmd_line_parser() args = parser.parse_args(sys.argv[1:]) app = pyqtgraph.mkQApp() app.setOrganizationName("py-asammdf") app.setOrganizationDomain("py-asammdf") app.setApplicationName("py-asammdf") set_app_user_model_id("py-asammdf") _main_window = MainWindow(measurements or args.measurements) app.setStyle(QtWidgets.QStyleFactory.create("Fusion")) app.exec() if __name__ == "__main__": main() asammdf-8.5.1/src/asammdf/blocks/000077500000000000000000000000001502633300400166055ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/blocks/__init__.py000066400000000000000000000000001502633300400207040ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/blocks/blocks_common.py000066400000000000000000000003151502633300400220030ustar00rootroot00000000000000from typing_extensions import Buffer, Protocol, TypeVar _T_co = TypeVar("_T_co", covariant=True) class UnpackFrom(Protocol[_T_co]): def __call__(self, buffer: Buffer, offset: int = 0) -> _T_co: ... asammdf-8.5.1/src/asammdf/blocks/bus_logging_utils.py000066400000000000000000000367101502633300400227050ustar00rootroot00000000000000from traceback import format_exc import typing from typing import Final from canmatrix import Frame, Signal import numpy as np from numpy.typing import NDArray from typing_extensions import Any, TypedDict from . import v4_blocks as v4b from . import v4_constants as v4c from .conversion_utils import from_dict from .utils import as_non_byte_sized_signed_int, MdfException MAX_VALID_J1939: Final = { 2: 1, 4: 0xA, 8: 0xFA, 10: 0x3FA, 12: 0xFAF, 16: 0xFAFF, 20: 0xFAFFF, 24: 0xFAFFFF, 28: 0xFAFFFFF, 32: 0xFAFFFFFF, 64: 0xFFFFFFFFFFFFFFFF, } def defined_j1939_bit_count(signal: Signal) -> int: size = typing.cast(int, signal.size) for defined_size in (2, 4, 8, 10, 12, 16, 20, 24, 28, 32, 64): if size <= defined_size: return defined_size return size def apply_conversion(vals: NDArray[Any], signal: Signal, ignore_value2text_conversion: bool) -> NDArray[Any]: conv = get_conversion(signal) if conv and not (ignore_value2text_conversion and conv.conversion_type in v4c.CONVERSIONS_WITH_TEXTS): vals = conv.convert(vals) return vals def extract_signal( signal: Signal, payload: NDArray[Any], raw: bool = False, ignore_value2text_conversion: bool = True, is_ISOTP: bool = False, ) -> NDArray[Any]: vals = payload big_endian = False if signal.is_little_endian else True signed = signal.is_signed is_float = signal.is_float start_bit = signal.get_startbit(bit_numbering=1) if big_endian: start_byte = start_bit // 8 bit_count = signal.size pos = start_bit % 8 + 1 over = bit_count % 8 if pos >= over: bit_offset = (pos - over) % 8 else: bit_offset = pos + 8 - over else: start_byte, bit_offset = divmod(start_bit, 8) bit_count = signal.size if is_float: if bit_offset: raise MdfException(f"Cannot extract float signal '{signal}' because it is not byte aligned") if bit_count not in (16, 32, 64): raise MdfException(f"Cannot extract float signal '{signal}' because it does not have a standard byte size") if big_endian: byte_pos = start_byte + 1 start_pos = start_bit bits = bit_count while True: pos = start_pos % 8 + 1 if pos < bits: byte_pos += 1 bits -= pos start_pos = 7 else: break if byte_pos > vals.shape[1]: raise MdfException( f'Could not extract signal "{signal.name}" with start ' f"bit {start_bit} and bit count {signal.size} " f"from the payload with shape {vals.shape}" ) else: if start_bit + bit_count > vals.shape[1] * 8: raise MdfException( f'Could not extract signal "{signal.name}" with start ' f"bit {start_bit} and bit count {signal.size} " f"from the payload with shape {vals.shape}" ) byte_size, r = divmod(bit_offset + bit_count, 8) if r: byte_size += 1 if byte_size in (1, 2, 4, 8): extra_bytes = 0 else: extra_bytes = 4 - (byte_size % 4) std_size = byte_size + extra_bytes # prepend or append extra bytes columns # to get a standard size number of bytes if is_ISOTP: # Don't muck around with size of ISO-TP signals return vals if extra_bytes: if big_endian: vals = np.column_stack( [ vals[:, start_byte : start_byte + byte_size], np.zeros(len(vals), dtype=f"<({extra_bytes},)u1"), ] ) if std_size > 8: fmt = f"({std_size},)u1" elif is_float: fmt = f">f{std_size}" else: fmt = f">u{std_size}" try: vals = vals.view(fmt).ravel() except: vals = np.frombuffer(vals.tobytes(), dtype=fmt) if std_size <= 8 and not is_float: vals = vals >> (extra_bytes * 8 + bit_offset) vals &= (2**bit_count) - 1 else: vals = np.column_stack( [ vals[:, start_byte : start_byte + byte_size], np.zeros(len(vals), dtype=f"<({extra_bytes},)u1"), ] ) if std_size > 8: fmt = f"({std_size},)u1" elif is_float: fmt = f"> bit_offset vals &= (2**bit_count) - 1 else: if big_endian: if std_size > 8: fmt = f"({std_size},)u1" elif is_float: fmt = f">f{std_size}" else: fmt = f">u{std_size}" try: vals = vals[:, start_byte : start_byte + byte_size].view(fmt).ravel() except: vals = np.frombuffer( vals[:, start_byte : start_byte + byte_size].tobytes(), dtype=fmt, ) if std_size <= 8 and not is_float: vals = vals >> bit_offset vals &= (2**bit_count) - 1 else: if std_size > 8: fmt = f"({std_size},)u1" elif is_float: fmt = f"> bit_offset vals &= (2**bit_count) - 1 if signed and not is_float: if extra_bytes or bit_count not in (8, 16, 32, 64): vals = as_non_byte_sized_signed_int(vals, bit_count) else: vals = vals.view(f"i{std_size}") if not raw: vals = apply_conversion(vals, signal, ignore_value2text_conversion) return vals def extract_can_signal( signal: Signal, payload: NDArray[Any], raw: bool = False, ignore_value2text_conversion: bool = True, ) -> NDArray[Any]: return extract_signal(signal, payload, raw, ignore_value2text_conversion) def extract_lin_signal( signal: Signal, payload: NDArray[Any], raw: bool = False, ignore_value2text_conversion: bool = True, ) -> NDArray[Any]: return extract_signal(signal, payload, raw, ignore_value2text_conversion) class ExtractedSignal(TypedDict): name: str comment: str unit: str samples: NDArray[Any] conversion: v4b.ChannelConversion | None t: NDArray[Any] invalidation_bits: NDArray[np.bool] | None def merge_cantp(payload: NDArray[Any], ts: NDArray[Any]) -> tuple[NDArray[Any], NDArray[Any]]: """Merge sequences of ISO-TP coded CAN payloads, enabling > 8 byte frames.""" INITIAL = 0x10 CONSECUTIVE = 0x20 merged = [] t_out = [] merging = np.array([], "uint8") for frame, t in zip(payload, ts, strict=False): if frame[0] & 0xF0 == INITIAL: expected_size = np.uint16(256) * (frame[0] & 0x0F) + frame[1] merging = np.array(frame[2:8], "uint8") if frame[0] & 0xF0 == CONSECUTIVE: merging = np.hstack((merging, frame[1:])) if len(merging) >= expected_size: merging = merging[:expected_size] merged.append(merging) t_out.append(t) # Using t from final received part (as does Canoe, apparently) frames = np.vstack(merged) if len(merged) > 0 else np.array([], "uint8") return frames, np.array(t_out) def extract_mux( payload: NDArray[Any], message: Frame, message_id: int | None, bus: int | None, t: NDArray[Any], muxer: str | None = None, muxer_values: NDArray[Any] | None = None, original_message_id: int | None = None, raw: bool = False, include_message_name: bool = False, ignore_value2text_conversion: bool = True, is_j1939: bool = False, is_extended: bool = False, ) -> dict[tuple[int | None, int | None, bool, int | None, str | None, int, int], dict[str, ExtractedSignal]]: """Extract multiplexed CAN signals from the raw payload. Parameters ---------- payload : np.ndarray Raw CAN payload as numpy array. message : canmatrix.Frame CAN message description parsed by canmatrix. message_id : int Message id. bus : int Bus channel number. t : np.ndarray Timestamps for the raw payload. muxer : str, optional Name of the parent multiplexor signal. muxer_values : np.ndarray, optional Multiplexor signal values. original_message_id : int, optional Original message id. ignore_value2text_conversion : bool, default True Ignore value to text conversions. .. versionadded:: 5.23.0 Returns ------- extracted_signal : dict Each value in the dict is a list of signals that share the same multiplexors. """ if muxer is None: if message.is_multiplexed: for sig in message: if sig.multiplex == "Multiplexor" and sig.muxer_for_signal is None: multiplexor_name = sig.name break for sig in message: if sig.multiplex not in (None, "Multiplexor"): if sig.muxer_for_signal is None: sig.muxer_for_signal = multiplexor_name if not hasattr(sig, "mux_val_min"): sig.mux_val_min = sig.mux_val_max = int(sig.multiplex) sig.mux_val_grp.insert(0, (int(sig.multiplex), int(sig.multiplex))) extracted_signals: dict[ tuple[int | None, int | None, bool, int | None, str | None, int, int], dict[str, ExtractedSignal] ] = {} # (Too?) simple check for ISO-TP CAN data - if it has flow control, we believe its ISO-TP is_ISOTP = "CanTpFcFrameId" in message.attributes if is_ISOTP: # print(f" ISO-TP frame, for message {message_id}, merging CAN frames...") payload, t = merge_cantp(payload, t) # assert(len(payload) == len(t)) # if len(payload) > 0: # print(f" message size post-merge: {payload.shape[1]}") # else: # print(f" no payload found to merge") if message.size == 0 or payload.shape[1] == 0: return extracted_signals elif message.size > payload.shape[1]: extra_bytes = message.size - payload.shape[1] payload = np.column_stack( [ payload, np.full(len(payload), 0xFF, dtype=f"({extra_bytes},)u1"), ] ) pairs: dict[tuple[int, int], list[Signal]] = {} for signal in message: if signal.muxer_for_signal == muxer: try: pair = signal.mux_val_min, signal.mux_val_max except: pair = tuple(signal.mux_val_grp[0]) if signal.mux_val_grp else (0, 0) pair_signals = pairs.setdefault(pair, []) pair_signals.append(signal) for pair, pair_signals in pairs.items(): entry = bus, message_id, is_extended, original_message_id, muxer, *pair signals = extracted_signals.setdefault(entry, {}) if muxer_values is not None: min_, max_ = pair idx = np.argwhere((min_ <= muxer_values) & (muxer_values <= max_)).ravel() payload_ = payload[idx] t_ = t[idx] else: t_ = t payload_ = payload for sig in pair_signals: samples = extract_signal( sig, payload_, ignore_value2text_conversion=ignore_value2text_conversion, raw=True, is_ISOTP=is_ISOTP, ) if len(samples) == 0 and len(t_): continue if include_message_name: sig_name = f"{message.name}.{sig.name}" else: sig_name = sig.name try: scale_ranges = getattr(sig, "scale_ranges", None) if scale_ranges: unit = scale_ranges[0]["unit"] or "" else: unit = sig.unit or "" signals[sig_name] = { "name": sig_name, "comment": sig.comment or "", "unit": unit, "samples": samples if raw else apply_conversion(samples, sig, ignore_value2text_conversion), "conversion": get_conversion(sig) if raw else None, "t": t_, "invalidation_bits": None, } if is_j1939: signals[sig_name]["invalidation_bits"] = samples > MAX_VALID_J1939[defined_j1939_bit_count(sig)] except: print(format_exc()) print(message, sig) print(samples, set(samples), samples.dtype, samples.shape) raise if sig.multiplex == "Multiplexor": extracted_signals.update( extract_mux( payload_, message, message_id, bus, t_, muxer=sig.name, muxer_values=samples, original_message_id=original_message_id, ignore_value2text_conversion=ignore_value2text_conversion, raw=raw, is_j1939=is_j1939, is_extended=is_extended, ) ) return extracted_signals def get_conversion(signal: Signal) -> v4b.ChannelConversion: conv: v4b.ChannelConversionKwargs = {} a, b = float(signal.factor), float(signal.offset) scale_ranges = getattr(signal, "scale_ranges", None) if scale_ranges: for i, scale_info in enumerate(scale_ranges): conv[f"upper_{i}"] = scale_info["max"] # type: ignore[literal-required] conv[f"lower_{i}"] = scale_info["min"] # type: ignore[literal-required] conv[f"text_{i}"] = from_dict({"a": scale_info["factor"], "b": scale_info["offset"]}) # type: ignore[literal-required] for i, (val, text) in enumerate(signal.values.items(), len(scale_ranges)): conv[f"upper_{i}"] = val # type: ignore[literal-required] conv[f"lower_{i}"] = val # type: ignore[literal-required] conv[f"text_{i}"] = text # type: ignore[literal-required] conv["default_addr"] = from_dict({"a": a, "b": b}) elif signal.values: for i, (val, text) in enumerate(signal.values.items()): conv[f"upper_{i}"] = val # type: ignore[literal-required] conv[f"lower_{i}"] = val # type: ignore[literal-required] conv[f"text_{i}"] = text # type: ignore[literal-required] conv["default_addr"] = from_dict({"a": a, "b": b}) else: conv["a"] = a conv["b"] = b return from_dict(conv) asammdf-8.5.1/src/asammdf/blocks/conversion_utils.py000066400000000000000000000606221502633300400225720ustar00rootroot00000000000000"""asammdf utility functions for channel conversions""" from copy import deepcopy import typing from typing import Literal from typing_extensions import overload from . import v2_v3_blocks as v3b from . import v2_v3_constants as v3c from . import v4_blocks as v4b from . import v4_constants as v4c from .types import ChannelConversionType @overload def conversion_transfer( conversion: ChannelConversionType | None, version: Literal[2, 3] = ..., copy: bool = ... ) -> v3b.ChannelConversion: ... @overload def conversion_transfer( conversion: ChannelConversionType, version: Literal[4], copy: bool = ... ) -> v4b.ChannelConversion: ... @overload def conversion_transfer(conversion: None, version: Literal[4], copy: bool = ...) -> None: ... @overload def conversion_transfer( conversion: ChannelConversionType | None, version: Literal[2, 3, 4] = ..., copy: bool = ... ) -> ChannelConversionType | None: ... def conversion_transfer( conversion: ChannelConversionType | None, version: Literal[2, 3, 4] = 3, copy: bool = False ) -> ChannelConversionType | None: """Convert between MDF4 and MDF3 channel conversions. Parameters ---------- conversion : block Channel conversion. version : int, default 3 Target MDF version. copy : bool, default False Return a copy if the input conversion version is the same as the required version. Returns ------- conversion : block Channel conversion for specified version. """ if version <= 3: if conversion is None: conversion = v3b.ChannelConversion(conversion_type=v3c.CONVERSION_TYPE_NONE) else: conversion_type = conversion.conversion_type if isinstance(conversion, v3b.ChannelConversion): if copy: conversion = deepcopy(conversion) else: unit = conversion.unit.strip(" \r\n\t\0").encode("latin-1") match conversion_type: case v4c.CONVERSION_TYPE_NON: conversion = v3b.ChannelConversion(unit=unit, conversion_type=v3c.CONVERSION_TYPE_NONE) case v4c.CONVERSION_TYPE_LIN: conversion = v3b.ChannelConversion( unit=unit, conversion_type=v3c.CONVERSION_TYPE_LINEAR, a=conversion.a, b=conversion.b, ) case v4c.CONVERSION_TYPE_RAT: conversion = v3b.ChannelConversion( unit=unit, conversion_type=v3c.CONVERSION_TYPE_RAT, P1=conversion.P1, P2=conversion.P2, P3=conversion.P3, P4=conversion.P4, P5=conversion.P5, P6=conversion.P6, ) case v4c.CONVERSION_TYPE_TAB: v3_kwargs = v3b.ChannelConversionKwargs(unit=unit, conversion_type=v3c.CONVERSION_TYPE_TAB) v3_kwargs["ref_param_nr"] = conversion.val_param_nr // 2 for i in range(conversion.val_param_nr // 2): v3_kwargs[f"raw_{i}"] = conversion[f"raw_{i}"] # type: ignore[literal-required] v3_kwargs[f"phys_{i}"] = conversion[f"phys_{i}"] # type: ignore[literal-required] conversion = v3b.ChannelConversion(**v3_kwargs) case v4c.CONVERSION_TYPE_TABI: v3_kwargs = v3b.ChannelConversionKwargs(unit=unit, conversion_type=v3c.CONVERSION_TYPE_TABI) v3_kwargs["ref_param_nr"] = conversion.val_param_nr // 2 for i in range(conversion.val_param_nr // 2): v3_kwargs[f"raw_{i}"] = conversion[f"raw_{i}"] # type: ignore[literal-required] v3_kwargs[f"phys_{i}"] = conversion[f"phys_{i}"] # type: ignore[literal-required] conversion = v3b.ChannelConversion(**v3_kwargs) case v4c.CONVERSION_TYPE_ALG: formula = conversion.formula.replace("X", "X1") conversion = v3b.ChannelConversion( formula=formula, unit=unit, conversion_type=v3c.CONVERSION_TYPE_FORMULA, ) case v4c.CONVERSION_TYPE_RTAB: nr = (conversion.val_param_nr - 1) // 3 v3_kwargs = { "unit": unit, "ref_param_nr": nr, "conversion_type": v3c.CONVERSION_TYPE_TABI, } for i in range(nr): l_ = conversion[f"lower_{i}"] u_ = typing.cast(float, conversion[f"upper_{i}"]) p_ = conversion[f"phys_{i}"] v3_kwargs[f"raw_{i}"] = l_ # type: ignore[literal-required] v3_kwargs[f"raw_{i}"] = u_ - 0.000_001 # type: ignore[literal-required] v3_kwargs[f"phys_{i}"] = p_ # type: ignore[literal-required] v3_kwargs[f"phys_{i}"] = p_ # type: ignore[literal-required] conversion = v3b.ChannelConversion(**v3_kwargs) case v4c.CONVERSION_TYPE_TABX: nr = conversion.val_param_nr v3_kwargs = { "ref_param_nr": nr + 1, "unit": unit, "conversion_type": v3c.CONVERSION_TYPE_RTABX, } for i in range(nr): v3_kwargs[f"lower_{i}"] = conversion[f"val_{i}"] # type: ignore[literal-required] v3_kwargs[f"upper_{i}"] = conversion[f"val_{i}"] # type: ignore[literal-required] block = conversion.referenced_blocks[f"text_{i}"] if isinstance(block, v4b.ChannelConversion): v3_kwargs[f"text_{i}"] = block.name.encode("latin-1") # type: ignore[literal-required] else: v3_kwargs[f"text_{i}"] = block # type: ignore[literal-required] new_conversion = v3b.ChannelConversion(**v3_kwargs) if isinstance( conversion.referenced_blocks["default_addr"], v4b.ChannelConversion, ): default_addr = conversion.referenced_blocks["default_addr"].name.encode("latin-1") else: default_addr = conversion.referenced_blocks["default_addr"] new_conversion.referenced_blocks["default_addr"] = default_addr conversion = new_conversion case v4c.CONVERSION_TYPE_RTABX: nr = conversion.val_param_nr // 2 v3_kwargs = { "ref_param_nr": nr + 1, "unit": unit, "conversion_type": v3c.CONVERSION_TYPE_RTABX, } for i in range(nr): v3_kwargs[f"lower_{i}"] = conversion[f"lower_{i}"] # type: ignore[literal-required] v3_kwargs[f"upper_{i}"] = conversion[f"upper_{i}"] # type: ignore[literal-required] block = conversion.referenced_blocks[f"text_{i}"] if isinstance(block, v4b.ChannelConversion): v3_kwargs[f"text_{i}"] = block.name.encode("latin-1") # type: ignore[literal-required] else: v3_kwargs[f"text_{i}"] = block # type: ignore[literal-required] new_conversion = v3b.ChannelConversion(**v3_kwargs) if isinstance( conversion.referenced_blocks["default_addr"], v4b.ChannelConversion, ): default_addr = conversion.referenced_blocks["default_addr"].name.encode("latin-1") else: default_addr = conversion.referenced_blocks["default_addr"] new_conversion.referenced_blocks["default_addr"] = default_addr conversion = new_conversion else: if not conversion or isinstance(conversion, v4b.ChannelConversion): if copy: conversion = deepcopy(conversion) else: conversion_type = conversion.conversion_type unit_str = conversion.unit_field.decode("latin-1").strip(" \r\n\t\0") match conversion_type: case v3c.CONVERSION_TYPE_NONE: conversion = v4b.ChannelConversion(conversion_type=v4c.CONVERSION_TYPE_NON) case v3c.CONVERSION_TYPE_LINEAR: conversion = v4b.ChannelConversion( conversion_type=v4c.CONVERSION_TYPE_LIN, a=conversion.a, b=conversion.b, ) case v3c.CONVERSION_TYPE_RAT: conversion = v4b.ChannelConversion( conversion_type=v4c.CONVERSION_TYPE_RAT, P1=conversion.P1, P2=conversion.P2, P3=conversion.P3, P4=conversion.P4, P5=conversion.P5, P6=conversion.P6, ) case v3c.CONVERSION_TYPE_FORMULA: formula = conversion.formula conversion = v4b.ChannelConversion(conversion_type=v4c.CONVERSION_TYPE_ALG, formula=formula) case v3c.CONVERSION_TYPE_TAB: v4_kwargs = v4b.ChannelConversionKwargs(conversion_type=v4c.CONVERSION_TYPE_TAB) v4_kwargs["val_param_nr"] = conversion.ref_param_nr * 2 for i in range(conversion.ref_param_nr): v4_kwargs[f"raw_{i}"] = conversion[f"raw_{i}"] # type: ignore[literal-required] v4_kwargs[f"phys_{i}"] = conversion[f"phys_{i}"] # type: ignore[literal-required] conversion = v4b.ChannelConversion(**v4_kwargs) case v3c.CONVERSION_TYPE_TABI: v4_kwargs = v4b.ChannelConversionKwargs(conversion_type=v4c.CONVERSION_TYPE_TABI) v4_kwargs["val_param_nr"] = conversion.ref_param_nr * 2 for i in range(conversion.ref_param_nr): v4_kwargs[f"raw_{i}"] = conversion[f"raw_{i}"] # type: ignore[literal-required] v4_kwargs[f"phys_{i}"] = conversion[f"phys_{i}"] # type: ignore[literal-required] conversion = v4b.ChannelConversion(**v4_kwargs) case v3c.CONVERSION_TYPE_TABX: nr = conversion.ref_param_nr v4_kwargs = { "val_param_nr": nr, "ref_param_nr": nr + 1, "conversion_type": v4c.CONVERSION_TYPE_TABX, } for i in range(nr): v4_kwargs[f"val_{i}"] = conversion[f"param_val_{i}"] # type: ignore[literal-required] v4_kwargs[f"text_{i}"] = conversion[f"text_{i}"] # type: ignore[literal-required] conversion = v4b.ChannelConversion(**v4_kwargs) case v3c.CONVERSION_TYPE_RTABX: nr = conversion.ref_param_nr - 1 v4_kwargs = { "val_param_nr": nr * 2, "ref_param_nr": nr + 1, "conversion_type": v4c.CONVERSION_TYPE_RTABX, "default_addr": typing.cast(bytes, conversion.referenced_blocks["default_addr"]), } for i in range(nr): v4_kwargs[f"lower_{i}"] = conversion[f"lower_{i}"] # type: ignore[literal-required] v4_kwargs[f"upper_{i}"] = conversion[f"upper_{i}"] # type: ignore[literal-required] v4_kwargs[f"text_{i}"] = conversion.referenced_blocks[f"text_{i}"] # type: ignore[literal-required] conversion = v4b.ChannelConversion(**v4_kwargs) conversion.unit = unit_str return conversion def inverse_conversion( conversion: ( ChannelConversionType | v3b.ChannelConversionKwargs | v4b.ChannelConversionKwargs | dict[str, object] | None ), ) -> v4b.ChannelConversion | None: if not conversion: return None if isinstance(conversion, v3b.ChannelConversion): conversion = conversion_transfer(conversion, version=4) conversion_dict: v3b.ChannelConversionKwargs | v4b.ChannelConversionKwargs | dict[str, object] if not isinstance(conversion, dict): conversion_dict = to_dict(conversion) else: conversion_dict = conversion if "a" in conversion_dict: kwargs: v4b.ChannelConversionKwargs = { "conversion_type": v4c.CONVERSION_TYPE_LIN, "a": 1 / typing.cast(float, conversion_dict["a"]), "b": typing.cast(float, conversion_dict["b"]) / typing.cast(float, conversion_dict["a"]), } conv = v4b.ChannelConversion(**kwargs) elif "P1" in conversion_dict: a, b, c, d, e, f = (typing.cast(float, conversion_dict[f"P{i}"]) for i in range(1, 7)) # type: ignore[literal-required] if e == 0 and f == 0: if d == 0 and a == 0: conv = None else: kwargs = { "P1": 0, "P2": e, "P3": -b, "P4": 0, "P5": -d, "P6": a, "conversion_type": v4c.CONVERSION_TYPE_RAT, } conv = v4b.ChannelConversion(**kwargs) elif a == 0 and d == 0: if e == 0 and b == 0: conv = None else: kwargs = { "P1": 0, "P2": -f, "P3": c, "P4": 0, "P5": e, "P6": -b, "conversion_type": v4c.CONVERSION_TYPE_RAT, } conv = v4b.ChannelConversion(**kwargs) else: conv = None return conv @overload def from_dict(conversion_dict: v4b.ChannelConversionKwargs | dict[str, object]) -> v4b.ChannelConversion: ... @overload def from_dict(conversion_dict: None) -> None: ... @overload def from_dict( conversion_dict: v4b.ChannelConversionKwargs | dict[str, object] | None, ) -> v4b.ChannelConversion | None: ... def from_dict(conversion_dict: v4b.ChannelConversionKwargs | dict[str, object] | None) -> v4b.ChannelConversion | None: if not conversion_dict: conversion = None elif "a" in conversion_dict: conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_LIN conversion = v4b.ChannelConversion(**conversion_dict) elif "formula" in conversion_dict: conversion_dict["formula"] = typing.cast(str, conversion_dict["formula"]) conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_ALG conversion = v4b.ChannelConversion(**conversion_dict) elif all(key in conversion_dict for key in [f"P{i}" for i in range(1, 7)]): conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_RAT conversion = v4b.ChannelConversion(**conversion_dict) elif "raw_0" in conversion_dict and "phys_0" in conversion_dict: conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_TAB nr = 0 while f"phys_{nr}" in conversion_dict: nr += 1 conversion_dict["val_param_nr"] = nr * 2 if conversion_dict.get("interpolation", False): conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_TABI else: conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_TAB conversion = v4b.ChannelConversion(**conversion_dict) elif "mask_0" in conversion_dict and "text_0" in conversion_dict: conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_BITFIELD nr = 0 while f"text_{nr}" in conversion_dict: val = conversion_dict[f"text_{nr}"] # type: ignore[literal-required] if isinstance(val, (bytes, str)): partial_conversion: dict[str, object] = { "conversion_type": v4c.CONVERSION_TYPE_RTABX, f"upper_{nr}": conversion_dict[f"upper_{nr}"], # type: ignore[literal-required] f"lower_{nr}": conversion_dict[f"lower_{nr}"], # type: ignore[literal-required] f"text_{nr}": ( text if isinstance((text := typing.cast(bytes | str, conversion_dict[f"text_{nr}"])), bytes) # type: ignore[literal-required] else text.encode("utf-8") ), "default": b"", } conversion_dict[f"text_{nr}"] = from_dict(partial_conversion) # type: ignore[literal-required] elif isinstance(val, dict): conversion_dict[f"text_{nr}"] = from_dict(val) # type: ignore[literal-required] nr += 1 conversion_dict["ref_param_nr"] = nr conversion_dict["val_param_nr"] = nr conversion = v4b.ChannelConversion(**conversion_dict) elif "upper_0" in conversion_dict and "phys_0" in conversion_dict: conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_RTAB nr = 0 while f"phys_{nr}" in conversion_dict: nr += 1 conversion_dict["val_param_nr"] = nr * 3 + 1 conversion = v4b.ChannelConversion(**conversion_dict) elif "val_0" in conversion_dict and "text_0" in conversion_dict: conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_TABX nr = 0 while f"text_{nr}" in conversion_dict: val = conversion_dict[f"text_{nr}"] # type: ignore[literal-required] if isinstance(val, str): conversion_dict[f"text_{nr}"] = val.encode("utf-8") # type: ignore[literal-required] elif isinstance(val, dict): conversion_dict[f"text_{nr}"] = from_dict(val) # type: ignore[literal-required] nr += 1 val = conversion_dict.get("default_addr", b"") if isinstance(val, str): conversion_dict["default_addr"] = val.encode("utf-8") elif isinstance(val, dict): conversion_dict["default_addr"] = from_dict(val) conversion_dict["ref_param_nr"] = nr + 1 conversion = v4b.ChannelConversion(**conversion_dict) elif "upper_0" in conversion_dict and "text_0" in conversion_dict: conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_RTABX nr = 0 while f"text_{nr}" in conversion_dict: val = conversion_dict[f"text_{nr}"] # type: ignore[literal-required] if isinstance(val, str): conversion_dict[f"text_{nr}"] = val.encode("utf-8") # type: ignore[literal-required] elif isinstance(val, dict): conversion_dict[f"text_{nr}"] = from_dict(val) # type: ignore[literal-required] nr += 1 conversion_dict["ref_param_nr"] = nr + 1 val = conversion_dict.get("default_addr", b"") if isinstance(val, str): conversion_dict["default_addr"] = val.encode("utf-8") elif isinstance(val, dict): conversion_dict["default_addr"] = from_dict(val) conversion = v4b.ChannelConversion(**conversion_dict) elif "default_addr" in conversion_dict: conversion_dict["conversion_type"] = v4c.CONVERSION_TYPE_TABX val = conversion_dict["default_addr"] if isinstance(val, str): conversion_dict["default_addr"] = val.encode("utf-8") elif isinstance(val, dict): conversion_dict["default_addr"] = from_dict(val) conversion_dict["ref_param_nr"] = 1 conversion = v4b.ChannelConversion(**conversion_dict) else: conversion = v4b.ChannelConversion(conversion_type=v4c.CONVERSION_TYPE_NON) return conversion @overload def to_dict(conversion: ChannelConversionType) -> dict[str, object]: ... @overload def to_dict(conversion: None) -> None: ... @overload def to_dict(conversion: ChannelConversionType | None) -> dict[str, object] | None: ... def to_dict(conversion: ChannelConversionType | None) -> dict[str, object] | None: if not conversion: return None if isinstance(conversion, v3b.ChannelConversion): conversion_v4 = conversion_transfer(conversion, version=4) else: conversion_v4 = conversion conversion_type = conversion_v4.conversion_type conversion_dict: dict[str, object] = { "name": conversion_v4.name, "unit": conversion_v4.unit, "comment": conversion_v4.comment, } match conversion_type: case v4c.CONVERSION_TYPE_LIN: conversion_dict["a"] = conversion_v4.a conversion_dict["b"] = conversion_v4.b conversion_dict["conversion_type"] = conversion_type case v4c.CONVERSION_TYPE_ALG: conversion_dict["formula"] = conversion_v4.formula conversion_dict["conversion_type"] = conversion_type case v4c.CONVERSION_TYPE_RAT: conversion_dict.update({key: conversion_v4[key] for key in [f"P{i}" for i in range(1, 7)]}) conversion_dict["conversion_type"] = conversion_type case v4c.CONVERSION_TYPE_TAB | v4c.CONVERSION_TYPE_TABI: params = conversion_v4.val_param_nr // 2 conversion_dict.update({key: conversion_v4[key] for key in [f"phys_{nr}" for nr in range(params)]}) conversion_dict.update({key: conversion_v4[key] for key in [f"raw_{nr}" for nr in range(params)]}) conversion_dict["conversion_type"] = conversion_type case v4c.CONVERSION_TYPE_RTAB: params = (conversion_v4.val_param_nr - 1) // 3 conversion_dict.update({key: conversion_v4[key] for key in [f"lower_{nr}" for nr in range(params)]}) conversion_dict.update({key: conversion_v4[key] for key in [f"upper_{nr}" for nr in range(params)]}) conversion_dict.update({key: conversion_v4[key] for key in [f"phys_{nr}" for nr in range(params)]}) conversion_dict["conversion_type"] = conversion_type conversion_dict["default"] = conversion_v4.default case v4c.CONVERSION_TYPE_TABX: nr = conversion_v4.ref_param_nr - 1 conversion_dict["conversion_type"] = conversion_type for key, val in conversion_v4.referenced_blocks.items(): if isinstance(val, str): conversion_dict[key] = val elif isinstance(val, v4b.ChannelConversion): conversion_dict[key] = to_dict(val) elif val is None: conversion_dict[key] = "" else: conversion_dict[key] = val.decode("utf-8", errors="replace") for i in range(nr): conversion_dict[f"val_{i}"] = conversion_v4[f"val_{i}"] case v4c.CONVERSION_TYPE_RTABX: nr = conversion_v4.ref_param_nr - 1 conversion_dict["conversion_type"] = conversion_type for key, val in conversion_v4.referenced_blocks.items(): if isinstance(val, str): conversion_dict[key] = val elif isinstance(val, v4b.ChannelConversion): conversion_dict[key] = to_dict(val) elif val is None: conversion_dict[key] = "" else: conversion_dict[key] = val.decode("utf-8", errors="replace") for i in range(nr): conversion_dict[f"upper_{i}"] = conversion_v4[f"upper_{i}"] conversion_dict[f"lower_{i}"] = conversion_v4[f"lower_{i}"] case _: return None return conversion_dict asammdf-8.5.1/src/asammdf/blocks/cutils.c000066400000000000000000002150221502633300400202560ustar00rootroot00000000000000#define NPY_NO_DEPRECATED_API NPY_1_22_API_VERSION #define PY_SSIZE_T_CLEAN 1 #include #define _FILE_OFFSET_BITS 64 #include "numpy/arrayobject.h" #include "numpy/ndarrayobject.h" #include #include #include #include #include #if defined(_WIN32) #include #include #define FSEEK64(file, address, whence) _fseeki64((file), (address), (whence)) #define FTELL64(file) _ftelli64(file) #else #include #include #include #include #include #define Sleep(x) usleep((int)(1000 * (x))) #define FSEEK64(file, address, whence) fseeko((file), (address), (whence)) #define FTELL64(file) ftello(file) #endif #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define PY_PRINTF(o) \ PyObject_Print(o, stdout, 0); \ printf("\n"); char err_string[1024]; struct rec_info { uint32_t id; uint32_t size; PyObject *mlist; }; struct node { struct node *next; struct rec_info info; }; static PyObject *sort_data_block(PyObject *self, PyObject *args) { uint64_t id_size = 0, position = 0, size; uint32_t rec_size, length, rec_id; PyObject *signal_data, *partial_records, *record_size, *optional, *mlist; PyObject *bts, *key, *value, *rem = NULL; unsigned char *buf, *end, *orig; struct node *head = NULL, *last = NULL, *item; if (!PyArg_ParseTuple(args, "OOOK|O", &signal_data, &partial_records, &record_size, &id_size, &optional)) { return 0; } else { Py_ssize_t pos = 0; position = 0; while (PyDict_Next(record_size, &pos, &key, &value)) { item = malloc(sizeof(struct node)); item->info.id = PyLong_AsUnsignedLong(key); item->info.size = PyLong_AsUnsignedLong(value); item->info.mlist = PyDict_GetItem(partial_records, key); item->next = NULL; if (last) last->next = item; if (!head) head = item; last = item; } buf = (unsigned char *)PyBytes_AsString(signal_data); orig = buf; size = (uint64_t)PyBytes_Size(signal_data); end = buf + size; while ((buf + id_size) < end) { rec_id = 0; for (unsigned char i = 0; i < id_size; i++, buf++) { rec_id += (*buf) << (i << 3); } key = PyLong_FromUnsignedLong(rec_id); value = PyDict_GetItem(record_size, key); if (!value) { rem = PyBytes_FromStringAndSize(NULL, 0); Py_XDECREF(key); return rem; } else { rec_size = PyLong_AsUnsignedLong(value); } mlist = PyDict_GetItem(partial_records, key); if (!mlist) { rem = PyBytes_FromStringAndSize(NULL, 0); Py_XDECREF(key); return rem; } Py_XDECREF(key); if (rec_size) { if (rec_size + position + id_size > size) { break; } bts = PyBytes_FromStringAndSize((const char *)buf, (Py_ssize_t)rec_size); PyList_Append( mlist, bts); Py_XDECREF(bts); buf += rec_size; } else { if (4 + position + id_size > size) { break; } rec_size = (buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0]; length = rec_size + 4; if (position + length + id_size > size) { break; } bts = PyBytes_FromStringAndSize((const char *)buf, (Py_ssize_t)length); PyList_Append(mlist, bts); Py_XDECREF(bts); buf += length; } position = (uint64_t)(buf - orig); } while (head != NULL) { item = head; item->info.mlist = NULL; head = head->next; item->next = NULL; free(item); } head = NULL; last = NULL; item = NULL; mlist = NULL; rem = PyBytes_FromStringAndSize((const char *)(orig + position), (Py_ssize_t)(size - position)); buf = NULL; orig = NULL; end = NULL; return rem; } } static Py_ssize_t calc_size(char *buf) { return (unsigned char)buf[3] << 24 | (unsigned char)buf[2] << 16 | (unsigned char)buf[1] << 8 | (unsigned char)buf[0]; } static PyObject *extract(PyObject *self, PyObject *args) { Py_ssize_t i = 0, count, max = 0, list_count; int64_t offset; Py_ssize_t pos = 0, size = 0; PyObject *signal_data, *is_byte_array, *offsets, *offsets_list = NULL; char *buf; PyArrayObject *vals; PyArray_Descr *descr_init, *descr; unsigned char *addr2; if (!PyArg_ParseTuple(args, "OOO", &signal_data, &is_byte_array, &offsets)) { return 0; } else { Py_ssize_t max_size = 0; Py_ssize_t retval = PyBytes_AsStringAndSize(signal_data, &buf, &max_size); if (retval == -1) { printf("PyBytes_AsStringAndSize error\n"); return NULL; } count = 0; pos = 0; if (offsets == Py_None) { while ((pos + 4) <= max_size) { size = calc_size(&buf[pos]); if ((pos + 4 + size) > max_size) break; if (max < size) max = size; pos += 4 + size; count++; } } else { offsets_list = PyObject_CallMethod(offsets, "tolist", NULL); list_count = (Py_ssize_t)PyList_Size(offsets_list); for (i = 0; i < list_count; i++) { offset = (int64_t)PyLong_AsLongLong(PyList_GetItem(offsets_list, i)); if ((offset + 4) > max_size) break; size = calc_size(&buf[offset]); if ((offset + 4 + size) > max_size) break; if (max < size) max = size; count++; } } if (PyObject_IsTrue(is_byte_array)) { npy_intp dims[2]; dims[0] = count; dims[1] = max; vals = (PyArrayObject *)PyArray_ZEROS(2, dims, NPY_UBYTE, 0); if (offsets == Py_None) { pos = 0; for (i = 0; i < count; i++) { addr2 = (unsigned char *)PyArray_GETPTR2(vals, i, 0); size = calc_size(&buf[pos]); pos += 4; memcpy(addr2, &buf[pos], size); pos += size; } } else { for (i = 0; i < count; i++) { addr2 = (unsigned char *)PyArray_GETPTR2(vals, i, 0); offset = (int64_t)PyLong_AsLongLong(PyList_GetItem(offsets_list, i)); size = calc_size(&buf[offset]); memcpy(addr2, &buf[offset + 4], size); } } } else { npy_intp dims[1]; dims[0] = count; descr_init = PyArray_DescrFromType(NPY_STRING); descr = PyArray_DescrNew(descr_init); Py_XDECREF(descr_init); #if NPY_ABI_VERSION < 0x02000000 descr->elsize = (int)max; #else PyDataType_SET_ELSIZE(descr, max); #endif vals = (PyArrayObject *)PyArray_Zeros(1, dims, descr, 0); if (offsets == Py_None) { pos = 0; for (i = 0; i < count; i++) { addr2 = (unsigned char *)PyArray_GETPTR1(vals, i); size = calc_size(&buf[pos]); pos += 4; memcpy(addr2, &buf[pos], size); pos += size; } } else { for (i = 0; i < count; i++) { addr2 = (unsigned char *)PyArray_GETPTR1(vals, i); offset = (int64_t)PyLong_AsLongLong(PyList_GetItem(offsets_list, i)); size = calc_size(&buf[offset]); memcpy(addr2, &buf[offset + 4], size); } } } if (offsets_list) Py_XDECREF(offsets_list); } return (PyObject *)vals; } static PyObject *lengths(PyObject *self, PyObject *args) { Py_ssize_t i = 0; Py_ssize_t count; PyObject *lst, *values, *item; if (!PyArg_ParseTuple(args, "O", &lst)) { return 0; } else { count = PyList_Size(lst); values = PyTuple_New(count); for (i = 0; i < (Py_ssize_t)count; i++) { item = PyList_GetItem(lst, i); PyTuple_SetItem(values, i, PyLong_FromSsize_t(PyBytes_Size(item))); } } return values; } static PyObject *get_vlsd_offsets(PyObject *self, PyObject *args) { Py_ssize_t i = 0; Py_ssize_t count; PyObject *lst, *item, *result; npy_intp dim[1]; PyArrayObject *values; uint64_t current_size = 0; void *h_result; if (!PyArg_ParseTuple(args, "O", &lst)) { return 0; } else { count = PyList_Size(lst); dim[0] = (Py_ssize_t)count; values = (PyArrayObject *)PyArray_SimpleNew(1, dim, NPY_ULONGLONG); for (i = 0; i < (Py_ssize_t)count; i++) { h_result = PyArray_GETPTR1(values, i); item = PyList_GetItem(lst, i); *((uint64_t *)h_result) = current_size; current_size += (uint64_t)PyBytes_Size(item); } } result = PyTuple_Pack(2, values, PyLong_FromUnsignedLongLong(current_size)); return result; } static PyObject *get_vlsd_max_sample_size(PyObject *self, PyObject *args) { Py_ssize_t i = 0; Py_ssize_t count = 0; PyObject *data, *offsets; uint64_t max_size = 0; uint32_t vlsd_size = 0; char *inptr = NULL, *data_end = NULL, *current_position = NULL; uint64_t current_size = 0, *offsets_array; if (!PyArg_ParseTuple(args, "OOn", &data, &offsets, &count)) { return 0; } else { offsets_array = (uint64_t *)PyArray_GETPTR1((PyArrayObject *)offsets, 0); inptr = PyBytes_AsString(data); data_end = inptr + PyBytes_Size(data); for (i = 0; i < count; i++, offsets_array++) { current_position = inptr + *offsets_array; if (current_position >= data_end) { return PyLong_FromUnsignedLongLong(max_size); } memcpy(&vlsd_size, inptr + *offsets_array, 4); if (vlsd_size > max_size) { max_size = vlsd_size; } } } return PyLong_FromUnsignedLongLong(max_size); } void positions_char(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { char min, max, *indata; int32_t *outdata; Py_ssize_t pos_min = 0, pos_max = 0; indata = (char *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); char *ps; double tmin, tmax, *ts, *pt; ps = (char *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_short(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { short min, max, *indata; int32_t *outdata; Py_ssize_t pos_min = 0, pos_max = 0; indata = (short *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); short *ps; double tmin, tmax, *ts, *pt; ps = (short *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_long(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { int32_t min, max, *indata; int32_t *outdata; Py_ssize_t pos_min = 0, pos_max = 0; indata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); int32_t *ps; double tmin, tmax, *ts, *pt; ps = (int32_t *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_long_long(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { int64_t min, max, *indata; int32_t *outdata; Py_ssize_t pos_min = 0, pos_max = 0; indata = (int64_t *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); int64_t *ps; double tmin, tmax, *ts, *pt; ps = (int64_t *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_unsigned_char(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { unsigned char min, max, *indata; int32_t *outdata; Py_ssize_t pos_min = 0, pos_max = 0; indata = (unsigned char *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); unsigned char *ps; double tmin, tmax, *ts, *pt; ps = (unsigned char *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_unsigned_short(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { unsigned short min, max, *indata; int32_t *outdata; Py_ssize_t pos_min = 0, pos_max = 0; indata = (unsigned short *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); unsigned short *ps; double tmin, tmax, *ts, *pt; ps = (unsigned short *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_unsigned_long(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { uint32_t min, max, *indata; int32_t *outdata; Py_ssize_t pos_min = 0, pos_max = 0; indata = (uint32_t *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); uint32_t *ps; double tmin, tmax, *ts, *pt; ps = (uint32_t *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_unsigned_long_long(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { uint64_t min, max, *indata; int32_t *outdata; Py_ssize_t pos_min = 0, pos_max = 0; indata = (uint64_t *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); uint64_t *ps; double tmin, tmax, *ts, *pt; ps = (uint64_t *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_float(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { float min, max, *indata = NULL; int32_t *outdata = NULL; Py_ssize_t pos_min = 0, pos_max = 0; indata = (float *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); float *ps; double tmin, tmax, *ts, *pt; ps = (float *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } void positions_double(PyObject *samples, PyObject *timestamps, PyObject *plot_samples, PyObject *plot_timestamps, PyObject *result, int32_t step, int32_t count, int32_t last) { double min, max, *indata = NULL; int32_t *outdata = NULL; Py_ssize_t pos_min = 0, pos_max = 0; indata = (double *)PyArray_GETPTR1((PyArrayObject *)samples, 0); outdata = (int32_t *)PyArray_GETPTR1((PyArrayObject *)result, 0); double *ps = NULL; double tmin, tmax, *ts = NULL, *pt = NULL; ps = (double *)PyArray_GETPTR1((PyArrayObject *)plot_samples, 0); pt = (double *)PyArray_GETPTR1((PyArrayObject *)plot_timestamps, 0); ts = (double *)PyArray_GETPTR1((PyArrayObject *)timestamps, 0); Py_ssize_t current_pos = 0, stop_index = count - 1; for (Py_ssize_t i = 0; i < (Py_ssize_t)count; i++) { pos_min = current_pos; pos_max = current_pos; min = max = *indata; indata++; current_pos++; tmin = tmax = *ts; ts++; if ((i != stop_index) || (0 != last)) { for (Py_ssize_t j = 1; j < step; j++, indata++, ts++) { if (*indata < min) { min = *indata; pos_min = current_pos; tmin = *ts; } else if (*indata > max) { max = *indata; pos_max = current_pos; tmax = *ts; } current_pos++; if ((i == stop_index) && (j == last)) break; } } if (pos_min < pos_max) { *outdata++ = pos_min; *outdata++ = pos_max; *ps++ = min; *pt++ = tmin; *ps++ = max; *pt++ = tmax; } else { *outdata++ = pos_max; *outdata++ = pos_min; *ps++ = max; *pt++ = tmax; *ps++ = min; *pt++ = tmin; } } } static PyObject *positions(PyObject *self, PyObject *args) { int32_t count, step, last; unsigned char itemsize; char *kind; Py_ssize_t _size; PyObject *samples, *timestamps, *result, *step_obj, *count_obj, *last_obj, *plot_samples, *plot_timestamps; if (!PyArg_ParseTuple(args, "OOOOOOOOs#B", &samples, ×tamps, &plot_samples, &plot_timestamps, &result, &step_obj, &count_obj, &last_obj, &kind, &_size, &itemsize)) { return NULL; } else { count = PyLong_AsLong(count_obj); step = PyLong_AsLong(step_obj); last = PyLong_AsLong(last_obj) - 1; if (kind[0] == 'u') { if (itemsize == 1) positions_unsigned_char(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); else if (itemsize == 2) positions_unsigned_short(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); else if (itemsize == 4) positions_unsigned_long(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); else positions_unsigned_long_long(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); } else if (kind[0] == 'i') { if (itemsize == 1) positions_char(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); else if (itemsize == 2) positions_short(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); else if (itemsize == 4) positions_long(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); else positions_long_long(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); } else if (kind[0] == 'f') { if (itemsize == 4) positions_float(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); else positions_double(samples, timestamps, plot_samples, plot_timestamps, result, step, count, last); } Py_INCREF(Py_None); return Py_None; } } static PyObject *get_channel_raw_bytes(PyObject *self, PyObject *args) { Py_ssize_t count, size, actual_byte_count, delta; PyObject *data_block, *out; Py_ssize_t record_size, byte_offset, byte_count; char *inptr, *outptr; if (!PyArg_ParseTuple(args, "Onnn", &data_block, &record_size, &byte_offset, &byte_count)) { return 0; } else { if (PyBytes_Check(data_block)) { size = PyBytes_Size(data_block); inptr = PyBytes_AsString(data_block); } else { size = PyByteArray_Size(data_block); inptr = PyByteArray_AsString(data_block); } if (!record_size) { out = PyByteArray_FromStringAndSize(NULL, 0); } else if (record_size < byte_offset + byte_count) { delta = byte_offset + byte_count - record_size; actual_byte_count = record_size - byte_offset; count = size / record_size; out = PyByteArray_FromStringAndSize(NULL, count * byte_count); outptr = PyByteArray_AsString(out); inptr += byte_offset; for (Py_ssize_t i = 0; i < count; i++) { for (Py_ssize_t j = 0; j < actual_byte_count; j++) *outptr++ = *inptr++; inptr += record_size - actual_byte_count; for (Py_ssize_t j = 0; j < delta; j++) { *outptr++ = '\0'; } } } else { count = size / record_size; out = PyByteArray_FromStringAndSize(NULL, count * byte_count); outptr = PyByteArray_AsString(out); inptr += byte_offset; delta = record_size - byte_count; for (Py_ssize_t i = 0; i < count; i++) { for (Py_ssize_t j = 0; j < byte_count; j++) *outptr++ = *inptr++; inptr += delta; } } data_block = NULL; return out; } } static PyObject *get_invalidation_bits_array(PyObject *self, PyObject *args) { Py_ssize_t count, size, actual_byte_count, delta, invalidation_pos, invalidation_size; PyObject *data_block, *out; Py_ssize_t record_size, byte_offset, byte_count; uint8_t mask, *inptr, *outptr; if (!PyArg_ParseTuple(args, "Onn", &data_block, &invalidation_size, &invalidation_pos)) { return 0; } else { if (PyBytes_Check(data_block)) { size = PyBytes_Size(data_block); inptr = (uint8_t *)PyBytes_AsString(data_block); } else { size = PyByteArray_Size(data_block); inptr = (uint8_t *)PyByteArray_AsString(data_block); } count = size / invalidation_size; byte_offset = invalidation_pos / 8; mask = (uint8_t ) (1 << (invalidation_pos % 8)); inptr += byte_offset; npy_intp dims[1]; dims[0] = count; out = PyArray_EMPTY(1, dims, NPY_BOOL, 0); outptr = (uint8_t *)PyArray_GETPTR1((PyArrayObject *)out, 0); for (int i=0; icount; thread_idx = indata->idx; thread_count = indata->thread_count; data = indata->data; for (Py_ssize_t i = 0; irecord_size < data->byte_offset + data->byte_count) { inptr = data->inptr; delta = data->byte_offset + data->byte_count - data->record_size; actual_byte_count = data->record_size - data->byte_offset; count = data->cycles; outptr = data->outptr; inptr += data->byte_offset; for (Py_ssize_t i = 0; i < count; i++) { for (Py_ssize_t j = 0; j < actual_byte_count; j++) *outptr++ = *inptr++; inptr += data->record_size - actual_byte_count; for (Py_ssize_t j = 0; j < delta; j++) { *outptr++ = 0; } } } else { inptr = data->inptr; count = data->cycles; outptr = data->outptr; inptr += data->byte_offset; delta = data->record_size - data->byte_count; for (Py_ssize_t i = 0; i < count; i++) { for (Py_ssize_t j = 0; j < data->byte_count; j++) *outptr++ = *inptr++; inptr += delta; } } for (Py_ssize_t i = 0; icount; thread_idx = indata->idx; data = indata->data; thread_count= indata->thread_count; for (Py_ssize_t i = 0; irecord_size; step = record_size - data->byte_count; cycles = data->cycles; byte_count = data->byte_count; inptr = data->inptr; if (!record_size) continue; outptr = data->outptr + data->byte_offset; for (Py_ssize_t i=0; i size) size = current_size; } return PyLong_FromSsize_t(size); } } void transpose(uint8_t * restrict dst, uint8_t * restrict src, uint64_t p, uint64_t n, size_t block) { for (size_t i = 0; i < n; i += block) { for(size_t j = 0; j < p; ++j) { for(size_t b = 0; b < block && i + b < n; ++b) { dst[j*n + i + b] = src[(i + b)*p + j]; } } } } typedef struct InfoBlock { int64_t address; int64_t original_size; int64_t compressed_size; int64_t block_limit; int64_t record_offset; Py_ssize_t param; Py_ssize_t block_type; Py_ssize_t idx; Py_ssize_t count; } InfoBlock, *PtrInfoBlock; typedef struct SignalInfo { int64_t byte_offset; int64_t byte_count; int32_t invalidation_bit_position; uint8_t *data; PyObject *obj; } SignalInfo, *PtrSignalInfo; typedef struct ProcessesingBlock { uint8_t stop; uint8_t * inptr; PtrInfoBlock block_info; struct SignalInfo *signals; Py_ssize_t signal_count; Py_ssize_t record_size; Py_ssize_t idx; #if defined(_WIN32) HANDLE bytes_ready; HANDLE block_ready; #else pthread_cond_t bytes_ready; pthread_cond_t block_ready; pthread_mutex_t bytes_ready_lock; pthread_mutex_t block_ready_lock; #endif } ProcessesingBlock, *PtrProcessesingBlock; void * get_channel_raw_bytes_complete_C(void *lpParam ) { Py_ssize_t count, byte_count, byte_offset, delta, thread_count, param, block_type; int64_t original_size, compressed_size, record_offset, block_limit, cycles, current_uncompressed_size=0, current_out_size=0, max_cycles=0; PtrProcessesingBlock thread_info; thread_info = (PtrProcessesingBlock) lpParam; PtrInfoBlock block_info; Py_ssize_t signal_count, thread_idx, record_size, in_size, cols, lines; record_size = thread_info->record_size; int result; clock_t start, end; double t1=0, t2=0, t3=0, t4=0, t5=0, t6=0, t7=0; uint8_t *outptr, *inptr, *write; uint8_t *pUncomp=NULL, *pUncompTr=NULL, *read, *data_ptr; inptr = thread_info->inptr; while (1) { #if defined(_WIN32) start = clock(); WaitForSingleObject(thread_info->block_ready, INFINITE); ResetEvent(thread_info->block_ready); end = clock(); t3 += end - start; if (thread_info->stop) break; /* printf("Thr %d processing\n", thread_info->idx); printf("Block type=%d\n", thread_info->block_info->block_type); printf("Block limit=%d\n", thread_info->block_info->block_limit); printf("Block original_size%d\n", thread_info->block_info->original_size); printf("Block compressed_size=%d\n", thread_info->block_info->compressed_size); printf("Block param=%d\n", thread_info->block_info->param); printf("Block record_offset=%d\n", thread_info->block_info->record_offset); */ #else pthread_mutex_lock(&thread_info->block_ready_lock); pthread_cond_wait(&thread_info->block_ready, &thread_info->block_ready_lock); pthread_mutex_unlock(&thread_info->block_ready_lock); #endif original_size = thread_info->block_info->original_size; compressed_size = thread_info->block_info->compressed_size; param = thread_info->block_info->param; block_type = thread_info->block_info->block_type; record_offset = thread_info->block_info->record_offset; count = original_size / record_size; if (thread_info->block_info->block_limit >= 0) { cycles = thread_info->block_info->block_limit / record_size ; } else { cycles = count; } if (block_type == 0) { data_ptr = inptr; } else { // decompress if (original_size > current_uncompressed_size) { //printf("\tThr %d new ptr\n", thread_info->idx); if (pUncomp) free(pUncomp); pUncomp = (uint8_t *) malloc(original_size); //if (!pUncomp) printf("\tThr %d pUncomp error\n", thread_info->idx); current_uncompressed_size=original_size; } //printf("\tThr %d start decompress %p %d\n", thread_info->idx, inptr, compressed_size); struct libdeflate_decompressor *decompressor = libdeflate_alloc_decompressor(); libdeflate_zlib_decompress(decompressor, inptr, compressed_size, pUncomp, original_size, NULL); libdeflate_free_decompressor(decompressor); //printf("\tThr %d decmpressed\n", thread_info->idx); // reverse transposition if (block_type == 2) { cols = param; lines = original_size / cols; if (current_out_size < original_size) { //printf("\tThr %d new trtrtrptr\n", thread_info->idx); if (pUncompTr) free(pUncompTr); pUncompTr = (uint8_t *) malloc(original_size); //if (!pUncompTr) printf("\tThr %d pUncompTr error\n", thread_info->idx); current_out_size = original_size; } start = clock(); read = pUncomp; for (int j = 0; j < (Py_ssize_t)cols; j++) { write = pUncompTr + j; for (int i = 0; i < (Py_ssize_t)lines; i++) { *write = *read++; write += cols; } } end = clock(); t7 += end - start; data_ptr = pUncompTr; //printf("\tThr %d transposed\n", thread_info->idx); } else { data_ptr = pUncomp; } } //printf("\tThr %d %d %d\n", thread_info->idx, cycles, max_cycles); for (int i =0; isignal_count; i++) { byte_offset = thread_info->signals[i].byte_offset; byte_count = thread_info->signals[i].byte_count; read = data_ptr + byte_offset; write = thread_info->signals[i].data + record_offset * byte_count; for (Py_ssize_t j = 0; j < cycles; j++) { memcpy(write, read, byte_count); write += byte_count; read += record_size; } } //printf("\tThr %d set event\n", thread_info->idx); #if defined(_WIN32) SetEvent(thread_info->bytes_ready); #else pthread_mutex_lock(&thread_info->bytes_ready_lock); pthread_cond_signal(&thread_info->bytes_ready); pthread_mutex_unlock(&thread_info->bytes_ready_lock); #endif } if (pUncomp) free(pUncomp); if (pUncompTr) free(pUncompTr); //printf("t1=%lf t2=%lf t3=%lf t4=%lf t5=%lf t6=%lf t7=%lf\n", t1, t2, t3, t4, t5, t6, t7); return 0; } static PyObject *get_channel_raw_bytes_complete(PyObject *self, PyObject *args) { Py_ssize_t info_count, signal_count, signal_and_invalidation_count, thread_count=11; PyObject *data_blocks_info, *signals, *out = NULL, *item, *ref, *obj, *group_index, *InvalidationArray; char *outptr, *file_name; char *read_pos = NULL, *write_pos = NULL; Py_ssize_t position = 0, record_size = 0, cycles, step = 0, invalidation_bytes; Py_ssize_t isize = 0, offset = 0; int is_list; int64_t byte_offset, byte_count, new_cycles, max_uncompressed=0, max_compressed=0, record_offset=0; int32_t invalidation_bit_position; PtrInfoBlock block_info; InfoBlock info_block; PtrProcessesingBlock thread_info; PtrProcessesingBlock thread; FILE *fptr; uint8_t *buffer; int result; clock_t start, end; double tt=0; if (!PyArg_ParseTuple(args, "OOsnnnO|n", &data_blocks_info, &signals, &file_name, &cycles, &record_size, &invalidation_bytes, &group_index, &thread_count)) { return NULL; } else { ref = PyImport_ImportModule("asammdf"); InvalidationArray = PyObject_GetAttrString(ref, "InvalidationArray"); Py_XDECREF(ref); //fptr = fopen(file_name,"rb"); #if defined(_WIN32) TCHAR *lpFileName = TEXT(file_name); HANDLE hFile; HANDLE hMap; LPVOID lpBasePtr; LARGE_INTEGER liFileSize; hFile = CreateFile(lpFileName, GENERIC_READ, // dwDesiredAccess FILE_SHARE_READ, // dwShareMode NULL, // lpSecurityAttributes OPEN_EXISTING, // dwCreationDisposition FILE_FLAG_RANDOM_ACCESS, // dwFlagsAndAttributes 0); // hTemplateFile if (hFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFile failed with error %d\n", GetLastError()); return 1; } if (!GetFileSizeEx(hFile, &liFileSize)) { fprintf(stderr, "GetFileSize failed with error %d\n", GetLastError()); CloseHandle(hFile); return 1; } if (liFileSize.QuadPart == 0) { fprintf(stderr, "File is empty\n"); CloseHandle(hFile); return 1; } hMap = CreateFileMapping( hFile, NULL, // Mapping attributes PAGE_READONLY, // Protection flags 0, // MaximumSizeHigh 0, // MaximumSizeLow NULL); // Name if (hMap == 0) { fprintf(stderr, "CreateFileMapping failed with error %d\n", GetLastError()); CloseHandle(hFile); return 1; } lpBasePtr = MapViewOfFile( hMap, FILE_MAP_READ, // dwDesiredAccess 0, // dwFileOffsetHigh 0, // dwFileOffsetLow 0); // dwNumberOfBytesToMap if (lpBasePtr == NULL) { fprintf(stderr, "MapViewOfFile failed with error %d\n", GetLastError()); CloseHandle(hMap); CloseHandle(hFile); return 1; } HANDLE *hThreads, *block_ready, *bytes_ready; DWORD *dwThreadIdArray; hThreads = (HANDLE *) malloc(sizeof(HANDLE) * thread_count); dwThreadIdArray = (DWORD *) malloc(sizeof(DWORD) * thread_count); block_ready = (HANDLE *) malloc(sizeof(HANDLE) * thread_count); bytes_ready = (HANDLE *) malloc(sizeof(HANDLE) * thread_count); #else int fdin = open(file_name, O_RDONLY); struct stat statbuf; uint8_t * lpBasePtr; fstat (fdin, &statbuf); lpBasePtr = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0); pthread_t *dwThreadIdArray = (pthread_t *) malloc(sizeof(pthread_t) * thread_count); pthread_mutex_t *bytes_ready_locks, *block_ready_locks; // Declare mutex pthread_cond_t *block_ready, *bytes_ready; block_ready = (pthread_cond_t *) malloc(sizeof(pthread_cond_t) * thread_count); bytes_ready = (pthread_cond_t *) malloc(sizeof(pthread_cond_t) * thread_count); bytes_ready_locks = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t) * thread_count); block_ready_locks = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t) * thread_count); #endif PtrSignalInfo signal_info; is_list = PyList_Check(signals); if (is_list) { signal_count = PyList_Size(signals); } else { signal_count = PyTuple_Size(signals); } if (invalidation_bytes) { signal_and_invalidation_count = signal_count +1; signal_info = (PtrSignalInfo) malloc(sizeof(SignalInfo) * (signal_count + 1)); if (!signal_info) { PyErr_SetString(PyExc_ValueError, "Memmory allocation error for signal_info\n\0"); return NULL; } } else { signal_and_invalidation_count = signal_count; signal_info = (PtrSignalInfo) malloc(sizeof(SignalInfo) * signal_count); if (!signal_info) { PyErr_SetString(PyExc_ValueError, "Memmory allocation error for signal_info\n\0"); return NULL; } } for (int i=0; i= thread_count) { #if defined(_WIN32) start = clock(); WaitForSingleObject(bytes_ready[position], INFINITE); end = clock(); tt += end - start; ResetEvent(bytes_ready[position]); #else pthread_mutex_lock(&bytes_ready_locks[position]); pthread_cond_wait(&bytes_ready[position], &bytes_ready_locks[position]); pthread_mutex_unlock(&bytes_ready_locks[position]); #endif } thread->block_info = &block_info[i]; thread->block_info->record_offset = record_offset; record_offset += block_info[i].original_size / record_size; memcpy(thread->inptr, ((uint8_t*)lpBasePtr) + block_info[i].address, block_info[i].compressed_size); //FSEEK64(fptr, block_info[i].address, 0); //result = fread(thread->inptr, 1, block_info[i].compressed_size, fptr); #if defined(_WIN32) SetEvent(block_ready[position]); #else pthread_mutex_lock(&block_ready_locks[position]); pthread_cond_signal(&block_ready[position]); pthread_mutex_unlock(&block_ready_locks[position]); #endif position++; if (position == thread_count) position = 0; } //printf("TT=%lf\n", tt); for (int i=0; istop = 1; #if defined(_WIN32) SetEvent(block_ready[position]); #else pthread_mutex_lock(&block_ready_locks[position]); pthread_cond_signal(&block_ready[position]); pthread_mutex_unlock(&block_ready_locks[position]); #endif position++; if (position == thread_count) position = 0; } #if defined(_WIN32) UnmapViewOfFile(lpBasePtr); CloseHandle(hMap); CloseHandle(hFile); WaitForMultipleObjects(thread_count, hThreads, true, INFINITE); for (int i=0; i< thread_count; i++) { CloseHandle(hThreads[i]); CloseHandle(block_ready[i]); CloseHandle(bytes_ready[i]); } #else munmap(lpBasePtr, statbuf.st_size); close(fdin); for (int i=0; i< thread_count; i++) { pthread_join(dwThreadIdArray[i], NULL); } #endif for (int i=0; i bytes: ... def extract(signal_data: bytes, is_byte_array: bool, offsets: NDArray[np.uintp]) -> NDArray[np.uint8]: ... def get_vlsd_max_sample_size(data: bytes, offsets: NDArray[np.uint64], count: int) -> int: ... def get_channel_raw_bytes( data_block: bytes | bytearray, record_size: int, byte_offset: int, byte_count: int ) -> bytearray: ... def get_invalidation_bits_array( data_block: bytes | bytearray, invalidation_size: int, invalidation_pos: int ) -> NDArray[np.uint8]: ... def get_channel_raw_bytes_parallel( data_block: bytes | bytearray, record_size: int, signals: list[list[int]], thread_count: int = 11 ) -> list[bytearray]: ... def data_block_from_arrays( data_blocks: list[tuple[bytes | NDArray[Any], int]], cycles_obj: int, thread_count: int = 11 ) -> bytearray: ... def bytes_dtype_size(ret: NDArray[Any]) -> int: ... def get_channel_raw_bytes_complete( data_blocks_info: list[DataBlockInfo], signals: list[tuple[int, int, int]], file_name: str, cycles: int, record_size: int, invalidation_bytes: int, group_index: int, thread_count: int = 11, ) -> tuple[tuple[bytearray, InvalidationArray | None], ...]: ... asammdf-8.5.1/src/asammdf/blocks/mdf_common.py000066400000000000000000000265551502633300400213120ustar00rootroot00000000000000from abc import ABC from collections import defaultdict from collections.abc import Callable, Iterable, Iterator import logging from pathlib import Path from typing import Generic import numpy as np from numpy.typing import DTypeLike, NDArray from typing_extensions import Any, Required, TypedDict, TypeVar from . import v2_v3_blocks as v3b from . import v4_blocks as v4b from .types import DbcFileType, StrPath from .utils import ( ChannelsDB, DataBlockInfo, EMPTY_TUPLE, MdfException, SignalDataBlockInfo, ) logger = logging.getLogger("asammdf") __all__ = ["MDF_Common"] class MdfKwargs(TypedDict, total=False): temporary_folder: StrPath | None raise_on_multiple_occurrences: bool use_display_names: bool fill_0_for_missing_computation_channels: bool remove_source_from_channel_names: bool password: str | None progress: Callable[[int, int], None] | Any callback: Callable[[int, int], None] | Any class MdfCommonKwargs(MdfKwargs, total=False): original_name: Required[str | Path | None] __internal__: bool _DG = TypeVar("_DG", v3b.DataGroup, v4b.DataGroup) _CG = TypeVar("_CG", v3b.ChannelGroup, v4b.ChannelGroup) _CN = TypeVar("_CN", v3b.Channel, v4b.Channel) _CD = TypeVar("_CD", v3b.ChannelDependency, list[v4b.ChannelArrayBlock] | list[tuple[int, int]]) _ST = TypeVar("_ST", list[int], list[int] | list[tuple[int, int]] | np.dtype[Any]) class Group(Generic[_DG, _CG, _CN, _CD, _ST]): __slots__ = ( "channel_dependencies", "channel_group", "channels", "data_blocks", "data_blocks_info_generator", "data_group", "data_location", "index", "read_split_count", "record", "record_size", "signal_data", "signal_types", "single_channel_dtype", "sorted", "string_dtypes", "trigger", "uses_ld", "uuid", ) def __init__(self, data_group: _DG) -> None: self.data_group: _DG = data_group self.channel_group: _CG self.channels: list[_CN] = [] self.channel_dependencies: list[_CD | None] = [] self.signal_data: list[tuple[list[SignalDataBlockInfo], Iterator[SignalDataBlockInfo]] | None] = [] self.record: list[tuple[np.dtype[Any], int, int, int] | None] | None = None self.record_size: dict[int, int] = {} self.trigger: v3b.TriggerBlock | None = None self.sorted: bool self.string_dtypes: list[np.dtype[np.bytes_]] = [] self.data_blocks: list[DataBlockInfo] = [] self.signal_types: _ST self.single_channel_dtype: DTypeLike | None = None self.uses_ld = False self.read_split_count = 0 self.data_blocks_info_generator: Iterator[DataBlockInfo] = iter(EMPTY_TUPLE) self.uuid = "" self.data_location: int self.index = 0 def set_blocks_info(self, info: list[DataBlockInfo]) -> None: self.data_blocks = info def __contains__(self, item: str) -> bool: return hasattr(self, item) def clear(self) -> None: self.data_blocks.clear() self.channels.clear() self.channel_dependencies.clear() self.signal_data.clear() self.data_blocks_info_generator = iter(()) def get_data_blocks(self) -> Iterator[DataBlockInfo]: yield from self.data_blocks while True: try: info = next(self.data_blocks_info_generator) self.data_blocks.append(info) yield info except StopIteration: break def get_signal_data_blocks(self, index: int) -> Iterator[SignalDataBlockInfo]: signal_data = self.signal_data[index] if signal_data is not None: signal_data_blocks, signal_generator = signal_data yield from signal_data_blocks while True: try: info = next(signal_generator) signal_data_blocks.append(info) yield info except StopIteration: break def load_all_data_blocks(self) -> None: for _ in self.get_data_blocks(): continue GroupV3 = Group[v3b.DataGroup, v3b.ChannelGroup, v3b.Channel, v3b.ChannelDependency, list[int]] GroupV4 = Group[ v4b.DataGroup, v4b.ChannelGroup, v4b.Channel, list[v4b.ChannelArrayBlock] | list[tuple[int, int]], list[int] | list[tuple[int, int]] | np.dtype[Any], ] _Group = TypeVar("_Group", GroupV3, GroupV4) class MDF_Common(ABC, Generic[_Group]): """Common methods for MDF objects.""" def __init__(self, raise_on_multiple_occurrences: bool) -> None: self.groups: list[_Group] = [] self.channels_db = ChannelsDB() self._raise_on_multiple_occurrences = raise_on_multiple_occurrences def _set_temporary_master(self, master: NDArray[Any] | None) -> None: self._master = master # @lru_cache(maxsize=1024) def _validate_channel_selection( self, name: str | None = None, group: int | None = None, index: int | None = None, ) -> tuple[int, int]: """Validate channel selection. The channel can be specified in two ways: * Using the first positional argument `name`. * If there are multiple occurrences for this channel, then the `group` and `index` arguments can be used to select a specific group. * If there are multiple occurrences for this channel and either the `group` or `index` arguments is None, then a warning is issued. * Using the group number (keyword argument `group`) and the channel number (keyword argument `index`). Use `info` method for group and channel numbers. Parameters ---------- name : str, optional Name of channel. group : int, optional 0-based group index. index : int, optional 0-based channel index. Returns ------- group_index, channel_index : (int, int) Selected channel's group and channel index. Raises ------ MdfException * if the channel name is not found * if the group index is out of range * if the channel index is out of range * if there are multiple channel occurrences in the file and the arguments `name`, `group`, `index` are ambiguous. This behaviour can be turned off by setting `raise_on_multiple_occurrences` to False. """ if name is None: if group is None or index is None: message = 'Invalid arguments for channel selection: must give "name" or, "group" and "index"' raise MdfException(message) else: gp_nr, ch_nr = group, index if ch_nr >= 0: try: grp = self.groups[gp_nr] except IndexError: raise MdfException("Group index out of range") from None try: grp.channels[ch_nr] except IndexError: raise MdfException(f"Channel index out of range: {(name, group, index)}") from None else: if name not in self.channels_db: raise MdfException(f'Channel "{name}" not found') else: if group is None: entries = self.channels_db[name] if len(entries) > 1: if self._raise_on_multiple_occurrences: message = ( f'Multiple occurrences for channel "{name}": {entries}. ' 'Provide both "group" and "index" arguments' " to select another data group" ) logger.exception(message) raise MdfException(message) else: message = ( f'Multiple occurrences for channel "{name}": {entries}. ' "Returning the first occurrence since the MDF object was " "configured to not raise an exception in this case." ) logger.warning(message) gp_nr, ch_nr = entries[0] else: gp_nr, ch_nr = entries[0] else: if index is not None and index < 0: gp_nr = group ch_nr = index else: if index is None: entries = tuple((gp_nr, ch_nr) for gp_nr, ch_nr in self.channels_db[name] if gp_nr == group) count = len(entries) if count == 1: gp_nr, ch_nr = entries[0] elif count == 0: message = f'Channel "{name}" not found in group {group}' raise MdfException(message) else: if self._raise_on_multiple_occurrences: message = ( f'Multiple occurrences for channel "{name}": {entries}. ' 'Provide both "group" and "index" arguments' " to select another data group" ) logger.exception(message) raise MdfException(message) else: message = ( f'Multiple occurrences for channel "{name}": {entries}. ' "Returning the first occurrence since the MDF object was " "configured to not raise an exception in this case." ) logger.warning(message) gp_nr, ch_nr = entries[0] else: if (group, index) in self.channels_db[name]: ch_nr = index gp_nr = group else: message = f'Channel "{name}" not found in group {group} at index {index}' raise MdfException(message) return gp_nr, ch_nr class _BusInfo(TypedDict): dbc_files: Iterable[DbcFileType] unknown_id_count: int class CanInfo(_BusInfo): total_unique_ids: set[tuple[int, bool]] not_found_ids: defaultdict[StrPath, list[tuple[tuple[int, bool] | int, str]]] found_ids: defaultdict[StrPath, set[tuple[tuple[int, int, bool], str]]] unknown_ids: set[int | tuple[int, bool]] max_flags: list[list[list[bool]]] class LinInfo(_BusInfo): total_unique_ids: set[tuple[int, ...]] not_found_ids: defaultdict[StrPath, list[tuple[int, str]]] found_ids: defaultdict[StrPath, set[tuple[tuple[int, bool, bool], str]]] unknown_ids: set[int] class LastCallInfo(TypedDict, total=False): CAN: CanInfo LIN: LinInfo asammdf-8.5.1/src/asammdf/blocks/mdf_v2.py000066400000000000000000000016341502633300400203400ustar00rootroot00000000000000"""ASAM MDF version 2 file format module""" from typing_extensions import Unpack from .mdf_v3 import Kwargs, MDF3 from .types import StrPath from .utils import FileLike, MdfException, validate_version_argument from .v2_v3_constants import Version2 __all__ = ["MDF2"] # MDF versions 2 and 3 share the same implementation class MDF2(MDF3): """Shared implementation for MDF version 2 and 3.""" def __init__( self, name: StrPath | FileLike | None = None, version: Version2 = "2.14", channels: list[str] | None = None, **kwargs: Unpack[Kwargs], ) -> None: version = validate_version_argument(version, hint=2) if not kwargs.get("__internal__", False): raise MdfException("Always use the MDF class; do not use the class MDF2 directly") super().__init__(name, version, channels=channels, **kwargs) if __name__ == "__main__": pass asammdf-8.5.1/src/asammdf/blocks/mdf_v3.py000066400000000000000000004274611502633300400203530ustar00rootroot00000000000000"""ASAM MDF version 3 file format module""" from collections import defaultdict from collections.abc import Callable, Iterable, Iterator, Sequence from copy import deepcopy from datetime import datetime from functools import lru_cache from itertools import product import logging from math import ceil import mmap import os from pathlib import Path import sys from tempfile import NamedTemporaryFile import time from traceback import format_exc import typing from typing import BinaryIO, IO, Literal, TYPE_CHECKING import xml.etree.ElementTree as ET import numpy as np from numpy import ( arange, array, array_equal, ascontiguousarray, column_stack, concatenate, float32, float64, frombuffer, linspace, searchsorted, uint16, unique, zeros, ) from numpy.typing import ArrayLike, DTypeLike, NDArray from pandas import DataFrame from typing_extensions import Any, Buffer, overload, SupportsBytes, TypedDict, Unpack from .. import tool from ..signal import Signal from . import mdf_common, utils from . import v2_v3_constants as v23c from .conversion_utils import conversion_transfer from .cutils import data_block_from_arrays, get_channel_raw_bytes from .mdf_common import MDF_Common, MdfCommonKwargs from .options import GLOBAL_OPTIONS from .source_utils import Source from .types import ChannelsType, CompressionType, RasterType, StrPath from .utils import ( as_non_byte_sized_signed_int, CHANNEL_COUNT, CONVERT, count_channel_groups, DataBlockInfo, FileLike, fmt_to_datatype_v3, get_fmt_v3, get_text_v3, is_file_like, MdfException, Terminated, UniqueDB, validate_version_argument, VirtualChannelGroup, ) from .v2_v3_blocks import ( Channel, ChannelConversion, ChannelConversionKwargs, ChannelDependency, ChannelDependencyKwargs, ChannelExtension, ChannelExtensionKwargs, ChannelGroup, ChannelGroupKwargs, ChannelKwargs, DataGroup, DataGroupKwargs, FileIdentificationBlock, HeaderBlock, TextBlock, TriggerBlock, ) from .v2_v3_constants import Version, Version2 if TYPE_CHECKING: from ..mdf import MDF try: decode = np.strings.decode encode = np.strings.encode except: decode = np.char.decode encode = np.char.encode logger = logging.getLogger("asammdf") __all__ = ["MDF3"] Group = mdf_common.GroupV3 class Kwargs(MdfCommonKwargs, total=False): skip_sorting: bool class TriggerInfoDict(TypedDict): comment: str index: int group: int time: float pre_time: float post_time: float class MDF3(MDF_Common[Group]): """The `header` attribute is a `HeaderBlock`. The `groups` attribute is a list of `Group` objects, each one with the following attributes: * ``data_group`` - `DataGroup` object * ``channel_group`` - `ChannelGroup` object * ``channels`` - list of `Channel` objects with the same order as found in the MDF file * ``channel_dependencies`` - list of `ChannelArrayBlock` objects in case of channel arrays; list of `Channel` objects in case of structure channel composition * ``data_blocks`` - list of `DataBlockInfo` objects, each one containing address, type, size and other information about the block * ``data_location``- integer code for data location (original file, temporary file or memory) * ``data_block_addr`` - list of raw samples starting addresses * ``data_block_type`` - list of codes for data block type * ``data_block_size`` - list of raw samples block size * ``sorted`` - sorted indicator flag * ``record_size`` - dict that maps record IDs to record sizes in bytes * ``size`` - total size of data block for the current group * ``trigger`` - `Trigger` object for current group Parameters ---------- name : str | path-like | file-like, optional MDF file name (if provided it must be a real file name) or file-like object. version : str, default '3.30' MDF file version ('2.00', '2.10', '2.14', '3.00', '3.10', '3.20' or '3.30'). callback : function, optional Function to call to update the progress; the function must accept two arguments (the current progress and maximum progress value). Attributes ---------- channels_db : dict Used for fast channel access by name; for each name key the value is a list of (group index, channel index) tuples. groups : list List of data group dicts. header : HeaderBlock MDF file header. identification : FileIdentificationBlock MDF file start block. last_call_info : dict | None A dict to hold information about the last called method. .. versionadded:: 5.12.0 masters_db : dict Used for fast master channel access; for each group index key the value is the master channel index. name : pathlib.Path MDF file name. version : str MDF version. """ def __init__( self, name: StrPath | FileLike | None = None, version: Version2 | Version = "3.30", channels: list[str] | None = None, **kwargs: Unpack[Kwargs], ) -> None: if not kwargs.get("__internal__", False): raise MdfException("Always use the MDF class; do not use the class MDF3 directly") # bind cache to instance to avoid memory leaks self.determine_max_vlsd_sample_size = lru_cache(maxsize=1024 * 1024)(self._determine_max_vlsd_sample_size) self._kwargs = kwargs self._password = kwargs.get("password", None) self.original_name = kwargs["original_name"] if channels is None: self.load_filter = set() self.use_load_filter = False else: self.load_filter = set(channels) self.use_load_filter = True self.temporary_folder = kwargs.get("temporary_folder", GLOBAL_OPTIONS["temporary_folder"]) self.masters_db: dict[int, int] = {} self.version: str = version self._master_channel_metadata: dict[int, tuple[str, Literal[1]]] = {} self._closed = False self._tempfile = NamedTemporaryFile(dir=self.temporary_folder) self._tempfile.write(b"\0") self._mapped_file: BinaryIO | None = None self._file: FileLike | mmap.mmap | None = self._mapped_file self._remove_source_from_channel_names = kwargs.get("remove_source_from_channel_names", False) self._read_fragment_size = GLOBAL_OPTIONS["read_fragment_size"] self._write_fragment_size = GLOBAL_OPTIONS["write_fragment_size"] self._single_bit_uint_as_bool = GLOBAL_OPTIONS["single_bit_uint_as_bool"] self._integer_interpolation = GLOBAL_OPTIONS["integer_interpolation"] self._float_interpolation = GLOBAL_OPTIONS["float_interpolation"] self._use_display_names = kwargs.get("use_display_names", GLOBAL_OPTIONS["use_display_names"]) self._fill_0_for_missing_computation_channels = kwargs.get( "fill_0_for_missing_computation_channels", GLOBAL_OPTIONS["fill_0_for_missing_computation_channels"] ) self._si_map: dict[bytes | int, ChannelExtension] = {} self._cc_map: dict[bytes | int, ChannelConversion] = {} self._master: NDArray[Any] | None = None self.virtual_groups_map: dict[int, int] = {} self.virtual_groups: dict[int, VirtualChannelGroup] = {} self.vlsd_max_length: dict[tuple[int, str], int] = {} self._delete_on_close = False progress = kwargs.get("progress", None) super().__init__(kwargs.get("raise_on_multiple_occurrences", GLOBAL_OPTIONS["raise_on_multiple_occurrences"])) if name: if is_file_like(name): self._file = name self.name = self.original_name = Path("From_FileLike.mdf") self._from_filelike = True self._read(self._file, mapped=False, progress=progress) else: try: if sys.maxsize < 2**32: self.name = Path(name) self._file = open(self.name, "rb") self._from_filelike = False self._read(self._file, mapped=False, progress=progress) else: self.name = Path(name) self._mapped_file = open(self.name, "rb") self._file = mmap.mmap(self._mapped_file.fileno(), 0, access=mmap.ACCESS_READ) self._from_filelike = False self._read(self._file, mapped=True, progress=progress) except: if self._file: self._file.close() if self._mapped_file: self._mapped_file.close() self._file = self._mapped_file = None raise else: self._from_filelike = False version = validate_version_argument(version, hint=3) self.identification = FileIdentificationBlock(version=version) self.version = version self.header = HeaderBlock(version=self.version) self.name = Path("__new__.mdf") if not kwargs.get("skip_sorting", False): self._sort(progress=progress) for index, grp in enumerate(self.groups): self.virtual_groups_map[index] = index if index not in self.virtual_groups: self.virtual_groups[index] = VirtualChannelGroup() virtual_channel_group = self.virtual_groups[index] virtual_channel_group.groups.append(index) virtual_channel_group.record_size = grp.channel_group.samples_byte_nr virtual_channel_group.cycles_nr = grp.channel_group.cycles_nr self._parent: MDF | None = None def __del__(self) -> None: self.close() def _load_data( self, group: Group, record_offset: int = 0, record_count: int | None = None, optimize_read: bool = True, ) -> Iterator[tuple[bytes, int, int | None]]: """Get group's data block bytes.""" has_yielded = False offset = 0 _count = record_count channel_group = group.channel_group stream: FileLike | mmap.mmap | IO[bytes] if group.data_location == v23c.LOCATION_ORIGINAL_FILE: # go to the first data block of the current data group if self._file is None: raise RuntimeError(f"file was not opened '{self.name}'") stream = self._file else: stream = self._tempfile samples_size = channel_group.samples_byte_nr record_offset *= samples_size if record_count is not None: record_count *= samples_size finished = False # go to the first data block of the current data group if group.sorted: if not samples_size: yield b"", 0, _count has_yielded = True else: if self._read_fragment_size: split_size = self._read_fragment_size // samples_size split_size *= samples_size else: channels_nr = len(group.channels) y_axis = CONVERT idx = int(searchsorted(CHANNEL_COUNT, channels_nr, side="right") - 1) idx = max(idx, 0) split_size = y_axis[idx] split_size = split_size // samples_size split_size *= samples_size if split_size == 0: split_size = samples_size split_size = int(split_size) blocks = iter(group.data_blocks) cur_size = 0 data_list: list[bytes] = [] while True: try: info = next(blocks) address, size = info.address, typing.cast(int, info.original_size) current_address = address except StopIteration: break if offset + size < record_offset + 1: offset += size continue stream.seek(address) if offset < record_offset: delta = record_offset - offset stream.seek(delta, 1) current_address += delta size -= delta offset = record_offset if record_count: while size >= split_size - cur_size: stream.seek(current_address) if data_list: data_list.append(stream.read(min(record_count, split_size - cur_size))) bts = b"".join(data_list)[:record_count] record_count -= len(bts) __count = len(bts) // samples_size yield bts, offset // samples_size, __count has_yielded = True current_address += split_size - cur_size if record_count <= 0: finished = True break else: bts = stream.read(min(split_size, record_count))[:record_count] record_count -= len(bts) __count = len(bts) // samples_size yield bts, offset // samples_size, __count has_yielded = True current_address += split_size - cur_size if record_count <= 0: finished = True break offset += split_size size -= split_size - cur_size data_list = [] cur_size = 0 else: while size >= split_size - cur_size: stream.seek(current_address) if data_list: data_list.append(stream.read(split_size - cur_size)) yield b"".join(data_list), offset, _count has_yielded = True current_address += split_size - cur_size else: yield stream.read(split_size), offset, _count has_yielded = True current_address += split_size offset += split_size size -= split_size - cur_size data_list = [] cur_size = 0 if finished: data_list = [] offset = -1 break if size: stream.seek(current_address) if record_count: data_list.append(stream.read(min(record_count, size))) else: data_list.append(stream.read(size)) cur_size += size offset += size if data_list: data = b"".join(data_list) if record_count is not None: data = data[:record_count] yield data, offset, len(data) // samples_size has_yielded = True else: yield data, offset, _count has_yielded = True elif not offset: yield b"", 0, _count has_yielded = True if not has_yielded: yield b"", 0, _count else: record_id = group.channel_group.record_id cg_size = group.record_size if group.data_group.record_id_len <= 2: record_id_nr = group.data_group.record_id_len else: record_id_nr = 0 data_list = [] blocks = iter(group.data_blocks) for info in blocks: address, size = info.address, typing.cast(int, info.original_size) stream.seek(address) data = stream.read(size) i = 0 while i < size: rec_id = data[i] # skip record id i += 1 rec_size = cg_size[rec_id] if rec_id == record_id: rec_data = data[i : i + rec_size] data_list.append(rec_data) # consider the second record ID if it exists if record_id_nr == 2: i += rec_size + 1 else: i += rec_size data = b"".join(data_list) size = len(data) if size: if offset + size < record_offset + 1: offset += size continue if offset < record_offset: delta = record_offset - offset size -= delta offset = record_offset yield data, offset, _count has_yielded = True offset += size if not has_yielded: yield b"", 0, _count def _prepare_record(self, group: Group) -> list[tuple[np.dtype[Any], int, int, int] | None]: """Compute record list. Parameters ---------- group : dict MDF group dict. Returns ------- record : list Mapping of channels to records fields, records fields dtype. """ if group.record is None: byte_order = self.identification.byte_order channels = group.channels record: list[tuple[np.dtype[Any], int, int, int] | None] = [] for new_ch in channels: start_offset = new_ch.start_offset try: additional_byte_offset = new_ch.additional_byte_offset start_offset += 8 * additional_byte_offset except AttributeError: pass byte_offset, bit_offset = divmod(start_offset, 8) data_type = new_ch.data_type bit_count = new_ch.bit_count if not new_ch.component_addr: # adjust size to 1, 2, 4 or 8 bytes size = bit_offset + bit_count byte_size, rem = divmod(size, 8) if rem: byte_size += 1 bit_size = byte_size * 8 if data_type in ( v23c.DATA_TYPE_SIGNED_MOTOROLA, v23c.DATA_TYPE_UNSIGNED_MOTOROLA, ): if size > 32: bit_offset += 64 - bit_size elif size > 16: bit_offset += 32 - bit_size elif size > 8: bit_offset += 16 - bit_size if not new_ch.dtype_fmt: new_ch.dtype_fmt = np.dtype(get_fmt_v3(data_type, size, byte_order)) record.append( ( new_ch.dtype_fmt, new_ch.dtype_fmt.itemsize, byte_offset, bit_offset, ) ) else: record.append(None) group.record = record return group.record def _get_not_byte_aligned_data(self, data: bytes, group: Group, ch_nr: int) -> NDArray[Any]: big_endian_types = ( v23c.DATA_TYPE_UNSIGNED_MOTOROLA, v23c.DATA_TYPE_FLOAT_MOTOROLA, v23c.DATA_TYPE_DOUBLE_MOTOROLA, v23c.DATA_TYPE_SIGNED_MOTOROLA, ) record_size = group.channel_group.samples_byte_nr channel = group.channels[ch_nr] byte_offset, bit_offset = divmod(channel.start_offset, 8) bit_count = channel.bit_count byte_size = bit_offset + bit_count if byte_size % 8: byte_size = (byte_size // 8) + 1 else: byte_size //= 8 types = [ ("", f"S{byte_offset}"), ("vals", f"({byte_size},)u1"), ("", f"S{record_size - byte_size - byte_offset}"), ] vals: NDArray[Any] = np.rec.fromstring(data, dtype=np.dtype(types)) vals = vals["vals"] if byte_size in {1, 2, 4, 8}: extra_bytes = 0 else: extra_bytes = 4 - (byte_size % 4) std_size = byte_size + extra_bytes big_endian = channel.data_type in big_endian_types # prepend or append extra bytes columns # to get a standard size number of bytes if extra_bytes: if big_endian: vals = column_stack([vals, zeros(len(vals), dtype=f"<({extra_bytes},)u1")]) try: vals = vals.view(f">u{std_size}").ravel() except: vals = frombuffer(vals.tobytes(), dtype=f">u{std_size}") vals = vals >> (extra_bytes * 8 + bit_offset) vals &= (1 << bit_count) - 1 else: vals = column_stack([vals, zeros(len(vals), dtype=f"<({extra_bytes},)u1")]) try: vals = vals.view(f"> bit_offset vals &= (1 << bit_count) - 1 else: if big_endian: try: vals = vals.view(f">u{std_size}").ravel() except: vals = frombuffer(vals.tobytes(), dtype=f">u{std_size}") vals = vals >> bit_offset vals &= (1 << bit_count) - 1 else: try: vals = vals.view(f"> bit_offset vals &= (1 << bit_count) - 1 data_type = channel.data_type if data_type in v23c.SIGNED_INT: return as_non_byte_sized_signed_int(vals, bit_count) elif data_type in v23c.FLOATS: return vals.view(get_fmt_v3(data_type, bit_count, self.identification.byte_order)) else: return vals def _read( self, stream: FileLike | mmap.mmap, mapped: bool = False, progress: Callable[[int, int], None] | Any | None = None, ) -> None: filter_channels = self.use_load_filter cg_count, _ = count_channel_groups(stream) if progress is not None: if callable(progress): progress(0, cg_count) current_cg_index = 0 stream.seek(0, 2) self.file_limit = stream.tell() stream.seek(0) dg_cntr = 0 self.identification = FileIdentificationBlock(stream=stream) self.header = HeaderBlock(stream=stream) self.version = self.identification.version_str.decode("latin-1").strip(" \n\t\0") # this will hold mapping from channel address to Channel object # needed for linking dependency blocks to referenced channels after # the file is loaded ch_map = {} # go to first data group dg_addr = self.header.first_dg_addr # read each data group sequentially while dg_addr: if dg_addr > self.file_limit: logger.warning(f"Data group address {dg_addr:X} is outside the file size {self.file_limit}") break data_group = DataGroup(address=dg_addr, stream=stream, mapped=mapped) record_id_nr = data_group.record_id_len cg_nr = data_group.cg_nr cg_addr = data_group.first_cg_addr data_addr = data_group.data_block_addr # read trigger information if available trigger_addr = data_group.trigger_addr if trigger_addr: if trigger_addr > self.file_limit: logger.warning(f"Trigger address {trigger_addr:X} is outside the file size {self.file_limit}") trigger = None else: trigger = TriggerBlock(address=trigger_addr, stream=stream) else: trigger = None new_groups: list[Group] = [] for i in range(cg_nr): kargs: DataGroupKwargs = {"first_cg_addr": cg_addr, "data_block_addr": data_addr} if self.version >= "3.20": kargs["block_len"] = v23c.DG_POST_320_BLOCK_SIZE else: kargs["block_len"] = v23c.DG_PRE_320_BLOCK_SIZE kargs["record_id_len"] = record_id_nr kargs["address"] = data_group.address new_groups.append(Group(DataGroup(**kargs))) grp = new_groups[-1] grp.channels = [] grp.trigger = trigger grp.channel_dependencies = [] if record_id_nr: grp.sorted = False else: grp.sorted = True # read each channel group sequentially if cg_addr > self.file_limit: logger.warning(f"Channel group address {cg_addr:X} is outside the file size {self.file_limit}") break grp.channel_group = ChannelGroup(address=cg_addr, stream=stream) # go to first channel of the current channel group ch_addr = grp.channel_group.first_ch_addr ch_cntr = 0 grp_chs = grp.channels while ch_addr: if ch_addr > self.file_limit: logger.warning(f"Channel address {ch_addr:X} is outside the file size {self.file_limit}") break if filter_channels: display_names = {} if utils.stream_is_mmap(stream, mapped): ( id_, block_len, next_ch_addr, channel_type, name_bytes, ) = v23c.CHANNEL_FILTER_uf(stream, ch_addr) name = name_bytes.decode("latin-1").strip(" \t\n\r\0") if block_len >= v23c.CN_LONGNAME_BLOCK_SIZE: tx_address = v23c.UINT32_uf(stream, ch_addr + v23c.CN_SHORT_BLOCK_SIZE)[0] if tx_address: name = get_text_v3(tx_address, stream, mapped=mapped) if block_len == v23c.CN_DISPLAYNAME_BLOCK_SIZE: tx_address = v23c.UINT32_uf(stream, ch_addr + v23c.CN_LONGNAME_BLOCK_SIZE)[0] if tx_address: display_names = { get_text_v3(tx_address, stream, mapped=mapped): "display_name", } else: stream.seek(ch_addr) ( id_, block_len, next_ch_addr, channel_type, name_bytes, ) = v23c.CHANNEL_FILTER_u(stream.read(v23c.CHANNEL_FILTER_SIZE)) name = name_bytes.decode("latin-1").strip(" \t\n\r\0") if block_len >= v23c.CN_LONGNAME_BLOCK_SIZE: stream.seek(ch_addr + v23c.CN_SHORT_BLOCK_SIZE) tx_address = v23c.UINT32_u(stream.read(4))[0] if tx_address: name = get_text_v3(tx_address, stream, mapped=mapped) if block_len == v23c.CN_DISPLAYNAME_BLOCK_SIZE: stream.seek(ch_addr + v23c.CN_LONGNAME_BLOCK_SIZE) tx_address = v23c.UINT32_u(stream.read(4))[0] if tx_address: display_names = { get_text_v3(tx_address, stream, mapped=mapped): "display_name", } if id_ != b"CN": message = f'Expected "CN" block @{hex(ch_addr)} but found "{id_!r}"' raise MdfException(message) if self._remove_source_from_channel_names: name = name.split("\\", 1)[0] display_names = {_name.split("\\", 1)[0]: val for _name, val in display_names.items()} if ( channel_type == v23c.CHANNEL_TYPE_MASTER or name in self.load_filter or (any(_name in self.load_filter for _name in display_names)) ): new_ch = Channel( address=ch_addr, stream=stream, mapped=mapped, si_map=self._si_map, cc_map=self._cc_map, parsed_strings=(name, display_names), ) else: ch_addr = next_ch_addr continue else: # read channel block and create channel object new_ch = Channel( address=ch_addr, stream=stream, mapped=mapped, si_map=self._si_map, cc_map=self._cc_map, parsed_strings=None, ) if new_ch.data_type not in v23c.VALID_DATA_TYPES: ch_addr = new_ch.next_ch_addr continue if self._remove_source_from_channel_names: new_ch.name = new_ch.name.split("\\", 1)[0] new_ch.display_names = { _name.split("\\", 1)[0]: val for _name, val in new_ch.display_names.items() } # check if it has channel dependencies if new_ch.component_addr: dep = ChannelDependency(address=new_ch.component_addr, stream=stream) else: dep = None grp.channel_dependencies.append(dep) # update channel map entry = dg_cntr, ch_cntr ch_map[ch_addr] = entry for name in (new_ch.name, *tuple(new_ch.display_names)): if name: self.channels_db.add(name, entry) if new_ch.channel_type == v23c.CHANNEL_TYPE_MASTER: self.masters_db[dg_cntr] = ch_cntr # go to next channel of the current channel group ch_cntr += 1 grp_chs.append(new_ch) ch_addr = new_ch.next_ch_addr cg_addr = grp.channel_group.next_cg_addr dg_cntr += 1 current_cg_index += 1 if progress is not None: if callable(progress): progress(current_cg_index, cg_count) else: if progress.stop: self.close() raise Terminated # store channel groups record sizes dict and data block size in # each new group data belong to the initial unsorted group, and # add the key 'sorted' with the value False to use a flag; # this is used later if memory=False cg_size: dict[int, int] = {} total_size = 0 for grp in new_groups: record_id = grp.channel_group.record_id cycles_nr = grp.channel_group.cycles_nr record_size = grp.channel_group.samples_byte_nr self._prepare_record(grp) cg_size[record_id] = record_size record_size += record_id_nr total_size += record_size * cycles_nr grp.record_size = cg_size for grp in new_groups: grp.data_location = v23c.LOCATION_ORIGINAL_FILE if total_size: grp.data_blocks.append( DataBlockInfo( address=data_group.data_block_addr, block_type=0, original_size=total_size, compressed_size=total_size, param=0, ) ) self.groups.extend(new_groups) # go to next data group dg_addr = data_group.next_dg_addr # finally update the channel dependency references for grp in self.groups: for dep in grp.channel_dependencies: if dep: for i in range(dep.sd_nr): ref_channel_addr = typing.cast(int, dep[f"ch_{i}"]) channel = ch_map[ref_channel_addr] dep.referenced_channels.append(channel) def _filter_occurrences( self, occurrences: Iterator[tuple[int, int]], source_name: str | None = None, source_path: str | None = None, acq_name: str | None = None, ) -> Iterator[tuple[int, int]]: if source_name is not None: occurrences = ( (gp_idx, cn_idx) for gp_idx, cn_idx in occurrences if (source := self.groups[gp_idx].channels[cn_idx].source) is not None and source.name == source_name ) if source_path is not None: occurrences = ( (gp_idx, cn_idx) for gp_idx, cn_idx in occurrences if (source := self.groups[gp_idx].channels[cn_idx].source) is not None and source.path == source_path ) return occurrences def add_trigger( self, group: int, timestamp: float, pre_time: float = 0, post_time: float = 0, comment: str = "", ) -> None: """Add trigger to data group. Parameters ---------- group : int Group index. timestamp : float Trigger time. pre_time : float, default 0 Trigger pre time. post_time : float, default 0 Trigger post time. comment : str, optional Trigger comment. """ comment_template = """ {} """ try: gp = self.groups[group] except IndexError: return trigger = gp.trigger if comment: try: comment_elem = ET.fromstring(comment) tx_elem = comment_elem.find(".//TX") if tx_elem is not None: comment = tx_elem.text or "" else: comment = "" except ET.ParseError: pass if trigger: count = trigger.trigger_events_nr trigger.trigger_events_nr += 1 trigger.block_len += 24 trigger[f"trigger_{count}_time"] = timestamp trigger[f"trigger_{count}_pretime"] = pre_time trigger[f"trigger_{count}_posttime"] = post_time if comment: if trigger.comment is None: comment = f"{count + 1}. {comment}" comment = comment_template.format(comment) trigger.comment = comment else: current_comment = trigger.comment try: comment_elem = ET.fromstring(current_comment) tx_elem = comment_elem.find(".//TX") if tx_elem is not None: current_comment = tx_elem.text or "" else: current_comment = "" except ET.ParseError: pass comment = f"{current_comment}\n{count + 1}. {comment}" comment = comment_template.format(comment) trigger.comment = comment else: trigger = TriggerBlock( # type: ignore[call-arg] trigger_0_time=timestamp, trigger_0_pretime=pre_time, trigger_0_posttime=post_time, ) if comment: comment = f"1. {comment}" comment = comment_template.format(comment) trigger.comment = comment gp.trigger = trigger @overload def append( self, signals: list[Signal] | Signal, acq_name: str | None = ..., acq_source: Source | None = ..., comment: str = ..., common_timebase: bool = ..., units: dict[str, str] | None = ..., ) -> int: ... @overload def append( self, signals: DataFrame, acq_name: str | None = ..., acq_source: Source | None = ..., comment: str = ..., common_timebase: bool = ..., units: dict[str, str] | None = ..., ) -> None: ... @overload def append( self, signals: list[Signal] | Signal | DataFrame, acq_name: str | None = ..., acq_source: Source | None = ..., comment: str = ..., common_timebase: bool = ..., units: dict[str, str] | None = ..., ) -> int | None: ... def append( self, signals: list[Signal] | Signal | DataFrame, acq_name: str | None = None, acq_source: Source | None = None, comment: str = "Python", common_timebase: bool = False, units: dict[str, str] | None = None, ) -> int | None: """Append a new data group. For channel dependencies type Signals, the `samples` attribute must be a np.recarray. Parameters ---------- signals : list | Signal | pandas.DataFrame List of `Signal` objects, or a single `Signal` object, or a pandas DataFrame object. All bytes columns in the DataFrame must be *latin-1* encoded. acq_name : str, optional Channel group acquisition name. acq_source : Source, optional Channel group acquisition source. comment : str, default 'Python' Channel group comment. common_timebase : bool, default False Flag to hint that the signals have the same timebase. Only set this if you know for sure that all appended channels share the same time base. units : dict, optional Will contain the signal units mapped to the signal names when appending a pandas DataFrame. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> import pandas as pd Case 1: Conversion type None. >>> s1 = np.array([1, 2, 3, 4, 5]) >>> s2 = np.array([-1, -2, -3, -4, -5]) >>> s3 = np.array([0.1, 0.04, 0.09, 0.16, 0.25]) >>> t = np.array([0.001, 0.002, 0.003, 0.004, 0.005]) >>> s1 = Signal(samples=s1, timestamps=t, unit='+', name='Positive') >>> s2 = Signal(samples=s2, timestamps=t, unit='-', name='Negative') >>> s3 = Signal(samples=s3, timestamps=t, unit='flts', name='Floats') >>> mdf = MDF(version='3.30') >>> mdf.append([s1, s2, s3], comment='created by asammdf') Case 2: VTAB conversions from channels inside another file. >>> mdf1 = MDF('in.mdf') >>> ch1 = mdf1.get("Channel1_VTAB") >>> ch2 = mdf1.get("Channel2_VTABR") >>> mdf2 = MDF('out.mdf') >>> mdf2.append([ch1, ch2], comment='created by asammdf') >>> df = pd.DataFrame.from_dict({'s1': np.array([1, 2, 3, 4, 5]), 's2': np.array([-1, -2, -3, -4, -5])}) >>> units = {'s1': 'V', 's2': 'A'} >>> mdf2.append(df, units=units) """ if isinstance(signals, Signal): signals = [signals] elif isinstance(signals, DataFrame): self._append_dataframe(signals, comment=comment, units=units) return None integer_interp_mode = self._integer_interpolation float_interp_mode = self._float_interpolation # check if the signals have a common timebase # if not interpolate the signals using the union of all timebases if signals: timestamps = signals[0].timestamps if not common_timebase: for signal in signals[1:]: if not array_equal(signal.timestamps, timestamps): different = True break else: different = False if different: times = [s.timestamps for s in signals] timestamps = unique(concatenate(times)).astype(float64) signals = [ s.interp( timestamps, integer_interpolation_mode=integer_interp_mode, float_interpolation_mode=float_interp_mode, ) for s in signals ] del times else: timestamps = array([]) if self.version >= "3.00": channel_size = v23c.CN_DISPLAYNAME_BLOCK_SIZE elif self.version >= "2.10": channel_size = v23c.CN_LONGNAME_BLOCK_SIZE else: channel_size = v23c.CN_SHORT_BLOCK_SIZE file = self._tempfile tell = file.tell ce_kargs: ChannelExtensionKwargs = { "module_nr": 0, "module_address": 0, "type": v23c.SOURCE_ECU, "description": b"Channel inserted by Python Script", } ce_block = ChannelExtension(**ce_kargs) canopen_time_fields = ("ms", "days") canopen_date_fields = ( "ms", "min", "hour", "day", "month", "year", "summer_time", "day_of_week", ) dg_cntr = len(self.groups) gp = Group(DataGroup()) gp_channels = gp.channels = [] gp_dep = gp.channel_dependencies = [] gp_sig_types = gp.signal_types = [] gp.string_dtypes = [] record = gp.record = [] self.groups.append(gp) cycles_nr = len(timestamps) fields: list[NDArray[Any]] = [] types: list[DTypeLike | tuple[str, np.dtype[Any], tuple[int, ...]]] = [] ch_cntr = 0 offset = 0 field_names = UniqueDB() if signals: master_metadata = signals[0].master_metadata else: master_metadata = None if master_metadata: time_name = master_metadata[0] else: time_name = "time" if signals: # conversion for time channel cc_kargs: ChannelConversionKwargs = { "conversion_type": v23c.CONVERSION_TYPE_NONE, "unit": b"s", "min_phy_value": timestamps[0] if cycles_nr else 0, "max_phy_value": timestamps[-1] if cycles_nr else 0, } cc_block = ChannelConversion(**cc_kargs) cc_block.unit = "s" new_source = ce_block # time channel t_type, t_size = fmt_to_datatype_v3(timestamps.dtype, timestamps.shape) cn_kargs: ChannelKwargs = { "short_name": time_name.encode("latin-1"), "channel_type": v23c.CHANNEL_TYPE_MASTER, "data_type": t_type, "start_offset": 0, "min_raw_value": timestamps[0] if cycles_nr else 0, "max_raw_value": timestamps[-1] if cycles_nr else 0, "bit_count": t_size, "block_len": channel_size, } channel = Channel(**cn_kargs) channel.name = name = time_name channel.conversion = cc_block channel.source = new_source gp_channels.append(channel) self.channels_db.add(name, (dg_cntr, ch_cntr)) self.masters_db[dg_cntr] = 0 # time channel doesn't have channel dependencies gp_dep.append(None) fields.append(timestamps) types.append((field_names.get_unique_name(name), timestamps.dtype)) offset += t_size ch_cntr += 1 gp_sig_types.append(0) record.append( ( timestamps.dtype, timestamps.dtype.itemsize, 0, 0, ) ) for signal in signals: sig = signal names = sig.samples.dtype.names name = signal.name if names is None: sig_type = v23c.SIGNAL_TYPE_SCALAR else: if names in (canopen_time_fields, canopen_date_fields): sig_type = v23c.SIGNAL_TYPE_CANOPEN elif names[0] != sig.name: sig_type = v23c.SIGNAL_TYPE_STRUCTURE_COMPOSITION else: sig_type = v23c.SIGNAL_TYPE_ARRAY gp_sig_types.append(sig_type) # conversions for channel cc_block = conversion_transfer(signal.conversion) cc_block.unit = unit = signal.unit israw = signal.raw if not israw and not unit: conversion = None else: conversion = cc_block if sig_type == v23c.SIGNAL_TYPE_SCALAR: # source for channel if signal.source: source = signal.source if source.source_type != 2: ce_kargs = { "type": v23c.SOURCE_ECU, "description": source.name.encode("latin-1"), "ECU_identification": source.path.encode("latin-1"), } else: ce_kargs = { "type": v23c.SOURCE_VECTOR, "message_name": source.name.encode("latin-1"), "sender_name": source.path.encode("latin-1"), } new_source = ChannelExtension(**ce_kargs) else: new_source = ce_block # compute additional byte offset for large records size if offset > v23c.MAX_UINT16: additional_byte_offset = ceil((offset - v23c.MAX_UINT16) / 8) start_bit_offset = offset - additional_byte_offset * 8 else: start_bit_offset = offset additional_byte_offset = 0 s_type, s_size = fmt_to_datatype_v3(signal.samples.dtype, signal.samples.shape) name = signal.name display_names = signal.display_names if signal.samples.dtype.kind == "u" and signal.bit_count <= 4: s_size_ = signal.bit_count else: s_size_ = s_size cn_kargs = { "channel_type": v23c.CHANNEL_TYPE_VALUE, "data_type": s_type, "start_offset": start_bit_offset, "bit_count": s_size_, "additional_byte_offset": additional_byte_offset, "block_len": channel_size, } s_size = max(s_size, 8) channel = Channel(**cn_kargs) channel.name = signal.name channel.comment = signal.comment channel.source = new_source channel.conversion = conversion channel.display_names = display_names gp_channels.append(channel) if len(signal.samples.shape) > 1: dtype_fmt = np.dtype((signal.samples.dtype, signal.samples.shape[1:])) else: dtype_fmt = signal.samples.dtype channel.dtype_fmt = dtype_fmt record.append( ( dtype_fmt, dtype_fmt.itemsize, offset // 8, 0, ) ) offset += s_size entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in display_names: self.channels_db.add(_name, entry) field_name = field_names.get_unique_name(name) if signal.samples.dtype.kind == "S": gp.string_dtypes.append(signal.samples.dtype) fields.append(signal.samples) if s_type != v23c.DATA_TYPE_BYTEARRAY: types.append((field_name, signal.samples.dtype)) else: types.append((field_name, signal.samples.dtype, signal.samples.shape[1:])) ch_cntr += 1 # simple channels don't have channel dependencies gp_dep.append(None) # second, add the composed signals elif sig_type in ( v23c.SIGNAL_TYPE_CANOPEN, v23c.SIGNAL_TYPE_STRUCTURE_COMPOSITION, ): new_dg_cntr = len(self.groups) new_gp = Group(DataGroup()) new_gp_channels = new_gp.channels = [] new_gp_dep = new_gp.channel_dependencies = [] new_gp_sig_types = new_gp.signal_types = [] new_record = new_gp.record = [] self.groups.append(new_gp) new_fields: list[NDArray[Any]] = [] new_types: list[DTypeLike | tuple[str, np.dtype[Any], tuple[int, ...]]] = [] new_ch_cntr = 0 new_offset = 0 new_field_names = UniqueDB() # conversion for time channel cc_kargs = { "conversion_type": v23c.CONVERSION_TYPE_NONE, "unit": b"s", "min_phy_value": timestamps[0] if cycles_nr else 0, "max_phy_value": timestamps[-1] if cycles_nr else 0, } cc_block = ChannelConversion(**cc_kargs) cc_block.unit = "s" new_source = ce_block # time channel t_type, t_size = fmt_to_datatype_v3(timestamps.dtype, timestamps.shape) cn_kargs = { "short_name": time_name.encode("latin-1"), "channel_type": v23c.CHANNEL_TYPE_MASTER, "data_type": t_type, "start_offset": 0, "min_raw_value": timestamps[0] if cycles_nr else 0, "max_raw_value": timestamps[-1] if cycles_nr else 0, "bit_count": t_size, "block_len": channel_size, } channel = Channel(**cn_kargs) channel.name = name = time_name channel.source = new_source channel.conversion = cc_block new_gp_channels.append(channel) new_record.append( ( timestamps.dtype, timestamps.dtype.itemsize, 0, 0, ) ) self.channels_db.add(name, (new_dg_cntr, new_ch_cntr)) self.masters_db[new_dg_cntr] = 0 # time channel doesn't have channel dependencies new_gp_dep.append(None) new_fields.append(timestamps) new_types.append((name, timestamps.dtype)) new_field_names.get_unique_name(name) new_gp_sig_types.append(0) new_offset += t_size new_ch_cntr += 1 names = signal.samples.dtype.names if names == ("ms", "days"): channel_group_comment = "From mdf v4 CANopen Time channel" elif names == ( "ms", "min", "hour", "day", "month", "year", "summer_time", "day_of_week", ): channel_group_comment = "From mdf v4 CANopen Date channel" else: channel_group_comment = "From mdf v4 structure channel composition" for name in names or (): samples = signal.samples[name] new_record.append( ( samples.dtype, samples.dtype.itemsize, new_offset // 8, 0, ) ) # conversions for channel cc_kargs = { "conversion_type": v23c.CONVERSION_TYPE_NONE, "unit": signal.unit.encode("latin-1"), "min_phy_value": 0, "max_phy_value": 0, } cc_block = ChannelConversion(**cc_kargs) # source for channel if signal.source: source = signal.source if source.source_type != 2: ce_kargs = { "type": v23c.SOURCE_ECU, "description": source.name.encode("latin-1"), "ECU_identification": source.path.encode("latin-1"), } else: ce_kargs = { "type": v23c.SOURCE_VECTOR, "message_name": source.name.encode("latin-1"), "sender_name": source.path.encode("latin-1"), } new_source = ChannelExtension(**ce_kargs) else: new_source = ce_block # compute additional byte offset for large records size if new_offset > v23c.MAX_UINT16: additional_byte_offset = ceil((new_offset - v23c.MAX_UINT16) / 8) start_bit_offset = new_offset - additional_byte_offset * 8 else: start_bit_offset = new_offset additional_byte_offset = 0 s_type, s_size = fmt_to_datatype_v3(samples.dtype, samples.shape) cn_kargs = { "channel_type": v23c.CHANNEL_TYPE_VALUE, "data_type": s_type, "start_offset": start_bit_offset, "bit_count": s_size, "additional_byte_offset": additional_byte_offset, "block_len": channel_size, } s_size = max(s_size, 8) channel = Channel(**cn_kargs) channel.name = name channel.source = new_source channel.conversion = cc_block new_gp_channels.append(channel) new_offset += s_size self.channels_db.add(name, (new_dg_cntr, new_ch_cntr)) field_name = new_field_names.get_unique_name(name) new_fields.append(samples) new_types.append((field_name, samples.dtype)) new_ch_cntr += 1 # simple channels don't have channel dependencies new_gp_dep.append(None) # channel group cg_kargs: ChannelGroupKwargs = { "cycles_nr": cycles_nr, "samples_byte_nr": new_offset // 8, "ch_nr": new_ch_cntr, } new_gp.channel_group = ChannelGroup(**cg_kargs) new_gp.channel_group.comment = channel_group_comment # data group if self.version >= "3.20": block_len = v23c.DG_POST_320_BLOCK_SIZE else: block_len = v23c.DG_PRE_320_BLOCK_SIZE new_gp.data_group = DataGroup(block_len=block_len) # data block new_gp.sorted = True block: Buffer try: samples = np.rec.fromarrays(new_fields, dtype=np.dtype(new_types)) block = samples.tobytes() except: struct_fields: list[tuple[bytes | NDArray[Any], int]] = [] for samples in new_fields: size = samples.dtype.itemsize if len(samples.shape) > 1: shape = samples.shape[1:] for dim in shape: size *= dim if not samples.flags["C_CONTIGUOUS"]: samples = ascontiguousarray(samples) struct_fields.append((samples, size)) block = data_block_from_arrays(struct_fields, cycles_nr) new_gp.data_location = v23c.LOCATION_TEMPORARY_FILE if cycles_nr: data_address = tell() new_gp.data_group.data_block_addr = data_address self._tempfile.write(block) size = len(block) new_gp.data_blocks.append( DataBlockInfo( address=data_address, original_size=size, compressed_size=size, block_type=0, param=0, ) ) else: new_gp.data_group.data_block_addr = 0 # data group trigger new_gp.trigger = None else: new_dg_cntr = len(self.groups) new_gp = Group(DataGroup()) new_gp_channels = new_gp.channels = [] new_gp_dep = new_gp.channel_dependencies = [] new_gp_sig_types = new_gp.signal_types = [] new_record = new_gp.record = [] self.groups.append(new_gp) new_fields = [] new_types = [] new_ch_cntr = 0 new_offset = 0 new_field_names = UniqueDB() names = signal.samples.dtype.names name = signal.name component_names: list[str] = [] component_samples: list[NDArray[Any]] = [] if names: samples = signal.samples[names[0]] else: samples = signal.samples shape = samples.shape[1:] dims = [list(range(size)) for size in shape] for indexes in product(*dims): subarray = samples for idx in indexes: subarray = subarray[:, idx] component_samples.append(subarray) indexes_str = "".join(f"[{idx}]" for idx in indexes) component_name = f"{name}{indexes_str}" component_names.append(component_name) # add channel dependency block for composed parent channel sd_nr = len(component_samples) cd_kargs: ChannelDependencyKwargs = {"sd_nr": sd_nr} for i, dim in enumerate(shape[::-1]): cd_kargs[f"dim_{i}"] = dim # type: ignore[literal-required] parent_dep = ChannelDependency(**cd_kargs) new_gp_dep.append(parent_dep) # source for channel if signal.source: source = signal.source if source.source_type != 2: ce_kargs = { "type": v23c.SOURCE_ECU, "description": source.name.encode("latin-1"), "ECU_identification": source.path.encode("latin-1"), } else: ce_kargs = { "type": v23c.SOURCE_VECTOR, "message_name": source.name.encode("latin-1"), "sender_name": source.path.encode("latin-1"), } new_source = ChannelExtension(**ce_kargs) else: new_source = ce_block s_type, s_size = fmt_to_datatype_v3(samples.dtype, (), True) # compute additional byte offset for large records size if new_offset > v23c.MAX_UINT16: additional_byte_offset = ceil((new_offset - v23c.MAX_UINT16) / 8) start_bit_offset = new_offset - additional_byte_offset * 8 else: start_bit_offset = offset additional_byte_offset = 0 cn_kargs = { "channel_type": v23c.CHANNEL_TYPE_VALUE, "data_type": s_type, "start_offset": start_bit_offset, "bit_count": s_size, "additional_byte_offset": additional_byte_offset, "block_len": channel_size, } s_size = max(s_size, 8) new_record.append(None) channel = Channel(**cn_kargs) channel.comment = signal.comment channel.display_names = signal.display_names new_gp_channels.append(channel) self.channels_db.add(name, (new_dg_cntr, new_ch_cntr)) new_ch_cntr += 1 for i, (name, samples) in enumerate(zip(component_names, component_samples, strict=False)): if i < sd_nr: dep_pair = new_dg_cntr, new_ch_cntr parent_dep.referenced_channels.append(dep_pair) description = b"\0" else: description_str = f"{signal.name} - axis {name}" description = description_str.encode("latin-1") s_type, s_size = fmt_to_datatype_v3(samples.dtype, ()) shape = samples.shape[1:] # source for channel if signal.source: source = signal.source if source.source_type != 2: ce_kargs = { "type": v23c.SOURCE_ECU, "description": source.name.encode("latin-1"), "ECU_identification": source.path.encode("latin-1"), } else: ce_kargs = { "type": v23c.SOURCE_VECTOR, "message_name": source.name.encode("latin-1"), "sender_name": source.path.encode("latin-1"), } new_source = ChannelExtension(**ce_kargs) else: new_source = ce_block # compute additional byte offset for large records size if new_offset > v23c.MAX_UINT16: additional_byte_offset = ceil((new_offset - v23c.MAX_UINT16) / 8) start_bit_offset = new_offset - additional_byte_offset * 8 else: start_bit_offset = new_offset additional_byte_offset = 0 new_record.append( ( samples.dtype, samples.dtype.itemsize, new_offset // 8, 0, ) ) cn_kargs = { "channel_type": v23c.CHANNEL_TYPE_VALUE, "data_type": s_type, "start_offset": start_bit_offset, "bit_count": s_size, "additional_byte_offset": additional_byte_offset, "block_len": channel_size, "description": description, } s_size = max(s_size, 8) channel = Channel(**cn_kargs) channel.name = name channel.source = new_source new_gp_channels.append(channel) size = s_size for dim in shape: size *= dim new_offset += size self.channels_db.add(name, (new_dg_cntr, new_ch_cntr)) field_name = field_names.get_unique_name(name) new_fields.append(samples) new_types.append((field_name, samples.dtype, shape)) new_gp_dep.append(None) ch_cntr += 1 for name in names[1:] if names else (): samples = signal.samples[name] component_names = [] component_samples = [] shape = samples.shape[1:] dims = [list(range(size)) for size in shape] for indexes in product(*dims): subarray = samples for idx in indexes: subarray = subarray[:, idx] component_samples.append(subarray) indexes_str = "".join(f"[{idx}]" for idx in indexes) component_name = f"{name}{indexes_str}" component_names.append(component_name) # add channel dependency block for composed parent channel sd_nr = len(component_samples) cd_kargs = {"sd_nr": sd_nr} for i, dim in enumerate(shape[::-1]): cd_kargs[f"dim_{i}"] = dim # type: ignore[literal-required] parent_dep = ChannelDependency(**cd_kargs) new_gp_dep.append(parent_dep) # source for channel if signal.source: source = signal.source if source.source_type != 2: ce_kargs = { "type": v23c.SOURCE_ECU, "description": source.name.encode("latin-1"), "ECU_identification": source.path.encode("latin-1"), } else: ce_kargs = { "type": v23c.SOURCE_VECTOR, "message_name": source.name.encode("latin-1"), "sender_name": source.path.encode("latin-1"), } new_source = ChannelExtension(**ce_kargs) else: new_source = ce_block s_type, s_size = fmt_to_datatype_v3(samples.dtype, ()) # compute additional byte offset for large records size if new_offset > v23c.MAX_UINT16: additional_byte_offset = ceil((new_offset - v23c.MAX_UINT16) / 8) start_bit_offset = new_offset - additional_byte_offset * 8 else: start_bit_offset = new_offset additional_byte_offset = 0 cn_kargs = { "channel_type": v23c.CHANNEL_TYPE_VALUE, "data_type": s_type, "start_offset": start_bit_offset, "bit_count": s_size, "additional_byte_offset": additional_byte_offset, "block_len": channel_size, } s_size = max(s_size, 8) new_record.append(None) channel = Channel(**cn_kargs) channel.name = name channel.comment = signal.comment channel.source = new_source new_gp_channels.append(channel) self.channels_db.add(name, (new_dg_cntr, new_ch_cntr)) new_ch_cntr += 1 for i, (name, samples) in enumerate(zip(component_names, component_samples, strict=False)): if i < sd_nr: dep_pair = new_dg_cntr, new_ch_cntr parent_dep.referenced_channels.append(dep_pair) description = b"\0" else: description_str = f"{signal.name} - axis {name}" description = description_str.encode("latin-1") s_type, s_size = fmt_to_datatype_v3(samples.dtype, ()) shape = samples.shape[1:] # source for channel if signal.source: source = signal.source if source.source_type != 2: ce_kargs = { "type": v23c.SOURCE_ECU, "description": source.name.encode("latin-1"), "ECU_identification": source.path.encode("latin-1"), } else: ce_kargs = { "type": v23c.SOURCE_VECTOR, "message_name": source.name.encode("latin-1"), "sender_name": source.path.encode("latin-1"), } new_source = ChannelExtension(**ce_kargs) else: new_source = ce_block # compute additional byte offset for large records size if new_offset > v23c.MAX_UINT16: additional_byte_offset = ceil((new_offset - v23c.MAX_UINT16) / 8) start_bit_offset = new_offset - additional_byte_offset * 8 else: start_bit_offset = new_offset additional_byte_offset = 0 cn_kargs = { "channel_type": v23c.CHANNEL_TYPE_VALUE, "data_type": s_type, "start_offset": start_bit_offset, "bit_count": s_size, "additional_byte_offset": additional_byte_offset, "block_len": channel_size, "description": description, } s_size = max(s_size, 8) new_record.append( ( samples.dtype, samples.dtype.itemsize, new_offset // 8, 0, ) ) channel = Channel(**cn_kargs) channel.name = name channel.source = new_source new_gp_channels.append(channel) size = s_size for dim in shape: size *= dim new_offset += size self.channels_db.add(name, (new_dg_cntr, new_ch_cntr)) field_name = field_names.get_unique_name(name) new_fields.append(samples) new_types.append((field_name, samples.dtype, shape)) new_gp_dep.append(None) ch_cntr += 1 # channel group cg_kargs = { "cycles_nr": cycles_nr, "samples_byte_nr": new_offset // 8, "ch_nr": new_ch_cntr, } new_gp.channel_group = ChannelGroup(**cg_kargs) new_gp.channel_group.comment = "From mdf v4 channel array" # data group if self.version >= "3.20": block_len = v23c.DG_POST_320_BLOCK_SIZE else: block_len = v23c.DG_PRE_320_BLOCK_SIZE new_gp.data_group = DataGroup(block_len=block_len) # data block new_gp.sorted = True samples = np.rec.fromarrays(new_fields, dtype=np.dtype(new_types)) block = samples.tobytes() new_gp.data_location = v23c.LOCATION_TEMPORARY_FILE if cycles_nr: data_address = tell() new_gp.data_group.data_block_addr = data_address self._tempfile.write(block) size = len(block) new_gp.data_blocks.append( DataBlockInfo( address=data_address, original_size=size, compressed_size=size, block_type=0, param=0, ) ) else: new_gp.data_group.data_block_addr = 0 # data group trigger new_gp.trigger = None # channel group cg_kargs = { "cycles_nr": cycles_nr, "samples_byte_nr": offset // 8, "ch_nr": ch_cntr, } if self.version >= "3.30": cg_kargs["block_len"] = v23c.CG_POST_330_BLOCK_SIZE else: cg_kargs["block_len"] = v23c.CG_PRE_330_BLOCK_SIZE gp.channel_group = ChannelGroup(**cg_kargs) gp.channel_group.comment = comment # data group if self.version >= "3.20": block_len = v23c.DG_POST_320_BLOCK_SIZE else: block_len = v23c.DG_PRE_320_BLOCK_SIZE gp.data_group = DataGroup(block_len=block_len) # data block gp.sorted = True if signals: samples = np.rec.fromarrays(fields, dtype=np.dtype(types)) else: samples = array([]) block = samples.tobytes() self._tempfile.seek(0, 2) gp.data_location = v23c.LOCATION_TEMPORARY_FILE if cycles_nr: data_address = tell() gp.data_group.data_block_addr = data_address size = len(block) self._tempfile.write(block) gp.data_blocks.append( DataBlockInfo( address=data_address, block_type=0, original_size=size, compressed_size=size, param=0, ) ) self.virtual_groups_map[dg_cntr] = dg_cntr if dg_cntr not in self.virtual_groups: self.virtual_groups[dg_cntr] = VirtualChannelGroup() virtual_channel_group = self.virtual_groups[dg_cntr] virtual_channel_group.groups.append(dg_cntr) virtual_channel_group.record_size = gp.channel_group.samples_byte_nr virtual_channel_group.cycles_nr = gp.channel_group.cycles_nr # data group trigger gp.trigger = None return dg_cntr def _append_dataframe( self, df: DataFrame, comment: str = "", units: dict[str, str] | None = None, ) -> None: """Append a new data group from a pandas DataFrame.""" units = units or {} t = df.index.values time_name = df.index.name if isinstance(df.index.name, str) and df.index.name else "time" version = self.version timestamps = t if self.version >= "3.00": channel_size = v23c.CN_DISPLAYNAME_BLOCK_SIZE elif self.version >= "2.10": channel_size = v23c.CN_LONGNAME_BLOCK_SIZE else: channel_size = v23c.CN_SHORT_BLOCK_SIZE file = self._tempfile tell = file.tell ce_kargs: ChannelExtensionKwargs = { "module_nr": 0, "module_address": 0, "type": v23c.SOURCE_ECU, "description": b"Channel inserted by Python Script", } ce_block = ChannelExtension(**ce_kargs) dg_cntr = len(self.groups) gp = Group(DataGroup()) gp_channels = gp.channels = [] gp_dep = gp.channel_dependencies = [] gp_sig_types = gp.signal_types = [] gp.string_dtypes = [] record = gp.record = [] self.groups.append(gp) cycles_nr = len(timestamps) fields: list[ArrayLike] = [] types: list[DTypeLike] = [] ch_cntr = 0 offset = 0 field_names = UniqueDB() if df.shape[0]: # conversion for time channel cc_kargs: ChannelConversionKwargs = { "conversion_type": v23c.CONVERSION_TYPE_NONE, "unit": b"s", "min_phy_value": typing.cast(float, timestamps[0]) if cycles_nr else 0, "max_phy_value": typing.cast(float, timestamps[-1]) if cycles_nr else 0, } conversion = ChannelConversion(**cc_kargs) conversion.unit = "s" source = ce_block # time channel t_type, t_size = fmt_to_datatype_v3(timestamps.dtype, timestamps.shape) cn_kargs: ChannelKwargs = { "short_name": time_name.encode("latin-1"), "channel_type": v23c.CHANNEL_TYPE_MASTER, "data_type": t_type, "start_offset": 0, "min_raw_value": typing.cast(float, timestamps[0]) if cycles_nr else 0, "max_raw_value": typing.cast(float, timestamps[-1]) if cycles_nr else 0, "bit_count": t_size, "block_len": channel_size, } channel = Channel(**cn_kargs) channel.name = name = time_name channel.conversion = conversion channel.source = source gp_channels.append(channel) self.channels_db.add(name, (dg_cntr, ch_cntr)) self.masters_db[dg_cntr] = 0 record.append( ( timestamps.dtype, timestamps.dtype.itemsize, 0, 0, ) ) # time channel doesn't have channel dependencies gp_dep.append(None) fields.append(timestamps) types.append((field_names.get_unique_name(name), timestamps.dtype)) offset += t_size ch_cntr += 1 gp_sig_types.append(0) for signal in df.columns: sig = df[signal] name = signal sig_type = v23c.SIGNAL_TYPE_SCALAR gp_sig_types.append(sig_type) new_source = ce_block # compute additional byte offset for large records size if offset > v23c.MAX_UINT16: additional_byte_offset = ceil((offset - v23c.MAX_UINT16) / 8) start_bit_offset = offset - additional_byte_offset * 8 else: start_bit_offset = offset additional_byte_offset = 0 s_type, s_size = fmt_to_datatype_v3(sig.dtype, sig.shape) cn_kwargs: ChannelKwargs = { "channel_type": v23c.CHANNEL_TYPE_VALUE, "data_type": s_type, "min_raw_value": 0, "max_raw_value": 0, "start_offset": start_bit_offset, "bit_count": s_size, "additional_byte_offset": additional_byte_offset, "block_len": channel_size, } s_size = max(s_size, 8) channel = Channel(**cn_kwargs) channel.name = name channel.source = new_source channel.dtype_fmt = np.dtype((sig.dtype, sig.shape[1:])) record.append( ( channel.dtype_fmt, channel.dtype_fmt.itemsize, offset // 8, 0, ) ) unit = units.get(name, "") if unit: # conversion for time channel cc_kwargs: ChannelConversionKwargs = { "conversion_type": v23c.CONVERSION_TYPE_NONE, "unit": unit.encode(encoding="latin-1"), "min_phy_value": 0, "max_phy_value": 0, } conversion = ChannelConversion(**cc_kwargs) conversion.unit = unit gp_channels.append(channel) offset += s_size self.channels_db.add(name, (dg_cntr, ch_cntr)) field_name = field_names.get_unique_name(name) if sig.dtype.kind == "S": dtype = typing.cast(np.dtype[np.bytes_], sig.dtype) gp.string_dtypes.append(dtype) fields.append(sig) types.append((field_name, sig.dtype)) ch_cntr += 1 # simple channels don't have channel dependencies gp_dep.append(None) # channel group cg_kwargs: ChannelGroupKwargs = { "cycles_nr": cycles_nr, "samples_byte_nr": offset // 8, "ch_nr": ch_cntr, } if self.version >= "3.30": cg_kwargs["block_len"] = v23c.CG_POST_330_BLOCK_SIZE else: cg_kwargs["block_len"] = v23c.CG_PRE_330_BLOCK_SIZE gp.channel_group = ChannelGroup(**cg_kwargs) gp.channel_group.comment = comment # data group if self.version >= "3.20": block_len = v23c.DG_POST_320_BLOCK_SIZE else: block_len = v23c.DG_PRE_320_BLOCK_SIZE gp.data_group = DataGroup(block_len=block_len) # data block gp.sorted = True samples: NDArray[Any] if df.shape[0]: samples = np.rec.fromarrays(fields, dtype=np.dtype(types)) else: samples = array([]) block = samples.tobytes() gp.data_location = v23c.LOCATION_TEMPORARY_FILE if cycles_nr: data_address = tell() gp.data_group.data_block_addr = data_address size = len(block) self._tempfile.write(block) gp.data_blocks.append( DataBlockInfo( address=data_address, block_type=0, original_size=size, compressed_size=size, param=0, ) ) else: gp.data_location = v23c.LOCATION_TEMPORARY_FILE self.virtual_groups_map[dg_cntr] = dg_cntr if dg_cntr not in self.virtual_groups: self.virtual_groups[dg_cntr] = VirtualChannelGroup() virtual_channel_group = self.virtual_groups[dg_cntr] virtual_channel_group.groups.append(dg_cntr) virtual_channel_group.record_size = gp.channel_group.samples_byte_nr virtual_channel_group.cycles_nr = gp.channel_group.cycles_nr # data group trigger gp.trigger = None def close(self) -> None: """Call this just before the object is not used anymore to clean up the temporary file and close the file object. """ try: if self._closed: return else: self._closed = True self._parent = None if self._tempfile is not None: self._tempfile.close() if self._file is not None and not self._from_filelike: self._file.close() if self._mapped_file is not None: self._mapped_file.close() if self._delete_on_close: try: Path(self.name).unlink() except: pass if self.original_name is not None: if Path(self.original_name).suffix.lower() in ( ".bz2", ".gzip", ".mf4z", ".zip", ): try: os.remove(self.name) except: pass self._call_back = None self.groups.clear() self.channels_db.clear() self.masters_db.clear() self._master_channel_metadata.clear() self._si_map.clear() self._cc_map.clear() except: print(format_exc()) def extend(self, index: int, signals: Sequence[tuple[NDArray[Any], NDArray[np.bool] | None]]) -> None: """Extend a group with new samples. `signals` contains (values, invalidation_bits) pairs for each extended signal. Since MDF3 does not support invalidation bits, the second item of each pair must be None. The first pair is the master channel's pair, and the next pairs must respect the same order in which the signals were appended. The samples must have raw or physical values according to the signals used for the initial append. Parameters ---------- index : int Group index. signals : sequence Sequence of (np.ndarray, None) tuples. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> s1 = np.array([1, 2, 3, 4, 5]) >>> s2 = np.array([-1, -2, -3, -4, -5]) >>> s3 = np.array([0.1, 0.04, 0.09, 0.16, 0.25]) >>> t = np.array([0.001, 0.002, 0.003, 0.004, 0.005]) >>> s1 = Signal(samples=s1, timestamps=t, unit='+', name='Positive') >>> s2 = Signal(samples=s2, timestamps=t, unit='-', name='Negative') >>> s3 = Signal(samples=s3, timestamps=t, unit='flts', name='Floats') >>> mdf = MDF(version='3.30') >>> mdf.append([s1, s2, s3], comment='created by asammdf') >>> t = np.array([0.006, 0.007, 0.008, 0.009, 0.010]) >>> mdf.extend(0, [(t, None), (s1.samples, None), (s2.samples, None), (s3.samples, None)]) """ new_group_offset = 0 gp = self.groups[index] if not signals: message = '"append" requires a non-empty list of Signal objects' raise MdfException(message) stream: FileLike | mmap.mmap | IO[bytes] if gp.data_location == v23c.LOCATION_ORIGINAL_FILE: if self._file is None: raise ValueError("self._file cannot be None") stream = self._file else: stream = self._tempfile canopen_time_fields = ("ms", "days") canopen_date_fields = ( "ms", "min", "hour", "day", "month", "year", "summer_time", "day_of_week", ) fields: list[NDArray[Any]] = [] types: list[DTypeLike | tuple[str, np.dtype[Any], tuple[int, ...]]] = [] samples: NDArray[Any] cycles_nr = len(signals[0][0]) string_counter = 0 for k_i, ((signal, invalidation_bits), sig_type) in enumerate(zip(signals, gp.signal_types, strict=False)): sig = signal names = sig.dtype.names if sig_type == v23c.SIGNAL_TYPE_SCALAR: if signal.dtype.kind == "S": str_dtype = gp.string_dtypes[string_counter] signal = signal.astype(str_dtype) string_counter += 1 fields.append(signal) if signal.shape[1:]: types.append(("", signal.dtype, signal.shape[1:])) else: types.append(("", signal.dtype)) # second, add the composed signals elif sig_type in ( v23c.SIGNAL_TYPE_CANOPEN, v23c.SIGNAL_TYPE_STRUCTURE_COMPOSITION, ): new_group_offset += 1 new_gp = self.groups[index + new_group_offset] new_fields: list[NDArray[Any]] = [] new_types: list[DTypeLike] = [] names = signal.dtype.names for name in names or (): new_fields.append(signal[name]) new_types.append(("", signal.dtype)) # data block samples = np.rec.fromarrays(new_fields, dtype=np.dtype(new_types)) data = samples.tobytes() record_size = new_gp.channel_group.samples_byte_nr extended_size = cycles_nr * record_size if data: stream.seek(0, 2) data_address = stream.tell() stream.write(data) new_gp.data_blocks.append( DataBlockInfo( address=data_address, original_size=extended_size, compressed_size=extended_size, block_type=0, param=0, ) ) else: names = signal.dtype.names component_samples: list[NDArray[Any]] = [] if names: samples = signal[names[0]] else: samples = signal shape = samples.shape[1:] dims = [list(range(size)) for size in shape] for indexes in product(*dims): subarray = samples for idx in indexes: subarray = subarray[:, idx] component_samples.append(subarray) if names: new_samples = [signal[fld] for fld in names[1:]] component_samples.extend(new_samples) for samples in component_samples: shape = samples.shape[1:] fields.append(samples) types.append(("", samples.dtype, shape)) record_size = gp.channel_group.samples_byte_nr extended_size = cycles_nr * record_size # data block samples = np.rec.fromarrays(fields, dtype=np.dtype(types)) data = samples.tobytes() if cycles_nr: stream.seek(0, 2) data_address = stream.tell() stream.write(data) gp.channel_group.cycles_nr += cycles_nr gp.data_blocks.append( DataBlockInfo( address=data_address, block_type=0, original_size=extended_size, compressed_size=extended_size, param=0, ) ) virtual_channel_group = self.virtual_groups[index] virtual_channel_group.cycles_nr += cycles_nr def get_channel_name(self, group: int, index: int) -> str: """Get channel name. Parameters ---------- group : int 0-based group index. index : int 0-based channel index. Returns ------- name : str Found channel name. """ gp_nr, ch_nr = self._validate_channel_selection(None, group, index) grp = self.groups[gp_nr] channel = grp.channels[ch_nr] return channel.name def get_channel_metadata( self, name: str | None = None, group: int | None = None, index: int | None = None, ) -> Channel: gp_nr, ch_nr = self._validate_channel_selection(name, group, index) grp = self.groups[gp_nr] channel = grp.channels[ch_nr] channel = deepcopy(channel) return channel def get_channel_unit( self, name: str | None = None, group: int | None = None, index: int | None = None, ) -> str: """Get channel unit. The channel can be specified in two ways: * Using the first positional argument `name`. * If there are multiple occurrences for this channel, then the `group` and `index` arguments can be used to select a specific group. * If there are multiple occurrences for this channel and either the `group` or `index` arguments is None, then a warning is issued. * Using the group number (keyword argument `group`) and the channel number (keyword argument `index`). Use `info` method for group and channel numbers. Parameters ---------- name : str, optional Name of channel. group : int, optional 0-based group index. index : int, optional 0-based channel index. Returns ------- unit : str Found channel unit. """ gp_nr, ch_nr = self._validate_channel_selection(name, group, index) grp = self.groups[gp_nr] channel = grp.channels[ch_nr] if channel.conversion: unit = channel.conversion.unit else: unit = "" return unit def get_channel_comment( self, name: str | None = None, group: int | None = None, index: int | None = None, ) -> str: """Get channel comment. The channel can be specified in two ways: * Using the first positional argument `name`. * If there are multiple occurrences for this channel, then the `group` and `index` arguments can be used to select a specific group. * If there are multiple occurrences for this channel and either the `group` or `index` arguments is None, then a warning is issued. * Using the group number (keyword argument `group`) and the channel number (keyword argument `index`). Use `info` method for group and channel numbers. Parameters ---------- name : str, optional Name of channel. group : int, optional 0-based group index. index : int, optional 0-based channel index. Returns ------- comment : str Found channel comment. """ gp_nr, ch_nr = self._validate_channel_selection(name, group, index) grp = self.groups[gp_nr] channel = grp.channels[ch_nr] return channel.comment @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., samples_only: Literal[False] = ..., data: tuple[bytes, int, int | None] | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = ..., record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> Signal: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., *, samples_only: Literal[True], data: tuple[bytes, int, int | None] | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = ..., record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> tuple[NDArray[Any], None]: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., samples_only: bool = ..., data: tuple[bytes, int, int | None] | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = ..., record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> Signal | tuple[NDArray[Any], None]: ... def get( self, name: str | None = None, group: int | None = None, index: int | None = None, raster: RasterType | None = None, samples_only: bool = False, data: tuple[bytes, int, int | None] | None = None, raw: bool = False, ignore_invalidation_bits: bool = False, record_offset: int = 0, record_count: int | None = None, skip_channel_validation: bool = False, ) -> Signal | tuple[NDArray[Any], None]: """Get channel samples. The channel can be specified in two ways: * Using the first positional argument `name`. * If there are multiple occurrences for this channel, then the `group` and `index` arguments can be used to select a specific group. * If there are multiple occurrences for this channel and either the `group` or `index` arguments is None, then a warning is issued. * Using the group number (keyword argument `group`) and the channel number (keyword argument `index`). Use `info` method for group and channel numbers. If the `raster` keyword argument is not None, the output is interpolated accordingly. Parameters ---------- name : str, optional Name of channel. group : int, optional 0-based group index. index : int, optional 0-based channel index. raster : float, optional Time raster in seconds. samples_only : bool, default False If True, return only the channel samples as np.ndarray; if False, return a `Signal` object. data : bytes, optional Prevent redundant data read by providing the raw data group samples. raw : bool, default False Return channel samples without applying the conversion rule. ignore_invalidation_bits : bool, default False Only defined to have the same API with the MDF v4. record_offset : int, optional If `data=None`, use this to select the record offset from which the group data should be loaded. record_count : int, optional Number of records to read; default is None and in this case all available records are used. skip_channel_validation : bool, default False Skip validation of channel name, group index and channel index. If True, the caller has to make sure that the `group` and `index` arguments are provided and are correct. .. versionadded:: 7.0.0 Returns ------- res : (np.ndarray, None) | Signal Returns `Signal` if `samples_only=False` (default option), otherwise returns a (np.ndarray, None) tuple (for compatibility with MDF v4 class). The `Signal` samples are: * np.recarray for channels that have CDBLOCK or BYTEARRAY type channels * np.ndarray for all the rest Raises ------ MdfException * if the channel name is not found * if the group index is out of range * if the channel index is out of range * if there are multiple channel occurrences in the file and the arguments `name`, `group`, `index` are ambiguous. This behaviour can be turned off by setting `raise_on_multiple_occurrences` to False. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> t = np.arange(5) >>> s = np.ones(5) >>> mdf = MDF(version='3.30') >>> for i in range(4): ... sigs = [Signal(s * (i * 10 + j), t, name='Sig') for j in range(1, 4)] ... mdf.append(sigs) Specifying only the channel name is not enough when there are multiple channels with that name. >>> mdf.get('Sig') MdfException: Multiple occurrences for channel "Sig": ((0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)). Provide both "group" and "index" arguments to select another data group In this case, adding the group number is also not enough since there are multiple channels with that name in that group. >>> mdf.get('Sig', 1) MdfException: Multiple occurrences for channel "Sig": ((1, 1), (1, 2), (1, 3)). Provide both "group" and "index" arguments to select another data group Get the channel named "Sig" from group 1, channel index 2. >>> mdf.get('Sig', 1, 2) Get the channel from group 2 and channel index 1. >>> mdf.get(None, 2, 1) >>> mdf.get(group=2, index=1) """ if skip_channel_validation: if group is None or index is None: raise ValueError("'group' or 'index' cannot be None if 'skip_channel_validation' is True") gp_nr, ch_nr = group, index else: gp_nr, ch_nr = self._validate_channel_selection(name, group, index) original_data = data grp = self.groups[gp_nr] channel = grp.channels[ch_nr] conversion = channel.conversion name = channel.name display_names = channel.display_names bit_count = channel.bit_count or 64 dep = grp.channel_dependencies[ch_nr] cycles_nr = grp.channel_group.cycles_nr encoding = "latin-1" # get data group record data_: Iterable[tuple[bytes, int, int | None]] if data is None: data_ = self._load_data(grp, record_offset=record_offset, record_count=record_count) else: data_ = (data,) # check if this is a channel array vals: NDArray[Any] if dep: if dep.dependency_type == v23c.DEPENDENCY_TYPE_VECTOR: arrays: list[NDArray[Any]] = [] types: list[DTypeLike] = [] for dg_nr, ch_nr in dep.referenced_channels: sig = self.get( group=dg_nr, index=ch_nr, raw=raw, data=original_data, record_offset=record_offset, record_count=record_count, ) arrays.append(sig.samples) types.append((sig.name, sig.samples.dtype)) vals = np.rec.fromarrays(arrays, dtype=types) elif dep.dependency_type >= v23c.DEPENDENCY_TYPE_NDIM: shape: list[int] = [] i = 0 while True: try: dim = typing.cast(int, dep[f"dim_{i}"]) shape.append(dim) i += 1 except (KeyError, AttributeError): break shape = shape[::-1] record_shape = tuple(shape) arrays = [ self.get( group=dg_nr, index=ch_nr, samples_only=True, raw=raw, data=original_data, record_offset=record_offset, record_count=record_count, )[0] for dg_nr, ch_nr in dep.referenced_channels ] shape.insert(0, cycles_nr) vals = column_stack(arrays).flatten().reshape(tuple(shape)) arrays = [vals] vals = np.rec.fromarrays(arrays, dtype=np.dtype([(channel.name, vals.dtype, record_shape)])) else: raise ValueError(f"unexpected dependency_type '{dep.dependency_type}'") if not samples_only or raster: timestamps = self.get_master( gp_nr, original_data, record_offset=record_offset, record_count=record_count, ) if raster and len(timestamps) > 1: num = float(float32((timestamps[-1] - timestamps[0]) / raster)) if num.is_integer(): t = linspace(timestamps[0], timestamps[-1], int(num)) else: t = arange(timestamps[0], timestamps[-1], raster) vals = ( Signal(vals, timestamps, name="_") .interp( t, integer_interpolation_mode=self._integer_interpolation, float_interpolation_mode=self._float_interpolation, ) .samples ) timestamps = t else: # get channel values channel_values: list[NDArray[Any]] = [] times: list[NDArray[Any]] = [] count = 0 records = self._prepare_record(grp) for fragment in data_: data_bytes, _offset, _count = fragment info = records[ch_nr] bits = channel.bit_count if info is not None: dtype_, byte_size, byte_offset, bit_offset = info buffer = get_channel_raw_bytes( data_bytes, grp.channel_group.samples_byte_nr, byte_offset, byte_size, ) vals = frombuffer(buffer, dtype=dtype_) data_type = channel.data_type size = byte_size vals_dtype = vals.dtype.kind if vals_dtype not in "ui" and (bit_offset or bits != size * 8): vals = self._get_not_byte_aligned_data(data_bytes, grp, ch_nr) else: dtype_ = vals.dtype kind_ = dtype_.kind if data_type in v23c.INT_TYPES: dtype_fmt = get_fmt_v3(data_type, bits, self.identification.byte_order) channel_dtype: np.dtype[Any] = np.dtype(dtype_fmt.split(")")[-1]) if channel_dtype.byteorder == "=" and data_type in ( v23c.DATA_TYPE_SIGNED_MOTOROLA, v23c.DATA_TYPE_UNSIGNED_MOTOROLA, ): view = f">u{vals.itemsize}" else: view = f"{channel_dtype.byteorder}u{vals.itemsize}" vals = vals.view(view) if bit_offset: vals = vals >> bit_offset if bits != size * 8: if data_type in v23c.SIGNED_INT: vals = as_non_byte_sized_signed_int(vals, bits) else: mask = (1 << bits) - 1 vals = vals & mask elif data_type in v23c.SIGNED_INT: view = f"{channel_dtype.byteorder}i{vals.itemsize}" vals = vals.view(view) else: if bits != size * 8: vals = self._get_not_byte_aligned_data(data_bytes, grp, ch_nr) else: vals = self._get_not_byte_aligned_data(data_bytes, grp, ch_nr) if not samples_only or raster: times.append(self.get_master(gp_nr, fragment)) if bits == 1 and self._single_bit_uint_as_bool: vals = array(vals, dtype=bool) channel_values.append(vals) count += 1 if count > 1: vals = concatenate(channel_values) elif count == 1: vals = channel_values[0] else: vals = np.array([]) if not samples_only or raster: if count > 1: timestamps = concatenate(times) else: timestamps = times[0] if raster and len(timestamps) > 1: num = float(float32((timestamps[-1] - timestamps[0]) / raster)) if num.is_integer(): t = linspace(timestamps[0], timestamps[-1], int(num)) else: t = arange(timestamps[0], timestamps[-1], raster) vals = ( Signal(vals, timestamps, name="_") .interp( t, integer_interpolation_mode=self._integer_interpolation, float_interpolation_mode=self._float_interpolation, ) .samples ) timestamps = t if not raw: if conversion: vals = conversion.convert(vals) conversion = None if vals.dtype.kind == "S": encoding = "latin-1" vals = array([e.rsplit(b"\0")[0] for e in typing.cast(list[bytes], vals.tolist())], dtype=vals.dtype) res: tuple[NDArray[Any], None] | Signal if samples_only: res = vals, None else: if channel.conversion: unit = channel.conversion.unit else: unit = "" comment = channel.comment description = channel.description.decode("latin-1").strip(" \t\n\0") if comment: comment = f"{comment}\n{description}" else: comment = description if channel.source: source = Source.from_source(channel.source) else: source = None master_metadata = self._master_channel_metadata.get(gp_nr, None) res = Signal( samples=vals, timestamps=timestamps, unit=unit, name=channel.name, comment=comment, conversion=conversion, raw=raw, master_metadata=master_metadata, display_names=display_names, source=source, bit_count=bit_count, encoding=encoding, group_index=gp_nr, channel_index=ch_nr, ) return res def get_master( self, index: int, data: tuple[bytes, int, int | None] | None = None, record_offset: int = 0, record_count: int | None = None, one_piece: bool = False, ) -> NDArray[Any]: """Get master channel samples for the given group. Parameters ---------- index : int Group index. data : (bytes, int), optional (data block raw bytes, fragment offset). record_offset : int, optional If `data=None`, use this to select the record offset from which the group data should be loaded. record_count : int, optional Number of records to read; default is None and in this case all available records are used. Returns ------- t : np.ndarray Master channel samples. """ if self._master is not None: return self._master fragment = data if fragment: data_bytes, offset, _count = fragment else: offset = 0 group = self.groups[index] time_ch_nr = self.masters_db.get(index, None) cycles_nr = group.channel_group.cycles_nr t: NDArray[Any] metadata: tuple[str, Literal[1]] if time_ch_nr is None: if fragment: count = len(data_bytes) // group.channel_group.samples_byte_nr else: count = cycles_nr t = arange(count, dtype=float64) metadata = ("time", 1) else: time_ch = group.channels[time_ch_nr] metadata = (time_ch.name, 1) if time_ch.bit_count == 0: if time_ch.sampling_rate: sampling_rate = time_ch.sampling_rate else: sampling_rate = 1 t = arange(cycles_nr, dtype=float64) * sampling_rate else: # get data group record data_: Iterable[tuple[bytes, int, int | None]] if data is None: data_ = self._load_data(group, record_offset=record_offset, record_count=record_count) _count = record_count else: data_ = (data,) records = self._prepare_record(group) record = records[time_ch_nr] if record is None: raise ValueError("record is None") time_values: list[NDArray[Any]] = [] count = 0 for fragment in data_: data_bytes, offset, _count = fragment dtype_, byte_size, byte_offset, bit_offset = record buffer = get_channel_raw_bytes( data_bytes, group.channel_group.samples_byte_nr, byte_offset, byte_size, ) t = frombuffer(buffer, dtype=dtype_) time_values.append(t) count += 1 if count > 1: t = concatenate(time_values) elif count == 1: t = time_values[0] else: t = array([], dtype=float64) if time_ch.data_type in v23c.INT_TYPES: dtype_fmt = get_fmt_v3( time_ch.data_type, time_ch.bit_count, self.identification.byte_order, ) channel_dtype: np.dtype[Any] = np.dtype(dtype_fmt.split(")")[-1]) if channel_dtype.byteorder == "=" and time_ch.data_type in ( v23c.DATA_TYPE_SIGNED_MOTOROLA, v23c.DATA_TYPE_UNSIGNED_MOTOROLA, ): view = f">u{t.itemsize}" else: view = f"{channel_dtype.byteorder}u{t.itemsize}" if bit_offset: t >>= bit_offset if time_ch.bit_count != t.itemsize * 8: if time_ch.data_type in v23c.SIGNED_INT: t = as_non_byte_sized_signed_int(t, time_ch.bit_count) else: mask = (1 << time_ch.bit_count) - 1 t &= mask elif time_ch.data_type in v23c.SIGNED_INT: view = f"{channel_dtype.byteorder}i{t.itemsize}" t = t.view(view) # get timestamps conversion = time_ch.conversion if conversion is None: time_conv_type = v23c.CONVERSION_TYPE_NONE else: time_conv_type = conversion.conversion_type if time_conv_type == v23c.CONVERSION_TYPE_LINEAR: time_a = conversion.a time_b = conversion.b t = t * time_a if time_b: t += time_b if t.dtype != float64: timestamps = t.astype(float64) else: timestamps = t self._master_channel_metadata[index] = metadata return timestamps def iter_get_triggers(self) -> Iterator[TriggerInfoDict]: """Generator that yields triggers. Yields ------ trigger_info : dict Trigger information with the following keys: * comment : trigger comment * time : trigger time * pre_time : trigger pre time * post_time : trigger post time * index : trigger index * group : data group index of trigger """ for i, gp in enumerate(self.groups): trigger = gp.trigger if trigger: for j in range(trigger.trigger_events_nr): trigger_info: TriggerInfoDict = { "comment": trigger.comment, "index": j, "group": i, "time": typing.cast(float, trigger[f"trigger_{j}_time"]), "pre_time": typing.cast(float, trigger[f"trigger_{j}_pretime"]), "post_time": typing.cast(float, trigger[f"trigger_{j}_posttime"]), } yield trigger_info def info(self) -> dict[str, object]: """Get MDF information as a dict. Examples -------- >>> mdf = MDF('test.mdf') >>> mdf.info() """ info: dict[str, object] = { "author": self.header.author, "department": self.header.department, "project": self.header.project, "subject": self.header.subject, } info["version"] = self.version info["groups"] = len(self.groups) for i, gp in enumerate(self.groups): inf: dict[str, object] = {} info[f"group {i}"] = inf inf["cycles"] = gp.channel_group.cycles_nr inf["comment"] = gp.channel_group.comment inf["channels count"] = len(gp.channels) for j, channel in enumerate(gp.channels): name = channel.name if channel.channel_type == v23c.CHANNEL_TYPE_MASTER: ch_type = "master" else: ch_type = "value" inf[f"channel {j}"] = f'name="{name}" type={ch_type}' return info @property def start_time(self) -> datetime: """Getter and setter of the measurement start timestamp. Returns ------- timestamp : datetime.datetime Start timestamp. """ return self.header.start_time @start_time.setter def start_time(self, timestamp: datetime) -> None: self.header.start_time = timestamp def save( self, dst: StrPath, overwrite: bool = False, compression: CompressionType = 0, progress: Any | None = None, add_history_block: bool = True, ) -> Path: """Save `MDF` to `dst`. If `overwrite` is True, then the destination file is overwritten, otherwise the file name is appended with '.', where '' is the first counter that produces a new file name that does not already exist in the filesystem. Parameters ---------- dst : str | path-like Destination file name. overwrite : bool, default False Overwrite flag. compression : int, optional Does nothing for MDF version 3; introduced here to share the same API as MDF version 4 files. Returns ------- output_file : pathlib.Path Path to saved file. """ dst = Path(dst).with_suffix(".mdf") destination_dir = dst.parent destination_dir.mkdir(parents=True, exist_ok=True) if overwrite is False: if dst.is_file(): cntr = 0 while True: name = dst.with_suffix(f".{cntr}.mdf") if not name.exists(): break else: cntr += 1 message = ( f'Destination file "{dst}" already exists and "overwrite" is False. Saving MDF file as "{name}"' ) logger.warning(message) dst = name if not self.header.comment: self.header.comment = f""" created {tool.__tool__} {tool.__vendor__} {tool.__version__} """ else: old_history = self.header.comment timestamp = time.asctime() text = f"{old_history}\n{timestamp}: updated by {tool.__tool__} {tool.__version__}" self.header.comment = text defined_texts: dict[bytes | str, int] = {} cc_map: dict[bytes, int] = {} si_map: dict[bytes, int] = {} if dst == self.name: destination = dst.with_suffix(".savetemp") else: destination = dst with open(destination, "wb+") as dst_: groups_nr = len(self.groups) write = dst_.write seek = dst_.seek # list of all blocks blocks: list[bytes | SupportsBytes] = [] address = 0 write(bytes(self.identification)) address += v23c.ID_BLOCK_SIZE write(bytes(self.header)) address += self.header.block_len if self.header.program: write(bytes(self.header.program)) self.header.program_addr = address address += self.header.program.block_len else: self.header.program_addr = 0 comment = TextBlock(text=self.header.comment) write(bytes(comment)) self.header.comment_addr = address address += comment.block_len # DataGroup # put them first in the block list so they will be written first to # disk this way, in case of memory=False, we can safely # restore he original data block address gp_rec_ids = [] original_data_block_addrs = [group.data_group.data_block_addr for group in self.groups] for idx, gp in enumerate(self.groups): dg = gp.data_group gp_rec_ids.append(dg.record_id_len) dg.record_id_len = 0 # DataBlock dim = 0 for data_bytes, _, __ in self._load_data(gp): dim += len(data_bytes) write(data_bytes) if gp.data_blocks: gp.data_group.data_block_addr = address else: gp.data_group.data_block_addr = 0 address += dim if progress is not None: if callable(progress): progress(int(33 * (idx + 1) / groups_nr), 100) for gp in self.groups: dg = gp.data_group blocks.append(dg) dg.address = address address += dg.block_len if self.groups: for i, gp in enumerate(self.groups[:-1]): addr = self.groups[i + 1].data_group.address gp.data_group.next_dg_addr = addr self.groups[-1].data_group.next_dg_addr = 0 for idx, gp in enumerate(self.groups): # Channel Dependency cd = gp.channel_dependencies for dep in cd: if dep: dep.address = address blocks.append(dep) address += dep.block_len for channel, dep in zip(gp.channels, gp.channel_dependencies, strict=False): if dep: channel.component_addr = dep.address = address blocks.append(dep) address += dep.block_len else: channel.component_addr = 0 address = channel.to_blocks(address, blocks, defined_texts, cc_map, si_map) count = len(gp.channels) if count: for i in range(count - 1): gp.channels[i].next_ch_addr = gp.channels[i + 1].address gp.channels[-1].next_ch_addr = 0 # ChannelGroup cg = gp.channel_group if gp.channels: cg.first_ch_addr = gp.channels[0].address else: cg.first_ch_addr = 0 cg.next_cg_addr = 0 address = cg.to_blocks(address, blocks, defined_texts, si_map) # TriggerBLock trigger = gp.trigger if trigger: address = trigger.to_blocks(address, blocks) if progress is not None: progress.signals.setValue.emit(int(33 * (idx + 1) / groups_nr) + 33) progress.signals.setMaximum.emit(100) if progress.stop: dst_.close() self.close() raise Terminated # update referenced channels addresses in the channel dependencies for gp in self.groups: for dep in gp.channel_dependencies: if not dep: continue for i, pair_ in enumerate(dep.referenced_channels): dg_nr, ch_nr = pair_ grp = self.groups[dg_nr] ch = grp.channels[ch_nr] dep[f"ch_{i}"] = ch.address dep[f"cg_{i}"] = grp.channel_group.address dep[f"dg_{i}"] = grp.data_group.address # DataGroup for gp in self.groups: gp.data_group.first_cg_addr = gp.channel_group.address if gp.trigger: gp.data_group.trigger_addr = gp.trigger.address else: gp.data_group.trigger_addr = 0 if self.groups: address = self.groups[0].data_group.address self.header.first_dg_addr = address self.header.dg_nr = len(self.groups) if progress is not None and progress.stop: dst_.close() self.close() raise Terminated if progress is not None: blocks_nr = len(blocks) threshold = blocks_nr / 33 count = 1 for i, block in enumerate(blocks): write(bytes(block)) if i >= threshold: progress.signals.setValue.emit(66 + count) count += 1 threshold += blocks_nr / 33 else: for block in blocks: write(bytes(block)) for gp, rec_id, original_address in zip(self.groups, gp_rec_ids, original_data_block_addrs, strict=False): gp.data_group.record_id_len = rec_id gp.data_group.data_block_addr = original_address seek(0) write(bytes(self.identification)) write(bytes(self.header)) if dst == self.name: self.close() Path.unlink(self.name) Path.rename(destination, self.name) self.groups.clear() self.channels_db.clear() self.masters_db.clear() self._tempfile = NamedTemporaryFile(dir=self.temporary_folder) self._file = open(self.name, "rb") self._read(self._file) return dst def _sort(self, progress: Callable[[int, int], None] | Any | None = None) -> None: if self._file is None: return common: defaultdict[int, list[tuple[int, int]]] = defaultdict(list) for i, group in enumerate(self.groups): if group.sorted: continue if group.data_blocks: address = group.data_blocks[0].address common[address].append((i, group.channel_group.record_id)) read = self._file.read seek = self._file.seek self._tempfile.seek(0, 2) tell = self._tempfile.tell write = self._tempfile.write for address, groups in common.items(): partial_records: dict[int, list[bytes]] = {id_: [] for (_, id_) in groups} group = self.groups[groups[0][0]] record_id_nr = group.data_group.record_id_len cg_size = group.record_size for info in group.data_blocks: address, size, block_size, block_type, param = ( info.address, info.original_size, info.compressed_size, info.block_type, info.param, ) seek(address) data = read(block_size) size = len(data) i = 0 while i < size: rec_id = data[i] # skip record id i += 1 rec_size = cg_size[rec_id] partial_records[rec_id].append(data[i : i + rec_size]) # consider the second record ID if it exists if record_id_nr == 2: i += rec_size + 1 else: i += rec_size data_blocks: dict[int, list[DataBlockInfo]] = {} for rec_id, new_data in partial_records.items(): if new_data: data = b"".join(new_data) size = len(data) address = tell() write(bytes(data)) block_info = DataBlockInfo( address=address, block_type=0, original_size=size, compressed_size=size, param=0, ) data_blocks[rec_id] = [block_info] for idx, rec_id in groups: group = self.groups[idx] group.data_location = v23c.LOCATION_TEMPORARY_FILE group.set_blocks_info(data_blocks[rec_id]) group.sorted = True def included_channels( self, index: int | None = None, channels: ChannelsType | None = None, skip_master: bool = True, minimal: bool = True, ) -> dict[int, dict[int, list[int]]]: if channels is None: if index is None: raise ValueError("index argument must be set if channels is unset") group = self.groups[index] gps: dict[int, list[int]] = {} included_channels = set(range(len(group.channels))) master_index = self.masters_db.get(index, None) if master_index is not None and len(included_channels) > 1: included_channels.remove(master_index) for dep in group.channel_dependencies: if dep is None: continue for gp_nr, ch_nr in dep.referenced_channels: if gp_nr == index: included_channels.remove(ch_nr) if included_channels: gps[index] = sorted(included_channels) result = {index: gps} else: group_sets: dict[int, set[int]] = {} for item in channels: if isinstance(item, (list, tuple)): if len(item) not in (2, 3): raise MdfException( "The items used for filtering must be strings, " "or they must match the first 3 arguments of the get " "method" ) else: gp_idx, idx = self._validate_channel_selection(*item) if gp_idx not in group_sets: group_sets[gp_idx] = {idx} else: group_sets[gp_idx].add(idx) else: name = item gp_idx, idx = self._validate_channel_selection(name) if gp_idx not in group_sets: group_sets[gp_idx] = {idx} else: group_sets[gp_idx].add(idx) result = {} for group_index, _channels in group_sets.items(): group = self.groups[group_index] channel_dependencies = [group.channel_dependencies[ch_nr] for ch_nr in _channels] if minimal: for dep in channel_dependencies: if dep is None: continue for gp_nr, ch_nr in dep.referenced_channels: if gp_nr == group_index: try: _channels.remove(ch_nr) except KeyError: pass gp_master = self.masters_db.get(group_index, None) if skip_master and gp_master is not None and gp_master in _channels and len(_channels) > 1: _channels.remove(gp_master) result[group_index] = {group_index: sorted(_channels)} return result def _yield_selected_signals( self, index: int, groups: dict[int, list[int]] | None = None, record_offset: int = 0, record_count: int | None = None, skip_master: bool = True, version: str = "4.20", ) -> Iterator[list[Signal] | list[tuple[NDArray[Any], None]]]: if groups is None: groups = self.included_channels(index)[index] channels = groups[index] group = self.groups[index] encodings: list[str | None] = [ None, ] self._set_temporary_master(None) for idx, fragment in enumerate(self._load_data(group, record_offset=record_offset, record_count=record_count)): master = self.get_master(index, data=fragment) self._set_temporary_master(master) self._prepare_record(group) signals: list[Signal] | list[tuple[NDArray[Any], None]] # the first fragment triggers and append that will add the # metadata for all channels if idx == 0: signals = [ self.get( group=index, index=channel_index, data=fragment, raw=True, ignore_invalidation_bits=True, samples_only=False, ) for channel_index in channels ] else: signals = [(master, None)] for channel_index in channels: signals.append( self.get( group=index, index=channel_index, data=fragment, raw=True, ignore_invalidation_bits=True, samples_only=True, ) ) if version < "4.00": if idx == 0: signals = typing.cast(list[Signal], signals) for sig, channel_index in zip(signals, channels, strict=False): if sig.samples.dtype.kind == "S": encodings.append(sig.encoding) strsig = self.get( group=index, index=channel_index, samples_only=True, ignore_invalidation_bits=True, )[0] sig.samples = sig.samples.astype(strsig.dtype) del strsig if sig.encoding != "latin-1": if sig.encoding == "utf-16-le": sig.samples = sig.samples.view(uint16).byteswap().view(sig.samples.dtype) sig.samples = encode(decode(sig.samples, "utf-16-be"), "latin-1") else: sig.samples = encode(decode(sig.samples, sig.encoding), "latin-1") else: encodings.append(None) else: signals = typing.cast(list[tuple[NDArray[Any], None]], signals) for i, (signal_samples, encoding) in enumerate(zip(signals, encodings, strict=False)): if encoding: samples = signal_samples[0] if encoding != "latin-1": if encoding == "utf-16-le": samples = samples.view(uint16).byteswap().view(samples.dtype) samples = encode(decode(samples, "utf-16-be"), "latin-1") else: samples = encode(decode(samples, encoding), "latin-1") signals[i] = (samples, signal_samples[1]) self._set_temporary_master(None) yield signals def reload_header(self) -> None: if self._file is None: raise RuntimeError("self._file is None") self.header = HeaderBlock(address=0x40, stream=self._file) def _determine_max_vlsd_sample_size(self, group: int, index: int) -> int: return 0 if __name__ == "__main__": pass asammdf-8.5.1/src/asammdf/blocks/mdf_v4.py000066400000000000000000017233251502633300400203530ustar00rootroot00000000000000"""ASAM MDF version 4 file format module""" import bisect from collections import defaultdict, deque from collections.abc import Callable, Collection, Iterable, Iterator, Sequence from copy import deepcopy from datetime import datetime from functools import lru_cache from hashlib import md5 from io import StringIO import logging from math import ceil, floor from mimetypes import guess_type import mmap import os from pathlib import Path import re import shutil import sys import tempfile from tempfile import gettempdir, NamedTemporaryFile from traceback import format_exc import typing from typing import BinaryIO, Final, Literal, TYPE_CHECKING from zipfile import ZIP_DEFLATED, ZipFile import canmatrix from canmatrix.canmatrix import CanMatrix from lz4.frame import compress as lz_compress from lz4.frame import decompress as lz_decompress import numpy as np from numpy import ( arange, argwhere, array, array_equal, column_stack, concatenate, empty, float32, float64, frombuffer, full, linspace, nonzero, searchsorted, transpose, uint8, uint16, uint32, uint64, unique, where, zeros, ) from numpy.typing import DTypeLike, NDArray from pandas import DataFrame, Series from typing_extensions import ( Any, Buffer, overload, SupportsBytes, TypedDict, TypeIs, Unpack, ) from .. import tool from ..signal import InvalidationArray, Signal from . import bus_logging_utils, mdf_common, utils from . import v4_constants as v4c from .conversion_utils import conversion_transfer from .cutils import ( data_block_from_arrays, extract, get_channel_raw_bytes, get_channel_raw_bytes_parallel, get_invalidation_bits_array, get_vlsd_max_sample_size, sort_data_block, ) from .mdf_common import LastCallInfo, MDF_Common, MdfCommonKwargs from .options import GLOBAL_OPTIONS from .source_utils import Source from .types import ( BusType, ChannelsType, CompressionType, DbcFileType, RasterType, StrPath, ) from .utils import ( all_blocks_addresses, as_non_byte_sized_signed_int, CHANNEL_COUNT, CONVERT, count_channel_groups, DataBlockInfo, extract_display_names, extract_encryption_information, extract_xml_comment, FileLike, fmt_to_datatype_v4, Fragment, get_fmt_v4, get_text_v4, InvalidationBlockInfo, is_file_like, load_can_database, MdfException, SignalDataBlockInfo, Terminated, THREAD_COUNT, TxMap, UINT8_uf, UINT16_uf, UINT32_p, UINT32_uf, UINT64_uf, UniqueDB, validate_version_argument, VirtualChannelGroup, ) from .v4_blocks import ( AttachmentBlock, Channel, ChannelArrayBlock, ChannelArrayBlockKwargs, ChannelConversion, ChannelGroup, ChannelGroupKwargs, ChannelKwargs, DataBlock, DataGroup, DataList, DataListKwargs, DataZippedBlock, DataZippedBlockKwargs, EventBlock, FileHistory, FileIdentificationBlock, HeaderBlock, HeaderList, HeaderListKwargs, ListData, ListDataKwargs, SourceInformation, TextBlock, ) from .v4_constants import Version try: from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes CRYPTOGRAPHY_AVAILABLE = True except: CRYPTOGRAPHY_AVAILABLE = False try: from isal.isal_zlib import decompress except ImportError: from zlib import decompress if TYPE_CHECKING: from ..mdf import MDF try: decode = np.strings.decode encode = np.strings.encode except: decode = np.char.decode encode = np.char.encode MASTER_CHANNELS: Final = (v4c.CHANNEL_TYPE_MASTER, v4c.CHANNEL_TYPE_VIRTUAL_MASTER) COMMON_SIZE: Final = v4c.COMMON_SIZE COMMON_u = v4c.COMMON_u COMMON_uf = v4c.COMMON_uf COMMON_SHORT_SIZE: Final = v4c.COMMON_SHORT_SIZE COMMON_SHORT_uf = v4c.COMMON_SHORT_uf COMMON_SHORT_u = v4c.COMMON_SHORT_u VALID_DATA_TYPES: Final = v4c.VALID_DATA_TYPES EMPTY_TUPLE: Final = () # 100 extra steps for the sorting, 1 step after sorting and 1 step at finish SORT_STEPS: Final = 102 logger = logging.getLogger("asammdf") __all__ = ["MDF4"] Group = mdf_common.GroupV4 class BusLoggingMap(TypedDict): CAN: dict[int, dict[int, int]] ETHERNET: dict[int, int] FLEXRAY: dict[int, int] LIN: dict[int, int] class Kwargs(MdfCommonKwargs, total=False): column_storage: bool process_bus_logging: bool class MDF4(MDF_Common[Group]): r"""The `header` attribute is a `HeaderBlock`. The `groups` attribute is a list of `Group` objects, each one with the following attributes: * ``data_group`` - `DataGroup` object * ``channel_group`` - `ChannelGroup` object * ``channels`` - list of `Channel` objects with the same order as found in the MDF file * ``channel_dependencies`` - list of `ChannelArrayBlock` objects in case of channel arrays; list of `Channel` objects in case of structure channel composition * ``data_blocks`` - list of `DataBlockInfo` objects, each one containing address, type, size and other information about the block * ``data_location`` - integer code for data location (original file, temporary file or memory) * ``data_block_addr`` - list of raw samples starting addresses * ``data_block_type`` - list of codes for data block type * ``data_block_size`` - list of raw samples block size * ``sorted`` - sorted indicator flag * ``record_size`` - dict that maps record IDs to record sizes in bytes (including invalidation bytes) * ``param`` - row size used for transposition, in case of transposed zipped blocks Parameters ---------- name : str | path-like | file-like, optional MDF file name (if provided it must be a real file name) or file-like object. version : str, default '4.10' MDF file version ('4.00', '4.10', '4.11', '4.20'). use_display_names : bool, default True Parse the XML channel comment to search for the display name; XML parsing is quite expensive so setting this to False can decrease the loading times very much. remove_source_from_channel_names : bool, default False Remove source from channel names ("Speed\XCP3" -> "Speed"). compact_vlsd (False) : bool, optional Use slower method to save the exact sample size for VLSD channels. column_storage : bool, default True Use column storage for MDF version >= 4.20. password : bytes | str, optional Use this password to decode encrypted attachments. Attributes ---------- attachments : list List of file attachments. channels_db : dict Used for fast channel access by name; for each name key the value is a list of (group index, channel index) tuples. events : list List event blocks. file_history : list List of (FileHistory, TextBlock) pairs. groups : list List of data group dicts. header : HeaderBlock MDF file header. identification : FileIdentificationBlock MDF file start block. last_call_info : dict | None A dict to hold information about the last called method. .. versionadded:: 5.12.0 masters_db : dict Used for fast master channel access; for each group index key the value is the master channel index. name : pathlib.Path MDF file name. version : str MDF version. """ def __init__( self, name: StrPath | FileLike | None = None, version: Version = "4.10", channels: list[str] | None = None, **kwargs: Unpack[Kwargs], ) -> None: if not kwargs.get("__internal__", False): raise MdfException("Always use the MDF class; do not use the class MDF4 directly") # bind cache to instance to avoid memory leaks self.determine_max_vlsd_sample_size = lru_cache(maxsize=1024 * 1024)(self._determine_max_vlsd_sample_size) self.extract_attachment = lru_cache(maxsize=128)(self._extract_attachment) self._kwargs = kwargs self.original_name = kwargs["original_name"] self.file_history: list[FileHistory] = [] self.masters_db: dict[int, int] = {} self.attachments: list[AttachmentBlock] = [] self._attachments_cache: dict[bytes | str, int] = {} self.events: list[EventBlock] = [] self.bus_logging_map: BusLoggingMap = {"CAN": {}, "ETHERNET": {}, "FLEXRAY": {}, "LIN": {}} self._attachments_map: dict[int, int] = {} self._ch_map: dict[int, tuple[int, int]] = {} self._master_channel_metadata: dict[int, tuple[str, int]] = {} self._invalidation_cache: dict[tuple[int, int, int, int], InvalidationArray] = {} self._external_dbc_cache: dict[bytes, CanMatrix] = {} self._si_map: dict[bytes | int | Source, SourceInformation] = {} self._file_si_map: dict[object, object] = {} self._cc_map: dict[bytes | int, ChannelConversion] = {} self._file_cc_map: dict[object, object] = {} self._cg_map: dict[int, int] = {} self._cn_data_map: dict[int, tuple[int, int]] = {} self._dbc_cache: dict[int, CanMatrix] = {} self._interned_strings: TxMap = {} self._closed = False self.temporary_folder = kwargs.get("temporary_folder", GLOBAL_OPTIONS["temporary_folder"]) if channels is None: self.load_filter: set[str] = set() self.use_load_filter = False else: self.load_filter = set(channels) self.use_load_filter = True self._tempfile = NamedTemporaryFile(dir=self.temporary_folder) self._mapped_file: BinaryIO | None = None self._file: FileLike | mmap.mmap | None = None self._read_fragment_size = GLOBAL_OPTIONS["read_fragment_size"] self._write_fragment_size = GLOBAL_OPTIONS["write_fragment_size"] self._single_bit_uint_as_bool = GLOBAL_OPTIONS["single_bit_uint_as_bool"] self._integer_interpolation = GLOBAL_OPTIONS["integer_interpolation"] self._float_interpolation = GLOBAL_OPTIONS["float_interpolation"] self._use_display_names = kwargs.get("use_display_names", GLOBAL_OPTIONS["use_display_names"]) self._fill_0_for_missing_computation_channels = kwargs.get( "fill_0_for_missing_computation_channels", GLOBAL_OPTIONS["fill_0_for_missing_computation_channels"], ) self._remove_source_from_channel_names = kwargs.get("remove_source_from_channel_names", False) self._password = kwargs.get("password", None) self._force_attachment_encryption = kwargs.get("force_attachment_encryption", False) self.compact_vlsd = kwargs.get("compact_vlsd", False) self.virtual_groups: dict[int, VirtualChannelGroup] = {} # master group 2 referencing groups self.virtual_groups_map: dict[int, int] = {} # group index 2 master group self.vlsd_max_length: dict[ tuple[int, str], int ] = {} # hint about the maximum vlsd length for group_index, name pairs self._master = None self.last_call_info: LastCallInfo = {} # make sure no appended block has the address 0 self._tempfile.write(b"\0") self._delete_on_close = False progress = kwargs.get("progress", None) self._column_storage = False super().__init__(kwargs.get("raise_on_multiple_occurrences", GLOBAL_OPTIONS["raise_on_multiple_occurrences"])) if name: if is_file_like(name): self._file = name self.name = self.original_name = Path("From_FileLike.mf4") self._from_filelike = True self._read(self._file, mapped=False, progress=progress) else: try: with open(name, "rb") as stream: identification = FileIdentificationBlock(stream=stream) version_str = identification.version_str.decode("utf-8").strip(" \n\t\0") flags = identification.unfinalized_standard_flags if version_str >= "4.10" and flags: tmpdir = Path(gettempdir()) if self.temporary_folder: tmpdir = Path(self.temporary_folder) self.name = tmpdir / f"{os.urandom(6).hex()}_{Path(name).name}" shutil.copy(name, self.name) self._file = open(self.name, "rb+") self._from_filelike = False self._delete_on_close = True self._read(self._file, mapped=False, progress=progress) else: if sys.maxsize < 2**32: self.name = Path(name) self._file = open(self.name, "rb") self._from_filelike = False self._read(self._file, mapped=False, progress=progress) else: self.name = Path(name) self._mapped_file = open(self.name, "rb") self._file = mmap.mmap(self._mapped_file.fileno(), 0, access=mmap.ACCESS_READ) self._from_filelike = False self._read(self._file, mapped=True, progress=progress) except: if self._file: self._file.close() if self._mapped_file: self._mapped_file.close() del self._file self._mapped_file = None raise else: self._from_filelike = False version = validate_version_argument(version) self.header = HeaderBlock() self.identification = FileIdentificationBlock(version=version) self.version: str = version if self.version >= "4.20": self._column_storage = kwargs.get("column_storage", True) else: self._column_storage = False self.name = Path("__new__.mf4") self._parent: MDF | None = None def __del__(self) -> None: self.close() def _check_finalised(self) -> int: flags = self.identification.unfinalized_standard_flags if flags & 1: message = f"Unfinalised file {self.name}: Update of cycle counters for CG/CA blocks required" logger.info(message) if flags & 1 << 1: message = f"Unfinalised file {self.name}: Update of cycle counters for SR blocks required" logger.info(message) if flags & 1 << 2: message = f"Unfinalised file {self.name}: Update of length for last DT block required" logger.info(message) if flags & 1 * 8: message = f"Unfinalised file {self.name}: Update of length for last RD block required" logger.info(message) if flags & 1 << 4: message = ( f"Unfinalised file {self.name}: Update of last DL block in each chained list of DL blocks required" ) logger.info(message) if flags & 1 << 5: message = ( f"Unfinalised file {self.name}: Update of cg_data_bytes and cg_inval_bytes in VLSD CG block required" ) logger.info(message) if flags & 1 << 6: message = ( f"Unfinalised file {self.name}:" " Update of offset values for VLSD channel required" " in case a VLSD CG block is used" ) logger.info(message) return flags def _read( self, stream: FileLike | mmap.mmap, mapped: bool = False, progress: Callable[[int, int], None] | Any | None = None, ) -> None: self._mapped = mapped dg_cntr = 0 stream.seek(0, 2) self.file_limit = stream.tell() stream.seek(0) cg_count, _ = count_channel_groups(stream) progress_steps = cg_count + SORT_STEPS if progress is not None: if callable(progress): progress(0, progress_steps) current_cg_index = 0 self.identification = FileIdentificationBlock(stream=stream, mapped=mapped) version = self.identification.version_str self.version = version.decode("utf-8").strip(" \n\t\r\0") if self.version >= "4.20": self._column_storage = self._kwargs.get("column_storage", True) else: self._column_storage = False if self.version >= "4.10": # Check for finalization past version 4.10 finalisation_flags = self._check_finalised() if finalisation_flags: message = f"Attempting finalization of {self.name}" logger.info(message) self._finalize(stream) self._mapped = mapped = False self.header = HeaderBlock(address=0x40, stream=stream, mapped=mapped) # read file history fh_addr = self.header.file_history_addr while fh_addr: if (fh_addr + v4c.FH_BLOCK_SIZE) > self.file_limit: logger.warning(f"File history address {fh_addr:X} is outside the file size {self.file_limit}") break history_block = FileHistory(address=fh_addr, stream=stream, mapped=mapped) self.file_history.append(history_block) fh_addr = history_block.next_fh_addr # read attachments at_addr = self.header.first_attachment_addr index = 0 while at_addr: if (at_addr + v4c.AT_COMMON_SIZE) > self.file_limit: logger.warning(f"Attachment address {at_addr:X} is outside the file size {self.file_limit}") break at_block = AttachmentBlock(address=at_addr, stream=stream, mapped=mapped) self._attachments_map[at_addr] = index self.attachments.append(at_block) at_addr = at_block.next_at_addr index += 1 # go to first date group and read each data group sequentially dg_addr = self.header.first_dg_addr while dg_addr: if (dg_addr + v4c.DG_BLOCK_SIZE) > self.file_limit: logger.warning(f"Data group address {dg_addr:X} is outside the file size {self.file_limit}") break new_groups = [] group = DataGroup(address=dg_addr, stream=stream, mapped=mapped) record_id_nr = group.record_id_len # go to first channel group of the current data group cg_addr = first_cg_addr = group.first_cg_addr cg_nr = 0 cg_size: dict[int, int] = {} while cg_addr: if (cg_addr + v4c.CG_BLOCK_SIZE) > self.file_limit: logger.warning(f"Channel group address {cg_addr:X} is outside the file size {self.file_limit}") break cg_nr += 1 if cg_addr == first_cg_addr: grp = Group(group) else: grp = Group(group.copy()) # read each channel group sequentially block = ChannelGroup( address=cg_addr, stream=stream, mapped=mapped, si_map=self._si_map, tx_map=self._interned_strings, ) self._cg_map[cg_addr] = dg_cntr channel_group = grp.channel_group = block grp.record_size = cg_size if channel_group.flags & v4c.FLAG_CG_VLSD: # VLDS flag record_id = channel_group.record_id cg_size[record_id] = 0 elif channel_group.flags & v4c.FLAG_CG_BUS_EVENT: samples_size = channel_group.samples_byte_nr inval_size = channel_group.invalidation_bytes_nr record_id = channel_group.record_id cg_size[record_id] = samples_size + inval_size else: # in case no `cg_flags` are set samples_size = channel_group.samples_byte_nr inval_size = channel_group.invalidation_bytes_nr record_id = channel_group.record_id cg_size[record_id] = samples_size + inval_size if record_id_nr: grp.sorted = False else: grp.sorted = True # go to first channel of the current channel group ch_addr = channel_group.first_ch_addr ch_cntr = 0 # Read channels by walking recursively in the channel group # starting from the first channel self._read_channels(ch_addr, grp, stream, dg_cntr, ch_cntr, mapped=mapped) cg_addr = channel_group.next_cg_addr dg_cntr += 1 current_cg_index += 1 if progress is not None: if callable(progress): progress(current_cg_index, progress_steps) new_groups.append(grp) # store channel groups record sizes dict in each # new group data belong to the initial unsorted group, and add # the key 'sorted' with the value False to use a flag; address = group.data_block_addr total_size = 0 inval_total_size = 0 block_type = b"##DT" record_size = 0 for new_group in new_groups: channel_group = new_group.channel_group if channel_group.flags & v4c.FLAG_CG_REMOTE_MASTER: block_type = b"##DV" total_size += channel_group.samples_byte_nr * channel_group.cycles_nr inval_total_size += channel_group.invalidation_bytes_nr * channel_group.cycles_nr record_size = channel_group.samples_byte_nr else: block_type = b"##DT" total_size += ( channel_group.samples_byte_nr + channel_group.invalidation_bytes_nr ) * channel_group.cycles_nr record_size = channel_group.samples_byte_nr + channel_group.invalidation_bytes_nr if self.identification.unfinalized_standard_flags & v4c.FLAG_UNFIN_UPDATE_CG_COUNTER: total_size = 10**12 inval_total_size = 10**12 data_blocks_info = self._get_data_blocks_info( address=address, stream=stream, block_type=block_type, mapped=mapped, total_size=total_size, inval_total_size=inval_total_size, record_size=record_size, ) data_blocks = list(data_blocks_info) # load the info blocks directly here uses_ld = self._uses_ld( address=address, stream=stream, block_type=block_type, mapped=mapped, ) for grp in new_groups: grp.data_location = v4c.LOCATION_ORIGINAL_FILE grp.data_blocks_info_generator = data_blocks_info grp.data_blocks = data_blocks grp.uses_ld = uses_ld self._prepare_record(grp) self.groups.extend(new_groups) dg_addr = group.next_dg_addr # all channels have been loaded so now we can link the # channel dependencies and load the signal data for VLSD channels for gp_index, grp in enumerate(self.groups): if self.version >= "4.20" and grp.channel_group.flags & v4c.FLAG_CG_REMOTE_MASTER: grp.channel_group.cg_master_index = self._cg_map[grp.channel_group.cg_master_addr] index = grp.channel_group.cg_master_index else: index = gp_index self.virtual_groups_map[gp_index] = index if index not in self.virtual_groups: self.virtual_groups[index] = VirtualChannelGroup() virtual_channel_group = self.virtual_groups[index] virtual_channel_group.groups.append(gp_index) virtual_channel_group.record_size += ( grp.channel_group.samples_byte_nr + grp.channel_group.invalidation_bytes_nr ) virtual_channel_group.cycles_nr = grp.channel_group.cycles_nr for ch_index, dep_list in enumerate(grp.channel_dependencies): if not dep_list: continue for dep in dep_list: if isinstance(dep, ChannelArrayBlock): if dep.flags & v4c.FLAG_CA_DYNAMIC_AXIS: for i in range(dep.dims): ch_addr = typing.cast(int, dep[f"dynamic_size_{i}_ch_addr"]) if ch_addr: ref_channel = self._ch_map[ch_addr] dep.dynamic_size_channels.append(ref_channel) else: dep.dynamic_size_channels.append(None) if dep.flags & v4c.FLAG_CA_INPUT_QUANTITY: for i in range(dep.dims): ch_addr = typing.cast(int, dep[f"input_quantity_{i}_ch_addr"]) if ch_addr: ref_channel = self._ch_map[ch_addr] dep.input_quantity_channels.append(ref_channel) else: dep.input_quantity_channels.append(None) if dep.flags & v4c.FLAG_CA_OUTPUT_QUANTITY: ch_addr = dep.output_quantity_ch_addr if ch_addr: ref_channel = self._ch_map[ch_addr] dep.output_quantity_channel = ref_channel else: dep.output_quantity_channel = None if dep.flags & v4c.FLAG_CA_COMPARISON_QUANTITY: ch_addr = dep.comparison_quantity_ch_addr if ch_addr: ref_channel = self._ch_map[ch_addr] dep.comparison_quantity_channel = ref_channel else: dep.comparison_quantity_channel = None if dep.flags & v4c.FLAG_CA_AXIS: for i in range(dep.dims): cc_addr = typing.cast(int, dep[f"axis_conversion_{i}"]) if cc_addr: conv = ChannelConversion( stream=stream, address=cc_addr, mapped=mapped, tx_map={}, ) dep.axis_conversions.append(conv) else: dep.axis_conversions.append(None) if (dep.flags & v4c.FLAG_CA_AXIS) and not (dep.flags & v4c.FLAG_CA_FIXED_AXIS): for i in range(dep.dims): ch_addr = typing.cast(int, dep[f"scale_axis_{i}_ch_addr"]) if ch_addr: ref_channel = self._ch_map[ch_addr] dep.axis_channels.append(ref_channel) else: dep.axis_channels.append(None) else: break self._sort( stream, current_progress_index=current_cg_index, max_progress_count=progress_steps, progress=progress, ) if progress is not None: if callable(progress): progress(progress_steps - 1, progress_steps) # second to last step now for grp in self.groups: channels = grp.channels if len(channels) == 1 and channels[0].dtype_fmt.itemsize == grp.channel_group.samples_byte_nr: grp.single_channel_dtype = channels[0].dtype_fmt if self._kwargs.get("process_bus_logging", True): self._process_bus_logging() # read events addr = self.header.first_event_addr ev_map: dict[int, int] = {} event_index = 0 while addr: if (addr + v4c.COMMON_SIZE) > self.file_limit: logger.warning(f"Event address {addr:X} is outside the file size {self.file_limit}") break event = EventBlock(address=addr, stream=stream, mapped=mapped) event.update_references(self._ch_map, self._cg_map) self.events.append(event) ev_map[addr] = event_index event_index += 1 addr = event.next_ev_addr for event in self.events: addr = event.parent_ev_addr if addr: parent = ev_map.get(addr, None) if parent is not None: event.parent = parent else: event.parent = None addr = event.range_start_ev_addr if addr: range_start_ev_addr = ev_map.get(addr, None) if range_start_ev_addr is not None: event.parent = range_start_ev_addr else: event.parent = None self._si_map.clear() self._ch_map.clear() self._cc_map.clear() self._interned_strings.clear() self._attachments_map.clear() if progress is not None: if callable(progress): progress(progress_steps, progress_steps) # last step, we've completely loaded the file for sure self.progress = cg_count, cg_count @overload def _read_channels( self, ch_addr: int, grp: Group, stream: FileLike | mmap.mmap, dg_cntr: int, ch_cntr: int, parent_channel: Channel, mapped: bool = ..., ) -> tuple[int, list[ChannelArrayBlock] | list[tuple[int, int]], np.dtype[Any]]: ... @overload def _read_channels( self, ch_addr: int, grp: Group, stream: FileLike | mmap.mmap, dg_cntr: int, ch_cntr: int, parent_channel: None = ..., mapped: bool = ..., ) -> tuple[int, None, None]: ... def _read_channels( self, ch_addr: int, grp: Group, stream: FileLike | mmap.mmap, dg_cntr: int, ch_cntr: int, parent_channel: Channel | None = None, mapped: bool = False, ) -> tuple[int, list[ChannelArrayBlock] | list[tuple[int, int]] | None, np.dtype[Any] | None]: filter_channels = self.use_load_filter use_display_names = self._use_display_names channels = grp.channels dependencies = grp.channel_dependencies unique_names = UniqueDB() if parent_channel: composition: list[tuple[int, int]] | None = [] composition_channels: list[Channel] | None = [] else: composition = composition_channels = None if grp.channel_group.path_separator: path_separator = chr(grp.channel_group.path_separator) else: path_separator = "." while ch_addr: # read channel block and create channel object if (ch_addr + v4c.COMMON_SIZE) > self.file_limit: logger.warning(f"Channel address {ch_addr:X} is outside the file size {self.file_limit}") break if filter_channels: if utils.stream_is_mmap(stream, mapped): ( id_, links_nr, next_ch_addr, component_addr, name_addr, comment_addr, ) = v4c.CHANNEL_FILTER_uf(stream, ch_addr) channel_type = stream[ch_addr + v4c.COMMON_SIZE + links_nr * 8] name = get_text_v4(name_addr, stream, mapped=mapped, tx_map=self._interned_strings) if use_display_names: comment = get_text_v4(comment_addr, stream, mapped=mapped, tx_map=self._interned_strings) display_names = extract_display_names(comment) else: display_names = {} comment = None else: stream.seek(ch_addr) ( id_, links_nr, next_ch_addr, component_addr, name_addr, comment_addr, ) = v4c.CHANNEL_FILTER_u(stream.read(v4c.CHANNEL_FILTER_SIZE)) stream.seek(ch_addr + v4c.COMMON_SIZE + links_nr * 8) channel_type = stream.read(1)[0] name = get_text_v4(name_addr, stream, mapped=mapped, tx_map=self._interned_strings) if use_display_names: comment = get_text_v4(comment_addr, stream, mapped=mapped, tx_map=self._interned_strings) display_names = extract_display_names(comment) else: display_names = {} comment = None if id_ != b"##CN": message = f'Expected "##CN" block @{hex(ch_addr)} but found "{id_!r}"' raise MdfException(message) if self._remove_source_from_channel_names: name = name.split(path_separator, 1)[0] display_names = {_name.split(path_separator, 1)[0]: val for _name, val in display_names.items()} if ( parent_channel or channel_type in v4c.MASTER_TYPES or name in self.load_filter or (use_display_names and any(dsp_name in self.load_filter for dsp_name in display_names)) ): if comment is None: comment = get_text_v4(comment_addr, stream, mapped=mapped, tx_map=self._interned_strings) channel = Channel( address=ch_addr, stream=stream, cc_map=self._cc_map, si_map=self._si_map, at_map=self._attachments_map, use_display_names=use_display_names, mapped=mapped, tx_map=self._interned_strings, parsed_strings=(name, display_names, comment), ) si_path = getattr(channel.source, "path", "") if si_path and not self._remove_source_from_channel_names: path_name = f"{si_path}.{channel.name}" if path_name not in channel.display_names: channel.display_names[path_name] = "source_path" elif not component_addr: ch_addr = next_ch_addr continue else: if (component_addr + v4c.CC_ALG_BLOCK_SIZE) > self.file_limit: logger.warning( f"Channel component address {component_addr:X} is outside the file size {self.file_limit}" ) break # check if it is a CABLOCK or CNBLOCK stream.seek(component_addr) blk_id = stream.read(4) if blk_id == b"##CN": ( ch_cntr, _1, _2, ) = self._read_channels( component_addr, grp, stream, dg_cntr, ch_cntr, None, mapped=mapped, ) ch_addr = next_ch_addr continue else: channel = Channel( address=ch_addr, stream=stream, cc_map=self._cc_map, si_map=self._si_map, at_map=self._attachments_map, use_display_names=use_display_names, mapped=mapped, tx_map=self._interned_strings, parsed_strings=None, ) if channel.data_type not in VALID_DATA_TYPES: ch_addr = channel.next_ch_addr continue if channel.channel_type == v4c.CHANNEL_TYPE_SYNC: channel.attachment = self._attachments_map.get( channel.data_block_addr, None, ) if channel.source and channel.source.bus_type in v4c.BUS_LOGGING_TYPES and channel.source.path: path_name = f"{channel.source.path}.{channel.name}" if path_name not in channel.display_names: channel.display_names[path_name] = "source_path" if self._remove_source_from_channel_names: channel.name = channel.name.split(path_separator, 1)[0] channel.display_names = { _name.split(path_separator, 1)[0]: val for _name, val in channel.display_names.items() } entry = (dg_cntr, ch_cntr) self._ch_map[ch_addr] = entry channels.append(channel) if composition is not None and composition_channels is not None: composition.append(entry) composition_channels.append(channel) for _name in channel.display_names: self.channels_db.add(_name, entry) self.channels_db.add(channel.name, entry) # signal data cn_data_addr = channel.data_block_addr if cn_data_addr: grp.signal_data.append(([], self._get_signal_data_blocks_info(cn_data_addr, stream))) else: grp.signal_data.append(None) if cn_data_addr: self._cn_data_map[cn_data_addr] = entry if channel.channel_type in MASTER_CHANNELS: self.masters_db[dg_cntr] = ch_cntr ch_cntr += 1 component_addr = channel.component_addr if component_addr: if (component_addr + 4) > self.file_limit: logger.warning( f"Channel component address {component_addr:X} is outside the file size {self.file_limit}" ) break index = ch_cntr - 1 dependencies.append(None) # check if it is a CABLOCK or CNBLOCK stream.seek(component_addr) blk_id = stream.read(4) if blk_id == b"##CN": ( ch_cntr, ret_composition, ret_composition_dtype, ) = self._read_channels( component_addr, grp, stream, dg_cntr, ch_cntr, channel, mapped=mapped, ) dependencies[index] = ret_composition channel.dtype_fmt = ret_composition_dtype else: # only channel arrays with storage=CN_TEMPLATE are # supported so far channel.dtype_fmt = np.dtype( get_fmt_v4( channel.data_type, channel.bit_offset + channel.bit_count, channel.channel_type, ) ) first_dep = ca_block = ChannelArrayBlock(address=component_addr, stream=stream, mapped=mapped) ca_dependencies = [first_dep] while ca_block.composition_addr: stream.seek(ca_block.composition_addr) blk_id = stream.read(4) if blk_id == b"##CA": ca_block = ChannelArrayBlock( address=ca_block.composition_addr, stream=stream, mapped=mapped, ) ca_dependencies.append(ca_block) elif channel.data_type == v4c.DATA_TYPE_BYTEARRAY: # read CA-CN nested structure ( ch_cntr, ret_composition, ret_composition_dtype, ) = self._read_channels( ca_block.composition_addr, grp, stream, dg_cntr, ch_cntr, channel, mapped=mapped, ) ret_composition = typing.cast(list[ChannelArrayBlock], ret_composition) channel.dtype_fmt = ret_composition_dtype ca_cnt = len(ca_dependencies) if ret_composition: ca_dependencies.extend(ret_composition) byte_offset_factors: list[int] = [] bit_pos_inval_factors: list[int] = [] dimensions: list[int] = [] total_elem = 1 for ca_blck in ca_dependencies[:ca_cnt]: # only consider CN templates if ca_blck.ca_type != v4c.CA_STORAGE_TYPE_CN_TEMPLATE: logger.warning("Only CN template arrays are supported") continue # 1D array with dimensions for i in range(ca_blck.dims): dim_size = typing.cast(int, ca_blck[f"dim_size_{i}"]) dimensions.append(dim_size) total_elem *= dim_size # 1D arrays for byte offset and invalidation bit pos calculations byte_offset_factors.extend(ca_blck.get_byte_offset_factors()) bit_pos_inval_factors.extend(ca_blck.get_bit_pos_inval_factors()) multipliers = [1] * len(dimensions) for i in range(len(dimensions) - 2, -1, -1): multipliers[i] = multipliers[i + 1] * dimensions[i + 1] def _get_nd_coords(index: int, factors: list[int]) -> list[int]: """Convert 1D index to CA's nD coordinates.""" coords = [0] * len(factors) for i, factor in enumerate(factors): coords[i] = index // factor index %= factor return coords def _get_name_with_indices(ch_name: str, ch_parent_name: str, indices: list[int]) -> str: coords = "[" + "][".join(str(coord) for coord in indices) + "]" m = re.match(ch_parent_name, ch_name) n = re.search(r"\[\d+\]", ch_name) if m: name = ch_name[: m.end()] + coords + ch_name[m.end() :] elif n: name = ch_name[: n.start()] + coords + ch_name[n.start() :] else: name = ch_name + coords return name ch_len = len(channels) for elem_id in range(1, total_elem): for cn_id in range(index, ch_len): nd_coords = _get_nd_coords(elem_id, multipliers) # copy composition block new_block = deepcopy(channels[cn_id]) # update byte offset & position of invalidation bit byte_offset = bit_offset = 0 for coord, byte_factor, bit_factor in zip( nd_coords, byte_offset_factors, bit_pos_inval_factors, strict=False ): byte_offset += coord * byte_factor bit_offset += coord * bit_factor new_block.byte_offset += byte_offset new_block.pos_invalidation_bit += bit_offset # update channel name new_block.name = _get_name_with_indices(new_block.name, channel.name, nd_coords) # append to channel list channels.append(new_block) # update channel dependencies if (deps := dependencies[cn_id]) is not None: cn_deps: list[tuple[int, int]] = [] for dep in deps: if not isinstance(dep, ChannelArrayBlock): dep_entry = (dep[0], dep[1] + (ch_len - index) * elem_id) cn_deps.append(dep_entry) dependencies.append(cn_deps) else: dependencies.append(None) # update channels db entry = (dg_cntr, ch_cntr) self.channels_db.add(new_block.name, entry) ch_cntr += 1 # modify channels' names found recursively in-place orig_name = channel.name for cn_id in range(index, ch_len): nd_coords = _get_nd_coords(0, multipliers) name = _get_name_with_indices(channels[cn_id].name, orig_name, nd_coords) entries = self.channels_db.pop(channels[cn_id].name) channels[cn_id].name = name # original channel entry will only contain single source tuple self.channels_db.add(name, entries[0]) break else: logger.warning( "skipping CN block; Nested CA structure should be contained within BYTEARRAY data type" ) break dependencies[index] = ca_dependencies else: dependencies.append(None) channel.dtype_fmt = np.dtype( get_fmt_v4( channel.data_type, channel.bit_offset + channel.bit_count, channel.channel_type, ) ) # go to next channel of the current channel group ch_addr = channel.next_ch_addr if composition_channels is not None and parent_channel: composition_channels.sort(key=lambda x: x.byte_offset) padding = 0 dtype_fields: list[DTypeLike] = [] offset = parent_channel.byte_offset for comp_channel in composition_channels: if (delta := (comp_channel.byte_offset - offset)) > 0: dtype_fields.append((f"__padding_{padding}__", f"V{delta}")) padding += 1 dtype_fields.append((unique_names.get_unique_name(comp_channel.name), comp_channel.dtype_fmt)) offset = comp_channel.byte_offset + comp_channel.dtype_fmt.itemsize composition_dtype = np.dtype(dtype_fields) else: composition_dtype = None return ch_cntr, composition, composition_dtype def _load_signal_data( self, group: Group | None = None, index: int | None = None, offsets: tuple[int, int] | None = None, ) -> bytes: """This method is used to get the channel signal data, usually for VLSD channels. Returns ------- data : bytes Signal data bytes. """ if group is not None and index is not None: info_blocks = group.signal_data[index] if info_blocks is not None: stream: tempfile._TemporaryFileWrapper[bytes] | FileLike | mmap.mmap if offsets is None: data_list: list[bytes] = [] for info in group.get_signal_data_blocks(index): address, original_size, compressed_size, block_type, param = ( info.address, info.original_size, info.compressed_size, info.block_type, info.param, ) if not info.original_size: continue if info.location == v4c.LOCATION_TEMPORARY_FILE: stream = self._tempfile else: if self._file is None: raise RuntimeError("'_file' is None") stream = self._file stream.seek(address) new_data = stream.read(compressed_size) match block_type: case v4c.DZ_BLOCK_DEFLATE: new_data = decompress(new_data, bufsize=original_size) case v4c.DZ_BLOCK_TRANSPOSED: new_data = decompress(new_data, bufsize=original_size) cols = param lines = original_size // cols matrix_size = lines * cols if matrix_size != original_size: new_data = ( frombuffer(new_data[:matrix_size], dtype=uint8) .reshape((cols, lines)) .T.ravel() .tobytes() + new_data[matrix_size:] ) else: new_data = ( frombuffer(new_data, dtype=uint8).reshape((cols, lines)).T.ravel().tobytes() ) case v4c.DZ_BLOCK_LZ: new_data = lz_decompress(new_data) data_list.append(new_data) data = b"".join(data_list) else: start_offset, end_offset = offsets data_array = bytearray() start_offset = int(start_offset) end_offset = int(end_offset) last_sample_start = end_offset - start_offset current_offset = 0 for info in group.get_signal_data_blocks(index): address, original_size, compressed_size, block_type, param = ( info.address, info.original_size, info.compressed_size, info.block_type, info.param, ) if not info.original_size: continue if info.location == v4c.LOCATION_TEMPORARY_FILE: stream = self._tempfile else: if self._file is None: raise RuntimeError("'_file' is None") stream = self._file if current_offset + original_size < start_offset: current_offset += original_size continue stream.seek(address) new_data = stream.read(compressed_size) match block_type: case v4c.DZ_BLOCK_DEFLATE: new_data = decompress(new_data, bufsize=original_size) case v4c.DZ_BLOCK_TRANSPOSED: new_data = decompress(new_data, bufsize=original_size) cols = param lines = original_size // cols matrix_size = lines * cols if matrix_size != original_size: new_data = ( frombuffer(new_data[:matrix_size], dtype=uint8) .reshape((cols, lines)) .T.ravel() .tobytes() + new_data[matrix_size:] ) else: new_data = ( frombuffer(new_data, dtype=uint8).reshape((cols, lines)).T.ravel().tobytes() ) case v4c.DZ_BLOCK_LZ: new_data = lz_decompress(new_data) if start_offset > current_offset: data_array.extend(new_data[start_offset - current_offset :]) else: data_array.extend(new_data) current_offset += original_size if (current_data_size := len(data_array)) >= last_sample_start + 4: (last_sample_size,) = UINT32_uf(data_array, last_sample_start) required_size = last_sample_start + 4 + last_sample_size if required_size <= current_data_size: data = bytes(data_array[:required_size]) break else: data = bytes(data_array) else: data = b"" else: data = b"" return data def _load_data( self, group: Group, record_offset: int = 0, record_count: int | None = None, optimize_read: bool = False, ) -> Iterator[Fragment]: """Get group's data block bytes.""" from time import perf_counter cc = 0 offset = 0 invalidation_offset = 0 has_yielded = False _count = 0 data_blocks_info_generator = group.data_blocks_info_generator channel_group = group.channel_group stream: FileLike | mmap.mmap | tempfile._TemporaryFileWrapper[bytes] if group.data_location == v4c.LOCATION_ORIGINAL_FILE: stream = typing.cast(FileLike | mmap.mmap, self._file) else: stream = self._tempfile read = stream.read seek = stream.seek if group.uses_ld: samples_size = channel_group.samples_byte_nr invalidation_size = channel_group.invalidation_bytes_nr invalidation_record_offset = record_offset * invalidation_size rm = True else: rm = False samples_size = channel_group.samples_byte_nr + channel_group.invalidation_bytes_nr invalidation_size = channel_group.invalidation_bytes_nr record_offset *= samples_size finished = False if record_count is not None: invalidation_record_count = record_count * invalidation_size record_count *= samples_size max_size = record_count + invalidation_record_count else: max_size = (invalidation_size + samples_size) * channel_group.cycles_nr if not samples_size: if rm: yield Fragment(b"", offset, _count, b"") else: yield Fragment(b"", offset, _count, None) else: if group.read_split_count: split_size = group.read_split_count * samples_size invalidation_split_size = group.read_split_count * invalidation_size else: if self._read_fragment_size: split_size = self._read_fragment_size // samples_size invalidation_split_size = split_size * invalidation_size split_size *= samples_size else: channels_nr = len(group.channels) y_axis = CONVERT idx = int(searchsorted(CHANNEL_COUNT, channels_nr, side="right") - 1) idx = max(idx, 0) split_size = y_axis[idx] split_size = split_size // samples_size invalidation_split_size = split_size * invalidation_size split_size *= samples_size if split_size == 0: split_size = samples_size invalidation_split_size = invalidation_size split_size = int(split_size) if split_size > max_size: invalidation_split_size = (max_size // samples_size) * invalidation_size split_size = max_size buffer = bytearray(split_size) buffer_view = memoryview(buffer) invalidation_split_size = int(invalidation_split_size) blocks = iter(group.data_blocks) cur_size = 0 data: list[object] = [] cur_invalidation_size = 0 invalidation_data: list[bytes] = [] tt = perf_counter() ss = 0 cc = 0 while True: try: info = next(blocks) ( address, original_size, compressed_size, block_type, param, block_limit, ) = ( info.address, typing.cast(int, info.original_size), info.compressed_size, info.block_type, info.param, info.block_limit, ) if rm and invalidation_size: invalidation_info = info.invalidation_block else: invalidation_info = None except StopIteration: try: info = next(data_blocks_info_generator) ( address, original_size, compressed_size, block_type, param, block_limit, ) = ( info.address, typing.cast(int, info.original_size), info.compressed_size, info.block_type, info.param, info.block_limit, ) if rm and invalidation_size: invalidation_info = info.invalidation_block else: invalidation_info = None group.data_blocks.append(info) except StopIteration: break if offset + original_size < record_offset + 1: offset += original_size if rm and invalidation_size: if invalidation_info is None: raise RuntimeError( "'invalidation_info' cannot be None if 'rm and invalidation_size' is True" ) if invalidation_info.all_valid: count = original_size // samples_size invalidation_offset += count * invalidation_size else: invalidation_offset += typing.cast(int, invalidation_info.original_size) continue seek(address) new_data: bytes | memoryview[int] = read(typing.cast(int, compressed_size)) cc += 1 ss += original_size match block_type: case v4c.DZ_BLOCK_DEFLATE: new_data = decompress(new_data, bufsize=original_size) case v4c.DZ_BLOCK_TRANSPOSED: new_data = decompress(new_data, bufsize=original_size) cols = typing.cast(int, param) lines = original_size // cols matrix_size = lines * cols if matrix_size != original_size: new_data = ( frombuffer(new_data[:matrix_size], dtype=uint8) .reshape((cols, lines)) .T.ravel() .tobytes() + new_data[matrix_size:] ) else: new_data = frombuffer(new_data, dtype=uint8).reshape((cols, lines)).T.ravel().tobytes() case v4c.DZ_BLOCK_LZ: new_data = lz_decompress(new_data) if block_limit is not None: new_data = new_data[:block_limit] if len(new_data) > split_size - cur_size: new_data = memoryview(new_data) if rm and invalidation_size: if invalidation_info is None: raise RuntimeError("'invalidation_info' cannot be None if 'rm and invalidation_size' is True") if invalidation_info.all_valid: count = original_size // samples_size new_invalidation_data = b"\0" * (count * invalidation_size) else: seek(invalidation_info.address) compressed_size = typing.cast(int, invalidation_info.compressed_size) new_invalidation_data = read(compressed_size) original_size = typing.cast(int, invalidation_info.original_size) if invalidation_info.block_type == v4c.DZ_BLOCK_DEFLATE: new_invalidation_data = decompress( new_invalidation_data, bufsize=original_size, ) elif invalidation_info.block_type == v4c.DZ_BLOCK_TRANSPOSED: new_invalidation_data = decompress( new_invalidation_data, bufsize=original_size, ) cols = typing.cast(int, invalidation_info.param) lines = original_size // cols nd = frombuffer(new_invalidation_data[: lines * cols], dtype=uint8) nd = nd.reshape((cols, lines)) new_invalidation_data = nd.T.ravel().tobytes() + new_invalidation_data[lines * cols :] if invalidation_info.block_limit is not None: new_invalidation_data = new_invalidation_data[: invalidation_info.block_limit] inv_size = len(new_invalidation_data) if offset < record_offset: delta = record_offset - offset new_data = new_data[delta:] original_size -= delta offset = record_offset if rm and invalidation_size: delta = invalidation_record_offset - invalidation_offset new_invalidation_data = new_invalidation_data[delta:] inv_size -= delta invalidation_offset = invalidation_record_offset while original_size >= split_size - cur_size: if cur_size: buffer_view[cur_size:] = new_data[: split_size - cur_size] new_data = new_data[split_size - cur_size :] if rm and invalidation_size: invalidation_data.append( new_invalidation_data[: invalidation_split_size - cur_invalidation_size] ) new_invalidation_data = new_invalidation_data[ invalidation_split_size - cur_invalidation_size : ] invalidation_data_ = b"".join(invalidation_data) if record_count is not None: if rm and invalidation_size: __data = buffer[:record_count] _count = len(__data) // samples_size yield Fragment( __data, offset // samples_size, _count, invalidation_data_[:invalidation_record_count], ) invalidation_record_count -= len(invalidation_data_) else: __data = buffer[:record_count] _count = len(__data) // samples_size yield Fragment(__data, offset // samples_size, _count, None) has_yielded = True record_count -= split_size if record_count <= 0: finished = True break else: if rm and invalidation_size: _count = split_size // samples_size yield Fragment(buffer, offset // samples_size, _count, invalidation_data_) else: _count = split_size // samples_size yield Fragment(buffer, offset // samples_size, _count, None) has_yielded = True else: buffer_view[:] = new_data[:split_size] new_data = new_data[split_size:] if rm and invalidation_size: invalidation_data_ = new_invalidation_data[:invalidation_split_size] new_invalidation_data = new_invalidation_data[invalidation_split_size:] if record_count is not None: if rm and invalidation_size: yield Fragment( buffer[:record_count], offset // samples_size, _count, invalidation_data_[:invalidation_record_count], ) invalidation_record_count -= len(invalidation_data_) else: __data = buffer[:record_count] _count = len(__data) // samples_size yield Fragment(__data, offset // samples_size, _count, None) has_yielded = True record_count -= split_size if record_count <= 0: finished = True cur_size = 0 break else: if rm and invalidation_size: _count = split_size // samples_size yield Fragment(buffer, offset // samples_size, _count, invalidation_data_) else: _count = split_size // samples_size yield Fragment(buffer, offset // samples_size, _count, None) has_yielded = True offset += split_size original_size -= split_size - cur_size data = [] cur_size = 0 if rm and invalidation_size: invalidation_offset += invalidation_split_size invalidation_data = [] cur_invalidation_size = 0 inv_size -= invalidation_split_size - cur_invalidation_size if finished: cur_size = 0 original_size = 0 if rm and invalidation_size: invalidation_data = [] break if original_size > 0: buffer_view[cur_size : cur_size + original_size] = new_data cur_size += original_size if rm and invalidation_size: invalidation_data.append(new_invalidation_data) cur_invalidation_size += inv_size if record_count is not None and cur_size >= record_count: finished = True break if 0 and (vv := (perf_counter() - tt)) > 10: print(f"{ss / 1024 / 1024 / vv:.6f} MB/s {cc=} {vv=}") cc = 0 ss = 0 tt = perf_counter() if cur_size: data_ = buffer[:cur_size] if rm and invalidation_size: invalidation_data_ = b"".join(invalidation_data) if record_count is not None: if rm and invalidation_size: __data = data_[:record_count] _count = len(__data) // samples_size yield Fragment( __data, offset // samples_size, _count, invalidation_data_[:invalidation_record_count] ) invalidation_record_count -= len(invalidation_data_) else: __data = data_[:record_count] _count = len(__data) // samples_size yield Fragment(__data, offset // samples_size, _count, None) has_yielded = True record_count -= len(data_) else: if rm and invalidation_size: _count = len(data_) // samples_size yield Fragment(data_, offset // samples_size, _count, invalidation_data_) else: _count = len(data_) // samples_size yield Fragment(data_, offset // samples_size, _count, None) has_yielded = True if not has_yielded: if rm and invalidation_size: yield Fragment(b"", 0, 0, b"") else: yield Fragment(b"", 0, 0, None) def _prepare_record(self, group: Group) -> list[tuple[np.dtype[Any], int, int, int] | None]: """Compute record. Parameters ---------- group : dict MDF group dict. Returns ------- record : list Mapping of channels to records fields, records fields dtype. """ if group.record is None: channels = group.channels record: list[tuple[np.dtype[Any], int, int, int] | None] = [] for idx, new_ch in enumerate(channels): start_offset = new_ch.byte_offset bit_offset = new_ch.bit_offset data_type = new_ch.data_type bit_count = new_ch.bit_count ch_type = new_ch.channel_type dependency_list = group.channel_dependencies[idx] if ch_type not in v4c.VIRTUAL_TYPES: # adjust size to 1, 2, 4 or 8 bytes size = bit_offset + bit_count byte_size, rem = divmod(size, 8) if rem: byte_size += 1 bit_size = byte_size * 8 if data_type in ( v4c.DATA_TYPE_SIGNED_MOTOROLA, v4c.DATA_TYPE_UNSIGNED_MOTOROLA, ): if size > 32: bit_offset += 64 - bit_size elif size > 16: bit_offset += 32 - bit_size elif size > 8: bit_offset += 16 - bit_size if new_ch.dtype_fmt == np.dtype(np.void): new_ch.dtype_fmt = np.dtype(get_fmt_v4(data_type, size, ch_type)) if ( bit_offset or dependency_list or (new_ch.dtype_fmt.kind in "ui" and size < 64 and size not in (8, 16, 32)) ): new_ch.standard_C_size = False record.append( ( new_ch.dtype_fmt, new_ch.dtype_fmt.itemsize, start_offset, bit_offset, ) ) else: record.append(None) group.record = record return group.record def _uses_ld( self, address: int, stream: FileLike | mmap.mmap, block_type: bytes = b"##DT", mapped: bool = False, ) -> bool: mapped = mapped or not is_file_like(stream) uses_ld = False if utils.stream_is_mmap(stream, mapped): if address: id_string, block_len = COMMON_SHORT_uf(stream, address) if id_string == b"##LD": uses_ld = True # or a header list elif id_string == b"##HL": hl = HeaderList(address=address, stream=stream, mapped=mapped) address = hl.first_dl_addr uses_ld = self._uses_ld( address, stream, block_type, mapped, ) else: if address: stream.seek(address) id_string, block_len = COMMON_SHORT_u(stream.read(COMMON_SHORT_SIZE)) # can be a DataBlock if id_string == b"##LD": uses_ld = True # or a header list elif id_string == b"##HL": hl = HeaderList(address=address, stream=stream) address = hl.first_dl_addr uses_ld = self._uses_ld( address, stream, block_type, mapped, ) return uses_ld def _get_data_blocks_info( self, address: int, stream: FileLike | mmap.mmap, block_type: bytes = b"##DT", mapped: bool = False, total_size: int = 0, inval_total_size: int = 0, record_size: int = 0, ) -> Iterator[DataBlockInfo]: mapped = mapped or not is_file_like(stream) if record_size > 4 * 1024 * 1024: READ_CHUNK_SIZE = record_size elif record_size: READ_CHUNK_SIZE = 4 * 1024 * 1024 // record_size * record_size else: READ_CHUNK_SIZE = 4 * 1024 * 1024 READ_CHUNK_SIZE = min(READ_CHUNK_SIZE, total_size) if utils.stream_is_mmap(stream, mapped): if address: id_string, block_len = COMMON_SHORT_uf(stream, address) # can be a DataBlock if id_string == block_type: size = block_len - 24 if size: size = min(size, total_size) address = address + COMMON_SIZE # split the DTBLOCK into chucks of up to 32MB while True: if size > READ_CHUNK_SIZE: total_size -= READ_CHUNK_SIZE size -= READ_CHUNK_SIZE yield DataBlockInfo( address=address, block_type=v4c.DT_BLOCK, original_size=READ_CHUNK_SIZE, compressed_size=READ_CHUNK_SIZE, param=0, block_limit=None, ) address += READ_CHUNK_SIZE else: if total_size < size: block_limit = total_size else: block_limit = None yield DataBlockInfo( address=address, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, block_limit=block_limit, ) break # or a DataZippedBlock elif id_string == b"##DZ": ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_uf(stream, address + v4c.DZ_INFO_COMMON_OFFSET) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED if total_size < original_size: block_limit = total_size else: block_limit = None total_size -= original_size yield DataBlockInfo( address=address + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, block_limit=block_limit, ) # or a DataList elif id_string == b"##DL": while address: dl = DataList(address=address, stream=stream, mapped=mapped) for i in range(dl.data_block_nr): addr = getattr(dl, f"data_block_addr{i}") id_string, block_len = COMMON_SHORT_uf(stream, addr) # can be a DataBlock if id_string == block_type: size = block_len - 24 if size: size = min(size, total_size) addr += COMMON_SIZE # split the DTBLOCK into chucks of up to 32MB while True: if size > READ_CHUNK_SIZE: total_size -= READ_CHUNK_SIZE size -= READ_CHUNK_SIZE yield DataBlockInfo( address=addr, block_type=v4c.DT_BLOCK, original_size=READ_CHUNK_SIZE, compressed_size=READ_CHUNK_SIZE, param=0, block_limit=None, ) addr += READ_CHUNK_SIZE else: if total_size < size: block_limit = total_size else: block_limit = None total_size -= size yield DataBlockInfo( address=addr, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, block_limit=block_limit, ) break # or a DataZippedBlock else: ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_uf(stream, addr + v4c.DZ_INFO_COMMON_OFFSET) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED if total_size < original_size: block_limit = total_size else: block_limit = None total_size -= original_size yield DataBlockInfo( address=addr + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, block_limit=block_limit, ) address = dl.next_dl_addr # or a ListData elif id_string == b"##LD": uses_ld = True while address: ld = ListData(address=address, stream=stream, mapped=mapped) has_invalidation = ld.flags & v4c.FLAG_LD_INVALIDATION_PRESENT for i in range(ld.data_block_nr): addr = getattr(ld, f"data_block_addr_{i}") id_string, block_len = COMMON_SHORT_uf(stream, addr) # can be a DataBlock if id_string == b"##DV": size = block_len - 24 if size: if total_size < size: block_limit = total_size else: block_limit = None total_size -= size data_info = DataBlockInfo( address=addr + COMMON_SIZE, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, block_limit=block_limit, ) # or a DataZippedBlock elif id_string == b"##DZ": ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_uf(stream, addr + v4c.DZ_INFO_COMMON_OFFSET) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED if total_size < original_size: block_limit = total_size else: block_limit = None total_size -= original_size data_info = DataBlockInfo( address=addr + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, block_limit=block_limit, ) if has_invalidation: inval_addr = typing.cast(int, ld[f"invalidation_bits_addr_{i}"]) if inval_addr: id_string, block_len = COMMON_SHORT_uf(stream, inval_addr) if id_string == b"##DI": size = block_len - 24 if size: if inval_total_size < size: block_limit = inval_total_size else: block_limit = None inval_total_size -= size data_info.invalidation_block = InvalidationBlockInfo( address=inval_addr + COMMON_SIZE, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, block_limit=block_limit, ) else: ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_uf( stream, inval_addr + v4c.DZ_INFO_COMMON_OFFSET, ) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED if inval_total_size < original_size: block_limit = inval_total_size else: block_limit = None inval_total_size -= original_size data_info.invalidation_block = InvalidationBlockInfo( address=inval_addr + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, block_limit=block_limit, ) else: data_info.invalidation_block = InvalidationBlockInfo( address=0, block_type=v4c.DT_BLOCK, original_size=None, compressed_size=None, param=None, all_valid=True, ) yield data_info address = ld.next_ld_addr # or a header list elif id_string == b"##HL": hl = HeaderList(address=address, stream=stream, mapped=mapped) address = hl.first_dl_addr yield from self._get_data_blocks_info( address, stream, block_type, mapped, total_size, inval_total_size, record_size, ) else: if address: stream.seek(address) id_string, block_len = COMMON_SHORT_u(stream.read(COMMON_SHORT_SIZE)) # can be a DataBlock if id_string == block_type: size = block_len - 24 if size: size = min(size, total_size) address = address + COMMON_SIZE # split the DTBLOCK into chucks of up to 32MB while True: if size > READ_CHUNK_SIZE: total_size -= READ_CHUNK_SIZE size -= READ_CHUNK_SIZE yield DataBlockInfo( address=address, block_type=v4c.DT_BLOCK, original_size=READ_CHUNK_SIZE, compressed_size=READ_CHUNK_SIZE, param=0, block_limit=None, ) address += READ_CHUNK_SIZE else: if total_size < size: block_limit = total_size else: block_limit = None yield DataBlockInfo( address=address, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, block_limit=block_limit, ) break # or a DataZippedBlock elif id_string == b"##DZ": stream.seek(address + v4c.DZ_INFO_COMMON_OFFSET) ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_u(stream.read(v4c.DZ_COMMON_INFO_SIZE)) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED if total_size < original_size: block_limit = total_size else: block_limit = None total_size -= original_size yield DataBlockInfo( address=address + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, block_limit=block_limit, ) # or a DataList elif id_string == b"##DL": while address: dl = DataList(address=address, stream=stream) for i in range(dl.data_block_nr): addr = getattr(dl, f"data_block_addr{i}") stream.seek(addr) id_string, block_len = COMMON_SHORT_u(stream.read(COMMON_SHORT_SIZE)) # can be a DataBlock if id_string == block_type: size = block_len - 24 if size: addr = addr + COMMON_SIZE # split the DTBLOCK into chucks of up to 32MB while True: if size > READ_CHUNK_SIZE: total_size -= READ_CHUNK_SIZE size -= READ_CHUNK_SIZE yield DataBlockInfo( address=addr, block_type=v4c.DT_BLOCK, original_size=READ_CHUNK_SIZE, compressed_size=READ_CHUNK_SIZE, param=0, block_limit=None, ) addr += READ_CHUNK_SIZE else: if total_size < size: block_limit = total_size else: block_limit = None total_size -= size yield DataBlockInfo( address=addr, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, block_limit=block_limit, ) break # or a DataZippedBlock elif id_string == b"##DZ": stream.seek(addr + v4c.DZ_INFO_COMMON_OFFSET) ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_u(stream.read(v4c.DZ_COMMON_INFO_SIZE)) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED if total_size < original_size: block_limit = total_size else: block_limit = None total_size -= original_size yield DataBlockInfo( address=addr + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, block_limit=block_limit, ) address = dl.next_dl_addr # or a DataList elif id_string == b"##LD": uses_ld = True while address: ld = ListData(address=address, stream=stream) has_invalidation = ld.flags & v4c.FLAG_LD_INVALIDATION_PRESENT for i in range(ld.data_block_nr): addr = getattr(ld, f"data_block_addr{i}") stream.seek(addr) id_string, block_len = COMMON_SHORT_u(stream.read(COMMON_SHORT_SIZE)) # can be a DataBlock if id_string == b"##DV": size = block_len - 24 if size: if total_size < size: block_limit = total_size else: block_limit = None total_size -= size data_info = DataBlockInfo( address=addr + COMMON_SIZE, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, block_limit=block_limit, ) # or a DataZippedBlock elif id_string == b"##DZ": stream.seek(addr + v4c.DZ_INFO_COMMON_OFFSET) ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_u(stream.read(v4c.DZ_COMMON_INFO_SIZE)) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED if total_size < original_size: block_limit = total_size else: block_limit = None total_size -= original_size data_info = DataBlockInfo( address=addr + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, block_limit=block_limit, ) if has_invalidation: inval_addr = typing.cast(int, ld[f"invalidation_bits_addr_{i}"]) if inval_addr: stream.seek(inval_addr) id_string, block_len = COMMON_SHORT_u(stream.read(COMMON_SHORT_SIZE)) if id_string == b"##DI": size = block_len - 24 if size: if inval_total_size < size: block_limit = inval_total_size else: block_limit = None inval_total_size -= size data_info.invalidation_block = InvalidationBlockInfo( address=inval_addr + COMMON_SIZE, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, block_limit=block_limit, ) else: stream.seek(inval_addr + v4c.DZ_INFO_COMMON_OFFSET) ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_u(stream.read(v4c.DZ_COMMON_INFO_SIZE)) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED if inval_total_size < original_size: block_limit = inval_total_size else: block_limit = None inval_total_size -= original_size data_info.invalidation_block = InvalidationBlockInfo( address=inval_addr + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, block_limit=block_limit, ) else: data_info.invalidation_block = InvalidationBlockInfo( address=0, block_type=v4c.DT_BLOCK, original_size=0, compressed_size=0, param=0, all_valid=True, ) yield data_info address = ld.next_ld_addr # or a header list elif id_string == b"##HL": hl = HeaderList(address=address, stream=stream) address = hl.first_dl_addr yield from self._get_data_blocks_info( address, stream, block_type, mapped, total_size, inval_total_size, record_size, ) def _get_signal_data_blocks_info( self, address: int, stream: FileLike | mmap.mmap, ) -> Iterator[SignalDataBlockInfo]: if not address: raise MdfException(f"Expected non-zero SDBLOCK address but got 0x{address:X}") stream.seek(address) id_string, block_len = COMMON_SHORT_u(stream.read(COMMON_SHORT_SIZE)) # can be a DataBlock if id_string == b"##SD": size = block_len - 24 if size: yield SignalDataBlockInfo( address=address + COMMON_SIZE, compressed_size=size, original_size=size, block_type=v4c.DT_BLOCK, ) # or a DataZippedBlock elif id_string == b"##DZ": stream.seek(address + v4c.DZ_INFO_COMMON_OFFSET) ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_u(stream.read(v4c.DZ_COMMON_INFO_SIZE)) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED yield SignalDataBlockInfo( address=address + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, ) # or a DataList elif id_string == b"##DL": while address: dl = DataList(address=address, stream=stream) for i in range(dl.data_block_nr): addr = typing.cast(int, dl[f"data_block_addr{i}"]) stream.seek(addr) id_string, block_len = COMMON_SHORT_u(stream.read(COMMON_SHORT_SIZE)) # can be a DataBlock if id_string == b"##SD": size = block_len - 24 if size: yield SignalDataBlockInfo( address=addr + COMMON_SIZE, compressed_size=size, original_size=size, block_type=v4c.DT_BLOCK, ) # or a DataZippedBlock elif id_string == b"##DZ": stream.seek(addr + v4c.DZ_INFO_COMMON_OFFSET) ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_u(stream.read(v4c.DZ_COMMON_INFO_SIZE)) if original_size: if zip_type == v4c.FLAG_DZ_DEFLATE: block_type_ = v4c.DZ_BLOCK_DEFLATE param = 0 else: block_type_ = v4c.DZ_BLOCK_TRANSPOSED yield SignalDataBlockInfo( address=addr + v4c.DZ_COMMON_SIZE, block_type=block_type_, original_size=original_size, compressed_size=zip_size, param=param, ) address = dl.next_dl_addr # or a header list elif id_string == b"##HL": hl = HeaderList(address=address, stream=stream) address = hl.first_dl_addr yield from self._get_signal_data_blocks_info( address, stream, ) def _filter_occurrences( self, occurrences: Iterator[tuple[int, int]], source_name: str | None = None, source_path: str | None = None, acq_name: str | None = None, ) -> Iterator[tuple[int, int]]: if source_name is not None: occurrences = ( (gp_idx, cn_idx) for gp_idx, cn_idx in occurrences if ((source := self.groups[gp_idx].channels[cn_idx].source) is not None and source.name == source_name) or ( (acq_source := self.groups[gp_idx].channel_group.acq_source) is not None and acq_source.name == source_name ) ) if source_path is not None: occurrences = ( (gp_idx, cn_idx) for gp_idx, cn_idx in occurrences if ((source := self.groups[gp_idx].channels[cn_idx].source) is not None and source.path == source_path) or ( (acq_source := self.groups[gp_idx].channel_group.acq_source) is not None and acq_source.path == source_path ) ) if acq_name is not None: occurrences = ( (gp_idx, cn_idx) for gp_idx, cn_idx in occurrences if self.groups[gp_idx].channel_group.acq_name == acq_name ) return occurrences def get_invalidation_bits( self, group_index: int, pos_invalidation_bit: int, fragment: Fragment, ) -> InvalidationArray: """Get invalidation indexes of the channels in the given group. Parameters ---------- group_index : int Group index. pos_invalidation_bit : int Channel invalidation bit position. fragment : Fragment Data bytes as a Fragment. Returns ------- invalidation_bits : iterable Iterable of valid channel indexes; if all are valid `None` is returned. """ group = self.groups[group_index] data_bytes, offset, _count, invalidation_bytes = ( fragment.data, fragment.record_offset, fragment.record_count, fragment.invalidation_data, ) if invalidation_bytes is None: invalidation_bytes_nr = group.channel_group.invalidation_bytes_nr samples_byte_nr = group.channel_group.samples_byte_nr record = group.record if record is None: self._prepare_record(group) invalidation_bytes = get_channel_raw_bytes( data_bytes, samples_byte_nr + invalidation_bytes_nr, samples_byte_nr, invalidation_bytes_nr, ) key = (group_index, offset, _count, pos_invalidation_bit) if key not in self._invalidation_cache: self._invalidation_cache[key] = InvalidationArray( get_invalidation_bits_array( invalidation_bytes, group.channel_group.invalidation_bytes_nr, pos_invalidation_bit ), (group_index, pos_invalidation_bit), ) return self._invalidation_cache[key] @overload def append( self, signals: DataFrame, acq_name: str | None = None, acq_source: Source | None = None, comment: str = "Python", common_timebase: bool = False, units: dict[str, str] | None = None, ) -> None: ... @overload def append( self, signals: list[Signal] | Signal, acq_name: str | None = None, acq_source: Source | None = None, comment: str = "Python", common_timebase: bool = False, units: dict[str, str] | None = None, ) -> int: ... @overload def append( self, signals: list[Signal] | Signal | DataFrame, acq_name: str | None = ..., acq_source: Source | None = ..., comment: str = ..., common_timebase: bool = ..., units: dict[str, str] | None = ..., ) -> int | None: ... def append( self, signals: list[Signal] | Signal | DataFrame, acq_name: str | None = None, acq_source: Source | None = None, comment: str = "Python", common_timebase: bool = False, units: dict[str, str] | None = None, ) -> int | None: """Append a new data group. For channel dependencies type Signals, the `samples` attribute must be a np.recarray. Parameters ---------- signals : list | Signal | pandas.DataFrame List of `Signal` objects, or a single `Signal` object, or a pandas DataFrame object. All bytes columns in the DataFrame must be *utf-8* encoded. acq_name : str, optional Channel group acquisition name. acq_source : Source, optional Channel group acquisition source. comment : str, default 'Python' Channel group comment. common_timebase : bool, default False Flag to hint that the signals have the same timebase. Only set this if you know for sure that all appended channels share the same time base. units : dict, optional Will contain the signal units mapped to the signal names when appending a pandas DataFrame. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> import pandas as pd Case 1: Conversion type None. >>> s1 = np.array([1, 2, 3, 4, 5]) >>> s2 = np.array([-1, -2, -3, -4, -5]) >>> s3 = np.array([0.1, 0.04, 0.09, 0.16, 0.25]) >>> t = np.array([0.001, 0.002, 0.003, 0.004, 0.005]) >>> s1 = Signal(samples=s1, timestamps=t, unit='+', name='Positive') >>> s2 = Signal(samples=s2, timestamps=t, unit='-', name='Negative') >>> s3 = Signal(samples=s3, timestamps=t, unit='flts', name='Floats') >>> mdf = MDF(version='4.10') >>> mdf.append([s1, s2, s3], comment='created by asammdf') Case 2: VTAB conversions from channels inside another file. >>> mdf1 = MDF('in.mf4') >>> ch1 = mdf1.get("Channel1_VTAB") >>> ch2 = mdf1.get("Channel2_VTABR") >>> mdf2 = MDF('out.mf4') >>> mdf2.append([ch1, ch2], comment='created by asammdf') >>> mdf2.append(ch1, comment='just a single channel') >>> df = pd.DataFrame.from_dict({'s1': np.array([1, 2, 3, 4, 5]), 's2': np.array([-1, -2, -3, -4, -5])}) >>> units = {'s1': 'V', 's2': 'A'} >>> mdf2.append(df, units=units) """ source_block = SourceInformation.from_common_source(acq_source) if acq_source else None if isinstance(signals, Signal): signals = [signals] elif isinstance(signals, DataFrame): self._append_dataframe( signals, acq_name=acq_name, acq_source=source_block, comment=comment, units=units, ) return None if not signals: return None # check if the signals have a common timebase # if not interpolate the signals using the union of all timebases supports_virtual_channels = self.version >= "4.10" virtual_master = False virtual_master_conversion = None if signals: t_ = signals[0].timestamps if ( supports_virtual_channels and all(sig.flags & sig.Flags.virtual_master for sig in signals) and all(np.array_equal(sig.timestamps, t_) for sig in signals) ): virtual_master = True virtual_master_conversion = signals[0].virtual_master_conversion t = t_ else: if not common_timebase: for s in signals[1:]: if not array_equal(s.timestamps, t_): different = True break else: different = False if different: times = [s.timestamps for s in signals] t = unique(concatenate(times)) if t.dtype != float64: t = t.astype(float64) signals = [ s.interp( t, integer_interpolation_mode=self._integer_interpolation, float_interpolation_mode=self._float_interpolation, ) for s in signals ] else: t = t_ else: t = t_ else: t = np.array([]) if self.version >= "4.20" and self._column_storage: return self._append_column_oriented(signals, acq_name=acq_name, acq_source=source_block, comment=comment) dg_cntr = len(self.groups) gp = Group(DataGroup()) gp_sdata = gp.signal_data = [] gp_channels = gp.channels = [] gp_dep = gp.channel_dependencies = [] gp_sig_types = gp.signal_types = [] cycles_nr = len(t) # channel group cg_kwargs: ChannelGroupKwargs = {"cycles_nr": cycles_nr, "samples_byte_nr": 0} gp.channel_group = ChannelGroup(**cg_kwargs) gp.channel_group.acq_name = acq_name gp.channel_group.acq_source = source_block gp.channel_group.comment = comment record = gp.record = [] inval_bits: dict[tuple[int, int], list[InvalidationArray] | InvalidationArray] = { InvalidationArray.ORIGIN_UNKNOWN: [] } if any(sig.invalidation_bits is not None for sig in signals): invalidation_bytes_nr = 1 gp.channel_group.invalidation_bytes_nr = invalidation_bytes_nr else: invalidation_bytes_nr = 0 self.groups.append(gp) fields: list[tuple[bytes | NDArray[Any], int]] = [] ch_cntr = 0 offset = 0 defined_texts: dict[str, int] = {} si_map = self._si_map # setup all blocks related to the time master channel file = self._tempfile tell = file.tell seek = file.seek seek(0, 2) if signals: master_metadata = signals[0].master_metadata else: master_metadata = None if master_metadata: time_name, sync_type = master_metadata match sync_type: case 0 | 1: time_unit = "s" case 2: time_unit = "deg" case 3: time_unit = "m" case 4: time_unit = "index" else: time_name, sync_type = "time", v4c.SYNC_TYPE_TIME time_unit = "s" gp.channel_group.acq_source = source_block if signals: # time channel if virtual_master: cn_kwargs: ChannelKwargs = { "channel_type": v4c.CHANNEL_TYPE_VIRTUAL_MASTER, "data_type": v4c.DATA_TYPE_UNSIGNED_INTEL, "sync_type": sync_type, "byte_offset": 0, "bit_offset": 0, "bit_count": 0, } ch = Channel(**cn_kwargs) ch.unit = time_unit ch.name = time_name ch.source = source_block ch.dtype_fmt = t.dtype ch.conversion = conversion_transfer(virtual_master_conversion, version=4) name = time_name gp_channels.append(ch) gp_sdata.append(None) self.channels_db.add(name, (dg_cntr, ch_cntr)) self.masters_db[dg_cntr] = 0 # time channel doesn't have channel dependencies gp_dep.append(None) ch_cntr += 1 gp_sig_types.append((v4c.SIGNAL_TYPE_VIRTUAL, 0)) else: t_type, t_size = fmt_to_datatype_v4(t.dtype, t.shape) cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_MASTER, "data_type": t_type, "sync_type": sync_type, "byte_offset": 0, "bit_offset": 0, "bit_count": t_size, } ch = Channel(**cn_kwargs) ch.unit = time_unit ch.name = time_name ch.source = source_block ch.dtype_fmt = t.dtype name = time_name gp_channels.append(ch) gp_sdata.append(None) self.channels_db.add(name, (dg_cntr, ch_cntr)) self.masters_db[dg_cntr] = 0 record.append( ( t.dtype, t.dtype.itemsize, 0, 0, ) ) # time channel doesn't have channel dependencies gp_dep.append(None) if not t.flags["C_CONTIGUOUS"]: t = np.ascontiguousarray(t) fields.append((t, t.itemsize)) offset += t_size // 8 ch_cntr += 1 gp_sig_types.append((v4c.SIGNAL_TYPE_SCALAR, t_size // 8)) for signal in signals: sig = signal samples = sig.samples sig_dtype = samples.dtype sig_shape = samples.shape names = sig_dtype.names name = signal.name if names is None: if supports_virtual_channels and sig.flags & sig.Flags.virtual: sig_type = v4c.SIGNAL_TYPE_VIRTUAL else: sig_type = v4c.SIGNAL_TYPE_SCALAR if sig_dtype.kind in "SV": sig_type = v4c.SIGNAL_TYPE_STRING else: prepare_record = False if names in (v4c.CANOPEN_TIME_FIELDS, v4c.CANOPEN_DATE_FIELDS): sig_type = v4c.SIGNAL_TYPE_CANOPEN elif names[0] != sig.name: sig_type = v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION else: sig_type = v4c.SIGNAL_TYPE_ARRAY # first add the signals in the simple signal list if sig_type == v4c.SIGNAL_TYPE_SCALAR: # compute additional byte offset for large records size s_type, s_size = fmt_to_datatype_v4(sig_dtype, sig_shape) if (s_type, s_size) == (v4c.DATA_TYPE_BYTEARRAY, 0): offsets = typing.cast(NDArray[np.uint64], arange(len(samples), dtype=uint64) * (sig_shape[1] + 4)) values = [ full(len(samples), sig_shape[1], dtype=uint32), samples, ] types_ = [("o", uint32), ("s", sig_dtype, sig_shape[1:])] records = np.rec.fromarrays(values, dtype=types_) data_size = len(records) * records.itemsize if data_size: data_addr = tell() info = SignalDataBlockInfo( address=data_addr, compressed_size=data_size, original_size=data_size, location=v4c.LOCATION_TEMPORARY_FILE, ) gp_sdata.append( ( [info], iter(EMPTY_TUPLE), ) ) records.tofile(file) else: data_addr = 0 gp_sdata.append( ( [], iter(EMPTY_TUPLE), ) ) byte_size = 8 cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VLSD, "bit_count": 64, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if invalidation_bytes_nr and signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = np.dtype(" 1: ch.dtype_fmt = np.dtype((sig_dtype, sig_shape[1:])) else: ch.dtype_fmt = sig_dtype ch.attachment = attachment # conversions for channel if signal.raw: ch.conversion = conversion_transfer(signal.conversion, version=4) # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) record.append( ( ch.dtype_fmt, ch.dtype_fmt.itemsize, offset, 0, ) ) offset += byte_size if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append((samples, byte_size)) gp_sdata.append(None) entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) ch_cntr += 1 # simple channels don't have channel dependencies gp_dep.append(None) elif sig_type == v4c.SIGNAL_TYPE_VIRTUAL: channel_type = v4c.CHANNEL_TYPE_VIRTUAL sync_type = v4c.SYNC_TYPE_NONE cn_kwargs = { "channel_type": channel_type, "sync_type": sync_type, "bit_count": 0, "byte_offset": offset, "bit_offset": 0, "data_type": v4c.DATA_TYPE_UNSIGNED_INTEL, "flags": 0, } ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names # conversions for channel ch.conversion = conversion_transfer(signal.virtual_conversion, version=4) # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) gp_sig_types.append((sig_type, 0)) gp_sdata.append(None) entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) ch_cntr += 1 # virtual channels don't have channel dependencies gp_dep.append(None) elif sig_type == v4c.SIGNAL_TYPE_CANOPEN: vals: bytes | NDArray[Any] if names == v4c.CANOPEN_TIME_FIELDS: record.append( ( np.dtype("V6"), 6, offset, 0, ) ) if not signal.samples.flags["C_CONTIGUOUS"]: vals = np.ascontiguousarray(signal.samples) else: vals = signal.samples fields.append((vals, 6)) byte_size = 6 s_type = v4c.DATA_TYPE_CANOPEN_TIME s_dtype = np.void(6) gp_sig_types.append((sig_type, 6)) else: record.append( ( np.dtype("V7"), 7, offset, 0, ) ) arrays: list[NDArray[Any]] = [] for field in ("ms", "min", "hour", "day", "month", "year"): if field == "hour": arrays.append(signal.samples[field] + (signal.samples["summer_time"] << 7)) elif field == "day": arrays.append(signal.samples[field] + (signal.samples["day_of_week"] << 4)) else: arrays.append(signal.samples[field]) vals = np.rec.fromarrays(arrays) if not vals.flags["C_CONTIGUOUS"]: vals = np.ascontiguousarray(vals) fields.append((vals, 7)) byte_size = 7 s_type = v4c.DATA_TYPE_CANOPEN_DATE s_dtype = np.void(7) gp_sig_types.append((sig_type, 7)) s_size = byte_size * 8 # there is no channel dependency gp_dep.append(None) # add channel block cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if invalidation_bytes_nr and signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = np.dtype(s_dtype) # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) offset += byte_size entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) gp_sdata.append(None) ch_cntr += 1 elif sig_type == v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION: ( offset, dg_cntr, ch_cntr, struct_self, new_fields, ) = self._append_structure_composition( gp, signal, offset, dg_cntr, ch_cntr, defined_texts, invalidation_bytes_nr, inval_bits, ) fields.extend(new_fields) gp_sig_types.append((sig_type, signal.samples.dtype.itemsize)) elif sig_type == v4c.SIGNAL_TYPE_ARRAY: if names is None: raise RuntimeError("'names' is None") # here we have channel arrays or mdf v3 channel dependencies samples = signal.samples[names[0]] shape = samples.shape[1:] if len(names) > 1 or len(shape) > 1: # add channel dependency block for composed parent channel dims_nr = len(shape) names_nr = len(names) if names_nr == 0: ca_kwargs: ChannelArrayBlockKwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_LOOKUP, "flags": v4c.FLAG_CA_FIXED_AXIS, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] elif len(names) == 1: ca_kwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_ARRAY, "flags": 0, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] else: ca_kwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_LOOKUP, "flags": v4c.FLAG_CA_AXIS, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] parent_dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([parent_dep]) else: # add channel dependency block for composed parent channel ca_kwargs = { "dims": 1, "ca_type": v4c.CA_TYPE_ARRAY, "flags": 0, "byte_offset_base": samples.dtype.itemsize, "dim_size_0": shape[0], } parent_dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([parent_dep]) # first we add the structure channel s_type, s_size = fmt_to_datatype_v4(samples.dtype, samples.shape, True) # add channel block cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if invalidation_bytes_nr and signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = samples.dtype record.append( ( samples.dtype, samples.dtype.itemsize, offset, 0, ) ) # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) size = s_size // 8 for dim in shape: size *= dim offset += size if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append((samples, size)) gp_sig_types.append((sig_type, size)) gp_sdata.append(None) entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) ch_cntr += 1 for name in names[1:]: samples = signal.samples[name] shape = samples.shape[1:] # add channel dependency block ca_kwargs = { "dims": 1, "ca_type": v4c.CA_TYPE_SCALE_AXIS, "flags": 0, "byte_offset_base": samples.dtype.itemsize, "dim_size_0": shape[0], } dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([dep]) # add components channel s_type, s_size = fmt_to_datatype_v4(samples.dtype, ()) byte_size = s_size // 8 or 1 cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if invalidation_bytes_nr and signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = samples.dtype record.append( ( samples.dtype, samples.dtype.itemsize, offset, 0, ) ) gp_channels.append(ch) entry = dg_cntr, ch_cntr parent_dep.axis_channels.append(entry) for dim in shape: byte_size *= dim offset += byte_size if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append((samples, byte_size)) gp_sdata.append(None) self.channels_db.add(name, entry) ch_cntr += 1 else: encoding = signal.encoding samples = signal.samples sig_dtype = samples.dtype match encoding: case "utf-8": data_type = v4c.DATA_TYPE_STRING_UTF_8 case "latin-1": data_type = v4c.DATA_TYPE_STRING_LATIN_1 case "utf-16-be": data_type = v4c.DATA_TYPE_STRING_UTF_16_BE case "utf-16-le": data_type = v4c.DATA_TYPE_STRING_UTF_16_LE case _: raise MdfException(f'wrong encoding "{encoding}" for string signal') if self.compact_vlsd: buffers: list[bytes] = [] offsets_list: list[int] = [] off = 0 if encoding == "utf-16-le": for elem in samples: offsets_list.append(off) size = len(elem) if size % 2: size += 1 elem = elem + b"\0" buffers.append(UINT32_p(size)) buffers.append(elem) off += size + 4 else: for elem in samples: offsets_list.append(off) size = len(elem) buffers.append(UINT32_p(size)) buffers.append(elem) off += size + 4 data_size = off offsets = array(offsets_list, dtype=uint64) if data_size: data_addr = tell() info = SignalDataBlockInfo( address=data_addr, compressed_size=data_size, original_size=data_size, location=v4c.LOCATION_TEMPORARY_FILE, ) gp_sdata.append( ( [info], iter(EMPTY_TUPLE), ) ) file.seek(0, 2) file.write(b"".join(buffers)) else: data_addr = 0 gp_sdata.append( ( [], iter(EMPTY_TUPLE), ) ) else: offsets = typing.cast( NDArray[np.uint64], arange(len(samples), dtype=uint64) * (signal.samples.itemsize + 4) ) values = [ full(len(samples), samples.itemsize, dtype=uint32), samples, ] types_ = [("o", uint32), ("s", sig_dtype)] records = np.rec.fromarrays(values, dtype=types_) data_size = len(records) * records.itemsize if data_size: data_addr = tell() info = SignalDataBlockInfo( address=data_addr, compressed_size=data_size, original_size=data_size, location=v4c.LOCATION_TEMPORARY_FILE, ) gp_sdata.append( ( [info], iter(EMPTY_TUPLE), ) ) records.tofile(file) else: data_addr = 0 gp_sdata.append( ( [], iter(EMPTY_TUPLE), ) ) # compute additional byte offset for large records size byte_size = 8 gp_sig_types.append((sig_type, 8)) cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VLSD, "bit_count": 64, "byte_offset": offset, "bit_offset": 0, "data_type": data_type, "flags": 0, } if invalidation_bytes_nr: if signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = np.dtype(" int: defined_texts: dict[str, int] = {} si_map = self._si_map # setup all blocks related to the time master channel file = self._tempfile tell = file.tell seek = file.seek write = file.write seek(0, 2) dg_cntr = initial_dg_cntr = len(self.groups) # add the master group gp = Group(DataGroup()) gp_sdata = gp.signal_data = [] gp_channels = gp.channels = [] gp_dep = gp.channel_dependencies = [] gp_sig_types: list[int] = [] gp.signal_types = gp_sig_types gp.uses_ld = True gp.sorted = True record = gp.record = [] timestamps = signals[0].timestamps cycles_nr = len(timestamps) # channel group cg_kwargs: ChannelGroupKwargs = {"cycles_nr": cycles_nr, "samples_byte_nr": 0} gp.channel_group = remote_master_channel_group = ChannelGroup(**cg_kwargs) gp.channel_group.acq_name = acq_name gp.channel_group.acq_source = acq_source gp.channel_group.comment = comment self.groups.append(gp) ch_cntr = 0 types: list[tuple[str, np.dtype[Any], tuple[int, ...]] | DTypeLike] = [] ch_cntr = 0 offset = 0 prepare_record = True source_block = acq_source master_metadata = signals[0].master_metadata if master_metadata: time_name, sync_type = master_metadata match sync_type: case 0 | 1: time_unit = "s" case 2: time_unit = "deg" case 3: time_unit = "m" case 4: time_unit = "index" case _: raise RuntimeError(f"unexpected sync_type '{sync_type}'") else: time_name, sync_type = "time", v4c.SYNC_TYPE_TIME time_unit = "s" gp.channel_group.acq_source = source_block # time channel t_type, t_size = fmt_to_datatype_v4(timestamps.dtype, timestamps.shape) cn_kwargs: ChannelKwargs = { "channel_type": v4c.CHANNEL_TYPE_MASTER, "data_type": t_type, "sync_type": sync_type, "byte_offset": 0, "bit_offset": 0, "bit_count": t_size, } ch = Channel(**cn_kwargs) ch.unit = time_unit ch.name = time_name ch.source = source_block ch.dtype_fmt = timestamps.dtype name = time_name gp_channels.append(ch) gp_sdata.append(None) self.channels_db.add(name, (dg_cntr, ch_cntr)) self.masters_db[dg_cntr] = 0 record.append( ( timestamps.dtype, timestamps.dtype.itemsize, offset, 0, ) ) # time channel doesn't have channel dependencies gp_dep.append(None) types.append((name, timestamps.dtype)) offset += t_size // 8 ch_cntr += 1 gp_sig_types.append(0) gp.channel_group.samples_byte_nr = offset # data block gp.sorted = True size = cycles_nr * timestamps.itemsize cg_master_index = dg_cntr virtual_group = VirtualChannelGroup() self.virtual_groups[cg_master_index] = virtual_group self.virtual_groups_map[dg_cntr] = dg_cntr virtual_group.groups.append(dg_cntr) virtual_group.record_size = offset virtual_group.cycles_nr = cycles_nr dg_cntr += 1 if size: data_address = tell() gp.data_location = v4c.LOCATION_TEMPORARY_FILE write(timestamps.tobytes()) chunk = self._write_fragment_size // timestamps.itemsize chunk *= timestamps.itemsize while size: if size > chunk: gp.data_blocks.append( DataBlockInfo( address=data_address, block_type=v4c.DT_BLOCK, original_size=chunk, compressed_size=chunk, param=0, ) ) data_address += chunk size -= chunk else: gp.data_blocks.append( DataBlockInfo( address=data_address, block_type=v4c.DT_BLOCK, original_size=size, compressed_size=size, param=0, ) ) size = 0 else: gp.data_location = v4c.LOCATION_TEMPORARY_FILE for signal in signals: gp = Group(DataGroup()) gp_sdata = gp.signal_data = [] gp_channels = gp.channels = [] gp_dep = gp.channel_dependencies = [] gp.signal_types = gp_sig_types = [] gp.sorted = True gp.uses_ld = True record = gp.record = [] # channel group cg_kwargs = { "cycles_nr": cycles_nr, "samples_byte_nr": 0, "flags": v4c.FLAG_CG_REMOTE_MASTER, } gp.channel_group = ChannelGroup(**cg_kwargs) gp.channel_group.acq_name = acq_name gp.channel_group.acq_source = acq_source gp.channel_group.comment = remote_master_channel_group.comment gp.channel_group.cg_master_index = cg_master_index self.groups.append(gp) types = [] ch_cntr = 0 offset = 0 field_names = UniqueDB() sig = signal samples = sig.samples sig_dtype = samples.dtype sig_shape = samples.shape names = sig_dtype.names name = signal.name if names is None: sig_type = v4c.SIGNAL_TYPE_SCALAR if sig_dtype.kind in "SV": sig_type = v4c.SIGNAL_TYPE_STRING else: if names in (v4c.CANOPEN_TIME_FIELDS, v4c.CANOPEN_DATE_FIELDS): sig_type = v4c.SIGNAL_TYPE_CANOPEN elif names[0] != sig.name: sig_type = v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION else: sig_type = v4c.SIGNAL_TYPE_ARRAY gp_sig_types.append(sig_type) # first add the signals in the simple signal list if sig_type == v4c.SIGNAL_TYPE_SCALAR: # compute additional byte offset for large records size s_type, s_size = fmt_to_datatype_v4(sig_dtype, sig_shape) byte_size = s_size // 8 or 1 if sig_dtype.kind == "u" and signal.bit_count <= 4: s_size = signal.bit_count if signal.flags & signal.Flags.stream_sync: channel_type = v4c.CHANNEL_TYPE_SYNC if signal.attachment: at_data, at_name, hash_sum = typing.cast(tuple[bytes, Path, bytes], signal.attachment) attachment_addr = self.attach(at_data, at_name, hash_sum, mime="video/avi", embedded=False) data_block_addr = attachment_addr else: data_block_addr = 0 sync_type = v4c.SYNC_TYPE_TIME else: channel_type = v4c.CHANNEL_TYPE_VALUE data_block_addr = 0 sync_type = v4c.SYNC_TYPE_NONE cn_kwargs = { "channel_type": channel_type, "sync_type": sync_type, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if signal.invalidation_bits is not None: invalidation_bits = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 else: invalidation_bits = None ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names # conversions for channel if signal.raw: ch.conversion = conversion_transfer(signal.conversion, version=4) # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) gp_sdata.append(None) entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) _shape = sig_shape[1:] types.append((name, sig_dtype, _shape)) gp.single_channel_dtype = ch.dtype_fmt = np.dtype((sig_dtype, _shape)) record.append( ( ch.dtype_fmt, ch.dtype_fmt.itemsize, 0, 0, ) ) offset = byte_size # simple channels don't have channel dependencies gp_dep.append(None) elif sig_type == v4c.SIGNAL_TYPE_CANOPEN: if names == v4c.CANOPEN_TIME_FIELDS: record.append( ( np.dtype("V6"), 6, 0, 0, ) ) types.append((name, "V6")) gp.single_channel_dtype = np.dtype("V6") byte_size = 6 s_type = v4c.DATA_TYPE_CANOPEN_TIME else: record.append( ( np.dtype("V7"), 7, 0, 0, ) ) vals: list[Any] = [] for field in ("ms", "min", "hour", "day", "month", "year"): if field == "hour": vals.append(signal.samples[field] + (signal.samples["summer_time"] << 7)) elif field == "day": vals.append(signal.samples[field] + (signal.samples["day_of_week"] << 4)) else: vals.append(signal.samples[field]) samples = np.rec.fromarrays(vals) types.append((name, "V7")) gp.single_channel_dtype = np.dtype("V7") byte_size = 7 s_type = v4c.DATA_TYPE_CANOPEN_DATE s_size = byte_size * 8 # there is no channel dependency gp_dep.append(None) # add channel block cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if signal.invalidation_bits is not None: invalidation_bits = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 else: invalidation_bits = None ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = gp.single_channel_dtype # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) offset = byte_size entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) gp_sdata.append(None) elif sig_type == v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION: ( offset, dg_cntr, ch_cntr, struct_self, new_fields, new_types, ) = self._append_structure_composition_column_oriented( gp, signal, field_names, offset, dg_cntr, ch_cntr, defined_texts, ) if signal.invalidation_bits is not None: invalidation_bits = signal.invalidation_bits else: invalidation_bits = None gp.signal_types = np.dtype(new_types) offset = gp.signal_types.itemsize samples = signal.samples elif sig_type == v4c.SIGNAL_TYPE_ARRAY: fields: list[NDArray[Any]] = [] if names is None: raise RuntimeError("'names' is None") # here we have channel arrays or mdf v3 channel dependencies samples = signal.samples[names[0]] shape = samples.shape[1:] if len(names) > 1 or len(shape) > 1: # add channel dependency block for composed parent channel dims_nr = len(shape) names_nr = len(names) if names_nr == 0: ca_kwargs: ChannelArrayBlockKwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_LOOKUP, "flags": v4c.FLAG_CA_FIXED_AXIS, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] elif len(names) == 1: ca_kwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_ARRAY, "flags": 0, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] else: ca_kwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_LOOKUP, "flags": v4c.FLAG_CA_AXIS, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] parent_dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([parent_dep]) else: # add channel dependency block for composed parent channel ca_kwargs = { "dims": 1, "ca_type": v4c.CA_TYPE_SCALE_AXIS, "flags": 0, "byte_offset_base": samples.dtype.itemsize, "dim_size_0": shape[0], } parent_dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([parent_dep]) field_name = field_names.get_unique_name(name) if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append(samples) dtype_pair = field_name, samples.dtype, shape types.append(dtype_pair) record.append( ( samples.dtype, samples.dtype.itemsize, offset, 0, ) ) # first we add the structure channel s_type, s_size = fmt_to_datatype_v4(samples.dtype, samples.shape, True) # add channel block cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if signal.invalidation_bits is not None: invalidation_bits = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 else: invalidation_bits = None ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = samples.dtype # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) size = s_size // 8 for dim in shape: size *= dim offset += size gp_sdata.append(None) entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) ch_cntr += 1 for name in names[1:]: field_name = field_names.get_unique_name(name) samples = signal.samples[name] shape = samples.shape[1:] if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append(samples) types.append((field_name, samples.dtype, shape)) record.append( ( samples.dtype, samples.dtype.itemsize, offset, 0, ) ) # add channel dependency block ca_kwargs = { "dims": 1, "ca_type": v4c.CA_TYPE_SCALE_AXIS, "flags": 0, "byte_offset_base": samples.dtype.itemsize, "dim_size_0": shape[0], } dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([dep]) # add components channel s_type, s_size = fmt_to_datatype_v4(samples.dtype, ()) byte_size = s_size // 8 or 1 cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if signal.invalidation_bits is not None: invalidation_bits = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 else: invalidation_bits = None ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = samples.dtype gp_channels.append(ch) entry = dg_cntr, ch_cntr parent_dep.axis_channels.append(entry) for dim in shape: byte_size *= dim offset += byte_size gp_sdata.append(None) self.channels_db.add(name, entry) ch_cntr += 1 gp.signal_types = np.dtype(types) samples = signal.samples else: encoding = signal.encoding samples = signal.samples sig_dtype = samples.dtype match encoding: case "utf-8": data_type = v4c.DATA_TYPE_STRING_UTF_8 case "latin-1": data_type = v4c.DATA_TYPE_STRING_LATIN_1 case "utf-16-be": data_type = v4c.DATA_TYPE_STRING_UTF_16_BE case "utf-16-le": data_type = v4c.DATA_TYPE_STRING_UTF_16_LE case _: raise MdfException(f'wrong encoding "{encoding}" for string signal') offsets = arange(len(samples), dtype=uint64) * (signal.samples.itemsize + 4) values = [full(len(samples), samples.itemsize, dtype=uint32), samples] types_ = [("o", uint32), ("s", sig_dtype)] array = np.rec.fromarrays(values, dtype=types_) data_size = len(array) * array.itemsize if data_size: data_addr = tell() info = SignalDataBlockInfo( address=data_addr, compressed_size=data_size, original_size=data_size, location=v4c.LOCATION_TEMPORARY_FILE, ) gp_sdata.append( ( [info], iter(EMPTY_TUPLE), ) ) array.tofile(file) else: data_addr = 0 gp_sdata.append( ( [], iter(EMPTY_TUPLE), ) ) # compute additional byte offset for large records size byte_size = 8 cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VLSD, "bit_count": 64, "byte_offset": offset, "bit_offset": 0, "data_type": data_type, "flags": 0, } if signal.invalidation_bits is not None: invalidation_bits = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 else: invalidation_bits = None ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names # conversions for channel conversion = conversion_transfer(signal.conversion, version=4) if signal.raw: ch.conversion = conversion # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) record.append( ( np.dtype(uint64), 8, offset, 0, ) ) offset = byte_size entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) types.append((name, uint64)) gp.single_channel_dtype = ch.dtype_fmt = np.dtype(uint64) samples = offsets # simple channels don't have channel dependencies gp_dep.append(None) gp.channel_group.samples_byte_nr = offset if invalidation_bits is not None: gp.channel_group.invalidation_bytes_nr = 1 virtual_group.groups.append(dg_cntr) self.virtual_groups_map[dg_cntr] = cg_master_index virtual_group.record_size += offset if signal.invalidation_bits: virtual_group.record_size += 1 dg_cntr += 1 size = cycles_nr * samples.itemsize if size: data_address = tell() data = samples.tobytes() raw_size = len(data) data = lz_compress(data, store_size=True) size = len(data) write(data) gp.data_blocks.append( DataBlockInfo( address=data_address, block_type=v4c.DZ_BLOCK_LZ, original_size=raw_size, compressed_size=size, param=0, ) ) if invalidation_bits is not None: addr = tell() data = invalidation_bits.tobytes() raw_size = len(data) data = lz_compress(data, store_size=True) size = len(data) write(data) gp.data_blocks[-1].invalidation_block = InvalidationBlockInfo( address=addr, block_type=v4c.DZ_BLOCK_LZ, original_size=raw_size, compressed_size=size, param=None, ) gp.data_location = v4c.LOCATION_TEMPORARY_FILE return initial_dg_cntr def _append_dataframe( self, df: DataFrame, acq_name: str | None = None, acq_source: SourceInformation | None = None, comment: str = "", units: dict[str, str] | None = None, ) -> None: """Append a new data group from a pandas DataFrame.""" units = units or {} if df.shape == (0, 0): return t: NDArray[Any] = df.index.values index_name = df.index.name time_name = index_name if isinstance(index_name, str) and index_name else "time" sync_type = v4c.SYNC_TYPE_TIME time_unit = "s" dg_cntr = len(self.groups) gp = Group(DataGroup()) gp_sdata = gp.signal_data = [] gp_channels = gp.channels = [] gp_dep = gp.channel_dependencies = [] gp_sig_types = gp.signal_types = [] record = gp.record = [] cycles_nr = len(t) # channel group cg_kwargs: ChannelGroupKwargs = {"cycles_nr": cycles_nr, "samples_byte_nr": 0} gp.channel_group = ChannelGroup(**cg_kwargs) gp.channel_group.acq_name = acq_name gp.channel_group.acq_source = acq_source gp.channel_group.comment = comment self.groups.append(gp) fields: list[NDArray[Any]] = [] types: list[DTypeLike | tuple[str, np.dtype[Any], tuple[int, ...]]] = [] ch_cntr = 0 offset = 0 field_names = UniqueDB() # setup all blocks related to the time master channel file = self._tempfile tell = file.tell seek = file.seek seek(0, 2) virtual_group = VirtualChannelGroup() self.virtual_groups[dg_cntr] = virtual_group self.virtual_groups_map[dg_cntr] = dg_cntr virtual_group.groups.append(dg_cntr) virtual_group.cycles_nr = cycles_nr # time channel t_type, t_size = fmt_to_datatype_v4(t.dtype, t.shape) cn_kwargs: ChannelKwargs = { "channel_type": v4c.CHANNEL_TYPE_MASTER, "data_type": t_type, "sync_type": sync_type, "byte_offset": 0, "bit_offset": 0, "bit_count": t_size, "min_raw_value": t[0] if cycles_nr else 0, "max_raw_value": t[-1] if cycles_nr else 0, "lower_limit": t[0] if cycles_nr else 0, "upper_limit": t[-1] if cycles_nr else 0, "flags": v4c.FLAG_PHY_RANGE_OK | v4c.FLAG_VAL_RANGE_OK, } ch = Channel(**cn_kwargs) ch.unit = time_unit ch.name = time_name ch.dtype_fmt = t.dtype name = time_name gp_channels.append(ch) gp_sdata.append(None) self.channels_db.add(name, (dg_cntr, ch_cntr)) self.masters_db[dg_cntr] = 0 record.append( ( t.dtype, t.dtype.itemsize, offset, 0, ) ) # time channel doesn't have channel dependencies gp_dep.append(None) fields.append(t) types.append((name, t.dtype)) field_names.get_unique_name(name) offset += t_size // 8 ch_cntr += 1 gp_sig_types.append(0) for signal in df.columns: if index_name == signal: continue sig: Series[Any] = df[signal] name = signal sig_type = v4c.SIGNAL_TYPE_SCALAR if sig.dtype.kind in "SV": sig_type = v4c.SIGNAL_TYPE_STRING gp_sig_types.append(sig_type) # first add the signals in the simple signal list if sig_type == v4c.SIGNAL_TYPE_SCALAR: # compute additional byte offset for large records size if sig.dtype.kind == "O": array = encode(sig.array.astype(str), "utf-8") else: array = sig.to_numpy() s_type, s_size = fmt_to_datatype_v4(array.dtype, array.shape) byte_size = s_size // 8 or 1 channel_type = v4c.CHANNEL_TYPE_VALUE data_block_addr = 0 sync_type = v4c.SYNC_TYPE_NONE cn_kwargs = { "channel_type": channel_type, "sync_type": sync_type, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, } ch = Channel(**cn_kwargs) ch.name = name ch.unit = units.get(name, "") ch.dtype_fmt = np.dtype((array.dtype, array.shape[1:])) record.append( ( ch.dtype_fmt, ch.dtype_fmt.itemsize, offset, 0, ) ) gp_channels.append(ch) offset += byte_size gp_sdata.append(None) self.channels_db.add(name, (dg_cntr, ch_cntr)) field_name = field_names.get_unique_name(name) fields.append(array) types.append((field_name, array.dtype, array.shape[1:])) ch_cntr += 1 # simple channels don't have channel dependencies gp_dep.append(None) elif sig_type == v4c.SIGNAL_TYPE_STRING: array = sig.to_numpy() offsets = arange(len(array), dtype=uint64) * (array.dtype.itemsize + 4) values = [full(len(array), array.dtype.itemsize, dtype=uint32), array] types_: list[DTypeLike] = [("", uint32), ("", array.dtype)] data = np.rec.fromarrays(values, dtype=types_) data_size = len(data) * data.itemsize if data_size: data_addr = tell() info = SignalDataBlockInfo( address=data_addr, compressed_size=data_size, original_size=data_size, location=v4c.LOCATION_TEMPORARY_FILE, ) gp_sdata.append( ( [info], iter(EMPTY_TUPLE), ) ) data.tofile(file) else: data_addr = 0 gp_sdata.append( ( [], iter(EMPTY_TUPLE), ) ) # compute additional byte offset for large records size byte_size = 8 cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VLSD, "bit_count": 64, "byte_offset": offset, "bit_offset": 0, "data_type": v4c.DATA_TYPE_STRING_UTF_8, "min_raw_value": 0, "max_raw_value": 0, "lower_limit": 0, "upper_limit": 0, "flags": 0, } ch = Channel(**cn_kwargs) ch.name = name ch.unit = units.get(name, "") ch.dtype_fmt = np.dtype(" tuple[int, int, int, tuple[int, int], list[tuple[NDArray[Any], int]]]: si_map = self._si_map fields: list[tuple[NDArray[Any], int]] = [] file = self._tempfile seek = file.seek seek(0, 2) gp = grp gp_sdata = gp.signal_data gp_channels = gp.channels gp_dep = gp.channel_dependencies record = self._prepare_record(gp) name = signal.name names = signal.samples.dtype.names if names is None: raise RuntimeError("'names' is None") # first we add the structure channel if signal.attachment and signal.attachment[0]: at_data, at_name, hash_sum = typing.cast(tuple[bytes, Path, bytes], signal.attachment) if at_name is not None: suffix = Path(at_name).suffix.lower().strip(".") else: suffix = "dbc" if suffix == "a2l": mime = "application/A2L" else: mime = f"application/x-{suffix}" attachment_index = self.attach(at_data, at_name, hash_sum=hash_sum, mime=mime) attachment = attachment_index else: attachment = None # add channel block cn_kwargs: ChannelKwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": signal.samples.dtype.itemsize * 8, "byte_offset": offset, "bit_offset": 0, "data_type": v4c.DATA_TYPE_BYTEARRAY, "precision": 0, } if attachment is not None: cn_kwargs["attachment_addr"] = 0 def source_bus(source: Source | None) -> TypeIs[Source]: return source is not None and source.source_type == v4c.SOURCE_BUS if source_bus(signal.source): cn_kwargs["flags"] = v4c.FLAG_CN_BUS_EVENT flags_ = v4c.FLAG_CN_BUS_EVENT grp.channel_group.flags |= v4c.FLAG_CG_BUS_EVENT | v4c.FLAG_CG_PLAIN_BUS_EVENT else: cn_kwargs["flags"] = 0 flags_ = 0 if invalidation_bytes_nr and signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.attachment = attachment ch.dtype_fmt = signal.samples.dtype record.append((ch.dtype_fmt, ch.dtype_fmt.itemsize, offset, 0)) if source_bus(signal.source) and grp.channel_group.acq_source is None: grp.channel_group.acq_source = SourceInformation.from_common_source(signal.source) match signal.source.bus_type: case v4c.BUS_TYPE_CAN: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "CAN" case v4c.BUS_TYPE_FLEXRAY: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "FLEXRAY" case v4c.BUS_TYPE_ETHERNET: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "ETHERNET" case v4c.BUS_TYPE_K_LINE: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "K_LINE" case v4c.BUS_TYPE_MOST: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "MOST" case v4c.BUS_TYPE_LIN: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "LIN" # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source entry = dg_cntr, ch_cntr gp_channels.append(ch) struct_self = entry gp_sdata.append(None) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) ch_cntr += 1 dep_list: list[tuple[int, int]] = [] gp_dep.append(dep_list) # then we add the fields for name in names: samples = signal.samples[name] fld_names = samples.dtype.names if fld_names is None: sig_type = v4c.SIGNAL_TYPE_SCALAR if samples.dtype.kind in "SV": sig_type = v4c.SIGNAL_TYPE_STRING else: if fld_names in (v4c.CANOPEN_TIME_FIELDS, v4c.CANOPEN_DATE_FIELDS): sig_type = v4c.SIGNAL_TYPE_CANOPEN elif fld_names[0] != name: sig_type = v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION else: sig_type = v4c.SIGNAL_TYPE_ARRAY if sig_type in (v4c.SIGNAL_TYPE_SCALAR, v4c.SIGNAL_TYPE_STRING): s_type, s_size = fmt_to_datatype_v4(samples.dtype, samples.shape) byte_size = s_size // 8 or 1 # add channel block cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": flags_, } if invalidation_bytes_nr: if signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.dtype_fmt = np.dtype((samples.dtype, samples.shape[1:])) record.append( ( ch.dtype_fmt, ch.dtype_fmt.itemsize, offset, 0, ) ) entry = (dg_cntr, ch_cntr) gp_channels.append(ch) dep_list.append(entry) offset += byte_size if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append((samples, byte_size)) gp_sdata.append(None) self.channels_db.add(name, entry) ch_cntr += 1 gp_dep.append(None) elif sig_type == v4c.SIGNAL_TYPE_ARRAY: # here we have channel arrays or mdf v3 channel dependencies array_samples = samples names = samples.dtype.names if names is None: raise RuntimeError("'names' is None") samples = array_samples[names[0]] shape = samples.shape[1:] if len(names) > 1: # add channel dependency block for composed parent channel dims_nr = len(shape) names_nr = len(names) if names_nr == 0: ca_kwargs: ChannelArrayBlockKwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_LOOKUP, "flags": v4c.FLAG_CA_FIXED_AXIS, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] elif len(names) == 1: ca_kwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_ARRAY, "flags": 0, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] else: ca_kwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_LOOKUP, "flags": v4c.FLAG_CA_AXIS, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] parent_dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([parent_dep]) else: # add channel dependency block for composed parent channel ca_kwargs = { "dims": 1, "ca_type": v4c.CA_TYPE_SCALE_AXIS, "flags": 0, "byte_offset_base": samples.dtype.itemsize, "dim_size_0": shape[0], } parent_dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([parent_dep]) record.append( ( samples.dtype, samples.dtype.itemsize, offset, 0, ) ) # first we add the structure channel s_type, s_size = fmt_to_datatype_v4(samples.dtype, samples.shape, True) # add channel block cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if invalidation_bytes_nr: if signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = samples.dtype # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) size = s_size // 8 for dim in shape: size *= dim offset += size if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append((samples, size)) gp_sdata.append(None) entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) ch_cntr += 1 for name in names[1:]: samples = array_samples[name] shape = samples.shape[1:] record.append( ( samples.dtype, samples.dtype.itemsize, offset, 0, ) ) # add channel dependency block ca_kwargs = { "dims": 1, "ca_type": v4c.CA_TYPE_SCALE_AXIS, "flags": 0, "byte_offset_base": samples.dtype.itemsize, "dim_size_0": shape[0], } dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([dep]) # add components channel s_type, s_size = fmt_to_datatype_v4(samples.dtype, ()) byte_size = s_size // 8 or 1 cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if invalidation_bytes_nr: if signal.invalidation_bits is not None: if (origin := signal.invalidation_bits.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits[origin]) invalidation_arrays.append(signal.invalidation_bits) else: inval_bits[origin] = signal.invalidation_bits cn_kwargs["flags"] = v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = origin[1] ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = samples.dtype gp_channels.append(ch) entry = dg_cntr, ch_cntr parent_dep.axis_channels.append(entry) for dim in shape: byte_size *= dim offset += byte_size if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append((samples, byte_size)) gp_sdata.append(None) self.channels_db.add(name, entry) ch_cntr += 1 elif sig_type == v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION: struct = Signal( samples, samples, name=name, invalidation_bits=signal.invalidation_bits, ) ( offset, dg_cntr, ch_cntr, sub_structure, new_fields, ) = self._append_structure_composition( grp, struct, offset, dg_cntr, ch_cntr, defined_texts, invalidation_bytes_nr, inval_bits, ) dep_list.append(sub_structure) fields.extend(new_fields) return offset, dg_cntr, ch_cntr, struct_self, fields def _append_structure_composition_column_oriented( self, grp: Group, signal: Signal, field_names: UniqueDB, offset: int, dg_cntr: int, ch_cntr: int, defined_texts: dict[str, int], ) -> tuple[ int, int, int, tuple[int, int], list[NDArray[Any]], list[tuple[str, np.dtype[Any], tuple[int, ...]]], ]: si_map = self._si_map fields: list[NDArray[Any]] = [] types: list[tuple[str, np.dtype[Any], tuple[int, ...]]] = [] file = self._tempfile seek = file.seek seek(0, 2) gp = grp gp_sdata = gp.signal_data gp_channels = gp.channels gp_dep = gp.channel_dependencies record = self._prepare_record(gp) name = signal.name names = signal.samples.dtype.names if names is None: raise RuntimeError("'names' is None") field_name = field_names.get_unique_name(name) # first we add the structure channel if signal.attachment and signal.attachment[0]: at_data, at_name, hash_sum = typing.cast(tuple[bytes, Path, bytes], signal.attachment) if at_name is not None: suffix = Path(at_name).suffix.strip(".") else: suffix = "dbc" attachment_index = self.attach(at_data, at_name, hash_sum=hash_sum, mime=f"application/x-{suffix}") attachment = attachment_index else: attachment = None # add channel block cn_kwargs: ChannelKwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": signal.samples.dtype.itemsize * 8, "byte_offset": offset, "bit_offset": 0, "data_type": v4c.DATA_TYPE_BYTEARRAY, "precision": 0, } if attachment is not None: cn_kwargs["attachment_addr"] = 0 def source_bus(source: Source | None) -> TypeIs[Source]: return source is not None and source.source_type == v4c.SOURCE_BUS if source_bus(signal.source): cn_kwargs["flags"] = v4c.FLAG_CN_BUS_EVENT flags_ = v4c.FLAG_CN_BUS_EVENT grp.channel_group.flags |= v4c.FLAG_CG_BUS_EVENT else: cn_kwargs["flags"] = 0 flags_ = 0 if signal.invalidation_bits is not None: cn_kwargs["flags"] |= v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.attachment = attachment ch.dtype_fmt = signal.samples.dtype if source_bus(signal.source): grp.channel_group.acq_source = SourceInformation.from_common_source(signal.source) match signal.source.bus_type: case v4c.BUS_TYPE_CAN: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "CAN" case v4c.BUS_TYPE_FLEXRAY: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "FLEXRAY" case v4c.BUS_TYPE_ETHERNET: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "ETHERNET" case v4c.BUS_TYPE_K_LINE: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "K_LINE" case v4c.BUS_TYPE_MOST: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "MOST" case v4c.BUS_TYPE_LIN: grp.channel_group.path_separator = 46 grp.channel_group.acq_name = "LIN" # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source entry = dg_cntr, ch_cntr gp_channels.append(ch) struct_self = entry gp_sdata.append(None) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) ch_cntr += 1 dep_list: list[tuple[int, int]] = [] gp_dep.append(dep_list) record.append((ch.dtype_fmt, ch.dtype_fmt.itemsize, offset, 0)) # then we add the fields for name in names: field_name = field_names.get_unique_name(name) samples = signal.samples[name] fld_names = samples.dtype.names if fld_names is None: sig_type = v4c.SIGNAL_TYPE_SCALAR if samples.dtype.kind in "SV": sig_type = v4c.SIGNAL_TYPE_STRING else: if fld_names in (v4c.CANOPEN_TIME_FIELDS, v4c.CANOPEN_DATE_FIELDS): sig_type = v4c.SIGNAL_TYPE_CANOPEN elif fld_names[0] != name: sig_type = v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION else: sig_type = v4c.SIGNAL_TYPE_ARRAY if sig_type in (v4c.SIGNAL_TYPE_SCALAR, v4c.SIGNAL_TYPE_STRING): s_type, s_size = fmt_to_datatype_v4(samples.dtype, samples.shape) byte_size = s_size // 8 or 1 fields.append(samples) types.append((field_name, samples.dtype, samples.shape[1:])) # add channel block cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": flags_, } if signal.invalidation_bits is not None: cn_kwargs["flags"] |= v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 ch = Channel(**cn_kwargs) ch.name = name ch.dtype_fmt = np.dtype((samples.dtype, samples.shape[1:])) record.append( ( ch.dtype_fmt, ch.dtype_fmt.itemsize, offset, 0, ) ) entry = (dg_cntr, ch_cntr) gp_channels.append(ch) dep_list.append(entry) offset += byte_size gp_sdata.append(None) self.channels_db.add(name, entry) ch_cntr += 1 gp_dep.append(None) elif sig_type == v4c.SIGNAL_TYPE_ARRAY: # here we have channel arrays or mdf v3 channel dependencies array_samples = samples names = samples.dtype.names if names is None: raise RuntimeError("'names' is None") samples = array_samples[names[0]] shape = samples.shape[1:] record.append( ( samples.dtype, samples.dtype.itemsize, offset, 0, ) ) if len(names) > 1: # add channel dependency block for composed parent channel dims_nr = len(shape) names_nr = len(names) if names_nr == 0: ca_kwargs: ChannelArrayBlockKwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_LOOKUP, "flags": v4c.FLAG_CA_FIXED_AXIS, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] elif len(names) == 1: ca_kwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_ARRAY, "flags": 0, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] else: ca_kwargs = { "dims": dims_nr, "ca_type": v4c.CA_TYPE_LOOKUP, "flags": v4c.FLAG_CA_AXIS, "byte_offset_base": samples.dtype.itemsize, } for i in range(dims_nr): ca_kwargs[f"dim_size_{i}"] = shape[i] # type: ignore[literal-required] parent_dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([parent_dep]) else: # add channel dependency block for composed parent channel ca_kwargs = { "dims": 1, "ca_type": v4c.CA_TYPE_SCALE_AXIS, "flags": 0, "byte_offset_base": samples.dtype.itemsize, "dim_size_0": shape[0], } parent_dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([parent_dep]) field_name = field_names.get_unique_name(name) fields.append(samples) dtype_pair = field_name, samples.dtype, shape types.append(dtype_pair) # first we add the structure channel s_type, s_size = fmt_to_datatype_v4(samples.dtype, samples.shape, True) # add channel block cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if signal.invalidation_bits is not None: cn_kwargs["flags"] |= v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = samples.dtype # source for channel source = signal.source if source: if source in si_map: ch.source = si_map[source] else: new_source = SourceInformation(source_type=source.source_type, bus_type=source.bus_type) new_source.name = source.name new_source.path = source.path new_source.comment = source.comment si_map[source] = new_source ch.source = new_source gp_channels.append(ch) size = s_size // 8 for dim in shape: size *= dim offset += size gp_sdata.append(None) entry = (dg_cntr, ch_cntr) self.channels_db.add(name, entry) for _name in ch.display_names: self.channels_db.add(_name, entry) ch_cntr += 1 for name in names[1:]: field_name = field_names.get_unique_name(name) samples = array_samples[name] shape = samples.shape[1:] fields.append(samples) types.append((field_name, samples.dtype, shape)) record.append( ( samples.dtype, samples.dtype.itemsize, offset, 0, ) ) # add channel dependency block ca_kwargs = { "dims": 1, "ca_type": v4c.CA_TYPE_SCALE_AXIS, "flags": 0, "byte_offset_base": samples.dtype.itemsize, "dim_size_0": shape[0], } dep = ChannelArrayBlock(**ca_kwargs) gp_dep.append([dep]) # add components channel s_type, s_size = fmt_to_datatype_v4(samples.dtype, ()) byte_size = s_size // 8 or 1 cn_kwargs = { "channel_type": v4c.CHANNEL_TYPE_VALUE, "bit_count": s_size, "byte_offset": offset, "bit_offset": 0, "data_type": s_type, "flags": 0, } if signal.invalidation_bits is not None: cn_kwargs["flags"] |= v4c.FLAG_CN_INVALIDATION_PRESENT cn_kwargs["pos_invalidation_bit"] = 0 ch = Channel(**cn_kwargs) ch.name = name ch.unit = signal.unit ch.comment = signal.comment ch.display_names = signal.display_names ch.dtype_fmt = samples.dtype gp_channels.append(ch) entry = dg_cntr, ch_cntr parent_dep.axis_channels.append(entry) for dim in shape: byte_size *= dim offset += byte_size gp_sdata.append(None) self.channels_db.add(name, entry) ch_cntr += 1 elif sig_type == v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION: struct = Signal( samples, samples, name=name, invalidation_bits=signal.invalidation_bits, ) ( offset, dg_cntr, ch_cntr, sub_structure, new_fields, new_types, ) = self._append_structure_composition_column_oriented( grp, struct, field_names, offset, dg_cntr, ch_cntr, defined_texts, ) dep_list.append(sub_structure) fields.extend(new_fields) types.extend(new_types) return offset, dg_cntr, ch_cntr, struct_self, fields, types def extend(self, index: int, signals: Sequence[tuple[NDArray[Any], NDArray[np.bool] | None]]) -> None: """Extend a group with new samples. `signals` contains (values, invalidation_bits) pairs for each extended signal. The first pair is the master channel's pair, and the next pairs must respect the same order in which the signals were appended. The samples must have raw or physical values according to the signals used for the initial append. Parameters ---------- index : int Group index. signals : sequence Sequence of (np.ndarray, np.ndarray) tuples. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> s1 = np.array([1, 2, 3, 4, 5]) >>> s2 = np.array([-1, -2, -3, -4, -5]) >>> s3 = np.array([0.1, 0.04, 0.09, 0.16, 0.25]) >>> t = np.array([0.001, 0.002, 0.003, 0.004, 0.005]) >>> s1 = Signal(samples=s1, timestamps=t, unit='+', name='Positive') >>> s2 = Signal(samples=s2, timestamps=t, unit='-', name='Negative') >>> s3 = Signal(samples=s3, timestamps=t, unit='flts', name='Floats') >>> mdf = MDF(version='4.10') >>> mdf.append([s1, s2, s3], comment='created by asammdf') >>> t = np.array([0.006, 0.007, 0.008, 0.009, 0.010]) Extend without invalidation bits. >>> mdf.extend(0, [(t, None), (s1.samples, None), (s2.samples, None), (s3.samples, None)]) Extend with some invalidation bits. >>> s1_inv = np.array([0, 0, 0, 1, 1], dtype=bool) >>> mdf.extend(0, [(t, None), (s1.samples, s1_inv), (s2.samples, None), (s3.samples, None)]) """ if self.version >= "4.20" and (self._column_storage or 1): return self._extend_column_oriented(index, signals) gp = self.groups[index] if not signals: message = '"append" requires a non-empty list of Signal objects' raise MdfException(message) stream = self._tempfile fields: list[tuple[bytes | NDArray[Any], int]] = [] inval_bits_map: dict[tuple[int, int], list[InvalidationArray] | InvalidationArray] = { InvalidationArray.ORIGIN_UNKNOWN: [] } added_cycles = len(signals[0][0]) invalidation_bytes_nr = gp.channel_group.invalidation_bytes_nr signal_types = typing.cast(list[tuple[int, int]], gp.signal_types) for i, ((signal, invalidation_bits), (sig_type, sig_size)) in enumerate( zip(signals, signal_types, strict=False) ): if invalidation_bytes_nr: if invalidation_bits is not None: if not isinstance(invalidation_bits, InvalidationArray): invalidation_array = InvalidationArray(invalidation_bits) else: invalidation_array = invalidation_bits if (origin := invalidation_array.origin) == InvalidationArray.ORIGIN_UNKNOWN: invalidation_arrays = typing.cast(list[InvalidationArray], inval_bits_map[origin]) invalidation_arrays.append(invalidation_array) else: inval_bits_map[origin] = invalidation_array # first add the signals in the simple signal list match sig_type: case v4c.SIGNAL_TYPE_SCALAR: if not signal.flags["C_CONTIGUOUS"]: signal = np.ascontiguousarray(signal) fields.append((signal, sig_size)) case v4c.SIGNAL_TYPE_CANOPEN: names = signal.dtype.names if names == v4c.CANOPEN_TIME_FIELDS: if not signal.flags["C_CONTIGUOUS"]: signal = np.ascontiguousarray(signal) fields.append((signal, sig_size)) else: arrays: list[Any] = [] for field in ("ms", "min", "hour", "day", "month", "year"): arrays.append(signal[field]) vals = np.rec.fromarrays(arrays).tobytes() fields.append((vals, sig_size)) case v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION: if not signal.flags["C_CONTIGUOUS"]: signal = np.ascontiguousarray(signal) fields.append((signal, sig_size)) case v4c.SIGNAL_TYPE_ARRAY: names = signal.dtype.names if names is None: raise RuntimeError("'names' is None") samples = signal[names[0]] if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append((samples, sig_size)) for name in names[1:]: samples = signal[name] shape = samples.shape[1:] s_type, s_size = fmt_to_datatype_v4(samples.dtype, ()) size = s_size // 8 for dim in shape: size *= dim if not samples.flags["C_CONTIGUOUS"]: samples = np.ascontiguousarray(samples) fields.append((samples, size)) case _: if self.compact_vlsd: cur_offset = sum(blk.original_size for blk in gp.get_signal_data_blocks(i)) pairs: list[bytes] = [] offsets: list[int] = [] off = 0 if gp.channels[i].data_type == v4c.DATA_TYPE_STRING_UTF_16_LE: for elem in signal: offsets.append(off) size = len(elem) if size % 2: size += 1 elem = elem + b"\0" pairs.extend((UINT32_p(size), elem)) off += size + 4 else: for elem in signal: offsets.append(off) size = len(elem) pairs.extend((UINT32_p(size), elem)) off += size + 4 offsets_arr: NDArray[np.integer[Any]] = array(offsets, dtype=uint64) stream.seek(0, 2) addr = stream.tell() data_size = off if data_size: info = SignalDataBlockInfo( address=addr, compressed_size=data_size, original_size=data_size, location=v4c.LOCATION_TEMPORARY_FILE, ) signal_data = typing.cast( list[tuple[list[SignalDataBlockInfo], Iterator[SignalDataBlockInfo]]], gp.signal_data ) signal_data[i][0].append(info) stream.write(b"".join(pairs)) offsets_arr += cur_offset # type: ignore[misc, unused-ignore] if not offsets_arr.flags["C_CONTIGUOUS"]: offsets_arr = np.ascontiguousarray(offsets_arr) fields.append((offsets_arr, 8)) else: cur_offset = sum(blk.original_size for blk in gp.get_signal_data_blocks(i)) offsets_arr = arange(len(signal), dtype=uint64) * (signal.itemsize + 4) values = [full(len(signal), signal.itemsize, dtype=uint32), signal] types_ = [("", uint32), ("", signal.dtype)] values_arr = np.rec.fromarrays(values, dtype=types_) stream.seek(0, 2) addr = stream.tell() block_size = len(values_arr) * values_arr.itemsize if block_size: info = SignalDataBlockInfo( address=addr, compressed_size=block_size, original_size=block_size, location=v4c.LOCATION_TEMPORARY_FILE, ) signal_data = typing.cast( list[tuple[list[SignalDataBlockInfo], Iterator[SignalDataBlockInfo]]], gp.signal_data ) signal_data[i][0].append(info) values_arr.tofile(stream) offsets_arr += cur_offset if not offsets_arr.flags["C_CONTIGUOUS"]: offsets_arr = np.ascontiguousarray(offsets_arr) fields.append((offsets_arr, 8)) if invalidation_bytes_nr: unknown_origin = typing.cast(list[InvalidationArray], inval_bits_map.pop(InvalidationArray.ORIGIN_UNKNOWN)) inval_array_map = typing.cast(dict[tuple[int, int], InvalidationArray], inval_bits_map) inval_bits = typing.cast(list[NDArray[np.bool]], list(inval_array_map.values()) + unknown_origin) cycles_nr = len(inval_bits[0]) new_invalidation_bytes_nr = len(inval_bits) for _ in range(8 - new_invalidation_bytes_nr % 8): inval_bits.append(zeros(cycles_nr, dtype=bool)) inval_bits.reverse() new_invalidation_bytes_nr = len(inval_bits) // 8 if new_invalidation_bytes_nr != invalidation_bytes_nr: raise MdfException( "The invalidation bytes number in the extend methods differs from the one from the append" ) inval_bits_vals = np.fliplr( np.packbits(array(inval_bits).T).reshape((cycles_nr, invalidation_bytes_nr)) ).ravel() if self.version < "4.20": fields.append((inval_bits_vals, invalidation_bytes_nr)) samples_bytes = data_block_from_arrays(fields, added_cycles, THREAD_COUNT) size = len(samples_bytes) samples_view = memoryview(samples_bytes) del fields stream.seek(0, 2) addr = stream.tell() record_size = gp.channel_group.samples_byte_nr + gp.channel_group.invalidation_bytes_nr if size: if self.version < "4.20": block_size = 32 * 1024 * 1024 // record_size * record_size count = ceil(size / block_size) for i in range(count): data_ = samples_view[i * block_size : (i + 1) * block_size] raw_size = len(data_) data_ = lz_compress(data_, store_size=True) size = len(data_) data_address = self._tempfile.tell() self._tempfile.write(data_) gp.data_blocks.append( DataBlockInfo( address=data_address, block_type=v4c.DZ_BLOCK_LZ, original_size=raw_size, compressed_size=size, param=0, ) ) gp.channel_group.cycles_nr += added_cycles self.virtual_groups[index].cycles_nr += added_cycles else: raw_size = size data = lz_compress(samples, store_size=True) size = len(data) stream.write(data) gp.data_blocks.append( DataBlockInfo( address=addr, block_type=v4c.DZ_BLOCK_LZ, original_size=raw_size, compressed_size=size, param=0, ) ) gp.channel_group.cycles_nr += added_cycles self.virtual_groups[index].cycles_nr += added_cycles if invalidation_bytes_nr: addr = stream.tell() data = inval_bits_vals.tobytes() raw_size = len(data) data = lz_compress(data, store_size=True) size = len(data) stream.write(data) gp.data_blocks[-1].invalidation_block = InvalidationBlockInfo( address=addr, block_type=v4c.DZ_BLOCK_LZ, original_size=raw_size, compressed_size=size, param=0, ) def _extend_column_oriented( self, index: int, signals: Sequence[tuple[NDArray[Any], NDArray[np.bool] | None]] ) -> None: """Extend a group with new samples. `signals` contains (values, invalidation_bits) pairs for each extended signal. The first pair is the master channel's pair, and the next pairs must respect the same order in which the signals were appended. The samples must have raw or physical values according to the signals used for the initial append. Parameters ---------- index : int Group index. signals : sequence Sequence of (np.ndarray, np.ndarray) tuples. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> s1 = np.array([1, 2, 3, 4, 5]) >>> s2 = np.array([-1, -2, -3, -4, -5]) >>> s3 = np.array([0.1, 0.04, 0.09, 0.16, 0.25]) >>> t = np.array([0.001, 0.002, 0.003, 0.004, 0.005]) >>> s1 = Signal(samples=s1, timestamps=t, unit='+', name='Positive') >>> s2 = Signal(samples=s2, timestamps=t, unit='-', name='Negative') >>> s3 = Signal(samples=s3, timestamps=t, unit='flts', name='Floats') >>> mdf = MDF(version='4.10') >>> mdf.append([s1, s2, s3], comment='created by asammdf') >>> t = np.array([0.006, 0.007, 0.008, 0.009, 0.010]) Extend without invalidation bits. >>> mdf.extend(0, [(t, None), (s1.samples, None), (s2.samples, None), (s3.samples, None)]) Extend with some invalidation bits. >>> s1_inv = np.array([0, 0, 0, 1, 1], dtype=bool) >>> mdf.extend(0, [(t, None), (s1.samples, s1_inv), (s2.samples, None), (s3.samples, None)]) """ gp = self.groups[index] if not signals: message = '"append" requires a non-empty list of Signal objects' raise MdfException(message) stream = self._tempfile stream.seek(0, 2) write = stream.write tell = stream.tell added_cycles = len(signals[0][0]) self.virtual_groups[index].cycles_nr += added_cycles for i, (signal, invalidation_bits) in enumerate(signals): gp = self.groups[index + i] sig_type = typing.cast(int, gp.signal_types[0]) # first add the signals in the simple signal list match sig_type: case v4c.SIGNAL_TYPE_SCALAR: samples = signal case v4c.SIGNAL_TYPE_CANOPEN: names = signal.dtype.names if names == v4c.CANOPEN_TIME_FIELDS: samples = signal else: vals = [] for field in ("ms", "min", "hour", "day", "month", "year"): vals.append(signal[field]) samples = np.rec.fromarrays(vals) case v4c.SIGNAL_TYPE_STRUCTURE_COMPOSITION: samples = signal case v4c.SIGNAL_TYPE_ARRAY: samples = signal case _: cur_offset = sum(blk.original_size for blk in gp.get_signal_data_blocks(0)) offsets = arange(len(signal), dtype=uint64) * (signal.itemsize + 4) arrays = [full(len(signal), signal.itemsize, dtype=uint32), signal] types_ = [("", uint32), ("", signal.dtype)] values = np.rec.fromarrays(arrays, dtype=types_) addr = tell() block_size = len(values) * values.itemsize if block_size: info = SignalDataBlockInfo( address=addr, compressed_size=block_size, original_size=block_size, location=v4c.LOCATION_TEMPORARY_FILE, ) sd_block_infos = typing.cast( tuple[list[SignalDataBlockInfo], Iterator[SignalDataBlockInfo]], gp.signal_data[i] ) sd_block_infos[0].append(info) write(values.tobytes()) offsets += cur_offset samples = offsets addr = tell() if added_cycles: data = samples.tobytes() raw_size = len(data) data = lz_compress(data, store_size=True) size = len(data) write(data) gp.data_blocks.append( DataBlockInfo( address=addr, block_type=v4c.DZ_BLOCK_LZ, original_size=raw_size, compressed_size=size, param=0, ) ) gp.channel_group.cycles_nr += added_cycles if invalidation_bits is not None: addr = tell() data = invalidation_bits.tobytes() raw_size = len(data) data = lz_compress(data, store_size=True) size = len(data) write(data) gp.data_blocks[-1].invalidation_block = InvalidationBlockInfo( address=addr, block_type=v4c.DZ_BLOCK_LZ, original_size=raw_size, compressed_size=size, param=None, ) def attach( self, data: bytes, file_name: StrPath | None = None, hash_sum: bytes | None = None, comment: str = "", compression: bool = True, mime: str = r"application/octet-stream", embedded: bool = True, password: str | bytes | None = None, ) -> int: """Attach embedded attachment as application/octet-stream. Parameters ---------- data : bytes Data to be attached. file_name : str | path-like, optional File name. hash_sum : bytes, optional MD5 of the data. comment : str, optional Attachment comment. compression : bool, default True Use compression for embedded attachment data. mime : str, default 'application/octet-stream' Mime type. embedded : bool, default True Attachment is embedded in the file. password : str | bytes, optional Password used to encrypt the data using AES256 encryption. .. versionadded:: 7.0.0 Returns ------- index : int New attachment index. """ if self._force_attachment_encryption: password = password or self._password if password and not CRYPTOGRAPHY_AVAILABLE: raise MdfException("cryptography must be installed for attachment encryption") hash_digest: bytes | str if hash_sum is None: worker = md5() worker.update(data) hash_digest = worker.hexdigest() else: hash_digest = hash_sum if hash_digest in self._attachments_cache: return self._attachments_cache[hash_digest] hash_sum_encrypted: bytes | str if password: if isinstance(password, str): password = password.encode("utf-8") size = len(password) if size < 32: password = password + bytes(32 - size) else: password = password[:32] iv = os.urandom(16) cipher = Cipher(algorithms.AES(password), modes.CBC(iv)) encryptor = cipher.encryptor() original_size = len(data) rem = original_size % 16 if rem: data += os.urandom(16 - rem) data = iv + encryptor.update(data) + encryptor.finalize() worker = md5() worker.update(data) hash_sum_encrypted = worker.hexdigest() comment = f""" {comment} true AES256 {hash_sum_encrypted} {original_size} """ else: hash_sum_encrypted = hash_digest if hash_sum_encrypted in self._attachments_cache: return self._attachments_cache[hash_digest] creator_index = len(self.file_history) fh = FileHistory() fh.comment = """ Added new embedded attachment from {file_name} {tool} {vendor} {version} """.format( file_name=file_name if file_name else "bin.bin", version=tool.__version__, tool=tool.__tool__, vendor=tool.__vendor__, ) self.file_history.append(fh) file_name = file_name or "bin.bin" at_block = AttachmentBlock( data=data, compression=compression, embedded=embedded, file_name=file_name, comment=comment, ) at_block.comment = comment at_block.creator_index = creator_index self.attachments.append(at_block) file_path = Path(file_name) mime_type, _ = guess_type(Path(file_path)) if mime_type is None: suffix = file_path.suffix.lower().strip(".") if suffix == "a2l": mime = "application/A2L" else: mime = f"application/x-{suffix}" else: mime = mime_type at_block.mime = mime index = len(self.attachments) - 1 self._attachments_cache[hash_digest] = index self._attachments_cache[hash_sum_encrypted] = index return index def close(self) -> None: """Call this just before the object is not used anymore to clean up the temporary file and close the file object. """ if self._closed: return else: self._closed = True self._parent = None if self._tempfile is not None: self._tempfile.close() if not self._from_filelike and self._file is not None: self._file.close() if self._mapped_file is not None: self._mapped_file.close() if self._delete_on_close: try: Path(self.name).unlink() except: pass if self.original_name is not None: if Path(self.original_name).suffix.lower() in ( ".bz2", ".gzip", ".mf4z", ".zip", ): try: Path(self.name).unlink() except: pass for gp in self.groups: gp.clear() self.groups.clear() del self.header del self.identification self.file_history.clear() self.channels_db.clear() self.masters_db.clear() self.attachments.clear() self._attachments_cache.clear() self.events.clear() self._ch_map.clear() self._master_channel_metadata.clear() self._invalidation_cache.clear() self._external_dbc_cache.clear() self._si_map.clear() self._file_si_map.clear() self._cc_map.clear() self._file_cc_map.clear() self._cg_map.clear() self._cn_data_map.clear() self._dbc_cache.clear() self.virtual_groups.clear() def _extract_attachment( self, index: int | None = None, password: str | bytes | None = None, ) -> tuple[bytes | str, Path, bytes | str]: """Extract attachment data by index. If it is an embedded attachment, then this method creates the new file according to the attachment file name information. Parameters ---------- index : int, optional Attachment index. password : str | bytes, optional Password used to encrypt the data using AES256 encryption. .. versionadded:: 7.0.0 Returns ------- data : (bytes, pathlib.Path, bytes) Tuple of attachment data and path. """ password = password or self._password if index is None: return b"", Path(""), md5().digest() attachment = self.attachments[index] current_path = Path.cwd() file_path = Path(attachment.file_name or "embedded") data: bytes | str md5_sum: bytes | str try: os.chdir(self.name.resolve().parent) flags = attachment.flags # for embedded attachments extract data and create new files if flags & v4c.FLAG_AT_EMBEDDED: data = attachment.extract() md5_worker = md5() md5_worker.update(data) md5_sum = md5_worker.digest() encryption_info = extract_encryption_information(attachment.comment) if encryption_info.get("encrypted", False): if not password: raise MdfException("the password must be provided for encrypted attachments") if isinstance(password, str): password = password.encode("utf-8") size = len(password) if size < 32: password = password + bytes(32 - size) else: password = password[:32] if encryption_info["algorithm"] == "aes256": md5_worker = md5() md5_worker.update(data) md5_sum = md5_worker.hexdigest().lower() if md5_sum != encryption_info["original_md5_sum"]: raise MdfException( f"MD5 sum mismatch for encrypted attachment: original={encryption_info['original_md5_sum']} and computed={md5_sum}" ) iv, data = data[:16], data[16:] cipher = Cipher(algorithms.AES(password), modes.CBC(iv)) decryptor = cipher.decryptor() data = decryptor.update(data) + decryptor.finalize() data = data[: encryption_info["original_size"]] else: raise MdfException( f"not implemented attachment encryption algorithm <{encryption_info['algorithm']}>" ) else: # for external attachments read the file and return the content if file_path.exists() and file_path.is_file(): data = file_path.read_bytes() else: if self.original_name is None: raise RuntimeError("'original_name' is None") file_path = Path(self.original_name).parent / file_path.name if file_path.exists() and file_path.is_file(): data = file_path.read_bytes() else: raise Exception(f"External attachment file {attachment.file_name} was not found") md5_worker = md5() md5_worker.update(data) md5_sum = md5_worker.digest() if attachment.mime.startswith("text"): data = data.decode("utf-8", errors="replace") if flags & v4c.FLAG_AT_MD5_VALID and attachment.md5_sum != md5_sum: message = ( f'ATBLOCK md5sum="{attachment.md5_sum!r}" ' f"and external attachment data ({file_path}) " f'md5sum="{md5_sum!r}"' ) logger.warning(message) except Exception as err: os.chdir(current_path) message = f'Exception during attachment "{attachment.file_name}" extraction: {err!r}' logger.warning(message) data = b"" md5_sum = md5().digest() finally: os.chdir(current_path) return data, file_path, md5_sum @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., samples_only: Literal[False] = ..., data: Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = ..., record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> Signal: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., *, samples_only: Literal[True], data: Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: Literal[False] = ..., record_offset: int = ..., record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> tuple[NDArray[Any], NDArray[np.bool] | None]: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., *, samples_only: Literal[True], data: Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: Literal[True], record_offset: int = ..., record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> tuple[NDArray[Any], None]: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., *, samples_only: Literal[True], data: Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = ..., record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> tuple[NDArray[Any], NDArray[np.bool] | None]: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., samples_only: bool = ..., data: Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = ..., record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> Signal | tuple[NDArray[Any], NDArray[np.bool] | None]: ... def get( self, name: str | None = None, group: int | None = None, index: int | None = None, raster: RasterType | None = None, samples_only: bool = False, data: Fragment | None = None, raw: bool = False, ignore_invalidation_bits: bool = False, record_offset: int = 0, record_count: int | None = None, skip_channel_validation: bool = False, ) -> Signal | tuple[NDArray[Any], NDArray[np.bool] | None]: """Get channel samples. The raw data group samples are not loaded to memory so it is advised to use `filter` or `select` instead of performing several `get` calls. The channel can be specified in two ways: * Using the first positional argument `name`. * If there are multiple occurrences for this channel, then the `group` and `index` arguments can be used to select a specific group. * If there are multiple occurrences for this channel and either the `group` or `index` arguments is None, then a warning is issued. * Using the group number (keyword argument `group`) and the channel number (keyword argument `index`). Use `info` method for group and channel numbers. If the `raster` keyword argument is not None, the output is interpolated accordingly. Parameters ---------- name : str, optional Name of channel. group : int, optional 0-based group index. index : int, optional 0-based channel index. raster : float, optional Time raster in seconds. samples_only : bool, default False If True, return only the channel samples as np.ndarray; if False, return a `Signal` object. data : Fragment, optional Prevent redundant data read by providing the raw data group samples. raw : bool, default False Return channel samples without applying the conversion rule. ignore_invalidation_bits : bool, default False Option to ignore invalidation bits. record_offset : int, optional If `data=None`, use this to select the record offset from which the group data should be loaded. record_count : int, optional Number of records to read; default is None and in this case all available records are used. skip_channel_validation : bool, default False Skip validation of channel name, group index and channel index. If True, the caller has to make sure that the `group` and `index` arguments are provided and are correct. .. versionadded:: 7.0.0 Returns ------- res : (np.ndarray, np.ndarray) | Signal Returns `Signal` if `samples_only=False` (default option), otherwise returns a (np.ndarray, np.ndarray) tuple of samples and invalidation bits. If invalidation bits are not used or if `ignore_invalidation_bits` is False, then the second item will be None. The `Signal` samples are: * np.recarray for channels that have composition/channel array address or for channels of type CANOPENDATE, CANOPENTIME * np.ndarray for all the rest Raises ------ MdfException * if the channel name is not found * if the group index is out of range * if the channel index is out of range * if there are multiple channel occurrences in the file and the arguments `name`, `group`, `index` are ambiguous. This behaviour can be turned off by setting `raise_on_multiple_occurrences` to False. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> t = np.arange(5) >>> s = np.ones(5) >>> mdf = MDF(version='4.10') >>> for i in range(4): ... sigs = [Signal(s * (i * 10 + j), t, name='Sig') for j in range(1, 4)] ... mdf.append(sigs) Specifying only the channel name is not enough when there are multiple channels with that name. >>> mdf.get('Sig') MdfException: Multiple occurrences for channel "Sig": ((0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)). Provide both "group" and "index" arguments to select another data group In this case, adding the group number is also not enough since there are multiple channels with that name in that group. >>> mdf.get('Sig', 1) MdfException: Multiple occurrences for channel "Sig": ((1, 1), (1, 2), (1, 3)). Provide both "group" and "index" arguments to select another data group Get the channel named "Sig" from group 1, channel index 2. >>> mdf.get('Sig', 1, 2) Get the channel from group 2 and channel index 1. >>> mdf.get(None, 2, 1) >>> mdf.get(group=2, index=1) """ if skip_channel_validation: if group is None: raise RuntimeError("'group' cannot be None if 'skip_channel_validation' is True") if index is None: raise RuntimeError("'index' cannot be None if 'skip_channel_validation' is True") gp_nr, ch_nr = group, index else: gp_nr, ch_nr = self._validate_channel_selection(name, group, index) grp = self.groups[gp_nr] # get the channel object channel = grp.channels[ch_nr] dependency_list = grp.channel_dependencies[ch_nr] master_is_required = not samples_only or bool(raster) vals: NDArray[Any] | None = None all_invalid = False if channel.byte_offset + (channel.bit_offset + channel.bit_count) / 8 > grp.channel_group.samples_byte_nr: all_invalid = True logger.warning( "\n\t".join( [ f"Channel {channel.name} byte offset too high:", f"byte offset = {channel.byte_offset}", f"bit offset = {channel.bit_offset}", f"bit count = {channel.bit_count}", f"group record size = {grp.channel_group.samples_byte_nr}", f"group index = {gp_nr}", f"channel index = {ch_nr}", ] ) ) if (channel.bit_offset + channel.bit_count) / 8 > grp.channel_group.samples_byte_nr: vals = np.array([]) else: channel = deepcopy(channel) channel.byte_offset = 0 if vals is None: if dependency_list: if not isinstance(dependency_list[0], ChannelArrayBlock): dependency_list = typing.cast(list[tuple[int, int]], dependency_list) samples, timestamps, invalidation_bits, encoding = self._get_structure( channel=channel, group=grp, group_index=gp_nr, channel_index=ch_nr, dependency_list=dependency_list, raster=raster, data=data, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=record_count, master_is_required=master_is_required, raw=raw, ) else: dependency_list = typing.cast(list[ChannelArrayBlock], dependency_list) samples, timestamps, invalidation_bits, encoding = self._get_array( channel=channel, group=grp, group_index=gp_nr, channel_index=ch_nr, dependency_list=dependency_list, raster=raster, data=data, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=record_count, master_is_required=master_is_required, ) else: if ( data and (fast_path := channel.fast_path) is not None and not master_is_required and ignore_invalidation_bits and not raster ): samples, timestamps, invalidation_bits, encoding = self._fast_scalar_path(*fast_path, data) else: samples, timestamps, invalidation_bits, encoding = self._get_scalar( channel=channel, group=grp, group_index=gp_nr, channel_index=ch_nr, dependency_list=dependency_list, raster=raster, data=data, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=record_count, master_is_required=master_is_required, ) else: samples = vals timestamps = np.array([], dtype=np.float64) invalidation_bits = None encoding = None if all_invalid: invalidation_bits = np.ones(len(samples), dtype=bool) res: tuple[NDArray[Any], NDArray[np.bool] | None] | Signal if samples_only: if not raw: conversion = channel.conversion if conversion: samples = conversion.convert(samples) res = samples, invalidation_bits else: if timestamps is None: raise RuntimeError("'timestamps' cannot be None if 'samples_only' is False") conversion = channel.conversion if not raw: if conversion: samples = conversion.convert(samples) conversion = None if samples.dtype.kind == "S": encoding = "utf-8" channel_type = channel.channel_type if name is None: name = channel.name unit = (conversion and conversion.unit) or channel.unit comment = channel.comment source_information = channel.source if source_information: source = Source.from_source(source_information) else: cg_source = grp.channel_group.acq_source if cg_source: source = Source.from_source(cg_source) else: source = None if channel.attachment is not None: attachment = self.extract_attachment( channel.attachment, ) else: attachment = None master_metadata = self._master_channel_metadata.get(gp_nr, None) if channel_type == v4c.CHANNEL_TYPE_SYNC: flags = Signal.Flags.stream_sync else: flags = Signal.Flags.no_flags try: res = Signal( samples=samples, timestamps=timestamps, unit=unit, name=name, comment=comment, conversion=conversion, raw=raw, master_metadata=master_metadata, attachment=attachment, source=source, display_names=channel.display_names, bit_count=channel.bit_count, flags=flags, invalidation_bits=invalidation_bits, encoding=encoding, group_index=gp_nr, channel_index=ch_nr, ) except: debug_channel(self, grp, channel, dependency_list) raise if data is None: self._invalidation_cache.clear() return res @overload def _get_structure( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[tuple[int, int]], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[False], record_offset: int, record_count: int | None, master_is_required: Literal[False], raw: bool, ) -> tuple[NDArray[Any], None, NDArray[np.bool] | None, None]: ... @overload def _get_structure( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[tuple[int, int]], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[True], record_offset: int, record_count: int | None, master_is_required: Literal[False], raw: bool, ) -> tuple[NDArray[Any], None, None, None]: ... @overload def _get_structure( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[tuple[int, int]], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[False], record_offset: int, record_count: int | None, master_is_required: Literal[True], raw: bool, ) -> tuple[NDArray[Any], NDArray[Any], NDArray[np.bool] | None, None]: ... @overload def _get_structure( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[tuple[int, int]], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[True], record_offset: int, record_count: int | None, master_is_required: Literal[True], raw: bool, ) -> tuple[NDArray[Any], NDArray[Any], None, None]: ... @overload def _get_structure( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[tuple[int, int]], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: bool, record_offset: int, record_count: int | None, master_is_required: bool, raw: bool, ) -> tuple[NDArray[Any], NDArray[Any] | None, NDArray[np.bool] | None, None]: ... def _get_structure( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[tuple[int, int]], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: bool, record_offset: int, record_count: int | None, master_is_required: bool, raw: bool, ) -> tuple[NDArray[Any], NDArray[Any] | None, NDArray[np.bool] | None, None]: grp = group gp_nr = group_index # get data group record self._prepare_record(grp) # get group data if data is None: fragments = self._load_data(grp, record_offset=record_offset, record_count=record_count) else: fragments = iter((data,)) groups = self.groups channel_invalidation_present = channel.flags & (v4c.FLAG_CN_ALL_INVALID | v4c.FLAG_CN_INVALIDATION_PRESENT) _dtype = np.dtype(channel.dtype_fmt) conditions = [ _dtype.itemsize == channel.bit_count // 8, all( groups[dg_nr].channels[ch_nr].channel_type != v4c.CHANNEL_TYPE_VLSD and ( (conversion := groups[dg_nr].channels[ch_nr].conversion) is None or not conversion.conversion_type == v4c.CONVERSION_TYPE_NON ) for (dg_nr, ch_nr) in dependency_list ), ] channel_values: list[NDArray[Any]] | list[list[NDArray[Any]]] if all(conditions): fast_path = True flat_channel_values: list[NDArray[Any]] = [] masters: list[NDArray[Any]] = [] invalidation_arrays: list[InvalidationArray] = [] byte_offset = channel.byte_offset record_size = grp.channel_group.samples_byte_nr + grp.channel_group.invalidation_bytes_nr count = 0 for fragment in fragments: bts = fragment.data buffer = get_channel_raw_bytes(bts, record_size, byte_offset, _dtype.itemsize) flat_channel_values.append(frombuffer(buffer, dtype=_dtype)) if master_is_required: masters.append(self.get_master(gp_nr, fragment, one_piece=True)) if channel_invalidation_present: invalidation_arrays.append( self.get_invalidation_bits(gp_nr, channel.pos_invalidation_bit, fragment) ) count += 1 channel_values = flat_channel_values else: unique_names = UniqueDB() fast_path = False names = [unique_names.get_unique_name(grp.channels[ch_nr].name) for _, ch_nr in dependency_list] channel_values_list: list[list[NDArray[Any]]] = [[] for _ in dependency_list] masters = [] invalidation_arrays = [] count = 0 for fragment in fragments: for i, (dg_nr, ch_nr) in enumerate(dependency_list): vals = self.get( group=dg_nr, index=ch_nr, samples_only=True, data=fragment, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=record_count, raw=False, )[0] channel_values_list[i].append(vals) if master_is_required: masters.append(self.get_master(gp_nr, fragment, one_piece=True)) if channel_invalidation_present: invalidation_arrays.append( self.get_invalidation_bits(gp_nr, channel.pos_invalidation_bit, fragment) ) count += 1 channel_values = channel_values_list if fast_path: flat_channel_values = typing.cast(list[NDArray[Any]], channel_values) total_size = sum(len(_) for _ in flat_channel_values) shape = (total_size,) + flat_channel_values[0].shape[1:] if count > 1: out = empty(shape, dtype=flat_channel_values[0].dtype) vals = concatenate(flat_channel_values, out=out) else: vals = flat_channel_values[0] else: channel_values_list = typing.cast(list[list[NDArray[Any]]], channel_values) total_size = sum(len(_) for _ in channel_values_list[0]) if count > 1: arrays: list[NDArray[Any]] = [] for lst in channel_values_list: shape_len = len(lst[0].shape) # fix bytearray signals if the length changes between the chunks if shape_len == 2: shape = (total_size,) vlsd_max_size = max(l.shape[1] for l in lst) shape = (*shape, vlsd_max_size) max_vlsd_arrs = [] for arr in lst: if arr.shape[1] < vlsd_max_size: arr = np.hstack( ( arr, np.zeros( ( arr.shape[0], vlsd_max_size - arr.shape[1], ), dtype=arr.dtype, ), ) ) max_vlsd_arrs.append(arr) arr = concatenate( max_vlsd_arrs, out=empty(shape, dtype=max_vlsd_arrs[0].dtype), ) arrays.append(arr) elif shape_len == 1: arr = concatenate( lst, out=empty((total_size,), dtype=lst[0].dtype), ) arrays.append(arr) else: arrays.append( concatenate( lst, out=empty((total_size,) + lst[0].shape[1:], dtype=lst[0].dtype), ) ) else: arrays = [lst[0] for lst in channel_values_list] types: DTypeLike = [(name_, arr.dtype, arr.shape[1:]) for name_, arr in zip(names, arrays, strict=False)] types = np.dtype(types) vals = np.rec.fromarrays(arrays, dtype=types) if master_is_required: if count > 1: out = empty(total_size, dtype=masters[0].dtype) timestamps = concatenate(masters, out=out) else: timestamps = masters[0] else: timestamps = None if channel_invalidation_present: if count > 1: out = empty(total_size, dtype=invalidation_arrays[0].dtype) invalidation_array = concatenate(invalidation_arrays, out=out) else: invalidation_array = invalidation_arrays[0] if not ignore_invalidation_bits: vals = vals[nonzero(~invalidation_array)[0]] if master_is_required: if timestamps is None: raise RuntimeError("'timestamps' cannot be None if 'master_is_required' is True") timestamps = timestamps[nonzero(~invalidation_array)[0]] invalidation_bits = None else: invalidation_bits = invalidation_array else: invalidation_bits = None if raster: if timestamps is None: raise RuntimeError("'timestamps' cannot be None if 'raster' is not None") if len(timestamps) > 1: t = arange(timestamps[0], timestamps[-1], raster, dtype=np.float64) signal = Signal(vals, timestamps, name="_", invalidation_bits=invalidation_bits).interp( t, integer_interpolation_mode=self._integer_interpolation, float_interpolation_mode=self._float_interpolation, ) vals, timestamps, invalidation_bits = ( signal.samples, signal.timestamps, signal.invalidation_bits, ) return vals, timestamps, invalidation_bits, None @overload def _get_array( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[False], record_offset: int, record_count: int | None, master_is_required: Literal[False], ) -> tuple[NDArray[Any], None, NDArray[np.bool] | None, None]: ... @overload def _get_array( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[True], record_offset: int, record_count: int | None, master_is_required: Literal[False], ) -> tuple[NDArray[Any], None, None, None]: ... @overload def _get_array( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[False], record_offset: int, record_count: int | None, master_is_required: Literal[True], ) -> tuple[NDArray[Any], NDArray[Any], NDArray[np.bool] | None, None]: ... @overload def _get_array( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[True], record_offset: int, record_count: int | None, master_is_required: Literal[True], ) -> tuple[NDArray[Any], NDArray[Any], None, None]: ... @overload def _get_array( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: bool, record_offset: int, record_count: int | None, master_is_required: bool, ) -> tuple[NDArray[Any], NDArray[Any] | None, NDArray[np.bool] | None, None]: ... def _get_array( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock], raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: bool, record_offset: int, record_count: int | None, master_is_required: bool, ) -> tuple[NDArray[Any], NDArray[Any] | None, NDArray[np.bool] | None, None]: grp = group gp_nr = group_index ch_nr = channel_index # get data group record self._prepare_record(grp) # get group data if data is None: fragments = self._load_data(grp, record_offset=record_offset, record_count=record_count) else: fragments = iter((data,)) dep = ca_block = dependency_list[0] shape = tuple(typing.cast(int, ca_block[f"dim_size_{i}"]) for i in range(ca_block.dims)) shape = tuple(dim for dim in shape if dim > 1) shape = shape or (1,) dim = 1 for d in shape: dim *= d size = ca_block.byte_offset_base * dim if group.uses_ld: record_size = group.channel_group.samples_byte_nr else: record_size = group.channel_group.samples_byte_nr + group.channel_group.invalidation_bytes_nr channel_dtype = get_fmt_v4( channel.data_type, channel.bit_count, channel.channel_type, ) byte_offset = channel.byte_offset dtype_fmt: np.dtype[Any] = np.dtype( [ ("", f"S{byte_offset}"), ("vals", channel_dtype, shape), ("", f"S{record_size - size - byte_offset}"), ] ) channel_invalidation_present = channel.flags & (v4c.FLAG_CN_ALL_INVALID | v4c.FLAG_CN_INVALIDATION_PRESENT) channel_group = grp.channel_group samples_size = channel_group.samples_byte_nr + channel_group.invalidation_bytes_nr channel_values: list[NDArray[Any]] = [] masters: list[NDArray[Any]] = [] invalidation_arrays: list[InvalidationArray] = [] count = 0 timestamps: NDArray[Any] | None for fragment in fragments: arrays: list[NDArray[Any]] = [] types: list[tuple[str, np.dtype[Any], tuple[int, ...]]] = [] data_bytes, offset, _count, invalidation_bytes = ( fragment.data, fragment.record_offset, fragment.record_count, fragment.invalidation_data, ) cycles = len(data_bytes) // samples_size vals = frombuffer(data_bytes, dtype=dtype_fmt)["vals"] if dep.flags & v4c.FLAG_CA_INVERSE_LAYOUT: shape = vals.shape shape = (shape[0],) + shape[1:][::-1] vals = vals.reshape(shape) axes = (0, *reversed(range(1, len(shape)))) vals = transpose(vals, axes=axes) cycles_nr = len(vals) dtype_pair: tuple[str, np.dtype[Any], tuple[int, ...]] for ca_block in dependency_list[:1]: if not isinstance(ca_block, ChannelArrayBlock): break dims_nr = ca_block.dims if ca_block.ca_type == v4c.CA_TYPE_SCALE_AXIS: shape = (ca_block.dim_size_0,) arrays.append(vals) dtype_pair = channel.name, vals.dtype, shape types.append(dtype_pair) elif ca_block.ca_type == v4c.CA_TYPE_LOOKUP: shape = vals.shape[1:] arrays.append(vals) dtype_pair = channel.name, vals.dtype, shape types.append(dtype_pair) if ca_block.flags & v4c.FLAG_CA_FIXED_AXIS: for i in range(dims_nr): shape = (typing.cast(int, ca_block[f"dim_size_{i}"]),) axis_list: list[float] = [] for j in range(shape[0]): key = f"axis_{i}_value_{j}" axis_list.append(typing.cast(float, ca_block[key])) axis = array(axis_list) axis = array([axis for _ in range(cycles_nr)]) arrays.append(axis) dtype_pair = (f"axis_{i}", axis.dtype, shape) types.append(dtype_pair) else: for i in range(dims_nr): axis_channel = ca_block.axis_channels[i] shape = (typing.cast(int, ca_block[f"dim_size_{i}"]),) if axis_channel is None: axisname = f"axis_{i}" axis_values = array( [arange(shape[0])] * cycles, dtype=f"({shape[0]},)f8", ) else: try: (ref_dg_nr, ref_ch_nr) = axis_channel except: debug_channel(self, grp, channel, dependency_list) raise axisname = self.groups[ref_dg_nr].channels[ref_ch_nr].name if ref_dg_nr == gp_nr: axis_values = self.get( group=ref_dg_nr, index=ref_ch_nr, samples_only=True, data=fragment, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=cycles, raw=True, )[0] else: channel_group = grp.channel_group record_size = channel_group.samples_byte_nr record_size += channel_group.invalidation_bytes_nr start = offset // record_size end = start + len(data_bytes) // record_size + 1 ref = self.get( group=ref_dg_nr, index=ref_ch_nr, samples_only=True, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=cycles, raw=True, )[0] axis_values = ref[start:end].copy() axis_values = axis_values[axisname] if len(axis_values) == 0 and cycles: axis_values = array([arange(shape[0])] * cycles) arrays.append(axis_values) dtype_pair = (axisname, axis_values.dtype, shape) types.append(dtype_pair) elif ca_block.ca_type == v4c.CA_TYPE_ARRAY: shape = vals.shape[1:] arrays.append(vals) dtype_pair = channel.name, vals.dtype, shape types.append(dtype_pair) for ca_block in dependency_list[1:]: if not isinstance(ca_block, ChannelArrayBlock): break dims_nr = ca_block.dims if ca_block.flags & v4c.FLAG_CA_FIXED_AXIS: for i in range(dims_nr): shape = (typing.cast(int, ca_block[f"dim_size_{i}"]),) axis_list = [] for j in range(shape[0]): key = f"axis_{i}_value_{j}" axis_list.append(typing.cast(float, ca_block[key])) axis = array([axis_list for _ in range(cycles_nr)], dtype=f"{shape}f8") arrays.append(axis) types.append((f"axis_{i}", axis.dtype, shape)) else: for i in range(dims_nr): axis_channel = ca_block.axis_channels[i] shape = (typing.cast(int, ca_block[f"dim_size_{i}"]),) if axis_channel is None: axisname = f"axis_{i}" axis_values = array([arange(shape[0])] * cycles, dtype=f"({shape[0]},)f8") else: try: ref_dg_nr, ref_ch_nr = axis_channel except: debug_channel(self, grp, channel, dependency_list) raise axisname = self.groups[ref_dg_nr].channels[ref_ch_nr].name if ref_dg_nr == gp_nr: axis_values = self.get( group=ref_dg_nr, index=ref_ch_nr, samples_only=True, data=fragment, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=cycles, raw=False, )[0] else: channel_group = grp.channel_group record_size = channel_group.samples_byte_nr record_size += channel_group.invalidation_bytes_nr start = offset // record_size end = start + len(data_bytes) // record_size + 1 ref = self.get( group=ref_dg_nr, index=ref_ch_nr, samples_only=True, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=cycles, raw=False, )[0] axis_values = ref[start:end].copy() axis_values = axis_values[axisname] if len(axis_values) == 0 and cycles: axis_values = array([arange(shape[0])] * cycles) arrays.append(axis_values) dtype_pair = (axisname, axis_values.dtype, shape) types.append(dtype_pair) vals = np.rec.fromarrays(arrays, np.dtype(types)) if master_is_required: masters.append(self.get_master(gp_nr, fragment, one_piece=True)) if channel_invalidation_present: invalidation_arrays.append(self.get_invalidation_bits(gp_nr, channel.pos_invalidation_bit, fragment)) channel_values.append(vals) count += 1 if count > 1: total_size = sum(len(_) for _ in channel_values) shape = (total_size,) + channel_values[0].shape[1:] if count > 1: out = empty(shape, dtype=channel_values[0].dtype) vals = concatenate(channel_values, out=out) elif count == 1: vals = channel_values[0] else: vals = np.array([]) if master_is_required: if count > 1: out = empty(total_size, dtype=masters[0].dtype) timestamps = concatenate(masters, out=out) else: timestamps = masters[0] else: timestamps = None if channel_invalidation_present: if count > 1: out = empty(total_size, dtype=invalidation_arrays[0].dtype) invalidation_array = concatenate(invalidation_arrays, out=out) else: invalidation_array = invalidation_arrays[0] if not ignore_invalidation_bits: vals = vals[nonzero(~invalidation_array)[0]] if master_is_required: if timestamps is None: raise RuntimeError("'timestamps' cannot be None is 'master_is_required' is True") timestamps = timestamps[nonzero(~invalidation_array)[0]] invalidation_bits = None else: invalidation_bits = invalidation_array else: invalidation_bits = None if raster: if timestamps is None: raise RuntimeError("'timestamps' cannot be None is 'raster' is not None") if len(timestamps) > 1: t = arange(timestamps[0], timestamps[-1], raster, dtype=np.float64) signal = Signal(vals, timestamps, name="_", invalidation_bits=invalidation_bits).interp( t, integer_interpolation_mode=self._integer_interpolation, float_interpolation_mode=self._float_interpolation, ) vals, timestamps, invalidation_bits = ( signal.samples, signal.timestamps, signal.invalidation_bits, ) return vals, timestamps, invalidation_bits, None def _fast_scalar_path( self, gp_nr: int, record_size: int, byte_offset: int, byte_size: int, pos_invalidation_bit: int, # data_type, # channel_type, # bit_count, dtype: np.dtype[Any], fragment: Fragment, ) -> tuple[NDArray[Any], None, InvalidationArray | None, None]: buffer: Buffer if fragment.is_record: buffer = get_channel_raw_bytes( fragment.data, record_size, byte_offset, byte_size, ) else: buffer = fragment.data vals = frombuffer(buffer, dtype=dtype) if pos_invalidation_bit >= 0: invalidation_bits = self.get_invalidation_bits(gp_nr, pos_invalidation_bit, fragment) else: invalidation_bits = None return vals, None, invalidation_bits, None @overload def _get_scalar( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock] | list[tuple[int, int]] | None, raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[False], record_offset: int, record_count: int | None, master_is_required: Literal[False], skip_vlsd: bool = ..., ) -> tuple[NDArray[Any], None, NDArray[np.bool] | None, str | None]: ... @overload def _get_scalar( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock] | list[tuple[int, int]] | None, raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[True], record_offset: int, record_count: int | None, master_is_required: Literal[False], skip_vlsd: bool = ..., ) -> tuple[NDArray[Any], None, None, str | None]: ... @overload def _get_scalar( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock] | list[tuple[int, int]] | None, raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[False], record_offset: int, record_count: int | None, master_is_required: Literal[True], skip_vlsd: bool = ..., ) -> tuple[NDArray[Any], NDArray[Any], NDArray[np.bool] | None, str | None]: ... @overload def _get_scalar( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock] | list[tuple[int, int]] | None, raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: Literal[True], record_offset: int, record_count: int | None, master_is_required: Literal[True], skip_vlsd: bool = ..., ) -> tuple[NDArray[Any], NDArray[Any], None, str | None]: ... @overload def _get_scalar( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock] | list[tuple[int, int]] | None, raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: bool, record_offset: int, record_count: int | None, master_is_required: bool, skip_vlsd: bool = ..., ) -> tuple[NDArray[Any], NDArray[Any] | None, NDArray[np.bool] | None, str | None]: ... def _get_scalar( self, channel: Channel, group: Group, group_index: int, channel_index: int, dependency_list: list[ChannelArrayBlock] | list[tuple[int, int]] | None, raster: RasterType | None, data: Fragment | None, ignore_invalidation_bits: bool, record_offset: int, record_count: int | None, master_is_required: bool, skip_vlsd: bool = False, ) -> tuple[NDArray[Any], NDArray[Any] | None, NDArray[np.bool] | None, str | None]: grp = group # get group data if data is None: fragments = self._load_data(grp, record_offset=record_offset, record_count=record_count) one_piece = False else: fragments = iter((data,)) one_piece = True gp_nr = group_index ch_nr = channel_index channel_invalidation_present = channel.flags & (v4c.FLAG_CN_ALL_INVALID | v4c.FLAG_CN_INVALIDATION_PRESENT) data_type = channel.data_type channel_type = channel.channel_type bit_count = channel.bit_count encoding: str | None = None channel_dtype = channel.dtype_fmt vals: NDArray[Any] timestamps: NDArray[Any] | None = None invalidation_bits: NDArray[np.bool] | None = None # get channel values if channel_type in { v4c.CHANNEL_TYPE_VIRTUAL, v4c.CHANNEL_TYPE_VIRTUAL_MASTER, }: if channel.dtype_fmt == np.dtype(np.void): channel.dtype_fmt = np.dtype(get_fmt_v4(data_type, 64)) ch_dtype = channel.dtype_fmt channel_values: list[NDArray[Any]] = [] masters: list[NDArray[Any]] = [] invalidation_arrays: list[InvalidationArray] = [] channel_group = grp.channel_group record_size = channel_group.samples_byte_nr record_size += channel_group.invalidation_bytes_nr count = 0 for fragment in fragments: data_bytes, offset, _count, invalidation_bytes = ( fragment.data, fragment.record_offset, fragment.record_count, fragment.invalidation_data, ) offset = offset // record_size vals = arange(len(data_bytes) // record_size, dtype=ch_dtype) vals += offset if master_is_required: masters.append( self.get_master( gp_nr, fragment, record_offset=offset, record_count=_count, one_piece=True, ) ) if channel_invalidation_present: invalidation_arrays.append( self.get_invalidation_bits(gp_nr, channel.pos_invalidation_bit, fragment) ) channel_values.append(vals) count += 1 if count > 1: total_size = sum(len(_) for _ in channel_values) shape = (total_size,) + channel_values[0].shape[1:] if count > 1: out = empty(shape, dtype=channel_values[0].dtype) vals = concatenate(channel_values, out=out) elif count == 1: vals = channel_values[0] else: vals = np.array([]) if master_is_required: if count > 1: out = empty(total_size, dtype=masters[0].dtype) timestamps = concatenate(masters, out=out) else: timestamps = masters[0] else: timestamps = None if channel_invalidation_present: if count > 1: out = empty(total_size, dtype=invalidation_arrays[0].dtype) invalidation_array = concatenate(invalidation_arrays, out=out) else: invalidation_array = invalidation_arrays[0] if not ignore_invalidation_bits: vals = vals[nonzero(~invalidation_array)[0]] if master_is_required: if timestamps is None: raise RuntimeError("'timestamps' cannot be None if 'master_is_required' is True") timestamps = timestamps[nonzero(~invalidation_array)[0]] invalidation_bits = None else: invalidation_bits = invalidation_array else: invalidation_bits = None if raster: if timestamps is None: raise RuntimeError("'timestamps' cannot be None if 'raster' is not None") if len(timestamps) > 1: num = float(float32((timestamps[-1] - timestamps[0]) / raster)) if num.is_integer(): t = linspace(timestamps[0], timestamps[-1], int(num)) else: t = arange(timestamps[0], timestamps[-1], raster) signal = Signal(vals, timestamps, name="_", invalidation_bits=invalidation_bits).interp( t, integer_interpolation_mode=self._integer_interpolation, float_interpolation_mode=self._float_interpolation, ) vals, timestamps, invalidation_bits = ( signal.samples, signal.timestamps, signal.invalidation_bits, ) if channel.conversion: vals = channel.conversion.convert(vals) else: channel_group = grp.channel_group record_size = channel_group.samples_byte_nr if one_piece: fragment = next(fragments) data_bytes, rec_offset, rec_count = fragment.data, fragment.record_offset, fragment.record_count record = self._prepare_record(grp) info = record[ch_nr] if info is not None: dtype_, byte_size, byte_offset, bit_offset = info buffer: Buffer if ch_nr == 0 and len(grp.channels) == 1 and channel.dtype_fmt.itemsize == record_size: buffer = bytearray(data_bytes) else: if fragment.is_record: buffer = get_channel_raw_bytes( data_bytes, record_size + channel_group.invalidation_bytes_nr, byte_offset, byte_size, ) else: buffer = data_bytes vals = frombuffer(buffer, dtype=dtype_) if not channel.standard_C_size: size = byte_size view: DTypeLike if channel_dtype.byteorder == "=" and data_type in ( v4c.DATA_TYPE_SIGNED_MOTOROLA, v4c.DATA_TYPE_UNSIGNED_MOTOROLA, ): view = np.dtype(f">u{vals.itemsize}") else: view = np.dtype(f"{channel_dtype.byteorder}u{vals.itemsize}") if view != vals.dtype: vals = vals.view(view) if bit_offset: vals >>= bit_offset if bit_count != size * 8: if data_type in v4c.SIGNED_INT: vals = as_non_byte_sized_signed_int(vals, bit_count) else: mask = (1 << bit_count) - 1 vals &= mask elif data_type in v4c.SIGNED_INT: view = f"{channel_dtype.byteorder}i{vals.itemsize}" if np.dtype(view) != vals.dtype: vals = vals.view(view) elif channel_type == v4c.CHANNEL_TYPE_VALUE and channel.fast_path is None: channel.fast_path = ( gp_nr, record_size + channel_group.invalidation_bytes_nr, byte_offset, byte_size, channel.pos_invalidation_bit if channel_invalidation_present else -1, # data_type, # channel_type, # bit_count, dtype_, ) else: vals = self._get_not_byte_aligned_data(data_bytes, grp, ch_nr) if bit_count == 1 and self._single_bit_uint_as_bool: vals = array(vals, dtype=bool) if master_is_required: timestamps = self.get_master(gp_nr, fragment, one_piece=True) else: timestamps = None if channel_invalidation_present: invalidation_array = self.get_invalidation_bits(gp_nr, channel.pos_invalidation_bit, fragment) if not ignore_invalidation_bits: vals = vals[nonzero(~invalidation_array)[0]] if master_is_required: if timestamps is None: raise RuntimeError("'timestamps' cannot be None if 'master_is_required' is True") timestamps = timestamps[nonzero(~invalidation_array)[0]] invalidation_bits = None else: invalidation_bits = invalidation_array else: invalidation_bits = None else: channel_values = [] masters = [] invalidation_arrays = [] record = self._prepare_record(grp) info = record[ch_nr] if info is None: for count, fragment in enumerate(fragments, 1): data_bytes, offset, _count, invalidation_bytes = ( fragment.data, fragment.record_offset, fragment.record_count, fragment.invalidation_data, ) vals = self._get_not_byte_aligned_data(data_bytes, grp, ch_nr) if bit_count == 1 and self._single_bit_uint_as_bool: vals = array(vals, dtype=bool) if master_is_required: masters.append(self.get_master(gp_nr, fragment, one_piece=True)) if channel_invalidation_present: invalidation_arrays.append( self.get_invalidation_bits(gp_nr, channel.pos_invalidation_bit, fragment) ) channel_values.append(vals) vals = concatenate(channel_values) else: dtype_, byte_size, byte_offset, bit_offset = info buffers: list[bytearray] = [] count = 0 for count, fragment in enumerate(fragments, 1): data_bytes = fragment.data if ch_nr == 0 and len(grp.channels) == 1 and channel.dtype_fmt.itemsize == record_size: buffers.append(bytearray(data_bytes)) else: buffers.append( get_channel_raw_bytes( data_bytes, record_size + channel_group.invalidation_bytes_nr, byte_offset, byte_size, ) ) if master_is_required: masters.append(self.get_master(gp_nr, fragment, one_piece=True)) if channel_invalidation_present: invalidation_arrays.append( self.get_invalidation_bits(gp_nr, channel.pos_invalidation_bit, fragment) ) if count > 1: buffer = bytearray().join(buffers) elif count == 1: buffer = buffers[0] else: buffer = bytearray() vals = frombuffer(buffer, dtype=dtype_) if not channel.standard_C_size: size = dtype_.itemsize if channel_dtype.byteorder == "=" and data_type in ( v4c.DATA_TYPE_SIGNED_MOTOROLA, v4c.DATA_TYPE_UNSIGNED_MOTOROLA, ): view = f">u{vals.itemsize}" else: view = f"{channel_dtype.byteorder}u{vals.itemsize}" if np.dtype(view) != dtype_: vals = vals.view(view) if bit_offset: vals >>= bit_offset if bit_count != size * 8: if data_type in v4c.SIGNED_INT: vals = as_non_byte_sized_signed_int(vals, bit_count) else: mask = (1 << bit_count) - 1 vals &= mask elif data_type in v4c.SIGNED_INT: view = f"{channel_dtype.byteorder}i{vals.itemsize}" if np.dtype(view) != vals.dtype: vals = vals.view(view) if bit_count == 1 and self._single_bit_uint_as_bool: vals = array(vals, dtype=bool) total_size = len(vals) if master_is_required: if count > 1: out = empty(total_size, dtype=masters[0].dtype) timestamps = concatenate(masters, out=out) elif count == 1: timestamps = masters[0] else: timestamps = np.array([], dtype=np.float64) else: timestamps = None if channel_invalidation_present: if count > 1: out = empty(total_size, dtype=invalidation_arrays[0].dtype) invalidation_array = concatenate(invalidation_arrays, out=out) elif count == 1: invalidation_array = invalidation_arrays[0] else: invalidation_array = typing.cast( np.ndarray[tuple[int], np.dtype[np.bool]], np.array([], dtype=np.bool) ) if not ignore_invalidation_bits: vals = vals[nonzero(~invalidation_array)[0]] if master_is_required: if timestamps is None: raise RuntimeError("'timestamps' cannot be None if 'master_is_required' is True") timestamps = timestamps[nonzero(~invalidation_array)[0]] invalidation_bits = None else: invalidation_bits = invalidation_array else: invalidation_bits = None if raster: if timestamps is None: raise RuntimeError("'timestamps' cannot be None if 'raster' is not None") if len(timestamps) > 1: num = float(float32((timestamps[-1] - timestamps[0]) / raster)) if num.is_integer(): t = linspace(timestamps[0], timestamps[-1], int(num)) else: t = arange(timestamps[0], timestamps[-1], raster) signal = Signal(vals, timestamps, name="_", invalidation_bits=invalidation_bits).interp( t, integer_interpolation_mode=self._integer_interpolation, float_interpolation_mode=self._float_interpolation, ) vals, timestamps, invalidation_bits = ( signal.samples, signal.timestamps, signal.invalidation_bits, ) if channel_type == v4c.CHANNEL_TYPE_VLSD and not skip_vlsd: count_ = len(vals) if count_: signal_data = self._load_signal_data(group=grp, index=ch_nr, offsets=(vals[0], vals[-1])) else: signal_data = b"" max_vlsd_size = self.determine_max_vlsd_sample_size(group_index, channel_index) if signal_data: if data_type in ( v4c.DATA_TYPE_BYTEARRAY, v4c.DATA_TYPE_UNSIGNED_INTEL, v4c.DATA_TYPE_UNSIGNED_MOTOROLA, v4c.DATA_TYPE_MIME_SAMPLE, v4c.DATA_TYPE_MIME_STREAM, ): vals = extract(signal_data, True, vals - vals[0]) if vals.shape[1] < max_vlsd_size: vals = np.hstack( ( vals, np.zeros( ( vals.shape[0], max_vlsd_size - vals.shape[1], ), dtype=vals.dtype, ), ) ) else: vals = extract(signal_data, False, vals - vals[0]) if data_type not in ( v4c.DATA_TYPE_BYTEARRAY, v4c.DATA_TYPE_UNSIGNED_INTEL, v4c.DATA_TYPE_UNSIGNED_MOTOROLA, v4c.DATA_TYPE_MIME_SAMPLE, v4c.DATA_TYPE_MIME_STREAM, ): match data_type: case v4c.DATA_TYPE_STRING_UTF_16_BE: encoding = "utf-16-be" case v4c.DATA_TYPE_STRING_UTF_16_LE: encoding = "utf-16-le" case v4c.DATA_TYPE_STRING_UTF_8: encoding = "utf-8" vals = np.array( [e.rsplit(b"\0")[0] for e in typing.cast(list[bytes], vals.tolist())], dtype=vals.dtype, ) case v4c.DATA_TYPE_STRING_LATIN_1: encoding = "latin-1" vals = np.array( [e.rsplit(b"\0")[0] for e in typing.cast(list[bytes], vals.tolist())], dtype=vals.dtype, ) case _: raise MdfException(f'wrong data type "{data_type}" for vlsd channel "{channel.name}"') vals = vals.astype(f"S{max_vlsd_size}") else: if len(vals): raise MdfException( f'Wrong signal data block refence (0x{channel.data_block_addr:X}) for VLSD channel "{channel.name}"' ) # no VLSD signal data samples if data_type != v4c.DATA_TYPE_BYTEARRAY: vals = array([], dtype=f"S{max_vlsd_size}") match data_type: case v4c.DATA_TYPE_STRING_UTF_16_BE: encoding = "utf-16-be" case v4c.DATA_TYPE_STRING_UTF_16_LE: encoding = "utf-16-le" case v4c.DATA_TYPE_STRING_UTF_8: encoding = "utf-8" case v4c.DATA_TYPE_STRING_LATIN_1: encoding = "latin-1" case _: raise MdfException(f'wrong data type "{data_type}" for vlsd channel "{channel.name}"') else: vals = array([], dtype=f"({max_vlsd_size},)u1") elif v4c.DATA_TYPE_STRING_LATIN_1 <= data_type <= v4c.DATA_TYPE_STRING_UTF_16_BE: if channel_type in (v4c.CHANNEL_TYPE_VALUE, v4c.CHANNEL_TYPE_MLSD): match data_type: case v4c.DATA_TYPE_STRING_UTF_16_BE: encoding = "utf-16-be" case v4c.DATA_TYPE_STRING_UTF_16_LE: encoding = "utf-16-le" case v4c.DATA_TYPE_STRING_UTF_8: encoding = "utf-8" case v4c.DATA_TYPE_STRING_LATIN_1: encoding = "latin-1" case _: raise MdfException(f'wrong data type "{data_type}" for string channel') elif data_type in (v4c.DATA_TYPE_CANOPEN_TIME, v4c.DATA_TYPE_CANOPEN_DATE): # CANopen date if data_type == v4c.DATA_TYPE_CANOPEN_DATE: types: np.dtype[Any] = np.dtype( [ ("ms", "> 7, # add summer or standard time information for hour (vals["day"] & 0xF0) >> 4, # add day of week information ] names = [ "ms", "min", "hour", "day", "month", "year", "summer_time", "day_of_week", ] vals = np.rec.fromarrays(arrays, names=names) # type: ignore[call-overload] # CANopen time elif data_type == v4c.DATA_TYPE_CANOPEN_TIME: types = np.dtype([("ms", " NDArray[Any]: big_endian_types = ( v4c.DATA_TYPE_UNSIGNED_MOTOROLA, v4c.DATA_TYPE_REAL_MOTOROLA, v4c.DATA_TYPE_SIGNED_MOTOROLA, ) if group.uses_ld: record_size = group.channel_group.samples_byte_nr else: record_size = group.channel_group.samples_byte_nr + group.channel_group.invalidation_bytes_nr channel = group.channels[ch_nr] bit_offset = channel.bit_offset byte_offset = channel.byte_offset bit_count = channel.bit_count if ch_nr >= 0: dependencies = group.channel_dependencies[ch_nr] if dependencies and isinstance(dependencies[0], ChannelArrayBlock): ca_block = dependencies[0] size = bit_count // 8 shape = tuple(typing.cast(int, ca_block[f"dim_size_{i}"]) for i in range(ca_block.dims)) if ca_block.byte_offset_base // size > 1 and len(shape) == 1: shape += (ca_block.byte_offset_base // size,) dim = 1 for d in shape: dim *= d size *= dim bit_count = size * 8 byte_size = bit_offset + bit_count if byte_size % 8: byte_size = (byte_size // 8) + 1 else: byte_size //= 8 types = [ ("", f"S{byte_offset}"), ("vals", f"({byte_size},)u1"), ("", f"S{record_size - byte_size - byte_offset}"), ] vals: NDArray[Any] = np.rec.fromstring(data, dtype=np.dtype(types)) vals = vals["vals"] if byte_size in {1, 2, 4, 8}: extra_bytes = 0 elif byte_size < 8: extra_bytes = 4 - (byte_size % 4) else: extra_bytes = 0 std_size = byte_size + extra_bytes big_endian = channel.data_type in big_endian_types # prepend or append extra bytes columns # to get a standard size number of bytes if extra_bytes: if big_endian: vals = column_stack([vals, zeros(len(vals), dtype=f"<({extra_bytes},)u1")]) try: vals = vals.view(f">u{std_size}").ravel() except: vals = frombuffer(vals.tobytes(), dtype=f">u{std_size}") vals = vals >> (extra_bytes * 8 + bit_offset) vals &= (1 << bit_count) - 1 else: vals = column_stack([vals, zeros(len(vals), dtype=f"<({extra_bytes},)u1")]) try: vals = vals.view(f"> bit_offset vals &= (1 << bit_count) - 1 else: if big_endian: try: vals = vals.view(f">u{std_size}").ravel() except: vals = frombuffer(vals.tobytes(), dtype=f">u{std_size}") vals = vals >> bit_offset vals &= (1 << bit_count) - 1 else: try: vals = vals.view(f"> bit_offset vals &= (1 << bit_count) - 1 data_type = channel.data_type if data_type in v4c.SIGNED_INT: return as_non_byte_sized_signed_int(vals, bit_count) elif data_type in v4c.FLOATS: return vals.view(get_fmt_v4(data_type, bit_count)) else: return vals def _determine_max_vlsd_sample_size(self, group_idx: int, index: int) -> int: group_index = group_idx channel_index = index group = self.groups[group_idx] ch = group.channels[index] if ch.channel_type != v4c.CHANNEL_TYPE_VLSD: return 0 if (group_index, ch.name) in self.vlsd_max_length: return self.vlsd_max_length[(group_index, ch.name)] else: offsets, *_ = self._get_scalar( ch, group, group_index, channel_index, group.channel_dependencies[channel_index], raster=None, data=None, ignore_invalidation_bits=True, record_offset=0, record_count=None, master_is_required=False, skip_vlsd=True, ) offsets = offsets.astype("u8") data = self._load_signal_data(group, channel_index) max_size = get_vlsd_max_sample_size(data, offsets, len(offsets)) return max_size def included_channels( self, index: int | None = None, channels: ChannelsType | None = None, skip_master: bool = True, minimal: bool = True, ) -> dict[int, dict[int, list[int]]]: if channels is None: if index is None: raise ValueError("index cannot be None if channels is None") virtual_channel_group = self.virtual_groups[index] groups = virtual_channel_group.groups gps: dict[int, list[int]] = {} for gp_index in groups: group = self.groups[gp_index] included_channels = set(range(len(group.channels))) master_index = self.masters_db.get(gp_index, None) if master_index is not None: included_channels.remove(master_index) for dependencies in group.channel_dependencies: if dependencies is None: continue if all(not isinstance(dep, ChannelArrayBlock) for dep in dependencies): dependencies = typing.cast(list[tuple[int, int]], dependencies) for _, ch_nr in dependencies: try: included_channels.remove(ch_nr) except KeyError: pass else: dependencies = typing.cast(list[ChannelArrayBlock], dependencies) for dep in dependencies: for referenced_channels in ( dep.axis_channels, dep.dynamic_size_channels, dep.input_quantity_channels, ): for gp_nr, ch_nr in filter(None, referenced_channels): if gp_nr == gp_index: try: included_channels.remove(ch_nr) except KeyError: pass if dep.output_quantity_channel: gp_nr, ch_nr = dep.output_quantity_channel if gp_nr == gp_index: try: included_channels.remove(ch_nr) except KeyError: pass if dep.comparison_quantity_channel: gp_nr, ch_nr = dep.comparison_quantity_channel if gp_nr == gp_index: try: included_channels.remove(ch_nr) except KeyError: pass gps[gp_index] = sorted(included_channels) result = {index: gps} else: gps_set: dict[int, set[int]] = {} for item in channels: if isinstance(item, list | tuple): if len(item) not in (2, 3): raise MdfException( "The items used for filtering must be strings, " "or they must match the first 3 arguments of the get " "method" ) else: gp_nr, idx = self._validate_channel_selection(*item) gps_idx = gps_set.setdefault(gp_nr, set()) gps_idx.add(idx) else: name = item gp_nr, idx = self._validate_channel_selection(name) gps_idx = gps_set.setdefault(gp_nr, set()) gps_idx.add(idx) result = {} for gp_index, gps_idx in gps_set.items(): master = self.virtual_groups_map[gp_index] group = self.groups[gp_index] if minimal: channel_dependencies = [group.channel_dependencies[ch_nr] for ch_nr in gps_idx] for dependencies in channel_dependencies: if dependencies is None: continue if all(not isinstance(dep, ChannelArrayBlock) for dep in dependencies): dependencies = typing.cast(list[tuple[int, int]], dependencies) for _, ch_nr in dependencies: try: gps_idx.remove(ch_nr) except KeyError: pass else: dependencies = typing.cast(list[ChannelArrayBlock], dependencies) for dep in dependencies: for referenced_channels in ( dep.axis_channels, dep.dynamic_size_channels, dep.input_quantity_channels, ): for gp_nr, ch_nr in filter(None, referenced_channels): if gp_nr == gp_index: try: gps_idx.remove(ch_nr) except KeyError: pass if dep.output_quantity_channel: gp_nr, ch_nr = dep.output_quantity_channel if gp_nr == gp_index: try: gps_idx.remove(ch_nr) except KeyError: pass if dep.comparison_quantity_channel: gp_nr, ch_nr = dep.comparison_quantity_channel if gp_nr == gp_index: try: gps_idx.remove(ch_nr) except KeyError: pass gp_master = self.masters_db.get(gp_index, None) if gp_master is not None and gp_master in gps_idx: gps_idx.remove(gp_master) if master not in result: result[master] = {} result[master][master] = [self.masters_db.get(master, None)] # type: ignore[list-item] result[master][gp_index] = sorted(gps_idx) return result def _yield_selected_signals( self, index: int, groups: dict[int, list[int]] | None = None, record_offset: int = 0, record_count: int | None = None, skip_master: bool = True, version: str | None = None, ) -> Iterator[list[Signal] | list[tuple[NDArray[Any], None]]]: version = version or self.version virtual_channel_group = self.virtual_groups[index] record_size = virtual_channel_group.record_size from time import perf_counter tt = perf_counter() if groups is None: groups = self.included_channels(index, skip_master=skip_master)[index] record_size = 0 for group_index in groups: grp = self.groups[group_index] record_size += grp.channel_group.samples_byte_nr + grp.channel_group.invalidation_bytes_nr record_size = record_size or 1 if self._read_fragment_size: count = self._read_fragment_size // record_size or 1 else: if version < "4.20": count = 64 * 1024 * 1024 // record_size or 1 else: count = 128 * 1024 * 1024 // record_size or 1 data_streams: list[Iterator[Fragment]] = [] for idx, group_index in enumerate(groups): grp = self.groups[group_index] grp.read_split_count = count data_streams.append(self._load_data(grp, record_offset=record_offset, record_count=record_count)) if group_index == index: master_index = idx encodings: dict[int, list[tuple[str | None, np.dtype[Any]] | None]] = { group_index: [None] for group_index in groups } self._set_temporary_master(None) idx = 0 group_info: dict[int, list[list[int]]] = {} for group_index, channels in groups.items(): grp = self.groups[group_index] if not grp.single_channel_dtype: self._prepare_record(grp) ch_info: list[list[int]] = [] group_info[group_index] = ch_info dependency_list = grp.channel_dependencies info = self._prepare_record(grp) for channel_index in channels: channel = grp.channels[channel_index] if ( channel.byte_offset + (channel.bit_offset + channel.bit_count) / 8 > grp.channel_group.samples_byte_nr ): ch_info.append([0, 0]) elif dependency_list[channel_index]: ch_info.append([0, 0]) else: if (record := info[channel_index]) is not None: _, byte_size, byte_offset, _ = record ch_info.append([byte_offset, byte_size]) else: ch_info.append([0, 0]) while True: try: fragments = [next(stream) for stream in data_streams] except: break # # if perf_counter() - tt > 120: # x = 1 / 0 # prepare the master _master = self.get_master(index, data=fragments[master_index], one_piece=True) self._set_temporary_master(_master) signals: list[Signal] | list[tuple[NDArray[Any], None]] if idx == 0: signals = [] else: signals = [(_master, None)] for fragment, (group_index, channels) in zip(fragments, groups.items(), strict=False): grp = self.groups[group_index] if not grp.single_channel_dtype: self._prepare_record(grp) self._invalidation_cache.clear() if 1 and len(channels) >= 100: # prepare the invalidation bytes for this group and fragment invalidation_bytes = get_channel_raw_bytes( fragment.data, grp.channel_group.samples_byte_nr + grp.channel_group.invalidation_bytes_nr, grp.channel_group.samples_byte_nr, grp.channel_group.invalidation_bytes_nr, ) channels_raw_data = get_channel_raw_bytes_parallel( fragment.data, grp.channel_group.samples_byte_nr + grp.channel_group.invalidation_bytes_nr, group_info[group_index], THREAD_COUNT, ) if idx == 0: sigs = typing.cast(list[Signal], signals) for channel_index, raw_data in zip(channels, channels_raw_data, strict=False): signal = self.get( group=group_index, index=channel_index, data=( Fragment( data=raw_data, record_offset=fragment.record_offset, record_count=fragment.record_count, invalidation_data=invalidation_bytes, is_record=False, ) if raw_data else fragment ), raw=True, ignore_invalidation_bits=True, samples_only=False, skip_channel_validation=True, ) sigs.append(signal) else: for channel_index, raw_data in zip(channels, channels_raw_data, strict=False): samples, invalidation_bits = self.get( group=group_index, index=channel_index, data=( Fragment( data=raw_data, record_offset=fragment.record_offset, record_count=fragment.record_count, invalidation_data=invalidation_bytes, is_record=False, ) if raw_data else fragment ), raw=True, ignore_invalidation_bits=True, samples_only=True, skip_channel_validation=True, ) signals.append((samples, invalidation_bits)) else: if idx == 0: sigs = typing.cast(list[Signal], signals) for channel_index in channels: signal = self.get( group=group_index, index=channel_index, data=fragment, raw=True, ignore_invalidation_bits=True, samples_only=False, ) sigs.append(signal) else: for channel_index in channels: samples, invalidation_bits = self.get( group=group_index, index=channel_index, data=fragment, raw=True, ignore_invalidation_bits=True, samples_only=True, ) signals.append((samples, invalidation_bits)) if version < "4.00": if idx == 0: sigs = typing.cast(list[Signal], signals) for sig, channel_index in zip(sigs, channels, strict=False): if sig.samples.dtype.kind == "S": strsig = self.get( group=group_index, index=channel_index, samples_only=True, ignore_invalidation_bits=True, )[0] _dtype = strsig.dtype sig.samples = sig.samples.astype(_dtype) encodings[group_index].append((sig.encoding, _dtype)) del strsig if sig.encoding != "latin-1": if sig.encoding == "utf-16-le": sig.samples = sig.samples.view(uint16).byteswap().view(sig.samples.dtype) sig.samples = encode(decode(sig.samples, "utf-16-be"), "latin-1") else: sig.samples = encode( decode(sig.samples, sig.encoding), "latin-1", ) sig.samples = sig.samples.astype(_dtype) else: encodings[group_index].append(None) else: for i, (sig_samples, encoding_tuple) in enumerate( zip(signals, encodings[group_index], strict=False) ): if encoding_tuple: encoding, _dtype = encoding_tuple samples = sig_samples[0] if encoding != "latin-1": if encoding == "utf-16-le": samples = samples.view(uint16).byteswap().view(samples.dtype) samples = encode(decode(samples, "utf-16-be"), "latin-1") else: samples = encode(decode(samples, encoding), "latin-1") samples = samples.astype(_dtype) signals[i] = (samples, sig_samples[1]) self._set_temporary_master(None) idx += 1 yield signals grp.read_split_count = 0 self._invalidation_cache.clear() def get_master( self, index: int, data: Fragment | None = None, record_offset: int = 0, record_count: int | None = None, one_piece: bool = False, ) -> NDArray[Any]: """Get master channel samples for the given group. Parameters ---------- index : int Group index. data : Fragment, optional Data bytes as a Fragment. record_offset : int, optional If `data=None`, use this to select the record offset from which the group data should be loaded. record_count : int, optional Number of records to read; default is None and in this case all available records are used. Returns ------- t, virtual_master_conversion : (np.ndarray, ChannelConversion | None) Master channel samples and virtual master conversion. """ if self._master is not None: return self._master group = self.groups[index] if group.channel_group.flags & v4c.FLAG_CG_REMOTE_MASTER: if data is not None: record_offset = data.record_offset record_count = data.record_count return self.get_master( typing.cast(int, group.channel_group.cg_master_index), record_offset=record_offset, record_count=record_count, ) time_ch_nr = self.masters_db.get(index, None) channel_group = group.channel_group record_size = channel_group.samples_byte_nr record_size += channel_group.invalidation_bytes_nr if record_count is not None: cycles_nr = record_count else: cycles_nr = group.channel_group.cycles_nr fragment = data if fragment: data_bytes, offset, _, invalidation_bytes = ( fragment.data, fragment.record_offset, fragment.record_count, fragment.invalidation_data, ) cycles_nr = len(data_bytes) // record_size if record_size else 0 record_offset = fragment.record_offset record_count = fragment.record_count else: offset = 0 t: NDArray[Any] if time_ch_nr is None: if record_size: t = arange(cycles_nr, dtype=float64) t += offset else: t = array([], dtype=float64) metadata = ("timestamps", v4c.SYNC_TYPE_TIME) else: time_ch = group.channels[time_ch_nr] time_conv = time_ch.conversion time_name = time_ch.name metadata = (time_name, time_ch.sync_type) if time_ch.channel_type == v4c.CHANNEL_TYPE_VIRTUAL_MASTER: if record_count is None: t = arange(record_offset, cycles_nr, 1, dtype=float64) else: t = arange(record_offset, record_offset + record_count, 1, dtype=float64) if time_conv is not None: t = time_conv.convert(t) else: # check if the channel group contains just the master channel # and that there are no padding bytes if len(group.channels) == 1 and time_ch.dtype_fmt.itemsize == record_size: if one_piece: if data is None: raise RuntimeError("data is None") t = frombuffer(data.data, dtype=time_ch.dtype_fmt) else: # get data fragments: Iterable[Fragment] if fragment is None: fragments = self._load_data( group, record_offset=record_offset, record_count=record_count, ) else: fragments = (fragment,) buffer = bytearray().join([fragment.data for fragment in fragments]) t = frombuffer(buffer, dtype=time_ch.dtype_fmt) else: record = typing.cast(list[tuple[np.dtype[Any], int, int, int]], self._prepare_record(group)) dtype_, byte_size, byte_offset, bit_offset = record[time_ch_nr] if one_piece: if data is None: raise RuntimeError("data is None") data_bytes = data.data buffer = get_channel_raw_bytes( data_bytes, record_size, byte_offset, byte_size, ) t = frombuffer(buffer, dtype=dtype_) else: # get data if fragment is None: fragments = self._load_data( group, record_offset=record_offset, record_count=record_count, ) else: fragments = (fragment,) buffer = bytearray().join( [ get_channel_raw_bytes( fragment.data, record_size, byte_offset, byte_size, ) for fragment in fragments ] ) t = frombuffer(buffer, dtype=dtype_) if not time_ch.standard_C_size: channel_dtype = time_ch.dtype_fmt bit_count = time_ch.bit_count data_type = time_ch.data_type size = byte_size if channel_dtype.byteorder == "=" and time_ch.data_type in ( v4c.DATA_TYPE_SIGNED_MOTOROLA, v4c.DATA_TYPE_UNSIGNED_MOTOROLA, ): dtype = f">u{t.itemsize}" else: dtype = f"{channel_dtype.byteorder}u{t.itemsize}" if np.dtype(dtype) != t.dtype: t = t.view(dtype) if bit_offset: t >>= bit_offset if bit_count != size * 8: if data_type in v4c.SIGNED_INT: t = as_non_byte_sized_signed_int(t, bit_count) else: mask = (1 << bit_count) - 1 t &= mask elif data_type in v4c.SIGNED_INT: dtype = f"{channel_dtype.byteorder}i{t.itemsize}" if np.dtype(dtype) != t.dtype: t = t.view(dtype) # get timestamps if time_conv: t = time_conv.convert(t) self._master_channel_metadata[index] = metadata if t.dtype != float64: t = t.astype(float64) return t def get_bus_signal( self, bus: BusType, name: str, database: CanMatrix | StrPath | None = None, ignore_invalidation_bits: bool = False, data: Fragment | None = None, raw: bool = False, ignore_value2text_conversion: bool = True, ) -> Signal: """Get a signal decoded from a raw bus logging. The currently supported buses are CAN and LIN (LDF databases are not supported, they need to be converted to DBC and fed to this function). .. versionadded:: 6.0.0 Parameters ---------- bus : str "CAN" or "LIN". name : str Signal name. database : str | path-like | CanMatrix, optional Path of external CAN/LIN database file (.dbc or .arxml) or canmatrix.CanMatrix. .. versionchanged:: 6.0.0 `db` and `database` arguments were merged into this single argument. ignore_invalidation_bits : bool, default False Option to ignore invalidation bits. data : Fragment, optional Data bytes as a Fragment. raw : bool, default False Return channel samples without applying the conversion rule. ignore_value2text_conversion : bool, default True Return channel samples without values that have a description in .dbc or .arxml file. Returns ------- sig : Signal Signal object with the physical values. """ match bus: case "CAN": return self.get_can_signal( name, database=database, ignore_invalidation_bits=ignore_invalidation_bits, data=data, raw=raw, ignore_value2text_conversion=ignore_value2text_conversion, ) case "LIN": return self.get_lin_signal( name, database=database, ignore_invalidation_bits=ignore_invalidation_bits, data=data, raw=raw, ignore_value2text_conversion=ignore_value2text_conversion, ) def get_can_signal( self, name: str, database: CanMatrix | StrPath | None = None, ignore_invalidation_bits: bool = False, data: Fragment | None = None, raw: bool = False, ignore_value2text_conversion: bool = True, ) -> Signal: """Get CAN message signal. You can specify an external CAN database path or a canmatrix database object that has already been loaded from a file. The signal name can be specified in the following ways: * ``CAN..`` - the `ID` value starts from 1 and must match the ID found in the measurement (the source CAN bus ID). Example: CAN1.Wheels.FL_WheelSpeed * ``CAN.CAN_DataFrame_.`` - the `ID` value starts from 1 and the `MESSAGE_ID` is the decimal message ID as found in the database. Example: CAN1.CAN_DataFrame_218.FL_WheelSpeed * ``.`` - in this case the first occurrence of the message name and signal are returned (the same message could be found on multiple CAN buses; for example on CAN1 and CAN3). Example: Wheels.FL_WheelSpeed * ``CAN_DataFrame_.`` - in this case the first occurrence of the message name and signal are returned (the same message could be found on multiple CAN buses; for example on CAN1 and CAN3). Example: CAN_DataFrame_218.FL_WheelSpeed * ```` - in this case the first occurrence of the signal name is returned (the same signal name could be found in multiple messages and on multiple CAN buses). Example: FL_WheelSpeed Parameters ---------- name : str Signal name. database : str | path-like | CanMatrix, optional Path of external CAN database file (.dbc or .arxml) or canmatrix.CanMatrix. .. versionchanged:: 6.0.0 `db` and `database` arguments were merged into this single argument. ignore_invalidation_bits : bool, default False Option to ignore invalidation bits. data : Fragment, optional Data bytes as a Fragment. raw : bool, default False Return channel samples without applying the conversion rule. ignore_value2text_conversion : bool, default True Return channel samples without values that have a description in .dbc or .arxml file. Returns ------- sig : Signal Signal object with the physical values. """ if database is None: return self.get(name) if isinstance(database, (str, Path)): database_path = Path(database) if database_path.suffix.lower() not in (".arxml", ".dbc"): message = f'Expected .dbc or .arxml file as CAN channel attachment but got "{database_path}"' logger.exception(message) raise MdfException(message) else: db_string = database_path.read_bytes() md5_sum = md5(db_string).digest() if md5_sum in self._external_dbc_cache: db = self._external_dbc_cache[md5_sum] else: db = load_can_database(database_path, contents=db_string) if db is None: raise MdfException("failed to load database") else: db = database is_j1939 = db.contains_j1939 name_ = name.split(".") message_id: str | int if len(name_) == 3: can_id_str, message_id_str, signal_name = name_ match = v4c.CAN_ID_PATTERN.search(can_id_str) if match is None: raise MdfException(f'CAN id "{can_id_str}" of signal name "{name}" is not recognised by this library') else: can_id = int(match.group("id")) match = v4c.CAN_DATA_FRAME_PATTERN.search(message_id_str) if match is None: message_id = message_id_str else: message_id = int(match.group("id")) if isinstance(message_id, str): frame = db.frame_by_name(message_id) else: frame = db.frame_by_id(message_id) elif len(name_) == 2: message_id_str, signal_name = name_ can_id = None match = v4c.CAN_DATA_FRAME_PATTERN.search(message_id_str) if match is None: message_id = message_id_str else: message_id = int(match.group("id")) if isinstance(message_id, str): frame = db.frame_by_name(message_id) else: frame = db.frame_by_id(message_id) else: frame = None for msg in db: for signal in msg: if signal.name == name: frame = msg can_id = None signal_name = name if frame is None: raise MdfException(f"Could not find signal {name} in {database}") for signal in frame.signals: if signal.name == signal_name: break else: raise MdfException(f'Signal "{signal_name}" not found in message "{frame.name}" of "{database}"') test_ids: Collection[int] if can_id is None: index = None for _can_id, messages in self.bus_logging_map["CAN"].items(): if is_j1939: test_ids = [ canmatrix.ArbitrationId(id_, extended=True).pgn for id_ in self.bus_logging_map["CAN"][_can_id] ] id_ = frame.arbitration_id.pgn else: id_ = frame.arbitration_id.id test_ids = self.bus_logging_map["CAN"][_can_id] if id_ in test_ids: if is_j1939: for id__, idx in self.bus_logging_map["CAN"][_can_id].items(): if canmatrix.ArbitrationId(id__, extended=True).pgn == id_: index = idx break else: index = self.bus_logging_map["CAN"][_can_id][frame.arbitration_id.id] if index is not None: break else: raise MdfException( f'Message "{frame.name}" (ID={hex(frame.arbitration_id.id)}) not found in the measurement' ) else: if can_id in self.bus_logging_map["CAN"]: if is_j1939: test_ids = [ canmatrix.ArbitrationId(id_, extended=True).pgn for id_ in self.bus_logging_map["CAN"][can_id] ] id_ = frame.arbitration_id.pgn else: id_ = frame.arbitration_id.id test_ids = self.bus_logging_map["CAN"][can_id] if id_ in test_ids: if is_j1939: for id__, idx in self.bus_logging_map["CAN"][can_id].items(): if canmatrix.ArbitrationId(id__, extended=True).pgn == id_: index = idx break else: index = self.bus_logging_map["CAN"][can_id][frame.arbitration_id.id] else: raise MdfException( f'Message "{frame.name}" (ID={hex(frame.arbitration_id.id)}) not found in the measurement' ) else: raise MdfException(f'No logging from "{can_id}" was found in the measurement') can_ids = self.get( "CAN_DataFrame.ID", group=index, ignore_invalidation_bits=ignore_invalidation_bits, data=data, ) can_ids.samples = can_ids.samples.astype("> 8 ps = tmp_pgn & 0xFF pf = (can_ids.samples >> 16) & 0xFF _pgn = tmp_pgn & 0x3FF00 can_ids.samples = where(pf >= 240, _pgn + ps, _pgn) indexes = argwhere(can_ids.samples == frame.arbitration_id.pgn).ravel() else: indexes = argwhere(can_ids.samples == frame.arbitration_id.id).ravel() payload = payload[indexes] t = can_ids.timestamps[indexes].copy() if can_ids.invalidation_bits is not None: invalidation_bits = can_ids.invalidation_bits[indexes] else: invalidation_bits = None if not ignore_invalidation_bits and invalidation_bits is not None: payload = payload[nonzero(~invalidation_bits)[0]] t = t[nonzero(~invalidation_bits)[0]] extracted_signals = bus_logging_utils.extract_mux( payload, frame, None, None, t, original_message_id=None, ignore_value2text_conversion=ignore_value2text_conversion, raw=raw, ) comment = signal.comment or "" for entry, signals in extracted_signals.items(): for signal_name, extracted_signal in signals.items(): if signal_name == signal.name: sig = Signal( samples=extracted_signal["samples"], timestamps=extracted_signal["t"], name=signal_name, unit=signal.unit or "", comment=comment, raw=raw, conversion=extracted_signal["conversion"], ) if len(sig): return sig else: raise MdfException(f'No logging from "{signal}" was found in the measurement') raise MdfException(f'No logging from "{signal}" was found in the measurement') def get_lin_signal( self, name: str, database: CanMatrix | str | Path | None = None, ignore_invalidation_bits: bool = False, data: Fragment | None = None, raw: bool = False, ignore_value2text_conversion: bool = True, ) -> Signal: """Get LIN message signal. You can specify an external LIN database path or a canmatrix database object that has already been loaded from a file. The signal name can be specified in the following ways: * ``LIN_Frame_.`` - Example: LIN_Frame_218.FL_WheelSpeed * ``.`` - Example: Wheels.FL_WheelSpeed * ```` - Example: FL_WheelSpeed .. versionadded:: 6.0.0 Parameters ---------- name : str Signal name. database : str | path-like | CanMatrix, optional Path of external LIN database file (.dbc, .arxml or .ldf) or canmatrix.CanMatrix. ignore_invalidation_bits : bool, default False Option to ignore invalidation bits. data : Fragment, optional Data bytes as a Fragment. raw : bool, default False Return channel samples without applying the conversion rule. ignore_value2text_conversion : bool, default True Return channel samples without values that have a description in .dbc, .arxml or .ldf file. Returns ------- sig : Signal Signal object with the physical values. """ if database is None: return self.get(name) if isinstance(database, (str, Path)): database_path = Path(database) if database_path.suffix.lower() not in (".arxml", ".dbc", ".ldf"): message = f'Expected .dbc, .arxml or .ldf file as LIN channel attachment but got "{database_path}"' logger.exception(message) raise MdfException(message) else: db_string = database_path.read_bytes() md5_sum = md5(db_string).digest() if md5_sum in self._external_dbc_cache: db = self._external_dbc_cache[md5_sum] else: contents = None if database_path.suffix.lower() == ".ldf" else db_string db = load_can_database(database_path, contents=contents) if db is None: raise MdfException("failed to load database") else: db = database name_ = name.split(".") if len(name_) == 2: message_id_str, signal_name = name_ match = v4c.LIN_DATA_FRAME_PATTERN.search(message_id_str) message_id: str | int if match is None: message_id = message_id_str else: message_id = int(match.group("id")) if isinstance(message_id, str): frame = db.frame_by_name(message_id) else: frame = db.frame_by_id(message_id) else: frame = None for msg in db: for signal in msg: if signal.name == name: frame = msg signal_name = name if frame is None: raise MdfException(f"Could not find signal {name} in {database}") for signal in frame.signals: if signal.name == signal_name: break else: raise MdfException(f'Signal "{signal_name}" not found in message "{frame.name}" of "{database}"') id_ = frame.arbitration_id.id if id_ in self.bus_logging_map["LIN"]: index = self.bus_logging_map["LIN"][id_] else: raise MdfException( f'Message "{frame.name}" (ID={hex(frame.arbitration_id.id)}) not found in the measurement' ) can_ids = self.get( "LIN_Frame.ID", group=index, ignore_invalidation_bits=ignore_invalidation_bits, data=data, ) can_ids.samples = can_ids.samples.astype(" dict[str, object]: """Get MDF information as a dict. Examples -------- >>> mdf = MDF('test.mdf') >>> mdf.info() """ info: dict[str, object] = { "version": self.version, "program": self.identification.program_identification.decode("utf-8").strip(" \0\n\r\t"), "comment": self.header.comment, } info["groups"] = len(self.groups) for i, gp in enumerate(self.groups): inf: dict[str, object] = {} info[f"group {i}"] = inf inf["cycles"] = gp.channel_group.cycles_nr inf["comment"] = gp.channel_group.comment inf["channels count"] = len(gp.channels) for j, channel in enumerate(gp.channels): name = channel.name ch_type = v4c.CHANNEL_TYPE_TO_DESCRIPTION[channel.channel_type] inf[f"channel {j}"] = f'name="{name}" type={ch_type}' return info def _extract_can_logging( self, output_file: "MDF4", dbc_files: Iterable[DbcFileType], ignore_value2text_conversion: bool = True, prefix: str = "", progress: Callable[[int, int], None] | Any | None = None, ) -> "MDF4": out = output_file max_flags: list[list[list[bool]]] = [] valid_dbc_files: list[tuple[CanMatrix, StrPath, int]] = [] unique_name = UniqueDB() for dbc_name, bus_channel in dbc_files: if isinstance(dbc_name, CanMatrix): valid_dbc_files.append( ( dbc_name, unique_name.get_unique_name("UserProvidedCanMatrix"), bus_channel, ) ) else: dbc = load_can_database(Path(dbc_name)) if dbc is None: continue else: valid_dbc_files.append((dbc, dbc_name, bus_channel)) count = sum( 1 for group in self.groups if group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT and group.channel_group.acq_source and group.channel_group.acq_source.bus_type == v4c.BUS_TYPE_CAN ) count *= len(valid_dbc_files) if progress is not None: if callable(progress): progress(0, count) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(count) if progress.stop: raise Terminated cntr = 0 total_unique_ids: set[tuple[int, bool]] = set() found_ids: defaultdict[StrPath, set[tuple[tuple[int, int, bool], str]]] = defaultdict(set) not_found_ids: defaultdict[StrPath, list[tuple[tuple[int, bool] | int, str]]] = defaultdict(list) unknown_ids: defaultdict[int | tuple[int, bool], list[bool]] = defaultdict(list) for dbc, dbc_name, bus_channel in valid_dbc_files: messages = {(message.arbitration_id.id, message.arbitration_id.extended): message for message in dbc} global_is_j1939 = dbc.attributes.get("ProtocolType", "").lower() == "j1939" not_extended = [msg for msg in dbc if not msg.arbitration_id.extended] if global_is_j1939 and not_extended: logger.warning( f"Not all j1939 messages in <{dbc_name}> seem to use extended addressing. Disabling global j1939 flag..." ) for msg in not_extended: logger.warning(f" {msg} with id {msg.arbitration_id}") global_is_j1939 = False # Relax req on j1939 adressing j1939_messages = { ( message.arbitration_id.pgn, message.arbitration_id.j1939_source, ): message for message in dbc if message.is_j1939 or global_is_j1939 } current_not_found = { ( ( (message.arbitration_id.id, message.arbitration_id.extended) if not message.is_j1939 and not global_is_j1939 else message.arbitration_id.pgn ), message.name, ) for msg_id, message in messages.items() } msg_map: dict[tuple[int | None, int | None, bool, int | None, str | None, int, int], int] = {} for i, group in enumerate(self.groups): if ( not group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT or (group.channel_group.acq_source and group.channel_group.acq_source.bus_type != v4c.BUS_TYPE_CAN) or not "CAN_DataFrame" in [ch.name for ch in group.channels] ): continue self._prepare_record(group) data = self._load_data(group, optimize_read=False) for fragment in data: self._set_temporary_master(None) self._set_temporary_master(self.get_master(i, data=fragment, one_piece=True)) bus_ids = self.get( "CAN_DataFrame.BusChannel", group=i, data=fragment, ).samples.astype("> 31).samples msg_ids &= 0x1FFFFFFF data_bytes = self.get( "CAN_DataFrame.DataBytes", group=i, data=fragment, ).samples buses = np.unique(bus_ids) for bus in buses: if bus_channel and bus != bus_channel: continue idx = np.argwhere(bus_ids == bus).ravel() bus_t = msg_ids.timestamps[idx] bus_msg_ids = msg_ids.samples[idx] bus_msg_ide = msg_ide[idx] bus_data_bytes = data_bytes[idx] tmp_pgns = bus_msg_ids >> 8 pss = tmp_pgns & 0xFF pfs = (bus_msg_ids >> 16) & 0xFF _pgns = tmp_pgns & 0x3FF00 j1939_msg_pgns = np.where(pfs >= 240, _pgns + pss, _pgns) j9193_msg_sa = bus_msg_ids & 0xFF unique_ids = set( zip( typing.cast(list[int], bus_msg_ids.tolist()), typing.cast(list[bool], bus_msg_ide.tolist()), strict=False, ) ) total_unique_ids = total_unique_ids | set(unique_ids) for msg_id, is_extended in sorted(unique_ids): message = messages.get((msg_id, is_extended), None) if message is None: tmp_pgn = msg_id >> 8 ps = tmp_pgn & 0xFF pf = (msg_id >> 16) & 0xFF _pgn = tmp_pgn & 0x3FF00 msg_pgn = _pgn + ps if pf >= 240 else _pgn for (_pgn, _sa), _msg in j1939_messages.items(): if _pgn == msg_pgn: message = _msg break else: unknown_ids[msg_id].append(True) continue is_j1939 = message.is_j1939 or global_is_j1939 if is_j1939: source_address = msg_id & 0xFF pgn_number = message.arbitration_id.pgn key = (pgn_number, source_address, True) found_ids[dbc_name].add((key, message.name)) try: current_not_found.remove((pgn_number, message.name)) except KeyError: pass else: key = msg_id, bool(is_extended), False found_ids[dbc_name].add((key, message.name)) try: current_not_found.remove(((msg_id, is_extended), message.name)) except KeyError: pass unknown_ids[(msg_id, is_extended)].append(False) if is_j1939: idx = np.argwhere( (j1939_msg_pgns == pgn_number) & (j9193_msg_sa == source_address) ).ravel() else: idx = np.argwhere((bus_msg_ids == msg_id) & (bus_msg_ide == is_extended)).ravel() payload = bus_data_bytes[idx] t = bus_t[idx] try: extracted_signals = bus_logging_utils.extract_mux( payload, message, msg_id, bus, t, original_message_id=source_address if is_j1939 else None, ignore_value2text_conversion=ignore_value2text_conversion, is_j1939=is_j1939, is_extended=is_extended, raw=True, ) except: print(format_exc()) raise for entry, signals in extracted_signals.items(): if len(next(iter(signals.values()))["samples"]) == 0: continue if entry not in msg_map: sigs: list[Signal] = [] index = len(out.groups) msg_map[entry] = index for name_, signal in signals.items(): signal_name = f"{prefix}{signal['name']}" sig = Signal( samples=signal["samples"], timestamps=signal["t"], name=signal_name, comment=signal["comment"], unit=signal["unit"], invalidation_bits=signal["invalidation_bits"], display_names={ f"CAN{bus}.{message.name}.{signal_name}": "bus", f"{message.name}.{signal_name}": "message", }, raw=True, conversion=signal["conversion"], ) sigs.append(sig) if is_j1939: if prefix: comment = f"{prefix}: CAN{bus} ID=0x{msg_id:X} {message} PGN=0x{pgn_number:X} SA=0x{source_address:X}" else: comment = f"CAN{bus} ID=0x{msg_id:X} {message} PGN=0x{pgn_number:X} SA=0x{source_address:X}" acq_name = f"SourceAddress = 0x{source_address}" else: if prefix: acq_name = ( f"{prefix}: CAN{bus} message ID=0x{msg_id:X} EXT={bool(is_extended)}" ) comment = f'{prefix}: CAN{bus} - message "{message}" 0x{msg_id:X} EXT={bool(is_extended)}' else: acq_name = f"CAN{bus} message ID=0x{msg_id:X} EXT={bool(is_extended)}" comment = ( f"CAN{bus} - message {message} 0x{msg_id:X} EXT={bool(is_extended)}" ) acq_source = Source( name=acq_name, path=f"CAN{int(bus)}.CAN_DataFrame.ID=0x{message.arbitration_id.id:X} EXT={bool(is_extended)}", comment=f"""\ CAN{bus} data frame 0x{message.arbitration_id.id:X} EXT={bool(is_extended)} - {message.name} {int(bus)} """, source_type=v4c.SOURCE_BUS, bus_type=v4c.BUS_TYPE_CAN, ) for sig in sigs: sig.source = acq_source cg_nr = out.append( sigs, acq_name=acq_name, acq_source=acq_source, comment=comment, common_timebase=True, ) out.groups[cg_nr].channel_group.flags = v4c.FLAG_CG_BUS_EVENT if is_j1939: max_flags.append([[False]]) for ch_index, sig in enumerate(sigs, 1): max_flags[cg_nr].append( [ ( bool(np.all(sig.invalidation_bits)) if sig.invalidation_bits is not None else False ) ] ) else: max_flags.append([[False]] * (len(sigs) + 1)) else: index = msg_map[entry] signal_samples: list[tuple[NDArray[Any], NDArray[np.bool] | None]] = [] for name_, signal in signals.items(): signal_samples.append( ( signal["samples"], signal["invalidation_bits"], ) ) t = signal["t"] if is_j1939: for ch_index, sig_sample in enumerate(signal_samples, 1): max_flags[index][ch_index].append( bool(np.all(sig_sample[1])) if sig_sample[1] is not None else False ) signal_samples.insert(0, (t, None)) out.extend(index, signal_samples) self._set_temporary_master(None) cntr += 1 if progress is not None: if callable(progress): progress(cntr, count) else: progress.signals.setValue.emit(cntr) if progress.stop: raise Terminated if current_not_found: not_found_ids[dbc_name] = list(current_not_found) unknown_id_set = {msg_id for msg_id, not_found in unknown_ids.items() if all(not_found)} self.last_call_info["CAN"] = { "dbc_files": dbc_files, "total_unique_ids": total_unique_ids, "unknown_id_count": len(unknown_id_set), "not_found_ids": not_found_ids, "found_ids": found_ids, "unknown_ids": unknown_id_set, "max_flags": max_flags, } if not out.groups: logger.warning(f'No CAN signals could be extracted from "{self.name}". The output file will be empty.') return out def _extract_lin_logging( self, output_file: "MDF4", dbc_files: Iterable[DbcFileType], ignore_value2text_conversion: bool = True, prefix: str = "", progress: Callable[[int, int], None] | Any | None = None, ) -> "MDF4": out = output_file valid_dbc_files: list[tuple[CanMatrix, StrPath, int]] = [] unique_name = UniqueDB() for dbc_name, bus_channel in dbc_files: if isinstance(dbc_name, CanMatrix): valid_dbc_files.append( ( dbc_name, unique_name.get_unique_name("UserProvidedCanMatrix"), bus_channel, ) ) else: dbc = load_can_database(Path(dbc_name)) if dbc is None: continue else: valid_dbc_files.append((dbc, dbc_name, bus_channel)) count = sum( 1 for group in self.groups if group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT and group.channel_group.acq_source and group.channel_group.acq_source.bus_type == v4c.BUS_TYPE_LIN ) count *= len(valid_dbc_files) if progress is not None: if callable(progress): progress(0, count) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(count) if progress.stop: raise Terminated cntr = 0 total_unique_ids: set[tuple[int, ...]] = set() found_ids: defaultdict[StrPath, set[tuple[tuple[int, bool, bool], str]]] = defaultdict(set) not_found_ids: defaultdict[StrPath, list[tuple[int, str]]] = defaultdict(list) unknown_ids: defaultdict[int, list[bool]] = defaultdict(list) for dbc, dbc_name, bus_channel in valid_dbc_files: messages = {message.arbitration_id.id: message for message in dbc} current_not_found_ids = {(msg_id, message.name) for msg_id, message in messages.items()} msg_map = {} for i, group in enumerate(self.groups): if ( not group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT or (group.channel_group.acq_source and group.channel_group.acq_source.bus_type != v4c.BUS_TYPE_LIN) or not "LIN_Frame" in [ch.name for ch in group.channels] ): continue self._prepare_record(group) data = self._load_data(group, optimize_read=False) for fragment in data: self._set_temporary_master(None) self._set_temporary_master(self.get_master(i, data=fragment, one_piece=True)) msg_ids = self.get("LIN_Frame.ID", group=i, data=fragment).astype(" LIN{bus} data frame 0x{message.arbitration_id.id:X} - {message.name} {int(bus)} """, source_type=v4c.SOURCE_BUS, bus_type=v4c.BUS_TYPE_LIN, ) for sig in sigs: sig.source = acq_source cg_nr = out.append( sigs, acq_name=acq_name, acq_source=acq_source, comment=f"from LIN{bus} - message {message} 0x{msg_id:X}", common_timebase=True, ) out.groups[cg_nr].channel_group.flags = v4c.FLAG_CG_BUS_EVENT else: index = msg_map[entry] signal_samples: list[tuple[NDArray[Any], NDArray[np.bool] | None]] = [] for name_, signal in signals.items(): signal_samples.append( ( signal["samples"], signal["invalidation_bits"], ) ) t = signal["t"] signal_samples.insert(0, (t, None)) out.extend(index, signal_samples) self._set_temporary_master(None) cntr += 1 if progress is not None: if callable(progress): progress(cntr, count) else: progress.signals.setValue.emit(cntr) if progress.stop: raise Terminated if current_not_found_ids: not_found_ids[dbc_name] = list(current_not_found_ids) unknown_id_set = {msg_id for msg_id, not_found in unknown_ids.items() if all(not_found)} self.last_call_info["LIN"] = { "dbc_files": dbc_files, "total_unique_ids": total_unique_ids, "unknown_id_count": len(unknown_id_set), "not_found_ids": not_found_ids, "found_ids": found_ids, "unknown_ids": unknown_id_set, } if not out.groups: logger.warning(f'No LIN signals could be extracted from "{self.name}". The output file will be empty.') return out @property def start_time(self) -> datetime: """Getter and setter of the measurement start timestamp. Returns ------- timestamp : datetime.datetime Start timestamp. """ return self.header.start_time @start_time.setter def start_time(self, timestamp: datetime) -> None: self.header.start_time = timestamp def save( self, dst: FileLike | StrPath, overwrite: bool = False, compression: CompressionType = v4c.CompressionAlgorithm.NO_COMPRESSION, progress: Any | None = None, add_history_block: bool = True, ) -> Path: """Save `MDF` to `dst`. If `overwrite` is True, then the destination file is overwritten, otherwise the file name is appended with '.', where '' is the first counter that produces a new file name that does not already exist in the filesystem. Parameters ---------- dst : str | path-like | file-like Destination file name. overwrite : bool, default False Overwrite flag. compression : int, default 0 Use compressed data blocks; valid since MDF version 4.10. * 0 - no compression * 1 - deflate (slower, but produces smaller files) * 2 - transposition + deflate (slowest, but produces the smallest files) add_history_block : bool, default True Option to add file history block. Returns ------- output_file : pathlib.Path Path to saved file. """ if is_file_like(dst): dst_ = dst file_like = True if hasattr(dst, "name"): dst = Path(dst.name) else: dst = Path("__file_like.mf4") dst_.seek(0) suffix = ".mf4" else: file_like = False suffix = Path(dst).suffix.lower() dst = Path(dst).with_suffix(".mf4") destination_dir = dst.parent destination_dir.mkdir(parents=True, exist_ok=True) if overwrite is False: if dst.is_file(): cntr = 0 while True: name = dst.with_suffix(f".{cntr}.mf4") if not name.exists(): break else: cntr += 1 message = ( f'Destination file "{dst}" already exists and "overwrite" is False. Saving MDF file as "{name}"' ) logger.warning(message) dst = name if dst == self.name: destination = dst.with_suffix(".savetemp") else: destination = dst dst_ = open(destination, "wb+") if not self.file_history: comment = "created" else: comment = "updated" if add_history_block: fh = FileHistory() fh.comment = f""" {comment} {tool.__tool__} {tool.__vendor__} {tool.__version__} """ self.file_history.append(fh) cg_map = {} try: defined_texts: dict[bytes | str, int] = {"": 0, b"": 0} cc_map: dict[bytes | int, int] = {} si_map: dict[bytes | int, int] = {} groups_nr = len(self.groups) write = dst_.write tell = dst_.tell seek = dst_.seek blocks: list[bytes | SupportsBytes] = [] write(bytes(self.identification)) self.header.to_blocks(dst_.tell(), blocks) for block in blocks: write(bytes(block)) original_data_addresses = [] if self.version < "4.30": if compression > v4c.CompressionAlgorithm.TRANSPOSED_DEFLATE: zip_type = v4c.FLAG_DZ_TRANSPOSED_DEFLATE elif compression == v4c.CompressionAlgorithm.DEFLATE: zip_type = v4c.FLAG_DZ_DEFLATE else: zip_type = v4c.FLAG_DZ_TRANSPOSED_DEFLATE else: match compression: case v4c.CompressionAlgorithm.DEFLATE: zip_type = v4c.FLAG_DZ_DEFLATE case v4c.CompressionAlgorithm.TRANSPOSED_DEFLATE: zip_type = v4c.FLAG_DZ_TRANSPOSED_DEFLATE case v4c.CompressionAlgorithm.LZ4: zip_type = v4c.FLAG_DZ_LZ4 case v4c.CompressionAlgorithm.TRANSPOSED_LZ4: zip_type = v4c.FLAG_DZ_TRANSPOSED_LZ4 case v4c.CompressionAlgorithm.ZSTD: zip_type = v4c.FLAG_DZ_ZSTD case v4c.CompressionAlgorithm.TRANSPOSED_ZSTD: zip_type = v4c.FLAG_DZ_TRANSPOSED_ZSTD # write DataBlocks first for gp_nr, gp in enumerate(self.groups): original_data_addresses.append(gp.data_group.data_block_addr) if gp.channel_group.flags & v4c.FLAG_CG_VLSD: continue address = tell() total_size = ( gp.channel_group.samples_byte_nr + gp.channel_group.invalidation_bytes_nr ) * gp.channel_group.cycles_nr if total_size: if self._write_fragment_size: samples_size = gp.channel_group.samples_byte_nr + gp.channel_group.invalidation_bytes_nr if samples_size: split_size = self._write_fragment_size // samples_size split_size *= samples_size if split_size == 0: split_size = samples_size chunks = float(total_size) / split_size chunks = ceil(chunks) self._read_fragment_size = split_size else: chunks = 1 else: chunks = 1 data = self._load_data(gp) if chunks == 1: fragment = next(data) data_, inval_ = fragment.data, fragment.invalidation_data if self.version >= "4.20" and gp.uses_ld: if compression: if gp.channel_group.samples_byte_nr > 1: current_zip_type = zip_type if compression == 1: param = 0 else: param = gp.channel_group.samples_byte_nr else: current_zip_type = v4c.FLAG_DZ_DEFLATE param = 0 dz_kwargs: DataZippedBlockKwargs = { "data": data_, "zip_type": current_zip_type, "param": param, "original_type": b"DV", } data_block: DataZippedBlock | DataBlock = DataZippedBlock(**dz_kwargs) else: data_block = DataBlock(data=data_, type="DV") write(bytes(data_block)) data_address = address align = data_block.block_len % 8 if align: write(b"\0" * (8 - align)) if inval_ is not None: inval_address = address = tell() if compression: if compression == 1: param = 0 else: param = gp.channel_group.invalidation_bytes_nr dz_kwargs = { "data": inval_, "zip_type": zip_type, "param": param, "original_type": b"DI", } inval_block: DataZippedBlock | DataBlock = DataZippedBlock(**dz_kwargs) else: inval_block = DataBlock(data=inval_, type="DI") write(bytes(inval_block)) align = inval_block.block_len % 8 if align: write(b"\0" * (8 - align)) address = tell() ld_kwargs: ListDataKwargs = { # type: ignore[typeddict-unknown-key] "flags": v4c.FLAG_LD_EQUAL_LENGHT, "data_block_nr": 1, "data_block_len": gp.channel_group.cycles_nr, "data_block_addr_0": data_address, } if inval_: ld_kwargs["flags"] |= v4c.FLAG_LD_INVALIDATION_PRESENT ld_kwargs["invalidation_bits_addr_0"] = inval_address # type: ignore[typeddict-unknown-key] ld_block = ListData(**ld_kwargs) write(bytes(ld_block)) align = ld_block.block_len % 8 if align: write(b"\0" * (8 - align)) if gp.channel_group.cycles_nr: gp.data_group.data_block_addr = address else: gp.data_group.data_block_addr = 0 else: if compression and self.version >= "4.10": if compression == 1: param = 0 else: param = gp.channel_group.samples_byte_nr + gp.channel_group.invalidation_bytes_nr dz_kwargs = { "data": data_, "zip_type": zip_type, "param": param, } data_block = DataZippedBlock(**dz_kwargs) else: data_block = DataBlock(data=data_) write(bytes(data_block)) align = data_block.block_len % 8 if align: write(b"\0" * (8 - align)) if gp.channel_group.cycles_nr: gp.data_group.data_block_addr = address else: gp.data_group.data_block_addr = 0 else: if self.version >= "4.20" and gp.uses_ld: dv_addr = [] di_addr = [] block_size = 0 for i, fragment in enumerate(data): data_, inval_ = fragment.data, fragment.invalidation_data if i == 0: block_size = len(data_) if compression: if compression == 1: param = 0 else: param = gp.channel_group.samples_byte_nr dz_kwargs = { "data": data_, "zip_type": zip_type, "param": param, "original_type": b"DV", } data_block = DataZippedBlock(**dz_kwargs) else: data_block = DataBlock(data=data_, type="DV") dv_addr.append(tell()) write(bytes(data_block)) align = data_block.block_len % 8 if align: write(b"\0" * (8 - align)) if inval_ is not None: if compression: if compression == 1: param = 0 else: param = gp.channel_group.invalidation_bytes_nr dz_kwargs = { "data": inval_, "zip_type": zip_type, "param": param, "original_type": b"DI", } inval_block = DataZippedBlock(**dz_kwargs) else: inval_block = DataBlock(data=inval_, type="DI") di_addr.append(tell()) write(bytes(inval_block)) align = inval_block.block_len % 8 if align: write(b"\0" * (8 - align)) address = tell() ld_kwargs = { "flags": v4c.FLAG_LD_EQUAL_LENGHT, "data_block_nr": len(dv_addr), "data_block_len": block_size // gp.channel_group.samples_byte_nr, } for i, addr in enumerate(dv_addr): ld_kwargs[f"data_block_addr_{i}"] = addr # type: ignore[literal-required] if di_addr: ld_kwargs["flags"] |= v4c.FLAG_LD_INVALIDATION_PRESENT for i, addr in enumerate(di_addr): ld_kwargs[f"invalidation_bits_addr_{i}"] = addr # type: ignore[literal-required] ld_block = ListData(**ld_kwargs) write(bytes(ld_block)) align = ld_block.block_len % 8 if align: write(b"\0" * (8 - align)) if gp.channel_group.cycles_nr: gp.data_group.data_block_addr = address else: gp.data_group.data_block_addr = 0 else: hl_kwargs: HeaderListKwargs = { "flags": v4c.FLAG_DL_EQUAL_LENGHT, "zip_type": zip_type, } hl_block = HeaderList(**hl_kwargs) dl_kwargs: DataListKwargs = { "flags": v4c.FLAG_DL_EQUAL_LENGHT, "links_nr": chunks + 1, "data_block_nr": chunks, "data_block_len": split_size, } dl_block = DataList(**dl_kwargs) for i, fragment in enumerate(data): data_ = fragment.data if compression and self.version >= "4.10": if compression == 1: zip_type = v4c.FLAG_DZ_DEFLATE else: zip_type = v4c.FLAG_DZ_TRANSPOSED_DEFLATE if compression == 1: param = 0 else: param = ( gp.channel_group.samples_byte_nr + gp.channel_group.invalidation_bytes_nr ) dz_kwargs = { "data": data_, "zip_type": zip_type, "param": param, } block = DataZippedBlock(**dz_kwargs) else: block = DataBlock(data=data_) address = tell() block.address = address write(bytes(block)) align = block.block_len % 8 if align: write(b"\0" * (8 - align)) dl_block[f"data_block_addr{i}"] = address address = tell() dl_block.address = address write(bytes(dl_block)) if compression and self.version != "4.00": hl_block.first_dl_addr = address address = tell() hl_block.address = address write(bytes(hl_block)) gp.data_group.data_block_addr = address else: gp.data_group.data_block_addr = 0 if progress is not None: progress.signals.setValue.emit(int(50 * (gp_nr + 1) / groups_nr)) if progress.stop: dst_.close() self.close() raise Terminated address = tell() blocks = [] # file history blocks for fh in self.file_history: address = fh.to_blocks(address, blocks, defined_texts) for i, fh in enumerate(self.file_history[:-1]): fh.next_fh_addr = self.file_history[i + 1].address self.file_history[-1].next_fh_addr = 0 # data groups gp_rec_ids = [] valid_data_groups = [] for gp in self.groups: if gp.channel_group.flags & v4c.FLAG_CG_VLSD: continue valid_data_groups.append(gp.data_group) gp_rec_ids.append(gp.data_group.record_id_len) address = gp.data_group.to_blocks(address, blocks, defined_texts) if valid_data_groups: for i, dg in enumerate(valid_data_groups[:-1]): addr_ = valid_data_groups[i + 1].address dg.next_dg_addr = addr_ valid_data_groups[-1].next_dg_addr = 0 # go through each data group and append the rest of the blocks for i, gp in enumerate(self.groups): channels = gp.channels for j, channel in enumerate(channels): if channel.attachment is not None: channel.attachment_addr = self.attachments[channel.attachment].address elif channel.attachment_nr: channel.attachment_addr = 0 address = channel.to_blocks(address, blocks, defined_texts, cc_map, si_map) if channel.channel_type == v4c.CHANNEL_TYPE_SYNC: if channel.attachment is not None: channel.data_block_addr = self.attachments[channel.attachment].address else: sdata = self._load_signal_data(group=gp, index=j) if sdata: split_size = self._write_fragment_size if self._write_fragment_size: chunks = float(len(sdata)) / split_size chunks = ceil(chunks) else: chunks = 1 if chunks == 1: if compression and self.version > "4.00": signal_data: DataZippedBlock | DataBlock = DataZippedBlock( data=sdata, zip_type=v4c.FLAG_DZ_DEFLATE, original_type=b"SD", ) signal_data.address = address address += signal_data.block_len blocks.append(signal_data) align = signal_data.block_len % 8 if align: blocks.append(b"\0" * (8 - align)) address += 8 - align else: signal_data = DataBlock(data=sdata, type="SD") signal_data.address = address address += signal_data.block_len blocks.append(signal_data) align = signal_data.block_len % 8 if align: blocks.append(b"\0" * (8 - align)) address += 8 - align channel.data_block_addr = signal_data.address else: dl_kwargs = { "flags": v4c.FLAG_DL_EQUAL_LENGHT, "links_nr": chunks + 1, "data_block_nr": chunks, "data_block_len": self._write_fragment_size, } dl_block = DataList(**dl_kwargs) for k in range(chunks): data_ = sdata[k * split_size : (k + 1) * split_size] if compression and self.version > "4.00": zip_type = v4c.FLAG_DZ_DEFLATE param = 0 dz_kwargs = { "data": data_, "zip_type": zip_type, "param": param, "original_type": b"SD", } block = DataZippedBlock(**dz_kwargs) else: block = DataBlock(data=data_, type="SD") blocks.append(block) block.address = address address += block.block_len align = block.block_len % 8 if align: blocks.append(b"\0" * (8 - align)) address += 8 - align dl_block[f"data_block_addr{k}"] = block.address dl_block.address = address blocks.append(dl_block) address += dl_block.block_len if compression and self.version > "4.00": hl_kwargs = { "flags": v4c.FLAG_DL_EQUAL_LENGHT, "zip_type": v4c.FLAG_DZ_DEFLATE, "first_dl_addr": dl_block.address, } hl_block = HeaderList(**hl_kwargs) hl_block.address = address address += hl_block.block_len blocks.append(hl_block) channel.data_block_addr = hl_block.address else: channel.data_block_addr = dl_block.address else: channel.data_block_addr = 0 dep_list = gp.channel_dependencies[j] if dep_list: if all(isinstance(dep, ChannelArrayBlock) for dep in dep_list): dep_list = typing.cast(list[ChannelArrayBlock], dep_list) for dep in dep_list: dep.address = address address += dep.block_len blocks.append(dep) for k, dep in enumerate(dep_list[:-1]): dep.composition_addr = dep_list[k + 1].address dep_list[-1].composition_addr = 0 channel.component_addr = dep_list[0].address else: dep_list = typing.cast(list[tuple[int, int]], dep_list) index = dep_list[0][1] addr_ = gp.channels[index].address group_channels = gp.channels if group_channels: for j, channel in enumerate(group_channels[:-1]): channel.next_ch_addr = group_channels[j + 1].address group_channels[-1].next_ch_addr = 0 # channel dependencies j = len(channels) - 1 while j >= 0: dep_list = gp.channel_dependencies[j] if dep_list and all(isinstance(dep, tuple) for dep in dep_list): dep_list = typing.cast(list[tuple[int, int]], dep_list) index = dep_list[0][1] channels[j].component_addr = channels[index].address index = dep_list[-1][1] channels[j].next_ch_addr = channels[index].next_ch_addr channels[index].next_ch_addr = 0 for _, ch_nr in dep_list: channels[ch_nr].source_addr = 0 j -= 1 # channel group if gp.channel_group.flags & v4c.FLAG_CG_VLSD: continue gp.channel_group.first_sample_reduction_addr = 0 if channels: gp.channel_group.first_ch_addr = gp.channels[0].address else: gp.channel_group.first_ch_addr = 0 gp.channel_group.next_cg_addr = 0 address = gp.channel_group.to_blocks(address, blocks, defined_texts, si_map) gp.data_group.first_cg_addr = gp.channel_group.address cg_map[i] = gp.channel_group.address if progress is not None: progress.signals.setValue.emit(int(50 * (i + 1) / groups_nr) + 25) if progress.stop: dst_.close() self.close() raise Terminated for gp in self.groups: for dep_list in gp.channel_dependencies: if dep_list: if all(isinstance(dep, ChannelArrayBlock) for dep in dep_list): dep_list = typing.cast(list[ChannelArrayBlock], dep_list) for dep in dep_list: for i, (gp_nr, ch_nr) in enumerate(filter(None, dep.dynamic_size_channels)): grp = self.groups[gp_nr] ch = grp.channels[ch_nr] dep[f"dynamic_size_{i}_dg_addr"] = grp.data_group.address dep[f"dynamic_size_{i}_cg_addr"] = grp.channel_group.address dep[f"dynamic_size_{i}_ch_addr"] = ch.address for i, (gp_nr, ch_nr) in enumerate(filter(None, dep.input_quantity_channels)): grp = self.groups[gp_nr] ch = grp.channels[ch_nr] dep[f"input_quantity_{i}_dg_addr"] = grp.data_group.address dep[f"input_quantity_{i}_cg_addr"] = grp.channel_group.address dep[f"input_quantity_{i}_ch_addr"] = ch.address for i, conversion in enumerate(dep.axis_conversions): if conversion: address = conversion.to_blocks(address, blocks, defined_texts, cc_map) dep[f"axis_conversion_{i}"] = conversion.address else: dep[f"axis_conversion_{i}"] = 0 if dep.output_quantity_channel: gp_nr, ch_nr = dep.output_quantity_channel grp = self.groups[gp_nr] ch = grp.channels[ch_nr] dep.output_quantity_dg_addr = grp.data_group.address dep.output_quantity_cg_addr = grp.channel_group.address dep.output_quantity_ch_addr = ch.address if dep.comparison_quantity_channel: gp_nr, ch_nr = dep.comparison_quantity_channel grp = self.groups[gp_nr] ch = grp.channels[ch_nr] dep.comparison_quantity_dg_addr = grp.data_group.address dep.comparison_quantity_cg_addr = grp.channel_group.address dep.comparison_quantity_ch_addr = ch.address for i, (gp_nr, ch_nr) in enumerate(filter(None, dep.axis_channels)): grp = self.groups[gp_nr] ch = grp.channels[ch_nr] dep[f"scale_axis_{i}_dg_addr"] = grp.data_group.address dep[f"scale_axis_{i}_cg_addr"] = grp.channel_group.address dep[f"scale_axis_{i}_ch_addr"] = ch.address position = tell() for gp in self.groups: gp.data_group.record_id_len = 0 cg_master_index = gp.channel_group.cg_master_index if cg_master_index is not None: gp.channel_group.cg_master_addr = cg_map[cg_master_index] seek(gp.channel_group.address) write(bytes(gp.channel_group)) seek(position) ev_map = [] if self.events: for event in self.events: for i, ref in enumerate(event.scopes): if isinstance(ref, tuple): dg_cntr, ch_cntr = ref event[f"scope_{i}_addr"] = self.groups[dg_cntr].channels[ch_cntr].address else: dg_cntr = ref event[f"scope_{i}_addr"] = self.groups[dg_cntr].channel_group.address blocks.append(event) ev_map.append(address) event.address = address address += event.block_len if event.name: tx_block = TextBlock(text=event.name) tx_block.address = address blocks.append(tx_block) address += tx_block.block_len event.name_addr = tx_block.address else: event.name_addr = 0 if event.comment: meta = event.comment.startswith("= threshold: progress.signals.setValue.emit(75 + count) count += 1 threshold += blocks_nr / 25 else: for block in blocks: write(bytes(block)) for gp, rec_id in zip(self.groups, gp_rec_ids, strict=False): gp.data_group.record_id_len = rec_id if valid_data_groups: addr_ = valid_data_groups[0].address self.header.first_dg_addr = addr_ else: self.header.first_dg_addr = 0 self.header.file_history_addr = self.file_history[0].address if self.attachments: first_attachment = self.attachments[0] addr_ = first_attachment.address self.header.first_attachment_addr = addr_ else: self.header.first_attachment_addr = 0 seek(v4c.IDENTIFICATION_BLOCK_SIZE) write(bytes(self.header)) for orig_addr, gp in zip(original_data_addresses, self.groups, strict=False): gp.data_group.data_block_addr = orig_addr at_map = {value: key for key, value in at_map.items()} for event in self.events: for i in range(event.attachment_nr): key = f"attachment_{i}_addr" addr = typing.cast(int, event[key]) event[key] = at_map[addr] except: if not file_like: dst_.close() raise else: if not file_like: dst_.close() if suffix in (".zip", ".mf4z"): output_fname = dst.with_suffix(suffix) try: zipped_mf4 = ZipFile(output_fname, "w", compression=ZIP_DEFLATED) zipped_mf4.write( str(dst), dst.name, compresslevel=1, ) zipped_mf4.close() os.remove(destination) dst = output_fname except: pass if dst == self.name: self.close() try: Path.unlink(self.name) Path.rename(destination, self.name) except: pass self.groups.clear() del self.header del self.identification self.file_history.clear() self.channels_db.clear() self.masters_db.clear() self.attachments.clear() self._ch_map.clear() self._tempfile = NamedTemporaryFile(dir=self.temporary_folder) self._file = open(self.name, "rb") self._read(self._file) return dst def get_channel_name(self, group: int, index: int) -> str: """Get channel name. Parameters ---------- group : int 0-based group index. index : int 0-based channel index. Returns ------- name : str Found channel name. """ gp_nr, ch_nr = self._validate_channel_selection(None, group, index) return self.groups[gp_nr].channels[ch_nr].name def get_channel_metadata( self, name: str | None = None, group: int | None = None, index: int | None = None, ) -> Channel: gp_nr, ch_nr = self._validate_channel_selection(name, group, index) grp = self.groups[gp_nr] channel = grp.channels[ch_nr] return channel def get_channel_unit( self, name: str | None = None, group: int | None = None, index: int | None = None, ) -> str: """Get channel unit. The channel can be specified in two ways: * Using the first positional argument `name`. * If there are multiple occurrences for this channel, then the `group` and `index` arguments can be used to select a specific group. * If there are multiple occurrences for this channel and either the `group` or `index` arguments is None, then a warning is issued. * Using the group number (keyword argument `group`) and the channel number (keyword argument `index`). Use `info` method for group and channel numbers. Parameters ---------- name : str, optional Name of channel. group : int, optional 0-based group index. index : int, optional 0-based channel index. Returns ------- unit : str Found channel unit. """ gp_nr, ch_nr = self._validate_channel_selection(name, group, index) grp = self.groups[gp_nr] channel = grp.channels[ch_nr] conversion = channel.conversion unit = (conversion and conversion.unit) or channel.unit or "" return unit def get_channel_comment( self, name: str | None = None, group: int | None = None, index: int | None = None, ) -> str: """Get channel comment. The channel can be specified in two ways: * Using the first positional argument `name`. * If there are multiple occurrences for this channel, then the `group` and `index` arguments can be used to select a specific group. * If there are multiple occurrences for this channel and either the `group` or `index` arguments is None, then a warning is issued. * Using the group number (keyword argument `group`) and the channel number (keyword argument `index`). Use `info` method for group and channel numbers. Parameters ---------- name : str, optional Name of channel. group : int, optional 0-based group index. index : int, optional 0-based channel index. Returns ------- comment : str Found channel comment. """ gp_nr, ch_nr = self._validate_channel_selection(name, group, index) grp = self.groups[gp_nr] channel = grp.channels[ch_nr] return extract_xml_comment(channel.comment) def _finalize(self, stream: FileLike | mmap.mmap) -> None: """ Attempt finalization of the file. :return: None """ flags = self.identification.unfinalized_standard_flags blocks, block_groups, addresses = all_blocks_addresses(stream) stream.seek(0, 2) limit = stream.tell() mapped = self._mapped if flags & v4c.FLAG_UNFIN_UPDATE_LAST_DL: for dg_addr in block_groups[b"##DG"]: group = DataGroup(address=dg_addr, stream=stream, mapped=mapped) data_addr = group.data_block_addr if not data_addr: continue stream.seek(data_addr) blk_id = stream.read(4) if blk_id == b"##DT": continue elif blk_id in (b"##DL", b"##HL"): if blk_id == b"##HL": hl = HeaderList(address=data_addr, stream=stream, mapped=mapped) data_addr = hl.first_dl_addr while True: dl = DataList(address=data_addr, stream=stream, mapped=mapped) if not dl.next_dl_addr: break kwargs: DataListKwargs = {} count = dl.links_nr - 1 valid_count = 0 for i in range(count): dt_addr = dl[f"data_block_addr{i}"] if dt_addr: valid_count += 1 kwargs[f"data_block_addr{i}"] = dt_addr # type: ignore[literal-required] else: break starting_address = dl.address next_block_position = bisect.bisect_right(addresses, starting_address) # search for data blocks after the DLBLOCK for j in range(i, count): if next_block_position >= len(addresses): break next_block_address = addresses[next_block_position] next_block_type = blocks[next_block_address] if next_block_type not in {b"##DZ", b"##DT", b"##DV", b"##DI"}: break else: stream.seek(next_block_address + v4c.DZ_INFO_COMMON_OFFSET) if next_block_type == b"##DZ": ( zip_type, param, original_size, zip_size, ) = v4c.DZ_COMMON_INFO_uf(stream.read(v4c.DZ_COMMON_INFO_SIZE)) exceeded = limit - (next_block_address + v4c.DZ_COMMON_SIZE + zip_size) < 0 else: id_string, block_len = COMMON_SHORT_uf(stream.read(v4c.COMMON_SIZE)) original_size = block_len - 24 exceeded = limit - (next_block_address + block_len) < 0 # update the data block size in case all links were NULL before if i == 0 and (dl.flags & v4c.FLAG_DL_EQUAL_LENGHT): kwargs["data_block_len"] = original_size # check if the file limit is exceeded if exceeded: break else: next_block_position += 1 valid_count += 1 kwargs[f"data_block_addr{j}"] = next_block_address # type: ignore[literal-required] kwargs["links_nr"] = valid_count + 1 kwargs["flags"] = dl.flags if dl.flags & v4c.FLAG_DL_EQUAL_LENGHT: kwargs["data_block_len"] = dl.data_block_len else: for i in range(valid_count): kwargs[f"offset_{i}"] = dl[f"offset_{i}"] # type: ignore[literal-required] stream.seek(data_addr) stream.write(bytes(DataList(**kwargs))) self.identification.unfinalized_standard_flags -= v4c.FLAG_UNFIN_UPDATE_LAST_DL if flags & v4c.FLAG_UNFIN_UPDATE_LAST_DT_LENGTH: try: for dg_addr in block_groups[b"##DG"]: group = DataGroup(address=dg_addr, stream=stream, mapped=mapped) data_addr = group.data_block_addr if not data_addr: continue stream.seek(data_addr) blk_id = stream.read(4) if blk_id == b"##DT": blk = DataBlock(address=data_addr, stream=stream, mapped=mapped) elif blk_id == b"##DL": while True: dl = DataList(address=data_addr, stream=stream, mapped=mapped) if not dl.next_dl_addr: break data_addr = typing.cast(int, dl[f"data_block_addr{dl.links_nr - 2}"]) blk = DataBlock(address=data_addr, stream=stream, mapped=mapped) elif blk_id == b"##HL": hl = HeaderList(address=data_addr, stream=stream, mapped=mapped) data_addr = hl.first_dl_addr while True: dl = DataList(address=data_addr, stream=stream, mapped=mapped) if not dl.next_dl_addr: break data_addr = typing.cast(int, dl[f"data_block_addr{dl.links_nr - 2}"]) blk = DataBlock(address=data_addr, stream=stream, mapped=mapped) next_block = bisect.bisect_right(addresses, data_addr) if next_block == len(addresses): block_len = limit - data_addr else: block_len = addresses[next_block] - data_addr blk.block_len = block_len stream.seek(data_addr) stream.write(bytes(blk)) except: print(format_exc()) raise self.identification.unfinalized_standard_flags -= v4c.FLAG_UNFIN_UPDATE_LAST_DT_LENGTH self.identification.file_identification = b"MDF " def _sort( self, stream: FileLike | mmap.mmap, compress: bool = True, current_progress_index: int = 0, max_progress_count: int = 0, progress: Callable[[int, int], None] | None = None, ) -> None: flags = self.identification.unfinalized_standard_flags common: defaultdict[int, list[tuple[int, int]]] = defaultdict(list) for i, group in enumerate(self.groups): if group.sorted: continue try: data_block = next(group.get_data_blocks()) common[data_block.address].append((i, group.channel_group.record_id)) except: continue read = stream.read seek = stream.seek self._tempfile.seek(0, 2) tell = self._tempfile.tell write = self._tempfile.write for address, groups in common.items(): cg_map = {rec_id: self.groups[index_].channel_group for index_, rec_id in groups} final_records: dict[int, list[DataBlockInfo]] = {id_: [] for (_, id_) in groups} for rec_id, channel_group in cg_map.items(): if channel_group.address in self._cn_data_map: gp_idx, cn_idx = self._cn_data_map[channel_group.address] self.groups[gp_idx].signal_data[cn_idx] = ([], iter(EMPTY_TUPLE)) group = self.groups[groups[0][0]] record_id_nr = group.data_group.record_id_len cg_size = group.record_size match record_id_nr: case 1: _unpack_stuct = UINT8_uf case 2: _unpack_stuct = UINT16_uf case 4: _unpack_stuct = UINT32_uf case 8: _unpack_stuct = UINT64_uf case _: message = f"invalid record id size {record_id_nr}" raise MdfException(message) rem = b"" blocks = list(group.get_data_blocks()) # might be expensive ? # most of the steps are for sorting, but the last 2 are after we've done sorting # so remove the 2 steps that are not related to sorting from the count step = float(SORT_STEPS - 2) / len(blocks) / len(common) count = float(current_progress_index) previous = count for block_info in blocks: dtblock_address, dtblock_raw_size, dtblock_size, block_type, param = ( block_info.address, typing.cast(int, block_info.original_size), block_info.compressed_size, block_info.block_type, block_info.param, ) count += step # if we've been told to notify about progress # and we've been given a max progress count (only way we can do progress updates) # and there's a tick update (at least 1 integer between the last update and the current index) # then we can notify about the callback progress if callable(progress) and max_progress_count and floor(previous) < floor(count): progress(floor(count), max_progress_count) previous = count seek(dtblock_address) if block_type != v4c.DT_BLOCK: partial_records: dict[int, list[bytes]] = {id_: [] for _, id_ in groups} new_data = read(dtblock_size) if block_type == v4c.DZ_BLOCK_DEFLATE: new_data = decompress(new_data, bufsize=dtblock_raw_size) elif block_type == v4c.DZ_BLOCK_TRANSPOSED: new_data = decompress(new_data, bufsize=dtblock_raw_size) cols = typing.cast(int, param) lines = dtblock_raw_size // cols nd: NDArray[np.record] = np.rec.fromstring(new_data[: lines * cols], dtype=uint8) nd = nd.reshape((cols, lines)) new_data = nd.T.ravel().tobytes() + new_data[lines * cols :] new_data = rem + new_data try: rem = sort_data_block( new_data, partial_records, cg_size, record_id_nr, _unpack_stuct, ) except: print(format_exc()) raise for rec_id, records in partial_records.items(): channel_group = cg_map[rec_id] dg_cntr: int | None ch_cntr: int | None if channel_group.address in self._cn_data_map: dg_cntr, ch_cntr = self._cn_data_map[channel_group.address] else: dg_cntr, ch_cntr = None, None if records: tempfile_address = tell() new_data = b"".join(records) original_size = len(new_data) if original_size: if compress: new_data = lz_compress(new_data, store_size=True) compressed_size = len(new_data) write(new_data) if dg_cntr is not None and ch_cntr is not None: info = SignalDataBlockInfo( address=tempfile_address, compressed_size=compressed_size, original_size=original_size, block_type=v4c.DZ_BLOCK_LZ, location=v4c.LOCATION_TEMPORARY_FILE, ) signal_data = typing.cast( list[tuple[list[SignalDataBlockInfo], Iterator[SignalDataBlockInfo]]], self.groups[dg_cntr].signal_data, ) signal_data[ch_cntr][0].append(info) else: block_info = DataBlockInfo( address=tempfile_address, block_type=v4c.DZ_BLOCK_LZ, compressed_size=compressed_size, original_size=original_size, param=0, ) final_records[rec_id].append(block_info) else: write(new_data) if dg_cntr is not None and ch_cntr is not None: info = SignalDataBlockInfo( address=tempfile_address, compressed_size=original_size, original_size=original_size, block_type=v4c.DT_BLOCK, location=v4c.LOCATION_TEMPORARY_FILE, ) signal_data = typing.cast( list[tuple[list[SignalDataBlockInfo], Iterator[SignalDataBlockInfo]]], self.groups[dg_cntr].signal_data, ) signal_data[ch_cntr][0].append(info) else: block_info = DataBlockInfo( address=tempfile_address, block_type=v4c.DT_BLOCK, compressed_size=original_size, original_size=original_size, param=0, ) final_records[rec_id].append(block_info) else: # DTBLOCK seek(dtblock_address) limit = 32 * 1024 * 1024 # 32MB while dtblock_size: if dtblock_size > limit: dtblock_size -= limit new_data = rem + read(limit) else: new_data = rem + read(dtblock_size) dtblock_size = 0 partial_records = {id_: [] for _, id_ in groups} rem = sort_data_block( new_data, partial_records, cg_size, record_id_nr, _unpack_stuct, ) for rec_id, records in partial_records.items(): channel_group = cg_map[rec_id] if channel_group.address in self._cn_data_map: dg_cntr, ch_cntr = self._cn_data_map[channel_group.address] else: dg_cntr, ch_cntr = None, None if records: tempfile_address = tell() new_data = b"".join(records) original_size = len(new_data) if original_size: if compress: new_data = lz_compress(new_data, store_size=True) compressed_size = len(new_data) write(new_data) if dg_cntr is not None and ch_cntr is not None: info = SignalDataBlockInfo( address=tempfile_address, compressed_size=compressed_size, original_size=original_size, block_type=v4c.DZ_BLOCK_LZ, location=v4c.LOCATION_TEMPORARY_FILE, ) signal_data = typing.cast( list[tuple[list[SignalDataBlockInfo], Iterator[SignalDataBlockInfo]]], self.groups[dg_cntr].signal_data, ) signal_data[ch_cntr][0].append(info) else: block_info = DataBlockInfo( address=tempfile_address, block_type=v4c.DZ_BLOCK_LZ, compressed_size=compressed_size, original_size=original_size, param=None, ) final_records[rec_id].append(block_info) else: write(new_data) if dg_cntr is not None and ch_cntr is not None: info = SignalDataBlockInfo( address=tempfile_address, compressed_size=original_size, original_size=original_size, block_type=v4c.DT_BLOCK, location=v4c.LOCATION_TEMPORARY_FILE, ) signal_data = typing.cast( list[tuple[list[SignalDataBlockInfo], Iterator[SignalDataBlockInfo]]], self.groups[dg_cntr].signal_data, ) signal_data[ch_cntr][0].append(info) else: block_info = DataBlockInfo( address=tempfile_address, block_type=v4c.DT_BLOCK, compressed_size=original_size, original_size=original_size, param=None, ) final_records[rec_id].append(block_info) # after we read all DTBLOCKs in the original file, # we assign freshly created blocks from temporary file to # corresponding groups. for idx, rec_id in groups: group = self.groups[idx] group.data_location = v4c.LOCATION_TEMPORARY_FILE group.set_blocks_info(final_records[rec_id]) group.sorted = True for i, group in enumerate(self.groups): if flags & v4c.FLAG_UNFIN_UPDATE_CG_COUNTER: channel_group = group.channel_group if channel_group.flags & v4c.FLAG_CG_VLSD: continue if self.version >= "4.20" and channel_group.flags & v4c.FLAG_CG_REMOTE_MASTER: index = typing.cast(int, channel_group.cg_master_index) else: index = i if group.uses_ld: samples_size = channel_group.samples_byte_nr else: samples_size = channel_group.samples_byte_nr + channel_group.invalidation_bytes_nr total_size = sum(typing.cast(int, blk.original_size) for blk in group.get_data_blocks()) cycles_nr = total_size // samples_size virtual_channel_group = self.virtual_groups[index] virtual_channel_group.cycles_nr = cycles_nr channel_group.cycles_nr = cycles_nr if self.identification.unfinalized_standard_flags & v4c.FLAG_UNFIN_UPDATE_CG_COUNTER: self.identification.unfinalized_standard_flags -= v4c.FLAG_UNFIN_UPDATE_CG_COUNTER if self.identification.unfinalized_standard_flags & v4c.FLAG_UNFIN_UPDATE_VLSD_BYTES: self.identification.unfinalized_standard_flags -= v4c.FLAG_UNFIN_UPDATE_VLSD_BYTES def _process_bus_logging(self) -> None: groups_count = len(self.groups) for index in range(groups_count): group = self.groups[index] if group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT: source = group.channel_group.acq_source if ( source and source.bus_type in (v4c.BUS_TYPE_CAN, v4c.BUS_TYPE_OTHER) and "CAN_DataFrame" in [ch.name for ch in group.channels] ): try: self._process_can_logging(index, group) except Exception: message = f"Error during CAN logging processing: {format_exc()}" logger.error(message) if ( source and source.bus_type in (v4c.BUS_TYPE_LIN, v4c.BUS_TYPE_OTHER) and "LIN_Frame" in [ch.name for ch in group.channels] ): try: self._process_lin_logging(index, group) except Exception as e: message = f"Error during LIN logging processing: {e}" logger.error(message) def _process_can_logging(self, group_index: int, grp: Group) -> None: channels = grp.channels group = grp dbc = None for channel in channels: if channel.name == "CAN_DataFrame": attachment_addr = channel.attachment if attachment_addr is not None: if attachment_addr not in self._dbc_cache: attachment, at_name, md5_sum = self.extract_attachment( index=attachment_addr, ) if at_name.suffix.lower() not in (".arxml", ".dbc"): message = f'Expected .dbc or .arxml file as CAN channel attachment but got "{at_name}"' logger.warning(message) elif not attachment: message = f'Attachment "{at_name}" not found' logger.warning(message) else: dbc = load_can_database(at_name, contents=attachment) if dbc: self._dbc_cache[attachment_addr] = dbc else: dbc = self._dbc_cache[attachment_addr] break if not group.channel_group.flags & v4c.FLAG_CG_PLAIN_BUS_EVENT: self._prepare_record(group) data = self._load_data(group, record_offset=0, record_count=1) for fragment in data: self._set_temporary_master(None) self._set_temporary_master(self.get_master(group_index, data=fragment, one_piece=True)) bus_ids = self.get( "CAN_DataFrame.BusChannel", group=group_index, data=fragment, samples_only=True, )[0].astype("> 8 ps = tmp_pgn & 0xFF pf = (msg_id_signal.samples >> 16) & 0xFF _pgn = tmp_pgn & 0x3FF00 msg_id_signal.samples = where(pf >= 240, _pgn + ps, _pgn) buses = unique(bus_ids) if len(bus_ids) == 0: continue for bus in buses: idx_ = bus_ids == bus bus_msg_ids = msg_id_signal.samples[idx_] bus_t = msg_id_signal.timestamps[idx_] bus_data_bytes = data_bytes[idx_] unique_ids = sorted(unique(bus_msg_ids).astype(" None: channels = grp.channels group = grp dbc = None for channel in channels: if channel.name == "LIN_Frame": attachment_addr = channel.attachment if attachment_addr is not None: if attachment_addr not in self._dbc_cache: attachment, at_name, md5_sum = self.extract_attachment( index=attachment_addr, ) if at_name.suffix.lower() not in (".arxml", ".dbc", ".ldf"): message = ( f'Expected .dbc, .arxml or .ldf file as LIN channel attachment but got "{at_name}"' ) logger.warning(message) elif not attachment: message = f'Attachment "{at_name}" not found' logger.warning(message) else: contents = None if at_name.suffix.lower() == ".ldf" else attachment dbc = load_can_database(at_name, contents=contents) if dbc: self._dbc_cache[attachment_addr] = dbc else: dbc = self._dbc_cache[attachment_addr] break if dbc is None: self._prepare_record(group) data = self._load_data(group, optimize_read=False) for fragment in data: self._set_temporary_master(None) self._set_temporary_master(self.get_master(group_index, data=fragment, one_piece=True)) msg_ids = ( self.get( "LIN_Frame.ID", group=group_index, data=fragment, samples_only=True, )[0].astype(" None: if not self._file: raise RuntimeError("self._file is None") self.header = HeaderBlock(address=0x40, stream=self._file) def debug_channel( mdf: MDF4, group: Group, channel: Channel, dependency: list[ChannelArrayBlock] | list[tuple[int, int]] | None, file: StringIO | None = None, ) -> None: """Use this to print debug information in case of errors. Parameters ---------- mdf : MDF Source MDF object. group : dict Group. channel : Channel Channel object. dependency : ChannelDependency Channel dependency object. """ print("MDF", "=" * 76, file=file) print("name:", mdf.name, file=file) print("version:", mdf.version, file=file) print("read fragment size:", mdf._read_fragment_size, file=file) print("write fragment size:", mdf._write_fragment_size, file=file) print() record = mdf._prepare_record(group) print("GROUP", "=" * 74, file=file) print("sorted:", group.sorted, file=file) print("data location:", group.data_location, file=file) print("data blocks:", group.data_blocks, file=file) print("dependencies", group.channel_dependencies, file=file) print("record:", record, file=file) print(file=file) cg = group.channel_group print("CHANNEL GROUP", "=" * 66, file=file) print(cg, cg.cycles_nr, cg.samples_byte_nr, cg.invalidation_bytes_nr, file=file) print(file=file) print("CHANNEL", "=" * 72, file=file) print(channel, file=file) print(file=file) print("CHANNEL ARRAY", "=" * 66, file=file) print(dependency, file=file) print(file=file) asammdf-8.5.1/src/asammdf/blocks/options.py000066400000000000000000000052131502633300400206530ustar00rootroot00000000000000from enum import IntEnum import os from typing import Final, Literal from typing_extensions import Any, TypedDict from .types import StrPath class IntegerInterpolation(IntEnum): REPEAT_PREVIOUS_SAMPLE = 0 LINEAR_INTERPOLATION = 1 HYBRID_INTERPOLATION = 2 class FloatInterpolation(IntEnum): REPEAT_PREVIOUS_SAMPLE = 0 LINEAR_INTERPOLATION = 1 class _GlobalOptions(TypedDict): read_fragment_size: int write_fragment_size: int use_display_names: bool single_bit_uint_as_bool: bool integer_interpolation: IntegerInterpolation float_interpolation: FloatInterpolation temporary_folder: StrPath | None raise_on_multiple_occurrences: bool fill_0_for_missing_computation_channels: bool GLOBAL_OPTIONS: Final[_GlobalOptions] = { "read_fragment_size": 256 * 1024 * 1024, "write_fragment_size": 4 * 1024 * 1024, "use_display_names": True, "single_bit_uint_as_bool": False, "integer_interpolation": IntegerInterpolation.REPEAT_PREVIOUS_SAMPLE, "float_interpolation": FloatInterpolation.LINEAR_INTERPOLATION, "temporary_folder": None, "raise_on_multiple_occurrences": True, "fill_0_for_missing_computation_channels": False, } _Opt = Literal[ "read_fragment_size", "write_fragment_size", "use_display_names", "single_bit_uint_as_bool", "integer_interpolation", "float_interpolation", "temporary_folder", "raise_on_multiple_occurrences", "fill_0_for_missing_computation_channels", ] def set_global_option(opt: _Opt, value: Any) -> None: if opt not in GLOBAL_OPTIONS: raise KeyError(f'Unknown global option "{opt}"') if opt == "read_fragment_size": GLOBAL_OPTIONS[opt] = int(value) elif opt == "write_fragment_size": GLOBAL_OPTIONS[opt] = min(int(value), 4 * 1024 * 1024) elif opt in ( "use_display_names", "single_bit_uint_as_bool", "raise_on_multiple_occurrences", "fill_0_for_missing_computation_channels", ): GLOBAL_OPTIONS[opt] = bool(value) elif opt == "integer_interpolation": GLOBAL_OPTIONS[opt] = IntegerInterpolation(value) elif opt == "float_interpolation": GLOBAL_OPTIONS[opt] = FloatInterpolation(value) elif opt == "temporary_folder": value = value or None if value is not None: os.makedirs(value, exist_ok=True) GLOBAL_OPTIONS[opt] = value def get_global_option(opt: _Opt) -> object: return GLOBAL_OPTIONS[opt] def get_option(opt: _Opt, instance_options: _GlobalOptions) -> object: value: object = instance_options[opt] if value is None: value = get_global_option(opt) return value asammdf-8.5.1/src/asammdf/blocks/source_utils.py000066400000000000000000000057261502633300400217110ustar00rootroot00000000000000"""asammdf utility functions for source information""" from functools import lru_cache from . import v2_v3_blocks as v3b from . import v2_v3_constants as v3c from . import v4_blocks as v4b from . import v4_constants as v4c from .types import SourceType class Source: __slots__ = "bus_type", "comment", "name", "path", "source_type" SOURCE_OTHER = v4c.SOURCE_OTHER SOURCE_ECU = v4c.SOURCE_ECU SOURCE_BUS = v4c.SOURCE_BUS SOURCE_IO = v4c.SOURCE_IO SOURCE_TOOL = v4c.SOURCE_TOOL SOURCE_USER = v4c.SOURCE_USER BUS_TYPE_NONE = v4c.BUS_TYPE_NONE BUS_TYPE_OTHER = v4c.BUS_TYPE_OTHER BUS_TYPE_CAN = v4c.BUS_TYPE_CAN BUS_TYPE_LIN = v4c.BUS_TYPE_LIN BUS_TYPE_MOST = v4c.BUS_TYPE_MOST BUS_TYPE_FLEXRAY = v4c.BUS_TYPE_FLEXRAY BUS_TYPE_K_LINE = v4c.BUS_TYPE_K_LINE BUS_TYPE_ETHERNET = v4c.BUS_TYPE_ETHERNET BUS_TYPE_USB = v4c.BUS_TYPE_USB def __init__(self, name: str, path: str, comment: str, source_type: int, bus_type: int) -> None: """Common representation for source information. Attributes ---------- name : str Source name. path : str Source path. comment : str Source comment. source_type : int Source type code. bus_type : int Source bus code. """ self.name, self.path, self.comment, self.source_type, self.bus_type = ( name, path, comment, source_type, bus_type, ) @classmethod @lru_cache(128) def from_source(cls, source: SourceType) -> "Source": if isinstance(source, v3b.ChannelExtension): if source.type == v3c.SOURCE_ECU: return cls( source.name, source.path, source.comment, cls.SOURCE_OTHER, # source type other cls.BUS_TYPE_NONE, # bus type none ) else: return cls( source.name, source.path, source.comment, cls.SOURCE_BUS, # source type bus cls.BUS_TYPE_CAN, # bus type CAN ) elif isinstance(source, v4b.SourceInformation): return cls( source.name, source.path, source.comment, source.source_type, source.bus_type, ) elif isinstance(source, Source): return cls( source.name, source.path, source.comment, source.source_type, source.bus_type, ) def get_details(self) -> str: source_type = v4c.SOURCE_TYPE_TO_STRING[self.source_type] bus_type = v4c.BUS_TYPE_TO_STRING[self.bus_type] return f" {source_type} source on bus {bus_type}: name=[{self.name}] path=[{self.path}]" asammdf-8.5.1/src/asammdf/blocks/types.py000066400000000000000000000017501502633300400203260ustar00rootroot00000000000000from collections.abc import Sequence from os import PathLike from typing import Literal, TYPE_CHECKING, Union from canmatrix import CanMatrix from numpy.typing import NDArray from typing_extensions import Any if TYPE_CHECKING: from . import v2_v3_blocks as v3b from . import v4_blocks as v4b from . import v4_constants as v4c from .source_utils import Source StrPath = str | PathLike[str] # asammdf specific types BusType = Literal["CAN", "LIN"] ChannelConversionType = Union["v3b.ChannelConversion", "v4b.ChannelConversion"] ChannelsType = Sequence[str | tuple[str | None, int, int] | tuple[str, int]] CompressionType = Union[Literal[0, 1, 2, 3, 4, 5], "v4c.CompressionAlgorithm"] DbcFileType = tuple[StrPath | CanMatrix, int] EmptyChannelsType = Literal["skip", "zeros"] FloatInterpolationModeType = Literal[0, 1] IntInterpolationModeType = Literal[0, 1, 2] RasterType = float | str | NDArray[Any] SourceType = Union["v3b.ChannelExtension", "v4b.SourceInformation", "Source"] asammdf-8.5.1/src/asammdf/blocks/utils.py000066400000000000000000001600761502633300400203310ustar00rootroot00000000000000"""asammdf utility functions and classes""" from collections.abc import Callable, Iterator from functools import lru_cache import logging import mmap import multiprocessing from pathlib import Path from random import randint import re import string from struct import Struct import subprocess import sys from tempfile import TemporaryDirectory from time import perf_counter from types import TracebackType import typing from typing import Final, Literal, Optional, Union import xml.etree.ElementTree as ET from canmatrix.canmatrix import CanMatrix, matrix_class import canmatrix.formats import numpy as np from numpy import arange, bool_, interp, where from numpy.typing import NDArray import pandas as pd from pandas import Series from typing_extensions import ( Any, Buffer, LiteralString, NamedTuple, overload, ParamSpec, Protocol, runtime_checkable, TypedDict, TypeIs, TypeVar, Unpack, ) from . import v2_v3_constants as v3c from . import v4_constants as v4c from .blocks_common import UnpackFrom from .types import StrPath try: from cchardet import detect except: try: from chardet import detect except: class DetectDict(TypedDict): encoding: str | None def detect(text: bytes) -> DetectDict: encoding: str | None for encoding in ("utf-8", "latin-1", "cp1250", "cp1252"): try: text.decode(encoding) break except: continue else: encoding = None return {"encoding": encoding} class Terminated(Exception): def __init__(self, *args: object) -> None: super().__init__("terminated by user", *args) THREAD_COUNT: Final = max(multiprocessing.cpu_count() - 1, 1) target_byte_order: Final = "<=" if sys.byteorder == "little" else ">=" UINT8_u: Callable[[Buffer], tuple[int]] = Struct(" str: return f"asammdf MdfException: {self.args[0]}" def extract_xml_comment(comment: str) -> str: """Extract *TX* tag or otherwise the *common_properties* from an XML comment. Parameters ---------- comment : str XML string comment. Returns ------- comment : str Extracted string. """ comment = comment.replace(' xmlns="http://www.asam.net/mdf/v4"', "") try: comment_elem = ET.fromstring(comment) match = comment_elem.find(".//TX") if match is None: common_properties = comment_elem.find(".//common_properties") if common_properties is not None: comments: list[str] = [] for e in common_properties: field = f"{e.get('name')}: {e.text}" comments.append(field) comment = "\n".join(field) else: comment = "" else: comment = match.text or "" except ET.ParseError: pass return comment def matlab_compatible(name: str) -> str: """Make a channel name compatible with Matlab variable naming. Parameters ---------- name : str Channel name. Returns ------- compatible_name : str Channel name compatible with Matlab. """ compatible_names = [ch if ch in ALLOWED_MATLAB_CHARS else "_" for ch in name] compatible_name = "".join(compatible_names) if compatible_name[0] not in string.ascii_letters: compatible_name = "M_" + compatible_name # max variable name is 63 and 3 chars are reserved # for get_unique_name in case of multiple channel name occurrence return compatible_name[:60] @runtime_checkable class FileLike(Protocol): def __iter__(self) -> Iterator[bytes]: ... def close(self) -> None: ... def read(self, size: int | None = -1, /) -> bytes: ... def seek(self, target: int, whence: int = 0, /) -> int: ... def tell(self) -> int: ... def write(self, buffer: Buffer, /) -> int: ... class BlockKwargs(TypedDict, total=False): stream: FileLike | mmap.mmap mapped: bool address: int def stream_is_mmap(_stream: FileLike | mmap.mmap, mapped: bool) -> TypeIs[mmap.mmap]: return mapped @overload def get_text_v3( address: int, stream: FileLike | mmap.mmap, mapped: bool = ..., decode: Literal[True] = ..., ) -> str: ... @overload def get_text_v3( address: int, stream: FileLike | mmap.mmap, mapped: bool = ..., *, decode: Literal[False], ) -> bytes: ... @overload def get_text_v3(address: int, stream: FileLike | mmap.mmap, mapped: bool = ..., decode: bool = ...) -> bytes | str: ... def get_text_v3(address: int, stream: FileLike | mmap.mmap, mapped: bool = False, decode: bool = True) -> bytes | str: """Faster way to extract strings from MDF versions 2 and 3 TextBlock. Parameters ---------- address : int TextBlock address. stream : handle File IO handle. mapped : bool, default False Flag for mapped stream. decode : bool, default True Option to auto-detect character encoding and return decoded str instead of raw bytes. Returns ------- text : str | bytes Unicode string or bytes object depending on the `decode` argument. """ if address == 0: return "" if decode else b"" if stream_is_mmap(stream, mapped): block_id = stream[address : address + 2] if block_id != b"TX": return "" if decode else b"" (size,) = UINT16_uf(stream, address + 2) text_bytes = stream[address + 4 : address + size].split(b"\0", 1)[0].strip(b" \r\t\n") else: stream.seek(address) block_id = stream.read(2) if block_id != b"TX": return "" if decode else b"" size = UINT16_u(stream.read(2))[0] - 4 text_bytes = stream.read(size).split(b"\0", 1)[0].strip(b" \r\t\n") text: bytes | str if decode: try: text = text_bytes.decode("latin-1") except UnicodeDecodeError: encoding = detect(text_bytes)["encoding"] if encoding: try: text = text_bytes.decode(encoding, "ignore") except: text = "" else: text = "" else: text = text_bytes return text class MappedText(NamedTuple): raw: bytes decoded: str TxMap = dict[int, MappedText] @overload def get_text_v4( address: int, stream: FileLike | mmap.mmap, mapped: bool = ..., decode: Literal[True] = ..., *, tx_map: TxMap, ) -> str: ... @overload def get_text_v4( address: int, stream: FileLike | mmap.mmap, mapped: bool = ..., *, decode: Literal[False], tx_map: TxMap, ) -> bytes: ... @overload def get_text_v4( address: int, stream: FileLike | mmap.mmap, mapped: bool = ..., decode: bool = ..., *, tx_map: TxMap, ) -> bytes | str: ... def get_text_v4( address: int, stream: FileLike | mmap.mmap, mapped: bool = False, decode: bool = True, *, tx_map: TxMap, ) -> bytes | str: """Faster way to extract strings from MDF version 4 TextBlock. Parameters ---------- address : int TextBlock address. stream : handle File IO handle. mapped : bool, default False Flag for mapped stream. decode : bool, default True Option to auto-detect character encoding and return decoded str instead of raw bytes. tx_map : dict, optional Map that contains interned strings. Returns ------- text : str | bytes Unicode string or bytes object depending on the `decode` argument. """ if mapped_text := tx_map.get(address, None): return mapped_text.decoded if decode else mapped_text.raw if address == 0: tx_map[address] = MappedText(b"", "") return "" if decode else b"" if stream_is_mmap(stream, mapped): block_id, size = BLK_COMMON_uf(stream, address) if block_id not in (b"##TX", b"##MD"): tx_map[address] = MappedText(b"", "") return "" if decode else b"" text_bytes = stream[address + 24 : address + size].split(b"\0", 1)[0].strip(b" \r\t\n") else: stream.seek(address) block_id, size = BLK_COMMON_u(stream.read(24)) if block_id not in (b"##TX", b"##MD"): tx_map[address] = MappedText(b"", "") return "" if decode else b"" text_bytes = stream.read(size - 24).split(b"\0", 1)[0].strip(b" \r\t\n") try: decoded_text = text_bytes.decode("utf-8") except UnicodeDecodeError: encoding = detect(text_bytes)["encoding"] if encoding: try: decoded_text = text_bytes.decode(encoding, "ignore") except: decoded_text = "" else: decoded_text = "" tx_map[address] = MappedText(text_bytes, decoded_text) return decoded_text if decode else text_bytes def sanitize_xml(text: str) -> str: return re.sub(_xmlns_pattern, "", text) def extract_display_names(comment: str) -> dict[str, str]: comment = comment.replace(' xmlns="http://www.asam.net/mdf/v4"', "") display_names = {} if comment.startswith("" in comment: try: start = comment.index("") end = comment.index("") + 8 names = ET.fromstring(comment[start:end]) for i, elem in enumerate(names.iter()): if i == 0: continue if elem.text is None: raise ValueError("text is None") display_names[elem.text.strip(" \t\r\n\v\0")] = elem.tag except: pass return display_names class EncryptionInfo(TypedDict, total=False): encrypted: bool algorithm: str original_md5_sum: str original_size: int def extract_encryption_information(comment: str) -> EncryptionInfo: info: EncryptionInfo = {} comment = comment.replace(' xmlns="http://www.asam.net/mdf/v4"', "") if comment.startswith("" in comment: try: comment_elem = ET.fromstring(comment) for match in comment_elem.findall(".//extensions/extension"): elem = match.find("encrypted") if elem is None: raise RuntimeError("cannot find 'encrypted' Element") if elem.text is None: raise RuntimeError("text is None") encrypted = elem.text.strip().lower() == "true" elem = match.find("algorithm") if elem is None: raise RuntimeError("cannot find 'algorithm' Element") if elem.text is None: raise RuntimeError("text is None") algorithm = elem.text.strip().lower() elem = match.find("original_md5_sum") if elem is None: raise RuntimeError("cannot find 'original_md5_sum' Element") if elem.text is None: raise RuntimeError("text is None") original_md5_sum = elem.text.strip().lower() elem = match.find("original_size") if elem is None: raise RuntimeError("cannot find 'original_size' Element") if elem.text is None: raise RuntimeError("text is None") original_size = int(elem.text) info["encrypted"] = encrypted info["algorithm"] = algorithm info["original_md5_sum"] = original_md5_sum info["original_size"] = original_size break except: pass return info def extract_ev_tool(comment: str) -> str: tool = "" comment = comment.replace(' xmlns="http://www.asam.net/mdf/v4"', "") try: comment_elem = ET.fromstring(comment) match = comment_elem.find(".//tool") if match is None: tool = "" else: tool = match.text or "" except: pass return tool @lru_cache(maxsize=1024) def get_fmt_v3(data_type: int, size: int, byte_order: int = v3c.BYTE_ORDER_INTEL) -> str: """Convert MDF versions 2 and 3 channel data type to numpy dtype format string. Parameters ---------- data_type : int MDF channel data type. size : int Data bit size. byte_order : int, default 0 (BYTE_ORDER_INTEL) Integer code for byte order (endianness). Returns ------- fmt : str Numpy compatible data type format string. """ if data_type in (v3c.DATA_TYPE_STRING, v3c.DATA_TYPE_BYTEARRAY): size = size // 8 if data_type == v3c.DATA_TYPE_STRING: fmt = f"S{size}" else: fmt = f"({size},)u1" else: if size > 64 and data_type in ( v3c.DATA_TYPE_UNSIGNED_INTEL, v3c.DATA_TYPE_UNSIGNED, v3c.DATA_TYPE_UNSIGNED_MOTOROLA, v3c.DATA_TYPE_SIGNED_INTEL, v3c.DATA_TYPE_SIGNED, v3c.DATA_TYPE_SIGNED_MOTOROLA, ): fmt = f"({size // 8},)u1" else: if size <= 8: size = 1 elif size <= 16: size = 2 elif size <= 32: size = 4 elif size <= 64: size = 8 else: size = size // 8 match data_type: case v3c.DATA_TYPE_UNSIGNED_INTEL: fmt = f"u{size}" case v3c.DATA_TYPE_UNSIGNED_MOTOROLA: fmt = f">u{size}" case v3c.DATA_TYPE_SIGNED_INTEL: fmt = f"i{size}" case v3c.DATA_TYPE_SIGNED_MOTOROLA: fmt = f">i{size}" case v3c.DATA_TYPE_FLOAT_INTEL | v3c.DATA_TYPE_DOUBLE_INTEL: fmt = f"f{size}" case v3c.DATA_TYPE_FLOAT | v3c.DATA_TYPE_DOUBLE: if byte_order == v3c.BYTE_ORDER_INTEL: fmt = f"f{size}" return fmt @lru_cache(maxsize=1024) def get_fmt_v4(data_type: int, size: int, channel_type: int = v4c.CHANNEL_TYPE_VALUE) -> str: """Convert MDF version 4 channel data type to numpy dtype format string. Parameters ---------- data_type : int MDF channel data type. size : int Data bit size. channel_type : int, default 0 (CHANNEL_TYPE_VALUE) MDF channel type. Returns ------- fmt : str Numpy compatible data type format string. """ if data_type in v4c.NON_SCALAR_TYPES: size = size // 8 or 1 if data_type in ( v4c.DATA_TYPE_BYTEARRAY, v4c.DATA_TYPE_MIME_STREAM, v4c.DATA_TYPE_MIME_SAMPLE, ): if channel_type == v4c.CHANNEL_TYPE_VALUE: fmt = f"({size},)u1" else: fmt = f" 64 and data_type in ( v4c.DATA_TYPE_UNSIGNED_INTEL, v4c.DATA_TYPE_UNSIGNED_MOTOROLA, v4c.DATA_TYPE_SIGNED_INTEL, v4c.DATA_TYPE_SIGNED_MOTOROLA, ): fmt = f"({size // 8},)u1" else: if size <= 8: size = 1 elif size <= 16: size = 2 elif size <= 32: size = 4 elif size <= 64: size = 8 else: size = size // 8 match data_type: case v4c.DATA_TYPE_UNSIGNED_INTEL: fmt = f"u{size}" case v4c.DATA_TYPE_SIGNED_INTEL: fmt = f"i{size}" case v4c.DATA_TYPE_REAL_INTEL: fmt = f"f{size}" case v4c.DATA_TYPE_COMPLEX_INTEL: fmt = f"c{size}" return fmt @lru_cache(maxsize=1024) def fmt_to_datatype_v3(fmt: np.dtype[Any], shape: tuple[int, ...], array: bool = False) -> tuple[int, int]: """Convert numpy dtype format string to MDF versions 2 and 3 channel data type and size. Parameters ---------- fmt : numpy.dtype Numpy data type. shape : tuple Numpy array shape. array : bool, default False Disambiguate between bytearray and channel array. Returns ------- data_type, size : int, int Integer data type as defined by ASAM MDF and bit size. """ byteorder = fmt.byteorder if byteorder in "=|": byteorder = "<" if sys.byteorder == "little" else ">" size = fmt.itemsize * 8 kind = fmt.kind if not array and shape[1:] and fmt.itemsize == 1 and kind == "u": data_type = v3c.DATA_TYPE_BYTEARRAY for dim in shape[1:]: size *= dim else: match kind: case "u": if byteorder == "<": data_type = v3c.DATA_TYPE_UNSIGNED_INTEL else: data_type = v3c.DATA_TYPE_UNSIGNED_MOTOROLA case "i": if byteorder == "<": data_type = v3c.DATA_TYPE_SIGNED_INTEL else: data_type = v3c.DATA_TYPE_SIGNED_MOTOROLA case "f": if byteorder == "<": if size == 32: data_type = v3c.DATA_TYPE_FLOAT else: data_type = v3c.DATA_TYPE_DOUBLE else: if size == 32: data_type = v3c.DATA_TYPE_FLOAT_MOTOROLA else: data_type = v3c.DATA_TYPE_DOUBLE_MOTOROLA case "S" | "V": data_type = v3c.DATA_TYPE_STRING case "b": data_type = v3c.DATA_TYPE_UNSIGNED_INTEL size = 1 case _: message = f"Unknown type: dtype={fmt}, shape={shape}" logger.exception(message) raise MdfException(message) return data_type, size @lru_cache(maxsize=1024) def info_to_datatype_v4(signed: bool, little_endian: bool) -> int: """Map CAN signal to MDF integer types. Parameters ---------- signed : bool Signal is flagged as signed in the CAN database. little_endian : bool Signal is flagged as little-endian (Intel) in the CAN database. Returns ------- datatype : int Integer code for MDF channel data type. """ if signed: if little_endian: datatype = v4c.DATA_TYPE_SIGNED_INTEL else: datatype = v4c.DATA_TYPE_SIGNED_MOTOROLA else: if little_endian: datatype = v4c.DATA_TYPE_UNSIGNED_INTEL else: datatype = v4c.DATA_TYPE_UNSIGNED_MOTOROLA return datatype @lru_cache(maxsize=1024) def fmt_to_datatype_v4(fmt: np.dtype[Any], shape: tuple[int, ...], array: bool = False) -> tuple[int, int]: """Convert numpy dtype format string to MDF version 4 channel data type and size. Parameters ---------- fmt : numpy.dtype Numpy data type. shape : tuple Numpy array shape. array : bool, default False Disambiguate between bytearray and channel array. Returns ------- data_type, size : int, int Integer data type as defined by ASAM MDF and bit size. """ byteorder = fmt.byteorder if byteorder in "=|": byteorder = "<" if sys.byteorder == "little" else ">" size = fmt.itemsize * 8 kind = fmt.kind if not array and len(shape) > 1 and size == 8 and kind == "u": data_type = v4c.DATA_TYPE_BYTEARRAY for dim in shape[1:]: size *= dim else: match kind: case "u": if byteorder == "<": data_type = v4c.DATA_TYPE_UNSIGNED_INTEL else: data_type = v4c.DATA_TYPE_UNSIGNED_MOTOROLA case "i": if byteorder == "<": data_type = v4c.DATA_TYPE_SIGNED_INTEL else: data_type = v4c.DATA_TYPE_SIGNED_MOTOROLA case "f": if byteorder == "<": data_type = v4c.DATA_TYPE_REAL_INTEL else: data_type = v4c.DATA_TYPE_REAL_MOTOROLA case "S" | "V": data_type = v4c.DATA_TYPE_STRING_LATIN_1 case "b": data_type = v4c.DATA_TYPE_UNSIGNED_INTEL size = 1 case "c": if byteorder == "<": data_type = v4c.DATA_TYPE_COMPLEX_INTEL else: data_type = v4c.DATA_TYPE_COMPLEX_MOTOROLA case _: message = f"Unknown type: dtype={fmt}, shape={shape}" logger.exception(message) raise MdfException(message) return data_type, size def as_non_byte_sized_signed_int(integer_array: NDArray[Any], bit_length: int) -> NDArray[Any]: """The MDF spec allows values to be encoded as integers that aren't byte-sized. Numpy only knows how to do two's complement on byte-sized integers (i.e. int16, int32, int64, etc.), so we have to calculate two's complement ourselves in order to handle signed integers with unconventional lengths. Parameters ---------- integer_array : np.ndarray Array of integers to apply two's complement to. bit_length : int Number of bits to sample from the array. Returns ------- integer_array : np.ndarray Signed integer array with non-byte-sized two's complement applied. """ if integer_array.flags.writeable: integer_array &= (1 << bit_length) - 1 # Zero out the unwanted bits truncated_integers = integer_array else: truncated_integers = integer_array & ((1 << bit_length) - 1) # Zero out the unwanted bits return where( truncated_integers >> bit_length - 1, # sign bit as a truth series (True when negative) (2**bit_length - truncated_integers) * np.int8(-1), # when negative, do two's complement truncated_integers, # when positive, return the truncated int ) def count_channel_groups( stream: FileLike | mmap.mmap, include_channels: bool = False, mapped: bool = False ) -> tuple[int, int]: """Count all channel groups as fast as possible. This is used to provide reliable progress information when loading a file using the GUI. Parameters ---------- stream : file handle Opened file handle. include_channels : bool, default False Also count channels. mapped : bool, default False Flag for mapped stream. Returns ------- count : int Channel group count. """ count = 0 ch_count = 0 stream.seek(0, 2) file_limit = stream.tell() stream.seek(64) blk_id = stream.read(2) if blk_id == b"HD": version = 3 else: blk_id += stream.read(2) if blk_id == b"##HD": version = 4 else: raise MdfException(f"'{getattr(stream, 'name', stream)}' is not a valid MDF file") if version >= 4: if stream_is_mmap(stream, mapped): dg_addr = UINT64_uf(stream, 88)[0] while dg_addr: stream.seek(dg_addr + 32) cg_addr = UINT64_uf(stream, dg_addr + 32)[0] while cg_addr: count += 1 if include_channels: ch_addr = UINT64_uf(stream, cg_addr + 32)[0] while ch_addr: ch_count += 1 ch_addr = UINT64_uf(stream, ch_addr + 24)[0] if ch_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid CH block address") cg_addr = UINT64_uf(stream, cg_addr + 24)[0] if cg_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid CG block address") dg_addr = UINT64_uf(stream, dg_addr + 24)[0] if dg_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid DG block address") else: stream.seek(88, 0) dg_addr = UINT64_u(stream.read(8))[0] while dg_addr: stream.seek(dg_addr + 32) cg_addr = UINT64_u(stream.read(8))[0] while cg_addr: count += 1 if include_channels: stream.seek(cg_addr + 32) ch_addr = UINT64_u(stream.read(8))[0] while ch_addr: ch_count += 1 stream.seek(ch_addr + 24) ch_addr = UINT64_u(stream.read(8))[0] if ch_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid CH block address") stream.seek(cg_addr + 24) cg_addr = UINT64_u(stream.read(8))[0] if cg_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid CG block address") stream.seek(dg_addr + 24) dg_addr = UINT64_u(stream.read(8))[0] if dg_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid DG block address") else: stream.seek(68, 0) dg_addr = UINT32_u(stream.read(4))[0] while dg_addr: stream.seek(dg_addr + 8) cg_addr = UINT32_u(stream.read(4))[0] while cg_addr: count += 1 if include_channels: stream.seek(cg_addr + 8) ch_addr = UINT32_u(stream.read(4))[0] while ch_addr: ch_count += 1 stream.seek(ch_addr + 4) ch_addr = UINT32_u(stream.read(4))[0] if ch_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid CH block address") stream.seek(cg_addr + 4) cg_addr = UINT32_u(stream.read(4))[0] if cg_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid CG block address") stream.seek(dg_addr + 4) dg_addr = UINT32_u(stream.read(4))[0] if dg_addr >= file_limit: raise MdfException("File is a corrupted MDF file - Invalid DG block address") return count, ch_count @overload def validate_version_argument(version: v3c.Version2, hint: Literal[2]) -> v3c.Version2: ... @overload def validate_version_argument(version: v3c.Version2 | v3c.Version, hint: Literal[3]) -> v3c.Version2 | v3c.Version: ... @overload def validate_version_argument(version: v4c.Version, hint: Literal[4] = ...) -> v4c.Version: ... @overload def validate_version_argument(version: str, hint: int = ...) -> v3c.Version2 | v3c.Version | v4c.Version: ... def validate_version_argument(version: str, hint: int = 4) -> v3c.Version2 | v3c.Version | v4c.Version: """Validate the version argument against the supported MDF versions. The default version used depends on the hint MDF major revision. Parameters ---------- version : str Requested MDF version. hint : int, default 4 MDF revision hint. Returns ------- valid_version : str Valid version. """ valid_version: v3c.Version2 | v3c.Version | v4c.Version if version not in SUPPORTED_VERSIONS: if hint == 2: valid_version = "2.14" elif hint == 3: valid_version = "3.30" else: valid_version = "4.10" message = 'Unknown MDF version "{}". The available versions are {}; automatically using version "{}"' message = message.format(version, SUPPORTED_VERSIONS, valid_version) logger.warning(message) else: valid_version = typing.cast(v3c.Version2 | v3c.Version | v4c.Version, version) return valid_version class ChannelsDB(dict[str, tuple[tuple[int, int], ...]]): def __init__(self) -> None: super().__init__() def add(self, channel_name: str, entry: tuple[int, int]) -> None: """Add name to channels database and check if it contains a source path. Parameters ---------- channel_name : str Name that needs to be added to the database. entry : tuple (group index, channel index) pair. """ if channel_name: if channel_name not in self: self[channel_name] = (entry,) else: self[channel_name] += (entry,) if "\\" in channel_name: channel_name, _ = channel_name.split("\\", 1) if channel_name not in self: self[channel_name] = (entry,) elif entry not in self[channel_name]: self[channel_name] += (entry,) def randomized_string(size: int) -> bytes: """Get a null-terminated string of length `size`. Parameters ---------- size : int Target string length. Returns ------- string : bytes Randomized string. """ return bytes(randint(65, 90) for _ in range(size - 1)) + b"\0" def is_file_like(obj: object) -> TypeIs[FileLike]: """Check if the object is a file-like object. For objects to be considered file-like, they must be an iterator AND have a 'read' and 'seek' method as an attribute. Note: file-like objects must be iterable, but iterable objects need not be file-like. Parameters ---------- obj : object The object to check. Returns ------- is_file_like : bool Whether `obj` has file-like properties. Examples -------- >>> buffer = BytesIO(b"data") >>> is_file_like(buffer) True >>> is_file_like([1, 2, 3]) False """ return isinstance(obj, FileLike) or isinstance(getattr(obj, "file", None), FileLike) class UniqueDB: def __init__(self) -> None: self._db: dict[str, int] = {} def get_unique_name(self, name: str) -> str: """Return an available unique name. Parameters ---------- name : str Name to be made unique. Returns ------- unique_name : str New unique name. """ if name not in self._db: self._db[name] = 0 return name else: index = self._db[name] self._db[name] = index + 1 return f"{name}_{index}" def cut_video_stream(stream: bytes, start: float, end: float, fmt: str) -> bytes: """Cut video stream from `start` to `end` time. Parameters ---------- stream : bytes Video file content. start : float Start time. end : float End time. Returns ------- result : bytes Content of cut video. """ with TemporaryDirectory() as tmp: in_file = Path(tmp) / f"in{fmt}" out_file = Path(tmp) / f"out{fmt}" in_file.write_bytes(stream) try: ret = subprocess.run( [ "ffmpeg", "-ss", f"{start}", "-i", f"{in_file}", "-to", f"{end}", "-c", "copy", f"{out_file}", ], capture_output=True, check=False, ) except FileNotFoundError: result = stream else: if ret.returncode: result = stream else: result = out_file.read_bytes() return result def get_video_stream_duration(stream: bytes) -> float | None: with TemporaryDirectory() as tmp: in_file = Path(tmp) / "in" in_file.write_bytes(stream) try: process = subprocess.run( [ "ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", f"{in_file}", ], capture_output=True, check=False, ) result = float(process.stdout) except FileNotFoundError: result = None return result class VirtualChannelGroup: """Starting with MDF v4.20 it is possible to use remote masters and column oriented storage. This means we now have virtual channel groups that can span over multiple regular channel groups. This class facilitates the handling of these virtual groups. """ __slots__ = ( "cycles_nr", "groups", "record_size", ) def __init__(self) -> None: self.groups: list[int] = [] self.record_size = 0 self.cycles_nr = 0 def __repr__(self) -> str: return f"VirtualChannelGroup(groups={self.groups}, records_size={self.record_size}, cycles_nr={self.cycles_nr})" def block_fields(obj: object) -> list[str]: fields = [] for attr in dir(obj): if attr[:2] + attr[-2:] == "____": continue try: if callable(getattr(obj, attr)): continue fields.append(f"{attr}:{getattr(obj, attr)}") except AttributeError: continue return fields @overload def components( channel: NDArray[Any], channel_name: str, unique_names: UniqueDB, prefix: str = ..., master: Union[NDArray[Any], "pd.Index[Any]"] | None = ..., only_basenames: bool = ..., use_polars: Literal[False] = ..., ) -> Iterator[tuple[str, "pd.Series[Any]"]]: ... @overload def components( channel: NDArray[Any], channel_name: str, unique_names: UniqueDB, prefix: str = ..., master: Union[NDArray[Any], "pd.Index[Any]"] | None = ..., only_basenames: bool = ..., *, use_polars: Literal[True], ) -> Iterator[tuple[str, "list[object]"]]: ... def components( channel: NDArray[Any], channel_name: str, unique_names: UniqueDB, prefix: str = "", master: Union[NDArray[Any], "pd.Index[Any]"] | None = None, only_basenames: bool = False, use_polars: bool = False, ) -> Iterator[tuple[str, Union["pd.Series[Any]", list[object]]]]: """Yield pandas Series and unique name based on the ndarray object. Parameters ---------- channel : np.ndarray Channel to be used for Series. channel_name : str Channel name. unique_names : UniqueDB Unique names object. prefix : str, optional Prefix used in case of nested recarrays. master : np.ndarray | pd.Index, optional Optional index for the Series. only_basenames : bool, default False Use just the field names, without prefix, for structures and channel arrays. .. versionadded:: 5.13.0 use_polars : bool, default False Use polars. .. versionadded:: 8.1.0 Yields ------ name, series : (str, values) Tuple of unique name and values. """ names = channel.dtype.names # channel arrays if names and names[0] == channel_name: name = names[0] if not only_basenames: if prefix: name_ = unique_names.get_unique_name(f"{prefix}.{name}") else: name_ = unique_names.get_unique_name(name) else: name_ = unique_names.get_unique_name(name) samples = channel[name] if samples.dtype.byteorder not in target_byte_order: samples = samples.byteswap().view(samples.dtype.newbyteorder()) if len(samples.shape) > 1: values = ( list(samples) if use_polars else Series( list(samples), index=master, ) ) elif not use_polars: values = Series( samples, index=master, ) yield name_, values for name in names[1:] if names else (): samples = channel[name] if samples.dtype.byteorder not in target_byte_order: samples = samples.byteswap().view(samples.dtype.newbyteorder()) if not only_basenames: axis_name = unique_names.get_unique_name(f"{name_}.{name}") else: axis_name = unique_names.get_unique_name(name) if len(samples.shape) > 1: values = ( list(samples) if use_polars else Series( list(samples), index=master, ) ) elif not use_polars: values = Series( samples, index=master, ) yield axis_name, values # structure composition else: for name in channel.dtype.names or (): samples = channel[name] if samples.dtype.names: yield from components( samples, name, unique_names, prefix=f"{prefix}.{channel_name}" if prefix else f"{channel_name}", master=master, only_basenames=only_basenames, ) else: if samples.dtype.byteorder not in target_byte_order: samples = samples.byteswap().view(samples.dtype.newbyteorder()) if not only_basenames: name_ = unique_names.get_unique_name( f"{prefix}.{channel_name}.{name}" if prefix else f"{channel_name}.{name}" ) else: name_ = unique_names.get_unique_name(name) if len(samples.shape) > 1: values = ( list(samples) if use_polars else Series( list(samples), index=master, ) ) elif not use_polars: values = Series( samples, index=master, ) yield name_, values class DataBlockInfo: __slots__ = ( "address", "block_limit", "block_type", "compressed_size", "first_timestamp", "invalidation_block", "last_timestamp", "original_size", "param", ) def __init__( self, address: int, block_type: int, original_size: int | None, compressed_size: int | None, param: int | None, invalidation_block: Optional["InvalidationBlockInfo"] = None, block_limit: int | None = None, first_timestamp: bytes | None = None, last_timestamp: bytes | None = None, ) -> None: self.address = address self.block_type = block_type self.original_size = original_size self.compressed_size = compressed_size self.param = param self.invalidation_block = invalidation_block self.block_limit = block_limit self.first_timestamp = first_timestamp self.last_timestamp = last_timestamp def __repr__(self) -> str: return ( f"DataBlockInfo(address=0x{self.address:X}, " f"block_type={self.block_type}, " f"original_size={self.original_size}, " f"compressed_size={self.compressed_size}, " f"param={self.param}, " f"invalidation_block={self.invalidation_block}, " f"block_limit={self.block_limit}, " f"first_timestamp={self.first_timestamp!r}, " f"last_timestamp={self.last_timestamp!r})" ) class Fragment: def __init__( self, data: bytes | bytearray, record_offset: int = -1, record_count: int = -1, invalidation_data: bytes | bytearray | None = None, is_record: bool = True, ) -> None: self.data = data self.record_count = record_count self.record_offset = record_offset self.invalidation_data = invalidation_data self.is_record = is_record def __repr__(self) -> str: return ( f"FragmentInfo({len(self.data)} bytes, " f"record_offset={self.record_offset}, " f"record_count={self.record_count}, " f"is_record={self.is_record})" ) class InvalidationBlockInfo(DataBlockInfo): __slots__ = ("all_valid",) def __init__( self, address: int, block_type: int, original_size: int | None, compressed_size: int | None, param: int | None, all_valid: bool = False, block_limit: int | None = None, ) -> None: super().__init__(address, block_type, original_size, compressed_size, param, block_limit=block_limit) self.all_valid = all_valid def __repr__(self) -> str: return ( f"InvalidationBlockInfo(address=0x{self.address:X}, " f"block_type={self.block_type}, " f"original_size={self.original_size}, " f"compressed_size={self.compressed_size}, " f"param={self.param}, " f"all_valid={self.all_valid}, " f"block_limit={self.block_limit})" ) class SignalDataBlockInfo: __slots__ = ( "address", "block_type", "compressed_size", "location", "original_size", "param", ) def __init__( self, address: int, original_size: int, block_type: int = v4c.DT_BLOCK, param: int = 0, compressed_size: int | None = None, location: int = v4c.LOCATION_ORIGINAL_FILE, ) -> None: self.address = address self.compressed_size = compressed_size or original_size self.block_type = block_type self.original_size = original_size self.param = param self.location = location def __repr__(self) -> str: return ( f"SignalDataBlockInfo(address=0x{self.address:X}, " f"original_size={self.original_size}, " f"compressed_size={self.compressed_size}, " f"block_type={self.block_type})" ) def get_fields(obj: object) -> list[str]: fields: list[str] = [] for attr in dir(obj): if attr[:2] + attr[-2:] == "____": continue try: if callable(getattr(obj, attr)): continue fields.append(attr) except AttributeError: continue return fields # code snippet taken from https://www.kaggle.com/arjanso/reducing-dataframe-memory-size-by-65 def downcast(array: NDArray[Any]) -> NDArray[Any]: kind = array.dtype.kind if kind == "f": array = array.astype(np.float32) elif kind in "ui": min_ = array.min() max_ = array.max() if min_ >= 0: if max_ < 255: array = array.astype(np.uint8) elif max_ < 65535: array = array.astype(np.uint16) elif max_ < 4294967295: array = array.astype(np.uint32) else: array = array.astype(np.uint64) else: if min_ > np.iinfo(np.int8).min and max_ < np.iinfo(np.int8).max: array = array.astype(np.int8) elif min_ > np.iinfo(np.int16).min and max_ < np.iinfo(np.int16).max: array = array.astype(np.int16) elif min_ > np.iinfo(np.int32).min and max_ < np.iinfo(np.int32).max: array = array.astype(np.int32) elif min_ > np.iinfo(np.int64).min and max_ < np.iinfo(np.int64).max: array = array.astype(np.int64) return array def _csv_int2bin(val: int) -> str: """Format CAN id as bin. 100 -> 1100100 """ return f"{val:b}" csv_int2bin = np.vectorize(_csv_int2bin, otypes=[str]) def _csv_int2hex(val: "pd.Series[int]") -> str: """Format CAN id as hex. 100 -> 64 """ return f"{val:X}" csv_int2hex = np.vectorize(_csv_int2hex, otypes=[str]) def _csv_bytearray2hex(val: NDArray[Any], size: int | None = None) -> str: """Format CAN payload as hex strings. b'\xa2\xc3\x08' -> A2 C3 08 """ if size is not None: hex_val = typing.cast(bytes, val.tobytes())[:size].hex(" ", 1).upper() # type: ignore[redundant-cast, unused-ignore] else: try: hex_val = typing.cast(bytes, val.tobytes()).hex(" ", 1).upper() # type: ignore[redundant-cast, unused-ignore] except: hex_val = "●" return hex_val csv_bytearray2hex = np.vectorize(_csv_bytearray2hex, otypes=[str]) def pandas_query_compatible(name: str) -> str: """Adjust column name for usage in DataFrame query string.""" for c in ".$[]: ": name = name.replace(c, "_") if name.startswith(tuple(string.digits)): name = "file_" + name try: exec(f"from pandas import {name}") except ImportError: pass else: name = f"{name}__" return name class _Kwargs(TypedDict, total=False): fd: bool load_flat: bool cluster_name: str def load_can_database( path: StrPath, contents: bytes | str | None = None, **kwargs: Unpack[_Kwargs] ) -> CanMatrix | None: """ Parameters ---------- path : str | path-like Database path. contents : bytes | str, optional Optional database content. fd : bool, optional If supplied, only buses with the same FD kind will be loaded. load_flat : bool, optional If True, all the CAN messages found in multiple buses will be contained in the CAN database object. By default the first bus will be returned. cluster_name : str, optional If supplied, load just the clusters with this name. Returns ------- db : canmatrix.CanMatrix | None CAN database object or None. """ path = Path(path) import_type = path.suffix.lstrip(".").lower() try: if contents is None: dbs = canmatrix.formats.loadp(str(path), import_type=import_type, key="db", **kwargs) else: dbs = canmatrix.formats.loads(contents, import_type=import_type, key="db", **kwargs) except UnicodeDecodeError: if contents is None: contents = path.read_bytes() encoding = detect(contents)["encoding"] if encoding: try: dbs = canmatrix.formats.loads( contents, import_type=import_type, key="db", encoding=encoding, **kwargs, ) except: dbs = None if dbs: # filter only CAN clusters dbs = {name: db for name, db in dbs.items() if db.type == matrix_class.CAN} if dbs: cluster_name = kwargs.get("cluster_name", None) if cluster_name is not None: dbs = {name: db for name, db in dbs.items() if name == cluster_name} if "fd" in kwargs: fd = kwargs["fd"] dbs = {name: db for name, db in dbs.items() if db.contains_fd == fd} if kwargs.get("load_flat", False): can_matrix, *rest = list(dbs.values()) can_matrix.merge(rest) else: first_bus = list(dbs)[0] can_matrix = dbs[first_bus] else: can_matrix = None return can_matrix def all_blocks_addresses(obj: FileLike | mmap.mmap) -> tuple[dict[int, bytes], dict[bytes, list[int]], list[int]]: DG = "DG\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00" others = "(D[VTZIL]|AT|C[AGHNC]|EV|FH|HL|LD|MD|R[DVI]|S[IRD]|TX|GD)\x00\x00\x00\x00" pattern = re.compile( f"(?P##({DG}|{others}))".encode("ascii"), re.DOTALL | re.MULTILINE, ) try: obj.seek(0) except: pass source: Buffer | bytes if isinstance(obj, Buffer): re.search(pattern, obj) source = obj else: source = obj.read() addresses: list[int] = [] block_groups: dict[bytes, list[int]] = {} blocks: dict[int, bytes] = {} for match in re.finditer(pattern, source): btype: bytes = match.group("block")[:4] start = match.start() if start % 8: continue btype_addresses = block_groups.setdefault(btype, []) btype_addresses.append(start) addresses.append(start) blocks[start] = btype return blocks, block_groups, addresses def plausible_timestamps( t: NDArray[Any], minimum: float, maximum: float, exp_min: int = -15, exp_max: int = 15, ) -> tuple[bool, NDArray[bool_]]: """Check if the timestamps are plausible. Parameters ---------- t : np.ndarray Timestamps array. minimum : float Minimum plausible timestamp. maximum : float Maximum plausible timestamp. exp_min : int, default -15 Minimum plausible exponent used for the timestamps float values. exp_max : int, default 15 Maximum plausible exponent used for the timestamps float values. Returns ------- all_ok, idx : (bool, np.ndarray) The `all_ok` flag to indicate if all the timestamps are ok; this can be checked before applying the indexing array. """ exps = np.log10(t) idx = (~np.isnan(t)) & (~np.isinf(t)) & (t >= minimum) & (t <= maximum) & (t == 0) | ( (exps >= exp_min) & (exps <= exp_max) ) if not np.all(idx): all_ok = False return all_ok, idx else: all_ok = True return all_ok, idx table = str.maketrans( { "<": "<", ">": ">", "&": "&", "'": "'", '"': """, } ) def escape_xml_string(string: str) -> str: return string.translate(table) class SignalFlags: no_flags = 0x0 user_defined_comment = 0x1 user_defined_conversion = 0x2 user_defined_unit = 0x4 user_defined_name = 0x8 stream_sync = 0x10 computed = 0x20 virtual = 0x40 virtual_master = 0x80 _Params = ParamSpec("_Params") _Ret = TypeVar("_Ret") def timeit(func: Callable[_Params, _Ret]) -> Callable[_Params, _Ret]: def timed(*args: _Params.args, **kwargs: _Params.kwargs) -> _Ret: t1 = perf_counter() ret = func(*args, **kwargs) t2 = perf_counter() delta = t2 - t1 if delta >= 1e-3: print(f"CALL {func.__qualname__}: {delta * 1e3:.3f} ms") else: print(f"CALL {func.__qualname__}: {delta * 1e6:.3f} us") return ret return timed class Timer: def __init__(self, name: str = "") -> None: self.name = name or str(id(self)) self.count = 0 self.total_time = 0.0 def __enter__(self) -> "Timer": now = perf_counter() self.start = now return self def __exit__( self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: now = perf_counter() self.total_time += now - self.start self.count += 1 def display(self) -> None: if self.count: for factor, r, unit in ((1e3, 3, "ms"), (1e6, 6, "us"), (1e9, 9, "ns")): tpi = round(self.total_time / self.count, r) if tpi: break print( f"""TIMER {self.name}: \t* {self.count} iterations in {self.total_time * 1000:.3f}ms \t* {self.count / self.total_time:.3f} iter/s \t* {self.total_time / self.count * factor:.3f} {unit}/iter""" ) else: print(f"TIMER {self.name}:\n\t* inactive") asammdf-8.5.1/src/asammdf/blocks/v2_v3_blocks.py000066400000000000000000003541211502633300400214610ustar00rootroot00000000000000"""Classes that implement the blocks for MDF versions 2 and 3""" from collections.abc import Iterator, Sequence from datetime import datetime, timedelta, timezone from getpass import getuser import logging from struct import pack, unpack, unpack_from import sys from textwrap import wrap from traceback import format_exc import typing from typing import Final import xml.etree.ElementTree as ET import dateutil.tz from numexpr import evaluate import numpy as np from numpy.typing import ArrayLike, NDArray from typing_extensions import Any, overload, SupportsBytes, TypedDict, Unpack from .. import tool from . import utils from . import v2_v3_constants as v23c from .utils import ( BlockKwargs, get_fields, get_text_v3, MdfException, UINT16_u, UINT16_uf, ) try: from sympy import lambdify, symbols except: lambdify, symbols = None, None SEEK_START: Final = v23c.SEEK_START SEEK_END: Final = v23c.SEEK_END CHANNEL_DISPLAYNAME_u = v23c.CHANNEL_DISPLAYNAME_u CHANNEL_DISPLAYNAME_uf = v23c.CHANNEL_DISPLAYNAME_uf CHANNEL_LONGNAME_u = v23c.CHANNEL_LONGNAME_u CHANNEL_LONGNAME_uf = v23c.CHANNEL_LONGNAME_uf CHANNEL_SHORT_u = v23c.CHANNEL_SHORT_u CHANNEL_SHORT_uf = v23c.CHANNEL_SHORT_uf COMMON_uf = v23c.COMMON_uf COMMON_u = v23c.COMMON_u CONVERSION_COMMON_SHORT_uf = v23c.CONVERSION_COMMON_SHORT_uf SOURCE_COMMON_uf = v23c.SOURCE_COMMON_uf SOURCE_EXTRA_ECU_uf = v23c.SOURCE_EXTRA_ECU_uf SOURCE_EXTRA_VECTOR_uf = v23c.SOURCE_EXTRA_VECTOR_uf SOURCE_COMMON_u = v23c.SOURCE_COMMON_u SOURCE_EXTRA_ECU_u = v23c.SOURCE_EXTRA_ECU_u SOURCE_EXTRA_VECTOR_u = v23c.SOURCE_EXTRA_VECTOR_u logger = logging.getLogger("asammdf") __all__ = [ "Channel", "ChannelConversion", "ChannelDependency", "ChannelExtension", "ChannelGroup", "DataBlock", "DataGroup", "FileIdentificationBlock", "HeaderBlock", "ProgramBlock", "TextBlock", "TriggerBlock", ] class ChannelKwargs(BlockKwargs, total=False): parsed_strings: tuple[str, dict[str, str]] | None cc_map: dict[bytes | int, "ChannelConversion"] si_map: dict[bytes | int, "ChannelExtension"] block_len: int next_ch_addr: int conversion_addr: int source_addr: int component_addr: int comment_addr: int channel_type: int short_name: bytes description: bytes start_offset: int bit_count: int data_type: int range_flag: int min_raw_value: float max_raw_value: float sampling_rate: float long_name_addr: int display_name_addr: int additional_byte_offset: int class Channel: """CNBLOCK class. If the `load_metadata` keyword argument is not provided or is False, then the conversion, source and display name information is not processed. CNBLOCK fields: * ``id`` - bytes : block ID; always b'CN' * ``block_len`` - int : block bytes size * ``next_ch_addr`` - int : next CNBLOCK address * ``conversion_addr`` - int : address of channel conversion block * ``source_addr`` - int : address of channel source block * ``component_addr`` - int : address of dependency block (CDBLOCK) of this channel * ``comment_addr`` - int : address of TXBLOCK that contains the channel comment * ``channel_type`` - int : integer code for channel type * ``short_name`` - bytes : short signal name * ``description`` - bytes : signal description * ``start_offset`` - int : start offset in bits to determine the first bit of the signal in the data record * ``bit_count`` - int : channel bit count * ``data_type`` - int : integer code for channel data type * ``range_flag`` - int : value range valid flag * ``min_raw_value`` - float : min raw value of all samples * ``max_raw_value`` - float : max raw value of all samples * ``sampling_rate`` - float : sampling rate in *'s'* for a virtual time channel * ``long_name_addr`` - int : address of TXBLOCK that contains the channel's name * ``display_name_addr`` - int : address of TXBLOCK that contains the channel's display name * ``additional_byte_offset`` - int : additional Byte offset of the channel in the data record Other attributes: * ``address`` - int : block address inside MDF file * ``comment`` - str : channel comment * ``conversion`` - ChannelConversion : channel conversion; None if the channel has no conversion * ``display_names`` - dict : channel display names .. versionchanged:: 7.0.0 Changed from str to dict. * ``name`` - str : full channel name * ``source`` - SourceInformation : channel source information; None if the channel has no source information Parameters ---------- address : int Block address; to be used for objects created from file. stream : handle File handle; to be used for objects created from file. load_metadata : bool Option to load conversion, source and display_names; default is True. for dynamically created objects : See the key-value pairs. Examples -------- >>> with open('test.mdf', 'rb') as mdf: ... ch1 = Channel(stream=mdf, address=0xBA52) >>> ch2 = Channel() >>> ch1.name 'VehicleSpeed' >>> ch1['id'] b'CN' """ __slots__ = ( "additional_byte_offset", "address", "bit_count", "block_len", "channel_type", "comment", "comment_addr", "component_addr", "conversion", "conversion_addr", "data_type", "description", "display_name_addr", "display_names", "dtype_fmt", "id", "long_name_addr", "max_raw_value", "min_raw_value", "name", "next_ch_addr", "range_flag", "sampling_rate", "short_name", "source", "source_addr", "start_offset", "unit", ) def __init__(self, **kwargs: Unpack[ChannelKwargs]) -> None: super().__init__() self.name = self.comment = self.unit = "" self.display_names: dict[str, str] = {} self.conversion = self.source = None self.dtype_fmt: np.dtype[Any] | None = None try: stream = kwargs["stream"] self.address = address = kwargs["address"] mapped = kwargs.get("mapped", False) if utils.stream_is_mmap(stream, mapped): (size,) = UINT16_uf(stream, address + 2) if size == v23c.CN_DISPLAYNAME_BLOCK_SIZE: ( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, self.long_name_addr, self.display_name_addr, self.additional_byte_offset, ) = CHANNEL_DISPLAYNAME_uf(stream, address) parsed_strings = kwargs["parsed_strings"] if parsed_strings is None: addr = self.long_name_addr if addr: self.name = get_text_v3(address=addr, stream=stream, mapped=mapped) else: self.name = self.short_name.decode("latin-1").strip(" \t\n\r\0") addr = self.display_name_addr if addr: self.display_names = { get_text_v3(address=addr, stream=stream, mapped=mapped): "display_name", } else: self.name, self.display_names = parsed_strings elif size == v23c.CN_LONGNAME_BLOCK_SIZE: ( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, self.long_name_addr, ) = CHANNEL_LONGNAME_uf(stream, address) parsed_strings = kwargs["parsed_strings"] if parsed_strings is None: addr = self.long_name_addr if addr: self.name = get_text_v3(address=addr, stream=stream, mapped=mapped) else: self.name = self.short_name.decode("latin-1").strip(" \t\n\r\0") else: self.name, self.display_names = parsed_strings else: ( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, ) = CHANNEL_SHORT_uf(stream, address) self.name = self.short_name.decode("latin-1").strip(" \t\n\r\0") cc_map = kwargs.get("cc_map", {}) si_map = kwargs.get("si_map", {}) address = self.conversion_addr if address: try: if address in cc_map: conv = cc_map[address] else: (size,) = UINT16_uf(stream, address + 2) raw_bytes = stream[address : address + size] if raw_bytes in cc_map: conv = cc_map[raw_bytes] else: conv = ChannelConversion( raw_bytes=raw_bytes, stream=stream, address=address, mapped=mapped, ) cc_map[raw_bytes] = cc_map[address] = conv except: logger.warning( f"Channel conversion parsing error: {format_exc()}. The error is ignored and the channel conversion is None" ) conv = None self.conversion = conv address = self.source_addr if address: try: if address in si_map: source = si_map[address] else: raw_bytes = stream[address : address + v23c.CE_BLOCK_SIZE] if raw_bytes in si_map: source = si_map[raw_bytes] else: source = ChannelExtension( raw_bytes=raw_bytes, stream=stream, address=address, mapped=mapped, ) si_map[raw_bytes] = si_map[address] = source except: logger.warning( f"Channel source parsing error: {format_exc()}. The error is ignored and the channel source is None" ) source = None self.source = source self.comment = get_text_v3(address=self.comment_addr, stream=stream, mapped=mapped) else: stream.seek(address + 2) (size,) = UINT16_u(stream.read(2)) stream.seek(address) block = stream.read(size) if size == v23c.CN_DISPLAYNAME_BLOCK_SIZE: ( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, self.long_name_addr, self.display_name_addr, self.additional_byte_offset, ) = CHANNEL_DISPLAYNAME_u(block) parsed_strings = kwargs["parsed_strings"] if parsed_strings is None: addr = self.long_name_addr if addr: self.name = get_text_v3(address=addr, stream=stream, mapped=mapped) else: self.name = self.short_name.decode("latin-1").strip(" \t\n\r\0") addr = self.display_name_addr if addr: self.display_names = { get_text_v3(address=addr, stream=stream, mapped=mapped): "display_name", } else: self.name, self.display_names = parsed_strings elif size == v23c.CN_LONGNAME_BLOCK_SIZE: ( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, self.long_name_addr, ) = CHANNEL_LONGNAME_u(block) parsed_strings = kwargs["parsed_strings"] if parsed_strings is None: addr = self.long_name_addr if addr: self.name = get_text_v3(address=addr, stream=stream, mapped=mapped) else: self.name = self.short_name.decode("latin-1").strip(" \t\n\r\0") else: self.name, self.display_names = parsed_strings else: ( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, ) = CHANNEL_SHORT_u(block) self.name = self.short_name.decode("latin-1").strip(" \t\n\r\0") cc_map = kwargs.get("cc_map", {}) si_map = kwargs.get("si_map", {}) address = self.conversion_addr if address: try: if address in cc_map: conv = cc_map[address] else: stream.seek(address + 2) (size,) = UINT16_u(stream.read(2)) stream.seek(address) raw_bytes = stream.read(size) if raw_bytes in cc_map: conv = cc_map[raw_bytes] else: conv = ChannelConversion( raw_bytes=raw_bytes, stream=stream, address=address, mapped=mapped, ) cc_map[raw_bytes] = cc_map[address] = conv except: logger.warning( f"Channel conversion parsing error: {format_exc()}. The error is ignored and the channel conversion is None" ) conv = None self.conversion = conv address = self.source_addr if address: try: if address in si_map: source = si_map[address] else: stream.seek(address) raw_bytes = stream.read(v23c.CE_BLOCK_SIZE) if raw_bytes in si_map: source = si_map[raw_bytes] else: source = ChannelExtension( raw_bytes=raw_bytes, stream=stream, address=address, mapped=mapped, ) si_map[raw_bytes] = si_map[address] = source except: logger.warning( f"Channel source parsing error: {format_exc()}. The error is ignored and the channel source is None" ) source = None self.source = source self.comment = get_text_v3(address=self.comment_addr, stream=stream, mapped=mapped) if self.id != b"CN": message = f'Expected "CN" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) except KeyError: self.address = 0 self.id = b"CN" self.block_len = kwargs.get("block_len", v23c.CN_DISPLAYNAME_BLOCK_SIZE) self.next_ch_addr = kwargs.get("next_ch_addr", 0) self.conversion_addr = kwargs.get("conversion_addr", 0) self.source_addr = kwargs.get("source_addr", 0) self.component_addr = kwargs.get("component_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.channel_type = kwargs.get("channel_type", 0) self.short_name = kwargs.get("short_name", (b"\0" * 32)) self.description = kwargs.get("description", (b"\0" * 128)) self.start_offset = kwargs.get("start_offset", 0) self.bit_count = kwargs.get("bit_count", 8) self.data_type = kwargs.get("data_type", 0) self.range_flag = kwargs.get("range_flag", 1) self.min_raw_value = kwargs.get("min_raw_value", 0) self.max_raw_value = kwargs.get("max_raw_value", 0) self.sampling_rate = kwargs.get("sampling_rate", 0) if self.block_len >= v23c.CN_LONGNAME_BLOCK_SIZE: self.long_name_addr = kwargs.get("long_name_addr", 0) if self.block_len >= v23c.CN_DISPLAYNAME_BLOCK_SIZE: self.display_name_addr = kwargs.get("display_name_addr", 0) self.additional_byte_offset = kwargs.get("additional_byte_offset", 0) if self.name in self.display_names: del self.display_names[self.name] def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int], cc_map: dict[bytes, int], si_map: dict[bytes, int], ) -> int: text = self.name if self.block_len >= v23c.CN_LONGNAME_BLOCK_SIZE: if len(text) > 31: if text in defined_texts: self.long_name_addr = defined_texts[text] else: tx_block = TextBlock(text=text) self.long_name_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.long_name_addr = 0 self.short_name = text.encode("latin-1", "backslashreplace")[:31] text = list(self.display_names)[0] if self.display_names else "" if self.block_len >= v23c.CN_DISPLAYNAME_BLOCK_SIZE: if text: if text in defined_texts: self.display_name_addr = defined_texts[text] else: tx_block = TextBlock(text=text) self.display_name_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.display_name_addr = 0 text = self.comment if text: if len(text) < 128: self.description = text.encode("latin-1", "backslashreplace")[:127] self.comment_addr = 0 else: if text in defined_texts: self.comment_addr = defined_texts[text] else: tx_block = TextBlock(text=text) self.comment_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) self.description = b"\0" else: self.comment_addr = 0 conversion = self.conversion if conversion: address = conversion.to_blocks(address, blocks, defined_texts, cc_map) self.conversion_addr = conversion.address else: self.conversion_addr = 0 source = self.source if source: address = source.to_blocks(address, blocks, defined_texts, si_map) self.source_addr = source.address else: self.source_addr = 0 blocks.append(self) self.address = address address += self.block_len return address def metadata(self) -> str: max_len = max(len(key) for key in self) template = f"{{: <{max_len}}}: {{}}" metadata: list[str] = [] lines = f""" name: {self.name} display names: {self.display_names} address: {hex(self.address)} comment: {self.comment} """.split("\n") keys = ( "id", "block_len", "next_ch_addr", "conversion_addr", "source_addr", "component_addr", "comment_addr", "channel_type", "short_name", "description", "start_offset", "bit_count", "data_type", "range_flag", "min_raw_value", "max_raw_value", "sampling_rate", "long_name_addr", "display_name_addr", "additional_byte_offset", ) for key in keys: if not hasattr(self, key): continue val = getattr(self, key) if key.endswith("addr") or key.startswith("text_"): lines.append(template.format(key, hex(val))) elif isinstance(val, float): lines.append(template.format(key, val)) else: if isinstance(val, bytes): lines.append(template.format(key, val.strip(b"\0"))) else: lines.append(template.format(key, val)) if key == "data_type": lines[-1] += f" = {v23c.DATA_TYPE_TO_STRING[self.data_type]}" elif key == "channel_type": lines[-1] += f" = {v23c.CHANNEL_TYPE_TO_STRING[self.channel_type]}" for line in lines: if not line: metadata.append(line) else: for wrapped_line in wrap(line, width=120): metadata.append(wrapped_line) return "\n".join(metadata) def __bytes__(self) -> bytes: block_len = self.block_len if block_len == v23c.CN_DISPLAYNAME_BLOCK_SIZE: return v23c.CHANNEL_DISPLAYNAME_p( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, self.long_name_addr, self.display_name_addr, self.additional_byte_offset, ) elif block_len == v23c.CN_LONGNAME_BLOCK_SIZE: return v23c.CHANNEL_LONGNAME_p( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, self.long_name_addr, ) else: return v23c.CHANNEL_SHORT_p( self.id, self.block_len, self.next_ch_addr, self.conversion_addr, self.source_addr, self.component_addr, self.comment_addr, self.channel_type, self.short_name, self.description, self.start_offset, self.bit_count, self.data_type, self.range_flag, self.min_raw_value, self.max_raw_value, self.sampling_rate, ) def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __contains__(self, item: str) -> bool: return hasattr(self, item) def __iter__(self) -> Iterator[str]: for attr in dir(self): if attr[:2] + attr[-2:] == "____": continue try: if callable(getattr(self, attr)): continue yield attr except AttributeError: continue def __lt__(self, other: "Channel") -> int: self_start = self.start_offset other_start = other.start_offset try: self_additional_offset = self.additional_byte_offset if self_additional_offset: self_start += 8 * self_additional_offset other_additional_offset = other.additional_byte_offset if other_additional_offset: other_start += 8 * other_additional_offset except AttributeError: pass if self_start < other_start: result = 1 elif self_start == other_start: if self.bit_count >= other.bit_count: result = 1 else: result = 0 else: result = 0 return result def __repr__(self) -> str: fields = [] for attr in dir(self): if attr[:2] + attr[-2:] == "____": continue try: if callable(getattr(self, attr)): continue fields.append(f"{attr}:{getattr(self, attr)}") except AttributeError: continue return f"Channel (name: {self.name}, display names: {self.display_names}, comment: {self.comment}, address: {hex(self.address)}, fields: {fields})" class _ChannelConversionBase: __slots__ = ( "P1", "P2", "P3", "P4", "P5", "P6", "P7", "a", "address", "b", "block_len", "comment_addr", "conversion_type", "flags", "formula", "formula_field", "id", "inv_conv_addr", "max_phy_value", "min_phy_value", "precision", "ref_param_nr", "referenced_blocks", "reserved0", "unit", "unit_field", "val_param_nr", ) class ChannelConversionKwargs(BlockKwargs, total=False): raw_bytes: bytes unit: bytes conversion_type: int range_flag: int min_phy_value: float max_phy_value: float b: float a: float P1: float P2: float P3: float P4: float P5: float P6: float P7: float formula: bytes | str ref_param_nr: int CANapeHiddenExtra: bytes default_addr: bytes class ChannelConversion(_ChannelConversionBase): """CCBLOCK class. `ChannelConversion` has the following common fields: * ``id`` - bytes : block ID; always b'CC' * ``block_len`` - int : block bytes size * ``range_flag`` - int : value range valid flag * ``min_phy_value`` - float : min raw value of all samples * ``max_phy_value`` - float : max raw value of all samples * ``unit`` - bytes : physical unit * ``conversion_type`` - int : integer code for conversion type * ``ref_param_nr`` - int : number of referenced parameters `ChannelConversion` has the following specific fields: * linear conversion * ``a`` - float : factor * ``b`` - float : offset * ``CANapeHiddenExtra`` - bytes : sometimes CANape appends extra information; not compliant with MDF specs * algebraic conversion * ``formula`` - bytes : equation as string * polynomial or rational conversion * ``P1`` to ``P6`` - float : parameters * exponential or logarithmic conversion * ``P1`` to ``P7`` - float : parameters * tabular with or without interpolation (grouped by index) * ``raw_`` - int : N-th raw value (X axis) * ``phys_`` - float : N-th physical value (Y axis) * text table conversion * ``param_val_`` - int : N-th raw value (X axis) * ``text_`` - N-th text physical value (Y axis) * text range table conversion * ``default_lower`` - float : default lower raw value * ``default_upper`` - float : default upper raw value * ``default_addr`` - int : address of default text physical value * ``lower_`` - float : N-th lower raw value * ``upper_`` - float : N-th upper raw value * ``text_`` - int : address of N-th text physical value Other attributes: * ``address`` - int : block address inside MDF file * ``formula`` - str : formula string in case of algebraic conversion * ``referenced_blocks`` - list : list of CCBLOCK/TXBLOCK referenced by the conversion * ``unit`` - str : physical unit Parameters ---------- address : int Block address inside MDF file. raw_bytes : bytes Complete block read from disk. stream : file handle MDF file handle. for dynamically created objects : See the key-value pairs. Examples -------- >>> with open('test.mdf', 'rb') as mdf: ... cc1 = ChannelConversion(stream=mdf, address=0xBA52) >>> cc2 = ChannelConversion(conversion_type=0) >>> cc1['b'], cc1['a'] 0, 100.0 """ def __init__(self, **kwargs: Unpack[ChannelConversionKwargs]) -> None: super().__init__() self.is_user_defined = False self.unit = self.formula = "" self.referenced_blocks: dict[str, bytes | ChannelConversion] = {} if "raw_bytes" in kwargs or "stream" in kwargs: mapped = kwargs.get("mapped", False) self.address = address = kwargs.get("address", 0) try: block = kwargs["raw_bytes"] (self.id, self.block_len) = COMMON_uf(block) size = self.block_len block_size = len(block) block = block[4:] stream = kwargs["stream"] except KeyError: stream = kwargs["stream"] if utils.stream_is_mmap(stream, mapped): (self.id, self.block_len) = COMMON_uf(stream, address) block_size = size = self.block_len block = stream[address + 4 : address + size] else: stream.seek(address) block = stream.read(4) (self.id, self.block_len) = COMMON_u(block) block_size = size = self.block_len block = stream.read(size - 4) ( self.range_flag, self.min_phy_value, self.max_phy_value, self.unit_field, self.conversion_type, self.ref_param_nr, ) = CONVERSION_COMMON_SHORT_uf(block) self.unit = self.unit_field.decode("latin-1").strip(" \t\r\n\0") conv_type = self.conversion_type if conv_type == v23c.CONVERSION_TYPE_LINEAR: (self.b, self.a) = typing.cast( tuple[float, float], unpack_from("<2d", block, v23c.CC_COMMON_SHORT_SIZE) ) if size != v23c.CC_LIN_BLOCK_SIZE: self.CANapeHiddenExtra = block[v23c.CC_LIN_BLOCK_SIZE - 4 :] size = len(self.CANapeHiddenExtra) nr = size // 40 values = unpack_from("<" + "d32s" * nr, block, v23c.CC_COMMON_SHORT_SIZE) for i in range(nr): (self[f"param_val_{i}"], self[f"text_{i}"]) = ( values[i * 2], values[2 * i + 1], ) elif conv_type == v23c.CONVERSION_TYPE_NONE: pass elif conv_type == v23c.CONVERSION_TYPE_FORMULA: self.formula_field = block[v23c.CC_COMMON_SHORT_SIZE :] self.formula = self.formula_field.decode("latin-1").strip(" \t\r\n\0").replace("x", "X") if "X1" not in self.formula: self.formula = self.formula.replace("X", "X1") elif conv_type in (v23c.CONVERSION_TYPE_TABI, v23c.CONVERSION_TYPE_TAB): nr = self.ref_param_nr size = v23c.CC_COMMON_BLOCK_SIZE + nr * 16 if block_size == v23c.MAX_UINT16: stream.seek(address) raw_bytes = stream.read(size) conversion = ChannelConversion(raw_bytes=raw_bytes, stream=stream, address=address) conversion.block_len = size # self.update(conversion) self.referenced_blocks = conversion.referenced_blocks else: float_values: tuple[float, ...] = unpack_from(f"<{2 * nr}d", block, v23c.CC_COMMON_SHORT_SIZE) for i in range(nr): (self[f"raw_{i}"], self[f"phys_{i}"]) = ( float_values[i * 2], float_values[2 * i + 1], ) elif conv_type in (v23c.CONVERSION_TYPE_POLY, v23c.CONVERSION_TYPE_RAT): (self.P1, self.P2, self.P3, self.P4, self.P5, self.P6) = typing.cast( tuple[float, float, float, float, float, float], unpack_from("<6d", block, v23c.CC_COMMON_SHORT_SIZE), ) elif conv_type in (v23c.CONVERSION_TYPE_EXPO, v23c.CONVERSION_TYPE_LOGH): ( self.P1, self.P2, self.P3, self.P4, self.P5, self.P6, self.P7, ) = typing.cast( tuple[float, float, float, float, float, float, float], unpack_from("<7d", block, v23c.CC_COMMON_SHORT_SIZE), ) elif conv_type == v23c.CONVERSION_TYPE_TABX: nr = self.ref_param_nr size = v23c.CC_COMMON_BLOCK_SIZE + nr * 40 if block_size == v23c.MAX_UINT16: stream.seek(address) raw_bytes = stream.read(size) conversion = ChannelConversion(raw_bytes=raw_bytes, stream=stream, address=address) conversion.block_len = size for attr in get_fields(conversion): setattr(self, attr, getattr(conversion, attr)) self.referenced_blocks = conversion.referenced_blocks else: values = unpack_from("<" + "d32s" * nr, block, v23c.CC_COMMON_SHORT_SIZE) for i in range(nr): (self[f"param_val_{i}"], self[f"text_{i}"]) = ( values[i * 2], values[2 * i + 1], ) elif conv_type == v23c.CONVERSION_TYPE_RTABX: nr = self.ref_param_nr - 1 size = v23c.CC_COMMON_BLOCK_SIZE + (nr + 1) * 20 if block_size == v23c.MAX_UINT16: stream.seek(address) raw_bytes = stream.read(size) conversion = ChannelConversion(raw_bytes=raw_bytes, stream=stream, address=address) conversion.block_len = size for attr in get_fields(conversion): setattr(self, attr, getattr(conversion, attr)) self.referenced_blocks = conversion.referenced_blocks else: ( self.default_lower, self.default_upper, self.default_addr, ) = typing.cast(tuple[float, float, int], unpack_from("<2dI", block, v23c.CC_COMMON_SHORT_SIZE)) if self.default_addr: self.referenced_blocks["default_addr"] = get_text_v3( address=self.default_addr, stream=stream, mapped=mapped, decode=False, ) else: self.referenced_blocks["default_addr"] = b"" values = unpack_from("<" + "2dI" * nr, block, v23c.CC_COMMON_SHORT_SIZE + 20) for i in range(nr): (self[f"lower_{i}"], self[f"upper_{i}"], self[f"text_{i}"]) = ( values[i * 3], values[3 * i + 1], values[3 * i + 2], ) if values[3 * i + 2]: block = get_text_v3( address=values[3 * i + 2], stream=stream, mapped=mapped, decode=False, ) self.referenced_blocks[f"text_{i}"] = block else: self.referenced_blocks[f"text_{i}"] = b"" if self.id != b"CC": message = f'Expected "CC" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) else: self.address = 0 self.id = b"CC" self.unit_field = kwargs.get("unit", b"") if kwargs["conversion_type"] == v23c.CONVERSION_TYPE_NONE: self.block_len = v23c.CC_COMMON_BLOCK_SIZE self.range_flag = kwargs.get("range_flag", 1) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.unit_field = kwargs.get("unit", ("\0" * 20).encode("latin-1")) self.conversion_type = v23c.CONVERSION_TYPE_NONE self.ref_param_nr = 0 elif kwargs["conversion_type"] == v23c.CONVERSION_TYPE_LINEAR: self.block_len = v23c.CC_LIN_BLOCK_SIZE self.range_flag = kwargs.get("range_flag", 1) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.unit_field = kwargs.get("unit", ("\0" * 20).encode("latin-1")) self.conversion_type = v23c.CONVERSION_TYPE_LINEAR self.ref_param_nr = 2 self.b = kwargs.get("b", 0) self.a = kwargs.get("a", 1) if self.block_len != v23c.CC_LIN_BLOCK_SIZE: self.CANapeHiddenExtra = kwargs["CANapeHiddenExtra"] elif kwargs["conversion_type"] in ( v23c.CONVERSION_TYPE_POLY, v23c.CONVERSION_TYPE_RAT, ): self.block_len = v23c.CC_POLY_BLOCK_SIZE self.range_flag = kwargs.get("range_flag", 1) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.unit_field = kwargs.get("unit", ("\0" * 20).encode("latin-1")) self.conversion_type = kwargs["conversion_type"] self.ref_param_nr = 6 self.P1 = kwargs.get("P1", 0) self.P2 = kwargs.get("P2", 0) self.P3 = kwargs.get("P3", 0) self.P4 = kwargs.get("P4", 0) self.P5 = kwargs.get("P5", 0) self.P6 = kwargs.get("P6", 0) elif kwargs["conversion_type"] in ( v23c.CONVERSION_TYPE_EXPO, v23c.CONVERSION_TYPE_LOGH, ): self.block_len = v23c.CC_EXPO_BLOCK_SIZE self.range_flag = kwargs.get("range_flag", 1) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.unit_field = kwargs.get("unit", ("\0" * 20).encode("latin-1")) self.conversion_type = kwargs["conversion_type"] self.ref_param_nr = 7 self.P1 = kwargs.get("P1", 0) self.P2 = kwargs.get("P2", 0) self.P3 = kwargs.get("P3", 0) self.P4 = kwargs.get("P4", 0) self.P5 = kwargs.get("P5", 0) self.P6 = kwargs.get("P6", 0) self.P7 = kwargs.get("P7", 0) elif kwargs["conversion_type"] == v23c.CONVERSION_TYPE_FORMULA: formula = kwargs["formula"] formula_len = len(formula) if isinstance(formula, bytes): self.formula = formula.decode("latin-1") formula += b"\0" else: self.formula = formula formula = formula.encode("latin-1") + b"\0" self.block_len = 46 + formula_len + 1 self.range_flag = kwargs.get("range_flag", 1) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.unit_field = kwargs.get("unit", ("\0" * 20).encode("latin-1")) self.conversion_type = v23c.CONVERSION_TYPE_FORMULA self.ref_param_nr = formula_len self.formula_field = formula elif kwargs["conversion_type"] in ( v23c.CONVERSION_TYPE_TABI, v23c.CONVERSION_TYPE_TAB, ): nr = kwargs["ref_param_nr"] self.block_len = v23c.CC_COMMON_BLOCK_SIZE + nr * 2 * 8 self.range_flag = kwargs.get("range_flag", 1) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.unit_field = kwargs.get("unit", ("\0" * 20).encode("latin-1")) self.conversion_type = kwargs["conversion_type"] self.ref_param_nr = nr for i in range(nr): self[f"raw_{i}"] = kwargs[f"raw_{i}"] # type: ignore[literal-required] self[f"phys_{i}"] = kwargs[f"phys_{i}"] # type: ignore[literal-required] elif kwargs["conversion_type"] == v23c.CONVERSION_TYPE_TABX: nr = kwargs["ref_param_nr"] self.block_len = v23c.CC_COMMON_BLOCK_SIZE + 40 * nr self.range_flag = kwargs.get("range_flag", 0) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.unit_field = kwargs.get("unit", ("\0" * 20).encode("latin-1")) self.conversion_type = v23c.CONVERSION_TYPE_TABX self.ref_param_nr = nr for i in range(nr): self[f"param_val_{i}"] = kwargs[f"param_val_{i}"] # type: ignore[literal-required] self[f"text_{i}"] = kwargs[f"text_{i}"] # type: ignore[literal-required] elif kwargs["conversion_type"] == v23c.CONVERSION_TYPE_RTABX: nr = kwargs["ref_param_nr"] self.block_len = v23c.CC_COMMON_BLOCK_SIZE + 20 * nr self.range_flag = kwargs.get("range_flag", 0) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.unit_field = kwargs.get("unit", ("\0" * 20).encode("latin-1")) self.conversion_type = v23c.CONVERSION_TYPE_RTABX self.ref_param_nr = nr self.default_lower = 0 self.default_upper = 0 self.default_addr = 0 key = "default_addr" if key in kwargs: self.referenced_blocks[key] = kwargs[key] # type: ignore[literal-required] else: self.referenced_blocks[key] = b"" for i in range(nr - 1): self[f"lower_{i}"] = kwargs[f"lower_{i}"] # type: ignore[literal-required] self[f"upper_{i}"] = kwargs[f"upper_{i}"] # type: ignore[literal-required] key = f"text_{i}" self.default_addr = 0 self.referenced_blocks[key] = kwargs[key] # type: ignore[literal-required] else: message = f'Conversion type "{kwargs["conversion_type"]}" not implemented' logger.exception(message) raise MdfException(message) def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int], cc_map: dict[bytes, int], ) -> int: self.unit_field = self.unit.encode("latin-1", "ignore")[:19] if self.conversion_type == v23c.CONVERSION_TYPE_FORMULA: formula = self.formula if not formula.endswith("\0"): formula += "\0" self.formula_field = formula.encode("latin-1") self.block_len = v23c.CC_COMMON_BLOCK_SIZE + len(self.formula_field) for key, block in self.referenced_blocks.items(): if block: if isinstance(block, ChannelConversion): address = block.to_blocks(address, blocks, defined_texts, cc_map) self[key] = block.address else: text = block if text in defined_texts: self[key] = defined_texts[text] else: tx_block = TextBlock(text=text) defined_texts[text] = address blocks.append(tx_block) self[key] = address address += tx_block.block_len else: self[key] = 0 bts = bytes(self) if bts in cc_map: self.address = cc_map[bts] else: blocks.append(bts) self.address = address cc_map[bts] = address size = self.block_len address += len(bts) return address def metadata(self, indent: str = "") -> str: conv = self.conversion_type keys: Sequence[str] if conv == v23c.CONVERSION_TYPE_NONE: keys = v23c.KEYS_CONVERSION_NONE elif conv == v23c.CONVERSION_TYPE_FORMULA: keys = v23c.KEYS_CONVERSION_FORMULA elif conv == v23c.CONVERSION_TYPE_LINEAR: keys = v23c.KEYS_CONVERSION_LINEAR if self.block_len != v23c.CC_LIN_BLOCK_SIZE: keys += ("CANapeHiddenExtra",) nr = self.ref_param_nr new_keys: list[str] = [] for i in range(nr): new_keys.extend((f"param_val_{i}", f"text_{i}")) keys += tuple(new_keys) elif conv in (v23c.CONVERSION_TYPE_POLY, v23c.CONVERSION_TYPE_RAT): keys = v23c.KEYS_CONVERSION_POLY_RAT elif conv in (v23c.CONVERSION_TYPE_EXPO, v23c.CONVERSION_TYPE_LOGH): keys = v23c.KEYS_CONVERSION_EXPO_LOGH elif conv in (v23c.CONVERSION_TYPE_TABI, v23c.CONVERSION_TYPE_TAB): nr = self.ref_param_nr keys = list(v23c.KEYS_CONVERSION_NONE) for i in range(nr): keys.append(f"raw_{i}") keys.append(f"phys_{i}") elif conv == v23c.CONVERSION_TYPE_RTABX: nr = self.ref_param_nr keys = list(v23c.KEYS_CONVERSION_NONE) keys += ["default_lower", "default_upper", "default_addr"] for i in range(nr - 1): keys.append(f"lower_{i}") keys.append(f"upper_{i}") keys.append(f"text_{i}") elif conv == v23c.CONVERSION_TYPE_TABX: nr = self.ref_param_nr keys = list(v23c.KEYS_CONVERSION_NONE) for i in range(nr): keys.append(f"param_val_{i}") keys.append(f"text_{i}") max_len = max(len(key) for key in keys) template = f"{{: <{max_len}}}: {{}}" metadata: list[str] = [] lines = f""" address: {hex(self.address)} """.split("\n") for key in keys: val = getattr(self, key) if key.endswith("addr") or (key.startswith("text_") and isinstance(val, int)): lines.append(template.format(key, hex(val))) elif isinstance(val, float): lines.append(template.format(key, val)) else: if isinstance(val, bytes): lines.append(template.format(key, val.strip(b"\0"))) else: lines.append(template.format(key, val)) if key == "conversion_type": lines[-1] += f" [{v23c.CONVERSION_TYPE_TO_STRING[self.conversion_type]}]" elif self.referenced_blocks and key in self.referenced_blocks: val = self.referenced_blocks[key] if isinstance(val, bytes): lines[-1] += f" (= {str(val)[1:]})" else: lines[-1] += f" (= CCBLOCK @ {hex(val.address)})" if self.referenced_blocks: max_len = max(len(key) for key in self.referenced_blocks) template = f"{{: <{max_len}}}: {{}}" lines.append("") lines.append("Referenced blocks:") for key, block in self.referenced_blocks.items(): if isinstance(block, ChannelConversion): lines.append(template.format(key, "")) lines.extend(block.metadata(indent + " ").split("\n")) else: lines.append(template.format(key, str(block)[1:])) for line in lines: if not line: metadata.append(line) else: for wrapped_line in wrap(line, initial_indent=indent, subsequent_indent=indent, width=120): metadata.append(wrapped_line) return "\n".join(metadata) @overload def convert( self, values: NDArray[Any], as_object: bool = ..., as_bytes: bool = ..., ignore_value2text_conversions: bool = ..., ) -> NDArray[Any]: ... @overload def convert( self, values: ArrayLike, as_object: bool = ..., as_bytes: bool = ..., ignore_value2text_conversions: bool = ..., ) -> NDArray[Any] | np.number[Any]: ... def convert( self, values: ArrayLike, as_object: bool = False, as_bytes: bool = False, ignore_value2text_conversions: bool = False, ) -> NDArray[Any] | np.number[Any]: conversion_type = self.conversion_type scalar = False if not isinstance(values, np.ndarray): if isinstance(values, (int, float)): new_values = np.array([values]) scalar = True else: new_values = np.array(values) else: new_values = values if conversion_type == v23c.CONVERSION_TYPE_NONE: pass elif conversion_type == v23c.CONVERSION_TYPE_LINEAR: a = self.a b = self.b if (a, b) != (1, 0): new_values = new_values * a if b: new_values += b elif conversion_type in (v23c.CONVERSION_TYPE_TABI, v23c.CONVERSION_TYPE_TAB): nr = self.ref_param_nr raw_vals = np.array([self[f"raw_{i}"] for i in range(nr)]) phys = np.array([self[f"phys_{i}"] for i in range(nr)]) if conversion_type == v23c.CONVERSION_TYPE_TABI: new_values = np.interp(new_values, raw_vals, phys) else: dim = raw_vals.shape[0] inds = np.searchsorted(raw_vals, new_values) inds[inds >= dim] = dim - 1 # type: ignore[index, unused-ignore] inds2 = inds - 1 inds2[inds2 < 0] = 0 # type: ignore[index, unused-ignore] cond = np.abs(new_values - raw_vals[inds]) >= np.abs(new_values - raw_vals[inds2]) new_values = np.where(cond, phys[inds2], phys[inds]) elif conversion_type == v23c.CONVERSION_TYPE_TABX: if not ignore_value2text_conversions: nr = self.ref_param_nr raw_vals = np.array([self[f"param_val_{i}"] for i in range(nr)]) phys = np.array([self[f"text_{i}"] for i in range(nr)]) x = sorted(zip(raw_vals, phys, strict=False)) raw_vals = np.array([e[0] for e in x], dtype=" object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: conv = self.conversion_type # compute the fmt if conv == v23c.CONVERSION_TYPE_NONE: fmt = v23c.FMT_CONVERSION_COMMON elif conv == v23c.CONVERSION_TYPE_FORMULA: fmt = v23c.FMT_CONVERSION_FORMULA.format(self.block_len - v23c.CC_COMMON_BLOCK_SIZE) elif conv == v23c.CONVERSION_TYPE_LINEAR: fmt = v23c.FMT_CONVERSION_LINEAR if self.block_len != v23c.CC_LIN_BLOCK_SIZE: fmt += f"{self.block_len - v23c.CC_LIN_BLOCK_SIZE}s" elif conv in (v23c.CONVERSION_TYPE_POLY, v23c.CONVERSION_TYPE_RAT): fmt = v23c.FMT_CONVERSION_POLY_RAT elif conv in (v23c.CONVERSION_TYPE_EXPO, v23c.CONVERSION_TYPE_LOGH): fmt = v23c.FMT_CONVERSION_EXPO_LOGH elif conv in (v23c.CONVERSION_TYPE_TABI, v23c.CONVERSION_TYPE_TAB): nr = self.ref_param_nr fmt = v23c.FMT_CONVERSION_COMMON + f"{2 * nr}d" elif conv == v23c.CONVERSION_TYPE_RTABX: nr = self.ref_param_nr fmt = v23c.FMT_CONVERSION_COMMON + "2dI" * nr elif conv == v23c.CONVERSION_TYPE_TABX: nr = self.ref_param_nr fmt = v23c.FMT_CONVERSION_COMMON + "d32s" * nr keys: Sequence[str] if conv == v23c.CONVERSION_TYPE_NONE: keys = v23c.KEYS_CONVERSION_NONE elif conv == v23c.CONVERSION_TYPE_FORMULA: keys = v23c.KEYS_CONVERSION_FORMULA elif conv == v23c.CONVERSION_TYPE_LINEAR: keys = v23c.KEYS_CONVERSION_LINEAR if self.block_len != v23c.CC_LIN_BLOCK_SIZE: keys += ("CANapeHiddenExtra",) elif conv in (v23c.CONVERSION_TYPE_POLY, v23c.CONVERSION_TYPE_RAT): keys = v23c.KEYS_CONVERSION_POLY_RAT elif conv in (v23c.CONVERSION_TYPE_EXPO, v23c.CONVERSION_TYPE_LOGH): keys = v23c.KEYS_CONVERSION_EXPO_LOGH elif conv in (v23c.CONVERSION_TYPE_TABI, v23c.CONVERSION_TYPE_TAB): nr = self.ref_param_nr keys = list(v23c.KEYS_CONVERSION_NONE) for i in range(nr): keys.append(f"raw_{i}") keys.append(f"phys_{i}") elif conv == v23c.CONVERSION_TYPE_RTABX: nr = self.ref_param_nr keys = list(v23c.KEYS_CONVERSION_NONE) keys += ["default_lower", "default_upper", "default_addr"] for i in range(nr - 1): keys.append(f"lower_{i}") keys.append(f"upper_{i}") keys.append(f"text_{i}") elif conv == v23c.CONVERSION_TYPE_TABX: nr = self.ref_param_nr keys = list(v23c.KEYS_CONVERSION_NONE) for i in range(nr): keys.append(f"param_val_{i}") keys.append(f"text_{i}") self.block_len = min(self.block_len, v23c.MAX_UINT16) result = pack(fmt, *[self[key] for key in keys]) return result def __str__(self) -> str: fields = [] for attr in dir(self): if attr[:2] + attr[-2:] == "____": continue try: if callable(getattr(self, attr)): continue fields.append(f"{attr}:{getattr(self, attr)}") except AttributeError: continue return f"ChannelConversion (referenced blocks: {self.referenced_blocks}, address: {hex(self.address)}, fields: {fields})" class ChannelDependencyKwargs(BlockKwargs, total=False): sd_nr: int class ChannelDependency: """CDBLOCK class. CDBLOCK fields: * ``id`` - bytes : block ID; always b'CD' * ``block_len`` - int : block bytes size * ``dependency_type`` - int : integer code for dependency type * ``sd_nr`` - int : total number of signals dependencies * ``dg_`` - address of data group block (DGBLOCK) of N-th signal dependency * ``dg_`` - address of channel group block (CGBLOCK) of N-th signal dependency * ``dg_`` - address of channel block (CNBLOCK) of N-th signal dependency * ``dim_`` - int : Optional size of dimension *K* for N-dimensional dependency Other attributes: * ``address`` - int : block address inside MDF file * ``referenced_channels`` - list : list of (group index, channel index) pairs Parameters ---------- stream : file handle MDF file handle. address : int Block address inside MDF file. for dynamically created objects : See the key-value pairs. """ def __init__(self, **kwargs: Unpack[ChannelDependencyKwargs]) -> None: super().__init__() self.referenced_channels: list[tuple[int, int]] = [] try: stream = kwargs["stream"] self.address = address = kwargs["address"] stream.seek(address) (self.id, self.block_len, self.dependency_type, self.sd_nr) = typing.cast( tuple[bytes, int, int, int], unpack("<2s3H", stream.read(8)) ) links_size = 3 * 4 * self.sd_nr links: tuple[int, ...] = unpack(f"<{3 * self.sd_nr}I", stream.read(links_size)) for i in range(self.sd_nr): self[f"dg_{i}"] = links[3 * i] self[f"cg_{i}"] = links[3 * i + 1] self[f"ch_{i}"] = links[3 * i + 2] optional_dims_nr = (self.block_len - 8 - links_size) // 2 if optional_dims_nr: dims: tuple[int, ...] = unpack(f"<{optional_dims_nr}H", stream.read(optional_dims_nr * 2)) for i, dim in enumerate(dims): self[f"dim_{i}"] = dim if self.id != b"CD": message = f'Expected "CD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) except KeyError: sd_nr = kwargs["sd_nr"] self.id = b"CD" self.block_len = 8 + 3 * 4 * sd_nr self.dependency_type = 1 self.sd_nr = sd_nr for i in range(sd_nr): self[f"dg_{i}"] = 0 self[f"cg_{i}"] = 0 self[f"ch_{i}"] = 0 i = 0 while True: try: self[f"dim_{i}"] = kwargs[f"dim_{i}"] # type: ignore[literal-required] i += 1 except KeyError: break if i: self.dependency_type = 256 + i self.block_len += 2 * i def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: fmt = f"<2s3H{self.sd_nr * 3}I" keys: tuple[str, ...] = ("id", "block_len", "dependency_type", "sd_nr") for i in range(self.sd_nr): keys += (f"dg_{i}", f"cg_{i}", f"ch_{i}") links_size = 3 * 4 * self.sd_nr option_dims_nr = (self.block_len - 8 - links_size) // 2 if option_dims_nr: fmt += f"{option_dims_nr}H" keys += tuple(f"dim_{i}" for i in range(option_dims_nr)) result = pack(fmt, *[self[key] for key in keys]) return result class ChannelExtensionKwargs(BlockKwargs, total=False): raw_bytes: bytes block_len: int type: int module_nr: int module_address: int description: bytes ECU_identification: bytes reserved0: bytes CAN_id: int CAN_ch_index: int message_name: bytes sender_name: bytes class ChannelExtension: """CEBLOCK class. CEBLOCK has the following common fields: * ``id`` - bytes : block ID; always b'CE' * ``block_len`` - int : block bytes size * ``type`` - int : extension type identifier CEBLOCK has the following specific fields: * for DIM block * ``module_nr`` - int: module number * ``module_address`` - int : module address * ``description`` - bytes : module description * ``ECU_identification`` - bytes : identification of ECU * ``reserved0`` - bytes : reserved bytes * for Vector CAN block * ``CAN_id`` - int : CAN message ID * ``CAN_ch_index`` - int : index of CAN channel * ``message_name`` - bytes : message name * ``sender_name`` - bytes : sender name * ``reserved0`` - bytes : reserved bytes Other attributes: * ``address`` - int : block address inside MDF file * ``comment`` - str : extension comment * ``name`` - str : extension name * ``path`` - str : extension path Parameters ---------- stream : file handle MDF file handle. address : int Block address inside MDF file. for dynamically created objects : See the key-value pairs. """ __slots__ = ( "CAN_ch_index", "CAN_id", "ECU_identification", "address", "block_len", "comment", "description", "id", "message_name", "module_address", "module_nr", "name", "path", "reserved0", "sender_name", "type", ) def __init__(self, **kwargs: Unpack[ChannelExtensionKwargs]) -> None: super().__init__() self.name = self.path = self.comment = "" if "stream" in kwargs: stream = kwargs["stream"] try: (self.id, self.block_len, self.type) = SOURCE_COMMON_uf(kwargs["raw_bytes"]) if self.type == v23c.SOURCE_ECU: ( self.module_nr, self.module_address, self.description, self.ECU_identification, self.reserved0, ) = SOURCE_EXTRA_ECU_uf(kwargs["raw_bytes"], 6) elif self.type == v23c.SOURCE_VECTOR: ( self.CAN_id, self.CAN_ch_index, self.message_name, self.sender_name, self.reserved0, ) = SOURCE_EXTRA_VECTOR_uf(kwargs["raw_bytes"], 6) self.address = kwargs.get("address", 0) except KeyError: if utils.stream_is_mmap(stream, kwargs.get("mapped", False)): self.address = address = kwargs["address"] (self.id, self.block_len, self.type) = SOURCE_COMMON_uf(stream, address) if self.type == v23c.SOURCE_ECU: ( self.module_nr, self.module_address, self.description, self.ECU_identification, self.reserved0, ) = SOURCE_EXTRA_ECU_uf(stream, address + 6) elif self.type == v23c.SOURCE_VECTOR: ( self.CAN_id, self.CAN_ch_index, self.message_name, self.sender_name, self.reserved0, ) = SOURCE_EXTRA_VECTOR_uf(stream, address + 6) else: self.address = address = kwargs["address"] stream.seek(address) block = stream.read(v23c.CE_BLOCK_SIZE) (self.id, self.block_len, self.type) = SOURCE_COMMON_uf(block) if self.type == v23c.SOURCE_ECU: ( self.module_nr, self.module_address, self.description, self.ECU_identification, self.reserved0, ) = SOURCE_EXTRA_ECU_uf(block, 6) elif self.type == v23c.SOURCE_VECTOR: ( self.CAN_id, self.CAN_ch_index, self.message_name, self.sender_name, self.reserved0, ) = SOURCE_EXTRA_VECTOR_uf(block, 6) if self.id != b"CE": message = f'Expected "CE" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) else: self.address = 0 self.id = b"CE" self.block_len = kwargs.get("block_len", v23c.CE_BLOCK_SIZE) self.type = kwargs.get("type", 2) if self.type == v23c.SOURCE_ECU: self.module_nr = kwargs.get("module_nr", 0) self.module_address = kwargs.get("module_address", 0) self.description = kwargs.get("description", b"\0") self.ECU_identification = kwargs.get("ECU_identification", b"\0") self.reserved0 = kwargs.get("reserved0", b"\0") elif self.type == v23c.SOURCE_VECTOR: self.CAN_id = kwargs.get("CAN_id", 0) self.CAN_ch_index = kwargs.get("CAN_ch_index", 0) self.message_name = kwargs.get("message_name", b"\0") self.sender_name = kwargs.get("sender_name", b"\0") self.reserved0 = kwargs.get("reserved0", b"\0") if self.type == v23c.SOURCE_ECU: self.path = self.ECU_identification.decode("latin-1").strip(" \t\n\r\0") self.name = self.description.decode("latin-1").strip(" \t\n\r\0") self.comment = f"Module number={self.module_nr} @ address={self.module_address}" else: self.path = self.sender_name.decode("latin-1").strip(" \t\n\r\0") self.name = self.message_name.decode("latin-1").strip(" \t\n\r\0") self.comment = f"Message ID={hex(self.CAN_id)} on CAN bus {self.CAN_ch_index}" def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int], cc_map: dict[bytes, int], ) -> int: if self.type == v23c.SOURCE_ECU: self.ECU_identification = self.path.encode("latin-1")[:31] self.description = self.name.encode("latin-1")[:79] else: self.sender_name = self.path.encode("latin-1")[:35] self.message_name = self.name.encode("latin-1")[:35] bts = bytes(self) if bts in cc_map: self.address = cc_map[bts] else: blocks.append(bts) self.address = address cc_map[bts] = address address += self.block_len return address def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def metadata(self) -> str: if self.type == v23c.SOURCE_ECU: keys = ( "id", "block_len", "type", "module_nr", "module_address", "description", "ECU_identification", "reserved0", ) else: keys = ( "id", "block_len", "type", "CAN_id", "CAN_ch_index", "message_name", "sender_name", "reserved0", ) max_len = max(len(key) for key in keys) template = f"{{: <{max_len}}}: {{}}" metadata: list[str] = [] lines = f""" address: {hex(self.address)} """.split("\n") for key in keys: val = getattr(self, key) if key.endswith("addr") or key.startswith("text_"): lines.append(template.format(key, hex(val))) elif isinstance(val, float): lines.append(template.format(key, val)) else: if isinstance(val, bytes): lines.append(template.format(key, val.strip(b"\0"))) else: lines.append(template.format(key, val)) if key == "type": lines[-1] += f" = {v23c.SOURCE_TYPE_TO_STRING[self.type]}" # elif key == "bus_type": # lines[-1] += f" = {v23c.BUS_TYPE_TO_STRING[self.bus_type]}" for line in lines: if not line: metadata.append(line) else: for wrapped_line in wrap(line, width=120): metadata.append(wrapped_line) return "\n".join(metadata) def __bytes__(self) -> bytes: typ = self.type if typ == v23c.SOURCE_ECU: return v23c.SOURCE_ECU_p( self.id, self.block_len, self.type, self.module_nr, self.module_address, self.description, self.ECU_identification, self.reserved0, ) else: return v23c.SOURCE_VECTOR_p( self.id, self.block_len, self.type, self.CAN_id, self.CAN_ch_index, self.message_name, self.sender_name, self.reserved0, ) def __str__(self) -> str: fields = [] for attr in dir(self): if attr[:2] + attr[-2:] == "____": continue try: if callable(getattr(self, attr)): continue fields.append(f"{attr}:{getattr(self, attr)}") except AttributeError: continue return f"ChannelExtension (name: {self.name}, path: {self.path}, comment: {self.comment}, address: {hex(self.address)}, fields: {fields})" class ChannelGroupKwargs(BlockKwargs, total=False): block_len: int next_cg_addr: int first_ch_addr: int comment_addr: int record_id: int ch_nr: int samples_byte_nr: int cycles_nr: int class ChannelGroup: """CGBLOCK class. CGBLOCK fields: * ``id`` - bytes : block ID; always b'CG' * ``block_len`` - int : block bytes size * ``next_cg_addr`` - int : next CGBLOCK address * ``first_ch_addr`` - int : address of first channel block (CNBLOCK) * ``comment_addr`` - int : address of TXBLOCK that contains the channel group comment * ``record_id`` - int : record ID used as identifier for a record if the DGBLOCK defines a number of record IDs > 0 (unsorted group) * ``ch_nr`` - int : number of channels * ``samples_byte_nr`` - int : size of data record in bytes without record ID * ``cycles_nr`` - int : number of cycles (records) of this type in the data block * ``sample_reduction_addr`` - int : address to first sample reduction block Other attributes: * ``address`` - int : block address inside MDF file * ``comment`` - str : channel group comment Parameters ---------- stream : file handle MDF file handle. address : int Block address inside MDF file. for dynamically created objects : See the key-value pairs. Examples -------- >>> with open('test.mdf', 'rb') as mdf: ... cg1 = ChannelGroup(stream=mdf, address=0xBA52) >>> cg2 = ChannelGroup(sample_bytes_nr=32) >>> hex(cg1.address) 0xBA52 >>> cg1['id'] b'CG' """ __slots__ = ( "address", "block_len", "ch_nr", "comment", "comment_addr", "cycles_nr", "first_ch_addr", "id", "next_cg_addr", "record_id", "sample_reduction_addr", "samples_byte_nr", ) def __init__(self, **kwargs: Unpack[ChannelGroupKwargs]) -> None: super().__init__() self.comment = "" try: stream = kwargs["stream"] mapped = kwargs.get("mapped", False) self.address = address = kwargs["address"] if utils.stream_is_mmap(stream, mapped): ( self.id, self.block_len, self.next_cg_addr, self.first_ch_addr, self.comment_addr, self.record_id, self.ch_nr, self.samples_byte_nr, self.cycles_nr, ) = v23c.CHANNEL_GROUP_uf(stream, address) if self.block_len == v23c.CG_POST_330_BLOCK_SIZE: # sample reduction blocks are not yet used self.sample_reduction_addr = 0 else: stream.seek(address) block = stream.read(v23c.CG_PRE_330_BLOCK_SIZE) ( self.id, self.block_len, self.next_cg_addr, self.first_ch_addr, self.comment_addr, self.record_id, self.ch_nr, self.samples_byte_nr, self.cycles_nr, ) = v23c.CHANNEL_GROUP_u(block) if self.block_len == v23c.CG_POST_330_BLOCK_SIZE: # sample reduction blocks are not yet used self.sample_reduction_addr = 0 if self.id != b"CG": message = f'Expected "CG" block @{hex(address)} but found "{self.id!r}"' raise MdfException(message.format(self.id)) if self.comment_addr: self.comment = get_text_v3(address=self.comment_addr, stream=stream, mapped=mapped) except KeyError: self.address = 0 self.id = b"CG" self.block_len = kwargs.get("block_len", v23c.CG_PRE_330_BLOCK_SIZE) self.next_cg_addr = kwargs.get("next_cg_addr", 0) self.first_ch_addr = kwargs.get("first_ch_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.record_id = kwargs.get("record_id", 1) self.ch_nr = kwargs.get("ch_nr", 0) self.samples_byte_nr = kwargs.get("samples_byte_nr", 0) self.cycles_nr = kwargs.get("cycles_nr", 0) if self.block_len == v23c.CG_POST_330_BLOCK_SIZE: self.sample_reduction_addr = 0 def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int], si_map: dict[bytes, int], ) -> int: text = self.comment if text: if text in defined_texts: self.comment_addr = defined_texts[text] else: tx_block = TextBlock(text=text) self.comment_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.comment_addr = 0 blocks.append(self) self.address = address address += self.block_len return address def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: if self.block_len == v23c.CG_POST_330_BLOCK_SIZE: return ( v23c.CHANNEL_GROUP_p( self.id, self.block_len, self.next_cg_addr, self.first_ch_addr, self.comment_addr, self.record_id, self.ch_nr, self.samples_byte_nr, self.cycles_nr, ) + b"\0" * 4 ) else: return v23c.CHANNEL_GROUP_p( self.id, self.block_len, self.next_cg_addr, self.first_ch_addr, self.comment_addr, self.record_id, self.ch_nr, self.samples_byte_nr, self.cycles_nr, ) def metadata(self) -> str: keys = ( "id", "block_len", "next_cg_addr", "first_ch_addr", "comment_addr", "record_id", "ch_nr", "samples_byte_nr", "cycles_nr", "sample_reduction_addr", ) max_len = max(len(key) for key in keys) template = f"{{: <{max_len}}}: {{}}" metadata: list[str] = [] lines = f""" address: {hex(self.address)} comment: {self.comment} """.split("\n") for key in keys: if not hasattr(self, key): continue val = getattr(self, key) if key.endswith("addr") or key.startswith("text_"): lines.append(template.format(key, hex(val))) elif isinstance(val, float): lines.append(template.format(key, val)) else: if isinstance(val, bytes): lines.append(template.format(key, val.strip(b"\0"))) else: lines.append(template.format(key, val)) for line in lines: if not line: metadata.append(line) else: for wrapped_line in wrap(line, width=120): metadata.append(wrapped_line) return "\n".join(metadata) class DataBlockKwargs(BlockKwargs, total=False): size: int data: bytes class DataBlock: """Data Block class (pseudo block not defined by the MDF 3 standard). `DataBlock` attributes: * ``data`` - bytes : raw samples bytes * ``address`` - int : block address Parameters ---------- address : int Block address inside the measurement file. stream : file.io.handle Binary file stream. data : bytes When created dynamically. """ __slots__ = "address", "data" def __init__(self, **kwargs: Unpack[DataBlockKwargs]) -> None: super().__init__() try: stream = kwargs["stream"] size = kwargs["size"] self.address = address = kwargs["address"] stream.seek(address) self.data = stream.read(size) except KeyError: self.address = 0 self.data = kwargs.get("data", b"") def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: return self.data class DataGroupKwargs(BlockKwargs, total=False): block_len: int next_dg_addr: int first_cg_addr: int comment_addr: int data_block_addr: int cg_nr: int record_id_len: int class DataGroup: """DGBLOCK class. DGBLOCK fields: * ``id`` - bytes : block ID; always b'DG' * ``block_len`` - int : block bytes size * ``next_dg_addr`` - int : next DGBLOCK address * ``first_cg_addr`` - int : address of first channel group block (CGBLOCK) * ``trigger_addr`` - int : address of trigger block (TRBLOCK) * ``data_block_addr`` - address of data block * ``cg_nr`` - int : number of channel groups * ``record_id_len`` - int : number of record IDs in the data block * ``reserved0`` - bytes : reserved bytes Other attributes: * ``address`` - int : block address inside MDF file Parameters ---------- stream : file handle MDF file handle. address : int Block address inside MDF file. for dynamically created objects : See the key-value pairs. """ __slots__ = ( "address", "block_len", "cg_nr", "data_block_addr", "first_cg_addr", "id", "next_dg_addr", "record_id_len", "reserved0", "trigger_addr", ) def __init__(self, **kwargs: Unpack[DataGroupKwargs]) -> None: super().__init__() try: stream = kwargs["stream"] mapped = kwargs.get("mapped", False) self.address = address = kwargs["address"] if utils.stream_is_mmap(stream, mapped): block = stream.read(v23c.DG_PRE_320_BLOCK_SIZE) ( self.id, self.block_len, self.next_dg_addr, self.first_cg_addr, self.trigger_addr, self.data_block_addr, self.cg_nr, self.record_id_len, ) = v23c.DATA_GROUP_PRE_320_uf(stream, address) if self.block_len == v23c.DG_POST_320_BLOCK_SIZE: self.reserved0 = stream[ address + v23c.DG_PRE_320_BLOCK_SIZE : address + v23c.DG_POST_320_BLOCK_SIZE ] else: stream.seek(address) block = stream.read(v23c.DG_PRE_320_BLOCK_SIZE) ( self.id, self.block_len, self.next_dg_addr, self.first_cg_addr, self.trigger_addr, self.data_block_addr, self.cg_nr, self.record_id_len, ) = v23c.DATA_GROUP_PRE_320_u(block) if self.block_len == v23c.DG_POST_320_BLOCK_SIZE: self.reserved0 = stream.read(4) if self.id != b"DG": message = f'Expected "DG" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) except KeyError: self.address = kwargs.get("address", 0) self.id = b"DG" self.block_len = kwargs.get("block_len", v23c.DG_PRE_320_BLOCK_SIZE) self.next_dg_addr = kwargs.get("next_dg_addr", 0) self.first_cg_addr = kwargs.get("first_cg_addr", 0) self.trigger_addr = kwargs.get("comment_addr", 0) self.data_block_addr = kwargs.get("data_block_addr", 0) self.cg_nr = kwargs.get("cg_nr", 1) self.record_id_len = kwargs.get("record_id_len", 0) if self.block_len == v23c.DG_POST_320_BLOCK_SIZE: self.reserved0 = b"\0\0\0\0" def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: keys: tuple[str, ...] if self.block_len == v23c.DG_POST_320_BLOCK_SIZE: fmt = v23c.FMT_DATA_GROUP_POST_320 keys = v23c.KEYS_DATA_GROUP_POST_320 else: fmt = v23c.FMT_DATA_GROUP_PRE_320 keys = v23c.KEYS_DATA_GROUP_PRE_320 result = pack(fmt, *[self[key] for key in keys]) return result class FileIdentificationBlockKwargs(BlockKwargs, total=False): version: str class FileIdentificationBlock: """IDBLOCK class. IDBLOCK fields: * ``file_identification`` - bytes : file identifier * ``version_str`` - bytes : format identifier * ``program_identification`` - bytes : creator program identifier * ``byte_order`` - int : integer code for byte order (endianness) * ``float_format`` - int : integer code for floating-point format * ``mdf_version`` - int : version number of MDF format * ``code_page`` - int : unicode code page number * ``reserved0`` - bytes : reserved bytes * ``reserved1`` - bytes : reserved bytes * ``unfinalized_standard_flags`` - int : standard flags for unfinalized MDF * ``unfinalized_custom_flags`` - int : custom flags for unfinalized MDF Other attributes: * ``address`` - int : block address inside MDF file; should be 0 always Parameters ---------- stream : file handle MDF file handle. version : int MDF version in case of new file (dynamically created). """ __slots__ = ( "address", "byte_order", "code_page", "file_identification", "float_format", "mdf_version", "program_identification", "reserved0", "reserved1", "unfinalized_custom_flags", "unfinalized_standard_flags", "version_str", ) def __init__(self, **kwargs: Unpack[FileIdentificationBlockKwargs]) -> None: super().__init__() self.address = 0 try: stream = kwargs["stream"] stream.seek(0) ( self.file_identification, self.version_str, self.program_identification, self.byte_order, self.float_format, self.mdf_version, self.code_page, self.reserved0, self.reserved1, self.unfinalized_standard_flags, self.unfinalized_custom_flags, ) = typing.cast(v23c.Id, unpack(v23c.ID_FMT, stream.read(v23c.ID_BLOCK_SIZE))) except KeyError: version = kwargs["version"] self.file_identification = "MDF ".encode("latin-1") self.version_str = version.encode("latin-1") + b"\0" * 4 self.program_identification = f"{tool.__tool_short__}{tool.__version__}".encode("latin-1") self.byte_order = v23c.BYTE_ORDER_INTEL if sys.byteorder == "little" else v23c.BYTE_ORDER_MOTOROLA self.float_format = 0 self.mdf_version = int(version.replace(".", "")) self.code_page = 0 self.reserved0 = b"\0" * 2 self.reserved1 = b"\0" * 26 self.unfinalized_standard_flags = 0 self.unfinalized_custom_flags = 0 def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: result = pack(v23c.ID_FMT, *[self[key] for key in v23c.ID_KEYS]) return result class HeaderBlockKwargs(BlockKwargs, total=False): version: str class _CommonProperties(TypedDict, total=False): author: str project: str department: str subject: str class HeaderBlock: """HDBLOCK class. HDBLOCK fields: * ``id`` - bytes : block ID; always b'HD' * ``block_len`` - int : block bytes size * ``first_dg_addr`` - int : address of first data group block (DGBLOCK) * ``comment_addr`` - int : address of TXBLOCK that contains the measurement file comment * ``program_addr`` - int : address of program block (PRBLOCK) * ``dg_nr`` - int : number of data groups * ``date`` - bytes : date at which the recording was started in "DD:MM:YYYY" format * ``time`` - bytes : time at which the recording was started in "HH:MM:SS" format * ``author_field`` - bytes : author name * ``organization_field``` - bytes : organization name * ``project_field``` - bytes : project name * ``subject_field``` - bytes : subject Since version 3.2 the following extra keys were added: * ``abs_time`` - int : timestamp at which recording was started in nanoseconds. * ``tz_offset`` - int : UTC time offset in hours (= GMT time zone) * ``time_quality`` - int : time quality class * ``timer_identification`` - bytes : timer identification (time source) Other attributes: * ``address`` - int : block address inside MDF file; should always be 64 * ``comment`` - int : file comment * ``program`` - ProgramBlock : program block * ``author`` - str : measurement author * ``department`` - str : author department * ``project`` - str : working project * ``subject`` - str : measurement subject Parameters ---------- stream : file handle MDF file handle. version : int MDF version in case of new file (dynamically created). """ def __init__(self, **kwargs: Unpack[HeaderBlockKwargs]) -> None: super().__init__() self.address = 64 self.program = None self._common_properties: _CommonProperties = {} self.description = "" self.comment = "" try: stream = kwargs["stream"] stream.seek(64) ( self.id, self.block_len, self.first_dg_addr, self.comment_addr, self.program_addr, self.dg_nr, self.date, self.time, self.author_field, self.department_field, self.project_field, self.subject_field, ) = typing.cast(v23c.HeaderCommon, unpack(v23c.HEADER_COMMON_FMT, stream.read(v23c.HEADER_COMMON_SIZE))) if self.block_len > v23c.HEADER_COMMON_SIZE: ( self.abs_time, self.tz_offset, self.time_quality, self.timer_identification, ) = typing.cast( v23c.HeaderPost320Extra, unpack(v23c.HEADER_POST_320_EXTRA_FMT, stream.read(v23c.HEADER_POST_320_EXTRA_SIZE)), ) if self.id != b"HD": message = f'Expected "HD" block @{hex(self.address)} but found "{self.id!r}"' message = message.format(hex(64), self.id) logger.exception(message) raise MdfException(message) if self.program_addr: self.program = ProgramBlock(address=self.program_addr, stream=stream) if self.comment_addr: self.comment = get_text_v3(address=self.comment_addr, stream=stream) except KeyError: version = kwargs.get("version", "3.20") self.id = b"HD" self.block_len = 208 if version >= "3.20" else 164 self.first_dg_addr = 0 self.comment_addr = 0 self.program_addr = 0 self.dg_nr = 0 try: user = getuser() except (ModuleNotFoundError, OSError): user = "" self.author_field = f"{user:\0<32}".encode("latin-1") self.department_field = "{:\0<32}".format("").encode("latin-1") self.project_field = "{:\0<32}".format("").encode("latin-1") self.subject_field = "{:\0<32}".format("").encode("latin-1") if self.block_len > v23c.HEADER_COMMON_SIZE: self.time_quality = 0 self.timer_identification = "{:\0<32}".format("Local PC Reference Time").encode("latin-1") self.start_time = datetime(1980, 1, 1, tzinfo=timezone.utc) self.author = self.author_field.strip(b" \r\n\t\0").decode("latin-1") self.department = self.department_field.strip(b" \r\n\t\0").decode("latin-1") self.project = self.project_field.strip(b" \r\n\t\0").decode("latin-1") self.subject = self.subject_field.strip(b" \r\n\t\0").decode("latin-1") @property def comment(self) -> str: root = ET.Element("HDcomment") text = ET.SubElement(root, "TX") text.text = self.description common = ET.SubElement(root, "common_properties") for name, value in self._common_properties.items(): if isinstance(value, dict): tree = ET.SubElement(common, "tree", name=name) for subname, subvalue in value.items(): ET.SubElement(tree, "e", name=subname).text = subvalue elif isinstance(value, str): ET.SubElement(common, "e", name=name).text = value else: raise TypeError("value must be of type 'dict' or 'str'") xml_string: bytes = ET.tostring(root, encoding="utf8", method="xml") return xml_string.replace(b"\n", b"").decode("utf-8") @comment.setter def comment(self, string: str) -> None: self._common_properties = {} if string.startswith(" str: return self._common_properties.get("author", "") @author.setter def author(self, value: str) -> None: self._common_properties["author"] = value @property def project(self) -> str: return self._common_properties.get("project", "") @project.setter def project(self, value: str) -> None: self._common_properties["project"] = value @property def department(self) -> str: return self._common_properties.get("department", "") @department.setter def department(self, value: str) -> None: self._common_properties["department"] = value @property def subject(self) -> str: return self._common_properties.get("subject", "") @subject.setter def subject(self, value: str) -> None: self._common_properties["subject"] = value def to_blocks( self, address: int, blocks: list[SupportsBytes], defined_texts: dict[str, int], si_map: dict[bytes, int], ) -> int: blocks.append(self) self.address = address address += self.block_len text = self.comment if text: if text in defined_texts: self.comment_addr = defined_texts[text] else: tx_block = TextBlock(text=text) self.comment_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.comment_addr = 0 if self.program: self.program_addr = address address += self.program.block_len blocks.append(self.program) else: self.program_addr = 0 self.author_field = self.author.encode("latin-1") self.department_field = self.department.encode("latin-1") self.project_field = self.project.encode("latin-1") self.subject_field = self.subject.encode("latin-1") return address @property def start_time(self) -> datetime: """Getter and setter of the measurement start timestamp. Returns ------- timestamp : datetime.datetime Start timestamp. """ try: if self.block_len > v23c.HEADER_COMMON_SIZE: if self.abs_time: timestamp = self.abs_time / 10**9 tz = timezone(timedelta(hours=self.tz_offset)) try: timestamp_dt = datetime.fromtimestamp(timestamp, tz) except OverflowError: timestamp_dt = datetime.fromtimestamp(0, tz) + timedelta(seconds=timestamp) except OSError: timestamp_dt = datetime.now(tz) else: timestamp_fmt = "{} {}".format(self.date.decode("ascii"), self.time.decode("ascii")) timestamp_dt = datetime.strptime(timestamp_fmt, "%d:%m:%Y %H:%M:%S").astimezone(timezone.utc) else: timestamp_fmt = "{} {}".format(self.date.decode("ascii"), self.time.decode("ascii")) timestamp_dt = datetime.strptime(timestamp_fmt, "%d:%m:%Y %H:%M:%S").astimezone(timezone.utc) except: return datetime.now().astimezone(timezone.utc) return timestamp_dt @start_time.setter def start_time(self, timestamp: datetime) -> None: if timestamp.tzinfo is None: # the user provided a naive datetime # use the local time zone tzinfo = dateutil.tz.tzlocal() timestamp = datetime.fromtimestamp(timestamp.timestamp(), tzinfo) self.date = timestamp.strftime("%d:%m:%Y").encode("ascii") self.time = timestamp.strftime("%H:%M:%S").encode("ascii") if self.block_len > v23c.HEADER_COMMON_SIZE: if timestamp.tzinfo is None: raise ValueError("tzinfo is None") offset = timestamp.tzinfo.utcoffset(timestamp) if offset is None: raise ValueError("utcoffset is None") self.tz_offset = int(offset.total_seconds() / 3600) self.abs_time = int(timestamp.timestamp() * 10**9) def start_time_string(self) -> str: tzinfo = self.start_time.tzinfo if tzinfo is None: raise ValueError("tzinfo is None") dst = tzinfo.dst(self.start_time) if dst is not None: dst = tzinfo.dst(self.start_time) if dst is None: raise ValueError("dst is None") dst_offset = int(dst.total_seconds() / 3600) else: dst_offset = 0 offset = tzinfo.utcoffset(self.start_time) if offset is None: raise ValueError("offset is None") tz_offset = int(offset.total_seconds() / 3600) - dst_offset tz_offset_sign = "-" if tz_offset < 0 else "+" dst_offset_sign = "-" if dst_offset < 0 else "+" tz_information = f"[GMT{tz_offset_sign}{tz_offset:.2f} DST{dst_offset_sign}{dst_offset:.2f}h]" if self.block_len > v23c.HEADER_COMMON_SIZE: if self.abs_time: tz_offset_sign = "-" if self.tz_offset < 0 else "+" tz_information = f"[GMT{tz_offset_sign}{abs(self.tz_offset):.2f} DST+{0:.2f}h]" start_time = f"local time = {self.start_time.strftime('%d-%b-%Y %H:%M:%S + %fu')} {tz_information}" return start_time def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: fmt = v23c.HEADER_COMMON_FMT keys: tuple[str, ...] = v23c.HEADER_COMMON_KEYS if self.block_len > v23c.HEADER_COMMON_SIZE: fmt += v23c.HEADER_POST_320_EXTRA_FMT keys += v23c.HEADER_POST_320_EXTRA_KEYS result = pack(fmt, *[self[key] for key in keys]) return result class ProgramBlockKwargs(BlockKwargs, total=False): data: bytes class ProgramBlock: """PRBLOCK class. PRBLOCK fields: * ``id`` - bytes : block ID; always b'PR' * ``block_len`` - int : block bytes size * ``data`` - bytes : creator program free format data Other attributes: * ``address`` - int : block address inside MDF file Parameters ---------- stream : file handle MDF file handle. address : int Block address inside MDF file. """ __slots__ = ("address", "block_len", "data", "id") def __init__(self, **kwargs: Unpack[ProgramBlockKwargs]) -> None: super().__init__() try: stream = kwargs["stream"] self.address = address = kwargs["address"] stream.seek(address) (self.id, self.block_len) = COMMON_u(stream.read(4)) self.data = stream.read(self.block_len - 4) if self.id != b"PR": message = f'Expected "PR" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) except KeyError: self.id = b"PR" self.block_len = len(kwargs["data"]) + 6 self.data = kwargs["data"] def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: fmt = v23c.FMT_PROGRAM_BLOCK.format(self.block_len - 4) result = pack(fmt, *[self[key] for key in v23c.KEYS_PROGRAM_BLOCK]) return result class TextBlockKwargs(BlockKwargs, total=False): text: bytes | str class TextBlock: r"""TXBLOCK class. TXBLOCK fields: * ``id`` - bytes : block ID; always b'TX' * ``block_len`` - int : block bytes size * ``text`` - bytes : text content Other attributes: * ``address`` - int : block address inside MDF file Parameters ---------- stream : file handle MDF file handle. address : int Block address inside MDF file. text : bytes | str Bytes or str for creating a new TextBlock. Examples -------- >>> tx1 = TextBlock(text='VehicleSpeed') >>> tx1['text'] b'VehicleSpeed\x00' """ __slots__ = ("address", "block_len", "id", "text") def __init__(self, **kwargs: Unpack[TextBlockKwargs]) -> None: super().__init__() try: stream = kwargs["stream"] mapped = kwargs.get("mapped", False) self.address = address = kwargs["address"] if utils.stream_is_mmap(stream, mapped): (self.id, self.block_len) = COMMON_uf(stream, address) if self.id != b"TX": message = f'Expected "TX" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) self.text = stream[address + 4 : address + self.block_len] else: stream.seek(address) (self.id, self.block_len) = COMMON_u(stream.read(4)) if self.id != b"TX": message = f'Expected "TX" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) size = self.block_len - 4 self.text = stream.read(size) except KeyError: self.address = 0 text = kwargs["text"] if isinstance(text, str): text_bytes = text.encode("latin-1", "backslashreplace") else: text_bytes = text self.id = b"TX" self.block_len = len(text_bytes) + 5 self.text = text_bytes + b"\0" if self.block_len > 65000: self.block_len = 65000 + 5 self.text = self.text[:65000] + b"\0" def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: return v23c.COMMON_p(self.id, self.block_len) + self.text def __repr__(self) -> str: return f"TextBlock(id={self.id!r}, block_len={self.block_len}, text={self.text!r})" class TriggerBlock: """TRBLOCK class. TRBLOCK fields: * ``id`` - bytes : block ID; always b'TR' * ``block_len`` - int : block bytes size * ``text_addr`` - int : address of TXBLOCK that contains the trigger comment text * ``trigger_events_nr`` - int : number of trigger events * ``trigger__time`` - float : trigger time [s] of trigger's N-th event * ``trigger__pretime`` - float : pre trigger time [s] of trigger's N-th event * ``trigger__posttime`` - float : post trigger time [s] of trigger's N-th event Other attributes: * ``address`` - int : block address inside MDF file * ``comment`` - str : trigger comment Parameters ---------- stream : file handle MDF file handle. address : int Block address inside MDF file. """ def __init__(self, **kwargs: Unpack[BlockKwargs]) -> None: super().__init__() self.comment = "" try: self.address = address = kwargs["address"] stream = kwargs["stream"] stream.seek(address + 2) (size,) = UINT16_u(stream.read(2)) stream.seek(address) block = stream.read(size) (self.id, self.block_len, self.text_addr, self.trigger_events_nr) = typing.cast( tuple[bytes, int, int, int], unpack("<2sHIH", block[:10]) ) nr = self.trigger_events_nr if nr: values: tuple[float, ...] = unpack(f"<{3 * nr}d", block[10:]) for i in range(nr): ( self[f"trigger_{i}_time"], self[f"trigger_{i}_pretime"], self[f"trigger_{i}_posttime"], ) = (values[i * 3], values[3 * i + 1], values[3 * i + 2]) if self.text_addr: self.comment = get_text_v3(address=self.text_addr, stream=stream) if self.id != b"TR": message = f'Expected "TR" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) except KeyError: self.address = 0 nr = 0 while f"trigger_{nr}_time" in kwargs: nr += 1 self.id = b"TR" self.block_len = 10 + nr * 8 * 3 self.text_addr = 0 self.trigger_events_nr = nr for i in range(nr): key = f"trigger_{i}_time" self[key] = kwargs[key] # type: ignore[literal-required] key = f"trigger_{i}_pretime" self[key] = kwargs[key] # type: ignore[literal-required] key = f"trigger_{i}_posttime" self[key] = kwargs[key] # type: ignore[literal-required] def to_blocks(self, address: int, blocks: list[bytes | SupportsBytes]) -> int: text = self.comment if text: tx_block = TextBlock(text=text) self.text_addr = address address += tx_block.block_len blocks.append(tx_block) else: self.text_addr = 0 blocks.append(self) self.address = address address += self.block_len return address def __getitem__(self, item: str) -> object: return self.__getattribute__(item) def __setitem__(self, item: str, value: object) -> None: self.__setattr__(item, value) def __bytes__(self) -> bytes: triggers_nr = self.trigger_events_nr fmt = f"<2sHIH{triggers_nr * 3}d" keys: tuple[str, ...] = ("id", "block_len", "text_addr", "trigger_events_nr") for i in range(triggers_nr): keys += ( f"trigger_{i}_time", f"trigger_{i}_pretime", f"trigger_{i}_posttime", ) result = pack(fmt, *[self[key] for key in keys]) return result asammdf-8.5.1/src/asammdf/blocks/v2_v3_constants.py000066400000000000000000000325121502633300400222150ustar00rootroot00000000000000"""MDF v2 and v3 constants""" from collections.abc import Callable import struct from typing import Literal from typing_extensions import Buffer from .blocks_common import UnpackFrom # byte order BYTE_ORDER_INTEL = 0 BYTE_ORDER_MOTOROLA = 1 # data types DATA_TYPE_UNSIGNED = 0 DATA_TYPE_SIGNED = 1 DATA_TYPE_FLOAT = 2 DATA_TYPE_DOUBLE = 3 DATA_TYPE_STRING = 7 DATA_TYPE_BYTEARRAY = 8 DATA_TYPE_UNSIGNED_INTEL = 13 DATA_TYPE_UNSIGNED_MOTOROLA = 9 DATA_TYPE_SIGNED_INTEL = 14 DATA_TYPE_SIGNED_MOTOROLA = 10 DATA_TYPE_FLOAT_INTEL = 15 DATA_TYPE_FLOAT_MOTOROLA = 11 DATA_TYPE_DOUBLE_INTEL = 16 DATA_TYPE_DOUBLE_MOTOROLA = 12 VALID_DATA_TYPES = { DATA_TYPE_UNSIGNED, DATA_TYPE_SIGNED, DATA_TYPE_FLOAT, DATA_TYPE_DOUBLE, DATA_TYPE_STRING, DATA_TYPE_BYTEARRAY, DATA_TYPE_UNSIGNED_INTEL, DATA_TYPE_UNSIGNED_MOTOROLA, DATA_TYPE_SIGNED_INTEL, DATA_TYPE_SIGNED_MOTOROLA, DATA_TYPE_FLOAT_INTEL, DATA_TYPE_FLOAT_MOTOROLA, DATA_TYPE_DOUBLE_INTEL, DATA_TYPE_DOUBLE_MOTOROLA, } DATA_TYPE_TO_STRING = { DATA_TYPE_UNSIGNED: "UNSIGNED", DATA_TYPE_SIGNED: "SIGNED", DATA_TYPE_FLOAT: "FLOAT", DATA_TYPE_DOUBLE: "DOUBLE", DATA_TYPE_STRING: "STRING", DATA_TYPE_BYTEARRAY: "BYTEARRAY", DATA_TYPE_UNSIGNED_INTEL: "UNSIGNED_INTEL", DATA_TYPE_UNSIGNED_MOTOROLA: "UNSIGNED_MOTOROLA", DATA_TYPE_SIGNED_INTEL: "SIGNED_INTEL", DATA_TYPE_SIGNED_MOTOROLA: "SIGNED_MOTOROLA", DATA_TYPE_FLOAT_INTEL: "FLOAT_INTEL", DATA_TYPE_FLOAT_MOTOROLA: "FLOAT_MOTOROLA", DATA_TYPE_DOUBLE_INTEL: "DOUBLE_INTEL", DATA_TYPE_DOUBLE_MOTOROLA: "DOUBLE_MOTOROLA", } SIGNED_INT = {DATA_TYPE_SIGNED, DATA_TYPE_SIGNED_INTEL, DATA_TYPE_SIGNED_MOTOROLA} FLOATS = { DATA_TYPE_FLOAT, DATA_TYPE_DOUBLE, DATA_TYPE_FLOAT_INTEL, DATA_TYPE_FLOAT_MOTOROLA, DATA_TYPE_DOUBLE_INTEL, DATA_TYPE_DOUBLE_MOTOROLA, } STANDARD_INT_SIZES = {8, 16, 32, 64} SIGNAL_TYPE_SCALAR = 0 SIGNAL_TYPE_STRING = 1 SIGNAL_TYPE_CANOPEN = 2 SIGNAL_TYPE_STRUCTURE_COMPOSITION = 3 SIGNAL_TYPE_ARRAY = 4 INT_TYPES = { DATA_TYPE_UNSIGNED, DATA_TYPE_SIGNED, DATA_TYPE_UNSIGNED_INTEL, DATA_TYPE_UNSIGNED_MOTOROLA, DATA_TYPE_SIGNED_INTEL, DATA_TYPE_SIGNED_MOTOROLA, } # channel types CHANNEL_TYPE_VALUE = 0 CHANNEL_TYPE_MASTER = 1 CHANNEL_TYPE_TO_STRING = {CHANNEL_TYPE_VALUE: "VALUE", CHANNEL_TYPE_MASTER: "MASTER"} # channel conversion types CONVERSION_TYPE_NONE = 65535 CONVERSION_TYPE_LINEAR = 0 CONVERSION_TYPE_TABI = 1 CONVERSION_TYPE_TAB = 2 CONVERSION_TYPE_POLY = 6 CONVERSION_TYPE_EXPO = 7 CONVERSION_TYPE_LOGH = 8 CONVERSION_TYPE_RAT = 9 CONVERSION_TYPE_FORMULA = 10 CONVERSION_TYPE_TABX = 11 CONVERSION_TYPE_RTABX = 12 CONVERSION_TYPE_TO_STRING = { CONVERSION_TYPE_NONE: "NONE", CONVERSION_TYPE_LINEAR: "LINEAR", CONVERSION_TYPE_TABI: "TABI", CONVERSION_TYPE_TAB: "TAB", CONVERSION_TYPE_POLY: "POLY", CONVERSION_TYPE_EXPO: "EXPO", CONVERSION_TYPE_LOGH: "LOGH", CONVERSION_TYPE_RAT: "RAT", CONVERSION_TYPE_FORMULA: "FORMULA", CONVERSION_TYPE_TABX: "TABX", CONVERSION_TYPE_RTABX: "RTABX", } RAT_CONV_TEXT = "(P1 * X**2 + P2 * X + P3) / (P4 * X**2 + P5 * X + P6)" POLY_CONV_SHORT_TEXT = "P4 * X / P1" POLY_CONV_LONG_TEXT = "(P2 - (P4 * (X - P5 -P6))) / (P3* (X - P5 - P6) - P1)" DEPENDENCY_TYPE_NONE = 0 DEPENDENCY_TYPE_VECTOR = 1 DEPENDENCY_TYPE_NDIM = 256 DEPENDENCY_TYPE_TO_STRING = { DEPENDENCY_TYPE_NONE: "NONE", DEPENDENCY_TYPE_VECTOR: "VECTOR", DEPENDENCY_TYPE_NDIM: "NDIM", } # flags FLAG_PRECISION = 1 FLAG_PHY_RANGE_OK = 2 FLAG_VAL_RANGE_OK = 8 # channel source types SOURCE_ECU = 2 SOURCE_VECTOR = 19 SOURCE_TYPE_TO_STRING = {SOURCE_ECU: "ECU", SOURCE_VECTOR: "VECTOR"} # bus types BUS_TYPE_NONE = 0 BUS_TYPE_CAN = 2 BUS_TYPE_FLEXRAY = 5 BUS_TYPE_TO_STRING = { BUS_TYPE_NONE: "NONE", BUS_TYPE_CAN: "CAN", BUS_TYPE_FLEXRAY: "FLEXRAY", } # file IO seek types SEEK_START = 0 SEEK_REL = 1 SEEK_END = 2 # blocks size ID_BLOCK_SIZE = 64 HEADER_COMMON_SIZE = 164 HEADER_POST_320_EXTRA_SIZE = 44 CE_BLOCK_SIZE = 128 FH_BLOCK_SIZE = 56 DG_PRE_320_BLOCK_SIZE = 24 DG_POST_320_BLOCK_SIZE = 28 HD_BLOCK_SIZE = 104 CN_DISPLAYNAME_BLOCK_SIZE = 228 CN_SHORT_BLOCK_SIZE = 218 CN_LONGNAME_BLOCK_SIZE = 222 CG_PRE_330_BLOCK_SIZE = 26 CG_POST_330_BLOCK_SIZE = 30 DT_BLOCK_SIZE = 24 CC_COMMON_BLOCK_SIZE = 46 CC_COMMON_SHORT_SIZE = 42 CC_ALG_BLOCK_SIZE = 88 CC_LIN_BLOCK_SIZE = 62 CC_POLY_BLOCK_SIZE = 94 CC_EXPO_BLOCK_SIZE = 102 CC_FORMULA_BLOCK_SIZE = 304 SR_BLOCK_SIZE = 156 # max int values MAX_UINT8 = (1 << 8) - 1 MAX_UINT16 = (1 << 16) - 1 MAX_UINT32 = (1 << 32) - 1 MAX_UINT64 = (1 << 64) - 1 # data location LOCATION_ORIGINAL_FILE = 0 LOCATION_TEMPORARY_FILE = 1 LOCATION_MEMORY = 2 # blocks struct fmts and keys ID_FMT = "<8s8s8s4H2s26s2H" Id = tuple[bytes, bytes, bytes, int, int, int, int, bytes, bytes, int, int] ID_KEYS = ( "file_identification", "version_str", "program_identification", "byte_order", "float_format", "mdf_version", "code_page", "reserved0", "reserved1", "unfinalized_standard_flags", "unfinalized_custom_flags", ) HEADER_COMMON_FMT = "<2sH3IH10s8s32s32s32s32s" HeaderCommon = tuple[bytes, int, int, int, int, int, bytes, bytes, bytes, bytes, bytes, bytes] HEADER_COMMON_KEYS = ( "id", "block_len", "first_dg_addr", "comment_addr", "program_addr", "dg_nr", "date", "time", "author_field", "department_field", "project_field", "subject_field", ) FMT_COMMON = "<2sH" Common = tuple[bytes, int] COMMON_SIZE = 4 COMMON_u: Callable[[Buffer], Common] = struct.Struct(FMT_COMMON).unpack COMMON_uf: UnpackFrom[Common] = struct.Struct(FMT_COMMON).unpack_from COMMON_p = struct.Struct(FMT_COMMON).pack HEADER_POST_320_EXTRA_FMT = "QhH32s" HeaderPost320Extra = tuple[int, int, int, bytes] HEADER_POST_320_EXTRA_KEYS = ( "abs_time", "tz_offset", "time_quality", "timer_identification", ) FMT_CHANNEL_FILTER = "<2sHI16xH32s" ChannelFilter = tuple[bytes, int, int, int, bytes] CHANNEL_FILTER_u: Callable[[Buffer], ChannelFilter] = struct.Struct(FMT_CHANNEL_FILTER).unpack CHANNEL_FILTER_uf: UnpackFrom[ChannelFilter] = struct.Struct(FMT_CHANNEL_FILTER).unpack_from CHANNEL_FILTER_SIZE = 58 FMT_CHANNEL_DISPLAYNAME = "<2sH5IH32s128s4H3d2IH" ChannelDisplayname = tuple[ bytes, int, int, int, int, int, int, int, bytes, bytes, int, int, int, int, float, float, float, int, int, int ] CHANNEL_DISPLAYNAME_u: Callable[[Buffer], ChannelDisplayname] = struct.Struct(FMT_CHANNEL_DISPLAYNAME).unpack CHANNEL_DISPLAYNAME_uf: UnpackFrom[ChannelDisplayname] = struct.Struct(FMT_CHANNEL_DISPLAYNAME).unpack_from CHANNEL_DISPLAYNAME_p = struct.Struct(FMT_CHANNEL_DISPLAYNAME).pack KEYS_CHANNEL_DISPLAYNAME = ( "id", "block_len", "next_ch_addr", "conversion_addr", "source_addr", "ch_depend_addr", "comment_addr", "channel_type", "short_name", "description", "start_offset", "bit_count", "data_type", "range_flag", "min_raw_value", "max_raw_value", "sampling_rate", "long_name_addr", "display_name_addr", "additional_byte_offset", ) FMT_CHANNEL_SHORT = "<2sH5IH32s128s4H3d" ChannelShort = tuple[bytes, int, int, int, int, int, int, int, bytes, bytes, int, int, int, int, float, float, float] CHANNEL_SHORT_u: Callable[[Buffer], ChannelShort] = struct.Struct(FMT_CHANNEL_SHORT).unpack CHANNEL_SHORT_uf: UnpackFrom[ChannelShort] = struct.Struct(FMT_CHANNEL_SHORT).unpack_from CHANNEL_SHORT_p = struct.Struct(FMT_CHANNEL_SHORT).pack FMT_CHANNEL_LONGNAME = FMT_CHANNEL_SHORT + "I" ChannelLongname = tuple[ bytes, int, int, int, int, int, int, int, bytes, bytes, int, int, int, int, float, float, float, int ] CHANNEL_LONGNAME_u: Callable[[Buffer], ChannelLongname] = struct.Struct(FMT_CHANNEL_LONGNAME).unpack CHANNEL_LONGNAME_uf: UnpackFrom[ChannelLongname] = struct.Struct(FMT_CHANNEL_LONGNAME).unpack_from CHANNEL_LONGNAME_p = struct.Struct(FMT_CHANNEL_LONGNAME).pack KEYS_CHANNEL_SHORT = ( "id", "block_len", "next_ch_addr", "conversion_addr", "source_addr", "ch_depend_addr", "comment_addr", "channel_type", "short_name", "description", "start_offset", "bit_count", "data_type", "range_flag", "min_raw_value", "max_raw_value", "sampling_rate", ) KEYS_CHANNEL_LONGNAME = (*KEYS_CHANNEL_SHORT, "long_name_addr") FMT_CHANNEL_GROUP = "<2sH3I3HI" ChannelGroup = tuple[bytes, int, int, int, int, int, int, int, int] KEYS_CHANNEL_GROUP = ( "id", "block_len", "next_cg_addr", "first_ch_addr", "comment_addr", "record_id", "ch_nr", "samples_byte_nr", "cycles_nr", ) CHANNEL_GROUP_u: Callable[[Buffer], ChannelGroup] = struct.Struct(FMT_CHANNEL_GROUP).unpack CHANNEL_GROUP_uf: UnpackFrom[ChannelGroup] = struct.Struct(FMT_CHANNEL_GROUP).unpack_from CHANNEL_GROUP_p = struct.Struct(FMT_CHANNEL_GROUP).pack FMT_DATA_GROUP_POST_320 = "<2sH4I2H4s" KEYS_DATA_GROUP_POST_320 = ( "id", "block_len", "next_dg_addr", "first_cg_addr", "trigger_addr", "data_block_addr", "cg_nr", "record_id_len", "reserved0", ) FMT_DATA_GROUP_PRE_320 = "<2sH4I2H" DataGroupPre320 = tuple[bytes, int, int, int, int, int, int, int] KEYS_DATA_GROUP_PRE_320 = ( "id", "block_len", "next_dg_addr", "first_cg_addr", "trigger_addr", "data_block_addr", "cg_nr", "record_id_len", ) DATA_GROUP_PRE_320_u: Callable[[Buffer], DataGroupPre320] = struct.Struct(FMT_DATA_GROUP_PRE_320).unpack DATA_GROUP_PRE_320_uf: UnpackFrom[DataGroupPre320] = struct.Struct(FMT_DATA_GROUP_PRE_320).unpack_from DATA_GROUP_PRE_320_p = struct.Struct(FMT_DATA_GROUP_PRE_320).pack FMT_SOURCE_COMMON = "<2s2H" SourceCommon = tuple[bytes, int, int] SOURCE_COMMON_u: Callable[[Buffer], SourceCommon] = struct.Struct(FMT_SOURCE_COMMON).unpack SOURCE_COMMON_uf: UnpackFrom[SourceCommon] = struct.Struct(FMT_SOURCE_COMMON).unpack_from FMT_SOURCE_ECU = "<2s3HI80s32s4s" SourceEcu = tuple[bytes, int, int, int, int, bytes, bytes, bytes] SOURCE_ECU_u: Callable[[Buffer], SourceEcu] = struct.Struct(FMT_SOURCE_ECU).unpack SOURCE_ECU_uf: UnpackFrom[SourceEcu] = struct.Struct(FMT_SOURCE_ECU).unpack_from SOURCE_ECU_p = struct.Struct(FMT_SOURCE_ECU).pack FMT_SOURCE_EXTRA_ECU = " None: self.file_name = self.mime = self.comment = "" try: self.address = address = kwargs["address"] stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) if utils.stream_is_mmap(stream, mapped): ( self.id, self.reserved0, self.block_len, self.links_nr, self.next_at_addr, self.file_name_addr, self.mime_addr, self.comment_addr, self.flags, self.creator_index, self.reserved1, self.md5_sum, self.original_size, self.embedded_size, ) = v4c.AT_COMMON_uf(stream, address) address += v4c.AT_COMMON_SIZE self.embedded_data = stream[address : address + self.embedded_size] else: stream.seek(address) ( self.id, self.reserved0, self.block_len, self.links_nr, self.next_at_addr, self.file_name_addr, self.mime_addr, self.comment_addr, self.flags, self.creator_index, self.reserved1, self.md5_sum, self.original_size, self.embedded_size, ) = v4c.AT_COMMON_u(stream.read(v4c.AT_COMMON_SIZE)) self.embedded_data = stream.read(self.embedded_size) if self.id != b"##AT": message = f'Expected "##AT" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) tx_map = kwargs.get("tx_map", {}) self.file_name = get_text_v4(self.file_name_addr, stream, mapped=mapped, tx_map=tx_map) self.mime = get_text_v4(self.mime_addr, stream, mapped=mapped, tx_map=tx_map) self.comment = get_text_v4(self.comment_addr, stream, mapped=mapped, tx_map=tx_map) except KeyError: self.address = 0 self.comment = kwargs.get("comment", "") self.mime = kwargs.get("mime", "") file_name = Path(kwargs.get("file_name", None) or "bin.bin") data = kwargs["data"] original_size = embedded_size = len(data) compression = kwargs.get("compression", False) embedded = kwargs.get("embedded", False) md5_sum = md5(data).digest() flags = v4c.FLAG_AT_MD5_VALID if embedded: flags |= v4c.FLAG_AT_EMBEDDED if compression: flags |= v4c.FLAG_AT_COMPRESSED_EMBEDDED data = compress(data, COMPRESSION_LEVEL) embedded_size = len(data) self.file_name = file_name.name else: self.file_name = str(file_name) embedded_size = 0 data = b"" self.id = b"##AT" self.reserved0 = 0 self.block_len = v4c.AT_COMMON_SIZE + embedded_size self.links_nr = 4 self.next_at_addr = 0 self.file_name_addr = 0 self.mime_addr = 0 self.comment_addr = 0 self.flags = flags self.creator_index = kwargs.get("creator_index", 0) self.reserved1 = 0 self.md5_sum = md5_sum self.original_size = original_size self.embedded_size = embedded_size self.embedded_data = data def extract(self) -> bytes: """Extract attachment data. Returns ------- data : bytes """ if self.flags & v4c.FLAG_AT_EMBEDDED: if self.flags & v4c.FLAG_AT_COMPRESSED_EMBEDDED: data = typing.cast(bytes, decompress(self.embedded_data, bufsize=self.original_size)) # type: ignore[redundant-cast, unused-ignore] else: data = self.embedded_data if self.flags & v4c.FLAG_AT_MD5_VALID: md5_worker = md5() md5_worker.update(data) md5_sum = md5_worker.digest() if self.md5_sum != md5_sum: message = f"ATBLOCK md5sum={self.md5_sum!r} and embedded data md5sum={md5_sum!r}" logger.warning(message) return data else: logger.warning("external attachments not supported") return b"" def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int] ) -> int: text = self.file_name if text: if text in defined_texts: self.file_name_addr = defined_texts[text] else: tx_block = TextBlock(text=str(text)) self.file_name_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.file_name_addr = 0 text = self.mime if text: if text in defined_texts: self.mime_addr = defined_texts[text] else: tx_block = TextBlock(text=text) self.mime_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.mime_addr = 0 text = self.comment if text: if text in defined_texts: self.comment_addr = defined_texts[text] else: meta = text.startswith(" object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: fmt = f"{v4c.FMT_AT_COMMON}{self.embedded_size}s" result = pack(fmt, *[self[key] for key in v4c.KEYS_AT_BLOCK]) return result def __repr__(self) -> str: return f"ATBLOCK(address={self.address:x}, file_name={self.file_name}, comment={self.comment})" class ChannelKwargs(BlockKwargs, total=False): at_map: dict[int, int] tx_map: TxMap parsed_strings: tuple[str, dict[str, str], str] | None use_display_names: bool cc_map: dict[bytes | int, "ChannelConversion"] si_map: dict[Union[bytes, int, "Source"], "SourceInformation"] channel_type: int sync_type: int data_type: int bit_offset: int byte_offset: int bit_count: int flags: int pos_invalidation_bit: int precision: int min_raw_value: float max_raw_value: float lower_limit: float upper_limit: float lower_ext_limit: float upper_ext_limit: float attachment_addr: int CN = b"##CN" class Channel: """If the `load_metadata` keyword argument is not provided or is False, then the conversion, source and display name information is not processed. Furthermore if the `parse_xml_comment` is not provided or is False, then the display name information from the channel comment is not processed (this is done to avoid expensive XML operations). `Channel` has the following attributes, which are also available as dict-like key-value pairs. CNBLOCK fields: * ``id`` - bytes : block ID; always b'##CN' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``next_ch_addr`` - int : next ATBLOCK address * ``component_addr`` - int : address of first channel in case of structure channel composition, or ChannelArrayBlock in case of arrays file name * ``name_addr`` - int : address of TXBLOCK that contains the channel name * ``source_addr`` - int : address of channel source block * ``conversion_addr`` - int : address of channel conversion block * ``data_block_addr`` - int : address of signal data block for VLSD channels * ``unit_addr`` - int : address of TXBLOCK that contains the channel unit * ``comment_addr`` - int : address of TXBLOCK/MDBLOCK that contains the channel comment * ``attachment__addr`` - int : address of N-th ATBLOCK referenced by the current channel; if no ATBLOCK is referenced there will be no such key-value pair * ``default_X_dg_addr`` - int : address of DGBLOCK where the default X axis channel for the current channel is found; this key-value pair will not exist for channels that don't have a default X axis * ``default_X_cg_addr`` - int : address of CGBLOCK where the default X axis channel for the current channel is found; this key-value pair will not exist for channels that don't have a default X axis * ``default_X_ch_addr`` - int : address of default X axis channel for the current channel; this key-value pair will not exist for channels that don't have a default X axis * ``channel_type`` - int : integer code for the channel type * ``sync_type`` - int : integer code for the channel's sync type * ``data_type`` - int : integer code for the channel's data type * ``bit_offset`` - int : bit offset * ``byte_offset`` - int : byte offset within the data record * ``bit_count`` - int : channel bit count * ``flags`` - int : CNBLOCK flags * ``pos_invalidation_bit`` - int : invalidation bit position for the current channel if there are invalidation bytes in the data record * ``precision`` - int : integer code for the precision * ``reserved1`` - int : reserved bytes * ``min_raw_value`` - int : min raw value of all samples * ``max_raw_value`` - int : max raw value of all samples * ``lower_limit`` - int : min physical value of all samples * ``upper_limit`` - int : max physical value of all samples * ``lower_ext_limit`` - int : min physical value of all samples * ``upper_ext_limit`` - int : max physical value of all samples Other attributes: * ``address`` - int : channel address * ``attachments`` - list : list of referenced attachment blocks indexes; the index reference to the attachment block index * ``comment`` - str : channel comment * ``conversion`` - ChannelConversion : channel conversion; None if the channel has no conversion * ``display_name`` - str : channel display name; this is extracted from the XML channel comment * ``name`` - str : channel name * ``source`` - SourceInformation : channel source information; None if the channel has no source information * ``unit`` - str : channel unit Parameters ---------- address : int Block address; to be used for objects created from file. stream : handle File handle; to be used for objects created from file. load_metadata : bool Option to load conversion, source and display_name; default is True. parse_xml_comment : bool Option to parse XML channel comment to search for display name; default is True. for dynamically created objects : See the key-value pairs. """ __slots__ = ( "address", "attachment", "attachment_addr", "attachment_nr", "bit_count", "bit_offset", "block_len", "byte_offset", "channel_type", "comment", "comment_addr", "component_addr", "conversion", "conversion_addr", "data_block_addr", "data_type", "default_X_cg_addr", "default_X_ch_addr", "default_X_dg_addr", "display_names", "dtype_fmt", "fast_path", "flags", "id", "links_nr", "lower_ext_limit", "lower_limit", "max_raw_value", "min_raw_value", "name", "name_addr", "next_ch_addr", "pos_invalidation_bit", "precision", "reserved0", "reserved1", "source", "source_addr", "standard_C_size", "sync_type", "unit", "unit_addr", "upper_ext_limit", "upper_limit", ) def __init__(self, **kwargs: Unpack[ChannelKwargs]) -> None: self.dtype_fmt: np.dtype[Any] = np.dtype(np.void) if "stream" in kwargs: self.address = address = kwargs["address"] self.attachment = None stream = kwargs["stream"] mapped = kwargs["mapped"] if utils.stream_is_mmap(stream, mapped): (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(stream, address) if self.id != b"##CN": message = f'Expected "##CN" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) if self.block_len == CN_BLOCK_SIZE: ( self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) = SIMPLE_CHANNEL_PARAMS_uf(stream, address + COMMON_SIZE) elif self.block_len == CN_SINGLE_ATTACHMENT_BLOCK_SIZE: ( self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, self.attachment_addr, self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) = SINGLE_ATTACHMENT_CHANNEL_PARAMS_uf(stream, address + COMMON_SIZE) self.attachment = kwargs["at_map"].get(self.attachment_addr, 0) else: stream.seek(address + COMMON_SIZE) block = stream.read(self.block_len - COMMON_SIZE) links_nr = self.links_nr links: tuple[int, ...] = unpack_from(f"<{links_nr}Q", block) params: v4c.Channel = unpack_from(v4c.FMT_CHANNEL_PARAMS, block, links_nr * 8) ( self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, ) = links[:8] at_map = kwargs.get("at_map", {}) if params[10]: self.attachment_addr = links[8] self.attachment = at_map.get(links[8], 0) self.links_nr -= params[10] - 1 self.block_len -= (params[10] - 1) * 8 params = ( params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], 1, params[11], params[12], params[13], params[14], params[15], params[16], ) if params[6] & v4c.FLAG_CN_DEFAULT_X: ( self.default_X_dg_addr, self.default_X_cg_addr, self.default_X_ch_addr, ) = links[-3:] # default X not supported yet ( self.default_X_dg_addr, self.default_X_cg_addr, self.default_X_ch_addr, ) = (0, 0, 0) ( self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) = params tx_map = kwargs["tx_map"] parsed_strings = kwargs["parsed_strings"] if parsed_strings is None: self.name = get_text_v4(self.name_addr, stream, mapped=mapped, tx_map=tx_map) self.comment = get_text_v4(self.comment_addr, stream, mapped=mapped, tx_map=tx_map) if kwargs["use_display_names"]: self.display_names = extract_display_names(self.comment) else: self.display_names = {} else: self.name, self.display_names, self.comment = parsed_strings self.unit = get_text_v4(self.unit_addr, stream, mapped=mapped, tx_map=tx_map) address = self.conversion_addr if address: cc_map = kwargs["cc_map"] try: if address in cc_map: conv = cc_map[address] else: (size,) = UINT64_uf(stream, address + 8) raw_bytes = stream[address : address + size] if raw_bytes in cc_map: conv = cc_map[raw_bytes] else: conv = ChannelConversion( raw_bytes=raw_bytes, stream=stream, address=address, mapped=mapped, tx_map=tx_map, ) cc_map[raw_bytes] = cc_map[address] = conv except: logger.warning( f"Channel conversion parsing error: {format_exc()}. The error is ignored and the channel conversion is None" ) conv = None self.conversion = conv else: self.conversion = None address = self.source_addr if address: si_map = kwargs["si_map"] try: if address in si_map: source = si_map[address] else: raw_bytes = stream[address : address + v4c.SI_BLOCK_SIZE] if raw_bytes in si_map: source = si_map[raw_bytes] else: source = SourceInformation( raw_bytes=raw_bytes, stream=stream, address=address, mapped=mapped, tx_map=tx_map, ) si_map[raw_bytes] = si_map[address] = source except: logger.warning( f"Channel source parsing error: {format_exc()}. The error is ignored and the channel source is None" ) source = None self.source = source else: self.source = None else: stream.seek(address) block = stream.read(CN_SINGLE_ATTACHMENT_BLOCK_SIZE) (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(block) if self.id != b"##CN": message = f'Expected "##CN" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) if self.block_len == CN_BLOCK_SIZE: ( self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) = SIMPLE_CHANNEL_PARAMS_uf(block, COMMON_SIZE) elif self.block_len == CN_SINGLE_ATTACHMENT_BLOCK_SIZE: ( self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, self.attachment_addr, self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) = SINGLE_ATTACHMENT_CHANNEL_PARAMS_uf(block, COMMON_SIZE) at_map = kwargs.get("at_map", {}) self.attachment = at_map.get(self.attachment_addr, 0) else: block = block[24:] + stream.read(self.block_len - CN_BLOCK_SIZE) links_nr = self.links_nr links = unpack_from(f"<{links_nr}Q", block) params = unpack_from(v4c.FMT_CHANNEL_PARAMS, block, links_nr * 8) ( self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, ) = links[:8] at_map = kwargs.get("at_map", {}) if params[10]: self.attachment_addr = links[8] self.attachment = at_map.get(links[8], 0) self.links_nr -= params[10] - 1 self.block_len -= (params[10] - 1) * 8 params = ( params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], 1, params[11], params[12], params[13], params[14], params[15], params[16], ) if params[6] & v4c.FLAG_CN_DEFAULT_X: ( self.default_X_dg_addr, self.default_X_cg_addr, self.default_X_ch_addr, ) = links[-3:] # default X not supported yet ( self.default_X_dg_addr, self.default_X_cg_addr, self.default_X_ch_addr, ) = (0, 0, 0) ( self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) = params tx_map = kwargs["tx_map"] parsed_strings = kwargs["parsed_strings"] if parsed_strings is None: self.name = get_text_v4(self.name_addr, stream, tx_map=tx_map) self.comment = get_text_v4(self.comment_addr, stream, tx_map=tx_map) if kwargs["use_display_names"]: self.display_names = extract_display_names(self.comment) else: self.display_names = {} else: self.name, self.display_names, self.comment = parsed_strings self.unit = get_text_v4(self.unit_addr, stream, mapped=mapped, tx_map=tx_map) si_map = kwargs["si_map"] cc_map = kwargs["cc_map"] address = self.conversion_addr if address: try: if address in cc_map: conv = cc_map[address] else: stream.seek(address + 8) (size,) = UINT64_u(stream.read(8)) stream.seek(address) raw_bytes = stream.read(size) if raw_bytes in cc_map: conv = cc_map[raw_bytes] else: conv = ChannelConversion( raw_bytes=raw_bytes, stream=stream, address=address, tx_map=tx_map, mapped=mapped, ) cc_map[raw_bytes] = cc_map[address] = conv except: logger.warning( f"Channel conversion parsing error: {format_exc()}. The error is ignored and the channel conversion is None" ) conv = None self.conversion = conv else: self.conversion = None address = self.source_addr if address: try: if address in si_map: source = si_map[address] else: stream.seek(address) raw_bytes = stream.read(v4c.SI_BLOCK_SIZE) if raw_bytes in si_map: source = si_map[raw_bytes] else: source = SourceInformation( raw_bytes=raw_bytes, stream=stream, address=address, tx_map=tx_map, mapped=mapped, ) si_map[raw_bytes] = si_map[address] = source except: logger.warning( f"Channel source parsing error: {format_exc()}. The error is ignored and the channel source is None" ) source = None self.source = source else: self.source = None else: self.address = 0 self.name = self.comment = self.unit = "" self.display_names = {} self.conversion = self.source = self.attachment = None ( self.id, self.reserved0, self.block_len, self.links_nr, self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) = ( b"##CN", 0, v4c.CN_BLOCK_SIZE, 8, 0, 0, 0, 0, 0, 0, 0, 0, kwargs["channel_type"], kwargs.get("sync_type", 0), kwargs["data_type"], kwargs["bit_offset"], kwargs["byte_offset"], kwargs["bit_count"], kwargs.get("flags", 0), kwargs.get("pos_invalidation_bit", 0), kwargs.get("precision", 3), 0, 0, kwargs.get("min_raw_value", 0), kwargs.get("max_raw_value", 0), kwargs.get("lower_limit", 0), kwargs.get("upper_limit", 0), kwargs.get("lower_ext_limit", 0), kwargs.get("upper_ext_limit", 0), ) if "attachment_addr" in kwargs: self.attachment_addr = kwargs["attachment_addr"] self.block_len += 8 self.links_nr += 1 self.attachment_nr = 1 # ignore MLSD signal data if self.channel_type == v4c.CHANNEL_TYPE_MLSD: self.data_block_addr = 0 self.channel_type = v4c.CHANNEL_TYPE_VALUE if self.name in self.display_names: del self.display_names[self.name] self.standard_C_size = True self.fast_path: tuple[int, int, int, int, int, np.dtype[Any]] | None = None def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int], cc_map: dict[bytes | int, int], si_map: dict[bytes | int, int], ) -> int: text = self.name if text in defined_texts: self.name_addr = defined_texts[text] else: tx_block = TextBlock( text=text.encode("utf-8", "replace"), meta=False, safe=True, ) self.name_addr = defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) text = self.unit if text in defined_texts: self.unit_addr = defined_texts[text] else: tx_block = TextBlock( text=text.encode("utf-8", "replace"), meta=False, safe=True, ) self.unit_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) comment = self.comment display_names = self.display_names if display_names: items = [] for _name, description in display_names.items(): description = "display" items.append(f"<{description}>{_name}") display_names_tags = "\n".join(items) else: display_names_tags = "" if display_names_tags and not comment: text = v4c.CN_COMMENT_TEMPLATE.format("", display_names_tags) elif display_names_tags and comment: if not comment.startswith(" bytes: if self.block_len == v4c.CN_BLOCK_SIZE: return v4c.SIMPLE_CHANNEL_PACK( self.id, self.reserved0, self.block_len, self.links_nr, self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) elif self.attachment_nr == 1: return v4c.SINGLE_ATTACHMENT_CHANNEL_PACK( self.id, self.reserved0, self.block_len, self.links_nr, self.next_ch_addr, self.component_addr, self.name_addr, self.source_addr, self.conversion_addr, self.data_block_addr, self.unit_addr, self.comment_addr, self.attachment_addr, self.channel_type, self.sync_type, self.data_type, self.bit_offset, self.byte_offset, self.bit_count, self.flags, self.pos_invalidation_bit, self.precision, self.reserved1, self.attachment_nr, self.min_raw_value, self.max_raw_value, self.lower_limit, self.upper_limit, self.lower_ext_limit, self.upper_ext_limit, ) else: fmt = v4c.FMT_CHANNEL.format(self.links_nr) keys: tuple[str, ...] = ( "id", "reserved0", "block_len", "links_nr", "next_ch_addr", "component_addr", "name_addr", "source_addr", "conversion_addr", "data_block_addr", "unit_addr", "comment_addr", ) if self.attachment_nr: keys += ("attachment_addr",) if self.flags & v4c.FLAG_CN_DEFAULT_X: keys += ("default_X_dg_addr", "default_X_cg_addr", "default_X_ch_addr") keys += ( "channel_type", "sync_type", "data_type", "bit_offset", "byte_offset", "bit_count", "flags", "pos_invalidation_bit", "precision", "reserved1", "attachment_nr", "min_raw_value", "max_raw_value", "lower_limit", "upper_limit", "lower_ext_limit", "upper_ext_limit", ) return pack(fmt, *[getattr(self, key) for key in keys]) def __str__(self) -> str: return f"""""" def metadata(self) -> str: keys: tuple[str, ...] if self.block_len == v4c.CN_BLOCK_SIZE: keys = v4c.KEYS_SIMPLE_CHANNEL else: keys = ( "id", "reserved0", "block_len", "links_nr", "next_ch_addr", "component_addr", "name_addr", "source_addr", "conversion_addr", "data_block_addr", "unit_addr", "comment_addr", ) if self.attachment_nr: keys += ("attachment_addr",) if self.flags & v4c.FLAG_CN_DEFAULT_X: keys += ("default_X_dg_addr", "default_X_cg_addr", "default_X_ch_addr") keys += ( "channel_type", "sync_type", "data_type", "bit_offset", "byte_offset", "bit_count", "flags", "pos_invalidation_bit", "precision", "reserved1", "attachment_nr", "min_raw_value", "max_raw_value", "lower_limit", "upper_limit", "lower_ext_limit", "upper_ext_limit", ) max_len = max(len(key) for key in keys) template = f"{{: <{max_len}}}: {{}}" metadata: list[str] = [] lines = f""" name: {self.name} display names: {self.display_names} address: {hex(self.address)} comment: {self.comment} unit: {self.unit} """.split("\n") for key in keys: val = getattr(self, key) if key.endswith("addr") or key.startswith("text_"): lines.append(template.format(key, hex(val))) elif isinstance(val, float): lines.append(template.format(key, val)) else: if isinstance(val, bytes): lines.append(template.format(key, val.strip(b"\0"))) else: lines.append(template.format(key, val)) if key == "data_type": lines[-1] += f" = {v4c.DATA_TYPE_TO_STRING[self.data_type]}" elif key == "channel_type": lines[-1] += f" = {v4c.CHANNEL_TYPE_TO_STRING[self.channel_type]}" elif key == "sync_type": lines[-1] += f" = {v4c.SYNC_TYPE_TO_STRING[self.sync_type]}" elif key == "flags": flags = [] for fl, string in v4c.FLAG_CN_TO_STRING.items(): if self.flags & fl: flags.append(string) if flags: lines[-1] += f" [0x{self.flags:X}= {', '.join(flags)}]" for line in lines: if not line: metadata.append(line) else: for wrapped_line in wrap(line, width=120): metadata.append(wrapped_line) return "\n".join(metadata) def __contains__(self, item: str) -> bool: return hasattr(self, item) def __lt__(self, other: "Channel") -> bool: self_byte_offset = self.byte_offset other_byte_offset = other.byte_offset if self_byte_offset < other_byte_offset: result = True elif self_byte_offset == other_byte_offset: self_range = self.bit_offset + self.bit_count other_range = other.bit_offset + other.bit_count if self_range > other_range: result = True else: result = False else: result = False return result class _ChannelArrayBlockBase: __slots__ = ( "address", "axis_channels", "axis_conversions", "block_len", "byte_offset_base", "ca_type", "comparison_quantity_channel", "dims", "dynamic_size_channels", "flags", "id", "input_quantity_channels", "invalidation_bit_base", "links_nr", "output_quantity_channel", "reserved0", "storage", ) class ChannelArrayBlockKwargs(BlockKwargs, total=False): ca_type: int dims: int dim_size_0: int flags: int byte_offset_base: int invalidation_bit_base: int class ChannelArrayBlock(_ChannelArrayBlockBase): """ Other attributes: * ``address`` - int : array block address * ``axis_channels`` - list : list of (group index, channel index) pairs referencing the axis of this array block * ``axis_conversions`` - list : list of ChannelConversion or None for each axis of this array block * ``dynamic_size_channels`` - list : list of (group index, channel index) pairs referencing the axis dynamic size of this array block * ``input_quantity_channels`` - list : list of (group index, channel index) pairs referencing the input quantity channels of this array block * ``output_quantity_channels`` - tuple | None : (group index, channel index) pair referencing the output quantity channel of this array block * ``comparison_quantity_channel`` - tuple | None : (group index, channel index) pair referencing the comparison quantity channel of this array block """ def __init__(self, **kwargs: Unpack[ChannelArrayBlockKwargs]) -> None: self.axis_channels: list[tuple[int, int] | None] = [] self.dynamic_size_channels: list[tuple[int, int] | None] = [] self.input_quantity_channels: list[tuple[int, int] | None] = [] self.output_quantity_channel: tuple[int, int] | None = None self.comparison_quantity_channel: tuple[int, int] | None = None self.axis_conversions: list[ChannelConversion | None] = [] try: self.address = address = kwargs["address"] stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) if utils.stream_is_mmap(stream, mapped): (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(stream, address) if self.id != b"##CA": message = f'Expected "##CA" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) nr = self.links_nr address += COMMON_SIZE links: tuple[int, ...] = unpack_from(f"<{nr}Q", stream, address) self.composition_addr = links[0] links = links[1:] address += nr * 8 values: tuple[int, int, int, int, int, int] = unpack_from("<2BHIiI", stream, address) dims_nr = values[2] ( self.ca_type, self.storage, self.dims, self.flags, self.byte_offset_base, self.invalidation_bit_base, ) = values address += 16 dim_sizes: tuple[int, ...] = unpack_from(f"<{dims_nr}Q", stream, address) for i, size in enumerate(dim_sizes): self[f"dim_size_{i}"] = size stream.seek(address + dims_nr * 8) if self.storage == v4c.CA_STORAGE_TYPE_DG_TEMPLATE: data_links_nr = 1 for size in dim_sizes: data_links_nr *= size for i in range(data_links_nr): self[f"data_link_{i}"] = links[i] links = links[data_links_nr:] if self.flags & v4c.FLAG_CA_DYNAMIC_AXIS: for i in range(dims_nr): self[f"dynamic_size_{i}_dg_addr"] = links[3 * i] self[f"dynamic_size_{i}_cg_addr"] = links[3 * i + 1] self[f"dynamic_size_{i}_ch_addr"] = links[3 * i + 2] links = links[dims_nr * 3 :] if self.flags & v4c.FLAG_CA_INPUT_QUANTITY: for i in range(dims_nr): self[f"input_quantity_{i}_dg_addr"] = links[3 * i] self[f"input_quantity_{i}_cg_addr"] = links[3 * i + 1] self[f"input_quantity_{i}_ch_addr"] = links[3 * i + 2] links = links[dims_nr * 3 :] if self.flags & v4c.FLAG_CA_OUTPUT_QUANTITY: self.output_quantity_dg_addr = links[0] self.output_quantity_cg_addr = links[1] self.output_quantity_ch_addr = links[2] links = links[3:] if self.flags & v4c.FLAG_CA_COMPARISON_QUANTITY: self.comparison_quantity_dg_addr = links[0] self.comparison_quantity_cg_addr = links[1] self.comparison_quantity_ch_addr = links[2] links = links[3:] if self.flags & v4c.FLAG_CA_AXIS: for i in range(dims_nr): self[f"axis_conversion_{i}"] = links[i] links = links[dims_nr:] if (self.flags & v4c.FLAG_CA_AXIS) and not (self.flags & v4c.FLAG_CA_FIXED_AXIS): for i in range(dims_nr): self[f"scale_axis_{i}_dg_addr"] = links[3 * i] self[f"scale_axis_{i}_cg_addr"] = links[3 * i + 1] self[f"scale_axis_{i}_ch_addr"] = links[3 * i + 2] links = links[dims_nr * 3 :] if self.flags & v4c.FLAG_CA_FIXED_AXIS: for i in range(dims_nr): for j in range(typing.cast(int, self[f"dim_size_{i}"])): (value,) = FLOAT64_u(stream.read(8)) self[f"axis_{i}_value_{j}"] = value else: stream.seek(address) (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_u(stream.read(24)) if self.id != b"##CA": message = f'Expected "##CA" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) nr = self.links_nr links = unpack(f"<{nr}Q", stream.read(8 * nr)) self.composition_addr = links[0] links = links[1:] values = unpack("<2BHIiI", stream.read(16)) dims_nr = values[2] ( self.ca_type, self.storage, self.dims, self.flags, self.byte_offset_base, self.invalidation_bit_base, ) = values dim_sizes = unpack(f"<{dims_nr}Q", stream.read(8 * dims_nr)) for i, size in enumerate(dim_sizes): self[f"dim_size_{i}"] = size if self.storage == v4c.CA_STORAGE_TYPE_DG_TEMPLATE: data_links_nr = 1 for size in dim_sizes: data_links_nr *= size for i in range(data_links_nr): self[f"data_link_{i}"] = links[i] links = links[data_links_nr:] if self.flags & v4c.FLAG_CA_DYNAMIC_AXIS: for i in range(dims_nr): self[f"dynamic_size_{i}_dg_addr"] = links[3 * i] self[f"dynamic_size_{i}_cg_addr"] = links[3 * i + 1] self[f"dynamic_size_{i}_ch_addr"] = links[3 * i + 2] links = links[dims_nr * 3 :] if self.flags & v4c.FLAG_CA_INPUT_QUANTITY: for i in range(dims_nr): self[f"input_quantity_{i}_dg_addr"] = links[3 * i] self[f"input_quantity_{i}_cg_addr"] = links[3 * i + 1] self[f"input_quantity_{i}_ch_addr"] = links[3 * i + 2] links = links[dims_nr * 3 :] if self.flags & v4c.FLAG_CA_OUTPUT_QUANTITY: self.output_quantity_dg_addr = links[0] self.output_quantity_cg_addr = links[1] self.output_quantity_ch_addr = links[2] links = links[3:] if self.flags & v4c.FLAG_CA_COMPARISON_QUANTITY: self.comparison_quantity_dg_addr = links[0] self.comparison_quantity_cg_addr = links[1] self.comparison_quantity_ch_addr = links[2] links = links[3:] if self.flags & v4c.FLAG_CA_AXIS: for i in range(dims_nr): self[f"axis_conversion_{i}"] = links[i] links = links[dims_nr:] if (self.flags & v4c.FLAG_CA_AXIS) and not (self.flags & v4c.FLAG_CA_FIXED_AXIS): for i in range(dims_nr): self[f"scale_axis_{i}_dg_addr"] = links[3 * i] self[f"scale_axis_{i}_cg_addr"] = links[3 * i + 1] self[f"scale_axis_{i}_ch_addr"] = links[3 * i + 2] links = links[dims_nr * 3 :] if self.flags & v4c.FLAG_CA_FIXED_AXIS: for i in range(dims_nr): for j in range(typing.cast(int, self[f"dim_size_{i}"])): (value,) = FLOAT64_u(stream.read(8)) self[f"axis_{i}_value_{j}"] = value except KeyError: self.id = b"##CA" self.reserved0 = 0 self.address = 0 ca_type = kwargs["ca_type"] if ca_type == v4c.CA_TYPE_ARRAY: dims_nr = kwargs["dims"] self.block_len = 48 + dims_nr * 8 self.links_nr = 1 self.composition_addr = 0 self.ca_type = v4c.CA_TYPE_ARRAY self.storage = v4c.CA_STORAGE_TYPE_CN_TEMPLATE self.dims = dims_nr self.flags = 0 self.byte_offset_base = kwargs.get("byte_offset_base", 1) self.invalidation_bit_base = kwargs.get("invalidation_bit_base", 0) for i in range(dims_nr): self[f"dim_size_{i}"] = kwargs[f"dim_size_{i}"] # type: ignore[literal-required] elif ca_type == v4c.CA_TYPE_SCALE_AXIS: self.block_len = 56 self.links_nr = 1 self.composition_addr = 0 self.ca_type = v4c.CA_TYPE_SCALE_AXIS self.storage = v4c.CA_STORAGE_TYPE_CN_TEMPLATE self.dims = 1 self.flags = 0 self.byte_offset_base = kwargs.get("byte_offset_base", 1) self.invalidation_bit_base = kwargs.get("invalidation_bit_base", 0) self.dim_size_0 = kwargs["dim_size_0"] elif ca_type == v4c.CA_TYPE_LOOKUP: flags = kwargs["flags"] dims_nr = kwargs["dims"] dim_size_sum = sum(kwargs[f"dim_size_{i}"] for i in range(dims_nr)) # type: ignore[literal-required] if flags & v4c.FLAG_CA_FIXED_AXIS: self.block_len = 48 + dims_nr * 16 + dim_size_sum * 8 self.links_nr = 1 + dims_nr self.composition_addr = 0 for i in range(dims_nr): self[f"axis_conversion_{i}"] = 0 self.ca_type = v4c.CA_TYPE_LOOKUP self.storage = v4c.CA_STORAGE_TYPE_CN_TEMPLATE self.dims = dims_nr self.flags = v4c.FLAG_CA_FIXED_AXIS | v4c.FLAG_CA_AXIS self.byte_offset_base = kwargs.get("byte_offset_base", 1) self.invalidation_bit_base = kwargs.get("invalidation_bit_base", 0) for i in range(dims_nr): self[f"dim_size_{i}"] = kwargs[f"dim_size_{i}"] # type: ignore[literal-required] for i in range(dims_nr): for j in range(typing.cast(int, self[f"dim_size_{i}"])): self[f"axis_{i}_value_{j}"] = kwargs.get(f"axis_{i}_value_{j}", j) else: self.block_len = 48 + dims_nr * 5 * 8 self.links_nr = 1 + dims_nr * 4 self.composition_addr = 0 for i in range(dims_nr): self[f"axis_conversion_{i}"] = 0 for i in range(dims_nr): self[f"scale_axis_{i}_dg_addr"] = 0 self[f"scale_axis_{i}_cg_addr"] = 0 self[f"scale_axis_{i}_ch_addr"] = 0 self.ca_type = v4c.CA_TYPE_LOOKUP self.storage = v4c.CA_STORAGE_TYPE_CN_TEMPLATE self.dims = dims_nr self.flags = v4c.FLAG_CA_AXIS self.byte_offset_base = kwargs.get("byte_offset_base", 1) self.invalidation_bit_base = kwargs.get("invalidation_bit_base", 0) for i in range(dims_nr): self[f"dim_size_{i}"] = kwargs[f"dim_size_{i}"] # type: ignore[literal-required] def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __str__(self) -> str: return f"" def __bytes__(self) -> bytes: flags = self.flags dims_nr = self.dims keys: tuple[str, ...] = ( "id", "reserved0", "block_len", "links_nr", "composition_addr", ) if self.storage: dim_sizes = [typing.cast(int, self[f"dim_size_{i}"]) for i in range(dims_nr)] data_links_nr = 1 for size in dim_sizes: data_links_nr *= size else: dim_sizes = [] data_links_nr = 0 if self.storage == v4c.CA_STORAGE_TYPE_DG_TEMPLATE: keys += tuple(f"data_link_{i}" for i in range(data_links_nr)) if flags & v4c.FLAG_CA_DYNAMIC_AXIS: for i in range(dims_nr): keys += ( f"dynamic_size_{i}_dg_addr", f"dynamic_size_{i}_cg_addr", f"dynamic_size_{i}_ch_addr", ) if flags & v4c.FLAG_CA_INPUT_QUANTITY: for i in range(dims_nr): keys += ( f"input_quantity_{i}_dg_addr", f"input_quantity_{i}_cg_addr", f"input_quantity_{i}_ch_addr", ) if flags & v4c.FLAG_CA_OUTPUT_QUANTITY: keys += ( "output_quantity_dg_addr", "output_quantity_cg_addr", "output_quantity_ch_addr", ) if flags & v4c.FLAG_CA_COMPARISON_QUANTITY: keys += ( "comparison_quantity_dg_addr", "comparison_quantity_cg_addr", "comparison_quantity_ch_addr", ) if flags & v4c.FLAG_CA_AXIS: keys += tuple(f"axis_conversion_{i}" for i in range(dims_nr)) if (flags & v4c.FLAG_CA_AXIS) and not (flags & v4c.FLAG_CA_FIXED_AXIS): for i in range(dims_nr): keys += ( f"scale_axis_{i}_dg_addr", f"scale_axis_{i}_cg_addr", f"scale_axis_{i}_ch_addr", ) keys += ( "ca_type", "storage", "dims", "flags", "byte_offset_base", "invalidation_bit_base", ) keys += tuple(f"dim_size_{i}" for i in range(dims_nr)) if flags & v4c.FLAG_CA_FIXED_AXIS: keys += tuple( f"axis_{i}_value_{j}" for i in range(dims_nr) for j in range(typing.cast(int, self[f"dim_size_{i}"])) ) dim_sizes = [1 for i in range(dims_nr) for j in range(typing.cast(int, self[f"dim_size_{i}"]))] if self.storage: keys += tuple(f"cycle_count_{i}" for i in range(data_links_nr)) fmt = f"<4sI{self.links_nr + 2}Q2BHIiI{dims_nr}Q{sum(dim_sizes)}d{data_links_nr}Q" result = pack(fmt, *[getattr(self, key) for key in keys]) return result def get_byte_offset_factors(self) -> list[int]: """Return a list of factors f(d), used to calculate byte offset.""" return self._factors(self.byte_offset_base) def get_bit_pos_inval_factors(self) -> list[int]: """Return a list of factors f(d), used to calculate invalidation bit position. """ return self._factors(self.invalidation_bit_base) def _factors(self, base: int) -> list[int]: factor = base factors = [factor] # column oriented layout if self.flags & v4c.FLAG_CA_INVERSE_LAYOUT: for i in range(1, self.dims): factor *= typing.cast(int, self[f"dim_size_{i - 1}"]) factors.append(factor) # row oriented layout else: for i in range(self.dims - 2, -1, -1): factor *= typing.cast(int, self[f"dim_size_{i + 1}"]) factors.insert(0, factor) return factors class ChannelGroupKwargs(BlockKwargs, total=False): reserved0: int next_cg_addr: int first_ch_addr: int acq_name_addr: int acq_source_addr: int first_sample_reduction_addr: int comment_addr: int record_id: int cycles_nr: int flags: int path_separator: int reserved1: int samples_byte_nr: int invalidation_bytes_nr: int cg_master_addr: int tx_map: TxMap si_map: dict[Union[bytes, int, "Source"], "SourceInformation"] class ChannelGroup: """`ChannelGroup` has the following attributes, which are also available as dict-like key-value pairs. CGBLOCK fields: * ``id`` - bytes : block ID; always b'##CG' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``next_cg_addr`` - int : next channel group address * ``first_ch_addr`` - int : address of first channel of this channel group * ``acq_name_addr`` - int : address of TextBLock that contains the channel group acquisition name * ``acq_source_addr`` - int : address of SourceInformation that contains the channel group source * ``first_sample_reduction_addr`` - int : address of first SRBLOCK; this is considered 0 since sample reduction is not yet supported * ``comment_addr`` - int : address of TXBLOCK/MDBLOCK that contains the channel group comment * ``record_id`` - int : record ID for the channel group * ``cycles_nr`` - int : number of cycles for this channel group * ``flags`` - int : channel group flags * ``path_separator`` - int : ordinal for character used as path separator * ``reserved1`` - int : reserved bytes * ``samples_byte_nr`` - int : number of bytes used for channels samples in the record for this channel group; this does not contain the invalidation bytes * ``invalidation_bytes_nr`` - int : number of bytes used for invalidation bits by this channel group Other attributes: * ``acq_name`` - str : acquisition name * ``acq_source`` - SourceInformation : acquisition source information * ``address`` - int : channel group address * ``comment`` - str : channel group comment """ __slots__ = ( "acq_name", "acq_name_addr", "acq_source", "acq_source_addr", "address", "block_len", "cg_master_addr", "cg_master_index", "comment", "comment_addr", "cycles_nr", "first_ch_addr", "first_sample_reduction_addr", "flags", "id", "invalidation_bytes_nr", "links_nr", "next_cg_addr", "path_separator", "record_id", "reserved0", "reserved1", "samples_byte_nr", ) def __init__(self, **kwargs: Unpack[ChannelGroupKwargs]) -> None: self.comment = "" self.acq_name: str | None = "" self.acq_source = None self.cg_master_index: int | None = None try: self.address = address = kwargs["address"] stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) if utils.stream_is_mmap(stream, mapped): (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(stream, address) if self.block_len == v4c.CG_BLOCK_SIZE: ( self.next_cg_addr, self.first_ch_addr, self.acq_name_addr, self.acq_source_addr, self.first_sample_reduction_addr, self.comment_addr, self.record_id, self.cycles_nr, self.flags, self.path_separator, self.reserved1, self.samples_byte_nr, self.invalidation_bytes_nr, ) = v4c.CHANNEL_GROUP_SHORT_uf(stream, address + COMMON_SIZE) else: ( self.next_cg_addr, self.first_ch_addr, self.acq_name_addr, self.acq_source_addr, self.first_sample_reduction_addr, self.comment_addr, self.cg_master_addr, self.record_id, self.cycles_nr, self.flags, self.path_separator, self.reserved1, self.samples_byte_nr, self.invalidation_bytes_nr, ) = v4c.CHANNEL_GROUP_RM_SHORT_uf(stream, address + COMMON_SIZE) else: stream.seek(address) ( self.id, self.reserved0, self.block_len, self.links_nr, ) = v4c.COMMON_u(stream.read(COMMON_SIZE)) if self.block_len == v4c.CG_BLOCK_SIZE: ( self.next_cg_addr, self.first_ch_addr, self.acq_name_addr, self.acq_source_addr, self.first_sample_reduction_addr, self.comment_addr, self.record_id, self.cycles_nr, self.flags, self.path_separator, self.reserved1, self.samples_byte_nr, self.invalidation_bytes_nr, ) = v4c.CHANNEL_GROUP_SHORT_u(stream.read(v4c.CG_BLOCK_SIZE - COMMON_SIZE)) else: ( self.next_cg_addr, self.first_ch_addr, self.acq_name_addr, self.acq_source_addr, self.first_sample_reduction_addr, self.comment_addr, self.cg_master_addr, self.record_id, self.cycles_nr, self.flags, self.path_separator, self.reserved1, self.samples_byte_nr, self.invalidation_bytes_nr, ) = v4c.CHANNEL_GROUP_RM_SHORT_u(stream.read(v4c.CG_RM_BLOCK_SIZE - COMMON_SIZE)) if self.id != b"##CG": message = f'Expected "##CG" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) tx_map = kwargs.get("tx_map", {}) self.acq_name = get_text_v4(self.acq_name_addr, stream, mapped=mapped, tx_map=tx_map) self.comment = get_text_v4(self.comment_addr, stream, mapped=mapped, tx_map=tx_map) si_map = kwargs["si_map"] address = self.acq_source_addr if address: if utils.stream_is_mmap(stream, mapped): raw_bytes = stream[address : address + v4c.SI_BLOCK_SIZE] else: stream.seek(address) raw_bytes = stream.read(v4c.SI_BLOCK_SIZE) if raw_bytes in si_map: source = si_map[raw_bytes] else: source = SourceInformation( raw_bytes=raw_bytes, stream=stream, address=address, mapped=mapped, tx_map=tx_map, ) si_map[raw_bytes] = source self.acq_source = source else: self.acq_source = None except KeyError: self.address = 0 self.id = b"##CG" self.reserved0 = kwargs.get("reserved0", 0) self.next_cg_addr = kwargs.get("next_cg_addr", 0) self.first_ch_addr = kwargs.get("first_ch_addr", 0) self.acq_name_addr = kwargs.get("acq_name_addr", 0) self.acq_source_addr = kwargs.get("acq_source_addr", 0) self.first_sample_reduction_addr = kwargs.get("first_sample_reduction_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.record_id = kwargs.get("record_id", 1) self.cycles_nr = kwargs.get("cycles_nr", 0) self.flags = kwargs.get("flags", 0) self.path_separator = kwargs.get("path_separator", 0) self.reserved1 = kwargs.get("reserved1", 0) self.samples_byte_nr = kwargs.get("samples_byte_nr", 0) self.invalidation_bytes_nr = kwargs.get("invalidation_bytes_nr", 0) if self.flags & v4c.FLAG_CG_REMOTE_MASTER: self.cg_master_addr = kwargs.get("cg_master_addr", 0) self.block_len = v4c.CG_RM_BLOCK_SIZE self.links_nr = 7 else: self.block_len = v4c.CG_BLOCK_SIZE self.links_nr = 6 def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int], si_map: dict[bytes | int, int], ) -> int: text = self.acq_name if text: if text in defined_texts: self.acq_name_addr = defined_texts[text] else: tx_block = TextBlock(text=text) self.acq_name_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.acq_name_addr = 0 text = self.comment if text: if text in defined_texts: self.comment_addr = defined_texts[text] else: meta = text.startswith(" bytes: if self.flags & v4c.FLAG_CG_REMOTE_MASTER: result = v4c.CHANNEL_GROUP_RM_p( self.id, self.reserved0, self.block_len, self.links_nr, self.next_cg_addr, self.first_ch_addr, self.acq_name_addr, self.acq_source_addr, self.first_sample_reduction_addr, self.comment_addr, self.cg_master_addr, self.record_id, self.cycles_nr, self.flags, self.path_separator, self.reserved1, self.samples_byte_nr, self.invalidation_bytes_nr, ) else: result = v4c.CHANNEL_GROUP_p( self.id, self.reserved0, self.block_len, self.links_nr, self.next_cg_addr, self.first_ch_addr, self.acq_name_addr, self.acq_source_addr, self.first_sample_reduction_addr, self.comment_addr, self.record_id, self.cycles_nr, self.flags, self.path_separator, self.reserved1, self.samples_byte_nr, self.invalidation_bytes_nr, ) return result def metadata(self) -> str: keys: tuple[str, ...] = ( "id", "reserved0", "block_len", "links_nr", "next_cg_addr", "first_ch_addr", "acq_name_addr", "acq_source_addr", "first_sample_reduction_addr", "comment_addr", ) if self.block_len == v4c.CG_RM_BLOCK_SIZE: keys += ("cg_master_addr",) keys += ( "record_id", "cycles_nr", "flags", "path_separator", "reserved1", "samples_byte_nr", "invalidation_bytes_nr", ) max_len = max(len(key) for key in keys) template = f"{{: <{max_len}}}: {{}}" metadata: list[str] = [] lines = f""" name: {self.acq_name} address: {hex(self.address)} comment: {self.comment} """.split("\n") for key in keys: val = getattr(self, key) if key.endswith("addr") or key.startswith("text_"): lines.append(template.format(key, hex(val))) elif isinstance(val, float): lines.append(template.format(key, val)) else: if isinstance(val, bytes): lines.append(template.format(key, val.strip(b"\0"))) else: lines.append(template.format(key, val)) if key == "flags": flags = [] for fl, string in v4c.FLAG_CG_TO_STRING.items(): if self.flags & fl: flags.append(string) if flags: lines[-1] += f" [0x{self.flags:X}= {', '.join(flags)}]" elif key == "path_separator": if self.path_separator: sep = pack("`` - float : N-th raw value * ``phys_`` - float : N-th physical value * tabular range conversion * ``lower_`` - float : N-th lower value * ``upper_`` - float : N-th upper value * ``phys_`` - float : N-th physical value * tabular value to text conversion * ``val_`` - float : N-th raw value * ``text_`` - int : address of N-th TXBLOCK that contains the physical value * ``default`` - int : address of TXBLOCK that contains the default physical value * tabular range to text conversion * ``lower_`` - float : N-th lower value * ``upper_`` - float : N-th upper value * ``text_`` - int : address of N-th TXBLOCK that contains the physical value * ``default`` - int : address of TXBLOCK that contains the default physical value * text to value conversion * ``val_`` - float : N-th physical value * ``text_`` - int : address of N-th TXBLOCK that contains the raw value * ``val_default`` - float : default physical value * text transformation (translation) conversion * ``input__addr`` - int : address of N-th TXBLOCK that contains the raw value * ``output__addr`` - int : address of N-th TXBLOCK that contains the physical value * ``default_addr`` - int : address of TXBLOCK that contains the default physical value Other attributes: * ``address`` - int : channel conversion address * ``comment`` - str : channel conversion comment * ``formula`` - str : algebraic conversion formula; default '' * ``referenced_blocks`` - dict : dict of referenced blocks; can be TextBlock objects for value to text, and text to text conversions; for partial conversions the referenced blocks can be ChannelConversion object as well * ``name`` - str : channel conversion name * ``unit`` - str : channel conversion unit """ def __init__(self, **kwargs: Unpack[ChannelConversionKwargs]) -> None: self._cache: _Cache | None = None self.is_user_defined = False if "stream" in kwargs: stream = kwargs["stream"] mapped = kwargs["mapped"] try: self.address = address = kwargs["address"] tx_block = kwargs["raw_bytes"] (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(tx_block) if self.id != b"##CC": message = f'Expected "##CC" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) tx_block = tx_block[COMMON_SIZE:] except KeyError: self.address = address = kwargs["address"] stream.seek(address) (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_u(stream.read(COMMON_SIZE)) if self.id != b"##CC": message = f'Expected "##CC" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) from None tx_block = stream.read(self.block_len - COMMON_SIZE) (conv,) = UINT8_uf(tx_block, self.links_nr * 8) if conv == v4c.CONVERSION_TYPE_NON: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = v4c.CONVERSION_NONE_INIT_u(tx_block) elif conv == v4c.CONVERSION_TYPE_LIN: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, self.b, self.a, ) = v4c.CONVERSION_LINEAR_INIT_u(tx_block) elif conv == v4c.CONVERSION_TYPE_RAT: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, self.P1, self.P2, self.P3, self.P4, self.P5, self.P6, ) = typing.cast(v4c.ConversionRatInit, unpack(v4c.FMT_CONVERSION_RAT_INIT, tx_block)) elif conv == v4c.CONVERSION_TYPE_ALG: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.formula_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = typing.cast(v4c.ConversionAlgebraicInit, unpack(v4c.FMT_CONVERSION_ALGEBRAIC_INIT, tx_block)) elif conv in (v4c.CONVERSION_TYPE_TABI, v4c.CONVERSION_TYPE_TAB): ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = v4c.CONVERSION_NONE_INIT_uf(tx_block) nr = self.val_param_nr values: tuple[float, ...] = unpack_from(f"<{nr}d", tx_block, 56) for i in range(nr // 2): self[f"raw_{i}"], self[f"phys_{i}"] = ( values[i * 2], values[2 * i + 1], ) elif conv == v4c.CONVERSION_TYPE_RTAB: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = v4c.CONVERSION_NONE_INIT_uf(tx_block) nr = self.val_param_nr values = unpack_from(f"<{nr}d", tx_block, 56) for i in range((nr - 1) // 3): (self[f"lower_{i}"], self[f"upper_{i}"], self[f"phys_{i}"]) = ( values[i * 3], values[3 * i + 1], values[3 * i + 2], ) (self.default,) = FLOAT64_u(tx_block[-8:]) elif conv == v4c.CONVERSION_TYPE_TABX: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, ) = typing.cast(tuple[int, int, int, int], unpack_from("<4Q", tx_block)) links_nr = self.links_nr - 4 links: tuple[int, ...] = unpack_from(f"<{links_nr}Q", tx_block, 32) for i, link in enumerate(links[:-1]): self[f"text_{i}"] = link self.default_addr = links[-1] ( self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = typing.cast( tuple[int, int, int, int, int, float, float], unpack_from("<2B3H2d", tx_block, 32 + links_nr * 8) ) values = unpack_from(f"<{links_nr - 1}d", tx_block, 32 + links_nr * 8 + 24) for i, val in enumerate(values): self[f"val_{i}"] = val elif conv == v4c.CONVERSION_TYPE_RTABX: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, ) = typing.cast(tuple[int, int, int, int], unpack_from("<4Q", tx_block)) links_nr = self.links_nr - 4 links = unpack_from(f"<{links_nr}Q", tx_block, 32) for i, link in enumerate(links[:-1]): self[f"text_{i}"] = link self.default_addr = links[-1] ( self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = typing.cast( tuple[int, int, int, int, int, float, float], unpack_from("<2B3H2d", tx_block, 32 + links_nr * 8) ) values = unpack_from(f"<{self.val_param_nr}d", tx_block, 32 + links_nr * 8 + 24) self.default_lower = self.default_upper = 0 for i in range(self.val_param_nr // 2): j = 2 * i self[f"lower_{i}"] = values[j] self[f"upper_{i}"] = values[j + 1] elif conv == v4c.CONVERSION_TYPE_TTAB: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, ) = typing.cast(tuple[int, int, int, int], unpack_from("<4Q", tx_block)) links_nr = self.links_nr - 4 links = unpack_from(f"<{links_nr}Q", tx_block, 32) for i, link in enumerate(links): self[f"text_{i}"] = link ( self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = typing.cast( tuple[int, int, int, int, int, float, float], unpack_from("<2B3H2d", tx_block, 32 + links_nr * 8) ) values = unpack_from(f"<{self.val_param_nr}d", tx_block, 32 + links_nr * 8 + 24) for i, val in enumerate(values[:-1]): self[f"val_{i}"] = val self.val_default = values[-1] elif conv == v4c.CONVERSION_TYPE_TRANS: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, ) = typing.cast(tuple[int, int, int, int], unpack_from("<4Q", tx_block)) links_nr = self.links_nr - 4 links = unpack_from(f"<{links_nr}Q", tx_block, 32) for i in range((links_nr - 1) // 2): j = 2 * i self[f"input_{i}_addr"] = links[j] self[f"output_{i}_addr"] = links[j + 1] self.default_addr = links[-1] ( self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = typing.cast( tuple[int, int, int, int, int, float, float], unpack_from("<2B3H2d", tx_block, 32 + links_nr * 8) ) elif conv == v4c.CONVERSION_TYPE_BITFIELD: ( self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, ) = typing.cast(tuple[int, int, int, int], unpack_from("<4Q", tx_block)) links_nr = self.links_nr - 4 links = unpack_from(f"<{links_nr}Q", tx_block, 32) for i, link in enumerate(links): self[f"text_{i}"] = link ( self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) = typing.cast( tuple[int, int, int, int, int, float, float], unpack_from("<2B3H2d", tx_block, 32 + links_nr * 8) ) values = unpack_from(f"<{self.val_param_nr}Q", tx_block, 32 + links_nr * 8 + 24) for i, val in enumerate(values): self[f"mask_{i}"] = val self.referenced_blocks: dict[str, bytes | ChannelConversion] = {} tx_map = kwargs["tx_map"] self.name = get_text_v4(self.name_addr, stream, mapped=mapped, tx_map=tx_map) self.unit = get_text_v4(self.unit_addr, stream, mapped=mapped, tx_map=tx_map) self.comment = get_text_v4(self.comment_addr, stream, mapped=mapped, tx_map=tx_map) conv_type = conv if conv_type == v4c.CONVERSION_TYPE_ALG: self.formula = get_text_v4(self.formula_addr, stream, mapped=mapped, tx_map=tx_map).replace("x", "X") else: self.formula = "" if conv_type in v4c.TABULAR_CONVERSIONS: refs = self.referenced_blocks = {} if conv_type in ( v4c.CONVERSION_TYPE_TTAB, v4c.CONVERSION_TYPE_BITFIELD, ): tabs = self.links_nr - 4 else: tabs = self.links_nr - 4 - 1 for i in range(tabs): address = typing.cast(int, self[f"text_{i}"]) if address: if address in tx_map: refs[f"text_{i}"] = tx_map[address].raw else: stream.seek(address) _id = stream.read(4) if _id == b"##TX": refs[f"text_{i}"] = get_text_v4( address=address, stream=stream, mapped=mapped, decode=False, tx_map=tx_map, ) elif _id == b"##CC": cc_block = ChannelConversion( address=address, stream=stream, mapped=mapped, tx_map=tx_map, ) refs[f"text_{i}"] = cc_block else: message = f'Expected "##TX" or "##CC" block @{hex(address)} but found "{_id!r}"' logger.exception(message) raise MdfException(message) else: refs[f"text_{i}"] = b"" if conv_type not in ( v4c.CONVERSION_TYPE_TTAB, v4c.CONVERSION_TYPE_BITFIELD, ): address = self.default_addr if address: if address in tx_map: refs["default_addr"] = tx_map[address].raw else: stream.seek(address) _id = stream.read(4) if _id == b"##TX": refs["default_addr"] = get_text_v4( address=address, stream=stream, mapped=mapped, decode=False, tx_map=tx_map ) elif _id == b"##CC": cc_block = ChannelConversion( address=address, stream=stream, mapped=mapped, tx_map=tx_map, ) refs["default_addr"] = cc_block else: message = f'Expected "##TX" or "##CC" block @{hex(address)} but found "{_id!r}"' logger.exception(message) raise MdfException(message) else: refs["default_addr"] = b"" elif conv_type == v4c.CONVERSION_TYPE_TRANS: refs = self.referenced_blocks = {} # link_nr - common links (4) - default text link (1) for i in range((self.links_nr - 4 - 1) // 2): for key in (f"input_{i}_addr", f"output_{i}_addr"): address = typing.cast(int, self[key]) if address: if address in tx_map: refs[key] = tx_map[address].raw else: refs[key] = get_text_v4( address=address, stream=stream, mapped=mapped, decode=False, tx_map=tx_map ) else: refs[key] = b"" address = self.default_addr if address: if address in tx_map: refs["default_addr"] = tx_map[address].raw else: tx_map[address] = MappedText( get_text_v4(address=address, stream=stream, mapped=mapped, decode=False, tx_map=tx_map), "", ) else: refs["default_addr"] = b"" else: self.name = kwargs.get("name", "") self.unit = kwargs.get("unit", "") self.comment = kwargs.get("comment", "") self.formula = kwargs.get("formula", "") self.referenced_blocks = {} self.address = 0 self.id = b"##CC" self.reserved0 = 0 if kwargs["conversion_type"] == v4c.CONVERSION_TYPE_NON: self.block_len = v4c.CC_NONE_BLOCK_SIZE self.links_nr = 4 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = 0 self.conversion_type = v4c.CONVERSION_TYPE_NON self.precision = 1 self.flags = 0 self.ref_param_nr = 0 self.val_param_nr = 0 self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) elif kwargs["conversion_type"] == v4c.CONVERSION_TYPE_LIN: self.block_len = v4c.CC_LIN_BLOCK_SIZE self.links_nr = 4 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) self.conversion_type = v4c.CONVERSION_TYPE_LIN self.precision = kwargs.get("precision", 1) self.flags = kwargs.get("flags", 0) self.ref_param_nr = 0 self.val_param_nr = 2 self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) self.b = float(kwargs["b"]) self.a = float(kwargs["a"]) elif kwargs["conversion_type"] == v4c.CONVERSION_TYPE_ALG: self.block_len = v4c.CC_ALG_BLOCK_SIZE self.links_nr = 5 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) self.formula_addr = kwargs.get("formula_addr", 0) self.conversion_type = v4c.CONVERSION_TYPE_ALG self.precision = kwargs.get("precision", 1) self.flags = kwargs.get("flags", 0) self.ref_param_nr = 1 self.val_param_nr = 0 self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) elif kwargs["conversion_type"] in ( v4c.CONVERSION_TYPE_TAB, v4c.CONVERSION_TYPE_TABI, ): nr = kwargs["val_param_nr"] self.block_len = 80 + 8 * nr self.links_nr = 4 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) self.conversion_type = kwargs["conversion_type"] self.precision = kwargs.get("precision", 1) self.flags = kwargs.get("flags", 0) self.ref_param_nr = 0 self.val_param_nr = nr self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) for i in range(nr // 2): self[f"raw_{i}"] = kwargs[f"raw_{i}"] # type: ignore[literal-required] self[f"phys_{i}"] = kwargs[f"phys_{i}"] # type: ignore[literal-required] elif kwargs["conversion_type"] == v4c.CONVERSION_TYPE_RTAB: self.block_len = kwargs["val_param_nr"] * 8 + 80 self.links_nr = 4 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) self.conversion_type = v4c.CONVERSION_TYPE_RTAB self.precision = kwargs.get("precision", 0) self.flags = kwargs.get("flags", 0) self.ref_param_nr = 0 self.val_param_nr = kwargs["val_param_nr"] self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) for i in range((kwargs["val_param_nr"] - 1) // 3): self[f"lower_{i}"] = kwargs[f"lower_{i}"] # type: ignore[literal-required] self[f"upper_{i}"] = kwargs[f"upper_{i}"] # type: ignore[literal-required] self[f"phys_{i}"] = kwargs[f"phys_{i}"] # type: ignore[literal-required] self.default = kwargs["default"] elif kwargs["conversion_type"] == v4c.CONVERSION_TYPE_RAT: self.block_len = 80 + 6 * 8 self.links_nr = 4 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) self.conversion_type = kwargs["conversion_type"] self.precision = kwargs.get("precision", 1) self.flags = kwargs.get("flags", 0) self.ref_param_nr = 0 self.val_param_nr = kwargs.get("val_param_nr", 6) self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) for i in range(1, 7): self[f"P{i}"] = kwargs[f"P{i}"] # type: ignore[literal-required] elif kwargs["conversion_type"] == v4c.CONVERSION_TYPE_TABX: self.referenced_blocks = {} nr = kwargs["ref_param_nr"] - 1 self.block_len = (nr * 8 * 2) + 88 self.links_nr = nr + 5 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) for i in range(nr): key = f"text_{i}" self[key] = 0 self.referenced_blocks[key] = kwargs[key] # type: ignore[literal-required] self.default_addr = 0 key = "default_addr" if "default_addr" in kwargs: default = kwargs["default_addr"] else: default = kwargs.get("default_addr", b"") self.referenced_blocks[key] = default self.conversion_type = v4c.CONVERSION_TYPE_TABX self.precision = kwargs.get("precision", 0) self.flags = kwargs.get("flags", 0) self.ref_param_nr = nr + 1 self.val_param_nr = nr self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) for i in range(nr): self[f"val_{i}"] = kwargs[f"val_{i}"] # type: ignore[literal-required] elif kwargs["conversion_type"] == v4c.CONVERSION_TYPE_RTABX: self.referenced_blocks = {} nr = kwargs["ref_param_nr"] - 1 self.block_len = (nr * 8 * 3) + 88 self.links_nr = nr + 5 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) for i in range(nr): key = f"text_{i}" self[key] = 0 self.referenced_blocks[key] = kwargs[key] # type: ignore[literal-required] self.default_addr = 0 self.default_lower = self.default_upper = 0 if "default_addr" in kwargs: default = kwargs["default_addr"] else: default = kwargs.get("default_addr", b"") if isinstance(default, bytes) and b"{X}" in default: formula = default.decode("latin-1").replace("{X}", "X").split('"')[1] cc_block = ChannelConversion(conversion_type=v4c.CONVERSION_TYPE_ALG, formula=formula) self.referenced_blocks["default_addr"] = cc_block else: self.referenced_blocks["default_addr"] = default self.conversion_type = v4c.CONVERSION_TYPE_RTABX self.precision = kwargs.get("precision", 0) self.flags = kwargs.get("flags", 0) self.ref_param_nr = nr + 1 self.val_param_nr = nr * 2 self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) for i in range(nr): self[f"lower_{i}"] = kwargs[f"lower_{i}"] # type: ignore[literal-required] self[f"upper_{i}"] = kwargs[f"upper_{i}"] # type: ignore[literal-required] elif kwargs["conversion_type"] == v4c.CONVERSION_TYPE_TTAB: self.block_len = ((kwargs["links_nr"] - 4) * 8 * 2) + 88 self.links_nr = kwargs["links_nr"] self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) for i in range(kwargs["links_nr"] - 4): self[f"text_{i}"] = kwargs.get(f"text_{i}", 0) self.conversion_type = v4c.CONVERSION_TYPE_TTAB self.precision = kwargs.get("precision", 0) self.flags = kwargs.get("flags", 0) self.ref_param_nr = kwargs["links_nr"] - 4 self.val_param_nr = kwargs["links_nr"] - 4 + 1 self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) for i in range(kwargs["links_nr"] - 4): self[f"val_{i}"] = kwargs[f"val_{i}"] # type: ignore[literal-required] self.val_default = kwargs["val_default"] elif kwargs["conversion_type"] == v4c.CONVERSION_TYPE_BITFIELD: self.referenced_blocks = {} nr = kwargs["val_param_nr"] self.block_len = (nr * 8 * 2) + 80 self.links_nr = nr + 4 self.name_addr = kwargs.get("name_addr", 0) self.unit_addr = kwargs.get("unit_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.inv_conv_addr = kwargs.get("inv_conv_addr", 0) for i in range(nr): key = f"text_{i}" self[key] = 0 self.referenced_blocks[key] = kwargs[key] # type: ignore[literal-required] self.conversion_type = v4c.CONVERSION_TYPE_BITFIELD self.precision = kwargs.get("precision", 0) self.flags = kwargs.get("flags", 0) self.ref_param_nr = nr self.val_param_nr = nr self.min_phy_value = kwargs.get("min_phy_value", 0) self.max_phy_value = kwargs.get("max_phy_value", 0) for i in range(nr): self[f"mask_{i}"] = kwargs[f"mask_{i}"] # type: ignore[literal-required] else: message = "Conversion {} dynamic creation not implemented" message = message.format(kwargs["conversion_type"]) logger.exception(message) raise MdfException(message) # the inverse conversion is not used (see issue #1017) self.inv_conv_addr = 0 # use the first unit found in a refereced block (see issue #1205) if not self.unit: for block in self.referenced_blocks.values(): if isinstance(block, ChannelConversion) and block.unit: self.unit = block.unit break def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int], cc_map: dict[bytes | int, int], ) -> int: if id(self) in cc_map: return address text = self.name if text: if text in defined_texts: self.name_addr = defined_texts[text] else: tx_block = TextBlock( text=text.encode("utf-8", "replace"), meta=False, safe=True, ) self.name_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.name_addr = 0 text = self.unit if text: if text in defined_texts: self.unit_addr = defined_texts[text] else: tx_block = TextBlock( text=text.encode("utf-8", "replace"), meta=False, safe=True, ) self.unit_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.unit_addr = 0 if self.conversion_type == v4c.CONVERSION_TYPE_ALG: text = self.formula if text: if text in defined_texts: self.formula_addr = defined_texts[text] else: tx_block = TextBlock( text=text.encode("utf-8", "replace"), meta=False, safe=True, ) self.formula_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.formula_addr = 0 text = self.comment if text: if text in defined_texts: self.comment_addr = defined_texts[text] else: meta = text.startswith(" NDArray[Any]: ... @overload def convert( self, values: ArrayLike, as_object: bool = ..., as_bytes: bool = ..., ignore_value2text_conversions: bool = ..., ) -> NDArray[Any] | np.number[Any]: ... def convert( self, values: ArrayLike, as_object: bool = False, as_bytes: bool = False, ignore_value2text_conversions: bool = False, ) -> NDArray[Any] | np.number[Any]: identical = ChannelConversion(conversion_type=v4c.CONVERSION_TYPE_NON) scalar = False if not isinstance(values, np.ndarray): if isinstance(values, (int, float)): new_values = np.array([values]) scalar = True else: new_values = np.array(values) else: new_values = values values_count = len(new_values) index: np.intp | int conversion_type = self.conversion_type if conversion_type == v4c.CONVERSION_TYPE_NON: pass elif conversion_type == v4c.CONVERSION_TYPE_LIN: a = self.a b = self.b if (a, b) != (1, 0): names = new_values.dtype.names if names: name = names[0] vals = new_values[name] vals = vals * a if b: vals += b new_values = np.rec.fromarrays( [vals] + [new_values[name] for name in names[1:]], dtype=[(name, vals.dtype, vals.shape[1:])] + [(name, new_values[name].dtype, new_values[name].shape[1:]) for name in names[1:]], ) else: new_values = new_values * a if b: new_values += b elif conversion_type == v4c.CONVERSION_TYPE_RAT: P1 = self.P1 P2 = self.P2 P3 = self.P3 P4 = self.P4 P5 = self.P5 P6 = self.P6 names = new_values.dtype.names if names: name = names[0] vals = new_values[name] if (P1, P3, P4, P5) == (0, 0, 0, 0): if P2 != P6: vals = vals * (P2 / P6) elif (P2, P3, P4, P6) == (0, 0, 0, 0): if P1 != P5: vals = vals * (P1 / P5) else: X = vals try: vals = evaluate(v4c.CONV_RAT_TEXT) except TypeError: vals = (P1 * X**2 + P2 * X + P3) / (P4 * X**2 + P5 * X + P6) new_values = np.rec.fromarrays( [vals] + [new_values[name] for name in names[1:]], dtype=[(name, vals.dtype, vals.shape[1:])] + [(name, new_values[name].dtype, new_values[name].shape[1:]) for name in names[1:]], ) else: X = new_values if (P1, P3, P4, P5) == (0, 0, 0, 0): if P2 != P6: new_values = new_values * (P2 / P6) elif (P2, P3, P4, P6) == (0, 0, 0, 0): if P1 != P5: new_values = new_values * (P1 / P5) else: try: new_values = evaluate(v4c.CONV_RAT_TEXT) except TypeError: new_values = (P1 * X**2 + P2 * X + P3) / (P4 * X**2 + P5 * X + P6) elif conversion_type == v4c.CONVERSION_TYPE_ALG: try: X = new_values INF = np.inf NaN = np.nan new_values = evaluate(self.formula.replace("X1", "X")) except: if lambdify is not None: X_symbol = symbols("X") expr = lambdify( X_symbol, self.formula.replace("X1", "X"), modules=[{"INF": np.inf, "NaN": np.nan}, "numpy"], dummify=False, cse=True, ) new_values = expr(new_values) elif conversion_type in (v4c.CONVERSION_TYPE_TABI, v4c.CONVERSION_TYPE_TAB): nr = self.val_param_nr // 2 raw_vals = np.array([self[f"raw_{i}"] for i in range(nr)]) phys_vals = np.array([self[f"phys_{i}"] for i in range(nr)]) if conversion_type == v4c.CONVERSION_TYPE_TABI: new_values = np.interp(new_values, raw_vals, phys_vals) else: dim = raw_vals.shape[0] inds = np.searchsorted(raw_vals, new_values) inds[inds >= dim] = dim - 1 # type: ignore[index, unused-ignore] inds2 = inds - 1 inds2[inds2 < 0] = 0 # type: ignore[index, unused-ignore] cond = np.abs(new_values - raw_vals[inds]) >= np.abs(new_values - raw_vals[inds2]) new_values = np.where(cond, phys_vals[inds2], phys_vals[inds]) elif conversion_type == v4c.CONVERSION_TYPE_RTAB: nr = (self.val_param_nr - 1) // 3 lower_vals = np.array([self[f"lower_{i}"] for i in range(nr)]) upper_vals = np.array([self[f"upper_{i}"] for i in range(nr)]) phys_vals = np.array([self[f"phys_{i}"] for i in range(nr)]) if new_values.dtype.kind == "f": idx1 = np.searchsorted(lower_vals, new_values, side="right") - 1 idx2 = np.searchsorted(upper_vals, new_values, side="right") else: idx1 = np.searchsorted(lower_vals, new_values, side="right") - 1 idx2 = np.searchsorted(upper_vals, new_values, side="right") - 1 idx_ne = np.nonzero(idx1 != idx2)[0] idx_eq = np.nonzero(idx1 == idx2)[0] new_values = np.zeros(len(new_values), dtype=phys_vals.dtype) if len(idx_ne): new_values[idx_ne] = self.default if len(idx_eq): new_values[idx_eq] = phys_vals[idx1[idx_eq]] # type: ignore[index, unused-ignore] elif conversion_type == v4c.CONVERSION_TYPE_TABX and values_count >= 150: if ignore_value2text_conversions: nr = self.val_param_nr raw = [self[f"val_{i}"] for i in range(nr)] phys: list[bytes | ChannelConversion] = [] for i in range(nr): tx_ref = self.referenced_blocks[f"text_{i}"] if isinstance(tx_ref, bytes): phys.append(identical) else: phys.append(tx_ref) pairs = sorted(zip(raw, phys, strict=False)) raw_vals = np.array([e[0] for e in pairs], dtype="= 0: ret_vals = ret_vals.astype(f"S{size}") else: try: ret_vals = ret_vals.astype("f8") except: if as_bytes: ret_vals = ret_vals.astype(bytes) elif not as_object: ret_vals = np.array( [ np.nan if isinstance(v, bytes) else v for v in typing.cast(list[object], ret_vals.tolist()) ] ) ret_vals = ret_vals.reshape(shape) new_values = np.rec.fromarrays( [ret_vals] + [new_values[name] for name in names[1:]], dtype=[(name, ret_vals.dtype, ret_vals.shape[1:])] + [(name, new_values[name].dtype, new_values[name].shape[1:]) for name in names[1:]], ) else: ret_vals = np.full(new_values.size, None, "O") idx1 = np.searchsorted(raw_vals, new_values, side="right") - 1 idx2 = np.searchsorted(raw_vals, new_values, side="left") idx = np.argwhere(idx1 != idx2).ravel() if idx.size: # some raw values were not found in the conversion table # so the default physical value must be returned if isinstance(default, bytes): ret_vals[idx] = default else: ret_vals[idx] = default.convert( new_values[idx], ignore_value2text_conversions=ignore_value2text_conversions ) idx = np.argwhere(idx1 == idx2).ravel() if idx.size: indexes = idx1[idx] # type: ignore[index, unused-ignore] if indexes.size <= 300: index_list = sorted(set(typing.cast(list[int], indexes.tolist()))) else: index_list = typing.cast(list[int], np.unique(indexes).tolist()) for index in index_list: item = phys[index] idx_ = np.argwhere(indexes == index).ravel() if isinstance(item, bytes): ret_vals[idx[idx_]] = item else: ret_vals[idx[idx_]] = item.convert( new_values[idx[idx_]], ignore_value2text_conversions=ignore_value2text_conversions ) else: # all the raw values are found in the conversion table if idx1.size: if idx1.size <= 300: index_list = sorted(set(typing.cast(list[int], idx1.tolist()))) else: index_list = typing.cast(list[int], np.unique(idx1).tolist()) for index in index_list: item = phys[index] idx_ = np.argwhere(idx1 == index).ravel() if isinstance(item, bytes): ret_vals[idx_] = item else: ret_vals[idx_] = item.convert( new_values[idx_], ignore_value2text_conversions=ignore_value2text_conversions ) size = bytes_dtype_size(ret_vals) if size >= 0: ret_vals = ret_vals.astype(f"S{size}") else: try: ret_vals = ret_vals.astype("f8") except: if as_bytes: ret_vals = ret_vals.astype(bytes) elif not as_object: ret_vals = np.array([np.nan if isinstance(v, bytes) else v for v in ret_vals.tolist()]) new_values = ret_vals elif conversion_type == v4c.CONVERSION_TYPE_TABX: if ignore_value2text_conversions: nr = self.val_param_nr raw = [self[f"val_{i}"] for i in range(nr)] phys = [] for i in range(nr): tx_ref = self.referenced_blocks[f"text_{i}"] if isinstance(tx_ref, bytes): phys.append(identical) else: phys.append(tx_ref) pairs = sorted(zip(raw, phys, strict=False)) raw = [e[0] for e in pairs] phys = [e[1] for e in pairs] ref = self.referenced_blocks["default_addr"] if ref is None: ref = identical if isinstance(ref, bytes): default = identical else: default = ref default_is_bytes = False else: self._cache = typing.cast(_ValsCache | None, self._cache) if self._cache is None or self._cache["type"] != "small": nr = self.val_param_nr raw = [self[f"val_{i}"] for i in range(nr)] phys = [self.referenced_blocks[f"text_{i}"] for i in range(nr)] pairs = sorted(zip(raw, phys, strict=False)) raw = [e[0] for e in pairs] phys = [e[1] for e in pairs] self._cache = {"phys": phys, "raw_vals": raw, "type": "small"} else: phys = self._cache["phys"] raw = typing.cast(list[object], self._cache["raw_vals"]) ref = self.referenced_blocks["default_addr"] if ref is None: default = identical else: default = ref default_is_bytes = isinstance(default, bytes) names = new_values.dtype.names if names: name = names[0] vals = new_values[name] shape = vals.shape objects = vals.ravel().tolist() ret: list[object] = [] all_bytes = True for v in objects: try: v_ = phys[raw.index(v)] if isinstance(v_, bytes): ret.append(v_) else: v_ = v_.convert([v], ignore_value2text_conversions=ignore_value2text_conversions)[0] ret.append(v_) if all_bytes and not isinstance(v_, bytes): all_bytes = False except: if default_is_bytes: default = typing.cast(bytes, default) ret.append(default) else: default = typing.cast(ChannelConversion, default) v_ = default.convert([v], ignore_value2text_conversions=ignore_value2text_conversions)[0] ret.append(v_) if all_bytes and not isinstance(v_, bytes): all_bytes = False if not all_bytes: try: ret_vals = np.array(ret, dtype="= 100: if ignore_value2text_conversions: nr = self.val_param_nr // 2 phys = [] for i in range(nr): tx_ref = self.referenced_blocks[f"text_{i}"] if isinstance(tx_ref, bytes): phys.append(identical) else: phys.append(tx_ref) lower = [self[f"lower_{i}"] for i in range(nr)] upper = [self[f"upper_{i}"] for i in range(nr)] triplets = sorted(zip(lower, upper, phys, strict=False)) lower_vals = np.array([e[0] for e in triplets], dtype="= 0: ret_vals = ret_vals.astype(f"S{size}") else: try: ret_vals = ret_vals.astype("f8") except: if as_bytes: ret_vals = ret_vals.astype(bytes) elif not as_object: ret_vals = np.array([np.nan if isinstance(v, bytes) else v for v in ret_vals.tolist()]) new_values = ret_vals elif conversion_type == v4c.CONVERSION_TYPE_RTABX: if ignore_value2text_conversions: nr = self.val_param_nr // 2 phys = [] for i in range(nr): tx_ref = self.referenced_blocks[f"text_{i}"] if isinstance(tx_ref, bytes): phys.append(identical) else: phys.append(tx_ref) lower = [self[f"lower_{i}"] for i in range(nr)] upper = [self[f"upper_{i}"] for i in range(nr)] triplets = sorted(zip(lower, upper, phys, strict=False)) lower = [e[0] for e in triplets] upper = [e[1] for e in triplets] phys = [e[2] for e in triplets] ref = self.referenced_blocks["default_addr"] if ref is None: ref = identical if isinstance(ref, bytes): default = identical else: default = ref default_is_bytes = False else: self._cache = typing.cast(_BoundCache | None, self._cache) if self._cache is None or self._cache["type"] != "small": nr = self.val_param_nr // 2 phys = [self.referenced_blocks[f"text_{i}"] for i in range(nr)] lower = [self[f"lower_{i}"] for i in range(nr)] upper = [self[f"upper_{i}"] for i in range(nr)] triplets = sorted(zip(lower, upper, phys, strict=False)) lower = [e[0] for e in triplets] upper = [e[1] for e in triplets] phys = [e[2] for e in triplets] self._cache = { "phys": phys, "lower": lower, "upper": upper, "type": "small", } else: phys = self._cache["phys"] lower = typing.cast(list[object], self._cache["lower"]) upper = typing.cast(list[object], self._cache["upper"]) ref = self.referenced_blocks["default_addr"] if ref is None: default = identical else: default = ref default_is_bytes = isinstance(default, bytes) ret = [] objects = typing.cast(list[Any], new_values.tolist()) all_bytes = True if new_values.dtype.kind in "ui": for v in objects: for l, u, p in zip(lower, upper, phys, strict=False): if l <= v <= u: if isinstance(p, bytes): ret.append(p) else: p = p.convert([v], ignore_value2text_conversions=ignore_value2text_conversions)[0] ret.append(p) if all_bytes and not isinstance(p, bytes): all_bytes = False break else: if default_is_bytes: default = typing.cast(bytes, default) ret.append(default) else: default = typing.cast(ChannelConversion, default) v_ = default.convert([v], ignore_value2text_conversions=ignore_value2text_conversions)[0] ret.append(v_) if all_bytes and not isinstance(v_, bytes): all_bytes = False else: for v in objects: for l, u, p in zip(lower, upper, phys, strict=False): if l <= v < u: if isinstance(p, bytes): ret.append(p) else: p = p.convert([v], ignore_value2text_conversions=ignore_value2text_conversions)[0] ret.append(p) if all_bytes and not isinstance(p, bytes): all_bytes = False break else: if default_is_bytes: default = typing.cast(bytes, default) ret.append(default) else: default = typing.cast(ChannelConversion, default) v_ = default.convert([v], ignore_value2text_conversions=ignore_value2text_conversions)[0] ret.append(v_) if all_bytes and not isinstance(v_, bytes): all_bytes = False if not all_bytes: try: ret_vals = np.array(ret, dtype="f8") except: ret_vals = np.array(ret, dtype="O") if as_bytes: ret_vals = ret_vals.astype(bytes) elif not as_object: ret_vals = np.array([np.nan if isinstance(v, bytes) else v for v in ret_vals.tolist()]) else: ret_vals = np.array(ret, dtype=bytes) new_values = ret_vals elif conversion_type == v4c.CONVERSION_TYPE_TTAB: nr = self.val_param_nr - 1 phys_2 = [self.referenced_blocks[f"text_{i}"] for i in range(nr)] raw = [self[f"val_{i}"] for i in range(nr)] val_default = self.val_default ret = [] for val in new_values: try: obj = raw[phys_2.index(val)] except ValueError: obj = val_default ret.append(obj) new_values = np.array(ret) elif conversion_type == v4c.CONVERSION_TYPE_TRANS: if not ignore_value2text_conversions: nr = (self.ref_param_nr - 1) // 2 in_ = [self.referenced_blocks[f"input_{i}_addr"] for i in range(nr)] out_ = [self.referenced_blocks[f"output_{i}_addr"] for i in range(nr)] default_addr = self.referenced_blocks["default_addr"] ret = [] for val in new_values: try: obj = out_[in_.index(val.strip(b"\0"))] except ValueError: obj = default_addr ret.append(obj) new_values = np.array(ret) elif conversion_type == v4c.CONVERSION_TYPE_BITFIELD: if not ignore_value2text_conversions: nr = self.val_param_nr ref_blocks = [self.referenced_blocks[f"text_{i}"] for i in range(nr)] masks = np.array([self[f"mask_{i}"] for i in range(nr)], dtype="u8") block_or_cc_list = [ ( block if isinstance(block, bytes) else ((f"{block.name}=".encode(), block) if block.name else (b"", block)) ) for block in ref_blocks ] bytes_values: list[bytes] = [] values_as_int = new_values.astype("u8") non_int = new_values != values_as_int for val in typing.cast(list[int], values_as_int.tolist()): new_val: list[bytes] = [] masked_values = typing.cast(list[int], (masks & val).tolist()) for on, conv in zip(masked_values, block_or_cc_list, strict=False): if isinstance(conv, bytes): if conv: new_val.append(conv) else: prefix, conversion = conv converted_val = conversion.convert( [on], ignore_value2text_conversions=ignore_value2text_conversions )[0] if converted_val: if prefix: new_val.append(prefix + converted_val) else: new_val.append(converted_val) elif prefix: new_val.append(prefix) bytes_values.append(b"|".join(new_val)) new_values = np.array(bytes_values, dtype=bytes) new_values[non_int] = b"" if scalar: return typing.cast(np.number[Any], new_values[0]) else: return new_values def metadata(self, indent: str = "") -> str: keys: tuple[str, ...] if self.conversion_type == v4c.CONVERSION_TYPE_NON: keys = v4c.KEYS_CONVERSION_NONE elif self.conversion_type == v4c.CONVERSION_TYPE_LIN: keys = v4c.KEYS_CONVERSION_LINEAR elif self.conversion_type == v4c.CONVERSION_TYPE_RAT: keys = v4c.KEYS_CONVERSION_RAT elif self.conversion_type == v4c.CONVERSION_TYPE_ALG: keys = v4c.KEYS_CONVERSION_ALGEBRAIC elif self.conversion_type in ( v4c.CONVERSION_TYPE_TABI, v4c.CONVERSION_TYPE_TAB, ): keys = v4c.KEYS_CONVERSION_NONE for i in range(self.val_param_nr // 2): keys += (f"raw_{i}", f"phys_{i}") elif self.conversion_type == v4c.CONVERSION_TYPE_RTAB: keys = v4c.KEYS_CONVERSION_NONE for i in range(self.val_param_nr // 3): keys += (f"lower_{i}", f"upper_{i}", f"phys_{i}") keys += ("default",) elif self.conversion_type == v4c.CONVERSION_TYPE_TABX: keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) keys += tuple(f"text_{i}" for i in range(self.links_nr - 4 - 1)) keys += ("default_addr",) keys += ( "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) keys += tuple(f"val_{i}" for i in range(self.val_param_nr)) elif self.conversion_type == v4c.CONVERSION_TYPE_RTABX: keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) keys += tuple(f"text_{i}" for i in range(self.links_nr - 4 - 1)) keys += ("default_addr",) keys += ( "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) for i in range(self.val_param_nr // 2): keys += (f"lower_{i}", f"upper_{i}") elif self.conversion_type == v4c.CONVERSION_TYPE_TTAB: keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) keys += tuple(f"text_{i}" for i in range(self.links_nr - 4)) keys += ( "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) keys += tuple(f"val_{i}" for i in range(self.val_param_nr - 1)) keys += ("val_default",) elif self.conversion_type == v4c.CONVERSION_TYPE_TRANS: keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) for i in range((self.links_nr - 4 - 1) // 2): keys += (f"input_{i}_addr", f"output_{i}_addr") keys += ( "default_addr", "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) keys += tuple(f"val_{i}" for i in range(self.val_param_nr - 1)) elif self.conversion_type == v4c.CONVERSION_TYPE_BITFIELD: keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) keys += tuple(f"text_{i}" for i in range(self.links_nr - 4)) keys += ( "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) keys += tuple(f"mask_{i}" for i in range(self.val_param_nr)) max_len = max(len(key) for key in keys) template = f"{{: <{max_len}}}: {{}}" metadata: list[str] = [] lines = f""" name: {self.name} unit: {self.unit} address: {hex(self.address)} comment: {self.comment} formula: {self.formula} """.split("\n") for key in keys: val = getattr(self, key) if key.endswith("addr") or key.startswith("text_"): lines.append(template.format(key, hex(val))) elif isinstance(val, float): lines.append(template.format(key, val)) else: if isinstance(val, bytes): lines.append(template.format(key, val.strip(b"\0"))) else: lines.append(template.format(key, val)) if key == "conversion_type": lines[-1] += f" = {v4c.CONVERSION_TYPE_TO_STRING[self.conversion_type]}" elif self.referenced_blocks and key in self.referenced_blocks: val = self.referenced_blocks[key] if isinstance(val, bytes): lines[-1] += f" (= {str(val)[1:]})" else: lines[-1] += f" (= CCBLOCK @ {hex(val.address)})" if self.referenced_blocks: max_len = max(len(key) for key in self.referenced_blocks) template = f"{{: <{max_len}}}: {{}}" lines.append("") lines.append("Referenced blocks:") for key, block in self.referenced_blocks.items(): if isinstance(block, ChannelConversion): lines.append(template.format(key, "")) lines.extend(block.metadata(indent + " ").split("\n")) else: lines.append(template.format(key, str(block)[1:])) for line in lines: if not line: metadata.append(line) else: for wrapped_line in wrap(line, initial_indent=indent, subsequent_indent=indent, width=120): metadata.append(wrapped_line) return "\n".join(metadata) def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __contains__(self, item: str) -> bool: return hasattr(self, item) def __bytes__(self) -> bytes: keys: tuple[str, ...] if self.conversion_type == v4c.CONVERSION_TYPE_NON: result = v4c.CONVERSION_NONE_PACK( self.id, self.reserved0, self.block_len, self.links_nr, self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) elif self.conversion_type == v4c.CONVERSION_TYPE_LIN: result = v4c.CONVERSION_LINEAR_PACK( self.id, self.reserved0, self.block_len, self.links_nr, self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, self.b, self.a, ) elif self.conversion_type == v4c.CONVERSION_TYPE_RAT: result = v4c.CONVERSION_RAT_PACK( self.id, self.reserved0, self.block_len, self.links_nr, self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, self.P1, self.P2, self.P3, self.P4, self.P5, self.P6, ) elif self.conversion_type == v4c.CONVERSION_TYPE_ALG: result = v4c.CONVERSION_ALGEBRAIC_PACK( self.id, self.reserved0, self.block_len, self.links_nr, self.name_addr, self.unit_addr, self.comment_addr, self.inv_conv_addr, self.formula_addr, self.conversion_type, self.precision, self.flags, self.ref_param_nr, self.val_param_nr, self.min_phy_value, self.max_phy_value, ) elif self.conversion_type in ( v4c.CONVERSION_TYPE_TABI, v4c.CONVERSION_TYPE_TAB, ): fmt = f"<4sI{self.links_nr + 2}Q2B3H{self.val_param_nr + 2}d" keys = v4c.KEYS_CONVERSION_NONE for i in range(self.val_param_nr // 2): keys += (f"raw_{i}", f"phys_{i}") result = pack(fmt, *[getattr(self, key) for key in keys]) elif self.conversion_type == v4c.CONVERSION_TYPE_RTAB: fmt = f"<4sI{self.links_nr + 2}Q2B3H{self.val_param_nr + 2}d" keys = v4c.KEYS_CONVERSION_NONE for i in range(self.val_param_nr // 3): keys += (f"lower_{i}", f"upper_{i}", f"phys_{i}") keys += ("default",) result = pack(fmt, *[getattr(self, key) for key in keys]) elif self.conversion_type == v4c.CONVERSION_TYPE_TABX: fmt = f"<4sI{self.links_nr + 2}Q2B3H{self.val_param_nr + 2}d" keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) keys += tuple(f"text_{i}" for i in range(self.links_nr - 4 - 1)) keys += ("default_addr",) keys += ( "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) keys += tuple(f"val_{i}" for i in range(self.val_param_nr)) result = pack(fmt, *[getattr(self, key) for key in keys]) elif self.conversion_type == v4c.CONVERSION_TYPE_RTABX: fmt = f"<4sI{self.links_nr + 2}Q2B3H{self.val_param_nr + 2}d" keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) keys += tuple(f"text_{i}" for i in range(self.links_nr - 4 - 1)) keys += ("default_addr",) keys += ( "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) for i in range(self.val_param_nr // 2): keys += (f"lower_{i}", f"upper_{i}") result = pack(fmt, *[getattr(self, key) for key in keys]) elif self.conversion_type == v4c.CONVERSION_TYPE_TTAB: fmt = f"<4sI{self.links_nr + 2}Q2B3H{self.val_param_nr + 2}d" keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) keys += tuple(f"text_{i}" for i in range(self.links_nr - 4)) keys += ( "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) keys += tuple(f"val_{i}" for i in range(self.val_param_nr - 1)) keys += ("val_default",) result = pack(fmt, *[getattr(self, key) for key in keys]) elif self.conversion_type == v4c.CONVERSION_TYPE_TRANS: fmt = f"<4sI{self.links_nr + 2}Q2B3H{self.val_param_nr + 2}d" keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) for i in range((self.links_nr - 4 - 1) // 2): keys += (f"input_{i}_addr", f"output_{i}_addr") keys += ( "default_addr", "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) keys += tuple(f"val_{i}" for i in range(self.val_param_nr - 1)) result = pack(fmt, *[getattr(self, key) for key in keys]) elif self.conversion_type == v4c.CONVERSION_TYPE_BITFIELD: fmt = f"<4sI{self.links_nr + 2}Q2B3H2d{self.val_param_nr}Q" keys = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", ) keys += tuple(f"text_{i}" for i in range(self.val_param_nr)) keys += ( "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) keys += tuple(f"mask_{i}" for i in range(self.val_param_nr)) result = pack(fmt, *[getattr(self, key) for key in keys]) return result def __str__(self) -> str: return f"" class DataBlockKwargs(BlockKwargs, total=False): data: bytes | bytearray type: Literal["DT", "SD", "RD", "DV", "DI"] class DataBlock: """Common implementation for DTBLOCK/RDBLOCK/SDBLOCK/DVBLOCK/DIBLOCK. `DataBlock` has the following attributes, which are also available as dict-like key-value pairs. DTBLOCK fields: * ``id`` - bytes : block ID; b'##DT' for DTBLOCK, b'##RD' for RDBLOCK, b'##SD' for SDBLOCK, b'##DV' for DVBLOCK or b'##DI' for DIBLOCK * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``data`` - bytes : raw samples Other attributes: * ``address`` - int : data block address Parameters ---------- address : int DTBLOCK/RDBLOCK/SDBLOCK/DVBLOCK/DIBLOCK address inside the file. stream : int File handle. reduction : bool Sample reduction data block. """ __slots__ = ("address", "block_len", "data", "id", "links_nr", "reserved0") def __init__(self, **kwargs: Unpack[DataBlockKwargs]) -> None: self.data: bytes | bytearray try: self.address = address = kwargs["address"] stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) if utils.stream_is_mmap(stream, mapped): (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(stream, address) if self.id not in (b"##DT", b"##RD", b"##SD", b"##DV", b"##DI"): message = f'Expected "##DT", "##DV", "##DI", "##RD" or "##SD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) self.data = stream[address + COMMON_SIZE : address + self.block_len] else: stream.seek(address) (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_u(stream.read(COMMON_SIZE)) if self.id not in (b"##DT", b"##RD", b"##SD", b"##DV", b"##DI"): message = f'Expected "##DT", "##DV", "##DI", "##RD" or "##SD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) self.data = stream.read(self.block_len - COMMON_SIZE) except KeyError: self.address = 0 type = kwargs.get("type", "DT") if type not in ("DT", "SD", "RD", "DV", "DI"): type = "DT" self.id = f"##{type}".encode("ascii") self.reserved0 = 0 self.block_len = len(kwargs["data"]) + COMMON_SIZE self.links_nr = 0 self.data = kwargs["data"] def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: return v4c.COMMON_p(self.id, self.reserved0, self.block_len, self.links_nr) + self.data class DataZippedBlockKwargs(BlockKwargs, total=False): data: bytes | bytearray original_type: bytes zip_type: int param: int transposed: bool class DataZippedBlock: """`DataZippedBlock` has the following attributes, which are also available as dict-like key-value pairs. DZBLOCK fields: * ``id`` - bytes : block ID; always b'##DZ' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``original_type`` - bytes : b'DT', b'SD', b'DI' or b'DV' * ``zip_type`` - int : zip algorithm used * ``reserved1`` - int : reserved bytes * ``param`` - int : for transpose deflate the record size used for transposition * ``original_size`` - int : size of the original uncompressed raw bytes * ``zip_size`` - int : size of compressed bytes * ``data`` - bytes : compressed bytes Other attributes: * ``address`` - int : data zipped block address * ``return_unzipped`` - bool : decompress data when accessing the 'data' key Parameters ---------- address : int DTBLOCK address inside the file. stream : int File handle. """ __slots__ = ( "_prevent_data_setitem", "_transposed", "address", "block_len", "data", "id", "links_nr", "original_size", "original_type", "param", "reserved0", "reserved1", "return_unzipped", "zip_size", "zip_type", ) def __init__(self, **kwargs: Unpack[DataZippedBlockKwargs]) -> None: self.data: bytes | bytearray self._prevent_data_setitem = True self._transposed = False try: self.address = address = kwargs["address"] stream = kwargs["stream"] stream.seek(address) ( self.id, self.reserved0, self.block_len, self.links_nr, self.original_type, self.zip_type, self.reserved1, self.param, self.original_size, self.zip_size, ) = typing.cast(v4c.DzCommon, unpack(v4c.FMT_DZ_COMMON, stream.read(v4c.DZ_COMMON_SIZE))) if self.id != b"##DZ": message = f'Expected "##DZ" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) self.data = stream.read(self.zip_size) except KeyError: self._prevent_data_setitem = False self.address = 0 data = kwargs["data"] self.id = b"##DZ" self.reserved0 = 0 self.block_len = 0 self.links_nr = 0 self.original_type = kwargs.get("original_type", b"DT") self.zip_type = kwargs.get("zip_type", v4c.FLAG_DZ_DEFLATE) self.reserved1 = 0 if self.zip_type == v4c.FLAG_DZ_DEFLATE: self.param = 0 else: self.param = kwargs["param"] self._transposed = kwargs.get("transposed", False) self.data = data self._prevent_data_setitem = False self.return_unzipped = True def __setattr__(self, item: str, value: object) -> None: if item == "data" and not self._prevent_data_setitem: data = typing.cast(bytes | bytearray, value) original_size = len(data) self.original_size = original_size compress_func: Callable[[Buffer, int], bytes] if self.zip_type in (v4c.FLAG_DZ_DEFLATE, v4c.FLAG_DZ_TRANSPOSED_DEFLATE): compress_func = compress compression_level = COMPRESSION_LEVEL elif self.zip_type in (v4c.FLAG_DZ_LZ4, v4c.FLAG_DZ_TRANSPOSED_LZ4): compress_func = lz_compress compression_level = 1 elif self.zip_type in (v4c.FLAG_DZ_ZSTD, v4c.FLAG_DZ_TRANSPOSED_ZSTD): compress_func = zstd_compress compression_level = 1 if self.zip_type in (v4c.FLAG_DZ_DEFLATE, v4c.FLAG_DZ_LZ4, v4c.FLAG_DZ_ZSTD): data = compress_func(data, compression_level) else: if not self._transposed: cols = self.param lines = original_size // cols if lines * cols < original_size: data_view = memoryview(data) data = ( np.frombuffer(data_view[: lines * cols], dtype="B") .reshape((lines, cols)) .T.ravel() .tobytes() ) + data_view[lines * cols :] else: data = np.frombuffer(data, dtype=np.uint8).reshape((lines, cols)).T.ravel().tobytes() data = compress_func(data, compression_level) zipped_size = len(data) self.zip_size = zipped_size self.block_len = zipped_size + v4c.DZ_COMMON_SIZE DataZippedBlock.__dict__[item].__set__(self, data) DataZippedBlock.__dict__["_transposed"].__set__(self, False) else: DataZippedBlock.__dict__[item].__set__(self, value) DataZippedBlock.__dict__["_transposed"].__set__(self, False) def __getattribute__(self, item: str) -> object: if item == "data": if self.return_unzipped: data = DataZippedBlock.__dict__[item].__get__(self) original_size = self.original_size if self.zip_type in (v4c.FLAG_DZ_DEFLATE, v4c.FLAG_DZ_TRANSPOSED_DEFLATE): data = decompress(data, bufsize=original_size) elif self.zip_type in (v4c.FLAG_DZ_LZ4, v4c.FLAG_DZ_TRANSPOSED_LZ4): data = lz_decompress(data) elif self.zip_type in (v4c.FLAG_DZ_ZSTD, v4c.FLAG_DZ_TRANSPOSED_ZSTD): data = zstd_decompress(data) if self.zip_type == v4c.FLAG_DZ_TRANSPOSED_DEFLATE: cols = self.param lines = original_size // cols if lines * cols < original_size: data = memoryview(data) data = ( np.frombuffer(data[: lines * cols], dtype=np.uint8) .reshape((cols, lines)) .T.ravel() .tobytes() ) + data[lines * cols :] else: data = np.frombuffer(data, dtype=np.uint8).reshape((cols, lines)).T.ravel().tobytes() else: data = DataZippedBlock.__dict__[item].__get__(self) value = data else: value = DataZippedBlock.__dict__[item].__get__(self) return value def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __getitem__(self, item: str) -> object: return getattr(self, item) def __str__(self) -> str: return f"""""" def __bytes__(self) -> bytes: self.return_unzipped = False data = ( v4c.DZ_COMMON_p( self.id, self.reserved0, self.block_len, self.links_nr, self.original_type, self.zip_type, self.reserved1, self.param, self.original_size, self.zip_size, ) + self.data ) self.return_unzipped = True return data class DataGroupKwargs(BlockKwargs, total=False): id: bytes reserved0: int block_len: int links_nr: int next_dg_addr: int first_cg_addr: int data_block_addr: int comment_addr: int record_id_len: int reserved1: bytes class DataGroup: """`DataGroup` has the following attributes, which are also available as dict-like key-value pairs. DGBLOCK fields: * ``id`` - bytes : block ID; always b'##DG' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``next_dg_addr`` - int : address of next data group block * ``first_cg_addr`` - int : address of first channel group for this data group * ``data_block_addr`` - int : address of DTBLOCK, DZBLOCK, DLBLOCK or HLBLOCK that contains the raw samples for this data group * ``comment_addr`` - int : address of TXBLOCK/MDBLOCK that contains the data group comment * ``record_id_len`` - int : size of record ID used in case of unsorted data groups; can be 1, 2, 4 or 8 * ``reserved1`` - int : reserved bytes Other attributes: * ``address`` - int : data group address * ``comment`` - str : data group comment """ __slots__ = ( "address", "block_len", "comment", "comment_addr", "data_block_addr", "first_cg_addr", "id", "links_nr", "next_dg_addr", "record_id_len", "reserved0", "reserved1", ) def __init__(self, **kwargs: Unpack[DataGroupKwargs]) -> None: self.comment = "" try: self.address = address = kwargs["address"] stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) if utils.stream_is_mmap(stream, mapped): ( self.id, self.reserved0, self.block_len, self.links_nr, self.next_dg_addr, self.first_cg_addr, self.data_block_addr, self.comment_addr, self.record_id_len, self.reserved1, ) = v4c.DATA_GROUP_uf(stream, address) else: stream.seek(address) ( self.id, self.reserved0, self.block_len, self.links_nr, self.next_dg_addr, self.first_cg_addr, self.data_block_addr, self.comment_addr, self.record_id_len, self.reserved1, ) = v4c.DATA_GROUP_u(stream.read(v4c.DG_BLOCK_SIZE)) if self.id != b"##DG": message = f'Expected "##DG" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) self.comment = get_text_v4(self.comment_addr, stream, mapped=mapped, tx_map={}) except KeyError: self.address = 0 self.id = b"##DG" self.reserved0 = kwargs.get("reserved0", 0) self.block_len = kwargs.get("block_len", v4c.DG_BLOCK_SIZE) self.links_nr = kwargs.get("links_nr", 4) self.next_dg_addr = kwargs.get("next_dg_addr", 0) self.first_cg_addr = kwargs.get("first_cg_addr", 0) self.data_block_addr = kwargs.get("data_block_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.record_id_len = kwargs.get("record_id_len", 0) self.reserved1 = kwargs.get("reserved1", b"\00" * 7) def copy(self) -> "DataGroup": dg = DataGroup( id=self.id, reserved0=self.reserved0, block_len=self.block_len, links_nr=self.links_nr, next_dg_addr=self.next_dg_addr, first_cg_addr=self.first_cg_addr, data_block_addr=self.data_block_addr, comment_addr=self.comment_addr, record_id_len=self.record_id_len, reserved1=self.reserved1, ) dg.comment = self.comment dg.address = self.address return dg def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int] ) -> int: text = self.comment if text: if text in defined_texts: self.comment_addr = defined_texts[text] else: meta = text.startswith(" object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: result = v4c.DATA_GROUP_p( self.id, self.reserved0, self.block_len, self.links_nr, self.next_dg_addr, self.first_cg_addr, self.data_block_addr, self.comment_addr, self.record_id_len, self.reserved1, ) return result class _DataListBase: __slots__ = ( "address", "block_len", "data_block_len", "data_block_nr", "flags", "id", "links_nr", "next_dl_addr", "reserved0", "reserved1", ) class DataListKwargs(BlockKwargs, total=False): links_nr: int flags: int reserved1: bytes data_block_nr: int data_block_len: int class DataList(_DataListBase): """`DataList` has the following attributes, which are also available as dict-like key-value pairs. DLBLOCK common fields: * ``id`` - bytes : block ID; always b'##DL' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``next_dl_addr`` - int : address of next DLBLOCK * ``data_block_addr`` - int : address of N-th data block * ``flags`` - int : data list flags * ``reserved1`` - int : reserved bytes * ``data_block_nr`` - int : number of data blocks referenced by this list DLBLOCK specific fields: * for equal-length blocks * ``data_block_len`` - int : equal uncompressed size in bytes for all referenced data blocks; last block can be smaller * for variable-length blocks * ``offset_`` - int : byte offset of N-th data block Other attributes: * ``address`` - int : data list address """ def __init__(self, **kwargs: Unpack[DataListKwargs]) -> None: try: self.address = address = kwargs["address"] stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) if utils.stream_is_mmap(stream, mapped): (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(stream, address) if self.id != b"##DL": message = f'Expected "##DL" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) address += COMMON_SIZE links: tuple[int, ...] = unpack_from(f"<{self.links_nr}Q", stream, address) self.next_dl_addr = links[0] for i, addr in enumerate(links[1:]): setattr(self, f"data_block_addr{i}", addr) stream.seek(address + self.links_nr * 8) self.flags = stream.read_byte() if self.flags & v4c.FLAG_DL_EQUAL_LENGHT: (self.reserved1, self.data_block_nr, self.data_block_len) = typing.cast( tuple[bytes, int, int], unpack("<3sIQ", stream.read(15)) ) else: (self.reserved1, self.data_block_nr) = typing.cast( tuple[bytes, int], unpack("<3sI", stream.read(7)) ) offsets: tuple[int, ...] = unpack( f"<{self.links_nr - 1}Q", stream.read((self.links_nr - 1) * 8), ) for i, offset in enumerate(offsets): setattr(self, f"offset_{i}", offset) else: stream.seek(address) (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_u(stream.read(COMMON_SIZE)) if self.id != b"##DL": message = f'Expected "##DL" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) links = unpack(f"<{self.links_nr}Q", stream.read(self.links_nr * 8)) self.next_dl_addr = links[0] for i, addr in enumerate(links[1:]): self[f"data_block_addr{i}"] = addr self.flags = stream.read(1)[0] if self.flags & v4c.FLAG_DL_EQUAL_LENGHT: (self.reserved1, self.data_block_nr, self.data_block_len) = typing.cast( tuple[bytes, int, int], unpack("<3sIQ", stream.read(15)) ) else: (self.reserved1, self.data_block_nr) = typing.cast( tuple[bytes, int], unpack("<3sI", stream.read(7)) ) offsets = unpack( f"<{self.links_nr - 1}Q", stream.read((self.links_nr - 1) * 8), ) for i, offset in enumerate(offsets): self[f"offset_{i}"] = offset except KeyError: self.address = 0 self.id = b"##DL" self.reserved0 = 0 self.block_len = 40 + 8 * kwargs.get("links_nr", 2) self.links_nr = kwargs.get("links_nr", 2) self.next_dl_addr = 0 for i in range(self.links_nr - 1): self[f"data_block_addr{i}"] = kwargs.get(f"data_block_addr{i}", 0) self.flags = kwargs.get("flags", 1) self.reserved1 = kwargs.get("reserved1", b"\0\0\0") self.data_block_nr = kwargs.get("data_block_nr", self.links_nr - 1) if self.flags & v4c.FLAG_DL_EQUAL_LENGHT: self.data_block_len = kwargs["data_block_len"] else: self.block_len = 40 + 8 * kwargs.get("links_nr", 2) - 8 + 8 * self.data_block_nr for i in range(self.data_block_nr): self[f"offset_{i}"] = kwargs[f"offset_{i}"] # type: ignore[literal-required] def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: keys: tuple[str, ...] = ("id", "reserved0", "block_len", "links_nr", "next_dl_addr") keys += tuple(f"data_block_addr{i}" for i in range(self.links_nr - 1)) if self.flags & v4c.FLAG_DL_EQUAL_LENGHT: keys += ("flags", "reserved1", "data_block_nr", "data_block_len") fmt = v4c.FMT_DATA_EQUAL_LIST.format(self.links_nr) else: keys += ("flags", "reserved1", "data_block_nr") keys += tuple(f"offset_{i}" for i in range(self.data_block_nr)) fmt = v4c.FMT_DATA_LIST.format(self.links_nr, self.data_block_nr) result = pack(fmt, *[getattr(self, key) for key in keys]) return result class _EventBlockBase: __slots__ = ( "address", "attachment_nr", "block_len", "cause", "comment", "comment_addr", "creator_index", "event_type", "flags", "group_name", "group_name_addr", "id", "links_nr", "name", "name_addr", "next_ev_addr", "parent", "parent_ev_addr", "range_start", "range_start_ev_addr", "range_type", "reserved0", "reserved1", "scope_nr", "scopes", "sync_base", "sync_factor", "sync_type", "tool", ) class EventBlockKwargs(BlockKwargs, total=False): tx_map: TxMap next_ev_addr: int parent_ev_addr: int range_start_ev_addr: int name_addr: int comment_addr: int event_type: int sync_type: int range_type: int cause: int flags: int sync_base: int sync_factor: float group_name_addr: int class EventBlock(_EventBlockBase): """`EventBlock` has the following attributes, which are also available as dict-like key-value pairs. EVBLOCK fields: * ``id`` - bytes : block ID; always b'##EV' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``next_ev_addr`` - int : address of next EVBLOCK * ``parent_ev_addr`` - int : address of parent EVLBOCK * ``range_start_ev_addr`` - int : address of EVBLOCK that is the start of the range for which this event is the end * ``name_addr`` - int : address of TXBLOCK that contains the event name * ``comment_addr`` - int : address of TXBLOCK/MDBLOCK that contains the event comment * ``scope__addr`` - int : address of N-th block that represents a scope for this event (can be CGBLOCK, CHBLOCK, DGBLOCK) * ``attachemnt__addr`` - int : address of N-th attachment referenced by this event * ``event_type`` - int : integer code for event type * ``sync_type`` - int : integer code for event sync type * ``range_type`` - int : integer code for event range type * ``cause`` - int : integer code for event cause * ``flags`` - int : event flags * ``reserved1`` - int : reserved bytes * ``scope_nr`` - int : number of scopes referenced by this event * ``attachment_nr`` - int : number of attachments referenced by this event * ``creator_index`` - int : index of FHBLOCK * ``sync_base`` - int : timestamp base value * ``sync_factor`` - float : timestamp factor Other attributes: * ``address`` - int : event block address * ``comment`` - str : event comment * ``name`` - str : event name * ``parent`` - int : index of event block that is the parent for the current event * ``range_start`` - int : index of event block that is the start of the range for which the current event is the end * ``scopes`` - list : list of (group index, channel index) or channel group index that define the scope of the current event """ def __init__(self, **kwargs: Unpack[EventBlockKwargs]) -> None: self.name = self.comment = self.group_name = "" self.scopes: list[tuple[int, int] | int] = [] self.parent: int | None = None self.range_start = None if "stream" in kwargs: self.address = address = kwargs["address"] stream = kwargs["stream"] stream.seek(address) (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_u(stream.read(COMMON_SIZE)) block = stream.read(self.block_len - COMMON_SIZE) links_nr = self.links_nr links: tuple[int, ...] = unpack_from(f"<{links_nr}Q", block) params: v4c.EventParams = unpack_from(v4c.FMT_EVENT_PARAMS, block, links_nr * 8) ( self.next_ev_addr, self.parent_ev_addr, self.range_start_ev_addr, self.name_addr, self.comment_addr, ) = links[:5] scope_nr = params[6] for i in range(scope_nr): self[f"scope_{i}_addr"] = links[5 + i] attachment_nr = params[7] for i in range(attachment_nr): self[f"attachment_{i}_addr"] = links[5 + scope_nr + i] ( self.event_type, self.sync_type, self.range_type, self.cause, self.flags, self.reserved1, self.scope_nr, self.attachment_nr, self.creator_index, self.sync_base, self.sync_factor, ) = params if self.flags & v4c.FLAG_EV_GROUP_NAME: self.group_name_addr = links[-1] if self.id != b"##EV": message = f'Expected "##EV" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) tx_map = kwargs.get("tx_map", {}) self.name = get_text_v4(self.name_addr, stream, tx_map=tx_map) self.comment = get_text_v4(self.comment_addr, stream, tx_map=tx_map) else: self.address = 0 scopes = 0 while f"scope_{scopes}_addr" in kwargs: scopes += 1 self.id = b"##EV" self.reserved0 = 0 self.block_len = 56 + (scopes + 5) * 8 self.links_nr = scopes + 5 self.next_ev_addr = kwargs.get("next_ev_addr", 0) self.parent_ev_addr = kwargs.get("parent_ev_addr", 0) self.range_start_ev_addr = kwargs.get("range_start_ev_addr", 0) self.name_addr = kwargs.get("name_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) for i in range(scopes): self[f"scope_{i}_addr"] = kwargs[f"scope_{i}_addr"] # type: ignore[literal-required] self.event_type = kwargs.get("event_type", v4c.EVENT_TYPE_TRIGGER) self.sync_type = kwargs.get("sync_type", v4c.EVENT_SYNC_TYPE_S) self.range_type = kwargs.get("range_type", v4c.EVENT_RANGE_TYPE_POINT) self.cause = kwargs.get("cause", v4c.EVENT_CAUSE_TOOL) self.flags = kwargs.get("flags", v4c.FLAG_EV_POST_PROCESSING) self.reserved1 = b"\x00\x00\x00" self.scope_nr = scopes self.attachment_nr = 0 self.creator_index = 0 self.sync_base = kwargs.get("sync_base", 1) self.sync_factor = kwargs.get("sync_factor", 1.0) if self.flags & v4c.FLAG_EV_GROUP_NAME: self.group_name_addr = kwargs.get("group_name_addr", 0) self.tool = extract_ev_tool(self.comment) def update_references(self, ch_map: dict[int, tuple[int, int]], cg_map: dict[int, int]) -> None: self.scopes.clear() for i in range(self.scope_nr): addr = typing.cast(int, self[f"scope_{i}_addr"]) if addr in ch_map: self.scopes.append(ch_map[addr]) elif addr in cg_map: self.scopes.append(cg_map[addr]) else: message = "{} is not a valid CNBLOCK or CGBLOCK address for the event scope" message = message.format(hex(addr)) logger.exception(message) raise MdfException(message) def __bytes__(self) -> bytes: fmt = v4c.FMT_EVENT.format(self.links_nr) keys: tuple[str, ...] = ( "id", "reserved0", "block_len", "links_nr", "next_ev_addr", "parent_ev_addr", "range_start_ev_addr", "name_addr", "comment_addr", ) keys += tuple(f"scope_{i}_addr" for i in range(self.scope_nr)) keys += tuple(f"attachment_{i}_addr" for i in range(self.attachment_nr)) if self.flags & v4c.FLAG_EV_GROUP_NAME: keys += ("group_name_addr",) keys += ( "event_type", "sync_type", "range_type", "cause", "flags", "reserved1", "scope_nr", "attachment_nr", "creator_index", "sync_base", "sync_factor", ) result = pack(fmt, *[getattr(self, key) for key in keys]) return result def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __str__(self) -> str: return f"EventBlock (name: {self.name}, comment: {self.comment}, address: {hex(self.address)}, scopes: {self.scopes}, fields: {super().__str__()})" @property def value(self) -> float: return self.sync_base * self.sync_factor @value.setter def value(self, val: float) -> None: self.sync_factor = val / self.sync_base def to_blocks(self, address: int, blocks: list[SupportsBytes]) -> int: text = self.name if text: tx_block = TextBlock(text=text) self.name_addr = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.name_addr = 0 text = self.comment if text: tx_block = TextBlock(text=text) self.comment_addr = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.comment_addr = 0 if self.flags & v4c.FLAG_EV_GROUP_NAME: text = self.group_name if text: tx_block = TextBlock(text=text) self.group_name_addr = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.group_name_addr = 0 blocks.append(self) self.address = address address += self.block_len return address class FileIdentificationBlockKwargs(BlockKwargs, total=False): version: str class FileIdentificationBlock: """`FileIdentificationBlock` has the following attributes, which are also available as dict-like key-value pairs. IDBLOCK fields: * ``file_identification`` - bytes : file identifier * ``version_str`` - bytes : format identifier * ``program_identification`` - bytes : creator program identifier * ``reserved0`` - bytes : reserved bytes * ``mdf_version`` - int : version number of MDF format * ``reserved1`` - bytes : reserved bytes * ``unfinalized_standard_flags`` - int : standard flags for unfinalized MDF * ``unfinalized_custom_flags`` - int : custom flags for unfinalized MDF Other attributes: * ``address`` - int : should always be 0 """ __slots__ = ( "address", "file_identification", "mdf_version", "program_identification", "reserved0", "reserved1", "unfinalized_custom_flags", "unfinalized_standard_flags", "version_str", ) def __init__(self, **kwargs: Unpack[FileIdentificationBlockKwargs]) -> None: super().__init__() self.address = 0 try: stream = kwargs["stream"] stream.seek(self.address) ( self.file_identification, self.version_str, self.program_identification, self.reserved0, self.mdf_version, self.reserved1, self.unfinalized_standard_flags, self.unfinalized_custom_flags, ) = typing.cast( v4c.IdentificationBlock, unpack(v4c.FMT_IDENTIFICATION_BLOCK, stream.read(v4c.IDENTIFICATION_BLOCK_SIZE)), ) except KeyError: version = kwargs.get("version", "4.00") self.file_identification = b"MDF " self.version_str = f"{version} ".encode() self.program_identification = f"{tool.__tool_short__}{tool.__version__}".encode() self.reserved0 = b"\0" * 4 self.mdf_version = int(version.replace(".", "")) self.reserved1 = b"\0" * 30 self.unfinalized_standard_flags = 0 self.unfinalized_custom_flags = 0 def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: result = pack( v4c.FMT_IDENTIFICATION_BLOCK, *[self[key] for key in v4c.KEYS_IDENTIFICATION_BLOCK], ) return result class FileHistoryKwargs(BlockKwargs, total=False): tx_map: TxMap reserved0: int block_len: int links_nr: int next_fh_addr: int comment_addr: int abs_time: int tz_offset: int daylight_save_time: int time_flags: int reserved1: bytes class FileHistory: """`FileHistory` has the following attributes, which are also available as dict-like key-value pairs. FHBLOCK fields: * ``id`` - bytes : block ID; always b'##FH' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``next_fh_addr`` - int : address of next FHBLOCK * ``comment_addr`` - int : address of TXBLOCK/MDBLOCK that contains the file history comment * ``abs_time`` - int : timestamp at which the file modification happened * ``tz_offset`` - int : UTC time offset in hours (= GMT time zone) * ``daylight_save_time`` - int : daylight saving time * ``time_flags`` - int : time flags * ``reserved1`` - bytes : reserved bytes Other attributes: * ``address`` - int : file history address * ``comment`` - str : history comment """ __slots__ = ( "abs_time", "address", "block_len", "comment", "comment_addr", "daylight_save_time", "id", "links_nr", "next_fh_addr", "reserved0", "reserved1", "time_flags", "tz_offset", ) def __init__(self, **kwargs: Unpack[FileHistoryKwargs]) -> None: super().__init__() self.comment = "" try: self.address = address = kwargs["address"] stream = kwargs["stream"] stream.seek(address) ( self.id, self.reserved0, self.block_len, self.links_nr, self.next_fh_addr, self.comment_addr, self.abs_time, self.tz_offset, self.daylight_save_time, self.time_flags, self.reserved1, ) = typing.cast(v4c.FileHistory, unpack(v4c.FMT_FILE_HISTORY, stream.read(v4c.FH_BLOCK_SIZE))) if self.id != b"##FH": message = f'Expected "##FH" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) tx_map = kwargs.get("tx_map", {}) self.comment = get_text_v4(address=self.comment_addr, stream=stream, tx_map=tx_map) except KeyError: self.id = b"##FH" self.reserved0 = kwargs.get("reserved0", 0) self.block_len = kwargs.get("block_len", v4c.FH_BLOCK_SIZE) self.links_nr = kwargs.get("links_nr", 2) self.next_fh_addr = kwargs.get("next_fh_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.abs_time = kwargs.get("abs_time", int(time.time()) * 10**9) self.tz_offset = kwargs.get("tz_offset", 120) self.daylight_save_time = kwargs.get("daylight_save_time", 60) self.time_flags = kwargs.get("time_flags", 2) self.reserved1 = kwargs.get("reserved1", b"\x00" * 3) localtz = dateutil.tz.tzlocal() self.time_stamp = datetime.fromtimestamp(time.time(), tz=localtz) def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int] ) -> int: text = self.comment if text: if text in defined_texts: self.comment_addr = defined_texts[text] else: meta = text.startswith(" object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: result = pack(v4c.FMT_FILE_HISTORY, *[self[key] for key in v4c.KEYS_FILE_HISTORY]) return result @property def time_stamp(self) -> datetime: """Getter and setter of the file history timestamp. Returns ------- timestamp : datetime.datetime Start timestamp. """ timestamp = self.abs_time / 10**9 tz_local = False if self.time_flags & v4c.FLAG_HD_LOCAL_TIME: tz_local = True tz = timezone.utc else: tz = timezone(timedelta(minutes=self.tz_offset + self.daylight_save_time)) try: timestamp_dt = datetime.fromtimestamp(timestamp, tz) if tz_local: timestamp_dt = timestamp_dt.replace(tzinfo=None) except OverflowError: timestamp_dt = datetime.fromtimestamp(0, tz) + timedelta(seconds=timestamp) return timestamp_dt @time_stamp.setter def time_stamp(self, timestamp: datetime) -> None: if timestamp.tzinfo is None: self.time_flags = v4c.FLAG_HD_LOCAL_TIME self.abs_time = int(timestamp.replace(tzinfo=timezone.utc).timestamp() * 10**9) self.tz_offset = 0 self.daylight_save_time = 0 else: self.time_flags = v4c.FLAG_HD_TIME_OFFSET_VALID tzinfo = timestamp.tzinfo dst = tzinfo.dst(timestamp) if dst is not None: dst_offset = int(dst.total_seconds() / 60) else: dst_offset = 0 utc_offset = tzinfo.utcoffset(timestamp) if utc_offset is None: raise RuntimeError("utc_offset is None") tz_offset = int(utc_offset.total_seconds() / 60) - dst_offset self.tz_offset = tz_offset self.daylight_save_time = dst_offset self.abs_time = int(timestamp.timestamp() * 10**9) def __repr__(self) -> str: return f"FHBLOCK(time={self.time_stamp}, comment={self.comment})" class GuardBlockKwargs(BlockKwargs, total=False): reserved0: int block_len: int links_nr: int gd_addr: int gd_version: int reserved1: bytes class GuardBlock: """`GuardBlock` has the following attributes, which are also available as dict-like key-value pairs. GDBLOCK fields: * ``id`` - bytes : block ID; always b'##GD' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``gd_addr`` - int : address of guarded block * ``gd_version`` - int : minimum MDF format version * ``reserved1`` - int : reserved bytes Other attributes: * ``address`` - int : guard block address """ __slots__ = ( "address", "block_len", "gd_addr", "gd_version", "guarded_block", "id", "links_nr", "reserved0", "reserved1", ) def __init__(self, **kwargs: Unpack[GuardBlockKwargs]) -> None: self.guarded_block = None try: self.address = address = kwargs["address"] stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) if utils.stream_is_mmap(stream, mapped): ( self.id, self.reserved0, self.block_len, self.links_nr, self.gd_addr, self.gd_version, self.reserved1, ) = v4c.GD_uf(stream, address) else: stream.seek(address) ( self.id, self.reserved0, self.block_len, self.links_nr, self.gd_addr, self.gd_version, self.reserved1, ) = v4c.GD_u(stream.read(v4c.GD_BLOCK_SIZE)) if self.id != b"##GD": message = f'Expected "##GD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) except KeyError: self.address = 0 self.id = b"##GD" self.reserved0 = kwargs.get("reserved0", 0) self.block_len = kwargs.get("block_len", v4c.GD_BLOCK_SIZE) self.links_nr = kwargs.get("links_nr", 1) self.gd_addr = kwargs.get("gd_addr", 0) self.gd_version = kwargs.get("gd_version", 430) self.reserved1 = kwargs.get("reserved1", b"\00" * 6) def copy(self) -> "GuardBlock": gd = GuardBlock( reserved0=self.reserved0, block_len=self.block_len, links_nr=self.links_nr, gd_addr=self.gd_addr, gd_version=self.gd_version, reserved1=self.reserved1, ) gd.address = self.address return gd def to_blocks(self, address: int, blocks: list[SupportsBytes], defined_texts: dict[str, int]) -> int: blocks.append(self) self.address = address self.gd_addr = self.guarded_block.address if self.guarded_block else 0 address += self.block_len return address def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: result = v4c.GD_p( self.id, self.reserved0, self.block_len, self.links_nr, self.gd_addr, self.gd_version, self.reserved1, ) return result class HeaderBlockKwargs(BlockKwargs, total=False): reserved3: int block_len: int links_nr: int first_dg_addr: int file_history_addr: int channel_tree_addr: int first_attachment_addr: int first_event_addr: int comment_addr: int abs_time: int tz_offset: int daylight_save_time: int time_flags: int time_quality: int flags: int reserved4: int start_angle: int start_distance: int class HeaderBlock: """`HeaderBlock` has the following attributes, which are also available as dict-like key-value pairs. HDBLOCK fields: * ``id`` - bytes : block ID; always b'##HD' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``first_dg_addr`` - int : address of first DGBLOCK * ``file_history_addr`` - int : address of first FHBLOCK * ``channel_tree_addr`` - int : address of first CHBLOCK * ``first_attachment_addr`` - int : address of first ATBLOCK * ``first_event_addr`` - int : address of first EVBLOCK * ``comment_addr`` - int : address of TXBLOCK/MDBLOCK that contains the file comment * ``abs_time`` - int : timestamp at which recording was started in nanoseconds. * ``tz_offset`` - int : UTC time offset in hours (= GMT time zone) * ``daylight_save_time`` - int : daylight saving time * ``time_flags`` - int : time flags * ``time_quality`` - int : time quality flags * ``flags`` - int : file flags * ``reserved1`` - int : reserved bytes * ``start_angle`` - int : angle value at measurement start * ``start_distance`` - int : distance value at measurement start Other attributes: * ``address`` - int : header address * ``comment`` - str : file comment * ``author`` - str : measurement author * ``department`` - str : author's department * ``project`` - str : working project * ``subject`` - str : measurement subject """ def __init__(self, **kwargs: Unpack[HeaderBlockKwargs]) -> None: super().__init__() self._common_properties: dict[str, object] = {} self._other_elements: list[ET.Element] = [] self.description = "" self.comment = "" try: self.address = address = kwargs["address"] stream = kwargs["stream"] stream.seek(address) ( self.id, self.reserved0, self.block_len, self.links_nr, self.first_dg_addr, self.file_history_addr, self.channel_tree_addr, self.first_attachment_addr, self.first_event_addr, self.comment_addr, self.abs_time, self.tz_offset, self.daylight_save_time, self.time_flags, self.time_quality, self.flags, self.reserved1, self.start_angle, self.start_distance, ) = typing.cast(v4c.HeaderBlock, unpack(v4c.FMT_HEADER_BLOCK, stream.read(v4c.HEADER_BLOCK_SIZE))) if self.id != b"##HD": message = f'Expected "##HD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) self.comment = get_text_v4(address=self.comment_addr, stream=stream, tx_map={}) except KeyError: self.address = 0x40 self.id = b"##HD" self.reserved0 = kwargs.get("reserved3", 0) self.block_len = kwargs.get("block_len", v4c.HEADER_BLOCK_SIZE) self.links_nr = kwargs.get("links_nr", 6) self.first_dg_addr = kwargs.get("first_dg_addr", 0) self.file_history_addr = kwargs.get("file_history_addr", 0) self.channel_tree_addr = kwargs.get("channel_tree_addr", 0) self.first_attachment_addr = kwargs.get("first_attachment_addr", 0) self.first_event_addr = kwargs.get("first_event_addr", 0) self.comment_addr = kwargs.get("comment_addr", 0) self.abs_time = kwargs.get("abs_time", 0) self.tz_offset = kwargs.get("tz_offset", 0) self.daylight_save_time = kwargs.get("daylight_save_time", 0) self.time_flags = kwargs.get("time_flags", 0) self.time_quality = kwargs.get("time_quality", 0) self.flags = kwargs.get("flags", 0) self.reserved1 = kwargs.get("reserved4", 0) self.start_angle = kwargs.get("start_angle", 0) self.start_distance = kwargs.get("start_distance", 0) localtz = dateutil.tz.tzlocal() self.start_time = datetime.fromtimestamp(time.time(), tz=localtz) @property def comment(self) -> str: def common_properties_to_xml(root: ET.Element, common_properties: dict[str, object]) -> None: for name, value in common_properties.items(): if isinstance(value, dict): list_element = ET.SubElement(root, "tree", name=name) common_properties_to_xml(list_element, value) else: value = typing.cast(str | None, value) ET.SubElement(root, "e", name=name).text = value root = ET.Element("HDcomment") text = ET.SubElement(root, "TX") text.text = self.description common = ET.SubElement(root, "common_properties") common_properties_to_xml(common, self._common_properties) for elem in self._other_elements: root.append(elem) comment_xml = ( ET.tostring(root, encoding="utf8", method="xml") .replace(b"\n", b"") .decode("utf-8") ) comment_xml = minidom.parseString(comment_xml).toprettyxml(indent=" ") return "\n".join([line.strip() for line in comment_xml.splitlines()[1:]]) @comment.setter def comment(self, string: str) -> None: self._common_properties = {} self._other_elements.clear() def parse_common_properties(root: ET.Element) -> dict[str, object]: info: dict[str, Any] = {} if root.tag in ("list", "tree", "elist"): root_name = root.attrib["name"] info[root_name] = {} try: for element in root: if element.tag == "e": name = element.attrib["name"] if root.tag == "tree": root_name = root.attrib["name"] info[root_name][name] = element.text or "" else: info[name] = element.text or "" elif element.tag in ("list", "tree", "elist"): info.update(parse_common_properties(element)) elif element.tag == "li": root_name = root.attrib["name"] info[root_name].update(parse_common_properties(element)) elif element.tag == "eli": root_name = root.attrib["name"] info[root_name][str(len(info[root_name]))] = element.text or "" except: print(format_exc()) return info if string.startswith(" str: return typing.cast(str, self._common_properties.get("author", "")) @author.setter def author(self, value: str) -> None: self._common_properties["author"] = value @property def project(self) -> str: return typing.cast(str, self._common_properties.get("project", "")) @project.setter def project(self, value: str) -> None: self._common_properties["project"] = value @property def department(self) -> str: return typing.cast(str, self._common_properties.get("department", "")) @department.setter def department(self, value: str) -> None: self._common_properties["department"] = value @property def subject(self) -> str: return typing.cast(str, self._common_properties.get("subject", "")) @subject.setter def subject(self, value: str) -> None: self._common_properties["subject"] = value def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) @property def start_time(self) -> datetime: """Getter and setter of the measurement start timestamp. Returns ------- timestamp : datetime.datetime Start timestamp. """ timestamp = self.abs_time / 10**9 tz_local = False if self.time_flags & v4c.FLAG_HD_LOCAL_TIME: tz = timezone.utc tz_local = True else: tz = timezone(timedelta(minutes=self.tz_offset + self.daylight_save_time)) try: timestamp_dt = datetime.fromtimestamp(timestamp, tz) if tz_local: timestamp_dt = timestamp_dt.replace(tzinfo=None) except OverflowError: timestamp_dt = datetime.fromtimestamp(0, tz) + timedelta(seconds=timestamp) return timestamp_dt @start_time.setter def start_time(self, timestamp: datetime) -> None: if timestamp.tzinfo is None: self.time_flags = v4c.FLAG_HD_LOCAL_TIME self.abs_time = int(timestamp.replace(tzinfo=timezone.utc).timestamp() * 10**9) self.tz_offset = 0 self.daylight_save_time = 0 else: self.time_flags = v4c.FLAG_HD_TIME_OFFSET_VALID tzinfo = timestamp.tzinfo dst = tzinfo.dst(timestamp) if dst is not None: dst_offset = int(dst.total_seconds() / 60) else: dst_offset = 0 utc_offset = tzinfo.utcoffset(timestamp) if utc_offset is None: raise RuntimeError("utc_offset is None") tz_offset = int(utc_offset.total_seconds() / 60) - dst_offset self.tz_offset = tz_offset self.daylight_save_time = dst_offset self.abs_time = int(timestamp.timestamp() * 10**9) def start_time_string(self) -> str: if self.time_flags & v4c.FLAG_HD_TIME_OFFSET_VALID: tz_offset = self.tz_offset / 60 tz_offset_sign = "-" if tz_offset < 0 else "+" dst_offset = self.daylight_save_time / 60 dst_offset_sign = "-" if dst_offset < 0 else "+" tz_information = f"[GMT{tz_offset_sign}{tz_offset:.2f} DST{dst_offset_sign}{dst_offset:.2f}h]" start_time = f"local time = {self.start_time.strftime('%d-%b-%Y %H:%M:%S + %fu')} {tz_information}" else: tzinfo = self.start_time.tzinfo if tzinfo is None: return ( f"local time = {self.start_time.strftime('%d-%b-%Y %H:%M:%S + %fu')} (no timezone info available)" ) dst = tzinfo.dst(self.start_time) if dst is not None: dst_offset = int(dst.total_seconds() / 3600) else: dst_offset = 0 utc_offset = tzinfo.utcoffset(self.start_time) if utc_offset is None: raise RuntimeError("utc_offset is None") tz_offset = int(utc_offset.total_seconds() / 3600) - dst_offset tz_offset_sign = "-" if tz_offset < 0 else "+" dst_offset_sign = "-" if dst_offset < 0 else "+" tz_information = f"[assumed GMT{tz_offset_sign}{tz_offset:.2f} DST{dst_offset_sign}{dst_offset:.2f}h]" start_time = f"local time = {self.start_time.strftime('%d-%b-%Y %H:%M:%S + %fu')} {tz_information}" return start_time def to_blocks(self, address: int, blocks: list[bytes | SupportsBytes]) -> int: blocks.append(self) self.address = address address += self.block_len tx_block = TextBlock(text=self.comment, meta=True) self.comment_addr = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) return address def __bytes__(self) -> bytes: result = pack(v4c.FMT_HEADER_BLOCK, *[self[key] for key in v4c.KEYS_HEADER_BLOCK]) return result class HeaderListKwargs(BlockKwargs, total=False): first_dl_addr: int flags: int zip_type: int class HeaderList: """`HeaderList` has the following attributes, which are also available as dict-like key-value pairs. HLBLOCK fields: * ``id`` - bytes : block ID; always b'##HL' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``first_dl_addr`` - int : address of first data list block for this header list * ``flags`` - int : source flags * ``zip_type`` - int : integer code for zip type * ``reserved1`` - bytes : reserved bytes Other attributes: * ``address`` - int : header list address """ __slots__ = ( "address", "block_len", "first_dl_addr", "flags", "id", "links_nr", "reserved0", "reserved1", "zip_type", ) def __init__(self, **kwargs: Unpack[HeaderListKwargs]) -> None: super().__init__() try: self.address = address = kwargs["address"] stream = kwargs["stream"] stream.seek(address) ( self.id, self.reserved0, self.block_len, self.links_nr, self.first_dl_addr, self.flags, self.zip_type, self.reserved1, ) = typing.cast(v4c.HlBlock, unpack(v4c.FMT_HL_BLOCK, stream.read(v4c.HL_BLOCK_SIZE))) if self.id != b"##HL": message = f'Expected "##HL" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) except KeyError: self.address = 0 self.id = b"##HL" self.reserved0 = 0 self.block_len = v4c.HL_BLOCK_SIZE self.links_nr = 1 self.first_dl_addr = kwargs.get("first_dl_addr", 0) self.flags = kwargs.get("flags", 1) self.zip_type = kwargs.get("zip_type", 0) self.reserved1 = b"\x00" * 5 def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: result = pack(v4c.FMT_HL_BLOCK, *[self[key] for key in v4c.KEYS_HL_BLOCK]) return result class _ListDataBase: __slots__ = ( "address", "block_len", "data_block_len", "data_block_nr", "flags", "id", "links_nr", "next_ld_addr", "reserved0", ) class ListDataKwargs(BlockKwargs, total=False): data_block_nr: int flags: int data_block_len: int class ListData(_ListDataBase): """`ListData` has the following attributes, which are also available as dict-like key-value pairs. LDBLOCK common fields: * ``id`` - bytes : block ID; always b'##LD' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``next_ld_addr`` - int : address of next LDBLOCK * ``data_block_addr_`` - int : address of N-th data block bits data block * ``flags`` - int : data list flags * ``data_block_nr`` - int : number of data blocks referenced by this list LDBLOCK specific fields: * if invalidation data present flag is set * ``invalidation_bits_addr_`` - int : address of N-th invalidation * for equal-length blocks * ``data_block_len`` - int : equal uncompressed size in bytes for all referenced data blocks; last block can be smaller * for variable-length blocks * ``offset_`` - int : byte offset of N-th data block * if time values flag is set * ``time_value_`` - int | float : first raw timestamp value of N-th data block * if angle values flag is set * ``angle_value_`` - int | float : first raw angle value of N-th data block * if distance values flag is set * ``distance_value_`` - int | float : first raw distance value of N-th data block Other attributes: * ``address`` - int : data list address """ def __init__(self, **kwargs: Unpack[ListDataKwargs]) -> None: try: self.address = address = kwargs["address"] stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) if utils.stream_is_mmap(stream, mapped): (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(stream, address) if self.id != b"##LD": message = f'Expected "##LD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) address += COMMON_SIZE links: tuple[int, ...] = unpack_from(f"<{self.links_nr}Q", stream, address) address += self.links_nr * 8 self.flags, self.data_block_nr = unpack_from("<2I", stream, address) address += 8 if self.flags & v4c.FLAG_LD_EQUAL_LENGHT: (self.data_block_len,) = UINT64_uf(stream, address) address += 8 else: offsets: tuple[int, ...] = unpack_from(f"<{self.data_block_nr}Q", stream, address) address += self.data_block_nr * 8 for i, offset in enumerate(offsets): self[f"offset_{i}"] = offset if self.flags & v4c.FLAG_LD_TIME_VALUES: values: tuple[bytes, ...] = unpack_from(f"<{8 * self.data_block_nr}s", stream, address) address += self.data_block_nr * 8 for i, value in enumerate(values): self[f"time_value_{i}"] = value if self.flags & v4c.FLAG_LD_ANGLE_VALUES: values = unpack_from(f"<{8 * self.data_block_nr}s", stream, address) address += self.data_block_nr * 8 for i, value in enumerate(values): self[f"angle_value_{i}"] = value if self.flags & v4c.FLAG_LD_DISTANCE_VALUES: values = unpack_from(f"<{8 * self.data_block_nr}s", stream, address) address += self.data_block_nr * 8 for i, value in enumerate(values): self[f"distance_value_{i}"] = value self.next_ld_addr = links[0] for i in range(self.data_block_nr): self[f"data_block_addr_{i}"] = links[i + 1] if self.flags & v4c.FLAG_LD_INVALIDATION_PRESENT: for i in range(self.data_block_nr): self[f"invalidation_bits_addr_{i}"] = links[self.data_block_nr + 1 + i] else: stream.seek(address) (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_u(stream.read(COMMON_SIZE)) if self.id != b"##LD": message = f'Expected "##LD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) links = unpack(f"<{self.links_nr}Q", stream.read(self.links_nr * 8)) self.flags, self.data_block_nr = typing.cast(tuple[int, int], unpack("<2I", stream.read(8))) if self.flags & v4c.FLAG_LD_EQUAL_LENGHT: (self.data_block_len,) = UINT64_u(stream.read(8)) else: offsets = unpack(f"<{self.data_block_nr}Q", stream.read(self.data_block_nr * 8)) for i, offset in enumerate(offsets): self[f"offset_{i}"] = offset if self.flags & v4c.FLAG_LD_TIME_VALUES: values = unpack( f"<{8 * self.data_block_nr}s", stream.read(self.data_block_nr * 8), ) for i, value in enumerate(values): self[f"time_value_{i}"] = value if self.flags & v4c.FLAG_LD_ANGLE_VALUES: values = unpack( f"<{8 * self.data_block_nr}s", stream.read(self.data_block_nr * 8), ) for i, value in enumerate(values): self[f"angle_value_{i}"] = value if self.flags & v4c.FLAG_LD_DISTANCE_VALUES: values = unpack( f"<{8 * self.data_block_nr}s", stream.read(self.data_block_nr * 8), ) for i, value in enumerate(values): self[f"distance_value_{i}"] = value self.next_ld_addr = links[0] for i in range(self.data_block_nr, 1): self[f"data_block_addr_{i}"] = links[i] if self.flags & v4c.FLAG_LD_INVALIDATION_PRESENT: for i in range(self.data_block_nr, self.data_block_nr + 1): self[f"invalidation_bits_addr_{i}"] = links[i] except KeyError: self.address = 0 self.id = b"##LD" self.reserved0 = 0 self.data_block_nr = kwargs["data_block_nr"] self.flags = kwargs["flags"] self.data_block_len = kwargs["data_block_len"] self.next_ld_addr = 0 for i in range(self.data_block_nr): self[f"data_block_addr_{i}"] = kwargs[f"data_block_addr_{i}"] # type: ignore[literal-required] if self.flags & v4c.FLAG_LD_INVALIDATION_PRESENT: self.links_nr = 2 * self.data_block_nr + 1 for i in range(self.data_block_nr): self[f"invalidation_bits_addr_{i}"] = kwargs[f"invalidation_bits_addr_{i}"] # type: ignore[literal-required] else: self.links_nr = self.data_block_nr + 1 self.block_len = 24 + self.links_nr * 8 + 16 def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: fmt = "<4sI3Q" keys: tuple[str, ...] = ( "id", "reserved0", "block_len", "links_nr", "next_ld_addr", ) fmt += f"{self.data_block_nr}Q" keys += tuple(f"data_block_addr_{i}" for i in range(self.data_block_nr)) if self.flags & v4c.FLAG_LD_INVALIDATION_PRESENT: fmt += f"{self.data_block_nr}Q" keys += tuple(f"invalidation_bits_addr_{i}" for i in range(self.data_block_nr)) fmt += "2I" keys += ("flags", "data_block_nr") if self.flags & v4c.FLAG_LD_EQUAL_LENGHT: fmt += "Q" keys += ("data_block_len",) else: fmt += f"<{self.data_block_nr}Q" keys += tuple(f"offset_{i}" for i in range(self.data_block_nr)) if self.flags & v4c.FLAG_LD_TIME_VALUES: fmt += "8s" * self.data_block_nr keys += tuple(f"time_value_{i}" for i in range(self.data_block_nr)) if self.flags & v4c.FLAG_LD_ANGLE_VALUES: fmt += "8s" * self.data_block_nr keys += tuple(f"angle_value_{i}" for i in range(self.data_block_nr)) if self.flags & v4c.FLAG_LD_DISTANCE_VALUES: fmt += "8s" * self.data_block_nr keys += tuple(f"distance_value_{i}" for i in range(self.data_block_nr)) result = pack(fmt, *[getattr(self, key) for key in keys]) return result class SourceInformationKwargs(BlockKwargs, total=False): raw_bytes: bytes tx_map: TxMap source_type: int bus_type: int class SourceInformation: """`SourceInformation` has the following attributes, which are also available as dict-like key-value pairs. SIBLOCK fields: * ``id`` - bytes : block ID; always b'##SI' * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``name_addr`` - int : address of TXBLOCK that contains the source name * ``path_addr`` - int : address of TXBLOCK that contains the source path * ``comment_addr`` - int : address of TXBLOCK/MDBLOCK that contains the source comment * ``source_type`` - int : integer code for source type * ``bus_type`` - int : integer code for source bus type * ``flags`` - int : source flags * ``reserved1`` - bytes : reserved bytes Other attributes: * ``address`` - int : source information address * ``comment`` - str : source comment * ``name`` - str : source name * ``path`` - str : source path """ __slots__ = ( "address", "block_len", "bus_type", "comment", "comment_addr", "flags", "id", "links_nr", "name", "name_addr", "path", "path_addr", "reserved0", "reserved1", "source_type", ) def __init__(self, **kwargs: Unpack[SourceInformationKwargs]) -> None: self.name = self.path = self.comment = "" if "stream" in kwargs: stream = kwargs["stream"] mapped = kwargs["mapped"] try: block = kwargs["raw_bytes"] self.address = address = kwargs["address"] except KeyError: self.address = address = kwargs["address"] stream.seek(address) block = stream.read(v4c.SI_BLOCK_SIZE) ( self.id, self.reserved0, self.block_len, self.links_nr, self.name_addr, self.path_addr, self.comment_addr, self.source_type, self.bus_type, self.flags, self.reserved1, ) = typing.cast(v4c.SourceInformation, unpack(v4c.FMT_SOURCE_INFORMATION, block)) if self.id != b"##SI": message = f'Expected "##SI" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) tx_map = kwargs["tx_map"] self.name = get_text_v4(address=self.name_addr, stream=stream, mapped=mapped, tx_map=tx_map) self.path = get_text_v4(address=self.path_addr, stream=stream, mapped=mapped, tx_map=tx_map) self.comment = get_text_v4(address=self.comment_addr, stream=stream, mapped=mapped, tx_map=tx_map) else: self.address = 0 self.id = b"##SI" self.reserved0 = 0 self.block_len = v4c.SI_BLOCK_SIZE self.links_nr = 3 self.name_addr = 0 self.path_addr = 0 self.comment_addr = 0 self.source_type = kwargs.get("source_type", v4c.SOURCE_TOOL) self.bus_type = kwargs.get("bus_type", v4c.BUS_TYPE_NONE) self.flags = 0 self.reserved1 = b"\x00" * 5 def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __contains__(self, item: str) -> bool: return hasattr(self, item) def copy(self) -> "SourceInformation": source = SourceInformation( source_type=self.source_type, bus_type=self.bus_type, ) source.name = self.name source.comment = self.comment source.path = self.path return source def metadata(self) -> str: max_len = max(len(key) for key in v4c.KEYS_SOURCE_INFORMATION) template = f"{{: <{max_len}}}: {{}}" metadata: list[str] = [] lines = f""" name: {self.name} path: {self.path} address: {hex(self.address)} comment: {self.comment} """.split("\n") for key in v4c.KEYS_SOURCE_INFORMATION: val = getattr(self, key) if key.endswith("addr") or key.startswith("text_"): lines.append(template.format(key, hex(val))) elif isinstance(val, float): lines.append(template.format(key, round(val, 6))) else: if isinstance(val, bytes): lines.append(template.format(key, val.strip(b"\0"))) else: lines.append(template.format(key, val)) if key == "source_type": lines[-1] += f" = {v4c.SOURCE_TYPE_TO_STRING[self.source_type]}" elif key == "bus_type": lines[-1] += f" = {v4c.BUS_TYPE_TO_STRING[self.bus_type]}" for line in lines: if not line: metadata.append(line) else: for wrapped_line in wrap(line, width=120): metadata.append(wrapped_line) return "\n".join(metadata) def to_blocks( self, address: int, blocks: list[bytes | SupportsBytes], defined_texts: dict[bytes | str, int], si_map: dict[bytes | int, int], ) -> int: id_ = id(self) if id_ in si_map: return address text = self.name if text: if text in defined_texts: self.name_addr = defined_texts[text] else: tx_block = TextBlock( text=text.encode("utf-8", "replace"), meta=False, safe=True, ) self.name_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.name_addr = 0 text = self.path if text: if text in defined_texts: self.path_addr = defined_texts[text] else: tx_block = TextBlock( text=text.encode("utf-8", "replace"), meta=False, safe=True, ) self.path_addr = address defined_texts[text] = address tx_block.address = address address += tx_block.block_len blocks.append(tx_block) else: self.path_addr = 0 text = self.comment if text: if text in defined_texts: self.comment_addr = defined_texts[text] else: meta = text.startswith(" "SourceInformation": obj = cls() obj.name = source.name obj.path = source.path obj.comment = source.comment obj.source_type = source.source_type obj.bus_type = source.bus_type return obj def __bytes__(self) -> bytes: return v4c.SOURCE_INFORMATION_PACK( self.id, self.reserved0, self.block_len, self.links_nr, self.name_addr, self.path_addr, self.comment_addr, self.source_type, self.bus_type, self.flags, self.reserved1, ) def __str__(self) -> str: return f"" class TextBlockKwargs(BlockKwargs, total=False): safe: bool text: bytes | str meta: bool class TextBlock: """Common TXBLOCK and MDBLOCK class. `TextBlock` has the following attributes, which are also available as dict-like key-value pairs. TXBLOCK fields: * ``id`` - bytes : block ID; b'##TX' for TXBLOCK and b'##MD' for MDBLOCK * ``reserved0`` - int : reserved bytes * ``block_len`` - int : block bytes size * ``links_nr`` - int : number of links * ``text`` - bytes : actual text content Other attributes: * ``address`` - int : text block address Parameters ---------- address : int Block address. stream : handle File handle. meta : bool Flag to set the block type to MDBLOCK for dynamically created objects; default is False. text : bytes/str Text content for dynamically created objects. """ __slots__ = ("address", "block_len", "id", "links_nr", "reserved0", "text") def __init__(self, **kwargs: Unpack[TextBlockKwargs]) -> None: if "safe" in kwargs: self.address = 0 text = kwargs["text"] size = len(text) self.id = b"##MD" if kwargs["meta"] else b"##TX" self.reserved0 = 0 self.links_nr = 0 self.text = text self.block_len = size + 32 - size % 8 elif "stream" in kwargs: stream = kwargs["stream"] mapped = kwargs.get("mapped", False) or not is_file_like(stream) self.address = address = kwargs["address"] if utils.stream_is_mmap(stream, mapped): (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_uf(stream, address) size = self.block_len - COMMON_SIZE if self.id not in (b"##TX", b"##MD"): message = f'Expected "##TX" or "##MD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) self.text = text = stream[address + COMMON_SIZE : address + self.block_len] else: stream.seek(address) (self.id, self.reserved0, self.block_len, self.links_nr) = COMMON_u(stream.read(COMMON_SIZE)) size = self.block_len - COMMON_SIZE if self.id not in (b"##TX", b"##MD"): message = f'Expected "##TX" or "##MD" block @{hex(address)} but found "{self.id!r}"' logger.exception(message) raise MdfException(message) self.text = text = stream.read(size) align = size % 8 if align: self.block_len = size + COMMON_SIZE + 8 - align else: if text: if text[-1]: self.block_len += 8 else: self.block_len += 8 else: text = kwargs["text"] if isinstance(text, str): text = text.encode("utf-8", "replace") size = len(text) self.id = b"##MD" if kwargs.get("meta", False) else b"##TX" self.reserved0 = 0 self.links_nr = 0 self.text = text self.block_len = size + 32 - size % 8 def __getitem__(self, item: str) -> object: return getattr(self, item) def __setitem__(self, item: str, value: object) -> None: setattr(self, item, value) def __bytes__(self) -> bytes: return pack( f"<4sI2Q{self.block_len - COMMON_SIZE}s", self.id, self.reserved0, self.block_len, self.links_nr, self.text, ) def __repr__(self) -> str: return ( f"TextBlock(id={self.id!r}," f"reserved0={self.reserved0}, " f"block_len={self.block_len}, " f"links_nr={self.links_nr} " f"text={self.text!r})" ) asammdf-8.5.1/src/asammdf/blocks/v4_constants.py000066400000000000000000000615741502633300400216210ustar00rootroot00000000000000"""MDF v4 constants""" from collections.abc import Callable from enum import IntEnum import re import struct import sys from typing import Literal from typing_extensions import Buffer from .blocks_common import UnpackFrom SUPPORTED_MDF_VERSION = 420 MAX_UINT64 = (1 << 64) - 1 DATA_TYPE_UNSIGNED_INTEL = 0 DATA_TYPE_UNSIGNED_MOTOROLA = 1 DATA_TYPE_SIGNED_INTEL = 2 DATA_TYPE_SIGNED_MOTOROLA = 3 DATA_TYPE_REAL_INTEL = 4 DATA_TYPE_REAL_MOTOROLA = 5 DATA_TYPE_STRING_LATIN_1 = 6 DATA_TYPE_STRING_UTF_8 = 7 DATA_TYPE_STRING_UTF_16_LE = 8 DATA_TYPE_STRING_UTF_16_BE = 9 DATA_TYPE_BYTEARRAY = 10 DATA_TYPE_MIME_SAMPLE = 11 DATA_TYPE_MIME_STREAM = 12 DATA_TYPE_CANOPEN_DATE = 13 DATA_TYPE_CANOPEN_TIME = 14 DATA_TYPE_COMPLEX_INTEL = 15 DATA_TYPE_COMPLEX_MOTOROLA = 16 DATA_TYPE_STRING_WITH_BOM = 17 VALID_DATA_TYPES = { DATA_TYPE_UNSIGNED_INTEL, DATA_TYPE_UNSIGNED_MOTOROLA, DATA_TYPE_SIGNED_INTEL, DATA_TYPE_SIGNED_MOTOROLA, DATA_TYPE_REAL_INTEL, DATA_TYPE_REAL_MOTOROLA, DATA_TYPE_STRING_LATIN_1, DATA_TYPE_STRING_UTF_8, DATA_TYPE_STRING_UTF_16_LE, DATA_TYPE_STRING_UTF_16_BE, DATA_TYPE_BYTEARRAY, DATA_TYPE_MIME_SAMPLE, DATA_TYPE_MIME_STREAM, DATA_TYPE_CANOPEN_DATE, DATA_TYPE_CANOPEN_TIME, DATA_TYPE_COMPLEX_INTEL, DATA_TYPE_COMPLEX_MOTOROLA, } DATA_TYPE_TO_STRING = dict( enumerate( [ "UNSIGNED_INTEL", "UNSIGNED_MOTOROLA", "SIGNED_INTEL", "SIGNED_MOTOROLA", "REAL_INTEL", "REAL_MOTOROLA", "STRING_LATIN_1", "STRING_UTF_8", "STRING_UTF_16_LE", "STRING_UTF_16_BE", "BYTEARRAY", "MIME_SAMPLE", "MIME_STREAM", "CANOPEN_DATE", "CANOPEN_TIME", "COMPLEX_INTEL", "COMPLEX_MOTOROLA", ] ) ) NON_SCALAR_TYPES = { DATA_TYPE_BYTEARRAY, DATA_TYPE_MIME_SAMPLE, DATA_TYPE_MIME_STREAM, DATA_TYPE_STRING_UTF_8, DATA_TYPE_STRING_LATIN_1, DATA_TYPE_STRING_UTF_16_BE, DATA_TYPE_STRING_UTF_16_LE, DATA_TYPE_CANOPEN_DATE, DATA_TYPE_CANOPEN_TIME, } STRING_TYPES = { DATA_TYPE_STRING_UTF_8, DATA_TYPE_STRING_LATIN_1, DATA_TYPE_STRING_UTF_16_BE, DATA_TYPE_STRING_UTF_16_LE, } SIGNAL_TYPE_SCALAR = 0 SIGNAL_TYPE_STRING = 1 SIGNAL_TYPE_CANOPEN = 2 SIGNAL_TYPE_STRUCTURE_COMPOSITION = 3 SIGNAL_TYPE_ARRAY = 4 SIGNAL_TYPE_BYTEARRAY = 5 SIGNAL_TYPE_VIRTUAL = 6 SIGNED_INT = {DATA_TYPE_SIGNED_INTEL, DATA_TYPE_SIGNED_MOTOROLA} FLOATS = {DATA_TYPE_REAL_INTEL, DATA_TYPE_REAL_MOTOROLA} STANDARD_INT_SIZES = {8, 16, 32, 64} INT_TYPES = { DATA_TYPE_UNSIGNED_INTEL, DATA_TYPE_UNSIGNED_MOTOROLA, DATA_TYPE_SIGNED_INTEL, DATA_TYPE_SIGNED_MOTOROLA, } CHANNEL_TYPE_VALUE = 0 CHANNEL_TYPE_VLSD = 1 CHANNEL_TYPE_MASTER = 2 CHANNEL_TYPE_VIRTUAL_MASTER = 3 CHANNEL_TYPE_SYNC = 4 CHANNEL_TYPE_MLSD = 5 CHANNEL_TYPE_VIRTUAL = 6 CHANNEL_TYPE_VLSC = 7 SYNC_TYPE_NONE = 0 SYNC_TYPE_TIME = 1 SYNC_TYPE_ANGLE = 2 SYNC_TYPE_DISTANCE = 3 SYNC_TYPE_INDEX = 4 SYNC_TYPE_TO_STRING = dict(enumerate(["NONE", "TIME", "ANGLE", "DISTANCE", "INDEX"])) CHANNEL_TYPE_TO_STRING = CHANNEL_TYPE_TO_DESCRIPTION = { CHANNEL_TYPE_VALUE: "VALUE", CHANNEL_TYPE_VLSD: "VLSD", CHANNEL_TYPE_MASTER: "MASTER", CHANNEL_TYPE_VIRTUAL_MASTER: "VIRTUAL MASTER", CHANNEL_TYPE_SYNC: "SYNC", CHANNEL_TYPE_MLSD: "MLSD", CHANNEL_TYPE_VIRTUAL: "VIRTUAL", } MASTER_TYPES = {CHANNEL_TYPE_MASTER, CHANNEL_TYPE_VIRTUAL_MASTER} VIRTUAL_TYPES = {CHANNEL_TYPE_VIRTUAL, CHANNEL_TYPE_VIRTUAL_MASTER} CONVERSION_TYPE_NON = 0 CONVERSION_TYPE_LIN = 1 CONVERSION_TYPE_RAT = 2 CONVERSION_TYPE_ALG = 3 CONVERSION_TYPE_TABI = 4 CONVERSION_TYPE_TAB = 5 CONVERSION_TYPE_RTAB = 6 CONVERSION_TYPE_TABX = 7 CONVERSION_TYPE_RTABX = 8 CONVERSION_TYPE_TTAB = 9 CONVERSION_TYPE_TRANS = 10 CONVERSION_TYPE_BITFIELD = 11 CONVERSION_TYPE_TO_STRING = dict( enumerate( [ "NON", "LIN", "RAT", "ALG", "TABI", "TAB", "RTAB", "TABX", "RTABX", "TTAB", "TRANS", "BITFIELD", ] ) ) CONV_RAT_TEXT = "(P1 * X**2 + P2 * X + P3) / (P4 * X**2 + P5 * X + P6)" TABULAR_CONVERSIONS = { CONVERSION_TYPE_TABX, CONVERSION_TYPE_RTABX, CONVERSION_TYPE_TTAB, CONVERSION_TYPE_BITFIELD, } CONVERSIONS_WITH_TEXTS = { CONVERSION_TYPE_ALG, CONVERSION_TYPE_RTABX, CONVERSION_TYPE_TABX, CONVERSION_TYPE_TRANS, CONVERSION_TYPE_TTAB, CONVERSION_TYPE_BITFIELD, } CONVERSIONS_NUMERIC = { CONVERSION_TYPE_NON, CONVERSION_TYPE_LIN, CONVERSION_TYPE_RAT, CONVERSION_TYPE_ALG, CONVERSION_TYPE_TABI, CONVERSION_TYPE_TAB, CONVERSION_TYPE_RTAB, } CONVERSION_GROUP_1 = {CONVERSION_TYPE_NON, CONVERSION_TYPE_TRANS, CONVERSION_TYPE_TTAB} CONVERSION_GROUP_2 = { CONVERSION_TYPE_LIN, CONVERSION_TYPE_RAT, CONVERSION_TYPE_ALG, CONVERSION_TYPE_TABI, CONVERSION_TYPE_TAB, CONVERSION_TYPE_RTAB, } CA_TYPE_ARRAY = 0 CA_TYPE_SCALE_AXIS = 1 CA_TYPE_LOOKUP = 2 CA_STORAGE_TYPE_CN_TEMPLATE = 0 CA_STORAGE_TYPE_CG_TEMPLATE = 1 CA_STORAGE_TYPE_DG_TEMPLATE = 2 SOURCE_OTHER = 0 SOURCE_ECU = 1 SOURCE_BUS = 2 SOURCE_IO = 3 SOURCE_TOOL = 4 SOURCE_USER = 5 SOURCE_VIDEO = 6 SOURCE_RADAR = 7 SOURCE_LIDAR = 8 SOURCE_PROTOCOL = 9 SOURCE_TYPE_TO_STRING = { SOURCE_OTHER: "OTHER", SOURCE_ECU: "ECU", SOURCE_BUS: "BUS", SOURCE_IO: "IO", SOURCE_TOOL: "TOOL", SOURCE_USER: "USER", SOURCE_VIDEO: "VIDEO", SOURCE_RADAR: "RADAR", SOURCE_LIDAR: "LIDAR", SOURCE_PROTOCOL: "PROTOCOL", } BUS_TYPE_NONE = 0 BUS_TYPE_OTHER = 1 BUS_TYPE_CAN = 2 BUS_TYPE_LIN = 3 BUS_TYPE_MOST = 4 BUS_TYPE_FLEXRAY = 5 BUS_TYPE_K_LINE = 6 BUS_TYPE_ETHERNET = 7 BUS_TYPE_USB = 8 BUS_LOGGING_TYPES = {BUS_TYPE_CAN, BUS_TYPE_FLEXRAY, BUS_TYPE_K_LINE, BUS_TYPE_LIN} BUS_TYPE_TO_STRING = { BUS_TYPE_NONE: "NONE", BUS_TYPE_OTHER: "OTHER", BUS_TYPE_CAN: "CAN", BUS_TYPE_LIN: "LIN", BUS_TYPE_MOST: "MOST", BUS_TYPE_FLEXRAY: "FLEXRAY", BUS_TYPE_K_LINE: "K_LINE", BUS_TYPE_ETHERNET: "ETHERNET", BUS_TYPE_USB: "USB", } EVENT_TYPE_RECORDING = 0 EVENT_TYPE_RECORDING_INTERRUPT = 1 EVENT_TYPE_ACQUISITION_INTERRUPT = 2 EVENT_TYPE_START_RECORDING_TRIGGER = 3 EVENT_TYPE_STOP_RECORDING_TRIGGER = 4 EVENT_TYPE_TRIGGER = 5 EVENT_TYPE_MARKER = 6 EVENT_TYPE_TO_STRING = { EVENT_TYPE_RECORDING: "Recording", EVENT_TYPE_RECORDING_INTERRUPT: "Recording interrupt", EVENT_TYPE_ACQUISITION_INTERRUPT: "Acquisition interrupt", EVENT_TYPE_START_RECORDING_TRIGGER: "Start recording trigger", EVENT_TYPE_STOP_RECORDING_TRIGGER: "Stop recording trigger", EVENT_TYPE_TRIGGER: "Trigger", EVENT_TYPE_MARKER: "Bookmark", } EVENT_SYNC_TYPE_S = 1 EVENT_SYNC_TYPE_RAD = 2 EVENT_SYNC_TYPE_M = 3 EVENT_SYNC_TYPE_INDEX = 4 EVENT_RANGE_TYPE_POINT = 0 EVENT_RANGE_TYPE_BEGINNING = 1 EVENT_RANGE_TYPE_END = 2 EVENT_CAUSE_OTHER = 0 EVENT_CAUSE_ERROR = 1 EVENT_CAUSE_TOOL = 2 EVENT_CAUSE_SCRIPT = 3 EVENT_CAUSE_USER = 4 SEEK_START = 0 SEEK_REL = 1 SEEK_END = 2 TIME_CH_SIZE = 8 SI_BLOCK_SIZE = 56 FH_BLOCK_SIZE = 56 DG_BLOCK_SIZE = 64 HD_BLOCK_SIZE = 104 CN_BLOCK_SIZE = 160 CN_SINGLE_ATTACHMENT_BLOCK_SIZE = 168 CG_BLOCK_SIZE = 104 CG_RM_BLOCK_SIZE = 112 COMMON_SIZE = 24 COMMON_SHORT_SIZE = 16 CC_NONE_BLOCK_SIZE = 80 CC_ALG_BLOCK_SIZE = 88 CC_LIN_BLOCK_SIZE = 96 AT_COMMON_SIZE = 96 DZ_COMMON_SIZE = 48 DZ_COMMON_INFO_SIZE = 22 CC_COMMON_BLOCK_SIZE = 80 HL_BLOCK_SIZE = 40 IDENTIFICATION_BLOCK_SIZE = 64 HEADER_BLOCK_SIZE = 104 SR_BLOCK_SIZE = 64 GD_BLOCK_SIZE = 40 FLAG_ALL_SAMPLES_VALID = 1 FLAG_INVALIDATION_BIT_VALID = 2 FLAG_PRECISION = 1 FLAG_PHY_RANGE_OK = 1 << 4 FLAG_VAL_RANGE_OK = 1 << 3 FLAG_AT_EMBEDDED = 1 FLAG_AT_COMPRESSED_EMBEDDED = 2 FLAG_AT_MD5_VALID = 4 FLAG_DZ_DEFLATE = 0 FLAG_DZ_TRANSPOSED_DEFLATE = 1 FLAG_DZ_ZSTD = 2 FLAG_DZ_TRANSPOSED_ZSTD = 3 FLAG_DZ_LZ4 = 4 FLAG_DZ_TRANSPOSED_LZ4 = 5 FLAG_CA_DYNAMIC_AXIS = 1 FLAG_CA_INPUT_QUANTITY = 1 << 1 FLAG_CA_OUTPUT_QUANTITY = 1 << 2 FLAG_CA_COMPARISON_QUANTITY = 1 << 3 FLAG_CA_AXIS = 1 << 4 FLAG_CA_FIXED_AXIS = 1 << 5 FLAG_CA_INVERSE_LAYOUT = 1 << 6 FLAG_CA_LEFT_OPENED_INTERVAL = 1 << 7 FLAG_CA_STANDARD_AXIS = 1 << 8 FLAG_DL_EQUAL_LENGHT = 1 FLAG_DL_TIME_VALUES = 1 << 1 FLAG_DL_ANGLE_VALUES = 1 << 2 FLAG_DL_DISTANCE_VALUES = 1 << 3 FLAG_LD_EQUAL_LENGHT = 1 FLAG_LD_TIME_VALUES = 1 << 1 FLAG_LD_ANGLE_VALUES = 1 << 2 FLAG_LD_DISTANCE_VALUES = 1 << 3 FLAG_LD_INVALIDATION_PRESENT = 1 << 31 FLAG_EV_POST_PROCESSING = 1 FLAG_EV_GROUP_NAME = 1 << 1 FLAG_CG_VLSD = 1 FLAG_CG_BUS_EVENT = 1 << 1 FLAG_CG_PLAIN_BUS_EVENT = 1 << 2 FLAG_CG_REMOTE_MASTER = 1 << 3 FLAG_CG_EVENT_GROUP = 1 << 4 FLAG_UNFIN_UPDATE_CG_COUNTER = 0x1 FLAG_UNFIN_UPDATE_SR_COUNTER = 0x2 FLAG_UNFIN_UPDATE_LAST_DT_LENGTH = 0x4 FLAG_UNFIN_UPDATE_LAST_RD_LENGTH = 0x8 FLAG_UNFIN_UPDATE_LAST_DL = 0x10 FLAG_UNFIN_UPDATE_VLSD_BYTES = 0x20 FLAG_UNFIN_UPDATE_VLSD_OFFSETS = 0x40 FLAG_CG_TO_STRING = { FLAG_CG_VLSD: "VLSD", FLAG_CG_BUS_EVENT: "BUS_EVENT", FLAG_CG_PLAIN_BUS_EVENT: "PLAIN_BUS_EVENT", FLAG_CG_REMOTE_MASTER: "REMOTE_MASTER", FLAG_CG_EVENT_GROUP: "EVENT_GROUP", } FLAG_AT_TO_STRING = { FLAG_AT_EMBEDDED: "Embedded", FLAG_AT_COMPRESSED_EMBEDDED: "Compressed", FLAG_AT_MD5_VALID: "MD5 sum valid", } FLAG_CN_ALL_INVALID = 1 FLAG_CN_INVALIDATION_PRESENT = 1 << 1 FLAG_CN_PRECISION = 1 << 2 FLAG_CN_VALUE_RANGE = 1 << 3 FLAG_CN_LIMIT_RANGE = 1 << 4 FLAG_CN_EXTENDED_LIMIT_RANGE = 1 << 5 FLAG_CN_DISCRETE = 1 << 6 FLAG_CN_CALIBRATION = 1 << 7 FLAG_CN_CALCULATED = 1 << 8 FLAG_CN_VIRTUAL = 1 << 9 FLAG_CN_BUS_EVENT = 1 << 10 FLAG_CN_MONOTONOUS = 1 << 11 FLAG_CN_DEFAULT_X = 1 << 12 FLAG_CN_EVENT_SIGNAL = 1 << 13 FLAG_CN_VLSD = 1 << 14 FLAG_CN_RAW_SENSOR_EVENT = 1 << 15 FLAG_CN_AUXILIARY_CHANNEL = 1 << 16 FLAG_CN_DS = 1 << 17 FLAG_CN_ALIGNMENT_RESET = 1 << 18 FLAG_CN_PROTOCOL_EVENT = 1 << 19 FLAG_CN_TO_STRING = { FLAG_CN_ALL_INVALID: "ALL_INVALID", FLAG_CN_INVALIDATION_PRESENT: "INVALIDATION_PRESENT", FLAG_CN_PRECISION: "PRECISION", FLAG_CN_VALUE_RANGE: "VALUE_RANGE", FLAG_CN_LIMIT_RANGE: "LIMIT_RANGE", FLAG_CN_EXTENDED_LIMIT_RANGE: "EXTENDED_LIMIT_RANGE", FLAG_CN_DISCRETE: "DISCRETE", FLAG_CN_CALIBRATION: "CALIBRATION", FLAG_CN_CALCULATED: "CALCULATED", FLAG_CN_VIRTUAL: "VIRTUAL", FLAG_CN_BUS_EVENT: "BUS_EVENT", FLAG_CN_MONOTONOUS: "MONOTONOUS", FLAG_CN_DEFAULT_X: "DEFAULT_X", FLAG_CN_EVENT_SIGNAL: "EVENT_SIGNAL", FLAG_CN_VLSD: "VLSD", } FLAG_CC_PRECISION = 1 FLAG_CC_RANGE = 1 << 1 FLAG_HD_LOCAL_TIME = 1 FLAG_HD_TIME_OFFSET_VALID = 2 # data location LOCATION_ORIGINAL_FILE = 0 LOCATION_TEMPORARY_FILE = 1 LOCATION_MEMORY = 2 # data block type DT_BLOCK = 0 DZ_BLOCK_DEFLATE = 1 DZ_BLOCK_TRANSPOSED = 2 DZ_BLOCK_LZ = 3 class CompressionAlgorithm(IntEnum): NO_COMPRESSION = 0 DEFLATE = 1 TRANSPOSED_DEFLATE = 2 ZSTD = 3 TRANSPOSED_ZSTD = 4 LZ4 = 5 TRANSPOSED_LZ4 = 6 FMT_CHANNEL = "<4sI2Q{}Q4B4I2BH6d" FMT_CHANNEL_PARAMS = "<4B4I2BH6d" Channel = tuple[int, int, int, int, int, int, int, int, int, int, int, float, float, float, float, float, float] FMT_CHANNEL_FILTER = "<4s12x4Q32xQ" ChannelFilter = tuple[bytes, int, int, int, int, int] CHANNEL_FILTER_u: Callable[[Buffer], ChannelFilter] = struct.Struct(FMT_CHANNEL_FILTER).unpack CHANNEL_FILTER_uf: UnpackFrom[ChannelFilter] = struct.Struct(FMT_CHANNEL_FILTER).unpack_from CHANNEL_FILTER_SIZE = 88 FMT_SIMPLE_CHANNEL = "<4sI10Q4B4I2BH6d" KEYS_SIMPLE_CHANNEL = ( "id", "reserved0", "block_len", "links_nr", "next_ch_addr", "component_addr", "name_addr", "source_addr", "conversion_addr", "data_block_addr", "unit_addr", "comment_addr", "channel_type", "sync_type", "data_type", "bit_offset", "byte_offset", "bit_count", "flags", "pos_invalidation_bit", "precision", "reserved1", "attachment_nr", "min_raw_value", "max_raw_value", "lower_limit", "upper_limit", "lower_ext_limit", "upper_ext_limit", ) FMT_SIMPLE_CHANNEL_PARAMS = "<8Q4B4I2BH6d" SimpleChannel = tuple[ int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, float, float, float, float, float, float, ] SIMPLE_CHANNEL_PARAMS_u: Callable[[Buffer], SimpleChannel] = struct.Struct(FMT_SIMPLE_CHANNEL_PARAMS).unpack SIMPLE_CHANNEL_PARAMS_uf: UnpackFrom[SimpleChannel] = struct.Struct(FMT_SIMPLE_CHANNEL_PARAMS).unpack_from SIMPLE_CHANNEL_PACK = struct.Struct(FMT_SIMPLE_CHANNEL).pack FMT_SINGLE_ATTACHMENT_CHANNEL = "<4sI11Q4B4I2BH6d" SINGLE_ATTACHMENT_CHANNEL_PACK = struct.Struct(FMT_SINGLE_ATTACHMENT_CHANNEL).pack FMT_SINGLE_ATTACHMENT_CHANNEL_PARAMS = "<9Q4B4I2BH6d" SingleAttachmentChannel = tuple[ int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, float, float, float, float, float, float, ] SINGLE_ATTACHMENT_CHANNEL_PARAMS_uf: UnpackFrom[SingleAttachmentChannel] = struct.Struct( FMT_SINGLE_ATTACHMENT_CHANNEL_PARAMS ).unpack_from SINGLE_ATTACHMENT_CHANNEL_PARAMS_u: Callable[[Buffer], SingleAttachmentChannel] = struct.Struct( FMT_SINGLE_ATTACHMENT_CHANNEL_PARAMS ).unpack FMT_TEXT_BLOCK = "<4sIQQ{}s" KEYS_TEXT_BLOCK = ("id", "reserved0", "block_len", "links_nr", "text") FMT_SOURCE_INFORMATION = "<4sI5Q3B5s" SourceInformation = tuple[bytes, int, int, int, int, int, int, int, int, int, bytes] KEYS_SOURCE_INFORMATION = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "path_addr", "comment_addr", "source_type", "bus_type", "flags", "reserved1", ) SOURCE_INFORMATION_PACK = struct.Struct(FMT_SOURCE_INFORMATION).pack FMT_CHANNEL_GROUP = "<4sI10Q2H3I" ChannelGroup = tuple[bytes, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int] KEYS_CHANNEL_GROUP = ( "id", "reserved0", "block_len", "links_nr", "next_cg_addr", "first_ch_addr", "acq_name_addr", "acq_source_addr", "first_sample_reduction_addr", "comment_addr", "record_id", "cycles_nr", "flags", "path_separator", "reserved1", "samples_byte_nr", "invalidation_bytes_nr", ) CHANNEL_GROUP_u: Callable[[Buffer], ChannelGroup] = struct.Struct(FMT_CHANNEL_GROUP).unpack CHANNEL_GROUP_uf: UnpackFrom[ChannelGroup] = struct.Struct(FMT_CHANNEL_GROUP).unpack_from CHANNEL_GROUP_p = struct.Struct(FMT_CHANNEL_GROUP).pack FMT_CHANNEL_GROUP_SHORT = "<8Q2H3I" ChannelGroupShort = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int] KEYS_CHANNEL_GROUP_SHORT = ( "next_cg_addr", "first_ch_addr", "acq_name_addr", "acq_source_addr", "first_sample_reduction_addr", "comment_addr", "record_id", "cycles_nr", "flags", "path_separator", "reserved1", "samples_byte_nr", "invalidation_bytes_nr", ) CHANNEL_GROUP_SHORT_u: Callable[[Buffer], ChannelGroupShort] = struct.Struct(FMT_CHANNEL_GROUP_SHORT).unpack CHANNEL_GROUP_SHORT_uf: UnpackFrom[ChannelGroupShort] = struct.Struct(FMT_CHANNEL_GROUP_SHORT).unpack_from CHANNEL_GROUP_SHORT_p = struct.Struct(FMT_CHANNEL_GROUP_SHORT).pack FMT_CHANNEL_GROUP_RM = "<4sI11Q2H3I" ChannelGroupRm = tuple[bytes, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int] KEYS_CHANNEL_GROUP_RM = ( "id", "reserved0", "block_len", "links_nr", "next_cg_addr", "first_ch_addr", "acq_name_addr", "acq_source_addr", "first_sample_reduction_addr", "comment_addr", "cg_master_addr", "record_id", "cycles_nr", "flags", "path_separator", "reserved1", "samples_byte_nr", "invalidation_bytes_nr", ) CHANNEL_GROUP_RM_u: Callable[[Buffer], ChannelGroupRm] = struct.Struct(FMT_CHANNEL_GROUP_RM).unpack CHANNEL_GROUP_RM_uf: UnpackFrom[ChannelGroupRm] = struct.Struct(FMT_CHANNEL_GROUP_RM).unpack_from CHANNEL_GROUP_RM_p = struct.Struct(FMT_CHANNEL_GROUP_RM).pack FMT_CHANNEL_GROUP_RM_SHORT = "<9Q2H3I" ChannelGroupRmShort = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int, int] KEYS_CHANNEL_GROUP_RM_SHORT = ( "next_cg_addr", "first_ch_addr", "acq_name_addr", "acq_source_addr", "first_sample_reduction_addr", "comment_addr", "cg_master_addr", "record_id", "cycles_nr", "flags", "path_separator", "reserved1", "samples_byte_nr", "invalidation_bytes_nr", ) CHANNEL_GROUP_RM_SHORT_u: Callable[[Buffer], ChannelGroupRmShort] = struct.Struct(FMT_CHANNEL_GROUP_RM_SHORT).unpack CHANNEL_GROUP_RM_SHORT_uf: UnpackFrom[ChannelGroupRmShort] = struct.Struct(FMT_CHANNEL_GROUP_RM_SHORT).unpack_from CHANNEL_GROUP_RM_SHORT_p = struct.Struct(FMT_CHANNEL_GROUP_RM_SHORT).pack FMT_DATA_BLOCK = "<4sI2Q{}s" KEYS_DATA_BLOCK = ("id", "reserved0", "block_len", "links_nr", "data") FMT_COMMON = "<4sI2Q" Common = tuple[bytes, int, int, int] COMMON_u: Callable[[Buffer], Common] = struct.Struct(FMT_COMMON).unpack COMMON_uf: UnpackFrom[Common] = struct.Struct(FMT_COMMON).unpack_from COMMON_p = struct.Struct(FMT_COMMON).pack FMT_COMMON_SHORT = "<4s4xQ" CommonShort = tuple[bytes, int] COMMON_SHORT_u: Callable[[Buffer], CommonShort] = struct.Struct(FMT_COMMON_SHORT).unpack COMMON_SHORT_uf: UnpackFrom[CommonShort] = struct.Struct(FMT_COMMON_SHORT).unpack_from COMMON_SHORT_p = struct.Struct(FMT_COMMON_SHORT).pack FMT_FILE_HISTORY = "<4sI5Q2hB3s" FileHistory = tuple[bytes, int, int, int, int, int, int, int, int, int, bytes] KEYS_FILE_HISTORY = ( "id", "reserved0", "block_len", "links_nr", "next_fh_addr", "comment_addr", "abs_time", "tz_offset", "daylight_save_time", "time_flags", "reserved1", ) FMT_DATA_GROUP = "<4sI6QB7s" DataGroup = tuple[bytes, int, int, int, int, int, int, int, int, bytes] KEYS_DATA_GROUP = ( "id", "reserved0", "block_len", "links_nr", "next_dg_addr", "first_cg_addr", "data_block_addr", "comment_addr", "record_id_len", "reserved1", ) DATA_GROUP_u: Callable[[Buffer], DataGroup] = struct.Struct(FMT_DATA_GROUP).unpack DATA_GROUP_uf: UnpackFrom[DataGroup] = struct.Struct(FMT_DATA_GROUP).unpack_from DATA_GROUP_p = struct.Struct(FMT_DATA_GROUP).pack FMT_DATA_EQUAL_LIST = "<4sI2Q{}QB3sIQ" FMT_DATA_LIST = "<4sI2Q{}QB3sI{}Q" FMT_CONVERSION_NONE = "<4sI6Q2B3H2d" KEYS_CONVERSION_NONE = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) CONVERSION_NONE_PACK = struct.Struct(FMT_CONVERSION_NONE).pack FMT_CONVERSION_NONE_INIT = "<4Q2B3H2d" ConversionNoneInit = tuple[int, int, int, int, int, int, int, int, int, float, float] CONVERSION_NONE_INIT_u: Callable[[Buffer], ConversionNoneInit] = struct.Struct(FMT_CONVERSION_NONE_INIT).unpack CONVERSION_NONE_INIT_uf: UnpackFrom[ConversionNoneInit] = struct.Struct(FMT_CONVERSION_NONE_INIT).unpack_from FMT_CONVERSION_LINEAR = FMT_CONVERSION_NONE + "2d" CONVERSION_LINEAR_PACK = struct.Struct(FMT_CONVERSION_LINEAR).pack KEYS_CONVERSION_LINEAR = (*KEYS_CONVERSION_NONE, "b", "a") FMT_CONVERSION_LINEAR_INIT = "<4Q2B3H4d" ConversionLinearInit = tuple[int, int, int, int, int, int, int, int, int, float, float, float, float] CONVERSION_LINEAR_INIT_u: Callable[[Buffer], ConversionLinearInit] = struct.Struct(FMT_CONVERSION_LINEAR_INIT).unpack CONVERSION_LINEAR_INIT_uf: UnpackFrom[ConversionLinearInit] = struct.Struct(FMT_CONVERSION_LINEAR_INIT).unpack_from FMT_CONVERSION_ALGEBRAIC = "<4sI7Q2B3H2d" CONVERSION_ALGEBRAIC_PACK = struct.Struct(FMT_CONVERSION_ALGEBRAIC).pack KEYS_CONVERSION_ALGEBRAIC = ( "id", "reserved0", "block_len", "links_nr", "name_addr", "unit_addr", "comment_addr", "inv_conv_addr", "formula_addr", "conversion_type", "precision", "flags", "ref_param_nr", "val_param_nr", "min_phy_value", "max_phy_value", ) FMT_CONVERSION_ALGEBRAIC_INIT = "<5Q2B3H2d" ConversionAlgebraicInit = tuple[int, int, int, int, int, int, int, int, int, int, float, float] FMT_CONVERSION_RAT = FMT_CONVERSION_NONE + "6d" CONVERSION_RAT_PACK = struct.Struct(FMT_CONVERSION_RAT).pack KEYS_CONVERSION_RAT = (*KEYS_CONVERSION_NONE, "P1", "P2", "P3", "P4", "P5", "P6") FMT_CONVERSION_RAT_INIT = "<4Q2B3H8d" ConversionRatInit = tuple[ int, int, int, int, int, int, int, int, int, float, float, float, float, float, float, float, float ] FMT_HEADER_BLOCK = "<4sI9Q2h4B2Q" HeaderBlock = tuple[bytes, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int] FMT_IDENTIFICATION_BLOCK = "<8s8s8s4sH30s2H" IdentificationBlock = tuple[bytes, bytes, bytes, bytes, int, bytes, int, int] KEYS_HEADER_BLOCK = ( "id", "reserved0", "block_len", "links_nr", "first_dg_addr", "file_history_addr", "channel_tree_addr", "first_attachment_addr", "first_event_addr", "comment_addr", "abs_time", "tz_offset", "daylight_save_time", "time_flags", "time_quality", "flags", "reserved1", "start_angle", "start_distance", ) KEYS_IDENTIFICATION_BLOCK = ( "file_identification", "version_str", "program_identification", "reserved0", "mdf_version", "reserved1", "unfinalized_standard_flags", "unfinalized_custom_flags", ) FMT_AT_COMMON = "<4sI6Q2HI16s2Q" AtCommon = tuple[bytes, int, int, int, int, int, int, int, int, int, int, bytes, int, int] KEYS_AT_BLOCK = ( "id", "reserved0", "block_len", "links_nr", "next_at_addr", "file_name_addr", "mime_addr", "comment_addr", "flags", "creator_index", "reserved1", "md5_sum", "original_size", "embedded_size", "embedded_data", ) AT_COMMON_u: Callable[[Buffer], AtCommon] = struct.Struct(FMT_AT_COMMON).unpack AT_COMMON_uf: UnpackFrom[AtCommon] = struct.Struct(FMT_AT_COMMON).unpack_from FMT_DZ_COMMON = "<4sI2Q2s2BI2Q" DzCommon = tuple[bytes, int, int, int, bytes, int, int, int, int, int] KEYS_DZ_BLOCK = ( "id", "reserved0", "block_len", "links_nr", "original_type", "zip_type", "reserved1", "param", "original_size", "zip_size", "data", ) DZ_COMMON_p = struct.Struct(FMT_DZ_COMMON).pack FMT_DZ_INFO_COMMON = "\d+)") CAN_DATA_FRAME_PATTERN = re.compile(r"(?i:CAN_DataFrame)_(?P\d+)") LIN_DATA_FRAME_PATTERN = re.compile(r"(?i:LIN_Frame)_(?P\d+)") CN_COMMENT_TEMPLATE = """ {} {} """ HD_COMMENT_TEMPLATE = """ {} {} {} {} {} """ CANOPEN_TIME_FIELDS = ("ms", "days") CANOPEN_DATE_FIELDS = ( "ms", "min", "hour", "day", "month", "year", "summer_time", "day_of_week", ) CAN_ERROR_TYPES = { 0: "Other/unknown error ", 1: "Bit Error", 2: "Form Error", 3: "Bit Stuffing Error", 4: "CRC Error", 5: "Acknowledgment Error", } for string in ( "CAN Frame", "Error Frame", "Remote Frame", "Unknown", "LIN Frame", "Checksum Error Frame", "Receive Error Frame", "Sync Error Frame", "Transmission Error Frame", "A", "B", "AB", ): sys.intern(string) for string in CAN_ERROR_TYPES.values(): sys.intern(string) for chn in range(20): sys.intern(f"CAN {chn}") sys.intern(f"LIN {chn}") sys.intern(f"FLX {chn}") for chk in range(256): sys.intern(f"Checksum 0x{chk:02X}") Version = Literal["4.00", "4.10", "4.11", "4.20"] asammdf-8.5.1/src/asammdf/gui/000077500000000000000000000000001502633300400161145ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/__init__.py000066400000000000000000000000001502633300400202130ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/dialogs/000077500000000000000000000000001502633300400175365ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/dialogs/__init__.py000066400000000000000000000000001502633300400216350ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/dialogs/advanced_search.py000066400000000000000000000475711502633300400232200ustar00rootroot00000000000000import os import re from traceback import format_exc from natsort import natsorted import numpy as np from PySide6 import QtCore, QtGui, QtWidgets from ...blocks.utils import extract_xml_comment from ..ui.search_dialog import Ui_SearchDialog from .messagebox import MessageBox from .range_editor import RangeEditor class AdvancedSearch(Ui_SearchDialog, QtWidgets.QDialog): NameColumn = 0 GroupColumn = 1 ChannelColumn = 2 UnitColumn = 3 SourceNameColumn = 4 SourcePathColumn = 5 CommentColumn = 6 columns = 7 def __init__( self, mdf, return_names=False, show_add_window=False, show_apply=False, show_pattern=True, apply_text="Apply", add_window_text="Add channels", show_search=True, window_title="Search & select channels", pattern=None, *args, **kwargs, ): channels_db = kwargs.pop("channels_db", {}) super().__init__(*args, **kwargs) self.setupUi(self) icon = QtGui.QIcon() icon.addFile(":/search.png", QtCore.QSize(), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.setWindowIcon(icon) self.selection.can_delete_items = True self.selection.all_texts = True self.result = {} self.add_window_request = False if mdf: self.channels_db = mdf.channels_db self.mdf = mdf else: self.mdf = None self.channels_db = channels_db self.apply_btn.clicked.connect(self._apply) self.add_btn.clicked.connect(self._add) self.add_window_btn.clicked.connect(self._add_window) self.cancel_btn.clicked.connect(self._cancel) self.search_box.editingFinished.connect(self.search_text_changed) self.match_kind.currentTextChanged.connect(self.search_box.textChanged.emit) self.matches.itemDoubleClicked.connect(self._match_double_clicked) self.selection.itemDoubleClicked.connect(self._selection_double_clicked) self.matches.header().sectionResized.connect(self.section_resized) self.selection.header().sectionResized.connect(self.section_resized) self.apply_pattern_btn.clicked.connect(self._apply_pattern) self.cancel_pattern_btn.clicked.connect(self._cancel_pattern) self.define_ranges_btn.clicked.connect(self._define_ranges) self.y_range_min.setMinimum(-np.inf) self.y_range_min.setMaximum(np.inf) self.y_range_min.setValue(0) self.y_range_max.setMinimum(-np.inf) self.y_range_max.setMaximum(np.inf) self.y_range_max.setValue(100) self.search_box.setFocus() self._return_names = return_names self.ranges = [] self.pattern_window = False self.apply_btn.setText(apply_text) self.add_window_btn.setText(add_window_text) self.selection.can_delete_items = True self.matches.can_delete_items = False if not show_add_window: self.add_window_btn.hide() if not show_apply: self.apply_btn.hide() if not show_pattern: self.tabs.removeTab(1) if not show_search: self.tabs.removeTab(0) if pattern: self.pattern.setText(pattern["pattern"]) self.filter_type.setCurrentText(pattern["filter_type"]) self.filter_value.setValue(pattern["filter_value"]) self.pattern_match_type.setCurrentText(pattern["match_type"]) if pattern.get("case_sensitive", False): self.case_sensitivity_pattern.setCurrentText("Case sensitive") else: self.case_sensitivity_pattern.setCurrentText("Case insensitive") self.raw.setCheckState(QtCore.Qt.CheckState.Checked if pattern["raw"] else QtCore.Qt.CheckState.Unchecked) self.name.setText(pattern["name"]) self.ranges = pattern["ranges"] self.integer_format.setCurrentText(pattern.get("integer_format", "phys")) y_range = sorted(pattern.get("y_range", (0, 100))) self.y_range_min.setValue(y_range[0]) self.y_range_max.setValue(y_range[1]) self.setWindowTitle(window_title) self.matches.setColumnWidth(self.NameColumn, 450) self.matches.setColumnWidth(self.GroupColumn, 40) self.matches.setColumnWidth(self.ChannelColumn, 40) self.matches.setColumnWidth(self.UnitColumn, 40) self.matches.setColumnWidth(self.SourceNameColumn, 170) self.matches.setColumnWidth(self.SourcePathColumn, 170) self.setWindowFlag(QtCore.Qt.WindowType.WindowMaximizeButtonHint, True) self.pattern.editingFinished.connect(self.update_pattern_matches) self.case_sensitivity_pattern.currentIndexChanged.connect(self.update_pattern_matches) self.pattern_match_type.currentIndexChanged.connect(self.update_pattern_matches) self.filter_type.currentIndexChanged.connect(self.update_pattern_matches) self.filter_value.valueChanged.connect(self.update_pattern_matches) self.raw.checkStateChanged.connect(self.update_pattern_matches) self.show_alias_btn.clicked.connect(self.show_overlapping_alias) self.update_pattern_matches() self.showMaximized() def search_text_changed(self): text = self.search_box.text().strip() extened_search = self.extended_search.checkState() == QtCore.Qt.CheckState.Checked if len(text) >= 2: self.matches.collapseAll() self.matches.clear() match_kind = self.match_kind.currentText() if match_kind == "Wildcard": wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" pattern = text.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") else: pattern = text try: if self.case_sensitivity.currentText() == "Case insensitive": pattern = re.compile(f"(?i){pattern}") else: pattern = re.compile(pattern) if extened_search: matches = {} for group_index, group in enumerate(self.mdf.groups): cg_source = getattr(group.channel_group, "acq_source", None) # check channel group source name if cg_source and ( pattern.fullmatch(cg_source.name or "") or pattern.fullmatch(cg_source.path or "") or pattern.fullmatch(cg_source.name or "") or pattern.fullmatch(cg_source.comment or "") or pattern.fullmatch(group.channel_group.name) or pattern.fullmatch(group.channel_group.comment) ): matches.update( { (group_index, channel_index): { "names": [ch.name], "comment": extract_xml_comment(ch.comment).strip(), "unit": (ch.conversion and ch.conversion.unit) or ch.unit, "source_name": cg_source.name, "source_path": cg_source.path, } for channel_index, ch in enumerate(group.channels) } ) else: for channel_index, ch in enumerate(group.channels): entry = group_index, channel_index source = ch.source targets = [ ch.name, *ch.display_names.values(), ] for target in targets: if pattern.fullmatch(target): if entry not in matches: matches[entry] = { "names": [target], "comment": extract_xml_comment(ch.comment).strip(), "unit": (ch.conversion and ch.conversion.unit) or ch.unit, "source_name": source.name if source else "", "source_path": source.path if source else "", } else: matches[entry]["name"].append(target) if entry not in matches: targets = [ch.unit, ch.comment] if source: targets.append(source.name) targets.append(source.path) for target in targets: if pattern.fullmatch(target): matches[entry] = { "names": [ch.name], "comment": extract_xml_comment(ch.comment).strip(), "unit": (ch.conversion and ch.conversion.unit) or ch.unit, "source_name": source.name if source else "", "source_path": source.path if source else "", } break else: found_names = [name for name in self.channels_db if pattern.fullmatch(name)] matches = {} for name in found_names: for entry in self.channels_db[name]: if entry not in matches: (group_index, channel_index) = entry ch = self.mdf.groups[group_index].channels[channel_index] cg = self.mdf.groups[group_index].channel_group source = ch.source or getattr(cg, "acq_source", None) matches[entry] = { "names": [], "comment": extract_xml_comment(ch.comment).strip(), "unit": (ch.conversion and ch.conversion.unit) or ch.unit, "source_name": source.name if source else "", "source_path": source.path if source else "", } info = matches[entry] if name == ch.name: info["names"].insert(0, name) else: info["names"].append(name) matches = [(group_index, channel_index, info) for (group_index, channel_index), info in matches.items()] matches.sort(key=lambda x: x[-1]["names"][0]) self.matches.clear() for group_index, channel_index, info in matches: names = info["names"] group_index, channel_index = str(group_index), str(channel_index) item = QtWidgets.QTreeWidgetItem( [ names[0], group_index, channel_index, info["unit"], info["source_name"], info["source_path"], info["comment"], ] ) self.matches.addTopLevelItem(item) children = [ QtWidgets.QTreeWidgetItem( [ name, group_index, channel_index, info["unit"], info["source_name"], info["source_path"], info["comment"], ] ) for name in names[1:] ] if children: item.addChildren(children) if matches: self.status.setText(f"{self.matches.topLevelItemCount()} results") else: self.status.setText("No results") self.matches.expandAll() except Exception as err: print(format_exc()) self.status.setText(str(err)) self.matches.setSortingEnabled(True) def _add(self, event): selection = set() iterator = QtWidgets.QTreeWidgetItemIterator(self.selection) while item := iterator.value(): data = tuple(item.text(i) for i in range(self.columns)) selection.add(data) iterator += 1 for item in self.matches.selectedItems(): data = tuple(item.text(i) for i in range(self.columns)) selection.add(data) selection = natsorted(selection) items = [QtWidgets.QTreeWidgetItem(texts) for texts in selection] self.selection.setSortingEnabled(False) self.selection.clear() self.selection.addTopLevelItems(items) self.selection.setSortingEnabled(True) def _apply(self, event=None): if self._return_names: self.result = set() iterator = QtWidgets.QTreeWidgetItemIterator(self.selection) while item := iterator.value(): self.result.add(item.text(self.NameColumn)) iterator += 1 else: self.result = {} iterator = QtWidgets.QTreeWidgetItemIterator(self.selection) while item := iterator.value(): entry = int(item.text(self.GroupColumn)), int(item.text(self.ChannelColumn)) name = item.text(self.NameColumn) self.result[entry] = name iterator += 1 self.accept() def _apply_pattern(self, event): self.result = { "pattern": self.pattern.text().strip(), "match_type": self.pattern_match_type.currentText(), "case_sensitive": self.case_sensitivity_pattern.currentText() == "Case sensitive", "filter_type": self.filter_type.currentText(), "filter_value": self.filter_value.value(), "raw": self.raw.checkState() == QtCore.Qt.CheckState.Checked, "ranges": self.ranges, "name": self.name.text().strip(), "integer_format": self.integer_format.currentText(), "y_range": sorted([self.y_range_min.value(), self.y_range_max.value()]), } if not self.result["pattern"]: MessageBox.warning(self, "Cannot apply pattern", "The pattern cannot be empty") return if not self.result["name"]: MessageBox.warning(self, "Cannot apply pattern", "The name cannot be empty") return self.pattern_window = True self.accept() def _add_window(self, event=None): self.add_window_request = True self._apply() def _cancel(self, event): self.result = {} self.reject() def _cancel_pattern(self, event): self.result = {} self.reject() def _define_ranges(self, event=None): name = self.pattern.text().strip() dlg = RangeEditor(f"Channel of <{name}>", ranges=self.ranges, parent=self) dlg.exec_() if dlg.pressed_button == "apply": self.ranges = dlg.result def _match_double_clicked(self, item): selection = set() new_item = item iterator = QtWidgets.QTreeWidgetItemIterator(self.selection) while item := iterator.value(): data = tuple(item.text(i) for i in range(self.columns)) selection.add(data) iterator += 1 new_data = tuple(new_item.text(i) for i in range(self.columns)) if new_data not in selection: selection.add(new_data) selection = natsorted(selection) items = [QtWidgets.QTreeWidgetItem(texts) for texts in selection] self.selection.clear() self.selection.addTopLevelItems(items) def _selection_double_clicked(self, item): root = self.selection.invisibleRootItem() (item.parent() or root).removeChild(item) @QtCore.Slot(int, int, int, result=None) def section_resized(self, index, old_size, new_size): if self.selection.columnWidth(index) != new_size: self.selection.setColumnWidth(index, new_size) if self.matches.columnWidth(index) != new_size: self.matches.setColumnWidth(index, new_size) def show_overlapping_alias( self, ): items = self.matches.selectedItems() or self.selection.selectedItems() if not items: return else: item = items[0] group_index, index = int(item.text(self.GroupColumn)), int(item.text(self.ChannelColumn)) try: channel = self.mdf.get_channel_metadata(group=group_index, index=index) info = (channel.data_type, channel.byte_offset, channel.bit_count) position = (group_index, index) alias = {} for gp_index, gp in enumerate(self.mdf.groups): for ch_index, ch in enumerate(gp.channels): if (gp_index, ch_index) != position and (ch.data_type, ch.byte_offset, ch.bit_count) == info: alias[ch.name] = (gp_index, ch_index) if alias: alias_text = "\n".join( f"{name} - group {gp_index} index {ch_index}" for name, (gp_index, ch_index) in alias.items() ) MessageBox.information( self, f"{channel.name} - other overlapping alias", f"{channel.name} has the following overlapping alias channels:\n\n{alias_text}", ) else: MessageBox.information( self, f"{channel.name} - no other overlapping alias", f"No other overlapping alias channels found for {channel.name}", ) except: print(format_exc()) def update_pattern_matches(self, *args): from ..widgets.mdi_area import extract_signals_using_pattern self.pattern_matches.clear() if not self.channels_db: return pattern_info = { "pattern": self.pattern.text().strip(), "case_sensitive": self.case_sensitivity_pattern.currentText() == "Case sensitive", "match_type": self.pattern_match_type.currentText(), "filter_value": self.filter_value.value(), "filter_type": self.filter_type.currentText(), "raw": self.raw.isChecked(), "integer_format": self.integer_format.currentText(), "ranges": [], } signals = extract_signals_using_pattern( mdf=self.mdf, channels_db=self.channels_db, pattern_info=pattern_info, ignore_value2text_conversions=True, as_names=True, ) items = [QtWidgets.QTreeWidgetItem([name]) for name in signals] self.pattern_matches.addTopLevelItems(items) asammdf-8.5.1/src/asammdf/gui/dialogs/advanced_search_helpers.py000066400000000000000000000027411502633300400247300ustar00rootroot00000000000000from PySide6 import QtCore, QtWidgets class SearchTreeItem(QtWidgets.QTreeWidgetItem): def __init__(self, name, group, index, unit, source_name, source_path, comment): super().__init__([name, group, index, unit, source_name, source_path, comment]) self.name = name self.group = group self.index = index self.unit = unit self.source_name = source_name self.source_path = source_path self.comment = comment def __del__(self): self.name = None self.group = None self.index = None self.unit = None self.source_name = None self.source_path = None self.comment = None class SearchTreeWidget(QtWidgets.QTreeWidget): def __init__(self, can_delete_items=False, *args, **kwargs): super().__init__(*args, **kwargs) self.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.NoDragDrop) self.setUniformRowHeights(True) self.can_delete_items = can_delete_items def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key.Key_Delete and self.can_delete_items: selected_items = self.selectedItems() root = self.invisibleRootItem() for item in selected_items: (item.parent() or root).removeChild(item) event.accept() else: super().keyPressEvent(event) asammdf-8.5.1/src/asammdf/gui/dialogs/bus_database_manager.py000066400000000000000000000045501502633300400242230ustar00rootroot00000000000000from PySide6 import QtCore, QtWidgets from ..widgets.bus_database_manager import BusDatabaseManager class BusDatabaseManagerDialog(QtWidgets.QDialog): def __init__( self, *args, **kwargs, ): super().__init__(*args, **kwargs) self.setObjectName("BusDatabaseManagerDialog") self.resize(404, 294) self.setSizeGripEnabled(True) self.setWindowFlags(QtCore.Qt.WindowType.Window) self.verticalLayout = QtWidgets.QVBoxLayout(self) self._settings = QtCore.QSettings() databases = {} can_databases = self._settings.value("can_databases", []) buses = can_databases[::2] dbs = can_databases[1::2] databases["CAN"] = list(zip(buses, dbs, strict=False)) lin_databases = self._settings.value("lin_databases", []) buses = lin_databases[::2] dbs = lin_databases[1::2] databases["LIN"] = list(zip(buses, dbs, strict=False)) self.widget = BusDatabaseManager(databases) self.verticalLayout.addWidget(self.widget) self.horLayout = QtWidgets.QHBoxLayout(self) spacer = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum ) self.apply_btn = QtWidgets.QPushButton("Apply") self.cancel_btn = QtWidgets.QPushButton("Cancel") self.horLayout.addSpacerItem(spacer) self.horLayout.addWidget(self.apply_btn) self.horLayout.addWidget(self.cancel_btn) self.verticalLayout.addLayout(self.horLayout) self.apply_btn.clicked.connect(self.apply) self.cancel_btn.clicked.connect(self.cancel) self.pressed_button = "cancel" self.setWindowTitle("Bus Database Manager") self.showMaximized() def apply(self, *args): self.pressed_button = "apply" self.close() def cancel(self, *args): self.pressed_button = "cancel" self.close() def store(self): databases = self.widget.to_config() dbs = [] for bus, database in databases["CAN"]: dbs.extend((bus, database)) self._settings.setValue("can_databases", dbs) dbs = [] for bus, database in databases["LIN"]: dbs.append(bus) dbs.append(database) self._settings.setValue("lin_databases", dbs) asammdf-8.5.1/src/asammdf/gui/dialogs/channel_group_info.py000066400000000000000000000014141502633300400237470ustar00rootroot00000000000000from PySide6 import QtCore, QtGui, QtWidgets from ..widgets.channel_group_info import ChannelGroupInfoWidget class ChannelGroupInfoDialog(QtWidgets.QDialog): def __init__(self, mdf, group, index, *args, **kwargs): super().__init__(*args, **kwargs) self.setWindowFlags(QtCore.Qt.WindowType.Window) layout = QtWidgets.QVBoxLayout() self.setLayout(layout) self.setWindowTitle(f"Channel group {index}") layout.addWidget(ChannelGroupInfoWidget(mdf, group, self)) self.setStyleSheet('font: 8pt "Consolas";}') icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.setWindowIcon(icon) self.setGeometry(240, 60, 1200, 600) asammdf-8.5.1/src/asammdf/gui/dialogs/channel_info.py000066400000000000000000000013361502633300400225360ustar00rootroot00000000000000from PySide6 import QtCore, QtGui, QtWidgets from ..widgets.channel_info import ChannelInfoWidget class ChannelInfoDialog(QtWidgets.QDialog): def __init__(self, channel, *args, **kwargs): super().__init__(*args, **kwargs) self.setWindowFlags(QtCore.Qt.WindowType.Window) layout = QtWidgets.QVBoxLayout() self.setLayout(layout) self.setWindowTitle(channel.name) layout.addWidget(ChannelInfoWidget(channel, self)) self.setStyleSheet('font: 8pt "Consolas";}') icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.setWindowIcon(icon) self.setGeometry(240, 60, 1200, 600) asammdf-8.5.1/src/asammdf/gui/dialogs/conversion_editor.py000066400000000000000000000356041502633300400236530ustar00rootroot00000000000000import numpy as np from PySide6 import QtCore, QtGui, QtWidgets from asammdf.blocks import v4_constants as v4c from asammdf.blocks.conversion_utils import from_dict from ..ui.define_conversion_dialog import Ui_ConversionDialog from .messagebox import MessageBox # from https://stackoverflow.com/a/53936965/11009349 def range_overlapping(x, y): if x.start == x.stop or y.start == y.stop: return False return x.start <= y.stop and y.start <= x.stop class ConversionEditor(Ui_ConversionDialog, QtWidgets.QDialog): def __init__(self, channel_name="", conversion=None, original_conversion=None, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.original_conversion = original_conversion self.vtt_default_conversion = None self.vrtt_default_conversion = None self.vtt_default_mode.currentIndexChanged.connect(self.vtt_mode.setCurrentIndex) self.vrtt_default_mode.currentIndexChanged.connect(self.vrtt_mode.setCurrentIndex) self.vtt_default_btn.clicked.connect(self.edit_vtt_default_conversion) self.vrtt_default_btn.clicked.connect(self.edit_vrtt_default_conversion) for widget in ( self.a, self.b, self.p1, self.p2, self.p3, self.p4, self.p5, self.p6, ): widget.setMaximum(np.inf) widget.setMinimum(-np.inf) self.load_conversion(conversion=conversion) self.insert_btn.clicked.connect(self.insert) self.insert_vrtt_btn.clicked.connect(self.insert_vrtt) self.reset_btn.clicked.connect(self.reset) self.reset_vrtt_btn.clicked.connect(self.reset_vrtt) self.apply_btn.clicked.connect(self.apply) self.cancel_btn.clicked.connect(self.cancel) self.load_original_conversion_btn.clicked.connect(self.load_conversion) self.vtt_list.setUniformItemSizes(True) self.vtt_list.setAlternatingRowColors(False) self.vrtt_list.setUniformItemSizes(True) self.vrtt_list.setAlternatingRowColors(False) self.setWindowTitle(f"Edit {channel_name} conversion") self.pressed_button = None self.setWindowFlag(QtCore.Qt.WindowType.WindowMinimizeButtonHint, True) self.setWindowFlag(QtCore.Qt.WindowType.WindowMaximizeButtonHint, True) def apply(self, event): if self.tabs.currentIndex() == 1: if (self.p4.value(), self.p5.value(), self.p6.value()) == (0, 0, 0): MessageBox.warning( self, "Invalid conversion parameters", "The rational conversion parameters P4, P5 and P6 cannot all be 0.", ) return elif self.tabs.currentIndex() == 2: mapping = set() for i in range(self.vtt_list.count()): item = self.vtt_list.item(i) if item is None: continue widget = self.vtt_list.itemWidget(item) value = int(widget.value.value()) if value in mapping: MessageBox.warning( self, "Invalid conversion parameters", f"The value-to-text conversion raw value {value} is defined multiple times.", ) return else: mapping.add(value) elif self.tabs.currentIndex() == 3: mapping = set() for i in range(self.vrtt_list.count()): item = self.vrtt_list.item(i) if item is None: continue widget = self.vrtt_list.itemWidget(item) lower = int(widget.lower.value()) upper = int(widget.upper.value()) if upper < lower: MessageBox.warning( self, "Invalid conversion parameters", f"The upper value must be greater or higher than the lower value. ({upper=} and {lower=}", ) return else: y = range(lower, upper) for x in mapping: if range_overlapping(x, y): MessageBox.warning( self, "Invalid conversion parameters", f"The ranges cannot overlap; {x} overlaps with {y}", ) return else: mapping.add(y) self.pressed_button = "apply" self.close() def cancel(self, event): self.pressed_button = "cancel" self.close() def conversion(self): if self.pressed_button in (None, "cancel"): conversion = None else: if self.tabs.currentIndex() == 0: conversion = { "name": self.name.text().strip(), "unit": self.unit.text().strip(), "comment": self.comment.toPlainText().strip(), "a": self.a.value(), "b": self.b.value(), } elif self.tabs.currentIndex() == 1: conversion = { "name": self.name.text().strip(), "unit": self.unit.text().strip(), "comment": self.comment.toPlainText().strip(), "P1": self.p1.value(), "P2": self.p2.value(), "P3": self.p3.value(), "P4": self.p4.value(), "P5": self.p5.value(), "P6": self.p6.value(), } elif self.tabs.currentIndex() == 2: conversion = { "name": self.name.text().strip(), "unit": self.unit.text().strip(), "comment": self.comment.toPlainText().strip(), } if self.vtt_default_mode.currentIndex() == 0: conversion["default"] = self.vtt_default.text().strip().encode("utf-8") else: conversion["default"] = self.vtt_default_conversion cntr = 0 for i in range(self.vtt_list.count()): item = self.vtt_list.item(i) if item is None: continue widget = self.vtt_list.itemWidget(item) value = int(widget.value.value()) text = widget.reference() conversion[f"val_{cntr}"] = value conversion[f"text_{cntr}"] = text cntr += 1 elif self.tabs.currentIndex() == 3: conversion = { "name": self.name.text().strip(), "unit": self.unit.text().strip(), "comment": self.comment.toPlainText().strip(), } if self.vrtt_default_mode.currentIndex() == 0: conversion["default"] = self.vrtt_default.text().strip().encode("utf-8") else: conversion["default"] = self.vrtt_default_conversion cntr = 0 for i in range(self.vrtt_list.count()): item = self.vrtt_list.item(i) if item is None: continue widget = self.vrtt_list.itemWidget(item) lower = int(widget.lower.value()) upper = int(widget.upper.value()) text = widget.reference() conversion[f"lower_{cntr}"] = lower conversion[f"upper_{cntr}"] = upper conversion[f"text_{cntr}"] = text cntr += 1 elif self.tabs.currentIndex() == 4: conversion = { "name": self.name.text().strip(), "unit": self.unit.text().strip(), "comment": self.comment.toPlainText().strip(), } conversion = from_dict(conversion) return conversion def edit_vtt_default_conversion(self): dlg = ConversionEditor("default", self.vtt_default_conversion, parent=self) dlg.exec_() if dlg.pressed_button == "apply": self.vtt_default_conversion = dlg.conversion() def edit_vrtt_default_conversion(self): dlg = ConversionEditor("default", self.vrtt_default_conversion, parent=self) dlg.exec_() if dlg.pressed_button == "apply": self.vrtt_default_conversion = dlg.conversion() def insert(self, event): count = self.vtt_list.count() if count: item = self.vtt_list.item(count - 1) last = self.vtt_list.itemWidget(item) value = last.value.value() + 1 else: value = 0 widget = VTTWidget(value=value) item = QtWidgets.QListWidgetItem() item.setSizeHint(widget.sizeHint()) self.vtt_list.addItem(item) self.vtt_list.setItemWidget(item, widget) def insert_vrtt(self, event): count = self.vrtt_list.count() if count: item = self.vrtt_list.item(count - 1) last = self.vrtt_list.itemWidget(item) lower = last.upper.value() upper = lower + 1 else: lower = 0 upper = 1 widget = VRTTWidget(lower=lower, upper=upper) item = QtWidgets.QListWidgetItem() item.setSizeHint(widget.sizeHint()) self.vrtt_list.addItem(item) self.vrtt_list.setItemWidget(item, widget) def load_conversion(self, *, conversion=None): conversion = conversion or self.original_conversion original_conversion_color = QtGui.QColor("#62b2e2") bar = self.tabs.tabBar() for i in range(self.tabs.count()): bar.setTabTextColor(i, QtGui.QColor()) if conversion is not None: self.name.setText(conversion["name"]) self.unit.setText(conversion["unit"]) self.comment.setPlainText(conversion["comment"]) if conversion["conversion_type"] == v4c.CONVERSION_TYPE_LIN: self.tabs.setCurrentIndex(0) bar.setTabTextColor(0, original_conversion_color) self.a.setValue(conversion["a"]) self.b.setValue(conversion["b"]) elif conversion["conversion_type"] == v4c.CONVERSION_TYPE_RAT: self.tabs.setCurrentIndex(1) bar.setTabTextColor(1, original_conversion_color) self.p1.setValue(conversion["P1"]) self.p2.setValue(conversion["P2"]) self.p3.setValue(conversion["P3"]) self.p4.setValue(conversion["P4"]) self.p5.setValue(conversion["P5"]) self.p6.setValue(conversion["P6"]) elif conversion["conversion_type"] == v4c.CONVERSION_TYPE_TABX: self.tabs.setCurrentIndex(2) bar.setTabTextColor(2, original_conversion_color) if isinstance(conversion.referenced_blocks["default_addr"], bytes): self.vtt_default_mode.setCurrentIndex(0) self.vtt_default.setText( conversion.referenced_blocks["default_addr"].decode("utf-8", errors="replace") ) else: self.vtt_default_mode.setCurrentIndex(1) self.vtt_default_conversion = conversion.referenced_blocks["default_addr"] for i in range(conversion.ref_param_nr - 1): if isinstance(conversion.referenced_blocks[f"text_{i}"], bytes): widget = VTTWidget( mode="text", value=conversion[f"val_{i}"], text=conversion.referenced_blocks[f"text_{i}"].decode("utf-8", errors="replace"), ) else: widget = VTTWidget( mode="conversion", value=conversion[f"val_{i}"], conversion=conversion.referenced_blocks[f"text_{i}"], ) item = QtWidgets.QListWidgetItem() item.setSizeHint(widget.sizeHint()) self.vtt_list.addItem(item) self.vtt_list.setItemWidget(item, widget) elif conversion["conversion_type"] == v4c.CONVERSION_TYPE_RTABX: self.tabs.setCurrentIndex(3) bar.setTabTextColor(3, original_conversion_color) if isinstance(conversion.referenced_blocks["default_addr"], bytes): self.vrtt_default_mode.setCurrentIndex(0) self.vrtt_default.setText( conversion.referenced_blocks["default_addr"].decode("utf-8", errors="replace") ) else: self.vrtt_default_mode.setCurrentIndex(1) self.vrtt_default_conversion = conversion.referenced_blocks["default_addr"] for i in range(conversion.ref_param_nr - 1): if isinstance(conversion.referenced_blocks[f"text_{i}"], bytes): widget = VRTTWidget( mode="text", lower=conversion[f"lower_{i}"], upper=conversion[f"upper_{i}"], text=conversion.referenced_blocks[f"text_{i}"].decode("utf-8", errors="replace"), ) else: widget = VRTTWidget( mode="conversion", lower=conversion[f"lower_{i}"], upper=conversion[f"upper_{i}"], conversion=conversion.referenced_blocks[f"text_{i}"], ) item = QtWidgets.QListWidgetItem() item.setSizeHint(widget.sizeHint()) self.vrtt_list.addItem(item) self.vrtt_list.setItemWidget(item, widget) elif conversion["conversion_type"] == v4c.CONVERSION_TYPE_NON: self.tabs.setCurrentIndex(4) bar.setTabTextColor(4, original_conversion_color) else: self.name.setText("") self.unit.setText("") self.comment.setPlainText("") self.tabs.setCurrentIndex(4) bar.setTabTextColor(4, original_conversion_color) def reset(self, event): self.vtt_list.clear() def reset_vrtt(self, event): self.vrtt_list.clear() from ..widgets.vrtt_widget import VRTTWidget from ..widgets.vtt_widget import VTTWidget asammdf-8.5.1/src/asammdf/gui/dialogs/define_channel.py000066400000000000000000000304471502633300400230420ustar00rootroot00000000000000from functools import partial import inspect import os import re from PySide6 import QtCore, QtGui, QtWidgets from ...signal import Signal from ..ui.define_channel_dialog import Ui_ComputedChannel from ..utils import ( computation_to_python_function, generate_python_function_globals, generate_python_variables, ) from ..widgets.python_highlighter import PythonHighlighter from .advanced_search import AdvancedSearch from .messagebox import MessageBox SIG_RE = re.compile(r"\{\{(?!\}\})(?P.*?)\}\}") class DefineChannel(Ui_ComputedChannel, QtWidgets.QDialog): def __init__( self, mdf, computation=None, origin_uuid=None, functions=None, global_variables=None, *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self.trigger_interval.setMinimum(1e-9) global_variables = global_variables or "" _in_globals = generate_python_function_globals() ret = generate_python_variables(global_variables, in_globals=_in_globals) self.global_variables = {name: val for name, val in _in_globals.items() if isinstance(val, (int, float))} self.setWindowFlags(QtCore.Qt.WindowType.WindowMinMaxButtonsHint | self.windowFlags()) self.mdf = mdf self.result = None self.pressed_button = None self.origin_uuid = origin_uuid or (mdf.uuid if mdf else os.urandom(6).hex()) self.arg_widgets = [] spacer = QtWidgets.QSpacerItem( 20, 20, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding ) self.arg_layout.addItem(spacer, len(self.arg_widgets) + 2, 0) self.arg_widgets.append(spacer) for widget in ( self.apply_btn, self.cancel_btn, ): widget.setDefault(False) widget.setAutoDefault(False) self._functions = functions or {} self.info = None self.signature = None self.functions.addItems(sorted(self._functions)) self.functions.setCurrentIndex(-1) self.functions.currentTextChanged.connect(self.function_changed) self.functions.currentIndexChanged.connect(self.function_changed) self.apply_btn.clicked.connect(self.apply) self.cancel_btn.clicked.connect(self.cancel) self.show_definition_btn.clicked.connect(self.show_definition) self.trigger_search_btn.clicked.connect(self.search) self.global_variable_timestamps_shift.currentTextChanged.connect( self.update_global_variable_timestamps_description ) self.computation = computation self.global_variable_timestamps_shift.addItems(sorted(self.global_variables)) if computation: computation = computation_to_python_function(computation) self.name.setText(computation.get("channel_name", computation.get("channel", ""))) self.unit.setText(computation.get("channel_unit", "")) self.comment.setPlainText(computation.get("channel_comment", "")) if computation["triggering"] == "triggering_on_all": self.triggering_on_all.setChecked(True) elif computation["triggering"] == "triggering_on_channel": self.triggering_on_channel.setChecked(True) self.trigger_channel.setText(computation["triggering_value"]) elif computation["triggering"] == "triggering_on_interval": self.triggering_on_interval.setChecked(True) self.trigger_interval.setValue(float(computation["triggering_value"])) if computation["function"] in self._functions: self.functions.setCurrentText(computation["function"]) for i, arg_name in enumerate(list(self.signature.parameters)[:-1]): names = computation["args"][arg_name] self.arg_widgets[i][1].insertPlainText("\n".join(names)) if computation.get("computation_mode", "sample_by_sample") == "sample_by_sample": self.sample_by_sample.setChecked(True) else: self.complete_signal.setChecked(True) if "time_stamps_shift" in computation: time_stamps_shift = computation["time_stamps_shift"] if time_stamps_shift["type"] == "fixed": self.shift_type_fixed.setChecked(True) else: self.shift_type_global.setChecked(True) self.fixed_timestamps_shift.setValue(time_stamps_shift["fixed_timestamps_shift"]) self.global_variable_timestamps_shift.setCurrentText( time_stamps_shift["global_variable_timestamps_shift"] ) self.showMaximized() def apply(self): if not self.functions.currentIndex() >= 0: return name = self.name.text().strip() or f"Function_{os.urandom(6).hex()}" if self.triggering_on_all.isChecked(): triggering = "triggering_on_all" triggering_value = "all" elif self.triggering_on_interval.isChecked(): triggering = "triggering_on_interval" triggering_value = self.trigger_interval.value() else: triggering = "triggering_on_channel" triggering_value = self.trigger_channel.text().strip() fargs = {} for i, (label, text_edit, button) in enumerate(self.arg_widgets[:-1]): names = text_edit.toPlainText().splitlines() names = [line.strip() for line in names if line.strip()] fargs[label.text()] = names self.result = { "type": "channel", "common_axis": False, "individual_axis": False, "enabled": True, "mode": "phys", "fmt": "{:.3f}", "format": "phys", "precision": 3, "flags": Signal.Flags.no_flags, "ranges": [], "unit": self.unit.text().strip(), "computed": True, "color": f"#{os.urandom(3).hex()}", "uuid": os.urandom(6).hex(), "origin_uuid": self.origin_uuid, "group_index": -1, "channel_index": -1, "name": name, "computation": { "args": fargs, "type": "python_function", "definition": "", "channel_name": name, "function": self.functions.currentText(), "channel_unit": self.unit.text().strip(), "channel_comment": self.comment.toPlainText().strip(), "triggering": triggering, "triggering_value": triggering_value, "computation_mode": "sample_by_sample" if self.sample_by_sample.isChecked() else "complete_signal", "time_stamps_shift": { "fixed_timestamps_shift": self.fixed_timestamps_shift.value(), "global_variable_timestamps_shift": self.global_variable_timestamps_shift.currentText() or "", "type": "fixed" if self.shift_type_fixed.isChecked() else "global", }, }, } self.pressed_button = "apply" self.close() def cancel(self, event): self.result = None self.pressed_button = "cancel" self.close() def function_changed(self, *args): name = self.functions.currentText() for widgets in self.arg_widgets[:-1]: for widget in widgets: self.arg_layout.removeWidget(widget) widget.setParent(None) widget.deleteLater() self.arg_layout.removeItem(self.arg_widgets[-1]) self.arg_widgets.clear() definition = self._functions[name] exec(definition.replace("\t", " ")) func = locals()[name] icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/search.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.signature = inspect.signature(func) parameters = list(self.signature.parameters)[:-1] for i, arg_name in enumerate(parameters, 2): label = QtWidgets.QLabel(arg_name) self.arg_layout.addWidget(label, i, 0) text_edit = QtWidgets.QPlainTextEdit() self.arg_layout.addWidget(text_edit, i, 1) button = QtWidgets.QPushButton("") button.setIcon(icon) button.clicked.connect(partial(self.search_argument, index=i - 2)) self.arg_layout.addWidget(button, i, 2) self.arg_widgets.append((label, text_edit, button)) spacer = QtWidgets.QSpacerItem( 20, 20, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding ) self.arg_layout.addItem(spacer, len(self.arg_widgets) + 2, 0) self.arg_widgets.append(spacer) def search_argument(self, *args, index=0): dlg = AdvancedSearch( self.mdf, show_add_window=False, show_apply=True, apply_text="Select channel", show_pattern=False, parent=self, return_names=True, ) dlg.setModal(True) dlg.exec_() result, pattern_window = dlg.result, dlg.pattern_window if result: lines = [self.arg_widgets[index][1].toPlainText(), *list(result)] self.arg_widgets[index][1].setPlainText("\n".join(lines)) def search(self, *args, text_widget=None): dlg = AdvancedSearch( self.mdf, show_add_window=False, show_apply=True, apply_text="Select channel", show_pattern=False, parent=self, return_names=True, ) dlg.setModal(True) dlg.exec_() result, pattern_window = dlg.result, dlg.pattern_window if result: self.trigger_channel.setText(list(result)[0]) def show_definition(self, *args): function = self.functions.currentText() if function: definition = self._functions[self.functions.currentText()] # keep a reference otherwise the window gets closed self.info = info = QtWidgets.QPlainTextEdit(definition) PythonHighlighter(info.document()) info.setReadOnly(True) info.setLineWrapMode(info.NoWrap) info.setWindowFlags(QtCore.Qt.WindowType.WindowMinMaxButtonsHint | info.windowFlags()) info.setWindowTitle(f"{function} definition") info.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) p = info.palette() for active in (QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorGroup.Inactive): p.setColor(active, QtGui.QPalette.ColorRole.Base, QtGui.QColor("#131314")) p.setColor(active, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor("#ffffff")) p.setColor(active, QtGui.QPalette.ColorRole.Text, QtGui.QColor("#ffffff")) info.setPalette(p) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) info.setWindowIcon(icon) info.show() rect = info.geometry() rect.setWidth(600) rect.setHeight(400) info.setGeometry(rect) else: if self.computation: function = self.computation["function"] MessageBox.warning( self, f"{function} definition missing", f"The function {function} was not found in the Functions manager", ) else: MessageBox.warning( self, "No function selected", "Please select one of the fucntion defined in the Functions manager", ) def update_global_variable_timestamps_description(self, text): if text: if text in self.global_variables: self.global_variable_timstamps_shift_description.setText(f"{text} = {self.global_variables[text]:.9f}s") else: self.global_variable_timstamps_shift_description.setText(f"{text} not found => default shift is 0s") else: self.global_variable_timstamps_shift_description.setText("default shift 0s") asammdf-8.5.1/src/asammdf/gui/dialogs/dependencies_dlg.py000066400000000000000000000157341502633300400233760ustar00rootroot00000000000000from collections import defaultdict import contextlib from importlib.metadata import distribution, PackageNotFoundError import re from packaging.requirements import Requirement from PySide6.QtCore import QSize from PySide6.QtGui import QGuiApplication, QIcon from PySide6.QtWidgets import ( QDialog, QPushButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, ) class DependenciesDlg(QDialog): def __init__(self, package_name: str, is_root_package: bool = True) -> None: """Create a dialog to list all dependencies for `package_name`.""" super().__init__() # Variables self._package_name = package_name self._is_root_package = is_root_package # Widgets self._tree = QTreeWidget() self._copy_btn = QPushButton("Copy installed dependencies to clipboard") # Setup widgets self._setup_widgets() # Setup layout self._setup_layout() # Signals and slots self._connect_signals() def _setup_widgets(self) -> None: self.setWindowTitle(f"Dependency Overview for {self._package_name}") self.setMinimumWidth(700) self.setMinimumHeight(500) icon = QIcon() icon.addFile(":/asammdf.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.setWindowIcon(icon) headers = ["package", "required", "installed", "summary", "url"] self._tree.setHeaderLabels(headers) self._populate_tree(self._package_name) self._tree.expandAll() self._tree.resizeColumnToContents(0) self._tree.resizeColumnToContents(1) self._tree.resizeColumnToContents(2) # enable copy button for root package only self._copy_btn.setVisible(self._is_root_package) def _setup_layout(self) -> None: vbox = QVBoxLayout() self.setLayout(vbox) vbox.addWidget(self._tree) vbox.addWidget(self._copy_btn) def _connect_signals(self) -> None: self._tree.itemDoubleClicked.connect(self._on_item_double_clicked) self._copy_btn.clicked.connect(self._on_copy_button_clicked) def _populate_tree(self, package_name: str) -> None: package_dist = distribution(package_name) requires = package_dist.requires if requires is None: return root_nodes: dict[str, QTreeWidgetItem] = {} def get_root_node(name: str | None = None) -> QTreeWidgetItem: if name is None: name = "mandatory" if name in root_nodes: return root_nodes[name] new_root_node = QTreeWidgetItem([name]) root_nodes[name] = new_root_node font = new_root_node.font(0) font.setBold(True) new_root_node.setFont(0, font) self._tree.invisibleRootItem().addChild(new_root_node) return new_root_node for group, requirements in grouped_dependencies(package_name).items(): for req_string in requirements: req = Requirement(req_string) parent_node = get_root_node(group) item = QTreeWidgetItem() item.setText(0, req.name) item.setText(1, str(req.specifier)) with contextlib.suppress(PackageNotFoundError): dist = distribution(req.name) item.setText(2, str(dist.version)) item.setText(3, dist.metadata["Summary"]) item.setText(4, dist.metadata["Home-Page"]) parent_node.addChild(item) def _on_item_double_clicked(self, item: QTreeWidgetItem, column: int) -> None: if column != 0: return if item.parent() is self._tree.invisibleRootItem(): return package_name = item.text(0) DependenciesDlg.show_dependencies(package_name, is_root_package=False) def _on_copy_button_clicked(self) -> None: """Create a list of all dependencies and their versions and write it to clipboard. """ lines: list[str] = [] dependencies = find_all_dependencies(self._package_name) max_name_length = max(len(name) for name in dependencies) header = f"{'Package':<{max_name_length}} Version" lines.append(header) lines.append("-" * len(header)) for name in sorted(dependencies): version = distribution(name).version lines.append(f"{name:<{max_name_length}} {version}") # write to clipboard QGuiApplication.clipboard().setText("\n".join(lines)) @staticmethod def show_dependencies(package_name: str, is_root_package: bool = True) -> None: dlg = DependenciesDlg(package_name, is_root_package) dlg.exec() def grouped_dependencies(package_name: str) -> dict[str, list[str]]: """Retrieve a dictionary grouping the dependencies of a given package into mandatory and optional categories. This function fetches the dependencies of the specified package and categorizes them into groups, such as 'mandatory' or any optional feature groups specified by `extra` markers. :param package_name: The name of the package to analyze. :return: A dictionary where keys are group names (e.g., 'mandatory', 'extra_feature') and values are lists of package names corresponding to those groups. """ dependencies: defaultdict[str, list[str]] = defaultdict(list) package_dist = distribution(package_name) if requires := package_dist.requires: for req_string in requires: req = Requirement(req_string) group = "mandatory" if match := re.search(r"extra\s*==\s*['\"](?P\S+)['\"]", str(req.marker)): group = match["extra"] dependencies[group].append(req_string) return dependencies def find_all_dependencies(package_name: str) -> set[str]: """Recursively find all dependencies of a given package, including transitive dependencies. This function determines all dependencies of the specified package, following any transitive dependencies (i.e., dependencies of dependencies) and returning a complete set of package names. :param package_name: The name of the package to analyze. :return: A set of all dependencies for the package, including transitive dependencies. """ def _flatten_groups(grouped_deps: dict[str, list[str]]) -> set[str]: _dep_set = set() for group, requirements in grouped_deps.items(): _dep_set |= {Requirement(req_string).name for req_string in requirements} return _dep_set dep_set: set[str] = {package_name} todo = _flatten_groups(grouped_dependencies(package_name)) while todo: req_name = todo.pop() if req_name in dep_set: continue try: todo |= _flatten_groups(grouped_dependencies(req_name)) except PackageNotFoundError: continue dep_set.add(req_name) return dep_set asammdf-8.5.1/src/asammdf/gui/dialogs/error_dialog.py000066400000000000000000000055671502633300400225750ustar00rootroot00000000000000import os from PySide6 import QtCore, QtGui, QtWidgets from ..ui.error_dialog import Ui_ErrorDialog class ErrorDialog(Ui_ErrorDialog, QtWidgets.QDialog): def __init__(self, title, message, trace, *args, **kwargs): remote = kwargs.pop("remote", False) timeout = kwargs.pop("timeout", int(os.environ.get("ASAMMDF_ERROR_DIALOG_TIMEOUT", "90"))) logger = kwargs.pop("logger", None) super().__init__(*args, **kwargs) self.setupUi(self) if logger is not None: logger.error(f">>> {title}\n{message}\n{trace}") print(trace) self.trace = QtWidgets.QTextEdit() families = QtGui.QFontDatabase.families() for family in ( "Consolas", "Liberation Mono", "DejaVu Sans Mono", "Droid Sans Mono", "Liberation Mono", "Roboto Mono", "Monaco", "Courier", ): if family in families: break font = QtGui.QFont(family) self.trace.setFont(font) self.layout.insertWidget(2, self.trace) self.trace.hide() self.trace.setText(trace) self.trace.setReadOnly(True) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/error.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.setWindowIcon(icon) self.setWindowTitle(title) self.error_message.setText(message) self.copy_to_clipboard_btn.clicked.connect(self.copy_to_clipboard) self.show_trace_btn.clicked.connect(self.show_trace) self.layout.setStretch(0, 0) self.layout.setStretch(1, 0) self.layout.setStretch(2, 1) self._timeout = timeout self.timer = QtCore.QTimer() self.timer.timeout.connect(self.count_down) if timeout > 0: self.status.setText(f"This window will be closed in {self._timeout}s\nAbort the countdown - [F1]") self.timer.start(1000) def copy_to_clipboard(self, event): text = f"Error: {self.error_message.text()}\n\nDetails: {self.trace.toPlainText()}" QtWidgets.QApplication.instance().clipboard().setText(text) def count_down(self): if self._timeout > 0: self._timeout -= 1 self.status.setText(f"This window will be closed in {self._timeout}s\nAbort the countdown - [F1]") else: self.close() def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key.Key_F1: self.timer.stop() self.status.clear() event.accept() else: super().keyPressEvent(event) def show_trace(self, event): if self.trace.isHidden(): self.trace.show() self.show_trace_btn.setText("Hide error trace") else: self.trace.hide() self.show_trace_btn.setText("Show error trace") asammdf-8.5.1/src/asammdf/gui/dialogs/functions_manager.py000066400000000000000000000071431502633300400236170ustar00rootroot00000000000000from copy import deepcopy import os from PySide6 import QtCore, QtWidgets from ..dialogs.messagebox import MessageBox from ..widgets.functions_manager import FunctionsManager class FunctionsManagerDialog(QtWidgets.QDialog): def __init__( self, definitions, channels=None, selected_definition="", prefix="", global_variables="", *args, **kwargs, ): definitions = definitions or {} definitions = { name: { "definition": definition, "uuid": os.urandom(6).hex(), } for name, definition in definitions.items() } self.original_definitions = {} self.modified_definitions = {} self.global_variables = "" for name, info in definitions.items(): self.original_definitions[info["uuid"]] = { "name": name, "definition": info["definition"], } super().__init__(*args, **kwargs) self.setObjectName("FunctionsManagerDialog") self.resize(404, 294) self.setSizeGripEnabled(True) self.setWindowFlags(QtCore.Qt.WindowType.Window) self.verticalLayout = QtWidgets.QVBoxLayout(self) self.widget = FunctionsManager(deepcopy(definitions), channels, selected_definition, global_variables) self.verticalLayout.addWidget(self.widget) self.horLayout = QtWidgets.QHBoxLayout(self) spacer = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum ) self.apply_btn = QtWidgets.QPushButton("Apply") self.cancel_btn = QtWidgets.QPushButton("Cancel") self.horLayout.addSpacerItem(spacer) self.horLayout.addWidget(self.apply_btn) self.horLayout.addWidget(self.cancel_btn) self.verticalLayout.addLayout(self.horLayout) self.apply_btn.clicked.connect(self.apply) self.cancel_btn.clicked.connect(self.cancel) self.pressed_button = "cancel" if prefix: self.setWindowTitle(f"{prefix} - Functions Manager") else: self.setWindowTitle("Functions Manager") def apply(self, *args): self.pressed_button = "apply" self.modified_definitions = {} self.widget.refresh_definitions() for name, info in self.widget.definitions.items(): if info["current_definition"] != info["definition"]: result = MessageBox.question( self, "Unsaved function definitions", "Do you want to review the functions before exporting them?" ) if result == MessageBox.StandardButton.No: break else: for row in range(self.widget.functions_list.count()): item = self.widget.functions_list.item(row) if item.text() == name: self.widget.functions_list.setCurrentRow(row) self.widget.functions_list.scrollToItem(item) break return for name, info in self.widget.definitions.items(): self.modified_definitions[info["uuid"]] = { "name": name, "definition": info["current_definition"], } self.global_variables = "\n".join( line for line in self.widget.globals_definition.toPlainText().splitlines() if line ) self.close() def cancel(self, *args): self.pressed_button = "cancel" self.close() asammdf-8.5.1/src/asammdf/gui/dialogs/gps_dialog.py000066400000000000000000000036421502633300400222250ustar00rootroot00000000000000from PySide6 import QtWidgets from ..ui.gps_dialog import Ui_GPSDialog from .advanced_search import AdvancedSearch class GPSDialog(Ui_GPSDialog, QtWidgets.QDialog): def __init__( self, mdf, latitude="", longitude="", *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self.mdf = mdf self.latitude.setText(latitude) self.longitude.setText(longitude) self.apply_btn.clicked.connect(self._apply) self.cancel_btn.clicked.connect(self._cancel) self.search_latitude_btn.clicked.connect(self.search_latitude) self.search_longitude_btn.clicked.connect(self.search_longitude) self.valid = False def _apply(self, event): if self.latitude.text().strip() and self.longitude.text().strip(): self.valid = True self.close() def _cancel(self, event): self.close() def search_latitude(self, *args): dlg = AdvancedSearch( self.mdf, show_add_window=False, show_apply=True, show_pattern=False, window_title="Search for the latitude channel", return_names=True, parent=self, ) dlg.setModal(True) dlg.exec_() result, pattern_window = dlg.result, dlg.pattern_window if result: self.latitude.setText(list(result)[0]) def search_longitude(self, *args): dlg = AdvancedSearch( self.mdf, show_add_window=False, show_apply=True, show_pattern=False, window_title="Search for the longitude channel", return_names=True, parent=self, ) dlg.setModal(True) dlg.exec_() result, pattern_window = dlg.result, dlg.pattern_window if result: self.longitude.setText(list(result)[0]) asammdf-8.5.1/src/asammdf/gui/dialogs/messagebox.py000066400000000000000000000224351502633300400222530ustar00rootroot00000000000000import os from PySide6 import QtCore, QtGui, QtWidgets DEFAULT_TIMEOUT = int(os.environ.get("ASAMMDF_ERROR_DIALOG_TIMEOUT", "60")) class MessageBox(QtWidgets.QMessageBox): def __init__(self, *args, **kwargs): self.timeout = kwargs.pop("timeout", DEFAULT_TIMEOUT) informative_text = kwargs.pop("informative_text", "") detailed_text = kwargs.pop("detailed_text", "") escapeButton = kwargs.pop("escapeButton", None) defaultButton = kwargs.pop("defaultButton", None) markdown = kwargs.pop("markdown", False) super().__init__(*args, **kwargs) self.label = label = self.findChild(QtWidgets.QLabel, "qt_msgbox_label") idx = self.layout().indexOf(label) position = self.layout().getItemPosition(idx) self.layout().removeWidget(label) layout = QtWidgets.QVBoxLayout() layout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetMinAndMaxSize) self.scroll_contents = scroll_contents = QtWidgets.QWidget() scroll_contents.setLayout(layout) self.scroll = scroll = QtWidgets.QScrollArea() scroll.setWidgetResizable(False) scroll.setWidget(scroll_contents) scroll.setFrameShape(QtWidgets.QFrame.Shape.NoFrame) layout.addWidget(label) self.layout().addWidget(scroll, *position) self.original_text = self.text() if markdown: self.setTextFormat(QtCore.Qt.TextFormat.MarkdownText) if defaultButton is not None: self.setDefaultButton(defaultButton) if self.defaultButton() is not None: if markdown: self.setText( f"""{self.original_text} * * * This message will be closed in {self.timeout}s * Default button - [{self.defaultButton().text().strip("&")}] * Abort the countdown - [F1]""" ) else: self.setText( f"{self.original_text}\n\nThis message will be closed in {self.timeout}s\n" f"Default button - [{self.defaultButton().text().strip('&')}]\n" "Abort the countdown - [F1]" ) else: if markdown: self.setText( f"""{self.original_text} * * * This message will be closed in {self.timeout}s * Abort the countdown - [F1]""" ) else: self.setText( f"{self.original_text}\n\nThis message will be closed in {self.timeout}s\n" "Abort the countdown - [F1]" ) if escapeButton is not None: self.setEscapeButton(escapeButton) self.show() if informative_text: self.setInformativeText(informative_text) if detailed_text: self.setDetailedText(detailed_text) self.scroll.setMinimumWidth(min(800, self.scroll_contents.width())) self.scroll.setMinimumHeight(min(800, self.scroll_contents.height())) rect = QtCore.QRect(0, 0, self.scroll_contents.width() + 70, self.scroll_contents.height() + 90) cursor = QtGui.QCursor() for screen in QtWidgets.QApplication.screens(): pos = cursor.pos(screen) screen_rect = screen.availableGeometry() if screen_rect.contains(pos): rect.moveCenter(screen_rect.center()) break else: screen_rect = screen.availableGeometry() rect.moveCenter(screen_rect.center()) self.setGeometry(rect) self.timer = QtCore.QTimer() self.timer.timeout.connect(self.tick) self.timer.start(1000) def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key.Key_F1: self.timer.stop() self.setText(self.original_text) event.accept() else: super().keyPressEvent(event) def tick(self): self.timeout -= 1 default = self.defaultButton() if self.timeout <= 0: self.timer.stop() if default is not None: default.animateClick() else: self.done(0) else: if self.defaultButton() is not None: if self.textFormat() == QtCore.Qt.TextFormat.MarkdownText: self.setText( f"""{self.original_text} * * * This message will be closed in {self.timeout}s * Default button - [{self.defaultButton().text().strip("&")}] * Abort the countdown - [F1]""" ) else: self.setText( f"{self.original_text}\n\nThis message will be closed in {self.timeout}s\n" f"Default button - [{self.defaultButton().text().strip('&')}]\n" "Abort the countdown - [F1]" ) else: if self.textFormat() == QtCore.Qt.TextFormat.MarkdownText: self.setText( f"""{self.original_text} * * * This message will be closed in {self.timeout}s * Abort the countdown - [F1]""" ) else: self.setText( f"{self.original_text}\n\nThis message will be closed in {self.timeout}s\n" "Abort the countdown - [F1]" ) @classmethod def about( cls, parent, title, text, buttons=QtWidgets.QMessageBox.StandardButton.Ok, defaultButton=QtWidgets.QMessageBox.StandardButton.Ok, escapeButton=QtWidgets.QMessageBox.StandardButton.Ok, timeout=DEFAULT_TIMEOUT, markdown=False, informative_text="", detailed_text="", ): msg = cls( QtWidgets.QMessageBox.Icon.NoIcon, title, text, buttons, parent, timeout=timeout, defaultButton=defaultButton, escapeButton=escapeButton, markdown=markdown, informative_text=informative_text, detailed_text=detailed_text, ) return msg.exec() @classmethod def critical( cls, parent, title, text, buttons=QtWidgets.QMessageBox.StandardButton.Ok, defaultButton=QtWidgets.QMessageBox.StandardButton.Ok, escapeButton=QtWidgets.QMessageBox.StandardButton.Ok, timeout=DEFAULT_TIMEOUT, markdown=False, informative_text="", detailed_text="", ): msg = cls( QtWidgets.QMessageBox.Icon.Critical, title, text, buttons, parent, timeout=timeout, defaultButton=defaultButton, escapeButton=escapeButton, markdown=markdown, informative_text=informative_text, detailed_text=detailed_text, ) return msg.exec() @classmethod def information( cls, parent, title, text, buttons=QtWidgets.QMessageBox.StandardButton.Ok, defaultButton=QtWidgets.QMessageBox.StandardButton.Ok, escapeButton=QtWidgets.QMessageBox.StandardButton.Ok, timeout=DEFAULT_TIMEOUT, markdown=False, informative_text="", detailed_text="", ): msg = cls( QtWidgets.QMessageBox.Icon.Information, title, text, buttons, parent, timeout=timeout, defaultButton=defaultButton, escapeButton=escapeButton, markdown=markdown, informative_text=informative_text, detailed_text=detailed_text, ) return msg.exec() @classmethod def question( cls, parent, title, text, buttons=QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No, defaultButton=QtWidgets.QMessageBox.StandardButton.No, escapeButton=QtWidgets.QMessageBox.StandardButton.No, timeout=DEFAULT_TIMEOUT, markdown=False, informative_text="", detailed_text="", ): msg = cls( QtWidgets.QMessageBox.Icon.Question, title, text, buttons, parent, timeout=timeout, defaultButton=defaultButton, escapeButton=escapeButton, markdown=markdown, informative_text=informative_text, detailed_text=detailed_text, ) return msg.exec() @classmethod def warning( cls, parent, title, text, buttons=QtWidgets.QMessageBox.StandardButton.Ok, defaultButton=QtWidgets.QMessageBox.StandardButton.Ok, escapeButton=QtWidgets.QMessageBox.StandardButton.Ok, timeout=DEFAULT_TIMEOUT, markdown=False, informative_text="", detailed_text="", ): msg = cls( QtWidgets.QMessageBox.Icon.Warning, title, text, buttons, parent, timeout=timeout, defaultButton=defaultButton, escapeButton=escapeButton, markdown=markdown, informative_text=informative_text, detailed_text=detailed_text, ) return msg.exec() asammdf-8.5.1/src/asammdf/gui/dialogs/multi_search.py000066400000000000000000000076441502633300400226020ustar00rootroot00000000000000import os import re from textwrap import wrap from natsort import natsorted from PySide6 import QtCore, QtWidgets from ..ui.multi_search_dialog import Ui_MultiSearchDialog from .messagebox import MessageBox class MultiSearch(Ui_MultiSearchDialog, QtWidgets.QDialog): def __init__(self, measurements, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.setWindowFlags( self.windowFlags() | QtCore.Qt.WindowType.WindowSystemMenuHint | QtCore.Qt.WindowType.WindowMinMaxButtonsHint ) for widget in ( self.apply_btn, self.cancel_btn, self.add_btn, self.show_measurement_list_btn, ): widget.setDefault(False) widget.setAutoDefault(False) self.result = set() self.measurements = measurements self.matches.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection) self.apply_btn.clicked.connect(self._apply) self.add_btn.clicked.connect(self._add) self.cancel_btn.clicked.connect(self._cancel) self.show_measurement_list_btn.clicked.connect(self.show_measurement_list) self.search_box.editingFinished.connect(self.search_text_changed) self.search_box.setFocus() self.match_kind.currentTextChanged.connect(self.search_box.textChanged.emit) self.setWindowTitle("Search & select channels") def search_text_changed(self): text = self.search_box.text().strip() case_sensitive = self.case_sensitivity.currentText() == "Case sensitive" if len(text) >= 2: if self.match_kind.currentText() == "Wildcard": wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" pattern = text.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") else: pattern = text self.matches.clear() results = [] try: if case_sensitive: pattern = re.compile(pattern) else: pattern = re.compile(f"(?i){pattern}") for mdf in self.measurements: match_results = [f"{mdf.uuid}:\t{name}" for name in mdf.channels_db if pattern.fullmatch(name)] results.extend(match_results) except Exception as err: self.status.setText(str(err)) else: if results: self.status.setText("") self.matches.addItems(results) else: self.status.setText("No match found") self.add_btn.setFocus() def _add(self, event): count = self.selection.count() names = {self.selection.item(i).text() for i in range(count)} to_add = {item.text() for item in self.matches.selectedItems()} names = names | to_add names = natsorted(names) self.selection.clear() self.selection.addItems(names) self.add_btn.setFocus() def _apply(self, event): count = self.selection.count() self.result = set() for i in range(count): text = self.selection.item(i).text() uuid, channel_name = text.split(":\t") for mdf in self.measurements: if mdf.uuid == uuid: for entry in mdf.channels_db[channel_name]: self.result.add((uuid, entry, channel_name)) self.close() def _cancel(self, event): self.result = set() self.close() def show_measurement_list(self, event): info = [] for mdf in self.measurements: info.extend(wrap(f"{mdf.uuid}:\t{mdf.original_name}", 120)) MessageBox.information(self, "Measurement files used for comparison", "\n".join(info)) asammdf-8.5.1/src/asammdf/gui/dialogs/range_editor.py000066400000000000000000000044031502633300400225530ustar00rootroot00000000000000from PySide6 import QtCore, QtWidgets from ..ui.range_editor_dialog import Ui_RangeDialog from ..widgets.range_widget import RangeWidget class RangeEditor(Ui_RangeDialog, QtWidgets.QDialog): def __init__(self, name, unit="", ranges=None, brush=False, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.setWindowFlags( self.windowFlags() | QtCore.Qt.WindowType.WindowSystemMenuHint | QtCore.Qt.WindowType.WindowMinMaxButtonsHint ) self.name = name self.unit = unit self.result = [] self.pressed_button = None self._brush = brush if ranges: for range_info in ranges: widget = RangeWidget( parent=self, name=self.name, brush=brush, **range_info, ) item = QtWidgets.QListWidgetItem() item.setSizeHint(widget.sizeHint()) self.ranges.addItem(item) self.ranges.setItemWidget(item, widget) self.ranges.setUniformItemSizes(True) self.apply_btn.clicked.connect(self.apply) self.insert_btn.clicked.connect(self.insert) self.cancel_btn.clicked.connect(self.cancel) self.reset_btn.clicked.connect(self.reset) self.setWindowTitle(f"Edit {self.name} range colors") self.show() def apply(self, event): ranges = [] count = self.ranges.count() for i in range(count): item = self.ranges.item(i) if item is None: continue widget = self.ranges.itemWidget(item) ranges.append(widget.to_dict(brush=self._brush)) self.result = ranges self.pressed_button = "apply" self.close() def insert(self, event): widget = RangeWidget(self.name) item = QtWidgets.QListWidgetItem() item.setSizeHint(widget.sizeHint()) self.ranges.addItem(item) self.ranges.setItemWidget(item, widget) def reset(self, event): self.ranges.clear() self.result = [] def cancel(self, event): self.result = [] self.pressed_button = "cancel" self.close() asammdf-8.5.1/src/asammdf/gui/dialogs/simple_search.py000066400000000000000000000103341502633300400227270ustar00rootroot00000000000000import os import re import sys from traceback import format_exc from natsort import natsorted from PySide6 import QtWidgets from asammdf.gui.utils import excepthook from ..ui.simple_search_dialog import Ui_SimpleSearchDialog sys.excepthook = excepthook class SimpleSearch(Ui_SimpleSearchDialog, QtWidgets.QDialog): def __init__(self, channels_db, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.result = set() self.channels_db = channels_db self.apply_btn.clicked.connect(self._apply) self.add_btn.clicked.connect(self._add) self.cancel_btn.clicked.connect(self._cancel) self.search_box.editingFinished.connect(self.search_text_changed) self.match_kind.currentTextChanged.connect(self.search_box.textChanged.emit) self.matches.itemDoubleClicked.connect(self._match_double_clicked) self.matches.itemSelectionChanged.connect(self.show_match_comment) self.selection.itemDoubleClicked.connect(self._selection_double_clicked) self.setWindowTitle("Search channels") self.search_box.setFocus() def show_match_comment(self, items=None): items = self.matches.selectedItems() if items: item = items[0] comment = self.channels_db[item.text(0)] self.comment.setText(comment) else: self.comment.setText("") def _match_double_clicked(self, new_item): selection = set() iterator = QtWidgets.QTreeWidgetItemIterator(self.selection) while item := iterator.value(): selection.add(item.text(0)) iterator += 1 if new_item.text(0) not in selection: selection.add(new_item.text(0)) selection = natsorted(selection) items = [QtWidgets.QTreeWidgetItem([name]) for name in selection] self.selection.clear() self.selection.addTopLevelItems(items) def _selection_double_clicked(self, item): root = self.selection.invisibleRootItem() (item.parent() or root).removeChild(item) def search_text_changed(self): self.comment.setText("") text = self.search_box.text().strip() if len(text) >= 2: if self.match_kind.currentText() == "Wildcard": wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" pattern = text.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") else: pattern = text try: if self.case_sensitivity.currentText() == "Case insensitive": pattern = re.compile(f"(?i){pattern}") else: pattern = re.compile(pattern) matches = [] for name in self.channels_db: if pattern.fullmatch(name): matches.append(name) items = [QtWidgets.QTreeWidgetItem([name]) for name in matches] self.matches.clear() self.matches.addTopLevelItems(items) if items: self.status.setText("") else: self.status.setText("No match found") self.matches.setFocus() except: self.status.setText(format_exc()) self.matches.clear() def _add(self, event): items = set() iterator = QtWidgets.QTreeWidgetItemIterator(self.selection) while item := iterator.value(): items.add(item.text(0)) iterator += 1 for item in self.matches.selectedItems(): items.add(item.text(0)) items = natsorted(items) items = [QtWidgets.QTreeWidgetItem([name]) for name in items] self.selection.clear() self.selection.addTopLevelItems(items) def _apply(self, event): self.result = set() iterator = QtWidgets.QTreeWidgetItemIterator(self.selection) while item := iterator.value(): self.result.add(item.text(0)) iterator += 1 self.close() def _cancel(self, event): self.result = set() self.close() asammdf-8.5.1/src/asammdf/gui/dialogs/window_selection_dialog.py000066400000000000000000000017521502633300400250100ustar00rootroot00000000000000from PySide6 import QtWidgets from ..ui.windows_selection_dialog import Ui_WindowSelectionDialog class WindowSelectionDialog(Ui_WindowSelectionDialog, QtWidgets.QDialog): def __init__(self, options=("Plot", "Numeric", "Tabular"), default=None, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) for i, name in enumerate(options): radio = QtWidgets.QRadioButton(name) self.selection_layout.addWidget(radio) if default is None: if i == 0: radio.setChecked(True) else: if name == default: radio.setChecked(True) def selected_type(self): for i in range(self.selection_layout.count()): radio = self.selection_layout.itemAt(i).widget() if radio.isChecked(): return radio.text() return "" def disable_new_channels(self): return self.disable_channels.isChecked() asammdf-8.5.1/src/asammdf/gui/plot.py000066400000000000000000000034301502633300400174440ustar00rootroot00000000000000import logging from ..blocks.utils import plausible_timestamps from ..signal import Signal try: from PySide6 import QtWidgets from .widgets.plot_standalone import PlotWindow QT = True except ImportError: QT = False logger = logging.getLogger("asammdf") def plot(signals: Signal | list[Signal], title: str = "", validate: bool = True) -> None: """Create a stand-alone plot using the input signal or signals. Arguments --------- signals : iterable | Signal Signals to plot. title : str, default '' Window title. validate : bool, default True Consider the invalidation bits. """ if QT: app = QtWidgets.QApplication([]) app.setOrganizationName("py-asammdf") app.setOrganizationDomain("py-asammdf") app.setApplicationName("py-asammdf") if validate: if isinstance(signals, (tuple, list)): signals = [signal.validate() for signal in signals] else: signals = [signals.validate()] for signal in signals: all_ok, idx = plausible_timestamps(signal.timestamps, -1e6, 1e9) if not all_ok: signal.samples = signal.samples[idx] signal.timestamps = signal.timestamps[idx] main = PlotWindow({sig.name: sig for sig in signals}) if title.strip(): main.setWindowTitle(title.strip()) else: if isinstance(signals, (tuple, list)): main.setWindowTitle(", ".join(sig.name for sig in signals)) else: main.setWindowTitle(signals.name) app.setStyle(QtWidgets.QStyleFactory.create("Fusion")) app.exec_() else: raise Exception("Signal plotting requires pyqtgraph or matplotlib") asammdf-8.5.1/src/asammdf/gui/serde.py000066400000000000000000000617121502633300400175770ustar00rootroot00000000000000from collections.abc import Collection from copy import deepcopy import json from pathlib import Path import re from traceback import format_exc import typing from typing import Final, Literal, Union import lxml.etree from pyqtgraph import functions as fn from PySide6 import QtCore, QtGui from typing_extensions import NotRequired, TypedDict from asammdf.blocks import v4_constants as v4c from asammdf.blocks.utils import SignalFlags C_FUNCTION: Final = re.compile(r"\s+(?P\S+)\s*\(\s*struct\s+DATA\s+\*data\s*\)") COLOR_MAPS: Final = { "Accent": ["#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b16", "#666666"], "Dark2": ["#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666"], "Paired": [ "#a6cee3", "#1f78b4", "#b2df8a", "#33a02c", "#fb9a99", "#e31a1c", "#fdbf6f", "#ff7f00", "#cab2d6", "#6a3d9a", "#ffff99", "#b15928", ], "Pastel1": ["#fbb4ae", "#b3cde3", "#ccebc5", "#decbe4", "#fed9a6", "#ffffcc", "#e5d8bd", "#fddaec", "#f2f2f2"], "Pastel2": ["#b3e2cd", "#fdcdac", "#cbd5e8", "#f4cae4", "#e6f5c9", "#fff2ae", "#f1e2cc", "#cccccc"], "Set1": ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", "#a65628", "#f781bf", "#999999"], "Set2": ["#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3"], "Set3": [ "#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f", ], "tab10": [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf", ], "tab20": [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5", ], "tab20b": [ "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6", ], "tab20c": [ "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9", ], } COLORS: Final = COLOR_MAPS["tab10"] COLORS_COUNT: Final = len(COLORS) COMPARISON_NAME: Final = re.compile(r"(\s*\d+:)?(?P.+)") class _ChannelBaseDict(TypedDict): color: str comment: str | None common_axis: bool enabled: bool flags: int fmt: str individual_axis: bool name: str origin_uuid: str precision: int ranges: list[dict[str, object]] type: Literal["channel"] unit: str class _ChannelNotComputedDict(_ChannelBaseDict): computed: Literal[False] conversion: NotRequired[dict[str, object]] mode: Literal["phys"] y_range: list[float] class _ChannelComputedDict(_ChannelBaseDict): computed: Literal[True] computation: dict[str, object] conversion: object user_defined_name: str | None _ChannelDict = _ChannelComputedDict | _ChannelNotComputedDict class _ChannelGroupDict(TypedDict): channels: list[Union["_ChannelGroupDict", _ChannelDict]] enabled: bool name: str | None origin_uuid: str pattern: dict[str, object] | None ranges: list[dict[str, object]] type: Literal["group"] def extract_mime_names(data: QtCore.QMimeData, disable_new_channels: bool | None = None) -> list[str]: def fix_comparison_name( data: list[_ChannelGroupDict | _ChannelDict], disable_new_channels: bool | None = None ) -> None: for item in data: if item["type"] == "channel": if disable_new_channels is not None: item["enabled"] = not disable_new_channels if ( item["group_index"], # type: ignore[typeddict-item] item["channel_index"], # type: ignore[typeddict-item] ) != (-1, -1): match = COMPARISON_NAME.match(item["name"]) if match is None: raise RuntimeError(f"cannot parse '{item['name']}'") name = match.group("name").strip() item["name"] = name else: if disable_new_channels is not None: item["enabled"] = not disable_new_channels fix_comparison_name(item["channels"], disable_new_channels=disable_new_channels) names: list[str] = [] if data.hasFormat("application/octet-stream-asammdf"): data_data = data.data("application/octet-stream-asammdf").data() data_bytes = data_data.tobytes() if isinstance(data_data, memoryview) else data_data text = data_bytes.decode("utf-8") obj = json.loads(text, cls=ExtendedJsonDecoder) fix_comparison_name(obj, disable_new_channels=disable_new_channels) names = obj return names def set_mime_enable(mime: list[_ChannelGroupDict | _ChannelDict], enable: bool) -> None: for item in mime: if item["type"] == "channel": item["enabled"] = enable else: set_mime_enable(item["channels"], enable) def flatten_dsp(channels: list[_ChannelGroupDict | _ChannelDict]) -> list[str]: res: list[str] = [] for item in channels: if item["type"] == "group": res.extend(flatten_dsp(item["channels"])) else: res.append(item["name"]) return res def load_dsp( file: Path, background: str = "#000000", flat: bool = False, colors_as_string: bool = False ) -> dict[str, object] | list[str]: if not colors_as_string and isinstance(background, str): background = fn.mkColor(background) def parse_conversions(display: lxml.etree._Element | None) -> dict[str | None, dict[str, object]]: conversions: dict[str | None, dict[str, object]] = {} if display is None: return conversions for item in display.findall("COMPU_METHOD"): try: name = item.get("name") conv: dict[str, object] = { "name": name, "comment": item.get("description"), "unit": item.get("unit"), } conversion_type = int(item.attrib["cnv_type"]) match conversion_type: case 0: conv["conversion_type"] = v4c.CONVERSION_TYPE_LIN coeffs = item.find("COEFFS_LINIAR") if coeffs is None: raise RuntimeError("cannot find 'COEFFS_LINIAR' element") conv["a"] = float(coeffs.attrib["P1"]) conv["b"] = float(coeffs.attrib["P2"]) case 9: conv["conversion_type"] = v4c.CONVERSION_TYPE_RAT coeffs = item.find("COEFFS") if coeffs is None: raise RuntimeError("cannot find 'COEFFS' element") for i in range(1, 7): conv[f"P{i}"] = float(coeffs.attrib[f"P{i}"]) case 11: conv["conversion_type"] = v4c.CONVERSION_TYPE_TABX vtab = item.find("COMPU_VTAB") if vtab is not None: for i, item in enumerate(vtab.findall("tab")): conv[f"val_{i}"] = float(item.attrib["min"]) text = item.get("text") if isinstance(text, bytes): text = text.decode("utf-8", errors="replace") conv[f"text_{i}"] = text case 12: conv["conversion_type"] = v4c.CONVERSION_TYPE_RTABX vtab = item.find("COMPU_VTAB_RANGE") if vtab is not None: text = vtab.get("default") if isinstance(text, bytes): text = text.decode("utf-8", errors="replace") conv["default_addr"] = vtab.get("default") for i, item in enumerate(vtab.findall("tab_range")): conv[f"upper_{i}"] = float(item.attrib["max"]) conv[f"lower_{i}"] = float(item.attrib["min"]) text = item.get("text") if isinstance(text, bytes): text = text.decode("utf-8", errors="replace") conv[f"text_{i}"] = text case _: continue conversions[name] = conv except: print(format_exc()) continue return conversions def parse_channels( display: lxml.etree._Element, conversions: dict[str | None, dict[str, object]] ) -> list[_ChannelGroupDict | _ChannelDict]: channels: list[_ChannelGroupDict | _ChannelDict] = [] for elem in display.iterchildren(): if elem.tag == "CHANNEL": channel_name = elem.attrib["name"] or "unnamed" comment_elem = elem.find("COMMENT") if comment_elem is not None: comment = elem.get("text") else: comment = "" color_ = int(elem.attrib["color"]) c = 0 for i in range(3): c = c << 8 c += color_ & 0xFF color_ = color_ >> 8 ch_color = c gain = abs(float(elem.attrib["gain"])) offset = float(elem.attrib["offset"]) / 100 multi_color = elem.find("MULTI_COLOR") ranges: list[dict[str, object]] = [] if multi_color is not None: for color in multi_color.findall("color"): some_elem = color.find("min") if some_elem is None: raise RuntimeError("cannot find element 'min'") min_ = float(some_elem.attrib["data"]) some_elem = color.find("max") if some_elem is None: raise RuntimeError("cannot find element 'max'") max_ = float(some_elem.attrib["data"]) some_elem = color.find("color") if some_elem is None: raise RuntimeError("cannot find element 'color'") color_ = int(some_elem.attrib["data"]) c = 0 for i in range(3): c = c << 8 c += color_ & 0xFF color_ = color_ >> 8 font_color = f"#{c:06X}" if colors_as_string else fn.mkColor(f"#{c:06X}") ranges.append( { "background_color": background, "font_color": font_color, "op1": "<=", "op2": "<=", "value1": min_, "value2": max_, } ) chan: _ChannelNotComputedDict = { "color": f"#{ch_color:06X}", "common_axis": False, "computed": False, "flags": 0, "comment": comment, "enabled": elem.get("on") == "1" and elem.get("trc_fmt") != "2", "fmt": "{}", "individual_axis": False, "name": channel_name, "mode": "phys", "precision": 3, "ranges": ranges, "unit": "", "type": "channel", "y_range": sorted( [ -gain * offset, -gain * offset + 19 * gain, ] ), "origin_uuid": "000000000000", } conv_name = elem.get("cnv_name") if conv_name in conversions: chan["conversion"] = deepcopy(conversions[conv_name]) channels.append(chan) elif str(elem.tag).startswith("GROUP"): channels.append( { "name": elem.get("data") or "unnamed", "enabled": elem.get("on") == "1", "type": "group", "channels": parse_channels(elem, conversions=conversions), "pattern": None, "origin_uuid": "000000000000", "ranges": [], } ) elif elem.tag == "CHANNEL_PATTERN": try: filter_type = elem.get("filter_type") filter_value: float if filter_type in ("None", None): filter_type = "Unspecified" filter_value = 0 raw = False else: filter_value = float(elem.attrib["filter_value"]) raw = bool(int(elem.attrib["filter_use_raw"])) info: dict[str, object] = { "pattern": elem.get("name_pattern"), "name": elem.get("name_pattern") or "unnamed", "match_type": "Wildcard", "filter_type": filter_type, "filter_value": filter_value, "raw": raw, } multi_color = elem.find("MULTI_COLOR") ranges = [] if multi_color is not None: for color in multi_color.findall("color"): some_elem = color.find("min") if some_elem is None: raise RuntimeError("cannot find element 'min'") min_ = float(some_elem.attrib["data"]) some_elem = color.find("max") if some_elem is None: raise RuntimeError("cannot find element 'max'") max_ = float(some_elem.attrib["data"]) some_elem = color.find("color") if some_elem is None: raise RuntimeError("cannot find element 'color'") color_ = int(some_elem.attrib["data"]) c = 0 for i in range(3): c = c << 8 c += color_ & 0xFF color_ = color_ >> 8 font_color = f"#{c:06X}" if colors_as_string else fn.mkColor(f"#{c:06X}") ranges.append( { "background_color": background, "font_color": font_color, "op1": "<=", "op2": "<=", "value1": min_, "value2": max_, } ) info["ranges"] = ranges channels.append( { "channels": [], "enabled": True, "name": typing.cast(str, info["pattern"]), "pattern": info, "type": "group", "ranges": [], "origin_uuid": "000000000000", } ) except: print(format_exc()) continue return channels def parse_virtual_channels(display: lxml.etree._Element | None) -> dict[str | None, dict[str, object]]: channels: dict[str | None, dict[str, object]] = {} if display is None: return channels for item in display.findall("V_CHAN"): try: virtual_channel: dict[str, object] = {} parent = item.find("VIR_TIME_CHAN") vtab = item.find("COMPU_VTAB") if parent is None or vtab is None: continue name = item.get("name") virtual_channel["name"] = name virtual_channel["parent"] = parent.attrib["data"] elem = item.find("description") if elem is None: raise RuntimeError("cannot find element 'description'") virtual_channel["comment"] = elem.attrib["data"] conv: dict[str, object] = {} for i, item in enumerate(vtab.findall("tab")): conv[f"val_{i}"] = float(item.attrib["min"]) text = item.get("text") if isinstance(text, bytes): text = text.decode("utf-8", errors="replace") conv[f"text_{i}"] = text virtual_channel["vtab"] = conv channels[name] = virtual_channel except: continue return channels def parse_c_functions(display: lxml.etree._Element | None) -> Collection[str]: c_functions: set[str] = set() if display is None: return c_functions for item in display.findall("CALC_FUNC"): string = item.text if string is None: raise RuntimeError("element text is None") for match in C_FUNCTION.finditer(string): c_functions.add(match.group("function")) return sorted(c_functions) dsp = lxml.etree.fromstring(Path(file).read_bytes().replace(b"\0", b""), parser=lxml.etree.XMLParser(recover=True)) conversions = parse_conversions(dsp.find("COMPU_METHODS")) elem = dsp.find("DISPLAY_INFO") if elem is None: raise RuntimeError("cannot find element 'DISPLAY_INFO'") channels = parse_channels(elem, conversions) c_functions = parse_c_functions(dsp) functions: dict[str, object] = {} virtual_channels: list[_ChannelGroupDict | _ChannelDict] = [] for i, ch in enumerate(parse_virtual_channels(dsp.find("VIRTUAL_CHANNEL")).values()): virtual_channels.append( { "color": COLORS[i % len(COLORS)], "common_axis": False, "computed": True, "computation": { "args": {"arg1": []}, "type": "python_function", "channel_comment": ch["comment"], "channel_name": ch["name"], "channel_unit": "", "function": f"f_{ch['name']}", "triggering": "triggering_on_all", "triggering_value": "all", }, "flags": int(SignalFlags.computed | SignalFlags.user_defined_conversion), "enabled": True, "fmt": "{}", "individual_axis": False, "name": typing.cast(str, ch["parent"]), "precision": 3, "ranges": [], "unit": "", "conversion": ch["vtab"], "user_defined_name": typing.cast(str | None, ch["name"]), "comment": f"Datalyser virtual channel: {ch['comment']}", "origin_uuid": "000000000000", "type": "channel", } ) functions[f"f_{ch['name']}"] = f"def f_{ch['name']}(arg1=0, t=0):\n return arg1" if virtual_channels: channels.append( { "name": "Datalyser Virtual Channels", "enabled": False, "type": "group", "channels": virtual_channels, "pattern": None, "origin_uuid": "000000000000", "ranges": [], } ) windows: list[dict[str, object]] = [] info: dict[str, object] | list[str] = { "selected_channels": [], "windows": windows, "has_virtual_channels": bool(virtual_channels), "c_functions": c_functions, "functions": functions, } if flat: info = flatten_dsp(channels) else: plot: dict[str, object] = { "type": "Plot", "title": "Display channels", "maximized": True, "minimized": False, "configuration": { "channels": channels, "locked": True, "pattern": {}, }, } windows.append(plot) return info class ExtendedJsonDecoder(json.JSONDecoder): def __init__(self, **kwargs): kwargs["object_hook"] = self.object_hook super().__init__(**kwargs) def object_hook(self, obj): for key in ("color", "background_color", "font_color"): if key in obj: obj[key] = fn.mkColor(obj[key]) return obj class ExtendedJsonEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, QtGui.QBrush): return obj.color().name() elif isinstance(obj, QtGui.QColor): return obj.name() else: return super().default(obj) def load_lab(file: Path) -> dict[str, list[str]]: sections: dict[str, list[str]] = {} with open(file) as lab: for line in lab: line = line.strip() if not line: continue if line.startswith("[") and line.endswith("]"): section_name = line.strip("[]") s: list[str] = [] sections[section_name] = s else: if "s" in locals(): s.append(line) return {name: channels for name, channels in sections.items() if channels if name != "SETTINGS"} def load_channel_names_from_file(file_name: str, lab_section: str = "") -> list[str]: file_path = Path(file_name) channels: Collection[str] extension = file_path.suffix.lower() match extension: case ".dsp": channels = load_dsp(file_path, flat=True) case ".dspf": with open(file_path) as infile: info = json.load(infile, cls=ExtendedJsonDecoder) channels = [] for window in info["windows"]: if window["type"] == "Plot": channels.extend(flatten_dsp(window["configuration"]["channels"])) elif window["type"] == "Numeric": channels.extend([item["name"] for item in window["configuration"]["channels"]]) elif window["type"] == "Tabular": channels.extend(window["configuration"]["channels"]) case ".lab": info = load_lab(file_path) if info: if len(info) > 1 and lab_section: channels = info[lab_section] else: channels = list(info.values())[0] channels = [name.split(";")[0] for name in channels] case ".cfg": with open(file_path) as infile: info = json.load(infile, cls=ExtendedJsonDecoder) channels = info.get("selected_channels", []) case ".txt": try: with open(file_path) as infile: info = json.load(infile, cls=ExtendedJsonDecoder) channels = info.get("selected_channels", []) except: with open(file_path) as infile: channels = [line.strip() for line in infile.readlines()] channels = [name for name in channels if name] return sorted(set(channels)) asammdf-8.5.1/src/asammdf/gui/ui/000077500000000000000000000000001502633300400165315ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/ui/__init__.py000066400000000000000000000000001502633300400206300ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/ui/attachment.py000066400000000000000000000054131502633300400212360ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'attachment.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QHBoxLayout, QHeaderView, QLabel, QPushButton, QSizePolicy, QTreeWidget, QTreeWidgetItem, QWidget) from . import resource_rc class Ui_Attachment(object): def setupUi(self, Attachment): if not Attachment.objectName(): Attachment.setObjectName(u"Attachment") Attachment.resize(717, 205) self.horizontalLayout = QHBoxLayout(Attachment) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.number = QLabel(Attachment) self.number.setObjectName(u"number") self.horizontalLayout.addWidget(self.number) self.fields = QTreeWidget(Attachment) self.fields.setObjectName(u"fields") self.fields.setMinimumSize(QSize(0, 187)) self.fields.header().setVisible(True) self.fields.header().setMinimumSectionSize(100) self.horizontalLayout.addWidget(self.fields) self.extract_btn = QPushButton(Attachment) self.extract_btn.setObjectName(u"extract_btn") icon = QIcon() icon.addFile(u":/export.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.extract_btn.setIcon(icon) self.horizontalLayout.addWidget(self.extract_btn) self.horizontalLayout.setStretch(1, 1) self.retranslateUi(Attachment) QMetaObject.connectSlotsByName(Attachment) # setupUi def retranslateUi(self, Attachment): Attachment.setWindowTitle(QCoreApplication.translate("Attachment", u"Form", None)) self.number.setText(QCoreApplication.translate("Attachment", u"Number", None)) ___qtreewidgetitem = self.fields.headerItem() ___qtreewidgetitem.setText(1, QCoreApplication.translate("Attachment", u"Value", None)); ___qtreewidgetitem.setText(0, QCoreApplication.translate("Attachment", u"Item", None)); self.extract_btn.setText(QCoreApplication.translate("Attachment", u"Extract", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/attachment.ui000066400000000000000000000035611502633300400212250ustar00rootroot00000000000000 Attachment 0 0 717 205 Form 1 1 1 1 1 Number 0 187 true 100 Item Value Extract :/export.png:/export.png asammdf-8.5.1/src/asammdf/gui/ui/bar.py000066400000000000000000000060751502633300400176570ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'bar.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QDoubleSpinBox, QHBoxLayout, QLabel, QListWidgetItem, QSizePolicy, QSlider, QVBoxLayout, QWidget) from asammdf.gui.widgets.list import MinimalListWidget from . import resource_rc class Ui_BarDisplay(object): def setupUi(self, BarDisplay): if not BarDisplay.objectName(): BarDisplay.setObjectName(u"BarDisplay") BarDisplay.resize(480, 666) self.verticalLayout = QVBoxLayout(BarDisplay) self.verticalLayout.setObjectName(u"verticalLayout") self.channels = MinimalListWidget(BarDisplay) self.channels.setObjectName(u"channels") self.verticalLayout.addWidget(self.channels) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.timestamp = QDoubleSpinBox(BarDisplay) self.timestamp.setObjectName(u"timestamp") self.timestamp.setDecimals(9) self.timestamp.setSingleStep(0.001000000000000) self.horizontalLayout_2.addWidget(self.timestamp) self.min_t = QLabel(BarDisplay) self.min_t.setObjectName(u"min_t") self.horizontalLayout_2.addWidget(self.min_t) self.timestamp_slider = QSlider(BarDisplay) self.timestamp_slider.setObjectName(u"timestamp_slider") self.timestamp_slider.setMaximum(99999) self.timestamp_slider.setOrientation(Qt.Horizontal) self.timestamp_slider.setInvertedAppearance(False) self.timestamp_slider.setInvertedControls(False) self.timestamp_slider.setTickPosition(QSlider.NoTicks) self.timestamp_slider.setTickInterval(1) self.horizontalLayout_2.addWidget(self.timestamp_slider) self.max_t = QLabel(BarDisplay) self.max_t.setObjectName(u"max_t") self.horizontalLayout_2.addWidget(self.max_t) self.horizontalLayout_2.setStretch(2, 1) self.verticalLayout.addLayout(self.horizontalLayout_2) self.retranslateUi(BarDisplay) QMetaObject.connectSlotsByName(BarDisplay) # setupUi def retranslateUi(self, BarDisplay): BarDisplay.setWindowTitle(QCoreApplication.translate("BarDisplay", u"Form", None)) self.timestamp.setSuffix(QCoreApplication.translate("BarDisplay", u"s", None)) self.min_t.setText("") self.max_t.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/bar.ui000066400000000000000000000041741502633300400176420ustar00rootroot00000000000000 BarDisplay 0 0 480 666 Form s 9 0.001000000000000 99999 Qt::Horizontal false false QSlider::NoTicks 1 MinimalListWidget QListWidget

asammdf/gui/widgets/list.h
asammdf-8.5.1/src/asammdf/gui/ui/batch_widget.py000066400000000000000000001677231502633300400215470ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'batch_widget.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QDoubleSpinBox, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QListView, QListWidget, QListWidgetItem, QPushButton, QRadioButton, QScrollArea, QSizePolicy, QSpacerItem, QSplitter, QStackedWidget, QTabWidget, QTextEdit, QTreeWidgetItem, QVBoxLayout, QWidget) from asammdf.gui.widgets.list import MinimalListWidget from asammdf.gui.widgets.tree import TreeWidget from . import resource_rc class Ui_batch_widget(object): def setupUi(self, batch_widget): if not batch_widget.objectName(): batch_widget.setObjectName(u"batch_widget") batch_widget.resize(828, 718) self.gridLayout_9 = QGridLayout(batch_widget) self.gridLayout_9.setSpacing(1) self.gridLayout_9.setObjectName(u"gridLayout_9") self.gridLayout_9.setContentsMargins(1, 1, 1, 1) self.splitter = QSplitter(batch_widget) self.splitter.setObjectName(u"splitter") self.splitter.setOrientation(Qt.Orientation.Horizontal) self.aspects = QTabWidget(self.splitter) self.aspects.setObjectName(u"aspects") self.aspects.setTabPosition(QTabWidget.TabPosition.West) self.aspects.setDocumentMode(False) self.concatenate_tab = QWidget() self.concatenate_tab.setObjectName(u"concatenate_tab") self.gridLayout_7 = QGridLayout(self.concatenate_tab) self.gridLayout_7.setSpacing(1) self.gridLayout_7.setObjectName(u"gridLayout_7") self.gridLayout_7.setContentsMargins(1, 1, 1, 1) self.concatenate_sync = QCheckBox(self.concatenate_tab) self.concatenate_sync.setObjectName(u"concatenate_sync") self.concatenate_sync.setChecked(True) self.gridLayout_7.addWidget(self.concatenate_sync, 0, 0, 1, 2) self.concatenate_add_samples_origin = QCheckBox(self.concatenate_tab) self.concatenate_add_samples_origin.setObjectName(u"concatenate_add_samples_origin") self.concatenate_add_samples_origin.setChecked(True) self.gridLayout_7.addWidget(self.concatenate_add_samples_origin, 1, 0, 1, 2) self.label_11 = QLabel(self.concatenate_tab) self.label_11.setObjectName(u"label_11") self.gridLayout_7.addWidget(self.label_11, 2, 0, 1, 1) self.concatenate_format = QComboBox(self.concatenate_tab) self.concatenate_format.setObjectName(u"concatenate_format") self.gridLayout_7.addWidget(self.concatenate_format, 2, 1, 1, 1) self.line_5 = QFrame(self.concatenate_tab) self.line_5.setObjectName(u"line_5") self.line_5.setFrameShape(QFrame.Shape.HLine) self.line_5.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_7.addWidget(self.line_5, 3, 0, 1, 2) self.label_12 = QLabel(self.concatenate_tab) self.label_12.setObjectName(u"label_12") self.gridLayout_7.addWidget(self.label_12, 4, 0, 1, 1) self.concatenate_compression = QComboBox(self.concatenate_tab) self.concatenate_compression.setObjectName(u"concatenate_compression") self.gridLayout_7.addWidget(self.concatenate_compression, 4, 1, 1, 1) self.concatenate_split = QCheckBox(self.concatenate_tab) self.concatenate_split.setObjectName(u"concatenate_split") self.concatenate_split.setChecked(True) self.gridLayout_7.addWidget(self.concatenate_split, 5, 0, 1, 1) self.line_6 = QFrame(self.concatenate_tab) self.line_6.setObjectName(u"line_6") self.line_6.setFrameShape(QFrame.Shape.HLine) self.line_6.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_7.addWidget(self.line_6, 7, 0, 1, 2) self.concatenate_split_size = QDoubleSpinBox(self.concatenate_tab) self.concatenate_split_size.setObjectName(u"concatenate_split_size") self.concatenate_split_size.setMaximum(4.000000000000000) self.gridLayout_7.addWidget(self.concatenate_split_size, 6, 1, 1, 1) self.label_10 = QLabel(self.concatenate_tab) self.label_10.setObjectName(u"label_10") self.gridLayout_7.addWidget(self.label_10, 6, 0, 1, 1) self.concatenate_btn = QPushButton(self.concatenate_tab) self.concatenate_btn.setObjectName(u"concatenate_btn") icon = QIcon() icon.addFile(u":/plus.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.concatenate_btn.setIcon(icon) self.gridLayout_7.addWidget(self.concatenate_btn, 9, 1, 1, 1) self.verticalSpacer_4 = QSpacerItem(20, 2, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_7.addItem(self.verticalSpacer_4, 8, 1, 1, 1) self.gridLayout_7.setColumnStretch(1, 1) self.aspects.addTab(self.concatenate_tab, icon, "") self.convert_tab = QWidget() self.convert_tab.setObjectName(u"convert_tab") self.verticalLayout_5 = QVBoxLayout(self.convert_tab) self.verticalLayout_5.setSpacing(1) self.verticalLayout_5.setObjectName(u"verticalLayout_5") self.verticalLayout_5.setContentsMargins(1, 1, 1, 1) self.scrollArea_3 = QScrollArea(self.convert_tab) self.scrollArea_3.setObjectName(u"scrollArea_3") self.scrollArea_3.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 517, 706)) self.horizontalLayout_2 = QHBoxLayout(self.scrollAreaWidgetContents_3) self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.horizontalLayout_2.setContentsMargins(1, 1, 1, 1) self.verticalLayout_14 = QVBoxLayout() self.verticalLayout_14.setSpacing(1) self.verticalLayout_14.setObjectName(u"verticalLayout_14") self.filter_view = QComboBox(self.scrollAreaWidgetContents_3) self.filter_view.addItem("") self.filter_view.addItem("") self.filter_view.addItem("") self.filter_view.setObjectName(u"filter_view") self.verticalLayout_14.addWidget(self.filter_view) self.filter_tree = TreeWidget(self.scrollAreaWidgetContents_3) self.filter_tree.setObjectName(u"filter_tree") self.verticalLayout_14.addWidget(self.filter_tree) self.horizontalLayout_5 = QHBoxLayout() self.horizontalLayout_5.setSpacing(1) self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") self.load_filter_list_btn = QPushButton(self.scrollAreaWidgetContents_3) self.load_filter_list_btn.setObjectName(u"load_filter_list_btn") icon1 = QIcon() icon1.addFile(u":/open.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.load_filter_list_btn.setIcon(icon1) self.horizontalLayout_5.addWidget(self.load_filter_list_btn) self.save_filter_list_btn = QPushButton(self.scrollAreaWidgetContents_3) self.save_filter_list_btn.setObjectName(u"save_filter_list_btn") icon2 = QIcon() icon2.addFile(u":/save.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.save_filter_list_btn.setIcon(icon2) self.horizontalLayout_5.addWidget(self.save_filter_list_btn) self.clear_filter_btn = QPushButton(self.scrollAreaWidgetContents_3) self.clear_filter_btn.setObjectName(u"clear_filter_btn") icon3 = QIcon() icon3.addFile(u":/erase.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.clear_filter_btn.setIcon(icon3) self.horizontalLayout_5.addWidget(self.clear_filter_btn) self.advanced_serch_filter_btn = QPushButton(self.scrollAreaWidgetContents_3) self.advanced_serch_filter_btn.setObjectName(u"advanced_serch_filter_btn") icon4 = QIcon() icon4.addFile(u":/search.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.advanced_serch_filter_btn.setIcon(icon4) self.horizontalLayout_5.addWidget(self.advanced_serch_filter_btn) self.horizontalSpacer_5 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_5.addItem(self.horizontalSpacer_5) self.verticalLayout_14.addLayout(self.horizontalLayout_5) self.horizontalLayout_2.addLayout(self.verticalLayout_14) self.verticalLayout_13 = QVBoxLayout() self.verticalLayout_13.setSpacing(1) self.verticalLayout_13.setObjectName(u"verticalLayout_13") self.label_3 = QLabel(self.scrollAreaWidgetContents_3) self.label_3.setObjectName(u"label_3") self.verticalLayout_13.addWidget(self.label_3) self.selected_filter_channels = QListWidget(self.scrollAreaWidgetContents_3) self.selected_filter_channels.setObjectName(u"selected_filter_channels") self.selected_filter_channels.setViewMode(QListView.ViewMode.ListMode) self.selected_filter_channels.setUniformItemSizes(True) self.selected_filter_channels.setSortingEnabled(True) self.verticalLayout_13.addWidget(self.selected_filter_channels) self.horizontalLayout_2.addLayout(self.verticalLayout_13) self.verticalLayout_15 = QVBoxLayout() self.verticalLayout_15.setSpacing(1) self.verticalLayout_15.setObjectName(u"verticalLayout_15") self.verticalLayout_15.setContentsMargins(1, 1, 1, 1) self.cut_group = QGroupBox(self.scrollAreaWidgetContents_3) self.cut_group.setObjectName(u"cut_group") self.cut_group.setCheckable(True) self.cut_group.setChecked(False) self.gridLayout_23 = QGridLayout(self.cut_group) self.gridLayout_23.setSpacing(1) self.gridLayout_23.setObjectName(u"gridLayout_23") self.gridLayout_23.setContentsMargins(1, 1, 1, 1) self.label_62 = QLabel(self.cut_group) self.label_62.setObjectName(u"label_62") self.gridLayout_23.addWidget(self.label_62, 0, 0, 1, 1) self.cut_stop = QDoubleSpinBox(self.cut_group) self.cut_stop.setObjectName(u"cut_stop") self.cut_stop.setDecimals(6) self.cut_stop.setMaximum(999999.999998999992386) self.gridLayout_23.addWidget(self.cut_stop, 1, 1, 1, 1) self.label_63 = QLabel(self.cut_group) self.label_63.setObjectName(u"label_63") self.gridLayout_23.addWidget(self.label_63, 1, 0, 1, 1) self.cut_start = QDoubleSpinBox(self.cut_group) self.cut_start.setObjectName(u"cut_start") self.cut_start.setDecimals(6) self.cut_start.setMaximum(999999.999998999992386) self.gridLayout_23.addWidget(self.cut_start, 0, 1, 1, 1) self.whence = QCheckBox(self.cut_group) self.whence.setObjectName(u"whence") self.gridLayout_23.addWidget(self.whence, 3, 0, 1, 2) self.cut_time_from_zero = QCheckBox(self.cut_group) self.cut_time_from_zero.setObjectName(u"cut_time_from_zero") self.gridLayout_23.addWidget(self.cut_time_from_zero, 4, 0, 1, 2) self.verticalLayout_15.addWidget(self.cut_group) self.resample_group = QGroupBox(self.scrollAreaWidgetContents_3) self.resample_group.setObjectName(u"resample_group") self.resample_group.setCheckable(True) self.resample_group.setChecked(False) self.gridLayout_24 = QGridLayout(self.resample_group) self.gridLayout_24.setSpacing(1) self.gridLayout_24.setObjectName(u"gridLayout_24") self.gridLayout_24.setContentsMargins(1, 1, 1, 1) self.raster_type_step = QRadioButton(self.resample_group) self.raster_type_step.setObjectName(u"raster_type_step") self.raster_type_step.setChecked(True) self.gridLayout_24.addWidget(self.raster_type_step, 0, 0, 1, 1) self.raster = QDoubleSpinBox(self.resample_group) self.raster.setObjectName(u"raster") self.raster.setMinimumSize(QSize(0, 0)) self.raster.setDecimals(6) self.raster.setMinimum(0.000001000000000) self.gridLayout_24.addWidget(self.raster, 0, 1, 1, 1) self.raster_type_channel = QRadioButton(self.resample_group) self.raster_type_channel.setObjectName(u"raster_type_channel") self.gridLayout_24.addWidget(self.raster_type_channel, 2, 0, 1, 1) self.raster_channel = QComboBox(self.resample_group) self.raster_channel.setObjectName(u"raster_channel") self.raster_channel.setEnabled(False) self.raster_channel.setInsertPolicy(QComboBox.InsertPolicy.InsertAtBottom) self.raster_channel.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) self.gridLayout_24.addWidget(self.raster_channel, 2, 1, 1, 1) self.raster_search_btn = QPushButton(self.resample_group) self.raster_search_btn.setObjectName(u"raster_search_btn") self.raster_search_btn.setIcon(icon4) self.gridLayout_24.addWidget(self.raster_search_btn, 2, 2, 1, 1) self.resample_time_from_zero = QCheckBox(self.resample_group) self.resample_time_from_zero.setObjectName(u"resample_time_from_zero") self.gridLayout_24.addWidget(self.resample_time_from_zero, 3, 0, 1, 3) self.gridLayout_24.setColumnStretch(1, 1) self.verticalLayout_15.addWidget(self.resample_group) self.groupBox_11 = QGroupBox(self.scrollAreaWidgetContents_3) self.groupBox_11.setObjectName(u"groupBox_11") self.verticalLayout_21 = QVBoxLayout(self.groupBox_11) self.verticalLayout_21.setSpacing(1) self.verticalLayout_21.setObjectName(u"verticalLayout_21") self.verticalLayout_21.setContentsMargins(1, 1, 1, 1) self.output_format = QComboBox(self.groupBox_11) self.output_format.setObjectName(u"output_format") self.verticalLayout_21.addWidget(self.output_format) self.output_options = QStackedWidget(self.groupBox_11) self.output_options.setObjectName(u"output_options") self.MDF = QWidget() self.MDF.setObjectName(u"MDF") self.gridLayout_25 = QGridLayout(self.MDF) self.gridLayout_25.setSpacing(1) self.gridLayout_25.setObjectName(u"gridLayout_25") self.gridLayout_25.setContentsMargins(1, 1, 1, 1) self.mdf_split = QCheckBox(self.MDF) self.mdf_split.setObjectName(u"mdf_split") self.mdf_split.setChecked(True) self.gridLayout_25.addWidget(self.mdf_split, 3, 0, 1, 2) self.mdf_compression = QComboBox(self.MDF) self.mdf_compression.setObjectName(u"mdf_compression") self.gridLayout_25.addWidget(self.mdf_compression, 2, 1, 1, 1) self.label_39 = QLabel(self.MDF) self.label_39.setObjectName(u"label_39") self.gridLayout_25.addWidget(self.label_39, 2, 0, 1, 1) self.label_40 = QLabel(self.MDF) self.label_40.setObjectName(u"label_40") self.gridLayout_25.addWidget(self.label_40, 0, 0, 1, 1) self.line_17 = QFrame(self.MDF) self.line_17.setObjectName(u"line_17") self.line_17.setFrameShape(QFrame.Shape.HLine) self.line_17.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_25.addWidget(self.line_17, 1, 0, 1, 2) self.label_38 = QLabel(self.MDF) self.label_38.setObjectName(u"label_38") self.gridLayout_25.addWidget(self.label_38, 4, 0, 1, 1) self.mdf_version = QComboBox(self.MDF) self.mdf_version.setObjectName(u"mdf_version") self.mdf_version.setMinimumSize(QSize(0, 0)) self.gridLayout_25.addWidget(self.mdf_version, 0, 1, 1, 1) self.groupBox_12 = QGroupBox(self.MDF) self.groupBox_12.setObjectName(u"groupBox_12") sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.groupBox_12.sizePolicy().hasHeightForWidth()) self.groupBox_12.setSizePolicy(sizePolicy) self.gridLayout_26 = QGridLayout(self.groupBox_12) self.gridLayout_26.setSpacing(1) self.gridLayout_26.setObjectName(u"gridLayout_26") self.gridLayout_26.setContentsMargins(1, 1, 1, 1) self.scramble_btn = QPushButton(self.groupBox_12) self.scramble_btn.setObjectName(u"scramble_btn") icon5 = QIcon() icon5.addFile(u":/scramble.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.scramble_btn.setIcon(icon5) self.gridLayout_26.addWidget(self.scramble_btn, 1, 0, 1, 1) self.horizontalSpacer_24 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_26.addItem(self.horizontalSpacer_24, 1, 1, 1, 1) self.label_64 = QLabel(self.groupBox_12) self.label_64.setObjectName(u"label_64") sizePolicy.setHeightForWidth(self.label_64.sizePolicy().hasHeightForWidth()) self.label_64.setSizePolicy(sizePolicy) self.label_64.setWordWrap(True) self.gridLayout_26.addWidget(self.label_64, 0, 0, 1, 2) self.gridLayout_26.setRowStretch(0, 1) self.gridLayout_26.setColumnStretch(1, 1) self.gridLayout_25.addWidget(self.groupBox_12, 5, 0, 1, 2) self.mdf_split_size = QDoubleSpinBox(self.MDF) self.mdf_split_size.setObjectName(u"mdf_split_size") self.mdf_split_size.setMaximum(4.000000000000000) self.gridLayout_25.addWidget(self.mdf_split_size, 4, 1, 1, 1) self.output_options.addWidget(self.MDF) self.HDF5 = QWidget() self.HDF5.setObjectName(u"HDF5") self.gridLayout_17 = QGridLayout(self.HDF5) self.gridLayout_17.setSpacing(1) self.gridLayout_17.setObjectName(u"gridLayout_17") self.gridLayout_17.setContentsMargins(1, 1, 1, 1) self.empty_channels = QComboBox(self.HDF5) self.empty_channels.setObjectName(u"empty_channels") self.gridLayout_17.addWidget(self.empty_channels, 8, 1, 1, 1) self.verticalSpacer_12 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_17.addItem(self.verticalSpacer_12, 9, 0, 1, 1) self.label_71 = QLabel(self.HDF5) self.label_71.setObjectName(u"label_71") self.gridLayout_17.addWidget(self.label_71, 7, 0, 1, 1) self.label_66 = QLabel(self.HDF5) self.label_66.setObjectName(u"label_66") self.gridLayout_17.addWidget(self.label_66, 8, 0, 1, 1) self.export_compression = QComboBox(self.HDF5) self.export_compression.setObjectName(u"export_compression") self.gridLayout_17.addWidget(self.export_compression, 7, 1, 1, 1) self.line_32 = QFrame(self.HDF5) self.line_32.setObjectName(u"line_32") self.line_32.setFrameShape(QFrame.Shape.HLine) self.line_32.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_17.addWidget(self.line_32, 4, 0, 1, 2) self.raw = QCheckBox(self.HDF5) self.raw.setObjectName(u"raw") self.gridLayout_17.addWidget(self.raw, 3, 0, 1, 2) self.time_as_date = QCheckBox(self.HDF5) self.time_as_date.setObjectName(u"time_as_date") self.gridLayout_17.addWidget(self.time_as_date, 2, 0, 1, 2) self.time_from_zero = QCheckBox(self.HDF5) self.time_from_zero.setObjectName(u"time_from_zero") self.gridLayout_17.addWidget(self.time_from_zero, 1, 0, 1, 2) self.single_time_base = QCheckBox(self.HDF5) self.single_time_base.setObjectName(u"single_time_base") self.gridLayout_17.addWidget(self.single_time_base, 0, 0, 1, 2) self.use_display_names = QCheckBox(self.HDF5) self.use_display_names.setObjectName(u"use_display_names") self.gridLayout_17.addWidget(self.use_display_names, 5, 0, 1, 2) self.reduce_memory_usage = QCheckBox(self.HDF5) self.reduce_memory_usage.setObjectName(u"reduce_memory_usage") self.gridLayout_17.addWidget(self.reduce_memory_usage, 6, 0, 1, 2) self.output_options.addWidget(self.HDF5) self.MAT = QWidget() self.MAT.setObjectName(u"MAT") self.gridLayout_18 = QGridLayout(self.MAT) self.gridLayout_18.setSpacing(1) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridLayout_18.setContentsMargins(1, 1, 1, 1) self.label_41 = QLabel(self.MAT) self.label_41.setObjectName(u"label_41") self.gridLayout_18.addWidget(self.label_41, 10, 0, 1, 1) self.label_72 = QLabel(self.MAT) self.label_72.setObjectName(u"label_72") self.gridLayout_18.addWidget(self.label_72, 7, 0, 1, 1) self.label_73 = QLabel(self.MAT) self.label_73.setObjectName(u"label_73") self.gridLayout_18.addWidget(self.label_73, 9, 0, 1, 1) self.export_compression_mat = QComboBox(self.MAT) self.export_compression_mat.setObjectName(u"export_compression_mat") self.gridLayout_18.addWidget(self.export_compression_mat, 7, 1, 1, 1) self.verticalSpacer_13 = QSpacerItem(20, 2, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_18.addItem(self.verticalSpacer_13, 11, 0, 1, 1) self.line_33 = QFrame(self.MAT) self.line_33.setObjectName(u"line_33") self.line_33.setFrameShape(QFrame.Shape.HLine) self.line_33.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_18.addWidget(self.line_33, 4, 0, 1, 2) self.empty_channels_mat = QComboBox(self.MAT) self.empty_channels_mat.setObjectName(u"empty_channels_mat") self.gridLayout_18.addWidget(self.empty_channels_mat, 8, 1, 1, 1) self.mat_format = QComboBox(self.MAT) self.mat_format.setObjectName(u"mat_format") self.gridLayout_18.addWidget(self.mat_format, 9, 1, 1, 1) self.oned_as = QComboBox(self.MAT) self.oned_as.setObjectName(u"oned_as") self.gridLayout_18.addWidget(self.oned_as, 10, 1, 1, 1) self.label_74 = QLabel(self.MAT) self.label_74.setObjectName(u"label_74") self.gridLayout_18.addWidget(self.label_74, 8, 0, 1, 1) self.raw_mat = QCheckBox(self.MAT) self.raw_mat.setObjectName(u"raw_mat") self.gridLayout_18.addWidget(self.raw_mat, 3, 0, 1, 2) self.use_display_names_mat = QCheckBox(self.MAT) self.use_display_names_mat.setObjectName(u"use_display_names_mat") self.gridLayout_18.addWidget(self.use_display_names_mat, 5, 0, 1, 2) self.reduce_memory_usage_mat = QCheckBox(self.MAT) self.reduce_memory_usage_mat.setObjectName(u"reduce_memory_usage_mat") self.gridLayout_18.addWidget(self.reduce_memory_usage_mat, 6, 0, 1, 2) self.time_as_date_mat = QCheckBox(self.MAT) self.time_as_date_mat.setObjectName(u"time_as_date_mat") self.gridLayout_18.addWidget(self.time_as_date_mat, 2, 0, 1, 2) self.time_from_zero_mat = QCheckBox(self.MAT) self.time_from_zero_mat.setObjectName(u"time_from_zero_mat") self.gridLayout_18.addWidget(self.time_from_zero_mat, 1, 0, 1, 2) self.single_time_base_mat = QCheckBox(self.MAT) self.single_time_base_mat.setObjectName(u"single_time_base_mat") self.gridLayout_18.addWidget(self.single_time_base_mat, 0, 0, 1, 2) self.output_options.addWidget(self.MAT) self.CSV = QWidget() self.CSV.setObjectName(u"CSV") self.gridLayout_2 = QGridLayout(self.CSV) self.gridLayout_2.setSpacing(1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(1, 1, 1, 1) self.escapechar = QLineEdit(self.CSV) self.escapechar.setObjectName(u"escapechar") self.escapechar.setMaxLength(1) self.gridLayout_2.addWidget(self.escapechar, 10, 1, 1, 1) self.doublequote = QCheckBox(self.CSV) self.doublequote.setObjectName(u"doublequote") self.doublequote.setChecked(True) self.gridLayout_2.addWidget(self.doublequote, 9, 0, 1, 1) self.quoting = QComboBox(self.CSV) self.quoting.addItem("") self.quoting.addItem("") self.quoting.addItem("") self.quoting.addItem("") self.quoting.setObjectName(u"quoting") self.gridLayout_2.addWidget(self.quoting, 13, 1, 1, 1) self.raw_csv = QCheckBox(self.CSV) self.raw_csv.setObjectName(u"raw_csv") self.gridLayout_2.addWidget(self.raw_csv, 3, 0, 1, 2) self.label_15 = QLabel(self.CSV) self.label_15.setObjectName(u"label_15") self.gridLayout_2.addWidget(self.label_15, 10, 0, 1, 1) self.empty_channels_csv = QComboBox(self.CSV) self.empty_channels_csv.setObjectName(u"empty_channels_csv") self.gridLayout_2.addWidget(self.empty_channels_csv, 7, 1, 1, 1) self.use_display_names_csv = QCheckBox(self.CSV) self.use_display_names_csv.setObjectName(u"use_display_names_csv") self.gridLayout_2.addWidget(self.use_display_names_csv, 5, 0, 1, 2) self.delimiter = QLineEdit(self.CSV) self.delimiter.setObjectName(u"delimiter") self.delimiter.setMaxLength(2) self.delimiter.setClearButtonEnabled(False) self.gridLayout_2.addWidget(self.delimiter, 8, 1, 1, 1) self.quotechar = QLineEdit(self.CSV) self.quotechar.setObjectName(u"quotechar") self.quotechar.setMaxLength(1) self.gridLayout_2.addWidget(self.quotechar, 12, 1, 1, 1) self.label_2 = QLabel(self.CSV) self.label_2.setObjectName(u"label_2") self.gridLayout_2.addWidget(self.label_2, 8, 0, 1, 1) self.line_34 = QFrame(self.CSV) self.line_34.setObjectName(u"line_34") self.line_34.setFrameShape(QFrame.Shape.HLine) self.line_34.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_2.addWidget(self.line_34, 4, 0, 1, 2) self.label_67 = QLabel(self.CSV) self.label_67.setObjectName(u"label_67") self.gridLayout_2.addWidget(self.label_67, 7, 0, 1, 1) self.label_6 = QLabel(self.CSV) self.label_6.setObjectName(u"label_6") self.gridLayout_2.addWidget(self.label_6, 13, 0, 1, 1) self.time_as_date_csv = QCheckBox(self.CSV) self.time_as_date_csv.setObjectName(u"time_as_date_csv") self.gridLayout_2.addWidget(self.time_as_date_csv, 2, 0, 1, 2) self.lineterminator = QLineEdit(self.CSV) self.lineterminator.setObjectName(u"lineterminator") self.gridLayout_2.addWidget(self.lineterminator, 11, 1, 1, 1) self.time_from_zero_csv = QCheckBox(self.CSV) self.time_from_zero_csv.setObjectName(u"time_from_zero_csv") self.gridLayout_2.addWidget(self.time_from_zero_csv, 1, 0, 1, 2) self.single_time_base_csv = QCheckBox(self.CSV) self.single_time_base_csv.setObjectName(u"single_time_base_csv") self.gridLayout_2.addWidget(self.single_time_base_csv, 0, 0, 1, 2) self.label_4 = QLabel(self.CSV) self.label_4.setObjectName(u"label_4") self.gridLayout_2.addWidget(self.label_4, 11, 0, 1, 1) self.label_5 = QLabel(self.CSV) self.label_5.setObjectName(u"label_5") self.gridLayout_2.addWidget(self.label_5, 12, 0, 1, 1) self.add_units = QCheckBox(self.CSV) self.add_units.setObjectName(u"add_units") self.gridLayout_2.addWidget(self.add_units, 6, 0, 1, 2) self.output_options.addWidget(self.CSV) self.ASC = QWidget() self.ASC.setObjectName(u"ASC") self.output_options.addWidget(self.ASC) self.verticalLayout_21.addWidget(self.output_options) self.verticalLayout_15.addWidget(self.groupBox_11) self.groupBox = QGroupBox(self.scrollAreaWidgetContents_3) self.groupBox.setObjectName(u"groupBox") self.gridLayout = QGridLayout(self.groupBox) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.modify_output_folder = QLineEdit(self.groupBox) self.modify_output_folder.setObjectName(u"modify_output_folder") self.modify_output_folder.setClearButtonEnabled(True) self.gridLayout.addWidget(self.modify_output_folder, 0, 0, 1, 1) self.modify_output_folder_btn = QPushButton(self.groupBox) self.modify_output_folder_btn.setObjectName(u"modify_output_folder_btn") self.modify_output_folder_btn.setIcon(icon1) self.gridLayout.addWidget(self.modify_output_folder_btn, 0, 1, 1, 1) self.verticalLayout_15.addWidget(self.groupBox) self.verticalSpacer_14 = QSpacerItem(20, 2, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_15.addItem(self.verticalSpacer_14) self.apply_btn = QPushButton(self.scrollAreaWidgetContents_3) self.apply_btn.setObjectName(u"apply_btn") icon6 = QIcon() icon6.addFile(u":/checkmark.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.apply_btn.setIcon(icon6) self.verticalLayout_15.addWidget(self.apply_btn) self.verticalLayout_15.setStretch(4, 1) self.horizontalLayout_2.addLayout(self.verticalLayout_15) self.horizontalLayout_2.setStretch(0, 1) self.horizontalLayout_2.setStretch(1, 1) self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) self.verticalLayout_5.addWidget(self.scrollArea_3) icon7 = QIcon() icon7.addFile(u":/convert.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.aspects.addTab(self.convert_tab, icon7, "") self.stack_tab = QWidget() self.stack_tab.setObjectName(u"stack_tab") self.gridLayout_8 = QGridLayout(self.stack_tab) self.gridLayout_8.setSpacing(1) self.gridLayout_8.setObjectName(u"gridLayout_8") self.gridLayout_8.setContentsMargins(1, 1, 1, 1) self.stack_sync = QCheckBox(self.stack_tab) self.stack_sync.setObjectName(u"stack_sync") self.stack_sync.setChecked(True) self.gridLayout_8.addWidget(self.stack_sync, 0, 0, 1, 2) self.stack_add_samples_origin = QCheckBox(self.stack_tab) self.stack_add_samples_origin.setObjectName(u"stack_add_samples_origin") self.stack_add_samples_origin.setChecked(True) self.gridLayout_8.addWidget(self.stack_add_samples_origin, 1, 0, 1, 2) self.label_26 = QLabel(self.stack_tab) self.label_26.setObjectName(u"label_26") self.gridLayout_8.addWidget(self.label_26, 2, 0, 1, 1) self.stack_format = QComboBox(self.stack_tab) self.stack_format.setObjectName(u"stack_format") self.gridLayout_8.addWidget(self.stack_format, 2, 1, 1, 1) self.line_8 = QFrame(self.stack_tab) self.line_8.setObjectName(u"line_8") self.line_8.setFrameShape(QFrame.Shape.HLine) self.line_8.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_8.addWidget(self.line_8, 3, 0, 1, 2) self.label_25 = QLabel(self.stack_tab) self.label_25.setObjectName(u"label_25") self.gridLayout_8.addWidget(self.label_25, 4, 0, 1, 1) self.stack_compression = QComboBox(self.stack_tab) self.stack_compression.setObjectName(u"stack_compression") self.gridLayout_8.addWidget(self.stack_compression, 4, 1, 1, 1) self.stack_split = QCheckBox(self.stack_tab) self.stack_split.setObjectName(u"stack_split") self.stack_split.setChecked(True) self.gridLayout_8.addWidget(self.stack_split, 5, 0, 1, 1) self.label_23 = QLabel(self.stack_tab) self.label_23.setObjectName(u"label_23") self.gridLayout_8.addWidget(self.label_23, 6, 0, 1, 1) self.stack_split_size = QDoubleSpinBox(self.stack_tab) self.stack_split_size.setObjectName(u"stack_split_size") self.stack_split_size.setMaximum(4.000000000000000) self.gridLayout_8.addWidget(self.stack_split_size, 6, 1, 1, 1) self.line_7 = QFrame(self.stack_tab) self.line_7.setObjectName(u"line_7") self.line_7.setFrameShape(QFrame.Shape.HLine) self.line_7.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_8.addWidget(self.line_7, 7, 0, 1, 2) self.verticalSpacer_7 = QSpacerItem(20, 502, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_8.addItem(self.verticalSpacer_7, 8, 1, 1, 1) self.stack_btn = QPushButton(self.stack_tab) self.stack_btn.setObjectName(u"stack_btn") icon8 = QIcon() icon8.addFile(u":/stack.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.stack_btn.setIcon(icon8) self.gridLayout_8.addWidget(self.stack_btn, 9, 1, 1, 1) self.gridLayout_8.setColumnStretch(1, 1) self.aspects.addTab(self.stack_tab, icon8, "") self.extract_bus_tab = QWidget() self.extract_bus_tab.setObjectName(u"extract_bus_tab") self.verticalLayout_4 = QVBoxLayout(self.extract_bus_tab) self.verticalLayout_4.setSpacing(1) self.verticalLayout_4.setObjectName(u"verticalLayout_4") self.verticalLayout_4.setContentsMargins(1, 1, 1, 1) self.scrollArea = QScrollArea(self.extract_bus_tab) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 517, 706)) self.gridLayout_3 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_3.setSpacing(1) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.groupBox_3 = QGroupBox(self.scrollAreaWidgetContents) self.groupBox_3.setObjectName(u"groupBox_3") self.gridLayout_10 = QGridLayout(self.groupBox_3) self.gridLayout_10.setSpacing(1) self.gridLayout_10.setObjectName(u"gridLayout_10") self.gridLayout_10.setContentsMargins(1, 1, 1, 1) self.lineterminator_bus = QLineEdit(self.groupBox_3) self.lineterminator_bus.setObjectName(u"lineterminator_bus") self.gridLayout_10.addWidget(self.lineterminator_bus, 9, 2, 1, 1) self.line_13 = QFrame(self.groupBox_3) self.line_13.setObjectName(u"line_13") self.line_13.setFrameShape(QFrame.Shape.HLine) self.line_13.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_10.addWidget(self.line_13, 12, 1, 1, 3) self.empty_channels_bus = QComboBox(self.groupBox_3) self.empty_channels_bus.setObjectName(u"empty_channels_bus") self.gridLayout_10.addWidget(self.empty_channels_bus, 5, 2, 1, 2) self.delimiter_bus = QLineEdit(self.groupBox_3) self.delimiter_bus.setObjectName(u"delimiter_bus") self.delimiter_bus.setMaxLength(2) self.delimiter_bus.setClearButtonEnabled(False) self.gridLayout_10.addWidget(self.delimiter_bus, 6, 2, 1, 1) self.time_from_zero_bus = QCheckBox(self.groupBox_3) self.time_from_zero_bus.setObjectName(u"time_from_zero_bus") self.gridLayout_10.addWidget(self.time_from_zero_bus, 1, 1, 1, 2) self.escapechar_bus = QLineEdit(self.groupBox_3) self.escapechar_bus.setObjectName(u"escapechar_bus") self.escapechar_bus.setMaxLength(1) self.gridLayout_10.addWidget(self.escapechar_bus, 8, 2, 1, 1) self.label_7 = QLabel(self.groupBox_3) self.label_7.setObjectName(u"label_7") self.gridLayout_10.addWidget(self.label_7, 11, 1, 1, 1) self.bus_time_as_date = QCheckBox(self.groupBox_3) self.bus_time_as_date.setObjectName(u"bus_time_as_date") self.gridLayout_10.addWidget(self.bus_time_as_date, 2, 1, 1, 2) self.label_9 = QLabel(self.groupBox_3) self.label_9.setObjectName(u"label_9") self.gridLayout_10.addWidget(self.label_9, 8, 1, 1, 1) self.label_29 = QLabel(self.groupBox_3) self.label_29.setObjectName(u"label_29") self.gridLayout_10.addWidget(self.label_29, 5, 1, 1, 1) self.quoting_bus = QComboBox(self.groupBox_3) self.quoting_bus.addItem("") self.quoting_bus.addItem("") self.quoting_bus.addItem("") self.quoting_bus.addItem("") self.quoting_bus.setObjectName(u"quoting_bus") self.gridLayout_10.addWidget(self.quoting_bus, 11, 2, 1, 1) self.label_14 = QLabel(self.groupBox_3) self.label_14.setObjectName(u"label_14") self.gridLayout_10.addWidget(self.label_14, 10, 1, 1, 1) self.export_raster_bus = QDoubleSpinBox(self.groupBox_3) self.export_raster_bus.setObjectName(u"export_raster_bus") self.export_raster_bus.setDecimals(6) self.gridLayout_10.addWidget(self.export_raster_bus, 4, 2, 1, 2) self.add_units_bus = QCheckBox(self.groupBox_3) self.add_units_bus.setObjectName(u"add_units_bus") self.gridLayout_10.addWidget(self.add_units_bus, 3, 1, 1, 2) self.label_28 = QLabel(self.groupBox_3) self.label_28.setObjectName(u"label_28") self.gridLayout_10.addWidget(self.label_28, 4, 1, 1, 1) self.extract_bus_csv_btn = QPushButton(self.groupBox_3) self.extract_bus_csv_btn.setObjectName(u"extract_bus_csv_btn") icon9 = QIcon() icon9.addFile(u":/csv.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.extract_bus_csv_btn.setIcon(icon9) self.gridLayout_10.addWidget(self.extract_bus_csv_btn, 13, 1, 1, 3) self.single_time_base_bus = QCheckBox(self.groupBox_3) self.single_time_base_bus.setObjectName(u"single_time_base_bus") self.gridLayout_10.addWidget(self.single_time_base_bus, 0, 1, 1, 2) self.quotechar_bus = QLineEdit(self.groupBox_3) self.quotechar_bus.setObjectName(u"quotechar_bus") self.quotechar_bus.setMaxLength(1) self.gridLayout_10.addWidget(self.quotechar_bus, 10, 2, 1, 1) self.label_13 = QLabel(self.groupBox_3) self.label_13.setObjectName(u"label_13") self.gridLayout_10.addWidget(self.label_13, 9, 1, 1, 1) self.doublequote_bus = QCheckBox(self.groupBox_3) self.doublequote_bus.setObjectName(u"doublequote_bus") self.doublequote_bus.setChecked(True) self.gridLayout_10.addWidget(self.doublequote_bus, 7, 1, 1, 2) self.label_8 = QLabel(self.groupBox_3) self.label_8.setObjectName(u"label_8") self.gridLayout_10.addWidget(self.label_8, 6, 1, 1, 1) self.gridLayout_3.addWidget(self.groupBox_3, 2, 1, 1, 1) self.output_info_bus = QTextEdit(self.scrollAreaWidgetContents) self.output_info_bus.setObjectName(u"output_info_bus") self.output_info_bus.setReadOnly(True) self.gridLayout_3.addWidget(self.output_info_bus, 0, 2, 3, 1) self.tabWidget = QTabWidget(self.scrollAreaWidgetContents) self.tabWidget.setObjectName(u"tabWidget") self.tab = QWidget() self.tab.setObjectName(u"tab") self.verticalLayout = QVBoxLayout(self.tab) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.load_can_database_btn = QPushButton(self.tab) self.load_can_database_btn.setObjectName(u"load_can_database_btn") self.load_can_database_btn.setIcon(icon1) self.verticalLayout.addWidget(self.load_can_database_btn) self.can_database_list = MinimalListWidget(self.tab) self.can_database_list.setObjectName(u"can_database_list") self.verticalLayout.addWidget(self.can_database_list) self.tabWidget.addTab(self.tab, "") self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") self.verticalLayout_2 = QVBoxLayout(self.tab_2) self.verticalLayout_2.setSpacing(1) self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.verticalLayout_2.setContentsMargins(1, 1, 1, 1) self.load_lin_database_btn = QPushButton(self.tab_2) self.load_lin_database_btn.setObjectName(u"load_lin_database_btn") self.load_lin_database_btn.setIcon(icon1) self.verticalLayout_2.addWidget(self.load_lin_database_btn) self.lin_database_list = MinimalListWidget(self.tab_2) self.lin_database_list.setObjectName(u"lin_database_list") self.verticalLayout_2.addWidget(self.lin_database_list) self.tabWidget.addTab(self.tab_2, "") self.gridLayout_3.addWidget(self.tabWidget, 0, 0, 1, 2) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.label = QLabel(self.scrollAreaWidgetContents) self.label.setObjectName(u"label") self.horizontalLayout.addWidget(self.label) self.prefix = QLineEdit(self.scrollAreaWidgetContents) self.prefix.setObjectName(u"prefix") self.prefix.setMinimumSize(QSize(0, 0)) self.horizontalLayout.addWidget(self.prefix) self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer) self.horizontalLayout.setStretch(2, 1) self.gridLayout_3.addLayout(self.horizontalLayout, 1, 0, 1, 2) self.groupBox_2 = QGroupBox(self.scrollAreaWidgetContents) self.groupBox_2.setObjectName(u"groupBox_2") self.gridLayout_5 = QGridLayout(self.groupBox_2) self.gridLayout_5.setSpacing(1) self.gridLayout_5.setObjectName(u"gridLayout_5") self.gridLayout_5.setContentsMargins(1, 1, 1, 1) self.extract_bus_compression = QComboBox(self.groupBox_2) self.extract_bus_compression.setObjectName(u"extract_bus_compression") self.extract_bus_compression.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents) self.gridLayout_5.addWidget(self.extract_bus_compression, 0, 1, 1, 1) self.label_24 = QLabel(self.groupBox_2) self.label_24.setObjectName(u"label_24") self.gridLayout_5.addWidget(self.label_24, 1, 0, 1, 1) self.label__1 = QLabel(self.groupBox_2) self.label__1.setObjectName(u"label__1") self.gridLayout_5.addWidget(self.label__1, 0, 0, 1, 1) self.line_12 = QFrame(self.groupBox_2) self.line_12.setObjectName(u"line_12") self.line_12.setFrameShape(QFrame.Shape.HLine) self.line_12.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_5.addWidget(self.line_12, 3, 0, 1, 2) self.extract_bus_btn = QPushButton(self.groupBox_2) self.extract_bus_btn.setObjectName(u"extract_bus_btn") icon10 = QIcon() icon10.addFile(u":/down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.extract_bus_btn.setIcon(icon10) self.gridLayout_5.addWidget(self.extract_bus_btn, 4, 0, 1, 2) self.extract_bus_format = QComboBox(self.groupBox_2) self.extract_bus_format.setObjectName(u"extract_bus_format") self.extract_bus_format.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents) self.gridLayout_5.addWidget(self.extract_bus_format, 1, 1, 1, 1) self.label_27 = QLabel(self.groupBox_2) self.label_27.setObjectName(u"label_27") self.gridLayout_5.addWidget(self.label_27, 2, 0, 1, 1) self.gridLayout_3.addWidget(self.groupBox_2, 2, 0, 1, 1) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.verticalLayout_4.addWidget(self.scrollArea) self.aspects.addTab(self.extract_bus_tab, icon10, "") self.splitter.addWidget(self.aspects) self.gridLayout_9.addWidget(self.splitter, 1, 0, 1, 1) self.list_layout = QVBoxLayout() self.list_layout.setSpacing(1) self.list_layout.setObjectName(u"list_layout") self.files_list = MinimalListWidget(batch_widget) self.files_list.setObjectName(u"files_list") self.list_layout.addWidget(self.files_list) self.verticalLayout_3 = QVBoxLayout() self.verticalLayout_3.setSpacing(1) self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.sort_by_start_time_btn = QPushButton(batch_widget) self.sort_by_start_time_btn.setObjectName(u"sort_by_start_time_btn") icon11 = QIcon() icon11.addFile(u":/clock.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.sort_by_start_time_btn.setIcon(icon11) self.verticalLayout_3.addWidget(self.sort_by_start_time_btn) self.sort_alphabetically_btn = QPushButton(batch_widget) self.sort_alphabetically_btn.setObjectName(u"sort_alphabetically_btn") icon12 = QIcon() icon12.addFile(u":/alphabetical_sorting.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.sort_alphabetically_btn.setIcon(icon12) self.verticalLayout_3.addWidget(self.sort_alphabetically_btn) self.list_layout.addLayout(self.verticalLayout_3) self.gridLayout_9.addLayout(self.list_layout, 1, 1, 1, 1) self.gridLayout_9.setColumnStretch(0, 2) self.gridLayout_9.setColumnStretch(1, 1) self.retranslateUi(batch_widget) self.aspects.setCurrentIndex(0) self.output_options.setCurrentIndex(0) self.quoting.setCurrentIndex(1) self.quoting_bus.setCurrentIndex(1) self.tabWidget.setCurrentIndex(0) QMetaObject.connectSlotsByName(batch_widget) # setupUi def retranslateUi(self, batch_widget): batch_widget.setWindowTitle(QCoreApplication.translate("batch_widget", u"Form", None)) self.concatenate_sync.setText(QCoreApplication.translate("batch_widget", u"Sync using measurements timestamps", None)) self.concatenate_add_samples_origin.setText(QCoreApplication.translate("batch_widget", u"Add samples origin file", None)) self.label_11.setText(QCoreApplication.translate("batch_widget", u"Output format", None)) self.label_12.setText(QCoreApplication.translate("batch_widget", u"Compression", None)) self.concatenate_split.setText(QCoreApplication.translate("batch_widget", u"Split data blocks", None)) self.concatenate_split_size.setSuffix(QCoreApplication.translate("batch_widget", u"MB", None)) self.label_10.setText(QCoreApplication.translate("batch_widget", u"Split size ", None)) self.concatenate_btn.setText(QCoreApplication.translate("batch_widget", u"Concatenate", None)) self.aspects.setTabText(self.aspects.indexOf(self.concatenate_tab), QCoreApplication.translate("batch_widget", u"Concatenate", None)) self.filter_view.setItemText(0, QCoreApplication.translate("batch_widget", u"Natural sort", None)) self.filter_view.setItemText(1, QCoreApplication.translate("batch_widget", u"Internal file structure", None)) self.filter_view.setItemText(2, QCoreApplication.translate("batch_widget", u"Selected channels only", None)) ___qtreewidgetitem = self.filter_tree.headerItem() ___qtreewidgetitem.setText(0, QCoreApplication.translate("batch_widget", u"Channels", None)); #if QT_CONFIG(tooltip) self.filter_tree.setToolTip(QCoreApplication.translate("batch_widget", u"Double click channel to see extended information", None)) #endif // QT_CONFIG(tooltip) #if QT_CONFIG(tooltip) self.load_filter_list_btn.setToolTip(QCoreApplication.translate("batch_widget", u"Load channel selection list", None)) #endif // QT_CONFIG(tooltip) self.load_filter_list_btn.setText("") #if QT_CONFIG(tooltip) self.save_filter_list_btn.setToolTip(QCoreApplication.translate("batch_widget", u"Save channel selection list", None)) #endif // QT_CONFIG(tooltip) self.save_filter_list_btn.setText("") #if QT_CONFIG(tooltip) self.clear_filter_btn.setToolTip(QCoreApplication.translate("batch_widget", u"Clear selection", None)) #endif // QT_CONFIG(tooltip) self.clear_filter_btn.setText("") #if QT_CONFIG(tooltip) self.advanced_serch_filter_btn.setToolTip(QCoreApplication.translate("batch_widget", u"Search and select channels", None)) #endif // QT_CONFIG(tooltip) self.advanced_serch_filter_btn.setText("") self.label_3.setText(QCoreApplication.translate("batch_widget", u"All selected channels", None)) self.cut_group.setTitle(QCoreApplication.translate("batch_widget", u"Cut", None)) self.label_62.setText(QCoreApplication.translate("batch_widget", u"Start", None)) self.cut_stop.setSuffix(QCoreApplication.translate("batch_widget", u"s", None)) self.label_63.setText(QCoreApplication.translate("batch_widget", u"End", None)) self.cut_start.setSuffix(QCoreApplication.translate("batch_widget", u"s", None)) self.whence.setText(QCoreApplication.translate("batch_widget", u"Start relative to first time stamp", None)) self.cut_time_from_zero.setText(QCoreApplication.translate("batch_widget", u"Time from 0s", None)) self.resample_group.setTitle(QCoreApplication.translate("batch_widget", u"Resample", None)) self.raster_type_step.setText(QCoreApplication.translate("batch_widget", u"step", None)) self.raster.setSuffix(QCoreApplication.translate("batch_widget", u"s", None)) self.raster_type_channel.setText(QCoreApplication.translate("batch_widget", u"channel", None)) #if QT_CONFIG(tooltip) self.raster_search_btn.setToolTip(QCoreApplication.translate("batch_widget", u"Search raster channel", None)) #endif // QT_CONFIG(tooltip) self.raster_search_btn.setText("") self.resample_time_from_zero.setText(QCoreApplication.translate("batch_widget", u"Time from 0s", None)) self.groupBox_11.setTitle(QCoreApplication.translate("batch_widget", u"Output format", None)) self.mdf_split.setText(QCoreApplication.translate("batch_widget", u"Split data blocks", None)) self.label_39.setText(QCoreApplication.translate("batch_widget", u"Compression", None)) self.label_40.setText(QCoreApplication.translate("batch_widget", u"Version", None)) self.label_38.setText(QCoreApplication.translate("batch_widget", u"Split size ", None)) self.groupBox_12.setTitle(QCoreApplication.translate("batch_widget", u"Scramble", None)) self.scramble_btn.setText(QCoreApplication.translate("batch_widget", u"Scramble texts", None)) self.label_64.setText(QCoreApplication.translate("batch_widget", u"Anonymize the measurements: scramble all texts and replace them with random strings", None)) self.mdf_split_size.setSuffix(QCoreApplication.translate("batch_widget", u"MB", None)) self.label_71.setText(QCoreApplication.translate("batch_widget", u"Compression", None)) self.label_66.setText(QCoreApplication.translate("batch_widget", u"Empty channels", None)) self.raw.setText(QCoreApplication.translate("batch_widget", u"Raw values", None)) self.time_as_date.setText(QCoreApplication.translate("batch_widget", u"Time as date", None)) self.time_from_zero.setText(QCoreApplication.translate("batch_widget", u"Time from 0s", None)) self.single_time_base.setText(QCoreApplication.translate("batch_widget", u"Single time base", None)) self.use_display_names.setText(QCoreApplication.translate("batch_widget", u"Use display names", None)) self.reduce_memory_usage.setText(QCoreApplication.translate("batch_widget", u"Reduce memory usage", None)) self.label_41.setText(QCoreApplication.translate("batch_widget", u".mat oned_as", None)) self.label_72.setText(QCoreApplication.translate("batch_widget", u"Compression", None)) self.label_73.setText(QCoreApplication.translate("batch_widget", u".mat format", None)) self.label_74.setText(QCoreApplication.translate("batch_widget", u"Empty channels", None)) self.raw_mat.setText(QCoreApplication.translate("batch_widget", u"Raw values", None)) self.use_display_names_mat.setText(QCoreApplication.translate("batch_widget", u"Use display names", None)) self.reduce_memory_usage_mat.setText(QCoreApplication.translate("batch_widget", u"Reduce memory usage", None)) self.time_as_date_mat.setText(QCoreApplication.translate("batch_widget", u"Time as date", None)) self.time_from_zero_mat.setText(QCoreApplication.translate("batch_widget", u"Time from 0s", None)) self.single_time_base_mat.setText(QCoreApplication.translate("batch_widget", u"Single time base", None)) self.escapechar.setInputMask("") self.escapechar.setPlaceholderText(QCoreApplication.translate("batch_widget", u"None", None)) self.doublequote.setText(QCoreApplication.translate("batch_widget", u"Double quote", None)) self.quoting.setItemText(0, QCoreApplication.translate("batch_widget", u"ALL", None)) self.quoting.setItemText(1, QCoreApplication.translate("batch_widget", u"MINIMAL", None)) self.quoting.setItemText(2, QCoreApplication.translate("batch_widget", u"NONNUMERIC", None)) self.quoting.setItemText(3, QCoreApplication.translate("batch_widget", u"NONE", None)) self.raw_csv.setText(QCoreApplication.translate("batch_widget", u"Raw values", None)) self.label_15.setText(QCoreApplication.translate("batch_widget", u"Escape Char", None)) self.use_display_names_csv.setText(QCoreApplication.translate("batch_widget", u"Use display names", None)) self.delimiter.setText(QCoreApplication.translate("batch_widget", u",", None)) self.quotechar.setText(QCoreApplication.translate("batch_widget", u"\"", None)) self.label_2.setText(QCoreApplication.translate("batch_widget", u"Delimiter", None)) self.label_67.setText(QCoreApplication.translate("batch_widget", u"Empty channels", None)) self.label_6.setText(QCoreApplication.translate("batch_widget", u"Quoting", None)) self.time_as_date_csv.setText(QCoreApplication.translate("batch_widget", u"Time as date", None)) self.lineterminator.setText(QCoreApplication.translate("batch_widget", u"\\r\\n", None)) self.time_from_zero_csv.setText(QCoreApplication.translate("batch_widget", u"Time from 0s", None)) self.single_time_base_csv.setText(QCoreApplication.translate("batch_widget", u"Single time base", None)) self.label_4.setText(QCoreApplication.translate("batch_widget", u"Line Terminator", None)) self.label_5.setText(QCoreApplication.translate("batch_widget", u"Quote Char", None)) self.add_units.setText(QCoreApplication.translate("batch_widget", u"Add units", None)) self.groupBox.setTitle(QCoreApplication.translate("batch_widget", u"Output folder", None)) self.modify_output_folder.setPlaceholderText(QCoreApplication.translate("batch_widget", u"please select an output folder", None)) self.modify_output_folder_btn.setText("") self.apply_btn.setText(QCoreApplication.translate("batch_widget", u"Apply", None)) self.aspects.setTabText(self.aspects.indexOf(self.convert_tab), QCoreApplication.translate("batch_widget", u"Modify && Export", None)) #if QT_CONFIG(tooltip) self.aspects.setTabToolTip(self.aspects.indexOf(self.convert_tab), QCoreApplication.translate("batch_widget", u"conv", None)) #endif // QT_CONFIG(tooltip) self.stack_sync.setText(QCoreApplication.translate("batch_widget", u"Sync using measurements timestamps", None)) self.stack_add_samples_origin.setText(QCoreApplication.translate("batch_widget", u"Add samples origin file", None)) self.label_26.setText(QCoreApplication.translate("batch_widget", u"Output format", None)) self.label_25.setText(QCoreApplication.translate("batch_widget", u"Compression", None)) self.stack_split.setText(QCoreApplication.translate("batch_widget", u"Split data blocks", None)) self.label_23.setText(QCoreApplication.translate("batch_widget", u"Split size ", None)) self.stack_split_size.setSuffix(QCoreApplication.translate("batch_widget", u"MB", None)) self.stack_btn.setText(QCoreApplication.translate("batch_widget", u"Stack", None)) self.aspects.setTabText(self.aspects.indexOf(self.stack_tab), QCoreApplication.translate("batch_widget", u"Stack", None)) self.groupBox_3.setTitle(QCoreApplication.translate("batch_widget", u"CSV", None)) self.lineterminator_bus.setText(QCoreApplication.translate("batch_widget", u"\\r\\n", None)) self.delimiter_bus.setText(QCoreApplication.translate("batch_widget", u",", None)) self.time_from_zero_bus.setText(QCoreApplication.translate("batch_widget", u"Time from 0s", None)) self.escapechar_bus.setInputMask("") self.escapechar_bus.setPlaceholderText(QCoreApplication.translate("batch_widget", u"None", None)) self.label_7.setText(QCoreApplication.translate("batch_widget", u"Quoting", None)) self.bus_time_as_date.setText(QCoreApplication.translate("batch_widget", u"Time as date", None)) self.label_9.setText(QCoreApplication.translate("batch_widget", u"Escape Char", None)) self.label_29.setText(QCoreApplication.translate("batch_widget", u"Empty channels", None)) self.quoting_bus.setItemText(0, QCoreApplication.translate("batch_widget", u"ALL", None)) self.quoting_bus.setItemText(1, QCoreApplication.translate("batch_widget", u"MINIMAL", None)) self.quoting_bus.setItemText(2, QCoreApplication.translate("batch_widget", u"NONNUMERIC", None)) self.quoting_bus.setItemText(3, QCoreApplication.translate("batch_widget", u"NONE", None)) self.label_14.setText(QCoreApplication.translate("batch_widget", u"Quote Char", None)) self.export_raster_bus.setSuffix(QCoreApplication.translate("batch_widget", u"s", None)) self.add_units_bus.setText(QCoreApplication.translate("batch_widget", u"Add units", None)) self.label_28.setText(QCoreApplication.translate("batch_widget", u"Raster", None)) self.extract_bus_csv_btn.setText(QCoreApplication.translate("batch_widget", u"Export to CSV ", None)) self.single_time_base_bus.setText(QCoreApplication.translate("batch_widget", u"Single time base", None)) self.quotechar_bus.setText(QCoreApplication.translate("batch_widget", u"\"", None)) self.label_13.setText(QCoreApplication.translate("batch_widget", u"Line Terminator", None)) self.doublequote_bus.setText(QCoreApplication.translate("batch_widget", u"Double quote", None)) self.label_8.setText(QCoreApplication.translate("batch_widget", u"Delimiter", None)) self.load_can_database_btn.setText(QCoreApplication.translate("batch_widget", u"Load CAN database", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("batch_widget", u"CAN", None)) self.load_lin_database_btn.setText(QCoreApplication.translate("batch_widget", u"Load LIN database", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("batch_widget", u"LIN", None)) self.label.setText(QCoreApplication.translate("batch_widget", u"Prefix", None)) self.groupBox_2.setTitle(QCoreApplication.translate("batch_widget", u"MDF", None)) self.label_24.setText(QCoreApplication.translate("batch_widget", u"Version", None)) self.label__1.setText(QCoreApplication.translate("batch_widget", u"Compression", None)) self.extract_bus_btn.setText(QCoreApplication.translate("batch_widget", u"Extract Bus signals", None)) self.label_27.setText("") self.aspects.setTabText(self.aspects.indexOf(self.extract_bus_tab), QCoreApplication.translate("batch_widget", u"Bus logging", None)) self.sort_by_start_time_btn.setText(QCoreApplication.translate("batch_widget", u"Sort by start time", None)) self.sort_alphabetically_btn.setText(QCoreApplication.translate("batch_widget", u"Sort alphabetically", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/batch_widget.ui000066400000000000000000002217061502633300400215240ustar00rootroot00000000000000 batch_widget 0 0 828 718 Form 1 1 1 1 1 Qt::Orientation::Horizontal QTabWidget::TabPosition::West 0 false :/plus.png:/plus.png Concatenate 1 1 1 1 1 Sync using measurements timestamps true Add samples origin file true Output format Qt::Orientation::Horizontal Compression Split data blocks true Qt::Orientation::Horizontal MB 4.000000000000000 Split size Concatenate :/plus.png:/plus.png Qt::Orientation::Vertical 20 2 :/convert.png:/convert.png Modify && Export conv 1 1 1 1 1 true 0 0 517 706 1 1 1 1 1 1 Natural sort Internal file structure Selected channels only Double click channel to see extended information Channels 1 Load channel selection list :/open.png:/open.png Save channel selection list :/save.png:/save.png Clear selection :/erase.png:/erase.png Search and select channels :/search.png:/search.png Qt::Orientation::Horizontal 40 20 1 All selected channels QListView::ViewMode::ListMode true true 1 1 1 1 1 Cut true false 1 1 1 1 1 Start s 6 999999.999998999992386 End s 6 999999.999998999992386 Start relative to first time stamp Time from 0s Resample true false 1 1 1 1 1 step true 0 0 s 6 0.000001000000000 channel false QComboBox::InsertPolicy::InsertAtBottom QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon Search raster channel :/search.png:/search.png Time from 0s Output format 1 1 1 1 1 0 1 1 1 1 1 Split data blocks true Compression Version Qt::Orientation::Horizontal Split size 0 0 0 0 Scramble 1 1 1 1 1 Scramble texts :/scramble.png:/scramble.png Qt::Orientation::Horizontal 40 20 0 0 Anonymize the measurements: scramble all texts and replace them with random strings true MB 4.000000000000000 1 1 1 1 1 Qt::Orientation::Vertical 20 40 Compression Empty channels Qt::Orientation::Horizontal Raw values Time as date Time from 0s Single time base Use display names Reduce memory usage 1 1 1 1 1 .mat oned_as Compression .mat format Qt::Orientation::Vertical 20 2 Qt::Orientation::Horizontal Empty channels Raw values Use display names Reduce memory usage Time as date Time from 0s Single time base 1 1 1 1 1 1 None Double quote true 1 ALL MINIMAL NONNUMERIC NONE Raw values Escape Char Use display names , 2 false " 1 Delimiter Qt::Orientation::Horizontal Empty channels Quoting Time as date \r\n Time from 0s Single time base Line Terminator Quote Char Add units Output folder 1 1 1 1 1 please select an output folder true :/open.png:/open.png Qt::Orientation::Vertical 20 2 Apply :/checkmark.png:/checkmark.png :/stack.png:/stack.png Stack 1 1 1 1 1 Sync using measurements timestamps true Add samples origin file true Output format Qt::Orientation::Horizontal Compression Split data blocks true Split size MB 4.000000000000000 Qt::Orientation::Horizontal Qt::Orientation::Vertical 20 502 Stack :/stack.png:/stack.png :/down.png:/down.png Bus logging 1 1 1 1 1 true 0 0 517 706 1 1 1 1 1 CSV 1 1 1 1 1 \r\n Qt::Orientation::Horizontal , 2 false Time from 0s 1 None Quoting Time as date Escape Char Empty channels 1 ALL MINIMAL NONNUMERIC NONE Quote Char s 6 Add units Raster Export to CSV :/csv.png:/csv.png Single time base " 1 Line Terminator Double quote true Delimiter true 0 CAN 1 1 1 1 1 Load CAN database :/open.png:/open.png LIN 1 1 1 1 1 Load LIN database :/open.png:/open.png 1 Prefix 0 0 Qt::Orientation::Horizontal 40 20 MDF 1 1 1 1 1 QComboBox::SizeAdjustPolicy::AdjustToContents Version Compression Qt::Orientation::Horizontal Extract Bus signals :/down.png:/down.png QComboBox::SizeAdjustPolicy::AdjustToContents 1 <html><head/><body><p>The channels from the first measurement will be used in the Modifi &amp; Export tab</p></body></html> Qt::TextFormat::RichText true 1 Sort by start time :/clock.png:/clock.png Sort alphabetically :/alphabetical_sorting.png:/alphabetical_sorting.png MinimalListWidget QListWidget
asammdf.gui.widgets.list.h
TreeWidget QTreeWidget
asammdf/gui/widgets/tree.h
asammdf-8.5.1/src/asammdf/gui/ui/bus_database_manager.py000066400000000000000000000106071502633300400232160ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'bus_database_manager.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QGridLayout, QListWidgetItem, QPushButton, QSizePolicy, QSpacerItem, QTabWidget, QWidget) from asammdf.gui.widgets.list import MinimalListWidget from . import resource_rc class Ui_BusDatabaseManager(object): def setupUi(self, BusDatabaseManager): if not BusDatabaseManager.objectName(): BusDatabaseManager.setObjectName(u"BusDatabaseManager") BusDatabaseManager.resize(632, 267) self.gridLayout = QGridLayout(BusDatabaseManager) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.tabWidget = QTabWidget(BusDatabaseManager) self.tabWidget.setObjectName(u"tabWidget") self.tab = QWidget() self.tab.setObjectName(u"tab") self.gridLayout_4 = QGridLayout(self.tab) self.gridLayout_4.setSpacing(1) self.gridLayout_4.setObjectName(u"gridLayout_4") self.gridLayout_4.setContentsMargins(1, 1, 1, 1) self.load_can_database_btn = QPushButton(self.tab) self.load_can_database_btn.setObjectName(u"load_can_database_btn") icon = QIcon() icon.addFile(u":/open.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.load_can_database_btn.setIcon(icon) self.gridLayout_4.addWidget(self.load_can_database_btn, 0, 0, 1, 1) self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_4.addItem(self.horizontalSpacer, 0, 1, 1, 1) self.can_database_list = MinimalListWidget(self.tab) self.can_database_list.setObjectName(u"can_database_list") self.gridLayout_4.addWidget(self.can_database_list, 1, 0, 1, 2) self.tabWidget.addTab(self.tab, "") self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") self.gridLayout_8 = QGridLayout(self.tab_2) self.gridLayout_8.setSpacing(1) self.gridLayout_8.setObjectName(u"gridLayout_8") self.gridLayout_8.setContentsMargins(1, 1, 1, 1) self.load_lin_database_btn = QPushButton(self.tab_2) self.load_lin_database_btn.setObjectName(u"load_lin_database_btn") self.load_lin_database_btn.setIcon(icon) self.gridLayout_8.addWidget(self.load_lin_database_btn, 0, 0, 1, 1) self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_8.addItem(self.horizontalSpacer_3, 0, 1, 1, 1) self.lin_database_list = MinimalListWidget(self.tab_2) self.lin_database_list.setObjectName(u"lin_database_list") self.gridLayout_8.addWidget(self.lin_database_list, 1, 0, 1, 2) self.tabWidget.addTab(self.tab_2, "") self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) self.retranslateUi(BusDatabaseManager) self.tabWidget.setCurrentIndex(0) QMetaObject.connectSlotsByName(BusDatabaseManager) # setupUi def retranslateUi(self, BusDatabaseManager): BusDatabaseManager.setWindowTitle(QCoreApplication.translate("BusDatabaseManager", u"Form", None)) self.load_can_database_btn.setText(QCoreApplication.translate("BusDatabaseManager", u"Load CAN database", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("BusDatabaseManager", u"CAN", None)) self.load_lin_database_btn.setText(QCoreApplication.translate("BusDatabaseManager", u"Load LIN database", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("BusDatabaseManager", u"LIN", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/bus_database_manager.ui000066400000000000000000000100161502633300400231750ustar00rootroot00000000000000 BusDatabaseManager 0 0 632 267 Form 1 1 1 1 1 0 CAN 1 1 1 1 1 Load CAN database :/open.png:/open.png Qt::Orientation::Horizontal 40 20 LIN 1 1 1 1 1 Load LIN database :/open.png:/open.png Qt::Orientation::Horizontal 40 20 MinimalListWidget QListWidget
asammdf.gui.widgets.list.h
asammdf-8.5.1/src/asammdf/gui/ui/channel_bar_display_widget.py000066400000000000000000000065041502633300400244340ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'channel_bar_display_widget.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QHBoxLayout, QLabel, QPushButton, QSizePolicy, QVBoxLayout, QWidget) class Ui_ChannelBarDisplay(object): def setupUi(self, ChannelBarDisplay): if not ChannelBarDisplay.objectName(): ChannelBarDisplay.setObjectName(u"ChannelBarDisplay") ChannelBarDisplay.resize(168, 46) ChannelBarDisplay.setMinimumSize(QSize(40, 46)) ChannelBarDisplay.setMaximumSize(QSize(16777215, 46)) self.verticalLayout = QVBoxLayout(ChannelBarDisplay) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.layout = QHBoxLayout() self.layout.setObjectName(u"layout") self.color_btn = QPushButton(ChannelBarDisplay) self.color_btn.setObjectName(u"color_btn") sizePolicy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.color_btn.sizePolicy().hasHeightForWidth()) self.color_btn.setSizePolicy(sizePolicy) self.color_btn.setMinimumSize(QSize(16, 16)) self.color_btn.setMaximumSize(QSize(16, 16)) self.color_btn.setAutoFillBackground(False) self.color_btn.setFlat(False) self.layout.addWidget(self.color_btn) self.name = QLabel(ChannelBarDisplay) self.name.setObjectName(u"name") sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Preferred) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.name.sizePolicy().hasHeightForWidth()) self.name.setSizePolicy(sizePolicy1) self.name.setMinimumSize(QSize(130, 40)) self.name.setMaximumSize(QSize(16777215, 40)) self.name.setMouseTracking(False) self.name.setTextFormat(Qt.TextFormat.PlainText) self.name.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByMouse) self.layout.addWidget(self.name) self.verticalLayout.addLayout(self.layout) self.retranslateUi(ChannelBarDisplay) QMetaObject.connectSlotsByName(ChannelBarDisplay) # setupUi def retranslateUi(self, ChannelBarDisplay): ChannelBarDisplay.setWindowTitle(QCoreApplication.translate("ChannelBarDisplay", u"Form", None)) self.color_btn.setText("") self.name.setText(QCoreApplication.translate("ChannelBarDisplay", u"MAIN CLOCK", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/channel_bar_display_widget.ui000066400000000000000000000055551502633300400244260ustar00rootroot00000000000000 ChannelBarDisplay 0 0 168 46 40 46 16777215 46 Form 1 1 1 1 1 0 0 16 16 16 16 false false 0 0 130 40 16777215 40 false MAIN CLOCK Qt::TextFormat::PlainText Qt::TextInteractionFlag::LinksAccessibleByMouse asammdf-8.5.1/src/asammdf/gui/ui/channel_group_info_widget.py000066400000000000000000000205611502633300400243110ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'channel_group_info_widget.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QCheckBox, QGroupBox, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPlainTextEdit, QScrollArea, QScrollBar, QSizePolicy, QSpacerItem, QSplitter, QTabWidget, QVBoxLayout, QWidget) class Ui_ChannelGroupInfo(object): def setupUi(self, ChannelGroupInfo): if not ChannelGroupInfo.objectName(): ChannelGroupInfo.setObjectName(u"ChannelGroupInfo") ChannelGroupInfo.resize(926, 558) self.verticalLayout_2 = QVBoxLayout(ChannelGroupInfo) self.verticalLayout_2.setSpacing(1) self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.verticalLayout_2.setContentsMargins(1, 1, 1, 1) self.tabs = QTabWidget(ChannelGroupInfo) self.tabs.setObjectName(u"tabs") font = QFont() font.setFamilies([u"Consolas"]) font.setPointSize(8) self.tabs.setFont(font) self.ta_widet = QWidget() self.ta_widet.setObjectName(u"ta_widet") self.horizontalLayout = QHBoxLayout(self.ta_widet) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.groupBox = QGroupBox(self.ta_widet) self.groupBox.setObjectName(u"groupBox") self.groupBox.setFlat(False) self.verticalLayout_4 = QVBoxLayout(self.groupBox) self.verticalLayout_4.setSpacing(1) self.verticalLayout_4.setObjectName(u"verticalLayout_4") self.verticalLayout_4.setContentsMargins(1, 1, 1, 1) self.scrollArea = QScrollArea(self.groupBox) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 443, 497)) self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_3.setSpacing(1) self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.verticalLayout_3.setContentsMargins(1, 1, 1, 1) self.channel_group_label = QLabel(self.scrollAreaWidgetContents) self.channel_group_label.setObjectName(u"channel_group_label") self.channel_group_label.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByMouse|Qt.TextInteractionFlag.TextSelectableByKeyboard|Qt.TextInteractionFlag.TextSelectableByMouse) self.verticalLayout_3.addWidget(self.channel_group_label) self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_3.addItem(self.verticalSpacer_3) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.verticalLayout_4.addWidget(self.scrollArea) self.horizontalLayout.addWidget(self.groupBox) self.groupBox_3 = QGroupBox(self.ta_widet) self.groupBox_3.setObjectName(u"groupBox_3") self.verticalLayout_5 = QVBoxLayout(self.groupBox_3) self.verticalLayout_5.setSpacing(1) self.verticalLayout_5.setObjectName(u"verticalLayout_5") self.verticalLayout_5.setContentsMargins(1, 1, 1, 1) self.scrollArea_3 = QScrollArea(self.groupBox_3) self.scrollArea_3.setObjectName(u"scrollArea_3") self.scrollArea_3.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 442, 497)) self.verticalLayout = QVBoxLayout(self.scrollAreaWidgetContents_3) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.source_label = QLabel(self.scrollAreaWidgetContents_3) self.source_label.setObjectName(u"source_label") self.source_label.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByMouse|Qt.TextInteractionFlag.TextSelectableByKeyboard|Qt.TextInteractionFlag.TextSelectableByMouse) self.verticalLayout.addWidget(self.source_label) self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout.addItem(self.verticalSpacer_2) self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) self.verticalLayout_5.addWidget(self.scrollArea_3) self.horizontalLayout.addWidget(self.groupBox_3) self.tabs.addTab(self.ta_widet, "") self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") self.horizontalLayout_3 = QHBoxLayout(self.tab_2) self.horizontalLayout_3.setSpacing(1) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.horizontalLayout_3.setContentsMargins(1, 1, 1, 1) self.splitter = QSplitter(self.tab_2) self.splitter.setObjectName(u"splitter") self.splitter.setOrientation(Qt.Orientation.Horizontal) self.layoutWidget = QWidget(self.splitter) self.layoutWidget.setObjectName(u"layoutWidget") self.verticalLayout_6 = QVBoxLayout(self.layoutWidget) self.verticalLayout_6.setSpacing(1) self.verticalLayout_6.setObjectName(u"verticalLayout_6") self.verticalLayout_6.setContentsMargins(0, 0, 0, 0) self.wrap = QCheckBox(self.layoutWidget) self.wrap.setObjectName(u"wrap") self.wrap.setChecked(True) self.verticalLayout_6.addWidget(self.wrap) self.channels = QListWidget(self.layoutWidget) self.channels.setObjectName(u"channels") self.verticalLayout_6.addWidget(self.channels) self.splitter.addWidget(self.layoutWidget) self.display = QPlainTextEdit(self.splitter) self.display.setObjectName(u"display") self.display.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.display.setUndoRedoEnabled(False) self.display.setLineWrapMode(QPlainTextEdit.LineWrapMode.WidgetWidth) self.display.setReadOnly(True) self.splitter.addWidget(self.display) self.horizontalLayout_3.addWidget(self.splitter) self.scroll = QScrollBar(self.tab_2) self.scroll.setObjectName(u"scroll") self.scroll.setMaximum(9999) self.scroll.setOrientation(Qt.Orientation.Vertical) self.horizontalLayout_3.addWidget(self.scroll) self.tabs.addTab(self.tab_2, "") self.verticalLayout_2.addWidget(self.tabs) self.retranslateUi(ChannelGroupInfo) self.tabs.setCurrentIndex(0) QMetaObject.connectSlotsByName(ChannelGroupInfo) # setupUi def retranslateUi(self, ChannelGroupInfo): ChannelGroupInfo.setWindowTitle(QCoreApplication.translate("ChannelGroupInfo", u"Form", None)) self.groupBox.setTitle(QCoreApplication.translate("ChannelGroupInfo", u"Channel Group", None)) self.channel_group_label.setText(QCoreApplication.translate("ChannelGroupInfo", u"Channel group metadata", None)) self.groupBox_3.setTitle(QCoreApplication.translate("ChannelGroupInfo", u"Source", None)) self.source_label.setText(QCoreApplication.translate("ChannelGroupInfo", u"No source", None)) self.tabs.setTabText(self.tabs.indexOf(self.ta_widet), QCoreApplication.translate("ChannelGroupInfo", u"Channel group CGBLOCK", None)) self.wrap.setText(QCoreApplication.translate("ChannelGroupInfo", u"Text wrap", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab_2), QCoreApplication.translate("ChannelGroupInfo", u"Raw bytes", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/channel_group_info_widget.ui000066400000000000000000000216561502633300400243040ustar00rootroot00000000000000 ChannelGroupInfo 0 0 926 558 Form 1 1 1 1 1 Consolas 8 0 Channel group CGBLOCK 1 1 1 1 1 Channel Group false 1 1 1 1 1 true 0 0 443 497 1 1 1 1 1 Channel group metadata Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse Qt::Orientation::Vertical 20 40 Source 1 1 1 1 1 true 0 0 442 497 1 1 1 1 1 No source Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse Qt::Orientation::Vertical 20 40 Raw bytes 1 1 1 1 1 Qt::Orientation::Horizontal 1 Text wrap true Qt::ScrollBarPolicy::ScrollBarAlwaysOff false QPlainTextEdit::LineWrapMode::WidgetWidth true 9999 Qt::Orientation::Vertical asammdf-8.5.1/src/asammdf/gui/ui/channel_info_widget.py000066400000000000000000000164641502633300400231040ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'channel_info_widget.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout, QLabel, QScrollArea, QSizePolicy, QSpacerItem, QVBoxLayout, QWidget) class Ui_ChannelInfo(object): def setupUi(self, ChannelInfo): if not ChannelInfo.objectName(): ChannelInfo.setObjectName(u"ChannelInfo") ChannelInfo.resize(926, 558) self.horizontalLayout = QHBoxLayout(ChannelInfo) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.groupBox = QGroupBox(ChannelInfo) self.groupBox.setObjectName(u"groupBox") font = QFont() font.setFamilies([u"Consolas"]) font.setPointSize(8) self.groupBox.setFont(font) self.groupBox.setFlat(False) self.verticalLayout_4 = QVBoxLayout(self.groupBox) self.verticalLayout_4.setSpacing(1) self.verticalLayout_4.setObjectName(u"verticalLayout_4") self.verticalLayout_4.setContentsMargins(1, 1, 1, 1) self.scrollArea = QScrollArea(self.groupBox) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 295, 529)) self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_3.setSpacing(1) self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.verticalLayout_3.setContentsMargins(1, 1, 1, 1) self.channel_label = QLabel(self.scrollAreaWidgetContents) self.channel_label.setObjectName(u"channel_label") self.channel_label.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByMouse|Qt.TextInteractionFlag.TextSelectableByKeyboard|Qt.TextInteractionFlag.TextSelectableByMouse) self.verticalLayout_3.addWidget(self.channel_label) self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_3.addItem(self.verticalSpacer_3) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.verticalLayout_4.addWidget(self.scrollArea) self.horizontalLayout.addWidget(self.groupBox) self.groupBox_2 = QGroupBox(ChannelInfo) self.groupBox_2.setObjectName(u"groupBox_2") self.groupBox_2.setFont(font) self.verticalLayout_6 = QVBoxLayout(self.groupBox_2) self.verticalLayout_6.setSpacing(1) self.verticalLayout_6.setObjectName(u"verticalLayout_6") self.verticalLayout_6.setContentsMargins(1, 1, 1, 1) self.scrollArea_2 = QScrollArea(self.groupBox_2) self.scrollArea_2.setObjectName(u"scrollArea_2") self.scrollArea_2.setWidgetResizable(True) self.scrollAreaWidgetContents_2 = QWidget() self.scrollAreaWidgetContents_2.setObjectName(u"scrollAreaWidgetContents_2") self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 294, 529)) self.verticalLayout_2 = QVBoxLayout(self.scrollAreaWidgetContents_2) self.verticalLayout_2.setSpacing(1) self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.verticalLayout_2.setContentsMargins(1, 1, 1, 1) self.conversion_label = QLabel(self.scrollAreaWidgetContents_2) self.conversion_label.setObjectName(u"conversion_label") self.conversion_label.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByMouse|Qt.TextInteractionFlag.TextSelectableByKeyboard|Qt.TextInteractionFlag.TextSelectableByMouse) self.verticalLayout_2.addWidget(self.conversion_label) self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_2.addItem(self.verticalSpacer) self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) self.verticalLayout_6.addWidget(self.scrollArea_2) self.horizontalLayout.addWidget(self.groupBox_2) self.groupBox_3 = QGroupBox(ChannelInfo) self.groupBox_3.setObjectName(u"groupBox_3") self.groupBox_3.setFont(font) self.verticalLayout_5 = QVBoxLayout(self.groupBox_3) self.verticalLayout_5.setSpacing(1) self.verticalLayout_5.setObjectName(u"verticalLayout_5") self.verticalLayout_5.setContentsMargins(1, 1, 1, 1) self.scrollArea_3 = QScrollArea(self.groupBox_3) self.scrollArea_3.setObjectName(u"scrollArea_3") self.scrollArea_3.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 295, 529)) self.verticalLayout = QVBoxLayout(self.scrollAreaWidgetContents_3) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.source_label = QLabel(self.scrollAreaWidgetContents_3) self.source_label.setObjectName(u"source_label") self.source_label.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByMouse|Qt.TextInteractionFlag.TextSelectableByKeyboard|Qt.TextInteractionFlag.TextSelectableByMouse) self.verticalLayout.addWidget(self.source_label) self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout.addItem(self.verticalSpacer_2) self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) self.verticalLayout_5.addWidget(self.scrollArea_3) self.horizontalLayout.addWidget(self.groupBox_3) self.retranslateUi(ChannelInfo) QMetaObject.connectSlotsByName(ChannelInfo) # setupUi def retranslateUi(self, ChannelInfo): ChannelInfo.setWindowTitle(QCoreApplication.translate("ChannelInfo", u"Form", None)) self.groupBox.setTitle(QCoreApplication.translate("ChannelInfo", u"Channel", None)) self.channel_label.setText(QCoreApplication.translate("ChannelInfo", u"Channel metadata", None)) self.groupBox_2.setTitle(QCoreApplication.translate("ChannelInfo", u"Conversion", None)) self.conversion_label.setText(QCoreApplication.translate("ChannelInfo", u"No conversion", None)) self.groupBox_3.setTitle(QCoreApplication.translate("ChannelInfo", u"Source", None)) self.source_label.setText(QCoreApplication.translate("ChannelInfo", u"No source", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/channel_info_widget.ui000066400000000000000000000201311502633300400230530ustar00rootroot00000000000000 ChannelInfo 0 0 926 558 Form 1 1 1 1 1 Consolas 8 Channel false 1 1 1 1 1 true 0 0 295 529 1 1 1 1 1 Channel metadata Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse Qt::Orientation::Vertical 20 40 Consolas 8 Conversion 1 1 1 1 1 true 0 0 294 529 1 1 1 1 1 No conversion Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse Qt::Orientation::Vertical 20 40 Consolas 8 Source 1 1 1 1 1 true 0 0 295 529 1 1 1 1 1 No source Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse Qt::Orientation::Vertical 20 40 asammdf-8.5.1/src/asammdf/gui/ui/channel_stats.py000066400000000000000000001154731502633300400217440ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'channel_stats.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QAbstractScrollArea, QApplication, QComboBox, QGridLayout, QGroupBox, QLabel, QScrollArea, QSizePolicy, QSpacerItem, QTextEdit, QVBoxLayout, QWidget) class Ui_ChannelStats(object): def setupUi(self, ChannelStats): if not ChannelStats.objectName(): ChannelStats.setObjectName(u"ChannelStats") ChannelStats.resize(315, 852) font = QFont() font.setFamilies([u"Roboto Condensed"]) font.setPointSize(10) ChannelStats.setFont(font) self.verticalLayout_2 = QVBoxLayout(ChannelStats) self.verticalLayout_2.setSpacing(1) self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.verticalLayout_2.setContentsMargins(1, 1, 1, 1) self.scrollArea = QScrollArea(ChannelStats) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 309, 846)) self.verticalLayout = QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.gridLayout = QGridLayout() self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.visible_group = QGroupBox(self.scrollAreaWidgetContents) self.visible_group.setObjectName(u"visible_group") self.gridLayout_3 = QGridLayout(self.visible_group) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setHorizontalSpacing(1) self.gridLayout_3.setVerticalSpacing(1) self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.visible_start = QLabel(self.visible_group) self.visible_start.setObjectName(u"visible_start") self.visible_start.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_start, 0, 1, 1, 1) self.unit7 = QLabel(self.visible_group) self.unit7.setObjectName(u"unit7") self.unit7.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.unit7, 8, 2, 1, 1) self.label_10 = QLabel(self.visible_group) self.label_10.setObjectName(u"label_10") self.gridLayout_3.addWidget(self.label_10, 4, 0, 1, 1) self.label_35 = QLabel(self.visible_group) self.label_35.setObjectName(u"label_35") self.gridLayout_3.addWidget(self.label_35, 7, 0, 1, 1) self.unit5 = QLabel(self.visible_group) self.unit5.setObjectName(u"unit5") self.unit5.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.unit5, 3, 2, 1, 1) self.visible_stop = QLabel(self.visible_group) self.visible_stop.setObjectName(u"visible_stop") self.visible_stop.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_stop, 1, 1, 1, 1) self.label_19 = QLabel(self.visible_group) self.label_19.setObjectName(u"label_19") self.gridLayout_3.addWidget(self.label_19, 8, 0, 1, 1) self.label_9 = QLabel(self.visible_group) self.label_9.setObjectName(u"label_9") self.gridLayout_3.addWidget(self.label_9, 3, 0, 1, 1) self.visible_rms = QLabel(self.visible_group) self.visible_rms.setObjectName(u"visible_rms") self.visible_rms.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_rms, 6, 1, 1, 1) self.unit17 = QLabel(self.visible_group) self.unit17.setObjectName(u"unit17") self.unit17.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.unit17, 7, 2, 1, 1) self.label_16 = QLabel(self.visible_group) self.label_16.setObjectName(u"label_16") self.gridLayout_3.addWidget(self.label_16, 2, 0, 1, 1) self.visible_min = QLabel(self.visible_group) self.visible_min.setObjectName(u"visible_min") self.visible_min.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_min, 3, 1, 1, 1) self.visible_std = QLabel(self.visible_group) self.visible_std.setObjectName(u"visible_std") self.visible_std.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_std, 7, 1, 1, 1) self.xunit4 = QLabel(self.visible_group) self.xunit4.setObjectName(u"xunit4") self.xunit4.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.xunit4, 0, 2, 1, 1) self.label_39 = QLabel(self.visible_group) self.label_39.setObjectName(u"label_39") self.gridLayout_3.addWidget(self.label_39, 9, 0, 1, 1) self.label_8 = QLabel(self.visible_group) self.label_8.setObjectName(u"label_8") self.gridLayout_3.addWidget(self.label_8, 1, 0, 1, 1) self.label_7 = QLabel(self.visible_group) self.label_7.setObjectName(u"label_7") self.gridLayout_3.addWidget(self.label_7, 0, 0, 1, 1) self.unit6 = QLabel(self.visible_group) self.unit6.setObjectName(u"unit6") self.unit6.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.unit6, 4, 2, 1, 1) self.xunit6 = QLabel(self.visible_group) self.xunit6.setObjectName(u"xunit6") self.xunit6.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.xunit6, 2, 2, 1, 1) self.visible_delta = QLabel(self.visible_group) self.visible_delta.setObjectName(u"visible_delta") self.visible_delta.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_delta, 8, 1, 1, 1) self.label_31 = QLabel(self.visible_group) self.label_31.setObjectName(u"label_31") self.gridLayout_3.addWidget(self.label_31, 6, 0, 1, 1) self.unit12 = QLabel(self.visible_group) self.unit12.setObjectName(u"unit12") self.unit12.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.unit12, 5, 2, 1, 1) self.label_30 = QLabel(self.visible_group) self.label_30.setObjectName(u"label_30") self.gridLayout_3.addWidget(self.label_30, 5, 0, 1, 1) self.visible_max = QLabel(self.visible_group) self.visible_max.setObjectName(u"visible_max") self.visible_max.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_max, 4, 1, 1, 1) self.visible_delta_t = QLabel(self.visible_group) self.visible_delta_t.setObjectName(u"visible_delta_t") self.visible_delta_t.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_delta_t, 2, 1, 1, 1) self.visible_average = QLabel(self.visible_group) self.visible_average.setObjectName(u"visible_average") self.visible_average.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_average, 5, 1, 1, 1) self.xunit5 = QLabel(self.visible_group) self.xunit5.setObjectName(u"xunit5") self.xunit5.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.xunit5, 1, 2, 1, 1) self.unit13 = QLabel(self.visible_group) self.unit13.setObjectName(u"unit13") self.unit13.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.unit13, 6, 2, 1, 1) self.label_40 = QLabel(self.visible_group) self.label_40.setObjectName(u"label_40") self.gridLayout_3.addWidget(self.label_40, 10, 0, 1, 1) self.visible_gradient_unit = QLabel(self.visible_group) self.visible_gradient_unit.setObjectName(u"visible_gradient_unit") self.visible_gradient_unit.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_gradient_unit, 9, 2, 1, 1) self.visible_integral_unit = QLabel(self.visible_group) self.visible_integral_unit.setObjectName(u"visible_integral_unit") self.visible_integral_unit.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_integral_unit, 10, 2, 1, 1) self.visible_gradient = QLabel(self.visible_group) self.visible_gradient.setObjectName(u"visible_gradient") self.visible_gradient.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_gradient, 9, 1, 1, 1) self.visible_integral = QLabel(self.visible_group) self.visible_integral.setObjectName(u"visible_integral") self.visible_integral.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_3.addWidget(self.visible_integral, 10, 1, 1, 1) self.gridLayout_3.setColumnStretch(1, 1) self.gridLayout.addWidget(self.visible_group, 4, 0, 1, 2) self.overall_group = QGroupBox(self.scrollAreaWidgetContents) self.overall_group.setObjectName(u"overall_group") self.gridLayout_2 = QGridLayout(self.overall_group) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setHorizontalSpacing(1) self.gridLayout_2.setVerticalSpacing(1) self.gridLayout_2.setContentsMargins(1, 1, 1, 1) self.xunit7 = QLabel(self.overall_group) self.xunit7.setObjectName(u"xunit7") self.xunit7.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.xunit7, 0, 2, 1, 1) self.overall_delta = QLabel(self.overall_group) self.overall_delta.setObjectName(u"overall_delta") self.overall_delta.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_delta, 9, 1, 1, 1) self.overall_max = QLabel(self.overall_group) self.overall_max.setObjectName(u"overall_max") self.overall_max.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_max, 5, 1, 1, 1) self.overall_stop = QLabel(self.overall_group) self.overall_stop.setObjectName(u"overall_stop") self.overall_stop.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_stop, 1, 1, 1, 1) self.label_43 = QLabel(self.overall_group) self.label_43.setObjectName(u"label_43") self.gridLayout_2.addWidget(self.label_43, 9, 0, 1, 1) self.label_6 = QLabel(self.overall_group) self.label_6.setObjectName(u"label_6") self.gridLayout_2.addWidget(self.label_6, 5, 0, 1, 1) self.overall_std = QLabel(self.overall_group) self.overall_std.setObjectName(u"overall_std") self.overall_std.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_std, 8, 1, 1, 1) self.label_3 = QLabel(self.overall_group) self.label_3.setObjectName(u"label_3") self.gridLayout_2.addWidget(self.label_3, 0, 0, 1, 1) self.label_32 = QLabel(self.overall_group) self.label_32.setObjectName(u"label_32") self.gridLayout_2.addWidget(self.label_32, 6, 0, 1, 1) self.unit9 = QLabel(self.overall_group) self.unit9.setObjectName(u"unit9") self.unit9.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.unit9, 5, 2, 1, 1) self.label_41 = QLabel(self.overall_group) self.label_41.setObjectName(u"label_41") self.gridLayout_2.addWidget(self.label_41, 10, 0, 1, 1) self.overall_rms = QLabel(self.overall_group) self.overall_rms.setObjectName(u"overall_rms") self.overall_rms.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_rms, 7, 1, 1, 1) self.xunit8 = QLabel(self.overall_group) self.xunit8.setObjectName(u"xunit8") self.xunit8.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.xunit8, 1, 2, 1, 1) self.overall_average = QLabel(self.overall_group) self.overall_average.setObjectName(u"overall_average") self.overall_average.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_average, 6, 1, 1, 1) self.unit8 = QLabel(self.overall_group) self.unit8.setObjectName(u"unit8") self.unit8.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.unit8, 4, 2, 1, 1) self.label_4 = QLabel(self.overall_group) self.label_4.setObjectName(u"label_4") self.gridLayout_2.addWidget(self.label_4, 1, 0, 1, 1) self.label_5 = QLabel(self.overall_group) self.label_5.setObjectName(u"label_5") self.gridLayout_2.addWidget(self.label_5, 4, 0, 1, 1) self.unit18 = QLabel(self.overall_group) self.unit18.setObjectName(u"unit18") self.unit18.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.unit18, 8, 2, 1, 1) self.overall_integral_unit = QLabel(self.overall_group) self.overall_integral_unit.setObjectName(u"overall_integral_unit") self.overall_integral_unit.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_integral_unit, 11, 2, 1, 1) self.unit19 = QLabel(self.overall_group) self.unit19.setObjectName(u"unit19") self.unit19.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.unit19, 9, 2, 1, 1) self.overall_gradient_unit = QLabel(self.overall_group) self.overall_gradient_unit.setObjectName(u"overall_gradient_unit") self.overall_gradient_unit.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_gradient_unit, 10, 2, 1, 1) self.unit14 = QLabel(self.overall_group) self.unit14.setObjectName(u"unit14") self.unit14.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.unit14, 6, 2, 1, 1) self.label_33 = QLabel(self.overall_group) self.label_33.setObjectName(u"label_33") self.gridLayout_2.addWidget(self.label_33, 7, 0, 1, 1) self.unit15 = QLabel(self.overall_group) self.unit15.setObjectName(u"unit15") self.unit15.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.unit15, 7, 2, 1, 1) self.label_36 = QLabel(self.overall_group) self.label_36.setObjectName(u"label_36") self.gridLayout_2.addWidget(self.label_36, 8, 0, 1, 1) self.label_42 = QLabel(self.overall_group) self.label_42.setObjectName(u"label_42") self.gridLayout_2.addWidget(self.label_42, 11, 0, 1, 1) self.overall_start = QLabel(self.overall_group) self.overall_start.setObjectName(u"overall_start") self.overall_start.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_start, 0, 1, 1, 1) self.overall_min = QLabel(self.overall_group) self.overall_min.setObjectName(u"overall_min") sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.overall_min.sizePolicy().hasHeightForWidth()) self.overall_min.setSizePolicy(sizePolicy) self.overall_min.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_min, 4, 1, 1, 1) self.overall_integral = QLabel(self.overall_group) self.overall_integral.setObjectName(u"overall_integral") self.overall_integral.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_integral, 11, 1, 1, 1) self.overall_gradient = QLabel(self.overall_group) self.overall_gradient.setObjectName(u"overall_gradient") self.overall_gradient.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_gradient, 10, 1, 1, 1) self.label_44 = QLabel(self.overall_group) self.label_44.setObjectName(u"label_44") self.gridLayout_2.addWidget(self.label_44, 3, 0, 1, 1) self.overall_delta_t = QLabel(self.overall_group) self.overall_delta_t.setObjectName(u"overall_delta_t") self.overall_delta_t.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.overall_delta_t, 3, 1, 1, 1) self.xunit9 = QLabel(self.overall_group) self.xunit9.setObjectName(u"xunit9") self.xunit9.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_2.addWidget(self.xunit9, 3, 2, 1, 1) self.gridLayout_2.setColumnStretch(1, 1) self.gridLayout.addWidget(self.overall_group, 5, 0, 1, 2) self.cursor_group = QGroupBox(self.scrollAreaWidgetContents) self.cursor_group.setObjectName(u"cursor_group") self.cursor_group.setFlat(False) self.cursor_group.setCheckable(False) self.gridLayout_4 = QGridLayout(self.cursor_group) self.gridLayout_4.setObjectName(u"gridLayout_4") self.gridLayout_4.setHorizontalSpacing(1) self.gridLayout_4.setVerticalSpacing(1) self.gridLayout_4.setContentsMargins(1, 1, 1, 1) self.cursor_t = QLabel(self.cursor_group) self.cursor_t.setObjectName(u"cursor_t") self.cursor_t.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_4.addWidget(self.cursor_t, 0, 1, 1, 1) self.label_12 = QLabel(self.cursor_group) self.label_12.setObjectName(u"label_12") self.gridLayout_4.addWidget(self.label_12, 0, 0, 1, 1) self.cursor_value = QLabel(self.cursor_group) self.cursor_value.setObjectName(u"cursor_value") self.cursor_value.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_4.addWidget(self.cursor_value, 1, 1, 1, 1) self.label_11 = QLabel(self.cursor_group) self.label_11.setObjectName(u"label_11") self.gridLayout_4.addWidget(self.label_11, 1, 0, 1, 1) self.xunit0 = QLabel(self.cursor_group) self.xunit0.setObjectName(u"xunit0") self.xunit0.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_4.addWidget(self.xunit0, 0, 2, 1, 1) self.unit1 = QLabel(self.cursor_group) self.unit1.setObjectName(u"unit1") self.unit1.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_4.addWidget(self.unit1, 1, 2, 1, 1) self.gridLayout_4.setColumnStretch(1, 1) self.gridLayout.addWidget(self.cursor_group, 2, 0, 1, 2) self.name = QTextEdit(self.scrollAreaWidgetContents) self.name.setObjectName(u"name") sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(1) sizePolicy1.setHeightForWidth(self.name.sizePolicy().hasHeightForWidth()) self.name.setSizePolicy(sizePolicy1) self.name.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.name.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.name.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) self.name.setReadOnly(True) self.gridLayout.addWidget(self.name, 0, 0, 1, 2) self.region_group = QGroupBox(self.scrollAreaWidgetContents) self.region_group.setObjectName(u"region_group") self.gridLayout_5 = QGridLayout(self.region_group) self.gridLayout_5.setObjectName(u"gridLayout_5") self.gridLayout_5.setHorizontalSpacing(1) self.gridLayout_5.setVerticalSpacing(1) self.gridLayout_5.setContentsMargins(1, 1, 1, 1) self.label_13 = QLabel(self.region_group) self.label_13.setObjectName(u"label_13") self.gridLayout_5.addWidget(self.label_13, 0, 0, 1, 1) self.selected_integral_unit = QLabel(self.region_group) self.selected_integral_unit.setObjectName(u"selected_integral_unit") self.selected_integral_unit.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_integral_unit, 13, 2, 1, 1) self.selected_rms = QLabel(self.region_group) self.selected_rms.setObjectName(u"selected_rms") self.selected_rms.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_rms, 9, 1, 1, 1) self.label_29 = QLabel(self.region_group) self.label_29.setObjectName(u"label_29") self.gridLayout_5.addWidget(self.label_29, 9, 0, 1, 1) self.selected_gradient_unit = QLabel(self.region_group) self.selected_gradient_unit.setObjectName(u"selected_gradient_unit") self.selected_gradient_unit.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_gradient_unit, 12, 2, 1, 1) self.selected_start = QLabel(self.region_group) self.selected_start.setObjectName(u"selected_start") self.selected_start.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_start, 0, 1, 1, 1) self.label_15 = QLabel(self.region_group) self.label_15.setObjectName(u"label_15") self.gridLayout_5.addWidget(self.label_15, 1, 0, 1, 1) self.selected_delta_t = QLabel(self.region_group) self.selected_delta_t.setObjectName(u"selected_delta_t") self.selected_delta_t.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_delta_t, 3, 1, 1, 1) self.label_2 = QLabel(self.region_group) self.label_2.setObjectName(u"label_2") self.gridLayout_5.addWidget(self.label_2, 4, 0, 1, 1) self.label_14 = QLabel(self.region_group) self.label_14.setObjectName(u"label_14") self.gridLayout_5.addWidget(self.label_14, 6, 0, 1, 1) self.label = QLabel(self.region_group) self.label.setObjectName(u"label") self.gridLayout_5.addWidget(self.label, 8, 0, 1, 1) self.selected_stop = QLabel(self.region_group) self.selected_stop.setObjectName(u"selected_stop") self.selected_stop.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_stop, 1, 1, 1, 1) self.unit16 = QLabel(self.region_group) self.unit16.setObjectName(u"unit16") self.unit16.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.unit16, 10, 2, 1, 1) self.label_34 = QLabel(self.region_group) self.label_34.setObjectName(u"label_34") self.gridLayout_5.addWidget(self.label_34, 10, 0, 1, 1) self.xunit1 = QLabel(self.region_group) self.xunit1.setObjectName(u"xunit1") self.xunit1.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.xunit1, 0, 2, 1, 1) self.xunit3 = QLabel(self.region_group) self.xunit3.setObjectName(u"xunit3") self.xunit3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.xunit3, 3, 2, 1, 1) self.label_21 = QLabel(self.region_group) self.label_21.setObjectName(u"label_21") self.gridLayout_5.addWidget(self.label_21, 3, 0, 1, 1) self.selected_max = QLabel(self.region_group) self.selected_max.setObjectName(u"selected_max") self.selected_max.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_max, 7, 1, 1, 1) self.label_17 = QLabel(self.region_group) self.label_17.setObjectName(u"label_17") self.gridLayout_5.addWidget(self.label_17, 7, 0, 1, 1) self.label_37 = QLabel(self.region_group) self.label_37.setObjectName(u"label_37") self.gridLayout_5.addWidget(self.label_37, 12, 0, 1, 1) self.selected_std = QLabel(self.region_group) self.selected_std.setObjectName(u"selected_std") self.selected_std.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_std, 10, 1, 1, 1) self.label_18 = QLabel(self.region_group) self.label_18.setObjectName(u"label_18") self.gridLayout_5.addWidget(self.label_18, 11, 0, 1, 1) self.xunit2 = QLabel(self.region_group) self.xunit2.setObjectName(u"xunit2") self.xunit2.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.xunit2, 1, 2, 1, 1) self.unit11 = QLabel(self.region_group) self.unit11.setObjectName(u"unit11") self.unit11.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.unit11, 9, 2, 1, 1) self.selected_min = QLabel(self.region_group) self.selected_min.setObjectName(u"selected_min") self.selected_min.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_min, 6, 1, 1, 1) self.label_38 = QLabel(self.region_group) self.label_38.setObjectName(u"label_38") self.gridLayout_5.addWidget(self.label_38, 13, 0, 1, 1) self.unit3 = QLabel(self.region_group) self.unit3.setObjectName(u"unit3") self.unit3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.unit3, 7, 2, 1, 1) self.selected_delta = QLabel(self.region_group) self.selected_delta.setObjectName(u"selected_delta") self.selected_delta.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_delta, 11, 1, 1, 1) self.selected_integral = QLabel(self.region_group) self.selected_integral.setObjectName(u"selected_integral") self.selected_integral.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_integral, 13, 1, 1, 1) self.unit4 = QLabel(self.region_group) self.unit4.setObjectName(u"unit4") self.unit4.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.unit4, 11, 2, 1, 1) self.selected_average = QLabel(self.region_group) self.selected_average.setObjectName(u"selected_average") self.selected_average.setAutoFillBackground(False) self.selected_average.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_average, 8, 1, 1, 1) self.selected_gradient = QLabel(self.region_group) self.selected_gradient.setObjectName(u"selected_gradient") self.selected_gradient.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_gradient, 12, 1, 1, 1) self.unit10 = QLabel(self.region_group) self.unit10.setObjectName(u"unit10") self.unit10.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.unit10, 8, 2, 1, 1) self.unit2 = QLabel(self.region_group) self.unit2.setObjectName(u"unit2") self.unit2.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.unit2, 6, 2, 1, 1) self.label_20 = QLabel(self.region_group) self.label_20.setObjectName(u"label_20") self.gridLayout_5.addWidget(self.label_20, 5, 0, 1, 1) self.selected_left = QLabel(self.region_group) self.selected_left.setObjectName(u"selected_left") self.selected_left.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_left, 4, 1, 1, 1) self.selected_right = QLabel(self.region_group) self.selected_right.setObjectName(u"selected_right") self.selected_right.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.selected_right, 5, 1, 1, 1) self.unit21 = QLabel(self.region_group) self.unit21.setObjectName(u"unit21") self.unit21.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.unit21, 4, 2, 1, 1) self.unit22 = QLabel(self.region_group) self.unit22.setObjectName(u"unit22") self.unit22.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.gridLayout_5.addWidget(self.unit22, 5, 2, 1, 1) self.gridLayout_5.setColumnStretch(1, 1) self.gridLayout.addWidget(self.region_group, 3, 0, 1, 2) self.precision = QComboBox(self.scrollAreaWidgetContents) self.precision.setObjectName(u"precision") self.gridLayout.addWidget(self.precision, 1, 1, 1, 1) self.label_22 = QLabel(self.scrollAreaWidgetContents) self.label_22.setObjectName(u"label_22") self.gridLayout.addWidget(self.label_22, 1, 0, 1, 1) self.gridLayout.setRowStretch(0, 1) self.gridLayout.setColumnStretch(1, 1) self.verticalLayout.addLayout(self.gridLayout) self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout.addItem(self.verticalSpacer) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.verticalLayout_2.addWidget(self.scrollArea) self.retranslateUi(ChannelStats) QMetaObject.connectSlotsByName(ChannelStats) # setupUi def retranslateUi(self, ChannelStats): ChannelStats.setWindowTitle(QCoreApplication.translate("ChannelStats", u"Form", None)) self.visible_group.setTitle(QCoreApplication.translate("ChannelStats", u"Visible region", None)) self.visible_start.setText("") self.unit7.setText("") self.label_10.setText(QCoreApplication.translate("ChannelStats", u"Max", None)) self.label_35.setText(QCoreApplication.translate("ChannelStats", u"STD", None)) self.unit5.setText("") self.visible_stop.setText("") self.label_19.setText(QCoreApplication.translate("ChannelStats", u"\u0394", None)) self.label_9.setText(QCoreApplication.translate("ChannelStats", u"Min", None)) self.visible_rms.setText("") self.unit17.setText("") self.label_16.setText(QCoreApplication.translate("ChannelStats", u"\u0394t", None)) self.visible_min.setText("") self.visible_std.setText("") self.xunit4.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.label_39.setText(QCoreApplication.translate("ChannelStats", u"Gradient", None)) self.label_8.setText(QCoreApplication.translate("ChannelStats", u"t2", None)) self.label_7.setText(QCoreApplication.translate("ChannelStats", u"t1", None)) self.unit6.setText("") self.xunit6.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.visible_delta.setText("") self.label_31.setText(QCoreApplication.translate("ChannelStats", u"RMS", None)) self.unit12.setText("") self.label_30.setText(QCoreApplication.translate("ChannelStats", u"Avg", None)) self.visible_max.setText("") self.visible_delta_t.setText("") self.visible_average.setText("") self.xunit5.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.unit13.setText("") self.label_40.setText(QCoreApplication.translate("ChannelStats", u"Integral", None)) self.visible_gradient_unit.setText("") self.visible_integral_unit.setText("") self.visible_gradient.setText("") self.visible_integral.setText("") self.overall_group.setTitle(QCoreApplication.translate("ChannelStats", u"Overall", None)) self.xunit7.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.overall_delta.setText("") self.overall_max.setText("") self.overall_stop.setText("") self.label_43.setText(QCoreApplication.translate("ChannelStats", u"\u0394", None)) self.label_6.setText(QCoreApplication.translate("ChannelStats", u"Max", None)) self.overall_std.setText("") self.label_3.setText(QCoreApplication.translate("ChannelStats", u"t1", None)) self.label_32.setText(QCoreApplication.translate("ChannelStats", u"Avg", None)) self.unit9.setText("") self.label_41.setText(QCoreApplication.translate("ChannelStats", u"Grad", None)) self.overall_rms.setText("") self.xunit8.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.overall_average.setText("") self.unit8.setText("") self.label_4.setText(QCoreApplication.translate("ChannelStats", u"t2", None)) self.label_5.setText(QCoreApplication.translate("ChannelStats", u"Min", None)) self.unit18.setText("") self.overall_integral_unit.setText("") self.unit19.setText("") self.overall_gradient_unit.setText("") self.unit14.setText("") self.label_33.setText(QCoreApplication.translate("ChannelStats", u"RMS", None)) self.unit15.setText("") self.label_36.setText(QCoreApplication.translate("ChannelStats", u"STD", None)) self.label_42.setText(QCoreApplication.translate("ChannelStats", u"Integral", None)) self.overall_start.setText("") self.overall_min.setText("") self.overall_integral.setText("") self.overall_gradient.setText("") self.label_44.setText(QCoreApplication.translate("ChannelStats", u"\u0394t", None)) self.overall_delta_t.setText("") self.xunit9.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.cursor_group.setTitle(QCoreApplication.translate("ChannelStats", u"Cursor", None)) self.cursor_t.setText("") self.label_12.setText(QCoreApplication.translate("ChannelStats", u"Time", None)) self.cursor_value.setText("") self.label_11.setText(QCoreApplication.translate("ChannelStats", u"Value", None)) self.xunit0.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.unit1.setText("") self.name.setHtml(QCoreApplication.translate("ChannelStats", u"\n" "\n" "


", None)) self.region_group.setTitle(QCoreApplication.translate("ChannelStats", u"Selected region", None)) self.label_13.setText(QCoreApplication.translate("ChannelStats", u"t1", None)) self.selected_integral_unit.setText("") self.selected_rms.setText("") self.label_29.setText(QCoreApplication.translate("ChannelStats", u"RMS", None)) self.selected_gradient_unit.setText("") self.selected_start.setText("") self.label_15.setText(QCoreApplication.translate("ChannelStats", u"t2", None)) self.selected_delta_t.setText("") self.label_2.setText(QCoreApplication.translate("ChannelStats", u"First", None)) self.label_14.setText(QCoreApplication.translate("ChannelStats", u"Min", None)) self.label.setText(QCoreApplication.translate("ChannelStats", u"Avg", None)) self.selected_stop.setText("") self.unit16.setText("") self.label_34.setText(QCoreApplication.translate("ChannelStats", u"STD", None)) self.xunit1.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.xunit3.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.label_21.setText(QCoreApplication.translate("ChannelStats", u"\u0394t", None)) self.selected_max.setText("") self.label_17.setText(QCoreApplication.translate("ChannelStats", u"Max", None)) self.label_37.setText(QCoreApplication.translate("ChannelStats", u"Gradient", None)) self.selected_std.setText("") self.label_18.setText(QCoreApplication.translate("ChannelStats", u"\u0394", None)) self.xunit2.setText(QCoreApplication.translate("ChannelStats", u" s", None)) self.unit11.setText("") self.selected_min.setText("") self.label_38.setText(QCoreApplication.translate("ChannelStats", u"Integral", None)) self.unit3.setText("") self.selected_delta.setText("") self.selected_integral.setText("") self.unit4.setText("") self.selected_average.setText("") self.selected_gradient.setText("") self.unit10.setText("") self.unit2.setText("") self.label_20.setText(QCoreApplication.translate("ChannelStats", u"Last", None)) self.selected_left.setText("") self.selected_right.setText("") self.unit21.setText("") self.unit22.setText("") self.label_22.setText(QCoreApplication.translate("ChannelStats", u"Precisison", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/channel_stats.ui000066400000000000000000001262311502633300400217230ustar00rootroot00000000000000 ChannelStats 0 0 315 852 Roboto Condensed 10 Form 1 1 1 1 1 Qt::ScrollBarAsNeeded true 0 0 309 846 1 1 1 1 1 1 Visible region 1 1 1 1 1 1 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Max STD Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Δ Min Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Δt Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Gradient t2 t1 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter RMS Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Avg Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Integral Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Overall 1 1 1 1 1 1 s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Δ Max Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter t1 Avg Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Grad Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter t2 Min Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter RMS Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter STD Integral Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Δt Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Cursor false false 1 1 1 1 1 1 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Time Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Value s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 1 Qt::ScrollBarAsNeeded Qt::ScrollBarAlwaysOff QAbstractScrollArea::AdjustToContents true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } hr { height: 1px; border-width: 0; } </style></head><body style=" font-family:'Roboto Condensed'; font-size:10pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Consolas';"><br /></p></body></html> Selected region 1 1 1 1 1 1 t1 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter RMS Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter t2 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter First Min Avg Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter STD s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Δt Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Max Gradient Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Δ s Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Integral Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Last Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Precisison Qt::Vertical 20 40 asammdf-8.5.1/src/asammdf/gui/ui/database_item.py000066400000000000000000000037321502633300400216720ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'database_item.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QHBoxLayout, QLabel, QSizePolicy, QWidget) class Ui_DatabaseItemUI(object): def setupUi(self, DatabaseItemUI): if not DatabaseItemUI.objectName(): DatabaseItemUI.setObjectName(u"DatabaseItemUI") DatabaseItemUI.resize(291, 24) self.horizontalLayout = QHBoxLayout(DatabaseItemUI) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.bus = QComboBox(DatabaseItemUI) self.bus.setObjectName(u"bus") self.horizontalLayout.addWidget(self.bus) self.database = QLabel(DatabaseItemUI) self.database.setObjectName(u"database") self.horizontalLayout.addWidget(self.database) self.horizontalLayout.setStretch(1, 1) self.retranslateUi(DatabaseItemUI) QMetaObject.connectSlotsByName(DatabaseItemUI) # setupUi def retranslateUi(self, DatabaseItemUI): DatabaseItemUI.setWindowTitle(QCoreApplication.translate("DatabaseItemUI", u"Form", None)) self.database.setText(QCoreApplication.translate("DatabaseItemUI", u"TextLabel", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/database_item.ui000066400000000000000000000017721502633300400216610ustar00rootroot00000000000000 DatabaseItemUI 0 0 291 24 Form 1 1 1 1 1 TextLabel asammdf-8.5.1/src/asammdf/gui/ui/define_channel_dialog.py000066400000000000000000000446731502633300400233620ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'define_channel_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QAbstractSpinBox, QApplication, QComboBox, QDialog, QDoubleSpinBox, QFrame, QGridLayout, QGroupBox, QLabel, QLineEdit, QPlainTextEdit, QPushButton, QRadioButton, QScrollArea, QSizePolicy, QSpacerItem, QVBoxLayout, QWidget) from . import resource_rc class Ui_ComputedChannel(object): def setupUi(self, ComputedChannel): if not ComputedChannel.objectName(): ComputedChannel.setObjectName(u"ComputedChannel") ComputedChannel.resize(723, 552) ComputedChannel.setMaximumSize(QSize(16777215, 16777215)) icon = QIcon() icon.addFile(u":/plus.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) ComputedChannel.setWindowIcon(icon) ComputedChannel.setSizeGripEnabled(True) self.gridLayout = QGridLayout(ComputedChannel) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.label_8 = QLabel(ComputedChannel) self.label_8.setObjectName(u"label_8") self.label_8.setAlignment(Qt.AlignmentFlag.AlignLeading|Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignTop) self.gridLayout.addWidget(self.label_8, 7, 0, 1, 1) self.comment = QPlainTextEdit(ComputedChannel) self.comment.setObjectName(u"comment") self.gridLayout.addWidget(self.comment, 7, 1, 1, 4) self.apply_btn = QPushButton(ComputedChannel) self.apply_btn.setObjectName(u"apply_btn") self.gridLayout.addWidget(self.apply_btn, 9, 3, 1, 1) self.cancel_btn = QPushButton(ComputedChannel) self.cancel_btn.setObjectName(u"cancel_btn") self.gridLayout.addWidget(self.cancel_btn, 9, 4, 1, 1) self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout.addItem(self.horizontalSpacer_3, 9, 1, 1, 1) self.unit = QLineEdit(ComputedChannel) self.unit.setObjectName(u"unit") self.gridLayout.addWidget(self.unit, 8, 1, 1, 1) self.label_7 = QLabel(ComputedChannel) self.label_7.setObjectName(u"label_7") self.gridLayout.addWidget(self.label_7, 5, 0, 1, 1) self.groupBox_2 = QGroupBox(ComputedChannel) self.groupBox_2.setObjectName(u"groupBox_2") self.gridLayout_2 = QGridLayout(self.groupBox_2) self.gridLayout_2.setSpacing(1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(1, 1, 1, 1) self.complete_signal = QRadioButton(self.groupBox_2) self.complete_signal.setObjectName(u"complete_signal") self.complete_signal.setChecked(False) self.gridLayout_2.addWidget(self.complete_signal, 2, 0, 1, 1) self.sample_by_sample = QRadioButton(self.groupBox_2) self.sample_by_sample.setObjectName(u"sample_by_sample") self.sample_by_sample.setChecked(True) self.gridLayout_2.addWidget(self.sample_by_sample, 0, 0, 1, 1) self.label_25 = QLabel(self.groupBox_2) self.label_25.setObjectName(u"label_25") self.gridLayout_2.addWidget(self.label_25, 2, 1, 1, 1) self.label_24 = QLabel(self.groupBox_2) self.label_24.setObjectName(u"label_24") self.label_24.setTextFormat(Qt.TextFormat.RichText) self.label_24.setWordWrap(False) self.gridLayout_2.addWidget(self.label_24, 0, 1, 1, 1) self.line = QFrame(self.groupBox_2) self.line.setObjectName(u"line") self.line.setFrameShape(QFrame.Shape.HLine) self.line.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_2.addWidget(self.line, 1, 1, 1, 1) self.gridLayout_2.setColumnStretch(1, 1) self.gridLayout.addWidget(self.groupBox_2, 1, 0, 1, 5) self.groupBox_3 = QGroupBox(ComputedChannel) self.groupBox_3.setObjectName(u"groupBox_3") self.gridLayout_8 = QGridLayout(self.groupBox_3) self.gridLayout_8.setSpacing(1) self.gridLayout_8.setObjectName(u"gridLayout_8") self.gridLayout_8.setContentsMargins(1, 1, 1, 1) self.horizontalSpacer_8 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_8.addItem(self.horizontalSpacer_8, 1, 2, 1, 1) self.trigger_interval = QDoubleSpinBox(self.groupBox_3) self.trigger_interval.setObjectName(u"trigger_interval") self.trigger_interval.setMinimumSize(QSize(121, 0)) self.trigger_interval.setDecimals(9) self.trigger_interval.setMinimum(0.000001000000000) self.trigger_interval.setMaximum(10.000000000000000) self.trigger_interval.setSingleStep(0.100000000000000) self.trigger_interval.setStepType(QAbstractSpinBox.StepType.DefaultStepType) self.trigger_interval.setValue(0.010000000000000) self.gridLayout_8.addWidget(self.trigger_interval, 1, 1, 1, 1) self.trigger_channel = QLineEdit(self.groupBox_3) self.trigger_channel.setObjectName(u"trigger_channel") self.gridLayout_8.addWidget(self.trigger_channel, 4, 1, 1, 2) self.triggering_on_channel = QRadioButton(self.groupBox_3) self.triggering_on_channel.setObjectName(u"triggering_on_channel") self.gridLayout_8.addWidget(self.triggering_on_channel, 4, 0, 1, 1) self.triggering_on_interval = QRadioButton(self.groupBox_3) self.triggering_on_interval.setObjectName(u"triggering_on_interval") self.gridLayout_8.addWidget(self.triggering_on_interval, 1, 0, 1, 1) self.trigger_search_btn = QPushButton(self.groupBox_3) self.trigger_search_btn.setObjectName(u"trigger_search_btn") icon1 = QIcon() icon1.addFile(u":/search.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.trigger_search_btn.setIcon(icon1) self.gridLayout_8.addWidget(self.trigger_search_btn, 4, 3, 1, 1) self.triggering_on_all = QRadioButton(self.groupBox_3) self.triggering_on_all.setObjectName(u"triggering_on_all") self.triggering_on_all.setMinimumSize(QSize(155, 0)) self.triggering_on_all.setChecked(True) self.gridLayout_8.addWidget(self.triggering_on_all, 0, 0, 1, 1) self.gridLayout.addWidget(self.groupBox_3, 0, 0, 1, 5) self.groupBox = QGroupBox(ComputedChannel) self.groupBox.setObjectName(u"groupBox") self.verticalLayout = QVBoxLayout(self.groupBox) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.scrollArea = QScrollArea(self.groupBox) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setFrameShape(QFrame.Shape.NoFrame) self.scrollArea.setLineWidth(0) self.scrollArea.setWidgetResizable(True) self.args_widget = QWidget() self.args_widget.setObjectName(u"args_widget") self.args_widget.setGeometry(QRect(0, 0, 717, 54)) self.arg_layout = QGridLayout(self.args_widget) self.arg_layout.setSpacing(1) self.arg_layout.setObjectName(u"arg_layout") self.arg_layout.setContentsMargins(1, 1, 1, 1) self.show_definition_btn = QPushButton(self.args_widget) self.show_definition_btn.setObjectName(u"show_definition_btn") icon2 = QIcon() icon2.addFile(u":/info.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.show_definition_btn.setIcon(icon2) self.arg_layout.addWidget(self.show_definition_btn, 0, 2, 1, 1) self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.arg_layout.addItem(self.horizontalSpacer, 1, 1, 1, 1) self.label_9 = QLabel(self.args_widget) self.label_9.setObjectName(u"label_9") self.label_9.setMinimumSize(QSize(155, 0)) self.arg_layout.addWidget(self.label_9, 0, 0, 1, 1) self.functions = QComboBox(self.args_widget) self.functions.setObjectName(u"functions") self.arg_layout.addWidget(self.functions, 0, 1, 1, 1) self.label = QLabel(self.args_widget) self.label.setObjectName(u"label") self.arg_layout.addWidget(self.label, 1, 0, 1, 1) self.scrollArea.setWidget(self.args_widget) self.verticalLayout.addWidget(self.scrollArea) self.gridLayout.addWidget(self.groupBox, 4, 0, 1, 5) self.label_6 = QLabel(ComputedChannel) self.label_6.setObjectName(u"label_6") self.gridLayout.addWidget(self.label_6, 8, 0, 1, 1) self.name = QLineEdit(ComputedChannel) self.name.setObjectName(u"name") self.gridLayout.addWidget(self.name, 5, 1, 1, 4) self.horizontalSpacer_7 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout.addItem(self.horizontalSpacer_7, 9, 2, 1, 1) self.groupBox_4 = QGroupBox(ComputedChannel) self.groupBox_4.setObjectName(u"groupBox_4") self.gridLayout_3 = QGridLayout(self.groupBox_4) self.gridLayout_3.setSpacing(1) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.shift_type_fixed = QRadioButton(self.groupBox_4) self.shift_type_fixed.setObjectName(u"shift_type_fixed") self.shift_type_fixed.setMinimumSize(QSize(155, 0)) self.shift_type_fixed.setChecked(True) self.gridLayout_3.addWidget(self.shift_type_fixed, 0, 0, 1, 1) self.global_variable_timestamps_shift = QComboBox(self.groupBox_4) self.global_variable_timestamps_shift.setObjectName(u"global_variable_timestamps_shift") self.gridLayout_3.addWidget(self.global_variable_timestamps_shift, 1, 1, 1, 1) self.fixed_timestamps_shift = QDoubleSpinBox(self.groupBox_4) self.fixed_timestamps_shift.setObjectName(u"fixed_timestamps_shift") self.fixed_timestamps_shift.setDecimals(9) self.fixed_timestamps_shift.setMinimum(-2592000.000000000000000) self.fixed_timestamps_shift.setMaximum(2592000.000000000000000) self.gridLayout_3.addWidget(self.fixed_timestamps_shift, 0, 1, 1, 1) self.shift_type_global = QRadioButton(self.groupBox_4) self.shift_type_global.setObjectName(u"shift_type_global") self.gridLayout_3.addWidget(self.shift_type_global, 1, 0, 1, 1) self.global_variable_timstamps_shift_description = QLabel(self.groupBox_4) self.global_variable_timstamps_shift_description.setObjectName(u"global_variable_timstamps_shift_description") self.gridLayout_3.addWidget(self.global_variable_timstamps_shift_description, 1, 2, 1, 1) self.gridLayout_3.setColumnStretch(2, 1) self.gridLayout.addWidget(self.groupBox_4, 3, 0, 1, 5) QWidget.setTabOrder(self.triggering_on_all, self.triggering_on_interval) QWidget.setTabOrder(self.triggering_on_interval, self.trigger_interval) QWidget.setTabOrder(self.trigger_interval, self.triggering_on_channel) QWidget.setTabOrder(self.triggering_on_channel, self.trigger_channel) QWidget.setTabOrder(self.trigger_channel, self.trigger_search_btn) QWidget.setTabOrder(self.trigger_search_btn, self.sample_by_sample) QWidget.setTabOrder(self.sample_by_sample, self.complete_signal) QWidget.setTabOrder(self.complete_signal, self.scrollArea) QWidget.setTabOrder(self.scrollArea, self.functions) QWidget.setTabOrder(self.functions, self.show_definition_btn) QWidget.setTabOrder(self.show_definition_btn, self.name) QWidget.setTabOrder(self.name, self.comment) QWidget.setTabOrder(self.comment, self.unit) QWidget.setTabOrder(self.unit, self.apply_btn) QWidget.setTabOrder(self.apply_btn, self.cancel_btn) self.retranslateUi(ComputedChannel) QMetaObject.connectSlotsByName(ComputedChannel) # setupUi def retranslateUi(self, ComputedChannel): ComputedChannel.setWindowTitle(QCoreApplication.translate("ComputedChannel", u"Define new channel", None)) self.label_8.setText(QCoreApplication.translate("ComputedChannel", u"Computed channel comment", None)) self.apply_btn.setText(QCoreApplication.translate("ComputedChannel", u"Apply", None)) self.cancel_btn.setText(QCoreApplication.translate("ComputedChannel", u"Cancel", None)) self.unit.setPlaceholderText("") self.label_7.setText(QCoreApplication.translate("ComputedChannel", u"Computed channel name", None)) self.groupBox_2.setTitle(QCoreApplication.translate("ComputedChannel", u"Computation mode", None)) self.complete_signal.setText(QCoreApplication.translate("ComputedChannel", u"complete signal", None)) self.sample_by_sample.setText(QCoreApplication.translate("ComputedChannel", u"sample by sample", None)) self.label_25.setText(QCoreApplication.translate("ComputedChannel", u"\n" "\n" "
  • the function will be called only once
  • \n" "
  • each argument will receive the complete signal ndarray
\n" "
  • the t argument will receive the complete time base ndarray
", None)) self.label_24.setText(QCoreApplication.translate("ComputedChannel", u"\n" "\n" "
  • the function will be called several times for each of the individual time stamp in the time base
  • \n" "
  • earch argument will receive the signal sample at the" " current time stamp
  • \n" "
  • the t argument will receive the current time stamp value
", None)) self.groupBox_3.setTitle(QCoreApplication.translate("ComputedChannel", u"Triggering", None)) self.trigger_interval.setSuffix(QCoreApplication.translate("ComputedChannel", u"s", None)) self.triggering_on_channel.setText(QCoreApplication.translate("ComputedChannel", u"on channel", None)) self.triggering_on_interval.setText(QCoreApplication.translate("ComputedChannel", u"time interval", None)) self.trigger_search_btn.setText("") self.triggering_on_all.setText(QCoreApplication.translate("ComputedChannel", u"all channels timestamps", None)) self.groupBox.setTitle(QCoreApplication.translate("ComputedChannel", u"Function", None)) self.show_definition_btn.setText("") self.label_9.setText(QCoreApplication.translate("ComputedChannel", u"Name", None)) self.label.setText(QCoreApplication.translate("ComputedChannel", u"Arguments:", None)) self.label_6.setText(QCoreApplication.translate("ComputedChannel", u"Computed channel unit", None)) self.name.setInputMask("") self.name.setText("") self.name.setPlaceholderText("") self.groupBox_4.setTitle(QCoreApplication.translate("ComputedChannel", u"Time stamps shift", None)) self.shift_type_fixed.setText(QCoreApplication.translate("ComputedChannel", u"Fixed", None)) self.fixed_timestamps_shift.setSuffix(QCoreApplication.translate("ComputedChannel", u"s", None)) self.shift_type_global.setText(QCoreApplication.translate("ComputedChannel", u"Global variable", None)) self.global_variable_timstamps_shift_description.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/define_channel_dialog.ui000066400000000000000000000440721502633300400233400ustar00rootroot00000000000000 ComputedChannel 0 0 723 552 16777215 16777215 Define new channel :/plus.png:/plus.png true 1 1 1 1 1 Computed channel comment Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop Apply Cancel Qt::Orientation::Horizontal 40 20 Computed channel name Computation mode 1 1 1 1 1 complete signal false sample by sample true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } hr { height: 1px; border-width: 0; } </style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;"> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the function will be called only once</li> <li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">each argument will receive the complete signal ndarray</li></ul> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the<span style=" font-style:italic;"> </span><span style=" font-weight:700; font-style:italic;">t</span><span style=" font-style:italic;"> </span>argument will receive the complete time base ndarray</li></ul></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } hr { height: 1px; border-width: 0; } </style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;"> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the function will be called several times for each of the individual time stamp in the time base</li> <li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">earch argument will receive the signal sample at the current time stamp</li> <li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the<span style=" font-weight:700; font-style:italic;"> t</span> argument will receive the current time stamp value</li></ul></body></html> Qt::TextFormat::RichText false Qt::Orientation::Horizontal Triggering 1 1 1 1 1 Qt::Orientation::Horizontal 40 20 121 0 s 9 0.000001000000000 10.000000000000000 0.100000000000000 QAbstractSpinBox::StepType::DefaultStepType 0.010000000000000 on channel time interval :/search.png:/search.png 155 0 all channels timestamps true Function 1 1 1 1 1 QFrame::Shape::NoFrame 0 true 0 0 717 54 1 1 1 1 1 :/info.png:/info.png Qt::Orientation::Horizontal 40 20 155 0 Name Arguments: Computed channel unit Qt::Orientation::Horizontal 40 20 Time stamps shift 1 1 1 1 1 155 0 Fixed true s 9 -2592000.000000000000000 2592000.000000000000000 Global variable triggering_on_all triggering_on_interval trigger_interval triggering_on_channel trigger_channel trigger_search_btn sample_by_sample complete_signal scrollArea functions show_definition_btn name comment unit apply_btn cancel_btn asammdf-8.5.1/src/asammdf/gui/ui/define_conversion_dialog.py000066400000000000000000000505041502633300400241250ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'define_conversion_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QDialog, QDoubleSpinBox, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListWidgetItem, QPlainTextEdit, QPushButton, QSizePolicy, QSpacerItem, QStackedWidget, QTabWidget, QVBoxLayout, QWidget) from asammdf.gui.widgets.list import MinimalListWidget from . import resource_rc class Ui_ConversionDialog(object): def setupUi(self, ConversionDialog): if not ConversionDialog.objectName(): ConversionDialog.setObjectName(u"ConversionDialog") ConversionDialog.resize(937, 501) ConversionDialog.setMaximumSize(QSize(16777215, 16777215)) icon = QIcon() icon.addFile(u":/plus.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) ConversionDialog.setWindowIcon(icon) ConversionDialog.setSizeGripEnabled(True) self.gridLayout = QGridLayout(ConversionDialog) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.horizontalSpacer_4 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout.addItem(self.horizontalSpacer_4, 5, 2, 1, 1) self.label_8 = QLabel(ConversionDialog) self.label_8.setObjectName(u"label_8") self.label_8.setAlignment(Qt.AlignmentFlag.AlignLeading|Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignTop) self.gridLayout.addWidget(self.label_8, 3, 0, 1, 1) self.label_7 = QLabel(ConversionDialog) self.label_7.setObjectName(u"label_7") self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1) self.unit = QLineEdit(ConversionDialog) self.unit.setObjectName(u"unit") self.gridLayout.addWidget(self.unit, 4, 1, 1, 1) self.label_6 = QLabel(ConversionDialog) self.label_6.setObjectName(u"label_6") self.gridLayout.addWidget(self.label_6, 4, 0, 1, 1) self.apply_btn = QPushButton(ConversionDialog) self.apply_btn.setObjectName(u"apply_btn") self.gridLayout.addWidget(self.apply_btn, 5, 5, 1, 1) self.name = QLineEdit(ConversionDialog) self.name.setObjectName(u"name") self.gridLayout.addWidget(self.name, 1, 1, 1, 6) self.comment = QPlainTextEdit(ConversionDialog) self.comment.setObjectName(u"comment") self.gridLayout.addWidget(self.comment, 3, 1, 1, 6) self.load_original_conversion_btn = QPushButton(ConversionDialog) self.load_original_conversion_btn.setObjectName(u"load_original_conversion_btn") self.gridLayout.addWidget(self.load_original_conversion_btn, 5, 3, 1, 1) self.cancel_btn = QPushButton(ConversionDialog) self.cancel_btn.setObjectName(u"cancel_btn") self.gridLayout.addWidget(self.cancel_btn, 5, 6, 1, 1) self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout.addItem(self.horizontalSpacer_3, 5, 1, 1, 1) self.tabs = QTabWidget(ConversionDialog) self.tabs.setObjectName(u"tabs") self.tab = QWidget() self.tab.setObjectName(u"tab") self.gridLayout_5 = QGridLayout(self.tab) self.gridLayout_5.setSpacing(1) self.gridLayout_5.setObjectName(u"gridLayout_5") self.gridLayout_5.setContentsMargins(1, 1, 1, 1) self.label_10 = QLabel(self.tab) self.label_10.setObjectName(u"label_10") self.gridLayout_5.addWidget(self.label_10, 2, 0, 1, 1) self.b = QDoubleSpinBox(self.tab) self.b.setObjectName(u"b") self.b.setDecimals(6) self.gridLayout_5.addWidget(self.b, 2, 1, 1, 1) self.label_11 = QLabel(self.tab) self.label_11.setObjectName(u"label_11") self.gridLayout_5.addWidget(self.label_11, 0, 0, 1, 2) self.label_9 = QLabel(self.tab) self.label_9.setObjectName(u"label_9") self.gridLayout_5.addWidget(self.label_9, 1, 0, 1, 1) self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_5.addItem(self.horizontalSpacer, 1, 2, 1, 1) self.a = QDoubleSpinBox(self.tab) self.a.setObjectName(u"a") self.a.setMinimumSize(QSize(100, 0)) self.a.setDecimals(6) self.gridLayout_5.addWidget(self.a, 1, 1, 1, 1) self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_5.addItem(self.verticalSpacer, 3, 0, 1, 1) self.tabs.addTab(self.tab, "") self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") self.gridLayout_6 = QGridLayout(self.tab_2) self.gridLayout_6.setSpacing(1) self.gridLayout_6.setObjectName(u"gridLayout_6") self.gridLayout_6.setContentsMargins(1, 1, 1, 1) self.label_3 = QLabel(self.tab_2) self.label_3.setObjectName(u"label_3") self.gridLayout_6.addWidget(self.label_3, 1, 0, 1, 1) self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_6.addItem(self.verticalSpacer_2, 7, 0, 1, 1) self.p3 = QDoubleSpinBox(self.tab_2) self.p3.setObjectName(u"p3") self.p3.setDecimals(6) self.gridLayout_6.addWidget(self.p3, 3, 1, 1, 1) self.p1 = QDoubleSpinBox(self.tab_2) self.p1.setObjectName(u"p1") self.p1.setMinimumSize(QSize(100, 0)) self.p1.setDecimals(6) self.gridLayout_6.addWidget(self.p1, 1, 1, 1, 1) self.p2 = QDoubleSpinBox(self.tab_2) self.p2.setObjectName(u"p2") self.p2.setDecimals(6) self.gridLayout_6.addWidget(self.p2, 2, 1, 1, 1) self.label_4 = QLabel(self.tab_2) self.label_4.setObjectName(u"label_4") self.gridLayout_6.addWidget(self.label_4, 2, 0, 1, 1) self.label_15 = QLabel(self.tab_2) self.label_15.setObjectName(u"label_15") self.gridLayout_6.addWidget(self.label_15, 6, 0, 1, 1) self.label_13 = QLabel(self.tab_2) self.label_13.setObjectName(u"label_13") self.gridLayout_6.addWidget(self.label_13, 4, 0, 1, 1) self.p6 = QDoubleSpinBox(self.tab_2) self.p6.setObjectName(u"p6") self.p6.setDecimals(6) self.gridLayout_6.addWidget(self.p6, 6, 1, 1, 1) self.p5 = QDoubleSpinBox(self.tab_2) self.p5.setObjectName(u"p5") self.p5.setDecimals(6) self.gridLayout_6.addWidget(self.p5, 5, 1, 1, 1) self.label_5 = QLabel(self.tab_2) self.label_5.setObjectName(u"label_5") self.gridLayout_6.addWidget(self.label_5, 3, 0, 1, 1) self.p4 = QDoubleSpinBox(self.tab_2) self.p4.setObjectName(u"p4") self.p4.setDecimals(6) self.gridLayout_6.addWidget(self.p4, 4, 1, 1, 1) self.label_14 = QLabel(self.tab_2) self.label_14.setObjectName(u"label_14") self.gridLayout_6.addWidget(self.label_14, 5, 0, 1, 1) self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_6.addItem(self.horizontalSpacer_2, 1, 2, 1, 1) self.label_2 = QLabel(self.tab_2) self.label_2.setObjectName(u"label_2") self.gridLayout_6.addWidget(self.label_2, 0, 0, 1, 3) self.tabs.addTab(self.tab_2, "") self.tab_3 = QWidget() self.tab_3.setObjectName(u"tab_3") self.gridLayout_2 = QGridLayout(self.tab_3) self.gridLayout_2.setSpacing(1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(1, 1, 1, 1) self.vtt_list = MinimalListWidget(self.tab_3) self.vtt_list.setObjectName(u"vtt_list") self.gridLayout_2.addWidget(self.vtt_list, 1, 0, 4, 4) self.vtt_mode = QStackedWidget(self.tab_3) self.vtt_mode.setObjectName(u"vtt_mode") self.page = QWidget() self.page.setObjectName(u"page") self.horizontalLayout = QHBoxLayout(self.page) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.vtt_default = QLineEdit(self.page) self.vtt_default.setObjectName(u"vtt_default") self.horizontalLayout.addWidget(self.vtt_default) self.vtt_mode.addWidget(self.page) self.page_2 = QWidget() self.page_2.setObjectName(u"page_2") self.horizontalLayout_2 = QHBoxLayout(self.page_2) self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.horizontalLayout_2.setContentsMargins(1, 1, 1, 1) self.vtt_default_btn = QPushButton(self.page_2) self.vtt_default_btn.setObjectName(u"vtt_default_btn") self.horizontalLayout_2.addWidget(self.vtt_default_btn) self.vtt_mode.addWidget(self.page_2) self.gridLayout_2.addWidget(self.vtt_mode, 5, 2, 1, 1) self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_2.addItem(self.verticalSpacer_3, 2, 4, 1, 1) self.insert_btn = QPushButton(self.tab_3) self.insert_btn.setObjectName(u"insert_btn") self.gridLayout_2.addWidget(self.insert_btn, 1, 4, 1, 1) self.label_16 = QLabel(self.tab_3) self.label_16.setObjectName(u"label_16") self.gridLayout_2.addWidget(self.label_16, 5, 0, 1, 1) self.label = QLabel(self.tab_3) self.label.setObjectName(u"label") self.gridLayout_2.addWidget(self.label, 0, 0, 1, 4) self.reset_btn = QPushButton(self.tab_3) self.reset_btn.setObjectName(u"reset_btn") self.gridLayout_2.addWidget(self.reset_btn, 4, 4, 1, 1) self.vtt_default_mode = QComboBox(self.tab_3) self.vtt_default_mode.addItem("") self.vtt_default_mode.addItem("") self.vtt_default_mode.setObjectName(u"vtt_default_mode") self.gridLayout_2.addWidget(self.vtt_default_mode, 5, 1, 1, 1) self.tabs.addTab(self.tab_3, "") self.tab_4 = QWidget() self.tab_4.setObjectName(u"tab_4") self.gridLayout_3 = QGridLayout(self.tab_4) self.gridLayout_3.setSpacing(1) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.vrtt_list = MinimalListWidget(self.tab_4) self.vrtt_list.setObjectName(u"vrtt_list") self.gridLayout_3.addWidget(self.vrtt_list, 1, 0, 3, 4) self.label_12 = QLabel(self.tab_4) self.label_12.setObjectName(u"label_12") self.gridLayout_3.addWidget(self.label_12, 0, 0, 1, 4) self.vrtt_mode = QStackedWidget(self.tab_4) self.vrtt_mode.setObjectName(u"vrtt_mode") self.page_3 = QWidget() self.page_3.setObjectName(u"page_3") self.horizontalLayout_3 = QHBoxLayout(self.page_3) self.horizontalLayout_3.setSpacing(1) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.horizontalLayout_3.setContentsMargins(1, 1, 1, 1) self.vrtt_default = QLineEdit(self.page_3) self.vrtt_default.setObjectName(u"vrtt_default") self.horizontalLayout_3.addWidget(self.vrtt_default) self.vrtt_mode.addWidget(self.page_3) self.page_4 = QWidget() self.page_4.setObjectName(u"page_4") self.horizontalLayout_4 = QHBoxLayout(self.page_4) self.horizontalLayout_4.setSpacing(1) self.horizontalLayout_4.setObjectName(u"horizontalLayout_4") self.horizontalLayout_4.setContentsMargins(1, 1, 1, 1) self.vrtt_default_btn = QPushButton(self.page_4) self.vrtt_default_btn.setObjectName(u"vrtt_default_btn") self.horizontalLayout_4.addWidget(self.vrtt_default_btn) self.vrtt_mode.addWidget(self.page_4) self.gridLayout_3.addWidget(self.vrtt_mode, 4, 2, 1, 1) self.insert_vrtt_btn = QPushButton(self.tab_4) self.insert_vrtt_btn.setObjectName(u"insert_vrtt_btn") self.gridLayout_3.addWidget(self.insert_vrtt_btn, 1, 4, 1, 1) self.verticalSpacer_4 = QSpacerItem(20, 78, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_3.addItem(self.verticalSpacer_4, 2, 4, 1, 1) self.reset_vrtt_btn = QPushButton(self.tab_4) self.reset_vrtt_btn.setObjectName(u"reset_vrtt_btn") self.gridLayout_3.addWidget(self.reset_vrtt_btn, 3, 4, 1, 1) self.label_17 = QLabel(self.tab_4) self.label_17.setObjectName(u"label_17") self.gridLayout_3.addWidget(self.label_17, 4, 0, 1, 1) self.vrtt_default_mode = QComboBox(self.tab_4) self.vrtt_default_mode.addItem("") self.vrtt_default_mode.addItem("") self.vrtt_default_mode.setObjectName(u"vrtt_default_mode") self.gridLayout_3.addWidget(self.vrtt_default_mode, 4, 1, 1, 1) self.tabs.addTab(self.tab_4, "") self.tab_5 = QWidget() self.tab_5.setObjectName(u"tab_5") self.verticalLayout = QVBoxLayout(self.tab_5) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.label_18 = QLabel(self.tab_5) self.label_18.setObjectName(u"label_18") self.verticalLayout.addWidget(self.label_18) self.verticalSpacer_5 = QSpacerItem(20, 166, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout.addItem(self.verticalSpacer_5) self.tabs.addTab(self.tab_5, "") self.gridLayout.addWidget(self.tabs, 0, 0, 1, 7) self.horizontalSpacer_5 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout.addItem(self.horizontalSpacer_5, 5, 4, 1, 1) self.gridLayout.setRowStretch(0, 1) self.gridLayout.setColumnStretch(2, 1) QWidget.setTabOrder(self.tabs, self.a) QWidget.setTabOrder(self.a, self.b) QWidget.setTabOrder(self.b, self.p1) QWidget.setTabOrder(self.p1, self.p2) QWidget.setTabOrder(self.p2, self.p3) QWidget.setTabOrder(self.p3, self.p4) QWidget.setTabOrder(self.p4, self.p5) QWidget.setTabOrder(self.p5, self.p6) QWidget.setTabOrder(self.p6, self.vtt_list) QWidget.setTabOrder(self.vtt_list, self.insert_btn) QWidget.setTabOrder(self.insert_btn, self.reset_btn) QWidget.setTabOrder(self.reset_btn, self.vtt_default_mode) QWidget.setTabOrder(self.vtt_default_mode, self.vtt_default) QWidget.setTabOrder(self.vtt_default, self.vrtt_list) QWidget.setTabOrder(self.vrtt_list, self.insert_vrtt_btn) QWidget.setTabOrder(self.insert_vrtt_btn, self.reset_vrtt_btn) QWidget.setTabOrder(self.reset_vrtt_btn, self.vrtt_default_mode) QWidget.setTabOrder(self.vrtt_default_mode, self.vrtt_default) QWidget.setTabOrder(self.vrtt_default, self.name) QWidget.setTabOrder(self.name, self.comment) QWidget.setTabOrder(self.comment, self.unit) QWidget.setTabOrder(self.unit, self.apply_btn) QWidget.setTabOrder(self.apply_btn, self.cancel_btn) QWidget.setTabOrder(self.cancel_btn, self.vrtt_default_btn) QWidget.setTabOrder(self.vrtt_default_btn, self.vtt_default_btn) self.retranslateUi(ConversionDialog) self.tabs.setCurrentIndex(0) self.vtt_mode.setCurrentIndex(0) self.vrtt_mode.setCurrentIndex(0) QMetaObject.connectSlotsByName(ConversionDialog) # setupUi def retranslateUi(self, ConversionDialog): ConversionDialog.setWindowTitle(QCoreApplication.translate("ConversionDialog", u"Define new channel", None)) self.label_8.setText(QCoreApplication.translate("ConversionDialog", u"Conversion comment", None)) self.label_7.setText(QCoreApplication.translate("ConversionDialog", u"Conversion name", None)) self.unit.setPlaceholderText("") self.label_6.setText(QCoreApplication.translate("ConversionDialog", u"Conversion unit", None)) self.apply_btn.setText(QCoreApplication.translate("ConversionDialog", u"Apply", None)) self.name.setInputMask("") self.name.setText("") self.name.setPlaceholderText("") self.load_original_conversion_btn.setText(QCoreApplication.translate("ConversionDialog", u"Load original conversion", None)) self.cancel_btn.setText(QCoreApplication.translate("ConversionDialog", u"Cancel", None)) self.label_10.setText(QCoreApplication.translate("ConversionDialog", u"Offset (b)", None)) self.label_11.setText(QCoreApplication.translate("ConversionDialog", u"Y = a * X + b", None)) self.label_9.setText(QCoreApplication.translate("ConversionDialog", u"Factor (a)", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab), QCoreApplication.translate("ConversionDialog", u"Linear", None)) self.label_3.setText(QCoreApplication.translate("ConversionDialog", u"P1", None)) self.label_4.setText(QCoreApplication.translate("ConversionDialog", u"P2", None)) self.label_15.setText(QCoreApplication.translate("ConversionDialog", u"P6", None)) self.label_13.setText(QCoreApplication.translate("ConversionDialog", u"P4", None)) self.label_5.setText(QCoreApplication.translate("ConversionDialog", u"P3", None)) self.label_14.setText(QCoreApplication.translate("ConversionDialog", u"P5", None)) self.label_2.setText(QCoreApplication.translate("ConversionDialog", u"Y = (P1 * X^2 + P2 * X +P3) / (P4 * X^2 + P5 * X + P6)", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab_2), QCoreApplication.translate("ConversionDialog", u"Rational", None)) self.vtt_default_btn.setText(QCoreApplication.translate("ConversionDialog", u"Default conversion", None)) self.insert_btn.setText(QCoreApplication.translate("ConversionDialog", u"Insert", None)) self.label_16.setText(QCoreApplication.translate("ConversionDialog", u"Default", None)) self.label.setText(QCoreApplication.translate("ConversionDialog", u"X -> Y (str/float) ", None)) self.reset_btn.setText(QCoreApplication.translate("ConversionDialog", u"Reset", None)) self.vtt_default_mode.setItemText(0, QCoreApplication.translate("ConversionDialog", u"Text", None)) self.vtt_default_mode.setItemText(1, QCoreApplication.translate("ConversionDialog", u"Conversion", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab_3), QCoreApplication.translate("ConversionDialog", u"Value to Text/Conversion", None)) self.label_12.setText(QCoreApplication.translate("ConversionDialog", u"[ .. X .. ) -> Y (str/float) ", None)) self.vrtt_default_btn.setText(QCoreApplication.translate("ConversionDialog", u"Default conversion", None)) self.insert_vrtt_btn.setText(QCoreApplication.translate("ConversionDialog", u"Insert", None)) self.reset_vrtt_btn.setText(QCoreApplication.translate("ConversionDialog", u"Reset", None)) self.label_17.setText(QCoreApplication.translate("ConversionDialog", u"Default", None)) self.vrtt_default_mode.setItemText(0, QCoreApplication.translate("ConversionDialog", u"Text", None)) self.vrtt_default_mode.setItemText(1, QCoreApplication.translate("ConversionDialog", u"Conversion", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab_4), QCoreApplication.translate("ConversionDialog", u"Value range to Text/Conversion", None)) self.label_18.setText(QCoreApplication.translate("ConversionDialog", u"X -> X", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab_5), QCoreApplication.translate("ConversionDialog", u"1:1", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/define_conversion_dialog.ui000066400000000000000000000521351502633300400241140ustar00rootroot00000000000000 ConversionDialog 0 0 937 501 16777215 16777215 Define new channel :/plus.png:/plus.png true 1 1 1 1 1 Qt::Orientation::Horizontal 40 20 Conversion comment Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop Conversion name Conversion unit Apply Load original conversion Cancel Qt::Orientation::Horizontal 40 20 0 Linear 1 1 1 1 1 Offset (b) 6 Y = a * X + b Factor (a) Qt::Orientation::Horizontal 40 20 100 0 6 Qt::Orientation::Vertical 20 40 Rational 1 1 1 1 1 P1 Qt::Orientation::Vertical 20 40 6 100 0 6 6 P2 P6 P4 6 6 P3 6 P5 Qt::Orientation::Horizontal 40 20 Y = (P1 * X^2 + P2 * X +P3) / (P4 * X^2 + P5 * X + P6) Value to Text/Conversion 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 Default conversion Qt::Orientation::Vertical 20 40 Insert Default X -> Y (str/float) Reset Text Conversion Value range to Text/Conversion 1 1 1 1 1 [ .. X .. ) -> Y (str/float) 0 1 1 1 1 1 1 1 1 1 1 Default conversion Insert Qt::Orientation::Vertical 20 78 Reset Default Text Conversion 1:1 1 1 1 1 1 X -> X Qt::Orientation::Vertical 20 166 Qt::Orientation::Horizontal 40 20 MinimalListWidget QListWidget
asammdf.gui.widgets.list.h
tabs a b p1 p2 p3 p4 p5 p6 vtt_list insert_btn reset_btn vtt_default_mode vtt_default vrtt_list insert_vrtt_btn reset_vrtt_btn vrtt_default_mode vrtt_default name comment unit apply_btn cancel_btn vrtt_default_btn vtt_default_btn
asammdf-8.5.1/src/asammdf/gui/ui/error_dialog.py000066400000000000000000000072531502633300400215620ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'error_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QDialog, QHBoxLayout, QLabel, QPushButton, QSizePolicy, QSpacerItem, QVBoxLayout, QWidget) from . import resource_rc class Ui_ErrorDialog(object): def setupUi(self, ErrorDialog): if not ErrorDialog.objectName(): ErrorDialog.setObjectName(u"ErrorDialog") ErrorDialog.resize(622, 114) icon = QIcon() icon.addFile(u":/error.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) ErrorDialog.setWindowIcon(icon) ErrorDialog.setSizeGripEnabled(True) self.layout = QVBoxLayout(ErrorDialog) self.layout.setSpacing(1) self.layout.setObjectName(u"layout") self.layout.setContentsMargins(1, 1, 1, 1) self.error_message = QLabel(ErrorDialog) self.error_message.setObjectName(u"error_message") self.layout.addWidget(self.error_message) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.horizontalLayout_2.addItem(self.verticalSpacer) self.layout.addLayout(self.horizontalLayout_2) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer) self.show_trace_btn = QPushButton(ErrorDialog) self.show_trace_btn.setObjectName(u"show_trace_btn") self.horizontalLayout.addWidget(self.show_trace_btn) self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer_2) self.copy_to_clipboard_btn = QPushButton(ErrorDialog) self.copy_to_clipboard_btn.setObjectName(u"copy_to_clipboard_btn") self.horizontalLayout.addWidget(self.copy_to_clipboard_btn) self.horizontalLayout.setStretch(0, 1) self.layout.addLayout(self.horizontalLayout) self.status = QLabel(ErrorDialog) self.status.setObjectName(u"status") self.layout.addWidget(self.status) self.layout.setStretch(1, 1) self.retranslateUi(ErrorDialog) QMetaObject.connectSlotsByName(ErrorDialog) # setupUi def retranslateUi(self, ErrorDialog): ErrorDialog.setWindowTitle(QCoreApplication.translate("ErrorDialog", u"Dialog", None)) self.error_message.setText("") self.show_trace_btn.setText(QCoreApplication.translate("ErrorDialog", u"Show error trace", None)) self.copy_to_clipboard_btn.setText(QCoreApplication.translate("ErrorDialog", u"Copy to clipboard", None)) self.status.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/error_dialog.ui000066400000000000000000000057621502633300400215520ustar00rootroot00000000000000 ErrorDialog 0 0 622 114 Dialog :/error.png:/error.png true 1 1 1 1 1 1 Qt::Orientation::Vertical 20 40 1 Qt::Orientation::Horizontal 40 20 Show error trace Qt::Orientation::Horizontal 40 20 Copy to clipboard asammdf-8.5.1/src/asammdf/gui/ui/fft_window.py000066400000000000000000000112041502633300400212470ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'fft_window.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QDoubleSpinBox, QHBoxLayout, QLabel, QMainWindow, QMenuBar, QSizePolicy, QSpacerItem, QStatusBar, QVBoxLayout, QWidget) class Ui_FFTWindow(object): def setupUi(self, FFTWindow): if not FFTWindow.objectName(): FFTWindow.setObjectName(u"FFTWindow") FFTWindow.resize(640, 480) self.centralwidget = QWidget(FFTWindow) self.centralwidget.setObjectName(u"centralwidget") self.horizontalLayout = QHBoxLayout(self.centralwidget) self.horizontalLayout.setObjectName(u"horizontalLayout") self.verticalLayout = QVBoxLayout() self.verticalLayout.setObjectName(u"verticalLayout") self.label_2 = QLabel(self.centralwidget) self.label_2.setObjectName(u"label_2") self.verticalLayout.addWidget(self.label_2) self.start_frequency = QDoubleSpinBox(self.centralwidget) self.start_frequency.setObjectName(u"start_frequency") self.start_frequency.setDecimals(3) self.start_frequency.setMinimum(0.001000000000000) self.start_frequency.setMaximum(1000000.000000000000000) self.start_frequency.setValue(1.000000000000000) self.verticalLayout.addWidget(self.start_frequency) self.label = QLabel(self.centralwidget) self.label.setObjectName(u"label") self.verticalLayout.addWidget(self.label) self.end_frequency = QDoubleSpinBox(self.centralwidget) self.end_frequency.setObjectName(u"end_frequency") self.end_frequency.setDecimals(3) self.end_frequency.setMinimum(0.001000000000000) self.end_frequency.setMaximum(1000000.000000000000000) self.end_frequency.setValue(1000.000000000000000) self.verticalLayout.addWidget(self.end_frequency) self.label_3 = QLabel(self.centralwidget) self.label_3.setObjectName(u"label_3") self.verticalLayout.addWidget(self.label_3) self.frequency_step = QDoubleSpinBox(self.centralwidget) self.frequency_step.setObjectName(u"frequency_step") self.frequency_step.setDecimals(3) self.frequency_step.setMinimum(0.001000000000000) self.frequency_step.setMaximum(1000000.000000000000000) self.frequency_step.setValue(1.000000000000000) self.verticalLayout.addWidget(self.frequency_step) self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout.addItem(self.verticalSpacer) self.horizontalLayout.addLayout(self.verticalLayout) self.layout = QVBoxLayout() self.layout.setObjectName(u"layout") self.horizontalLayout.addLayout(self.layout) self.horizontalLayout.setStretch(1, 1) FFTWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(FFTWindow) self.menubar.setObjectName(u"menubar") self.menubar.setGeometry(QRect(0, 0, 640, 21)) FFTWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(FFTWindow) self.statusbar.setObjectName(u"statusbar") FFTWindow.setStatusBar(self.statusbar) self.retranslateUi(FFTWindow) QMetaObject.connectSlotsByName(FFTWindow) # setupUi def retranslateUi(self, FFTWindow): FFTWindow.setWindowTitle(QCoreApplication.translate("FFTWindow", u"MainWindow", None)) self.label_2.setText(QCoreApplication.translate("FFTWindow", u"Start frequency", None)) self.start_frequency.setSuffix(QCoreApplication.translate("FFTWindow", u"Hz", None)) self.label.setText(QCoreApplication.translate("FFTWindow", u"End frequency", None)) self.end_frequency.setSuffix(QCoreApplication.translate("FFTWindow", u"Hz", None)) self.label_3.setText(QCoreApplication.translate("FFTWindow", u"Frequency step", None)) self.frequency_step.setSuffix(QCoreApplication.translate("FFTWindow", u"Hz", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/fft_window.ui000066400000000000000000000067151502633300400212470ustar00rootroot00000000000000 FFTWindow 0 0 640 480 MainWindow Start frequency Hz 3 0.001000000000000 1000000.000000000000000 1.000000000000000 End frequency Hz 3 0.001000000000000 1000000.000000000000000 1000.000000000000000 Frequency step Hz 3 0.001000000000000 1000000.000000000000000 1.000000000000000 Qt::Vertical 20 40 0 0 640 21 asammdf-8.5.1/src/asammdf/gui/ui/file_widget.py000066400000000000000000001630351502633300400213750ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'file_widget.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QDoubleSpinBox, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QListView, QListWidget, QListWidgetItem, QPushButton, QRadioButton, QScrollArea, QSizePolicy, QSpacerItem, QSplitter, QStackedWidget, QTabWidget, QTextEdit, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget) from asammdf.gui.widgets.list import MinimalListWidget from asammdf.gui.widgets.tree import TreeWidget from . import resource_rc class Ui_file_widget(object): def setupUi(self, file_widget): if not file_widget.objectName(): file_widget.setObjectName(u"file_widget") file_widget.resize(1034, 621) sizePolicy = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(file_widget.sizePolicy().hasHeightForWidth()) file_widget.setSizePolicy(sizePolicy) file_widget.setMinimumSize(QSize(1, 1)) self.verticalLayout = QVBoxLayout(file_widget) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.aspects = QTabWidget(file_widget) self.aspects.setObjectName(u"aspects") self.aspects.setTabPosition(QTabWidget.TabPosition.West) self.aspects.setDocumentMode(False) self.channels_tab = QWidget() self.channels_tab.setObjectName(u"channels_tab") self.verticalLayout_5 = QVBoxLayout(self.channels_tab) self.verticalLayout_5.setSpacing(1) self.verticalLayout_5.setObjectName(u"verticalLayout_5") self.verticalLayout_5.setContentsMargins(1, 1, 1, 1) self.splitter = QSplitter(self.channels_tab) self.splitter.setObjectName(u"splitter") self.splitter.setOrientation(Qt.Orientation.Horizontal) self.verticalLayoutWidget = QWidget(self.splitter) self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget") self.channels_layout = QVBoxLayout(self.verticalLayoutWidget) self.channels_layout.setSpacing(1) self.channels_layout.setObjectName(u"channels_layout") self.channels_layout.setContentsMargins(0, 0, 0, 0) self.channel_view = QComboBox(self.verticalLayoutWidget) self.channel_view.addItem("") self.channel_view.addItem("") self.channel_view.addItem("") self.channel_view.setObjectName(u"channel_view") self.channels_layout.addWidget(self.channel_view) self.channels_tree = TreeWidget(self.verticalLayoutWidget) self.channels_tree.setObjectName(u"channels_tree") self.channels_layout.addWidget(self.channels_tree) self.buttons_layout = QHBoxLayout() self.buttons_layout.setSpacing(1) self.buttons_layout.setObjectName(u"buttons_layout") self.load_channel_list_btn = QPushButton(self.verticalLayoutWidget) self.load_channel_list_btn.setObjectName(u"load_channel_list_btn") icon = QIcon() icon.addFile(u":/open.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.load_channel_list_btn.setIcon(icon) self.buttons_layout.addWidget(self.load_channel_list_btn) self.button_spacer1 = QSpacerItem(20, 20, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum) self.buttons_layout.addItem(self.button_spacer1) self.save_channel_list_btn = QPushButton(self.verticalLayoutWidget) self.save_channel_list_btn.setObjectName(u"save_channel_list_btn") icon1 = QIcon() icon1.addFile(u":/save.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.save_channel_list_btn.setIcon(icon1) self.buttons_layout.addWidget(self.save_channel_list_btn) self.select_all_btn = QPushButton(self.verticalLayoutWidget) self.select_all_btn.setObjectName(u"select_all_btn") icon2 = QIcon() icon2.addFile(u":/checkmark.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.select_all_btn.setIcon(icon2) self.buttons_layout.addWidget(self.select_all_btn) self.clear_channels_btn = QPushButton(self.verticalLayoutWidget) self.clear_channels_btn.setObjectName(u"clear_channels_btn") icon3 = QIcon() icon3.addFile(u":/erase.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.clear_channels_btn.setIcon(icon3) self.buttons_layout.addWidget(self.clear_channels_btn) self.advanced_search_btn = QPushButton(self.verticalLayoutWidget) self.advanced_search_btn.setObjectName(u"advanced_search_btn") icon4 = QIcon() icon4.addFile(u":/search.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.advanced_search_btn.setIcon(icon4) self.buttons_layout.addWidget(self.advanced_search_btn) self.create_window_btn = QPushButton(self.verticalLayoutWidget) self.create_window_btn.setObjectName(u"create_window_btn") icon5 = QIcon() icon5.addFile(u":/plus.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.create_window_btn.setIcon(icon5) self.buttons_layout.addWidget(self.create_window_btn) self.horizontalSpacer_6 = QSpacerItem(20, 20, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum) self.buttons_layout.addItem(self.horizontalSpacer_6) self.load_embedded_channel_list_btn = QPushButton(self.verticalLayoutWidget) self.load_embedded_channel_list_btn.setObjectName(u"load_embedded_channel_list_btn") icon6 = QIcon() icon6.addFile(u":/load_embed.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.load_embedded_channel_list_btn.setIcon(icon6) self.buttons_layout.addWidget(self.load_embedded_channel_list_btn) self.save_embedded_channel_list_btn = QPushButton(self.verticalLayoutWidget) self.save_embedded_channel_list_btn.setObjectName(u"save_embedded_channel_list_btn") icon7 = QIcon() icon7.addFile(u":/attach.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.save_embedded_channel_list_btn.setIcon(icon7) self.buttons_layout.addWidget(self.save_embedded_channel_list_btn) self.button_spacer2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.buttons_layout.addItem(self.button_spacer2) self.channels_layout.addLayout(self.buttons_layout) self.splitter.addWidget(self.verticalLayoutWidget) self.verticalLayout_5.addWidget(self.splitter) icon8 = QIcon() icon8.addFile(u":/graph.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.aspects.addTab(self.channels_tab, icon8, "") self.modify = QWidget() self.modify.setObjectName(u"modify") self.horizontalLayout = QHBoxLayout(self.modify) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.verticalLayout_2 = QVBoxLayout() self.verticalLayout_2.setSpacing(1) self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.filter_view = QComboBox(self.modify) self.filter_view.addItem("") self.filter_view.addItem("") self.filter_view.addItem("") self.filter_view.setObjectName(u"filter_view") self.verticalLayout_2.addWidget(self.filter_view) self.filter_tree = TreeWidget(self.modify) self.filter_tree.setObjectName(u"filter_tree") self.verticalLayout_2.addWidget(self.filter_tree) self.horizontalLayout_4 = QHBoxLayout() self.horizontalLayout_4.setSpacing(1) self.horizontalLayout_4.setObjectName(u"horizontalLayout_4") self.load_filter_list_btn = QPushButton(self.modify) self.load_filter_list_btn.setObjectName(u"load_filter_list_btn") self.load_filter_list_btn.setIcon(icon) self.horizontalLayout_4.addWidget(self.load_filter_list_btn) self.save_filter_list_btn = QPushButton(self.modify) self.save_filter_list_btn.setObjectName(u"save_filter_list_btn") self.save_filter_list_btn.setIcon(icon1) self.horizontalLayout_4.addWidget(self.save_filter_list_btn) self.clear_filter_btn = QPushButton(self.modify) self.clear_filter_btn.setObjectName(u"clear_filter_btn") self.clear_filter_btn.setIcon(icon3) self.horizontalLayout_4.addWidget(self.clear_filter_btn) self.advanced_serch_filter_btn = QPushButton(self.modify) self.advanced_serch_filter_btn.setObjectName(u"advanced_serch_filter_btn") self.advanced_serch_filter_btn.setIcon(icon4) self.horizontalLayout_4.addWidget(self.advanced_serch_filter_btn) self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_4.addItem(self.horizontalSpacer_2) self.verticalLayout_2.addLayout(self.horizontalLayout_4) self.horizontalLayout.addLayout(self.verticalLayout_2) self.verticalLayout_6 = QVBoxLayout() self.verticalLayout_6.setSpacing(1) self.verticalLayout_6.setObjectName(u"verticalLayout_6") self.label = QLabel(self.modify) self.label.setObjectName(u"label") self.verticalLayout_6.addWidget(self.label) self.selected_filter_channels = QListWidget(self.modify) self.selected_filter_channels.setObjectName(u"selected_filter_channels") self.selected_filter_channels.setViewMode(QListView.ViewMode.ListMode) self.selected_filter_channels.setUniformItemSizes(True) self.selected_filter_channels.setSortingEnabled(True) self.verticalLayout_6.addWidget(self.selected_filter_channels) self.horizontalLayout.addLayout(self.verticalLayout_6) self.scrollArea = QScrollArea(self.modify) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 331, 609)) self.verticalLayout_4 = QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_4.setSpacing(1) self.verticalLayout_4.setObjectName(u"verticalLayout_4") self.verticalLayout_4.setContentsMargins(1, 1, 1, 1) self.verticalLayout_3 = QVBoxLayout() self.verticalLayout_3.setSpacing(1) self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.cut_group = QGroupBox(self.scrollAreaWidgetContents) self.cut_group.setObjectName(u"cut_group") self.cut_group.setCheckable(True) self.cut_group.setChecked(False) self.gridLayout_19 = QGridLayout(self.cut_group) self.gridLayout_19.setSpacing(1) self.gridLayout_19.setObjectName(u"gridLayout_19") self.gridLayout_19.setContentsMargins(1, 1, 1, 1) self.label_59 = QLabel(self.cut_group) self.label_59.setObjectName(u"label_59") self.gridLayout_19.addWidget(self.label_59, 0, 0, 1, 1) self.cut_stop = QDoubleSpinBox(self.cut_group) self.cut_stop.setObjectName(u"cut_stop") self.cut_stop.setDecimals(6) self.cut_stop.setMinimum(-9999999999999999635896294965248.000000000000000) self.cut_stop.setMaximum(999999999999999983222784.000000000000000) self.gridLayout_19.addWidget(self.cut_stop, 1, 1, 1, 1) self.label_60 = QLabel(self.cut_group) self.label_60.setObjectName(u"label_60") self.gridLayout_19.addWidget(self.label_60, 1, 0, 1, 1) self.cut_start = QDoubleSpinBox(self.cut_group) self.cut_start.setObjectName(u"cut_start") self.cut_start.setDecimals(6) self.cut_start.setMinimum(-9999999999999999635896294965248.000000000000000) self.cut_start.setMaximum(999999999999999983222784.000000000000000) self.gridLayout_19.addWidget(self.cut_start, 0, 1, 1, 1) self.whence = QCheckBox(self.cut_group) self.whence.setObjectName(u"whence") self.gridLayout_19.addWidget(self.whence, 3, 0, 1, 2) self.cut_time_from_zero = QCheckBox(self.cut_group) self.cut_time_from_zero.setObjectName(u"cut_time_from_zero") self.gridLayout_19.addWidget(self.cut_time_from_zero, 4, 0, 1, 2) self.verticalLayout_3.addWidget(self.cut_group) self.resample_group = QGroupBox(self.scrollAreaWidgetContents) self.resample_group.setObjectName(u"resample_group") self.resample_group.setCheckable(True) self.resample_group.setChecked(False) self.gridLayout_21 = QGridLayout(self.resample_group) self.gridLayout_21.setSpacing(1) self.gridLayout_21.setObjectName(u"gridLayout_21") self.gridLayout_21.setContentsMargins(1, 1, 1, 1) self.raster_type_step = QRadioButton(self.resample_group) self.raster_type_step.setObjectName(u"raster_type_step") self.raster_type_step.setChecked(True) self.gridLayout_21.addWidget(self.raster_type_step, 0, 0, 1, 1) self.raster = QDoubleSpinBox(self.resample_group) self.raster.setObjectName(u"raster") sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.raster.sizePolicy().hasHeightForWidth()) self.raster.setSizePolicy(sizePolicy1) self.raster.setMinimumSize(QSize(0, 0)) self.raster.setDecimals(6) self.raster.setMinimum(0.000001000000000) self.gridLayout_21.addWidget(self.raster, 0, 1, 1, 1) self.raster_type_channel = QRadioButton(self.resample_group) self.raster_type_channel.setObjectName(u"raster_type_channel") self.gridLayout_21.addWidget(self.raster_type_channel, 2, 0, 1, 1) self.raster_channel = QComboBox(self.resample_group) self.raster_channel.setObjectName(u"raster_channel") self.raster_channel.setEnabled(False) self.raster_channel.setInsertPolicy(QComboBox.InsertPolicy.InsertAtBottom) self.raster_channel.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) self.gridLayout_21.addWidget(self.raster_channel, 2, 1, 1, 1) self.raster_search_btn = QPushButton(self.resample_group) self.raster_search_btn.setObjectName(u"raster_search_btn") self.raster_search_btn.setIcon(icon4) self.gridLayout_21.addWidget(self.raster_search_btn, 2, 2, 1, 1) self.resample_time_from_zero = QCheckBox(self.resample_group) self.resample_time_from_zero.setObjectName(u"resample_time_from_zero") self.gridLayout_21.addWidget(self.resample_time_from_zero, 3, 0, 1, 3) self.gridLayout_21.setColumnStretch(1, 1) self.verticalLayout_3.addWidget(self.resample_group) self.groupBox_10 = QGroupBox(self.scrollAreaWidgetContents) self.groupBox_10.setObjectName(u"groupBox_10") self.verticalLayout_20 = QVBoxLayout(self.groupBox_10) self.verticalLayout_20.setSpacing(1) self.verticalLayout_20.setObjectName(u"verticalLayout_20") self.verticalLayout_20.setContentsMargins(1, 1, 1, 1) self.output_format = QComboBox(self.groupBox_10) self.output_format.setObjectName(u"output_format") self.verticalLayout_20.addWidget(self.output_format) self.output_options = QStackedWidget(self.groupBox_10) self.output_options.setObjectName(u"output_options") self.MDF = QWidget() self.MDF.setObjectName(u"MDF") self.gridLayout_22 = QGridLayout(self.MDF) self.gridLayout_22.setSpacing(1) self.gridLayout_22.setObjectName(u"gridLayout_22") self.gridLayout_22.setContentsMargins(1, 1, 1, 1) self.mdf_compression = QComboBox(self.MDF) self.mdf_compression.setObjectName(u"mdf_compression") self.gridLayout_22.addWidget(self.mdf_compression, 2, 1, 1, 1) self.label_28 = QLabel(self.MDF) self.label_28.setObjectName(u"label_28") self.gridLayout_22.addWidget(self.label_28, 4, 0, 1, 1) self.mdf_split = QCheckBox(self.MDF) self.mdf_split.setObjectName(u"mdf_split") self.mdf_split.setChecked(True) self.gridLayout_22.addWidget(self.mdf_split, 3, 0, 1, 2) self.label_29 = QLabel(self.MDF) self.label_29.setObjectName(u"label_29") self.gridLayout_22.addWidget(self.label_29, 2, 0, 1, 1) self.line_14 = QFrame(self.MDF) self.line_14.setObjectName(u"line_14") self.line_14.setFrameShape(QFrame.Shape.HLine) self.line_14.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_22.addWidget(self.line_14, 1, 0, 1, 2) self.groupBox_9 = QGroupBox(self.MDF) self.groupBox_9.setObjectName(u"groupBox_9") self.gridLayout_20 = QGridLayout(self.groupBox_9) self.gridLayout_20.setSpacing(1) self.gridLayout_20.setObjectName(u"gridLayout_20") self.gridLayout_20.setContentsMargins(1, 1, 1, 1) self.scramble_btn = QPushButton(self.groupBox_9) self.scramble_btn.setObjectName(u"scramble_btn") icon9 = QIcon() icon9.addFile(u":/scramble.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.scramble_btn.setIcon(icon9) self.gridLayout_20.addWidget(self.scramble_btn, 1, 0, 1, 1) self.horizontalSpacer_23 = QSpacerItem(2, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_20.addItem(self.horizontalSpacer_23, 1, 1, 1, 1) self.label_61 = QLabel(self.groupBox_9) self.label_61.setObjectName(u"label_61") self.label_61.setWordWrap(True) self.gridLayout_20.addWidget(self.label_61, 0, 0, 1, 2) self.gridLayout_22.addWidget(self.groupBox_9, 5, 0, 1, 2) self.label_27 = QLabel(self.MDF) self.label_27.setObjectName(u"label_27") self.gridLayout_22.addWidget(self.label_27, 0, 0, 1, 1) self.mdf_version = QComboBox(self.MDF) self.mdf_version.setObjectName(u"mdf_version") self.mdf_version.setMinimumSize(QSize(0, 0)) self.gridLayout_22.addWidget(self.mdf_version, 0, 1, 1, 1) self.mdf_split_size = QDoubleSpinBox(self.MDF) self.mdf_split_size.setObjectName(u"mdf_split_size") self.mdf_split_size.setMaximum(4.000000000000000) self.gridLayout_22.addWidget(self.mdf_split_size, 4, 1, 1, 1) self.output_options.addWidget(self.MDF) self.HDF5 = QWidget() self.HDF5.setObjectName(u"HDF5") self.gridLayout_2 = QGridLayout(self.HDF5) self.gridLayout_2.setSpacing(1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(1, 1, 1, 1) self.empty_channels = QComboBox(self.HDF5) self.empty_channels.setObjectName(u"empty_channels") self.gridLayout_2.addWidget(self.empty_channels, 8, 1, 1, 1) self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_2.addItem(self.verticalSpacer_3, 9, 0, 1, 1) self.label_67 = QLabel(self.HDF5) self.label_67.setObjectName(u"label_67") self.gridLayout_2.addWidget(self.label_67, 7, 0, 1, 1) self.label_65 = QLabel(self.HDF5) self.label_65.setObjectName(u"label_65") self.gridLayout_2.addWidget(self.label_65, 8, 0, 1, 1) self.export_compression = QComboBox(self.HDF5) self.export_compression.setObjectName(u"export_compression") self.gridLayout_2.addWidget(self.export_compression, 7, 1, 1, 1) self.line_30 = QFrame(self.HDF5) self.line_30.setObjectName(u"line_30") self.line_30.setFrameShape(QFrame.Shape.HLine) self.line_30.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_2.addWidget(self.line_30, 4, 0, 1, 2) self.single_time_base = QCheckBox(self.HDF5) self.single_time_base.setObjectName(u"single_time_base") self.gridLayout_2.addWidget(self.single_time_base, 0, 0, 1, 2) self.time_from_zero = QCheckBox(self.HDF5) self.time_from_zero.setObjectName(u"time_from_zero") self.gridLayout_2.addWidget(self.time_from_zero, 1, 0, 1, 2) self.time_as_date = QCheckBox(self.HDF5) self.time_as_date.setObjectName(u"time_as_date") self.gridLayout_2.addWidget(self.time_as_date, 2, 0, 1, 2) self.raw = QCheckBox(self.HDF5) self.raw.setObjectName(u"raw") self.gridLayout_2.addWidget(self.raw, 3, 0, 1, 2) self.use_display_names = QCheckBox(self.HDF5) self.use_display_names.setObjectName(u"use_display_names") self.gridLayout_2.addWidget(self.use_display_names, 5, 0, 1, 2) self.reduce_memory_usage = QCheckBox(self.HDF5) self.reduce_memory_usage.setObjectName(u"reduce_memory_usage") self.gridLayout_2.addWidget(self.reduce_memory_usage, 6, 0, 1, 2) self.output_options.addWidget(self.HDF5) self.MAT = QWidget() self.MAT.setObjectName(u"MAT") self.gridLayout_3 = QGridLayout(self.MAT) self.gridLayout_3.setSpacing(1) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.label_19 = QLabel(self.MAT) self.label_19.setObjectName(u"label_19") self.gridLayout_3.addWidget(self.label_19, 10, 0, 1, 1) self.label_70 = QLabel(self.MAT) self.label_70.setObjectName(u"label_70") self.gridLayout_3.addWidget(self.label_70, 7, 0, 1, 1) self.label_69 = QLabel(self.MAT) self.label_69.setObjectName(u"label_69") self.gridLayout_3.addWidget(self.label_69, 9, 0, 1, 1) self.export_compression_mat = QComboBox(self.MAT) self.export_compression_mat.setObjectName(u"export_compression_mat") self.gridLayout_3.addWidget(self.export_compression_mat, 7, 1, 1, 1) self.verticalSpacer_4 = QSpacerItem(20, 2, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_3.addItem(self.verticalSpacer_4, 11, 0, 1, 1) self.line_31 = QFrame(self.MAT) self.line_31.setObjectName(u"line_31") self.line_31.setFrameShape(QFrame.Shape.HLine) self.line_31.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_3.addWidget(self.line_31, 4, 0, 1, 2) self.empty_channels_mat = QComboBox(self.MAT) self.empty_channels_mat.setObjectName(u"empty_channels_mat") self.gridLayout_3.addWidget(self.empty_channels_mat, 8, 1, 1, 1) self.mat_format = QComboBox(self.MAT) self.mat_format.setObjectName(u"mat_format") self.gridLayout_3.addWidget(self.mat_format, 9, 1, 1, 1) self.oned_as = QComboBox(self.MAT) self.oned_as.setObjectName(u"oned_as") self.gridLayout_3.addWidget(self.oned_as, 10, 1, 1, 1) self.label_68 = QLabel(self.MAT) self.label_68.setObjectName(u"label_68") self.gridLayout_3.addWidget(self.label_68, 8, 0, 1, 1) self.single_time_base_mat = QCheckBox(self.MAT) self.single_time_base_mat.setObjectName(u"single_time_base_mat") self.gridLayout_3.addWidget(self.single_time_base_mat, 0, 0, 1, 2) self.time_from_zero_mat = QCheckBox(self.MAT) self.time_from_zero_mat.setObjectName(u"time_from_zero_mat") self.gridLayout_3.addWidget(self.time_from_zero_mat, 1, 0, 1, 2) self.time_as_date_mat = QCheckBox(self.MAT) self.time_as_date_mat.setObjectName(u"time_as_date_mat") self.gridLayout_3.addWidget(self.time_as_date_mat, 2, 0, 1, 2) self.raw_mat = QCheckBox(self.MAT) self.raw_mat.setObjectName(u"raw_mat") self.gridLayout_3.addWidget(self.raw_mat, 3, 0, 1, 2) self.use_display_names_mat = QCheckBox(self.MAT) self.use_display_names_mat.setObjectName(u"use_display_names_mat") self.gridLayout_3.addWidget(self.use_display_names_mat, 5, 0, 1, 2) self.reduce_memory_usage_mat = QCheckBox(self.MAT) self.reduce_memory_usage_mat.setObjectName(u"reduce_memory_usage_mat") self.gridLayout_3.addWidget(self.reduce_memory_usage_mat, 6, 0, 1, 2) self.output_options.addWidget(self.MAT) self.CSV = QWidget() self.CSV.setObjectName(u"CSV") self.gridLayout = QGridLayout(self.CSV) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.empty_channels_csv = QComboBox(self.CSV) self.empty_channels_csv.setObjectName(u"empty_channels_csv") self.gridLayout.addWidget(self.empty_channels_csv, 7, 1, 1, 2) self.label_66 = QLabel(self.CSV) self.label_66.setObjectName(u"label_66") self.gridLayout.addWidget(self.label_66, 7, 0, 1, 1) self.doublequote = QCheckBox(self.CSV) self.doublequote.setObjectName(u"doublequote") self.doublequote.setChecked(True) self.gridLayout.addWidget(self.doublequote, 9, 0, 1, 1) self.line_32 = QFrame(self.CSV) self.line_32.setObjectName(u"line_32") self.line_32.setFrameShape(QFrame.Shape.HLine) self.line_32.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout.addWidget(self.line_32, 4, 0, 1, 3) self.time_from_zero_csv = QCheckBox(self.CSV) self.time_from_zero_csv.setObjectName(u"time_from_zero_csv") self.gridLayout.addWidget(self.time_from_zero_csv, 1, 0, 1, 3) self.quotechar = QLineEdit(self.CSV) self.quotechar.setObjectName(u"quotechar") self.quotechar.setMaxLength(1) self.gridLayout.addWidget(self.quotechar, 12, 1, 1, 2) self.label_4 = QLabel(self.CSV) self.label_4.setObjectName(u"label_4") self.gridLayout.addWidget(self.label_4, 11, 0, 1, 1) self.delimiter = QLineEdit(self.CSV) self.delimiter.setObjectName(u"delimiter") self.delimiter.setMaxLength(2) self.delimiter.setClearButtonEnabled(False) self.gridLayout.addWidget(self.delimiter, 8, 1, 1, 2) self.label_5 = QLabel(self.CSV) self.label_5.setObjectName(u"label_5") self.gridLayout.addWidget(self.label_5, 12, 0, 1, 1) self.single_time_base_csv = QCheckBox(self.CSV) self.single_time_base_csv.setObjectName(u"single_time_base_csv") self.gridLayout.addWidget(self.single_time_base_csv, 0, 0, 1, 3) self.label_2 = QLabel(self.CSV) self.label_2.setObjectName(u"label_2") self.gridLayout.addWidget(self.label_2, 8, 0, 1, 1) self.label_3 = QLabel(self.CSV) self.label_3.setObjectName(u"label_3") self.gridLayout.addWidget(self.label_3, 10, 0, 1, 1) self.use_display_names_csv = QCheckBox(self.CSV) self.use_display_names_csv.setObjectName(u"use_display_names_csv") self.gridLayout.addWidget(self.use_display_names_csv, 5, 0, 1, 3) self.label_6 = QLabel(self.CSV) self.label_6.setObjectName(u"label_6") self.gridLayout.addWidget(self.label_6, 13, 0, 1, 1) self.quoting = QComboBox(self.CSV) self.quoting.addItem("") self.quoting.addItem("") self.quoting.addItem("") self.quoting.addItem("") self.quoting.setObjectName(u"quoting") self.gridLayout.addWidget(self.quoting, 13, 1, 1, 2) self.raw_csv = QCheckBox(self.CSV) self.raw_csv.setObjectName(u"raw_csv") self.gridLayout.addWidget(self.raw_csv, 3, 0, 1, 3) self.lineterminator = QLineEdit(self.CSV) self.lineterminator.setObjectName(u"lineterminator") self.gridLayout.addWidget(self.lineterminator, 11, 1, 1, 2) self.escapechar = QLineEdit(self.CSV) self.escapechar.setObjectName(u"escapechar") self.escapechar.setMaxLength(1) self.gridLayout.addWidget(self.escapechar, 10, 1, 1, 2) self.time_as_date_csv = QCheckBox(self.CSV) self.time_as_date_csv.setObjectName(u"time_as_date_csv") self.gridLayout.addWidget(self.time_as_date_csv, 2, 0, 1, 3) self.add_units = QCheckBox(self.CSV) self.add_units.setObjectName(u"add_units") self.gridLayout.addWidget(self.add_units, 6, 0, 1, 3) self.output_options.addWidget(self.CSV) self.page = QWidget() self.page.setObjectName(u"page") self.output_options.addWidget(self.page) self.verticalLayout_20.addWidget(self.output_options) self.verticalLayout_3.addWidget(self.groupBox_10) self.verticalSpacer_2 = QSpacerItem(20, 2, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_3.addItem(self.verticalSpacer_2) self.apply_btn = QPushButton(self.scrollAreaWidgetContents) self.apply_btn.setObjectName(u"apply_btn") self.apply_btn.setIcon(icon2) self.verticalLayout_3.addWidget(self.apply_btn) self.verticalLayout_3.setStretch(3, 1) self.verticalLayout_4.addLayout(self.verticalLayout_3) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.horizontalLayout.addWidget(self.scrollArea) icon10 = QIcon() icon10.addFile(u":/convert.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.aspects.addTab(self.modify, icon10, "") self.extract_bus_tab = QWidget() self.extract_bus_tab.setObjectName(u"extract_bus_tab") self.verticalLayout_8 = QVBoxLayout(self.extract_bus_tab) self.verticalLayout_8.setSpacing(1) self.verticalLayout_8.setObjectName(u"verticalLayout_8") self.verticalLayout_8.setContentsMargins(1, 1, 1, 1) self.scrollArea_2 = QScrollArea(self.extract_bus_tab) self.scrollArea_2.setObjectName(u"scrollArea_2") self.scrollArea_2.setWidgetResizable(True) self.scrollAreaWidgetContents_2 = QWidget() self.scrollAreaWidgetContents_2.setObjectName(u"scrollAreaWidgetContents_2") self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 999, 609)) self.gridLayout_7 = QGridLayout(self.scrollAreaWidgetContents_2) self.gridLayout_7.setSpacing(1) self.gridLayout_7.setObjectName(u"gridLayout_7") self.gridLayout_7.setContentsMargins(1, 1, 1, 1) self.groupBox_3 = QGroupBox(self.scrollAreaWidgetContents_2) self.groupBox_3.setObjectName(u"groupBox_3") self.gridLayout_6 = QGridLayout(self.groupBox_3) self.gridLayout_6.setSpacing(1) self.gridLayout_6.setObjectName(u"gridLayout_6") self.gridLayout_6.setContentsMargins(1, 1, 1, 1) self.time_from_zero_bus = QCheckBox(self.groupBox_3) self.time_from_zero_bus.setObjectName(u"time_from_zero_bus") self.gridLayout_6.addWidget(self.time_from_zero_bus, 1, 0, 1, 3) self.quotechar_bus = QLineEdit(self.groupBox_3) self.quotechar_bus.setObjectName(u"quotechar_bus") self.quotechar_bus.setMaxLength(1) self.gridLayout_6.addWidget(self.quotechar_bus, 11, 2, 1, 1) self.export_raster_bus = QDoubleSpinBox(self.groupBox_3) self.export_raster_bus.setObjectName(u"export_raster_bus") self.export_raster_bus.setDecimals(6) self.gridLayout_6.addWidget(self.export_raster_bus, 4, 2, 1, 1) self.add_units_bus = QCheckBox(self.groupBox_3) self.add_units_bus.setObjectName(u"add_units_bus") self.gridLayout_6.addWidget(self.add_units_bus, 3, 0, 1, 3) self.single_time_base_bus = QCheckBox(self.groupBox_3) self.single_time_base_bus.setObjectName(u"single_time_base_bus") self.gridLayout_6.addWidget(self.single_time_base_bus, 0, 0, 1, 3) self.bus_time_as_date = QCheckBox(self.groupBox_3) self.bus_time_as_date.setObjectName(u"bus_time_as_date") self.gridLayout_6.addWidget(self.bus_time_as_date, 2, 0, 1, 3) self.doublequote_bus = QCheckBox(self.groupBox_3) self.doublequote_bus.setObjectName(u"doublequote_bus") self.doublequote_bus.setChecked(True) self.gridLayout_6.addWidget(self.doublequote_bus, 7, 0, 1, 3) self.label_8 = QLabel(self.groupBox_3) self.label_8.setObjectName(u"label_8") self.gridLayout_6.addWidget(self.label_8, 6, 0, 1, 1) self.label_11 = QLabel(self.groupBox_3) self.label_11.setObjectName(u"label_11") self.gridLayout_6.addWidget(self.label_11, 10, 0, 1, 2) self.label_23 = QLabel(self.groupBox_3) self.label_23.setObjectName(u"label_23") self.gridLayout_6.addWidget(self.label_23, 4, 0, 1, 1) self.escapechar_bus = QLineEdit(self.groupBox_3) self.escapechar_bus.setObjectName(u"escapechar_bus") self.escapechar_bus.setMaxLength(1) self.gridLayout_6.addWidget(self.escapechar_bus, 8, 2, 1, 1) self.lineterminator_bus = QLineEdit(self.groupBox_3) self.lineterminator_bus.setObjectName(u"lineterminator_bus") self.gridLayout_6.addWidget(self.lineterminator_bus, 10, 2, 1, 1) self.quoting_bus = QComboBox(self.groupBox_3) self.quoting_bus.addItem("") self.quoting_bus.addItem("") self.quoting_bus.addItem("") self.quoting_bus.addItem("") self.quoting_bus.setObjectName(u"quoting_bus") self.gridLayout_6.addWidget(self.quoting_bus, 12, 2, 1, 1) self.label_10 = QLabel(self.groupBox_3) self.label_10.setObjectName(u"label_10") self.gridLayout_6.addWidget(self.label_10, 11, 0, 1, 1) self.line_13 = QFrame(self.groupBox_3) self.line_13.setObjectName(u"line_13") self.line_13.setFrameShape(QFrame.Shape.HLine) self.line_13.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_6.addWidget(self.line_13, 13, 0, 1, 3) self.delimiter_bus = QLineEdit(self.groupBox_3) self.delimiter_bus.setObjectName(u"delimiter_bus") self.delimiter_bus.setMaxLength(2) self.delimiter_bus.setClearButtonEnabled(False) self.gridLayout_6.addWidget(self.delimiter_bus, 6, 2, 1, 1) self.label_25 = QLabel(self.groupBox_3) self.label_25.setObjectName(u"label_25") self.gridLayout_6.addWidget(self.label_25, 5, 0, 1, 2) self.label_7 = QLabel(self.groupBox_3) self.label_7.setObjectName(u"label_7") self.gridLayout_6.addWidget(self.label_7, 12, 0, 1, 1) self.label_9 = QLabel(self.groupBox_3) self.label_9.setObjectName(u"label_9") self.gridLayout_6.addWidget(self.label_9, 8, 0, 1, 1) self.extract_bus_csv_btn = QPushButton(self.groupBox_3) self.extract_bus_csv_btn.setObjectName(u"extract_bus_csv_btn") icon11 = QIcon() icon11.addFile(u":/csv.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.extract_bus_csv_btn.setIcon(icon11) self.gridLayout_6.addWidget(self.extract_bus_csv_btn, 14, 2, 1, 1) self.empty_channels_bus = QComboBox(self.groupBox_3) self.empty_channels_bus.setObjectName(u"empty_channels_bus") self.gridLayout_6.addWidget(self.empty_channels_bus, 5, 2, 1, 1) self.gridLayout_6.setColumnStretch(0, 1) self.gridLayout_7.addWidget(self.groupBox_3, 2, 1, 1, 1) self.output_info_bus = QTextEdit(self.scrollAreaWidgetContents_2) self.output_info_bus.setObjectName(u"output_info_bus") self.output_info_bus.setReadOnly(True) self.gridLayout_7.addWidget(self.output_info_bus, 0, 2, 3, 1) self.groupBox_2 = QGroupBox(self.scrollAreaWidgetContents_2) self.groupBox_2.setObjectName(u"groupBox_2") self.gridLayout_5 = QGridLayout(self.groupBox_2) self.gridLayout_5.setSpacing(1) self.gridLayout_5.setObjectName(u"gridLayout_5") self.gridLayout_5.setContentsMargins(1, 1, 1, 1) self.label__1 = QLabel(self.groupBox_2) self.label__1.setObjectName(u"label__1") self.gridLayout_5.addWidget(self.label__1, 0, 0, 1, 1) self.label_26 = QLabel(self.groupBox_2) self.label_26.setObjectName(u"label_26") self.gridLayout_5.addWidget(self.label_26, 3, 1, 1, 1) self.extract_bus_btn = QPushButton(self.groupBox_2) self.extract_bus_btn.setObjectName(u"extract_bus_btn") icon12 = QIcon() icon12.addFile(u":/down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.extract_bus_btn.setIcon(icon12) self.gridLayout_5.addWidget(self.extract_bus_btn, 5, 1, 1, 2) self.horizontalSpacer_4 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_5.addItem(self.horizontalSpacer_4, 5, 0, 1, 1) self.extract_bus_format = QComboBox(self.groupBox_2) self.extract_bus_format.setObjectName(u"extract_bus_format") self.extract_bus_format.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents) self.gridLayout_5.addWidget(self.extract_bus_format, 1, 1, 1, 2) self.line_12 = QFrame(self.groupBox_2) self.line_12.setObjectName(u"line_12") self.line_12.setFrameShape(QFrame.Shape.HLine) self.line_12.setFrameShadow(QFrame.Shadow.Sunken) self.gridLayout_5.addWidget(self.line_12, 4, 0, 1, 3) self.extract_bus_compression = QComboBox(self.groupBox_2) self.extract_bus_compression.setObjectName(u"extract_bus_compression") self.extract_bus_compression.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents) self.gridLayout_5.addWidget(self.extract_bus_compression, 0, 1, 1, 2) self.label_24 = QLabel(self.groupBox_2) self.label_24.setObjectName(u"label_24") self.gridLayout_5.addWidget(self.label_24, 1, 0, 1, 1) self.gridLayout_7.addWidget(self.groupBox_2, 2, 0, 1, 1) self.tabWidget = QTabWidget(self.scrollAreaWidgetContents_2) self.tabWidget.setObjectName(u"tabWidget") self.tab = QWidget() self.tab.setObjectName(u"tab") self.gridLayout_4 = QGridLayout(self.tab) self.gridLayout_4.setSpacing(1) self.gridLayout_4.setObjectName(u"gridLayout_4") self.gridLayout_4.setContentsMargins(1, 1, 1, 1) self.load_can_database_btn = QPushButton(self.tab) self.load_can_database_btn.setObjectName(u"load_can_database_btn") self.load_can_database_btn.setIcon(icon) self.gridLayout_4.addWidget(self.load_can_database_btn, 0, 0, 1, 1) self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_4.addItem(self.horizontalSpacer, 0, 1, 1, 1) self.can_database_list = MinimalListWidget(self.tab) self.can_database_list.setObjectName(u"can_database_list") self.gridLayout_4.addWidget(self.can_database_list, 1, 0, 1, 2) self.tabWidget.addTab(self.tab, "") self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") self.gridLayout_8 = QGridLayout(self.tab_2) self.gridLayout_8.setSpacing(1) self.gridLayout_8.setObjectName(u"gridLayout_8") self.gridLayout_8.setContentsMargins(1, 1, 1, 1) self.load_lin_database_btn = QPushButton(self.tab_2) self.load_lin_database_btn.setObjectName(u"load_lin_database_btn") self.load_lin_database_btn.setIcon(icon) self.gridLayout_8.addWidget(self.load_lin_database_btn, 0, 0, 1, 1) self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_8.addItem(self.horizontalSpacer_3, 0, 1, 1, 1) self.lin_database_list = MinimalListWidget(self.tab_2) self.lin_database_list.setObjectName(u"lin_database_list") self.gridLayout_8.addWidget(self.lin_database_list, 1, 0, 1, 2) self.tabWidget.addTab(self.tab_2, "") self.gridLayout_7.addWidget(self.tabWidget, 0, 0, 1, 2) self.horizontalLayout_3 = QHBoxLayout() self.horizontalLayout_3.setSpacing(1) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.label_12 = QLabel(self.scrollAreaWidgetContents_2) self.label_12.setObjectName(u"label_12") self.horizontalLayout_3.addWidget(self.label_12) self.prefix = QLineEdit(self.scrollAreaWidgetContents_2) self.prefix.setObjectName(u"prefix") self.prefix.setMinimumSize(QSize(0, 0)) self.horizontalLayout_3.addWidget(self.prefix) self.horizontalSpacer_5 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_3.addItem(self.horizontalSpacer_5) self.horizontalLayout_3.setStretch(2, 1) self.gridLayout_7.addLayout(self.horizontalLayout_3, 1, 0, 1, 2) self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) self.verticalLayout_8.addWidget(self.scrollArea_2) self.aspects.addTab(self.extract_bus_tab, icon12, "") self.info_tab = QWidget() self.info_tab.setObjectName(u"info_tab") self.gridLayout_9 = QGridLayout(self.info_tab) self.gridLayout_9.setSpacing(1) self.gridLayout_9.setObjectName(u"gridLayout_9") self.gridLayout_9.setContentsMargins(1, 1, 1, 1) self.info = QTreeWidget(self.info_tab) self.info.setObjectName(u"info") self.info.setUniformRowHeights(False) self.gridLayout_9.addWidget(self.info, 0, 0, 1, 1) icon13 = QIcon() icon13.addFile(u":/info.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.aspects.addTab(self.info_tab, icon13, "") self.attachments_tab = QWidget() self.attachments_tab.setObjectName(u"attachments_tab") self.verticalLayout_10 = QVBoxLayout(self.attachments_tab) self.verticalLayout_10.setSpacing(1) self.verticalLayout_10.setObjectName(u"verticalLayout_10") self.verticalLayout_10.setContentsMargins(1, 1, 1, 1) self.attachments = QListWidget(self.attachments_tab) self.attachments.setObjectName(u"attachments") self.verticalLayout_10.addWidget(self.attachments) self.aspects.addTab(self.attachments_tab, icon7, "") self.verticalLayout.addWidget(self.aspects) self.retranslateUi(file_widget) self.aspects.setCurrentIndex(0) self.output_options.setCurrentIndex(0) self.quoting.setCurrentIndex(1) self.quoting_bus.setCurrentIndex(1) self.tabWidget.setCurrentIndex(0) QMetaObject.connectSlotsByName(file_widget) # setupUi def retranslateUi(self, file_widget): file_widget.setWindowTitle(QCoreApplication.translate("file_widget", u"Form", None)) #if QT_CONFIG(tooltip) self.aspects.setToolTip("") #endif // QT_CONFIG(tooltip) self.channel_view.setItemText(0, QCoreApplication.translate("file_widget", u"Natural sort", None)) self.channel_view.setItemText(1, QCoreApplication.translate("file_widget", u"Internal file structure", None)) self.channel_view.setItemText(2, QCoreApplication.translate("file_widget", u"Selected channels only", None)) ___qtreewidgetitem = self.channels_tree.headerItem() ___qtreewidgetitem.setText(0, QCoreApplication.translate("file_widget", u"Channels", None)); #if QT_CONFIG(tooltip) self.channels_tree.setToolTip(QCoreApplication.translate("file_widget", u"Double click channel to see extended information", None)) #endif // QT_CONFIG(tooltip) #if QT_CONFIG(tooltip) self.load_channel_list_btn.setToolTip(QCoreApplication.translate("file_widget", u"Load display file", None)) #endif // QT_CONFIG(tooltip) self.load_channel_list_btn.setText("") #if QT_CONFIG(tooltip) self.save_channel_list_btn.setToolTip(QCoreApplication.translate("file_widget", u"Save display file", None)) #endif // QT_CONFIG(tooltip) self.save_channel_list_btn.setText("") #if QT_CONFIG(tooltip) self.select_all_btn.setToolTip(QCoreApplication.translate("file_widget", u"Select all the channels", None)) #endif // QT_CONFIG(tooltip) self.select_all_btn.setText("") #if QT_CONFIG(tooltip) self.clear_channels_btn.setToolTip(QCoreApplication.translate("file_widget", u"Clear all selected channels", None)) #endif // QT_CONFIG(tooltip) self.clear_channels_btn.setText("") #if QT_CONFIG(tooltip) self.advanced_search_btn.setToolTip(QCoreApplication.translate("file_widget", u"Search and select channels", None)) #endif // QT_CONFIG(tooltip) self.advanced_search_btn.setText("") #if QT_CONFIG(tooltip) self.create_window_btn.setToolTip(QCoreApplication.translate("file_widget", u"Add new window", None)) #endif // QT_CONFIG(tooltip) self.create_window_btn.setText("") #if QT_CONFIG(tooltip) self.load_embedded_channel_list_btn.setToolTip(QCoreApplication.translate("file_widget", u"Load embedded display file", None)) #endif // QT_CONFIG(tooltip) self.load_embedded_channel_list_btn.setText("") #if QT_CONFIG(tooltip) self.save_embedded_channel_list_btn.setToolTip(QCoreApplication.translate("file_widget", u"Embed display file", None)) #endif // QT_CONFIG(tooltip) self.save_embedded_channel_list_btn.setText("") self.aspects.setTabText(self.aspects.indexOf(self.channels_tab), QCoreApplication.translate("file_widget", u"Channels", None)) self.filter_view.setItemText(0, QCoreApplication.translate("file_widget", u"Natural sort", None)) self.filter_view.setItemText(1, QCoreApplication.translate("file_widget", u"Internal file structure", None)) self.filter_view.setItemText(2, QCoreApplication.translate("file_widget", u"Selected channels only", None)) ___qtreewidgetitem1 = self.filter_tree.headerItem() ___qtreewidgetitem1.setText(0, QCoreApplication.translate("file_widget", u"Channels", None)); #if QT_CONFIG(tooltip) self.filter_tree.setToolTip(QCoreApplication.translate("file_widget", u"Double click channel to see extended information", None)) #endif // QT_CONFIG(tooltip) #if QT_CONFIG(tooltip) self.load_filter_list_btn.setToolTip(QCoreApplication.translate("file_widget", u"Load channel selection list", None)) #endif // QT_CONFIG(tooltip) self.load_filter_list_btn.setText("") #if QT_CONFIG(tooltip) self.save_filter_list_btn.setToolTip(QCoreApplication.translate("file_widget", u"Save channel selection list", None)) #endif // QT_CONFIG(tooltip) self.save_filter_list_btn.setText("") #if QT_CONFIG(tooltip) self.clear_filter_btn.setToolTip(QCoreApplication.translate("file_widget", u"Clear selection", None)) #endif // QT_CONFIG(tooltip) self.clear_filter_btn.setText("") #if QT_CONFIG(tooltip) self.advanced_serch_filter_btn.setToolTip(QCoreApplication.translate("file_widget", u"Search and select channels", None)) #endif // QT_CONFIG(tooltip) self.advanced_serch_filter_btn.setText("") self.label.setText(QCoreApplication.translate("file_widget", u"All selected channels", None)) self.cut_group.setTitle(QCoreApplication.translate("file_widget", u"Cut", None)) self.label_59.setText(QCoreApplication.translate("file_widget", u"Start", None)) self.cut_stop.setSuffix(QCoreApplication.translate("file_widget", u"s", None)) self.label_60.setText(QCoreApplication.translate("file_widget", u"End", None)) self.cut_start.setSuffix(QCoreApplication.translate("file_widget", u"s", None)) self.whence.setText(QCoreApplication.translate("file_widget", u"Start relative to first time stamp", None)) self.cut_time_from_zero.setText(QCoreApplication.translate("file_widget", u"Time from 0s", None)) self.resample_group.setTitle(QCoreApplication.translate("file_widget", u"Resample", None)) self.raster_type_step.setText(QCoreApplication.translate("file_widget", u"step", None)) self.raster.setSuffix(QCoreApplication.translate("file_widget", u"s", None)) self.raster_type_channel.setText(QCoreApplication.translate("file_widget", u"channel", None)) #if QT_CONFIG(tooltip) self.raster_search_btn.setToolTip(QCoreApplication.translate("file_widget", u"Search raster channel", None)) #endif // QT_CONFIG(tooltip) self.raster_search_btn.setText("") self.resample_time_from_zero.setText(QCoreApplication.translate("file_widget", u"Time from 0s", None)) self.groupBox_10.setTitle(QCoreApplication.translate("file_widget", u"Output format", None)) self.label_28.setText(QCoreApplication.translate("file_widget", u"Split size ", None)) self.mdf_split.setText(QCoreApplication.translate("file_widget", u"Split data blocks", None)) self.label_29.setText(QCoreApplication.translate("file_widget", u"Compression", None)) self.groupBox_9.setTitle(QCoreApplication.translate("file_widget", u"Scramble", None)) self.scramble_btn.setText(QCoreApplication.translate("file_widget", u"Scramble texts", None)) self.label_61.setText(QCoreApplication.translate("file_widget", u"Anonymize the measurements: scramble all texts and replace them with random strings", None)) self.label_27.setText(QCoreApplication.translate("file_widget", u"Version", None)) self.mdf_split_size.setSuffix(QCoreApplication.translate("file_widget", u"MB", None)) self.label_67.setText(QCoreApplication.translate("file_widget", u"Compression", None)) self.label_65.setText(QCoreApplication.translate("file_widget", u"Empty channels", None)) self.single_time_base.setText(QCoreApplication.translate("file_widget", u"Single time base", None)) self.time_from_zero.setText(QCoreApplication.translate("file_widget", u"Time from 0s", None)) self.time_as_date.setText(QCoreApplication.translate("file_widget", u"Time as date", None)) self.raw.setText(QCoreApplication.translate("file_widget", u"Raw values", None)) self.use_display_names.setText(QCoreApplication.translate("file_widget", u"Use display names", None)) self.reduce_memory_usage.setText(QCoreApplication.translate("file_widget", u"Reduce memory usage", None)) self.label_19.setText(QCoreApplication.translate("file_widget", u".mat oned_as", None)) self.label_70.setText(QCoreApplication.translate("file_widget", u"Compression", None)) self.label_69.setText(QCoreApplication.translate("file_widget", u".mat format", None)) self.label_68.setText(QCoreApplication.translate("file_widget", u"Empty channels", None)) self.single_time_base_mat.setText(QCoreApplication.translate("file_widget", u"Single time base", None)) self.time_from_zero_mat.setText(QCoreApplication.translate("file_widget", u"Time from 0s", None)) self.time_as_date_mat.setText(QCoreApplication.translate("file_widget", u"Time as date", None)) self.raw_mat.setText(QCoreApplication.translate("file_widget", u"Raw values", None)) self.use_display_names_mat.setText(QCoreApplication.translate("file_widget", u"Use display names", None)) self.reduce_memory_usage_mat.setText(QCoreApplication.translate("file_widget", u"Reduce memory usage", None)) self.label_66.setText(QCoreApplication.translate("file_widget", u"Empty channels", None)) self.doublequote.setText(QCoreApplication.translate("file_widget", u"Double quote", None)) self.time_from_zero_csv.setText(QCoreApplication.translate("file_widget", u"Time from 0s", None)) self.quotechar.setText(QCoreApplication.translate("file_widget", u"\"", None)) self.label_4.setText(QCoreApplication.translate("file_widget", u"Line Terminator", None)) self.delimiter.setText(QCoreApplication.translate("file_widget", u",", None)) self.label_5.setText(QCoreApplication.translate("file_widget", u"Quote Char", None)) self.single_time_base_csv.setText(QCoreApplication.translate("file_widget", u"Single time base", None)) self.label_2.setText(QCoreApplication.translate("file_widget", u"Delimiter", None)) self.label_3.setText(QCoreApplication.translate("file_widget", u"Escape Char", None)) self.use_display_names_csv.setText(QCoreApplication.translate("file_widget", u"Use display names", None)) self.label_6.setText(QCoreApplication.translate("file_widget", u"Quoting", None)) self.quoting.setItemText(0, QCoreApplication.translate("file_widget", u"ALL", None)) self.quoting.setItemText(1, QCoreApplication.translate("file_widget", u"MINIMAL", None)) self.quoting.setItemText(2, QCoreApplication.translate("file_widget", u"NONNUMERIC", None)) self.quoting.setItemText(3, QCoreApplication.translate("file_widget", u"NONE", None)) self.raw_csv.setText(QCoreApplication.translate("file_widget", u"Raw values", None)) self.lineterminator.setText(QCoreApplication.translate("file_widget", u"\\r\\n", None)) self.escapechar.setInputMask("") self.escapechar.setPlaceholderText(QCoreApplication.translate("file_widget", u"None", None)) self.time_as_date_csv.setText(QCoreApplication.translate("file_widget", u"Time as date", None)) self.add_units.setText(QCoreApplication.translate("file_widget", u"Add units", None)) self.apply_btn.setText(QCoreApplication.translate("file_widget", u"Apply", None)) self.aspects.setTabText(self.aspects.indexOf(self.modify), QCoreApplication.translate("file_widget", u"Modify && Export", None)) self.groupBox_3.setTitle(QCoreApplication.translate("file_widget", u"CSV", None)) self.time_from_zero_bus.setText(QCoreApplication.translate("file_widget", u"Time from 0s", None)) self.quotechar_bus.setText(QCoreApplication.translate("file_widget", u"\"", None)) self.export_raster_bus.setSuffix(QCoreApplication.translate("file_widget", u"s", None)) self.add_units_bus.setText(QCoreApplication.translate("file_widget", u"Add units", None)) self.single_time_base_bus.setText(QCoreApplication.translate("file_widget", u"Single time base", None)) self.bus_time_as_date.setText(QCoreApplication.translate("file_widget", u"Time as date", None)) self.doublequote_bus.setText(QCoreApplication.translate("file_widget", u"Double quote", None)) self.label_8.setText(QCoreApplication.translate("file_widget", u"Delimiter", None)) self.label_11.setText(QCoreApplication.translate("file_widget", u"Line Terminator", None)) self.label_23.setText(QCoreApplication.translate("file_widget", u"Raster", None)) self.escapechar_bus.setInputMask("") self.escapechar_bus.setPlaceholderText(QCoreApplication.translate("file_widget", u"None", None)) self.lineterminator_bus.setText(QCoreApplication.translate("file_widget", u"\\r\\n", None)) self.quoting_bus.setItemText(0, QCoreApplication.translate("file_widget", u"ALL", None)) self.quoting_bus.setItemText(1, QCoreApplication.translate("file_widget", u"MINIMAL", None)) self.quoting_bus.setItemText(2, QCoreApplication.translate("file_widget", u"NONNUMERIC", None)) self.quoting_bus.setItemText(3, QCoreApplication.translate("file_widget", u"NONE", None)) self.label_10.setText(QCoreApplication.translate("file_widget", u"Quote Char", None)) self.delimiter_bus.setText(QCoreApplication.translate("file_widget", u",", None)) self.label_25.setText(QCoreApplication.translate("file_widget", u"Empty channels", None)) self.label_7.setText(QCoreApplication.translate("file_widget", u"Quoting", None)) self.label_9.setText(QCoreApplication.translate("file_widget", u"Escape Char", None)) self.extract_bus_csv_btn.setText(QCoreApplication.translate("file_widget", u"Export to CSV ", None)) self.groupBox_2.setTitle(QCoreApplication.translate("file_widget", u"MDF", None)) self.label__1.setText(QCoreApplication.translate("file_widget", u"Compression", None)) self.label_26.setText("") self.extract_bus_btn.setText(QCoreApplication.translate("file_widget", u"Extract Bus signals", None)) self.label_24.setText(QCoreApplication.translate("file_widget", u"Version", None)) self.load_can_database_btn.setText(QCoreApplication.translate("file_widget", u"Load CAN database", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("file_widget", u"CAN", None)) self.load_lin_database_btn.setText(QCoreApplication.translate("file_widget", u"Load LIN database", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("file_widget", u"LIN", None)) self.label_12.setText(QCoreApplication.translate("file_widget", u"Prefix", None)) self.aspects.setTabText(self.aspects.indexOf(self.extract_bus_tab), QCoreApplication.translate("file_widget", u"Bus Logging", None)) ___qtreewidgetitem2 = self.info.headerItem() ___qtreewidgetitem2.setText(1, QCoreApplication.translate("file_widget", u"Value", None)); ___qtreewidgetitem2.setText(0, QCoreApplication.translate("file_widget", u"Cathegory", None)); self.aspects.setTabText(self.aspects.indexOf(self.info_tab), QCoreApplication.translate("file_widget", u"Info", None)) self.aspects.setTabText(self.aspects.indexOf(self.attachments_tab), QCoreApplication.translate("file_widget", u"Attachments", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/file_widget.ui000066400000000000000000002150701502633300400213570ustar00rootroot00000000000000 file_widget 0 0 1034 621 0 0 1 1 Form 1 1 1 1 1 QTabWidget::TabPosition::West 0 false :/graph.png:/graph.png Channels 1 1 1 1 1 Qt::Orientation::Horizontal 1 Natural sort Internal file structure Selected channels only Double click channel to see extended information Channels 1 Load display file :/open.png:/open.png Qt::Orientation::Horizontal QSizePolicy::Policy::Fixed 20 20 Save display file :/save.png:/save.png Select all the channels :/checkmark.png:/checkmark.png Clear all selected channels :/erase.png:/erase.png Search and select channels :/search.png:/search.png Add new window :/plus.png:/plus.png Qt::Orientation::Horizontal QSizePolicy::Policy::Fixed 20 20 Load embedded display file :/load_embed.png:/load_embed.png Embed display file :/attach.png:/attach.png Qt::Orientation::Horizontal 40 20 :/convert.png:/convert.png Modify && Export 1 1 1 1 1 1 Natural sort Internal file structure Selected channels only Double click channel to see extended information Channels 1 Load channel selection list :/open.png:/open.png Save channel selection list :/save.png:/save.png Clear selection :/erase.png:/erase.png Search and select channels :/search.png:/search.png Qt::Orientation::Horizontal 40 20 1 All selected channels QListView::ViewMode::ListMode true true true 0 0 331 609 1 1 1 1 1 1 Cut true false 1 1 1 1 1 Start s 6 -9999999999999999635896294965248.000000000000000 999999999999999983222784.000000000000000 End s 6 -9999999999999999635896294965248.000000000000000 999999999999999983222784.000000000000000 Start relative to first time stamp Time from 0s Resample true false 1 1 1 1 1 step true 0 0 0 0 s 6 0.000001000000000 channel false QComboBox::InsertPolicy::InsertAtBottom QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon Search raster channel :/search.png:/search.png Time from 0s Output format 1 1 1 1 1 0 1 1 1 1 1 Split size Split data blocks true Compression Qt::Orientation::Horizontal Scramble 1 1 1 1 1 Scramble texts :/scramble.png:/scramble.png Qt::Orientation::Horizontal 2 20 Anonymize the measurements: scramble all texts and replace them with random strings true Version 0 0 MB 4.000000000000000 1 1 1 1 1 Qt::Orientation::Vertical 20 40 Compression Empty channels Qt::Orientation::Horizontal Single time base Time from 0s Time as date Raw values Use display names Reduce memory usage 1 1 1 1 1 .mat oned_as Compression .mat format Qt::Orientation::Vertical 20 2 Qt::Orientation::Horizontal Empty channels Single time base Time from 0s Time as date Raw values Use display names Reduce memory usage 1 1 1 1 1 Empty channels Double quote true Qt::Orientation::Horizontal Time from 0s " 1 Line Terminator , 2 false Quote Char Single time base Delimiter Escape Char Use display names Quoting 1 ALL MINIMAL NONNUMERIC NONE Raw values \r\n 1 None Time as date Add units Qt::Orientation::Vertical 20 2 Apply :/checkmark.png:/checkmark.png :/down.png:/down.png Bus Logging 1 1 1 1 1 true 0 0 999 609 1 1 1 1 1 CSV 1 1 1 1 1 Time from 0s " 1 s 6 Add units Single time base Time as date Double quote true Delimiter Line Terminator Raster 1 None \r\n 1 ALL MINIMAL NONNUMERIC NONE Quote Char Qt::Orientation::Horizontal , 2 false Empty channels Quoting Escape Char Export to CSV :/csv.png:/csv.png true MDF 1 1 1 1 1 Compression Extract Bus signals :/down.png:/down.png Qt::Orientation::Horizontal 40 20 QComboBox::SizeAdjustPolicy::AdjustToContents Qt::Orientation::Horizontal QComboBox::SizeAdjustPolicy::AdjustToContents Version 0 CAN 1 1 1 1 1 Load CAN database :/open.png:/open.png Qt::Orientation::Horizontal 40 20 LIN 1 1 1 1 1 Load LIN database :/open.png:/open.png Qt::Orientation::Horizontal 40 20 1 Prefix 0 0 Qt::Orientation::Horizontal 40 20 :/info.png:/info.png Info 1 1 1 1 1 false Cathegory Value :/attach.png:/attach.png Attachments 1 1 1 1 1 MinimalListWidget QListWidget
asammdf.gui.widgets.list.h
TreeWidget QTreeWidget
asammdf/gui/widgets/tree.h
asammdf-8.5.1/src/asammdf/gui/ui/functions_manager.py000066400000000000000000000230611502633300400226070ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'functions_manager.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QGridLayout, QGroupBox, QHBoxLayout, QListWidgetItem, QPlainTextEdit, QPushButton, QSizePolicy, QSpacerItem, QTabWidget, QVBoxLayout, QWidget) from asammdf.gui.widgets.list import MinimalListWidget from . import resource_rc class Ui_FunctionsManager(object): def setupUi(self, FunctionsManager): if not FunctionsManager.objectName(): FunctionsManager.setObjectName(u"FunctionsManager") FunctionsManager.resize(1035, 703) self.verticalLayout = QVBoxLayout(FunctionsManager) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.tabs = QTabWidget(FunctionsManager) self.tabs.setObjectName(u"tabs") self.tab = QWidget() self.tab.setObjectName(u"tab") self.gridLayout_2 = QGridLayout(self.tab) self.gridLayout_2.setSpacing(1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(1, 1, 1, 1) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.add_btn = QPushButton(self.tab) self.add_btn.setObjectName(u"add_btn") icon = QIcon() icon.addFile(u":/plus.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.add_btn.setIcon(icon) self.add_btn.setIconSize(QSize(24, 24)) self.horizontalLayout_2.addWidget(self.add_btn) self.erase_btn = QPushButton(self.tab) self.erase_btn.setObjectName(u"erase_btn") icon1 = QIcon() icon1.addFile(u":/erase.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.erase_btn.setIcon(icon1) self.erase_btn.setIconSize(QSize(24, 24)) self.horizontalLayout_2.addWidget(self.erase_btn) self.import_btn = QPushButton(self.tab) self.import_btn.setObjectName(u"import_btn") icon2 = QIcon() icon2.addFile(u":/open.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.import_btn.setIcon(icon2) self.import_btn.setIconSize(QSize(24, 24)) self.horizontalLayout_2.addWidget(self.import_btn) self.export_btn = QPushButton(self.tab) self.export_btn.setObjectName(u"export_btn") icon3 = QIcon() icon3.addFile(u":/save.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.export_btn.setIcon(icon3) self.export_btn.setIconSize(QSize(24, 24)) self.horizontalLayout_2.addWidget(self.export_btn) self.horizontalSpacer_5 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_2.addItem(self.horizontalSpacer_5) self.gridLayout_2.addLayout(self.horizontalLayout_2, 0, 0, 1, 1) self.function_group = QGroupBox(self.tab) self.function_group.setObjectName(u"function_group") self.gridLayout = QGridLayout(self.function_group) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.function_definition = QPlainTextEdit(self.function_group) self.function_definition.setObjectName(u"function_definition") font = QFont() font.setFamilies([u"Consolas"]) self.function_definition.setFont(font) self.function_definition.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.function_definition.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap) self.function_definition.setTabStopDistance(140.000000000000000) self.gridLayout.addWidget(self.function_definition, 0, 0, 1, 2) self.horizontalLayout_3 = QHBoxLayout() self.horizontalLayout_3.setSpacing(1) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.check_syntax_btn = QPushButton(self.function_group) self.check_syntax_btn.setObjectName(u"check_syntax_btn") icon4 = QIcon() icon4.addFile(u":/checkmark.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.check_syntax_btn.setIcon(icon4) self.horizontalLayout_3.addWidget(self.check_syntax_btn) self.store_btn = QPushButton(self.function_group) self.store_btn.setObjectName(u"store_btn") icon5 = QIcon() icon5.addFile(u":/shift_down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.store_btn.setIcon(icon5) self.horizontalLayout_3.addWidget(self.store_btn) self.load_original_function_btn = QPushButton(self.function_group) self.load_original_function_btn.setObjectName(u"load_original_function_btn") icon6 = QIcon() icon6.addFile(u":/shift_up.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.load_original_function_btn.setIcon(icon6) self.horizontalLayout_3.addWidget(self.load_original_function_btn) self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_3.addItem(self.horizontalSpacer_2) self.gridLayout.addLayout(self.horizontalLayout_3, 1, 0, 1, 2) self.gridLayout_2.addWidget(self.function_group, 0, 1, 2, 1) self.functions_list = MinimalListWidget(self.tab) self.functions_list.setObjectName(u"functions_list") self.functions_list.setMinimumSize(QSize(300, 0)) self.gridLayout_2.addWidget(self.functions_list, 1, 0, 1, 1) self.gridLayout_2.setColumnStretch(1, 1) self.tabs.addTab(self.tab, "") self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") self.gridLayout_3 = QGridLayout(self.tab_2) self.gridLayout_3.setSpacing(1) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.horizontalSpacer = QSpacerItem(637, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(self.horizontalSpacer, 1, 2, 1, 1) self.globals_definition = QPlainTextEdit(self.tab_2) self.globals_definition.setObjectName(u"globals_definition") self.globals_definition.setTabStopDistance(140.000000000000000) self.gridLayout_3.addWidget(self.globals_definition, 0, 0, 1, 3) self.check_globals_syntax_btn = QPushButton(self.tab_2) self.check_globals_syntax_btn.setObjectName(u"check_globals_syntax_btn") self.check_globals_syntax_btn.setIcon(icon4) self.gridLayout_3.addWidget(self.check_globals_syntax_btn, 1, 0, 1, 1) self.load_original_globals_btn = QPushButton(self.tab_2) self.load_original_globals_btn.setObjectName(u"load_original_globals_btn") self.load_original_globals_btn.setIcon(icon6) self.gridLayout_3.addWidget(self.load_original_globals_btn, 1, 1, 1, 1) self.tabs.addTab(self.tab_2, "") self.verticalLayout.addWidget(self.tabs) self.retranslateUi(FunctionsManager) self.tabs.setCurrentIndex(0) QMetaObject.connectSlotsByName(FunctionsManager) # setupUi def retranslateUi(self, FunctionsManager): FunctionsManager.setWindowTitle(QCoreApplication.translate("FunctionsManager", u"Form", None)) self.add_btn.setText(QCoreApplication.translate("FunctionsManager", u"Add", None)) #if QT_CONFIG(tooltip) self.erase_btn.setToolTip("") #endif // QT_CONFIG(tooltip) self.erase_btn.setText(QCoreApplication.translate("FunctionsManager", u"Delete all", None)) self.import_btn.setText(QCoreApplication.translate("FunctionsManager", u"Load definitions", None)) self.export_btn.setText(QCoreApplication.translate("FunctionsManager", u"Save definitions", None)) self.function_group.setTitle(QCoreApplication.translate("FunctionsManager", u"Function definition", None)) self.function_definition.setPlaceholderText(QCoreApplication.translate("FunctionsManager", u"function code", None)) self.check_syntax_btn.setText(QCoreApplication.translate("FunctionsManager", u"Check syntax", None)) self.store_btn.setText(QCoreApplication.translate("FunctionsManager", u"Store function changes", None)) self.load_original_function_btn.setText(QCoreApplication.translate("FunctionsManager", u"Load original function", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab), QCoreApplication.translate("FunctionsManager", u"Functions", None)) self.check_globals_syntax_btn.setText(QCoreApplication.translate("FunctionsManager", u"Check syntax", None)) self.load_original_globals_btn.setText(QCoreApplication.translate("FunctionsManager", u"Load original globals", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab_2), QCoreApplication.translate("FunctionsManager", u"Global variables", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/functions_manager.ui000066400000000000000000000246061502633300400226020ustar00rootroot00000000000000 FunctionsManager 0 0 1035 703 Form 1 1 1 1 1 0 Functions 1 1 1 1 1 1 Add :/plus.png:/plus.png 24 24 Delete all :/erase.png:/erase.png 24 24 Load definitions :/open.png:/open.png 24 24 Save definitions :/save.png:/save.png 24 24 Qt::Orientation::Horizontal 40 20 Function definition 1 1 1 1 1 Consolas Qt::ScrollBarPolicy::ScrollBarAsNeeded QPlainTextEdit::LineWrapMode::NoWrap 140.000000000000000 function code 1 Check syntax :/checkmark.png:/checkmark.png Store function changes :/shift_down.png:/shift_down.png Load original function :/shift_up.png:/shift_up.png Qt::Orientation::Horizontal 40 20 300 0 Global variables 1 1 1 1 1 Qt::Orientation::Horizontal 637 20 140.000000000000000 Check syntax :/checkmark.png:/checkmark.png Load original globals :/shift_up.png:/shift_up.png MinimalListWidget QListWidget
asammdf.gui.widgets.list.h
asammdf-8.5.1/src/asammdf/gui/ui/gps.py000066400000000000000000000057451502633300400177070ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'gps.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QDoubleSpinBox, QHBoxLayout, QLabel, QSizePolicy, QSlider, QVBoxLayout, QWidget) from . import resource_rc class Ui_GPSDisplay(object): def setupUi(self, GPSDisplay): if not GPSDisplay.objectName(): GPSDisplay.setObjectName(u"GPSDisplay") GPSDisplay.resize(674, 49) self.map_layout = QVBoxLayout(GPSDisplay) self.map_layout.setSpacing(1) self.map_layout.setObjectName(u"map_layout") self.map_layout.setContentsMargins(1, 1, 1, 1) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.timestamp = QDoubleSpinBox(GPSDisplay) self.timestamp.setObjectName(u"timestamp") self.timestamp.setDecimals(9) self.timestamp.setSingleStep(0.001000000000000) self.horizontalLayout_2.addWidget(self.timestamp) self.min_t = QLabel(GPSDisplay) self.min_t.setObjectName(u"min_t") self.horizontalLayout_2.addWidget(self.min_t) self.timestamp_slider = QSlider(GPSDisplay) self.timestamp_slider.setObjectName(u"timestamp_slider") self.timestamp_slider.setMaximum(99999) self.timestamp_slider.setOrientation(Qt.Orientation.Horizontal) self.timestamp_slider.setInvertedAppearance(False) self.timestamp_slider.setInvertedControls(False) self.timestamp_slider.setTickPosition(QSlider.TickPosition.NoTicks) self.timestamp_slider.setTickInterval(1) self.horizontalLayout_2.addWidget(self.timestamp_slider) self.max_t = QLabel(GPSDisplay) self.max_t.setObjectName(u"max_t") self.horizontalLayout_2.addWidget(self.max_t) self.horizontalLayout_2.setStretch(2, 1) self.map_layout.addLayout(self.horizontalLayout_2) self.retranslateUi(GPSDisplay) QMetaObject.connectSlotsByName(GPSDisplay) # setupUi def retranslateUi(self, GPSDisplay): GPSDisplay.setWindowTitle(QCoreApplication.translate("GPSDisplay", u"Form", None)) self.timestamp.setSuffix(QCoreApplication.translate("GPSDisplay", u"s", None)) self.min_t.setText("") self.max_t.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/gps.ui000066400000000000000000000044001502633300400176570ustar00rootroot00000000000000 GPSDisplay 0 0 674 49 Form 1 1 1 1 1 1 s 9 0.001000000000000 99999 Qt::Orientation::Horizontal false false QSlider::TickPosition::NoTicks 1 asammdf-8.5.1/src/asammdf/gui/ui/gps_dialog.py000066400000000000000000000124261502633300400212200ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'gps_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QDialog, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QSizePolicy, QSpacerItem, QWidget) from . import resource_rc class Ui_GPSDialog(object): def setupUi(self, GPSDialog): if not GPSDialog.objectName(): GPSDialog.setObjectName(u"GPSDialog") GPSDialog.resize(623, 190) icon = QIcon() icon.addFile(u":/globe.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) GPSDialog.setWindowIcon(icon) GPSDialog.setSizeGripEnabled(True) self.gridLayout = QGridLayout(GPSDialog) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.label_3 = QLabel(GPSDialog) self.label_3.setObjectName(u"label_3") self.gridLayout.addWidget(self.label_3, 0, 0, 1, 3) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer) self.cancel_btn = QPushButton(GPSDialog) self.cancel_btn.setObjectName(u"cancel_btn") self.horizontalLayout.addWidget(self.cancel_btn) self.horizontalSpacer_2 = QSpacerItem(20, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer_2) self.apply_btn = QPushButton(GPSDialog) self.apply_btn.setObjectName(u"apply_btn") self.horizontalLayout.addWidget(self.apply_btn) self.horizontalLayout.setStretch(0, 1) self.gridLayout.addLayout(self.horizontalLayout, 5, 0, 1, 3) self.latitude = QLineEdit(GPSDialog) self.latitude.setObjectName(u"latitude") self.gridLayout.addWidget(self.latitude, 2, 1, 1, 1) self.search_latitude_btn = QPushButton(GPSDialog) self.search_latitude_btn.setObjectName(u"search_latitude_btn") icon1 = QIcon() icon1.addFile(u":/search.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.search_latitude_btn.setIcon(icon1) self.gridLayout.addWidget(self.search_latitude_btn, 2, 2, 1, 1) self.label_2 = QLabel(GPSDialog) self.label_2.setObjectName(u"label_2") self.gridLayout.addWidget(self.label_2, 3, 0, 1, 1) self.label = QLabel(GPSDialog) self.label.setObjectName(u"label") self.gridLayout.addWidget(self.label, 2, 0, 1, 1) self.search_longitude_btn = QPushButton(GPSDialog) self.search_longitude_btn.setObjectName(u"search_longitude_btn") self.search_longitude_btn.setIcon(icon1) self.gridLayout.addWidget(self.search_longitude_btn, 3, 2, 1, 1) self.verticalSpacer = QSpacerItem(20, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout.addItem(self.verticalSpacer, 1, 0, 1, 1) self.longitude = QLineEdit(GPSDialog) self.longitude.setObjectName(u"longitude") self.gridLayout.addWidget(self.longitude, 3, 1, 1, 1) self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout.addItem(self.verticalSpacer_2, 4, 0, 1, 1) self.gridLayout.setRowStretch(4, 1) QWidget.setTabOrder(self.latitude, self.longitude) QWidget.setTabOrder(self.longitude, self.search_latitude_btn) QWidget.setTabOrder(self.search_latitude_btn, self.search_longitude_btn) QWidget.setTabOrder(self.search_longitude_btn, self.apply_btn) QWidget.setTabOrder(self.apply_btn, self.cancel_btn) self.retranslateUi(GPSDialog) QMetaObject.connectSlotsByName(GPSDialog) # setupUi def retranslateUi(self, GPSDialog): GPSDialog.setWindowTitle(QCoreApplication.translate("GPSDialog", u"GPS channels selection", None)) self.label_3.setText(QCoreApplication.translate("GPSDialog", u"Search for the latitude and longitude channels:", None)) self.cancel_btn.setText(QCoreApplication.translate("GPSDialog", u"Cancel", None)) self.apply_btn.setText(QCoreApplication.translate("GPSDialog", u"Apply", None)) self.search_latitude_btn.setText("") self.label_2.setText(QCoreApplication.translate("GPSDialog", u"Longitude", None)) self.label.setText(QCoreApplication.translate("GPSDialog", u"Latitude", None)) self.search_longitude_btn.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/gps_dialog.ui000066400000000000000000000107511502633300400212040ustar00rootroot00000000000000 GPSDialog 0 0 623 190 GPS channels selection :/globe.png:/globe.png true 1 1 1 1 1 Search for the latitude and longitude channels: 1 Qt::Orientation::Horizontal 40 20 Cancel Qt::Orientation::Horizontal 20 20 Apply :/search.png:/search.png Longitude Latitude :/search.png:/search.png Qt::Orientation::Vertical 20 20 Qt::Orientation::Vertical 20 40 latitude longitude search_latitude_btn search_longitude_btn apply_btn cancel_btn asammdf-8.5.1/src/asammdf/gui/ui/images/000077500000000000000000000000001502633300400177765ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/ui/images/alphabetical_sorting.png000066400000000000000000000027261502633300400246710ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxME; aY5YB-A$D!h̗ИX& &6!HPCƃEЃbP Ưh(9DDCŲHX,KXdXlb{u $dqP73*({Rx*X7b lQ#տC/W$p]{Qlq٧GvZ^ a)*z_D]TIi[%i J8<rC+o{q<'-E]a:P,Bx- gBF7خv8 ȽM~0,.T-.9R3F ]9Z(M e:۾5I 7@:FX~Oe8q` Ies"d;]v ōݴ+V 0l6Zf yh% 6 ڝSX; %< }BD} yJ9븴As }U n֗WV/ԵH^$< y$pgݣyx38ӯmcQlW,V@:-> |c}i+tf_ҘM.qi1 Ϧ#\[ ju:,]>ͥLl{+u]1ZU.@n(* 99b& J=R5= +XJT#-ѾIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/arrow_next_higher.png000066400000000000000000000013451502633300400242250ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxA@4P9Hk# ˨[u3204C .\4.@;I*yUyߗJz*˗!=XTH `I=1(e<@n.xh stxsgyx ouD}*%pE*@$|(<zˌP2x3,nO;Px7#,NIOB{FH2Zff!IjG%Vk?Z"bSR]kջfFh,~e v`3,}8QAC4ZCܪw#ZGx81;&{?#~OB/MZ0ZaK+'[WwTW[hC`n0N|0Z㛖?O=?6BٜL`U Nc/'YY^fCqE5IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/arrow_next_lower.png000066400000000000000000000013301502633300400241010ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx=nAWE* D`m:j4)P TL BQX!.eDaql|ڳ3Ow3BcW'{ |J?3J?`UKxW B/MRCDRI{o=Nśd`@&"\($K+#7pPIV8-$J(} xa,*}@{4y @6/&0[ea H6{JnZ | 3kL;!?SB04S@<Y!́揎HL6;8އ" :/a0Baq6dSgE#@ O"́ #̺b=p/#-vg p`9~XOxgf<#Jhy9$l,wB2A =BH!ZhdS! ԟp II;rrP9i!/"/&Jπ"lMa[ФvMa_A :^ZK*v#T,"`#TmP1J?:ZKOOIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/arrow_previous_higher.png000066400000000000000000000013151502633300400251200ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxۿkARDZE$Eb& D+.ŀ`i'̟,ơ̇yqs{o`ա/D0|1(m^, l-7!G @OB;KC)JjBip !Ӡk̀[7 E޷+Ncl_M]% QvJ{/TR@OIA #H0B ?b#N S(P3Dž\hCNaWEZԀDVNJ {B9 O]l E{' F: !(:B@cͺh!i0EDD@8Vf" +D HLA tք$ 8#:o}x| SF6uuQ/k@΋`+] C`C1•a !Bb(Bg,0bɃah+%B (Vс+yJ~Pڼ>]M,BiLif?X^Ĩ IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/arrow_previous_lower.png000066400000000000000000000014041502633300400250010ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx?nAo, F$B(ZYQEgtKkAbA hЊ[ ((8]?k{gWgۗMbzXyN}όz\lz^:ƺ7c[s ]K^w>%x=1=?NJ_XiUBkb_Vq1֝_gg { Px}u” lЈGy, [)a?F_gQfLd 4TOb3ეe{BxGq;/^Fz6kx(YxP0]_uKpwVCACu'C*|\ π.3!&k p`7"ƺKʵWP ``|/<.@;`\I"x 1<{` \rT xz*d6r?sײx8X<(xK!𠯀xU@t<) t  H$CT!MjUxc¼mՔ?HjwxeMp8t8w8cq p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ@a7gƫlOZڟJwiiۘzZhi1;8ÆwAN)N;Clp8U` {[ZVw:ͳv>j44ZK F~m|ّ} ?FkW FmYZCj0I 6 i)CY= EhXoS^Mdc\%^;UVUiR2ZmXfh[.ml-qIKۓ`ҒԔGǥm h tEj5o}Igl:"Kx橳8NC5.9W4BtowZ)$ht[Zk%IZL_9z@)_mC@LK T hdLH0O"A[Wn|-PFY^iip8ڀv&/(eALwնlTXX\V@].45o\5`_(k㑫&$NԪ$Xi=_-ۘ-HUAUFq0LP鹥r~E@-oJ%k`I-_}%Ը4)^sS`i׼ 0elDhe'50oY{0RhO{-UP+ϼlG/XhtUklণmn{Z"h8cKEN]WtjnS)rfŬ9\Yg ^:_#gUoMX4XR:f ᷉lؖ "-S-NKnE_mPqaOf Ji  kP(nTU;~*g #,-VhT^*^mF~ Cz̹ayGuk~!]:ڮ[u<Ӑ%]2$+e~eJq56"b|&]ui4GHn&g'2P 9+YLmiC\FmKheZz1=-F6%iE]xF0o2)l&*^)?v׆ ؆BW @EkzQc)M$4aRԖƐ64۞4+_Rr]c傘%)'LmV2YQ X `IT.*~O!ԭxKJlf@UVͶe[ؖXJ\)vWyeb@R` +JQrv~KKgd6(3@:AiEېe.vM 7/pWY6t)RaKW4.NJ"[]_MS(%qȅ5G456iiZ? "m@$b_!DzZe@Bi)m$o-,CQ?߆($<ԡQ*=3B@[EmJ2Oht`%\v5yؖ@6wn5_iQIg_VLQqu)sȆAcFH.>aFw&ZhPZ-0(k j]I6̔km P_o,vEZ^s ɺ{6z{$j) vzjhIb{KQJ-"(Q6Vlic]\epϲ4h F%,0MT٦|*\:6RFئ0$FmXs;P(XT 0= ,|սWo2}ħM~{殒-(Wn53[óVtDiؖo@>-|a5WTa̽y+ӈ|!A*C6cXXZV ^s¿Td dLyX8mX۬5[Emf'-e+jʔ}HtI(ܿEƯ%Y0 ڎ ?{nBӯ"yъKvkJ[ [Ysը{=- &$-%V%Kd4"b[ WVJX& |d-Rɿ01WJU5x]#_Z@@JPZ#7ܓI(n[t% ?n,V!e} & s{70_k(?ʐl-2 <˚`>-lQZb)fmjRxC6OmSCe1N-֬#?̝/0r6Qz&Am&0C;I(zIܕ7V"b`Ve+e@ikKU2Wmڒ.=-iue,Znȏ-rwx|~><_d` J>1 TR֬l|o^huMUGqK &^A٪j|98`,:^, 5J KFxrϋ4¬ SҶi=2z/Ӳtu2H*O~ mue`֦ N`I,V( 4*DzyhNya&A3kvY;M:Ų9bw;  <ӋׄI0;m(JK 8c$Dʴ0 I %i2_ D?-M0y^{Bau<|TKl$ c R ߟ$\[ܹ!7l-IP^j?ۍEA(2&{ҲVu[ M)q~v9Hdknz*  Ϟ>+@5=ax o6\cŦ=Ds`6d:]AS M'La2#l[ZKx^Y2";7δsy_͇oڬǶ_7<_̀uKzL-9?p|tp a8hY Bx} {74`:ߨUӵ ;::ei<1= ( @ICQ4O /¢lDWmH[%چ͒ϼ2K=D("œ8[UCzBB"l~sYD iDLr6\.h.lI?[s.žz_G HeKف*g *~`cKFU0aZW|e!SQ BlI9;DW%,rlDS 텐| iɖ8hgiic}KLkI (1?jP,=hW hJMJbʲ@Se¦G,ת,ZLK rN &gVy ߴwv Ⱦς2ڔ&roq08`Kb\FTW2+h*2#0Nv ,PXڜJ, P6˜򠭷{O Q\ה}:acUteTQЦ -QIیڀ=-*mNKf^kW"LᤢZ2*՞no%Ж* 7܇Ypt)5ð>;sb3)6!;EشNv 2N_&Mr~!8vbؘ0fh$@UEa , ;9ĮĨdP.Vo0иU=a2(LsS5d{Uf0Zĵ(3M´mBtޯ*ZƿH5e c)-)Q_bnbwc{ϩp8ˠ"Pmx@.*G.2J h pս*xK39·\ ܚN.$g7%WZ43)u4gڧ+ 79fy"8YDy^Tn3`׆bf}^Q\,مBp8[[fs(ﴱA_B͌XPm-_&W{ fzͮ9['UTWw8ۆގYlJxg5;Uð)M5~<̓fMi3LYp٢WɍQJ<&'Wδִ(KQymέXɈRV`զ{( ִ@a6kAs絥q8ۆ*ʉInU[&llCUFԅ汕EXɨ2R+<A 51ζ%Z6 0 8ƴŲLYaMLM*%=JX K*6TJP W I]M\cTm `fR^qOZWLVlئ=n1(s;ӍEKTL?X6uښ*JZtJwVgvq+V)rXh2Ko4l Tac]^+&%׌Z(/w8Mv2Vc m9_kial`"s*S 2K]b ʛ2ly Fn4Ch*UPVrލA[V9YkU:֪=n /^a(^)lflMAZŕ6 @/CifSW{S;Uu5w_.qwuh<1`x򞱌ÑejB2d  YUdYڬp8gv尵Ef'D9 [^S FXp8F#57haSh9p8;IFi)^h ZZK/҇"; S44p8@)p NQ5u'%DsGNPV$"aRvJhi{6T Ro;mt^LM5,qS4Oە4puKMa 0tjMZcFa1"`<`@A(… j)YNTwf` Dݤ-̼ҪU_(t#۽Pq`ASʼ\k}'2f5!c1" Xhd*UبWDQ_p0`# o֍3F#fSǏ!e0xtdsAe500L cA6 Rp8t2'Ov|iOZG$py9Dx 0XbV"f84m2:)HMs {!NNNtYL>-N4mad:ê.( WXr΍)R]|˜Xlxү4e$+gҡÌa~{{{+|v:.sn~,D}|l:: 0N9iQ΍&zʻ>B!rZ5֒/<- IDAT|:b HӰwyHY쩶iEBP#D3LK 2 1f0&-A@`)MB㴴QqOhѶQblKҲ]{PnKZ!H6mJp p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ8p8)p Np8cq p8;SAp8p8v8ñ8p8)p #|t#>^'0,렟y9 _ `2Vq[isg𓗠#n#u|w}9;qn^ alpCwNzx[E+ѣBܸq [g_Nś!3O.pb.gbJEz^^˙cg1i_?,SQo~H,㾇}u{xx63\xTH][;]gq먃9'C(x$>ꡏFQgmew@Dqܱ*mAHsnVx[F.J8r|~|w8~}<;`yd8]/K:_ZΧ |p =S\{Iw8>vN{}lz :{goG&>wPIMc܍>~}6_ޛg/nex1 x`^]]/nr9r[7k|_~ -t=5|K}ikyI249S_+wK5AU\u!^=?y9pF/q1]X6so~} |s @mywm) !>8_L wV])C*MaN&#{ۇ>~3W+U7S7/6~o ppҏL_5l?P/i} eq_[ x{oΧ4#W Xᄓx(oeqҮs^&V΀y=EGE$uDin n6`8ex wko)~CWBL9e GW=s'op'-/7PYiΛ=ݣ 9c֙@4W nvʓQ'_6xkO_ſܜ kt|J4əb9r|0̇,8ۮ0@Dǘf8??E1_aޅA {7a.d"yf?qU݊ޗ- U x>kC[P(R"5x2LBHIWNDI ab<1fT2?fӘC4A^{8tƀ 0!!P;.78^cfYҸʌ{'=,k~bp 0LpyyY87YW8R6ui!c_>#  P`ml d:Ee: ͊p=\^^.!VGǜGl5B(C@{lnjG҆;[=^//^P(~iơ'8_a|y=ϟc2>7^!EGa:\:s,Vl>~L[U_B0|^[nsg5dI'w1L\k׮m:Z qqqW^Q+z&޼|17~ ~=z ܺuo)ʔ'O@k׮ZEE ꖍIr=7:*uyW:̓.^N&5VgaE)~Gyq_=ht-ۮrcǯu;+Ә\>{i})Ec*?olsDBTOǀ_}qK8yt$572_Dk;2_WiySW7 T_^?[$Ȳ-elYq|ul}Z,񭂫+yknp՘9ˋrp稭,}w4`;iy1K*q-%-O5aӑSss(#Z3+ih2]_G~!`#E\o|aV4tݿ"Ԟr{|jaǨz>{)1W;͖l]{t4wV(12GL~_wYUv׏Ϝ`Fr8C#v<]nvk_ݴ ôIsQsZ•{_IV4JЭR,IaVvŠZp} z ]n_wJ.Qt<޼E=.G?\]g-΍A+Uʝv_+R虻G]OZo p3sXolW.}ie8+R0-6%Le(UQٓnh**|E)Ea9"rw|mp hloz2G-ќsQ*Q؞Qv}W~KK[@z0܋oZ;c9ںcnלL&\&uUȲ{M?֕n5+zU8qʡMUכN(Df+-6rwpGObfoTj)}a/OVQ%Sڂ]E})nz)¦E{^ꧮS× d,eu$w ƀ3R=;;OpfG?q7|xj"Fk.t{?pTgZóK L"; .N W Ac& Gvn 2pyfӵ) 2M=P9SqxwN{z,_U zOH~p{oJYV9 +.r՜;4S(kMWݪS,jb,)%u5~,'xEQd=-P̚:{m㻏S~77FEi^;dM[* |4Kj2VeSJ =/5fP)Nغ_9@}LבorFʇCo})h B5e]ejk?E04p Q"Z"`:6ڮJofOO$4{[=ݫ٪8Rlb`+&&>m(M6|RJyjcUŔ4UM5|W;*[c' *RVQ)NM;עk _pGOٴQmR&-.TUje1hiI@":nQELP"Uoj*63 O^Y2 ؔ˺pc'{`>nQ$ E@H CQEaY BA+W^X,-.g10p=mlGcHtMJCqW)T-,y4w_`tx\%~%t`CQ8cT*,954زJ>򘏽r̢D[@3RLK˟;qdz4Z󛆄 S_ur{Ҋ%.<JĤP-z/f=OKGQP6MRH&!?I+Xw-֦¯2By'*xoE _;g)e^ygLFXJYMB[WuyAzXLZ݁|krݳ[P(St.R46,EqX3>;m0.!xp8x4“'O1F&pKx |'PCO>gR@9L{.C WK˖ZrF6[O]YTtj5ROPd/{j!1? If3b F`}/2_ E1Fqapp/+gPHUrwx> d2-@xfO:=pa*>yǷ y<\T{.cQXdf,1{T<.!*cQg=%&b*y_E?iSA⦛,sx\0%Y/Ă/ fGQ):7O6nUT 8R ]rxGcTSGX4YGDY.t8'8=D;W>prrOP DgqE{ܸ;r_7E=[7o+]ʧO1 WL z].n<ܼyliyBLSz=\~={q>͛ݹ,[澏L`6a<\v T|˗'Jas|eoKf3\zK {L\Nѓ.3ۚ.0č7vjjTݤl9nܸ@du*z ͔Xa<~\g0>  8=9MB}52C?--<5Nz e$DuTd,CwXj^'x\QH(A] O~x|TM|뱜0ѱɳHV1ƉuE Ͼx%kƅPK5?/==D$ʕqByv" E24NT~BK!K޿Q$mJ4$ Und8ݦa?[ǫSL|)/yuª䉣FMjdҪm(V"%ҕr>(N/Mo.*m]2EX}vsU%_ߞGC<̎o늀N"~ȬR$1(]+2/g޳ >q, B<9hC?KΫ*9YV YWJiI):J :P MB;֯:/3v*}u[9П+<$dJWV)uS }´1`3r*ջzJ%e+ű F!P%HHߩFb<=sL`$rxYaǢ4 qcғVy75,'{%wϧcvy0?1Af; IDAT,p稃@T?Ays6tM|{a@.5Ϣ? _w'.t|* _.e>ܷrpМ]:wXPc6~OwC&o4ty$&7333 kPDh6S75c=LCJ<$0; ~4$0)yIA6]gvt<h^PS$P--ܛ.@ڑڌiATxū}MJ*،E([c~lOҏ*9SSΥ(<:7D}#Zq·)Jyhip1ߊ:c&r#+ G/&ELUciHuq>YXUJ|ݖ< ;LXȘ㫘P|] C?'/uy@fjזV銇c=4 ޢ&PR4] PM:v8\qqXji.1dDZT7A@clU+}\x1?Pp&yo9Gˁ$G[g t rKj&GV) k|&苠Q=U;X`5(FQ THƿvXn ~H &ڔKt'|0a7 , z,ø |~,1 bU\/ShӷYC6߫ema4u_y?,W:?|>$Ϣ,*Li^G^Hr"ZdEүL/ @(ELb n'ci%g}aPdzb)ֵǧq> ~oUt9r=( ּ<6EX)+|C'/g.0/JS:rVHS9.*כ,IڇrR>@(R.~Ǐ_Nq<)DAI9<37i5b ҢNrA2\07Ej |^rfZ{w<ⵣ> d#24'h> N=˱b3@1 /TA_g. ΀>zdWt=.IS[uV/^?c B1q.T J.TY4='ӹx鍲qK6jc0G_?7YSDncӹI pxeoVw*Bvԙ=NX; PRr_e"S*^^#ŏjJپ"' ~} cj|&8F;ow93requp> qfX4n_SU dO^r O{i2A)5]T֔4:<4H$EJ^2T~,ϓ;sD#b3c)3")KIRk1 @4K bL dMV-#k/Մ^e$&ϝR,r0@D~Kk(n u&dD"ri{U߲rLpuI9Vg4DzD*h޴49#!ϞOS\^BM _97Zg fT4usCUXnSKc *GZRx U~b>W{9WHC.MV wV1.a I؆-X ò2!NnL%u Ձ$m̍.! "Sv2޽Of3Bo%Yɮc7*k8 $َ,`EH6ΔPzTƠD7ڑîmJ9وy Ҍ^Fx6i !GR'#[ [=d`?U,l ~lYf rwFֵq@x ΢/B_/ӤXzzdirEc)echUB}_FFs~ DW2$n S]|2-PdCTFZ48&nܐ>~:/2>% hT։BSC+rHU#R! ƀFsXVX)–u$L<:D:Ba'Li9@7s[EV_.m($g.3$P^2ܓ{C/'!|^\д6 \T=^/2ۦwʾ8kP?Wnôǀ{WG-eSf{ljmJcRI(i#vh_;HȊZf) _~0ӡ[u1 41QӲ@wj:7|W`F,osJw3: =yBau޽Lʉ8H\YWIؽ1|ɸT-,lZXi~M&fƂpM2|t2eh)'})_zS$%mR7f\ ('*NܖTԆLePm[Zb 8TmHy6 k~lW!?}Q1% `qØjl/0V*qeQIŪ?x:MdmIO"/nǁ=9Gϗ 1B$4Yfk0%3R\Sð6Hmd?y6"),~wc+giлhrfQnTaܧOCkß>)F[&DT+xNm f:wb,)˔SLavd(iF} _~>g;$ˡA @:3] 2: ljVleLph*OA&na"'~VټyPi{Rsq t\V\+U A /pՆ@Go تY5~EQm*x\wcSEqJWY `/6'¯֧L{aZU =!/zI`RNYaΣ|*O9eTcEasb&|%eˣ9 dR #Lqd9)^Lܪ܂tIt-yp9DÓQ!0iЪ_9<$K- q7O:䕾$-?Q@ss PWuŶ20 ;9,)ʎY~1fٱW+/j{Q< ~/S#hg_aN"4FP'@G63=xvzUb1h )>f!Q 1'9.JI4%G"tIڞ[>Χ"1q[ T`!/c@m>Ě3k6l[V@$ ʄLW#,Q)򥗛/flb*u^JQt-+gA{6˄.իUރɏ>yPylt=_y`v4F \ 3h.&XAh`]"6߲0Jvz.۶0|}|R N~$L*cr%iMXo*3>Uir]H~j:rG-EBg4Ej"cƟNʫY]W[ p>làHf@u>GQ}oƸ%~I &jpr/?奪{ݤ~遳I}?g SBs'_hdrL޶`Ʊ*W?|6G^!-tr_PF]P58]Ҷw1 D~LDOX=HӋ K%*eή6+B٘(L DHc2&fQ Rf[x9 =g'!F{y3g)2dJ!:rLCP eo9VI;67lnPMB(}>PK#.ou,)I_אijڌ&m, \Cd&!Fmiy:3rb)rB^3LjqQ'4=j(!jYFaы)|0ʅAبy0+'y$6q]30S_Ҧ6i Sfh/ '(Bf|E\]0&e' !(MګmJfSJyrȯ/ꥸ͐KgM}x* ϗ5 ~=^L2? ʋnJO(vU87s6>T!1>2XP(WFъ%\w;0 L-h)^V',-TGY#gR,T_Jf&J[Fa D٫:t8C %Sy)t9fJ!_S13S;ʸY ehde Ia_S`x_FD۹tJ'IO\Cܿ_h+D9 wAǨ,pVoLH 2'&IH n Q;8ʍbEFiUM{Q+c 3_l)LrU#bu,ձM#^F3RoJm_˻,K0S\mG*;v٘M܎$XMJ܍ѫ)0#Q`ou}%o/ J *\ H8=~j85铐p}~ @;m3Q+r@m) P0iWe05NZd7>q/ IVɤ4 dS5xƢ1beΫtS%2Ey F2#-45Rj>5+V,ȭC%oXanSnI^ #sٯBjZrE6EO֕'3+)nUˮ(,⢶Ѻr^S9NOf^W*RQW@d'p^P$!RB|]dA*sE^'3<~$H{r}ZhZOY_ _ƀ\a4K3Xt,\, n:'!F6oyqZٚdŐ4j!py! `77* i-UJ|spH$J|spK-3,R0&R VRj=s}rHEN_ÜܭeHgW>h@_^IdgH>MqZiH@d*L,e@]_(C+쳬T(+iY@A2BfmB0_K|(BOfϺT&)3Į3xMR&:b8  Ba&)8"kt6NLCF?•?lTm`:cO5sDqf3"D M<`2 1m t: `2" ,syToa"7)fem69l:l@n fA)M!a2EXNZ:G eU9r5Ntl7%t Ya(YG=e2P-QOCQ @ YW56{)Q[wm‘5g 3 @}!l4]@'PN2fzFRCSH5+N@p˳3 lz a~88%ɓZe.H2+ N&/T[W_Lw珆 !pq~ 0޽`A"hAWR9zx`{ ;|VQ< qyB!\98Bܻw^?pG@H,"4Mg u8ݻXhI 19F1F1>}2j[1{|݁h4a=vEކ>A1=͓Jfdc{q !0 !lCKz ǂ\!sD\2QW`vQM`{D JakE׉}0  qR:8<*nwjfƓ)~Yn!}c p|Y4pt|ÁƱ88<ʇ4Ki} # F ߿l:>Zh>:Sppp~Y :zٵf)]ai"!9f#Dg8<:BcŻiSM."OyLiIM23!CA G{@6L◽Ms8tJ**ɞ L12,y sF 0gFb^EI*U%)fR<` LMSf4ߨVϧ,AS$V|gmW<?5_ZIhBjR \?_|۲ u wlSh`q=/Jn#bGt"1  l媫4(^c!d$S̔-N94xO3ԉ6PyUZWd%d9h&hDZq!C<4Oq2|2}_'ݛE)X5֒iN57({O] `jF[45Mň;%$`fMORLAw`lv|vAG@">Bhlq IDATRK82K5"n60kj6erɶXmc1n5Lϕ2gL( ޯȮmp' u[iy{Lbpv# 7]GIJC$3Vl|"엀6T=PVӯr\u5k+1#"*N,*SO&ڑ,7)jU0=z CKL kOS#21sF&fmZja7CzWl|iޣ`0{e7ApP w BCW)sJگ~,4>.XO*& :MLz#!d2c8^#Ig~? eJ?5D@av5}~=O<ԥa_=Og.|g@$f0DF< i陃QEW;Xlqqi"zg ~XP=aͳ25=-}?/z(GVExQ$'Jѣ16d3;R&T$ܻ,yM櫶Ŧ($oRj%޵^j0Y TQv7 v6&C%hS Tdr Td+飖(9۾U!/T¢>ڳ4] GN=[Zĭ,*GjNpԉHfYEzb~W VJbKMYdw7:hNΕ2ri:3-f" Kl*ZWf=k'Jlv<*!Wys`)Ou<Η<3IBftDi}$H}&$Qbe4u1Vuh)gN|`Jn,! $Sq˴ 뗙tԛ繳6*Uk,xXW5dAHc#$nKeV#V:ϱXHc%Wү_=Jv~ Փt'ruEiڐ2QuhOq05F$}X~5gtH`@lWjgK iIDfgtx{bL3x-|Om=BaEh#a/s–BS>+fEҴE#e ׆{i,ӏ+iQ1DɛOUg\񽉕C`{Mjw5ߡ>G6yݫ<LOO(Rek*G*F՜bfa -_4MVzI%v}$~lBPqD&m#D]fWgNn@zY')}.ϯx{ Iaj&e!2,J 4]2Ct RcT=.7]v83 b K:"PH2c14HM$T:Wh;Ц.WX)%ՒEѪB䈅"eXYOQolufv^ҹ̪0_ N42b 7 XN5VJ1~ph%Z"mk@^gՓҷjEU'ݫkm,:^%i.-^Y|~R]_ڽB}ZXd71" }yqü2>$gQs+ibLYNF: BF32C 涘ۂ$?=klՍU)Pl4 8Wj= 3N }N"!aU5& 81Wb KL 1J0o[_/^I{GzmЩ]o&62߼x}jq5.vv&reP]־HיiI}!LjlI;lGyj;V8,mAK,2b6Dz85Fhoeu !O|C8(L[(@+RL1=XD^R-ZV:dO092,Vpln_a?Hd#&1k[%i%w:L}Vј4go1{;^)Ep?a?-^8h &딅EznK%,lMfo2x[&ކ?[§xL9'u>Ȇmbh!sF nb2K3 ^1&!E89FS$RqQHʌ*6i0jG^fRh{O_;װ礛K3w/Su]Vϟ\.g z2NFԻ\7V]XniGY_~:]$+Oq,I47Kמ@V[M܃%J} On $<LWؓsEIw(Y z70] eb +԰$hAöӽ 4ۂdl)UEu 5 hsq,'zo *hlˇ80,'}dMCa*nоeAQO;i;:XqGIno?ݗ,ȝ]WOެ==sN塚HnL9 @J-Vp-JTkm? !Bf8i L'2jk|N 6=N,T,~9*2S]/ȌŦ:*="8^>ϝ}f-kڡX] ;w3|p|,VniPyw&rhr0_]@rV܏"ʙγ{n<{.=s?̟.5zbfM 5jɊv ^͂e f h]D+ 7хhu/i>7,Ӏ ݪ66{TMWdU$ç%@ZR8hI,zy oeaj%URuIL3PZ2/>'~+(h̕?]!JEcTANOO4c=-5_Gx~#Ԃ&w='®:-qG|jѱ8,lꎠRy[%s 8@PnЇɘd_]ZzyQ|n` . Rjt:{ 'eur0,@ J%FQ6rBs%^]BБr $l|nYDuY^0W>ɱS~!~7I_>.B" DqCytY~`_9^?;3C?O^%@X|f*MҦY4~r$o (H\ԋ8L11,ޟ^h@l"Iu`mO+(Ei6 ֡IXn|2"3SG5>"t2WﱸDf!(ѪÊ}6LFK`ԴrLcWqв/H+w{/𥥿ɳgږL&nMlLhEE (,o>W ѻ~KUc($3&MKo`15@0&dg+Y4@6dPCdYks+W@X#q,1TEV1LQ}2 |N^ީE>gXcX~Xi=g!=hoXXBcIy9ٌC?.c p(nE֏DâXp8`L)L$!%ĤÕag._W91o֥U)Vpl|/)9LMq?x- Oh&P7a+ C[qiR9*L0!`Ra9|mȩύu;08Rwp 1YmFI ؂-fP1 vcФjp˥]Q܏qw{7$#3L%4 J_P7# Cʚ ~?y/rWT&?/-x8͆fe$Sdmy_(SmYR[üoE8I*NQEHt䴌Lj7 {# & Ŧr1֫Ⱦ] ~ 3x|u7cOqjFFYɹN6E>mѸ-^T=v!2?Qͯ9fu=)Z _ܛcE5nQ}xjgFݱ,!uxQW^ %&a &\?{-,%i$j\(-Ɲ/.$?HS+ϽMMkBZ;L2'.=TmOkV˧OzGx~5inWk]BM3Xz˛G)!:hZZ8 ^~Vg?'6_z[+s?̗}Qz8:d,7%Τn<ØL끤_*)fk`;*@5ey(t^CޗuHJ187~U3>Z ŠyAA]k.}^A~bW8^><g:G~ ;5J4%A;hJ3/c؞$d E}EﯦhR$b@0"3ڱ&ڵzOIzı `0OjMn1q|Sk)[q`pGxz'yz"5a|aF_.iMj@#PId2!YI^pH6]wwNK>iȫ+o,_^+@f+RepM ucW',;C_idLe{ # ۙ:9I/HU7bvڐpnֻW8'\3f:i1s؏qOjyU-ɻ =AljxPK2|6"ck)|˗p'WjSkCqki>sZybur,C+ZK3SRBС'DY,_ *1O51b"+PMXM n|fYi/O`f97R=?Fv4 ߮b1&ݘ㸉EG돸މ@"I_eC:60m\ɿ;KoP#ۗX |ug&b X;̖-^`|gLӫ*:B\2+l( n`?15J uBrOꠍI57ggbf;Ȥlp:87BQk=ڭ.Sl AJ?TAv !cW3 CY67\NL=0Y_ 8f8X}΀D4vKqeaED׊?l*iƶ7k'5?oՑOyj5g*NA^`6m'L@ZR5 #Wu_mؖmdè}y$Y94,|HB, mcn|YLT!0U߃@)E4vxuH k%%!vݿV}t:ضEY]yE2{Mi6+;Oql뛬l?Mk$yj#GRG_ IDATwsG} >ȝtc ^腻MeϦQcӘpX{}FZ5%Kt}$'4.~"@vq]NKhK_%ht'Ml~&E*4ͱ|PDJ.ﳳeYoWtoc[Pꕩ:/ny¬>+XngYyyJowHBߓ7{aoXbm[puK{Ƀ͂_ٶ2NMXv?`m &+̔,z={^.h&ZoB:2l^m3J<]?_3c<{^g\?YSo+\ڤ뫓GYSv^J/i]:%RY\hۗe)ixN^eY5l+"=EcOӄx"N4A/DHt]m*dI/j]EXagRS~%䉜)ww*GiS >SN-B @dvCJϋ;lLd%Kvl {%l71~e5ڦﱴmۉ?-Ip\}dBMVvHY4`vKQ Z= lY\ñr KXxG\\.r4%hrw5;ppc`u|2s,Zvp9 *`1ӟԪe &VY^>\HG1|Wi|Ol&`tA8;_1t鯳^:a̷Tsc;^B bsk-VVVVce4,+‰N˥\[JJJbY-GBUQ=Wdz WWoȀCjU:14HJ YDK,Y>T. C\8a-IyTeHvNٚhVm2T.a;NDWDxK;$tCjjL2JYdxo(P dOa6JrywQ^~+KkMusw^~_K;'kU;A+!Fћ.W*XEVT*3 $^J//=Zkn j*V<`FZΣjU" wʐ|rVHV,煼.uҍ vВT4BWDoW'q+(>nZ8YӊK݈ AcmqYn̡֫؁V Suf?չ@ؙH)Hrea}EWi1<}&]H=\1u ;G~O"j&MLdw!#cLG>?;x»S B. 1$xx`>p'op'oEscy..~>B/"ƕLe4M>Ħ_/J IPB;'$[#!29 sD.9U{$LK,5V?kyzzHk>}Y!], *!Mr Vr(aЭA\g!7tZl:vc\; wL I91ijaC-p=ǩ9r}cYيaxd)!VG +r"( 3ȿ8rHB̷TvCC;E̬ȄɲHzзն4f% [ ?ƿg+vZ-‘yeǹp4k\lv!6dž͖?>!G2)r$p *Ddox㔼!Li^*&FV-]KXqϳ➣t)qD-f`BQ+ py6gnEx7LN4DiH+hB6}۟?dwL>k?*:{/W܃l܎hj(EՁ`ruVu?%ЗtԆXDQW-=o גK؆s|prU>~/ !%ˍYnȽ:q?wܛh'&oJvƾA) e$˴b&bQ)LP|>R,`:#6۸6 W}"Zj4FrZ~-8 L"Aђequ#Qk8m /#n ݏ;c7v[ޓ ޽-1ƙ }lVVvgE"ce ^SC8))kV; S%h jh87%PG#}̝xV_*sցD^w8>Ws虼/bo1b WsED덵"յ".àoo? /bxk<ă s,0%s󬬮I ٮQ=EzF$ _ TdW}GăFkR Fk]S:D[GӮU9F|3GdLU&U5/>~Ұ v cOV:z4VR9$@6>f 0٧Fl,)K%/zóS-=C(KT"&@ZD\& `FF k2b% Psz/*`lx"aՎtm>7o?ɉs|[ C/1۽hfIk*ǹ:5NmS#@ūD^Q8@K(tQ, \fctIJJnxz]vcCaP)\x^^*bE6C*`ʱ^ ٙ.q%}iVӷgKv @x!vȈJ w)odu`0Y kbkSaP3KPdbs{yVߦ[Y8W7*YŪU8QE{c í{}=_~,_\{/˳=k4^H9ƟcۜL9 xU ϕʭ\.[TuǼ 15@ Uh4D 0:kCZ1Զ:9I Xظ~j=_YlM# e凖PRm!o?S+IuF%V&"$Nh$GChQ_Va[<_rfc1|GiQE繠5W؜l)oIē|+ =eY ǦVg}gmo]~8~Tw7pX_ג>в8_8Wis׹Ӊ$׹k,+.E&TĄ"8PTRv:o2յ5,$Ƕ%?FjVgz RCeVHS&,/a%)КXf|IϗtųH0/JK0a)8ѷiVxg&jɵU;o3=|.Ss7x fj}Z_'Y+\z˷㋩a SMNP7ō ?pKR̖,cО@Uh'!I*Lv],W< FcԆU>=EwY)a1r Kf춾6lekbH-E($G0B 2*pU£{m25W6MAjФMG9`ɽXv1zJ H6z)e(E kM wo%*ntHs_)qEy>ެ=[¾05@œD16u]qy}Ft}I#<ɤ p>!el ["EPWdw&Qv؊AΤH^xlfhĞ>TڥDvy^(}kP"XTNrޱ\Oq8b1+ZMn>aX[Jؖ(aq;CmMߡ5~E]mQ'J͝<Hlީ뵇y~V= LX"0ƎRjO=Mϋ ~$m7^rGfQݢ!#+D[ؚl#DDU*@nװQ|ަ9Ljdra)Hg={ci~(ӃEtٖZ{EOrn[MU L+QZ5KJzmW?wz3ט]_M"^|n-!~_8Sjz] /]3(rhx0vx TbjBMEސ!=4\8?2#u&sZB@ o(d)c2ȯCOӏ GaZz|5r"FcxԶQhl CuL(x D pψKv;v?! JXQRNoD)v*gd3[L*6ϱ;a<k [<˙3u^?ƅ@}1Tu [՛تfr՛تN{ag$LɢdmC^Qߏ 뚋.`%A^A\Vfa:($sP-UǹAKbL‡^ʱ}o.jF- >X~qƝ e;TOS=;#TIh?ܿJmVܷY龅p\HΓɎ3NޥF7T7׿\2sN7 /EPO{B\L4vn)H[Ѽ0ZBϕl :?:BFJS_D1a:hsi#a ٘IMD(0͠ҧfzcXL0b.3TGR5E`ngg71 ,\QrV.oByͺFCMNDu^g=w S  gk쇹\:ϟGo1JfHzґ@e{E XaLci6h0IA-H݆-C5J_oĉSҩ;Ț̓g"OFV8'd &Ls Sf\kylvB ]at,rnjtYVol큤,G9}SW8{~ǀϭZX-GyhtbzOis`QZ)?-|nA%] U+|1PGkܭ5C" ;}P$: h|jO,qۢiaЧudfzEϓپ7BcBj'2^"t[.a1Tcs>Ţz$e`L(N^ީދ\$N^ =3+*VWg|[_dopˇ _]>vLCO^vdW Cm!P<7Q_.KlأUt^PL )Cw}TX(`[0DHt1M:I(I$S^^ L5QM7>OX3` ~5 2cd Zn(MrI!^j"2T*+N񕥿W2%˝opoqk}%ʞʶll!x򥥟] FPMJYpӋRP,e=+u%D`p]=;Ocd5d E'yW ]! ~=IX344ݬ7r4G)kAAl}5},~~ӫ/WE-1 l"x2%նGTdO+F VqS:e?kC*E٩r2Vg?d5k7j|J/\<~| 8<)dGo -ʓ:Xk X9ROl0x96}h>~@/xOx5w}G(vOLY}Fw{-w9p7wm((c SJia.VB>wrĽC;q;{?'|ߜleg(ֶ YoR.m:J,M&CwXe l{rfSsB%?3L$L%l+)\hia&_\m;.a{5Xz~d"4K%;iN+4Q^뗶 -5ĜjPSLz7@~obS+ ĵי=tKljے0/xwX{ؼu.VC6NR- (ǒq!E2ij_X|arS% u?s`cK{y> LW%t sq62 -|#5/sעk R1LM8NsƶmWB j=%e:TtnMAjBDښq-K"zm.vQ$rcAӕ4 ̌e-]^F,|EbP?Q`HSnmVEcsk =o .Cb|Kڞ -K>T+|] ^ZVSxM0פhX[_\*y>g^۲dU3yKdtT;vYEH\E 4\I~9p}+˶<sIA`=qFwo[MCrv뮍C|5nt=?mŃ "OQs[\Og5SB@=:\2 : *S^$Tz=Ѫ܀H2zZ!"3\uĞOs+rK*ToXɤ<W^jr CkpmNe8r{zGB.~U` 3E+ +yX.3&.yJVÇ~dtAjYNjג{J>%5<ŋQ\q n<߹' z,qq]'R!*ۈ')E [v,wFp' [a)b- TcUGE#'<0A #izzP&T+Yr,˽Y_;gM⦂ԂBZPூv.DY:mù=N.?BTEkc<iE,'%_"tmCD'ia_"jdNSMDZ=鉡jE%.+^]󑢈]q/%~zb8:8eL["URaE#W%BZڹǙ hC5~ \Y65E+\ Ka_J g@$AɣdRgy aQa"m{>MNIٹO\TʒC/C/CTzH = KC$./ŲRH܂NAF[}ϩ冦ciK! slk,/iw'Me3{C%o~0浙p~֘ C$ϔlz;s?e5-l3| h:^-Ug#IÜjVI/H73TWʾT+*"m d`gUm%=/ vpPw)e4%_ @ʀ T¶]c̖l<깉IЭ;e( !_v%RmJCTt9nj=Mgu׆>Ca{k<7@۞祙Orts.oە|jpE]Q)[J@=@L,r{gfxuf;xINUW}};l3ʪԼKb1!ļ !(j@ 0޹{{g ܮ:uZ<9)[dxۥ!+1eut!i#;HN{_Ak.RONi%Xs})7#1f^jѾ@DCF1d#l^ `ef? Kc|93a 9PѽGIL,4wxˇ_ƼRh_7l/0oey``7,9??JIFv1/ϳ>NΧ&|g]tmƮwzZ{&ꪪU"^~ 2mI\?kAқ۵w9)RL?.bƸyw[plr?}\vyu.1o; 4S:zw$ ^h2`EɍnjV"O$A9 G>V˰Ͽ6/MBcZF2YF]Ud3eЋ}ԙ.bAc󅭬P3kY{`#'lۭ?bUI,>HHmB3?7ux8?O Ӽ1OV8[X~^|x&Fb\Ě☳6 `FP2}00V]q.+6/m,<+~]GvM`||]c2?^:+'f|8b?E~5~?>Bے^3hQ#M+2ɴ,Ew mG[fLy*@U'olplFd ^R(BsLn2$h= R-ˇ8!NHUx=)xIFd7Qt^FiH2̆,U++3~.jxkxAy&MVRvw=>Nai^FA3) 9=R1 XcMv;:iWNZ0bnmŪkcT#敌o c[BRjΤX8w Ya чDg*cbP7CkY_ez(Bg(jR2LfA}v= ;gɶ`tZUXp,Z>u4 %E2;߹l1߃S0=T 5Ӳ>}rÑWByau4wh:­IDhar/Fq,x]˓UK"f`M)h[ƪky6XrXH E9Ee򜜍ڔ/~)r_ױ2|^#˓[mW`i1'k!*H_5VHbQ f<;d AJ^0Dg8E@-m㛱8*l,͞3s h݊ߣx P]C<[~qtdޱJDI|@*zg}piXz"&Å|ha߀:>wC"~k G}h/;YuM޹>Lyb^#3eop{_ 8Vı!pA/^ \f@OI1Ts%jK(n{M[ x`ǗŁX/;Q|mWx5˂!2(ž:,OXR>ӞLr}1QORl!<8S*QD tHG*E-PE WP㒱xKH2T`Od(>_eՀv/LR,<+ 1Řep̑ FSl@9pOj׽ނ7NBŸwvMz4V/QD5 I4eP-Q$EfR δ=,w(⼩;-/Nv T( 8[an! G1'e3S[kk<j0b !J$ 1= Mr4)8OM8'bU9{K+,MڡkG mY =A/#beodUp»oT!#BQZ݊%֝|\Ihk+}eywTѥZǣA?|(;Ql'WUL`8&fqLyz߿ӞΙ#l;5]mMW؇",us&9yxRyf@٬Yvݖ[/pρ s l%FV%ա8.gfru6X,HzV,6D=?[Rv  ؓx3X`su] z\'p/,celie\?x3˺Rp,9_V*kh_k!G_bZ׽Zxur"E= F#(G>m]MeP 3pMt>~gR.%1=ļh!qt]p7 } ',+YӰU+a ϊf֤YG{ `ԙl'O^Aզ ο H3aOǟ8[-Θ_0*,MC{;=3PKX Pm)]\Ioʦ54g5mz@700[uw7;YD 7,,A.,&i o40)}cLڦ95Pf5@yXR}dpr~z9pJW|k[1[l>95 ˥ztړxLJE~>2]jGvϷ\YQ tH`Ebk+R,&oyUK>[gKnX}DA zM_u.+xFBū ^R Ј ?Ӿ3Qwgx2 /џUYRtZu,fg̩mLp}tIE4n Uzݸ٤xQ RLϵ\ӧuՊbdmMk͂]q2G gZs3Qw;pėgͶ=F&^tK}[k8@&tm)xUٖkpO׷ 0֘7YWBK޻/6Ar, n:l gm8P zp\^3Qwt-ONیm-5F _9}ްiv~M3 :w4[OrΙKB)>4 S^*qJ/`R5E܄X[ 71ro75Ϸ\5+$._6}4`9k}ʰblysY/Ų˒;_FdUnBá-g]r^UWm#~mIj g9S勥ª/5MNzhʸbE~Uٶv4~ jfCayǜ]mzjG8];z Q¦k\+kV]Y\Q1ҷQ/N`ŅZCF~v0l-ntg.Vka ]bF)/oO$F:,K ݓ^ЬnN#VZs%B)QB00/3U]UhMMR#/"cI:OH$ PG{sICacՕQZ;Pg$cQd[~i+RJ޾8 I0߃2|lgp~z)Zɘ$h^(۶QuذIFU>>ESjY(" 1agX\N)=$SISi475㸚IOE>@e'V NgmG$qٴkY @<(hni˪X&b2}f3[UDRak C%}4>Ilwئ:I*r,#4)n~Ӝymɼ= !f|ak)yȿ ?w*L@gQ&'&itwwe7tVք8|0!;o.Xk@SҸf 6֋ÇaΜ9ٴ 5S$fD=Jpa(ӃƋo&'0o<VW !$ _0^:1kA1j8F)EAWww򽼴ٿi7[35;~:8ebzs(n>| (HK{qпҴR rLch: lOSئ|ˬW8^!2~O׷~ |lV,N65sqq tw}xy:z=~3'-x#Y_-z@1(j2tK#ZGoGAd#K=̽Ninį%+V3o:W=޲MR W#~-4.%Viڤ!4K#Q)ixi~%"G@`PO1MzgZ1aĻ(易v+Jj8;oN r˭k0{/ 4*D_㪑Q&>bL?d-ʳgtIJUJ^-@d|/pߠWW8;zIA0uㄠ2][8na?Z!^TeuB@0e$x0ꝏ8[Ո,uZ3Yn@am)4/7}EU/7W͋D_x-omV̋i (;M^?+|B rjC[q GSM(ZXBO޻D5z}Hר|(Vq'>*Ngh k> pJ1;vlqs WؗPֽיە|;984mk:~s%U9 an!h .5 Ds!m" ^r,(*<]s< ڦmq˞gBi]\JRcQuގqCcCH$hoD1Ya?Ξ v,0CQ]w˖np+QzŮXz(\'4>Q|6R݌1| Чpprq#eHMU|G^~Ο_?i\2St Sԕ_ꈾ,2T4[/-Ψ)PPćzF.ೃ79?\d#B<2IR M%9ss6M#) Fv;6~X|}U,:fRjFqb%| )!}{7z5O7G=Sbwp=j4j˧ъg.|JJ?[BX혱<'Fn~ >ywCEeL묏1zqw_AtXtjRB4N= ~_9yПa"gB?+HkH?G)(NL/\5 eaV3A)ew؞߿.՝86ۍj'_]]Nc<9LyH 2Y\jůgSd7_uRùF@#2Jpķv|W =b^0v;][Uƶ@ךn ƟĚS(m ; 6BߋYC<]z1ׇێۂ$ӌ x ?dNRDqD DqG-@!%ٔz3+N`(Sf<'x+|v!y¼ wsN(/wҙ-Meqؿ0 Q :r4Z1n.>YLT?V?30Tc_TZsy4`0 /dQ.Zh{6,CvlP^AyMz/Md&6'myϥQ}_`^ 絆"V_#˿WqDAb r'`oJf+DC@fIv,LhF Fvq-89|SMg+E\:' P/4FdileސwaFUb Q l2+z4>KFo%wح@WB]{{n$crr,@MLpBGUpa( !! dYBЪ4aY$"LBRB;)"V7( $20524LOC$Ȓ`J͌2Y)iHey͌ x>oM& #XAYuh_ a@)Q>=5@p-F P%`m' +ZUfx."88R>?I ﱗus4=NC[s/N~("(S4XPCg 0OqRL#}|װ42 b vo߿:>P+ Ag  KLW 5K;e(B %ꨳFgzdEδK0͸۸a9Ν#| nQmQd%Y" (BQ-@,+TlF1 N=,~Rl?wB5+"+JSch -ůz8,H(,A(gy? vtGyw+t[ ,*Xz 7,_ĐC!Rfz0J̱t.@3zq{߭~/"ŐaRC;C}x"쨞:?/3G_X;@VK P!&祦K)ĩmӵJøv軸!zs ҈W޷t\Akxi 'i$szpԻY%tk6;UٙbS`xF:W=a",M G?߀Z? XBTaZaQ,H|P&;q+Zur,7} Qb_?5l1?S`ye'|K9as5Yk@ޞTwEւ+Ⴑ Gge<MR 6XF]S*Ruv݌n.Wk`r+ i#ޅK yՂ 1.1C!&= uW%,6n :#iĞ4ۉnugv蟋qiTa1t8c>J˫6""RF<'&cFxl;k t9ތv~t $#q4][PuF^t 2ӵŸ% Gc[qط,/offy#s3LF'BJc(3%3Ut'Ƹx=a;"V + 6p~N}LrݘtYW,( A(2]5(("HaYH1 buK/#QöFe$I|^}Et@\i^/`Y8%~vP ECp_ױ߿R IҐ$ P2ZXo PW!yNCiIx7cu ~C.^RMc8I7߅EMJ8Է4`-,A(\h ЬS\~:v\88o̔a:@_xuX|G|'⥦KVl$)P7EoJijiY#/S7Ͽ6ť?FHkʯ419ߍ AH™aSA䩊r <[?^ @qr9vHr3F8h"ie`C!w{#|1Ϧ vyx[e픺إ5[N ʼ`Op= nĢGLP*,d$aEr Θ=N,Eܖ*$"L  6r-EH`,G}KSmmŢQ G-5,#L?V,4ǧ'DxZBMlm\ok$IB%*GB8BRN|x^\^~oƯGP*ybb[oBdtXJQ'9I_'X;U8߆S&X)ŕӞ.uaП&(P~?<z& >0;{Hi!RT MPT2ecod{)*z~<2تEeR)p^>߬JOf>;!.)?ctF$fgZl'=tlˌP$+ fίyQOj~K<@)|~?DƏ#6, Gy?z(聥Z';ƴ;R)'tvd ř0pTwLtV3clXz ً 2^9ձ: `Ӈpȿe.L}L֘3X߿A ;ʀ?:7Uqu;oA]904^[X*bM)1}1-1jSa|ވ|(eW`G;T] \[kcObq MBpM8rL] W!y ]a{Ͽ1n}JJ)@5%a<% %W$M* cUyl@"oQdt^J(IinS+19yO @ qMxK-UG UGͲ,SU S'Ff?7|Bu~#!F8 37K#} Ҥ0.+*OI\Uʮp_8Wgv&6N.}l.hE)"i70w hdnͷ;yuXd"Y?ᆣ<;`O`CeC_2Cż[qXx,ͅ]!wf]D8lZwQ.Y&CfˀBȊts >8MV >;-,M{:̜λ3pªON0FyU/{,,菕k ېL%qĿP%@zXD mgܬfy/^{T 46B)jH|x3!wCkOEBXLz鬣( R487ʐ$ D|˕z^ j,Y];obtMOd}AÅ"ِ0~DAb)cy%T4dWrź88 ӞBӽ_LNy_Mn R$Ҙ8)@V)d͏!o(IP(Řw>5]M` K<"uiB(=(O!ui> 0#3Jy0 _ă7#UB .8>0}o&^9Ŕ R { Ȋ>̓rr xA烇`A?3\5X؂<( %/m7ocW`#xR*d}垷E5>-Ǝ4rfe[i/._A>Xۤ!< J.dO6XvKar/ I(>7;4ۡBt#"MYvC;hoN3>|a)@P ';C &4Μ o$4!4^+ xq།Ȳ Ayg')>>C7y'{Lvh_(D~,$<oqȿ L=#j03_;J^_ Y1 4]Vq}^)@`iJ<Ո_FdaSAay;U5,pQYt~@'>1e@S$-Mck&bM)?Wh1M4%o5kg2  Gۿޚ]pbrNLnFbOpN]AEߍt[J+/`] ,KX[A@A`{lyORMg~ǜDț"(W^'~s v7ʑSR6;WѶ?mXv@mEXLsԯ2qHGUb*QtajQ8ʯ)7ŸO\[C<%W4 ^ͅ.>_yzKFcf qs}wWek3w&p}`q({+p*AJ2C*i,OnŪsXxl^~( K /yr'{RwZK e25YCmklmN CB/G+0?|qO>~r@/Ň'")&bӜy^41[shHwzIFђePa7C<~~\~7z}1C%Ilcv|!˫)F4555x$@h ,"|zah"bP-xKX-bcL:Cx B9jR2Vşʼnɗ)S)qt&yTMMuX*x( 3sKbB?_A$(U `f&W(pJWΘ]~j Kq_;|:-Z@Clk"Mi9>(Uٶk1|LTB9(\ba1n.^ _=V!FxQC(SK*Qxi*P~%B`B >$V$Lzg((94 j7|F΃ޅܟ(di8%hyG[Kߋt8_C-QbL=; \*c.NLlKXRL3 /^ܠHymEdlWJsӗEGfgvdySq!LZC wX݈[?Uqk |K+Q6̫[Z>1nQwO!"ł4dY]Bcm8 4SPJp8x<phFd+F9t Y7(7qw"|K1[(^ H&P☟~w(&SoGU)`JGrNHӈD"`:Sd("@-S( ͨ1]a&fD4k&[}pOcGL*j jgP͚#_ZLux3;rLB, WdQG&xf4z7$CW 3c fisXz5ָ dY 6a[!_4{j("L"wj!ApA+Cpf.be>cW:#ͧi`H%% KtV8LXh PPJX&^6Rkq|}̄i)vOŽ~em|3r2@7^sZe{*>?@qĆ ~n XRܦ"PGRc@H$`J˓/fHl_H,H$|3o.0L=:1ۃiO.H)6$ۄ$>Mˣ#"OIS/YE0vhUgjG2 yP(8k*H$`Y@̏{ bQuHnŊt ŧ dYn\͘NQ$ d,{bl S`.c@%_I/'!t:nćgG+rnOCyHS% Py6p$MR<(̉7Sec?FPZh9SB˕x{өU(g* {ЙtJ, cFӴE^ k'd @0lx @20S`}&byE,M%W ȲT2 ͊P99IJge3 = x5r!E)zHÙ]H @0X@-Q<-G*|FP7ҥEQQ\9}l>r<kXBD;Z -ϕ` :g' EQ"nzw2T{ϔ9ev2{tjB@,IE70n)u/oc(I"xWC{fFx+r6bl[11` )|G晈X^RSJC[]8剭z)+LO~ ݀8bxW(+YVa&EQ(z`,وOANnf@ 9jV?&a.5s $YzkPm»V\<|#}+Q   2O.R|99ȻƐK%3K|t6,Y "^l@{0+qзqп JE)chlBlTu+ J u7@Zb/Ƣ@pbO/EDÖc3e!@K%VC$(TqS2BiIkP-( @fX@>:3$;, "T,E-8g0杋qOFyǐoEٟ֑$ $S 5C16zܼm >!W#^u2aj#x 8[V4}Q%\ʀ,IP(~L~vVLyc0@Ӂ8ێ Oƹ9H9̺\A(%q%)KY6.gi YiX vNcGQ{8%)8 @HƔcM`^J! Q;*E"&^Lp{NI×P7M2kA{$"@)6*3Z\hf^E?YJd@Jt34 o9}/15Hlw!l,6]Z ]eΤ [hYWAN/Rx؜4۟ܗ:45LjF#Q$Brs maXF57b; YzX Shq3BRde,N(TQlK)sDUrc3TRbmg chMm3-ίVI̚wT8R=PruPPJ!Wu*Sy6Z $K}m)PP@S2 ԰ -J-, hC>@K]EQ@q׬-Ir^wlQjTXWhL͗ᥦKpZhm#^J!y=fC}OaX_G$Đ^ɘ٤ a5!$yöETa0 Ӑ2BP ÂaȬA(P À4x[aX&qQqeNV-͗㥦K1 .¾kLuҕì*뇎乳R. $ 4Sz$,St!ujԶ Tèmiv` J̜3LFWHfԬ~N<&jҬ} 0# Rǰ6$>2~;]{ȿV"Tlr07{N^ 4/Qny,ٟ[tlע:}N+)2J}+^XQb ^#cyb+>2Xj{ӭ*@@UĐÕIܥ/Rʩ* &u n2E7՚3m!+{,RB_jv|xvNXށ'أ`&ζ妋W uUTL^lU`(t?=Z(h4SZ6\/nU7 RhU@4sɒjj*˾Y6}?=ҷppS-@ U7 P`aKhlP d6Gd7vjNNϵ|1z/cZ8(lGQۢiP +BL϶\g[z}8~2ii#.}ˌc;+1uX= TC g=A,ז’/ղr(.k c^{@tgD`*;w<Ӵ{u\+t>G3#FKɹu AɝooufaAZ5%Xtm..)A.vg`e1*>NBXᒿ㝪[nHҥ~ XxyԺ/Zh9c8XwPkdCJR0ݾAɚ8PnYu -[ k%#"-Q95|z7z/)oDBR(<  vBQbX d-BW|Xn$bpUW%;_1xkK(nPhK`';q3HGe*B=(Ta]{CA`ieS읤tT,c}S^kOvw,i1x<էS߬_]z Eֺux>Ѥ玵0XNmmo\W/z{<^gP~3R)h5ѻn uj{[>^,H~Gu:+ùv'fkUU +z>H~Z#˯Lkﴩں:|L{Jb{gw7z梪`zv6Wkj=u{2Nm:7>> 7,JL囋#F.o{MY,vZ[zu4^|c}s=/ǣ7з0{{NiywK\[n8 $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @U IDAT $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @ $ @f؟ΛIu?}cY?]A.L,IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/attach.png000066400000000000000000000041161502633300400217520ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx͛Ȗ?HHH3hc~8-JN!Rщwef/D9ڎ6Eif[er1y8~y\yz\s_W.  l`05G \OJoKs"7%m[!oguR3`uizk>3ɸ;eq`]C~:@Cp x0x8xf>59np!.p>8o{gew5oVk<#\zyo͈f jԸDtCae2?-kޚcemXG VXŗg[Ű;e*.1[|ޚSbhnٹ`|"`πe5|E}ubj1[~ ٔ*. b Ue~Fp֌Ԝ{2Q_0xT on!_ 5ޚB>LBt;DQ5ųh!bGWB?*_\\Гu&OEr3OB4.rTyNP. Sv=|5/C꒩ҶP6f]]Re::UۄmB24YpYX!~+;7Z`REEډINytT9X]{IgLJ=9e{b1yk cRmA yG=;R"_ԿFoK'ЩʕeՇ9,TȓT43Bo㈛yv[_WS%E43vt@КbnL8Ye˂A'o!ȓ~"`vݻ|c!HT3vsB$ecTX$C3vsj\SnYN 3vsZTw{+%Htˢ~{RTUh`~)Z r EBYz9:w9s9{~ܙ{]L@a4D"*:WWij0z8g"`"uv 瀯G@g0zȜF  hfy'h9?8?u`Rֹ+azN^r>  UԮsXxxK ka()~PRwEA| #pș&vARA| #Z P! Oux068_]*)tTFc\A3OW+Rȏӵ8Q\;K3Ǝ ћ$:CAݟ6G>qCG0v19 Й3="}A,.& p3ȆGۑCC%6g `!pBIi{iɶ B~NqDhl7b[_-?<`5Kvo9ͣB%Jh!n:}a iW*)Eko /a{F M#?8 m=cvq/Zcz~½M"VIqR2qaM"p 4J}vC˶@ s^TF"nPR\ʼn1 x4]"<ߣ$7 l'ї [4#JIcJ؟΁ДC~w>sQRLF~bOzK=2C=fӌTR~>;|cK ǁ$t`LIq%enLT)xK#9\hpi9$p:k`w6pC3 }&s׋\L q7q*D K:!H! XXlqvq+@c7󥒇O@FoJ6or?[6۝~7U./ OM ymt\U&OWL6ڸ /caBS%2GXT;?3G IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/axis_on.png000066400000000000000000000034271502633300400221520ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx՛]UE^D'^"D> *"r񡨇Jjo3ʲф ICa"!""! ȡsf=g}3gϬϞ5k3q rٱ&T66!§=2P gzX;DW%08De7Q(ρ)_ONQ8b Q F,PB^;v׿A.'I&yoBW DJ9 ,VB t+$B Dk!(!k*={nR _C>a8 =N WHm%È"t)`#3 {LW׀yJ?>]#@1'Ko]2ȏ:(˳bg!Q&'#N~xf-BQ wyav{Cdu&ol"AȻ̏?"~w#fRoG6Ay[~ˁEq%dT^xdEM؝ ~b\h"'m0vGEJߔBpD&f_<,1GmA/a7Ž`yb=W/ny5J;'JKA>u7mt,v+! -[ zANhqbLi`7:JHcG~oeD)!d"ˁD7Bor6(!U`)P!?`., !)k(^gs"ܔ[݈۽ >򛊌UZWƛ88sK3YST@J97sV^t$BVݘR䡄55 e Pp d ,QB.6;MFJC7 7a%76ۜEWq/:*74zL>mO317yn M(Tj șxDa~.JK9f߭i?/oҦ%-\fpyv#\2/E<SEb7[0"AOnC|V~I0CXL%:Fmm%)N1 `N-k}QPw &kiW okɃE-:z+AsƠ $ۂ &#ɸ|ePV>gEsiZn%IGa $-ځuO:E`nGjIDATxOh@J)"E4^,ZZDPQR ko^U"# E{PRD2$C),Bfw&oc^^&/$y3I:q8 v 2[6v`? \* ˚1h8Xp2-URv[> 4G!PT`Zj " 0Χ. 5fB*[}ZD3W!H3W!H2W!HUZ>U HS -@iH 0@Z4)  Mai HS - cJZ3m8 < ׊8dB/C`sM(߬V?j5hƀ0ܱZ)RRP78 8ASv m;&q~j1N[ ۯI_vmĀy\B1RW$1`cj*Ib@q'5%BDPU-U.E(i?jKKQ|ӾxnHIODB_(8?I0l2jl \_p86cR-p`6bznS.pی~`8i@eHӾf.5 S5@B2 |MKQƼ Volv$8`*q~ 0l&5řUqxZ"KbVY2j5C#*L0"hVV[3k y`EO#wy2`8b+58b@ZլGVOr asI8#ARyRu`:{r QKIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/bookmark_on.png000066400000000000000000000016171502633300400230120ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+AIDATx?hAH"A$PHc`#jA?MQGt6AuP$2"#"AE*b!ADRI%"C=!lvn~p͛w6bn@7*L#޸ƶ8'e5޸p5}xZ2 }X:ի C0ց`5FD fLUe&`fUeUeUe@9s䡖OiH 0@Z4)  Mai HS -@iH ȘR8 x$>b8'D`sE(_q?uhĀ0_jO\0pl93޸b=$6 IbTĀeuWjJ2`IT8 ^'-1DFN/%=U~OSV['otq u+ih;덻Le] m<ܧ]:/o1z euo!ҀʔV2:s`:EeMg8Pv_R1/`m}bG`o\ F>`=)N.C;K`%O ޸I]9FO7+, p߾(AE ̀`MOo8$̓sAoܷpCf9EC^ (W=&57.Ν 3I<̀K埪X@IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/bus_can.png000066400000000000000000000035121502633300400221170ustar00rootroot00000000000000PNG  IHDRL\sRGBgAMA a pHYsttfxIDATx^휽NJsp(1)" Zv*+J<hhx+QH+ҡ]F.AIax<| ̜ǟo  @ C!ȐdH2$ @ C!ȐdH2$1\,jU1'Gn/y,:nz~_1:FsyafXciz޹KlX'֮'I ?>z!{%xMz듣" xK!zFFAͅU6-zw<}&4QkbMQP\͆[cciw칃͕5 P|(qz%z`>V0DWDV@sD\$wpKf% 0 ;+6"T`/وPBJ@ O##(SdH XОe#BL؜?*uj{8~u9+ a`WjG6"* 'xm_xm9MG7I0tpQmF/Ć]n SN~B.SbyOp!nWFu{d;͕ކ}i|(ZR31 ړ L(57a1S Q3}B @51tvn?@<нۿZ P:w$ן{EiXHtMud7^C+qU`ao(,= '(}<'!B+ `{gpM"9v~yt:hZ`b#36;fT@O&`%QÜ$@QPm`{878L`߽K_Aeb2,N$%o!3Ӟ$eʇHo,3$`Z @IYL IYJ 0 t "j2KL!\uBA L3$Lhj2!`eB$ БH@$$ t2 AK]h C!ȐdH2$ @ C!ȐdH2$ @ C!ȐdH2$ @PNC,*pBIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/bus_eth.png000066400000000000000000000011201502633300400221270ustar00rootroot00000000000000PNG  IHDRL\sRGBgAMA a pHYsttfxIDATx^!nTQ) $t4xbTX !_h& jH+Ji9f_}ά=2se| &@L1b  &@L1b  os;J21b  cdždb  &@L1b߯0'z>ݯc}I1bMBg/~|5ab  &@L1bM?bL  &@lch1e :_AW<|t}lN9ˏ96n|96_٘1b  &@L1b EyͿe0%@L1bC=6b  &@L1b  &@L1bs%yI1b  &@L1b  &@L1R]vq9IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/bus_flx.png000066400000000000000000000022761502633300400221550ustar00rootroot00000000000000PNG  IHDRL\sRGBgAMA a pHYsttfxSIDATx^1OQiIAaİbHԘ ?Хop0q?016``5d#Xnw|_yCL|9| 8޺0P C`( 0P C`( yH2uqkw6 w C`( 0_ C`( 0P C`( l$y䐥P(e8GW|0,D!L^ C`( 0P C`( 0PNX~'xr,k;suk0!$?jbW?-WO-fTgv]9Eʹ0A)*)Wh˿^0W+ȥӮ GY")@KmzOz#Hg>N7 VoʳNhS^+KLS4go;2mBTc[nmBV=KN:J֋֎1kPBcFZz!\o*2\2siG*R=oDЖ8s&%V5O"zG6C&V7 L[7@* A9c'iўN9j*nJgr4PCMIhKP]_]i>x?uJgӛrG,[ :1+z&mQX悤o, R>G4shZTEғdQX8~v#olK}) LJ[s*s +01 kXr/'mK]9 oOE7gzpg2A/HN.I<+~bg7QCO3:I藃<9y} w*fLU_Ό3DϭBrLU >.SGqh{ц#tM]WOsŃN̒v4AT&WJrL;f4ZU9ZEצRՅVT59~+:=> o;$(ϳwaIވlUx0,g|zm:ct(=63yĩͯBfēo/K@;S8I`Uvb(D2^hd8\Pv|o-p08s4\<LSaO+WX?|X,{,-aF`h+t,\mz*BF$e4:7  ̢J}JHhY FtM?sgkC=f( e_>7M^YZʧ4-5\/T)(6o>7VfY*=mrG^Mm<_ݕ/! i5N=Dg i>+7~mvN&7x)0+wRn1'h 0{lH{_t,F.˓`s$]fs;#}a&P2ꓒʙqJMFVƅ!9,W9^dtq " _ keJDM in^ 8u !3B̃ 8eays7PNȯ KsnG̤ *13_=F-'( X_^ X_^ pnr_^ .|.%0( ŴOVMk?5qѿ `9,Q@#Ͼ`P /`R^ >}3FsTsCDA`P0( A`P0( A`P0(X{; IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/checkmark.png000066400000000000000000000025161502633300400224400ustar00rootroot00000000000000PNG  IHDR@@iqIDATx]UU1 aXIFEdA>l̰ta0VN%Q"QAMY1&(D(CQ*ڇd AB!}0s~{־wΝ\9{ֆ8.Ćq~>X YVj?0O=8jOLI}k2y6)qR9I`~fcN`j5s;`yJF\!`DbU7?Mqm@WK`o>3W_h98KpOK`]5VZu@/N8o5B5Vb!bgC⟖>2HB! )ckꃖn'JVK> ^6RVM^6md 1KqABʻVzTZ"I J JHm돯$#DEB Ac^KL! AD.!pǚӓ=>??>3k֬=kf1󀇁SI0~;V ~7` PV+߾VGy<̖u9A`ju 0163iaxؠfÖu9ju-p#e;X 燍_`'ObV?*5X ̰[Vi@'(c?0a>q b#4 . =!`)l:%o^QwXlG~}1@|`p 2RMXEF ;ʒZ5q~ p+p0M^ ʮZ]^"t8_$q~X,!i5d*ڳ3 \ث  o!VoJ+4a/`4VMu*6@XAxd G\ile]R-/F" ^)Cׁ=V01XF[wR5c @`.D{CvNagVwQlMH3G(.azDvg.3\m*u.w PA\Μ  T~'V}U0q~n:ݤt;a'&DA`1W VҭO1bu߀+KfבEJ+Z tZreAh̕AÔൂcMR3=fT\={u`4H0"rr> )jI~2aO)ݾz3@ʝ GFX^Bb;mYlU~քSK7mMWEW=dnwUN&SebF:iQ/A]%S!|dP;\c8KLJ:KRXOd ܝixN:4$jp},q>5q~L'Rwl9rc 8:=Z[<4@X8gta%-!y S<Ңd]e$G/B61#3L*z>6ct'L6#pEprIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/comments.png000066400000000000000000000021371502633300400223340ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxKEmE!dKD0/$xQDZ_`]ăO9aǡ$ ɒG9bN>rӃZ,"$ ˰ ;魮i5﮿ꇆf2v"*HeNRu2v;pXƮq8R"'p 8»Pƶ6Th)nCel|"<_Ɇ$R*L]o`ӭng\&)"tesqMD=Cg"`գ:6DW ؠKrq&ϤÀa(IIY^"v9BxôCe(cw\#<{*YOO٭;LWW'e+xZKq-yX`IK-%ena™lp+N1_%_bWT<ƦqZ.Z w?Y%(R*cwʏkWvࢌx,?1tG?W7!>zΐw6Sxp0]/(d]_(zTЄZ:UB/ M$7zta?Q6r/%.rNspS \ UOhB/D~Â<ݑ !M婰eňqXEjhbg1IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/compare.png000066400000000000000000000034361502633300400221400ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx͛iE,BX$G,(CLQx`ʃ?&DTT%*FAQh<#Tb "?T2S=Sݓ?4Sw{^e.C %?6h)j@A_:A;xyE+p.ڨM(c%<>`@4K0\ pA| ̬qvxK#(p8pt7XI3xS{^w>eB{Os Zɢm~;91Rl.fU=L@K1 ^U^X* =#Z_YP$Dm[= ~ z{ i6TJ TG@^; !am88?JخQv 83g`cَi)TRbzh)&NWF7>x#\-oy+URLi)&{7(eBBM(wg_Hb>ZN"¸'m♼ (c*@m$ԾR(ek8L#!an"@; ,>  A^Vu5- !02vQݢVJH-۔ז_ydIB¡Yt4g3: %lw>E;;IRp] |=6"(xW; ,,ܽUI8_DOi;}ؤ}X-/p|NSLݍ5y/AӺc,SƮR]!&6s(cwoWT!,QӺ[nܪ靖Y1w)b+h;|sȻy:N9"6)Zo}Z1Z- xj@U,= ~N<%;aZ;!wKm@fY!&;jP;x*Tu UZ/Q}=xw |['-;`igx8J~1LZKV0}XӡؑY&dl:O`Qε1uc\zH3LD%5#8m~c`Y*eARp'm#ⴝOOgw?.4vEeRB|dNi)v,I&\dx'p~;Kڏ[sqznR,O~ĆF+-mEf3筙s,pN8pScb2v%p .QT糰ZKC:#'xX4i5}VPpR|x#:5q4b\lO]b-y j) ZIߡ]8'_{"RJ"s *\OhKu^؟Ike (w?7.W)>zou;a*ux4`VM'3(NѺ x˓v264bwdmp'.m"p"kgxQ`q;xlbf+61XAm)- P݋cR6`P> Sz-ŽIBoGp-U7=%5+KpjLy'&efQIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/convert.png000066400000000000000000000027631502633300400221740ustar00rootroot00000000000000PNG  IHDR@@iqIDATx՛mUE.,~ D iWPDQj#aHkD R蔉}(̠*)(Id?HHH,>̬=眽~؝}9ϝ 숔RKQwQ Ĺ"2v5Ave"RnEvXGA +E򕩖%@IX^'\ꇩ;$uh)kPW 8t=je=%(,`SAX_F.Dؙv+ce \U/j؉!]!D!isR-DR%Hn.Yo3fzG-^/Q{Ǵ2v=qT<]1GvacKwj uaOYW@$*:j)8aqLo?<OKqX`" ,Jrj)v*c2< -{p޹IWA|y}.dx)E'$n/(3%kB%p)٨4yT;e5 \z@^YYs\wl36TEBp~#Ab DY!!2dͭ~ٱC3G%& S|JnMr(c'W:ӌ-i8#j0 A1~Ķw|3+ABN k ݩ> HBF _]ωFzZz[c)O?L`@+t P~s{hVq KSe>#]]YގXʗz p[}ַi \}"8čWi73oGO +maL v^%: #kuIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/copy.png000066400000000000000000000032301502633300400214540ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+JIDATxoEr{+JD$ +CTPIQ$ 3(MJV aՇ ){ԃd y>̮{޻o'r{̜9̙ Hv`t`@pحo$Б.P^ $R|H^pa2vphee@{#pƺi)VQ~!; @t-6~w-72SK"XСNb:Dlةoi)jkSS8 ^ȍi)Fgw>NSAK1)&מ6%Tў?n5z6 /͙} ;phzE"MOr-ŏdEWSEH,R%oPvӀ FgԞ+n@k#|7ƶM5`>oԩ}+uIs*!3Zhn.\KK.L5e^0R`%T`"}*gBkm&f0L $c4[lAF% B$DEFK% rf W Y`  1Ș P>NdR@4_Qa+V8];/v0yT\%[Kas'E#ǀs@7dU1`VzY8[mNhu%Z SE'T.\>כݗǁ7Zݧl$GK*rˌ$ۑu77T> ,YG3Ӟ{2y(e P^zt{άnsy0Z u t[sV80,)2@\ |Oc5&TlC6ڲ%ЏK`d39٤8QYH9A}/py\ RbMPz*CЖ! |ۣOZmsBy؁5.BKx!U>آτw.TZCدq$ ؍QQ8yEko8I,>5Tq'ƳWzy-E/Kp j)vs)g7laZ  |0r= -Q`2%\q 0j{:S7,a(zO5D9@C|#ɧ́kWeTT _J2P|#ɍ6;_|%ԛFxΖcԏiJ;]Z n:j Q.L65@^?Jt4y6Pp/ga`JY 6ɷ&IcRY46k)e8gƨlj)VA)h+>ڿ؊$i6b B Wܙ,,]1bvFd.`/I&pIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/csv.png000066400000000000000000000035241502633300400213030ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxmEMD,d01IX/9QV"bPA>fYiJ0$DBfKf8wΜ={fggfyf!F~6h:[$M_ ڬ8 | ,8QT;UDq->X XY\Q<]Dej;mU%SM@#m@<ȉPV_^QUD]};+*6>gn˫\\O`wJ]VQŧ!5[@WPn[g|*R坋} <Jq>0fף2> k-}ő2⤇8Q.!!sw!CO-hAV벒PR/OP-( i75;[BQ_Gg*,b%mEζey*y ~X"( 7 )`QƀZ4D83ÇWzpwt]( e6n(02INT%`j-b!`t B)E `S>h Xlp<.19q̑k~@jhp9QRAK u (6Vi^*RaVY.ђP#)RQ" !Tv[p{R.i3&8CE{Q3h9+9ZݨJqʐꨧT+2P^#[e%bbԔrskQ\EuSeFV:rt]FU*osmAu[DnXLFQ+/޹A03B)NR,BM͎2;Pd5PZM]ڳlMh?8! [eԠj`}śPB(a3GɆL F3XG#í2wLQ!;Ɍ؆R6mB5J!<55G7Qn·PfY/ 7=CaZ403B)  |n[J@ ̴dlJP6i5Vn~-⃡ }nj@%^˵(wa7 PUaZ@%%Q#)o죫Ou++uAۍdžiin clCip5rvƓ>464TOޡIN]ѴA/ z:޳^c`MAO$f?嫱fA\-@ p;b*SA *5~"u;R \[G#,b-Jm`,಴EPԺr{9_p}Rr}͑7({չ3!`^*ʣHI\ǣ-l@ Qsr,X$| B-V៥"%^Mpê<NNsqO&NcB)ڝ8G( s=ql7rzp W>Т<#61xOx  HW|KR j)V(c*c) AR6$Q+4* !U@C^ QƎH/w]ZWeE`2vTHY|oj)v  2vlh"㤥0m9y*2v|"H p pCSĔ#WqBpJ!O!w8L<180+o9PH)ᄇ܅Y(,BR3_ |]Z<5j)N Ay8.b|H ѵp.r\EEBV075{}$,MKqx: FITiNoL26^ӵ3e!w+cm@Q:=׏G2KbV@ uWrb*j)Oq=a|$t%ہu! [<K Dc 3v-qՄ@PDAQVw꣥lA+- H&$1v,|=H^QT&(={1mh{E!}p8)c'$̻y^qVMBVt?tg[fUHvg7=ONLpL}fgRv%x0AEZ qX`]r$Q!tl24 oj8LR}ysϪ!%J[ 89F=njN]#;,BnU P>rRaàYCCo*Qo$ZXz4^ $X(~$*MXeTLEE@c1@2v8ng($aweTC@z!`Q-E1&4m5%4G"чF8Pj)TF1Ha E2v0'k) 9" 5<[,*cGOg ]R\ ex`nOt$ ˸mjjyE)NKO ] `\cѨ鸆Nqdz | p01F4A pJ[!2ЈG < |7",v R4e\EH+nIE@h;yCB,g/qA5vַ|auStNF ZݸKFOEWrL7@KqH/[j)?"72n 5.eql*=9_u#PeʣN1HWk,{!7HTfH>O j*]+?7~3,tޠgU:bM3,T>ܙDЩ"r'xS[?|ۯNk;<)4.^d|ߋ GwHbDޡ^O\61om$< [7#R,eø )'$֣P}6E܁GWꯄ˓0IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/decrease-font.png000066400000000000000000000020731502633300400232250ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxϋG?6 ""!l,AZ\ E1 'a/}A%cE!eO AȲ,9tNOiz^ի_@ OƞZYs5:nhcǁ6A]cvEֵ@Q8Ť6K_#|5J)c1O_=5J8{NzmV7r@,6K:VLS&;*NTV]M>G* Dhc#`F`\`Sui||Y~5'8R$ \^ |̚@*)B5vdS,\?u+=)m]H"@̮H.zG"/%*^HTx((3`Oza/hc]3K"`F`X2tn4Qܽ[Ҍ0fK!o鿿x0' lum>Q;ʮhc/\v%X憅~[P (Q2~Wu_&A6tH  Uoq/jcn)o r,'c+n{ S$t q{ Xa]ex4p>\k:Kk>IT K^?)&59)lm;RC'{AH&8;jedFdl']J>+,&'n@l[;6-, '⃰{ i?w1 , j𿒨x#m J;o'lv=}_ _vl@BiZ'd΁dI$ؽicwy"n"ZړV?ox'meQGTu5pSh>*>Xk;iEwR&@ _XЅcFOIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/delta.png000066400000000000000000000015101502633300400215720ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx1NAg5];p9i"W#VP.\ GҧaS@@[qhؗ#fq'!aiP( yut(D}jM-`~h?dqӯYjMY8k. q;ƱdЋklϦ&."@ EU iGU=*-iU=7}ϰ&z*H~ ղ-l]5D>TwyvK8G-'j xBw=p9ތ7\fH7 xZ ]jkDup~o#&HY^ţu26~iAh[gwc 0ldua TZcuZke1P@1P@Kbqi p ae-a R{5N& DW ARk&p[;dlJk"t1P@JB:1=A 'H@8YEc:75N$ ke Z@ZE삘@.SP{ۯ1/ߘ8cbqA/ZϣK;[(5괆&'`zaeDE^@P( BP(l?&vkIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/delta_on.png000066400000000000000000000015021502633300400222670ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxiAQG); B47y8!?M|Eά:[~fnBP([(\z? #&tně>1W tgB6Fp1tD' j&@x `32X2J~0qA"Q'p<\_iE+pcrUƠb.3pu\1c ^ WVTQĘv 0_m9wO0@X;p6vO`*$ \Nt\0p)V56@Z;ğ7߂jkl&4mskDW3w,/u265{1P X]汵6 c \FU){r@Uk/ť1`@U =_' Id_lsSZcB{r@Ei+'G " b1Ę' Q=AjO@ Zdؘ8Ik{,c'X{,c-@@O Gt >$]gmYhw KD'`vWji?CKTB#ĭq^;DG `[Cbr=^-++d'Q BP( Ba'ZQ`IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/down.png000066400000000000000000000017551502633300400214630ustar00rootroot00000000000000PNG  IHDR@@iqIDATxjA?qBB#"AgЍLoXr$ hP1ƅ3dN m;SU=P&s!H$D"HtCi~9ͩ |U쏖ՐP澫j^O6{U`'Zis0n!{ J^s ◁2 XRktP2 1@ھ(ޱx9/ݸH+25agyͺRqlo7p_)S`C4kn2 6&w؎?VsOg™b۱&7Vۭ`ϵ7`_O|*hLdNKsŒV JLݼz8YGKsB LԅĻjلn@4ト(m6aﻅ-#Vנ &-WX#A! KX,N:@c|p(m6/ñb@c+;FpH5Nb[)@DŽ)lyEd(<ZB>*"wCV-CC@DŽb@FC@DŽ34,:l恺M;nk3ġ!.iCC:ț[sGϰ׆ &D<0 laDG&_L$D"H$coB?IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/edit.png000066400000000000000000000017471502633300400214420ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx?hACDR,d  hcc VdDPDAQ+& YD;b*EL`bI!"A C6{33;YUnov.w=>X ׀/ Uq! 7]doJ|eE6!~)!υ ZC!˫-r 7(gJ{pNn^;,>0q!cζz`8iE`0"aح>,9B[' oow+$ Z ?bଵ:aިM bKL#37 txr3`~%WCF n[88; y#Aޞ<>pD{Fp`>b0!08. .i$ vg '~f3V=Cs-˫4!!LzlpZzTs]յ a^N ]8l9 Tv8山F9@30㱁 @#a& ߏd a<<v aIU~0ڮrW䊫U):{2^],-#gz*E7 vv>uˠ^+Iм0jk-,B%:U`kY dOl 1LFo5&-? H`Jib(I'[E%`G8$m2Rb*2BE |}I>#B`]X==! ;?M%'xZэ&cL^>IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/error.png000066400000000000000000000025601502633300400216400ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+"IDATxkEYB(D)HK,%->6Tf)*ЁZ >CR4(G(~[Pd(hC("%\|齛3{r3gΞ9glVBI`y6aGR 'n} <GӞZ "{(\˦ v 쏣 f=۲F- ~,\1ꊀE]dK :(tJHk{xB-eTΪv|GQ`xɑ-x! p诨jru3>xzR=k9<Tz s;2c 2'/ΔkUIfls`goCҮUaAH՝4nM6츏aXP̖,BZ0)U9n>Hޢ6NI!'*z^6tNA!:"A'³i7S空-2NS` :dG\]x8yc0[9wex(Y6g\.moiaq  QxxS߃hm0O'7ŏTcQ!pḍ_|c!cu)VƚTͅ'2 6<&Z[uo!3نm9.U0kc=V$_Qضǜc!ճ@\SM?=5Qz;y &(NDo yuۊ.nGݶ G@ay8 _|\$^D[ n%V[~W?QxF6?c~*3IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/export.png000066400000000000000000000010651502633300400220270ustar00rootroot00000000000000PNG  IHDR@@iqIDATxMJPұ t'YB}Xؕd ق+pDBAqJM_>=7& -M{~4K{QTpC<⢪7@}[]N.{9_w)lr" {w`nMBXDlQ{!Jg\INpiFG;ǡ; Ta)˃s1Eyp `UXg_r`emibt0`f9C HRE, (r|H)|_f!!x(!9!1?+3xCwK?g@`-<"L˃`%؀`^D HCܿIRٶ}ux!ufԙ<^)jd%O@=:3zu&5 #1 6?fԙ<ةf#+_IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/file.png000066400000000000000000000011601502633300400214210ustar00rootroot00000000000000PNG  IHDR@@iq7IDATx1kT1}"aT: WT(n"]:u* NuppdP"kKRġwp}\r4]ǻ.6 @3/޻ǣ4c>.?^{q^j(w[JX\gi-F 67bT'W' u `XYikC+w 莎~m(`~|R< )V<6AS6; x |_YNNbx7FoV\NNbOi7P6/]rVic \X6IwC.H֌]o@S ?~Gi׷lS N :~*KԍtT ${Rb(2X+Ut*^| N`Fԍ\,^7UtT Hདྷ.2uH'Q/ ''Gx3"=־'} }|s۷4V|c8IA~%HD k_\S =ط?2_ e0gIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/filter.png000066400000000000000000000025321502633300400217730ustar00rootroot00000000000000PNG  IHDR@@iq!IDATx]hEKRJ(RE("BU4! RPP"RQ[-V?hEġ) R%0s޹{w,ˆ;gΜ9{v~:(c WW5*{d_DY5p*pح8 XI_KC2` +5ݜ2: vkfZdM #q&Im+BZ*Nk{@ 0\$ +ZS(cG[ "#Zb)e;`E0VK1 ?8T `Ώ}ϓ?SJn X(XW?!-i`-p:P!T @iܰaGH2v9j)hW(c#u X84v*b{2>_5i-74+e쪼Kc'M:-ش$Aeu-e2 pQxbT@ׁE'[i2v)pEŷ:|u/.J"Ӑ-6ⲼsYeV6pXO}1 \ Q4lR+I{;GmT/7j)>oG~];};SWa=F8[3PƮ$HjY4@e,f̲7@4b ͒S0]w2Py(JAYRhL.y(20# yV;m/;͏Ϻ#ʻXRJ5%=kiwit2vHۛa?Q!y&mQO(c'צ"-A˓(7jFq9p S}@B]oV2RNQ%I]@CXmH2CZˀ͸vb-jLt ƍ:Ya`#p5[Zc"rOaIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/fit.png000066400000000000000000000025311502633300400212670ustar00rootroot00000000000000PNG  IHDR@@iq IDATxME%% a9,9 D$9hOCʄNCS#h‰&M aѤM0okt' 1ρMt$C7A*xh>2fd g !}\Llp߀)8p/pqS n'x 8/6N+#y7&t(_\LY[ViIj0 |Aw>QaBOrj8c12/C>" VuoPӄq``MĶ˂ϰZ "`l=_a7vE|x|aV *;CѭJ J\Z zp%͎S|އ#v.8 a VM9V~:Je`x0Z#s1$MY518ZIo^fO q{zb_g4l4΋LHo~~#Np) V{`-l8߿Es1`5q6#U^o5:۷?`ziy]Z}VCk!۵̎Op\]YfjC(:N•/[v?M̳Ttyli3cL(Vf؏w(IY阡:ykNMk屒T ̈́DoE⫁o[jU(juؓ<ׄT*“vkakm Z^Nl~ =Pt@학"?Jz+FHlC^'=c4LW֩O"x+8>fj> IgU&HP$ R+a |@nKpPQ2)6ij6 w8$6hM 'T&NrI/ET6, NH"U+pV)qmAv-nԼ $% A%F;9Ktja--Oif}vRT 5ȿ 0JX5) J\ *!E`8 UIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/focus.png000066400000000000000000000032051502633300400216230ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+7IDATxOUU^D0HD,E8$%1 肄 nhʹOBlt, ͍̅Ȕ Q"%bBY0|oy{{e?x9};3 cX K+QO| n(o)L5zs;X*pG?R^gc5 \Ջ6`|XNEE5@ߍpv c U L`;"D̖c8j*y( W0pCd>ƪ 8J~ \~~Rw+X s3 7gyH?lQpV-3*x 3@wW"X>fFwO;Oy c5x fz3 Rlz\+ng.z&"} x-n`Sߥ0V/}b7^Y@[6Dk:X@F. D^',12~}~O^AA}Q(JfL17e>GIA`Er<0۱+Nc2`k2 0/oycՂ>K0#fh7fǁNʇZ l(GXuW=+<~ vK`$Ga'Ћ$3^Pn!~~u&GpFZ$wJ?n~Wtk0c=L0>UMdp Ch']o|ћ"[ä:,\ l:txrno:$T=GcC;-L\v}DCo)M\-F%CL $L#ђCL*F`e qJNqDg%-zA5ʌ7+iQ_P + X*_ށ*1δ FFIZ19.ã{1Is>Tҏw_GGx_s%]QQ{f($Vrdغ"o:/D#&]pFhbt$]"->h8%^z(*ei1vG]I?RD)zXmن ԇytՍ7ZWҕ9}|x|/L$z<̔#gAAlsV.E2VTAX,"!%fDHIZHeyI.5엊h/ic,~(XYl!""b-8v߮7a3wf9s{`QX3PDt@nMH5b Ӂk@kΡ:v`5BB p"0\@xXkM|A Q@ Ei`eKA^<Lg:oMqr) R% '\kY_̬ G8㫝No/Ѕx!0`$p; YL p >[N 0 \\(bk=W@7BGleo|{0.+{} gS{o&3nVQ8X!kZJ o@|w[5^p+bˈ\R l"} 5ykˁȖ0X6( @z yD G:ERn&~/1Qo.M>kQx))w:=}-A,l<5q;0 8t v'^8AmH\kym$\%a20c@_SA6Ӭ¹jtkW(\<4ζ&>\y˺HOּw ѧ5OW|@tG}━9l4 9{$aKU pG[X]5osJ0$z9)c.:>'F_Qny5BEk"pQx1+Ѓx-= t:|TPM5q|5(`3$F? GKhS:kPzz |(k}JE-YODa+~:< 7<,~I^cZ3~;侯(dTϯ%2 Z1eh 'Mz}V"=_jOJi)ײYZ7@ \J-% Y/'3*+</oGJ_ra~g)3(B4R}]luD II9 +B߾י|f+ao[ɚ* W{ʯ% Qxb253;U! #,$}5r;sc)q4cw (L\F*8^6DnA7tXTCj9fp)޷Esc5IiK}d 97G.}ǵŎBqD2MD\?6[z#{=XHt ܵ u񭉷" 3{{o]:5!\N2rzXӯJg"aHD1}q| .F4Dp+ ϟXOBuomt00vIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/globe.png000066400000000000000000000046621502633300400216040ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+ dIDATx՛]E?l61iHU2i!VLrb!Q@GEl- 6M -*ZJ-8A mh*:iƔ6ul6/1^=s}oVM6̏;̙3gΜ9ml ,ؒg{^/;9U.6/)6lV;^a>f7]hhc+z XgjOU@#TC[ 2Qcr(cL,Cv<#e`p>0LígjsS2G,mj}@gYxHuy[[Jobo[ѯiWkՆ-uzp Y+GRq6FcVH{:ghw&^u~fgO#8ⶹմoMl35^Z3@E[':ӫ2[*6x| dbRhcO|`Up#bgvǀIUx5ԁB6v'`=[_}ߗ; 7i뵱#+xHaq׫ ÙwFGQnn9XN:C.>'؂+hknAQ>?E,Ї"G8x H1xU5Xw4A`Km )N-ɉO m t $NQ ;l=U3@_ \}$0 mUG|ɏFNܹy^p-:5T+u_sm:E!Rjwu :l%)?Vڟ+t^RdC|}@Zm53`!EoQj*_,fLx8A?liZ1S7;J7pSx8"7&Dig$Vf ߾ C,Gˎ!Ur9@q 6vg,{gXEf 4+MlO;J'$/Λ5:4S|7 pĥ{-^CCHbd6?LvDkZz!b[kLmʽx+6v0'°k{ @pDa!RʯZyal@ezx7Kڂ!2h #Dg :(aAɐO6N6h?k_"SeN>?-BHKy"]}5Q)^ }`ڼM;8%HǟEHFq&l=hc+LN;9slzL%m YZv_(* R>I ؃pRfhG -Z/x'Azg4GrvDC^~!ݡMh}u:EKPoDN\`QE+FYc\}-7hcgSweqw1{Aru ( =r:bW ij?-2{ џ~ ~}S @N@j\PTqm"(pQ:o?-่yS}Ns Q~oT,5Lt׹]w@)9 NdEe5۳Tv#hxAvtT-PVXgꉠ|\HM |~SN1Ɍ6v\f7ow f-24pﻝ~353tw݋C pO^:VU8ΤM58T7!cѫ Fg, V'ƴRNlN#gs>\H[7 8ob` f2)ݭ0q?Qt]LYgνYa&R9$1IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/graph.png000066400000000000000000000032641502633300400216120ustar00rootroot00000000000000PNG  IHDR@@iq{IDATxTU? &f%EMDD"Bbʂ| {~ieIQXHDfF${iM4MBrĖ-deY㼩73us= q9#6À灅(4:s@Sk`j&dEJ)n/03n@ 4WΊ@; :c_?aQ;xke ,vƗ:Ev÷"NE"CH;\G]g!S]+Uyvr{ !4Y.")e JغuTWkl)s<Q. Gg ? ?<:jwE,R:DmEuTǣ1Bp+J{ː#*"K2%40?"~D^'qx *+]ʨB #}@ )-gdVǷ/'Q* mD`p u ,)i]L\ B "= uԶ>} ?\GH!}bmWC .6vI+dcTEkId \Gm:HynH[c#RvukcTh.«IIw"|6)VsI U.!m1k312(T:[j5Ihf:U:cG@Ñ"jK6 j̵`\iUa8S>Ȇ…HA2^l{|: LѴ!4,x(6KOic(^!^:js!"y#5#M39sHwGjmhDma/Nʳ*8p߯|@=Rx!wxPvY,Ŧ?=dNOπE^bO0o;_§ߑ*V5E%:F*#]<uB :5΄#Qz8Sdx )ZCK?A,xw>iLNr G,~KX+rWI:2"Ev@n#d nzDCZĕH*Үծ^(E0x!:KwsJNN\Gf#;0)|#OozE0Й $a*Yyv@+Zum q_/{_IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/grid.png000066400000000000000000000016361502633300400214370ustar00rootroot00000000000000PNG  IHDR@@iqeIDATx훻kQY%be TRDi|4ZLe # ( 66*L#H E "1EB"(KX,v7Lܛ9$9o=sۂ(.w T@G Vmz-%V[]riwJX:Nk,m7ٮYOa PSgѺͶˏcu`:Dut5j\2'ƨuL!y3 5Jrț0Q-`J g\jU(bmr, gQ<W#&6R(  W'4X (w3Ոm +iaܳ<ޢY5bfB۝"c#*+p }oT( m( `]Onf~nj[ീ{j0gWБ{(h0@[6\}wyFlx$wpĈ#ܫ,Læ3R,S x.,c)P-@Q-@7U 1Nc!Aod^#_n? `b6T%rط%]"*ZpTIg^ܧ_?C#qgaؐ 'A9lx [B-OW.8#u_6r5*E# Wpum9LrGA'ֽMpr`=ԼܢL1sȎUHZB )-8<ڗȳ"!92pǕŬ4F ]gWIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/home.png000066400000000000000000000022731502633300400214400ustar00rootroot00000000000000PNG  IHDR@@iqIDATx_UE?^%dEVyX%A%i:ACi!AAH YXZ8EdGt32!" eEfv[93se7}=w̹H2 N{"Ǯ.GjYTt`Q}7ʆ߀~nizUK\="]av3>&3ة]ZDS P㊯q&gߖ\DW[ Pqg6~ yFEZ*7@W|nd9΄{Tj2v Ù0Pe)4)*1@{7p NUvBeX? ܙ8ٲJ!\1j).ZߖG7p{)e(8zRM5σe鉥o;|z6Z6@8B~ QK16ضВ<ؔWtTNa"rlR\cRkPx1" -Ŏ"RL۔C ̢}-~&>Ǿ]^[SDo(ck~`{DfRD?D?lFKzLfQ^=l1!h2 xR!0'~@7ebC`CbZq}x 4 \2@\(c%np sw_k'G*AqKoqKƎY(cK8g[ p3@z-řW,qtsrA{/n $:}3m2Z+C{M)~E5#?=#V0kOTNk+SPKk^Ok+u`o wʺPYUƂap8v*2״p3{*>jb_qxXRR_gej)V+p5.5 !8v-.hJǀR1 t H- 5R HMǀR1 t H- 5R HMǀR1 @]_JZ'Ȝ5F/P |a2d|8 gu &ǽWfc^D~-EO<nIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/increase-font.png000066400000000000000000000023131502633300400232400ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+}IDATxME?a]BXĠMò,B "QZ^: QكxJyP? !B"K\r K x:{  3tWWzzzzzzzzzܖ{ XZ^WFͺ NSvkntchJ9)x1V^rnT:nv&ښ$vF]7w u /4o:pimt6Zk-"h2`N zE tii<Y^5/9TXKW pW\ ڎok 2\+g2Fkwٶ;,8>U&nQp= ķcUjIy3Uk"~++iWd=$Q`Y0Hu{v^2VΉynN [X2 hw$[+'eKc7*6F yp;BuV[6~y\ }[2*?_ZMDSFbkTC[wܵ:p*x( @ńBUA{uȀU8[rO2l5|ddQ_%iq#ںd"Qd{ҷⳂ6&;{t:ecvbNV.ں_X~x ?㗗RБUn2PP]'ݔOثUn.-? :6F埧(j~">5*eEC ,uDZ\"H.8E〰9Mm!u[+R+{[\HrޯUvjnp~Y"PYmg xlf<AV,$8NZ$KUL[uP.c$u& FEkm e%)˨>WgM_IFd.ZHcxQ'h%IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/info.png000066400000000000000000000036031502633300400214410ustar00rootroot00000000000000PNG  IHDR@@iqJIDATxU?lC6dRm?BĴb1B*m]1T0H-jS믠1 AT *AR %db*!IC(yݷwl=sy3s|it. \|88p?noͱNwZ' Uޚ}XRB ,*S7P <l/Ci)p!Z^`zr uD[p!^<lGO yk^)\k;,oŖB<\ǀ=~k|'w+8,քV^j. 7n xw~i@/C"QP֬i_~Nadmx[SGFӀ#_tYܖ\p!.|ٝGop!D[r`Y3'4u GȜ3oͦf@:"6<KuBJ76"xk\܏L9 +YB4docA|(\!?J pF†HJo5sOg<2ykNJUtAVBօ qbw}ޚ~`pTi ~#[j`Xޒb9 0@L+$0*wxk`"ߤ/[s 7….`h\mFUvgqieL*@?!S^. 5Yd徼<>g_xSυt+B93ޚ4jB\K>J_&Yd9 MXzY[F)s0'wȘSo*%"<߅8C4f(?I]4y Q\ГoaQ%G@;4hóa|,`%Hr^T^ҋxx/'@kݬro6V9?[1bx5T:d(t? Q:R7{k׻aH)/NJ9|w \FF4:b/6ɪt7Pr Q[]a'&.b\6BߡfWEzWVzk~߲@s&GKkaȢMCϥ+:`)Li ޚg 2.9,th+B9R. yF%}enn5ۀ>8>t! KWHlAvo ,lvW[SdKVY>G|1r͜.K t%o@*Hʡ2a罾ڋL ) kR`~`M^)Am#BE"oH}O*Ko |pXEBv?gtMm~-YN""µ mޚ]Hvtm-(t6]f#P)j@n^UH))Gou^xo9#EMHP$důrN A$t)0ꑊ'IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/left.png000066400000000000000000000010271502633300400214360ustar00rootroot00000000000000PNG  IHDR@@iqIDATxڿ@7X,CRO#8)$XqXEPř[eH2,N~X>' R#[NRx/[nr]?|C~@--O]rL`) hy^rg||) N7Xf@+۬/U}OQ]5/V<IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/left2.png000066400000000000000000000017301502633300400215210ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxk@?(DDDdXDDgQK)x<'Qh)ERRRJmf2%/i3/~efycu9"K̞d1`*gIQHkiӕ8GJs>/SYbC%4/nb{yeAsEyX/*VɺPӼ/߆Q2U,>Z0` `"K̏ Z l+fOK O<:Un@=/m~@TA,1>yh@!i^\Ú?'ukj4`~>44/Ʊ N^ ͋#`yҼNwQ2BP_.HQ"9 U4/.c{^ürT"=:p !,b_B/Y쓟w Ox&8_$w0IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/left_interconnect.png000066400000000000000000000213661502633300400242210ustar00rootroot00000000000000PNG  IHDR@@iq zTXtRaw profile type exifxڵZYv㰮*N 񜻃[ %cb'%k AP(M;?x< ) ^>l vٯ>^87r)ן2셫R;NZdӏ1,s%Ա\I<{z<|ZgN\N\";8䙟̕Ut8~q[gqϝOW3vxLls9ꊏpi<u u[[/N6f*ލ3[x|΅'m` 6J%'6 !N^ ]ӫOp }0`|ٺOݜYIa*h.92ci[\}ϹG\{Q\҆Y&ug,@hs誋sfGf@i)ΡdvԐIS8Ԝ7 [Rt&GtՁ1N 9Zg`5yڑr+FѼŝ.J} 8(y. 鑑j sgH37ȐYuGn^{aH4)'#8L^^ʺINQ*n=bR/#(~fG+,D-l}ϔpQ(QY[P]P$_Pli.Tmb.!ywK'vh>@=}eThY{;5ci٦ҞiTX:@c ut|WB)= @mP"Ӣ*R=a6\a9d5Ю;"N(!M|P]erUqy+VO#Lʊ¤>{AO3SJ}^L^8by`uY$͆<"dD9.*oDI8ȍ1GTdD`/ *5(]Π }![i{ m_!;%Uҽ*$ A'#&ށ0(TdWyY`PWp]H  +~.WRRJ f{ T7A*'#6c.22וbCS \䡴02ԡ*0A "<f%Sn _Lj?U fGPo ^x*>hӪunTDRw_|%qG:_Ȣ.%~ '+8!l<GQEe6d &x)-@/<·M/XcR'p׹-? -ZPS@@Xmy9$}lHsC˜%fyj,AVoZ4"9*_n]p=22: ;{nf M"`=ٱ-qZFIp THWsO?_$'A_:-`gsy~goWD1LC'I?JCFћ:JeԷ-??wu~ڻu oPug#jj>~֐YH/:D_<׀+ 2ڀ+ 2CߕQ"89_oo@~G@OՌ[ST~$Zܘ>}}xgQ+yH\ޓEOD>0(z= AՓˣ'm-*N11Zw++I/ExI]M=M{Mڼ݂4!E=W"_(Q!BQ"[z<~Տ8xen΃AoN[arM_?O=ۻqiCCPICC profilex}=H@_S"+8dNDEIX Ъɥ_Ф!Iqq\ ~,V\uup77'E)IExwqe〪YF23U1.`3xj1 u_"<ܟWə sL7, MKObEI!>'3ď\]~\pX!#'6ۘ x8 [r5_i+)F K#2( Z5RL$i?r r*c?ONI(b#@`hlض'ZJ$G@6pq=r|%Cr$?M!蛲@-гoC`@n3~wr*iTXtXML:com.adobe.xmp TbKGD pHYs+tIME" 6mIDATxoE?ެnTfKpHq? ^="qb%$ DHHAUPP)]!4Mqv8-&Nn]$cvvwΛ73D "Y26&ך-ND 灇)"]lLAt \KxIQPP:Jr Ж_En8ץk*@8<_MeK֖_>]'~‹)G )o E(VfUؔ2u*`w 73%z8(_P[ 2pxz-uBpKeP^T[2W^.eeۀ*g*1`Gy^*k)dUR-TnCH&jJ )S+L$"綄?7$i oS+8 )+R!+U?R>H2m`uUIBz1!tQxlj#!ԯu Xns-6a m)ǿ?l\ :4 Qⓓ`u[|[\uXf ̋E*9-r((=:sA{T} +4Կ*8h[*:]-`f"Sk@MyqCTIeJ^ڽi.5ȓ۠l]vXyaı@wV/-9Tqch-mg`[D2suҿ@h* BnWdN`3K?1Y@<ّ`?W$[؛: 6`V?|}/l`o+3 ,В`-2&1yAXЯ"8 Ve`IO`yqDZȮ(G%iгަ31G؞Kc#x}@0XN-^]RdO]h^&;gke2$ 2rzA/LҎ), cTJ tk{0嘿ED ?%D6 @q&1 l*;W"j,C6Mg-1Q=k~` f>"'LNW/+tr 8a5I<+BGI!~ xw.N]`VG qjkkn4 *U֓ eg79u X#stWT^e12NbL_`Z-wz$Uw ؒh u)AgPwS:͔MKgQ: dfJHvQlI, pڐ P(?GgP0X¦r%ЈV7QIxKbl+:ȇIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/line_interconnect.png000066400000000000000000000165711502633300400242200ustar00rootroot00000000000000PNG  IHDR@@iqzTXtRaw profile type exifxڭYu0*Y/l; %}cr+e`H+|q)7||\m}<~ݧ-ҭ)`WᦣAG顣} Y\wz`ʚs)Ա~$/w^gx: p5 .<[TD%\[qOۍUye^upޙ,7ifdΑw?+5#\ISWXr7Eo5#Hmom8b1c4^rlmpz K^qAMkЙP =# yct vY B#tq<~WtsVW5=4ڡb@fE; &ec| :Jy[ vXiApձцͬk]DЀL#!~'P .B RȡD} 1F ;82s%SH1qJr*fr̜Sι ZsA T[]5Xki[hqKr+vב'zSϽ 3JÏ0FEjK(,I5C /úHiE>QCS $(f@zY@@[lK{K be V +Ӎ"069nprrн@+nOP6ms4RS7HŦvQEk-䋐 D;Ej4z]P,-]fS\2*~XKL>ot0t|u :.NrtU8^aָw6-hlZq6uh9&}H:|8bk۠Rcۻ ]4e]]IW+eYmX#:elN3 5Դ~hđLl5u+[<'85]>ؿ NaCI'j^@Fi\-&Cxdo)C7Y/oHlq@Vxe]඀a([Ѯ%Héڊ};THF_Ψ)GTž[! =0{ŖS _ 0`2wKaV+7-v&.d4\⋃wON5YHHȅx)/\1IcM0X\eg J!K3T+(A0+8 ɺVOw6`,דL9@`E;=: z(;/TegB"1*!P᭴l6]=P =r2`(ROJw HI=4Mnb дVL!h˜ >F AlDoX>JSRҏArs8zJž*V.H)x]$|E3zNn6Sjf^jeK^}(_/Kz#_iBwu|.uM UjBW:[z|T/P^|}D2O֕_t}#5[ٶR_"aO~ aOK{k1=7ѵ]ۍߌѯ|[ÏK(4bDa"` ,^:}'3ď\]~\pX!#'6ۘ x8 [r5_i+)F K#2( Z5RL$i?r r*c?ONI(b#@`hlض'ZJ$G@6pq=r|%Cr$?M!蛲@-гoC`@n3~wr*iTXtXML:com.adobe.xmp FbKGD pHYs+tIME8}5߽1IDATxkP̴T"ntaݚ*$  r]2Rܸхq!T+б9QLN27gf { sp` ,H5ϱggCJ@Q`sJA2F.qC4mXr'&<\VLnpReW5'VXJuրoHe6, M@\Tk>^\?8\n&qRN*x c:pKϱ?Rg89r\BA1T#: !x#\ J pe=s>5 Tq@m+҄7^ xc HZ6'Z\.e5F F) #; <.NoE34LHe 2p>h0>UL|ȃS o-m -)ic $7~]Htv@e @|ShK T<Ǯ4 [ 7.)Fx|3ppmp'#(X- wQ#p݄WN8`Ggjj'=R pZ |䀒g "Z6ɛIЯM^ƒq1P`F@IF(=*nj,$X$oonww!H 3 mpM`(**[&q4:ͯ3.0g|WA[ 86 %E70 < '<Xg;+w#eL pG_ % _xi|V8_h릁1/S@[7_IU@"H$S=[Euni~8yd_8[ SWiX=}|R\kQrVM|n%Esl0%wy^lD"HDVyu&d|]T@[îѹΈmQr5B%7>zOxp)G?3 yQSY~ ֿ FUD@cNxQo|&%_4l ';rW(uD"H$ vp?nw*T~I 0DgںB wLFaG9)md(31(36MPfbvzhmVX;'e[*|\lD".JKS9IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/list2.png000066400000000000000000000045061502633300400215460ustar00rootroot00000000000000PNG  IHDRx IDATxOuôHĞ=G;3hA{]:H`"ba f~* ߷LJE8Iw??PKPH@!PH@!PH@!PH@!PH@!PH@!X ]j CWx `VB ($B ($BS<wfkB ($B ($ ]g@!/@!PH@!PH@8CY'OVmfrk`dCy~r`NOPH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!Ph| `VS4tKã+8۽f`N7b `N7PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!PH@!Ph} `VS|?t= Iv\>S-Or&I.laIV1$=d<8==qѕ$ey1լPxq/H v,lksZz˼BUGGQxXeg{$?<묟du>/~0eO^,c`[=_ IngYy»xKwf6+YMpWgWl?PH@!8t0+r PH@!PH@!PH@!PH@!PH@!PH@)n]j CWPH@!PH@!3t0)VCWr PH@!PH@!௡+YMp `V>  ($B ($B bYLIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/load_embed.png000066400000000000000000000020651502633300400225620ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx͋G-eJ10@B R$$EV;_{>)pxW"FIG(ۨۂjsΛ/IrN/( q;`68뭙+ӆ^,p[yY p!Nz?Lyk~l>&ZJOzkG,qp[DzK p!n# f5b.č)>p!ެ< kvxA)(SW;5(Ĕ-`/+?+PpP!ҀZMS Iƀ lRޚ?ڊZfVD?Y*ԟb_/SbfS#Uyʦ+Go`n B%44pMW)o^ Sޚ*1(iޞkaԀjRs'zA[y4I Po8譑Y ~ȝ%ZA$_,ޚQGM4{\;FWGq![ޚKƪ6J/ Ā232t  榚k7D * Z@igd4#`H.ĝ$fLfE^oͯmc]D\ׁo]2]3%$#~p!>* z=IR6g7;]N2g].KjDjwq3at!NI1l]oLcdZZ…T5umªRd MPV!u^s9ЎM8[>wfށtcJeJ"P$801|0F8kG~U&硩qRXs_iJrS"k!d[7dzW ~W|Cp z2i^y(knH7HoU1*/;DXz7%rs?ʩ.IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/locked.png000066400000000000000000000020121502633300400217400ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxAOA?6Iʴ!.AJZ9(1FB*7F=IN:ڶ)lDIogޛվOmm~yfPJz%6^#L:ZPurpXm\ͤ6I3pVՌ2W1c@&) 91`{̙0懩nXa+ ф@_Dِ6W\v=nOLؿ=42)>_B,p~\̤6#6hp8M9vVogҦ4eR<ܦ؄Lᄉ#w@Ń,@cV#@76s%_4. 5 HiPiM9$f>%DdRl,쳐hyQDHPRƀf2)&#Fi1g@c@R4LiٗHbff |Uڌ*mv6S]xjcb\fn~_e0QJHaF) ȤwwO߷X&WLq@3i4GHǀO"p]{WUqwe G|fNTlNW^W^O?Ǚ[|[.9~{ϧ.[BlbI^9Iq#u=?'ˏo&$'|:dZ0бby)ɳ8/'' N˹8jo=K$IK'С.W%ye{zMv5Nێ@GfYmߐY?wfII:NÚ%wcs-_$y`>JS)[_ lV5L6${N,vp÷v>| S2[,J@iy#I9N>z*)-OMr׷c$1Nz f公>n p;8,볺ӻZ2v` Zw O ܿjܓw`˜I+I>[,ϵf*x'$z>$h= b9i= ͻ;3X/4` d~s ZvŮM9Iz$j=<-[o -zU͛&yyn{{ 0I^Ľ6jEƸ`H/OC،geClo RvO0'ya!@ܳz{ 0 I~k}UNF~503I^Չל874ݝ[lNαrP$  (H@A;`I䇭y%9zlVL-~^;0Nד<䳭yv={vrs&6­^3Y݄ӓ3] 6lLo+260tl=l|~7Nj[u$  (H@A P$  (H@A P$Fg[b`~o $  (H@A P$  (H@A Pz-g0]g['|:9l= Iޖe[I$p&$[Bε9P$  (H@AmtN$  (H=nYȀN@A P#& 葫``u B$Y7,d@eY;(_zd=&Y7,d@ ڲ,dPzdsN.` (H=nYȀ9&Y7,d@ (H@A P$  GM00 #w GM00 #{``;4+yF-%di=z(A!`n>%T9*s$  (H@A P/-Dz/X P$k f{B6*`h=P$ 0^^[e#1^X P$  (H@A P$  (H@A;by!ɛ<,tI>=NZc%h\_HroA֕$m=C@``2G@``2G$ Ⱥ f!z$ Ⱥ f!z$@$F;vmtNlN7 P$Y7,dPzw$  (H@Au Be00 (H@Au B (H@A$ Ⱥ f!z$Y7,dPz$@#& @Pzd=rzJ:Lr-փЭ0$o~~{Iz&I$~#[`\\m=r-{c e/A!Kz'$[A\Hrg!$?z'%`|9[,i=}s1[g93I^乭_`NrG׽I^?[, L$yf`Hr_3ɟW '`lG2I$3[,z<-|rXjXz p,.|Aco$Krc>N];9tr S7N춞2@A P$  (H@A P$  (H@A P$F{vmzm'  (H@A P/-Dz/ (H@A PNgX$yf;ZBMtjKIOփЭ'yWփX ZIrtI P$ Ⱥ f!z@00 GM00 $  (H=r L@Au B Gv[#&nj =00Ⱥ f!zd L@Au B!#& C00Ⱥ f!zd Lזmf!/f~~a` @``2(H=r L@A P$Y7,d@\eY;(% Xzd` Gq;vu B G#& =00 (ht=&YnkA N|:ٝ-=P`> H|:o=@eށ@A P$  (H@A P$  (H@Amzm'Fv P$ 0^^[e#1^_ P$  (H@A PN`Xd{~ϤY[~Zob~&_6q6kfsZ8Pf5oO{vo[vg_:\|](0Ngܻ~O] pJ$  (H@A 'wzZ}\KOv>r! $_k=Ķ'$_m=@ד|"x8tr%Dz`XIt$_o=$y`>d ̧$Lz{(ɗZ1`sՉ)l$KhABl|:y4\i= =Ӊ7DlփI#OɵփؠMHQ _'փؼ&'o= ǽ<axO~b}:0 Uì~Gg`8_|WōGn>*{N|:y$o&TVZ&y{??}42[,L$BqN7ܗnӆhhXO$J$;m'ܵ$;Y$w4`(_O$O'{NtbX^H򂬪yqXG|>|5}-L%sk;ìn$߰r%ymV{.du&9n~fu O&|:r0nMl/.?$<.&9q zV_]ye2$VoO-;Y ~\X?KI~zϗ=wή9  `|Pݬ6YpӟIג?]|55'lh^ IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/minus.png000066400000000000000000000002741502633300400216420ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+nIDATx1qB DVJ,b#LTPP+68?ێ:$>=]\ j5ꀚu@̀:f@P;n!W|XQž,IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/number.png000066400000000000000000000021621502633300400217750ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+$IDATxMG K """R & A JŏPDs9yc.Bz1H>(xP"F$ BfY$"2,ࡺޞ׳kvgv~NUT~oit5X ,(;Y34̈́+;FGݾh"NR 6<~.$]v+V/SȆhOƀmFgyIx`O^_F! NlNh׀+dVV 74EZBYӢsҐhӟH t~B .u@NV;?BH9@}2^d|.4i7lwPN:Ϧi.ݖ]GRfܻSv*@cyiZqosR%\y(]ϷLM8p9ާ3V=lOV?`_Zj&Vㅲ5 `kԆty/@mڀ m@h6 4] !J3SG0/ͨ 5٦3ɩF.u^Se\ s,MѪ8A|Dp5fHAWH?jK_f*)!v>powxԱ1!X"5#lD ԧyH8 NBխSXa S`we4p!NEmtFjeN .gA%Na8M*35Z.m8bX9:RQo1j17CgOZ,KyVW9D=,%0;01Zf?2Gr'f2{ NҥXw+K& UB{oIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/number_on.png000066400000000000000000000021611502633300400224700ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+#IDATxMG K"""AD$D?&"@ AO9䐣DP%%D$$A d"Aa]ݭA;UӯS!f N`#!0 DȚ埩\ѥn6[x3J?ECUq[djx~N׍req|\+?G/ȆO*dk~ N#`e|jL8M".K8 nSYY(gHyFLw ^Fc`QWȝ|m~.Uk"`o{F!-#yWҿ:׿,TD'B%&AӦX$T%cB٢{(tkK> 74EZBYӢsҐhӟH L~B .u@NV?Bo0'3D/τ&m:ڗM)Y`; ͥ۲+>:Hj,{wNpO:-]+m./U̗|飠 Nv9pQz xY`Q8E-7QzPVsBqmڡ6B ^0 B @f @~!ZZ PyWqu@5t39#xӥktJVkaG\ <7Jwg.?`k̒vo~Ԗ$@T 96&R4L;B|mgccBL(kF$2_86&R"e8MG#ob p1NwY:$p+2Jˌ&N%mtF&P+s(zwt)0=Ԗ8MN 68(6YbyWKiJFŴު6wL<2>}f] d!d) `yQ6S,9; F;q8Mc=nl],S66keU( IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/numeric.png000066400000000000000000000025231502633300400221500ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx_hUǸ EJ"Ao(!"* ⓠGAE""R("2Q!րj^$H)%];svNf&s9{ϝͅFam(120{;g/"O;Ҷ)>38V%<ٞl"귄:Ʒ|)ɤMu{R3zb`EH\:q,EuNm {ES`x}.O88}$0\\i ,ap2Jp?vLcQb78 ;6D@*ՉN)8>k 8 ^ưFXR%AtM;Ana}̠|m(1v *GtU iƚvW ȡHk x} 髛9l"*3!pgD*V08 %1Aup%pmU?5NNnxhhjl4j {*G8lT>elԱIz +c#"z&Tܿ:2F0m*kC=YGa1Qb6B,"9#/RGI:#v7Q c;Sot| vV.氃&+Hxu tL>8TI={;_I97Tw-i[$Y?(v}&n_w>r:{G',pT*D$KxMa,s;C~Bž^迕^3?MG0JG~{qj%f VOC]~E9S!RMJ jCԎhuZgPAmi^U9C9 @TAT}$XE*1atPݠ{ 16.Nt{9ľ<>'7[vѡe_VVtm$h.4xthaMiCjnA6+}d#)1WWȈŗ]iߧ+tfn-8|̓V҇%W|(c_M0885<' 2v^I-bF`9Z?,pf+Ae"*UelS]61'PYgH9ZMbkp!Kr!3TYeh)Uh;4*kݎc}Nge<4ME\\{%&i㝪 sJkn012vtցkZK -ŽilU8 w^d | &|#Yq3ށ'b# (c_ab#-'Rye. ǭ u pCc@z]REm#Z6EO}[ ]mgtZ;Pg'U@\cʯK(c_-{Ÿ*7ZŸ8O8@1_>Jf[`aJ|b"C]~RT`.p}j ~CF|sqƕJ X@\orYЦZ!._:}yCTyF໶D}2N8d["HŽmEկOzH.V52M[Ǵ%-ŭ_pGLր SFb.Y;G@ٮG>n**PQڶ{ykrxJ@K E">^)nWKUC-8 a"MbMsth8 ,]IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/paint.png000066400000000000000000000036631502633300400216270ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+eIDATxm]%HYBK$(J*h|Q[1-EcBZT ~ J_Nژ*D&DSb#ڦ!j%%ᙳ=weϞy{33g&Ƥ&*S0 XEǛh * ""*zJu%2٢XA.SU} 'Vp uUBWVsOwAp~onOhc;9GgaҜ6<jD@;>K M7&{ńA^e oA|k=i7:\Q=@<{ >-́v7E+XEަ׃l˓gaA>Vѐ˿hicXJ.Ӏ6n[ ,#6fa6y,|=Wh4aD C8s\>XEk2`=27t]]f'^mNUd7+3V~aܯUZmB~<omUt% tSHeDx$8 `qNB;6GN)hdcJt+|B"^d'7\wl?D&.@=Ž&"ΉUt0}s6vwtUhcF]y}"MO-d+on'Vz4`tA%Es2^$mN:c*Z]q[Jy= |!,vMm_fZpw"KmB{˛<*5n'5%+n5OD.bt]AI埍,V1aH<@;؍/qT3e/&|UtXB`QW,>pS+!riˑVc&B1ߕ|7-sA"/?E|7lׇҽXErDDXE0F"4H> he:6v7B^],Èm'Um+Rfi8y1C ! B6D%* Ej- pM-Uȉ/R[+\n)}uؐo9.By$4` mZIF>t / %&P+~4#GF IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/plus.png000066400000000000000000000005431502633300400214710ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx1@x Bat$^q:ϡ B**|dw2L4pt[8^ugN^Rb6]4@ 8-@4@ 8-@4@ $ # g/^s}>Zaio?@ 8-@4@ 8-@Ku8 \\tI}ǖ>s?@ 8-@4@ 8-@4@ 8-@|_=>JW̆fM|$IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/range.png000066400000000000000000000026441502633300400216060ustar00rootroot00000000000000PNG  IHDR@@iqkIDATx{UE?^.D "mDYDQS!DDVADSEEeXړ2EldEYB?~yws<93ޙcJc2` p8 tGcVgҌ]yuO&^n#HƯ,ƺ6`#pO"V}*In$O#X wٹ* ƺ}x!Xw90@zšXW.C~o(k`+\ t󁶢W s]2As(=#`<2 X)i0y'e 멂 <jICw?rIAn Q2x0]Ǚ/*NN{ QYu#g~Zr*{x

$SkTjx3@2APu3p8oT usok/+2ăq;u?;H-Ou#~z@>_.J#X׉t?iu<4z MF2ڬ':iu*"'<ƺ:R ܛRDZ  EA`M[1nU.$X7X|SxqK@-jmH~cr{{oV_'ٌxs#`kZo)Lct`;yX7睗.``ԣnʄB `[,1ML75Cx7⻓eplp ƺWHeVh sԣ6`F }UH$20L^55֭bwGZ-#ݗޤu~bN3 uXU˸;ԁIYIv;uK#Fx*8 k^I"!nmPv1'.3]B("E*)J"&Pċ?SP*HK=yA"TV D`uEQA 2H !H)%aKw76~o޾e7f~ 8OI퓘 #60 LA q1j m@id(8 Pz`'\g+9/ZlqtS,pL"D88 Poqe2cU@D'ckvS$BaވUIv\3 .#|ѱYnrN?ʱǜe`j2+. Gz8 .UGO0d0.О¦!G4!wonצap~x$WρπE?*FHH2~&gC2бZD/fWK{>NZ. Y?l'%&]NX)1F FzW⅄5iGBX,1²[gKLjgaqG|jz[hUphpm *rP VI3NޱZ-jEd}utq!NV"R IڸQ`ulg t.`ж/ K`I=~m< OI\I9v$<:0"R jP*l$m4FVEhF2gb9R_ ,s8 {p8_Z jX8|#)<"07.9jHHX0[ګ 琟 n35+;l<agn _]Y$4GW {M ޽'uY}iE8Fs OX8Lă6yȓƐ[ձZ-VN -k!B͠lY׳ZJU~F*l"GV7kFZ{ZДA?}O@qtX)|U })4.@c^@QG#5bIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/right.png000066400000000000000000000010671502633300400216250ustar00rootroot00000000000000PNG  IHDR@@iqIDATx훻J@?-,E,`YDD`F,EH!b+aYSHvfr|3B&d2_TM;v+W`N-p+o _c^5#p8򝷺,n$_yH8\GWv='(O{!kZ`'o`QnZ5\ ?7}<YЉ.%۵X( U<xh@a)CRN=p!{z@jAÀŃ5N*b9/(uYH@g95ˢ/g;G{*<($L0Z W K"7a~@ 0yG(r] ORm@Hj00FcP]ip5#J\+g&6rن &le 1 C7ńMpv3#T^M ф ||$fŽU<a cE#>F"rtc8w>`#갆w*A9 G'w8&ںUDdp*z?J} lnz4(#~: XrL.߄COÞЎ: pZd6p.zN]C#t#b±S`@8L}(ڡvu'+A &SC:ս n" "5 |=$n ߪԑ I&CQ $j1 "ȋDB,ZR?:E>탑^>=8k-Rɧ}AB[7'?,8_+sI*-zdvCi7:avyMk )J_v$_үr⇿ z1;6|[gN 0-.Ew{$c1040}npn[k+cщM׏V\rEYQ{qQ*~祡1l+epCo\@8x3Gqu@g#&L6;Gnp!crH Dq@` Ʊ fk1 C:o 0̶K!'ZZ04 @0HMrXy#>C{f,9q.! *~Yxa "%I.1Db9 BSJ9c wg\s_"%Tr}\CmA'ZhbK-wA;ХǞzpaȈ#|AЂ7)vL =bmD2K><-}T-́IO欙HV?[?&>0:oyB[ !t.uۥ x<2Ct򈷱#@Щ5s:Ae]Ϳ } < Zyz^yM7GI[5<v) l[թRV}RW$ѝ|QhJ$z]?>+It_$ vB[y7=.}?EK[~v }.=֓i׮Uk EKB|e9SKLrFOLrc3-=z_ՄZG5y.?hAҨ_43-˙>hU:Ӳi.Lrc3->^_>_4*6tiq۷:cty)n_ ֋^3s:]?`\1 U,苨=~fO2`٩o9g\jhd*MNèfW>:Gzʧ;K'Qw.{N/JӯQwRJZT~7wq,.εٶ߽N2f:9Ì9׫xgC)-DJ;U9Q6.tv{h&ap zejaDA"+g}Pr-jF:}moEG,`X}C(StA_6G]w=6S=OͪCOrhf8uMݤYy.e1\I[siCCPICC profilex}=H@_S"+8dNDEIX Ъɥ_Ф!Iqq\ ~,V\uup77'E)IExwqe〪YF23U1.`3xj1 u_"<ܟWə sL7, MKObEI!>'3ď\]~\pX!#'6ۘ x8 [r5_i+)F K#2( Z5RL$i?r r*c?ONI(b#@`hlض'ZJ$G@6pq=r|%Cr$?M!蛲@-гoC`@n3~wr*iTXtXML:com.adobe.xmp |l1 bKGD pHYs+tIME$UhbGIDATxMEq f$9OxMC@'A0 ŋ<(6xP s1OԄlv:3=q~2ﭷޯY^n&jw"]V- G>DIe~z 42xx6A <.bkj;cا G[tw3rP\DmO.mߍ?ȼ?m t#3JA Y 2 >Bu+灏(5 F/**< `tݪKW,^eslCbuZy.:%Ee2YiW*I=(K{|{[Mk33EMie#G_?GMlhTlŸIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/save.png000066400000000000000000000016021502633300400214410ustar00rootroot00000000000000PNG  IHDR@@iqIIDATx1h@/RD:.qp`kAT:ġB {PGEqhtpq8éREk}8K_^$?]r/WÇ0v; -ln58Gc?c\ƿbV Μ8?x[m˰XܕSm/ժjqqA`5pkW:VY6E,Z,fTJ` < X`ժ;ֶ4HcXI9`9 4`=afV¢` #-*F6ju.FP0wJ`\t'7ZzP|`0pnZyS92Jj$.ju H{8 ;VeUtq~1fe]X֦ 88?8êLZ]h,̊:}ɯFW 틄1f8k`?!O 0&LW Χ G.",S[sKqGόK ⅂6&?BctW7?CMJVק BJi<@2k,dGfb.!$qm26X%~٦p6RY&qW )/I5'clSN (8?8\bI>Us4dY*] 2'?H#e#$O,=,V;3ʟ#>,?Hm&Hexj|8?0s (.Ftq~aؔ{Lxe1 lq~-r9AXvV=lսv x(SMa+|/hH#Vvg^V؉|@K8L 2- *)N[&tB> wjuc En2fȘE~.`H#H#jPh8pB$Ňc 5ȟ.PƇ"MB/!nI!Xdtefum.eɇ q$hR$`E&8@rih$&`|# uep&bߝ”r@b2d09# 6^Za\5)H5p_mV]e_j뚜q~2p3m0k7nZ,b=AɣX2!fy{EUY~G6I :\c~`ALA akQHea^@*K6.IG#@%qkyvV$I12rC8L(%P46/Iϋ5*&Jh5KRE*d|^p&qOh8iOHt7>:E/Go&di~9zgJ%C 0p7 ͯ͝u4jxzs Iu\̸L_-b v/UbfiIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/search.png000066400000000000000000000030471502633300400217550ustar00rootroot00000000000000PNG  IHDR@@iqIDATxoE?.qU!"2\rTHdiҋ 04IQ*"E蔖c")CC3x ixp4v:^1O'ӧk[16LLw:f6R\7֦ڠ/~0 I>-py Ws P d&c[*@Ol,-y6JUyO*$@bmva"6BC(^"ٟ6*fDsЌx8M'ۀۙ%mJPRT CIM4K4n-b3REY%O@lnQzLMOaE45B{K /qp;H~{ײN0 %`m%@XO}}8_f))Nߖ=Ucu%ZB<' IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/settings.png000066400000000000000000000511771502633300400223570ustar00rootroot00000000000000PNG  IHDRx IDATx^W}U=UOJU4ʍVB("Pq<ǣ8bl0`5`1(a]^<xc 1c0q!EEin4ZK۫?{UTBs||H]{""udjශ4U8,i=R "I&] ?> <Ѩ#򫀯xx 8фǡUIX,8ÒdfV.> < . DD(eJ-Xз94tpxJ.p0$0pLY)i7o \c|xI_2 <辎++4 DD&>`/' c[ied}&#CXf`D(Y"7oޅod|2Cmlk#4&[*M"Iۣ;?IhC~\䷰zmGbuʦ,yE}[H|WI Xݡb+x 8i DDfp~kh~YpgUO$Y 3, /@P "rcbE}+:g x4Ibײ#@iWъH\5Vv&vTɻ+eICiśt~6`[|],_|SAgFz!\Xo`n,F-""$:MuYvH13~ =_\lrd'˂\QzCYqg(K`o4 c#,m6"3Pc$ >twʝ4otC"".{ 8d&f'~B3 DDfW @ ~o4\M 7Są jp* c: vG}ħՈO/ OA|N~""< dq@@|Ǹ49p DD9,=iڟ/(P@"" D@D@BNBq DDB8V)F<EZw@Dda*@Ddat DDv(cHGp,le52Jߣ DDd2`7<igP "2mlVDH!U垇#x{ ""Hp-Z9VAp? S "2?Xw4F (idyaV`H)p8nO<G:GApa$p;ƁOqTK|9pVɿ>j P "&;pjh @Djay8WH-iY*P "-st@0\/Nv&G${ݲ4Ɩ*rǁp_pv#=0c3hn/֖ 7`+ˁ/q4?O˿ Pi GkYg0 MmzN}Rj^^-&X;Mvˍ6sg3 HVK]MO`YOA`e &_d!] 稘[&z?P "Ms=>Ʋaق!,(&ǩ_ M^dK7?/.&xV "MKrlR9~ C,08=m&˱,4ҵ$Y^`Fu3 {ul(SLMbEq۠L6|4K-:hؿ/^p{qxSG D)Ioo83X@p #X005K\ؿ/`{pܶЖY2 v/X|;C|Ď= ܟ iZG/'Y~pvt9e#/"[5&"qg<8M<7/ԉHGcgKv.q4F<8:|xJ AEdrl2;߭Cwqt`:NwVk0<Ȃ,_nT~=U .}V BA@' \*Eqـz7[\>q߃&w,SN[ DdI, \= h8֝sU(k >܆ Pк)lտ+$=67(%s+[ h֗NWWkI7^"6,? ܀e6͒= *{Kha'/4ER@D:"_-jRR K<òI3kت"QIz؊eҝn;SIŚh8V8U4[.Hh>';^7goae8zWRSXY1q".My ;wPvSXaW'!Kv)&~)b؉wܝ)Of{ ~qt P,xxV3Q5"k'|5v.`U%cꢟvJ|'RZ!pB'D),߀m \K5`}Q5Ifح} EH f8 ?fG5w7URt{;)nL"@ @G,?{ngҺeUzJaGrQ@DipI/cX!;ǻ= |j8mmT#85:@DBzM?NHR Z@DBCO#qyP WeHutR#~@5*LDi9αZi(2"MkQ>m;FHg e:"XqeFu 2|h96@K[gQv0Draޤs-Q "~ :o 5j J={ig% D$4X @5 R ")@RЇLDBӇ(bP "2eF[(PgS?ZvڿT :U("*<,W9e) 4?z X6C,~[ ;C&"S+}6aU0mj*U q@iT=J\{#/NoL MUZ6b'M,v @˪!j2׀R1ہjԉx@D᪻RU. 6@[68]X7xdyo끷oxWz`3 hJ|p9~n>lOKK)ƭ~VbiwoΫx<*RX@@8@eD W̵=~}Tk/6&Y^I,V%R1v` !EDjtM pX,R#ILh%ED%Y[_\ ;9|x*r?>I+N8_ t+rZnQ\j[ahFu \eJ9hGm]E<_arJ6j+( " JJ, XeX6` r|U~6kX qts/+"q+܉ҽet*_a_T GD0=Y@Dk?="Dh @[{0BӔ:e.?(vZUG|2xz'q4dkX=#"*" -U; ? 8{ %t؍q \!U ҏ]T65QFi` f<vgĬH =EZJsWpЉziWX19Ow1i~`A,sQV*vS`hƱKpcG* /a"@i;7(>`MuiǰZKw?@vؽb#9\\\'}qUXWUS5<е ?7Baص)isG`A@73=cA0x]g5H+NUد.G{f: OBI 춰2G@aŀ;i7' TGs8qt,G)!Ki_;^$Y[_羮YǰмH;|EueڲRGI UF8ٟ B)9cߨJ88:e ^H ,jڿvYQ P/h kX&<2ϙ^ݟδ>#$˟~U'6.CuĽǶ,A>Ƽ }VP,_R)Xz} q/&~N\3GNAB2G6aY5LX|~HKNʺ*ɥ nu*Vpt6ᏺY'sO:֑$˟B _'ٸ,a*밠`#Xp]dj ^Zu/iUN4*8qX6d?4,S_ j -?y% K ^=#%t輤]zrY>{,Mx 3|D+ ]jc),_t@r1؅( ꣼ԕxQ I\]1s_y;hPG : Xci=G;EG Iej*ؾSހ:+V_ Z(2]Y+52cA0EIir' 8:Ǝ+.JJm+ 5e`[ m e,pERR?(֔yr~vLtˆF-8=_H+|0AH8\g'{{k;ATVj~Cw̴X:m<Oa8&cNԥ4({+e6Z&:|KIŊn^-i x N}y*U sJvBUTXf{cKi[e YUHt@2 ,q!Mff{m@R\{ Ҕq`G|$$ x/_ IDATYeh&l/>\8fH{,6ˬBi udVICwFȒ**t@viXn U8hH(_ [g8 }T}JsAKհX2iNzVk,Wp,_d$˫ :ϝ y=TNTp^=%Y؁>R!=%xI.~Y叧qt:a^BK7aucM UB@sp+@ ܈$`lGr Mkwn$˷aNTH#~lIXUuV<J|vF4j a*wtpn=\| dU!>'|f`cnխ~Ӓ,M|;0ߎezxV-NJ]7Q0-wlLU<PV:+ $Y |_Q `~s&v@Mخpi36|0MaT@Լ!P, KJ@մXL_ N+6G~ـ7$YM_+Ydy~767A%>w`z}ofR\ ,8 9T<ho7J쁶x$8:(ˣ' = drɘVJ@h!rx,E61&ˀ]W›PPMm lU$˿ Q*($lzbl}?2=#8ZjiI_|o:muϗCa6 ~ KAOez7-J6sBkv:p 16T[Ó>`/p B9B X {=.[Oa8:C}8Ltoj`C/ԄɿP.[Au{UJo.Ƨmn<K(OxN8p Hʠ+xn}neU).1@*[.U~F A_f1c7Z$m2eh*;~&B/Q|2=G^e;i7<$˷Ď2 `3IþV:fuMsFPs`~xǾ\;jB|;6OՍW=Wzvj™N)$?m77Ku*7RI6SY(p WgxvȎ& 5Cz&,Kd$˯3J+ic۔rD?Lnd8V[pU$x#aU-þ'aIN=P\_˰U_RM\|qh`B}wmϓZ.Pɿ} 6w=n5܌u`'Z7k[گƲEܛѠx>u~8p01 J<7^ƎQǫw]:8V۰7v/)qX5X0p"m(lg5H^PO ^-CJo>G[PoŊĨmJ4LwbwYQ &;҉ӭ`2/Ӫl }=vddyM|Kb8Yz<^E-P/V b([xTbQo/@YM;P~6 + ۵H|9yV*k> cw#f xu+$˷a[ s,ndcCҌb,Ϛ-tߧ ױ"-V+l_~$'[ Q+U儛npWǰ q,YG,5:PɿVY4Ůzl lDuVURlzl)Gބ߁y-Z& `EMh`d*k Ezn5c73sF݈0^VUf7W xl%JdƮD: )dn"Moxۤqt0aﰢXOTX-P;Խ | khdcԷl)twp$_V7cuNfKIRI)$Ǿ{^e˪ƚtUwA[aC۰[Dlxk+܀=VSY}q࠮m4NMv@'3,E}!l rX؋]_z?FD Ot뎅F,{cV`%X TV#Otf+`0l?UpKipHDDn-x ͘v1ln8:U I{ 8ciB(ag/<kxGu<I9, [6yV>? xkjlW&CgP! ?x5v;W(rEap `z@`%XlV`gr.SX0xhxpz;OQg"b_J(ֹ,6+PLr{ d&XZukP IDe ?+0; Ne,+@` hm]4vqႯ(;aY& $Oj#RG}n p lÂ_ƞg4`B}2;mŮf>mAv:%-c=Hz<Ѱm"x0?łc^G%(<s8:{0]I` MUG;ǰ}5}XU-9i/@}E:4;4vQRC"2< <կHݔ*p`MD'R \Q1 Xq,H_"Q~SIYlkP[TQ)g qHJO*J4au ;iRYi8k D4-`ڻt_8,9{Uj+R&VAچl@Dx <GD7M'Q%8%Ic9S?*8g""Q?T*pDu  R xHхA"P?T.pFGP@۟H*Il+@{"~۟H*E]eLď3Q?T6pƀ'|DaLDSmB]E|؏?x+R'N%1r.u X-0 <]B""Qt6:#Zp~+0VppDn"M><YlEu _gxKSH{۟H.p['=D'R* VKKH;U?eaCHQ?ҩsHɝjkDDnVH-vۓ,DtjM{h]{,"-`2a5z7ء,Hy@5=Ǫ_#MXP5z ^k;×68׊Bl=VDZ `'0Wʟ[aJ,X<ɽ"T-˱,X$| ,_\^YIl?wrSjI7c5%Yރ{mހN7bARԝ8. %MI)*#,t6U 1lǶ Q@$l2l_k 8IqNlk`;,0PV}6 GY&dj1tK~VgB_`p=uR,0Pa{º^Zd\.A/ x8ј!- K$%XmvT8تMXe?: ZX׿Vc2pLL$s,?o&1m 4n+[2|6iOs&JaCiUXM^oŚ۬:TH!M^_}:gBojT4+P L3nE۫<l&#|O^GeI`٣ŊG7Q cŀ>""z`9pj[}xʫq4dK醿n IiUXH@^4 JfSlT]'BGiSgmY]6]$ʮdѿ6c))q#i[4֭-)X]}X7A b\T5==se ò'zNvmT.p6bva˽KJ6/QCA `kj-XwNdrILɿV}:cAa r-"*}Xq\l ʿMvWQӛ'H*At-MnrSo4g^ h-XQxVK3Gt6X_'t;[ΉOcs֋ej .w8vTit &vB@5ڎmT HYT&p4Թ{N`A½jWu"Rw {g:I=:Ih-Th!]%WU ]nSZ@]Nzk|D*`PZQG~.,ǂ=@˓, nljLUGSQ &&,ж е]"vjڊ X{[\ExS-b+˖rR)Y~,*k$V; |SPnw(.N:d?cAi:*""$ ~o >O,qV]$WaYO,BaEgu,A1Ru%d lb~6Zշ W,Bcό'ƙg ,~g 2f\1Zϻ^{5]HsN X.S1"[0y >(^g]Zk*xŊ߹|_]w ?hgP*cX0Pd .2t41P` 1o 'L7f~{&Ww[$P#(8a\`A` pFgJ]' ؤ^Tox5O!4@daI_=9J5ACP}F5*v*W󺷻K{ hǰ Ѹ0hQ|8:|81MlúI9[?V=E^k~m3_Q %UWyj "rl&XEs^G!(|N`pzQ %VW^A5)!W)>DJL7| d\Ʋ_JM56u;{@i'PPf+tUI9ÊN4,Sl+GʧePn#tIy]qyHJf}BZ@DN[5et6tٲ_<&SF @Dk48j[IJ:""]Ʊq)9xtRZ&c""]Ʊ&2R 簻EDɪ|&&2R %"PNSU$ԉtE,: YI.s@DH54*ƫf mH)(ItyL՜CAtrB⪙@5"E K?jSDJrZC.ձ]%"]zdQ5=%" ʩnԐKDH@9-YqH)($}Bf.RP^=*߃E"l=i"UE$Z"еxAH,Nu( "]Sj+[>Q*{"R/(^`uk|DZ6=֏UX{"R/ ʭ{Ҳ5(.SPno$Y2%dy/ֽ||@YE0uҬz Pf7{jQKIQH+V{|B {Ҵ4R*1V {tI/}ErmH1V[,rD40{"*: i2J%l=iT?%%VDiY K)K $Y؊ 8,pxx{^R@G#I| KGª_UGlY³L/y,z( `8DS V?NHSRZϏqt"ee3k+_Xk x{,ت0^辎`:B.Yov g :,K ztp)#u,4M'U?CLOd?ѤqtŒ:ȹİ{3]捁/u ˰jt#Xn؋>2ݫ`Ɖ~, /lIj _XpA[7rmH`,%r l^O)9Eu8v;Tƭf Vb/bFFX̻/zvW)}1џez/jYXG3KEXZuXFR&׀[8:{02--X`vgO?s>̅(>H ^L^2,5V>n+LaAnLw׻`U^_4l#)~mFPH 0LXg<[ޯbǰ @D, B6ϰ1SmiR,_ >jUxˆ*|?-[V ǁX8j͵gM EUM">pamumZ$u?;Pvi&=*,i =bmIkeIoލ|M=DcY/ԏ;.Hx cFWD̄ A.IDATBk蕾R.кK<NX 1}"@EV!n܂gU]jsXuh9v*$uBl>\.iEQPofWKߞd*߃$˷a7<H*8w}"`+´OB5i$7aik@K.H@L`W*8eXQ ,WE-%?:n9;ESm K;> yI.ym(/8m߃\۳C5 Z:$qMat=H@*UkQ{ pOC˒,]ﻐ̜3&$˷xO>{ނUuͯHXcw‘-&k{,xIn&KQb?IJ"K|,_ <\{,%2m|x<#5U\+> pWG/\1۩vXQۯ$Y`GͥwRXK5QH*+ocWMa:r=7`)Qw: |xV"J, ߃(eXu)t{ɿ5[0}A vM[ؕdOq{U$Yރ]s3pvoAW|8{ "2ow{,%7eTc*ϦqTn*[$pOGj#:dbJ`Ep&YM4zY,VaW%Gq:lu0w "u>{,r 7|qKGdi=[]2`Yo`}{,*ar$Y+iӄɥ#(oc]m[=_m2p1= a?y3n [_^*?̯N1e؊z +LX0p$ v*KkPRUί >{,52L`XƎfVC0Φqtn?ȥ}=h"ִgӓh_{)e&o`^tmw,V˱H9l`0d`&eXs^4տH.pȬ ӓ{2_dZ̪q_?TZP-W~ *XDZؗѸ2pƁP2VE#ҩsP4q@\]UHTk"@uiVFETE-'1"Қ-&Y`DdqjnqWcwzHU `Y\& \ |]$n}DDVnRi`${,6@+bHob@b"LKKކ=DsVc[WhH*l8w:/ ˰#7bW2H*`Gn%Yz,"WБ?nǎ^D$ \p "JzeXIH@*G`9p v4P8@Tnrl8q#"Ķt4P$ 6;,"a(p߄NRvHzVk}F*#oޅ=hD$<}gt̊'f"a[ \{ "uV+0vXD¶ ؉ {0"uU >#THMbGI|Q'${4mȟH .@+nƑU#"لxQ+ { "Ҵc;t4PJ4)hU:(= \ ב?jX { "uQ+<jXBtMwX." ֭"WIt4PJsuX)z]%Q*ự?`/p]k|F,nȟH=hD: byt:iCH,`]uӧH`:'RoX1`i 'VwJё?[]."m\p^@@Ddv[;,{0"U\}; ," |;7r"A{vAMD[ { "U$R۰[t%f H["- &Ʋ+Mv2H7( IEv`pB2^= U+Y =]0@G#(rN:>IL[-O l0pXDJMux8ѸŶHvWX'Ma۹4\Gkg[) :+7"Ҽ u0 |*0F.$ nnNSäiXkxb2u4v>"tP `K~ؗB;6Y7QaL'b[= j]+$p9\eE>_}6A(Mͱ- betPAQ"nQe",~ ^Gҍ3?)Ӫ@wgy,RYlXr?IV`<|8|tM)Gk[bgFNjU  b>@B=Fxǀo'T;&/HoV'6vȿrg_'RЙOZvv =z,-h4RIU9sL.h+f:7U·OIIڼGYK7%j(h88 $O/u@1 $NR'uPc"8='U[,RGGWfNq_껺G,}،Y+!h%̀KDm،_ѲYg:ϟg,R`k!xkzD׳r@SMw:~a:Ih8ȦAs?e ?N50~C\">MY*:@c!` |Mz_d=(~^+%/uX6 ߈WÌ;z9 X >Fve/uS/ 3K|Jn;-qmuV q5_zgX;} xb4{>7z[2~'Il@ܐd2dFdgwYbsCN8uT#ݽ灿AP#IwePS6M)`y0L7lc'UR@RTWI`B9IZ@u p-zJPRTKA iHR D SBf&J, D `@R:KmNg$@ 0nEHR x- j$`ЦQGK-65#%O[mjF$@ sb tx4SDR0 9.PRԄ;( jBG{^3 .$bPRkm:Jw m`4LRDR1)SFAiLgHR# jʔ|:&gAePSko0$Iz52d "IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/shift_down.png000066400000000000000000000030211502633300400226440ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx͛KE!c\0  xCDQQD[{ EDPD1!pm&pE !d29U]]݇wwLCNfc>KNہߔG\yT88>TR46dͿ,F{J=3}$D3rGʮ+`L6 51HQ`hѵ|\Qq/ x@IS)|\q0FD3π<_))~ Mqq'ؖ,qE`8D7?Wsx`[~/gܡ80=wZ*-ViU|ݖk&pMc4, !j5XX00> E:jqș_XEfD`kk!|@h_t`w\()E`L4Bٖt*z/+)^fr 0a=;+ a=1X-_N׻`}u1?Hy 'z3C>-߫MJ-B6t w%3֣V(۔Cف|f:LPL۔\< 1G]ug"!,#u@]& k66ȖNZKX<6ue[[J$̶"b08 7} v9 D { 7O}m0 ,tE<&lWj(|osב<q&NQ7aXj/F|`s ybwC"xL@x788PфRxڙ0Lhr-M(U|لOd5x2@Es< F8?`Y8ah QIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/shift_right.png000066400000000000000000000027571502633300400230310ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxߋVE?,"]t5t]]t%jf9)ZVRqhwfn(- ڬͱҴ"O8K,y}3)n;3sfC%K-y&K.. /̷bcb}¾ p&ըrm 0<"'xaLl: VFm¾3к +c ބ%sh΂jX |"+dzYԶ'6ѿ MZ8fHx#ashVV8 0BGŒȐt.pX"o\$|]ְHmzA1̈́Fo&6 y@hB4a w6ĦH1^w\&k;o3Z/kT̈́{V?pyEe&Pv< E/$~MXB5l݀h8ټEHhc`g `:CpՙXh6~ osm4Z.b4M8堗&3Z 5=7aU3$FZ ZLg\#f!$Z+nb>/ȓMu?ȓFdLbӇ<׀ѪQ[xo'~Uhyj#ZF҄rǀ u2CdOpĥu#*Cĉ?Ax0CLNpeִMe .#N(9Ah?IOON,>D.k ANĊ?[_rCA@wUB3Lxh;ŏFaA\vCRٵ~'ŷ~ x˵odBCql맧ŷp'~\PV* !o\gg1 (IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/shift_up.png000066400000000000000000000030521502633300400223250ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx͛[UE$BB$b" !"A8>Dm2e]ʬ)#.RfIABz^yB̲uY{Yfm=盙5kJ;[d/pq*V>҄?ηa2^(c>z/Loob-Ŷ.5{Ц2vQte}ÃkSLh|xxM|RIh(c `2vI&Qc#>2 H nNx>QQJ؇pMTKJʀIGs愤,L^R.Ovxwj:j5:>se}z{:3&e؛zbnFKMR,/TD IK 3jBH?_K1P2QK&`21O W1OlPeVSOu>.Z@᯸ tzkpj~ob~~M8{KuL9 (XKbO8׊=Vy;[QE'A* kQيmmLބ_߂a-`!pl=Ɣ3a_rCp/X)c~{ ߖ*oIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/sort-ascending.png000066400000000000000000000021101502633300400234160ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATx=I-aEtOD1 Tܟ@XKl9VETc1\L9N.D DdiDDda1nw{fv烆yUիW  L 03i&;VUA׀@4=,aoge`eajU(tЬB_|O#7>YiT/EtB4l;fOiyZyֱR|+0Ӽ 7mYuEeZ/?g r~ȫQ< | tq4'oy^ ?J xVeI9ݐgс.Q?ȱ"Yst4:PVQ Nyѩ%>jiJPNN=mhL9TG oH3]8eC'' (KuV&"A:#=J>;Tj>)bQVX(!9 n7c wyK^UNJVqPaaBd-PrW(3!Txa@e2BAA.n*Q|8ђ\V~8)Mp3`~zfw'3@nN};¡'e9yQ1^YQ&,4]:3RZf6ߴ c8PVV.Ǵ?Cak qo[7ZjJ*L-J^зa׀;Nek%Z{~ "9@q=[W#scY6|3nɾJNVf˶~!vs( J18ZN()r4!Ve[~)mdh*-^U7^xƀ1AB#pY+û 0`qXAeЮIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/sort-descending.png000066400000000000000000000021221502633300400235710ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxMGiEF1$z*$ $ !DADBCri1"91d+"zY%x1,9ArC!.eY!ɶ5S3Atu{5WҲD WaAy~?5%d: C|x:nѸpP6JFMh7PC{`Ň>~8%~x hk*0#P(8 EBJ?Lm7pPIKQIrux<>05(0EL C(3v` k`8\ςA7#Y䖔˖2laz/ GC,G>ې|S>c20G^bQy͢Eun:B!nST\(ǀ㙢$͏E>/}"I9鵮|*a%Ex܀ׯr8E ! /b3pp0|;.:5Ʒ)m+A`$E'pp?p:AnNi3g $_<<]"<XI1z6-]b5Va z;uqgF@ J@$EH S1YŪ~H _a'mq^GR`k?<\IR.DǞ86bJ.=>$BU$d ܕ{;.yIџYȋeصk_3ȹ7t̍8>tȋ6ltW~,)GNm]o"ߊXqypuEn%3JJpM$Ź0&EoZPeK%f-agԽyЂ}]_]|_d!3y7˰}'(˾8w A!q/?U gb wDRte} \b YBvwER (m38zr!!LwWߋ*#")N;.B$G SѶ*C°%^+OPy(J G S&z&BVnWp6,n#!z!VuҦKFwE詵ERJ<jPjH6+mJDL̩X {yȗϝJKL~kbF9.Ah J@h)<n=MŚ4w]Y&FtK®>.J&,YMM Ztz0 \$ApɐF,S\9aXPZ,4=myWNf5Yaؔwa2Ja KƨP AzOIU`/1a]G92"?L#Hbf²+.{]áD 6Jut IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/structure.png000066400000000000000000000026401502633300400225460ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+RIDATx]hElCRD /JVH)UASkQRREPD_K(e(1Ԡ5%0{fݹ{$=;ߙ39(CK`hmgǂ8ȸ+0WI ſf?k{vVmfs`ă%e)tpCjҧ*0SY)6@; X4TND].ͯ?'! kC )6 /;D:Gx.1vy./uB9% df @闕#{G ـ> kzh &Pw.a'e6 nn֊ylEW%2^Bf-:& ,pc[z~n2Thc-C,~nNF.Vx/@t4 aqEZV+WvH턴CA`H<2 e0|#stH FkcfvYG<01*u63E A1HԨPE^C^T v7EpJ 68n;;?Y+s|IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/undo.png000066400000000000000000000022141502633300400214500ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+>IDATxOh\E?]  C$ƿPRAmN=YmEAAEkEJBXBHY3/y]7ofov~{(e#BGE#e` @8!0揨U 2I QR_0|NUʙT)c>(so+St*ǁ+|_Z:u*`kʯ3_,?_k) Ejƣϴ#|;:9W8Ro.i).U1j@})؝-[R-`NKwcCK VZۧ׀ؾ-!-'AL^7vI`ë j)ev a [KWgFaH;Lgƃ~~-ap7?WEyY0 LA-{{o(WKq }`󔗀ԟ,}'0ybUKp'qnP0[x EZe-,"n$TEn`_S,n$DS.*-~lB; i)/(OKn_^S%BDŽ~p [5>0uX CⲖb9~R4q;!tXbs6ZE ^lv*c'S0h7 TFSJ;Sv#Ю 6-`)z1`邖zp·LEC-D @+pOh" a(cwOTA ``huynEsAڙXLGj]RĨ2Zw2tL@xHK52JR~OѝCz>R,5`Yఖ󪆱XNh)C el[e1X>.yWA˻[,ǽ8(~.[3>}IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/unlocked.png000066400000000000000000000020411502633300400223050ustar00rootroot00000000000000PNG  IHDR@@iq pHYs+IDATxOHA?<"$"D4HĢ."C'klVKGAԆmH0E/餬Gi͈T80`e8l0.D~î &-LfʑxIo"9.}Ub@2G@LO@B/%,G7`_+2F]+_wB/ɶk&Fun=f%t}/ 7w@Q82V P۸b$E>ePfRLGLiI hgs8ʄd(co"LaB"/xmBt/nB4MH]x eB PxxaphғoK<6;]KixMcDbM!l^(c5sm; c)Pk ;,{]<[D[,${$VaF;AXՄJK@8i)c^U]} (]*408Vez./#0%m`r:'Mz^Kq  Lh@I&M9z_ӄ9x?Nvo_ e= 3-F*cſĝBHVƞ.bf_W2e0L[֊iBqoh)Fe[Ŧ= Ѕ/4cx]KA10p]:Vk)KANi)8 #8w?qs2 RVmQQuz XR|1R.ǙCi6e\Ϣ Z/;V{f0I7  lBGУVƮLCcc&ˀ"0Ӷc3/}$,_9kɃG,i_IZ'_ \[!  3@Z4i8H  3@Z4i8H  3@Z4i8̲:$TiƘ44 gi X,Px ̀f&;˖54mzAhi5* Ѭw`DPFh *p\lM2fJܝde|0n9D9Xh.-6 [ Jf-u&{xwM"ʗG%vx@etg@E+$$eu=ʉFyB_KVY>$ֽiizIENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/zoom-in.png000066400000000000000000000034131502633300400220750ustar00rootroot00000000000000PNG  IHDR@@iqIDATxmVE."&STY؛hB% ?DeDJ-JLR4) b1dYsy>ssߞmw~3sg߹gΜ3Ogxt t+@`~%ECwc L&A pبV6%:`.0@X-mBM :PSiJq86 6azϝf))ӹxL>zFtkS@?F5rĬ))Z:UO2'w>$0K"j`JXi2{wnb ,ǮvʝOeRRݰ/4sȕOoCX R83>g⥠07oXg%%O!p`JCm|Cee.g!C6(;4j28 0^qCv2+A?P'4#F;dSUvO*2Y!qJIJwJ+Y ؂McMBhMu4mb6GSa8w97Q6lQ;67M ();MkjQRuH,wՅ H/ | w5`t ^Ž-)Agmp%s`j%]fkMue'B6%] tp |yjraok&M2Q(Z-$%`C8ϰ;Dq+p` VM_ۃv(mn&X4l,T?[1mqd46:$G-|%v Mtf=6cwzllp36Y2 ؝rGa>yBcrMŴb0@Dn1x%$;MPkw] Ɵ &ϊ8lNl%՝^}ѷ񁾽q-2n͠[5GDϟF*)T}\mTcXB'/2?W{sA(13Бt1#AOPPB@7׵;t" 4SHisH׮]8M:`}"QPx A;` rƃ%`M>x*oӉց#$evG ,-IENDB`asammdf-8.5.1/src/asammdf/gui/ui/images/zoom-out.png000066400000000000000000000032721502633300400223010ustar00rootroot00000000000000PNG  IHDR@@iqIDATxmUE,"!!"HL!&Q-f"Ib/d&z(^LJDAPQLD2I|!YJDEeÜ+s{ϝs>yg3y9u0m#- 0@+ OIіuYt6} `<4ZJΥ w9 tJ^\mgׁ9 | ,QR  lF40WIM%ʹh36A8~Na @#0Y ,VRt')F@ 'w4¤0 KT50]Iq!N!mbwo%M,X7+ą]ĸ2' f>*a2O*)x̾X^qx8dJ@}w1XZA >g╨03mHS7bmVcG31 Jł8U >tAPR(օEdB@%Y! aW_1" C@3W+KmGS6 XӀY0[IѕA>XŅ?Y![8A^~*h3< i4$$ۀ#q`&GY:M&8d<b P5 q;6ܽhvGЌد3OqF0!;_pmx I f> ZN%ŎWP흎S~c&aQl%vܪwbG,3q aT ?* %w XN\u)+)ڌF)vƇ.ýc!3> lGyN/Q?hWUU 6[U*F>!gxo/[ bI[ aYG&9.<6\3"'C6.ƕ-)m8V^۽ PR;քբAwۀՅ?YU^  ^ý-+>A JVU,5C`XUi x|~$b*=Jt cOh3}ɓF&l!f4sgJ =w'tɩVm-()v) E6cVh&))&i*ZE~֠}qۅǡ`Hl8lVD .he plug:t`_30>;[^"+ta\[ƨ$'JSkFW[8 ؤep#pzl ̏LK@AI~JtFxC6cXPB@vǵ;\)j>J[ݕ:z $6ƃJK){` 4uƃ%^i,åCs؏ځ2J/|nIENDB`asammdf-8.5.1/src/asammdf/gui/ui/main_window.py000066400000000000000000000115151502633300400214210ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'main_window.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QFrame, QMainWindow, QMenuBar, QSizePolicy, QStackedWidget, QTabWidget, QVBoxLayout, QWidget) from . import resource_rc class Ui_PyMDFMainWindow(object): def setupUi(self, PyMDFMainWindow): if not PyMDFMainWindow.objectName(): PyMDFMainWindow.setObjectName(u"PyMDFMainWindow") PyMDFMainWindow.resize(800, 723) sizePolicy = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(PyMDFMainWindow.sizePolicy().hasHeightForWidth()) PyMDFMainWindow.setSizePolicy(sizePolicy) icon = QIcon() icon.addFile(u":/asammdf.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) PyMDFMainWindow.setWindowIcon(icon) self.action_memory_minimum = QAction(PyMDFMainWindow) self.action_memory_minimum.setObjectName(u"action_memory_minimum") self.action_memory_minimum.setCheckable(True) self.action_memory_full = QAction(PyMDFMainWindow) self.action_memory_full.setObjectName(u"action_memory_full") self.action_memory_full.setCheckable(True) self.action_memory_low = QAction(PyMDFMainWindow) self.action_memory_low.setObjectName(u"action_memory_low") self.action_memory_low.setCheckable(True) self.centralwidget = QWidget(PyMDFMainWindow) self.centralwidget.setObjectName(u"centralwidget") self.verticalLayout = QVBoxLayout(self.centralwidget) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.stackedWidget = QStackedWidget(self.centralwidget) self.stackedWidget.setObjectName(u"stackedWidget") self.stackedWidget.setFrameShape(QFrame.NoFrame) self.stackedWidgetPage1 = QWidget() self.stackedWidgetPage1.setObjectName(u"stackedWidgetPage1") self.verticalLayout_2 = QVBoxLayout(self.stackedWidgetPage1) self.verticalLayout_2.setSpacing(1) self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.verticalLayout_2.setContentsMargins(1, 1, 1, 1) self.files = QTabWidget(self.stackedWidgetPage1) self.files.setObjectName(u"files") self.files.setDocumentMode(False) self.files.setTabsClosable(True) self.verticalLayout_2.addWidget(self.files) self.stackedWidget.addWidget(self.stackedWidgetPage1) self.verticalLayout.addWidget(self.stackedWidget) PyMDFMainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(PyMDFMainWindow) self.menubar.setObjectName(u"menubar") self.menubar.setGeometry(QRect(0, 0, 800, 21)) PyMDFMainWindow.setMenuBar(self.menubar) self.retranslateUi(PyMDFMainWindow) self.stackedWidget.setCurrentIndex(0) self.files.setCurrentIndex(-1) QMetaObject.connectSlotsByName(PyMDFMainWindow) # setupUi def retranslateUi(self, PyMDFMainWindow): PyMDFMainWindow.setWindowTitle(QCoreApplication.translate("PyMDFMainWindow", u"asammdf", None)) self.action_memory_minimum.setText(QCoreApplication.translate("PyMDFMainWindow", u"minimum", None)) #if QT_CONFIG(tooltip) self.action_memory_minimum.setToolTip(QCoreApplication.translate("PyMDFMainWindow", u"Minimal memory usage by loading only the nedded block addresses", None)) #endif // QT_CONFIG(tooltip) self.action_memory_full.setText(QCoreApplication.translate("PyMDFMainWindow", u"full", None)) #if QT_CONFIG(tooltip) self.action_memory_full.setToolTip(QCoreApplication.translate("PyMDFMainWindow", u"Load all blocks in the RAM", None)) #endif // QT_CONFIG(tooltip) self.action_memory_low.setText(QCoreApplication.translate("PyMDFMainWindow", u"low", None)) #if QT_CONFIG(tooltip) self.action_memory_low.setToolTip(QCoreApplication.translate("PyMDFMainWindow", u"Load metdata block in RAM but leave the samples on disk", None)) #endif // QT_CONFIG(tooltip) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/main_window.ui000066400000000000000000000066241502633300400214130ustar00rootroot00000000000000 PyMDFMainWindow 0 0 800 723 0 0 asammdf :/asammdf.png:/asammdf.png 1 1 1 1 1 QFrame::NoFrame 0 1 1 1 1 1 -1 false true 0 0 800 21 true minimum Minimal memory usage by loading only the nedded block addresses true full Load all blocks in the RAM true low Load metdata block in RAM but leave the samples on disk asammdf-8.5.1/src/asammdf/gui/ui/multi_search_dialog.py000066400000000000000000000146101502633300400231030ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'multi_search_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QDialog, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem, QPushButton, QSizePolicy, QSpacerItem, QWidget) from asammdf.gui.widgets.list import MinimalListWidget from . import resource_rc class Ui_MultiSearchDialog(object): def setupUi(self, MultiSearchDialog): if not MultiSearchDialog.objectName(): MultiSearchDialog.setObjectName(u"MultiSearchDialog") MultiSearchDialog.resize(1028, 549) MultiSearchDialog.setSizeGripEnabled(True) self.grid_layout = QGridLayout(MultiSearchDialog) self.grid_layout.setSpacing(1) self.grid_layout.setObjectName(u"grid_layout") self.grid_layout.setContentsMargins(1, 1, 1, 1) self.match_kind = QComboBox(MultiSearchDialog) self.match_kind.addItem("") self.match_kind.addItem("") self.match_kind.setObjectName(u"match_kind") self.grid_layout.addWidget(self.match_kind, 0, 0, 1, 1) self.status = QLabel(MultiSearchDialog) self.status.setObjectName(u"status") self.grid_layout.addWidget(self.status, 10, 0, 1, 1) self.matches = QListWidget(MultiSearchDialog) self.matches.setObjectName(u"matches") self.grid_layout.addWidget(self.matches, 6, 0, 2, 1) self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.grid_layout.addItem(self.verticalSpacer_2, 7, 1, 1, 1) self.selection = MinimalListWidget(MultiSearchDialog) self.selection.setObjectName(u"selection") self.selection.setMinimumSize(QSize(500, 0)) self.grid_layout.addWidget(self.selection, 6, 2, 3, 4) self.label = QLabel(MultiSearchDialog) self.label.setObjectName(u"label") self.grid_layout.addWidget(self.label, 2, 2, 1, 1) self.search_box = QLineEdit(MultiSearchDialog) self.search_box.setObjectName(u"search_box") self.grid_layout.addWidget(self.search_box, 2, 0, 1, 1) self.show_measurement_list_btn = QPushButton(MultiSearchDialog) self.show_measurement_list_btn.setObjectName(u"show_measurement_list_btn") icon = QIcon() icon.addFile(u":/info.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.show_measurement_list_btn.setIcon(icon) self.grid_layout.addWidget(self.show_measurement_list_btn, 0, 2, 1, 2) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.cancel_btn = QPushButton(MultiSearchDialog) self.cancel_btn.setObjectName(u"cancel_btn") self.horizontalLayout.addWidget(self.cancel_btn) self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer_2) self.apply_btn = QPushButton(MultiSearchDialog) self.apply_btn.setObjectName(u"apply_btn") self.horizontalLayout.addWidget(self.apply_btn) self.horizontalLayout.setStretch(1, 1) self.grid_layout.addLayout(self.horizontalLayout, 9, 0, 1, 6) self.add_btn = QPushButton(MultiSearchDialog) self.add_btn.setObjectName(u"add_btn") self.add_btn.setFocusPolicy(Qt.FocusPolicy.TabFocus) icon1 = QIcon() icon1.addFile(u":/left.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.add_btn.setIcon(icon1) self.grid_layout.addWidget(self.add_btn, 6, 1, 1, 1) self.case_sensitivity = QComboBox(MultiSearchDialog) self.case_sensitivity.addItem("") self.case_sensitivity.addItem("") self.case_sensitivity.setObjectName(u"case_sensitivity") self.grid_layout.addWidget(self.case_sensitivity, 1, 0, 1, 1) self.grid_layout.setColumnStretch(0, 1) QWidget.setTabOrder(self.match_kind, self.case_sensitivity) QWidget.setTabOrder(self.case_sensitivity, self.search_box) QWidget.setTabOrder(self.search_box, self.matches) QWidget.setTabOrder(self.matches, self.add_btn) QWidget.setTabOrder(self.add_btn, self.selection) QWidget.setTabOrder(self.selection, self.apply_btn) QWidget.setTabOrder(self.apply_btn, self.cancel_btn) QWidget.setTabOrder(self.cancel_btn, self.show_measurement_list_btn) self.retranslateUi(MultiSearchDialog) self.match_kind.setCurrentIndex(0) QMetaObject.connectSlotsByName(MultiSearchDialog) # setupUi def retranslateUi(self, MultiSearchDialog): MultiSearchDialog.setWindowTitle(QCoreApplication.translate("MultiSearchDialog", u"Dialog", None)) self.match_kind.setItemText(0, QCoreApplication.translate("MultiSearchDialog", u"Wildcard", None)) self.match_kind.setItemText(1, QCoreApplication.translate("MultiSearchDialog", u"Regex", None)) self.status.setText("") self.label.setText(QCoreApplication.translate("MultiSearchDialog", u"Final selection", None)) self.search_box.setText("") self.show_measurement_list_btn.setText(QCoreApplication.translate("MultiSearchDialog", u"Show measurement list", None)) self.cancel_btn.setText(QCoreApplication.translate("MultiSearchDialog", u"Cancel", None)) self.apply_btn.setText(QCoreApplication.translate("MultiSearchDialog", u"Apply", None)) self.add_btn.setText("") self.case_sensitivity.setItemText(0, QCoreApplication.translate("MultiSearchDialog", u"Case insensitive", None)) self.case_sensitivity.setItemText(1, QCoreApplication.translate("MultiSearchDialog", u"Case sensitive", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/multi_search_dialog.ui000066400000000000000000000116441502633300400230740ustar00rootroot00000000000000 MultiSearchDialog 0 0 1028 549 Dialog true 1 1 1 1 1 0 Wildcard Regex Qt::Orientation::Vertical 20 40 500 0 Final selection Show measurement list :/info.png:/info.png 1 Cancel Qt::Orientation::Horizontal 40 20 Apply Qt::FocusPolicy::TabFocus :/left.png:/left.png Case insensitive Case sensitive MinimalListWidget QListWidget

asammdf.gui.widgets.list.h
match_kind case_sensitivity search_box matches add_btn selection apply_btn cancel_btn show_measurement_list_btn asammdf-8.5.1/src/asammdf/gui/ui/numeric_offline.py000066400000000000000000000242711502633300400222550ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'numeric_offline.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QDoubleSpinBox, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QSizePolicy, QSlider, QSpacerItem, QVBoxLayout, QWidget) from . import resource_rc class Ui_NumericDisplay(object): def setupUi(self, NumericDisplay): if not NumericDisplay.objectName(): NumericDisplay.setObjectName(u"NumericDisplay") NumericDisplay.resize(681, 666) self.main_layout = QVBoxLayout(NumericDisplay) self.main_layout.setSpacing(1) self.main_layout.setObjectName(u"main_layout") self.main_layout.setContentsMargins(1, 1, 1, 1) self.controls = QGroupBox(NumericDisplay) self.controls.setObjectName(u"controls") self.controls.setFlat(True) self.verticalLayout = QVBoxLayout(self.controls) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.gridLayout_2 = QGridLayout() self.gridLayout_2.setSpacing(1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.toggle_controls_btn = QPushButton(self.controls) self.toggle_controls_btn.setObjectName(u"toggle_controls_btn") icon = QIcon() icon.addFile(u":/down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.toggle_controls_btn.setIcon(icon) self.gridLayout_2.addWidget(self.toggle_controls_btn, 0, 3, 1, 1) self.controls_label = QLabel(self.controls) self.controls_label.setObjectName(u"controls_label") self.gridLayout_2.addWidget(self.controls_label, 0, 0, 1, 1) self.float_precision = QComboBox(self.controls) self.float_precision.setObjectName(u"float_precision") self.gridLayout_2.addWidget(self.float_precision, 0, 1, 1, 1) self.controls_spacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_2.addItem(self.controls_spacer, 0, 2, 1, 1) self.gridLayout_2.setColumnStretch(2, 1) self.verticalLayout.addLayout(self.gridLayout_2) self.time_group = QGroupBox(self.controls) self.time_group.setObjectName(u"time_group") self.horizontalLayout_2 = QHBoxLayout(self.time_group) self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.horizontalLayout_2.setContentsMargins(1, 1, 1, 1) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.timestamp = QDoubleSpinBox(self.time_group) self.timestamp.setObjectName(u"timestamp") self.timestamp.setDecimals(9) self.timestamp.setSingleStep(0.001000000000000) self.horizontalLayout.addWidget(self.timestamp) self.min_t = QLabel(self.time_group) self.min_t.setObjectName(u"min_t") self.horizontalLayout.addWidget(self.min_t) self.timestamp_slider = QSlider(self.time_group) self.timestamp_slider.setObjectName(u"timestamp_slider") self.timestamp_slider.setMaximum(99999) self.timestamp_slider.setOrientation(Qt.Orientation.Horizontal) self.timestamp_slider.setInvertedAppearance(False) self.timestamp_slider.setInvertedControls(False) self.timestamp_slider.setTickPosition(QSlider.TickPosition.NoTicks) self.timestamp_slider.setTickInterval(1) self.horizontalLayout.addWidget(self.timestamp_slider) self.max_t = QLabel(self.time_group) self.max_t.setObjectName(u"max_t") self.horizontalLayout.addWidget(self.max_t) self.horizontalLayout.setStretch(2, 1) self.horizontalLayout_2.addLayout(self.horizontalLayout) self.verticalLayout.addWidget(self.time_group) self.search_group = QGroupBox(self.controls) self.search_group.setObjectName(u"search_group") self.gridLayout = QGridLayout(self.search_group) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.pattern_match = QLineEdit(self.search_group) self.pattern_match.setObjectName(u"pattern_match") self.gridLayout.addWidget(self.pattern_match, 0, 1, 1, 1) self.op = QComboBox(self.search_group) self.op.addItem("") self.op.addItem("") self.op.addItem("") self.op.addItem("") self.op.addItem("") self.op.addItem("") self.op.setObjectName(u"op") self.gridLayout.addWidget(self.op, 0, 2, 1, 1) self.match_type = QComboBox(self.search_group) self.match_type.addItem("") self.match_type.addItem("") self.match_type.setObjectName(u"match_type") self.gridLayout.addWidget(self.match_type, 1, 1, 1, 1) self.target = QLineEdit(self.search_group) self.target.setObjectName(u"target") self.gridLayout.addWidget(self.target, 0, 3, 1, 1) self.match_mode = QComboBox(self.search_group) self.match_mode.addItem("") self.match_mode.addItem("") self.match_mode.setObjectName(u"match_mode") self.gridLayout.addWidget(self.match_mode, 0, 0, 1, 1) self.case_sensitivity = QComboBox(self.search_group) self.case_sensitivity.addItem("") self.case_sensitivity.addItem("") self.case_sensitivity.setObjectName(u"case_sensitivity") self.gridLayout.addWidget(self.case_sensitivity, 2, 1, 1, 1) self.horizontalLayout_3 = QHBoxLayout() self.horizontalLayout_3.setSpacing(1) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.backward = QPushButton(self.search_group) self.backward.setObjectName(u"backward") icon1 = QIcon() icon1.addFile(u":/right.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.backward.setIcon(icon1) self.horizontalLayout_3.addWidget(self.backward) self.horizontalSpacer_4 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_3.addItem(self.horizontalSpacer_4) self.forward = QPushButton(self.search_group) self.forward.setObjectName(u"forward") icon2 = QIcon() icon2.addFile(u":/left.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.forward.setIcon(icon2) self.horizontalLayout_3.addWidget(self.forward) self.gridLayout.addLayout(self.horizontalLayout_3, 1, 3, 2, 1) self.match = QLabel(self.search_group) self.match.setObjectName(u"match") self.gridLayout.addWidget(self.match, 3, 0, 1, 4) self.gridLayout.setColumnStretch(1, 1) self.verticalLayout.addWidget(self.search_group) self.main_layout.addWidget(self.controls) QWidget.setTabOrder(self.timestamp, self.pattern_match) QWidget.setTabOrder(self.pattern_match, self.op) QWidget.setTabOrder(self.op, self.target) QWidget.setTabOrder(self.target, self.backward) QWidget.setTabOrder(self.backward, self.forward) self.retranslateUi(NumericDisplay) QMetaObject.connectSlotsByName(NumericDisplay) # setupUi def retranslateUi(self, NumericDisplay): NumericDisplay.setWindowTitle(QCoreApplication.translate("NumericDisplay", u"Form", None)) self.controls.setTitle("") self.toggle_controls_btn.setText(QCoreApplication.translate("NumericDisplay", u"Show controls", None)) self.controls_label.setText(QCoreApplication.translate("NumericDisplay", u"Precision", None)) self.time_group.setTitle(QCoreApplication.translate("NumericDisplay", u"Time stamp", None)) self.timestamp.setSuffix(QCoreApplication.translate("NumericDisplay", u"s", None)) self.min_t.setText("") self.max_t.setText("") self.search_group.setTitle(QCoreApplication.translate("NumericDisplay", u"Search for values", None)) self.pattern_match.setPlaceholderText(QCoreApplication.translate("NumericDisplay", u"pattern", None)) self.op.setItemText(0, QCoreApplication.translate("NumericDisplay", u"==", None)) self.op.setItemText(1, QCoreApplication.translate("NumericDisplay", u"!=", None)) self.op.setItemText(2, QCoreApplication.translate("NumericDisplay", u"<", None)) self.op.setItemText(3, QCoreApplication.translate("NumericDisplay", u"<=", None)) self.op.setItemText(4, QCoreApplication.translate("NumericDisplay", u">", None)) self.op.setItemText(5, QCoreApplication.translate("NumericDisplay", u">=", None)) self.match_type.setItemText(0, QCoreApplication.translate("NumericDisplay", u"Wildcard", None)) self.match_type.setItemText(1, QCoreApplication.translate("NumericDisplay", u"Regex", None)) self.target.setPlaceholderText(QCoreApplication.translate("NumericDisplay", u"target value", None)) self.match_mode.setItemText(0, QCoreApplication.translate("NumericDisplay", u"Raw", None)) self.match_mode.setItemText(1, QCoreApplication.translate("NumericDisplay", u"Scaled", None)) self.case_sensitivity.setItemText(0, QCoreApplication.translate("NumericDisplay", u"Case insensitive", None)) self.case_sensitivity.setItemText(1, QCoreApplication.translate("NumericDisplay", u"Case sensitive", None)) self.backward.setText("") self.forward.setText("") self.match.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/numeric_offline.ui000066400000000000000000000237421502633300400222440ustar00rootroot00000000000000 NumericDisplay 0 0 681 666 Form 1 1 1 1 1 true 1 1 1 1 1 1 Show controls :/down.png:/down.png Precision Qt::Orientation::Horizontal 40 20 Time stamp 1 1 1 1 1 1 s 9 0.001000000000000 99999 Qt::Orientation::Horizontal false false QSlider::TickPosition::NoTicks 1 Search for values 1 1 1 1 1 pattern == != < <= > >= Wildcard Regex target value Raw Scaled Case insensitive Case sensitive 1 :/right.png:/right.png Qt::Orientation::Horizontal 40 20 :/left.png:/left.png timestamp pattern_match op target backward forward asammdf-8.5.1/src/asammdf/gui/ui/range_editor_dialog.py000066400000000000000000000074121502633300400230700ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'range_editor_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QAbstractItemView, QApplication, QDialog, QGridLayout, QListWidgetItem, QPushButton, QSizePolicy, QSpacerItem, QWidget) from asammdf.gui.widgets.list import MinimalListWidget class Ui_RangeDialog(object): def setupUi(self, RangeDialog): if not RangeDialog.objectName(): RangeDialog.setObjectName(u"RangeDialog") RangeDialog.resize(1300, 329) RangeDialog.setSizeGripEnabled(True) RangeDialog.setModal(True) self.gridLayout = QGridLayout(RangeDialog) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.ranges = MinimalListWidget(RangeDialog) self.ranges.setObjectName(u"ranges") self.ranges.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) self.ranges.setDefaultDropAction(Qt.DropAction.MoveAction) self.gridLayout.addWidget(self.ranges, 0, 0, 7, 1) self.verticalSpacer = QSpacerItem(20, 271, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout.addItem(self.verticalSpacer, 4, 1, 1, 1) self.reset_btn = QPushButton(RangeDialog) self.reset_btn.setObjectName(u"reset_btn") self.gridLayout.addWidget(self.reset_btn, 3, 1, 1, 1) self.cancel_btn = QPushButton(RangeDialog) self.cancel_btn.setObjectName(u"cancel_btn") self.gridLayout.addWidget(self.cancel_btn, 6, 1, 1, 1) self.apply_btn = QPushButton(RangeDialog) self.apply_btn.setObjectName(u"apply_btn") self.gridLayout.addWidget(self.apply_btn, 5, 1, 1, 1) self.insert_btn = QPushButton(RangeDialog) self.insert_btn.setObjectName(u"insert_btn") self.gridLayout.addWidget(self.insert_btn, 0, 1, 1, 1) self.verticalSpacer_2 = QSpacerItem(20, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout.addItem(self.verticalSpacer_2, 1, 1, 1, 1) self.gridLayout.setRowStretch(4, 1) self.gridLayout.setColumnStretch(0, 1) QWidget.setTabOrder(self.ranges, self.insert_btn) QWidget.setTabOrder(self.insert_btn, self.reset_btn) QWidget.setTabOrder(self.reset_btn, self.apply_btn) QWidget.setTabOrder(self.apply_btn, self.cancel_btn) self.retranslateUi(RangeDialog) QMetaObject.connectSlotsByName(RangeDialog) # setupUi def retranslateUi(self, RangeDialog): RangeDialog.setWindowTitle(QCoreApplication.translate("RangeDialog", u"Edit value range colors", None)) self.reset_btn.setText(QCoreApplication.translate("RangeDialog", u"Reset", None)) self.cancel_btn.setText(QCoreApplication.translate("RangeDialog", u"Cancel", None)) self.apply_btn.setText(QCoreApplication.translate("RangeDialog", u"Apply", None)) self.insert_btn.setText(QCoreApplication.translate("RangeDialog", u"Insert range", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/range_editor_dialog.ui000066400000000000000000000057551502633300400230650ustar00rootroot00000000000000 RangeDialog 0 0 1300 329 Edit value range colors true true 1 1 1 1 1 QAbstractItemView::DragDropMode::InternalMove Qt::DropAction::MoveAction Qt::Orientation::Vertical 20 271 Reset Cancel Apply Insert range Qt::Orientation::Vertical 20 20 MinimalListWidget QListWidget
asammdf.gui.widgets.list.h
ranges insert_btn reset_btn apply_btn cancel_btn
asammdf-8.5.1/src/asammdf/gui/ui/range_widget.py000066400000000000000000000132041502633300400215420ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'range_widget.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QSizePolicy, QWidget) class Ui_RangeWidget(object): def setupUi(self, RangeWidget): if not RangeWidget.objectName(): RangeWidget.setObjectName(u"RangeWidget") RangeWidget.resize(673, 41) sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(RangeWidget.sizePolicy().hasHeightForWidth()) RangeWidget.setSizePolicy(sizePolicy) RangeWidget.setMinimumSize(QSize(0, 41)) RangeWidget.setMaximumSize(QSize(16777215, 41)) self.horizontalLayout = QHBoxLayout(RangeWidget) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.label = QLabel(RangeWidget) self.label.setObjectName(u"label") self.horizontalLayout.addWidget(self.label) self.value1 = QLineEdit(RangeWidget) self.value1.setObjectName(u"value1") self.horizontalLayout.addWidget(self.value1) self.op1 = QComboBox(RangeWidget) self.op1.addItem("") self.op1.addItem("") self.op1.addItem("") self.op1.addItem("") self.op1.addItem("") self.op1.addItem("") self.op1.setObjectName(u"op1") self.op1.setEnabled(False) self.horizontalLayout.addWidget(self.op1) self.name = QLabel(RangeWidget) self.name.setObjectName(u"name") self.name.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout.addWidget(self.name) self.op2 = QComboBox(RangeWidget) self.op2.addItem("") self.op2.addItem("") self.op2.addItem("") self.op2.addItem("") self.op2.addItem("") self.op2.addItem("") self.op2.setObjectName(u"op2") self.op2.setEnabled(False) self.horizontalLayout.addWidget(self.op2) self.value2 = QLineEdit(RangeWidget) self.value2.setObjectName(u"value2") self.horizontalLayout.addWidget(self.value2) self.label_2 = QLabel(RangeWidget) self.label_2.setObjectName(u"label_2") self.horizontalLayout.addWidget(self.label_2) self.background_color_btn = QPushButton(RangeWidget) self.background_color_btn.setObjectName(u"background_color_btn") self.background_color_btn.setMinimumSize(QSize(40, 0)) self.horizontalLayout.addWidget(self.background_color_btn) self.label_3 = QLabel(RangeWidget) self.label_3.setObjectName(u"label_3") self.horizontalLayout.addWidget(self.label_3) self.font_color_btn = QPushButton(RangeWidget) self.font_color_btn.setObjectName(u"font_color_btn") self.font_color_btn.setMinimumSize(QSize(40, 0)) self.horizontalLayout.addWidget(self.font_color_btn) self.horizontalLayout.setStretch(3, 1) self.retranslateUi(RangeWidget) QMetaObject.connectSlotsByName(RangeWidget) # setupUi def retranslateUi(self, RangeWidget): RangeWidget.setWindowTitle(QCoreApplication.translate("RangeWidget", u"Form", None)) self.label.setText(QCoreApplication.translate("RangeWidget", u"If", None)) self.op1.setItemText(0, QCoreApplication.translate("RangeWidget", u"==", None)) self.op1.setItemText(1, QCoreApplication.translate("RangeWidget", u"!=", None)) self.op1.setItemText(2, QCoreApplication.translate("RangeWidget", u">", None)) self.op1.setItemText(3, QCoreApplication.translate("RangeWidget", u">=", None)) self.op1.setItemText(4, QCoreApplication.translate("RangeWidget", u"<", None)) self.op1.setItemText(5, QCoreApplication.translate("RangeWidget", u"<=", None)) self.name.setText(QCoreApplication.translate("RangeWidget", u"TextLabel", None)) self.op2.setItemText(0, QCoreApplication.translate("RangeWidget", u"==", None)) self.op2.setItemText(1, QCoreApplication.translate("RangeWidget", u"!=", None)) self.op2.setItemText(2, QCoreApplication.translate("RangeWidget", u">", None)) self.op2.setItemText(3, QCoreApplication.translate("RangeWidget", u">=", None)) self.op2.setItemText(4, QCoreApplication.translate("RangeWidget", u"<", None)) self.op2.setItemText(5, QCoreApplication.translate("RangeWidget", u"<=", None)) self.label_2.setText(QCoreApplication.translate("RangeWidget", u"then set background", None)) self.background_color_btn.setText("") self.label_3.setText(QCoreApplication.translate("RangeWidget", u"and font/curve", None)) self.font_color_btn.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/range_widget.ui000066400000000000000000000100711502633300400215260ustar00rootroot00000000000000 RangeWidget 0 0 673 41 0 0 0 41 16777215 41 Form 1 1 1 1 1 If false == != > >= < <= TextLabel Qt::AlignmentFlag::AlignCenter false == != > >= < <= then set background 40 0 and font/curve 40 0 asammdf-8.5.1/src/asammdf/gui/ui/resource.qrc000066400000000000000000000115021502633300400210660ustar00rootroot00000000000000 images/attach.png images/alphabetical_sorting.png images/arrow_next_higher.png images/arrow_next_lower.png images/arrow_previous_higher.png images/arrow_previous_lower.png images/asammdf.png images/axis.png images/axis_on.png images/bookmark.png images/bookmark_on.png images/bus_can.png images/bus_eth.png images/bus_flx.png images/bus_lin.png images/bus_usb.png images/checkmark.png images/clock.png images/comments.png images/compare.png images/convert.png images/copy.png images/csv.png images/cursor.png images/cut.png images/decrease-font.png images/delta.png images/delta_on.png images/down.png images/edit.png images/erase.png images/error.png images/export.png images/file.png images/filter.png images/fit.png images/focus.png images/focus_on.png images/globe.png images/graph.png images/grid.png images/home.png images/increase-font.png images/info.png images/left.png images/left2.png images/left_interconnect.png images/line_interconnect.png images/list.png images/list2.png images/load_embed.png images/lock_range.png images/locked.png images/memory.png images/minus.png images/number.png images/number_on.png images/numeric.png images/open.png images/paint.png images/plus.png images/range.png images/redo.png images/resample.png images/right.png images/right2.png images/right_interconnect.png images/save.png images/scramble.png images/search.png images/settings.png images/shift_down.png images/shift_left.png images/shift_right.png images/shift_up.png images/sort-ascending.png images/sort-descending.png images/stack.png images/structure.png images/undo.png images/unlocked.png images/up.png images/window.png images/zoom-in.png images/zoom-out.png asammdf-8.5.1/src/asammdf/gui/ui/resource_rc.py000066400000000000000000024576011502633300400214350ustar00rootroot00000000000000# Resource object code (Python 3) # Created by: object code # Created by: The Resource Compiler for Qt version 6.7.3 # WARNING! All changes made in this file will be lost! from PySide6 import QtCore qt_resource_data = b"\ \x00\x00\x05N\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x05\x15IDATx\x9c\xed\x9a]\x88UU\ \x14\xc7\x7f\xdd\x061\x09\x19\x86a\x08\x91\x8d\x0f\x83\x84\ XIFEd\x0f\x11A>l\xcc\xb0\xc0t\xf7a\ \x19\xe30VN%Q\x22QAM\xa6Y1\x16\x91\ \xe6&(D(\xf6CQ*\x16\x85\xda\x87d\x0a\x11\ \x11\x11\x1b\x91AB\x86!\x86\x18\x86\xa1\x87}\xee0\ s\xe7~\x9c{\xd6\xbew\xce\x9d\xfa\xbf\x5c\xee9{\ \xad\xb5\xd7\xff\xac\xfd\xb5\xd6\x86\xff8.\x9b\xed\x0e\xc4\ \x86q~>\xb0\x01X\x09\x0c\x03\x1fY\xad\xceVj\ ?\xa7\x080\xce\x17\x80O\x00=\xe5\xf18\xf0\x06\xb0\ \xc3j\xf5O\xa9L\xa1I}k\x16\xb62\xddy\x80\ 6\xe0)\xe0\xb4q\xfe\xfaR\x819\x13\x01\xc6\xf9\x15\ \xc0I`~\x95fc\xc0N`\xc0j5\x01s\x84\ \x00\xe3\xfc\x02\xe0;`yJ\x91\xa3\xc0F\xab\xd5\xd0\ \x5c!`\x0f\xf0D\x9db\xe7\x81U\x977\xa0?M\ \x85q\xfe\x0e\xe0m\xea\x8f\xe6\x85@WK\x13`\x9c\ o\x07>\x07\xda3\xaa\xb8\xa2\xd5W\x81\xbd\x80\x12\xc8\ _h\xd99\xc08\xbf\x86\xb0\xe6KpOK\x12`\ \x9c\xef\x02\xce\x01]\x025\x87\xadV\xebZu\x08\xbc\ \x8b\xcc\xf9\x8b@/\xb4\xe0N\xd08o\x805B5\ \xbdV\xab\x8b\xd0b\x1b!\xe3\xfcb\xe0g\xa0C\xa0\ \xe6\x90\xd5\xea\xbe\xe2\x9f\x96\x89\x80\xe4\xa0\xf3>2\xe7\ \x87HB\xbf\x88\x96!\x00\xd8\x0c\xdc)\xd4\xd1c\xb5\ \xfak\xea\x83\x96\x18\x02\xc6\xf9n\xe0'\xe0J\x81\x9a\ \x0f\xadV\x1bK\x1f\xe6>\x02\xa6\x84\xbe\xc4\xf9\x0b\xc0\ \xe3\xe5^\xe4\x9e\x00\xc2\x19\xff6\x81\xfc\x04\xf0\xa8\xd5\ \xeaR\xb9\x97\xb9\x1e\x02\xc6\xf9\xab\x81\xd3\xc0\x02\x81\x9a\ \xfdV\xabM\x95^\xe66\x02\x8c\xf3m\xc0\x01d\xce\ \xff\x09\x12\x8e\x02\ \x831\xecK\x10\xf5\x82\x84q\xfeAB\xca\xbbV\x8d\ \x7f\x18\xb8\xa6\x11\x19\x9ez\x11\xb5\x96\xab\xf4_\xbaB\x05,\xa7\ p\x0f~\x1a\xb8\x02\x5c\xcc\xa4\xf86#6\x0eh\xa5\ \xcd\x00p\x018M\xf1\xec\xec\xb69\xcfvV\xeeo\ \x82g\x80\xd2\xa6\x05\xbc\x03\x96\x174\x9b\x06\x0eeR\ \xdc\xf1\xd4<\x08\xdc\xa6\xd8\x84\x8f\xc0\x9aL\x8a\xef\xbe\ \xb5\xb6#\xc6w@\x1f\xc5\x83\x07\x18\xf4\x1d<\x80m\ ;\xe8h\xb6\x02\xd8\xe9\xab9\x1b1\x0c\xe8w\xc4\x0d\ \xf9j\xb0,\x03\xb6o\x11\xbb;\xd0\xfd\x8b\x18\x06\xf4\ :\xe2\xd7;\x99\xa6\xb6\xcf\xf5\xc0\xdcNb\x18\xb0\xd6\ \x11\x7f\x1c\xa0\xed\xea\xdb\x13\xa0\x0d\xc41`\xa9#>\ \x16\xa0\xed\xea\xbb,@\x1b\x88c\x80\xebV\xfa#@\ \xdb\xd57\xf86\x1es%\xf8_\xd2\x18\x90\xba\x80\xd4\ 4\x06\xa4. 5\x8d\x01\xa9\x0bH\x8d\xf3iPi\ \xf3\x1a\x10\x05M\x169$f>\xfa\x96%D\xdfd\ Rl,\xea\xec\xb3\x90hy\x14QDH\xdfP\xfd\ \x96\xab\xf3\xbc\xbf\x04\x1a\x03R\x17\x90\x9a\xc6\x80\xd4\x05\ \xa4f\xde\x1b\x10\xe3\xdf\xe2\xab2)&#\xe8\x94F\ i\xb3\x12\xf8\x10\xa21\xefg@c@\xea\x02R\xd3\ \x18\x90\xba\x80\xd44\x06\xa4L\xae\xb4i\xd9\x97\xab\xc9\ Hb\x80\xd2f\x8b\xd2f\x14\xf8\x0a|U\xda\x8c*\ m\xb6\xa4\xa8\xa5v\x03\x946\xbd\xc0S\xf2\xb7\xca]\ \xf6\xa7\x0fxjc\xb5\x92b\x06\x5c\xa6\xfdf\x8an\ \x1b\xab\x95\x14\x06\x14\xbd\xd3\x0f~\xdf_\x96\x14\x06\x14\ \xed\xf8\xace\x7f\xf0\x9f\xa40\xe0Q\x87\xb1JHa\ \xc0\x19\xa0\xddF\xc7)\x1b\xab\x95\xda\x0d\xc8\xa4\x18\x03\ \xb6\x01w\xc9w\x85O\xda\xdf\xb7\xd9X\xad\xc4\xda&\ W\x8aL\x8aq\xe0@\x8a\xdc3i\x96\xc2\x114\x16\ G\xd0H\x96\xdb\xc7\x80O\x8e\xf8\xe6\xd0\x22\x02p\xad\ \x1c]\xb5{\x19\xf0\xc6\x11W\x1e\x1aUq\xd8\x11w\ \xd5\xeee\xc0\x0bG|\x9f\xd2f\x9f\x87NTlN\ W^W\xed^\x06<\xf4h3T\xa7\x096\xd7\x90\ \xa3\xd94\x1e\xb5{m\x96V\xda\x8c\xe0w\xfe\xe7\x01\ p\x0bx\x05\x04mbnC\x0b\xd8D~\xc9\xed\xf5\ h\xaf3)\x5c\xdbx\xbd\xd7\x01\x03\xf8\x19\xe03-\ \xeb\xc2k\x7f\xb2\xd7m0\x93\xe2\x09p/\xa4\x9a\x9a\ \xb9gkvRf\x1dp\x0c\xf7\xee\xed\xb9\x80!\xaf\ \xd5\x0bo\x03\xecI\xad=\xb4\x7f\x90\x99+L\x01{\ \xca\x9c*+\xb5\x12\xcc\xa4x\x05\xecbn\xce\x04\x03\ \xec\xb25zSz)l\x13l\x05\xee\x97\xed[!\ \xf7\x81\xade\x07\x0f\x81g\x86\x946\x128G\xbc#\ \xb2e\xd1\xc0\xa5L\x0a\xdd\xa9@\xaccsk\xc9\xef\ \xcd\xdb\x81\x0dD\xd8\xc7?\x0b\x9f\xc8\x97\xb7/\x80\x87\ \xf6\xb1:\x88\x9fr\xcd\xdd\xf3\x97\xadc!\x00\x00\x00\ \x00IEND\xaeB`\x82\ \x00\x00\x03\x8c\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x03>IDATx\x9c\xed\ \x9bOh\xd4@\x14\x87\xbfJ)\x22E\xa4\x14\xf14\ \x07\x85^,Z\xbc\x08\x82ZDPQ\x07\xf4R\x0b\ \x8a\x8e\x7f\xc0ko^\x8a\x08U\x0f\x9e\x8b\x22\xb5#\ \x88 \x1e\xa4\x8c\x14\x04\x15E{P\x11\x0fRD\xa4\ \x872\x8a\xf4$\xc5C)\x8b,\x1e\xb2B\xc9fw\ \x93\xdd&oc\xf3\xc1^^&/\xbf\xf9\xed$y\ 3I:\x88\x89q\xbe\x138\x0c\x1c\x05v\x01\xbd\xc0\ \xba\xb8\xfb\x0b2\x07\x8c[\xad\xa6\xa26v\xc4\xc9`\ \x9c?\x0d\x5c\x07\xd4*\x0a\xcb\x9a1\xab\xd5h8X\ \xd7\x00\xe3\xfc\x06\xe0\x01p2-U\x19R\x06v[\ \xad>\xae\x0c\xd6\x1c\xc2\xc6\xf9\xf5\xc04\xffG\xe7!\ \xe8\xebPT\xb0\x16\xe3\xc0`Zj\x84\xe8\x0d\x07\x22\ \x0d0\xce\x1f\x00\xce\xa7.\xa7\x0d\xa85\x02\xaef\xaa\ B\x90*\x03\x8c\xf3[\x81}\x02ZD\x88\x1a\x01\x07\ 3W!H\x94\x01\xdb3W!H\x94\x01\x9b2W\ !H\x94\x01\xe5\xccU\x08\x92\x87Z>U\x0a\x03\xa4\ \x05HS\x18 -@\x9a\xc2\x00i\x01\xd2\x14\x06H\ \x0b\x90\xa60@Z\x804\x85\x01\xd2\x02\xa4)\x0c\x90\ \x16 Ma\x80\xb4\x00i\x0a\x03\xa4\x05HS\x18 \ - cJ\xe1\xc0Z3\xe0m8\xb0\x96\x0c\xf8\x04\ <\x0a\x07\xd7\x8a\x01\x0e8d\xb5\xfa\x13\xde\xd0\xd9B\ \xd2/\xc0C`\x96\x88s\xabM(\x01\xdf\xacV?\ j5h\xc6\x80\x120\x02\xdc\xb1Z\xe5\xfe)RR\ \x03\xca\xc0P\xad7\xae\xd2\xc28\x7f\x0c8A\xe3S\ v\x09\xb8m\xb5\x9a\x8d\x9b;\xa9\x01\x13\x02\x9d\x1f\x04\ \x9e&\xd8\xe5\x94q~\x9b\xd5j1N\xe3\xa4\x17\xc1\ [\x09\xdb\xaf\x06I_\xd6\xe8\x01v\xc4m\x9c\xc4\x80\ y\xab\xd5\x5cB1R\xc4\xeeW\x12\x03\x16\x9a\x10\xd2\ \xf6$1`cj*\x04Ib@\x9fq\xbe'5\ %BD\x19PU-U\xe8\x04.\xa6\xa8E\x84(\ \x03\xbe\xd7i?j\x9c\xefKK\x8c\x04Q\x06|\xa8\ \xd3\xbe\x1bxn\x9c\x1fHIO\xe6D\x15B\xaf\x81\ _\x04\xf7\xd3(\x14\xf0\xde8?I0\x17\xf8l\xb5\ \xfa\x9d\x8e\xbc\xf4\xa92\xc0j\xb5l\x9c\xbf\x0b\x5c\xa9\ \xb3_\x17p\xb9\xf2\xc38\x9f\x866c\xb5\xba\xdfR\ \x02\xe7-p\x8e`\xc26b\xb5z\x11nS\xeb.\ p\x13\xf8\xd9\xca\xc1\xdb\x8c~`\xda8\xdf\x1f\xde\x10\ i@eH\x0f\xd3\xbe\xd3\xdcf\xe8\x02.\x84\x835\ \xeb\x00\xab\xd5\x1b\x82\x0f\x0c\x96S\x14\x955\xdd\xe1@\ \xddB\xa82\xf3\xdb\x0b|MKQ\xc6\xbc\x0c\x07\x1a\ V\x82\x95olv\x02\x97\x08\xd6\xd5\xf2\xca$\xf08\ \x1c\x8c\xb5\x1e`\xb5*\x01\x13\xc0\x84q~\x0b0\x00\ l&\xdd5\xc5\x99U\xc8q\x0fx\x05\xccZ\xad\x22\ \xff\xbc\xc4KbV\xab\x05\xe0Y\x8b\xc22\xc1j5\ C\x03#\xf3\xba*\xbcL0\x22\xa7h\xf1\xed\xf6V\ V\x85\xa5\x98\x07\x8e\xff[\xf73\xcek\x82\x8a\xb4\xea\ \x0a\x1f\x87\xbc\x8d\x80y`\xff\xcaEO\xab\x95#\xf8\ \x9cw\xa9\x99\x84y2`\x118b\xb5\xaa\xaa\xbb+\ 5\xcb\x19\x9a8\x1d\xf2b@\x19\x18\xb6Z\xd5\xacG\ \xacVO\x80\xb1\xa4\x89\xf3r\x0d\xb8a\xb5\x8as\xe7\ \xb9\x06\xecI\x928\x0f#\xe0\x1dA\xc7\x1aRyR\ u\x96`:\x1f\x8b\xbf{r\xae\x81\x0aQK\xaa\x00\ \x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x05Z\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x05!IDATx\x9c\xed\x9b]h\x1dE\ \x14\x80\xbf\x84K\x08RJ(R\xa4\xd6\xc1\x07E\xad\ (\x22\xa5BU\xac\xb6\xfe4\xad\x83!\xad\x0f\xfe\x0c\ \x88\xd1R\x8b\xd6PP\xa1\x82\x0f\xa2\x22\x08RQ[\ \x11\xa5\x1d-\xd5V\xad\x8e\x8d?\x0f\x96h\xa1\x0fE\ \x82\x14\x7f\x90\x8a\xc4\xa1\x14)\xa5\x14\x09R\xc2%\xf8\ 0s\x9b\xeb\xde\xb9\xb9\xbb{w\x92,\xc9\x07\xcb\x86\ \x9d;g\xce\x9c\xcc9{v~:\xf0(c\x17\x01\ \x0a\xb8\x0a\xe8\xf2W\x05\xe8\xf4W\xfd\xdf5*\x89{\ \x8d\xe4\xef\x8ad\xc2_\x00\xd5DY5p\x9f\xf0\xf7\ *p\x1e\xf8\x1d\xd8\xad\xa58\x0b\xd0\x01\xa0\x8c\xbd\x05\ \xf8\x14X\x1cI\xe9\xd9\xc6\x19\xa0_K\xf1C\x872\ \xf6\x12\xe0\x17`\xd1\x0c+5\xdd\x9c\x03\xae\xed\x04\xb6\ 2\xf7:\x0f\xd0\x03\x0cv\x02kfZ\x93\x19dM\ \x05\x18\x06\x96\x07\x0a\xab\xc0#\xc0q&\x83I\xfd\x95\ \xfcm+B\xf5Z\xd1*\x98N\x15\x94k\x81{\x19\ \xb0\x87\xc6@\x0d0\x5c\x01\x9e\x05\x96\x00\x0f$\x0a+\ \xc0\x8b\xc0\xcdZ\x8aS\x19\x15\x9f\x15(c\x17\x03\x1f\ \x13\xee\xfcG\xc0\xb6\xda[\xa0\x0b\x18\x22\xec\x0e#\xc0\ \xedZ\x8a\x7fb)\x1a\x03e\xec\x02\xe0;`E\xa0\ \xf80\xb0VK1\xde\x09\xa0\xa5\x18\x07\xfa\x81\x1f\x03\ ?\xbe\x118\xe0\x8dT\x0a\x94\xb1\x15`\x1f\xe1\xce\x8f\ \x00}\xbe\xcf\x93\xfe\xe3\xff\xc3\xeb\x80?\x02\x95\xee\x02\ \xdeS\xc6\xc6Jn\x0a\xc3\xeb\xb8\x13X\x1f(\xfe\x13\ XW?\x9a\xff\xd7!-\xc5i`-p:P\xf9\ !\xe0\x95\xe2T\x8d\xc6\x0b\xc0@\xe0\xf9i\xdc\xb0\xff\ \xbb\xfeaGH\x822v9\xce\x7f\x16\x06\x8a\xb7j\ )\xdehW\xcb\x18(c\x1f\xc7\xfd\xf7\x93#u\x0c\ X\xad\xa58\x96\xac\x134\x80\x17v\x0f\xf0\x05\xee\x9b\ \xa0\x9e*\xf0\xa0\x96b\x7f{\xea\x16\x8b2\xf6>\xe0\ \x00\x8d\x11\x7f\x1c\xe7\xf3_\x85\xea5\xf5i-\xc57\ \xc0\xa34\xbe\xbb+\xc0\x1ee\xec\xaa\xbc\xca\x16\x8d\xff\ \x96\xd9Kc\xe7'\x80M\xcd:\x0f-\xbe\xd8\xb4\x14\ \x1f\xe2\xf2\x84$\xdd\xc0Ae\xec\xf5\x19u-\x1ce\ \xec2\xe0 pQ\xa0x\xbb\x96b\xf7T\xf5\x9b\xba\ @\xa2\x91\xd7\x81\xa7\x03E'\x81[\xb5\x14\xa3i\xe4\ \x14\x8d2v)p\x04\xb8\x9f\x81E\ \xc5\xb7\xf1\x01\xe1\xce\xff\x84\x8b\xf8\xa9:\x0f\x19\xa7\xad\ |\x06u/.\xa3J\x22\x81\x9d\xd3\x90-\xee\x006\ \x04\x9e\x8f\xe2\xb2\xbcsY\x84eV\xd6\x7f\x196\xcb\ \x16\x07p\x99X\x14\x94\xb1\xcf\x03O\x04\x8a\xce\xe0\x86\ }\xe6\xaf\xd6\xd41 \xa0\xcc\x0a\x5c\xb6\xb8 Q4\ \x01l\xd1R\xec\xca+\xbbI{\x03\xc0;\x84\xb3\xbc\ \xbb\xb5\x14G\xf3\xc8\xcdm\x00\xafT/\xee\x1d\x1c\xca\ \x167j)>oG~];\xeb};\xc9\x18S\ \xc5\xf9\xfc\xa1\xbc\xb2\xdb\xf2W\x9fa=F8[\xdc\ \xeb3\xb4\xb6P\xc6\xae$<\xa9Q\xcb\xf2rw\x1e\ \xda\x1c\x015\x94\xb1\xcf\x00\xaf\x06\x8a\xce\x02\x0f\xfb{\ \x1ezp\x11?\x94gl\xd7R\xbc\x9cS\xee\x05\x0a\ 1\x00\x802v\x07\xf0TQ\xf2Z\xf0\xb6\x96bK\ \x11\x82\x8a|e\x0d\x12\xce\x16\x8b\xe6\x13\xdcT~!\ \x146\x02\xe0B\x866\x04\xdcQ\xa4\xdc:\x86\xc9\x90\ \xe5\xa5\xa1P\x03\x00(c\x17\x02\xdf\x037\x14,\xfa\ 8p[\xd6D\xa7\x15\x85\x1b\x00@\x19\xbb\x04\xf8\x8d\ \xc6\x19\xa5\x11\xdc\x02\xe5Tt\xe3&b\xeb\x19\x03\xae\ \xd1R\x9c,F\xc3I\xa2\x18\x00@\x19\xfb\x17 \x12\ \x8f\xaf\xd4R\x84&]\xeb\xeb]\x01\x9cH<>\xa5\ \xa5\xb8\xb4H\xfdj\xcc\xfaY\xde\xd8\xc44@\xd6e\ \xb0\x19\xa1,\x06\x88f\xcc\xb2\xb8\xc0\x9c7@4b\ \x1a \xcd\x92\xf9\x8cS\x96\x110\xe7]\xa0\x94\x06\x98\ w\x812P\x16\x03\xccy\x17(\xa5\x01JAYR\ \xe1hL\xb7\x01\xf2.\x9d\xcdy\x17(\xa5\x01\xe6\xf3\ \x8020\xdd# \xfa\xf2yV\xa6;\x08\xe6m/\ \x9a;\xcd\x8f\x80\x88\xb2\xc7\x03\xcf\xba#\xb6\x97\x8b\x98\ \x06\x08\xed\x17\xca\xbbXRJ\x17\xf85\xf0\xec%\xbf\ \xdc=k\x88i\x80wit\x83\x1e\xe0\x882vH\ \x19\xdb\x9ba?Q\xf9\x12!\xbfy\xf2\xb5&m\xf6\ \xe2\x16QO(c\x9f\xf3'\xd7\xa6\x22\x9a\x01\xa2-\ \x8dA\xcb\x93(\xf5\x8c\x03\x067jFq\x87\x1b\xeb\ 9\xa6\xa5\xb8\xa9p\x05\x89\x9c\x09\xfaS\x19}@\xab\ \xbdB]\xb8\xado\xdf\xe2V\x96\x93\x942\x08\x02\xa0\ \xa5\x18\xd3R\xf4\xe1\xf6\x17\x1eNQ%\xe4\x0e\xe5\x8b\ \x01I\xb4\x14\x87\xb4\x14\xab\x81\xeb\x80]@\x96CX\ \x85m\x88H2\xed\x1fCZ\x8a\x9f\xb5\x14\x9b\x81\xcb\ \x80\xcd\xb8\xed\xad\xad\x88vb-j\x10L\x8b\xdft\ \xb9\x09\xb8\x9f\xc6\x8d\x97\xe0\x0e:\x7f\x16\xa3\xedYa\ \x80\x1a\xfe\xac\xdf\x06`#p5\xee\x80\xf3[Z\x8a\ \xf7c\xb5\xf9\x1f\x22\xa8r\xbfOa\xee\xfa\x00\x00\x00\ \x00IEND\xaeB`\x82\ \x00\x00\x04_\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x04\x11IDATx\x9c\xed\ \x9aK\x88\x1cE\x18\x80\xbfm\x86E\x96!\x84\x1cd\ \x0fK\x91D0\x07/\x1e\xbc\x06$xQ\xb1\xd8\xe4\ \x10D\x02Z\x01_`\x14]\xc4\x83\x04\x11O9\xe4\ a\xc0\x98\xc7\xa1$\x01\x09\xc9\x92G\xa99\x89bN\ >r\xd3\x83\x82\xacZ,\x22\x12$\x84 \xcb\xb0\x0c\ \x1e\xba;\xe9\xad\xae\x9ei\xd35\xd3\xf3\xe8\x0f\x9a\xe9\ \xfe\xeb\xef\xae\xbf\xfe\xa9\xfe\xab\xba\xea\x87\x86\x86\xa9f\ \xa6\x9f\x822v\x0e\x98\x05\x22\xe7\xc8\xd2*\xb8\xbdH\ \x9ee\xbd\x84N\x15\xfe\xd2R\x14\xd6\xe1u\x802v\ ;p\x00X\x04\xb6\x0e\xc6\xae\xa1q\x138\x0f\x1c\xd5\ R\xac\xb8\x85\x1b\x1c\xa0\x8c\x9d\x05\xde\x07\xde\x22\xfe\xd7\ '\x89\x0ep\x0c8\xa8\xa5\xe8\xa4\xc2\xbb\x0eP\xc6\xb6\ \x81\xab\xc0\xae\xe1\xdb6T\xae\x03\xcfh)nC\xe2\ \x00el\x04|\x06\x22<_\x7f\xc9\x86\xc2$\ R*\x06L\x13]o\x0f`\xf2\xb6\xc6\xd3\xad\x7f\x97\ n\x84g\xa1\x90\xc9\x5c&\xf3\xb6)\x22\xde\x07te\ s\x1e\xddq\xa7M\xfe\x95\xefD\xc0\x1d\x8f\xb2\x18\xbc\ =Cg\x81\xbc\x03\xd6\x22`\xd5\xa3\xfc\xfc\xe0\xed\x19\ :\xbe6\xadD\xc0\x17\x9e\x82W\x94\xb1\xcf\x0d\xd8\xa0\ \xa1\xa1\x8c\xddK\x9c\x04\xe2rq&\x89\x8e\xbf\x90\xcf\ \xa4\xe8\x02\xa7\x81\xc3\x80\x05\xd6\xc7a\xc7(I\xf7I\ Y\x00\xde\x01^\x22\x1f\x04\x7f\x07v\xa49B\x8b\xc0\ \xe5\x1e\xcf\xfd\x97x\xc3\xb4C\xf0e\x93(cw\x01\x87\xd8\x18\x5c\ #\xe7<{\xdd*Y\xd6O\xb7\xed\xd1O\xd9\xad\xa5\ \xb8\x92\xcd\x12;L\x9c\x1eW\x85W\xb5\x14'\xb3\x02\ e\xec+\ xZKq-y\xd6\x03\xc0\x1f\xc0\x83\xf7\xf9\xac\x90\ X`IK\xb1\x9c\x15\xe6\xde\x0f-\xc5%e\xec\xe7\ \xc0\xb3\xc0n\xe0a\xe2\x84\xa2l\xbep+\xf3\xebN\ 1_\x06\xae%\xe7\x8b\xf8\x1b_\x94bWT\xde\xef\ <\xfd\xcd\xc6\xa6\x0eq\xecZ\x01.\x02\xcbZ\x0aw\ \xd2\xd7?Y\xda%\x89\xb2\xe9\xf1(\xf0\x9d\xa3\xd2\x01\ \x1e\xd2R\xac*c\xbf\x06\x1ew\xca\x8f\x03\xef\xd2\xdb\ \x01\xbekWv\xf7\xbc\xca\xe8\xf4\xbf\x1d\xe0\xa2\x8c\xfd\ \x01x\xcc\x11\xbf\x07,\x03?\xb21\xcet\x81G\xb4\ \x14?W\xad7\x14!>z\xce\x90w\xc0\x8b\xc06\ \xf2S\xcf\xeb\xa3\xd4x\x08\xb3\x1ep\x1e\xb8\xed\xc8\x16\ \x88\x130]\xce\x04\xa8/(\x95\x1d\x90d]_(\ \xa1z\x13\xb8T\xb5\xbe\xd0\x84Z\x11:UB\xe7\xac\ /\x0a\xd7M\x10\x07$\xa9\xa87z\xa8t\x19\xc1\xee\ \x0fa\xd7\x04?\xeeQ6r\xc1/%\xa4\x03.\x00\ \xff\x14\x94\xf5rN\xad\x04s\x80\x96\xe2\x0ep\xd6S\ \xb4\x0a\x5c\x09UOhB/\x8b\x7fD~\x95\xf9\xc3\ \x82<\xdd\x91 \xa8\x03\xb4\x14\xbf\x02\x07\xb9\xe7\x84\xef\ \x81\x13!\xeb\x08M\xe5\xa9\xb0\x0fe\xec\x16\xe2\xc5\x88\ \xd5qXEjh\x98b\xfe\x03\xd7g\x05\x92\xc5\x1b\ 1\x14\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x05S\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x05\x05IDATx\x9c\xed\ \x9a_h\x1cU\x14\xc6\x7f\x19\xc7\xb8\x14\x09EJ\x1f\ \x82\x8c\x22A\xa4\x8ao\xc6(\xa2\x0f\xfa\xa2\x94!\x94\ \x22*\x8a\x0c\xe2\x93\xa0\xa5\x16\xb4\x88\x16\xc1GAE\ \xdf\x22\x0e\x22R(\x222\x14Q\xec\x83\xf4!\xd6\x80\ \xa1j\x95\xf8\x87\xb6^$H)\xa5\x8a\x84%\x99\x16\ \x1f\xee]\xb2;sv\xf7\xccNf\xb2&\xfb\xc1\x92\ \xec\xd9s\xef9\xf7\xdc{\xcf\x9d\xf3\xcd\x85\x11F\x18\ a\x84m\x8c\xb1(1\x1e\xf02\xf00\xe0\x03\x9e\xfb\ \x90\xf9\x1f\xf7{;\xb2\xbfg\x91\xd5/\x8a\x22\xed\xaf\ \xbaO;\xd2\xb6\xbf)\xb0\xea>\x97\x813\xc0\x11\x1f\ 8\x02\xbcV\xce\xcf\xff%\xf6\x02\xa9\x07<\xb9\xd9\x9e\ l\x22\x1e\xea\xb7\x84\xb7:\xc6\xb7\xf3\xe0\x01|)\xc9\ \xa4\xc0Mu{R\x13\xfe\xa03\xb1zb\x96\x8d\xc3\ `\xb9\x1e\x7f\xeaE\x94\x98\xacH\x5c\x01\xbd:\x98\x01\ \xf6\x00\xf3q\x18,E\x89\x99\x06\xee\x03\x1a\xc0uN\ m\x0d{\x1c\xa5\xc0E\xe0S`\x05x\xc4\xe9}\x11\ \x87\xc1\xe5.\xfdO8\xbd\x148\x8e\x9d\xad}\xc0$\ 0\x0e\x5c\x03\x5ci\xeb\xbf\x09,\xc6ap2J\xcc\ \x14p?\xb0\x14\x87\xc1\xbcvLcQb\xce\x017\ \xb7\xc9\xd28\x0c\xae\x15\x9c;\x00\xbc\xe5\xbe6\x9d\x83\ \xfb\xe8\x9fD\xcf\x02\xcb\xd8@\x01\x18\xe0\x9e\xec*\x8b\ \x12\xb3\x13\xf8\x16\xb8\xd5\x89N\x01\xbb\x80)\xc58>\ \xc1\x1ek\x0d\xf7\xfd\x8d8\x0c^\x15\xc6\xb0F\xe7\x16\ XR%A\xf7\xb0t\xb8M\xd4\x00\xf6\xa3;An\ a}\xf0\x00\x01\xf0\x84\xa0\xb7\x9f\xf5\xc1\x03\xcc\xa0\x1b\ |\xabm\xa3\xed\xfb\xc1(1\xe3\x8av\xbe\xf6\x14\xf0\ \x81\x09\xa5\xae\x06\x92\xdd\x1b*\xee\xbf\x94\xa2G\xfe\xb1\ t\x95\xfc\xa3\xa7\x84U\xa5\x0di\xc6\x9a\x8avW\x0b\ \xd8\xc8\xa1H\x12\xcc\x06k\x09x\x1a\x9b\x14}\xe1\xf7\ \x14\xf8\x07\xd8\x0d\xcc\xf5\xe9\xab\x9b\xec9l\x22\x9d\xe8\ \xe2\xeb*\xf03\xf0!pg\x9f\xbeD\x94*V\xe2\ 08\x0d\x9c\xee\xa5\x13%\xe61A\xacup%\x0e\ \x83\xa4\x9f\x92p\xbc\xa9m\x14\xd9\x02U?5\xe6N\ \x9e\x1a\xa0N\x82\x1b\x8d\xaa\xednx\x12\xdchh\xed\ j\x92l\x99\xfe\x87\xbe\x12\x1c4\x00j\x0c{\x00*\ G\x91\xa58\xe8lT>\x8bel\xd4\xb1\x02\xb4\xce\ Iz\xa9 +c#\x87\x22\x01\xa8z&\xafT\xdc\ \xbf\x88:\x02\xa0\x9d\xc52\x18\xd8F\x91\x1c0\xa8\x11\ m\xe0\xca\x04*kC=Y\xdaGa1\x00Qb\ \x02\xe06\xe4B\x06,\x11\x229#\x15/R\xe1\xe3\ G\x89\xb9\x17\xd8I\xf7\xc9:#\xf8\x96v\xb1\x9b7\ \xa0Q\x8a\xc3 \x8d\x12c\x80;\xda\xc4S\xc0ot\ \x1f|\x0b\x12\xbdvV\x90\xfd.\xc8\xe6\xb0\x83\xef\x85\ &\xf9\x80\x1a\x94+\xaaH\x0ex\xcau\x0c\xb0\x80\x0d\ \x9e\x86t\x98\xc4\x16L\xad\xd5\xf0>\x96\xc1\xc9\xe28\ \xf0\x1e\xebT\xd7\x0f\xf4\x1fI\ \xb1={\x1e;\xeb\x7f\x01_I\xce9\xd97\xc0\x05\ \xa7\xbbT\xa0\xff\x14\x98w\xbe-\x14i[$\x00\x1f\ \x03\xb3\xd8Y?\x04\xec(\xd0v\x16\xbb}&\x81\xa3\ n_w\xc0\xc9>r:{\x80G\xd1'\xb3\x1d\xc0\ \x01\xe7\xdb,pT\xeb\x98*\x07D\x89\xf1\x81\xe9\x8c\ \xf8\x14\x96$\xbd\xbbK\xb3\x14\xf8\x1b\xf8\x17x\xa7M\ \xeea\xf9\xbe,s;C~B\x9e\xc5\xbe\xa3\xb8^\ \xe8\xbf\x95\x98\xbf\x07^\xa13?MG\x89\xf1\xe30\ \xe8\xbbJ\xb5\xa7\x80G~\xbf{q\x18\x1c\x03\x8e\xf5\ j\x18%f\xaf \x96VOC\x90]\x8a\xc3\xe0\x83\ ~\xceE\x899\x9c\x11\x8dS\x03!R\x86M\x92\xec\ J\xfd\x0djC\xa2\xe8\xd4\x8ehu\xcb\xd4\x11Z\xf6\ gP\x1b\x95\xf0\x01\x1b\x19\x80Am\x16i\xa7^\x01\ U\x179C\xcd9\x14\x09@\xd5\xf4T\x1d\xbcA\x0e\ \xc3T\x0e\x0f}\x00\xb6$\xeaX\x9eE*\xce\xda1\ \xda\x02\x9bat\x98P\xea\xdd\xa0{\x07\xbf\x0b\xf91\ 6\xc5\xd6\x01\xa5\xe0.Nt{9\xda\xc4\xbe<\x1d\ \x18>\xba\xa5'\xd1\xe27\x02\xe7\xb0\xd5[\xafv\x12\ \xd1\xa1e\x80_\xc7V\xa1\xbdV\xea\x05t\xbc\x84\x08\ m\x00$h.4xt\xde\xfahaMiCj\ \x9b\xc5nA\xa6\xa6\xc46+\x07\x94\xde\x1a}\xd0d\ #)1WW\x9f\xc8\x88\xc5\x97\xf2]\x9ci\xdf\xa7\ +\xc0\xe7\x82\xde\xd7t\x12\xa3\x17\x9d\xae\x06\x7ff\xbe\ \x7f\xa6\xe1\x02\xc0n\x01-\xb5\xf58\xf0\x92\x15l\x8ab{u\x15\xca\ \x0d\x02\x1d\x04$\xc1\x8fd\xc2\xd9q\xff\xb5P\xce7\ \x84\xe6\x1d\xb23\xfd*\xe0\x06\xa1\xec\xbe(\xb6{R\ \xbf\x97x\xda\xdd\x0e\x1c*\xa3X7\x88b\xbb\x18\xd8\ \x09l\x00\x96\x01\x93\xc0Q\xe0#\xa3\xd5\xbf\xbe\xbaC\ \x99\x86\xf6\x03/W\xa0\xd3$p]{\xc8\xf4\x13Q\ l\x87\x81\xbf\xc9\x7fq\x16\xb8\xd9\xa7Gv\x0e\xd8Z\ \x91^\xa3\xc0\x9a\x8a\xda\x0aa)\xb2\xd5*\xe0z_\ \xe5\x8b\x04D\xb1]\x0eT\x19\xd1I\x93i\xd5\xc8[\ \xb1\xd2\xf0\xfa%i\x0b\xd8J8<\xee\x06\x83r\x8b\ C+\x8eo\xae\xea\x98\x04\x1f\x14\xca\xcc\x02{q\xf9\ \xbf<\xec'\xff-\x8cE\xb1]a\xb4:\x15P\xb0\ ,B\x04x-\xa4\x09\x17g\xd1\xf5B\x99\x93F\xab\ 7\xa4\x06\xa2\xd8\xae\x03v\x08\xe2\xad8\xa7\xa9\x9f\x18\ \x09\xc8\xbd\x04\xb4M~\x130,\x94\xf9.\xf0\x80\xaf\ <\xb2A\xcc\x03!\x02\xbc\x16\xd2&@2\x7f\x80\xef\ \x03\x0f8\x8c\x1b&yX\x1d\xc5vY\xa0~Y\x94\ # \xf1\xfe\xee\x17\xe4\xd3\xc8\xa1/\x00F\xabs\xc8\ )\xf1\x06\xd5-\xad\x12B\x04\x5c\xe3\x136p\xa9o\ \xe9-\x1d1ZI\x93_\x1a\x9f{d[\x0a\xd4/\ \x83\xd2C\xc0\xe7\xb0|ZP\x89\x83\xc8\xab\xc4=\x89\ \x95\xf5\x0bW\x05\xe4^\x82\x9a\xc0\x07\xc0\x97I\xc1&\ n<\xb7\x80)\xe0\x9f\x22\x1a\x18\xad\xc6\xa3\xd8\xde\x08\ \x5cK\xa7/\xd1\x02.\xf4y\xdb\xac\x94\x054\x8dV\ 3\xc0\xd9\xb2Z$s\xc1\xb9\xb2\xed\xf4\x80JV\x81\ :CZ\xbe\xdbX\xf0\x04\x84<\xc1\x05O\xc0\x15?\ \x04J\xc5\x02W\x02\x01W\xbc\x05\x8cD\xb1]$\x09\ \x17\x02\x01\xdex\x1f\xe7\xdb\x88e:\x92\xa2Ql\x9b\ 8F\x9b\xc9\xd5>\x13T\x14-.9R3F\xab\ \x0b]\xd4\xed\x1a\x89\x879Z\xa0\xe8(\x82\x8f\x92M\ \x8a\xbe\x09\x01\xdce\xb4:\xdb\xbe\xd15\x01\ I\x0a\xfd7@:\x10\xf5\xb1\xd1\xea\xb1\x1e\x94\xebF\ \x87\xa5\xc0\xcf\xc0X\x17\xd5\xce\x03\xf7\x1a\xad~O\xdf\ \xece\x158\x80\xdc\xf9q`\x8f \xab\x0cI\xf2e\ s\xf2\xbc\x22\x98\x02\xb6d;\x0f]\x12\x10\xc5v\x1b\ \xf0\x84 \x9e\xc5\x8d\xfb\xf3\xdd\xb4\xd9+\x8cV\xa7\x81\ \xbb\x09\x930\x05l6Z\xe5f\xae\x0b\x13\x90\xe4\xf7\ \xdf\xf3\xd4y\xd7h%\x9d\x1a\xe9\x0b\x12\x126 \xa7\ \xf4\xda\x9d\x17S\xfb\xddX\xc0\xfb\xc8;\xad\x7f\xe1\xf6\ \x0f\x07\x0e\xa3\xd5\x19\x1c\x09\xd9%\xf7<\xee\x7f\x0c\xde\ }\x8dB\x04D\xb1}\x0ay\x83\xa3\x05\xecJ\x9c\x95\ 9\x81\xd1\xca\x02\xeb\xb8\xb4As\x06\xd8 \x99}\x1a\ \xc1U \x8a\xed\x18n\xd6\x97\xe2\xeeW\x8dV/\x15\ \xd4\xb5\xafH\x82\xa6\xf5\xb8\x03\x9d\x85^\x88\x97\x80$\ <\xfe\x09y\xf3\xe4$pg\xc1\xdd\xa3y\x89\xd0\x10\ x\x01\xb9\xf338\xd3\xafm\xe7\xc1c\x01QlW\ \x01\xbf\xe0\xfe,\x95\x87\xe7\x8dV\xd2\xc9\xf1\xda@:\ ->\x0c|\x88\xdc\xf9c\xc0\xdb}\xd2i\xa0\x90\x86\ \xc0+tf_\xd2\x98\x02\xa2\xba\xfeM.\x8b\xbc\xc3\ \xd2\x1bqi1\x09\xcf\xa6\x83\x89\xba#\x9b\x13\x5c\x82\ [\xf2\x96\x0b\xe5\x0f\x19\xadju\x18:\x84,\x01\x06\ \xd9\xd7\x07\xb7]>\xcd\xa5L\xcfl\xe6{+u]\ \x00\x9e1ZU\x96\x14\xe9\x07.\xc6\xf3\x81@\xa7\x8d\ n\xcf\xfb(*\xcc\x0a\xf5\x03\xe99\xe0\xb59\xd3b\ \x0e\x91& \xb4\xcb\xda\x0b\xe6\xfdJ\x91=\xceR5\ \xe6=\x01\xe9\x9c\xde\x09\xaa\xdf+\xec\xeb\xd6X\x15\xf8\ \x1f\x89JT#\x88-\xd1\xbe\x00\x00\x00\x00IEN\ D\xaeB`\x82\ \x00\x00\x04!\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x03\xd3IDATx\x9c\xed\ \x9bOH\x15A\x1c\xc7?\x86<\x22$\x22D4H\ \xc4\xa2.\x11\x92\x07\x11\x22\xfcC'\xc3kl\xd0V\ K\xb7\x82\x8a\xa0\x88\x88\x88G\x06A\x87\xa0\x9b\xb1\xd4\ \x86m\x8a\xa7\xf0\x14\xf9H0\xbcE\x07/\x85\x89<\ \xa8D\xc4\x83t\x88\x88G\x87\x9d\xb0\xec\xbd\x9d\xd97\ \xb3;\xc6{\x1f\x10\xc4\xdf\xcc\xef\xf7\x9b\xef\x9b}\xfb\ \x1bg\xa6\x81\x8cp|w\x1bp\x14\x18\x04\xba\x80\x0e\ `\xa70\xaf\x03K\xc0{`\x1a\x98\x0d\xbd\xa0\x94E\ ^\x0di\x07p|\xb7\x19\xb8\x04\x9c\x07Z\x15\xbb-\ \x03\x8f\x81\x87\xa1\x17\xac\xa6\x95\x1b\xa4(\x80\xf8\xc4/\ \x02y6>\xe9\xa4\xac\x03\xb7\x80Gi\xcd\x88T\x04\ \x10\x9f\xfa80`\xc8e\x018\x99\xc6l0.\x80\ \xe3\xbb\xedD\xcf\xf1~\xc3\xae\x17\x80\xc1\xd0\x0b\x8a&\ \x9d\x1a\x15\xc0\xf1\xdd\x16\xe0-\xe6\x07\xff\x9b\x05\xa0\xd7\ \xe4L\xd8f\xca\x91x\xe6\xc7Io\xf0\x08\xdf\xe3\x22\ \x96\x11\x8c9\x02.\x03}\x06\xfdUb@\xc42\x82\ \x91G@L\xfdO@\x93B\xf3/\xc0\x13\xa2\xef\x89\ %\xf1\xb7\x0e\xa2\xfa\xe0,\xb0G\xc1\xc77`_\xe8\ \x05+\xc92\xfd\x97F]\x07\x82+\xc8\x07_\x02\xee\ \x03wB/\xf8\xbe\xc9\xb6\x08\x14\x1c\xdf\xcd\x03\xb7\x81\ k\xc4\xcf\xce&\x11\xf3Fu\xe9n\xa0=\x03\x1c\xdf\ \xcd\x01\x9f\x81\xe6\x98f%\xe0t\xe8\x05\xcf\x15}\x9e\ \x02\x9e\x11/\xc2\x0a\xb07\xf4\x82\x1f\xaa\xb9\x96\xc3\xc4\ w@\x1f\xf1\x83\x07\x18Q\x1d<\x80h;\x22i\xd6\ \x02\x1cS\xf5Y\x09\x13\x02\x0cJ\xecE\xa2j0)\ y\xd17\x8e\xe3U\xf8\xfd\x0b\x13\x02tI\xec\xa3\xd5\ LS\xd1gT3\xb6\x14\x13\x02tJ\xec\xaf5|\ \xcb\xfavh\xf8\x06\xcc\x08\xb0Kb_\xd0\xf0-\xeb\ \xbb[\xc37`\xe65(\xf3\xf1S\xc3\xf7\x1a\xd0\x16\ c\xd7^!\x9a\xaa\x03RA,\x81\x97\xd3\x8ca\xb2\ \x14\xfe/\xa9\x0b`;\x01\xdb\xd4\x05\xb0\x9d\x80mj\ ^\x00\xe9j\xd0\xf1\xdd\x0f@{L\x93\xed\x12\x17\x9b\ \x97\xbeYR\x0c\xbd\xe0`\x5c\x03\x95: \x87|\x90\ q\xe8\xf4\xd5%'kP\xf3\x8f@]\x00\xdb\x09\xd8\ \xa6.\x80\xed\x04lS\xf3\x02\x98X\x0e\xb7\x85^\x90\ \xea\x92\xb5\x12\x8e\xef\xb6\x02_u|\xd4\xfc\x0c\xa8\x0b\ `;\x01\xdb\xd4\x05\xb0\x9d\x80m\xea\x02\xd8\x0c\xee\xf8\ nNl\xaeZ\xc3\xca\xbf\xc5\x1d\xdf=\x02< :\ 7\x88\xe3\xbb\xb3\xc0\xd5\xd0\x0b\xdee\x9dK\xe63\xc0\ \xf1\xdd.`\x86hW\xb9Q\xfc\xf4\x013\xc2\x96)\ 6\x1e\x81{\x94?L\xd1$l\x99bC\x80\xb8=\ }\xed\xfd\xfe\xa4\xd8\x10 n?/\x93\xf3\xc1\x7fb\ C\x80WU\xdaR\xc1\x86\x00\xd7\x81r\x07\x1dW\x85\ -S2\x17 \xf4\x82\x05\xa0\x07xA\xb4\xf3\xbb,\ ~\xef\x11\xb6L\xb1R\x07\x84^\xb0\x0886bo\ \xa6^\x0a\x1b\xf0\xb1\xc3\x80\x0fk\xb1U\x04X\x93\xd8\ \x0f\xeb&\xa1\x81\xacr\x94\xe5\xae$\xc0G\x89\xfd\x9c\ \x82\x8f\xb48#\xb1\xcbrW\x12`Nb\x1fv|\ wX\xc1\x8fQDLY\x5cY\xeeJ\x02L)\xb4\ \x19\xcbR\x04\x11kL\xd2\xac\x84B\xeeJ\x87\xa5\x1d\ \xdf\x9dF\xed\xfe\xcfK\xe0)0\x0fh\x1db.C\ \x0e8D\xf4\xc8\x9dPh_\x08\xbd@v\x8cW\xb9\ \x0e\xc8\xa3&\x80\xca\xb4\xcc\x0a\xa5\xf3\xc9J\xaf\xc1\xd0\ \x0b\xde\x00\x13:\xd9d\xcc\x84\xc8YJ\x92:\xe0\x02\ \xf2\xd3\xdb[\x81\x22Q\xaeJ(\x0b nj\x0dQ\ ~!\xb3UX\x05\x86\x92\xdc*KT\x09\x86^0\ \x0f\xf4\xb35gB\x11\xe8\x179*\x93\xb8\x14\x16\x01\ \xba\x81\xc9\xa4}Sd\x12\xe8N:x\xd0\xbc3\xe4\ \xf8\xee\x00p\x13sWd\x93R\x00\xee\x86^P\xa8\ \xd6\x81\xa9ks\x9dD\xef\xe6^\xe0\x00\x06\xce\xf1W\ `\x8d\xa8\xbc\x9d\x03\xa6\xc4\xb2Z\x8b_\xfa:\xe0h\ \xde\xe0w\x1f\x00\x00\x00\x00IEND\xaeB`\x82\ \ \x00\x00\x02\xd8\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x02\x8aIDATx\x9c\xe5\ \xda=n\x13A\x18\xc6\xf1\xbfW\x11E*\x0aD\x85\ \xb6\xa2\xe4\x16`\xd1m:j4\x07\x00\xc2\xc7)P\ \xc2\x0d\xe6\x02TL\x0d\xe2\x06\x08\x10B\x08QX\xa3\ \x08!\x14\x89.eDa\xcf\xcaql\xef\xee\xec|\ \xef\xd3\xda\xb33\xefO\xb3\xb6w\xfc\xc2\xc0\x08\xa5\xef\ \x0e\x1d\xe33B\xe9\xc7c\xc6W\x03'{\x0d|\x11\ J?\x183\xa9\xe3\xbc\x11J?\xb1\x1d\xdc\x1b`U\ \xfcK\xe0\x10xW\x0aB/\x80\xb5\xe2MRC\xa8\ \xb0D\xe8\x04\xd8R\xbcI\x11\x08{\x01\xf6\x14o\x92\ =\xc2N\x80\x1e\xc5\x9bd\x8d\xb0\x15`@\xf1&\xd9\ \x22\x5c\x03\xb0(\xde$K\x84+\x00#\x8a7\xc9\x0e\ \xa1\x05pP\xbcIV\x08\x158-\xde$\x1b\x84J\ (}\x0bx\xe4a\xd2,\x10*\xd9\xd4\xe7\xc0}@\ {\x984y\x84\x0a@6\xf5/&\x8a0[\x7fe\ \xf5\xa8\xfb\x11\xb8\xe3a\xe2\x0b\xe0H6\xf5{\x97\x17\ \x15J\xff\x03nZ\x0c\xbd\x04\x8e\xaf|\x0d\xae\xed\x84\ 3\x07k\xdbL\x8a;\xe1\xf8\xda\x0f!\xd9\xd4?\x99\ \x0e\xc2\xf6\x9f\xc2SB\xd8\xf904\x15\x84\xbd\x8f\xc3\ S@\xe8<\x10Y!\xcc\x81\xdf\x1e\xe6\x8f\x8e\xd0\xeb\ HL6\xf5\x0f\x96;\xa18\x84\xde\x87\xa2\xa5\x22\x0c\ :\x16/\x11a\x10\x00\x94\x870\x18\x00\xcaB\xb0\x02\ \x80\x16a\x0e\xfcq\xb7\x9c6\xc1\x10\xac\x01\x00dS\ \x7fg\xb9\x13\xb2E\x18\x05\x00\xf9#\x8c\x06\x80\xbc\x11\ \x9c\x00@\xbe\x08\xce\x00 O\x04\xa7\x00\xd0\x22\xcc\x81\ \xbf\xae\xaf\x8d\x07\x04\xe7\x00\x00\xb2\xa9\xbf\xb1\xdc\x09\xc9\ #\xcc\xba\xdfb\x1f\xa1\xf4=\xe0\x03p\xdb\xc3\xe5/\ \x80#\xe0-vg\x82\x00\x0b\xaf\x00\x10\x04\xe1\x06p\ `9~\xe1\xe5\x16XO\x80\xdb\xc1\xb6x\xc0\xd3g\ \xc0f<#\x8cJ\x10\x00h\x11\xe6\xc0y\xa89\xfb\ $\x18\x00\x80l\xea\xaf,wB2\x08A\x01 =\ \x84\xe0\x00\x90\x16B\x14\x00H\x07!\x1a\x00\xa4\x81\x10\ \x15\x00Z\x84h\xdf\x0e\xd1\x01\x00dS\x7f\x06\x1e\x12\ \x01!\x09\x00\x00\xd9\xd4\x9f\x88\x80p \x94\x16\xc0I\ \xc8I;r\x18r\xb2\x19\x80P\xfa9i!\x84\xca\ \xc2\xf4\x08\x9d\x02/\x22/&J\xda\xcf\x80\xa9\x22l\ \xf6\x08M\x0ea[\x8f\xd0\xa4\x10v\xf5\x08M\x06a\ _\x8f\x90A\xb8\x0c\xb7\x9c\xf0\xe9\xea\x11:\x05^\x05\ ZK\x94\xf4\xe9\x11*\xfav\xe8\xdb#T,\xc2\x90\ \x1e\xa1\x22\x11\x86\xf6\x08\x15\x87`\xd3#T\x14\x82m\ \x8fP1\x08\xa3\xfe\x1a\x13J?\x03\x9e:ZK\x8c\ \x9c\xfd\x07\xf4\xebO\x9c\xad\xd2\xdbO\x00\x00\x00\x00I\ END\xaeB`\x82\ \x00\x00\x09\xb2\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x09dIDATx\x9c\xd5\ \x9b\x7f\x8c]E\x15\xc7?l6\x9b\xa61\x9b\xbai\ HU2i\xa0!\x05\xa4V\xc4\xc6\x10L\x9a\xb6\x02\ \x1ar\x85b!Q@G\x05\xa3E\x14l-\x0d6\ \xa6\x81M\x8d\x05\x0b\x12\x94\xa0\xcb-*ZJ-8\ A\x04\x0b\xa4m\x1a\xad\xb5\xadh*\xa9\xa4\xd1:i\ \xea\xc6\x94\xa66u\xd3l6/\xfe1\xf3^\xe7\xcd\ =s\xef}o\xdfV\xfaM6\xfb\xe6\xcc\x8f;\xe7\ \xcc\xcc\x993g\xce\x9c\xc79\x02ml\x1f\xb0\x08\xb8\ \x09\xb8\x12\x98\x01\x9c\x06,\xb0\x03\xd8\x92g\xea\xef\x9d\ \xb6{^/;9U\xd0\xc6.\x016\x00\xef/)\ 6\x01l\x02V\xe6\x99\x1a\xad\xdb\xf6;^\x00\xda\xd8\ a\xe0>\xa0\xaff\x95\x7f\x037\xe6\x99\xfa]\x9d\xc2\ \xefh\x01hc\xd7\x03+\xba\xa8z\x0aX\x9cgj\ OU\xc1\xff\xab\x00\xb4\xb1\xfd@#\xcfTC\xc8[\ \x0a\xfc2Q\xb5\x81cr\x00\x98\x96(c\x81\xcb\xf3\ L\x9d,\xebC\x7f\xfd\xeev\x07\xcf\xe4<\xe0#\xc0\ e\xc0\x1c`\x16p>0\x08\xec\x02\xae\x8d\xeaL\xc3\ \xad\xf9\x18\xa7\x81\x87\x80\x91\x98gjs\x9e\xa9S\x892G\xa3\xf4,\ m\xec\xbbj\xb4}\xa5@\xfbgY\x85\x8e\x05\xa0\x8d\ \xbd\x0fx\x16Hu\xc8\x02\x9b\x13y[\x81[J\x18\ obo\x94\x9e\x0e\xdc[\xd1\xafi\xc0Wk\xb4\xd5\ \x86\x8e\x04\xe0-\xb3u\x89z\xa7p\xba\xe0\x12\xdc\x1e\ \x1c\xe3 \xf0Y\xaf\xac\xaa\xf0+\x81\xb6\xc6\x1bGR\ \xbf\x06\x80\xa7q6F\x88c\xc0\xee\xb2\x0f\xd5V\x82\ \xda\xd8\x07H\x9b\xa5{\x80\xcf\xe4\x99:\xa4\x8d\xbd\x0e\ g\xf4\x84h\x00w\xd4\x18\xf9&^\xc4u~f\xd4\ \xd7g\xb5\xb1O\x02#8\x81\x0e\xe2\xb6\xb9\xd5\xb4o\ \x7fMl\xce35^\xf6\xa1Z3@\x1b\xfbE\xe0\ [\x89\xec'\x81\x8f\xe6\x99:\xe4\xd3\xab\x842[*\ \xf6\xf06x\x8d\xff\x94\x90\xd5\x0f|\x05\xd8\x07\xfc\x17\ \xf8\x17\xf0\x0bd\xe6\x1b\xc8\xdbb\xa1\xc1Rhc\xaf\ \x06\x1eO|`U\x9e\xa9\x87\x82\xb2\xf3p#\x12b\ \x02g\xaav\x8a\xc7\x80\xbbI\xdb\xfaUx5\xcf\xd4\ \x81\xaaB\xa5\xa6\xb06v\x06\xf0'`\xb6\x90=\x8a\ [_}\xfe\xaf\xdf\x97\x9b\x1b\x95;\x0d\xbc\xee\xff7\ \x90\xb7\xa5\xe6\x12i\xdb\xeb\xb5\xb1#\xc0\xe7+xH\ aq\x9e\xa9\xd7\xab\x0aU\xcd\x80\x87\x91\x99\x07w\xa0\ \xb9\xa1FG\xa6\x01\x9f\xa8Qn\x07n9\x85X\x07\ \xdcN\xe7\x06\xdb\xee:\xccC\x89\x0e\xd0\xc6.\x04>\ \xd7\xe1\x87'\x83\x95\xfe\xe4\xd8\x82\xd7+\x9b\xbahk\ \xb8nAQ\x00\xde\xff\xb6>\x95?E\x98\x03\xdc,\ \xd0\x87\xa9\xb0\xe6\x22\xecG8\xfcx\x9e\x0aH1x\ \x03\xb2U5\xd5X\x15w4\xcf\xd4A`K\x07m\ \x0c\xc7\x0e\x16\xaf\x9c\xbf)\x15N\xad-\xc9\x89\xb0\x13\ \xa7\xcdO\x0a\xf5\x06\x81m\xb4\x0bt\x0c\xf8$N\xc1\ \xc1\x99Q\x0c;\x17\x8el\xc3\xff\xf5\x03\xf1\xde=\x8c\ \x9b\x1dU3\xf2\x00\xf0\x82@_\x0b\x5c\xa5\x8d}$\ \xcf\xd4\xe90\xa3 \x00m\xecU\x14G\xbf\x01|\xc9\ \x8fF\x01\xbeN\xdc\xb9\xfdy\xa6^\xad\xe8p-\xe4\ \x99:\xa0\x8d5T+\xddu\xc2\xe8_\x81s\xce\xf4\ \xf9\xfam:E\x92\xe8\x1d\x02\xed\xe5\x14\xf3\x1e\x92!\ Rj\x83w\x81u\x15\xf9\x87\x90\xcf \xdf\xe6\x0c\x9f\ :\xcel\x13\x80\xb7\xa9%)?V\xf1\xf1\xcb\x05\xda\ \x9f+\xeat\x04\xef\xe1\xdd^RdC|\xce\xf0\xa3\ \x7f}@Z\xa4\x8dm\xf35\xc43`!Eo\xce\ Q\xa0j*_,\xd0\xcafL\xb7x8A?\x0e\ l\x14\xe8\xcbi\xe7\xb1\x1f\xb7\x1cZ\x88\x05\xf01\xa1\ \x11S\xe3\x047;J7pS\xb2\xd7x\x198\x22\ \xd07&\x89\x1b\x95\x9e\xc2\x0f\ \x84\xb4\xce\xf3D\x15i\xe6\xb6\xf1\xd8\x12\x80g$V\ f\x0d\x9c\xdf\xbe\x0cC\x14\x0f,G\xa4\xcb\x8e\x1e!\ \xf6\x15\xbcUr\xe89@q \x946v\xa8\x99\x08\ g\xc0,\x8a\xfe{\x9bg\xeaXE\x87f\x094\xc9\ \xd1\xd9+\xec\xc1\xd9\x18MlO\x15\xf4\x83\x10;J\ \xfb\x08\x1c'\xa1\x00$/\xce\x9b5:4S\xa0\xf5\ |\xfa7\xe1\x0d\x99p\xc4\xa5{\x85\x10\x12\x0f-^\ CCHbd\x896\xf6?\x15\x1f\x90\xac\xc9L\x1b\ \xfbvDkZz!b\xe5\x1a[\x86\x00k\xf3L\ m\x8c\xca\xbd\x89\xbb\x12\x03x+\xfe\xb86v\x070\ \xdf'\x07\x84\xfe\xb5\xb6\xc2\xb0\xf3\x92k{ \xd1@\ \x15\x06p\xba\xa1\x17\xb8D\xa0\xd9\xe0\xf7a!\xffR\ \xca\xaf\xe3Zy\xa1\x00\xbaa\xf4l@\xbaez\x1e\ x\x1b7K\xda\x82!\xbc2\xaf\xba\xa7h\xf1\x1a\x0a\ \xa0\x93#\xe7\xd9D\xc1\xfd\x9eg\xea\x0d\xe0\x8d\x92:\ \xb5\x1d(aA\xc9\x90\x18O\xd0\xe36\xe2N6h\ ?\xd1\xc5k_\xda\x22Se\xba\xd9N\x8f\xe3\xb6\xe6\ >\xff?\x9e\xdd-\x9eB\x01H\xdb\xddKy\xa6\xa4\ \x9b\xda\x16\xb4\xb1\x8b\x80\xd7\x22\xb2\xc1]}5Q)\ \x80^\xd9\x0d\xbe\x9d\xd6}`\xe2\xda\xbc\xb5M\x87\x02\ \xb0\x14\x11;8%H\x82\x1b\xac\xf2\xc7\x9fEH\xe7\ \x94\x16\xaf\xa1\x00Fq&l\xa8=\xe7hc\x07+\ \xc2L\xea\xdc\xeeN\x1a\xda\xd8;9s\xealz\x97\ \x87\xf3L%m\x0e\xaf\x10\xe7\x0bY\xad\x83Z\xcb\x10\ \xf2v\xf6_\xa2\x82\xfd\xc8\xe7\x83\x10\xc7(*\xd0\x0b\ R>\xb8I\xe0\x0b\xb8\xd8\x83\xbbp\xf7\x05\xf7R\xad\ \xecf\x03\xef\x8dhG\x09\x06-\xee\xa4\x14Z\xf6\xf1\ \xb2/x\xc1\xc5'\xb4Azg\x074GrvD\ \x1eC^~!\x96\x08\xb4\xdd\xa1\xbe\x89\x05\xb0M\xa8\ \xb0\xb4\xc6h\x1e\x8e\xd2}\xc0\x85\x15u:\xc1\x10E\ K\xd5\xd6P\x9c\xcb\x04\xdao\xc2D\xcc\xd8N\x5c`\ Q\x08E\xf1\xba+F\xc1\x1c\xc5Yc\xbd\xc2\x5c\x8a\ }-\xf57hcgS\xecw\x83\xc8e\x1e\xbb\xa0\ \xc7qw\xf81\xa4{\xf7\x10\x92\xe3Ar\x93u\x0b\ \xc9\xe7(\x09=\xc4r\x8a:bW\x9e\xa9\xb6\xe0\x0b\ ij?-\xd02\x1f\x12\x93\x82\x14\x9b\xd3\xcb{\x85\ \x0f\x0b\xb4\xa4\xcf\xd1\x9f\xf7\xef\x14\xb2~\x14\x13\x0a\x97\ \xa3~\xbd\xef\xa3\xb8}\xbc\x80\xec\x99\xed\xc7\xf9\x04\xe2\ \xa8\xceS\xb4\xdf\x0b@\xfaN@j\x13\xce\x5c\xbc\x8e\ PT\x82\xcbq\x82\x97\xf4\xc0m\xb8\xdd\x22\xc4(p\ Q\xec:\x13o\x87\xb5\xb1\xb7\x02?-\xe9\xe0\xb9\x88\ \xd5y\xa6\xbe\x13\x13S\xda}\x13\xedN\x87s\x1d\xa3\ \xc0\x0f\xa4\x0cQ\x00~o\xff\xc6T\xf6\xe8,\xe3\xfe\ \x945\x9b\xdc\xdf\xf3L\xfd\x96t\xb4\xd7\xb9\x84]\xc8\ w\x06@\xb5)\xb9\x1c\xb8\x9a\xa29\x09N\xc9\xc5\xcb\ d\x16Ee5\x81\xdb\xb3\xc7\xfd\xef\xf0\x98\xdb\xfc\xdd\ Tv\xcd\xdf\xfd\xb8#\xac\xa2\xe8\xdc\x18\xa5hx\xcd\ Av\xe9\x9d\x02t\x99\xc1T\x19-\xee\x8f\xbb\xafP\ \x14V\x03X\x9eg\xea\x89\xa0\xec|\x5cHM\x88\x09\ \xe0\xb2|\xed\x05~\x8d\x8bSN1\xff\x13\x9c\ \x8e\xa8\xed\x8d\xea\xea\xc9\x8c6\xf6v\x5c\x14f7o\ \x04\x9e\x02\xbe\x1cw\xd2\x0bf-\xe9\x88\xd424p\ \xb3\xef\xbb\x9d\xfa\x16\xbb~3\xe45\xfe3tw\xec\ \xdd\x8b\x8bC\xda\xee\xd3\x0b\x80\x07pO^:\xc5\x11\ \xdcV\xd7U8\xce\xa4\x1eM\xf9\x10\xf558\xf7T\ 7!\xadc\xb8\xd1\xab\xf3\x16 F\x03g\xe0\xac,\ \xf3\x0bV\xa1'\xaf\xc6\xb4\xb1\x17\xe3\xd6\xeeR\xceN\ l\xe1N\x1c\xe3\x95\x0f#\xab\xd0\xd3gs>\x1e\xef\ \x1e\x5cH[7\xfa\xa1\x0c\xe38o\xce\xfa\xba\xcfb\ \xeb`\xaa\xde\x0d\x0e\xe1f\xc32\x9c)\xdd\xad0\xc6\ q\xf1\x00\xcf\x03?\xef\xe4Qt]L\xf9\xd3Y\xff\ \xd6g\x01\xce\xbd\xfe\x01\xdcYa&\xf2R9\x8e\xb3\ \xf3\x0f\xe0\xde$\xed\x9e\xcc\xfa\xae\x83\xff\x01\xfe\xf2\xbf\ \xf4\xf2\xa4\xa21\x00\x00\x00\x00IEND\xaeB`\ \x82\ \x00\x00\x06V\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x06\x08IDATx\x9c\xd5\ \x9bm\xa8\x16E\x14\x80\x1fE.\x11\x22&\x22%:\ \x89HE\x89\x94\x95\x14\xf4C\x08\x8a0\xe7\x97\x18Z\ L)I\x04R\x90\x89H\x88\x98e\xf4%XY\x84\ !6}\x99\x94\xd8$\x95\x16f!\x92e\x97RQ\ \x13\x13\x19?\xba\x5cJD\xe4b\x97\xcb\xa5\x1f\xb3W\ \xde\xbbw\xf7}w\xdf9\xbb\xd2\x03\xef\x9f\xd9\xd9s\ \xce\x9cw>\xce\x9c\x99\x1d\xc6\x15\xc08?\x03x\x14\ \xb8\x07\xe8\x03\xf6\x02\xef[\xad\xf6\xd7m\xcb\xb0\xba\x14\ \x19\xe7\x87\x03\x1aX\x06\xdc\x95Sm/\xf0\x12\xf0\x95\ \xd5\xaa\xbf\x0e\xbbjq\x80q\xfeA`5pk\xc1\ W:\x81\x95V\xab\xed\xd5Y\x15\xa8\xd4\x01\xc6\xf9\xe9\ \xc0\xeb\xc0\xcc6E\xfc\x08,\xb5Z\xfd,fT\x8a\ J\x1c`\x9c\x1f\x0b\xbc\x08<\x0e\x0c\x8f\x14\xd7\x0fX\ `\x99\xd5\xaa;\xd6\xb64\xa2\x0eH\xc6\xf9c\xc0\xcb\ \xc0XI\xd9\xc09`9\xf0\x9e\xe4\xfc \xe6\x00\xe3\ \xfc4`=af\xaf\x92\xbd\xc0\x93V\xab\x03\x12\xc2\ \xa2\x1d`\x9c\x1f\x0d\xac\x04\x16\x03#\xa2-*F\x1f\ \xf06\xb0\xcaju.FP\xdb\x0e0\xcew\x10\xc6\ \xf8J`\x5c\x8c\x11\x11t'\xfa7Z\xadz\xdb\x11\ P\xda\x01\xc6\xf9\x11\xc0|`\x050\xa5\x1d\xa5\x15p\ \x8c\xb0\xccn\xb6Z\xf5\x95y\xb1\xb0\x03\x8c\xf3S\x80\ 9\xc0\x13\xc0\xa42Jj\xe4$\xf0.\xb0\xc5ju\ \xa2\xc8\x0b\xb9\x0eH\x82\x97{\x81\x9b\x80\xa9\xc0\x04\x01\ \x03\xeb\xa2\x1f8\x0d\x1c\x00\x8e\x02;\xacV\xdfeU\ \xcct\x80q~1\xf0fe\xe6]\x19\x96X\xad\xd6\ \xa6\x0b\x878\xc08?\x128\x03\x8c\xaa\xc3\xaa\x1a\xb9\ \x00L\xb4Z]h,\xcc\x8a\xd2:\xa8\xaf\xf1}\xc9\ \xaf\x0eF\x01W\xa5\x0b\xb3\xd6\xed\x8b\x841\x14\x1b\xc2\ f\xd1\x058\xe0k`?!\xba\xebO\x0c\xbb\x960\ \xd7\xcc&L\xb6W\x0b\xeb\xee\x07\xce\xa7\x0b\xb3\x1c\xd0\ G\xe8.\xa3\x05\x95\x1f\x22,S[s\x96\xa9K\x89\ qG\x81\xcf\x8c\xf3K\x09\xdb\xe2\x85\x826\xf4\x90\xd1\ \xdb\xf2&\xc1?\x81\xc9B\x8a\xbb\x08c\xaftW7\ \xce?C\xd8MJ\xe0\xadV\xd7\xa7\x0b\xf3\xba\xf9\xdf\ BJ\x01\xfa\xdai<@2k\x7f,dGf\x9b\ \xf2b\xf7.!\xa5\x99$\xbb\xc6\xf1\x84q\xdem\xb5\ \x1a26\x1bX\x0e\xcc%~\x9f\x91\xd9\xa6\xbc\x1ep\ 6RY&\xc6\xf9q\xc6\xf9W\x09\xcb\xec)\xe0\x0f\ \xe0\x1f\xe3\xfc/I\xe05\x04\xab\x95'\xec\x00c\xc9\ lS\x9e\x03N\x09(\x1c\xa4\xc38?\x178\x02<\ K\x98\xf1\x1b\x9f\xdf\x01|a\x9c\x9f\x93#\xe3\xb0\x80\ \x1d\x99m\xcas@\xa18\xba c\x8d\xf3\xeb\x80O\ \x801M\xea\x0d\x07\x96\xe4<\xeb\x11\xb0\xc3g\x15\xe6\ \x8d+I\x07t\x00O\x15\xac;>\xa7\x5cbI>\ \x9eU\x98\xd7\x03\x8e\x13\x02\x87\xba\xc9s\xfc4\x01\xd9\ \xc5\x1d\x90dY*]\x092\xe8'\x04?\x83H\xb6\ \xe1\xd3#e\x9f#$O\x86\xd0,\xdc=\x14\xa9\xb4\ ,\xab\xacV;3\xca\x9f#>,?\x9c\x97Hm\ &\xf8\xb7H\xa5ex\xcbj\xf5|\xba\xd08?\x13\ 0\x02\xf2s\xdb\xd2\xcc\x01\xbf\x0a(.\xc2F\xe0\xe9\ t\xa1q~\x12a\xe5\x90\xd8\x94\xed\xcb{\xd0Lx\ e\xa71\x0dl\x06\x16\xa5\xbb\xa7q~\x02\xf0-\x83\ \xe3\x85\x18r\x03\xa9\xa69A\xe3\xfc\x19\xf2\x97\xa6X\ v\x01\x0f\xa4\xb3\xb9\xc6\xf9\x1b\x80\x1d\xc8\xe5\x1d\xbb\xac\ V\xd7\xe5=l\xd5\xbdv\x0b\x19\x91\xa6\x1bx(\xa3\ \xf1S\x81\x1f\x90M\xba\xfe\xd4\xeca+\x07|/h\ H#\xab\xadV\x83vg\xc6\xf9\xf1\x84\x7f^\xaa\xdb\ \x0f\xb0\xa3\xd9\xc3V\x0e\xd8\x89|@\xd4K8\xecL\ \xf3\x0e\xd5\x0c\xb7\xac\xa5\xf52-\xcf\x05\x8c\xf3\x07\x09\ \xa9*)N[\xad&\xa6t\x8c\x03\xfeB>\x0dw\ \xccjuc\xb3\x0aE\x14n\x132f\x80\xac\xe4\xc8\ \x98\x82\xb6\x94\xa5\xa5\xedE\x94~.`H#\xa3\x93\ \x84H#\x9ej\xf6\x1e\x9f\xb6\xaaP\xe8h\xcc8\x7f\ \x84pB$\xc5\x87\x84c\xac\x7f\x09\x7f\xc25\xc8\x9f\ .\xb7\xec\xfe\x94P\xf8\x01\xe1\xc6\x87\x14\x8f\x08\xca\xca\ \xe3\xa3\x22\x95\x8a\x8e\xbbM\x84\xd9\xfb\xffB/!\xc4\ nI!\x07X\xad\xce\x02\x95\xdf\xd8\x12d\xbb\xd5\xea\ t\x91\x8aef\xdeum\x1a\x93\xc7.\xc2e\xc9\x87\ \x09q\x81\xe4$\xb8\xbeh\xc5R\x17$\x8c\xf3\xfb\x80\ \x19\xa5\xcd\x19\xca\x1a`E\xe3&\xc88\xbf\x10\xd8@\ \xfcr\xd8i\xb5\xba\xbdh\xe5\xb2\xca$&\xc2\x13\xa4\ \x1a\x0f`\xb5\xda\x08|# \x7fu\x99\xcae\x1d\xb0\ \x9dp\xa8\x19\xc3\xe9&\xd7\xdcb\xd3\xdf\x9d\x84\xc3\xd7\ \xc2\x94r@b\xf8\xf22\xefd09#\x10\x1a \ 6\xe4^Z\xf6\x0ea\xe9\xf1\x96\x5c5)\xe5\xe5\x14\ \x13\xc8H\x93\x1b\xe75p_\x84\xdcmV\xab]e\ _j\xeb\x9a\x9cq~2p\x90\xb83\xfcm\x840\ \xbb\x17\xb8\x9f\x90\xfbk7\x12\xec\x01n\xb1Z\x9d,\ \xfbb\xcc=A\xc9\xa3\xebX2\xef\xff\x14!f\xc9\ y\x03\xd8\x13\xf1\xbe\x14{\x08\xb6\xb4E\xd4UY\xe3\ \xbc\x02~G\xf66I\x19\xce\x03\xb7\xb5\xd3\xf5\x07\x88\ \x0a:\x92\xa3\xeb\x05\x5c\x99c\xb4~`AL\xe3A\ \x09a\xb5\xda\x06\xac\x8a\x95\xd3\x06k\x12\xddQH\ ea^@\xee*K\x116\x13.IG#\xf9\xbd\ @\x07\xf0%qky\x11v\x01\xb3\xacV\x97$\x84\ I\x7f12\x92\xe0\x84\x99\x92r\x1b\xd8C8L\xb9\ (%P4\x11\x99\x186\x9b\xf0/I\xb3\x9b\xf0\xcf\ \x8b5\x1e*\xc8\xc4&\x06\xce\x02\xb6\x08\x8a\xddJh\ \xfc\x85\x965KRE*\x9ad|\xce\x03^\x13\x10\ \xb7\x96p\x8c&qOh\x08\x95\x7f8i\x9c\x9fO\ Ht\x94\xdd7\xf4\x10>\x8e\xca:E\x12\xa3\xae/\ Go&di\x8b~9z\x08\x98g\xb5\xaa\xfc\x96\ J%C \x8d\xd5\xea0p7\xf0\x0a\xcd\xaf\xc7\xf7\ \x11\x86\xcd\x9du4\x1ej\xfcxz\x80\xe4s\xda\x0d\ \x0c\xbd\xf8\xd4I\xe8\xf2u\x5c\xcc\xb8L\xed\x0e\x80\xcb\ _\x9e-\x04\x16\x11b\xfa\x0d\xc0\xa6v/U\xc7\xf0\ \x1f\x18b\xad\xf3\xbb\x81fi\x00\x00\x00\x00IEN\ D\xaeB`\x82\ \x00\x00\x01c\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x01\x15IDATx\x9c\xed\ \x9b1\x0e\x82@\x14\x05\x1f\x86x\x0cBa\xac\xf4\x1c\ t$^\x80\xc3q\x01\x13:\xcf\xa1\x95\xb1 \x1c\x83\ \xcaB**\x03|\xc7d\xdf\xf4\x7fw2\xc9\x16\xbb\ \x84L\xc14\xddp\x94t[8^\xb5u\xf1\xdc\xd2\ gN\x1e\xb9\xf8\xc4^R\xb9b6\x94]\xf4\x06\xff\ \x8e\x03\xd0\x024\x0e@\x0b\xd08\x00-@\xe3\x00\xb4\ \x00\x8d\x03\xd0\x024\x0e@\x0b\xd08\x00-@\xe3\x00\ \xb4\x00\x8d\x03\xd0\x024\x0e@\x0b\xd0$\x1f \x9b\xde\ \xed#\x9f\x9f\x0f\x92\xae\x0bg/\x92^\x1b\xba\xcc\x19\ s}>Z\x94\x81\x9b\xacai\xb8o\xe9\x93?\x02\ \x0e@\x0b\xd08\x00-@\xe3\x00\xb4\x00\x8d\x03\xd0\x02\ 4\x0e@\x0b\xd08\x00-@\x93K\xaa\x94\xf0u8\ \x0b\x5c\x5c\x92\xd4t\xc3I\xd2}\xe1\xf8\xb9\xad\x8b\xc7\ \x96>s\x92?\x02\x0e@\x0b\xd08\x00-@\xe3\x00\ \xb4\x00\x8d\x03\xd0\x024\x0e@\x0b\xd08\x00-@\xe3\ \x00\xb4\x00\x8d\x03\xd0\x024\x0e@\x0b\xd08\x00-@\ \x93|\x80_\xfc=>J\xeaW\xcc\x86\xf2\x06\xe1f\ \x18M|\xe7$\xec\x00\x00\x00\x00IEND\xaeB\ `\x82\ \x00\x00\x08N\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x08\x00IDATx\x9c\xcd\ \x9b\x7f\xc8\x96\xd5\x19\xc7?\xbdH\x88\x84H\x88H\xb4\ 3\x89\x10\x91\xb6\xb9hc\xcb~8\x8b-JN\xfd\ !R\x12\xd1\x89\xac\x16\xaewef/\xe1D\xc49\ \x7f\xed\xd5\xe1\xdc\xd6\xda\x8e\xb86\x96E\xb8\x9b\x12i\ f\x9b\xd4\x16\x12[\xeb\x17e\x16r\x101\x11y\x91\ \x10\x89\x97\x87\xfe8\xf7\xec\xf5~\xbe\xe7y\x9e\xfb\xc7\ \xf3\xd6\xf7\xcf\xeb\x5c\xf7y\xae\xfbz\xae\xeb\x9c\xeb\x5c\ \xdfs_\xc0W\x00.\x0b\x93\x81\x05\xc0\x0d\xc0l`\ \x1a0\x01\x18\x01\x0e\x01\xaf\x01\xbb\xbd5G\x9a\xfe\xed\ \x0b\x9a\x9e\xb0\x0c\x5c\x16\xa6\x01O\x00\xf7\x02\x93\xba\xa8\ \xb7\x80\xbd\xc0Jo\xcd\x7f\x9a\xb2\xe1Ks\x80\xcb\xc2\ \x22\xe07\xc0\xc5%\x1fm\x01[\x80!o\xcdgu\ \xed\xf8R\x1c\xe0\xb2\xf03`u\xcdi\xf6\x03\xb7z\ k>\xad3\xc9\xb8;\xc0e\xe1q`]C\xd3\xed\ \x07~\xe4\xad\x19\xad:\xc1@C\x86\xf4\x04\x97\x85\xf9\ \xc0\xda\xc4p\x0bx\x01\xb8\x1f\xf8\x010\x17\xb8\x03x\ \x128\x9dxf>5\x9d9n\x11\xe0\xb2p!\xf0\ .p\xb9\x18>\x088o\xcd{\x89g\xa7\x00\x1b\x89\ \x8be\x11\xa3\xc0w\xbc5oV\xb1k<#\xe0\xa7\ \xe8\x97\xdf\x03\x5c\x9fzy\x00o\xcd\x88\xb7f\x09\xf0\ \xb0\x18\x9e\x00\xac\xaaj\xd4\xb8D\x80\xcb\xc2t\xe0C\ \xe0\xa2\xc2\xd0a\xe0\xdbe\x162\x97\x85?\x00\xf7\x14\ \xc4-\xe0k\xde\x9acem\x1b\xaf\x08XG\xfb\xcb\ \x03\x0cVX\xc5\x97\x03\xc5g\x06\x00[\xc5\xb0\xbe;\ \xc0e\xe1*\xe0.1\xb4\xc7[\xb3\xa7\xec|\xde\x9a\ S\xc0\xf3bhn\xd9\xb9`|\x22`\xab\xf8\x9d\xcf\ \x80e5\xe6|E\xc8\xd4\xfa\xd2\x15}u\x80\xcb\xc2\ b\xe0j1\xb4\xdd[\xf3~\x8d\xa9\x8f\x0a\xd9\x94*\ \x13\xf5\xcd\x01.\x0b\x93\x80\xf5b\xe8\x04\xf5\xab\xc0\x0b\ \x85\xacUe\xa2~F\xc0\x10p\xa9\x90\xaf\xf4\xd6\x8c\ \xd4\x9c{\x96\x90\x1d\xaf2Q_\x1c\xe0\xb20\x03x\ T\x0c\xbd\x09<\xd5\xc0O\xdc*d\xefT\x99hB\ MCR\xd8\x08L\x14\xf2AoM[\xa8\xe6\xe92\ \x1d8\xa2\xc6\x0b\xbaW\x03\xd7\x89\xa1\x97\xab\x18\xdax\ \x04\xb8,\x5c\x07,\x14C\xcfyk\x0e\x08\xfd;\x81\ O\x80\x8f\x80w]\x16\x92\xab\xb9\xcb\xc2\x000,\x86\ N\x01/U\xb1\xb7Q\x07\xe4\x06n\x15Cg\x89\x05\ LQ\x7f\x06\xf0{\xbe(\x92f%\x9e\xff?\xee\x04\ \xbe+\xe4\xdb\xbd5gK\x19\x9b\xa3\xe9\x08\xb8\x17\x98\ #\xe4\x9b\x12\xed,\x95*j\x81\xc3e\xe1\x22\xf4\xae\ r<\x9f\xa7\x12\x1as@~b[#\x86\x8e\x22\x0c\ wY\x98\x87N\x95W\x13?\xf1\x04q\x9d(b\xc8\ [\x93:.wE\x93\x11\xb0\x92\xd8\xcc,bE\xb1\ \xde\xef\x90*g\xf2y\xce\x83\xcb\xc2e\xc4\xd3d\x11\ o\x00;\xcb\x9b\xfa\x05\x1a\xd9\x05\x5c\x16f\x02K\xc5\ \xd0\xeb\xde\x9a\xbf\x08\xf9}\xc07\x85|\x93\xb7&\x08\ \xf9f\xdaS\xa5EzW\x99CL\xc5\x83\x9d\x8e\xd9\ \xd0\x5c\x04\x0c\xd3^\x9d\xb5\x80\x9f\x08\xe3R\xa9\x12\xd0\ \xa92\x1f\xb8M\xe8\xef\xf2\xd6\xfcK\xe8?\x02\xfc\x17\ \xf0\xc0\xdb.\x0bww2\xbc\xb6\x03\x5c\x16n\x02n\ \x16C;\xbd5o\x08\xf9*`\xaa\x90\xaf\xf0\xd6\x9c\ )\xcc=\x81t\xaa\xa8]\xe5r\xceo\x91\x0d\xa0\x17\ \xce\xf3\x14*#os\xa9}\xf9Sb)\x5c\xd4\x9f\ \x05<(\xf4_\xf5\xd6\xfcU\xc8\xef\x03\xae\x10\xf2\xf5\ \xde\x1au \xdaL{$v<$\xd5\x8d\x80\x07\xd1\ \xdb\xd6Zo\x8d\xaa\xcdS\xa92XTtY\xb8\x18\ }h\x0a\xc0&\xa1\x7f#\xba)\xb2K\xc8\xce\xa1\xb2\ \x03\x5c\x16\xa6\xa2{q\x1f\x13\x89\x8b\xa2\xfe\xcd\xc0M\ B\x7fG\x82\xe9Y\x8dN\x95\xe5\x89TQ\x91x\x06\ \x11\x89cQ'\x02\xd6\xa2\xc3kY\xb1*\xeb\x90*\ \xa7\xd1\xa92\x1bx@\xe8\x1f\xf0\xd6\xa8\x7f\xf4\x01t\ \xaa\xacK\xa4\xca9Tr@\xbe\xcd\xa8\x16\xf5>o\ \xcdn!_\x0a\xcc\x14\xf25\xde\x9a\x13B>L\xfb\ \x16\xddBt\x85;\xa4\xca\x11D\xaa\x14Q5\x02\x86\ \xc5\xb3\xa3h\x03\xa7!\x8a\x1bbG\xf8WB\xdf\x02\ ?\x14\xfa\x7f\xec\x90*\x8a_\x5c\xde\xcb\xf9\xa0\xb4\x03\ \x5c\x16\x16\x02\xf3\xc4\xd0\x93\xde\x1au&O\xa5\xca\xc3\ Er3O\x95\xcdB\xf74\xb1\x14.\xdar\x05\xe9\ TyN\xc8\xdbP\xca\x01.\x0b\x13\xd1\x07\x8fS\xe8\ \x12v\x0e\xed=|\x80\x97\xbc5/\x08\xf9C\xe8\xe6\ \xe6\xea\x92\xa9\xd2\xb6\xab\xa4P6\x02\x1e\x05f\x08\xf9\ \xaa\xbc]]\x84\xea\x08\xa7Re::U\x0e\x01\xdb\ \x84\xfem\xc0\x8dB\xff\xa924Y\xcf\x0epY\xb8\ \x14X!\x86\xde\x03~+\xf4\x17\xa1;7\xdb\x13\xf5\ \xf9Z`\xb2\x90\xa7REE\xe2\x08\xda\x89I\x94\x89\ \x80N\xec\xcey\xf4t\x87T9\x89X\xb1]\x16\xae\ \x04\xee\x16\xfa{\x13\xe4I\x8agL\xa5J\x12=9\ \xc0e\xe1{\xc0b1\x94yk\xf6\x09\xf9c\x80\x11\ \xf2\xa6R\xa5mA\x04\xde\x07\xb6\x0byG\xf4\x1a\x01\ =\xb3;\x1dR\xe5\x1d\x22\xd7_\xd4\xbf\x1d\xb8F\xe8\ oK\x90'\xeb\xd0\xa9\xb2\xac\xca\x95\x99\xae\x0e\xc8\xf7\ e\xd5\x87\xdb\xe2\xad9,\xe4\xeb\xd1\x17\x9eT\xaa\xa4\ \xc8\x93T\xaa4\xca3Bo\x11\xa0\xb6\x94\xe3\x88\x9b\ \x1ey\xcb\xfav\xa1\xbf\xdb[\xb3_\xc8W\xa0S%\ E\x9e4\xce3vt@\x1e\xce\xf3\xc4\xd0\x9ab\x1f\ nL\x9b\xab8\xe7Ye\xa0\xcb\x82A\x93'o!\ \xc8\x93~\xf1\x8c\xdd\x22`\x81\xd0\x19\x01v\x08\xdd\xbb\ \x80\xab\x84|\x8b\xb7\xe6c!\xdfH\xfdT\xa9\xcd3\ vs\xc0\xb5B\x96\x89\xe3\xe8$\xf4e\xa5c\xe8T\ \xb9\x06X$\xf4\x9f\xf7\xd6\xfcC\xc8\xfb\xc63vs\ \x80j\x5c\xfeS\xc8\x16\x93nY\xf7\xda\x11N\xa5\xca\ \x0c\xfa\xc83vs\x80Z\xa0T\x15w\x8b\x90\x1d\x04\ \x9e\x16\xf2{\x80+\x85\xfc\x97%\xc8\x13Ht\x84\xcb\ \xa2\x9b\x03\xd4~{R\xc8TU\xb6\xb9h`~)\ Z\xdd\x13<\x86H\xa1\xb2C%\ \x13\xbc\xf8K\xc0-\x15y\xa0\x8b&\xf4\x03K\xa9.\ \x1e.\xaf\x09\x8b\x03\xdb/\xa6\xda\xcc\xb7bcb\xd3\ }\xc2\xbe\x85\xe8\x07\x1a\xc0\xa8\xb0\xff p&\xc4\x04\ \xa3\xd5\xa8\xe7\x9a\x12rm\xed\x86\x09\xd9\x1a0\x00\xbc\ \x03<\x22\x1c'xaLl:\x0c\x1c\xa2\xe0\x10V\ \x82\xfdF\xabm\xc2\xbe3\xd0\xba\x0b\x0c\x00\x1f\x00+\ \x85c\x05\xaf\x09\xde\x84\x98\xbd\xfe%\xa3\xd5s\x11\xfd\ \x9bh\xce\x82\xd1j\x12X\x0d|\x22\x1c+\xf8\xb0d\ \xb4z\x15\x88Y\xd4\xb6'6\xdd\x1b\xd1\xbf\x89\xbe\xf6\ \x0b\x89M\xe7\x00\x1f\x01Z8f\x95H\xd8\x08\xc4\x1c\ x\xa2#a\xc6sh\xb4\x9a\x00V\x01V8\xe6 \ 0\xe6\xb7\xd7B\x18\xad\x0e\xf2\x1fG\xc2\x8c\x08\xc8\x90\ \xd8t.p\x06X\x22\x1c\xfbo\x5c$|]\xd6\xb0\ \x86H\xd8m\xb4zA\xd21\xd7\x00\xa8\xcd\x84\xa5F\ \xabo\xca\x1a&6\xdd\x0c\x8c\x08y@hB\xa1\x01\ \xd04a\x0cw\x90\x91\xe0\x8a6\xa1\xd4\x00\x80\xc4\xa6\ \x83\xb8H\x881\xe1^\xa3\xd5w\x01\x5c\xb1&\ \x80k;\x10\xb3\xc2o3Z\xed/kT\xc9\x00\xa8\ \xcd\x84{\x8cV?\x04p\xed\x00\xf6\x08y\x00\xb6\xf8\ \x88\xcaEe\x03\xa0\xb9&\x8c\x01\xd2\xecP\x15\x13v\ \x02\xbb\x84<\x00\x0d\xa3\xd5\xe1\xbc\x1fE/$~M\ X\x0e\x88\xb2B\xc05\xb8l\xf3\xfc\x00\xae\xdd\x80h\ \x8f\xf78\x90\xd8\xf4\xd9\xbc\x1fE\x11\x90\xa1\x86H\xf8\ \x13\xb8\xdbh\xf5c\x00\xd7\x1e`\x87\x90g\x0a\xd8`\ \xb4:\xda\xfeC\x94\x01p\xd5\x99\xf0\xb4\xd1\xeaX\xeb\ \xc5h\x03\xa06\x13\x16\x1a\xad~\x0a\xe0\xda\x0b\x04o\ sm\x98\x02\x9e4Z\x1d\xcf.\xd4b\x004M8\ \x07\x94\xbe\x04\xe5\xa0\x97&\xac3Z\xbd\x095\x1a\x00\ =7a\x1f\xb0U\xc83\x05$F\xab\xd1Z\x0d\x80\ ZL\xf8\x03g\xc2\xcf\x01\x5c#\xc0f!\xcf$\xb0\ Z\x9a\x97+\xc2\x04n\x9f\x97b\x08\xb8>\xb0\xed/\ \xc8\x93\xac\x03\xc0Mu?\x02\xfd\xc0\xbb\xc8\x93\xab\x13\ \xc0\x03F\xab\xd2dLb\xd3\x87<\xd7\x80\x90\xeb\xb0\ \xd1\xaaQ[\x04x\xf1o\x10'~U\xa0\xf8\x07\x89\ \x13\x7f\xd4h\xd5\x00yj\xba\xfd\x86\xfa\x81#\xc0Z\ \xe1\x10\x93\xc0\xc3F\xab\xd2\x84\xac\x17\xff\x1er\xf1\xc7\ \x80\x0d\xd9\x1fu\x1c\x842\xf1\xeb\x85Cd\xe2O\x07\ p\xad\xc4\xa5\xee\xa5\xe2\x8f\xe3\xce\x01\xcdu#*\x02\ \xbc\xf8C\xc4\x89\x7f\xb4\x82\xf8\x98\x99?A\x9bx\x88\ 0\xc0\x8b\x1f\x01\x86\x85CL\x02\x8f\x1b\xadN\x05p\ e\xe2\xe7\x08\xb9\xde\x06\xd6\xb4\x8b\x87\xb8\x08\x18\x01\xa4\ \x85M\x93\xb8\x83\xc8\xfbe\x0d\x13\x9b.#N\xfc(\ 9\xe2Ah\x80?\x85I\xc5O\x01O\x18\xadN\x06\ \xf0,\x03>D.\xfe\xa4\xe7\x9a\xcck \xc9\x08\xc5\ \x1eA\xd7\x18\xadN\x04\xf0\xc4\x8a?\x85[_r\xc5\ C\xc5\x08\xa8A\xfc\xba@\xf1\x1a\xb7\xdawU\x02\xbc\x90\xd0B\xe6\xca\ \xe23\x08L\xb8\x00\xac\xe8\x96xh;\x08\xf9\xf5\xe0\ \x08\xc5\x8fFa\xc1A\x08\x12\x9b\xde\xca\xe5\x7f\xca\xca\ \xc3\x05\x5c\x01v\xd7\xc4C\xe7R\xd9\xb5\xb8\xfc~'\ \x13\xa2\xc5\xb7\xf0\x14\x99\xd0\x13\xf1\x90\x7f\x14~\x0cx\ \x8b\xe9\xaf\xcb\xb5\x89o\xe1\xe9dB\xcf\xc4Cq\xa9\ l\xeb\xa7\xa7\xda\xc5\xb7\xf0\xb4\x9ap\x11'~\xbc\x1b\ \x5c\x9dPV*\xbb\x0c\xb8!\xe4\x84\x17\x03o\xc2\x16\ \x5c\x02\xb3g\xe2g1\x0b\xf8\x17\xb6\xec\x99\x01(\xb3\ \x19\xc8\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x044\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x03\xfbIDATx\x9c\xed\x9bA\x88\xddD\ \x18\x80\xbf\x0da\x91R\x8a\x07)E\xca\xd0\x83\x07Y\ D\xd4\x93\x88x,\xb2\xd4\x01\x8bX\xad8-\x14\xc1\ \xbb\xc7R\xbc\xd5\x83\xa0(\x9e*Z:\xbb\xb4Z\xa4\ \xe0X=\xd4RE\x96\xa5H\x8f\x16\xaa-\x8b\x0cX\ <,K)ey,K\xf0\x90<\x9b\x977\xd9\x97\ \x97y\x99n\xde\xe6\x83\x90\x97?\x93\x99\x7f\xfe\xcc\xcc\ ?\xf3g\x1etttttt\xecXf\x5cBe\ \xec\x13\xc0\x1c\xb0\x1b\x98\xcd\x8e\x08\x88\xb3s\x04$\xd9\ \xb1\x99;\xf7\x80\x07\xc0\x1d-\xc5\xdd\xa6\x95\x9f\x04\x03\ \x06P\xc6>\x03|\x04\xcc\x93V\xd2\x87%\xe0\x94\x96\ \xe2W\xcf|\x1a\xe5\x7f\x03(c\x8f\x02_\x01\x8fM\ 0\xff\x048\xad\xa585\xc1<'\xca\x0c\x802v\ \x1e\xf8\x01\xff\xb7^\xc6I-\xc5\xe9\x86\xf2\xf6bF\ \x19\xbb\x07\xf8\x13\xd8\xd7`9\x9b\xc0\xf3Z\x8a?\x1a\ ,\xa3\x16\x11p\x9cf+\x0f\xe9\xe0\xf9A\xc3e\xd4\ \x22\x02\x8e\x04*\xebUelS]\xac61\xb0'\ PY\xfb\x80\xa7\x95\xb1\xab\xc0\x06\x0f\xddg\xe2H\xeb\ \x929\xe5Z\x8aM\x1f\xa5b\x9f\x87kp\xd3!K\ r\xe7\xc4!\xcf3TYe\xac\x05\xbe\x04\xceh)\ \xd6\xc7Uh;4\xc9\xfe\xc4*\xe6\xe1\xa4k\x96\xd4\ \x1d\x17\x8f\xdd\x8ec\x0e\xf8\x14\xb8\xa9\x8c}\xb1N\xe1\ \xd3\xc2\x01\xe0ge\xec\xcb\xe3<4M\x06\x80\xb4E\ \x5c\xc8\x5c{%\xa6\xcd\x00\x00\xfb\x81\xf7\xab&\xee\xf7\ \xbfi\xe3\x9d\xaa\x09\xa7\xd5\x00s\xca\xd8Jk\x9a\xd0\ n0\x141\xf0\xbd2v\x9dt\x89\xde\x03\xd6\x81\x7f\ \x80kZ\x8a\xeb\xf9\x84\xd3\xca\xc1\xb2\x1b\xca\xd8K\xc0\ \x09-\xc5\xbdil\xfeU8\x0c\xfc\xa8\x8c\x8dw\xaa\ \x01\x00^\x02\x8e\xefd\x03\x00\x1c\x99\xc4\x18\xb0\x0a|\ \x0d\xdc&\x8d\x07\xf6\xe3\x83\xe0\x98\xbb\x97\xc8|\xc9\xd7\ #\xef\xd9\xfa\xf2Y\xe0q\xe03\x06\xbd\xde\x81\x18\xbf\ \x81\xf0'\xe0\x98\x96b\xd5#\x8f (c_a\xd8\ \xe5\xdf\xf7\xa9\xfc\x12\xf0\xba\x96b\xc3#\x8f\x90\xbc\xeb\ \x90-\xfb\x8c\x01'\xdbRye\xec.\xe0\x0d\xc7\xad\ \x0bu\x0dp\x8b\xb4\x05\xb4\x85C\xa4c@\x9e\x15\xe0\ z]\x03\x9c\xd5R\x94Em\xb6#\xc7\x1c\xb2\xf3Z\ \x8a\xa4\x8e\x016\x81EO\x85\x82\xa1\x8c}\x12\xf7\xac\ \xf0\x1c\xd4[\x0c]m\xcbg\xaf\x8c\xb7\x18\xf6t\xcb\ Z\x8a;P\xcf\x00g'\xa1U@\x5c\xcd\x7f\xa1\xff\ c\xdc\xca\xaf\x01\xc6K\x9d\x80(c_\x00\x9e-\x88\ {\xc0\xc5\xfe\xc5\xb8\x06\xb8\xa8\xa5\xe8\xf9*\x16\x10\xd7\ \xdb7Z\x8a\xb5\xfe\xc5\xb8\x068\xe7\xa7O8\x94\xb1\ \xb3\xa4\xfd\xbf\xc8@\x1d\xc61\xc0_\xc0\xef>J\x05\ f\x1e\xd8[\x90\xdd\x05\xae\xe4\x05\xe3\x18`aJ|\ \xff\xc0b\xac\xaa\x01\x12\xda\xe5\xfb\xf7\x92\xb6\x80\x22C\ ]\xb8\xaa\x01~\xd3R\xfc\xed\xa3T`\x8e\x92.\x81\ \xf3\xdcp}\x9e\xafj\x80\xd6\x0c~\x19\xae\xe6\xef\xac\ C\xc4\xe8\x00\xc5\x03\xe0\x92\xafF\xa1\xc8|\xffs\x05\ q\x0f\xf8\xc6\x95\xbeJ\x0b\xb8\xac\xa5\xb8\xef\xabX@\ \x5co\xffrY\xd0\xa6\x8a\x01Z\xd3\xfc\xb3\x8f!.\ \xdf_:}\x1f\xd5\x05\xfe\x05\xaey\xea\x15\x92CT\ \xf0\xfdyF\x19\xe0\xbb\xb6D}2N8d\x8b[\ \xed\x22\x89H\xb7\xab\x94\xb1\xb0\xc5\xbdmE\xb6\xd5\xaf\ \xb8\xeeO\x18\xb1z\x8dH\xc3\xda.V\x80\x1b\xfe\xaa\ 5\x8f2\xf6M\xe0[\x86\xc7\xb4%-\xc5\xad\xad\x9e\ \x8d\x81_pGL\xd6\x80\x83\xca\xd8\x0d\x06\xf7\xef\x14\ \x9bS\xd9F\xa7\xaa\xb8b\x12.Y\x9c;G\xa4\x13\ \x9d\xfd\xc0\xdb@\xd9\xae\x90\x8fG\x15>\x93\x85\x8cn\ \x03\xbb**\xdc\x16\x16\xb5\x14\xaeP\xf8\x00Q\x16\xde\ \xda\xb6{ykr\x05x\xafJ\xc2\x08@K\xf1\x09\ \xf0E\x93\x1a\x05\x22\x01>\x07^\xab\x1a\xb8)n\x97\ W\xa4\xfd\xa6\xe8K\xdb\xc0U\xe0C-\xc5\xf28\x0f\ \x0d\xfda\x22\x9bM\x1d\x06\x9e\x9a\x90bMs\x8ft\ \xaa\xbb\xf2\xa8\x15\xe9\xe8\xe8\xe8\xe8\xe8h\x19\xff\x01\xcc\ 8\xfe\xf4\x09,]\x04\x00\x00\x00\x00IEND\xae\ B`\x82\ \x00\x00\x07\x0b\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x06\xd2IDATx\x9c\xe5\x9bm\x88VE\ \x14\xc7\x7f.\x8b\x88\x88\xc4\x22&\x12S\x88\x89\xacT\ \x8b\x86\x99Y\x96\xd8\x9b\xe6h\x92\x1a\xa9\x97B\xa5\xf2\ %\xcb\x0c?\x98De\x1fD\xcbJ-J\xad\x18\xb5\ \x17\x13\xb1\xb1LR4\xc4\xd4\xcc\xcc\x17\x12)\x0b\x1b\ b1\x91\xc5d\x11Y\x96\xa5\x0fs\x1fy\xf6>s\ \xefs\xdf\x9emw\xfd\xc3~\xd83sg\xce\xf9\xdf\ \xb9g\xce\x9c3O\x17\xfegx\xdat\x03\x86\xfa\x7f\ \xb7\x00\x02\xe8\x0dt\x07\xaa\x80+@\x03`\x80\xd3\xc0\ \xcf\xc0~%EC\x1e\xf3w\xc9c\x90\xa4\xf0\xb4\xe9\ \x0aL\x00\xa6\x02\xa3\xb1\xc6&A\x0bp\x08\xf8\x12\xd8\ \xa8\xa4\xb8\x90V\x976%\xc0\xd3\xe6:`.0\x0f\ \xfb\x96\xf3@\x13\xb0\x11X\xa6\xa4\xf8-\xe9\xc3mB\ \x80\xa7M\x15\xf0\x0c\xf0:PS\xa1i\x9a\x81\x0f\x81\ \xc5J\x8a\x8bq\x1f\xaa8\x01\x9e6\xfd\x81\x0d\xc0\xb0\ \x84\x8f6a\x97z\xb7\x84\xcf\x9d\x03f))\xbe\x8e\ \xd3\xb9\xa2\x04x\xdaL\x04>\x06zFtk\x01\x8e\ \x00\xbb\x81\x1f\x81S@\xbd\x92\xe2\xb2?F5\xd0\x07\ \xe8\x0f\xdc\x0e\x8c\xc4\xfa\x8dr\xc4\xac\x00\x16))Z\ \xa2:U\x8c\x00O\x9b\x85\xc02\xac'w\xe1\x1c\xf0\ >\xf0\x89\x92\xc2$\x1c\xbb\x070\x19\xebK\xea\x22\xba\ j`\x8a\x92\xe2JX\x87\x8a\x10\xe0i\xf32\xf6{\ w\xe1\x12\xf0\x06\xf0n\x94b\x09\xe6\x9a\x00,\xc7\xae\ \x10\x17v\x03\xe3\xc2\xe6\xca\x9d\x00O\x9b\xb9\xc0\xaa\x08\ e\x9eRR\xfc\x9d\xf3\x9c\xdd\xb0\x84/\xc0\xbd\xe24\ \xf0\xa8\xebs\xc8\x95\x00O\x9b\x07\x80oC\x94X\x0a\ \xbcR\xee\x9b\xcc8\xff\x18\xe03\xdc>g\x85\x92\xe2\ \xa5\xa007\x02\xe0\x1f\x87\xac\ oXg%\xc5%O\x9b!\xc0p\xa2\x9d\xe0`J\ C\xe9m\xd8|C\x18\x9a\x81\xa3e\xcae.\xdd\xce\ g!\xe0\xacC6(\xea\x01\xff;\xdc\x17\xd5\xc7\xd3\ \xce\x04\xf1\xd94\xc7\xe1\x00j\x1d2\x93\xe5\x138\xe5\ \x90\x0d\xcd0^\xa5q\x87Cv2+\x01A?P\ \xe7'4\xda#F;d\x87S\x13\x10\xb2\x9c\xab\xb1\ U\xdfv\x05O\x1b\x81\xad*\x15\xe32Y\x08\xf0\xb1\ \xdd!\x9b\x91q\xccJ\xe0IJw\xbc\xddJ\x8a+\ Y\x09\xd8\x82M\x80\x14c\xb8\xa7M\xd2Bh\xc5\xe0\ \x17M\x9eu4m\x82\x8c\xf9\x00\xffb\xc26GS\ \xbb\xc9\x08\x01\xcfa\x8b\xab\xc58\x8f\xafw\x1e9\xc1\ 7\x1d\xb2Q\x9e6\xaelQ\x1c\xb8\xc2\xe9\xa8\x10;\ \x14\x9e67\x00\x8b\x1dM\xab\x0a\xc7\xf6\xcc\x04()\ \x0e\x03;\x1cMk\xfcjQR\x1c\xa0u\xc4\xd8H\ \x8a,\x93\x9f\xaew\x95\xe6\x1b\x80\xd5\x85\x7f\xf2\xaa\x0c\ \xbdH\xa9/\xe8\x0d|\xe1\xdf\x07\x8a\x0d\x7fw\xb9\xdb\ \x1f\xf35`\x88\x92\xe2t\x0a\x9d^\xc5\xbd\xf5-)\ \xbeA\x92gmp%\xf0\xbc\xa3\xe9s`j%\x8b\ \xa2\x0e]f\x02k\x1dM\x87\x80\xbb\x8au\xc9e\x05\ \xf8\xe9\xf1'B\x9a\x1f\x076%]\x09\x19t\x99\x8d\ \xfb\xdcp\x09\x98\x1e|\x11y\x94\xc6j\xb1\xf9\xb6r\ \xb7\xbe\xf6aok\x84&M2\xeaQ\x8d\xbd(\xe1\ Z\x85-\xc0$%\xc5\xd6`C\x1e\x85\x918\xc6\x03\ \xdc\x03\x1c\xcf\xb0;D\xe9q+p\x10\xb7\xf1`\xef\ \x0a\x95\x18\x0f\x19V\x80\xa7M_\xe0\x17\xd2\xdd\xf7\xdb\ \x83\xbd\xcev(\xed\xfc\xbe\x0e\x85mn&\xee\x92\x1a\ X\xa7\xb74l\x8c,\x04T\x01?\x90\xfc\xfa[1\ \x0e\x00\xeb\x81mq\xaf\xbe\xfa\xbed46\xb9:\x91\ \xd2$G\x01-\xc0|%\xc5\xea\x90v \xa3\x0f\xf0\ \xb4\xe9\x87Mtf=\x016c\xebw\x87\xb1\xa5\xf6\ zl\x86\x07l\xf2\xa4\x0fp36Y2\x9c\xf2\xb9\ \xc5\x0b\xd8\x9d\xe7\xbbr\x13\xe7\xe1\x04Ga\xef\x05\x85\ \xbd\x89\xf3\xc0\xa7\xc0\xec\x88>yBc\xaf\xe4\xc4r\ \xb6\xb1\x9d\xa0\xa7M\xad\xbf\xc5\xb4\x82\x92b\x0f0\x85\ \xd2@\x08\xac\xf1\xf7\xf9\xb7Dn\xc3\x1d1\xe6\x85\xd3\ \xc0x%\xc5\xf8$;M\xac\x15P\xe4\xedk\xb0\x06\ \xedw\xf4\x19\x85\xbd\xbd]\xf8\x1c\x0a\xc6\x9f\x0a\xf4\x1b\ \x8a\x8d\xf2&\x90\xcf\x8a8\x04\xbc\x03lN\x13l\x95\ %\xc0\xb1\xd5\x9d\xc7^}\xf9\xd3\xd1\xb7\x1f\xf6\x98\xd9\ \x0f\x87\xf1\x81\xbe\xbd\xb0\xe5\xf5q\xd8-2n\xcd\xa0\ \x19[\xe6\xfa\x06\xd8\x125G\x1cD\x12\x10\xb1\xcf\x9f\ \x01F*)\xea\x1d\xcfT\x01}\x5cm\x11\xf3Tc\ \x93\x96\xb5\xd8\xd2\xd8\xf5XB\xaa\xb0'\xc1\x06\xe0/\ \xec2?\xe1W{sA(\x011\x82\x9c3\xc0\x83\ \xae\x95\xd0\x91\xe0t\x821#\xbc\xfe\xc0AO\x9b\x11\ \x95P\xac\xadPB@\xc2\xf0\xb67\xb0\xd7\xb5;t\ \x14\xb4\x22 \xa1\xf1\x054\x00\xdf\xe7\xa8S\x9b\xe2\xaa\ \x0fHi\xbcs\xab\xebH\xe8\x02\xd7\xae\xf1\x00]\xfc\ \xfd\xf88\x11\x85M\x07:\x85\xf1`}\xc0\x22\xaeQ\ \xe3\xc1\x12\xf0P\x82\xfe\x9d\xcax\xb0\x04\xc4\x0dA;\ \x9d\xf1`\x09\x88\x93r\xee\x94\xc6\x83%`M\x99>\ \x9d\xd6x\x80*\xff\x17\x96o\x85\xb4\xd7\xd3\x89\x8d\x87\ \xd6\x81\xd0#\xc0\x1c\xec\x8f\x1f\x1a\x81\x9d\xd8\x1f$\xa7\ \xfeevG\xc0\x7f\x0d\xed,-\xc3\x0e\x9b\xe3\x00\x00\ \x00\x00IEND\xaeB`\x82\ \x00\x00\x07\x16\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x06\xc8IDATx\x9c\xd5\ \x9b_\x88UE\x1c\xc7?\xbb\x88DO\xb2\xc4&\xb6\ \x0c\x8bHD\x88\x0f\x12\xf9\xd0C\xa8\x88\xc8\xe2@Q\ \x0f\x06QG\xad\xd4\xdat\xb3U\xd6?\x88\xff\xcd\xfc\ WV\x96EC\x85E\x12\x04\xc7\x8743\xe9\x0f\x16\ >\xf8 \x12\x11\x11r\x10\x11\x09\x91EB\x16Yz\ \x989:w\xee9s\xcf9\xf7\xdc{\xcf~\xdf\xee\ \xdc\x99\xf9\xcd\xf7{\xcf\xcc\xf9\xcd\xef\xf7\xbb]L@\ \x04a4\x0f\xd8\x0fD\xc0\xa0\x92\x22*:WWi\ \xabj\x13\x820z\x1a8\x06\xdcg\x9a\x22`\x81\x92\ \xe2\xaf\x22\xf3u\x97\xb5\xb0v \x08\xa3\xe7\x80\xaf\xb9\ G\x1e@\x00g\x830z\xb4\xc8\x9c\x13F\x80 \x8c\ \x96\x02\x9f\x01\x93\x12\xbe\x9e\x06\x9c\x09\xc2hf\xdey\ '\xc4\x16\x08\xc2h9\xf0\x11\xb5?\xd88\xf5?\xe0\ u`\xbe\x92\xe2R\xd6\xb9+\xff\x04\x04a\xb4\x82z\ \xf2\xb7\x80\x05\xc0\x87N\xf7^r>\x09\x95\x16 \x08\ \xa3U\xc0\xfb\xd4\xaes\x14X\xa4\xa4\xf8\x11x\x15x\ \xcf\x19\x96K\x84\xca\x0a\x10\x84\xd1k\xc0a\xea\xc9\x0f\ ()~\x05PR\x8c\x03\xab\x81w\x9d\xe1\x99E\xa8\ \xa4\x00A\x18\xbd\x0e\xbc\x83\x87|\x0c#\xc2\x10p\xc8\ \x99&\x16\xc1\xfbv\xa8\x9c\x00A\x18\xad\x01\x0eR\xbf\ \xb6A\x97|\x0c#\xc2Z\x0a\x88P\xa9\xb7\x80!\xbf\ \x9f\xe4\x1f\xe6\x0a\xfa\x84Oux\x820\xea6\xe3\xd7\ 8_]\x03\xe6*)\xfet\xc7TF\x80\x06\xe4c\ \x5cA\x13\xf9\xdb3O\x9a\x08W\xcd\xd8\x1a\x01+\xb1\ \x05R\xc8\x8f\x02\xa1\xd3\xb5\x0f8\x1d\x84Q\x7f\xda\x5c\ \x9e\xed\x10;K3\xec\xc6\x8e\x0b\x10\x84\xd1\x9b$\x93\ \x1f\x00\x9e\x02\x8e:C\xfa\x81\x13A\x18\xdd\x9f6\xa7\ G\x84>\xb4\x08\xfdqCG\x050\xe4\xdfv\xd61\ \x869\xed\x0d\x91\x95\xc0\x07\xce\xd0\x99\xc03\xbe\xb9=\ \x22\x08\xb4\x08}\xd0A\x01,\xf2.&\x03\xf3\xe2\x0f\ \x86\xc8 p\xc0\xea3\x0e\xfc\xd3\xc8\x86G\x84\xe9\xe8\ \xad\xd4\xdb\x91C\xd0C\xde\xc6\x16%\xc56g\xdc\x0a\ `!pBI\xf1i\x0e{i\x07\xe3\xc9\xb6\x0b\x90\ B~\x14\xfd\xabNq\xda\xebDh\xc2\xeel\xe07\ \xf4\x13\x16\xe3b[\x05\xf0\x90_\x88\x16\xe0\x14-\x10\ \xc1\x90?\x05<`5\x8f\x03K\xdav\x06\x18\xf2o\ 9\xcd\xa3\xc0B%\xc5\xefJ\x8a\xf3h!n:}\ \xb6\x06a\xb4\xa9\x09\xbbi\xe4W*)\x8e\xb7E\x00\ \x8b\xbcko\x0c\xf8/\xfe\xe0\x11a{\x10F\x1b\x0a\ \xd8M#?\xa8\xa48\x0am\xf0\x04=\xe4c\xfc\x8b\ vq/Zc\x1e\x07\xbe\x03z\xac~\xe3\xc0\x90\x92\ \xc2\xbd\xf9\xa5\xd9M\x22\x0f\xb0VIq\xf7\x8d\xd2R\ \x012\x90\x8fq\x1d\xed\xa6\xfea\x8dM\x22p\x07\x1d\ \x0b\xf8\xa1\x81\xdd4\xf2\xc3J\x8a}vC\xcb\xb6@\ \x0a\xf9\xf8\xc0s\xbd\xbb^\xe0T\x10F\x22nPR\ \x5c\x00\xe6\xa3\xc5\x891\x09x\xb6\x81\xdd4\xf2\xeb]\ \xf2\xd0\x22\x01<\xe4\x07\x94\x14\xdf\xa3\xbd\xbb$7\xf5\ \x0b\xbb\xc1l\x8b'\xd1\x97 \xd0\xdb\xe0[\x8f\xdd4\ \xf2#J\x8a\xbdIcJ\x17\xc0\xf3\xd8\x9f\x04\xce\x81\ \xf6\xd0\x94\x14C\x80\xbb\xa8~w>s\x85\x9d\x03\xbc\ \x00\xccQR\x9cL\xb1\x9bF~\xb3\x92bO\xdaz\ K=\x032\xec\xf9C\x86\xb8=f\x1d\xb0\xd3\x8c\x19\ TR\xb8~\x7f\x16\xbb>\xf2;|cK\x13 \xc7\ \x81\x97$\xc2t`LIq%e\x8c\xcfn\x1a\xf9\ L\x0eT)\x02x<\xbc!`7\xfa\x90\xb3\xb1W\ I\xb1\xbe\x04\xbbM\x91\x87\x12\xce\x00\x0f\xf9\x01sa\ \x99\x8f\x0eI\xd9X\x17\x84\x91\xf7:\x9b\xc1n\x1a\xf9\ \x1dy\x5c\xe7\xa6\x04\xf0\xdc\xeaF\xac\xd0\xf5%\xb4\x08\ W\x9d>K\x9a\xb0\xeb#\xbf9\xcf\x5c\x85\x05hp\ \xa5\xddi\xbc9\x00\x8c\x83\xf3$p\xd9\xea\x93\xfa:\ k`w6p\x9a\x12\xc8C\xc13 \xe3}\xfe&\ \xfa\xa2s\xde\x1a\xd7\x8b\x8e\xe4\x5cL\x0bq7\xb0\x1b\ \x93\xefq\xbe*D\x1e\x0a\x08\xe0\xd9\xf3\xdf\x00K\x9d\ \xf6:\x11\x8a\xa2\x15\xe4!\xe7\x16H!\x7f\x0bX\xac\ \xa4X\x06lq\xbe\x9b\x82vq\x1f+\xba@c7\ \xde\xf3\xa5\x92\x87\x1cO@\x10Fo\xa0\xc3J6\xee\ \xa0or?[\xfd6\x01\xdb\x9d~7\xd0U\x1c\x17\ \xf2.\xb0\xcc\x03/\x09\x99\x9e\x00\x13\xb7O\xda\xf3\x93\ \x80\xe7M\xcc\x0d\x00\xe3ymt\xfa\xf5\xa0\x9f\x84\x5c\ U\x1c\xad&\x0f\x19\x9e\x80\x8c\x19\x9bO\x80WL\x14\ 6\x1e\xb7\x01\xed\xe2\xda\xb8\x0a<\xa1\xa4\xb8\x9c\xc1n\ \x1a\xf9=J\x8a\x91F\xe3\xb3\xc2\xfb\x04\x98,mR\ \xd2\xc2ul\x96\x03\x87\x9d'a\x170\x82\xbe\xc1\xc5\ \x98\x86.s\xf1\xa2]\xe4\xc1#\x80\xc9\xcf\xbbY\xda\ Q`\x11\xb5W\xd4\x18\xab\x80\xadv\x83\xb9\x85\x0dS\ +\x82\x1b\xf4t\xed\xb6\x8d<\xa4\x08`\xc8\xa7\xe5\xe7\ \xcf\x99\x04\xe3\x5ct\x89\x9a\x8d\x0dn\xee\xcd\x84\x9f^\ \x02n\xa3\xe3\x7fn`\xd4\xb6\xdbV\xf2\x90 \x80)\ Kq\xc9\x83&p7Xi2\xb4s\xa9\xcd\xd0\x8c\ \xa3\x03\x9d50w\x82\x87\x80\x07\x95\x14_&-\xa4\ \x13\xe4\xc19\x04M\xe6\xc5\xad\xc9\xb1q\x0d\xfd:\xbb\ d\x8d\xe9\x03\x14:\xe7vPI\xe1\x16.5D\xa7\ \xc8\x83%@\x10F/\x03G\xa8OTNv\xc6\xd4\ \x89\xd0\x0c<\x1e\xde.%\x85\xfb:-\x1d\xddf\x11\ /RO~\x14\xfd\x88\x1fp\xc6LE'\x16\x1fi\ \xd6x\x03\xf7\xb6\xe5\xe4\x01\xbaM\xed\xed\xc7$\x97\xa2\ \x9dC\x9f\xe2I\x22\x1ck\xc6p\xab|\xfb\xbc\xe8F\ {mv\xf9\xe9\x18\xf7\xc8\xc7)\xe6a\xea\x03\x98\xd3\ \x8a\x1am\xa5o\x9f\x17\xdd\xd4\xc6\xddA\xef\xf9\xc5v\ \x83\x89\xe2\xaeG\xe7\xdao\xa3E\xda]\xc4\xa0\xe7\xc0\ \xdb\xd6n\xf2\x00]A\x18M\x05~\x01f8\xdf%\ \x9e\xc0A\x18\xf5\x00()n\xe45VF\x0c\xafl\ t\x01\x98\x8c\xccO\xd4\xc7\xe5K{\x0dU\x91<\xd4\ \xbe\x06\xa7\xa3E\xe8s\xfa4-BU\xc9C\xbd#\ \xf40p\x96\xfa\x03\xae\xb0\x08\xcd$-\xda\x81\xba\xeb\ \xb0\xb9\xb3\x9fA\xbf\xeal\xe4\x16\xc1C~\xa3\xb9-\ v\x1c\x89\xf1\x00#\xc2Y\xea\x13\x1a\xfb\x94\x14\xc3Y\ &\x9e\x08\xe4\xc1\x13\x101\xa5\xe6g( B\x83,\ mj\xa2\xb2\x13\xf0F\x84\x820\x9a\x85\x16\xc1%\x92\ *B\x83\xfc|b\x8a\xba\x93\xc8\x12\x12\xcb,B\x9e\ \xca\x8c\xaa ST8\x8b\x08\x9e\x82\xa4a\xbb&\xa7\ j\xc8\x13\x16O\x15\x01\xf8\x8ad\xf2k\x95\x14n%\ H\xa5\x90+3\xe4\x11\xe16\xb5\x7ff\x1c\x07V+\ )\xdc?4U\x0eERc\xb3\xd0\xd7X\xf7\xed\x10\ #\xae\xc3\xcb]\xe9\xd1\x09\x14M\x8e\xceD\x8b\xe0:\ Kq\x05\xa6[\x05VY\x14\xae\x101\x11\xa1\xd3\xdc\ \xbb;\xdc\x01\x96))>/ca\xedBS%2\ \xe6\x9f\x17G\xd0\xf5\xf7\x9b\x95\x14\xc7\xcbXT;\xf1\ ?\xe8\xfd\x16\x86\x923G\x09\x00\x00\x00\x00IEN\ D\xaeB`\x82\ \x00\x00\x07\xbc\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x07nIDATx\x9c\xcd\ \x9bk\xa8]\xc5\x15\x80?/\x97\x10B\x10\x91\x8bZ\ \x89C\x9a\x86\x90\xd6`5>\xa0\xa9\xdaTZ\x7f\xf8\ \x98\xfa\xd6\x22I\x1c\xdf\x0a\x0a\x96J\x0d\x9aJH\xcb\ m\xeb\xeb\x8f\xaf\xda\xea$\x1a\x8c\x12#\xe9\x18DE\ B\x0cA\x05c^\x84KL\xe3\x83!\xda AD\ .!\x84p\xf1\xc7\x9a\x90\xd3\x93=\x8f\xbd\xcf>\x07\ ?\xb8?\xee>3k\xd6\xac\x99=kf\xcd\xda\xc7\ 1\x00\x8c\xf3\xf3\x80\x87\x81S\x81I\xc0\x100\x1c~\ \x9e\xe8\xf8;\x14\xfe\xf6\x03\xa3V\xab\x0d\xfd\xd6\xed\xb8\ ~7`\x9c\x1f\x01\xfe\x0b\x9cP\xb3\xea\x01\xe0\xa7V\ +\xdf\xbeVG\x19\xea\xa7\xf0\xc0y\xd4\xef<\xc0\x14\ \xe0\xcc\x96u9\x86A\x18`j\x0fu\xfb\xae\xdf \ \x0c01\x806\x1a3\x08\x03\xec\xef\xa1\xee\xb7\xadi\ \x11a\x10\x06x\x1f\xd8\xd8\xa0\xdef\xe0\xc3\x96u9\ \x86\xbe\x1b\xc0ju\x08\xf8-p#e\xb3\xe1;\xc0\ \x00\x17X\xad\x0e\xa6\x0a\x1a\xe7\x87\x8d\xf3\xc7\xf7\xa2_\ \xdf\xdd`'\xc6\xf9O\x81\x19\x99b\xfb\xacV?*\ \x905\x1fX\x0d\x9c\x88\xcc\xb0[\xacV\x9f\xd5\xd5i\ \x10\xaf@'\x93\xda(c\x9c?\x03\xf8\x0f0\x82\xf4\ a>\xf0\xb1q\xfe\xb2\xba\x0a\x0db#4\x0c\xcc\x05\ .\x02\x96 \xfe=\xc5!`)\xb0\x1e\xd8l\xb5:\ \xdc%o\x04\xf8\x08\x98^Qw\x02Xl\xb5\xfaG\ \xa9~}1@\xe8\xf4|`\x01p\x092RM\xf8\ \x06X\x07\xac\x02\xdeEF\xfb\xed ;\xc5\x02\xab\xd5\ \xca\x92\x06Z5\x80q~\x0ap+p\x0f0\xb3M\ \xd9\xc0^\xc0\x03\xf3\x0a\xca\xae\xb3Z]^\x22t8\ _$\x8fq~\x08X\x08,\x03\xa6\xb5!\xb3\x82i\ 5d\xef*\x15\xda\xb3\x01\x8c\xf33\x00\x0b\x5c\xd8\xab\ \xac\x96\xd8\x0b\x8c\x96\x16\xee\xc9\x0b\x18\xe7o\x00\xb6\xf2\ \xc3\xe9\xfc!\xe0\xf7V\xaboJ+4\x9a\x01a\xca\ /\x03\x1e`\xf0\xae4\xc5\xfdV\xabMu*\xd46\ @X\xe1\x9fA\x16\xbb\xbaxd\x8b\xbb\x0b\xf8\x12\x18\ G\x5c\xd7\xf1\xc0i\xc0l\xc4e\xaa\x06\xb2\xbf\x06\xfe\ ]\xb7R-/\x10F\xde\x22\x0b^)\xbbC\x9d\xd7\ \x81=V\xab\xe4\xe90\xb41\x13\xb8\x02X\x04\xfc\xac\ F[\xaf\x03\xd7w\xef\x1dR\xd45\xc0c\xc0\x1f\x0a\ \x8b\xef@\xc2`.\xd7\xe9D{C\xc0\xc5\xc8\xebv\ Na\xb5g\xadVw\x95\xb6Ql\x00\xe3\xfcM\xc8\ H\xe6\x18\x07\x1e\x04\x9e\xae3\x12\x99\xb6\x87\x80\x9b\x81\ G(\x8b.\xdda\xb5z\xaeDv\x91\x01\x8c\xf3\xb3\ \x91\xedg.\xba3\x06\x5cm\xb5*\xf6\xc3u\x08.\ w\x0d\xf9P\xd9A\xe0\x5c\xab\xd5\xce\x9c\xcc\xec\x0a\x1e\ \xac\xff<\xf9\xceo\x00~\xd1\xaf\xce\x03\x84\xd3\xde\x05\ \xc0[\x99\xa2\x93\x81\x15a\xc1NR\xe2\xc2\x16\x92\xdf\ ~\xae\x07.\xb5Z}W \xaf'\xacV\xe3\xc0\xef\ \x8073E\xe7\x02\xb7\xe7\xe4%_\x81\xb0\xb7\xff\x84\ \xf4\x16t\x0c\xf8\xa5\xd5\xaa\xef\xe1\xabN\x82n\xef\x91\ ^\x1c\xf7\x03?I\x0dLn\x06\xdcL\xba\xf3\xe3\x88\ \xeb\xb97\x9c\xd1\x07\x86\xd5\xea\x00p-\xe9\xb8\xe1\x08\ pgJNt\x06\x84w\xff\x13\xd2\xa7\xbaw\x107\ \x05\xb2\xa1Y\x07,\xb5ZmI5\xda&\xc6\xf9\x85\ \xc0\x8aD\x91\xbd\xc0\x8fc\x1e)5\x03.\x22\xdd\xf9\ -\xc0\xab]\xb24\xf0\x91q~\xb5q\xbe\xce\x06\xa6\ \x17V\x22\x81\xd7\x18\xd3\x90\x98D%)\x03\xdc\x98i\ x\x09\xf0\x22\xe0*d^\x03l7\xce[\xe3\xfc\xf4\ \x8c\x9c\x9e\x08\x9b\xac%\x99b\xd1\xbeT\xbe\x02\xc1}\ |\x09\x9c\x14\xa9\xb7\x0b8\xddj5a\x9c\x9f\x04\xfc\ \x13\xb8)R\xf6 \xf0\x1c\xf0W\xab\xd5\xd7\x19E\x1b\ c\x9c\xdfJ|\x7f\xf0-pr\x88P\xff\x1f\xb1\x19\ 0\x87x\xe7\x01V\x1c\xd9\xde\x06\xa1\xb7 \xa3P\xb5\ \xe5\x9d\x0c\xdc\x0b|j\x9c_\xd6k\x18;\xa5S\xe2\ \xb7\x13\x90;\xcac\x88\x19\xe0\xfcLck;\xff\xb1\ ZMX\xad\xfe\x02\x5c\x8f\xdc\xeaV1\x15x\x081\ \xc4\x1f\x83\x1bk\x93\xb5\x99\xdf+\xf721\x03\xfc<\ !h\x1fr\xc2;\x06\xab\xd5k\xc0\xaf\x90\x957\xc6\ \x08\xb2\xa7\xff\xdc8\x7f\xe4o\x95q\xbe\xf4\xb0S\x89\ \xd5\xea\x0b\xe0\x8bD\x91\xb3\xab\x1e\xc6\x0c0+!h\ K\xeatg\xb5\xda\x0c\x9cK\xfeZ\xeb$$\xb4=\ \x1d\xb8\x01\xf8\xc08\x9f\xdd\xb9eH\xb9\xdf\xca>\xc5\ \x0c\x90\xda\xfcT\x8e~'V\xab}\xc0\xaf\x11\x17U\ \xca0\xf0\x94q~n\x8d:\xdd\xa4t;\xa5\xeaa\ \xcc\x00'&\x04\xfd\xafD\x13\xab\xd5A\xab\xd5\x02`\ 1\xe5W\xe4\xc3\xc0\x9f\x0a\xcbV\x91\xd2\xad\xb2O1\ \x03\xa4\x16\xa8\xf1bu\x00\xab\xd5\xdf\x80+\x91K\xcf\ \x12f\xd7\x91\xdfEJ\xb7\xca+\xb7\x98\x01Z\x0dt\ Z\xad\x1cr\x8c\xade\xbcA\x10\xebh\xcc\x95A\xc3\ \x94\x17\xab\xd5\x0e\xe0\xb5\x82\xa2cM\xe4\x07R3\xb7\ \xf2\xaa=f\x80T\x5c={u\x9d`4\xa6H\xe0\ 0\xe2\x22\x9brr\xe2\xb7\xca>\xc5\x0c\x90\xf2\xe3)\ \x17\x99\xc4j\xb5\x1bI~\xa82\xc2a\xe0\xae\x1eO\ \x92)\xdd\xbe\xaaz\x183@\xca\x9d\xcc\x0dG\xe5F\ X\xad^\x01\xceBb\xf8;\x80m\xc8Y\xe1l\xab\ U\xed\xb8~\x17\x95\xdb\xdd\xc0\x9e\xaa\x87\xb1\x98\xd9\xd6\ \x84\xa0S\x10K7\x8e\xfd\x85\xb8\xe1mM\xebW\x11\ \x02\xa6\xd3\x13E\xb6W=\x8c\x8ddn\x17wU\x81\ N\x83&\xa7Se\x9fb\x06\xd8F:\xa1iQ/\ \xafA\xdb\x04]\x16%\x8a\x8cS\xc7\x00!|\xd4\x1d\ \xe8\xe8d\x16P;\x1f\xa7\x8f\x5c\x8c\x1c\xe1c\xbc\x13\ \xcb8K\x8d\xe2\xaaL\xa3\xcbJ\xe2\xee\xfd\xa6\xe3\xa6\ :\xc5K\xb1\x1fR\x06XOd\xe5\x0c\x9c\x01\xdc\x9d\ ix\x10\xdcN:4\xfe\x15\x12\xac\xad$j\x80p\ \xe4},\xd3\xf8\xa8q>5\xf5\xfa\x8aq~\x16\xf0\ \xf7L\xb1'Rw\x94\xb9\x85l9r\xa7\x1fc\x0a\ \xb0\xc68\x9f:=\xf6\x85\x10Z[\x8d\xe4\x16\xc4\xd8\ \x07<\x9b\x92\x934@X8\x16gt\x99\x05\xbca\ \x9c\xef%-\xbe\x16!\x9c\xb6\x06y\x0dS<\x1c\xae\ \xd2\xa2d]\x99\xd5\xeae$G/\xc5<\xe0\xedA\ \xcc\x840\xf2o\x00\xbf\xc9\x14}\x9f\x82\x8c\x91R_\ ~\x1b\xf9\xd4\xf5yHX\xabokB\xb8\xa6\xff\x00\ \xb9\xb4I1\x8e\xe4\x0eg\x031u\x12$\xaeAn\ \x82rF;\x80$H<\xd9b\x82\xc40r\xc77\ J\xd9q\xdcX\xad\x96\x97\xc8\xae\x9b\x22\xb3\x14\xf8s\ a\xf1\x9dH\x8a\xcc\xda\x1eSd\xae\x08rJ/_\ \x1f\xb5Z\xdd_\xdaF\xdd\x8d\xccR\xe40T\x12\xbd\ \x9d\x83,T{\x8c\xf3/!q\xfb\x9d\x85IRs\ 8\x9a$\x95K\xaf\xef\xe4\x05j\xc6\x14k\xe7\x0a\x07\ \x05\x9f\xa1\xcc\x08\xdd\xecG\xce\x19\xbb\x91\x00\xe6\x914\ \xb9\xa9H\xa0e\x06\x92\xd8P\x19\xc1\xcd\xb0\x9c\xc2\xf7\ \xbe\x93F\xc9\xd2\xc1\x08\x0f!S\xf3\x87p(z\x1c\ I\x92\xac\xfd\xaa\xf5\x94-n\x9c\xbf\x0a\xc9\x1fj\xf2\ ]`\x1b\x8c\x03\xf7\x94.xU\xf4\x9c.o\x9cW\ \xc0\xbf8\x9a(1(6 \xe9p\xd9\x8b\x9a\x14\xad\ }/`\x9c\xbf\x0eqSu\x16\xad&x\xe4&z\ eS\xef\xd2I\xdb\x1fLLB\xb2\xca\xee\xa3^\x8a\ k\x09\xbb\x81'\x80\xe5\xb9\xaf\xc9\xea\xd0\xafOf\x86\ \x90+\xf6\x05H\xe0\xa4\xc9\xaa\x0er\x98qHlb\ c\x1b#\xde\xcd >\x9a\x1aB61\xe7#\xd7\xee\ 3\x11\x83L\xee*z\x18\xc9\xf8\x1e\x03>\x066\x01\ c\xfd\xe8t'\xdf\x03L6#\xd1pEpr\x00\ \x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x025\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x01\xfcIDATx\x9c\xed\xd9MJ\xc3P\ \x14\xc5\xf1\xbf\xd2\xb1\xc3\x82 \xc1\x1dt'YB\xc0\ }X\xa4\xd8\x95d\x09\xd9\x82+p\xecDBAq\ \xe8\x02\x8a\x03\xfbJ\x11M_>\xde=7&\x07\x0a\ -M\x93{~4\xedK{QT\xf5\x13pC\xf7\ \xac\xca<\xfb\xec\xfa\xe2\xa2\xaa7@\xd1\xe3\xf8}\xb2\ [\xf0]\xfe\xb6\xc7N.{\x0e\xb19\x1c_\x82\xd0\ w\xf8\xde)\xf3l\x0f\xdc\x01\xa5\xe2\xf8r\x00\xd0\x22\ \xb8\x00\x00\x1d\x82\x1b\x00\xd0 \xb8\x02\x00{\x04w\x00\ `\x8b\x10\x03\xb0\x02\xae\x1bn\x9d\xd7\x00M\xb1BX\ Dl\xf3Q\xe6\xd9{\xca!\xfeJ\x99g\xfb\xa2\xaa\ \xef\x0e\x0f\x93\xac\x13\x5c\x9e\x02\xa7I\xfdNp\x0f\x00\ i\x11F\x01\x00G\x84\x97\xa1\xf7;\x1a\x80\xa2\xaa\xef\ \x81\xc7\xa1\xf7;\x0a\x80T\xe5a\x04\x00)\xcb\x83s\ \x80\xd4\xe5\xc11\x80Eyp\x0a`U\x1e\x1c\x02X\ \x96\x07g\x00\x03\x94_\xd3r\xb1\xe4\x06`\x88\xf2e\ \x9emi\xb9bt\x010`\xf9\xd6\xcbf9\xc0\x90\ \xe5C\xda H\x01R\x94\x0f\x89E\x90\x01\xa4,\x1f\ \x12\x83 \x01\xb0(\x1fr\x0e\xc1\x1c\xc0\xb2|H\x13\ \x82)\x80\xa2|\xc8_\x08f\x00\xca\xf2!\xbf!\x98\ \x00x(\x1f\xf2\x13!9\x80\xa7\xf2!\xa7\x081?\ \x8b+3x\xf9\x90\x03\xc2C\xf2w\xc0\xa1\xc0\xba\xc3\ K\x93\x95?\x8d\xc9g@\x07\x04\x93\xf2`\xf8-\xd0\ \x02\xc1\xac<\x18\xaf\x03\x22\x10L\xcb\x83`%\xd8\x80\ `^\x1eD\xd7\x02\xbf H\xcaC\xdc\xbf\xc3IR\ \xe6\xd9\xb6\xa8\xea\xe3}\xd5\x1c\xd2u\x80\xb2x\x88\xfc\ \x17!uf\x00\xf5\x00\xea\xcc\x00\xea\x01\xd4\x99<\x80\ \xf7\xcb\xe1^)\xaa\xfa\x12\xb8j\xd8d\xff\xaf\x01\x80\ %\xf0\xd6\xf0\xfc\xeb\xe4O\x81\x19@=\x80:3\x80\ z\x00u&\x0f\x10\xf35\xb8\x0c\xd7\xed#\xcc\xf2\xdc\ \x061\x00\xcf\x03\x0c\xe26\x93?\x05f\x00\xf5\x00\xea\ \xcc\x00\xea\x01\xd4\x99<\xc0\x02\xd8\xa9\x87\x10f\xf7\x05\ \xb8#\xcf+\xc2\xe7\xc0_\x00\x00\x00\x00IEND\ \xaeB`\x82\ \x00\x00\x15\xec\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x02\x00\x00\x00\x02\x00\x08\x06\x00\x00\x00\xf4x\xd4\xfa\ \x00\x00\x15\xb3IDATx\x9c\xed\xdd\x7f\x88\xe4w\ }\xc7\xf1\x97\xc7r=\x8e\xe3z\x04\x09A\xca\x10D\ \x82\x15\x15\x11)bA\xc4\x8a\xa4EF\xb1?\xa8\x14\ \xa7`\x15\xb5V\xac\x88\xa5\x22A\x8aH\xfe\xb0\xd6\x16\ \xadQlK\x1d\xa9\x14\x7fU\x06\xa1ZZ\x9b\x16k\ K(\x22VD\x82H:H*r\xbd^\x8fe\xb9\ .\xcb\xd2?f\x0e\xd7\xf36\x97d\xe7\xbb\x9f\xcf|\ \xdf\x8f\x07\x0c\xb7\x99\x5cv\xdf\xd9\xd9\xef\xf7\xfb\x9c\xef\ \xafM\x00\x80r\x9e\xd2z\x00\x9e\xb8\xd9by6\xc9\ \xc5\xf5\xe3\xdc\x91\xc7\xd9\xf5cg\xfdg\x92\x5cZ\x7f\ |!\xc9\xf9\x9b>\xd5O\xad?\xc7\x99[|\x99[\ \xfd\xfd\xa3.\x1e\xf9\x1a\xc79\xbf\xfe\xbe~\xe4\xb1{\xe3\xf3\ \xcf\xa7\x93\x9b\xbf.[B\x00l\x89\xd9b\xb9\x93\xe4\ \xb9I^\x96\xe49I\x9e\x9a\xd5\x06\xf0\xfc\xfaq#\ \x00\x8e\x86\x00\xc0\x93u=?\xda\xf0\xef'\xd9\xcb\x8f\ o\xfc\xaf\xae\x1f\x8f&\xf9\xcf$\x0f'\xf9\xf6|:\ \xb9\xd2dZ\x9e0\x01\xd0\xb1\xd9by)\xc9\xb3\x93\ \xbc8\xc9/'\xb9'\xab\x0d\xfcN\xcb\xb9\x00\x8e8\ \xc8jo\xc2\x8d=\x06\xdfK\xf2\xa5$\xff\x90\xe4\x9b\ I\xae\xd8K\xd0'\x01\xd0\xa1\xf5.\xfeW%ye\ \x92{\xb3z\xa7\x0f\xb0Mv\x93<\x98\xe4sI>\ 5\x9fN\xf6\xdb\x8e\xc3\xcd\x04@Gf\x8b\xe5\x1dY\ m\xf0\xdf\x90\xe4\xf9Y\x1d?w\x8c\x1b\xd8f\xbbI\ \xbe\x9a\xe4\x83I\xbe:\x9fN\xf6\x1a\xcf\xc3\x9a\x00\xe8\ \xc0\xfa\xf8\xfe\x8b\x92\xbc%\xabw\xfe\x8e\xdf\x03cs\ -\xc9_$y`>\x9d<\xdcz\x18\x04@S\xb3\ \xc5\xf2L\x92\xbb\xb2\xda\xf0\xbf.\xc9\x9d\xf1\x8e\x1f\x18\ \xaf\x83\xacN\x16|_\x92/\xd8\x1b\xd0\x96\x8dM[\ /I\xf2\x99$\xbf\x9fU\x08x=\x801\xdbI\xf2\ \xac$\x7f\x9e\xe4\x83\xb3\xc5\xf2\xee\xb6\xe3\xd4f\x0f@\ \x03\xb3\xc5\xf2|\x92W'yO\x92g4\x1e\x07\xa0\ \x85\xfd$\xff\x9c\xe4\xedY]>\xe8J\x81S\xe6\x1d\ \xe7)[_\xda\xf7\xfe\xac\x0a\xd8\xc6\x1f\xa8\xealV\ \xf75\xf9L\x92\x976\x9e\xa5${\x00N\xd1\xfa,\ \xff\xfb\x92\xfcv\x9c\xe8\x07p\xc3\xb7\x93\xbcv>\x9d\ |\xbd\xf5 \x95\x08\x80S2[,\xefJ\xf2@\x92\ i\xecy\x01\xb8\xd9#I\xde9\x9fN>\xdbz\x90\ *\x04\xc0)\x98-\x96OMr\x7f\x92\xd7\xb7\x9e\x05\ \xa0c\xcb$\xbf1\x9fN\xbe\xdaz\x90\x0a\x04\xc0\xc0\ f\x8b\xe5\x85\xac\x8e\xf9\xbf>n\xe1\x0bp;\xdf\xc9\ \xea\xd2\xe8\x07\x9d\x188,\xbb\xa2\x07\xb4\xbe\xa5\xef\xeb\ \xb3\xba\xc6\xdf\xc6\x1f\xe0\xf6\x9e\x99\xd5\x1e\xd3\xbbZ\x0f\ 2v\x02` \xeb\xbb\xfb\xfdZ\x92w\xc5\x09\x7f\x00\ O\xc4\x0b\x92\xdc\xbf\xbej\x8a\x81\x08\x80\xe1\xdc\x93\xd5\ \x19\xffw\xb6\x1e\x04`\xcb\x9cI\xf2+I\xde>[\ ,\xcf\xb5\x1ef\xac\x04\xc0\x00\xd6\xc7\xfd\xef\xcb*\x02\ \x00x\xe2\xce'\xf9\xdd$\xbf\xd4z\x90\xb1\x12\x00\x1b\ \xb6>\xee\xff\xba$\xafh=\x0b\xc0\x96\xbb\x98\xe4\xbe\ \xd9b9i=\xc8\x18\x09\x80\xcd\xbb;\xab3X/\ 4\x9e\x03`\x0c\x9e\x99d\xb6~s\xc5\x06\x09\x80\x0d\ Z\xffv\xbf\xb7\xc5\xae\x7f\x80M9\x97\xe4\xcdI\x9e\ \xd7z\x90\xb1\x11\x00\x9b\xf5\xbc$\xafj=\x04\xc0\xc8\ <-\xc9[\xd7o\xb2\xd8\x10\xdf\xcc\x0d\x99-\x96\x17\ \xb3z\xf7\xef\xdaU\x80\xcd\x9b&y\xb5\x08\xd8\x1c\xdf\ \xc8\xcdyn\x92{\xe3{\x0a0\x84\x8bI^\x93\xc4\ \xbd\x016\xc4\xc6j\x03\xd6E\xfa\xc6\xb8\xe6\x1f`H\ /O\xf2\xa2\xd6C\x8c\x85\x00\xd8\x8cg\xc5e\x7f\x00\ C\xbb\x90\xe4\x8d\x0e\x03l\x86o\xe2\x09\xad\xefR\xf5\ \x86\xacvO\x010\xac\x17'ya\xeb!\xc6@\x00\ \x9c\xdc\xb3\xb3z\xf7\xef{\x090\xbc\x0bI~k}\ \xc7UN\xc0F\xeb\xe4~5\xab\x9b\xff\x000\xbc3\ I^\x9a\xd5\x89\xd7\x9c\x80\x008\xb97\xc5\xf7\x11\xe0\ 4\xdd\x9d\xe4\x17[\x0f\xb1\xedl\xb8N\xce\xb1\x7f\x80\ \xd3\xe7r\xc0\x13\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\ \x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\ \x00\x00@A;\xad\x07`\x10\x87I\xbe\x97\xe4\x87\xad\ \x07y\x9c\xce%9\xdbz\x88\xc7\xe9lV\xf3\xf6\xe4\ \xc6L-\x82~\x9b^;\xe0\x08\x010N\xd7\x93<\ \x90\xe4\xb3\xad\x07y\x9cv\xb2={\xa3v\xd2\xdfr\ s&\xed6\xc2\xad^\xbb3Y\xdd\x84\xab\xc5\xff\xf7\ \xd3\x93\xbc3\xc9]\x0d\xbe6lLo+26\xe3\ 0\xc9\xe5\xf9t\xb2l=\x08\x8c\xcdl\xb1|~\x92\ 7\xb7\x9e\x03Nj[\xdeu\x01\x00\x1b$\x00\x00\xa0\ \x01\x00\x00\x05\x09\x00\x00(H\x00\x00@A\x02\x00\ \x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\x00\x14$\ \x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\x00\x00@\ A\x02\x00\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\ \x00\x14$\x00\x00\xd8Fg[\x0f\xb0\xed\x04\x00\x00\xdb\ \xe8b\xeb\x01\xb6\x9d\x00\x00`\x1b\xd9~\x9d\x90o \ \x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\ \x00\x00@A\x02\x00\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\ \x82\x04\x00\x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\ \x00(H\x00\x00@A\x02\x00\x00\x0a\x12\x00\x00P\x90\ \x00\x00\x80\x82\x04\x00\x00\x14\xb4\xd3z\x00\xea\x99-\x96\ g\x93\xbc0\xc9]\xadg\xa1[\x0f'\xf9\xe6|:\ 9l=\x08\x8c\x95\x00\xa0\x85\x0bI\xde\x96\xe4e\xad\ \x07\xa1[\x1fI\xf2\xed$\xfb\xad\x07\x81\xb1\x12\x00\xb4\ p&\xc9\xf9$\x17[\x0fB\xb7\xce\xb5\x1e\x00\xc6\xce\ 9\x00\x00P\x90\x00\x00\x80\x82\x04\x00\x00\x14$\x00\x00\ \xa0 \x01\x00\x00\x05\x09\x00\x00(H\x00\x00@A\x02\ \x00\x80mt\xa9\xf5\x00\xdbN\x00\x00\xb0\x8d\xdc\xc8\xee\ \x84\x04\x00\x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\ \x00(H\x00\x00=\xb2n\x82\x81Y\xc8\x80\x1e\x1d\xb6\ \x1e\x00\xc6N\x00\x00@A\x02\x00\x00\x0a\x12\x00\x00P\ \x90\x00\x00\x80\x82\x04\x00\xd0#\xeb&\x18\x98\x85\x0c\xe8\ \x91\xab\x00``\x02\x00\xe8\x91u\x13\x0c\xccB\x06\xf4\ \xc8\x1e\x00\x18\x98\x00\x00\x80\x82\x04\x00\x00\x14$\x00\x80\ \x1eY7\xc1\xc0,d@\x8f\x9c\x03\x00\x03\x13\x00\xe3\ \xe5\xb5e\x9b\xf9\xf9\x85\x81Y\xc8\xc6\xcb;(\xb6\x99\ \x9f_\x18\x98\x00\x00zd\xdd\x04\x03\xb3\x90\x01=\xb2\ \x07\x00\x06&\x00\x80\x1eY7\xc1\xc0,d@\x8f\xec\ \x01\x80\x81\x09\x80\xf1\xf2\xda\xb2\xcd\xfc\xfc\xc2\xc0,d\ \xe3\xe5\x1d\x14\x00\xc7\x12\x00\x00P\x90\x00\x00zd\x0f\ \x16\xb7s\xae\xf5\x00\xdbN\x00\x00\xb0\x8d.\xb6\x1e`\ \xdb\x09\x00\x00(H\x00\x00=\xb2n\x82\x81Y\xc8\x80\ \x1e9\x07\x00\x06&\x00\x80\x1eY7\xc1\xc0,d@\ \x8f\xec\x01\x80\x81\x09\x00\x00(H\x00\x00@A\x02\x00\ \x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\x00\x14$\ \x00\x00\xa0 \x01\x00\x00\x05\x09\x00\xa0G\xd6M00\ \x0b\x19\xd0#w\x02\x84\x81\x09\x00\xa0G\xd6M00\ \x0b\x19\xd0#{\x00``;\xad\x07\xa04+y\x80\ F\x04\x00-\xec%\xf9d\x92\x7fi=\x08\xddz(\ \xc9A\xeb!`\xcc\x04\x00\xa7n>\x9d\xec%\xf9T\ \xeb9\x00*s\x0e\x00\x00\x14$\x00\x00\xa0 \x01\x00\ \x00\x05\x09\x00\x00(H\x00\x00@A\x02\x00\x00\x0a\x12\ \x00\x00P\x90\x00\x18/\xaf-\x00\xc7\xb2\x91\x18/\xb7\ \xd9\x05\xe0X\x02\x00\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\ \x82\x04\x00\x00\x14$\x00\xc6\xcbk\x0b\x8c\x99\xdff{\ B6\x12\xe3\xe5*\x00`\xcc\xeeh=\xc0\xb6\x13\x00\ \x00P\x90\x00\x00\x80\x82\x04\x00\x00\x14$\x00\x00\xa0 \ \x010^^[\x00\x8ee#1^\xae\x02\x00\xe0X\ \x02\x00\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\x00\ \x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\x00\ \x00@A\x02\x00\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\ \x04\x00\x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00\ (H\x00\x00@A;\xad\x07\xa0\x9e\xd9by!\xc9\ \x9b\x92<\xa7\xf5,t\xeb\xcbI>=\x9fN\x0eZ\ \x0f\x02c%\x00h\xe1\x5c\x92_Hro\xebA\xe8\ \xd6\x95$\x9fm=\x04\x8c\x99C\x00@\x8f\xac\x9b`\ `\x162\xa0G\x87\xad\x07\x80\xb1\x13\x00@\x8f\xac\x9b\ ``\x162\xa0G\xf6\x00\xc0\xc0\x04\x00\x00\x14$\x00\ \x00\xa0 \x01\x00\xf4\xc8\xba\x09\x06f!\x03z\xe4\x1c\ \x00\x18\x98\x00\x00\x80\x82\x04\x00\x00\x14$\x00\x00\xa0 \ \x01\x00\xf4\xc8\xba\x09\x06f!\x03z\xe4$@\x18\x98\ \x00\x00\x80\x82\x04\x00\x00\x14$\x00\x00\xd8F;\xad\x07\ \xd8v\x02\x00\x80mt\xa9\xf5\x00\xdbN\x00\x00\xb0\x8d\ l\xbfN\xc87\x10\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\ \x82\x04\x00\x00\x14$\x00\x80\x1eY7\xc1\xc0,d\x00\ P\x90\x00\x00z\xe4w\x01\xc0\xc0\x04\x00\x00\x14$\x00\ \x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\x00\x00@A\ \x02\x00\xe8\x91u\x13\x0c\xccB\x06\xf4\xc8e\x8000\ \x01\x00\x00\x05\x09\x00\x00(H\x00\x00@A\x02\x00\xe8\ \x91u\x13\x0c\xccB\x06\x00\x05\x09\x00\x00(H\x00\x00\ @A\x02\x00\xe8\x91\xfb\x00\xc0\xc0\x04\x00\x00\x14$\x00\ \x00\xa0 \x01\x00\xf4\xc8\xba\x09\x06f!\x03z\xe4\x1c\ \x00\x18\x98\x00\x00\x80\x82\x04\x00\x00\x14$\x00\x80\x1eY\ 7\xc1\xc0,d\x00P\x90\x00\x00z\xe4$@\x18\x98\ \x00\x00\x80\x82\x04\x00\xd0#\xeb&\x18\x98\x85\x0c\x00\x0a\ \x12\x00@\x8f\x9c\x03\x00\x03\x13\x00\x00P\x90\x00\x00z\ d\xdd\x04\x03\xb3\x90\x01=r\x08\x00\x06\xb6\xd3z\x00\ J:Lr-\xc9\xe5\xd6\x83\xd0\xad\xbd\xd6\x030\xa8\ \xc3$\xd7o\xf1\xdc~~<\xfen\xf5\xdc\xc1\xfa\xc1\ \x09\x09\x00Z\xd8M\xf2\xfe$\x9fh=\x08\xddz$\ V\xf2-\x1df\xb5\x9c^^\xffym\xfd\xe7~\x92\ +Y\xbd6Wo\xfao\x0e\x92\xfc\xcf1\x9f\xeb\xca\ -\x9e\xbb9\xf2\x0e\xf2\x93Q\xb0\x9f[\x07\xc0\xfe\xe3\ \xf9\x9f\xe0\xb1\x09\x00N\xdd|:\xd9O\xf2\xef\xad\xe7\ \x00\x92\xac6\xf2\xcb$\x0f'\xf9\x87\xf5\x9f\x8fd\xb5\ \xd1?\xcc\x8f6\xbeG\xff<\xfa\xfcQ\xb7{I\xbe\ \xd2z\x08\xfa&\x00\x00\xc6\xe7\x1bI\xdc\xec\x87\xc7$\ \x00\x00\xc6\xe7\xcb~\xb1\x0f\xb7#\x00\x00\xc6\xe7[\xad\ \x07\xa0\x7f\x02\x00`\x5c\xf6\x93\x5cm=\x04\xfd\x13\x00\ \x00\xe3r-\xab{\x00\xc0c\x12\x00\x00\xe3\xb2\x1b\x01\ \xc0\xe3 \x00\x00\xc6e/\xc9A\xeb!\xe8\x9f\x00\x00\ \x80\x82\x04\x00\xc0\xb8\x9cK\xb2\xd3z\x08\xfa'\x00\x00\ \xc6\xe5\x8e$\xe7[\x0fA\xff\x04\x00\xc0\xb8\x5cHr\ g\xeb!\xe8\x9f\x00\x00\x18\x97\x9d$?\xdfz\x08\xfa\ '\x00\x00\xc6\xe7%\xad\x07\xa0\x7f\x02\x00`|\x9e9\ [,\xefi=\x04}\x13\x00\x00\xe3s1\xc9[g\ \x8b\xa5\x93\x019\x96\x00\x00\x18\x9f3I^\x91\xe4\xb9\ \xad\x07\xa1_\x02\x00`\x9c\xeeNr\x9f\xbd\x00\x1cG\ \x00\x00\x8c\xd7\xbdI^?[,\xdd\x18\x88\x9f \x00\ \x00\xc6\xebL\x92\xf7$y\x93\x08\xe0f\x02\x00`\xdc\ \xeeHr_\x92\x97\xb5\x1e\x84\xbe\x08\x00\x80\xf1\xbb3\ \xc9\x9f\xce\x16\xcbW\xdb\x13\xc0\x0d\x02\x00\xa0\x86\xa7'\ \xf9`\x92\xe9l\xb1\xb4\xeeG\x00\x00\x142I\xf2\xa1\ $\xbf3[,\x9f\xdaz\x18\xda\x12\x00\x00\xb5<-\ \xc9\x07\x92|r\xb6X\xbej\xb6X\xde\xd1z \xda\ p,\x08\xa0\x9e\x9d\xac.\x11|A\x92\xef\xcd\x16\xcb\ \x07\x93\xfcc\x92o$\xd9Kr\x90\xe4\xf0\xe8c>\ \x9d\x1c\xb6\x19\x95\xa1\x08\x00N\xdd\xfa\xf8\xe3]\xf1;\ \xcb9\xde\xd5\xf9tr\xb9\xf5\x10\x05\x9d\x1c\xb4\x1e\x02\xc6\xcc\x0a\x98\ S7\x9fN\x0e\x93\xec\xb6\x9e\x03\xa02\xe7\x00\x00@\ A\x02\x00\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\ \x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\ \x00\x00@A\x02\x00\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\ \x82\x04\x00\x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\ \x00(H\x00\x00@A\x02\x00\x00\x0a\x12\x00\x00P\x90\ \x00\x00\x80\x82\x04\x00\x00\x14$\x00\x00\xd8F{\xad\x07\ \xd8v\x02\x00\x80m\xb4\xdbz\x80m'\x00\x00\xa0 \ \x01\x00\x00\x05\x09\x00\x00(H\x00\x00@A\x02\x00\x00\ \x0a\x12\x00\x00P\x90\x00\x18/\xaf-\x00\xc7\xb2\x91\x18\ \xaf\xc3\xd6\x03\x00\xd0/\x01\x00\x00\x05\x09\x00\x00(H\ \x00\x00@A\x02\x00\x00\x0a\x12\x00\x00P\xd0N\xeb\x01\ \xa8g\xb6X\xee$yf\x92;Z\xcfB\xb7\x1eM\ \xf2\xbd\xf9t\xe2j\x16\x18\x88\x00\xa0\x85KI\xeeO\ \xf2\xf2\xd6\x83\xd0\xad\x0f'yW\x92\xfd\xd6\x83\xc0X\ \x09\x00Z\xd9Ir\xb6\xf5\x10t\xcb\xe1I\x18\x98\x85\ \x0c\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\x00\x14\ $\x00\x00\xa0 \x01\x00\xf4\xc8\xba\x09\x06f!\x03z\ \xe4\x06@00\x01\x00\x00\x05\x09\x00\xa0G\xd6M0\ 0\x0b\x19\x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\ \x00(H\x00\x00=r\x19 \x0cL\x00\x00@A\x02\ \x00\xe8\x91u\x13\x0c\xccB\x06\x00\x05\x09\x00\xa0G\xce\ \x01\xe0v\xf6[\x0f\xb0\xed\x04\x00\xd0#\xeb&n\xe7\ j\xeb\x01\xb6\x9d\x85\x0c\xe8\x91=\x0000\x01\x00\xf4\ \xc8\xba\x09\x06f!\x03zd\x0f\x00\x0cL\x00\x00@\ A\x02\x00\xe8\x91u\x13\x0c\xccB\x06\xf4\xc8!\x00\x18\ \x98\x00\x00\x80\x82\x04\x00\xd0#\xeb&\x18\x98\x85\x0c\xe8\ \x91C\x0000\x01\x00\xf4\xc8\xba\x09\x06f!\x03z\ d\x0f\x00\x0cL\x00\x8c\x97\xd7\x96m\xe6\xe7\x17\x06f\ !\x1b/\xef\xa0\xd8f~~a`\x02\x00\x00\x0a\x12\ \x00@\x8f\xac\x9b``\x162\x00(H\x00\x00=r\ \x0e\x00\x0cL\x00\x00@A\x02\x00\x00\x0a\x12\x00\x00P\ \x90\x00\x00\x80\x82\x04\x00\x00\x14$\x00\x80\x1eY7\xc1\ \xc0,d@\x8f\x5c\x06\x08\x03\x13\x00\xe3\xe5\xb5e\x9b\ \xf9\xf9\x85\x81Y\xc8\xc6\xcb;(\x00\x8e%\x00\x80\x1e\ \x09X\x18\x98\x00\x00zd\xdd\xc4\xed\x88\xc4\x13\xb2\x90\ \x01\xb0\x8d\xae\xb5\x1e`\xdb\x09\x00\xa0G\xde\xddq;\ \x07\xad\x07\xd8v\x02\x00\xe8\x91u\x13\x0c\xccB\x06\x00\ \x05\x09\x00\xa0G\x0e\x01\xc0\xc0\x04\x00\xd0#\xeb&\x18\ \x98\x85\x0c\xe8\x91=\x0000\x01\x00\x00\x05\x09\x00\x00\ (h\xa7\xf5\x00\x94t=\xc9\xdf&Y\xb6\x1e\x84n\ \xfdk\x1c\x06\x80A\x09\x00N\xdd|:\xd9\x9d-\x96\ \x1f\x8d=P\x1c\xef`>\x9d\xb8\xd1\x0b\x0cH\x00\xd0\ \xc4|:\xd9o=\x03@e\xde\x81\x01@A\x02\x00\ \x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\x00\x14$\ \x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\x00\x00@\ A\x02\x00\x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\ \x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\ \x00\x00@A\x02\x00\x80m\xb4\xd7z\x80m'\x00\x00\ \xd8F\xbb\xad\x07\xd8v\x02\x00\x00\x0a\x12\x00\x00P\x90\ \x00\x00\x80\x82\x04\x00\x00\x14$\x00\x00\xa0 \x010^\ ^[\x00\x8ee#1^\x87\xad\x07\x00\xa0_\x02\x00\ \x00\x0a\x12\x00\x00P\x90\x00\x00\x80\x82\x04\x00\x00\x14$\ \x00\x00\xa0 \x01\x00\x00\x05\x09\x00\x00(H\x00\x00@\ A\x02\x00\x00\x0a\x12\x00\x00P\xd0N\xeb\x01`\xb6X\ \xeed{~\x16\xcf\xa4\xbfY[~\xffZ\x7f\xed\x16\ ob~&\xc9\xd9\x06_\x176\xaa\xb7\x15\x19\x9bq\ 6\xc9kf\x8b\xe5sZ\x0f\xf28\x9d\xcb\xf6\xacP\ \xcff5oO{\xcfv\x92\x9co\xf4\xb5[\xbdv\ g\xd6_\xbb\xc5:\xec\x5c\x92\xbb\x1a|]\xd8(\x01\ 0Ng\x93\xdc\xbb~\x00\xc0O\xe8\xe9]\x0c\x00p\ J\x04\x00\x00\x14$\x00\x00\xa0 \x01\x00\x00\x05\x09\x00\ \x00(H\x00\x00@A\x02\x00\x00\x0a\x12\x00'w\xd8\ z\x00\x80\x82\x0eZ\x0f\xb0\xed\x04\xc0\xc9}\xb1\xf5\x00\ \x00\xc5\x5cK\xf2O\xad\x87\xd8v\x02\xe0\xe4>\x9e\xe4\ r\xeb!\x00\x0a\xf9\xb7$_k=\xc4\xb6\x13\x00'\ \xf7\xb5$_m=\x04@\x11\xd7\x93|\x22\xdex\x9d\ \x98\x008\xa1\xf9tr%\xc9\xc7\xb2\xfa\xa1\x04`X\ \xdfI\xf2\x85\xf9t\xe2\xfc\xab\x13\x12\x00\x9b\xf1\x95$\ _o=\x04\xc0\xc8\x1d$y`>\x9d\xec\xb5\x1ed\ \x0c\x04\xc0\x06\xcc\xa7\x93\xfd$\x1fL\xb2\xdbz\x16\x80\ \x11{(\xc9\x97Z\x0f1\x16\x02`s\xbe\x96\xd5\x89\ )\x00l\xde\xf5$\x9fK\xf2h\xebA\xc6B\x00l\ \xc8|:y4\xc9\xfb\x93\x5ci=\x0b\xc0\x08=\x94\ \xe4\xcf\xe6\xd3\x89\xeb\xff7D\x00l\xd6\x83I\xfe\xae\ \xf5\x10\x00#\xb3\x97\xe4O\xe6\xd3\xc9\xb5\xd6\x83\x8c\x89\ \x00\xd8\xa0\xf5\xb9\x00\xefM\xf2H\xe3Q\x00\xc6\xe2 \ \xc9_'\xf9\xfb\xd6\x83\x8c\x8d\x00\xd8\xbc\xef&\x99'\ \xd9o=\x08\xc0\x08\xfc \xc9\xc7\xbd\xfb\xdf<\x01\xb0\ a\xeb\xbd\x00\x1f\xcb\xeax\x15\x00O\xde~\x92\x07b\ }:\x08\x010\x80\xf5\x09\x81\xef\x8e\xb3U\x01\x9e\xac\ \xc3\xac~\xd7\xcaG\xdd\xf4g\x18\x02`8_\xcb\xea\ |\x00W\x05\x00\x91\xe4\xc5\ \x8dG\x01\xe8\xc1n\x92\xfb\x93\xfc\xe1\xfa>*\x9c\x12\ {\x00N\xd9|:y$\xc9o&\xf9TV\xbb\xbc\ \x00\xaaZ&y{\x92?\xb2\xf1?}\xf6\x0042\ [,\xefL\xf2\x8e$\xbf\x9d\xe4B\xe3q\x00N\xdb\ 7\x93\xdc\x97\xe4\x8bn\xf4\xd3\x86\x00hh\xb6X\x9e\ O\xf2\x8a$\xefJ\xf2\xec$;m'\x02\x18\xdc\xb5\ $\x8b\xac\xce\xf6\xff\xae\x8d\x7f;\x02\xa0\x03\xb3\xc5\xf2\ \x19Y\xed\x06\xfb\xf5$w4\x1e\x07`(_O\xf2\ \xa1$\x9f\x9eO'{\xad\x87\xa9N\x00tb\xb6X\ ^H\xf2\x82\xac\xaa\xf8yqX\x00\x18\x8fG\x93|\ >\xc9\x07\x92|\xdf5\xfe}\x10\x00\x9d\x99-\x96\x97\ \x92L\x93\xbc%\xc9s\x93\x9ck;\x11\xc0\x93\xf6\xc3\ \xacn\x82\xf6\x81$\xdf\xb0\xe1\xef\x8b\x00\xe8\xd4\xfar\ \xc1\x17%ymV{\x06.du\x8e\x80\xf3\x04\x80\ \x1e\x1d&9\xc8\xean~\x8ffu\x0b\xf4O&\xf9\ \xce|:\xb9\xdar0nM\x00l\x81\xf5\x15\x03/\ \xc8\xea.\x82?\x9b\xe4\xce$\x97\x8e<.&9\x1f\ q\x00\x0c\xefzV\xd7\xee_]\xffye\xfd\xf12\ \xc9\x7f$\xf9V\x92o\xba\xa1O\xff\x04\xc0\x96\x99-\ \x96;Y\xed\x0d\xb8\xb8~\x5cX?\xce\x1d\xf9\xe7K\ I~z\xfd\xcf\x97\x92\x9c=\xf2w\xce\xae\x9f\xdf9\ \xf2\xdc\x0d\x17\xb2\x0a\x09`|\x0e\xb3\xdaP\x1f\x1c\xf9\ \xe7\xdd\xac6\xe8\xfbY\x9d\x9d\x7fp\xd3\x9f\xbbI\xfe\ \xfb\xc8\xc7\xd7\x92\xec\xad?\xde]\x7f|5\xc95'\ \xf5\x01\x00l\x81\xff\x07\x04h\x08\xa4^\xb9\x0c\x83\x00\ \x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x04;\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x03\xedIDATx\x9c\xed\ \x9a\xcf\x8b\x14G\x14\xc7?6\xc3 \xcb\x22\x22!\x98\ \x10\x1b\x11\x91\xb0l\x82,A\xc2\x12\x88\x88\xa8\xc8Z\ \x1a\xd7\x5c\x0dE\x021\xa7\xb0\x87\xfc\x0d\xc1\x83'\x05\ a/}\xceA\x0f%\xf8c\xd5E\xf6\xe0!\x84e\ \x15O\x82\x1e\x0a\x11\xe3A\x82\x88\xc8\xb2,9t\x8f\ \xce\xf6NO\xbd\xae\xfe\x91\x81\xd4\x07\x86iz^\xd5\ \xab\xfe\xf6\xab_\xaf\x06\x02\x81@ \x10\x08\x04\x02\xff\ O\xb6\xf8\x14\xd2\xc6\x9e\x05\xce\x03\x1f\x01\x9d\xec\xf6Z\ \xf6\xbd\xde\xf7Y\x05\x9e\x03s\x89\x8a\x17\xaa5\xb5\x19\ :n\x93\x8dhc\xc7\x81\x8b\xc06A]c\xc0v\ \xe0\x02\xf0E\xe9\xd6\xb5@\xe4Q\xe68\x9b\x1f\xde\xc5\ \xa46\xf6K\x0f_\x8d\xe3#\xc0\xf7\x9e\xbe|\xcb5\ J)\x01\xb4\xb1c\xc01O_\xa7=\xcb5J\xd9\ \x088\x02\x8c{\xfa\x9a\xd0\xc6Nz\x96m\x8c\xb2\x02\ \xccV\xf47r\xdd@,\x806\xb6K:\x00V\xe1\ L\xc5\xf2\xb5S&\x02\x0e\x02;*\xfa\x9b\xd0\xc6N\ T\xac\xa3V\xca\x08\xf0]M>G*\x0aD\x02h\ c#`F`\xfa\x5c`Su\x1c\xa9\x15i\x04|\ \x05|\xe6\xb0Y\x03~\x11\xd45\xa9\x8d\xdd'\xf4\xdb\ 8R\x01$\xe1\xbf\x0c\x5c\x07^\x0a|\x8e\xcc\x9a@\ *\xc0)\x81\xcdB\xa2\xe25\xe0\x8e\xc0vd\xba\x81\ S\x80,\x5c?\x17\xd4u+\xf7=\x8c)m\xec\x1e\ \x81]\xe3H\x22@\xf2\xf6\xff\x01\xfe\xcc\xae\x17H\xb7\ \xc2.\xbf\x92z\x1bG\x22\x80\xa4\xff/%*^\x05\ HT\xfc\x02x((3\x12\xdd`\xa8\x00\xda\xd8O\ \x81\x03\x82z\xf2a/\x19\x07\x0ehc]3K\xe3\ \xb8\x22`F`\x03\x9b\x1fX2\x0et\x18\x81n\xe0\ \xca\x08\x9d\x14\xd4\xf14Q\xf1\xe3\xdc\xbd\xfb\xc0[\xd2\ \x8c\xd00f\x81K\x02\x1f\xbd\xc5\xd8!\xd2\x01\xb9\x9b\ \xdd\xeeo\x7f\xff\xf5\x1a\x83\xe9\xbf\xbf\x92\xa8x\xb10\ '\xa8\x8d\xdd\x06\xfc\x0dlu\xb4m>Q\xf1\xcf\x03\ \xca\xdf\x06\x0e;\xca\xae\x02\xbb\x12\x15\xbb\xd6\x0ehc\ /\x03\xe7\x5cv%X\x07\xe6\x86\x85\xf7\x11\xdc\x0f\x0f\ \xc5\xe1~[P\xb6\x0b(\x97Q\xf62~\x12\xd4W\ \x86\x08\xf8u\x98\x00\x92\xf0_\x05\xee\x15\xfc&\x19\x08\ A6\x1bt\xf1H\xe0\x0a\x88\x06\x0a\xa0\x8d\xed \xdb\ \xfb\xff\x95\xa8\xf8U\xc1o\x0fq/\x8b\x01\x0ejc\ \xabn\xb3\xbd)\x8a\x80o\x90\xed\xfd\x0b\xdfr\xb6,\ \xbe'\xa8c+n\xb1{\xe7\x0c\xb5S$\x80t\xef\ \xef\x9a\xee\xee\x0a\xebq\xf9{\x0dXa]ex4\ p\x16\xd0\xc6>\x01\x5ck\xf5\xb7\xc0\xb7\xa4\xe3\xc0:\ \xe9\x14\x93\x7fK\xfb\x80k\x82\x86\xbc\x01>IT\xfc\ \xa6\xc8 K\xa8^\xc4?)\x9b\xe7\x05\xf0\xe3&\x01\ \xb2\x03\x8c\x0759)\xc3l\xa2\xe2\xabm;\x1d\xd4\ \x05\x9c\xd3RC\xfc'{\x83A\x02H\xa6\xbf&8\ \xae\x8d\x95\xac;je\x83\x00\xd9\xe6d\xaa\xedFd\ l']\xea\xb6J>\x02\xa4\x9b\x9f\xa6\xa8+\xf3,\ &\xff\xb0'\xdan@\x8e\x99l\x11\xd6\x1a\xef\x05\xc8\ \xce\xfd[\x0f\xc1\x1c;\x81\xe96\x1d\xf6\xab-\xdd\xfc\ ,\x03\xbf\x0d\xa9'\xe2\x83\xb0\x9d\xbe{\x09i?w\ 1\x0b,\x09\xecj\xa1\xbf\xe1\xd2\xf0\xbf\x92\xa8x\xb1\ \xac#m\xec\x0f\xc8\x12 J\x1b;\x97\xa8\xb8\x91\xa5\ o\x9e\x08\xde'\x1b\xa4\x07\x9f\xbe\xff\xf5\x91l\x8f\x01\ v\x03\xfb=}\x94\xa6\x17\xaa_\x03\x1f\x0b\xec_\x92\ v\x01\x1f\xca\x08\xd7\xdal\xd0\x13@\x1a\xfe\x8b\x15B\ \xf3i\xf6\x91\xd0Z\xae\xb0'\x80\xe4\xe0\x13d\xc9\xce\ \x81d\xc2I\x93$\x13\xda\xd8\xbd\xbe\xbe\xca\x10ic\ w\x03\x92\xbf\xae\x94y\x80\x22n\x08\xed\x22Z\xda\x93\ \x94\x19\xfcV\x12\x15?\xab\xe8o\x11x'\xb4me\ Q\x16\x01G\x85\xb6\x7fTu\x96\xa8\xf85pSh\ >\xad\x8d\x95\xac\x1b*\x11\xe1>\xf7\x07X\x01\xe6k\ \xf2\xf9;i\x02\xc4E\x17wR&\x10\x08\x04\x02\x81\ @ \x10\xf0\xe4_\xc1X\xd0\x85cFO\xa7\x00\x00\ \x00\x00IEND\xaeB`\x82\ \x00\x00\x05Y\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x05 IDATx\x9c\xed\x9bM\x88\x1cE\ \x18\x86\x9f\x1d\x96%\x84%\x84 a\x0f\xa1\x089,\ 9\x04\x09\x1eD$\x04\x94\xa09h\xe1O<\x88X\ \xa2DEC\xd0\xa8a]%J~V\xa3k \xc4\ \xb0F\x11\x0f\x85\xd1H\x8c\xc6\xf2w\xe3!!gE\ \xe3\xd1\x83H\x9dD\xc4\xc3\x12D\xc22x\xa8jw\ 2\xdb?\xd5\xd3_&\x97~`\x0e;S\xfdv}\ ow\xf5V\xd5\xf7\xf5\x88q~\x028\x08L\x00c\ @\xa7\xe7\x03\xd0\x8d\x9f~\x8a\xbe\xff\x13x\xdej\xf5\ W\xceo\x03c\x9c_\x0d\xec\x076\xd4\xec'\xc0b\ _\x9b+\xc0\xdf\xc0\xc1Q\xe0]@Kv6v\xea\ aa\xcd\x19\xe0ia\xcd\xf5\x1d`RX\x14\xc2U\ \x92F]\x03\xcdu\x1d`TXt\x11\x98\x15\xd6\x04\ x\x9bp\xebJ2\xda\xa9nS\x8b.\xb0\xcbju\ VX\x17\xab\xd59\xe0Q\x96\xc6\xb3\x04\xa3\xbd\x0f\x91\ \xa6t\x09\x0f\xbf\xf7\x84\xf4\x96a\xb5\xfa\x08x\x92\xe2\ \x87]m$\x0d\x98\xb6Z\x1d\x15\xd2*\xc4j\xf5\x01\ \xf0\x14B&H\x05?e\xb5zSH\xab\x92x\x97\ \x89\x98\xd0\xd4\x80.C\x0e>C\xca\x84NC\x81S\ \xd7#\xf8\x8ch\xc2\x89&\x1aM\x0d\xd8a\x9c\xdf\xd1\ \xa4\x03M0\xceo\x07\x1ek\xa2\xd1t\x08\x8c\x01'\ \xaf\x87\x091\xf8\xcf\x81\x15Mt$\x1e\x82C7A\ *xh>\x042\x86f\x82d\xf0 g\x00\x0c\xc1\ \x04\xe9\xe0!}\x08\x5cLl\x97\x99p\xdf\x80\xfd)\ \xc48\x7f\x07p\x86\xf4\xe0/\x92pqS\x0c\x98\x06\ n\x03\x0e'\x9ex\x0c\xf8\xd88/\xb6\xc46\xce\xdf\ N\xb8\xf2+\x13\x0f\x99#\xf4y7\x15&t(_\ \x5cLY\xad\x0e[\xad\xbaV\xabi\xea\x99\xf0I\xbc\ j\x8d0\xce\xdf\x0a|A\xbd\xe0w\xc7>\xcfQa\ B\xd1\x1d\xd0\x05\xf6\xf6Orj\x9a\xb0\x028c\x9c\ \xbf1\xb1\xfd2\x8c\xf3\x1b\x80/\x81\xf1\xc4C\xfe\x0f\ >\xfb\x22\x9a\xb0\x8b\x02\x13\xf2\x0c\xc8Vuo\xe5\x1d\ P\xd3\x84q``\x03\x80M\xc0\x9a\xc4\xb6\xcb\x82\xcf\ \xb0Z\x9d \xac\x22\x97\xdd\xed\x1d`\xa1\xe7\xefl=\ _\xba\xaa\xaba\xc27\xc0\xa9\x84vE|\x95x|\ a\xf0\x19V\xab\xf7\x09\xfb\x09\xbd\x9b*\x97;\x84\x05\ \xc5\x0f\xc0\xef\xc0C\xd1\xadJ\xa2\x09\x87J\x9a\x5c\x04\ \x1e\xb0Z\x0d\xbc\x81\x11\x03z\x04p%\xcd\x8eS\x11\ |\x8f\xde\x87\xc0\xbd\xc0\xaf\xc0\xcf\xc0\xe3#\x83v.\ \xc38\xff\x0aa\xb7\xb6\x97\x0b\xc0\xddV\xab\xcbM\xf5\ \xe39V\x00\xa7\x81\xbb\xfa~:J\x18\xae\x03\xcfe\ \x1a\x1b\x00`\x9c\x7f\x01x\x830\xa4\xbe\x03\xee\xb7Z\ \xfd#\xa1\xdds\x8e1\xe0$\x90M\xb4\x0eY\xad\xf6\ 5\xd5\x151\x00\xc08\x7f\x0f\xb0\x1e\x98\xb3ZIo\ ^f\xe7\xe8\x00O\x00\x0bq{\xac\xa5\xa5\xa5\xa5\xa5\ \xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xe5zb\x9c_g\x9c\xdf\ 4\x84\xf3l4\xce\x8b\x15L\x89\x14H\x18\xe7o\x06\ ~\x04~\x8a\x9b#\xd7\x04\xe3\xfcN\xe0\x12p)\xe6\ \x0a\x1a\xd3\xd8\x00\xe3\xfcV\xe0{`-\xa1\xe2l\xd6\ 8\xdf\xbfE\xd6\x18\xe3\xfcs\x84\x9a\xc61`5\xf0\ \xb5q\xbe\x7f\x8b\xac6#\xc6\xf9U\xc0^\xc2\xf6\xf3\ \x11\xab\xd5o5:\xb5\x8d\x90\xb1\xc9\xdb\xb7?`\xb5\ z\xb5i\x07\xe3y\x9e\x05\x8e\xb0\xfc\x82]\x01\x1e\xb4\ Z}VCk\x1d!\xdb\xb5\x00\xcc\x8e\x18\xe7O\xb3\ \xb4\xcf\xf6\x07p\xa7\xd5\xea\x97\x04\xa1\xed\x84\x5c]Y\ \xc6f\xdaj\x95\x9aC(:\xcfN\xc2\x95/\xba[\ \xaf\x10v\xb3?M\xd0\xda\x08\xcc\xb3Tty\xae\x03\ l\xeci3\x01\x9c\x8fc\xbaL(\xcb\xd2V\xa5\xab\ f\x9a\x8c\xd5\xd8\x8fw(\x1f\xaaIY\xe9\x98\xa1:\ \xcf\xd5\x15\xa7\x93y\xc2k\x80\xf9\x98\x93\xcb\x13\xaa\x9b\ \xa2NMk\xe5\xb1\x92\xb4\xe7T\xa9\x09\xc6\xf9\xcd\x84\ \xe7\xd4D\xffoE\xe2\xab\x81o\x8d\xf3[\xfa\x84\xea\ \x06\xbf\xcfjU\x96\xd4(\xc5ju\x01\xd8\x93\xd8<\ \xd7\x84\x9e\xe0\xd7\xe6\x1dT\xe6\xee*\xc2\x93vk\x14\ \xaa\x1b\xfca\xab\xd5k\x89m\x0b\xb1Z\x1d\x03^N\ l~\x95\x09=\xc1\xdfPt@\xd5\xed\x95\x99\xf0\x22\ \xf5\x82?Jz\xa7+\x89F\x1eHl\x9e\x99\xf0\x12\ \x15\xc1C\xda\xf8\x1a\x07^'=\xf8c4LW\xe5\ \x11\xff\xa5\xd6\xa9O\x98\xa1\x22x\x90+\x95\xcd8\x0e\ \xec\x91\x0e>\xa3fj>\x09I\x03\xe6\x80g\xaeU\ \xf0\x19\xd2&H\x19P\x99\x9f\x97$\x9a R\xa2+\ a\xc0\x09\x86\x18|\x0f\xd3@n\x15K\x1d\x9a\x1ap\ \x96PQ2\xec\xe0\xb3\xe2\x89)\xc06\xd1ij\xc0\ 6 w\xc68$6\xb3\xbch\xa2\x16M\x0d\x18'\ \xcc\x13\xb6T\xb6\x14&Nr\xe6I/\xa2\xcaE\xa2\ T6\x9b,\x0d\xedNH\x99\xe1\xa5\x22U+\x9c\x99\ p\x8b\x80V)q\xdbm\x1e\x81\xe0Av\x1e\x90-\ \xa0n\x12\xd4\xbc\x0a\xe3\xfc$%\x0b\x9bA\x90\xac\x16\ \x87%\x13\xc4\xdfF\x8d;9\xb9K\xda\x06t\xabj\ \x85\x07a-\xe1-Oif\x91\x7f}v\xb1\xbfR\ T\x0a\xe95\x06\xc8\xbf\xe2\x0b\xb00JX5)\xc2\ \x0aJ\x82\x7f\x11\x5c\x0a\xf7\xb0\x9f\xf0\xa2\xf7*!\xbd\ E`\xff\x7f\xe48\xc0\x0dU\xc1\xe8\x8f\x00\x00\x00\x00\ IEND\xaeB`\x82\ \x00\x00R\x7f\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x02\x00\x00\x00\x02\x00\x08\x06\x00\x00\x00\xf4x\xd4\xfa\ \x00\x00 \x00IDATx\x9c\xec\xdd\x7f\x90^W\ }\xe7\xf9\xb7U=\xbd\xda\x1eUO\xafJ\xa3U4\ \xca\x8dV\x11B(\x8a\x22\x84P\x14\xc5q<\x8e\xc7\ \xa38\xe4bl0`\xc35`\x881\xe0\x10\x06(\ \xc7\xe5a]^\x17\xa1<\x14x\x1dc\x0c1\xb6\xc3\ \xc5\x18c\x8c\xe3\xdc0\x1e\xc7q\x1c\xc7\x11\xc6\x08!\ \x14E\xa5\xd2\x08Ein4Z\xa5\xa7K\xd5\xd5\xd5\ \xdb\xab\xea\xea\xea\xda?\xbe\xe7\xaa\x1f\xb5\xfa\xe7\xf3\xeb\ \x9c{\xef\xe7U\xf5T\xdbB\x96\x0e\xdd\xcfs\xcf\xf7\ |\xcf\xf7|\x0f\x88\x88\x88\x88\x88\x88\x88H\xf5]\xe2\ {\x00\x22\x22u\x93d\xf9\x16\xe0j\xe0\xb7\x81\xbf\x04\ \xd24\x8e\xce\xf8\x1dU8\x92,\xdf\x00\xf4\x02\x83i\ \x1c\x9d\xf3=\x9e\xaaR\x00 \x22\xd2\x05I\x96\xaf\xc2\ &\xfd\x9b\x80]\xc0\x0a\xf7?\x9d\x03>\x09<\x9e\xc6\ \xd1\xa8\xa7\xe1\x05#\xc9\xf2\xab\x80\xaf\x02\xeb\x81\x1cx\ \x1ax\x0c8\x9e\xc6\xd1\x84\xc7\xa1U\x8e\x02\x00\x11\x91\ \x0eI\xb2\xbc\x07\xd8\x01\xbc\x17\xb8\x16X\x03,\x9b\xe5\ \xb7\xe6\xc0\x87\x80\x17\xd38\x9a\xea\xde\x08\xc3\x92d\xf9\ f\xe0\xdb\xc0V.\xfe>\xed\x03\xbe\x09<\x03\x0c\xd7\ \xf9\xfb\xd4.\x0a\x00DD\xda(\xc9\xf2e\xc0J\xe0\ -\xc0\xcdX\x00\xd0\xb7\x88\xff\xf49\xe0\xf64\x8e\x8e\ tpx\xc1J\xb2\xbc\x1f\xf8.p\x19\x96\xfe\x9f\xcb\ 0\xf0$\xf00pLY\x81\xe6)\x00\x10\x11i\x03\ 7\xf1o\x07\xde\x0d\x5c\x0f\xacc\xf6\xd5\xfe|\xfe\x08\ x\xa0\x8e\xf5\x00I\x96\xdf\x0f\xbc\x0f\xe8_\xe4\x7f2\ \x09\xbc\x04<\xe8\xbe\x8e++\xb04\x0a\x00DD\x9a\ \xe4&\xfd>`/\xb6\xda\xdf\xc3\xe2'\xb0\xd9\x0cc\ [\x01\xcf\xd5ie\x9bd\xf9\xf5\xc0}\xc0\xda&\xff\ \x88#\xc0CXf`D\x81\xc0\xe2(\x00\x10\x11Y\ \x227\xf1o\x00\xde\x85\xed\xefod\xe9\xab\xfd\xb9\xbc\ \x04|2\x8d\xa3Cm\xfa\xf3\x82\xe6\xf6\xfd\xbf\x03l\ \xa1\xf5\xef\xe1\x19\xe0k\xc0#\xc0\xa94\x8e&[\xfc\ \xf3*M\x01\x80\x88\xc8\x22\xb8I\xbf\x17\xdb\xa3\xbe\x19\ \xb8\x12\xdb\xeb\xef\x84;\x81?I\xe3h\xb8C\x7f~\ \x10\x5c\x91\xe4\xb7\xb0z\x89\xe5m\xfc\xa3G\xb1b\xc1\ \xfb\x81\xa3u\xca\xa6,\x85\x02\x00\x11\x91y\xb8\x89\x7f\ \x1d\xd3E}[\x99\xbfH\xad\x1d\x86\xdc\xdf\xf5|\x95\ W\xb1I\x96\x7f\x04\xb8\x0bX\xdd\xa1\xbfb\x12+\xae\ \xbc\x1fx\x0d8\xa7\xed\x81i\x0a\x00DDfp\x93\ ~\xe3\x11\xbekh~\x7f\xbaY\x19pgUO\x05\ $Y\xbe\x09\xf83,\xf5\xdf\x0d/\x02\xf7\x02\xaf\xa2\ @\x00P\x00 \x22r\x9e\x9b\xf8\x97c\xe9\xfd\x8fb\ E}+\xe6\xfd\x8f:g\x0a\xb8\x1dx4\x8d\xa3\xb3\ \x9e\xc6\xd0\x11I\x96\xf7b\xfb\xf4\xd7\xb2\xb8#\x92\xed\ \xa4@\xc0iW\xd1\x8a\x88H\x15\x5c\x03\xfc5V\x94\ v\x15\xfe&\x7f\xb0\xe7\xf3\xad\xc0v\x17\x98T\xc9\xbb\ \x80+\xe8\xfe\xe4\x0f\x16\xdc\xfd\x15\xf0\xe7\xc0eI\x96\ \xfb\x18C\x10\xaa\xf6\xa6\x12\x11i\xc5\x9b\x80\xcdt~\ \x8f\x7f\xb16`[\x10\x1b|\x0f\xa4]\x92,_\x07\ |\x1c\xeb\x8a\xe8S\x11\x08<\x9cd\xf9\xc6\x0a\x06Y\ \x0b\xaa\xdd\xffa\x11\x91y\xfc\x0bVA\x1e\x92w\x01\ \x97Va\xa5\xea&\xd9;i\xef\xb1\xc9V\xf4\x007\ `\xed\x87;U\x88\x18\xac\x10~\x00\x22\x22\xa1\xc8\x81\ \x11\xdf\x83\x98a9V\x8f\xb0\xd5\xf7@\xda`\xaf{\ \xb5\xd2,\xa9\x13\xceb'\x06jE\x01\x80\x88\xc8\xb4\ \x1c\x9b\x0cB\xb3\x13\xb8.\xc9\xf2n\x9fDh\x9b$\ \xcb\x07\x80OcG*Cs\x14\x05\x00\x22\x22\xb5v\ \x9a\xf0\xb6\x00\x0a\x1f\x00v\xb8\xe69\xa5\xe2R\xff\x1f\ \xc3\xb2\x18!\x8e\xff\x1f\x80\xda5\x0bR\x00 \x22\xe2\ \xb8Kx\x86\x08s5\xb8\x0a\xbb'`\x93\xef\x814\ a;V\xcc\xb8\xca\xf7@\xe6p\x18\x05\x00\x22\x22\xb5\ w\x9a\xf0\xea\x00\x0ao\x01\xaet\xe9\xf4Rpg\xfe\ \xef\x04\x22\xdfc\x99\xc3ijzo\x80\x02\x00\x11\x91\ \x0b\xfd\x14\xbb\x95/D\xcbp\x05\x81e8\xb6\xe6\xc6\ \x98\x00\xbbio\xaf\xffv:H\x0dW\xff\xa0\x00@\ Dd\xa6S\x84\x9b\x01\x00\xdb\x02\xb8\x91pW\xd4\x8d\ \xd6a\xcd\x8c|\x9f\xf9\x9fO-\xd3\xff\xa0\x00@D\ d\xa6A\xc2<\x09\xd0(\x01v%Y\x1e\xea\xaa\xba\ \xb8\xe9\xefv\xc29\xf3?\x97Z\x16\x00B\xd8?\x14\ \x11\x11\x1fNa[\x00!\xf7\x88\xef\xc3V\xd6\x9b}\ \x0fd\x1e{\x81\xab\x09\xef\xcc\x7f\xa3)\xe0\x10\x0a\x00\ DD\xc4\x15\x83\x85\xd8\x10h\xa6\xcb\x81\xbdI\x96\xaf\ \xf4=\x90\x99\xdc\x98>A\x98g\xfe\x1b\x1d\x05F\xea\ z!\x90\x02\x00\x11\x91\x8b\x85\x5c\x08\xd8\xe8\xa3Xo\ \x80`\x9e\xe5n,\x1f\x01\xb6\x11\xe6\x99\xffF\xb5-\ \x00\x04\x05\x00\x22\x22\xb3\x19$\xfc:\x00\xb0\x15\xf6M\ \x84uY\xd0v\xacH1\xd43\xff\x8d~\x0c\x9c\xf3\ =\x08_\x14\x00\x88\x88\x5cl\x90rd\x00\x00\xae'\ \x90\xcb\x82\x5cQ\xe2\x1d\xc0z\xcfCY\xac\xda\xee\xff\ \x83\x02\x00\x11\x91\x8b\xa4q\x94\x03g(\xc7\xe4\xd0K\ \x00\xbd\x01\xdc\xdf\xfd\x1e`\x0f\xe1\x9e\xf9o4\x0c\x9c\ \xacc\x03\xa0\x82\x02\x00\x11\x91\xd9\xfd#\xe5\xd8\x06\x00\ \xbb,\xe8m\xf8\xbd\xd26\x22\xfc3\xff\x8d\x0eP\x8e\ \x00\xafc\x14\x00\x88\x88\xcc\xee$\xe5\x09\x00\x00>\x08\ \xect\xadw\xbb\xca\x9d\xf9\xff4\xe1\x9f\xf9ot\x88\ \x1a\xef\xffC\xf8\x15\x9a\x22\x22\xbe\x9c\xc0.\x06\xda\xe2\ { \x8b\xb4\x0a\xb8\x198\x99d\xf9\xf1&\xff\x8cf\ '\xef\xbd\xee\x15\xf2\x99\xff\x99~B\xcd3\x00\x0a\x00\ DDfW\xb6\x0c\x00@\x0c\x1c\x07~\xc0\xd2o4\ \x5c\x81M\xe0\xcd\xcc\x0b7S\x8e\xd6\xc4\x85\x09j\xdc\ \x02\xb8p\x89\xef\x01\x88\x88\x84*\xc9\xf2\xfb\xb0\xd4\xfa\ \x0a\xdfc\x91\xb6:\x0c\xfcv\x1aG\xa7}\x0f\xc4\xa7\ \xb2\xec\xd5\x88\x88\xf8\xf0O\x94/\x0b \x0b\xdbO\xcd\ \xf7\xffA\x01\x80\x88\xc8|N\xa0\x00\xa0\x8a~\x82\x02\ \x00\x05\x00\x22\x22\xf3\x18\xa4<\x0d\x81dq\xa6\xd0\x11\ @@\x01\x80\x88\xc8|N\x12\xfe\xcd\x80\xb249p\ \xba\xce\x0d\x80\x0a\x0a\x00DD\xe6\x90\xc6\xd19,\x08\ \x18\xf5=\x16i\x9b\xda\x9f\xff/(\x00\x10\x11\x99\xdf\ \xcfP\x1d@\x95\xfc\x08\xa5\xff\x01\x05\x00\x22\x22\x0b\x19\ D\x01@\x95\x1cD\x19\x00@\x01\x80\x88\xc8BN\xa0\ B\xc0\xaa\x18\x05\x8e\xa6q\xa4\x0c\x00\x0a\x00DD\x16\ \x92\xa3B\xc0\xaa8\x80V\xff\xe7)\x00\x10\x11\x99\x87\ \xab\x16\x1f\x04F<\x0fEZw\x08\xed\xff\x9f\xa7\x00\ @Dda\xff\x8c\x02\x80*\xf8\x11\xca\x00\x9c\xa7\x00\ @Dda\x83\xa8\x10\xb0\xect\x01\xd0\x0c\x0a\x00D\ D\x16v\x1a\xf5\x02(\xbbc\xc0H\x1aG\xaa\xe5p\ \x14\x00\x88\x88,l\x10e\x00\xca\xee5\x94\xfe\xbf\x80\ \x02\x00\x11\x91\x85\x9d\xc32\x00J\x1f\x97\xd7\xdf\xa3\x00\ \xe0\x02\x0a\x00DD\xe6\x91d\xf92`7\xb0\x19\xe8\ \xf5<\x1ci\x9e\xf6\xffgP\x00 \x222\xbf\xf5\xc0\ m\xc0\x0e\xcf\xe3\x90\xd6l\x01V\xf8\x1eDH\x14\x00\ \x88\x88\xcc!\xc9\xf2U\xc0\xa7\x81\xab\x81\xe5\x9e\x87#\ \xad\xb9\x0fx{\x92\xe5\x03\xbe\x07\x12\x0a\x05\x00\x22\x22\ \xb3H\xb2\xbc\x1f\xf8\x04p-Z9VA\x1fp?\ \x0a\x02\xceS\x00 \x222\x83\x9b\xfc?\x06\xbc\x0fX\ \xedw4\xd2F\x0a\x02\x1a(\x00\x10\x11i\x90dy\ \x1f\xf0a\xe0V`\xad\xe7\xe1H\xfb)\x08p\x14\x00\ \x88\x888n\xf2O\x80\x0f\x01\xeb<\x0fG:GA\ \x00p\x89\xef\x01\x88\x88\x84\xa0a\xf2\xff$\xb0\xd1\xf3\ p\xa4;\xc6\x81\x8f\x03O\xa7qT\xbb\xbb\x1e\x94\x01\ \x10\x91\xdaK\xb2|9p\x03V\xf4\xa7\xc9\xbf>j\ \x9d\x09P\x00 \x22\xb5\xe6&\xff\x18;\xeb\xbf\xc9\xf3\ p\xa4\xfbj\x1b\x04h\x0b@Dj\xaba\xf2\xbf\x13\ \xd8\xe6y8\xe2W\xed\xb6\x03\x14\x00\x88H-i\xf2\ \x97Y\xd4*\x08P\x00 \x22-s\x05t\xfd@\x0f\ 0\x89\xf5\x5c/\xbeN\x84v\x05\xab&\x7f\x99G\xa9\ \x82\x80$\xcb{\xb1\xcf\xdd\xb24\x8e\xc6\x96\xf2\xdf*\ \x00\x10\x91\x96\xb8\xcbr\xae\x05\xee\xc0\x8e\xce\xe5\xd8\xf5\ \xb9\xc7\x81\x7fp_\x87p\xc1\x00v#\x9b\xb7\xa0\xc0\ =0c\xe03h\xf2\x97\xd9\x05\x19\x04\xb8\xf7n/\ \xd6\x96\xba\x07\x0b\xba7`\xb5+\xcb\x81/\xa5q4\ \xbe\xd8?O\x01\x80\x88\xb4\xc4\xf5\xcb\xbf\x07\xf8 \xf6\ P\x9ai\x12\x0b\x00\x8e\x02G\xb0kY\x0f\x03g\xb8\ 0 \xe8\xf8Mm\xee\x01z\x99\x1b\xef\xeeN\xff}\ Rj^\x83\x00\xf7^-&\xfa\xe5X;\xeaM\xc0\ v\xe0\x97\xb1\xcb\x8d6s\xe1g\xee\x1d\xc03\x8b\x0d\ \xae\x15\x00\x88H\xd3\x1aV\xffK]MO`Y\x82\ \x83\xc0O\xdc\xd7A`\x94\x0ee\x09\x1a&\xff\xbb\xb1\ \xc9_\xa7\xa0d!]\x09\x02\xdc\xe7\xa8\x98\xf0\x8b\xaf\ [\x80\x9d\xc0\x1b\xb0\xcf\xd6&\x16\xbe\x8ez?\xf0\xef\ \x17\x9b\x05P\x00 \x22Ms=\xf3\xef\x01>\xc2\xec\ \xab\xff\xa5\x18\xc6\xb2\x04\x87\x80\x1fa\xd9\x82!,\x18\ (\x02\x82\xc9&\xc7\xa9\xc9_\x9a\xd5\xf6 \xc0M\xf8\ \xcb\x1b^\x03\xd8\xca\xfe\xcd\xd8d\xbf\x13K\xef7\xe3\ ?\x02/.&xV\x00 \x22MK\xb2\xfcrl\ R\xbd\xac\x03\x7f\xfc9\xac~\xe0 \xf0C,08\ \x8d=\x90\x17\xbdm\xe0&\xff\xcb\xb1,\xc5\x1e4\xf9\ \xcb\xd2\xb5\x14\x04$Y^\xa4\xf1\x8b\xd7\x1a`\x17\xf0\ F\xf7u3\x0b\xaf\xee\x17\xeb{\xc0u\x8b\xf9l(\ \x00\x10\x91\xa6\xb8\x89\xf5S\xc0\xa7\xb1\x15L\xa7Mb\ \xdb\x04E\x86\xa0q\xdb\xa0\xc8\x12L6\xae|4\xf9\ K\x1b-:\x08h\xd8\xbf/^\x1b\xb9p\xc2\x8f\xe8\ \xdc{q\x12xS\x1aG\x87\x17\xfa\x8d\x0a\x00D\xa4\ )I\x96o\xc7\xd2\xffo\xf18\x8c3X@p\x00\ \x0b\x0a\x8e\x03#X00\x85\xa5\xfb5\xf9K\xbb\x5c\ \x14\x04\xcc\xd8\xbf/\x8a\xf5\xb6`\xe9\xfc\x1d\xd8{p\ \x80\xee\xbe\xff\xbe\x02\xdc\xb6\xd0\x96\x99\x02\x00\x11Y2\ \x97\xd2\xfc v\xf4/\xf2<\x9cF#X\xed\xc0A\ \xe0\x7f\x02o\xc5\x1e\xc2\x9a\xfc\xa5]\x8a \xe09\xec\ }U\xec\xdf\xbf\x09\xdb\xbb\xdf\x81\xb5\x17\xf6i\x04x\ C\x1aGg\xe6\xfbM\x0a\x00Dd\xc9\x92,\x8f\x80\ \xcf\x02\xef\xf1=\x16\x11\x0f\xc6\xb1\xbd\xf6\xcd\xd8j\xbf\ \xd5\x02\xd8N\xb8\x03\xf8/\xf3\x15\x03**\x16\x91%\ q)\xcf=\xd8JG\xa4\x8e\xfa\x80\xeb\xb1\x8a\xfd\x10\ '\x7f\x80\xf7\xb3@&B\x01\x80\x88,U?\xf0k\ \xe8\xe6<\x91\x90m\x02\xae\x9a\xef7(\x00\x10\x91\xa5\ \xda\x85\xedu\x86\xba\xf2\x11\x11\xf3!w\x22aV\x0a\ \x00Dd\xd1\xdc%:\xbf\x8ez\xe8\x8b\x94\xc1\x95\xd8\ \x11\xc4Y)\x00\x10\x91\xa5\xd8\x8ae\x00V\xf8\x1e\x88\ \x88,\xa8\x07\xb8\xc5\xd5\xed\x5cD\x01\x80\x88,\x8a;\ \xfa\xb7\x07;\xf2$\x22\xe5p\x03s4\xeaR\x00 \ \x22\x8b\xb5\x0ekn\xb2\xc6\xf7@Dd\xd1Va\x17\ v]D\x01\x80\x88,\xc8\xa5\x10w\xa1\xa3\x7f\x22e\ \xf4~W\xbfs\x01\x05\x00\x22\xb2\x18:\xfa'R^\ \xb3n\xdd)\x00\x10\x91\xc5\xd8\x81\x8e\xfe\x95\xdd\x14v\ Q\xcc9\xac\x93\xdd\x18v\x91\xd2\x08v\x15\xf3\xb0\xfb\ \xe7\x11\xf7\xeb\xe3L\xdf\xbc\xb8\xe0\xd5\xb2\x12\xbc\x9bg\ \x16\x03\xea\xc3,\x22\xf3r\xe7\x88wa'\x00\xa4<\ \xcea\x93\xfc80\xc1\xf4\x84?\xc4t\x000\x06\xfc\ \xbf\xee\xd7'\x81\x95\xc0\xff\xc2\xf4\x1d\xf5=\xee\xeb\x1a\ \xf7\xb5\x17\xeb.W\xbc\xb4\x88,\x8f\xeb\xb1\x8b\xb1\xce\ \xdf\x0f\xa0\x00@D\x16\xb2\x09+\xfe\xeb\xc6\x95\xbf\xd2\ \x9a\x09l2\x1f\x06\x0e\x03\xdf\xc7.F:\x01\x0c/\ t;\xdc|\x92,\x1f\x00\xd63}\xf1\xcdn\xac0\ t\x00\x0b\x18$l\xfd\xd8\x89\x80/\x16\xbf\xa0\xcb\x80\ DdN.e\x98`+\x87\x0d\x9e\x87#\xb3\x9b\xc2\ V\xf2#\xc01\xe0\xbfb\x17\xd5\xe4\xadL\xf8\x0bI\ \xb2|%p5\xf0\x0e,;\xb4\x0a\xeb\x0f\xa1\xac@\ \xb8\x0e\x03\xbf\x96\xc6\xd18(\x03 \x22\xf3[\x09\xfc\ *\xb6\xf2\x93\xb0La\x93\xfe)\xe0e\xe0\xbb\xc0\x81\ \xe2\xe1\xdeii\x1c\x9d\x05\x1eO\xb2\xfc\x09l\x8b\xe8\ \x1d\xc0\x15\xc0Z\xa6\xb7\x0b$,\xdb\xb0\x82\xc0\x17A\ \x19\x00\x11\x99G\x92\xe5{\x81\xbb\xb1\x07\xbc\x84a\x0a\ K\xf3\x9f\x04\xbe\x03<\x01\x9c\x9a\xef\xda\xd7nI\xb2\ |-\x96\x15\xb8\x0e\xcb\x0a\xacF\x81@h\x9e\x04n\ L\xe3hJ\x01\x80\x88\xcc\xca\x15\xff}\x0a\xbbW\x5c\ \xad\x7f\xc30\x0a\xe4X\x8a\xff1\xe0D\x08\x13\xffL\ \xee\xbds5\xf0Q\xacf`%\xda\x1a\x08\xc58\xf0\ Ki\x1c\x0dj\x0b@D\xe6\xb2\x11x#\x9a\xfcC\ 0\x81\xa5\xfa\xbf\x07<\x02\x1c\xed\xe4\xfe~\xab\xd28\ \x9a\x00\x9eM\xb2\xfcU\xe0\xc3\xc0;\xb1\x1a\x12\x15\x0b\ \xfa\xd7\x87\xd5\xf5\xfc_\xca\x00\x88\xc8E\x5c\xf1\xdf{\ \xb0\xe2\xbf9o\x13\x93\xae\x18\xc5*\xf9?\x07\xbc\x92\ \xc6\xd19\xcf\xe3Y\xb2$\xcb/\x07>\x8e\x9d\x1cX\ \x85\xea\xcf|;\x91\xc6\xd1\xeb\xf4C\x10\x91\xd9\xf4\x01\ \xbf\x84\x8a\xff|\x9a\xc4\x8e\xf3=\x0d\xdc\x9f\xc6\xd1\x09\ \xcf\xe3iZ\x1aG/'Y~\x10\xf8\x00p\x13v\ \xb4t9\xda\x16\xf0e#\xe8\x9b/\x22\xb3[\x8e5\ \x88\x19\xc2&\x22\xe9\xaeq\xec\xc8\xd6\x1d\xc0g\xca<\ \xf9\x17\xd28\x1aM\xe3\xe8\xff\x06\xde\x0f<\x83\x057\ \xc1\xd5/\xd4\x89\x02\x00\x11\xb9H\x1aG\xc3\xc0\x97\x81\ \xcfcg\xcbK\x97v.\xb1q\xe0\x05\xac\x80\xee\xf1\ 4\x8eF<\x8f\xa7\xad\xd28:\x04|\x08x\x14\xeb\ J\xa7 \xa0\xfb\x86A\xc7\x00Ed\x1e\xae\x9a\xfbr\ l2\xba\x14;\xdf\xad\x85C\xe7\x8c\x03\xcf\x01w\xa7\ qt\xc4\xf7`:\xc9\xddNw\x17Vk\xb2\x16\xbd\ \xaf\xba\xe1\x1c0\x08<\x9c\xc6\xd1\x17\x15\x00\x88\xc8\x82\ \x92,_\x8f\xa5n\xaf\xc7\xea\x02T\xcd\xdd~\xa3\xc0\ \xf3\xc0=U\x9f\xfc\x0b.\x08\xf8}\xe0V BA\ @'\x0d\x01\xaf\xd0\x10\x5c*\x00\x10\x91Eq\xd9\x80\ \xbd\xd8\xc3z7\xd6[\x5c\x0f\xec\xf6\x18\x05\x9e\x02>\ \x9f\xc6\xd1q\xdf\x83\xe9&w\xe2\xe4\x0f\xb0,S\x84\ N\x08\xb4[\xb1\xea\x7f\x00\xf8\x93\xc6\xe3\xa3\x0a\x00D\ dI\x92,\xdf\x08\xdc\x0c\x5c\x8b=\xb0\x95\x0dh\xcd\ 8\xd6\x9d\xedsU(\xf6k\x86\x0b\x02>\x02\xdc\x86\ \xf5\x0bP\x10\xd0\xba)l\xd5\xbf\x0f+$=6\xf3\ 7(\x00\x10\x91%s\xa9\xdb+\x81[\xb0\xde\xe2\xaa\ \x0dh\xce\x04\xd6\x97\xfdNW\x1cWkI\x967^\ <\xa5\xf7S\xf3\xc6\xb1\x1b \xef\x07\xd2\xb9\x9aF)\ \x00\x10\x91\xa65\xd4\x06\xbc\x1duz[\xaa)\xac\xc1\ \xcf'\x81}!\xb6\xf4\xf5!\xc9\xf2\xff\x13\xcb\x04\xac\ \xf2=\x96\x12\x9a\xc2NV\xbc\x04\xdc\x95\xc6\xd1\xc9\xf9\ ~\xb3\x22,\x11iZ\x1aG\x83\xc0g\xb1I\xecy\ t\xb6{)Nb\xdd\xfd\xf6k\xf2\xbf\xc0\x1fc\xb7\ \x1b\xea\xe8\xe9\xd2\x14\x1d#o\x07\xde\xbf\xd0\xe4\x0f\xca\ \x00\x88H\x9b$Y\xbe\x0e\xeb1\xfen,\x1b\xd0\xe7\ wDA;\x8b\xa5\xba\x9f\xa8\xda9\xffvH\xb2|\ ;\xf00v\x91\x90\xea\x01\xe67\xc9\xf4=\x11\xf7\xa6\ qtj\xb1\xff\xa1\x02\x00\x11i\x1bwR\xe02\xec\ \xa4\xc0\xa5\xd8-pz\x80_h\x12\xf8\x1aV\xf1\xbf\ \xe0*\xad\xae\x92,\x7f\x1f\xd6'@\xc7\x03\xe7v\x16\ 8\x02\xdc\x0b<\xbf\xd4L\x92>\x98\x22\xd26\xee\x16\ \xb8\x17\x93,?\x0a\xdc\x80e\x036\xa1\x1b\x05\x1b\x1d\ \x05\xbe\x8d\x1d\xcd\x92\xb9=\x01\xbc\x09\xcb*\xf5{\x1e\ Kh\xcea\xab\xfe'\x81/4\x9bER\x06@D\ :\x22\xc9\xf2\x1e\xac_\xc0-\xc0\x15\xc0j\xb4\xe8\x18\ \xc5R\xff\xa9R\xff\x0bK\xb2<\x02\x1e\xc3\xb2I\xbd\ \x9e\x87\x13\x8a3\xc0k\xd8\xaa\xbf\xa5\xfa\x11\x05\x00\x22\ \xd2QI\x96\xaf\xc6z\x06\xbc\x17\xd8\x8ae\x03\xea\x98\ \xd2\x9d\xc2n\xf6\xbb;\x8d\xa3\xa3\xbe\x07S\x16I\x96\ \xef\xc5\x9a\xd8\xd4\xfdh\xe08V8\xfaU\xe0\xd14\ \x8e\xc6[\xfd\x03\xeb\xfc\xcd\x14\x91.H\xe3h\x08\xf8\ \x13\xec>\xf8'\x81\x1c;\xff^7g\x80oa\xe7\ \xb3e\x91\xd28z\x1e\xeb\x95\xd0\xf2\x84WRSX\ \xba\xffY\xe0\x9d\xc0\x97\xdb1\xf9\x83\xd2q\x22\xd2\x05\ .My \xc9\xf2\xe3\xc0\xf7\xb1;\xe1wP\x9fv\ \xc2SX\x95\xf6aW'!K\xf3\x08v)\xd5&\ \xea\xf1~)\x8cb\x01\xe3\x03\xd8\x89\x91\xb6\xbew\xea\ \xf4\x8d\x14\x11\xcf\xdc\x9d\xf0)\xd6\xe8\xe5O\xb1\x94f\ \x1d\xce{\x0f\x03\xff\x0d\xcb~\xc8\x12\xa5qt\x00\xeb\ \x0dP\x97,\xc0\x04\xf6\xd9x\x1cx\x1bV3\xd2\xf6\ \xc0Q5\x00\x22\xe2\x85k'|5v\xaf\xc0.\xec\ \xc8`U\x17%\x8fc\xb7\xfc\xd5\xea\xa2\x9fvJ\xb2\ |'\xb6\x85R\xf5Z\x80!\xe0\x10p\x1f\xf0B'\ \x9bD)\x00\x10\x11\xaf\x92,\xdf\x80m\x09\x5cK5\ \x1b\x08\x8d`}\x11\x9eQ\xfa\xbf5I\x96\x7f\x1b\x88\ \xa9f\xcb\xe9\xa2\xc8\xef\xeb\xd8\xad}\xa3\x9d\xfe\x0b\xab\ \x1cE\x89H\x09\xb8f8\x9f\xc3\xda\x09?\x87\xad\x80\ f\xbd\xbc\xa4\xa4\xf6\x01G5\xf9\xb7\xc5w\xb0\xe67\ URt\xf2{\x16;)\xf3\xc5nL\xfe\xa0\x22@\ \x11\x09@\x1aG\xe7\x80\x17\x92,?\x02\xbc\x07{\x10\ n\xa2\xfcg\xbf\xa7\x80\xbf\xc3\x1e\xf0\xd2\xba\x17\xb1\xef\ eUzJ\x9c\x05\x8eaG\xfb\x9er\x9f\x83\xaeQ\ \x06@D\x82\x91\xc6\xd1i\xe0\x8b\xd8\x03\xf1\x8c\xe7\xe1\ \xb4\xc3\x10p\x18\xdb\x06\x90\x16\xb9\xe6I/\x02c\xbe\ \xc7\xd2\x06\x13X!\xec;\x81\xc7\xbb=\xf9\x83\x02\x00\ \x11\x09\x8c\xbb\xbb|\x94j\x9c\x0e8\x00\x9c\xd6m\x7f\ m\xf5\xb7T#\x008\x835\x85:\xe5\xeb\xfd\xa1\x00\ @DB\xb4\x82\xf2\x17zM\x01?\x02N\xfb\x1eH\ \xc5\xec\xc7R\xe7\x0a\xaaZ\xa4\x00@DB\xd4C\xf9\ \x9fO#\xd8q\xae\xaa\x15\xady\xe5\xb6\x01\x0eP\x8d\ \x0c\x91We\xff\x80\x89Hu\x95\xfd\xf9t\x02\x18R\ \xfa\xbf#~@5\xb6\x01\xbc*\xfb\x07LD\xaai\ 9\xe5\xaf\xf2\xce\xb1Z\x06i\xbf\xa3(\x03\xd02\x05\ \x00\x22\x12\xa2\x7fM\xf9k\x00\x06Q\xf5\x7f\xa7\x1c\xa3\ >m\x81;F\x01\x80\x88Hg\xfc\x0ce\x00:\x22\ \x8d\xa3\xb3Xqe\x95\x1aFu\x9d\x02\x00\x11\x09\xd1\ 2\xca\xfd|\x1a\xc7\x1a\xd6h\x95\xda9\xc7\xd06@\ K\xca\xfc\x01\x13\x91\xea\xea\xa3\xdc[\x00g\x80Q\x15\ \x00v\xd40\xca\x00\xb4D\x01\x80\x88\x84\xa8\x97r\x17\ \x01\x8ea\x9d\xde\xa4s\xfe\x05\x05\x00-Q\x00 \x22\ \xd2~\x0a\x00:o\x0c5\x03j\x89\x02\x00\x11\x09J\ \x92\xe5=\x94{\xf5\x0f\xb6\xf7\xaf\xd5ig\x8d\xa2\x00\ \xa0%\x0a\x00D$4\xfdX\x0d@\x99\x8d\xa0\x025\ \x09\x9c\x02\x00\x11\x11\x91\x1aR\x00 \x22\xa1)\xfb\x11\ @\x91R\xd0\x87LDB\xd3\x87\x9d\x02(\xb3\xb2\x9f\ b\x90\x1aP\x00 \x22\xa1\xe9\xa5\xfc\x01\xc0\x00\xe5\xff\ \xff\x10\xba2\xf7\x89\x08\x82\x02\x00\x11\x91\xf6\xab\xc2e\ F\xa1[\x83\x82\xac\x96(\x00\x10\x91\xd0\xf4P\xfeg\ S?Z\xa1v\xda\xbf\xa5\xfc\xef\x13\xaf\xf4\xcd\x13\x91\ \xd0T\xe1\x18\xe0\x0a\xb4:\xed\xb4U(\xcb\xd2\x12\x05\ \x00\x22\x12\x9a*<\x97\xd6\x00\xab\x93,W\x10\xd09\ e\xdf\x02\xf0\xde)\xb2\x0a\x1f4\x11\xa9\x9e\xb2?\x9b\ z\x80\x0dX6C\xda,\xc9\xf2~\xec\xfb[\xe6\x0c\ \xc0\x10\x9e;\x19\x96\xfdC&\x22\xd5S\x95\x02\xba\xd7\ \x01+}\x0f\xa2\xa26a\xc1U\x99\xe70\xefm\x8c\ \xcb\xfc\xcd\x13\x91j*\xfbU\xc0\x85\x0d\xd8q@i\ \xbf\xadT\xe3=\xe2\x95\x02\x00\x11\x91\xce\xd8\x00\xacJ\ \xb2\x5c\xcf\xd9\xf6{#\xe5/\x14\xf5NoL\x11\x09\ MUZ\x01\xaf\x066b'\x02\xa4M\x92,\xef\x03\ v\xa0\x0c@\xcb\xaa\xf0!\x13\x91j\xa9\xca\x16\xc02\ \xe0\xd7\x80\xb5\xbe\x07R1\xdb\x81\x88j\xd4\x89x\xa5\ \x00@D\x82\xe1\xaa\xbb\xd7R\x9dU\xf3. \xd26\ @[\xfd6\xd58]\xb1\x02X\xe9\xf3\xbd\xa17\xa5\ \x88x\x97dyo\x92\xe5\xeb\x81\xb7\x03o\xc3\xcex\ W\xc1z`3\xd5\x09h\xbcJ\xb2|\x05p9\xd5\ \xf8~n\x00>\x04lO\xb2\xdcK\xc6K)\x14\x11\ \xf1\xc6\xad~Vbi\xddw\x03o\xc1\xf6\xce\xab\xa2\ \xd8\x06x\x01\x18\xf5<\x96*\xa8R\xfa\xbf\x1f\xf8\xcf\ X@\xf3@\x92\xe5\xaf\x01\xa7\xd28\xea\xda\xf1@e\ \x00D\xc4\x0bW\xcc\xb5\x15\xf8=\xe0~\xe0}Tk\ \xf2/\xec\x026&Y^\x85I\xcb\x1b\x17,V%\ \xfd\xdf\xe8R\xe01\xe0v`\xb7\xdb\x06\xeb\x0a\xbd!\ E\xa4\xab\xdcD\xb8\x16\xd8\x03\xbc\x17\xb8\x8cj\xa4t\ \xe7\xb2\x01\xf8M\xe0 p\xda\xf3X\xca,\x02\xf6R\ \xbd\x00\x00\xac\xf0\xf5#\xc0\x15\xc0\xfdI\x96\xbf\x04\x9c\ L\xe3h\xb2\x93\x7f\xe9%\x9d\xfc\xc3ED\x1a%Y\ \xbe\x12[\xf5_\x07\x5c\x0b\xac\xf3;\xa2\xae9\x0e|\ \x1cx\xb1\xd3\x0f\xf5*r\xab\xff?\x04>I\xf5\xbb\ +N\x00\xcf\x02\x8f\x00\x07\xd38\x1a\xee\xd4_\xa4\x0c\ \x80\x88t\x9c+rZ\x8f\xad\xe0n\x04\xb6Q\xee\x8b\ \x5c\x96j\x13\xf0[\xc0a\x94\x05hF\x84\x05\x8du\ \xe8\xac\xd8\x0b\x5c\x8fe\xc8\x1eJ\xb2\xfc9\xe0h\x1a\ Gm\xbf\x86]E<\x81\xd5\ \x14\x14_\x97a\x93\xf9r\xf7\xb5\x17\xfb\x99\xff\x1f\xd8\ J\x7f\x036\xe1\xf7\xa3j\xfe\xb2\x19\xc2\x1d\xff+(\ \x03 \x22\x0bJ\xb2\xfcJ,\x0b\xb0\xc7\xf7X\xa4e\ \x93X6`\x0c\xdb\x13\x9er\xff|\x0e\x9b\xf0\xfb\xb0\ U~\x1f6\xd1k\xa1X\x0d\x8f\xa6qts\xe3/\ \xe8\x07+\x22\x8bq\x18+\x06\xdc\x89\xd2\xbde\xd7\xc3\ t*_\xeaa\x12\xf8\xe6\xcc_T\x0aGD\x16\x94\ \xc6\xd1\x10\xd6\x190\xf7=\x16\x11Y\xb2\xe3\xc0\xbe\x99\ \xbf\xa8\x00@D\x16k?\x96\x05\xa8\xfc=\xf5\x22\x15\ \xf3\xad\xd9\xfaDh\x0b@\xda\xc6\x1d\x19[\xee{\x1c\ \x8b0\x19B\xd3\x94\x12:\x89e\x01\xae\xc0.\xa9\x11\ \x91\xf0\x8d\x02\xcf\xcc\xf6?(\x00\x90vZ\x8bU\x1e\ \x87\xbeG|2\xc9\xf2\x97\xaax\xcfz'\xa5q4\ \x91d\xf9kX=\xc0\x15\xbe\xc7#\x22\x8b\xf2*\xd6\ \x1b\xe2\x22\x0a\x00\xa4-\xdcU\x9f;\x81\xfb\x09?\x0b\ \xf0\x1c\xf6\x818\xe9{ %t\x04\xdb\x06\xd8\x8d\xee\ q\x17\x09\xdd\x14\xf0\xc8\x5c\x9d!U\x03 \xed\xd2\x8f\ ]T\x12\xfa\xe4\x0f6\xd65\xbe\x07QFi\x1c\x8d\ `\x0df\x14<\x89\x84\xef\x04vg\xc4\xac\x14\x00H\ \xbb\x0c\x00\xaf\xf7=\x88E\x1a\xc0Z\x98Js\x0e\xb8\ Wp\xb7\xd0\x89\xc8\x05\xbe\x81\xf5z\x98\x95\x02\x00i\ \x97\x15\x94\xa7W\xbc\x02\x80\xd6\xe4X1\xe0\x19\xdf\x03\ \x11\x919\x8d\x00O\xcfw1\x94\x02\x00i\x97~`\ \xbd\xefA,\xd2\x00\xf0s\xbe\x07QV\xee\x81\xf2*\ vS`h\xc6\xb1Kp\x0ec\xc7\x16\x87\xfc\x0eG\ *\xaa\x0c\x05\xc4/a\xe7\xff\xe7\xa4\x22@i\x99;\ \xfe7\x80\x9d\x02(\x83>`M\x92\xe5\xcbu\x12\xa0\ i\xc7\xb0Z\x80K\xf1w?@\xd1\xd2v\xd8\xbd\xce\ b\xb7\xe0\xfd#\xb6\xf79\x02\x5c\x07\x5c\x8f\xdd\x5c'\ \xd2\x0e\xa7\xb1}\xf5\x15\xd8q\xd8UXW\xc5U\x84\ S\x035\x01<\xbc\xd0\xb5\xd0\x0a\x00\xa4\x1d\xfa\xb0\xc9\ ?\x947\xffB\x96a\x1f\xd8\xb5\xa8\x98\xad)i\x1c\ \x9dsG\x02\x8f`A@7\x8c3=\xd9\x0fc\xab\ \xfbA\xe0\xa7\xd8\xcf\xf1\x040\xdcx\xd3]\x92\xe5g\ \xb0\xec\xd45\xee\xabH+N\x03\x0f\x02\x7f\x8cU\xd8\ \xaf\xc7.G\xda\x00\xbc\x0e{\xa6\xacf: \x18\xc0\ O\xa6\xfd\x08\xf0\xf2B\xbfI\x01\x80\xb4\xc3\x0a\xec\xb6\ \xb02\xe9G\x01@\xab\x0ea\xc5\x80;i\x7f\xf07\ \x81\xad\xe0\x1b'\xfc\xc6\xd5\xfd\x09\xe0T\x1aGs\x16\ 8\x01\xa4qt,\xc9\xf2G\xb0\x87\xf1\x15\x1d\x18\xa7\ \xd4\xc7)\xe0!\xe0Ki\x1c\x8d\xb9_;\xea^\x00\ $Y\xbe\x96\xe9[\x13_\xe7\xbe\xae\xa6\xfbY\x82\xc7\ \xb0\xcf\xd0\xbc\x14\x00H;\xac\xa0|Eue\xda\xb2\ \x08R\x1aG\xc3I\x96\xff\x00\xb8\x0a\xd8\xd2\xc2\x1fU\ \xdcF\xd78\xd9\x9f\x01\xfe\x09\x9b\xe8\x8b\xd5\xfd\xc8B\ )\xcd9\xecc\xfa\xf2\x9b\x1d\x84\xdf\xa8J\xc2\xd38\ \xf9\x8f\xce\xf5\x9b\xd28:\x8de\x09^\x01H\xb2\xbc\ \x0f\x0b\x02\x1a\x83\x82\xc6,\xc1j\xda\xbf\x85v\x1a\xc8\ \x16\xf3YQ\x00 \xedP\xa6\x13\x00\x85\x95\x94/h\ \x09\xd1kX\xb1\xdd&\x16\xff<\x19\xc7\xf6\xeb\xcf2\ \x9d\xca\xcf\x99^\xdd\x9f\x04\xce\xb4\xab>#\x8d\xa3\xa9\ $\xcb\x9f\xc7~\xe6\x9f\xc0\xfaU\xe8\xd9'\x8b\xb5\xa8\ \xc9\x7f6.Cu\xc4\xbd\x80\x8b\xb2\x04\xaf\xc7\xb6\x11\ \x8a,A\x11\x18\xb4\x12\xa4>\xeb\xc6\xbc }\x08\xa4\ \x1dVP\x9e\x13\x00\x85\x01\xe0\xe7\x93,_\xd6\xe4\xaa\ R\xcc)\xe0\x07Xz}\xb6 \xb0q\xb2/&\xfc\ \xd3\xd8\xea~\x10\x9b\xec\x07\x81\xb1N\xfe\x1c\x5c\xcd\xc2\ 3\xd8\xd6\xcfG\xb1\x87\xafNA\xc9B\x9a\x9e\xfc\xe7\ 2G\x96\xa0\x08\x086aY\x825L\x07\x05\xabX\ |\xfd\xca\x18\xf0\x8d\xc5~\x96\x14\x00HK\x1aN\x00\ \x94\xad\xca\xba\x0f\xfb\x90\xad\xc0*\xc9\xa5\x09nu\xfd\ *Vpt\x056\xe1\x8f\xba\xd7Y\xa6'\xfb\x1c\x9b\ \xecs\x9aO\xe5\xb7:\xd6\x91$\xcb\x9f\xc0\x1e\xa6\x1f\ B\x19 \x99_\xdb'\xff\xd9\xb8,\xc1a\xf7*\x9e\ \xa9\xeb\xb0\xa0`#\xf0\x8bXp]d\x07\x8a\xad\x83\ \xd9j\x09^\xc2Zu/\x8a\x02\x00iU\xd9N\x00\ 4*\xea\x00\x14\x00\xb4\xe68\xd6q\xec\xc7X\xe1\xde\ \x106\xf1\x9f\xc2\xd3d?\x974\x8e\x86\x92,\xffS\ \xe0_\x03\x09j\x09-\xb3\xeb\xca\xe4?\x1b\xf7y\xc9\ \xdd\xeb%\xb8 K\xb0\x1e\x0b\x06^\x8f=\xbb\x8a\x80\ \xa0\xa8#\xb8\x9f%t\xe8\xbc\xa4]\x83\x96zr\xfb\ Y\x9f\x00>\xe5{,Mx\x0d\xb83\x8d\xa3\x97|\ \x0fD\xba+\xc9\xf2\x0d\xd8\xfb\xf6]\xe8jc\xb9\x90\ \xb7\xc9\x7f)\x92,_\xc5t@\xb0\x16\xdb\xd2\xfar\ \xe31\xd8\x85(\x03 \xad\xea\xa3\xbc\xa9\xd4\x95\x94\xaf\ xQ\xda \x8d\xa3\x93I\x96\x7f\x15\xcb\x5c]\x83\x82\ \x001\xa7\xb0s\xfe_\x0ey\xf2\x07;\x85\x83\xd5\xd4\ \x1ch\xf6\xcfP\x11\x8c\xb4\xaa\x8cG\x00\x0b:\x0aX\ ci\x1c\x1d\x01\x1e\xc0\xaa\xa6\x87=\x0fG\xfc;\x85\ \xbd\x1f\x82\x9f\xfc\xdbE\x01\x80\xb4\xaa\x8cG\x00\x0b\xc5\ I\x00e\xc2j*\x8d\xa3\xc3\xd8\xbe\xe9S\xe8\xde\x80\ :+V\xfe_\xa9\xcb\xe4\x0f\x0a\x00\xa4\x05\xaeZ\xb5\ \x9f\xf2\x9d\x00(\xf42]Y+5\xe52\x01\xf7\x03\ \x8fc\x13A0E\x8b\xd2\x15\xa5I\xfb\xb7\x9b\x02\x00\ i\xc5r\xac\x8a\xba\x8c'\x00\x0a\xaa\x03\x10\xd28:\ \x8e\xa5\x7f\x1f\xc6\x8e+.\xba\x90JJm\x08+\xf8\ \xab\xdd\xe4\x0f\x0a\x00\xa45e\xbc\x03`\xa6\x01\xca[\ \xc3 m\x94\xc6\xd1 \xf0e,\x1bp\x84E\xf4R\ \x97R\x1b\x06\x1e\xa5\xa6\x93?(\x00\x90\xd6\x94y\xff\ \xbf\xa0\x96\xc0r\x9e\xab\xac~\x14\xf8\x02vLt\xde\ \xcb\x86\xa4\xb4F\xb1-\x9f\xfb\xd28\x1a\xf1=\x18_\ \x14\x00H+\xca|\x02\xa00\x00\xfc\xbc\xefAH8\ \x5cg\xb6'\x81{\xb1{\xdfk;AT\xd4\x18V\ \xf4\xf9\x05j~\xfaC\x01\x80\xb4\xa2\x8cw\x00\xcc\xb4\ \x02X\xeb:m\x89\x00\xe0\x9a\xa9<\x8f\x05\x01Oa\ \xb7\x13\xaa8\xb0\xfc&\xb0c\x9f\x9f\x05N\x87\xd4\xa5\ \xd2\x07\x1d\x7f\x92\xa64\x9c\x00({+\xd5e\xd86\ \xc0Z\xec&:\x11\xe0|K\xd6\xfdI\x96\x9f\xc5\x8a\ \xc5n\xc0\x02^-\x9c\xcai\x0ax\x11\x0b\xeaN\xd5\ }\xf2\x07\xbd\x91\xa5y\xc5\x11\xba*\xac\x9cU\x07 \ sJ\xe3\xe8\x04vB\xe0UT\x18Xf\xfb\x81{\ \x80cKi\x97[e\x0a\x00\xa4YUH\xff\x17t\ \x12@\x162\x86\xad \xf5\xcc,\xa7q\xe0\xf3\xc0!\ M\xfe\xd3\xf4f\x96f\xf5\x03\xbf\xe0{\x10m\xa2\x00\ @\x16R\x5c\xb8\xd2\xeb{ \xd2\x94q\xe0`\x1aG\ \xe7|\x0f$$\x0a\x00\xa4\xacx/_\x00\x00 \x00\ IDATYe\xbe\x04h&\xb5\x04\x96\x85l\xa2\ \xbc\x1d/\xc5>\xe3\xab\x5c\xed\x928\xfafH\xb3\xaa\ \xd0\x03\xa0\xb0\x1c{\xb8\x0f,\xf4\x1b\xa5\xb66\xa1\x1b\ \x03\xcb\xac\x07\xd8B\xb9\xbb\x96\xb6\x9d\x02\x00i\xd6\x0a\ \xaau\x93\x9e\xb6\x01dVI\x96\xf7\x02\xafCwF\ \x94\xdd\x1b\xd1\x16\xce\x05\x14\x00\xc8\x92\xb9\x07\xe2*\xac\ \x0e\xa0*t\x12@\xe6\xb2\x16\xcbvi\xf5Xn\xdb\ \xd0\xcf\xf0\x02\x0a\x00\xa4\x19U\xe8\x008\xd3\x00\xd5\xca\ hH\xfb(\xfd_\x0d[\xb1g\x978\x0a\x00\xa4\x19\ }T\xaf}\xeeJ\xaas\xaaA\xdaK\x05\x80\xd5\xb0\ \x1aX\xef2\x98\x82\x02\x00iN\x95z\x00\x14V\x00\ k\x92,W\x8ap\x91\x92,_\x9ed\xf9\xa6$\xcb\ \xab\x96\x0d:\xcf\x9d\x0cy=\xca\x00T\xc5NT\x07\ p^\xed\x8f=%Y\xbe\x02\xd8\x81\xf5\xfa>\xa1\xf6\ \x90\x8bR\xa5\x13\x00\x85\x1e\xec!\xbf\x1a\xc8=\x8f%\ xI\x96\xaf\x06.\x03~\x1b\xf8Y\x92\xe5\x8f\xa7q\ t\xd2\xf3\xb0:a\x15\xf6^\xafB\xc7K\x817a\ u\x00c\xbe\x07\x12\x82\xda\x06\x00\xee<\xe8J\xe0]\ \xc0;\xb1>\xf0\xdfM\xb2\xfc\x95\xba\xde\x0d\xbd\x04U\ \xac\x01\x80\xe9B@\x05\x00sp+\xe2\x8d@\x0c\xdc\ \x88\x1d\xad\x1a\x02\xfe\xd7$\xcb\x1f\xae`\x10\xa0\xf4\x7f\ \xb5lG\x85\x80\xe7\xd5r\x0b\xc0M\xfek\x80\x0f\x00\ w\x01\x97\x02\xef\xc1n\x88\xfa\xbd$\xcb\xb7\xa8a\xc4\ \xec\x1aN\x00T\xf1H\x94\x8e\x02\xce#\xc9\xf2~l\ \xd5\xffI\xe0\x13XUu\x0fV<\x99\x00\x1fJ\xb2\ |\x83\xbf\x11v\xc4F\x94\xfe\xaf\x92\x08\xdb\xea\xd3\xf3\ \x9d\x1a\x06\x00\xee\x07\xbf\x0e\xb8\x15\xf84\xd3\x1f\xee\x1e\ \xec\x81\xf6\x19\xe0\x0e\xe0j\xf7\xc0\x93\x0b\xf5a\x1f\xa2\ *\xbewt\x14p\x0en\x9f\xff\xed\xd8\xe7\xe3=\x5c\ |\x0bd\xe5\x82\x00\xf7\xac\xd0\xfe\x7f\xb5\xf4\xa2\xe3\x80\ \xe7U\xf1!>'\xf7\x81\xde\x08|\x1c\xf8\x03f\xff\ `\xf7c\xdb\x02\xca\x06\xccn\x05\xd5\xad\x96\x1f\x00\xfe\ \x9d~\xde\xd3\x92,\xefM\xb2|;\x160\xdf\x8ee\ \x00\xe6zxV-\x08\xe8\xc7\x8a]\xb5\x10\xa8\x967\ \xa3\x00\x00\xa8Q\x00\xd00\xf9\x7f\x02\xf8\x18\xf3\x9f\x07\ -\xb2\x01w\xa2l\xc0LU<\x01P\xe8\xc3V\xb6\ :+\x0c$Y\xbe\x12\xb8\x0a\xfb\x0c|\x18\xdb\x0f_\ \xe8\x99Q\xa5 `\x03\xf6~\xa8\xcds\xb2&v\xa0\ \x93\x00@M\xde\xd8\xaepi36\xf9\x7f\x80\xc5\xff\ \xf0\x07\x98\xce\x06|0\xc9\xf2M\x9d\x19a\xa9T\xf1\ \x04@\xa3\x95\xd4\xbc!P\x92\xe5\xcb\xdc\xe4\xfd\x1e,\ \xe5\x7f\x0dK\xab\xf9\xa8J\x10\xa0\x06@\xd5\xb4\x05X\ \xa9L_\x0dN\x01\xb8\xc9\x7f+6\xf9\xbf\x8b\xa5G\ ~\x8d\xd9\x807$Y\xfeM\xe0\xb5\x1a_+Y\xd5\ \x13\x00\x85\xa2\x0e\xe0\x98\xef\x81\xf8\x90dy\x1f\xf6~\ \x7f76\xf17\x1b\xec\x15A\x00%>\x1d\xf0\x06\xca\ w\x02`\x1c\x18\x05\x96z\xe7}\x0f\x96\x16ofR\ \x5c\xd1\xe4\x7f\xe7\xcb\x0a,\x088\x09\xd4\xf59\x0eT\ <\x00h\x98\xfco\x07\xae\xa7\xb57\xe9J\xec\x81\xb6\ \x19x$\xc9\xf2\x17\xd28:\xdd\xfa(\xcb\xa3\xe2'\ \x00\x0a\xb5=\x09\x90d\xf9\x1a\xe0r\xe0\xbd\xd8\xc9\x98\ V\xb7\xbdJ\x1b\x04\xb8@h\x03\xe5\xba!r\x12x\ \x0e\xf8\x11\x16\x08,E\x0f61\xfe\xab&\xfe\xde\xcb\ \x80]\x94\xabW\xc2\x9b\x81\x17P\x00PMm\x9e\xfc\ \x0b\xbd\xc0\x1elU\xf4\x86$\xcb\xbf\x0b\x1c\xa8Q\xf3\ \xa0*\x9f\x00(\xd4\xee$\x80\xfb\xacl\x02\xae\xc5z\ bl\xa1}?\xe3\xb2\x06\x01\xeb\xb1\xfd\xff2=#\ \x8f\x00\x0f\x02\xfb\xd28Zj\x06\xa0iI\x96_\x05\ |\x81\xf6\xbeo:m\x07\x96\xf1\xa8u\xcf\x97\xb2\xfc\ \xb0\x96\xa4C\x93\x7fa\x196\x09~\x0c\xdb\x1f\xbd\xd6\ \x15K\xd5A\x95O\x00\x14\xfa\xb1\x93\x00ez\xf07\ -\xc9\xf2\x01\xe0J\xac\xd0\xef6\xecs\xd3\xee\xe7B\ \x19k\x02\xcav\xfe\x7f\x04\xf8:p\xb8\x9b\x93\xbf\xf3\ \x0a\x90\xb91\x94\xc56T\xec[\xbd\x00\xa0\xc3\x93\x7f\ \xa3>`/p\x0f\xf0\xe1\x9a\x1c\x17\xac\xf2\x09\x80B\ \x1d\xb69\x8aB\xbf\xf5\xc0\x0dX {=\x9d\xdd\xef\ .[\x10\xb0\x91\xf2\xec\xffOa\xe9\xec\xe7\xd28:\ \xdb\xed\xbf\xdc\xd5C}\x1d8\x00Lt\xfb\xefo\xd2\ j`C\xdd/\x06\xaa\xd4\x84\xd5\xc5\xc9\xbfP\x9c.\ \xb8\x1d[A\xedu{\x87U\xb5\x02\xdb\x17\xad\xbaJ\ o\x03\xb8\xf7\xe8.\xac\x1f\xc6\xa7\xb1m\xadn<\x08\ K\x11\x04\xb8\xe7\xc8\xeb(O\x10x\x1c\x9b\x80\xbd\xb5\ \xb0N\xe3\xe88\xf0\x18p\x0a\x0bH\xca\xa0\xf6\xc7\x01\ +\x13\x00x\x98\xfc\x1b\xf5\xbb\xbf\xf3n\xe0}ne\ U).\xbb1@\xb5\x8f\x00\x16*[\x08\xe8.\xf1\ \x89\xb1U\xff\x07\xe8~F\xa7\x0cA\xc0\x1a\xec\xe7_\ \x86f1c\xc07\xb1Z$\xdf\x05m\xdf\xc32\x11\ e\xb9h\xa7\xb8\x18\xa8\xb6*\x11\x00\xb8\xc9\x7f;~\ &\xffB/\x16Q\xde\x05|2\xc9\xf2=\x15\xdbG\ ^\x81e;\xea\xd0\x10i\x15\x15\xbb7<\xc9\xf2\x9e\ $\xcb\xb7\x00\x1f\xc4\x8e\xb4\xee\xc5\xdf\xcf2\xf4 `\ 3\xe5I\xff\x17\xfb\xef\xc3\xbe\x07\x92\xc6\xd1\x18\xf0\x08\ V\x8c\xd8\xed:\x84f\x14\x85\x80\xb5u\x89\xef\x01\xb4\ \xcaM\xb2\xbb\xb1s\xfe\xd7\x10FPs\x0e\xfb`~\ \x1dx\xde\xc7\xbe\x5c;\xb8\xef\xedj\xacB|;\xf0\ 6\xec\xc8O\xd5\x8d\x03\xaf\x02\x7f\x86\xa5W\x8f\x03\xa7\ =\x14W\xb5\x85\xbb\xf2z\x17v\xbc\xefj\xc2\x99\xdc\ N\x03)\x10\xd4\xe9\x80$\xcb?\x82m\x8d\xac\xf7<\ \x94\x85\xe4\xd8\xc5L\xcf\xa5q\xb4\xd4c\x7f\x1d\xe12\ \x85\x1f\xc1\xb6DCo\xa85\x01\xfc:p\xb0F'\ \xb9.P\xea\x00\xc0MP{p\xfb\xef\x9e\x873\xd3\ $0\x88\x05\x01\xcf\xa6qt\xc4\xefp\x16g\xc6\xa4\ \xbf\x09\xf8el\xf2\xdfL\xb9\xaa\xa2\xdba\x04k\x08\ t\x10\xf8{\xf7\xcf'\x80\xa1\xb2\x04\x03\xee\x12\x9f\xbd\ \xd8\xd5\xbd\xbb\x09o\xc5\x13T\x10\xe0\xde\xff\x9f\xc72\ %!W\x89O\x00\x7f\x0c\xdc\x17Z?\x12\xb7\xcdt\ ?\xb6\xd5\x14zM\xd4\xcd\xc0\x93\xa1\x04P\xddV\xda\ \x00 \xf0\xc9\xbf\xd1(\x96\xa2\xfb\x06v>7\xb87\ \x9aKu\xaf\xc1*\x9f7R\xefI\x7f6S\xc0Y\ \xe0(p\x88\x0b\x83\x81\xe1\x10W\x0f\xeeg\xba\x15x\ \x07v\x8b\xdf\x06\xc2\xc8\x8e\xcd&\x98 \xc05Cz\ \x08\xcb&\x86\xec\x15,K\x11d\x1f\x92$\xcb\xaf\x00\ \xee\xa33\xc7J\xdb\xe9+\xc0\x1di\x1c\x95\xe9\x08c\ \xdb\x94r\x8f\xbaD\x93?L\x17\x08n\x02\xbe\x9ed\ \xf9\xf7\xd28\xf2V\xad[p\xdf\xc3U\xd8$\xbf\x19\ x#\xf6aU\xff\xf3\x8b-\xc3\xbe'\x97a\x1d\xf2\ \x86\x80\xc3\xee\xf5\xf7I\x96\x1f\x01N\xb8=P\xef\x5c\ _\x8a\xcb\xb0U\xff\x15\x84_\xcd\x1eR\xb3\xa0M\x5c\ |\xd5qh\xce`\x15\xf7\xc7B\x9c\xfc\x9d}\xc0w\ \xb1\x9fm\xc8\xcf\x93Z\xd7\x01\x94.\x03P\xb2\xc9\xbf\ \xd1\x14\xf6\xc1}\x0a\xf86\x16\xb9w=\x8d\xecn5\ \xdc\x8cu\xed\xfa\x15`'Z\xe97k\x12[\xbd\x1e\ \xc0\xda\xaf\x1e\xc6\xb2\x04\xa7<\xfdl{\xb0\x0c\xce[\ \xb0\x8e~\xdb)W\x90\xef=\x13\x90d\xf9\x07\xb1b\ \xe2\x8d>\xfe\xfeE\x98\x04\xbe\x06\xdc\x9b\xc6\xd1\xa0\xe7\ \xb1\xcc\xcb\x15x>\x88\xb5\x97\x0eu\x92\x1d\x05~\x15\ 8\x1ep0\xd51\xa5\x0a\x00J<\xf97\x1a\x07^\ \xc6\x8e\xee\xbc\x90\xc6Q\xc7\xabw]:8\xc2V\xf8\ \xdb\xb07\xfcv\xc2/\xd2)\x93q\xacX\xf05\xe0\ \x87X0p\x22\x8d\xa3\xae\xb4\x1am(\xf4\xbb\x11\xfb\ l\x94\xf5g\xeb5\x08H\xb2\xfc^\xec\xea\xe3PO\ \xbb\x1c\xc0\x0a\xff^-C\x1dJ\x92\xe5o\x07>G\ \xd8[Po\xc5\x8a\xb5\xcb\xd2\xc4\xa8mJ\x13\x004\ L\xfewbw\x94\x97YQ \xf8\x04\x96&;\xd2\ \x89\xe8\xd3\xad\xf6\xb7`\x93\xfd\xaf2\xbd\xda/\xd3\xaa\ \xb0l\xa6\x98\xce\x0a\xfc\xd0}=\x82\x15\x0evd\x85\ \x91dy\x84M\xfa\xef\xa6|\x97\xb2\xcc\xc6K\x10\xe0\ \x82\xa8\xafb\xb7\x86\x868Y\x9d\xc5z\x8d<^\x96\ \x93E\xae\xe9\xd4\xe7\xb0-\x9eP/V\xba\x0b\xf8b\ ([x\xddT\x8a\x00\xa0b\x93\x7f\xa3Q\xec\xf6\xae\ o\x02/\xb5\xa3@\xd0\x1d\xc3Y\x85M\xf6;\x80\xdf\ \xc0\x02\x80P\x8e~\xd5\xc9\x186\xf9\xbf\x0a\xfc\x00+\ \xcc\xdb\xb5\xd2H\xb2|9\x96\xd1y\x07V\xb4\x16\ \xf2*k\xa9\xba\x1e\x04\xb8>\x09\xf7cw#\x84f\ \x0ax\x12\xb8\xdbu\xdd+\x8d$\xcb\xb7a[\x01\xbb\ \x09s\xf1\xf1,\xf0\xa1ndcC\x13\xe2\x0f\xe3\x02\ \x15\x9e\xfc\xc1\xd2\x8c\xd7b\xfb\x8d\xeb\x93,\xcf\x9a-\ \x10t\xdf\xa7\xb5\xd8\x0a\xf0\xd7\xb1\x22\xb0-\x84\xbb\xf7\ V\x07+\xb0\x87\xde\x0el_~\x1f\xf0\xfd$\xcb\xf7\ \x03'[\x09\xf8\xdcQ\xab+\xb0U\xff\xe5\x84\x9b\xb2\ n\x96\x8f\xc2\xc0\x88pW\xa9\xc7\xb0\x85\xc2\xa0\xe7q\ ,Y\x1aG\x87\x93,\xff\x06\x16\xa0\x86\xb85\xb5\x8d\ \x9a\xb6\x04\x0e:\x03P\xf1\xc9\xbf\xd1\x14VY\xfe4\ \xf0\x1d\xe0\xb5\xc5\xae\x12\xdd\xfe\xfezl\xe2\xff\x0dl\ \xe2\xdfDuV\x82URl\x0f\xbc\x06\xfc\xad\xfbz\ l)\xa9G\xf7\xf3\xde\x84\xad\xf8\xdf\x81\x05y\xc1\x07\ \xf2-\xe8Z& \xc9\xf2\x0f`\xf5E\xa1\x15\x00\x8e\ \x01\x9f\x05\x1eM\xe3h\xc8\xf7`\x9a\x91d\xf9*\xec\ \xca\xe0k\x09\xaf\xbf\xc2\x04\xb6Ez\xb8n\x85\x80\xc1\ \x06\x005\x9a\xfc\x1b\x8dc\x93\xc27\xb0\xa2\x943s\ \xfdF\x97\xfe\xdd\x88\xad0\x7f\x13\xfb^\x85\xd8VU\ f7\x04\xec\xc7\x02\x81W\x80\xa3\x0b\x05\x02\xeex\xdf\ \x1el\xd5\x7f%\xf5\xd9\xd6\xe9J\x10\x90d\xf9\x7f\xc6\ \xaeD\x0e\xe9\xfb:\x85\xf5\x11\xf9\x0c\xf6\x1e)\xed\x04\ \x95d\xf9n\xe0\x01\xc2<\x9dr#\xf0L\x00\xf7)\ tUh?\x04\xa0\xb6\x93?X\xf1\xd6\xe5\xd8D\xfe\ \xba$\xcb\xff\x8c\x866\x95n\x7f\x7f\x05\x96\xb2\xda\x89\ \xa5\xfa\xf7\x10fZM\xe6\xb7\x1a\xdb\x16\xd8\x03\xfc\x16\ \xf07nk\xe0(3\x9a\x0b\xb9\xcf\xc3\x06.<\xde\ W\xa7\x94e\xb7\xb6\x03\xfe\x0d\xe1\x15P\x9e\xc4\xba\x89\ \x9e(\xf3\xe4\xef\xec\xc7\xb61\xd6\x11^\xaf\x85_\xc1\ .3\xaaU\x00\x10\x5c\x06\xa0\xc6\x93\xffL\xa3\xc0K\ \xb8S\x02\xd8^\xfe\x06\xe0\x97\x98\xdeW\x0eu\xbfR\ \x96\xee,\xf6s\xde\x8f\xf5\x148\x8a\xed\xf7\x16w]\ \x5c\x87U\xfaW\xf2\x96\xc2E\xeah& \xc9\xf2?\ \xc4\xaeH\x0eer\x1a\x07\xbe\x08<8_6\xb0L\ \x5c\xa7\xc5\xfb\x08\xafM\xf0S\xc0\xade9]\xd1.\ Ae\x004\xf9_\xa0\x1f[\xf1m\xc3\xce\x94\xf7a\ {\xbf\xeb\x08\xec\xe7&mQt\xef\xdb\x8dM\xfc\x87\ \xb0V\xc3=X\xf7\xc1Zw,s:\x9d\x09x\x01\ \xf8\xdf\xb1,\xdc&\xfcOP\xaf`\x17R\x95r\xdf\ \x7f6i\x1c\x9dI\xb2\xfc!\xacv%\x846\xc1\xe3\ X\xe0\xfd}\xac\x16\xa0VB\x9bH\xfa\xb0\x08\xbc\xee\ \x93\x7f\xa1H\xfdjo\xbf>\x8a\x22\xbfM\xbe\x07\x12\ \xa8\xb5\xd8\xf3\xe1o\xb0\xf4x\xdb\xa4qt0\xc9\xf2\ a\xe0\xef\xb0\xa2\xb0\x1dX\x00\xbe\x8a\xeeOT\x83X\ -P\x15;\xd4\xbd\x0a|\x0bkh\xe4\xab\x03\xe9\x10\ \x16d\x1f\xc0\x8e\xe8\xee\xabc\x1f\x80\xd0\x02\x00\xb0\xd4\ \xb7\x88\xc8l\xce\xe1\xfa)t\xe2\x0fw\xc7p\xf3$\ \xcb_\xc4V\xa8\xbb\x817cu\x17\xeb\xe9N\x16f\ \x1cKI\xbfR\xc5I)\x8d\xa3\xc9$\xcb\x1f\xc7\xbe\ \xaf{\xe9^\xa6e\x12\xcb\xaa\x1d\xc6\x9at\xbd\x8aU\ \xfe\x07wA[\xb7\x84\x16\x00\x8ca\xfbC\xdb\xb0\xe8\ [D\xa4\xd1\x01l\xf5x\xa2\x93\x7f\x89k\xe1\xfc\xaa\ +\xcc\xdc\x80=\x8f\x8a\xac\xc0V\xac\xfe\xa6SY\x81\ }\xd8q\xe0\xa0\xae\xf9m\xa74\x8eN\xb9\xad\x80M\ \xd8v@'3,E}\xcd!l\xe2\xdf\x0f\x0c\x96\ \xa1\x95r\xa7\x85X\x04\xd8\x8b]_z?\xba\xa0F\ D\xa6\x0d\x02\xf7\x02Ot\xeb\x8e\x85F\xee,{c\ V`\x07\xb6%\xd1\xce\x13\x19\x83X\x0dTV\xc5\xd5\ \x7f#\xf7\xac\xffOtf+`\x12\xbb\x9b\xe30\xf0\ \x13l\xd2?\x08\x8cUpK\xa5i\xc1\x05\x00p\xbe\ \x87\xfd\xdd\xc0\xef\xe3\xbfHDD\xfc\x1b\xc3n\xc1\xbb\ \xdf\xf7-x\x0d\xcd\x98v1\x1d\x08l\xa6\xf5n\x8c\ \xe3\xc0\x97\x80\x07\xd28:\xd5\xe2\x9fU\x0aI\x96\xaf\ \xc3\x16{\xed\xda\x0a8\x83\xad\xf6\x0fc\xa7i\x0e\xa0\ \xd5\xfe\x9cB\xdb\x02(\x8c\x01\x0fag\xdd/\xf5<\ \x16\x11\xf1k\x8a\xe9\xb4xG\xf6\xfe\x97\xc2u\xe9<\ \x02\x1cI\xb2\xfc9,\x00\xd8\x09\xbc\x89\xe9[6\x9b\ y\xb6V>\xf5?\x93\xdb\x0ax\x10kj\xd6lW\ \xcb\xe2&\xceC\xc0\x8f\xb1\x95\xfe\xe1\xaagP\xda!\ \xc8\x0c\x00\x9c?\x12x5v;W(\xe7rE\xa4\ \xfb\x8ea\xadp\x9f\x09\xb5`\xcb\xddz\xb7\x99\xe9@\ `\x07\x96%XlV`\x90\x9a\xa4\xfegr\x19\x95\ \x8f\x01\xb7\xb3\xf8.\x8cSX0x\x04\x9b\xf0\x7f\x82\ \xad\xf6\xcfh\xb5\xbfx\xc1\x06\x00p\xfez\xce;\x80\ OQ\xaf\xceg\x22b\xce\x02_\x06\x1eJ\xe3(\xf8\ \x95\xb1\xeb\xd6\xb9\x06\xcb\x04,6+P\xbb\xd4\xffL\ \xeer\xab{\xb1\xfa\xaf\xf9\xee\x0a\x18\xc1\x9ad\x1d\xc2\ &\xfd\x83X\x8b\xe4Zu\xf0k\x97P\xb7\x00\x0a\xe3\ \xc0\xc3\xd8\x07I\xbd\x01D\xeae\x12\xd7\x0d\xb3\x0c\x93\ ?\x80+0;\x0d\x9cN\xb2\xfce,+\xb0\x9d\xe9\ @`\x0b\x96\x15h\xacm\xaa]\xea\x7f\xa64\x8e\x86\ \x1a\xb6\x02vq\xe1\x82\xaf(\xe8;\x82\xa5\xf8\x0fa\ \x13\xffY\x15\xf4\xb5&\xe8\x00 \x8d\xa3\xa9$\xcbO\ \x01\x9f\xc7\xde\x18j\x88#R\x1f\x87\xb1\xde\xf1G}\ \x0f\xa4\x19n\xbb\xe2 p\xd0\xd5\x0al\xc3\x82\x80_\ \xc6\x9eg\x1b\xb1\x864\x8f`\xb7B\xd6}2;\x88\ m\xf9\xae\xc5\xaef>\x85m\xff\x14\x13\xffA\xac\xa0\ \xafv\x1d\xfb:%\xe8-\x80\x82\xbb\xf9\xeec\xc0=\ \xa8\x1d\xaaH\x1d\x9c\xc1z\x82<\x9a\xc6\xd1\xb0\xef\xc1\ \xb4\x8b\xabm\x8a\xb0\xfa\x80\x22\x00x\xb9\xac\xd7\xfc\xb6\ \x9b\xdb\xf6\xfd0\xf0\xbf\x01?\xc5\x82\xbfc\xe8\xf8^\ G\x94%\x00(\xf6\xd5\xee\x03\xae\xf7<\x1c\x11\xe9\xac\ s\xc0\x13\xc0\xe7\xd38:\xe6{0\xd2]I\x96\x0f\ `\xef\x81\x09M\xfa\x9dU\x8a\x00\x00\xceG\xce;\x81\ \xc7\xb0}5\x11\xa9\xa6}X\x1f\x90\x97U\xd1-\xd2\ 9\xa5i\xb2\xe3\x1e\x04\x87\xb0\xa6\x11\xba/@\xa4\x9a\ \x06\xb1}\xff\xfd\x9a\xfcE:\xab4\x01\x00\x80;\xea\ \xf14vQ\x86RC\x22\xd52\x06<\x0b<\xef\xa3\ \xd5\xafH\xdd\x94*\x00p\xce\x02\x0f`M\x1fD\xa4\ \x1a\x82\xea\xf6'R\x07\xa5\x0b\x00\x5cQ\xc81\xe0\x0b\ X\x05\xad\x88\x94\xdfq,\xf5\x7fH\x85_\x22\xddQ\ \xba\x00\x00\xce\xf7\xe2~\x1e\xf8S\xacI\x84\x88\x94\xd7\ Ylk\xef\xa5P[\xfd\x8aTQ)\x03\x00g\x0c\ \xeb\x12\xf8\xb2\xe7q\x88H\xf3J\xd7\xedO\xa4*J\ \x1b\x00\xb84a\x8eu\x09\x1c\xf4;\x1a\x11iR\xa9\ \xbb\xfd\x89\x94Yi\x03\x008\xbf\x15\xb0\x0fk\x1f\xa9\ \xcb D\xca\xe54\xf0-`\x9f\xda\xbb\x8at_\xa9\ \x03\x00\xe7\x1c\xf08\x90\xf9\x1e\x88\x88,\xda9\xac\x8e\ \xe7{Uj\xf5+R&\xa5\x0f\x00\xdcV\xc0\x19\xac\ A\x90\xda\x86\x8a\x94\xc3\x01l\xf5\x7f\xc2\xf7@D\xea\ \xaa\xf4\x01\x00\x9c\xef\x12x\x10\x0b\x02\xc6<\x0fGD\ \xe67\x88M\xfe\xea\xf6'\xe2Q%\x02\x008\xdf%\ \xf0\x19\xe0I\xdfc\x11\x919\x15\xdd\xfe\x9eS\xb7?\ \x11\xbf*\x13\x008g\x81\x07\x81\xfd\xbe\x07\x22\x22\x17\ Q\xb7?\x91\x80T*\x00p\xe9Du\x09\x14\x09\x93\ \xba\xfd\x89\x04\xa4R\x01\x00\x9c\xdf\x0ax\x01H\xd1\x85\ A\x22\xa1P\xb7?\x91\xc0T.\x00pF\x81GP\ \x97@\x91\x10\xa8\xdb\x9fH\x80*\x19\x00\xb8\xf4\xe2I\ l+@{\x8d\x22~\xa9\xdb\x9fH\x80*\x19\x00\xc0\ E]\x02\xd5eL\xc4\x8f3\xc0\xb7Q\xb7?\x91\xe0\ T6\x00p\xc6\x80'\x80\xe7|\x0fD\xa4\x86\xcea\ \x9f\xbdL\xdd\xfeD\xc2S\xe9\x00\xc0m\x05\x9cB]\ \x02E|\xd8\x8f\xba\xfd\x89\x04\xab\xd2\x01\x00\x9c?\x1a\ \xb8\x1fx\x00+\x0e\x14\x91\xce\x1b\xc4R\xff\xea\xf6'\ \x12\xa8\xca\x07\x00N\xd1%\xf0\x19\xdf\x03\x11\xa9\x811\ \xecr.u\xfb\x13\x09X-\x02\x00\xb7\x150\x0c<\ \x84]B\x22\x22\x9dQt\xfb\xfb6:\x81#\x12\xb4\ Z\x04\x00p~+\xe00V\x0fp\xd6\xf3pD\xaa\ \xea\x18\xb6\xef\xafn\x7f\x22\x81\xabM\x00\x00\xe7\xbb\x04\ >\x0f<\x8e\xba\x04\x8a\xb4\xdbYl\x9b\xedEu\xfb\ \x13\x09_\xad\x02\x00g\x04x\x18KS\x8aH{\xa8\ \xdb\x9fH\xc9\xd4.\x00p[\x01'\x80\xfb\x00=\xa8\ D\xda\xe3\x10\xea\xf6'R*\xb5\x0b\x00\xe0\xfcV\xc0\ K\xa8K\xa0H;\x9c\xc1\xae\xf8U\xb7?\x91\x12\xa9\ e\x00\xe0\x8ca\xb7\x93\xa9C\x99H\xf3\xa6\x80\x17Q\ \xb7?\x91\xd2\xa9s\x00\xd0\x03\xac\x05\x96\xfb\x1e\x88H\ \xc9\x9d\xc5jkD\xa4D\xea\x1c\x00\xac\x00n\x02V\ \xfa\x1e\x88H\x89-\x03v\x03\xdb\x93,\xaf\xf3\xf3D\ \xa4tj\xf9\x81M\xb2\xbc\x17{h]\xed{,\x22\ \x15\xb0\x15\xf8-`\x8d\xef\x81\x88\xc8\xe2\xd52\x00\x00\ \x06\x80\x0f\xa1\xd5\x7f\xc8\xcea\xa9\xe5\xe25\x86z7\ \x84\xaa\x0f\xb8\x12\xd8\xa1,\x80Hy\xf4\xf8\x1e@\xb7\ 5\xac\xfe\xaf\xf0=\x96\x9a\x1b\xc7\xaa\xc7\x1b_#\xc0\ \xff\x87M\xf6\x13X\x10P\xe8\xc1\xea5z\xb1\x09\xe7\ \xdf\x00\xab\x1b^k\xb0\x80\xae\xb7;\xc3\x97\x196\x03\ \xff\x1e8\x88\x8e\xd7\x8a\x94B\xed\x02\x00l\x92\xb8\x05\ \xe8\xf7=\x90\x1a\x99\xc2V\xf1\xc7\xb1\x1e\x0c\x83\xc0\xbf\ `'0\x8aW\xb1\xca\x9f\x98\xaf\x8b\x9c[a\xf6\xb9\ \xd7J,\x9b\xb3\x12X\xe5\xbe\xfe<\xb0\xc9\xbd\x22T\ \xe4\xd9-\xcb\xb1\xa0\xfa\xef\x92,\xcf\xd4\x06X$|\ \xb5\x0a\x00\x92,_\x0e\x5c\xee^\xd2Y\xe3\xc0Il\ \xd2?\x0e\xfcw\xecr\x98S\xd8j\x7f\xac\x99I\xc2\ \xfd7c\xee5\xd4\xf8\xbf%Y\xde\x83\x05\x01\x91{\ m\x00\xde\x80\xadN7bA\x82R\xd4\x9d\xb3\x19\xab\ \x058\x88.\x02\x12\x09\xde%\xbe\x07\xd0MI\x96\xaf\ \xc1\xba\x95)\xfd\xdf\x19\x93\xd8\x04\xff*\xf0#,\x00\ \x18t\xbf6\xd2\xedU\xa1\x0b\xf8\xd61\x1d\x10\xbc\x1e\ \xd8\x01l\xc7\xb6\x0d\xa4\xfd\x8e\x01\x9f\x01\x9eQ\x16@\ $l\xb5\xc9\x00\xb8\xc9\xe02l\xff_\xdak\x0c8\ \x02\xbc\x06\xfc\xc0\xfd\xf3I\xd7q\xd1\x1b\xf7\xf7\x9f\x00\ N\xb8\xad\x83\x01lk`;\xf0\x1b\xc0\x1e,0P\ V\xa0}6\x00\xbf\x09\xecGY\x00\x91\xa0\xd5&\x03\ \x90d\xf9j\xe01t\xf4\xaf\x9d\x86\xb1K\x95~\x00\ \x1c\xc0V\x7fgB_\xf9\xb9`p=\xb0\x13\xf8u\ \xe0R,0P\x01a{\x1c\x06\xee\xc2\xba\x03\x06\xfd\ ^\x10\xa9\xb3Zd\x00\x5c\xe5\xff.\xecA/\xad\x1b\ \xc5\xd2\xfc\xff\x0dx\x058\x91\xc6\xd1\x98\xdf!-\x9e\ \xcb\x0c\x1cK\xb2\xfc$\x16\xc0\xfc%\xf0\xabXm\xc8\ vT8\xd8\xaaMX\x86e?:\x11 \x12\xacZ\ \x04\x00X\xd7\xbf\xf7\xa2\xca\xffV\x8dc\xb7\xbe\xfd\x05\ \xf02p\xa4L\x13\xffL\xee\xe2\x9a\xc1$\xcbs,\ \xa0\xf9\x1b\xe0?\x00o\xc1&1m\x0d4\xa7\xd8n\ \xfb+\x14\x00\x88\x04\xab\xf2[\x00\xae2|\x176i\ \xa9\xf1Os&\xb0J\xfe\xefa\xab\xe5Ci\x1cU\ \xae\xf7\xbb\xab\x13X\x83M^o\xc5\x9a\xdb\xac\xf2:\ \xa8\xf2\x1a\x03\xee\x05\xbeT\xc5\xf7\x8aH\x15\xd4!\x03\ \xd0\x07\xbc\x03M\xfe\xcd\x1a\x01^\x00\xbe\x05\xbc\x96\xc6\ \xd1\x19\xcf\xe3\xe9\x18\xb7_}:\xc9\xf2g\xb1B\xc6\ \x1f\x03o\xc3j\x05T\x1f\xb04+\xb0\xfa\x8a\x17\xb1\ \xe2P\x11\x09L\xa53\x00nE\xb7\x19\xdb\xab\x8e<\ \x0f\xa7l&\xb1#|O\x02\xdf\xc5\xd2\xfd\x93^G\ \xd4eI\x96\x0f`\xd9\xa3\xdf\xc5\x8aG7\xf8\x1dQ\ \xe9\x0cc\xc5\x80\x8f\xfa>\x11\x22\x22\x17\xabz\x06`\ 9p\x15\x9a\xfc\x97j\x1c[\xb5}\x1dx\xa1\xca\xab\ \xfe\xf9\xa4q4\x92d\xf9K\xd8\xe9\x86\xbf\x07n\xc4\ \x0aI\xab\xfe\xb9i\x97UX\x16\xa0\xf8\x1e\x8aH@\ \xaa^\xe44\x00\xbc\xdb\xf7 Jf\x08\xf8Sl\xe5\ \xf6T]'\xffB\x1aG\x93i\x1c\xe5\xc0S\xc0\xe7\ \x80g\xb1\xfdmY\x9c]\xc06]\x12$\x12\x9e\xca\ \xaed\xdc\xd1\xbf\x9d\xc06\xdfc)\x89)\xacq\xcb\ #\xc0\x93i\x1c\x9d\xf0<\x9e\xa0\xa4q4\x9ad\xf9\ +\xd8\x9d\x05\xc3\xc0\xb5\xa8\x9b\xe0bD\xc0\x9b\xb1S\ #C\xf3\xffV\x11\xe9\xa6*G\xe5}\xc0;\xd1\x99\ \xee\xc5\x98\xc4\xaa\xfc\xef\x03\xbe\xa6\xc9\x7fvn\x1f\xfb\ \x10\xf6}\xfa\x0a\xd6\xeaX\xe6W\xf4\xe0\xd8\xe2{ \ \x22r\xa1J\x16\x01\xbat\xe3V\xe0\xaf\xd11\xae\x85\ L`\x15\xef\xf7\x03\xdfK\xe3\xe8\xac\xe7\xf1\x94B\x92\ \xe5k\x81\x18x?\x96i\xaar0\xdd\xaa\x11lK\ \xe9OT\x0c(\x12\x8e\xaa>\xb4\x8a[\xff4\xf9\xcf\ \xef\x1c\xd6\xad\xed\xb3\xd8\xe5-\x9a\xfc\x17)\x8d\xa3\xd3\ X]\xc0}X7A\xb5\xbc\x9d\xdb\x00\xb6\x0d\xa0b\ \x5c\x91\x80T5\x00\xe8\x03\xae\xf3=\x88\xc0\x15\x93\xff\ =\xc0se\xee\xe8\xe7\x8b\x0b\x98\x9e\xc3\xb2'\xafz\ \x1eN\xe8v\xa0m\x00\x91\xa0T.\x00p\x9d\xff6\ b\x0f\x1c\x99\xdd\x04va\xcb\xbd\xc0KJ\xcb6/\ \x8d\xa3Q\xac\xd9\xcdC\xc0A\xcf\xc3\x09\xd9\x06`k\ \x92\xe5j\xc7-\x12\x88\xca\x05\x00X\xfa\xffw\xb0N\ dr\xb1I\xecL\xf6\x17\xb0\xc9\xbfV\xcd}:\xc1\ \x05\x01\xcfcA\xc0a\xcf\xc3\x09\xd5r\xe0\x8d\xd8-\ \x8c\x22\x12\x80*\x06\x00}Xq\x96\x5cl\x0a\xeb\xee\ \xf7\x00\x96\xf6\xd7\xca\xbfM\xdcv\xc0\xb3\xc0WQ\xd3\ \x9b\xb9\xec\x00\xb6\xa8'\x80H\x18*\xf5At\xe9\xff\ -\xd8Mnr\xb1S\xc0\x83\xc0\xd3\xda\xf3o\xbf4\ \x8e\x86\x81g\xb0^\x0a\xb9\xe7\xe1\x84h-\xf0\xcbX\ Q\xa0\x88xV\xa9\x00\x00K3\xfeGt\xf6\x7f6\ \xc3X_\xff't;[\xe7\xb8\xce\x89O\x02\x8fc\ \xdfs\x99\xd6\x8be\x01\x14\xa0\x8b\x04\xa0j\x01\xc0\x0a\ \xec.w\xb9\xd08vT\xed\xabi\x1c\xa9\x1b[\x87\ \xa5qt\x0a\xf8&vB@5\x16\x17\xda\x8em\x03\ T\xb6\x0b\xa9HYT&\x00p\xad\x7f\xb5\xba\xb8\xd8\ \x14\xd6\xe5\xef\xc14\x8e\xd4\xb9\xae{N`A\x80\xae\ \xc2\xbd\xd0j\xe0W\x81u\xbe\x07\x22Rw\x95\x09\x00\ \xb0\xb4\xff\xef\xa2{\xdbg:\x8d\xedI\xef\xf3=\x90\ :I\xe3h\x02\xeb\xb3\xf0-T\x0f\xd0h\x19\xb0\x07\ \xdd\xd1!\xe2]%\x02\x00WU\xbc\x0a\xbb\xb3]\xa6\ \x8d\x00\xdf\xc3n\xf5S\xc5\x7f\x97\xb9Z\x8b\xe7\xb0\xc2\ @\x15]N\xdb\x08\xfcz\x92\xe5k|\x0fD\xa4\xce\ *\x11\x00`\xab\xfe\xabPZ\xb1Q\xd1\xecG\xfb\xfe\ ~\xe5\xc0\xb7\xb1\xdb\xf0\xd4.\xd8,\xc7\x82\xf5=\xaa\ \x05\x10\xf1\xa7\xd4\x01@\x92\xe5\xcb\x93,\xdf\x0c\xec\x05\ n\xa6\xe4\xff\x7f\xdal\x18\xf8\x0ejL\xe3U\x1aG\ S\xd8\xcf\xe0\x9b\xc0Q\xcf\xc3\x09\xc9&\xe0&,\x08\ \xd0\xb6\x9d\x88\x07\xa5\xb9\x0d\xd0\xb5\x10]\x0f\xac\xc1\xce\ \x13\xff\x22v\xb9\xc8j\xf7\xda\x8a\xf6\xff\x0b\x13X{\ \xda[\x5cE\xbax\xe6\xd2\xdd\x1f\x07\xfe\x00\x1dS-\ \x8cb\xd7+\x1f\x04\xfe\x11\xcb\x96\x9cr\xaf\xb3\xeaR\ )\xd2Y\xc1\xa5\xdf\xdc~\xfe\x1a,\x9d\xbf\x0e\x9b\xe4\ \x7f\xc1\xfd\xda*\xa0\x1fk$\xb2\xda\xfd\xb3V\xfd\x17\ ;\x0d|S\x93\x7fP\x86\x80\xbf\xc1n\xa9\xdc\xedw\ (\xc1\xe8\x07.\xc3N\xef\x9c\x9d\xf1:\x93d\xf9?\ cA\xc1i\xe0\x8c\xfb:\xee\xb2*\x22\xd2\x22\xaf\x19\ \x80$\xcb\x07\xb0\x09~\x1d\xb6\xaao\x9c\xe8\x07\x80\x95\ \x0d\xaf>O\xc3,\x9bq\xac\xf0\xefV]\xef\x1b\x96\ $\xcbWaY\x80O\xa1,\xc0B\xceaE\xacg\ \xdd\xd7\xe2u\x06\xf8\x7f\xb0,A\x911\x18R\x91\xab\ \xc8\xd2u%\x03\x90d\xf9\x0alb\x8f\xb0\x89~\x1d\ 6\xd9\x17\x93\xfb\x00\xd3\x13\xfe\x00Z\xd5\xb7\xe2\x0c\xb6\ \xfa\xd7\xe4\x1f\x9e\xb3\xc0\xdf\x01W\xa2,\xc0B\x96c\ \xcf\x8c\x99'\x05\xc6\x99\x0e\x06\xceg\x0c\x92,\x1f\x02\ ~\x86\x05\x04g\x98\x0e\x0c\xb4\x8d 2\x87\xb6f\x00\ \x5c1\xcfZ\xf7\x8a\xb0\x0f\xef\xcf\xbb\x7f\xef\xe7\xe2\xc9\ ^{\xf6\xed5\x8e]Hs\xab\xbb\xa1N\x02\xe3\xb2\ \x00\xb7\x01\xff\x09\xddX\xd9.S\xd81\xcb\x22[0\ \xea\xfey\x18\x0b\x06\xfe\x19\xdb>(^g]\x9f\x06\ \x91Zk*\x03\xe0\x8e\xee\x14\xc5x\xc5\x8a\xfe\xdf\xb9\ \xaf\x8d\x13|\xb1_\xaf\x07]w\x0c\x01\x7f\xae\xc9?\ hg\x99\xae\x05\xb8\xcc\xefP*c\x19\xf6\xac\xe9\x9f\ \xf1\xeb\x93X0Pd\x0c\x8a\x7f.2\x06\xff\xcct\ \xc6\xe04\x961P` \xb51o\x06\xc0\x15\xe4\xad\ \xc5\x0a\xee\x1a'\xfa\xb5L\xef\xd37\xbef~\x00\xa5\ {&\x81W\x80w\xba[\xe9$P\xae\xf6\xe5#\xc0\ \x1d(8\xf6a\x12\xcb\x18\x5c\x14\x18`A\xf4\xff`\ \xba\xf0\xf0\x0cpF\xb7gJ\x15]\x02\xe7'\xfa\x0d\ \xd8\xa4^T\xe0\xff\x1c\x96\xc6\xefox5\xae\xea\xb5\ O\x1f\x96!\xe0\xfe4\x8e\xfe\xc8\xf7@daI\x96\ _\x05\xdc\x03\xec\xf2=\x169\xaf\xd8J\x98\x995\x18\ \xc5\x02\x81\xffACP\x80}\xe6F\x945\x90\xb2*\ \xb6\x00v\x03\x9f\xc1*\xed\x1bW\xf3\xba\xb7\xbb\x1c\xa6\ \xb0\x15K\xe6{ \xb2h\xc7\xb0\xf3\xef\x0a\x00\xc2\xd1\ \xb8\x950\xb3\xabhQ|8\xda\xf0:\x06|\x158\ \xd2\xc51\x8a\xb4M\x11\x00l\xc3\xba\xe9I9\x8d\x03\ \x07\xb0[\xff\xa4\x1c\xce\x00?\xc1V\x91\xab=\x8fE\ \x16\xd6\xe7^k\x1b~m3\xf0_Q\x00 %U\ \xa4\xf1Wy\x1d\x85\xb4j\x08\xf8\x0b\xa5\x22\xcb\xc3\xfd\ \xac\x8e\xb9\x97\x94\xd3r\x02l\xa6&\xb2XE\x00\xf0\ s^G!\xad(\xd2\xff\xba\xee\xb7|N`\xadp\ \xa5\x9czQ\x00 %V\x04\x00\xea\xb2W^\xa3\xc0\ A5\xfe)\xa5!\xe0\x1f\xdcW)\x9f>\xd4\xcbD\ JL\x95\xfc\xe57\x02|\xdf\xf7 d\xe9\x5c\x97\xba\ \xa3\xe8\xc6\xc6\xb2\xd2\xea_JM5\x00\xe56\x85u\ ;{\xcd\xf7@\xa4i'P\x00Pf+t\x9d\xb1\ \x94U\x11\x00\xa8\x19I9\x9d\xc3\x8a\xc8N\xfb\x1e\x88\ 4\xed,\xf0Sl+G\xca\xa7\x0fe\x02\xa4\xa4\xb4\ \x05Pn#\xc0\x0ft\xe1Iy\xb9\x9f]qy\x8d\ \x88H\xd7\x14\x01\xc0J\xaf\xa3\x90f\x8d\x02\xfb}\x0f\ BZ\xa6\x00@D\xbaN[\x00\xe55\x85e\x00t\ \x8e\xbc\xfc\x86\xd16\x8e\x88t\xd9\xb2\x19_\xa5<&\ \x80S\xba\xa4\xa4\x12F\xb0 @D\xa4k4\xf1\x97\ \xd78j\xfd[\x15\xa3\xc0\xff\xc4\xb2:\x22\x22]\xa1\ \x00\xa0\xbc\xc6\xb1\xeaq)9\xd7\x16x\x04\xfb\x99\x8a\ \x88t\x85\x02\x80\xf2R\x06\xa0Z&\xb0c\x9d\x22\x22\ ]\xa1\x00\xa0\xbc\xc6\xb1&2R\x0d\xe7\xb0\xbb\xe8E\ D\xba\xa2\x08\x00\xd4\xc9\xaa|&\xb0&2R\x0d\x93\ \xee%\x22\xd2\x15\xea\x03PNS\xc0\xb8\x1a\x00U\xca\ $\x16\xd4\x89\x88tE\x11\x00,\xf7:\x0aY\xaaI\ \x94.\xae\x9as\xa8\x06@D\xbaH5\x00\xe54\x85\ *\xc6\xabf\x0am\x01\x88H\x17)\x00(\xa7It\ yL\xd5\x9cCA\x9d\x88t\x91\x02\x80r\x9aB\xe9\ \xe2\xaa\x99@5\x00\x22\xd2E\x0a\x00\xcaK?\xbbj\ \xd1\xcfSD\xbaJ\x0f\x9drZ\x86\xddC.\xd5\xb1\ \x1c]\xca%\x22]\xa4\x00\xa0\x9cz\xd0dQ5=\ \xee%\x22\xd2\x15\x0a\x00\xca\xa9\x07\xf5n\xa8\x9a\x1e\xd4\ \x90KD\xbaH\x01@9\xf5\xa0-\x80\xaaY\x8e\xfa\ q\x88H\x17)\x00(\xaf\xde$\xcb\xfb}\x0fB\xda\ f\x19\xda\x02\x10\x91.R\x00P^=\xc0*\xdf\x83\ \x90\xb6\xe9E\x19\x00\x11\xe9\x22\x05\x00\xe5\xd5\x07l\xf4\ =\x08i\x1b\x05\x00\x22\xd2UE\x00\xa0\x06$\xe5\xa3\ \x00\xa0Z\xfa\xd0\xc9\x0e\x11\xe9\xa2\x22\x00\xd0\xb5\xb2\xe5\ \xb3\x02x\xbd\xefAH\xeb\x92,\xef\xc3Nu(\x03\ \x22]S\x04\x00j+[>\xcbQ\x06\xa0*\x06\ \x80\x7f\xeb{\x10\x22R/\xaa\x01(\xaf^`u\x92\ \xe5k|\x0fDZ6\x00\xac\xf6=\x08\x11\xa9\x17\x05\ \x00\xe5\xd6\x8f\xb2\x00U\xb0\x1aX\xe7{\x10\x22R/\ \x0a\x00\xca\xad\x1f\xd8\xe5{\x10\xd2\xb25(\x00\x10\x91\ .S\x00Pn\x03\xc0o$Y\xae\x062%\x95d\ y/\xb0\xd6\xbd\xa4|\xa6|\x0f@\xa4YE\x000\ \xe4u\x14\xd2\xac\xe5\xc0z\xb4\x0dPf\xeb\x807\xa0\ {\x00\xcaj\x14\x15QKI\x15\x01\xc0\xb8\xd7QH\ +V\x01{|\x0fB\x9a\xb6\x09\xd8\xe1{\x10\xd2\xb4\ \x894\x8e\x94\x05\x90R*\x02\x801\xaf\xa3\x90V\x0c\ \x00\xbf\xe1{\x10\xb2tI\x96/\x07\xb6\x00\x9b}\x8f\ E\x9ar\x0em\x01H\x89\x15\x01\xc01\xaf\xa3\x90V\ \xf4\x01[\x92,\xd7\x1er\xf9D\xc0\xaf\xa0\x9b\x1d\xcb\ \xea40\xe2{\x10\x22\xcd*\x02\x80\xbf\xf5:\x0ai\ \xc52\xac\x8a\xfcJ\xdf\x03\x91%\xdb\x08l\xf7=\x08\ i\xda\x11T?%%V\x04\x00\xfb\x80\xff\x02\xbc\x02\ \x9cDi\xad\xb2Y\x0d\xfc\xaeK)K\x09$Y\xbe\ \x02\xd8\x8a\x0a8\xcb\xe6,p\x08x\x1ax\x04{^\ \x8a\x94R\x0f@\x1aG#I\x96\xdf\x0f|\x0bKG\ \xae\xc2\xaa\x93_\x87U\x99G\xc0\x06l\xbfY\xc2\xb3\ \x1c\x9bL\xf6\x00/y\x1e\x8b,\xcez\xe0\x8d(\xfd\ \x1f\xaa\x09`\x188\x01\xe4\xd8D\xffS\xe0\x0cV\xf9\ ?\x02\x9cN\xe3H\xf5SRZ\xe7\xcf\x8f\xa7qt\ \x1a\xdb\xd3\x22\xc9\xf2e\xd8e3\xfd\xeek\xf1\xcf+\ \xb1\xaa\xe5_\xc0\x02\x82\xf5X\xa0\xa0\x95\xa7\x7fk\x81\ \xb7\xa1\x00 x\xee\xf3\xb5\x19\xd8\xe9{,\x02\xd8\xaa\ \xfe\x140\xe8^\xff\xe8\xbe\x8e`\x93\xfd\x98\xfb:\x8a\ \xaa\xfe\xa5B.Y\xcaov\x0dg\x06\x98\x0e\x0a\x8a\ \xd7:,K\xf0\x0b\xee\xebz\x14\x18t\xdb\x14p\x00\ \xb8)\x8d#\x15u\x06,\xc9\xf2\xf5\xc0\xa7\x81\x0f\xa2\ \xf3\xff\xdd4\x8eM\xf4'\xb1U\xfd?\xba\xafCL\ O\xf4\xc5d?\x9e\xc6\xd1\xa4\xa7q\x8at\xc5\x92:\ \xc8\xb9\x0f\xc4\xb0{\x9d\xe7\xae3]\xc1\xf4\x9d\xe6\x8d\ \x81\xc1/\xba\xaf\x1b\xdc\xd7u\xe8\xa1\xd7\x09\xcb\xb0\xe0\ \xebjt\xaa#Xn\xf5\xbf\x1b\xd8\x8b>\x07\x9d2\ \x81\xa5\xea\x07\xdd\xab\x98\xec\xcf`\xab\xfa\xc6\x89~,\ \x8d\xa3\x09/\xa3\x14\xf1lI\x19\x80\xa5j\x08\x0c\x1a\ _\xfdX\x86\xe0\xe7\xb9p\x1bA\xbd\xd0[7\x89\x15\ r\xbe\xd7m\xe9H`\x92,\xdf\x08\xdc\x0e\xbc\x8f%\ \x06\xe0r\x91\x09l\xf5^\xac\xe8O\x01\xff\xe4\xbe\x16\ )\xfb\xb1\x86\xd79\xa5\xefE\xa6u\xf4\x01\x94\xc6\xd1\ 8\x96v;\x7fT\xc6\xad\x80f\x0b\x0cVb\xc1\xc0\ /b\x81\xc1F\xf7\xef\xdaFX\xbc\x1e\xac\xb1\xcc\xbb\ \x80/z\x1e\x8b\xcc\xe0\xb6\xd0v\x03W\xa1\xc9\x7f)\ \x8a\x82\xbc\x9c\xe9\x15}1\xd1\x9fez\x82\x1f/\xbe\ j\xa2\x17YXG3\x00K\xe1\x02\x83\x99E\x87\xfd\ XZ\xfbuX\xf1\xe1F\xf7R\xe5\xf4\xdc&\x81\xd7\ \x80[\xd28:\xea{02-\xc9\xf2-\xc0\x1dX\ \x80\xa6\x00`vg\x99\x9e\xe8O\x02?s\xff>\xcc\ \x85\x13\xfd(\xb6\xa2\xd7>\xbdH\x93\x82\x09\x00\xe6\xe2\ \xb6\x11\xfa\x1b^\x03L\x07\x05\x9b\x1b^2\xed,\xf0\ 5\xe0\x0e\xad\x84\xc2\xe0V\xff\xef\x01>\x8bn\xfe+\ La\x93\xfcA\xacn\xe5\xa7Lw\xd7\xbb`U\xaf\ \x89^\xa4\xfd\x82_\x854l#\x9c)~mFP\ \xb0\x06\xb8\x19H\xbc\x0c0L\x03Xg\xc0\xbf\xc0\x9a\ <\x89\x7f[\x81\xdf\xc1\xde\xafb\x99\xaa\xa7\x81\xc7\xb0\ @\xc7\xecD\xba,\xf8\x0c\xc0B\xdc\xd6\xc16\xe0\ \xcf\xb0\x9a\x011\xa3\xc0S\xc0mi\x1c\xe9\xbaR\x8f\ \x92,_\x03\xdc\x0a\xfc>j\xa6Ux\x15\xcb\x86\xbc\ \xa8*|\x11?\x96-\xfc[\xc2\xe6V\x0b\xc7\x81\xd4\ \xf7X\x02\xb3\x02\xb8\x1c\xb8\xd6\xf38j\xcd\xb5g\xbe\ \x12\xb8\x01M\xfe\x85\x09\xe0E\xe0UM\xfe\x22\xfe\x94\ >\x00p\xceam\x8cu\xf4mZ\xd1\x17\xe0\xe6$\ \xcbu\xe1\x8c?;\x81\x9bPv\xaa\xd1\x11\xe0\x87i\ \x1c\xe9&=\x11\x8f*\x11\x00\xb8,\xc0i \xf3=\ \x96\xc0\xf4b\x13\xd0mI\x96k\xf5\xd9eI\x96o\ \x00\xde\x8d\xdd\xd1\x10|\xbdM\x17\xbd\x06\x1c\xf6=\x08\ \x91\xba\xabD\x00\xe0\x8ccY\x00\xa5\x14/\xd4\x8f\x9d\ ;\xff\xa0\xab\x97\x90.H\xb2\xbc\x1fx\x0b\xb6\x05\xa3\ c\xab\xd3F\x80\x7f\xa0\xa1\xa8WD\xfc\xa8\xcc\x84\xe0\ \x8e\x09\x1d\xc3A\x90\xbd\x88\x00\x00\x12.IDAT\ \x8a\x8b\xe4Bk\xb0\x95\xe8\x95\xbe\x07R\x07.\xd0\xba\ \x14K\xfd\xaf\xf6<\x9c\xd0\x1c\x03N\xe8X\x9f\x88\x7f\ \x95\x09\x00\x9c1\xe0\xcf}\x0f\x22@E\x87\xc0\x8f\xba\ V\xb4\xd2!n\xf2\xdf\x05\xdc\x82\x1d\xfd\xab\xdag\xac\ U\x87\xb1\xa2]\x11\xf1\xacj\x0f\xa7sXu\xf1\xa8\ \xef\x81\x04h9v*\xe0\xce$\xcbu\xefB\xe7l\ \x07>\x01\x5c\x81.\xfb\x99i\x14\xa5\xffE\x82Q\xa9\ \x00\xa0\xa1\x18P\xcdofW\xecK\xdf\x9ed\xf9*\ \xdf\x83\xa9\x9a$\xcb\xb7\x02\xb7a7\xfd\xad\xf0<\x9c\ \x10\x1d\x05\x8e\xe9\xe8\x9fH\x18*\x15\x008\xe3\xc0w\ }\x0f\x22`+\xb1\xc2\xb4O\xb8B5i\x83$\xcb\ 7ai\xffk\xb0@K.\xa6\xf4\xbfH@\xaa\x18\ \x00L`W\xe2*\xcd8\xbbeXQ\xe0\x0d\xc0\x87\ \x93,W\x9a\xbaE\xee\xb8\xdf-\xd8%?:n9\ ;\xa5\xffE\x02S\xb9\x00\xc0m\x03\x0c\x03\xcf\xfb\x1e\ K\xc0\x96\x01\xeb\xb0;\x14>\xa2 \xa0yI\x96\xaf\ \xc5.\xf9y\x0f\xa0m\x95\xb9\x1d\x06\x8e(\xfd/\x12\ \x8e\xca\x05\x00\xce8\xf0m\xdf\x83\x08\x5c\x0f\xb0\x01\xdb\ \xb3\xfeC5\x0aZ:\x97\xf6\xff$\xb6\xfa\xd7q\xbf\ \xb9Ma\xcd\x7ft=\xb5H@*\x19\x00\xb8U\xc6\ \x11\xe0\x90\xef\xb1\x04\xae\x07kQ{\x0bpO\x92\xe5\ \x91\xdf\xe1\x94C\x92\xe5\xcb\x92,\xdf\x05\xdc\x05\xbc\x0f\ ]\xef\xbb\x90\x93\xc0\x8f\xb1\xcc\x9c\x88\x04\xa2\x92\x01\x80\ 3\x82\x8a\x01\x17\xa3\xb1&\xe0\x9e$\xcb\xb7x\x1eO\ \xd0\xdc\xe5>{\xb1\x9b\xec\xde\x82\x15U\xca\xfc\x0e\x00\ \x87u\xcd\xafHX\xaa\x1c\x00\x8ccw\x03\xe8\xc2\x91\ \x85-\xc3&\xb2k\x80{\x93,\xbf\xc2\xf3x\x82\xe4\ \xb6In\xc0&\xffKQ\xb5\xffb\x8c\x02?\xc4\xb2\ \x00\x22\x12\x90K|\x0f\xa0\x93\x92,_\x09<\x04\x5c\ \xef{,%2\x8em\x9f|\x1dx<\x8d#5U\ \x02\x5c\xf3\xa4\x04+\x9c\x8c\xd0\xe5>\x8b\xf5\x0apW\ \x1aG/\xfb\x1e\x88\x88\x5c\xa8\xea\x0f\xb11\xe0\x9b\xc0\ \xdb\xa9v\xb6\xa3\x9d\xfa\x80\x1dXQ\xdb\xaf$Y\xfe\ `\x1aG\xb5\xbd\xb9\xcd\xa5\xfcw\x01\x1f\xc2\xeeRX\ \x8d\xdeK\x8b5\x89\xdd\xcdQ\xdb\xf7\x8fH\xc8*\x9d\ \x01\x80\xf3+\xb7ocW\xb2\xca\xe2Ma\x01\xd4\x01\ \xe0\x11\xe0\xe9:\x1d\xe1r=\xfd7`)\xff\xb7\x01\ \x1bQw\xbf\xa5:\x0a|\x06xV\xfb\xff\x22\xe1\xa9\ \xc3J\xe6,\xf0\x0d\xdf\x83(\xa1e\xd8\x1e\xf7\xa5X\ \xb5\xfb\xbdu)\x10t{\xfd\xd7\x03\x0f\x00\x1f\x05\xb6\ \xa1\xc9\xbf\x19\xaf\x02\x075\xf9\x8b\x84\xa9\xea[\x000\ }A\xd0 v\xe4M\x96\xa6\x17[\xfd\xbe\x0f\xd8\x95\ d\xf9\x9f\x03O\xa6q\x94{\x1dU\x07$Y\xde\x83\ ]\xe6s3p\x15v\xbco\xb9\xd7A\x95W\x0e|\ \x1f8\xe5{ \x222\xbb\xcao\x01\x00\xb8\x9e\xf7w\ \x00\x7f\xe8{,%7\x89eT\x0ec\xdb*\xcf\xa6\ qT\xfa\xb3\xddn\xe2\xdf\x04\xbc\x13\xb8\xda\xfd\xb3*\ \xfc[\xf3$pO\x1aGj\xfe#\x12\xa8:d\x00\ \xc0\xf6\xb2\xbf\x85\xadb\xd7\xf8\x1dJ\xa9\xf5`Ep\ \x97\x01\x9b\x81\xb7&Y\xfeM\xe0\x854\x8e\xcez\x1d\ Y\x13\x92,\xef\xc3V\xfc\xd7aW%G\xd8q\xc8\ :l\x8du\xd20\xf0w\xc0\x09\xdf\x03\x11\x91\xb9\xd5\ \x22\x03\x00\xe7\xf7u\xef\x01>\xe6{,\x15r\x0e\xbb\ \xdc\xe5\x04\xf0\xd7\xd8\xfd\x0b\xc17|q\xef\x85K\xb1\ \x89\x7f\x17\x96\xea\xefG\x13\x7f\xbbd\xc0\xddi\x1c\x1d\ \xf4=\x10\x11\x99[]2\x00`Y\x80o`\x97\xb6\ \xa8\xef}{,\xc7\xea*\xd6a\x85r\xef\x04\x0e$\ Y\xfe\x17\xc0+i\x1c\x05\xd3\x84\xc9\xa5\xf9#\xec(\ \xdfoc\xe3]\x8d\x8a\xfb\xdam\x04[\xfd\x1f\xf3=\ \x10\x11\x99_m2\x00p\xbe1\xd0\xe7\x80\xdf\xf3=\ \x96\x8a\x9a\xc2\x1a\x09\x0da\x9d\xdf\x0e\x00?\x02\x0e\x02\ y\xb73\x03n\xa5\xbf\x0d[\xe5\xbf\x19\xdb\xdb_\xe5\ ^*\xee\xeb\x8c\x17\xb0\xc6?\xaf\xf9\x1e\x88\x88\xcc\xaf\ N\x19\x00\xb0\xb6\xa4\x8f\x001\xaa\x05\xe8\x84e\xd8\x8a\ z\x05\xb6\xda\xde\x01\xbc\x0b+\x1c\x1cL\xb2\xfc\x87X\ 0p$\x8d\xa3\xb6\xdf\x0b\xef\x9a\xf6\xac\x07v\x02\xbf\ \xc6\xf4*\x7f\x00K\xf1k\xd2\xef\xac\x11\xe0\xafP\xe3\ \x1f\x91R\xa8U\x06\x00\xce\xaf\x0a\xef\x04>\xe5{,\ 52\x05L`\x01X\xf1\x1a\xc6\x8ef\xfe\x13VC\ 0\x08\x9c\x06\xce\xa6qtn\xae?\xc8\xa5\xf2\xfb\xb0\ \x89}=\x16h\xfc\x22\xd6\xb4g\x1d\xd3\x93\xfd\x00\x16\ \x88h_\xbf{\xb4\xfa\x17)\x91\xbae\x00\xc0&\x9f\ o`\x8d^t\xfdmw,\xc3V\xdf\xcb\xb1\x89\x1b\ \xecH\xe19l\xcb`\xdc\xfd\xf3\x040\x91d\xf9\xcc\ `\xa1\x07\xab\xce\xef\xc3&\xf6eX\x7f\x82\xe2\xcf\xec\ s\xaf^4\xe1\xfb\xa2\xd5\xbfH\xc9\xd4.\x03\x00\xe7\ \xfb\x02\xfc\x01p\xb7\xef\xb1\xc8\xac\xa6\xb0\x00\xa1\xf8\x0a\ \xd3\x93{\x1d\x83\xd62\xd0\xea_\xa4d\xea\xbaZ\x1a\ \x03\x9e\x02\x8e\xfb\x1e\x88\xcc\xaaq\x85_\xd4\x14\xf4\xa2\ \xc9?TZ\xfd\x8b\x94P-\x03\x00W\x8d~\x0a\xbb\ *XDZ\xb3\x1f\xd8\x97\xc6\xd1\xb8\xef\x81\x88\xc8\xe2\ \xd52\x00p\xc6\x81\xe7P\xb72\x91V\x1dE\x9f#\ \x91\xd2\xa9s\x00P4\x86\xd1q@\x91\xd6\x5c\x8a]\ \x14U\xe7\xe7\x89H\xe9\xd4\xf2\x03\xeb\x1eTk\xb1\x22\ @u\x82\x13i\xcdV\xe0F\xa0\x16\xd7E\x8bTE\ -\x03\x00\xec\x9c\xf8'\xb1\x861\x22\xd2\x9a\xe5\xd8-\ \x8a\xd7&Y\xbe\xca\xf7`Ddqj\x17\x00\xb8n\ qWcw\x02\xf4z\x1e\x8eHU\x0c`Y\x80\xab\ \x5c\xb3&\x11\x09\x5c\xad\x02\x00\x97\xfa\xdf\x0c|\x06]\ \x08$\xd2n\x1b\x80\xf7\x03\xbb}\x0fDD\x16V\xab\ \x00\x00\xbb\x04\xe6n\xecR\x18\x11i\xaf\x1e`\x0f\xf0\ \xce$\xcb\xd7{\x1e\x8b\x88,\xa06\x01@\x92\xe5+\ \x80\x0fb\xd7\xc1\xd6\xe6\xff\xb7H\x97\xf5\x01o\x07b\ \xf7\x99\x13\x91@\xd5b\x22L\xb2\xbc\x17KK\xde\x86\ =\xa0D\xa4sVc[\x01W\xe8h\xa0H\xb8*\ \xff\xe1l8\xf2w\x0f:\xf3/\xd2\x0d\xcb\xb0#\x81\ 7bW2\x8bH\x80*\x1f\x00`G\xfen\xc7\xee\ \xa6\x17\x91\xee\xe8\x05\xf6\x02\xd7%Y\xbez\xa1\xdf,\ \x22\xddW\xe9\x00\xc0\x1d\xf9\x8b\x81\x1b\xd0\x91?\x91n\ \xeb\xc7\x8e\xdb^\xed\xb6\xe1D$ \x95\x0d\x00\x5c\xea\ \x7f\x13p\x17\xf6 \x12\x91\xee\x8b\x80\x9b\xb0\xd3\x01\x22\ \x12\x90\xca\x06\x00\xc0J\xe0\xb3\xc0z\xcf\xe3\x10\xa9\xb3\ eX\x01\xee\x8dI\x96\xeb\xf8\xadH@*\x19\x00\xb8\ \xe3G\xbf\x87\x8e\xfc\x89\x84`9p\x0dv4P\xd9\ 8\x91@Tnrl8\xf2\xf7q\xec\xc1#\x22\xfe\ \xad\xc4\xb6\x02t4P$\x10\x95\xfa 6\x1c\xf9\xbb\ \x17;\x8b,\x22a(\xdap\xdf\x84N\xe4\x88\x04\xa1\ R\x01\x00v\xb5\xef\x9d\xe8\xec\xb1H\x88z\x80\xab\xb0\ V\xc1k}\x0fF\xa4\xee*\x13\x00\xb8#\x7fo\x07\ \xde\x85=hD$<}\xd8gt\xaf\xfb\xcc\x8a\x88\ '\x95\x08\x00f\xdc\xf2\xa7\xfe\xe3\x22a[\x0b\xdc\x0c\ \x5c\xea{ \x22uV\x89\x00\x00+0\xfa\x1cv\xe6\ XD\xc2\xb6\x0c\xd8\x89\x1d\x0d\xdc\xec{0\x22uU\ \xfa\x00 \xc9\xf2>\xe0#\xc0\xe5T\xe0\xff\x8fHM\ \xf4bG\x03\xafI\xb2|\xa5\xef\xc1\x88\xd4Q\xa9'\ \xcc$\xcb{\xb04\xe2m\xe8\xc8\x9fH\xd9\x0c\x00\xef\ \x05.\xd7\xd1@\x91\xee+\xed\x87n\xc6\x91\xbfU\x9e\ \x87#\x22\xcd\xd9\x84\x8e\x06\x8axQ\xda\x00\x00+\xf6\ \xbb\x0b\xd8\xea{ \x22\xd2\xb4\x1e\xacc\xe7;t4\ P\xa4\xbbJ\x19\x004\x1c\xf9\xbb\x1e\x1d\xf9\x13)\xbb\ \xe2h\xe0U:\x1a(\xd2=\xa5\x0b\x00\x5c\xea\x7f\x0b\ \xb6\xfa\xd7\x91?\x91jX\x87\x1d\x0d\xdc\xed{ \x22\ uQ\xba\x00\x00+\x1c\xfa<\xf6\xc0\x10\x91jX\x06\ \xecB\xb7\x06\x8atM\xa9\x02\x00w\xe4\xef\x13X\xe5\ \x7f\xa9\xc6.\x22\x0b\xea\x05\xae\x05\xae\xd6\xad\x81\x22\x9d\ W\x9aI\xd4\x1d\xf9\xbb\x1c\xf8\x18\xf6\xa0\x10\x91\xea\x19\ \xc0\xb6\x02t4P\xa4\xc3J\xf1\x01s\x0f\x82uX\ \xb7\xbf\x01\xcf\xc3\x11\x91\xce)\xdaz\xbf\x17]\xea%\ \xd2Q\xa5\x08\x00\xb0*\xe1\xbb\xb1\xe2?\x11\xa9\xb6\x1e\ `/p]\x92\xe5k|\x0fF\xa4\xaa\x82\x0f\x00\x92\ ,\xef\x05n\xc0\x8e\xfd\xe9\xc8\x9fH=\xac\x00\x12\xec\ h\xa0\xb6\xfcD: \xe8\x00\xc0\xa5\xfe\xb7b\xb7\xfc\ \xf5y\x1e\x8e\x88t\xd7:\xe0\xfd\xd8\xe9\x00\x11i\xb3\ \xa0\x03\x00\xa6\x8f\xfc\xa9C\x98H\xfd,\x03\xf6`]\ \x02u\xd3\xa7H\x9b\x05\x1b\x00\xb8\x8e`:\xf2'R\ o\xbdX\x97\xc0\xab\xdd1`\x11i\x93 'Vw\ \xe4\xefJ\xe0\xf7\xd1\x91?\x91\xba[\x85]\x18\xa4.\ \x81\x22m\x14\x5c\x00\xd0p\xe4\xef^@\xcd@Dd\ \x19v[\xe0;\x93,\xdf\xe8{0\x22U\x11\x5c\x00\ \x80\x15\xfb}\x16;\x0b,\x22\x02\x96\x09|;\xb07\ \xc9r\xdd\x01\x22\xd2\x06A\x05\x00\xee\xb8\xcf{\xb0v\ \xa0A\x8dMD\xbc[\x89\x9d\x0a\xd8\xe3{ \x22U\ \x10\xcc$\xebR\xff\xdb\xb0[\xfet%\xa8\x88\xccf\ \x1b\xd6 H[\x01\x22-\x0a&\x00\xc0\xc6\xb2\x1e+\ \xf8\x11\x11\x99M\x0fv2H7\x06\x8a\xb4(\x98\x00\ \x8d\xa3I\xe0E\xe0v`\xd2\xf3pB2\x06\xec\ \x03^\xf3=\x10\xe9\x9a\x09\xe0U\xe0\x0e\xe0+\xc0Y\ \xbf\xc3\x09\xca\x04\xf0=\xe0\x90\xef\x81\x88\x94]0\x01\ \x00@\x1aG#\xc0\xa3(\x08\x00\x98\x02r\xe0N\xe0\ :\xe0\xdd\xd8\xfe\xe7>\xf7\xbfI\xf5L\x02\x07\x80[\ \xb1\x9f\xf7\x97\xb0-\xb1O\xa2\x09\x0fl\xf2\xff\x1a\xf0\ 0p\xc6\xf3XDJ\xef\x12\xdf\x03\x98M\x92\xe5\x03\ \xc0\x07\xb0\xa3\x80u\xec\xff\x7f\x0ex\x05\xb8\x078\x98\ \xc6\xd1\xb8\xab\x91\xe8\xc5\xb6Hv\x03\xb7\x00W\x10X\ \x10'M\x99\x04\x8e\x00\x8f\x00\xcfa\x93\xdb\xb94\x8e\ \xa6\x00\x5c\x03\x9c\xed\xc0G\x81k\xa8g[\xec) \ \xc5:\x83\x1e+\xbe7\x22\xd2\xbc \x03\x00\xa8u\x10\ 0\x0c|\x19\xf8*0\xe4\xb6F.\xe0\xba$\xae\xc4\ \x0a\xa2n\xc5nNS\xc3\xa4\xf2\x99\x02\x8e\x03\x8f\x01\ \xcf\x00\xa7i\x98\xf8\x1b\xb9\xe6Xk\xb1\xaex\xb7b\ \xf52u\xf24v\x1d\xf8\xe1\xd9>\x13\x22\xb2t\xc1\ \x06\x00P\xbb `\x12K\xf3~\x06\xd8\x97\xc6\xd1\xd8\ B\xff\x81;6Y\x04\x027Q\xdf\xd5a\xd9L\x01\ '\x80\xaf\x03\xcfb[=\xe3\x0b\xadj]\x16\xa8\x0f\ +\x82\xfb$p9\xd5\xff\x5c\x80eE>\x07\xbc\xa6\ \xc9_\xa4}\x82\x0e\x00\xa06A\xc0(\xf0\x04\x96\xde\ <\x95\xc6\xd1\xc4R\xfec\x17\x08\xf4\x03[\xb0:\x81\ k\xb0\x8b\x94$,\x93\xd8\x8a\xff\x1b\xf0\xff\xb7w7\ !\x92]e\x1c\xc6\x9f\x85\xccB\x86\x10\x06\x17\x83H\ -\xc4\x95d\x15D\xc4\x95\xe0\x07(\xa4\x82(\xba\x88\ \xb6\x1f!\x88\x88\x84A]H\x90ADDM\xc0\x95\ B\x02A\x8aID\xe2\xaa\x1d?\x08\xb3\x10\x91A\x82\ \x840\x88\x0c:\xc4\xd8Nb3\x14MQ\x14E1\ 4\x8d\x8b\xf7V\xa6\x12z\xa6\xabo\xdd\xba\xe7\x9es\ \x9f\xdf.\x90\xa4\xcfLU\xdf\xf7\x7f\xcf9\xef9\xec\ \xb2f\xe1\x7f\xbb\xea\xf3~/\xf0(\xf0e\xca\xee\x9c\ Y\x16\xff\x97N\xfb{!\xe9\xde:\x1f\x00\xa0\xe8\x10\ \xb0\x9c\x02\xfe\x01\xf1\xa0\x9bn\xb2\xb6YM\x13\xdfG\ L\x0f\x7f\x9e\x98.\xf6\x16\xb5\xf4\xe6\xc0\xcbD\xe1\xbf\ \x02\xdc\xa2F\xe1_U\xcd\x06\xdc\x07|\x8a\x98\x0dx\ \xb0\x81qv\xcd\x1f\x89SA-\xfe\xd2\x16d\x11\x00\ \xa0\xc8\x100'\x8a\xfeE\xe0\xd5\xd1p\xb0h\xea\x7f\ \x5c\x05\x81w\x12k\xc6C\x22\x0c\x94X \xban\x0c\ \xfc\x09x\x8eh\xe3\x9c\x00\xb7\x9b\xdc\xc0V\xed\x07y\ \x80\xd8 \xf8Y\xa0\x94cr-\xfe\xd2\x96e\x13\x00\ \xa0\x98\x10pDl\xf6\xfa)\xb1\xaby\xa3\xb7\xfe{\ \xa9\xde\x12\x97\x1b\x06?\x00<\x02|\x02/Y\xda\xa6\ C\xe0\x1f\xc0\x0bD\x11\xbbA\xbc\xedo\xad\x88U\x81\ \xef]\xc0\xe7\x80o\x02\xb9\x9f\x92g\xf1\x97Z\x90U\ \x00\x80\xecC\xc0\x82\xe8\xe3\xbf\x08\xbc2\x1a\x0e\xe6m\ \xfd\xe0j\xdd\xf8,\xb1<\xf00q\xdf\xc2\x03m\xfd\ \xfc\x1eX\xbe\xed\xff\x9a;o\xfb\x8b67\xadU\xed\ \x82\x1f\x02.\x10A/\xc7\xce\x90\xab\xc4\x92\xd8\x157\ \xfcI\xdb\x95]\x00\x80lC\xc0\x01q\xb0\xcb/\x80\ q\xaa\x87\xdb\xcaN\xf2s\xc0\x07\x89\xe5\x81\x8f\xe1\xa6\ \xc1:\xe6D\xe7\xc6\x0b\xc4\xda\xfeM\xb6\xfc\xb6\x7f\x92\ *\xe8\xbd\x87\xd8 \xf8U\xe0|\xaa\xb1\xd4p\x95x\ \xf3\xbf\xe2\x9b\xbf\xb4}Y\x06\x00\xc8*\x04\x1c\x02\xd7\ \x88c]\xaf\xae\xd3\xde\xd7\x96\x95Y\x81w\x13\x9b\xc9\ >M\xec\x15\xc8\xf1\xcd\xb1-\x0bb\xe3\xe6e\xe0\x0f\ \xc4t\xff\x82\xbb\xf4\xef\xa7P\x85\xbc\xb3\xc4AQ\xdf\ \x22n\xcf\xeb\xfa\x81Q\x16\x7f\xa9e\xd9\x06\x00\xc8\x22\ \x04,\xdb\xfb~\x0c\xbc\xd1\xd5\x07\xdb\xca^\x81\xb3\xc4\ \xdb\xe3G\x80\x8f\x12\xd3\xc9\xe7\xd2\x8d\xac3\x0e\x89\xb5\ \xfc\xcb\xc0\xef\x88\xa2?\xa7\xe5)\xfe\xd3\xaa\x02\xde\xfb\ \x88\x83\x83\xbe@wgy,\xfeR\x02Y\x07\x00\xe8\ l\x08X\x1e\xf4r\x91\xd8\xe9?\xeb\xca\xdb\xe1IV\ \xc2\xc0\x19\xa2`<\x08|\x9c8|\xe6\xfdt\xffM\ \xb2)G\xc0k\xc4\xe7\xf7[b\x16gF\xc7\x8b\xfe\ \xdbU\x9f\xe7\xfd\xc4\x0c\xcf\x05\xba\xd7\x0db\xf1\x97\x12\ \xc9>\x00@\xe7B\xc0\x9c\xd8\xc5\xfc=\xe0F\xce\x0f\ \xb5\xaax\xbc\x83\x08\x04\xe7\x81\xc7\x80o'\x1dT;\ &\xc0/\x81\xa7H\xb0\x99o\x1bV\xda\x05\x1f'6\ \x80v\xe1\xc4\xc8\xbfrg\xc3_\xb6\xbf'R\xae\x8a\ \x08\x00\xd0\x99\x10\xb0O\x9cZ\xb6\xd5\xf6\xbe\x14vv\ \xf7\xce\x12\x07\x0b=\x93z,-\xb8\x0e\xfch4\x1c\ \x8cR\x0f\xa4IU\xbb\xe09\xe2sL\xdd.h\xf1\ \x97\x12+f:7\xf1U\xc2\xb7\x89\x16\xb0\xcf\x00O\ \x8f\x86\x83II\xc5\x1f\xa0\xda\xbc\xb8G\xfcYK7\ %\xcej(\xcah88\x1c\x0d\x07\xb7\x80\xa7\x89\xdb\ $\x7fO\x9a\xcf\xd3\xe2/u@1\x01\x00\x92\x85\x80\ \x09\xf0$\xd1N\xf7R\x93'\xfauP\x91\x85\xf1\x18\ c\x22\xec\x14\xa9\xfa\x8e\xfe\x998=\xf0'\xc4\xccU\ [,\xfeRG\x14\x15\x00\xa0\xd5\x10\xb0\xbc\xbd\xef\x8b\ \xc0\x0fG\xc3\xc1\xb1W\xf7\x16fN\xc1\x85q\xc5\x01\ \xd1\xd3_\xac\xea\xbb\xbaG,\x99}\x83\xd8\x8c\xb7\xed\ Y+\x8b\xbf\xd4!\xc5\x05\x00h%\x04\xcc\x80KD\ \xdf\xfc\x8bm\x9e\xe8\x97\xd8\x8c\xd8\x19_\xb2\x19\xd1\xb2\ Y\xfcg:\x1a\x0e\x8e\xaa\xa5\x9d\xcb\xc4\x06\xcf\x9f\x13\ \xe1g\x1b,\xfeR\xc7\x14\x19\x00`k!\xe0\x88x\ kz\x9c\xd8D\xb5\xd7\xb3\x87\xd9r\x1f@\xc9\x0e\x80\ \xd7S\x0f\xa2M\xd5w\xf8:\xf0\x04\xf1\xbd~\xb9\xe1\ \x1fa\xf1\x97:\xa8\xd8\x00\x00\x8d\x87\x80\x05\xd1\xde\xf7\ I\xe0\xd2h8\xc8\xa6\xb7\xbfAs\xe0?\xa9\x07\xb1\ e\x13\x0a\x9f\xfe?N5\x1b0\x05~C\xcc\x06\x5c\ \x22>\xefMY\xfc\xa5\x8e*:\x00@c!`\x0c\ |\x9f\xb8M\xefz_\x1fd=\xe9\x04(~\xfd\xff\ ^\xaa\xef\xf6+\xc4\x11\xc2\xdf%\x0e\xb4\xaa\xcb\xe2/\ uX\xf1\x01\x006\x0a\x01\x87\xc0\xdf\x88\xf6\xbe\x9f\x95\ \xd8\xdeW\xc3\x8c\xb2;\x01z9\x03\xb0\xaa\x9a\x0dX\ \xb6\x0b>F\xbdv\xc1e\xf1\x7f\xd1\xe2/uS/\ \x02\x00\xd4\x0a\x013\xe2\xf6\xbe\x87\x88K|Jn\xef\ ;\x8d\x92\xf7\x01\x1c\x12-qm\xb6\xc5uV\xf5\x9d\ \xff\x0bq\x97\xc0\x93\xc0\xad5\xff\xd3\xd5\xe2_zg\ \x8c\x94\xad\xde\x04\x00X;\x04\x1c\x11\xb7\xbd}\x09x\ b4\x1c\xec\xfb\x10{\x8b\x92\x03\xc0\x14\xf8\x9f\xb3<\ wT\xdf\xfd\x9b\xc4y\xfd_'\x8a\xfb\xbd\xfe~,\ \xfeR&z\x15\x00\xe0\xc4\x10\xb0 6A=\x04\xec\ \xf6\xa1\x15\xac\x86\x92\xcf\x02\x18S~\x9b\xe3\xa9UK\ \x02s`\x17\xf8\x0a\xb1409\xe6_\xb5\xf8K\x19\ \xe9]\x00\x80\xbb\x86\x80}\xe0;\xc0\xa3\xc4%>>\ \xc0\x8e7\x03\xfe\x9bz\x10[2\xc1\xe9\xff\xbb\xaa~\ '\xfeIl\x0e\xbc@\xdc\x90\xb8d\xf1\x972\x93\xfa\ \xe6\xbcdF\xc3\xc1dgw\xefYbs\xd3\xc3\xc4\ C\xed\x9a\x1b\x96N\xb4\x9c\x018\xa2\xbc\x00\xd9\xeb\x0e\ \x80uT\xcb#\x93\x9d\xdd\xbd\xe7\x81\xbf\x13A\xe0<\ qs\xa2\xc5_\xcaH1\xb7\x01\xd6\xb5\xb3\xbbw\x06\ 8\x03\xcc]\xfb]\xcf\xce\xee\xde\x87\x81_\x01\x83\xd4\ ci\xd8\xf3\xc0\xd7\xaavG\x9d\xa0\xba.\xfa\xfe\xea\ \x1f\xa7\x16\x7f)/\xbd\x9d\x01X\xaa\xde\xf8}\xeb?\ \x9d9\xf1\xa6\x5cR\x00\x98\x03\xb7,\xfe\xeb\xab\x02\xf3\ \xb6\x8e\x0e\x96\xb4e\xa5M\xe1\xaa\x1d%\xde\x09p@\ \xf9\xa7\x1cJ\xd2\x9b\x0c\x00\xaa\xa3\xc4V\xc0\x09e\x1f\ p$Ioa\x00P\x1d3\xca{[>\xa0\xbcP\ #Iwe\x00P\x1d\xab\x9d\x00\xa5\xe8\xfd\x11\xc0\x92\ \xfa\xc5\x00\xa0S\xab6\x7fM)\xa7`\x1e\x11\x87\x00\ y\x06\x80\xa4\xde0\x00\xa8\xae\x92\xf6\x01L\x807l\ c\x93\xd4'\x06\x00\xd5UR\x00\xb0\x03@R\xef\x18\ \x00TWI\x01`B9\x7f\x16IZ\x8b\x01@u\ \x95\xd4\x09p\x80-\x80\x92z\xc6\x00\xa0\xbaJ\xea\x04\ \xb0\x05PR\xef\x18\x00TKA\x9d\x00\x0b\xe2\x08\xe0\ i\xea\x81HR\x9b\x0c\x00\xdaD\x09\xfb\x00\xc6\xc0\xbf\ S\x0fB\x92\xdaf\x00\xd0&J\x08\x00\x1e\x01,\xa9\ \x97\x0c\x00\xdaD\x09\x01`\x8a\x01@R\x0f\x19\x00\xb4\ \x89\x12:\x01\xec\x00\x90\xd4K\x06\x00m\xa2\x84N\x00\ g\x00$\xf5\x92\x01@\xb5\x15\xd0\x090\x05n\x8e\x86\ \x83E\xea\x81HR\xdb\x0c\x00\xda\xd4\x0cx-\xf5 \ j\x9a\x00\xaf\xa7\x1e\x84$\xa5`\x00\xd0\xa6\xa6\xc0\xab\ \xa9\x07Q\x93G\x00K\xea-\x03\x8065#\xdf%\ \x00O\x00\x94\xd4[\x06\x00mjF\xbe\x07\xe9\x18\x00\ $\xf5\x96\x01@\x1b\x19\x0d\x07sb\x06 \xb7\x8dt\ \x87\xc0x4\x1c\x8cS\x0fD\x92R0\x00\xa8\x099\ .\x03\xb8\x01PR\xaf\x19\x00\xd4\x84\x1c;\x01\xdc\x00\ (\xa9\xd7\x0c\x00jB\x8eG\x02{\x07\x80\xa4^3\ \x00\xa8\x09\xb9.\x01\xec\xa7\x1e\x84$\xa5b\x00P\x13\ \xa6\xc0\xbfR\x0f\xe2\x94\xec\x00\x90\xd4k\x06\x00m\xac\ :Jw\x9f\x98\x09\xc8\xc1m\xe0`4\x1cLR\x0f\ D\x92R1\x00\xa8)S\xe0F\xeaA\xaciL\xbe\ g\x17HR#\x0c\x00j\xca\x94|:\x01&\xe4\xb7\ gA\x92\x1ae\x00PS\x0e\x80k\xa9\x07\xb1\xa6\x9c\ o0\x94$I\x92\xa4z\xfe\x0f52d\xaa\xa9\x0b\ \x22\x80\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x04T\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x04\x06IDATx\x9c\xed\ \x9bM\x88]5\x18\x86\x9f\xd6\x22e\x18\x5c\x88\x96a\ (\xb1\x0b)\xa5k)bk\xd1\xfa\xdb\x82\x01-E\ WJ\x10\x17\x82\x0b\x11\xa4\x16)\x22.\xdaE\x17V\ \x14t\x95E\xb5\x147\xd6\xf8S\x1d\x06\xea\xd4A\x10\ +\xd4\x22#\x8a\x0b\xc9\xc2E\x11\x19D\x8a\x0e\xe5\xd2\ E\xce\x8c\x97\xf99\xe7\xce=or\xaf\xf4>\xdbs\ \xce\x9b/\xefIrN\x92/\x1b(\x88\x0bq;`\ \x81\xdd\xc06\xe0\x16\xa0\x03\xcc\x03\x11\xf8\x1e8\xeb\xad\ \x99+\x15\xd3\x86\x12\x85\xb8\x10\x1f\x06^\x05\xf6\xf6\xf8\ \xc8,p\xcc[\xf3y\xbe\xa8\x12Y\x0dp!N\x00\ \xef\x91\xdez?L\x03\xcfyk~\x93\x05\xb5\x8cl\ \x06\xb8\x10\xef\x06>\x02&ZJ\xcd\x03Ozk\xa6\ \xdaG\xb5\x92,\x06\xb8\x10\xf7\x00\xe7\x80q\x91\xe4\x02\ p\xc8[\x13DzK\xc8\x0dp!n#\x0df\xb7\ \x8a\xa5\xaf\x02\xbb\xbd5\x97\x94\xa2\x1b\x95b.\xc4\x8d\ \xc0)\xf4\x95\x07\x18\x03>p!\xde\xac\x14\x95\x1a\x00\ <\x0d\xec\x11kv\xb3\x13xA)(\xeb\x02\xd5\xdb\ \xff\x19\xb8S\xa5\xb9\x06W\x80;\xbc5\xff(\xc4\x94\ -`/\xf9+\x0f\xb0\x85\xfe?\xab+P\x1apP\ \xa8\xd5\xc4!\x95\x90\xd2\x80\x07\x85ZM\xecS\x09I\ \xc6\x80\xaa\xff\xff\x0blR\xe8\xf5\xc8\xed\xde\x9a?\xda\ \x8a\xa8Z\xc0f\xcaV\x1eD?Y*\x03\xd4\x9f\xd3\ b\xa8\x02_\x10\xe9\x14/Sb\x80\xb7f\x01\xf8S\ \xa1\xd5#\x1dUy\xca\xa6+\xfdGo`n\x18\x7f\ \x84\xce\x09\xb5\x9a\xf8B%\xa44\xe04pM\xa8W\ \xc7)\x95\x90\xcc\x00o\xcd\xef\xc0\x19\x95^\x0dS\xde\ \x9a\xcb*1\xf5\xe7\xeb(i\xde\x9e\x8bk\xc0a\xa5\ \xa0\xd4\x80j\xed\xee\x88Rs\x19'\x86zA\x04\xc0\ [\xf3\x16y\xba\xc24\xa9\x85I\xc9\xf5\x07\xf7\x0c\xf0\ \xa9Po\x168\xe8\xad\x91\x0f\xb2Y\x0c\xa8~\x8c\x1e\ \x07\xde\x16\xc8\x9d\x06\x1e\xf1\xd6\xfc%\xd0ZA\xf6\x8d\ \x11\x17\xe2\x01\xe0$\xeb_,\x89\xc0\xcb\xde\x9a\x0f\xf5\ Q\xfdG\xa9\x9d\xa1M\xc0\x13\xa4\xae\xb1\x8f4{\x5c\ \x8d\x0e\xf0\x15\xe9;\x7fF\xf5\xb7WG\x11\x03\xbaq\ !\xbe\x02\x1c[\xe3\xf2\xbb\xde\x9a\xe7K\xc6\xf3\xbf\x9d\ \xc6\xaa\x186\x03J/\xaa\x0c\xc4\x80\xba2\x8b\xc73\ 2\xa0t\x81\x0d\xdc\x10\x06\x0c\x95\xe9\x83\x08\xe6\xa6\x9a\ k7D\x0b\x18*\x86\xad\x0b\x8cZ@i\x86\xad\x05\ \x14gd\xc0\xa0\x03\x184#\x03\x06\x1d\xc0\xa0\x19\x8d\ \x01\x83\x0e`\xd0H\xe7\xdf.\xc4\x9d\xc0\xb3\xc0$\xf0\ \x13\xf0f\xdb\xc5L\x17\xe2f\xe0E\xe0^\xe0\x17\xe0\ \x1do\xcd\xafmc]D\xd6\x02\x5c\x88\xbb\x80\xef\x80\ \x97\x80\xa7\x80\xd7\x81o]\x88\xa6\xdf2]\x88\xb7\x01\ 3\xa4%\xb4\x03$#~p!>*\x09z=\xc1\ \xf4\xc0IR6g7;\x80\xaf]\x88\xebN\x9f\xab\ 2\xcdg\x80]\xcb.\x8d\x01\xbe\xcaKj\x8dD\xa4\ j\xa6w\xadq\xd9\x003\xd5a\x89\x9e\xcat!N\ \x02\xe7I\x99\xa1\xab1\x01l]o\x9c\xab\xa1L\x92\ \xaac\x92d\xc2Z\x15Z\xc2\x85\xb8\x95T\xf9\x1d5\ \xb7u\x10m\xc2\xaaRd\xe6\x81\xe3\x0d\xb7MP\xff\ V!\x19u\x1e\xd8^s\x0f\xc0\xfb\x8a\x149\xd0\x8e\ \x01\xaf\x01M\xbb8[\x80\xba\x01\xec>\x9aw\x90f\ \x01\xd9\xde\x81tc\xa4Je\xff\x98\xfaJ\xb6\xe1\x22\ \xf0P\xd5\xe2$\xe4801\x06|\x820\x9d\xb5\xe2\ \x12\xf0\x80\xb7F\x9a\x8d\x96\xeb\xc8\xcc8\xf0\x19\xbd\x9f\ \x12k\xe2G\xe0~U\xbf\xef&\xe7\xa1\xa9qR\xe6\ X\xdb\x03\x14s\xa4\xca_i\x1f\xd5Jr\x1f\x9b\x1b\ \x07\xbe\x04\xee\xe9S\x22k\xe5!\xf3d\xc8[\xf37\ \xb0\x1f\xf8\xa6\x8f\xc7\xb3W\x1e\x0a\xcc\x06\xab\xc9\xd0~\ \xd2\xe7\xabW\x16\xfb|\xd6\xcaC\xa1\xe9p\x97\x09\x17\ z\xb8\xfd2i\xb4\xcf^y(\xb8\x1e\xd0\xd5\x1d\xa6\ kn\xbbH\xa17\xbfH\xd1\x05\x11o\xcdU\xe01\ \xe0\xec*\x97/\x90\xe1;\xdfD\xf1\x14\x19X\xca\x19\ z\x83\x947\xd4\x01\xa6\x80\xc3%r\x82\x96s\x1d\xca\ ?\xf7\xf3\xa0\xca\xa9.\x00\x00\x00\x00IEND\xae\ B`\x82\ \x00\x00\x02P\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00\x80\x00\x00\x00\x80\x08\x02\x00\x00\x00L\x5c\xf6\x9c\ \x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ \x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ \x09pHYs\x00\x00\x12t\x00\x00\x12t\x01\xdef\ \x1fx\x00\x00\x01\xe5IDATx^\xed\xdb!n\ TQ\x18\x80\xd1)\x09\xa2$\x14\x01\xa2\x84t\x114\ \x08\x1cx\x82b\x05T\xe0X\x03\x8e\x0d\xd4!\xd8\x01\ \xa6\x04_\x1c\x82\xc0\x1eh\x08\x08\x10\x9d& jH\ \x9a+J\x82\xa0\xd3i\xbe\xbe\xcc9f\xee\xd5_\xfe\ \xc9}\xef\xce\xac=\xdd\xfb2\xa3se|\x12\x11 \ &@L\x80\x98\x001\x01b\x02\xc4\x04\x88\x09\x10\x13\ &@L\x80\x98\x001\x01b\x02\xc4\x04\x88\x09\x10\ \x13 \xb6\xc0\x95\xe4\xb5\xe7\x8fo\xde\x1d\xebs;\x9a\ \xef\xec\x1f\x8e\xf5J2\x011\x01b\x02\xc4\x04\x88\x09\ \x10\x13 \xb6\xc4c\xe8\xf1\xbb\xf7\xdf\xdf\xcc\xc7\x86\xff\ d\x02b\x02\xc4\x04\x88\x09\x10\x13 &@L\x80\x98\ \x001\x01b\x02\xc4\xda\x1b\xb1\xdf\xaf\xde\xfe\xf80\xd6\ '\xee\xdcz\xbd\xbd>\xd6\x17\xe0\xf3\xa7\x83\xdd\xafc\ }I\x98\x80\x98\x001\x01b\x02\xc4\x04\x88M\xefB\ \xe6\xfe\xbd\xadg\xb7\xc7\xfa/\xdf~\xee|\xfc5\xd6\ \xd3a\x02b\x02\xc4\x04\x88\x09\x10\x13 &@L\x80\ \x98\x001\x01b\x02\xc4\x04\x88M\xef?b\xde\x05\xb1\ L\x02\xc4\x04\x88\x09\x10\x13 &@l\x81ch\xcc\ 1\x94e\x12 \xb6:_AW\x9f<\xdc|t}\ lN9\xcb\x8f96n\xbc|\xb0\xb196\xa7\x1c\ \xcd_\xec\x1f\x1e\x8c\xcd\xd9\x98\x80\x98\x001\x01b\x02\ \xc4\x04\x88\x09\x10\x13 &@L\x80\x98\x001\x01b\ \x02\xc4\x04\x88\x09\x10\x9b\xde\xeb\xe8Ey\x1d\xcd\xbf\x98\ \x80e0\x01\xd3%@L\x80\x98\x001\x01b\x02\xc4\ \x1cC=\x88\xad6\x01b\x02\xc4\x04\x88\x09\x10\x13 \ &@L\x80\x98\x001\x01b\x02\xc4\x04\x88\x09\x10\x13\ &@L\x80\x98\x001\x01b\xabs%yI\x99\ \x80\x98\x001\x01b\x02\xc4\x04\x88\x09\x10\x13 &@\ L\x80\x98\x001\x01b\x02\xc4\x04\x88\x09\x10\x13 &\ @L\x80\x98\x001\x01R\xb3\xd9\x1f]\xcavq\x12\ \x06\xf59\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x1dy\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x08\x90zTXtRaw prof\ ile type exif\x00\x00x\ \xda\xadY\xe9u\xf30\x0e\xfc\x8f*\xb6\x04\xf1\x04Y\ \x0e/\xbc\xb7\x1dl\xf9; %}\xb6c\xc7r\x12\ +\x16e\x89\x07\x88\xc1`H\x85\xc6\xff\xfe+\xf4\x1f\ |\xbcq\x1b\xf9\xc0)\xe6\x187||\xf6\xd9\x16\x5c\ \xa4m}\xca<\x9b\xcd\xcf\xf3\xfc\xf8\xfd\x11~\xdf\xdd\ \xa7\xf3\x81\xc5-\x87\xd2\xad\x9f)\xee\xf5\x8f\xfb\xe6\xec\ `\x15\x05W\xe1\xa6\xa3\xd4\xf6\x07\xf5\xfeA\xdeG\xb0\ \xe9\xa1\xa3} \xa7\x16Y\x5c\xf4\xbd\xa3\xbcw\xe4\xec\ z`\xf6\x0e\xca\x9a\xd6\x16s\xe2\xdb)\xd4\xb1\xca~\ \xcc$\xad/\xe9\xa9\x1ew\xc3^\xf9\xe1\xb7gx\xaf\ \x07\x8c\xe3\xac\x1d\x0e\xae\xc5\xd9:\xbb\x0cp\xfa5\xe4\ \x0a.\xe2<[TD%\x5c[\x97q\xf6\xee\x98\x12\ \x1c\xf2\xccO\xdb\x8dU\xf4\x88\xcaye^\xdc\x7f\x00\ \xc5\xc5u\x9fp\xe3\xde\x99\xf1,\x9f\xde7\xe1\xb9\xf3\ i\xba\xf8fd\xd7\xce\x91\xef\xee\x8f\xf9w?\x9d\xe3\ +\xd2\x13\x89\x8c5\xbb\xe2#\x5c\x1a\xf7I\x1dS\x99\ W\xa8X\xe1r7\x9bE\x1c\x8co\xc05\xcf#\xe3\ H\x84\xe8m\x80\xbcom\xab8\x9a\xc9\xc6\xc2\xe3b\ \xbc\xe9\xa6\x181c\x96\xcd4\x98\xe8\xed\xb0\x8c\xd2\xda\ \x06\xa0\xf4^rl\xb3m\xa0\x08p\xf2z\x18\xb1\x0c\ \xac\xbaK\xc0\xac\x01^\x87\xbb\xf6\xb4\xc5\xccq\xf3\x1c\ \xae\x99\x84\x81\xbbAMk\xd0\x99\xd1P =\xfd\xc5\ \xf1\xb2#\x11\x0dyc\xb6t\xfa\x0avY\x0dB\x98\ \xa1\xc8\xe9\x19\xb5\x00\x88\x91#\x8e\xc2t\xf0q<~\ \x14W\x07\x04\xc3ts\xc2\x04\xcbVW\x175\x98=\ \xb64\x8e\xdc\x04\xda\xa1b@\xb9\xb8f\xb8\xef\x1d\xc0\ E\x18;\xc0\x18\xe3\x80\xc0\x16\x8d\x0b&\x9a\x8d\xade\ c\xe0\xc7\x04|\x0a:J\xd6y[\x01\x81\x09\xc1v\ XiA\x8d\x08p\x92\xd5\xb1\xd1\x86\xcd\xack\x83]\ \xb7\x91\xb3\x00D\x00\xb1\x18\xd0\x80L\xc0\xca#\xb1!\ ~\xd8'\xc4P\x09.\xf8\x10B\x0c\x1cR\xc8\xa1D\ \x17}\x0c1F\x8e\x9a\xfc\x0a;\xf6\x1c82s\xe2\ \xcc%\xb9\xe4SH1qJ\x94r*\xd9f\x87\xe4\ \x18r\xcc\x9cS\xce\xb9\x14\x0cZ\xd0sA\xeb\x82\x0a\ \xa5T[]\xf55\xd4X\xb9\xa6\x9aki\x08\x9f\xe6\ [h\xb1qK\xd4r+\xddv\xd7\x91'z\xec\xdc\ S\xcf\xbd\x0c3\x10J\xc3\x8f0\xe2\xe0\x91F\x1eE\ \x10j\xe2\xc4K\x90(,I\xb2\x94\x135C\x0b\xd6\ /\xc7u\xd4\xcc\x81\x9a\x9dHiE>QCS\xe6\ \xa3\x0b\xa3\xe9$(f@\xccz\x03\xc4Y\x11@@\ [\xc5lK\xc6{K\x0a\x9db\xb6e\x0bV\x04\x0b\ +\x83\x82\xd3\x8d\x22\x06\x04\xfd06\x889\xb1\xfb\x87\ \xdc\x1dn\xe4\xfd\xafp\xb3\x07r\xa4\xd0\xfd\x05r\xa4\ \xd0\xbd@\xee+nOP\xeb\xaa6ms4\x11R\ \x1a\xaaS7\x07\xfa\xa1\xc2H\xc5\xa6\xa2\xa2v\xb9\xa4\ \xcf\x1a\xd4\xee\x90QE\x87k-\xb2\x8c\x9e\xf4\xe4\x8b\ \x90\xdb\x0a\xac\x95\xe4D\x1f;\x93Ej4z]\x83\ \xadP\xa9,-\x06\xe9\xec]fS\x91\x5c2\xb7*\ \x0e~X\xddKL\x02\xc2\xd2>\xd6\x08\xa8ot0\ t\x91|u\xa3\x05\x19\xb9\x0b:\xa9.N\x1brt\ U8\x8e^a\xc4\xd6\xb8w\xe9\xb16\xb8\x1b-\xe9\ h\xea\xe5lZ\xa4\xfaq6uh9\x9b\x9a&}\ H\xc7\xf4:|8b\xa9\xa0k\xf0\xb5\x8e\xda\xdb\xa0\ R\x1c\x80\xc4c\xdb\xbb\x1d\x89\x1b\xa4 \x18]\xec4\ \xaee]\xeb\x8a\xe0]IW+\xeee\x18Ym\xdd\ X\xcf#:\xa7elN\x083\x09\x88\xc0\xc0\x85\xa5\ \x995\xa1\xd4\xb4\x84~h\x98\xe4\x00\xbd\xc0\xc4\x91\xc6\ \x07Ll5u\x00\xe7+\xbc\x9a\x11[\xbb\xfd\x95<\ '\xff8\xee\xbf\xf95\x18\x00\xb2]\xb0\x97>\x9a\xd8\ \xbf\x09\x8e\x15N\x98aC\xee\x96\xd8I'\x01\x8cj\ \xe0^@Fi\xd5\xf4\x5c\x01\xf2\xc4-&\xd0Cx\ d\x18\xee\x8e\xa9o)C7Y\xba\xab\xa3\x83/\xb9\ \xc3oHl\xb6q\x8c@\xb8Vx\xc4e\xa9]\xe0\ \xb6\x80a\x91(\xeb\xd6[\x1e\xe2\xd1\xae%\xe4H\xc3\ \xa9\xa2\xe9\x18\x1e\xc1\xd5\xda\x8a\xc9\x01}\xa6;\x1aT\ H\xbaF\x17\xb4_\xce\xa8\x84)GT\xc2\x9e\x1c\xfb\ \x19\x95\xa0\xfb\x1e\x95[!\x09=\xd8\xc0\x8c\xa40\x90\ {\xc5\x96\x19S\x09\xac_\x0c0\x9b`\x982\xc7\xfb\ \xa6\xa4w\x15\x1eKaV\x1f+7\x07\xb2-\x88\xa9\ v\x16&\xf8\x18.\x03\x13d\x844\x1a\x5c\x85\xec\x07\ \x8e\xb0\x13\xae\xe2\x8b\x83\x87w\xbeO\x1e\xe9\x94N\x1e\ \xb55Y\xe5\x11\x81H\xfd\x96H\xc8\x85\x12x\xeb)\ \x0e/\x5c\x02\xda\x011I\x15\xee\xaa\xb8cM\xe5\x11\ \xf70\x8bX\x5c\xebe\x18\x86\xa6g\x0d\xb2J\xb3!\ K\xb43\x1c\x8cT+\x1a\x05\xfa\xab\xd5\xd8\x05\x86\xe2\ \xac\x01\xe1\xa3\xd3(\xaaA\xd90\x90\xa2+8\xdb\x01\ \xbf \x8b\x87\xa8\xc9\xba\xfd\xbc\xd3V\xa9O\xa6w\x97\ \x156\x08\xc5`,\xd7\x93\x8f\xc6L\x9f\xad9@`\ \xdeE;\xfd\x05=\xd4:\xfa\x0bz(;\xe8/\xe8\ \xb1T\xe4\x17\xb4\xb8e\x05\xdd\xd2\xe2g\x1dB\xb9\xd5\ \x221*\xe8\x8e\x1b\xa4\xb6!\x02\xb1\xb8P\x13\xe1\xad\ \xb4l\xcf6]\x91=\xfaP\x1f\xbb\xbc\xa0\x0c=r\ \xe6\x812\xe9`(R\xfd\xc1\xd1\xc2O\x08Jw\x0c\ \x1dHI=4\x17M\xc5nb\xe4\xc9\xec\x0c\xbf\x0d\ \x0b\xcc\xd0\xb4\xb7\x84\xb0\x81VL\x86!h\xb0\xcb\x9c\ \x11\xed\x09\xfa\xa5>F\x8b\x1c\xb1\x0cA\x18l<\xa0\ \xc9Q\xe3L#\x04Q3T\x22\x11;\xd9$\xf0C\ J\x8f\x88\x8fZ\xb0\xe6A\x9c\xc1\xbd\x0eKN\x0a\xa1\ `]U\xb7\x1fu\xc8V&\xf7\xb1\xac\xa38\xa2d\ d\x0b\x8d<\xacn\x92g\xf5\xd5\xb6l\xb7a]\xf8\ \xedmIW+B\x03\xab|C\x15:\xb8\xf2\x84*\ f\xc1\xbc\xe4\xf9\xe4\xe7\x0brB\xb2\x0fn\x86\x0e\xf7\ \xeb\x12\xa3aW\x88db'\xab\x11\x9c\xdc\x02PC\ \xd3\x9a\xa1\xe3\xe2V\x02\xaf\x08\x9b\x95\xcba\x9e\x18]\ \x8cb\x09\x80%p\x93j\x18\x82\x01_\xb2\x86\x06\x92\ ;V\x9d\xa2f\x22\x0a*\xb6\x9e\x9a\xf7\x03\xd6\x9f\xb5\ 32T\xe8\x03\xee\xc5\xf2\xc5\xb5R}!\xe4\xbc\x99\ \x15?\xecn\xa9Um\xc8\xda\x9ah\x9d\xa7\xca\x88\xbc\ \xe4\xad\x83}\xea\xa9e7B\xe4\xbaB\xcd\x92>\x93\ \xb2\xd7D\xa1o\xa4\xecX\x12>J\xd9SR\xd2\x8f\ \x85\xecAr\x08\x9as\xab8\xb7z\xf3J\xc2\x9e*\ \x18\x9d\x12\xf6\xbe\xbbV\xbf\xd1.\xfaH\xbc\xbe)\xe9\ \x8dx]$\x08|\xf4E\xbc\xb4\xf13\xf1z\xb3\xb0\ \xa3\x0f\xa4\xebN\xb9n6\x1aSj\xe8f\xa7\xf1^\ \xbc\x9ej\xd7\xea\x92\x1e\xe5\xebe\x97K\xbe^\xaa\x17\ }(_/Kz#_\x97iBw\xe2u\xb7\xbc\ |\xb7\xba\xbc\xd7.\x9a\xe2uM\xba\xfe\x09\xcd\xf6U\ j\xe6\x16B\xae\x8a\xd7W\xed:\xbb\xa4[\xf9z\xd5\ \xe5\x8d|\xbdT/\xfaP\xbe^\x96\xf4\x8d|}D\ \x162O\x16\x96\x17\xd6\x95_\xb4\x8b\xd0\xf2\xaat}\ #5\x90\xec[\xb5\xd9\xb6\xb7\xf2\xf5R\xbd\xe8_\x9f\ \xaf\xba\xfc\x22aO\x15\x8c~ aOK\xba\xb6\x1b\ {\xbf\x19\xa3k\xbb\xb1\xf7\x9b1\xfa\x91\x88=\xd97\ \xd1\xb5\xdd\xd8\xfb\xcd\x18]\xdb\x8d\xbd\xdf\x8c\xd1\xaf\x05\ \xed|[\xc3\x8fK<\xb5wW\xb0i\xec\xce\x93i\ \xaa*X:\x0c\xc59\xe8\x9b\xae\x0d>(4bD\ \x86\x1f\xaea\x22\xd6\xf9\x12\x9a\xbe\x9f\xc9`\x09\xbc,\ ^:\xe7}\x80'\x1e\ 3\xe8\x82\xc4\x8f\x5c\x97]~\xe3\x5cpX\xe0\x99!\ #\x9d\x9c'\x0e\x11\x8b\x856\x96\xdb\x98\x15\x0d\x95x\ \x8a8\xac\xa8\x1a\xe5\x0b\x19\x97\x15\xce[\x9c\xd5r\x95\ 5\xef\xc9_\x18\xcci+)\xae\xd3\x1cF\x0cK\x88\ #\x01\x112\xaa(\xa1\x0c\x0b\x11Z5RL$i\ ?\xea\xe1\x1fr\xfc\x09r\xc9\xe4*\x81\x91c\x01\x15\ \xa8\x90\x1c?\xf8\x1f\xfc\xee\xd6\xccON\xb8I\xc1(\ \xd0\xf9b\xdb\x1f#@`\x17h\xd4l\xfb\xfb\xd8\xb6\ \x1b'\x80\xff\x19\xb8\xd2Z\xfeJ\x1d\x98\xf9$\xbd\xd6\ \xd2\xc2G@\xdf6pq\xdd\xd2\xe4=\xe0r\x07\x18\ |\xd2%Cr$?M!\x9f\x07\xde\xcf\xe8\x9b\xb2\ @\xff-\xd0\xb3\xe6\xf6\xd6\xdc\xc7\xe9\x03\x90\xa6\xae\x96\ o\x80\x83C`\xb4@\xd9\xeb\x1e\xef\xeen\xef\xed\xdf\ 3\xcd\xfe~\x00w\x1fr\xa9\xe5*\x1e\xe2\x00\x00\x0f\ \x9ciTXtXML:com.ado\ be.xmp\x00\x00\x00\x00\x00\ \x0a\x0a \x0a \x0a \ \x0a \x0a \x0a \x0a \ \x0a \x0a \ \x0a \x0a \x0a \x0a \ \x0a \ \x0a \x0a \x0a \x0a \x0a \x0a \x0a \ \x0a \x0a \ \x0a \x0a\ \x0a \ \x0a \x0a\ \x0a \x0a \ \x0a <\ /plus:Licensor>\x0a\ \x0a \ \x0a\x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a\ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \x0a\x0bF\xde\xc2\x00\x00\x00\x06bKGD\x00\xff\x00\ \xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\ \x00\x0e\xc4\x00\x00\x0e\xc4\x01\x95+\x0e\x1b\x00\x00\x00\x07\ tIME\x07\xe5\x06\x02\x07\x1d8}5\xdf\xbd\x00\ \x00\x031IDATx\xda\xe5\x9b\xcbk\xd4P\x14\ \x87\xbf\xcc\xb4\xa5\xedT\xad\x96\xa2\x22\x06\x91nta\ \xd7\xee\xdd\x9a*\x05\x15\x14$ \x08\xfe\x03\x82\x16\xf1\ \x81 \xee\xbar\x19]\xbb2\xa8\xb4R\xdc\xb8\xd1\x85\ \xba\x10q!\xf8\x88\x05\x1fT+\xf4\xe1\xd0\xb1\x1d\x17\ 9\xd1Q\xc8L\xc6N27g\x0e\x04f\xc2\x09\xcc\ \xf7\xbb\xbf{\xee\x09s\xaf\x85\xa2p\xfd`\x0c\xd8\x03\ \xec\x04\xba\x81\x01\xf9\xdc\x03,H\xda5\xcf\xb1g\xa2\ g\xba\xd0\x15\xbb\x80C\xc0\x16\xb9J@\x11\xa8\x02\x05\ \xe1\xdd\xef\xfa\xc1Q`\xdas\xecJA\x99\x00\xc32\ \xea\xc3\xc0F\x19\xf9.qC4\xd8\xfd\xc0m\xe0\x8c\ \xeb\x07\xa3\xda\x04\xf8\x0e\x94\x05\xbc\x08Xr\xdf\xfa'\ \xaf\x17\xb8\x0e\x1c\xd7&\xc0\xa8\x8c<\xc0\xaa\x5cVL\ n\x0fpR\x9b\x00\xdbe\xeeW\x81\x95\x065\xee'\ \xf0V\xe3\x14X\x16\x01Ju\xf2\xd6\x80oHe\xd4\ \x14\xd3\x026\xd0\x00\xbe\x02,\x01\x8f\xb5\x09\xb0M\xea\ @\x5cTk>\x7f\x00^\xab\xe9\x03\x5c?8\x07\x5c\ n\x00\xbf&\x85q\x0e\xb8\x03\xdc\xebR\x04\x7f\xb5N\ \xca\x0f\xb1\xfc*\xf0\x1ex\x0a\xf8\x9ec\xbf\xb3:\x00\ \xfe\x19pK\xe0\x97\x80\xe7\xc0\x17\xcf\xb1?Rg\x8d\ \xd4\x02\xff\x008\xec9\xf6r\x5cBA1\xfcT#\ \xf8\xdc: !\xfcx#\xf8\x5c\x0a\xd0J\xf8\xdc\x09\ \xe0\xfa\xc1\x04pe=s>\xb75 \x01\xfcT\xb3\ \xf0\xb9q@\xabm\x9f+\x01\xd2\x847^\x80\xb4\xe1\ \x8d\x16 \x0bxc\x05\xc8\x0a\xdeH\x01Z\xd1\xde6\ \x13\x05\xc3\xe0'Z\xd1\xde\xe6\xd2\x01\xae\x1f\x5c\x00.\ e5\xf2F\x09\x90F\x87\x97\x9b) #\xdf\x16\xf8\ \xb6; \xa1\xed\xc7<\xc7.\xa7\xf5\x1b\xacN\x86o\ \x9b\x00\xa6\xc0\xb7E\x00\x93\xe03\x17\xc04\xf8L\x05\ H\xb8\xd4e\x0a\x9f\xd92\x98p\xa9\xcb\x1c>\x13\x07\ \x98h\xfb\xcc\x040\x1d>U\x01L\x9d\xf3\x99\xd4\x00\ \x93\xe7|\xea\x0e\xc8\x83\xedS\x13 o\xf0-\x15\xa0\ \x9d\xaf\xb4m\x17 \xaf\xf0-)\x82i\xfdc\x93\x0b\ \x07$\x84\x1f7\x15~]\x0eH\x00\x7f\xdft\xf8\xff\ v@\x13\xf0e\x0c\x0f\xab\x93\xe1\x9b\x16@\x1b|S\ \x02h\x84\xffK\x00\xd7\x0f\xba\x09\xf7\xd5\x03T<\xc7\ \xae4\xd1\xe1\xe5\x12\xfe\xb7\x00\xae\x1f\x0c\x01[\x09\xb7\ \x9a\x16\x087\x16.\x03\xf3\xc0)\xe0\xbcFx\xf8\xb3\ \x9d|3p\x84p\x9fm\x89p\xd7\xf5'\xc2#(\ \x07\xb5\xc2\x03X\xae\x1f\x8c\x00\x07\x80\x13\x80-\x0e\xf8\ \x0a\x0c\xcaw\xb5\xf0Q#\xb4\x17p\x80\xdd\x84\xdb\xcc\ W\x81\xa1N\x80\x8f\x048\x06\xec\x13\xf8\x15\x11`G\ \x9dg\xeej\x81\x8fj\xc0\x08\xd0'\xe0=R\x0c\xe3\ \xe2\x09pZ\x0b|\xe4\x80\x92\xc0\x17\xa5\x18\xc6\xc5g\ \xb1\xfe \x8a\x22Z\xf2\x006\xd4\xc9\x9b\x03\x1eI\x9f\ \xd0\xafM\x80^\xc2\x83\x86q1\x0f\xbc\x11\xa1\x16P\ \x16\x05`F\xa6@\x1c\xfc\x02\xb0IF\xbe(=\x82\ *\x01n\x02\x93\x84\xe7\xe8j\xa3,\xf7\xd6$\xaf\x0f\ X$\xdeoon\xee\xbeww!\x91H\x0c3\x0d\x00\ m\xdd\x04p\x07\xb8\x0e\x8c\x02M`\xc5(\xd9**\ \xa0\xad[\x07&\x06\xe8q\x90\xec4:\xcd\xaf\x01\xa7\ 3\xe2.0g\x94|\x9fWA[\xf7\x0d86 \ \x83\x83\xa6%\x80E\x0e7\x0f0\x09<\x09\xeb'<\ \x02X\xc8\xd1g;+\xa4\xb6\x08\xfcw\xfe\x7f\xf5\xca\ #\x80\xcd\x1c\xbde\x94\xfc\x1a\xcaL\x0c\x04p\x1f\xf8\ \xd5G_\x0c\xe8%\x0a\xa2\xb3\xcb_\x05\xde\x1dx\x7f\ \x07\xb8i\x94|\x1a\xc7V8\x1a\x07_h\xeb\xa6\x81\ 1\xfc\xd2\xdf/S@[7\x83_IU\xa4\x1d\xdb\ @\x22\x91H$\x12\x11\xe9\xe6\x01S\xc0=\xfe\xce\x03\ \x96\x8d\x92[E\x05\xb4u\x1f\xa9n\x1e\xf0\xb9\xd1i\ ~\x1d8\x99\x11\x7f\x02\x17\x8d\x92\x1by\x15\xea\x92\x07\ d\x9b\x07\x18\x07\x1e\x87\xf5\x13\x1e\x81_\xf6\xfd8\xa7\ \xad\xab\xea\xa7[\x0a\x01\x8c\x14\x1cS\xa4W\x1a\x81\xdf\ \xf0\xfa\xf1iX\xf2\x80\x1f=\xb4}|R\x5ck\x84\ Qr\x1b\x98\x03V\xf1M\x03|\x00n\x18%\x9fE\ s\x16\x88l\x1e0\x0e\x8c\x1a%w\xcb\x16\xd0\xd6\x1d\ \xa7\xbay\xc0^l\x03\x89D\x22\x91HD\xa4\x9b\x07\ \x9c\x00V\x80y\xfcu\x81&\xb0d\x94|]T@\ [\xf7\x85\xea\x8e\xc3\xae\xd1\xb9\x18\xf2\x06\x98\xce\x88m\ \xe0\xb2Qr5\xafB\x1d\xf2\x80%\x0e7\x0f>\x19\ z\x14\xd6Ox\x04p)G?3\x0cy\xc0Q\x1c\ SY\x04~\x0a\xec\xc7\xd6\xbf\x0cFUD\x00\xcb@\ \xaf\xd0c\x0f\xb8\x1d\xd6Nx\x84Q\xd2\x01\x17\x80\xe7\ \xc0o|&\xd0\x04\xae\x19%_\xc64\x17\x82l\x1e\ \xf0'\xa5\xf4\x9c\xac\xad\x1b;rW\xe1(u\x0f\ D\x22\x91H$\xea\xca\xd0\xff\x0cv\xf3\x80\x19\xe0\x01\ p\x05?\x05n\x00w\x8d\x92\xaf\x8a*T~\x1c\xd6\ \xd6I\xfc\xf3\x02\x0b\xf80D\x00g\x81\x17\xda\xba\xf9\ \x98\xeeB \xf0w\x86L\xf5\xd0F\x80\x87a\xed\x84\ G\x00\xb39\xfa)m\xddd(31(3\xeb\xd7\ \xfa\xff\xb2\x00\xf26\xbaM\xa3\xe4\xf7Pfb\xd0\xcd\ \x03vzhm\xe0VX;\xe1\xc9\xc6\xe2\xe7\xf1'\ e\x9b\xf2\xb1\xf8[*|\x9b\x5cl\x03\x89D\x22.\ \x7f\x00JK\xaf\x03\x81S\xda9\x00\x00\x00\x00IE\ ND\xaeB`\x82\ \x00\x00\x02p\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x027IDATx\x9c\xed\x9b1kT1\ \x1c\xc0\x7f}\x94\x22\x8e\xc5\xf9a\xc1\xc1\x0f\xe0T:\ \x16\xe9 WT(\x08\x12\xa1n\x0e\x22\x8e]:u\ *\xe2 \x0eN\xc2upp\xa8dP\xbf\x80\x9b\x9f\ \x22\x83\x88kK\x91R\xc4\xa1wp}\x5cr\xb94\ \xb9\xff]\x92\x1f\x1c\xc7\xbb\x7f.\xf9\xe7\xf7\x92\xbc\xdc\ \xe3\xde\x12\x16\x946\x0d\xf0\x06\xb8\x07\xac\x00\xcb@3\ \x08/\x0f\xde\xbb\xc7\xa34c>\xbb.?\x81\xe7\xfd\ ^{\x16\xab\xc2q\x89\x0f\xd9\x05^\xc5j(\x12w\ \x80[J\x9b\xedX\x12\x5cgi-F\x03\x09\xd8\x04\ \x8e\x9567bT\xe6\x12\xe0\x1a\x1d\xd2\xdc'\x92\x04\ W'\xbb\xb1\x0b\xe0\xebu\x1b\x0c`\x03X\x1d\xf3\xf9\ \x16\xf0Yi\xf3\xb8\xdfk\xcfC+w\x09\xe8\x8e\x8e\ \xd3~\xaf\xdd\x0em(\x14\xa5\xcd\x0f`\xdd\x12~\x00\ |R\xda<\x09\x95\xe0\x9a\x02)V\xf1\x14<\x02\x8e\ \x946AS6\x07\x01\x00;\xc0\xc7\x10\x09\xb9\x08\x00\ x\x0a|\x18\xec_\xbcY\xb4NNb\x17x7\x8d\ \x84\x9cF\xc0\x90\x17\xc0\xa1o\xe1\x1c\x05\x00\xbcV\xda\ \x1c\xf8\x14\x5c\xe4NNbOi\xb37\xa9P\xce\x02\ \x00\x0e\x946/]\x05r\x17\x00\xf0Vi\xb3c\x0b\ \xe6\xba\x06\x8c\xd2\x00\xcf\x5c\xc1\x90X6\x14\xd1I\x17\ \xf3\xfc\x93w\xc8C.\xefH\xc1\xd5\x13\xd6\x8c\xbc\xe0\ \xea]\xaao@\xebS\xf9\xdc\x0b\xe8\xf7\xda?\xd3~\ Gi\xf3\xd7\xb7l\xf1S\xa0\x0a\x90N \x11\xff:\ \xc7\xd6~\xe6*\xa0K\xf1\x02\xac\xd4\x8d\x90t\x02\xd2\ T\x01\xd2\x09$\xa2{\x15\xb0R\x05\xa4\xccb\x8e(\ \xfe2X\xbc\x00+U\x80t\x02\xd2\xe4*\xa0^\x05\ |\xa9\x02\xa4\x13\x90\xa6\x0a\x90N`F\xd4\x8d\x90\x8d\ \x5c\x05\x14\x7f\x19,^\x807U\x80t\x02\xd2T\x01\ \xd2\x09H\xe3\x12\xe0\xbd\x92.2u\x04H'\x90\x88\ \xe2\xf7\x01Q\x04\x14\xbf\x06\x14/ '\xac'\xb3\x8e\ \x00G\xacx\x01\x173\xcb\x22=\xd6\xbe\xb8\xfe'\xd8\ }\x0a\xeb\xa6\xd2\xe6}\x9c|\x92s\xdb\xb7\xe04\x02\ V\xb8|\x1ac\x11\xb1\x8e\x00\xd7\x148I\x90\x88\x14\ A\x02~%HD\x0ak_\x5cS\xe0\x0b\xf0\x1d\xb8\ \x1b=\x9d\xd9\xf2\x1b\xd8\xb7\x05\xff\x03?2_\x0c\xd0\ e0g\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x06*\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x05\xdcIDATx\x9c\xcd\ \x9b[\xa8UE\x18\xc7\x7f\x85\x84\x1c$BB$b\ \x1e\x22\xe2 !\x11\x22\xbd\x15\xd5A\xba8>D\x9a\ \xd1m\xb42\xbb\xaae\xde\x13\xef\x95]\xd4\xcc\xca\xac\ )#\x89.R\xa3\x96\xa5fI\xc8ABz\x88^\ \x83y\x8a\x08\x89\x83\x1cB\xe2\xd0\xc3\xcc\xb2u\xf6Y\ {\xafY\xb3f\xed\xed\xffm\xaf=\xeb\x9b\xf9\xfd\xe7\ \x9b\x995k\xf6\x86\x1eJ\x19;[\x19\xfbd/\xdb\ pq\xaf*V\xc6\xce\x06>\x06\xb6\xf7\xd2\x84\x9e\x18\ \xa0\x8c\xbd\x07\x07?\xce\xb7a\xbb2\xf6\xe9^\xb4\xa5\ \xeb\x06(c\xef\x05>\xc2\xc1\xe7\xdb\xf1z/L\xb8\ \xa8\x9b\x95\xf9\x9eo\x85o\xd5b-\xc5\xb6.5\xa9\ {\x19\xd0\xa6\xe7\x8b\xf4\xaa2vQ\x17\x9a\x04t\xc9\ \x00e\xec}\xc0\x87\x94\xc3\x83kS\xd7Lh|\x08\ xxM\x18|\xab\x9e\xd5R\xbc\x96\xb8I\xa3\xd4h\ \x06(c\x1f \x1e\x1e`\xab2vI\xc2&\x8dQ\ c\x19\xe0\xe1\xdf#\x1e>\xaf\xc62\xa1\x91\x0cH\x0c\ \x0fnNx>Q\xacQJ\x9e\x01\xca\xd8\x87p\xf0\ M\x98\xbbTK\xf1J\xca\x80I\x1b\xa9\x8c\x9dGs\ \xf0\xe0\xe6\x84\xa4\x99\x90,\x03<\xfc\xbbtgi]\ \xa6\xa5x9E\xa0$\x8dU\xc6>L\xf7\xe0\x01^\ R\xc6.O\x11\xa8v\x06x\xf8w\xe8\xcd\xc6j\x85\ \x96\xe2\xc5:\x01j5:\x01\xfc>\xa0\xces\xff\x16\ e\xec\xca\x1a\xf7\xc7\x1b\xa0\x8c}\x94z\xf0{\x81\x07\ \xb5\x14\x8b\x81:3\xfb&e\xec\xea\xd8\x9b\xa3\x86\x80\ \x87\x7f\x8bz\xf0\xf3\xb5\x14\xff\xe6bn\x05\x9e\x8b\x8c\ \x07\xb0FK\xb1\xb1\xeaM\x95\x01\x9a\x80\x07\xd0R,\ \x05\xea\xcc\xec\x1b\x94\xb1/T\xbd\xa9\x12D\x02\xf8\x0f\ \x00\xd5\x0a\x9fIK\xb1\x0c\xa83\xa9\xad\xabjB\xf0\ \x10H\x04?_K1\x12P\xd7\x16\xa0\xce2\xb7Q\ K\xb1&\xa4`\x10\x8c2\xf61\xea\xc1\xbfO <\ \x80\x96b\x05\xb09\xb2.\x80\xd5\xca\xd8u!\x05K\ 3\xc0\xc3\xbfI=\xf8GB\xe1[\xea\xde\x04\xd4Y\ \xe6J3\xa1#T\x02\xf8=D\xc2\x03h)V\x01\ \x95g\xf6\x9cV{\x13\xdb\xaa-X\x02\xf8\xdd\xc0\x82\ X\xf8L\xbe\x07\xd7\xd7\x08\xb1\xb2\x93\x09\x85p\x89\xe0\ \x17\x96\xc1+c\xafR\xc6\xf6\x97\x05\xd3R\xac\xa5\xbe\ \x09[\x8a\xbe\x18\x03\xa8\x8c}\x9cz\xf0o\x13\x08\x0f\ \x1c\x07\x8e+c\xa7\x94\x05\xf5&\xac\x8dl\x13\xc0r\ \xff\xb05J\xa3&A\x0f\xff\x06\xf5\xe0\x9f\x08\x80\xbf\ \x1a8\x06\x08\x7f\xe9\x0f`@K\xf1kY\x05~\x9d\ \x0f\x9a\xe1\xdbh\x1b\xee\x15\xdb\x08\xe4@\xfd~\xbe\x17\ \xf0\x00\x93\x81c\xca\xd8\xa9e\x95h)\xd6S/\x13\ \x16\x01\x1b\xb2\x0fy\xd8A\xe0\xcf\xc8\xa0\xbb\x08\x83\xbf\ \x86\xb1\xf0\x99&\x01G*\x98\x10\xf4\xa0S\xa0!\xe0\ P\xf6\xa1u\x08L\xf1\x0d\x9c\x5c!\xe0N\xe0\x99\x0a\ \xf0W\x96\xc4\xfb\x0b7\x1c~)\xab\xd8o\x85;.\ s-\x1a\x02n\xd3R\x9c\xcc.\x8cy\x10\xaah\xc2\ .\xe0\xa9\xc0\xb4?N9|\xa638\x13N\x97\x15\ \xf4[\xe1\x0de\xe5(\x80\x87\x82\xf1\xae\xa5\xf8\x0d\xb8\ \x0571u\xd2N\xc2\xe0\xfb\x81\x1f\x09\x87\x07\x98\x88\ \x1b\x0e\xd3\xca\x0a\xfa-\xf0\xaa\x92b\x85\xf0\xd0f\xc2\ \x0b0a\x07ai\xdf\x8f\xcb\xa6+J\x1aX\xa4\xcc\ \x84\xe9e\x05\xb5\x14\x9b\x81\x15m\xbe\x1e\x02\xee(\x82\ \x87\x92\xbd@\x9b\xe1\xb0\x03w\x84\xdd$|^C\xc0\ \x0c-\xc5`YA\xff\xa24\xff\xc0\xd3\xb6\xe73\x85\ l\x86\xfaq\xe3w2\xe1\xf01\x93i'\x95\x82\xe4\ \xea\xceL\x082.\xe8}\x80\x07\x9a\x03\xac\x0b\xec\xf9\ \xcc\xb0\x94\xaab\xc2\x12`0\xa4l\xd2\xa3\xb1\x06z\ \xbeUC\xc0L-\xc5\x89T\x01S\x9e\x0c5\x0d\x9f\ \xe9,nRKbB\xaa\x93\xa1n\xc1\x03L\x00\x0e\ )coJ\x11\xac\xb6\x01\xca\xd8k\xe9\x1e|\xa6\x09\ \xc0\x81\x14&\xd4=\x19\xaa\x0b\x7f\x1a(\xdd\x01\xb6Q\ \x96\x097G\xde\x0f\xd4;\x19\x9a\x8a\x83\x9f\x14\x19\xe2\ g`\x00\xb8\x118\x15\x19\xa3\x0f\x97\x09\xd1&D\x19\ \x90\x08~\x86\x96\xe2\x8c\x96\xe2\x0c\xce\x88\xd8I\xad\x96\ \x09\x95W\x81\x1c\xfc\xe51\x15\x92\x83o\x89\xdb\x07\x1c\ \x00b{s\x18\xb7D~_\xe5\xa6\xaa'C\xd7Q\ \x0f\xfe4\x05\xf0\x00Z\x8aa`&p42v\x96\ \x09\xb7V\xb9)\xd8\x00\x0f\x7f\x84z=?P\x04\x9f\ \xc9\x9b0\x0b8\x1cYG\x1f\xf0U\x15\x13B\x1f\x85\ \xaf\xc7\xc1O\x8cl\xd8)\x5c\xcf\xff\x1dX\xdfx\xe0\ \x0b\xe0\xf6\xc8\xfa\x86\x81YZ\x8a\xd2l\x0a\xd9\x0c\xd5\ \x85/\x1c\xf3\x01\xf5v\xc5\x84\xb2\xed\xf04\xe0[\xea\ \xc1\x0f\x84\xf6|A\xfd\x8d\x9b\xd0\xe9d(\x05|p\ \xda\x17IK\xf1\x0fp\x17\xf0ud\x88\xd29\xa10\ \x03\xfc[\x98o\xe8Q\xcf\x17\xb4g<\xf0\x19pg\ d\x88\xb6Kd\xd1K\xd1\xe9\xb8\x9e\xbf,\xb2\xb2J\ \x13^\xa8\x9a2\xa1\xf5\xb5\xf8\x05\x09\x9f\xa9\x09\x13\xf2\ 'C7p\x01\xc3\xc3\xf99\xe1n\xe0`d\x881\ \x8f\xcd\xf9I\xf0R`|d\xe0A\x12\x8e\xf9NJ\ `\xc2%\xe4\x1e\xe6\xce\x1b\xa0\xa5\xf8\xce\x07>W1\ \xe0O\xb8\x9e\x1f\x8alPe\xe5V\x07S\xf1\xd6\x11\ \xdcOu>\xcd.\x8cZ\x06\xb5\x14\x07\x81\xb9@\xe1\ \xaf\xb8\x0at\x12\xf7z\xaak\xf0\x99\xb4\x14\xe7p\x1d\ \x16j\xc2\x08\xee\xd8~o\xfeb\xd1\xc9\xd0~\xe0~\ \xcaM8\x81{K\xdbu\xf8L9\x13\xbe\x0c(\xbe\ XK\xb1\xbb\xf5b\xbb\x93\xa1O\x80\xf98\xd7\x8a\xf4\ \x03=\xea\xf9Vy\x13\xe6\x00\xfb;\x14[\xa6\xa5\xd8\ Q\xf4E\xdb'A\x9f*\x0b\x18k\xc2Q\x1c\xfc\xd9\ \x8ammL\xde\x84\xb9\xc0\xe7\x05_\xaf\xe9\xf4\xdf\x82\ \x8e\xdba-\xc5\x1e`!\xff\x9bp\x18\xf7l=\x1c\ \xd9\xd6\xc6\x943a_\xeer\xe9\xef\x87C\xb7\xc3\xf3\ p\xaf\xad\x94\x9f\x81/X)c\xc7\xe1~\xe3\xf4{\ \xc8\x7f\x09\xfe\x03\xf0\xdf\x96\xb4*\xc5\xc5o\x00\x00\x00\ \x00IEND\xaeB`\x82\ \x00\x00\x027\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x01\xfeIDATx\x9c\xed\x9b\xbbJ\xc4@\ \x14\x86?\x97-,E,\xac\x82\xbd\x8d\xad\xaf`\x11\ Y\x16DD\xd2\xf9`F,EH!b\xeb+\x88\ \x95\x85\x04\x9faY\x16\x11\x9b\x04SHvfr\xe6\ \xca|\xb0\xdd\xee\x9c\xf3\xff\x993\x99\xdbB&\x93\xc9\ d2\x19_TM;\xab\x9av\xee+\xfe\xccW`\ \x80N\xf8-p\xe0+\x07o\x06\x0c\xc4_\xfb\xccc\ ^5\xed#p8\xf2\x9d\xb7\xba,n$\x83\x0e\xc4\ _\xf5yH\xb6\xaf\xc3\x1c8\x01\x8e\x5c\x05\xfcG\xbc\ W\x9cv\xbd\x11\xf1\xe9\x0f\x82\xa1=\xf9\x1e'\x06(\ \x88O\xb7\x07\x84\xfa\xe4{\xac\x1a\xa0!\xde\xdbk\xd0\ Z`\xcd'\xefo\x1e`\xa3Q\x83n\xffZ5\xed\ \xb7\x8d\x5c\xb6 ?\x077\xac\xf9}\xe9<\x14Y\x89\ \x1a\xd0\x89\xbf\x03.%\xdb\xb5\x89X\xed\xc5(\x1e\x84\ \x0c\x88U<\x08\x18\x10\xb3x\x98h@\xec\xe2a\x82\ \x01)\x88\x07C\x03R\x11\x0f\x06\x13\xa1N\xfc=p\ !\x9f\x8e{\xb4z@j\xe2A\xc3\x80\x14\xc5\x83\xa2\ \x01\xa9\x8a\x075\x03\x92\x15\x0f\xea\x06\xec\xd9N\xc4\x17\ *\x06\xac\x81\x05\xf0b9\x17/(\x8d\x01uY\xac\ H\xd4\x04\xe5\xb7@g\xc29\x89\x99\xa05\x0f\xa8\xcb\ \xa2/\x87g;\xe9\xb8G{*<(\x87$L0\ Z\x0b\xa4\xd4\x13\x8cW\x83\x9d\x09K\x227a\xd2~\ @\x0a\xe50yG(\xf6r\x10\xd9\x13\x8c\xd9\x04\xb1\ ]\xe1\x81\x09ORm\xba@\xf4Hj00Fc\ \x82\xf8\xc9P]\x16\xeb\xaai\x97\xc0\x03p\xa6\xf8\xb3\ 5\xf0#\x9d\x8bJ\x5c+g\x83\x06&\x9c\x02\xef6\ r\xd9\x86\xb5\x8b\x09\x9a&l\xea\xb2\xd8\xd8\xcae\x0c\ \xab\xc7\xd21\x8c\x09\xd6\xcf\xe5C7\xc1\xc9\xc5\x84\x90\ Mpv3#T\x13\x9c^M\x09\xd1\x84\x19\xf0\x09\ |\x8c|\xbe$\x03\x86f\xc2\x8e\xaf\xc0U\xd3\xee\xf2\ \xf7\x8a<\xae\xcb\xc2\xcb<\xc0\xdb\xed\xacP\xd6\x0e^\ \xff/\xd0M~\x16\x08\x97Y&\x93\xc9d2\x19%\ ~\x01\xa4\xd3\xb3\xa4Y\xec\x81`\x00\x00\x00\x00IE\ ND\xaeB`\x82\ \x00\x00\x03\xe7\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x03\x99IDATx\x9c\xe5\ \x9b?h\x14A\x14\x87\xbf\x84CD\xc4R,d\x0b\ \x15\xbb\x08\xa2\x85 hcc \xab\xb1VdDP\ \x14DA\x11Q+\xad\xd4\xc2&\x8a YD;\xd1\ \xe8\x04b\x93\xca*EL\xa1`\x11\xc5bI!\x22\ A\xa2\x04\x91 \x16\xbbC6{\xbb\xb9\xfd33;\ Y\x7fUnov.\xdfw\xef\xbd=\x96\xbb>\xd6\ X\x84\x0c\xb7\x01\xd7\x80\x03\xc0/\xe0\x05\xf0 \xf0\xbd\ \x1fU\xf6\xeb\xd3\xf8\xbf\x19\x8f\x90\xe1q\xe0\x11\xb0!\ \xf5\xd4\x07\x0c\x07\xbe7]d\ o\xe7\x05\x08\x19\xee\x00\xde\x01\x9bJ\x9c\xb6\x08\x9c\x08\ |\xefe\xaf\x85E\x8c6\x16!\xc3~\xe0)\xe5\xe0\ !\x9a\x11\xcf\x85\x0c\xcf\xf6Z\xe8\xb4\x00\xe0\x02\xb0\xaf\ \xe2\xb9\xfd\xc0C!\xc3\xcb\xab-r\xb6\x05\x84\x0c7\ \x03\x9f(\xff\xeeg\xe5J\xe0{\xf7\xb2\x9ep\xb9\x02\ N\xa1\x07\x1e\xe0n^;\xb8,\xe0>0\xa9q\xbf\ \x11!\xc3c\xe9\x83\xce\xb6\x00\x80\x90\xe1z`\x1c8\ \xa4i\xcbE\xe0`\xf2\x12\xe9\xb4\x000\x22a\x0e\xd8\ \xad>,9\xd3\x02B\x86\x9d\xac\xe3\x81\xef\xfd\x06\x86\ \xd0\xd7\x0e[\x81'\xea\x81\x13\x02\x84\x0co\x01o\xe2\ w\xbb+\x06$\x0c\x0a\x19\x9e\x06\x07Z \x86\xbf\x11\ ?\x9c\x04\x86b\xe0\xac\xb5:\xdba\x1e\xd8\xde\xa8\x80\ \x14\xbc\x8aM\x09\xd7\x1b\x13\x90\x03\xafbK\xc2L#\ 3\xa0\x07\x08\x05\xbe7\x0b\x0c\x03\x7ft\xbf\ x\x89\x18\x81\x87r3`\x10\x18\xc3~%\x18\x83\x87\ \xf2W\x01\xdb\x12\x8c\xc2CF\x0b\x08\x19n\xc9[\x1c\ \xf8\xde\x04\xf6\xda\xc18\x16\xfbA\x88X,\x22\ !%f\xb2\x95\x95\x85D\x94\xa4HIZHey\ I.5\x11\xa6\xfd\xa2\xec\x97\x8a\x89h\xd1/\xe8\x97\ \x15i\xde\xea\xf6c\xca,\xa2\xd2\xc4~(\x11\x8b\x15\ \xa8\x84XY\x89l!\x22\x22b\x12\x8b-\x8f\xfe8\ \xf3v\xdf\xae\xf7\xdc7\xf7\xbe\xfb\x9e\xbb\xf5\x05a\xbd\ 3w\xee\x99\xf3f\xce9s\xe6{\x06\xd1`\x04Q\ X\x02\xc6\x00\xe3\x81\xf3\x803\x80\x11\xc0P\xe0D\xa0\ \x04t\x02\x87\x81\xfd@\x07\xf0\x13\xb0\x1d\xd8nM\xdc\ \xd9H\xf9\x065b\xd0 \x0a\x87\x00\xd3\x81k\x80\xc9\ @k\xce\xa1:\x81v`\x1d\xf0\x915\xf1\x9eB\x04\ \xacB\xa1\x0a\x08\xa2p\x220\x07\x98\x01\x9c\x5c\xe4\xd8\ @\x19\xf8\x16x\x15XkM|\xb4\x88A\x0bQ@\ \x10\x85\xd7\x02\x8b\x80\x09E\x8c\xe7\x81\x0e\xe0i`e\ \xbd\x8a\xa8K\x01A\x14^\x00<\x0fL\xacg\x9c:\ \xb0\x1b\x98oM\xfcq\xde\x01r) \x88\xc2\xc1\xc0\ R\xe0\x01\xa0%\xef\xc7\x0b\xc4'\xc0\x5ck\xe2\xbdY\ _\xcc\xac\x80 \x0aG\x03\x16\xb88\xe3\xab\x9d\xc0N\ \xf7o/\xf0\x17\xd0\x85x\x81\x93\x80!\xc00`$\ p\xae\xfb;\x0b\x0e\x00\xb7Y\x13\x7f\x92\xe5\xa5L\x0a\ \x08\xa2p\x0a\xf0>\xfe\xc2\xed\x01\xd6\x02\x9f\x03[\xac\ \x89\xff\xf6\xfcN\x0b0\x0e\x98\x0a\x5c\x0f\x5c\x80(\xaa\ \x16\xca\xc0bk\xe2\xc7=\xe5\xf3W@\x10\x85\xb3\x80\ 7\x81\xc1\x1eB\xacGl\xc3\xd7\xd6\xc4e\xdfo\xa4\ |{\x1c0\x17\x08\xf1\xf3.+\x80{}\xbe\xed\xa5\ \x80 \x0ag\x03\xafS{\xbfo\x04\x1e\xb6&\xde\xee\ 3nV\x04Q8\x02X\x00\xdc\xe1!\xcbk\xc0\x9c\ ZJ\xa8\xa9\x80 \x0ao@\xf6|\xda\x07\xf7\x01w\ [\x13\xaf\xad5^\x11p+b\x15\xb5\xdd\xee\xcb\x88\ \x5c\xaa\x12R\xf7\x95\x0bl\xde\x22}\xf2\x1b\x80\x0b\x9b\ 5y\x00k\xe2\x1f\x81\xcb\x81\xe5\xc8\x96\xd30\x0fX\ \x926\x96\xba\x02\x82(\x1c\x09\xfc@z\x18\xfb\x0c\xb2\ \xe4\xeb\xde\xe7y\x11D\xe1\x0c\xe4G:E\xe9R\x06\ n\xb6&~/\xa91Q\x01\xce\xcfo\x02.M\x19\ \xf4>k\xe2\x17\xb2\x89\xdb\x18\x04Qx)\xf0)\xba\ w:\x84\xac\xd2=}\x1b\xb4-\xf0\x08\xfa\xe4A,\ l\xbf\x98<\x805q;0\x0d8\xa2t\x19\x0a\xac\ v'\xd3^8\xe6A\x10\x85mH\x5c\xaf\xe1\x19k\ \xe2\x15y\x04m$\xac\x89\xb7\x00\x01\x12\x5c%a2\ 0\xbb\xef\xc3c\xb6@\x10\x85_\x00S\x94A6\x02\ \xd3\xac\x89\xb5\x8f\xa4\xc2\xb9\xb1\xafjt\xeb\x02\xce\xcf\ kW\x82(\x5c\x08<\xa64\xef\x03\xce\xb6&>\x5c\ y\xd0\xcb\xba\xbbHO\x9b\xfc\x01\xe0\xd6\xbc\x93w\x18\ \x0c\x8c\xad\xd1\xa7\x12\x1e\xe75\xacO\x01W\x91|@\ \x1b\x0e\xdc\x05tG\x8a}\xb7\xc0\xe2\x94\x81\xe7\xe79\ l4\x1b\xee\x07\xba\x0d9{$a\xbeK\xd8\x00U\ \x0apG[\xedX\xdb\x0e\xbc]\x94\x90\x8d\x865\xf1\ o\xc0sJ\xf30$\xa4\x06z\xaf\x809)c.\ :\x9e\xbe>'\x9eF\xdc_\x12\xee\xac\xfcQ\x82n\ \xbf\x7f\xa3\xd2y\x8b5\xf1\xe6BEk\x02\xac\x89\x0f\ \x22\xa1p\x12\xc6\x06Qx1\xf4\xac\x80+\xd0\x83\x88\ \x97\x8a\x15\xad\xa9x\x15\xdd-\xde\x04=\x0a\x98\xa6t\ :\x04|T\xb0PM\x835q\x07\xf0\xa5\xd2|5\ \xf4(`\xb2\xd2\xe93\xdf$F?\xc6\x07\xca\xf3\xb6\ \x0aG\x94\x9cKhS:\xadk\x90P\xcd\xc4z\ \xf4\x98\xe2\x92\x12z\xba\xa9\x0c|\xd3(\xa9\x9a\x05k\ \xe2}\xc0\xcfJ\xf3E-\xe8\x91Y\x87O\xe0\x13D\ a+~\xf9:\x80\xd3<\xfb\x0d\x0f\xa2\xd07\xe2<\ \xea,~\x1a\xdaI^\xe5cZ\x803\x95\x97~\xf3\ \x14\xe0;\xe4\xbe\xaf(\xb4\x00\x7fd\xe8\xbf\x19\x98T\ \xa3\xcf\xaf\xca\xf3\xd1%\xe4\xa22\x09Z\x101\x10\xa1\ \xcdeh\x09\xc9\xc7'\xa1\xa1\xb7\xb2M\x86z}V\ \x22=\x95\xf4_\x81jOJi\x8d\xff\x07\xa4)\xc0\ \xd7\xb2\x0f\x04\xa8Y\xed\x12\xa0\xb9\x90Z7@\x03\x09\ \xea\x5cJ\x08-%\x09Y/'\xfb3\x86*\xcf\x0f\ \xb4\x00\xbf+\x8d\xa3<\x07/\xe3oGJ\xf8_r\ \xfa\x1aa\x9f~g)\xcf\xf7\xb4\x00\xbb\x94\xc63\x82\ (\x1c\xeeB\xc94\x9c\x83\xbf\xbd\x18\x89\x10\xa0\xd2\xd0\ \x05\x9c\x8a\xbfR}\x14\xa0]\xa1\xfd\xdc\x02lu\x83\ \xf4\x9dD\x09I\x91\xadI\x1b9\x0b\x8b+\x88B\xdf\ \xbe\x7f\xd7\x99|\xad\xfef+\xfaao[\xc9\x9a\xf8\ \x10\xfa*\xd0\xf2\x04\x03\x09W\xa2{\x81\xf6\xca\xaf\xae\ %\x0d\xa6\x07Qxb\xf125\x153\x95\xe7;\xad\ \x89\xf7U\x14\xa0\x9d\xfb\x87!\x94\xb7\x01\x89 \x0a\x87\ #,\x93$\xac\x87\x9e}\xff5r\xf1\x91\x84;\x95\ \xe7\x03\x01s\xd1c\x80\x0f\xc1)\xc0q\xed4cw\ \x99\xe3\x09\x0c(\xb8L\xd7<\xa5y\x17\xf0=\xf4\xb6\ \xfc\xaf\xa0\xbb\x94\xc7\x92nV\xfb9\x1eDO\xc0\xac\ \xaa\xdcstO\xca\x9ax\x07\xba1\xbc\x0c\x98U\xa8\ x\x0d\x84\xa3\xf2\xdd\xaf4\x1f\x01\xde\xa8\xfc\xa7\xef\xaf\ \xba4e\xdcg\x9dQ\xe9\xd7p+u\x15:\x9bl\ \x855q\xb7\xbd\xeb\xa5\x00G4\xf8Ly\xb1\x15x\ \xddq\xf8\xfa3\x1eB.z\x92\xb0\x1fx\xb2\xfaA\ \xd2d\xe6#W\xe4I\xfe\x7f*\xb0\x0c\xa1\xaa\xe5A\ '\xb0\xa5F\x9f.r&c\x1ci{YJ\x97\x05\ .\xf0\xeb\x86\xc6\x11z\x14};\x94\x11\xea\x99v\xef\ v\x5c\x10D\xe1\x04\x84|\xa1e\xb8\xbe\x01&\xf5\xbd\ \xe4\xd5,\xfb\x1387\x91\x80\x12\xf0b\x10\x85w\xe4\ \x11\xb4\x11p\x17\x9d\xeb\xd0'\x7f\x18\xe1\x11\x1f\xb3\xb2\ \xd2hrc\x90\x94\xb7v\x96.#L\x8b%\xc7\x99\ &7\x1dx\x07=\xb9\x0bB\x93{7\xa9!\x95)\ \x1aD\xe1\x95\x08\xfd,-;\xb4\x01\xa1\xce\xd4:6\ \x17\x0ag\x8c\x17\x22\xac\x964\xc3\xfc\xb85\xb1J\xfa\ J\x0dn\xac\x897\x02\xb7\x92~6\x9f\x0al\x0b\xa2\ \xf0\xba\xb4\xb1\x8a\x84c\xb2mB\xecT\xda\xe4W\x92\ N\xfb\xf1&K\x1b\xe4\xae\xbd\x96\x0b\xdc\x80X\xdaF\ \x91\xa5[\x11\x0f4\x8f\xda9\xcb7P\xf6}5\xb2\ \xd0\xe5g\x03\xab=>\x5cF*8^\x046\x17D\ \x97\x1f\x8b\x1c\xcanA7t\xd5X\x89T\x90\x14C\ \x97\xaf\x12\xe4j\x849\x9efp\xaa\xb1\x1b)\x98\xf8\ \x14\xf8\xde\xb7\xc0\xc9Esc\x91\xed5\x13Ii\xf9\ \xe6\x12\x97\x03K}\x15\x9f\xa7d\xa6\x0d\xa9\x1a97\ \xe3\xabG\x90\xf4\xdb.\xe4\xe8}\x14\xf8\xc7\xb5\x95\x80\ \x13\x10\xc5\x8eB\xcaq\xb2\xd6\x1a\x1eD\xea\x032\xb1\ \xd6\xf3\x16M\x9d\x8cD\x5c\xf7\xd0?\x8a\xa66\x00\xb7\ [\x13\xff\x99\xf5\xc5z\xcb\xe6\xc6#{=\x8dX\xdd\ Ht \x04\xce\xdc\xb5\x0au\x9d\xf1\xad\x89\xb7\x22\x85\ \x0b3\x81\x1d\xf5\x8c\x95\x11{\x81{\x11\xdeo]\x85\ \x1a\x85\x95\xce:\xc35\x05!\x5cN\xa7\xf8\xab\xb52\ r\x90z\x05X\xd3\xafJg\xfb\x22\x88\xc2a\xc0\xb5\ H\xf1\xf4D\xfc\xa91}q\x14\xa1\xb7|\x8e\xd4\x0b\ \xef.F\xc2\x1e4D\x01\xd5p+\xa3\x0d\xa9\x03\xac\ \x94\xcf\x9f\x8eX\xfc\x8aO\xefB\xac\xf8\x01\xc4u\xfe\ \x82\x94\xcfomt\xf9\xfc\xbf\xb20\x0f0\xf9v\xc4\ \xd5\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x03\xbe\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x03\x85IDATx\x9c\xed\x99I\x8b\x151\ \x14FO7.ED\x5c\xe7'\xb8\x10\x11q\xe1V\ D\x88{\x918\xcf\xf3\xd0\xce\x03N\xad\xb6\xdd\xed<\ +\xb6\x11\xdc\x9b\x8d\x88\x08\x22.\xc4\x9f\x91\xb5\x0b\x11\ q%\x8d\x8b\xa4\xa4\xba\xfb\x0dU\x95\xa4\x1eB\xce\xee\ =\xde\xbb\xb9\xdfWI*\xf7\x062\x99L&\x93\xc9\ d2\x99L\xa6e\x94\xb1\x17\x95\xb1\xa7\x07\x99\xc3\xd0\ \xa0\x06V\xc6^\x06\xce\xfa\x8f\xe7\xb4\x14W\x06\x91\xc7\ @\x0cP\xc6^\x05f?\xf9KZ\x8a\x0bm\xe7\xd2\ \xba\x01]\xc4\x17\x5c\xd1R\x9ck3\x9fV\x0d\xe8#\ \xbe`TKq\xa6\x8d|\xa0E\x03\x94\xb1\xd7\x80\x93\ \x15\x7f>\xa6\xa58\x912\x9f\x82V\x0cP\xc6\xde\x00\ \x8e\xd7\xfc\xdb\xb8\x96b$E>e\x92\x1bP\xf3\xc9\ \xcff\x12\x18\xd1RLGLi\x06I\x0dh\xf8\xe4\ gs\x178\x9c\xca\x84d\x06(co\x02\xc7\x22\x85\ \xbb\x0f\x1cLaB\x12\x03\x22\x8b/x\x08\xec\x8fm\ Bt\x03\x12\x89/\x88nB4\x03\x94\xb1\xc3\xc0M\ \xe0H\xac\x98]x\x0a\xec\x8eeB\x14\x03\xbc\xf8\x09\ \xe0P\x8cx\x15x\x0e\xec\x8ca\xc2ph\x80\xd2\x93\ oK<\xc06\xe0\x89\x1f;\x88\xa0\x19\xd0\xe2\xb4\xef\ \xc6\x14\xb0]K\xf1\xa7i\x80\xc6\x06x\xf1\xb7\x80\x03\ McDb\x8a\x00\x13\x1aM\xa1\x88\xe2\x9f\xe3\xde\xf1\ !l\x02^(c\xe75\xf9sm\x03\xbc\xf8;\x84\ \x8b\x7f\x0c\xec\x04\x0e\x02\xb7\x03c)\x1a\x9aPk\x09\ \x94\xc4\xef\xab;\xd0,\x1e\x03{\x8b]<\xe2[D\ \x03[\xeb,\x87\xca\x06\xf8$\xef\x01{\x1a$V\xa6\ \xebaF\x19;A\xf8\x86\xfa\x06\xd8X\xd5\x84JK\ \xc0\x8b\x7f@\xb8\xf8\xfb\xf48\xc9i)\x8e\x02\xe3\x81\ c\xac\x07^U]\x0e}\x0d(\x89\xdf\x15\x98\xd8]\ *\x144\xbe\x070\x168Ve\x13z.\x01/\xfe\ \x11\xb0#0\xa1\xda%m`\x1f\xa1\xa0\xefr\xe8:\ \x03\xbc\xf8'\x84\x8b\xbfM\x83z^Kq\x0a\x18\x0d\ \x1c\xbb\xefL\xe8h@I\xfc\xb6\xc0\x04&\x81\xa3M\ \xcf\xec\xbe9\x1az_\xd0\xd3\x849\x06x\xf1\xcf\x08\ \x17?N\x84v\x96o\x93_\x0a\xcce=\xf0\xb2\x93\ \x093\xf6\x80\x92\xf8-\x81\x03F\xef\xea*c\xcf\x03\ \x17\x03\xc3\xcc\xd9\x13\xfe\x19\xe0\xc5\xbf\xc4\x9d\xaaBH\ \xd6\xd2V\xc6\x9e\x05.\x07\x86\xd1\xc0\xe6bf\x0e\xf9\ \xc0\xb1\xc4_\xf7\x9bW2\xfce\xea\xd5\xc00\xffL\ \x18\xf2\xeb\xe2\x05\xe1\xe2[\xbb\xd6\x8aiBq\x06\xff\ o\xc4\x03h)F\x81\xd0e\xa6\x80[\xc5\xa6\xf7=\ \xd0\x85\xb6/4\x01\xb4\x14c\x84\x99\xf0\x03x]\ \xec\x01K\x80\x8f\xc0\xe2\x9aA\xce\xf8\xa710\x94\xb1\ \xc7p]\xa9:\xfc\x00Vk)\xbe\x95\xdf\x02K\x81\ \x0f\xc0\xa2\x8aANi)\xae\xd7\x1c8\x09\xca\xd8#\ 8\x13\xaa\x14w?q\xe2\xbf\xc2\xdcs\xc02\x9c\x09\ \x0b\xfb\x04\x19\xd1R\x84VmQQ\xc6\x1e\xc0u\xa9\ z\x99\xf0\x0bX\xa3\xa5\xf8R|1\xa7\x18R\xc6.\ \xc7\x99\xb0\xa0C\x80i\xdc\xd16\xb4\x83\x93\x04e\xec\ \x1e\x5c\xcf\xa2\x93\x09\xbf\x80\xb5Z\x8a\xcf\xe5/;V\ \x83\xca\xd8\x15\xc0{f\x9a0\x8d\xab\xe5\x1f\xc6I7\ \x0d\xca\xd8\x1d\xb8\x0a\xb6lBG\xf1\xd0\xa3\x1cV\xc6\ \xae\x04\xde\xe1L\x98\xc6\xdd\xc6<\x8d\x9bn\x1a\x94\xb1\ [po\xb7a\xe07N\xfc\xa7N\xbf\xed\xd7\x0fX\ \x05\xbc\xc5\x95\xb3Sq\xd3L\x8b2v\x03\xae\x91\xb3\ \xae\x9b\xf8\xaa\x81\xe6\xc7J\xaam\xfe\xe7\xdc3\x99L\ &\x93\xc9d2\x99\xc4\xfc\x05\x93\xc5R\xfb\xd7u\xe4\ \xdc\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x22\xf6\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x0b\x8ezTXtRaw prof\ ile type exif\x00\x00x\ \xda\xb5ZYv\xe3\xb0\xae\xfc\xc7*\xee\x12\x08N \ \x97\xc3\xf1\x9c\xbb\x83\xb7\xfc[ %\xc7cb'\xfd\ \xec\x8e%k A\xa0P(\xc8M\xe3\xff\xfe;\xe9\ ?x\x05\xe3<\xf9 )\xe6\x18\x0d^>\xfbl\x0b\ v\x92\xd9\xaf\xb2>\xd9\xf8\xf5\xb9^\xfe8\x85\xef7\ \xc7\xe9r\xc2\xe2\x90\xc3\xd6\xed\xaf)\x1e\xd7\x9f\xc7\xf9\ 2\xc0\xde\x14\xec\x85\xab\x81R;N\xd4\xdb\x13\xf9\x98\ \xc1\xa6\xbb\x81\x8e\x89\x9cZd\xb1\xd3\x8f\x81\xf21\x90\ \xb3\xfb\x04\x1f\x03\x94\xbd,\x13s\x92\xeb%\xd4\xb1\xb7\ \xfd\x5cI\xda\x7f\xa4\x1f\xf5<\x1a\x8e\x8b\xef\xbe{\x81\ \xf7z\xc0<\xce\xda\xe1\xd8\x19|Zg\xb7\x01N\xff\ \x98\x5c\xc1N\x5c\x9f\x16\x17\xe2\x22\xec;\xe7\xd7\xe7\xe9\ \x138\xe4\x99\x9f\xcc\x95Ut\x1f\x95\xcb\x1e\xbf8~\ \x17\x14\x17\xf7q\xc2\x81[g\xc6\xcb\xf6\xe9q\x0e\xcf\ \x9dO\xcb\xc5W3\xbbv\x99\xf9\xe6xLl\xef\x97\ s\xfe\xcd\xd9\x13\xcd9\xf6\xea\x8a\x8fpi<\x16u\ \xf1\x8e\xee\xe0\xc2\x0a\x97\xbbu[\xc4[\xf0\x17\xb0/\ \xeb\x9d\xf1N\x04\xf46\x84\xbc\x9bf*\xde\x8d3[\ x|\xb2\xe7\xce\x85'\x8f\xb5m\xdc`\xa2\xb7\xc3\x0a\ \xb6\xd66\x04J\x8f%'6\xdb\xe6\x0c!N^\xdf\ <\xad\xb8\xec\xbaK\x08fCx5r\xf6b\x0b\xaf\ y\xf3\x9a\xaeq\xc2\xc4\x9dq\xa5e\x0c\xc6\x0a\x05\xd2\ \x8f\x7f\xf1~9\xd0\x9c\x0ayf\x93.\xbe\x82]V\ \x1d\x0e34r\xfa\x89\xab\x10\x10\x9e'\x8e\xc2r\xf0\ \xf9\xbe\x7fi\x5c\x1d\x22\x18\x96\x9b\x13\x16XL\xddC\ \xd4\xc0\x07\xb6\x14Gn\x05\xda\xe1\xc2\x80\xed\xce5\x96\ ~\x0c\x00\x17a\xee\x00c\xd8!\x02&\xb2\x0b\x1c\xd9\ \x88\xb5\xc2\x0c?&\xc4\xa7`\xa0d\x9d\xb7\x15!\xe0\ \x10l\x87\x95\xd6;\x17\x11\x9cdun\xdc#\xbc\xae\ \xb5\xc1\xee\xc3\xe0,\x04\x22 \xb1\x04\xa1\xc9\xae V\ Jl\xc0\x8f\xf8\x04\x0c\x95\xe0\x82\x0f!\xc4 !\x85\ \x1cJt\xd1\xc7\x10c\x94\xa8\xe4W\xc4\x89\x97 Q\ D\x92d)\xc9%\x9fB\x8aIR\xa2\x94S\xc96\ ;\x90c\xc81KN9\xe7R0i\xc1\xc8\x05w\ \x17\x5cPJ\xb5\xd5U_C\x8dUj\xaa\xb9\x96\x06\ \xf84\xdfB\x8bMZ\xa2\x96[\xe9\xb6\xbb\x0e\x9e\xe8\ \xb1KO=\xf72x\x00J\xc3\x8f0\xe2\x90\x91F\ \x1ee\x02j\xd3M?\xc3\x8cSf\x9ay\x96K\xd4\ \x98vX\x1f\xde\xefG\x8d\xcf\xa8\xd9\x15)\xbdP.\ Q\xc3\xad\x22\xe7\x10\xact\x124f\x88\x98\xf5\x8c\x88\ \x8bF\x00\x80\xb6\x1a3\x93\xd8{K\x1a:\x8d\x99\xc9\ \x16Y\x11,\xac\x0c\x1a\x9c\xce\x1a1D\xd0\x0f\xb6a\ \xf2%v_\x91\xbb\x89\x1by\xff\xa7\xb8\xd93r\xa4\ \xa1\xfb\x17\x91#\x0d\xdd\x8b\xc8=\xc6\xedI\xd4\xbaV\ \x9bf\x1c\xad\x08i\x1a\xaaS\x8dC\xfa\x81O\xa6\xc1\ \x85\x0e\x9c\xc7\xb6\xcd\x1a'\x8e\x16\x91\x9ee\xb4^\xdd\ \x1c!\x8d\xd9{\xad\x22\xb3z\xc7\x13[\x0a\x05\x1b\x9d\ \x0b\x17\xeb\xbd\x18\xc8q\xd6m\x8dH\xee\x1al\xedH\ \xa1.\xa01\xb6X\xa6\xafp\x11\x9c1r\xcb=\x08\ K]\xf7\x925\xc5\xa6b\xb1\xdc\xe1\xf6.H\xf8a\ \xbb'\x9a)\xec\xa9\x02w\xdd\xb6\xecau\x1b:\x15\ %\x8cP\x82M\x013\x81\x87B\x11\xfc\xf3e\xb64\ \xba\xb8V\xf5\x86\xc1\xb8\x01\xdb\xee\xb1\x06l\xad\x8eW\ Q\xf9\xe6\xd7\x19\xba=5\x03\xac\x80\xad\xa5\x04\x1e}\ \x22v\xb3K\xc4hN\x86I\xdf\xd9Em\xa4\xf9\x9d\ \xc9\xa9\xb8Q\xb2\x97*\x03>\x0b]\xd3\xabOp\x8f\ \x1a\xbb\x0c\xc2}0\x95`\x90\xdd\xc3|\xd9\xbaO\xdd\ \x9cY\xa6\xa6\x8b\xa5I\xb6\xa1\x88\xf3a*\xadh\xe9\ \xf5\xd8.\x83\x969\xf0\xcb2\xf5\xe5\xb9\x07ci[\ \x8b\xe5\x5c\xec}\xcf\xb9\xf7\xbe\xa5\xa7\x16\xff\xe8\xdaG\ \xcf\xd2\xef\x5c{\xe3\xbfQ\x5c\xc3\xd2\x86Y\xc6&\xef\ \xe7\xe8u\x8e\xdcg,@\xfehs\xe6\xe8\xaa\x8b\xa3\ \xf7\x8es\xdcfGf\x00\xbb@i)\x9c\xa4\xa0\xf2\ \xb7\xce\xa1dv\xd4\x90\xa8\xb9I\x8e\x1e\xe9\x98\xe1S\ \x1f8\xd4\x9c\xf6\x9e7\x0c[\x12R\x9c\xd7t&G\ \xa4t\x9d\xdd\xd5\x81\x131\xae\xe5N\xdb\x10\xfe\x81\x09\ \xab \x8b9\xcdZg\xe9`\x11\xb9\xba5\xe5y\xde\ \xda\x91\xf7\xf9r+F\xd1\xbc\xc5\x9d.\xcfJ}\x96\ \xb5\xc2\xc0\x86\x14\x848(\x19y.\x15\x09\xe9\x91\ \x91\xae\x80\xe5j\x09\xdd \x14\xb6\x0e\xa5\x8esgH\ 3\x027\x82\x14\x8a\x90\x1f\x11\xf3\xc8\x90Y\x8eu\x8d\ \x94G\xbd\xe1n\xcb\x13\xa5^\xba\ \x03\x1f\x9d{aH4\x0e)\x0f'\x06\xe8\xa4\xd6\xe0\ \xcf\xd9\xd4#\xfe\xa0\x9a\xce8\xea\xb2L^^\x04\x1e\ \xd8\xcd\xca\xba\x98I\xbd\xc0\x89NQ\x02*n\xea=\ \x10b\x85\xe8\x9aR\xa7/#(~\x10f\xa0G\x8b\ \x99\x8d+\x04\xd5,\xf4D\xbe\x80\x87\xaa\x1b-l\xf4\ \x04\x80}\xd1\xea\xc2\xcf\x94\xb8p\x05Q(\xc0Q\x8f\ \xb5Y[\xdbP\xbc\x94\xee\x87\x14\x98]P\xae\x8b$\ _P\x8eli.\xa0\xc2T\xe9m\x11b\x99.!\ \xd9\xf7\xbeywK\x8f'vh\xc3\x04\x90>@=\ }\xc1\x1ee\xc6ThY\xeb{;\x08\xbe5\xefc\ i\xd9\xa6\xd1\xd2\x9eiT\x97\xda\xf5\xe4X\xb1:\x8b\ @\xf9\xc8c\x7f\xb8\x0au\xe4t\xd5\xd4|\xe8\x17W\ \xa1\xfa\x1d\xaeB)\x08=\xd8 @m\x1dP\x22\xd3\ \xa2*R\xb5=\xa1\x08\xdea6\x5ca\x16\x05\xfb9\ d\xa55\x0e\xc8\xd0\xae;\xa4\xf0\x01\x22N\xc4(\x80\ \xc0!\x1bM\x07|P\xa8\xba\x7f]\xaa\xf6\x96\xbe\xa9\ erUq\x15y\x97\x8a\xbb\xa1\xb7+\xee\x82\x9eV\ \xda\xeaO\xec\xb9#L\xca\x8a\xcf\xc2\xa4>{AO\ 3\x08\x99\x9e\xe2\xf0SJ\xc0}^\xd2L\x15^\xaf\ 8by\xf1\xa4\xa6\x14`\x86\x96u\xfb\x87Y\xe3\x83\ $\x99\xcd\x86<\xe3\x22d\x0f\x86D9\xec\xb9.*\ o\x15D\xa5I\xb28\x07\xca\xc8\x8d1G\x85T\x12\ dD\xb6`\x1b\x10/\x0c\x96\x1c\xa2*\xa0\xf65(\ ]\x8f\xfa\xce\xa0\x0d\xa9\xab\xcf\x0a\xba\xcb\x1a}\xa8\xaf\ !\xe8\x81\x13\xf9\x08[\xd5i{\x0d\x90m_!\xdd\ ;\xc5%\x03U\x82\xa2\xd2\xbd*$\x0b\x9cA'\xf5\ #\x17&\xfc\x89\xde\x810(\x02Td\xec\x1dWy\ Y\xb0`\xc3PWp]\xacH\x98\x92\x0e\x0c\x09\x8f\ \xf2\x84\x9d\xe8\x07\xfa\x02\x0b+\x00\xda\x1a~.\x02W\ \x9a\xbe\x10\xf8RRJ\xe0\xb4\x18\xbc\x1e\x0c\xae\x04\xce\ \x1b\x02f{\x0a\x9d\xcbT7\xf9\x81\xd5\x01A\xc8\xc1\ \xd9*\xab'#\x9c6c\x82.\x9c22\x85\x0e\xd7\ \x95\x9abCS\x09\xb7\xd9\xe5\x5c\xe4\xa1\xb40\xe0\x96\ \x82\x8c2\x80\xd4\xa1\xc2*0\xb5A\x0b\xf3\xbe\x98\xd2\ \x22\xfb\x0f\xaa<\x04\xe2f\xca%\x10\x17Sn\x81\x18\ _\xa1\xfe\x10\x8a\xd0\xc7\x88\x88?\xcaU\xa9\xbe \ \xb6f\x0fG\xeeP\x9co\x0d\x87\xec^\xc9\x07x*\ \xa2\x9c\xaa\xbc>\x92\xb7h\x8e\xd3\xaau\xdbn\xa8\xea\ \xabT\xbbDRw\x90\x11_|\x00%\x9e\xa1q\xa1\ \x8fG:\x90_\xc8\xa2\xb0\xf2.%\x05~\x84\xa5 \ \x13'+8\xea!\xc8l\xc4<\xa0\x05\x80\xecGQ\ \x07E\xf1\xc0e6\xc3\x02\x97\x11\x03d\xa4\x18\x0c\xa4\ \xb6&\xe8\xe6\x9fx\xe2)-\xa8\x96\xda\xc4@\xf3\x15\ /<\xd2\xc2\xb7\xecM/X\xe1cR\xa0'\xacp\ \x9d\xbd\xd7\xb9\xfb-\x1d\xd0\x03\x1f\xbc?\xdc\x0d\x11\xd0\ \x15\x13\x1b-\xcd\xd4ZPS\x90\x10@\x81\x1b\x88@\ Xm\x92y9$}\x8d\xf9lH\xb1s\x11\xa9C\ \x13\x85\xc2\x98\xc1\xbc\x9a%\x96\x19f\xaa\xb7\x0eyj\ \xd1\x1c\xff\xd4\xfe,\x16AVo\xa2Z4\x05\x229\ \x88*_\x88\x8e\xee\x99n\x11]\x1bp=\xa42\x84\ 2:\x8d\x90\x10 \x1b\x08;{\xd5n\xc5f\xe5\ \xc3\x0bM\xd1\x22\x0e\x9d\xe3`\xa9\xf2=\xc9\xd9\xb1\x1f\ \x10-qZF\x82\xecI\x16p\xf1\xa4\x8a\xea\x0cT\ \x1b\x12\xbe\x95HW\xfcsO?\x14_\x08$\xad\x1d\ '\xd3A_\xbe\xe0:\xfd-`\xb3\x1d\xe5g\x02\xe9\ sy\x04\xc1~\xa7g\x90oW\x8a\x06\xa9\xf9\xa6D\ \xa2\xaf1\xdf\x1f\xf2\x99L\xa2C'\xbd\x94I?J\ \x93CF\xd1\x9b:Je\xd4\xb7\xf5\x8f\xde-\x80?\ \xd5?\xf2w\x85\xee\xb7u\x8e~\x02\xda\xbbu\x8e\xee\ \x0b\xddo\xeb\x1c\xbd\xdd\xfd\xfeP\xe7\xe8u\xed\xfc\xac\ \xce\xd1g\xcf\x1b\xcc\xdd#\xa4\xe9\xc5\xf0j\x9f\xa0j\ \xb3>\xb2~\xd6\x90\xf3\xab\xb6\xf3Y\x83H/:D\ \xb4\xef_\xe4\x8a\xc8<\x15\x86\xd7\x80\xa1\xbf+\xa3\x0d\ \x18\xfa\xbb2\xda\x80\xa1\xbf+\xa3\x0d\x18\xfa\xbb2\xda\ C\xd2\xdf\x95\xd1\xcb\x07Q\xef\x22\xe7\x168\xf4\x149\ _\xd4oo\xa8\xff@\xce\x11\xce~G\xfe@\xceO\ \xd5\x8c\x87\xb5\x06\x95\x93[\xd4\x07\x03\x9eST\xa1\xbf\ ~$Z\xa4\xdc\x98>}\xbc\xf3\xea\xe9\x0e}\xf4x\ g\xcc\x1bQ\x84+yH\x5c\xaa\x88\xde\x93EOD\ \x91>\x1d\xb8\x120\xf4\x99(z= \xfdA\x12\xdd\ \xc8\x04\xfa\xd5\x93\xe3\xfd\x90\xf8\xa6\xcb\xa3'm\x1e\x84\ \x80-\xd2*N\xd71\xb41\x06\xf6Zw\xc3+\xf7\ \x94\x13\xe5+I/\x1a\x9c\x1eExI\x8f]\xfd\xcf\ M=\xa9\xd6M\x05\xfa\xdf\x04\x84\xba{M\xdf\xda\xbc\ \xcf\xdd\x82\xbc4\x9c\xa3\xca!E\xc4=W\x22\xaa\x1a\ \xe8_(\x11\x1d\x92\xfe\x85\x12Q!B\x7fQ\x22\xd7\ [z<\xe1~\xd5\x8f\xd0\xf1\x13\x0e\xfe\x95\x048\x00\x9c\ \x98\xc9\x05xe\x04\x04\x1e\xd0n\xce\x83A\x91oN\ [\x9ba\x8e\x82\x90rM\xff_?\xd4\xc1O=\xd3\ \xff\x00\xa9\xfd\xdb\xbb\x87q\x03\x99\x00\x00\x01\x85iC\ CPICC profile\x00\x00x\ \x9c}\x91=H\xc3@\x1c\xc5_S\xb5\x22\x15\x07+\ \x888d\xa8N\x16DE\xc4I\xaaX\x04\x0b\xa5\xad\ \xd0\xaa\x83\xc9\xa5_\xd0\xa4!Iqq\x14\x5c\x0b\x0e\ ~,V\x1d\x5c\x9cuup\x15\x04\xc1\x0f\x1077\ 'E\x17)\xf1\x7fI\xa1E\x8c\x07\xc7\xfdxw\xef\ q\xf7\x0e\x10\xeae\xa6\x9a\x1d\xe3\x80\xaaYF2\x16\ \x153\xd9U1\xf0\x8a.\x08\x08`\x00\xb3\x123\xf5\ xj1\x0d\xcf\xf1u\x0f\x1f_\xef\x22<\xcb\xfb\xdc\ \x9f\xa3W\xc9\x99\x0c\xf0\x89\xc4sL7,\xe2\x0d\xe2\ \xe9MK\xe7\xbcO\x1cbEI!>'\x1e3\xe8\ \x82\xc4\x8f\x5c\x97]~\xe3\x5cpX\xe0\x99!#\x9d\ \x9c'\x0e\x11\x8b\x856\x96\xdb\x98\x15\x0d\x95x\x8a8\ \xac\xa8\x1a\xe5\x0b\x19\x97\x15\xce[\x9c\xd5r\x955\xef\ \xc9_\x18\xcci+)\xae\xd3\x1cF\x0cK\x88#\x01\ \x112\xaa(\xa1\x0c\x0b\x11Z5RL$i?\xea\ \xe1\x1fr\xfc\x09r\xc9\xe4*\x81\x91c\x01\x15\xa8\x90\ \x1c?\xf8\x1f\xfc\xee\xd6\xccON\xb8I\xc1(\xd0\xf9\ b\xdb\x1f#@`\x17h\xd4l\xfb\xfb\xd8\xb6\x1b'\ \x80\xff\x19\xb8\xd2Z\xfeJ\x1d\x98\xf9$\xbd\xd6\xd2\xc2\ G@\xdf6pq\xdd\xd2\xe4=\xe0r\x07\x18|\xd2\ %Cr$?M!\x9f\x07\xde\xcf\xe8\x9b\xb2@\xff\ -\xd0\xb3\xe6\xf6\xd6\xdc\xc7\xe9\x03\x90\xa6\xae\x96o\x80\ \x83C`\xb4@\xd9\xeb\x1e\xef\xeen\xef\xed\xdf3\xcd\ \xfe~\x00w\x1fr\xa9\xe5*\x1e\xe2\x00\x00\x0f\x9ci\ TXtXML:com.adobe\ .xmp\x00\x00\x00\x00\x00\x0a<\ x:xmpmeta xmlns:\ x=\x22adobe:ns:meta\ /\x22 x:xmptk=\x22XMP \ Core 4.4.0-Exiv2\ \x22>\x0a \x0a \x0a \x0a \x0a \x0a \x0a\ \x0a \ \x0a \x0a \x0a \x0a \x0a \ \x0a <\ /iptcExt:Registr\ yId>\x0a \x0a \x0a \x0a \x0a \x0a \x0a\ \x0a \ \x0a \x0a \ \x0a \ \x0a \x0a \ \x0a \ \x0a \x0a <\ rdf:Seq/>\x0a \x0a \ \x0a \x0a<\ /x:xmpmeta>\x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a\ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a\ \ \x0a\xe0\ \xe0T\xe2\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\ \xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0e\ \xc4\x00\x00\x0e\xc4\x01\x95+\x0e\x1b\x00\x00\x00\x07tI\ ME\x07\xe5\x06\x02\x07\x22 6\x87m\xd7\x00\x00\x05\ \xb0IDATx\xda\xe5\x9b\xcfo\x1bE\x14\xc7?\ \xde\xac\xed\xd8n\x9a\xb4\xa5T\x90f\x01\x11\xf1K\x82\ \x16\x0ep\xe0\x92\x1e\x90\xb8\xb0H\x1c\xf8q\x01\xed?\ \x80\xc4\x09\x8e\x1c\x11\xb7^\xe0\xb8=\x22qb%$\ \x90\x0aD\x15HH\x08AUP\x1aP)]\xa0\x15\ !4M\xf3\xc3q\xd6v8\xf8-\x19&\xb3N\xdc\ n\xec]\xf3$\xcb\xfbcvv\xdfw\xde\xfb\xce\x9b\ 73\x05D\xbc \xb4\x80\x11\xc0\x22Y\xee\x9426\ \xb0&\xd7\x9a\xc0\xba\xfc\x8f\x00-\xa0\xed\xbbND\x9f\ \xc5\x0b\xc2\xe7\x81\x87\x81)\xa0\x08\x1c\x90\xe3\x12\xb0\x22\ \xc5\xde\xf1]\xe7l\xfcLA\x1et\x80\x07\x80\x1a\xb0\ \x0c\x5cKx\xc7I\xe0\x0eQ\xf6\x12P\x01\xea\xc0\xaa\ \x80P\x94:Jr\x8e\x02\xd4\x0a\xd0\x96_E\xa9\xb3\ n8\xd7\xa5\xaa\x1c\xafk\xf7*\xc0\x93@\x038\x05\ <\x0e\x1c\x96_M\x1aeK\x1a\xd6\x96\xe7_\x02>\ \xf5]'\xb2\x95\x8a\x1e\x04\xee\x06~\x97\xc2\x8b\x86\x0f\ )\x01G\x80\x0d)o\x0b\x18\xd7E\xd1\x18\x80\xb2\xbc\ (VfU\x94\xd8\x94\x8f\x19\x952u\xf9\xaf*`\ \x96\xb5w\xda\xc0\x09\xb9\xbe\x06\x9c7\x803\x05\xdc%\ \x16z\x008\xaa(_P\x1b[\xca\x7f\x08\xbc\xe5\x05\ \xe1\xac\x0a\xc02p\x1cx\x8f\xfc\xcbz\x82\xf2\xb1\x8c\ \x02\xef\x02\xa7-\x00\xdfuB\xe0\x02p\x83\xe1\x10K\ \xb8\xa8eP^\xb5\xe6\xd7T\xc2[2\xf8W^\xc5\ \x16\xe5\xed.e\x9a\xc0e\xdb\x80\x9c*g\xc4*\x16\ \xa4\xb21`\x1e\xb8\x1f\xb8G\xfcy^*k)d\ UR\x08-T\xccnCH\xb0&\xefjJ\x1d\x0d\ )S\x96\x16+\x01\xe3\xf2L$\xf5\xac\x88\x9b\x22\xf7\ \x90\xe7\xb6\x84?\x8e\x01\xaf\xcb7\x16\xe4\xd9$i\x0b\ o\xfd\x07\xa1\x08\xf8S+8\x0d\xcc)\xe7\x17\x81+\ R\xee\x1b!\x9c+\xca\xf3U\xed?R>\x1a\xf1\xcb\ H\xc82\x06\xaam`uUI\x04\xb8\x86B\xaaz\ \xaf1!\x8dtQxlj\x17\xe5#!\xd4\xafu\ \x0bX\xd5\xce\x17\xa4\x05\xbf\x02\xfe\x02n\xf8\xaes-\ \x8b6\xef\x05a\x19\xb8\x09\xbc\x02\xcc\x00\xf7\x19\x8am\ )\xc7\xbf\x01?\xab\x00l\x1a\x5c\xe0\x0b\xe0\x92\xef:\ \xe7\xb2\xee\xf4\xbe\xeb4\xbc \xfcQ\xe2\x93\x93\xd2`\ u\x89[\xaa\xa2|[\x5cu\x11\xf8\x08\xf8\xd8\xd2X\ \xb1f \x8a\xcc\x8b\x17\x84E\x01\xe1*\xf09\xf0-\ \xf0\x83\xb4r(\x8d\xfb\xb7(\xfe=\x10\x00\x81\xef:\ \xbf\xda\x1as\x1e\xd2\xea\xae\x03\xb6\x17\x84\xc5A\x84\xb6\ {T\xbe\xa0}\xdb\x05\xe0\x03\x89\x04\x8f\x8b\x05\x94\x81\ \xcb\xe2\xf7\xdf\x01\x0b\xb1+\xab\x00\x1c4\xd4\xbf*\xe8\ \x15\x858\xb2h\xfa[\xda\xf9*\xf0\x99:\xc6\xf1]\ \xa7\xdd-`\x88\xa5f\x00\xa1\x22\xfeS\xcek@\xd0\ My\x1d\x80qC\x97T\xee\x12Ie\x95\x0fJ^\ \x10\xda\xbd\x84\x8c\xb1\x8ci\xa3.5\xd0\xc8\x93\x1c\x12\ \xa6\xef\x19\x00\xdb\xa0l]\xc2\xe3v\x8e\x00X\xd4y\ a\xaf\x00\xc4\xb1@\xae\xc5w\x9dV/\xe5-\xcd\xdc\ \x1b9\xf2\xf5T\xb8\xc9\xcaqc\xf7\x15\x80h\x80-\ m\xefg\xfd\xbb\x01`\x8b[D\x832s\xdfu\x9a\ \xb7\xd2\xbf\xa7\x05@\x13h\x0e*\x0c\xee\x85\xcd\xd3\x00\ \xc0\xee\x02B\xae\x89nW\x00dN`3K\xa3?\ 1\xff\xbeY@<\xd9\x91\x99\x9c`?\x94W\x01\xb0\ $\xea\xcb[\xd8\x9b:\x096\x06`\xeaV?|}\ /\x00l`\x9e\x96\xdao\x92+\xf4\xcb\xdc3\x17\x09\ \x8a\xe2\xed,\xb9\xc0\xd0\x92\xdd\xed\x00`\x0f\xc0-2\ \x03\x80\x9d&1\xea\xcayAX\xd0\xaf\xf5\xdb\x22\xd4\ 8 \x9e\xa2Ve\xb4\x0f\x16`IO`\x0f\xd2\x05\ \xe2y\xbdq\xed\xfeDZ\x03\xa1\x84\xc8\xae(\xb1G\ %i\xd0\xb3\xdf\x12\xa3\xde\xa631\xa2\xe7\x04G\xd8\ \x9e\xc7Kc\xfc\xbe\xa5\xb9\xc3\xc0#\xd0x}@\x94\ 0\x0eXN\xe3\xe3\x12\x88-^]R\x1fdO\xa0\ \xfa]\x9d\x9d\xd9\xd4\x15\xd2\xc9\x13\x9a\x00h\xf7\x9a\xbf\ \xdb\xef^\xe0&;g\x87\xeb\x86k\xb7e\xfe2\xf2\ $\x0b\xca\xeb\x16\xd02\x10\xder\x1a\x00\xc4\xcazA\ \x18/\x9c\xc8L\xf6\xd9\xd2\x8e\xf5)\xb0\xf5\x94, \ \x96\x1a\x19\x9bcT\x01\xa8\x18\x00\x88\xd2J\x87\x09\x11\ \xde\x1ct\xe8\xdbk\x98{0\xe5\x98\xbfE\xc6D\xcf\ \x09\xea\x0b\x8b\x9e\xfa?%D6\x0c\xb1@q\x17\xb3\ \x1e\x19&\x00\x1a\xc8\xd21\xb5\xfb\x8a\xbb\xad\xbd\x0cl\ \xf2\x0e\xc0*;W\x8a\xfe\x22\xe1j\x12\x7f\xb4\x87\xc9\ \x02,C\xc46Mg-\xa01\xb8Q\x19=k\xec\ ~\xab\x00`\x18\x0d\xda\x09f>\x14\x19\xe4\xdd\x12\x22\ '\x80\x17L\xad\xec\xbbN\x14\x03\x92W\xff\xff\x17\x00\ /\x08+\xc0\xbdt\xd6\x00\xabr\x0c8\xea\x05a5\ I\xc9<+\xaf\x06BG\x80I\xe0!\xed~\x09x\ \x1a\xf8\xd2w\x9d\xd9.\x01N\xee]`\x82\xceV\x93\ G\x0dq\xc0\xb3\xc0\x8c\x17\x84\x93jk\xf7k\xeen\ \xbf\xa5\xe0\x05\xe14\xf0\x0c\xf0*\x9dU\xd6\x93\x09e\ g\x817\x809\xdfu\x1a\x0c\x89X\xc0#\xc0st\ \xd6\xffW\xbb\x94\x9d\xa1\xb3\xcc\xf4T\xde\xfd^\x07\xe0\ e\xe01\xe9\xef\xf72N\x7fb\x18L_\x05`Z\ \x86\xc2-\xb6wz$\xc9U\xb6w\x80\x0c\x85\xd8\x92\ \xa4h\x09\xe1\x8du)\xbb\x06\xfcAg\xf5\xf5P\x01\ \x10\xcf\x08wS\xfe:\x9d\xcd\x94M\xd2K\x93g\x06\ \x80Q:\x1b\x0d\x93d\x89\xcefJ\xb2\x98\xd0H\x83\ \x03\xcevQlI,\xe4\xb0\xf0\xc4\x16\xe6\x1d\xa5\xb9\ \x06\xe0\x0cp\xda\x90\x0c\xd9P\xa2\xc1\x9a(?Gg\ \x1b\xcaP\x010\x07\xbc\x0f\xbc\xadX\xc2\xa6r\x1c\x89\ %\xfc\x04\x9c\x93\xdf\xd0\x88\x1a\xdaV\x807\x81\x17\x05\ \x98QIx\xccKb\xe4\x13\xe0\xbcl\xb3\x1d\x1a\xf9\ \x07\xd9+\xcc:\xc8\x87\x86\xb1\x00\x00\x00\x00IEN\ D\xaeB`\x82\ \x00\x00\x05\xde\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x05\x90IDATx\x9c\xed\ \x9b[\x88UU\x18\xc7\x7f\x0e\x11\x12\x12\x12\xd1\xe3B\ |\xea)$z\x88Ab\x12%/\xb5LM\xecn\ +*\xb0\x8b\x966:\xe9\xa8hjy\xc9n\x92\x15\ \xd8B*\xd2\xb2\xc8U\x9a\xb7\xac|\x88\x88\x88\xf2!\ \xa2\xa7a=\x84\x0f\x11\x11!\x83\x0cC\x0fk\x9f\xdc\ \x9e9\xe7\xecu\xbe\xb5\xf7Fb\xfeo\xb3g\xed\xf3\ \xdf\xff\xff\xfa\xd6^{\x7f\xdf\xb7a\x1c\xe3\xa8\x1d\xc6\ \xf9\xe5\xc6yU\x03\xcft\xe3\xfc\xb4Ncz\xaa\xbe\ \x88f\x18\xe77\x00\xaf\x02_Ui\x82q\xbe\x0f\xf8\ \x22\xe3\xe9m7\xaeV\x032\xf1\x9b\xb2?\xa7R\x91\ \x09\x99\xf8\xcf\x80I\xc0d\xe0xvl\x0cj3\xc0\ 8?\xc8E\xf1\x0dL\x05\xbe1\xceO)\x91g\x06\ \x17\xc570\x098b\x9c\x9f\xd9<~BY\xc4\x05\ \x175\x08<\xdfa\xc8\x10p\xab\xd5j(\x91g\x06\ p\x98K\xc5\xe71\x0c\xcc\xb7Z\x9dh\x1c\xa8<\x02\ \x22\xc4\x03L!,\x87)\x09\xedu@]&\xdc\x0b\xec\ k6\xa1\xb46\xb9\xc8\x96\xd8N\xe8\xb7Z\xed\x8a\xe0\ \x99KX\x0e\x13\x85<\xef\x00\x8f6\xf2\x97\xa5u\x89\ e[[J$\xec\xcc\xb6\xd8\x22\x9e\xa3\xc0b\xe4\x91\ \xf00\xb0\xd78\xdf\x03\x15\xf4\x0a7}\x13 \xc1\xaa\ \xc8v9\x0d\x1cD\x1e\x09{\x80\x15\x95\xf4\x0a\x1b\xe7\ 7\x01\x85O}m0\x0a,\xcb\xd2tE<\xa9&\ l\xab\xa4W\xd8j\xb5\x11(|\xeeo\x83s\xc0\xd7\ \x91<\x0e\xf9\x8dq\x04\xf8\xb9\xb2\xef\x05\x84&\xfcN\ \xc8\xfd\xff\xd6\x05\xcfQ\xba7a\x04Xj\xb5\xfa\xb0\ \xf2/F\xb2|\xc0`\xc4\xd0s\x04\xf1\xbf\x0ayb\ w\x87\x11\xc2C\xd1\x01\xa8\xef\x93\x99\x22\x13\x92\xc4\xe7\ x\x8aL\xb8@x78\xd48P\x8b\x01\xd0\xd1\x84\ R\xc4\xe7x\xda\x990Lh\x9er\xf9\x83\xb5\x19\x00\ -M(U|\x8e\xa7\xd9\x84\xf3\x84Od\x8e5\x8f\ \xad\xd5\x00\x80\xacx2@E\xe2s<\x0d\x13F\x08\ \x8d\x14\xa7\xab\xe0\x11\xc18?`\x9c\xbf\xbe\x06\x9e\xd9\ Y\xaf\xf18\xc6\xd1\x06\xff\x02a\xfc\x9ah\xed\xdb \ Q\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x05\xa0\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x05RIDATx\x9c\xed\ \x9b]h\x1dE\x14\xc7\x7f\xbdlC\x88\xa1\x84RD\ \xab\x0c\xc5/J\xd1V\xaa\xf6\xa1H\x05)\x08U\xb6\ \xf5A\xe8\xa3Sk\x1f\x14Q\x14\xa9R\xa3\x04\xabR\ \x8a\x14E\x10\xd3\xe2\x82PD_\x84\x01\xb5\x88\x16\xd4\ \xf8\x81\x16\xc1\x12\xeaK(e(1\xa0\xd4\xa05\x86\ \xeb%\xf80{\xcd\xcdf\xef\xee\xc9\xdd\xb9{\xef\x8a\ \x7f\xb8$\xec\x9e=;\xf3\xdf\x993\xe7\x9c9\xb3\x8a\ \xff(\xb4\xb1C\xc0K\xc0\x1e`\x01h\xb4\xfcm\x00\ g\x80\xc7\x82\x9e\xb5\xb0\xfb8\x06\x1c\xc8\xb8\x7f+0\ WI\x02\xb4\xb1\x0a\xb8\x1d\xa8\xc5\xbff?\x82\x96k\ {\x05\xaavV\x8e\x00m\xecf\xe0s`\xc4\x83\xba\ \xa1\x9a\x07%e\xe3)\xfct\x1epC\xa5j\xb8\xd2\ \xa7\xb2*\x120\xe0SY)6@\x1b;\x0c\xec\x03\ \x86X4T\xab\xe3\xff\x7f\x01ND\xa1\xfa]\xa8.\ \xad\xcd\xaf\x03?'\xae\x8d! k\x95\xf0\xa5\x1dC\ \x1b\x1b\xe0\x8c\xd6\xf6\x0c\xb1)\xe06\x09\x09\xda\xd8/\ \x81;\x13\x97\xb7D\xa1:\x9b\x90\xfb\x13Gx\x16.\ \x941\x05v\x90\xddy\x80\x1b\x80\xfb\x84\xfa\xa4\xa3\xb6\ .\x90\x99/\x83\x80uB9%\x94\x93\xb6\xd9\x0ad\ f\xca @\xfa\x0e\xe9\x97\x95\xea\x1b#{\x14\xcc\x03\ G\x0a\xd9\x80\xd8\xdf>\x00\xdc\x08\x0c\xb2\xd4\x13kz\ h\x0a\xd8&Pw.\xfe\xe5a'\xcb\xfd\x80e6\ n\x9f\x02n\x8e\xdb\xd6\x8ay\xe0l\x14\xaa\x8bE\ W\x81\xf7\x90\xcf\xdd\xef\x19\xa9%2\x12\ \x14\x99\x02^\xf3\xf3\xbdB\x11\x02f\x91\xef\xd3\xf5-\ :& \x0a\xd5,p\xcac[z\x82\xa2\x8e\xd0\x03\ \xc0~\x9c\xa1\x19n\xa3\xaf\x8c2\xb9Thc\xaf\xc5\ -\xafC,~\xec\x06n\xfaNF\xa1\x9a.\xa3V\ x/\xf0\xae@t4\x0a\xd5a\x81\xbe\xefq\xa7E\ Z\x91V+\xbc\x07W\xc6\xd7\xce\x01\x9b\x07v\x97\xe1\ \x07H\xed\x84\xb4\xf2C\xaa\xef\x05\xb2\xbd\xcfA\xe0`\ \x19\x04H<2\x90\xd5\xf6\x82\x9c\x80\x0d\x02\x99\xf5e\ \x100\x01|\x9b#s\x1e\xf9\x86\xa7t\xa4H\xb6\xfc\ \x06\xbb\x1e\x0dF\xa1\xaakc\xef\xc1\x19\xcbfv\xb6\ YG\xdc<01\x1e\xaf*\x12\xa4\x8d\x80\x87\xb4\xb1\ \xc9\x03\x13\xa2\xbeu\xdd\x08\xfa\x866\xf63\xfcE\x8e\ \xa5\x1c\x98\xf0\x0d\xc9A\x081\xaaH\x80\xd4\xa8\x8aP\ E\x02^C^T\x99\x8b\xca\xd9\x00\xf8\xf7 \xc4v\ \x167E\xd2p\x8c\xfc\x04\xea\xb9J\x12 \x816\xf6\ 8n\xe5\xc9\xc2\x1b\x95;;\xbc\x02<\x8esw\x9b\ \x15e\x0b,=>\xff\x1d\xf0\xf4?\x19\xb9Y\x05+\ s\x10|\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x04H\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x03\xfaIDATx\x9c\xed\ \x9a=\x88\x14I\x14\x80\xbf-\x9aa\x19Et\x11O\ D\x8a\xe3\x10\x111\x90\x0bT\xd4\xdc\x9f\xa0@\xe1X\ \x8fKl\x04\x03\xf1\x079V\x13ET\xe4\xfcc\x13\ 1\x5c\xcbL\x059\xce\xc6\xc0\xe0N.\xb8\xcbD\x8c\ \x0cDdiDDd\x11\x11\x19\x96a1\xa8nw\ \x1d\xa7{\xba\xa6\xab\xb7fv\xe7\x83\x86\x99\xfay\xfd\ \xeaU\xd5\xab\xaeW\x05\x03\x06\x0c\x18\xb0\x88\x19\x0a\xa3\ \xb8\x0eL\x00\x0a\xa8\x01\x0103\xe7i&\xcf;\xe0\ \x92V\xf2\xb6\x1fU\xabA\x00\xd7\x80\x03@\x1d\xd3\xf8\ 4=\xc0\x18\xa4\x0e,\x03\xd6\x01\x13a\x14o\xf2\xa0\ ge\x08`\xa7e\xf9\x8d\x15\xe9\xe2\x05\x81\xe9a\x1b\ jU(\xe2\x8bt\xa8\xdb\xd0\xacB\x11_\x08\x8c\xa3\ \xb3\xc1\xb6|O#\xb0\xef\xd1\x057\x02>Y\xd6i\ T\xa1\x88/\x04\xf0\x9fE\xf9\xcf\xc0\xf3\x8at\xf1B\ \x00\x9c\xc64l;f\xbdO\x99iy\xa6\x81\x8bZ\ \xc9\xc9y\xd6\xb1R\x86|+\xe0\x820\x8a\x05\xb0\x1b\ \xd8\x07\xac\xc7\xf8\xa9\xa7\xc0\x1d\xad\xe4\xd3\xbc\xba\x0b\xc5\ \x007\x80\xa3m\xb2\x9a\xc0\x1e\xad\xe4\xdfYuEe\ Z\xcd/?g\xa4\x07\xc0\x96\xbc\x8a\x0b\xc5\x00\xcbr\ \xf2~\xc8\xab\x18\x00\x84Q<\x0c\xac\xc2|\xe6\xd6\xe6\ \xe6\xb5\xf9\x0d\xdf\xef\x16\x1b\xc0\x1b\xad\xe4tq\x9d\x9d\ \xb24'oy^\xc5 \x8c\xe2\x0d\xc0?\xc0\x9a\x92\ J\xbc\x0a\xa3x\x97V\xf2eI9\xdd\x90g\x80\xbc\ \xd1\x81\x00.Q\xbe\xf1\x00?\x01\xe7\x1d\xc8\xb1\x22Y\ \x01\x86s\x8at4\xc0:\x87\xfa\xfc\xe8PVQ\xd2\ N\x16y\xa3\x03\xd1\xa9\x80%>\x9cji\x03\xf4\ \xfbJP\xda\x00\xfdN\xa7\x80N=\xf1\x13m\x11\xf4\ \xff\xee\xae\xa3\x01\xc8\xe9h\x01L9T\xc6G\xac \ o\x05H\xf33\xa7\x88\xc0\x84\xc4]\xd0\x04\xae8\x92\ eC''\x9e\x1b\xf7\x0c\xb4\x92\xb7\xc2(\x9e\x04\xb6\ \x01K\x98u\x8c\xb6\xfe\xe1\x81V\xd2&\xb6\xe0\x8a\x22\ A\xdd:\x19#=\x00\xd0J>\x06\x1e;Tj>\ )b\x80\xccQ\xb2\x18V\x01X\xe0\x06(\xf2!\x97\ \xf99\xbc\xe8\x0d\x90n\x877c\x82\x0a\xc3\x14w\x80\ yK^\xbaUN\x99\x02\xfe\xd4JVq\xa6P\xce\ \x00a\x14\xef\x07\xeea\x7fBd\xcb-\xe0P\x05r\ W\x14(3\x92\x95!\x80\x93T\xdfx\x80\x83a\x14\ \xaf\xac@\xee\xaa\x02e2\xa3BAA\x01.\x10\x98\ \xe8\xcc\xfbn*\x87Q|\x048\xd1\x92\x5c\x03V\x17\ \xa8~8\x19\xe9)M\xe0\x03p3`~z\xbf\x14\ \xc9f\xe6\x1c\xddw\xd6\x08\xed\xa7\xc1\xf2\xbe\xd8\x0e'\ \xce3\xaa@\xf4\xbdnN\x87}\xf1;\xf0\xc2\xa1\xbc\ '\xc0e\x819\xf2\xeay\xb4\x92\x1f\x81Q\xcc1^\ Y\xa6\x80Q\xad\xe4\xb4\x00&\x1d\x08,\xc24]:\ \xc0\x14\xad\xe43\xccRZf\xd46\x81\xdf\xb4\x92\xaf\ \xc0\xcc\xff\xb3\xb8\x8d\x09\xb4c\x068\xaf\x95\xfcPV\ \x90V\xf2.\xe5\xa2\xcf\xc7\xb4\x92\x8f\xd2?C\x00a\ \x14\x8f\x00k\x99\x0d\x1e\xa4\x8eq\xeeo[\x9a\x98\x86\ 7\x80\xb7Z\xc9\xd7\xddj\xdcJ\xb2*L\x00\x07-\ \xab\x9e\xd3J^\x98\x9b\xd0\xb7\x87\xa3a\x14\xd7\x80;\ \xc0\xfeNe\x13\xaek%\xc7Z\x13{~\x09\xcc\x22\ 9\x86\xfb\x15\xf8\xab@\xf1q\xcc=\x88\xef\xe8[\x03\ \xc0W#\x8c\x02\xf7s\x8a\x8d\x03cY\x1b\xb1\xbe6\ \x00|3\x12n\xb7\xc9\xbeJN\xe3\xc1\xdc\x15\x0e\x80\ \xe3\xc0Vf\xaf\xcb\xb6~!vs\x9f\xb0(\x0d\xe0\ J\x12\x96\xeb\x9a\xc41\xfe\x01\x9c\xc28\xe0\xd3Z\xc9\ \xf1N\xf5\x86\xc2(\xbe\x08\x9c)\xf3r\x074\x80\x1d\ \x9d\xae\xb3\x14!\x8c\xe2\x9d\xc0\x94V\xb2\xd0e\xae\x00\ \xd8[\xf6\xa5\x0e\x18\x06~\xc1\xdc\xeb)\x85md\xda\ \xf5\xe1h\x19\xbc\xf8\xa3*\xe7\xb6-^\xf4\xe8\xa5U\ \xc0\xdb\x08\xe8\x95\xed\xb07\x03\xb8\xd8^\xba\xc0\x8b\x1e\ \x02\x07\x9e\xd7\x11\xff\xfbx\xa9\x00\xc6\x80\x7f1AB\ \x1f\xd3\xe1#pY+\xf9\xd0\xc3\xbb\x07\x0c\x180`\ q\xf3\x05\xa4X\xddA\xaae\xd0\xae\x00\x00\x00\x00I\ END\xaeB`\x82\ \x00\x00\x06\x5c\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x06#IDATx\x9c\xd5\x9bm\x88UE\ \x18\xc7\x7f^dYD\x16\x11\x91\xa5d0\x08\x91\x10\ \x13\xe9K\x86oXfVSiY\xa8\x8de\x16\x98\ \x99\x85\xa5\x08\x11,}\xc8\x17\x22L6\xa5\xecm\xb2\ 7*\xb5\xc9\xb2\x22K\xcb\xa2D\x82\xc4\xa4\xfa\xb0\xc8\ |\xd8BDDd\x91\x90K\x1f\xe6\x5c\xb9\x9e\x9d\xb3\ \xf7\x9e{\xe6\x9cs\xfd\xc3e\xd9\xf3\xcc\x99\xe79\xcf\ \x99y\xde\xe69\xc3h\x01\xca\xd8\x19\xc0j`\x12\xf0\ \x1f\xf0\x03\xb0EKa[\x99\xafL\x0cK{\x832\ \xf69\xa0\x07\xa8\xc4H\xa7\x80;\xb5\x14GB\x08V\ \x14R)@\x19;\x1f\xf8b\x88!\xe7\x81\x85Z\x8a\ o2IU \xe2o\xb1\x11\xd66\xa0\x8f\x04>W\ \xc6>\xd0\xa2<\x85#\xad\x02\xa661\xa6\x03xO\ \x19\xfbx\x0b\xf2\x14\x8e\xb4\x0a\xe8\x8c\xfd\xdf\x0f\xecH\ \x98\xb7W\x19\xfb|KR\x15\x88\xb4\x0a\x88\x8f\xafj\ )V\x02\x9b\x13\xc6\xf7(c\xb7*c\xd3\xf2)\x0c\ A\x04\xd3R\xac\x076$\x90\x9f\x04\xdeQ\xc6\x0e\x0f\ \xc1+4\xd2* \xf1!\xb4\x14\x1b\x81U@\xd5C\ ^\x0a\xecQ\xc6\x8eH\xc9/w\x04]\x9aZ\x8aW\ \x81e\xc0E\x0f\xf9\x0e`\xbf2vTH\x9eY\x11\ |oj)v\x01\x0b\x81\x0b\x1e\xf2\x0c\xe0\x802v\ lh\xbe\xad\x22\x17\xe3\xa4\xa50\xc0m\xc09\x0fy\ *\xf0\xa32v|\x1e\xbc\xd3\x22\xab\x17H\x84\x96\xe2\ p\x0bp\xdaC\x9e\x80S\xc2\xc4\x94\xfc\x83#W\ \xf7\x14\xe5\x05\xb3q\xf1B\x1c\xe3pJ\xb8!O\x19\ \x1a!w\xff\xac\xa58\x0eL\x07\xfa<\xe418\x9b\ 0+o9\x92PH\x80\xa2\xa5\xe8\xc3)\xe1\x84\x87\ \xdc\x85\xf3\x0e\xb2\x08Y\xe2(,B\xd3R\xf4\x033\ \x01_\xba\xdc\x09|\xaa\x8c]Z\x94<5\x14\x1a\xa2\ j)N\xe3\x0c\xe3A\x0fy8.b|\xa2H\x99\ \x0a\x8f\xd1\xb5\x14\xe7p.r\x9f\x87\x5c\x01\xb6EE\ \x97B\x90V\x01\xbe075\xb4\x14\x17\x80{\x80\xf7\ \x13\x86\xbc\xa0\x8c}\xb9\x88$\xaa\xb4,MKq\x11\ x\x10\x7f:\x0d\xf0\x14\xf0F\xdeIT\xa9i\xaa\x96\ \xa2\x96NoL\x18\xf2\x10\xf0\x9126^\x87\x08\x86\ \xb6\xc8\xd3\xb5\x14\x1b\x80\xf5\xf8\xb7\xd8\x02\xe03e\xec\ \xc8\xea!w\x02\x1f+\ c\x17\xa5\x9d\xb7\xadm@\x1cQ:=\x07\xd7\x8f\x10\ G\x07\xf0\xae2\xb6\x99\xf3\xcbK\xb8bV@\x0du\ \xe9\xf4W\x1er\x07\xf0b\x9a\xf9\xb2*\xa0\x14\x05j\ )\x06\x80\xbb\x80O<\xe4Yi\xe6J\x9bj\x16\xbe\ \x05\x94\xb1\x1d\xc0h\xa0;\xf6\xbb\x1a\xf7\xc6\xab\x5c\xfe\ \x22:\xd2\xcc_\xba\x02\xa2\xf3B\x09\x5c\x85{\xa8n\ \x9c\x8f\xaf\xfd\x1dM:9}\x81S\x22\xb2\x16\x1bB\ l\x81*\xd0\x8b{\xd0\x10\xd0i\x06\x97n\x03\xa2\xf2\ \xd8\xdbY\xe7\x89p\x0c\xd7\xc0\xd54\x0a3b\xca\xd8\ \xbb\x878\x05\xea\xc5\x7f\xa2\xdc,\x06pJ\x9c\x1dy\ \x89\xa6Q\x88\x0dP\xc6\xae\x00\xb6\x03\xbb\x81\xfb\xe3t\ -E\x9f2v/p\xaf\xe7\xf6\x01\x5c.\xd0\x0f\xfc\ \x1b\xfd\xfe\x89\xfe\xf6\x03'\x81\xbe\xa8\xc6\x98\x1a\xb9\xdb\ \x00e\xec:\x9co\xae\x00\x0b\x94\xb1\x22\xa1\xa1\xf2%\ \xfc\x0a\x98\xa3\xa5\xf8%\x9b\x98\xc9\xc8m\x0b(c+\ \xca\xd8M\xc0\xa6:>\xc3q\x1d\xa6\x83\x10=\xe4a\ \x0f\xe9\xe9|$t\xc8%\x14\x8e\xea\xf9\xdb\x81u\x1e\ \xf2\xf2!\x0a\x9c[<\xd7\x16\xe4\xd9K\x10\xdc\x0bD\ \x81\xcb\x07\xc0c\x09\xf7\x8c\xc6\xf5\x0c\xf9\xb0\x0f\xf83\ v-q\xd5\x84@P\x05DA\xcd\x1e\xa0QV\xb6\ \xc6w\xea\xa3\xa5\xa8\xe2lA\x1c+\xf2\xea-\x0a\xa6\ \x80H\xc0\xfd\xc0\xfc&\xee\x9b\x08$\x151v\xe1,\ |=\xbaH^Q\x99\x90\xd5\x06T\x00\xa2\xa6\xa7\x03\ \xb8&(\xdf=\x7f{\xae\xaf\xf11\x88\x02\xa3m\x1e\ \xd2\xeah{\x05E\xe6\x15\xa0\x8c\x15\xc0!\xfc}\xc4\ \x17\x80\xfbp\xb5\xfe8\xe6)c'$\xcc\xbb\x03\xd7\ y^\x8fq\xc0\xe2V\x05MBV\x05t\x02?\xe1\ \x96t\x1cg\x81[\xb5\x14\xbb\xa3\xe2f\xdc\xc5UH\ v\x89g\x807=\xa4\xb5\xa1O\x8c\xd3N\x16\xef\xfd\ \xab\xe0\xdeL\x1c\xa7p\x01L}\xe5f\xabg\x9cR\ \xc6v%\xf0\xda\xca\xe0\xf0x\x120\xaf\x19A\x9bE\ Z\x05\xf8\x0a\x10qX`\xa6\x96\xe2\xb7\xd8\xf5\xbd\x11\ \xad\x1e]\xc0r\xdf$Q!t\xb7\x87\xf4l\x132\ 4\x8d\xb4\x0a\xe8\xc1o\xd0j8\x0eL\xd7R\xc4}\ y\xad\x1f\xa0\xd7s\xcf\xaa!\x96\xb5\xcf%\xceJ[\ \xf7\x1b\x0a\xa9\x14\xa0\xa58\x8b\xeb\xfb\xfb9F\xaa\xe2\ \xba=nj\xf0\xe1\xd4N\x06\x9f\xf9]\x8b\xeb#\xf6\ \xf1;\x82\xbf\x00\x1a,B(\xa5\x14\x91\x22\x92\ \xc3\x18E\x0f*\x8a\x14)J\xa5\x22\xb5&\xa0\x8cP\ \xc4\x8b\xc5?S\xf5P*\xb5H\xdbK=y\xc8A\ \x0f\x22TV\x0a\x13D\xf4`\x05u\x10\x04\x11\x0f\xf5\ \x10EQA\x11\x11\x092\x88H\x09!H)%\x84\ \xe0a\xdeKw7\xfb6\xfb~o\xf2\xde\xbe\xf7\x81\ e7\xd9\xfcf~\xbf\xef\xce\xce\xfb\xcd\xef\xf7\x02\x0d\ \xc78\xaf\x8c\xf3OI\xed\x93\x98\xce\xd4\xc4\x0d\xc0\x07\ \xc6\xf9#\x12\xe36\x080\x09L\x00\xf3\xc6\xf9\xe7\x8a\ \x1a\xb7A\x80\x8c\x09\xe0\xbcq\xde\x141j\x93\x00 \ \x10\xa1m\x02@\x88id\x11\xda(\x00\x14\x10\xe1\xba\ \xed\xf6\xc48\xbf\x0bP\xc0\x1e\xe0z`'\xb0\x83\xb0\ \x5c\x93\xaeg\xd2\xe7\xa2\x1f\xca\xcd\xc0+9\xef\xad\x03\ /Z\xadl\x9eqt\x01\x8c\xf3S\xc0,p\x10\xd8\ \x07L\x13\x82\xac\x8b\xa1\x22D\x11\xc08\xbf\x038\x0c\ \x1c\x05\x0ePo\xc0\x83\xc8\x15\xa1\x94\x00\xc6\xf9\xdd\xc0\ q\xe0e\xe0\xa62cU\xc0@\x11D\x02\x18\xe7'\ \x80c\xc0k\x84\xefvS\xd8$Ba\x01\x8c\xf3\xf7\ \x00\xf3\xc0\xde\x88\x8eUI\x8f\x08\x85v\x5c\xe3\xfc3\ \xc0\x02\xcd\x0d\x1e\xfa.\x91#\xad\x00\xe3|\x02\xcc\x01\ \xa7\xb7\xd1\xb1\xaaY\x02n\xdfr\xb7N\x83?\x0f\x14\ \xca\xb1\xc7\x9ce`\xc6j\xb52\xf4+\x90\x06\xff.\ \xed\x0b\xfe\x90\xd5\xeaG\xd8z\x0f8\x0b\xbc\xb0\xed.\ UGO\xf00d\x0f0\xce\x1f\x06.\xd0\x9e\xf3\xc2\ \xa6\xe0!G\x00\xe3\xfc4\xf0\x13!wo\x03\x03\x83\ \x87\x01\x9fn\xd7\xa6\xd7\xfa\xe0ap\xce~\x04x$\ \xd2\xe4W\x80\xcf\x81\xcf\x80E\xe0?\xe0*\xb0FH\ H\xd6\xd3\xd7\x19\xd9\xef2\xf2\xde\xeb~\xbd\x0f\xf8&\ g\xfe\xa1\xc1C\x9f\x00\xc6\xf9\x9d\xc0\xeb\xb9\xe1\x8c\xce\ 2\xf0\x06\xd0\xb1Z\xadD\x18/\x17\xe3\xfc\xea\x10\x1f\ f\x86\x05\x0f\x9bW\xc0K\x84\xb3{\x19>\x04NZ\ \xad.\x95\x1c\xa7\x0cY\xf0?l\xf5\x87\x1b\x02\x18\xe7\ '\x81\x13%&]\x03NX\xad\xde)1F\x0cF\ \x0e\x1ezW\xc0\xe3\x84\xe2\x85\x845\xe0i\xab\xd5G\ B\xfbX,1\xc2\xb2\xef\xa6[\x80gKL\xfcj\ \x8d\xc1g\x9b\xe1\x12a\xc3\xfb\xb9\x88q\x02\x1b\x85\x8d\ G\x85\x0e|j\xb5z[h\x1b\x83U\xe0\x12p\xb0\ h\xf0pm\x05\x1c \x14*\x8br\x99P\x0d\xaa\x93\ \x7f\x80\x87\xadV\xbfI\x8c3\x01\x1e\x12N\xde\xb1Z\ \xfd-\xb4\x8d\x82\xd5j\x89\xb0\xfcEd\x99\xe0}\x02\ \xdbu\xe0\x9ct\xe2q!\x13\xe0N\x81\xed\xb7V\xab\ \xbf\x22\xfaR\x0bI\xda\xb8\xb8Q`\xfbulg\xea\ \x01\xa6\x84\xb6\xdf\xc7t\xa4.\x12`\xb7\xd0\xb6\xd6\ \xcd/\x16\x09\xb2\xcb\x1f\x84K`\xe3I\xe8=~\x16\ \xb5m<\x09\xf2O\xb2I\x1d\xa1\x5c\x12\xe4I\x84\xe4\ \xd29v$\x84<:\xaf\xa80\x8c\x07\x22\xfbR\x0b\ \x89\xd5j\x8dP\xae*\xcal\xda$m4\xd9FV\ \xf8\x14Eh\x87\xcfF\xf4\xa5\x162\x01\x16\x84\xf6g\ b9R\x17\x99\x00_\x09\xed\x1f,s\x9b\xea8\x90\ \x09\xf0{\xfa\x90p\xce8_\xb6\x90Z\x1b\x09\x80\xd5\ j\x1d\xf8X8\xc6\x1e\xe0\x13\xe3|#\x1b)\xdd\xd9\ \xdc<\xbd\x8d\x88\x22\xec\x05\xbe0\xce7.9\xda\x10\ \xc0j\xb5H\xe8\xe2H\xb9\x1fX0\xce\xdf[\xda\xab\ \x0a\xe9\xcf\xe7\xe7\x90\x9f\x0d\x00n\x03\xbe3\xce\xcf5\ \xe5+\xb1\xa9;l\x9c\xbf\x00<\x19a\xec\x15\xa0\x03\ \xbcg\xb5\x92n\xb0\xdb\xce \x01\xa6\x81_\x80]\x11\ \xe7Y\x04\xfe$4GW\x09{M\xd6 \x85\xde\xbd\ '\xefu\xff\xcfY\x83\xf4}iE\x18\xf2\xef\x0f8\ Fs\x0a\x9eOX\xad\x9c\xd48\xefL\xdf\x01\xc4\x83\ 6\x89\x81\x02\xa4y\xc1\xf3\xc8\x93\xa3\xc6\x90[\xd5\xb1\ Z-\x03\x8f\x01\xffV\xe7N\xf5\x0c-k\xa5\xb9\xc1\ !B\xcd\xa0\x95lY\xd7\xb3Z\xfdJ\xb8\xf7\xbf\x15\ U\xe0~F*l\xa6\x22\xecGV7\x18kF\xae\ \xecZ\xad\ \x82\x8d\x0f\x86\xf6\x81\x9czd\xb1\xd3vCi7\xe4\ \xec:av\x03yMk\x0b)\xca\xed\x14J_\xdb\ v\xcc$\xae_\xd2\xafr\x1c\xe5\xfd\xe2\x87\xbf\xbd \ z\x8d1\x8e\xb3\xb6;\xe36|[g\x97\x03N\x7f\ \x0d\xb9\x8c\x9d0\xbf-.\xc4E\xd8w\xfb\x91\xb0{\ \x82\x80<\x8b\xd3v\xe3\x15=\xa2r\xd93/\x8e?\ \x80\x82\xc1\xe6q\xc2\x81\xfb`\x86\xcb\xf6\xe9q\xc3\xcf\ \x83O3\xc47#\xbbz\x19\xf9\xee\xb8a\xe3\x1e\xa7\ s\xfc\x8e\xd1\x22\x8d\xd1\xd7\xec\xb2\x0f\x08i\xd8'u\ Le\xee\xe1\xc2\x82\x90\xbby[\xc0G\xf0\xcb\xd8\x97\ \xf9I\xf8D\x02{+ o[\xdd\x0a>\xd5$c\ 1\xf60\xde4\x93\xcd0}n\xab\xa9p\xd1\xdbn\ \x05[k+\x80\xd2c\xd1\x89M\xb6\xba\x8d\x80\x93\xd7\ \x8f\x19V\x5cr\xcdE\x80Y\x01\xaf\xc3Q{\xf1\xc5\ \xccq\xd3\x1c\xae\x9a\x88\x81\x9b\xc1\x95\xd6\xc0\x98Q*\ \x90~\xfd\xc5\xe7\xa5\xa11\x94\xf2\xc6l\xf1\x12+\xf8\ e\x95\x84pC\x91\xd3o\x5c\x05@\xcc8x\xc43\ \xc0\xc7\xe7\xf1Gqu@\x90g\x98#&\x98\xb7\xb2\ L\x146;\xb7\x94Gn\x02\xedp!c\xbbr\xcd\ H\xdb\x0d D\x18\x9b\xe1\x8cq@`\x0b\xc6\xb1\x09\ f\x13k\xc5\x18\xc41\x02\x9f\x0cC\xd1:o\x0b \ 0\xcc\xb6\xc1K\xeb\x91!\x00'Z\x1d\x1b\xf7\x88\x99\ \xd7Z\xb6\xeb04\x0b@0\xd2H\x00Mr\x19X\ y\x08\x1b\xf8#>\x82C\x99\x1d{f\x0e,\x1c9\ q\x0e.\xf8\xc0!\x04\x09*~Y\x9cxa\x09\x22\ \x12%I\x8e.\xfa\xc81D\x89\x91b\x8a9\xd9\xe4\ \x8e\x9cB\x92\x14SJ9c\xd0\x0c\xcb\x19wg\ \x5c\x90s\xb1\xc5\x15_\xb8\x84\x22%\x96Tr\x05}\ \xaa\xaf\x5cC\x95\x1a\xa9\xa6\x9a\x9bm\xaeA'Zh\ \xd2bK-w\xd3A\xa5\xee;\xf7\xd0\xa5\xc7\x9ez\ \x1e\xa0\xdap\xc3\x0f\x1ea\xc8\x88#\x8d|A\xcd\xd0\ \x82\xf5\xc7\xe77)vL\x9a\xa2\x05\x0c=\ \x8c\x04b\xab\x86\xa3\x11\x82\x9b\x1a\xadm\x95D2K\ \x89\x95>\x93<\xe0\xd0-}\x9e\xd4T-\xa9\xa1\xdd\ \xd6\xcc\x81\x9aIO\x8a\xe6\xac\x99\xcfH\x83V\xe7\xa0\ \xcd\x0f\xd6\xd0?\xd2\xe6\x07[\xe8\xbd\x1a?\x10&>\ \x17\x1e\xfa\x980:\xc0\x13\xc6\xd0o\x94yB\x98[\ \x15\xbf\xe3\x0b\x9d!\xcc\x19\x83t\x9e.\xd3u\xcb\xdb\ \xa5\x95\xba\xa3\x0d\x9d\xe3\x8dx<\x81\x8e\x08\x7f2\xda\ Ct\xf2\x88\xb7\xb1#\xa1\xc4\xe1\xa9@\xc7\xd0\xa95\ \xd3\xf1\xd0\xfa\xb2\x0e\xe9s\xff\xaf\x95\xe8\xb3\xda\xff\xaa\ \xe6\x1f:A\xdf\xd6\xfc\x83e\xf4]\xcd\xbf\x96\x1c\xba\ \x16\x09}\xc0\xbf\x96\x09<\xf2\xdc\x14\x0a\x84\xfdZy\ \x9e\x16\x1ez^y\xce\x1a\xad\xa5M\x167GI[\ 5<\x1cv)\x0d\x12\x1d\xe0\xab\xc6l\xcd\x01\x0f\x95\ \xef[\xf5\xd5\xa9\xd3\xf7\xad\xfaR\x1d\xfa\xadV}R\ \xaa\xe8W\x91\xf9\xa0$\xd1\x9d\xc4|Q\x92hJ\xcc\ \x1f\x94$z]?>+It_\xe6\xfe\xb9$\xe9\ \xd3\xd1\x12\x99\x09\xe6v\xdd\xfeB\x8a\xa7\xad\x0e\x1d\xbd\ \xce[\xc1y\xa37\xf4\xbe\xf1=\xa7.\xf4}?\xbb\ \xf8E\xdf\xf7\xb3K[\xe8\xfb~v\xa9\x0a}\xdf\xcf\ .=\xa1\x8b\xa0\x9c\xd6\x93\xe7\xaf\x02\xe8i\xdb\x1b\x9f\ \xd7\xaeU\xba\x9ek\x0b\xfdEK\xa3\xeaB|\xa2e\ 9SK\xe8L\xcbrFO\xe8L\xcbr\xa6c\xa1\ 3-\xcb\x19=\xa1\x0fz\xa0_\xd5\x84\x1eZ\x96G\ 5y\xa5.?hA\x7f\xd1\xd2\xa8\xc2\xd0_\xb44\ \xba\xa53-\xcb\x99\x8e\x85>h\x8c\x7fU\x15:\xd3\ \xb2\x9ci.\xe8L\xcbr\xa6c\xa13-\xcb\x19\x85\ \xa1\xef\xde>^_>\xd2_\xb44*6t\xae\xa5\ \xe9\xf7\xcdiq\x17\xa4\xe7\xdb\xb7:cty)\xdc\ n_\x0a\xb7\xd6\x8b\xc9\x06^3\x8bs\xa2\xcb\x02\xc1\ :]?`\xdb\x19\x19\x5c1\x09U\xb5,\xbd\xe8\x8b\ \xa8\xa9=~fO\xf32\xa3`\xd9\xa9o9g\x5c\ \x9ajh\xb5d\x9d\x18\xbb*\x00M\xbaN\xc3\xa8\xe3\ \xee\xc2f\xfa\x8bW>:Gz\xff\xca\xa7\xc7;\xed\ K\xa6\xb6'\x15\x92\xfe\x9d\xcb\xf7\xac\xa3\x7f\xe7\xf2\xbd\ Q\xfaw.\x7f\xf6\x86\xfd\x04\xa7\x17\xa5\xe9{N/\ J\xd3\xaf\x9c\xbeQ\xbcw\x14\xa1\xc7R\xa7JZT\ ~7\xd6w\xe4q\xb8,.\xf9\xce\xb5\xd9\xb6\xbf\xbf\ \xce\xd6\xdf\xbd\xbcN2\x8c\xaef\xed\xe3\xd9:\x8a\x91\ 9\x1e\x84\x1d\xc3\x8c9\xde\xd0\xd7\xab\xf0\xa3xg\xd4\ C\xce)\x15\xe0\xda-\xb2D\xd7\xc5J\xe2\xec;U\ \x8c9Q\x06\xed\xc6\xd5\xda6.\xd6t\x19\x07\x96v\ {h&\xeca\xb1\xa3p\xb6\xdd\x0dz\x9eej\xf3\ \xf9\x99a\xb3DA\x03\x22\x98+g}\x81\x1f\x82\x89\ \x89Pr-\xea\x8d\x01\x8c\xb5j\x12\xda\x02\xc4\xf1\x1d\ F\x06\x19\x11:}moE\x01G,`\x15X\xc7\ }\xc5C\x01\x03\x8a(S\x83t\x8dA\x95\xcd\x03\x11\ _\xb46G]\x0fw=\x1c6\xaf\xebS\x87\x16=\ \xacO\xcd\xaaCO\x16\xa8r\x90hf8uM\x03\ \xb3\xb0\xdd\xa4\xe8Y\x97\x05y.\x91\xa1e1\xf3\xfd\ \xe4\x5c\x17I\xeb\x1d[\x8es\x05\xa4\xfb\x00\x00\x01\x85iCCPICC \ profile\x00\x00x\x9c}\x91=H\xc3\ @\x1c\xc5_S\xb5\x22\x15\x07+\x888d\xa8N\x16\ DE\xc4I\xaaX\x04\x0b\xa5\xad\xd0\xaa\x83\xc9\xa5_\ \xd0\xa4!Iqq\x14\x5c\x0b\x0e~,V\x1d\x5c\x9c\ uup\x15\x04\xc1\x0f\x1077'E\x17)\xf1\x7f\ I\xa1E\x8c\x07\xc7\xfdxw\xefq\xf7\x0e\x10\xeae\ \xa6\x9a\x1d\xe3\x80\xaaYF2\x16\x153\xd9U1\xf0\ \x8a.\x08\x08`\x00\xb3\x123\xf5xj1\x0d\xcf\xf1\ u\x0f\x1f_\xef\x22<\xcb\xfb\xdc\x9f\xa3W\xc9\x99\x0c\ \xf0\x89\xc4sL7,\xe2\x0d\xe2\xe9MK\xe7\xbcO\ \x1cbEI!>'\x1e3\xe8\x82\xc4\x8f\x5c\x97]\ ~\xe3\x5cpX\xe0\x99!#\x9d\x9c'\x0e\x11\x8b\x85\ 6\x96\xdb\x98\x15\x0d\x95x\x8a8\xac\xa8\x1a\xe5\x0b\x19\ \x97\x15\xce[\x9c\xd5r\x955\xef\xc9_\x18\xcci+\ )\xae\xd3\x1cF\x0cK\x88#\x01\x112\xaa(\xa1\x0c\ \x0b\x11Z5RL$i?\xea\xe1\x1fr\xfc\x09r\ \xc9\xe4*\x81\x91c\x01\x15\xa8\x90\x1c?\xf8\x1f\xfc\xee\ \xd6\xccON\xb8I\xc1(\xd0\xf9b\xdb\x1f#@`\ \x17h\xd4l\xfb\xfb\xd8\xb6\x1b'\x80\xff\x19\xb8\xd2Z\ \xfeJ\x1d\x98\xf9$\xbd\xd6\xd2\xc2G@\xdf6pq\ \xdd\xd2\xe4=\xe0r\x07\x18|\xd2%Cr$?M\ !\x9f\x07\xde\xcf\xe8\x9b\xb2@\xff-\xd0\xb3\xe6\xf6\xd6\ \xdc\xc7\xe9\x03\x90\xa6\xae\x96o\x80\x83C`\xb4@\xd9\ \xeb\x1e\xef\xeen\xef\xed\xdf3\xcd\xfe~\x00w\x1fr\ \xa9\xe5*\x1e\xe2\x00\x00\x0f\x9ciTXtXML\ :com.adobe.xmp\x00\x00\ \x00\x00\x00\x0a\x0a \x0a\ \x0a \x0a \ \x0a \x0a \ \x0a \x0a \x0a \x0a \ \x0a \x0a \ \x0a \x0a \x0a \ \x0a \x0a\ \x0a \ \x0a \ \x0a \x0a \x0a \x0a \x0a \x0a \x0a\ \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a\ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a\ \ \ \ \ \ \ \x0a \ \ \ \ \ \ \x0a \ \ \x0a|l1\x0b\x00\x00\x00\ \x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\ \x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\x01\ \x95+\x0e\x1b\x00\x00\x00\x07tIME\x07\xe5\x06\x02\ \x07$\x08Uhb\xab\x00\x00\x04GIDATx\ \xda\xed\x9bM\x88\x1cE\x18\x86\x9f\xe9\xe9\x19\xb3\x99\x8d\ q\xfc\x17\xb1\x0df\xc1\x10$9\xa8\x07O\x8axM\ C\x0e\xfe@\x0e\xd2'A0 \x08\x9e\xc5\x8b\xe4\x1e\ <\xb6\x07\xf1\xa2(6xP\x83 \xe4 \xf8s1\ \xe2O\xd4\x84\x8a\x11\xd1lv\xe3\xc6\xec:3=\xe3\ \xa1\xdf\xd6\xdeq~2\xee\xa6\xbb\xa7\xda\x0f\x86\x9e\xa9\ \xae\x99\xa9\xef\xad\xb7\xde\xaf\xea\xeb\xaa\x1a\x16Y\x10\x99\ \x1a\xd0\x06^\x00n\x06\x16\x81\xbb\x80&\xb0\xa6j\xaf\ \x84\xbew\x22\xfd\x8e\x8b]V\x93\xe3\x0f\x03\xf7\x02-\ \xa0\x0e\x0c\x00G\xfe>\x14D\xe6I\xe0\xfd\xd0\xf7\xba\ \x8ee\x00\xb4\x81\xc3\xc0~\xe0z\xf5\xbc\x0b42\x9d\ \xbd\x13x\x13x6\x88\xccA\xdb\x00\xd8\x09<.\xc7\ \xebb\x04\x99kj;\x80c\xc0\x11\xdb\x00\xd8\xa7\x9e\ \x07\x88\xf5\xaa\x8d\xa9\xdb\x04\x9e\xb6\x0d\x80G\x80[\xe5\ tw\x8a\xc6\xf5\x803\xb6\x89\xe0\x83r\xde\x01\xae\x9b\ P\xaf\x0f\x5cD\x15m\xb2O\x81\x1f\xaf\xc2\xf9.\xf0\ \x07\xf0\x89m\x00\x9c\x02\xce\x01\xdf\x8d\xb9?\xc8\xbc?\ \x07\x9c\xb6m\x08\x9c\x16\x0b\x1c\xf5t#3\x11J\xa3\ A\x0c\xac\x02\xef\x02\xefY\xc1\x80 2\x0d\x80\xd0\xf7\ >\x03\xde\x01B\xe0u\xe0+\xe0\x97\xa1\xea\xe7\x81\x8f\ \x81(\xf4\xbd\xb35\x1b\xa6\xbf\xa1\xef\x0dF\x94/*\ *<\x0a<\x9f\xb9u\x14\xf86\xf4\xbd\x0f\x98\x10#\ mY\x1b,i^\xf0y\xa6\xf8 \xb0\x1a\xfa\x9e\xb1\ 1\x0a\x8cS\xfd\xb1\xe6X\xd8\xeb\xcd 2W-\xee\ 62\xa0-\xa5\xaf,\x00\x17F\x89be\x00\x08}\ /\x9e\xa5\xbe3\xc7c}[\x22\xd8<3\xa0\x1a\x00\ \xcc\xa2\xe8\xd6\x01\xa0Y^o\xccX\xef[\x0f\xc0,\ jn-\x03*\x0b\xc0\xb8ENe\x00\xc8\xc3\xf9\xaa\ ,\x86\xca\x0d@\x10\x19'\x8f\xb1^J\x00\xe4x-\ /\xba\x97\x0e\x009\xde/\xe0\xaf{\xa5\x19\x02\x05\xf4\ ~\xafT\x00\x14\x11\xfb\xb3\xf9\x02\xa7H\xe7\x82\xc8\xd4\ \x86\xcb\xf2fD\x19\x18\xe0(\x12\x14\xf2\x8c\xc2\xc9\xb3\ \xf7G\xf4n\x83\xe4i\xcd\xc2\xb8E\xcf\xb5\xb6`\x80\x1f\x80\ \xb7t\xdd\xaa\xe5\x99K\xf0\x80\xbb\x81\x1b\xa5W\xdd,\ \x03^\x93\x06\x1ces\x8alCb\xd2\xd7u\x1d\xf8\ Z\xaf\x9f\xb7\x81y.\xf9\xa5\xe4:\xc0%E\x85e\ 2YiW\x0e\xbd*\x85\x7fI=\xd3\x11(\x03\x85\ \xb7K\xc0\x19\xe0{\xe0|\xe8{[Mk\xff\x993\ \xed\x97\xd5\xf6\x7f\xaf\xe93\x13\x98\x05\xe0EM\x89\x1d\ i\xc3e\xe0#\x92\xc3G_\x02?\xa5GMl\xb1\ \xbf\x00\x19hTl\xfb\xee\xc2\x9f\x00\x00\x00\x00IE\ ND\xaeB`\x82\ \x00\x00\x03\xe1\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x03\x93IDATx\x9c\xe5\ \x9b\xcdk\x151\x14\xc5\x7fuQJ)\xa5\x14)\xa5\ \x94 \x22\x22\x22ED\x8a\x14\xa9\xad\xaf\xf5\xab:.\ \x5c\xb8\xce_\xe4B\x5cJ\xfe\x00\x17bD\xa5<\xeb\ G\x11\x11\x11\x11\x11\x11\x11\x91 EJ)ED\x5c\ \x88\xb8\xc8\x1b)\xa2\xcf\xc9\xcc\xcdL\x1e\x9ee_r\ 3\xe7\xf4d\x92{\x93\xe9C\x18\xda\xba~\xe02p\ \xc5d\xea\xa5t|i\xf4I\x06\xd3\xd6\x0d\x00\xd7\x80\ \xb3\xc0\x06\xb0h2\xf5Br\x0ci\x88\x09\xa0\xad\x1b\ \x04n\x00\x0b\xdb\xfe\xbc\x89\x17\xe1\xb9\xd48\xd2\x10\x11\ @[7\x04\xdc\x02f\xff\xf0s\xd2\x22T\x16@[\ 7\x0c\xdc\x01f\xba4KV\x84J\x02h\xebF\xf0\ \xe4\x8f\x14h\x9e\xa4\x08\xa5\x05\xd0\xd6\x8d\x02\xcb\xc0\xe1\ \x80n\xc9\x89\xb0\xa3L'm\xddN\xa0M\x18y\x80\ Q\xa0\xad\xad\x0b\xed\x17\x0d\xc1\x0e\xe8\x90_\x01\xa6*\ \x8c\x9b\x8c\x13\x82\x04\xd0\xd6\x8d\xe1\xc9\x1f\x10\x18;\x09\ \x11\x0a\x0b\xa0\xad\x1b\xc7\x93\xdf/8~\xe3\x22\x84\xbc\ \x03v\x01Jx\xfc\xfc\x9dpP8na\x14\x16\xc0\ d\xea\x09\xb0\x04|\x11~\x86Q`\xa5)\x11\xca\xbc\ \x04g\xf1\xbb\xbe!\xe1g\xd9\x04Zu\xe7\x0e\xc1\xcb\ \xa0\xc9\xd4*\xf1\x9cP\xfbt\xa8\xb2\x11\x8a\xe5\x84Z\ \xb3\xc8\xaa[\xe1\x98\x22\xb4\xea\xa8'H$C=-\ \x82T:\x1cK\x84u\xbc\x08\xaf\x84\xe3\xfe\x82dA\ \xa4'E\x90.\x89\x1d\xc5\xa7\xc71D\x987\x99z\ -\x1cWV\x00\xe8=\x11J\xa5\xc3\xdd`2\xf5\x08\ 8\x8d\xfc>a\x0c\xbfc\x94\xccE\xe4\x1d\x90#\xa2\ \x13>\xe1\x9d\xf0F\x22\x98\xb8\x03rt\x9c\x10c\xc7\ 8\x8ew\xc2>\x89`\xd1\x1c\x90#\xe2\xea\xb0\x86w\ \xc2\xdb*A\xa29 G'w8\x87\xbc\x13&\x80\ \xfb\xda\xba\xbdU\x82D\x17\x00\xc0d\xea\x01p\x1e\xf8\ *\x1cz\x02?\x1dJ\x8b\x10}\x0al\x87\xb6n\x01\ \x7fz4(\x1c\xfa#~:\xbc\x0b\xedX\x8b\x03r\ \x98L\xdd\x05.\x00\xdf\x84CO\xe2\xa7\xc3\x9e\xd0\x8e\ \xb5: \x87\xb6\xee\x0cp\x1d\xe8\x17\x0e\x1d\xec\x84Z\ \x1d\x90\xc3d\xea6p\x11\xf8.\x1cz\x12\xffN\xd8\ ]\xb4C#\x02t\xf0#b\xdc\xc2\xb1\x9b\x9a\x02\xa7\ \xf0S`@8\xb4\x03\x8e\x99L}(\xda\xa1v\x01\ \xb4u'\xf0+A\x0c\xf2\xf3&S\xefC:\xd5\xbd\ \x0c\x1e\x07n\x22\xbf\x0c\x96\x22\x0f5\x0a\x10\x91|\xe9\ =\x00\xd4$\x80\xb6n\x0e\x9f\x0f\xc4 \xdf\xaa\x92\x0f\ \xd4\x91\x0c\xcd\xe1\xff\xf3I&CQ\x05\x88\x9c\x09\xb6\ $j\x021\x0b\x22\xb1\xc8\x8b\x16D\xa2\x08\x10\xb9B\ ,Z\x17\xfc\xef\x8b\xa2\xbdR\x16\xdf\xc0\x93\x17?\x1b\ \x10\xcb\x05:\xb6\x8fE>\xed\x83\x91^>\x1f\xac\xec\ \x80\x1a\x8e\xc9\xd3=\x1c\x8d8\xe7k\xbb-R\xda\x01\ \x91\xc9\xa7}AB[7\x83'?,\xfb8\xf5_\ \x9b+sI*\x16\xf9-<\xf9g\xc2q\xbb\x22\xf4\ \xa6\xe84\xfe\x82\xf4\x88\xf0s4B\x1e\xc2n\x8aN\ \x01\x0f\x89C\xfe\xa4\xc9\xd4S\xe1\xb8\x85\x10\xf2\x12\x5c\ \xc3\xe7\xdf\x92h\x94<\x84\xdd\x14\xdd\x00Z\x80\xd4\x8e\ \xacq\xf2\x10\xb8\x0c\x9aL\xad\xe3E\xa8\xba9I\x82\ <\x94_\x06\xf3\x0f&\xca\xdc\xeaL\x86\ `\x85\x96\xe2\xd3@\xed\x05\xc74\x01\xca\xd8K\x81\x97\ \xe9\xee\xad\xfb0\x0e\x5c\xa4\xa5\xf8 p\xbbA\xd0\x07\ \xa0\x8c\x9d\x0f|\x0b\xcc\xac\xa8\x9fq\xdcvx\xbf\xa2\ \xf6K#\x8a\xff\x8e\xe0\x9f\xfc(p\x1d\xb0\x188\x0e\ \x98\x07\x1c\x05\x1c\x01\x1c\x19\xff\x7f\x14pt\x9c7\x0f\ X\x05\xecI\xb53\x03xS\x19{^\xe0\xf1w\x8d\ >e\xecB\xe0{O\xdes\xc0\x0dZ\x8a\xc9\xa2\x8d\ \xc6m~\x8d;9\x1a1\x01\xac\xd4Rl.\xdaf\ U\x88\x80\xcb=\xe9\xdf\x00\xab\xcbL\x1e@K1\x0a\ \xfc\xee\xc9\x1a\x04^U\xc6^X\xa6\xdd*\x10\x01\x0b\ =\xe9#Z\x8a\xf4\x19_\x14Y\xe4\x1dP$D\xc0\ \xc1\x9e\xf4\x89\x00m\xb7[=\x07\x0c\x09\x11~\xe1\xd7\ \xed\xdb\xcf\xd3\xc6 \xf0z\xac{\xf4\x0ci\xd56\xc1\ T\x80\xb6\xf3\xac\xa2\x01\xdcJ\xe8\x19\x09\xfdTG@\ ^; !am\xdc\xef\xec8\xed\xa08?J\x95\ \x9f\x02\xfe\xc3\x11\xbc\x17\xd8\xae\xa5\xd8Qv\x90\xfd\x9e\ \x0e \xcc\x16\xf8\x0283g\xd9\x01`c\xd9\x8e\x94\ \xb1\xaf\x01\xd7i)\xf6\x15\xad\xeb\x9b<\x84Y\x01\xf7\ \xe1t\x891\x9ca\xb4\x07\xf8\x13g\x1f\x84\x10\xb2\x8d\ \x18\x06>T\xc6\x1eR\xb4b\xd6\x16\xe8z\x05h)\ &\x00\x95NW\xc6F\xb87>\x07x\x1c\x08\xa5\x1d\ \x9e\x84#\xe1\x5c-\xc5oy+U\xb9\x02\xbc\xd0R\ Li)&\xb4\x14\xbb\x81{\x027\xbf\x00\xf8(\xf6\ e\xe4B\x96\xe5\x17B\x06\xe4\x81\xefM\xfd\x0e\xac\xcb\ (\x9f\x8cw\x00g_\x9cH\xab\xdfb>\x8e\x84\xe5\ Z\x8a\xb1N\x03\xc8\x22\xa0\xb2\x15\x90\xc2\xb8'm\x9f\ \x96\xe2\x99\xbc\x0d(c\xb7\xd0*@\x8f\xc1m\x87\x8e\ $\xd4\xbe\x05R(ek\xa4\xf0\x02\xee8L#!\ an\xbb\xca\x11\xfe\xc9\x16\x22@\x19;\x1c\x0b\xb7\xda\ \x11\xdb,>\x02 \x07\x09A\x08\x00\x9e\x05^V\xc6\ \x16u\xa5\x85\x925\xbe\xad\x94\xa0-\x09!\xb7\xc00\ \xf0\x952vQ\x89\xba\xdd\xa2\xd3VJH\x98\x93\xce\ \x08-\x03\xe6\x03\xdb\x94\xb1\xd7\x96\xac_\x16ydI\ B\xc2\xa1\x8d\x89Y\x04t\xb34g\x00\x1b\x95\xb1\x1b\ \x95\xb13:\x94\x0d%l\xf3\x8ew>\xb0E\x19;\ ;I\xa8Rp]\x0b|\xa6\x8c=6\xab\x80\x96\x22\ \x14\x01\x7f\x14(\xbb\x00xW\x19;\x0b\xc2\x09\xc1,\ ,\x01\xbe\xae\xc1\xdc\xbd\x15\xd8U\xa0\xfcI8_D\ \xd4O\x0e\x02\x94\xb1\xa7\x00\x0f\xb5i\xb0\x9d;}\x08\ \xd8\xa4\x8c}\x10X\x17\xc0\xd5\xd6\x02-\xc5/\xca\xd8\ \x13p\xfb|\x16NSL\x9e\x19\x80\xc0\xa9\xdd\x8d\xc6\ \xd2\xd9\xc05y/A\x86\x80\xd3\xba\x18c\x04\xdc\x05\ ,S\xc6\xae\xd2R\xf8\x1c\xa6]!&6s\x15(\ cw\x03o\xa7\x92WT!\x04\xdb\xe1,\xdcQ\x19\ \xea\xea\xad\x08\xb6\xd3\xba\xda\x0f\xad[\x15\xfe\x03\xe7n\ \xcf\xd2\xdc\xaa\x84\xef\xa8\x9cY\xa71\xb4\x1dw)b\ +h;\x0f|s\x1a\xc8\xbb\x02\xb6\x02\x87\xb5y:\ \xb9\xa2\x9e\x02N\x0f9\xf9\x226\x7f\x8c)Z\xe7\x95\ \xef\x14\x88o\x88\xd2\xf7}\x8d\x83\xc9Z1\xe3\xc0Z\ -\xc5\x0b\x05\x06\xda\x16\xb1\xfcx\x16\xe7j\xbb\xa3@\ U\xdf\x18\xa3,= \x04~\x02N\x0e<\xf9%\xb8\ ;\xc7aZ\xef\x1d;!\x93\x80\xbc\x85\x8b\xe0\x15\xdc\ \xe4w\x96\xa8\xeb\x95K\xca\xd8\xeb\x81m@\xa6fY\ \x06\xa1\x83!&\x81;\xb5\x14\x8f\x86jP\x19;\x13\ x\x02\xb8*T\x9b\x8d\x08u\x0a\xec\xc7\xed\xc9UZ\ \x8a/\xbb\x1aQ\x83}\xa2\x8c=\x1ex\x15\xa7\xbfw\ \x0b\xef\x9c|[\xc0'-;\xe1\x15`i\xd1\xc9g\ x\x91\xa28\xefJ\xdc~\x0f1\xf9L\x04\xd9\x02Z\ \x8a\x1bKV\xf5\x110\xa8\x8c}\x1aX\xd3\xa1\xee\x19\ \xca\xd8\x91\x8c\xbc\xbf\xb4\x14Y\x9e\xe5&d\x1d\x83\xbd\ \xc4l:O\x1e`Q\xfc\xf8\xd0\xce\xb5\xde\x04\xdf1\ \x98uc\x5c\x05z\xe2H\xcd3\x80\xc1\x9a\xfa\xaf\x8b\ \xe8LD\xf8\x8d\x84%5\xf5\xef\xf3#\x84\xbe8m\ \x8b~\xe0c`Y*\xfd\x1ee\xec\xe6\xb2AR\x05\ p\xa9'm\x03\xf0#\xee\xe2\xb4\x9dO\xd1\x00Og\ \xe4\xe5\x1ew?.4\xf6v\x9a\xb7\xc3\x12\xe0Ee\ \xac\xd2R\xb4\xf3\xb9\x97B|\xfc\xad\x01\x1e\xf3d\xbf\ \xa4\xa5\xf8N\x19\xbb\x03\x17\xb9\x9a\xa5\xf9\x8di)\xde\ \xe9v,I\xa4\xe8&\x5cdx\x1a\xbb\x81'\x81\x1f\ p\x86\xcd~\x8a;K\x12\xa1\xda\x8f[\xf2sq\xc1\ \x94\xa7z\xcan\xd5R,O~\xc4\x86\xcfF\xfc+\ \xe5\x11-\xc5mE\x06\xa2\x8c\xfd\x97f\xb93\x96\xfc\ \xb8\x15\xe7\xad\x99\x95\xaas,\xf0p\x91N\xba\xc08\ pSc\x82\x96b\xaf2v%p\x0b.\x82\xbd\xa8\ \x01\xd4\x11Q\xdc\xd1\x18\xee\xadT\xbd\xe7\xb3\xb0\x1f\xb8\ ZK\xf1C:#\x8e'x\x04X\x8e\x8b4i\xac\ \xd35\xa6\xf7}\xbc\x9fVP\xcc\xc7\x1e\x02\xfbp\x9e\ \xa2\xd7\xda\x15\xd2R|\x8e\xfbx#\x89:\x0f\xa2\xc0\ 5\xe9\x01q4\xf7b\x5clO]\xc7\xd1b-\xc5\ \x1by\x0aj)\xf6\x00\xe7\x03\xeb\x09\xb4\x02Z\xbe\x18\ I\x10\xdf\xa1]\x80\x8b\xc28\x1c'\xc0\x12_{\xd4\ \xf0\x14\xc1\x22RJ\x96\x96\x22s\x0c\xed\xa0\x8c\x1d*\ \xe2\x5c\x8dO\x9e\x7fh\x16\x82\xbbKu^\x16\xca\xd8\ \x9fI\x1dke\x09(\xd1w?\xf07\xcd\x04\xec\xea\ \xb9.\x1e\x0f\xacW\x98\xaa\x9b\x00\xdf)\x93>z\xab\ \x82o\xae\x93u\x13\xe0;a*ux4`\x90V\ \x12\xf6\xd6M\xc0\xa8'\xad\xac3\xa5(N\xa5\x95\x80\ \xd1\xba\x09x\xcb\x93v\x9926\x8f\x03\xa44bw\ \xba\xf6dm\xaa\xfb\x14\x88p\xdf'\xa5\x97\xfd\x14.\ \xdcm\x04\xd8\x19\x22p\x22\xeek\x01\xb0\x1agx\xa5\ \xd5\xe8Q`q\xad\x04\xc4\x03;\x1bx\x8fl\x1db\ \x92f\xc3+\xaf\x9361\xba\x92X\xe4A\xb2m\x87\ )\xe0\x1c-\xc5\xd6\xda\x09\x00P\xc6\xde\x0f\xdc\xdd\x8b\ \xbec\xac\xd3R\xac\x876\x9a`\xd5P\xc6>\x80\x0b\ \x9a\xa8\x13S\xc0z-\xc5\xbdIB\xcf\x08\x80\xe9o\ \x95Gp\xa1-U\xe3\x17\xe0\xe6\xf47\x8b=%\x00\ \xa65\xc1+\x80Kpj\xf2L\xc2y\x8b'\x80\x1d\ \xc0\xeb\xc0\x1b\xbe\xf8\xa4\xff\x01&\x08\x13\x8defQ\ \xc1\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x02\x17\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x01\xdeIDATx\x9c\xed\xda\xbf\x8a\xd4@\ \x00\x07\xe0\x8f\xe5\xb87\xb0\xb1X,\xae\x12\x1b\xb1\x13\ \xfbC\x0e\xf6\x11R\x1d\xe7\x8aO\xe2\x03\x88\xd8\xee#\ \xa4\xbd\xfe8\xef)$\x95X\xc8qX\x8bEP\xb6\ \xda\xcd\xc5\x99\xcc\x1f\xe6\x07[eH\xf2\xfb2\x13\x92\ \xb0\xb4\xb4\xb4\xb4\xb4\xb4\xb4,\x9d\xae\x1fN\xbb~X\ \xa5>\x8f\x94'\xf0\x0c\x9fR#\xa4\xbe\x02[\x89\x11\ NR\x1dx/[\xe8\xfa\xe1\xc3n\xb3\xfe\x1dr\xc7\ ]?|\xc4\xf3\x03C~\xe4\x00@<\x84\xd7xs\ `\xfb\xb7\xd4K`?I\x96CN\x00$@\xc8\x0d\ \x80\x85\x11r\x04`A\x84\x5c\x01X\x08!g\x00\x16\ @8\xe9\xfa\xe1\x1aOc\x1d\xe0@N'\x8e\xdbb\ \xd5\xf5\xc3\xfb\xd0\xcf\x09\x8c\x0fBg\xc6\xc7\xd2\x9cs\ \x051\x10r_\x02\xfb\xb9\xc2\xe7\xd0\xcb\xa1$\x00\x22\ \x94\x06@`\x84\x12\x01\x08\x88P*\x00\x81\x10J\ \x06 \x00B\xe9\x00\x8c\x08_\xe6\x22\xd4\x00\x00\x97f\ \x22\xd4\x02\xc0L\x84\x9a\x00\x98\x81\x90\xcb'\xb1\x90\xb9\ \x84\xae\x1f\xdeM\x19\x5c#\x00#\xc2\xca\x84\x19^+\ \x00\xbc0\xe1\x8d\xb3\xb6{\xc0\xdf\xdc\xe1\x1c\xbf\x8e\x0d\ \xac\x11\xe0\x0e\xe7\xbb\xcd\xfa~\xca\xe0\xda\x00\x1eU\x9e\ \xba\x00\x1e]\x9ez\x00f\x95\xa7\x0e\x80[3\xcbS\ >\xc0-\xde\xce-O\xd9\x00\xff]\x9er\x01\x82\x94\ \xa7L\x80`\xe5)\x0f hy\xca\x02\x08^\x9er\ \x00\xa2\x94g|\x1b|)\x0d\xc4\x19\xbeN\x18\x17\xad\ <\x9c\xc4\xda\xf1\xb1t\xfd0\xe5\xb87\xb8\x88y\x8e\ 9\x7f\x0f\xb81^\xf9\x87\x98\x07\xc9\xf5\x1e\xb0Hy\ \xf2\x04X\xac<\xf9\x01,Z\x9e\xbc\x00\x16/O>\ 7\xc1X\xe5\x1f\xf0\xf3\xc0\xf6\xfb\x1cf@\xb4+\xbf\ \xdb\xac/\xf0\xe4\xc0\xefU\xea\x19\x10}\xda\x1f\xfbO\ Q\xca\x19\xf0]\x825\xdf\xd2\xd2\xd2\xd2\xd2\xd2\xf2/\ \x7f\x00V\x8c\xad\x19\xcb\xd1<\xd2\x00\x00\x00\x00IE\ ND\xaeB`\x82\ \x00\x00\x07T\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x07\x06IDATx\x9c\xe5\ \x9bm\xa8\x15E\x18\xc7\x7f\xcaMD\xac,\xcd\xc2d\ 01\xb9I\x9a\xa2\x98X\x86\x99\x9a/9\xbe\x14\x95\ Q\xd9\x1aV\x22\x14\x11\x11\x94\x16bPA\x12\xbd\xe8\ \x87\xc8\xd6>\x98fY\xb9\x88\xa9i\x9a\x99\x99J\x1a\ \xdd\x0f\x970\x93\xc5$\xc4DB\xe4f\xb7K\x1ff\ \xf68w\xce\x9c={f\xf7\xa8\x17\xff\xb0\x9c\x9d\xd9\ g\x9e\x9d\xf9\x9fgf\x9eyf\xb6\x13\x05!\x88\xe2\ F\xe0~\xe06\xa0\x07\xd0\x05h\x00:[\x97\x89$\ \xafM_\x09\xda\xac\xab\x158\x0d|\x0d,\x0f\xa58\ QT\xbd;\xe5U\x10Dq\x1f\xe0-\xe0>\xca\x1b\ X\x0f\x9c\x04\x9e\x0b\xa5XY\x84\xb2\x5c\x04\x04Q<\ \x1a\xf8\x02\xe8]Dej\xc4;\xc0\xb3\xa1\x14mU\ %S\xe0M@\x10\xc5#\x81m@\xf7<\x15\xc8\x89\ \x95\xc0\xbcP\x8aV_\x05^\x04\x04Q\xdc\x03\xf8\x19\ \x10UD]};+*\x8d\x1b6>\x06\xe6\xf8\x92\ \xe0\xdbg\x17\xe1n\xfc\xaf\xc0\x1c\xe0\x06\xe0\x1a\xa0\xa7\ \xbe\xae\xb4\xae\xcb\xab\x5c\x89\x5cO`\x02\xf0wJ]\ \x1e\x02V\x07Q\xdc\xc5\xa7!5[@\x10\xc5W\x00\ \x7fPn\xfa[\x80\x99\xa1\x14g|*R\xe5\x9d\x8b\ \x81\x97\xab\x88}\x09<\x10Jq\xb6\x16\xdd>\x160\ \x8b\xf2\xc6\x1f\x07f\xd7\xa3\xf1\x1a\x072\xc8\xcc\x00>\ \x09\xa2\xb8k-\x8a}\x08\xb8\xc5\x91\xb72\x94\xe2\xa4\ \x87\xae\xac8\x9dQ.!!sw\xf0!\xa0\xc1\x91\ \xb7\xcfCO-h\xa9AV\x02\xeb\xb2\x92P\x94\xe3\ R/\xd3OP\xeb\x08\x7f\x0f\x19-\xa1(\x0b\xa8i\ \xe0\xf1\x80\xcf\x147\x035;\xb8\xea[BQ\x16\x90\ \xcb\x1b\xcb\x00_Gg\x16\xb0*\x8d\x84\xa2,\xe0b\ %\x00\xd4\x02mE\x10\xc5\xce\xb6\x16e\x01y*\x98\ \x05y\x09~\x14X\xe6\x22\xa1(\x0b\xa87\x8a \xf8\ )`\xb1\x9d\xd9Q\xc6\x80Z\xa6\xc14\xbc\x18D\xf1\ 83\xc3\x87\x00W\x99z\x13p\xba\xa0wt\x06\x96\ \x9a]\xa1(\x02\xea\x0a\xede6\x15\xa4n(02\ I\xf8\xf4\xe7\xf3N\x80\xc6T\xe0%`\x00j-b\ \x86\xdc\x1a\xac\xab\x9b!\xe3\xc2\x08`\x0ft \x02B\ )\x8e\x02\xf3\xb3\xca\xebE\xd1\x0c`\x05\x8a\x10\x13\xa5\ \x05S\x87\xe8\x02>\x08\xa5h\x09\xa5X\x03lp<\ .\xfd\xf1\x1d\xa219q\xcc\x91\x97k\x10\xbc\x10~\ @\x1e\xb8\x16j\xb9\x08\xe8hp9Q\x97\x94\x05\xfc\ \x97\xf6\xf0R\xb5\x80\x12\xda\xfd\x9bA\x14K\xe0\x19\xca\ \xe7\xd5\xe4\xea\x0c\xf4u\xe8\x09\x83(6\xc3Vi^\ \x9b\x1d*\xcfRa\xd7V\xd9Y\xd4.\xd1\x92P\x8a\ #)\xfaRQ\x22 \x88\xe2!\xc0\xa7Tv\x1e\xd2\ \xd0\xe8[\x81\x02p{\x10\xc5\xc3R\x02\xb2\xa9.\xb4\ i\x013\xa8\xde\xf8\xd3\xc0&\xa0\x19\xf8\x07\x15\xbb\x1f\ \x08\x8c\xa7\xdc\xd9\x008\x05\xac\x05\xbeCE\x8e{\x03\ \x83Q\x81\x8a\x01\x86\xdc\x16\xe0\x90\xbe\xef\x063\xfch\x95\xd9\xc79+\ 9\x82\xb1\x18\xd1\xe8\x85Z\xa6\xee\xd7\xe9\xdd\xa8\xfe\xde\ \x15\xd8\x1bJq\xca\x90\x9d\xea\xa8\xa7\xb7\x05T+\xb8\ \xd12\xe3\xc7P\x84\x98\x03^#\xe5[e%b\xf5\ \xfe\xfdb\xd4\x94\x05\xcar\xaes\xbck\xa2Q\xa6\x05\ \xbd\x5cEu\x07\x13S\x1ce\xebF\xc0\x0fV:\xeb\ rt\x82\x99\xd0]\xe8F\xe0U*os\xddm\xa5\ \x93Au[\x92\x11D\xb1\x00n\xceX\x87L\xa8F\ \xc0Q+\xdd/\xa3\xde\xb9A\x14\x8f03B)N\ \x86R,BM\x83\xcd\x8e2\xa3\xf5\xb9\x83\x04;P\ d\xed5\xf2\xa6P\xb0\xf7ZM\x99\xbd\xe3\x93\xf5\xe5\ ]\x81\xcd\xda\xb3l\x07\xed\xb5M\xa5\xdc\x12\x1ah?\ 8\xee\x05\xbe\xd1\xdd!\xc1\xb4\x0a\xef\xab[\x17\xe8e\ \xa5\x8f\xd4\xa0\xfbj`}\x10\xc5\x9b\xb5\x9fPB(\ \xc5a\xe03G\x99\xc9\x86L\x0b\xf0F\x92\xd63\xcf\ XG\x19\xa8#\x01\xc3\xad\xf42\x8fwL\x04\xb6\x07\ Q\xbc\xd4\xca\xff\xdd!;\xc9\x8c\xd8\x86R\xec6\x9e\ \x8d\xc3\xedm\xe6B5\x02\xa4\xb9\xc3\x1aJ\xf1!\xf0\ <\xca5\x055G7Qn\xce\x87P\x9e\xa3\xe9\x05\ fY/\xf4\xa5\xf2 7=C\xf9\x9aa\x12\xe0Z\ 4\xf4\x01\x9e03B)\xde\x04\xae\x05\xae\x07\xae\x0a\ \xa5\x18\x0c|n\x95[\x13J\xb1@\xcb\xdc\x04\xdc\x0a\ \xcc\xb4dl\xebJP6\xcdi\xef\xcf5\xfd\xf9\xa2\ \xd4V\xd3\x11\xaa\xb4n~-\x88\xe2\x83\xa1\x14\xbb\x92\ \x0c}\x0e\xc7\x8c\xb5\x1d@\xed\xbf%\xf8^\xcb\xb5\xe2\ \x18\xf1\x83(\x1e\x85\xda\xc3wa\x1a\xf0\xba\x957\x0a\ \xb7\xefP\xad\xeeUaZ@%%\xddQ#\xfa\xd3\ )\xe7o\xec\xa3\xab\x15Ou\x19\x87++u\xbf\x91\ A\x14\xdb\x8d\xb5\xad\xc7\x86\xf7\xae\x91i\x01i\xcb\xc9\ n\xc0\xdb\xc0\xa2 \x8a\xb7\xa2\xfa\xf8\xbf\xa8clC\ i\xbfp\x015\xe8\xed\x04\xbe\x05\x0e\xa3\xc8\xed\x8br\ v\xc6\x93>\xf64\xa0\x0e64\xa1\x1a\xd6\x1d\xb5T\ O\x83\xf7\xde\xa1I\xc0N]\xd1\xb4\xf5A/\xe0\xc1\ \x0cz\xbb\xa0\x1a:\xde\xb3^c\xa9<\xe5\xd9hB\ \xad>\xbd`\xfa\xecMA\x14O\x03\x16\xa0\xe6\xf0$\ \x04f\xa3?\xe5\xab\xb1f\xb2\x9f\xe4\xf2A\x9b\xf1\x9b\ \x5c-@\x0c\xbc\x92\xe7\xbcp\xbb\x7f;\x94b\x13*\ \xe2S\x11A\x14\xaf\xa6\xdc\x0a\x1e\xb7\xe6\xec\x0e\x03\x1f\ \x0f*5\xce~\x11\x22u;\xffR \xc0\x85\x5c\x04\ \xb8\xfa[G#\xa0\x84\xa2,\xe0b\xde-Jm\xe3\ \xa5`\x01\x85\x13\xd0\xd1,\xe0\xb2\xb4\x87E\x11P\xd3\ \x11\xf5\xf3\x8c\xd4\xba\xf9\x10\xe0r\x99\xfb{\xe89_\ p}\xd9Rr\x9d}\x08\xf8\xcd\x917\xaf\xd6\x0f\x15\ \xce\x07\x82(\xee\x8b{\xd5\xb93\xb9\xf1!`\x03\xe5\ \xb1\xc2\x81\xc0\xbb\x95\xce\xe3^\x08\xe8\x10\xda*\xca\xa3\ H\x87\x80\x83I\xc2\xf7\xab\xb1\x15\xc0\x5c\xc7\xa3-\xa8\ \xa3l\xcd\xc0\x99\xbc\xdf\xf4\xf9@\xff\x09\xe3Q\x1fs\ \x0er\x88,\x08\xa5X\x9e$|\x09\xe8\x03\xfcB\xe5\ -\xaaV\xce\xed\xe1\x9f\xa5\xfa\x99\x80\x22\xd1%\xa5^\ M\xc0p\xf3\xc3\xaa<\x1fNN\x01\xd6sqO\x81\ &N\x01cB)\xda\x9d8\xf5\xee\xb3\xa1\x14\x1b\x81\ G(\xee s=q\x02\x98l7\x1erzp\xfa\ \xe2\x18\xe0\xa7\x7f/\x01SYb\xb6C\xcf\x13%\x804/n\ b{\xbe\x9fy\xa7e\xe0A\x96\x98\xad\x90sE\x07\ \xa0\xa2y\xa7\xcfX\x08\xbf\xeb\x9e/*\x00\x9e\xe6\x9d\ V\x81\xc9\xba\x10\xa2\x01P\xd3\xbc\xd3\x1a\x16\xc2/\xdf\ \x86Q\x00\x182\xe0U\xd5\x17,\x84\x9f>\x8dZ\x07\ 0`\xaa\xab\xab\x0d`\x22K\xcc\x8f\xaa\x0dZ\x05 \ l\xde\xe9+\x16\xc2f\x95\x83O\x08\x9e\xd8K\xe5\x0a\ O\xda<\x80\x01:U\x0fn\x05@\xcf=/m~\ \x07\xbb@\xfaT\xb5A\xe3\xb7\xc0\xa1\xb5\xbd\xa4\xba\xc0\ \xc3,1\x8b>\x8d\x1a\x05\x10\x9byh\x10@\x8c\xe6\ \xa1!\x00i^\x5c\xc3\x9a?'\x1c\xda\xdd\xf3\x8bu\ \x03\xa8\x0f\x82\xca\xe6k\xf7\xbc\x93j\x064`~>\ 4\x90\x1a\x804/\xc6\xb1\xe6\xcf\x0b\x87\x0eN\xfb^\ \xa9\x00\x18\x15\xf3\xa0\x00 \xcd\x8b\xab\xc0\x02#`\x1e\ \x84\x01\x8c\x9ay\x10\x9c\x05\xd2\xbc\xb8\x82N\xdawQ\ 2\x0fB\x19P\x9a_\x00.H\xc4\xebQ\xd0\x22\xa7\ \x8a\x82\x01\xf4\xf4\xfc\xc5\xf0\xcb9 \xb5\xb4\xefU\x10\ \x804/.c{^\xc3\xbc\xc8\x96r\x8a\x0e\x00T\x9a\ \x22\x97\xb0=\x1f:p\xc6\x09\x00\x0e\xcc\x0e\x87!,\ b\x97\xbc\xc1_\x8dB\xc4\x00\xa0/\x84Y\xec\x93\x9f\ \xc8w\xc3\x10\xe1 \xd8O\xe5\xc0\xf8\x12x&\xf9\xe5\ 8\xc0_$\xfcw\xe6\x1f\xe2\x030\x00\x00\x00\x00I\ END\xaeB`\x82\ \x00\x00\x02\xcd\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x02\x7fIDATx\x9c\xe5\ \xdb\xbfk\x14A\x14\xc0\xf1\xef\x1d\x92RD\xa2\xa4Z\ \xacE$E\x08b\x11\xec\x85\x05\xc5& \x82\xf3\x1f\ D\xf0\xcf\xd0\xc2\xf4+\x82\x92.\xc5\x80\x04\x91\xe0\xbf\ `i'\xcc\x9f\x10\xac\x8e\x10,\xf6\xc8\xaf\xcb\xde\xed\ \xcc\xce\xcc\x9b\x9dy\xe5qs\xb3\xef\xc3\xde{o\x96\ \xbb\x89\xd2\xe6\x00\xd8`\xbc\xb1\xdf\xd4\xd5\xa1\xeb\xe2\x89\ \xd2\xe6/\xf0\xc0\xdf\xf5D\x8f\x19\xb0\xeb\x8a0\xf5|\ 1\x12\xb1\x06\x1c(m^\xba,\xce\x01\x00\x06 \xe4\ \x02\x00\x17\x08\xafl\x16\xe5\x04\x00-\xc27\x1b\x84\xdc\ \x00\xe0\x02\xa1\xd7\xd7!G\x00\xb0\xa8\x09\xb9\x02@O\ \x84\x9c\x01\xa0\x07B\xee\x00\xb0\xa2;\x94\x00\x00K\xba\ C)\x00\xd0\xd1\x1dJ\x02\x80\x1bjBi\x00p\x0d\ !\x87\xd3\xa0k\xcc\x80\xdd[\x917\xfd\x0d\xbc\x00\xfe\ E\xde\xb7+Nc\x03l\x02_\x80\xe7M]%\x81\ Q\x03v\x80\xefJ\x9b\xdb\x02{/\x84T\x11\xdc\ \x01\x8eR@\x90\xec\x02OI\x00A\xba\x0d\x8a#H\ \x03\x800B\x0a\x00 \x88\x90\x0a\x00\xb4\x08?b#\ \xa4\x04\x00\xf0\x84\x16\xe1N\xac\x0dS\x03\x80\x16\xe1(\ \x16\xc2P\x803\xe0\xd4\xc7\x85\x5c\x8bh\x08C\x01N\ \x80\xb7\x8c\x18a\xf0W\xa0\xa9\xab\xaf\x84E\x08Z\x13\ \xbc\xd4\x80\xc0\x08\xdb\x04D\xf0V\x04\xc7\x8a\xe0\xb5\x0b\ \x8c\x11\xc1{\x1b\x1c\x1bB\x909 \x02\xc2O\xa5\xcd\ ]\x1f\x1f\x16l\x10\x0a\x8c\xb0E{'\x0cF\x08:\ \x09\x8e\x01!\xf8(\x9c:B\x94\xb3@\x04\x84c\xa5\ \xcd\xba\xcb\xe2h\x87\xa1\xc0\x08\x9b\xb4\x85\xd1\x1a!\xea\ i0E\x84\xe8\xc7\xe1\xd4\x10D\x9e\x07D@8V\ \xda\xdc\xef\xf3f\xb1\x07\x22\x81\x11\x1e\xd3\xde\x09+\x11\ D\x9f\x08\xa5\x80 \xfeHL\x1aA\x1c\x00\xa2 t\ \xd6\x84$\x00 8\xc2#:\x10\xa6\x80\xf3o\xed}\ \x87\x04\xc2\x14x\x0f|\x0a\xb0\xa1S\xc4F\x986u\ u\x06\xecQ\x16\xc2/\xa5\xcd\x06\xcck@\x81\x08\x0f\ \x99\x1f\xa0\xce\x8b`\x81\x08\x7f\x80\x93+]\xa0 \x84\ C\xda\xff\x19\xcd\x16\xda`\x01\x08\xe7\xc9C\xc7\x1c\x90\ 1\xc2\x95\xe4a\xc9 \x94!\xc2B\xf2\xb0b\x12\xcc\ \x08\xe1\xc6\xe4\xa1\xc7(\x9c\x01Bg\xf2\xd0\xf3,0\ b\x84\xa5\xc9\x83\xc5ah\x84\x08+\x93\x07\xcb\xd3\xe0\ %\x84\x8f\xf3\x97B\x0c(V\xd1\x81\xd0+y\x80\x89\ \xeb\xc6J\x9b\x0f\xc0\x9b\xa6\xae\xee\xb9~\x86\xcfP\xda\ \xbc\x06>\x03\x9a\x9e\xc9\xfb\xd8\xf4]\xf0M,Bi\ \xf3Li\xb3f\xb3\xe6?\xa5X^\xc4\xa8\xbe\x0c\xae\ \x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x05\xf3\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x05\xbaIDATx\x9c\xd5\x9bm\x88UE\ \x18\xc7\x7f.\x8b,~\xb0\x08\x11\x09\x1bD\xa4\x17\x09\ \x13iW\x93\x08\xfbP\x14\xc5D\xbeQj#\x06\xbd\ \x80\xa8a\x04\x95\x88H\xafkD\x09\x89\xf8R\xe8\x94\ \x89\x99}\x98(\xcc\xa0\xa2\x17*)\x13\x12\x91(\x91\ Id?HH\x88H,\x97>\xcc\xac\xdc\xdd=\xf7\ \x9c\x99\xb9\xe7\x9c\xbd\xfe\xe1~\xd8\x9d\xff}\x9e9\xcf\ \x9d\xf3\xcc\x09\xec\x88\x94\xbdRKQ\x18\x86wQ\x91\xb3\ \x0a\xc4\xb9\x22\x822v\x1e\xb05A\xf6ve\xec\xec\ \x22R\x17n\xa9\x8cE\xc4v\x1eX\x99G\xf0\xc1\xd7\ A\xb2\x0b+E\x98\x00\x1c\xf2\x95\xa9\x96\xe8\xf2\xf5\xb8\ %@\x9dI\x8b\x06\xf0X^\x86\xd8'\x5c\xf7\xe3\xea\ \x87\xa9\x98\x0e\xec\xcd;$u\x01h)\x8e\x01k\xda\ P\x14\x8bW\xb5\x14\x87\x0b8\xfd\xc0\x82\x12t=\x08\ \xbc\xd8j\xf0\x8ae\xb4\x14\xbb\x81=%(,\xc2\x11\ `S\x1eA\x19\xbb\x14X_\xa2\xce\xcd\xca\xd8\xfb\xb2\ \x06F.\x8d\xd5\xc0\xf1\x12\x15\x8f\x84\xc5\x15D\x1b\xad\ \x08\xca\xd8\x99\xc0\xae\x92\xf5v\x01\xef+c\xa7e\x0d\ \x5c\x81\x8f\xa8\x96\x00U\xd4\xe9/\x03\x8b\xf2j\x82\xca\ \xd8\x89\xc0!\xe2\x0f]!\x98D\xc6!i\x94s\xd0\ R\xfc\x89\xf3\xce-\x7f\xa5D\xac\xd1R\x14%H\xde\ \x05n.Yo3\xfa\x18\xb1\xa5fzG-\x85\x01\ ^/Q\xf1{\xde\xc7\xb4\x842v=q\xf9\xc6T\ <\xad\x8c]1\xf4G\xde\xf1v\x13\xcea\xb5\x8bc\ \x14\x1cK\x95\xb1w\xe2j\x0dua\x87O\xef\xe7\x97\ \xc7\xfdY\xfeW@$*:\x0f\xf4j)\xce\x14\xe8\ \xf8\x8d\xf6\xf6\xfb\x14\xfc\x01\xf4\xe6\x068\xdea\xa5\x1e\ \x92\x06q\x1e\xffL\x01o\x17\xf5?<\xc0\x8d\xc0\xd6\ \xc2\x08OKq\x14X\x97\xa0`\xa3\x96\x22\xe4\x15\x9a\ \x99 \xbb,\xcc\x08Jrj)v*c\xe72<\ \x0d\x95\x87\x8f\x81-\x81\xdc{p\xde\xb9\x87\xd6IW\ A|y}\x1d.\xe4\x1edx\x18\xde\xfc\xf9)\xb8\ E\xc6'$\xbe\x03n/\xa0\x9e\x04\xee(3%\xae\ \x8c\x9d\x0f\xfc\x10\xf9\xb5kB\xe6\x10\x9c\xe4\xf0\x15\xde\ %\xe4\x87\xcf\x17p\x87\x9d\xb2\xeb\x01)\xd9\xa8\xa04\ yT\x96\xc7;\xb4\xe5\xb8e5\x12\x0d\x5c\x12\xa2\x8a\ z@^\xd7Y\x16\x06\xb4\x14Ys\x1c\x85\xe8\x5c\xba\ wl\x1b3\x866\xfb\x03T\x15\x08\xedE\x18Bp\ ~#\xb5Ab\x0b\xce\xd1\x0d\xe1\x13\xe0\xe5DY!\ \xb8!\x92\x7f2\x94\x98d\x00\x1f\xcd\xad\x02\x0e\x03\xdf\ \xe0\x96~\xd9\xb1C3\xa6G\xf2\x7f\x0e%&\xf7\x09\ \xfa\xa6\xa7\xfbS\xbf\x1f\x89\x98\x00\xa9\x01|\x1fJn\ \xb7M\xaer(c'\x10W\x95:\x1e\xd3\x8c\xd9\xf1\ \x06\xc0\xdd-\x88i\xca8\x14#\xfcj0\xc0\x82\x08\ \xee \xf0A\x8c\xf0\xab\xc1\x001~\xc6\xc4\xb6\xe0w\ \xb4\x01|\xa13\xb4+\xa5ABN\xa1\xa3\x0d\x80k\ \xca\x0a\xdd\xa9>\x0aH\xb9\x8dB\xc7\x1a\xc0\x17F\x9e\ \x0a\xa4_\xc0]\xcf\x89F\xc7\x1a\x00\xd7\xfa\x12z\x00\ Z\x97z\x0f\xa1\xf2[c)\xf0\xa1\xf7\xef\x84\xed\xff\ \xbb\xb5\x14O\xa4\xea\xea\xd4\x15\xb0\x9e\xb0\x87?L`\ \x1f@+t\xdc\x0aP\xc6\xce\x01~\xa4\xf8\xf0s\x04\ \x97{h\xab\x13\xa5\xa3V\x80\xcf\x10\x1f\xa4\xf8\xe1\xf7\ \x00\x0f\x95q\x09\xa3\xedKSe\xc1\x97\xc5>#\xdf\ \xf1]\xc4]\xb1\xddY\x96\xde\x8eX\x01\xfe\x06\xca\x97\ \xe4\x1fz\x0cp[\x99\x0f\x0f\x1d\xe0\x03\x94\xb1}\xb8\ \xd6\xb7i\x19\xc3\x0d\x5c\xcb}\xbf\x96\x228\xc4\x8d\xc1\ \x98\x19\xc0Wi7\x00\xcf3\xfc\x9do\x00G\x81O\ \x81\x0f\x03\x0a+maL\x0c\xe0\xfbv^\xc1%:\ \xfe\xc3\xf5\x0d\xfc\x85\xab#\x1e\xad\xf3\x1a\xfd\xffk\x8a\ \x8e\xd3\xecu\xd4\x00\x00\x00\x00\x00IEND\xaeB\ `\x82\ \x00\x00\x06\x8e\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x06UIDATx\x9c\xe5\x9b{\x88UE\ \x1c\xc7?\xca\x22\x22\x22\x8b\xc9\xa2\x22\x83\xc4VbZ\ \xb6H\x84\x88\x99\x99E\xc4`\x12B\x0f\x86\xa2\xacl\ 3E\xc30\x93\x90\xe8\x85e\xd4\x12\x82=\xc4SD\ \x89,1PY\x9a\xd2\xd2\x03\xc3\x1edn%!\xcb\ \xa0\xb6,&\x22\x8b,\xb2,\xfd1s\xb9w\xafs\ \xcfc\xe7\x9c\xdd\xbb\xf9\x85\x81s\xe6\xf1;\xbf\xf3\xbd\ \xbf\xdf\xcco~s\xee\x18F1\x946\x13\x80\xeb\x5c\ \x99\x0b\xcc\x02z#)\xeeN+\xa3\xa1 \xdd\x86\x0b\ O\x00\xdb\xaa\xea\xfa\x946\xe3\x22).\xa6\x1106\ \x7f\x9d\x86\x15\x7fz\xea\xc6c-!\x15F;\x01\x9d\ 5\xea\xafK+`\xb4\x13\xd0\x05\xf4z\xea\xafO+\ \xa0\xae\x08P\xdaLR\xda\xa8\xb4\xfd#)\x06\xf0\xbb\ \xc1\x9c\xb42\xea\x86\x00\xa5\xcd\x1d\xc01`\xb7\xd2\xe6\ \x81\x0cC\x7f\xf7\xd4\x8d\x1e\x17P\xda\x8cW\xda\xb4\x01\ \x9f\x013\x5c\xf5\xdbJ\x9b\x99)E\x1c\xf5\xd4MU\ \xdaLI3x\xc4\x09\x00\xb6\x00O2X\x97I\xc0\ \x07J\x9b4\xcb\xb4\xcf\x02\xc6\x02\xb3\xd3<\xbc\x1e\x08\ x\x138\xe3\xa9_\x08<\x9db|\xd0J0\xe2\x04\ DR\xf4\x00kj4oU\xda\xccK\x18\x7f\x128\ \xebi\x9a\x9b\xe6\xf9#N\x00@$\xc5\xc7@\xbb\xa7\ i\x1c\xd6\x15\xc6'\x88\xf0YA\xaa\x95\xa0.\x08p\ h\xc5\xef\x0as\x80\xad\x09c\x7f\xf3\xd4\xcdV\xda$\ \xbe_\xdd\x10\x10I\xd1\x8d%\xc1\x87\xf5J\x9b\x851\ \xc3}+A#\xe5U\xa5&\xea\x86\x00\x80H\x8a=\ \xc0^OS\x03\xb0Ki3\xb1\xc6P\xdfJ\x00)\ \xdc\xa0\xae\x08ph\x05\xba=\xf5\xcd\xc0\xab5\xc6t\ \x02\x03\x9e\xfa\xd1G\x80[\x15V\xd7h~\x5ci\xb3\ \xd43\xe6,p\xd2\xd3?q%(\x94\x00\xa5\xcdF\ \xa5\xcd\x0b1\xa6\xebE$\xc5\xa7\xc0\x87\x9e\xa6\xb1\xc0\ {J\x9bFO\x9b\xcf\x0d\x12\x83\xa1\xc2\x08P\xda\x08\ \xe0y\xe09\xe0\x98\xd2feF\x11k\xf1\xff\xaa\x02\ \x1b\xd7\xaf\x0f\x7fr\xe4\xda8E\ \x0b! \x92\xa2/\x92b3p\x03p0\xa1\xfb|\ \xe0;\xa5\xcd.\xa5\xcd\xd4\x1a\xf2:\x80\xed5\xc6\xb7\ )m\xa6\xbb\xeb\xcc+A\xa1\xcb`$E'p\x1b\ p?p:A\x8f\x07\xb1n\xb1Ni3\xce\xd3g\ \x0b\xfe\x17\x9c\x8c\xb5$\x80_<\xed\xb1\xe1\xf0\x98\xb8\ \xc6<\xa1\xb4\x99\x84]\x16\x9f\x22\xf9<\xa2\x13X\x13\ I1\xc8z\x946-\xc0\x0f\xd8]b5Va\x09\ z\x06;\x1f\x1cu\xf7\x9dqg\x04\xc3F@\x09J\ \x9b\xd9@\x1b\xb0$E\xf7\xbd\xc0\x86H\x0aS1\xfe\ Y\xe0\xc5\xaa~\xe7\x81\xd6H\x0a_\xf0\x14\x8ba'\ \xa0\x04\x17\x18m\xc3\xc6\x08q\xe8\x05^\x06\xb6GR\ \xf4\xb9\xc0\xe6\x1b`\x81k?\x00<\x5cIR\x16\x8c\ \x18\x01\x00.D\xde\x04\xac\xc7\x9e\xe8\xc4\xe18\xb06\ \x92b\x9f\xd2\xe6J\xe0\x10\x96\x98\x9d.=>$\xe4\ B\x80\xfbU$\xf0\xad\xdb\xccd\x1d\xdf\x0c\xbc\x01\xdc\ \x95\xa2{;.y\x12I\xd1\x9f\xf5Y\xd5\xc8\x8b\x80\ e\xc0\x97\xd8\xb5\xba\x13k\x96_\x03\x1d\x91\x14\xe73\ \xc8\xb9\x13\x1b\xe77\xc7t\xbb\x08\xcc\x8d\xa48>t\ \x8d\xcb\xc8\x8b\x806ltW\x8d\x8b\xc0\x8f\xc0~,\ )G\x92Nm]\xfeo\x1d\xb0\x19\xf0\xed\x22\xdf\x8a\ \xa4X\x1b\xa6q\x19y\x11\xf0\x17pu\x8a\xae\xe7\x80\ \x0e\xac\xb5\x1c\x8c\xa4\xf0En%\x993\xb0\x93\xe4J\ \xca\xf1J\x0fpM$\xc5\xb90\x8d\xcb\x08&\xc0E\ o\xa7\x18ZPe\xb0\x96\xb1\x1fK\xc8%\xf3\x87\xd2\ f\x11\xd6-\xe6ag\xfb\xf7\x03\xd4\xbd\x04y\x10\xd0\ \x82}\x81\xc4\xdd]\x02\x06\x80_\x81\xaf\x9c\xbc\xef]\ |_\x9ad\x97\x03\xed!3\xbe\x0fy\xae\x027\x02\ \xb7\x03\xcb\xb0\xf1}\xe8\xd7'\x17(\xbb\xcb\xbe8w\ \x09A!q\x80\xdb\xeb/\xc6\xee\x03\x96\x12?\xab\xa7\ \xc5U\x91\x14\x7f\xe7 g\x10b\x09\xf0\x9c\xd5wD\ Rte}\x88\x0b\x5c\x96b\x09YBvw\xe9\x01\ \xa6ER\x0c(m\x1638z\xecr\xbb\xc5!!\ \xc9LwW\xdd\xdf\x8b\xfd*#\x13\x22)N\x00;\ \x81\x9d.\x01\xd2B\x99\x90\x05$G\x81\x1d\x15\xbe\xdf\ \x0a\xdcS\xd1\xb6\x07\xeb*C\xc2\xb0\x7f%\xe6^\xe4\ \x88+\xaf\xb8O\xdd\x16P\xb6\x8ey\x1e\xbd\xbe(J\ \x9f \x02\xdcG\x0cS\xb0&z&\x92\xe2BV\x19\ n\xcc\x01Wp\x1f6,\x02n\xc5\xce#\xcd\xc0\xe7\ !z\xc6!\xd4\x02V\x03\x1b\xddu\xbf\xd2\xa6\x17K\ FwE\xf9\xa7\xea\xbe\x1b\xe8\xa9\xb5\x9cER\x9c\xc1\ \xc6\xfb\xed\x00J\x9b\xc6<\x03\x9fj\x84\x12P\x99\xc2\ j\xc0\x1eH6\x92\x1c\x15\xf6+mJD\x9d\xa6L\ \xcc\xa9\x8a\xba\xd3X\xa2\x0a{y\xc8\x97\x80\xac\xcf\x9d\ \xeeJKL\xbf~\xa5\xcdk\x91\x14\x9bb\xfa\x04\x05\ F\xa19\xc1\xa6\xe4.Ah \xf0\x05\x93\x10J@\ h\xf8\x9b\x06\xff\x16)<\xd4\x05n\xc6\x1e=M\xc5\ \x9a\xf34w]Y&\x13Ft\xe6\x04K\x16\x04\x11\ \xe0\xa2\xc2\xae\xb8>.\xc5\xdd\xe4J\x89\x94&,Y\ M\x15\xf7M\xd8\x09\xb4Z\xa7\xb8tz0\x0a\x0f\x84\ \x5c\x02\xe4$\xfe\x93\xdeAp\xc9\x90F,\x19S\x5c\ \xf99aXPZ,4\x10\x9a\x88=\x81m\xc0\x9a\ y\x9c\xa9WNf\xfd5\xea\x07\xb0Y\xa4\x12a\x03\ \xd8\x94wa\x182\x01J\x9b\xf9\xc0a\x8a\xff\xca\xe4\ \x0a\xfc\xdf\x01\xe6\x82\x10\xe5K\xbf\xfa\xa8\xc6\xa8\x7f\x81\ P\x84\x10\x10\x9c\x93\xcf\x09Az\x84\x10\x90\xeaOI\ \xf5\x8e\x90U\xc0`\x8f\xbd\x8b\x86\xef/1\xb9a\xc8\ \x04\xb8]\xdaG9\xea2\x22\xf8?L\x82#\xba\x1b\ \x1c\xf5\xc8\xea\x02\xb7\xb8\x1c\xdeHbf\x9e\xc2\xb2\x12\ \xf0\xa8+\xf5\x84\xcb\xde\x05.{\x02\x82\x90\xe4\x02]\ \xc3\xa1D \x826J\xff\x01\xd5\xfa\xe6u\xb5\xb2t\ \x0a\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x04R\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x04\x04IDATx\x9c\xed\ \x9aM\x88\x14G\x14\x80\xbfi\x9aEF1\x12$z\ *$\x07\x09$\xe4 !\xe4\x96D\x10A\xa4DB\ \xd8Cri\x10\x92\x8b1\x229\x041\x10d\xe3\x0f\ \x08\xfe+\x22\x14\x82z\x8a\x10\x1aY\xcc%x\xc81\ ,9\xe4\xe0Ar\xa8C\xc8!.\x8b\x84eY\x86\ !\x87\xee\xc9\xb6\xb3\xdd\xd55\xdd\xd5S3\xbb\xfdA\ \xc3tu\xd5{5\xaf\xab\xea\xbdW\xd5\xd0\xd2\xd2\xd2\ \xb2\x89\xe9D\xb1\xee\x02\xb7\x00\x09\x84\xe9\x05\x10\xa4W\ \x1eaAy\x1e\xbd\xcc\xef~\xe6\xea\xa5\xd7?\xc05\ %\xc5\xf5\x11d:\xa3\x13\xc5\xfa\x0a\xf0\x95\x0f\xe5C\ |\xac\xa4x:n\xa5\x01\xf0\xd1\xb8\x95\x16p\xc0\x87\ \xd2\x00\xe8\xfaP\x9c\xc36\x1fJ\x03F\x9b\xcfM\xd2\ \xf7\xa1\xb4h\x91\xf3\x817\x03\xac\xfaP\x9cC\xaf\xbc\ \x8a{\x02`\xc5\x87\xe2\x1c\xbc\x8d\x80\xa7>\x14\x0f\xd1\ \x07~\xf6\xa18\x04\xbe%\x19~\xef\x93x\x84\x90\xb5\ h\x1ck\xc4*0\xe7#\x06\x00\xe8\xf8P\xea\x9a\ (\xd6\x01\xb0\x1f8\x0a\xbcE\xf2B\x17\x80\x07J\x8a\ ?Lm7\x8a\x01\x8a\xa2\xd9\x1epPI\xf1KQ\ \xdbIr\x83ux\xaf\xa0<\x04>05\xdc(\x06\ 0E\x91\xbbL\x0dC\x80(\xd63\xc0v`\x0bk\ \x8b`8\x5c\xcf\x82A\xa67\xf8\xdd#Y\xe4\x96\x94\ \x14\xcb\x962\xaa\xb0\xdd\xf0l\x87\xa9a\x18\xc5z/\ \x89\x0b\xda\xe3\xb2GC,G\xb1>\xa1\xa4\xb8\xdb\x90\ |S>c2\x0e\x010G\xb3\x7f\x1e\x92\x0e^\x89\ b\xed<\xe1I=\x80\xc9\x00F\x9d\x01\xb0\xd7i\x8f\ \x8a\xe9\x02o4 w\x06\xf3\x14-\x1d\x01\xe3LC\ \x9bXt\xcb\x0cP:\x02\xa6\xdd\x13\xd46\xc0\xb4S\ \xb6\xa1\xd3M\xd7\x89\x5c&)\x1b\xacJ\xa9\x010\xbc\ \xe8\x00Xt\xda\x1d3\xff6 s\x8b\xc5s\xa3\x01\ \xee9\xedN1\x8f\x95\x14\x7f7 \xb7l\x117.\ \xf4\xa1\x92\xe2N\x14kM\x92\x0eoe\xf4u!o\ 'g\xb8\xec\x05p{D\xb9\xb6\x94\x8d\x00H\xa6A\ \xeeH\x0f\x01\x94\x14O\x80'\x0e;5Nl\xdcx\ a\x9d\xcd\xe0\x05`\x83\x1b\xc0f\x04\x14F\x83\x9b\xde\ \x00\x83t\xf8\x1d`\x1fk\xe9p6\xb2\xb2\x8d\x16\xe7\ \x95\x14\xcf,\xea\xb9\xa6\x9e\x01\xa2XK\xe0\x11\xf5O\ \x88\xceF\xb1>\xa8\xa4\xf8\xb5\xa6\x9cQy\xcd\xa2\xce\ \xebE\x0f\x02\xe0\x1b\xdc\x1c\x8fu\x81\xb3\x0e\xe4\x8c\xca\ n\x8b:\x85\xbbB!nST\x1b\x9f\x5c\x89(\xd6\ \xc7\x80\xe3\x99\xa2\x80$\x11\x12\x16\xcd\x8fE\xb1>\x94\ \xb9\xef\x03/\x81\x1b\xc3\xf3}\x22I\x93\x999\xaa\xbf\ \xac\x9d\xe9\xb5\xae|*\xd2a%E\x1fx\xdc\x80\xe8\ \x1f\x03<\x9d\xc9U\xe0\x14\xf0\xa7Cy\x0b\xc09\xd7\ \xa7\xc3\x8d\x19SI\xb1\x04\xcc\x02.v\x97\x97\x80Y\ %\xc5J\x00h\x07\x02\x07\xfc\xe5P\xd6:\x94\x14\xbf\ \x01_P\xcf\xd0=\xe03%\xc5sH\xe6\xff\x19\x92\ \x15\xb1.\x8b\xc09\x07r\x8c()\xee\x03\xe7k\x88\ 8\xa9\xa4\x98\x1f\xdct\x00\xa2X\xef\x04\xde\xe4\xd5\x83\ \x110{\x88\xec'o\xcb\xc0\xb3t\x986N\xea\x15\ \xee\x01\x9f\x8f\xd8\xf4\x07%\xc5\xe9l\xc1\xd4\x1e\x8e\xa6\ \xa7Y\x8f\x80\xc3\x96M\xae*)N\x0c\x17N\xbc\x0b\ ,BI\xb1\x0a|\x0a\xcc\x97\xd5\x05n\x02'\xf3\x1e\ L\xad\x01\x00\x94\x14+\xc0'\xc0O\x86j7\x81\xe3\ i,\xb1\x8e\xa96\x00\xfco\x84Y\xe0a\xce\xe3\xcb\ \x18\xfe<$\x9f\xca\x86\xc0\x97\xc0\x87\xbc\x1a\xcb\x0f\xf6\ \xf5\xfa\x99\xfb\x0bJ\x8a\x85\xda\xbdn\x80ta\xbc\x04\ |M\xd2\xd7\xd3J\x8a\x8be\xed:Q\xac\xbf\x03\xbe\ \xb7\xd4\xb3\x04\xbc\xad\xa4h\xd4\xdf\xd7!\x8a\xf5~`\ QI\xf1\xbbM\xfd\x1082\x82\xfc\x1d\xc0\xbb4\x1c\ \xf0\xd4\xc1\xf49L\x1eU\x0eG\x1bKy}P\xe5\ [\xe1\x99&:\xe2\x8b*\xe9\xf0\xd4{\x8e,\x01\x9e\ \xbe\xd1\x9d\x14\xaa\x9c\x0eO\xcb\xfe\x81\x15\x01\xc9\xc6\x80\ -}\xe0yC}\xf1B@\xb2\xd3b\xb3\x95\xbd\x0c\ \x9c\x99\xd4@\xa8\xa5\xa5\xa5\xa5\xa5\x02\xff\x01\x93\x10\xdb\ v~\x8d\x5c\x09\x00\x00\x00\x00IEND\xaeB`\ \x82\ \x00\x00\x04r\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x04$IDATx\x9c\xed\ \x9bM\x88\x14G\x14\xc7\x7f\xdb\x0cK\x10\x09\x22\x22\x22\ R\x04\xa2 &\x86 A\x0cJ\xe2\xc5\x8f\xf5P\x8a\ D\x04s\x90\x16\x84\x90\x839y\xf0\x90c.B\x0e\ z\x101H\x81\x8a\x8a\xa8\x87>\x88\x89\x1f(xP\ \x0f\x22F$\x09B\x96f\x11Y$\xc8\x222,\xc3\ \xe0\xa1\xba\x93\xde\x9e\xd7\xb3kv\xab\xaagv~\xd0\ \xecNU\xf5\xf4\xab\xffT\xbd\xae\xea~o\x88i\x88\ \x93t5\xb0\x15X\x0b,\x00\x86\x81(;\x1aY\xb3\ \xfc3\x15\x9f\xcb4\xba\xd4\xcd\x84\x96\xf0\x7f+;\xde\ \x02\xaf\x81\xbf\x81\xdbF\xabG\xdd\xbeh\xa8\xaa\x22N\ R\x0d\x1c\x016\xcc\xca\xd4\xf0<\x01~\x02.\x1b\xad\ \xda\xe5\xca\x0e\x01\xe2$]\x06\x9c\x06v\xb8\xb7\xcd+\ \xbf\x01\xfb\x8dV/\x8b\x85S\x04\xc8\x86\xfb\xaf\x80\xf2\ h\x98O\xc6\x80mF\xabgy\xc1\xbf\x02\xc4I\xba\ \x1cx\x00\xac\x08`\x98O^\x02_\x1a\xadF!\x13\ N\xd2\x08\xb8\x05l\x16Nh\x03\xd7\x80+\xc0\x1f\ \xc0dVV<\x8am;\xe6\xd9\x1cRv\x9e\x11S\ \x1dr\x03\xeb\xa4\x97\x03{\x01\x8d\xec\x8c\x1f\x02\x1b\x8d\ V\xad\xfc\x0b\xf7!w\xfe9\xf0\xad\xd1\xea\xe1\xacM\ \xf7\xcf\xc58I\xbf\x00\xce\x02\xabKu\xeb\x81\x03\xc0\ \xa9\xa1\xec\xd7\xff\x13XYj\xf4\x17\xf0u\xd9i\xf4\ \x1aq\x92.\x01\xee\x02kJU\xa3\xc0\xc7\x11\xf0\x15\ \x9d\x9do\x01{{\xbd\xf3\x00F\xabW\xc0\x1e\xec\xd4\ -\xf2\x11\xb0)\x02F\x84\xf3\xce\x1b\xad\x1e;\xb6\xcd\ \x1b\x99\xd7?'T\x8dD\xc0\xa7B\xc5Y\xb7&\x05\ A\xea\xd3\xba\x08X(T\x8c\xba\xb5%\x08\xa3B\xd9\ \xc2\x08{\xdb(\xd3tkK\x10\xa4>\x0d\x1774\ EZBY\xaf\xd3\xa2s\x8d\xd2\x90\x04h\xd3\x9f\x02\ H\x0b\xb4\xc6t\xdb\xd6~B\x12 \xaa\x9a\x02.\x97\ \xb3u\xa2\xd1@\x1e\x01N\x05\xc8V\x9f;\xb0\x8b\x11\ \xb0?B\x1b\x98\x00\xceH\xfb\xf69@\x1c\x01\xb3}\ 2\xf3^d\x1d\xdf\x05\xfc\x08|.4i\x03\x97\x81\ 7\xbel\xcawPN\xc9:\xbe\x1b\xdb\xf1\xcf\xa6i\ .\xdd\x96]\xd1\xf0\xd1\xf9\xed\xd8GR\xebf\xd0\xdc\ \xbbSv*@\x9c\xa4\x87\x80c\xefy\x9a\xd7i\xe9\ Zqos\xf9\xffR%\xc0\x5cy\xe1\xda\xef(]\ \xcf\xb7\xa7L\x1d\x05M\xe08p\xb4\xcb9\xde\xa7\x80\ 3\x8cV\x93\xc0=l\xc7O\x00\xab\x8cV?`_\ Z\xd4\x02\x1fj\x1f\x04&\x8dV\xe3\x85\xb2\xda\xec5\ \x9c\x0b`\xb4\x1a\x13\x8ak\xb3\xd4\x0e\xb5\x11\x9a\xf7\x02\ \xd4\x86\xc1\x08\x08t\xddy/@m\x18\x08\x10\xda\x80\ \xd0\x0c\x04\x08m@h\x06\x02\x846 4\x03\x01\x02\ ]\xb7\xf6\x0b!\xd7\xc2\xd4J\x80\xda\xec\xcd3\xbc\x8a\ SG\x1f0/\x04\xa8\xcd\xa8\x0b5\x05\xaa\xae\xd9\xa6\ 3\x98\xc9\xa9\x1d\xa1F\xc0\xdb.u^\xa3S\xf2\xb7\ \xb2e\x5c\x0bs\x1f\xd8\x0f,\xe6\xbf\xe7\x92M\xe0\x85\ \xd1\xaa\x9b8\xb3A|\xff\x11D\x00\xa3\xd5\x04p\xc6\ \xe55fH\xbb\x8e\xb7AWH?jK\x12\xa0_\ \xc3f*\x05\x10\x83\x87\x1c\x1b\x13\x02)\x1a\xa6\x1d!\ \xdfv>po\x8fw\xc4x\xc8\x08\xf9\xb6\xb3\xd4\xb1\ 1!X\x22\x945#l\x12D\x99\x9d\x8e\x8d\x09\x81\ \xd4\xa7\xe7y\xa6H\x99\xef\xb28\xfb\xbe N\xd2\xc5\ \xc0\xf7B\xd5\xad\x08\xb8\x0e\xfcS\xaaX\x04\x9c\x8e\x93\ \xb4\xe7\x9da\x16\xa0\xf5\x0b\x9dS`\x02\xb8\x16\x19\xad\ \xf2w\xf7e4p!N\xd2E\x8emtF\x9c\xa4\ \x1f\x02\x17\xb0\x11jeN\x1a\xad\xde\x0c\x15\x1a\xfe\x8e\ \x9c.\xf7\x02\xf8\x19\xb8\x04\x8cgA\x0f\xb5%N\xd2\ a\xac\x13\xff\x068\x8cM\xa0*3\x06\xac5Z\xbd\ .\xa6\xcdm\xc2\xfa\x83\xaa8\xbdb\x96X\x9e9\x06\ \xf2:\xc2\xd5\xeaR\x9a\x92Q\xe1o1\xad\xb7j1\ 7\x89\xcd\x1d\xbc\x03\x9d\x89\x93\xbb\xb1C\xc6g\xb0\xa2\ OZ\xd8,\xb8Ky\xc1\x14\x95\x8cVW\xb19D\ =\x9f,%0\x0e\x8c\x14;\x0f\xc201Z\xdd\xc6\ f\x8a\x9f\xa0?2Gr'\xff\x89\xd1\xeaf\xb9\xb2\ 2{\x1c N\xd2\xa5X\x0f\xba\x05\x9bw\xd7+K\ \xe4&\xf0\x0c\xb8\x81\xcd\x1a\x7fU\xd5\xf0\x1d\xe0B\x07\ {\xefo\x92\x85\x00\x00\x00\x00IEND\xaeB`\ \x82\ \x00\x00\x06'\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x05\xeeIDATx\x9c\xe5\x9bo\x88\x16E\ \x1c\xc7?.\xc7q\xc4U\x12!\x222\x5cr\x98\xa4\ \x82T\x84H\x84\x84\x84\x8a\x0edi\xd2\x8b\x0d\x950\ \xb8\xc0\xab\xd04IQ*\xb5\x17\x86\xf6\x22\xf1E\xe8\ \x94\x96\x99\x9ac\x1d\xe1\x9f\x08\x22\x15)\xb5\x92\x08\xb1\ C\x86\x90\x12\x93\x88\x90C\xe4\xa1\x173\xcf\xf5x\xee\ \xec\xb3\xfb\xec\xce\xf1<\xf6yu\xb73;\xbf}\xbe\ \xbb\xfb\x9b\xf9\xfd~\xb3#(@\xacM70\x0d\x98\ \x0c\x8c\x05\xee\x02\xda\x81\x1b\xc05\xe07\xe0W\xe04\ \xf0\x9d\x92b\xa0\x88\xbd\x10\x8c\xc8{B\xac\x8d\x00\x96\ \x00\x0b\x81\xf19N\xfd\x078\x0c\xec\x04\xfa\x94\x147\ \xf2\xda\x0eAf\x01bm\xba\x80\xb5\xc0\xb3\xd8\xbb\x5c\ \x84~7\xd6n%E\xa5\xe0X\x85\xa8+@\xacM\ \x1b\xd0\x0b\xac\x03\xee(\xd9\xfeI`\x89\x92\xe2\xe7\x92\ \xc7\xcdL\xaa\x00\xb16\xa3\x81\x8f\x80\xe9\x01\xafa\x00\ \xe8QR\xbc\x1f\xd0\x86\x17\xaf\x00\xb16\x0f\x00_\x00\ ]\xc3t-\x9b\x81\xe5\xc3\xfdJ\xb4%\x1d\x8c\xb5\x99\ \x04\x1c\x03Fe\x18\xe3\x22\xf0\x15\xf0\x13\xd6\xeb_\x03\ :\xdc\xb9\xf7\x03S\x81\x87}\xb6jx\x19\xe8\x04\x96\ f\xb0Y\x1a\xb7<\x01\xb16c\x81\x13\xd8i\xcdG\ \x05\xf8\x0cx\x078^\xef\xae\xb9W)\x06^\x02F\ \xd7\xb9\xa6\xb5J\x8a\xf5u\xfa\x94\xc6M\x02\xc4\xda\xb4\ \x03\xdf\x00\x8f\xa4\x9cs\x16X\xaa\xa48\x95\xd7X\xac\ M'\xd6\xfb\xf7\xe2\x7f\x22*\xc0\x5c%E_\xde\xf1\ \x1ba\xa8\x00\x1b\x80\x95)\xfd\xb7\x03\xcb\x8a.hb\ mf\x00{\x80{<].\x03\x93\x95\x14\x97\x8b\xd8\ \xc9\xc2\xa0\x00\xee\xbd?\x83\xff\xce\xbc\xa1\xa4x\xbd,\ \xc3\xce\xde\x11\xfc\xaf\xc4v%Ep\x7f\x10\xd5\xfc\xbd\ \x01\xff\x8f\xdfV\xe6\x8f\x07PR\x9c\x03faW\x88\ I,v3QP\x22\x80X\x9b)\xc0\x1cO\x9fS\ \xc0\xb2\x10\xc6\x95\x14g\xf1{\xfd6`y\x08\xbb\xb5\ T\x9f\x80\x1eO\xfbu`\x91\x92\xe2z\xa8\x0bPR\ \xec\x06\xb4\xa7ya\xacM\x96\xa9\xb8a\x22\xe7\xf9\x17\ x\xdaw\x0c\xd32u96\x82\x1cJ\x070/\xa4\ \xe1\x08x\x14\x1b\xc6\x0e\xa5\x02l\x09i\xbc\x8a\x92\xe2\ <\xfe\xa7`nH\xdb\x116\x9eO\xe2\xc7a\x0eR\ vz\x8eOs\x01Y\x10\x22`\xa2\xa7\xedh(\xa3\ )\xf6\x92\xd6\x17#\x09\x18\x8fD\x80\xf0\xb4\x9d\x09e\ 4\x09%\xc55\xe0\x17OsW(\xbb\x11\xc9\xef?\ \xd8 g\xb8\xb9\xea9\x1el&\x88\xb0\x9e6\x89\xbf\ C\x19M\xc1\x17T\xf9nRa\xa2\x14\xa3\xff\x0b\x22\ l\xfc\x9e\x84/P\x09\x89\xcf\xdb\xfb\x96\xcb\x85\x89\xb0\ \x91W\x12\xdd\xa1\x8c\xa6p\xaf\xe7\xf8\xef\xa1\x0cF\x80\ \xf1\xb4=\x14\xcah\x12\xb16#\x81\x09\x9e\xe6\xfeP\ v#\xe0\x07O\xdb\x8cPF=\xcc!\xf9\x15\xf8\x0b\ \xffM*L\x04\x1c\xf7\xb4\x8d\x8f\xb5\x99\x1a\xcap\x02\ K<\xc7O\x86,\xa2D\xd8\x14\xd7%O{\x900\ x(N\xe8\xe9\x9e\xe6C!mG.\xa1\xf9\xb1\xa7\ }A\xac\x8d/V(\x85X\x9b\x08\xd8\xe4i\x1e\x00\ >\x0di\xbf\x9a\x0fx\x8f\xe4p4\x02v:\x07\x15\ \x8a^\xe01O\xdb'\xa1\xf3\x82\x11\x80\x92\xe2\x02\xb0\ \xdb\xd3\xa7\x1b\xd8\x13k\xe3[16L\xac\xcdL\xfc\ w\xff:\xf0f\xd96\x87R\x9b\x13\x5c\x85\x7f\xc1\xf1\ \x04\xb07\xd6\xa6\xb4\xda\xa0\xfb\xf1\x07\xf0/~\xb6\xba\ 0\x13\x7f\x12\xa3\x96\x0a\xd6I\xee\x07>\xf0-\ p\x9c\xc8\xdf\x03y\x8b\xa2\x0dW\xaes\x0bP\x8b\x0b\ d&\x00\x0f\x02c\x80\xbb\xb1[\xe8*\xd8@\xe6O\ l,\x7f\xca-\xb4\xb2\x8cy\x08\x7f\xa16\x8d\x8dJ\ \x8aUyO*$@\x08bmva\xf7\x226B\ \xee\xb5C(\xcf^\x84\x22\xd9\x9f\x15\xb16\xbe\xe0*\ \x91f\x14\xe0D\xc1\xf3s\x89\xd0\x8c\x02\x1c\xa6x\x16\ 8\xb3\x08M'\x80\xdb\x80\x95\xdb\x99%\xb0\xc2m\xfa\ J\xa5\xe9\x04\x00PR\xec\x00T\x09C\xad\x8c\xb5I\ M\xaa4\xa5\x00\x8e\xe7\x81\xcfK\x18\xe7\xb54\x11\x9a\ n\x1a\xac\xc5-\x8c\x0eb3REY\xaf\xa4\xb8%\ \xc9\xd2\xccO@\xd5\x1f\ ln\xa2Q\xfa\x9az\x1aL\xc3M\x91O\xe1\xdfa\ \x9a\x85\xee\x96\x15\x00\x06E\x98\x8f\xcd45B{K\ \x0b\x00\xe0\xd2\xe3\xcf\xe0/\xee\xa6q\xb5\xe5\x05\x00p\ ;H\x9e\x03\xf2~{\xd8\xd7\xb2N0\x09\x97\xa3\xdc\ \x02\xbc\x98\xa1\xfb%`\xe2m%@\x95X\x9b\x95\xd8\ O}}\xdf8_\x06f))N\xdf\x96\x02\xc0\xe0\ \xc7\xde=\xd8Ucu\x87\xcb\x00\xf0%\xb0\xa9Z\xd0\ \xfd\x17B<\xa9'\x9e\x95\xe2\x0b\x00\x00\x00\x00IE\ ND\xaeB`\x82\ \x00\x00\x07\xb3\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x07eIDATx\x9c\xed\ \x9bm\x88]\xc5\x19\xc7\x7f\xb9\x84%HYB\xb0K\ \x08\xe1$\x86(\x12J*\x11\xa3h|\x89Q[1\ \x8c-\x1aEcB\xc7Z\xd4T\xab\xb6\x0d~\x10\x11\ \xf5\x83\x90\x1a\x92\x0aJ\x1b_N\xda\x98*\xbeD\x1d\ \xa3&\xc4DSb#\xda\xa6!j\x14\x1b%\x0e%\ \xd8\x10\x82\x84\x12\x96\xe5\xb2\xf8\xe1\x99\xb3\x9e=w\xe6\ \xde\xf3\xba\xfb\xc1\xfd\xc3e\xcf\x9ey{\xfe\xff33\ \xe7\x99g\xe6\xc0\x04&\xf0\xbd\xc6\xa4&*\xd5\xc6\xf6\ \x03S\x81\x160\x0c\xb4\x81\xc1XE\xc7\x9bh\xaf\x0a\ *\x09\xa0\x8d\x9d\x0d\x9c\x07\xfc\x18\x98\x07\xcc\x05\x22\xe0\ \x07\x81\x22\x0f\xc4*z\xa8J\x9bu\xa3\x90\x00\xda\xd8\ \xc9\xc0%\xc02\xe0\xa7\x08\xd9\xa2X\x13\xab\xe8\xde\x12\ \xe5\x1aA.\x01\xb4\xb1S\x81U\xc0\xed\xc0\xcc\x1a\xda\ }\x0c\xb8'V\xd1p\x0duUBW\x01\xdc\x13\xbf\ \x03\xb8\x1f\x98Vs\xdbO\x00w\x8e\xb7\x08A\x01\xb4\ \xb1\x11\xf0\x1cp~\x83\xedo\x00n\x1fO\x11\xbc\x02\ hc\xe7\x01;\x80\x199\xea\xb0\xc0\x07\xc0G\xc0g\ \xc0a\xe0\x11\xe0\xd2\x9c6<\x03\xfcj\xbcD\xe8\x10\ @\x1b;\x03\xf8\x90\xee\xe4\x0f\x00\x9b\x80\xad\xb1\x8a>\ K\x95\x9d\x0c\xc4\xc0M\x05\xed\x187\x11&{\xee\xc5\ \x84\xc9\xefA^e\xbb\xb2\x09\x8e\xfc\x93\x84\xc9oA\ |\x82k=i7\xbb:\xc6\x5c\x84Q=@\x1b\xab\ \x80\xd7<\xf9\x06\x81{\x80\x0d>\x03\xb5\xb1-\x84\xfc\ \xcd\x81v\xb6\x007\xb8\xeb\xcd\xf8E\x00\xf8+\xf0\xcb\ XE\xed\xde\xa6\xd7\x83l\x0f\xb8\xcb\x93g\x10\xb8\xca\ \xf7\xd4a\x84\xfc\x9f\xe9A>V\xd1\x90\xcb\xbf\xdc\xdd\ \xf7\x89\xb0\x12hic\xf5X\x89\xd0J.\xb4\xb1\xd3\ \x80\x8b\x07\x8e\x87\x166n\x02[\x0b,\x02\xfa\ \x80#\xc0\x83\xb1\x8a6f\xf2\x95\x11a\x08\x896y\ \x1d\xb8,|=\xa0\x85\xac\x08W\x16h4\x8ba\xe0\ \x04\xf2D\x8e C\xe78\xd2s\xfa\x5c\xdd>\x07\xe7\ \xdeXEk2\xf6\x94\x11\x01`=27t]]\ f'\xc1^\xeem\xd3\x18\x02N\x8fUd\xd37+\ \x88\xb0\x11\x893\x04\x17V\xd9\xd9~\x1da\xf2\xdb\xdc\ \xaf\xc9UZ\x1f\x12m\x1e\x85\x94\xb3\xf4B\xc1\xfa~\ \x01<\xe9\x1e\xac\x17\xe9\xd5\xe0o\x81\xdf\x04\xf2m\x01\ \xae\x8eUt%\xe2\x04\xdd\x09\xbc\x8dt\xe9\xba\xe1\xdd\ SH\xb9\xcdeDx$\x948\x09\xc0\xb9\x97\xef\xe1\ \x8f\x10\x19`\x99\xcf\xc9qN\xd0B\xf7;\x9b\xef6\ GN)hd\x1a\x8bc\x15\xbd\x1bJt\xcb\xe4\xcd\ \x14\x1f\x0e+|\xbeB\x22\xc0^d\x87'\x8b7\x81\ \x9f\x17\xf1\xf0\x5cw\x9b\x81l\x9a\xcc\x04\xa6\x03?D\ &\xbd\xa9.\xed\x92@\xf1=\xc0\xc5\xbd&\xae\x92\x22\ \x9c\x04\xce\x89Ut0}s\x926v\x01\xf2\xfa\xca\ \xe2\x1f\xc0\xe5\xbewtUhc\xefF\xba\xe5\x94\xd4\ \xed]\xc0\xf5y}\x8a\x92\x22\xec\x03\xceMO\x8a-\ d\x9b+\x8bo\x90n\xdf\xc4\x18'V\xd1z\xe04\ `\x05\xb2\xdbtA\xac\xa2%E\x1c\xaa\x92s\xc2\x02\ 2^\xee$m\xecN:c\xf8\x8f\xc6*Z]\xa0\ \xe2q\x83[\xae\x7fJ\xfey\xe7\x04\xf2\xaa=\x0a\xd2\ \x03|!\xf0\xbd\xf5\x98\xd7,\xdc\x1e\xc6v\x8aM\xba\ \xfd\xc0\xc8\xc3m\xe1_\xf9\x9d\xa8fZ\xf3p\xe4w\ \x22K\xf1\xa2\xb8\xcdm\xf8\xd2B\xc6{\x16\xb3\xcb\x9b\ \xd6<*\x92\x07\xf15n\x04\x11\xe0\x90'\xc35%\ +n\x1c5\x90O\xb0\x02D\x80\xf7<\x89Whc\ \x97Vl\xa0v\xd4H\x1e`\xa16vz\x0b\x89\xc3\ eC\xdf-`s\xdd\x01\xc8*\xa8\x99<\x08\xc7K\ [\xeeu\xf0'O\x86~\xe0\x0dm\xecY55X\ \x1a=\xc8\x0f\x03\xcf\x02\x7f\x03\xf6\xbb\xff\xf3\xe2\xc2\xc4\ \x15\xeeG\xbc\xc1\xb9\x9eLG\x81%\xb1\x8a>.b\ t]\xe8A\xbe\x8d\x84\xc1\x9eI\xe5\x9f\x8d,\xd6V\ 1\xda\xd3\xf4a\xcfH<@\x1b;\x17\xd8\x8d\xdf/\ \xf8\x1aq\x8b\xc7T\x84\xa2\xe43e\xe7\x01/\x07\xca\ &\xf8|\xc4\x07\x88Ut\x08XB`\x83\x04\xd8Q\ W,>\x0f\xaa\x90\x07p\x8b\x9e\x8b\x91S+!\xf4\ \x8dr\x82\xdci\x8f\xcb\x91\x10V\x16c&B\x8e1\ \xdf\x95|\x027\xbf-\xa3s\x92\x1fA\x87\x17\x18\xab\ \xe8\x00\x22\x82/\xfe?\x83\x86E\xa8\x8b|\x027l\ \xd7\x87\xd2\xbd\xa1\xa2XE\xfb\x19\x07\x11r\x92\x7f\xaa\ D\xd5\xeb\x08D\xaf\x82\xb1\xb2XE\xfb\x80\x9f0F\ \x224H>\x19\x0a\xdb\xb9\x0f\xff\xc6h\x1b\ \xd0e\x0f:\xe4\x816v7\xa3\xcfB^]\xf5\x93\ \x99\xf9\x88\x08\x03\x81,\xc3\x88\xeam\x97'\xd4\xe3\xda\ \xc8\xce\xcd\xf3U\xec\xe9\x05m\xec+\xc0\xcfR\xb7f\ \x15\x1e\x02i8\xb7y1\xb2\x05\xeeC\x0b\xe9!\xd3\ \x09\x93\x1fB6D\x1a%\xef\x90\xb6\xd3\xc6*\x0a\xef\ \x9a\xe6Ej\xd5\xe5\x8b-\xf6\xc2 pM\xac\xa2-\ U\xed\xc8\x89/R\xd7[\xa1\x8b+\x5c\x04n)}\ \x01\xb2\x97\x98\x17\xfb\x90\x1d\xa1\xadu\xd8\x90\x13o\xbb\ \xbf\xc3\xc89\x88\xfa\xbf\x1b\xd4\xc6.B\xb6\xbb\x96\xd2\ y\xc4\xe6$\xb2\x07\xf84`\xc6\xe3\x03\x09m\xecZ\ \xe0\x7f\xc9I\x94F>\x9ct\x0d\xb5\x10\x0f/\x99 \ \x8f\x01\x87\xaa\x9e%\x9c\xc0\x04&P+\xbe\x05\xfe~\ \xd34#GF \x00\x00\x00\x00IEND\xaeB\ `\x82\ \x00\x00\x03\x82\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x03IIDATx\x9c\xed\x9b1h\xd5@\ \x18\xc7\x7f/\x96RD:\x14\x91.\x06qp\xe8`\ kA\xddT:\x96\x12\xc4\xa1B\x85\xeb \x0a\xa2{\ \xa7\xea\xa6P\x07GEqh\xa4\x15\xd1\xe9tp\x15\ \x15\x07q\x91\xb68\x88\x96\xc3\xa9\x94RE\x05k}\ 8\xbc\xa6\xbe\xc6\xe4\x92K_^\xd2$?\x08\xbc\xf7\ \xf2]\xee\xbb\x7f\xbe\xbb\xefr/W\xc3\x87\x90\xea\x18\ 0\x0e\x1c\x06v\x03\x9d\x80\xe5;\x9a\x09\xfa-\x8a\xf5\ \x14l\xeb\x80\x04n\xba\x8e\xbd\x12\xf7\xe25\xef\x83\x90\ \xaa\x1b\xb8\x07\x8c\x1a8\x97G\x96\x80\xf3\xaec?\x8b\ c\x5c\x83\xcd\xc6\xbf\x00\x06bV\xb2\x0a<\xc1\xecN\ &\xc1\x1f]\xde\xf7\x0e\x1a\x91\xb9\x0f8\xc1\xff\x11X\ \x07&]\xc7\xbe\x1eU\x81'\xc0\x0c0\x16\xd3\xa9%\ \xe0\xb8\xeb\xd8\x8b1\xedSEHu\x06xLp7\ \xbc\x03\x5cv\x1d\xbb\x1eV\xbe&\xa4\x1a\x04\xde\x19\xd4\ 9\xe1:\xf6\x94\x99\x9bf\x08\xa9\x9a\xc7\x9b\x0e\xdf\xe9\ 5\xd7\xb1\xd7}\xf6\xf3@_\xc8\xe5f\x81q\x7f\x19\ \x0f\x0b8g\xe8\xdfwC{#\x84T]\xc0W\xe0\ 7\xf0\x0b\xf8\xe1;\x86\x03\x8a\xadj.9\x06\xcc\x08\ \xa9\xfcB\x02\x0d\x01\xc2\x94\xcb\x0a\xaf\x7f\x9b\x105\x16\ \x8d\x12\x22\x82\x05t\x19V\x16\xda\x9fZH\x1aiu\ \x14\x98\xde\xe8^[*2U;m\x01L\x1b\x0f\xf1\ \xb3\xd1\x18p\xdb_Y`\xdf(0\x17\x85TW\xbd\ /Ifqi\x93\xc4'\xd3\xa8\xbc&\xa4:\xedU\ f\x1a\x01iO~\x92`*\x80\x05\xdc\x17R\xf5\xe6\ 1\x02\xdaE\x0f0Yf\x01\x00\x86\xcb.@\xea\x8f\ \xb2\xb9\xa7\xd4w\x1f\xf2\x99\x06\xdbJ\x12\x01\x0a5q\ *\xf5\xdd\x87*\x02*\x01\x924\xa6\xa7\xe5^l\xe5\ \x1b\xd0\xaf9\xaf\x02~3}\xa4\xdf\xa4&\xa4\xfa\x0c\ \x1c0(\xb3\x00\x1cu\x1d\xfbg\xd2J[\x89\x90j\ \x00xK\xb2\x9b\xb9\x98\xa4P\x1f\xf0RH\xf5\x80\xc6\ R\xd4:\xff&Gu\xda\xb3`\xe2q\x10\x98`\x1b\ \xdd2i\xc1\xc1\x8dc\xc7S\xa5\xc1\xac\x1d\xc8\x9aJ\ \x80\xac\x1d\xc8\x9aJ\x80\xac\x1d\xc8\x9a8i\xf0.p\ \x0bX\xa3\x91\xef\xbd<\xdf\xbc0\x92\xe6\x22\xc9v\xa6\ \xde\x02\xb8\x81\xe6FG]\xfc\x15pI\xf7\xefj\xce\ \x99\x12R\xed\x07\xae\x84\x19Du\x81\xf7;\xb8\xf1\x1e\ \xf3\xba\x93Q\x02\xac\xb5\xd0\x91\x5c\x12%@\x11\x16@\ \xb5m\x88\x12`\xa7\x87\x7f$e\x88\x00-\xa5\x9f\x07\ T\x11\x90\xb5\x03m@;\x8eU\x02D\x18\xfci\xad\ /\xf9#J\x80\xd2\xa7\xc1\xc2S\x09@\x09R\x9d\x8e\ 2D@\xe4\xb3@\xe1\x07:\x1d\x95\x00T\x02h\x05\ (\xfc\x18\x11\x95\x05v\xb5\xcb\x91\xac\xa8\xba\x00\xc5\x9f\ \x07h\xbb\xb1\x85~\xe1\xb3\x08c\xc0\xb6\x04(\xd4\xfb\ @\x01\xd4-\xe0\xa3\xc6\xa0\x08\x02\xe8v\xc4(\x0bx\ \xa81H\xfb\x85\xa8v\xd0\xad9\xf7\xc8\xdb8\xf9\x14\ \x18\x090X\x06\x8e\xb8\x8e\xfd%\x0d\xcf\xd2fcG\ \xec\x1b\x82w\xc6}\x00\xfa=\x01\xf6\x02\xaf\x81C\x01\ \x86\xcb\xc0s\x1a\xfb\x05u\x7f\x90\xfaI\xe3\x85\xa9\xb0\ \xf7\x1a\xfd\x9b\xbb;\x81=\xc0)\xc0\x0e\xb0_\x01N\ \xba\x8e=\xd7\xbcy\xba\x17\x98\x01\x86Z\xebs\xee\x98\ \x03\xce\xba\x8e\xbd\x00M\xbb\xc7=\x84T#\xc0\x05\x1a\ \xdb\xe7\x8b\xc4'`\x1a\x98m\xdeF\xfb\x17;\x8a\xc3\ $\xe7(\xef\x8b\x00\x00\x00\x00IEND\xaeB`\ \x82\ \x00\x00\x03\x8f\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x03AIDATx\x9c\xed\ \x9b?h\x14A\x14\x87\xbfH\x08\x22A$\x04\xb1\xb2\ PHc\xd0`#\x08j\x10A\xc5?\xa0M\x1c\xd0\ QG\x05\xdbt6A\x84\xa8\x85uP$\x8e2\x22\ #\x16\x12\x22\x01AE\xd1\x14*b!ADR\x04\ \x15I%\xc1\x22\x84C\x0e\x8b=!l\xf6\xeev\xef\ \xb2\xfbn\xcd~p\xcd\x9b\xd9w\xbf\xf9\xdd\xec\xee\x9b\ \xb9\xdd6b\xa2\xacn\x07\x0e\x00\x87\x80\xed@7\xb0\ *\xee\xf1\x82L\x03#\xde\xb8\xb1\xa8\xc6\xb68\x19\x94\ \xd5'\x81\xab\xc0\xc6e\x14\x965\xc3\xde\xb8\xa1p\xb0\ \xa6\x01\xca\xea5\xc0}\xe0xZ\xaa2\xa4\x0c\xec\xf0\ \xc6}X\x1c\xac:\x85\x95\xd5\xab\x81\x09\xfe\x8f\xc1C\ 0\xd6\x81\xa8`5F\x80\xfe\xb4\xd4\x08\xd1\x1d\x0eD\ \x1a\xa0\xac\xde\x0b\x98\xd4\xe5\xb4\x00\xd5f\xc0\xe5LU\ \x08\xb2\xc4\x00e\xf5&`\xb7\x80\x16\x11\xa2f\xc0\xbe\ \xccU\x08\x12e\xc0\x96\xccU\x08\x12e\xc0\xba\xccU\ \x08\x12e@9s\x15\x82\xe4\xa1\x96O\x95\xc2\x00i\ \x01\xd2\x14\x06H\x0b\x90\xa60@Z\x804\x85\x01\xd2\ \x02\xa4)\x0c\x90\x16 Ma\x80\xb4\x00i\x0a\x03\xa4\ \x05HS\x18 -@\x9a\xc2\x00i\x01\xd2\x14\x06H\ \x0b\xc8\x98R8\xb0\xd2\x0cx\x13\x0e\xac$\x03>\x02\ \x0f\xc3\xc1\x95b\xc08\xb0\xdf\x1b\xf7'\xdc\xd0\xdeD\ \xd2\xcf\xc0\x03`\x8a\x88s\xabE(\x01_\xbdq?\ \xaauh\xc4\x80\x120\x08\xdc\xf2\xc6\xe5\xfe_\xa4\xa4\ \x06\x94\x81\x81jO\x5c\xa5\x85\xb2\xfa0p\x8c\xfa\xa7\ \xec\xac\xd1\x05l\x8d\xdb9\x89\x01\ 3\xde\xb8\xe9\x84b\xa4\x88=\xae$\x06\xcc6 \xa4\ \xe5Ib\xc0\xda\xd4T\x08\x92\xc4\x80\x1eeuWj\ J\x84\x882`I\xb5T\xa1\x1d8\x9f\xa2\x16\x11\xa2\ \x0c\xf8^\xa3\xff\x90\xb2\xba'-1\x12D\x19\xf0\xbe\ F\xffN\xe0\x99\xb2\xba/%=\x99\x13U\x08\xbd\x02\ ~\x11\xdcO\xa3\xd8\x08\xbcSV[\x82\xb5\xc0'o\ \xdc\xeft\xe4\xa5\xcf\x12\x03\xbcq\x0b\xca\xea\xdb\xc0\xa5\ \x1a\xc7u\x00\x17+\x1f\x94\xd5ih;\xeb\x8d\xbb\xd7\ L\x02e\xf5]\xe0\x0c\xc1\x82m\xd0\x1b\xf7<\xdc\xa7\ \xda]\xe0:\xf0\xb3\x99/o1z\x81\x09euo\ \xb8!\xd2\x80\xca\x94V\xb4\xee2\xb7\x11:\x80s\xe1\ `\xd5:\xc0\x1b\xf7\x9a\xe0\x05\x83\x85\x14EeMg\ 8P\xb3\x10\xaa\xac\xfcv\x01_\xd2R\x941/\xc2\ \x81\xba\x95`\xe5\x1d\x9bm\xc0\x05\x82}\xb5\xbcb\x81\ G\xe1`\xac\xfd\x00o\x5c\x09\x18\x05F\x95\xd5\x1b\x80\ >`=\xe9\xee)N.C\x8e;\xc0K`\xca\x1b\ \x17\xf9\xe3%\xde\x12\xf3\xc6\xcd\x02O\x9b\x14\x96\x09\xde\ \xb8I\xea\x18\x99\xd7]\xe1\x05\x82\x199F\x93O\xb7\ 7\xb3+,\xc5\x0cp\xe4\xdf\xbe\x9f\xb2\xfa(AE\ \xba\xe4\x0a\x1f\x87\xbc\xcd\x80\x19`\xcf\xe2MOo\xdc\ 8\xc1\xeb\xbc\xf3\x8d$\xcc\x93\x01s\xc0Ao\xdc\xb7\ pC\xa5f9E\x03\xa7C^\x0c(\x03\xca\x1bW\ \xb5\x1e\xf1\xc6=\x06\x86\x93&\xce\xcb5\xe0\x9a7.\ \xce\x9d\xe7\x0a\xb03I\xe2<\xcc\x80\xb7\x04\x03\xabK\ \xe5\x9f\xaa\xd3\x04\xcb\xf9X\xfc\x05\xe1\x07\xb6\xa1@\xb8\ \xf3\x9c\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x06\xb4\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x06{IDATx\x9c\xed\x9b\x7f\x88TU\ \x14\xc7?\xb3\x0c\xb2\x88\xc8&f%\xcbEMDD\ \xac\xc4\x22Bb\xcd\xca\x82|\x0a\x91\xae\x9b{\xc5~\ i\x9aeIQ\x84\x88XHDfF\xf6\xc3${\ \x96i\x94\xdaM\xc44\xb7MB\x97\xa2\x10\xfb\x81\x94\ \xc8r\xdb\xc4\xc4\x96-d\x90eY\xfa\xe3\xbc\xa9\xd9\ 73\xef\xc7\xcc\xec\xdbu\xdd\xef\x9fs\xcf=\xf7\x9c\ \xf3\xee\xbd\xe7\xd7\x1d\x18\xc4 \x06q9#\xd5\xd7\x02\ \xf46\xb4\xb1\xc3\x80\xe7\x81\x85\xc0(\xe04\xb0\x15\xd8\ \xe4:\xaas@\x1b\xc0S\xfek`j\x81\xe1&\xe0\ \xee\xaadEJ\x1c\xab)\xac<\xc0m\xc0\xca\x81n\ \x80\x85!\xe3\x0b\x06\xac\x01\xb4\xb1C\x913\x1f\x84\x9a\ \x01k\x00\xd7Q\x19\xe0|\x08Y\xc7\x805\x806\xf6\ )\xe0\xea\x10\xb2\xed}\xe6\x05\xb4\xb1\xd3\x81\xe9@\x15\ \xd0\x024\xbb\x8e\xea\xae\x10\xef\xc7\x81W=\xde\xc5\xb0\ \x1f\x98\x93\xb8\x01<\xd7\xb4\x1d\x98\xeb\x1b:\x02\xdc\xeb\ :*l\xdb\x86\xf1_\x0a\xbcAO\xe5\xbb\x80V\xa0\ \x069\x16\xef\x01\x1b\xfb$\x0e\xd0\xc6\xee!_\xf9,\ \x9a\x81\x99\xa5\xee\x04m\xecC\xc0\xdb\xf4T\xfe\x02b\ \xd8\x83\x85\xe6$z\x07hc'S\x5cy\x80:\xe4\ X\x94\xc2[\x93\xaf|\x06\x98]LyH\xd8\x00\xc0\ M\x11hn\x8d\xcbT\x1b\xdb\x80\x84\xb7~\xe5\xe7\xb8\ \x8ej\x0e\x9a\x9b\xb4\x01j\x22\xd0\xcc\xd7\xc6N\x88\xca\ P\x1b[\x0f\xbc\x0f\xa4s~\xbe\x88l\xfb/\xc3\xe6\ 'v\x07hc\xaf\x07\xf6\x00c\x22\x90g\x80u\xc0\ \x06\xd7Q\x9d\x01<\x1b\xc8W\xbe\x13Q~_\x14\xb9\ \x121\x80'\xe8\x16`h\xcc\xa9'\x81']G\x1d\ \xf0\xf8Ty<2\xc0\x03\xc0\x9b\xe4+?\xdfu\xd4\ \xde\xa8\x0b\xf4\xaa\x01\xb4\xb1i\xe0%`%\xe1\xc7\xed\ \x1c\xc5C\xd7&$\x8d\xbd\x07\x18\x89\x18`\x98\x8fg\ 'p\xbf\xeb\xa8O\xe2\xc8\xd8k\x06\xd0\xc6\x8e\x04>\ \x02n/0\xbc\x11\xf8\x90\xff3\xb5\xa3\xc8\xd7n@\ \x0c\x16\x16\xc1\xf9\xd1\x054\xba\x8e\xda\x19W\xce\x8a\x18\ @\x1b;\x0a\xf9:c\x81\xbf\x81_\x81\xd7\xc8?\xef\ \x19\xe0a\xd7Q;\x02x\xd5\x00k\x81e\xf4\xdc\xde\ \xc5\xd0\x0d,v\x1d\xe5\xc6\x97\xbc\x02\x06\xd0\xc6:\xc8\ E\x14v\xc3\xb7\x22\x97\xd3\x0f\x11\xf9NE\x22\xba\x9b\ CH;\x5cG]\x11\x85g!\x94\xe5\x06\xb5\xb1S\ \x80]\x84+\xdf\x04\xdc\x18Uy\x00\x8fv\x06r\xb6\ {\x0d\xe5\xc6\x01\xcf\x01\xd5!4\x9b\x80Y\xa5\xc4\xf8\ \xae\xa3.\x22\xc7)\x08e\xe5\x0e\xe5\x1a J\xd8\xba\ \xc6uTW\x19kl)s<\x10Q.\x99\x02\x0cG\x92\x89\xbd\xc0g\xc0\x0a\x82\ \x15?\x0a\x8c\xa6\xa7\xcf?\x07<\xea:jw\xe5E\ \xae,R\xde\xf6:D\xf4m\x9dE\x13\xb0\xceuT\ \xb3\xc7\xa3\x0e1B\x1bp\xc4+J\xf6{\xa4\xb4\xb1\ \xcb\x90\x80#*\x0e\x22\x8a\x7f\xd3K2%\x8a40\ ?\x22\xed~D\xf1\x96^\x94'q\xa4\x89\x96x\xcc\ \x0a*+]\xca\xa8B\xd2\xcc \xb4#\xe7}@\xa2\ \x0a)\x11\x07\xc1-\xd7\xd7\xf6gd\xdd\xe0V\xa4\xc2\ \xe2\xc7\xb7\x88/\xff'Q\xa9*\x0cm\xecD`\x1e\ p\x0d\xf0\x1b\xb0\xd3u\xd4\x19\xc8\x09\x84\xb4\xb1\xf3\x80\ \xc5\xc0\x04\xe0,\xf0)\x12i]L\x5c\xe2\x0aB\x1b\ \xfb\x0c\xf0\x22=\xc3\xfe\x0c\xb0\xdcu\xd4\xb6>} \ \xe1\x15?\xaa\x5cG\xb5\xf7\x12\xff\xb9H!\xb6\x10\xba\ \x81\x19}b\x00m\xec\x9d\xc8W\x99\x8a\xdcC\xbf \ .6vI+d\x9dc\x04\x17T\x0e\xf4Ek\xac\ \x1eId\x0a\xa5\xe2\xab\x5cGm\xa8\xd0:\xd5Hy\ nH\x00\xd9\xe9\xa4[c#\x90Rv\xb1u\xd7k\ c\xc7Th\xb9.\xc2\xabI\xddIw\x86\xee\x22\xb8\ |6\x04)\xaeV\x02\xe3\x91s\x1e\x84\xa3I\x1b \ \xec\xc9\x0a\xc0U\xe5.\xe2\xb5\xd6\x0e!\x99m1\xb4\ \x03k\x123\x80\x971\xde\x10\x81\xf4\xcf2\xd7\x19\x87\ (\x1fT\xad:\x89\xb4\xe1[\x93j\x8d\x055I\xfc\ h\x03f\xb8\x8e:U\xc2:c\x80\xaf\xc8\xefG\xec\ @\xba\xc7\xc3\x91\x22jK6\xba\xcd\x0d\x84j\x91\xce\ \xcc\xb5\x1e\xd1\xe7\x95\xc8\xfc\xbc\xd2\xf9\x1e`\x5c\x8ci\ \xb1\x8d\xa0\x8dU\xc0a\xe4\xec\xe7\xe2\x1d\xa48S\xf0\ >\xc8\x86\xc2\x85\x9a\x97\xddHA\xf2\x892^l\xd4\ {|\x87\xf9\x86:\x90\xd7 \xb5\xc8\xc5\xd7\x09L\xf3\ \xd1\xb4!\xdb4\xac,\x9e\xfdx\x87\x91(6\x17\xef\ \x02K\x82\xe4Oic\xa7\x01\xc7(^!^\xee:\ js\x04!\x86\x22\xa9\xf5y\xc4\x05\xad\x07\x1e#\xdf\ \xe55#M\xcc39s\xd3Hw\xa9\xc1G\x1bj\ \x04m\xechD\xf9\x89\xbe\xa1m\xc0\x83a\x1f/\xa5\ \x8d\xddN\xf0\x8b\xca\xb3\xc0*\xe08p\xca\xdf\xaf\xf7\ |\xfb\xcb@=\xb2\x83\xba\x90Rx!w\xb7\x11x\ \xbaPvY\x8a\x11\x02\x94\xdf\x01,\x8a\x92\xc5\xa6\xb4\ \xb1?\x02\x93\xc3\x08=d\x90N\xcdO\xc0\xcf\x80E\ ^bO\x8a0o\x89\xeb\xa8\x0f\x82\x88\xe2\x18\xc1;\ \xf3_\x90\xaf\xfc\xc7\xc8\x0e\x8b\x94\xc2\xa7\xb4\xb1\xdf\x91\ \x7f\xfe*\x89V\xe25E\x83\x8c\xb0\x13\x89%:\x90\ F\x89\xf2\xd1\xec\x06\x16\x04\xbd*\xf1#\xa5\x8d]\x0f\ <\x1buB\x09\x18\xeb:\xaa5\xce\x84\x00#\x04\xc1\ \x00\xf7\xc5Q\x1e\xe4\x82z\x058Sd\xbc\x13x\x0b\ )\x88Z\xc2CK?\xba\x91\x1eA,x\xdbw\x11\ \x10\xf5\xb5\xc7>\xe4iL\xecNr\xd6\x0d\x8eG,\ ~K\xceX+r\x8b\xfeW\x0f\xf4\xf2\xf7I\xc0\x14\ \xe0:\xa4\xca2\x22\x80\xbfEv@\xa9n\xb4\x1a\xf8\ #d\x8d\x0b\xc0\x95\xa5\x16nzD\x82\xdeC\xc6Z\ \xc4\x95\x1d\x0f\xbbH\xbc*\xd2\xae\x00\x92\xd5\xae\xa3^\ (E0\x8f\x7f\x1a\xf8\x8b\xe0\x98\xbe\xac\x07\x12\x95x\ !\xf2:\xe2\xef\xfd\xd8K\x89\xdb\xd2\xc7\xffw\x82\xe3\ \xfas\xae\xa3JN\xa0\xcaN\x86\x5cG\xad\x00f#\ \xee\xa7\x05\xb9\x8c\x1a\x91\x9b\xbf\x12\xaf;\xc2\xfa\x11\xcd\ \xe50\xef\xf7\x7f\x9a\xf2\x12\x9c\xef)|\x0f\xb4#O\ o\xc2z\x1bE\xd1\xef\xff0\xe1\xb9\xd0\x99\xc0\x09\xdf\ \xd0\x09$a*Yy\xb8\x04v@\x16\xde+\xd1Z\ \xe4\xa3u\x03m\x95\xfa\x83\xc5 \x06q\x19\xe3_\xab\ \x17/{\xae\xeb_\xd4\x00\x00\x00\x00IEND\xae\ B`\x82\ \x00\x00\x02\xe5\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x02\x97IDATx\x9c\xe5\ \xdaA\x8a\xd4@\x14\xc6\xf1\xff4\xb3\x14\x8fP\xab9\ Hk#\xee\xea\x0c\x92\x03\x08\xd2\xf4\x01\xdc\xcb\xa8[\ \x17u\x073\xd7\x10\x172\xc804C\x08\x8d\x88\x88\ \x0b\x17.\x5c4.\x92@;\x9dI\xa7*yU\x95\ \xca\xdb\x0ey\xa9\xdf\x97Jz\x12\xde\x19\x03*\xcb\xcb\ \x97\xc0\xab!=\x02\xd7\xee\xdc\xf5\xc8\x1a\xff\x16X\x8c\ \xb7\x1e\xff\xe5\xb4\xf8T\xf0\xe0\x00H\x09\x0f\x96\x88\xd4\ \xf0`\x01I\x11\x0f=1\xa9\xe2\xa1\x07(e<\x9c\ @\xa5\x8e\x87\x0e\xd8\x1c\xf0\xf0\x00n.xh\x01\xce\ \x09\x0f\xf7\x90s\xc3\xc3\x01t\x8ex\xa8\xb1s\xc5\x03\ \x9cgy\xf9\x02x\x0d\xfc\x0e\xbc\x96\xa6\x1e\x01\xceo\ \xa9\xb6u\xe6\xebD}*\xcb\xcb%pE\x15\x82\x8f\ *\xa2\xd9\xf2\x01\xf0@$\xf7|(\x03<\xe1\xaf\x05z\x1f\x95\xcb\x8cP\ 2x\xb0\x9f\x11\x92\xc4\x7f\xc73\x1e,n\x01O\xf8\ \xaf\x02\xbd;\xab\xef\x8cP\x92x\xe87#\x94,\x1e\ N\xcf\x08I\xe2\xbf\x01OB\xe2\xa1{FH\x1a\xbf\ 2Z\xdd\x08\xf4\xb6\xaa\x87f\x84f\x81\x87\xf6\x19!\ I\xfc\x8ej\xdbG\x81\x87\xe3\x19\xa1%\xb2\xf8\x95\xd1\ \xeaV\xa0\xb7k\xbd?\x9c\x11Z\x22\xf7bSR]\ \xf9\x98\xf0k\xa3\xd5\xbbfFh\x89,~e\xb4\xda\ \x0a\xf4v\xad\xb5\xd1\xea\x12`\x91\xe5\xe5\x053\xc5\x03\ ,\xea\xc5}\x108QA\xb5\xed\xa3\xc5C\xfd\x104\ Z\xad\x81\xcb\xd6C\xdc\xaa\xa0\xba\xf2w#\xf6\x1cZ\ Gx8\xf8\x15\x181\x84;&\x82\x87{?\x83#\ \x84\x10\x1b~O\x07\x1e\xda\xff\x13\xdc\xe0\x16B\x83/\ \x1c\x8e\x95\xaaM\x17\x1eZ\x020Z\xed\xb1\x0faK\ \xf5\xc0+\xac\x96'[\x9dW\xbe\xa9\xd6w\x01\xcb\x10\ \xb6TW\xbe\xb4[\x9fh\xf5\xc2C\xc7\xdb`\xcf\x10\ n\x990\x1eN|\x0f0Z\xed\xeb\x07\xe3\x9b\x96?\ O\x1e\x0f=?\x89\x19\xad6\xfc\x1fB\x83\xdf\xd9\x9c\ L\xb8\xac\xf1`\xf1U\xf8 \x84\x1b\xaa\x07\xde\xe4\xf1\ N\x95\xe5\xe5c/'\xeaYY^fC\x8e\xff\x07\ \x95qE\xa0\x10\xc5\xf95\x00\x00\x00\x00IEND\ \xaeB`\x82\ \x00\x00\x03\xed\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x03\xb4IDATx\x9c\xed\x9a\xcbj\x14A\ \x14\x86?\x1b\x11\x11q\xe9BB#\x22A\xc4g\xd0\ \x8d\x88\xb7L\xbc\x05oX\x8a\x88\x88\xa8\xe8\x13\xb8r\ \x1d$\x88\x04\xc9\xc2\x09\x18\xd4h\xb4P\x111\x89\x88\ \xef\xe0\xc6\x85\xd43\x88\x88d\xe1\xa2N\x0dm;\xd3\ \xd3SU=\x83P\xdf&\xa1\xa6\xea\xd4\xf9\xffs\xba\ \xa7\xa7\xbb!\x91H$\x12\x89D\x22\x91HtCi\ \xb3~\xd49\xf8\xa2\xb4\xc9\xfa\xcd\xa9\x9c\xa0\xb4\xd9\x0d\ |U\xda\xec\x8f\x96\xd5\x90P\xda\xec\xc5\xe6\xbe\xabj\ ^O\x03\x946{\x80U`'\xf0Zis0n\ \x8a\xcd!\x05{\x0b\x8c\x03\xcbJ\x9b\xf1^s\xbb\x1a\ \xe2\x97\x81\xad2\xb4\x09XR\xda\x1c\x8d\x9ckt\ \xa4P\xaf\x81\xcd2\xb4\x8d\x0a\x13\xfe1@\xda\xbe(\ \xde\xb1\x11x\xae\xb49\x16/\xdd\xb8H\x81\x96\xb0\x05\ +2\x865agy\xcd\xbaR\x80ql\xdbo\xab\ \xd8\xe77p\xb6\xdd\xca_\x86\xa5\x1b\x17)\xccS`\ C\xc54\x03\xeck\xb7\xf2\xefn\xa0\xd3\x01\xe2\xce2\ \xd5\xe2\x91\x0d\x16\x946\xa7\xbc\xb3\x8d\x8c\xd2\xe6\x04\xfd\ \xc5\x03\xe4\xc0\xaa\xd2&w\x03\x99\x04\xd8\x8e\x15?V\ sOg\xc2\x99\x81\xb3\x8d\x8c\x14b\x81\xfe\xe2\x1d\xdb\ \xb1&\x8c\x01\xac\x137V\x81\x1d\x1e\xfb\xaf\x01\x17\xdb\ \xad\xfc\x89\xc7\xda`\xa4\x00\xf3\x80\xcf\xb5\xca7`_\ \x06\xdc\xc5O<\xb2\xf1c\xa5\xcd9\xcf\xf5\xde\xc8\x9e\ \xbe\xe2\xc1~\xbd\xdf\xcb\x80\x9b\xc0J@.\xce\x04\x15\ \x10c D\xfcc\xfc\xc5\x03|\x01nf\xedV\xfe\ \x13\x98 \xdc\x849\xa5\xcd\xa5\x80\x18\xb5\x10\xa3C\xc5\ \x7f\x06\x0e\xb5[\xf9\x8f\x0c \xb2\x09\x97\x03bT\x22\ \xe2\xe7\x08\x13\xff\x098\xd2n\xe5?\xa0\xf05\x18\xc9\ \x84\x0c\x98m\xc2\x04\xe9\xae\x18\xe2'\x9cx(]\x09\ F\xec\x84GJ\x9b+\x011\xfeB\xc4?\x22L\xfc\ \x0a%\xf1\xd0\xe5R8r'\x5c\x0d\x88\x01\x80\x18\x19\ Z\xf9\xae\xe2\xa1\xc7\x8f!1a\x92p\x13\x1e*m\ \xae\xf9\x06\x10\xf1\xb3\xf4\xf9\xd9\xde\x87\x15`R4\xfd\ C\xcf\xc0\xe2\xd6$\xf6\xb8\xf1%\x03\x1e\xf8\x98 k\ B\xc5\x7f\xa4G\xe5\x1d\x95\xc1e\xe1\x04qL\xb8^\ w\x81\x88\x7f\xd0/\xbf>|\xa4\xa2\xf2\xc5\xe4*\x89\ h\xc2L\x1d\x13dN\xa8\xf8\xf7\xd4\x10\xef\x12\xebK\ \xc1\x84\xd0s\xc2\x8c\xd2\xe6V\xaf\x09J\x9b\x1b\xc0L\ \xdd\xbcz\xf0\x1e8YG\xbcK\xaa\x16\x85sB\xa8\ \x09\xd3\xddL\x90\xb1\xfb\x83\xe4\xd4\x85\x81\xc4\xbb\x84j\ \x13\xd9\x84\xdbn@\xfe\x9f\x1e4\x9f\x12\xef\x80\xe3\x83\ \x88\x87\xd2\x1d\xa1\xba(m6a\xef\xbb\x85\xde-\xbe\ #\x7f\xa7\x03\xe3\xbc\xc3V\xfe\xd7\xa0\x0b\xbd\x0c\x80\xa8\ &\x84\xf2\x06\x98\xf2\x11\x0f\x01-W\xb8X\xfa\xe0\x1b\ #\x02A\xe2!\xa0\x03\x1c\xd2\x09K\xc0\x81\xd0X\x03\ \x12,\x1e\xc2N:@\xa7\x13\x8ec\xcf\xc0\xc3\xe2\x15\ \x9e\xc7|\x99\xe0\x0ep(m6\x02/\x80\xc3\xb1b\ \xf6@c+\xff;F\xb0\xe0\x0epH5Nb[\ \xb3)\xa2\x8a\x87\x88\x06@\xc7\x84)l\xa2\xb1yE\ d\xf1\x10\xf1\x10(\xa2\xb4\xd9\x00<\x07Z\x91B\xbe\ \xc4>\x8d\x8a*\x1e\x22w\x80C\x12\x9d\xc2V-\x94\ \xc6\xc4CC\x06@\xc7\x84\xd3\xc0b@\x98F\xc5C\ \x83\x06@\xc7\x84\xf3\xc03\x8f\xe5\x8b4,\x1e\x1a:\ \x07\x94\x91\xd7l\xe6\x81\xba\xcf\x12\x17\x81\xf3M\x8b\x87\ \x86;\xc0\xd1n\xe5k\xc0\x05\xa0\xce3\xc4\xa1\x89\x87\ !\x19\x00\x1d\x13.\x02\xed\x8aiC\x15\x0fC:\x04\ \x8a\xc8\x9b[s\xc0\xa5\xd2G\xcf\xb0\xe2\xd7\x86\x99\xcf\ \xd0\x0d\x80\xae&\x8cD<\x8c\xc8\x00\xe8\x980\x0bl\ aD\xe2G\x8e\xd2&\xfb\x9f_\xc4L$\x12\x89D\ \x22\x91H$\xfec\xfe\x00\x8c\xfdo\xe5\xcfB\xc9?\ \x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x06\x85\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x067IDATx\x9c\xed\ \x9bO\x88UU\x18\xc0\x7f^D\xc4\xc50\x99H\x81\ \xdcD,\xc4E8\x82$\xa5%1\x0b\x9b\xe8\x82\x84\ \x92\x0b\x19nh\xcd\xb4\xf0O\xe2Bl\x16\xa6\xe2\xc2\ \xd4t\x91\xe3\x1f\xb8\xd8,\x0c\xa5\xcd\x8d\xcc\x85\xc8\x94\ \x16\x86\xd4\x0cQ\x22%b\x87\x81B\xac\x86Y\xc80\ \xc8\xd0\xe2|o\xe6y\xe7\x9c{\xef{\xef\xdc\xf7\xe6\ e?x\xf0\xde9\xe7\x9e\xf3}\xdf;\xf7\xfc\xfb\xbe\ 3\x83\x82\x09c\xb5\x18X\x09\xb4\x01K\x80\x85\xc0+\ Q\xe0\xdfO\x94\x9b\x07|\x0d\xdc\x05n\x01\x03\xc0\xf5\ (\xf0o\x17)\xdfL\xd7\x15\x86\xb1\xf2\x805\xc0z\ \xa0\x03\xf0s\xb6;\x13X*\x9f\x8e\xb2\xfa\x14p\x11\ \xb8\x00\xf4G\x81?\xeeR^g\x06\x08c5\x1f\xe8\ \x02\xb6\x00\x0b\x5c\xd5\x8b6`\x97|\x86\xc2X\x9d\x04\ NE\x81\x7f\xcfE\xe55\x1b@\x14\xdf\x8d\x16pv\ \xcd\x12\xa5\xb3\x00\xd8\x07\xec\x09c\xd5\x0b\x1c\xac\xd5\x10\ U\x1b \x8c\xd5L`;\xd0\x03\xb4\xd4\x22D\x15\xcc\ \x96\xb6\xdf\x0ec\xb5\x178\x1e\x05\xfe\xc3j*\xf2\xaa\ y(\x8c\xd5\xf3\xc0\x0d\xe0\x10\xf5W\xbe\x9c\x16\xe00\ pCd\xaa\x98\x19\x95>\x10\xc6\xaa\x0b8J\xfe\xee\ ~\x0f\xb8\x0c\x5c\x05~\x04~\x8d\x02\x7f\xd8Rw+\ \xf0\x1c\xb0\x1cX\x0d\xb4\x03\xf3s\xb63\x0a\xec\x88\x02\ \xbf7gy\xa0\x02\x03H\x97?\x01l\xceQ\xfc\x01\ \xf0\x19p\x16\xb8V\xed\xc8-3\xca*\xa0\x13x\x0b\ \x98\x93\xe3\xb13@w\xdeW\x22\x97\x01\xc2X\xcd\x01\ >\x07\xd6f\x14\x1dFw\xc9O\xa2\xc0\xff;O\xdd\ y\x09c5\x17x\x0f\xd8\x09\xb4f\x14\xbf\x04\xbc\x19\ \x05\xfe\x83\xacz3\x0d \xca\x7f\x05\xbc\x9cRl\x1c\ \xe8\x05z\x5c+n\x90g.z&\xe8\x22}\x0c\xfb\ \x06x-\xcb\x08\xa9\x06\x90n\xff\x05\xe9\xff\xfc\x1d`\ S\x14\xf8\xdf\xa5\xd5\xe5\x9a0V/\x02}\xc0\xa2\x94\ b\x97\x807\xd2^\x87\xacY\xe0\x04\xe9\xca\xc7@[\ \xbd\x95\x07\x906\xdbD\x06\x1bk\xd1:X\xb1\x1a@\ F\xfb\xb4\x01\xef\x08\xb0.\x0a\xfc\x91\xb4\x06\x8aD\xda\ ^'\xb2\xd8\xd8,\xba\x181\xbe\x022\xa7~\x8f}\ \xaa\xdb\x1f\x05~O^A\xebA\x18\xab}\xc0\x07\x96\ \xecQ\xe0\x85(\xf0\x7fJfL1\x80\xbc\xf77\x80\ e\x96\xca>\x8e\x02\x7fG\xb5\x82\x16I\x18\xab\xa3\xe8\ \x15\xa2\x89A`Er<0\xbd\x02\xdb\xb1+\x1f\xa3\ \xa7\xa1\xe9\xcaN\xecc\xc22`k2\xf1\x91\x1e \ \x1b\x9b\xdf0/o\xef\xa0\x07\xbc\x86\xbd\xf3y\x08c\ \xd5\x82>K0\xcd\x0e#\xc0\xb3\xe5\x1b\xa8\xe4fh\ 7f\xe5\xc7\x81N\x97\xca\x87\xb1Z\x0al\x94\x9f\xe7\ \xa2\xc0\xbf\xe9\xa2\xde(\xf0G\xc2Xu\xa2\x0fW\x92\ =\xbc\x05\xad\xe3\xc4+<\xd1\x03\xe4\xdf\xff\x1d\xf3\xc0\ \xd7\x1b\x05~\xb7\x0b\x01\xa5\xadv\xe0K`\x96$\x8d\ \x01\xafG\x81\x7f\xd9a\x1b'\xd0\x8b\xa5$\xa3\xc03\ \xa5^Pn!\xdb~~\x18\xbd\xe5u\xc9\x01&\x95\ G\xbe\x1fp\xdcF\x0fZ\xf6$\xb3\x81wJ?<\ \x98\xd8tl\xb1Ttn\xc9~Wt\x9e\xe8\x01k0\x1fc=\ \x00\x8e\xb9\x14L0\xcd>U\x9dMdp\x0c\xadC\ \x92\x05h\x9d'\x1a]o\xa9\xe0|\xd1\x9b\x9b\x22\x11\ \xd9\xcf[\xb2\xd7\xc3\xa4\x01:,\x85\xfa\x5c\x0b\xd5\x00\ l:t\x00xrno:\xba\xbe\x0f\xf4\x17$T\ =\xe9G\xeb\x92\xc4\x0fc\xb5\xd8C;-L\x5cv\ }\x06\xdf\x08D\x07\xdb\xf4\xba\xd2Co)M\x5c-\ F\xa4\x86\xf0\xad%\xbd\xcdC\xbb\xabL\x0c\x16$L\ #\xf8\xd1\x92\xbe\xc4C\xfb\xeaL\xdc*F\x96\x86`\ \xd3e\xe1\x0cqJNq\x90D\x81\xffg%-\xc8\ \xf2\xf6\x00zA\x935\xa7\xb7\x18\xca\x8c\xa37+i\ \x8c\x03\xb7\x81\xddQ\xe0_\xa9P\xbe\xa7\x0c\xc9\x0f+\ \xf6\x0bX*_\x8a\xde\x81\xcd\xca*\xeb\x881\xf4\xce\ \xb4\xe6\x0d\x94\xab\xd5\xd7F\xea\xa7<\xd2\xd6\xc6\xccR\ 9(b\xf9\xd9T\xb82\xc09t\xb7\xac\x17c\xd2\ f\xcd\xb8\x1c\x04_\x05\x0e\xd2l\x83`\x18\xab_\xd0\ Q\x19I\x9e,j#\x14\xc6\xea\x1f\xa6\xba\xb7\x86\xa3\ \xc0\x7f\xa2\xa0\xf6\xe6\x02\x7f\x19\xb2nz\xe8\x98\x1c\x13\ \xb6\x05R3b\xd3\xe5\xae\x87}\x91`;\x19nF\ \x96[\xd2oy\xe8\xf9\xdb\xc4\xea\x82\x84i\x04/Y\ \xd2\x07<\xe0\xba%\xb3\xbdtl\xd4\xcc\x88\x0e\xed\x96\ \xec\xeb\x9e\xc4\xe1)C\xe6<\xe4\xd8\xa8\xc9Y\x83\xd6\ %\x89\x8a\x02\xffv\xe9\x1f\xbehyxS!\x22\xd5\ \x17\x9b\x0e\x17ar.\xbe`)\xb4A\xa6\x90\xa6D\ d\xdf`\xc9\xbe\x00\x93\x06\xe8\x07\x86\x0c\x85\xe6\x00\xdb\ \x9cK\xa6\x174y\xd2je\x1b\xe6\xb8\xa2!\xe4\xb8\ \xcf\x83\x89c\xa3\xd3\x96J\xb6\xcaj\xd1%\xa6\xf8_\ \xa71\xc1\x22\xf3\x14g\xa8p\xb2t\xdcW>\xca\xf7\ \xa2\xddFIZ\xd119.\xd9\xc3\xa3{\x871I\ s\xc9>\xcc\xc1T\xa3\xc0\xa9\xd2\x8f\xa4w\xd8\xe6_\ \x1fGGx_s%]Q\xceQ\xa9{\x15f\xe7\ ($\xe2\x1b\xfe\x8b\xee\xf1V\xe0\x07r\xba\xc7\x1f\xb1\ \x90d\xd8\xba\xfb\x22\xa0o:/\x8eD\xb6\xb3\xd8#\ \xc7\xf6&\x83\xab\x8d]\x04\xfb\x89p\x80\x0e\x84\x9c\xae\ \x1cF\xcbhb\x10\x83\xb3t\x8a\x01$\x86\xa6\x13\xf3\ \x80\x08\xb0]\x02\x92\xa6\x15\x22\x93->h\x14\x1d\xcb\ 8%^\xd0z(*\xa1ei1vG\x80]\x8d\ \xf6\x1eI\xb7?\x04\xbc\x9fR\xac\xdb\x16D\x9d\x15)\ z\x9a\xf4X\xc1\x18m\xd9\x86\x0c\x8c\x12\x0f\xd4\x87\xbd\ \xdb\x03\x9c\x89\x02\xdf\x16\xfb\x90yt\xd5\x8d\x0e7\xb5\ \x11\x00\x03\x12\xb6ZW\xa4\xcd\x01\xd2\x95\xbf\x84\xd6\xc1\ \xca\xff\xc1\xd29\x1b}|\xc3\xe5\xcb\x04x|/L\ $\x84z<\xaf\xcc\x94#\xc1\xd4g\xa9\xfe\xe0\xf4\xe9\ \xa4\xdfA\xce\xed\xff\xa8\xb2\xbeA\xf4l\xf4s\xa5\x0f\ V\xb5\xac\x95\xa8\xeb\x15\xc0.\xb2\x9d\x19E2\x82\x1e\ \x13VT\xa3<\xd4poP\xde\xb1\x8f\xc2X}J\ \xfd.N\x96\x18E\xcf:\x8d\xbb8YB\x04\xd8\x11\ \xc6\xea \xc5\x5c\x9d-g\x08\x98^WgK\x88@\ \x1f\x86\xb1\xdaO\xf6\xe5\xe9Jh\x8e\xcb\xd3%D\xc0\ +\xf2\xb1]\x9f7MQ\x0f\x81\x9b\xd4\xf9\xfa\xfc\xbf\ \xc9\xec\xfe\xa3\xe6\xd5\xd2C\xf4\x0ecc&\xcb\ \x80\x220\xd3\xb6c3/\x9c\x01\xd2\x02\xa4\xb1}$\ ,\x02\xe7\x80_9k\xc9\x83G\x18\xef,i_I\ \xaf\xb4\xf2\xe6Z\xaf'_\xfc \x5c\xf6\x86[\xf8!\ \xe0\x0c\x90\x16 \x8d3@Z\x804\xce\x00i\x01\xd2\ 8\x03\xa4\x05H\xe3\x0c\x90\x16 \x8d3@Z\x804\ \xce\x00i\x01\xd28\x03\xa4\x05H\xe3\x0c\x90\x16 \x8d\ 3@Z\x804\xce\x00i\x01\xd28\x03\xa4\x05\xe4\xcc\ \xb2\xf6:\x03$T\xb4\x13i\x06\x14\xc6\x98\xc244\ \x0dg\x80\xb4\x00i\x8a\xf6\x0cX\xf1,Px\x03\x0a\ \x83\xcd\x80f&;\xb5\x1b\xcb\x96\x04\xa554m\xed\ \xd0z\xa7\xb8\x06\xf8Ah\xed\xd9i\x06\xb4\xed\xf2\xf6\ 5\xd0\xc9*\x0c\xb0\xa5\xd1\xacw\x0e`\xe9\xd9\x1dD\ \x89P\xfdF\xfdh\xbc\xa6\xee\x0d\xd1*p\x88\xd2\x5c\ \xea\x99\x1e\xb6lM2\xd2f\x9aJ\xdc\x9d\xebde\ \xb1\x96\x89\xee|\x1f0n9\xd5D\xa3\xb49X\xda\ h\xb3.-6\x0d[\x0a\xac\xc9Jf\xa1\x95\xbc\xbf\ \x94-u&\x03\xf5\xcc\xd1{\xc0\xb5\x06\x17\xfd\xdfx\ \xa9\x95w\xaa\xee\xceM\xe0\x9d\xa4\x9a\x9c\x99\x22\xca\x97\ \x8c\xbaG\x9c%v\x12x@\x1bet\xb5\x88g@\ E+\xef\x07$\xb2\xc7\xeb$\xd2\xe7\xf7\x11e\x88u\ \x12=\x1f\xca\x89\xdfF\xa9\xf3y\x91\x96B_K\xfc\ VY\x9a>\xbf$\xfb\xf5\x0f\xe7\xd6\xbd\x94iiz\ \xd1\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x01\x01R\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x02\x00\x00\x00\x02\x00\x08\x06\x00\x00\x00\xf4x\xd4\xfa\ \x00\x00 \x00IDATx\x9c\xec\xbd\xd9\xaf-\xcb\ }\xdf\xf7\xad\xea^\xd3\x1e\xcf\xde\xe7\xdc3\xdd{\xee\ @\xdeK^\x8e\x97\xa2H\x85\x9a()\x90\x12 \x96\ \x8c\x04p\x90\xc0\x89,E\xb1\x83$@^\xf2\x96?\ !\xc8\xab\x1d\x07A\x92\x07g\xf2\x83\x1d\xc8\x0e`\x1b\ \x88aK\x86d\xd2\xa4HZ\x14)s\x90(\xf2\xde\ {\xe6y\x0fk\xec\xae_\x1e\xba\xab\xbb\xba\xba\xaa\x87\ 5v\xafU\x9f\x83uvwuuuU\xd7\xf0\xfb\ \xd5\xaf\x86f\xff\xed\xffw\x97\x86\x01\xc1\xe1p8\x1c\ \x0e\xc7n\xb0\xe73\xf8OG!\x9c\xf8w8\x1c\x0e\ \x87cw\x18\xcd\x00>\xe8\xf0M\xc7\xc3\xe1p8\x1c\ \x0e\xc7\x1a\x19t8\x9c\xf4w8\x1c\x0e\x87c\x07q\ \x0a\x80\xc3\xe1p8\x1c;\x88S\x00\x1c\x0e\x87\xc3\xe1\ \xd8A\x9c\x02\xe0p8\x1c\x0e\xc7\x0e\xe2\x14\x00\x87\xc3\ \xe1p8v\x10\xa7\x008\x1c\x0e\x87\xc3\xb1\x838\x05\ \xc0\xe1p8\x1c\x8e\x1d\xc4)\x00\x0e\x87\xc3\xe1p\xec\ N\x01p8\x1c\x0e\x87c\x07q\x0a\x80\xc3\xe1p\ 8\x1c;\x88S\x00\x1c\x0e\x87\xc3\xe1\xd8A\x9c\x02\xe0\ p8\x1c\x0e\xc7\x0e\xe2\x14\x00\x87\xc3\xe1p8v\x10\ \xa7\x008\x1c\x0e\x87\xc3\xb1\x838\x05\xc0\xe1p8\x1c\ \x8e\x1d\xc4)\x00\x0e\x87\xc3\xe1p\xec N\x01p8\ \x1c\x0e\x87c\x07q\x0a\x80\xc3\xe1p8\x1c;\x88S\ \x00\x1c\x0e\x87\xc3\xe1\xd8A\x9c\x02\xe0p8\x1c\x0e\xc7\ \x0e\xe2\x14\x00\x87\xc3\xe1p8v\x10\xa7\x008\x1c\x0e\ \x87\xc3\xb1\x838\x05\xc0\xe1p8\x1c\x8e\x1d\xc4)\x00\ \x0e\x87\xc3\xe1p\xec N\x01p8\x1c\x0e\x87c\x07\ q\x0a\x80\xc3\xe1p8\x1c;\x88S\x00\x1c\x0e\x87\xc3\ \xe1\xd8A\x9c\x02\xe0p8\x1c\x0e\xc7\x0e\xe2\x14\x00\x87\ \xc3\xe1p8v\x10\xa7\x008\x1c\x0e\x87\xc3\xb1\x83\xf8\ \x9b\x8e@\x13a\x067\x8a\xffg\xc6\xab\xed\x82\xe2\xd4\ lOZ\xda\x9f\x12J\xfewii\x12\xdb\x98\x96\xf6\ \xa7\xa4zZh\x1d\x91i1;\xad\x00\xb4\xbf\x1a8\ \x1c\x0e\x87\xc3\x86\xad\x8dw\x8aA\xc4N)\x00N\xe0\ ;\x1c\x0e\x87C\x97\x05\xbb\xaa\x10l\xbd\x02\xe0\x84\xbe\ \xc3\xe1p8\x8a\xd8U\x85`\xab\x14\x80\xc6\x0a{[\ \xe9ZV\x84w\xa5\xb4:\x1c\x8e\xcd\xb3\xccv\xcb>\ \xe1j\xa344ZK\xa7\xf5\x0a\xc0F\x85~\xd9\xc3\ m\x05|\xd9\x91\xae\x1b\x9e\x88\xff\xb6}\x0d\x08\xc5?\ F\x00k\xac\xfaW\x09F\x00mYZ\x18C\x83\xb5\ \xf2j0\xa2\xadI\x0b\x88\xd26\xa9\x09i)\x8aC\ Y\xfc\x04\xad=\x0d\xea\xe3\xb6E\x19h\xb5\x08Xo\ \xfeS\xb6\xe7^\xe5\xe1M\xa8d\x0e\x87c\x01\x5c%\ ^;U\xdbVU\x99i\x8aR\xd32Zm\x01X\ \x9d\x16f\x08\x99\xe4\x1f\xda\x1a\xf5\x8fh[\x12\x92.\ ml-q\x1a\x18\xb1\xadIK\xdb\x93\x01`\xeb\xd2\ \x92\xd4\x94\xb6\xa7G\xb6\xc7\xa5m\x98\xd3\x0a\x8ah\xb5\ \x02\xb0\xdb\xcd\x0dt\xccEj5o}\x01I\ \x16gl:\x22K\xa2\xe9\x8dx\x15\xb2\x8a\xff\xe6\xa9\ \xb38\xaaN\xac\x17\x0eC5\xef.\x019W\xb1\xa9\ 4B\x01\xd8to\xbf\x9awZ\x8e\xf6\xbc)\xbb\x9b\ \x1c\xc7$\xca\xf6h\xe4\x00t[Zk%\xaeIZ\ \xb6\xc2\xceL\xe9_\xd6\xc2\xc59z\xbe@)_m\ C\xad\x0f\xea@\xb9LK\x0b\xeb\x0b\xa3T\x09hd\ \xbe\x14LH0O\xa1\xa2\xdc\xf5\x22A[\xbbW\xbe\ \xc4n|\x93-\x02\x8dP\x00\x16\xa6FY^i\x0f\ \xbdi\x95\xca\xe1p8\xda\x80\xdev&\x9b/(\xe7\ eA\x18\xdcLw\xd5\xb6\xfc\xeb\x12\xbc\xe9\xdd\xfa\x1a\ lT\x01XX\x5cV\x08@].\xba4\xe6\xe85\ o\x5c5`\xda_(\xf5k\xe3\x91\xab\x81\xda&$\ N\xd4\xaa$Xi\xf3\x1c\x00=_\xda-\x11\xdb\x98\x96-H\ \x8c\xb2\x13\xe0\xca\x1fUA\xbaU\x89Fq0\xac\xe0\ L\xbb\xbf\xc6P\x81\xe9\xb9\xa5r~\x0eE@\x0e-\ oJ%k\xae\x05`I\x93-\xf2\x17\xcc\xe6\xa3\xd2\ \xc7\xc5_\x05\xab}\x1f\x9a%\x9c\xd4\xb84)^s\ S`\xb9i\x13\xb2\xd7\xbc\x0d0e\xc9l\xfb\xa1D\ h\xb6\x1fe'\xa050o\xb5\xd4\xdbY{0\xd5\ \xd2Rh\xadO\x86{\xab\xbf\x97\xca\xc3\x03-\xa8\x03\ \xcdU\x00\x16\xa0P\xf8+\x7f\xeb\x97\xcf\xbc\xf9l\x99\ \xb2G/X\xabht\x92\x19\xda\xf2U\xac\xe0\x19k\ \xa7\xc2l\xe0\xa6\xa3\xaemn{Z\x22\xb6h8c\ K\xf2EN\x9a]W\xbe\xa4\xabtjn\xe6S)\ rf\xc5\xac\xec9\x19\xd9\x5c\xf2\xa0\x16\xc9\xf1\xb9Y\ \x9b\x02\xb0\xcc\x02g\x0b\xcb\xe8^:\xae_#\xac\x05\ \xccgUo\xc9MX4X\xad\x16R:\xd4\xfdf\ \x0c\xe1\xb7\x89\xd4l\xde\xf6\xbd\xf3\x91\x98\x00\xd8\x96\x98\ \xcd\xe5\x17\x0d\xb7\x22-\xf2\x83S-NKn\xf3\x9c\ \x15\xa7E_mP\xf5q\x95\x85\xada\xf8O\x7ff\ \x95\x8d\x81\xaa\x0c\x0f\x98\x14\x81J\xcfi\xc2 \x7f\x09\ kP\x00\xe6\x18\xdf(\xf0n\xbaTU\xf0\xcf;~\ \xcf*\xdag\x0b\xe7#,\xa9\xc2-\x1a\xceV\xf5h\ \x98T\x88\x1a^\xcb*\xc0\x80\xcc^\xedmF\x9d\x04\ \xd8~\xb6 C\xa0\xe6\xc5z\x14\xcc\xb9\x9fay\xdd\ \xf9\xf1\xf8\xfcG\xb3uk~\x15!]:\xdb\xda\xae\xb3\x9e\x07[\x92\x16u\xdc<\xd3\ \x90\xb7%]2\xae$+\xba\x96\x96e\x85\xaf\xc0\xa8\ ~\xe0eJ\x83q5\x9f6\xf7\xa7\xcc\x22\x00\x14\xcb\ b\xeb|\x02\xed\xe1&\x01]u\xe8\xa1i4G\x01\ \xa8H\x95\x1e\x7f\x1d\xc1\xaf\xden\xd4&\xcb\x1fg\xb8\ '2P\x15\x0a\xfb9+\xe0\xdc\x16\x06Y\x19L\xce\ mi\xcc\x00C\x5c\x95FmKheZ\x98z\x98\ \x0e1\xb5=-F\xe76%\x8ai\x7f\x97\xbdE\xb3\ \xa9]\xa9\x1axF0\x9bo2)\x06\xfa\x90l\xd2\ &*^)\xe7?v\xd7\x86\x07\xca\xe6\x09\xd8\x86\x05\ \xac\xcaB\x11\xeb\xec\xdaW\xa4\x19\x0a@E\xc1k\xbe\ \xb7zQ\xaec\xae\xcf)\x08\xd6M$4a\xcfR\ \xf7\xb2\xe7\x17\xb1\xd2\xce\x06\xa5\xab\x19\xda\xd4\x96\xe9\xa8\ \xc6\x906\xa7\x03\xc8\xf64\xdb\x9e\x16\x00\xcb\x174\x1b\ \x83\xb6+_\xb0\x9a\xfaR\xd3r\x1f]c\xe5\x82\x98\ \x81%\x17)'\xe1\xb3\xf3\x19L\x93\x01mV\x812\ \x7f\xe9\xf3\xcb\xe7\x06\x98\xee\xb1\x86YQ\x09X\x97\xae\ \xd0\x0c\x05`IT\x19.\xa8*\xf4\xcd~\xe3\xd9\xc0\ \x9aO\xd3\x06!\xb6\xc7\xd4\xadxK\xaf\xa8J\xe9l\ \xf3\xacf@U\xcc\x1a\xa6V\xcf\xcd\xb6\xa5e[\xd8\ \x96\xb4\xac\x7fX\xa6J\x9b\x5c\x04)\x1e\x93vW\xd6\ \xf9\x92y\x01e\xab\x02\x98\xe1b\xd1\xd0@\xddR`\ \x14\xe2\x0d+J\xadQ\x00\xac\x9a\x98r\xddv\x9f\xc1\ \xfb\x1c~\xec\xe3\xe6K\x13\xf6K\xae\x98\xa6\xe0\x84\x9c\ \x03\xb0\xa2g\xae\x93d\x19\xe06(3@:A\xab\ \xedi\x89\xeb\x07\xc3\x16\xa4E\x91\x99\xdb\x90\x16\xb2\xa4\ e.\x93vM\x0a\xb7\xef7\xf9/pW\x8f\xd4\x0e\ \x19Y\xda6\x99\xee\xb2t\x15\xf9)\xbb\xbfR\xaf\xbd\ a\xc3\x00KW\x00\x8a4.\xab\xc7\x8a\x97\x22\xe1[\ \xad\xb7]\xc5\xdc_M\xf0\xe7S\x94(\x01%q\xc8\ \x855G\x9a\x97\x8d45\xcb\xe36\xb7iiZ\xda\ ?\x07 \xfa\xc2\xf4\xb6\x98\xcd\x01\x22\x81m\xc8\x17\x80\ @$b\xcb_\xdb!\x80D\xa5z\xbf\x92\xb4\x96\x04\ Ze\x07@B\xd6\xe2\x9ai\x8b)m\xaf\xf5\xb9\x03\ \xc9$o-,\xf5\xba\x8cCQ\x8f?\x91\xdf\x86\x89\ \x81\x95\xa9($\xe7\xb5<\xd4\xa1Q\x16\x80*\x82\xbc\ \xee=\xf3\xf4\xfa3B\xbf@\xd0[\x15\x15\xed\xf6E\ \xc7\xf1\xd5\x02\x1fmJ2Oh\xc9t`%\x5c\x19\ v\x1b\xa75\xeby\xd8\x96\xf8\x17@\x046w\xfen\ \x1a5_\x14\x05\xb3\xe5iQI\xd3\xd2\xc2\xfa\xa2\xad\ g_V\xbe\x90\xecL\xc4\xe1Q\x85\xb1q\xebu)\ \x84s\xcf\xc8\x86A\x8acFH\xaa\xed.\xe5\x15\x01\ \xd3>\x01\xa6a\x81\xa2\xebFw\xe5&\xfdZ\xe5\x0e\ \xf1\x86h\x94\x02P\xb7Z-\xaa0\x98\xad\x02\x96\x10\ (\xb5\x9f\x19\x9fk\xd7\x19\x0a\x14\x85j\xa9]\x86\xa0\ \x93\xd3\x14I6\x06\xb1\xea\xcc\x94km \x13\xd7\xc8\ \x04P_\x03o,\xed\xb5\x00\xe4\xcb\xd0v\xa4EZ\ \x99\xd4^s\x1b\xeb\x0b\xc9\xba\x02{\x1b6\x0fz{\ \xc4\x18\xab$\xe8j)\x0a\xd9\xcevzjh\x8fI\ \xbd\xc7b\x11\xd0{\xfbKQ\x02J\xae-\x22\xfc\x8b\ \x9e\xb5(\x8dQ\x00\xe6\x11\xe66\xff\xa5\xcb\xf4\xacV\ \x81li\xaac]\xa8\x12\xd7\x5ce\xa9p\xcf\xb2\xc8\ 4h \x80\xb4F\xae%\xe4,0MT\xab\xe7\xa0\ \xed\x1f\xd0\xd9\xa6|\xc9\xd7\x07*\xb9\xde\x5c\xd2:\xce\ \xd66\x07\xb0R\xf8\x86F\xd8\xa6\x140\xfd$\xf1F\ \x85mX\xe6s\xe1\x94\xdf;P\x1f\x16(\x1a\x12X\ T\x090=\xa3\x09,\xa4\x00|\xe9\xd5\xbd\xcc\xf9W\ \xef\x0e\xcbo2\xf6\xba\xab\xb9\x15}\xc4\xa7\xa8\xd0\x15\ \xf5\xfaM\xe6~{\xa1\x92\xe6\xae\x92\xe7-(\xe8W\ n5\x95\x9a3[\xc3\xb3V\x88\xec\x9d\x01\xeb\xd9\xde\ t\x95Di\x11\xd8\x96o\x01@\x8e\x9b\xb7>-\xd2\ \xc2\xd4\xfe|a\xea\x1c\x805\xa6\xa5\xeaWT\x93a\ \x84\xcc\xbdy\xe5+\xda\xd3\x88\x14\x97|\xb8\xa4\x1d\x83\ !\xb3A\x91\xfa\xad\x8a*C\x026\x01\x9e\xdccX\ \x1aX\xb9\xe7\xbe\xc1\x11\xa5\xa5Z\x00V\x96\x86\x0a\xb3\ \xfd\x0d^s\xfe\xad\xc2\xbfT\xf0\x03\xd1d dL\ \x81\xd9\xe7\xce\x1f\xc7yX8\x88mX\xdb\xac\x985\ [\x9d\x0e\x8d\xb6\xa7Emf\xb7'-\xed\xcf\x17\x95\ e\xa5\xa5\x8a\x80+j\xef\xca\x94\x03}H\x81\x92\xe1\ \xbet\xe8\x8fI\xe3\x06\xe5\xc3\xc8(\x02\x8a\xa3\xdc\xbf\ E\xc6\xaf\xea\xbc\x00\x13\x19%\xc0\x96\xa8\x05Y\xd50\ \xc0\xfa\x87\x00\x0c\xda\x8e\xee\xb4\x0a\xd3\xff\xbc\xc2?{\ \x9fnB\xaa\xd6\xd3\xaf\x22\xf0\xab\xa6y\xd1\x8aK\xc9\ \xffvkJ[\x90\x0d\x01[\x83Ys\xd5\xa8{\x1a\ \xb4=-\x91\xb2\xbc\x05\x0a&\x80$-%V\xbf\xa6\ \x93\xd4\xfb%\xe7K\x1d\xc1d4\xa3\x1b\x22b[\x0d\ W\x00\xa8V\x01\xa6\xb6\xdfJX&\x81\x9e\x0a\xea\ |d\xaa\x98\xfc-\xb7\x16R\xc9\xbf\xac\xfb\x1b01\ \xadW\x01\xb0\xa4\xafJ\xb2\xad\xc2U\xfe5x\xb0]\ \xab#\xfc\xb3\xf2_\x9d\xf1Z<\xc9i\x9e%\x7f\x95\ \xb2\x7f\xc12\x92\xec\x9f\xcf\x96\xbc'\xf8\xa60[\x02\ [I2F\xb9\x05i\x81KK\xa3H\x8ce\xf2d\ \x89i\xc9\x84=\x07\xa6\x1ewr\xcd\xd0\xab7^T\ \xae\x13\xf2\xbd\xfa\xc4\x1d\xa9\x12`[)`\xb4JT\ \xb0\x02\x98\xd2b\xf2\x97\xf3##\xbc\x01\x1a3\x09P\ \x92y\x0d\x0b\xbc\x94*\xc2\xdf$\xf8\xad\x13\xfb\x12\xe1\ /3\x91Y\xef3\xc5\xc3v^va\xd1b\xa1\xce\ \x82e`\x10R\x03\x88\x15N\x8e\x0a\xdf-h\x10j\ \x5cSk\x06\x81\xb7$\xfe6\xa2F4\xb2f\xb41\ -j\xbe$i\xc1\x16\xa4%\xb6-\xabiic}\ \x91_\xce\xa4x\x0e@Q\xbe\xcc\xf55?\x83U\xd7\ \xe8\xc5b\xf2\xb7\xcd\x9a\xd7\xdb\xd5\xa4\xa3\x9c\xb1\x02h\ V\x01\xed@\xb7\x06\xe8\x96\x00u8@\x0fC\x9f\x18\ XiC!M[P\xfdo\xd5$\xc0ZT\x10p\ u\x84\x7f\x91\xf05\x09\xffz\xe3\xfd\xe5\x82\x97Y\xa2\ X(\xf0-\xf1\xcc\x871\xa7PV\xbdk=c\xbd\ A\x03c\x89\x05\xa0-\x8d\x19\xa0\xc5UV4}\x87\ \x8f\x16\x92F\xbf\x9di\xc9\x95!\xd3G\xd9[Bn\ \xf3/\xedk\x80m\xac/L\xefI\x17Z(Y\xde\ \xb2\x96\x91\x9cU\x9ekQ$\xd4\xde\xbd\xea\x5c\x10\xae\ I\x08\xcb+\x891\xc3\xb0\x0fA\x22\xf0\x0d\xd6\x80$\ \x5c\x99\xa7\x94\x9d\x13\x10\x85\x95O\xf2\xbcJ\x80\x1e\xa7\ |\x22\xcb\x87\x00j\xbc\xfe\xca4\xca\x020\xcfd\xc8\ *\xc2_\xbfh\x13\xfe\x8c\xe5\xdd\xe58\xbf\xd4\xfd\xad\ \xf7Z\xdc\xf5gf/\xd9\xb5\xa2\xb2FF/\xc8\xb6\ \xe7\xea\x90v\xd4\x9e\xa6,\x8fUyl+[\xf2\x01\ \x9d\xb4.l\xc3|\x86\x94V\xa7\x85E\xf9Q\xb9\x8c\ Y\x1a8\xf5\x03>@\xb1@J\xf7\xee\xb7\xf9PZ\ #\xbd\x1d7\xdc\x93\xd5I(\x13n\xda\xeb\xcf[\x03\ t% \xe3?\x13n\xde\x12\xa0\x86\xb1,V!\xc8\ \xe7e}\x0a\x80&\xa5\x0a\xe4s\xa9{\xa1\x907\xb8\ \xeb\xeb\xfb\xf50\xed\x82_k\xc0(\xeb?\x17\x1f\xcb\ \x03\x18\x94\xca\x90\x8bl-\xe7\xc5\xfd2 \xaa<\xac\ \xf5\xcb\x9a\x00`\xfb>\x06\xb4-lQZ\xb6b\xa3\ )fm\xbfj\x86Rx\xaeC6O\x94m\x13S\ C\x03e\xef1\x18\xc4\xd4N\x8c\xb1-\xd6\xac\x01\xaa\ \x12\x10\xb9#\xe3\x9e?\x89\x9d\xcc\x9d\xf8\xf4\x99\x94/\ \xe5\xd90\xd3\x00r\x96\x84\xfc\xe36\xc2\xea\x15\x80\x8a\ \x93\x1b\x97Q\xc1\xcaz\xd9&Am\x12\xfe&\xc80\ C;\x17\x9eI\x91(\xd0z\xe6I\xf3\xdc\x957V\ \xc0\x22\x8b\xb9b\xc9`\xe9\xb5V\x90\xe9\x06\xc4\xcd\x05\ e+e\x1b\xd3\xc2@i\x19kK\xfcU2\xef\x9d\ \xd2\xc6Wm\xe9\xda\x92.=-\x9ai\xb8ue,\ \xce\x03\x92\x16\x00Zn\xbe\xd4\xfd\xc8\x8f\xbc\x90\xb9-\ \x11\xcarw\xd2x\x86\x8f\xda|\xc6~\xe4>\x00\xfa\ <\x81\x9c\x99_\xb1\x06d\xb2\xce`\x0d\x90J\x87>\ 1\xb0\xf2\x12\xc0\x0aTR\x02\xd6\xac\x19l|\x0e\x80\ \xd9o^h\xeb\xe7uM\xffU\x85\x7f\xd6\xe4\xcf\x12\ \x7f\x9cG\x05\x93q\x9e\x0fK\x0b\xc7&\xf4\x8b^A\ \xd9\xaa\x81\x85\xebj|\xa3\xc798\xe3`,:^\ ,\xd0\x0d\xa0\xc45J\x0bK\xf2F\xbf\xdex\x94\xb8\ r\xcf\x8b\xd2\xc2\xda4\xc2\xac\xa0\xe5\x0bS\xd3\xd2\xb6\ \x04\xe9i\x01\xc0=\xde\xee2\xc6\x00\xce\xe3z/\xd3\ \xb2\xa4t\xc8u\xf82H\x9b\xfc*\xfa\xd8O~\x08\ m\x81ue\x80\x13\x8b\xca\x17\x00\xae\xec\x13`\x12\ \xd6\xa6\x09\x82\xba\x10N\xe2`I\x80\xaa,\x99\xd2V\ (\xd8\x0b4\x88\xcc\xf3\x18*\xe5\xc7\xb2\xf5\x83\xf5\xce\ \x01\xb0\xbdyh\x02Nya\xaa\xe9&\x13\x84A\x83\ 3kvY;M:\x86\xc5\xb2\x939bw\xd9;\ \xd6\x0b\x15\x09\x91\xfe\xe5<\xd3\x8b\x86\xe2\xd7\x84I\xf9\ 0;\xac\xb6m\x91\x95\x81(JK\x18\x86\xb9\x0a\xd2\ \x168c\x08\xc3\x10$\x04D\xfc\x03\xd0\xca\xb40\xc6\ \x82 I\x0b\x11%\xe9i\x1b2_ D\x94?\ -M\x8b\xec\x08\x08\x99\x860\x04y^{\xd3B\x14\ \xb7a\x94\xd4\xfbu\xa6\xc5<\xf1\xcd|\xdd\xe4\x97T\ \xabKl\xc5$\x8a\xea\x0bc\x0c\x82R\x09\xad\xdf\x9f\ \x19$\xcc\x5c\xa7\xf4\x7f\x83\x80\xcf\x1c[\x14\x80\xdc\xb9\ !\xf2\xb6\x16\x89\xa9\xfe7\xd4l-I\x01P^\xa4\ \xe6\x9e\x11\xc0j\x86\x9b\xec?\xb9\xdb\x8dEA\xbb\xc5\ \x1a(2&{\xd2\xb2V\xcdu[\xb8\x14\x0bM\x10\ \xa6\x93)\x84\x08q~v\x06\xc69H\x08d\xeck\ \x95\xe2nz\x8e\xe1\xda* \x02\xe7\x1c\x82\x08\xa3\xd1\ \x10\x0c\x0c\xcf\x9e>\x8d+\x8f@\xbb\xba5\x04\xce=\ \x84a\x80\xd1x\x0co6\x8d\x5cc\xc5\xa6=D\xe5\ \x87s\x8e`6\xc3d:\x01]\x00A\x10\xb4S\xd0\ \xb2\x90M'\x13L\xa6\x13\x9c\x9d\x9da2\x1e#\ l[Z\x88\x12K\xdfx<\xc6t6\xc3\xf3g\xcf\ \xe0w:q\xbe\xb4k\x0c\x801\x0e\x10a4\x1e!\ \x0cB<{\xf6\x0c\xbe\xe7!\x14!\xd6\x97\x8e\xb2\xde\ \x8e\xad\xf7\xc4\xb4S\x0e\x22\x81\xc9d\x0a\x02\xe1\xec\xec\ ,\xdf\x89\xc9\xdc\xa3\x9ag+\xb8\xcb\xf9\x03\xa68Y\ \xc3-\xf3\xab\x93\xb5;D\xa5II\xc3\x1a\xc7\x00\x97\ \xa4\x00\xd8\x22\xac-5\xcbx+0\x07HW\x96}\ Q\x9903AdM<\xa6g\x98\xdc\xf3O5\xf4\ \xeac\x01/\xc2\x10A@\xe8v\xbb\xe0\x1e\x07\x09=\ \x0c\xbb\xe4\xb1\xc5\xa9\xdc\xefr\x91\x15e6\x9d\x00`\ \xe8\x0f\xfa\xe0\x8c\xb7\xb2\xd7\xcc9G\x18\x06\x98M\xa7\ \xf0<\x1f\x83~\x0f@K\xad\x19\x9cc\xe6{\x98L\ '\xe8v:\xd8\x1b\xf4!D\xfb\xd2\x01Di\xe1\x8c\ a6\x9b\xa1\xd7\xebbo0@\x18\xb6L\x01@\xdc\ \x06\xc7\xf5%\x0cC\xf4\x07}t;\xddV*f\xb2\ \xfd\x0dE\x88)\xa6\x18\xf4\xfb\xf0}\x7f\xf3\x16\x80\x0c\ UZ\xd2X\x01@\x94'B\x10z\xbd\xae\xa2\x000\ \xeb\xfd\xa6\x16\xbf\xbc\x05\xb7\x85\x97\x0a\x7f\xeb5K<\ \xf2\xa4\x81d>\xfb^\xe9\xde\xc5Y\xe9\xb7\x002\x22\ ;7\x16\xce\xb4sy\xa2_\xcd\x87o\xda\xac\xc7\xb6\ \xe6_7\xbf\xeb\xe3\xfe\xcc\xf2<\xdd_\x18\x06\x00\x11\ \xf6\xf7\xf7\xe3\xcd\x80\xb2\x1e\x8c\xf1\xd5u\x1eKzL\ \xcf-\xf79?\xd2\x02p|t\xbc\xd4p\xd7\x0d\x11\ a8\x1c\xa1\xdb\xed\xe0\xf0\xf0h\xd3\xd1Y\x88 \x98\ \xe1\xf2\xf2\x12\x83\xc1\x00\x07\x07\x87\x9b\x8e\xceB\xf8\xbe\ \x87\xf1x\x84\x83\xfd}\x0c\x06{\xe574\x18\x06`\ :\x9d\xe2\xe8\xf0\x08\xbe\xdf\xa8U\xd3\xb5\x09\x82\xa8\x0d\ ;::\x02\x97\xf3\x7f\x96\x8ee\xbc\xbb\x86i<1\ \x18\x93\xd9\x1d\x14\xe5\x89\x10\x84\xfd\xbd=\xa3\x09\xbf(\ \x0c\xb5\x93@\x9a\x9f\xcc\xfdI\x98\x8a\x7f\xd3\x10C\x81\ Q\x974O\xe6\xe1\x0d\xca\xcd\x01\xa8\xba/\xc2\xa2l\ \xbcDW\x15m\x85\x82\xb4H[\xd0\xee%\x02\xb8\x14\ \xda\x86\x1b\x8d\xca\x05\x90\x8e\xcd\x92\x80\xcf\xbc\x8c\x872\ \xe5\xc1\x12\xad\x02K\x8f=\xb5\x8b\xaa\x02\x82\x04D(\ \x22\xc5\x93\x048[UC\xb0zB\x11B\x88\x10\x22\ l\xe3~sYD\x18\x8f\xff\x0b\xb1\x1di\x89\xd3\xd3\ \xf6\xb4D\xf3L\xa2r\xc66\xdf\x5c.\x84\x08\xc3h\ .\x83\x08\xc1\x96\xac\x00\xd8l\xadI?[s.\xfb\ \xc2\x9ez\x90_\xb6G \x11\xcd\x01H\xdce\x9bK\ \xd9\x81\xd9*\x13\x03\xf5g\x97\x09\xd8*~`\xf1c\ K\xf3\xa6F\x95\x9aU\xa2\x970\xf6aZ\xf6W\x16\ |\xa1e!\xe3SQ\xff\x0cB\xbelI\xa1\xe99\ \xb6;\xca\xdeD\xddW%\xcb\x17\xa3\xf4,\xb6r\xb6\ lDS\x89\xab\xe1\xa3 \xed\x85\x90|\x0c\xa8\x85i\ \xc9\x96\xa18\x1dhg\xbe\x18\xcb\x18\xa5iic}\ \x91KL\x93\xe6kI\x09(\xdb\xf01?\xa8jP\ \x08,=h\x93\x10W\x95\x80\xb8\x98\xe5\x1e\xae\x0bh\ \xf3\xfdJ\xbcMJ\x02b\xa5\x82\xa2\x96\xb2\xca\xb2@\ S\xd8e\x8a\xc2\xa6G,\xd7\xaa\x00,Z\xe6LK\ \xff\xca\x0arN\x09\xa8\x11\xa7\x8c&\xaa\x16\xf4\x1a\xc2\ \xdf\xde\xe3gV\x7fy\xbf\x8b\x93\x0b\xdf\xb4wv\x0b\ \xc8\xbe\xcf\x82\xda\xd82\xda\x94\x07&r\xf1oq\xbe\ 0\xed8\xfa\x1a`\xbb\xebKb\xed\x5c\xf2\xa6F\xa5\ \xedT\xce\x04\x9fW\x082\xfb+h\x87\xaa\x12\x00\xe8\ \xc5*2#0\xa5\x81N\x85\xb6\x16\x8e\xa6\x04\xe4v\ \x0c,P\x12\xcaX\xbc\x19\xda\x9cJ\xd9,\x0b\xc0\x1c\ \x18\xb7P6\xbc\xcb\x9c\xf2\xa0\xad\xb7\xd6{\xff\xaa\xf0\ O\x0a\x13Q\xe6\x5c\xbd\xd7\x94}\xf9\x1e\xbf\xdd:a\ \x8acUte\xbaT\xa9Q\xbe\x05\xd0\xa6\xc6\xcc\x0c\ -\xbdQ\xdb\x08\x91\xa4I\x0e\xdb\x8c\xda\x80\xb6=-\ *mNKf\x04\xda\xd2^\x15\xddk\xe8\xb0W\x22\ \xb3\x84\x9bL\xe1\xa4\xa2Z\x15\xf2\xa62\xa4*\x02\x99\ \xbb\x19\x92\xbd\xfc\xd5\x9e\xbb\xbcn\x8bo\xa5%\xd0\x96\ \x00\xea*\x09\xd6\xe07\xdc\x87Y\xeb\x00p\xd5t\xd6\ )\x9c\xc6\xc9\x7f5\xc3\xb0>;sb\x193\xb2<\ \xa8\xaa\xf0g,\xfdU\x89\x9b\xe9g\x8d\xb2\xc3\xe1p\ ,\x88\xa9\x8d)j\x83\xac\xe1hm]\xf6\xde\xf4\xac\ \x8a5\xd5\x1c\xcfl/\xae\xaaU5\xdfV\xd7\xa7,\ \xec\x92\xbb\xeb=\xab\xf6\x1dv6j\x01\xc8\x0a\xdb%\ %\x89\x19\x0f\x8d\xe7U\x83\xb3)\x16e\x05\xb5H\xf8\ W\x15\xf8\x8byP\xc8\x99\x064\x15\xb9-\x9a\x83\x12\ W&\xcf\x81\xf6\xc4\xbf\x10\x02\x03\xb53-\x86\xf2\xb5\ 5i\xd1\xbe\x06\xd8\xc6\xfa\x22\xbf\x02\x9eK\xcb\xa2a\ \xc7\x98\x82+\xea\xf0\xd9M\xee\xd1\x99\xbc^\xd8\xd36\ \xee\xe7\x9b\xbf\xc7\x14F\x95\x1e|\xd6\x0aQm\x1e\x80\ =\xb0\x0dw\xf5-\xacX\x01\xc8'\xb8\x92\x89\xda\xe0\ f\x1a\xff\xaf\x1a\x86n\xa2W\xcd\xff\xd6\x89\x7f,/\ \xfcM\xcf`\x06\xb74\xdcb\xc5\xa1,\xdev\xc7j\ \x98\xac\x19LJ\xcd\xf8c@Kk\x0c\xd6E.\xbf\ \xd2\x09gm\x86\xa1|BU\xa3\xd1#\xdd\xe6\xe1\x8c\ \x5c\xa4\xb5\xb4\xb4)Q\xb9\x86\xaaZ\xbe\xe8c\xf0\x85\ a[n\xce\x15\x09\xfd\xf6\xd8C^\xd0\xdb\x95\x00-\ \x19\xb98f\xbe\xe8\x17+>\xa4\xf8\xb1)\x1e6\xa5\ \x81!;\xa4\x00\x83\x9fE\xd8\xb4N\xb0v\x0b\xc02\ \xebN\xce\xfc_\xd0\xfb\xaf\x1a\x07\x9b\x10\x8e\xe4&\x95\ \xfbM\xe2\xc5r~\x96!\xf8\xdb\xd4\xf68\x1c\x8ev\ b\xeb\xd8\x98\xc8\xc90f\xbeh\x13\x98\xfa$@U\ Ea\x8c\x0a,\x01\x9a\xca ;9\xb1\xc4\xae\xa2\xc4\ \xa8\xf3\x00d\xb3\xbd\x88P.V\x98\xf2\x81o\xda0\ \xd0\xb8U\x00\xab\xb6\xae\x99\xd6\xfe\xe7=\x95\x85a\xb0\ 2(\xd7L\x01\x98\x1e\x9bs\x9aS\xe8\x1b5d\x8d\ \xcc{Uf\xe30\xfdZ\xc3\xc9\xc4\xb5\xa2\xc2\xd7\x1e\ (3\x83\xb9M\xa8\xf9\xc2\xb4\x86\xb9m\xe4\xd2B\xd2\ \x1a\x98\xbf\xdet\xd4\xde\xaf*Z\xeb\xc6\xbfH\x98\x16\ \xf6\xf45e\x80\x99\xfc\x18\xc2\xcb\xf4\xc6\x0d\x96\x80\xaa\ \x96\x0cc\xf8\x1b\x16\xba\x80)-\x9b)Q\x8d_\x05\ \xb0\xae\xd7b\x13\xe8\xb5\xc2\xd0nb\x16wc\xf8\x96\ {\x8d\xcf\xa9\xe8\xe6p8\x1c\xcb\xa0\xc8\x22P\xa4\x10\ \xe4\x94\x01mx@\x17\xf4\x80.\xec\xf3*G\x95\xb6\ .\xf9\xa8\xf02\xec\xf4J\x98\x0b\xcd\x03h \x8d\xdb\ \x06\xae\xacp\xd5\xbd\xbf\xce\xdc\xc2*\xa6x\x9b\xf0\x9d\ K\xf83\xe5\xa79\xe5\xc2\xb7\x5c\xab\x0a\xd3\xfe\xda\xdc\ \x9aN.\xfe$g7\xb5\x9b\xb6\xa7%W\x86Z\xbc\ 43\x1f\xef\xfa\x02\xa8)\xa8u\xdc4\x8c\xb9\xacg\ \xd8\xda\xa7\x9c\x9b\xa1\xbd+\x0a79fy\xb7\x22\xff\ \xb68\x1a\xafY\x84D\x9b\xf2y^\x1a\xa7\x00T\xa1\ n\xc6\xd83\xde\xec\xb9\xcc\x1a`\xd7\x86\xa3bf}\ ^Q\x5c,\xcf\xd9\x85B\xe8p8\xb6\x07[[f\ s(\xef\xb4\xb1\xac\xbb\xe2A_B\xcd\x8c\x01\x1a\xe2\ X\xa0P\x94m-_\x97&\xb7\xe1\x8dW\x00\xaa\x9b\ {\x96\xfb\x0c\x19fz\xcd\xae9['\xf7UTW\ \x9d\xe0w8\x1c\xdb\x86\xde\x8e\x15Y\x03lJ\x00\xcb\ x\xaeg\xd15\x85;\x0fU\xc3\xb0)\x15M\xb6\xe9\ 5~\x0e\xc0<\xcc\x93\xe9fM\x90i\xd33\x8aL\ \x81Y\x85\xa1p\xd9\xa2\xad\xd0W\x89\xa8\x85\xf2\xc9\x8d\ QJ\x98<\x96\x13\x9b\x18\xc3&'\xa1\xd4\xc7\x10W\ \xaa\x92\xfe\xf6\xd0\xce\xb4\xe4\x16\xcf\x03\xd8\xd6\xb4\xb4\xb0\ \xbe(\xc3KQ\xafy\xbe\xf8\xcf\xf3\xb9m\xd9\xc2\xd8\ \xce\xad\xfeX\xc9\x88\xc5\x12\xe2R\xf7\xfa\xb6\xb1V\x05\ `\x99\xd5\xa6\xca\xf6\xbf\xf9{\xcc\xeb\xff\x8b\xc2(\x0b\ \xd6\xb4\x8f@a\x186kA\xc9s\xd2\xe7\xb5\xa5\xe1\ q8\x1c\xdb\x86\xa9\xfd\xa9\xa2\x14\x14*\x01\xca\x89I\ \x00\xa7n\xcaU\xfd[&\xba\xb2\xc0\x90l\x0fl\x8b\ C\xe6\x19U\xb6\x05F\xd4\x85\xa2\x12\x15\xc1\x1e\xff\xe6\ \xb1\x95\x16\x80EX\x8a\xc9\xa8\x8a2R+<\xc5\x06\ A\xb4\xb8\x12 51\x96\x16\xce\xb6\xa8\x15\xd9%Z\ \x91\xcb6\x0c\x990 \x998\xd7\xc6\xb4\xe4\xf2\xc5\xb2\ \x19L\x1b\xc8Y\xfd\xb6a\x19\xa0\xac\xe8\xda\x06M\xcb\ \x12L\xb2M*\x12\xa2\xcb\x12\x84\xa5\x9d\xb2%=\xa7\ JX\xc5\x0aK\xf3\xd9*\x05\xc06\x8eT\xe7\x9e\xc8\ \xcd\xe0J\xba\x9f\xb2P\x0cW\x0c\xa6\xff\xba\x0dI\x99\ \xf0\xb7]M\x1a\xad\xb6\xb4\x5c\x0e\x87c\xe5Tm\x0e\ \x0a\x85`fR^qOZW\xa2LV\x80l\xd8\ \xa6=\x00\xe6\xc0\x10\xc0\xd2\xc2n1\x8d\x9f\x04\xb8(\ s\xcb;\xd3\x8d\xb4\xc0\xb7\xda\xe7\x14\xfeEKTL\ ?\x87\xc3\xe1X6u\xda\x9a*\x16J\xd5Z\xc4t\ \xc7JwVg\x9evq\xd9+\x01\x9a\xcaV)\x00\ \xeb\xd0\xe2\xa4r\xbb\xea\xbd\xce\xdcX\xbf\xc3\xe1h2\ Ko\xa1\x1a4l\xb4\x0d\x9b\xfcTa\xab\x14\x00c\ \xa7]^+\x10\xa8\x95&\xef%\xe1\xa4\xd7\x8c\x1f\x12\ Z\xd2\xe4\xc2(\xac\xbc/\xd7\xd3w8\x1cM\xc1\xda\ v2V\xbf\x13c\x9b m\xb0\x9e\x16\xf9\xcb\x069\ _ki\x8c\xbaa\x08\xa1\xedl\x95\x02`\x22\x19s\ *S\xe9\x0a2\xb3\xf8K\x84\xe5\xe3]\xcbb\x0b\xca\ \x9b\xc3\xe1\xd82l\x9d\x92y\x96\x0c\xbaFn\xbd4\ C\x01h\x82*UPV\xf5r\xdc\xde\x8dA\xdb\x16\ [\x87\xc3\xd1V\xd69\x8cYkU\xd5:\x1e\xd2\x12\ \xd6\xaa\x00\xcc=\x7fn\x09/^\xdd\x03\xc0\xeca\x19\ \xcf(\xb9^)\x8c\xbc\xe9l\x19f\xffl\xea\xa3M\ A\x98\xf1Z\xb3\xc9\xc5\x95\x92\xff\xb6\x806\x7f\x0b@\ /C\x04\xb6\x05i\x89f\x88S\xa6\x02\xb6\xb1\xbe\xa8\ \xcb\x1aW\x15{S;Uu\xe85w_.\x9c\xfa\ q\x99w\xe8u\x97h\x86\x05\xc0\xc2<\x131\x17\xc9\ `\xfbx\xd6\xf2\x9e\xb1\x8c\xfb\x1d\x0e\x87\xc3\x91\xa7\xca\ \xf6\xebej\xe9B2d\x9e\x89\x0a\x1b\xa4\xd1\x0a\xc0\ \xb2YU\x7fd\x95Y\xda\xac\xe2\xe2p8\x1c\xf5\x98\ g\x02v\xe5\xb0\xb5\xf3Ef\xef'\x9b\x19\xcd\x1fD\ 9\x0d[^\xb0S\x0a\xc0FX\xb2\xf5\xc0\xe1p8\ \xdaF#\x9657h\x99aSh\xbd\x02\xb0\xb1\xf1\ \xb89\xc7\xfb\xab\xee\xa8\xe5p8\x1c;I\x03\x9b\xc1\ \x06Fi)\xb4^\x01h\x0b\xdbZ\x80\x1c\x0e\x87\xa3\ \x8cZK\x02\x17\xe8\xa9/\xd2\x87\x22\xed;\x09\xbb\x80\ S\x004\xda4\xc3\xd7\xe1p8\xda@\x9d\xed\x81\x1d\ \xeb\xc3)\x00\x0e\x87\xc3\xe1p\xec N\x01\xd8Q\x9a\ 5\x17u\x11\xb6'%\xdbD\xbbs\x85\xf2G\xedN\ P\xccV$\x22a\xbbR\xb3\x19vJ\x01h\x93\x89\ i\xe5{\xfe\xd36T R\xfeo;\xd4\xe2m\x80\ t\xda^\xb8L\x9bM\xb5\x9d5,qS\x9e4O\ \xdb\x95\xf94pu\xdfK\xa1M\xb2a\x99\xf8\xab\x0c\ <\xdaEk;\xe0\x9c'?\xa0\xbd\x05\x86s\x0f\xdc\ \xf3\xc0\x00x\xdc\xdbtt\x16\xc2\xf7}p\xee\xc1\xe3\ \xed\xd7c}\xdf\x87\xc7y\xeb\xf3\x04\x88\xf3\xc5\xe3\xe0\ \xdb\x90\x16\xcf\x03\xe7\x0c\xbe\xbf\xd2\xa6r-x^T\ W<\xaf\xddia\x8c\x81s\x0e\x02\x81\xb1\xb6\xee7\ \xd9\x0c\x96Z\x12\x0a3\xa2\xa8S@\x22\x17\x06c\xca\ \xb1\xe1\xc6t\x1b[\xfb\x87y\xe5v\x90\xea6\x98\xd9\ {M\xe1)\x0f%\x80\xc7\x93Wf\xc1\x0cA\x18b\ <\x1e\xc3\xe3\x1c\x82\xc8\x18\x87\x5c<\x0a\xbed\xb5\xd8\ \xae\x85\xf5\x8b=c\x1c\x82\x04f\xd3\x19\xc0\x80\x8b\xcb\ \x0bp\xce!\x84h\x9dB\xc39\xc7l\x16`6\x9b\ \x811`8\x1a\x02D\xf3}\x80d\xc3p\xce1\x1e\ O\x10\x04\x01&\x931F\xa3\x11\x84\x087\x1d\xad9\ `\xe0\x9c\xe1\xf2r\x880\x080\x1a\x0d\xe1\xfb>\xc2\ 0\xd8t\xc4j\x13MZc\x18\x8dF\x08\xc2\x10\x97\ \x97\x17\xe8\xf5\xfb\x10a\xfb\xf2\x851\x06\x22`<\x9e\ `\x16\x04\xb8\xb8\xb8@\xa7\xd3A(\xc2\x85\xeb\xfd\xbc\ \x1b\x0b\x9bj)YNTw\xc6\x18\x04\x11f\xb3\x00\ \x82\x08\xe3\xf1\x18`\x0cD\x94\xf1\x97\x0e\xdd\xa4-\xa5\ \xfe\xcc\xbc\xbb\xd2\xaa\x1a\xe4U\xea_\x97(\xf6t\xe4\ \x9b#\xdb\xbd\x04Pq\xb8\xab`A\x05\xc0\xf6\x8a\xd2\ S\xca\xbc\xc9\x5c\x92\xe3\x03\xcbk\xd4\xef\xd3\xf7}'\ 2\x9c\xeb\xf7\xc7f\xe2\xdc5\xd2\xee!c\xf8\x8c1\ \x80\x08\xe3\xc9\x18\x22\x0c\xf1\xf2\xe5\xcbXh\x86\x96\xf8\ \xd8\xd2d*\xd1U\xfc\xd8\xa8WD\x08Q\x8f_\x08\ \x81\xe1p\x080\xe0\xc9\xe3\xc7`\x9c#\x0c\x17o\x08\ \xd6\x8d\xe7\xf9\x98\x053\x8cF#\xccfS\xb0\xc7\x8f\ !\x04\x81\x14e\xb2\x1d0x\x9e\x87\xe9t\x82\xc9d\ \x82\xb3\xf3s\x04A\x80\xb0e\x82\x86\x105\xce\x1e\xf7\ 0\x1e\x8f0\x99L\xf0\xfc\xf9\x0b\x8c\xc7c\x04A\x88\ 6\xd9\x02\x09\x91R\xc6\x18\xc3p8\xc4t2\xc1\x93\ 'O\xd1\xedv\xe3|iOZ\x80\xc8\xeaG$p\ y9D\x10\x06x\xf2\xe4\x09\xfc\x8e\x8f0X\x86b\ V\xf4\x19\xd5\x22\x07f84m\xde\xcf2\xc7:\xc2\xc9\xe9)H\x10\xa8M\x82\x86\xa2\ \xb6\x8ds\x8e\xf3\x8b\x0b{\x06!\x04NN\ N\x12\x05\xa0\x8e\x05\xc0t\x9c\xe9\xbfY\xe6L\xc8>\ \x9f-\xac\xbc\x9b\x16N\xae\x8f\xc7\x00\x884m\x05a\ \xae\x82\xa5\x0e\x01\x98d\x92:\xb1\xc3\xaa.(\x09W\ \x8fX\xfer\xce\x8d)R]\x9f|\xc2\x98\xea\x9f\xe5\ \xae\xc9\xf0X\xe6\xfelx\xd2\xaf4e\xf6\xfb\xfd$\ \xa3\x18+\x8fg\x91\xd2\xa1\xc3\x8c\xefa\xf9\xf8~\x07\ \x8c\x01{{{+|\xca\xea\xe9v\xbb\xf0\xfd\x0e:\ \x9d.\xfa\xfd\xc1\xa6\xa3\xb3\x10\x9cs\xf8\x9e\x87n\xaf\ \x87~\xaf\xbf\xe9\xe8,D\x10\x86\xf0}\x0f\xfd\xc1\x00\ \xbd\x96\xa7\xa5\xdf\xef\xc3\xf3|\xec\xed\xed\xa3\xd3\xe9l\ ::\x0b\xd1\xed\xf60\x99N\xb1\xbf\xbf\xb7\x96\xf9\x19\ 9\xe1iQ\xce\x8d&z\xca\xbb\x91\xe2\xe6\xfb>B\ !\xd0\xeb\xf5r\xf7\xab\xfe\xa4\x15Z5\xd6\x92\xc1/\ \x90\xed<\x90\x1e\x8e\x16\x9e-\xde\xd9\xf9\x00\x00 \x00\ IDAT\x1a\xa7|:\x8d\xc9\xd4b\xa9\xfb\xcf\x0a\ H\xd3\xb0wyH\xf5Y\xe9\xec\xa9\xb6i\xcaE\x08\ \x11B\x08\x81P\xb4\xab\xb7\xac\x13\xa5#D\x18\x8a\x96\ \x8e3\xa7\x04\x81LK\xbb\xd3\x01 2\xfb\x0b\xd1\xca\ 1f\x9d0\x08\xb7&-A\x18@\x08\x81`)\xe6\ \xf2MB\x08\xe3\xb4\xb4\xbd\xbe\x10Q\xd2\x1e\xb7q\xce\ O\x93h\xff\xf4\xe9\xb5\xd1\xb6Q\xf2b\xb6\xe7\xb3\x03\ lK\xd2\xb2]{PnKZ\x92!\xbe\xadH\xd0\ 6\x95\xb1mJ\xcb\xe6p\x0a\x80\xc3\xe1p8\x1c;\ \x88S\x00\x1c\x0e\x87\xc3\xe1\xd8A\x9c\x02\xe0p8\x1c\ \x0e\xc7\x0e\xe2\x14\x00\x87\xc3\xe1p8v\x10\xa7\x008\ \x1c\x0e\x87\xc3\xb1\x838\x05\xc0\xe1p8\x1c\x8e\x1d\xc4\ )\x00\x0e\x87\xc3\xe1p\xec N\x01p8\x1c\x0e\x87\ c\x07q\x0a\x80\xc3\xe1p8\x1c;\x88S\x00\x1c\x0e\ \x87\xc3\xe1\xd8A\x9c\x02\xe0p8\x1c\x0e\xc7\x0e\xe2\x14\ \x00\x87\xc3\xe1p8v\x10\xa7\x008\x1c\x0e\x87\xc3\xb1\ \x838\x05\xc0\xe1p8\x1c\x8e\x1d\xc4)\x00\x0e\x87\xc3\ \xe1p\xec N\x01p8\x1c\x0e\x87c\x07q\x0a\x80\ \xc3\xe1p8\x1c;\x88S\x00\x1c\x0e\x87\xc3\xe1\xd8A\ \x9c\x02\xe0p8\x1c\x0e\xc7\x0e\xe2\x14\x00\x87\xc3\xe1p\ 8v\x10\xa7\x008\x1c\x0e\x87\xc3\xb1\x838\x05\xc0\xe1\ p8\x1c\x8e\x1d\xc4)\x00\x0e\x87\xc3\xe1p\xec \xfe\ \xa6#\xb0\x08\xd7\xf7|\x1ct#\x1d\xe6\xd7\xdf>\xc2\ ^'\xab\xcf0\xfd,\xeb\xa0\x9f\x1ay9\x09\xf0\xfb\ \xef_\xe2 \xe8`2\x11\xb8\xb2\xef\xe3\xe9\x98\x16\x89\ \xf6V\xe3q\x86[\x07i\xb1\xbas\xd4\xc1\xa7\xaf\xf5\ \x97\xfe\x9cg\xe3\x10\x7f\xf0\x93\x97\xa0#\x1f\xbdn\x07\ \xbb\x90#\xaf\x1du\x00\x00\xb7\x0f|\xbcw}\xb0\xe1\ \xd8\xd89;\xf3q\xff\xc1\x14\xb7n^\xc5\xd1\xd1\xd1\ \xdc\xe1\x0c\x03\xc2\xef\xbf\x7fa\xbc\xf6\xe1\xd9l\xeep\ \x1d\xcbC\x96\xc9wNzx\xfb\xa4[\xf9\xbeE\xea\ +\x11\xe1\xd1\xa3\x10B\x08\xdc\xb8q\x0d\x8c\x99[\xf2\ \xb2g\xe4\xae\x13\x15_\xaf\x1aN\xc5\x9b\xa5\x17!\x04\ \x18\x03\x183\xf7\xc7\xff\xf9O.p\xefb\x86\x87\x17\ \x01.g\xa2b\xac\xaa\xd1J\x05\xa0\xebE\x19\xfe\xde\ \xf5\x01\x8e\xfb\x1e\x00\xe0\xed\xd3\x1ez^\x15\x91^\x8f\ \xcb\x99\x87\xe7c\x81g\xfe\x00\x931\xc3\xc1i\x1f_\ \xbd?\xc6,\xdc\x05\x91S\x8f\x8e\xc7\xf0\xfaQ\x07o\ \x9f\xf4\x12\xb7\x1b\xfb~\xd2H,\x93\xe3\xbe\x87\xe7\x97\ }\x1c\x8e\xfa\xe8u{x\xe4\xfbx6\x0e\x11\x8a\xed\ \xcb\x17\x8f3\x5c\x1dx\xf8T\xacH]\xdb[\xcd;\ ]\x16g\xe8\xc0\xbb\xf4q\xeb\xa8\x83\xa3\x05\xe29\x15\ \x84'C\xb3\xf2(\x04\xf0x\x14$\xe7\xae>\xae\x97\ \x8e\xc7\xf0\xea\xa1\x8f\x8f\x9dF\xf9\xf3\xc6Qgme\ \x92\x88\xd0\x1bw@D\xb8q\xdc\xb1*\x00mA\x88\ H\xa8snV\x00\x9e\x8f\x07x\xf5\xb0\x83\x1f\xbf\x9c\ \xe2[\x0fF\x98.\xb1\xac\xb7J\x018\xe8r|\xf9\ \xce\x01~\xed\xad\x83\xe4|\xd5\xecw8~\xe9\xf5}\ <;\x98`<\xf6p\xe3\xc6!~\xe5\xad#\xdc=\ \x9f\xe1\x0f?\xb8\xc4\xf7\x9fMW\x1e\x87\xa6\xf3\x99\xeb\ }\x5c\xdb\xf3\xf13\xb7\x069+\xcc\xaa8\xecr\xfc\ \xdck{\xb8C\xfb\xe8v\xbb\xb8u\xfb\x14\xe73\x81\ ?\xf8\xe0\x12O\x87!~\xf4\xa2\xfd\xf9\xe2q\x86/\ \xdc\xec\xe3\x17\xee\x1c`\xbf\xc3\xe0\xf1v7tu\xe9\ r\x86\x9f{m\xcfx\xedK\xaf\xeea\x1c\xa4\xbd\xa1\ \xef>\x19\xe3\xdey\xa4\x10\x8c\x02\x81\x7f\xf3d\xb2\x96\ 8\xee\x1a\xfb]\x8e/\xdc\x1c\xe0K\xaf\xee\xad\xad\xae\ \xef:_\xb8\x95Z\xfb\xce\xa7\x02\xff\xea\xee\x10\xbf\xf7\ \x93\x0b|p\xbe\xb8\x15\xac\x15\x0a\xc0\xf5=\x1f\xbf\xf3\ \xb9S\x5c\xeb{I\x8f\x7f\x93\xecw8>v\xda\xc3\ \xc7N{\xf8\xf3\xe7\x13\xfc\x9f\xdf}\x81\xd1l\xf7z\ \xb7\x0f:\xf8\x8d\x8f\x1d\xe2\xf6\xc1\xe6{\xa3\x1eg\ \xb8\xd2\xf3\xf0\xeboG&\xe7\x1f>\x9b\xe2\x9f\xff\xe4\ \x02w\x97PI\xd6M\xc7c\xf8\xdc\x8d>~\xee\xd5\ }\x9c\x0e6_\xde\x9b\x08g\xc8\x08\xa0/\xde\xda\x03\ n\xa5\xd7e\xbe\xff\xcb\x0f\x87x1\x09\xf1x\x18`\ \x12\xec^\x1d]\x16\x07]\x8e/\xde\xde\xc3\x17n\x0e\ \xd6\xd2\xf1r\x989\xecr\xfc\xea[\x07\xf8\x957\xf6\ \xf1\x07\x1f\x0e\xf1\xbf\xfd\xf1\xb3\x85\xc2k\xbc\x02\xf0\x1f\ |\xfc\x08_~\xfd\x00\x87\x0d-t\x1f=\xe9\xe1\xbf\ \xf9\xc25|\xed\xde\x10\xff\xe2\x83K}\x18iky\ \xf5\xb0\x83\xdf\xfe\xecI2\x1c\xd34\xde9\xed\xe2\x9d\ \xd3S\xfc\xb3\x1f_\xe0+w\x87K5\x9b\xad\x92A\ \x87\xe3\xbf\xfa\xfcU\x5cu\x82\x7f!^=\x8c\x94\xd2\ \xff\xf0\x13\xc7\x00\x80\xe7\xe3\x10?y9\xc5pF\xf8\ \xc3\x0f/q1]\xeeX\xea6s\xe3\xc0\xc7o\x7f\ \xe6\xc4\xf5\xf8\x1b\x84\xc7\x19~\xe9\xf5}\x0c|\x86\xbf\ \xf5\x8d\xa7s\x87\xd3\x0c\x05@m\x9b\x15y\xf2\x9f\xbd\ w\x82\x9f\x7fm\x7f\xed\xd1)\x82\x0c\x12\xfe\xa4\xef\xe1\ \xdf\xfd\xc8!>8\x9b\xe1\xcf_L\xb3\x93\x0b\xa5w\ V\xe8\xa4])\x9fC\xc2*Ma\xd4\xc3N\xef\xc9\ &#{\xad\x8c\xdb\x87>~\xeb3W\x1a+\xfcU\ \xfe\xed7\x0f\xf0S7\x07\xf8\xbf\xbf\xfb\x02\x0f/\x83\ \xf2\x1b6\xc8~\xc7\xc3o\x7f\xe6\xc4\x09\xff\x15p\xd2\ \xf7p\xd2\x8fL\xa9_\xbc5\xc0\xfd\x8b\x19\xbe\xffl\ \x8a\xef?\x9d\xe0\xf1P/\x17i} \xf9\xdf\x02\xf5\ e\xb3\xa8q\xad\xaf\x04_\xdf\xf7\xf1[\x0d\x15\xfe\xa6\ \xb6x\xd7\xf8\x99\xdb{\x10\x04\xfc\xedo\xce\xa7\x044\ #W\x99\xf2\x8b\xf9\x9d\x06\x0a\x7f\xc6X\xe1\x84\x93\xdf\ x\xe7(o\xa9\xd0\xd2eq\xd2\xae\xb0\xd2\x7fs\xc4\ ^&\x02\xe9\x8a\x08\x96\xbdV\x01\xce\x80\xdfy\xef\x14\ =\x7f\xf3EG\xe6E\xd9$\xa0\x93\xbe\x87\xbf\xf6\x99\ \x93uDin\x06\x1d\x8e\xdf\xfe\xec\x09n6`8\ e\xdb\xe9x\x0c\xaf\x1fw\xf1ko\x1d\xe0\xbf\xfc\xfc\ )~\xfd\x9dC\xdc\xd8W\xfbBL9\x92e\x0c\xc6\ \xeb\xcdG\xad\xe3\xb2\xeeW\x8b\xff\xb5=\x0f\x7f\xfds\ '\xd8o\x98\xf0\x97\xedp\xdb'\xff-\x8b/\xbd\xba\ \x877\x8f\xab\xaf\xc0PYi\xce\xce\x9b=\x7f\xe5\xdd\ \xa3\xc6\x09\x7f\xce9\x18c\xd6\x99\x9a@4\xe3\xfdW\ \xdf\xff\x0an\x1ev\xe7\xca\x93\ \xa6Q'_6\x8d\xcf\x19\xbexk\x0f\xff\xf5O_\ \xc5\xbf\xff\xf1\xa3\xdc\x9c\x0b\x99\x16\xcfk\x86\xb1t\x11\ \xd7|\xa1\xa5\ \x96\xea\xfc\xbaJ\xf9\x87\xc0\x88\x814\x1f\xc9\x99b\xca\ 9\xear|\xf9\xce\x1e\xc20\xcc\x87\xaf\xaf\xd3,8\ \xb7\x1d\xdb\xae\xd9\xfc0\xc6@D\x18\x8f\xc7\x98\xcdf\ 8??\x07\xe7E\xb7\ \xdb1\xb6\xb1\x92_\xb8\xb3\x8f\x8b\x17\xcfa\xde\x85A\ \x0d{\xbe7a\xba\xcf\x16\x96\xea.\xdb\xe3\xc9d\x02\ \x22\xc2\xf9\xf9y\xe2f\xf3?\xefq\x1d\x7fU\xdd\x8a\ \xde\x97-\x0dU\xe8\xfb\x0c\xaf\xec\xf9x>\x0ek\xcd\ C[P\x01(\x7fR\x22\xfc\x19\xd95\x04\x85\xbf\xf4\ \xd1\x03\xf4x\xf42LB\xb9H\xc8\xdb\x04\xbbI\xc8\ W\xb9NDI\xe1\x0a\x82\x00a\x18b<\x1e\x831\ fT\x00\xe4\xf1\xe7\xaf2\xfc\xa3?\x1bf\xd3\x98\x1b\ C4A\xe5^\xaa{\xc8\xf9\xf68\x87\x10\x84\xd9t\ \x06\xc6\x80\xcb\xcb\x0b0\xc6!\x84\xbd!P\xf9\x85;\ \xfb\xe0\xb3\x11.78\xb1^\xbec\xcf\xf3\x10\x04\x01\ f\xb3Y\xd2\xb8\x99\xca\x8c\xce{'\xc0\x9f=,k\ \xd6\xd6\x07\x03\xc3\xcf~b\x80\xe1p\x88 \x080\x99\ LpyyY\xd887\x11YW8\xe7\x89R6\ \x1a\x8d\x00\xa0ui\xf9\xc4!\xe1c\x1f\xef\xe1_\xdd\ \x1b\xe1\x1f>\x1a#\x0c\x02\x0c\x87\x97\x08\x82\x19\xc2P\ `\xb1ml\xd6\x0f\xe3\x1c \xc2d:E\x10\xa7e\ :\xed \x0c\xcd\x8ap\xdf\xe7\xf8\xec\x95=\x5c^^\ .\xf6\xdc\x02!VG\x98\xaa\xc7\x9cG\xca\xccl\x16\ 5B\xa3\xd1(\xe9\x90\xe9C\x82\xaa\x85@\x0f\xaf\xaa\ {\xd5\xfblnjG\xd2\x86\xac;\xba[\x19\xfa=\ \xbf\xf1\xf6\x11\xfe\xde\xf7^\xe2\xc7/\xab/\x81^P\ \x01\xc8\xed\xb5\x97\x81\x18\xc0(~i\xc6\xa1'\x96\xbb\ \xef\x17\xde8\x82_a|y\xdd=\x8a\xe7\xcf\x9fc\ 2\x99\xe0\xf4\xf4\x14\x9e\xe7\x15>\xff7^!\xfcE\ \xf8\x04\xcfGa:\xf4\xae\x5c\xb7\x15\x85:\xe3\x8cs\ \xe9\xdd,Vl>\x88\xe2~\xeb\xf6\xed\xc8L[\xf1\ U\xfe\xa5\xcf_\xc5\xf5\xfd\xe6\x98B\xc30\xc4\x07\x1f\ |\x80^\xaf\x87[\xb7n\x95\xdf\x00\xa0s\x12\xe0\xdb\ \xe3g\x185dI\xd8'\xaf\xf5\xf1\xb9w\x8e1\x99\ L\x10\x04\x01\xae\x5c\xb9\x82k\xd7\xaem:Z\x0bq\ qq\x81\x07\x0f\x1e\xe0\x95W^\xc1\xd1\xd1Q+z\ \xff&\xde\xbc\x03|\xfa\xf61\xfe\xde7~\x82\xd1\xfe\ \x0d\xf4\xfa\xbd\xb6\xc9~\xa8\x93\x00\x1f=z\x84\x8b\xcb\ \x0b\xdc\xbau\x1b\x9d\x8eo\xed)\xfe\xf2\x1b\xfb\xf8\xf8\ \x1b\xcd\x1c\xca\x94\x1d\xb2'O\x9e@\x08\x81k\xd7\xae\ \x15Z\x00\xd6\x11\x9fE\x91\x9d\xc9E\xc3\xea\xfb\x0c\xa3\ \xa0\xde\xea\x96\x8d\xb6\xe6Ir\x19\xc3\xf5=\x0f7\x0f\ :\xf0*\xbe\x84u\x8f\xfd\xc8\xe7y\x9eW:\xf6\xd4\ \xe7\xc0\xcd\x83.^N&5\x15\x00V\xeaga\x14\ E\xcc\xf7<\x98\xb6H6qu\xe0\xe1\xa8\xef7j\ \x5cWj\xcees3Tn\x1dv\xf1\x91\xd3~c\ 6\x8a\xf9\xc5\xd7\x0f\x92\xf1r\x99\x8e&\xbd\xe3y\x90\ \xf1\x97ij\xf38\xed\xab\x87]\xfc'\x9f>\xc1\xe5\ \xfe)~\xf7\xcfG\xed\x9a\xff\xa7\x11\xf7\xc3\xe0y\x1c\ \x8cq\xeb\xb0\xdf\x17_=ht\x19\xd4-\x02\xba\xdb\ \xaerc\xdf\xc7\xaf\xbdu\x88\xff\xe3;\xcf+\xdf\xd3\ \x98\x5c>\xe9{\xf8\xd8i\x0f}\xbf\x99\x19)\xcd\xcb\ Ec\xcc*?o\xd9\xc1lsD\x1a\xb2\x10\xd1\x1e\ \xdaBTO\x8b\xc7\x80_}\xeb\xb0qK\x81\xe48\ y\xd5t$\xf75\xa8\x177\x132_D\xf2k;\ 2_\xda\xda\xf3W\x91iy\xf7\xb4\x83\xff\xf8SW\ \xf0\xd1\x1a\xfb\xdd7\x0b\xaaT_^?\xee\xa0\xa1[\ \xae$\xc8\xb2\xb5-elY\x1c\xf5<\xbcw\xbd\xde\ wW\x1a\x93\xd5\xe7\x13\x81\xe7\xe3&M\xceZ\x8c\xd3\ \x81\x8f\xe3~c^/r\xc355\xf4\xac\x90\x80w\ \xaf\xf6\xca=\xb6\x84/\xdfi\xc6j\x80\xb7O\xbb\x99\ \xfd\xd3\xdb\xde[\xdev>q\xb5\x87\xbf\xf6\x99\x13|\ \xbc\xb5u\xa1\xbcl}\xeaZ\x1f\xfd\x06,\xf1\xad\x82\ \xab+y\xceknp\xd5\x98\x9c\xbe\xbe\xef\xe3\xea\xa0\ 9\xe3\xcb\x8br\xd2\xf7p\xe7\xa8\xad\xbd\x85,\xc7}\ \x9e\xd9w\xbd\xed\x9c4`;i\x00\xe8y\xbc1K\ *\x1d\xd5\xf9\xab\x9f\xba\x82\xbf\xf2\xeeq-%\xba-\ \x9cO\xdb5a\xd3\x91\xa5Sss\xb6\xc6(\x00\x7f\ \xf9\x9d#\xfcZ\xc3\xd7\xd0\xd7\xe53\xaf\xf4+\xcfi\ h2\xef]_\xdfG~\xd6\xc1\xa4!\xdb\x02\xb7`\ #E\x87\x85\xcf\x5c\xef\xe3o|\xee\xb4\x15\xbbaV\ \x85\x01\xe84t\xdd\xbf\xa3\x1c\x22\xd4\x9e\x04\xe8r{\ \x85|\xf2j\x0fa\xcb\xc7\xa8z>\x9b{\x97)\x87\ \x1d\x06\xe0\x17\x1b\xbc1\x91\xa3\x9cW\x0f;\xf8\xcd\x96\ l\x89]\x85\x83\x1e\xc7\xcf\xde\x1e\x94{t4\x92\x1f\ \xbd\x98\xe2w\xbf\x7fV\xeb\x9e\xc6(\x00\x82\x80\xed1\ 2GL\x04\xb5~_w\x9f\xa1\xc5\x13\x9f\x9a\xcd\xc1\ \x16YUv\x95\xd7\x8f\xba\xf8\xad\xcf\x9c`\x1bFr\ 8C#\xb6\xf8v\xcc\xc7<\xcb\x00]n\xaf\x90\x81\ \xcf\xf1\xde\xf5vk\xd4_\xbc\xdd\xb4\xd5\x0c\xdb\xc3\xb4\ I\xcb\x11\x1cs\xf3\xdaQ\x07\x7f\xfds\xa7\xf0Z\xae\ \x05\x10\x01\xc2\x95\xc9\xd6\xf2{\xef_\xe2I\xee\xc3V\ \xc54J\x01\xd0\xad\xe5\xa4\xfc\xadR,I\xfb\x99\xdc\ a\xb8Vv\xbc\x08\x1f\xbd\xd2\xc5\xa0\xc5Z\xf5\x1b\xce\ \xfc\xefp\x94\x12}\x1e\xfb\x0az\x0d]\xc6\xec\xd8n\ \x9e\x8c\x02\xfc\xb3\x1f_\xb4w\x15\x80J\x91\xb0.\xfa\ \x15\x85\xa3\xba\x99\x9eQt<\xef\x0f\x00\xde\xbc\xd2E\ \xb7\xa5=\x83\xfd.G?\x1e\xdf\x5c\xf4]\xac\xf2g\ \x8a\x9f-\xce\x8dA+\x12U\xca\x9d\xee\xcfv\xae_\ +R\x8a\x81\xfa\xef\xab\xe8\x99\xbb\xcc\xebG]\xfc\xe6\ \xa7OZo\x09p\xb4\x8f\x7f\xf0\x833\x04sXo\ \x1a\xa9\x00l\x1bW\x1a\xb2\xec\xac.\xaf\x1e\xf8\xb8}\ \xd8ie\x03\xdf\xf88+R\xb4\xaa0-\x13\xfc6\ %\xc1\xf2\xd8L\x98e\xfe\xab(\x11U\x14\xb0\xb6\xfd\ \xea\xa6\xe3\xceQ\x07\xbf\xf3\xd9\x93\xd6n\x18h*\x0f\ \x8b*|E\xf7\x96)\xa5Ea9\x22\xberw\x88\ \x7f\xf1\xfe|\xdfmp\x0a\xc0\x0a\x91\x85\xf5\x97\xdeh\ \xe7lo\xe6z2\x0eG-\x08\xd1\x9c\x80\xff\xfcs\ \xa7\x9b\x8e\xca\xc2\xd4Q\xf8\xaa*Q\xfa\xbd\xb6\xe7\xd8\ \x9eQv}W~\x92\x8b\xa9\xc0\xdf\xff\xdeK\xccK\ \xb3\x15\x00[\xaa\x8b\xd4@\x93\x7f\xfdz\x950\xca\xdc\ \x8b\x9e\xa1\xf9o\xeb\xee\xae\xbf\xf8Z;\x15\x17\x87c\ \xd3\xdc9\xea\xe0\x93\xd7\xda\xbac\xa0\xa3\xc9\xc8n\xd9\ \xd7\xef\x0f\xf1\xdf\x7f\xe5\x11\x1e\xd7\x9c\xf8\xa7\xd2L\x05\ \xc0&\x5c\xab\xa8\xa0&\xffuU\xc8\xb2{M\x8a\x80\ \xc5?\x11\xf0\xd6\x95\x0en5\xe8+zU8\xecq\ \x9c\xca\xa1\x8bM\xab\xbbU\xd4\xe1\xaa\xd7\x9bN\x1b\xe2\ \xe8(Df\xe1\x7f\xf4\xc9+-\xde6\xd8\xd1\x04\x98\ \xe1\xf7r\x12\xe2w\x7fp\x86\xbf\xf9GO\xf1\xfe\xd9\ b\xdffo\x97Tj)}\x9f\xe3\xe6a\x07\xf7/\ \xdb\xf3\xad\x83\xf7\xae\xf7\xb1\xdf\xe5\xd6O\x86\xb6\x8a\x86\ \xa6\x81\xd4\x03\x93\x82\xba\x06V\xb1Q%S\xfe\xda\x82\ \xaf]\xae\x18\xec\xefE}\x08)n\xba\x7f\x9b\x9bz\ \xaf)\xc2\xa6\x8eE\xc9{\x93^\xfe\xea\xa7\xae\xe0\x7f\ \xfc\xe6S<\xbchO\xdd\xdf4U\x8b\xa4*\x14\xdb\ \x0c\xd3\xfe\xaa\x0cg\x02\xd3x\xe7\xd2\x1f\xbd\x98\xe2\x8f\ \xee\x8f\xf0'\x8fF\xb5g\xfb\xdbh\x8c\x02\xb0\xa1\xf6\ \xaf2U;\x92L\xf1\xa7\xba\xfd\xc2k\xfb\xf8\xd6\x83\ \xd1*\xa2\xb6\x12\x1a\xb2[\xaec\xc5\xac\x22\x9b\xcb\xea\ \x0a\x83]\xf1\xb0*\x06u\x87\xec\xe6u+z\xben\ \xf9+\x81\x10\xa5\xf3W\xdf<\xc4\xdf\xfd\xd3\x17\x08\xdd\ \x1a\xfbJ|\xed\xde\x10\xa3Y^\xc0%\xe5\x8a\x08\x8f\ \x1e]B\x08\x81\x1b\xa3\xfd\xe4\xa3@\xc6\xecU\x1cI\ ;\x22\xed&cQ(\xb8\x9e\xf7C\xc5\xfe,\x8eB\ \x08\x80\x01\x9c\xf1\x9c\xff\x7f\xfa\xe3\x0b\x5c\xc4\xc2~\x9e\ Y\xfee4F\x01\xd8\x16lY\xd4\xa6\xddB\x07>\ \xc3\x97\xe2\x0d\x80\x9a\xdcd\x99,\xfde\x14u$w\ \x0d\xc6\x80\x7f\xf8\x833\xfc\xc5\xcb\xe9R\xc3=;;\ \xc3\xfd\x07Op\xf3f\x07\xc7G\xf9\xb0?q\xb5\x87\ 7\x8e\xbb\xb9|x\xf7j\xaf\xd0\x22\xd1Fk\x14\x11\ \xf0\xb1\xd3.\xbet{\x80?\xfcp\xb8\xe9\xe8Tg\ \x03\xefZ\xe6\xfd\xff\xfb\xc3\xb3\xe4\x93\xdd\x19\x9dK\x0a\ L\x22\x0e;\xfe\xe2\xc5\x0c\xf7\ .\x16\x1b\xb3\xdd\x05N\x07\x1e\x9e\x0c\xddW\x09\xd7A\ c\x14\x80\xca\x10\xe5\xed\x87&\xb7\x86\xd1\xe5\x0cG\xbd\ v\x08\xd5\xf7n\x0c2\x1ap\x93\xd0\x1b\xddy\x04f\ \x13\xd3\xb5)\xfa\x0d2M=\xbc\x08\xf0P9\xff\xf3\ \xe7\xa9\xf5\xe0S\xaf\xf4q\xdc\xe3x\xed\xb0\x83wN\ {\xe8z,\xd9\x7f_U\x04\x16\x19\x0d\xa8zO\xd9\ H\x80~\x9d\x08\xd8\xebp\xfc{o\x1f\xe2\x7f\xf9\xd7\ \xcfJ\x9e\xbcYV9\x0c+\x95.\x9br\xd5\x9c\x92\ \xb8;4S\x01(k\xa1M\xd7W\xdd\xaaS,j\ \x88\xcc\xcfb,\xef\xae)%\xaf\x1du\xe1\xdf\x1f5\ ~,\xf0\xa3'\x1dx\x9cE\xfb\x82\xd7Q\xacd\xfa\ \xe5=-P\xcc\x9a\xc4:{\xffm\xe3\xbb\x8fS\xcb\ \xd9~\x87\xe1\xb37\x06\xb8\xbe\xe7\xe3\xf37\x07FE\ \xa0i\x08\x02^;\xec\xe0\x97\xdf\xd8\xc7\xef\xfdd\xbe\ M[\xda\xce*\x95\x0b\xc7|4\xb2Kj2\x85V\ \x9d\x7f\xb3\xb1\xc2eSJ\x14\x85\xe1\xbd\xeb\xfd\xc6\xcf\ \x05\xe8\xf9\x0c=/5\xc3f\xd2P\xf6\xd3\xef)\xba\ \xbfN\xd8\xba_\xf59@\xda\xcd\xca}L\xc2\xe0\xd7\ \x91\xa1\x8do\xe5rF\xf8\xca\x87C\xfc\x83\x1f\x9c\xe1\ o}\xe3)\xbe\xfdh\x0cB\xf45\xbbe\xec]e\ jk\xaa\xb6?E0\x06\xfc\xca\x1b\x07\xd8\xeb4\xbc\ \x11p\xec\x0c\x8dQ\x00\x22\x81\x9f\xafZ\xaa\x22`:\ 6\x8d\x9d\xda\xae\xd5\xf9\x01\xf9Jo\xbbfOO\xd6\ \xef$\x14\xd8\xeb4{[\xe0=\x9f\xe3\xdd\xab\xbd\xdc\ \xec\xd9\xaa\xe9\xad\xda8R\x1d\x81l\x12\xec\xaab`\ \xba\xa6+\x0e&\xbf\x1b&\x89\xce\ >\xd1\xe0m\x82\xeb(M\xb66\xc2\xd1|\x9a\xa3\x00\ \x90R\x90J\x94\xc9y\xfc\x98jcU\xc5\x944\xff\ U\xac\x86\xb6\xca\x0f\x00M5\x00|\xfc\xb4\x87W\x0f\ ;\xc9*\x05[c'\x0c\xe7*\xa6\x86R\xbfV\xa5\ Q\xb5\xf9\xaf\x13\x8e)NM\xa1\xee;\xb2\xbd\xd7\xa2\ k\xa6\xe7\xed\x0a_\xf9p\x88\xbf\xf9GO\xf0\xfe\xd9\ \xb4Q\xbdm\x99\x0f\xbf\xf8\xfa\xfeR&-.\x13\xbd\ \x8cTUj\xca\xeae\x9d\xfb\x1c\xeb\xa31\xa2h\x93\ \x19\xef\xadi\xa9\x9a\x14\x94\xbf\xd4\xd0I@\x81\x22\xf8\ \x8b\x04\x8d\x89:\x15\xbfn\x03Q\xe8\xa6E\xaaLP\ \x22\xeb\xbdU\x98\xe2oj\xb0\xd5\xe3*\xca\xd163\ \x0a\x08\x7f\xe7O^\xe0\x83\xb3Y2\x1c \x99\xe7\x1d\ \xd8\x94\xcb\xba\x84\x82pc\xdf\xc7'\xae\xf5\xe7\xb8{\ \x85\xac\xb1`\xb4\xbd>n\x03\x8dQ\x00$\xcb\x16 \ E\xe1\x02@H\x84\x7f\xfa\xe3\x0b\x8cCQ\xe9\xf9E\ a\xd9\x1aY\xfd\xbc\x89\x0b\x01<\xce\xf0\xb3\xaf\xed\xad\ \xe5YD\x91\xd2\xd5\xd1\x1a\xe4\x9c?\xcb\xbdFw\xe4\ \xf3\xbd\xa8<4\x01u\xc8J*3e\x16\xa4U\xd5\ \x8fmf\x16\x12\xfe\xd7?~\x86\x99 \xf8\x9c%\x16\ ,`9m\xca<\xe1\x10\xa2\x95\x0a_~\xbd\xf9\x9f\ \xdc\xb6\xd5\xb7\x95BA+\ W\xba\xc0\xa2^\xae\xcfX\xba\x1c\xb2,\x83-\xad.\ g\x1c\x8c10p\xc5=m\xbdl\xcaGcHt\ MJ\xf3Cq\x9bW\x11\xd3)\xb2T-\xef\x8d\xa4\ \xe6,\xcey\x9c\x96\x06\x99\xb84\xfe\xeew_`\x12\ \x08tx\x5c\x08\xd5\xf2%\xff\x12\xc0\x18\x07\xc0\xe2\xbf\ \xf9\xeb\x8b\xfe\xe4~%\xbft\xe7`\xc5C\x90Q\x1a\ 8c\xe0\x05\xf9\x92T\xb5*\xe9,\xb8\x9e954\ \xd8\xb2\x9aJ\x8b\x97>\xf2\x98\x8f\xbdr\xcc\xa2\xb4D\ \x7f\x9b[\xc6\xda@3\x14\x00RL\x9f\xf9K\x95\xcb\ \x9f\xed\x1e\x93;\x80\x9c\xb2\xe9qdz\x04\x99\x9b\x19\ \x03\xa04\xd0Z\xa1\xad\xf3\x9b\x86\x84\x81\xcf\x0d\x13\x01\ S_u\x1b\xf9r\xd2{\xd2\x8a\x13%\xe6\xed\x93.\ <\xc6\x10\xcaJ\xa9\xc4\xc4\xa4P-\xf2\xebz\x1c\xf7\ /f\xf8\xf1\xd9\x14\xc7=OK\xb5\xe1G\xe6\xe3\x94\ \xec\xc6\xef\xfa\x86Q\x90\xe5\xcaP\xb66MR\xfeH\ &!\xb2?I+X\x14w-\xd6\xa6\xc2\xaf\x87\x8b\ \xd82By\xa5'\xd9*x\xa5o\x83E\x0a\x8d\x12\ \xa3\xa6\xbd\xfd\xa7\xa3\x10_\xbd;\x02g\xb2\xb6)e\ ^ygL\xfe\xc7\xe2\xf7FXJ\x0fY\xfdMB\ \xc2[W\xba\xb8u\xb8\x8ayA\xd9z\x0f\xa5\xde\xdb\ \xf2\xc5X\xf7L\xbf\xa2\xebZ\xbd\xd3\xdd\x81|\xfbk\ \x88r\x1a\x1f\xdd\xb3\xf6\xbd\x07\x93\x92\x11\xdd[P\xee\ (\xfdS\xa9t.R\x84\xb5\x874\xa56,\xb5\xc4\ \xe5\x12Eq\x06X3>\xc4\xc3\xfb\x97\x18\xce\xc4\xca;m\x03\x9f\ \xe3\xc90\xc0\x07\x1f<\xc5\xe9t\x80\xbb\x87\x17\x18\x05\ \xf5\x8d\xf2\x9e\xe7a6\x9b\xe1\xe2\xf2\x12\x93\xc9\x04\x8c\ ?\x80\x10\xa2\xb4\x97?\xf09\xee]\xccp\xf7\xeef\ \xbf\xcb\xce\x00\xdc\xbd1Fp\xe0cF\x0c\x93\xc9\x04\ \xc3\xd1\x08`\x0c\xb3 D\x18\x06+\x8fC\xdf\xe7\xb8\ {\xf79\xee>\x9f.!\xb4\xa8\xb2x\xdc\xc3p8\ \xc4x4\xc2\x93'O1\x1cF\xf5&\xaepKx\ \xce\xf2\xf8\xdf\xef\x02\xfe\xe5\x09\xde<\xeeb\x1c\xa4e\ \x9f\x04\xc0=\x0e\xc6\x80\x8b\x8bK\x8cGc<\xb8\xff\ \x00\xbd^\x1f\xa1\x08\xa2v\x01X^r\x08\xe8\xf9\x1c\ \xfc\xfc\x1cw\xef\x0e\x97\x14h\x1a8\xe7\x1cD\x84\xf3\ \xf3sLg3|\x8a'\xa3P\xbb\x1e\x95\x1f\ \xce\x19\x04\x11\x86\x97C\x10\x08O\x9e>\x05g\x1c\xa1\ \x10\x89R@\xf29L{.C\xf6\x1c\x0c\x94\x8b\x87\ \xeaWK\x13\x93\xcb\x96\xf3\xee\x9a\x83\xf5Z\xae\xf3\x02\ \xc4rF\x1f6[O]Y\xf9Tt\xa6\xabj\xfa\ 5\x00RO\x13P\xcc\xeb\xaad\x95/\x9e\x08\xc4\xd4\ {\x12\xb5\x00j!1?\x0bIf3b F`\ \x14\xf5\x84}/2\x89_\x06\x00\x8f\xcd\xfc\x0c\x0c\x8c\ E\xe11Fq\x1c\xe2a\x00pp/+\xe8\xa3g\ P\x12\x03\xa9\x9aH\xab\xae\xecU\xc8r\x15\x02\xf8\xe9\ \xdb\xfb\xf8\x97w\xc7x>\x09d\x922\xf1-\xa6\x9e\ \x06@\x04x\x9c\x83\x81\x81\xc7fO\xc6\x18:\x9e\x07\ \xc6=p\xee\xc1\xaba\x83\xcc*>\xd5\xfdy\x1e\xc7\ \xb7\x1e\x0d\xe1y\x1c\x1e\xe7\xf0<\x0f\x5cT{.c\ Q\xe3\xccXdf\xe6\xdc\x03\xe7,1\x9f{\x9e\x07\ \x12T\xf8\xf2<\x8f\xc3\xf3\x04\xc0\xd7\xee\x8f\ \x97\x1a.!\x1a*\x8b\x14\x01\x0f\x9c\x85\xe0\xdc\x03c\ Q\xdeg\xe2\xc0=%\x9d\xd2&\x95b*\x8ay_\ \xeaE\x96\xbf?i\xbeSA\xcb\xe2\xa6\x9b\xc7\xc3,\ \x9csx\x5c\xe90%\x9aY\x9c/\x84\xc4\x82\xc9\xe3\ \xba/\xef\x8d\x82\xcc\x0b\xe0\xbc\xe0f\x8a\x15\xc1\xe0G\ Q\x16\xd4\x16\x9e)\xee:\x94\xbb7O6n\xd5\xda\ \xd0U\xb2T\x05 \x97\xee8\x81R\x09\xd0\x1b\xb3\xf4\ ]rx\x8cGcT\x9c\x83S\xb6G\xc8X4Y\ G\x1d\xbb\x12D\xb9\xe7\x15\x8e\x07Y.\x1dt8\x0e\ \x0e'8\x12=\xbcD\x17\xd4;\xc0\xf5\x03\x8e\x99\xa1\ W>\x1a\x8dprr\x1aO\x07P\x0c\x9cD\xd6g\ \xdb\x1aq\x9fE{\x10\xdc\xb8\xe1\xa3;\x0er\xf1_\ \xa5\xfe7\x9bE=\xbe[7o\xe2\x8d+]\xfc\xca\ \xa7O1\x0a\x04\x8eW\xf8L z\x17\xfb]\x8e\xe9\ \xfd.n\xde<\xc2\xed\x9b\x03\xdc\xbcy\x84\xe1l\xbe\ iyB\x08L\xa7S\xf4z=\x5c\xbf~\xa3\xd2=\ {\x1d\x0eq>\xc3\xcd\x9b\xdd\xb9\x9e\xb9,\x18\x80[\ \xb7\xae\xe2\xe6\xbe\x8f\xe1L`6\x9da<\x1e\xe3\xca\ \xf1\x15\x5c\xbdv\x15\x00\x14\x0bT|\x0f\xcb\x97'\xf5\ \x9aJ\x15\xe5a\xe0s\xdc|\xdc\xc3eo\x19\x16\x80\ \x94\xcb\xcbK\xccf3\x5c\xbdz\x15\x07\x07\x87K\x0d\ {\xd9L\x00\x5c\xf6N\xf0\xd1\x93.\x863\x91\xdb\x9a\ \xf7\xf9\xf3.\x820\xc4\x8d\x1b7\xd0\xedv\xacj\xb7\ jT\xd7\xdd\xa4\xbb\x9e\x1d\xaa\x9b\xcf\x19\x0e\x02\xc2\x17\ \xce\xf7\xf0\xe1\xd9l\xae\xb4\x94\xc1\x18\xc7\xc5\xc59n\ \xdc\xb8\x91\x13\xfe@d\x01\xb8u\xf3*z\x1e\xcb\xec\ \x0a\xaa\xa6\xcd\x94\x06X\xdc\xeb\xb6a<~\xf9\xaf\x5c\ g\xe0\xc30\x13>\xa0\x0c\x1d \xaa\xfb\xa1\x108=\ 9M\xfc\x90\xc1\x9f\xb4B\xab}52\xf8\x05\xb2C\ ?\x04-\x1c-<5Nz\x99\xb0\x0de\xeb\x0f$\ DuT\x08\xd9\xd1d\x86\x1b\xec,CwX\xa9j\ ^'\x82\xb1\xd1\x1d\xfax\x5c\x94\x11QH\x82(\xf9\ A\xf7\xa3]\x17\x14\xcd\x0dO~\xfa\xb5x|T\x95\ \xf3\x1f\x9cM\xf1|\x1c\xa2\xeb\xb1\x9c\xdf0\x14\xd1\xb1\ \x10\xc9\xb3H\x86\xa3\x9c\xe7V1\x00\xc6\x89u\x01E\ \x0d\xf0\xcf\xbe\xba\xde\xcf\x03\x13\x89x\xb8%\x8ak\x10\ \xc6\x85P\x89\xb3\xfeK\xef5\x1f\x17?/=\xf6=\ \xe0\xe5D$\xca\x95q\xe4\xa3\x06B\xa4y\xd2v\x02\ \x11\x22\x0cE2\x11\xd34N\xaa\xba\x99\xf2\xc6T\xee\ \x8a~\xabB\xc4\xe5K\xac\xf2!K\xe4\xf7\xde\xbf\x00\ Q$\x84\xf3mJ4\xac$\xeb\xbd\x0dU\xa8\xe8n\ d8\xd7\xdd\xa6a\xb4?\xc8[\xc7\xabSL\x85\x08\ \xe3|)\xae/\x04\xfb\x84\xeay\x7fu\xc2\xaa\x02\x91\ \x00\x95\xe4\x89\xa3\x9c\xe6\xecF\x13\xabMj\xe3d\xd2\ \xaam(V\x22%\xcc\x02\xbf\x91\xd2\x95\xf3r>\xcd\ \x17\xaa(N\x94\xfc\xb5\x05/\xcfM\x9ao.*\x14\ m\x88\xd3]\xf3\x97\x81\xe42E\xa9X}\xf1v\xaa\ \x80\xd8\xdesU%\xc0\x96_\xd2\xdf\x9e\xc7\xf1\x9dG\ C<\xba\xcc\x8eo\xeb\x8a\x80\x1eN\xb6\x07\x22\x87~\ \xa4\xa0\x89\x95\x00\xaa\xd6\xe3\xa8\xd3\xc8\xac\x1aR\xe6\xb0\ $\xe5\xab1\xb1\x9b\x9f(]+\xd62\x96\xc8\xfb/\ g\xf8\xde\xb3\x09>q\xb5\x87\xe1,\x1d\xc6\x03\x00\x11\ \x12\x84 \x84B\xac<9\x04\xa0\xeb\xb1hC\xae\xa5\ ?K\xce\xab*\xce\x179\xb1Y\x8f\x97\xe9\xd8\xe6\xc7\ \xe6V\x96\xa4\xea\x9d\x0aYW\xe2\x9b\xdcJ\x80\xb9i\ \xcc\xe0\x9cI\x03\xac\xa2)\xa6\x9a:J\xf7\xf8\xce\x04\ \x0c\xe4\x04:\x00\xfc\xfe\xfb\x97\xd1\x18\xbe\xa6\x8cP\xfc\ \x1f\xe9\xd7\x0c\xbf\xb2\x9e\x97\xfcMB\x81;\x87\x1d\x9c\ \x0e\xd6\xaf\x87\xc9:\xf3\xca\xc0\xbc\xfd/\xa0\xbd3\xcd\ \xcdv\xad\xec\x9e*}u[9\xd0\x9f+\x15\x81\xa2\ <\xcf\xfd\x1a$\x97d\x99JW\xc0\xa4V)uS\ \xa1\xfd\x88\xec\x16\x1b\xd3}\xeb\xb6\x00\x00\xeb\x9a\xc2\ \xb4<\xbe\xf5p\x04 \xaf\x8cR2p\xad\x0c\xf9\xad\ (\x0e3A\xf8\xe9\x9b\x03\xf4;\xabj\x96\xab\xe5\x8a\ \xde\xc6\xad\xebgoA\x16I\x8d\xa3\x88\xc6X\x00d\ \xa1\x03R!Q\x96\xc1\xb6\xa2\x22\xdd\xf5\xb1+\xd2\xce\ \x13\xffJ@r\x0cP\x906\xd6\x0a\xe4\x04\x91\x1a\xe6\ <\x8c\x02\xc2\xf5}\x1f\x07\x1d\x86g\xa3\x05\x02\x9a\x93\ k{>\x06\x1d\x8e\x89\xa1\xbb1\xaf\x12`\x833\xe0\ r*\xf0\xd5\xbb\xf9\x84\xd6z\x87J\xe6%e\x86\xea\ \x85\xd1\x10\xf9\x1f+\x8b\xc5\xb1\x99\xf7\xfd\xeb\x0a\x94\xa3\ \x98\xa7\xc3\x10\xcfF!\x0e\xba\x1c\xb3P\xa4\xca%\xa9\ \xfbHH\xdf\xa9\x15\xcaFb\x91\xa4\xfc<\x0e\xd5=\ sL\xd1\xe4`\xb1\xe8\xd8\xd8\x02$rxYa\xad\ \xf4\x06\xc7\xa24\xc6\x02 \x1bq\xd9c\xa9\xd2\x93V\ \xfd\x00y75,\xfd'\xb4{%w\xcf\xa7\xf8\x93\ \xc7c\x1cvy\xfe\x990?\xdb\xe8\xaf\xc2\x8f1\x06\ A\xc0\xc9\x06f\xa1\xd9;\x00\x00 \x00IDAT\ ,\x00\x00p\xe7\xa8\x83\xab\x03\x0f\xa3@T\x8e\xf3\xbc\ ?A\x91ys\x12\xa66\x80tM\xfa|\xbf\xa2{\ a\xf9\x9b\x98\xa7\x1b@.\xde5\xcb\xcf\xa2? _\ \xfew\x95'\xc3\x00\x0f.\x03t\xbd\xe5|\x9c*\xb1\ \xbe \xbb_\x88\xee.e\xbd\xa0\xe8\xdb\x00\xfb>\xc3\ \xcf\xdc\xde\xdc\xb7\x01\xd4r\xb1p\x8f\xbe\xe6\x8f\xd0\x9c\ ]:w\x85\xc6X\x00\x04\xa4P\xae\xb8c\x9b6~\ O\x94wC\xec&o\xc84\xfc\x84ty\xa1\xc2$\ \x00&\x81\x80\x17\xaf7\x95333\x13\x0a\xf3\x81k\ P\xfcD\xf3h6S\xbd\x11\xe1\xf37\x07\xf8\xe3\x87\ \xeb5\x01\xf8\x9c\xe1c\xa7=LCJ\x86<$\xab\ 0\xad\xf5;\x0c\xdf~4\xc6$0\xe4\xad)\xbb\x95\ y\x1a\xaa\x9f\xc4I\x15\x96\x05A\xda\xfe6\x01]\xd8\ gv\x9et\xac\x9d\xef<\x1a\xe3\x9d\xd3h\x12^\x92\ \x07\xaaPS\xdc\xe6\xa9$\xaa\xc5P-\xd6\xd2-\xa4\ \xe8\xb3\xdc\x9b\xfa.@\xda\x91\xda\x8c\x8a\xec\xca\xfd\xfa\ i\x8c\x02\x10A\x10T\xfc\x8dx\xc5\xab}MJ\x8c\ *\xd8\x8cE\x9a([\xb1c~\xf0l\x8aO\xbe\xd2\ \x8f\x84\xbf*9\xf4\xeeS\xb1\xfc\x87\xbaS\x01\xd3\xce\ \xa5\xdb(\x04\xae\xf4<\xdc:\xe8\xe0\xc1\xe5\xea7\x7f\ \x91\x84D\xb8}\xe0#\x10\xe9\x06\xb1Z\xf4\x91q\xa8\ \xb0\xce\x87)J\x96\xbay\x08\x11\xe0\xf3h\x03\xa0i\ \xc1p\x83\xd11\xa3\xb3\x91\x96\xa7\xe9\xdf\x8a:c&\ \xfb\x9a\x00\xc9\xff\xf4r\x06\x94\xaf#+\x0b\xd8\x0d\x92\ \xd6\xe2G/&\x98\x04\xd9\xddEL\x94U\xff\xb2\xfb\ \xf4c\x95iH\xb8u\xe0\xe3\xb0\xc7q>Y\x7f\x7f\ XUJ\x81|\x11\xd4\xdd\x96\xf1< ;L\xe2X\ \x1f\x8d\x19\x02\xc8\x98\xe3\xab\x98\x98P|]\x0dC\x86\ \xaf?'\xf2\x96/u\xdfy@fj\xd7\x96\x92V\xad\xfc\xe9\x8a\x87c=\ 4\xc6\x02 \x0b\xde\xa2&P\xd3R4]\x09P\x8f\ M:v\xd7\xe38\x9b\x08\x5c\xe9q\x84qX\xea\xcc\ ji\x82.1\x00d\xe2DZ\xdcT7A@\xcf\ c\xe0l\xf1\xb5\xf1U\xf9\xec+}\x5c\xe9\xfbx1\ \xc9?P\xdfp&yo\xda9\xc1\xbe\x02G\xbd\xbf\ \xcb\x81\xc7\xc3\x10\xff\xe6\xc9$\xebG\xfb[\x97\x8c\xb2\ g\x0a\xd8t\xae\xfb\xdd rKj\xa9\xd4\xc8&\xb0\ \xeaG\x8b\x8cV\xad\xac\xc9)\x7f\x0d\xd9\xfck\xca|\ \x88&\x10\x8a\xe8\x8b\xa0Q=\x8c\xb6\xb0U;\x13\x99\ \xb2\xb3\xa2\xd7\xc6X\xb4\x1a\xe0\xb0\xcb\xf1`5\x8f(\ FQ \x97\x10T\x06\xd3\x10H\xc6\xbf\xa1\x9dv\xac\ \x96\xe6X\x00\xa0\xf6n\x0a~H\xe7\x0b\xe4&\xda\x94\ \xddK\xe6\xfbt\xce'\x02\xdf|0\xc2a7\xed\x09\ ,\xa2\x09\x0b\xe5\xafz,\xc3\xb8\x98\x09|\xee\xc6\x00\ \x9d\xd5~\x0e,\x811 \xca\xec\xf6\xa5b\xb2\x96\ \x98\xceU\xb7\x5c/S\xbd\x86h\xc8\xc1\xd3\xb7YC\ 6\xdf\xab\xfc\xf4em\xc9\xf2\xcf\xcaa4\xa7u\x89\ \xca_\x14\x9fy?,\x95\xfb\x91\xf6W\xbf\xa6\xba\x93\ \x13\xff:?|>\xc1\xd9$\x84\xcf\xa2\xe1,\xb9\xd9\ \x17\x90*Li\xbd\xa6\xdc\xcf\xe6^\xf9G\x04\x0f\xc0\ \x97^\xdd\xdfH\xfa\xd5r\x22\x13ZdE\xd2\xaf\x17\ \x15\xceL\x98\x06/\x8e\xf5\xd3 \x0b@\xda(E\x93\ \xef\xcc\xfeL\x1d\x1b\xa2b\xed\x92\x0cn\xd1\x05\xb9\xd4\ '\x7f\xc9ci%g\xb1\xe0\xc8}a\xadP\x98d\ \xfb\xfd\xe9\x8a\xf5\xfczb)\x08\xd6\xb5\xfc\xe7\xea\xc0\ \xc7\xa7\xaf\xf5q>\x0d\x01\x96~\x91oUt9\xc3\ \xd7\xef\x8dr\x1f=\xca(\x0b\xb1\x9b\x9e\x8f\xd6\xbc\x9b\ \x13\xa9<6\x02EX\x03\xf6\x95)+|\xbcC\xe3\ '/g\x18\x05\x84\xc3.\x83\xdc0/\xa9\x9fJ\xc6\ \xe8\xaaS:\xbf\x84rVHS9.*\xd7\x9b,\ \xa3\xa9\x02I\xda\x87rR\x18\x18\xd4\xed\xd2\xd4\xfd\xed\ \xa3\x05\x94\xe6\x0f\x04\xd9>\x1a\x94\xb4\x83\xae@\xae\x9d\ \xe6(\x00R\xc8\xc2.\x94\xab~<\xc1\xe4EuS\ \x16\x06X{\x84\xdf|8\xc2\xe7n\x0cp\xd8\x8d\xd6\ \xc9\xebV\x87\x22\xf4\xedi\xe4V\xbb\xcc\xf0<\xc6\x80\ Y@8\xeey\xf8\xa9\x9b\x03|\xed\xde\xeaW\x03L\ \x02\x82\xcf\x19B\x010\x9em\xb0\x96m\x83\x10\x88\xe6\ \x00\x84\xb6\x8c#\xb9\x1d\xb3\xece1\xed8=\xd3\xdf\ \xacn\xf5\xa9\xc2:\x05l\x19\xa6\x9e\xba\xd0\xae\x03\xd5\ \xf6\xc3\x98'\xdf\x1a\xf2\x1a\x1a\x85\xcf\x19\x9e\x8fC\x5c\ \xe9\xf1\xd4\x14n\xe8\xa2\xaaC\x5c\xd0.\xe7:(%\ \xee:\x0c\xc0x\x8e/d.\x8b$\xb9\xb6*\x1b_\ HvKDvW\x04aMq^q\xca\x5c3\xac\ \xcar\xac\x96\xe6(\x00\xd0z@JW\xb0\xa8\x813\ \x8d\xf9\xdb\xd0\xfd\xaa\xbd/\x9d\xb3\x89R\x8c\xb5^\xaa\ ~K\xc9b\x84\xa4\xa7\x97\xfc\xd5\xae\x09D\x9ff\x1d\ \xaci[\xe0\xcf^\xef#\xb3\xc0Ay\xc1\xcb\xaa\x80\ 2\xfb\x06>\xc7\x8f_Nq\xf7<\xff\x81\x13)\xf0\ D\xa6AI\x9b\x08\xb59\xa0\xf8<37\x01\x99i\ \x805b\xd6\x0c\xa4\xd2\xa2Nr\x84A\x99\xa9\x922\ \xa3\xbe\x5c\xa207E\x11j\x12\x81 |\xf3\xc1\x08\ \xef^\xed\xe1r\x16f\xcd\xd4Z{\xb4\xaa\xf7w\x19\ \x10\xde<\xee\xe2\xb5\xa3\xce\xca>\x0cd#\x19\x8a2\ \xa4\xcd4'\xa8h>\x90\x0c\xa7\xeaN\xbd\x06=\xcb\ \xb1b\x9a3\x07@1\x83\x0a\xf5/TA\x91\x1e\x93\ \xe6\xae_\xd3g\xef\xc2\xe0.\x85\xaf\x09\xce\x80\x1f>\ \x9b\xc0\xe3\xda\x18\xb3z\x1c\x07d\x1d\x07W\x1at=\ .I\xba\xe3\xbf\xe7S\x81[\x07\x1d\xecuV/\xa0\ ^?\xea\xc0c\x0cB1q.T\xf3\x0c\xf7J\xa7\ .\x8f\xe6T\x9cY\x964\xe9='\xd3\xb9\xaex\xe9\ \x8d\xb2q\xbc\xdb\xf2K6\x87j\x02\x86\xb2\x11\x9d\xe7\ \xff\xa5c\xcc\xe6\x7f0\x1cG\x1f\xaa\xca_\x93?7\ \x07\xc0\x8c\xcfY\xfc\xd1\x1cS\xdeD\xe8n\xa6\x1f\xb4\ c\xd3\xb9\x89I p\xd4\xe3xeo\xfd\xfd\xb3\xc2\ \x1e\xbaVw*\xcd\x07B\xf1v\xd4\x99\xb9=N\x05\ X;\x0d\xb2\x00PR\x08r_\x11\x8be\x22S*\ \x1b\xcb^\x8a\xc3\xc8^#\xc5\x8fj\xa4J\xdc\xe3\xd9\ \xbe\xa6\x22'\x08\xf8\xc1\xd3\x09~\xf9\xf5}\xbc\x9c\x04\ \xd9\x0a\x1d\xdf\xc3c\x93\x95j\xd6\xcf|&8\x97F\ ;\x97\xb3\x10o\x1cw\xd0\xf79\x863\xf3r\xb9e\ \xf0\xe6q\x17\xaf\xeeup>\x0dq\x84\xb4\x92\x02f\ \xc1X4n\xa9\xbe_S\xe2\x18\xa2\xa5U\x8f\x87\xf6\ \xfd\x0dd\x03\xa0O^\xb7\x8d\xff\x13\xa2r O\xa4\ \x12\x90{\xbei2A\xfc\xa7)\xbb\x8d\x19\x95\x13\x14\ \x97\x13\xdb5]\xc8T\xb9\xd6\x94\xf7\xd04:<\xfa\ 4\xadH\x94$E\x91J^\xa02T\x95\xcb\x14\xb9\ \xeb\x87~,\xcf\x93;s\xf7D#\xea\x91\x02b\xda\ 3c\xd5\xc8\xfa\x94)3\xf1\xc9\x22\xdf\xdc)KI\ R\x8f\x1dk\xa51\x0a@4\x8eK b\x19\x13\x13\ \x80L\xe3\x0ddM\x9b\x04\xe4\xf7\xddV\xc2-\xda\xd4\ #\x9a\xe5k/\xd5\x84\xe8\xf3\xb5^\xbce\xaf\x9c\x08\ $\xcd&\xa6\xcf\x9dR,\xcdr\xa1\x92\xf10\x13\xcf\ @D\xcb\xf3~\xef\xfdKk\x9c\x16\x85(\x1an\xb8\ \x88\x95\x0cu\x86\xb3\x11&\xe7dD\xbb\x22\x92r\x9c\ \x84i{\x16\xa2\xa5U\xdf\xb2\xecr\x98\xae\xdb\xcf\xf6\ \x98L\x7f\xf5p\x81\xbcu\xc8\xe8I9Vg\x174\ \x81D\xf8\x1bzD*\xb5\xe7h\xe8\x85\xde\xb44\xb0\ 9#!\x8d\xe3\xcf\x9eO\xf1\xe3\x97S\x5c\x1d\xf8\xd9\ ^\xaa\xf4\x90\xd1BM\xe4\x0b_\x9a\x87\xb697Z\ \x89g\x0c\xa3\xd9fT4u\xa2s\xa6CU\xa9\xda\ X\xbb\x08\x05n\xa9\x93S\x02\xd6Kc\x14\x00 \xdb\ \x0b*\xf4GZ\x91R\x1bx\xb2\x17\xbb\xa4 \xab\x16\ \x05\xca\xf6\xe0U~\xf4b\x8a\x1f>\x9f\xe0\xe3W{\ 9\xf3\x7f\x82\xa9\x1cWHC.M\x88V\x1e\x9c\x0c\ \xbc\x9awV\x871\xe0\x9d\xd3.\x86\xe3\xa8a\x11 \ \xf0\x12I\x90\xf9\xfc\xb1\xe5\xd8\x86\xc7\x18\xa6\x82\xd0-\ X\xde\x18\x0d\xf7\xd8\xc3\xb2\xc92\x19\x07\xb9!N\xb4\ n\xdbL\x92\xf7\x8c%\xfe\x1b\x01\xa5\xe5u\x9e\x1e\xbc\ \x0d\xa6\xd5\x81$\xbd\x94m\xcc\x8d\x96\x13\x07.\xa6\x02\ \xcf\xc7!\xae\xef\xf9\x19\x0b\x8d\xa4\xb2\x22\xa6\xddSv\ \xac2\x0e\x04\xde\xbd\xd6\xc3O\xcef\xb9\xd53\xabB\ \xb6o\xba%\xaa\xec\xe9Y\xfd\xd2\xd4\xd3\xc9\xae\xea\x8a\ \xcac\xac\x18\xa9\x9d7\xb9*k\xee\x148\xea\xd2\x18\ \x05 \xfd$\xaa\xb2\xd9\x8e\x82,`E\x93\xfe\xca\xdc\ H\xbf\x99\x95\x176\xce\x94\x1e\x80\xda\x13PzT\xb9\ \xc6\xa0D\x93\xd57\xda\x91\x8c\x03\x81\xc3\xae\x87\xa3\x15\ m\x03J\x04\xdc9\xea\xe2\xd9\x88\x92y\x0d\xd2\x8c\xbe\ \x8a\x0e\xe1^\x97\xe3\x1b\x0fFx6\xb2\x0fi\x94\x09\ !\xfd\x92\x80\xbdGR\xd6'#\x11[\x98\x0a\xfc\xad\ \x13\xb9\xee[\xc4=\xaed\x9c\xdf`\x95\xa9\x93?U\ \x95\x89\xc6,\x87l ~l\xf5\xb3Yf\x0a\xeb\xb7\ r\xacwF\xaa\xd6\xb5q@x\xeb\xb8\x0b\xce\xa2/\ \x04\xae\x8b\xaaB_\xf5/\xd3\xa4\xb6Xzz\xc9\xd2\ \xced\xdei\xfc\xf7r\xea\x06\xa7\xd6Ec\x14\x00)\ \xf8ech\x13\xe6U\x1bB}\xdc_\xef\x96\xb3\xf8\ \xff\xb2F\xf0\xeb\xf7F\xb8s\x94~ D\x95W\xc9\ 2\x18\xdd$n\x0bS\x1f\xa3\xd0\xfc]\xce\x04\xee\x1c\ \xf9\xb8\xb1\xef\xe3|2-\x8e\xd8\x1c\x1c\xf7\xa2\xc1\x8b\ Pd\x95\x1aCT\x16FZ48\xec\x82&\xb1\xa8\ \xa8n\x84\xdc\x90\x8e\xe9>\xf5~\xa9\xcc\xe4\x1a\x1d\x18\ \xe6\x88\xd0\xf2\xd3:/2>\x89%\xc0 hT\xbf\ \xd6\x89\x11\xaa\xa7\x1a\x9aBS\xdeC\x13\x91+rH\ \xfbU\xa1\xb4#R!\x0c\xc6\x80\xe1\x06\x96\x02Fs\ \xa2X\xa6\x13V\xa5X\x15)\x9a\x99\xfa\x1a\x1f\x9b\xc2\ \x96\xfb\xa0\xbcu\xd2\xc3\xf9$L<\xe4:\x01D\xe8\ \x8c:\x10B\xe0\xc6a'\x19\x9aL\x9e\xa7\xb5i\xfa\ 9@\x067s[\x14\xfb\xb6\x86\xad\xba\xa5\xa1\x9b\xae\ EV\x90\x90\x80\xf7_.\xbfm\x9f\x97\xe6(\x00$\ g.3\xeb\xe4$\xdbP\xa6^\xa82\xe1\x1a\xdc\x93\ {\xa8\xfc\xe3C/'!|\xce\x10\xc8^\x1a\x01\x5c\ \xf6\xd0\xb4\x9c6\x09\x9e\xfc\x5c\x00\xcaT\x08=^\xa3\ \x80\xe0/2\xdb\xa6\x80w\xaf\xf6\xf0\xca\xbe\x8f\x0f\x03\ \x11\x7f\x8a8k\x02P?\xe0\x93\x8dW\xean\xda\xe4\ \xc3\xb4\xc1\x87\xc7\x80\x17\x93\x10\xdf{\x9a\xdd\xfeWG\ \xae\xf8\xc8\xe4-e\x8f\xad\xf7\xea\x82S\xb9f{\xc7\ \x89\xd0m\x02JcRI\xd0(\x89\xb2\x96\xfb\x1ai\ \xab#\xd4v\x8d\x7f\xfdh\x84_\xdd;H\x86\x08\xd5\ \x1d\x01\x17\xa5\xc8\x8a\x99Z\xb7\xd8f\xca)\x99\xe7\x05\ \xad\xa2\x83 \x11\x9a\xe3_~\xfb0\xd3\xa1\xca\xcc\x12\ \x8e\xff[\xafu\xa01\x0a\x804\xe3\xca1Q\ \xf5\xd3\xb2@\xbewj:\xcf7\x88\xa4|\xd2W\xdd\ `F\xce\x02,o\ \xc7sJw\x9d3\x16:\xca\x0a\x7f\xd5=\x03\xcb\xfc\ \xc9y\x95Ba\x99\xecu\x18\xde\xbd\xd6\xc3\xc5L\xa4\ \xca\x89\x148H\xe3\x5cYW\xb1I\x9e\xd8\xbd\xef1\ |\xed\xc9\xb8T\x91\xb3-\xc3,\x12l\xf2Z\xd2X\ i~M\xf7&f\xc6\x82p\xd7M2|\x81t\x1f\ \xf82e\xa6\xach\x15\xa1\xd7)'\xff\xed\xf4}\x96\ )_z\xb9\x91\xf5S\xdf\x1c\x87\x99\xba\x94\x06\xe4\x88\ $\x8b\xfd%m\x97R7\x03\x02f\xeb\x5c\x0a('\ \xc8*\xcaN\xe6\xb2\xe1\xdc\x96T\xab\x90\xd4\x86\xf7L\ ePm[\xf5\xba\x90Z\x8a\xd3\xfab\x8b\x9f\x0d\x8b\ \xfc\xcf8Tm\x93H\xbb\x16\x8b\x9a\x9c\xa2\xae\xfay\ 6\x0a\x92k~l\x89\xfd\xf9W\xf7\xf1\xf9\x9b\xfb\xf8\ \xc6\xfd!\xfe\xaf?}Q1%\x8b\xd3\x18\x05 \x11\ \xfe`q\xc3\x98\xbej\x8el/\x110\xf5V\xa3*\ \x94qeQ\x81I\xcc\xf1\xb2\xc0\xc5\xaa\x9a\xfe\x1c\x1b\ ?x:\xc1M\x16\xc0\xe3\xf2\xc9d\x15\x98\xb9\x02m\ \x12\xf6IO\x22/n\xc7\x81\xc0\xb5=\x1f\x1f9\xe9\ \xe2G\xcf\x97\xa7\x0d\xce\x04\xa1\xe71\x04B$\x854\ \x12\xc0Y\x7f\x04\x18f\xec\x1a\x14\x1e\xdbk\x8b\x15\xa4\ \xae\xc70\x13%3\xee\xa5\x02R\xa1\xb1\xc9\x5cS\x15\ \x18\x98\xc3\xb06H\x96\xe7m\x82d\xf7?\xa4y\xa1\ 6\x22\x99),\x9a\x93~\x8c\xacwc\xcf+g\xb5\ i\xd0\xbbh\x1a\x89r\x9afQn\xfc\x97\x19\xdcT\ a\xae\xfb\xd5\xc3\xcf\xdc\xa7\x1dOC\x81k\x03\x0f\x9f\ \xbc\xd6\xc3\x9f>)\x1eF[&\xd1DT\x96\xd4+\ \xa0xN\x8em\x9e\x8e\x09\x19f:w\xcab,)\ \xab\xcb\x94\xfd\x99\x9eS\x16\x8f\xb2\x1bLa\xe4\x9av\ \xe5\xbdd\x94\x1c(i\xd5\xfc\xa4\xbb\x98F\x04\x14}\ \x03\xe6\xfe\xe5\x0c\x83\x8e\x87_~\xe3\x00>g\xf8;\ \x7f\xf2\xbc$\x15\xcb\xa1A\x0a@:3]\x1f\x0d\xa9\ 2:\xc2\x0c\xc7\x89V\x8dle\xcdLp\xb1h\xbb\ *O\x86A&n\x9c\xb2a\x9b\x22\x93\xc4'~V\ \xd9\xbc\x06y\x1cP\xf4i\xe0\x1b{\xfeR\x15\x80\xb7\ \xaf\xf4\xe0s\x86q\x98\x0a\x82t\xe9\x5cV\x5c\x18+\ U\x0dA\xd1\xe5\x0c\xf7/\x02\xe3\xf6\xbf\xa6p\xd5\x86\ @Go \xd4\xd8\xaa\xa6Y5~EQm\x94\x05\ \x00\xe9\x1c\x08\xdd*\x93x\xd0\x0e\xad\x8a\x8d\xe5\x5cw\ \xd7\xdfcS\xdeE\x13\x89\x1aqJ\xcaW\xd2Y\x88\ \x0b`\x91\x90\xa8\x9a/6\xe4'\xc2\xaf\xed\xf9\x00\xd6\ \xa7\x00\xd8\x14\x9fL{\xa9aZ\xb5U\xf6\x0c\xfd=\ \xd9\x14!\xe3\xfd\x8a\xf0/z\xb6I`\x93R\x11\xd4\ N\x9cYa\xce\xa3\xcb\x13\x81|\x1b\xae*O9e\ \xc6T\xa7cEa\x12\x10\xee\x9e\xcf\xf0s\xaf\xed\xe3\ b&\xf0\xff|\xef\xa5%e\xcb\xa39\x0a\x00d\x86\ R\xa6\x87\x0a\x98\x85\xbb\xbc\xc7\xd4#\x12\xd0Lq\xb0\ d\xa6\xc5\x04\xa5\xc39\xc3\xdd\xf3)^\x1d\xb0L\x03\ \x9d\xdc\xaa\x95\x9c\xcc\xdc\x82t\x04\xc2\x10\x01\xb3\xf3\xcb\ I\x88\xb7\xaet\xf1\xed\xc7\xe3\xa5-\x89y\xed\xa8\x83\ \xae\xc7p9\xa5\xf4\xc3D\xa8\x96\xfe\xba\xf8\x1e\xc3\x93\ Q\x80\xa7\x05\xcb\xff\x80\xb4!0i\xd0\xaa\x9f\xec_\ 9<$\xef\x93K\xe7\x90-\x0c\x96\xc0\xd2\xedq7\ O:\xe4\x95\xbe\x83$-\xaa?\x14\xf7\xfcQ\xf1\x1c\ @\xa6\xe1ss\x00\x0aP\xf3\x84\xe6W\x1cu\xc5\xb6\ \xcc2\xa0\x12\x100\x09\xd7;9,)\x1b\xba\xb5\xa8\ \xec\xbe\xca\x8eY\xe4\x98~\xae1f\xd9\xb1\x7f\xe9W\ \x06\xab\xfe\xca\xe2\xa5+/j{\x9cQ<\x0c\xf5\xce\ \x14\x9e~\xcd\xf4\x01/S\xf8\xb6\xb0\xa4\x12#\xe3\xf9\ h\x18\xe0g_\xdd\xc3\xd7\xee\x0e\xf1a\x85N\xd4\x22\ 4F\x01P\xbf\xb4'\x1b\xa6\x8c@G63\xf3=\ \xc6xvz\x91\xc0U\x88\xc2b\xd61h\x95\x99 \ \xfc\xf9\xb3)>\xf6f\x0f!Q\xb2\x0a 1\xef'\ \xb59.\xa0\x99\xc5\xeaJ\xc4\xe3\xbfI\x1a4%G\ \x1e\x87\x22\xfa\x82\xdetI\x95\xff\xda\x9e\x87[\x07>\ \xce\xa7\x22\xed1\xc7q[\x8a\x0c\xd0T`!\x08/\ \xab\xecc@\x84\xd0\xf2\xfem\x8d\xa6>\xc4\x9a3\x9b\ k\xf7\xe76l[V\x9a\x97@\x12\xe7$\x0d\xca\x84\ \xc0LW#\xf6\xab\x1e\xcb\xf3\xba\xcf,Q\x8a\x1d)\ \x99\xf2\xa5\x97\x9b\x8a/\xaf\x8a\x92f\xeb\xd4lb\xd3\ *u^\xd0J\x9f\x03\xd9Q\xa2\xf8\xb9\xca\x0e\xab\x00\ \x98t\xcf\xc4-\xf5+\x15gA\x14\xed\xd5\x12{6\ \xf5\xe2\xcb\x84\xb0.\xb4\xd5\xabU\xde\x83\xc9\x8f>y\ \x11P\x94\x1dyl\xb9\x7f\x12\x08t=\x0f\xbf\xf9\xd9\ \x13\xfc\x0f_y\x8c`\x85\x1bv4F\x01\x90\x0d\xa0\ \x5c\x83\x0a\xd83\xd3h.\xd6&\xe3X\xfdA\x19\xb3\ \xa2h\x19`\xd5\xf8]\xce\x04\x0e\x90\xdf\xf0\x22\x156\ \xca\xfe\xdf\xb20J\xa1\xaf\xe4vz\x98\xc6.\xdb\xb6\ 0\xf4|\xe0\xe3\xa7}|\xe7\xf1\xb8R\xfc\x0a\xe3N\ \xc0~\xd7\xc3\xd9$L*\x0fcr\xb9%i\xad\x90\ M\xf4\xc2\xee\xae\xbe\xc3X\x9b\xaf\x1co*\xcf3\x9b\ >\xa5\xae\x1a\xb1\x95\x19\xa1\xb9U\xd9ir]H\x81\ \xaf~j:rG\x9a-EBg\xc1\x844E\x11\ j\x22\x1ec\xe8\xc6\x9f\xb1N\x97\x01\xca\xabY\xb1]\ \xd6\xcbW\xfd\x98\xac[\x0c\xd9\x0ep\xd2>l\xa0\xac\ \x1a\x95\x9d\x02\xac\xc3\xa0\x15H\xeaf\x1c@\x88\xf4\xfd\ \xe8u>\x13G\xca\xc6Q}o\xc6\xb8\x10\x8c\x9b\xc0\ %\xe7\xcc~I\x0b&\xc1\x94\x8fjpr/\x9b\x8c\ ?\xe5\xa5\xaa{\xdd\xa4~\x13\xe9\x81\xb3I\x88\xab}\ \x0f?\x7fg\x1f\xbf\xff\x93\x0bS\xaa\x96Bs\x14\x80\ \xb8\xb0'_\xeb\xa3h\xdddr\x1d\xf9\xe3L\xe1\xd3\ \xde\xb6\xa9`\x9a\xc6\xb1\xaa*W?|6\xc1G\x8f\ \x80\xcf^\xe3\x98\xc9\xf8!-tr\x9c_\xb7P\xc8\ F\xdc\x14\x17]\xf7P5\xff\x0e\xe78]\xd2\xb6\xc0\ \xaf\x1fw1\x0dD\xf2~\x05\x01LD\x93OX\xf2\ =H\xd3\x8b \xe3\xf8\x96\x9cK\xae\xcc\x1a\xc8\xdc%\ \x04*\xede\x90\xce\xae6+B\xd9\x98(\x07L\xf9\ \xc6\x1d\xc9\x0aD\x05\xa9Hc\x9f\xec\x80\xd8\x002&\ f\xa5Q\xab\xdb\xf0\xeb\x0d\x8d\x15\xddR\xb3\x81\x1ef\ [x9\x0d\xf1\xc1\xf9\x14=\x8fg\x97'\xc7\xc8!\ F{y3\x9fg\xae)\x9d\x162d\xa2\xb0J\xb4\ \xd5!\xe7:\xe8\xf3rLCP\xf2\x9c\x0a\xae\xeb\xa4\ \x13\xb1\xd3\xe7e\x9eo9V\xcfI;6\xfa7\xdc\ l\xbdnP\xbcM\xa8\xefB(\xc7\x12}>\x00P\ \xdc\xd6\xc8K\x91\xc5#\xeb.\x7fo\x1cu\xec\x01,\ \x81\x06)\x00\xd2\xfcI\x08\x05\xc5_\xea\x93\xd7\x90\x99\ ij\xda\x8c&m\xe6\xa3,\xc8\x0b\x5cC\xb1d&\ \x9f\x96\xf8!\xda\xdcFm\x9c\x85\x96i\xbay:\x13\ 3\x93rb)\xfcrB\xc8^\x87\xa3\xe73L\x82\ jq\xb4\xf1\xfaQ'\x114\x99\xc9=j\x1a(\x8d\ \x9b!jY\x85F\xf9\xab\xb3\xd7a\xf8\xd1\x8b)\x1e\ \x16|\x010\x81\xca\x85\x10A\xb5\xd8\xa8\x8ey\xa5\xb1\ 0+\x95\x1a\xd6\x14\x99'\x95\x18y$\x976\xa9\xe3\ \xaf\xe5q\x95\xe5]\x1b30\xf9S_\xd2\xa66\x9a\ i\x09\x97S\x81\x0f\xcff\xf8h/\xdb '(B\ \xa3\x8a\x02f|\xd5E\x9a\x02\xa2\x5c]\xf7\xf60&\ e'\x8a\x0b\xd2!(M\xda\xabmJf\xa3SJ\ \xdd\xe4yr\xab\xc8\xaf\xdf/\x14\xe0\xea\xa5\xb8\xcd\x90\ KgM\xef\x9e\x94\x03}\xc9x*\xc8\x0b\xdc\x0d\xcf\ \x97\xf55\xbb\x09\x9a~=\x9b^\x10L\xd3\x1b2\xf7\ \x9a\x94? \xca\x8b\x17\x93\xd5n\x04\xdd\x1c\x05\x00J\ O(v\xb0U8\x06\xca7s6\xa9\xaa\x04\xa0\xfb\ \x8f>\x06T\xbd!\xfc\xee\xe31>\xf9\x862\x89\x8e\ X\xd2\x13P\x15\x16\xc6(W\xf8\xa5\x9f\xa2\x18F\xd1\ \x8a\xe6%\x5c\xce\x08w\x0e;\xb8\xd2\xf3\xf00\xa8 \ L-\xf4\xfch\xdc)\x10\xe9\xcc^\xf5\xfdV\x99\xf8\ \xa2\xbb'\xc7,\x7f\xbf\x17\x0f-T\xf9\x80\x89\x8cG\ Y#g\xcc\x1fR,\x08T\xc1\x92\x13_\x97Jf\ \x13\x90\xf1&\xc3\xcfJ\xae[F\xf1a\x91\x0dD\xbd\ \x8e\xa4\xd9\xab:\xfc\xb5\xabt8C \x14%Sy\ \xb5\xea\xbb\xcc)\x07\x06t\xa59\x9b\x17f\x8f\xa5J\ \xed\x92!\xed\xa7_S\x8713\x17\xd4S\xc3;\xca\ \xb8Y\x8e\x0b\xe3eh\xa3d\xdbe\xb2\x96\xe5\xfa\x0b\ \x86\x07Ia\x0e\xe4\x87_\x92\x9a\x92S`\xc8x_\ F\xe0\x1b\xdaD\xdb\xb9t\x96J\x8c\xbe'\xed\xcbI\ \x88O\x5c\xed\xe3\xeb\x07C\xdc\xbf\x98_\x06\x14\xd1\x1c\ \x05\x80\xe4\x8ch\x96+D9\xb3\x0a\xcc\x1awA\xdf\ \xc7\xa8,pVoL\xf8\xd9H\xc0\xe7\x0c\xc3 2\ \xff'\xe5\x84\xf4\xb1\x1e\xf3\xfd&\xf7\xbc\x89\x9d\x92\xe3\ IH\xe0\x0bn\x0b\xfc\xc6Q\x07\xd7\xf7;8\x9b\xc8\ \xcf\xff\xca\x8d\x8cbEF\x89\x94iU\x84M{\x95\ \xe9Q+\x00c\x0c\x973\xc2_\xbc\xa8\xbel)L\ \x04rU#b\xfe\xf9u\xc6,\xd5\xb1\xf6M#\xad\ ^\xeaF3R\xd8\xd8oJ\x0fm_\x9d\xd4\xcb\xbb\ \xa9\xfe\x00\xe6\x15\x07\x8e,\x14K\x9a\xcc0S\x5c\x7f\ \x80\xeamG*;\xb3\xb9\x91\xd6v\xd9\x98\xa4\xbd\x84\ M\xe4\x8d\xdc\x8e\xdd$XMJ\x8b\xad\xb6\x9a\xdc\x8d\ \xc9\xd1\xab\xbd\xa1)0\xc5#Q\xca`o\xf7u}\ %o/\x8e\x8f\x0dJ\x0b*\x5c\xd7\xe7 H\x0f\x99\ 8\x91=~j8\xf2\x1e5\xe9\x93\x90p}\xcf\xc7\ ~\xd7\x03\xb0\xed\x0a@\xfc\x93\xb3;m\x99\x953Q\ +\x0er\xce@\xa6\xf7m)\xa1\x0c\x91 \x08\xa5\x9d\ \xc6\x1a\xab\xf4\x01\xe3P\xe0\xe10\xc0\xf1\xa0\x83i\x18\ We\xad\x1005NZ\xe4\xf5\x82\xa8\x17\x8c\xdcd\ 7\x02>q\xad\x87\xfb\x17\xf3/\x05\x09IV\xea\xf8\ \x19\xc9\xa4\xa6\xc8\xd2\xc04\x0d\xd6d\xb6S\xd15x\ \xc6\xa21\x7f\xc6be\x82\x03\xf7\xce\xab\x17\xd6tS\ %\x93\x882\xf9\x8f\xe3\x17\xa7E\x08\x91\xdb\x11\xac\xf0\ y\x0d\xea\xf5F\xbd\xca\xd82#-45\x1a\xfe\xa2\ R\xab\x9f\xab\x8a\xdcj>5\x91\xad+\xedV,\xa2\ \xb4\xc8\xad\x9aC%o\x80Xa\x95\xb6nS\xebn\ \x1a\x8dI^\x0d\x19\xda#s\xd9\xaf\xb2B\xa9jZ\ \xa2\xa3r\xa5E6\x87EO\xd6\x95\x96\xd4'3\xf8\ +\x8f\x1e)\xc7\xf2\xafn\xd0U\xcb\xae\xa0\xc8\xc2(\ \xeb\x8c\xfe,\x9b\xe2\xa2\xb6\xd1\xbar\xa0\xc7^\x8fS\ \x91\xa2\x91\xb99NOf^\xb4\xeeW\xa9*R\x91\ QW@\xc8\xe0d'p\x95\x9f\x83^\xa9\x02P\xa6\ \xf9\xa8$\xbd!R\x85B\xbe\xc7\xc9\x12\xb7|\xe8\xb9\ ]\xeddA\xd2*\xa1\xdas\xb2\x7fE^\xb9\x01\x00\ \xe7\x1e\xce'3<\x1a\x86\xb8~\xd0\xc5$H{\x04\ r}\xaaZh\xd5\xf5\xeaZ\xac\xe2\xfcO\xaf\xc9\xc6\ Y\x1d_\x92\xed\x0b\xcf\xdd_\x1d\xc6\x80\x8f\x5c\xe9a\ 4K\xab3\xe7\x1e\x18\xf7\xc0Xt,\x15\x8d\x5c,\ \x0dn\xa6\x9e\xa5:\x87\xc0\xf3\x18\xce'!\xbc\x8a\x02\ F6\xaa\xf3\x94o\x02\xe0yqZ\xb8\x97\xd9\x9a\xd5\ d\xc5\x904j\x15\x00!\x1e\x82\x12\xe0\xbe\x07p\x06\ \xc6y\xad!\x0a\x93`7\x8e7*\x0di\xa2\xb8-\ U\x19J\xc3\xf2|\x1f\x9csp\xbeH\xe9\xdd$J\ \xbd\xf7|\x80sp\xcfK-3,\xb5R\x1a\xad0\ &\xe9R \xa1\xf2V\xc0\xd8\xdbR\xcaj\xda\xdd\xf0\ =\x0f\x9cs\xf8\x9e}r\xb1\x14H\x89\xf0\xb5EN\ _\xc3\x9c\xdc\xad\x84eHg\xdeW>h@_\xfa\ \x9d^Id\x00gH>\xedM\x15\x14\x9b\xccqZ\ iH\xa9@\x04d*L\xaa\xe8\xc4\xe7,\x1f\x96\xe9\ \x01\xf2\xdde\xf4@]\xef\xa3\xac_\x01\x96\xf1\x0f(\ C\x03+\xec\xb3\xacT\x01(+\xbciY\xa2\xe8\x13\ \xb5\x82@\x9cA\xa8\x9f\x872\x05B\xf9\xf1\x12\x13\xf6\ \xf7\x96fm\x00B\x10\x84\x08\xc30\xe3_\x1eK\x13\ |(B\x90\x10\x18Of\x18\xcf\xba\x98\xcd\x02\xd8T\ \x1c\x93&)3\xb2\xcc\xc4\xae\xba\x073\x86\x03\x1f\xb8\ \xd2\x11x\xa4M\xaa\xabR&\xf6:\x1c\x03\x1eb8\ \x09\x11\x08\x02\xe7\x0cB\x08\x04a\x00\xc6\x18&\xd3)\ 8\xe7\x10\x22kt6N\x98L\xd2CF?\x04\xc2\ \x95\x9e\x87\xef?\x1e\xe2lTm\x08`:c\x18O\ \xa7\x98\xce\xea5sD\x80\xe7q\xccf3\x84\x22D\ \x10\x86\x08\xc2 \xe9M\x17\xc1<`2\x091\x9bm\ \xf6\x93\x9c\x0c\xc0t:\xc3\xd4\x13\x98\x09`2\x99\x22\ \x0c\x09\xb3 \xc0,\x08sy\x02To\x08\xd4a\x99\ \x227\x8f\x18\xa6\xb3)f\xb3em6\xc2\xc09\xc3\ l:\x03\x91\xc0l\x16@\x88\xa8n\xb5\x0d\xc6\x18f\ A\x80)M!\x04a2\x9dE\x8a\xa6XNZ\xca\ :G\x0c\xc0\x04\x1e\xa6\xd3\xe9\xc2eU\xae9\x0f\xe2\ r5\x9dN\xd1\xe9t\x11\x8al\x9b7%\x8e\xe9t\ \x0a\xc1Ya\xaf\xb3(\xeeY\xe3G=\xc9e\x1b2\ P\x8d-Q\xcbO\x08C\x01\x12Q\xdb\x0d\xc6@\xd2\ \x0cY\x00\xe9\x11W5\x92\x9c\xe96{)Q\x88\x94\ [\xf5w\x90m\xf7\x99\xd1\x0f\xe5\xfc\x01\xd2\xec\xc2\x91\ \xfd\x045g\x0c\x973\x81\xc9\x0a\xbf\x07\xb1\xa0\x02@\ \x86\xb3\xac}\x83\x14!\x9e\xf6l4]\x90\x80@\x84\ \x98\x85\x00\x87\x88'\xdePN2fzFRCS\ \xdcH5\xe7+\xcfN\xe3@\x99p\x18\x11\xc6\x1e\xc3\ \xcb\xb33\x9c\x0d\x83lz\xe2\xb0\xe4\xe6\x0d\xe3\xf1\x18\ a\x10\xe2\x0f~\xf8\x00\xc78\x02\x91\x80\x10\xf98%\ \xc9\x93Ze.\xedH\xc6\x0f\xd52\xab\x8e+\xca\xf8\ \x0b\x02N\x07\x1e&/\x86\xb8\xffT[W_\xa1L\ \xbcw\xa3\x8f\xe7\x8f\x86\xb8\x98\x85\x00\x01\xdc\xe3 !\ pq~\x090\xe0\xde\xbd\xfb`\x9cA\x84\x22\xb5\x8e\ hAW\xa9\xc2R\x899\xefzx\xf0`\x84{\x15\ \xf7\x00\xe8\x0d;\xb8\xe7\x1d\xe0|V\xbdQ\x95\xaf\xd1\ \xf3<\x04\xc1\x0c\xe7\x17\x97\xf0\xfdq\xb4y\x14\x11B\ !\x8c\xed\x80\x5c9\xd2\xf78\x9e\x8eB\xdc\xbbw^\ \xf9\x99\xab\x80\x01\xb8\xdb?\xc7p\xcfG@\x1c\xd3\xe9\ \x04\xc3\xd1\x08\x84H\xd8,\x224M\x96g \xdf\xf8\ \xecu8\xee\xdd\xbbXh\x88I\x0d\x9d1\x06\xce9\ F\xe31F\xe31\x9e>}\x8a\xe1\xf02j\xa4[\ \x05\x811\x8e{|\x0f\xdd\x81\xc0h4\xc2\xfd\x07\xf7\ \xd1\xeb\xf6\x10\x86a\xee=\x02vE\xde\x86>\x81\xcc\ \xc4A\x97\xe3\xee\xfd1\xee=\x1c\xcd\x93\x88\x18\x02\x8f\ \xadJ\x17\x97\x97\x08f\x01\x1e\xfa\x14dc\x1f{\xe6q\ \xee\x0a!0\xc3\x0c\xfd\xc1\x00\x07\x07\xfb\x08\xe2!\x80\ lCKz\xf0\x0a\x06\xc7\x82\x5c\x95!s\xce\xf0\xe9\ \xd7\xf6\xf0D\x5c\xd4\xfe2\xd8\xe1Q\x1fW\x8e\xfb`\ \xf1v\xc2Q\xe5\x11\x18M\xa6`\x00\xf6\x0f\x0f\xe1{\ \x1eD\xfc\x81 \xddJak\xe8\x00E\xd7\x89\xcf}\ \xc60\x0c\x04\x1e\x0b\xc2\xf1q\xafR\xfc\x8e\x8e:8\ <\xde\x07*nw\xacj\xe2\xdc\xe3\x08f\x01\xc6\x93\ )\xba~\x07\x07\x07\x87\xb1Y\xdbn\x91!\x00}\x9f\ c\xda\x09p|\xbcY\xf34\x03pt|\x80\xc3\x81\ \x8f\x90\x18\xc6\xb1\xd0\xec\xf5\xfa88<\x04\x91\xd0\xca\ \x87\xa64\x1b\xfbKi}\xb2\x0d\x03\xa8\xc7\xfb\x1d\x86\ \xa3#\x8e\xa1\xb7\xa4\x09F\x0c\xf0\xb8\x07\xdf\xbf\xc0l\ :\xc3\xfe\xfe>\x0e\x0e\x0eZh\x01\x88\x84\xc9\xd1\xd1\ >\xf6:S\xbc\x18\xcdppp\x84~\xbf\x1fY\x0a\ \xb5:\x00\xe4\x05z\xd9\xb5\xec\xb2f\xf5\xc9)\x87]\ \x8e\xe3a\x17\xc7\xe3\xee\xc2i\x01\x22!9f#\x1c\ \x1e\x1e\xa2\xd3\xedD\x8a\xbf\xc2\xc0g8<:B\xd7\ c\xc5\xbb\xcfi\xbd\x04S\x9b\x90M\xa3.\x13\x22O\ \xa6y\x06LiIM2\x833\x0e\x02!\x08C\x08\ A\x18\x0c\xf6\x12\x05G{@6L\x93\xa0\xd0\xe2\x97\ \xbdM\x8bs\xdc8\xcat\xa9J\x89\xea\x9b\xe9\xf7*\ \x8a\x82\x1e*\xc5\x0e\xc9\x9e\x0bL\xbd\xc6\x00\xc6\xe01\ \xbe2\xe1\x0f,y\x08 \xff\x8e\xa3\xdesF\x090\ \xf9g\xb1F\xc5\x01b\xfb\x00\x8c^EI\x1c\xf9*\xbb\x13U\x12%)\ f\xc8R\xe9<\x91`\x90\x14 \xb2\x8cLMSf\ \x00\x804\xdf\xa8\x9e\xb6\x81\x1f\x84V\x00\xcf\xa7\xe5\x06\ \x94,AS\xca$\x1a\xa0V|\x8e\xe1\x07\x86g\xab\ mW\xd3\xd5\xf2<\x19\xae\xe5?5_\xe2\xc2\xce\xe8\ \xa6ZIhB\xeajR\xbe\x0c\x02\x5c?\xf4_\xf0\ |\x1f\xdb\xb2\x86\x0a\x00\x89u\x80\xac\x97\xaa\x9a\xd7\x12\ \x82\xf3\x0dwlSh\xf8\xc9\xf5\x11\xab`\x00\xb5q\ =/\xf1\x01\x88\xcbJn#\xfb\xcd\xe3b\xafGt\ \xb5\x22\xc41\x09\xa4\x04\xd7\xf5\xf0\xbd \xd4l\xb4\xfa\ \xe5\xaa\xab\x124\x85(\x99^c!\xf1\x90d\xc6\xd9\ $\xe1\xf9\xe1\xdc\x7f\xf0\xae\xd3\xfcS\xcc\x94-N\xce\ 9\xec4\x1ax\xbeO\xdf\xf5\xb0\x1d3\xb9\xd4\x89\x7f\ 6P\x8c\xb2yU\xeeZ\xf6W\xc7d\x9d\xbf%\x9e\ \x97\xfad\x149h&\xe6h\x8a\xc7\xb1q!C\xa6\ \x8c\xc1\xd7\xe3<\xa34O\xa7\xdbq\xaa\xe7\x05\x042\ \xc0\x8f|\x9b2}_\xa9'\x90\xdd\x9bE)X\xcf\ \x07\xd9\xdd\x055\xd6\x92\xe4\xcdi\xf1\xa4\xbcN\xff5\ 7({\x1aO]\x0b\xc5\x07`\xa9j\xf3\xfaF\x8f\ \xb3[\xfb\xeb\xab45\xcb\x00M\x9b\x01\xc5\x88;\x81\ %\xd2\xcd\x14$\xa9`\xa0f\xd4MOR\xf1\xa4L\ \xaf\x85\xecA\xddw`\x1clv|v\xfaA\x18G\ @\xe1\xaf\x19\xeb\x91\x22\xa8\x14>B\xbbh\xca\x17\xf8\ \xa0lq\x86\x00\x00 \x00IDAT\x92\x99\xaa\xcd\ R\xd5\x1eK\x0082\xe3\x84K\x1c5\x22\xafn6\ \x13\xc6\x010k\x99\xa6j\x9a6e\x8a\x07r\xc9\xb6\ Xm\xf9c1\x7f\xe2\xef\x9d\x9c\x1bn\x8e\xfd5L\ \xcf\x952\xd9\xdd\xcf\xd4gL\x84(\x90\xa3\xb8\x8f\x1e\ \x0c\x92\xcd\x7f\x88\xde\xaf\xc8\xaem\x86\xacp\x98\xf4'\ \xad\xcf\xe4\xd2\x0a\x8eu\xec[\x94\xb9iy\xc1{\xc0\ L\xc9b\xb9\xeapv#\x0d7]\xbcGIJ\xf4\ C\x06$3V\x99l\xa8\xeb|\x04\xbc\x22\xec\x97\x80\ 6\xa8T=PV\xb1\xd3\xafr\xac\xd0\x5cu\xfa\x10\ \xf2\xe9\x035\xec\x11k+\x951#\xd1\x22\xb2*\x02\ \x7fN\x19,*S\x1bO&\xda\x91\x08,\xda7)\ \xaa\xbbjU0=\xb8\xe8z CKL \xe1k\ \x17\xda\x05\xa5O\x0eS#\x00\xc4\x1f2\x0e\x8a\x921\ sF\xbf&fmZj\x92\xfa\x1a\xa6a7\xb2\x1d\ C\x19\xb2\xbb\x08\x89z\xa9\xe9\xd2\xec\x07\xccWl|\ i\x90\x00\xa2\xde\xa3\x0e`\xa10{\xa9e7A\x1d\ p\xe1\xeeP\x02\xdb\x0aw\x0a\x1c\x05\xa7\xe7\xca\xd8B\ \xd0C\x89W\x10\xd5)\x99s\x92J\xa7\x16\xc5\xf5\x91\ \xda\xaf~,\x044\xfb>\xee.\xa4\xa9X\x13\x1d\x9a\ O\xfb\x8d\xad*\xf1\xfd&\x0b\x8b:\x90ML\xf5z\ #!d2\x8ac\x10\xfd\xa9\x048^#\xac\x13\xa6\ I\xb4g\xdc~\xff\xbd\x04?\x90\xf4\xfc e\xe2J\ ?5\xbd\xb6D\xc1@av\xd15}\xce\x7f\xd4\xf7\ ~=\xbeO<\x96\xd4\xa5\xd8a_\x8b\x04\x01\x9d\xa1\ \x93=O\xf3g\xe9.\x86|\xb9g\x0f\xa8\x97@$\ f\xf70D\xb2\x1c\x1aF<\xd0\x0a\xd5i\x96\xe9\x99\ \x83\x98\xbb\xe9QE\x8f\x1f\xd4W\xe2\xeb\xea;\x8a\x8f\ \xab\xb6\xa0\xeaX\xfc\xa7\xeflqq\x9f\xb7\x02\x86i\ \x12\x00\x22\xc2\x17z\xd6g\x09~\xc6X\xa5P=\x9d\ a\x15\xcd\xb3\x812\x005\xa6\xbc\x9b=\xd1-\x01}\ ?\xaa/\xd9z(\xb2GV\x8a\x1cExQ\x89\x84\ \x92\xde\xf6$'\xe7J\xbc\xb6\xd1\xa31\xc26\xbb\xb6\ \x15\x06\xf9\xf1d\x1c3;\x1a\xc0R\xa4\xcc&\xaa\x80\ T$\x80\xdc\xbb\xd3,\xf2\xb1yM\x97\xe6\xab\xb6\xc5\ \xc5\xa6\xcb\xea(\xf1\xff\x15$\xcco\xac\x9bRj\x1a\ \xd7%\xd0\xde\xb5^\x9ej\xb90Y\x0bT\x94\xe8Q\ \xf7v\x98\xf57\x98\x09v\x98\xf1\xb7\x98\xf56\xa9\xc9\ &\xe5\xa0C%hS\x0d\xdaTd\x9br\xd0\xc1\x09\ \xfaTd+\xe9\xa3\x96\xf4(\x07\xd99\xdb\xbeU!\ \x10\xe1\xfc\xb1/\x1c\xfaT\x90\xc2\xa2\xbc>\x87\xa8\xcc\ \xe2\xda\xb34]\x0b\xef\xd2\x06\xf3GN\xb1\xdc=\x83\ [Z\xc4\xad,\xe3\x95\x17\xf1*G\xf0\xedjNp\ \xd4\x89\xd5HfYEz\x90\xfb\xa7b~W V\ Jb\xc1KM\xcfY\x01d\xf6w\xd0\xf1\xa8\x887\ \xee:h\xc4\xedN\xce\x95\x06\xe7\x18\xfa\x802ri\ :\xbd3\xe4-\xb2\x98f\xa8\x84\x22\x0dK\x19\xedl\ *\xb3\xb9\x13Z\x15\xe5W\xa7\x06\xf4\xba\xc8\xdc\xc1\x10\ f\xaf=k\xd0'J\xc7l\xa4v\xca\xf4<\x88\xee\ \x8d\xfd\xe4\x16*!\x15\xf9\xddW\xb6ys\xf3`\x96\ )O\x91\x00\x10u<\xe2\xce\x97\xf6\xba<\xcb3\x07\ \xd9I\xd9B\xa8\xcef\x82tD\x02\x83i}\xf4\xb8\ \x08$\xbc\xb1\xd9\xe3H}&$\xa2Q\xe7\x8a\xfd\x11\ b\xa1e\x904\xc9\x18u\x11\x02\xbc1V\x00\x1c\xa9\ \xdb\x1c\x9buh\xb9)g\x8c\xefN\x82|`\xde\xd1\ J\x85n\xf2,\x92\xe6\xfd!\x92\xf8 $S\x12q\ \x99\x03\xea\xa4\x7f\xcb\xb4\x9f\xc8\x0c\x91\xd2\xeb\x97\x99\x17\ t\xbb\xd4\x9b\xe7\xb9\xb3\xf36\x8b\xde*\x8b\xeeU\x16\ \xbdk,x\xd7X\xf0W\xa9\xfa\xad\xdd5d\x00\xca\ A\x0fHc#$nK\xeee\x88V#V:\x1d\ \xda\xe7\xcf\xb1\xd4X\xe2Hc%W\x86\xef\xcc\xd2\xaf\ \x1e\xa6_=J\xafv\x9c~\xed\x18\xfd\xfa\x09\xba\xd5\ \x93t\xeb'\xc1r\x86\xf2\xf2\xe4uE\xbf\xd3\x14\x14\ i\xda\x902\x7f\x99\xf4Qu\xe3\x19\xa9\xfd\x8eh\xd5\ O\x91q\xd40\xd9\xc5\xd55F\x07\x87$\xde}\xc1\ X\xcf\xe5\x8f~5\xe3g\xee\xd8t\xdfH\x8c\xb7`\ \xca@\xfd\xcbl\xa3\xad\xd5Wj\xe7\xc6g\x18\xf2\x14\ \xe5K\x04\x0a\x06\xf7\x81\xb8\xedi\x1e\x99\xdc\x1b\xe6\x95\ I\xbe\x99\xb2\x8dD\xf2\xe6f\x9fg\xaetx{\xe7\ \xe0b\x94L\x8d\x00\x103\xfex\xbe-|\x81\x86O\ \x10\x8d\x9b\xcc\xe2\x08m\xce=\xf9B\xd1a\x92E\xd5\ h#\x01a/s\xc2\x96\x88\x89B\xecS\x90>+\ f\xae\xa6\xe5\x1fE\xd2\xb4\x9eE\xa5\x11\x8e#\xb8e\ \xa1\xcc\x0b\xd7\x86{\x04\xc7\xd3\x04i\x88\xde,\xd3\x8f\ \x1d+\xe3\x0ei\xf2\x91Q1\xf0\xfdD\xc2\xc9\x9b\x9b\ \xa3\xc7\xffO\xcaU\x84\xbe\xc2g\xa6\xf2\x5c\xae\x1e\xf1\ \xbd\x89\x95C\xc9`{Mj\xadw\xa85\xdf\xa1\xd6\ >G\xad\xf56\xb5\xd6y\xca\xdd\xab\x00<\x98L\ \x9cOO(Re\x93k*G*\xfe\x12\xa3F\xd5\ \x9c\x04bf\x1a\xfba\xe5\x1e\xad\x0b-\x19_\x814\ M\xaa\x16\xba\xf8V\x86\xf7\xb7\xf8z\xd5I%v}\ \xea$~l\xd9\x16\x04BPqD\xee\x01\xc9&m\ \xc4\xe4#\xae\x8fD]f\xa8W\xa8\x90\xe1gN\xa4\ \x96n\xfe@zY\xf1'\xcf)}\xc0\xd9\xcd.\xcf\ \xaf\xf6x{\x0c\x1f\xafIaj\x04\x00\xd5\xd1&e\ \x9e!2\xef,J\x0c\xb44]2\xd7Ct\x0a\xf5\ \xa2R\xa6\xbe\x9ccT\xac\xb6=.7]\x96\xaav\ 8\x1d\x10\x95\x193\xff\xa4\xce\xc2\xd0\x0a\xbdb\x0a\x93\ K:\xb1\x22PH\x192\xf5\x85\x8a\x85c14H\ \xc7M\xf3\xa5$T\xb1:W\x17\x9e\xcbh\x90\xc6\xef\ ;\xee\xd0\xa6.\xabWX\xa0\x7f\x15)%\xd5\x92E\ \x7f\x17\xd1\xaaB\x82\x93\xb7\x1e\xe4\x88\x85\x22\xdce\xa4\ \xee\x88XY\xee\x0e\xf3\xebOQo\xbe\xcel\xe3u\ fv^\xa3\xd2\xb9\xcc\xaa\x940_\xb6\xc3\xf5\xff\xea\xb3\x0dN4\xc9\ 2\x14\xfd\x85\x8f\x01\x19\x95b\x0b\x187\xe8\xab \xe0\ X\xeb\x05N\xbd\xf25\x16V\xbfJ\xb9\xb71~\x05\ \xf6\x01\xbeph\xd9\xf3\xb4\xec%Z\xf6\x22mk\x9e\ \xa6\xbd@\xcb^\xa4g\xd5\x93\xbf\xbe\xa8\xd2\xb7j\xf4\ E\x8d\xbeU\xc5'\xdd\xab\xa1k\xa5\xf1\xefm\x0e\xbe\xc2,\xdb\xd6\x1c\ \x10\xbe\xc7\xcd\xf9:^\xc5\xc6\xf5%\x9d\xf9\x0e\xe7\xfd\ \x07i.-\xd1^Y\xc9|~\xcb\xefR\xe9]\xa3\ \xdc_\xa7\xda\xbdB\xad}\x91Z\xfb\x02\xd5\xce\x05\xaa\ \x9d\x8bX\xc1d7\xf31\xc1\x22\xe0\x96\xee\x0b\xdc\xd2\ }\x81\x1f\x11\xbf\xce\x1b\xb5\x07yq\xe6\xc3\xbc2\xf3\ \x18>\xbb\xdf$g\x1aQs\x04\xf5\x92\x85\x1b\xc4+\ ib\x8b\x9aL\xcc\xd5Y\xf3\xb5\xae\xc1\xa6N\x82\x83\ F\x86\xc9:\x10\x0b\x14B\xc0F\xc73\x9b\xe9\xf6\x11\ 2C\x84\xd4\x0b\xe6\xb6\x98\xac\x14\xba\xdb\x82$?=\ kl\xd5\x8dU)\x07\x8e\xe9\x11\x00P\x97\x83\xc5\x1a\ l4\x97\xae\x8b\xc7\x09\x8a8W\xac\xd5\x16\x88\xe7j\ \xce=\xf6\xb9\x0b\x0d\x97\xa33N\x14\x13 }N\xbc\ \x22!a\xe6\x05U\xd55\x06\xb5\xba&\xf4\x03\xb0\xad\ \xfc \x0381W\xa2b\x8b\xd0\x1a\x01\x99\x8d\x92\x06\ \x09K\xc3\xe6\xf2L\xf5\x0d\x08\xeb1J0\x99\x05o\ \x8d\xfb[_\xe6\xbd\xcd/\xb3\xec^\x1c\xf1I{G\ \xafz\x98\xd6\xecm\xb4\xea\xb7\xd0\xa9\x9f\xa2]\xbf\x05\ o\xee&6\xbc2\xdf\xbcx}\xb4j\x15q\xdf\xd0\ 5.\x9d\xa8\xfav\x95v\xfd&\xda\xf5\x9bre\x08\ \x19P\xe9]\xa3\xd6\xbeH\xbd\xf5\x16\xb3\xcd\xd7\x99i\ \xbeI\xad}\x01!\xf7\xc7\x88lI\x9f;\xda\xdf\xe6\ \x8e\xf6\xb7\xe9l\xcc\xf2\xfc\xecGyj\xf6\x93\xac\x97\ \xbe;V\x14\xac\xcc8,\xd7m\xb6\xbbA\xe6\xfb\x84\ \xdfK\x1f,\xea\xe02\xb1\xf4b\x18\x15\x9b\xe86\xc7\ \xb28\xbf\xe3\xb2\xcb\xc55\xbbF\x18\xf8ho\xfbe\ \x18\xa7\x16u\x0b\x87!O\xea\xa4|C\x108(L\ \x8f\x00\x10[\x00(\x8e@\xa7+\xb4R\xd3\xd5\xf2L\ 1=\xc9X\x14D^R\xdf-Z\xd1V\xb6\xea:\ \xe1dO0\x859\xaa2\x8c,\xe2\xc4\x06\xe8V\x90\ \xae\x17pl\xc6\xe1\xec\x96\x1bn\xf6\x13_\x17a\xe0\ \x1f?H\x97\xbcd\x9e#\xb2\x8c&1k\x1a\xaa\xa2\ [%\xd4i\x97\x18\x8e%\xd8\xee\x06\xacw\xcc\xc6\x7f\ \x1b\x9f\xdb:\xdf\xe6\xa1\xc6\x7f\xe5L\xfb\x19\xac}\x9e\ \xd1\xecV\x8f\xd1\x98\xbd\x9d\xe6\xdc\xed4go\xa31\ {;^)\xbfEp\xd9\x12\x8c?a\xb1?\x88-\ ^\xb1\x86\x998h\x8e \x95&\xeb\x94\x85E\xb7z\ \x8cn\xf5\x18\x1bK\x0f%\xd7,\xbf\xcbl\xf3Mf\ \x9ao2\xdbx\x9d\xb9\xc6\xcb\xd4[\xe7&\xde\x86\x9a\ \xdf\xe4\xd1\xed?\xe4\xd1\xed\xff\xc2[\xb5\x07\xf8\xfa\xc2\ \xa7x\x96\xf7L\xfc9\x07\x89\x8e'\x93u\xe8\x19\x96\ >\xc8\x86mbh\xa6\x84!\x02s\xf2\x08\x19\x8e\xb1\ \x83F\xea \x0d\xdbn\xc6\xf3b2K\x1c3\x0c^\xe3\xf6\ 1\x93\x93&\xa9!\xbeE\xe4\x07\xf7\xb8\xf0\x02\xb8\xd6\ \xf289\x17F\xdfS\x97\xc8$\xd5R\xb5q\xd2\x07\ \x0e\x99\xc0\x88\xaa\x9d\xb5Q\x04H\xaa\x96\xcd\xca\x8c\x93\ \x11\x00\xe6*6\x16i0\x8b\xec\xf6\xc7j\x1b\xe3\x16\ G\x01\x8c\x06\xb6^\xab\xb4fRh\xf7\xd3{O\xf6\ _\xe7\x03;\x9f\xe5\x9e\xd6\xd7\xb0\xe5\xe4\xe7\xa4\x9b\xb3\ \xb7\xb2\xb1\xf8\x10\x9bK\x0f\xb23w/\xbeS\xc3u\ ]V\xcf\x9f\xa7\x5c.g\xec\x0bz\x8b2\xba\x8a\xbc\ N\xde\xd5F\xc8\xd4\xbb\x5c\xa6\xfe\x19\x89\xac7\xe8V\ ]\x01\xa3\xe0X\xf9\x84ni\x8e\x8d\xe5GY_~\ \x14\x80:]\xae\xbe\xf5$+\xdbOq\xa6\xf3,\xcb\ \xee\xa5I4\x8a\xe3\xbd7\xf9K\xd7\x9e@V\x9f\xe0\ \xa9\xf2\xff\xc8[\xd5\xf7M\xa4\xdc\x83\x80%\x04\xc7\xe7\ J\xf4}\x99\x09O\xaen\x0a$\xf4\xf1<\x00\xc3\xfc\ \x80L\x08\x08W\xd8\xd8\x93sE\x19\x19Iw\x1c\x81\ (\xea\x96Y\x0c\xbfz\xd970]\x98\x1a\x01 e\ \xfeb\x10\x0d+\xb4\x02\x98\x06\xd4\xb0\x9d\xb4\xf4\xf5\xae\ \xbb\x85$\xdc\x1d\xd0h\xe2\xd3\xcc\xfd\xa6\x00A\xc3\xb6\ \xa6\xd4\xd3\xbd 4\x19\xdb\x82d\x8e\xf0\xe4l)\xcb\ \x04\xa5\xf6\x1bUEu\xb2\x0c\xe4\x00\xf7\x8a\x815\x0a\ \xef\xbf\xd4hs\x7f\xebq\x1e\xd9\xf9,'zo\x0c\ *hl\xf4\xcb\x87\xd88\xf40\x1b\x8b\x0f\xb3\xb9\xf8\ \x10\xfd\xd2\x02\x99\xaf,\xb5\xef'\xcd}\xc3d\xe8\x98\ \x1aMCa*\xfa\x9f\x8e\x9c\xe3\xa8\xd6n\xd0\xbee\ A\xe7QO\x03\xa7\xce;\xb3\x1f\xe0i;\x9c:X\ \xf4\xaeqG\xe7Ino?\xc9\xcd\xdd\x97\xf6,\xc8\ \x9d\xe8\xbf\xce]W\xfeO\xde\xac=\xc8\x7f=\xf4s\ \xac\x96N\xef\xa9\xbc\x83\x80\x1fH\xban\xc0L9\x0d\ \x91\x15\xbf\xb3@J-V\xc7p\x14\xe5-J\x17\x84\ \xd3Tkm\x9f\xd5\x01\x11?\xf7\x0b!\xf3\x1f\xdcB\ \xbd\x9b\xedf8\x19i\xf6\xd4\x0c\xcc\xef\x1dL\x8f\x00\ \x10\xfd\x97\x98\xa8\x19\xb0'\x802\x8f\xa4j\xf9\xaa\xc6\ k|\x86\xccN\x0d\xa8\xcf\xd8\x0b\xae6=N\xce\xf9\ ,T,\xfa~\xb6\xae9\x16*\xf3\xd72S\x12\x98\ \x85\x19\x15]/\xe0\xc8\x8c\xc3\xc5\xa6\x1b:*\x01\x9e\ \x1c=\xb6\xbb\xfe\x9e\x8a\x04\xa8\x228^\x83\xe3\x97>\ \xc7\xcf\x9d\xfb}f\xbc\xc9-\xdfk\xcd\xdc\xc2\xda\xa1\ \xc7X]\xfe ;\xb3w\xa03|\xa1p\xb8\xd8|\ \x9e\x12\xe9,\xb1Vn\xcb\x1c\x07\xec\xcd\xc1i\x92P\ y\xb4\x89w\x9b\xf2&\xc7r\xb0\xe0hr0\x8b\xd3\ \xe2_]@\xderV\xf8\xd6\xdc\x8f\xf3\xad\xb9\x1f\xa7\ \x22\xdb\xdc\xd9\xfa\x16\xf7\xb4\xbf\xca\x99\xce\xb3{\x12\x06\ n\xed<\xc3{.=\xc7\xd3s?\xcc\x9f.\xfd5\ zbf\xf8M\xd7\x09\xcb5\x9bj\xc9\x8av\xb8\x0c\ \x89\x91\xba\x85\xf6^\x96\xcd\x82\xea\x7f\x14\x96e\x0a\x04\ f\x09h\xb9\x01\x9d]D\xd7\xdc+\xa4\x0c7\xf3\xd1\ \x85hu\x7f\x13\xb5/\x19\x15\x19i>\xce\xe4\x177\ ,\x02\xd3\x80\xa9\x11\x00 \xdd\xaa66{\xeb\x1d\xc4\ \xd4\xe9TMWd\xae\xa5\xddU$\xff\xab\xd7\xc3\xa7\ \xec%\x0e@ZR8h\x07I\xc3\xc3,\xb5zy\ \xc3\x18\xb2 \xdd\xf5oe\xc6a\xa9j%\x9b\x12\x15\ URu\xb2IL\x9b\xca\x033\x03\xdbP\x87Z\xf7\ 2\xa7/\xfd>'\xaf~\x01\xcb\x1f\xbe+\xe1(h\ \xcf\xdc\xcc\x95\xc3?\xc0\xb5\xc3\x1f\xa1]\x1b\xac!\xc6\ \xdfJ\xed\x07\xb1EcT\xe5AN\xe2\x83O\x08\xf1\ \xfbO\x9d\xff4\xab\x06\xc5\x16\x8d\xb0\x00\xad\xbc\x82c\ =-5_\x17\xf7\x97\x9e\xa8\xf3\xfc\xecGx~\xf6\ #\xd4\x82&w\xb5\xbf\xc1=\xad'\xb8\xa5\xf3\xc2\xae\ \x1c:-\x19\xf0\xfe\x9d\xcfqG\xfb\x9b|\xfe\xd0\xcf\ \xf3j\xfd\xd1\xb1\xcb8\x08,\xd7l\xea\x8e\xa0\xd1\x0f\ R\xc7\xd9\x11y\xbe\xe9[\xa9\xf7%s\xe7\x0a\xd4\xf3\ \xf88@P\xb6\xb9n\xd0\x87\x88\xc9\x98d\xec_\x1a\ ]\x96Zz\x86\xb6\xa8y\xa3\xdfQ|\xa5n`\xb2\ \x98\x1a\x01 \xde\x15.\xb1\x04\x18\xf2\x0c\x1c\x80\x1a\xe7\ \x12Rj\xf3t:{\x0b\x7f'eu\xba\xb0\xe3r\ \xe7\xe10,\xb0@ \xf5\x90\x84J%\xf3\xf3\xd5\xea\ F\x95Q\xba6\x18rB\x83\x84\x93s%^]\xef\ \x85\x1e\xc3B\xd0\x91r\xe0 \x1a$l\x98\x84\x97\xf8\ |\xa1\xf1\x1dn\xbe\xf8\xbb\x1cY\xff\xeaD\x96\x96u\ \xecY^\x9c\xf90\xe7W>\xc9\xb1S\xf7\xd2\xf6\x82\ \x81\x1a\xab~!~7I_\x99\x12\x86>.B\xe6\ \x22\x8d\x7f\x09D\xfe\x1e\xd3q\x16C\x9c\x01\x14\xa1y\ \x14t\xacY\x9e\x99\xfd\x04\xcf\xcc~\x82\x99`\x9b\xfb\ \x9a_\xe1\xa1\xc6\x179\xec^\x18\xad\x00\x05\xf3\xde\x06\ \x7f\xe9\xda?\xe7;3\x8f\xf1\xf9C?O\xd3^\x1a\ \xbb\x8c\xfd\x82%@X\x82\xbe\xb2\xc1|f*M\x19\ \xd2\xa6\xbeY4~r\xe7\x83$\x05\x11\xee\xf9\xf1\xce\ \xf6\xc1o\x0d\x0b(\xd6\xd4\xf1\x07\x95H\x5c\x01\xe3\xc2\ \xd4\x8b\xa2\xb0\xef\x9a\x04\x8c\x1b8\x18L\x8d\x00\x001\ 1,\xde\x9f^h\xc7\xea@\xccl\xff\xab\xf6\xa8\x22\ \x07\xc0\xe8\xbfIu\xba\xb6\x1b`\x13mO+\x8a(\ E\xf6i\xd96\xca\x0c\xc9\xd6\xa1\x0f\x18I\x14\x16\x18\ X\xae\xdb\xc9n|2\x1a\xc1\x223\x88S\xebG\xac\ 5\xc7>\x00\x96\x22t\xa9\xcf\x112\xe0\xe8\xc6W\xb9\ \xe9\xd2\xef\xb1\xb8\xf3\xf2\xd0\xf6\x0f\x83D\xf0f\xfd!\ \x9e\x9b\xfd(\xaf\xd6\x1f\xc1\xa7\xc4\xd1\xaa\xc3\x8a\xa1}\ \xa66\x9b\xcbL\xffF\x15K\xa6\xc8\x00`\xd4\xb4r\ LcW\x95\x1d\x8d\xbc\xc6\x16\xb0q\xd0\xb2\x16\xf8\xe6\ \xfc\x9f\xe3\x9b\xf3\x7f\x8e\x9b\xbb/\xf1H\xe3\xb3\xdc\xd9\ \xfa\xe6\xd8\x13+w\xb7\xbe\xc1{\xba/\xf0\xa5\xa5\xbf\ \xc9\xb3\xb3\x1fg\x1a\xc2\xc0\xda\x96\xe0\xd8L\xb8\x92&\ nMl\x95L\x02hE\xe9E\x82\xf4 (\x86\x97\ ,o\xd4>W \xa1\xd1\xbb~KUc\xab\xd4(\ \x9f$\xeb\x9f\x15\xab3&\x9f\x95\xe1\xab\xfbMK\x92\ o`\x7f15\x02@\xb2\xfe\x14\x92\x1e0\xa8\x0f&\ \xbc\xdddg+\xb8Y\xbd4@6\xd8\x15\xfa\x81d\ \xa7\x1fP\xb1\xc3\xf9Cd\xd6Yk\x10s\xd7+\x98\ \x89\xd0W\xf0\x12\xbc@\xe2X\x82\x9a#\x98q,<\ UE\xc9Y6\xd4\xd0\xc0\x92\xecP\xcd\x86\x0dv\xfc\ 6\xa7\xae~\x81\xd3\x97\xff\x80Z\xf7\xeah\x8d\x1f\x80\ \x1dg\x99\xa7g?\xc9\xf3\xb3\x1fe\xdb9\x92\xbd\xa8\ \xbd\x9ba>\x1c1T\x8bE\x91V1\xa8\xdfL\x15\ \x81Q\xfa}2\x05\x10\x9d\xef\xc5\x09|\x14\xfa\xbd\xd7\ \xf7\xf0N\xf5^\xde\xa9\xde\xcb\xf2\xd2E>\xb8\xf5\xfb\ \xbc\xb7\xf5gXcX\x88\xaa~\x8b\x9fX\xfb\x15\xee\ i=\xceg\x97\xff!\xdb\xce\xe1=\xd6hoX\xae\ \xd9XB\x84cIy9\x81\xd2\xd9\x8c\xef\xac\xc0\x17\ C\x87\xde?\x8b\xfa.\x80c\x0bp\x0f\xbe\xa7\x06(\ \xfdn\xd8\xe3E\xd6\x8fD\x8d\xc3\xa2\xf6\xbfXp\x1a\ \xa1\xb8\x1b8`L\x8d\x00\x00)\x11L$\xed\xc8!\ %\x86\xee\xc4\xa4\xf3\xc8\x1c\xc3\x95ag.\x1c\xb4\x13\ \x1c_\x1dW\xb2\xdd\xf591o\xe1\xb9\xd9\xfa\xa9\x95\ \xd6\xa5\xe3\x81U)V\xdep\x03\xc9l\xc9\xe2\xd4|\ \x89\x9e/)9\xda\x0e\x84\x05\xf5L\x84\x1fM\xf3\xaf\ \xf6\xaeq\xf3\xe5?\xe0\xe4\xb5\xcf\xe3x\xed\x01-\x1d\ \x0d\xe7\xaa\xf7\xf0\xad\xf9\x1f\xe7\xd5\xfa\xa3\x04\x14Oh\ \xea&\xef\xf0P7a+\x15\x05\xe2\xf0\xab\x09\xb3\x94\ \xbaC[q\x80\xa7i\x13\x00R\xbf\x97\x14\xaa\xf69\ *L\x9a\xe90!`R\xefa\xdd9\xc9\x1f\x1e\xfe\ \x07|m\xf1\xa7\xf9\xc1\xad\xff\xc8\xa9\x9d\xcf\x8du\xff\ \x99\xce\xf3\xfc\xfc\xe5\xff\x89\xcf\x1f\xfa;\xbc0\xf3\x83\ \x13\xaa\xd5\xf88Rwp\x84\xc0\xcd\x091\xfa\x82Y\ m\x14\xeb\x11\xb7F\x84I\x09\xa9\xd8\x82\xcb-\x8ff\ \xff\xfa\xf4\xd2P\x08\x1d1\x16\x9f\xd4\xda \xb3\xa3v\ \x90\x80c\xb2<\x8d\xf7\xf6n`\x12\x98\x1a\x01 \xeb\ \x0c\xa5t#CO\x89\xb5\xa3\x5c\xa7R\x8e\x13\x13\xbf\ \x84d\xc1\xbf\x92#\xb4\x1e\x88\x84\x81L\xa4\x0d\x12|\ \xdf\xcc\xe4\x8d#Jh\xf3\xef2;\x00\x06\x0e\x08\x01\ \x1d/\xe0P\xcd\x01)\xf1\x95e\x88@>\xee\x80\xe2\ \xd0\xa4j\xcf\xf3\x8d\xefp\xcb\xa5\xdf\xe3\xe8\xc6\xde\xe7\ \xf7]Q\xe6\xc5\xd9\x0f\xf3\xe4\xdc\x8fq\xb5\xfc\x9e\xa1\ \xf9\x93w\x9f{7\xaa$#3\xc9\xe1\xe7L%\xa3\ \x944\x0f\xea\x0dJ\xaa\x1c\xdf\xec\xbd_P\x89\xa6\xfe\ 7\x08#\x0b\x90C\xca\x9a\xf4\x96\xb3\xeb\xce\x09~\xef\ \xf0?\xa6\xce\xc7y\xdf\xd6/r\x9c\xd1W\x88T\xfd\ &?\xb5\xfa/\xb9\xa3\xfd-\xfex\xf9\x7f8\xf0\xcd\ \x86f\xca\x16\xf3e\x8b\x9e\x1f$Sd\xa0m\x07\x9c\ y_\xa3\x1c\xa7(\x8a\x85\x9f\xb9S\x82mY\x04R\ \xe2\x0f[\xc3\xbco\x90\xa3\x8d\x11E\xf3\xca8I*\ \x8aNQ\x11E\xbeH\xf1t\xe4\xb4\x8c\xcf\xef\x05L\ \x8d\x00\xa0j\xee\xba\xee7 {\xae#\x19\xe7\xe8\x0a\ &\xb4\x84\x9c\x9c\x13 \xc0\xc5\xa6\xcbr\xdd1\xd6\xab\ \xc8\xbe]\xa4\xe7\x0e\xd5\xe4\xa2\x0c~ 3\x12x\xae\ \xe0\xb8|u\x90\xfa\x1e\xc77\xbf\xc6c\xdbOq\xa8\ \xf5j\xd1\x13FF\xd3Y\xe4\xc9\xb9\x1f\xe7\xe9\xb9\x1f\ N6\xbb\x19\x07E>\x1f\x80\x99\x8a\xc4m\xd1\xb8\xa6\ \xa9\xdf\xe8-\xbb^\xfb\xac\x9b\x90T=v\x80\x8d\xb5\ \xaf!\x13\xb02\xf9?\x9d\xd4Q\xcd\xaf9f\xa3u\ =)\x87\xafZ\xd9\x0b\xae\x94\xcf\xf0\xec\xb1_\xe4\xc2\ \xdc\x9b\xfc\x8c\xff\xbbcE\x84\xbc\xa7\xf55n\xea\xbd\ \xcc\x1f\x1e\xfe\x07\xbcQ}x\x1fjgF\xdd\xb1\xa8\ \x97,\x9a\xae\xd9!u\xe8x\x1c\x82Q\xba\x9d\x10\x82\ \xaeW\x1c^\xfb %\xe9\x1e&a\x0a\xc6\xd6&\ \x5c?{-\xb6,\x0e\xa3\xdd\x19%i\x14\x82\x7f\x03\ \xfb\x82\xa9\x11\x00$j\x5c\xf4(-\xea\x10\xa6\x1d\xeb\ \xc6\x9d/.\xfa\x9d$?H\x9d\xeb\xf2\x85\xc6S\x1a\ \x10\xb6+\x9e\xae\x88\xeb\x12\xcf\xbd\xa5MM\x89\xbb\xfa\ kB\xe6Z\xc1;\x91\xc0L\xf72'.\xff\x11\xb7\ =\xfd\xebT\xbcm\x16O\x9f\x06k\xf7\xeb\x8dV\xcb\ \xa7\xf9\xe6\xfcO\xf2\xfc\xec\x0f\xeezG\xb8x~5\ i\x83n\xfdW\x1b\x17k\x17\xb1\xe6\x11]\xd6\xcd\xe8\ \x19\xe2B\xfe\xddM\x8b\x10\x103\xffXz\xcb\x9b\x99\ G)!:\xcah\xaa\x86\x9cZZ8\xd6\xf6\x93\xe2\ \x0a^\x9a\xf9~Vg?\xc2'6\x7f\x93\x07\x1a_\ \x1a\x99\xbe\xcfz[\xfc\xe5+\xbf\xc8\xd3s?\xcc\x97\ \x0e\xfd\x1c}Q\xd9\xc7z\x868:\xe3d\xbd\xff\x95\ \xbe\x96,7%\xea\x92\x05\x1c\xce\xa4\xd9\xean<\xc3\ \x98\xa3\x17\xc8L\x84\xcf\xeb\x81\xa4_*)\xa6\x00f\ \xc6k\xa2\xf8\xfd\xe4\xb5\xfe\xec`\x9f\x9e\x08\x9d\xdf;\ \x98*\x01@\xfd5e\xd0y\xc1(t\xc0\ ^\xbc\xb7C\xde\x97\x1a\xf0u\xa1HJ\xad\x9d\x9a\x1a\ \xa6\xae\x99\xcf18\xf2\xef7~\xef\xd3\xc0\xfeU\xe1\ 3>\x96Z\xba\x0a\x9d\x91\x0c\xc5\xa0y\x81\xe8\xdaA\ \xc8A]k\x86\xcf.\xff}^\x98\xf9A~b\xfd\ W8\xe4^\x19\xe9>\x01<\xdc\xf8\x02g:\xcf\xf1\ \x07G~\x81\x0b\x95;\xf7\xad\x8e\xcb5\x9b\xc3\xeaJ\ \x1a4%A\xc9;h\x8c\x0eJ3\x95\xa1\xc3\x11\xa1\ /\x91c\x89\xb1\xb6\xd8\x9e$\x12\x07d\x0dE}E\ \xef\xaf\xa6\xf1h\xb4\xca\xe6R$b\x8f\xbb\x10\xde\xc0\ \xf8\x98\x1e\x01@\xca0\x16\x00\x223\x07\x07\xda\xb1&\ \x89\xea\x9d\xcb\x12\xda\xb5\x01\x92z\xa8\xadO\xa4\xfaI\ \x9dz\xbe\xc4\xb1 \xb3\x8a\xc7`\xbd0\xdeOj\xca\ Mn1q\xb1\x11\xb0\xd8|\x85Sk\x7f\xc2\xf1\xf5\ \xc7)\xbb[q\xe9\xbb\x1e`\x81\xe5p\xe5\xc8Gx\ z\xe1'y\xb6\x7fz\x22\x035a|\x06a\xac\x98\ \xd0F_.\xf1i\x08M\xe6j@#\xbd\x8c\xa2\xf3\ \xeb\x89P\xc0\x91Id\xc2\xc8\x08\x902\xe6\x11\xe6\x8c\ \x07!Y\xdeI^pH6\x86\xda]\xd5w\x85w\ \xaa\xf7\xf1\xefN\xfeK>\xbc\xf5i\x1e\xdb\xfe\xcc\xc8\ \xab\x05\x96\xbc+\xfc\xec\xe5\xff\x8do,\xfe\x14_^\ \xfc+\xf8\xfb@\xb2f+\x16\xb6\x10\x04R\x11\x1be\ \xb6\x7f\xaa\x8e\xa6\x89p\xaaM\xab\x00\xe9\xb6\xe0\x0c\x97\ \xb1ucW\xd9\x12\xbc\xd9\xf4\xae\x1b\xf3'\xa9\x8f,\ \xec;\xb9\xfcC\xaa\x9a\xb8_i\x08d\xfe\xfdL\x8b\ e\xee{\x09\xd3#\x00\xa0\x0c\xb8\xa8\xdb\x99:\x9e\xce\ \xf8\x8b\xae\x17\x9d\x9b\x9e9I\xb4\xfa\x01\x1d/H\xb6\ \xe7\xd5U7\xd3\xfcbv\x8e\xda\x90\xc1pn\xb2\xde\ \xd6\xbbW8\xb5\xf6'\x9c\x5c\xff3f:\xe3\x07i\ 1\xa1\xef\xccs\xee\xd8\x8fq\xf6\xe8O\xe2\xd4\x0f\xf3\ \xf6j\x17y\x1d\xb7\xd3U-\x05\xc9\xbb =\x1e\xf6\ A\xc7\x89\x1axP\x88\x99K2\x06\xd0|6\x22\x8c\ ck)\xb2|\xc5\xcf\xcb\x97\xbe\xffp\xa9\xf0'\x8b\ \x7f\x83Wj\x8f\xf2Sk\xff\x8aC\xee\xe5\x91\xee\xb3\ \x08\xf8\xe0\xd6\xefqk\xfbi>s\xe4\x17\xb8Z\xba\ ybur,\xc1\xe1\xaaC\xc7+Z\x85\x9e\x17K\ 3S\x01\x1aR\x85B\xa0\xc7\xe1\xd0\xa1\x97\x1c\xb0'\ \xc3\xdcD\x90Y\x8e\x1d\xa7\xed\xb6,\x86\xd0_\xed\xda\ \x0d\x17\x80\x83\xc7\xd4\x08\x00*1O5\xc2\xf0\xc0\xd4\ 1b\xed\xde\x22+\x8d\x9b\x8f\xcd\xf6P\x11MXM\ \x92\x0cn\xf5|\xba\xbe\xa4f\x8b\xac\xb9Yi\x9f\xc9\ \xf4/\xb4\xc4\xc4O`\x08f\xba\x979\xb6\xf1\x04\xc7\ 7\xbe\xcaR\xf3\x95=\xd7?F\xb3v\x8a\xb7\x8e\xfd\ 4\x17\x0f\x7f\x0c\xdf\xaeb\x01\xae\x17\x841\x0e&\x88\ \xdd\x98\xe4\xe3\xb8\x89\xba\xff\x7f\xac\xbd\x98EG\xf5\xee\ \xeb\x8f\xb8\xde\x89@\x22I\x96_e\x08\xb0\xc2C\x06\ \xd5\xdb\xe4:\x91\x9b60\x08\xc7\xd7\xe3m\x5c\xac\xdc\ \xc9\xbf;\xf1K\xfc\xd0\xc6o\xf2P\xe3\xf3#\x13\xfe\ \xa3\xfd\xb7\xf9\xdb\x97\xfe\x17\x9eX\xf8\x0b|u\xf1g\ &b\x0dX\xa9;\xcc\x96-\xba^`|g\x19\xc7\ L\xd3\xab*\x9c\x9b\x19\x8f\x85:B\xd0\xec\xf9\x5c\xbb\ \x8e\xf3\xff2\x92\xa4\x13+l\x81\xef\xdf(\x96\x8d\x81\ \xcf\xd1\xf2\x0c\x16\x93n`?15\x02\x80J\x0cu\ B\x86r\x9e\xbbO\xa6\xbf\xea\xa0\x8d\xac\xc4I\xba\xaa\ \x01\xa9\xd45\xef\xf3\xbb7\x08\x11\xed\xd6gg\xc3b\ f;\xbc\xc8\xa4\xc5\x1al\x96p\x17\x1b\xdf\xe6:\xe7\ 8\xbe\xf1\x04\xc77\xbf\xcaB\xeb\xcdQk\x96=\x95\ \xe6\xda\xad.<\xc0\xd9c\x9f\xe2\xca\xe2#\x80H\x06\ \xbbc\xc1F\xd7g\xa77IW\x1d\xf3\x02\xbe\xc1\x10\ \xd1\x9d\x8a\xe6,U\x8d7\xbf\x91I\xa6?\xed\x87\xd9\ g\x97\x88\x09n\xf8\xbfL\xa64\x8c\xf5\x1bRg\x13\ \xbb\x19f\x14\xd9\xcf\xd7 3\x03.\x0fWT\xf8\xe3\ \xe5\xbf\xc7\xab3\x1f\xe0\xcf\xad\xfd\xf2\xc8+\x05l\xe9\ \xf1\x83[\xff\x1fw\xb7\xbf\xceg\x0f\xff}.\x96o\ \xdfu\x1dmKpr.t\xfe\x0b\xa2\xe1\x96\x11\xca\ I5\xf3\xf8\x174\xba4\xa2\xe5)\x86.\x9c\xc5i\ \xc2\x0a7\x00\xda_\xf3\xffpq/^\x05\x00\xc5+\ \xa4\xb2\xe9\xf99\xca\x22\x03\x93\xa9\x8f\xaa\xabW\x82\xb1\ H\xf1t\x08\xf2\xefv\xec\xab\x000\xc8\x0fIGJ\ \xd0e&M\xcfS\xecP2>\x12S\xf2\x08\xb0l\ \x0b\xcb\x0a\xff\x06AJ\xb8\xda\xf2\x98?TA\xc6v\ \xdd\x11 !c\xd6W\xb53\x0b\x9fC\x8d\x97Y\xd9\ \xfe6\xc77\xbf\xc6\x5c\xe7<\x83\x88\xeb\xc0vX6\ \x96m#\x00;Z\x01\x10X\x0e\x17\x96?\xca[\xc7\ >\xc5N\xfdL\xae=0Y_\x09\xb5\xec\xc4\xe48\ \x82f\xa1\xe6\x11\x80\xed8X\xb6\x8d\xad}\x13\x95\xb0\ \xea\xce\x80\xd3D4\xe2vK\xc0q\x1c\x84eaE\ \xdfD\xd7\x8a\xf4\xbe?l*i\xd4\xe7\xef\x07\x1c\xc7\ \xc6\xb6\x87\x8f\x15\x807\xab\x0f\xf1k'\xfe5?\xb6\ \xfeo\xb9\xa7\xf5\xd5\x91\x9f\xb1\xd2\x7f\x87\x9f\xbb\xf4O\ yj\xfe\x87\xf9\xb3\xc5\xff\x9e\xae5\xfe\x0e\x83\xc7g\ \x1d*\x8e\x15N\xd9A^\x08\x17`\xdb6\x96\xb0\xb0\ m'\xabL@\x9e\xc0\x15Z\x03R\x18\x055\x19\x0a\ #W\xf7u\xfb_\x81m\xdb\xd8\x96\x8dm\x17\x93\xfd\ d\x8c\xe8\x9d\xc3\xa8}\x91\xeey\xa2$\x16\xf5Y\xfd\ 9\xea4\x8a,|H\x1eB\x08,\xcb\x0am\x15c\ n\xcf|\x03YLT\x00\x18\xf8!\x8c\xbc0U\xdf\ \x83@\x12\xc8\x00)E4\x1f\xaav\x89\xe8x\xc8\x03\ \xe2\xee\x93u\x14\x8c\x96\xa9H\x0ck\xa5%%!\xe8\ v\xbb\xf4\xa2\xdd\xbf\x84V\xa6\x15\xa5\xb8}\x17\xcf\xf3\ \xe9t:\xd8\xb6E\x10\x04\x89\xa9Y\xef\x82\xd5\xc0\xa6\ ]\xf1\x94yE2{\x15\x14Mi\xa8\xf1\xeb\xca\xee\ 6+;Oql\xeb\x9b\xacl?M\xc9k$y\ \x1bj#G\x85\x04\xcb\x12\x04R\xd2\xefG_\xe5\xa2\ \x00\x00 \x00IDAT\xf7\x11\xc0\x15w\x96sG\ \x7f\x82\xb7\x0f}\x0c\xb7\xbc\x08>\xc8\x9d\x1d\xe3t\x8a\ c\x09^\xdf\xe8\x85\xbb\xa4M\x08e\xcf\xa6Q\xea\xd3\ \x1bc\xdb\xd3\x98pX\x96\x85\xeb\xb9\xf4{}\xa4\x84\ F\xb3\x15Z5\x06\xb9\xd0\x03%K\xd0t}\x1a\xcd\ \xde$\x9a\xb0'4\xaa.~\xc9\x22@\xd0\xebvq\ ]\x8fN\xb7K\xb3\xd5\xc2\x0f\xf2\xef\xb9h\x9aK\xbd\ \xa6_\x1f\x84\xb2%h\xect'\xf6M\xe3\xef\xd2l\ \xb6\xf0<\x8fv\xbb\x85m[xzt,\x0d\x0d\xe0\ 7k\x7f\x8f\xfb\xfc{\xf8\xd1\x8d\x7fG5h\x8e\xfc\ \xcc;\x9b\xff\x89\xd3W\xbe\xc8\x97\x0e\xfd,\xcf\xcf~\ \x84QW\xa5,V,V\xec\x1ak\x9b]\x03s\x92\ XB\x80\x104\xdbm\x5c\xcf\xa7\xd1lR\xaeT\x08\ \xfc\xd8\xffeDfE^\xe3W\xaf\x01\xd8\x16\xb4[\ \xb0\xba\xd9\xa5\xe5Mn|%\x16\xd0(\xe8C\xb7\xdb\ \xc3u]\x1a\x8d\x06\xa5\x92\x83\xef\x07\x99f\x94-A\ \xa3\xe6a[\xc5\x02\xff \xa5\xaeh\x1a*F\xe1(\ \x171\x1d\x0d\xefj6;t=\x99\xbbG\x02\x96\x08\ \xf9\x83\xebz\x042\xa0\xd3\xe9 \x84\x88\x1c\xc8\xb3\x90\ *\xf7\x90\xd9r\xe2Z\x9a\x04\xb2\xf48/\x5c\x98\xcf\ \xa3\xe7\x18\x1a8\x88\xb2e\x97A&\xa6\x97\xa1\xf7M\ \x12{\x14\x00\x86\xbc\x9e\x98\x91\x17\xd8\x84\xd2dI\x10\ \x04\x04\x81\xc0W\x04\x00\x19h\xbb\xdbe>\xb2\xcc~\ \xd9\xf8\x9a\xb6&E*\xd7\xd3\xe44\xcd\xb1\xa0\xd5\xea\ \xd2\xec\xfb\xb9|\xc8P\xc2DJ\xba\xbd.\x81\xef\xb3\ \xb3\xb3\x83eY\x04\x81\x9foWtoc[P\xea\ \x95\xa9:\x02/n\x83\x94y\xc2\xac>+\xf0Xn\ \xbe\xcc\xe1\x9dgY\xd9y\x9a\xa5\xe6\xab\x10yJo\ \xb3wHB\x8d\xdf\x93\x827\xaa\x0f\xf1\xf6\x91\x1f\xa3\ {\xf2\xc3\x08a\xe1o\xb9Xbm\xe0\xbd\x15[p\ u\xadK{\x82\xf1\xc9\x83\x9a\xcd\x82_\xa6\xeb\xcb\xd1\ \xd5\xda\xe8\x9d\xd9\xb6\x1d2\x99N\x1b\xc7\xed\x87\xc2M\ \x10\x84\x82\xd9\x00\xee\xe7X\x82v?`m\xfd\xfa\x0a\ \x00\x02\xb8&+\xcc\x94,\xa4\xb0\xe8\xf5\xfb\xf4z=\ \x1a\x8d\x06\x9e\xef\xe3{^.\x7f\x8c\xddh\xfb&\x94\ \x1c\xc1\xeaZoB\xd3:2\xd2\xccl\xba\xdd\x0e\xbd\ ^\x8f\xad\xadm\xba\xbd\x1e\xbe\xe73J\xad\xbf\xcc\xdd\ <]\xfe?\xf8\x89\xb5_\xe6\xd6\xce3c<{\x95\ \x0f^\xfdg\xdc\x5c\xb9\x93?Y\xfa\xeb\xbcS\xbdo\ \xe8\x1d\x87\x97+\x5c\xbe\xda\xa4\xeb\xab\x93GY\x01S\ \x02\x9dv\x87^\xbf\xc7\xea\xda\x1a\xd5J\x05/i\x8b\ \x06]:\xd3%\xb3\x01RY\xc5\x16\x5ch\xb8\x9c\xdb\ \x97\x1d\x00e\xd8\x16)i\xb5\xdax\xbe\xc7\xfa\xfa\x1a\ N\xa9\xa4\xf4\xb1\xb0^e\x1b\xaeY5l+\x22=\ E\x13\xf5\x99c\xa1\x16\x91\x85\xd0O\xd3\x84x\x8c\xaa\ \xbd\x22N\xdb\xd8\xe8\x844A/D\x88H\x00\x90t\ \xbb]\xa4\x84\xed\xedm\x84\x15*d\xe9\xfb\x15I\xfe\ \xcc/j]EX\x1fa\xc8\x1fgR\xaf\xe9\xe5\x08\ S\xba~\xaf\xe9%\xe4\x89\x9c\xd1)w\xa4\x01\xbew\ *\xb0G\x01\xc0\xd0\xf0\xcci\xb8\xb6S\xe8\x1f >\ SN-\xcbB\x08\x0b\xcb\x0a\x19\xb4@dvC\x11\ J\xcf\x8b;\x92\x14\xa9\x86\x9e\xc2lL\x12d\xc7%\ \x84Kvl\x0b\xe6{%l71~e\xee\x0f5\ \x01\xd8\xde\xda\xa6\xdf\xef\xb1\xb4\xb8\x88m\xdb\x89\x10\x91\ \xe9?\xca\xf3\x0e-\x95\x99\xab\xd8Ip\x91\x5c}d\ \xc0B\xfbMVv\x9e\xe5H\xe3Y\x8e4\x9e\xc7\xf6\ \xfb\xe1\xc5\x19`v\x85\xc1\x18\xfd\xe3K\xa0Q\xbf\x85\ \x0b\xcb\x1f\xe7\xed\xe5\x8f\xf1\xf6Z\xc8\xfc\x8e\x1f=\x16\ \x11\x87\xc1\x0c\xc0\x11\x82\xa6\x1b\xb0l\xf5Y\x98\xe0\x5c\ \xc0\xa1\x9a\xc3\xb1\xc5r\x86\x08\x8f\x0aKXx\x9eG\ \x10\x5c\xa6\x5c.\xb3\xb2r4\x11\x1a\x07\xbd\x9a\x92%\ h\xbb\x92\xadrw\x0f5\xdf;\x04p\xfcp\x85\xba\ c\x11`\xd1\xedu\xb9|\xe92s\xf3\xf3,\x1fZ\ \x0e\xa7\xc2v\xe9p9\x0a\xff\x91\x12*\x8e`\xdb\xe9\ 1\xd3\x9f\xd4\xaa\x0e\x81e\x09\x1a\xcd&\xab\xd7VY\ ^>\xc4\xdc\xdc\x5cH\x9cG\xc61\xbe|\xeaW\xd9\ i|\x9eOl\xfe&\xe5`tA\xed8;\xbc\x9f\ _\xe1\x15\xfb1\xfet\xe9\xaf\xb3^:a\xcc\xb7T\ s\xb8c\xa9\x82;\xa0^B\x84\x0cbsk\x93\xad\ \xcd-VVV\xa8V\xabc\xb6e4\x94,\x8b+\ \xa2\xc3\xf1\xfa\xfe\x84\xc2\x89\xe9\xef\xea\xea\x1a\xedN\x9b\ \x95\x95\xa3\x94\xcb\xa5\x5c[J\x96\xe0\xd8J\x15\xdbJ\ \x97b\x17Y-G\x15BU\xeb\xc7\xd0\xfcQ=W\ d\xde\x02\x10\xebz\xc2\x0aWW\xac\xafo\x10\xc8\x80\ C\x87\x0e\x81\x10\xe8\xfb\x17\xc4\xf9\x07j\xfb\x9aU:\ \xcb\x01\xd214H\xcd\xcd\xe8\xa0J\x0b\x87Y\x0e\xd2\ \xf2\x05\xf1D\xa5\xaa\xb8\xbcK,\x00Y\x98>\xb0T\ .\x16\x8a\x0b\xf1\xfc\xba\xe5C\x5c8\xf4a\xce-\x7f\x82\xed\ \xfa\xadI\xba\xbdy\x0e\x04T\xab\xb5\xa1eH\xa0\xe6\ \x08v\x9a\x1eN\xd9\x9ah\x87\xa9Vm\xca\xd52\xec\ \xd2\xf1\xa9T.a;\x0eN\xa9D\xa5\x92\x8d\x16W\ Dx\x1cK\xe0;\x01\xd5\xea$t\xe8\xddC\x00\xd5\ j\x85j\xbc\x93\xa3\x08\xfdL\xca\xe52\xe5JY\xc9\ \x05\xc5dxo(\xdbP\xad\x09\xfa\xd6d\x19O\xb5\ \xeaa\xdb6\x95J\x95rywQ\xfc^\xaa~\x8a\ +K\x8f\xf2\x13k\xbf\xccM\xdd\xef\x8cu\xef\x03\xc1\ s\xbcw\xfd\x05^\x9a\xfd~\x1e_\xfcK\xac;'\ \x93k\x8bU\x9b;\x97\xcb\xf8A\x18+!F\xd1\x9b\ .W*X\xb6E\xadV\xa3T*3\x0a\x8a\x18\xa7\ \xc9$^\xb2\xa1\xedJ\x9c\x8a\xa4\xea\xec/\xd9/\x97\ \xcb\xf4\xfb=\xea\xf5Z\xe2k\x92\xb9n\x0bj\xd5*\ V<\x05`\xd2\xfa\xd1\xd2F\xe6\xeeZ\x11\xd2\xf0\xce\ \xa3\x84jU\x22\xdd w\x8f\xca\x90\x1d\xc7\xc1\x0f|\ \xca\xe5rVH\xd0\xf2\xc5V\xe8,\xa3\xce\xe7\x85\xbc\ \xff\x99.\x00\xa8\xe5\xa9u\xd2\x8d \x03\xe5v\xf5\xa2\ \xd0\x92T\xfe4BW\x98Do\xd9W'\xc0q+\ (\xd1>\xc2nZ\xa8\xf7\xaa8Y\xd3\x8a\x12K\xdd\ \x88\xf5\x0c\x82\x00\x19\x04\xf8A\x80c\x0f\x0f\x9f\xdbm\ \xacq\xac\x7f\x96\xa5\x9d\x17Yn\xbd\xcc\xa1\xd6\xab\xd8\ \x81\x9bV S\xd9\xc9\xc1uf\xb8\xbc\xf8\x18\xe7\x97\ ?\xca\xd5\xb9\x07@\xd8\x99\x06\x06\x81\x8f\x1f\xf8H)\ \xf0\x03\xdfH\x08re\x06a\x94\xc3}\xc1\x00EW\ \xb7\xd8\xc4i1<\xcf\xc3\xf7}<\xcfO\x06lF\ \xcb\xd5~\x93\xe3\x83\x12\xaf\x87@]\xc1\xe2z\x1e\xbe\ \x1f\x84m1\x99\x04\x8d\xe7Z_6\xfc\x9a\xf2\xa7\xcf\ \xdf\x1f!\xc8\xf7|\x02\x19\x84\xd3d{\xc0\xbas\x82\ \xffp\xec\x17\xf9@\xe3s|t\xf3\xb7)\x07\xa3[\ m,\x02\xeeo~\x85\xfb\x9a\x8f\xf3\xd2\xec\xf7\xf3\x8d\ \xf9?\xcf\xe5\xf2\xad\x9c\x9e\x0fCV{2\xcf\xc3\x12\ >&\xd3]H=\xcf\xc7\xf7\x03\x5c\xcf\xc7\x191\xda\ u\xae\xbf\x15\x9c\xc7\x06\xce\x0b;\xee\x01\x04\xff\x91\xf8\ \xbeG\x10\x04\xf8~\xf1\xb8O\x22\x01\x0ej\x84\x92&\ M\x83L\xc9d\x92\x1d\xd4w\xae\x96!\x10#\xd1c\ \x99L\x19G>?\xd7;x\xc2\xbb\x18S\xb5\x0c\xd0\ \x14\x84B\xbd.\x0c\xc71\x8a$x\x93\x90\x9ax\xf3\ \x0e`>\xe3\xa0\x1e\xecp\xa2\xf7\x1a'\xfbop\xb2\ \xf7\x1a'\xfao\xb2\xe0Es\xea\xfb\xc8\xecc\xf4\x9d\ y..~\x1f\x97\x96>\xc4\xd5\xf9\x07\x90B\xf9\xac\ \x9a\x18\x1b/\x9b\x13\x22\x8a\xc6\x95Le\xa8\xe6\xa74\ M\x08\xe8\xfb\x01\xeb\xfb\xb0>\xb9\xc8\xc4\xa6_/J\ \x0b\xa4\x08I\x8cPB;'\xc4$[\xae\xda\x1f\xa6\ \x84\xff#\x85\x1a\x07!29\x09s\xfd\x8a\xb4\xcaD\ .\x93\x9a9\xb2\xa0\x91\x19\x17\x97\xddU{$L\xaa\ \xb7K,\xbe5\xf7\xe3\xbcV\xfb\x00?\xba\xfek\xdc\ \xd6yz\xcczH\xeek>\xce}\xcd\xc7Y\x9d\xbd\ \x87\x8b\x95\x9f\xe6\xfc\xc2\xf7!\x85], *\x07!\ M\x12\x91r\x12\x0bVr\xa0\x9f\xc9\xe0\xfa(\xcf\x10\ a\xc4\xd0\xad\xeeA\x05\xd6\x1a\x5cg\x95!\x8f\xda7\ tZl:\x1fv\x1cc\x5c;\xd4\x0d\xb6\xbfwL\ \x8f\x00 I\xa49\x95\x88\x83\xd21\x95\x04i\xa0\x88\ j\xa7\xd2\xd7\xec\x16\xcda\x8dC\x04-\x19p\xc4=\ \xc7\xa9\xee9\x8e\xf6\xcer\xcc}\x87c\xeeY\x96\xbc\ \xab\xd9\x8a\x08ax\xe2d\xd1)\x1f\xe2\xd2\xe2\x07\xb9\ \xb8\xf8!V\xe7\xeeG\x0a+\xf3\xber\x02\x90\x22(\ \xcb\xf8\xff\x0c3\xc8\xbf\x898\x16\x81\x84\xc4\x19r\xd2\ HB\xf8\x8e\x88\xcc\xb7T\x99\x9d\xc6\xed\xa5vC\x86\ \xb8\xedC;\xc6E\xcc\xac\xd5\xc8\x84\xc9\xb2H\xa5z\ \xc2\xd0\xb7\xd5\xb6\xc4\xd7\x13\xe64f%\xae\xff\x9b\x18\ \x0d[\xce\x0a\xff\xf1\xe8?\xe3\xee\xf6\xd7\xf9\xe4\xc6\xbf\ g\xde+vZ-\xc2\x91\xe6\xcb\x1cy\xf5e\xee\xac\ \x1c\xe6\xfc\xf2\xc7\xb9p\xf8\xe34k\xa7\xb5\x5c\xc2l\ \xd1\xd6\x04\xab\xddv!\xf56\xc7\x86\xcd\x96?>!\ \xdaG\x042\xdd)r$\x18\xfa\x90\x84p\xcc\x0d*\ Dd\xfbox\xe3\x94\xbc\x84\xef!L\x8f\x00\xa0\xfd\ \xc5i\x19\x06^\xa8*\xa6\x87&F\x1f\xa7\xe7\xac\x03\ \xf1\x14\x80V\xae-]\x96\xddK\xac\xb8\xe7Xq\xcf\ \xb3\xe2\x9e\xa3t\xe5)\x16\x1a\xafq\xbc\xb5\x8c\xe3D\ \xaf-f\xf4\x07`\x82\x92B\xb0Q\xbf\x83+\x0b\x8f\ py\xe1\x116gnE\x8fx7L\xdaN4D\ iH+hB\xc9\x12\xac6\xbd}\xdb\x9f<\xac\xce\ xe\xa7u\x97\x91\xf3Ov\x1f=dlN\x8ct\ \xeb\x8c\xa9{z\x02\x88\xa8\xdf@\x0f\x05\x9c\xe4\xd1\xfa\ v\xae\xee2\x9f\xb7\xe8s\xea2\xdc\xb4\xbc\x87q\xf0\ \x9d\xfa\xf7\xf1f\xedA~`\xfb\xd3<\xba\xfdYl\ 9\xbee\xaa\xd6[\xe3\x8eK\x9f\xe6\x8eK\x9ffc\ \xf6..\x1c\xfe\x04\x97\x96\xbe\x8f^\xe9\x10\xa9x,\ #\x81*\xdc\xa3$\x88\xa4L\x19\xbd\xdc\xd1V\x9f\x17\ svK\x08\xfc\x00.7\xdd\xa9\xe4{\xe3\xb4\xceh\ }\x95\xda\xb9^\xfe\x1e\x05\xa9\x1b\x98\x0c\xa6F\x00\x80\ \x94\x19\xcb\xc8F/H\xe3i\x87R\xa5F\xc1\x06,\ ~\xd6;\x9f\x1e\x96\xbf\xeam1\xd7\xbb\xcc\x82{\x99\ \xa3\x1b\xe7\x98\xeb]\xe2\xb0w\x91e\xef\x12\x8b\xee5\ ,\x11\xdd\x111\xf9\xf5\xde\x06=\xb9\x1f\xcbt\x8a\xd1\ \xb7g\xb9\xb2\xf0\x10\x97\xe7?\xc0\x95\x85\x0f\xd0s\x16\ 2\xd7M\xc2M\x11\xd4\xf7\xa0\xbe\x8bA\xf7I\xe2\xcd\ M\xf6\x8fi\x8ecn4\xb9w\xe8\xd3\x08\xe9\xbbH\ se\x9dv\xc6U\x93\xf7\x11q\xdc\x82X(\x8b\xb5\ \xff\x9c\xe4\x9bd\xcf\xa5\x8f \x13g\xef\x1f\x92\xe7\xdd\ \x80\xbe\xa8\xf2'\x8b?\xcb3\xb3\x9f\xe4c\x9b\xbf\xc5\ ]\xad\xaf\xef\xda\xdev\xa8\xf9\x0a\x87\x9a\xafp\xff;\ \xbf\xc2\xc6\xec\xbd\x5cYz\x8c+\x0b\x8f\xd0\xa8\x9dN\ \xbfI\x94W\x9d\xef\x1e\xed\xdd\x15\xe7r,\xb8\xd6\xf6\ \xe8\x8c\x11\x03\xe3 \xa5$P\xac\xb0\x03\xf3j\xbf\ z:\xea\xd8,\xf0MQ\xadV\xa2\xa8\xc0\x1b\xd87\ L\x8d\x00\x10H\x89\x94\x22\x99\x17M\x9cq\x94<\x96\ r.\xa3\xf3\x0c\x94s\x91\xfc/\xc3\xb8\xfa\x12>\xf9\ \xca?d\xb6w\x91\xb9\xde\x15\xec\xa0\x17\xcd\xe3\xa5L\ >k\xba?\xf8\x19\xa6\xc0*\xb1:{/W\xe7\x1e\ \xe0\xda\xdc\x83l\xcc\xdc\x8e\x14\xe6hj\xaa\x97\xe8(\ \xe3E\xd5\xfe\xd5\x81\x99\x19\xac\x1a\x87\xb5\x05\xb4\xdd`\ \xa2\xc1\x7fru\x1a\xa0\x91\xebV\x1bu\xc7?\x93\x13\ \x11\x14\x13%\xf5\xfa\xb4\xd0\x97t\xfb\x99\xd4\x86\x91X\ D\x86QW-=o\x0d\x92\x85\xd7\x92\xe7K\xde\xd5\ \x1a\xd8\x86s\x9c\xff|\xe4\x9fpr\xfeU>\xb9\xf9\ \x9b\x9c\xea\xee~/\x0c!%\xcb\x8d\x17Yn\xbc\xc8\ \xbd\xfc:\xed\xeaq\xae\xcd?\xc8w\xdc\x9bh\xb8'\ &\xdao\x04\xe0J\xb8\xb6\xaf\x91\xffv\x87\xa4\x0f\xc6\ \xbeA\xb1\xa0)\x0b\x8e\x0de$\xcb\xb4\x93\xf3b\x8d\ \x7f\x1c\x05\xe0\x06&\x8f\xa9\x11\x00b\xc4\x1aQ\xd2)\ L\x1aP|>\xa8\x1c\xb2\xcaR\x00,\xb5\xdf`\xa6\ \x7f\x85\xc4\xdb\xea:#\x106\x1b\xf5\xdb\xb86\xf7 \ W\xe7\xde\xc7\xea\xdc}\x04\x22Zj4F\xf5r\xf3\ \xfdZ\xba~-\xc38\xa5\xc2\xfb\x0dL\xc5\xf5\x83\xb1\ \x22\xf5\x8d\x8bA\xd1\x92e\xc1q\xdc\x0eu#\xa1Q\ k8m\x0c/#\x93\xed\xa1n\x01\xe6\x10\xac\xe1\xf9\ \x11\xeb\xdd\x8f\x8b\x95;\xf9\x8dc\xff7\xb7v\x9f\ \xe5\xc3[\x9f\xde\x93 \x10\xa3\xde\xbd\xc2-\xdd\xcf1\ \xbb\xbe\xc6\x99\xf5\x0d\x96\xda\x1f\xa4}\xe4\xfdl\xcd\xdc\ \xceV\xfdVv\xeag\xf0E\xf1\xb2\x80\x22ce \ \xa1^\x12S\xa9\xfd\xc7\xc8\x08\xd4C\x8e\x8d\x96\xa6\x8c\ \xf0\xa98\xf7)\x84)k\xb0\x8d\xa7V\xbe;\xfa\xe3\ \xbb\x09S%\x00h\x0aj\x9ah87\x99\xbd\x93%\ P\x05\xe5\xb7\xcaG#\x01\xe0\xfa\xc0\xb5\xeb\xac\xce\xdc\ \xcd\xda\xec}\xac\xce\xde\xc7\xc6\xcc\x9dxV\xba\xf6_\ *s\x8b\xc3\xd6\x81\xaaD^\x8fw\x8f\xe18>W\ \xd7\xc4\xc6s\xe8\x99\xbc\x8a\x98/\x05\xf4\x0ebo\xf2\ 1\x1f\xa1\x9bb\x0bWs\x98\x1cE\xa7D\xeb\x8d\xb5\ \x22\xd5\xb5\x22\xfd.\xbb\xc3\xa0oo\xcc?\x0d/b\ \x82x\xb3\xfa\x00k\xb7<\xc4\x83\xc1\x0b\xdcs\xe5\xd3\ ,\xef\xbc0\xa1\x92%s\xdd\xf3\xac\xac\xae\xc1\xea\xe7\ \x01I \x1c\x1a\xb5\x9b\xd9\xae\x9f\xa1Q=E\xabz\ \x92F\xf5$\xad\xea\x09\x81\xe3_\xdf\xfd T\ \x08d\x86\x81W\x19}G\xc4\x83F\xd9kR\xf6\xe2\ \xfa\x0d\x92F\xd3k\xbe]\xa1S:D\xb7\x14[G\ \x96\xe8\x94\x0f\xd3\xae\x1c\xa5U9F\xbb|\x94\xbe3\ \xbf\xbf\x15\xbf\x81\x1c\xa6G\x00\x88\xffdL\x18U\xa7\ &U\x83\x93\x89\x04\x99\xdb\x125\xf9/>\x08\xf3\xc6\ ~\xf4\xcd\xd2\xb0\x0dv\xe2\xe7\x09\xb6\x9cc\xac\x95O\ \xb1V:\xcdz\xf94\xafV\xea\x9c\x0f\x8eR9\xf9\ \xde$\x14\xb0\xbe\x17@\x116\xbb>\xc7f\x1c\xb3\xb6\ \x9d\xfe\x0c0\xd9\xa7\xd0\xfd\x1cF\xd8l,)K%\ \x8a\x19/z\xc3\xb3S-\xbb\xb8\xcc=C\xa6\xdf\xdc\ \xf4\xec(K\xf1\xb9T\x22\x00&\xff\x15@\xf1Z\x9e\ \x16\xbe\x17D\xbd\x5c&\xa6\x98\xd4\x0c`\xfaFF\x0c\ \x8a\xfdk2\x83\x99b%\xbf\x0bPs\xc2z/\xd7\ \x1d*\xb6`\xb6l\xe3\x05\xe1\xfa\xfcx\xe3\x98\x22\x07\ a\xd5\x8etm\xee>\xae\xcd\xdd\xc7\xd37\xfd\x03\x8e\ o?\xc9\x89\xad\xafs|\xfb[\x0aC\xbb\x81\xfd\x80\ \xed\xf7\x98\xf5/1\xdb\xbd\x14\xa5hfI\xc0\xb5k\ \xb4*\xc7\xb9\xd7:\xce5\xfb\x04\xeb\xa5\x13\xac\x95N\ \xb2\xee\x9c\xa4m\xdf\x10\x0e\xf6\x03S#\x00@\xaa\xc5\ \xabD^\xa7Q\x19\xc28@\xe1K\xf2(tQ\x15\ \x00\xfa\xf6,\xcd\xea\x09\x9a\xe5\x13\x5c\xb2\x8e\xb2f\x1f\ c\xabt\x9c\xb5\xd2I\xd6J\xa7\xf1\xacJ\x86\xc9n\ x\x1b\xf4z]vcC\xe8\xf9a\xe8P)\x83\xec\ \xba\xd7\x5c\xcex^^*bE6\xf7\x80\x95\x8fC\ \x99\xb5*`\x05\xca\xb1\xfa\x94\x18^ \xd9\x99\xd8.\ q\xc5\xf5\x19%\xbd\xe8}\ \xef\xa7iV\x8f\xd3\xb7g\x11\x84\x04\xe8\xfc\x8eK\xd7\ \xd3v\x03\x9c \xfc@\xd2\xf5\x82\x84x\x15!\x99\xe6\ \x10\xe4\xd6\xe1\x82\x1c\xba\xfev\x14\xc8\x88\x03J\xa5\x94\ \xac\xc0\x11\xe7\x0bw)\xdbod\xbc\xe0u\x05\xd5`\ \xd50Y\x04\x86\x09\x0c\x99k\x03\xa6b\x0e\x1a\x89\x10\ k\xfaSaP\xee3\x1a\xae\xc1KP\x9f\x12\xd3\xef\ \x15\x80\x87d\xa1b\xd3s\x82\xbd\xf7{\xe5yV\xdf\ \xa6[\xb1Y\xac8\xccW\x8b7\x9b*Y\x82\xc5\xaa\ U8\x15Q\xb6E\xb8{c \xc3\xad{\x85\xc0\x8f\ \xf7}\x97\xe9\x86=\x83\xcc_\xba\xef\x88~,\x00_\ \xd8\x5c\x9d{/\xd7\xe6\xde\xcb\xb3\xfc=\xea\xfdk\xac\ 4^\xe0H\xf39\xec\xc6\x9f\x02\xebc\xbc\x88\x1b\xd8\ \x0f\xcc\xf8\xdb\x9c\xf1\x9f\xe3L\xf79\xa4\x0cx\xec\xea\ U\x82 \xa0\xea\xdd\xcf\x95\xca\xad\x5c.\xbf\x87\xcb\xe5\ [\xb9T\xb9\x8du\xc7\xbc\x0d\xf4\x0d\xe415\x02@\ \x0cU\x03\x12h4\xccD\xfd\x0d0\xf8\xb3\x01\xe0\x8a\ :k\xb5\xdbCZ1\xd4\xb6:9\xf4\x03I\xdb\x0b\ X\xa8\xd8\xb8~\xb6\x8ej=\x93_Yl\x82\xcfM\ #\x8c\x0a\xe5e\xc4\xe5\x87\x96\x80P\xa2R\xbd\xe3m\ !\xf6o\xf7?S\xd5\x12+\x84\xccIuF%V\ \xbd&\xb3\x96\x8c\x22$N\x8f\xd3\xe4h$G\xe3\xff\ C\xfbhQ_V\xaca\xa6[<_r\xa8fc\ 1|G\xc8\x18i\x90\x17\x99\xf1\xcdQE\xe7\xb9\xa0\ \x845W\xe2\xd8\x9c\xc3\xc2l)o\x92I\xfa\xa1\xc4\ \x93\xe0\x14|\x93\x90\xf1+\x16\x0b=\x9a\x8c\xc1\xfce\ \xb4\xfe\xc4Y\x0c\xc7\xa6\xb4V\xe9\x08g\x0f}\x8c\xb3\ \xcb\x1fgm\xe6o\xd0]~\x99\x07\x97\xbb\x1c\x97\x17\ 8\xd4~\x83\xc5\xd6\x1bT\x8c\x0ew7p\xd0X\xf4\ \xae\xb1\xe4_\xe3\xee\xf6\xd7\x92>\xd0\xb2\xe68_\xbd\ \x9b\xf3\xe5\xbb8W\xbd\x8b\xf3\xe5\xbbi\xd9s\xd7\xb9\ \xa6\xd3\x89\xa9\x11\x00$\xa1\xd7\xb9\xadk\xa2\xbb,+\ .E\x15&T\xc4\x84\x228\xa0PTR\x82\xaf\xd8\ v\x8d\xb4:\x9e\x1e\x18\xa0\xbd\xe5o2\xe7\xd5\xb5\x1d\ 5\xbb\xc4,$\xc5\xc7\xb6%\xd8\xe8\xf8\xfb\x16\xff?\ Fj\xf2V\xcd\xd7\xd9g\x0ez\x0dR\xfb\xa7Ce\ VH\x11\xe5\x12S\xe3\xfc&\x89,\x12\x91\x00\xa3/\ \x89\x1ca%\xe4\xc8\xcf)\xc2\xf8\xdb\xd0\x9aXf\xf6\ \xb8\xeb\x07\xf4|I\xcf\x97t\xfd\xd4\xc5\xb3H0/\ JK\xae\xe9\x16\x0e\x830a\xaa\x91)\xeb8\xad\x15\ \xd1\xb7i\x96Vxg\xf1&\xae\xd5j\xc9\xb5\x99\xfe\ U\x16;o3\xdf=\xc7|\xf7\x02\xb3\xbd\xcb\xcc\xf6\ .Ss7\xc6x\xc2\x0d\xec\x07f\x82\x1d\xeej}\ \x83\xbbZ_'\xf6\xa7Y+\x9d\xe4\x5c\xe5\xee\xf0\xaf\ z\x0f\x17\xcb\xb7\xe3\x8b\xa9a\x7f\xd7\x0dS\xf3\x06\xe2\ \x81\x19\xceM\xa7NP\xea\x987\x07\xc5\x8d \x14\x82\ ?\x84p\xc6K\xc6\x0eR\x19\xdc\xea\xfa\xcc\x96,c\ \xd0\x9e\xc4\xd7@Uh\x86\x94'\x8a\xe8\xb0!I*\ \x07\x89\xd6L\xf4\x9e\xa4v]\x90,W<\x08\x0c\x0b\ Fc\xd4\x86U\x87>\xa5=Ew\x87Y\xa2\xe3)\ a\xfe1r\x0cK\xb3f\xec\xb6\xbe\xba\x83\xac\x9e6\ l\xaae\x94k\xe3bH\x97-\xee\xf3E\x16\x8e(\ \xcd$\xec\xc6\xd9G0\x18\x16B\xaa\xfd\x0c2\xd3*\ \xcd\xf2\xd1pU\xd1\xc2\xa3\x99{\xec\xc0\xa5\xe6m2\ \xe3\xae\xe3\xf4\xd6\xe85W\x99\xf16\xa8\xfaM\xaaA\ \x8bj\xd0\xa4\x16\xb4\xa8\xfaM\xca\xf4\xb0\xa5G9\xe8\ `\xc9\xbd\xfb\xdb\x04X\xf4\xa3\xe5v1z\xa2J\x80\ \x0dH6\x1d\xc9z\x19\xca\xe5\x9b)\x95\xc3e\x80\xae\ (\xe3E\x11\x0dk\xb2M\xc5\x0a\xbfw\xc9o%\x9d\ \xa7\xe4\xb7\x11\x91*\xf5nt\x96\x14H\x8e\xf4\xcfs\ \xa4\x7f\x8e\x87\x1b_\x00)qE\x99\x8b\x95\xdby\xb3\ \xfa>\xde\xac=\xc8[\xd5\x07\xe8\x8a\xea\xf0\xc2\xbe\xcb\ 05\x02@\xc2\x9cD1\xa1\x186\x80\xc3u\xeb\xf1\ \xde\xdd\x12]q\x88\xcb\x10\xb1\xfd\x1b\xd2y\xc4}F\ \x00t}I\xc5\xce\xef#\xb6\x9f<\xc9\xa4\xfd\xeb\x7f\ \x90\x0a\x14\x02p\x03\xc9\xce>\xc5\xff\xd7!e\x96\xb0\ \x8el\xfd [\xff\xa2\xeb\xa6\x22\xa7E\x08PW\xbc\ dw\x02\x18\xaf\x82&Qv\xd8\x8a\xc8A\xce\xa4\xa3\ \x94\x05\xda\x02\x04H^xl\xcd\x08\x94\xf3\xfd\x1cf\ \x83h\xc4\x9e>\xb5T\xda\xa5\x1c\x0f\x9a\xbe\xf3D\x89\ vy\x85^\xf5(\xaf\xbb}\xbc\xd9\xd1kP\x91\x1d\ \x84\x22\x08X\x04T\x82Nr\xde\xb1\xb2\xb1\x01\x5c\xab\ \x82Oq8b\xbd1\x97\xed+\xb4ZMn>a\ \x8e\x03\xe0X\x82[\x16J\xd8\x96\xc8(aq;\x89\ \xce\xed\xa0C\xd9\xef\xe2\x04m\x1c\xafM\xd9\xdf\xa1\xe2\ 5\xa3\xdf\x1d\xca~\x83\x8a\xbbE\xcd]\xa7\xeamQ\ \xef\xaf\xe3\xf8\x9d\xdc\xf3\xae'J\xb2\xc7\xcd\x9d\x17\xb8\ \xb9\xf3<\x1f\xdb\xfc\x0fHl\xde\xa9\xdc\xc5\xeb\xb5\x87\ y\xa3\xf6~\xceV\xef\xa7\xf7= \x10L\x8d\x00\x90\ X\x00\x22\xb3\xdb0\xe4\x96\x00\xc6\x8eRj\xba\x08O\ \xe3=\xaeM\xcf\x8b\x09\xf0~\xc3\x0f$m7\xa0^\ r\xe8GfQ\xdd\xa2!#+\x86D\x86[\xd8\x9a\ l\x96\xaa#\xe4\x08D\xd5D\x10U\xa2\xa5\xe7\x13\x84\ \xab\x16\xf6\xdb\xfc\x0f\xf1\xbb\xd7*\xa0\x1f\xeb\xf7@n\ \xd7\xb0Q|\x00\xa4\xf2\xde\xa6\x059\xa1Lj\xefd\ \xe4r\x86\xdfa\x12\x86)H\xcb\xdeg\x0e\x9c\x14\xee\ \xd4\x19={\x80c\x85i\xba~\x12(\x8a\xb5\xaf\xd3\ \x83\xdd\x08\x1eE\xef\xc9t\xac\x9e\xc7\xf7\xd9\x96\xe0Z\ \xcb\x1b{\x85EO\xd4r\x0fn[\x07\xb7\xfcMU\ \x0aL+Q\xe2\xf3\xc0\xaa\xe1Z5\x04K\xc8Jz\ m\xd0\x14\x8b\x1d\xf4\xa8\xf7W\xc3?w\x8dz\xef\x1a\ 3\xfd\xab\xd4\xfb\xd7\x98\xeb]\xa2\xde_M\x22\x17^\ \x0f\x08|n\xe9\xbe\xc0-\x9d\xe7\xf9!~\x03_8\ \xbcS\xb9\x97\xd7j\x0f\xf3z\xed\xfd\xbc]\xbb\x9f\xbe\ \xa8\x0c/\xe8]\x86\xe9\x11\x00\x14\xe2\xa73(\x93r\ \x18h\x92x\x91\x990vx\x0bTb\xa0jB\x07\ \xec\x14\xa6\x9a\xd7M\x83E\xdf\xd7\xde\x90!=4\x5c\ \xcf8\x13\xa2\xbe\xbb\xd8\xd3?\xd22#u&\xfe\x8d\ sZB\xd0\xe8\x1d\xec@\xdc\x0do(\xb2d\xc4\xc8\ \xf5\x9f)c\xfe\x90\xef\xf3\xc3\xda2\xc8\xafCO\xd3\ \x8f\x0b\x86GaZz\xcd|5\xb3\xc5r\x22\x91F\ c\x8dx\x8f\x89\xd4\xb6Qh\x8d\x1b\xf0l\xc8\x0a \ \xaa\xa5Cu\x1c\x8d\x85\x91L\xfd\xf6(x\xa4\x0a\x89\ \xb2D\xd3 p\xc4\xcf\x88\xcfKv\xc8\xfc\xd7;\xfb\ \xbb\x84v?!\x0dJXQ\x7fR\xa1No\xa2\xe5\ \xf1D\x85\x9d\xca)v*\xa7\xa2gd3[\x81\xcf\ L\xff*\xb3\xfd\xcb\xf46\xcf\xb1\xd4;\xcfa\xf7<\ \xcb\xee\x05\x16\xddk\xe4\xed\xa6\xfb\x0b[\xba\x9c\xe9<\ \xcb\x99\xce3\xfc\x88\xfcu^\xa9?\xc6\x85\xea\x1d\x1c@\x9c\xd4}\xc7\xd4\ \x08\x001T\xcd\x1c\xc2\x81u\xdf\xea\xef\xf2\x03\x17\xff\ \x0d[\xd5\x9b\xd8\xaa\x9ef\xb3r\x13\xdb\xd5\x9b\xd8\xaa\ \xde\xc4N\xe5\x14\x1d{a\xecg$\xac\xf0\x00\xed\xc1\ \x8d\xbe\xcfL\xc9\xa2d\x8b\x9c\x86m\x8a\xe3\x12\xa7C\ ^\x9bQ\xdf\x8f\x0a\x9d\xd0\xeb\x9a\x8b.`\xe5%\xfc\ \xf8A\x07\xf3^\x8a\xb4\xf7A\x1a\x5c\x91\x06V\x94\xa6\ \x1e\x07\x8cfa:($\xccs\x80\x04P\xf4-\x13\ \x18\xe6\xfbU\xc7\xb9AK\x02\xf5bL\xc2\x87^\x97\ \xc1\x8e\x99\xca\xb1\xcc\xd7}\x94o\x97\xbd.\x8d\xc7j\ \xfdF\xb3\x80\xe4-\x19\x83\xac\x1b\x83\x9e\x09\xe6>\xeb\ X\xef~\xe6\x0f\xa3\x8f\xa7q\xc6\x9d\x0a\xa1e\x90\x84\ ;\xa3\xeeTO\xb0S=\xc1;\xc1\xfd\xf4#\xe7T\ Ih\xae?\xdc\xbf\xc0J\xffmV\xdc\xb7Y\xe9\xbe\ \x85p\xbe\xc9\x5c\xff\xeaH\xed\x99\x04\x1c\xd9\xe7\xf6\xce\ \x93\xdc\xde\xfe\x16\x7f\x9e\x7f\xc9\x8e\xbd\xcc\xcb3\x1f\xe4\ \xe5\xfa\x07\xf9N\xfd\x83\xb4\xde\xa5\x81\x8a\xa6F\x00\x88\ 7\x86\xb1\xa3\xbd\x00T\xc67\xd7\xbf\xca\x5c\xff2s\ \xee\x15N7\x9e\x0c/\x88\xd8EP\xf0\xcd\xe3\x7f\x87\ \xc7O\xfd\xc2\xee\x9e{\x80B\x5cL4\x02\x99vn\ \xf5\x9a)H[\xd1\xbc\xad0\xa4\x8dZ\x87\xc4\xd7B\ \xa6\xcf\x95\x12l\x0b:\x9e\xa4\xe3\x1e\xcc\xfc?\xc4:\ \xa2\xf1BF\xebJ\x99S\xea\xe7\x11\xd6_\xa6\x9e\xf4\ \x8c\xc0\xe7D1a:h\xc4s\xe7\xf1\x9fi#\xa0\ a\x0c\xd9\x98IM\x1bD\xad\xc7(\xa60\xcd\xa0\xd2\ \xa7\xdff\xf7\xefz\x90\x85cX\xfdL0\xf5\xb2b\ \xe6.3\x15\x88\xfd\x19TGR5\xa0\x97E\x18\xaf\ `\xb5\xed\xb1\xf1ng\xfe\x1a\xbd\x19\xb4\xd1\x0f\x98\xfb\ g\xd171\x09\x7f\x99\xef,\xcd\xf9\x5cQ\xe1r\xe5\ V.\x95o\x05B\xfay\xcd\xbaF\xd9\xdd\xe1\x81C\ MN\xf4\xdf\xe2D\xefu\x8e\xf7^g\xc5=w \ S\x09\xf3\xfe\x1a\x8f\xed\xfc\x17\x1e\xdb\xfe\x0c\x01\x16g\ k\xef\xe3\xf9\x99\x8f\xf0\xc2\xec\x87\xb9\x5c:\xb3\xef\xcf\ \x9f\x14\xa6G\x00\x90\xe9o\x961Jf\x87Hz\xcd\ \xd2\x91\xa1\x84@\xef\x98\xbbe\xa0{E\xcb\x0dX\xac\ \x86aLc\x93i\xa2\x91\x1b\x06\x9a\x9e6h0\x0e\ \x82I\xeb\x8f\x7f\xe3\xe9\x94\xf8\xfaA-\x02H\x98\x9f\ \xa9\xdd\x86\xbc\xfa\xb1\xa9-C5J\x85\x90_o\xb8\ \x81\xc4\x89\x9cS\xd2\xa9\x98\xc1\xb5;\xc8\x9a\x17\xcd\x83\ g\xa6\x22\x14\xa2\x1dO\xb5\xa8F\x8d\xddV8'd\ \x0c\x12&Ls\x1f\xbb\xc0\xb0\xe9\x09S\x1f\x14\x84\xfb\ f\x5ckylv\xdf\xdd\xcc\x1fB\x0b\x99]\xe0\xdf\ at,\x1drn\xba\xa6\xbf\xc7\xdd\xfajt\xedY\ \xceVo\xe5l\xed\x81\xa4,G\xf69\xd1}\x9dS\ \xbdW8\xd5\xfd\x0e\xa7\xba\xdf\xe1\x88{~\xfc\xc2\xc7\ \x80\x85\xcf\xad\x9d\xa7\xb9\xb5\xfd\x14\x9fZ\xfd\x7fX-\ \x9d\xe6\xf9\xd9\x0f\xf3\xfc\xccGy\xbd\xfe\xfeh\x15\xc6\ tbz\x04\x00\xf5O\xebis\xee`\x01\xa0QZ\ \x89\xee)\x96?\xf5\x01-\xa3\xa8|\xd6\x01nA%\ \x81\xbe\x9f]\x9d\xa0\x0f\x0aU\x10\xc8\xdc+\x07\x9f\x8f\ \xfa|\xd5\xe4\x9e1\xbf\x8b\x90\xf1\xb7\x0fP\xfbG\x9b\ k\xdc\xad5C\x15\x22 ;}P\xe4$:\x0dh\ \xf4|j\x8e\x93\xac\xffO,\x01q\x9d\xc9\xf6\xdb\xa2\ i\xa2a\xd0\xa7\x91\x8a\xe6\xb2ud\xfcf\x14\x98\x18\ \xa1z\xac\xb6E\xcf\x93\xab\x1b\xd9\xbe\x1f\xe77\xfa\xf7\ \x14\xa1\xa8BcBj'2\xd6\xf2\x95\xf1\xa2^\x17\ \x22t\xf8[\xfd.a\xfe1\xa4Tcs\xc8\xe4\xff\ \xf1\x87\x8e>\xc5\xa2z$e\xa7`\xe4\x84L\xb1\x9e\ (\xf3N\xf5^\xde\xa9\xde\x8b\x5c\x00$\xd4\xfc\x1dN\ \xf5^\xe6\x96\xce\x0b\xbc\xa7\xfb<\xa7\xba/gVW\ L\x1aG\xdcs||\xe3\xb7\xf8\xf8\xc6o\xd1\xb4\x17\ xv\xf6\x93|{\xee\x93\xbcZ\x7f\x94`\xf0b\xf6\ \x03\xc7\xd4\x08\x00\x90jg\xfa\x18\x9eu\xaf\x0d\xbc\xaf\ \xe5,\xe5\x88\xc8\xf0g\xa5\x1d\xfb \xad\x00\x81\x94\xb8\ \x8a\x10\xa0\x8e\xacA\xe63\x13\xa1\xd4n\xcf`\xfc\xf7\ \x11\x12\xbc\xce\x01\x84\xff\xdd\x0br\x82\x1c\x06-\xc4@\ \xb0S\xa7\xb1\xe9\xc10\x13y\xce\xba\xb1[mZf\ \x9dg\x8b\xae\x99\x18\xf1\xa0\x0af\x85\x89\x88\xa4k\x02\ \x86:\xbeL~\x1d\xc3\x84\x89\xfd\xc00\xbf\x86\xe4\xbc\ @\xc0\x94\x80-B\x87\xd9\xf5\xb6\xff\xdd\xc5\xfc\x81\xac\ \xdf\x05\xc6\xe3\xc1\x89\xf1\xa5\xecE!dv\x1c\xc6\xe7\ 2\xbaF8\x05=\xa33\x85+*\xbcV\x7f\x84W\xeb\x8f\ \xf0\xfb\x87\xffg\x96\xdd\xf3\xdc\xd3|\x82\xfb[_\xe1\ \xb6\xf6\x93\x94do\xcf\xcfp\xa4\xcb\x87\xb6\x7f\x8f\xef\ \xdb\xf9\x0c_]\xf8\x19>\xb3\xfc\x8f\xd8v\x8eL\xa0\ \xf6C\x9e\xbb\xefO\x18\x11^\x00vd\xb3W\xb7\x18\ \x0d\xb5\xb9\xc1C\xae\x1bm\x80!P<\xa8\xa3\x9e\xa4\ \xef7\x1f\xe7\x13Q\x1e_\x0e\xee\xcc\xfb\x02\x19.\x01\ \xab\xa9Kl\xd8\xa3U\xc2t\x83\xd2^P\x98\xbfL\ \x05 )C\x87\xa6\xb6w}T\x9aX(\x89\xaa\x95\ `\x14\x82\x13[0\x02\xf2D\xa4\x90\xd8H\xa6\xcat\ \xab\xae1\x8fM\xcd:\x8bI\xe2\x1e(\xe9I\xc8\xe8\ \x01$S\xbf^\xf4^\x0a\x1dL5\xc1QM7>\ O\xa6\xbf\xa3X3\x8a`\x0a~5\xb2 2\x01\xa8\ c\xb1d\x09Zn\xc0\x95\xa6\x87(M\xefr\xaeI\ !^\x96j\x1a\x22\x83\xfa\x0f\xe4\xfb\x90\x1a\x052\x93\ \xc1T\x8e\x08\xfd*\x0e\xd8\x08\xb9+\xac\x95N\xf1\x95\ \xa5\xbf\xccW\x96\xfe2%\xbf\xcb\x9d\xedopo\xeb\ q\xeek}\x85%\xf7\xca\x9e\xca\xb6\xa4\xcf\x0fl\xfd\ \x0e\x8fl\xff!\x7fx\xf8\x1f\xf2\xa5\xa5\x9f\xdd\xd7]\ \x0b\xa7F\x00PMJY\xcf\xe2p\xd3\x8bRP,\ e\x95\xfd\x0e=+u\xa4\x18%\x0e\xb8D`\x8bp\ ]\xbe\xeb\xcb\x03\x17=;\xaeO\xdd\x11\x08\x91\x0fc\ \xaa\xc3d\x1a5\x11\xc2d\x0aE'\x9c\x86yW\x95\ \xa8\x0b\xa0\xef]\x9f\xd5\xf1!\x03\x97\x19\x0b\x80~=\ I\x17\xa9\x00\x93X3\x12\xaf\xb34\xa34\xdd\xac\x1c\ 7\x0fr\xa9\xe3\x104\xfa\x01\x15G\x98)k\x84A\ Al\x86}5}\x19\x96\xb9,\xf3\xb1~\x9f\xd0~\ \xd3\xab\xd9/W\xe4E\x9e-1\xbd\x9e\x9b\xce\x1a \ l\x8c\x22\x88\x8c\x03\xd3x\xb1\xac\xd02\xd8\xf7%\xeb\ \x1d\x8f\xd5\xb6G\xcd\x0f\xa8\x8d\xba\xef\xceT\xc1dO\ +F\xc7\x0b\xe8\xf9V\xceqS\x18\xba\xa8:e\xab\ ?\xd1\xf4k\xca\x13C\x10*E\x8d\xbe\xd9\xa9r\x94\ 2\xae\x07\xfaV\x95\xe7g?\xc2\xf3\xb3\x1f\x01\xe0d\ \xef5\xeek\xfe7\x1ej|\x81\xd3\xdd\xef\xec\xba\xdc\ J\xd0\xe6/\x5c\xfb\x17<\xba\xfd\x19~\xe3\xf8\xbf\xe0\ |\xf5\xee\x09\xd58\x8b\xa9\x11\x00<)\xf1d\xe6G\xbb\xbe\xbbo\xac\x0b\x1b\xc5\ \xd3-\xca\x93\xa4\x9a:X\xe8\x88k\xac\x0b\x17\xa3X\ 9\xf4R\xf4Ol\x140\x94\xb4x\x9c\xc4\x1b\x869\ 6\xf4}h\xbb>\xad~@\xa3\x1f\xd7\xe5\xdd\x01\xbf\ /x\xf3O\x17x\xe7\xcb\xe1\xc65w}\xaa\xcd\xe9\ G\x1b(vOL\xadY}\xa5Fw\xdb\xe1\x95\xdf\ \xcf{\xa4\x1f\xb9-\xe0\xee\x0fw9\xf3p7wm\ \x90\x10\x96\xbb\xa4((\x92\xac\x12c\x09\xe8\xba\xd2\xe8\ S\x00\x9a\x95J\xa4i\xd3\xf6a.V\xee\xe0B\xf9\ \x0e>w\xe8\xefr\xc4\xbd\xc0C;\x9f\xe3\x91\xc6\x1f\ q\xb2\xfb\xea\xae\xca;\xdd{\x85\xff\xfd\x9d\x9f\xe1?\ \x1f\xf9'|\xe9\xd0\xdf\x9cle\xd9g\x01\xa0(\xd6\ \xb6\x09Y\x12\x92\xbd\xa7o\xcfR\xf5\x8b\xf7\xa1.\xfb\ m:J,\xe6\xe1\x1aM\xe4\xf8&C\x89w\x14X\ \x96\x85e\x09l{rf\xc0\xb6\xebSsB\x11%\ \x0e?\xaa3\xf2\xbc\x15\xc3L\xce\xf3$\xd8L\xfa\x85\ %\xb0l+)\x5c\x08h\xf7\x83\xeb\xe6\x1c\xe7\x05i\ \xc0\x99a&_\xf5\x5c\x08\xb0m;\xfa.a{\xd4\ \xc05\xa6\xe6X\x02z~d\xf1\x99\x224\xfa\x01K\ %;i\xcf\xc0N+\xb3\xbf\xc34\xa3Q\xc6\xc2^\ \xa1\xeb\x97\xb6\xed \xac\xb0-\xba5\xc0\xc4\x9c\x8b\xe2\ \xfd\x8fj\xe5P\xcbS\x7f\xf5\xf4L\xe0\x19\xe5z\x18\ \xca7\xd2@\xbb\x01\xcd~\x90\x98\xc0\xe3ob\xdbS\ \xa3+\x0d\xc4\xb5\xef\xd4\x13\xe6\x0f\xf0\xca\xef\xd7\x99=\ \xea\xb2tK\x17\xc7\x89\xdb\x92\xd20\xbf/x\xfew\ \x96X{\xb1\xd8\xbc\xb1\xfa\x86\xc5\xea\x1bu.\xbfV\ \xe2C\x7f\xa5\x91\xb96N\x9fR-\x0a(\xc7\x92q\ \xa7!E2\xe6\xe3\xe9\xb1i\xc4j\xe9\x14_X\xfe\ \xbb|a\xf9\xefrS\xf7%\x1e\xdb\xfe\x03\x1e\xdb\xf9\ \x0cu?\x1fs`\x90\x1ccK\x8f\xff\xee\xda\xff\xc5\ {\xba\xcf\xf3\x1b\xc7\xffy\xe2\xf4>\x09L\xb4W\xe7\ %\xbet\x00\x0b\x99\x17\x06\xa4\x96\x0f\xa0\xd3sq\xca\ 6\xae2\x09\xd5\xf3-|\xdf#\xeb5/\x92s\xaf\ \xd7\xa2\x87k\xee\x0aR\x95\xe0\xb3\xec1\x90\xb0\xd3\xf1\ \xb2\xe6LM\xdd\x14\xd1\xc68\xddN\x17\xd7s\xd9\xde\ \xde\xc6\xb6m\x82\xc0W\xca\xcdB\x0c\xe1\xa6j=\xdb\ %\x8b\xb9\xb2e\xdc:T\xd7\xeet\x96n\xe0\x07\x85\ \x08M\x9b\x16A\x10\xd0j\xb5\x11B\xb0\xb5\xb9\x81D\ \xb0\xda\x9a\xec\x12\x97q\xd1-\xdb\xd4K\x22z\x07\xa3\ \x89\xf4\x96m\xe3\xba.\xadv\x87\xbe\xebQ\xd9\xd8$\ \x90\x01r\xc0\xfc\xbecA\xd3\x954\x0b\xcc\x8c\x07\x8d\ \xb8\xb5\x96e\xb3-]\xdc^\x9fF\xa3\x81\xb0,|\ \xbf\xb8\x8eE\xfdbP?\x18\xdb\xf8Q\xe8\x18`H\ Sn\xb2m\x8bV\xabE\xaf\xdfcsk\x0b\xd7\xf3\ \xf0=o \x91.\x9aC\x1e\xa7\xaa\xea\xfd\xc3\xd2b\ \xd8\xd1|\xb7\xebK\xda\x9e\xa4\xed\xfa\xc9\xca\x05\xcb\x0a\ -K\x8d\x9d\x1d\xfa\xfd>\xeb\x1b\xebT+\x15|\xdf\ \x1f\xff]\x1e ^\xfb\x96\xcf\xdaZVS\xbfx\xb6\ M0\xd7\xa4\xd1h\xd0\xed\xf5X[_\xa3\x5c*\xe1\ y>g\xff\xdb\xbd^\x0f\xdb\xb2\x08d\x90U\xd5\ 3\x87y\xbdKd\x9a\x9a\x9et\xbb\x10T\xed\xf0\x83\ \x17\xe4\xd9;\xc2vY\xb6E\x10H\x5c\xcfE \xe8\ \xb4\xdb4\x5cI\xbb\x7f\xfd\xf6\xe1\x06\x08\xfa\x16~\xd9\ \xca9p\x1a\x11}+\xcb\xb6\xf1<\x0f\xdfs\x01I\ \xab\xdd\x0e\xcd\xceA`\x1c=q\xd2Fw\xfa\xd6o\ [\x96M\xdf\xedC\xaf\xcf\xe1r\x89v\xbb\x8d\xef\xeb\ \xae\x8d\x07\x07\x13C\x1e\xc4\xf4\xe2|\x96\x085\xb3n\ \xb7\x87\xe7\xf9t\xbb=\x04\x02?\x08\x8am\xc5\x83\x0a\ \x1d\x22\xc9\xe8\x82OQ\xdd\xd5s[\xe9\x5c\x1dO\xe2\ \x05\x92\x96\xebg5S\xc0\x12\x16B@\xaf\xd7\xc7\xf7\ =:\xed\x0e\xbe\xef\x13\x5c\xc7\xef2\x0a:\xed\x0a\xed\ \xb6*S^\ $T\xf6z=\x84\x10\xd1\xaa\x05\xd3\xdc\x80\xc8\xcd\x15\ H\xa1\x95\xad2z\xfdZ\xae!\x22\xf33\xb0\x5c\xc8\ u\xc4\x9e\xa8\xf2\xf8\xc2\xcf\xf0\xc4\xc2Os\x7f\xf3+\ \xfc\xf8\xfa\xafrK\xe7\x99\xe8\xb2*T\x98\xfb\xd8\x1d\ \xedo\xf1\x8f\xce\xff<\xbft\xfa\xdf\xd3\xb7j\xc6<\ \xe3`\x8f\x02\x80\x18pF\x14\x8c'\xfch\xb9w\xab\ \xdc\x91ymB\xd0\x93\x82\xb9\x92\x85/\xa39\xea\xea\ \x11J\xde\x9bq\x86\xf4\xde(\x92\xca\xb2\xd3d\xbdV\ \x0d\x07\xae^\xbaH\x9f\x12\x13\x8a\xd8\x02\xdes\xb5\x84\xb8X\xc9\xa4\x9d<\xd9\ \xe4\xc4\xc9\x16W\xaf^\xa5\xd5jr\xe2\xf8\x09\x9c\x92\ Ck\xcd\xe1pm\x19Ne\xcb8r\xbf\xcb{\x7f\ z\x9b\x13GB\xa1.\xfd~U`\x09 \xd1\xc43\ \xdfE\xc9+\x0c\x04+\x90y\x7f\x8eX\xb9\xf7\x9a.\ 3&\x03.y\xbdJ\x02\xd7V\xaf\x11\x04\x92\xc3\x87\ \x0f\xe7\xa7~d\xf6\xbet\xaaAj\xe7Y\x1dNj\ \xd7\x92{\xf4\xfcJ>\x86\xa4%\xe7\x895<\xc5\x8b\ \xf3\x1f\xe5\xa5\xf9\x8f\xf0\xe0\xd6\x1f\xf1\xa9\xf5\x7f\xc5Q\ \xf7\x5cq\x01\x0an\xef<\xc5\xdf\xb9\xfc\xbf\xf2\xab'\ \xff\x0dz,\x99qq]'\xb6R!*\xdb\x88\x8e\ '\x99)E\x0c[\x86\xbb\xfd\xa5\xf9\x84v,\x98w\ \xafF\x8ep\xa9\xb9'\xd6\xdc\x13\x0a\x11\xa5[\xd1a\ \xb3\x1f\xb9\x17)\x02b\x98-\xe5\xe2\x09\xd3T\xef\x8f\ cUG\x04E\xb9#'<\xa8\x07\x06\xd90A \ \xc3\x00#\xf5\x92\x85izz\x90\xf0P\x94&\x04T\ \xbc\x06+\xdd\xd7Y\xe9\xbd\xc9r\xf7,\xcb\xbd\xb7Y\ \xec_\xe2\xfc;g\x11\xc0M\xe2\xa6\x82\x92\xd4\x82B\ \x12Z\x93\xa1\x96P\xf3\xdb\xe0\xaf\x82\xfbv.\xabD\ \xb0Y:\xce\xc5\xcam\x9c\xaf\xde\xc3\xb9\xca=\xac\x96\ N\x0f.?B\xa3\x1f\xb0T\xb3\xb1E\xb1\xb2\x98k\ c<\x0f\x18i\x06E\xb0,\x81'%\x1d_\x22\xc4\ tm\xc6\x11CD\xe6\xe8\x96'i\xb9a_\x10\x22\ \x8e\x13\xa1\xeb\xb9j\xaf\x1bd\xe4NSM\xc2D\x91\ \x80\x91\x7fZ\xf6\x1e=\x9f\xe9\x89\xa1\xd0jE\xdf%\ \x15\xae\x87.\xe1+\xb8^\x94]\xef\xf3\x91\xa2\x88\x15\ ]q\x03\x89/%\xad~\x80\x00z\x9e\xe2b8\xc2\ :\xc28\x8fe\x89L[\xa6\x15\x22\xf2URaE\ \xe3#\xa6W\x96%BZ\xe9\xda\xb9\xbc\x00\xc7\xdf\xdb\ \xc7\x99\x09h\xb9\x82C5\x9b~ \x8d\xdf\x5c\x08\xa1\ Y65\xc5E+\xd7\xca\x5c\x0b\x85\x01K\xc0\xb5\xb6\ \xa7\xd0\xd3\xfc\xcd\xe6\x9e\x1e\xce\xfe\x9b\xbea\xa6_J\ \xdag@$\xccA\xc9\xa3d\x96\x8aR\x17\x9eg\ y\x0aaQa\xdd\x15\xe5\x22m{>M\xbf\xa8N\ \x0f\x87\xecI\xf0\xed\xf9\x1f\xe3\xd9\xb9O\xf2\xf1\xed\xff\ \x97\x9f\x5c\xfb\xd7T\x02\xdd\xca\x92\xc7C\x8d/\xf2C\ \x1b\xff\x9e/\x1e\xfa\xdbC\xf3\x0e\xc2Tz\xb6H\x09\ \xdb=\x9f\xf9\x8a\x0d\x02\xb6K\x83C$.\xf6/\xc5\ \xb2\x9dRH\xf8\x93\x10\xca\xf8\xdc\x82\x86\x1b\x06\xa0\x19\ \xabNA\xb4F[\xca}\xd9\xcf\xa9\xe5\x86\xa6\xeb\xba\ ciK!\x0b\xea\xa3\x1c\xc7\xfds\xc1\xbd\xcc\xc9\xf6\ \x8b\x9cl\xbf\xc0\xd1\xcek,\xf6/iw\x08\xfc\xc0\ '\x08\x02\x84\x08M\xb3\xb6e3\x88\x94\x8f\x03\x81\xe4\ \x90{\x89C\xee%\xeeo~\x05\x80\x1d\xe70\xaf\xd7\ \x1e\xe6\xb5\x99\x0fp\xb6\xfa\x00~\xc1\xd6\x98\xbe\x0cC\ $\xcf\x94l\xd4\xf5\xc3z;\xd5s?\x08\xf0e\x10\ \x9a\x985\xa8-\xb2\x05l\xf5\x83\xa93\xfd\xab\x08|\ \x9f \x9a\xc2h\xf6\x03:\x9e\xa4^\x12\x94-\x91\xcc\ Ug#\xebI\xc3\x9cjV\xc3I/\xe4\xadH\xa6\ 7\x113\xc6TW\xca\xbe\xf1T+*\x22\xf2\xe1\x99\ \x1f\x84m\x09d`\x8c\xc3\x11gU\xbf\xb1\xfem\xd5\ %\xaa\x99\xa6\x88\xf0=\xd8\x11/\x8e\xaf\x07\x12\x82 \ \xbc\xdev\x83p\xfaP\x08\xba\x9e\xdc\xd3w\xf7\x83\x00\ )e4%\xf3\xee\x83\xda_\x82 @\xca\x80 \x08\ \x18\xe4\xcb\xecT\xc2\xb6\xb6]\x89c\xfb\xcc\x96l<\ \x99\xef\x07\xea\xb9\x89I\xab\xd0\xad;\x12\xa2e\xd8\xe1\ \xde(\xe3 \x89\x97!\xb3\xfb\x9a\xbc\x9b\xe1\x89\x12_\ <\xf4s<=\xf7C\xfc\xad\xcb\xff\x94\xdb[O\x0e\ \xbd\xe7S\xab\xbf\xc4\xd3s?\xccZ\xe9\xd4\xd0\xbcE\ \x98J\x01\x00BS\xddN\xd7g\xbej\xb3U\x1e\xdc\ \xc0\xe5\xde\xdb\x85s~q\xc0]\x0b\x81e\x85\x0e?\ ]7\x98\xca>\xd3v%R\x06\x94m\x11J\xcbC\ T\xb4\xaa\xdf\xe0t\xfb9nj=\xc3M\xadg\x98\ u\xd7\x86>C\xd5a\x0e\xe2\x15\xcc{k<\xdc\xf8\ \x02\x0f7\xbe@\xdb\x9e\xe7\xa5\x99\xef\xe7\xe9\xb9Or\ \xadts.o\xdb\x95\x08|j\xa5p\x8aE]\x1d\ \x00Q\xb3\x15)[J@\x86\x0e=\xba\xff@L\x17\ ,\x11\x06r\xe9{\xbbg\x02\xbb\xc5\xe5\xe7f\x00x\ \xe3\x8bu\xba\xebf\xb1\xf1\xb6\x1f\xfd\xff\xd9;\xf3x\ I\xaa\xf2\xee\xffNUW\xef}\xf7}\xb6;\xcc\xc2\ l\xcc\x023\xcc\x00\xca\xaa\x04\x14\x10\x10\x90\xc5\x05\xd1\ \x18\xd4\xbc\x8a\xc6\xe8Kb\xa21!\xd1\x18\x8d\xc4\xbc\ \x09!\x86(j@\x85\x80\xec\xb2\x0e\xcb\x0c\x0c\xfb\xc0\ \xc00\x1b\xb3\xde\xb9\xfb\xd6{\xad\xe7\xfd\xa3\xba\xba\xab\ \xab\xab\xaa\xab\xb7{\xbbg\xea\xfb\xf9\x0c\xdc\xae:u\ \x96Z\xce\xf3\x9c\xe7<\xe79)\xf8[dx\xdb\xa5\ \xbc\xe7!+\x141\x9e\x82e\x08\x02\x1eut\xe4!\ \x04\x1c\xab\x86i\x95\x04\x82#;\xfcHN\xb2\xd8\xfe\ {_A\xbe\xa1\x0e\x05k.R\x9d\xc1\xfaONi\ \xab%\x01X\x8f\xc2s})\xc1\x81\xd7\xd4\xf9\xc57\ \x1f\xf2#1f^\xf7\xb5\x1f\xe3\x11j\x95\xd1\xbe@\ D\xa4C\x82\xf6F1\x84d#l\xea\x07\x98\x07^\ \x0b`\xcb\xcf\xd5ef\x8b? \xe2\x94Kc\xe0|\ 93\xf2\xc1\xd7\x02\x18\xde\xcba\xef\x0b9\x8f\xf4P\ \x87\x82\xb5\x17\xa5\xd1\xbd\x84G\xa0I\x15L,\xa3\x8e\ \xe4\xf94\xc1\xd1w\xfc\x18x\xcb\x87\xc1\xed\xb9\xae\xac\ \xb9_\xc6\xbc\xd3Rh_\x94\x867l/\xb8\x07\xb7\ \x87\xb0\xe3\xae0\x00\xa0o\xa3\x80e\x1f\x9d\x02\xeb\xa5\ y\xe7\xf7\xbc\xac`\xd7`7\x02\x01\xf5\x9e\xf8\xda\x15\ ,9?\x99\xc9?\x7fJI\x16\x08Fv\x061\xf4\ \xb6/\xcf\xb3>\xbfN\xce\xa7\xa1\xb4\xfc&\xde\xf7\xe2\ \xe8\xb6|\xef\xef\x05g\xf3\x88\xf4\x8a\xe8]\xe3t\xe3\ \x1a\x82\xf7\x9fm\xc6\xaewz\xe0\xf5Z{\xfd\xbf\xf9\ \xf3&\x00\xea\xaa\xaa\x8eU\x22\xd6^\x98\xc2\xdc~\x09\ 2\xcdm\xee\xa4I\xf1\x5c?kA\xa6\xaf\xd2\x9b\xdb\ \xb5w9)RL\xa5\xcb\xf7?\xaa\xc3.\xbcb\xc6\ \xb8\xb9\xf8\xa7yw\xe2\xea\xe1[p\xce\xe4\xafl\xd3\ r\x94\xc7\xe5\xa3?\xc2\xed}\xff\x5cvyu\xab\x00\ \x00\xaa\xf9.\x9a\x961\xe1\x9bo\x9b\xae;\xb5\xdb\xf4\ \x0d\xd44S\xd5\xe4\xa5:\x18\xce\xd6zw\xa7\xa4$\ \x0a^\xa6h\xf22`\x19\x02E\xc9\x8d\xc7\x8cV\x8d\ \xab\x0e\xfe\x19\x9a\x85\xca\x22O\xcd$A9\x8a\x0d\xd1\ G\xb0>\xfa\x08\xf6\x07V\xe3\xa5\xe6\xcb\xb0\xcf\xbf6\ /MB\xa4\xa0\x90\xe1c\x19\xd5\x11\xd4\xf0\xb8\x8aZ\ F2\xe7YF]U\x10\x13d\x083\xf8\xcce\x81\ \xe0\xd0\x8b\x11\xec}\xd4\x99\x83\x8e\x96.\x95bA\x16\ \x8dc\xc3\xc7\xf3\x85\xad\xacP\xc43k\xd1Y\xa2\xbe\ \xcb{\x9e\x89`\xcf#\xf6\xf9'\xc6\x18l\xcd\x08\xdb\ \xad?\x0fb\xedUI,>\xbdHHm\x9e\xc1\xde\ \x17B\xd8\xf1\xa03?\x8e7u\x8a\xc7\xd2\xf3x\xac\ 8?\x0e\x8fO\x81 \xd3\xbc\x7f\x14\x14\xf11OV\ \xf8\x03\xc0\xde\x178\xf8[\x83X~^\x1c\xa3\xfb|\ x\xf9\xae\x10\x92&\x8aFb\x8c\xc9\x5c\x17\xc4\x9a\xeb\ \xe2\x98\xb36\x09\x02`\xe0\x1d\x7fFP\x152}\x80\ \xc5\xf4\x810\x800V]\x13\xb7\x14\x90\xc9q.+\ \xfc\x01\xe0\xe86/\x82m\x11,<+\x8a\xc9\x03~\ \xec\xf8]\x04GvM`|\x9c\xc7|]\x17\x94\x1e\ c2\xd7\xe5\xe7?\xfa^\xa0\xe2:\xe9\xd1+'f\ \xa8\xcb\xfd|8\xfcb\x00\xcb?\x16E\xa4\xd7~5\ \xcf\xc4~?\xf6>\xe2\xc1\x82B\xdd\xdb\x92\xb1\x1d\x1c\ ^\x893h\xf9\xea\x04\xfc\x1c\x03\x0fQ#\xf6\x19\xe7\ \xcaM\xd1\xfa+\x9d\xc2\xc92\xea\xd2\xdf\xc9\xb4\x8c\xf4\ ,E\x1f\xadw\x14\xc2\xe2\x7f\xba\xff\x1a\x09\xa6\x09\x17\ \x8d\xff\x9bm\xda\xf5\xb1G\xf1[\xe9fLy\xba\xca\ *\xab\xae\x15\x00@U\x02\xde'\xf6ol\x8bp\x14\ \x9c\x92\x80\xc0\x84\xf2\xcc\xf3lF\xf3\x14d\x0a^R\ \xd0(\xef\x9bBs\x11\xe2\xbcLn\xae2\xe7$\xa8\ \xfe\x7f\x7fh=\xd6\x0a\x0f\xcdR-\xcb\x87\x008!\ \xf5\x16NH\xbd\x85\x83\xfeUx\xaa\xf5\x93\x18\xf0\x9d\ \x98=\x9f\x14)xIF\xd8\xc7d\xf7\x077\x93\xe1\ \xd9Q\x05t\xca^FiH\x892\xd2\xf2\xcc\x86\xfd\ \x15\xe2,\xde\xfcU+\xa6\x0f\x94\x17+\xe2\xe03~\ \x90\xe9\x08.\xfc\x16\xc9\x1b\x85j\xc8\x14x\xf5\x17\xf6\ k\xb6\xadx\xf3\xb7A\x1cy\x97\xc3\xea\xab&M\xf3\ V\xeb\xdeRv\xddw=\xe9\xc3\xf0>\x0fN\xb9a\ \x1c\x89\xb4\x8ci^F\x80\x97A3\xdb\xe5\x8e\x1e)\ \xcc\xf7\xf0\xdb\x1c\x10\xf6\xdb\x0a9=\xdb\x7f\x1d\x86\xac\ \x00R\x9a1\x0dXc\x86\x96\xb7\x99\xc0M\x8c\x16v\ \x7f\xa3;\xbd\xf0\xb5\x84\xf0\x8e\xc3:i\xf9W\xabN\ \x1a\xef\xdc\xd7Z0\xe2\xb7b\xfa\x00\x8b\x97nm\xc5\ \xaak\xacc\xa5T\x02\x1f#\x98\xe6\x95\x8co\x0a\x81\ \xdfc\xae\x9c[B\xd4\xefR\xa6j\x14\xce\xa4X\x7f\ \xb18\xea\x91\xdfw\xde\x04\x8e\x0a\xf8\xa3\x89\x9fY\xa6\ a\xa8\x8c\x0d\xd1\x87\xf1D\xdbg\xcb*\xa3\xee\x15\x00\ \x00\x18c\xbb\x90b\xc2\x08P\xf3\x0f\x86\x80\xa27\xbd\ \x07\x87Ck\xf3\xe6\x14\x05Y\x9d_\x12e\x9a\x8dz\ \xd7(\xa8B\x8c\x82g(\xbc\x8cjR\xf52Lf\ \x17A\xb5}\x07\xc3\x1b\xb0v\xb2\xf1\x14\x00=\x0b\xd2\ ;\xf0\xd9\xc1\xff\x8b\xb7\xc3g\xe3\xc9\xb6\xeb\x91`\x9a\ \x01\xa8\x9d\xc5tZU\x82X\x02p,\xc9Z>\x08\ \x90u\xde4\xfa\x0d%E\x05\x822;\xf1\xfe\xdf\xb9\ \xbf\xb9l\x01\xaa1\xbd\xdf\x83\x91\x9d\x01S\xe10\xb8\ =T \xfc5\xd3\xb2>}r\x9c\xc3\x91WBy\ \x01a\x00u4wh\x9e:\xc2\xadI\xdd\x0f\xb0\x18\ \xd9\x19Dha\xe1\xbar\x89/\x1c\xdd\xe7F\xc5\xce\ q\xaa,\xe8\xd9\xfbx\x10]\xcb\x93\x05\x8a\x8fU\x9d\ \xa6\xf6\x87K\x9a\x22\xacf\x9d\x00`\xff\xb3M\x8e\x85\ \x7f)\xf5h[\x98\xc6\xaak\x81\xd8\x16\xe7y6\xf7\ \xcbXr\x81\xaaXH\x0aE\x94\xa79E\x80e\xf2\ \x9c\x9c\x8d\xfe\x1c\xda\x94\x1d/\xab~\x18)\xc9\x15\xfc\ \xa5r_\xe7\xd7\xb12\xf1|^\xcc\x00#\xcb\x93[\ \x8fm\x05\x00\x00\x0e\xfbW`i\xca\xda1\xa2'\xb1\ \x03\xfb\x03k!*\xeaH_\x1d5V\xbaHb\xf6\ Q\x14 \x9d\x11f<\x93\x9b;d\x09\xc1A\xffJ\ \x08\x8c\x1f^\xa50Dg\xb5\x10\x18\x1f8E@-\ \xe3m\x11\x00\xab\xe3\x9b\xb18\xf5*\x9el\xfd,\xb6\ \x87\xcf\xcd\x9e\xe33s\xf7\xac\x0ch\xdd\x8a\xdf\xa3\xfa\ x\x8b\x0a\x85\xa8P\x08\xbc\x92]C<[\x8e~\xc9\ q\xcetd\xde\xb1JD\xcfI|\x81@\xb7\x9b*\ \x18z\xdbg\xaa\x00\xec}\xbcp\x84\xb9\xea\xcai\x04\ \xdb\xf3\xb7\xcb\x0e\xb6\x8bXz\xc1\x14\x22\xbd\x85&\xe4\ \xa9\xc3\x85\x9f|\xb5\xeb\xbeha\xc1\xe1\xa2\x18\xcd\xe2\ \xc5\xcc\xdf\x80:\x07>wC\x22\xdb~\xabk\xd2\xe3\ \x0c\xa2G}h\xed/\xed;YuM\x1c\xde\xb9\xc3\ \x18\x1b\x1f\xc7\xfc\xf9>L\xed\xea\xa8y\x9db\x83^\ \xcb\xe9#3eop{\x08\x87_\x0c8V\xde\xfa\ \xd6\xc4\xb1\xe0\x92!p\x9c\x17\xb1A/^\xba\xb5\xb5\ \xcd\xda\xeb\xa3\xe8\x5cf\x1d\x1b@\xf3OI1T\ s\x8b\x87\x97%\xf0\xb2j\x14K\xc2\x00\xbc\xa4\x80\x97\ (\x18\xa2n{M\x91[\x0a\xe7\xe2\x1c\x99x\xf0`\ \xc7\x97\xf1\xc5\x81\xafX\xa6\xe9\xe5\xdf/;\xff\xc6Q\ \x00|\xcbm\x15\x80\x05\xb1W\xf0x\xd35\x85\xcb\x82\ \x8e!\xf4\x8e\xc82(\x04\x99\xc5\xbe\xc0:,O\xbc\ XR>\xd3\x9e\x0eLr}\x18\x8b\x9c\x8a\xa8\xb7\x17\ 1\xb6\x1dQO\x1bRl\x13\x04\x12\x80\xc0\xf8!\x11\ \x0e<\xc9\x178\x1c\xe5\xe1S\x92\x08*QD\xe4\x09\ \x84\xa5\x09tHG\xd1*\x1eE\x0f\x7f\x00-\xd2P\ E\x0aWP\x8e\xe3\x92\xb1\x9f\xe2\xc4\xd4\xcbx\xa8\xfd\ KH2\xb9\xf9T\xbd`Od\x84\xbd(\xaa\x1e\xf3\ >_e\x9e\xde\xd5\x80\x8f\x15v\xc0\x8b/L\x99\x8e\ \xb6\x01\x80\xf5R,<+\x0a1\xc5\x98\x8e\xd4e\xa1\ p\x1a\xc0\xcc\x91\x90\x8f\xb1\x05\x0a\x80F\xef\x9a\x04\xd2\ Sl\x9e@\xe99\xa9pO\x8dj\xd7\xbd\xff\x82\xd2\ \xde\x82\xf57N\x17\x08B\xb3\xba\xeb\xc9\xc5\xb8wv\ Mz\xba4\xeb\x86V\xa7\xf1\xf1\xc2\xfc\xad\xfc/\xaa\ Q\xa7\xc1\xed\xe6\xd3\x08\x1d\xabD\xd3\xe9\x9b\xde5\x09\ \xf4\xaeI\x944eP-\xf4Q\xfb$E\x8d\xa4\xa8\ \x87f\xff\xe3R\x09\xef\x84\xce\xb4=\xdf,\x8f\x96\x9d\ w\xc3(\x00\xef\x07\xd6\xe2\xbc\xa9;-\xcf/N\xbf\ \x0e\x02\x05v\xdb\xff\x1c\x8b\xec\x09\xac\xb7T\x00(\x80\ \x09\xae\x0f\x03\xbe\xa58\xea[\x8can!\x86 G1'\ \xbd\x1b\x03\xfee3S\xa1\x1a[\x17\xf4kk\xed\xd8\ \x1b<\x05\xda\x1ej\x000\xc1\xf5b\xbf\x7f\x0d\xde\x0f\ \xac\xc1!\xffJ$\x0d1\xa3\xd5=\x0c\xc6Mr\xaa\ \x9c4\x13\xc2\xde\xc0)\xd8\x1b8\x05O\xb5\x00M\xf2\ 8\x96'\xb6bU\xe29\xf4\xf1{K\xca+,M\ \xe1\xda\xa1\xef\xe1\xd9\xd6k\xb0\xa5\xf9\xe3\x15G\xbc\x9a\ \x09\xe6m\x8cY\x0a\x01=\xb1A/\xe2#\x1cb\x83\ \x9ce\x87o\xc6\xe2\xf3\x93\xa6\xe6dUp\xab\xc2\xbb\ o\xa3\x80\xb6\x13T!\xaf\x99\x8a#\xbdBQ\x0f\xf1\ Z\xd7\xdd\x8a\x8e%\xd6\x9d\x9b\xbf\xd9|\xb9\x5c\xf7I\ \xd6\xd7hk\xd8+\xa1}\x89\xf5\xbd\xaae\x9d\xf8\x98\ yw\xbc\xf8\xc2T\xd1\xa5\x83\xac\x97Z\xbe\x1f\xc7\x12\ \xc7\xa3A\xa1?\xbd\xdd\xf6|\x94\xed(;\xef\x86Q\ \x00\xe2l\x1b\x06\xbd'\xa0W\xb0\x1eU\xaeL\xbe`\ \xab\x008\x15\xaa\xf5\x82\x93\xfa&\x98f\xbc\xd0\xf2q\ Lyz\xb0\xdf\xbf\x1a\xd3\x9e\xce\x99\xa8\x9a#\xa2l\ ;\xb65]\x8cmM\x17\xa3W\xd8\x87\x8d\xd1\x07\xb1\ \x22\xb1\x05,u\xb6\xf6\x97\x81\x82s&\x7f\x8d9\xfc\ \x1e\xdc\xdfy\x13xRy\xec\xeb\x99f\xf4\xbd@\xd6\ \xd9\xac\xd2\xceY\x13\xe8v\xf9\x1c\xdd\x96[/\xbe\xe3\ \xaep\xd9\xeb\xcf\x81\xea\xd6\xdd\x0a\x7fs\xe9\xeb\xc0\x03\ \xad\xb5\x0d\xe7l%\xe4\xed\xa8F\x9d\xccV%\x00\x9a\ \xd5\xa18\xe1.g\xe9f\x82r\x04u6X\xd0,\ H\xf9zV,6D\x1f\xb5=?\xe0[Rv\xde\ \x0d\xa3\x00\x00\xc0\xce\xd0\x19\xb6\x0a\xc0\xba\xd8\x93x\xbc\ \xed\xf33X\xa3\xfa`s\xcbu\xb3]\x85\xa2\x0cz\ \x17\xe1\xfe\x8e\x9b\xf0\x5c\xcb'p\xee\xe4/\xb1,\xf1\ \xa2celi\xf2e\x5c?x3\xee\xee\xfa\xcb\xba\ Rp\xcc\x10\xe2,\xc6\xf79_\xdaV*\xbdk\x12\ h_\x94\xc6\xc0k!G\xb1\x06\xf4\xeb\xcf\x17_\x98\ \xc2\xfc\xd3b\x96\xa6\xe4Z\xd7\xbdZx\xfc\xf5\xb7\x9e\ \xb7\x96ur\xaa\x90\xf8\x22\xf5\xb1\xcfE=\x0b\xd3F\ #(G\xb1>\xf6\x88m\x9a]\xc1Me\xe7\xdfP\ \x0a\xc0\xbb\xc13p\xaeMt\xa4>~\x0f\xba\xc4\x03\ \x18\xe1\xfag\xaeR.%1\xe1\xe9\xc5=\x9d\xdf\xc4\ \xbc\xa6\x9d\xb8h\xec\xdf\xd0!\x1eqt]\x97p\x10\ 7\x0c}\x13\xbf\xe9\xfa\x0b\x1c\xf5\x96\xaf\xf1\xd6\x12'\ \x9e\xeb\x80\xea,\xe6\xf1+Y\xd3\xb0U\xf0\x18+\xbc\ a\x19\x0b\xcf\x8af\x03\xd6\xa4\xa7YG\x9e\xe0{\x1f\ \x0d`\xea\xb0\xc7\xd4\x99l\xa6\xea\xee\xe2\xe2\xe2\x9c\xf3\ '\xee\x80O\xb1^\x91A\xc1\xe0\xd5\xa6\x0b\xca\xce\xbf\ \xa1\x14\x80\xdd\xc1\x0dH3a\xf8\x15\xeb\x80\x17\xeb\xa2\ O\xe2\x0f\xed\xc7\x9f\x15\xa0\xd18\xec[\x8e\xdb\xe7\xfc\ \x18\x1f\x9c\xfa-\xce\x98\xfe_0\xb4\xf8\x08*,M\ \xe1\xd3C\x7f\x85{;\xbf\x81=\x81\xf53PK\xe7\ X\x09Pm)]\xf3\x5c\xc1\xd4Io\xf4\xbd\xca\xa6\ 54g5mz@\x9b\xa37\x86\xa2\xd50\x8b\x05\ 0[uw\xc9\xc7\xe37\x1f;\xa7\xa7YD\x0a7\ \xbb,\xc0,\xaeA\xbd\xe0.\x01,\x9d&i\x0c\x1f\ \x9a\xfco\xdb4\xfb\x02\xeb0\xe9\xe9)\xbb\x8c\xfa}\ cL\x90\x08\x87\x1d\xa1\x0f\xda\xa695\xf6Pf5\ @yX\xed\xc3\xecR}dp\xd8\xdcr\x1d~\xd9\ \xf3\xb7\x88z\x9c9\xb2pJ\x1aW\x8d|\x1f\xab\xe3\ \x9bk[\xb9\x121[\xa3\xbf\xe0l\x1e\xeb>9\x81\ \xde5\x09\xcb\xa5z\xa5t\xda\x93\x07\xfcx\xf9\xb6\x0e\ <\xff\xc3NL\x1e0\x0f\xd7\x1b\xe9\x15\xd0\xbb&\x81\ u\x9f\x9c\xc0\xa6\xafN\xc2\xdf^\xf8-\x8c\xee\xcc_\ .6\x13uw)N\xa8\xc3\xfc>\xc7\x87\x9dE~\ \x9c>2\xb3\xcb\x00]j\xcbG\xc7\xff\xddv\xf4\x0f\ \x00\xcf\xb7\x5cYQ\x19\x0d\xf7\x05\xbf\xdat\xa1\xe1H\ \xbe\xc0\xee\x10\x8f`Ebk\xed+R,&\xbd\xc5\ o\xbby\xef\xe3UK>\xe4[\x81\xdb\xfb\xfe\x19\xbb\ \x83\x1b\x1c\xa5g\xa8\x8cK\xc6n\xc5\xc6X}DA\ \x8c\x0dzM\x97_u.+\x1ex\xe6\xf0\x8b\xceF\ \xd1B\x9c\xc5\xab\xb7\xa9\xd1\xfa\xd2\xe3\x0c^\xbd\xad\xd9\ R\x09\xd0\x88\xf4\x0a\xe8?\xd3\xbe\x0e3Qw\x17g\ x\xc32\x9a\xfb\x0b\xe7\xf1\x8f\xbc\xec\x83\x10/\xbe\x8c\ \xb1\xd1\x9f\x87U\x9fYR\x1e\x15t\xa1Z\xc8u\xb3\ ,f\xbag\xee\x10\x8f\xe0\xcc\xa9\xbbm\xd3Lp}\ \xd8\xd6tIE\xe54\x9c\x02\xf0n\xf0\x0c\xc4\xd9\xc2\ \xe8Uz\x8a\xdd\xb8\xd9\xa4\xd4\x17\xe9xQ\x09RL\ \x18\xbf\xed\xba\x19\xcf\xb5\x5c\xe5\xa8\xcd\x04\xc0\xf9\xe3\xff\ \x85\xd3\xa7\xef\xadu\xd5\x8ab\x15d\xa6\xd8\xc8m\xff\ \xb3M\x96\xf3\xf6\x89\xb1\xfck\xcd\x82\xf5\xec\xf8]\x04\ \xc9q\xfb2\xa2G\x0bg\xf9Z\xfas\x9e\xf73Q\ w\x17\xe7\xcc;\xadp\xc4\x97\x1eg\xf0\xce\xfd\xcd\xb6\ \xd7\xd9=\x8fF\xa4&\xfd^\xfe\xce\xf0\xb3\x83\xc3\xe8\ t\x97\x8c\xfdK\xd1\xf5\xff\x8f\xb5}\x1e\x12\xa9\xec[\ k8\x05@&\x1e\xbc\xdct\x91m\x9a\x13\x93\xdb\xd0\ )\x1e\x9e\xa1\x1a\x15\xe1x\x91\xe0U\x80\x82\xe0\xd9\x96\ kpO\xd7\xb7 0\xce\xd6\x98\x9f7\xf9\xcbYW\ \xf8B\x9d\xe6K\xd9\xde\xbb/\x88\xfd\xcf6A\x16r\ \x1f\xbd,\x10\x0cn\x0f\xe1\xe5\xdb:l\xbd\xf8\x8d\x02\ \xd8\xcc\x0c\x9f\x1eg\xb0\xe5\x87m8\xbc\xadP\x11\x88\ \x0dz\xb1\xfb\xb1\x16\xd3\xe8p\x91\xde\x5c^3Qw\ \x17\xe7t-O\x9aN\xdb\x8c\xed\xe0\xf0\xf2m\x1d\xd9\ -\xa65F\xdf\x0b\xe0\x8d_\xb59\xde}\xb2\xde\xb0\ \xea\x1e\x1bi\xb9v\xb5\x99\x97~\x0f\x9b\xa6\x1f\xb0M\ 3\xe9\xe9\xc6\x0b\x15\x9a\xff\x81:w\x024[\x07O\ \x01\xbc\xd0r\x05\xce\x99\xfa\xb5\xf9KB)\x08\x01>\ 4\xf9\x0b\xdc\xdd\xfd\xed\xbcS\xc5^*\xa7q\x02\x8c\ \xe9J\x8d/`\x97\x9eR\x9a5E\x1d\xaf\xbc\x17\xdc\ \x84X\xcf\xdf\xe2\xea\xe1[\x10\x94\x0b7\x961r\xe6\ \xd4o\xd075\x1f\xcf\xb7\x5c5\x03\xb5+$\xd8.\ \xa2\xb9_6\x1d\x81\xed}4`\xdb9k\x9d}\xca\ \xb0\x18bl\x0f\x87y\x1bs\xbfY/\xc5\xb2\xcb\x92\ \xa6;\xce\xe9\x03\x01\x15\xa3\xb9_F\xd7\xf2dU\xeb\ n\x9cB\x18\xdb\xc3\xa1\xb7\x84-g]r\xb0^\x8a\ UW\xc6\xf0\xeam\x85#~mI\xa7\xddj\x0d\xab\ g9S\x98\x9a\xcf\x1d\xd8\xe5\x8b\xa5\xb0\xca\xc2\xaa/\ 5M\x9e\xddN\xbd\xfcz\x16\xa3h\x16\x0e\xca\xb8b\ \xf4\xfbE\xfd\xd8~\xdf\xf9U\x08\xc4\xd9\xb6\xddv4\ \x9c\x05\x00\x00\x86\xb9~\xec\x0a\x9ej\x9bfC\xf4a\ \xb4\x8b\x83y\xc7\x9c\xec]mzj\x06G\xf1\xb5\x12\ \xfe\x8d\xe6\xdc8\xe0]\x82;z\x7f\x80\x09\xae\xcfQ\ \xfa\xb3\xa7\xee\xc2\xa6\xe8\xefk\x5c+kV]Y\x5c\ Q1\xd2\xb7Q\xc0\xc6/N`\xd9\xc5\x85\xabZ\xb4\ \xfd\x00\xf4\xcc\xdb\x18C\xdfF\xfb\x88~v\xf8\xdb\x15\ \xac\xba\xb20\xa4l-\xeant\x10\xb4\x8a\x86g\xb7\ \xc6\xdd.\xf4\xad\x15Vk\xe1\xcd<\xec\xeb\xb1N\x80\ \xba\xb2\xa3\xd4\xad}\xfd\xed\x0a6}u\x12\xa1n\xe7\ \xb1\x00\xf4m\xa1T\xf7\xaf\xa4\x92\x8bSN\x9fV\xab\ \xde\xaa\xde{\xc1\x95\x89\x17\xb0\xa2\xc8\xde.\x03\xbe\xa5\ x\xb1\xf9\xb2\xaa\x947\xa3\x0a@\xb97\xdfL\x00?\ \xd5\xfa\x19\xdb\x1cY*\xe1\x82\x89\xff(\xb3\xc4|\x8c\ \xefo-\xc7\xe7\x94\xd2\x02M\xb4\xde_\xdaZ1\xe9\ \xe9\xc6\xcf{n\xc1\xb0\xaf\xdfQ\xfa\x0fM\xfc\x1c\x1b\ b\x0f\xd7\xb6R\x16\x04\xdbEK\xaf{#\xfev\x05\ k\xaf\x8fb\xe5e\x93\xf0\x86et.Ka\xc1\xd9\ |A\x1a3V^6\x89\xb5\xd7G\x1d\x95\xa3g\xc1\ \xd9<6~q\xc2t*a&\xea\xde<\xb7Pq\ \xf1\xb7+\x96+\x0c\xb4z9\xcdK\xc3\xca\x91\xce,\ \x9a\x9eU\x9dB\xc5\xea\xd4Q\xbb:i\xf4\xaeI`\ \xfd\x8d\xd3\x8e\x9e\x89\xa6\x8cEzsa\xa0\xf5X)\ 4\xe5\xdc\xdfR1\xeb\xcfjA)%\xd4k\x7fJ\ @q\xe9\xe8O\x8a\xa6\xbb\xa7\xf3\x1bPP\x1d+\x0f\ \xbb\xfe\x93_\xff\xaeX\xe6Njs\x9b\xf2\xe7\xfa\x06\ b\xe6/4\xd16oG\xbe\xf0$\xf9\x89\x0a\x8f\xe9\ ~\xeb\x850\x010\xee\x9d\x8b\xb5\xf1g\x10\x91'\xd4\ #D\xb7;eX\x8bB\x00\x00 \x00IDAT\ |\xe6\xef>a\x1f\xde\x09\x9f\x99]bF\x08)\xc8\ /oO\xf9\xec\x1e\xf3$\xfb\xb7F:\x95\x82,K\ \x08\x87\xc3 \x0c\x93\xdd\x93^\xbb\xd0\xac\x9e\xd9\xfa\x1b\ \xean\xd6N#VZs%\xca\x07\x01\x81B)\xa2\ \xd3Q\x10B\xd0\xd4\xdc\x04\x860\xa0\x99\xdd\x04\xea\x11\ \x91\xf1\xe3\x9d\xd0\x070/\xbd3\xb3\xebU\xee]U\ \x14\x19\xd1h\x14\x1e\x8f\x07MM\x11\x10\x00\x8bR\xaf\ #\xea\xe9\xc0\x90\xf7\x84\x19\xaf\xab/\x22c\xc1\x19I\ \x04:\x01O\x10\x88\x1d\xc9\xffH\x17\x7f$\x85\xbe\x0d\ \x85PG\xfe\xdc{s\x7f\x1c\x13\x13I\ \xf0Ca\xf4\xae\xf4c\xd5\x95Q\x04Z\xcc;\xeeP\ \x87\x84\x05g$\x11\x99\xab\xa0c\xb9\x88\xe8Q\x0f\xa4\ d\xe1\xf3\xd3\xca[~i\x14\xdd+R\xb6\xa3\xd7J\ \xea\xde\xbe8\x0dI\xe60\xb5\xdf\x83\xe6\x852\x96|\ l\x14\xb2g\x1a\xa1p\x04~\x9f\xea\xcb\xc1z)Z\ \x17\xc9\x98\xd8\xef\x85\x94$h^(\xdb\xb6Q\xa3u\ \xa1\x84\xd8\xb0\x17\xe9IFU>>\x1dES\x9f\xbd\ \x80jY(\x22\x15\xf5 1\xac\xb6a\xedg\xa3\xe8\ X\x5c\xb8\xaa\xc1\xaaN\xfe\x16)\xfb=$SI\xa4\ Si475\x83\xe3\xb8\x9a\xd7IO\xa0E\xca>\ \x93@\x07\xc5\xd4\xfe\xfc\x19\xdbe\x97'\xd1\x7fV\x12\ \x0bN\x8bg\x9fm\xa4G\x84$q\xd9\xb4\xab\xae\x89\ \xa3kY\x0a\x14@<\x1e\x87(\x8ahni\x06\xcb\ \xaa\xf5\xe8X&b\xfa\xa8\x17\xfc\x14\x83\xe6\x852\xd6\ }f\x1a\xa1\xf6\xd2\xc23[\xbdU\xc5\x04\xbf\x9d\x99\ \xbe\x18\x89D\x02\x94R\x84\xc2ak\x0bC\xb5%}\ \x8d4\x07\xf5>\x11\xacIl\xc6\xf9\x13w\xd8\xa6\xdd\ \x19:\x1d\xbf\xef\xbc\xa9*\xe5r,\x01\xb9\xf1\xd1#\ 4)\x96\xb7n~\xd3\x9c\xfcy\xc7m\x03\xc9\xbc\xdf\ \x14\xaa=\xa9\x16\x0a\x00!\xc0\xea\xc4f|a\xe0k\ \xc8)\x00\xd0\xfd\xad\x96y\xc8\xbf\x0a?\x99w\x87*\ \xe2L\x14\x00@g\x06\xb1Q\x00&'&\xc0\xf3i\ tww\x83e\xd9\xd2\x14\x00\xdd\x1f\x96\xed7\xc1\xce\ tV\xaa\xb8\xd6\x84\xbc\xac\xc88|\xe80\x08!\x98\ ;o.X\x86\xadk\x05@\x83S\xd2\xb8f\xe4\xef\ \xb0 \xfd6\xb4\xd6\x8b\xa2\x88\xc3\x87\x0f\xc3\xe7\xf3a\ \xce\x9c9\xd9\xb4\x0a\x18\xdc\xdf\xf95\xbcS$fD\ =\x91J\xa5p\xf8\xf0a\xb4\xb6\xb6\xa2\xb3\xb3\xbe\xc3\ \x1d\x9b\xa1\x7f\x87\xa2\xd1(\x86\x86\x86\xd0\xdd\xd3\x83\xe6\ \xa6\xc6\x8b\x14\xa8o\xcb\xd8\xf8\x18&\xc6'0o\xde\ <\x04\x02\x81\x82\xf3\xf5\x8eVW\x0a\x8a\xa1\xc1!$\ \x12\x09\xcc_0\x1f^\xae:1\x03\xca\x15\xfe\xfak\ \xa9\xc9A\xfd1j8F)\xc5\xc8\xc8\x08\x14EA\ Www\xde\xf2\xbd\xbc\xb4\xd9\xbfi\xf67\xb5\xc9[\ \xab35;\xa7\xab\x9f~:\xd58eb\xac\xab\xb1\ \xadzs\xb6\xf6\x97\xa2(\x00\x08n>|\x0d\x16\xa5\ \xde(H\x97K\xcf\xe0\x96\xfe{q\xd0\xbf\xd2\xb4\x8c\ R\x09rLc\xfa\x00h\xbc\x1d:\x0b\x07\x02\xabl\ \xd3\xccO\xef\xc0\x19S\xf7\xd8\xa6\xb1|\x89\xcb\xacW\ \xb58^\xe3\x02\x98!2~\xfcO\xd7\xb7\xf1~\xa0\ \xf8\xf6\xc0\x0c\x14|l\xecV,N\xbd6\x035s\ qq\xa9\x0a\x15tw\xd6}xy\x99:\xe9z\xab\ \xd9=\x9f\x90~3'\xfc-x\xa5\xe9#Y\xe1_\ -\xeaz\x15@1(\x08\x1ej\xfb2\xfet\xe0K\ \x99#\xe6Z\xf9G\xc7\xff\x1doG\xceA\xd4d#\ \x19K=\xde\xcc\xbd\x94\x90\xbc\x87Nin\xc4\xaf%\ \xd7\x1f+\x96\xad\x93\xd5\x03V\xab\x02\x8e\xc7\xe53\x12\ \xe3\xc7o:\xff\x02W\x8f\xfe=\x16\xa6\xde\xb2M\xcb\ R\x09W\x8c\xfe#~\xd9\xfd\xb7\x18\xf0-\x9d\xa1\x1a\ \xba\xb84.\x1e%\x8dVi\x18\xad\xd2\x10\xda\xa4!\ 4K#\x08\xc9Q\x84\xe4)\x04\xe4ixi\x1a~\ %\x01\x02\xd5\x22G\xa0@`\x82\xa0P\xb7\x02O1\ M\x88\xb1\xad\x88z\xda\x11gZ1\xce\xf5a\xc4\xbb\ \x00\xe3\xdc\x1c(\x86\xb1\xa6\xe9\xe8\xdf\xe6\x98\x93\xb3v\ +\x05J\x85\x10\x93\xfcj8\x1e;o\xf2N\xdb\xf3\ \x14\x0c\x1e\xea\xf8r\xd5\xcb\xadk\x05\xc0\x890{/\ \xb4\x09\xbb\x83\x1b\xb04\xf5*\xacD\xaa_\x89\xe3\xaa\ \x91\x7f\xc0\x7f\xf5\xfd\xc8Q\xae\xa6&>bL\xa3?\ d-\xca\xb3gtIJU\x02J\xa5^-\x1a\xd5\ @d|\xb8\xbb\xf3/p\xdd\xc8\xdf\xa0W\xb4W\x02\ 8\x85\xc7\xd5\xc3\x7f\x87;z\x7f\x80I\xceA0u\ \x17\x97\xe3\x84\xa02\x8d\xb9\xe9]\xe8\x16\xf6\xa3[8\ \x80na?Z\xc5!\x10\xb3^\xc2T\x1a\xaa\xf8e\ u\xb5B@\x8e\xa3\x15\xc30\xebe$x0\xea\x9d\ \x8f\xa3\xbe\xc58\xe8[\x81\x03\x81\xd5\x88\xb2\xed\xf9\x89\ \xac\x84\xf7,uZ3Yn@\x89am\xec)\xdb\ 4/7}\x14\x83\xdeEU/\xbb\xae\x15\x00\xa7\xc2\ \xf1\xb7\xdd7\xe3\xe6\x83W\x83\xcd\x8b\x9cD\x01\x9a\x9b\ \xc8_\x91x\x01\x1f\x9c\xfa-\x9eo\xf9\x84m\x19\x95\ \x08\xe4\xa2V\x00\x8b\xcc\x8b\x95i\x9c\x0a\xb0\xf3\x0d(\ \xfa\xde\x1a\xb4\x0f;M\xbc^\x11\x19?\xee\xea\xfa+\ |B\xf8\x0b\x10r\x18jC\xcc[\x10\x94\xa7q\xed\ \xf0\xdf\xe0\x8e\xde\x1f \xc9\xdaGS\x9bM(\xa0Z\ \x98\xd0X\xcfBO\xde\xbbD\xf2\x8f5\x1a\xb9z\xab\ }H\xc1\xdc\xf1\x8c\xd7\xa8|(\x80Vq\x18\xbd\xf1\ '\xd0>\xf1*Ng\x93\xe8\xc1h\x09\x19\x14k\xad\ \xfd\x90\xc3\x03\x11\xbd\xc2>\xf4\x0a\xfbpJ\xf41\x00\ \xc0\xb0\xb7\x1f;\x83\x9b\xf0v\xf8l\x8cqs\x0cW\ \xd8\x97P\xd6\xbd\xa7\x85\xd7\x99\xcd\xff\xdb\x95\xeb\xf4|\ \xa9\xf5;9\xf68\xbc4mk:~\xbc\xeds%\ \xe6\xea\x8c\x19U\x00\xaa9\xd2\xd5\x0b\xd9an!\x9e\ h\xfd\x0c.\x98\xf8\x99\xed5\x17\x8f\xfd\x0b\xf6\xf9\xd7\ \xe2\xa8\xffDs!m\x22\x89\x8b\x0b\xe7\xe2\xd1\x1d\xf3\ \xf2\xc8\xfc\xd0^\x92r,\x01\xa5(\x04\xc7*<\x13\ \xc4]\xdd\x7f\x8ds\x0e\xed\xc3<\x0c\xda\xa6m\x13\x07\ q\xed\xf0\xf7\xf0\xcb\x9e\xef\x81gB\xb6i]\x5c\x8e\ \x05\xbcJ\x1a\x8bR\xafcQ\xeau\x9c\x90\xde\x8e\x16\ q\x18CcCH$\x93ho\x9d\x07\x94\xed\x04\xe8\ D\xbc\x99\xa41\xf4Y\xaa\xe5a?\xce\x9e\xba\x0b\x83\ \xde\x13\xf0v\xe8,\xbc\x11\xf90\x12\x8cC\xa7Q]\ \x9f\xa7w\xfe\xcb\x96np\xd6+\x17\x02\xa3\xf2Qz\ \x9e\xc5\xaeX\x13\x7f\xc6\xf6\xfc\x9e\xc0z\x1c\xf2\xaf(\ \xb9\x5c'4\xb4\x13\xa0\x9e\xc7\xdb>\x87Q\xef|\xf5\ \x87\x856\xc7R\x11\xd7\x0f\xdd\x8c\x901|\x0b\xfe\xec\xd0\xa7p\xe5\xc8\x0f\ pr\xecq\xb4\x88#e\xe6HM\xfeU\x83|G\ \xaa^~\x1f\xce\x9f\xb8\x03_?\xf4i\x5c2\xf6S\ t\x0a\x87\xb4S\x86\xd4\x95\x97_\xea\x88\xbe,\xff\x81\ \x12\xd22T\xc6\xf2\xc4\x16\xdb4[\x9b/-\xa3\x16\ \xce\xa8\xeb)\x00\xa7PP\x88\xc4\x87\xbb\xbb\xfe\x12\x7f\ z\xe4F\xdb\x07\xd0.\x0e\xe0\xb3\x837\xe3\xb69?\ \x85\x5cd#\x85B\x07<\xe7\x8f\xd6\xd62\xe0\xd0I\ \xb0R\x0a\x95\x00M\x7f%9ss6M#)\x0c\ \xb9\xbaF\xd9v\xfc\xba\xfb;\xf86~\x82\x90\x12\xb5\ \xb9\x06X\x92|\x05\x1f\x1e\xbf\x03\x8f\xb5}\xbe\xd6\x15\ \xac\x88\xc6U\xde\xf4\xf5\xce,\xcd:f\xdbR\x1f\xed\ j\x95Fqb\xf2%\x9c\x98|\x09\xf3\xd3\xef\x82)\ \x08!\x9b\xff}\x13\xd4\xe2{7z5\x19O\xdb\xdc\ 7\x9d\x7f\x01G\x05\xac\x8f=\x8aS\xa2\x8fbwp\ =\x9ej\xfd4\x06\xbd\x8b\xad\xb3j\x10\xcb\xa7\xd1\x8a\ \xa0g\x1e\xff.|JJ?[\x9d\x87BX\xbc\x11\ \xf9\xa3\x9a\xd5\xed\x98\xb1\x00\x00\xc0\xee\xe0\x06<\xdd\xf6\ \xe9\xa2\xe9\x16\xa6\xdf\xc4'Fn\xc9~\x0c\xce>\x05\ \x9bywC\x06E\xad\x00\x06e\xdaL\xeb\xac\x8f\xee\ \xa51\x98\xe0zqw\xf7_At\xb0\x81\xd0\xc6\xe8\ \x83X\x1f\x7ft\x06j\xe5\xe2R\x1bB\xca4N\x8d\ =\x8c\xcf\x0d~\x13_9\xf2y\xfc\xd1\xc4\xcf\xd0\x9f\ \xdea\x22\xfcg\x02\xbdB\x91?\xb2\xcf\xfe+Hk\ H\xa3?G)\x08(NL\xbe\x8c/\x0e\xfc\x1f\x5c\ 5\xf2\xf7\xe8\x10\x07\x0a\xaf\xd5eaV\x1b\xab\xdf3\ A)e\xf6\xa7w\xd8\x9e\x7f\xdf\xbf\x16\x89\x1a\xfa.\ \xd5\x9d\x05\xc08\x026\x1b\x11\xdb\x8d\x92\x1fj\xff\x12\ \x16'_\xc3\x02\xfe]]\xe2\x8c\x07\x88Nc<9\ \xf6\x07Ly\xba\xf1H\xc7\x17\x0b2\xa7Y\xb7\xfd\xdc\ \xef\x5c\x90\x08j\xea\xc5\xaf\x8e\xf8\xf3g\xf6\xb5\x97S\ \xaf\xa8\x16\xf8\x03d\x92\x17\x8e7\xcc_\xa4\x8a\x1d\x14\ u\xf9R\xc3\xb9F@\x7f\x87\xb3#2Jp\xc4\xb7\ \x14\xf7v|\x03W\x0d\xff=\x18b\xdf\x11^0v\ ;\xc6\x17][\x1a\xa9U\ \xc6\xb6@\xf7\xcd\x18\xcf\xd7\x9an\xe1 \xd6\xc6\x9f\xc4\ \x9a\xf8S\x08(\xa5m\x10\x04 ;\xfa \x996\x10\ B\xb2\xdf\x8bYC\xa6<]\x98\xe0z1\xe9\xe9\xc1\ \x04\xd7\x87\x18\xdb\x8e\x18\xdb\x82$\xd3\x8c\x04\xdb\x0c\x99\ x \x10?d\xa2\x8a\x0eN\xe1\xc1R\x11\x1c\x04D\ \xa4qD\xe4\x09D\xa4q\xb4\x89G\xd1-\x1e@\x0f\ \xbf\x1f!%\xb3\xd9\x94\xd5\xc2z3+\x81N\x19`\ (\xc5\x19S\xf7\xe2\xa4\xf8f<\xd2\xf6'x+|\ v\xb6\x1d\x84!y\xc2\xbc w\x8bsN(\xcc/\ w\xa4\xd2\x99-M\xe9\xef\x10\x0fe\x7f\x9bq\xd8\xbf\ \xbc\xb2\x82\x8a0\xa3\x0a\x80Q\xf0\xe5\x09:\x93\xd1r\ \xd1\xfc\xf2\xae\xd14Z\x821n.\xee\xec\xf9\x1e>\ \x7f\xf4\x1b\xaaYL\x93\xe6T?\x0eV\x8f\x9d?\xfe\ 30T\xc6c\xed\x7f\x9c_\xc7\x02\xa9\x9e\xd3\x08T\ \xa5Z\x8d\x16\xa0\xafs\xee\xa5\xa0y\x01\x82\xb2\xf54\ \xb6\xdf`\xea0\x0b/\xead\xb4Q\xf0.Zh\x1d\ \x84\xe8\xf2\xd3{\xd16\xd2\xf0,Cv\xd4lP\xd4\ ^\x0f\x7f\x18Ay\x1a\xe7M\xfe\xc2\xf6z/Md\ \x96\x07\xfe\xb0\xa6&6'\xa8m\xa1y\xcf\xa5Q\xa7\ \x80\x88\xfe\x0f}_\xde`\xef\x17\xa0\xfb^\x0d\x1e\xe7\ \xb5\x86\xa5\x22V\xc5_\xc0\xfa\xd8#\x98\xcb\xbfWq\ \xd9D\xfb\xf0\x91\xff\x18\xa6\xd9\x0e\xec\xf7\x9f\x84A\xdf\ b\x0cr'`\xd8\xd7o\xbeJ\xc6f\x08+\x12\x1f\ D\xe2C\x1a@\xcc\xdbf\x9a\xbcI\x1e\xc7\xc2\xd4v\ ,L\xbd\x89\x85\xe9\xedh\x96F\x0bF\xfb\xea\x9fv\ \x8a\x00\x10\x91\xc6q\xf5\xc8-89\xf6\x07\xdc\xce|\ \x06S\xa4Mg\x05\xa0\xc6+\xf3\x8c\x1c\xf9E\xd0\x5c\ :'\x0a\x82\xc1\x04P\xb2\xf0/4Fdi\x17\x07\ le\xde\x90wa\x89\x85\x95FU\x15\x80\x82\xfb\xa2\ \x99b\x0c\xcf\xda\xe4Q\xe9\xae\xc9\x1d\xb3\xfc\xec\x0al\ 2\xb4\xe0\xf8+\xccz4\x85>\x87KFo\x85\xde\ \xf5%\xf7w\xee\xd8\xc6\xd8\xad\xe0\xa7\x06\xf1@\xc7W\ \xb2B]{{\xb4\x87\xa3n\x06$crr\x12,\ \xcb@\x91MLp\xc5BGU\xf2\xe6\x94p\xca\xea\ \x02\x96a\xa1(\x0a\xe2\x89\x04\x08!\x18\x1e\x1e\x06!\ \x0cdYB\xe3\xf4\xd0\xaa4aY\x16\x92$\x22\x99\ LB\xe0\x05\x80\x8c\x80R\x05\x8aB\xf1;\x9c\x0e)\ \xfa\x22V\xc77\x17\xc9\xeb(\xce\x18\xb9\x09\xbf\xea\xfe\ \x1e$2\x1b\xc605\xe0\x14\xc32\x10\x04\x01\xa94\ \x0fLOC\x92$\xc8\x92\xdc`J\x00\xcd\x8c2Y\ \xa4\xd3)\xf0i\x1e\xe3\x13\x13H\xa6\x92\x90ey\xd6\ \x02\xba\x94\x07\xcd\x8c\xf8\x09\x92\xc9\x04x\x9e\xc7\xc8\xf0\ \x08\xbc>oM\xdb\xd2&\x0d\xe1\x94\xe8#X\x17\x7f\ \x12AYuh\xb5_\xe0\xea\x0c\x86a@)\xc5Q\ >\x88=\x9e5\x98\x90\xcf\xc0@p-F\xd1\x09\x88\ P\xff\x01\x00\xa2\x99\x7f%`\xdbm\xa8'\x07\x01\xec\ \xc2\x0a\x00+\x00\xeeZ\xccU\xde\xc3\xea\xf8f\x9c\x94\ x.\xbb\x22\xcb88R\xa1\x05\xbf\x19\x86\xa0\x8d>\ \x8a?I\xff\x01\x0f\xb6\x7f\x09\xef\xb1\x97\x83\x10u\x93\ \xb3\xfc\xa2\xcds4=N\xf2\xe5C\xbe\x16[\xca\xf1\ \xfcs\xd9/\xe3N\x80~\x9a\xca(\x94\xaa\x22\x96\xa7(\ S\x8a4\x13\x06\xc0X\xf6\xfd\xd5PCg\xd5\x090\ O\xf3q\x12R\xaf\x84L\xb5\x9b#\x13\x0e\xff\xdd\xf7\ }|\xe1\xe8\xd7\xb04\xf92\x0a\xa5b\xbe\xfe\xb5 \ \xfd\x0e\xbev\xf8\x06\xfc\xaa\xe7o\xb1\xdf\xbf:\xe7>\ \xa0P\xf5\x01+\x0a\x90\x19Ag\x9f\xa7\xc1\x0a\xa4\x7f\ \x01\xb3\xfe\x09\x99\x84\xbaKLW\x09\xd85K\x8f\xa3\ ;e\xf2\x86(\x94B\xa1\x0a\x08%\xea\xa8\xb3\xc1F\ gzdE\xce\xb4\xc7\xfc\xcbK0\xcd\xb8\xab\xeb\xdb\ \xb8a\xf0\x9b\x16\x0e\xa19\xce\x9d\xb8\x13#\xdc|\xec\ \x0an\xacQm\xedQd%\xf3\x8eY\xf4\x22\x0d\x84\ \xac(\xa0\x94BQ\x1a\xbf-\x8a\xa2@\xa1\x80,+\ \xf0T\xa1\xb7l\x91F\xb01\xfa N\x8e=\x06\xbf\ \x92,~\x81\x03Rl\x18\xef\x06?\x80wB\x1f\xc0\ \xfb\xfe5\xa0\xba\xc1\x94\xfe\xfe+\x99\xe7\x22+J\x9e\ Sc\xb9\x94\xfbh\x0b\xa2\xf6\x01\x18\xf0-\xc5\xafz\ \xbe\x8b\x05\xe9\x1d8\x7f\xe2\x0e,H\xed(,A\xe7\ \xf6\xaf(\xb9\x80g\x11y\x02\x9f?\xfa\x0d<\xdbr\ %\xfe\xd0\xf6\x05H\x845\x9dw7+W\xff\xdbn\ Ia1\x07\xc0\xe2\xd1\x92K\xbf[2aK\xbe\xa6\ T\x1a6\x14\xb0\x19V\xfbt\x8b\xf0\xe2?{\x7f\x84\ /\x0f\xfc)\xfa\xd3\xdb-jB3:\x08A\x934\ \x86\x1b\x8f\xfc\x1f<\xdd\xf6I<\xd1\xf69(\x84\xc9\ \xe8\xa0\x99\x97\xce\x90\x83\xde\xc9\xa9@\x11\xc8\x13\xf2z\ \x0d\x90d\xd3[N_\xd9\xb6\xb5<4\x01\xa3-m\ \xa4\x0d\xac\x00\xe8\x9d.\xad\xee\xc7\x90\xb7\x1f\xf7t}\ \x13\xd7\x0e}\xd7v\x9d4\x03\x19\x1f\x1f\xf9G\xfc\xac\ \xef\x9f0\x5cc\xc7\x1b3\xb49L\xddX\xa7a\xd1\ \xbe\x91c\xa1-\xd9\xe7B+\x0b,;\x97\xdf\x8d\xd3\ \xa7\xff\x17+\x92/\x80\xa1\x95\x9b\xde\x150\xd8\x1b<\ \x05o\x84?\x84\xf7\x82\x9b\x8a\x065\x03\x90\x1d\x1dW\ \xda\x96R\xb1_\xab\x9f/X\x0f\xf8V\xe1\xf6\xde\x1f\ ce\xe2\x05|t\xec\xdf\xd0,\x8f\x182\xc9\xb6\x22\ \xfb7\xa1\xeaT\xca\xd9SwcA\xfa\x1d\xfc\xba\xfb\ \xbb\x98f;\x1c\xbf\x7ff\xca\x80\xe5\xc9\x12qT\xbe\ \xc5\xd8\x97\xa5\xe6K=\xab\xf9\xecf4\x10P\xd1\x07\ \xa2\xeb\x04mN\x17=f\x96\x81@\xfc\xf8\xf79\xff\ \x82\xbd\x81\x93\x91[\x07k4\x10\xe5LB\x0cd\x9c\ 7y'\xbe|\xe4F\xb4\x8bG\x01h&\x1a\xb39\ \xa1B\xd3\x91\xbe*\x9avI\x0b\xde,jzO\xf4\ 14\x0a\xaf+\x8f\xbc,\x08\xc9{\xe3\x1a\xa9\x93\xa6\ \xc6\xbf\xf3\xa6q\xcc\xd9\x1dX\x8fG\xdb\xbe`~c\ u\xff|J\x12\xd7\x0e}\x17Ay\xba\x86-\xb0\xa1\ \x91\x951\xc3\xefF\x9b\xf7\xd7c\xfcV\x08!\x86\x99\ h\xa7(X\x9e\xd8\x82\xcf\x1f\xfd3|a\xe0\xabX\ \x15\x7f\x16\x8c\x22\x17}\x0f\xed\xfe\x0dq\x0b\xf0x\xdb\ \x0d\xf8\xd1\xbc_\xe0W\xdd\x7f\x83wB\x1f\xb4\x15\xfe\ \xb9\xd1\xaf:J\xa9\xd5s\xb1\xab\xb6\xbe.\xd4\xe4\x97\ >\x9dvtG\xe8\x03\xf8\xe7yw\xe0\x85\xe6+t\ [\x09\xe7,\x00*\x86\xe1\x1e\xa5X\x98z\x0b7\x1d\ \xfe,\x16\xa5_\x87\x15\xf9\xf7\xc4\x90\xa5C\xf2\xfa!\ \x8b\xbe\xbf\x18Rfz\xc6\xea\x910\x90J\xcc\xb1t\ \x1a.\x0e@\xa93\x05\xfa\xd1z\x9a\x04q{\xdf\xad\ \xb8~\xe8/\xb0\x22\xb9\xc5\x90a\xee\xa5RC\x00\xab\ \x87\xe6\xf3;\xf1\xf5C\x9f\xc6}\xec\xa5x\x22\xf8\xf1\ \xec\xa8\x9e\xe6\xec\xfb:?\x01\xe4/\xb53\xa9G\xa1\ \xd9_\xaf\xf4X;@VK\x09P\xf3!\xd9\xfa\x96\ \xfb\xf2\xce&\xb4\xe0\x8f\xe2\xf7\xe7\xa5\xa6K\xd0)\x1c\ \xc4\xa9\xb1\x87m\xd3\xb5J\xc3\xb8v\xe8\xbb\xb8\xa3\xef\ \x1f!\xa3zs\xbe\x8e \xb9\xe7\xd2\x88\xe4W\x9b\xe8\ \xde\xb7\xc6\xc3t\x5cA\xed\xcfkxi\x0a'\xc7\x1e\ \xc7i\xd3\xf7\xa1\xad\x88\xff\x89\x13\xd2$\x88\xed\x91s\ \xf1z\xe4\x8fp\xd4\xbb\xc4Y%t\x14k\x8b\x196\ ;\x00\x97U\x9e\xd9\x99b\xf7S`\xfcx\xb8\xfdF\ \xbc\x11:\x17W\x8e\xfe\x00=\xfc\xfb\xd9\xd4\xd9a\x18\ \xa5\x86\x0e\x92\x22,M\xe2\x0bG\xbe\x86?\xb4\xdf\x80\ \xa7Z?\x0d\x8a\xc2X\x01\xc5BT\xd3\xec\x7f\xb4a\ Za\x9d\x8bQ,\xa9H|P\xc0\xaa\x8e\x9f&\xf8\ \x94\x14\x07\x91\xb5\xe6\xf3;q\xd9\xe8\x8f+Z\ u\xe1r\xfc\xd1,\x8d\xe2\xfc\xc9\xff\xc27\x0e}\x0a\ \x1f\x1d\xff\xf7\x8a\x85\xffQ\xdfb\xfc\xbe\xe3\xab\xf8\xe1\ \x82_\xe3\xa1\xf6?\xcd\x17\xfe5\xc6l\xe4\xee\xbc\xff\ 1?S`\x1d\x80y\x9fe\xec'\x07|K\xf1\xd3\ 9\xb7as\xeb5Yk@\xde\x9e\x06TwE\xd6\ \x82+\xe1\x82\xb1\xff\xc0\x0dG\xff\xbc\xc0\xa2g\xe5\xf8\ \xa7\xfd\xae\x16\xe6\x13\xcd\xf9e\xc4<\xf6\x0e\xbfMR\ \x09\xdb6\x97\xc1\xacX\x00\xccF\xc8\xc5\xd2\xd8]S\ \xcc*\xa0\xbf\x96Ru\x83\x85\xdfv\xdd\x8c\x11n\x01\ .\x19\xffW\x9d\x06\x96\x1d\xa7\xe7\xcd\xebk\xea`\x8f\ \xb0\x1f\x7fr\xf4+\xd8\x1d\xf9 \x1ei\xbf\x11#\xde\ \x85\xd9K\x0a\xea\x9by\xca\xfa\xd5\x82\xa6\x8e\x82\x96\x07\ \x0a\xfd\x06\xac1.\x9c1C\xad!\xcd&\xd7\xef=\ \xef\xe4\x89\xd4\x0b\xb9\xba\xaauW\xa7\x00\x9c\xdc%\x19\ ,\xee\xea\xfa6n\x1c\xf8\x0a:\xc4#\xb6i\xd7\xc4\ \x9e\xc64\xdb\x89\xc7\xdbn\xa8\xac\xba\x0e\xc9ug\x8d\ \xaav\xe8\x9f\x8bqiT\xa3a\xf8\x1e\x081t\xdc\ \xf9\xe7\xfb\xf8\xdd8c\xfa>\xacJ\x1f\x02\x01\x7f\xcd\xcb\xab6\xfa\xe7\x22\ \x8a\x22R\xa9\x14\x82\xc1\x00\xbc\xde\x19\x9eF\xa9\x02\xfa\ \xb6\xf0<\x0f\x9e\x17\x10\x0e\x87\xe1\xf1\xb0\xba\xf3\x14'\ &\xb7\xe1c\xa3\xb7\xe2\xfc\xc9\xffF\x8f\xb0\xbf\xa2\xcd\ x\xa2l;\x9ek\xbd\x0a\xf7t\xfe9\xde\x8c\x9c\x87\ \xa8\xa7\xa3\xe2v\xe4\xea\xaa~\xf7\xa9t\x0a\x92$#\ \x14\x0e\xabq4\x8a][\x81\x96P\xae\x90\xb4u\x18\ \xa4\xc0\x94\xa7\x1b\xafF\xfe\x08\xa1\xd8^t\x0b\x07\x10\ \x08\x042\xd3\xb5\xf9\xc2\x9f\xea\xac\x02\x01%\x86\x0d\xd1\ G\x10c[q\xd8\xb7,/o\xb3\xd1\x7ff\xbc\x07\ \xa3\xab\xa4f\xb5\xb0\xab\xafy#s\x89\x8c\xfd\xec\xea\ \xf83\xe8\x16\x0e\xa8\xe7LF\xb1\xfb\x82'\xe3\xb0\x7f\ \x85\x83BJ\x87c\xc9\xec(\x00\x803%\xc0\xa9\x02\ \xa0\x9d3U\x00t\x17\x1a\xaf'\x00\xc6\xb8\xb9x=\ \xfca\xf4\xf3;\xd0\x22\x8d\x98V\x8e\x10\x02\x81\x17 \ +\x0a\x02\x01\x7f6p\xce\x1c~\x0fN\x9b\xbe\x1f}\ \xfc\x1eLr\xdd\x98\xf6tY\x96W\xc0,(\x04\x80\ \xfa\x02\xab\x0a\x00A(\x142]5\xd1((\x94\x22\ \x99H\x82aY\x04\x83\xce\x14\x00\x00H1\x11\x0c\xf8\ \x97bu\xfc\x99\xa2\x1e\xd9K\x93/#\xea\xe9\xc4Q\ \xc3\xb6\xa4\xd5F\x92e$\x92I\xf8|^\xf8}\x8d\ \xa7\x00\xe8\x11E\x11\xa9t\x1a\x81@\x10\x5c\x15\xd7\xce\ \xcf\x06i^\x00/\xf0\x08\x85\xc2`Y\x16\x1e\x088\ %\xf6\x18\xae\x1c\xf9~v\x10P\x09\x83\xbeE\xf8C\ \xdb\xe7p_\xe7\xd7\xb1\xdf\xbf\x06\x02\x13\xa8R\xcd\x0b\ I\xa5\xd2\x90$\x09\xe1P\xd8\xd12\xc0ZXo\x9c\ \x0aP\xa3\xe0W\xff\xa7\xfe!\x12\x1f\xb6yNC\x82\ i\xc2Ix7cu\xd1\x0b~C\x0e\x94\x82\x81\x8c\ \x95\x89\xe7\xd1.\x0e\xe2\xbd\xe0\xc6\xec^\x06\xc6\xf2\xa8\ \xe1R\xa7\x98Mc8I7\x8f\xdf\x85E\xc9\xd7\x00\ \xe8\x14\x00\xddM\x19\xf1\xf6\xe3\xdd\xd0\x07J\xaf\x90\x03\ 8\x96\xd4\xb7\x13\xa0\xd94\x00`-,\xf3\xacA(\ \x5c\x12h\x9c\x0a\xd0\xac\x03S\x5c\x0f~:\xe7v\x5c\ 8\xf1\x9f8o\xea\xce\xcc\x94\x80a:@_\xae\xe6\ x\x02u\xf9\xc9\xca\xc4\xf3X\x99|\x01G|'\xe2\ \xa5\xa6K\xf1V\xe4l\xf0$\x94\x17\xe8\xb0\xc0)P\ 7E\xa0o\x9b\x91J\xc4\xb3i\x9e\x06\x93Y#/\ \x03\xd4S\xea7\xbb\xcf\xbf\x16\x0f\xb6\x7f\x19\x97\x8d\xfd\ \xc46\x1d\x01\xc5\xa5\xa3?FH\x9e\xc4\xe6\x96k\xca\ \xaf\xa0\x034\xb5\xb71\xcd\xe69\xa8\xc5\xdf\x8d\x0bA\ H\x9e\xc2\x99\x93\x8faS\xf4A\x84\xe4\xa9\x8ar\xa3\ \xd8\x1d<\x15[\x9a?^\xf3\xdd\xde\x0a\xa8\xca\x14\ @qr\xbd\xa7\xc99\x9b\xc2\xed\x04\xbfvH\x9b\xfa\ \xdb\xdar\x05\xe2\x813\xf0\xe9\xe1\xbfF\xab8h\x22\ \xfci\x81e`C\xf4!\xcc\xe1w\xe1\xbf{\xfe\x01\ #\xdc|\xe7\xed1\x9b\xce\xc8\xd6\xcf\xa6\x0dvy\xa2\ x\xac\xff\xfe\xf4[e\xe5\xed\x94\xba\xb6\x00\xd8\xa55\ \x93[N\xa6\x02\x0a\xcb\xca\xbc\xa8\x84`Op=\xde\ \x0bn\xc4\xa2\xf4\xf6\xdcG\x9e\xc9L\x10\x04P*\xc3\ \xef\xd3,\x00\xb4\xc0d\xd3$\x8daEr\x0b\xce\x98\ \xba\x07=\xe2\x01\x00\xc0\xa4\xa7\x07\x8aN\xdb,E\xdc\ \x96*\x9b\x9d$\xa7\x94\x22\x99L\x02\x84 \x18\x0c6\ \xf4r-E\xa1H\xa6\x92`\x98\xd2,\x00\x1aG}\ K\xe1S\x12\x98\xafm\x1dm\x01\x01\xc5\xa2\xd4\x1b\x08\ \xcaQ\xec\x09\xaeG-\xec5\x92,#\x99L\xc2\xeb\ \xf5\xc2\xef?V,\x00\x81\x86\xb7\x004\xc5\xf7\xe1\xec\ \xa1\x7f\xc7\xa7\x13\xff\x0f'\x8a\xdb\xe1\xa5\xe9\xb2\xe7\xcc\ Dx\xf1Z\xe4B\xdc\xd3\xf5Mlm\xbe\x1c\x13\x5c\ o\xd5\xebk\x05\x85\xba\x9f\x89$I\x08\x85B%\x07\ \x02*GB8\x9dB\xb0\xf2\x87\xd2\x04\xbf\x99R\x90\ N\xa7\x01\x00|x\x1e^\x8b\x5c\x88^~o\xc6\xaf\ G\xa7\xdeP\xe3\xdf*\x11y\x1c\x1bb\x8fb\x98[\ \x80\x11o\x7f\xbeBd\xa6tX\x08\xfaJQ'\x9a\ \x15\x9c9\xf5\x1b\xf5\xb7I_\x1c\x91'\xf1X\xdb\x17\ \xf2\x83;U\x89\x99\x99\x02\xc88\x9c\x91\xec\xdf\x86S\ &\x7f\xab\x07\x8a\xfb\x02X)\x01\x85\xd3\x03\xc5\x95\x00\ \xed\x7f\xd3\x9e.u\x85\x00a\xd0\x9f\xde\x01&\xb3\xef\ \xb6(\x88P\x14\x05~\xbf?\xa3\xd0\x10\xd3<\x00\x80\ \xa5\x12z\xf8\xf7\xb1&\xf1\x0c>0\xfd;\xf4\xf1{\ \x11\x90\xe3H\xb1\x11\xa4\x98\x88i\xa3\xaa!R\xa8\xa3\ \x7f\x14\xc9T\x0a\x00\xc9\x08M\xe2\xf0\xba\xfa\xfb\xa7P\ \x8aT2\x05\x86e\xe0\x0f\x04\xcb\xcaco\xe0d\xf4\ \xf2{\xd1)\x1e*\x9az\x1e\xbf\x13\xdd\xc2~\xbc\x1b\ <\x032\xd8\xaa\xb6E\x96e\xa4R)p^\x1f\xbc\ >\xdf\xac\xdf\xdbJ\xfe\x89\x92\x04\x9eO\xc3\xef\xf7\xc3\ \xe3\xe1f\xbd>\xe5\xfc;!\xfd\x06.\x19\xfb)\xce\ ?\xfact\xc5\xdeF$\xe8\x05\xcbf\xf6\x01\xa0\xa5\ \xe5\x16gZ\xf0l\xcb'\xf0\x9b\xee\x9b\xb1=t\x0e\ \xe2l\xcb\x8c\xb7\x07P\x85\xa6$+\x08\x86\x82 \xd9\ \xe0f\xce\xaf\xaf\x06\x05yQ\xe3Oj~\x8a\xe6\x1f\ K\xf3<@)|~?D\xc6\x8f\xd7#\x1f\x86\x02\ 6\xb3\x9f\x82\xf6\x8c,\x0a\xa3\x00Gy\xac\x8b?\x8e\ \x80\x12\xc3\xee\xe0z(\xba\xe8\x81\xa5\x08\xff\xa2\xf7\x86\ Z\xb4'\xf3;\xc6\xb4\xe3\xfc\xc9;\xc0R)'\x03\ t\x02\x8c\xa5\x12v\x84\xcf\xc4d\x0d\x94\xc5\x99\x9d\x02\ 0\x91pTw\x98\x1a\x93\xe9L\xd5\xfat\xfa\xdfV\ \xde\xff\xc6\xe3\xfa\xe9\x80\xec\xb5\xfa\xb23\xe9\xb5c\xaa\ \xc7\xe9\x1f\xe3\xb5\xc8\x05\xb8l\xf4\xc7X\x96z\x09 \ \xba\xb5\xa7\xd9\x8b\x0c\x952\xb6\x93\x02^9\x85\xd5\xb1\ \xa7\xb1:\xfe\x0c\x00`\xdc\xd3\x87\xf7\x03\xebp\xc8\xbf\ \x1c\x03\xbee\x18\xf2.\x84L\xb8\xfc}\x91L\xa8\xd6\ \x983\x1b\x07\x80X\xdf\xbf\x86\xc2A ;\x94\xcc\ \xca\x80?\x1e\xfc:\xe6\xa7\xed7\x0e\x02\x80Uqu\ \x07\xb3;\xbboA\x8a\x8d\x94]\xae9\x8d\xfe0\xf4\ 4^[X*bM\xfc)\x9c1}\x1f\xe6\xf0\xbb\ \x01\x001\xaa\xa8-1\x8bjS\x84a\xef\x02\xbc\xd0\ |\x15\xde\x88|(\x1b\xf4e\xf6\xc8\xf5W\xb5\x8c\xcd\ `\x9b\xb5\xc9\xc9\x02G;\x8b\xb4T\xff\x7f] \xa0\ \x5c[\x18<\xd1\xf6Y\x1c\xf2\xaf\xc0uC\xdfAH\ \xd6\xad\x12\xd0\xe7\xa0\xcb\x97P\x8a\xb3'\xff\x07'$\ \xdf\xc0\xcf{\xff\x01\xa3\xdc\x80\xb3\xa7\xfe\x07kcObq\xfa\x0d\xccM\xef\ B\x87p\x04M\xf28\xfcrL]\x99\x00\x80\xa5\x02\ \x14\xc6\x03\xaa\x0b\xdb\xe0W\xe2\xe0\x14\x1e!y\x0a]\ \xe2a\xf4\xf1{\xd0\xcf\xbf\x8d1n\x8e}\xe0\x08J\ \x91J\xa5\xd4)\x80@\xa0\xa15\x00%\xd3\x16\x86a\ \xe0\x0f\x94\xef<%\x13\x0f\xde\x09\x9d\x89%\xa9W\xd0\ $\x8f\x17M\xdf*\x0dcU\xe2y\xec\x0el@\x22\ o\x17\xb2\xf2Qd\x19\xa9t\x1a^\x8e\x83\xd7\xe7\xab\ J\x9e\xb3\x85(I\xe0\xd3i\xf8\xfc\x81\xaan\xa0S\ +\x9a\xa51\x9c9y\x17\xae\x1e\xbe\x05\xeb\xe2O\xe6\ \xbd\x03\x82 @\x10\x04\x04\x83\xc1\x8c\x05\xc0\x1e\x0a\x82\ \xbd\x81\x93q\x7f\xe7Mx\xb8\xe3K\x18\xf0-UG\ \x97\xb3\x0dUG\xcd\xb2,\xabS\x7fU\xd8\x0b\xc0\xaa\ \x1c\xebS\x85'\xcdF\xf9f?\x8d\x7f\xf3\xbc\xda7\ \xfa|\xfe\xac\xe9\x9cBu\xea~#\xfc!\xf4\xa7\xdf\ F\x8b8\x0c3\xc1\x9f\xb3\xe2\xa8\x7f7K#\xd8\x18\ }\x00\xe3\xdc\x1c\x0c\xfa\x16\x95\xd2\xa4\xb20\xe6\xd7.\ \x0e\xe0\xc4\xd4+\x96*\xb3OI\xe3\xf9\x96\xab\xaa\x5c\ \x8b\x99\xb6\x00\x18\x87\xf1U\xca\xaep\xb4_8\xb2W\ \x8fg\xac\x00\x99\x04\xa6\x03v\x8b\x11\xf1\xce\xc0&\xbc\ 6\xffN\xac\x9a\xfc\x03.\x97\xef\xc3\x1c\xe9}\xad\xf4\ l.\xd9\xe8\x81\xfa\x8ah\xe4E\x1a\xcc\x14\x94)\x99\ \xa5\x22\xba\x84\x03\xe8\x12\x0f\x16i\xb1\xb3\x9b70w\ \x09\x8e\xfa\x0a\x03\x86h\xed\xa7\xd9\xfadn\x05\xcd\xb7\ \x90\xd4;yu\xd5\x1eX\xde\xd6\xcc\xe5\x91d\x22\xf8\ Y\xef?\xe1\x86\xa3\xdf\xc4<\xfe\xbd\xa2\xe9;\x84\xc3\ \xf8\xf2\xc0\x17\xf1\xeb\xee\xef`O`Ce\x85C_\ \xfd\xca\xdb2\x1b\x14\xbcC\xc5\xbc[\xeb\x80\x05\xe9\xb7\ q\xc6\xf4\xbdX\x95x\x1e,\xcd\x85]\xd5\xf7!\x04\ \xdaw\x9d\x13\x1af]\x99D8l\x0f\x9f\x87\xe7Z\ \xae\xc2\x90wQ.\xa3Y&\xef\xbb\xcf\x1eC\xcd\xea\ f\xb7\xcb\x80\xe9\x19\x87B\xbf\x90\xdc\x13\xc8\x8a\xf2\xcc\ \xf3\x99\xf4t\xe3\xa7s\xfe\x03\x1f\x1b\xfd\x09>8\xfd\ \x9b\xc2\x1cMV\x0a\xf8\x95\x04>;\xf8-,M\xbe\ \x8c{:\xbf\x01\x81\xcc\x9c\x1f\xce\xbb\xa13p\xf1\xf8\ \xbf\xc2\xaa\x8f\xefO\xbf\x85N\xf10F\xb8yU/\ {\xe6,\x00\xea\xff,\xce\xda\xfc\xb6\xb1\x02\xe8\x8f\x95\ k\x09\xb0\xcc\xdb\x90L\x10%\x1c\xe5\x16\xe2\xf5\xae\xab\ q\xc4\xbf\x12\xad\xd2P\x91%@z\x85\xc0\xc2XD\ \x0c\xbfmg\xdc\xacf\xe7\xf2\xf3y/\xb8\x11\xa3^\ {\xef\xd6T\xc6\x07 \x10\x084\xa2\xa56\x8bB)\ \xd2\xe9\xb4j\x01\xa8\x82\xe3\x9cH|x3\xfc!\xcc\ \xe1w\xa3C\xb2\x0f\x14\x04\xa8\xf3\x88k\xe3O\xa1E\ \x1a\x81BXLz\xba\xa1\x94\xe9\xac\xa3(\x0aR\xa9\ 48\x8e\x83\xd77\xdb\xe6\xe2\xca\x90$\x09\xc9D\xf0|\xcb\x95\xb8\xab\xfb\xaf\xf0\ z\xe4\xfc\x9a\xef\xdf^\x09j,\x13Y];ob\ \xc5t\x8aMOd}A\x91\xc3\x85\x22\xd9\x90\xd60\ ~\x12DA\x9db\xb5\xb0\x96)\x84\xc1\xce\xd0\xe9\x18\ \xe1\xe6cy\xf2%\xb0T4d\xa4W\x06r\x99\xcf\ \xe7\xdf\xc5\xba\xd8\xe38\x108\x09\xd3\x9e\xaeB\xd3\xbd\ \x13\xf3\xbf\xc1\x84_L\xbaNy\xba\xf0\xa1\xa9_\x82\ \xa3\x82M\x9an\xec\x0d\x9eR$\xa7\xd2\x98\xb18\x00\ \x15)\x00@V\x82\xdb)\x00\xbad\x05\xe7\xcd\x8f\x93\ \x02!o\x97\x9f(IP(\x85\xd7\xeb\xc5\x98w>\ \xb65]\x84\xdd\xc1M` \xa3K<\x02\x16\x22\xec\ \x1eui\x96\xf6B\xc1\xee(=(\x0e\xf8O\xc2!\ \x9fu\xe0\x08\x85\x02i>\x0d\x10\x02\x9f\xdf\xdf0#\ \x7f3\x14J\x91\xe6y0\x0c\x0b_\x95\xd6\xce\xcb\xc4\ \x837#\xe7\xa2U\x1cB\x1f\xbf\x07\xf6\xdd\x1d\x05\xa1\ \x0a\xe6\xf0\xbb\xb0.\xf68>0}o&^9\xc5\ \x94\xa7\x0bR\x09{\x09\xc8\x8a\x02>\xcd\x83\xf3r\xf0\ r\x0d\xae\x00\xc8\x12xA\x80\xcf\xe7\x83\x87\xad\x0f\x05\ `A\xfa\x1d\x9c?\xf13\x5c5\xf2\x0fX\x99\xd8\x82\ \xb0<\x01\xdb\xe7\x9a\xf9\xbf(\x0a\x10%\x11\x01\xbf/\ \x13\xe1\xe9\xc5\xe3m7\xe0\xee\xeeoc\ W`#xR\xfa*\x94\x99\x84\x02\x10\x04\x1e\xb2\xac\ \xc0\xef\x0fd\xf6\xa1\xaf}\x99\xe5\x9e\xb7\x8b\x0f\xa0\xb6\ E\x955>\x83\x02\x90\xb3\x06\xa8\xff\x1f\xf4-\xc6\x8e\ \xf0\x07\xb14\xf9rfe\x97\xd1\x12[\xa8\x10\x84\xe5\ i\x9c\x16\xbd\x1f\x00\xb0/\xb0.\xeb\x81_\x8d\xd5\x00\ \xe6\x8a\x03A\x8f\xf0>\xe6\xdbX\x1e\xdb\xa4!<\xdd\ \xfa\xc9\x0aJ.d\xe6\x15\x00\xf5O\x8b\x146\xbf\x8b\ X\x01\xb4\xe3vK\x03ar\xde\xcc/\xc0\xaa\x0cI\ \x12\xa1(\x14>\xaf7;\xe74\xe5\xe9\xc2\xdb\xa1\xb3\ \xf0B\xcb\x15\x98\xf4t#\x22M\xa2Yv\x1e\xbb\xb9\ \x16\xd3\xefC\xde\x13\xb0;ho\x92N\xa7\xd5\xf93\ \xbf\xdf\xdf\xf0>\x00|\x9a\x07a\x99\xaa)\x00\x00@\ \xc1\xe0\x9d\xd0\x07\xc0P\x09'\xa4\xb6;\xbe\xceC\x05\ \xf4\x0a\xfb\xb0&\xfe4\xce\x9c\xba\x1b\x0b\xd3o\xc1\xa7\ $\x90\xf44!\xc94\xd9^+\xcb\x0ax\x9e\x07\xc7\ q\xe0\xbc\x8d\xad\x00\xc8\xb2\x0cA\x10\xe0\xf5yg\xd5\ \x02\x10\x96'\xb1)\xfa\x00>>\xfaC\x9c7y'\ \xe6\xf0{\xf2L\xfdvh_\x85(\x8a\x90D\x11~\ \xbf\x1f,\xc3\xe0\x80\xff$<\xd0\xf1\x15\xfco\xd7\xd7\ q\xc8\xbf\xb2 \xa0L=#\x08j03\xbf\xdf_\ ;\x1f\x00\x1d\xa5J\x15\xc7\xf1\x01\xa0\xb6\x05\x00\xbc^\ _\xde\x0c\xa0Y\x1e1\xb6\x0d\xaf4]\x84Vq\x10\ }\xc2^\x93)\x00\xe3\xd4\x00@\xa0`i\xea\x15\xac\ J<\x8b\xfd\x81\xd5\x88\xb2\x1d\xa6\xf5\xb0\xaa_\xb1\xe3\ Fd\xc2aS\xf4A\xcb\xf3ay\x12;\x83\xa7U\ 5,p\xdd\x04\x02\xaa\xa6\x87\xbbQ\x9eY\xf9\x04\xa8\ \xe7t~\x01@\x81'>1\xf9e\xf6@S$\x84\ -M\x97ck\xf3\xc7\xd1&\x0ebM\xfc)\xac\x8e\ ?\x83\x05\xfc\xbb\x16Wh\xf51\x9bM4\xd6\x1e%\ \xad\xd5o\x91\x86\xec5k\xed\x0f\xd2\xf8\x01g2\x0e\ \x0d\x00\xaa\xdf\x16\x0a\x82G\xdb\xbf\x80\xa8\xa7\x1d\x97\x8e\ \xde\x9a]\x0e\xea\x14\x0f\x15pbr\x1bNLn\x03\ F\xd5\xd5\x1f\xbb\x82\xa7bOp\x03\xf6\x04N\xb1]\ A\xd0\xe8\xcfE\xdf\x8d\xcet[\xbcJ\x1a+\x13/\ `]\xfc\x09,K\xbe\xe4X\xe0[A@A\xc1`\ {\xe8l\xbc\xd8y\x1d\x0e\xf8O\xaaRMg\x97\xd9\ ~\xc7\x9c\xacD\xc8\x9b\x22(\xf0\xa8W\xfd\xaa\xec\x04\ \xbf^\xbc'\x99\x10~\xd1s\x0bv\x077\xe0\xca\x91\ \x1f\x80SR\xf9\xa9\xcc6\x84\xa3\x14\xf3\xd3;\xf1\xad\ \x83W\xe3\xd1\xb6?\xc1\xe3m\x9f\x83X\xa3\x9d\xf9v\ \x86\xce@\x9cmEX\x9e\xb4Ls\xee\xd4\xaf2q\ H\xaaGU\x15\x80b\xe2\xcc*Q\xd1\xebta\xf3\ \xac\xd2j\xc7\xcbQ\x02\x00\x148\x08\x12\x14\xd6\xcb\xca\ \xaf)\x977\xc5\xb8\xa7\x07O\xb7\x5c\x87\xa7[\xaeC\ \xb3<\x8e%\xc9W\xb04\xf5\x0a\x96\xa4^\xcd\x85\x1a\ .\xa8\x9d>\x17\x93\x14\xa6_\x8byzK\xbf\x84\xbc\ F\x11\x93c\x96\xc5\xd7\x17\xba\xbaf\xe5\x7f\x0d\xd9\xd2\ \xfcq\x8cs}\xf8\xe4\xe0w\xe0W\xe2\x05\xe7e\xe2\ \x05k3w\xa7\xd1&\x0e\xe0\xb4\xe9\xfbp\xda\xf4}\ \xa0`q(\xb0\x02{\x82\xeb\xb1+p*\x8e\xf8\x97\ A\x04\xd3\xd8J\x99\xd9\xc72C\x8d\xf1*i,O\ n\xc5\xaa\xf8sX\x99x\x1e\xdel\xe7^~\x15(\ \x00\x9e\x09\xe2\xf9\xe6\x8f\xe0\xf1\xaeK \xb6/\x07\xc7\ yr'\x1b\xed{\xa1\xda\xf7R\xddw\xacZK\x0a\ \xad\x84\xbde\xe2\xec\x9c2\x055YCm\x1c\xe3k\ \x7flm\xfa\x18\xf6\xfbN\xc2\x0dC\xdfB/\xbfG\ +0?\x91\xa1|\x0f\x15q\xf1\xd8O\xb1>\xf6\x08\ ~\xdd\xf5\x9d\x82\xb9\xf8r\xe7\xfe\xb3\x10@\x02\x87\x17\ \x9b/\xc5\x87'\xfe\xdb\x22\x11\xc5)\xb1\xc7\xd0&\x1e\ \xad\xaa\x15\x80\xdc\xf8\xe8\x11\x9a\x14\xcb\xdb\xc4b\xd3\x9c\ \xfcy\xaf\x97\x06\x92\xf9^\xf5\xd9\xff\x9a\xcc4\x171\ \xd7[\x1es\xe8\x14hH\x9aw\xdezI\xa2\xf9\x94\ \x00\xa0F\xd1\x92e\x19\xc1P\x10\x8ca\xfe\x8c\x98\xa4\ 7\xa3C<\x82~~\x07\xe6\xa7\xdf\xc5\x5c~7z\ \x84}\x08\xc81C%\x8a\xe5\xa2Il\xf3\x12c\x9e\ v|\xb7\xff!\xcb\xab)\xa5\x88F\xa7\x01\x1045\ 55x$@\x19\xd1h\x0c,\xcb\x22\x12\xa9\xf6\x9a\ \xfc|z\x84\xfd\xb8a\xf0\x9bh\xd7\xed\x22\x98b\x9a\ \x10P\xa2\x15\xe7-\x13\x0e\x07\xd8\xc5xKX\x80\xa3\ -\xa7b\xa4c\x13\xe2L\xfd:\x93\x15C\x10x\xc4\ \xe3\x09\x84B\xa1\x829\xdaj\x11R\xa6\xb12\xf1\x02\ V\xc5\x9f\xc5\x89\xc9\x97\xe1)\xb2\xb1S)\x8cq\xf3\ \xb0\xb5\xf9\xe3\xd8\xd6t\x11&y\x06\xa9T\x12MM\ \xcdu\xe7\xd0X*\xf1x\x1c\xa2(\xa2\xb9\xb9\x09\x0c\ 3sK\x13\x9d\x08\xc2bB?_A\x00\x92\xc9$\ (U\x10\x0a\x85`f\x9d\xa5&\x17\xebW(pJ\ \x1aW\x8c\xfe\x13\xce\x98\xfa]~j\x0bK\x80\xfe\xc8\ \xd6\xe6\xcbq_\xe7\xd7\x11\xd3;|:\x10\xfe\xa6-\ \xa4Z\xbd\x08\xe6\xf2\xbb\xf1\xdd\xfd\x17\x99\xa5\x02@\xa1\ \x10\x16\xff\xd5\xfbClk\xba\xd8\x22Mi\x049\xa6\ >\xa6\x00\xec(U\xd9\xb6\x1b\xedk\xe7\xf51|L\ \xad\x01T\xf7B9(\x5c\xef\x1cb\xb7\x1aa\x8c\x9b\ \x8b1n.^\x0d_\x90=\x16V\xa6\xd0!\x1cF\ \xa7x\x08\x1d\xe2Q\xb4\x88C\x88(S\x08K\x93\x08\ *Qxi\x1a\x1e*\x80P\x19~%\x01\x80B`\ \x82\x90\x89\x07\x12\xf1B >\xc4\xd9\x16$\xd8V$\ \xd8\x16L\xb3\x1d\x16\x1f\x9czg((\xa09\xb54\ \xb8\x09\x80j7|\x06F\xce\x83\xde\x85\xf8\xc9\xdc\x9f\ \xe1\xfa\xc1\x9b\xb1(\xf5\x1ad\xc2\xe1\xdd\xe0i8%\ \xf6h\xc5y\xb3\x94G\xbf\xf0\x16\xda\xe3[\xe0K\xdf\ \x8b\xc0t\x00\xa3\xde\x058\xe0_\x85C\xbe\x15\x18\xf0\ -\xc5Q\xdfb\x08L=;\x9a\xe9\x9e\x0b\x90\xfd\x10\ \xaa\xf5\x5c\x18*c.\xff\x1eNLl\xc3\xf2\xe4K\ X\x90\xde\x01R\xe2\xb4L\x91\x12\xb03\xb8\x09/\xb4\ ^\x89\xf7\x82\x9b\xa0\xc5\xdc\xa0H\x01\xba\xa8y\xc8\x1c\ m\xb8\xefE\xb7d\xd6lW\xbb\xaa\x97Js\xd3\x97\ EG\xf4f\xd7\x17\xe4gv\xcedy\xa3\xc9\x0f\xb3\ \xa5\x89\x02\xf1\xe3\x7f\xba\xbe\x8d\x9d\xc1Sq\xcd\xd0\xdf\ !\xa4L\x15Z\x02\x8c\x05C\x0d\x06w\xc6\xf4\xbdX\ \x17\x7f\x02\x0f\xb7\xdd\x88\xa7[?U\x10\xe7\xc1qk\ \x0d\x09\x07|K\xb1+\xb8Q\x9d6\xcc\xab\xab\x0f[\ Z\xae\xc0\x1f\xda>\x8f1n\x8e\xd3\xdc\x1dQw\x16\ \x00\xb3O\xcb\xca!\xd0\x22\x9b\x82\xe3\xc5\x82\x10\x15\xb5\ \x08\x00\xe0\xf94dY]Bc\x8c\xa3m\xd7\x158\ \x0d\x804SPJ\x11\x8f\xab\xa6\xecp8\xdc\xe0\x16\ \x00\x05\xf1x<\xb3\x1dphF\xcad\xa9\x8c+F\ \x7f\x88\x01\xdf\x12\x9c9\xf5\x1bt\x16\x8d\xdf\xe0\x0cY\ \x92\x11\x8f\xc7\xe1\xf3\xf9\xe07\xd9\x0e\x98\x82\xc1(7\ \x0f\x03\xbe\x13q\xc4w\x22\x06|K1\xe8[\x84(\ \xdb^\x95\xf2\xab\x89 \x8aH&\x12\x08\x06\x83\xf0\x96\ \xe9\xd0\x18P\xe2\x98\x9f~\x17\xf3\xf9w\xb0(\xf5&\ \xfaSo\xc3G\x13U\xae)\x90`\x9a\xf1J\xd3G\ \xb1\xb5\xf9r\x8c\x9a\xac\xb3N\xa7\xd3H\xa7\xd3\x88D\ \x22`\xd9:\x08\xe8S\x01\xc9d\x12\xa2(\x22\x12\x89\ \x94\xbc\x17@-\xb0\x13\x94\xc5\x1c\x02S\xa9\x14(\xa5\ \x08\x06\x02\xb9\x0d\xcd\xa81]a&f\x8aD\x934\ \x8ek\x87\xbf\x8b\xd5\xf1\xcd&\x99\xd8[\x04\x06}\x8b\ pO\xe7\x9fcG\xe8L\xb3*\xe4\xd9j\x0bj\x93\ g\x99P\xa5\xcd\x9a\xf8\x93\xf8\xd3#_\x02\xa0\xeeZ\ \xfaL\xebux\xa2\xed3\x88\xd5\xe0;\x0frL\xf5\ \x15\x80B,\x14\x00\x8d\x0aW\x05\xd8dQ\x98G\x99\ \x8a\x00\x00\x08\xbc\xba\x84&\x10\xc8x\xd0f4\x15\xdb\ z\x16\xc1\xa9\xec\xb57\xfa\x97\x86\xaa\x00$\x00\x02\x84\ C\xa1\xc6W\x00\x12\x09\xb0\x0c3c\x0a\x80\x9efi\ \x14\xab\x12\xcf\xe1\xa4\xf8sX\x9cz5\xb7\xd6\xb8\x0c\ dY\xa7\x00\x94\x10\xd3 \xc56a\x98[\x88!_\ \x7f\xc6\xc24\x0f\xe3\xdc\x1c\x8c{\xfaj\x10\xaa\xd8\x19\ \x82(\x22\x99L\x22\x18\x08\xc2\xeb\xb5w\x9aj\x92\xc6\ \xd0!\x1dA\xbbp\x14\x9d\xe2A\xf4\x08\xfb\xd1+\xec\ C\xbbp\xa4f.\x84\x14\x04\xfb\x02\xeb\xf0b\xf3e\ \xd8\x1e>\x17\xb2\x8dcW:\xcd#\xcd\xa7\x11\x0e\x87\ \xe1i`\x05\x80\x02H%\x93\x10%\x09\x91\xb0\xb3\xed\ \x80K\xcd\x1f\xb0\x10tV\xd78LXh\x0dP\xe3\ \x7fPJ\xd5X&\xba^\xd16\x10\x91\xceRk\xc6\ \xc6\xe9\xfbq\xd5\xc8\xf7\x11\xd0|}\xcc\x84\xbfi\xc5\ )v\x07O\xc5\xbd\x9d\xdf\xc0~\x83\x93\xa8em\xf2\ |3r2\x92@\xc17\x0f^\x87\xed\xe1s\xb0\xb9\ \xf5Z\xa4\x98\xb0e{*\xa5>\x14\x00\xc0\xb1?@\ \xc1q\x87\x8a\x80\xfe\x9c\xe3\x90\xc4\x86\x03\xd9 \x1a~\ \x7fn\x0d\xad\x8d\xb9\xbfX\xfe\x95R\xae\xdc\xa6\x94\x22\ \x91PGR\xa1c@\x01H$\x12`\x19\x16\xc1\xd0\ \xec\x9a\xc7\xfdJ\x02\xcb\x93/\xe2\xa4\xf8f\xacHl\ \x85_\x89\x15\xbfH\x87,\xc9H$\x12\xf0\xfa|\xf0\ \xfb\xab3o.0\x01L\xb2=\x98\xe6:1\xed\xe9\ \xc4\x14\xdb\x83iO\x07\xa6\xb8.\xa4H\x04)6\x82\ $\xdb\x84$\x13\xa9\xea>\xf4\xb2\x90\x06M\x8c\xa1\xc3\ \xcb\xa3\x95\x89#\x22O\xa0I\x1aS\xff/\x8f\xa3Y\ \x1aE\xbb0\x80v\xe9hU\xe7\xee\x8b\x11g\xda\xf0\ j\xd3G\xb0\xb5\xf92\x8c\x14\x09\x96\xa5\xc1\xa7y\xf0\ <\x8fP(\x04\xd6\xd3\xb8\x0a\x00\x00\xa4\x92)\x88\x92\ \x84p\xb8\xf8n\x80N\xf7\x09\xa9\xf6\xbe\x02V\xd9\xe5\ \x9b\xf75\x05\x00\xa6\xd62C\xd2\xa2y\xeb\xd3\xb5\x8a\ \x83\xf8\xd4\xf0_ay\xe2\xc5\xc2\xabL\x04\xbf\xfe\x1c\ \x05\xc1k\x91\x0bp\x7f\xe7\xd7\xb2\xef\x97\xd5\xa8?\xff\ \x90\xb9\x8c\xac\xf54M}(\x00%\x9a\xc8\xed\x9c\x02\ K\xb9\xd6\xee\xe56K\xa7*\x00\x0a\xfc~_\x9e\xd0\ \xcc\x0f\x7fZ\xa7P\ (8k\xb5\xa8\x06\x94*H$\x92`Y\x06\x81@\ \xfd\xcc\x8f{ bQ\xf2u\xacHn\xc5\x8a\xc4\x16\ t\x09\xc5\xa7\x09dY\xcan\x07\x5c\xcd\x98\x06NQ\ \x08\x8b$\xd3\x04\x9e\x09d,\x07\xea{\x91b\xc2\xc8\ l\x87\x03\x9e\x09\x83S\xd2`\xa0.\xadc@\xb3\xa3\ %\x9f\x92\x80_I\xc0/'\x00!\x8et:\x05\xbf\ \xdf\x0fn\x96\x83\x1a\x89\xc4\x87\xb7\xc3g\xe1\x95\xc8G\ \xb0+\xb4\x11r\x89nO\xbc\xc0C\xe0y\x04\x83\xa1\ \x86\x9f\x02H\xa5S\x90%\x09\xc1P\xa8\xc0\x91y6\ p$\xecM\x0fR\xa4\xd3<(\xa8\xa5\xb5\xcc\x89\xe0\ 7\xca\xf3\x9c\x15\x83\xe2\x03S\xbf\xc3ec?FP\ \x8eZh9\xd6S\x05\x12\xe1\xf0B\xcb\x95x\xa0\xe3\ \xcb\xe6\xa6{\xd3\xa9\x8a\xe3U\x01\xd0(g* {\ \xd0\x99\x12\xe0tJ\xc0,\xad \xa8\x0a\x80\xcf\xe7\x03\ c\x11F\xd3\xb4\x95E\x1a^\x0b\xf1k\x97'\xa5\x14\ \xc9d\x12 @0\x10lx\x0b@2\x95\x02\xcb0\ \x19S`}\xd2&\x0eby\xf2E,M\xbe\x8c%\ \xa9W\x10\x92\xa7\x0b\xd2\xc8\xb2\x8cT2\x09\xce\xcb\xcd\ \x8a\x02P99\xef\x1dI\x14\x91J\xa7\x11\xf0\xfbg\ e3 \x0a\x82=\xc1\x0dx5r!\xb6\x87\xcfE\ \x9a)\x7fzHU\x00\xb4\xcd\x80\x1a]\x01H\xab\x0a\ @0X\xd2\x14@-\x04Q\xd1<-G\xca*|\ F\x01P7\x03\xd2\xa5\xb1\x10\xea\xa6E\x14Q\x12\x9a\ \xa4Q\x5c9\xf2}l\x88>\xe2\xa0r\x85\xd3\x05<\ \x13\xc0\xe6\x96k\xf1X\xfb\x1f\xe7BD;\xb4\x00\xd4\ Z\xf8\x03\xf5\xa4\x00\x94 \x88-\xcf\x95`\x09\xb0:\ g'\x0bEQ\x84\x22\xcb\xean\x80\xc4zw\xc3\xfc\ 2T\xaf{\xdb\xd6\xcf\x94\xfc\xcd\xce9ev\x03\x04\ 2{\x01\x90\x86tj\x06\x00\x9a\x89\x9f\xaf\xee\x06\xd8\ \x18B\x93@\xc1\x9c\xf4\x1e,I\xbd\x82E\xa97\xb0\ 0\xfd\x16\x9a\xa4\xf1\xccn\x80)u/\x00oc\xef\ \x06(I\x22x\x9eWC\x01{fF\x01\x90\x88\x17\ \xbb\x82\xa7\xe2\xed\xd0\xd9x+r6bl[\xf9\x99\ \xe9\xde11\xb3\x1b` \x10\x00\xa3)\x00\x8d\xf8\xbd\ \xd0|G\xe6\x99\x88\x04X\xb4^\x96\xa7\xec\xc5\x1f\xa5\ \xeaRSJ\xadC\x01[]\xe78\xad\xee\xef\xe5\x89\ \xad\xb8z\xf8\x16\xf4\x08\xef\xe7\xce\x14\x9d\xfb\xd0)+\ L\x10O\xb7~\x0a\x8f\xb7\xdd\x808\xd3b\x92\xf2x\ W\x00\xf4\x94(+\x8bY\x04\xacV\x16\xd8\xe5a&\ \xdcEQ\x84\xa2(\xf0z\xbd`,\xa4\x7f\xa9\x83\xe9\ \xd9\x88\xc3OA\x91N\xa5\x01\xa2\x86\x02n\xec\xbd\x00\ \x94\xdcf@\x0d9jV\xe9\x90\x0e\xa3?\xfe\x1a\xfa\ &\xb7a\xa9\xf4.\xe6\xd3\xc35s\x80\x9b\x09$Y\ \x82\xc0\xf3\xf0zk\xbb\x19P\x92m\xc2\xbb\xa1\xd3\xf1\ V\xf8\x5c\xbc\x1b<\x1d|\x05#}+\x04Q\x80\x98\ \x0d\x05\xdc\xc8\x16\x00\x0a\x9e\x17 \xcb2\xfc\x01\xff\xac\ O\x01\x14\x13\xf2\xa6\xd7\xe8.\x11\x04\x01\x94R\xf8|\ \xbe\xa299\xf5\x03\xc8\xbb\xc6\x90\x01K%\x9c3\xf9\ K|t\xe26\xe7\xd3\x02\x86<\xd2L\x08O\xb6]\ \x8f'Z\xafGR\xb7\x8d\xb8\xab\x00\xe8\xa9\xb2\x02\xe0\ \xdb\xecy+E\x81\x10M\x01\xa0\xf0z9S\xb3\ y\xd1\xfc\xebE\xce\xd2\xccf@\x80*4\xeb\xa5^\ e\xa0z\x03\xf3`\x18R\xb3\x8033\x85\xa2(H\ \xa7yp\x1e\x0fZ\xd8\x14\x16\xa4w`\x0e\xbf\x0b\xf3\ \xd2\xefa\xae\xb0\x0b\x9d\xc2a\x10\x93]\xeb\xea\x11Y\ \xcal\x06\xe4\xf5\x82\xad\xa2\x02 0~\x1c\xf0\xad\xc6\ \xee\xd0\x06\xec\x0c\x9e\x86\xc3\xfe\xe5PP[A&\x8a\ \x22DQ\x82\xdf\xef\xab\x8b\xa5s\x95 \x08\x19\x05\xc0\ \xef\xaf\xdb\xa9?'A\x00\x01\xd52C\x01p\x9c\xb7\ 0\xd6\x8b\xa9\x99\xddA\xd9\x0e*\x15\x96'q\xc9\xd8\ \xad\xf8\xe0\xd4\xef\xc0P}\x1c\x8ab\x15\xcf\x9dO1\ a<\xdbz\x0d\x9el\xbd\x1e\xd3\x9eNW\x01(\xa0\ \x1aJ\x00`\xbaJ\xc0\x89\xf5\xce\xec\xbc\xb6\x19\x90\x95\ \x02Pj~\x05iH\xee\x1d\xa9\xe5\xb7I)\xc0\xf3\ \xaa\xe7\xb5:\x9dQ\xbb\xb2j\x8d\xa2P\x08\x02\x0fB\ \x18\xf8\x1a|\x0b]YQ \xf0<<\x1e\x0f8\x93\ ys\xaf\x92\xc2\x1c~7\xe6\xa5wa\x8e\xb0\x0b}\ \xfc^\xf4\x08\xfb\xab\x12\x89\xb0*\xe8>,Y\x92 \ \x08\x22\xbc^\xael\x05@\x8d{0\x17\x87\xfc+q\ \xd0\xb7\x12\x07\x02\xabq\xd0\xbf\xb2 \xe8J\xad\x11E\ )c\x01hl\x05\x80B\x15\x9a\xb2l\xef\xc7T\x93\ \xb2u+\x0aJ\xdd\x03\xc0\x0au7@Z\xa0\x00\x94\ b\xe6/\x9a\xc6\xa2\xb2\x14@\x8fp\x00\x97\x8d\xfe\x08\ \xebbO\x14/E\xbb\x01\x86\xfcD\xe2\xc3\x96\xe6\xcb\ \xf1\x87\xf6\xcfc\x94\x9b\x97\x95\x133e\xfb\x9b!\x05\ @\xa5\xe4\xd7\xcd\xd1\x1c\xbb\x83K\xac\xcc\xf5%VC\ \x92$(T\x01\xc7q\x96S\x00\xa52\x1b\xb2\x97B\ \x8di\x00\x92\xd9Ik\x16\xeaP-(\xa5\x10\x04\x01\ \x84\x90\xb2\x03\xce\xd4\x0b\x8a\xa2@\x10\x04\xb0\x1e\x0f\xb8\ \x12\x84fX\x9e@\xaf\xf0>:3\xd1$;\x85\xc3\ \xe8\x90\x06\xd0,\x8d \x22\x8d\xcf\xcaT\x82,\xcb\x10\ E\x01\x1c\xe7-\xea8\x17g\xdb0\xe6\x9d\x8bqO\ \x1fF\xb9y\x18\xf1\xce\xc7\x90o\x11\x86\xb8E\xe0\x99\ \xd9\x9f\xd6\x91$\x09\x92$\xa9S\x7f\x0d\xac\x00\x00\xaa\ 5C\xd6\xf91\xcd6\x95\xbc\x99z\x05\xa0\xdc\xbcm\ \xd3\x14\x09\xed\xab\xfd>!\xb5\x1dW\x8c\xfc#\x96\xa4\ ^u\x94\x8f\x192a\xf0j\xe4#x\xb4\xfd\x0b8\ \xe2[V4}\xb5\x98Q\x05\x00\x98\x19%\xc0\xf6\x5c\ \x05\xca\x80,IP(\x05\xe7\xf1\xd8~L\xcb~\x08\xbev\ \x08\xdeVLy\xba\x10c\xdb0\xed\xe9@\xd4\xd3\x81\ 8\xdb\x8e\x09O\x0f\xc6\xb99\xe0\xab\x18\x7f\xa0\x16H\ \x92\x049\xa3\x00\xcc\xba\xe3\x5c\x85\xe8\xfd\x98\xeaA\x01\ (\x05\xa3\x1c\x15%\x11\xa0\x00\xc7q%)\x12\xa5\x8c\ \xf6KY\xa6\xb86\xfe\x14.\x1b\xfdg\xf4i\x1b\x0c\ Y\xe4i\x9e\x1f\xcdX\xa7\x09v\x86N\xc7\x13\xad\xd7\ cG\xf8\xac\xcc\xd1\xdaQ\xff{\x018\xb0\xd7\xdb%\ )8\xa7\x7f \xba\x0f@\xff\x98\xec\xa6\x13H\xc6\x94\ c\x97\xde\xea\x99\xebM`\xb3\xff\xed\x11\xb5\xe2\xb3^\ \x8fJ!\x99\x9b\xd9\xf0\x0dQ;\xe4*\xb7E\x22\x1c\ &\xb8^Lp\xbd\x8e\xd2{\xa8\x00NI\xc3\x97\xd9\ \x7f\x02P7M\xe12\x7fkA{$\x92\xf3\xb7\x10\ \x89\x0f\x22\xe3\x83@\xfc\x10\x89\x0f)6\xa2*3\xa2\ \xa8Z\xcb\x1a\x5chf\x9f\xcb\xec\x7f\xb4\x15\xa3\xae^\ \xaa\xaf\xefE?\xedYJd@\x02\x02J\xcat\xea\ 3\x16\xee4\xbd\x0do\x86\xcf\xc3\xf6\xf09\xd8\x18}\ \x18\x1f\x1d\xfb\x7f\xe8\xe1\xdf/1\x075\xfe\xc0\x8a\xc4\ \x16\xacHl\xc1\x90w!\x9el\xfb,\xb66]Z\ \xd5 ]\x05e\xce\xa4\x05 [hY\xa5\xd9\xe4W\ A\x86N/\x95\x15\x19\x94Rx\xd8\x9c\xce4\xdb\x9f\ \x91\xdd\xdc\x97\xf9\x05\x00\xa8:\xaa\x01\xa0\x8e45\xc7\ \x88F#\xb3\xa4Q\x92$\x10Brs\xcd\x0d\xda\x16\ \xaa\xa8maXF5\x9b7b;\x00\x80\xa8\xd6\x0c\ Y\x92\xc1zX\xb0\x0cS\xf5hq3B\xe6\xdbR\ d\x19\xb2\xac\xc0\xc3e,\x7f\x8d\xda\x16\xaaN\xcd(\ TQ\xa7\x98\xcalK)s\xf9\xb5D\x92U\x07\xbc\ rc3TR\xfdbmg c\xe3\xf4\x03\xb8h\ \xfc\xdf\x1c\x05\x01\xb3\xabM\x82m\xc63-\xd7\xe1\xfe\ \xce\xaf\x95VI\x07\xcc\x9a\x05\xa0\xa2w\xc7\xccT\xe3\ 8\xc3R=Pr\xc3u\xaaPPJ!Wu\x07\ \xb2\x92*Sy6Z\xa7\xa6\xa8\x0a\x9f$K\x9a\x1c\ \x9d}m\xc6)\x86\x11\x83\xa2P\x80P@\x92\xd4S\ \x8d\xd6\x16\xa2\xe92\xea\xfb\xa5\xc8\x0a\xd4\xb0\xa2\x0d\x86\ \xae-J\xa6-\xb2,\xab\xdf\x0dhC>\x17@\xf7\ \xddK\xb2\xba\xb3]\x03\xb7EQ\x94\xcc\x00@\xce\x1f\ q\xd7\xac-\xb5\xbbI\xea\x0e\x83\x14r^wlQ\ \x9e\xa3jTXW\xddhL\x06\x8b\xad\xcd\x97\xe1\xa5\ \xa6KpZ\xf4\xf7\xb8h\xec\xa7\xe8\xd0m#^J\ \xa9!y\x1a=\xc2\xfe\xca\xeafC}O\x01\x98a\ X\xe3_\x1cG\x06\xfe\x82$\xc4\x90^\xc9\x98\x01\x1b\ \xd9\xa4\xa9\x0d\xf6\xb5\x0f\x9fa\xd8\xc65\x00\x90\x8c\xd0\ \x04\x05!$\xbb\xbfy\xc3\xb6E\xa1\xa0T\x06a\x18\ 0\x0c\xd3\x90\xed\x002\x9f\xa7B\xa1P\x19\x0c\xc3\x82\ a\xc8\xac\x8f\x16\xcbA\xfb\xf2\x15(P\x14\x05\x0c\xc3\ \x804x[\x00\xf5\x9baX&\x13\xa4\xacqQ\x14\ \x05\x14\xf6\xfdqe\xed\xb3\x97\x15N\xf2V\x08\x8b-\ \xcd\x97\xe3\xa5\xa6K\xb01\xfa .\x1c\xbf\x1d\xbd\xc2\ \xbe\x92k\xf8L\xebu\x8e\xd2\x95\xc3\xac*\x00\x15\xeb\ \x87\x8e\xe4\xb9\xb3R\x8a.\x0d$\x0c4\x8b\x80S\x07\ \x9az\x1c$\x10\xe4,\x00\xda\xc7S\x8f\xf5t\x02!\ \xaa\x05\x80\x10\x92u\xd0j\xd4\xb6\x80\xa1 T\x01\xc3\ \xa8mi\xd8v\x00`\x18\x0aJ\x95\xcc\x9c3\xd3\xd0\ \xd3\xe7\x19\xfb\x9f\xfaL\x1cF\x00\xadWHf\xd4\xac\ ~\xf7\xf5\x1f\x02\xccN<\x92\x8c&\xa6\xee\xccj\x9e\ \xd2\xac}\x15\xf9\x0c\xe4\x95\xef0#\x00\x0a\xf1\xe0\xc5\ \xe6\xcb\xf0R\xf3\xc7\xb06\xf6$>2~;\xfa\xd3\ \xdb\x1d]{\xc8\xbf\x02\xbb\x82\x1b\x9d\x17V\x22\xb3\xaa\ \x00Tl\x81r0\xb87{N\xc5^\x0c\xf3\xf34\ \x97\xc8\xe1\x82\xfd\xa2/Q\x91\xf3\xb5\x81\x1a\xfe\xae\xf7\ n\xc0\x1a\x9a\xfd\xf0\x1by,\x93\x83\xd2\xd9\x9f[\xad\ \x06\xeat\xc6l\xd7\xa2:\xe4}\xf7\xc7\x00\x14\xb4N\ \x1c\x91+\xb8\xad\xba)2J\xed}\xe5+^\x0eX\ Qb\xe3\xa5\x0c^\x8f\x9c\x8f\xd7#\xe7cyb+\ >2\xf1\x1fX\x9e\xd8j{\xcd\xd3\xad\x9f*\xbf@\ \x07\xd4\xc5\x14@U\xc4\x90\x96\x89\xc3\x95\x03\xb0I\xe6\ \xdc\xa5\xa0\x02/\x9aR\xca\xa9\x06\xfa\xfb\xa3\x1d*\xe1\ \x9e\xd5\x0d&u\xa5\x0dn\xce\x042\x8fE\xf37\x99\ \xd5\x9a\x94\x89\xf1\xb9\x1c3m!\x05+\x7f\x1a\xf2{\ \xd1\xc6,\xa8\xd3\xe7RB_j\x97\xb2\x94v\x95|\ \x0f\xaax\xd3v\x86N\xc7\xce\xd0\xe9X\x90\xde\x81\xf3\ '\xee\xc0\xfa\xd8\xa3`\xa9\x94\x97&\xce\xb6\xe2\xe5\xa6\ \x8b\xaaW\xa8\x09u\xa1\x00\x00UT\x02\xcaL^\xbc\ l\x92\xb5\xfb\x94\xe8U`(t\x16?=Z(h\ 4SZ\xfd\xf5\x086\xe8\xab\x5c/n\xc9U\x80\x00\ \xa5\xad\x87\xaa7\x0c\xafR\xde\xfb\xd5h\x98U\xbb\x9c\ \xa0\xf2\xf5@\x9e\x11\x834\xf6s\xc9\x92\xd3jj*\ \xf4\xcb\xbe\xc8Y6\x07\xfd\xab\xf0\x9f}?\xc6=\xd2\ \xb7p\xce\xe4\xafp\xe6\xd4\xdd\x08\xcbS\x00\x80\xcd-\ \xd7@ \xb5\x0d\x86U7\x0a\x00P\xa1`\xb5\xca\xc8\ a\x86\xc6K\x9c\x96\xef\xf4\xddh\x94\x01\x83\x8b\x8b\x8b\ \xcblP\x0b\x95d6G\xf9\xa5d7\xe9\xe9\xc6\xff\ v\xfe\x19\x1ej\xff\x12N\x8b\xfe\x1e\xe7N\xfe\x12\xcf\ \xb5|\xa2\xba\x951\xa1\xae\x14\x80z\xa2\xda/c\xbd\ \xea\xdb\xf5Z\xaf\xd28\x06\xa6\x00(\x1a\xdbl\x9eG\ \xceQ\xb6\xf1\xdb\xa2\x06\xd0i\xa8\xa5\xb2\x16P\x0b+\ \xe6\xb1B\xbd\xb5\xa9\x9c\xfa\x08L\x00\xcf\xb6\x5c\x8dg\ [\xae\xaez}\xcc8~\x14\x802\xac\x02\x05ii\ \xae#\xd0.\xb5\xb3\x1c\x1c\x03}\x86\x8b\x8b\x8b\xcb\x8c\ c\xec;\xad\xfc\xfc+\x12\xfa\xf5\xa61\xcc\x02u\xab\ \x00X=\x9b\xaa\x0aT\xe3\x9cC\x09\xcb\x12\xac\xeag\ \x16=A\xb5\xab\xd6,\x01\x80\xdb\xd7\ \x96\xc2\x92\x16/\x00\xd5\xb2r(.\xe6\xcd\xf1k\x1c\ \x8f\xf7\xb3\xea\x0a\x80\x9dc\x90^{\xe5\x18@t\x9d\ \xc7g\x85\xa4D\xf1\xc2`*\xfb;\xe8\xb1w\xe6\xf2\ \xd8<\xd3\xb4\xac\xce\x07{\x88\xeb\x10\xd6\x08\x98u\x5c\ +t>\x1cG3\xa3#\xceF\xa1K\xc9\xb9\x0f\xd7\ u\x04\xac\x0dA\x0f\xc1\xc9\x9d\xfe\xbcoo\x9a\x97\xf3\ \x94\x03\xb7\xafu\xc6\xe2f\x0ea\x8eAZ\xa6\xd85\ %X\xbe\xdb\xc7\xe3\xfdt\xc7m..\xc7)A\x0f\ \xc1\xfa.\x7fv\x8ag\xef\x94`\xb9\x04\xd4e\xe61\ *\xde\xcd>\x16\xfd\x11\xd7\xf1\xb2\x14\xb4\x15N\x92B\ \xf1\xd6X\xe1\x92\xbf\xe3\x9d\xaa[\x00\xecn\xb0\xddH\ \xd2\xa5~\x91\x14\x0aXx\xce\xday\xd4\xba\xd4/\xda\ Zh\xed\x9b\xdc9\xc1c8\x95\x9b\xeb\xb7\x1b\xe1\x04\ Xw\xdcPk\x92\x12\xc5\xe6\x81d\xf6\xb7\x16\xa7\xa3\ \xbf\x89CJR0\x9c\x92\xdd\xbe\xb6\x08A\x0f\xc9\x9a\ \xfe\xf78Pn\x8f\xc7\xfbYu\x05 -[\xcf\x0b\ k\xbf%\x85\xba#\x8d\x06\x22-Q\x849\x805|\ \x04z\x93\x99\xfe\xb9\xbb\xd47z\xe1/)\x14o\x8f\ \xf3\x05\xc1\x9cD\x85BR(<\x0c\xb1\xfc\x8e\x01 \ v\xac\xd8B\xeb\x04\x8eQ\x97b\x1a\x83\xce\xec\x9d\x16\ \xd1\x13\xf4\xc0\xc3\x10\xb4\xfaX\x0c\xa7d\xb7\xaf-B\ W\xc0\x93\x15\xdc\xcb\xdb|Xn\x92\xe6\xa4\x0e\x1f$\ \x85b\xdbp\xfa\xb8\xbc\x9fUW\xe5\xa7\x05%;_\ \x121x\x08kK(\x12n\xa7\xd1PhK`\xc2\ \x1c\x93'\xf4\xff\x7f;\xf7\xb7\xd2\xd8\x15\x86q\xf83\ \x93HGe*\xfd\x03B=(T\xe8a\xe9]\xf5\ \x0e{\x13C\xa1\xccA\x85\xb6`\xc1ie\xb4S\xb5\ \x89\x9a\xec\x9d\xa4\x07\x1a\x9btT,\x8cc\xf0}\x9e\ S\x15\xc2\x06\xbf\xfd\xcb^k\xafO\xe6v\xc4\xfew\ \xd7,\xcbi\xfe\xe6\x7f1\x9e\xd6\x0f\x87\x17\xb7\x9e\xe4\ x<\xbc\xf9\xd5\xa7\xd9\xff\xf5S\x1b\x86\xcb\xe0\x9b\xab\ \x83\x97\xee\xf3\xa8\xdf\xac\xbd\xdb_\xc3\xf1\xc2\xda\xfd]\ z\x9d\xcc\xeb\xf9 \xa7\x1a\xec\xf7\xdb\xfa\xf2E\xaf\xb6\ \xd6\xbaux>\xae\x93\xd1\xa4\xb6\xe7\x8e\xb5\xfc\xfd\x96\ \xd70XN\xaf\x07mmo\x5c\xd6\xf4W/z\xb5\ {<\xaa^g\xe5\xfaP\x92~3\xb9\xf1\x88R\x96\ \xcb\xfc)h\xb35\xd1\xbbn\xe0\x7f\x0c\xda\xfa\xec\xf9\ \xb3\xda\xe8uj{\xbd[\xfb\x83\xb6>^\xed,\xec\ H\xb7\xa6\xfa~\xf5G\x93\xda\xe8u\x16\x1e\xf5\xf7:\ +\xf5\xf5\xe6\xea\xf5\xb7\xd9\xc3\xb9\xa5\x1a\xb3\xf6v'\ \xa3\xc9\xc2f\xe7\x99\xd9k\xd0UU\xaf\x8e\x86\x0b\xb3\ +\xedz>H\x00\xbc\x9e\x1b\x1c\xdf~\xfe\xd1\xc2\xcf\ \x0e\x06\xed\xc2Z#\xcb\xaf\x99Lk\xef\xb4\xa9\x9d\xcd\ \xd5\xda\xba:\xa3|\xa6\x9dL\xeb\xe7{\xbcJ\xc8\xe3\ \xfbb\xbd{\xbdg\xa3\xdb\xf9w\x08\xce\xeb7\x93z\ \xf9\xe6\xa2\xaa\xaa\xfe\x1c\x8e\xeb`\xd0\xd6\xd6z\xb7v\ 6Wk\xe7j=u\xf6{\xbf\xfd\xfd\xb4\x86\xe12\ \xf8\xf5\xb4\xa9\x8d\xd5Nm\xf4:7>\xb6>\x18\xb4\ \x0b7,\xb3\xf6\xfdJ\xbb\x9e\x0f\xb2\x9b\xa7\x99L\xeb\ \xe5\x9b\x8b\xeb#F\xab.o\x14{\xa7M\xed\xbaY\ ,\x9d\xb3vZ\xfd\xe6\xf2\xf1\xd7\xdb[\xbe\xc9\xef\x0f\ \xdazu4\xbc^\x0e\xa8\xba|\xa7\xf6\xa6\xf5c\x96\ \xd3}\x1e\x89\xce\xdes\x9e\xd9=\x1e\xd5/\xc7\xa3\x85\ \xbf\xdb\xef7\xf5\xe3\xd1\xd0\xb7\xff\x070\x9b\x9d{\xa7\ \x8b{\x00N\x86\xe3\xfa\xe9\xed\xf0\x9d\xf9i\xd6\xfe\x7f\ \xf3\xf3\xee\xb4yw\xefK\xd2\xf5\x5c\xf9\xee\xfb\xfd\xe9\ \xd9\x13[\xd7\x00\x00n\xb7\xd6\xeb8\x07\x00\x00\x12\x09\ \x00\x00\x08$\x00\x00 \x90\x00\x00\x80@\x02\x00\x00\x02\ \x09\x00\x00\x08$\x00\x00 \x90\x00\x00\x80@\x02\x00\x00\ \x02\x09\x00\x00\x08$\x00\x00 \x90\x00\x00\x80@\x02\x00\ \x00\x02\x09\x00\x00\x08$\x00\x00 \x90\x00\x00\x80@\x02\ \x00\x00\x02\x09\x00\x00\x08$\x00\x00 \x90\x00\x00\x80@\ \x02\x00\x00\x02\x09\x00\x00\x08$\x00\x00 \x90\x00\x00\x80\ @\x02\x00\x00\x02\x09\x00\x00\x08$\x00\x00 \x90\x00\x00\ \x80@\x02\x00\x00\x02\x09\x00\x00\x08$\x00\x00 \x90\x00\ \x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08$\x00\x00 \x90\ \x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08$\x00\x00 \ \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08$\x00\x00\ \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08$\x00\ \x00 \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08$\ \x00\x00 \x90\x00\x00\x80@\x02\x00\x00\x02\xfdU\x91\x0a\ \x00\x00\x00\xb9IDAT\x09\x00\x00\x08$\x00\x00 \ \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08$\x00\x00\ \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08$\x00\ \x00 \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08$\ \x00\x00 \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\x08\ $\x00\x00 \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\x00\ \x08$\x00\x00 \x90\x00\x00\x80@\x02\x00\x00\x02\x09\x00\ \x00\x08$\x00\x00 \x90\x00\x00\x80@\x02\x00\x00\x02\x09\ \x00\x00\x08$\x00\x00 \x90\x00\x00\x80@\x02\x00\x00\x02\ \x09\x00\x00\x08$\x00\x00 \x90\x00\x00\x80@\x9d\xf3f\ \xf2\xd8\x9f\x01\x00\xf8\x80\xce\x9bIu?}\xfe\xac\xce\ \xda\xe9c\x7f\x16\x00\xe0\x03Y\xeb\xae\xd4?\x15]A\ .L,\x14\x06\x00\x00\x00\x00IEND\xaeB`\ \x82\ \x00\x00\x07\x17\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x06\xc9IDATx\x9c\xd5\ \x9b]\xa8UE\x14\xc7\x7f^D\xa2'\x91\xb8\x95^\ \xe4\x22\x11\x11\xe2\x83D>\xf4 *\x22r\xf1\xa1\xa8\ \x87\x1d\xb4\xab\xd1J\xad\x9b\xde\xecj\xd7\x0f\xc4o3\ \xbf\xca\xca\xb2\xd8\xd1\x84\x0dI\x10\xe4C\x9a\x99\x14a\ \xe1\x83\x0f\x22\x11\x11!\x22\x22\x12!\x17\x09\xb9\xc8\xa1\ \x87\x99\xadsf\xef=g\xef}\xf6\xf9\xb8\xff\xb73\ g\xcf\xac\xf9\xff\xcf\x9e\x995k\xad3\x81q\x88 \ \x0a\xe7\x03\xfb\x80\xcb\xc0\xa0\x12\xf2r\xd9\xb1&T6\ \xab6!\x88\xc2\xa7\x80\xa3\xc0=\xa6\xe92\xb0P\x09\ \xf9g\x99\xf1z\xaa\x9aX;\x10D\xe1\xb3\xc0W\xdc\ %\x0f0\x1d8\x13D\xe1\xa3e\xc6\x1c7\x02\x04Q\ (\x80\xcf\x81\x89)_O\x05N\x07Q8\xb3\xe8\xb8\ \xe3b\x09\x04Q\xb8\x0c\xf8\x98\xfa\x1f\xacF\xf2\x07\xbc\ \x0e,PB^\xcc;v\xd7\xbf\x01A\x14.'I\ \xfe&\xb0\x10\xf8\xc8y\xbc\x97\x82oBW\x0b\x10D\ \xe1J\xe0\x03\xea\xe79\x0a,VB\xfe\x08\xbc\x0a\xbc\ \xeft+$B\xd7\x0a\x10D\xe1k\xc0!\x92\xe4\x07\ \x94\x90\xbf\x00(!k\xc0*\xe0=\xa7{n\x11\xba\ R\x80 \x0a_\x07\xde\xc5C>\x86\x11a\x088\xe8\ \x0c\x13\x8b\xe0=\x1d\xbaN\x80 \x0aW\x03\x07H\xce\ m\xd0%\x1f\xc3\x88\xb0\x86\x12\x22t\xd5)`\xc8\xef\ #\xfd\x87\xb9\x82\xde\xe13\x1d\x9e \x0a{L\xff\xd5\ \xceW\xd7\x80yJ\xc8?\xdc>]#@\x03\xf21\ \xae\xa0\x89\xfc\xe5\x19'K\x84\xab\xa6o\x9d\x80]\xb1\ \x042\xc8\x8f\x02\xdf:\x8f\xf6\x01\xa7\x82(\xec\xcf\x1a\ \xcb\xb3\x1cbg\xe9!\xbb\xb1\xe3\x02\x04Q\xf8&\xe9\ \xe4\x07\x80'\x81#N\x97~\xe0x\x10\x85\xf7f\x8d\ \xe9\x11\xa1\x0f-B\x7f\xdc\xd0Q\x01\x0c\xf9w\x9cy\ \x8cav{Cd\x05\xf0\xa1\xd3u&\xf0\xb4ol\ \x8f\x08\xd3\xd1\x22\xf4A\x07\x05\xb0\xc8\xbb\x98\x04\xcc\x8f\ ?\x18\x22\x83\xc0~\xeb\x99\x1a\xf0w#\x1b\x1e\x11f\ \xa0\x97RoG6A\x0fy\x1b\x9b\x95\x90[\x9d~\ \xcb\x81E\xc0q%dT\xc0^\xd6\xc6x\xa2\xed\x02\ d\x90\x1fE\xff\xaa\x93\x9d\xf6\x84\x08M\xd8\x9d\x0d\xfc\ \x8a~\xc3b\x5ch\xab\x00\x1e\xf2\x8b\xd0\x02\x9c\xa4\x05\ \x22\x18\xf2'\x81\xfb\xac\xe6\x1a\x10\xb4m\x0f0\xe4\xdf\ v\x9aG\x81EJ\xc8\xdf\x94\x90\xe7\xd0B\xdcp\x9e\ \xd9\x12D\xe1\xc6&\xecf\x91_\xa1\x84<\xd6\x16\x01\ ,\xf2\xae\xbd1\xe0\xbf\xf8\x83G\x84mA\x14\xae/\ a7\x8b\xfc\xa0\x12\xf2\x08\xb4\xc1\x13\xf4\x90\x8f\xf1\x0f\ \xda\xc5\xbd`\xf5y\x1c\xf8\x0e\x98b=W\x03\x86\x94\ \x90\xee\xcd/\xcbn\x1ay\x805J\xc8;'JK\ \x05\xc8A>\xc6u\xb4\x9b\xfa\xbb\xd57\x8d\xc0mt\ ,\xe0\x87\x06v\xb3\xc8\x0f+!\xf7\xda\x0d-[\x02\ \x19\xe4\xe3\x0d\xcf\xf5\xeez\x81\x93A\x14N\x8f\x1b\x94\ \x90\xe7\x81\x05hqbL\x04\x9ei`7\x8b\xfc:\ \x97<\xb4H\x00\x0f\xf9\x01%\xe4\xf7h\xef.\xcdM\ \xfd\xc2n0\xcbb.\xfa\x12\x04z\x19|\xe3\xb1\x9b\ E~D\x09\xb9'\xadO\xe5\x02x^\xfb\x13\xc0Y\ \xd0\x1e\x9a\x12r\x08p'\xd5\xef\x8eg\xae\xb0s\x80\ \xe7\x819J\xc8\x13\x19v\xb3\xc8oRB\xee\xce\x9a\ o\xa5{@\x8e5\x7f\xd0\x10\xb7\xfb\xac\x05v\x98>\ \x83JH\xd7\xef\xcfc\xd7G~\xbb\xafoe\x02\x14\ \xd8\xf0\xd2D\x98\x01\x8c)!\xafd\xf4\xf1\xd9\xcd\x22\ \x9f\xcb\x81\xaaD\x00\x8f\x877\x04\xecBor6\xf6\ (!\xd7U`\xb7)\xf2P\xc1\x1e\xe0!?`.\ ,\x0b\xd0!)\x1bk\x83(\xf4^gs\xd8\xcd\x22\ \xbf\xbd\x88\xeb\xdc\x94\x00\x9e[\xdd\x88\x15\xba\xbe\x88\x16\ \xe1\xaa\xdb\xbd\x09\xbb>\xf2\x9b\x8a\x8cUZ\x80\x06W\ \xda\x1d\xc6\x9b\x03\xc088s\x81K\xd63\x99\xc7Y\ \x03\xbb\xb3\x81ST@\x1eJ\xee\x019\xef\xf37\xd0\ \x17\x9dsV\xbf^t$\xe7BV\x88\xbb\x81\xdd\x98\ \xfc\x14\xe7\xabR\xe4\xa1\x84\x00\x9e5\xff5 \x9c\xf6\ \x84\x08e\xd1\x0a\xf2Pp\x09d\x90\xbf\x09,QB\ .\x056;\xdfMF\xbb\xb8\x8f\x95\x9d\xa0\xb1\x1b\xaf\ \xf9J\xc9C\x817 \x88\xc27\xd0a%\x1b\xb7\xd1\ 7\xb9\x9f\xad\xe76\x02\xdb\x9c\xe7\xfeEWq\x9c/\ :\xc1*7\xbc4\xe4z\x03L\xdc>m\xcdO\x04\ \x9e317\x00\x8c\xe7\xb5\xc1yn\x0a\xfaM(T\ \xc5\xd1j\xf2\x90\xe3\x0d\xc8\x99\xb1\xf9\x14x\xc5Da\ \xe3~\xeb\xd1.\xae\x8d\xab\xc0\x13J\xc8K9\xecf\ \x91\xdf\xad\x84\x1ci\xd4?/\xbco\x80\xc9\xd2\xa6%\ -\x5c\xc7f\x19p\xc8y\x13v\x02#\xe8\x1b\x5c\x8c\ \xa9\xe82\x17/\xdaE\x1e<\x02\x98\xfc\xbc\x9b\xa5\x1d\ \x05\x16S\x7fE\x8d\xb1\x12\xd8b7\x98[\xd80\xf5\ \x22\xb8AO\xd7n\xdb\xc8C\x86\x00\x86|V~\xfe\ \xacI0\xceC\x97\xa8\xd9X\xef\xe6\xdeL\xf8\xe9%\ \xe0\x16:\xfe\xe7\x06Fm\xbbm%\x0f)\x02\x98\xb2\ \x14\x97N1\x0f\x93\x0c`N-\ k\xb4\x95\xbe}Q\xf4P\x1fw\x07\xbd\xe6\x97\xd8\x0d\ &\x8a\xbb\x0e\x9dk\xbf\x85\x16iW\x19\x83\x9e\x0do\ k\xbb\xc9\x83\x16\xe0E\xc0-:z+\x88\xc2\x04A\ s\xa6O\x03\x1e\xcc\x9b\xa2\xb2\xd1 \x86\xe7\xde$\xdb\ \x82\x09\x00&#\xf3\x13\xc9\xb8|e\xc7P\x15\x01\xcc\ V\xc0>\x06g\xa0E\xe8s\x9eiZ\x84n%\x0f\ IG\xe8a\xe0\x0c\xc9\x0d\xae\xb4\x08\xcd$-\xda\x81\ \xc4u\xd8\xdc\xd9O\xa3\x8f:\x1b\x85E\xf0\x90\xdf`\ n\x8b\x1dGj<\xc0\x88p\x86dBc\xaf\x12r\ 8\xcf\xc0\xe3\x81\x07\x98\xc4\xc0T\x80\xaa\x1e\ w\x89y\xe8\x19vK\x8f8\xa7G\x9c\x03\xb8\xf5\x8c\ \xed-\xee'j\x98\x0a \xdc\xfb\xef\x88xB\xc4\x13\ \x00w\xbe\x9a\xda=\x81\xa9\x00\x92\xcc\x12p9\x1a\xec\ \xde\x8c\x06\xbb7\x04\x5c\xfa\xab\xea\xb6\xc6f\x02H\xf7\ \xfe\x86\xf9\xeb\xba\xff7\xa0\xda\x1a\x9b\x09 \xb4\xff\xb4\ \x05\xbaxZ\x0c]\x00\x98\xfajk\xc6\xc0D\x80\xaa\ \x9eu\x88p\xea\x1b\xe7\xec\xef~o#\x06&\x02H\ \x9f\xfb\xd7Y^\x1a\x83\xc5\xa3u26\x02\x08\xf6~\ \xac\xd8\xffiA\xb2\x18h\xf5\x04\xea\x02\x08[\xdfg\ \xf6w\xc8c\xa0\xd3\x1a\xab\x0b0\x7fl\xf5\xbf\xf3\xdb\ dua\x0cTZcu\x01\x84\x8bZk\xffe\x8d\ \x8c1P\x15@\xba\xf7\xff\xcd\xfe\x8e\x9c1P\x15@\ \xfa\xdaKbqi\x0c\x88p\x9a\xd2\x13\xa8\x0a\xa0a\ \xffe-a\x0cR{\x025\x01N\xce&\x07\x0cD\ \xdf\xfdW\x09\x88ARk\xac&\x80p\xef\x17[;\ dlJk\xac\x22\x80t\xef\x87\xd0\xfe\x8e\x1c1P\ \x11@\xda\xfaJ\xed\xef\xc8\x11\x03\x15\x01\xa4\x9f\xbcB\ \xec\x1f:\x87\x98\x871=A\xb2\x00\x01\xef\xfc\x83\xec\ \xef\x90\xc7 \xae'H\x16@\xba\xf7\x87\xda\xdf\x11\x10\ \x83\xa8\xd68Y\x00\xe9Ec\xec\x1f:7\xa65N\ \x12\xc0\xda\xfe\x0e\xcb\x18$\x09 \xfd\xe4\x15k\x7f\x87\ e\x0c\xa2\x05\x08\xd8\xfb\x93\xec\x1fZ\x83\x81\xfe\xc9\xd9\ \xe4@Z\xf7E\xec\x82\x98\x1f\xf6@\xa2\xe3.SP\ {\xf2\xfe\xdb\xaf\xa0\xa31\xcf/\x88\xdf\x98\xc7\xc0\xe7\ 8\xd7\x13\xfc\x94\x94\x8d\x17\xa0\x8dcb\xd1q\x97\x1e\ \xa1\xf9A\xa9\xe7\xb1\x02\xa6/Z\xe3\xcf\xa3\xc1K\xef\ \x87\x96\xa8\x08\x84\xd8\x7f;\xc8[\xe3(\x01\xa4\xaf\xbd\ \xb6\x88\xb85\x8e\x12\xc0\xea\xb4\x86&\xd2'\xc4`\x01\ \xaaz\xd6a\xf0\xab\xb8e\xe5D\x16\x83\xac\xe7\x04\xff\ E\x8a\x00\xdb^@\xa1P(\x14\x0a\x85B\xa1P(\ l\x83?&\xdev\x0f\xf5\xe9\xb2k\x00\x00\x00\x00I\ END\xaeB`\x82\ \x00\x00\x03B\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x02\xf4IDATx\x9c\xed\ \x9a\xd1i\x1bA\x10\x86\xffQ\xa2G\xb9\x00)\x15\xd8\ \x05\x18;\x05\xc8\x0d\x04\x94\x07\x13\xb2B\x05\x984\x10\ 7\x90\x0e\xee\x08y\x12\xa4\x01\xa7\x808\xa4\x00\xbb\x01\ !?\x07\x1b\x9c\x80\x1cM\x1e|\xab\x07E\xd6\xcd\xee\ \xce\xac\x02\xd9\x0f\x04:\xb8\xdd[~\xfe\xfff\xeen\ \x81B\xa1P(\x14\xfe[(\xe7\xc5\x5c\xe5z?\xe9\ \xe1\x0b\x80#\xe9\x18&\xbc\x9f\xbe\xfdtn\xb5\xa6\x8e\ \xd5\xc4\x9b\xb8\xa7\xc5>\x80\x83\x901\xc4\x18\xba\xca\xf5\ \x8c\x96\x94W\x00\x80\xde\x01\xd8\x0b\x1ct\xd0\x08gB\ 6\x01F\x95\xeb\x13p\x1c1t\x0fD'\xea\x0bj\ \xc8&@\xa7\xb3x\x09`\x103\xd62\x06\xd9\x04X\ 2\xbdJ\x18~\xf4\xab\xb30qA\x16\x01\x12\xec\xbf\ \x22Q\xc0'\xc9\xe3\x80\xce\xc3\x04\x91\xf6\xf7\x10p<\ \xaa\x5c_iE+\xcc\x05p\x95\xeb\x11c\xd8r\xda\ U\xf3\xdb\xc6\xa0\xb9\x8f\xa8b.\x80\xa4\xf63p\xcd\ \xc0u\xdb\x5c\x161\xb0\x8f\xc0c\x09\xdb^\xfb\x09W\ \xa0V\x07\x98\xc4\xc0T\x80Q\xe5\xfa\xc4\x98\xb4\x9cv\ \x0b\xe6\x0b0_\x00\xb8m9w\xd0\xdcO\xd40\x15\ @X\xfb\xef\xc0\xdd\x19\xb8;\x03p\xd76\xa7vO\ `*\x80$\xb3\x0c\x5cN\xc7\xf5\xcdt\x5c\xdf0p\ )\x98V\xb556\x13@Z\xfb;\xc4\x9f7\xfd\xdf\ \x82jkl&\x80\xd0\xfe\xf3\xe5\xb2\xfb\xd5\x1f4\xff\ \xe7msk\xc6\xc0D\x00W\xb9\x1e3\x9d\xb5\x9d\xe7\ \xed\xef\x8fw\x11\x03\x13\x01\xa4\xcf\xfd\x9b,/\x8e\xc1\ \xe3\xa3u26\x11\x90\xd4\xfe5\xfb{\xc41P\xea\ \x09\xd4\x05\x10\xb6\xbe\x7f\xd9\xdf\x13\x10\x03\x95\xd6X]\ \x80\xe6\xb1\xb5\xf5\x9d\xdf6\xab\x0bc\xa0\xd2\x1a\xab\x0b\ \x5c\xd4F\xfb\xaf\xe6\xc8\x18\x03U\x01\xa4\xb5\xff)\ \xfb{r\xc6@U\x00\xe9k/\x89\xc5\xa51`\xa6\ \xb3\x94\x9e@U\x00\x0d\xfb\xaf\xe6\x12\xc6\x00\x89=\x81\ \x9a\x00\xa3\xfa\xf4\x90\x10\x7f\xf7_' \x06I\xad\xb1\ \x9e\x03d\xb5_l\xed\x90sSZc\x15\x01\xa4\xb5\ \x1fB\xfb{r\xc4@E\x00i\xeb+\xb5\xbf'G\ \x0c\x94\x22 \xfb\xe4\x15b\xff\xd01\xc4\x98\xc4\xf4\x04\ \xc9\x02\x04\xbc\xf3\x0f\xb2\xbf' \x06Q=A\xb2\x00\ \xd2\xda\x1fj\x7fO@\x0c\xa2Z\xe3d\x01\xa4\x17\x8d\ \xb1\x7f\xe8\xd8\x98\xd68I\x00k\xfb{,c\x90\xe6\ \x00\xe1'\xafX\xfb{,c\x10-@@\xedO\xb2\ \x7f\xe8\x1c\x04\x0cG\xf5\xe9\xa1t\xde\xe7\xb1\x0b\xba\xa7\ \xc5>\x81$\xdb]\xe6\x84g\xb3\xd7\x1f\xdf\x04m\x8d\ Y\x87\xf9\xf7\x0f\x80\xe6hw\x9c\xef\x09\xbeK\xe6\x8d\ \x16\x00D'`\xd1v\x97\xc1\x92\x97\xdf\xc0\xd1Wj\ \x90\x9b\xb5i\x8d?\xd4\xe3\xba\xf5CKT\x04B\xec\ \xbf#\xc4\xadq\x94\x00\xd2\xd7^;D\xdc\x1aG\x09\ `\xb5[C\x13\xe9\x13b\xb0\x00\xaer=\x02^\xc4\ -++\xa2\x18d\xde'\xf8\xefQ\x04\xd8\xf5\x02\x0a\ \x85B\xa1P(\x14\x0a\x85Ba\x17\xfc\x01'\x82Z\ Q\xf4\xf4`\xcb\x00\x00\x00\x00IEND\xaeB`\ \x82\ \x00\x00\x06\xba\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x06\x81IDATx\x9c\xe5\x9bm\x88UE\ \x18\xc7\x7f\xbb,\x22!!\x22\xb6HL!&\xb2Q\ -\x19f\x22Ib/d\x8e&\xa9\x95z(\xd4^\ L\xb3\xac\xf0\x83JD\xf6A\xb2\xa8\xd4\xdeP\xabQ\ \x8bLD\xa62I\xd1\x10\xd3\xcd\xcc|!YJ\xa2\ \x86\x10\x13\xd9D\x96E\x96e\xe9\xc3\x9c+\xd7s\xe7\ \x9c{\xcf\x9ds\xee\xea\xfa\x87\xfb\xe1>\xf3\x9c\x99y\ \xfeg\xce3\xcfy\x9e9u\xf40\x02m\xfa\x02#\ \xc3\xdf-\x80\x00\x06\x01\xd7\x00\xf5\xc0\x05\xa0\x0d0@\ +\xf0\x0b\xb0OI\xd1\x96\xc5\xf8uYt\x92\x16\x81\ 6}\x80\xc9\xc0\x0c`<\xd6\xd84\xe8\x06Z\x80\xaf\ \x80\x8dJ\x8a\xb3\xd5\xce\xa5\xa6\x04\x04\xda\xf4\x07\xe6\x03\ \x0b\xb0w9\x0bt\x02\x1b\x81\x15J\x8a\xdf\xd3^\x5c\ \x13\x02\x02m\xea\x81g\x80\xd7\x81\x019\x0d\xd3\x05|\ \x0c,QR\x9c\xab\xf4\xa2\xdc\x09\x08\xb4\x19\x0al\x00\ F\xa5\xbc\xb4\x13\xbb\xd4\xfb\xa6\xbc\xee40WI\xf1\ M%\xca\xb9\x12\x10h3\x05\xf8\x04\xb86A\xad\x1b\ 8\x04\xec\x02~\x02N\x00\xa7\x94\x14\x1da\x1f\x0d@\ #0\x14\xb8\x03\x18\x8b\xf5\x1b\xe5\x88Y\x09,VR\ t')\xe5F@\xa0\xcd\xcb\xc0\x0a\xac'w\xe14\ \xf0\x01\xf0\xa9\x92\xc2\xa4\xec\xbb\x1f0\x0d\xebK\x9a\x13\ T50]Iq!N!\x17\x02\x02m\x96b\x9f\ w\x17\xce\x03o\x00\xef%M,\xc5X\x93\x817\xb1\ +\xc4\x85]\xc0\xc4\xb8\xb12' \xd0f>\xb0*\ a2O*)\xfe\xc9x\xcc\xbeX\xc2\x17\xe1^q\ \x1ax\xd8\xf58dJ@\xa0\xcd}\xc0w1\x93X\ \x0e\xbcZ\xee\x99\xf4\x1c\xffA\xe0\x0b\xdc>g\xa5\x92\ \xe2\x95\xa803\x02\x02m\x1a\x81\xe3\xc0\xc0HS7\ \xf0\xb4\x92bmVc\x95\x99G3\xb0\xd31\x0f\x80\ \x09J\x8a\xed\xc5\x828\x07U\x0d>\x8a\x19tA\xad\ \x8c\x07PR\x1c\x01\xee\xc5\xfa\x9a(\xd6\x85\xc1\xd8E\ dB@\xa0\x8d\x04\xa4\xa3\xe9\x1d%\xc5\xfbY\x8c\x91\ \x06!\x09\x8faW_1\x1a\xb1\x0e\xf8\x22\xbc\x09\x08\ \xa3\xbc\x15\x8e\xa6C@\xc93W+\x84K\xfdmG\ \xd3S\x816\xc3\x0a\x7f\xb2X\x01\xd3\x80\xe1\x11Y\x17\ 0[I\xd1\x95A\xff>X\x06\x9c\x8c\xc8\x1a\x80\xc5\ \x85?Y\x10\xb0\xd0![\xab\xa48\x96A\xdf^\x08\ \xf7~\xd7*\x9c\x19h3\x10<\x09\x08\xb4i\xa24\ \xc6\xef$\xf2\x9c\xf5$\x94\x14\xdb\x80#\x11q\x1f`\ &\xf8\xaf\x80G\x1c\xb2\xadY\x07:\x19\xc0\x15\x98M\ \x05\x7f\x02&8d\x1b<\xfb\xcc\x03\x9b\xb1\x99\xa5b\ \x8c\x0a\xb4\x19P5\x01\xe1\x0b\xc9\xed\x11q;6\xdc\ \xbd\xac\xa0\xa4h\x07vG\xc4\xf5\xc0\x18\x9f\x15\xd0\x8c\ \xf5\xa8\xc5\xd8\xaf\xa4\xe8\xf4\xe83O\xecq\xc8F\xf8\ \x100\xcc!;\xec\xd1_\xdep\xcdmx\xf4\x0e\xa6\ \xc1\x0d\x0e\xd9\x1fI\x17\x04\xda\x0c\x07f\x91>\x09Z\ \x0e\xdd\xc0N%\xc5\x8e\x04\x1dW\xbeP\xf8\x10\xe0\xca\ \xed\x9d\x8eS\x0e\xa3\xaf\x9f\x81~\x1ec&aQ\xa0\ \xcdl%\xc5\xfa\x98v\xd7\xdc\xaaw\x82\xb8\xefbG\ \x82\xfe,\xf23\xbe\x80\xb9q\x0daT\x1a\xdd\x09\xfa\ \xf8\x10\x90\xf6\xbd\xfe?\x8f\xb1*\x85\xeb\x0d\xb0\x18%\ \xf6\xfa\x10\xd0\xee\x90\xf5w\xc8\x0aX\x0f\xe4\x19\x1e\x9f\ \xc3\xc6\xfeN\x04\xda\x5c\x83\x8d\x00\x8b\xd1\xe1\xe3\x03\xfe\ u\xc8\x06\xc7)+)\xce\x05\xda\x8c\x00F\x93\xbd\x13\ \xec\x02\x0e\x97)\x97\xb9\xe6v\xc6\x87\x80\xbf\x1c\xb2\x9b\ \x93.\x08\x9f\xc3\xbd\x1ec\xfa\xa0\xc9!3>\x8f\xc0\ \x09\x87l\xa4G\x7fy\xe3N\x87\xec\xb8/\x01Q?\ \xd0\x1ch\x93W\xe9\xcb\x17\xe3\x1d\xb2\x83U\x13\x10\xb3\ \x9c\x1b\xb0U\xdf\xcb\x0a\x816\x02[U*F\x07>\ \x04\x84\xf8\xda!\x9b\xed\xd9g\x1ex\x82\xd2\x1do\x97\ \x92\xe2\x82/\x01[\xb0\x09\x90b\x8c\x0e\xb4I[\x08\ \xcd\x0da\xd1\xe4YG\xd3&\xf0\xcc\x07\x84\x07\x13\xb6\ 9\x9a.\x9b\x8c\x10\xf0<6\x1b\x5c\x8c3\x84\xf3\xce\ \x22'\xf8\x96C6.\xd0\xc6\x95-\xaa)\x02m\xae\ \x07\x968\x9aV\x15^\xdb\xbd\x09PR\x1c\x04\xb6;\ \x9a\xd6\x84\xd5\xa2\x1eA\x98\xaew\x95\xe6\xdb\x80\xd5\x85\ ?YU\x86^\xa2\xd4\x17\x0c\x02\xbe\x0c\xcf\x03\xf5\x04\ ^\xc3\xbd\xf5-+>A\x92\x09\x01J\x8aV\xc0U\ \x01\xba\x1b\xf8,\xbc\x1b5C\xa0\xcd\x1c`\xa9\xa3\xa9\ \x05\xf8\xb0X\x90Ui\xac\x09x<\xa6\xf9Q`S\ \xadVB\xa0\xcd|\ \x08\xa8\x07~$\xfd\xf1\xb7b\xec\x07\xd6\x01\xdb*=\ \xfa\x1a\xfa\x92\xf1\xd8\x14\xdb\x14J\x93\x1c\x05t\x03\x0b\ \x95\x14\xabc\xda\x01O\x1f\x10h3\x04\x9b\xe8\xf4}\ \x03\xec\xc2\xd6\xef\x0e\x02\xbf\x01\xa7\xb0\x19\x1e\xb0\xc9\x93\ F\xe0&l!f4\xe5s\x8bg\x81\x19J\x8a\xef\ \xcb\x0d\x9c\x85\x13\x1c\x87=\x17\x14w'\xce\x00\x9f\x03\ \xf3\x12t\xb2\x84\xc6\x1e\xc9\xa9\xc8\xd9V\xec\x04\x03m\ \x9a\xc2-\xe6\x12()v\x03\xd3)\x0d\x84\xc0\x1a\x7f\ \x8f\x92\xe2E\xe06\xdc\x11cVh\x05&))&\ \xa5\xd9i*Z\x01E\xde~\x00\xd6\xa0}\x0e\x9dq\ \xd8\xd3\xdb\x85\xc7\xa1`\xfc\x89\x88\xdeHl\xe48\x99\ lVD\x0b\xf0.\xb0\xb9\x9a\x13he\x09plu\ g\x80\xbb\x94\x14\x7f:t\x87`_3\x87\xe00>\ \xa2;\x10[^\x9f\x88\xdd\x22+\xad\x19ta\xcb\x5c\ \xdf\x02[\x92\xc6\xa8\x04\x89\x04$\xec\xf3'\x81\xb1J\ \x8aS\x8ek\xea\x81FW[\xc28\x0d\xd8\xa4e\x13\ p#p\x1d\x96\x90zl\xe6\xa6\x0d\xf8\x1b\xbb\xcc\x8f\ \x85\xd5\xdeL\x10K@\x05A\xceI\xe0~\xd7J\xb8\ \x92\xe0t\x82\x15FxC\x81\x03\x816c\xf2\x98X\ \xadPB@\xca\xf0v\x10\xb0\xc7\xb5;\x5c)\xb8\x84\ \x80\x94\xc6\x17\xd0\x06\xfc\x90\xe1\x9cj\x8a\x8b>\xa0J\ \xe3\x9d[\xdd\x95\x84:\xb8z\x8d\x07\xa8\x0b\xf7\xe3\xa3\ $\x146\x1d\xe8\x15\xc6\x83\xf5\x01\x8b\xb9J\x8d\x07K\ \xc0\x03)\xf4{\x95\xf1`\x09\xa84\x04\xedu\xc6\x83\ %\xa0\xb5\x02\xbd^i,\x00\x9b\x99\xe9\xb5\xc6\xc3\xa5\ \x81\xd0C\xc0s\xd8\x8f\x1f\xda\x81\x1d\xd8\x0f\x92\xab\xfe\ 2\xfbJ\xc0\xff/\xf0\x05\xfd\xea\x05|n\x00\x00\x00\ \x00IEND\xaeB`\x82\ \x00\x00\x07\x83\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x07JIDATx\x9c\xe5\x9b\x7f\x8cU\xc5\ \x15\xc7?\xdel\xac\x1aC6\xc4\x10\xa2d\xa2\x84R\ \xb3m\x89?\x91\xf8\x83\x1aB\xc8\x06\xe8\xc4\xb4\x85b\ \xc41B*\x02m\x8d]\xa3\xa21\x84T0\xfeH\ \xac-\xad\x15j\xb4S\xeb\xaf\xa01\xa3 A\xa3T\ \xdb\x0d*AR\x0d\xb5\xab%db\x08*!\x04I\ C(y\xe9\x1f\xe7\xbe\xdd\xb7\x8fw\xee\xbb\xef\xbe\xfb\ \x96\xdd\xf6\x9bl\x02\xf7\xcc=s\xeey3s\xe6\xcc\ |\xcfit\x18.\xc4\x04\x98\x0a\x5c\x02|\x178\x1f\ 8\x17\xe8\x06\xce\x00\x12\xe0\x18p\x04\xf8\x12\x88\xc0?\ \x80\xdd\xc0no\xcd\xb1N\xdawZ'\x94\xba\x10\xc7\ \x01\xf3\x81\xef\x03\xb3\x80\x09\x05U\x1d\x03\xfa\x81\xcd\xc0\ \xcb\xde\x9a}\xa5\x18X\x83R\x1d\xe0B\x9c\x09,\x03\ \xae\x03\xce*S7P\x01\xfe\x0a<\x01l\xf2\xd6\x1c\ /Ci)\x0ep!Z\xe0^`z\x19\xfar \ \x02\x0f\x03\x1b\xdauD[\x0ep!^\x04<\x06\xcc\ lGO\x1b\xd8\x0b\xf4yk^)\xaa\xa0\x90\x03\x5c\ \x88\xa7\x03k\x80;\x80\xae\xa2\x9d\x97\x88\x00,\xf7\xd6\ \xeco\xf5\xc5\x96\x1d\xe0B\x9c\x02<\x07\x5c\xd6\xe2\xab\ \xc7\x80=\xe9\xdf~\xe0k\xe0\x04\x12\x05\xce\x04\xc6\x01\ \xe3\x01\x03|'\xfdw+8\x08,\xf5\xd6\x84V^\ j\xc9\x01.\xc4\xd9\xc0\x0b\xe47n\x1f\xb0\x09x\x1d\ \xd8\xe1\xad\xf9w\xce~\xba\x80i@/\xf0C\xe0\x22\ \xc4Q\xcdP\x01\xee\xf3\xd6\xac\xcbi_~\x07\xb8\x10\ \x17\x01\x7f\x04N\xcfa\xc4\x16dmx\xcb[S\xc9\ \xdbGF\xdf\xd3\x80\xe5\x80#_tY\x0f\xdc\x96\xa7\ \xef\x5c\x0ep!.\x06\x9e\xa2\xf9|\xdf\x06\xdc\xe5\xad\ \xd9\x9dGo\xabp!\x9e\x8bD\x9b[r\xd8\xf2\x07\ `Y3'4u\x80\x0b\xf1G\xc8\x9c\xcf\xea\xf0\x00\ \xf03o\xcd\xa6f\xfa\xca@:\x226\xd2<\xec\xfe\ \x0e\xb1KuB\xe6\xbcJ76\x7f\x22\xfb\xe3\xb7\x02\ \x17\x8f\xd4\xc7\x03xk\xfe\x0e\x5c\x03\xdc\x8fL9\x0d\ +\x80\xd5Y\xba\xd4\x11\xe0B4\xc0\x07doc\x1f\ A\x86|\xdb\xf3\xbc(\x5c\x88\xd7!?\xd2\xd9J\x93\ \x0ap\x83\xb7\xe6\xf9F\xc2\x86\x0eH\xe3\xfc\xdb\xc0\x95\ \x19Jo\xf7\xd6\xfc\xba5sO\xeag<2\xba\x0e\ ykN\xb4\xa1\xe7J\xe0U\xf4\xe8t\x18\x19\xa5\xfb\ \xea\x05\xda\x14\xb8\x1b\xfd\xe3AV\xd8\xc2\x1f\xefB\xbc\ \xd6\x85\xf8\x1e\xf0\x15\xf0\x05\xf0\x95\x0b\xf1q\x17bw\ \x11}\xde\x9a~`\x1epTi\xd2\x0d<\x99f\xa6\ \xc3p\xd2\x03\x17b\x0f\xb2\xd2jx\xc4[\xb3\xbe\x88\ \xa1\xa9\xfe\x85\xc0\x1b\xc8\x02V\xed\xbf\x1b\xb8\x15\xf8[\ :*Z\x86\xb7f\x07p=\xb2\xb9j\x84Y\xc0\xe2\ \xfa\x87\x8dF\xc0c\xe8\xb1~\x1b\xb0\xaa\x88\x81\x00.\ \xc4s\x90lN[T{\x80\x07\x8b\xea\xf7\xd6\xbcF\ \xf6\xa2\xf7`\x9a\xaa\x0fb\x98\x03\xd2\x9d\xdel\xe5\xe5\ \x83\xc0\xcd\xed\xccU`!\xf2kga\x91\x0b\xf1\x8c\ 6\xfax\x08xG\x91M\x04~Z\xfb\xa0~\x04\xdc\ \x97\xa1\xb8\xafH\xb2Q\x87o\xe7hs60\xa9h\ \x07\xe9\x0f\xb4\x14\xc9=\x1a\xa1\xafv\x14\x0c: M\ m\xb5\xb4\xb6\x1fx\xa6\xa8Q5\xd0\x16\xa9z\xe4\xca\ \x194xk>\x03~\xa5\x88\xc7#[j`\xf8\x08\ X\x96\xa1\xf3\xde\x92b\xfd\xdb9\xda\x0c\x940\xd2@\ \x0eL\x0e+\xb2\x95\xd5\x7f$0\x18\xf7\x17*\x8dw\ xk\xb6\x97`\x10\xc8\x22\xda\xdf\xa4\xcd/\xcb\xe8\xc8\ [s\x08\xd9\x0a7\xc2\x85.\xc4\xcb`h\x04\x5c\x8b\ \xbe\x89\xf8m\x19\x06\xa5FU\x90\xf4vg\x03q\x05\ \x19ieL\xb5*\x9e@\x0f\x8b?\x86!\x07\xccS\ \x1a\x1d\x06^.\xd1 \xbc5\x07\x80\xab\x80\x9b\x90\x8c\ \xedYd\xe5\xbe\xbc\x95<>g_\x11xS\x11\xcf\ \x85t+\xecB\xfc\x089\x85\xa9\xc73\xde\x9a\x1b\xcb\ 4j\xa4\xe1B\x5c\x02<\xa9\x88\xcfK\xd2\x90\xd0\xa3\ 4\xd8\xdc\x19\xb3F\x14[\xd03\xc6\x19\x09\xfaqS\ \x05}C1f\x90N\xb9O\x14\xf1\xa5\x09p\xa1\x22\ \x8c%\x85\xa3\xd1\x00-\xf2L\xed\x02.P\x84\x9f\x95\ m\x85\x0bq\x16\xf0R\x93f\x03\xde\x9a+J\xee\xfa\ S\xe5\xf9\x94.\xe4\xa2\xb2\x11\xb4MD;\xe8\xa2y\ .0\xae\x89\xbc\x08\xb4o\xe9N2:\xec\xe8\xad\xec\ \x08C\xbd>K\xc8>J\xfa_\x81\x9a\xc1&Y\xc2\ \xff\x07d9 \xcfM\xccX\x81z\xaa\x9d\x00\x87\x14\ Y\xb3\x1b\xa0\xb1\x04\xf5[\x12\x84\x96\xd2\x08\x85\xce\xe6\ F)\xb4\xc8s0\x01\xfe\xa5\x08'w\xc8\x98S\x81\ o*\xcf\xf7%\xc0\x80\x22<\xdf\x858\xb1C\x06\x8d\ 4f(\xcf?I\x80]4\x0ey\x09\xa7\x8e\xf9Q\ \x1a\x5c\x88\x13\xd0\x93\xbd\x0f\x13o\xcda\xf4Q\xa0\x9d\ \x13\x8c%\xf4\xa2G\xb4\xfe\xaa@;4\x98\xdf\xe6\x11\ \xf5h\xc0\x02\xe5\xf9\x1eo\xcd\x81\xaa\x03\xb4\xbc\x7f<\ By\x1b\x93p!N\x02\xe6(\xe2-044\xde\ B.>\x1aa\xa5\xf2|,`\x19\xfa\x1e\xe0%H\ \x1d\x90r\xed^T\x1a^\x9d\xf2\x04\xc6\x14\xd2\x8b\xd6\ \x15\x8ax\x00x\x1f\x86/\x0e\x8f\xa3'@k\x1b\xdd\ \xac\x8er\xf4\xa1o\xe66V\xef9\x06?\xca[\xf3\ 1\xfabx5\xb0\xa8T\xf3:\x08\x17\xe2d\xe0\x17\ \x8a\xf8(\xf0t\xf5?\xf5\xbf\xea\x9a\x0c\xbd\x8f\x8e\x85\ \x8dQ:R7\xa2\xb3\xc9\xd6{k\x06\xd7\xbba\x0e\ H\x89\x06\xaf)/N\x00\x9eJ9|\xa3\x19w \ \x5c\x80F\xf8\x92\xba\xeb\xf7F\xf3\xba\x0f\xfd4\xa8\x97\ \x92\xae\xae:\x01\x17b/\xb06\xa3\xc9\xaat\xe37\ \x88\x93\x1c\xe0\xad\x19\x00\x1e\xc8Pr\xa7\x0bQ[]\ \x9ba'\xf0\xbd&\x7f\x85.b\x5c\x88\xd3\x11\x16\xab\ 6B\xdf\xa1f\xeeW\x91E\x92z\x17\x9d\x87W\x01\ Vzk~\xdf\xb2\xa5\x1d@\xfa\xf1\x9b\x81s\x94&\ G\x80K\xd3k\xf3a\xc8\xa2\xc9M\x05\xdeC\xcf\xa5\ +\xc0:`\xf5)\xa6\xc9\xcd\x07\xfeL\xf6i\xf2\x0d\ \xde\x9ag\x1b\x092\x99\xa2.\xc49\x08\xfd,\xebt\ h+B\x9d9\xd0\xc4\xd6R\x91.\xc6\xf7 \xac\x96\ \xac\x85y\x9d\xb7F%}enn\xbc5\xdb\x80\x9b\ \xc9>8\xed\x05>t!\xfe KW\x99H\x99l\ \x7fA\xc2v\xd6\xc7o \x9b\xf6\x93\x9b,\xbd\x84l\ vW\x15[\x91\x95\xb6Sd\xe9\x89\x08K\xedV\x9a\ \x9fY>\x8d\xd4\x0f\xb4G\x96\xae\xe9|1r\xcd\x9c\ \x87.\x1f\x80\xdf\x00\xdbK\xa2\xcb\xf7 t\xf9%\xe4\ \xa3\xcbo@*H\xca\xa1\xcb\xd7\x182\x17a\x8e\xe7\ \xbd\xbe\xda\x8b\x14L\xbc\x0a\xbc\x9f\xb7\xc0)\xdd\xcd\xf5\ \xd3k\x01R\x9d\x92\xb7`\xe2~`M^\xc7\x17\ )\x99\xe9A\xe2m#BE\x16\x8e\x22\xc7o\x03H\ \xea}\x1c\xf8O*K\x80o \x8e\x9d\x8c|p\xab\ \xb5\x86\x87\x90\xfa\x80\x96X\xebE\x8b\xa6\xceBv\x84\ ?gt\x14Mm\x05~\xe2\xad\xf9\xbc\xd5\x17\xdb-\ \x9b\xbb\x04\x99\xebY\xc4\xeaN\x22\x22\x04\xce\xc2\xb5\x0a\ m\xe5\xf8\xde\x9a]H\xe1\xc2\x02\xe0\xe3vt\xb5\x88\ \xfd\xc0m\xc0\xb7\xda-\xd4(\xadt6]\xb8f#\ \xc7P\xf3)\xffj\xad\x02\xec@\x0en^\x1cU\xa5\ \xb3\xf5H)\xef\x16)\x9e\x9e\x89\xbeGo\x86\xe3\x08\ \xbd\xe5u\xa4^xo9\x16\x0e\xa1#\x0e\xa8EM\ H\x9b\xc6P\xf9\xfc$d\xc5\xafr\x13N \xab\xf8\ A$t\xfe\x13)\x9f\xdf\xd5\xe9\xf2\xf9\xff\x02\xdd0\ \x17\xea\x91\x8a\x18'\x00\x00\x00\x00IEND\xaeB\ `\x82\ \x00\x00\x07J\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00\x80\x00\x00\x00\x80\x08\x02\x00\x00\x00L\x5c\xf6\x9c\ \x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ \x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ \x09pHYs\x00\x00\x12t\x00\x00\x12t\x01\xdef\ \x1fx\x00\x00\x06\xdfIDATx^\xed\x9c\xbdN\ \xe3J\x14\x80s\xafp\x91(1\x05)\x1c\x22\x97 \ Zv\xc3*\x1d\xf4+\xd0J<\xc1\xa5\xa0\xe3\x05h\ \xaehx\x01\x8a+Q\xf0\x06H+\x10\xfd\xd2\xa1]\ \x96\xb4\xab\x9b\xeeF\xc1.\xa0\xc0AIa\x8a\xeb\xc0\ \xb0\xf9\xf1\x9c\xf1x<\xf6\x89\xe1|\xc5\xee\xc0\x0a\xb1\ \xf8\xf3\xcc\x9c\x9f\x19\xfe\xf8\xeb\xec\xbf\x02\x81\xc7\x9f\xec\ o\x02\x09\x12\x80\x0c\x09@\x86\x04 C\x02\x90!\x01\ \xc8\x90\x00dH\x002$\x00\x19\x12\x80\x0c\x09@\x86\ \x04 C\x02\x90!\x01\xc8\x90\x00dH\x002$\x00\ \x19\xad\x1d1\xb3\xd4\x5c,\xad\x95\xe7j\xe5\x82U1\ \xd8'G\xf8n/\xf8\xf3\xc9y,\xdc:\xfdn\xcf\ \xefz~\xe7\xe5_\xde1:\x04\x98Fsya\xab\ fX\xecciz\xde\xdf\xdf\x1e\xde\xb9\x83\x84K\x90\ \xd1lX'\xeb\xd6\xae\xc2\xd3'\x9eI \xc0\x9c?\ \xdc\x1c>z\xf6!\xa1\x84\xa2\x00{%x\xf1Mz\ \xeb\x93\xa3\x22 x\xfa\x07K\xf4\xe2\xeb!\xbe\x80z\ \x95\x9e\xbeF\xe2FA\xa5\xbd\xcd\x85U6\x06\xe8\xf9\ -\xd7\xfbz\xebw<\x9f}&\xc04\xec\x82Q\xaf\ \x18k\xb5b\xed\xf7\x8eMQP\x5c\x01\xcd\x86\xbd[\ cc\x1e\xfe\xc5\xcd\xfdiw\xec\xb9\x83\x18\xcd\x95\xf9\ \xad\xb2\xff\xcf5\x09\x90\x17P\xaf\x9e|(\xb2q\x18\ z\x9d\x95\x90\xdf\x03\x8c\xed%z\xfa\xfa\x91\x16`\x96\ >V\xd80D\xb0\xf2\xd0\xd3WDV@s\x19\x8c\ \xfa\xdd\xf6\xfd\xa9\xc7\xc6D\x5c$\x05\x94\xd6\xc0\xbdw\ p\xf6Kf\xd7%\xf8\xc8\x090\x0d\xf0\xf9;\xfd+\ 6\x22T\x90\x12`/\x16\xa1\xf5\xa7\xe5\xf4\xd9\x88P\ BJ@\xbd\x0c\xa5\xbe\xfe\xed\xb0\xc4O\xa8##\xc0\ \xa8\x97\xd9(\xc4S\x97\xb6\xdfdH\x09X\x84\x02\xd0\ \x9e\xdfe#B\x11\x89L\xd8\x9c?\x84*\xcf\xce\xfd\ \xceuj{\x808\xf1~\xa6u\xd39\xca\xf9+ \ \x17\x05a`W\xe6\xd8\x08\xa6\xc6\xe9<\xe7\x8cD\x02\ \xdc\xc7\xf42\x00\xe3\x93\x15\xfdp-\xabd\xb3a^\ \x91\x10P\xc1\xe8\xf7\x8a*\x1fcT\x8a\x9fL6\xcc\ )3\xba\x04\x092\x8fI\x8c\x8f\x8b\xf9^\x85fS\ \x80\xd4\xfa\xf3\x82\x05\xe6(\xf9@B@\xcfw\xd9h\ \x9a\xd4~x8\xf0\x0dS+5\xd9(\x97$\x9b\x01\ e#\x95=\xb0^\xe2u=_\x0e\xd6\x85)\xae\xd5\ \xd9(\x8fH\x08\xf0|\x87\x8d2\xa2Y\xe3\x85\xff\xbd\ \xc1\x99\xcb\x0f\xbaVk%6\xca!\xc9f@\xc5H\ \xe1\xe5\xe3\x97\xbe]\xb7\x7fu;\xe0/\x86)M\xc4\ L\x90\x11 \xa8\xb8\xa50\xfd\x81\xd2\xb7\xd3\xf3\xc1\xb9\ \x98\xe7`TJ\xc0w`\xee\x07h\x9f\xfe@\x00:\ \xf81,9\xf4\x7f\xf0\x0d\xe48\x18\x95Z\x82:\xbd\ '6\x0a\xa39\x08\x01\x02\xd0\xd7\xb6\xcf\x953x\xfe\ {\x9a\xfc\xa6\xc4r{@\xb7\xdfb\xa30\xc5\xad\x15\ }o\x1f\x90\x00\x8fj\x1ePL\x9c\xdbUHr\x13\ \x165^\xac\xa5ym\x93\x80_\xf6\xf0\x7f\xde\xbe\x0a\ \xf0\xfa?\xf9\xff\x938\xa9\xc3,!+\xe0\xb4\xcd\x9f\ \xfb\xcf\x14w\x1bzv\x02(\x00\xfd>j\xfb\xf8\xdd\ G6\x9a\x22\xa7\xc1\xa8\xa4\x00\xf1*\x14\xec\x04\x0b'\ \x8dx\xab\xb0m\x96\xf6\x1a\xf3\x93_\x02\x9c\xbdx\x9c\ \xb8\xc9\x04m\x039M\x89\xa5\x05\x14\xfaG7\x82I\ 0tp\xb0QmF/\xc4\x86]\xaf\x1en\xd8\x07\ \xeb\x0b\xabS\x9dN~\x02\x1c\xea\xfb\x83\xafB.S\ by\x01\xc1O\xfep!n\xc1W\x8a\xbb\xeb\xf6\xc9\ Fu{\xa5d\x9b\xe3;\xb3\x11\xbc\xef\xcd\x95\xea\xde\ \x86}\xb2i\x1d|(Z\xbc\xf5\x1a\xe8\xc0\xbc\x04\xa0\ \xe3\x80\x1bR\x1e\xfb31\x8f\xa7\x0b\xda\x93\x0aL\x9c\ (5\xb67\xac\xcfa1\xbcS\xa7\xe0\x0d\x91\x1c\x1e\ Q\x8d3\x03\x02\xbc\x87}\xf1B\xa4\x0c\x14\x80\xba\xfd\ \xf0\x03\xed@5\x89\x1c\x06\xa31\x05\x04t\xefvn\ \x80\x9f?\x01@\x02<\x16\x80\x8e\x03\xd6\x07\xf3\x97\x12\ \xc7\x17\x10\xd0\xbd\xdb\xbf\xf4Z\xe2\xfd \x1eP\x07\x06\ :w\x04\xd5$\xf2\xd7\x9f\x89{Ei\x1c\xa3\xd9X\ HtMu\xb4d\x037\x9f\x04\xc7^\xc0C+\x83\ \xe3\xf3\xbb\xd0qU`\x83a\xf8\x17\x97\xae\xd4\x01o\ \xfe\x16(\xfd\xe5<\x94f\x00\xc3\xbf\xbavw\xce\xdd\ c\x07l\x99\x81\xf4\xfcV\xfb~\xb4aJ\x06\xa0\xe3\ \x80}:\x85`\xd4\xf8\xbc\x8c\x96\xc4%\x11\xf0\xc2P\ \xc3\xfeyg\xe7\xd2=n{\xad@\x06\xe7\xd1<\x7f\ \xd2\x19\x04\x0f\xfd\xf82p\xd6\xd9\xf9\xe6\x1e\xfd\x1a\xed\ \xae\xfc\x04X|\xf0\x14\xacI(\xa5\xc45s\x1bi\ \xf7N\xb2\x04\xe9\x02X\x7f\xa2bJ\xf8\xc6`x\x15\ \x12/AC\xdc\xb6\xbb\x1fy\xd1a\xc6\x96 M@\ \x97\x0f&+\x10a\xc0\x9aDa\xae\x1e\xffu\xd6Y\ R\x8c\x03\xbe\x00\xe8\x08P\xf4\xcd\x03\xb0&\xa1\x16\x8c\ j\xad\xabK\x83\xbe\x04E/\x0e*L/_\x92\xdf\ \x85\x1bA\x8d\xf1\x06\x97 \xc9#\x88qQL\x89\x11\ \xcay\xd8\x02\xd2:x\xaa\xd8\x9fY]\x9a\xaa\x90\xa7\ \x0e\xb2\x00 \x00\xd5\x80b\x7f\xa6b~\xc9v\x12\xe0\ \x0a\x10\xdc~M\x8cj\x7f&\xe3\xce\x1a\xaa\x00 \x01\ \xd6\x84\xea\x82\x9emR\x86\x19\x05Ae\xfdx\x17\x8f\ \xe0\x16\xc5Xn\xc5\x8f\x82Z\xce`\x95\xbb\x06B5\ \xa8\xb7\x15\x05A\x15\xd0p\x0bL\x08\x5c\x93\x88>,\ \xe4\x00=\xbe\x0c'\x01\x9e\x00(\x00\x8d}\xf5\x1e<\ '!\x11\x8cB\x87\xfe\xb2\xeb+\xa0\x09\x80\x12`\x85\ {gpM\x22\xfa9v~y\xdct:\xb3\xca\x04\ \x96\x00h\xfd\x01Z`b\xe0#3\x12\xfd\x99\xfe\xd7\ 6\xf7;fT\x99@\x13\xc0O\x94&\xce`\xc9\x03\ \x17\xae%\x82Q\xa8\xc3\x9c\xcd$@\x12\x00\x05\xa0Q\ \x15P\x00\xc1\xf9m\x89`\xd4{8\xe378\xb3\xa8\ L\xe0\x08\x80\x12`\xe5\xdf\xbd\x02\x9e\x93\x90K\xac\xae\ \xfe\xf5\xb8_\x9eAeb\x16\x1a2\x19\x00\xe4\x01\xa3\ \x84\x03,\x97N$%o\xb3!3\x13\x80\xa7\x8f\xd3\ \x9e\x04$\xe0\x15\xe8\xe0e\xca\x87\xbdH\xc0o\xc0\xa4\ ,\xd53\x13$`\x04\x94\x94\xa5Z\x99 \x01\xe3@\ IY\x8a\x93\x80\x04L\x00\x86\xb3\xa9\xdd\xfe \x01\x93\ \xc0IYJ\x95\x09\x120\x0d\x94\x94\xa5t\x13\x96\x04\ \x84\x80\x1a\x0c\x15\xf3\xcb\x22\x1bj\x84\x04\x84\x81\x932\ K\xff\x11\x02\x12\xc0\x03L\xca\xf4\x1f\xa2!\x01\x5c\xc4\ \xf7\xa2uB\x02\x00\xc4\xf7\xa2\xf5A\x02 \xa0\xa4L\ 3$\x00\x04\xacLh\x85\x04\x08\x00\xaf\x02j\x84\x04\ \x88\x80\x922\x8d\x90\x00!`eB\x1b$ \x02\xf8\ \xd0\x91\x1eH@\x14\x91\xbf\xa2$\x19$ \x92t\x93\ 2\x12 A\x9a\x93\xe0\x9d\x1cK\x99]h\x06 C\ \x02\x90!\x01\xc8\x90\x00dH\x002$\x00\x19\x12\x80\ \x0c\x09@\x86\x04 C\x02\x90!\x01\xc8\x90\x00dH\ \x002$\x00\x19\x12\x80\x0c\x09@\x86\x04 C\x02\x90\ !\x01\xc8\x90\x00dH\x002$\x00\x19\x12\x80\x0c\x09\ @\xa5P\xf8\x1fN\x10\x99C,*pB\x00\x00\x00\ \x00IEND\xaeB`\x82\ \x00\x00\x05\xa4\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x05kIDATx\x9c\xed\x9b{\x88UE\ \x1c\xc7?^.\xb1\x88\x88\x88D\x88\x0c\x22\x9bm\xb6\ \x98\x7fD\x19YD\x86Q\xb2S!\xbd\xac\xc6\x1e\x7f\ \x84\x81\x90\x05\x15\x96DDV\x14A\x10\xbdD\x93S\ \x06E\x0f\x1d\x1fEe\x7fX\xda\x932\x11\xd3El\ \x19d\x89E\x16\x11YB\x96\xa5?~\xb3yw\xf7\ \xee\xdds\xe6<\x97\xfa\xc2\xe1\xc293\xf3\x9b\xf9\xde\ \x99\xdf\xf3\x1c\xf8\x8fcJ\xd9\x13\x88\x03c\xdd2`\ \x0dp\x1a8\x0at\x03G\x80c\x91Vg\xd2\x8c]\ y\x02\x8cuO\x02\xcf\x03\xb5&\x8f\x87\x80^\x84\x90\ n\xe0\x0f\x84\x98#\xc0\x89H\xab\xa1\x89\xc6\xaf,\x01\ \xc6\xba6`#pO\xe0\x10\xa7\x11\x22\x0e\x03\xbf\x03\ \x87\x80\x83\x91V}\x8d\x8d*I\x80\xb1n\x16\xf0\x19\ \xb0$\x87\xe1O\x00\x07\x80\x9f\x81\x9d\x95#\xc0X\xd7\ \x01\xec\x00\xda\x0b\x10w\xb0\xd9\xb9*\x0d\xc6\xba\xeb\x80\ }\x14\xb3x\x80\xa9\x95!\xc0Xw\x1f\xf090\xb3\ @\xb1\xf5z\x81\xc2\x9a\xc2XW\x03\x9e\x05\x9e.C\ ~\xa9\x04\xf8\xc5o\x04\x1e(k\x0e\xa5\xef\x00`+\ \xe2\xdc\x5c\x0at\x02\xf3\x81\xb6\xa2\x84W\xd1\x0a\xb4\x01\ s\x81\x0e\x7f]\x8c\x902\x1f\x98As\x87(\x14=\ \x95#`<\xf8\xe32\x0b\x98\x87X\x89\xf5\x08)i\ 0y\x08\x18\x86'\xe2e\xe0\xd1\x0c\x86\xeb\xa9\x82\x0e\ \x88\x0d\x7f<\xde\x05\xee\xccj\xccIC\x80w\x8f?\ \x01\xae\xc9r\xdcIA\x80\xb1n\x1e\xb0\x0bQ\x8a\x99\ \xa22\x9e\xe0x0\xd6]\x8e\xb8\xc7\x99/\x1e*N\ \x80\xb1N\x03{\x80\x0b\xf2\x92QY\x02\x8cu\x0f#\ g~Z\x9er*\xa7\x03\xbc\x99{\x01x$S\x14k\xd7Tj\x07x3\xb7\x95\xf0\xc5\x1f\ \x04\xae@2A\xb1P\x19\x02\x8cu3\x91p8\xd4\ \xc6o\x03\xae\x8a\xb4\xea\x01\xce\xc6\xedT\x09\x02\x8cu\ s\x81o\x81k\x03\xba\x0f\x01/\x02+\x1a2\xc4\x83\ q;\x97\xae\x03\x8cu\x8b\x10\x1b?;\xa0\xfb\xdf\xc0\ \xeaH\xab-\xa3\xeeO\x0e\x02\x8cu\xd7#\x9a~z\ @\xf7>\xe4_\xff.\xcd\x1cJ#\xc0X\xd7\x89\xfc\ \xf3\xe7\x05t?\x04\xdc\x1ciu<\xe54z\xcb\xd4\ \x01\x87\x01\x1b\xd0\xef\x0b\xe0\xea\x0c\x16\xbf\x17\xe8\x8aM\ \x80\x0fF2\x83\xaf\xda\xac\x02\xf6'\xe8\xf6:\xd0\x15\ iu*\xa5\xf8\x0f\x80\x1b\x22\xad\xfa'<\x02\xc6\xba\ :R\x9a\x9a\x0d\xdc\x9bR\xf0\x08DZ\x0d\x18\xeb\xba\ \x10\x0b\xb0\xa0E\xd3A`M\xa4\xd5[1\x87nU\ \x12\xdb\x00\xac\x1f.\x9b\xb5$\xc0X7\x03\xf8\x10X\ \x06|\x1cSx\xb3q\xea\xc0K@-\xd2jm\xe3\ \xb3H\xab~c\xddr\xe0{\x9a{o\xfd\xc0\x1d\x91\ V_'\x10\xd9\x8c\x80\xb3\x88\xc5\xd8\xdcxs\xdc#\ `\xack\xf7\x93Z\xe6o\x05)Lc\xddt`;\ \x92\xc1y\xc4X7\xa6\xd6\xe7\x9d\x97.``\xd4\xa3\ n\xe0\xca\x84\x8b\x87\xb1\x04\x9cB\x8e\xce\xe6\xd1\x0d\x9b\ \x12`\xac[\x82,\xbe1\x04ML\x80\x8f\xe3\xf7\x01\ 75\xdc\xde\xe8C\xdc\x11\x88\xb4\xfa\x05x\xa8\xe1\xd6\ 7\xc8\xe2\xbb\x93\xcae\xa4\x1fp\x1c\xf1\x10\xbfl\xd6\ p\x0c\x01\xc6\xba\x95\xc0WH\x02\xb2e\xdbVh \ \xb1s\xd4\xa36`\xbb\xf7\xfeF \xd2\xea}\xe0U\ \xe0\x1d\xe0\xc6H\xab\xfe$2\x1b0L\xc0^\x84\xc4\ \xc3\xe35\x1c\x91\x145\xd6\xad\x03\x9e\xa3\xf9bwG\ Z-\x8f#\xdd\x97\xb9\xde\xa4u~\xff\x08b\xceN\ \xc6\x193\x09\x8cu\x9b\x90\xe3\xf4X\xa4U\xcb\xb8\xa0\ \xee;\xd4\x81\xb7IY\xa1I\x18\xcav\x00;\x8cu\ K#\xadF\x9f\xfd\xb4x*\xd2\xea\xaf8\x0dk^\ I\xed\x22\xfd\xe2\xa7!nm\x92Pv1\xf0\x9e'\ .3\xc4]<\xc8V\xdf\xce9M\x1f\x04c\x9dB\ l\xf9-\x01\xdd5\xb00\x8d\xfc4\xa8\x01sb\xb6\ mj\x05\x8cu\x8b\x11e\xb7(@\xfe\x19\xc4\xa7?\ \x10\xd07\x13\xa4\xdaz\xdeb\xec!,\x94\xed\x03\x96\ FZ\xedN3\x87\xb4Hb\xdb\xffm\xdbP\xd3_\ G\x18\x89\xdd\xc0\xf2H\xabc\x01}3Eb\x02\xbc\ \xb2\xdb\x04\xdc\x1e(\xf3\x07d\xdb\xf7M\xd8\xb2\x00$\ \x22\xc0X7\x07y{\xeb\xb2@y\xdb\x80\xbbs0\ {\xc1HB@;\xf0#a\xe7\x1d$\x94]\x1bi\ \x15;]U\x04\x92\x10p~\xa0\x8c!\xe0\x89H\xab\ W\x02\xfb\xe7\x8a\xbcSb\x03\xc0\xfd\x91V\x1f\xe5,\ '\x18y\x12p\x12\xb85m\xd22o\xe4E\xc01\ \xc4\xcc\x85\x84\xb2\x85\xa2F\xf6$\xfc\x84Dy\x95_\ \x22)@KmzOz#\ H\xf4\x04\x90g\x7f>N\xdb7\x80\xa8\x09\x90V\xe6\ o\xca\xb3\x7fN\xc4\x04hS^+\xa5KL\xbb\xb5\ S4\xd7\xf7\xccgo\xca\x1d\x7f\xdc;\xf9\xe2\xf1\x8e\ \xd12m\xfa\x93\xc3B\xb4\x04\xe4T\xf6\xe4c[\xf9\ \xbd\xf2\xdanm\xabBV\xfa=\xebK\xf7N\xa1\xd2\ \xdc:\xa8\xad\xed\xbaJ\xd6\x8b\xd6\x8e1\x04kPB\ \x00\x01\x96c\xd0\xd6\xcfF\xbe\xa7\xd2\xd6\x15Z\xf9\xdd\ z!\xf0\x0e\xab\x5c\xa9o\x1d\x98\xaf*\xf42\xca\x5c\ \xdb\x08\x902\xdes\xcbi\xe5G\xb7*\x12\xab\xff\xcd\ R=\xf0\x8eo\xc8\x18D\xc0\xb8\xa6\xd0\x968\xb6s\ \xf9\x98&%V\xf85\xec\xe1\x98O\x04\x08\x22\xc0\xa9\ zG6\xd6C\xed\x85&\xcf\xd1V7\x0d\xa7L[\ 7\x94@\x02*\x0d\xda\xeaA\xed9\x14c\xa3'\xc7\ i\xab\x1b\xb3\x11\xe8\xd1\x9e\xcbN\xe9\xb49j\x04\x9a\ \x82*\x8cnJg\xa7r\xb4\xe9\x8f\xfc4\xeb\xa9\xca\ \xf9P\xed\xf8\x97\xddCM\x06I\xe5\xf9\xech\x1eK\ \x04\x12P\xae\xb6\x18]\x13_]\x94i\x93\x8d>\xab\ x\xcf?\x86\xd5u\x0e\xea\xbb\xdcJg\xd3\x9b\x0f\xa7\ r\x83G\x9d\x88\x11,\x08[\xcd\x0f\xac\x0d\x8e:\xbd\ 1+\xfb\xcc\x0f\xba\x96z\xe9\xfd\xf8\xc7\x0e\x8d&m\ QX\xc1\xe6\x82\xa4\xb2\xba\xa4o,\x8e\x94\x86\xc0\xdf\ \x0d\xd5R\x9b>G4\xb6shZ\xffT\x9b\x97\xc9\ \x10E\xd2\x93d\xe6Q\xe6X\x81\xda8~v\xd0#\ \xa0\xdfo\xe9\x84l\x89K\xf5}\xb2)\xa3\xd7\xc3\x0a\ \xc7\x87[s\x8b\xfa*s\xa3\xc4\x0b+\x99\xc3\xca\xdb\ 01\x0dkXr/\x9e\x8c\xcd\xfd\xfe'm\xf6\xe3\ K\xf5\xf4\xf6]9\x0c\x05\xce\xce\xde\x7foO\xe8E\ 7g\x1f\xbf\xddzpg2A/\xfb\x93HN.\ \xdcI<\xb9+\xdf\xfe~b\xd8g\x817\xcbQ\x81\ C\x00\xe9\xb8\xfdO\xa7\xb73\xb2:I\xaf\x85\xe8\x97\ \x83<9y\xf7}\xe2\x09w*fLU\x13\x8f\x88\ \x86_\xce\x8c\x9a3D\x1a\xb8\x04\x10\x9c\xfd\xcf\xad\xaf\ \xca\xe4Br\x8c\xde\xe0\x81L\x17\x7f\x17\x8f\xdf\xf6\xed\ \x1e\xbb\xf9\xfa\xfb\xc4\x03U\x0a>\x0e.\x18S\xa7\xe5\ G\x99\x89q\xc7\xf9h\x9f\xd1{\xd1\x86#\x06t\xa1\ \xf0\xe5\xcaM\xbb\xb5]\xac\xf3\xcd\xd4\xe4W\xccOs\ \xc5\x83N\xcc\x92\xb9v4\x04\x81AT\xc0\x05\xba&\ \xdfW\xe5\x85\x04\xd9\xe8J\xe9\xae\xcerL;f4\ ZU\xa39\xc8ZE\xd7\xa6\xfc\x96R\xbe\x98\xc6\xf1\ \xda\xd5\x85V\xc4\x18T\xc05\xc19\xe0~\xc0\x1a\x07\ \x02+:\xd3=\x10\xbc\xa8>\x0ao\xf9;$\x02(\ \x12\x19\x10\xcf\xb3\xf1\xee\xa1\xe6\x8fw\xcc\x0faI\xdd\ \xde\x88lU\x06\x9d\xe5x\x830,g\x96\xdd|\xf7\ \xd9zm\xb6\xbe:c\xdat\x90(=63y\xfa\ \xba\xf3\xc4\xa9\xcd\xaf\x99\xa9\x05\xd1\xe8B\x99\x94f\xd4\ \xc4\x93\xcc\xc4\xd7o\xcd/\xdeK\xea@\x04;\x8a\x88\ \x1a\x96S8\xaa\xad\xb9\xa9\xc7\x00I`U\x0evb\ (D2\xbe\xba\x94^\x19\xe0hd8\x05\x5cP\xae\ \xd4\xd6v\xcd|\x9f\xf4o\xfc\xde\xcf-\x91\x93\x96\x07\ p0\xdc\x02\xda8\x85\x03s\xbd4\xe8\x5c<\x18\xd2\ \xf2L\xffSaO\x86+\x08\xfb\xe1\x13W\xaf\xae\x85\ X?|X,{\xa4\xf2\xfb\x1e,\xba\x04-\xf3\xee\ a\x04F\x00\xa5`\xb4h+t,\xa7\x5c\xa9\xbf\xda\ m\x87\x1cz\xeb*\xd2BF$e4:\x02\xae\x01\ 7\xe4\x14\x99\x9a\xd3\x09\x14\xc0 \xcc\xa2\x8aJ}\x87\ \xb5\xeeJH\x02\x89\xeb\xd1\x11\xc0\xae\xaa\xeb\x97h\xe3\ \x83Y\xa2 Ft\x04\xb8\xa9\x98\x17\xbe\xd9M?\xb4\ \x14sgk\xb7\xf6C=\x9ef\x95(\x88\x11\xa9\x11\ \xcde\xa7_>\xd67\xcfM\x04^Y\xebZ\xca\ \xa7\xa2\xdd4\x9b\xe1\xa6-5\xd6\x5c/T\xe3\x14\xc9\ )(\xd96\xb1\xa4o>\xd67\x1e\xa6Vf\xe5\x1c\ Y\x08*=\xffmrG^\x99Mm<\xd6_\xce\ \xc7\xd9\x15\xed\xdd\x95/! i\x8c\x03\x90\x805N\ =Dg\x1f\xc0\x9d\x0d\x0e\x02\xefi\xa8\xf7>\xa0\x13\ \xe6+\x8b7~\x1f\xe0\x81m\xfd\x15vN&7\xc3\ x\x7f\xa4\xa7\xc6)0\xa3+\xc0\xb6\xd6w\xeb\xa1\xce\ \xfeRn1\xcd\x08\xf5\xce\xce'\xc1\xcc\xcfh\x0a0\ \x8d\xe3\x10{\x9f\x84\x9f\x9c\x1blH\xef{\x87_\xb3\ t,\xf6\xf8\x13F.\x06\x04\xcb\x93\x84\x90\x90\xb9`\ \xc0\xe4s\xa4\x0e\xe3$]\x93\x9ff\xe3s\x81\x8b\xae\ ;\xe1\xca\xfb\x87#\xc0}a\xad&\xfc\xec\x9f\x13\xd5\ \xd3P2\xea\x93\x92\xa6\xca\x99\x98\xfbq\x08\xe2\xe6J\ \x1a\xd2M\xfa\xc7\x1a\xa7F\xa3\xf9\xbe\xea\xf0V\xc6\x85\ !\xc09,\xb5\xdeW9^\x9c\xf2dt\x8e\xa3\xb9\ \x08q\x0a\x22\xe3 _\xac\x09k\x18\xe9e\xe8\xf5\xd0\ \xceJ\xbe\xd0D\xa6M\x02\x0a\x08\x05in^\xf0\xdb\ 8\x05u\xc1\xd8\x09\xbb\x07!\xf73\xf2B\xd6\xe7\ \xcc\x83\xc0\xf5\xfd\x1e\x0a\x8e\x80 8e\xab\xb9\xe5\xd6\ a\x98y\xbf\xe4s\xfc7\xfe\xf7\xa8P\x00\x17N\xe1\ \xc8\xaf\x00 \xf0Ks\x97\xa0\x00n\xcaG\xc7\xcc\xa4\ \x18\x7f\x09\x0c\x0a\x10\xc0\xd9*13\xc3\xc1_\xdd=\ \x07\x05\x08\xe1\xf3F-'(\x00\x18\x14 \x04\xfb\xb3\ \x16\xbc\xa0\x00\x11X_^ \xf0\x96\xc0\xa0\x00\x01X\ _^ p\x97\xc0\xa0\x00nr\x8b\xd3\xde_^ \ \xf0\x97\xc0\xa0\x00.|\xb2\x92.\x02%0( \x08\ \xed\x12\x98\xc5\xb4OV\xb2Mk\x9b?5\x86\x87q\ \xa1\xd1\xbf\xa4\xc5\x0b\x1c\x01\xe1`\x96\x04\xbf\x11\x88\x02\ \x06\xc79,\x8a\xe7\xe5Q\xc0@\x98\x86\x95\xdf#\xcf\ \xbe`\xef\x13P\x80 \xed\xae/\xaf\x1d`R^\x08\ \xee \xdc>}3\x1a\xa7\xd5Fs\xbf\xf3\xbbT\x03\ sC\x05D\x07\x9c\x82\x80A\x01\xc0\xa0\x00`P\x00\ 0(\x00\x18\x14\x00\x0c\x0a\x00\x06\x05\x00\x83\x02\x80A\ \x01\xc0\xa0\x00`P\x000(\x00\x18\x14\x00\x0c\x0a\x00\ \x06\x05\x00\x83\x02\x80A\x01\xc0\xa0\x00`P\x000(\ \x00\x94X\xec\x7f{\x17\xee;\xcf \xfd\xf3\x00\x00\x00\ \x00IEND\xaeB`\x82\ \x00\x00\x03r\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00\x80\x00\x00\x00\x80\x08\x02\x00\x00\x00L\x5c\xf6\x9c\ \x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ \x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ \x09pHYs\x00\x00\x12t\x00\x00\x12t\x01\xdef\ \x1fx\x00\x00\x03\x07IDATx^\xed\xdc\xbdn\ \x13A\x14\x86\xe1\x05\xc9\x85-y]\xd0l\x82R\x1a\ \xa5\x8d\x10\x88\x0e\xfa\x08\x84\x94+\x80\x9e\x1b\xa0\xa3\xe1\ \x06\xe8\xb8\x87H((\x17@g\xf1\xe76\xc2\x1d\x96\ \xb1\x0b(\xe2Hv\xe1\x06C\x8e\x1c/\xdeYB4\ 3\xdf\x8a}\x9f\x86qA\xf5\xea\x90=\xe3%\xd7\x9e\ \x1c}M\xa0s\xdd\xfe\x84\x08\x01\xc4\x08 F\x001\ \x02\x88\x11@\x8c\x00b\x04\x10#\x80\x18\x01\xc4\x08 \ F\x001\x02\x88\x11@\x8c\x00b\x04\x10#\x80\x18\x01\ \xc4\xae\xf2\x95\xe4\xcen\xf6\xa2\xdb\xb0\x0f\xeb\xc6?\x9e\ ~\x9c\xd9\x19\x97\xc3\x04\x88\x11@\x8c\x00b\x04\x10#\ \x80\x18\x01\xc4\x08 F\x001\x02\x88\x11@\x8c\x00b\ \x04\x10#\x80\x18\x01\xc4\x08 F\x001\x02\x88\x11@\ \x8c\x00bU\xf8N\xb8\xf5\xec\xe1\x8d=;{1\x7f\ \xfd\xf6{\xcf\xceU\xc7\x04\x88\x11@\x8c\x00b\x04\x10\ #\x80X\xd5\xdf\x8c\xfb\xef\xdf\xc2c\x02\xc4\x08 F\ \x001\x02\x88\x11@\x8c\x00b\x04\x10#\x80\x18\x01\xc4\ \xbcn\xc2WS\xba\xd3\xb2\x09#,\x02\x88\x11@\x8c\ \x00b\x04\x10#\x80X\xd5\x7f{:\x8f\xa1\x08\x8b\x00\ b\x04\x10\xab\xc3\xcf\x80\xc6\xc1\x83l\xbfm\x1f6,\ \x8e\xdfM\x0e\xa7\xf6\xa1L\xdayy?\xcd\xec\xc3\xca\ \xa5\xff\xba\x03\x13\xd0\xd8\xbf\xd5\xb2\xa3\x02\x01\x92d+\ =H\xed\x18\x1f\x01\x96\x1a\xb7\xb7\xfd]\xee\xfe#\x02\ \xfc\x92u;\xf7\xec\x18\x1b\x01\xce5\x1f\xedj\x86\x80\ \x00F5\x04\x04Xi\xde\xb9i\xa7\x98\x08pa\xaf\ \xdb\xd9\xb1c<\x04X\xd3N\x1fG\x1f\x82*l\xc2\ \xa1\xff\x93^\xf9&\x9cW\xb2`\xb3\x09\xc7\x10})\ \xabo\x80\xfexn\xa7\x9c\xd87\x135\x9e\x80\xf1\xe9\ \xf1\x99\x1ds\xe2\x0eA\x9d\xff\x09Z\xbc\x9f,\xec\x98\ \x13\xf5f\xa2\xd6?\x03\x86'\xd3\xbe\x1dsb.e\ U\xff>\xc0\x87\xe2\xa7\xa0\xfe\xe7\xe1\xab\x91\xf3\xfb\x86\ \xc9`\xf2\xfc$?\x1f<\x05\x850\xfc6\x9f\xd81\ '\xda\x10\xd4=@2==\x1a\xdb1/\xd2\xcdD\ \xed\x03$I\xef\xcb\xb4p\x08\xe2\xdcL\x10`9\x04\ \xb3O\x85\xcf\xa3Qn&\x08\xb0\xb48\x1c\x14.e\ 1\x86\x80\x00\xbf\x8d\x1cKY\xbby7\xf0RF\x80\ s\xce\xa5,\xf4\xcd\x04\x01\x8ck)\x0b}3A\x80\ \x95\xd9\x9b\x81`\x08\x08p\xc1\xb5\x94%[\xadpK\ \x19\x01\xd6\xb8\x97\xb2p\xefL\x10 \xc7\xb5\x94eY\ +\xd0\xf3(\x01\xf2J\x96\xb2m;\xfaE\x80?\xb8\ \x97\xb2\xaci'\xaf\x08\xb0\xc1\xb9\x9456\xee\xa2=\ \xc0&\xe7\x10\x84@\x80\x22\xa3Y\xf1R\x16\x00\x01\ \x0a\xb9\x962\xff\x08P\xccy3\xe1\x1b\x01\x5cf\x1f\ \x8a\x972\xcf\x08\xe0\xe4Z\xca\xfc\x22\x80\x9b\xf3f\xc2\ '\x02\x94\xe9\x15\xbf\xbe\xe8\x13\x01J\xb9\x962\x7f\x08\ P.\xf8RF\x80\xbf\x09<\x04ux5\xb1\xd2\x98\ \x001\x02\x88\x11@\x8c\x00b\x04\x10#\x80\x18\x01\xc4\ \x08 F\x001\x02\x88\x11@\x8c\x00b\x04\x10#\x80\ \x18\x01\xc4\x08 F\x001\x02H%\xc9O'I\xe2\ \x09N\x15&\xc1\x00\x00\x00\x00IEND\xaeB`\ \x82\ \x00\x00\x05p\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x05\x22IDATx\x9c\xed\ \x9b\xddk\x1dE\x14\xc0\x7fYB(\xa5D)\xa1H\ \x08K,%\xa9\x89->\x846\x8a\xa2\x88T\x88f\ )*\x01\xbf\xd0\x81Z\xa5\x88\x96\x0a\x96>\x04\xc9C\ \x08R4(\x88\xe8\x83\xebG\xff\x81\x0e\xea\x9b\xd4\x07\ \xad(~\x80\x11[\xf3Pd(\xa5h\xe9C(\x22\ %\x5c|\x98\xb9\xe9\xbd\x9b\xbd\xbb\xb3\xbb3{\xd5\xe4\ \xf7r\xc9\xee\x993g\xce\x9e\x99\xd99g\x03\x9bl\ \xb2\xa1\xe9\xe9V\xc7B\xaaI`\xd2\xfcy6\x8e\xc2\ \xef\xbaaG\xed\x0e\x10R\x0d\x01\x1f\x01\xf7'n}\ \x09<\x13G\xa1\xaa\xd3\x9eZ\x1d \xa4\xda\x09\x9c\x01\ \xc2\x0e\x22\x97\x81{\xe3(\x5c\xae\xcb\xa6\xda\x1c \xa4\ \xea\x07\xbe\x05v\xe7\x88\xfe\x0a\xec\x8f\xa3\xf0\x9a\x7f\xab\ \xa8\xa3\x13\xc3\x1c\xf9\x83\x07\x18\x03f=\xdb\xb2F\ -\x11 \xa4\x1a\x03~\x02\xfa,\x9b\x5c\x07\xf6\xd41\ \x15\xea\x8a\x80E\xec\x07\x8f\x91]\xf4dK\x1b\xde\x1d\ \xa4:\x08\x1c(\xd1tJH\xf5\xb0k{\x92x\ \x9d\x02B\xaa-\xc0\x12\xb0\xab\xa4\x8ae\xf4T\xb8\xee\ \xce\xaav|G\xc0Q\xca\x0f\x1e`\x04x\xc9\x91-\ \xa9x\x8b\x00!\xd5 p\x0e\xe8\xaf\xa8j\x05\x18\x8d\ \xa3\xf0ru\xab\xd6\xe33\x02\x16\xa8>x\x8c\x8e\x05\ \x07zR\xf1\x12\x01\xe6=\xffk\xdc9\xb8\x01\xdc\xe9\ \xe3\xbc\xe0<\x02\x84T\x01z\x0bs\xa9;\x00\xde2\ \xba\x9d\xe2c\x0a<\xc1\x8dS\x9eK&\x8dn\xa78\ \x9d\x02B\xaam\xe8\x85o(Gt\x058\x05\xfc\x80\ ~\x08{\x80\xa7\x80\xed9\xed.\x02\xe3q\x14\xaeT\ 4u\x8d^W\x8a\x0c'\xc8\x1f\xfc/\xc0t\x1c\x85\ \xbf\xb7^\x14R-\x00\xa7\x81}\x19m\x87L\x1f'\ *\xd8\xd8\x86\xb3\x080G\xdd%`k\x86\xd85\xf4\ \x13L=\xf3[n\x9d\x7f\x1b\x1d\x17\xca\xda\xda\x8a\xcb\ 5\xe0u\xb2\x07\x0fp*+\xe1\x11G\xe1%\xe0\xc3\ \x1c\x1d[\x80\x93\xc5L\xeb\x8c\x13\x07\x08\xa9\xee\x03\x1e\ \xb1\x10=c!\xf3\x85\x85\xccA!U2\xa3T\x8a\ \xca\x0e\x10R\xf5b\xbf\xed]\xb5\x90\xf9\xcbB&\x00\ \x16M\xdf\x95p\x11\x01\x87\x80;,e;\xa5\xc2Z\ \xd9a\xa9k/p\xd8R\xb6#\x95\x1c \xa4\xda\x8e\ \xce\xf4\xd8r\x9b\x85L\x91\xc3\xd3\x9c\x90j\xa0\x80\xfc\ :\xaaF\xc0,\xf6O\x0c\xe0v\x0b\x99\xf1\x02\xfa\x06\ \x80\xd7\x0a\xc8\xaf\xa3\xb4\x03\x84T\xbb\x81#\x05\x9b\xd9\ 8`\xac\xa0\xce\xc3B*\x1b\xbd\xa9T\x89\x807(\ \x96\xe6\x02\x18\x14R\xdd\xdc\xe9\xa6\x90\xaa\x0f\x9d\x03(\ B\x9f\xb1\xa5\x14\xa5\x1c \xa4\x9a\x02\xa6J\xf6\x97\xf5\ \x84wQ\xdc\xa9\x00\x07\x84TQ\x89v\xc5\x1d`\x9e\ Ri\x8f\x93=\x0dl\xd2\xe6\x9d8iRp\x85(\ \x13\x01G\xa8fh\xd6\x22WE\xef\x08\xf0b\xd1F\ \x85\x1c \xa4\xdaA\xf5\xa2E\xd6 G+\xea\x9e\x15\ R\xddR\xa4A\xd1\x08\x98#\xff\xc8\x9aG\xd6\x1aP\ t\x01L\xd2\x0f\xcc\x17i`}\x1a\x14R\xedE\x9f\ \xdf\xab\xbe~6\x80\x9b\x92\xb5?\x93\xed\xf9\x93\xea\x0e\ n\xa0k\x8b\xdf\xdb\x08\x17\x89\x80E\xdc\xe4\x0f\x02\xd2\ \x9f\xf4\x00\xd5\x07\xdf\xd4\xbfh\x9b>\xb3\x122\xd5\x1d\ '\xa7/\xc3\xce\x94kU\xea\x07I\xee\x06fl\x04\ s\x1d`\xb6\x16g\xe7oC\x9a\x03\xd2\xaeUaA\ H\x95\x97\x9f\xb0\x8a\x80\xaa\xd5\x9d4nM\xb96\xec\ \xb8\x8fa\xe0X\x9eP\xa6\x03\xcc\x96\xe2,\xff\xd6B\ Z\xde0\xcd)U9n>\xc9\xe9H\xde\xa26\x8f\ \x9b\xeaN\x92I!\xd5'\xc0*z\xd5^\x05\x1e\xf0\ \xd0\xcf6t\xaa\xee\xc9N\x02\x1d\xb7A!\xd5\x04\xfa\ \x93\x96:\xbf\x22\xf1A\x03\xb8'\x8e\xc2\xb3i7S\ \x07\xe7\xa9\xba\xd3-2\xb7\xc5NS`\x06\xbd\x95\xf8\ \xe2\x0a:\xfb\xbbd\xfe\x1eG\xa7\xd6\x5c\xbc\x07\xa4\xb1\ \x0f]x\xf98yc\xdd\x140[\xc79\xec\xf2w\ e\xf8\x11x(Y\xee6\x8b\xd5g\xe8\x5c\x9f\x0f.\ \xa1\xcb\xecmo\xa0iaq\x0c\x7f\x83\xbf\x8a\xae\x0a\ \xad\xab\xf5\xc7Qx\x11x\x10\xf8\xc3S\xdf\x83\xa4\xec\ hm\x0e0O\xe1\xb8'\x03\x00\xde7\xc5\x8fT\x8c\ c\xde\xf1\xd8\xffQ!\xd5p\xeb\x85d\x04\xcc\xa3\xb7\ \x0e_|c!cu\x88)\xc9V\xf4\xb6\xb8\xc6\x9a\ \x03\x84T\xcd\x85\xc2'\xab\x162\x0d\xcf6<&\xa4\ Z[\xe0\x03\xa8u\xdb\xdbo!3\xe1\xd9\x86\xb6m\ \xb19\xe0\x19\xe0.\xcf\x1d\x03\xbc\x90U\xc80\x85\x96\ \xe7k\xb0c\x02\x13\xed=\xe6\xb4\xf7\x1b\xfeV\xfe$\ _\x01\x8f\xc6Q\xd8\xb6\xda\x1b\xc7\x9c\xa6\x9e\x07\x01\xfa\ c\x8b\xd1\x1e!\xd5\xb3@\x5cS\xa7M\xae\x00\x1f\xa0\ ?\xa4\x02=5\x0eQ\xac\xca\xe4\x82\xe7z\x81\xe9\x9a\ ;\x05\x9d\xfdy\xb5\x0b\xfd&\x99\xee\x94\x9e\xda(\x8c\ \x04\xb8\xffN\xe8\xbfDo\x80\xfe y\xa3\xb2\x1c\x00\ \xefu\xdb\x8a.\xf2n\x10G\xe1\xe7\xc0\x9b\xdd\xb6\xa4\ \x0b\xbc\x1dG\xe1\xa7\x01@\x1c\x85\xaf\x00\x8f\xa3\xffa\ \xe9\xff\xcey\xe0\xe98\x0a_\x86\xf4|\xc0\x08\xfa\x9b\ \x9f\x01\xf4\x02\xd9\x5c$\x9b\xbf\x01\xed\xaf\xcc\xdd^D\ [\xcf\x17\x0dn\x9c%V[~W\xd1\xef\x1e?\xc7\ Qx\xbeF\xdb6\xd9\xe4\xdf\xce?c~*3\x05\ \x88\x8d\xfe\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x01\x9c\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x01cIDATx\x9c\xed\x9b\xbbN\xc30\ \x18F?\x10\xaa:\xd2\xa5b\xf2\x08c\xde\xc4\x8f\x90\ \x87\xf3#\xe4M\x18a\xcc\x82\xc4\x84\x98\xaa\x0e\x88\xa5\ C\x95TFDN\x8f\xeb\xff?\xa3/\xf1\xd7\xa3Z\ \xbe\xa4\xbdSe\xf4\xc3\xf8&i\x93i\xf2\x92b8\ \x96\x1a\xef\xa1\xd4\x83\x0a\x12$m3\xf5\xf7%\x07+\ \xfa\xb0[\xc4\x05\xd0\x01h\x5c\x00\x1d\x80\xc6\xbc\x80\xe2\ \xcb`?\x8c\xaf\x92\xf6\x99&]\x8a\xe1\xb3\xf4\xb8K\ Yc\x1f\xb0\x97\xf4\x94\xa9\xaf\xea[WU\x18\x02\x17\ @\x07\xa0q\x01t\x00\x1a\xf3\x02j<\x0e/\xa6\x1f\ \xc6\xad\xa4\x8fL\x931\xc5\xd0\x9d\x174%\xe0\xc4c\ \xa6\xeekZ`~\x0a\xb8\x00:\x00\x8d\x0b\xa0\x03\xd0\ \x98\x170[\x06O\xe7\xf9\xe7L\x9f.\xc5\xf0\xbe^\ \xa4\xebri\x1f\xb0\xd1\x15\xef\xe5i\x9a\xfa0Kp\ \x01t\x00\x1a\x17@\x07\xa0q\x01t\x00\x1a\x17@\x07\ \xa0q\x01t\x00\x1a\x17@\x07\xa0\xb9t\x1a\xe3{Z\xd0\x94\x80\x14\xc3A\xd2\xee?}\xcc\ O\x01\x17@\x07\xa0q\x01t\x00\x1a\xf3\x02\xd6X\x06\ \xff\xfa)|U\xf7\x09\xc5\x05\xdc\xda}\x82\xf9)\xe0\ \x02\xe8\x004.\x80\x0e@c^@\x8d\xc7\xe1Q\xf9\ \xbf\xcf\x17\xddG\xfc\x02\x08\xf1#5b\xce\xe4\xb7\x00\ \x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x04q\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x04#IDATx\x9c\xed\ \x9bM\x88\x14G\x14\xc7\x7f\xdb\x0cK\x08\x22\x22\x22A\ D\x04\x15$\xc6\x10D\x82\xa2\xa8\x17?\xd6\xc3&\x88\ \x22\x9d@\x0b\x05\x81\xe0AO9\xe4\x90\xa3\x17\xc1\x83\ \x1eD\x14\xfbP\x8a%\xa2\x1e%\x89\x1fD\xf0\xa0\x1e\ $$A\x92 d\x0f\x8b\xc8\x22A\x16\x91a\x19\x86\ \x1c\xaa\xdb\xf4\xf6\xbc\x9e]\xdd\xad\xaa\x9e\xd9\xf9A\xb3\ ;U\xd5\xd3\xaf\xfeS\xf5\xba\xaa\xfb\xbd!f N\ \x93\xf5\xc0\x1e`#\xf0!0\x0cD\xd9\xd1\xc8\x9a\xe5\ \x9f\xa9\xf8\x5c\xa6\xd1\xa5n6\xb4\x84\xff[\xd9\xf1\x06\ x\x05\xfc\x03\xdc3J?\xe9\xf6ECU\x15q\x9a\ \x8c\x02\xdf\x03[\xe6djx~\x03N\x00\xd7\x8d\xd2\ \xedre\x87\x00q\x9a|\x04\x5c\x04\xf6\xbb\xb7\xcd+\ ?\x03G\x8c\xd2/\x8a\x85\xd3\x04\xc8\x86\xfbO\xc0*\ \x8f\x86\xf9d\x1c\xd8k\x94~\x9a\x17\xbc\x15 N\x93\ \x15\xc0#`e\x00\xc3|\xf2\x02\xd8j\x94\x1e\x83L\ \x808M\x22\xe0.\xb0K8\xa1\x0d\xdc\x02n\x00\x7f\ \x02SYY\xf1(\xb6\xed\x98g\xf3H\xd9yFL\ w\xc8\x0d\xac\x93^\x01\x1c\x06F\x91\x9d\xf1c`\x9b\ Q\xba\x95\x7f\xe1W\xc8\x9d\x7f\x06|m\x94~.U\x8d\x01k\x22`\x07\ \x9d\x9do\x01\x87{\xbd\xf3\x00F\xe9\x97\xc0!\xec\xd4\ -\xb2\x1a\xd8\x1e\x01#\xc2yW\x8c\xd2\xbf:\xb6\xcd\ \x1b\x99\xd7\xbf,T\x8dD\xc0'B\xc5%\xb7&\x05\ A\xea\xd3\xa6\x08X$T\x8c\xb9\xb5%\x08cB\xd9\ \xa2\x08{\xdb(\xd3tkK\x10\xa4>\x0d\x1774\ EZBY\xaf\xd3\xa2s\x8d\xd2\x90\x04h\xd3\x9f\x02\ H\x0b\xb4\xc6L\xdb\xd6~B\x12 \xaa\x9a\x02.\x97\ \xb3u\xa2\xd1@\x1e\x01N\x05\xc8V\x9f\xfb\xb1\x8b\x11\ \xb0?B\x1b\x98\x04\xb4\xb4o\x9f\x07\xc4\x110\xd7'\ 3\xefD\xd6\xf1/\x81\x1f\x80\xcf\x84&m\xe0:\xf0\ \xda\x97M\xf9\x0e\xca)Y\xc7\x0f`;\xfe\xe9\x0c\xcd\ \xa5\xdb\xb2+\x1a>:\xbf\x0f\xfbHj\xd3,\x9a{\ w\xcaN\x05\x88\xd3\xe4\x18p\xfa\x1dO\xf3:-]\ +\xeem.\xbf/U\x02\xcc\x97\x17\xae\xfd\x8e\xd2\xf5\ |\xfb\x83\xe9\xa3\xa0\x09\x9c\x01Nv9\xc7\xfb\x14p\ \x86Qz\x0ax\x80\xed\xf8Y`\x9dQ\xfa8\xf6\xa5\ E-\xf0\xa1\xf67\xc0\x94Qz\xa2PV\x9b\xbd\x86\ s\x01\x8c\xd2\xe3Bqm\x96\xda\xa16B\x0b^\x80\ \xda0\x18\x01\x81\xae\xbb\xe0\x05\xa8\x0d\x03\x01B\x1b\x10\ \x9a\x81\x00\xa1\x0d\x08\xcd@\x80\xd0\x06\x84f @\xa0\ \xeb\xd6~!\xe4Z\x98Z\x09P\x9b\xbdy\x86Wq\ \xea\xe8\x03\x16\x84\x00\xb5\x19u\xa1\xa6@\xd55\xdbt\ \x0639\xb5#\xd4\x08x\xd3\xa5\xcektJ\xfeV\ \xb6\x8cka\x1e\x02G\x80\xa5\xfc\xff\x5c\xb2\x09<7\ Jw\x13g.\x88\xef?\x82\x08`\x94\x9e\x04\xb4\xcb\ k\xcc\x92v\x1do\x83\xae\x90~\xd4\x96$@\xbf\x86\ \xcdT\x0a \x06\x0f96&\x04R4L;B\xbe\ \xed|\xe0\xde\x1e\xef\x88\xf1\x90\x11\xf2mg\xb9cc\ B\xb0L(kF\xd8$\x882_86&\x04R\ \x9f\x9e\xe5\x99\x22e\xbe\xcd\xe2\xec\xfb\x828M\x96\x02\ G\x85\xaa\xbb\x11\xf0#\xf0o\xa9b\x09p1N\x93\ \x9ew\x86Y\x80\xd6\x05:\xa7\xc0$p+2J\xe7\ \xef\xee\xcb\x8c\x02&N\x93%\x8emtF\x9c&\x8b\ \x01\x83\x8dP+s\xce(\xfdz\xa8\xd0\xf0w\xe4t\ \xb9\xe7\xc0)\xe0\x1a0\x91\x05=\xd4\x968M\x86\xb1\ N\xfc \xf0\x1d6\x81\xaa\xcc8\xb0\xd1(\xfd\xaa\x98\ 6\xb7\x1d\xeb\x0f\xaa\xe2\xf4\x8aYby\xe6\x18\xc8\xeb\ \x08W\xabKiJF\x85\xbf\xc5\xb4\xde\xaa\xc5\xdc\x14\ 6w\xf0\x17\xe8L\x9c<\x80\x1d2>\x83\x15}\xd2\ \xc2f\xc1]\xcb\x0b\xa6\xa9d\x94\xbe\x89\xcd!\xea\xf9\ d)\x81\x09`\xa4\xd8y\x10\x86\x89Q\xfa\x1e6S\ \xfc,\xfd\x919\x92;\xf9\x0dF\xe9;\xe5\xca\xca\xec\ q\x808M\x96c=\xe8nl\xde]\xaf,\x91\x9b\ \xc0S\xe066k\xfceU\xc3\xff\x00(\xde\x0a\x9b\ \x8e\xc8\xe2\x00\x00\x00\x00\x00IEND\xaeB`\x82\ \ \x00\x00\x045\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x03\xe7IDATx\x9c\xed\ \x9b\xcd\x8b\x14G\x18\x87\x9f-\x9ae\xd8\xe8\xb0J\x10\ 1\xa10\x87@\x12B\x08\xf9\x0b<\xe4\x90K\xca\x7f\ !\x0d9\xc6\x83\x87\x10d\x19$\x1b\xd1`D/\xa2\ b\x0e\x95Cn\xb9H#\x1er\xce1'\xc1\xdc\xd3\ \xa8H\xa2\xcb\xban\x86E\x86&\x87\xaaw\xd33\xee\ \xc7\xcctu\x97\xd9\xee\x07^\xa6{f\xba\xea\xad_\ \xd7WW\xd7\x0b\x1d\x1d\x1dmf\xa1|\x92fy\x02\ |\x00\x9c\x04\x8e\x02}\xe0\x10\xf0\x06\xb0T\xb2\xde\x84\ -N\x1c\xcbyR2U\xcaJy\x1b\xed\xe0\xd3h\ \x87\xe3\x11\xf0\x12\xd8\x00\x86\xc0V\xe9;1\xf9\xfe\xa5\ \xff\x1c\x02\xff\x00\x9b\xc0:\xf0\x17\x90\x03\x7fX\xa3\xb7\ \xf3\xd8\x16 \xcd\xf2\xaf\x80\x01plG\xa9\x0e\x0e\xeb\ \xc0w\xd6\xe8\xab\xe0\x05H\xb3\xfcK\xe0\xc7\x98^E\ \xb5F\xff$\xd5\xf2\x9b\xa8\xae\xc4a\x00\xb0\x90f\ y\x1fx\x1e\xd9\x99X\xbc\xa5\x80\x13\xb1\xbd\x88\xc8I\ \xc5\xc1\xef\xf4\xf6\xe2\xb8\x02\xde\x8c\xedED\x8e)\xdc\ x\xdfV\x96c\x0bp\x0f\xb8\x1b1\xff#\x0a8\x12\ )\xf3\xab\xc0\xe7\xc0i\xe0J$\x1f\xfa\x09n\xba\xdb\ 4\x17\xad\xd1+\xa5\xf3\xaf\xd3,\x7f\x01|\xdb\xb0\x1f\ }\x85\x9b\xeb7\xc9\xeaD\xe1\x01\xb0F\xaf\x02\xaf|\ _3KM\x0bp\xde\x1a}~\xb7\x1f\xad\xd1\x17i\ V\x84\x9e\xc2=\xdd5\xc1\x8a\xbf\xcb{\xe2Ehj\ j\xdeS\xb8G\xd7\xbaY\xf1\x05\x9b\x0ak\xf4e\x9a\ \x11\xa1\xa7p\xcf\xedu2S\xe1\x85\x86DX\xac\xbb\ \x06\xccUx\xa1\x01\x11j\x15\xa0R\xe1\x85\x9aEH\ \x14n\xb9*4A\x0a/\xd4(B\x22ks!\x19\ \x84,\xbcP\x93\x08*t\x0d\x18X\xa3/\x04Lo\ \x8c\x1aDP!\xef\xfej\x9d\x85\x17\xbc\x08\xe7B\xa5\ \x17J\x80\x0b{\xcd\xf0Bc\x8d\xfe\x9e@3\xc6\x10\ \x02\x5c\xb6F\x0f\x02\xa43\x13\xbe\x9f\xa9,zU\x01\ nX\xa3\xa3\xad(\xfb\xa9u\xa5f\xb7\xdb\xdb\x99i\ \xb8\x0f\x9c\xa9\x92y\x08|\xed\x9b{Q\xa5\xca\x08\xf0\ !\xf0 \xcd\xf25\xdc\xeb\xa8\xbd\xb8f\x8d\xcefI\ <\xcdr\x03\x9c\xdd\xe7o\x09\xb0\x0c\xbc7K\xda%\ F\x09\xf3\xd7\x005C\xc6\xbf\xcc\x91\xfe\xdb\xc0\xa99\ \xae\x9b\x09\x05\x14ug\xf2\x1a3j\xbb\x00E\x95N\ \xf0 0\xea\x04`\xff\x1e\xfc \xd3\x09\xa0p\xdbI\ \xda\xcaV'\x00n\xe3Q[\xd9T\xb8MCme\ C\x01\xcfb{\x11\x915\x05\xac\xc5\xf6\x22\x22\xcf\xda\ .\xc0\xd3\xb6\x0b\xd0\xfa&\xf0D\xe1\xf6\xd0\xb6\x95\x87\ \x0ax\x0c<\x89\xedI\x04\x9e\x02\x8f\x955\xba\x00\xae\ \xc5\xf6&\x02\xb7\xad\xd1\x85\xac\x0a_\x01\xae\xd3\x8e\xc5\ \x91\x02\xb8\x81_RO\x00|-8\x93f\xf9\x0f\xc0\ '\xb8\xed\xb3Gq;\xc8\xfa\xde\x96p\xdbi&\xe3\ \x05\x16}:\xf2)o\x9cC\xbfs,pO\xae\x05\ n\x0dCL\xe2\x03\xc4\x86\xde6\xbdm\xe0f\xbb\x7f\ \xe3\x9a\xfb\xef\xd6\xe8\x5c\x12\x1d[\x15\xf6?\xe4\xccH\ \x9a\xe5RXU2\x11\xa5\xe7\x1d\x99\x95\x9f\x81;\xfc\ \x17\x041\xc2\x15^ji\xe1o\x5c%\x16\xd2,\xff\ \x08\xf8\x0c\xb8n\x8d\x1eVM\xf0\xff@\x9a\xe5\x8b\xc0\ \x17\xc0o\x0bi\x96\x9f\x00\x1e\xe1\xaa\xc9\xaf\xc0\x03\xdc\ \xa8\xb0\x8e\xab>R\x95$$E\xaa\xd8V\x88;\x10\ \x02_\x03{\x8c\x87\xf5\x88\x1d\xf2\xb6\x8c\xdb\x18\xfe>\ \xf0)p\x1cxW\x22F\xfe\x04\xf4\x94\xf9I\xa1G\ \x94\xc4(\x99\xc4\xf0\x94\xdb\xa8\xb4\xdb\x82\xf1j<\xc9\ d\x13\x92\xfeD\xe2\x8e\xca\xf1HbR\xd0\xa4\x94\xc6\ 4\xe4\xc0;r\xd1%\xe0\xe6\x94\x17J\x06\xe2\xcc\xf2\ \x94\xd7\xbdn\x5c\xda\x1e\x06\xad\xd1\xb7\x80U\xda\xb1:\ 4\xc4\xbdP\xbd\x0d\xaf\x86\xcd\xf5\x81\x8fq\xaf\xa5$\ l\xee0\xe3\xe1r;\x85\xcd%\x8c\x87\xcc\x95\x87E\ 9\x9ewX\x94\xe6SnZ\x93\xc3\xden\xc7\x9b\xc0\ \x0b\x5c_&as\xf7\xdb\xd2\xd9wtt\xec\xcf\xbf\ \xa9\x86'\xfe2\xd8\x87\x07\x00\x00\x00\x00IEND\ \xaeB`\x82\ \x00\x00\x09F\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x02\x00\x00\x00\x02\x00\x08\x06\x00\x00\x00\xf4x\xd4\xfa\ \x00\x00\x09\x0dIDATx\x9c\xed\xddO\x8b\xd4u\ \x00\xc7\xf1\x8f\xc3\xb4\x88\x88\x99H\x85\xc4\x9e=G\xc7\ \x0e\x1e;\xed3h\x1fA\x9e\xba\x17\x15\x1d{\x08]\ \xf6\x1c\x04\xfb\x04\xba\xf4\x00:H\xd7`\xf1\x10\x22b\ a\x8b\x88\x0c\x1df~*\xe2\x9f\x0d\xd7\xdf\xb7\x9d\xcf\ \xeb\x05\xeb\x8c\xf2\xf3\xc7\x87E\x98\xf78\xbf\x9dI\x00\ \x00\x00\x80\xedw\xee\xf9?\xd8?\x00\x00P\xc8K\x00\x00\ PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\ \x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\ \x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\ \x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\ \x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\ \x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\xa6\ \x00X\x0d]\x01\x00\xccj\x0a\x80\xbbCW\x00\x00\xb3\ \x9a\x02\xe0x\xe8\x0a\x00`V\xae\x01\x00\x80B\x02\x00\ \x00\x0a\x09\x00\x00($\x00\x00\xa0\x90\x00\x00\x80B\x02\ \x00\x00\x0a\x09\x00\x00($\x00\x00\xa0\x90\x00\x00\x80B\ S\x00<\x1a\xba\x02\x00\x98\xd5\x14\x00w\x86\xae\x00\x00\ f\xe5\xd3\x00\x01\xa0\x90k\x00\x00\xa0\x90\x00\x00\x80B\ \x02\x00\x00\x0a\x09\x00\x00($\x00\x00\xa0\x90\x00\x00\x80\ B\x02\x00\x00\x0a\x09\x00\x00($\x00\x00\xa0\xd0\x14\x00\ \xff\x0c]\x01\x00\xcc\xcag\x01\x00@!/\x01\x00@\ !\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00\ @!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\ \x00@\xa1\xe5\xe6\xf68\xc9\xed\x91C\x00\x80Y\x1c'\ O\x03\xe0V\x92\x1f\xc6m\x01\x00frk\xf4\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x16\xe7\x92d\ \xff\xf0\xe8\xab\xd1C\x00\x80y\x1c\xec\xed~\xbb\xdc\xdc\ \xffr\xe8\x12\x00`NO\x02\xe0\xd2\xd0\x19\x00\xc0\xac\ \x16\xa3\x07\x00\x00\xf3\x13\x00\x00PH\x00\x00@!\x01\ \x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00@!\ \x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00@\ !\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00\ @!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\ \x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\ \x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00P\ H\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00\ PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\ \x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\ \x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\ \x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\ \x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\ \x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\ \x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\ \x04\x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\ \x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\ \x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\ \x00\x00\x85\x04\x00\x00\x14\x12\x00\x00Ph\xb9\xb9\xfd|\ \xe8\x0a\x00`VS\x00\xfc4t\x05\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\xf0\x16\x9dK\x92\xfd\xc3\xa3+\ \xa3\x87\x00\x00\xf38\xd8\xdb\xbd\xb7\xdc\xdc\xfff\xe8\x12\ \x00`N7\xa7\x00\xf8b\xe8\x0c\x00`N7\x17\xa3\ \x17\x00\x00\xf3\x13\x00\x00PH\x00\x00@!\x01\x00\x00\ \x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\ \x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\ \x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00@!\ \x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00@\ !\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00\ @!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\ \x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\ \x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00P\ H\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00\ PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\ \x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\ \x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\ \x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\ \x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\ \x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\x04\ \x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\ \x04\x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\ \x85\x04\x00\x00\x14\x12\x00\x00Ph\xb9\xb9\xfd}\xe8\x0a\ \x00`VS\x00|?t\x05\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\xf0\x16\x9d\x1b= I\xf6\x0f\x8fv\ \x92\x5c>\x85S-\x92\x9cOr\xe9\x14\xce\xf5&\x96\ I.l\xb6\xc0\xe4a\x92\x07IV\xa3\x87\x9c1\xab\ $\x8f\x93\xdc\x1b=d\xcb<8\xd8\xdb=\x1e=\x82\ q\x9e\x04\xc0\xfe\xe1\xd1\x95$\x1fe\xfd\xe0y1\xc9\ \xd5\xac\x1fP\xaf<\xf7w\x16I>x\xe6\xf7\xd3q\ /\xb2H\xf2\xfe\x09v,\x92\xec\x9cl\xf2k\xcfs\ Z\xe7z\xd3\x1d\xcb\xbc\xfc\xfbB\xa7U\x92G\xa3G\ \x9cQ\xab\xac\x03\x8a\xd3\xf3x\xf3\xc5\xe9Xe\x1d\xa9\ g\xe1{\xfa\xe3\xc1\xde\xee\xaf\xcb$\xd9?<\xba\x91\ \xe4\xeb\xac\x9f\xb5\xeed\xfd\xe0u>/~0\x9d\x9e\ eO^\xf5,\xf7\xf9c\x01`[=\xcc\xd9\xf8\x1f\ \xbe_\x92\xac\x03 \xc9\xc7In\x8c\xdb\x02\x00g\xde\ Yy\xc2\xbbx\xf2K\x92w\x07\x0e\x01\x00f6\x05\ \xc0\x85\xa1+\x00\x80YM\x01p\x1aW\xe0\x03\x00g\ \xc4\x14\x00\xcbW\x1e\x05\x00l\x15?\xa6\x06\x00\x85\x04\ \x00\x00\x14\x12\x00\x00PH\x00\x00@!\x01\x00\x00\x85\ \xa6\x00\xb88t\x05\x000+\xef\x03\x00\x00\x85\xbc\x0f\ \x00\x00\x14r\x0d\x00\x00\x14\x12\x00\x00PH\x00\x00@\ !\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\x00\ @!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\x00\ \x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00PH\ \x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00P\ H\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00\ PH\x00\x00@\xa1)\x00n\x0f]\x01\x00\xccj\x0a\ \x80\xc7CW\x00\x00\xb3\xf2\x12\x00\x00\x14\x12\x00\x00P\ H\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\x00\ PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x9a\x02\ \xe0\xd1\xd0\x15\x00\xc0\xac\xa6\x00\xb83t\x05\x000\xab\ )\x00VCW\x00\x00\xb3r\x0d\x00\x00\x14\x12\x00\x00\ PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x12\x00\ \x00PH\x00\x00@!\x01\x00\x00\x85\x04\x00\x00\x14\x9a\ \x02\xe0\xaf\xa1+\x00\x80YM\x01p\x7f\xe8\x0a\x00`\ V>\x0b\x00\x00\x0a\xb9\x06\x00\x00\x0a\x09\x00\x00($\ \x00\x00\xa0\x90\x00\x00\x80B\x02\x00\x00\x0a\x09\x00\x00(\ $\x00\x00\xa0\x90\x00\x00\x80B\x02\x00\x00\x00\x00\x1a\xfc\ \x0b\x8ebY\xd7L\xa5\xa0\x03\x00\x00\x00\x00IEN\ D\xaeB`\x82\ \x00\x00\x05-\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x04\xf4IDATx\x9c\xd5\x9b\xcd\x8b\x1cE\ \x18\x87\x9fm\xc2\xb2\xec!\x04\xc9\xb9\xff\x02\x11\x09A\ \x82\x07Q\xc3\xbaF\x93N\xfcJ\xcc\xd7\x08\xc6\x15\xc4\ \x05/\x01\x11\x0f\xb9\x99\x84\x9cB@\x0c(K:&\ qc6\xaec\x5c?\x82\xba\x04\x91\x10\x16Y\x16\x11\ \xcfs\x08\x12$\x84\x10$\x88\x88\x87\xaa\x9a\xf4\xf4t\ wUw}\xcc\xcc\xef6\xd3\xddo\xd5\xef\x99\xea\xee\ \xaa\xb7\xde\x19C\xa3V\xbb\x13\x01\xb3\xc0~ \x02N\ \xa6I\xfc\xa9\xee\xbaA\xa8\xd5\xee\xbc\x09\xec\x91\x1f\x17\ \xd2$\xfePw\xcd\x98&\xe0:\xe0\x13\xa0\x95;t\ \x0cx?M\xe2\xff\x9at\xd4\xb5\xe4\x8ft\x1c8\x9c\ ;\xf41\xf0V\x9a\xc4\xff\x96][\x0a\xa0\xd5\xeeL\ \x00\xf3@Rr\xcaG\xc0\xdb\x83\x86 \xcd\x9f\x06\xde\ (9\xe5\x12\xb0?M\xe2\x7f\x8a\x0e\x16\x02h\xb5;\ \x93\xc0\x02\xf0\xac\xa6\xfd\x148TE\xd8\xa7\xe4\x08\x9d\ \x03\x0ehNm\x03{\xd2$\xbe\x9f?\xd0\x07@\x9a\ \xff\x02x\xc6\xb0\x1f\xe7\x81\xd7BCh\xb5;\xe3\xc0\ \x19\xe0U\xc3K\xae\x00\xaf\xe4!\xf4\x00\x90\xe6\xbf\x02\ \x9e\xae\xd9\x9f\xcf\x80\x83\xa1 H\xf3\x17\x80\x17k^\ \xda\x07\xa1\x0b@\xde\xf3_b\xfe\xcb\xe7u\x11\x01\xa1\ \xf0^s%i~\x1e\xd8\xd50\xc4\x15\xe0%\xd5\xcf\ (\x13t\x81\xe6\xe6\x01v\x03\xe7d,/r`\x1e\ `;0\xaf\xfa9&\x9f\xa2\x17\x10\x06\x5c\xe82\xb0\ \xd7\xf5Hpd>\xab\xf3\xc0\xc1\x088\x82;\xf3 \ \xee\xcby\x97#A\xde\x9e\x9f\xe3\xce<\xc0>\xe0p\ D\xf9{\xdeF\xbbp\x04\xc1`>b\xa3\xbd\x110\ \xe1!08\x80\xe0\xd9<\xc0D\x84x*\xfaRc\ \x08\x01\xcc\x03\x9c\x8b\x80\xf7\x80E\x8f\x8d\xd4\x86\x90\xb9\ \xe7}\x9a\xbf\x04|0\x96i\xd0f\x0e`\xa2E\xc4\ t\xb4\xf2\xed\x10\xe8\x97\xff\x1e\xd8\x99&\xf1\xfd\xecD\ h\x12\xf8\x1ax\xd2c\xc3\x95\x10\x02\x99_\x06\x9eO\ \x93\xf8o\xe8\x9f\x0a\xaf\x07\xbe\x03\xb6x\xec@!\x84\ \xcc\xb0\xdf\xee\xb1\xedk\x08\xf3\xf7\xd4\x17E\x8b\xa1\xe0\ \x10\xa4\xf9\x05\xe09\x8fm\xfe\x8c0\x7f7\xfbe\xd9\ rx\x03\x02\xc2c\x1e;\xb4\x88\xc8\xdeD\xf87\xff\ \x0b\xb0-o\x1e\xaa\x13\x22\x0f! l\xf6\xd8\xb1E\ `\x9c\x01\x99\x07}J,\x04\x04\x9f\xaa4\x0f\x1a\x00\ \xd0\x85p\x15\xd8\xe4\xb0c!\xa45\x0f\x06\x00\x00Z\ \xed\xceF\xc4H\x18\x15\x087\x80\xe94\x89\xef\xe8N\ 4\x02\x00#\x05\xc1\xd8<\xd4\x00\x00#\x01\xa1\x96y\ \xa8\x09\x00\x86\x1aBm\xf3\xd0\x00\x00\x0c%\x84F\xe6\ \xa1!\x00\x18*\x08\x8d\xcd\x83\x05\x00\xe8B\xb8\x0a<\ j\x13\xc7BV\xe6\xc1\x12\x00t!\xfc\x00\x00\x19\xf3.\x0b\x92\xf2\xea.i\xd3\ $\xfe\x0b\xff\x10v\x03g\x8a \xf4\x00\x90'\x9c\xa5\ ~\x05f\x1d\xf5\xad\xe73\x10V=\xb6\xbb\x0f\x98\xcb\ C\xe8\x02\x90\xf5\x82s\xb8-\x99\xcb\xab4\x99!!\ L\x01\xbfzl\xff\x00pZz\x05\x1eT\x8a\xaa\x92\ s]\xd5\xb5\x8d\xb4\x99\x1c\x09a\x1a\xbf\x10^\x07N\ \xaa\x0f\x8a\xc4\x09\xca\xeb\xed]\xc88\x8d\x15\x08\xc2l\ \xab\xdd9\x0a\xa2Tv\x168\xe5\xb1\xb1F9\xbc@\ \xfb\x0e3\x110\xe3\xb1\x81\xc6\x09\xcc@#a&\x02\ \x0a\xdf\x8f\x0ed\x9d\xbd\x0d\x00a<\x02\x96<\x04v\ \x96\xba\xf6\x0caIU\x8a~\xeb0\xa8\xda\xaer\x92\ \xb7\x87\x9eW\xe4\x8a\xab\x98\x88\xc5\xd2\x11U):\x89\ \xd8\xe3{\xdc2\xa8\xf5^]\x95\x1c\xd6,-#\xca\ gz*E7 vv\x9a>u\xaf\xcb\xa0^\xcc\ +I\x08\xdf\xd0\xbc\x84\xef\x060\xa5j\x87\xf2\x95\xa2\ \x1b\x81\x9f\x80\x87k\x06-,B\xf4%\x8b:\xc6U\ `k\xf6\xf6\xecY\x0bd\xe6\xe4\xbf\xd7\x08\xaa\xcaO\ \x83\x98\x07\x90\xa3l\x0a1\xeaL\xb5F\xc1\xb3\xa9o\ 5\x98&\xf1-\x04\x84?\x0c\x82\xfeH`\xf3J\xb2\ \xcdi\xc4\x0f\xa0\xd3\x1ab\xd8\xdf\xca\x1f(\xcc\x07\xa4\ I\xfc'\xf0\x14\xf0[E\xd0%`G\xb6\xf08\xb4\ $\x84m\x88\xf2\xf72\xadRb\x1e*2B\x19\x08\ E\xaf\x9e\x8b\xc0\x0b\xaa\xe4|\x90\x92}\xd8I\xf1\x9f\ >\xae#\xee\xf9B\xf3`\x96\x14]\x8fX==!\ \xbf\xba\x0c\xbc;\xe8?M\xe7%\xd7\xf9'x\x90\xc5\ Z\x06\xde\xd1\x8d\xd0\xff\x01\x8f\xbf&c\xdfL^>\ \x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x04\xcb\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x04}IDATx\x9c\xed\ \x9aM\x88\x1cE\x14\x80?\x9ba]BX\x82\x88\xc4\ \xa0M\xd0\x10\xc3\xb2\x8a,\x12B\x10\x0c\x22Q\xc2Z\ \xfe\xac^\xc5:\xa9 \x84\x1c\xf4\xe2Q\xfc\xd9\x83\xa7\ x\x8aJy\xf5\xa2P\x82?\x1b\x0d!B\x0e\x22K\ \x5cr\x0a\x18\xa5\x90\xa0K\x90\x10\x96 \xe3\xb2x\xa8\ \x9a\xcd:\xdb\xdd\xf5\xba\xba{\x09\xd8\x1f\x0c3t\xbf\ W\xaf\xfa\xf5\xab\xaaW\xaf\x06zzzzzzz\ zz\xfe\x9f\xdc\x96\xa2\xa4\xad{\x09X\x00\xee\x04\x06\ \xe1\xf2Z\xf8^\xdf\xf4\x19\x02W\x80\x13F\xe5\x8b\xcd\ \xba\xda\x0d\x83\xb8\xc8\x7f\xd1\xd6\xed\x04N\x02S\x82\xb6\ v\x00\xbb\x80\x0f\x80\x07k\xf7n\x1b\xc8\x12t\x8e\xb1\ \xf5\xe1c\xcch\xeb\x1eJ\xb0\xd59)\x0ex1\xd1\ V\xaa^\xa7\xd4r\x80\xb6n\x07\xf0T\xa2\xad\xe7\x13\ \xf5:\xa5n\x04\x1c\x05v&\xda\x9a\xd6\xd6\xcd$\xea\ vF]\x07\xcc7\xb4w\xcb\x0d\x03\xb1\x03\xb4u\x13\ \xf8\x09\xb0\x09/4\xd4o\x9d:\x11p\x04\xb8\xa3\xa1\ \xbdim\xddt\xc36Z\xa5\x8e\x03\x9ek\xc9\xe6-\ \x15\x05\x22\x07h\xeb2`N zE \xd3t\x1e\ i\x15i\x04<\x02\xdc\x13\x91Y\x03^\x13\xb45\xa3\ \xad\xdb/\xb4\xdb9\xd2TX\x12\xfeK\xc0W\xc0\x0a\ pW\x85\x5c\x86\xcf\x09\xde\x17\xda\x8e\xa2\xad\x1b\x00o\ \xe2\xa3k\x0a\xff2\xae\x01\x9f\x18\x95\x7f\x5c\xa5+\x8d\ \x80g\x052\x8bF\xe5k\xc0w\x02\xd9\xb6\x87\xc1\xeb\ \xc0;\xc0,\xb0\x0f8\x00\x1c\x02>\xd2\xd6U&n\ Q\x07\x84p= \xe8\xc4\xb7c\xdfU\xccj\xeb\xee\ \x13\xc8Iy\xb2\xe2\xde3U\x8a\x92\x08\x90\xbc\xfdk\ \xc0\x8f\xe1\xf7\x22~+\x1c\xb3+iW\xcad\xe2=\ \x91\x03$\xe3\xff\x9cQ\xf9\x10\xc0\xa8\xfc\x0f`Y\xa0\ \xd3\xe60H\xd9\xd4\xc5\x15\xb5u{\x80\x83\x82v\xc6\ \xc3^2\x0f\x1c\xd4\xd6\xc5V\x96\xce\x89ynN \ \x03[\x1fX2\x0f\x0chw\x18$\x11[\x06+'\ \x90\xc0e\xa3\xf2Kc\xd7\xce\x037\xf0\x15\xa1*\xe6\ \x81\x0f\x056F\xc9\xd8\x13\xf8\x09y\x12\xdf\xf7\x01p\ ;\xb0\xb7BuV[\xf76\xf0\x0f~y\x5c\x0b}\ [2*?_Z\x13\xd4\xd6M\x01\x7f\x12\x99D\x80\ SF\xe5\xaf\x14\xe8\x9f\x0e\x1d\xaeb\x08\xdckT\xbe\ \x12\x91C[w\x12\xbf\xdc\xb5\xc5:p\xa2*\xbc\x8f\ \x12\x7fx(\x0f\xf7\xd3\x02\xdd\x09@\xc5\x84B\x1d\xf2\ UA{u\xc8\x80\xe3U\x0e\x90\x84\xff\x108[r\ O2\x11\x82l5\x18\x85|\xdbd\x85\x0e\x08\xa9\xa5\ d\xef\xff\x93Q\xf9_%\xf7\x96\xf1iq\x8c#\xda\ \xba\xa6\xdb\xecd\xca\x22\xe0Qd{\xff\xd2\xb7\x1c\xd2\ \xe2\xb3\x826&\x89;{t\xce\xd0:e\x0e\x90\xee\ \xfdc\xcb\xdd\xf7\xc2vb\xf6\xae\x03N\xd8V\x1d.\ \x16\xae\x02\xda\xba_\x80X\xae~\x03x\x0c?\x0f\xac\ \xe3\x97\x97\xf1\xb7\xb4\x1f\xf8R\xd0\x91U\xe0n\xa3\xf2\ \xd52\x81PP]\x00\xf6\xe0'\xcf\x01\xfe\x05\x0e\x80\ \xdd\x94O\xd8\xab\xc0Un.\x81\xa3\xbe\xfe\x0e\xe8-\ \x0e\x08\x07\x18?\x0b:\xdd6\xf3F\xe5\x9f\xa7(j\ \xeb~\xc0\x0f\xdb\x22>5*\xd7e\xbaEC \xba\ ,uD\x93\xbd\xc1Z\x5c\xa4\x98\x22\x07H\x96\xbf.\ 8\xa6\xad\x93\xe4\x1dE\xb4\xe3\x80\xb09\x99Mm\xac\ !\xbb\x80\xc7\x13u[\x8b\x00\xe9\xe6\xa7+R+\xcf\ \xc3\xc4{[\x1e\xf6\xe9\xc4\x0e\xb4\xc5\x5cH\xc2\xear\ \xb5\xe2\xde\xafU\x8a\x1b\x0e\x08\xf9vj\x08\xb6\xc5n\ \xe0p\x82\xde\x02~Y\x1b\xe7\x22PY\x14\xdd\xecm\ \xe9\xe6g\x09x\xa3\xa2\x9d\x8c\x9b\x8e\x1dl\xbaf\xf0\ \xe3<\xc6AV\xec,$8NZ\ $\x99\xd6\xd6\xedK\xb5U\x87L[\xb7\x17\x90\xfcu\ \xa5\xce\x03\x94\xf1\xb5P.c\x9b\xf6$u&\xbf\x0b\ F\xe5Ekm\x1d\xce\x00\x7f\x0be\xb7%)\xcb\xa8\ >W\xdb\xccgM\x8d\x19\x95_\x07\xbe\x11\x8a\x1f\xd6\ \xd6I\xf2\x86Fd\xc4\xcf\xfd\x01.\x00\xa7Z\xb2\xf9\ \x1e\xbeH\x11c\x82xQ\xa6\xa7\xa7\xa7\xa7\xa7\xa7\xa7\ \xa7\xa7'\x91\x7f\x01\xefh\xff\x87\xd2\xdd%\x12\x00\x00\ \x00\x00IEND\xaeB`\x82\ \x00\x00\x00\xbc\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x00nIDATx\x9c\xed\ \xd01qB\x01\x00\x05\xc1\x07\xf3\x0bD\xa4\xc0VJ\ ,b\x01#LTPP\xe0\x82+\xb2\xab\xe0\xe66\ \x00\x00\x00\x00\x00\xe0\xbf8\xdd\xee\x7f?\xdb\x8e:$\ \xf2>\xb6=\xb6]\xe3\x90\xca\xf3\x5c\x17\xd4\x0c\xa8\x03\ j\x06\xd4\x015\x03\xea\x80\x9a\x01u@\xcd\x80:\xa0\ f@\x1dP;\xb6\xfdn\xbb\xd4!\x91W\x1d\x00\x00\ \x00\x00\x00\x00|\xcf\x07\xcaX\x06Q\xb2\xc5\xbe,\x00\ \x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x04\x8c\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x04>IDATx\x9c\xe5\ \x9bOh\x5cE\x1c\xc7?]\x82\xe4 \xa1\x04\x91\x9c\ \xe6 \xd1C\x05\x0f\xb5\x07\xa5\x82\xb4\x12\x8a\x05\x07\xf1\ $\xc6\xbf\x83\x7fP\x90RAmN\xa5\x17\x05=Y\ \x8am\x15\xa7\x07E\xab\x14\x85AA\xa9\xe0Ek\x15\ \x91\xa0EJ\x95\x18\x86\x1eBXB\x08\xa1HY\x16\ \x0f3/y]\xdf\xee\xbe7o\x93\xdd\x19\xbf\xf0\xd8\ \xf7f\xdeov~\x9f\x9d\x99\x9d\x99\xdf{\x10(e\ \xec#\xca\xd8\xdbB\xedGE\x8d\x10#e\xec\xa3\xc0\ \xa7\xc0\xe4`\xab\xb3\xfd\xaa\x0c@\x19\xfb8\xf0!0\ \xe6\x8f\xa8U\x09\x802\xf6I\xe0\x0c\x9b\x8e\x07\xb5\xa0\ QR\xe9_0\xe7|\xf4N\xe7U\xca\x99T\x9d\x87\ \x12\x0e)c\x9f\x06>(so\x8c\xda\xd1+S\x19\ \xab\x80\xd3t\xef*\xc7\x81\xbf+|_\xdb\x1f\x99Z\ \xfe:\xfb\xbc\xee\x8fu\xe0*`\xb5\x14k\x15\xca\xaf\ \xac\xae\x00\xbc\xf3\xef3\xdc_\xbe\x05,\x02?\x03\xdf\ \x01_k)\xae\x0e\xf2\x0b\x0a\x01\x8c\x88\xf3Ej\x03\ \xdf\xe3\xc6\xa3\xcf\xb4\x14\xd7\xea\x16\xf8\x1f\x00#\xec|\ \xa7\x9a\xc0;\xc0\xf1:\xdd\xe4\x06\x00\x119\x9fW\x13\ 8\x06\x9c\xd2R\xb4\xaa\x1ao\x00\x88\xd4\xf9\xbc.\x02\ \xcfi).U1j@\x12\xce\x03\xdc\x03\xfc\xe4}\ )\xad\x1d\xca\xd8\x9d\xc0\x9f\xc0-[R\xad\xe1\xe8-\ `NK\xd1\xeewcCK\xb1\x0a\x1c\x00V\xb6\xbc\ Z\xdb\xa7\xd7\x80\xd3\xca\xd8\xbe-\xba\x01\xa0\xa5\xf8\x15\ \x98!-\x08\xcf\x02'\xfbA\xd8\xc8L\x14\xc2\xf3\xc0\ \xd1^7\x14\xcd\x03v\x03\xe7I`\xb3\xc3\xab\x0d\xcc\ j)\xce\x16ev\x9b\x09\xa6\x06a\x0d\xb8[K\xf1\ WgFa\xffH\xb0;L\x00g\x8a\xc6\x83~\xab\ \xc1~-a\x1fp\xc1\x9f7\xd8\x04\x9a?\x87\x1bW\ \x93EyY\xda\x180\x0e\xdc\x0cL\x03\x0f\x02\x0f\xfb\ \xebA\xe8\x05-\xc5{\xf9\x84\x9e\x00\x00\x94\xb1{\x80\ o(\x86\xb0WKq\xa1 }`\xf2\xf3\x94\x97\x80\ \xc3\xd4\x9f\xab,\x03\xb7\xe7\xd7\x0e}\xff'\xb5\x14\xbf\ 0\xc4y\x82\x96bUK\xf1\x06p'\xf0q\xcd\xe2\ n\xc5\xc1\xdcP\xa9\xa9\xaf\x870\x83[x\x0cEZ\ \x8ae-\xc5,\xf0\x22n\xd3$T\x87\x94\xb1\xe3\xd9\ E\xe9\xb9\x7fn`\x1c\x1a\x04_\x8fS\xc0,n\xb3\ $DS\x80\xcc.*-~\xb4\x14\xf3\xc0\x03lB\ \xe8;\xd7\xde\x0ai)\xce\x01/\xd7(\xe2\xa9\xec\xa4\ \xf2\xeaOK\xf1\x1bn\xf4_\xa2^S\xac%\xdf\x12\ B\xc7\x84\xfd~p\x0d[\xfe\xfa5\xf7>\xdc\xc6\xe5\ 0u\x08X\x0d\xb0\x1b\x07\xf6C\x8d\xf5\xbf\x96\xe2\xb2\ \x96b9\xd4~\x10\xd2R4q;\xd3!\xba\x1f\xe2\ \xde\x00\xc9t\x92\xb0\xae\xb8\x07\x12\x00\xa0\xa5Xbs\ 6ZE\xbb \x01\x00^\xe7\x03lv*c'S\ \x010\x1fh7\x95\x0a\x80\xd0\x7f\xa3\x89T\x00\x84\x06\ F\xc6S\x01\x10\xfa\xa4J;\x15\x00S\x81v\xeb\xa9\ \x00\xb8#\xd0\xae\x99\x0a\x80\xbd\x016-`)z\x00\ \xca\xd81\xe0`\x80\xe9\x82\x96\xe2z\xf4\x00p\xce\x87\ \x8c\x01\xf3\x10\xf9L\xd0\xef\xf2\xce\x05\x9a\xff\x08\x91\x03\ \x00\x1e\xc3E\x85C\xf4-D\x0c@\x19+pO\x88\ \x84h\x01\xf8\x03\x22\x05\xa0\x8c\x9d\x00\xbe a\xa4\x01(cw\x01O\xe0\xe2\xfc\x83\ \x88T\x9f\xf3A\x9e\x0d\xd5\x02\x90\xab`\xaf`h\xe7\ u\xd1y\x16\x18\x1d\x03n\xc2Es\xa7\x81A\xbe\x91\ \xb2\x06\xbc\xda\x99X\xb7\x05L\x03Gj\x96\xb1]\x9a\ \xd3R\xd8\xce\xc4\xa8\x06\xc1\x1a2Z\x8aw\x8b2\xfe\ \x0f\x00\xae\x00\xcft\xcbL\x1d@\x13xHK\xd15\ \xb4\x9f2\x80\x15\xe0\x80\x96\xe2J\xaf\x9bR\x05\xb0\x04\ \xcc\xf8\x90~O\xa5\x08\xe0\x12\xee\xd1\x9d\xbe\xceCz\ \x00>\x02\xee\xd5R,\x945\x18\xe9\x99`\x05Y\xe0\ \xb0\x96\xe2\xf3\xaa\x86\xb1\x03X\x01\xde\x06Nh)\xd6\ C\x0a\x88\x15\xc0e\xdc\xdbl\xba\xee[e1\x01X\ \x04\xbe\x04>\x01.\x96y\x17\xa0\x8c\xea\x02\xf8\x07W\ \xb1A\xa8\xed\xcb\xbb\x86[\xb8,\xfb\xb2\x7f\xc7\xbd\x0e\ \xb38(\xa7\xf3\xfa\x17\x80~.[3>\x1a}\x00\ \x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x06\x98\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x06JIDATx\x9c\xe5\ \x9bo\xa8\x15E\x14\xc0\x7f\xefr{\xc8+\xc4JD\ $\xa6\x08\x13\xd1\x0c+\xf3CT\xa0\x14\x98\xc8PI\ \x99Q\xe2$\xfa 3\x8b\xb2(\x93\x10MJ\x83\xfe\ \x88V\x84\x0c\x96a\x96\x92\x0e\x19\x06\x05\xd5\x87\x0a)\ \x14{\x88\xd4\x83d\x10\x13\x0d\x11\x11y\xbc\x1e\x97>\ \xcc\xae\xae{\xe7\xde\xbb\xbbo\xee\xbe'\xfd\xe0r\xb9\ \xb3{\xcf\xcc\x9c\x9d9\xe7\xcc\x99\xd9\x0e\x1a\xa0\x8c\x1d\ \x0bH\xe0v`\x14\xd0\x05t\x02\x95\xc4\x07`\x00\xa8\ \x01\xfd@\x1fp\x1a\xf8\x0e\xd8\xad\xa5\xe8o$\x7f\xb8\ \xd0\x91.P\xc6^\x07\xbc\x0e<\x8a\xebpQ\x0e\x03\ JK\xb1\x7f\x102\xda\xce%\x0aP\xc6\xce\x02>\x05\ \xae\x09$\xbf\x0f\xe8\xd6R|\x1cH^p\xe2a\x8c\ 2v\x0e\xb0\x87p\x9d\x07\x18\x01he\xec\x8b\x01e\ \x06\xa5\x03@\x19{#p\x00\x18\xd9\xc6\xba\xd6i)\ V\xb6Q~!\xaa\xd1\xf7\xdb\xf8;\xdf\x03\xbc\x0f\x1c\ \x01\xce\xe2\x0c\xdd@t-6~\xb5\xe8w-\x927\ \x06\xf8\x08\x98\x94\x92\xf5\x8a2\xb6SK\xb1\x22X\xeb\ \x03\xd0\xa1\x8c\x9d\x04\xfcNb:Dl\x03\x16\x15\xb1\ \xe4\xca\xd8\xa9\xc0o\x1e\x99\x00\xef\x01\xcfi)j\x9e\ k\xa5S\x01\xe6S\xdf\xd0\xfd8\x0b^\xc8\x8di)\ \x0e\xe2F\x8c\x8fg\x80w\x95\xb1>\xe5\x94N\x05\xb8\ \xc5S\xbeAK1\xe0)\xcf\xc3\xf9&\xd7\x9e\x066\ \x0e\x07%T\x80\xd1\x9e\xf2?\x02\xc8n5z\x9e\x02\ 6\x0d\xb5\x12\xaa\xb8\x08/\xcd\x99\x00\xb2}\x0a\xa8\x01\ \xbf\x00;p\xd3\xech\x80z\x06E\x15\x7f\xb4\x17\x22\ \x84MO\xa1\x83\xc0r-\xc5\x8f\x01d\x07\xa3\xcaE\ W\x18S\xa3\xbe\xf1EH\xca\xd8\x06,\xd6R\xf4%\ oP\xc6v\x01\xd3\x80\x09\xb8\xf5Fg\xd4\x9e+<\ \xf2\xfe\x8dd\x9e\x07~\x05~\x0a\xe1I\xaa\xf8]U\ \x08\x17\x15+\xe0s\x9cG\xb9\xa0\x90(\xf0Z\x09<\ \x02\x5cUP~\x8f2v\x85\x96b\xdf`\x1a\xd9\xc8\ \x00\x85P@\x1f\xce\x98.Ju~\x09.\xeex\x92\ \xe2\x9d\x07\xb8\x19\xd8\xab\x8c\x1d\x94K\xadP?\x05 \ \x8c\x02N\x02+\xb4\x14\xe7\xe2\x02e\xec\x1a\xe0C\xfc\ \x86\xb7\x08\x15\x5c\x5c\xb1U\x19\xeb\xebG&\x01\xed\xe2\ e\xe0\xab\xf8\x872v\x01\xf0j\x9b\xeaz\x1c\xd8\xae\ \x8c\xcd\xbd|\xefP\xc6\xfe\x05\xdc\x90(\xab\x01Wk\ )\x1aEr\xb9Q\xc6\x8e\x06\xfe\xc4\x19\xba4\xbd\xc0\ >\xe0\x14n\xda@k#|7\xf0\x80\xa7\xdc\x00\xf3\ \xd2\xc6\xb6\x19\x85\x86M\x01\x9e\xa7\xbe\xf35`\x15\xb0\ >o\xd4\xa9\x8c}\x07\xf8\x01\xb8+uI\x02\xbb\x94\ \xb1s\xb3*!\xb3\x02\xa2\xa7\x98\x873Z\x8a\x81h\ n.\xf0\x5c\x7fKK\xb1.\xa7L\x00\xb4\x145e\ \xec^\xea\x15\x000\x1b\xf8R\x19\xfb`\x16%T\xc8\ `\xf0\x22\x7f}*\xe7gB\xf4\xf7\xa9\xc0\xb8\x94\xc8\ \x13\xc0k\xad\xeam\xc1\xf1&\xd7f\xe1\x940\xa2\x95\ \x90L\x0a\x18$\xbe\x91c\xf2\xcc\xd3\x064[lA\ F%\x0c\xd5B$D\xa8\x9dEFK%\x0c\xf9r\ \xb4\x04f\xe1\x0c\xa3W\x09Y\x8d`\x0d\x17\x7f\xe7\xa1\ \xd9\x10\x0d1\xed\xf2\xc8\x98\x0d\xecP\xc6>\x9cN\xf2\ dR@4_\xef\xc8Qa+\xcaV\x008\x17\xb9\ ]\x19;/\xe9v\xcb0\x82\xed\xa2\x88\x1dy\x88T\ \xd8\x5c%\x9b\x1b\xec\xc4\xed\x19\xe4\xa1[Kas\xfe\ '\x0fE#\xd5\xc7\x80s@7d\xb7\x01U\x9c1\ \xc9\xc3`VzY8\x84[mNhu\xa3\x87%\ \xca\xd8\x03Z\x8a\x0f\xca\x0a\x85\x83\xa3\xa5\xe8S\xc6\xce\ \xc0E\x99\xd7\xe3\x14\x1e'T\xe2\xef.\x5c\x08>\x91\ \xfa\xcc\xd7\x9b\xca\xd8\xdd\x97\xad\x02\x00\xb4\x14\xc7\x817\ Z\xdd\xa7\x8c\x1d\x03l\x01\xe6$\x8aG\x02K\x87*\ \x0e\x08\x91r\xcb\x8c\x96\xe2$\xe0\xdb\x91\x9a\x99u\x04\ \xf4\x017\xe5\xac7\x97\x01T\xc6>\x0b,\xcdYG\ 3\xa6\xa4\xc2\xed\xd3\x9e{\xba2y\x81(\xf9\xd8\x1b\ \xaae\x0d\xb8\x16\x18\x1fP^zt\xc7{\x99\xc9\xf2\ \xce\xacn\xb0\x8as\x1fy0Z\x8a\x10\xfb\x0b\xa1\xf0\ \xf5\xb3\x9au\x0at\x02[sV8\x990\x1b,\xa1\ \xf0)\xa02\x9c\xbc@\xa8\xfd\x88\x5c\x0c\x95\x02|O\ c5\xb0&T\x05\x19\xd3lC6\x02\xea\x14\x10\x19\ \xda\xb2\xd7%\x99\x15\xd0\x8fK`\xe6\xe1d\x9e\x9b\x95\ \xb13\x81\x199\xeb\x88\xd9\xa4\xa58Q\xe4\x8fY\xdd\ \xe0\x00\xb0\xb6H\x059\x98A\xf1}\x83/py\xc6\ \xdc\x5c\xce\xcb\xe1 \xfc\x1fRbM\xa9P\xefz*\ \xc0\x9dC\xd0\x96!\xa1\x0a|\x8f\xdb\xa3O\xb2Z\x19\ \xfbm\x80sBy\xd8\x81\xdb5.B\xe1\xc4K\x15\ \xf8\x04x!U>\x1d\xd8\xa2\x8c\xed\x0e\x90\xbf\xcf\x84\ \x96\xa2\x07w.\xb1T\xaaZ\x8aC\xca\xd8\xafq\x99\ \xd3$\x0b\x80\xe9\xca\xd8\x8dQ\xc3\xceQ\x7f8\xb2\x19\ \xbdy\x8e\xd9Ek\xf6\xbc\xdbo\xcd8\x92\xe5\x04I\ \x1c\x07,\x07\xee\xa1>\x8d5\x11\xd8T\xb0\x01\x93q\ '\xc6\xb3\xb2\x8c\xb0\xdb\xe7W\xd2z\xf7\xc8y\x01-\ E/\xf0\x04\xed\x89\xc5K\x8f\xef\xf3p\xc1\x0dj)\ v\x03s)g\x057l\x16a\x97\xc4\x01Z\x0a\x03\ \xdc\x0a|\xc60\x7fr\x81\xa8\xd5=\x09-\xc5Q`\ \xbe2\xf6%\x5c\x12q\x0a0\x96\x8b\xc7\xd8\xe2\xecj\ \xab\xa7\x18{\x0f\xef:\xdcS\xf67\xee,a(\xd2\ \xf5zO\xc35\xecD\xb4\xa9\xb19@C|#\xc9\ \xa7\xf8\xcd\x81\xeak\x84W\x01e\x84\xc2\xdeTT\x09\ \xf5\xa6\x89_\xf8J2P\x86\x02|#\xa0\xe5\xc9\x8d\ 6\xe0;\x9a\xd7_\x86\x02|\x91\xe4\xcd%\xd4\x9bF\ x\xca\xce\x96\xa1\x80c\xd4\x8f\x82i\xca\xd8\xdbJ\xa8\ ;\x89\xf2\x94\xf5\xb4]\x01Z\x8a\x7f\x80\xf4\x09\xf1\x0a\ n\x9b:\xe4\x1bj\x0dQ\xc6.\xc4\x1d\xa6L\xb3\xa7\ \xee\xc5\xc965@\xe2\xdf^?Jt\xa24y\xa4\ 6P\x9d\x9d\xb8\x03\xa0\xcbp/g\xa4\x1f\xf6a`\ JY\x0a\xa8\x00\xdf\x00\xf76\xb8\xa5\x86\xb3\x15\xc9\xb7\ \xd2\xf2&Ic\xcfR\xc1Y\xfc\x114\xf76\xf7k\ )\xf6\x95\xa2\x00\x00e\xec8\xe0g\xfc\xc6\xa8l\xd6\ j)VA\x89)\xb1h+\xfb>\xda\xbf\xc7\xd8\x8a\ \xf5$\x0ei\x966\x02b\x94\xb1\xa3\x80\x0d\xc0B\xca\ \x0d\x88\x8e\xe1\xdeW\xdc\x99,,]\x011\xca\xd8\xf1\ \xc0b\xdc\xe9\xadv\x05F\x03\xb8d\xce.`\xa7/\ \xbb\xf5\x1fI\xbe\xe3\x04\x8a&p\x8b\x00\x00\x00\x00I\ END\xaeB`\x82\ \x00\x00\x03\x9e\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x03eIDATx\x9c\xed\x9b\xbbk\x14Q\ \x14\xc6\x7fY\x96%b\x1e\xbe\x90\x05e\x8a \x18T\ RD\x89i|4Z\xa8Le\xa1 #\x0a\xda(\ \xf8\x04\x05\x0b\x0b\x1b\x1f\x85\xa066*\x83\xf8\x07L\ #\xb1H \x85\x88E\x90 \x22\x161\x0e\x01EB\ \x08\x22(KX,v7L\xee\xdc\x9b9$\x90\x83\ \x99\xf9\xe0\x169\xbb\xdf\xdco\xbe\xbd\xf7\xcc=\xb9s\ \xdb\x82(.\x03w\x80\x13\xe4\x0b\xc3\xc0\xa5\xd6\xcd\xdf\ T\x16\xa3\x81\xb3@G\x09\x18\xd4V\xa2\x88\x81\x92\xb6\ \x02m\x94\x1d\xf1z\xa2-\x86\x8a%V\x13\xf4[\xb2\ \xf4]\x07\xe6\x04\xdcr\x93\x9f\xc4\x1ci\xad\xe6wJ\ \x96X:\xd0\xc4N\xa0\xb3\xd9\xd6\x02k,m\xbb\x85\ 7\xe1\xf8\xae\xd9\xaeY\xb8O\x84\xdca\x0b\xf7PS\ g\xa7\xd1\xba\x81\xf5\xcd\xb6\x11\xcb\x8fc\x1b\x01u`\ :\xf4\xbd\xbf\x96\xcf\xe6\x11D\xb1ut\x84\xbe\x975\ j\x5c\xdc\xfa2\xb9\x99\xa3'\x88\xe2\x1a\xc6\xa8u\x8d\ \x80L!\xab\x05y3 5Jr\xff\x14\xc8\x9b\x01\ \xc5\x080Q\x18\xa0-`\x85\x91J\xee\xae\x95\xe0\x8e\ \x8a\x7fg\x5c\xacj\x89U\x82(\xee\x13\x08\xd9b\ \x89m\x12r\xbb,\xb1\x9e \x8ag\x05\xdc\xd4\xfd\xb6\ \x05Q<\x02\x1c\x14\x90W#&\xf36\x05R(\x0c\ \xd0\x16\xa0\x0dW\x12\x1c'\xbb4\xad\x00\xbb\x8cX\x0d\ \xf8(\xe8w3\xb0\xd5\x88\xfd\x04\xa6\x04\xdcm\xa4\x13\ \xe1\x17 +i\x03\xf4a\xdc\xb3\xab\x1a<\x10\xfa\xde\ \xa2Y5\x88b\x0f\xf8f\x84\xa7B\xdf\xdb\x9d\xa5\x22\ \x88\xe2\x8b\xc0c#\xfc*\xf4\xbd+\x02\xee\x10p\xd8\ \x08\x9f\x0b}oT\xc0\xfd\x8e\xf1\xf4\xca\xfd\x14(\x0c\ \xd0\x16\xa0\x8d\xc2\x00m\x01\xda(\x0c\xd0\x16\xa0\x8d\xdc\ \x1b`\xab\x06\xeb\xc0]\xe0O\x06\xb7\x1b\xb8n\xc4f\ \x80\x87\x82~\xf7\x02\xc7\x8c\xd8[\xe0\xb5\x80{\x9a\xc6\ j0\x89g\xc0W\x01\xf7\x06\xd0\x91\xf8{\xb2(\x87\ \xb5\x15h\xa30@[\x806\x5c\xd5\xe0}\xb2wy\ \xbb\x80\xcbFl\x16x$\xe8w\x0fp\xc4\x88\xbd\x03\ \xde\x08\xb8\xa7\x80\x1e#\xf6\x02\x88\x05\xdc\xab,L\x82\ \xce\xff\x07\xdc\x13\x96\xc3\xa6\x013\xa1\xef\xdd\xceR\xd1\ ,\x87S\x06\x08\xb9\x83\xa4\x0dx.,\x87\xcfc\x18\ \x90\xfb)P\x18\xa0-@\x1b\x85\x01\xda\x02\xb4Q\x18\ \xa0-@\x1b\xb97\xc0U\x0d\x8e\x91\xbd1\xd2Nc\ \xa3!\x89\x1a\xf0A\xd0o\x15\xf0\x8c\xd8\x0fd\xab\xb9\ ^\xd2\x1b#\x9f\x81_\x02n?\x0b\x17\x7f\x93\xae\x95\ `\xbf\xe0b6T\x80\x81%r\xab\xd8\xb7\xdc%\xe8\ ]\x22\xaf\x98\x02\x85\x01\xda\x02\xb4\xe1*\x87\xf7\x91\xbd\ \xdbZ\x05\x86\x8c\xd8\x14pT\xd0\xefI\xd2g\x14^\ \x02\x0f\x04\xdc\xa7\xa4_\xf1?C#qga\x04\xd8\ \x90\x0c\xb8\x92\xe0'A9l\xfb\xbc\x16\xfa\xdex\x96\ \x8a \x8a\xf7[\xc2\xd3B\xae-\xdbO\x08\xb9\xe2\xf7\ \x04W\xeb\xd4\x10\xbf.\x9f\x1b\x14\x068\xe2\xae\xdc\xf0\ \xbf#u_6\x03r5*\xf2\x96\x04E# W\ p\xcd\xf5u\x89\xe7m\xeb\xd99\x7f\x8aLr\xb6G\ \x03A\x14'\x7f\xd0\xd6\xbd\x95\x12M\xfc\xaepr\xc1\ `=\xa4\xd4\xbc\xa0\xed\xd8\xdc\xa2\x87\xad\x12\xe2L1\ s\xc8\x8e\xcdUH\x8f\xdcZB\x93\x09\x9b)-8\ \xcb\xe1\xe5<\x05\xda\x97\xc8\xb3\x99\x22\x85\xed\x87\x10!\ \xf79\xa0\x04\xbc\xd7\x16\xa1\x88\xb12p\x8b\x86\x11\xc7\ \x95\xc5\xac4F\x81\x0b\xff\x00\xf9\xc0\xcf]\xc7\x08g\ W\x00\x00\x00\x00IEND\xaeB`\x82\ \x00\x00\x03\x04\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x02\xb6IDATx\x9c\xe5\ \xda?n\x13A\x14\xc7\xf1o,\x0b\xa5F$B(\ ZYQ\x14E\x08\x10\x05g\xa0tKk\xcdA\x88\ b\x0eA\xc5\xe6\x0ah\x1a\x84\xd0\x8a\x82[\xd0 \x8d\ ((8\x00\xa2\xa2\xd8]\xe3?k{g\xf7\xcd\xcc\ \xf3\xfaWg\xde\xfa\xf3\xdb\x97Mb\x07z\xc4X\xf7\ \xba\xcfy\xe9\x18\xebN}\xcf\x8cz\x5cl\x06\xbc\xef\ z^:\xc6\xba\x87\xc07c\xdd[\x9fs\x9d\x0a\xa8\ \xf0\x1f\x80\x07]\xceK\xa7\xc2\x7f\x06^\x01w>%\ x\x17\xb0\x84\xef\xbc=\x921\xd6=\xe2?\xbeN\xeb\ \x12\xbc\x10J\xf1_X\xc5\xd7iUBk\x88b\xfc\ \xcb\x1d_\xb6\xb7\x84V\x98\x1d\xf8q\x9b\xf3\xd21\xd6\ \x9d\xb3\x1f_gg\x09{\x0bPx\xe7}\xf0u\xb6\ \x96\xb0\x13\xa5\x18\xff\xa2\xc3\xf1\xc6\x12\xb6\xc2\x94\xe2\x0b\ \xba\xe1\xebl\x94\xd0\x88\xf3\xc0Gy\x06,\xe1\x9f\x09\ \x8c[)a\x03\xa8\xf0\xce?F\x0e_gQ\xc2\xc9\ \xda\xc5f\xf8\xe1\x7f\xe7\xd3\xecL\xf0\x85\xadd\x09\xff\ 4\xc0\xf8\xbf\xc0\xf3\x05T\xf1\x9d\x0f\x85\x7f\x93O\xb3\ \xef\xa3\xeab3\xba\xe1\x83\x94e\xac{Bx\xfcG\ \x80q\xcf;/^\xc0\x12\xfeFz6kx(\x01\ \xb7\xe8Y\xfb\xa8xP\x02\x070\xd6]\x00_\x89\x88\ \x87\xfe\x05\x8c\x8cu\xbdK\xac\xf0\x05p\xddwVC\ \xb6\xe2A\xc1\x06\xa4\xc4C\xe2\x02\x8cu\x19\xe5\xda'\ \xc1C\xc2\x02*|\x01\x5c\x05\x18\xdf\x0a\x0f\x02\xcf\x80\ .3\xb4\xe0!\xc1\x06\x18\xeb&\x94k\x9f\x1c\x0f\x91\ \x0b\xa8\xf0\x05p\x19`\xbc7\x1e\x22\x16\xa0\x11\x0f\x91\ \x9e\x01\xc6\xbaK\xca\xb5W\x85\x87\x08\x1bP\xe1\x0b`\ \x12`|/<\x04.@;\x1e\x02\x16`\xac\xbb\xa2\ \x5c\xfbI\x80\xf1\x22x\x08\xf4\x0c\xa8\xf0\x05\x90\xf5\x9c\ \xdf\x141<\x84\xf9{\xfe`\xf0 \x5c\x80\xb1\xee\x9a\ r\xed\x0f\x02\x0f\x82\x05T\xf8\x02\xb8\x90\x9a\xb9\x94 \ x\x10z\x06\x1c*\x1ed6\xe0\x86r\xed\x0f\x0e\x0f\ \xfd?\xd9\x19\x03\x9f\x80s\x81\xd7\xb2\x9e\xe0x\x90\xf9\ \x168X<(xK\xac!\xd1\xf0\xa0\xaf\x80\xa8x\ \xd0U@t<\xe8) \x09\x1et\x14\x90\x0c\x0f\xe9\ \x0bH\x8a\x87\xb4\x05$\xc7C\xba\x02T\xe0!M\x01\ j\xf0\x10\xbf\x00Ux\x80\x13c\xdd\x0f\xc2\xbcm\xd5\ \x94?\xc0\xafH\xd7j\x93w\xb1\xff\xd5\xf5\x94xe\ \xef\xcb<\x9ffy\xea\x1f\x83\xa92\xcf\xa7\xd9-\xa4\ \xff= E\x16x8\xbe\x02V\xf0p\x5c\x05l\xe0\ \xe1x\x0ah\xc4\xc3q\x14\xb0\x15\x0f\xc3/`'\x1e\ \x86]\xc0^<\x0c\xb7\x80Vx\x18f\x01\xad\xf10\ \xbc\x02\xbc\xf00\xac\x02\xbc\xf10\x9c\x02:\xe1\xa1\xfc\ h\xeb\xa7\xf0\x8b\x89\x9d\xfb|\x9a\xcd\xbb\x1e\xfe\x07\x14\ \xfeM[$\x08\x00C\x00\x00\x00\x00IEND\xae\ B`\x82\ \x00\x00\x06\x11\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ \x01\x95+\x0e\x1b\x00\x00\x05\xc3IDATx\x9c\xcd\ \x9bK\x8f\x15E\x18\x86\x1f\x08!\xc4\x18c\x5c\xb90\ \x95\x89\x0b\x7f\x81\x0b\xe3\xc2xCD\xa0\xb8\xaaQ\xa3\ \xa6\x8dQ\xe2\x15D\x10\x87[\xb8{\x17\xbc\xa1\x0b\xad\ \x18EDP\xa1D\x10\x141\x06\x89!\x86\xb8pm\ &\xbdpE\x0c!d2\x99\x98\x89\x8b\xaa\x9e\xe99\ \xd3\xddU]]\xdd\x87ww\xba\xab\xab\xbf\xf7\xa9\xea\ \xea\xaa\xfa\xfaL\xc3C\x89N\xef\x06f\x03\xab\x95\x14\ c>\xd7\xf4K\x89N\xa7\x03\xdb\x81\xdf\x94\x14G\x5c\ \xe5\xa7yT8\x1f8\x00\xcc\x02>\x01\x9eTR\xfc\ \xd74\xd06d\xcd\xbf\x0f,\x07F\x81{\x95\x14\xba\ \xea\x9aJ\x00=\xe63}\x0e$\x97\x1b\x84D\xa73\ \x80\x8f\x80\xc7r\x87G\x81\xfb\x95\x14\x87\xca\xae+\x05\ `\xbb\xfd\xb7L6\x9f\xe9\x0b\xe0\xd1\xcb\x05\x825\xff\ 1\xf0H\xc1\xe9Q`\xb1\x92\xe2h\xd1\xb5\x85\x00\x12\ \x9d\xde\x0e|\x07\x5cQq\xdf/\x81\x87\xfb\x0d\xc1\x9a\ \xff\x14x\xb0\xa2\xd8\x08\xb0@I\xf1S\xef\x89)\x00\ \x12\x9d\xde\x02|\x0f\x5c\xe9q\xff\xaf0\x10F\xfd\xc2\ \x8d\xabD\xa73\x81\xcf\x80\xfb<\x8a_\x02\xe6))\ ~\xcd\x1f\x9c\x04 \xd1\xe9M\xc0q\xe0\xaa\x1aq\x1c\ \x04\x1e\xe8\xba'\xd8\x96\xdf\x07,\xabq\xd9E`\x8e\ \x92\xe2\xf7\xec\xc08\x80D\xa77\x02?\x02W\x07\xc4\ s\x10x\xa8\xab\x9e`[~/\xf5\xccg\xba\x00\xdc\ \xa1\xa48\x070=w\xe2Z\xaa\x9f\xf9*-\x03\xf6\ \xdaViU\xd6|\xdd\x96\xcfk&pM\xf6c\x1c\ \x80\x9d4,\xc5\x0c\x18!j\x1d\x825\xbf\x1fX\x12\ X\xc50\xe6\x8d0>\x18\x16\x0d\x82E\xef\xfe:j\ \xe5q\xc8\x99_\x14XEf\xfeD\xfe`\xd9k\xf0\ \x1e\xe0k\xc2!|\x83\x19\x18\xa3@h\xcb<\x84O\ \x84|\x14\x05B\x9b\xe6a\xf2 8IJ\x8a\x1f0\ c\xc2p\xe0\x8d\x97\x00\xfb\xac\x81 \xb5m\x1e\xfc\x16\ Cw\x01\x87\x09\xef\x09\x870\xf3\xf1Z=!\x82\xf9\ \x11`a\x95y\xa8\xe8\x01\x99l\x05\x0b\x09\xef\x09\x8b\ \x80\xfduzB\xa2\xd3Y\x98\x81\xb8U\xf3\xe0\xd1\x03\ rA\xdd\x89\xe9\x09\xa1s\x05\x8dY\x9eV\xf6\x04\x0b\ \xea\x00 \x03\xef3\x02,-[\xfc\xf4\xca\x1b\x00D\ \x81p\x04\x03\xa1p\xae\xd1\xb5y\xa8\x09\x00\xa2@8\ \x8a\x09r\x12\x84~\x98\x87\x00\x00\xe0\xbd\x5c\xae\xd2\x09\ \xcc\xe8_\xc1t`\ w\xa2\xd3\x17\x5c\xc1()\xce\xd0\x1c\xc2E`\xae\xa7\ \xf9\xb5L\x98\xcf4\x80\x03B\xd9\x96\x98\xc0t\xfb*\ z/+)^\xf1\x08\xecf\xe0\x18\xf5r\x0d0a\ \xfe\x8c\xc7=\xd6\x02;+\x8a\x0ca\xb6\xc2\xff\xee=\ 1\xa5\x07X\xf3\xbd-_\xa4\x9d\x89N\xd7\xbb\x82\xb3\ \x06\xe6`\xf6\xe3}u\x01\x93\xc0\xf01?H\xb5y\ \x98\xe8\x09\x03\xbd'z3C>-\xdf\xabMJ\x8a\ -\xaeB6\xebt\x0cw\xe2%3\x7f\xd6\xa3\xce\xf5\ \xc0V\xaf(\x8d\x86\x80\xdb\x94\x14C\xd9\x81|f\xe8\ :L\xcb\xdfP\xa3\xc2L\xdb\x94\x14\x1b\x5c\x85< \ \xfc\x8b1\xff\x87G]u\xcdg\x1a\x22\x07!\xff\x08\ ,#\xcc<\xc0\xfaD\xa7\xdb]\x85lN\xae\xecq\ 8\x8f\xbf\xf9\x8d\x84\x99\x07\xf38\x8c\xaf<\xf3\x99\xa1\ ]\xc0\x8e\xc0J\x01\x06=!\x9ce*\x84\xf3\xc0\xec\ \x1a\xe67\x07Gi\x1e\xd9w\xb2\x1fE\x99\xa1\xad\x80\ sp\xab\xd0\x0e%\xc5:W!\x9b\x8c=\x0e\x8ca\ \xcc\xff\xe9q\xcdf`c\x83\xd8\xb6()6\xe5\x0f\ \x94\xbd\x06\x9bBxMI\xf1\x92\xab\x90\x850\xa2\xa4\ \xf8\xcb\xa3l\xd3\x98\x0a\x07\xeb\xaa\xccPS\xda^\x10\ |\x14!\x96\x0dJ\x8amE'\x5c\x1fI\xf5\x1d\x82\ \x1dW\x06\x1bTQj\x1e\x1ck\x01\xfb\xbc8\xdf\xf1\ \x15Z\xe330\x96\xa9m\xf3\xe0\xb9!\xd2\xe0\x9d\x9b\ \xc9k`\xec\xb9g\xeb\xe6\xa1^f\xa83\x08\x11\xcc\ \xafSRx\xbd\xd2\xbdw\x84,M\xe7l\xafB\x83\ v$\xafT\x97\xe6!,34\x88\xf9\x167T\xa5\ \xd3\xe6D\xa7;\x81\xb5\x0d\xea\xaee\x1e\xc23C\xd1\ !D0\xef\xb5<\xefU\x93\xcc\x90k\x0d\xee\xd28\ \x84~\x99\x87\xe6\x99\xa1\xc6\x10\x80\x19\xf4\xc9<\xc4\xc9\ \x0c5\x85\xd0D\x8d\xccC\xbc\xcc\xd0\x8b\xc0\xeb1\xea\ \xaa\xa1\xd5J\x8a7\x9aV\x1233\xd4%\x84(\xe6\ !\x22\x00\x00\xbb[\xfcf\xcc:\x0b\x14\xcd&3\x05\xb3\ \x8b\x07\xd8\xa9\x8c]ZDS\xdb\x0cP\xc6\xf6\xe3\x8a\ \xaf\xe7\x84\xd5q&\xf4g\xf4\xdf\x96\xd1\xde\x05\xdc\x5c\ DW[\x0cP\xc6\xd6q\xc5g\x156\x93~\x9c\x09\ yF\xcdE\xa1Z*7@\x19\xbb\x12W|\xde\xd4\ nd9\xce\x84\xb9\xa6{\xa9Tj\x802v\x00\x18\ \x01\xfa\x0a\x0c\xef\xc3\x990P\xae\xaa\xab\xa9\xcc\x00e\ \xec\x1d\xc0)\xa0\xb7\x854\xbd\xc0)\x9f\xab\x12*1\ @\x19{7p\x12\xe8\x09\x84\xfe\xe2\xff\xf2\xe8\x01N\ \xfa\x9c\xa5\xd3UvBe\xec\x1a\xe0\x18\xd0\x1d\x08\xfd\ \x11X\xe7?\x7f\x09\xdc\x99\x13\xbb\x048\x0e\xfc\xd9\xb2\ \xc0\x06J\x9d\x01\xca\xd8!\x5c1\xa1\xe2\xbf\x03\xd6j\ ).\xf8\xd5\xdfZ\xdf\x96G7p{\xab\x1a\x1b)\ \xcd\x00e\xec\x06\xe0(\xb08\x10z\x02\x18\xd4R\x8c\ M5\xf8\xcf\x83\xc0\xd7e\xe9\x89\xa5\x14\x03\x94\xb1\x9b\ \x81\x8f\x08\x17o\x80\x07\xb5\x14\x97\x1a;|\xdbz\x1f\ \xd36Z6@\x19\xbb\x158B\xf8~\xf2\x09\xb0Q\ K1\x91\x15\xe0\xfb6\xfa\xd8\xb6\xd0\x92\x01\xca\xd8\xed\ \xc0\xc1\x88<\x1a\xd8\x94W\xfct\xa0\x8b\xd9\xe4\xc7T\ Na\x03\x94\xb1\xbb\x80\xb7\x22r\xbc\x03l\xd1R\x5c\ \x8e\xcd\xedc\xb7\xf8\xb1\x95R\xe8kP\x19\xbb\x07x\ 1\x22\xf4\x0d-\xc5\x8e\x22\xd7\xd0RL\x02\xdb\x94\xb1\ \xe3\xc0\xd3\x11C\x06\x09\x7f\x93\xcc\xa2\xe9\x19\xa0\x8c}\ \x85\xb8\xe2\xf7\x15-~&>\xc7\xbe\x88\xd0]^[\ SDo\x88(ck\xc0~`{D\xf8\xb0\x96\xe2\ \xe5f\xc5\x04\xae\xff\x02\xf0RD\xe8\x9b\xc0\x0e?\x83\ \x82D\x19\xe0\x8b?\x08l\x8d\x08\x7fFK\xf1zL\ \xdefQ\xc6\xee\x04^\x8b\x08=\x04l\x8b1!h\ \x802\xb6\x0bx\x1f\xd8\x1c\x08\x9d\x04\x9e\xd2R\xbc\x1d\ !\xb00\xca\xd8'\x89\xbb\xf9~@\xc4\xcd7\xd7\x00\ e\xecb\xe0C`C\xe0b\x93\xc0\x13Z\x8a\xf7\x02\ q\xa5\xa0\x8c}\x1cx\x97\xb0\x09\x9f\x12\xf8\xfa\xcd4\ \xc0\x17\x7f\x14\x18\x0a\x5c\xe42\xf0\x98\x96\xe2\xe3@\x5c\ \xa9(c\x1f%n\x01\xf6\x05\xf0p\x96\x09s\x1a\xe0\ w_\x8f\x01k\x02\xc9'\x80G\xb4\x14\x9f\x05\xe2*\ A\x19\xfb\x10qK\xf0oqK\xf0\xf1\xc6\x8eY\x06\ (c\x97\x00\x9f\x03\xa1\xe7\xefK8g\xbf\x8a\x93[\ \x0d\xca\xd8\x07p3\xf5\x86@\xe8\xf7\xc0z-\xc5\xc5\ \x99\x8dW\x19\xe0\x0f,\x8e\x03\xa1\x1d\x98q\x9f\xect\ sr\xabA\x19{/n\xc6\xde\x18\x08\xfd\x09\xf7$\ :}\x003m\x802\xb6\x17\xb7\x8b\x13\xb3\x07\xf7\xbb\ \x96\xe2\xd6\x02Z+C\x19{\x96\xfcM\x95)~\xc5\ \xedE\x9c\x07\x7f\x17\xf5\xa75#\xc4\x15?=\xee\x1a\ #V\xd3\x000\xe2k\xa6\xe6OT\xb2Nk\xe6+\ S\xa7PKk\xc0^\xf2Ok\xe6+u`o\x0d\ w\xca\xbaPYU\x03\xc6\x82a\xf3\x97\xb1\x1ap8\ \xa3\xf3\x8fv*\xa9\x98\xbf2\xda\x0f\xd7\xb4\x14\x07p\ \xcf\xdb3\x97\x8a\xa7\x81{*\x97\xd5>\xd6\xe1j\x9a\ b\x02\xb7_q\xa0\x06\xa0\xa5x\x1eX\x06\xdc\x05\xac\ \xd0R\xac\xd6R\x8c\xb6_ge\x8cj)V\x03+\ p5.\xf35\xff\xff \xa1\xa5\xf8\x17\xf8!\x8d\xbe\ \xf6\xa0\xa58\x07\x9c\x9b\xd9v-.h\xdaJ\xc7\x80\ \xd4\x02R\xd31 \xb5\x80\xd4t\x0cH- 5\x1d\ \x03R\x0bHM\xc7\x80\xd4\x02R\xd31 \xb5\x80\xd4\ t\x0cH- 5\x1d\x03R\x0bHM\xc7\x80\xd4\x02\ R\xd31 \xb5\x80\xd4\x14\xfd\xbd@]\x19\xfb_\xa9\ JZ'\xf4\x96\xc8\x9c\x145\xa0F\xf8\x8d\x8c\xeb\x82\ \x05\xff/\xb0P\x0c\xc8|a2d\xc0|8 \x1d\ \x05\xcegu\x86\x0c\x18&\xc7\xbd\xeb\x84\xe1\xbcWf\ c^\x95\x1d\x02\x9e\x05D\x99\xaa\xda\xc0\xdf\xc0~-\ E\xee\xafO\xae\x00\x90\x16<\xb6\x99\x16\x0en\x00\x00\ \x00\x00IEND\xaeB`\x82\ \x00\x00\x06\xe6\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ \x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\ \x00\x00\x06\xadIDATx\x9c\xd5\x9bm\x88UE\ \x18\xc7\x7f^\x16\x11S\x11\xf1\x8d\xc5\xa6\x123\x11\x11\ I\xc9\xad\xd6\x97\xc22+\xa6\x08?\x84\xc4\x14\x99\x1f\ \xcc\x0fe&&\x11a[\xf4\xa1,\xd0\x04\xb1T\x9a\ \xb2\x22z\x81\xd1DBMeI\x90\x8a0\x13\x11\xb3\ e\x90E\xccBDd\x89\xe5\xd2\x87\x99\xbb\x9e=\xf7\ \xdc{\xe7\xee\x9e\xb9w\xfb\xc3\x81;s\x9e3\xf3\xcc\ \x7f\x9eg^\x9e\x99\x0b\xff\x13(cG*c\x0by\ \x97\xdb\x92w\x81yC\x19\xbb\x10X\x03,\x04n\x01\ \xfe\xcd\xb3\xfc!K\x802v\x09\xd0\x01\xb4\xf9\xac\x03\ Z\x8a\x5c\x1b\x0fC\x90\x00el+\xb0\x0dx<\xf5\ \xea\x87\x18\xf5\x0d)\x02|\xaf\xef\x01&f\xbc>\x16\ \xa3\xce\xdc\x07\x95\x81B\x19\xab\x80\xef\xc8n\xfcU\xe0\ \x97\x18\xf5\x0e\x09\x0bP\xc6>\x05\xec\xa6r\x87\xfc\x18\ \xc3\xff\xa9Ra\xc3\xa0\x8c\xbd\x1f\xd8YC\x97C\xb1\ \xeao*\x01\xca\xd8\xc9\xc0\xe7\xc0\xf0\x1a\xa2Q\xfc\x1f\ \x9ao\x01\xdb\xc8\xf6\xf9$\xae\x10\xc9\xff\xa1\x89\x04\xf8\ \x05\xce\x13\x01\xa2\x9dZ\x8a\xdeXz4\xd3\x02^\x0d\ \x94\x8b\xe6\xff\xd0$\x02\x94\xb1\x02X\x12(~$\xa2\ *M\xb3\x00\x19X\xf7e\xe0TLE\x9aE\xc0\xb2\ @\xb9c1\xfd\x1f\x9a@\x802v8ng\x17\x82\ (\xeb\xff$\x9aa\x01w\x01\xa3\x02e\x0f\xc7T\x04\ \x9aC\xc0\xe2@\xb9\x8b\xc0\x99\x88z\x00\xcd!`Q\ \xa0\xdc\x11-E1\xaa&4\x98\x00\xef\xffm5\x05\ \x1d\xa2\xce\xff%4\xda\x02\xe6\x11\xee\xffG\x22\xea\xd1\ \x87F\x13\xb08P\xcej)\xce\xc5T\xa4\x84F\x13\ \x10\xec\xff1\x95H\xa2a\x04\x0cE\xff\x87\x80\x88\x90\ 2v\x140\xd2'\xafk)\xae\x0d\xb0\xae9\xc0\x98\ \x00\xb9\x22\x0d\x98\xff\xc1\x9d5\x94\x11\xa0\x8c\x1d\x07<\ \x89[\xae\xce\x03\xc6\xe3,\xa5\x00\xf4*c\xaf\xe1\xd6\ \xe7G\x80O\xb4\x14g\x03\xeb\x0b]\xfd\x9d\xd5R\x5c\ \x08\x94\xad\x09e\xecx`\x9a\x7fnO\xfc\x9e\x06t\ \xb6$\x04\x0b\xc0\xcb\xb8mj\xa5\x9ej\x01\xc6\x02\xed\ \xfeyE\x19\xfb)\xb0NK\xf1O\x0d]\xee\x0b\xd4\ \xf9`\xa0\x5c\x1f\x94\xb1c\xb8\xd1\xa8\xe9\xb8\x86N\xf7\ \xe9qd\xbbz\x11\xe8\x18\xe6\x0b\x18\x0e|\x0dp01F4\x1dA\x1b\ \x0c\xafp\xbdJ\xdf[!\x7f\x8c2\xb6\xd0\x88\x98\x7f\ \x08\x86\xd5\x16\x19\x18\x94\xb1G\xa9\xbc\x0b<\x89\x0b|\ \x1c\x02\x0e7\xd3\x22\xa2\x10\xe0\x03,\x7f\x13v\x06\xd0\ \x0d\xac\xd7R4e\x5c\x88\x15\x15\x9eE\xf8\x01H+\ n\x9a\xdc\x1cI\x97\xaa\x88E@h\xf8;\x89\x97\x94\ \xb1y\xacC\xeaB,\x02\xe6g\xe4\x15\x81/qA\ \x935\xc0v\xca\x07\xd6\xb7|\xec\xafa\x88uSt\ NF\xde\x0bZ\x8a\x0f\x92\x19\xca\xd8\xdd\xb8K\x10\xa5\ FO\xc4E\x81\xbe\x88\xa4W\x19r\xb7\x00\x1f\x01\x9e\ \x9a\xca\xeeL7\x1e@Kq\x02H\xe7/\xcd[\xa7\ j\x88\xe1\x02\x93)\x1f\x00?\xac\x22\xbf7\x95\x1e\xcc\ 2\xbcn\xc4 \xa05\x95.\x02eq\xfe\x04l*\ =9_u\xaa#\x06\x01\xe9P\xd6e\xca\xa3N\xd5\ \xd0\xd0\x1b\xec1\x08H\x8f\xe2Wk,{\xd3!\xb5\ \x01\xef\xed\x07\x82\x18\x04\xa47H\xb5\xee\xf9\x89T\xba\ fH>O\xc4 \xe0j*]+\xb6?7\x95\x8e\ ~3,\x89\x18\x04t\xa5\xd2\xe3\xfd\xde\xa0\x12\xd2g\ \x92\xc7\xf3U\xa7:b\x10\xd0M\x7f3\x1e\x03,\xcf\ \x12T\xc6>\x04\xdc\x99\xc8\xea\x05\x0eD\xd0\xa9\x22r\ '\xc0\x0fx\xfbS\xd9[\xfd?\xc2\xfa\xa0\x8c\x9d\x07\ |\x9c\x92\xdb\xaf\xa5\xb8\x98\xb7N\xd5\x10k;<\x1b\ \xf8\x99\xf2)\xed4.\xcc^\xbad\x91|\xdf\x8b\x0b\ \x93G\xfbwH\x16b\x06D\xde\xa1\x7f\xa8\xbd\x16^\ O\x1f\x5c6\x021o\x89m$\xfb\xa8<\x0b[\x80\ 7#\xeaR\x11\xd1,\xa0\x04e\xec\xc3\xb8\xdb\x18\x0b\ )'\xfc$\xf0\x9a\x96\xc2\xc4\xd6\xa3\x12\xa2\x13P\x82\ \xbf}6\x13\xe7\xf7E\xdc\x81GW\xa3\xea\xaf\x84\xff\ \x00\xd6\x7f\xd2\xf9\xcb\x930\xf2\x00\x00\x00\x00IEN\ D\xaeB`\x82\ " qt_resource_name = b"\ \x00\x0d\ \x0b]\x12\x87\ \x00c\ \x00h\x00e\x00c\x00k\x00m\x00a\x00r\x00k\x00.\x00p\x00n\x00g\ \x00\x0a\ \x01\xb9<\x07\ \x00l\ \x00o\x00c\x00k\x00e\x00d\x00.\x00p\x00n\x00g\ \x00\x0c\ \x05\xa2\x93'\ \x00b\ \x00o\x00o\x00k\x00m\x00a\x00r\x00k\x00.\x00p\x00n\x00g\ \x00\x0a\ \x0a\xc8\xf7'\ \x00f\ \x00i\x00l\x00t\x00e\x00r\x00.\x00p\x00n\x00g\ \x00\x0c\ \x08\xfa\xd0\xc7\ \x00c\ \x00o\x00m\x00m\x00e\x00n\x00t\x00s\x00.\x00p\x00n\x00g\ \x00\x0b\ \x08!\xd0\xc7\ \x00n\ \x00u\x00m\x00e\x00r\x00i\x00c\x00.\x00p\x00n\x00g\ \x00\x18\ \x07\xae\x12\xa7\ \x00a\ \x00l\x00p\x00h\x00a\x00b\x00e\x00t\x00i\x00c\x00a\x00l\x00_\x00s\x00o\x00r\x00t\ \x00i\x00n\x00g\x00.\x00p\x00n\x00g\ \x00\x0c\ \x0e=<\x07\ \x00u\ \x00n\x00l\x00o\x00c\x00k\x00e\x00d\x00.\x00p\x00n\x00g\ \x00\x14\ \x02u|\xe7\ \x00a\ \x00r\x00r\x00o\x00w\x00_\x00n\x00e\x00x\x00t\x00_\x00l\x00o\x00w\x00e\x00r\x00.\ \x00p\x00n\x00g\ \x00\x09\ \x05\x88\x8b'\ \x00g\ \x00l\x00o\x00b\x00e\x00.\x00p\x00n\x00g\ \x00\x0c\ \x06\x15G'\ \x00s\ \x00c\x00r\x00a\x00m\x00b\x00l\x00e\x00.\x00p\x00n\x00g\ \x00\x08\ \x03\xc6Y\xa7\ \x00p\ \x00l\x00u\x00s\x00.\x00p\x00n\x00g\ \x00\x0a\ \x07\x96@\x07\ \x00a\ \x00t\x00t\x00a\x00c\x00h\x00.\x00p\x00n\x00g\ \x00\x0f\ \x02Ba\x07\ \x00s\ \x00h\x00i\x00f\x00t\x00_\x00r\x00i\x00g\x00h\x00t\x00.\x00p\x00n\x00g\ \x00\x08\ \x06\xc1Y\x87\ \x00o\ \x00p\x00e\x00n\x00.\x00p\x00n\x00g\ \x00\x0b\ \x03\x03\x9bG\ \x00z\ \x00o\x00o\x00m\x00-\x00i\x00n\x00.\x00p\x00n\x00g\ \x00\x08\ \x0f\x06ZG\ \x00a\ \x00x\x00i\x00s\x00.\x00p\x00n\x00g\ \x00\x09\ \x05\x9e\x83'\ \x00c\ \x00l\x00o\x00c\x00k\x00.\x00p\x00n\x00g\ \x00\x0a\ \x06\x9a\xc9\xa7\ \x00e\ \x00x\x00p\x00o\x00r\x00t\x00.\x00p\x00n\x00g\ \x00\x0a\ \x06\x96/\xc7\ \x00m\ \x00e\x00m\x00o\x00r\x00y\x00.\x00p\x00n\x00g\ \x00\x11\ \x04\xef:\xc7\ \x00d\ \x00e\x00c\x00r\x00e\x00a\x00s\x00e\x00-\x00f\x00o\x00n\x00t\x00.\x00p\x00n\x00g\ \ \x00\x07\ \x0d\x07W\x87\ \x00f\ \x00i\x00t\x00.\x00p\x00n\x00g\ \x00\x0c\ \x0b\xdf!G\ \x00s\ \x00e\x00t\x00t\x00i\x00n\x00g\x00s\x00.\x00p\x00n\x00g\ \x00\x0e\ \x0f\x96\x9b\x07\ \x00l\ \x00o\x00c\x00k\x00_\x00r\x00a\x00n\x00g\x00e\x00.\x00p\x00n\x00g\ \x00\x0b\ \x0cx\xc5\xe7\ \x00b\ \x00u\x00s\x00_\x00e\x00t\x00h\x00.\x00p\x00n\x00g\ \x00\x15\ \x00o\x13G\ \x00l\ \x00i\x00n\x00e\x00_\x00i\x00n\x00t\x00e\x00r\x00c\x00o\x00n\x00n\x00e\x00c\x00t\ \x00.\x00p\x00n\x00g\ \x00\x0b\ \x0d\xe8\xc5\xe7\ \x00b\ \x00u\x00s\x00_\x00f\x00l\x00x\x00.\x00p\x00n\x00g\ \x00\x08\ \x00\xa7Y'\ \x00l\ \x00i\x00s\x00t\x00.\x00p\x00n\x00g\ \x00\x08\ \x00(Z\xe7\ \x00f\ \x00i\x00l\x00e\x00.\x00p\x00n\x00g\ \x00\x0c\ \x09\xfe\xac\x07\ \x00s\ \x00h\x00i\x00f\x00t\x00_\x00u\x00p\x00.\x00p\x00n\x00g\ \x00\x09\ \x0d\xf7\xa6\xa7\ \x00r\ \x00i\x00g\x00h\x00t\x00.\x00p\x00n\x00g\ \x00\x08\ \x0b\x07Z'\ \x00e\ \x00d\x00i\x00t\x00.\x00p\x00n\x00g\ \x00\x0c\ \x0c\x0a\x0eg\ \x00f\ \x00o\x00c\x00u\x00s\x00_\x00o\x00n\x00.\x00p\x00n\x00g\ \x00\x06\ \x07\xc3WG\ \x00u\ \x00p\x00.\x00p\x00n\x00g\ \x00\x15\ \x04/\x1e\x87\ \x00l\ \x00e\x00f\x00t\x00_\x00i\x00n\x00t\x00e\x00r\x00c\x00o\x00n\x00n\x00e\x00c\x00t\ \x00.\x00p\x00n\x00g\ \x00\x0e\ \x06,\x0dg\ \x00s\ \x00h\x00i\x00f\x00t\x00_\x00l\x00e\x00f\x00t\x00.\x00p\x00n\x00g\ \x00\x0d\ \x09\xf7#\xc7\ \x00s\ \x00t\x00r\x00u\x00c\x00t\x00u\x00r\x00e\x00.\x00p\x00n\x00g\ \x00\x12\ \x03\xe3\x02\xc7\ \x00s\ \x00o\x00r\x00t\x00-\x00a\x00s\x00c\x00e\x00n\x00d\x00i\x00n\x00g\x00.\x00p\x00n\ \x00g\ \x00\x0a\ \x0ah\x0eg\ \x00c\ \x00u\x00r\x00s\x00o\x00r\x00.\x00p\x00n\x00g\ \x00\x08\ \x0b\xb2XG\ \x00r\ \x00e\x00d\x00o\x00.\x00p\x00n\x00g\ \x00\x16\ \x0cfu\x87\ \x00r\ \x00i\x00g\x00h\x00t\x00_\x00i\x00n\x00t\x00e\x00r\x00c\x00o\x00n\x00n\x00e\x00c\ \x00t\x00.\x00p\x00n\x00g\ \x00\x0a\ \x0fzH\xe7\ \x00r\ \x00i\x00g\x00h\x00t\x002\x00.\x00p\x00n\x00g\ \x00\x0b\ \x08T\x9f\x87\ \x00c\ \x00o\x00m\x00p\x00a\x00r\x00e\x00.\x00p\x00n\x00g\ \x00\x08\ \x0b\xd7Y\x07\ \x00l\ \x00e\x00f\x00t\x00.\x00p\x00n\x00g\ \x00\x07\ \x0a\xa9W\x87\ \x00c\ \x00s\x00v\x00.\x00p\x00n\x00g\ \x00\x09\ \x0du\xb2'\ \x00l\ \x00e\x00f\x00t\x002\x00.\x00p\x00n\x00g\ \x00\x19\ \x0d\x16\xd4\xe7\ \x00a\ \x00r\x00r\x00o\x00w\x00_\x00p\x00r\x00e\x00v\x00i\x00o\x00u\x00s\x00_\x00h\x00i\ \x00g\x00h\x00e\x00r\x00.\x00p\x00n\x00g\ \x00\x0b\ \x0cC\x9c\xc7\ \x00c\ \x00o\x00n\x00v\x00e\x00r\x00t\x00.\x00p\x00n\x00g\ \x00\x09\ \x07\x9e\xa2\x07\ \x00s\ \x00t\x00a\x00c\x00k\x00.\x00p\x00n\x00g\ \x00\x13\ \x00\xe0\x93\x07\ \x00s\ \x00o\x00r\x00t\x00-\x00d\x00e\x00s\x00c\x00e\x00n\x00d\x00i\x00n\x00g\x00.\x00p\ \x00n\x00g\ \x00\x0a\ \x08\xcb\xef'\ \x00n\ \x00u\x00m\x00b\x00e\x00r\x00.\x00p\x00n\x00g\ \x00\x0a\ \x08\x94`G\ \x00s\ \x00e\x00a\x00r\x00c\x00h\x00.\x00p\x00n\x00g\ \x00\x09\ \x00W\xbaG\ \x00p\ \x00a\x00i\x00n\x00t\x00.\x00p\x00n\x00g\ \x00\x08\ \x08\xc8Xg\ \x00s\ \x00a\x00v\x00e\x00.\x00p\x00n\x00g\ \x00\x0f\ \x0a'\xe0\xe7\ \x00b\ \x00o\x00o\x00k\x00m\x00a\x00r\x00k\x00_\x00o\x00n\x00.\x00p\x00n\x00g\ \x00\x09\ \x08k\x8aG\ \x00g\ \x00r\x00a\x00p\x00h\x00.\x00p\x00n\x00g\ \x00\x15\ \x048_\x07\ \x00a\ \x00r\x00r\x00o\x00w\x00_\x00n\x00e\x00x\x00t\x00_\x00h\x00i\x00g\x00h\x00e\x00r\ \x00.\x00p\x00n\x00g\ \x00\x08\ \x06\xe1Z'\ \x00d\ \x00o\x00w\x00n\x00.\x00p\x00n\x00g\ \x00\x09\ \x0a\xc6\x8d\xe7\ \x00f\ \x00o\x00c\x00u\x00s\x00.\x00p\x00n\x00g\ \x00\x0a\ \x0bi\x97\xc7\ \x00w\ \x00i\x00n\x00d\x00o\x00w\x00.\x00p\x00n\x00g\ \x00\x0b\ \x03xg\xc7\ \x00a\ \x00s\x00a\x00m\x00m\x00d\x00f\x00.\x00p\x00n\x00g\ \x00\x0b\ \x06\xb0\xb6g\ \x00a\ \x00x\x00i\x00s\x00_\x00o\x00n\x00.\x00p\x00n\x00g\ \x00\x09\ \x03\xa4\x82\xc7\ \x00d\ \x00e\x00l\x00t\x00a\x00.\x00p\x00n\x00g\ \x00\x0c\ \x0b9#\xa7\ \x00d\ \x00e\x00l\x00t\x00a\x00_\x00o\x00n\x00.\x00p\x00n\x00g\ \x00\x0c\ \x06\xeb\x97\xe7\ \x00z\ \x00o\x00o\x00m\x00-\x00o\x00u\x00t\x00.\x00p\x00n\x00g\ \x00\x08\ \x04\xd2YG\ \x00i\ \x00n\x00f\x00o\x00.\x00p\x00n\x00g\ \x00\x0b\ \x09\xd2\xc5\xe7\ \x00b\ \x00u\x00s\x00_\x00c\x00a\x00n\x00.\x00p\x00n\x00g\ \x00\x09\ \x04\xd8\xa6G\ \x00r\ \x00a\x00n\x00g\x00e\x00.\x00p\x00n\x00g\ \x00\x0b\ \x0cF\xc5\x87\ \x00b\ \x00u\x00s\x00_\x00u\x00s\x00b\x00.\x00p\x00n\x00g\ \x00\x0b\ \x02R\xc5\x87\ \x00b\ \x00u\x00s\x00_\x00l\x00i\x00n\x00.\x00p\x00n\x00g\ \x00\x09\ \x09e\x8eg\ \x00e\ \x00r\x00r\x00o\x00r\x00.\x00p\x00n\x00g\ \x00\x0c\ \x08Ag\xc7\ \x00r\ \x00e\x00s\x00a\x00m\x00p\x00l\x00e\x00.\x00p\x00n\x00g\ \x00\x0d\ \x01\xe6N'\ \x00n\ \x00u\x00m\x00b\x00e\x00r\x00_\x00o\x00n\x00.\x00p\x00n\x00g\ \x00\x0e\ \x02C\xfb\xe7\ \x00l\ \x00o\x00a\x00d\x00_\x00e\x00m\x00b\x00e\x00d\x00.\x00p\x00n\x00g\ \x00\x09\ \x0au\xb1G\ \x00l\ \x00i\x00s\x00t\x002\x00.\x00p\x00n\x00g\ \x00\x09\ \x08\x98\x8eG\ \x00e\ \x00r\x00a\x00s\x00e\x00.\x00p\x00n\x00g\ \x00\x11\ \x04\x83z\xc7\ \x00i\ \x00n\x00c\x00r\x00e\x00a\x00s\x00e\x00-\x00f\x00o\x00n\x00t\x00.\x00p\x00n\x00g\ \ \x00\x09\ \x05\xc6\xbfG\ \x00m\ \x00i\x00n\x00u\x00s\x00.\x00p\x00n\x00g\ \x00\x08\ \x04\xb2X\xc7\ \x00u\ \x00n\x00d\x00o\x00.\x00p\x00n\x00g\ \x00\x08\ \x06|Z\x07\ \x00c\ \x00o\x00p\x00y\x00.\x00p\x00n\x00g\ \x00\x08\ \x08\xf7Z\x87\ \x00g\ \x00r\x00i\x00d\x00.\x00p\x00n\x00g\ \x00\x18\ \x0d\xf8\x14G\ \x00a\ \x00r\x00r\x00o\x00w\x00_\x00p\x00r\x00e\x00v\x00i\x00o\x00u\x00s\x00_\x00l\x00o\ \x00w\x00e\x00r\x00.\x00p\x00n\x00g\ \x00\x0e\ \x0bZ\x02G\ \x00s\ \x00h\x00i\x00f\x00t\x00_\x00d\x00o\x00w\x00n\x00.\x00p\x00n\x00g\ \x00\x08\ \x068Z\xa7\ \x00h\ \x00o\x00m\x00e\x00.\x00p\x00n\x00g\ \x00\x07\ \x0a\xc7W\x87\ \x00c\ \x00u\x00t\x00.\x00p\x00n\x00g\ " qt_resource_struct = b"\ \x00\x00\x00\x00\x00\x02\x00\x00\x00U\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x03F\x00\x00\x00\x00\x00\x01\x00\x01\x02\xbe\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x06\x1a\x00\x00\x00\x00\x00\x01\x00\x01\xb21\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x02\xe4\x00\x00\x00\x00\x00\x01\x00\x00\xdd\xb4\ \x00\x00\x01\x92\xf6\x07+\xf2\ \x00\x00\x030\x00\x00\x00\x00\x00\x01\x00\x00\xff\xf3\ \x00\x00\x01\x92\xf6\x07+\xf2\ \x00\x00\x05\xba\x00\x00\x00\x00\x00\x01\x00\x01\xa3:\ \x00\x00\x01\x92\xf6\x07,\x0e\ \x00\x00\x00 \x00\x00\x00\x00\x00\x01\x00\x00\x05R\ \x00\x00\x01\x92\xf6\x07+\xf6\ \x00\x00\x08@\x00\x00\x00\x00\x00\x01\x00\x03\x15D\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x01\x94\x00\x00\x00\x00\x00\x01\x00\x00B\xac\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x08`\x00\x00\x00\x00\x00\x01\x00\x03\x19\xb9\ \x00\x00\x01\x92\xf6\x07+\xf6\ \x00\x00\x07\xee\x00\x00\x00\x00\x00\x01\x00\x03\x0a\xba\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00&\x07\ \x00\x00\x01\x95\x93\xcf\xa3\xa3\ \x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00L\xd7\ \x00\x00\x01\x92\xf6\x07,\x16\ \x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x01\xd8\xbe\ \x00\x00\x01\x92\xf6\x07+\xc5\ \x00\x00\x074\x00\x00\x00\x00\x00\x01\x00\x02\xe1/\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x01d\x00\x00\x00\x00\x00\x01\x00\x008\xf3\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x04J\x00\x00\x00\x00\x00\x01\x00\x01K:\ \x00\x00\x01\x92\xf6\x07,\x0e\ \x00\x00\x03\xd8\x00\x00\x00\x00\x00\x01\x00\x01\x1c\xba\ \x00\x00\x01\x92\xf6\x07+\xf1\ \x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x01\xc7\xb9\ \x00\x00\x01\x95\x93\xcf\x9a\xc2\ \x00\x00\x08\xb2\x00\x00\x00\x00\x00\x01\x00\x03,m\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x08\xf2\x00\x00\x00\x00\x00\x01\x00\x031\xfc\ \x00\x00\x01\x92\xf6\x07,\x0e\ \x00\x00\x07\x88\x00\x00\x00\x00\x00\x01\x00\x02\xee\x7f\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x07\xba\x00\x00\x00\x00\x00\x01\x00\x02\xfdT\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x02L\x00\x00\x00\x00\x00\x01\x00\x00z\xe9\ \x00\x00\x01\x92\xf6\x07+\xd4\ \x00\x00\x01.\x00\x00\x00\x00\x00\x01\x00\x00(\xe3\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00[\x00\ \x00\x00\x01\x92\xf6\x07+\xd3\ \x00\x00\x00:\x00\x00\x00\x00\x00\x01\x00\x00\x09`\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x08\xda\x00\x00\x00\x00\x00\x01\x00\x031<\ \x00\x00\x01\x92\xf6\x07+\xfa\ \x00\x00\x01F\x00\x00\x00\x00\x00\x01\x00\x002\x99\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x04\x08\x00\x00\x00\x00\x00\x01\x00\x01?\xb4\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x09\x8c\x00\x00\x00\x00\x00\x01\x00\x03I\xe7\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x09\x08\x00\x00\x00\x00\x00\x01\x00\x036\x8c\ \x00\x00\x01\x92\xf6\x07+\xd4\ \x00\x00\x022\x00\x00\x00\x00\x00\x01\x00\x00d\xf9\ \x00\x00\x01\x92\xf6\x07+\xf6\ \x00\x00\x02\x18\x00\x00\x00\x00\x00\x01\x00\x00b\xc0\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x02\xda\x14\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x01\xb8\x00\x00\x00\x00\x00\x01\x00\x00H\x9f\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x06\xb4\x00\x00\x00\x00\x00\x01\x00\x01\xca\xa2\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x07j\x00\x00\x00\x00\x00\x01\x00\x02\xe7\xc1\ \x00\x00\x01\x92\xf6\x07,\x18\ \x00\x00\x01z\x00\x00\x00\x00\x00\x01\x00\x00:Z\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x05\xa2\x00\x00\x00\x00\x00\x01\x00\x01\x9c\xa8\ \x00\x00\x01\x92\xf6\x07,\x0e\ \x00\x00\x00\xac\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x08\ \x00\x00\x01\x92\xf6\x07+\xc5\ \x00\x00\x03\xc6\x00\x00\x00\x00\x00\x01\x00\x01\x18\xf8\ \x00\x00\x01\x92\xf6\x07,\x15\ \x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\x16\xb1\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x08\x22\x00\x00\x00\x00\x00\x01\x00\x03\x13\xa4\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x04\xf0\x00\x00\x00\x00\x00\x01\x00\x01\x7fo\ \x00\x00\x01\x92\xf6\x07+\xd4\ \x00\x00\x06l\x00\x00\x00\x00\x00\x01\x00\x01\xc1\x01\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x06\x00\x00\x00\x00\x00\x00\x01\x00\x01\xac\x06\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x08\x9a\x00\x00\x00\x00\x00\x01\x00\x03'<\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x062\x00\x00\x00\x00\x00\x01\x00\x01\xb9\xe8\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x05\xe6\x00\x00\x00\x00\x00\x01\x00\x01\xa7\x90\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x09\x1e\x00\x00\x00\x00\x00\x01\x00\x03=(\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x00r\x00\x00\x00\x00\x00\x01\x00\x00\x12N\ \x00\x00\x01\x92\xf6\x07+\xd4\ \x00\x00\x08\x0a\x00\x00\x00\x00\x00\x01\x00\x03\x0e0\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x07\x9e\x00\x00\x00\x00\x00\x01\x00\x02\xf6\x06\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x04*\x00\x00\x00\x00\x00\x01\x00\x01E\x96\ \x00\x00\x01\x92\xf6\x07,\x0e\ \x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x01\x052\ \x00\x00\x01\x92\xf6\x07,\x0e\ \x00\x00\x06H\x00\x00\x00\x00\x00\x01\x00\x01\xbdn\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x04t\x00\x00\x00\x00\x00\x01\x00\x01O\x86\ \x00\x00\x01\x92\xf6\x07+\xd4\ \x00\x00\x08\x82\x00\x00\x00\x00\x00\x01\x00\x03\x1d\xf2\ \x00\x00\x01\x92\xf6\x07+\xf5\ \x00\x00\x05\x22\x00\x00\x00\x00\x00\x01\x00\x01\x88\xac\ \x00\x00\x01\x92\xf6\x07+\xd4\ \x00\x00\x06\xca\x00\x00\x00\x00\x00\x01\x00\x01\xce\x93\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x09\xa2\x00\x00\x00\x00\x00\x01\x00\x03N\xa6\ \x00\x00\x01\x92\xf6\x07+\xd4\ \x00\x00\x00X\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xf0\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x03\x92\x00\x00\x00\x00\x00\x01\x00\x01\x0d\x9b\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x07L\x00\x00\x00\x00\x00\x01\x00\x02\xe4{\ \x00\x00\x01\x92\xf6\x07+\xdc\ \x00\x00\x09j\x00\x00\x00\x00\x00\x01\x00\x03C\xd2\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x01\x92\xf6\x07+\xd2\ \x00\x00\x06\xe2\x00\x00\x00\x00\x00\x01\x00\x01\xd5\x1c\ \x00\x00\x01\x92\xf6\x07,\x16\ \x00\x00\x04\x8e\x00\x00\x00\x00\x00\x01\x00\x01U\xe6\ \x00\x00\x01\x92\xf6\x07+\xfb\ \x00\x00\x05\x0c\x00\x00\x00\x00\x00\x01\x00\x01\x86\x91\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x02\x88\x00\x00\x00\x00\x00\x01\x00\x00\x84\x85\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x03\xa8\x00\x00\x00\x00\x00\x01\x00\x01\x11\x86\ \x00\x00\x01\x92\xf6\x07+\xe7\ \x00\x00\x05\x86\x00\x00\x00\x00\x00\x01\x00\x01\x96\xb1\ \x00\x00\x01\x92\xf6\x07+\xd4\ \x00\x00\x07\xd2\x00\x00\x00\x00\x00\x01\x00\x03\x02\xfc\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x04\xa4\x00\x00\x00\x00\x00\x01\x00\x01Z\x9f\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x02\xc8\x00\x00\x00\x00\x00\x01\x00\x00\xdb`\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x02t\x00\x00\x00\x00\x00\x01\x00\x00\x7f(\ \x00\x00\x01\x92\xf6\x07+\xe6\ \x00\x00\x05N\x00\x00\x00\x00\x00\x01\x00\x01\x93\xe0\ \x00\x00\x01\x95\x93\xcf\x9f\x0f\ \x00\x00\x056\x00\x00\x00\x00\x00\x01\x00\x01\x90\x04\ \x00\x00\x01\x92\xf6\x07+\xf0\ \x00\x00\x03\x14\x00\x00\x00\x00\x00\x01\x00\x00\xfb1\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x03z\x00\x00\x00\x00\x00\x01\x00\x01\x0b`\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x094\x00\x00\x00\x00\x00\x01\x00\x03@\xca\ \x00\x00\x01\x95\x93\xcf\x95\xdd\ \x00\x00\x00\xe2\x00\x00\x00\x00\x00\x01\x00\x00!\xe2\ \x00\x00\x01\x92\xf6\x07,\x14\ \x00\x00\x01\xea\x00\x00\x00\x00\x00\x01\x00\x00S\xe6\ \x00\x00\x01\x92\xf6\x07+\xc8\ \x00\x00\x04\xd6\x00\x00\x00\x00\x00\x01\x00\x01{\x8a\ \x00\x00\x01\x92\xf6\x07,\x04\ \x00\x00\x02\xa6\x00\x00\x00\x00\x00\x01\x00\x00\xd7\x08\ \x00\x00\x01\x92\xf6\x07+\xf6\ " def qInitResources(): QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) def qCleanupResources(): QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) qInitResources() asammdf-8.5.1/src/asammdf/gui/ui/search_dialog.py000066400000000000000000000511311502633300400216700ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'search_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QAbstractItemView, QApplication, QCheckBox, QComboBox, QDialog, QDoubleSpinBox, QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QPushButton, QSizePolicy, QSpacerItem, QTabWidget, QTreeWidget, QTreeWidgetItem, QWidget) from asammdf.gui.dialogs.advanced_search_helpers import SearchTreeWidget from . import resource_rc class Ui_SearchDialog(object): def setupUi(self, SearchDialog): if not SearchDialog.objectName(): SearchDialog.setObjectName(u"SearchDialog") SearchDialog.resize(829, 679) SearchDialog.setSizeGripEnabled(True) self.gridLayout_2 = QGridLayout(SearchDialog) self.gridLayout_2.setSpacing(1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(1, 1, 1, 1) self.tabs = QTabWidget(SearchDialog) self.tabs.setObjectName(u"tabs") self.tab = QWidget() self.tab.setObjectName(u"tab") self.gridLayout = QGridLayout(self.tab) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.search_box = QLineEdit(self.tab) self.search_box.setObjectName(u"search_box") self.search_box.setClearButtonEnabled(True) self.gridLayout.addWidget(self.search_box, 0, 0, 1, 1) self.status = QLabel(self.tab) self.status.setObjectName(u"status") self.status.setMinimumSize(QSize(100, 0)) self.gridLayout.addWidget(self.status, 0, 1, 1, 1) self.match_kind = QComboBox(self.tab) self.match_kind.addItem("") self.match_kind.addItem("") self.match_kind.setObjectName(u"match_kind") self.gridLayout.addWidget(self.match_kind, 0, 2, 1, 1) self.case_sensitivity = QComboBox(self.tab) self.case_sensitivity.addItem("") self.case_sensitivity.addItem("") self.case_sensitivity.setObjectName(u"case_sensitivity") self.gridLayout.addWidget(self.case_sensitivity, 0, 3, 1, 1) self.extended_search = QCheckBox(self.tab) self.extended_search.setObjectName(u"extended_search") self.gridLayout.addWidget(self.extended_search, 0, 4, 1, 1) self.label_7 = QLabel(self.tab) self.label_7.setObjectName(u"label_7") self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1) self.matches = SearchTreeWidget(self.tab) self.matches.setObjectName(u"matches") self.matches.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.matches.setUniformRowHeights(False) self.matches.setSortingEnabled(False) self.matches.header().setMinimumSectionSize(40) self.matches.header().setStretchLastSection(True) self.gridLayout.addWidget(self.matches, 2, 0, 1, 5) self.label = QLabel(self.tab) self.label.setObjectName(u"label") self.gridLayout.addWidget(self.label, 4, 0, 1, 1) self.selection = SearchTreeWidget(self.tab) self.selection.setObjectName(u"selection") self.selection.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.selection.setSortingEnabled(False) self.selection.header().setMinimumSectionSize(25) self.selection.header().setProperty(u"showSortIndicator", False) self.gridLayout.addWidget(self.selection, 5, 0, 1, 5) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.horizontalSpacer_4 = QSpacerItem(20, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_2.addItem(self.horizontalSpacer_4) self.add_btn = QPushButton(self.tab) self.add_btn.setObjectName(u"add_btn") self.add_btn.setFocusPolicy(Qt.FocusPolicy.NoFocus) icon = QIcon() icon.addFile(u":/shift_down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.add_btn.setIcon(icon) self.add_btn.setAutoDefault(False) self.horizontalLayout_2.addWidget(self.add_btn) self.horizontalSpacer_5 = QSpacerItem(20, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_2.addItem(self.horizontalSpacer_5) self.show_alias_btn = QPushButton(self.tab) self.show_alias_btn.setObjectName(u"show_alias_btn") icon1 = QIcon() icon1.addFile(u":/info.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.show_alias_btn.setIcon(icon1) self.show_alias_btn.setAutoDefault(False) self.horizontalLayout_2.addWidget(self.show_alias_btn) self.gridLayout.addLayout(self.horizontalLayout_2, 3, 0, 1, 5) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.cancel_btn = QPushButton(self.tab) self.cancel_btn.setObjectName(u"cancel_btn") icon2 = QIcon() icon2.addFile(u":/erase.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.cancel_btn.setIcon(icon2) self.cancel_btn.setAutoDefault(False) self.horizontalLayout.addWidget(self.cancel_btn) self.horizontalSpacer_2 = QSpacerItem(20, 16, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer_2) self.apply_btn = QPushButton(self.tab) self.apply_btn.setObjectName(u"apply_btn") icon3 = QIcon() icon3.addFile(u":/checkmark.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.apply_btn.setIcon(icon3) self.apply_btn.setAutoDefault(False) self.horizontalLayout.addWidget(self.apply_btn) self.horizontalSpacer = QSpacerItem(10, 16, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer) self.add_window_btn = QPushButton(self.tab) self.add_window_btn.setObjectName(u"add_window_btn") icon4 = QIcon() icon4.addFile(u":/plus.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.add_window_btn.setIcon(icon4) self.add_window_btn.setAutoDefault(False) self.horizontalLayout.addWidget(self.add_window_btn) self.horizontalLayout.setStretch(1, 1) self.gridLayout.addLayout(self.horizontalLayout, 6, 0, 1, 5) self.gridLayout.setRowStretch(2, 1) self.gridLayout.setRowStretch(5, 1) icon5 = QIcon() icon5.addFile(u":/search.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.tabs.addTab(self.tab, icon5, "") self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") self.gridLayout_3 = QGridLayout(self.tab_2) self.gridLayout_3.setSpacing(1) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.filter_type = QComboBox(self.tab_2) self.filter_type.addItem("") self.filter_type.addItem("") self.filter_type.addItem("") self.filter_type.addItem("") self.filter_type.setObjectName(u"filter_type") self.gridLayout_3.addWidget(self.filter_type, 4, 2, 1, 1) self.name = QLineEdit(self.tab_2) self.name.setObjectName(u"name") self.gridLayout_3.addWidget(self.name, 0, 2, 1, 1) self.label_9 = QLabel(self.tab_2) self.label_9.setObjectName(u"label_9") self.gridLayout_3.addWidget(self.label_9, 8, 1, 1, 1) self.case_sensitivity_pattern = QComboBox(self.tab_2) self.case_sensitivity_pattern.addItem("") self.case_sensitivity_pattern.addItem("") self.case_sensitivity_pattern.setObjectName(u"case_sensitivity_pattern") self.gridLayout_3.addWidget(self.case_sensitivity_pattern, 3, 2, 1, 1) self.verticalSpacer = QSpacerItem(20, 254, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_3.addItem(self.verticalSpacer, 10, 1, 1, 1) self.label_4 = QLabel(self.tab_2) self.label_4.setObjectName(u"label_4") self.gridLayout_3.addWidget(self.label_4, 5, 1, 1, 1) self.label_8 = QLabel(self.tab_2) self.label_8.setObjectName(u"label_8") self.gridLayout_3.addWidget(self.label_8, 9, 1, 1, 1) self.filter_value = QDoubleSpinBox(self.tab_2) self.filter_value.setObjectName(u"filter_value") self.filter_value.setDecimals(6) self.filter_value.setMinimum(-9999999999999999635896294965248.000000000000000) self.filter_value.setMaximum(999999999999999983222784.000000000000000) self.gridLayout_3.addWidget(self.filter_value, 5, 2, 1, 1) self.label_3 = QLabel(self.tab_2) self.label_3.setObjectName(u"label_3") self.gridLayout_3.addWidget(self.label_3, 4, 1, 1, 1) self.label_5 = QLabel(self.tab_2) self.label_5.setObjectName(u"label_5") self.gridLayout_3.addWidget(self.label_5, 2, 1, 1, 1) self.label_6 = QLabel(self.tab_2) self.label_6.setObjectName(u"label_6") self.gridLayout_3.addWidget(self.label_6, 0, 1, 1, 1) self.define_ranges_btn = QPushButton(self.tab_2) self.define_ranges_btn.setObjectName(u"define_ranges_btn") icon6 = QIcon() icon6.addFile(u":/range.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.define_ranges_btn.setIcon(icon6) self.define_ranges_btn.setAutoDefault(False) self.gridLayout_3.addWidget(self.define_ranges_btn, 7, 2, 1, 1) self.pattern_match_type = QComboBox(self.tab_2) self.pattern_match_type.addItem("") self.pattern_match_type.addItem("") self.pattern_match_type.setObjectName(u"pattern_match_type") self.gridLayout_3.addWidget(self.pattern_match_type, 2, 2, 1, 1) self.raw = QCheckBox(self.tab_2) self.raw.setObjectName(u"raw") self.gridLayout_3.addWidget(self.raw, 6, 2, 1, 1) self.pattern_matches = QTreeWidget(self.tab_2) self.pattern_matches.setObjectName(u"pattern_matches") self.pattern_matches.setSortingEnabled(True) self.gridLayout_3.addWidget(self.pattern_matches, 0, 3, 11, 3) self.integer_format = QComboBox(self.tab_2) self.integer_format.addItem("") self.integer_format.addItem("") self.integer_format.addItem("") self.integer_format.addItem("") self.integer_format.setObjectName(u"integer_format") self.gridLayout_3.addWidget(self.integer_format, 8, 2, 1, 1) self.pattern = QLineEdit(self.tab_2) self.pattern.setObjectName(u"pattern") self.pattern.setMinimumSize(QSize(300, 0)) self.gridLayout_3.addWidget(self.pattern, 1, 2, 1, 1) self.horizontalSpacer_3 = QSpacerItem(282, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_3.addItem(self.horizontalSpacer_3, 11, 4, 1, 1) self.label_2 = QLabel(self.tab_2) self.label_2.setObjectName(u"label_2") self.gridLayout_3.addWidget(self.label_2, 1, 1, 1, 1) self.apply_pattern_btn = QPushButton(self.tab_2) self.apply_pattern_btn.setObjectName(u"apply_pattern_btn") self.apply_pattern_btn.setIcon(icon3) self.apply_pattern_btn.setAutoDefault(False) self.gridLayout_3.addWidget(self.apply_pattern_btn, 11, 5, 1, 1) self.cancel_pattern_btn = QPushButton(self.tab_2) self.cancel_pattern_btn.setObjectName(u"cancel_pattern_btn") self.cancel_pattern_btn.setIcon(icon2) self.cancel_pattern_btn.setAutoDefault(False) self.gridLayout_3.addWidget(self.cancel_pattern_btn, 11, 1, 1, 1) self.horizontalLayout_3 = QHBoxLayout() self.horizontalLayout_3.setSpacing(1) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.y_range_min = QDoubleSpinBox(self.tab_2) self.y_range_min.setObjectName(u"y_range_min") self.y_range_min.setDecimals(6) self.horizontalLayout_3.addWidget(self.y_range_min) self.y_range_max = QDoubleSpinBox(self.tab_2) self.y_range_max.setObjectName(u"y_range_max") self.y_range_max.setDecimals(6) self.horizontalLayout_3.addWidget(self.y_range_max) self.gridLayout_3.addLayout(self.horizontalLayout_3, 9, 2, 1, 1) self.gridLayout_3.setRowStretch(10, 1) self.gridLayout_3.setColumnStretch(3, 1) self.tabs.addTab(self.tab_2, "") self.gridLayout_2.addWidget(self.tabs, 0, 0, 1, 1) QWidget.setTabOrder(self.search_box, self.match_kind) QWidget.setTabOrder(self.match_kind, self.case_sensitivity) QWidget.setTabOrder(self.case_sensitivity, self.extended_search) QWidget.setTabOrder(self.extended_search, self.matches) QWidget.setTabOrder(self.matches, self.add_btn) QWidget.setTabOrder(self.add_btn, self.selection) QWidget.setTabOrder(self.selection, self.add_window_btn) QWidget.setTabOrder(self.add_window_btn, self.apply_btn) QWidget.setTabOrder(self.apply_btn, self.cancel_btn) QWidget.setTabOrder(self.cancel_btn, self.name) QWidget.setTabOrder(self.name, self.pattern) QWidget.setTabOrder(self.pattern, self.pattern_match_type) QWidget.setTabOrder(self.pattern_match_type, self.case_sensitivity_pattern) QWidget.setTabOrder(self.case_sensitivity_pattern, self.filter_type) QWidget.setTabOrder(self.filter_type, self.filter_value) QWidget.setTabOrder(self.filter_value, self.raw) QWidget.setTabOrder(self.raw, self.define_ranges_btn) QWidget.setTabOrder(self.define_ranges_btn, self.integer_format) QWidget.setTabOrder(self.integer_format, self.apply_pattern_btn) QWidget.setTabOrder(self.apply_pattern_btn, self.cancel_pattern_btn) self.retranslateUi(SearchDialog) self.tabs.setCurrentIndex(0) self.match_kind.setCurrentIndex(0) QMetaObject.connectSlotsByName(SearchDialog) # setupUi def retranslateUi(self, SearchDialog): SearchDialog.setWindowTitle(QCoreApplication.translate("SearchDialog", u"Dialog", None)) self.search_box.setPlaceholderText(QCoreApplication.translate("SearchDialog", u"channel name pattern", None)) self.status.setText(QCoreApplication.translate("SearchDialog", u"No results", None)) self.match_kind.setItemText(0, QCoreApplication.translate("SearchDialog", u"Wildcard", None)) self.match_kind.setItemText(1, QCoreApplication.translate("SearchDialog", u"Regex", None)) self.case_sensitivity.setItemText(0, QCoreApplication.translate("SearchDialog", u"Case insensitive", None)) self.case_sensitivity.setItemText(1, QCoreApplication.translate("SearchDialog", u"Case sensitive", None)) self.extended_search.setText(QCoreApplication.translate("SearchDialog", u"Extended search", None)) self.label_7.setText(QCoreApplication.translate("SearchDialog", u"Search results", None)) ___qtreewidgetitem = self.matches.headerItem() ___qtreewidgetitem.setText(6, QCoreApplication.translate("SearchDialog", u"Comment", None)); ___qtreewidgetitem.setText(5, QCoreApplication.translate("SearchDialog", u"Source path", None)); ___qtreewidgetitem.setText(4, QCoreApplication.translate("SearchDialog", u"Source name", None)); ___qtreewidgetitem.setText(3, QCoreApplication.translate("SearchDialog", u"Unit", None)); ___qtreewidgetitem.setText(2, QCoreApplication.translate("SearchDialog", u"Index", None)); ___qtreewidgetitem.setText(1, QCoreApplication.translate("SearchDialog", u"Group", None)); ___qtreewidgetitem.setText(0, QCoreApplication.translate("SearchDialog", u"Name", None)); self.label.setText(QCoreApplication.translate("SearchDialog", u"Final selection", None)) ___qtreewidgetitem1 = self.selection.headerItem() ___qtreewidgetitem1.setText(6, QCoreApplication.translate("SearchDialog", u"Comment", None)); ___qtreewidgetitem1.setText(5, QCoreApplication.translate("SearchDialog", u"Source path", None)); ___qtreewidgetitem1.setText(4, QCoreApplication.translate("SearchDialog", u"Source name", None)); ___qtreewidgetitem1.setText(3, QCoreApplication.translate("SearchDialog", u"Unit", None)); ___qtreewidgetitem1.setText(2, QCoreApplication.translate("SearchDialog", u"Index", None)); ___qtreewidgetitem1.setText(1, QCoreApplication.translate("SearchDialog", u"Group", None)); ___qtreewidgetitem1.setText(0, QCoreApplication.translate("SearchDialog", u"Name", None)); self.add_btn.setText(QCoreApplication.translate("SearchDialog", u"Add to selection", None)) self.show_alias_btn.setText(QCoreApplication.translate("SearchDialog", u"Show overlapping alias", None)) self.cancel_btn.setText(QCoreApplication.translate("SearchDialog", u"Cancel", None)) self.apply_btn.setText(QCoreApplication.translate("SearchDialog", u"Apply", None)) self.add_window_btn.setText(QCoreApplication.translate("SearchDialog", u"Add window", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab), QCoreApplication.translate("SearchDialog", u"Search", None)) self.filter_type.setItemText(0, QCoreApplication.translate("SearchDialog", u"Unspecified", None)) self.filter_type.setItemText(1, QCoreApplication.translate("SearchDialog", u"Contains", None)) self.filter_type.setItemText(2, QCoreApplication.translate("SearchDialog", u"Do not contain", None)) self.filter_type.setItemText(3, QCoreApplication.translate("SearchDialog", u"Constant", None)) self.label_9.setText(QCoreApplication.translate("SearchDialog", u"Integer format", None)) self.case_sensitivity_pattern.setItemText(0, QCoreApplication.translate("SearchDialog", u"Case insensitive", None)) self.case_sensitivity_pattern.setItemText(1, QCoreApplication.translate("SearchDialog", u"Case sensitive", None)) self.label_4.setText(QCoreApplication.translate("SearchDialog", u"Filter value", None)) self.label_8.setText(QCoreApplication.translate("SearchDialog", u"Y range", None)) self.label_3.setText(QCoreApplication.translate("SearchDialog", u"Filter type", None)) self.label_5.setText(QCoreApplication.translate("SearchDialog", u"Match type", None)) self.label_6.setText(QCoreApplication.translate("SearchDialog", u"Name", None)) self.define_ranges_btn.setText(QCoreApplication.translate("SearchDialog", u"Define ranges", None)) self.pattern_match_type.setItemText(0, QCoreApplication.translate("SearchDialog", u"Wildcard", None)) self.pattern_match_type.setItemText(1, QCoreApplication.translate("SearchDialog", u"Regex", None)) self.raw.setText(QCoreApplication.translate("SearchDialog", u"Use the raw channel values", None)) ___qtreewidgetitem2 = self.pattern_matches.headerItem() ___qtreewidgetitem2.setText(0, QCoreApplication.translate("SearchDialog", u"Channels matching the pattern conditions", None)); self.integer_format.setItemText(0, QCoreApplication.translate("SearchDialog", u"phys", None)) self.integer_format.setItemText(1, QCoreApplication.translate("SearchDialog", u"bin", None)) self.integer_format.setItemText(2, QCoreApplication.translate("SearchDialog", u"hex", None)) self.integer_format.setItemText(3, QCoreApplication.translate("SearchDialog", u"ascii", None)) self.pattern.setPlaceholderText(QCoreApplication.translate("SearchDialog", u"channel name pattern", None)) self.label_2.setText(QCoreApplication.translate("SearchDialog", u"Pattern", None)) self.apply_pattern_btn.setText(QCoreApplication.translate("SearchDialog", u"Apply", None)) self.cancel_pattern_btn.setText(QCoreApplication.translate("SearchDialog", u"Cancel", None)) self.tabs.setTabText(self.tabs.indexOf(self.tab_2), QCoreApplication.translate("SearchDialog", u"Pattern definition", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/search_dialog.ui000066400000000000000000000511401502633300400216550ustar00rootroot00000000000000 SearchDialog 0 0 829 679 Dialog true 1 1 1 1 1 0 :/search.png:/search.png Search 1 1 1 1 1 channel name pattern true 100 0 No results 0 Wildcard Regex Case insensitive Case sensitive Extended search Search results QAbstractItemView::SelectionMode::ExtendedSelection false false 40 true Name Group Index Unit Source name Source path Comment Final selection QAbstractItemView::SelectionMode::ExtendedSelection false 25 false Name Group Index Unit Source name Source path Comment 1 Qt::Orientation::Horizontal 20 20 Qt::FocusPolicy::NoFocus Add to selection :/shift_down.png:/shift_down.png false Qt::Orientation::Horizontal 20 20 Show overlapping alias :/info.png:/info.png false 1 Cancel :/erase.png:/erase.png false Qt::Orientation::Horizontal 20 16 Apply :/checkmark.png:/checkmark.png false Qt::Orientation::Horizontal 10 16 Add window :/plus.png:/plus.png false Pattern definition 1 1 1 1 1 Unspecified Contains Do not contain Constant Integer format Case insensitive Case sensitive Qt::Orientation::Vertical 20 254 Filter value Y range 6 -9999999999999999635896294965248.000000000000000 999999999999999983222784.000000000000000 Filter type Match type Name Define ranges :/range.png:/range.png false Wildcard Regex Use the raw channel values true Channels matching the pattern conditions phys bin hex ascii 300 0 channel name pattern Qt::Orientation::Vertical 282 20 Pattern Apply :/checkmark.png:/checkmark.png false Cancel :/erase.png:/erase.png false 1 6 6 SearchTreeWidget QTreeWidget
asammdf.gui.dialogs.advanced_search_helpers.h
search_box match_kind case_sensitivity extended_search matches add_btn selection add_window_btn apply_btn cancel_btn name pattern pattern_match_type case_sensitivity_pattern filter_type filter_value raw define_ranges_btn integer_format apply_pattern_btn cancel_pattern_btn
asammdf-8.5.1/src/asammdf/gui/ui/signal_scale.py000066400000000000000000000351521502633300400215350ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'signal_scale.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QDialog, QDoubleSpinBox, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QPushButton, QSizePolicy, QSpacerItem, QWidget) from . import resource_rc class Ui_ScaleDialog(object): def setupUi(self, ScaleDialog): if not ScaleDialog.objectName(): ScaleDialog.setObjectName(u"ScaleDialog") ScaleDialog.resize(1091, 678) self.gridLayout_3 = QGridLayout(ScaleDialog) self.gridLayout_3.setSpacing(1) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalSpacer_6 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer_6) self.cancel_btn = QPushButton(ScaleDialog) self.cancel_btn.setObjectName(u"cancel_btn") icon = QIcon() icon.addFile(u":/erase.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.cancel_btn.setIcon(icon) self.horizontalLayout.addWidget(self.cancel_btn) self.horizontalSpacer_7 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer_7) self.apply_btn = QPushButton(ScaleDialog) self.apply_btn.setObjectName(u"apply_btn") icon1 = QIcon() icon1.addFile(u":/checkmark.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.apply_btn.setIcon(icon1) self.horizontalLayout.addWidget(self.apply_btn) self.horizontalLayout.setStretch(0, 1) self.gridLayout_3.addLayout(self.horizontalLayout, 5, 0, 1, 2) self.verticalSpacer = QSpacerItem(20, 135, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout_3.addItem(self.verticalSpacer, 4, 1, 1, 1) self.groupBox_2 = QGroupBox(ScaleDialog) self.groupBox_2.setObjectName(u"groupBox_2") self.gridLayout = QGridLayout(self.groupBox_2) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.fit_btn = QPushButton(self.groupBox_2) self.fit_btn.setObjectName(u"fit_btn") icon2 = QIcon() icon2.addFile(u":/fit.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.fit_btn.setIcon(icon2) self.gridLayout.addWidget(self.fit_btn, 2, 0, 1, 1) self.label_3 = QLabel(self.groupBox_2) self.label_3.setObjectName(u"label_3") self.label_3.setAlignment(Qt.AlignmentFlag.AlignRight|Qt.AlignmentFlag.AlignTrailing|Qt.AlignmentFlag.AlignVCenter) self.gridLayout.addWidget(self.label_3, 2, 1, 1, 1) self.zoom_out_btn = QPushButton(self.groupBox_2) self.zoom_out_btn.setObjectName(u"zoom_out_btn") icon3 = QIcon() icon3.addFile(u":/zoom-out.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.zoom_out_btn.setIcon(icon3) self.gridLayout.addWidget(self.zoom_out_btn, 1, 0, 1, 1) self.label = QLabel(self.groupBox_2) self.label.setObjectName(u"label") self.label.setAlignment(Qt.AlignmentFlag.AlignRight|Qt.AlignmentFlag.AlignTrailing|Qt.AlignmentFlag.AlignVCenter) self.gridLayout.addWidget(self.label, 1, 1, 1, 1) self.fast_shift_up_btn = QPushButton(self.groupBox_2) self.fast_shift_up_btn.setObjectName(u"fast_shift_up_btn") icon4 = QIcon() icon4.addFile(u":/shift_up.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.fast_shift_up_btn.setIcon(icon4) self.gridLayout.addWidget(self.fast_shift_up_btn, 5, 0, 1, 1) self.label_2 = QLabel(self.groupBox_2) self.label_2.setObjectName(u"label_2") self.label_2.setAlignment(Qt.AlignmentFlag.AlignRight|Qt.AlignmentFlag.AlignTrailing|Qt.AlignmentFlag.AlignVCenter) self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1) self.shift_down_btn = QPushButton(self.groupBox_2) self.shift_down_btn.setObjectName(u"shift_down_btn") icon5 = QIcon() icon5.addFile(u":/down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.shift_down_btn.setIcon(icon5) self.gridLayout.addWidget(self.shift_down_btn, 4, 0, 1, 1) self.shift_up_btn = QPushButton(self.groupBox_2) self.shift_up_btn.setObjectName(u"shift_up_btn") icon6 = QIcon() icon6.addFile(u":/up.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.shift_up_btn.setIcon(icon6) self.gridLayout.addWidget(self.shift_up_btn, 3, 0, 1, 1) self.zoom_in_btn = QPushButton(self.groupBox_2) self.zoom_in_btn.setObjectName(u"zoom_in_btn") icon7 = QIcon() icon7.addFile(u":/zoom-in.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.zoom_in_btn.setIcon(icon7) self.gridLayout.addWidget(self.zoom_in_btn, 0, 0, 1, 1) self.fast_shift_down_btn = QPushButton(self.groupBox_2) self.fast_shift_down_btn.setObjectName(u"fast_shift_down_btn") icon8 = QIcon() icon8.addFile(u":/shift_down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.fast_shift_down_btn.setIcon(icon8) self.gridLayout.addWidget(self.fast_shift_down_btn, 6, 0, 1, 1) self.label_6 = QLabel(self.groupBox_2) self.label_6.setObjectName(u"label_6") self.label_6.setAlignment(Qt.AlignmentFlag.AlignRight|Qt.AlignmentFlag.AlignTrailing|Qt.AlignmentFlag.AlignVCenter) self.gridLayout.addWidget(self.label_6, 3, 1, 1, 1) self.label_7 = QLabel(self.groupBox_2) self.label_7.setObjectName(u"label_7") self.label_7.setAlignment(Qt.AlignmentFlag.AlignRight|Qt.AlignmentFlag.AlignTrailing|Qt.AlignmentFlag.AlignVCenter) self.gridLayout.addWidget(self.label_7, 4, 1, 1, 1) self.label_11 = QLabel(self.groupBox_2) self.label_11.setObjectName(u"label_11") self.label_11.setAlignment(Qt.AlignmentFlag.AlignRight|Qt.AlignmentFlag.AlignTrailing|Qt.AlignmentFlag.AlignVCenter) self.gridLayout.addWidget(self.label_11, 5, 1, 1, 1) self.label_12 = QLabel(self.groupBox_2) self.label_12.setObjectName(u"label_12") self.label_12.setAlignment(Qt.AlignmentFlag.AlignRight|Qt.AlignmentFlag.AlignTrailing|Qt.AlignmentFlag.AlignVCenter) self.gridLayout.addWidget(self.label_12, 6, 1, 1, 1) self.gridLayout_3.addWidget(self.groupBox_2, 2, 1, 1, 1) self.plot = QLabel(ScaleDialog) self.plot.setObjectName(u"plot") self.plot.setMinimumSize(QSize(750, 600)) self.plot.setMaximumSize(QSize(750, 600)) self.plot.setFrameShape(QFrame.Shape.Box) self.plot.setLineWidth(2) self.gridLayout_3.addWidget(self.plot, 1, 0, 4, 1) self.groupBox_3 = QGroupBox(ScaleDialog) self.groupBox_3.setObjectName(u"groupBox_3") self.gridLayout_4 = QGridLayout(self.groupBox_3) self.gridLayout_4.setSpacing(1) self.gridLayout_4.setObjectName(u"gridLayout_4") self.gridLayout_4.setContentsMargins(1, 1, 1, 1) self.label_5 = QLabel(self.groupBox_3) self.label_5.setObjectName(u"label_5") self.gridLayout_4.addWidget(self.label_5, 0, 0, 1, 1) self.target_max = QDoubleSpinBox(self.groupBox_3) self.target_max.setObjectName(u"target_max") self.target_max.setDecimals(3) self.target_max.setMinimum(0.000000000000000) self.target_max.setMaximum(1.000000000000000) self.gridLayout_4.addWidget(self.target_max, 0, 1, 1, 1) self.label_9 = QLabel(self.groupBox_3) self.label_9.setObjectName(u"label_9") self.gridLayout_4.addWidget(self.label_9, 1, 0, 1, 1) self.target_min = QDoubleSpinBox(self.groupBox_3) self.target_min.setObjectName(u"target_min") self.target_min.setDecimals(3) self.target_min.setMinimum(0.000000000000000) self.target_min.setMaximum(1.000000000000000) self.gridLayout_4.addWidget(self.target_min, 1, 1, 1, 1) self.gridLayout_3.addWidget(self.groupBox_3, 1, 1, 1, 1) self.groupBox_4 = QGroupBox(ScaleDialog) self.groupBox_4.setObjectName(u"groupBox_4") self.gridLayout_2 = QGridLayout(self.groupBox_4) self.gridLayout_2.setSpacing(1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(1, 1, 1, 1) self.label_10 = QLabel(self.groupBox_4) self.label_10.setObjectName(u"label_10") self.gridLayout_2.addWidget(self.label_10, 3, 0, 1, 1) self.label_8 = QLabel(self.groupBox_4) self.label_8.setObjectName(u"label_8") self.gridLayout_2.addWidget(self.label_8, 1, 0, 1, 1) self.offset = QDoubleSpinBox(self.groupBox_4) self.offset.setObjectName(u"offset") self.offset.setDecimals(1) self.offset.setMinimum(0.000000000000000) self.offset.setMaximum(1.000000000000000) self.gridLayout_2.addWidget(self.offset, 3, 1, 1, 1) self.label_4 = QLabel(self.groupBox_4) self.label_4.setObjectName(u"label_4") self.gridLayout_2.addWidget(self.label_4, 0, 0, 1, 1) self.label_13 = QLabel(self.groupBox_4) self.label_13.setObjectName(u"label_13") self.gridLayout_2.addWidget(self.label_13, 2, 0, 1, 1) self.scaling = QDoubleSpinBox(self.groupBox_4) self.scaling.setObjectName(u"scaling") self.scaling.setDecimals(6) self.gridLayout_2.addWidget(self.scaling, 2, 1, 1, 1) self.y_top = QLabel(self.groupBox_4) self.y_top.setObjectName(u"y_top") self.gridLayout_2.addWidget(self.y_top, 0, 1, 1, 1) self.y_bottom = QLabel(self.groupBox_4) self.y_bottom.setObjectName(u"y_bottom") self.gridLayout_2.addWidget(self.y_bottom, 1, 1, 1, 1) self.gridLayout_3.addWidget(self.groupBox_4, 3, 1, 1, 1) self.signal = QComboBox(ScaleDialog) self.signal.setObjectName(u"signal") self.gridLayout_3.addWidget(self.signal, 0, 0, 1, 2) QWidget.setTabOrder(self.signal, self.target_max) QWidget.setTabOrder(self.target_max, self.target_min) QWidget.setTabOrder(self.target_min, self.zoom_in_btn) QWidget.setTabOrder(self.zoom_in_btn, self.zoom_out_btn) QWidget.setTabOrder(self.zoom_out_btn, self.fit_btn) QWidget.setTabOrder(self.fit_btn, self.shift_up_btn) QWidget.setTabOrder(self.shift_up_btn, self.shift_down_btn) QWidget.setTabOrder(self.shift_down_btn, self.fast_shift_up_btn) QWidget.setTabOrder(self.fast_shift_up_btn, self.fast_shift_down_btn) QWidget.setTabOrder(self.fast_shift_down_btn, self.scaling) QWidget.setTabOrder(self.scaling, self.offset) QWidget.setTabOrder(self.offset, self.apply_btn) QWidget.setTabOrder(self.apply_btn, self.cancel_btn) self.retranslateUi(ScaleDialog) QMetaObject.connectSlotsByName(ScaleDialog) # setupUi def retranslateUi(self, ScaleDialog): ScaleDialog.setWindowTitle(QCoreApplication.translate("ScaleDialog", u"Dialog", None)) self.cancel_btn.setText(QCoreApplication.translate("ScaleDialog", u"Cancel", None)) self.apply_btn.setText(QCoreApplication.translate("ScaleDialog", u"Apply", None)) self.groupBox_2.setTitle(QCoreApplication.translate("ScaleDialog", u"Keyboard shortcuts", None)) self.fit_btn.setText(QCoreApplication.translate("ScaleDialog", u"Fit vertically", None)) self.label_3.setText(QCoreApplication.translate("ScaleDialog", u"F or Shift+F", None)) self.zoom_out_btn.setText(QCoreApplication.translate("ScaleDialog", u"Zoom out", None)) self.label.setText(QCoreApplication.translate("ScaleDialog", u"O or Shift+O", None)) self.fast_shift_up_btn.setText(QCoreApplication.translate("ScaleDialog", u"Fast shift up", None)) self.label_2.setText(QCoreApplication.translate("ScaleDialog", u"I or Shift+I", None)) self.shift_down_btn.setText(QCoreApplication.translate("ScaleDialog", u"Shift down", None)) self.shift_up_btn.setText(QCoreApplication.translate("ScaleDialog", u"Shift up", None)) self.zoom_in_btn.setText(QCoreApplication.translate("ScaleDialog", u"Zoom in", None)) self.fast_shift_down_btn.setText(QCoreApplication.translate("ScaleDialog", u"Fast shift down", None)) self.label_6.setText(QCoreApplication.translate("ScaleDialog", u"

Shift + \u2191

", None)) self.label_7.setText(QCoreApplication.translate("ScaleDialog", u"

Shift + \u2193

", None)) self.label_11.setText(QCoreApplication.translate("ScaleDialog", u"Shift + PageUp", None)) self.label_12.setText(QCoreApplication.translate("ScaleDialog", u"Shift + PageDown", None)) self.plot.setText("") self.groupBox_3.setTitle(QCoreApplication.translate("ScaleDialog", u"Expected signal values", None)) self.label_5.setText(QCoreApplication.translate("ScaleDialog", u"Signal max", None)) self.label_9.setText(QCoreApplication.translate("ScaleDialog", u"Signal min", None)) self.groupBox_4.setTitle(QCoreApplication.translate("ScaleDialog", u"Screen levels", None)) self.label_10.setText(QCoreApplication.translate("ScaleDialog", u"0 level on screen", None)) self.label_8.setText(QCoreApplication.translate("ScaleDialog", u"Y axis bottom value", None)) self.offset.setSuffix(QCoreApplication.translate("ScaleDialog", u"%", None)) self.label_4.setText(QCoreApplication.translate("ScaleDialog", u"Y axis top value", None)) self.label_13.setText(QCoreApplication.translate("ScaleDialog", u"Scaling [units/screen]", None)) self.y_top.setText("") self.y_bottom.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/signal_scale.ui000066400000000000000000000337041502633300400215230ustar00rootroot00000000000000 ScaleDialog 0 0 1091 678 Dialog 1 1 1 1 1 1 Qt::Orientation::Horizontal 40 20 Cancel :/erase.png:/erase.png Qt::Orientation::Horizontal 40 20 Apply :/checkmark.png:/checkmark.png Qt::Orientation::Vertical 20 135 Keyboard shortcuts 1 1 1 1 1 Fit vertically :/fit.png:/fit.png F or Shift+F Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter Zoom out :/zoom-out.png:/zoom-out.png O or Shift+O Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter Fast shift up :/shift_up.png:/shift_up.png I or Shift+I Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter Shift down :/down.png:/down.png Shift up :/up.png:/up.png Zoom in :/zoom-in.png:/zoom-in.png Fast shift down :/shift_down.png:/shift_down.png <html><head/><body><p>Shift + ↑</p></body></html> Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter <html><head/><body><p>Shift + ↓</p></body></html> Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter Shift + PageUp Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter Shift + PageDown Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 750 600 750 600 QFrame::Shape::Box 2 Expected signal values 1 1 1 1 1 Signal max 3 0.000000000000000 1.000000000000000 Signal min 3 0.000000000000000 1.000000000000000 Screen levels 1 1 1 1 1 0 level on screen Y axis bottom value % 1 0.000000000000000 1.000000000000000 Y axis top value Scaling [units/screen] 6 signal target_max target_min zoom_in_btn zoom_out_btn fit_btn shift_up_btn shift_down_btn fast_shift_up_btn fast_shift_down_btn scaling offset apply_btn cancel_btn asammdf-8.5.1/src/asammdf/gui/ui/simple_search_dialog.py000066400000000000000000000154231502633300400232450ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'simple_search_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QAbstractItemView, QApplication, QComboBox, QDialog, QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QPushButton, QSizePolicy, QSpacerItem, QTreeWidget, QTreeWidgetItem, QWidget) from . import resource_rc class Ui_SimpleSearchDialog(object): def setupUi(self, SimpleSearchDialog): if not SimpleSearchDialog.objectName(): SimpleSearchDialog.setObjectName(u"SimpleSearchDialog") SimpleSearchDialog.resize(1183, 421) SimpleSearchDialog.setSizeGripEnabled(True) self.gridLayout = QGridLayout(SimpleSearchDialog) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.matches = QTreeWidget(SimpleSearchDialog) self.matches.setObjectName(u"matches") self.matches.setFocusPolicy(Qt.FocusPolicy.TabFocus) self.matches.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.matches.setSortingEnabled(True) self.gridLayout.addWidget(self.matches, 3, 0, 2, 1) self.status = QLabel(SimpleSearchDialog) self.status.setObjectName(u"status") self.gridLayout.addWidget(self.status, 9, 0, 1, 1) self.selection = QTreeWidget(SimpleSearchDialog) self.selection.setObjectName(u"selection") self.selection.setSortingEnabled(True) self.gridLayout.addWidget(self.selection, 3, 2, 2, 1) self.label = QLabel(SimpleSearchDialog) self.label.setObjectName(u"label") self.gridLayout.addWidget(self.label, 2, 2, 1, 1) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_2.addItem(self.horizontalSpacer) self.gridLayout.addLayout(self.horizontalLayout_2, 0, 2, 1, 1) self.add_btn = QPushButton(SimpleSearchDialog) self.add_btn.setObjectName(u"add_btn") icon = QIcon() icon.addFile(u":/left.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.add_btn.setIcon(icon) self.gridLayout.addWidget(self.add_btn, 3, 1, 1, 1) self.search_box = QLineEdit(SimpleSearchDialog) self.search_box.setObjectName(u"search_box") self.gridLayout.addWidget(self.search_box, 2, 0, 1, 1) self.match_kind = QComboBox(SimpleSearchDialog) self.match_kind.addItem("") self.match_kind.addItem("") self.match_kind.setObjectName(u"match_kind") self.gridLayout.addWidget(self.match_kind, 0, 0, 1, 1) self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.gridLayout.addItem(self.verticalSpacer_2, 4, 1, 1, 1) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.cancel_btn = QPushButton(SimpleSearchDialog) self.cancel_btn.setObjectName(u"cancel_btn") self.horizontalLayout.addWidget(self.cancel_btn) self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer_2) self.apply_btn = QPushButton(SimpleSearchDialog) self.apply_btn.setObjectName(u"apply_btn") self.horizontalLayout.addWidget(self.apply_btn) self.horizontalLayout.setStretch(1, 1) self.gridLayout.addLayout(self.horizontalLayout, 6, 0, 1, 3) self.comment = QLabel(SimpleSearchDialog) self.comment.setObjectName(u"comment") self.gridLayout.addWidget(self.comment, 5, 0, 1, 3) self.case_sensitivity = QComboBox(SimpleSearchDialog) self.case_sensitivity.addItem("") self.case_sensitivity.addItem("") self.case_sensitivity.setObjectName(u"case_sensitivity") self.gridLayout.addWidget(self.case_sensitivity, 1, 0, 1, 1) QWidget.setTabOrder(self.match_kind, self.case_sensitivity) QWidget.setTabOrder(self.case_sensitivity, self.search_box) QWidget.setTabOrder(self.search_box, self.matches) QWidget.setTabOrder(self.matches, self.add_btn) QWidget.setTabOrder(self.add_btn, self.selection) QWidget.setTabOrder(self.selection, self.apply_btn) QWidget.setTabOrder(self.apply_btn, self.cancel_btn) self.retranslateUi(SimpleSearchDialog) self.match_kind.setCurrentIndex(0) QMetaObject.connectSlotsByName(SimpleSearchDialog) # setupUi def retranslateUi(self, SimpleSearchDialog): SimpleSearchDialog.setWindowTitle(QCoreApplication.translate("SimpleSearchDialog", u"Dialog", None)) ___qtreewidgetitem = self.matches.headerItem() ___qtreewidgetitem.setText(0, QCoreApplication.translate("SimpleSearchDialog", u"Channel", None)); self.status.setText("") ___qtreewidgetitem1 = self.selection.headerItem() ___qtreewidgetitem1.setText(0, QCoreApplication.translate("SimpleSearchDialog", u"Channel", None)); self.label.setText(QCoreApplication.translate("SimpleSearchDialog", u"Final selection", None)) self.add_btn.setText("") self.search_box.setText("") self.match_kind.setItemText(0, QCoreApplication.translate("SimpleSearchDialog", u"Wildcard", None)) self.match_kind.setItemText(1, QCoreApplication.translate("SimpleSearchDialog", u"Regex", None)) self.cancel_btn.setText(QCoreApplication.translate("SimpleSearchDialog", u"Cancel", None)) self.apply_btn.setText(QCoreApplication.translate("SimpleSearchDialog", u"Apply", None)) self.comment.setText("") self.case_sensitivity.setItemText(0, QCoreApplication.translate("SimpleSearchDialog", u"Case insensitive", None)) self.case_sensitivity.setItemText(1, QCoreApplication.translate("SimpleSearchDialog", u"Case sensitive", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/simple_search_dialog.ui000066400000000000000000000125041502633300400232270ustar00rootroot00000000000000 SimpleSearchDialog 0 0 1183 421 Dialog true 1 1 1 1 1 Qt::FocusPolicy::TabFocus QAbstractItemView::SelectionMode::ExtendedSelection true Channel true Channel Final selection 1 Qt::Orientation::Horizontal 40 20 :/left.png:/left.png 0 Wildcard Regex Qt::Orientation::Vertical 20 40 1 Cancel Qt::Orientation::Horizontal 40 20 Apply Case insensitive Case sensitive match_kind case_sensitivity search_box matches add_btn selection apply_btn cancel_btn asammdf-8.5.1/src/asammdf/gui/ui/tabular.py000066400000000000000000000213251502633300400205400ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'tabular.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QGridLayout, QGroupBox, QHBoxLayout, QListWidgetItem, QPushButton, QSizePolicy, QSpacerItem, QTextEdit, QVBoxLayout, QWidget) from asammdf.gui.widgets.list import MinimalListWidget from . import resource_rc class Ui_TabularDisplay(object): def setupUi(self, TabularDisplay): if not TabularDisplay.objectName(): TabularDisplay.setObjectName(u"TabularDisplay") TabularDisplay.resize(821, 618) self.verticalLayout = QVBoxLayout(TabularDisplay) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.verticalLayout.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.format_selection = QComboBox(TabularDisplay) self.format_selection.addItem("") self.format_selection.addItem("") self.format_selection.addItem("") self.format_selection.addItem("") self.format_selection.setObjectName(u"format_selection") self.horizontalLayout_2.addWidget(self.format_selection) self.float_precision = QComboBox(TabularDisplay) self.float_precision.setObjectName(u"float_precision") self.horizontalLayout_2.addWidget(self.float_precision) self.time_as_date = QCheckBox(TabularDisplay) self.time_as_date.setObjectName(u"time_as_date") self.horizontalLayout_2.addWidget(self.time_as_date) self.remove_prefix = QCheckBox(TabularDisplay) self.remove_prefix.setObjectName(u"remove_prefix") self.horizontalLayout_2.addWidget(self.remove_prefix) self.prefix = QComboBox(TabularDisplay) self.prefix.setObjectName(u"prefix") self.prefix.setMinimumSize(QSize(200, 0)) self.prefix.setEditable(True) self.horizontalLayout_2.addWidget(self.prefix) self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout_2.addItem(self.horizontalSpacer_3) self.toggle_filters_btn = QPushButton(TabularDisplay) self.toggle_filters_btn.setObjectName(u"toggle_filters_btn") icon = QIcon() icon.addFile(u":/down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.toggle_filters_btn.setIcon(icon) self.horizontalLayout_2.addWidget(self.toggle_filters_btn) self.verticalLayout.addLayout(self.horizontalLayout_2) self.filters_group = QGroupBox(TabularDisplay) self.filters_group.setObjectName(u"filters_group") self.gridLayout_3 = QGridLayout(self.filters_group) self.gridLayout_3.setSpacing(1) self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setContentsMargins(1, 1, 1, 1) self.add_filter_btn = QPushButton(self.filters_group) self.add_filter_btn.setObjectName(u"add_filter_btn") icon1 = QIcon() icon1.addFile(u":/plus.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.add_filter_btn.setIcon(icon1) self.gridLayout_3.addWidget(self.add_filter_btn, 0, 0, 1, 1) self.horizontalSpacer = QSpacerItem(20, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(self.horizontalSpacer, 0, 1, 1, 1) self.apply_filters_btn = QPushButton(self.filters_group) self.apply_filters_btn.setObjectName(u"apply_filters_btn") icon2 = QIcon() icon2.addFile(u":/filter.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.apply_filters_btn.setIcon(icon2) self.gridLayout_3.addWidget(self.apply_filters_btn, 0, 2, 1, 1) self.horizontalSpacer_2 = QSpacerItem(559, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(self.horizontalSpacer_2, 0, 3, 1, 1) self.filters = MinimalListWidget(self.filters_group) self.filters.setObjectName(u"filters") self.filters.setMaximumSize(QSize(16777215, 150)) self.gridLayout_3.addWidget(self.filters, 1, 0, 1, 4) self.groupBox = QGroupBox(self.filters_group) self.groupBox.setObjectName(u"groupBox") sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth()) self.groupBox.setSizePolicy(sizePolicy) self.groupBox.setMinimumSize(QSize(0, 30)) self.gridLayout = QGridLayout(self.groupBox) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.query = QTextEdit(self.groupBox) self.query.setObjectName(u"query") sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.MinimumExpanding) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.query.sizePolicy().hasHeightForWidth()) self.query.setSizePolicy(sizePolicy1) self.query.setMinimumSize(QSize(0, 7)) self.query.setMaximumSize(QSize(16777215, 150)) font = QFont() font.setFamilies([u"Lucida Console"]) self.query.setFont(font) self.query.setStyleSheet(u"background-color: rgb(186, 186, 186);") self.query.setReadOnly(True) self.gridLayout.addWidget(self.query, 0, 0, 1, 1) self.gridLayout_3.addWidget(self.groupBox, 2, 0, 1, 4) self.gridLayout_3.setColumnStretch(3, 1) self.verticalLayout.addWidget(self.filters_group) self.verticalLayout.setStretch(0, 1) QWidget.setTabOrder(self.format_selection, self.float_precision) QWidget.setTabOrder(self.float_precision, self.time_as_date) QWidget.setTabOrder(self.time_as_date, self.remove_prefix) QWidget.setTabOrder(self.remove_prefix, self.prefix) QWidget.setTabOrder(self.prefix, self.toggle_filters_btn) QWidget.setTabOrder(self.toggle_filters_btn, self.add_filter_btn) QWidget.setTabOrder(self.add_filter_btn, self.apply_filters_btn) QWidget.setTabOrder(self.apply_filters_btn, self.filters) QWidget.setTabOrder(self.filters, self.query) self.retranslateUi(TabularDisplay) QMetaObject.connectSlotsByName(TabularDisplay) # setupUi def retranslateUi(self, TabularDisplay): TabularDisplay.setWindowTitle(QCoreApplication.translate("TabularDisplay", u"Form", None)) self.format_selection.setItemText(0, QCoreApplication.translate("TabularDisplay", u"phys", None)) self.format_selection.setItemText(1, QCoreApplication.translate("TabularDisplay", u"hex", None)) self.format_selection.setItemText(2, QCoreApplication.translate("TabularDisplay", u"bin", None)) self.format_selection.setItemText(3, QCoreApplication.translate("TabularDisplay", u"ascii", None)) self.time_as_date.setText(QCoreApplication.translate("TabularDisplay", u"Time as date", None)) self.remove_prefix.setText(QCoreApplication.translate("TabularDisplay", u"Remove prefix", None)) self.toggle_filters_btn.setText(QCoreApplication.translate("TabularDisplay", u"Show filters", None)) self.filters_group.setTitle(QCoreApplication.translate("TabularDisplay", u"Filters", None)) self.add_filter_btn.setText(QCoreApplication.translate("TabularDisplay", u"Add new filter", None)) self.apply_filters_btn.setText(QCoreApplication.translate("TabularDisplay", u"Apply filters", None)) self.groupBox.setTitle(QCoreApplication.translate("TabularDisplay", u"pandas DataFrame query", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/tabular.ui000066400000000000000000000202341502633300400205230ustar00rootroot00000000000000 TabularDisplay 0 0 821 618 Form 1 1 1 1 1 1 1 phys hex bin ascii Time as date Remove prefix 200 0 true Qt::Orientation::Horizontal 40 20 Show filters :/down.png:/down.png Filters 1 1 1 1 1 Add new filter :/plus.png:/plus.png Qt::Orientation::Horizontal 20 20 Apply filters :/filter.png:/filter.png Qt::Orientation::Horizontal 559 20 16777215 150 0 0 0 30 pandas DataFrame query 1 1 1 1 1 0 0 0 7 16777215 150 Lucida Console background-color: rgb(186, 186, 186); true MinimalListWidget QListWidget
asammdf.gui.widgets.list.h
format_selection float_precision time_as_date remove_prefix prefix toggle_filters_btn add_filter_btn apply_filters_btn filters query
asammdf-8.5.1/src/asammdf/gui/ui/tabular_filter.py000066400000000000000000000047451502633300400221140ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'tabular_filter.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QHBoxLayout, QLineEdit, QSizePolicy, QWidget) class Ui_TabularFilter(object): def setupUi(self, TabularFilter): if not TabularFilter.objectName(): TabularFilter.setObjectName(u"TabularFilter") TabularFilter.resize(813, 26) TabularFilter.setMinimumSize(QSize(0, 26)) self.horizontalLayout = QHBoxLayout(TabularFilter) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.enabled = QCheckBox(TabularFilter) self.enabled.setObjectName(u"enabled") self.enabled.setChecked(True) self.horizontalLayout.addWidget(self.enabled) self.relation = QComboBox(TabularFilter) self.relation.setObjectName(u"relation") self.horizontalLayout.addWidget(self.relation) self.column = QComboBox(TabularFilter) self.column.setObjectName(u"column") self.column.setMinimumSize(QSize(300, 0)) self.horizontalLayout.addWidget(self.column) self.op = QComboBox(TabularFilter) self.op.setObjectName(u"op") self.horizontalLayout.addWidget(self.op) self.target = QLineEdit(TabularFilter) self.target.setObjectName(u"target") self.target.setClearButtonEnabled(False) self.horizontalLayout.addWidget(self.target) self.retranslateUi(TabularFilter) QMetaObject.connectSlotsByName(TabularFilter) # setupUi def retranslateUi(self, TabularFilter): TabularFilter.setWindowTitle(QCoreApplication.translate("TabularFilter", u"Form", None)) self.enabled.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/tabular_filter.ui000066400000000000000000000031161502633300400220700ustar00rootroot00000000000000 TabularFilter 0 0 813 26 0 26 Form 1 1 1 1 1 true 300 0 false asammdf-8.5.1/src/asammdf/gui/ui/vrtt_widget.py000066400000000000000000000106151502633300400214500ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'vrtt_widget.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QDoubleSpinBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QSizePolicy, QStackedWidget, QWidget) class Ui_VRTT_Widget(object): def setupUi(self, VRTT_Widget): if not VRTT_Widget.objectName(): VRTT_Widget.setObjectName(u"VRTT_Widget") VRTT_Widget.resize(512, 48) self.horizontalLayout = QHBoxLayout(VRTT_Widget) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.label = QLabel(VRTT_Widget) self.label.setObjectName(u"label") self.horizontalLayout.addWidget(self.label) self.lower = QDoubleSpinBox(VRTT_Widget) self.lower.setObjectName(u"lower") self.lower.setMinimumSize(QSize(100, 0)) self.lower.setDecimals(0) self.horizontalLayout.addWidget(self.lower) self.label_2 = QLabel(VRTT_Widget) self.label_2.setObjectName(u"label_2") self.horizontalLayout.addWidget(self.label_2) self.upper = QDoubleSpinBox(VRTT_Widget) self.upper.setObjectName(u"upper") self.upper.setMinimumSize(QSize(100, 0)) self.upper.setDecimals(0) self.horizontalLayout.addWidget(self.upper) self.label_3 = QLabel(VRTT_Widget) self.label_3.setObjectName(u"label_3") self.horizontalLayout.addWidget(self.label_3) self.mode_switch = QComboBox(VRTT_Widget) self.mode_switch.addItem("") self.mode_switch.addItem("") self.mode_switch.setObjectName(u"mode_switch") self.horizontalLayout.addWidget(self.mode_switch) self.mode = QStackedWidget(VRTT_Widget) self.mode.setObjectName(u"mode") self.page = QWidget() self.page.setObjectName(u"page") self.horizontalLayout_2 = QHBoxLayout(self.page) self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.horizontalLayout_2.setContentsMargins(1, 1, 1, 1) self.text = QLineEdit(self.page) self.text.setObjectName(u"text") self.horizontalLayout_2.addWidget(self.text) self.mode.addWidget(self.page) self.page_2 = QWidget() self.page_2.setObjectName(u"page_2") self.horizontalLayout_3 = QHBoxLayout(self.page_2) self.horizontalLayout_3.setSpacing(1) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.horizontalLayout_3.setContentsMargins(1, 1, 1, 1) self.conversion_btn = QPushButton(self.page_2) self.conversion_btn.setObjectName(u"conversion_btn") self.horizontalLayout_3.addWidget(self.conversion_btn) self.mode.addWidget(self.page_2) self.horizontalLayout.addWidget(self.mode) self.retranslateUi(VRTT_Widget) self.mode.setCurrentIndex(0) QMetaObject.connectSlotsByName(VRTT_Widget) # setupUi def retranslateUi(self, VRTT_Widget): VRTT_Widget.setWindowTitle(QCoreApplication.translate("VRTT_Widget", u"Form", None)) self.label.setText(QCoreApplication.translate("VRTT_Widget", u"[", None)) self.label_2.setText(QCoreApplication.translate("VRTT_Widget", u",", None)) self.label_3.setText(QCoreApplication.translate("VRTT_Widget", u") ->", None)) self.mode_switch.setItemText(0, QCoreApplication.translate("VRTT_Widget", u"Text", None)) self.mode_switch.setItemText(1, QCoreApplication.translate("VRTT_Widget", u"Conversion", None)) self.conversion_btn.setText(QCoreApplication.translate("VRTT_Widget", u"Referenced conversion", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/vrtt_widget.ui000066400000000000000000000071071502633300400214370ustar00rootroot00000000000000 VRTT_Widget 0 0 512 48 Form 1 1 1 1 1 [ 100 0 0 , 100 0 0 ) -> Text Conversion 0 1 1 1 1 1 1 1 1 1 1 Referenced conversion asammdf-8.5.1/src/asammdf/gui/ui/vtt_widget.py000066400000000000000000000073701502633300400212720ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'vtt_widget.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QDoubleSpinBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QSizePolicy, QStackedWidget, QWidget) class Ui_VTT_Widget(object): def setupUi(self, VTT_Widget): if not VTT_Widget.objectName(): VTT_Widget.setObjectName(u"VTT_Widget") VTT_Widget.resize(511, 48) self.horizontalLayout = QHBoxLayout(VTT_Widget) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.value = QDoubleSpinBox(VTT_Widget) self.value.setObjectName(u"value") self.value.setMinimumSize(QSize(100, 0)) self.value.setDecimals(0) self.horizontalLayout.addWidget(self.value) self.label_2 = QLabel(VTT_Widget) self.label_2.setObjectName(u"label_2") self.horizontalLayout.addWidget(self.label_2) self.mode_switch = QComboBox(VTT_Widget) self.mode_switch.addItem("") self.mode_switch.addItem("") self.mode_switch.setObjectName(u"mode_switch") self.horizontalLayout.addWidget(self.mode_switch) self.mode = QStackedWidget(VTT_Widget) self.mode.setObjectName(u"mode") self.page = QWidget() self.page.setObjectName(u"page") self.horizontalLayout_2 = QHBoxLayout(self.page) self.horizontalLayout_2.setSpacing(1) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.horizontalLayout_2.setContentsMargins(1, 1, 1, 1) self.text = QLineEdit(self.page) self.text.setObjectName(u"text") self.horizontalLayout_2.addWidget(self.text) self.mode.addWidget(self.page) self.page_2 = QWidget() self.page_2.setObjectName(u"page_2") self.horizontalLayout_3 = QHBoxLayout(self.page_2) self.horizontalLayout_3.setSpacing(1) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.horizontalLayout_3.setContentsMargins(1, 1, 1, 1) self.conversion_btn = QPushButton(self.page_2) self.conversion_btn.setObjectName(u"conversion_btn") self.horizontalLayout_3.addWidget(self.conversion_btn) self.mode.addWidget(self.page_2) self.horizontalLayout.addWidget(self.mode) self.retranslateUi(VTT_Widget) self.mode.setCurrentIndex(0) QMetaObject.connectSlotsByName(VTT_Widget) # setupUi def retranslateUi(self, VTT_Widget): VTT_Widget.setWindowTitle(QCoreApplication.translate("VTT_Widget", u"Form", None)) self.label_2.setText(QCoreApplication.translate("VTT_Widget", u"->", None)) self.mode_switch.setItemText(0, QCoreApplication.translate("VTT_Widget", u"Text", None)) self.mode_switch.setItemText(1, QCoreApplication.translate("VTT_Widget", u"Conversion", None)) self.text.setPlaceholderText("") self.conversion_btn.setText(QCoreApplication.translate("VTT_Widget", u"Referenced conversion", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/vtt_widget.ui000066400000000000000000000061551502633300400212570ustar00rootroot00000000000000 VTT_Widget 0 0 511 48 Form 1 1 1 1 1 100 0 0 -> Text Conversion 0 1 1 1 1 1 1 1 1 1 1 Referenced conversion asammdf-8.5.1/src/asammdf/gui/ui/windows_selection_dialog.py000066400000000000000000000100131502633300400241540ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'windows_selection_dialog.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QAbstractButton, QApplication, QCheckBox, QDialog, QDialogButtonBox, QFrame, QGroupBox, QScrollArea, QSizePolicy, QVBoxLayout, QWidget) class Ui_WindowSelectionDialog(object): def setupUi(self, WindowSelectionDialog): if not WindowSelectionDialog.objectName(): WindowSelectionDialog.setObjectName(u"WindowSelectionDialog") WindowSelectionDialog.resize(453, 435) self.verticalLayout_2 = QVBoxLayout(WindowSelectionDialog) self.verticalLayout_2.setSpacing(1) self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.verticalLayout_2.setContentsMargins(1, 1, 1, 1) self.groupBox = QGroupBox(WindowSelectionDialog) self.groupBox.setObjectName(u"groupBox") self.groupBox.setFlat(True) self.lay = QVBoxLayout(self.groupBox) self.lay.setSpacing(1) self.lay.setObjectName(u"lay") self.lay.setContentsMargins(1, 1, 1, 1) self.scrollArea = QScrollArea(self.groupBox) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setFrameShape(QFrame.Shape.NoFrame) self.scrollArea.setFrameShadow(QFrame.Shadow.Plain) self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents_2 = QWidget() self.scrollAreaWidgetContents_2.setObjectName(u"scrollAreaWidgetContents_2") self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 439, 355)) self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents_2) self.verticalLayout_3.setSpacing(1) self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.verticalLayout_3.setContentsMargins(1, 1, 1, 1) self.selection_layout = QVBoxLayout() self.selection_layout.setSpacing(1) self.selection_layout.setObjectName(u"selection_layout") self.verticalLayout_3.addLayout(self.selection_layout) self.scrollArea.setWidget(self.scrollAreaWidgetContents_2) self.lay.addWidget(self.scrollArea) self.disable_channels = QCheckBox(self.groupBox) self.disable_channels.setObjectName(u"disable_channels") self.lay.addWidget(self.disable_channels) self.verticalLayout_2.addWidget(self.groupBox) self.buttonBox = QDialogButtonBox(WindowSelectionDialog) self.buttonBox.setObjectName(u"buttonBox") self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Cancel|QDialogButtonBox.StandardButton.Ok) self.verticalLayout_2.addWidget(self.buttonBox) self.retranslateUi(WindowSelectionDialog) self.buttonBox.accepted.connect(WindowSelectionDialog.accept) self.buttonBox.rejected.connect(WindowSelectionDialog.reject) QMetaObject.connectSlotsByName(WindowSelectionDialog) # setupUi def retranslateUi(self, WindowSelectionDialog): WindowSelectionDialog.setWindowTitle(QCoreApplication.translate("WindowSelectionDialog", u"Select window type", None)) self.groupBox.setTitle(QCoreApplication.translate("WindowSelectionDialog", u"Available window types", None)) self.disable_channels.setText(QCoreApplication.translate("WindowSelectionDialog", u"Disable newly added channels", None)) # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/windows_selection_dialog.ui000066400000000000000000000076341502633300400241600ustar00rootroot00000000000000 WindowSelectionDialog 0 0 453 435 Select window type 1 1 1 1 1 Available window types true 1 1 1 1 1 QFrame::Shape::NoFrame QFrame::Shadow::Plain true 0 0 439 355 1 1 1 1 1 1 Disable newly added channels Qt::Orientation::Horizontal QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok buttonBox accepted() WindowSelectionDialog accept() 248 254 157 274 buttonBox rejected() WindowSelectionDialog reject() 316 260 286 274 asammdf-8.5.1/src/asammdf/gui/ui/xy.py000066400000000000000000000125051502633300400175460ustar00rootroot00000000000000# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'xy.ui' ## ## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QDoubleSpinBox, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QSizePolicy, QSlider, QVBoxLayout, QWidget) from . import resource_rc class Ui_XYDisplay(object): def setupUi(self, XYDisplay): if not XYDisplay.objectName(): XYDisplay.setObjectName(u"XYDisplay") XYDisplay.resize(919, 487) self.verticalLayout = QVBoxLayout(XYDisplay) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.plot_layout = QHBoxLayout() self.plot_layout.setSpacing(1) self.plot_layout.setObjectName(u"plot_layout") self.verticalLayout.addLayout(self.plot_layout) self.groupBox = QGroupBox(XYDisplay) self.groupBox.setObjectName(u"groupBox") self.horizontalLayout = QHBoxLayout(self.groupBox) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(1, 1, 1, 1) self.timestamp = QDoubleSpinBox(self.groupBox) self.timestamp.setObjectName(u"timestamp") self.timestamp.setDecimals(9) self.timestamp.setMinimum(-999999999999.000000000000000) self.timestamp.setMaximum(9999999.000000000000000) self.horizontalLayout.addWidget(self.timestamp) self.min_t = QLabel(self.groupBox) self.min_t.setObjectName(u"min_t") self.horizontalLayout.addWidget(self.min_t) self.timestamp_slider = QSlider(self.groupBox) self.timestamp_slider.setObjectName(u"timestamp_slider") self.timestamp_slider.setMaximum(99999) self.timestamp_slider.setOrientation(Qt.Orientation.Horizontal) self.timestamp_slider.setTickInterval(1) self.horizontalLayout.addWidget(self.timestamp_slider) self.max_t = QLabel(self.groupBox) self.max_t.setObjectName(u"max_t") self.horizontalLayout.addWidget(self.max_t) self.horizontalLayout.setStretch(2, 1) self.verticalLayout.addWidget(self.groupBox) self.groupBox_2 = QGroupBox(XYDisplay) self.groupBox_2.setObjectName(u"groupBox_2") self.gridLayout = QGridLayout(self.groupBox_2) self.gridLayout.setSpacing(1) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(1, 1, 1, 1) self.label = QLabel(self.groupBox_2) self.label.setObjectName(u"label") self.gridLayout.addWidget(self.label, 0, 0, 1, 1) self.x_channel_edit = QLineEdit(self.groupBox_2) self.x_channel_edit.setObjectName(u"x_channel_edit") self.gridLayout.addWidget(self.x_channel_edit, 0, 1, 1, 1) self.x_search_btn = QPushButton(self.groupBox_2) self.x_search_btn.setObjectName(u"x_search_btn") icon = QIcon() icon.addFile(u":/search.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.x_search_btn.setIcon(icon) self.gridLayout.addWidget(self.x_search_btn, 0, 2, 1, 1) self.label_2 = QLabel(self.groupBox_2) self.label_2.setObjectName(u"label_2") self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) self.y_channel_edit = QLineEdit(self.groupBox_2) self.y_channel_edit.setObjectName(u"y_channel_edit") self.gridLayout.addWidget(self.y_channel_edit, 1, 1, 1, 1) self.y_search_btn = QPushButton(self.groupBox_2) self.y_search_btn.setObjectName(u"y_search_btn") self.y_search_btn.setIcon(icon) self.gridLayout.addWidget(self.y_search_btn, 1, 2, 1, 1) self.gridLayout.setColumnStretch(1, 1) self.verticalLayout.addWidget(self.groupBox_2) self.verticalLayout.setStretch(0, 1) self.retranslateUi(XYDisplay) QMetaObject.connectSlotsByName(XYDisplay) # setupUi def retranslateUi(self, XYDisplay): XYDisplay.setWindowTitle(QCoreApplication.translate("XYDisplay", u"Form", None)) self.groupBox.setTitle(QCoreApplication.translate("XYDisplay", u"Time stamp", None)) self.timestamp.setSuffix(QCoreApplication.translate("XYDisplay", u"s", None)) self.min_t.setText("") self.max_t.setText("") self.groupBox_2.setTitle(QCoreApplication.translate("XYDisplay", u"Channels", None)) self.label.setText(QCoreApplication.translate("XYDisplay", u"X channel", None)) self.x_search_btn.setText("") self.label_2.setText(QCoreApplication.translate("XYDisplay", u"Y channel", None)) self.y_search_btn.setText("") # retranslateUi asammdf-8.5.1/src/asammdf/gui/ui/xy.ui000066400000000000000000000110441502633300400175300ustar00rootroot00000000000000 XYDisplay 0 0 919 487 Form 1 1 1 1 1 1 Time stamp 1 1 1 1 1 s 9 -999999999999.000000000000000 9999999.000000000000000 99999 Qt::Orientation::Horizontal 1 Channels 1 1 1 1 1 X channel :/search.png:/search.png Y channel :/search.png:/search.png asammdf-8.5.1/src/asammdf/gui/utils.py000066400000000000000000001250441502633300400176340ustar00rootroot00000000000000import bisect import builtins import collections from collections import namedtuple import ctypes from datetime import datetime from functools import partial, reduce import inspect from io import StringIO import itertools import math import os import random import re import struct import sys from textwrap import indent from threading import Thread from time import sleep import traceback from traceback import format_exc import numpy as np import pandas as pd from pyqtgraph import functions as fn from PySide6 import QtCore, QtGui, QtWidgets from ..blocks.options import FloatInterpolation, IntegerInterpolation from ..blocks.utils import Terminated from ..signal import Signal from .dialogs.error_dialog import ErrorDialog from .dialogs.messagebox import MessageBox _BUILTINS = vars(builtins).copy() for key in ("breakpoint", "compile", "eval", "exec", "input", "open"): _BUILTINS.pop(key, None) ERROR_ICON = None RANGE_INDICATOR_ICON = None NO_ERROR_ICON = None COMPUTED_FUNCTION_ERROR_VALUE = float("nan") SUPPORTED_FILE_EXTENSIONS = {".csv", ".zip", ".erg", ".dat", ".mdf", ".mf4", ".mf4z"} SUPPORTED_BUS_DATABASE_EXTENSIONS = {".arxml", ".dbc", ".xml"} GREEN = "#599e5e" BLUE = "#61b2e2" SCROLLBAR_STYLE = """ QTreeWidget {{ font-size: {font_size}pt; }} QScrollBar:vertical {{ border: 1px solid {color}; background: palette(window); width: 14px; margin: 14px 0px 14px 0px; }} QScrollBar::handle:vertical {{ border: 1px solid palette(window); background: {color}; min-height: 40px; width: 6px; }} QScrollBar::add-line:vertical {{ border: 1px solid {color}; background: palette(window); height: 13px; subcontrol-position: bottom; subcontrol-origin: margin; }} QScrollBar::sub-line:vertical {{ border: 1px solid {color}; background: palette(window); height: 13px; subcontrol-position: top; subcontrol-origin: margin; }} QScrollBar:up-arrow:vertical {{ background: {color}; width: 4px; height: 4px; }} QScrollBar:down-arrow:vertical {{ background: {color}; width: 4px; height: 4px; }} QScrollBar:horizontal {{ border: 1px solid {color}; background: palette(window); height: 14px; margin: 0px 14px 0px 14px; }} QScrollBar::handle:horizontal {{ border: 1px solid palette(window); background: {color}; min-width: 40px; height: 14px; }} QScrollBar::add-line:horizontal {{ border: 1px solid {color}; background: palette(window); width: 13px; subcontrol-position: right; subcontrol-origin: margin; }} QScrollBar::sub-line:horizontal {{ border: 1px solid {color}; background: palette(window); width: 13 px; subcontrol-position: left; subcontrol-origin: margin; }} QScrollBar:left-arrow:horizontal {{ background: {color}; width: 4px; height: 4px; }} QScrollBar:right-arrow:horizontal {{ background: {color}; width: 4px; height: 4px; }}""" COMPARISON_NAME = re.compile(r"(\s*\d+:)?(?P.+)") SIG_RE = re.compile(r"\{\{(?!\}\})(?P.*?)\}\}") FONT_SIZE = [6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72] VARIABLE = re.compile(r"(?P\{\{[^}]+\}\})") VARIABLE_GET_DATA = re.compile(r"get_data\s*\(\s*\"(?P[^\"]+)") C_FUNCTION = re.compile(r"\s+(?P\S+)\s*\(\s*struct\s+DATA\s+\*data\s*\)") FUNC_NAME = re.compile(r"def\s+(?P\S+)\s*\(") IMPORT = re.compile(r"^\s*import\s+") IMPORT_INNER = re.compile(r";\s*import\s+") FROM_IMPORT = re.compile(r"^\s*from\s+\S+\s+import\s+") FROM_INNER_IMPORT = re.compile(r";\s*from\s+\S+\s+import\s+") COMPRESSION_OPTIONS = { "4.10": ("no compression", "deflate", "transposed deflate"), "4.20": ("no compression", "deflate", "transposed deflate"), "4.30": ("no compression", "deflate", "transposed deflate", "zstd", "transposed zstd", "lz4", "transposed lz4"), } def excepthook(exc_type, exc_value, tracebackobj): """Global function to catch unhandled exceptions. Parameters ---------- exc_type : str Exception type. exc_value : int Exception value. tracebackobj : traceback Traceback object. """ separator = "-" * 80 notice = "The following error was triggered:" now = datetime.now().strftime("%Y-%m-%d, %H:%M:%S") info = StringIO() traceback.print_tb(tracebackobj, None, info) info.seek(0) info = info.read() errmsg = f"{exc_type}\t \n{exc_value}" sections = [now, separator, errmsg, separator, info] msg = "\n".join(sections) print("".join(traceback.format_tb(tracebackobj))) print(f"{exc_type}: {exc_value}") ErrorDialog(message=errmsg, trace=msg, title="The following error was triggered").exec_() def run_thread_with_progress(widget, target, kwargs, factor=100, offset=0, progress=None): thr = WorkerThread(target=target, kwargs=kwargs) thr.start() while widget.progress is None and thr.is_alive(): sleep(0.02) while thr.is_alive(): if progress and not progress.wasCanceled(): if widget.progress is not None: if widget.progress != (0, 0): progress.setValue(int(widget.progress[0] / widget.progress[1] * factor) + offset) else: progress.setRange(0, 0) QtCore.QCoreApplication.processEvents() sleep(0.1) if progress: progress.setValue(factor + offset) if thr.error: if isinstance(thr.error, Terminated): raise thr.error widget.progress = None if progress: progress.cancel() raise Exception(thr.error) widget.progress = None return thr.output class QWorkerThread(QtCore.QThread): error = QtCore.Signal(object) result = QtCore.Signal(object) # will forward to the progress dialog setLabelText = QtCore.Signal(str) setWindowTitle = QtCore.Signal(str) setWindowIcon = QtCore.Signal(object) setMinimum = QtCore.Signal(int) setMaximum = QtCore.Signal(int) setValue = QtCore.Signal(int) SIGNALS_TEMPLATE = namedtuple( "SIGNALS_TEMPLATE", [ "finished", "error", "result", "setLabelText", "setWindowTitle", "setWindowIcon", "setMinimum", "setMaximum", "setValue", ], ) def __init__(self, function, *args, **kwargs): super().__init__(parent=kwargs.pop("parent", None)) self.function = function self.args = args self.signals = self.SIGNALS_TEMPLATE( self.finished, self.error, self.result, self.setLabelText, self.setWindowTitle, self.setWindowIcon, self.setMinimum, self.setMaximum, self.setValue, ) args = inspect.signature(function) if "progress" in args.parameters: kwargs["progress"] = self self.kwargs = kwargs self.stop = False def run(self): """ Your code goes in this method """ try: result = self.function(*self.args, **self.kwargs) except: traceback.print_exc() exctype, value = sys.exc_info()[:2] self.error.emit((exctype, value, traceback.format_exc())) else: self.result.emit(result) finally: self.kwargs = self.args = None def requestInterruption(self): self.stop = True class ProgressDialog(QtWidgets.QProgressDialog): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.thread = None self.error = None self.result = None self.close_on_finish = True self.hide_on_finish = False self.setMinimumDuration(0) self.canceled.connect(partial(self.close, reject=True)) def run_thread_with_progress( self, target, args, kwargs, wait_here=False, close_on_finish=True, hide_on_finish=False ): self.show() self.result = None self.error = None self.thread_finished = False self.close_on_finish = close_on_finish self.hide_on_finish = hide_on_finish self.thread = QWorkerThread(target, *args, parent=self, **kwargs) self.thread.result.connect(self.receive_result) self.thread.finished.connect(self.thread_complete) self.thread.error.connect(self.receive_error) self.thread.setLabelText.connect(self.setLabelText) self.thread.setWindowIcon.connect(self.setWindowIcon) self.thread.setWindowTitle.connect(self.setWindowTitle) self.thread.setValue.connect(self.setValue) self.thread.setMinimum.connect(self.setMinimum) self.thread.setMaximum.connect(self.setMaximum) self.thread.start() if wait_here: loop = QtCore.QEventLoop() self.thread.finished.connect(loop.quit) loop.exec() return self.result def setLabelText(self, text): super().setLabelText(text) def processEvents(self): pass def receive_result(self, result): self.result = result def receive_error(self, error): self.error = error def thread_complete(self): self.processEvents() if self.hide_on_finish: self.hide() self.thread.result.disconnect(self.receive_result) self.thread.finished.disconnect(self.thread_complete) self.thread.error.disconnect(self.receive_error) self.thread.setLabelText.disconnect(self.setLabelText) self.thread.setWindowIcon.disconnect(self.setWindowIcon) self.thread.setWindowTitle.disconnect(self.setWindowTitle) self.thread.setValue.disconnect(self.setValue) self.thread.setMinimum.disconnect(self.setMinimum) self.thread.setMaximum.disconnect(self.setMaximum) self.thread = None if self.close_on_finish: QtCore.QTimer.singleShot(50, self.close) def close(self, reject=False): if self.thread and not self.thread.isFinished(): loop = QtCore.QEventLoop() self.thread.finished.connect(loop.quit) self.thread.requestInterruption() loop.exec() if reject: self.reject() else: self.accept() self.hide() def exec(self): super().exec() self.hide() def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key.Key_Escape and event.modifiers() == QtCore.Qt.KeyboardModifier.NoModifier: event.accept() self.close() else: super().keyPressEvent(event) def setWindowIcon(self, icon): if isinstance(icon, str): icon_name = icon icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(f":/{icon_name}.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) super().setWindowIcon(icon) def setup_progress(parent, title="", message="", icon_name="", autoclose=False): progress = ProgressDialog(message, "Cancel", 0, 0, parent) progress.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) progress.setCancelButton(None) progress.setAutoClose(autoclose) progress.setWindowTitle(title) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(f":/{icon_name}.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.setWindowIcon(icon) progress.setMinimumWidth(600) progress.show() return progress class WorkerThread(Thread): def __init__(self, *args, **kargs): super().__init__(*args, **kargs) self.output = None self.error = "" def run(self): try: self.output = self._target(*self._args, **self._kwargs) except Terminated as error: self.error = error except: self.error = traceback.format_exc() def get_data_function(signals, fill_0_for_missing_computation_channels): def get_data(name, t=0, interpolated=False): if name in signals: samples = ( signals[name] .interp( [t], integer_interpolation_mode=( IntegerInterpolation.REPEAT_PREVIOUS_SAMPLE if not interpolated else IntegerInterpolation.LINEAR_INTERPOLATION ), float_interpolation_mode=( FloatInterpolation.REPEAT_PREVIOUS_SAMPLE if not interpolated else FloatInterpolation.LINEAR_INTERPOLATION ), ) .samples ) if len(samples): return samples[0] else: return 0 elif fill_0_for_missing_computation_channels: return 0 else: raise Exception(f"{name} channel was not found") return get_data def compute_signal( description, measured_signals, all_timebase, functions, global_variables="", ): required_channels = {} for key, sig in measured_signals.items(): signal = sig.physical(copy=False, ignore_value2text_conversions=True) if signal.samples.dtype.kind in "fui": required_channels[key] = signal else: required_channels[key] = sig measured_signals = required_channels type_ = description["type"] try: if type_ == "python_function": func, trace = ( None, f"{description['function']} not found in the user defined functions", ) _globals = generate_python_function_globals() trace = generate_python_variables(global_variables, in_globals=_globals) if trace: raise Exception(trace) numeric_global_variables = { name: float(val) for name, val in _globals.items() if isinstance(val, (int, float)) } for function_name, definition in functions.items(): _func, _trace = generate_python_function(definition, in_globals=_globals) if function_name == description["function"]: func, trace = _func, _trace if func is None: raise Exception(trace) signals = [] found_args = [] for arg, alternative_names in description["args"].items(): for name in alternative_names: if name in measured_signals: signals.append(measured_signals[name]) found_args.append(arg) break else: found_numeric = False for base in (10, 16, 2): try: value = int(name, base) signals.append(value) found_args.append(arg) found_numeric = True break except: continue else: try: value = float(name) signals.append(value) found_args.append(arg) found_numeric = True except: continue if found_numeric: break names = [*found_args, "t"] triggering = description.get("triggering", "triggering_on_all") if triggering == "triggering_on_all": timestamps = [sig.timestamps for sig in signals if not isinstance(sig, (int, float))] if timestamps: common_timebase = reduce(np.union1d, timestamps) else: common_timebase = all_timebase signals = [sig.interp(common_timebase) if not isinstance(sig, (int, float)) else sig for sig in signals] elif triggering == "triggering_on_channel": triggering_channel = description["triggering_value"] if triggering_channel in measured_signals: common_timebase = measured_signals[triggering_channel].timestamps else: common_timebase = np.array([]) signals = [sig.interp(common_timebase) if not isinstance(sig, (int, float)) else sig for sig in signals] else: step = float(description["triggering_value"]) common_timebase = [] for signal in signals: if isinstance(signal, (int, float)): continue if len(signal): common_timebase.append(signal.timestamps[0]) common_timebase.append(signal.timestamps[-1]) common_timebase = common_timebase or all_timebase if common_timebase: common_timebase = np.unique(common_timebase) start = common_timebase[0] stop = common_timebase[-1] common_timebase = np.arange(start, stop, step) else: common_timebase = np.array([]) signals = [sig.interp(common_timebase) if not isinstance(sig, (int, float)) else sig for sig in signals] if not isinstance(common_timebase, np.ndarray): common_timebase = np.array(common_timebase) for i, (signal, arg_name) in enumerate(zip(signals, found_args, strict=False)): if isinstance(signal, (int, float)): value = signal signals[i] = Signal( name=arg_name, samples=np.full(len(common_timebase), value), timestamps=common_timebase ) if "time_stamps_shift" in description: time_stamps_shift = description["time_stamps_shift"] if time_stamps_shift["type"] == "fixed": shift = time_stamps_shift["fixed_timestamps_shift"] else: shift_variable = time_stamps_shift["global_variable_timestamps_shift"] shift = numeric_global_variables.get(shift_variable, 0.0) else: shift = 0.0 if description.get("computation_mode", "sample_by_sample") == "sample_by_sample": signals = [sig.samples.tolist() for sig in signals] signals.append(common_timebase) samples = [] for values in zip(*signals, strict=False): try: current_sample = func(**dict(zip(names, values, strict=False))) except: current_sample = COMPUTED_FUNCTION_ERROR_VALUE samples.append(current_sample) result = Signal( name="_", samples=samples, timestamps=common_timebase + shift, flags=Signal.Flags.computed, ) else: signals = [sig.samples for sig in signals] signals.append(common_timebase) not_found = [arg_name for arg_name in description["args"] if arg_name not in names] not_found_signals = [] args = inspect.signature(func) for i, (arg_name, arg) in enumerate(args.parameters.items()): if arg_name in names: continue else: not_found_signals.append(np.ones(len(common_timebase), dtype="u1") * arg.default) names.extend(not_found) signals.extend(not_found_signals) samples = func(**dict(zip(names, signals, strict=False))) if len(samples) != len(common_timebase): common_timebase = common_timebase[-len(samples) :] result = Signal( name="_", samples=samples, timestamps=common_timebase + shift, flags=Signal.Flags.computed, ) except: print(format_exc()) result = Signal( name="_", samples=[], timestamps=[], flags=Signal.Flags.computed, ) return result def computation_to_python_function(description): type_ = description["type"] if type_ == "arithmetic": op = description["op"] args = [] fargs = {} operand1 = description["operand1"] if isinstance(operand1, dict): fargs["arg1"] = [] args.append("arg1=0") operand1 = "arg1" elif isinstance(operand1, str): try: operand1 = float(operand1) if operand1.is_integer(): operand1 = int(operand1) except: fargs["arg1"] = [operand1] args.append("arg1=0") operand1 = "arg1" operand2 = description["operand2"] if isinstance(operand2, dict): fargs["arg2"] = [] args.append("arg2=0") operand2 = "arg2" elif isinstance(operand2, str): try: operand2 = float(operand2) if operand2.is_integer(): operand2 = int(operand2) except: fargs["arg2"] = [operand2] args.append("arg2=0") operand2 = "arg2" args.append("t=0") function_name = f"Arithmetic_{os.urandom(6).hex()}" args = ", ".join(args) body = f"return {operand1} {op} {operand2}" definition = f"def {function_name}({args}):\n {body}" new_description = { "args": fargs, "channel_comment": description["channel_comment"], "channel_name": description["channel_name"], "channel_unit": description["channel_unit"], "computation_mode": "sample_by_sample", "definition": definition, "type": "python_function", "triggering": "triggering_on_all", "triggering_value": "all", "function": function_name, } elif type_ == "function": channel = description["channel"] args = [] fargs = {} if isinstance(channel, dict): fargs["arg1"] = [] operand = "arg1" args.append("arg1=0") elif isinstance(channel, str): fargs["arg1"] = [channel] operand = "arg1" args.append("arg1=0") args.append("t=0") np_args = ", ".join([operand] + [str(e) for e in description["args"]]) np_function = description["name"] function_name = f"Numpy_{os.urandom(6).hex()}" args = ", ".join(args) body = f"return np.{np_function}( {np_args} )" definition = f"def {function_name}({args}):\n {body}" new_description = { "args": fargs, "channel_comment": description["channel_comment"], "channel_name": description["channel_name"], "channel_unit": description["channel_unit"], "computation_mode": "sample_by_sample", "definition": definition, "type": "python_function", "triggering": "triggering_on_all", "triggering_value": "all", "function": function_name, } elif type_ == "expression": exp = description["expression"] args = [] fargs = {} translation = {} for match in VARIABLE.finditer(exp): name = match.group("var") if name not in translation: arg = f"arg{len(translation) + 1}" translation[name] = arg args.append(f"{arg}=0") fargs[arg] = [name.strip("}{")] args.append("t=0") for name, arg in translation.items(): exp = exp.replace(name, arg) function_name = f"Expression_{os.urandom(6).hex()}" args = ", ".join(args) body = f"return {exp}" definition = f"def {function_name}({args}):\n {body}" new_description = { "args": fargs, "channel_comment": description.get("channel_comment", ""), "channel_name": description.get("channel_name", ""), "channel_unit": description.get("channel_unit", ""), "computation_mode": "sample_by_sample", "definition": definition, "type": "python_function", "triggering": "triggering_on_all", "triggering_value": "all", "function": function_name, } else: if "args" not in description or "function" not in description: exp = description["definition"] args = [] fargs = {} translation = {} for match in VARIABLE.finditer(exp): name = match.group("var") if name not in translation: arg = f"arg{len(translation) + 1}" translation[name] = arg args.append(f"{arg}=0") fargs[arg] = [name.strip("}{")] args.append("t=0") for name, arg in translation.items(): exp = exp.replace(name, arg) function_name = description["channel_name"] args = ", ".join(args) body = indent(exp, " ", lambda line: True) definition = f"def {function_name}({args}):\n {body}" new_description = { "args": fargs, "channel_comment": description["channel_comment"], "channel_name": description["channel_name"], "channel_unit": description["channel_unit"], "computation_mode": description.get("computation_mode", "sample_by_sample"), "definition": definition, "type": "python_function", "triggering": "triggering_on_all", "triggering_value": "all", "function": function_name, } else: new_description = description new_description["computation_mode"] = description.get("computation_mode", "sample_by_sample") return new_description def replace_computation_dependency(computation, old_name, new_name): new_computation = {} for key, val in computation: if isinstance(val, str) and old_name in val: new_computation[key] = val.replace(old_name, new_name) elif isinstance(val, dict): new_computation[key] = replace_computation_dependency(val, old_name, new_name) else: new_computation[key] = val return new_computation class HelperChannel: __slots__ = "added", "entry", "name" def __init__(self, entry, name): self.name = name self.entry = entry self.added = False def copy_ranges(ranges): if ranges: new_ranges = [] for range_info in ranges: range_info = dict(range_info) for color_name in ("background_color", "font_color"): color = range_info[color_name] if isinstance(color, QtGui.QBrush): range_info[color_name] = QtGui.QBrush(color) elif isinstance(color, (QtGui.QColor, str)): range_info[color_name] = fn.mkColor(color) new_ranges.append(range_info) return new_ranges else: return ranges def unique_ranges(ranges): def compare(r): v1, v2, op1, op2, c1, c2 = r if v1 is None: v1 = -float("inf") if v2 is None: v2 = -float("inf") return v1, v2, op1, op2, c1, c2 if ranges: new_ranges = set() for range_info in ranges: if isinstance(range_info["background_color"], QtGui.QColor): new_ranges.add( ( range_info["value1"], range_info["value2"], range_info["op1"], range_info["op2"], (0, range_info["background_color"].name()), (0, range_info["font_color"].name()), ) ) else: new_ranges.add( ( range_info["value1"], range_info["value2"], range_info["op1"], range_info["op2"], (1, range_info["background_color"].color().name()), (1, range_info["font_color"].color().name()), ) ) ranges = [] for value1, value2, op1, op2, bk_color, ft_color in sorted(new_ranges, key=compare): if bk_color[0] == 0: ranges.append( { "background_color": fn.mkColor(bk_color[1]), "font_color": fn.mkColor(ft_color[1]), "op1": op1, "op2": op2, "value1": value1, "value2": value2, } ) else: ranges.append( { "background_color": fn.mkBrush(bk_color[1]), "font_color": fn.mkBrush(ft_color[1]), "op1": op1, "op2": op2, "value1": value1, "value2": value2, } ) return ranges def get_colors_using_ranges(value, ranges, default_background_color, default_font_color): new_background_color = default_background_color new_font_color = default_font_color if value is None: return new_background_color, new_font_color if ranges: if isinstance(value, (float, int, np.number)): level_class = float else: level_class = str for range_info in ranges: ( background_color, font_color, op1, op2, value1, value2, ) = range_info.values() result = False if isinstance(value1, level_class): if op1 == "==": result = value1 == value elif op1 == "!=": result = value1 != value elif op1 == "<=": result = value1 <= value elif op1 == "<": result = value1 < value elif op1 == ">=": result = value1 >= value elif op1 == ">": result = value1 > value if not result: continue if isinstance(value2, level_class): if op2 == "==": result = value == value2 elif op2 == "!=": result = value != value2 elif op2 == "<=": result = value <= value2 elif op2 == "<": result = value < value2 elif op2 == ">=": result = value >= value2 elif op2 == ">": result = value > value2 if not result: continue if result: new_background_color = background_color new_font_color = font_color break return new_background_color, new_font_color def get_color_using_ranges( value, ranges, default_color, pen=False, ): new_color = default_color if value is None: return new_color if ranges: if isinstance(value, (float, int, np.number)): level_class = float else: level_class = str for range_info in ranges: ( background_color, font_color, op1, op2, value1, value2, ) = range_info.values() result = False if isinstance(value1, level_class): if op1 == "==": result = value1 == value elif op1 == "!=": result = value1 != value elif op1 == "<=": result = value1 <= value elif op1 == "<": result = value1 < value elif op1 == ">=": result = value1 >= value elif op1 == ">": result = value1 > value if not result: continue if isinstance(value2, level_class): if op2 == "==": result = value == value2 elif op2 == "!=": result = value != value2 elif op2 == "<=": result = value <= value2 elif op2 == "<": result = value < value2 elif op2 == ">=": result = value >= value2 elif op2 == ">": result = value > value2 if not result: continue if result: new_color = font_color break if pen: return fn.mkPen(new_color.name()) else: return new_color def value_as_bin(value, dtype): byte_string = np.array([value], dtype=dtype).tobytes() if dtype.byteorder != ">": byte_string = byte_string[::-1] nibles = [] for byte in byte_string: nibles.extend((f"{byte >> 4:04b}", f"{byte & 0xF:04b}")) return ".".join(nibles) def value_as_hex(value, dtype): byte_string = np.array([value], dtype=dtype).tobytes() if dtype.byteorder != ">": byte_string = byte_string[::-1] return f"0x{byte_string.hex().upper()}" def value_as_str(value, format, dtype=None, precision=3): float_fmt = f"{{:.0{precision}f}}" if precision >= 0 else "{}" if isinstance(value, (float, np.floating)): kind = "f" elif isinstance(value, int): kind = "u" value = np.min_scalar_type(value).type(value) dtype = dtype or value.dtype elif isinstance(value, np.integer): kind = "u" dtype = value.dtype else: kind = "S" if kind in "ui": match format: case "bin": string = value_as_bin(value, dtype) case "hex": string = value_as_hex(value, dtype) case "ascii": if 0 < value < 0x110000: string = chr(value) else: string = str(value) case _: string = str(value) elif kind in "SUV": string = str(value) else: string = float_fmt.format(value) return string def draw_color_icon(color): color = QtGui.QColor(color) pix = QtGui.QPixmap(64, 64) painter = QtGui.QPainter(pix) painter.setPen("black") painter.drawRect(QtCore.QRect(0, 0, 63, 63)) painter.setPen(color) painter.setBrush(color) painter.drawRect(QtCore.QRect(1, 1, 62, 62)) painter.end() return QtGui.QIcon(pix) def contains_imports(string): for line in string.splitlines(): if IMPORT.match(line) or FROM_IMPORT.match(line) or IMPORT_INNER.search(line) or FROM_INNER_IMPORT.search(line): return True return False def generate_python_variables(definition: str, in_globals: dict | None = None) -> str | None: trace = None if not isinstance(definition, str): trace = "The function definition must be a string" elif in_globals and not isinstance(in_globals, dict): trace = "'in_globals' must be a dict" else: definition = definition.replace("\t", " ") if contains_imports(definition): trace = "Cannot use import statements in the definition" else: _globals = in_globals or generate_python_function_globals() try: exec(definition, _globals) except: trace = format_exc() return trace def generate_python_function_globals() -> dict: func_globals = { "bisect": bisect, "collections": collections, "itertools": itertools, "math": math, "np": np, "pd": pd, "random": random, "struct": struct, "__builtins__": _BUILTINS, } try: import scipy as sp func_globals["sp"] = sp except ImportError: pass return func_globals def generate_python_function(definition: str, in_globals: dict | None = None) -> tuple: trace = None func = None if not isinstance(definition, str): trace = "The function definition must be a string" return func, trace if in_globals and not isinstance(in_globals, dict): trace = "'in_globals' must be a dict" return func, trace definition = definition.replace("\t", " ") if contains_imports(definition): trace = "Cannot use import statements in the definition" return func, trace _globals = in_globals or generate_python_function_globals() if not definition: trace = "The function definition must not be empty" return func, trace function_name = "" for match in FUNC_NAME.finditer(definition): function_name = match.group("name") if not function_name: trace = "The function name must not be empty" return func, trace try: exec(definition, _globals) func = _globals[function_name] except: trace = format_exc() func = None if func is not None: args = inspect.signature(func) if "t" not in args.parameters: trace = 'The last function argument must be "t=0"' func = None else: count = len(args.parameters) for i, (arg_name, arg) in enumerate(args.parameters.items()): if i == count - 1: if arg_name != "t": trace = 'The last function argument must be "t=0"' func = None elif arg.default != 0: trace = 'The last function argument must be "t=0"' func = None else: if arg.default == inspect._empty: trace = f'All the arguments must have default values. The argument "{arg_name}" has no default value.' func = None break return func, trace def check_generated_function(func, trace, function_source, silent, parent=None): if trace is not None: if not silent: ErrorDialog( title="Function definition check", message="The syntax is not correct. The following error was found", trace=f"{trace}\n\nin the function\n\n{function_source}", parent=parent, ).exec() return False, None args = inspect.signature(func) # try with sample by sample call kwargs = {} for i, (arg_name, arg) in enumerate(args.parameters.items()): kwargs[arg_name] = arg.default trace = "" sample_by_sample = True try: res = func(**kwargs) except ZeroDivisionError: pass except: sample_by_sample = False trace = f"Sample by sample: {format_exc()}" else: if not isinstance(res, (int, float)): sample_by_sample = False trace = "Sample by sample: The function did not return a numeric scalar value" # try with complete signal call kwargs = {} for i, (arg_name, arg) in enumerate(args.parameters.items()): kwargs[arg_name] = np.ones(10000, dtype="i8") * arg.default kwargs["t"] = np.arange(10000) * 0.1 complete_signal = True try: res = func(**kwargs) except ZeroDivisionError: pass except: complete_signal = False if trace: trace += f"\n\nComplete signal: {format_exc()}" else: trace = f"Complete signal: {format_exc()}" else: if not isinstance(res, (tuple, list, np.ndarray)): complete_signal = False if trace: trace += "\n\nComplete signal: The function did not return an list, tuple or np.ndarray" else: trace = "Complete signal: The function did not return an list, tuple or np.ndarray" try: if len(np.array(res).shape) > 1: complete_signal = False if trace: trace += "\n\nComplete signal: The function returned a multi dimensional array" else: trace = "Complete signal: The function returned a multi dimensional array" except: complete_signal = False if trace: trace += f"\n\nComplete signal: {format_exc()}" else: trace = f"Complete signal: {format_exc()}" if not sample_by_sample and not complete_signal: if not silent: ErrorDialog( title="Function definition check", message="The syntax is not correct. The following error was found", trace=f"{trace}\n\nin the function\n\n{function_source}", parent=parent, ).exec() return False, None elif not sample_by_sample: if not silent: MessageBox.information( parent, "Function definition check", "The function definition appears to be correct only for complete signal mode.", ) return True, func elif not complete_signal: if not silent: MessageBox.information( parent, "Function definition check", "The function definition appears to be correct only for sample by sample mode.", ) return True, func else: if not silent: MessageBox.information( parent, "Function definition check", "The function definition appears to be correct for both sample by sample and complete signal modes.", ) return True, func def set_app_user_model_id(app_user_model_id: str) -> None: if sys.platform == "win32": ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(app_user_model_id) if __name__ == "__main__": pass asammdf-8.5.1/src/asammdf/gui/widgets/000077500000000000000000000000001502633300400175625ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/widgets/__init__.py000066400000000000000000000000001502633300400216610ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/gui/widgets/attachment.py000066400000000000000000000141171502633300400222700ustar00rootroot00000000000000from pathlib import Path from tempfile import gettempdir import threading from PySide6 import QtGui, QtWidgets from ...blocks.utils import extract_encryption_information from ...blocks.v4_constants import FLAG_AT_TO_STRING from ..ui.attachment import Ui_Attachment try: import sounddevice as sd import soundfile as sf current_frame = 0 except: current_frame = None class Attachment(Ui_Attachment, QtWidgets.QWidget): def __init__(self, index, attachment_block, file, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.extract_btn.clicked.connect(self.extract) self.file = file self.index = index self.number.setText(f"{index + 1}.") fields = [] field = QtWidgets.QTreeWidgetItem() field.setText(0, "ATBLOCK address") field.setText(1, f"0x{attachment_block.address:X}") fields.append(field) field = QtWidgets.QTreeWidgetItem() field.setText(0, "File name") field.setText(1, str(attachment_block.file_name)) fields.append(field) field = QtWidgets.QTreeWidgetItem() field.setText(0, "MIME type") field.setText(1, attachment_block.mime) fields.append(field) field = QtWidgets.QTreeWidgetItem() field.setText(0, "Comment") field.setText(1, attachment_block.comment) fields.append(field) field = QtWidgets.QTreeWidgetItem() field.setText(0, "Flags") if attachment_block.flags: flags = [] for flag, string in FLAG_AT_TO_STRING.items(): if attachment_block.flags & flag: flags.append(string) text = f"{attachment_block.flags} [0x{attachment_block.flags:X}= {', '.join(flags)}]" else: text = "0" field.setText(1, text) fields.append(field) field = QtWidgets.QTreeWidgetItem() field.setText(0, "MD5 sum") field.setText(1, attachment_block.md5_sum.hex().upper()) fields.append(field) size = attachment_block.original_size if size <= 1 << 10: text = f"{size} B" elif size <= 1 << 20: text = f"{size / 1024:.1f} KB" elif size <= 1 << 30: text = f"{size / 1024 / 1024:.1f} MB" else: text = f"{size / 1024 / 1024 / 1024:.1f} GB" field = QtWidgets.QTreeWidgetItem() field.setText(0, "Size") field.setText(1, text) fields.append(field) self.fields.addTopLevelItems(fields) self.audio_comment = None self.audio_progress = None if current_frame is not None: if attachment_block.file_name == "user_audio_comment.ogg" and attachment_block.mime == r"audio/ogg": self.audio_comment = attachment_block.extract() field = QtWidgets.QTreeWidgetItem() field.setText(0, "Audio comment") widget = QtWidgets.QWidget() layout = QtWidgets.QHBoxLayout() widget.setLayout(layout) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/play.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) if icon.isNull(): play_audio_comment_btn = QtWidgets.QPushButton("Play comment") else: play_audio_comment_btn = QtWidgets.QPushButton(widget) play_audio_comment_btn.setIcon(icon) play_audio_comment_btn.clicked.connect(self.play_audio_comment) layout.addWidget(play_audio_comment_btn) self.audio_progress = QtWidgets.QProgressBar(widget) self.audio_progress.setValue(0) self.audio_progress.setTextVisible(False) layout.addWidget(self.audio_progress) layout.setStretch(1, 1) layout.setStretch(0, 0) self.fields.addTopLevelItem(field) self.fields.setItemWidget(field, 1, widget) def extract(self, event=None): attachment = self.file.mdf.attachments[self.index] encryption_info = extract_encryption_information(attachment.comment) password = None if encryption_info.get("encrypted", False) and self.file.mdf._mdf._password is None: text, ok = QtWidgets.QInputDialog.getText( self, "Attachment password", "The attachment is encrypted. Please provide the password:", QtWidgets.QLineEdit.EchoMode.Password, ) if ok and text: password = text data, file_path, md5_sum = self.file.mdf.extract_attachment(self.index, password=password) file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select extracted file", str(file_path), "All files (*.*)", "All files (*.*)", ) if file_name: file_name = Path(file_name) file_name.write_bytes(data) def play_audio_comment(self): if self.audio_comment is None: return global current_frame tmp = Path(gettempdir()) / "daxil_audio_comment.ogg" tmp.write_bytes(self.audio_comment) data, fs = sf.read(tmp) size = len(data) current_frame = 0 playback_finished = threading.Event() def callback(outdata, frames, time, status): global current_frame chunksize = min(len(data) - current_frame, frames) outdata[:chunksize] = data[current_frame : current_frame + chunksize] if chunksize < frames: outdata[chunksize:] = 0 raise sd.CallbackStop() current_frame += chunksize self.audio_progress.setValue(int(100 * current_frame / size)) stream = sd.OutputStream( samplerate=fs, channels=data.shape[1], callback=callback, finished_callback=playback_finished.set ) with stream: playback_finished.wait() self.audio_progress.setValue(0) tmp.unlink() asammdf-8.5.1/src/asammdf/gui/widgets/bar.py000066400000000000000000000273201502633300400207040ustar00rootroot00000000000000import os import re import numpy as np from numpy import searchsorted from PySide6 import QtCore, QtGui, QtWidgets from .. import serde from ..dialogs.messagebox import MessageBox from ..ui.bar import Ui_BarDisplay from .channel_bar_display import ChannelBarDisplay from .list_item import ListItem from .plot import PlotSignal OPS = { "!=": "__ne__", "==": "__eq__", ">": "__gt__", ">=": "__ge__", "<": "__lt__", "<=": "__le__", } class Bar(Ui_BarDisplay, QtWidgets.QWidget): add_channels_request = QtCore.Signal(list) timestamp_changed_signal = QtCore.Signal(object, float) def __init__(self, signals, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) for sig in signals: sig.timestamps = np.around(sig.timestamps, 9) self.signals = {} self._min = float("inf") self._max = -float("inf") self.add_new_channels(signals) self.timestamp.valueChanged.connect(self._timestamp_changed) self.timestamp_slider.valueChanged.connect(self._timestamp_slider_changed) self._timestamp = self._min self.set_timestamp() self._inhibit = False def items_deleted(self, names): for name in names: self.signals.pop(name) self.build() def _timestamp_changed(self, stamp): if not self._inhibit: self.set_timestamp(stamp) def _timestamp_slider_changed(self, stamp): if not self._inhibit: factor = stamp / 99999 stamp = (self._max - self._min) * factor + self._min self.set_timestamp(stamp) def set_timestamp(self, stamp=None): if stamp is None: stamp = self._timestamp if not (self._min <= stamp <= self._max): return idx_cache = {} for row in range(self.channels.count()): item = self.channels.item(row) widget = self.channels.itemWidget(item) uuid = widget.uuid sig = self.signals[uuid] if len(sig): if (sig.group_index, sig.origin_uuid) in idx_cache: idx = idx_cache[(sig.group_index, sig.origin_uuid)] else: idx = min(sig.size - 1, searchsorted(sig.timestamps, stamp)) idx_cache[(sig.group_index, sig.origin_uuid)] = idx value = sig.samples[idx] widget.set_value(value) widget.bar.update() self._inhibit = True if self._min != self._max: val = int((stamp - self._min) / (self._max - self._min) * 99999) self.timestamp_slider.setValue(val) self.timestamp.setValue(stamp) self._inhibit = False self.timestamp_changed_signal.emit(self, stamp) def add_new_channels(self, channels): for index, sig in enumerate(channels): sig.uuid = os.urandom(6).hex() sig.computed = False sig.computation = None sig.color = serde.COLORS[index % serde.COLORS_COUNT] sig.size = len(sig) sig.kind = sig.samples.dtype.kind invalid = [] for channel in channels: diff = np.diff(channel.timestamps) invalid_indexes = np.argwhere(diff <= 0).ravel() if len(invalid_indexes): invalid_indexes = invalid_indexes[:10] + 1 idx = invalid_indexes[0] ts = channel.timestamps[idx - 1 : idx + 2] invalid.append(f"{channel.name} @ index {invalid_indexes[:10] - 1} with first time stamp error: {ts}") if invalid: errors = "\n".join(invalid) MessageBox.warning( self, "The following channels do not have monotonous increasing time stamps:", f"The following channels do not have monotonous increasing time stamps:\n{errors}", ) self.plot._can_trim = False valid = [] invalid = [] for channel in channels: if len(channel): samples = channel.samples if samples.dtype.kind not in "SUV" and np.all(np.isnan(samples)): invalid.append(channel.name) elif channel.conversion: samples = channel.physical().samples if samples.dtype.kind not in "SUV" and np.all(np.isnan(samples)): invalid.append(channel.name) else: valid.append(channel) else: valid.append(channel) else: valid.append(channel) if invalid: MessageBox.warning( self, "All NaN channels will not be plotted:", f"The following channels have all NaN samples and will not be plotted:\n{', '.join(invalid)}", ) channels = valid for sig in channels: sig = PlotSignal(sig) if len(sig): self._min = min(self._min, sig.timestamps[0]) self._max = max(self._max, sig.timestamps[-1]) item = ListItem( (sig.group_index, sig.channel_index), sig.name, sig.computation, self.channels, sig.origin_uuid, ) item.setData(QtCore.Qt.ItemDataRole.UserRole, sig.name) tooltip = getattr(sig, "tooltip", "") or sig.comment it = ChannelBarDisplay( sig.uuid, 0, (sig.min, sig.max), sig.max + 1, sig.color, sig.unit, 3, tooltip, self, ) it.setAttribute(QtCore.Qt.WidgetAttribute.WA_StyledBackground) if sig.computed: font = QtGui.QFont() font.setItalic(True) it.name.setFont(font) it.set_name(sig.name) it.set_color(sig.color) item.setSizeHint(it.sizeHint()) self.channels.addItem(item) self.channels.setItemWidget(item, it) self.signals[sig.uuid] = sig def keyPressEvent(self, event): key = event.key() modifier = event.modifiers() if ( key in (QtCore.Qt.Key.Key_H, QtCore.Qt.Key.Key_B, QtCore.Qt.Key.Key_P) and modifier == QtCore.Qt.KeyboardModifier.ControlModifier ): if key == QtCore.Qt.Key.Key_H: self.format_selection.setCurrentText("hex") elif key == QtCore.Qt.Key.Key_B: self.format_selection.setCurrentText("bin") else: self.format_selection.setCurrentText("phys") event.accept() elif key == QtCore.Qt.Key.Key_Right and modifier == QtCore.Qt.KeyboardModifier.NoModifier: self.timestamp_slider.setValue(self.timestamp_slider.value() + 1) elif key == QtCore.Qt.Key.Key_Left and modifier == QtCore.Qt.KeyboardModifier.NoModifier: self.timestamp_slider.setValue(self.timestamp_slider.value() - 1) else: super().keyPressEvent(event) def to_config(self): channels = [] iterator = QtWidgets.QTreeWidgetItemIterator(self.channels) while item := iterator.value(): channels.append(item.text(0)) iterator += 1 config = { "format": self.format, "channels": channels if not self.pattern else [], "pattern": self.pattern, } return config def search_forward(self): if self.op.currentIndex() < 0 or not self.target.text().strip() or not self.pattern_match.text().strip(): self.match.setText("invalid input values") return operator = self.op.currentText() wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" text = self.pattern_match.text().strip() pattern = text.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") pattern = re.compile(f"(?i){pattern}") matches = [name for name in self.signals if pattern.search(name)] if not matches: self.match.setText("the pattern does not match any channel name") return try: target = float(self.target.text().strip()) except: self.match.setText("the target must a numeric value") else: if target.is_integer(): target = int(target) start = self.timestamp.value() timestamp = None signal_name = "" for name in matches: sig = self.signals[name].cut(start=start) samples = sig.samples op = getattr(samples, OPS[operator]) try: idx = np.argwhere(op(target)).flatten() if len(idx): if len(idx) == 1 or sig.timestamps[idx[0]] != start: timestamp_ = sig.timestamps[idx[0]] else: timestamp_ = sig.timestamps[idx[1]] if timestamp is None or timestamp_ < timestamp: timestamp = timestamp_ signal_name = name except: continue if timestamp is not None: self.timestamp.setValue(timestamp) self.match.setText(f"condition found for {signal_name}") else: self.match.setText("condition not found") def search_backward(self): if self.op.currentIndex() < 0 or not self.target.text().strip() or not self.pattern_match.text().strip(): self.match.setText("invalid input values") return operator = self.op.currentText() pattern = self.pattern_match.text().strip().replace("*", "_WILDCARD_") pattern = re.escape(pattern) pattern = pattern.replace("_WILDCARD_", ".*") pattern = re.compile(f"(?i){pattern}") matches = [name for name in self.signals if pattern.search(name)] if not matches: self.match.setText("the pattern does not match any channel name") return try: target = float(self.target.text().strip()) except: self.match.setText("the target must a numeric value") else: if target.is_integer(): target = int(target) stop = self.timestamp.value() timestamp = None signal_name = "" for name in matches: sig = self.signals[name].cut(stop=stop) samples = sig.samples[:-1] op = getattr(samples, OPS[operator]) try: idx = np.argwhere(op(target)).flatten() if len(idx): if len(idx) == 1 or sig.timestamps[idx[-1]] != stop: timestamp_ = sig.timestamps[idx[-1]] else: timestamp_ = sig.timestamps[idx[-2]] if timestamp is None or timestamp_ > timestamp: timestamp = timestamp_ signal_name = name except: continue if timestamp is not None: self.timestamp.setValue(timestamp) self.match.setText(f"condition found for {signal_name}") else: self.match.setText("condition not found") def set_format(self, fmt): self.format = fmt self._settings.setValue("numeric_format", fmt) self._update_values() asammdf-8.5.1/src/asammdf/gui/widgets/batch.py000066400000000000000000002455411502633300400212300ustar00rootroot00000000000000from datetime import timezone import os from pathlib import Path from traceback import format_exc from natsort import natsorted from PySide6 import QtCore, QtGui, QtWidgets import asammdf.mdf as mdf_module from ...blocks.utils import extract_xml_comment from ...blocks.v2_v3_blocks import HeaderBlock as HeaderBlockV3 from ...blocks.v4_blocks import HeaderBlock as HeaderBlockV4 from ...blocks.v4_constants import ( BUS_TYPE_CAN, BUS_TYPE_ETHERNET, BUS_TYPE_FLEXRAY, BUS_TYPE_LIN, BUS_TYPE_USB, ) from ..dialogs.advanced_search import AdvancedSearch from ..dialogs.messagebox import MessageBox from ..serde import load_channel_names_from_file, load_lab from ..ui.batch_widget import Ui_batch_widget from ..utils import COMPRESSION_OPTIONS, GREEN, HelperChannel, setup_progress from .database_item import DatabaseItem from .tree import add_children from .tree_item import MinimalTreeItem, TreeItem class BatchWidget(Ui_batch_widget, QtWidgets.QWidget): def __init__( self, ignore_value2text_conversions=False, integer_interpolation=2, float_interpolation=1, *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self._ignore = False self._settings = QtCore.QSettings() self.ignore_value2text_conversions = ignore_value2text_conversions self.integer_interpolation = integer_interpolation self.float_interpolation = float_interpolation self.files_list.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove) self._progress = None self.progress = None self.show() sizes = sum(self.splitter.sizes()) if sizes >= 700: self.splitter.setSizes([700, sizes - 700]) self.splitter.setStretchFactor(0, 0) self.splitter.setStretchFactor(1, 1) self.raster_type_channel.toggled.connect(self.set_raster_type) self.set_raster_type() for widget in ( self.concatenate_format, self.stack_format, self.extract_bus_format, self.mdf_version, ): widget.currentTextChanged.connect(self.mdf_format_changed) for widget in ( self.concatenate_format, self.stack_format, self.extract_bus_format, self.mdf_version, ): widget.insertItems(0, mdf_module.SUPPORTED_VERSIONS) widget.setCurrentText("4.10") for widget in ( self.concatenate_split_size, self.stack_split_size, self.mdf_split_size, ): widget.setValue(4) formats = ["MDF", "ASC", "CSV"] try: from hdf5storage import savemat formats.append("MAT") except ImportError: try: from scipy.io import savemat # noqa: F401 formats.append("MAT") except ImportError: pass try: from h5py import File as HDF5 # noqa: F401 formats.append("HDF5") except ImportError: pass try: from pyarrow.parquet import write_table as write_parquet # noqa: F401 formats.append("Parquet") except ImportError: pass self.output_format.addItems(formats) self.output_format.setCurrentIndex(0) self.concatenate_btn.clicked.connect(self.concatenate) self.scramble_btn.clicked.connect(self.scramble) self.stack_btn.clicked.connect(self.stack) self.extract_bus_btn.clicked.connect(self.extract_bus_logging) self.extract_bus_csv_btn.clicked.connect(self.extract_bus_csv_logging) self.advanced_serch_filter_btn.clicked.connect(self.search) self.raster_search_btn.clicked.connect(self.raster_search) self.apply_btn.clicked.connect(self.apply_processing) self.modify_output_folder_btn.clicked.connect(self.change_modify_output_folder) self.output_format.currentTextChanged.connect(self.output_format_changed) self.sort_alphabetically_btn.clicked.connect(self.sort_alphabetically) self.sort_by_start_time_btn.clicked.connect(self.sort_by_start_time) self.filter_view.setCurrentIndex(-1) self.filter_view.currentIndexChanged.connect(self.update_channel_tree) self.filter_view.setCurrentText(self._settings.value("filter_view", "Internal file structure")) self.load_can_database_btn.clicked.connect(self.load_can_database) self.load_lin_database_btn.clicked.connect(self.load_lin_database) self.load_filter_list_btn.clicked.connect(self.load_filter_list) self.save_filter_list_btn.clicked.connect(self.save_filter_list) self.empty_channels_bus.insertItems(0, ("skip", "zeros")) self.empty_channels.insertItems(0, ("skip", "zeros")) self.empty_channels_bus.insertItems(0, ("skip", "zeros")) self.empty_channels_mat.insertItems(0, ("skip", "zeros")) self.empty_channels_csv.insertItems(0, ("skip", "zeros")) try: import scipy # noqa: F401 self.mat_format.insertItems(0, ("4", "5", "7.3")) except: self.mat_format.insertItems(0, ("7.3",)) self.oned_as.insertItems(0, ("row", "column")) self.aspects.setCurrentIndex(0) self.setAcceptDrops(True) self.files_list.model().rowsInserted.connect(self.update_channel_tree) self.files_list.itemsDeleted.connect(self.update_channel_tree) self.clear_filter_btn.clicked.connect(self.clear_filter) self.filter_tree.itemChanged.connect(self.filter_changed) self._selected_filter = set() self._filter_timer = QtCore.QTimer() self._filter_timer.setSingleShot(True) self._filter_timer.timeout.connect(self.update_selected_filter_channels) databases = {} can_databases = self._settings.value("can_databases", None) or [] buses = can_databases[::2] dbs = can_databases[1::2] databases["CAN"] = list(zip(buses, dbs, strict=False)) lin_databases = self._settings.value("lin_databases", None) or [] buses = lin_databases[::2] dbs = lin_databases[1::2] databases["LIN"] = list(zip(buses, dbs, strict=False)) for bus, database in databases["CAN"]: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="CAN") widget.bus.setCurrentText(bus) self.can_database_list.addItem(item) self.can_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) for bus, database in databases["LIN"]: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="LIN") widget.bus.setCurrentText(bus) self.lin_database_list.addItem(item) self.lin_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) self.restore_export_settings() self.connect_export_updates() @QtCore.Slot(str) def mdf_format_changed(self, format): sender = self.sender() options = COMPRESSION_OPTIONS.get(format, ()) if sender is self.concatenate_format: self.concatenate_compression.clear() self.concatenate_compression.addItems(options) elif sender is self.stack_format: self.stack_compression.clear() self.stack_compression.addItems(options) elif sender is self.extract_bus_format: self.extract_bus_compression.clear() self.extract_bus_compression.addItems(options) elif sender is self.mdf_version: self.mdf_compression.clear() self.mdf_compression.addItems(options) def set_raster_type(self, event=None): if self.raster_type_channel.isChecked(): self.raster_channel.setEnabled(True) self.raster_search_btn.setEnabled(True) self.raster.setEnabled(False) self.raster.setValue(0) else: self.raster_search_btn.setEnabled(False) self.raster_channel.setEnabled(False) self.raster.setEnabled(True) self.raster_channel.setCurrentIndex(0) def export_changed(self, name): if name == "parquet": self.export_compression.setEnabled(True) self.export_compression.clear() self.export_compression.addItems(["GZIP", "SNAPPY", "LZ4"]) self.export_compression.setCurrentIndex(-1) elif name == "hdf5": self.export_compression.setEnabled(True) self.export_compression.clear() self.export_compression.addItems(["gzip", "lzf", "szip"]) self.export_compression.setCurrentIndex(-1) elif name == "mat": self.export_compression.setEnabled(True) self.export_compression.clear() self.export_compression.addItems(["enabled", "disabled"]) self.export_compression.setCurrentIndex(-1) else: self.export_compression.clear() self.export_compression.setEnabled(False) def update_progress(self, current_index, max_index): self.progress = current_index, max_index def scramble_thread(self, source_files, progress): count = len(source_files) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/scramble.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Scrambling measurements") # scrambling self.mdf for i, source_file in enumerate(source_files): progress.signals.setLabelText.emit(f"Scrambling file {i + 1} of {count}\n{source_file}") mdf_module.MDF.scramble(name=source_file, progress=progress) def scramble_finished(self): self._progress = None def scramble(self, event): count = self.files_list.count() source_files = [Path(self.files_list.item(row).text()) for row in range(count)] if not count: return self._progress = setup_progress(parent=self, autoclose=False) self._progress.finished.connect(self.scramble_finished) self._progress.run_thread_with_progress( target=self.scramble_thread, args=(source_files,), kwargs={}, ) def extract_bus_logging_finished(self): if self._progress.error is None: message = self._progress.result self.output_info_bus.setPlainText("\n".join(message)) self._progress = None def extract_bus_logging(self, event): version = self.extract_bus_format.currentText() self.output_info_bus.setPlainText("") database_files = {} count1 = self.can_database_list.count() if count1: database_files["CAN"] = [] for i in range(count1): item = self.can_database_list.item(i) widget = self.can_database_list.itemWidget(item) database_files["CAN"].append((widget.database.text(), widget.bus.currentIndex())) count2 = self.lin_database_list.count() if count2: database_files["LIN"] = [] for i in range(count2): item = self.lin_database_list.item(i) widget = self.lin_database_list.itemWidget(item) database_files["LIN"].append((widget.database.text(), widget.bus.currentIndex())) compression = self.extract_bus_compression.currentIndex() count = self.files_list.count() if not count or not (count1 + count2): return source_files = [Path(self.files_list.item(row).text()) for row in range(count)] self._progress = setup_progress(parent=self) self._progress.finished.connect(self.extract_bus_logging_finished) self._progress.run_thread_with_progress( target=self.extract_bus_logging_thread, args=(source_files, database_files, count, compression, version), kwargs={}, ) def extract_bus_logging_thread(self, source_files, database_files, count, compression, version, progress): icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/down.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Extract Bus logging from measurements") progress.signals.setLabelText.emit(f'Extracting Bus logging from "{count}" files') files = self._prepare_files(list(source_files), progress) message = [] progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(count) for i, (file, source_file) in enumerate(zip(files, source_files, strict=False)): progress.signals.setLabelText.emit(f"Extracting Bus logging from file {i + 1} of {count}\n{source_file}") if not isinstance(file, mdf_module.MDF): mdf = mdf_module.MDF(file) else: mdf = file mdf_ = mdf.extract_bus_logging( database_files=database_files, version=version, prefix=self.prefix.text().strip(), progress=progress, ) bus_call_info = dict(mdf.last_call_info) for bus, call_info in bus_call_info.items(): found_id_count = sum(len(e) for e in call_info["found_ids"].values()) message += [ "", f'Summary of "{mdf.name}":', f"- {found_id_count} of {len(call_info['total_unique_ids'])} IDs in the MDF4 file were matched in the DBC and converted", ] if call_info["unknown_id_count"]: message.append(f"- {call_info['unknown_id_count']} unknown IDs in the MDF4 file") else: message.append("- no unknown IDs in the MDF4 file") message += [ "", "Detailed information:", "", "The following Bus IDs were in the MDF log file and matched in the DBC:", ] for dbc_name, found_ids in call_info["found_ids"].items(): for msg_id, msg_name in sorted(found_ids): if not msg_id[2]: msg_id, extended = msg_id[:2] message.append(f"- 0x{msg_id:X} {extended=} --> {msg_name} in <{dbc_name}>") else: pgn, sa = msg_id[:2] message.append(f"- PGN=0x{pgn:X} SA=0x{sa:X} --> {msg_name} in <{dbc_name}>") message += [ "", "The following Bus IDs were in the MDF log file, but not matched in the DBC:", ] unknown_standard_can = sorted([e for e in call_info["unknown_ids"] if isinstance(e, int)]) unknown_j1939 = sorted([e for e in call_info["unknown_ids"] if not isinstance(e, int)]) for msg_id in unknown_standard_can: message.append(f"- 0x{msg_id:X}") for pgn, sa in unknown_j1939: message.append(f"- PGN=0x{pgn:X} SA=0x{sa:X}") file_name = source_file.with_suffix(".bus_logging.mdf" if version < "4.00" else ".bus_logging.mf4") # then save it progress.signals.setLabelText.emit(f'Saving extracted Bus logging file {i + 1} to "{file_name}"') try: mdf_.save( dst=file_name, compression=compression, overwrite=True, progress=progress, ) finally: mdf.close() return message def extract_bus_csv_logging_finished(self): if self._progress.error is None: message = self._progress.result self.output_info_bus.setPlainText("\n".join(message)) self._progress = None def extract_bus_csv_logging(self, event): version = self.extract_bus_format.currentText() self.output_info_bus.setPlainText("") database_files = {} count1 = self.can_database_list.count() if count1: database_files["CAN"] = [] for i in range(count1): item = self.can_database_list.item(i) widget = self.can_database_list.itemWidget(item) database_files["CAN"].append((widget.database.text(), widget.bus.currentIndex())) count2 = self.lin_database_list.count() if count2: database_files["LIN"] = [] for i in range(count2): item = self.lin_database_list.item(i) widget = self.lin_database_list.itemWidget(item) database_files["LIN"].append((widget.database.text(), widget.bus.currentIndex())) single_time_base = self.single_time_base_bus.checkState() == QtCore.Qt.CheckState.Checked time_from_zero = self.time_from_zero_bus.checkState() == QtCore.Qt.CheckState.Checked empty_channels = self.empty_channels_bus.currentText() raster = self.export_raster_bus.value() or None time_as_date = self.bus_time_as_date.checkState() == QtCore.Qt.CheckState.Checked delimiter = self.delimiter_bus.text() or "," doublequote = self.doublequote_bus.checkState() == QtCore.Qt.CheckState.Checked escapechar = self.escapechar_bus.text() or None lineterminator = self.lineterminator_bus.text().replace("\\r", "\r").replace("\\n", "\n") quotechar = self.quotechar_bus.text() or '"' quoting = self.quoting_bus.currentText() add_units = self.add_units_bus.checkState() == QtCore.Qt.CheckState.Checked if delimiter == "\\t": delimiter = "\t" count = self.files_list.count() if not count or not (count1 + count2): return source_files = [Path(self.files_list.item(row).text()) for row in range(count)] self._progress = setup_progress(parent=self) self._progress.finished.connect(self.extract_bus_csv_logging_finished) self._progress.run_thread_with_progress( target=self.extract_bus_csv_logging_thread, args=( source_files, database_files, version, single_time_base, time_from_zero, empty_channels, raster, time_as_date, delimiter, doublequote, escapechar, lineterminator, quotechar, quoting, add_units, count, ), kwargs={}, ) def extract_bus_csv_logging_thread( self, source_files, database_files, version, single_time_base, time_from_zero, empty_channels, raster, time_as_date, delimiter, doublequote, escapechar, lineterminator, quotechar, quoting, add_units, count, progress, ): icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/csv.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Extract Bus logging from measurements to CSV") progress.signals.setLabelText.emit(f'Extracting Bus logging from "{count}" files') files = self._prepare_files(list(source_files), progress) message = [] for i, (file, source_file) in enumerate(zip(files, source_files, strict=False)): progress.signals.setLabelText.emit(f"Extracting Bus logging from file {i + 1} of {count}") if not isinstance(file, mdf_module.MDF): mdf = mdf_module.MDF(file) else: mdf = file mdf_ = mdf.extract_bus_logging( database_files=database_files, version=version, prefix=self.prefix.text().strip(), progress=progress, ) bus_call_info = dict(mdf.last_call_info) for bus, call_info in bus_call_info.items(): found_id_count = sum(len(e) for e in call_info["found_ids"].values()) message += [ "", f'Summary of "{mdf.name}":', f"- {found_id_count} of {len(call_info['total_unique_ids'])} IDs in the MDF4 file were matched in the DBC and converted", ] if call_info["unknown_id_count"]: message.append(f"- {call_info['unknown_id_count']} unknown IDs in the MDF4 file") else: message.append("- no unknown IDs in the MDF4 file") message += [ "", "Detailed information:", "", "The following Bus IDs were in the MDF log file and matched in the DBC:", ] for dbc_name, found_ids in call_info["found_ids"].items(): for msg_id, msg_name in sorted(found_ids): if isinstance(msg_id, str): message.append(f"- 0x{msg_id:X} --> {msg_name} in <{dbc_name}>") else: message.append(f"- 0x{msg_id[0]:X} --> {msg_name} in <{dbc_name}>") message += [ "", "The following Bus IDs were in the MDF log file, but not matched in the DBC:", ] for msg_id in sorted(call_info["unknown_ids"]): message.append(f"- 0x{msg_id:X}") file_name = source_file.with_suffix(".bus_logging.csv") # then save it progress.signals.setLabelText.emit(f'Saving extracted Bus logging file {i + 1} to "{file_name}"') mdf_.configure( integer_interpolation=self.integer_interpolation, float_interpolation=self.float_interpolation, ) try: mdf_.export( fmt="csv", filename=file_name, single_time_base=single_time_base, time_from_zero=time_from_zero, empty_channels=empty_channels, raster=raster or None, time_as_date=time_as_date, ignore_value2text_conversions=self.ignore_value2text_conversions, delimiter=delimiter, doublequote=doublequote, escapechar=escapechar, lineterminator=lineterminator, quotechar=quotechar, quoting=quoting, add_units=add_units, progress=progress, ) finally: mdf.close() return message def load_can_database(self, event): file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select CAN database file", "", "ARXML or DBC (*.dbc *.arxml)", "ARXML or DBC (*.dbc *.arxml)", ) if file_names: file_names = [name for name in file_names if Path(name).suffix.lower() in (".arxml", ".dbc")] if file_names: for database in file_names: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="CAN") self.can_database_list.addItem(item) self.can_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) def load_lin_database(self, event): file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select LIN database file", "", "ARXML or DBC database (*.dbc *.arxml);;LDF database (*.ldf);;All supported formats (*.dbc *.arxml *ldf)", "All supported formats (*.dbc *.arxml *ldf)", ) if file_names: file_names = [name for name in file_names if Path(name).suffix.lower() in (".arxml", ".dbc", ".ldf")] if file_names: for database in file_names: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="LIN") self.lin_database_list.addItem(item) self.lin_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) def concatenate_finished(self): self._progress = None def concatenate(self, event=None): count = self.files_list.count() if not count: return version = self.concatenate_format.currentText() sync = self.concatenate_sync.checkState() == QtCore.Qt.CheckState.Checked add_samples_origin = self.concatenate_add_samples_origin.checkState() == QtCore.Qt.CheckState.Checked split = self.concatenate_split.checkState() == QtCore.Qt.CheckState.Checked if split: split_size = int(self.concatenate_split_size.value() * 1024 * 1024) else: split_size = 0 compression = self.concatenate_compression.currentIndex() if version < "4.00": output_file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output measurement file", "", "MDF version 3 files (*.dat *.mdf);;All files (*.*)", "MDF version 3 files (*.dat *.mdf)", ) else: output_file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output measurement file", "", "MDF version 4 files (*.mf4 *.mf4z);;All files (*.*)", "MDF version 4 files (*.mf4 *.mf4z)", ) if not output_file_name: return source_files = [Path(self.files_list.item(row).text()) for row in range(count)] self._progress = setup_progress(parent=self, autoclose=False) self._progress.finished.connect(self.concatenate_finished) rez = self._progress.run_thread_with_progress( target=self.concatenate_thread, args=( output_file_name, version, source_files, sync, add_samples_origin, split_size, compression, ), kwargs={}, ) def concatenate_thread( self, output_file_name, version, source_files, sync, add_samples_origin, split_size, compression, progress, ): icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/plus.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit(f"Concatenating files and saving to {version} format") output_file_name = Path(output_file_name) files = self._prepare_files(source_files, progress) try: mdf = mdf_module.MDF.concatenate( files=files, version=version, sync=sync, add_samples_origin=add_samples_origin, progress=progress, ) finally: for file in files: file.close() mdf.configure(write_fragment_size=split_size) # save it progress.signals.setLabelText.emit(f'Saving output file "{output_file_name}"') try: mdf.save( dst=output_file_name, compression=compression, overwrite=True, progress=progress, ) finally: mdf.close() def stack_thread( self, output_file_name, version, source_files, sync, add_samples_origin, split_size, compression, progress, ): icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/stack.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit(f"Stacking files and saving to {version} format") output_file_name = Path(output_file_name) files = self._prepare_files(source_files, progress) mdf = mdf_module.MDF.stack( files=files, version=version, sync=sync, add_samples_origin=add_samples_origin, progress=progress, ) mdf.configure(write_fragment_size=split_size) # save it progress.signals.setLabelText.emit(f'Saving output file "{output_file_name}"') try: result = mdf.save( dst=output_file_name, compression=compression, overwrite=True, progress=progress, ) finally: for file in files: file.close() mdf.close() return result def stack_finished(self): self._progress = None def stack(self, event): count = self.files_list.count() if not count: return version = self.stack_format.currentText() sync = self.stack_sync.checkState() == QtCore.Qt.CheckState.Checked add_samples_origin = self.stack_add_samples_origin.checkState() == QtCore.Qt.CheckState.Checked split = self.stack_split.checkState() == QtCore.Qt.CheckState.Checked if split: split_size = int(self.stack_split_size.value() * 1024 * 1024) else: split_size = 0 compression = self.stack_compression.currentIndex() if version < "4.00": output_file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output measurement file", "", "MDF version 3 files (*.dat *.mdf);;All files (*.*)", "MDF version 3 files (*.dat *.mdf)", ) else: output_file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output measurement file", "", "MDF version 4 files (*.mf4 *.mf4z);;All files (*.*)", "MDF version 4 files (*.mf4 *.mf4z)", ) if not output_file_name: return source_files = [Path(self.files_list.item(row).text()) for row in range(count)] self._progress = setup_progress(parent=self, autoclose=False) self._progress.finished.connect(self.stack_finished) self._progress.run_thread_with_progress( target=self.stack_thread, args=( output_file_name, version, source_files, sync, add_samples_origin, split_size, compression, ), kwargs={}, ) def _as_mdf(self, file_name): file_name = Path(file_name) suffix = file_name.suffix.lower() if suffix in (".erg", ".bsig", ".dl3", ".tdms"): try: from mfile import BSIG, DL3, ERG, TDMS except ImportError: print(format_exc()) from cmerg import BSIG, ERG if suffix == ".erg": cls = ERG elif suffix == ".bsig": cls = BSIG elif suffix == ".tdms": cls = TDMS else: cls = DL3 mdf = cls(file_name).export_mdf() mdf.original_name = file_name elif suffix in (".mdf", ".mf4", ".mf4z"): mdf = mdf_module.MDF(file_name) else: raise ValueError(f"Incompatible suffix '{suffix}'") return mdf def _prepare_files(self, files=None, progress=None): if files is None: files = [Path(self.files_list.item(row).text()) for row in range(self.files_list.count())] count = len(files) progress.signals.setMaximum.emit(count) progress.signals.setValue.emit(0) progress.signals.setWindowTitle.emit("Preparing measurements") mdf_files = [] for i, file_name in enumerate(files): if progress.stop: return [] progress.signals.setLabelText.emit(f"Preparing the file {i + 1} of {count}\n{file_name.name}") try: mdf = self._as_mdf(file_name) except: print(format_exc()) mdf = None mdf_files.append(mdf) progress.signals.setValue.emit(i + 1) return mdf_files def _get_filtered_channels(self): iterator = QtWidgets.QTreeWidgetItemIterator(self.filter_tree) channels = [] while item := iterator.value(): iterator += 1 group, index = item.entry if index == 0xFFFFFFFFFFFFFFFF: continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: channels.append((item.name, group, index)) needs_filter = self.selected_filter_channels.count() > 0 return needs_filter, channels def raster_search(self, event): if not self.files_list.count(): return with mdf_module.MDF(self.files_list.item(0).text()) as mdf: dlg = AdvancedSearch( mdf, show_add_window=False, show_pattern=False, show_apply=True, parent=self, return_names=True, apply_text="Set raster channel", ) dlg.setModal(True) dlg.exec_() result = dlg.result if result: name = list(result)[0] self.raster_channel.setCurrentText(name) def filter_changed(self, item, column=0): name = item.text(0) if item.checkState(0) == QtCore.Qt.CheckState.Checked: self._selected_filter.add(name) else: if name in self._selected_filter: self._selected_filter.remove(name) self._filter_timer.start(10) def update_selected_filter_channels(self, *args): self.selected_filter_channels.clear() self.selected_filter_channels.addItems(sorted(self._selected_filter)) def search(self, event=None): count = self.files_list.count() if not count: return source_files = [Path(self.files_list.item(row).text()) for row in range(count)] for file_name in source_files: if file_name.suffix.lower() in (".mdf", ".mf4"): break else: file_name = source_files[0] mdf = self._as_mdf(file_name) try: widget = self.filter_tree view = self.filter_view dlg = AdvancedSearch( mdf, show_add_window=False, show_pattern=False, parent=self, show_apply=True, apply_text="Check signals", ) dlg.setModal(True) dlg.exec_() result = dlg.result if result: if view.currentText() == "Internal file structure": iterator = QtWidgets.QTreeWidgetItemIterator(widget) dg_cntr = -1 ch_cntr = 0 while item := iterator.value(): if item.parent() is None: iterator += 1 dg_cntr += 1 ch_cntr = 0 continue if (dg_cntr, ch_cntr) in result: item.setCheckState(0, QtCore.Qt.CheckState.Checked) iterator += 1 ch_cntr += 1 elif view.currentText() == "Selected channels only": iterator = QtWidgets.QTreeWidgetItemIterator(widget) signals = set() while item := iterator.value(): if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.add(item.entry) iterator += 1 signals = signals | set(result) widget.clear() self._selected_filter.clear() uuid = os.urandom(6).hex() items = [] for entry in signals: gp_index, ch_index = entry ch = mdf.groups[gp_index].channels[ch_index] channel = MinimalTreeItem(entry, ch.name, strings=[ch.name], origin_uuid=uuid) channel.setCheckState(0, QtCore.Qt.CheckState.Checked) items.append(channel) self._selected_filter.add(ch.name) if len(items) < 30000: items = natsorted(items, key=lambda x: x.name) else: items.sort(key=lambda x: x.name) widget.addTopLevelItems(items) self.update_selected_filter_channels() else: iterator = QtWidgets.QTreeWidgetItemIterator(widget) while item := iterator.value(): if item.entry in result: item.setCheckState(0, QtCore.Qt.CheckState.Checked) iterator += 1 except: print(format_exc()) finally: mdf.close() def update_channel_tree(self, *args): if self.filter_view.currentIndex() == -1 or self._ignore: return count = self.files_list.count() source_files = [Path(self.files_list.item(row).text()) for row in range(count)] if not count: self.filter_tree.clear() self.raster_channel.clear() return else: uuid = os.urandom(6).hex() for file_name in source_files: if file_name.suffix.lower() in (".mdf", ".mf4"): break else: file_name = source_files[0] mdf = self._as_mdf(file_name) self.raster_channel.clear() if not self.raster_channel.count(): self.raster_channel.setSizeAdjustPolicy( QtWidgets.QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon ) self.raster_channel.addItems(sorted(mdf.channels_db, key=lambda x: x.lower())) self.raster_channel.setMinimumWidth(100) try: widget = self.filter_tree view = self.filter_view iterator = QtWidgets.QTreeWidgetItemIterator(widget) signals = set() if widget.mode == "Internal file structure": while item := iterator.value(): if item.entry[1] != 0xFFFFFFFFFFFFFFFF: if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.add(item.entry) iterator += 1 else: while item := iterator.value(): if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.add(item.entry) iterator += 1 widget.clear() widget.mode = view.currentText() if widget.mode == "Natural sort": items = [] for i, group in enumerate(mdf.groups): for j, ch in enumerate(group.channels): entry = i, j channel = MinimalTreeItem(entry, ch.name, strings=[ch.name], origin_uuid=uuid) channel.setToolTip(0, f"{ch.name} @ group {i}, index {j}") if entry in signals: channel.setCheckState(0, QtCore.Qt.CheckState.Checked) else: channel.setCheckState(0, QtCore.Qt.CheckState.Unchecked) items.append(channel) if len(items) < 30000: items = natsorted(items, key=lambda x: x.name) else: items.sort(key=lambda x: x.name) widget.addTopLevelItems(items) elif widget.mode == "Internal file structure": items = [] for i, group in enumerate(mdf.groups): entry = i, 0xFFFFFFFFFFFFFFFF channel_group = MinimalTreeItem(entry, origin_uuid=uuid) comment = extract_xml_comment(group.channel_group.comment) if mdf.version >= "4.00" and group.channel_group.acq_source: source = group.channel_group.acq_source if source.bus_type == BUS_TYPE_CAN: ico = ":/bus_can.png" elif source.bus_type == BUS_TYPE_LIN: ico = ":/bus_lin.png" elif source.bus_type == BUS_TYPE_ETHERNET: ico = ":/bus_eth.png" elif source.bus_type == BUS_TYPE_USB: ico = ":/bus_usb.png" elif source.bus_type == BUS_TYPE_FLEXRAY: ico = ":/bus_flx.png" else: ico = None if ico is not None: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(ico), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) channel_group.setIcon(0, icon) acq_name = getattr(group.channel_group, "acq_name", "") if acq_name: base_name = f"CG {i} {acq_name}" else: base_name = f"CG {i}" if comment and acq_name != comment: name = base_name + f" ({comment})" else: name = base_name channel_group.setText(0, name) channel_group.setFlags( channel_group.flags() | QtCore.Qt.ItemFlag.ItemIsAutoTristate | QtCore.Qt.ItemFlag.ItemIsUserCheckable ) if group.channel_group.cycles_nr: channel_group.setForeground(0, QtGui.QBrush(QtGui.QColor(GREEN))) items.append(channel_group) channels = [HelperChannel(name=ch.name, entry=(i, j)) for j, ch in enumerate(group.channels)] add_children( channel_group, channels, group.channel_dependencies, signals, entries=None, origin_uuid=uuid, version=mdf.version, ) widget.addTopLevelItems(items) else: items = [] for entry in signals: gp_index, ch_index = entry ch = mdf.groups[gp_index].channels[ch_index] channel = MinimalTreeItem(entry, ch.name, strings=[ch.name], origin_uuid=uuid) channel.setToolTip(0, f"{ch.name} @ group {gp_index}, index {ch_index}") channel.setCheckState(0, QtCore.Qt.CheckState.Checked) items.append(channel) if len(items) < 30000: items = natsorted(items, key=lambda x: x.name) else: items.sort(key=lambda x: x.name) widget.addTopLevelItems(items) except: print(format_exc()) finally: mdf.close() def _current_options(self): options = { "needs_cut": self.cut_group.isChecked(), "cut_start": self.cut_start.value(), "cut_stop": self.cut_stop.value(), "cut_time_from_zero": self.cut_time_from_zero.checkState() == QtCore.Qt.CheckState.Checked, "whence": int(self.whence.checkState() == QtCore.Qt.CheckState.Checked), "needs_resample": self.resample_group.isChecked(), "raster_type_step": self.raster_type_step.isChecked(), "raster_type_channel": self.raster_type_channel.isChecked(), "raster": self.raster.value(), "raster_channel": self.raster_channel.currentText(), "resample_time_from_zero": self.resample_time_from_zero.checkState() == QtCore.Qt.CheckState.Checked, "output_format": self.output_format.currentText(), } output_format = self.output_format.currentText() if output_format == "MDF": new = { "mdf_version": self.mdf_version.currentText(), "mdf_compression": self.mdf_compression.currentIndex(), "mdf_split": self.mdf_split.checkState() == QtCore.Qt.CheckState.Checked, "mdf_split_size": self.mdf_split_size.value() * 1024 * 1024, } elif output_format == "MAT": new = { "single_time_base": self.single_time_base_mat.checkState() == QtCore.Qt.CheckState.Checked, "time_from_zero": self.time_from_zero_mat.checkState() == QtCore.Qt.CheckState.Checked, "time_as_date": self.time_as_date_mat.checkState() == QtCore.Qt.CheckState.Checked, "use_display_names": self.use_display_names_mat.checkState() == QtCore.Qt.CheckState.Checked, "reduce_memory_usage": self.reduce_memory_usage_mat.checkState() == QtCore.Qt.CheckState.Checked, "compression": self.export_compression_mat.currentText() == "enabled", "empty_channels": self.empty_channels_mat.currentText(), "mat_format": self.mat_format.currentText(), "oned_as": self.oned_as.currentText(), "raw": self.raw_mat.checkState() == QtCore.Qt.CheckState.Checked, } elif output_format == "CSV": new = { "single_time_base": self.single_time_base_csv.checkState() == QtCore.Qt.CheckState.Checked, "time_from_zero": self.time_from_zero_csv.checkState() == QtCore.Qt.CheckState.Checked, "time_as_date": self.time_as_date_csv.checkState() == QtCore.Qt.CheckState.Checked, "use_display_names": self.use_display_names_csv.checkState() == QtCore.Qt.CheckState.Checked, "reduce_memory_usage": False, "compression": False, "empty_channels": self.empty_channels_csv.currentText(), "raw": self.raw_csv.checkState() == QtCore.Qt.CheckState.Checked, "delimiter": self.delimiter.text() or ",", "doublequote": self.doublequote.checkState() == QtCore.Qt.CheckState.Checked, "escapechar": self.escapechar.text() or None, "lineterminator": self.lineterminator.text().replace("\\r", "\r").replace("\\n", "\n"), "quotechar": self.quotechar.text() or '"', "quoting": self.quoting.currentText(), "mat_format": None, "oned_as": None, } else: new = { "single_time_base": self.single_time_base.checkState() == QtCore.Qt.CheckState.Checked, "time_from_zero": self.time_from_zero.checkState() == QtCore.Qt.CheckState.Checked, "time_as_date": self.time_as_date.checkState() == QtCore.Qt.CheckState.Checked, "use_display_names": self.use_display_names.checkState() == QtCore.Qt.CheckState.Checked, "reduce_memory_usage": self.reduce_memory_usage.checkState() == QtCore.Qt.CheckState.Checked, "compression": self.export_compression.currentText(), "empty_channels": self.empty_channels.currentText(), "mat_format": None, "oned_as": None, "raw": self.raw.checkState() == QtCore.Qt.CheckState.Checked, } options.update(new) class Options: def __init__(self, opts): self._opts = opts for k, v in opts.items(): setattr(self, k, v) return Options(options) def apply_processing_finished(self): self._progress = None def apply_processing(self, event): opts = self._current_options() output_format = opts.output_format if output_format == "HDF5": try: from h5py import File as HDF5 # noqa: F401 except ImportError: MessageBox.critical( self, "export_batch to HDF5 unavailale", "h5py package not found; export to HDF5 is unavailable", ) return elif output_format == "MAT": if opts.mat_format == "7.3": try: from hdf5storage import savemat except ImportError: MessageBox.critical( self, "export_batch to mat v7.3 unavailale", "hdf5storage package not found; export to mat 7.3 is unavailable", ) return else: try: from scipy.io import savemat # noqa: F401 except ImportError: MessageBox.critical( self, "export_batch to mat v4 and v5 unavailale", "scipy package not found; export to mat is unavailable", ) return elif output_format == "Parquet": try: from pyarrow.parquet import write_table as write_parquet # noqa: F401 except ImportError: MessageBox.critical( self, "export_batch to parquet unavailale", "pyarrow package not found; export to parquet is unavailable", ) return self._progress = setup_progress(parent=self, autoclose=False) self._progress.finished.connect(self.apply_processing_finished) self._progress.run_thread_with_progress( target=self.apply_processing_thread, args=(), kwargs={}, ) def apply_processing_thread(self, progress): count = self.files_list.count() source_files = [Path(self.files_list.item(row).text()) for row in range(count)] if not count: return opts = self._current_options() output_format = opts.output_format if output_format == "MDF": version = opts.mdf_version if output_format == "HDF5": suffix = ".hdf" from h5py import File as HDF5 # noqa: F401 elif output_format == "MAT": suffix = ".mat" if opts.mat_format == "7.3": from hdf5storage import savemat else: from scipy.io import savemat # noqa: F401 elif output_format == "Parquet": suffix = ".parquet" from pyarrow.parquet import write_table as write_parquet # noqa: F401 elif output_format == "CSV": suffix = ".csv" elif output_format == "ASC": suffix = ".asc" needs_filter, channels = self._get_filtered_channels() output_folder = self.modify_output_folder.text().strip() if output_folder: output_folder = Path(output_folder) else: output_folder = None try: if len(source_files) == 1: root = source_files[0].parent else: root = Path(os.path.commonpath(source_files)) except ValueError: root = None split_size = opts.mdf_split_size if output_format == "MDF" else 0 integer_interpolation = self.integer_interpolation float_interpolation = self.float_interpolation files = self._prepare_files(list(source_files), progress) for mdf_index, (mdf_file, source_file) in enumerate(zip(files, source_files, strict=False)): if mdf_file is None: continue mdf_file.configure( read_fragment_size=split_size, integer_interpolation=self.integer_interpolation, float_interpolation=self.float_interpolation, ) mdf = mdf_file if needs_filter: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/filter.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit(f"Filtering measurement {mdf_index + 1} of {count}") progress.signals.setLabelText.emit(f'Filtering selected channels from\n"{source_file}"') # filtering self.mdf result = mdf.filter( channels=channels, version=opts.mdf_version if output_format == "MDF" else "4.10", progress=progress, ) mdf.close() mdf = result mdf.configure( read_fragment_size=split_size, write_fragment_size=split_size, integer_interpolation=integer_interpolation, float_interpolation=float_interpolation, ) if opts.needs_cut: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/cut.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit(f"Cutting measurement {mdf_index + 1} of {count}") progress.signals.setLabelText.emit( f"Cutting from {opts.cut_start}s to {opts.cut_stop}s from \n{source_file}" ) # cut self.mdf target = mdf.cut result = target( start=opts.cut_start, stop=opts.cut_stop, whence=opts.whence, version=opts.mdf_version if output_format == "MDF" else "4.10", time_from_zero=opts.cut_time_from_zero, progress=progress, ) mdf.close() mdf = result mdf.configure( read_fragment_size=split_size, write_fragment_size=split_size, integer_interpolation=integer_interpolation, float_interpolation=float_interpolation, ) if opts.needs_resample: if opts.raster_type_channel: raster = opts.raster_channel message = f'Resampling using channel "{raster}"\n{source_file}' else: raster = opts.raster message = f"Resampling to {raster}s raster\n{source_file}" icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/resample.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit(f"Resampling measurement {mdf_index + 1} of {count}") progress.signals.setLabelText.emit(message) # resample self.mdf target = mdf.resample result = target( raster=raster, version=opts.mdf_version if output_format == "MDF" else "4.10", time_from_zero=opts.resample_time_from_zero, progress=progress, ) mdf.close() mdf = result mdf.configure( read_fragment_size=split_size, write_fragment_size=split_size, integer_interpolation=integer_interpolation, float_interpolation=float_interpolation, ) if output_format == "MDF": if mdf.version != version: icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(":/convert.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off, ) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit(f"Converting measurement {mdf_index + 1} of {count}") progress.signals.setLabelText.emit(f'Converting "{source_file}" from {mdf.version} to {version}') # convert self.mdf result = mdf.convert( version=version, progress=progress, ) mdf.close() mdf = result if version >= "4.00": suffix = ".mf4" else: suffix = ".mdf" mdf.configure( read_fragment_size=split_size, write_fragment_size=split_size, integer_interpolation=self.integer_interpolation, float_interpolation=self.float_interpolation, ) if output_folder is not None: if root is None: file_name = output_folder / Path(mdf_file.original_name).name else: file_name = output_folder / Path(mdf_file.original_name).relative_to(root) if not file_name.parent.exists(): os.makedirs(file_name.parent, exist_ok=True) else: file_name = Path(mdf_file.original_name) file_name = file_name.parent / (file_name.stem + ".modified" + suffix) file_name = file_name.with_suffix(suffix) # then save it icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/save.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit(f"Saving measurement {mdf_index + 1} of {count}") progress.signals.setLabelText.emit(f"Saving output file {mdf_index + 1} of {count}\n{source_file}") try: result = mdf.save( dst=file_name, compression=opts.mdf_compression, overwrite=True, progress=progress, ) finally: mdf.close() else: if output_folder is not None: if root is None: file_name = output_folder / Path(mdf_file.original_name).name else: file_name = output_folder / Path(mdf_file.original_name).relative_to(root) if not file_name.parent.exists(): os.makedirs(file_name.parent, exist_ok=True) else: file_name = Path(mdf_file.original_name) file_name = file_name.with_suffix(suffix) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/export.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit(f"export_batch measurement {mdf_index + 1} of {count}") progress.signals.setLabelText.emit( f"export_batching measurement {mdf_index + 1} of {count} to {output_format} (be patient this might take a while)\n{source_file}" ) delimiter = self.delimiter.text() or "," doublequote = self.doublequote.checkState() == QtCore.Qt.CheckState.Checked escapechar = self.escapechar.text() or None lineterminator = self.lineterminator.text().replace("\\r", "\r").replace("\\n", "\n") quotechar = self.quotechar.text() or '"' quoting = self.quoting.currentText() add_units = self.add_units.checkState() == QtCore.Qt.CheckState.Checked if delimiter == "\\t": delimiter = "\t" target = mdf.export kwargs = { "fmt": opts.output_format.lower(), "filename": file_name, "single_time_base": opts.single_time_base, "use_display_names": opts.use_display_names, "time_from_zero": opts.time_from_zero, "empty_channels": opts.empty_channels, "format": opts.mat_format, "raster": None, "oned_as": opts.oned_as, "reduce_memory_usage": opts.reduce_memory_usage, "compression": opts.compression, "time_as_date": opts.time_as_date, "ignore_value2text_conversions": self.ignore_value2text_conversions, "raw": opts.raw, "delimiter": delimiter, "doublequote": doublequote, "escapechar": escapechar, "lineterminator": lineterminator, "quotechar": quotechar, "quoting": quoting, "add_units": add_units, } target(**kwargs) mdf.close() def change_modify_output_folder(self, event=None): folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select output folder", "") if folder: self.modify_output_folder.setText(str(Path(folder))) def output_format_changed(self, name): if name == "MDF": self.output_options.setCurrentWidget(self.MDF) elif name == "MAT": self.output_options.setCurrentWidget(self.MAT) self.export_compression_mat.clear() self.export_compression_mat.addItems(["enabled", "disabled"]) self.export_compression_mat.setCurrentIndex(0) elif name == "CSV": self.output_options.setCurrentWidget(self.CSV) elif name == "ASC": self.output_options.setCurrentWidget(self.ASC) else: self.output_options.setCurrentWidget(self.HDF5) if name == "Parquet": self.export_compression.setEnabled(True) self.export_compression.clear() self.export_compression.addItems(["GZIP", "SNAPPY", "LZ4"]) self.export_compression.setCurrentIndex(0) elif name == "HDF5": self.export_compression.setEnabled(True) self.export_compression.clear() self.export_compression.addItems(["gzip", "lzf", "szip"]) self.export_compression.setCurrentIndex(0) elif name: self.export_compression.clear() self.export_compression.setEnabled(False) def sort_alphabetically(self, event=None): count = self.files_list.count() if not count: return source_files = natsorted([self.files_list.item(row).text() for row in range(count)]) self.files_list.clear() self.files_list.addItems(source_files) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/file.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) for row in range(count): self.files_list.item(row).setIcon(icon) def sort_by_start_time(self, event=None): count = self.files_list.count() if not count: return source_files = [self.files_list.item(row).text() for row in range(count)] start_times = [] for file_name in source_files: if Path(file_name).suffix.lower() in (".mdf", ".dat", ".mf4"): with open(file_name, "rb") as f: f.seek(64) blk_id = f.read(2) block_type = HeaderBlockV4 if blk_id == b"##" else HeaderBlockV3 header = block_type(stream=f, address=64) start_times.append((header.start_time, file_name)) else: mdf = self._as_mdf(file_name) header = mdf.header start_times.append((header.start_time, file_name)) mdf.close() try: start_times = sorted(start_times) except TypeError: start_times = [(st.replace(tzinfo=timezone.utc), name) for (st, name) in start_times] start_times = sorted(start_times) self.files_list.clear() self.files_list.addItems([item[1] for item in start_times]) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/file.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) for row in range(count): self.files_list.item(row).setIcon(icon) def save_filter_list(self): file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output filter list file", "", "CANape Lab file (*.lab)", "CANape Lab file (*.lab)", ) if file_name: file_name = Path(file_name) iterator = QtWidgets.QTreeWidgetItemIterator(self.filter_tree) signals = [] if self.filter_view.currentText() == "Internal file structure": while item := iterator.value(): iterator += 1 if item.parent() is None: continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.append(item.text(0)) else: while item := iterator.value(): iterator += 1 if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.append(item.text(0)) suffix = file_name.suffix.lower() if suffix == ".lab": section_name, ok = QtWidgets.QInputDialog.getText( self, "Provide .lab file section name", "Section name:", ) if not ok: section_name = "Selected channels" with open(file_name, "w") as output: if suffix == ".lab": output.write( """[SETTINGS] Version;V1.1 MultiRasterSeparator;& """ ) output.write(f"[{section_name}]\n") output.write("\n".join(natsorted(signals))) def load_filter_list(self, event=None, file_name=None): if file_name is None: file_name, _ = QtWidgets.QFileDialog.getOpenFileName( self, "Select channel list file", "", "Config file (*.cfg);;Display files (*.dsp *.dspf);;CANape Lab file (*.lab);;All file types (*.cfg *.dsp *.dspf *.lab *.txt)", "All file types (*.cfg *.dsp *.dspf *.lab *.txt)", ) if file_name is None or Path(file_name).suffix.lower() not in (".cfg", ".dsp", ".dspf", ".lab", ".txt"): return if not isinstance(file_name, dict): file_name = Path(file_name) if file_name.suffix.lower() == ".lab": info = load_lab(file_name) if info: if len(info) > 1: lab_section, ok = QtWidgets.QInputDialog.getItem( self, "Please select the ASAP section name", "Available sections:", list(info), 0, False, ) if ok: channels = info[lab_section] else: return else: channels = list(info.values())[0] channels = [name.split(";")[0] for name in channels] else: channels = load_channel_names_from_file(file_name) else: info = file_name channels = info.get("selected_channels", []) if channels: channels = set(channels) iterator = QtWidgets.QTreeWidgetItemIterator(self.filter_tree) if self.filter_view.currentText() == "Internal file structure": while item := iterator.value(): if item.parent() is None: iterator += 1 continue channel_name = item.text(0) if channel_name in channels: item.setCheckState(0, QtCore.Qt.CheckState.Checked) channels.remove(channel_name) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 elif self.filter_view.currentText() == "Natural sort": while item := iterator.value(): channel_name = item.text(0) if channel_name in channels: item.setCheckState(0, QtCore.Qt.CheckState.Checked) channels.remove(channel_name) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 else: items = [] self.filter_tree.clear() source_files = [Path(self.files_list.item(row).text()) for row in range(self.files_list.count())] for file_name in source_files: if file_name.suffix.lower() in (".mdf", ".mf4"): break else: file_name = source_files[0] mdf = self._as_mdf(file_name) origin_uuid = os.urandom(6).hex() self._selected_filter = set(channels) for i, gp in enumerate(mdf.groups): for j, ch in enumerate(gp.channels): if ch.name in channels: entry = i, j channel = TreeItem(entry, ch.name, origin_uuid=origin_uuid) channel.setText(0, ch.name) channel.setCheckState(0, QtCore.Qt.CheckState.Checked) items.append(channel) channels.remove(ch.name) if len(items) < 30000: items = natsorted(items, key=lambda x: x.name) else: items.sort(key=lambda x: x.name) self.filter_tree.addTopLevelItems(items) self.update_selected_filter_channels() mdf.close() def connect_export_updates(self): self.output_format.currentTextChanged.connect(self.store_export_setttings) self.mdf_version.currentTextChanged.connect(self.store_export_setttings) self.mdf_compression.currentTextChanged.connect(self.store_export_setttings) self.mdf_split.checkStateChanged.connect(self.store_export_setttings) self.mdf_split_size.valueChanged.connect(self.store_export_setttings) self.single_time_base.checkStateChanged.connect(self.store_export_setttings) self.time_from_zero.checkStateChanged.connect(self.store_export_setttings) self.time_as_date.checkStateChanged.connect(self.store_export_setttings) self.raw.checkStateChanged.connect(self.store_export_setttings) self.use_display_names.checkStateChanged.connect(self.store_export_setttings) self.reduce_memory_usage.checkStateChanged.connect(self.store_export_setttings) self.export_compression.currentTextChanged.connect(self.store_export_setttings) self.empty_channels.currentTextChanged.connect(self.store_export_setttings) self.single_time_base_csv.checkStateChanged.connect(self.store_export_setttings) self.time_from_zero_csv.checkStateChanged.connect(self.store_export_setttings) self.time_as_date_csv.checkStateChanged.connect(self.store_export_setttings) self.raw_csv.checkStateChanged.connect(self.store_export_setttings) self.add_units.checkStateChanged.connect(self.store_export_setttings) self.doublequote.checkStateChanged.connect(self.store_export_setttings) self.use_display_names_csv.checkStateChanged.connect(self.store_export_setttings) self.empty_channels_csv.currentTextChanged.connect(self.store_export_setttings) self.delimiter.editingFinished.connect(self.store_export_setttings) self.escapechar.editingFinished.connect(self.store_export_setttings) self.lineterminator.editingFinished.connect(self.store_export_setttings) self.quotechar.editingFinished.connect(self.store_export_setttings) self.quoting.currentTextChanged.connect(self.store_export_setttings) self.single_time_base_mat.checkStateChanged.connect(self.store_export_setttings) self.time_from_zero_mat.checkStateChanged.connect(self.store_export_setttings) self.time_as_date_mat.checkStateChanged.connect(self.store_export_setttings) self.raw_mat.checkStateChanged.connect(self.store_export_setttings) self.use_display_names_mat.checkStateChanged.connect(self.store_export_setttings) self.reduce_memory_usage_mat.checkStateChanged.connect(self.store_export_setttings) self.empty_channels_mat.currentTextChanged.connect(self.store_export_setttings) self.export_compression_mat.currentTextChanged.connect(self.store_export_setttings) self.mat_format.currentTextChanged.connect(self.store_export_setttings) self.oned_as.currentTextChanged.connect(self.store_export_setttings) def restore_export_settings(self): self.output_format.setCurrentText(self._settings.value("export_batch", "MDF")) self.mdf_version.setCurrentText(self._settings.setValue("export_batch/MDF/version", "4.10")) self.mdf_compression.setCurrentText(self._settings.value("export_batch/MDF/compression", "transposed deflate")) self.mdf_split.setChecked(self._settings.value("export_batch/MDF/split_data_blocks", True, type=bool)) self.mdf_split_size.setValue(self._settings.value("export_batch/MDF/split_size", 4, type=int)) self.single_time_base.setChecked(self._settings.value("export_batch/HDF5/single_time_base", False, type=bool)) self.time_from_zero.setChecked(self._settings.value("export_batch/HDF5/time_from_zero", False, type=bool)) self.time_as_date.setChecked(self._settings.value("export_batch/HDF5/time_as_date", False, type=bool)) self.raw.setChecked(self._settings.value("export_batch/HDF5/raw", False, type=bool)) self.use_display_names.setChecked(self._settings.value("export_batch/HDF5/use_display_names", False, type=bool)) self.reduce_memory_usage.setChecked( self._settings.value("export_batch/HDF5/reduce_memory_usage", False, type=bool) ) self.export_compression.setCurrentText(self._settings.value("export_batch/HDF5/export_compression", "gzip")) self.empty_channels.setCurrentText(self._settings.value("export_batch/HDF5/empty_channels", "skip")) self.single_time_base_csv.setChecked( self._settings.value("export_batch/CSV/single_time_base_csv", False, type=bool) ) self.time_from_zero_csv.setChecked( self._settings.value("export_batch/CSV/time_from_zero_csv", False, type=bool) ) self.time_as_date_csv.setChecked(self._settings.value("export_batch/CSV/time_as_date_csv", False, type=bool)) self.raw_csv.setChecked(self._settings.value("export_batch/CSV/raw_csv", False, type=bool)) self.add_units.setChecked(self._settings.value("export_batch/CSV/add_units", False, type=bool)) self.doublequote.setChecked(self._settings.value("export_batch/CSV/doublequote", False, type=bool)) self.use_display_names_csv.setChecked( self._settings.value("export_batch/CSV/use_display_names_csv", False, type=bool) ) self.empty_channels_csv.setCurrentText(self._settings.value("export_batch/CSV/empty_channels_csv", "skip")) self.delimiter.setText(self._settings.value("export_batch/CSV/delimiter", ",")) self.escapechar.setText(self._settings.value("export_batch/CSV/escapechar", "")) self.lineterminator.setText(self._settings.value("export_batch/CSV/lineterminator", r"\r\n")) self.quotechar.setText(self._settings.value("export_batch/CSV/quotechar", '"')) self.quoting.setCurrentText(self._settings.value("export_batch/CSV/quoting", "MINIMAL")) self.single_time_base_mat.setChecked( self._settings.value("export_batch/MAT/single_time_base_mat", False, type=bool) ) self.time_from_zero_mat.setChecked( self._settings.value("export_batch/MAT/time_from_zero_mat", False, type=bool) ) self.time_as_date_mat.setChecked(self._settings.value("export_batch/MAT/time_as_date_mat", False, type=bool)) self.raw_mat.setChecked(self._settings.value("export_batch/MAT/raw_mat", False, type=bool)) self.use_display_names_mat.setChecked( self._settings.value("export_batch/MAT/use_display_names_mat", False, type=bool) ) self.reduce_memory_usage_mat.setChecked( self._settings.value("export_batch/MAT/reduce_memory_usage_mat", False, type=bool) ) self.empty_channels_mat.setCurrentText(self._settings.value("export_batch/MAT/empty_channels_mat", "skip")) self.export_compression_mat.setCurrentText( self._settings.value("export_batch/MAT/export_compression_mat", "enabled") ) self.mat_format.setCurrentText(self._settings.value("export_batch/MAT/mat_format", "4")) self.oned_as.setCurrentText(self._settings.value("export_batch/MAT/oned_as", "row")) def store_export_setttings(self, *args): self._settings.setValue("export_batch", self.output_format.currentText()) self._settings.setValue("export_batch/MDF/version", self.mdf_version.currentText()) self._settings.setValue("export_batch/MDF/compression", self.mdf_compression.currentText()) self._settings.setValue("export_batch/MDF/split_data_blocks", self.mdf_split.isChecked()) self._settings.setValue("export_batch/MDF/split_size", self.mdf_split_size.value()) self._settings.setValue("export_batch/HDF5/single_time_base", self.single_time_base.isChecked()) self._settings.setValue("export_batch/HDF5/time_from_zero", self.time_from_zero.isChecked()) self._settings.setValue("export_batch/HDF5/time_as_date", self.time_as_date.isChecked()) self._settings.setValue("export_batch/HDF5/raw", self.raw.isChecked()) self._settings.setValue("export_batch/HDF5/use_display_names", self.use_display_names.isChecked()) self._settings.setValue("export_batch/HDF5/reduce_memory_usage", self.reduce_memory_usage.isChecked()) self._settings.setValue("export_batch/HDF5/export_compression", self.export_compression.currentText()) self._settings.setValue("export_batch/HDF5/empty_channels", self.empty_channels.currentText()) self._settings.setValue("export_batch/CSV/single_time_base_csv", self.single_time_base_csv.isChecked()) self._settings.setValue("export_batch/CSV/time_from_zero_csv", self.time_from_zero_csv.isChecked()) self._settings.setValue("export_batch/CSV/time_as_date_csv", self.time_as_date_csv.isChecked()) self._settings.setValue("export_batch/CSV/raw_csv", self.raw_csv.isChecked()) self._settings.setValue("export_batch/CSV/add_units", self.add_units.isChecked()) self._settings.setValue("export_batch/CSV/doublequote", self.doublequote.isChecked()) self._settings.setValue("export_batch/CSV/use_display_names_csv", self.use_display_names_csv.isChecked()) self._settings.setValue("export_batch/CSV/empty_channels_csv", self.empty_channels_csv.currentText()) self._settings.setValue("export_batch/CSV/delimiter", self.delimiter.text()) self._settings.setValue("export_batch/CSV/escapechar", self.escapechar.text()) self._settings.setValue("export_batch/CSV/lineterminator", self.lineterminator.text()) self._settings.setValue("export_batch/CSV/quotechar", self.quotechar.text()) self._settings.setValue("export_batch/CSV/quoting", self.quoting.currentText()) self._settings.setValue("export_batch/MAT/single_time_base_mat", self.single_time_base_mat.isChecked()) self._settings.setValue("export_batch/MAT/time_from_zero_mat", self.time_from_zero_mat.isChecked()) self._settings.setValue("export_batch/MAT/time_as_date_mat", self.time_as_date_mat.isChecked()) self._settings.setValue("export_batch/MAT/raw_mat", self.raw_mat.isChecked()) self._settings.setValue("export_batch/MAT/use_display_names_mat", self.use_display_names_mat.isChecked()) self._settings.setValue("export_batch/MAT/reduce_memory_usage_mat", self.reduce_memory_usage_mat.isChecked()) self._settings.setValue("export_batch/MAT/empty_channels_mat", self.empty_channels_mat.currentText()) self._settings.setValue("export_batch/MAT/export_compression_mat", self.export_compression_mat.currentText()) self._settings.setValue("export_batch/MAT/mat_format", self.mat_format.currentText()) self._settings.setValue("export_batch/MAT/oned_as", self.oned_as.currentText()) def clear_filter(self): iterator = QtWidgets.QTreeWidgetItemIterator(self.filter_tree) if self.filter_view.currentIndex() == 1: while item := iterator.value(): if item.parent() is None: item.setExpanded(False) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 else: while item := iterator.value(): item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 self._selected_filter.clear() self.update_selected_filter_channels() asammdf-8.5.1/src/asammdf/gui/widgets/bus_database_manager.py000066400000000000000000000067161502633300400242550ustar00rootroot00000000000000from pathlib import Path from PySide6 import QtWidgets from ..ui.bus_database_manager import Ui_BusDatabaseManager from .database_item import DatabaseItem class BusDatabaseManager(Ui_BusDatabaseManager, QtWidgets.QWidget): def __init__(self, databases, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) for bus, database in databases["CAN"]: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="CAN") widget.bus.setCurrentText(bus) self.can_database_list.addItem(item) self.can_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) for bus, database in databases["LIN"]: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="LIN") widget.bus.setCurrentText(bus) self.lin_database_list.addItem(item) self.lin_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) self.load_can_database_btn.clicked.connect(self.load_can_database) self.load_lin_database_btn.clicked.connect(self.load_lin_database) self.showMaximized() def to_config(self): dbs = { "CAN": [], "LIN": [], } count = self.can_database_list.count() for row in range(count): item = self.can_database_list.item(row) widget = self.can_database_list.itemWidget(item) dbs["CAN"].append((widget.bus.currentText(), widget.database.text())) count = self.lin_database_list.count() for row in range(count): item = self.lin_database_list.item(row) widget = self.lin_database_list.itemWidget(item) dbs["LIN"].append((widget.bus.currentText(), widget.database.text())) return dbs def load_can_database(self, event): file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select CAN database file", "", "ARXML or DBC (*.dbc *.arxml)", "ARXML or DBC (*.dbc *.arxml)", ) if file_names: file_names = [name for name in file_names if Path(name).suffix.lower() in (".arxml", ".dbc")] if file_names: for database in file_names: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="CAN") self.can_database_list.addItem(item) self.can_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) def load_lin_database(self, event): file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select LIN database file", "", "ARXML or DBC database (*.dbc *.arxml);;LDF database (*.ldf);;All supported formats (*.dbc *.arxml *ldf)", "All supported formats (*.dbc *.arxml *ldf)", ) if file_names: file_names = [name for name in file_names if Path(name).suffix.lower() in (".arxml", ".dbc", ".ldf")] if file_names: for database in file_names: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="LIN") self.lin_database_list.addItem(item) self.lin_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) asammdf-8.5.1/src/asammdf/gui/widgets/can_bus_trace.py000066400000000000000000000044421502633300400227300ustar00rootroot00000000000000import logging import dateutil.tz import pandas as pd from PySide6 import QtCore, QtGui from .tabular_base import TabularBase logger = logging.getLogger("asammdf.gui") LOCAL_TIMEZONE = dateutil.tz.tzlocal() class CANBusTrace(TabularBase): add_channels_request = QtCore.Signal(list) def __init__(self, signals=None, start=0, format="phys", ranges=None, *args, **kwargs): ranges = ranges or {name: [] for name in signals.columns} if not ranges["Event Type"]: ranges["Event Type"] = [ { "background_color": QtGui.QColor("#ff0000"), "font_color": QtGui.QColor("#000000"), "op1": "==", "op2": "==", "value1": "Error Frame", "value2": None, }, { "background_color": QtGui.QColor("#00ff00"), "font_color": QtGui.QColor("#000000"), "op1": "==", "op2": "==", "value1": "Remote Frame", "value2": None, }, ] super().__init__(signals, ranges) self.signals_descr = dict.fromkeys(signals.columns, 0) self.start = start.astimezone(LOCAL_TIMEZONE) self.pattern = {} self.format = format self.format_selection.setCurrentText(format) self._original_timestamps = signals["timestamps"] self._original_ts_series = pd.Series( self._original_timestamps, index=self.tree.pgdf.df_unfiltered.index, ) prefixes = set() for name in self.tree.pgdf.df_unfiltered.columns: while "." in name: name = name.rsplit(".", 1)[0] prefixes.add(f"{name}.") self.filters.minimal_menu = True self.prefix.insertItems(0, sorted(prefixes, key=lambda x: (-len(x), x))) self.prefix.setEnabled(False) self.prefix.currentIndexChanged.connect(self.prefix_changed) if prefixes: self.remove_prefix.setCheckState(QtCore.Qt.CheckState.Checked) self._settings = QtCore.QSettings() integer_mode = self._settings.value("tabular_format", "phys") self.format_selection.setCurrentText(integer_mode) asammdf-8.5.1/src/asammdf/gui/widgets/channel_bar_display.py000066400000000000000000000201171502633300400241160ustar00rootroot00000000000000import numpy as np from PySide6 import QtCore, QtGui, QtWidgets from ..dialogs.range_editor import RangeEditor from ..ui.channel_bar_display_widget import Ui_ChannelBarDisplay class BarWidget(QtWidgets.QWidget): def __init__(self, range=(0, 100), over=20, color=None): super().__init__() self.range = range self.over = over self.max = self.range[1] self.resizeEvent(None) self.color = color self.value = 50.0 def resizeEvent(self, event): width = self.size().width() parts = 6 while True: px = width / parts if px >= 50: break else: parts -= 2 if parts == 4: break if isinstance(self.range[0], int): self.ticks = [int(e) for e in np.linspace(self.range[0], self.range[1], parts + 1, True).tolist()] else: self.ticks = np.linspace(self.range[0], self.range[1], parts + 1, True).tolist() def setValue(self, value): self.value = float(value) self.paintEvent(None) def set_color(self, color): self.color = color self.paintEvent(None) def paintEvent(self, e): qp = QtGui.QPainter() qp.begin(self) self.drawWidget(qp) qp.end() def drawWidget(self, qp): font = QtGui.QFont("Serif", 7, QtGui.QFont.Weight.Light) qp.setFont(font) size = self.size() w = size.width() h = size.height() till = int((w / self.max) * self.value) full = int((w / self.max) * self.over) if self.value >= self.over: qp.setPen(QtGui.QColor(self.color)) qp.setBrush(QtGui.QColor(self.color)) qp.drawRect(0, 0, full, h) qp.setPen(QtGui.QColor(255, 175, 175)) qp.setBrush(QtGui.QColor(255, 175, 175)) qp.drawRect(full, 0, till - full, h) else: qp.setPen(QtGui.QColor(self.color)) qp.setBrush(QtGui.QColor(self.color)) qp.drawRect(0, 0, till, h) pen = QtGui.QPen(QtGui.QColor(20, 20, 20), 1, QtCore.Qt.PenStyle.SolidLine) qp.setPen(pen) qp.setBrush(QtCore.Qt.BrushStyle.NoBrush) qp.drawRect(0, 0, w - 1, h - 1) for j, val in enumerate(self.ticks): val_pos = int(val / self.range[1] * w) val = str(val) if isinstance(val, int) else f"{val:.3f}" qp.drawLine(val_pos, 0, val_pos, 5) metrics = qp.fontMetrics().boundingRect(val) fw = metrics.width() fh = metrics.height() x, y = int(val_pos - fw / 2), 7 + fh x = max(2, x) x = min(x, w - fw - 2) qp.drawText(x, y, val) class ChannelBarDisplay(Ui_ChannelBarDisplay, QtWidgets.QWidget): def __init__( self, uuid, value, range, over, color, unit="", precision=3, tooltip="", *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self.color = color self._value_prefix = "" self._value = value self._name = "" self.bar = BarWidget(range, over, color=self.color) self.layout.addWidget(self.bar) self.instant_value = QtWidgets.QLabel("") self.instant_value.setMinimumWidth(150) font = self.instant_value.font() font.setBold(True) font.setPointSize(16) self.instant_value.setFont(font) self.layout.addWidget(self.instant_value) self.layout.setStretch(0, 0) self.layout.setStretch(1, 0) self.layout.setStretch(2, 1) self.layout.setStretch(3, 0) self.uuid = uuid self.ranges = {} self.unit = unit.strip() self.precision = precision self._transparent = True self._tooltip = tooltip self.color_btn.clicked.connect(self.select_color) self.fm = QtGui.QFontMetrics(self.name.font()) self.setToolTip(self._tooltip or self._name) self.kind = "f" if self.kind in "SUVui": self.fmt = "{}" else: self.fmt = f"{{:.{self.precision}f}}" self.show() def set_selected(self, on): palette = self.name.palette() if on: brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Text, brush) else: brush = QtGui.QBrush(QtGui.QColor(self.color)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Text, brush) self.name.setPalette(palette) def set_precision(self, precision): if self.kind == "f": self.precision = precision self.fmt = f"{{:.{self.precision}f}}" def mouseDoubleClickEvent(self, event): dlg = RangeEditor(self.unit, self.ranges) dlg.exec_() if dlg.pressed_button == "apply": self.ranges = dlg.result def select_color(self): color = QtWidgets.QColorDialog.getColor(QtGui.QColor(self.color)) if color.isValid(): self.set_color(color.name()) self.bar.set_color(color) def set_fmt(self, fmt): if self.kind in "SUV": self.fmt = "{}" elif self.kind == "f": self.fmt = f"{{:.{self.precision}f}}" else: if fmt == "hex": self.fmt = "0x{:X}" elif fmt == "bin": self.fmt = "0b{:b}" elif fmt == "phys": self.fmt = "{}" def set_color(self, color): self.color = color self.set_name(self._name) self.set_value(self._value) self.color_btn.setStyleSheet(f"background-color: {color};") self.bar.set_color(color) palette = self.name.palette() brush = QtGui.QBrush(QtGui.QColor(color)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Text, brush) self.name.setPalette(palette) self.instant_value.setPalette(palette) def set_name(self, text=""): self.setToolTip(self._tooltip or text) self._name = text def set_prefix(self, text=""): self._value_prefix = text def update(self): width = self.name.size().width() if self.unit: self.name.setText( self.fm.elidedText(f"{self._name} ({self.unit})", QtCore.Qt.TextElideMode.ElideMiddle, width) ) else: self.name.setText(self.fm.elidedText(self._name, QtCore.Qt.TextElideMode.ElideMiddle, width)) self.set_value(self._value, update=True) def set_value(self, value, update=False): if self._value == value and update is False: return self.bar.setValue(value) self.instant_value.setText(self.fmt.format(value)) def keyPressEvent(self, event): key = event.key() modifier = event.modifiers() if modifier == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_C: QtWidgets.QApplication.instance().clipboard().setText(self._name) else: super().keyPressEvent(event) def resizeEvent(self, event): width = self.name.size().width() if self.unit: self.name.setText( self.fm.elidedText(f"{self._name} ({self.unit})", QtCore.Qt.TextElideMode.ElideMiddle, width) ) else: self.name.setText(self.fm.elidedText(self._name, QtCore.Qt.TextElideMode.ElideMiddle, width)) def text(self): return self._name def does_not_exist(self): icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/error.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.color_btn.setIcon(icon) self.color_btn.setFlat(True) self.color_btn.clicked.disconnect() def disconnect_slots(self): pass asammdf-8.5.1/src/asammdf/gui/widgets/channel_group_info.py000066400000000000000000000112531502633300400237750ustar00rootroot00000000000000import numpy as np import pandas as pd from PySide6 import QtCore, QtGui, QtWidgets from ...blocks.utils import csv_bytearray2hex from ..ui.channel_group_info_widget import Ui_ChannelGroupInfo from ..utils import BLUE from ..widgets.list_item import ListItem class ChannelGroupInfoWidget(Ui_ChannelGroupInfo, QtWidgets.QWidget): def __init__(self, mdf, group, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) channel_group = group.channel_group self.mdf = mdf self.group = group self.channel_group_label.setText(channel_group.metadata()) if hasattr(channel_group, "acq_source") and channel_group.acq_source: self.source_label.setText(channel_group.acq_source.metadata()) items = [] for i, ch in enumerate(group.channels): item = ListItem(entry=i, name=ch.name) item.setText(item.name) items.append(item) items.sort(key=lambda x: x.name) for item in items: self.channels.addItem(item) self.scroll.valueChanged.connect(self._display) self.channels.currentRowChanged.connect(self.select_channel) self.byte_count = 0 self.byte_offset = 0 self.position = 0 self.index_size = len(str(channel_group.cycles_nr)) self.cycles = channel_group.cycles_nr if self.mdf.version >= "4.00": self.record_size = channel_group.samples_byte_nr + channel_group.invalidation_bytes_nr else: self.record_size = channel_group.samples_byte_nr self.wrap.checkStateChanged.connect(self.wrap_changed) self._display(self.position) def wrap_changed(self): if self.wrap.checkState() == QtCore.Qt.CheckState.Checked: self.display.setWordWrapMode(QtGui.QTextOption.WrapMode.WordWrap) else: self.display.setWordWrapMode(QtGui.QTextOption.WrapMode.NoWrap) self._display(self.position) def select_channel(self, row): item = self.channels.item(row) channel = self.group.channels[item.entry] self.byte_offset = channel.byte_offset byte_count = channel.bit_count + channel.bit_offset if byte_count % 8: byte_count += 8 - (byte_count % 8) self.byte_count = byte_count // 8 self._display(self.position) def _display(self, position): self.display.clear() self.position = position record_offset = max(0, position * self.cycles // self.scroll.maximum()) record_end = max(0, position * self.cycles // self.scroll.maximum() + 100) record_count = record_end - record_offset data = b"".join( fragment.data for fragment in self.mdf._mdf._load_data(self.group, record_offset=record_offset, record_count=record_count) ) data = pd.Series(list(np.frombuffer(data, dtype=f"({self.record_size},)u1"))) data = list(csv_bytearray2hex(data)) lines = [ """ """ ] if self.byte_count == 0: template = f'

{{index: >{self.index_size}}}: {{line}}

' for i, l in enumerate(data, record_offset): lines.append(template.format(index=i, line=l)) else: template = f'

{{index: >{self.index_size}}}: {{start}}{{middle}}{{end}}

' for i, l in enumerate(data, record_offset): lines.append( template.format( index=i, start=l[: self.byte_offset * 3], middle=l[self.byte_offset * 3 : self.byte_offset * 3 + self.byte_count * 3], end=l[self.byte_offset * 3 + self.byte_count * 3 :], ) ) self.display.appendHtml("\n".join(lines)) if position == 0: self.display.verticalScrollBar().setSliderPosition(0) elif position == self.scroll.maximum(): self.display.verticalScrollBar().setSliderPosition(self.display.verticalScrollBar().maximum()) asammdf-8.5.1/src/asammdf/gui/widgets/channel_info.py000066400000000000000000000010061502633300400225540ustar00rootroot00000000000000from PySide6 import QtWidgets from ..ui.channel_info_widget import Ui_ChannelInfo class ChannelInfoWidget(Ui_ChannelInfo, QtWidgets.QWidget): def __init__(self, channel, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.channel_label.setText(channel.metadata()) if channel.conversion: self.conversion_label.setText(channel.conversion.metadata()) if channel.source: self.source_label.setText(channel.source.metadata()) asammdf-8.5.1/src/asammdf/gui/widgets/channel_stats.py000066400000000000000000000117261502633300400227710ustar00rootroot00000000000000from copy import deepcopy import numpy as np from PySide6 import QtCore, QtGui, QtWidgets from ..ui.channel_stats import Ui_ChannelStats MONOSPACE_FONT = None class ChannelStats(Ui_ChannelStats, QtWidgets.QWidget): precision_modified = QtCore.Signal() def __init__(self, xunit="s", precision=6, *args, **kwargs): super().__init__(*args, **kwargs) self._settings = QtCore.QSettings() self.setupUi(self) global MONOSPACE_FONT if MONOSPACE_FONT is None: families = QtGui.QFontDatabase.families() for family in ( "Consolas", "Liberation Mono", "DejaVu Sans Mono", "Droid Sans Mono", "Liberation Mono", "Roboto Mono", "Monaco", "Courier", ): if family in families: MONOSPACE_FONT = family break font = QtGui.QFont(MONOSPACE_FONT) self.setFont(font) self.xunit = xunit.strip() self.color = "#000000" self.fmt = "phys" self.name_template = '

{}

' self._name = "Please select a single channel" self.name.setStyleSheet("background-color: transparent;") for i in range(10): label = self.findChild(QtWidgets.QLabel, f"xunit{i}") label.setText(f" {self.xunit}") self.precision.addItems(["Full float precision"] + [f"{i} float decimals" for i in range(16)]) self.precision.setCurrentIndex(self._settings.value("stats_float_precision", 6, type=int) + 1) self.precision.currentIndexChanged.connect(self.set_float_precision) def set_stats(self, stats): if not stats: self.clear() return self._stats = deepcopy(stats) precision = self._settings.value("stats_float_precision", 6, type=int) fmt = f" {{:.{precision}f}}" color = stats["color"] if stats: for name, value in stats.items(): if name == "unit": for i in range(1, 23): label = self.findChild(QtWidgets.QLabel, f"unit{i}") if label: label.setText(f" {value}") self.selected_gradient_unit.setText(f" {value}/{self.xunit}") self.visible_gradient_unit.setText(f" {value}/{self.xunit}") self.overall_gradient_unit.setText(f" {value}/{self.xunit}") self.selected_integral_unit.setText(f" {value}*{self.xunit}") self.visible_integral_unit.setText(f" {value}*{self.xunit}") self.overall_integral_unit.setText(f" {value}*{self.xunit}") elif name == "name": self._name = value self.name.setText(self.name_template.format(self.color, self._name)) elif name == "color": self.color = value self.name.setText(self.name_template.format(color, self._name)) elif name in ("region", "color"): continue else: label = self.findChild(QtWidgets.QLabel, name) if precision >= 0: if isinstance(value, (float, np.floating)): label.setText(fmt.format(value)) else: label.setText(str(value)) else: label.setText(str(value)) if stats["region"]: self.cursor_group.setHidden(True) self.region_group.setHidden(False) else: self.cursor_group.setHidden(False) self.region_group.setHidden(True) else: self.clear() def clear(self): self._name = "Please select a single channel" self.color = "#000000" self.name.setText(self.name_template.format(self.color, self._name)) for k, group in enumerate( ( self.cursor_group, self.region_group, self.visible_group, self.overall_group, ) ): layout = group.layout() rows = layout.rowCount() for i in range(rows): label = layout.itemAtPosition(i, 1) if label is not None: label = label.widget() label.setText("") label = layout.itemAtPosition(i, 2) if label is not None: label = label.widget() if label.objectName().startswith("unit"): label.setText("") def set_float_precision(self, index): self._settings.setValue("stats_float_precision", index - 1) self.precision_modified.emit() asammdf-8.5.1/src/asammdf/gui/widgets/collapsiblebox.py000066400000000000000000000051521502633300400231410ustar00rootroot00000000000000from PySide6 import QtCore, QtWidgets class CollapsibleBox(QtWidgets.QWidget): def __init__(self, title="", parent=None): super().__init__(parent) self.toggle_button = QtWidgets.QToolButton(text=title, checkable=True, checked=False) self.toggle_button.setStyleSheet("QToolButton { border: none; }") self.toggle_button.setToolButtonStyle(QtCore.Qt.ToolButtonStyle.ToolButtonTextBesideIcon) self.toggle_button.setArrowType(QtCore.Qt.ArrowType.RightArrow) self.toggle_button.pressed.connect(self.on_pressed) self.toggle_animation = QtCore.QParallelAnimationGroup(self) self.content_area = QtWidgets.QScrollArea(maximumHeight=0, minimumHeight=0) self.content_area.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed) self.content_area.setFrameShape(QtWidgets.QFrame.Shape.NoFrame) lay = QtWidgets.QVBoxLayout(self) lay.setSpacing(0) lay.setContentsMargins(0, 0, 0, 0) lay.addWidget(self.toggle_button) lay.addWidget(self.content_area) self.toggle_animation.addAnimation(QtCore.QPropertyAnimation(self, b"minimumHeight")) self.toggle_animation.addAnimation(QtCore.QPropertyAnimation(self, b"maximumHeight")) self.toggle_animation.addAnimation(QtCore.QPropertyAnimation(self.content_area, b"maximumHeight")) @QtCore.pyqtSlot() def on_pressed(self): checked = self.toggle_button.isChecked() self.toggle_button.setArrowType( QtCore.Qt.ArrowType.DownArrow if not checked else QtCore.Qt.ArrowType.RightArrow ) self.toggle_animation.setDirection( QtCore.QAbstractAnimation.Direction.Forward if not checked else QtCore.QAbstractAnimation.Direction.Backward ) self.toggle_animation.start() def setContentLayout(self, layout): lay = self.content_area.layout() del lay self.content_area.setLayout(layout) collapsed_height = self.sizeHint().height() - self.content_area.maximumHeight() content_height = layout.sizeHint().height() for i in range(self.toggle_animation.animationCount()): animation = self.toggle_animation.animationAt(i) animation.setDuration(500) animation.setStartValue(collapsed_height) animation.setEndValue(collapsed_height + content_height) content_animation = self.toggle_animation.animationAt(self.toggle_animation.animationCount() - 1) content_animation.setDuration(200) content_animation.setStartValue(0) content_animation.setEndValue(content_height) asammdf-8.5.1/src/asammdf/gui/widgets/cursor.py000066400000000000000000000407031502633300400214550ustar00rootroot00000000000000import pyqtgraph as pg from PySide6 import QtCore, QtGui from ... import tool as Tool from ...blocks.utils import escape_xml_string from ..utils import BLUE class Bookmark(pg.InfiniteLine): def __init__(self, message="", title="", color="#ffffff", tool="", **kwargs): self.title = title or "Bookmark" if message: text = f"{self.title}\nt = {kwargs['pos']}s\n\n{message}\n " else: text = f"{self.title}\nt = {kwargs['pos']}s\n " text = "\n".join([f" {line} " for line in text.splitlines()]) super().__init__( movable=False, label=text, labelOpts={"movable": True}, **kwargs, ) self.line_width = 2 self.color = color self._visible = True self._message = "" self.message = message if tool and tool == Tool.__tool__: self.editable = True else: self.editable = False self.edited = False self.deleted = False self.fill = pg.mkBrush(BLUE) self.border = pg.mkPen( { "color": color, "width": 2, "style": QtCore.Qt.PenStyle.DashLine, } ) def __hash__(self): return hash((self.title, self.message)) @property def color(self): return self.pen.color().name() @color.setter def color(self, value): color = pg.mkColor(value) color.setAlpha(200) self.pen = QtGui.QPen(color.name()) self.hoverPen = QtGui.QPen(color.name()) self.update() def _computeBoundingRect(self): # br = UIGraphicsItem.boundingRect(self) vr = self.viewRect() # bounds of containing ViewBox mapped to local coords. if vr is None: return QtCore.QRectF() ## add a 6-pixel radius around the line for mouse interaction. px = self.pixelLength(direction=pg.Point(1, 0), ortho=True) ## get pixel length orthogonal to the line if px is None: px = 0 pw = max(self.pen.width() / 2, self.hoverPen.width() / 2) w = max(6, self._maxMarkerSize + pw) + 1 w = w * px br = QtCore.QRectF(vr) br.setBottom(-w) br.setTop(w) length = br.width() left = br.left() + length * self.span[0] right = br.left() + length * self.span[1] br.setLeft(left) br.setRight(right) br = br.normalized() vs = self.getViewBox().size() if self._bounds != br or self._lastViewSize != vs: self._bounds = br self._lastViewSize = vs self.prepareGeometryChange() self._endPoints = (left, right) self._lastViewRect = vr return self._bounds @property def line_width(self): return self._line_width @line_width.setter def line_width(self, value): self._line_width = value self.update() @property def message(self): return self._message @message.setter def message(self, value): self._message = value if value: text = f"{self.title}\nt = {self.value()}s\n\n{value}\n " else: text = f"{self.title}\nt = {self.value()}s\n " text = "\n".join([f" {line} " for line in text.splitlines()]) self.label.setPlainText(text) def paint(self, paint, *args, plot=None, uuid=None): if plot and self.visible: paint.setRenderHint(paint.RenderHint.Antialiasing, False) pen = self.pen pen.setWidth(self.line_width) pen.setStyle(QtCore.Qt.PenStyle.DashLine) paint.setPen(pen) position = self.value() rect = plot.viewbox.sceneBoundingRect() delta = rect.x() height = rect.height() px, py = plot.px, plot.py plot.px = (plot.x_range[1] - plot.x_range[0]) / rect.width() plot.py = rect.height() x, y = plot.scale_curve_to_pixmap( position, 0, y_range=plot.viewbox.viewRange()[1], x_start=plot.viewbox.viewRange()[0][0], delta=delta, ) paint.drawLine(QtCore.QPointF(x, 0), QtCore.QPointF(x, height)) rect = self.label.textItem.sceneBoundingRect() black_pen = pg.mkPen("#000000") paint.setPen(self.border) paint.setBrush(self.fill) paint.setRenderHint(paint.RenderHint.Antialiasing, True) paint.drawRect(rect) paint.setPen(black_pen) message = f"{self.title}\nt = {self.value()}s\n\n{self.message}" delta = 5 # pixels paint.drawText(rect.adjusted(delta, delta, -2 * delta, -2 * delta), message) if self.editable: paint.setPen(black_pen) paint.setBrush(QtGui.QBrush(QtGui.QColor("#000000"))) paint.setRenderHint(paint.RenderHint.Antialiasing, True) rect2 = QtCore.QRectF( rect.x() + rect.width() - 35, rect.y() + 1, 18, 18, ) paint.drawRect(rect2) rect2 = QtCore.QRectF( rect.x() + rect.width() - 18, rect.y() + 1, 18, 18, ) paint.drawRect(rect2) pix = QtGui.QPixmap(":/edit.png").scaled(16, 16) paint.drawPixmap(QtCore.QPointF(rect.x() + rect.width() - 34, rect.y() + 1), pix) pix = QtGui.QPixmap(":/erase.png").scaled(16, 16) paint.drawPixmap(QtCore.QPointF(rect.x() + rect.width() - 17, rect.y() + 1), pix) plot.px, plot.py = px, py def set_value(self, value): self.setPos(value) @property def visible(self): return self._visible @visible.setter def visible(self, value): self._visible = bool(value) self.label.setVisible(self._visible) def xml_comment(self): return f""" {escape_xml_string(self.message)} {Tool.__tool__} """ class Cursor(pg.InfiniteLine): def __init__( self, *args, show_circle=True, show_horizontal_line=True, line_width=1, color="#ffffff", **kwargs, ): super().__init__( *args, **kwargs, ) self.line_width = line_width self.color = color # disable mouse cursor until https://github.com/pyqtgraph/pyqtgraph/issues/2416 is fixed # self.setCursor(QtCore.Qt.CursorShape.SplitHCursor) self.sigDragged.connect(self.update_mouse_cursor) self.sigPositionChangeFinished.connect(self.update_mouse_cursor) self._cursor_override = False self.show_circle = show_circle self.show_horizontal_line = show_horizontal_line self.locked = False @property def color(self): return self.pen.color().name() @color.setter def color(self, value): color = pg.mkColor(value) color.setAlpha(200) self.pen = QtGui.QPen(color.name()) self.hoverPen = QtGui.QPen(color.name()) self.update() def isMovable(self): return self.movable @property def line_width(self): return self._line_width @line_width.setter def line_width(self, value): self._line_width = value self.update() def update_mouse_cursor(self, obj): if self.moving: if not self._cursor_override: QtGui.QGuiApplication.setOverrideCursor(QtCore.Qt.CursorShape.SplitHCursor) self._cursor_override = True else: if self._cursor_override is not None: self._cursor_override = False QtGui.QGuiApplication.restoreOverrideCursor() def set_value(self, value): self.setPos(value) def paint(self, paint, *args, plot=None, uuid=None): if plot: paint.setRenderHint(paint.RenderHint.Antialiasing, False) pen = self.pen pen.setWidth(self.line_width) if self.mouseHovering and self.movable: pen.setStyle(QtCore.Qt.PenStyle.DashLine) elif not self.locked: pen.setStyle(QtCore.Qt.PenStyle.SolidLine) else: pen.setStyle(QtCore.Qt.PenStyle.DashDotDotLine) paint.setPen(pen) position = self.value() rect = plot.viewbox.sceneBoundingRect() delta = rect.x() height = rect.height() width = rect.x() + rect.width() px, py = plot.px, plot.py plot.px = (plot.x_range[1] - plot.x_range[0]) / rect.width() plot.py = rect.height() if (not self.show_circle and not self.show_horizontal_line) or not uuid: x, y = plot.scale_curve_to_pixmap( position, 0, y_range=plot.viewbox.viewRange()[1], x_start=plot.viewbox.viewRange()[0][0], delta=delta, ) paint.drawLine(QtCore.QPointF(x, 0), QtCore.QPointF(x, height)) else: signal, idx = plot.signal_by_uuid(uuid) if signal.enable: index = plot.get_timestamp_index(position, signal.timestamps) raw_value, raw_kind, y_value, kind, fmt = signal.value_at_index(index) if y_value != "n.a.": x, y = plot.scale_curve_to_pixmap( position, y_value, y_range=signal.y_range, x_start=plot.viewbox.viewRange()[0][0], delta=delta, ) if self.show_circle: paint.drawLine(QtCore.QPointF(x, 0), QtCore.QPointF(x, y - 5)) paint.drawLine(QtCore.QPointF(x, y + 5), QtCore.QPointF(x, height)) if self.show_horizontal_line: paint.drawLine(QtCore.QPointF(delta, y), QtCore.QPointF(x - 5, y)) paint.drawLine(QtCore.QPointF(x + 5, y), QtCore.QPointF(width, y)) paint.setRenderHints(paint.RenderHint.Antialiasing, True) paint.drawEllipse(QtCore.QPointF(x, y), 5, 5) paint.setRenderHints(paint.RenderHint.Antialiasing, False) else: paint.drawLine(QtCore.QPointF(x, 0), QtCore.QPointF(x, height)) if self.show_horizontal_line: paint.drawLine(QtCore.QPointF(delta, y), QtCore.QPointF(width, y)) else: x, y = plot.scale_curve_to_pixmap( position, 0, y_range=plot.viewbox.viewRange()[1], x_start=plot.viewbox.viewRange()[0][0], delta=delta, ) paint.drawLine(QtCore.QPointF(x, 0), QtCore.QPointF(x, height)) else: x, y = plot.scale_curve_to_pixmap( position, 0, y_range=plot.viewbox.viewRange()[1], x_start=plot.viewbox.viewRange()[0][0], delta=delta, ) paint.drawLine(QtCore.QPointF(x, 0), QtCore.QPointF(x, height)) plot.px, plot.py = px, py def _computeBoundingRect(self): # br = UIGraphicsItem.boundingRect(self) vr = self.viewRect() # bounds of containing ViewBox mapped to local coords. if vr is None: return QtCore.QRectF() ## add a 6-pixel radius around the line for mouse interaction. px = self.pixelLength(direction=pg.Point(1, 0), ortho=True) ## get pixel length orthogonal to the line if px is None: px = 0 pw = max(self.pen.width() / 2, self.hoverPen.width() / 2) w = max(6, self._maxMarkerSize + pw) + 1 w = w * px br = QtCore.QRectF(vr) br.setBottom(-w) br.setTop(w) length = br.width() left = br.left() + length * self.span[0] right = br.left() + length * self.span[1] br.setLeft(left) br.setRight(right) br = br.normalized() vs = self.getViewBox().size() if self._bounds != br or self._lastViewSize != vs: self._bounds = br self._lastViewSize = vs self.prepareGeometryChange() self._endPoints = (left, right) self._lastViewRect = vr return self._bounds class Region(pg.LinearRegionItem): def __init__( self, values=(0, 1), orientation="vertical", brush=None, pen=None, hoverBrush=None, hoverPen=None, movable=True, bounds=None, span=(0, 1), swapMode="sort", clipItem=None, show_circle=True, show_horizontal_line=True, line_width=1, ): pg.GraphicsObject.__init__(self) self.orientation = orientation self.blockLineSignal = False self.moving = False self.mouseHovering = False self.span = span self.swapMode = swapMode self.clipItem = clipItem self._boundingRectCache = None self._clipItemBoundsCache = None self.moving_cursor = None # note LinearRegionItem.Horizontal and LinearRegionItem.Vertical # are kept for backward compatibility. lineKwds = { "movable": movable, "bounds": bounds, "span": span, "pen": pen, "hoverPen": hoverPen, "show_circle": show_circle, "show_horizontal_line": show_horizontal_line, "line_width": line_width, "color": pen, } self.lines = [ Cursor(QtCore.QPointF(values[0], 0), angle=90, **lineKwds), Cursor(QtCore.QPointF(values[1], 0), angle=90, **lineKwds), ] for l in self.lines: l.setParentItem(self) l.sigPositionChangeFinished.connect(self.lineMoveFinished) self.lines[0].sigPositionChanged.connect(self._line0Moved) self.lines[1].sigPositionChanged.connect(self._line1Moved) self.lines[0].sigPositionChanged.connect(self.update_moving_cursor) self.lines[1].sigPositionChanged.connect(self.update_moving_cursor) if brush is None: brush = QtGui.QBrush(QtGui.QColor(0, 0, 255, 50)) self.setBrush(brush) if hoverBrush is None: c = self.brush.color() c.setAlpha(min(c.alpha() * 2, 255)) hoverBrush = pg.functions.mkBrush(c) self.setHoverBrush(hoverBrush) self.setMovable(movable) def update_moving_cursor(self, cursor): self.moving_cursor = cursor def paint(self, p, *args, plot=None, uuid=None): if plot: rect = plot.viewbox.sceneBoundingRect() delta = rect.x() height = rect.height() px, py = plot.px, plot.py plot.px = (plot.x_range[1] - plot.x_range[0]) / rect.width() plot.py = rect.height() x1, y1 = plot.scale_curve_to_pixmap( self.lines[0].value(), 0, y_range=plot.viewbox.viewRange()[1], x_start=plot.viewbox.viewRange()[0][0], delta=delta, ) x2, y2 = plot.scale_curve_to_pixmap( self.lines[1].value(), 0, y_range=plot.viewbox.viewRange()[1], x_start=plot.viewbox.viewRange()[0][0], delta=delta, ) rect = QtCore.QRectF( x1, 0, x2 - x1, height, ) p.setBrush(self.currentBrush) p.setPen(pg.functions.mkPen(None)) p.setCompositionMode(QtGui.QPainter.CompositionMode.CompositionMode_SourceAtop) p.drawRect(rect) for line in self.lines: line.paint(p, *args, plot=plot, uuid=uuid) plot.px, plot.py = px, py asammdf-8.5.1/src/asammdf/gui/widgets/database_item.py000066400000000000000000000007541502633300400227240ustar00rootroot00000000000000from pathlib import Path from PySide6 import QtWidgets from ..ui.database_item import Ui_DatabaseItemUI class DatabaseItem(Ui_DatabaseItemUI, QtWidgets.QWidget): def __init__(self, database, bus_type="CAN"): super().__init__() self.setupUi(self) items = [f"Any {bus_type} bus"] + [f"{bus_type} {i:>2} only" for i in range(1, 17)] self.database.setText(str(Path(database.strip()))) self.bus.addItems(items) self.bus.setCurrentIndex(0) asammdf-8.5.1/src/asammdf/gui/widgets/dict_to_tree.py000066400000000000000000000030601502633300400225770ustar00rootroot00000000000000# taken from https://stackoverflow.com/a/46096319/11009349 from PySide6 import QtGui from PySide6.QtWidgets import QMainWindow, QTreeWidget, QTreeWidgetItem class ViewTree(QTreeWidget): def __init__(self, value, parent=None): super().__init__(parent) self.setHeaderLabel("Computation parameters") def fill_item(item, value): def new_item(parent, text, val=None): child = QTreeWidgetItem([text]) fill_item(child, val) parent.addChild(child) child.setExpanded(True) if value is None: return elif isinstance(value, dict): for key, val in sorted(value.items()): new_item(item, str(key), val) elif isinstance(value, (list, tuple)): for val in value: text = str(val) if not isinstance(val, (dict, list, tuple)) else f"[{type(val).__name__}]" new_item(item, text, val) else: new_item(item, str(value)) fill_item(self.invisibleRootItem(), value) class ComputedChannelInfoWindow(QMainWindow): def __init__(self, signal, parent=None): super().__init__(parent) self.setCentralWidget(ViewTree(signal.computation, self)) self.setWindowTitle(f"Computed channel {signal.name}") self.setMinimumSize(600, 400) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.setWindowIcon(icon) asammdf-8.5.1/src/asammdf/gui/widgets/fft_window.py000066400000000000000000000051071502633300400223050ustar00rootroot00000000000000import numpy as np from PySide6 import QtCore, QtWidgets import scipy.signal as scipy_signal from ..ui.fft_window import Ui_FFTWindow from .plot import Plot, PlotSignal, Signal class FFTWindow(Ui_FFTWindow, QtWidgets.QMainWindow): def __init__(self, signal, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self._settings = QtCore.QSettings() self.with_dots = self._settings.value("dots", False, type=bool) self.signal = signal self.signal_plot = Plot([], self.with_dots) self.fft_plot = Plot([], self.with_dots, x_axis="frequency") layout = self.layout layout.addWidget(self.signal_plot) layout.addWidget(self.fft_plot) self.show() self.signal_plot.add_new_channels([signal]) self.signal_plot.region_removed_signal.connect(self.update) self.signal_plot.region_moved_signal.connect(self.update) self.start_frequency.valueChanged.connect(self.update) self.end_frequency.valueChanged.connect(self.update) self.frequency_step.valueChanged.connect(self.update) self.setWindowTitle(f"{self.signal.name} FFT using Lomb-Scargle periodogram") self.update(initial=True) def update(self, *args, initial=False): xrange, yrange = self.fft_plot.plot.viewbox.viewRange() if self.signal_plot.plot.region: start, stop = self.signal_plot.plot.region.getRegion() signal = self.signal.cut(start, stop) else: signal = self.signal start_frequency = self.start_frequency.value() end_frequency = self.end_frequency.value() frequency_step = self.frequency_step.value() if start_frequency > end_frequency: start_frequency, end_frequency = end_frequency, start_frequency steps = int((end_frequency - start_frequency) / frequency_step) self.fft_plot.clear() if len(self.signal) and steps: f = np.linspace(start_frequency, end_frequency, steps) pgram = scipy_signal.lombscargle(signal.timestamps, signal.samples, f * 2 * np.pi, normalize=True) signal = Signal(samples=pgram, timestamps=f, name=f"{self.signal.name}_FFT") signal.color = self.signal.color signal.computed = False signal.computation = {} signal = PlotSignal(signal) self.fft_plot.add_new_channels([signal]) if not initial: self.fft_plot.plot.viewbox.setXRange(*xrange, padding=0) self.fft_plot.plot.viewbox.setYRange(*yrange, padding=0) asammdf-8.5.1/src/asammdf/gui/widgets/file.py000066400000000000000000004201471502633300400210630ustar00rootroot00000000000000from datetime import datetime, timezone from functools import partial from hashlib import md5 import json import os from pathlib import Path import re from tempfile import gettempdir from traceback import format_exc from zipfile import ZIP_DEFLATED, ZipFile from natsort import natsorted import pandas as pd from PySide6 import QtCore, QtGui, QtWidgets import asammdf.mdf as mdf_module from ... import tool from ...blocks.utils import extract_encryption_information, extract_xml_comment, Terminated from ...blocks.v4_blocks import AttachmentBlock, FileHistory, HeaderBlock from ...blocks.v4_blocks import TextBlock as TextV4 from ...blocks.v4_constants import ( BUS_TYPE_CAN, BUS_TYPE_ETHERNET, BUS_TYPE_FLEXRAY, BUS_TYPE_LIN, BUS_TYPE_USB, CompressionAlgorithm, FLAG_CG_BUS_EVENT, ) from .. import serde from ..dialogs.advanced_search import AdvancedSearch from ..dialogs.channel_group_info import ChannelGroupInfoDialog from ..dialogs.channel_info import ChannelInfoDialog from ..dialogs.error_dialog import ErrorDialog from ..dialogs.gps_dialog import GPSDialog from ..dialogs.messagebox import MessageBox from ..dialogs.window_selection_dialog import WindowSelectionDialog from ..serde import ( ExtendedJsonDecoder, ExtendedJsonEncoder, load_channel_names_from_file, load_dsp, load_lab, ) from ..ui.file_widget import Ui_file_widget from ..utils import ( COMPRESSION_OPTIONS, GREEN, HelperChannel, run_thread_with_progress, setup_progress, ) from .attachment import Attachment from .can_bus_trace import CANBusTrace from .database_item import DatabaseItem from .flexray_bus_trace import FlexRayBusTrace from .gps import GPS from .lin_bus_trace import LINBusTrace from .mdi_area import get_functions, MdiAreaWidget, WithMDIArea from .numeric import Numeric from .plot import Plot from .tabular import Tabular from .tree import add_children from .tree_item import MinimalTreeItem from .xy import XY def _process_dict(d): new_d = {} for k, v in d.items(): if isinstance(v, dict): v = _process_dict(v) if k == "mdf_uuid": k = "origin_uuid" new_d[k] = v return new_d FRIENDLY_ATRRIBUTES = { "author": "Author", "subject": "Subject", "host": "Host", "department": "Department", "pr_project": "Project", "project": "Project Name", "pr_location": "Location", "pr_surface": "Surface", "pr_manover": "Maneuver", "pr_manufacturer": "Manufacturere", "pr_platform": "Platform", "pr_vehicle": "Vehicle", "pr_weight": "Vehicle Weight", "pr_tire": "Tire Make and Size", "pr_transmission": "Transmission", "pr_transm_mode": "Transmission Mode", "pr_specification": "Specification", "pr_test_report": "Test report", "pr_display_file": "Default display file", } class Delegate(QtWidgets.QStyledItemDelegate): def createEditor(self, parent, option, index): self.editor = QtWidgets.QPlainTextEdit(parent) self.editor.setReadOnly(True) return self.editor def setEditorData(self, editor, index): if editor: editor.setPlainText(index.data()) def setModelData(self, editor, model, index): return class FileWidget(WithMDIArea, Ui_file_widget, QtWidgets.QWidget): open_new_files = QtCore.Signal(object) full_screen_toggled = QtCore.Signal() display_file_modified = QtCore.Signal(str) def __init__( self, file_name, with_dots, subplots=False, subplots_link=False, ignore_value2text_conversions=False, display_cg_name=False, line_interconnect="line", password=None, hide_missing_channels=False, hide_disabled_channels=False, *args, **kwargs, ): self.default_folder = kwargs.pop("default_folder", "") display_file = kwargs.pop("display_file", "") databases = kwargs.pop("databases", None) show_progress = kwargs.pop("show_progress", True) process_bus_logging = kwargs.pop("process_bus_logging", True) mdf = kwargs.pop("mdf", None) self._progress = None self.loaded_display_file = Path(""), b"" super(Ui_file_widget, self).__init__(*args, **kwargs) WithMDIArea.__init__(self, comparison=False) self.setupUi(self) self._settings = QtCore.QSettings() self.uuid = os.urandom(6).hex() self.hide_missing_channels = hide_missing_channels self.hide_disabled_channels = hide_disabled_channels self.display_cg_name = display_cg_name file_name = Path(file_name) self.subplots = subplots self.subplots_link = subplots_link self.ignore_value2text_conversions = ignore_value2text_conversions self.file_name = file_name self.progress = None self.mdf = None self.info_index = None self.with_dots = with_dots self.unknown_windows = [] self._show_filter_tree = False self.line_interconnect = line_interconnect if show_progress: progress = QtWidgets.QProgressDialog(f'Opening "{self.file_name}"', "", 0, 100, self.parent()) progress.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) progress.setCancelButton(None) progress.setAutoClose(True) progress.setWindowTitle("Opening measurement") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/open.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.setWindowIcon(icon) progress.setMinimumWidth(600) progress.show() else: progress = None try: if mdf is None: if file_name.suffix.lower() in (".asc", ".blf", ".erg", ".bsig", ".dl3", ".tdms"): extension = file_name.suffix.lower().strip(".") if progress: progress.setLabelText(f"Converting from {extension} to mdf") try: from mfile import ASC, BLF, BSIG, DL3, ERG, TDMS except ImportError: from cmerg import BSIG, ERG if file_name.suffix.lower() == ".erg": cls = ERG elif file_name.suffix.lower() == ".bsig": cls = BSIG elif file_name.suffix.lower() == ".tdms": cls = TDMS elif file_name.suffix.lower() == ".asc": cls = ASC elif file_name.suffix.lower() == ".blf": cls = BLF else: cls = DL3 out_file = Path(gettempdir()) / file_name.name if file_name.suffix.lower() in (".asc", ".blf"): meas_file = cls(file_name, databases=databases) else: meas_file = cls(file_name) mdf_path = meas_file.export_mdf().save(out_file.with_suffix(".tmp.mf4")) meas_file.close() self.mdf = mdf_module.MDF(mdf_path, process_bus_logging=process_bus_logging) self.mdf.original_name = file_name self.mdf.uuid = self.uuid elif file_name.suffix.lower() == ".csv": try: with open(file_name) as csv: names = [n.strip() for n in csv.readline().split(",")] units = [n.strip() for n in csv.readline().split(",")] try: float(units[0]) except: units = dict(zip(names, units, strict=False)) else: csv.seek(0) csv.readline() units = None df = pd.read_csv(csv, header=None, names=names) df.set_index(df[names[0]], inplace=True) self.mdf = mdf_module.MDF() self.mdf.append(df, units=units) self.mdf.uuid = self.uuid self.mdf.original_name = file_name except Exception as exc: if progress: progress.cancel() print(format_exc()) raise Exception( "Could not load CSV. The first line must contain the channel names. The seconds line " "can optionally contain the channel units. The first column must be the time" ) from exc else: original_name = file_name target = mdf_module.MDF kwargs = { "name": file_name, "callback": self.update_progress, "password": password, "use_display_names": True, "process_bus_logging": process_bus_logging, } try: self.mdf = run_thread_with_progress( self, target=target, kwargs=kwargs, factor=33, offset=0, progress=progress, ) except Terminated: return self.mdf.original_name = original_name self.mdf.uuid = self.uuid else: self.mdf = mdf self.mdf.original_name = file_name self.mdf.uuid = self.uuid self.mdf.configure(raise_on_multiple_occurrences=False) if progress: progress.setLabelText("Loading graphical elements") QtWidgets.QApplication.processEvents() if progress: progress.setValue(37) self.channels_tree.setDragEnabled(True) self.mdi_area = MdiAreaWidget() self.mdi_area.add_window_request.connect(self.add_window) self.mdi_area.create_window_request.connect(self._create_window) self.mdi_area.search_request.connect(self.search) self.mdi_area.open_files_request.connect(self.open_new_files.emit) self.mdi_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.splitter.addWidget(self.mdi_area) self.channels_tree.itemDoubleClicked.connect(self.show_info) self.filter_tree.itemDoubleClicked.connect(self.show_info) self.channel_view.setCurrentIndex(-1) self.filter_view.setCurrentIndex(-1) self.filter_view.setCurrentText(self._settings.value("filter_view", "Internal file structure")) self.channel_view.currentIndexChanged.connect(partial(self._update_channel_tree, widget=self.channels_tree)) self.filter_view.currentIndexChanged.connect(partial(self._update_channel_tree, widget=self.filter_tree)) self.channel_view.setCurrentText(self._settings.value("channels_view", "Internal file structure")) if progress: progress.setValue(70) QtWidgets.QApplication.processEvents() self.raster_type_channel.toggled.connect(self.set_raster_type) self.set_raster_type() if progress: progress.setValue(90) QtWidgets.QApplication.processEvents() self.output_options.setCurrentIndex(0) self.mdf_version.currentTextChanged.connect(self.mdf_format_changed) self.mdf_version.insertItems(0, mdf_module.SUPPORTED_VERSIONS) self.mdf_version.setCurrentText("4.10") self.mdf_compression.setCurrentText("transposed deflate") self.mdf_split_size.setValue(4) self.extract_bus_format.currentTextChanged.connect(self.mdf_format_changed) self.extract_bus_format.insertItems(0, mdf_module.SUPPORTED_VERSIONS) self.extract_bus_format.setCurrentText("4.10") index = self.extract_bus_format.findText(self.mdf.version) if index >= 0: self.extract_bus_format.setCurrentIndex(index) self.extract_bus_compression.setCurrentText("transposed deflate") self.extract_bus_btn.clicked.connect(self.extract_bus_logging) self.extract_bus_csv_btn.clicked.connect(self.extract_bus_csv_logging) self.load_can_database_btn.clicked.connect(self.load_can_database) self.load_lin_database_btn.clicked.connect(self.load_lin_database) if progress: progress.setValue(99) self.empty_channels.insertItems(0, ("skip", "zeros")) self.empty_channels_bus.insertItems(0, ("skip", "zeros")) self.empty_channels_mat.insertItems(0, ("skip", "zeros")) self.empty_channels_csv.insertItems(0, ("skip", "zeros")) try: import scipy # noqa: F401 self.mat_format.insertItems(0, ("4", "5", "7.3")) except: self.mat_format.insertItems(0, ("7.3",)) self.oned_as.insertItems(0, ("row", "column")) formats = ["MDF", "ASC", "CSV"] try: from hdf5storage import savemat formats.append("MAT") except ImportError: try: from scipy.io import savemat # noqa: F401 formats.append("MAT") except ImportError: pass try: from h5py import File as HDF5 # noqa: F401 formats.append("HDF5") except ImportError: pass try: from pyarrow.parquet import write_table as write_parquet # noqa: F401 formats.append("Parquet") except ImportError: pass self.output_format.addItems(formats) self.output_format.setCurrentIndex(0) self.output_format.currentTextChanged.connect(self.output_format_changed) # self.channels_tree.itemChanged.connect(self.select) self.create_window_btn.clicked.connect(self._create_window) self.clear_filter_btn.clicked.connect(self.clear_filter) self.clear_channels_btn.clicked.connect(self.clear_channels) self.select_all_btn.clicked.connect(self.select_all_channels) self.info.setColumnWidth(0, 200) self.aspects.setCurrentIndex(0) self.aspects.currentChanged.connect(self.aspect_changed) except: if progress: progress.setValue(100) progress.deleteLater() raise else: if progress: progress.setValue(100) progress.deleteLater() self.load_channel_list_btn.clicked.connect(partial(self.load_channel_list, manually=True)) self.save_channel_list_btn.clicked.connect(self.save_channel_list) self.load_filter_list_btn.clicked.connect(self.load_filter_list) self.save_filter_list_btn.clicked.connect(self.save_filter_list) self.advanced_search_btn.clicked.connect(self.search) self.advanced_serch_filter_btn.clicked.connect(self.search) self.raster_search_btn.clicked.connect(self.raster_search) self.filter_tree.itemChanged.connect(self.filter_changed) self._selected_filter = set() self._filter_timer = QtCore.QTimer() self._filter_timer.setSingleShot(True) self._filter_timer.timeout.connect(self.update_selected_filter_channels) self.scramble_btn.clicked.connect(self.scramble) self.setAcceptDrops(True) self.apply_btn.clicked.connect(self.apply_processing) self.update_attachments() self.load_embedded_channel_list_btn.clicked.connect(self.load_embedded_display_file) self.save_embedded_channel_list_btn.clicked.connect(self.embed_display_file) if self.mdf.version >= "4.00": if self.mdf.original_name.suffix.lower() not in (".mf4", ".mf4z"): self.save_embedded_channel_list_btn.setEnabled(False) else: self.load_embedded_channel_list_btn.setEnabled(False) self.save_embedded_channel_list_btn.setEnabled(False) if self.mdf.version >= "4.00": if not any(group.channel_group.flags & FLAG_CG_BUS_EVENT for group in self.mdf.groups): self.aspects.setTabVisible(2, False) else: self.aspects.setTabVisible(2, False) databases = {} can_databases = self._settings.value("can_databases", []) buses = can_databases[::2] dbs = can_databases[1::2] databases["CAN"] = list(zip(buses, dbs, strict=False)) lin_databases = self._settings.value("lin_databases", []) buses = lin_databases[::2] dbs = lin_databases[1::2] databases["LIN"] = list(zip(buses, dbs, strict=False)) for bus, database in databases["CAN"]: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="CAN") widget.bus.setCurrentText(bus) self.can_database_list.addItem(item) self.can_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) for bus, database in databases["LIN"]: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="LIN") widget.bus.setCurrentText(bus) self.lin_database_list.addItem(item) self.lin_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) self._splitter_sizes = None if display_file: self.load_channel_list(file_name=display_file) else: default_display_file = self.mdf.header._common_properties.get("pr_display_file", "") if default_display_file: default_display_file = Path(default_display_file) if default_display_file.exists(): self.load_channel_list(file_name=default_display_file, show_progress=False) else: default_display_file = Path(self.mdf.original_name).parent / default_display_file.name if default_display_file.exists(): self.load_channel_list(file_name=default_display_file, show_progress=False) self.restore_export_setttings() self.connect_export_updates() def sizeHint(self): return QtCore.QSize(1, 1) def set_raster_type(self, event=None): if self.raster_type_channel.isChecked(): self.raster_channel.setEnabled(True) self.raster_search_btn.setEnabled(True) self.raster.setEnabled(False) self.raster.setValue(0) else: self.raster_search_btn.setEnabled(False) self.raster_channel.setEnabled(False) self.raster.setEnabled(True) self.raster_channel.setCurrentIndex(0) def update_all_channel_trees(self): widgetList = [self.channels_tree, self.filter_tree] for widget in widgetList: self._update_channel_tree(widget=widget) def _update_channel_tree(self, index=None, widget=None, force=False): if widget is None: widget = self.channels_tree if not force: if widget is self.channels_tree and self.channel_view.currentIndex() == -1: return elif widget is self.filter_tree and (self.filter_view.currentIndex() == -1): return view = self.channel_view if widget is self.channels_tree else self.filter_view iterator = QtWidgets.QTreeWidgetItemIterator(widget) signals = set() if widget.mode == "Internal file structure": while item := iterator.value(): if item.entry[1] != 0xFFFFFFFFFFFFFFFF: if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.add(item.entry) iterator += 1 else: while item := iterator.value(): if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.add(item.entry) iterator += 1 widget.collapseAll() widget.clear() widget.mode = view.currentText() if widget.mode == "Natural sort": items = [] for i, group in enumerate(self.mdf.groups): for j, ch in enumerate(group.channels): entry = i, j channel = MinimalTreeItem(entry, ch.name, strings=[ch.name], origin_uuid=self.uuid) channel.setToolTip(0, f"{ch.name} @ group {i}, index {j}") if entry in signals: channel.setCheckState(0, QtCore.Qt.CheckState.Checked) else: channel.setCheckState(0, QtCore.Qt.CheckState.Unchecked) items.append(channel) if len(items) < 30000: items = natsorted(items, key=lambda x: x.name) else: items.sort(key=lambda x: x.name) widget.addTopLevelItems(items) elif widget.mode == "Internal file structure": items = [] for i, group in enumerate(self.mdf.groups): entry = i, 0xFFFFFFFFFFFFFFFF channel_group = MinimalTreeItem(entry, origin_uuid=self.uuid) comment = extract_xml_comment(group.channel_group.comment) if self.mdf.version >= "4.00" and group.channel_group.acq_source: source = group.channel_group.acq_source if source.bus_type == BUS_TYPE_CAN: ico = ":/bus_can.png" elif source.bus_type == BUS_TYPE_LIN: ico = ":/bus_lin.png" elif source.bus_type == BUS_TYPE_ETHERNET: ico = ":/bus_eth.png" elif source.bus_type == BUS_TYPE_USB: ico = ":/bus_usb.png" elif source.bus_type == BUS_TYPE_FLEXRAY: ico = ":/bus_flx.png" else: ico = None if ico is not None: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(ico), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) channel_group.setIcon(0, icon) if self.display_cg_name: acq_name = getattr(group.channel_group, "acq_name", "") if acq_name: base_name = f"CG {i} {acq_name}" else: base_name = f"CG {i}" if comment and acq_name != comment: name = base_name + f" ({comment})" else: name = base_name else: base_name = f"Channel group {i}" if comment: name = base_name + f" ({comment})" else: name = base_name channel_group.setText(0, name) channel_group.setFlags( channel_group.flags() | QtCore.Qt.ItemFlag.ItemIsAutoTristate | QtCore.Qt.ItemFlag.ItemIsUserCheckable ) if group.channel_group.cycles_nr: channel_group.setForeground(0, QtGui.QBrush(QtGui.QColor(GREEN))) items.append(channel_group) channels = [HelperChannel(name=ch.name, entry=(i, j)) for j, ch in enumerate(group.channels)] add_children( channel_group, channels, group.channel_dependencies, signals, entries=None, origin_uuid=self.uuid, version=self.mdf.version, ) widget.addTopLevelItems(items) else: items = [] for entry in signals: gp_index, ch_index = entry ch = self.mdf.groups[gp_index].channels[ch_index] channel = MinimalTreeItem(entry, ch.name, strings=[ch.name], origin_uuid=self.uuid) channel.setToolTip(0, f"{ch.name} @ group {gp_index}, index {ch_index}") channel.setCheckState(0, QtCore.Qt.CheckState.Checked) items.append(channel) if len(items) < 30000: items = natsorted(items, key=lambda x: x.name) else: items.sort(key=lambda x: x.name) widget.addTopLevelItems(items) setting = "channels_view" if widget is self.channels_tree else "filter_view" self._settings.setValue(setting, view.currentText()) def output_format_changed(self, name): if name == "MDF": self.output_options.setCurrentWidget(self.MDF) elif name == "MAT": self.output_options.setCurrentWidget(self.MAT) self.export_compression_mat.clear() self.export_compression_mat.addItems(["enabled", "disabled"]) self.export_compression_mat.setCurrentIndex(0) elif name == "CSV": self.output_options.setCurrentWidget(self.CSV) elif name == "ASC": self.output_options.setCurrentWidget(self.page) else: self.output_options.setCurrentWidget(self.HDF5) if name == "Parquet": self.export_compression.setEnabled(True) self.export_compression.clear() self.export_compression.addItems(["GZIP", "SNAPPY", "LZ4"]) self.export_compression.setCurrentIndex(0) elif name == "HDF5": self.export_compression.setEnabled(True) self.export_compression.clear() self.export_compression.addItems(["gzip", "lzf", "szip"]) self.export_compression.setCurrentIndex(0) elif name: self.export_compression.clear() self.export_compression.setEnabled(False) def search(self, event=None): toggle_frames = False if self.aspects.tabText(self.aspects.currentIndex()) == "Channels": show_add_window = True show_apply = True apply_text = "Check channels" widget = self.channels_tree view = self.channel_view if self._frameless_windows: toggle_frames = True self.toggle_frames() else: show_add_window = False show_apply = True apply_text = "Check channels" widget = self.filter_tree view = self.filter_view dlg = AdvancedSearch( self.mdf, show_add_window=show_add_window, show_apply=show_apply, apply_text=apply_text, parent=self, ) dlg.setModal(True) dlg.exec_() result, pattern_window = dlg.result, dlg.pattern_window if result: if pattern_window: options = [ "New pattern based plot window", "New pattern based numeric window", "New pattern based tabular window", ] dialog = WindowSelectionDialog(options=options, parent=self) dialog.setModal(True) dialog.exec_() if dialog.result(): window_type = dialog.selected_type() if window_type == "New pattern based plot window": self.load_window( { "type": "Plot", "title": result["pattern"], "configuration": {"channels": [], "pattern": result}, }, ) elif window_type == "New pattern based numeric window": self.load_window( { "type": "Numeric", "title": result["pattern"], "configuration": { "channels": [], "pattern": result, "format": "phys", }, } ) elif window_type == "New pattern based tabular window": self.load_window( { "type": "Tabular", "title": result["pattern"], "configuration": { "channels": [], "pattern": result, "filters": [], "time_as_date": False, "sorted": False, "filtered": False, }, } ) else: names = set() if view.currentText() == "Internal file structure": iterator = QtWidgets.QTreeWidgetItemIterator(widget) dg_cntr = -1 ch_cntr = 0 while item := iterator.value(): if item.parent() is None: iterator += 1 dg_cntr += 1 ch_cntr = 0 continue entry = (dg_cntr, ch_cntr) if entry in result: item.setCheckState(0, QtCore.Qt.CheckState.Checked) names.add((result[entry], dg_cntr, ch_cntr)) iterator += 1 ch_cntr += 1 elif view.currentText() == "Selected channels only": iterator = QtWidgets.QTreeWidgetItemIterator(widget) signals = set() while item := iterator.value(): if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.add((item.text(0), *item.entry)) iterator += 1 names = {(_name, *entry) for entry, _name in result.items()} signals = signals | names widget.clear() self._selected_filter = {e[0] for e in signals} items = [] for name, gp_index, ch_index in signals: entry = gp_index, ch_index ch = self.mdf.groups[gp_index].channels[ch_index] channel = MinimalTreeItem(entry, ch.name, strings=[ch.name], origin_uuid=self.uuid) channel.setCheckState(0, QtCore.Qt.CheckState.Checked) items.append(channel) if len(items) < 30000: items = natsorted(items, key=lambda x: x.name) else: items.sort(key=lambda x: x.name) widget.addTopLevelItems(items) self.update_selected_filter_channels() else: iterator = QtWidgets.QTreeWidgetItemIterator(widget) while item := iterator.value(): if item.entry in result: item.setCheckState(0, QtCore.Qt.CheckState.Checked) names.add((result[item.entry], *item.entry)) iterator += 1 if dlg.add_window_request: options = [ "New plot window", "New numeric window", "New tabular window", ] + [ mdi.windowTitle() for mdi in self.mdi_area.subWindowList() if not isinstance( mdi.widget(), (CANBusTrace, LINBusTrace, FlexRayBusTrace, GPS, XY), ) ] if active_window := self.mdi_area.activeSubWindow(): default = active_window.windowTitle() else: default = None dialog = WindowSelectionDialog(options=options, default=default, parent=self) dialog.setModal(True) dialog.exec_() if dialog.result(): window_type = dialog.selected_type() disable_new_channels = dialog.disable_new_channels() signals = natsorted( [ { "name": name, "group_index": dg_cntr, "channel_index": ch_cntr, "origin_uuid": self.uuid, "type": "channel", "ranges": [], "uuid": os.urandom(6).hex(), "enabled": not disable_new_channels, } for name, dg_cntr, ch_cntr in names ], key=lambda x: ( x["name"], x["group_index"], x["channel_index"], ), ) if window_type == "New plot window": self.add_window(["Plot", signals]) elif window_type == "New numeric window": self.add_window(["Numeric", signals]) elif window_type == "New tabular window": self.add_window(["Tabular", signals]) else: for mdi in self.mdi_area.subWindowList(): if mdi.windowTitle() == window_type: self.add_new_channels(signals, mdi.widget()) break if toggle_frames: self.toggle_frames() def to_config(self): config = {} iterator = QtWidgets.QTreeWidgetItemIterator(self.channels_tree) signals = [] if self.channel_view.currentText() == "Internal file structure": while item := iterator.value(): if item.parent() is None: iterator += 1 continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.append(item.text(0)) iterator += 1 else: while item := iterator.value(): if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.append(item.text(0)) iterator += 1 config["selected_channels"] = signals windows = list(self.unknown_windows) for window in self.mdi_area.subWindowList(): wid = window.widget() geometry = window.geometry() window_config = { "title": window.windowTitle(), "configuration": wid.to_config(), "geometry": [ geometry.x(), geometry.y(), geometry.width(), geometry.height(), ], "maximized": window.isMaximized(), "minimized": window.isMinimized(), } if isinstance(wid, Numeric): window_config["type"] = "Numeric" elif isinstance(wid, Plot): window_config["type"] = "Plot" if wid.closed: continue elif isinstance(wid, Tabular): window_config["type"] = "Tabular" elif isinstance(wid, GPS): window_config["type"] = "GPS" elif isinstance(wid, CANBusTrace): window_config["type"] = "CAN Bus Trace" elif isinstance(wid, FlexRayBusTrace): window_config["type"] = "FlexRay Bus Trace" elif isinstance(wid, LINBusTrace): window_config["type"] = "LIN Bus Trace" elif isinstance(wid, XY): window_config["type"] = "XY" else: continue windows.append(window_config) current_window = self.mdi_area.currentSubWindow() config["windows"] = windows config["active_window"] = current_window.windowTitle() if current_window else "" config["functions"] = self.functions config["global_variables"] = "\n".join([line for line in self.global_variables.splitlines() if line]) return config def save_channel_list(self, event=None, file_name=None): if file_name is None: if self.loaded_display_file[0].is_file(): dir = str(self.loaded_display_file[0]) else: dir = self.default_folder file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output display file", dir, "Display files (*.dspf)", ) if file_name: file_name = Path(file_name).with_suffix(".dspf") file_name.write_text(json.dumps(self.to_config(), indent=2, cls=ExtendedJsonEncoder)) worker = md5() worker.update(file_name.read_bytes()) self.loaded_display_file = file_name, worker.hexdigest() self.display_file_modified.emit(Path(self.loaded_display_file[0]).name) def load_channel_list(self, event=None, file_name=None, manually=False, show_progress=True): if file_name is None: file_name, _ = QtWidgets.QFileDialog.getOpenFileName( self, "Select channel list file", self.default_folder, "Config file (*.cfg);;TXT files (*.txt);;Display files (*.dsp *.dspf);;CANape Lab file (*.lab);;All file types (*.cfg *.dsp *.dspf *.lab *.txt)", "All file types (*.cfg *.dsp *.dspf *.lab *.txt)", ) if not file_name or Path(file_name).suffix.lower() not in ( ".cfg", ".dsp", ".dspf", ".lab", ".txt", ): return if not isinstance(file_name, dict): file_name = Path(file_name) extension = file_name.suffix.lower() if extension == ".dsp": palette = self.palette() info = load_dsp(file_name, palette.base().color().name()) if info.get("has_virtual_channels", False): message = ( "The DSP file contains virtual channels that are not supported.\n" 'For tracking purpose, the virtual channels will appear as regular (no computation) channels inside the group "Datalyser Virtual channels"' ) c_functions = info.get("c_functions", []) msg = MessageBox( MessageBox.Information, "DSP loading warning", message, parent=self, defaultButton=MessageBox.Ok, ) if c_functions: msg.setInformativeText( 'The user defined C function will NOT be available. Press "Show details" for the complete list' ) msg.setDetailedText("\n".join(c_functions)) msg.exec() channels = info.get("display", []) elif extension == ".lab": info = load_lab(file_name) if not info: return section, ok = QtWidgets.QInputDialog.getItem( self, "Select section", "Available sections:", list(info), 0, False, ) if not ok: return channels = [name.split(";")[0] for name in info[section]] elif extension == ".cfg": with open(file_name) as infile: info = json.load(infile, cls=ExtendedJsonDecoder) channels = info.get("selected_channels", []) elif extension == ".txt": try: with open(file_name) as infile: info = json.load(infile, cls=ExtendedJsonDecoder) channels = info.get("selected_channels", []) except: with open(file_name) as infile: channels = [line.strip() for line in infile.readlines()] channels = [name for name in channels if name] info = { "selected_channels": [], "windows": [ { "title": "Plot 0", "configuration": { "channels": [ { "type": "channel", "name": name, "unit": "", "flags": 0, "enabled": True, "individual_axis": False, "common_axis": False, "color": serde.COLORS[i % serde.COLORS_COUNT], "computed": False, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [0.0, 10], "origin_uuid": "df21b72e1fdd", } for i, name in enumerate(channels) ], "pattern": {}, "splitter": [732, 729, 0], "x_range": [-0.947017678447, 30.291065678447], "y_axis_width": 48.0, "grid": [False, False], "cursor_precision": 15, "font_size": 9, "locked": False, "common_axis_y_range": [0.0, 1.0], "channels_header": [732, [568, 83, 41, 20, 20, 0]], "channels_header_columns_visible": [True, True, True, True, True, False], "hide_axes": False, "hide_selected_channel_value_panel": False, "focused_mode": False, "delta_mode": "delta", "hide_bookmarks": True, "hide_missing_channels": False, "hide_disabled_channels": False, }, "geometry": [0, 0, 1475, 924], "maximized": True, "minimized": False, "type": "Plot", } ], "active_window": "Plot 0", "functions": {}, "global_variables": "", } elif extension == ".dspf": with open(file_name) as infile: info = json.load(infile, cls=ExtendedJsonDecoder) channels = info.get("selected_channels", []) original_file_name = Path(self.mdf.original_name) if ( original_file_name.suffix.lower() in ( ".mf4", ".mf4z", ) and not self.mdf.header._common_properties.get("pr_display_file", "") and manually ): result = MessageBox.question( self, "Set default display file?", "Would you like to use this display file as the default display file for this measurement file?", ) if result == MessageBox.Yes: display_file_name = str(Path(file_name).resolve()) _password = self.mdf._mdf._password uuid = self.mdf.uuid header = self.mdf.header self.mdf.close() windows = list(self.mdi_area.subWindowList()) for window in windows: widget = window.widget() self.mdi_area.removeSubWindow(window) widget.setParent(None) widget.close() widget.deleteLater() window.close() suffix = original_file_name.suffix.lower() if suffix == ".mf4z": with ZipFile(original_file_name, allowZip64=True) as archive: files = archive.namelist() if len(files) != 1: return fname = files[0] if Path(fname).suffix.lower() != ".mf4": return tmpdir = gettempdir() mdf_file_name = archive.extract(fname, tmpdir) mdf_file_name = Path(tmpdir) / mdf_file_name else: mdf_file_name = original_file_name with open(mdf_file_name, "r+b") as mdf: try: header._common_properties["pr_display_file"] = display_file_name comment = TextV4(meta=True, text=header.comment) mdf.seek(0, 2) address = mdf.tell() align = address % 8 if align: mdf.write(b"\0" * (8 - align)) address += 8 - align mdf.write(bytes(comment)) header.comment_addr = address mdf.seek(header.address) mdf.write(bytes(header)) except: print(format_exc()) return if suffix == ".mf4z": zipped_mf4 = ZipFile(original_file_name, "w", compression=ZIP_DEFLATED) zipped_mf4.write( str(mdf_file_name), original_file_name.with_suffix(".mf4").name, compresslevel=1, ) zipped_mf4.close() mdf_file_name.unlink() self.mdf = mdf_module.MDF( name=original_file_name, callback=self.update_progress, password=_password, use_display_names=True, ) self.mdf.original_name = original_file_name self.mdf.uuid = uuid else: return worker = md5() worker.update(file_name.read_bytes()) self.loaded_display_file = file_name, worker.hexdigest() else: extension = None info = file_name channels = info.get("selected_channels", []) self.loaded_display_file = Path(info.get("display_file_name", "")), b"" self.functions.update(info.get("functions", {})) self.global_variables = f"{self.global_variables}\n{info.get('global_variables', '')}" self.global_variables = "\n".join([line for line in self.global_variables.splitlines() if line]) if channels: iterator = QtWidgets.QTreeWidgetItemIterator(self.channels_tree) if self.channel_view.currentText() == "Internal file structure": while item := iterator.value(): if item.parent() is None: iterator += 1 continue channel_name = item.text(0) if channel_name in channels: item.setCheckState(0, QtCore.Qt.CheckState.Checked) channels.pop(channels.index(channel_name)) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 else: while item := iterator.value(): channel_name = item.text(0) if channel_name in channels: item.setCheckState(0, QtCore.Qt.CheckState.Checked) channels.pop(channels.index(channel_name)) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 if extension in (".dspf", ".dsp"): new_functions = {} if "functions" in info: for name, definition in info["functions"].items(): if name in self.functions: if self.functions[name] != definition: new_functions[os.urandom(6).hex()] = { "name": name, "definition": definition, } else: new_functions[os.urandom(6).hex()] = { "name": name, "definition": definition, } else: for window in info["windows"]: if window["type"] == "Plot": for name, definition in get_functions(window["configuration"]["channels"]).items(): if name in self.functions: if self.functions[name] != definition: new_functions[os.urandom(6).hex()] = { "name": name, "definition": definition, } else: new_functions[os.urandom(6).hex()] = { "name": name, "definition": definition, } if new_functions or info.get("global_variables", "") != self.global_variables: self.update_functions({}, new_functions, f"{self.global_variables}\n{info.get('global_variables', '')}") self.clear_windows() windows = info.get("windows", []) errors = {} if windows: count = len(windows) if show_progress: progress = setup_progress( parent=self, title="Loading display windows", message="", icon_name="window", ) progress.setRange(0, count - 1) progress.resize(500, progress.height()) else: progress = None for i, window in enumerate(windows, 1): window = _process_dict(window) window_type = window["type"] window_title = window["title"] if progress: progress.setLabelText(f"Loading {window_type} window <{window_title}>") QtWidgets.QApplication.processEvents() try: self.load_window(window) if progress: progress.setValue(i) except: print(format_exc()) errors[window_title] = format_exc() if progress: progress.cancel() active_window = info.get("active_window", "") for window in self.mdi_area.subWindowList(): if window.windowTitle() == active_window: self.mdi_area.setActiveSubWindow(window) break self.display_file_modified.emit(Path(self.loaded_display_file[0]).name) if errors: ErrorDialog( title="Errors while loading display file", message=f"There were errors while loading the following windows : {list(errors)}", trace="\n\n".join(list(errors.values())), parent=self, ).exec() def save_filter_list(self): file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output filter list file", self.default_folder, "CANape Lab file (*.lab)", "CANape Lab file (*.lab)", ) if file_name: file_name = Path(file_name) iterator = QtWidgets.QTreeWidgetItemIterator(self.filter_tree) signals = [] if self.filter_view.currentText() == "Internal file structure": while item := iterator.value(): iterator += 1 if item.parent() is None: continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.append(item.text(0)) else: while item := iterator.value(): iterator += 1 if item.checkState(0) == QtCore.Qt.CheckState.Checked: signals.append(item.text(0)) suffix = file_name.suffix.lower() if suffix == ".lab": section_name, ok = QtWidgets.QInputDialog.getText( self, "Provide .lab file ASAP section name", "Section name:", ) if not ok: section_name = "Selected channels" with open(file_name, "w") as output: if suffix == ".lab": output.write( """[SETTINGS] Version;V1.1 MultiRasterSeparator;& """ ) output.write(f"[{section_name}]\n") output.write("\n".join(natsorted(signals))) def load_filter_list(self, event=None, file_name=None): if file_name is None: file_name, _ = QtWidgets.QFileDialog.getOpenFileName( self, "Select channel list file", self.default_folder, "Config file (*.cfg);;Display files (*.dsp *.dspf);;CANape Lab file (*.lab);;All file types (*.cfg *.dsp *.dspf *.lab *.txt)", "All file types (*.cfg *.dsp *.dspf *.lab *.txt)", ) if file_name is None or Path(file_name).suffix.lower() not in ( ".cfg", ".dsp", ".dspf", ".lab", ".txt", ): return if not isinstance(file_name, dict): file_name = Path(file_name) if file_name.suffix.lower() == ".lab": info = load_lab(file_name) if info: if len(info) > 1: lab_section, ok = QtWidgets.QInputDialog.getItem( self, "Please select the ASAP section name", "Available sections:", list(info), 0, False, ) if ok: channels = info[lab_section] else: return else: channels = list(info.values())[0] channels = [name.split(";")[0] for name in channels] else: channels = load_channel_names_from_file(file_name) else: info = file_name channels = info.get("selected_channels", []) if channels: iterator = QtWidgets.QTreeWidgetItemIterator(self.filter_tree) if self.filter_view.currentText() == "Internal file structure": while item := iterator.value(): iterator += 1 if item.parent() is None: continue channel_name = item.text(0) if channel_name in channels: item.setCheckState(0, QtCore.Qt.CheckState.Checked) channels.pop(channels.index(channel_name)) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) elif self.filter_view.currentText() == "Natural sort": while item := iterator.value(): channel_name = item.text(0) if channel_name in channels: item.setCheckState(0, QtCore.Qt.CheckState.Checked) channels.pop(channels.index(channel_name)) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 else: items = [] self.filter_tree.clear() self._selected_filter = set(channels) for i, gp in enumerate(self.mdf.groups): for j, ch in enumerate(gp.channels): if ch.name in channels: entry = i, j channel = MinimalTreeItem(entry, ch.name, strings=[ch.name], origin_uuid=self.uuid) channel.setCheckState(0, QtCore.Qt.CheckState.Checked) items.append(channel) channels.pop(channels.index(ch.name)) if len(items) < 30000: items = natsorted(items, key=lambda x: x.name) else: items.sort(key=lambda x: x.name) self.filter_tree.addTopLevelItems(items) self.update_selected_filter_channels() def compute_cut_hints(self): t_min = [] t_max = [] for i, group in enumerate(self.mdf.groups): cycles_nr = group.channel_group.cycles_nr if cycles_nr: master_min = self.mdf.get_master(i, record_offset=0, record_count=1) if len(master_min): t_min.append(master_min[0]) self.mdf._mdf._master_channel_cache.clear() master_max = self.mdf.get_master(i, record_offset=cycles_nr - 1, record_count=1) if len(master_max): t_max.append(master_max[0]) self.mdf._mdf._master_channel_cache.clear() if t_min: time_range = t_min, t_max self.cut_start.setRange(*time_range) self.cut_stop.setRange(*time_range) self.cut_interval.setText("Cut interval ({:.6f}s - {:.6f}s)".format(*time_range)) else: self.cut_start.setRange(0, 0) self.cut_stop.setRange(0, 0) self.cut_interval.setText("Empty measurement") def update_progress(self, current_index, max_index): self.progress = current_index, max_index def show_info(self, item, column): group_index, index = item.entry if index == 0xFFFFFFFFFFFFFFFF: group = self.mdf.groups[group_index] msg = ChannelGroupInfoDialog(self.mdf, group, group_index, self) msg.show() else: channel = self.mdf.get_channel_metadata(group=group_index, index=index) msg = ChannelInfoDialog(channel, self) msg.show() def clear_filter(self): iterator = QtWidgets.QTreeWidgetItemIterator(self.filter_tree) if self.filter_view.currentIndex() == 1: while item := iterator.value(): if item.parent() is None: item.setExpanded(False) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 else: while item := iterator.value(): item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 def clear_channels(self): iterator = QtWidgets.QTreeWidgetItemIterator(self.channels_tree) if self.channel_view.currentIndex() == 1: while item := iterator.value(): if item.parent() is None: item.setExpanded(False) else: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 else: while item := iterator.value(): item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 def select_all_channels(self): iterator = QtWidgets.QTreeWidgetItemIterator(self.channels_tree) if self.channel_view.currentIndex() == 1: while item := iterator.value(): if item.parent() is None: item.setExpanded(False) else: item.setCheckState(0, QtCore.Qt.CheckState.Checked) iterator += 1 else: while item := iterator.value(): item.setCheckState(0, QtCore.Qt.CheckState.Checked) iterator += 1 def close(self): if self.mdf is not None: mdf_name = self.mdf.name self.mdf.close() if mdf_name != self.mdf.original_name and mdf_name.is_file(): mdf_name.unlink() self.channels_tree.clear() self.filter_tree.clear() self.clear_windows() self.mdf = None def _create_window(self, event=None, window_type=None): if window_type is None: dialog = WindowSelectionDialog( options=( "Plot", "Numeric", "Tabular", "CAN Bus Trace", "FlexRay Bus Trace", "LIN Bus Trace", "GPS", "XY", ), parent=self, ) dialog.setModal(True) dialog.exec_() if dialog.result(): window_type = dialog.selected_type() else: window_type = None disable_new_channels = dialog.disable_new_channels() else: disable_new_channels = False if window_type is None: return elif window_type in ("CAN Bus Trace", "FlexRay Bus Trace", "LIN Bus Trace", "XY"): signals = [] elif window_type == "GPS": target = "(latitude|gps_y)" sig = re.compile(target, re.IGNORECASE) latitude = "" for name in self.mdf.channels_db: if sig.fullmatch(name): latitude = name break else: for name in self.mdf.channels_db: if sig.search(name): latitude = name break target = "(longitude|gps_x)" sig = re.compile(target, re.IGNORECASE) longitude = "" for name in self.mdf.channels_db: if sig.fullmatch(name): longitude = name break else: for name in self.mdf.channels_db: if sig.search(name): longitude = name break dlg = GPSDialog( self.mdf, latitude=latitude, longitude=longitude, parent=self, ) dlg.setModal(True) dlg.exec_() if dlg.valid: latitude = dlg.latitude.text().strip() longitude = dlg.longitude.text().strip() signals = [ (name, *self.mdf.whereis(name)[0], self.uuid, "channel") for name in [latitude, longitude] if name in self.mdf ] if len(signals) != 2: return else: return else: try: iter(event) signals = event except: iterator = QtWidgets.QTreeWidgetItemIterator(self.channels_tree) signals = [] if self.channel_view.currentIndex() == 1: while item := iterator.value(): if item.parent() is None: iterator += 1 continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: group, index = item.entry ch = self.mdf.groups[group].channels[index] if not ch.component_addr: signals.append( { "name": ch.name, "group_index": group, "channel_index": index, "origin_uuid": self.uuid, "type": "channel", "ranges": [], "uuid": os.urandom(6).hex(), "enabled": not disable_new_channels, } ) iterator += 1 else: while item := iterator.value(): if item.checkState(0) == QtCore.Qt.CheckState.Checked: group, index = item.entry ch = self.mdf.groups[group].channels[index] if not ch.component_addr: signals.append( { "name": ch.name, "group_index": group, "channel_index": index, "origin_uuid": self.uuid, "type": "channel", "ranges": [], "uuid": os.urandom(6).hex(), "enabled": not disable_new_channels, } ) iterator += 1 self.add_window((window_type, signals)) def scramble_thread(self, progress): icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/scramble.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Scrambling measurement") progress.signals.setLabelText.emit(f'Scrambling "{self.file_name}"') # scrambling self.mdf mdf_module.MDF.scramble(name=self.file_name, progress=progress) def scramble_finished(self): if self._progress.error is None: path = Path(self.file_name) self.open_new_files.emit([str(path.with_suffix(f".scrambled{path.suffix}"))]) self._progress = None def scramble(self, event): self._progress = setup_progress(parent=self) self._progress.finished.connect(self.scramble_finished) self._progress.run_thread_with_progress( target=self.scramble_thread, args=(), kwargs={}, ) @QtCore.Slot(str) def mdf_format_changed(self, format): sender = self.sender() options = COMPRESSION_OPTIONS.get(format, ()) if sender is self.extract_bus_format: self.extract_bus_compression.clear() self.extract_bus_compression.addItems(options) elif sender is self.mdf_version: self.mdf_compression.clear() self.mdf_compression.addItems(options) def extract_bus_logging_finished(self): if self._progress.error is None: file_name, message = self._progress.result self.output_info_bus.setPlainText("\n".join(message)) self.open_new_files.emit([str(file_name)]) self._progress = None def extract_bus_logging(self, event): version = self.extract_bus_format.currentText() self.output_info_bus.setPlainText("") database_files = {} count1 = self.can_database_list.count() if count1: database_files["CAN"] = [] for i in range(count1): item = self.can_database_list.item(i) widget = self.can_database_list.itemWidget(item) database_files["CAN"].append((widget.database.text(), widget.bus.currentIndex())) count2 = self.lin_database_list.count() if count2: database_files["LIN"] = [] for i in range(count2): item = self.lin_database_list.item(i) widget = self.lin_database_list.itemWidget(item) database_files["LIN"].append((widget.database.text(), widget.bus.currentIndex())) compression = self.extract_bus_compression.currentIndex() if version < "4.00": filter = "MDF version 3 files (*.dat *.mdf)" suffix = ".mdf" else: filter = "MDF version 4 files (*.mf4)" suffix = ".mf4" if not (count1 + count2): return file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Save as measurement file", "", f"{filter};;All files (*.*)", filter, ) if not file_name: return self._progress = setup_progress(parent=self) self._progress.finished.connect(self.extract_bus_logging_finished) self._progress.run_thread_with_progress( target=self.extract_bus_logging_thread, args=(file_name, suffix, database_files, version, compression), kwargs={}, ) def extract_bus_logging_thread(self, file_name, suffix, database_files, version, compression, progress): file_name = Path(file_name).with_suffix(suffix) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/down.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Extract Bus logging") progress.signals.setLabelText.emit(f'Extracting Bus signals from "{self.file_name}"') # convert self.mdf mdf = self.mdf.extract_bus_logging( database_files=database_files, version=version, prefix=self.prefix.text().strip(), progress=progress, ) # then save it progress.signals.setLabelText.emit(f'Saving file to "{file_name}"') mdf.save( dst=file_name, compression=compression, overwrite=True, progress=progress, ) bus_call_info = dict(self.mdf.last_call_info) message = [] for bus, call_info in bus_call_info.items(): found_id_count = sum(len(e) for e in call_info["found_ids"].values()) message += [ f"{bus} bus summary:", f"- {found_id_count} of {len(call_info['total_unique_ids'])} IDs in the MDF4 file were matched in the DBC and converted", ] if call_info["unknown_id_count"]: message.append(f"- {call_info['unknown_id_count']} unknown IDs in the MDF4 file") else: message.append("- no unknown IDs in the MDF4 file") message += [ "", "Detailed information:", "", f"The following {bus} IDs were in the MDF log file and matched in the DBC:", ] for dbc_name, found_ids in call_info["found_ids"].items(): for msg_id_info, msg_name in sorted(found_ids): if msg_id_info[2]: pgn, sa = msg_id_info[:2] message.append(f"- PGN=0x{pgn:X} SA=0x{sa:X} --> {msg_name} in <{dbc_name}>") else: msg_id, extended = msg_id_info[:2] message.append(f"- 0x{msg_id:X} {extended=} --> {msg_name} in <{dbc_name}>") message += [ "", f"The following {bus} IDs were in the MDF log file, but not matched in the DBC:", ] unknown_standard_can = sorted([e for e in call_info["unknown_ids"] if isinstance(e, int)]) unknown_j1939 = sorted([e for e in call_info["unknown_ids"] if not isinstance(e, int)]) for msg_id in unknown_standard_can: message.append(f"- 0x{msg_id:X}") for pgn, sa in unknown_j1939: message.append(f"- PGN=0x{pgn:X} SA=0x{sa:X}") message.append("\n\n") return file_name, message def extract_bus_csv_logging_finished(self): if self._progress.error is None: message = self._progress.result self.output_info_bus.setPlainText("\n".join(message)) self._progress = None def extract_bus_csv_logging(self, event): version = self.extract_bus_format.currentText() self.output_info_bus.setPlainText("") database_files = {} count1 = self.can_database_list.count() if count1: database_files["CAN"] = [] for i in range(count1): item = self.can_database_list.item(i) widget = self.can_database_list.itemWidget(item) database_files["CAN"].append((widget.database.text(), widget.bus.currentIndex())) count2 = self.lin_database_list.count() if count2: database_files["LIN"] = [] for i in range(count2): item = self.lin_database_list.item(i) widget = self.lin_database_list.itemWidget(item) database_files["LIN"].append((widget.database.text(), widget.bus.currentIndex())) if not (count1 + count2): return single_time_base = self.single_time_base_bus.checkState() == QtCore.Qt.CheckState.Checked time_from_zero = self.time_from_zero_bus.checkState() == QtCore.Qt.CheckState.Checked empty_channels = self.empty_channels_bus.currentText() raster = self.export_raster_bus.value() time_as_date = self.bus_time_as_date.checkState() == QtCore.Qt.CheckState.Checked delimiter = self.delimiter_bus.text() or "," doublequote = self.doublequote_bus.checkState() == QtCore.Qt.CheckState.Checked escapechar = self.escapechar_bus.text() or None lineterminator = self.lineterminator_bus.text().replace("\\r", "\r").replace("\\n", "\n") quotechar = self.quotechar_bus.text() or '"' quoting = self.quoting_bus.currentText() add_units = self.add_units_bus.checkState() == QtCore.Qt.CheckState.Checked if delimiter == "\\t": delimiter = "\t" file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output CSV file", "", "CSV (*.csv);;All files (*.*)", "CSV (*.csv)", ) if not file_name: return self._progress = setup_progress(parent=self) self._progress.finished.connect(self.extract_bus_csv_logging_finished) self._progress.run_thread_with_progress( target=self.extract_bus_csv_logging_thread, args=( file_name, database_files, version, single_time_base, time_from_zero, empty_channels, raster, time_as_date, delimiter, doublequote, escapechar, lineterminator, quotechar, quoting, add_units, ), kwargs={}, ) def extract_bus_csv_logging_thread( self, file_name, database_files, version, single_time_base, time_from_zero, empty_channels, raster, time_as_date, delimiter, doublequote, escapechar, lineterminator, quotechar, quoting, add_units, progress, ): icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/csv.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Extract Bus logging to CSV") progress.signals.setLabelText.emit(f'Extracting Bus signals from "{self.file_name}"') # convert self.mdf mdf = self.mdf.extract_bus_logging( database_files=database_files, version=version, prefix=self.prefix.text().strip(), progress=progress, ) # then save it progress.signals.setLabelText.emit(f'Saving file to "{file_name}"') mdf.configure( integer_interpolation=self.mdf._mdf._integer_interpolation, float_interpolation=self.mdf._mdf._float_interpolation, ) mdf.export( fmt="csv", filename=file_name, single_time_base=single_time_base, time_from_zero=time_from_zero, empty_channels=empty_channels, raster=raster or None, time_as_date=time_as_date, ignore_value2text_conversions=self.ignore_value2text_conversions, delimiter=delimiter, doublequote=doublequote, escapechar=escapechar, lineterminator=lineterminator, quotechar=quotechar, quoting=quoting, add_units=add_units, progress=progress, ) bus_call_info = dict(self.mdf.last_call_info) message = [] for bus, call_info in bus_call_info.items(): found_id_count = sum(len(e) for e in call_info["found_ids"].values()) message += [ f"{bus} bus summary:", f"- {found_id_count} of {len(call_info['total_unique_ids'])} IDs in the MDF4 file were matched in the DBC and converted", ] if call_info["unknown_id_count"]: message.append(f"- {call_info['unknown_id_count']} unknown IDs in the MDF4 file") else: message.append("- no unknown IDs in the MDF4 file") message += [ "", "Detailed information:", "", f"The following {bus} IDs were in the MDF log file and matched in the DBC:", ] for dbc_name, found_ids in call_info["found_ids"].items(): for msg_id, msg_name in sorted(found_ids): try: message.append(f"- 0x{msg_id:X} --> {msg_name} in <{dbc_name}>") except: pgn, sa = msg_id message.append(f"- PGN=0x{pgn:X} SA=0x{sa:X} --> {msg_name} in <{dbc_name}>") message += [ "", f"The following {bus} IDs were in the MDF log file, but not matched in the DBC:", ] for msg_id in sorted(call_info["unknown_ids"]): message.append(f"- 0x{msg_id:X}") message.append("\n\n") return message def load_can_database(self, event): file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select CAN database file", "", "ARXML or DBC (*.dbc *.arxml)", "ARXML or DBC (*.dbc *.arxml)", ) if file_names: file_names = [name for name in file_names if Path(name).suffix.lower() in (".arxml", ".dbc")] if file_names: for database in file_names: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="CAN") self.can_database_list.addItem(item) self.can_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) def load_lin_database(self, event): file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select LIN database file", "", "ARXML or DBC database (*.dbc *.arxml);;LDF database (*.ldf);;All supported formats (*.dbc *.arxml *ldf)", "All supported formats (*.dbc *.arxml *ldf)", ) if file_names: file_names = [name for name in file_names if Path(name).suffix.lower() in (".arxml", ".dbc", ".ldf")] if file_names: for database in file_names: item = QtWidgets.QListWidgetItem() widget = DatabaseItem(database, bus_type="LIN") self.lin_database_list.addItem(item) self.lin_database_list.setItemWidget(item, widget) item.setSizeHint(widget.sizeHint()) def keyPressEvent(self, event): key = event.key() modifier = event.modifiers() if key == QtCore.Qt.Key.Key_F and modifier == QtCore.Qt.KeyboardModifier.ControlModifier: self.search() event.accept() elif key == QtCore.Qt.Key.Key_F11: self.full_screen_toggled.emit() event.accept() elif ( key in (QtCore.Qt.Key.Key_V, QtCore.Qt.Key.Key_H, QtCore.Qt.Key.Key_C, QtCore.Qt.Key.Key_T) and modifier == QtCore.Qt.KeyboardModifier.ShiftModifier ): if key == QtCore.Qt.Key.Key_V: mode = "tile vertically" elif key == QtCore.Qt.Key.Key_H: mode = "tile horizontally" elif key == QtCore.Qt.Key.Key_C: mode = "cascade" elif key == QtCore.Qt.Key.Key_T: mode = "tile" if mode == "tile": self.mdi_area.tileSubWindows() elif mode == "cascade": self.mdi_area.cascadeSubWindows() elif mode == "tile vertically": self.mdi_area.tile_vertically() elif mode == "tile horizontally": self.mdi_area.tile_horizontally() event.accept() elif key == QtCore.Qt.Key.Key_F and modifier == ( QtCore.Qt.KeyboardModifier.ShiftModifier | QtCore.Qt.KeyboardModifier.AltModifier ): self.toggle_frames() event.accept() elif key == QtCore.Qt.Key.Key_L and modifier == QtCore.Qt.KeyboardModifier.ShiftModifier: if self.channel_view.isVisible(): self._splitter_sizes = self.splitter.sizes() self.channel_view.hide() self.channels_tree.hide() self.splitter.setSizes([0, max(sum(self._splitter_sizes), 2)]) self.splitter.setStretchFactor(0, 0) self.splitter.setStretchFactor(1, 1) self.splitter.handle(0).setEnabled(False) self.splitter.handle(1).setEnabled(False) else: self.channel_view.show() self.channels_tree.show() self.splitter.setStretchFactor(0, 0) self.splitter.setStretchFactor(1, 1) self.splitter.setSizes(self._splitter_sizes) self.splitter.handle(0).setEnabled(True) self.splitter.handle(1).setEnabled(True) event.accept() elif key == QtCore.Qt.Key.Key_Period and modifier == QtCore.Qt.KeyboardModifier.NoModifier: self.set_line_style() event.accept() else: widget = self.get_current_widget() if widget: if isinstance(widget, Plot): widget.plot.viewbox.keyPressEvent(event) else: widget.keyPressEvent(event) else: super().keyPressEvent(event) def aspect_changed(self, index=None): current_index = self.aspects.currentIndex() count = self.aspects.count() for i in range(count): widget = self.aspects.widget(i) if i == current_index: widget.show() else: widget.hide() if self.aspects.tabText(current_index) == "Modify && Export": if not self.raster_channel.count(): self.raster_channel.setSizeAdjustPolicy( QtWidgets.QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon ) self.raster_channel.addItems(sorted(self.mdf.channels_db, key=lambda x: x.lower())) self.raster_channel.setMinimumWidth(100) if not self._show_filter_tree: self._show_filter_tree = True widget = self.filter_tree widget.clear() self._update_channel_tree(current_index, widget, force=True) for w in self.mdi_area.subWindowList(): widget = w.widget() if isinstance(widget, Plot): if widget.plot.region is not None: start, stop = widget.plot.region.getRegion() self.cut_start.setValue(start) self.cut_stop.setValue(stop) break elif self.aspects.tabText(current_index) == "Info": self.info.clear() self.info.setItemDelegate(Delegate(self.info)) # info tab try: file_stats = os.stat(self.mdf.original_name) except: file_stats = None file_info = QtWidgets.QTreeWidgetItem() file_info.setText(0, "File information") self.info.addTopLevelItem(file_info) children = [] item = QtWidgets.QTreeWidgetItem() item.setText(0, "Path") item.setText(1, str(self.mdf.original_name)) item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) children.append(item) item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, "Size") if file_stats is not None: item.setText(1, f"{file_stats.st_size / 1024 / 1024:.1f} MB") else: try: item.setText(1, f"{self.mdf.file_limit / 1024 / 1024:.1f} MB") except: item.setText(1, "Unknown size") children.append(item) if file_stats is not None: date_ = datetime.fromtimestamp(file_stats.st_ctime) else: date_ = datetime.now(timezone.utc) item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, "Created") item.setText(1, date_.strftime("%d-%b-%Y %H:%M:%S")) children.append(item) if file_stats is not None: date_ = datetime.fromtimestamp(file_stats.st_mtime) else: date_ = datetime.now(timezone.utc) item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, "Last modified") item.setText(1, date_.strftime("%d-%b-%Y %H:%M:%S")) children.append(item) file_info.addChildren(children) mdf_info = QtWidgets.QTreeWidgetItem() mdf_info.setText(0, "MDF information") self.info.addTopLevelItem(mdf_info) children = [] item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, "Version") item.setText(1, self.mdf.version) children.append(item) item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, "Program identification") item.setText( 1, self.mdf.identification.program_identification.decode("ascii").strip(" \r\n\t\0"), ) children.append(item) item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, "Measurement start time") item.setText(1, self.mdf.header.start_time_string()) children.append(item) item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, "Measurement comment") item.setText(1, self.mdf.header.description) item.setTextAlignment(0, QtCore.Qt.AlignmentFlag.AlignTop) children.append(item) mesaurement_attributes = QtWidgets.QTreeWidgetItem() mesaurement_attributes.setText(0, "Measurement attributes") children.append(mesaurement_attributes) for name, value in self.mdf.header._common_properties.items(): if isinstance(value, dict): tree = QtWidgets.QTreeWidgetItem() tree.setFlags(tree.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) tree.setText(0, name) tree.setTextAlignment(0, QtCore.Qt.AlignmentFlag.AlignTop) for subname, subvalue in value.items(): item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, subname) item.setText(1, str(subvalue).strip()) item.setTextAlignment(0, QtCore.Qt.AlignmentFlag.AlignTop) tree.addChild(item) mesaurement_attributes.addChild(tree) else: item = QtWidgets.QTreeWidgetItem() item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsEditable) item.setText(0, FRIENDLY_ATRRIBUTES.get(name, name)) item.setText(1, str(value).strip()) item.setTextAlignment(0, QtCore.Qt.AlignmentFlag.AlignTop) mesaurement_attributes.addChild(item) channel_groups = QtWidgets.QTreeWidgetItem() channel_groups.setText(0, "Channel groups") channel_groups.setText(1, str(len(self.mdf.groups))) children.append(channel_groups) channel_groups_children = [] for i, group in enumerate(self.mdf.groups): channel_group = group.channel_group if hasattr(channel_group, "comment"): comment = extract_xml_comment(channel_group.comment) else: comment = "" acq_name = getattr(group.channel_group, "acq_name", "") if acq_name: base_name = f"CG {i} {acq_name}" else: base_name = f"CG {i}" if comment and acq_name != comment: name = base_name + f" ({comment})" else: name = base_name cycles = channel_group.cycles_nr channel_group_item = QtWidgets.QTreeWidgetItem() channel_group_item.setText(0, name) if self.mdf.version < "4.00": size = channel_group.samples_byte_nr * cycles else: if channel_group.flags & 0x1: size = channel_group.samples_byte_nr + (channel_group.invalidation_bytes_nr << 32) else: size = (channel_group.samples_byte_nr + channel_group.invalidation_bytes_nr) * cycles if group.channel_group.acq_source: source = group.channel_group.acq_source if source.bus_type == BUS_TYPE_CAN: ico = ":/bus_can.png" elif source.bus_type == BUS_TYPE_LIN: ico = ":/bus_lin.png" elif source.bus_type == BUS_TYPE_ETHERNET: ico = ":/bus_eth.png" elif source.bus_type == BUS_TYPE_USB: ico = ":/bus_usb.png" elif source.bus_type == BUS_TYPE_FLEXRAY: ico = ":/bus_flx.png" else: ico = None if ico is not None: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(ico), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) channel_group_item.setIcon(0, icon) item = QtWidgets.QTreeWidgetItem() item.setText(0, "Channels") item.setText(1, f"{len(group.channels)}") channel_group_item.addChild(item) item = QtWidgets.QTreeWidgetItem() item.setText(0, "Cycles") item.setText(1, str(cycles)) if cycles: item.setForeground(1, QtGui.QBrush(QtGui.QColor(GREEN))) channel_group_item.addChild(item) if size <= 1 << 10: text = f"{size} B" elif size <= 1 << 20: text = f"{size / 1024:.1f} KB" elif size <= 1 << 30: text = f"{size / 1024 / 1024:.1f} MB" else: text = f"{size / 1024 / 1024 / 1024:.1f} GB" item = QtWidgets.QTreeWidgetItem() item.setText(0, "Raw size") item.setText(1, text) if cycles: item.setForeground(1, QtGui.QBrush(QtGui.QColor(GREEN))) channel_group_item.addChild(item) channel_groups_children.append(channel_group_item) channel_groups.addChildren(channel_groups_children) channels = QtWidgets.QTreeWidgetItem() channels.setText(0, "Channels") channels.setText(1, str(sum(len(entry) for entry in self.mdf.channels_db.values()))) children.append(channels) mdf_info.addChildren(children) self.info.expandAll() self.info.header().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeMode.Interactive) def toggle_frames(self, event=None): self._frameless_windows = not self._frameless_windows for window in self.mdi_area.subWindowList(): wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = True for w in self.mdi_area.subWindowList(): if self._frameless_windows: w.setWindowFlags(w.windowFlags() | QtCore.Qt.WindowType.FramelessWindowHint) else: w.setWindowFlags(w.windowFlags() & (~QtCore.Qt.WindowType.FramelessWindowHint)) for window in self.mdi_area.subWindowList(): wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = True def autofit_sub_plots(self): geometries = [] for window in self.mdi_area.subWindowList(): geometry = window.geometry() geometries.append(geometry) if len({(g.width(), g.x()) for g in geometries}) == 1: self.mdi_area.tile_vertically() elif len({(g.height(), g.y()) for g in geometries}) == 1: self.mdi_area.tile_horizontally() else: self.mdi_area.tileSubWindows() def _current_options(self): options = { "needs_cut": self.cut_group.isChecked(), "cut_start": self.cut_start.value(), "cut_stop": self.cut_stop.value(), "cut_time_from_zero": self.cut_time_from_zero.checkState() == QtCore.Qt.CheckState.Checked, "whence": int(self.whence.checkState() == QtCore.Qt.CheckState.Checked), "needs_resample": self.resample_group.isChecked(), "raster_type_step": self.raster_type_step.isChecked(), "raster_type_channel": self.raster_type_channel.isChecked(), "raster": self.raster.value(), "raster_channel": self.raster_channel.currentText(), "resample_time_from_zero": self.resample_time_from_zero.checkState() == QtCore.Qt.CheckState.Checked, "output_format": self.output_format.currentText(), } output_format = self.output_format.currentText() if output_format == "MDF": new = { "mdf_version": self.mdf_version.currentText(), "mdf_compression": CompressionAlgorithm(self.mdf_compression.currentIndex()), "mdf_split": self.mdf_split.checkState() == QtCore.Qt.CheckState.Checked, "mdf_split_size": self.mdf_split_size.value() * 1024 * 1024, } elif output_format == "MAT": new = { "single_time_base": self.single_time_base_mat.checkState() == QtCore.Qt.CheckState.Checked, "time_from_zero": self.time_from_zero_mat.checkState() == QtCore.Qt.CheckState.Checked, "time_as_date": self.time_as_date_mat.checkState() == QtCore.Qt.CheckState.Checked, "use_display_names": self.use_display_names_mat.checkState() == QtCore.Qt.CheckState.Checked, "reduce_memory_usage": self.reduce_memory_usage_mat.checkState() == QtCore.Qt.CheckState.Checked, "compression": self.export_compression_mat.currentText() == "enabled", "empty_channels": self.empty_channels_mat.currentText(), "mat_format": self.mat_format.currentText(), "oned_as": self.oned_as.currentText(), "raw": self.raw_mat.checkState() == QtCore.Qt.CheckState.Checked, } elif output_format == "CSV": new = { "single_time_base": self.single_time_base_csv.checkState() == QtCore.Qt.CheckState.Checked, "time_from_zero": self.time_from_zero_csv.checkState() == QtCore.Qt.CheckState.Checked, "time_as_date": self.time_as_date_csv.checkState() == QtCore.Qt.CheckState.Checked, "use_display_names": self.use_display_names_csv.checkState() == QtCore.Qt.CheckState.Checked, "reduce_memory_usage": False, "compression": False, "empty_channels": self.empty_channels_csv.currentText(), "raw": self.raw_csv.checkState() == QtCore.Qt.CheckState.Checked, "delimiter": self.delimiter.text() or ",", "doublequote": self.doublequote.checkState() == QtCore.Qt.CheckState.Checked, "escapechar": self.escapechar.text() or None, "lineterminator": self.lineterminator.text().replace("\\r", "\r").replace("\\n", "\n"), "quotechar": self.quotechar.text() or '"', "quoting": self.quoting.currentText(), "mat_format": None, "oned_as": None, } else: new = { "single_time_base": self.single_time_base.checkState() == QtCore.Qt.CheckState.Checked, "time_from_zero": self.time_from_zero.checkState() == QtCore.Qt.CheckState.Checked, "time_as_date": self.time_as_date.checkState() == QtCore.Qt.CheckState.Checked, "use_display_names": self.use_display_names.checkState() == QtCore.Qt.CheckState.Checked, "reduce_memory_usage": self.reduce_memory_usage.checkState() == QtCore.Qt.CheckState.Checked, "compression": self.export_compression.currentText(), "empty_channels": self.empty_channels.currentText(), "mat_format": None, "oned_as": None, "raw": self.raw.checkState() == QtCore.Qt.CheckState.Checked, } options.update(new) class Options: def __init__(self, opts): self._opts = opts for k, v in opts.items(): setattr(self, k, v) return Options(options) def _get_filtered_channels(self): iterator = QtWidgets.QTreeWidgetItemIterator(self.filter_tree) channels = [] while item := iterator.value(): iterator += 1 group, index = item.entry if index == 0xFFFFFFFFFFFFFFFF: continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: channels.append((item.name, group, index)) needs_filter = self.selected_filter_channels.count() > 0 return needs_filter, channels def apply_processing(self, event): needs_filter, channels = self._get_filtered_channels() opts = self._current_options() output_format = opts.output_format if output_format == "HDF5": try: from h5py import File as HDF5 # noqa: F401 except ImportError: MessageBox.critical( self, "Export to HDF5 unavailale", "h5py package not found; export to HDF5 is unavailable", ) return elif output_format == "MAT": if opts.mat_format == "7.3": try: from hdf5storage import savemat except ImportError: MessageBox.critical( self, "Export to mat v7.3 unavailale", "hdf5storage package not found; export to mat 7.3 is unavailable", ) return else: try: from scipy.io import savemat # noqa: F401 except ImportError: MessageBox.critical( self, "Export to mat v4 and v5 unavailale", "scipy package not found; export to mat is unavailable", ) return elif output_format == "Parquet": try: from pyarrow.parquet import write_table as write_parquet # noqa: F401 except ImportError: MessageBox.critical( self, "Export to parquet unavailale", "pyarrow package not found; export to parquet is unavailable", ) return if output_format == "MDF": version = opts.mdf_version if version < "4.00": filter = "MDF version 3 files (*.dat *.mdf)" default = filter else: filter = "MDF version 4 files (*.mf4);;Zipped MDF version 4 files (*.mf4z)" if Path(self.mdf.original_name).suffix.lower() == ".mf4z": default = "Zipped MDF version 4 files (*.mf4z)" else: default = "MDF version 4 files (*.mf4)" file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Save as measurement file", "", f"{filter};;All files (*.*)", default, ) else: filters = { "ASC": "Vector ascii files (*.asc)", "CSV": "CSV files (*.csv)", "HDF5": "HDF5 files (*.hdf)", "MAT": "Matlab MAT files (*.mat)", "Parquet": "Apache Parquet files (*.parquet)", } file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select export file", "", f"{filters[output_format]};;All files (*.*)", filters[output_format], ) version = "" if not file_name: return self._progress = setup_progress(parent=self) self._progress.finished.connect(self.apply_processing_finished) self._progress.run_thread_with_progress( target=self.apply_processing_thread, args=(), kwargs={ "file_name": file_name, "opts": opts, "version": version, "needs_filter": needs_filter, "channels": channels, }, ) def apply_processing_finished(self): self._progress = None def apply_processing_thread(self, file_name, opts, version, needs_filter, channels, progress=None): output_format = opts.output_format split_size = opts.mdf_split_size if output_format == "MDF" else 0 self.mdf.configure(read_fragment_size=split_size) mdf = None integer_interpolation = self.mdf._mdf._integer_interpolation float_interpolation = self.mdf._mdf._float_interpolation if needs_filter: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/filter.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Filtering measurement") progress.signals.setLabelText.emit(f'Filtering selected channels from "{self.file_name}"') # filtering self.mdf mdf = self.mdf.filter( channels=channels, version=opts.mdf_version if output_format == "MDF" else "4.10", progress=progress, ) mdf.configure( read_fragment_size=split_size, write_fragment_size=split_size, integer_interpolation=integer_interpolation, float_interpolation=float_interpolation, ) if opts.needs_cut: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/cut.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Cutting measurement") progress.signals.setLabelText.emit(f"Cutting from {opts.cut_start}s to {opts.cut_stop}s") # cut self.mdf target = self.mdf.cut if mdf is None else mdf.cut result = target( start=opts.cut_start, stop=opts.cut_stop, whence=opts.whence, version=opts.mdf_version if output_format == "MDF" else "4.10", time_from_zero=opts.cut_time_from_zero, progress=progress, ) if mdf is None: mdf = result else: mdf.close() mdf = result mdf.configure( read_fragment_size=split_size, write_fragment_size=split_size, integer_interpolation=integer_interpolation, float_interpolation=float_interpolation, ) if opts.needs_resample: if opts.raster_type_channel: raster = opts.raster_channel message = f'Resampling using channel "{raster}"' else: raster = opts.raster message = f"Resampling to {raster}s raster" icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/resample.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Resampling measurement") progress.signals.setLabelText.emit(message) # resample self.mdf target = self.mdf.resample if mdf is None else mdf.resample result = target( raster=raster, version=opts.mdf_version if output_format == "MDF" else "4.10", time_from_zero=opts.resample_time_from_zero, progress=progress, ) if mdf is None: mdf = result else: mdf.close() mdf = result mdf.configure( read_fragment_size=split_size, write_fragment_size=split_size, integer_interpolation=integer_interpolation, float_interpolation=float_interpolation, ) if output_format == "MDF": if mdf is None: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/convert.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Converting measurement") progress.signals.setLabelText.emit( f'Converting "{self.file_name}" from {self.mdf.version} to {version}' ) # convert self.mdf mdf = self.mdf.convert( version=version, progress=progress, ) mdf.configure( read_fragment_size=split_size, write_fragment_size=split_size, integer_interpolation=integer_interpolation, float_interpolation=float_interpolation, ) # then save it icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/save.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Saving measurement") progress.signals.setLabelText.emit(f'Saving output file "{file_name}"') handle_overwrite = Path(file_name) == self.mdf.name if handle_overwrite: dspf = self.to_config() _password = self.mdf._mdf._password self.mdf.close() windows = list(self.mdi_area.subWindowList()) for window in windows: widget = window.widget() self.mdi_area.removeSubWindow(window) widget.setParent(None) widget.close() widget.deleteLater() window.close() mdf.save( dst=file_name, compression=opts.mdf_compression, overwrite=True, progress=progress, ) if handle_overwrite: original_name = file_name self.mdf = mdf_module.MDF( name=file_name, password=_password, use_display_names=True, ) self.mdf.original_name = original_name self.mdf.uuid = self.uuid self.aspects.setCurrentIndex(0) # TO DO: may crash when modifying the GUI from this thread self.load_channel_list(file_name=dspf) self.aspects.setCurrentIndex(1) else: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/export.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.signals.setWindowIcon.emit(icon) progress.signals.setWindowTitle.emit("Export measurement") progress.signals.setLabelText.emit(f"Exporting to {output_format} (be patient this might take a while)") delimiter = self.delimiter.text() or "," doublequote = self.doublequote.checkState() == QtCore.Qt.CheckState.Checked escapechar = self.escapechar.text() or None lineterminator = self.lineterminator.text().replace("\\r", "\r").replace("\\n", "\n") quotechar = self.quotechar.text() or '"' quoting = self.quoting.currentText() add_units = self.add_units.checkState() == QtCore.Qt.CheckState.Checked if delimiter == "\\t": delimiter = "\t" target = self.mdf.export if mdf is None else mdf.export kwargs = { "fmt": opts.output_format.lower(), "filename": file_name, "single_time_base": opts.single_time_base, "use_display_names": opts.use_display_names, "time_from_zero": opts.time_from_zero, "empty_channels": opts.empty_channels, "format": opts.mat_format, "raster": None, "oned_as": opts.oned_as, "reduce_memory_usage": opts.reduce_memory_usage, "compression": opts.compression, "time_as_date": opts.time_as_date, "ignore_value2text_conversions": self.ignore_value2text_conversions, "raw": opts.raw, "delimiter": delimiter, "doublequote": doublequote, "escapechar": escapechar, "lineterminator": lineterminator, "quotechar": quotechar, "quoting": quoting, "add_units": add_units, "progress": progress, } try: target(**kwargs) except: print(format_exc()) def raster_search(self, event): dlg = AdvancedSearch( self.mdf, show_add_window=False, show_apply=True, apply_text="Set raster channel", show_pattern=False, return_names=True, parent=self, ) dlg.setModal(True) dlg.exec_() result = dlg.result if result: name = list(result)[0] self.raster_channel.setCurrentText(name) def filter_changed(self, item, column=0): name = item.text(0) if self.filter_view.currentText() == "Internal file structure": if item.checkState(0) == QtCore.Qt.CheckState.Checked and item.parent() is not None: self._selected_filter.add(name) else: if name in self._selected_filter: self._selected_filter.remove(name) elif self.filter_view.currentText() == "Natural sort": if item.checkState(0) == QtCore.Qt.CheckState.Checked: self._selected_filter.add(name) else: if name in self._selected_filter: self._selected_filter.remove(name) else: if item.checkState(0) == QtCore.Qt.CheckState.Checked: self._selected_filter.add(name) else: if name in self._selected_filter: self._selected_filter.remove(name) self._update_channel_tree(widget=self.filter_tree) self._filter_timer.start(10) def update_selected_filter_channels(self): self.selected_filter_channels.clear() self.selected_filter_channels.addItems(sorted(self._selected_filter)) def embed_display_file(self, event=None): if not self.save_embedded_channel_list_btn.isVisible() or not self.save_embedded_channel_list_btn.isEnabled(): return original_file_name = Path(self.mdf.original_name) if original_file_name.suffix.lower() not in (".mf4", ".mf4z"): return MessageBox.warning( self, "Wrong file type", f"The display file can only be embedded in .mf4 or .mf4z files\n{original_file_name}", ) _password = self.mdf._mdf._password uuid = self.mdf.uuid creator_index = len(self.mdf.file_history) current_display = self.to_config() data = json.dumps(current_display, indent=2, cls=ExtendedJsonEncoder).encode("utf-8", errors="replace") self.mdf.close() windows = list(self.mdi_area.subWindowList()) for window in windows: widget = window.widget() self.mdi_area.removeSubWindow(window) widget.setParent(None) widget.close() widget.deleteLater() window.close() suffix = original_file_name.suffix.lower() if suffix == ".mf4z": with ZipFile(original_file_name, allowZip64=True) as archive: files = archive.namelist() if len(files) != 1: return fname = files[0] if Path(fname).suffix.lower() != ".mf4": return tmpdir = gettempdir() file_name = archive.extract(fname, tmpdir) file_name = Path(tmpdir) / file_name else: file_name = original_file_name with open(file_name, "r+b") as mdf: try: embedded_file_name = "user_embedded_display.dspf" mime = r"application/x-dspf" header = HeaderBlock(stream=mdf, address=64) at_addr = header.first_attachment_addr parent = header while at_addr: at_block = AttachmentBlock(stream=mdf, address=at_addr) if at_block.file_name == embedded_file_name and at_block.mime == mime: new_at_block = AttachmentBlock( data=data, file_name=embedded_file_name, comment="user embedded display file", compression=True, mime=mime, embedded=True, password=_password, creator_index=at_block.creator_index, ) new_at_block.next_at_addr = at_block.next_at_addr blocks = [] mdf.seek(0, 2) file_end = mdf.tell() if (file_end - (at_block.address + at_block.block_len)) <= 7: address = at_block.address else: address = file_end mdf.seek(address) align = address % 8 if align: mdf.write(b"\0" * (8 - align)) address += 8 - align address = new_at_block.to_blocks(address, blocks, {}) for block in blocks: mdf.write(bytes(block)) if parent is header: header.first_attachment_addr = new_at_block.address else: parent.next_at_addr = new_at_block.address mdf.seek(parent.address) mdf.write(bytes(parent)) mdf.truncate(new_at_block.address + new_at_block.block_len) break at_addr = at_block.next_at_addr parent = at_block else: at_block = AttachmentBlock( data=data, file_name=embedded_file_name, comment="user embedded display file", compression=True, mime=mime, embedded=True, password=_password, ) fh_block = FileHistory() fh_block.comment = f""" Added new embedded attachment from {file_name} {tool.__tool__} {tool.__vendor__} {tool.__version__} """ at_block["creator_index"] = creator_index blocks = [] mdf.seek(0, 2) address = mdf.tell() align = address % 8 if align: mdf.write(b"\0" * (8 - align)) address += 8 - align address = fh_block.to_blocks(address, blocks, {}) address = at_block.to_blocks(address, blocks, {}) for block in blocks: mdf.write(bytes(block)) if header.first_attachment_addr: at_addr = header.first_attachment_addr while at_addr: last_at = AttachmentBlock(stream=mdf, address=at_addr) at_addr = last_at.next_at_addr last_at.next_at_addr = at_block.address mdf.seek(last_at.address) mdf.write(bytes(last_at)) else: header.first_attachment_addr = at_block.address if header.file_history_addr: fh_addr = header.file_history_addr while fh_addr: last_fh = FileHistory(stream=mdf, address=fh_addr) fh_addr = last_fh.next_fh_addr last_fh.next_fh_addr = fh_block.address mdf.seek(last_fh.address) mdf.write(bytes(last_fh)) else: header.file_history_addr = fh_block.address mdf.seek(header.address) mdf.write(bytes(header)) except: print(format_exc()) return if suffix == ".mf4z": zipped_mf4 = ZipFile(original_file_name, "w", compression=ZIP_DEFLATED) zipped_mf4.write( str(file_name), original_file_name.with_suffix(".mf4").name, compresslevel=1, ) zipped_mf4.close() file_name.unlink() self.mdf = mdf_module.MDF( name=original_file_name, callback=self.update_progress, password=_password, use_display_names=True, ) self.mdf.original_name = original_file_name self.mdf.uuid = uuid self.attachments.clear() self.save_embedded_channel_list_btn.setEnabled(True) self.load_embedded_channel_list_btn.setEnabled(True) current_display["display_file_name"] = self.loaded_display_file[0] self.load_channel_list(file_name=current_display) self.update_attachments() def load_embedded_display_file(self, event=None): if not self.load_embedded_channel_list_btn.isVisible() or not self.load_embedded_channel_list_btn.isEnabled(): return for index, attachment in enumerate(self.mdf.attachments): if attachment.file_name == "user_embedded_display.dspf" and attachment.mime == r"application/x-dspf": encryption_info = extract_encryption_information(attachment.comment) password = None if encryption_info.get("encrypted", False) and self.mdf._password is None: text, ok = QtWidgets.QInputDialog.getText( self, "Attachment password", "The attachment is encrypted. Please provide the password:", QtWidgets.QLineEdit.EchoMode.Password, ) if ok and text: password = text data, file_path, md5_sum = self.mdf.extract_attachment(index, password=password) dsp = json.loads(data.decode("utf-8", errors="replace"), cls=ExtendedJsonDecoder) dsp["display_file_name"] = "user_embedded_display.dspf" self.load_channel_list(file_name=dsp) def connect_export_updates(self): self.output_format.currentTextChanged.connect(self.store_export_setttings) self.mdf_version.currentTextChanged.connect(self.store_export_setttings) self.mdf_compression.currentTextChanged.connect(self.store_export_setttings) self.mdf_split.checkStateChanged.connect(self.store_export_setttings) self.mdf_split_size.valueChanged.connect(self.store_export_setttings) self.single_time_base.checkStateChanged.connect(self.store_export_setttings) self.time_from_zero.checkStateChanged.connect(self.store_export_setttings) self.time_as_date.checkStateChanged.connect(self.store_export_setttings) self.raw.checkStateChanged.connect(self.store_export_setttings) self.use_display_names.checkStateChanged.connect(self.store_export_setttings) self.reduce_memory_usage.checkStateChanged.connect(self.store_export_setttings) self.export_compression.currentTextChanged.connect(self.store_export_setttings) self.empty_channels.currentTextChanged.connect(self.store_export_setttings) self.single_time_base_csv.checkStateChanged.connect(self.store_export_setttings) self.time_from_zero_csv.checkStateChanged.connect(self.store_export_setttings) self.time_as_date_csv.checkStateChanged.connect(self.store_export_setttings) self.raw_csv.checkStateChanged.connect(self.store_export_setttings) self.add_units.checkStateChanged.connect(self.store_export_setttings) self.doublequote.checkStateChanged.connect(self.store_export_setttings) self.use_display_names_csv.checkStateChanged.connect(self.store_export_setttings) self.empty_channels_csv.currentTextChanged.connect(self.store_export_setttings) self.delimiter.editingFinished.connect(self.store_export_setttings) self.escapechar.editingFinished.connect(self.store_export_setttings) self.lineterminator.editingFinished.connect(self.store_export_setttings) self.quotechar.editingFinished.connect(self.store_export_setttings) self.quoting.currentTextChanged.connect(self.store_export_setttings) self.single_time_base_mat.checkStateChanged.connect(self.store_export_setttings) self.time_from_zero_mat.checkStateChanged.connect(self.store_export_setttings) self.time_as_date_mat.checkStateChanged.connect(self.store_export_setttings) self.raw_mat.checkStateChanged.connect(self.store_export_setttings) self.use_display_names_mat.checkStateChanged.connect(self.store_export_setttings) self.reduce_memory_usage_mat.checkStateChanged.connect(self.store_export_setttings) self.empty_channels_mat.currentTextChanged.connect(self.store_export_setttings) self.export_compression_mat.currentTextChanged.connect(self.store_export_setttings) self.mat_format.currentTextChanged.connect(self.store_export_setttings) self.oned_as.currentTextChanged.connect(self.store_export_setttings) def restore_export_setttings(self): self.output_format.setCurrentText(self._settings.value("export", "MDF")) self.mdf_version.setCurrentText(self._settings.setValue("export/MDF/version", "4.10")) self.mdf_compression.setCurrentText(self._settings.value("export/MDF/compression", "transposed deflate")) self.mdf_split.setChecked(self._settings.value("export/MDF/split_data_blocks", True, type=bool)) self.mdf_split_size.setValue(self._settings.value("export/MDF/split_size", 4, type=int)) self.single_time_base.setChecked(self._settings.value("export/HDF5/single_time_base", False, type=bool)) self.time_from_zero.setChecked(self._settings.value("export/HDF5/time_from_zero", False, type=bool)) self.time_as_date.setChecked(self._settings.value("export/HDF5/time_as_date", False, type=bool)) self.raw.setChecked(self._settings.value("export/HDF5/raw", False, type=bool)) self.use_display_names.setChecked(self._settings.value("export/HDF5/use_display_names", False, type=bool)) self.reduce_memory_usage.setChecked(self._settings.value("export/HDF5/reduce_memory_usage", False, type=bool)) self.export_compression.setCurrentText(self._settings.value("export/HDF5/export_compression", "gzip")) self.empty_channels.setCurrentText(self._settings.value("export/HDF5/empty_channels", "skip")) self.single_time_base_csv.setChecked(self._settings.value("export/CSV/single_time_base_csv", False, type=bool)) self.time_from_zero_csv.setChecked(self._settings.value("export/CSV/time_from_zero_csv", False, type=bool)) self.time_as_date_csv.setChecked(self._settings.value("export/CSV/time_as_date_csv", False, type=bool)) self.raw_csv.setChecked(self._settings.value("export/CSV/raw_csv", False, type=bool)) self.add_units.setChecked(self._settings.value("export/CSV/add_units", False, type=bool)) self.doublequote.setChecked(self._settings.value("export/CSV/doublequote", False, type=bool)) self.use_display_names_csv.setChecked( self._settings.value("export/CSV/use_display_names_csv", False, type=bool) ) self.empty_channels_csv.setCurrentText(self._settings.value("export/CSV/empty_channels_csv", "skip")) self.delimiter.setText(self._settings.value("export/CSV/delimiter", ",")) self.escapechar.setText(self._settings.value("export/CSV/escapechar", "")) self.lineterminator.setText(self._settings.value("export/CSV/lineterminator", r"\r\n")) self.quotechar.setText(self._settings.value("export/CSV/quotechar", '"')) self.quoting.setCurrentText(self._settings.value("export/CSV/quoting", "MINIMAL")) self.single_time_base_mat.setChecked(self._settings.value("export/MAT/single_time_base_mat", False, type=bool)) self.time_from_zero_mat.setChecked(self._settings.value("export/MAT/time_from_zero_mat", False, type=bool)) self.time_as_date_mat.setChecked(self._settings.value("export/MAT/time_as_date_mat", False, type=bool)) self.raw_mat.setChecked(self._settings.value("export/MAT/raw_mat", False, type=bool)) self.use_display_names_mat.setChecked( self._settings.value("export/MAT/use_display_names_mat", False, type=bool) ) self.reduce_memory_usage_mat.setChecked( self._settings.value("export/MAT/reduce_memory_usage_mat", False, type=bool) ) self.empty_channels_mat.setCurrentText(self._settings.value("export/MAT/empty_channels_mat", "skip")) self.export_compression_mat.setCurrentText(self._settings.value("export/MAT/export_compression_mat", "enabled")) self.mat_format.setCurrentText(self._settings.value("export/MAT/mat_format", "4")) self.oned_as.setCurrentText(self._settings.value("export/MAT/oned_as", "row")) def store_export_setttings(self, *args): self._settings.setValue("export", self.output_format.currentText()) self._settings.setValue("export/MDF/version", self.mdf_version.currentText()) self._settings.setValue("export/MDF/compression", self.mdf_compression.currentText()) self._settings.setValue("export/MDF/split_data_blocks", self.mdf_split.isChecked()) self._settings.setValue("export/MDF/split_size", self.mdf_split_size.value()) self._settings.setValue("export/HDF5/single_time_base", self.single_time_base.isChecked()) self._settings.setValue("export/HDF5/time_from_zero", self.time_from_zero.isChecked()) self._settings.setValue("export/HDF5/time_as_date", self.time_as_date.isChecked()) self._settings.setValue("export/HDF5/raw", self.raw.isChecked()) self._settings.setValue("export/HDF5/use_display_names", self.use_display_names.isChecked()) self._settings.setValue("export/HDF5/reduce_memory_usage", self.reduce_memory_usage.isChecked()) self._settings.setValue("export/HDF5/export_compression", self.export_compression.currentText()) self._settings.setValue("export/HDF5/empty_channels", self.empty_channels.currentText()) self._settings.setValue("export/CSV/single_time_base_csv", self.single_time_base_csv.isChecked()) self._settings.setValue("export/CSV/time_from_zero_csv", self.time_from_zero_csv.isChecked()) self._settings.setValue("export/CSV/time_as_date_csv", self.time_as_date_csv.isChecked()) self._settings.setValue("export/CSV/raw_csv", self.raw_csv.isChecked()) self._settings.setValue("export/CSV/add_units", self.add_units.isChecked()) self._settings.setValue("export/CSV/doublequote", self.doublequote.isChecked()) self._settings.setValue("export/CSV/use_display_names_csv", self.use_display_names_csv.isChecked()) self._settings.setValue("export/CSV/empty_channels_csv", self.empty_channels_csv.currentText()) self._settings.setValue("export/CSV/delimiter", self.delimiter.text()) self._settings.setValue("export/CSV/escapechar", self.escapechar.text()) self._settings.setValue("export/CSV/lineterminator", self.lineterminator.text()) self._settings.setValue("export/CSV/quotechar", self.quotechar.text()) self._settings.setValue("export/CSV/quoting", self.quoting.currentText()) self._settings.setValue("export/MAT/single_time_base_mat", self.single_time_base_mat.isChecked()) self._settings.setValue("export/MAT/time_from_zero_mat", self.time_from_zero_mat.isChecked()) self._settings.setValue("export/MAT/time_as_date_mat", self.time_as_date_mat.isChecked()) self._settings.setValue("export/MAT/raw_mat", self.raw_mat.isChecked()) self._settings.setValue("export/MAT/use_display_names_mat", self.use_display_names_mat.isChecked()) self._settings.setValue("export/MAT/reduce_memory_usage_mat", self.reduce_memory_usage_mat.isChecked()) self._settings.setValue("export/MAT/empty_channels_mat", self.empty_channels_mat.currentText()) self._settings.setValue("export/MAT/export_compression_mat", self.export_compression_mat.currentText()) self._settings.setValue("export/MAT/mat_format", self.mat_format.currentText()) self._settings.setValue("export/MAT/oned_as", self.oned_as.currentText()) def update_attachments(self): self.attachments.clear() hide_embedded_btn = True if self.mdf.version >= "4.00" and self.mdf.attachments: for i, attachment in enumerate(self.mdf.attachments): if attachment.file_name == "user_embedded_display.dspf" and attachment.mime == r"application/x-dspf": hide_embedded_btn = False att = Attachment(i, attachment, self) item = QtWidgets.QListWidgetItem() item.setSizeHint(att.sizeHint()) self.attachments.addItem(item) self.attachments.setItemWidget(item, att) else: self.aspects.setTabVisible(4, False) if hide_embedded_btn: self.load_embedded_channel_list_btn.setDisabled(True) asammdf-8.5.1/src/asammdf/gui/widgets/flexray_bus_trace.py000066400000000000000000000043741502633300400236450ustar00rootroot00000000000000import logging import dateutil.tz import pandas as pd from PySide6 import QtCore, QtGui from .tabular_base import TabularBase logger = logging.getLogger("asammdf.gui") LOCAL_TIMEZONE = dateutil.tz.tzlocal() class FlexRayBusTrace(TabularBase): add_channels_request = QtCore.Signal(list) def __init__(self, signals=None, start=0, format="phys", ranges=None, *args, **kwargs): ranges = ranges or {name: [] for name in signals.columns} if not ranges["Event Type"]: ranges["Event Type"] = [ { "background_color": QtGui.QColor("#ff0000"), "font_color": QtGui.QColor("#000000"), "op1": "==", "op2": "==", "value1": "Error Frame", "value2": None, }, { "background_color": QtGui.QColor("#00ff00"), "font_color": QtGui.QColor("#000000"), "op1": "==", "op2": "==", "value1": "Remote Frame", "value2": None, }, ] super().__init__(signals, ranges) self.signals_descr = dict.fromkeys(signals.columns, 0) self.start = start.astimezone(LOCAL_TIMEZONE) self.pattern = {} self.format = format self.format_selection.setCurrentText(format) self._original_timestamps = signals["timestamps"] self._original_ts_series = pd.Series( self._original_timestamps, index=signals.index, ) prefixes = set() for name in signals.columns: while "." in name: name = name.rsplit(".", 1)[0] prefixes.add(f"{name}.") self.filters.minimal_menu = True self.prefix.insertItems(0, sorted(prefixes, key=lambda x: (-len(x), x))) self.prefix.setEnabled(False) self.prefix.currentIndexChanged.connect(self.prefix_changed) if prefixes: self.remove_prefix.setCheckState(QtCore.Qt.CheckState.Checked) self._settings = QtCore.QSettings() integer_mode = self._settings.value("tabular_format", "phys") self.format_selection.setCurrentText(integer_mode) asammdf-8.5.1/src/asammdf/gui/widgets/formated_axis.py000066400000000000000000001023361502633300400227660ustar00rootroot00000000000000from datetime import datetime, timedelta, timezone from math import ceil from traceback import format_exc import numpy as np import pandas as pd import pyqtgraph as pg import pyqtgraph.functions as fn from pyqtgraph.graphicsItems.ButtonItem import ButtonItem from pyqtgraph.Point import Point from PySide6 import QtCore, QtGui, QtWidgets LOCAL_TIMEZONE = datetime.now(timezone.utc).astimezone().tzinfo BUTTON_SIZE = 16 class FormatedAxis(pg.AxisItem): rangeChanged = QtCore.Signal(object, object) scale_editor_requested = QtCore.Signal(object) def __init__(self, *args, **kwargs): self.plus = self.minus = None self.uuid = kwargs.pop("uuid", None) self.background = kwargs.pop("background", fn.mkColor("#000000")) self.linked_signal = kwargs.pop("linked_signal", None) super().__init__(*args, **kwargs) self.setAcceptHoverEvents(True) self._settings = QtCore.QSettings() self.format = "phys" self.mode = "phys" self.text_conversion = None self.origin = None self.hovering = False self._label_with_unit = "" self.locked = kwargs.pop("locked", False) if self.orientation in ("left", "right"): self.plus = ButtonItem(":/plus.png", BUTTON_SIZE, parentItem=self) self.minus = ButtonItem(":/minus.png", BUTTON_SIZE, parentItem=self) self.plus.clicked.connect(self.increase_width) self.minus.clicked.connect(self.decrease_width) if self.scene() is not None: self.scene().addItem(self.plus) self.scene().addItem(self.minus) self.setWidth(48) self.set_pen(self._pen) def increase_width(self): self.setWidth(self.width() + 10) def decrease_width(self): self.setWidth(self.width() - 10) def setWidth(self, w=None): if self.orientation in ("left", "right"): super().setWidth(max(w, 48)) else: super().setWidth(w) def tickStrings(self, values, scale, spacing): strns = [] self.tick_positions = values if self.text_conversion and self.mode == "phys": strns = [] for val in values: nv = self.text_conversion.convert(np.array([val]), as_bytes=True)[0] val = float(val) if val.is_integer(): val = int(val) if self.format == "hex": val = hex(int(val)) elif self.format == "bin": val = bin(int(val)) else: val = str(val) else: val = f"{val:.6f}" if isinstance(nv, bytes): try: strns.append(f"{val}={nv.decode('utf-8', errors='replace')}") except: strns.append(f"{val}={nv.decode('latin-1', errors='replace')}") else: strns.append(val) else: if self.format == "phys": strns = super().tickStrings(values, scale, spacing) elif self.format == "hex": for val in values: val = float(val) if val.is_integer(): val = hex(int(val)) else: val = "" strns.append(val) elif self.format == "bin": for val in values: val = float(val) if val.is_integer(): val = bin(int(val)) else: val = "" strns.append(val) elif self.format == "ascii": for val in values: val = float(val) if val.is_integer(): val = int(val) if 0 < val < 0x110000: val = chr(val) else: val = str(val) else: val = "" strns.append(val) elif self.format == "time": strns = [str(timedelta(seconds=val)) for val in values] elif self.format == "date": strns = ( ( pd.to_timedelta( np.array(values), unit="s", errors="coerce", ) + self.origin ) .astype(str) .to_list() ) return [val[:80] for val in strns] def setLabel(self, text=None, units=None, unitPrefix=None, **args): """Override pyqtgraph.AxisItem.setLabel.""" show_label = False if text is not None: self.labelText = text show_label = True if units is not None: self.labelUnits = units show_label = True if show_label: self.showLabel() if unitPrefix is not None: self.labelUnitPrefix = unitPrefix if len(args) > 0: self.labelStyle = args self.label.setHtml(self.labelString()) self._adjustSize() self.picture = None self.update() def labelString(self): if self.labelUnits == "": if not self.autoSIPrefix or self.autoSIPrefixScale == 1.0: units = "" else: units = "(x%g)" % (1.0 / self.autoSIPrefixScale) else: units = f"({self.labelUnitPrefix}{self.labelUnits})" s = f"{self.labelText} {units}" self._label_with_unit = s style = ";".join([f"{k}: {self.labelStyle[k]}" for k in self.labelStyle]) lsbl = f"{s}" return lsbl def mouseDragEvent(self, event): if self.locked: return if self.orientation in ("left", "right"): ev = event ev.accept() pos = ev.pos() lastPos = ev.lastPos() dif = pos - lastPos dif = dif * -1 if ev.button() in [ QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.MouseButton.MiddleButton, ]: if self.orientation in ("left", "right"): scale = (self.range[1] - self.range[0]) / self.sceneBoundingRect().height() delta = scale * dif.y() else: scale = (self.range[1] - self.range[0]) / self.sceneBoundingRect().width() delta = scale * dif.x() self.setRange(self.range[0] - delta, self.range[1] - delta) elif ev.button() & QtCore.Qt.MouseButton.RightButton: mid = sum(self.range) / 2 delta = self.range[-1] - self.range[0] if self.orientation in ("left", "right"): if dif.y() > 0: delta = 0.94 * delta else: delta = 1.06 * delta else: if dif.x() > 0: delta = 0.94 * delta else: delta = 1.06 * delta self.setRange(mid - delta / 2, mid + delta / 2) else: return self.linkedView().mouseDragEvent(event, axis=0, ignore_cursor=True) def mouseClickEvent(self, event): if event.button() == QtCore.Qt.MouseButton.RightButton: if self.sceneBoundingRect().contains(event.scenePos()): event.accept() self.raiseContextMenu(event) else: lv = self.linkedView() if lv is None: return return lv.mouseClickEvent(event) def hoverEnterEvent(self, event): self.hovering = True self.picture = None self.update() super().hoverEnterEvent(event) def hoverLeaveEvent(self, event): self.hovering = False self.picture = None self.update() super().hoverLeaveEvent(event) def resizeEvent(self, ev=None): if self.orientation in ("left", "right"): nudge = 5 if self.minus is not None: br = self.minus.boundingRect() p = QtCore.QPointF(0, 0) if self.orientation == "left": p.setY(5) p.setX(nudge) elif self.orientation == "right": p.setY(5) p.setX(int(self.size().width() - br.height() + nudge)) self.minus.setPos(p) if self.plus is not None: br = self.plus.boundingRect() p = QtCore.QPointF(0, 0) if self.orientation == "left": p.setY(26) p.setX(nudge) elif self.orientation == "right": p.setY(26) p.setX(int(self.size().width() - br.height() + nudge)) self.plus.setPos(p) return super().resizeEvent(ev) def close(self): self.linked_signal = None if self.plus is not None: self.scene().removeItem(self.plus) if self.minus is not None: self.scene().removeItem(self.minus) self.plus = None self.minus = None super().close() def set_pen(self, pen=None): if pen is None: pen = fn.mkPen(pen) color = pen.color() if self.minus is not None: p = QtGui.QPainter(self.minus.pixmap) self.minus.pixmap.fill(color) p.setBrush(self.background) p.drawRect(QtCore.QRect(4, 24, 56, 15)) p.end() if self.plus is not None: p = QtGui.QPainter(self.plus.pixmap) self.plus.pixmap.fill(color) p.setBrush(self.background) p.drawRect(QtCore.QRect(4, 24, 56, 15)) p.drawRect(QtCore.QRect(24, 4, 15, 56)) p.end() if pen is not self._pen: self.setPen(pen) def raiseContextMenu(self, ev): low, high = self.range if self.orientation in ("left", "right"): if self.linked_signal is None: axis = f"{self.linked_signal.name} Y" else: axis = "Y" else: axis = "X" menu = QtWidgets.QMenu() menu.addAction(f"Edit {axis} axis scaling") menu.addSeparator() menu.addAction("Apply new axis limits") menu.addSeparator() widget = QtWidgets.QWidget() layout = QtWidgets.QHBoxLayout() widget.setLayout(layout) layout.addWidget(QtWidgets.QLabel("max:")) upper = QtWidgets.QDoubleSpinBox() upper.setDecimals(9) upper.setMinimum(-1e64) upper.setMaximum(1e35) upper.setValue(high) layout.addWidget(upper) a = QtWidgets.QWidgetAction(self) a.setDefaultWidget(widget) menu.addAction(a) widget = QtWidgets.QWidget() layout = QtWidgets.QHBoxLayout() widget.setLayout(layout) layout.addWidget(QtWidgets.QLabel("min:")) lower = QtWidgets.QDoubleSpinBox() lower.setDecimals(9) lower.setMinimum(-1e64) lower.setMaximum(1e35) lower.setValue(low) layout.addWidget(lower) a = QtWidgets.QWidgetAction(self) a.setDefaultWidget(widget) menu.addAction(a) action = menu.exec_(ev.screenPos().toPoint()) if action is None: return elif action.text() == "Apply new axis limits": if self.orientation in ("left", "right"): self.setRange(lower.value(), upper.value()) else: self.setRange(lower.value(), upper.value()) elif action.text() == f"Edit {axis} axis scaling": self.scale_editor_requested.emit(self.uuid) def set_font_size(self, size): font = self.font() font.setPointSize(size) if self.orientation in ("top", "bottom"): metric = QtGui.QFontMetrics(font) height = max(metric.height() + 2, 18) self.setStyle(tickFont=font, tickTextHeight=height) else: self.setStyle(tickFont=font) self.setFont(font) self.label.setFont(font) def setRange(self, mn, mx): if mn > mx: mn, mx = mx, mn super().setRange(mn, mx) self.rangeChanged.emit(self.uuid, (mn, mx)) def wheelEvent(self, event): if self.locked: return lv = self.linkedView() factor = self._settings.value("zoom_wheel_factor", 0.165, type=float) if lv is None: # this is one of the individual axis pos = event.pos() rect = self.boundingRect() zoom_y_mode = self._settings.value("zoom_y_mode", "") if not zoom_y_mode: if self._settings.value("zoom_y_center_on_cursor", False, type=bool): zoom_y_mode = "center_on_cursor" else: zoom_y_mode = "center_on_mouse" if zoom_y_mode == "pin_zero_level": plot, uuid = self.linked_signal y_pos_val, sig_y_bottom, sig_y_top = plot.value_at_cursor(uuid) delta_proc = sig_y_top / (sig_y_top - sig_y_bottom) delta = sig_y_top - sig_y_bottom if event.delta() > 0: delta *= 1 / (1 + factor) else: delta *= 1 + factor end = delta_proc * delta start = end - delta self.setRange(start, end) elif zoom_y_mode == "center_on_cursor": plot, uuid = self.linked_signal y_pos_val, sig_y_bottom, sig_y_top = plot.value_at_cursor(uuid) delta_proc = (y_pos_val - (sig_y_top + sig_y_bottom) / 2) / (sig_y_top - sig_y_bottom) shift = delta_proc * (sig_y_top - sig_y_bottom) sig_y_top, sig_y_bottom = sig_y_top + shift, sig_y_bottom + shift delta = sig_y_top - sig_y_bottom if event.delta() > 0: end = sig_y_top - 1 / factor * delta start = sig_y_bottom + 1 / factor * delta else: end = sig_y_top + factor * delta start = sig_y_bottom - factor * delta self.setRange(start, end) elif zoom_y_mode == "center_on_mouse": y_pos_val = ((rect.height() + rect.y()) - pos.y()) / rect.height() * ( self.range[-1] - self.range[0] ) + self.range[0] ratio = abs((pos.y() - (rect.height() + rect.y())) / rect.height()) delta = self.range[-1] - self.range[0] if event.delta() > 0: delta = 1 / (1 + factor) * delta else: delta = (1 + factor) * delta start = y_pos_val - ratio * delta end = y_pos_val + (1 - ratio) * delta self.setRange(start, end) event.accept() else: # this is the main Y axis or the X axis if self.orientation in ("top", "bottom"): super().wheelEvent(event) else: # main Y axis if not lv.state["mouseEnabled"][1]: event.ignore() else: # the plot is not Y locked pos = event.pos() rect = self.boundingRect() zoom_y_mode = self._settings.value("zoom_y_mode", "") if not zoom_y_mode: if self._settings.value("zoom_y_center_on_cursor", False, type=bool): zoom_y_mode = "center_on_cursor" else: zoom_y_mode = "center_on_mouse" if zoom_y_mode == "pin_zero_level": plot, uuid = self.linked_signal y_pos_val, sig_y_bottom, sig_y_top = plot.value_at_cursor() delta_proc = sig_y_top / (sig_y_top - sig_y_bottom) delta = sig_y_top - sig_y_bottom if event.delta() > 0: delta *= 1 / (1 + factor) else: delta *= 1 + factor end = delta_proc * delta start = end - delta self.setRange(start, end) elif zoom_y_mode == "center_on_cursor": plot, uuid = self.linked_signal y_pos_val, sig_y_bottom, sig_y_top = plot.value_at_cursor() if isinstance(y_pos_val, (int, float)): delta_proc = (y_pos_val - (sig_y_top + sig_y_bottom) / 2) / (sig_y_top - sig_y_bottom) shift = delta_proc * (sig_y_top - sig_y_bottom) sig_y_top, sig_y_bottom = sig_y_top + shift, sig_y_bottom + shift delta = sig_y_top - sig_y_bottom if event.delta() > 0: end = sig_y_top - factor * delta start = sig_y_bottom + factor * delta else: end = sig_y_top + factor * delta start = sig_y_bottom - factor * delta self.setRange(start, end) else: y_pos_val = ((rect.height() + rect.y()) - pos.y()) / rect.height() * ( self.range[-1] - self.range[0] ) + self.range[0] ratio = abs((pos.y() - (rect.height() + rect.y())) / rect.height()) delta = self.range[-1] - self.range[0] if event.delta() > 0: delta = (1 - factor) * delta else: delta = (1 + factor) * delta start = y_pos_val - ratio * delta end = y_pos_val + (1 - ratio) * delta self.setRange(start, end) event.accept() def drawPicture(self, p, axisSpec, tickSpecs, textSpecs, ratio=1.0): p.setRenderHint(p.RenderHint.Antialiasing, False) p.setRenderHint(p.RenderHint.TextAntialiasing, True) bounding = self.boundingRect().toAlignedRect() bounding.setSize(bounding.size() * ratio) bounding.moveTo(bounding.topLeft() * ratio) ## draw long line along axis pen, p1, p2 = axisSpec p.setPen(pen) p.drawLine(p1, p2) ## draw ticks for pen, p1, p2 in tickSpecs: p.setPen(pen) p.drawLine(p1, p2) # Draw all text if self.style["tickFont"] is not None: p.setFont(self.style["tickFont"]) p.setPen(self.textPen()) p.setClipRect(bounding) for rect, flags, text in textSpecs: p.drawText(rect, int(flags), text) def paint(self, p, opt, widget): rect = self.boundingRect() width = ceil(rect.width()) height = ceil(rect.height()) ratio = widget.devicePixelRatio() if widget else 1.0 if self.picture is None: try: picture = QtGui.QPixmap(ceil(width * ratio), ceil(height * ratio)) if self.hovering: if self.background == fn.mkColor("#000000"): bk = fn.mkColor("#323232") else: bk = fn.mkColor("#CDCDCD") else: bk = self.background picture.fill(bk) painter = QtGui.QPainter() painter.begin(picture) if self.isVisible(): painter.setCompositionMode(QtGui.QPainter.CompositionMode.CompositionMode_SourceOver) if self.style["tickFont"]: painter.setFont(self.style["tickFont"]) specs = self.generateDrawSpecs(painter, ratio) if specs is not None: self.drawPicture(painter, *specs, ratio) bounding = self.boundingRect().toAlignedRect() bounding.setSize(bounding.size() * ratio) bounding.moveTo(bounding.topLeft() * ratio) if self.minus is not None: painter.drawPixmap( QtCore.QPoint(int(rect.x() * ratio) + 5 * ratio, 6 * ratio), self.minus.pixmap.scaled(BUTTON_SIZE * ratio, BUTTON_SIZE * ratio), ) painter.drawPixmap( QtCore.QPoint((int(rect.x()) + 5) * ratio, 27 * ratio), self.plus.pixmap.scaled(BUTTON_SIZE * ratio, BUTTON_SIZE * ratio), ) if self.orientation in ("left", "right"): painter.setPen(self._pen) label_rect = QtCore.QRectF( 1 * ratio, 1 * ratio, rect.height() * ratio - (28 + BUTTON_SIZE) * ratio, rect.width() * ratio, ) painter.translate(rect.bottomLeft() * ratio) painter.rotate(-90) painter.setRenderHint(painter.RenderHint.TextAntialiasing, True) painter.drawText( label_rect, QtCore.Qt.AlignmentFlag.AlignHCenter | QtCore.Qt.AlignmentFlag.AlignTop, self._label_with_unit, ) painter.rotate(90) painter.resetTransform() except: print(format_exc()) finally: painter.end() picture.setDevicePixelRatio(widget.devicePixelRatio() if widget else 1.0) self.picture = picture def generateDrawSpecs(self, p, ratio): """Call tickValues() and tickStrings() to determine where and how ticks should be drawn, then generates from this a set of drawing commands to be interpreted by drawPicture(). """ bounds = self.mapRectFromParent(self.geometry()) tickBounds = bounds if self.orientation == "left": span = (bounds.topRight(), bounds.bottomRight()) tickStart = tickBounds.right() tickStop = bounds.right() tickDir = -1 axis = 0 elif self.orientation == "right": span = (bounds.topLeft(), bounds.bottomLeft()) tickStart = tickBounds.left() tickStop = bounds.left() tickDir = 1 axis = 0 elif self.orientation == "top": span = (bounds.bottomLeft(), bounds.bottomRight()) tickStart = tickBounds.bottom() tickStop = bounds.bottom() tickDir = -1 axis = 1 elif self.orientation == "bottom": span = (bounds.topLeft(), bounds.topRight()) tickStart = tickBounds.top() tickStop = bounds.top() tickDir = 1 axis = 1 else: raise ValueError("self.orientation must be in ('left', 'right', 'top', 'bottom')") ## determine size of this item in pixels points = list(map(self.mapToDevice, span)) if None in points: return lengthInPixels = Point(points[1] - points[0]).length() if lengthInPixels == 0: return # Determine major / minor / subminor axis ticks if self._tickLevels is None: tickLevels = self.tickValues(self.range[0], self.range[1], lengthInPixels) tickStrings = None else: ## parse self.tickLevels into the formats returned by tickLevels() and tickStrings() tickLevels = [] tickStrings = [] for level in self._tickLevels: values = [] strings = [] tickLevels.append((None, values)) tickStrings.append(strings) for val, strn in level: values.append(val) strings.append(strn) ## determine mapping between tick values and local coordinates dif = self.range[1] - self.range[0] if dif == 0: xScale = 1 offset = 0 else: if axis == 0: xScale = -bounds.height() / dif offset = self.range[0] * xScale - bounds.height() else: xScale = bounds.width() / dif offset = self.range[0] * xScale xRange = [x * xScale - offset for x in self.range] xMin = min(xRange) xMax = max(xRange) tickPositions = [] # remembers positions of previously drawn ticks ## compute coordinates to draw ticks ## draw three different intervals, long ticks first tickSpecs = [] for i in range(len(tickLevels)): tickPositions.append([]) ticks = tickLevels[i][1] ## length of tick tickLength = self.style["tickLength"] / ((i * 0.5) + 1.0) lineAlpha = self.style["tickAlpha"] if lineAlpha is None: lineAlpha = (0.6**i) * 255 elif isinstance(lineAlpha, float): lineAlpha *= 255 lineAlpha = max(0, round(lineAlpha)) lineAlpha = min(255, round(lineAlpha)) elif isinstance(lineAlpha, int): if (lineAlpha > 255) or (lineAlpha < 0): raise ValueError("lineAlpha should be [0..255]") else: raise TypeError("Line Alpha should be of type None, float or int") for v in ticks: ## determine actual position to draw this tick x = (v * xScale) - offset if x < xMin or x > xMax: ## last check to make sure no out-of-bounds ticks are drawn tickPositions[i].append(None) continue tickPositions[i].append(x) p1 = [x, x] p2 = [x, x] p1[axis] = tickStart p2[axis] = tickStop p2[axis] += tickLength * tickDir tickPen = self.pen() color = tickPen.color() color.setAlpha(int(lineAlpha)) tickPen.setColor(color) tickSpecs.append((tickPen, Point(p1), Point(p2))) if self.style["stopAxisAtTick"][0] is True: minTickPosition = min(map(min, tickPositions)) if axis == 0: stop = max(span[0].y(), minTickPosition) span[0].setY(stop) else: stop = max(span[0].x(), minTickPosition) span[0].setX(stop) if self.style["stopAxisAtTick"][1] is True: maxTickPosition = max(map(max, tickPositions)) if axis == 0: stop = min(span[1].y(), maxTickPosition) span[1].setY(stop) else: stop = min(span[1].x(), maxTickPosition) span[1].setX(stop) axisSpec = (self.pen(), span[0], span[1]) textOffset = self.style["tickTextOffset"][axis] ## spacing between axis and text # if self.style['autoExpandTextSpace'] is True: # textWidth = self.textWidth # textHeight = self.textHeight # else: # textWidth = self.style['tickTextWidth'] ## space allocated for horizontal text # textHeight = self.style['tickTextHeight'] ## space allocated for horizontal text textSize2 = 0 lastTextSize2 = 0 textRects = [] textSpecs = [] ## list of draw # If values are hidden, return early if not self.style["showValues"]: return (axisSpec, tickSpecs, textSpecs) for i in range(min(len(tickLevels), self.style["maxTextLevel"] + 1)): ## Get the list of strings to display for this level if tickStrings is None: spacing, values = tickLevels[i] strings = self.tickStrings(values, self.autoSIPrefixScale * self.scale, spacing) else: strings = tickStrings[i] if len(strings) == 0: continue ## ignore strings belonging to ticks that were previously ignored for j in range(len(strings)): if tickPositions[i][j] is None: strings[j] = None ## Measure density of text; decide whether to draw this level rects = [] for s in strings: if s is None: rects.append(None) else: br = p.boundingRect( QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignmentFlag.AlignCenter, s, ) ## boundingRect is usually just a bit too large ## (but this probably depends on per-font metrics?) br.setHeight(br.height() * 0.8) rects.append(br) textRects.append(rects[-1]) if len(textRects) > 0: ## measure all text, make sure there's enough room if axis == 0: textSize = np.sum([r.height() for r in textRects]) textSize2 = np.max([r.width() for r in textRects]) else: textSize = np.sum([r.width() for r in textRects]) textSize2 = np.max([r.height() for r in textRects]) else: textSize = 0 textSize2 = 0 if i > 0: ## always draw top level ## If the strings are too crowded, stop drawing text now. ## We use three different crowding limits based on the number ## of texts drawn so far. textFillRatio = float(textSize) / lengthInPixels finished = False for nTexts, limit in self.style["textFillLimits"]: if len(textSpecs) >= nTexts and textFillRatio >= limit: finished = True break if finished: break lastTextSize2 = textSize2 # spacing, values = tickLevels[best] # strings = self.tickStrings(values, self.scale, spacing) # Determine exactly where tick text should be drawn for j in range(len(strings)): vstr = strings[j] if vstr is None: ## this tick was ignored because it is out of bounds continue x = tickPositions[i][j] # textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignmentFlag.AlignCenter, vstr) textRect = rects[j] height = textRect.height() width = textRect.width() # self.textHeight = height offset = max(0, self.style["tickLength"]) + textOffset if self.orientation == "left": alignFlags = QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter rect = QtCore.QRectF(tickStop - offset - width, x - (height / 2), width, height) elif self.orientation == "right": alignFlags = QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter rect = QtCore.QRectF(tickStop + offset, x - (height / 2), width, height) elif self.orientation == "top": alignFlags = QtCore.Qt.AlignmentFlag.AlignHCenter | QtCore.Qt.AlignmentFlag.AlignBottom rect = QtCore.QRectF(x - width / 2.0, tickStop - offset - height, width, height) elif self.orientation == "bottom": alignFlags = QtCore.Qt.AlignmentFlag.AlignHCenter | QtCore.Qt.AlignmentFlag.AlignTop rect = QtCore.QRectF(x - width / 2.0, tickStop + offset, width, height) textFlags = alignFlags | QtCore.Qt.TextFlag.TextDontClip # p.setPen(self.pen()) # p.drawText(rect, textFlags, vstr) textSpecs.append((rect, textFlags, vstr)) ## update max text size if needed. self._updateMaxTextSize(lastTextSize2) self.tickSpecs = tickSpecs axisSpec = ( axisSpec[0], axisSpec[1] * ratio, axisSpec[2] * ratio, ) bounds.setSize(bounds.size() * ratio) for spec in textSpecs: spec[0].setSize(spec[0].size() * ratio) spec[0].moveTo(spec[0].topLeft() * ratio) for i, spec in enumerate(tickSpecs): tickSpecs[i] = ( spec[0], spec[1] * ratio, spec[2] * ratio, ) return (axisSpec, tickSpecs, textSpecs) asammdf-8.5.1/src/asammdf/gui/widgets/functions_manager.py000066400000000000000000000406351502633300400236460ustar00rootroot00000000000000import json import os from pathlib import Path from natsort import natsorted from PySide6 import QtCore, QtGui, QtWidgets from ..dialogs.error_dialog import ErrorDialog from ..dialogs.messagebox import MessageBox from ..ui.functions_manager import Ui_FunctionsManager from ..utils import ( check_generated_function, generate_python_function, generate_python_function_globals, generate_python_variables, ) from .python_highlighter import PythonHighlighter class FunctionsManager(Ui_FunctionsManager, QtWidgets.QWidget): def __init__(self, definitions, channels=None, selected_definition="", global_variables="", *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.original_globals = global_variables self.channels = channels or {} definitions.pop("__global_variables__", None) for info in definitions.values(): info["original_definition"] = info["current_definition"] = info["definition"] = info["definition"].replace( "\t", " " ) self.definitions = definitions self.globals_definition.setPlaceholderText( """The global variables definition is written as Python code. Here is a minimalistic example: PI = 3.1415 # float value magic_number = 9 # integer value initial_samples = [3, 5, 6] # list of integers """ ) self.globals_definition.setPlainText(global_variables) self.globals_definition.setTabStopDistance( QtGui.QFontMetricsF(self.globals_definition.font()).horizontalAdvance(" ") * 4 ) p = self.globals_definition.palette() for active in (QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorGroup.Inactive): p.setColor(active, QtGui.QPalette.ColorRole.Base, QtGui.QColor("#131314")) p.setColor(active, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor("#ffffff")) p.setColor(active, QtGui.QPalette.ColorRole.Text, QtGui.QColor("#ffffff")) self.globals_definition.setPalette(p) self.globals_highlighter = PythonHighlighter(self.globals_definition.document()) self.function_definition.setPlaceholderText( """The virtual channel definition is written as a Python function. Use the 'return' statement to return a value, otherwise 'None' will automatically be returned by the function. The last function argument must be 't=0'. Here is a minimalistic example: def MyAverage(main_clock=0, p_FL=0, p_FR=0, p_RL=0, p_RR=0, vehicle_speed=0, t=0): if main_clock > 5000: return 0 else: avg = (p_FL + p_FR + p_RL + p_RR) / 4 if avg > 20.5 and vehicle_speed < 100: return avg else: return avg + 9 """ ) self.function_definition.setTabStopDistance( QtGui.QFontMetricsF(self.function_definition.font()).horizontalAdvance(" ") * 4 ) p = self.function_definition.palette() for active in (QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorGroup.Inactive): p.setColor(active, QtGui.QPalette.ColorRole.Base, QtGui.QColor("#131314")) p.setColor(active, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor("#ffffff")) p.setColor(active, QtGui.QPalette.ColorRole.Text, QtGui.QColor("#ffffff")) self.function_definition.setPalette(p) self.func_highlighter = PythonHighlighter(self.function_definition.document()) self.functions_list.minimal_menu = True self.functions_list.all_texts = True self.functions_list.placeholder_text = "Press the + button to add a new function definition" self.functions_list.user_editable = True self.functions_list.setAlternatingRowColors(True) self.functions_list.setIconSize(QtCore.QSize(16, 16)) self.functions_list.itemsDeleted.connect(self.definitions_deleted) self.add_btn.clicked.connect(self.add_definition) self.check_syntax_btn.clicked.connect(self.check_syntax) self.check_globals_syntax_btn.clicked.connect(self.check_globals_syntax) self.erase_btn.clicked.connect(self.erase_definitions) self.export_btn.clicked.connect(self.export_definitions) self.import_btn.clicked.connect(self.import_definitions) self.store_btn.clicked.connect(self.store_definition) self.load_original_function_btn.clicked.connect(self.load_original_function_definition) self.load_original_globals_btn.clicked.connect(self.load_original_globals_definition) self.tabs.currentChanged.connect(self.tabs_changed) self.refresh_functions_list(selected_definition=selected_definition) self.functions_list.currentItemChanged.connect(self.definition_selection_changed) for button in ( self.add_btn, self.check_syntax_btn, self.check_globals_syntax_btn, self.erase_btn, self.import_btn, self.export_btn, ): button.setDefault(False) button.setAutoDefault(False) self.showMaximized() def add_definition(self): if previous := self.functions_list.currentItem(): name = previous.text() previous.setIcon(QtGui.QIcon()) info = self.definitions[name] info["current_definition"] = self.function_definition.toPlainText().replace("\t", " ") ok, _ = self.check_syntax(silent=True) if ok: if info["current_definition"] != info["definition"]: previous.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxInformation)) else: previous.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_CommandLink)) else: previous.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxCritical)) counter = 1 while True: name = f"Function{counter}" if name in self.definitions: counter += 1 else: break self.definitions[name] = { "definition": f"def {name}(t=0):\n return 0", "current_definition": f"def {name}(t=0):\n return 0", "uuid": os.urandom(6).hex(), } self.refresh_functions_list(selected_definition=name) def check_globals_syntax(self, silent=False): trace = generate_python_variables(self.globals_definition.toPlainText()) if trace: ErrorDialog( title="Global variables definition check", message="The syntax is not correct. The following error was found", trace=trace, parent=self, ).exec() elif not silent: MessageBox.information( self, "Global variables definition check", "The global variables definition appears to be correct.", ) return not bool(trace) def check_syntax(self, silent=False, definition=None, globals_definition=None): if definition is None: definition = self.function_definition.toPlainText().replace("\t", " ") if globals_definition is None: globals_definition = self.globals_definition.toPlainText() _globals = generate_python_function_globals() generate_python_variables(globals_definition, in_globals=_globals) for info in self.definitions.values(): generate_python_function(info["definition"], in_globals=_globals) function_source = definition func, trace = generate_python_function(function_source, in_globals=_globals) return check_generated_function(func, trace, function_source, silent, parent=self) def definitions_deleted(self, deleted): count = self.functions_list.count() names = {self.functions_list.item(row).text() for row in range(count)} deleted = [name for name in self.definitions if name not in names] for name in deleted: del self.definitions[name] if not self.definitions: self.function_definition.setPlainText("") def definition_selection_changed(self, current, previous): if previous: name = previous.text() previous.setIcon(QtGui.QIcon()) info = self.definitions[name] info["current_definition"] = self.function_definition.toPlainText().replace("\t", " ") ok, _ = self.check_syntax(silent=True) if ok: if info["current_definition"] != info["definition"]: previous.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxInformation)) else: previous.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_CommandLink)) else: previous.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxCritical)) if current: name = current.text() info = self.definitions[name] self.function_definition.setPlainText(info["current_definition"]) ok, _ = self.check_syntax(silent=True) if ok: if info["current_definition"] != info["definition"]: current.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxInformation)) else: current.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_CommandLink)) else: current.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxCritical)) def erase_definitions(self): self.functions_list.clear() self.definitions = {} self.function_definition.setPlainText("") def export_definitions(self, *args): self.refresh_definitions() for name, info in self.definitions.items(): if info["current_definition"] != info["definition"]: result = MessageBox.question( self, "Unsaved function definitions", "Do you want to review the functions before exporting them?" ) if result == MessageBox.StandardButton.No: break else: for row in range(self.functions_list.count()): item = self.functions_list.item(row) if item.text() == name: self.functions_list.setCurrentRow(row) self.functions_list.scrollToItem(item) break return file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select functions definition export file", "", "Functions definition file (*.def)", ) if file_name and Path(file_name).suffix.lower() == ".def": definitions = {name: info["current_definition"] for name, info in self.definitions.items()} definitions["__global_variables__"] = self.globals_definition.toPlainText().replace("\t", " ") Path(file_name).write_text(json.dumps(definitions, indent=2)) def import_definitions(self, *args): self.refresh_definitions() file_name, _ = QtWidgets.QFileDialog.getOpenFileName( self, "Select functions definition file", "", "Functions definitions file (*.def)", "Functions definitions file (*.def)", ) if file_name and Path(file_name).suffix.lower() == ".def": file_name = Path(file_name) with open(file_name) as infile: info = json.load(infile) self.globals_definition.setPlainText(info.pop("__global_variables__", "").replace("\t", " ")) for name, definition in info.items(): definition = definition.replace("\t", " ") if name in self.definitions: self.definitions[name]["definition"] = self.definitions[name]["current_definition"] = definition else: self.definitions[name] = { "definition": definition, "current_definition": definition, "uuid": os.urandom(6).hex(), } self.refresh_functions_list() def load_original_globals_definition(self): self.globals_definition.setPlainText(self.original_globals) def load_original_function_definition(self): item = self.functions_list.currentItem() if not item: return current_name = item.text() info = self.definitions.pop(current_name) original_definition = info["original_definition"] info["current_definition"] = original_definition self.function_definition.setPlainText(original_definition) self.definitions[current_name] = info self.refresh_functions_list() def refresh_definitions(self): _globals = generate_python_function_globals() generate_python_variables(self.globals_definition.toPlainText(), in_globals=_globals) for info in self.definitions.values(): generate_python_function(info["current_definition"], in_globals=_globals) function_source = self.function_definition.toPlainText().replace("\t", " ") func, trace = generate_python_function(function_source, in_globals=_globals) if func is not None: name = func.__name__ if name in self.definitions: self.definitions[name]["current_definition"] = self.function_definition.toPlainText().replace( "\t", " " ) def refresh_functions_list(self, selected_definition=""): self.functions_list.blockSignals(True) self.functions_list.clear() if self.definitions: items = [] names = natsorted(self.definitions) for name in names: info = self.definitions[name] ok, func = self.check_syntax(silent=True, definition=info["definition"]) if ok: if info["current_definition"] != info["definition"]: items.append( QtWidgets.QListWidgetItem( self.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxInformation), name, self.functions_list, ) ) else: items.append( QtWidgets.QListWidgetItem( self.style().standardIcon(QtWidgets.QStyle.SP_CommandLink), name, self.functions_list, ) ) else: items.append( QtWidgets.QListWidgetItem( self.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxCritical), name, self.functions_list, ) ) self.functions_list.blockSignals(False) if selected_definition: if selected_definition in names: self.functions_list.setCurrentRow(names.index(selected_definition)) elif names: self.functions_list.setCurrentRow(0) else: self.functions_list.blockSignals(False) def store_definition(self, *args): item = self.functions_list.currentItem() if not item: return current_name = item.text() info = self.definitions.pop(current_name) info["definition"] = info["current_definition"] = self.function_definition.toPlainText().replace("\t", " ") ok, func = self.check_syntax(silent=True) if ok: func_name = func.__name__ if current_name != func_name and func_name in self.definitions: MessageBox.information( self, "Invalid function name", f'The name "{func_name}" is already given to another function.\nThe function names must be unique', ) else: current_name = func_name self.definitions[current_name] = info self.refresh_functions_list(selected_definition=current_name) def tabs_changed(self, index): self.check_globals_syntax(silent=True) asammdf-8.5.1/src/asammdf/gui/widgets/gps.py000066400000000000000000000107721502633300400207340ustar00rootroot00000000000000from time import perf_counter, sleep from traceback import format_exc import numpy as np from PySide6 import QtCore, QtWidgets from ..ui.gps import Ui_GPSDisplay try: from pyqtlet2 import L, MapWidget from PySide6.QtWebEngineCore import QWebEngineSettings except: print(format_exc()) class GPS(Ui_GPSDisplay, QtWidgets.QWidget): timestamp_changed_signal = QtCore.Signal(object, float) def __init__(self, latitude_channel, longitude_channel, zoom=15, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) timebase = np.around(np.union1d(latitude_channel.timestamps, longitude_channel.timestamps), 9) self.latitude_signal = latitude_channel.interp(timebase) self.longitude_signal = longitude_channel.interp(timebase) if len(timebase): self.latitude = float(self.latitude_signal.samples[0]) self.longitude = float(self.longitude_signal.samples[0]) else: self.latitude = self.longitude = None self._min = self._max = 0 self._inhibit = False if len(timebase): self._min = timebase[0] self._max = timebase[-1] else: self._min = float("inf") self._max = -float("inf") if self._min == float("inf"): self._min = self._max = 0 self._timestamp = self._min self.timestamp.setRange(self._min, self._max) self.timestamp.setValue(self._min) self.min_t.setText(f"{self._min:.6f}s") self.max_t.setText(f"{self._max:.6f}s") self.mapWidget = MapWidget() self.mapWidget.settings().setAttribute(QWebEngineSettings.WebAttribute.LocalContentCanAccessRemoteUrls, True) self.map_layout.insertWidget(0, self.mapWidget) self.map_layout.setStretch(0, 1) self.map = L.map(self.mapWidget) self.map.setView([47.13698, 27.59774], zoom) L.tileLayer("https://{s}.tile.osm.org/{z}/{x}/{y}.png").addTo(self.map) if len(timebase): line = L.polyline(np.column_stack([self.latitude_signal.samples, self.longitude_signal.samples]).tolist()) line.addTo(self.map) self.map.setView([self.latitude, self.longitude], zoom) self.marker = L.marker([self.latitude, self.longitude]) self.map.addLayer(self.marker) else: self.marker = None self.timestamp.valueChanged.connect(self._timestamp_changed) self.timestamp_slider.valueChanged.connect(self._timestamp_slider_changed) self.set_timestamp() self.show() def _timestamp_changed(self, stamp): if not self._inhibit: self.set_timestamp(stamp) def _timestamp_slider_changed(self, stamp): if not self._inhibit: factor = stamp / 99999 stamp = (self._max - self._min) * factor + self._min self.set_timestamp(stamp) def get_zoom(self): result = [] def callback(*args): result.append(args[0]) map_widget = self.map.getMapWidgetAtIndex(self.map.mapWidgetIndex) map_widget.page.runJavaScript("map.getZoom()", self.map.mapWidgetIndex, callback) app = QtWidgets.QApplication.instance() start = perf_counter() while not result and perf_counter() - start < 1: sleep(0.1) app.processEvents() return int(result[0]) if result else 15 def set_timestamp(self, stamp=None): if stamp is None: stamp = self._timestamp if not (self._min <= stamp <= self._max): return try: self.latitude = float(self.latitude_signal.cut(stamp, stamp).samples[0]) self.longitude = float(self.longitude_signal.cut(stamp, stamp).samples[0]) except: return if self.marker is not None: self.marker.setLatLng([self.latitude, self.longitude]) app = QtWidgets.QApplication.instance() app.processEvents() self._inhibit = True if self._min != self._max: val = int((stamp - self._min) / (self._max - self._min) * 99999) self.timestamp_slider.setValue(val) self.timestamp.setValue(stamp) self._inhibit = False self.timestamp_changed_signal.emit(self, stamp) def to_config(self): config = { "latitude_channel": self.latitude_signal.name, "longitude_channel": self.longitude_signal.name, "zoom": self.get_zoom(), } return config asammdf-8.5.1/src/asammdf/gui/widgets/lin_bus_trace.py000066400000000000000000000037011502633300400227460ustar00rootroot00000000000000import logging import dateutil.tz import pandas as pd from PySide6 import QtCore, QtGui from .tabular_base import TabularBase logger = logging.getLogger("asammdf.gui") LOCAL_TIMEZONE = dateutil.tz.tzlocal() class LINBusTrace(TabularBase): add_channels_request = QtCore.Signal(list) def __init__(self, signals=None, start=0, format="phys", ranges=None, *args, **kwargs): ranges = ranges or {name: [] for name in signals.columns} if not ranges["Event Type"]: ranges["Event Type"] = [ { "background_color": QtGui.QColor("#ff0000"), "font_color": QtGui.QColor("#000000"), "op1": "!=", "op2": "==", "value1": "LIN Frame", "value2": None, }, ] super().__init__(signals, ranges) self.signals_descr = dict.fromkeys(signals.columns, 0) self.start = start.astimezone(LOCAL_TIMEZONE) self.pattern = {} self.format = format self.format_selection.setCurrentText(format) self._original_timestamps = signals["timestamps"] self._original_ts_series = pd.Series( self._original_timestamps, index=signals.index, ) prefixes = set() for name in signals.columns: while "." in name: name = name.rsplit(".", 1)[0] prefixes.add(f"{name}.") self.filters.minimal_menu = True self.prefix.insertItems(0, sorted(prefixes, key=lambda x: (-len(x), x))) self.prefix.setEnabled(False) self.prefix.currentIndexChanged.connect(self.prefix_changed) if prefixes: self.remove_prefix.setCheckState(QtCore.Qt.CheckState.Checked) self._settings = QtCore.QSettings() integer_mode = self._settings.value("tabular_format", "phys") self.format_selection.setCurrentText(integer_mode) asammdf-8.5.1/src/asammdf/gui/widgets/list.py000066400000000000000000000514641502633300400211210ustar00rootroot00000000000000import json from struct import pack from natsort import natsorted from PySide6 import QtCore, QtGui, QtWidgets from ..serde import extract_mime_names class ListWidget(QtWidgets.QListWidget): itemsDeleted = QtCore.Signal(list) set_time_offset = QtCore.Signal(list) items_rearranged = QtCore.Signal() add_channels_request = QtCore.Signal(list) show_properties = QtCore.Signal(object) insert_computation = QtCore.Signal(str) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.details_enabled = False self.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove) self.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection) self.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.open_menu) self.setAlternatingRowColors(True) self.can_delete_items = True self.setAcceptDrops(True) self.itemSelectionChanged.connect(self.item_selection_changed) self.show() self._has_hidden_items = False def item_selection_changed(self, item=None): selection = list(self.selectedItems()) for row in range(self.count()): item = self.item(row) if item in selection: widget = self.itemWidget(item) if widget is not None: widget.set_selected(True) else: widget = self.itemWidget(item) if widget is not None: widget.set_selected(False) def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if key == QtCore.Qt.Key.Key_Delete and self.can_delete_items: selected_items = self.selectedItems() deleted = [] for item in selected_items: row = self.row(item) item_widget = self.itemWidget(item) deleted.append(getattr(item_widget, "uuid", None)) if hasattr(item_widget, "disconnect_slots"): item_widget.disconnect_slots() self.takeItem(row) if deleted: self.itemsDeleted.emit(deleted) event.accept() elif key == QtCore.Qt.Key.Key_Space and modifiers == QtCore.Qt.KeyboardModifier.NoModifier: event.accept() selected_items = self.selectedItems() if not selected_items: return states = [self.itemWidget(item).display.checkState() for item in selected_items] if any(state == QtCore.Qt.CheckState.Unchecked for state in states): state = QtCore.Qt.CheckState.Checked else: state = QtCore.Qt.CheckState.Unchecked for item in selected_items: wid = self.itemWidget(item) wid.display.setCheckState(state) elif key == QtCore.Qt.Key.Key_Space and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() selected_items = self.selectedItems() if not selected_items: return states = [self.itemWidget(item).individual_axis.checkState() for item in selected_items] if any(state == QtCore.Qt.CheckState.Unchecked for state in states): state = QtCore.Qt.CheckState.Checked else: state = QtCore.Qt.CheckState.Unchecked for item in selected_items: wid = self.itemWidget(item) wid.individual_axis.setCheckState(state) elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_C: selected_items = self.selectedItems() if not selected_items: event.accept() return self.itemWidget(selected_items[0]).keyPressEvent(event) elif modifiers == ( QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier ) and key in ( QtCore.Qt.Key.Key_C, QtCore.Qt.Key.Key_P, ): selected_items = self.selectedItems() if not selected_items: event.accept() return self.itemWidget(selected_items[0]).keyPressEvent(event) else: super().keyPressEvent(event) def startDrag(self, supportedActions): selected_items = self.selectedItems() mimeData = QtCore.QMimeData() data = [] for item in selected_items: entry = item.entry computation = item.computation widget = self.itemWidget(item) color = widget.color unit = widget.unit if entry == (-1, -1): info = { "name": item.name, "computation": computation, "computed": True, "unit": unit, "color": color, } info = json.dumps(info).encode("utf-8") else: info = item.name.encode("utf-8") data.append( pack( f"<12s3q{len(info)}s", str(item.origin_uuid).encode("ascii"), entry[0], entry[1], len(info), info, ) ) mimeData.setData("application/octet-stream-asammdf", QtCore.QByteArray(b"".join(data))) drag = QtGui.QDrag(self) drag.setMimeData(mimeData) drag.exec(QtCore.Qt.DropAction.CopyAction) def dragEnterEvent(self, e): if e.mimeData().hasFormat("application/octet-stream-asammdf"): e.accept() super().dragEnterEvent(e) def dropEvent(self, e): if e.source() is self: super().dropEvent(e) self.items_rearranged.emit() else: data = e.mimeData() if data.hasFormat("application/octet-stream-asammdf"): names = extract_mime_names(data) self.add_channels_request.emit(names) else: super().dropEvent(e) def open_menu(self, position): item = self.itemAt(position) if item is None: return else: menu = QtWidgets.QMenu() menu.addAction(f"{self.count()} items in the list") menu.addSeparator() menu.addAction("Copy name (Ctrl+C)") menu.addAction("Copy display properties (Ctrl+Shift+C)") menu.addAction("Paste display properties (Ctrl+Shift+P)") menu.addSeparator() menu.addAction("Enable all") menu.addAction("Disable all") menu.addAction("Enable all but this") menu.addSeparator() if self._has_hidden_items: show_hide = "Show disabled items" else: show_hide = "Hide disabled items" menu.addAction(show_hide) menu.addSeparator() menu.addAction("Add to common Y axis") menu.addAction("Remove from common Y axis") menu.addSeparator() menu.addAction("Set unit") menu.addAction("Set precision") menu.addSeparator() menu.addAction("Relative time base shift") menu.addAction("Set time base start offset") menu.addSeparator() menu.addAction("Insert computation using this channel") menu.addSeparator() menu.addAction("Delete (Del)") menu.addSeparator() menu.addAction("Toggle details") menu.addAction("File/Computation properties") action = menu.exec_(self.viewport().mapToGlobal(position)) if action is None: return if action.text() == "Copy name (Ctrl+C)": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier ) self.itemWidget(item).keyPressEvent(event) elif action.text() == "Copy display properties (Ctrl+Shift+C)": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.itemWidget(item).keyPressEvent(event) elif action.text() == "Paste display properties (Ctrl+Shift+P)": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_P, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.itemWidget(item).keyPressEvent(event) elif action.text() == "Enable all": for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) widget.display.setCheckState(QtCore.Qt.CheckState.Checked) elif action.text() == "Disable all": for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) widget.display.setCheckState(QtCore.Qt.CheckState.Unchecked) elif action.text() == "Enable all but this": selected_items = self.selectedItems() for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) if item in selected_items: widget.display.setCheckState(QtCore.Qt.CheckState.Unchecked) else: widget.display.setCheckState(QtCore.Qt.CheckState.Checked) elif action.text() == show_hide: if self._has_hidden_items: for i in range(self.count()): item = self.item(i) item.setHidden(False) else: for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) if not widget.display.isChecked(): item.setHidden(True) self._has_hidden_items = not self._has_hidden_items elif action.text() == "Add to common Y axis": selected_items = self.selectedItems() for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) if item in selected_items: widget.ylink.setCheckState(QtCore.Qt.CheckState.Checked) elif action.text() == "Remove from common Y axis": selected_items = self.selectedItems() for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) if item in selected_items: widget.ylink.setCheckState(QtCore.Qt.CheckState.Unchecked) elif action.text() == "Set unit": selected_items = self.selectedItems() unit, ok = QtWidgets.QInputDialog.getText(self, "Set new unit", "Unit:") if ok: selected_items = self.selectedItems() for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) if item in selected_items: widget.unit = unit widget.update() elif action.text() == "Set precision": selected_items = self.selectedItems() precision, ok = QtWidgets.QInputDialog.getInt(self, "Set new precision (float decimals)", "Precision:") if ok and 0 <= precision <= 15: for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) if item in selected_items: widget.set_precision(precision) widget.update() elif action.text() in ( "Relative time base shift", "Set time base start offset", ): selected_items = self.selectedItems() if selected_items: if action.text() == "Relative time base shift": offset, ok = QtWidgets.QInputDialog.getDouble( self, "Relative offset [s]", "Offset [s]:", decimals=6 ) absolute = False else: offset, ok = QtWidgets.QInputDialog.getDouble( self, "Absolute time start offset [s]", "Offset [s]:", decimals=6, ) absolute = True if ok: uuids = [] for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) if item in selected_items: uuids.append(widget.uuid) self.set_time_offset.emit([absolute, offset, *uuids]) elif action.text() == "Delete (Del)": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Delete, QtCore.Qt.KeyboardModifier.NoModifier ) self.keyPressEvent(event) elif action.text() == "Toggle details": self.details_enabled = not self.details_enabled for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) widget.details.setVisible(self.details_enabled) item.setSizeHint(widget.sizeHint()) elif action.text() == "File/Computation properties": selected_items = self.selectedItems() if len(selected_items) == 1: item = selected_items[0] self.show_properties.emit(self.itemWidget(item).uuid) elif action.text() == "Insert computation using this channel": selected_items = self.selectedItems() if len(selected_items) == 1: item = selected_items[0] self.insert_computation.emit(self.itemWidget(item)._name) class MinimalListWidget(QtWidgets.QListWidget): itemsDeleted = QtCore.Signal(list) itemsPasted = QtCore.Signal() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove) self.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection) self.setAlternatingRowColors(True) self.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.open_menu) self.setAcceptDrops(True) self.show() self.itemSelectionChanged.connect(self.item_selection_changed) self.minimal_menu = False self.all_texts = False self.placeholder_text = "" self.user_editable = True def item_selection_changed(self, item=None): try: selection = list(self.selectedItems()) for row in range(self.count()): item = self.item(row) if item in selection: self.itemWidget(item).set_selected(True) else: self.itemWidget(item).set_selected(False) except: pass def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if key == QtCore.Qt.Key.Key_Delete and self.user_editable: selected_items = self.selectedItems() deleted = [] if self.all_texts: to_delete = set() for item in selected_items: row = self.row(item) deleted.append(row) item_widget = self.itemWidget(item) if hasattr(item_widget, "disconnect_slots"): item_widget.disconnect_slots() to_delete.add(item.text()) all_texts = set() count = self.count() for row in range(count): item = self.item(row) all_texts.add(item.text()) self.clear() self.addItems(natsorted(all_texts - to_delete)) else: for item in selected_items: row = self.row(item) deleted.append(row) item_widget = self.itemWidget(item) if hasattr(item_widget, "disconnect_slots"): item_widget.disconnect_slots() self.takeItem(row) if deleted: self.itemsDeleted.emit(deleted) event.accept() elif key == QtCore.Qt.Key.Key_C and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: text = [] for item in self.selectedItems(): try: text.append(self.itemWidget(item).text()) except: text.append(item.text()) if text: text = "\n".join(text) else: text = "" QtWidgets.QApplication.instance().clipboard().setText(text) event.accept() elif ( key == QtCore.Qt.Key.Key_V and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and self.user_editable ): lines = QtWidgets.QApplication.instance().clipboard().text().splitlines() if lines: try: self.addItems(lines) self.itemsPasted.emit() except: pass event.accept() else: super().keyPressEvent(event) def open_menu(self, position): menu = QtWidgets.QMenu() if self.minimal_menu: if self.count() > 0: menu.addAction(f"{self.count()} items in the list") if self.user_editable: menu.addSeparator() menu.addAction("Delete (Del)") else: return else: if self.count() == 0: menu.addAction(f"{self.count()} items in the list") menu.addSeparator() if self.user_editable: menu.addAction("Paste names (Ctrl+V)") else: menu.addAction(f"{self.count()} items in the list") menu.addSeparator() menu.addAction("Copy names (Ctrl+C)") if self.user_editable: menu.addAction("Paste names (Ctrl+V)") menu.addSeparator() menu.addAction("Delete (Del)") action = menu.exec_(self.viewport().mapToGlobal(position)) if action is None: return if action.text() == "Delete (Del)": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Delete, QtCore.Qt.KeyboardModifier.NoModifier ) self.keyPressEvent(event) elif action.text() == "Copy names (Ctrl+C)": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) elif action.text() == "Paste names (Ctrl+V)": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_V, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) def paintEvent(self, event): super().paintEvent(event) if self.count() == 0 and self.placeholder_text: painter = QtGui.QPainter(self.viewport()) painter.save() col = self.palette().placeholderText().color() painter.setPen(col) fm = self.fontMetrics() elided_text = fm.elidedText( self.placeholder_text, QtCore.Qt.TextElideMode.ElideRight, self.viewport().width() ) painter.drawText(self.viewport().rect(), QtCore.Qt.AlignmentFlag.AlignCenter, elided_text) painter.restore() def search(self, attribute="", value=None): index = None count = self.count() for row in range(count): item = self.item(row) if hasattr(item, attribute): if getattr(item, attribute) == value: index = row break else: widget = self.itemWidget(item) if hasattr(widget, attribute): if getattr(widget, attribute) == value: index = row break return index asammdf-8.5.1/src/asammdf/gui/widgets/list_item.py000066400000000000000000000005021502633300400221220ustar00rootroot00000000000000from PySide6 import QtWidgets class ListItem(QtWidgets.QListWidgetItem): def __init__(self, entry, name="", computation=None, parent=None, origin_uuid=None): super().__init__() self.entry = entry self.name = name self.computation = computation self.origin_uuid = origin_uuid asammdf-8.5.1/src/asammdf/gui/widgets/loader.py000066400000000000000000000014721502633300400214060ustar00rootroot00000000000000from PySide6.QtCore import QMetaObject from PySide6.QtUiTools import QUiLoader class UiLoader(QUiLoader): def __init__(self, base_instance): QUiLoader.__init__(self, base_instance) self.base_instance = base_instance def createWidget(self, class_name, parent=None, name=""): if parent is None and self.base_instance: return self.base_instance else: # create a new widget for child widgets widget = QUiLoader.createWidget(self, class_name, parent, name) if self.base_instance: setattr(self.base_instance, name, widget) return widget def load_ui(ui_file, base_instance=None): loader = UiLoader(base_instance) widget = loader.load(ui_file) QMetaObject.connectSlotsByName(widget) return widget asammdf-8.5.1/src/asammdf/gui/widgets/main.py000066400000000000000000002235201502633300400210640ustar00rootroot00000000000000from functools import partial import gc import os from pathlib import Path import platform import sys import webbrowser from natsort import natsorted import pyqtgraph as pg from PySide6 import __version__ as pyside6_version from PySide6 import QtCore, QtGui, QtWidgets from ...version import __version__ as libversion from .. import utils from ..dialogs.bus_database_manager import BusDatabaseManagerDialog from ..dialogs.dependencies_dlg import DependenciesDlg from ..dialogs.functions_manager import FunctionsManagerDialog from ..dialogs.messagebox import MessageBox from ..dialogs.multi_search import MultiSearch from ..dialogs.window_selection_dialog import WindowSelectionDialog from ..ui.main_window import Ui_PyMDFMainWindow from ..utils import draw_color_icon from .batch import BatchWidget from .file import FileWidget from .mdi_area import get_functions, MdiAreaWidget, WithMDIArea from .plot import Plot class MainWindow(WithMDIArea, Ui_PyMDFMainWindow, QtWidgets.QMainWindow): def __init__(self, files=None, *args, **kwargs): super(Ui_PyMDFMainWindow, self).__init__(*args, **kwargs) WithMDIArea.__init__(self, comparison=True) self.setupUi(self) self._settings = QtCore.QSettings() self._settings.setValue("current_theme", self._settings.value("theme", "Light")) self._light_palette = self.palette() self.ignore_value2text_conversions = self._settings.value("ignore_value2text_conversions", False, type=bool) self.display_cg_name = self._settings.value("display_cg_name", False, type=bool) self.integer_interpolation = int(self._settings.value("integer_interpolation", "2 - hybrid interpolation")[0]) self.float_interpolation = int(self._settings.value("float_interpolation", "1 - linear interpolation")[0]) self.batch = BatchWidget( self.ignore_value2text_conversions, self.integer_interpolation, self.float_interpolation, ) self.stackedWidget.addWidget(self.batch) widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() widget.setLayout(layout) multi_search = QtWidgets.QPushButton("Search") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/search.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) multi_search.setIcon(icon) multi_search.clicked.connect(self.comparison_search) multi_info = QtWidgets.QPushButton("Measurements information") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) multi_info.setIcon(icon) multi_info.clicked.connect(self.comparison_info) multi_info2 = QtWidgets.QPushButton("Load dsp") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/open.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) multi_info2.setIcon(icon) multi_info2.clicked.connect(self.comparison_dsp) hbox = QtWidgets.QHBoxLayout() hbox.addWidget(multi_search) hbox.addWidget(multi_info) hbox.addWidget(multi_info2) hbox.addStretch() self.mdi_area = MdiAreaWidget(parent=self, comparison=True) self.mdi_area.add_window_request.connect(self.add_window) self.mdi_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) layout.addLayout(hbox) layout.addWidget(self.mdi_area) self.stackedWidget.addWidget(widget) self.stackedWidget.setCurrentIndex(0) self.progress = None self.files.tabCloseRequested.connect(self.close_file) self.stackedWidget.currentChanged.connect(self.mode_changed) menu = self.menubar.addMenu("File") open_group = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/open.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "Open", menu) action.triggered.connect(self.open) action.setShortcut(QtGui.QKeySequence("Ctrl+O")) open_group.addAction(action) action = QtGui.QAction(icon, "Open folder", menu) action.triggered.connect(self.open_folder) open_group.addAction(action) menu.addActions(open_group.actions()) menu.addSeparator() open_group = QtGui.QActionGroup(self) action = QtGui.QAction(icon, "Open configuration", menu) action.triggered.connect(self.open_configuration) open_group.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/save.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "Save configuration", menu) action.triggered.connect(self.save_configuration) open_group.addAction(action) menu.addActions(open_group.actions()) # mode_actions mode_actions = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/file.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}".format("Single files"), menu) action.triggered.connect(partial(self.stackedWidget.setCurrentIndex, 0)) mode_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/list.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}".format("Batch processing"), menu) action.triggered.connect(partial(self.stackedWidget.setCurrentIndex, 1)) mode_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/compare.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}".format("Comparison"), menu) action.triggered.connect(partial(self.stackedWidget.setCurrentIndex, 2)) mode_actions.addAction(action) menu = QtWidgets.QMenu("Mode", self.menubar) menu.addActions(mode_actions.actions()) self.menubar.addMenu(menu) # managers actions = QtGui.QActionGroup(self) action = QtGui.QAction("{: <20}\tF6".format("Functions manager"), menu) action.triggered.connect(self.functions_manager) action.setShortcut("F6") actions.addAction(action) action = QtGui.QAction("{: <20}".format("Bus database manager"), menu) action.triggered.connect(self.bus_database_manager) actions.addAction(action) menu = QtWidgets.QMenu("Managers", self.menubar) menu.addActions(actions.actions()) self.menubar.addMenu(menu) # settings menu = QtWidgets.QMenu("Settings", self.menubar) self.menubar.addMenu(menu) # sub plots subplot_action = QtGui.QAction("Sub-windows", menu) subplot_action.setCheckable(True) state = self._settings.value("subplots", True, type=bool) subplot_action.toggled.connect(self.set_subplot_option) subplot_action.triggered.connect(self.set_subplot_option) subplot_action.setChecked(state) menu.addAction(subplot_action) # Link sub-windows X-axis subplot_action = QtGui.QAction("Link sub-windows X-axis", menu) subplot_action.setCheckable(True) state = self._settings.value("subplots_link", True, type=bool) subplot_action.toggled.connect(self.set_subplot_link_option) subplot_action.setChecked(state) menu.addAction(subplot_action) # Ignore value2text conversions subplot_action = QtGui.QAction("Ignore value2text conversions", menu) subplot_action.setCheckable(True) subplot_action.toggled.connect(self.set_ignore_value2text_conversions_option) subplot_action.setChecked(self.ignore_value2text_conversions) menu.addAction(subplot_action) # Show Channel Group Name subplot_action = QtGui.QAction("Display Channel Group Name", menu) subplot_action.setCheckable(True) subplot_action.toggled.connect(self.set_display_cg_name_option) subplot_action.setChecked(self.display_cg_name) menu.addAction(subplot_action) # plot background plot_background_option = QtGui.QActionGroup(self) for option in ("Black", "White"): action = QtGui.QAction(option, menu) action.setCheckable(True) plot_background_option.addAction(action) action.triggered.connect(partial(self.set_plot_background, option)) if option == self._settings.value("plot_background", "Black"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Plot background", self.menubar) submenu.addActions(plot_background_option.actions()) menu.addMenu(submenu) # plot X axis display mode plot_xaxis_option = QtGui.QActionGroup(self) for option in ("seconds", "time", "date"): action = QtGui.QAction(option, menu) action.setCheckable(True) plot_xaxis_option.addAction(action) action.triggered.connect(partial(self.set_plot_xaxis, option)) if option == self._settings.value("plot_xaxis", "seconds"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Plot X axis", self.menubar) submenu.addActions(plot_xaxis_option.actions()) menu.addMenu(submenu) # theme menu theme_option = QtGui.QActionGroup(self) for option in ("Dark", "Light"): action = QtGui.QAction(option, menu) action.setCheckable(True) theme_option.addAction(action) action.triggered.connect(partial(self.set_theme, option)) if option == self._settings.value("theme", "Light"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Theme", self.menubar) submenu.addActions(theme_option.actions()) menu.addMenu(submenu) # step line connect menu step_option = QtGui.QActionGroup(self) for option in ("line", "left", "right"): icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(f":/{option}_interconnect.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off, ) action = QtGui.QAction(icon, option, menu) action.setCheckable(True) step_option.addAction(action) action.triggered.connect(partial(self.set_line_interconnect, option)) if option == self._settings.value("line_interconnect", "line"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Step mode", self.menubar) submenu.addActions(step_option.actions()) menu.addMenu(submenu) # integer interpolation menu theme_option = QtGui.QActionGroup(self) for option, tooltip in zip( ( "0 - repeat previous sample", "1 - linear interpolation", "2 - hybrid interpolation", ), ( "", "", "channels with integer data type (raw values) that have a conversion that outputs float " "values will use linear interpolation, otherwise the previous sample is used", ), strict=False, ): action = QtGui.QAction(option, menu) action.setCheckable(True) if tooltip: action.setToolTip(tooltip) theme_option.addAction(action) action.triggered.connect(partial(self.set_integer_interpolation, option)) if option == self._settings.value("integer_interpolation", "2 - hybrid interpolation"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Integer interpolation", self.menubar) submenu.addActions(theme_option.actions()) submenu.setToolTipsVisible(True) menu.addMenu(submenu) # float interpolation menu theme_option = QtGui.QActionGroup(self) for option in ("0 - repeat previous sample", "1 - linear interpolation"): action = QtGui.QAction(option, menu) action.setCheckable(True) theme_option.addAction(action) action.triggered.connect(partial(self.set_float_interpolation, option)) if option == self._settings.value("float_interpolation", "1 - linear interpolation"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Float interpolation", self.menubar) submenu.addActions(theme_option.actions()) submenu.setToolTipsVisible(True) menu.addMenu(submenu) # tabular interpolation subplot_action = QtGui.QAction("Tabular windows interpolation", menu) subplot_action.setCheckable(True) state = self._settings.value("tabular_interpolation", True, type=bool) subplot_action.toggled.connect(self.set_tabular_interpolation_option) subplot_action.setChecked(state) menu.addAction(subplot_action) submenu = QtWidgets.QMenu("Cursor", self.menubar) # cursor action = QtGui.QAction("Color") action.triggered.connect(partial(self.edit_cursor_options, action=action)) color = self._settings.value("cursor_color", "white") icon = draw_color_icon(color) action.setIcon(icon) submenu.addAction(action) action = QtWidgets.QWidgetAction(submenu) action.setText("Line width") combo = QtWidgets.QComboBox() combo.addItems([f"{size}pixels width" for size in range(1, 5)]) combo.currentIndexChanged.connect(partial(self.edit_cursor_options, action=action)) action.setDefaultWidget(combo) submenu.addAction(action) action = QtGui.QAction("Show circle") action.setCheckable(True) action.toggled.connect(partial(self.edit_cursor_options, action=action)) action.setChecked(self._settings.value("show_cursor_circle", False, type=bool)) submenu.addAction(action) action = QtGui.QAction("Show horizontal line") action.setCheckable(True) action.toggled.connect(partial(self.edit_cursor_options, action=action)) action.setChecked(self._settings.value("show_cursor_horizontal_line", False, type=bool)) submenu.addAction(action) menu.addMenu(submenu) self.edit_cursor_options() # plot option menu plot_actions = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/fit.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) fullscreen = QtGui.QAction(icon, f"{'Fullscreen': <20}\tF11", menu) fullscreen.triggered.connect(self.toggle_fullscreen) fullscreen.setShortcut(QtCore.Qt.Key.Key_F11) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/fit.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, f"{'Fit all': <20}\tF", menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_F)) action.setShortcut(QtCore.Qt.Key.Key_F) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/fit.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, f"{'Fit selected': <20}\tShift+F", menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_F, modifier=QtCore.Qt.KeyboardModifier.ShiftModifier) ) action.setShortcut(QtGui.QKeySequence("Shift+F")) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/grid.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tG".format("Grid"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_G)) action.setShortcut(QtCore.Qt.Key.Key_G) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/axis.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tH".format("Honeywell"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_H)) action.setShortcut(QtCore.Qt.Key.Key_H) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/home.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tW".format("Home"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_W)) action.setShortcut(QtCore.Qt.Key.Key_W) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/list2.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tS".format("Stack all"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_S)) action.setShortcut(QtCore.Qt.Key.Key_S) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/list2.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tShift+S".format("Stack selected"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_S, modifier=QtCore.Qt.KeyboardModifier.ShiftModifier) ) action.setShortcut(QtGui.QKeySequence("Shift+S")) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/zoom-in.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tI".format("Zoom in"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_I)) action.setShortcut(QtCore.Qt.Key.Key_I) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/zoom-out.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tO".format("Zoom out"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_O)) action.setShortcut(QtCore.Qt.Key.Key_O) plot_actions.addAction(action) action = QtGui.QAction("{: <20}\tX".format("Zoom to range"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_X)) action.setShortcut(QtCore.Qt.Key.Key_X) plot_actions.addAction(action) action = QtGui.QAction("{: <20}\t.".format("Toggle dots"), menu) action.triggered.connect(partial(self.toggle_dots, key=QtCore.Qt.Key.Key_Period)) action.setShortcut(QtCore.Qt.Key.Key_Period) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/focus.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\t2".format("Focused mode"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_2)) action.setShortcut(QtCore.Qt.Key.Key_2) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/plus.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tIns".format("Insert computation"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_Insert)) action.setShortcut(QtCore.Qt.Key.Key_Insert) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/save.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+S".format("Save active subplot channels"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_S, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+S")) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/save.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+Shift+S".format("Save all subplot channels"), menu) action.triggered.connect(self.save_all_subplots) action.setShortcut(QtGui.QKeySequence("Ctrl+Shift+S")) plot_actions.addAction(action) # channel shifting channel_shift_actions = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/shift_left.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tShift+←".format("Shift channels left"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_Left, modifier=QtCore.Qt.KeyboardModifier.ShiftModifier, ) ) action.setShortcut(QtGui.QKeySequence("Shift+Left")) channel_shift_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/shift_right.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tShift+→".format("Shift channels right"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_Right, modifier=QtCore.Qt.KeyboardModifier.ShiftModifier, ) ) action.setShortcut(QtGui.QKeySequence("Shift+Right")) channel_shift_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/shift_up.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tShift+↑".format("Shift channels up"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_Up, modifier=QtCore.Qt.KeyboardModifier.ShiftModifier, ) ) action.setShortcut(QtGui.QKeySequence("Shift+Up")) channel_shift_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/shift_down.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tShift+↓".format("Shift channels down"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_Down, modifier=QtCore.Qt.KeyboardModifier.ShiftModifier, ) ) action.setShortcut(QtGui.QKeySequence("Shift+Down")) channel_shift_actions.addAction(action) # values display display_format_actions = QtGui.QActionGroup(self) action = QtGui.QAction("{: <20}\tCtrl+H".format("Hex"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_H, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+H")) display_format_actions.addAction(action) action = QtGui.QAction("{: <20}\tCtrl+B".format("Bin"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_B, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+B")) display_format_actions.addAction(action) action = QtGui.QAction("{: <20}\tCtrl+P".format("Physical"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_P, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+P")) display_format_actions.addAction(action) action = QtGui.QAction("{: <20}\tCtrl+T".format("ASCII"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_T, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+T")) display_format_actions.addAction(action) # scaled display samples_format_actions = QtGui.QActionGroup(self) action = QtGui.QAction("{: <20}\tAlt+R".format("Raw samples"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_R, modifier=QtCore.Qt.KeyboardModifier.AltModifier) ) action.setShortcut(QtGui.QKeySequence("Alt+R")) samples_format_actions.addAction(action) action = QtGui.QAction("{: <20}\tAlt+S".format("Scaled samples"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_S, modifier=QtCore.Qt.KeyboardModifier.AltModifier) ) action.setShortcut(QtGui.QKeySequence("Alt+S")) samples_format_actions.addAction(action) # info info = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tM".format("Statistics"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_M)) action.setShortcut(QtGui.QKeySequence("M")) info.addAction(action) # sub_plots subs = QtGui.QActionGroup(self) action = QtGui.QAction("{: <20}\tShift+C".format("Cascade sub-windows"), menu) action.triggered.connect(partial(self.show_sub_windows, mode="cascade")) action.setShortcut(QtGui.QKeySequence("Shift+C")) subs.addAction(action) action = QtGui.QAction("{: <20}\tShift+T".format("Tile sub-windows in a grid"), menu) action.triggered.connect(partial(self.show_sub_windows, mode="tile")) action.setShortcut(QtGui.QKeySequence("Shift+T")) subs.addAction(action) action = QtGui.QAction("{: <20}\tShift+V".format("Tile sub-windows vertically"), menu) action.triggered.connect(partial(self.show_sub_windows, mode="tile vertically")) action.setShortcut(QtGui.QKeySequence("Shift+V")) subs.addAction(action) action = QtGui.QAction("{: <20}\tShift+H".format("Tile sub-windows horizontally"), menu) action.triggered.connect(partial(self.show_sub_windows, mode="tile horizontally")) action.setShortcut(QtGui.QKeySequence("Shift+H")) subs.addAction(action) action = QtGui.QAction("{: <20}\tShift+Alt+F".format("Toggle sub-windows frames"), menu) action.triggered.connect(self.toggle_frames) action.setShortcut(QtGui.QKeySequence("Shift+Alt+F")) subs.addAction(action) action = QtGui.QAction("{: <20}\tShift+L".format("Toggle channel list"), menu) action.triggered.connect(self.toggle_channels_list) action.setShortcut(QtGui.QKeySequence("Shift+L")) subs.addAction(action) # cursors cursors_actions = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/cursor.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) action = QtGui.QAction(icon, "{: <20}\tShift+G".format("Go to time stamp"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_G, modifier=QtCore.Qt.KeyboardModifier.ShiftModifier, ) ) action.setShortcut(QtGui.QKeySequence("Shift+G")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/right.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\t←".format("Move cursor left"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_Left)) action.setShortcut(QtCore.Qt.Key.Key_Left) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/left.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\t→".format("Move cursor right"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_Right)) action.setShortcut(QtCore.Qt.Key.Key_Right) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/arrow_next_higher.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+PgUp".format("Move cursor to next higher"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_PageUp, modifier=QtCore.Qt.KeyboardModifier.ControlModifier) ) action.setShortcut(QtGui.QKeySequence("Ctrl+PgUp")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/arrow_previous_higher.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+Shift+PgUp".format("Move cursor to previous higher"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_PageUp, modifier=QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+Shift+PgUp")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/arrow_next_lower.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+PgDown".format("Move cursor to next lower"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_PageDown, modifier=QtCore.Qt.KeyboardModifier.ControlModifier ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+PgDown")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/arrow_previous_lower.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+Shift+PgDown".format("Move cursor to previous lower"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_PageDown, modifier=QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+Shift+PgDown")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/right2.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tAlt+→".format("Move cursor to next different value"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_Right, modifier=QtCore.Qt.KeyboardModifier.AltModifier, ) ) action.setShortcut(QtGui.QKeySequence("Alt+Right")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/left2.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tAlt+←".format("Move cursor to previous different value"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_Left, modifier=QtCore.Qt.KeyboardModifier.AltModifier, ) ) action.setShortcut(QtGui.QKeySequence("Alt+Left")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/range.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tR".format("Range"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_R)) action.setShortcut(QtCore.Qt.Key.Key_R) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/lock_range.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tY".format("Lock/unlock range"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_Y)) action.setShortcut(QtCore.Qt.Key.Key_Y) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/lock_range.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tShift+Y".format("Swap range lock"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_Y, modifier=QtCore.Qt.KeyboardModifier.ShiftModifier) ) action.setShortcut(QtGui.QKeySequence("Shift+Y")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/bookmark.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+I".format("Insert bookmark"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_I, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+I")) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/bookmark.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tAlt+I".format("Toggle bookmarks"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_I, modifier=QtCore.Qt.KeyboardModifier.AltModifier) ) action.setShortcut(QtGui.QKeySequence("Alt+I")) cursors_actions.addAction(action) self.plot_menu = QtWidgets.QMenu("Plot", self.menubar) self.plot_menu.addAction(fullscreen) self.plot_menu.addSeparator() self.plot_menu.addActions(plot_actions.actions()) self.plot_menu.addSeparator() submenu = QtWidgets.QMenu("Channel shifting", self.plot_menu) submenu.addActions(channel_shift_actions.actions()) self.plot_menu.addMenu(submenu) self.plot_menu.addSeparator() submenu = QtWidgets.QMenu("Cursors and bookmarks", self.plot_menu) submenu.addActions(cursors_actions.actions()) self.plot_menu.addMenu(submenu) self.plot_menu.addSeparator() submenu = QtWidgets.QMenu("Display mode", self.plot_menu) submenu.addActions(display_format_actions.actions()) submenu.addSeparator() submenu.addActions(samples_format_actions.actions()) self.plot_menu.addMenu(submenu) self.plot_menu.addSeparator() submenu = QtWidgets.QMenu("Windows", self.plot_menu) submenu.addActions(subs.actions()) self.plot_menu.addMenu(submenu) self.plot_menu.addSeparator() self.plot_menu.addActions(info.actions()) self.menubar.addMenu(self.plot_menu) menu = self.menubar.addMenu("Help") open_group = QtGui.QActionGroup(self) action = QtGui.QAction("Dependencies", menu) action.triggered.connect(partial(DependenciesDlg.show_dependencies, "asammdf")) open_group.addAction(action) action = QtGui.QAction("Online documentation", menu) action.triggered.connect(self.help) action.setShortcut(QtGui.QKeySequence("F1")) open_group.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "About asammdf-gui", menu) action.triggered.connect(self.show_about) open_group.addAction(action) open_group.addAction(action) menu.addActions(open_group.actions()) self.with_dots = self._settings.value("dots", False, type=bool) self.setWindowTitle(f"asammdf {libversion} [PID={os.getpid()}] - Single files") self.set_subplot_option(self._settings.value("subplots", "Disabled")) self.set_subplot_link_option(self._settings.value("subplots_link", "Disabled")) self.hide_missing_channels = False self.hide_disabled_channels = False self.allways_accept_dots = False if files: for name in files: self._open_file(name) self.setAcceptDrops(True) self.show() self.fullscreen = None def comparison_dsp(self, event=None): windows = list(self.mdi_area.subWindowList()) for window in windows: widget = window.widget() self.mdi_area.removeSubWindow(window) widget.setParent(None) widget.close() widget.deleteLater() window.close() import json from traceback import format_exc file_name, _ = QtWidgets.QFileDialog.getOpenFileName( self, "Select display file", "", "Display files (*.dspf)", "Display files (*.dspf)", ) if not file_name or Path(file_name).suffix.lower() != ".dspf": return with open(file_name) as infile: info = json.load(infile) new_functions = {} if "functions" in info: for name, definition in info["functions"].items(): if name in self.functions: if self.functions[name] != definition: new_functions[os.urandom(6).hex()] = { "name": name, "definition": definition, } else: new_functions[os.urandom(6).hex()] = { "name": name, "definition": definition, } else: for window in info["windows"]: if window["type"] == "Plot": for name, definition in get_functions(window["configuration"]["channels"]).items(): if name in self.functions: if self.functions[name] != definition: new_functions[os.urandom(6).hex()] = { "name": name, "definition": definition, } else: new_functions[os.urandom(6).hex()] = { "name": name, "definition": definition, } if new_functions or info.get("global_variables", "") != self.global_variables: self.update_functions({}, new_functions, f"{self.global_variables}\n{info.get('global_variables', '')}") windows = info.get("windows", []) for i, window in enumerate(windows, 1): try: self.load_window(window) except: print(format_exc()) def sizeHint(self): return QtCore.QSize(1, 1) def help(self, event): webbrowser.open_new(r"http://asammdf.readthedocs.io/en/master/gui.html") def save_all_subplots(self, key): if self.stackedWidget.currentIndex() == 0: widget = self.files.currentWidget() elif self.stackedWidget.currentIndex() == 2: widget = self widget = self.files.currentWidget() widget.save_all_subplots() def plot_action(self, key, modifier=QtCore.Qt.KeyboardModifier.NoModifier): event = QtGui.QKeyEvent(QtCore.QEvent.Type.KeyPress, key, modifier) if self.stackedWidget.currentIndex() == 0: widget = self.files.currentWidget() if widget and widget.get_current_widget(): widget.get_current_widget().keyPressEvent(event) elif self.stackedWidget.currentIndex() == 2: widget = self if widget and widget.get_current_widget(): widget.get_current_widget().keyPressEvent(event) event.accept() def toggle_dots(self, key): file_widget = self.files.currentWidget() if file_widget: widget = file_widget.get_current_widget() if widget and isinstance(widget, Plot): new_setting_has_dots = not file_widget.with_dots current_plot = widget count = len(current_plot.plot.signals) self.with_dots = new_setting_has_dots self._settings.setValue("dots", self.with_dots) file_widget.set_line_style(with_dots=new_setting_has_dots) self.set_line_style(with_dots=self.with_dots) else: widget = self.get_current_widget() if widget and isinstance(widget, Plot): self.with_dots = not self.with_dots self._settings.setValue("dots", self.with_dots) self.set_line_style(with_dots=self.with_dots) def show_sub_windows(self, mode): if self.stackedWidget.currentIndex() == 0: widget = self.files.currentWidget() if widget: if mode == "tile": widget.mdi_area.tileSubWindows() elif mode == "cascade": widget.mdi_area.cascadeSubWindows() elif mode == "tile vertically": widget.mdi_area.tile_vertically() elif mode == "tile horizontally": widget.mdi_area.tile_horizontally() else: widget = self if widget: if mode == "tile": widget.mdi_area.tileSubWindows() elif mode == "cascade": widget.mdi_area.cascadeSubWindows() elif mode == "tile vertically": widget.mdi_area.tile_vertically() elif mode == "tile horizontally": widget.mdi_area.tile_horizontally() def edit_cursor_options(self, checked=None, action=None): if action: if action.text() == "Color": color = self._settings.value("cursor_color", "white") color = QtWidgets.QColorDialog.getColor(color) if not color.isValid(): return self._settings.setValue("cursor_color", color.name()) icon = draw_color_icon(color) action.setIcon(icon) elif action.text() == "Show circle": self._settings.setValue("show_cursor_circle", action.isChecked()) elif action.text() == "Show horizontal line": self._settings.setValue("show_cursor_horizontal_line", action.isChecked()) elif action.text() == "Line width": self._settings.setValue("cursor_line_width", action.defaultWidget().currentIndex() + 1) cursor_circle = self._settings.value("show_cursor_circle", False, type=bool) cursor_horizontal_line = self._settings.value("show_cursor_horizontal_line", False, type=bool) cursor_line_width = self._settings.value("cursor_line_width", 1, type=int) cursor_color = self._settings.value("cursor_color", "#e69138") for i in range(self.files.count()): file = self.files.widget(i) file.set_cursor_options(cursor_circle, cursor_horizontal_line, cursor_line_width, cursor_color) def set_subplot_option(self, state): if isinstance(state, str): state = True if state == "true" else False self.set_subplots(state) self._settings.setValue("subplots", state) count = self.files.count() for i in range(count): self.files.widget(i).set_subplots(state) def set_plot_background(self, option): self._settings.setValue("plot_background", option) if option == "Black": pg.setConfigOption("background", "k") pg.setConfigOption("foreground", "w") else: pg.setConfigOption("background", "w") pg.setConfigOption("foreground", "k") def set_integer_interpolation(self, option): self._settings.setValue("integer_interpolation", option) option = int(option[0]) self.integer_interpolation = option count = self.files.count() for i in range(count): self.files.widget(i).mdf.configure(integer_interpolation=option) self.batch.integer_interpolation = option def set_float_interpolation(self, option): self._settings.setValue("float_interpolation", option) option = int(option[0]) self.float_interpolation = option count = self.files.count() for i in range(count): self.files.widget(i).mdf.configure(float_interpolation=option) self.batch.float_interpolation = option def set_plot_xaxis(self, option): self._settings.setValue("plot_xaxis", option) if option == "seconds": fmt = "phys" elif option == "time": fmt = "time" elif option == "date": fmt = "date" if self.stackedWidget.currentIndex() == 0: widget = self.files.currentWidget() elif self.stackedWidget.currentIndex() == 2: widget = self else: widget = None if widget: plot = widget.get_current_widget() if plot and isinstance(plot, Plot): widget.get_current_widget().plot.x_axis.format = fmt widget.get_current_widget().plot.x_axis.updateAutoSIPrefix() if plot.plot.cursor1 is not None: plot.cursor_moved() if plot.plot.region is not None: plot.range_modified(plot.plot.region) def set_theme(self, option): self._settings.setValue("theme", option) app = QtWidgets.QApplication.instance() if option == "Light": app.setPalette(self._light_palette) else: palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Button, brush) brush = QtGui.QBrush(QtGui.QColor(82, 82, 82)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Light, brush) brush = QtGui.QBrush(QtGui.QColor(68, 68, 68)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Midlight, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Dark, brush) brush = QtGui.QBrush(QtGui.QColor(36, 36, 36)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Mid, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Text, brush) brush = QtGui.QBrush(QtGui.QColor(100, 100, 100)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.PlaceholderText, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.BrightText, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.ButtonText, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Base, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Window, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Shadow, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.AlternateBase, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.ToolTipBase, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.ToolTipText, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Button, brush) brush = QtGui.QBrush(QtGui.QColor(82, 82, 82)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Light, brush) brush = QtGui.QBrush(QtGui.QColor(68, 68, 68)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Midlight, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Dark, brush) brush = QtGui.QBrush(QtGui.QColor(36, 36, 36)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Mid, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Text, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.BrightText, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.ButtonText, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Base, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Window, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Shadow, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.AlternateBase, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.ToolTipBase, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.ToolTipText, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Button, brush) brush = QtGui.QBrush(QtGui.QColor(82, 82, 82)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Light, brush) brush = QtGui.QBrush(QtGui.QColor(68, 68, 68)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Midlight, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Dark, brush) brush = QtGui.QBrush(QtGui.QColor(36, 36, 36)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Mid, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Text, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.BrightText, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Base, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Window, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Shadow, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.AlternateBase, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ToolTipBase, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ToolTipText, brush) brush = QtGui.QBrush(QtGui.QColor(100, 100, 100)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Highlight, brush) app.setPalette(palette) def set_line_interconnect(self, option): self._settings.setValue("line_interconnect", option) self.line_interconnect = option count = self.files.count() for i in range(count): self.files.widget(i).set_line_interconnect(option) def set_subplot_link_option(self, state): if isinstance(state, str): state = True if state == "true" else False self.set_subplots_link(state) self._settings.setValue("subplots_link", state) count = self.files.count() for i in range(count): self.files.widget(i).set_subplots_link(self.subplots_link) def set_tabular_interpolation_option(self, state): if isinstance(state, str): state = True if state == "true" else False self._settings.setValue("tabular_interpolation", state) def set_ignore_value2text_conversions_option(self, state): if isinstance(state, str): state = True if state == "true" else False self.ignore_value2text_conversions = state self._settings.setValue("ignore_value2text_conversions", state) count = self.files.count() for i in range(count): self.files.widget(i).ignore_value2text_conversions = state self.batch.ignore_value2text_conversions = state def set_display_cg_name_option(self, state): if isinstance(state, str): state = True if state == "true" else False self.display_cg_name = state self._settings.setValue("display_cg_name", state) count = self.files.count() for i in range(count): self.files.widget(i).display_cg_name = state if self.files.widget(i).isVisible(): self.files.widget(i).update_all_channel_trees() self.batch.display_cg_name = state def update_progress(self, current_index, max_index): self.progress = current_index, max_index def open_batch_files(self, event): file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select measurement file", "", "CSV (*.csv);;MDF v3 (*.dat *.mdf);;MDF v4(*.mf4);;DL3/ERG files (*.dl3 *.erg);;All files (*.csv *.dat *.mdf *.mf4 *.dl3 *.erg)", "All files (*.csv *.dat *.mdf *.mf4 *.dl3 *.erg)", ) if file_names: self.batch.files_list.addItems(natsorted(file_names)) count = self.batch.files_list.count() icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/file.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) for row in range(count): self.batch.files_list.item(row).setIcon(icon) def open(self, event): if self.stackedWidget.currentIndex() in (0, 2): self.open_file(event) self.stackedWidget.setCurrentIndex(0) else: self.open_batch_files(event) def _open_file(self, file_name): if isinstance(file_name, (tuple, list)): file_names = file_name else: file_names = [file_name] for _file_name in file_names: file_name = Path(_file_name) index = self.files.count() try: widget = FileWidget( file_name, self.with_dots, self.subplots, self.subplots_link, self.ignore_value2text_conversions, self.display_cg_name, self.line_interconnect, 1, None, None, self, ) except: raise else: widget.mdf.configure(integer_interpolation=self.integer_interpolation) self.files.addTab(widget, file_name.name) self.files.setTabToolTip(index, str(file_name)) self.files.setCurrentIndex(index) widget.open_new_files.connect(self._open_file) widget.full_screen_toggled.connect(self.toggle_fullscreen) self.edit_cursor_options() def open_file(self, event): system = platform.system().lower() if system == "linux": # see issue #567 # file extension is case sensitive on linux file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select measurement file", self._settings.value("last_opened_path", "", str), "CSV (*.csv);;MDF v3 (*.dat *.mdf);;MDF v4(*.mf4 *.mf4z);;DL3/ERG files (*.dl3 *.erg);;All files (*.csv *.dat *.mdf *.mf4 *.mf4z *.dl3 *.erg)", "All files (*.csv *.dat *.mdf *.mf4 *.mf4z *.dl3 *.erg)", options=QtWidgets.QFileDialog.Option.DontUseNativeDialog, ) else: file_names, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "Select measurement file", self._settings.value("last_opened_path", "", str), "CSV (*.csv);;MDF v3 (*.dat *.mdf);;MDF v4(*.mf4 *.mf4z);;DL3/ERG files (*.dl3 *.erg);;All files (*.csv *.dat *.mdf *.mf4 *.mf4z *.dl3 *.erg)", "All files (*.csv *.dat *.mdf *.mf4 *.mf4z *.dl3 *.erg)", ) if file_names: self._settings.setValue("last_opened_path", file_names[0]) gc.collect() for file_name in natsorted(file_names): self._open_file(file_name) def open_folder(self, event): folder = QtWidgets.QFileDialog.getExistingDirectory( self, "Select folder", "", QtWidgets.QFileDialog.Option.ShowDirsOnly | QtWidgets.QFileDialog.Option.DontResolveSymlinks, ) if not folder: return gc.collect() if self.stackedWidget.currentIndex() == 0: for root, dirs, files in os.walk(folder): for file in natsorted(files): if file.lower().endswith((".csv", ".erg", ".dl3", ".dat", ".mdf", ".mf4", ".mf4z")): self._open_file(os.path.join(root, file)) else: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/file.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.batch._ignore = True for root, dirs, files in os.walk(folder): for file in natsorted(files): if file.lower().endswith((".csv", ".erg", ".dl3", ".dat", ".mdf", ".mf4", ".mf4z")): item = QtWidgets.QListWidgetItem(icon, os.path.join(root, file)) self.batch.files_list.addItem(item) self.batch._ignore = False self.batch.update_channel_tree() def close_file(self, index): widget = self.files.widget(index) if widget: widget.close() widget.setParent(None) widget.deleteLater() if self.files.count(): self.files.setCurrentIndex(0) def closeEvent(self, event): count = self.files.count() for i in range(count): self.files.widget(i).close() if self.fullscreen: widget, index = self.fullscreen widget.close() widget.deleteLater() event.accept() def dragEnterEvent(self, e): e.accept() def dropEvent(self, e): try: if self.stackedWidget.currentIndex() == 0: for path in e.mimeData().text().splitlines(): path = Path(path.replace(r"file:///", "")) if path.suffix.lower() in utils.SUPPORTED_FILE_EXTENSIONS: self._open_file(path) else: icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/file.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) for path in e.mimeData().text().splitlines(): path = Path(path.replace(r"file:///", "")) if path.suffix.lower() in utils.SUPPORTED_FILE_EXTENSIONS: row = self.batch.files_list.count() self.batch.files_list.addItem(str(path)) self.batch.files_list.item(row).setIcon(icon) except: pass def mode_changed(self, index): if index == 0: self.plot_menu.setEnabled(True) self.setWindowTitle(f"asammdf {libversion} [PID={os.getpid()}] - Single files") elif index == 1: self.plot_menu.setEnabled(False) self.setWindowTitle(f"asammdf {libversion} [PID={os.getpid()}] - Batch processing") elif index == 2: self.plot_menu.setEnabled(True) self.setWindowTitle(f"asammdf {libversion} [PID={os.getpid()}] - Comparison") def keyPressEvent(self, event): key = event.key() modifier = event.modifiers() if key == QtCore.Qt.Key.Key_F and modifier == QtCore.Qt.KeyboardModifier.ControlModifier: if self.files.count() and self.stackedWidget.currentIndex() == 0: self.files.currentWidget().keyPressEvent(event) elif self.files.count() and self.stackedWidget.currentIndex() == 2: event.accept() measurements = [file.mdf for file in self.iter_files()] dlg = MultiSearch(measurements, parent=self) dlg.setModal(True) dlg.exec_() result = dlg.result if result: options = [ "New plot window", "New numeric window", ] + [mdi.windowTitle() for mdi in self.mdi_area.subWindowList()] if active_window := self.mdi_area.activeSubWindow(): default = active_window.windowTitle() else: default = None dialog = WindowSelectionDialog(options=options, default=default, parent=self) dialog.setModal(True) dialog.exec_() if dialog.result(): window_type = dialog.selected_type() disable_new_channels = dialog.disable_new_channels() names = [] for uuid, (group, ch_index), channel_name in sorted(result): names.append( { "name": channel_name, "origin_uuid": uuid, "type": "channel", "ranges": [], "group_index": group, "channel_index": ch_index, "uuid": os.urandom(6), "computed": False, "computation": {}, "precision": 3, "common_axis": False, "individual_axis": False, "enabled": not disable_new_channels, } ) if window_type == "New plot window": self.add_window(["Plot", names]) elif window_type == "New numeric window": self.add_window(["Numeric", names]) elif window_type == "New tabular window": self.add_window(["Tabular", names]) else: for mdi in self.mdi_area.subWindowList(): if mdi.windowTitle() == window_type: self.add_new_channels(names, mdi.widget()) break elif key == QtCore.Qt.Key.Key_F11: self.toggle_fullscreen() event.accept() elif key in (QtCore.Qt.Key.Key_F2, QtCore.Qt.Key.Key_F3, QtCore.Qt.Key.Key_F4): if self.files.count() and self.stackedWidget.currentIndex() == 0: if key == QtCore.Qt.Key.Key_F2: window_type = "Plot" elif key == QtCore.Qt.Key.Key_F3: window_type = "Numeric" elif key == QtCore.Qt.Key.Key_F4: window_type = "Tabular" self.files.currentWidget()._create_window(None, window_type) event.accept() else: super().keyPressEvent(event) def comparison_search(self, event): event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_F, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) def comparison_info(self, event): count = self.files.count() measurements = [f"{self.files.widget(i).uuid}:\t{self.files.widget(i).mdf.name}" for i in range(count)] MessageBox.information(self, "Measurement files used for comparison", "\n".join(measurements)) def toggle_fullscreen(self): if self.files.count() > 0 or self.fullscreen is not None: if self.fullscreen is None: index = self.files.currentIndex() widget = self.files.widget(index) if widget: widget.setParent(None) widget.showFullScreen() widget.autofit_sub_plots() self.fullscreen = widget, index else: widget, index = self.fullscreen file_name = str(Path(widget.mdf.name).name) self.files.insertTab(index, widget, file_name) self.files.setTabToolTip(index, str(widget.mdf.name)) self.files.setCurrentIndex(index) self.fullscreen = None self.activateWindow() widget.autofit_sub_plots() self.with_dots = widget.with_dots self._settings.setValue("dots", self.with_dots) count = self.files.count() for i in range(count): self.files.widget(i).set_line_style(with_dots=self.with_dots) def toggle_frames(self, event=None): count = self.files.count() for i in range(count): self.files.widget(i).toggle_frames() def toggle_channels_list(self, event=None): if self.stackedWidget.currentIndex() == 0: widget = self.files.currentWidget() event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_L, QtCore.Qt.KeyboardModifier.ShiftModifier ) if widget: widget.keyPressEvent(event) def open_configuration(self, event=None): if self.stackedWidget.currentIndex() == 0: widget = self.files.currentWidget() if widget: widget.load_channel_list() def save_configuration(self, event=None): if self.stackedWidget.currentIndex() == 0: widget = self.files.currentWidget() if widget: widget.save_channel_list() def functions_manager(self): if self.stackedWidget.currentIndex() == 0: file = self.files.currentWidget() if file: channels = {} mdf = file.mdf for name, entries in mdf.channels_db.items(): gp_index, ch_index = entries[0] comment = mdf.groups[gp_index].channels[ch_index].comment channels[name] = comment dlg = FunctionsManagerDialog( file.functions, channels, parent=self, global_variables=file.global_variables ) dlg.setModal(True) dlg.exec_() if dlg.pressed_button == "apply": original_definitions = dlg.original_definitions modified_definitions = dlg.modified_definitions if file.global_variables != dlg.global_variables: new_global_variables = dlg.global_variables else: new_global_variables = file.global_variables file.update_functions( original_definitions, modified_definitions, new_global_variables=new_global_variables ) def bus_database_manager(self): dlg = BusDatabaseManagerDialog(parent=self) dlg.setModal(True) dlg.exec_() if dlg.pressed_button == "apply": dlg.store() def show_about(self): bits = "x86" if sys.maxsize < 2**32 else "x64" cpython = ".".join(str(e) for e in sys.version_info[:3]) cpython = f"{cpython} {bits}" MessageBox.about( self, "About asammdf-gui", f"""Graphical user interface for the asammdf package * * * Build information: * version {libversion} * PySide6 {pyside6_version} * CPython {cpython} Copyright © 2018-2025 Daniel Hrisca""", markdown=True, ) asammdf-8.5.1/src/asammdf/gui/widgets/mdi_area.py000066400000000000000000005717461502633300400217210ustar00rootroot00000000000000from copy import deepcopy import datetime from functools import partial import inspect import itertools import os from pathlib import Path from random import randint import re import sys from tempfile import gettempdir from traceback import format_exc from zipfile import ZIP_DEFLATED, ZipFile from natsort import natsorted import numpy as np import pandas as pd from pyqtgraph import functions as fn from PySide6 import QtCore, QtGui, QtWidgets import asammdf.mdf as mdf_module from ...blocks import v4_constants as v4c from ...blocks.conversion_utils import from_dict from ...blocks.utils import csv_bytearray2hex, extract_xml_comment, load_can_database, MdfException, UniqueDB from ...blocks.v4_blocks import EventBlock, HeaderBlock from ...signal import Signal from .. import utils from ..dialogs.advanced_search import AdvancedSearch from ..dialogs.channel_info import ChannelInfoDialog from ..dialogs.messagebox import MessageBox from ..dialogs.window_selection_dialog import WindowSelectionDialog from ..serde import extract_mime_names from ..utils import ( computation_to_python_function, compute_signal, copy_ranges, generate_python_function_globals, replace_computation_dependency, ) from .can_bus_trace import CANBusTrace from .flexray_bus_trace import FlexRayBusTrace from .gps import GPS from .lin_bus_trace import LINBusTrace from .numeric import Numeric from .plot import Plot from .tabular import Tabular from .xy import XY COMPONENT = re.compile(r"\[(?P\d+)\]$") SIG_RE = re.compile(r"\{\{(?!\}\})(?P.*?)\}\}") NOT_FOUND = 0xFFFFFFFF SNAP_PIXELS_DISTANCE = 20 CASCADE_PIXELS_DISTANCE = SNAP_PIXELS_DISTANCE + 10 def deepcopy_cfg_item(item): if item.get("type", "channel") == "group": ranges = [ { "background_color": fn.mkColor(range_item["background_color"]), "font_color": fn.mkColor(range_item["font_color"]), "op1": range_item["op1"], "op2": range_item["op2"], "value1": range_item["value1"], "value2": range_item["value2"], } for range_item in item["ranges"] ] new_item = { "type": "group", "name": item["name"], "enabled": item["enabled"], "pattern": None, "ranges": ranges, "origin_uuid": item["origin_uuid"], "expanded": item["expanded"], "disabled": item["disabled"], "channels": deepcopy_cfg_item(item["channels"]), } if pattern := item["pattern"]: ranges = [ { "background_color": fn.mkColor(range_item["background_color"]), "font_color": fn.mkColor(range_item["font_color"]), "op1": range_item["op1"], "op2": range_item["op2"], "value1": range_item["value1"], "value2": range_item["value2"], } for range_item in pattern["ranges"] ] new_item["pattern"] = { "pattern": pattern["pattern"], "match_type": pattern["match_type"], "case_sensitive": pattern["case_sensitive"], "filter_type": pattern["filter_type"], "filter_value": pattern["filter_value"], "raw": pattern["raw"], "ranges": ranges, "name": pattern["name"], "integer_format": pattern["integer_format"], "y_range": deepcopy(pattern["pattern"]), } else: ranges = [ { "background_color": fn.mkColor(range_item["background_color"]), "font_color": fn.mkColor(range_item["font_color"]), "op1": range_item["op1"], "op2": range_item["op2"], "value1": range_item["value1"], "value2": range_item["value2"], } for range_item in item["ranges"] ] new_item = { "type": "channel", "name": item["name"], "unit": item.get("unit", ""), "flags": item.get("flags", 0), "enabled": item.get("enabled", True), "individual_axis": item.get("individual_axis", False), "common_axis": item.get("common_axis", False), "color": fn.mkColor(item["color"]), "computed": item.get("computed", False), "ranges": ranges, "precision": item.get("precision", 3), "fmt": item.get("fmt", "{}"), "format": item.get("format", "phys"), "mode": item.get("mode", "phys"), "y_range": deepcopy(item.get("y_range", [])), "origin_uuid": item["origin_uuid"], } for key in ("computation", "conversion", "user_defined_name", "individual_axis_width", "user_defined_unit"): if key in item: new_item[key] = deepcopy(item[key]) return new_item def rename_origin_uuid(items): for item in items: if item.get("type", "channel") == "channel": if "mdf_uuid" in item: item["origin_uuid"] = item["mdf_uuid"] del item["mdf_uuid"] else: return else: rename_origin_uuid(item["channels"]) def get_origin_uuid(item): # if item.get("type", "channel") == "group": # for subitem in item["channels"]: # if subitem.get("type", "channel") == "channel": # return subitem["origin_uuid"] # # for subitem in item["channels"]: # if subitem.get("type", "channel") == "group": # uuid = get_origin_uuid(subitem) # if uuid is not None: # return uuid # # return None # # else: # return item["origin_uuid"] return item["origin_uuid"] def build_mime_from_config( items, mdfs=None, computed_origin_uuid=None, default_index=NOT_FOUND, top=True, has_flags=None, ): if mdfs is None: mdfs = [None] elif not isinstance(mdfs, (tuple, list)): mdfs = [mdfs] if top: rename_origin_uuid(items) if not mdfs: computed_origin_uuid = os.urandom(6).hex() descriptions = {} found = {} not_found = {} computed = {} mime = [] for cfg_item in items: if cfg_item.get("type", "channel") == "group": uuid = os.urandom(6).hex() cfg_item["uuid"] = uuid if cfg_item.get("pattern", None) is None: ( new_mine, new_descriptions, new_found, new_not_found, new_computed, ) = build_mime_from_config( cfg_item["channels"], mdfs, computed_origin_uuid, default_index, top=False, has_flags=has_flags, ) descriptions.update(new_descriptions) found.update(new_found) not_found.update(new_not_found) computed.update(new_computed) cfg_item["channels"] = new_mine mime.append(cfg_item) else: mime.append(cfg_item) else: for mdf in mdfs: if mdf is None: origin_uuid = computed_origin_uuid else: origin_uuid = mdf.uuid uuid = os.urandom(6).hex() item = deepcopy_cfg_item(cfg_item) item["uuid"] = uuid item["origin_uuid"] = origin_uuid descriptions[uuid] = item if has_flags is None: has_flags = "flags" in item if has_flags: # item["flags"] = Signal.Flags(item["flags"]) item_is_computed = item["flags"] & Signal.Flags.computed else: item_is_computed = item.get("computed", False) flags = Signal.Flags.no_flags if "comment" in item: flags |= Signal.Flags.user_defined_comment if "conversion" in item: flags |= Signal.Flags.user_defined_conversion if "user_defined_name" in item: flags |= Signal.Flags.user_defined_name if item_is_computed: flags |= Signal.Flags.computed item["flags"] = flags if item_is_computed: group_index, channel_index = -1, -1 computed[uuid] = item item["computation"] = computation_to_python_function(item["computation"]) item["computation"].pop("definition", None) item["origin_uuid"] = origin_uuid else: occurrences = mdf.whereis(item["name"]) if mdf else None if occurrences: group_index, channel_index = occurrences[0] found[uuid] = item else: group_index, channel_index = default_index, default_index not_found[uuid] = item item["group_index"] = group_index item["channel_index"] = channel_index mime.append(item) return mime, descriptions, found, not_found, computed def extract_signals_using_pattern( mdf, channels_db, pattern_info, ignore_value2text_conversions, uuid=None, as_names=False ): if not mdf and not channels_db: if as_names: return set() else: return {} elif not channels_db: channels_db = mdf.channels_db origin_uuid = getattr(mdf, "uuid", os.urandom(6).hex()) if mdf is not None: origin_mdf = mdf.original_name.name pattern = pattern_info["pattern"] match_type = pattern_info["match_type"] case_sensitive = pattern_info.get("case_sensitive", False) filter_value = pattern_info["filter_value"] filter_type = pattern_info["filter_type"] raw = pattern_info["raw"] integer_format = pattern_info.get("integer_format", "phys") pattern_ranges = pattern_info["ranges"] if match_type == "Wildcard": wild = f"__{os.urandom(3).hex()}WILDCARD{os.urandom(3).hex()}__" pattern = pattern.replace("*", wild) pattern = re.escape(pattern) pattern = pattern.replace(wild, ".*") try: if case_sensitive: pattern = re.compile(pattern) else: pattern = re.compile(f"(?i){pattern}") matches = set() for name, entries in channels_db.items(): if pattern.fullmatch(name): for entry in entries: if entry in matches: continue matches.add((name, *entry)) matches = natsorted(matches) except: print(format_exc()) signals = [] else: if (as_names and filter_type == "Unspecified") or not mdf: return {match[0] for match in matches} psignals = mdf.select( matches, ignore_value2text_conversions=ignore_value2text_conversions, copy_master=False, validate=True, raw=True, ) if filter_type == "Unspecified": keep = psignals else: keep = [] for i, (name, group_index, channel_index) in enumerate(matches): sig = psignals[i] sig.origin_uuid = uuid sig.group_index, sig.channel_index = group_index, channel_index size = len(sig) if not size: continue target = np.full(size, filter_value) if not raw: samples = sig.physical(copy=False).samples else: samples = sig.samples if filter_type == "Contains": try: if np.any(np.isclose(samples, target)): keep.append(sig) except: continue elif filter_type == "Do not contain": try: if not np.allclose(samples, target): keep.append(sig) except: continue else: try: if np.allclose(samples, target): keep.append(sig) except: continue signals = keep output_signals = {} for sig in signals: uuid = os.urandom(6).hex() sig.uuid = uuid sig.format = integer_format sig.ranges = copy_ranges(pattern_ranges) output_signals[uuid] = sig sig.origin_uuid = origin_uuid if mdf is not None: sig.origin_mdf = origin_mdf sig.enable = True if as_names: return {sig.name for sig in signals} else: return output_signals def generate_window_title(mdi, window_name="", title=""): used_names = {window.windowTitle() for window in mdi.mdiArea().subWindowList() if window is not mdi} if not title or title in used_names: window_name = title or window_name or "Subwindow" i = 0 while True: name = f"{window_name} {i}" if name in used_names: i += 1 else: break else: name = title return name def get_descriptions_by_name(channels): descriptions = {} for channel in channels: if channel.get("type", "channel") == "group": new_descriptions = get_descriptions_by_name(channel["channels"]) descriptions.update(new_descriptions) else: descriptions[channel["name"]] = channel return descriptions def get_flatten_entries_from_mime(data, default_index=None): entries = [] for item in data: if item.get("type", "channel") == "channel": new_item = dict(item) if default_index is not None: new_item["group_index"] = default_index new_item["channel_index"] = default_index entries.append(new_item) else: entries.extend(get_flatten_entries_from_mime(item["channels"], default_index)) return entries def get_functions(data): functions = {} for item in data: if item.get("type", "channel") == "group": functions.update(get_functions(item["channels"])) else: if item.get("computed", False): computation = item["computation"] = computation_to_python_function(item["computation"]) functions[computation["function"]] = computation["definition"] return functions def get_pattern_groups(data): groups = [] for item in data: if item.get("type", "channel") == "group": if item["pattern"] is not None: groups.append(item) else: groups.extend(get_pattern_groups(item["channels"])) return groups def get_required_from_computed(channel): names = [] if "computed" in channel: if channel["computed"]: computation = channel["computation"] if computation["type"] == "arithmetic": for op in ( computation["operand1"], computation["operand2"], ): if isinstance(op, str): names.append(op) elif isinstance(op, (int, float)): pass else: names.extend(get_required_from_computed(op)) elif computation["type"] == "function": op = computation["channel"] if isinstance(op, str): names.append(op) else: names.extend(get_required_from_computed(op)) elif computation["type"] == "expression": expression_string = computation["expression"] names.extend([match.group("name") for match in SIG_RE.finditer(expression_string)]) elif computation["type"] == "python_function": for alternative_names in computation["args"].values(): for name in alternative_names: if name: names.append(name) triggering = computation.get("triggering", "triggering_on_all") if triggering == "triggering_on_channel": triggering_channel = computation["triggering_value"] if triggering_channel: names.append(triggering_channel) else: names.append(channel["name"]) else: if channel["type"] == "arithmetic": for op in (channel["operand1"], channel["operand2"]): if isinstance(op, str): names.append(op) elif isinstance(op, (int, float)): pass else: names.extend(get_required_from_computed(op)) elif channel["type"] == "expression": expression_string = channel["expression"] names.extend([match.group("name") for match in SIG_RE.finditer(expression_string)]) elif channel["type"] == "function": op = channel["channel"] if isinstance(op, str): names.append(op) else: names.extend(get_required_from_computed(op)) elif channel["type"] == "python_function": for alternative_names in channel["args"].values(): for name in alternative_names: if name: names.append(name) return names def substitude_mime_uuids(mime, uuid=None, force=False): if not mime: return mime new_mime = [] for item in mime: if item.get("type", "channel") == "channel": if force or item["origin_uuid"] is None: item["origin_uuid"] = uuid new_mime.append(item) else: item["channels"] = substitude_mime_uuids(item["channels"], uuid, force=force) if force or item["origin_uuid"] is None: item["origin_uuid"] = uuid new_mime.append(item) return new_mime def parse_matrix_component(name): indexes = [] while True: match = COMPONENT.search(name) if match: name = name[: match.start()] indexes.insert(0, int(match.group("index"))) else: break return name, tuple(indexes) class MdiAreaMixin: def addSubWindow(self, window): geometry = window.geometry() geometry.setSize(QtCore.QSize(400, 400)) window.setGeometry(geometry) window.resized.connect(self.window_resized) window.moved.connect(self.window_moved) return super().addSubWindow(window) def clear_windows(self): for window in self.subWindowList(): widget = window.widget() self.removeSubWindow(window) widget.setParent(None) window.close() widget.deleteLater() widget.close() def window_moved(self, window, new_position, old_position): snap = False window_geometry = window.geometry() area_geometry = self.geometry() sub_windows = [sub.geometry() for sub in self.subWindowList() if sub is not window] # left edge snapping snap_candidates = [ 0, ] for sub in sub_windows: snap_candidates.append(sub.x()) snap_candidates.append(sub.x() + sub.width()) for x in snap_candidates: if abs(new_position.x() - x) <= SNAP_PIXELS_DISTANCE: new_position.setX(x) snap = True break else: # right edge snapping snap_candidates = [ area_geometry.width(), ] for sub in sub_windows: snap_candidates.append(sub.x()) snap_candidates.append(sub.x() + sub.width()) for x in snap_candidates: if abs(new_position.x() + window_geometry.width() - x) <= SNAP_PIXELS_DISTANCE: new_position.setX(x - window_geometry.width()) snap = True break # top edge snapping snap_candidates = [ 0, ] for sub in sub_windows: snap_candidates.append(sub.y()) snap_candidates.append(sub.y() + sub.height()) for y in snap_candidates: if abs(new_position.y() - y) <= SNAP_PIXELS_DISTANCE: new_position.setY(y) snap = True break else: # bottom edge snapping snap_candidates = [ area_geometry.height(), ] for sub in sub_windows: if sub is not window: snap_candidates.append(sub.y()) snap_candidates.append(sub.y() + sub.height()) for y in snap_candidates: if abs(new_position.y() + window_geometry.height() - y) <= SNAP_PIXELS_DISTANCE: new_position.setY(y - window_geometry.height()) snap = True break if snap: window.blockSignals(True) window_geometry.moveTo(new_position) window.setGeometry(window_geometry) window.blockSignals(False) window.previous_position = old_position def window_resized(self, window, new_size, old_size): snap = False window_geometry = new_geometry = window.geometry() new_position = window_geometry.topLeft() area_geometry = self.geometry() sub_windows = [sub for sub in self.subWindowList() if sub is not window] for sub in sub_windows: sub.blockSignals(True) previous_position = window.previous_position previous_geometry = QtCore.QRect(0, 0, 0, 0) previous_geometry.moveTo(previous_position) previous_geometry.setSize(old_size) # right edge of other windows growing and snapping snap_candidates = [ area_geometry.width(), ] for sub in sub_windows: if sub is not window: snap_candidates.append(sub.geometry().x() + sub.geometry().width()) for x in snap_candidates: if abs(new_position.x() + window_geometry.width() - x) <= SNAP_PIXELS_DISTANCE: window_geometry.setWidth(abs(x - new_position.x())) snap = True break else: # left edge of other windows growing and snapping snap_candidates = [] for sub in sub_windows: if sub is not window: snap_candidates.append(sub.geometry().x()) for x in snap_candidates: if abs(new_position.x() + window_geometry.width() - x) <= SNAP_PIXELS_DISTANCE: window_geometry.setWidth(abs(x - new_position.x())) snap = True break # bottom edge of other windows snapping snap_candidates = [ area_geometry.height(), ] for sub in sub_windows: if sub is not window: snap_candidates.append(sub.geometry().y() + sub.geometry().height()) for y in snap_candidates: if abs(new_position.y() + window_geometry.height() - y) <= SNAP_PIXELS_DISTANCE: window_geometry.setHeight(abs(y - new_position.y())) snap = True break else: # top edge of other windows snapping snap_candidates = [] for sub in sub_windows: if sub is not window: snap_candidates.append(sub.geometry().y()) for y in snap_candidates: if abs(new_position.y() + window_geometry.height() - y) <= SNAP_PIXELS_DISTANCE: window_geometry.setHeight(abs(y - new_position.y())) snap = True break if snap: window.blockSignals(True) window.setGeometry(window_geometry) window.blockSignals(False) new_size = window_geometry.size() new_geometry = window_geometry # manage edge driven resize of other windows x_delta = new_size.width() - old_size.width() y_delta = new_size.height() - old_size.height() previous_x = None previous_y = None # top left corner unchanged if new_geometry.topLeft() == previous_geometry.topLeft(): if x_delta: # right edge was dragged previous_x = previous_geometry.x() + old_size.width() if y_delta: # bottom edge was dragged previous_y = previous_geometry.y() + old_size.height() # top right corner unchanged elif new_geometry.topRight() == previous_geometry.topRight(): if x_delta: # left edge was dragged previous_x = previous_geometry.x() x_delta = -x_delta if y_delta: # bottom edge was dragged previous_y = previous_geometry.y() + old_size.height() # bottom left corner unchanged elif new_geometry.bottomLeft() == previous_geometry.bottomLeft(): if x_delta: # right edge was dragged previous_x = previous_geometry.x() + old_size.width() if y_delta: # top edge was dragged previous_y = previous_geometry.y() y_delta = -y_delta # bottom right corner unchanged elif new_geometry.bottomRight() == previous_geometry.bottomRight(): if x_delta: # left edge was dragged previous_x = previous_geometry.x() x_delta = -x_delta if y_delta: # top edge was dragged previous_y = previous_geometry.y() y_delta = -y_delta if previous_x is not None: for sub in sub_windows: geometry = sub.geometry() if abs(geometry.x() - previous_x) <= SNAP_PIXELS_DISTANCE: geometry.setX(geometry.x() + x_delta) sub.setGeometry(geometry) elif abs(geometry.x() + geometry.width() - previous_x) <= SNAP_PIXELS_DISTANCE: geometry.setWidth(geometry.width() + x_delta) sub.setGeometry(geometry) if previous_y is not None: for sub in sub_windows: geometry = sub.geometry() if abs(geometry.y() - previous_y) <= SNAP_PIXELS_DISTANCE: geometry.setY(geometry.y() + y_delta) sub.setGeometry(geometry) elif abs(geometry.y() + geometry.height() - previous_y) <= SNAP_PIXELS_DISTANCE: geometry.setHeight(geometry.height() + y_delta) sub.setGeometry(geometry) for sub in sub_windows: sub.blockSignals(False) class MdiSubWindow(QtWidgets.QMdiSubWindow): sigClosed = QtCore.Signal(object) titleModified = QtCore.Signal() resized = QtCore.Signal(object, object, object) moved = QtCore.Signal(object, object, object) pattern_modified = QtCore.Signal(object, object) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) layout = self.layout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) self.setOption(MdiSubWindow.RubberBandResize) self.setOption(MdiSubWindow.RubberBandMove) self.previous_position = QtCore.QPoint(0, 0) menu = self.systemMenu() before = menu.actions()[0] action = QtGui.QAction("Set title", menu) action.triggered.connect(self.set_title) menu.insertAction(before, action) action = QtGui.QAction("Edit window pattern", menu) action.triggered.connect(self.edit_window_pattern) menu.insertAction(before, action) def closeEvent(self, event): if isinstance(self.widget(), Plot): self.widget().close() super().closeEvent(event) self.sigClosed.emit(self) def edit_window_pattern(self): widget = self.widget() if not (pattern := getattr(widget, "pattern", None)): MessageBox.information( self, "Cannot edit window pattern", f"{self.windowTitle()} is not a pattern based window", ) else: if hasattr(widget.owner, "mdf"): mdf = widget.owner.mdf channels_db = None else: mdf = None channels_db = widget.owner.channels_db dlg = AdvancedSearch( mdf=mdf, show_add_window=False, show_apply=True, show_search=False, window_title="Show pattern based group", parent=self, pattern=pattern, channels_db=channels_db, ) dlg.setModal(True) dlg.exec_() if new_pattern := dlg.result: del dlg self.pattern_modified.emit(new_pattern, id(self)) def moveEvent(self, event): old_position = event.oldPos() new_position = event.pos() # old_position == new_position => restore from minimized or maximized super().moveEvent(event) if not (self.isMinimized() or self.isMaximized()): self.moved.emit(self, new_position, old_position) def resizeEvent(self, event): old_size = event.oldSize() new_size = event.size() super().resizeEvent(event) if old_size.isValid() and not (self.isMinimized() or self.isMaximized()): self.resized.emit(self, new_size, old_size) def set_title(self): name, ok = QtWidgets.QInputDialog.getText( self, "Set sub-plot title", "Title:", text=self.windowTitle(), ) if ok and name: self.setWindowTitle(generate_window_title(self, title=name)) self.titleModified.emit() class MdiAreaWidget(MdiAreaMixin, QtWidgets.QMdiArea): add_window_request = QtCore.Signal(list) create_window_request = QtCore.Signal() open_files_request = QtCore.Signal(object) search_request = QtCore.Signal() def __init__(self, comparison=False, *args, **kwargs): super().__init__(*args, **kwargs) self.setAcceptDrops(True) self.comparison = comparison self.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.open_menu) self.show() def cascadeSubWindows(self): sub_windows = self.subWindowList() if not sub_windows: return for window in sub_windows: wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = True window.blockSignals(True) position = QtCore.QPoint(0, 0) rect = QtCore.QRect(0, 0, 400, 300) for i, window in enumerate(sub_windows, 1): rect.moveTo(position) window.setGeometry(rect) position.setX(position.x() + CASCADE_PIXELS_DISTANCE) position.setY(position.y() + CASCADE_PIXELS_DISTANCE) if i % 5 == 0: position.setY(0) for window in sub_windows: wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = False window.blockSignals(False) def dragEnterEvent(self, e): e.accept() super().dragEnterEvent(e) def dropEvent(self, event): if event.source() is self: super().dropEvent(event) else: data = event.mimeData() if data.hasFormat("application/octet-stream-asammdf"): dialog = WindowSelectionDialog( options=("Plot", "Numeric") if self.comparison else ("Plot", "Numeric", "Tabular"), parent=self ) dialog.setModal(True) dialog.exec_() if dialog.result(): window_type = dialog.selected_type() disable_new_channels = dialog.disable_new_channels() names = extract_mime_names(data, disable_new_channels=disable_new_channels) self.add_window_request.emit([window_type, names]) event.accept() else: try: files = [] for url in event.mimeData().urls(): if sys.platform == "win32": path = Path(url.path().strip("/")) else: path = Path(url.path()) if ( path.suffix.lower() in utils.SUPPORTED_FILE_EXTENSIONS | utils.SUPPORTED_BUS_DATABASE_EXTENSIONS ): files.append(str(path)) if files: self.open_files_request.emit(files) event.accept() else: event.ignore() except: print(format_exc()) event.ignore() def open_menu(self, position=None): viewport = self.viewport() if not self.childAt(position) is viewport: return self.context_menu = menu = QtWidgets.QMenu() menu.addAction(f"{len(self.subWindowList())} existing windows") menu.addSeparator() action = QtGui.QAction(QtGui.QIcon(":/search.png"), "Search", menu) action.setShortcut(QtGui.QKeySequence("Ctrl+F")) menu.addAction(action) menu.addSeparator() menu.addAction(QtGui.QIcon(":/plus.png"), "Add new window") menu.addSeparator() action = QtGui.QAction("Cascade sub-windows", menu) action.setShortcut(QtGui.QKeySequence("Shift+C")) menu.addAction(action) action = QtGui.QAction("Tile sub-windows in a grid", menu) action.setShortcut(QtGui.QKeySequence("Shift+T")) menu.addAction(action) action = QtGui.QAction("Tile sub-windows vertically", menu) action.setShortcut(QtGui.QKeySequence("Shift+V")) menu.addAction(action) action = QtGui.QAction("Tile sub-windows horizontally", menu) action.setShortcut(QtGui.QKeySequence("Shift+H")) menu.addAction(action) action = menu.exec(viewport.mapToGlobal(position)) if action is None: return action_text = action.text() match action_text: case "Search": self.search_request.emit() case "Add new window": self.create_window_request.emit() case "Cascade sub-windows": self.cascadeSubWindows() case "Tile sub-windows in a grid": self.tileSubWindows() case "Tile sub-windows vertically": self.tile_vertically() case "Tile sub-windows horizontally": self.tile_horizontally() case _: pass def tile_horizontally(self): sub_windows = self.subWindowList() if not sub_windows: return position = QtCore.QPoint(0, 0) width = self.width() height = self.height() ratio = height // len(sub_windows) for window in sub_windows: wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = True window.blockSignals(True) for window in sub_windows: if window.isMinimized() or window.isMaximized(): window.showNormal() rect = QtCore.QRect(0, 0, width, ratio) rect.moveTo(position) window.setGeometry(rect) position.setY(position.y() + ratio) for window in sub_windows: wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = False window.blockSignals(False) def tile_vertically(self): sub_windows = self.subWindowList() if not sub_windows: return position = QtCore.QPoint(0, 0) width = self.width() height = self.height() ratio = width // len(sub_windows) for window in sub_windows: wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = True window.blockSignals(True) for window in sub_windows: if window.isMinimized() or window.isMaximized(): window.showNormal() rect = QtCore.QRect(0, 0, ratio, height) rect.moveTo(position) window.setGeometry(rect) position.setX(position.x() + ratio) for window in sub_windows: wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = False window.blockSignals(False) def tileSubWindows(self): sub_windows = self.subWindowList() if not sub_windows: return for window in sub_windows: wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = True window.blockSignals(True) super().tileSubWindows() for window in sub_windows: wid = window.widget() if isinstance(wid, Plot): wid._inhibit_x_range_changed_signal = False window.blockSignals(False) class WithMDIArea: windows_modified = QtCore.Signal() load_plot_x_range = False def __init__(self, comparison=False, *args, **kwargs): self.comparison = comparison self._cursor_source = None self._region_source = None self._splitter_source = None self._window_counter = 0 self._frameless_windows = False self.cursor_circle = True self.cursor_horizontal_line = True self.cursor_line_width = 1 self.cursor_color = "#e69138" self._busy = False self.functions = {} self.global_variables = "" def add_pattern_group(self, plot, group): signals = extract_signals_using_pattern( mdf=self.mdf, channels_db=None, pattern_info=group.pattern, ignore_value2text_conversions=self.ignore_value2text_conversions, uuid=self.uuid, ) signals = { sig_uuid: sig for sig_uuid, sig in signals.items() if sig.samples.dtype.kind not in "SU" and not sig.samples.dtype.names and not len(sig.samples.shape) > 1 } group.count = len(signals) if signals: plot.add_new_channels( signals, mime_data=None, destination=group, ) def add_new_channels(self, names, widget, mime_data=None): if isinstance(widget, Plot): ignore_value2text_conversions = False current_count = len(widget.plot.signals) count = len(names) elif isinstance(widget, XY): if names: name = names[0] else: dlg = AdvancedSearch( self.mdf, show_add_window=False, show_apply=True, show_pattern=False, apply_text="Apply", parent=self, ) dlg.setModal(True) dlg.exec_() result, pattern_window = dlg.result, dlg.pattern_window if result: name = list(result.values())[0] else: name = "" entries = self.mdf.whereis(name) if entries: entry = entries[0] channels = self.mdf.select( [(name, *entry)], raw=False, ignore_value2text_conversions=True, validate=True, ) widget.add_new_channels(channels) else: widget.add_new_channels([None]) return else: ignore_value2text_conversions = self.ignore_value2text_conversions try: names = list(names) if names and isinstance(names[0], str): signals_ = [ { "name": name, "group_index": self.mdf.whereis(name)[0][0], "channel_index": self.mdf.whereis(name)[0][1], "origin_uuid": self.uuid, "type": "channel", "ranges": [], "uuid": os.urandom(6).hex(), } for name in names if name in self.mdf ] uuids = {self.uuid} mime_data = signals_ computed = [] else: mime_data = names try: mime_data = substitude_mime_uuids(mime_data, self.uuid) except: pass entries = get_flatten_entries_from_mime(mime_data) uuids = {entry["origin_uuid"] for entry in entries} for uuid in uuids: if self.file_by_uuid(uuid): break else: mime_data = substitude_mime_uuids(mime_data, uuid=self.uuid, force=True) entries = get_flatten_entries_from_mime(mime_data) signals_ = [entry for entry in entries if (entry["group_index"], entry["channel_index"]) != (-1, -1)] computed = [entry for entry in entries if (entry["group_index"], entry["channel_index"]) == (-1, -1)] uuids = {entry["origin_uuid"] for entry in entries} if isinstance(widget, Tabular): dfs = [] for uuid in uuids: uuids_signals = [ (entry["name"], entry["group_index"], entry["channel_index"]) for entry in signals_ if entry["origin_uuid"] == uuid ] file_info = self.file_by_uuid(uuid) if not file_info: continue file_index, file = file_info selected_signals = file.mdf.to_dataframe( channels=uuids_signals, ignore_value2text_conversions=self.ignore_value2text_conversions, time_from_zero=False, use_interpolation=QtCore.QSettings().value("tabular_interpolation", True, type=bool), ) dfs.append(selected_signals) signals = pd.concat(dfs, axis=1) for name in signals.columns: if name.endswith(".ID"): signals[name] = signals[name].astype(" 1: signal.samples = csv_bytearray2hex(pd.Series(list(signal.samples))) if signal.name.endswith(".ID"): signal.samples = signal.samples.astype(" 1 ): nd.append(sig) else: signals[sig.uuid] = sig for sig in nd: if sig.samples.dtype.names is None: shape = sig.samples.shape[1:] matrix_dims = [list(range(dim)) for dim in shape] matrix_name = sig.name for indexes in itertools.product(*matrix_dims): indexes_string = "".join(f"[{_index}]" for _index in indexes) samples = sig.samples for idx in indexes: samples = samples[:, idx] sig_name = f"{matrix_name}{indexes_string}" new_sig = sig.copy() new_sig.name = sig_name new_sig.samples = samples new_sig.group_index = sig.group_index new_sig.channel_index = sig.channel_index new_sig.flags &= ~sig.Flags.computed new_sig.computation = {} new_sig.origin_uuid = sig.origin_uuid new_sig.uuid = os.urandom(6).hex() new_sig.enable = getattr(sig, "enable", True) signals[new_sig.uuid] = new_sig else: name = sig.samples.dtype.names[0] if name == sig.name: array_samples = sig.samples[name] shape = array_samples.shape[1:] matrix_dims = [list(range(dim)) for dim in shape] matrix_name = sig.name for indexes in itertools.product(*matrix_dims): indexes_string = "".join(f"[{_index}]" for _index in indexes) samples = array_samples for idx in indexes: samples = samples[:, idx] sig_name = f"{matrix_name}{indexes_string}" new_sig = sig.copy() new_sig.name = sig_name new_sig.samples = samples new_sig.group_index = sig.group_index new_sig.channel_index = sig.channel_index new_sig.flags &= ~sig.Flags.computed new_sig.computation = {} new_sig.origin_uuid = sig.origin_uuid new_sig.uuid = os.urandom(6).hex() new_sig.enable = getattr(sig, "enable", True) signals[new_sig.uuid] = new_sig signals = { key: sig for key, sig in signals.items() if sig.samples.dtype.kind not in "SU" and not sig.samples.dtype.names and not len(sig.samples.shape) > 1 } for signal in signals.values(): if len(signal.samples.shape) > 1: signal.samples = csv_bytearray2hex(pd.Series(list(signal.samples))) if signal.name.endswith(".ID"): signal.samples = signal.samples.astype("= "4.00": groups_count = len(self.mdf.groups) for index in range(groups_count): group = self.mdf.groups[index] if group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT: source = group.channel_group.acq_source names = [ch.name for ch in group.channels] if source and source.bus_type == v4c.BUS_TYPE_CAN: if "CAN_DataFrame" in names: data = self.mdf.get("CAN_DataFrame", index) # , raw=True) elif "CAN_RemoteFrame" in names: data = self.mdf.get("CAN_RemoteFrame", index, raw=True) elif "CAN_ErrorFrame" in names: data = self.mdf.get("CAN_ErrorFrame", index, raw=True) else: continue df_index = data.timestamps count = len(df_index) columns = { "timestamps": df_index, "Bus": np.full(count, "Unknown", dtype="O"), "ID": np.full(count, 0xFFFFFFFF, dtype="u4"), "IDE": np.zeros(count, dtype="u1"), "Direction": np.full(count, "", dtype="O"), "Name": np.full(count, "", dtype="O"), "Event Type": np.full(count, "CAN Frame", dtype="O"), "Details": np.full(count, "", dtype="O"), "ESI": np.full(count, "", dtype="O"), "EDL": np.full(count, "Standard CAN", dtype="O"), "BRS": np.full(count, "", dtype="O"), "DLC": np.zeros(count, dtype="u1"), "Data Length": np.zeros(count, dtype="u1"), "Data Bytes": np.full(count, "", dtype="O"), } for string in v4c.CAN_ERROR_TYPES.values(): sys.intern(string) frame_map = None if data.attachment and data.attachment[0]: dbc = load_can_database(data.attachment[1], data.attachment[0]) if dbc: frame_map = {frame.arbitration_id.id: frame.name for frame in dbc} for name in frame_map.values(): sys.intern(name) if data.name == "CAN_DataFrame": vals = data["CAN_DataFrame.BusChannel"].astype("u1") vals = [f"CAN {chn}" for chn in vals.tolist()] columns["Bus"] = vals vals = data["CAN_DataFrame.ID"].astype("u4") & 0x1FFFFFFF columns["ID"] = vals if frame_map: columns["Name"] = [frame_map.get(_id, "") for _id in vals.tolist()] if "CAN_DataFrame.IDE" in names: columns["IDE"] = data["CAN_DataFrame.IDE"].astype("u1") columns["DLC"] = data["CAN_DataFrame.DLC"].astype("u1") data_length = data["CAN_DataFrame.DataLength"].astype("u1") columns["Data Length"] = data_length vals = csv_bytearray2hex( pd.Series(list(data["CAN_DataFrame.DataBytes"])), data_length.tolist(), ) columns["Data Bytes"] = vals if "CAN_DataFrame.Dir" in names: if data["CAN_DataFrame.Dir"].dtype.kind == "S": columns["Direction"] = [ v.decode("utf-8") for v in data["CAN_DataFrame.Dir"].tolist() ] else: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["CAN_DataFrame.Dir"].astype("u1").tolist() ] if "CAN_DataFrame.ESI" in names: columns["ESI"] = [ "Error" if dir else "No error" for dir in data["CAN_DataFrame.ESI"].astype("u1").tolist() ] if "CAN_DataFrame.EDL" in names: columns["EDL"] = [ "CAN FD" if dir else "Standard CAN" for dir in data["CAN_DataFrame.EDL"].astype("u1").tolist() ] if "CAN_DataFrame.BRS" in names: columns["BRS"] = [str(dir) for dir in data["CAN_DataFrame.BRS"].astype("u1").tolist()] vals = None data_length = None elif data.name == "CAN_RemoteFrame": vals = data["CAN_RemoteFrame.BusChannel"].astype("u1") vals = [f"CAN {chn}" for chn in vals.tolist()] columns["Bus"] = vals vals = data["CAN_RemoteFrame.ID"].astype("u4") & 0x1FFFFFFF columns["ID"] = vals if frame_map: columns["Name"] = [frame_map.get(_id, "") for _id in vals.tolist()] if "CAN_RemoteFrame.IDE" in names: columns["IDE"] = data["CAN_RemoteFrame.IDE"].astype("u1") columns["DLC"] = data["CAN_RemoteFrame.DLC"].astype("u1") data_length = data["CAN_RemoteFrame.DataLength"].astype("u1") columns["Data Length"] = data_length columns["Event Type"] = "Remote Frame" if "CAN_RemoteFrame.Dir" in names: if data["CAN_RemoteFrame.Dir"].dtype.kind == "S": columns["Direction"] = [ v.decode("utf-8") for v in data["CAN_RemoteFrame.Dir"].tolist() ] else: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["CAN_RemoteFrame.Dir"].astype("u1").tolist() ] vals = None data_length = None elif data.name == "CAN_ErrorFrame": names = set(data.samples.dtype.names) if "CAN_ErrorFrame.BusChannel" in names: vals = data["CAN_ErrorFrame.BusChannel"].astype("u1") vals = [f"CAN {chn}" for chn in vals.tolist()] columns["Bus"] = vals if "CAN_ErrorFrame.ID" in names: vals = data["CAN_ErrorFrame.ID"].astype("u4") & 0x1FFFFFFF columns["ID"] = vals if frame_map: columns["Name"] = [frame_map.get(_id, "") for _id in vals.tolist()] if "CAN_ErrorFrame.IDE" in names: columns["IDE"] = data["CAN_ErrorFrame.IDE"].astype("u1") if "CAN_ErrorFrame.DLC" in names: columns["DLC"] = data["CAN_ErrorFrame.DLC"].astype("u1") if "CAN_ErrorFrame.DataLength" in names: columns["Data Length"] = data["CAN_ErrorFrame.DataLength"].astype("u1") columns["Event Type"] = "Error Frame" if "CAN_ErrorFrame.ErrorType" in names: vals = data["CAN_ErrorFrame.ErrorType"].astype("u1").tolist() vals = [v4c.CAN_ERROR_TYPES.get(err, "Other error") for err in vals] columns["Details"] = vals if "CAN_ErrorFrame.Dir" in names: if data["CAN_ErrorFrame.Dir"].dtype.kind == "S": columns["Direction"] = [ v.decode("utf-8") for v in data["CAN_ErrorFrame.Dir"].tolist() ] else: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["CAN_ErrorFrame.Dir"].astype("u1").tolist() ] df = pd.DataFrame(columns, index=df_index) dfs.append(df) if not dfs: df_index = [] count = 0 columns = { "timestamps": df_index, "Bus": np.full(count, "Unknown", dtype="O"), "ID": np.full(count, 0xFFFFFFFF, dtype="u4"), "IDE": np.zeros(count, dtype="u1"), "Direction": np.full(count, "", dtype="O"), "Name": np.full(count, "", dtype="O"), "Event Type": np.full(count, "CAN Frame", dtype="O"), "Details": np.full(count, "", dtype="O"), "ESI": np.full(count, "", dtype="O"), "EDL": np.full(count, "Standard CAN", dtype="O"), "BRS": np.full(count, "", dtype="O"), "DLC": np.zeros(count, dtype="u1"), "Data Length": np.zeros(count, dtype="u1"), "Data Bytes": np.full(count, "", dtype="O"), } signals = pd.DataFrame(columns, index=df_index) else: signals = pd.concat(dfs).sort_index() index = pd.Index(range(len(signals))) signals.set_index(index, inplace=True) del dfs trace = CANBusTrace(signals, start=self.mdf.header.start_time, ranges=ranges) sub = MdiSubWindow(parent=self) sub.setWidget(trace) trace.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.sigClosed.connect(self.window_closed_handler) sub.titleModified.connect(self.window_closed_handler) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/bus_can.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) sub.setWindowIcon(icon) if not self.subplots: for mdi in self.mdi_area.subWindowList(): mdi.close() w = self.mdi_area.addSubWindow(sub) w.showMaximized() else: w = self.mdi_area.addSubWindow(sub) if len(self.mdi_area.subWindowList()) == 1: w.showMaximized() else: w.show() if self._frameless_windows: w.setWindowFlags(w.windowFlags() | QtCore.Qt.WindowType.FramelessWindowHint) w.setWindowTitle(f"CAN Bus Trace {self._window_counter}") self._window_counter += 1 if self.subplots_link: trace.timestamp_changed_signal.connect(self.set_cursor) self.windows_modified.emit() trace.tree.auto_size_header() return trace def _add_flexray_bus_trace_window(self, ranges=None): items = [] if self.mdf.version >= "4.00": groups_count = len(self.mdf.groups) for index in range(groups_count): group = self.mdf.groups[index] if group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT: source = group.channel_group.acq_source names = [ch.name for ch in group.channels] if source and source.bus_type == v4c.BUS_TYPE_FLEXRAY: if "FLX_Frame" in names: data = self.mdf.get("FLX_Frame", index, raw=True) items.append((data, names)) elif "FLX_NullFrame" in names: data = self.mdf.get("FLX_NullFrame", index, raw=True) items.append((data, names)) elif "FLX_StartCycle" in names: data = self.mdf.get("FLX_StartCycle", index, raw=True) items.append((data, names)) elif "FLX_Status" in names: data = self.mdf.get("FLX_Status", index, raw=True) items.append((data, names)) if items: df_index = np.sort(np.concatenate([item.timestamps for (item, names) in items])) count = len(df_index) columns = { "timestamps": df_index, "Bus": np.full(count, "", dtype="O"), "Channel": np.full(count, "", dtype="O"), "ID": np.full(count, 0xFFFF, dtype="u2"), "Direction": np.full(count, "", dtype="O"), "Cycle": np.full(count, 0xFF, dtype="u1"), "Name": np.full(count, "", dtype="O"), "Event Type": np.full(count, "FlexRay Frame", dtype="O"), "Details": np.full(count, "", dtype="O"), "Data Length": np.zeros(count, dtype="u1"), "Data Bytes": np.full(count, "", dtype="O"), "Header CRC": np.full(count, 0xFFFF, dtype="u2"), } count = len(items) # TO DO: add flexray error types # for string in v4c.CAN_ERROR_TYPES.values(): # sys.intern(string) for _ in range(count): data, names = items.pop() frame_map = {} # TO DO : add flexray fibex support # if item.attachment and item.attachment[0]: # dbc = load_can_database(item.attachment[1], item.attachment[0]) # if dbc: # frame_map = { # frame.arbitration_id.id: frame.name for frame in dbc # } # # for name in frame_map.values(): # sys.intern(name) if data.name == "FLX_Frame": index = np.searchsorted(df_index, data.timestamps) vals = data["FLX_Frame.BusChannel"].astype("u1") vals = [f"FlexRay {chn}" for chn in vals.tolist()] columns["Bus"][index] = vals if data["FLX_Frame.FlxChannel"].dtype.kind == "S": columns["Channel"][index] = [v.decode("utf-8") for v in data["FLX_Frame.FlxChannel"].tolist()] else: columns["Channel"][index] = [ "B" if chn else "A" for chn in data["FLX_Frame.FlxChannel"].astype("u1").tolist() ] vals = data["FLX_Frame.ID"].astype("u2") columns["ID"][index] = vals if frame_map: columns["Name"][index] = [frame_map.get(_id, "") for _id in vals.tolist()] vals = data["FLX_Frame.Cycle"].astype("u1") columns["Cycle"][index] = vals data_length = data["FLX_Frame.DataLength"].astype("u1") columns["Data Length"][index] = data_length vals = csv_bytearray2hex( pd.Series(list(data["FLX_Frame.DataBytes"])), data_length, ) columns["Data Bytes"][index] = vals vals = data["FLX_Frame.HeaderCRC"].astype("u2") columns["Header CRC"][index] = vals if "FLX_Frame.Dir" in names: if data["FLX_Frame.Dir"].dtype.kind == "S": columns["Direction"][index] = [v.decode("utf-8") for v in data["FLX_Frame.Dir"].tolist()] else: columns["Direction"][index] = [ "Tx" if dir else "Rx" for dir in data["FLX_Frame.Dir"].astype("u1").tolist() ] vals = None data_length = None elif data.name == "FLX_NullFrame": index = np.searchsorted(df_index, data.timestamps) vals = data["FLX_NullFrame.BusChannel"].astype("u1") vals = [f"FlexRay {chn}" for chn in vals.tolist()] columns["Bus"][index] = vals if data["FLX_NullFrame.FlxChannel"].dtype.kind == "S": columns["Channel"][index] = [ v.decode("utf-8") for v in data["FLX_NullFrame.FlxChannel"].tolist() ] else: columns["Channel"][index] = [ "B" if chn else "A" for chn in data["FLX_NullFrame.FlxChannel"].astype("u1").tolist() ] vals = data["FLX_NullFrame.ID"].astype("u2") columns["ID"][index] = vals if frame_map: columns["Name"][index] = [frame_map.get(_id, "") for _id in vals.tolist()] vals = data["FLX_NullFrame.Cycle"].astype("u1") columns["Cycle"][index] = vals columns["Event Type"][index] = "FlexRay NullFrame" vals = data["FLX_NullFrame.HeaderCRC"].astype("u2") columns["Header CRC"][index] = vals if "FLX_NullFrame.Dir" in names: if data["FLX_NullFrame.Dir"].dtype.kind == "S": columns["Direction"][index] = [ v.decode("utf-8") for v in data["FLX_NullFrame.Dir"].tolist() ] else: columns["Direction"][index] = [ "Tx" if dir else "Rx" for dir in data["FLX_NullFrame.Dir"].astype("u1").tolist() ] vals = None data_length = None elif data.name == "FLX_StartCycle": index = np.searchsorted(df_index, data.timestamps) vals = data["FLX_StartCycle.Cycle"].astype("u1") columns["Cycle"][index] = vals columns["Event Type"][index] = "FlexRay StartCycle" vals = None data_length = None elif data.name == "FLX_Status": index = np.searchsorted(df_index, data.timestamps) vals = data["FLX_Status.StatusType"].astype("u1") columns["Details"][index] = vals.astype("U").astype("O") columns["Event Type"][index] = "FlexRay Status" vals = None data_length = None else: df_index = [] count = 0 columns = { "timestamps": df_index, "Bus": np.full(count, "", dtype="O"), "Channel": np.full(count, "", dtype="O"), "ID": np.full(count, 0xFFFF, dtype="u2"), "Direction": np.full(count, "", dtype="O"), "Cycle": np.full(count, 0xFF, dtype="u1"), "Name": np.full(count, "", dtype="O"), "Event Type": np.full(count, "FlexRay Frame", dtype="O"), "Details": np.full(count, "", dtype="O"), "Data Length": np.zeros(count, dtype="u1"), "Data Bytes": np.full(count, "", dtype="O"), "Header CRC": np.full(count, 0xFFFF, dtype="u2"), } signals = pd.DataFrame(columns) trace = FlexRayBusTrace(signals, start=self.mdf.header.start_time, ranges=ranges) sub = MdiSubWindow(parent=self) sub.setWidget(trace) trace.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.sigClosed.connect(self.window_closed_handler) sub.titleModified.connect(self.window_closed_handler) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/bus_flx.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) sub.setWindowIcon(icon) if not self.subplots: for mdi in self.mdi_area.subWindowList(): mdi.close() w = self.mdi_area.addSubWindow(sub) w.showMaximized() else: w = self.mdi_area.addSubWindow(sub) if len(self.mdi_area.subWindowList()) == 1: w.showMaximized() else: w.show() if self._frameless_windows: w.setWindowFlags(w.windowFlags() | QtCore.Qt.WindowType.FramelessWindowHint) w.setWindowTitle(f"FlexRay Bus Trace {self._window_counter}") self._window_counter += 1 if self.subplots_link: trace.timestamp_changed_signal.connect(self.set_cursor) self.windows_modified.emit() trace.tree.auto_size_header() return trace def _add_gps_window(self, signals): signals = [sig[:3] for sig in signals] latitude_channel, longitude_channel = self.mdf.select(signals, validate=True) gps = GPS(latitude_channel, longitude_channel) sub = MdiSubWindow(parent=self) sub.setWidget(gps) gps.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.sigClosed.connect(self.window_closed_handler) sub.titleModified.connect(self.window_closed_handler) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/globe.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) sub.setWindowIcon(icon) w = self.mdi_area.addSubWindow(sub) if len(self.mdi_area.subWindowList()) == 1: w.showMaximized() else: w.show() if self._frameless_windows: w.setWindowFlags(w.windowFlags() | QtCore.Qt.WindowType.FramelessWindowHint) w.setWindowTitle(f"GPS {self._window_counter}") self._window_counter += 1 if self.subplots_link: gps.timestamp_changed_signal.connect(self.set_cursor) self.windows_modified.emit() def _add_lin_bus_trace_window(self, ranges=None): dfs = [] if self.mdf.version >= "4.00": groups_count = len(self.mdf.groups) for index in range(groups_count): group = self.mdf.groups[index] if group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT: source = group.channel_group.acq_source names = [ch.name for ch in group.channels] if source and source.bus_type == v4c.BUS_TYPE_LIN: if "LIN_Frame" in names: data = self.mdf.get("LIN_Frame", index, raw=True) elif "LIN_SyncError" in names: data = self.mdf.get("LIN_SyncError", index, raw=True) elif "LIN_TransmissionError" in names: data = self.mdf.get("LIN_TransmissionError", index, raw=True) elif "LIN_ChecksumError" in names: data = self.mdf.get("LIN_ChecksumError", index, raw=True) elif "LIN_ReceiveError" in names: data = self.mdf.get("LIN_ReceiveError", index, raw=True) df_index = data.timestamps count = len(df_index) columns = { "timestamps": df_index, "Bus": np.full(count, "Unknown", dtype="O"), "ID": np.full(count, 0xFFFFFFFF, dtype="u4"), "Direction": np.full(count, "", dtype="O"), "Name": np.full(count, "", dtype="O"), "Event Type": np.full(count, "LIN Frame", dtype="O"), "Details": np.full(count, "", dtype="O"), "Received Byte Count": np.zeros(count, dtype="u1"), "Data Length": np.zeros(count, dtype="u1"), "Data Bytes": np.full(count, "", dtype="O"), } frame_map = None if data.attachment and data.attachment[0]: dbc = load_can_database(data.attachment[1], data.attachment[0]) if dbc: frame_map = {frame.arbitration_id.id: frame.name for frame in dbc} for name in frame_map.values(): sys.intern(name) if data.name == "LIN_Frame": vals = data["LIN_Frame.BusChannel"].astype("u1") vals = [f"LIN {chn}" for chn in vals.tolist()] columns["Bus"] = vals vals = data["LIN_Frame.ID"].astype("u1") & 0x3F columns["ID"] = vals if frame_map: columns["Name"] = [frame_map.get(_id, "") for _id in vals.tolist()] columns["Received Byte Count"] = data["LIN_Frame.ReceivedDataByteCount"].astype("u1") data_length = data["LIN_Frame.DataLength"].astype("u1").tolist() columns["Data Length"] = data_length vals = csv_bytearray2hex( pd.Series(list(data["LIN_Frame.DataBytes"])), data_length, ) columns["Data Bytes"] = vals if "LIN_Frame.Dir" in names: if data["LIN_Frame.Dir"].dtype.kind == "S": columns["Direction"] = [v.decode("utf-8") for v in data["LIN_Frame.Dir"].tolist()] else: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["LIN_Frame.Dir"].astype("u1").tolist() ] vals = None data_length = None elif data.name == "LIN_SyncError": names = set(data.samples.dtype.names) if "LIN_SyncError.BusChannel" in names: vals = data["LIN_SyncError.BusChannel"].astype("u1") vals = [f"LIN {chn}" for chn in vals.tolist()] columns["Bus"] = vals if "LIN_SyncError.BaudRate" in names: vals = data["LIN_SyncError.BaudRate"] unique = np.unique(vals).tolist() for val in unique: sys.intern(f"Baudrate {val}") vals = [f"Baudrate {val}" for val in vals.tolist()] columns["Details"] = vals columns["Event Type"] = "Sync Error Frame" vals = None data_length = None elif data.name == "LIN_TransmissionError": names = set(data.samples.dtype.names) if "LIN_TransmissionError.BusChannel" in names: vals = data["LIN_TransmissionError.BusChannel"].astype("u1") vals = [f"LIN {chn}" for chn in vals.tolist()] columns["Bus"] = vals if "LIN_TransmissionError.BaudRate" in names: vals = data["LIN_TransmissionError.BaudRate"] unique = np.unique(vals).tolist() for val in unique: sys.intern(f"Baudrate {val}") vals = [f"Baudrate {val}" for val in vals.tolist()] columns["Details"] = vals vals = data["LIN_TransmissionError.ID"].astype("u1") & 0x3F columns["ID"] = vals if frame_map: columns["Name"] = [frame_map.get(_id, "") for _id in vals.tolist()] columns["Event Type"] = "Transmission Error Frame" columns["Direction"] = ["Tx"] * count vals = None elif data.name == "LIN_ReceiveError": names = set(data.samples.dtype.names) if "LIN_ReceiveError.BusChannel" in names: vals = data["LIN_ReceiveError.BusChannel"].astype("u1") vals = [f"LIN {chn}" for chn in vals.tolist()] columns["Bus"] = vals if "LIN_ReceiveError.BaudRate" in names: vals = data["LIN_ReceiveError.BaudRate"] unique = np.unique(vals).tolist() for val in unique: sys.intern(f"Baudrate {val}") vals = [f"Baudrate {val}" for val in vals.tolist()] columns["Details"] = vals if "LIN_ReceiveError.ID" in names: vals = data["LIN_ReceiveError.ID"].astype("u1") & 0x3F columns["ID"] = vals if frame_map: columns["Name"] = [frame_map[_id] for _id in vals] columns["Event Type"] = "Receive Error Frame" columns["Direction"] = ["Rx"] * count vals = None elif data.name == "LIN_ChecksumError": names = set(data.samples.dtype.names) if "LIN_ChecksumError.BusChannel" in names: vals = data["LIN_ChecksumError.BusChannel"].astype("u1") vals = [f"LIN {chn}" for chn in vals.tolist()] columns["Bus"] = vals if "LIN_ChecksumError.Checksum" in names: vals = data["LIN_ChecksumError.Checksum"] unique = np.unique(vals).tolist() for val in unique: sys.intern(f"Baudrate {val}") vals = [f"Checksum 0x{val:02X}" for val in vals.tolist()] columns["Details"] = vals if "LIN_ChecksumError.ID" in names: vals = data["LIN_ChecksumError.ID"].astype("u1") & 0x3F columns["ID"] = vals if frame_map: columns["Name"] = [frame_map[_id] for _id in vals] if "LIN_ChecksumError.DataBytes" in names: data_length = data["LIN_ChecksumError.DataLength"].astype("u1").tolist() columns["Data Length"] = data_length vals = csv_bytearray2hex( pd.Series(list(data["LIN_ChecksumError.DataBytes"])), data_length, ) columns["Data Bytes"] = vals columns["Event Type"] = "Checksum Error Frame" if "LIN_ChecksumError.Dir" in names: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["LIN_ChecksumError.Dir"].astype("u1").tolist() ] vals = None dfs.append(pd.DataFrame(columns, index=df_index)) if not dfs: df_index = [] count = 0 columns = { "timestamps": df_index, "Bus": np.full(count, "Unknown", dtype="O"), "ID": np.full(count, 0xFFFFFFFF, dtype="u4"), "Direction": np.full(count, "", dtype="O"), "Name": np.full(count, "", dtype="O"), "Event Type": np.full(count, "LIN Frame", dtype="O"), "Details": np.full(count, "", dtype="O"), "Received Byte Count": np.zeros(count, dtype="u1"), "Data Length": np.zeros(count, dtype="u1"), "Data Bytes": np.full(count, "", dtype="O"), } signals = pd.DataFrame(columns, index=df_index) else: signals = pd.concat(dfs).sort_index() index = pd.Index(range(len(signals))) signals.set_index(index, inplace=True) del dfs trace = LINBusTrace(signals, start=self.mdf.header.start_time, range=ranges) sub = MdiSubWindow(parent=self) sub.setWidget(trace) trace.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.sigClosed.connect(self.window_closed_handler) sub.titleModified.connect(self.window_closed_handler) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/bus_lin.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) sub.setWindowIcon(icon) if not self.subplots: for mdi in self.mdi_area.subWindowList(): mdi.close() w = self.mdi_area.addSubWindow(sub) w.showMaximized() else: w = self.mdi_area.addSubWindow(sub) if len(self.mdi_area.subWindowList()) == 1: w.showMaximized() else: w.show() if self._frameless_windows: w.setWindowFlags(w.windowFlags() | QtCore.Qt.WindowType.FramelessWindowHint) w.setWindowTitle(f"LIN Bus Trace {self._window_counter}") self._window_counter += 1 if self.subplots_link: trace.timestamp_changed_signal.connect(self.set_cursor) self.windows_modified.emit() trace.tree.auto_size_header() return trace def _add_numeric_window(self, names): if names and isinstance(names[0], str): signals_ = [ ( name, *self.mdf.whereis(name)[0], self.uuid, "channel", [], os.urandom(6).hex(), ) for name in names if name in self.mdf ] else: flatten_entries = get_flatten_entries_from_mime(names) if not self.comparison: names = substitude_mime_uuids(names, uuid=self.uuid, force=True) flatten_entries = get_flatten_entries_from_mime(names) signals_ = [ entry for entry in flatten_entries if (entry["group_index"], entry["channel_index"]) != (-1, -1) ] signals_ = natsorted(signals_) uuids = {entry["origin_uuid"] for entry in signals_} signals = [] for uuid in uuids: uuids_signals = [ (entry["name"], entry["group_index"], entry["channel_index"]) for entry in signals_ if entry["origin_uuid"] == uuid and entry["group_index"] != NOT_FOUND ] not_found = [ (entry["name"], entry["group_index"], entry["channel_index"]) for entry in signals_ if entry["origin_uuid"] == uuid and entry["group_index"] == NOT_FOUND ] uuids_signals_objs = [ entry for entry in signals_ if entry["origin_uuid"] == uuid and entry["group_index"] != NOT_FOUND ] not_found_objs = [ entry for entry in signals_ if entry["origin_uuid"] == uuid and entry["group_index"] == NOT_FOUND ] file_info = self.file_by_uuid(uuid) if not file_info: continue file_index, file = file_info origin_mdf = file.mdf.original_name.name selected_signals = file.mdf.select( uuids_signals, ignore_value2text_conversions=self.ignore_value2text_conversions, copy_master=False, validate=True, raw=True, ) for sig, sig_, sig_obj in zip(selected_signals, uuids_signals, uuids_signals_objs, strict=False): sig.group_index = sig_[1] sig.channel_index = sig_[2] sig.flags &= ~sig.Flags.computed sig.computation = {} sig.origin_uuid = uuid sig.origin_mdf = origin_mdf sig.name = sig_[0] or sig.name sig.ranges = sig_obj["ranges"] sig.uuid = sig_obj["uuid"] if "color" in sig_obj: sig.color = fn.mkColor(sig_obj["color"]) signals.extend(selected_signals) for pattern_group in get_pattern_groups(names): file_info = self.file_by_uuid(uuid) if not file_info: continue file_index, file = file_info signals.extend( extract_signals_using_pattern( mdf=file.mdf, channels_db=None, pattern_info=pattern_group["pattern"], ignore_value2text_conversions=file.ignore_value2text_conversions, uuid=file.uuid, ).values() ) for signal in signals: if len(signal.samples.shape) > 1: if signal.name.endswith(".DataBytes"): length_name = signal.name.replace(".DataBytes", ".DataLength") for s in signals: if s.name == length_name: length = s.samples break else: if length_name in self.mdf: length = self.mdf.get(length_name, samples_only=True)[0] else: length = None else: length = None signal.samples = csv_bytearray2hex(pd.Series(list(signal.samples)), length) if signal.name.endswith(".ID"): signal.samples = signal.samples.astype(" 1) } signals = { key: sig for key, sig in signals.items() if sig.samples.dtype.kind not in "SU" and not sig.samples.dtype.names and not len(sig.samples.shape) > 1 } for sig in nd.values(): if sig.samples.dtype.names is None: shape = sig.samples.shape[1:] matrix_dims = [list(range(dim)) for dim in shape] matrix_name = sig.name for indexes in itertools.product(*matrix_dims): indexes_string = "".join(f"[{_index}]" for _index in indexes) samples = sig.samples for idx in indexes: samples = samples[:, idx] sig_name = f"{matrix_name}{indexes_string}" new_sig = sig.copy() new_sig.name = sig_name new_sig.samples = samples new_sig.group_index = sig.group_index new_sig.channel_index = sig.channel_index new_sig.flags &= ~sig.Flags.computed new_sig.computation = {} new_sig.origin_uuid = sig.origin_uuid new_sig.origin_mdf = origin_mdf new_sig.uuid = os.urandom(6).hex() new_sig.enable = getattr(sig, "enable", True) signals[new_sig.uuid] = new_sig else: name = sig.samples.dtype.names[0] if name == sig.name: array_samples = sig.samples[name] shape = array_samples.shape[1:] matrix_dims = [list(range(dim)) for dim in shape] matrix_name = sig.name for indexes in itertools.product(*matrix_dims): indexes_string = "".join(f"[{_index}]" for _index in indexes) samples = array_samples for idx in indexes: samples = samples[:, idx] sig_name = f"{matrix_name}{indexes_string}" new_sig = sig.copy() new_sig.name = sig_name new_sig.samples = samples new_sig.group_index = sig.group_index new_sig.channel_index = sig.channel_index new_sig.flags &= ~sig.Flags.computed new_sig.computation = {} new_sig.origin_uuid = sig.origin_uuid new_sig.origin_mdf = origin_mdf new_sig.uuid = os.urandom(6).hex() new_sig.enable = getattr(sig, "enable", True) signals[new_sig.uuid] = new_sig for signal in signals.values(): if len(signal.samples.shape) > 1: if signal.name.endswith(".DataBytes"): length_name = signal.name.replace(".DataBytes", ".DataLength") for s in signals: if s.name == length_name: length = s.samples break else: if length_name in self.mdf: length = self.mdf.get(length_name, samples_only=True)[0] else: length = None else: length = None signal.samples = csv_bytearray2hex(pd.Series(list(signal.samples)), length.astype("u2")) if signal.name.endswith(".ID"): signal.samples = signal.samples.astype("= "4.00": mdf_events = list(self.mdf.events) for pos, event in enumerate(mdf_events): event_info = {} event_info["value"] = event.value event_info["type"] = v4c.EVENT_TYPE_TO_STRING[event.event_type] if event.name: description = event.name else: description = "" if event.comment: try: comment = extract_xml_comment(event.comment) except: comment = event.comment if description: description = f"{description} ({comment})" else: description = comment event_info["description"] = description event_info["index"] = pos event_info["tool"] = event.tool if event.range_type == v4c.EVENT_RANGE_TYPE_POINT: events.append(event_info) elif event.range_type == v4c.EVENT_RANGE_TYPE_BEGINNING: events.append([event_info]) else: if event.parent is not None: parent = events[event.parent] parent.append(event_info) events.append(None) events = [ev for ev in events if ev is not None] else: for gp in self.mdf.groups: if not gp.trigger: continue for i in range(gp.trigger.trigger_events_nr): event = { "value": gp.trigger[f"trigger_{i}_time"], "index": i, "description": gp.trigger.comment, "type": v4c.EVENT_TYPE_TO_STRING[v4c.EVENT_TYPE_TRIGGER], } events.append(event) mdf = self.mdf else: events = [] origin = next(self.iter_files()).mdf.start_time mdf = None plot = Plot( [], events=events, with_dots=self.with_dots, line_interconnect=self.line_interconnect, origin=origin, mdf=mdf, parent=self, hide_missing_channels=self.hide_missing_channels, hide_disabled_channels=self.hide_disabled_channels, show_cursor_circle=self.cursor_circle, show_cursor_horizontal_line=self.cursor_horizontal_line, cursor_line_width=self.cursor_line_width, cursor_color=self.cursor_color, owner=self, ) plot.pattern_group_added.connect(self.add_pattern_group) plot.verify_bookmarks.connect(self.verify_bookmarks) plot.pattern = {} sub = MdiSubWindow(parent=self) sub.setWidget(plot) plot.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.sigClosed.connect(self.window_closed_handler) sub.titleModified.connect(self.window_closed_handler) sub.pattern_modified.connect(self.window_pattern_modified) if not self.subplots: self.mdi_area.clear_windows() w = self.mdi_area.addSubWindow(sub) w.showMaximized() else: w = self.mdi_area.addSubWindow(sub) if len(self.mdi_area.subWindowList()) == 1: w.showMaximized() else: w.show() if self._frameless_windows: w.setWindowFlags(w.windowFlags() | QtCore.Qt.WindowType.FramelessWindowHint) plot.show() w.setWindowTitle(generate_window_title(w, "Plot")) plot.add_channels_request.connect(partial(self.add_new_channels, widget=plot)) plot.edit_channel_request.connect(partial(self.edit_channel, widget=plot)) plot.show_overlapping_alias.connect(self._show_overlapping_alias) plot.show_properties.connect(self._show_info) plot.add_new_channels(signals, mime_data) if self.subplots_link: plot.x_range_changed_signal.connect(self.set_x_range) plot.cursor_moved_signal.connect(self.set_cursor) plot.region_removed_signal.connect(self.remove_region) plot.region_moved_signal.connect(self.set_region) plot.splitter_moved.connect(self.set_splitter) for i, mdi in enumerate(self.mdi_area.subWindowList()): widget = mdi.widget() if isinstance(widget, Plot): plot.plot.viewbox.setXRange(*widget.plot.viewbox.viewRange()[0], padding=0, update=True) break iterator = QtWidgets.QTreeWidgetItemIterator(plot.channel_selection) while item := iterator.value(): iterator += 1 if item.type() == item.Group: if item.pattern: plot.pattern_group_added.emit(plot, item) if self.comparison: plot.channel_selection.setColumnHidden(plot.channel_selection.OriginColumn, False) self.windows_modified.emit() return w, plot def _add_tabular_window(self, names): if names and isinstance(names[0], str): signals_ = [ ( name, *self.mdf.whereis(name)[0], self.uuid, "channel", [], os.urandom(6).hex(), ) for name in names if name in self.mdf ] else: flatten_entries = get_flatten_entries_from_mime(names) uuids = {entry["origin_uuid"] for entry in flatten_entries} for uuid in uuids: if self.file_by_uuid(uuid): break else: names = substitude_mime_uuids(names, uuid=self.uuid, force=True) flatten_entries = get_flatten_entries_from_mime(names) signals_ = [ entry for entry in flatten_entries if (entry["group_index"], entry["channel_index"]) != (NOT_FOUND, NOT_FOUND) ] signals_ = natsorted(signals_, key=lambda x: (x["group_index"], x["name"], x["channel_index"])) uuids = {entry["origin_uuid"] for entry in signals_} dfs = [] ranges = {} start = [] for uuid in uuids: unique_names = UniqueDB() uuids_signals = [ (entry["name"], entry["group_index"], entry["channel_index"]) for entry in signals_ if entry["origin_uuid"] == uuid ] file_info = self.file_by_uuid(uuid) if not file_info: continue file_index, file = file_info if self.comparison: for entry in signals_: if entry["origin_uuid"] != uuid: continue name = unique_names.get_unique_name(entry["name"]) ranges[f"{file_index + 1}: {name}"] = entry["ranges"] else: for entry in signals_: if entry["origin_uuid"] != uuid: continue name = unique_names.get_unique_name(entry["name"]) ranges[name] = entry["ranges"] start.append(file.mdf.header.start_time) for pattern_group in get_pattern_groups(names): uuids_signals.extend( [ (sig.name, sig.group_index, sig.channel_index) for sig in extract_signals_using_pattern( mdf=file.mdf, channels_db=None, pattern_info=pattern_group["pattern"], ignore_value2text_conversions=file.ignore_value2text_conversions, uuid=file.uuid, ).values() ] ) uuids_signals = [entry for entry in uuids_signals if entry[2] != file.mdf.masters_db.get(entry[1], None)] df = file.mdf.to_dataframe( channels=uuids_signals, ignore_value2text_conversions=self.ignore_value2text_conversions, time_from_zero=False, empty_channels="zeros", use_interpolation=QtCore.QSettings().value("tabular_interpolation", True, type=bool), ) if self.comparison: columns = {name: f"{file_index + 1}: {name}" for name in df.columns} df.rename(columns=columns, inplace=True) dfs.append(df) if not dfs: signals = pd.DataFrame() try: start = self.mdf.header.start_time except: start = datetime.datetime.now() else: signals = pd.concat(dfs, axis=1) start = min(start) for name in signals.columns: if name.endswith( ".ID", ): signals[name] = signals[name].astype(" 1 } if not self.comparison: events = [] origin = self.mdf.start_time if self.mdf.version >= "4.00": mdf_events = list(self.mdf.events) for pos, event in enumerate(mdf_events): event_info = {} event_info["value"] = event.value event_info["type"] = v4c.EVENT_TYPE_TO_STRING[event.event_type] event_info["tool"] = event.tool if event.name: description = event.name else: description = "" if event.comment: try: comment = extract_xml_comment(event.comment) except: comment = event.comment if description: description = f"{description} ({comment})" else: description = comment event_info["description"] = description event_info["index"] = pos if event.range_type == v4c.EVENT_RANGE_TYPE_POINT: events.append(event_info) elif event.range_type == v4c.EVENT_RANGE_TYPE_BEGINNING: events.append([event_info]) else: parent = events[event.parent] parent.append(event_info) events.append(None) events = [ev for ev in events if ev is not None] else: for gp in self.mdf.groups: if not gp.trigger: continue for i in range(gp.trigger.trigger_events_nr): event = { "value": gp.trigger[f"trigger_{i}_time"], "index": i, "description": gp.trigger.comment, "type": v4c.EVENT_TYPE_TO_STRING[v4c.EVENT_TYPE_TRIGGER], } events.append(event) mdf = self.mdf else: events = [] origin = next(self.iter_files()).mdf.start_time mdf = None plot = Plot( [], with_dots=self.with_dots, line_interconnect=self.line_interconnect, events=events, origin=origin, mdf=mdf, parent=self, hide_missing_channels=self.hide_missing_channels, hide_disabled_channels=self.hide_disabled_channels, show_cursor_circle=self.cursor_circle, show_cursor_horizontal_line=self.cursor_horizontal_line, cursor_line_width=self.cursor_line_width, cursor_color=self.cursor_color, owner=self, ) plot.plot._can_compute_all_timebase = False plot.pattern_group_added.connect(self.add_pattern_group) plot.verify_bookmarks.connect(self.verify_bookmarks) plot.pattern = pattern_info plot.plot._can_paint_global = False plot.show() sub = MdiSubWindow(parent=self) sub.setWidget(plot) plot.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.sigClosed.connect(self.window_closed_handler) sub.titleModified.connect(self.window_closed_handler) sub.pattern_modified.connect(self.window_pattern_modified) if not self.subplots: for mdi in self.mdi_area.subWindowList(): mdi.close() w = self.mdi_area.addSubWindow(sub) w.showMaximized() else: w = self.mdi_area.addSubWindow(sub) w.show() if geometry: w.setGeometry(*geometry) else: self.mdi_area.tileSubWindows() if window_info.get("maximized", False): w.showMaximized() elif window_info.get("minimized", False): w.showMinimized() w.setWindowTitle(generate_window_title(w, window_info["type"], window_info["title"])) if "x_range" in window_info["configuration"] and WithMDIArea.load_plot_x_range: x_range = window_info["configuration"]["x_range"] if isinstance(x_range, float): x_range = 0, x_range plot.plot.viewbox.setXRange(*x_range, padding=0) plot.plot.initial_x_range = "shift" if "splitter" in window_info["configuration"]: plot.splitter.setSizes(window_info["configuration"]["splitter"]) if "y_axis_width" in window_info["configuration"]: plot.plot.y_axis.setWidth(window_info["configuration"]["y_axis_width"]) if "grid" in window_info["configuration"]: x_grid, y_grid = window_info["configuration"]["grid"] plot.plot.plotItem.ctrl.xGridCheck.setChecked(x_grid) plot.plot.plotItem.ctrl.yGridCheck.setChecked(y_grid) if "font_size" in window_info["configuration"]: plot.set_font_size(window_info["configuration"]["font_size"]) plot.splitter.setContentsMargins(1, 1, 1, 1) plot.setContentsMargins(1, 1, 1, 1) # plot.hide() plot.show_overlapping_alias.connect(self._show_overlapping_alias) plot.show_properties.connect(self._show_info) plot.add_new_channels(signals, mime_data) # plot.show() plot.add_channels_request.connect(partial(self.add_new_channels, widget=plot)) plot.edit_channel_request.connect(partial(self.edit_channel, widget=plot)) if self.subplots_link: plot.x_range_changed_signal.connect(self.set_x_range) plot.cursor_moved_signal.connect(self.set_cursor) plot.region_removed_signal.connect(self.remove_region) plot.region_moved_signal.connect(self.set_region) plot.splitter_moved.connect(self.set_splitter) for i, mdi in enumerate(self.mdi_area.subWindowList()): widget = mdi.widget() if isinstance(widget, Plot): plot.plot.viewbox.setXRange(*widget.plot.viewbox.viewRange()[0], padding=0, update=True) break if "cursor_precision" in window_info["configuration"]: plot.cursor_info.set_precision(window_info["configuration"]["cursor_precision"]) iterator = QtWidgets.QTreeWidgetItemIterator(plot.channel_selection) while item := iterator.value(): iterator += 1 if item.type() == item.Group: if item.pattern: state = item.checkState(item.NameColumn) plot.pattern_group_added.emit(plot, item) item.setCheckState(item.NameColumn, state) if self.comparison: plot.channel_selection.setColumnHidden(plot.channel_selection.OriginColumn, False) if "common_axis_y_range" in window_info["configuration"]: plot.plot.common_axis_y_range = tuple(window_info["configuration"]["common_axis_y_range"]) # keep compatibility with older asammdf versions if "channels_header_sizes" in window_info["configuration"]: width, sizes = window_info["configuration"]["channels_header_sizes"] current_width = sum(plot.splitter.sizes()) plot.splitter.setSizes([width, max(current_width - width, 50)]) plot.channel_selection.set_header_sizes(sizes) elif "channels_header" in window_info["configuration"]: width, sizes = window_info["configuration"]["channels_header"] current_width = sum(plot.splitter.sizes()) plot.splitter.setSizes([width, max(current_width - width, 50)]) for i, size in enumerate(sizes): plot.channel_selection.setColumnWidth(i, size) # keep compatibility with older asammdf versions if "channels_header_columns_visiblity" in window_info["configuration"]: plot.channel_selection.set_header_columns_visibility( window_info["configuration"]["channels_header_columns_visiblity"] ) elif "channels_header_columns_visible" in window_info["configuration"]: for i, visible in enumerate(window_info["configuration"]["channels_header_columns_visible"]): plot.channel_selection.setColumnHidden(i, not visible) hide_missing = window_info["configuration"].get("hide_missing_channels", False) hide_disabled = window_info["configuration"].get("hide_disabled_channels", False) if hide_missing or hide_disabled: plot.channel_selection.hide_missing_channels = hide_missing plot.channel_selection.hide_disabled_channels = hide_disabled plot.channel_selection.update_hidden_states() plot.set_locked(locked=window_info["configuration"].get("locked", False)) plot.hide_axes(hide=window_info["configuration"].get("hide_axes", False)) plot.hide_selected_channel_value( hide=window_info["configuration"].get("hide_selected_channel_value_panel", True) ) plot.toggle_bookmarks(hide=window_info["configuration"].get("hide_bookmarks", False)) plot.toggle_focused_mode(focused=window_info["configuration"].get("focused_mode", False)) plot.toggle_region_values_display_mode(mode=window_info["configuration"].get("delta_mode", "value")) plot_graphics = plot.plot plot_graphics._can_paint_global = True plot_graphics._can_compute_all_timebase = True plot_graphics._compute_all_timebase() if len(plot_graphics.all_timebase) and plot_graphics.cursor1 is not None: plot_graphics.cursor1.set_value(plot_graphics.all_timebase[0]) plot_graphics.viewbox._matrixNeedsUpdate = True plot_graphics.viewbox.updateMatrix() plot.update() plot.channel_selection.refresh() plot.set_initial_zoom() return w, pattern_info def _load_tabular_window(self, window_info): uuid = self.uuid geometry = window_info.get("geometry", None) # patterns pattern_info = window_info["configuration"].get("pattern", {}) if pattern_info: required = set() found_signals = [] signals_ = extract_signals_using_pattern( mdf=self.mdf, channels_db=None, pattern_info=pattern_info, ignore_value2text_conversions=self.ignore_value2text_conversions, uuid=self.uuid, ).values() ranges = {sig.name: copy_ranges(pattern_info["ranges"]) for sig in signals_} signals_ = [(sig.name, sig.group_index, sig.channel_index) for sig in signals_] else: required = set(window_info["configuration"]["channels"]) signals_ = [ (name, *self.mdf.whereis(name)[0]) for name in window_info["configuration"]["channels"] if name in self.mdf ] ranges = window_info["configuration"].get("ranges", {}) if not signals_: return None, False signals = self.mdf.to_dataframe( channels=signals_, time_from_zero=False, ignore_value2text_conversions=self.ignore_value2text_conversions, use_interpolation=QtCore.QSettings().value("tabular_interpolation", True, type=bool), ) found = set(signals.columns) dim = len(signals.index) for name in sorted(required - found): vals = np.empty(dim) vals.fill(np.nan) signals[name] = pd.Series(vals, index=signals.index) tabular = Tabular( signals, ranges=ranges, start=self.mdf.header.start_time, parent=self, owner=self, ) tabular.pattern = pattern_info sub = MdiSubWindow(parent=self) sub.setWidget(tabular) tabular.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.sigClosed.connect(self.window_closed_handler) sub.titleModified.connect(self.window_closed_handler) sub.pattern_modified.connect(self.window_pattern_modified) if not self.subplots: for mdi in self.mdi_area.subWindowList(): mdi.close() w = self.mdi_area.addSubWindow(sub) w.showMaximized() else: w = self.mdi_area.addSubWindow(sub) w.show() if geometry: w.setGeometry(*geometry) else: self.mdi_area.tileSubWindows() if window_info.get("maximized", False): w.showMaximized() elif window_info.get("minimized", False): w.showMinimized() w.setWindowTitle(generate_window_title(w, window_info["type"], window_info["title"])) mode = tabular.format_selection.currentText() filter_count = 0 available_columns = [signals.index.name, *signals.columns] for filter_info in window_info["configuration"]["filters"]: if filter_info["column"] in available_columns: tabular.add_filter() filter = tabular.filters.itemWidget(tabular.filters.item(filter_count)) filter.enabled.setCheckState( QtCore.Qt.CheckState.Checked if filter_info["enabled"] else QtCore.Qt.CheckState.Unchecked ) filter.relation.setCurrentText(filter_info["relation"]) filter.column.setCurrentText(filter_info["column"]) filter.op.setCurrentText(filter_info["op"]) if mode == "phys": filter.target.setText(str(filter_info["target"]).strip('"')) elif mode == "hex": filter.target.setText(hex(filter_info["target"]).strip('"')) elif mode == "bin": filter.target.setText(bin(filter_info["target"]).strip('"')) filter.validate_target() filter_count += 1 if filter_count and window_info["configuration"]["filtered"]: tabular.apply_filters() tabular.time_as_date.setCheckState( QtCore.Qt.CheckState.Checked if window_info["configuration"]["time_as_date"] else QtCore.Qt.CheckState.Unchecked ) tabular.add_channels_request.connect(partial(self.add_new_channels, widget=tabular)) if self.subplots_link: tabular.timestamp_changed_signal.connect(self.set_cursor) sections_width = window_info["configuration"].get("header_sections_width", []) if sections_width: for i, width in enumerate(sections_width): tabular.tree.columnHeader.setColumnWidth(i, width) tabular.tree.dataView.setColumnWidth(i, width) tabular.tree.dataView.updateGeometry() tabular.tree.columnHeader.updateGeometry() return w, pattern_info def _load_can_bus_trace_window(self, window_info): if self.mdf.version < "4.00": return None, False ranges = window_info["configuration"].get("ranges", {}) widget = self._add_can_bus_trace_window(ranges) sections_width = window_info["configuration"].get("header_sections_width", []) if sections_width: for i, width in enumerate(sections_width): widget.tree.columnHeader.setColumnWidth(i, width) widget.tree.dataView.setColumnWidth(i, width) widget.tree.dataView.updateGeometry() widget.tree.columnHeader.updateGeometry() return None, False def _load_flexray_bus_trace_window(self, window_info): if self.mdf.version < "4.00": return None, False ranges = window_info["configuration"].get("ranges", {}) widget = self._add_flexray_bus_trace_window(ranges) sections_width = window_info["configuration"].get("header_sections_width", []) if sections_width: for i, width in enumerate(sections_width): widget.tree.columnHeader.setColumnWidth(i, width) widget.tree.dataView.setColumnWidth(i, width) widget.tree.dataView.updateGeometry() widget.tree.columnHeader.updateGeometry() return None, False def _load_lin_bus_trace_window(self, window_info): if self.mdf.version < "4.00": return None, False ranges = window_info["configuration"].get("ranges", {}) widget = self._add_lin_bus_trace_window(ranges) sections_width = window_info["configuration"].get("header_sections_width", []) if sections_width: for i, width in enumerate(sections_width): widget.tree.columnHeader.setColumnWidth(i, width) widget.tree.dataView.setColumnWidth(i, width) widget.tree.dataView.updateGeometry() widget.tree.columnHeader.updateGeometry() return None, False def _load_xy_window(self, window_info): geometry = window_info.get("geometry", None) x, y = window_info["configuration"]["channels"] if x in self.mdf: (x,) = self.mdf.select( [(x, *self.mdf.whereis(x)[0])], ignore_value2text_conversions=True, copy_master=False, validate=True, raw=False, ) else: x = None if y in self.mdf: (y,) = self.mdf.select( [(y, *self.mdf.whereis(y)[0])], ignore_value2text_conversions=True, copy_master=False, validate=True, raw=False, ) else: y = None xy = XY(x, y, color=window_info["configuration"]["color"]) sub = MdiSubWindow(parent=self) sub.setWidget(xy) xy.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) sub.sigClosed.connect(self.window_closed_handler) sub.titleModified.connect(self.window_closed_handler) if not self.subplots: for mdi in self.mdi_area.subWindowList(): mdi.close() w = self.mdi_area.addSubWindow(sub) w.showMaximized() else: w = self.mdi_area.addSubWindow(sub) w.show() if geometry: w.setGeometry(*geometry) else: self.mdi_area.tileSubWindows() if window_info.get("maximized", False): w.showMaximized() elif window_info.get("minimized", False): w.showMinimized() w.setWindowTitle(generate_window_title(w, window_info["type"], window_info["title"])) xy.add_channels_request.connect(partial(self.add_new_channels, widget=xy)) if self.subplots_link: xy.timestamp_changed_signal.connect(self.set_cursor) return w, xy def set_line_style(self, with_dots=None): if with_dots is None: with_dots = not self.with_dots current_plot = self.get_current_widget() if current_plot and isinstance(current_plot, Plot): self.with_dots = with_dots current_plot.with_dots = with_dots current_plot.plot.set_dots(with_dots) def set_line_interconnect(self, line_interconnect): if line_interconnect == "line": line_interconnect = "" self.line_interconnect = line_interconnect for i, mdi in enumerate(self.mdi_area.subWindowList()): widget = mdi.widget() if isinstance(widget, Plot): widget.line_interconnect = line_interconnect widget.plot.set_line_interconnect(line_interconnect) def set_subplots(self, option): self.subplots = option def set_subplots_link(self, subplots_link): self.subplots_link = subplots_link if subplots_link: for i, mdi in enumerate(self.mdi_area.subWindowList()): widget = mdi.widget() if isinstance(widget, Plot): widget.x_range_changed_signal.connect(self.set_x_range) widget.cursor_moved_signal.connect(self.set_cursor) widget.region_removed_signal.connect(self.remove_region) widget.region_moved_signal.connect(self.set_region) widget.splitter_moved.connect(self.set_splitter) elif widget: widget.timestamp_changed_signal.connect(self.set_cursor) else: for mdi in self.mdi_area.subWindowList(): widget = mdi.widget() if isinstance(widget, Plot): try: widget.cursor_moved_signal.disconnect(self.set_cursor) except: pass try: widget.x_range_changed_signal.disconnect(self.set_x_range) except: pass try: widget.region_removed_signal.disconnect(self.remove_region) except: pass try: widget.region_moved_signal.disconnect(self.set_region) except: pass try: widget.splitter_moved.disconnect(self.set_splitter) except: pass elif widget: try: widget.timestamp_changed_signal.disconnect(self.set_cursor) except: pass def set_cursor(self, widget, pos): if self._busy: return else: self._busy = True if not self.subplots_link: self._busy = False return active_window = self.mdi_area.currentSubWindow() if active_window is None: self._busy = False return active_widget = active_window.widget() if widget is not active_widget: self._busy = False return for mdi in self.mdi_area.subWindowList(): wid = mdi.widget() if wid is not widget: try: wid.set_timestamp(pos) except: print(format_exc()) self._busy = False def set_x_range(self, widget, x_range): if self._busy: return else: self._busy = True if not self.subplots_link: self._busy = False return if not isinstance(x_range, (tuple, list)): self._busy = False return if not len(x_range) == 2: self._busy = False return if np.any(np.isnan(x_range)) or not np.all(np.isfinite(x_range)): self._busy = False return for mdi in self.mdi_area.subWindowList(): wid = mdi.widget() if wid is not widget and isinstance(wid, Plot): try: wid._inhibit_x_range_changed_signal = True wid.plot.viewbox.setXRange(*x_range, padding=0, update=True) wid._inhibit_x_range_changed_signal = False except: print(format_exc()) self._busy = False def set_region(self, widget, region): if self._busy: return else: self._busy = True if not self.subplots_link: self._busy = False return active_window = self.mdi_area.currentSubWindow() if active_window is None: self._busy = False return active_widget = active_window.widget() if widget is not active_widget: self._busy = False return for mdi in self.mdi_area.subWindowList(): wid = mdi.widget() if isinstance(wid, Plot) and wid is not widget: try: if wid.plot.region is None: event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_R, QtCore.Qt.KeyboardModifier.NoModifier, ) wid.plot.keyPressEvent(event) wid.plot.region.setRegion(region) except: print(format_exc()) self._busy = False def set_splitter(self, widget, selection_width): if self._busy: return else: self._busy = True if not self.subplots_link: self._busy = False return if self._splitter_source is None: self._splitter_source = widget for mdi in self.mdi_area.subWindowList(): wid = mdi.widget() if isinstance(wid, Plot) and wid is not widget: if selection_width is not None: try: total_size = sum(wid.splitter.sizes()) if total_size > selection_width: wid.splitter.setSizes([selection_width, total_size - selection_width]) except: print(format_exc()) self._splitter_source = None self._busy = False def update_comparison_windows(self): if not self.comparison: return uuids = {file.mdf.uuid for file in self.iter_files()} windows = list(self.mdi_area.subWindowList()) for window in windows: widget = window.widget() widget.update_missing_signals(uuids) def update_functions(self, original_definitions, modified_definitions, new_global_variables): self.global_variables = new_global_variables # new definitions new_functions = [info for uuid, info in modified_definitions.items() if uuid not in original_definitions] for info in new_functions: self.functions[info["name"]] = info["definition"] new = {info["name"] for info in new_functions} # changed definitions translation = {} changed = set() changed_functions = [ (info, original_definitions[uuid]) for uuid, info in modified_definitions.items() if uuid in original_definitions and info != original_definitions[uuid] ] for new_info, old_info in changed_functions: translation[old_info["name"]] = new_info["name"] del self.functions[old_info["name"]] self.functions[new_info["name"]] = new_info["definition"] changed.add(old_info["name"]) # deleted definitions deleted = set() deleted_functions = [info for uuid, info in original_definitions.items() if uuid not in modified_definitions] for info in deleted_functions: del self.functions[info["name"]] deleted.add(info["name"]) # apply changes for mdi in self.mdi_area.subWindowList(): wid = mdi.widget() if isinstance(wid, Plot): iterator = QtWidgets.QTreeWidgetItemIterator(wid.channel_selection) while item := iterator.value(): if item.type() == item.Channel: if item.signal.flags & item.signal.Flags.computed: function = item.signal.computation["function"] if new_global_variables or function in changed: try: item.signal.computation["function"] = translation[ item.signal.computation["function"] ] func_name = item.signal.computation["function"] definition = self.functions[func_name] _globals = generate_python_function_globals() exec(definition.replace("\t", " "), _globals) func = _globals[func_name] parameters = list(inspect.signature(func).parameters)[:-1] args = {name: [] for name in parameters} for arg_name, alternatives in zip( parameters, item.signal.computation["args"].values(), strict=False, ): args[arg_name] = alternatives item.signal.computation["args"] = args except: print(format_exc()) self.edit_channel(wid.channel_item_to_config(item), item, wid) iterator += 1 return bool(new or changed or deleted) def remove_region(self, widget): if not self.subplots_link: return if self._region_source is None: self._region_source = widget for mdi in self.mdi_area.subWindowList(): plt = mdi.widget() if isinstance(plt, Plot) and plt is not widget: if plt.plot.region is not None: event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_R, QtCore.Qt.KeyboardModifier.NoModifier, ) plt.plot.keyPressEvent(event) self._region_source = None def save_all_subplots(self): file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Save as measurement file", "", "MDF version 4 files (*.mf4)" ) if file_name: with mdf_module.MDF() as mdf: for mdi in self.mdi_area.subWindowList(): widget = mdi.widget() if isinstance(widget, Plot): mdf.append(widget.plot.signals) elif isinstance(widget, Numeric): mdf.append([s.signal for s in widget.channels.backend.signals]) elif isinstance(widget, Tabular): mdf.append(widget.tree.pgdf.df_unfiltered) mdf.save(file_name, compression=2, overwrite=True) def file_by_uuid(self, uuid): try: if isinstance(self.files, QtWidgets.QMdiArea): for file_index, file_window in enumerate(self.files.subWindowList()): if file_window.widget().uuid == uuid: return file_index, file_window.widget() return None else: for file_index in range(self.files.count()): if self.files.widget(file_index).uuid == uuid: return file_index, self.files.widget(file_index) return None except: if self.uuid == uuid: return 0, self else: return None def iter_files(self): if isinstance(self.files, QtWidgets.QMdiArea): for file_index, file_window in enumerate(self.files.subWindowList()): if widget := file_window.widget(): yield widget else: for file_index in range(self.files.count()): if widget := self.files.widget(file_index): yield widget def _show_overlapping_alias(self, sig): group_index, index, uuid = sig.group_index, sig.channel_index, sig.origin_uuid file_info = self.file_by_uuid(uuid) if file_info: _, file = file_info try: channel = file.mdf.get_channel_metadata(group=group_index, index=index) info = (channel.data_type, channel.byte_offset, channel.bit_count) position = (group_index, index) alias = {} for gp_index, gp in enumerate(file.mdf.groups): for ch_index, ch in enumerate(gp.channels): if (gp_index, ch_index) != position and (ch.data_type, ch.byte_offset, ch.bit_count) == info: alias[ch.name] = (gp_index, ch_index) if alias: alias_text = "\n".join( f"{name} - group {gp_index} index {ch_index}" for name, (gp_index, ch_index) in alias.items() ) MessageBox.information( self, f"{channel.name} - other overlapping alias", f"{channel.name} has the following overlapping alias channels:\n\n{alias_text}", ) else: MessageBox.information( self, f"{channel.name} - no other overlapping alias", f"No other overlapping alias channels found for {channel.name}", ) except MdfException: print(format_exc()) def _show_info(self, sig): group_index, index = sig.group_index, sig.channel_index uuid = sig.origin_uuid file_info = self.file_by_uuid(uuid) if file_info: _, file = file_info try: channel = file.mdf.get_channel_metadata(group=group_index, index=index) msg = ChannelInfoDialog(channel, self) msg.show() except MdfException: MessageBox.warning( self, "Missing channel", f"The channel {sig.name} does not exit in the current measurement file.", ) def verify_bookmarks(self, bookmarks, plot): if self.comparison: return original_file_name = Path(self.mdf.original_name) if original_file_name.suffix.lower() not in (".mf4", ".mf4z"): return last_bookmark_index = None for i, bookmark in enumerate(bookmarks): if bookmark.editable: if last_bookmark_index is None: last_bookmark_index = i - 1 if bookmark.edited or bookmark.deleted: break else: return result = MessageBox.question( self, "Save measurement bookmarks?", "You have modified bookmarks.\n\nDo you want to save the changes in the measurement file?\n", ) if result == MessageBox.StandardButton.No: return _password = self.mdf._mdf._password uuid = self.mdf.uuid dspf = self.to_config() self.mdf.close() windows = list(self.mdi_area.subWindowList()) for window in windows: widget = window.widget() if widget is plot: continue self.mdi_area.removeSubWindow(window) widget.setParent(None) widget.close() widget.deleteLater() window.close() suffix = original_file_name.suffix.lower() if suffix == ".mf4z": with ZipFile(original_file_name, allowZip64=True) as archive: files = archive.namelist() if len(files) != 1: return fname = files[0] if Path(fname).suffix.lower() not in (".mdf", ".dat", ".mf4"): return tmpdir = gettempdir() file_name = archive.extract(fname, tmpdir) file_name = Path(tmpdir) / file_name else: file_name = original_file_name with open(file_name, "r+b") as mdf: try: mdf.seek(0, 2) address = mdf.tell() blocks = [] events = [] alignment = address % 8 if alignment: offset = 8 - alignment blocks.append(b"\0" * offset) address += offset for i, bookmark in enumerate(bookmarks[last_bookmark_index + 1 :]): if not bookmark.deleted: event = EventBlock( cause=v4c.EVENT_CAUSE_USER, range_type=v4c.EVENT_RANGE_TYPE_POINT, sync_type=v4c.EVENT_SYNC_TYPE_S, event_type=v4c.EVENT_TYPE_MARKER, flags=v4c.FLAG_EV_POST_PROCESSING, ) event.value = bookmark.value() event.comment = bookmark.xml_comment() events.append(event) address = event.to_blocks(address, blocks) for i in range(len(events) - 1): events[i].next_ev_addr = events[i + 1].address for block in blocks: mdf.write(bytes(block)) header = HeaderBlock(stream=mdf, address=0x40) if last_bookmark_index >= 0: address = header.first_event_addr for i in range(last_bookmark_index + 1): event = EventBlock(stream=mdf, address=address) address = event.next_ev_addr if events: event.next_ev_addr = events[0].address else: event.next_ev_addr = 0 mdf.seek(event.address) mdf.write(bytes(event)) else: if events: header.first_event_addr = events[0].address mdf.seek(header.address) mdf.write(bytes(header)) else: header.first_event_addr = 0 mdf.seek(header.address) mdf.write(bytes(header)) except: print(format_exc()) return if suffix == ".mf4z": zipped_mf4 = ZipFile(original_file_name, "w", compression=ZIP_DEFLATED) zipped_mf4.write( str(file_name), original_file_name.with_suffix(".mf4").name, compresslevel=1, ) zipped_mf4.close() file_name.unlink() self.mdf = mdf_module.MDF( name=original_file_name, callback=self.update_progress, password=_password, use_display_names=True, ) self.mdf.original_name = original_file_name self.mdf.uuid = uuid self.aspects.setCurrentIndex(0) self.load_channel_list(file_name=dspf) def window_closed_handler(self, obj=None): self.windows_modified.emit() def window_pattern_modified(self, pattern, window_id): for window in self.mdi_area.subWindowList(): if id(window) == window_id: wid = window.widget() wid.pattern = pattern geometry = window.geometry() window_config = { "title": window.windowTitle(), "configuration": wid.to_config(), "geometry": [ geometry.x(), geometry.y(), geometry.width(), geometry.height(), ], "maximized": window.isMaximized(), "minimized": window.isMinimized(), } if isinstance(wid, Numeric): window_config["type"] = "Numeric" elif isinstance(wid, Plot): window_config["type"] = "Plot" elif isinstance(wid, Tabular): window_config["type"] = "Tabular" del wid window.close() self.load_window(window_config) break def set_cursor_options(self, cursor_circle, cursor_horizontal_line, cursor_line_width, cursor_color): cursor_color = QtGui.QColor(cursor_color) self.cursor_circle = cursor_circle self.cursor_horizontal_line = cursor_horizontal_line self.cursor_line_width = cursor_line_width self.cursor_color = cursor_color for i, mdi in enumerate(self.mdi_area.subWindowList()): widget = mdi.widget() if isinstance(widget, Plot): widget.plot.cursor1.show_circle = cursor_circle widget.plot.cursor1.show_horizontal_line = cursor_horizontal_line widget.plot.cursor1.line_width = cursor_line_width widget.plot.cursor1.color = cursor_color if widget.plot.region is not None: for cursor in widget.plot.region.lines: cursor.show_circle = cursor_circle cursor.show_horizontal_line = cursor_horizontal_line cursor.line_width = cursor_line_width cursor.color = cursor_color widget.plot.update() asammdf-8.5.1/src/asammdf/gui/widgets/numeric.py000066400000000000000000002357531502633300400216150ustar00rootroot00000000000000import bisect from functools import partial import json import os from pathlib import Path import re from threading import Lock from traceback import format_exc from natsort import natsorted import numpy as np from numpy import searchsorted import pyqtgraph.functions as fn from PySide6 import QtCore, QtGui, QtWidgets from asammdf.gui import utils from asammdf.gui.dialogs.range_editor import RangeEditor from asammdf.gui.utils import ( copy_ranges, get_colors_using_ranges, unique_ranges, value_as_str, ) from asammdf.gui.widgets.plot import PlotSignal import asammdf.mdf as mdf_module from .. import serde from ..serde import ExtendedJsonDecoder, ExtendedJsonEncoder, extract_mime_names from ..ui.numeric_offline import Ui_NumericDisplay from ..utils import FONT_SIZE from .tree import substitude_mime_uuids HERE = Path(__file__).resolve().parent OPS = { "!=": "__ne__", "==": "__eq__", ">": "__gt__", ">=": "__ge__", "<": "__lt__", "<=": "__le__", } class SignalOnline: def __init__( self, name="", raw=None, scaled=None, unit="", entry=(), conversion=None, exists=True, format="phys", color="#505050", y_range=(0, 100), ): self.name = name self.raw = raw self.scaled = scaled self.unit = unit self.entry = entry self.conversion = conversion self.exists = exists self.configured_from_device = True self.format = format self.y_range = y_range color = color or "#505050" self.color = fn.mkColor(color) @property def origin_mdf(self): return "" @origin_mdf.setter def origin_mdf(self, value): pass @property def origin_uuid(self): return self.entry[0] @origin_uuid.setter def origin_uuid(self, value): self.entry = (value, self.name) def reset(self): self.raw = None self.scaled = None self.exists = True def update_values(self, values): self.raw = values[-1] if self.conversion: self.scaled = self.conversion.convert(values[-1:], as_bytes=True)[0] else: self.scaled = self.raw def __lt__(self, other): return self.name < other.name def get_value(self, index): if index == 0: return self.name elif index == 1: return self.raw elif index == 2: return self.scaled elif index == 3: return self.unit elif index == 4: return self.origin_uuid class SignalOffline: def __init__( self, signal=None, exists=True, ): self.signal = signal self.exists = exists self.raw = None self.scaled = None self.last_timestamp = None self.entry = signal.entry self.name = signal.name self.unit = signal.unit self.format = getattr(signal, "format", "phys") if not hasattr(signal, "color"): self.color = fn.mkColor("#505050") if not hasattr(signal, "y_range"): self.y_range = (0, 100) @property def y_range(self): return self.signal.y_range @y_range.setter def y_range(self, value): self.signal.y_range = value @property def color(self): return self.signal.color @color.setter def color(self, value): self.signal.color = value @property def origin_mdf(self): return self.signal.origin_mdf @origin_mdf.setter def origin_mdf(self, value): self.signal.origin_mdf = value @property def origin_uuid(self): return self.signal.origin_uuid @origin_uuid.setter def origin_uuid(self, value): self.signal.origin_uuid = value def reset(self, exists=True): self.signal.samples = self.signal.samples[:0] self.signal.timestamps = self.signal.timestamps[:0] self.exists = exists self.raw = None self.scaled = None self.last_timestamp = None def __lt__(self, other): return self.name < other.name def set_timestamp(self, timestamp): if timestamp is not None and (self.last_timestamp is None or self.last_timestamp != timestamp): self.last_timestamp = timestamp sig = self.signal if sig.samples.size: idx = searchsorted(sig.timestamps, timestamp, side="right") idx -= 1 idx = max(idx, 0) self.raw = sig.raw_samples[idx] self.scaled = sig.phys_samples[idx] def get_value(self, index, timestamp=None): self.set_timestamp(timestamp) if self.signal is not None: if index == 0: return self.signal.name elif index == 1: return self.raw elif index == 2: return self.scaled elif index == 3: return self.unit elif index == 4: return self.origin_uuid class OnlineBackEnd: def __init__(self, signals, numeric): super().__init__() self.signals = signals or [] self.map = None self.numeric = numeric self.sorted_column_index = 0 self.sorting_enabled = True self.sort_reversed = False self.numeric_viewer = None self.update() def update_signal_origin_uuid(self, signal, origin_uuid): old_entry = signal.entry signal.origin_uuid = origin_uuid self.map[signal.entry] = signal del self.map[old_entry] self.numeric_viewer.dataView.ranges[signal.entry] = self.numeric_viewer.dataView.ranges[old_entry] del self.numeric_viewer.dataView.ranges[old_entry] def update(self, others=()): self.map = {signal.entry: signal for signal in self.signals} for signal in others: if signal.entry not in self.map: self.map[signal.entry] = signal self.signals.append(signal) self.sort() def sort_column(self, ix): if ix != self.sorted_column_index: self.sorted_column_index = ix self.sort_reversed = False else: self.sort_reversed = not self.sort_reversed self.sort() def color_same_origin_signals(self, origin_uuid="", color=""): pass def data_changed(self): self.refresh_ui() def move_rows(self, rows, target_row): if target_row == -1: sigs = [self.signals.pop(row) for row in rows] self.signals.extend(sigs) else: sig = self.signals[target_row] sigs = [self.signals.pop(row) for row in rows] idx = self.signals.index(sig) for sig in sigs: self.signals.insert(idx, sig) self.data_changed() def refresh_ui(self): if self.numeric is not None and self.numeric.mode == "offline": numeric = self.numeric numeric._min = float("inf") numeric._max = -float("inf") for sig in self.signals: if sig.samples.size: numeric._min = min(self._min, sig.timestamps[0]) numeric._max = max(self._max, sig.timestamps[-1]) if numeric._min == float("inf"): numeric._min = numeric._max = 0 numeric._timestamp = numeric._min numeric.timestamp.setRange(numeric._min, numeric._max) numeric.min_t.setText(f"{numeric._min:.9f}s") numeric.max_t.setText(f"{numeric._max:.9f}s") numeric.set_timestamp(numeric._min) if self.numeric_viewer is not None: self.numeric_viewer.refresh_ui() def reorder(self, names): try: sigs = {sig.name: idx for idx, sig in enumerate(self.signals)} if len(sigs) == len(names): self.signals = [self.signals[sigs[name]] for name in names] self.data_changed() except: pass def sort(self): if not self.sorting_enabled: self.data_changed() return sorted_column_index = self.sorted_column_index if sorted_column_index == 0: self.signals = natsorted(self.signals, key=lambda x: x.name, reverse=self.sort_reversed) elif sorted_column_index in (1, 2): numeric = [] string = [] nones = [] for signal in self.signals: value = signal.get_value(sorted_column_index) if value is None: nones.append(signal) elif isinstance(value, (np.flexible, bytes)): string.append(signal) else: numeric.append(signal) self.signals = [ *sorted( numeric, key=lambda x: x.get_value(sorted_column_index), reverse=self.sort_reversed, ), *sorted( string, key=lambda x: x.get_value(sorted_column_index), reverse=self.sort_reversed, ), *natsorted(nones, key=lambda x: x.name, reverse=self.sort_reversed), ] elif sorted_column_index == 3: self.signals = natsorted(self.signals, key=lambda x: x.unit, reverse=self.sort_reversed) self.data_changed() def set_values(self, values=None): map_ = self.map if values: for entry, vals in values.items(): sig = map_[entry] sig.update_values(vals) if self.sorted_column_index in (1, 2): self.sort() else: self.data_changed() def shift_same_origin_signals(self, origin_uuid="", delta=0.0, absolute=False): pass def update_missing_signals(self, uuids=()): pass def reset(self): for sig in self.signals: sig.reset() self.data_changed() def __len__(self): return len(self.signals) def does_not_exist(self, entry, exists): self.map[entry].exists = exists def get_signal_value(self, signal, column): return signal.get_value(column) def set_format(self, fmt, rows): for row in rows: self.signals[row].format = fmt class OfflineBackEnd: def __init__(self, signals, numeric): super().__init__() self.timestamp = None self.signals = signals or [] self.map = None self.numeric = numeric self.sorted_column_index = 0 self.sorting_enabled = True self.sort_reversed = False self.numeric_viewer = None self.timebase = np.array([]) def update(self, others=()): self.map = {signal.entry: signal for signal in self.signals} for signal in others: if signal.entry not in self.map: self.map[signal.entry] = signal self.signals.append(signal) if self.signals: timestamps = {id(signal.signal.timestamps): signal.signal.timestamps for signal in self.signals} timestamps = list(timestamps.values()) self.timebase = np.unique(np.concatenate(timestamps)) else: self.timebase = np.array([]) self.sort() def sort_column(self, ix): if ix != self.sorted_column_index: self.sorted_column_index = ix self.sort_reversed = False else: self.sort_reversed = not self.sort_reversed self.sort() def data_changed(self): self.refresh_ui() def move_rows(self, rows, target_row): if target_row == -1: sigs = [self.signals.pop(row) for row in rows] self.signals.extend(sigs) else: sig = self.signals[target_row] sigs = [self.signals.pop(row) for row in rows] idx = self.signals.index(sig) for sig in sigs: self.signals.insert(idx, sig) self.data_changed() def refresh_ui(self): if self.numeric_viewer is not None: self.numeric_viewer.refresh_ui() def reorder(self, names): try: sigs = {sig.name: idx for idx, sig in enumerate(self.signals)} if len(sigs) == len(names): self.signals = [self.signals[sigs[name]] for name in names] self.data_changed() except: pass def sort(self): if not self.sorting_enabled: self.data_changed() return sorted_column_index = self.sorted_column_index if sorted_column_index == 0: self.signals = natsorted(self.signals, key=lambda x: (x.name, x.origin_uuid), reverse=self.sort_reversed) elif sorted_column_index in (1, 2): numeric = [] string = [] nones = [] for signal in self.signals: value = signal.get_value(sorted_column_index, self.timestamp) if value is None: nones.append(signal) elif isinstance(value, (np.flexible, bytes)): string.append(signal) else: numeric.append(signal) self.signals = [ *sorted( numeric, key=lambda x: x.get_value(sorted_column_index), reverse=self.sort_reversed, ), *sorted( string, key=lambda x: x.get_value(sorted_column_index), reverse=self.sort_reversed, ), *natsorted(nones, key=lambda x: x.name, reverse=self.sort_reversed), ] elif sorted_column_index == 3: self.signals = natsorted(self.signals, key=lambda x: x.unit, reverse=self.sort_reversed) self.data_changed() def color_same_origin_signals(self, origin_uuid="", color=""): for signal in self.signals: if signal.origin_uuid == origin_uuid: signal.color = color self.data_changed() def get_timestamp(self, stamp): max_idx = len(self.timebase) - 1 if max_idx == -1: return stamp idx = np.searchsorted(self.timebase, stamp) idx = min(idx, max_idx) return self.timebase[idx] def set_timestamp(self, stamp): self.timestamp = stamp if self.sorted_column_index in (1, 2): self.sort() else: self.data_changed() def shift_same_origin_signals(self, origin_uuid="", delta=0.0, absolute=False): for signal in self.signals: if signal.origin_uuid == origin_uuid: if not absolute: signal.signal.timestamps = signal.signal.timestamps + delta else: if len(signal.signal.timestamps): signal.signal.timestamps = signal.signal.timestamps - signal.signal.timestamps[0] + delta self.data_changed() def update_missing_signals(self, uuids=()): for signal in self.signals: if signal.origin_uuid not in uuids: signal.reset(exists=False) def reset(self): for sig in self.signals: sig.reset() self.data_changed() def __len__(self): return len(self.signals) def does_not_exist(self, entry, exists): self.map[entry].exists = exists def get_signal_value(self, signal, column): return signal.get_value(column, self.timestamp) def set_format(self, fmt, rows): for row in rows: self.signals[row].format = fmt class TableModel(QtCore.QAbstractTableModel): def __init__(self, parent, background_color, font_color): super().__init__(parent) self.numeric_viewer = parent self.backend = parent.backend self.view = None self.format = "Physical" self.float_precision = -1 self.background_color = background_color self.font_color = font_color def headerData(self, section, orientation, role=None): pass def columnCount(self, parent=None): return 5 def rowCount(self, parent=None): return len(self.backend) def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole): row = index.row() col = index.column() signal = self.backend.signals[row] cell = self.backend.get_signal_value(signal, col) match role: case QtCore.Qt.ItemDataRole.DisplayRole: if cell is None: return "●" elif isinstance(cell, (bytes, np.bytes_)): return cell.decode("utf-8", "replace") elif isinstance(cell, str): return cell elif isinstance(cell, (np.ndarray, np.record, np.recarray)): return str(cell[0]) else: if np.isnan(cell): return "NaN" else: return value_as_str(cell, signal.format, None, self.float_precision) case QtCore.Qt.ItemDataRole.BackgroundRole: channel_ranges = self.view.ranges[signal.entry] raw_cell = self.backend.get_signal_value(signal, 1) scaled_cell = self.backend.get_signal_value(signal, 2) try: scaled_value = float(scaled_cell) value = scaled_value except: scaled_value = str(scaled_cell) try: raw_value = float(raw_cell) value = raw_value except: value = scaled_value new_background_color, new_font_color = get_colors_using_ranges( value, ranges=channel_ranges, default_background_color=self.background_color, default_font_color=signal.color, ) return new_background_color if new_background_color != self.background_color else None case QtCore.Qt.ItemDataRole.ForegroundRole: channel_ranges = self.view.ranges[signal.entry] raw_cell = self.backend.get_signal_value(signal, 1) scaled_cell = self.backend.get_signal_value(signal, 2) try: scaled_value = float(scaled_cell) value = scaled_value except: scaled_value = str(scaled_cell) try: raw_value = float(raw_cell) value = raw_value except: value = scaled_value new_background_color, new_font_color = get_colors_using_ranges( value, ranges=channel_ranges, default_background_color=self.background_color, default_font_color=signal.color, ) return new_font_color case QtCore.Qt.ItemDataRole.TextAlignmentRole: if col: return int(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter) else: return int(QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter) case QtCore.Qt.ItemDataRole.DecorationRole: if col == 0: if not signal.exists: icon = utils.ERROR_ICON if icon is None: utils.ERROR_ICON = QtGui.QIcon() utils.ERROR_ICON.addPixmap( QtGui.QPixmap(":/error.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off, ) utils.NO_ERROR_ICON = QtGui.QIcon() icon = utils.ERROR_ICON else: icon = utils.NO_ERROR_ICON if icon is None: utils.ERROR_ICON = QtGui.QIcon() utils.ERROR_ICON.addPixmap( QtGui.QPixmap(":/error.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off, ) utils.NO_ERROR_ICON = QtGui.QIcon() icon = utils.NO_ERROR_ICON return icon elif col in (1, 2): has_ranges = bool(self.view.ranges.get(signal.entry, False)) if has_ranges: icon = utils.RANGE_INDICATOR_ICON if icon is None: utils.RANGE_INDICATOR_ICON = QtGui.QIcon() utils.RANGE_INDICATOR_ICON.addPixmap( QtGui.QPixmap(":/paint.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off, ) utils.NO_ERROR_ICON = QtGui.QIcon() utils.NO_ICON = QtGui.QIcon() icon = utils.RANGE_INDICATOR_ICON else: icon = utils.NO_ERROR_ICON if icon is None: utils.RANGE_INDICATOR_ICON = QtGui.QIcon() utils.RANGE_INDICATOR_ICON.addPixmap( QtGui.QPixmap(":/paint.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off, ) utils.NO_ERROR_ICON = QtGui.QIcon() utils.NO_ICON = QtGui.QIcon() icon = utils.NO_ERROR_ICON return icon case QtCore.Qt.ItemDataRole.ToolTipRole: if signal: return f"Origin = {signal.origin_uuid or 'unknown'}\nMDF = {signal.origin_mdf or 'unknown'}" def flags(self, index): return ( QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsDragEnabled | QtCore.Qt.ItemFlag.ItemIsDropEnabled ) def dropMimeData(self, data, action, row, column, parent): def moved_rows(data): rows = set() ds = QtCore.QDataStream(data.data("application/x-qabstractitemmodeldatalist")) while not ds.atEnd(): row = ds.readInt32() ds.readInt32() map_items = ds.readInt32() for i in range(map_items): ds.readInt32() ds.readQVariant() rows.add(row) return sorted(rows, reverse=True) self.backend.move_rows(moved_rows(data), parent.row()) def supportedDropActions(self) -> bool: return QtCore.Qt.DropAction.MoveAction | QtCore.Qt.DropAction.CopyAction def set_format(self, fmt, indexes): if fmt not in ("phys", "hex", "bin", "ascii"): return self.format = fmt rows = {index.row() for index in indexes} self.backend.set_format(fmt, rows) class TableView(QtWidgets.QTableView): add_channels_request = QtCore.Signal(list) def __init__(self, parent): super().__init__(parent) self.numeric_viewer = parent self.backend = parent.backend self.ranges = {} self._backgrund_color = self.palette().color(QtGui.QPalette.ColorRole.Window) self._font_color = self.palette().color(QtGui.QPalette.ColorRole.WindowText) model = TableModel(parent, self._backgrund_color, self._font_color) self.setModel(model) model.view = self self.horizontalHeader().hide() self.verticalHeader().hide() self.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) self.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) self.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection) self.setDragEnabled(True) self.setDropIndicatorShown(True) self.doubleClicked.connect(self.edit_ranges) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove) self.double_clicked_enabled = True def sizeHint(self): width = 2 * self.frameWidth() for i in range(self.model().columnCount()): width += self.columnWidth(i) height = 2 * self.frameWidth() height += 24 * self.model().rowCount() return QtCore.QSize(width, height) def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if key == QtCore.Qt.Key.Key_Delete and modifiers == QtCore.Qt.KeyboardModifier.NoModifier: event.accept() selected_items = {index.row() for index in self.selectedIndexes() if index.isValid()} for row in sorted(selected_items, reverse=True): signal = self.backend.signals.pop(row) del self.backend.map[signal.entry] self.backend.update() elif key == QtCore.Qt.Key.Key_R and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() selected_items = {index.row() for index in self.selectedIndexes() if index.isValid()} if selected_items: ranges = [] for row in selected_items: signal = self.backend.signals[row] if self.ranges[signal.entry]: ranges.extend(self.ranges[signal.entry]) dlg = RangeEditor( "", "", ranges=unique_ranges(ranges), parent=self, brush=True, ) dlg.exec_() if dlg.pressed_button == "apply": ranges = dlg.result for row in selected_items: signal = self.backend.signals[row] self.ranges[signal.entry] = copy_ranges(ranges) self.backend.update() elif ( modifiers == (QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier) and key == QtCore.Qt.Key.Key_C ): event.accept() selected_items = {index.row() for index in self.selectedIndexes() if index.isValid()} if not selected_items: return else: precision = self.model().float_precision row = list(selected_items)[0] signal = self.backend.signals[row] info = { "format": signal.format, "ranges": self.ranges[signal.entry], "type": "channel", "color": signal.color, "precision": precision, "ylink": False, "individual_axis": False, "y_range": signal.y_range, "origin_uuid": signal.origin_uuid, } QtWidgets.QApplication.instance().clipboard().setText(json.dumps(info, cls=ExtendedJsonEncoder)) elif ( modifiers == (QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier) and key == QtCore.Qt.Key.Key_V ): event.accept() info = QtWidgets.QApplication.instance().clipboard().text() selected_items = {index.row() for index in self.selectedIndexes() if index.isValid()} if not selected_items: return try: info = json.loads(info, cls=ExtendedJsonDecoder) except: print(format_exc()) else: for row in selected_items: signal = self.backend.signals[row] signal.format = info["format"] signal.color = fn.mkColor(info["color"]) signal.y_range = info["y_range"] signal.origin_uuid = info["origin_uuid"] self.ranges[signal.entry] = copy_ranges(info["ranges"]) self.backend.update() elif modifiers == QtCore.Qt.KeyboardModifier.NoModifier and key == QtCore.Qt.Key.Key_C: event.accept() selected_items = [index.row() for index in self.selectedIndexes() if index.isValid()] if selected_items: signal = self.backend.signals[selected_items[0]] color = signal.color color = QtWidgets.QColorDialog.getColor(color, parent=self) if color.isValid(): for row in set(selected_items): signal = self.backend.signals[row] signal.color = color elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_N: event.accept() selected_items = [] for index in self.selectedIndexes(): if not index.isValid(): continue if (row := index.row()) not in selected_items: selected_items.append(row) if not selected_items: return else: text = "\n".join(self.backend.signals[row].name for row in selected_items) QtWidgets.QApplication.instance().clipboard().setText(text) elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_C: event.accept() selected_items = [] for index in self.selectedIndexes(): if not index.isValid(): continue if (row := index.row()) not in selected_items: selected_items.append(row) data = [] numeric_mode = self.backend.numeric.mode for row in selected_items: signal = self.backend.signals[row] entry = signal.entry if numeric_mode == "online" else signal.signal.entry group_index, channel_index = entry info = { "name": signal.name, "computation": {}, "computed": False, "group_index": group_index, "channel_index": channel_index, "ranges": self.ranges[signal.entry], "origin_uuid": str(entry[0]) if numeric_mode == "online" else signal.signal.origin_uuid, "type": "channel", "uuid": os.urandom(6).hex(), "color": signal.color, } data.append(info) data = substitude_mime_uuids(data, None, force=True) QtWidgets.QApplication.instance().clipboard().setText(json.dumps(data, cls=ExtendedJsonEncoder)) elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_V: event.accept() try: data = QtWidgets.QApplication.instance().clipboard().text() data = json.loads(data, cls=ExtendedJsonDecoder) data = substitude_mime_uuids(data, random_uuid=True) self.add_channels_request.emit(data) except: pass else: super().keyPressEvent(event) def startDrag(self, supportedActions): indexes = self.selectedIndexes() if not self.backend.sorting_enabled: mime_data = self.model().mimeData(indexes) else: mime_data = QtCore.QMimeData() selected_items = [] for index in self.selectedIndexes(): if not index.isValid(): continue if (row := index.row()) not in selected_items: selected_items.append(row) data = [] numeric_mode = self.backend.numeric.mode for row in selected_items: signal = self.backend.signals[row] entry = signal.entry if numeric_mode == "online" else signal.signal.entry *_, group_index, channel_index = entry info = { "name": signal.name, "computation": {}, "computed": False, "group_index": group_index, "channel_index": channel_index, "ranges": self.ranges[signal.entry], "origin_uuid": str(entry[0]), "type": "channel", "uuid": os.urandom(6).hex(), "color": signal.color, } data.append(info) data = json.dumps(data, cls=ExtendedJsonEncoder).encode("utf-8") mime_data.setData("application/octet-stream-asammdf", QtCore.QByteArray(data)) drag = QtGui.QDrag(self) drag.setMimeData(mime_data) drag.exec(supportedActions) def dragEnterEvent(self, e): e.accept() def dropEvent(self, e): if e.source() is self: if e.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"): e.mimeData().removeFormat("application/octet-stream-asammdf") super().dropEvent(e) else: e.ignore() self.clearSelection() else: data = e.mimeData() if data.hasFormat("application/octet-stream-asammdf"): names = extract_mime_names(data) self.add_channels_request.emit(names) e.accept() else: e.ignore() def edit_ranges(self, index): if not self.double_clicked_enabled or not index.isValid(): return row = index.row() signal = self.backend.signals[row] dlg = RangeEditor(signal.name, signal.unit, self.ranges[signal.entry], parent=self, brush=True) dlg.exec_() if dlg.pressed_button == "apply": ranges = dlg.result self.ranges[signal.entry] = ranges def set_format(self, fmt): indexes = self.selectedIndexes() self.model().set_format(fmt, indexes) class HeaderModel(QtCore.QAbstractTableModel): def __init__(self, parent): super().__init__(parent) self.backend = parent.backend def columnCount(self, parent=None): return 5 def rowCount(self, parent=None): return 1 # 1? def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole): col = index.column() names = ["Name", "Raw", "Scaled", "Unit", "Origin"] if role == QtCore.Qt.ItemDataRole.DisplayRole: return names[col] elif role == QtCore.Qt.ItemDataRole.DecorationRole: if not self.backend.sorting_enabled or col != self.backend.sorted_column_index: return else: if self.backend.sort_reversed: icon = QtGui.QIcon(":/sort-descending.png") else: icon = QtGui.QIcon(":/sort-ascending.png") return icon elif role == QtCore.Qt.ItemDataRole.TextAlignmentRole: return QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter def headerData(self, section, orientation, role=None): pass class HeaderView(QtWidgets.QTableView): sorting_changed = QtCore.Signal(int) NameColumn = 0 RawColumn = 1 ScaledColumn = 2 UnitColumn = 3 OriginColumn = 4 def __init__(self, parent): super().__init__(parent) self.numeric_viewer = parent self.backend = parent.backend self.table = parent.dataView self.setModel(HeaderModel(parent)) self.padding = 10 self.header_cell_being_resized = None self.header_being_resized = False self.setMouseTracking(True) self.viewport().setMouseTracking(True) self.viewport().installEventFilter(self) self.setIconSize(QtCore.QSize(16, 16)) self.setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Maximum) ) self.setWordWrap(False) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) self.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) font = QtGui.QFont() font.setBold(True) self.setFont(font) self.horizontalHeader().hide() self.verticalHeader().hide() self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.resize(self.sizeHint()) self.columns_width = { self.RawColumn: self.columnWidth(self.RawColumn), self.ScaledColumn: self.columnWidth(self.ScaledColumn), self.UnitColumn: self.columnWidth(self.UnitColumn), self.OriginColumn: self.columnWidth(self.OriginColumn), } def all_columns_width(self): widths = [] for column in (self.NameColumn, self.RawColumn, self.ScaledColumn, self.UnitColumn, self.OriginColumn): if self.isColumnHidden(column): widths.append(self.columns_width.get(column, 100)) else: widths.append(self.columnWidth(column)) return widths def columns_visibility(self): return { "raw": not self.isColumnHidden(self.RawColumn), "scaled": not self.isColumnHidden(self.ScaledColumn), "unit": not self.isColumnHidden(self.UnitColumn), "origin": not self.isColumnHidden(self.OriginColumn), } def showEvent(self, a0: QtGui.QShowEvent) -> None: super().showEvent(a0) self.initial_size = self.size() def sorting(self): return { "sort_column": self.backend.sorted_column_index, "enabled": self.backend.sorting_enabled, "reversed": self.backend.sort_reversed, } def mouseDoubleClickEvent(self, event): point = event.pos() ix = self.indexAt(point) col = ix.column() if event.button() == QtCore.Qt.MouseButton.LeftButton and self.backend.sorting_enabled: self.backend.sort_column(col) self.sorting_changed.emit(col) else: super().mouseDoubleClickEvent(event) def eventFilter(self, object: QtCore.QObject, event: QtCore.QEvent): if event.type() in [ QtCore.QEvent.Type.MouseButtonPress, QtCore.QEvent.Type.MouseButtonRelease, QtCore.QEvent.Type.MouseButtonDblClick, QtCore.QEvent.Type.MouseMove, ]: return self.manage_resizing(object, event) return False def manage_resizing(self, object: QtCore.QObject, event: QtCore.QEvent): def over_header_cell_edge(mouse_position, margin=3): x = mouse_position if self.columnAt(x - margin) != self.columnAt(x + margin): if self.columnAt(x + margin) == 0: return None else: return self.columnAt(x - margin) else: return None mouse_position = event.pos().x() orthogonal_mouse_position = event.pos().y() if over_header_cell_edge(mouse_position) is not None: self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.SplitHCursor)) else: self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.ArrowCursor)) if event.type() == QtCore.QEvent.Type.MouseButtonPress: if over_header_cell_edge(mouse_position) is not None: self.header_cell_being_resized = over_header_cell_edge(mouse_position) return True else: self.header_cell_being_resized = None if event.type() == QtCore.QEvent.Type.MouseButtonRelease: self.header_cell_being_resized = None self.header_being_resized = False if event.type() == QtCore.QEvent.Type.MouseButtonDblClick: if over_header_cell_edge(mouse_position) is not None: header_index = over_header_cell_edge(mouse_position) self.numeric_viewer.auto_size_column(header_index) return True if event.type() == QtCore.QEvent.Type.MouseMove: if self.header_cell_being_resized is not None: size = mouse_position - self.columnViewportPosition(self.header_cell_being_resized) if size > 10: self.setColumnWidth(self.header_cell_being_resized, size) self.numeric_viewer.dataView.setColumnWidth(self.header_cell_being_resized, size) self.updateGeometry() self.numeric_viewer.dataView.updateGeometry() return True elif self.header_being_resized: size = orthogonal_mouse_position - self.geometry().top() self.setFixedHeight(max(size, self.initial_size.height())) self.updateGeometry() self.numeric_viewer.dataView.updateGeometry() return True return False def sizeHint(self): width = self.table.sizeHint().width() + self.verticalHeader().width() height = 16 + self.font().pointSize() + 2 * self.frameWidth() return QtCore.QSize(width, height) def toggle_column(self, checked, column): if not checked: self.columns_width[column] = self.columnWidth(column) self.setColumnHidden(column, not checked) self.numeric_viewer.dataView.setColumnHidden(column, not checked) if checked: self.setColumnWidth(column, self.columns_width[column]) self.numeric_viewer.dataView.setColumnWidth(column, self.columns_width[column]) self.updateGeometry() self.numeric_viewer.dataView.updateGeometry() def toggle_sorting(self, checked): self.backend.sorting_enabled = checked self.backend.sort() def minimumSizeHint(self): return QtCore.QSize(50, self.sizeHint().height()) class NumericViewer(QtWidgets.QWidget): def __init__(self, backend): super().__init__() backend.numeric_viewer = self self.backend = backend self.dataView = TableView(parent=self) self.columnHeader = HeaderView(parent=self) self.gridLayout = QtWidgets.QGridLayout() self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setSpacing(0) self.setLayout(self.gridLayout) self.dataView.horizontalScrollBar().valueChanged.connect(self.columnHeader.horizontalScrollBar().setValue) self.columnHeader.horizontalScrollBar().valueChanged.connect(self.dataView.horizontalScrollBar().setValue) # self.dataView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) # self.dataView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.gridLayout.addWidget(self.columnHeader, 0, 0) self.gridLayout.addWidget(self.dataView, 1, 0) # self.gridLayout.addWidget(self.dataView.horizontalScrollBar(), 2, 0, 1, 1) # self.gridLayout.addWidget(self.dataView.verticalScrollBar(), 1, 1, 1, 1) self.dataView.verticalScrollBar().setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Ignored) ) self.dataView.horizontalScrollBar().setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Ignored, QtWidgets.QSizePolicy.Policy.Fixed) ) self.gridLayout.setColumnStretch(0, 1) self.gridLayout.setRowStretch(1, 1) self.columnHeader.setSizePolicy(QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Maximum) self.default_row_height = 24 self.set_styles() for column_index in range(self.columnHeader.model().columnCount()): self.auto_size_column(column_index) self.columnHeader.horizontalHeader().setStretchLastSection(True) self.columnHeader.horizontalHeader().sectionResized.connect(self.update_horizontal_scroll) self.columnHeader.horizontalHeader().setMinimumSectionSize(1) self.dataView.horizontalHeader().setMinimumSectionSize(1) self.show() def set_styles(self): self.dataView.verticalHeader().setDefaultSectionSize(self.default_row_height) self.dataView.verticalHeader().setMinimumSectionSize(self.default_row_height) self.dataView.verticalHeader().setMaximumSectionSize(self.default_row_height) self.dataView.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Fixed) self.columnHeader.verticalHeader().setDefaultSectionSize(self.default_row_height) self.columnHeader.verticalHeader().setMinimumSectionSize(self.default_row_height) self.columnHeader.verticalHeader().setMaximumSectionSize(self.default_row_height) self.columnHeader.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Fixed) def auto_size_header(self): s = 0 for i in range(self.columnHeader.model().columnCount()): s += self.auto_size_column(i) delta = int((self.dataView.viewport().size().width() - s) // 4) if delta > 0: for i in range(self.columnHeader.model().columnCount()): self.auto_size_column(i, extra_padding=delta) # self.dataView.horizontalScrollBar().hide() else: self.dataView.horizontalScrollBar().show() def update_horizontal_scroll(self, *args): return s = 0 for i in range(self.columnHeader.model().columnCount()): s += self.dataView.columnWidth(i) + self.dataView.frameWidth() if self.dataView.viewport().size().width() < s: self.dataView.horizontalScrollBar().show() else: self.dataView.horizontalScrollBar().hide() def auto_size_column(self, column_index, extra_padding=0): width = 0 N = 100 for i in range(self.dataView.model().rowCount())[:N]: mi = self.dataView.model().index(i, column_index) text = self.dataView.model().data(mi) w = self.dataView.fontMetrics().boundingRect(text.replace("\0", " ")).width() width = max(width, w) for i in range(self.columnHeader.model().rowCount()): mi = self.columnHeader.model().index(i, column_index) text = self.columnHeader.model().data(mi) w = self.columnHeader.fontMetrics().boundingRect(text.replace("\0", " ")).width() width = max(width, w) padding = 20 width += padding + extra_padding self.columnHeader.setColumnWidth(column_index, width) self.dataView.setColumnWidth(column_index, self.columnHeader.columnWidth(column_index)) self.dataView.updateGeometry() self.columnHeader.updateGeometry() return width def scroll_to_column(self, column=0): index = self.dataView.model().index(0, column) self.dataView.scrollTo(index) self.columnHeader.selectColumn(column) self.columnHeader.on_selectionChanged(force=True) def refresh_ui(self): self.models = [] self.models += [ self.dataView.model(), self.columnHeader.model(), ] for model in self.models: model.beginResetModel() model.endResetModel() for view in [self.columnHeader, self.dataView]: view.updateGeometry() class Numeric(Ui_NumericDisplay, QtWidgets.QWidget): add_channels_request = QtCore.Signal(list) timestamp_changed_signal = QtCore.Signal(object, float) def __init__( self, channels=None, format=None, mode="offline", float_precision=None, owner=None, *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self.mode = mode self.owner = owner self.lock = Lock() self.visible_entries_modified = True self._settings = QtCore.QSettings() if mode == "offline": backend = OfflineBackEnd(None, self) else: backend = OnlineBackEnd(None, self) self.channels = NumericViewer(backend) self.backend = backend self.channels.dataView.ranges = {} self.main_layout.insertWidget(0, self.channels) self.main_layout.setStretch(0, 1) self.float_precision.addItems(["Full"] + [f"{i} decimals" for i in range(16)]) self.float_precision.currentIndexChanged.connect(self.set_float_precision) format = format or self._settings.value("numeric_format", "Physical") if format not in ("Physical", "Hex", "Binary", "Ascii"): format = "Physical" self._settings.setValue("numeric_format", format) if float_precision is None: float_precision = self._settings.value("numeric_float_precision", -1, type=int) self.float_precision.setCurrentIndex(float_precision + 1) self.timebase = np.array([]) self._timestamp = None if channels: self.add_new_channels(channels) self.channels.dataView.add_channels_request.connect(self.add_channels_request) self.channels.dataView.verticalScrollBar().valueChanged.connect(self.reset_visible_entries) self.channels.columnHeader.sorting_changed.connect(self.reset_visible_entries) self.channels.auto_size_header() self.double_clicked_enabled = True self.pattern = {} if self.mode == "offline": self.timestamp.valueChanged.connect(self._timestamp_changed) self.timestamp_slider.valueChanged.connect(self._timestamp_slider_changed) self._inhibit = False self.forward.clicked.connect(self.search_forward) self.backward.clicked.connect(self.search_backward) self.op.addItems([">", ">=", "<", "<=", "==", "!="]) self.time_group.setHidden(True) self.search_group.setHidden(True) self.toggle_controls_btn.clicked.connect(self.toggle_controls) else: self.toggle_controls_btn.setHidden(True) self.time_group.setHidden(True) self.search_group.setHidden(True) self.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.show_menu) def show_menu(self, position): count = len(self.channels.backend) header = self.channels.columnHeader menu = QtWidgets.QMenu() menu.addAction(f"{count} rows in the numeric window") menu.addSeparator() action = QtGui.QAction("Sorting", menu) action.setCheckable(True) action.setChecked(self.channels.backend.sorting_enabled) action.toggled.connect(header.toggle_sorting) menu.addAction(action) menu.addAction("Automatic set columns width") menu.addSeparator() action = QtGui.QAction("Raw Column", menu) action.setCheckable(True) action.setChecked(not header.isColumnHidden(header.RawColumn)) action.toggled.connect(partial(header.toggle_column, column=header.RawColumn)) menu.addAction(action) action = QtGui.QAction("Scaled Column", menu) action.setCheckable(True) action.setChecked(not header.isColumnHidden(header.ScaledColumn)) action.toggled.connect(partial(header.toggle_column, column=header.ScaledColumn)) menu.addAction(action) action = QtGui.QAction("Unit Column", menu) action.setCheckable(True) action.setChecked(not header.isColumnHidden(header.UnitColumn)) action.toggled.connect(partial(header.toggle_column, column=header.UnitColumn)) menu.addAction(action) action = QtGui.QAction("Origin Column", menu) action.setCheckable(True) action.setChecked(not header.isColumnHidden(header.OriginColumn)) action.toggled.connect(partial(header.toggle_column, column=header.OriginColumn)) menu.addAction(action) action = QtGui.QAction("Hide header and controls", menu) action.setCheckable(True) action.setChecked(header.isHidden()) menu.addAction(action) menu.addSeparator() submenu = QtWidgets.QMenu("Copy names") submenu.setIcon(QtGui.QIcon(":/copy.png")) action = QtGui.QAction("Copy names", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+N")) submenu.addAction(action) submenu.addAction("Copy names and values") menu.addMenu(submenu) submenu = QtWidgets.QMenu("Display structure") submenu.setIcon(QtGui.QIcon(":/structure.png")) action = QtGui.QAction("Copy display properties", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+Shift+C")) submenu.addAction(action) action = QtGui.QAction("Paste display properties", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+Shift+V")) submenu.addAction(action) action = QtGui.QAction("Copy channel structure", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+C")) submenu.addAction(action) action = QtGui.QAction("Paste channel structure", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+V")) submenu.addAction(action) menu.addMenu(submenu) menu.addSeparator() submenu = QtWidgets.QMenu("Edit") submenu.setIcon(QtGui.QIcon(":/edit.png")) action = QtGui.QAction("Set color", submenu) action.setShortcut(QtGui.QKeySequence("C")) submenu.addAction(action) submenu.addAction("Set random color") action = QtGui.QAction("Set color ranges", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+R")) submenu.addAction(action) menu.addMenu(submenu) menu.addSeparator() submenu = QtWidgets.QMenu("Display mode") action = QtGui.QAction("Ascii", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+T")) submenu.addAction(action) action = QtGui.QAction("Bin", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+B")) submenu.addAction(action) action = QtGui.QAction("Hex", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+H")) submenu.addAction(action) action = QtGui.QAction("Physical", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+P")) submenu.addAction(action) menu.addMenu(submenu) menu.addSeparator() action = QtGui.QAction("Delete", menu) action.setShortcut(QtGui.QKeySequence("Delete")) menu.addAction(action) action = menu.exec_(self.mapToGlobal(position)) if action is None: return action_text = action.text() if action_text == "Copy names": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_N, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) elif action_text == "Copy names and values": texts = [] precision = self.float_precision.currentIndex() - 1 t = self.timestamp.value() if precision == -1: t = str(t) else: template = f"{{:.{precision}f}}" t = template.format(t) selected_items = [] for index in self.channels.dataView.selectedIndexes(): if not index.isValid(): continue if (row := index.row()) not in selected_items: selected_items.append(row) model = self.channels.dataView.model() for row in selected_items: texts.append( ", ".join( [ model.data(model.createIndex(row, HeaderView.NameColumn)), t, f"{model.data(model.createIndex(row, HeaderView.RawColumn))}", f"{model.data(model.createIndex(row, HeaderView.ScaledColumn))}{model.data(model.createIndex(row, HeaderView.UnitColumn))}", ] ) ) QtWidgets.QApplication.instance().clipboard().setText("\n".join(texts)) elif action_text == "Copy channel structure": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier, ) self.keyPressEvent(event) elif action_text == "Paste channel structure": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_V, QtCore.Qt.KeyboardModifier.ControlModifier, ) self.keyPressEvent(event) elif action_text == "Copy display properties": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.keyPressEvent(event) elif action_text == "Paste display properties": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_V, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.keyPressEvent(event) elif action_text == "Copy display properties": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.keyPressEvent(event) elif action_text == "Paste display properties": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_V, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.keyPressEvent(event) elif action_text == "Automatic set columns width": header.numeric_viewer.auto_size_header() elif action_text == "Hide header and controls": if action.isChecked(): header.hide() self.controls.hide() else: header.show() self.controls.show() elif action_text == "Set color": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.NoModifier, ) self.keyPressEvent(event) elif action_text == "Set color ranges": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_R, QtCore.Qt.KeyboardModifier.ControlModifier, ) self.keyPressEvent(event) elif action_text == "Set random color": selected_items = {index.row() for index in self.channels.dataView.selectedIndexes() if index.isValid()} for row in selected_items: while True: rgb = os.urandom(3) if 100 <= sum(rgb) <= 650: break self.backend.signals[row].color = fn.mkColor(f"#{rgb.hex()}") elif action_text == "Ascii": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_T, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) elif action_text == "Bin": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_B, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) elif action_text == "Hex": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_H, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) elif action_text == "Physical": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_P, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) elif action_text == "Delete": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Delete, QtCore.Qt.KeyboardModifier.NoModifier ) self.keyPressEvent(event) def add_new_channels(self, channels, mime_data=None): if self.mode == "online": others = [] for index, sig in enumerate(channels): if sig is not None: entry = (sig.origin_uuid, sig.name) if getattr(sig, "color", None): color = sig.color or serde.COLORS[index % serde.COLORS_COUNT] else: color = serde.COLORS[index % serde.COLORS_COUNT] others.append( SignalOnline( name=sig.name, conversion=sig.conversion, entry=entry, unit=sig.unit, format=getattr(sig, "format", "phys"), color=color, ) ) sig.ranges = copy_ranges(sig.ranges) self.channels.dataView.ranges[entry] = sig.ranges else: others = [] for index, sig in enumerate(channels): if sig is not None: sig.flags &= ~sig.Flags.computed sig.computation = None exists = getattr(sig, "exists", True) ranges = sig.ranges sig = PlotSignal(sig, index=index, allow_trim=False, allow_nans=True) if sig.conversion: sig.phys_samples = sig.conversion.convert(sig.raw_samples, as_bytes=True) sig.entry = sig.origin_uuid, sig.group_index, sig.channel_index others.append( SignalOffline( signal=sig, exists=exists, ) ) self.channels.dataView.ranges[sig.entry] = ranges self.channels.backend.update(others) self.update_timebase() def reset(self): self.channels.backend.reset() self.channels.dataView.double_clicked_enabled = True def set_values(self, values=None): selection = self.channels.dataView.selectedIndexes() self.channels.backend.set_values(values) selection_model = self.channels.dataView.selectionModel() for index in selection: selection_model.select(index, QtCore.QItemSelectionModel.SelectionFlag.Select) def to_config(self): channels = [] pattern = self.pattern if not pattern: for signal in self.channels.backend.signals: channels.append( { "origin_uuid": str(signal.entry[0]), "name": signal.name, "ranges": self.channels.dataView.ranges[signal.entry], "format": signal.format, "color": signal.color, } ) config = { "format": "Physical", "mode": self.mode, "channels": channels, "pattern": pattern, "float_precision": self.float_precision.currentIndex() - 1, "header_sections_width": self.channels.columnHeader.all_columns_width(), "font_size": self.font().pointSize(), "columns_visibility": self.channels.columnHeader.columns_visibility(), "sorting": self.channels.columnHeader.sorting(), "header_and_controls_visible": not self.controls.isHidden(), } return config def does_not_exist(self, entry, exists=False): self.channels.backend.does_not_exist(entry, exists) def resizeEvent(self, event): super().resizeEvent(event) self.visible_entries_modified = True def reset_visible_entries(self, arg): self.visible_entries_modified = True def set_format(self, fmt): fmt = fmt.lower() if fmt in ("phys", "physical"): fmt_s = "Physical" fmt = "phys" elif fmt in ("bin", "binary"): fmt_s = "Bin" fmt = "bin" elif fmt == "hex": fmt_s = "Hex" elif fmt == "ascii": fmt_s = "Ascii" else: fmt_s = "Physical" fmt = "phys" self.channels.dataView.set_format(fmt) self._settings.setValue("numeric_format", fmt_s) self.channels.backend.data_changed() def set_float_precision(self, index): self._settings.setValue("numeric_float_precision", index - 1) self.channels.dataView.model().float_precision = index - 1 self.channels.backend.data_changed() def visible_entries(self): visible = set() if self.channels.backend.sorted_column_index in (1, 2): visible = set(self.channels.backend.map) else: rect = self.channels.dataView.viewport().rect() top = self.channels.dataView.indexAt(rect.topLeft()).row() bottom = self.channels.dataView.indexAt(rect.bottomLeft()).row() if top == -1: pass elif bottom == -1: visible = set(self.channels.backend.map) else: for row in range(top, bottom + 1): visible.add(self.channels.backend.signals[row].entry) self.visible_entries_modified = True return visible def _timestamp_changed(self, stamp): if not self._inhibit: self.set_timestamp(stamp, spinbox=True) def _timestamp_slider_changed(self, idx): if not self._inhibit: if not len(self.timebase): return self.set_timestamp(self.timebase[idx]) def set_timestamp(self, stamp=None, emit=True, spinbox=False): if stamp is None: if self._timestamp is None: if len(self.timebase): stamp = self.timebase[0] else: return else: stamp = self._timestamp if not len(self.timebase): return idx = np.searchsorted(self.timebase, stamp, side="right") - 1 new_stamp = self.timebase[idx] if spinbox: if new_stamp == self._timestamp and stamp > new_stamp: idx += 1 new_stamp = self.timebase[idx] self._timestamp = new_stamp self.channels.backend.set_timestamp(new_stamp) self._inhibit = True self.timestamp_slider.setValue(idx) self.timestamp.setValue(new_stamp) self._inhibit = False if emit: self.timestamp_changed_signal.emit(self, new_stamp) def search_forward(self): if self.op.currentIndex() < 0 or not self.target.text().strip() or not self.pattern_match.text().strip(): self.match.setText("invalid input values") return operator = self.op.currentText() if self.match_type.currentText() == "Wildcard": wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" text = self.pattern_match.text().strip() pattern = text.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") else: pattern = self.pattern_match.text().strip() if self.case_sensitivity.currentText() == "Case sensitive": pattern = re.compile(pattern) else: pattern = re.compile(f"(?i){pattern}") matches = [sig for sig in self.channels.backend.signals if pattern.fullmatch(sig.name)] mode = self.match_mode.currentText() if not matches: self.match.setText("the pattern does not match any channel name") return try: target = float(self.target.text().strip()) except: self.match.setText("the target must a numeric value") else: if target.is_integer(): target = int(target) start = self.timestamp.value() timestamp = None signal_name = "" for sig in matches: sig = sig.signal.cut(start=start) if mode == "Raw" or sig.conversion is None: samples = sig.raw_samples else: samples = sig.phys_samples op = getattr(samples, OPS[operator]) try: idx = np.argwhere(op(target)).flatten() if len(idx): if len(idx) == 1 or sig.timestamps[idx[0]] != start: timestamp_ = sig.timestamps[idx[0]] else: timestamp_ = sig.timestamps[idx[1]] if timestamp is None or timestamp_ < timestamp: timestamp = timestamp_ signal_name = sig.name except: continue if timestamp is not None: self.timestamp.setValue(timestamp) self.match.setText(f"condition found for {signal_name}") else: self.match.setText("condition not found") def search_backward(self): if self.op.currentIndex() < 0 or not self.target.text().strip() or not self.pattern_match.text().strip(): self.match.setText("invalid input values") return operator = self.op.currentText() if self.match_type.currentText() == "Wildcard": wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" text = self.pattern_match.text().strip() pattern = text.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") else: pattern = self.pattern_match.text().strip() if self.case_sensitivity.currentText() == "Case sensitive": pattern = re.compile(pattern) else: pattern = re.compile(f"(?i){pattern}") matches = [sig for sig in self.channels.backend.signals if pattern.fullmatch(sig.name)] mode = self.match_mode.currentText() if not matches: self.match.setText("the pattern does not match any channel name") return try: target = float(self.target.text().strip()) except: self.match.setText("the target must a numeric value") else: if target.is_integer(): target = int(target) stop = self.timestamp.value() timestamp = None signal_name = "" for sig in matches: sig = sig.signal.cut(stop=stop) if mode == "raw values" or sig.conversion is None: samples = sig.raw_samples[:-1] else: samples = sig.phys_samples[:-1] op = getattr(samples, OPS[operator]) try: idx = np.argwhere(op(target)).flatten() if len(idx): if len(idx) == 1 or sig.timestamps[idx[-1]] != stop: timestamp_ = sig.timestamps[idx[-1]] else: timestamp_ = sig.timestamps[idx[-2]] if timestamp is None or timestamp_ > timestamp: timestamp = timestamp_ signal_name = sig.name except: continue if timestamp is not None: self.timestamp.setValue(timestamp) self.match.setText(f"condition found for {signal_name}") else: self.match.setText("condition not found") def color_same_origin_signals(self, origin_uuid="", color=""): self.backend.shift_same_origin_signals(origin_uuid=origin_uuid, color=color) def shift_same_origin_signals(self, origin_uuid="", delta=0.0): self.backend.shift_same_origin_signals(origin_uuid=origin_uuid, delta=delta) def update_missing_signals(self, uuids=()): self.channels.backend.signals = [ signal for signal in self.channels.backend.signals if signal.origin_uuid in uuids ] self.channels.backend.data_changed() def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if ( key in (QtCore.Qt.Key.Key_H, QtCore.Qt.Key.Key_B, QtCore.Qt.Key.Key_P, QtCore.Qt.Key.Key_T) and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier ): event.accept() if key == QtCore.Qt.Key.Key_H: self.set_format("Hex") elif key == QtCore.Qt.Key.Key_B: self.set_format("Bin") elif key == QtCore.Qt.Key.Key_T: self.set_format("Ascii") else: self.set_format("Physical") elif ( key in ( QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right, QtCore.Qt.Key.Key_PageUp, QtCore.Qt.Key.Key_PageDown, QtCore.Qt.Key.Key_Home, QtCore.Qt.Key.Key_End, ) and modifiers == QtCore.Qt.KeyboardModifier.NoModifier and self.mode == "offline" ): self.timestamp_slider.keyPressEvent(event) elif ( key == QtCore.Qt.Key.Key_S and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and self.mode == "offline" ): event.accept() file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Save as measurement file", "", "MDF version 4 files (*.mf4)", ) if file_name: signals = [offline_signal.signal for offline_signal in self.channels.dataView.backend.signals] if signals: with mdf_module.MDF() as mdf: groups = {} for sig in signals: id_ = id(sig.timestamps) group_ = groups.setdefault(id_, []) group_.append(sig) for signals in groups.values(): sigs = [] for signal in signals: if ":" in signal.name: sig = signal.copy() sig.name = sig.name.split(":")[-1].strip() sigs.append(sig) else: sigs.append(signal) mdf.append(sigs, common_timebase=True) mdf.save(file_name, overwrite=True) elif key == QtCore.Qt.Key.Key_BracketLeft and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() self.decrease_font() elif key == QtCore.Qt.Key.Key_BracketRight and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() self.increase_font() elif ( key == QtCore.Qt.Key.Key_G and modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier and self.mode == "offline" ): event.accept() value, ok = QtWidgets.QInputDialog.getDouble( self, "Go to time stamp", "Time stamp", value=self.timestamp_slider.value(), decimals=9, ) if ok: self.set_timestamp(value) else: self.channels.dataView.keyPressEvent(event) def close(self): self.owner = None super().close() def decrease_font(self): font = self.font() size = font.pointSize() pos = bisect.bisect_left(FONT_SIZE, size) - 1 pos = max(pos, 0) new_size = FONT_SIZE[pos] self.set_font_size(new_size) def increase_font(self): font = self.font() size = font.pointSize() pos = bisect.bisect_right(FONT_SIZE, size) if pos == len(FONT_SIZE): pos -= 1 new_size = FONT_SIZE[pos] self.set_font_size(new_size) def set_font_size(self, size): self.hide() font = self.font() font.setPointSize(size) self.setFont(font) self.show() self.channels.default_row_height = 12 + size self.channels.set_styles() def toggle_controls(self, event=None): if self.toggle_controls_btn.text() == "Show controls": self.toggle_controls_btn.setText("Hide controls") self.time_group.setHidden(False) self.search_group.setHidden(False) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/up.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.toggle_controls_btn.setIcon(icon) else: self.toggle_controls_btn.setText("Show controls") self.time_group.setHidden(True) self.search_group.setHidden(True) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/down.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.toggle_controls_btn.setIcon(icon) def update_timebase(self): if self.mode == "online": return self.timebase = self.channels.backend.timebase count = len(self.timebase) if count: min_, max_ = self.timebase[0], self.timebase[-1] self.timestamp_slider.setRange(0, count - 1) if count >= 2: self.timestamp.setSingleStep(0.5 * np.min(np.diff(self.timebase))) else: min_, max_ = 0.0, 0.0 self.timestamp_slider.setRange(0, 0) self.timestamp.setRange(min_, max_) self.timestamp.setSingleStep(0.001) self.min_t.setText(f"{min_:.9f}s") self.max_t.setText(f"{max_:.9f}s") self.set_timestamp(emit=False) asammdf-8.5.1/src/asammdf/gui/widgets/plot.py000066400000000000000000007027731502633300400211320ustar00rootroot00000000000000import bisect from datetime import timedelta from functools import lru_cache, partial, reduce from math import ceil import os from pathlib import Path from tempfile import gettempdir from threading import Lock from time import perf_counter from traceback import format_exc from zipfile import ZIP_DEFLATED, ZipFile import dateutil.tz import numpy as np import pyqtgraph as pg from pyqtgraph import Qt import pyqtgraph.functions as fn from PySide6 import QtCore, QtGui, QtWidgets from ... import tool as Tool from ...blocks.conversion_utils import from_dict, to_dict from ...blocks.cutils import get_idx_with_edges, positions from ...blocks.utils import target_byte_order from ..dialogs.messagebox import MessageBox from ..utils import FONT_SIZE, value_as_str from .viewbox import ViewBoxWithCursor LOCAL_TIMEZONE = dateutil.tz.tzlocal() @lru_cache(maxsize=1024) def polygon_and_ndarray(size): polygon = QtGui.QPolygonF() polygon.resize(size) nbytes = 2 * len(polygon) * 8 ptr = polygon.data() if ptr is None: ptr = 0 buffer = Qt.shiboken.VoidPtr(ptr, nbytes, True) ndarray = np.frombuffer(buffer, np.double).reshape((-1, 2)) return polygon, ndarray def monkey_patch_pyqtgraph(): def _keys(self, styles): def getId(obj): try: return obj._id except AttributeError: obj._id = next(pg.graphicsItems.ScatterPlotItem.SymbolAtlas._idGenerator) return obj._id res = [ ( symbol if isinstance(symbol, (str, int)) else getId(symbol), size, getId(pen), getId(brush), ) for symbol, size, pen, brush in styles[:1] ] return res mkColor_factory = fn.mkColor mkBrush_factory = fn.mkBrush mkPen_factory = fn.mkPen def mkColor(*args): if isinstance(args[0], QtGui.QColor): return QtGui.QColor(args[0]) elif isinstance(args[0], QtGui.QBrush): return QtGui.QColor(args[0].color()) else: try: return cached_mkColor_factory(*args) except: return mkColor_factory(*args) @lru_cache(maxsize=2048) def cached_mkColor_factory(*args): return mkColor_factory(*args) def mkBrush(*args, **kwargs): if len(args) == 1 and isinstance(args[0], QtGui.QBrush): return args[0] try: return cached_mkBrush_factory(*args, **kwargs) except: return mkBrush_factory(*args, **kwargs) @lru_cache(maxsize=2048) def cached_mkBrush_factory(*args, **kargs): return mkBrush_factory(*args, **kargs) def mkPen(*args, **kwargs): try: return cached_mkPen_factory(*args, **kwargs) except: return mkPen_factory(*args, **kwargs) @lru_cache(maxsize=2048) def cached_mkPen_factory(*args, **kargs): return mkPen_factory(*args, **kargs) # speed-up monkey patches pg.graphicsItems.ScatterPlotItem.SymbolAtlas._keys = _keys pg.graphicsItems.ScatterPlotItem._USE_QRECT = False fn.mkBrush = mkBrush fn.mkColor = mkColor fn.mkPen = mkPen import asammdf.mdf as mdf_module from ...signal import Signal from .. import serde from ..dialogs.define_channel import DefineChannel from ..serde import extract_mime_names from ..utils import copy_ranges from .channel_stats import ChannelStats from .cursor import Bookmark, Cursor, Region from .dict_to_tree import ComputedChannelInfoWindow from .formated_axis import FormatedAxis from .tree import ChannelsTreeItem, ChannelsTreeWidget bin_ = bin HERE = Path(__file__).resolve().parent NOT_FOUND = 0xFFFFFFFF HONEYWELL_SECONDS_PER_CM = 0.1 float64 = np.float64 def simple_min(a, b): if b != b: # noqa: PLR0124 # b is NaN return a if a <= b: return a return b def simple_max(a, b): if b != b: # noqa: PLR0124 # b is NaN return a if a <= b: return b return a def get_descriptions_by_uuid(mime): descriptions = {} if mime: for item in mime: descriptions[item["uuid"]] = item if item.get("type", "channel") == "group": descriptions.update(get_descriptions_by_uuid(item["channels"])) return descriptions class PlotSignal(Signal): def __init__(self, signal, index=0, trim_info=None, duplication=1, allow_trim=True, allow_nans=False): super().__init__( signal.samples, signal.timestamps, signal.unit, signal.name, signal.conversion, signal.comment, signal.raw, signal.master_metadata, signal.display_names, signal.attachment, signal.source, signal.bit_count, invalidation_bits=signal.invalidation_bits, encoding=signal.encoding, flags=signal.flags, ) self._pos = self._plot_samples = self._plot_timestamps = None self._enable = False self.path = None self._dtype = "i1" self._buffer_size = 1 self.duplication = duplication self.uuid = getattr(signal, "uuid", os.urandom(6).hex()) self.origin_uuid = getattr(signal, "origin_uuid", os.urandom(6).hex()) self.origin_mdf = getattr(signal, "origin_mdf", "") self.group_index = getattr(signal, "group_index", NOT_FOUND) self.channel_index = getattr(signal, "channel_index", NOT_FOUND) self.precision = getattr(signal, "precision", 3) self._mode = "raw" self.enable = getattr(signal, "enable", False) self.format = getattr(signal, "format", "phys") self.individual_axis = False self.computation = signal.computation self.original_name = getattr(signal, "original_name", None) if hasattr(signal, "tooltip"): self.tooltip = signal.tooltip self.y_link = False self._y_range = None self.y_range = (0, -1) self.home = (0, -1) self.trim_info = None # take out NaN values samples = self.samples if samples.dtype.kind not in "SUV": if not allow_nans: nans = np.isnan(samples) if np.any(nans): self.samples = self.samples[~nans] self.timestamps = self.timestamps[~nans] if self.samples.dtype.byteorder not in target_byte_order: self.samples = self.samples.byteswap().view(self.samples.dtype.newbyteorder()) if self.timestamps.dtype.byteorder not in target_byte_order: self.timestamps = self.timestamps.byteswap().view(self.timestamps.dtype.n()) if self.timestamps.dtype != float64: self.timestamps = self.timestamps.astype(float64) self.text_conversion = None if self.conversion: samples = self.conversion.convert(self.samples, as_bytes=True) if samples.dtype.kind not in "SUV": if not allow_nans: nans = np.isnan(samples) if np.any(nans): self.raw_samples = self.samples[~nans] self.phys_samples = samples[~nans] self.timestamps = self.timestamps[~nans] self.samples = self.samples[~nans] else: self.raw_samples = self.samples self.phys_samples = samples else: self.raw_samples = self.samples self.phys_samples = samples else: self.text_conversion = self.conversion self.phys_samples = self.raw_samples = self.samples else: self.phys_samples = self.raw_samples = self.samples self.plot_samples = self.phys_samples self.plot_timestamps = self.timestamps self._stats = { "range": (0, -1), "range_stats": {}, "visible": (0, -1), "visible_stats": {}, "fmt": "", } if getattr(signal, "color", None): color = signal.color or serde.COLORS[index % serde.COLORS_COUNT] else: color = serde.COLORS[index % serde.COLORS_COUNT] self.color = fn.mkColor(color) self.color_name = self.color.name() self.pen = fn.mkPen(color=color, style=QtCore.Qt.PenStyle.SolidLine) self._min = None self._max = None self._rms = None self._avg = None self._std = None self._min_raw = None self._max_raw = None self._avg_raw = None self._rms_raw = None self._std_raw = None self._stats_available = False self._compute_basic_stats() self.mode = getattr(signal, "mode", "phys") if allow_trim: self.trim(*(trim_info or (None, None, 1900))) @property def avg(self): if not self._stats_available: self._compute_stats() return self._avg if self._mode == "phys" else self._avg_raw @avg.setter def avg(self, avg): self._avg = avg def _compute_basic_stats(self): self._stats_available = False if len(self.phys_samples): if self.raw_samples.dtype.kind in "SUV": self._min_raw = "" self._max_raw = "" self._avg_raw = "" self._rms_raw = "" self._std_raw = "" else: samples = self.raw_samples[np.isfinite(self.raw_samples)] if len(samples): self._min_raw = np.nanmin(samples) self._max_raw = np.nanmax(samples) else: self._min_raw = "n.a." self._max_raw = "n.a." if self.phys_samples is self.raw_samples: if self.phys_samples.dtype.kind in "SUV": self.is_string = True else: self.is_string = False self._min = self._min_raw self._max = self._max_raw else: if self.phys_samples.dtype.kind in "SUV": self.is_string = True self._min = "" self._max = "" self._avg = "" self._rms = "" self._std = "" else: self.is_string = False samples = self.phys_samples[np.isfinite(self.phys_samples)] if len(samples): self._min = np.nanmin(samples) self._max = np.nanmax(samples) else: self._min = "n.a." self._max = "n.a." self._avg = "n.a." self._rms = "n.a." self._std = "n.a." self.empty = False else: self.empty = True if self.phys_samples.dtype.kind in "SUV": self.is_string = True self._min = "" self._max = "" self._rms = "" self._avg = "" self._std = "" self._min_raw = "" self._max_raw = "" self._avg_raw = "" self._rms_raw = "" self._std_raw = "" else: self.is_string = False self._min = "n.a." self._max = "n.a." self._rms = "n.a." self._avg = "n.a." self._std = "n.a." self._min_raw = "n.a." self._max_raw = "n.a." self._avg_raw = "n.a." self._rms_raw = "n.a." self._std_raw = "n.a." def _compute_stats(self): if len(self.phys_samples): if self.raw_samples.dtype.kind in "SUV": self._min_raw = "" self._max_raw = "" self._avg_raw = "" self._rms_raw = "" self._std_raw = "" else: samples = self.raw_samples[np.isfinite(self.raw_samples)] if len(samples): self._avg_raw = np.mean(samples) self._rms_raw = np.sqrt(np.mean(np.square(samples))) self._std_raw = np.std(samples) else: self._min_raw = "n.a." self._max_raw = "n.a." self._avg_raw = "n.a." self._rms_raw = "n.a." self._std_raw = "n.a." if self.phys_samples is self.raw_samples: if self.phys_samples.dtype.kind in "SUV": self.is_string = True else: self.is_string = False self._min = self._min_raw self._max = self._max_raw self._avg = self._avg_raw self._rms = self._rms_raw self._std = self._std_raw else: if self.phys_samples.dtype.kind in "SUV": self.is_string = True self._min = "" self._max = "" self._avg = "" self._rms = "" self._std = "" else: self.is_string = False samples = self.phys_samples[np.isfinite(self.phys_samples)] if len(samples): self._avg = np.mean(samples) self._rms = np.sqrt(np.mean(np.square(samples))) self._std = np.std(samples) else: self._min = "n.a." self._max = "n.a." self._avg = "n.a." self._rms = "n.a." self._std = "n.a." self.empty = False else: self.empty = True if self.phys_samples.dtype.kind in "SUV": self.is_string = True self._min = "" self._max = "" self._rms = "" self._avg = "" self._std = "" self._min_raw = "" self._max_raw = "" self._avg_raw = "" self._rms_raw = "" self._std_raw = "" else: self.is_string = False self._min = "n.a." self._max = "n.a." self._rms = "n.a." self._avg = "n.a." self._std = "n.a." self._min_raw = "n.a." self._max_raw = "n.a." self._avg_raw = "n.a." self._rms_raw = "n.a." self._std_raw = "n.a." self._stats_available = True def cut(self, start=None, stop=None, include_ends=True, interpolation_mode=0): cut_sig = super().cut(start, stop, include_ends, interpolation_mode) cut_sig.group_index = self.group_index cut_sig.channel_index = self.channel_index cut_sig.color = self.color cut_sig.computation = self.computation cut_sig.precision = self.precision cut_sig.mdf_uuid = self.origin_uuid return PlotSignal(cut_sig, duplication=self.duplication) @property def enable(self): return self._enable @enable.setter def enable(self, enable_state): if self._enable != enable_state: self._enable = enable_state if enable_state: self._pos = np.empty(2 * self._buffer_size, dtype="i4") self._plot_samples = np.empty(2 * self._buffer_size, dtype=self._dtype) self._plot_timestamps = np.empty(2 * self._buffer_size, dtype="f8") else: self._pos = self._plot_samples = self._plot_timestamps = None def get_stats(self, cursor=None, region=None, view_region=None, precision=6): stats = {} sig = self x = sig.timestamps size = len(x) if precision == -1: precision = 16 format = sig.format if size: if sig.is_string: stats["overall_min"] = "" stats["overall_max"] = "" stats["overall_average"] = "" stats["overall_rms"] = "" stats["overall_std"] = "" stats["overall_start"] = x[0] stats["overall_stop"] = x[-1] stats["overall_gradient"] = "" stats["overall_integral"] = "" stats["overall_delta"] = "" stats["overall_start"] = x[0] stats["overall_stop"] = x[-1] stats["overall_delta_t"] = x[-1] - x[0] stats["unit"] = "" stats["color"] = sig.color stats["name"] = sig.name if cursor is not None: position = cursor stats["cursor_t"] = position raw_value, raw_kind, value, kind, _ = self.value_at_timestamp(position) stats["cursor_value"] = value_as_str(value, format, self.plot_samples.dtype, precision) else: stats["cursor_t"] = "" stats["cursor_value"] = "" if region: start, stop = region stats["selected_start"] = value_as_str(start, format, np.dtype("f8"), precision) stats["selected_stop"] = value_as_str(stop, format, np.dtype("f8"), precision) stats["selected_delta_t"] = value_as_str(stop - start, format, np.dtype("f8"), precision) rraw_value, raw_kind, value, kind, _ = self.value_at_timestamp(start) stats["selected_left"] = value_as_str(value, format, self.plot_samples.dtype, precision) raw_value, raw_kind, value, kind, _ = self.value_at_timestamp(stop) stats["selected_right"] = value_as_str(value, format, self.plot_samples.dtype, precision) else: stats["selected_start"] = "" stats["selected_stop"] = "" stats["selected_delta_t"] = "" stats["selected_left"] = "" stats["selected_right"] = "" stats["selected_min"] = "" stats["selected_max"] = "" stats["selected_average"] = "" stats["selected_rms"] = "" stats["selected_std"] = "" stats["selected_delta"] = "" stats["selected_gradient"] = "" stats["selected_integral"] = "" stats["visible_min"] = "" stats["visible_max"] = "" stats["visible_average"] = "" stats["visible_rms"] = "" stats["visible_delta"] = "" stats["visible_std"] = "" stats["visible_gradient"] = "" stats["visible_integral"] = "" else: if size == 1: stats["overall_gradient"] = 0 stats["overall_integral"] = 0 else: stats["overall_gradient"] = value_as_str( (float(sig.samples[-1]) - float(sig.samples[0])) / (sig.timestamps[-1] - sig.timestamps[0]), format, None, precision, ) stats["overall_integral"] = value_as_str( np.trapz(sig.samples, sig.timestamps), format, None, precision ) stats["overall_min"] = value_as_str(self.min, format, self.plot_samples.dtype, precision) stats["overall_max"] = value_as_str(self.max, format, self.plot_samples.dtype, precision) stats["overall_average"] = value_as_str(sig.avg, format, None, precision) stats["overall_rms"] = value_as_str(sig.rms, format, None, precision) stats["overall_std"] = value_as_str(sig.std, format, None, precision) stats["overall_start"] = value_as_str(sig.timestamps[0], format, np.dtype("f8"), precision) stats["overall_stop"] = value_as_str(sig.timestamps[-1], format, np.dtype("f8"), precision) stats["overall_delta"] = value_as_str( sig.samples[-1] - sig.samples[0], format, self.plot_samples.dtype, precision, ) stats["overall_delta_t"] = value_as_str(x[-1] - x[0], format, np.dtype("f8"), precision) stats["unit"] = sig.unit stats["color"] = sig.color stats["name"] = sig.name if cursor is not None: position = cursor stats["cursor_t"] = value_as_str(position, format, np.dtype("f8"), precision) raw_value, raw_kind, value, kind, _ = self.value_at_timestamp(position) stats["cursor_value"] = value_as_str(value, format, self.plot_samples.dtype, precision) else: stats["cursor_t"] = "" stats["cursor_value"] = "" if region: start, stop = region new_stats = {} new_stats["selected_start"] = value_as_str(start, format, np.dtype("f8"), precision) new_stats["selected_stop"] = value_as_str(stop, format, np.dtype("f8"), precision) new_stats["selected_delta_t"] = value_as_str(stop - start, format, np.dtype("f8"), precision) cut = sig.cut(start, stop) if self.mode == "raw": samples = cut.raw_samples else: samples = cut.phys_samples idx = np.isfinite(samples).ravel() samples = samples[idx] timestamps = cut.timestamps[idx] size = len(samples) if size: new_stats["selected_left"] = value_as_str( samples[0], format, self.plot_samples.dtype, precision ) new_stats["selected_right"] = value_as_str( samples[-1], format, self.plot_samples.dtype, precision ) new_stats["selected_min"] = value_as_str(np.nanmin(samples), format, samples.dtype, precision) new_stats["selected_max"] = value_as_str(np.nanmax(samples), format, samples.dtype, precision) new_stats["selected_average"] = value_as_str(np.mean(samples), format, None, precision) new_stats["selected_std"] = value_as_str(np.std(samples), format, None, precision) new_stats["selected_rms"] = value_as_str( np.sqrt(np.mean(np.square(samples))), format, None, precision, ) if samples.dtype.kind in "ui": new_stats["selected_delta"] = value_as_str( int(samples[-1]) - int(samples[0]), format, samples.dtype, precision, ) else: new_stats["selected_delta"] = value_as_str( samples[-1] - samples[0], format, samples.dtype, precision, ) if size == 1: new_stats["selected_gradient"] = 0 new_stats["selected_integral"] = 0 else: new_stats["selected_gradient"] = value_as_str( (float(samples[-1]) - float(samples[0])) / (timestamps[-1] - timestamps[0]), format, None, precision, ) new_stats["selected_integral"] = value_as_str( np.trapz(samples, timestamps), format, None, precision ) else: new_stats["selected_min"] = "n.a." new_stats["selected_max"] = "n.a." new_stats["selected_average"] = "n.a." new_stats["selected_left"] = "n.a." new_stats["selected_right"] = "n.a." new_stats["selected_rms"] = "n.a." new_stats["selected_std"] = "n.a." new_stats["selected_gradient"] = "n.a." new_stats["selected_integral"] = "n.a." new_stats["selected_delta"] = "n.a." sig._stats["range"] = (start, stop) sig._stats["range_stats"] = new_stats stats.update(sig._stats["range_stats"]) else: stats["selected_start"] = "" stats["selected_stop"] = "" stats["selected_delta_t"] = "" stats["selected_left"] = "" stats["selected_right"] = "" stats["selected_min"] = "" stats["selected_max"] = "" stats["selected_average"] = "" stats["selected_rms"] = "" stats["selected_std"] = "" stats["selected_delta"] = "" stats["selected_gradient"] = "" stats["selected_integral"] = "" start, stop = view_region new_stats = {} new_stats["visible_start"] = value_as_str(start, format, np.dtype("f8"), precision) new_stats["visible_stop"] = value_as_str(stop, format, np.dtype("f8"), precision) new_stats["visible_delta_t"] = value_as_str(stop - start, format, np.dtype("f8"), precision) cut = sig.cut(start, stop) if self.mode == "raw": samples = cut.raw_samples else: samples = cut.phys_samples idx = np.isfinite(samples).ravel() samples = samples[idx] timestamps = cut.timestamps[idx] size = len(samples) if size: kind = samples.dtype.kind new_stats["visible_min"] = value_as_str(np.nanmin(samples), format, samples.dtype, precision) new_stats["visible_max"] = value_as_str(np.nanmax(samples), format, samples.dtype, precision) new_stats["visible_average"] = value_as_str(np.mean(samples), format, None, precision) new_stats["visible_std"] = value_as_str(np.std(samples), format, None, precision) new_stats["visible_rms"] = value_as_str( np.sqrt(np.mean(np.square(samples))), format, None, precision ) if kind in "ui": new_stats["visible_delta"] = value_as_str( int(cut.samples[-1]) - int(cut.samples[0]), format, samples.dtype, precision, ) else: new_stats["visible_delta"] = value_as_str( cut.samples[-1] - cut.samples[0], format, samples.dtype, precision, ) if size == 1: new_stats["visible_gradient"] = 0 new_stats["visible_integral"] = 0 else: new_stats["visible_gradient"] = value_as_str( (float(samples[-1]) - float(samples[0])) / (timestamps[-1] - timestamps[0]), format, None, precision, ) new_stats["visible_integral"] = value_as_str( np.trapz(samples, timestamps), format, None, precision ) else: new_stats["visible_min"] = "n.a." new_stats["visible_max"] = "n.a." new_stats["visible_average"] = "n.a." new_stats["visible_rms"] = "n.a." new_stats["visible_std"] = "n.a." new_stats["visible_delta"] = "n.a." new_stats["visible_gradient"] = "n.a." new_stats["visible_integral"] = "n.a." sig._stats["visible"] = (start, stop) sig._stats["visible_stats"] = new_stats stats.update(sig._stats["visible_stats"]) else: stats["overall_min"] = "n.a." stats["overall_max"] = "n.a." stats["overall_average"] = "n.a." stats["overall_rms"] = "n.a." stats["overall_std"] = "n.a." stats["overall_start"] = "n.a." stats["overall_stop"] = "n.a." stats["overall_gradient"] = "n.a." stats["overall_integral"] = "n.a." stats["overall_delta"] = "n.a." stats["overall_delta_t"] = "n.a." stats["unit"] = sig.unit stats["color"] = sig.color stats["name"] = sig.name if cursor is not None: position = cursor stats["cursor_t"] = value_as_str(position, format, np.dtype("f8"), precision) stats["cursor_value"] = "n.a." else: stats["cursor_t"] = "" stats["cursor_value"] = "" if region is not None: start, stop = region stats["selected_start"] = value_as_str(start, format, np.dtype("f8"), precision) stats["selected_stop"] = value_as_str(stop, format, np.dtype("f8"), precision) stats["selected_delta_t"] = value_as_str(stop - start, format, np.dtype("f8"), precision) stats["selected_min"] = "n.a." stats["selected_max"] = "n.a." stats["selected_left"] = "n.a." stats["selected_right"] = "n.a." stats["selected_average"] = "n.a." stats["selected_rms"] = "n.a." stats["selected_std"] = "n.a." stats["selected_delta"] = "n.a." stats["selected_gradient"] = "n.a." stats["selected_integral"] = "n.a." else: stats["selected_start"] = "" stats["selected_stop"] = "" stats["selected_delta_t"] = "" stats["selected_min"] = "" stats["selected_max"] = "" stats["selected_left"] = "" stats["selected_right"] = "" stats["selected_average"] = "n.a." stats["selected_rms"] = "n.a." stats["selected_std"] = "n.a." stats["selected_delta"] = "" stats["selected_gradient"] = "" stats["selected_integral"] = "" start, stop = view_region stats["visible_start"] = value_as_str(start, format, np.dtype("f8"), precision) stats["visible_stop"] = value_as_str(stop, format, np.dtype("f8"), precision) stats["visible_delta_t"] = value_as_str(stop - start, format, np.dtype("f8"), precision) stats["visible_min"] = "n.a." stats["visible_max"] = "n.a." stats["visible_average"] = "n.a." stats["visible_rms"] = "n.a." stats["visible_std"] = "n.a." stats["visible_delta"] = "n.a." stats["visible_gradient"] = "n.a." stats["visible_integral"] = "n.a." stats["region"] = region is not None stats["color"] = self.color_name return stats @property def max(self): if self._mode == "phys": _max = self._max samples = self.phys_samples else: _max = self._max_raw samples = self.raw_samples if _max is not None: return _max else: if samples.dtype.kind in "SUV": return "" else: if len(samples): return np.nanmax(samples) else: return "n.a." @property def min(self): if self._mode == "phys": _min = self._min samples = self.phys_samples else: _min = self._min_raw samples = self.raw_samples if _min is not None: return _min else: if samples.dtype.kind in "SUV": return "" else: if len(samples): return np.nanmin(samples) else: return "n.a." @property def mode(self): return self._mode @mode.setter def mode(self, mode): if mode != self._mode: self._mode = mode if mode == "raw": self.plot_samples = self.raw_samples self.plot_timestamps = self.timestamps style = QtCore.Qt.PenStyle.DashLine else: self.plot_samples = self.phys_samples self.plot_timestamps = self.timestamps style = QtCore.Qt.PenStyle.SolidLine self.pen = fn.mkPen(color=self.color, style=style) if self.plot_samples.dtype.kind in "SUV": self.is_string = True else: self.is_string = False @property def rms(self): if not self._stats_available: self._compute_stats() return self._rms if self.mode == "phys" else self._rms_raw @rms.setter def rms(self, rms): self._rms = rms def set_color(self, color): self.color = color if self.mode == "raw": style = QtCore.Qt.PenStyle.DashLine else: style = QtCore.Qt.PenStyle.SolidLine self.pen = fn.mkPen(color=color, style=style) def set_home(self, y_range=None): self.home = y_range or self.y_range @property def std(self): if not self._stats_available: self._compute_stats() return self._std if self.mode == "phys" else self._std_raw def trim_c(self, start=None, stop=None, width=1, force=False): trim_info = (start, stop, width) if not force and self.trim_info == trim_info: return None self.trim_info = trim_info sig_timestamps = self.timestamps dim = sig_timestamps.size if dim: if start is None: start = sig_timestamps[0] if stop is None: stop = sig_timestamps[-1] if start > stop: start, stop = stop, start if self._mode == "raw": signal_samples = self.raw_samples else: signal_samples = self.phys_samples start_t_sig, stop_t_sig = ( sig_timestamps[0], sig_timestamps[-1], ) if start > stop_t_sig or stop < start_t_sig: self.plot_samples = signal_samples[:0] self.plot_timestamps = sig_timestamps[:0] pos = [] else: start_t = simple_max(start, start_t_sig) stop_t = simple_min(stop, stop_t_sig) if start_t == start_t_sig: start_ = 0 else: start_ = np.searchsorted(sig_timestamps, start_t, side="right") if stop_t == stop_t_sig: stop_ = dim else: stop_ = np.searchsorted(sig_timestamps, stop_t, side="right") if stop_ == start_: visible_duplication = 0 else: visible = ceil((stop_t - start_t) / (stop - start) * width) if visible: visible_duplication = (stop_ - start_) // abs(visible) else: visible_duplication = 0 if visible_duplication > self.duplication: samples = signal_samples[start_:stop_] timestamps = sig_timestamps[start_:stop_] count, rest = divmod(samples.size, visible_duplication) if rest: count += 1 else: rest = visible_duplication steps = visible_duplication if count > self._buffer_size: self._buffer_size = count self._pos = np.empty(2 * self._buffer_size, dtype="i4") self._plot_samples = np.empty(2 * self._buffer_size, dtype=self._dtype) self._plot_timestamps = np.empty(2 * self._buffer_size, dtype="f8") if samples.dtype.kind == "f" and samples.itemsize == 2: samples = samples.astype("f8") self._dtype = "f8" if samples.dtype != self._plot_samples.dtype: self._plot_samples = np.empty(2 * self._buffer_size, dtype=samples.dtype) self._dtype = samples.dtype if samples.flags.c_contiguous and timestamps.flags.c_contiguous: positions( samples, timestamps, self._plot_samples, self._plot_timestamps, self._pos, steps, count, rest, samples.dtype.kind, samples.itemsize, ) else: positions( samples.copy(), timestamps, self._plot_samples, self._plot_timestamps, self._pos, steps, count, rest, samples.dtype.kind, samples.itemsize, ) size = 2 * count pos = self._pos[:size] self.plot_samples = self._plot_samples[:size] self.plot_timestamps = self._plot_timestamps[:size] else: start_ = simple_min(simple_max(0, start_ - 2), dim - 1) stop_ = simple_min(stop_ + 2, dim) if start_ == 0 and stop_ == dim: self.plot_samples = signal_samples self.plot_timestamps = sig_timestamps pos = None else: self.plot_samples = signal_samples[start_:stop_] self.plot_timestamps = sig_timestamps[start_:stop_] pos = np.arange(start_, stop_) else: pos = None return pos def trim_python(self, start=None, stop=None, width=1900, force=False): trim_info = (start, stop, width) if not force and self.trim_info == trim_info: return None self.trim_info = trim_info sig = self dim = len(sig.timestamps) if dim: if start is None: start = sig.timestamps[0] if stop is None: stop = sig.timestamps[-1] if self.mode == "raw": signal_samples = self.raw_samples else: signal_samples = self.phys_samples start_t_sig, stop_t_sig = ( sig.timestamps[0], sig.timestamps[-1], ) if start > stop_t_sig or stop < start_t_sig: sig.plot_samples = signal_samples[:0] sig.plot_timestamps = sig.timestamps[:0] pos = [] else: start_t = max(start, start_t_sig) stop_t = min(stop, stop_t_sig) if start_t == start_t_sig: start_ = 0 else: start_ = np.searchsorted(sig.timestamps, start_t, side="right") if stop_t == stop_t_sig: stop_ = dim else: stop_ = np.searchsorted(sig.timestamps, stop_t, side="right") try: visible = abs(int((stop_t - start_t) / (stop - start) * width)) if visible: visible_duplication = abs(stop_ - start_) // visible else: visible_duplication = 0 except: visible_duplication = 0 while visible_duplication > self.duplication: rows = (stop_ - start_) // visible_duplication stop_2 = start_ + rows * visible_duplication samples = signal_samples[start_:stop_2].reshape(rows, visible_duplication) try: pos_max = samples.argmax(axis=1) pos_min = samples.argmin(axis=1) break except: try: pos_max = np.nanargmax(samples, axis=1) pos_min = np.nanargmin(samples, axis=1) break except ValueError: visible_duplication -= 1 if visible_duplication > self.duplication: pos = np.dstack([pos_min, pos_max])[0] pos.sort() # pos = np.sort(pos) offsets = np.arange(rows) * visible_duplication pos = (pos.T + offsets).T.ravel() samples = signal_samples[start_:stop_2][pos] timestamps = sig.timestamps[start_:stop_2][pos] if stop_2 != stop_: samples_ = signal_samples[stop_2:stop_] try: pos_max = samples_.argmax() pos_min = samples_.argmin() except: pos_max = np.nanargmax(samples_) pos_min = np.nanargmin(samples_) pos2 = [pos_min, pos_max] if pos_min < pos_max else [pos_max, pos_min] _size = len(pos) samples_ = signal_samples[stop_2:stop_][pos2] timestamps_ = sig.timestamps[stop_2:stop_][pos2] samples = np.concatenate((samples, samples_)) timestamps = np.concatenate((timestamps, timestamps_)) pos2 = p1, p2 = [min(e + stop_2, dim - 1) for e in pos2] # pos = np.concatenate([pos, pos2]) new_pos = np.empty(_size + 2, dtype=pos.dtype) new_pos[:_size] = pos new_pos[_size] = p1 new_pos[_size + 1] = p2 pos = new_pos sig.plot_samples = samples sig.plot_timestamps = timestamps else: start_ = min(max(0, start_ - 2), dim - 1) stop_ = min(stop_ + 2, dim) if start_ == 0 and stop_ == dim: sig.plot_samples = signal_samples sig.plot_timestamps = sig.timestamps pos = None else: sig.plot_samples = signal_samples[start_:stop_] sig.plot_timestamps = sig.timestamps[start_:stop_] pos = np.arange(start_, stop_) else: pos = None return pos def trim(self, start=None, stop=None, width=1900, force=False): if self._enable: if width > self._buffer_size: width = ceil(width) self._buffer_size = width self._pos = np.empty(2 * self._buffer_size, dtype="i4") self._plot_samples = np.empty(2 * self._buffer_size, dtype=self._dtype) self._plot_timestamps = np.empty(2 * self._buffer_size, dtype="f8") self.path = None try: return self.trim_c(start, stop, width, force) except: print(format_exc()) return self.trim_python(start, stop, width, force) def value_at_index(self, index): if self.mode == "raw": kind = self.raw_samples.dtype.kind else: kind = self.phys_samples.dtype.kind raw_kind = self.raw_samples.dtype.kind size = len(self) if index is None or size == 0: value = raw_value = "n.a." else: if index >= size: index = size - 1 if self.mode == "raw": value = self.raw_samples[index] else: value = self.phys_samples[index] raw_value = self.raw_samples[index] match kind: case "S": try: value = value.decode("utf-8").strip(" \r\n\t\v\0") except: value = value.decode("latin-1").strip(" \r\n\t\v\0") value = value or "" case "f": value = float(value) case _: value = int(value) match raw_kind: case "S": try: raw_value = raw_value.decode("utf-8").strip(" \r\n\t\v\0") except: raw_value = raw_value.decode("latin-1").strip(" \r\n\t\v\0") raw_value = raw_value or "" case "f": raw_value = float(raw_value) case _: raw_value = int(raw_value) return raw_value, raw_kind, value, kind, self.format def value_at_timestamp(self, timestamp, numeric=False, strict_timebase=True): if self.mode == "raw": kind = self.raw_samples.dtype.kind samples = self.raw_samples else: kind = self.phys_samples.dtype.kind samples = self.phys_samples raw_kind = self.raw_samples.dtype.kind if numeric and kind not in "uif": samples = self.raw_samples kind = self.raw_samples.dtype.kind if self.samples.size == 0 or (strict_timebase and not (self.timestamps[0] <= timestamp <= self.timestamps[-1])): value = "n.a." raw_value = "n.a." else: if timestamp > self.timestamps[-1]: index = -1 elif timestamp < self.timestamps[0]: index = 0 else: index = np.searchsorted(self.timestamps, timestamp, side="left") value = samples[index] raw_value = self.raw_samples[index] match kind: case "S": try: value = value.decode("utf-8", errors="replace").strip(" \r\n\t\v\0") except: value = value.decode("latin-1", errors="replace").strip(" \r\n\t\v\0") value = value or "" case "f": value = float(value) case _: value = int(value) match raw_kind: case "S": try: raw_value = raw_value.decode("utf-8", errors="replace").strip(" \r\n\t\v\0") except: raw_value = raw_value.decode("latin-1", errors="replace").strip(" \r\n\t\v\0") raw_value = raw_value or "" case "f": raw_value = float(raw_value) case _: raw_value = int(raw_value) return raw_value, raw_kind, value, kind, self.format def timestamp_of_next_different_value(self, timestamp, mode="higher", previous=False): if self.mode == "raw": kind = self.raw_samples.dtype.kind samples = self.raw_samples else: kind = self.phys_samples.dtype.kind samples = self.phys_samples if kind not in "uif": samples = self.raw_samples kind = self.raw_samples.dtype.kind if kind == "S" or self.samples.size == 0 or timestamp < self.timestamps[0] or timestamp > self.timestamps[-1]: new_timestamp = timestamp else: index = np.searchsorted(self.timestamps, timestamp, side="left") value = samples[index] match mode: case "higher": idx = np.argwhere(samples > value).ravel() case "lower": idx = np.argwhere(samples < value).ravel() case _: idx = np.argwhere(samples != value).ravel() if previous: idx = idx[idx < index] else: idx = idx[idx > index] if len(idx) == 0: new_timestamp = timestamp else: if previous: new_timestamp = self.timestamps[idx[-1]] else: new_timestamp = self.timestamps[idx[0]] return new_timestamp @property def y_range(self): return self._y_range @y_range.setter def y_range(self, value): self.path = None self._y_range = value from .signal_scale import ScaleDialog class Plot(QtWidgets.QWidget): add_channels_request = QtCore.Signal(list) close_request = QtCore.Signal() clicked = QtCore.Signal() cursor_moved_signal = QtCore.Signal(object, float) cursor_removed_signal = QtCore.Signal(object) edit_channel_request = QtCore.Signal(object, object) region_moved_signal = QtCore.Signal(object, list) region_removed_signal = QtCore.Signal(object) show_overlapping_alias = QtCore.Signal(object) show_properties = QtCore.Signal(object) splitter_moved = QtCore.Signal(object, int) pattern_group_added = QtCore.Signal(object, object) verify_bookmarks = QtCore.Signal(list, object) x_range_changed_signal = QtCore.Signal(object, object) item_double_click_handling = "enable/disable" dynamic_columns_width = True mouse_mode = "pan" def __init__( self, signals, with_dots=False, origin=None, mdf=None, line_interconnect="line", hide_missing_channels=False, hide_disabled_channels=False, x_axis="time", allow_cursor=True, show_cursor_circle=True, show_cursor_horizontal_line=True, cursor_line_width=1, cursor_color="#ffffff", region_values_display_mode="delta", owner=None, enable_zoom_history=True, *args, **kwargs, ): events = kwargs.pop("events", None) self.owner = owner self.enable_zoom_history = enable_zoom_history super().__init__(*args, **kwargs) self.closed = False self.line_interconnect = line_interconnect self.setContentsMargins(0, 0, 0, 0) self.pattern = {} self.mdf = mdf self._settings = QtCore.QSettings() self.x_name = "t" if x_axis == "time" else "f" self.x_unit = "s" if x_axis == "time" else "Hz" self.info_uuid = None self._can_switch_mode = True self._inhibit_x_range_changed_signal = False self._inhibit_timestamp_signals = False self._inhibit_timestamp_signals_timer = QtCore.QTimer() self._inhibit_timestamp_signals_timer.setSingleShot(True) self._inhibit_timestamp_signals_timer.timeout.connect(self._inhibit_timestamp_handler) self.can_edit_ranges = True self.region_values_display_mode = region_values_display_mode main_layout = QtWidgets.QVBoxLayout(self) main_layout.setSpacing(1) main_layout.setContentsMargins(1, 1, 1, 1) vbox = QtWidgets.QVBoxLayout() vbox.setSpacing(1) vbox.setContentsMargins(1, 1, 1, 1) widget = QtWidgets.QWidget() self.channel_selection = ChannelsTreeWidget( hide_missing_channels=hide_missing_channels, hide_disabled_channels=hide_disabled_channels, parent=self, plot=self, ) widget.setLayout(vbox) self.focused_mode = False self.show_bookmarks = True self.splitter = QtWidgets.QSplitter() self.splitter.addWidget(widget) self.splitter.setOpaqueResize(False) self.plot = PlotGraphics( with_dots=with_dots, line_interconnect=self.line_interconnect, parent=self, events=events, origin=origin, mdf=self.mdf, x_axis=x_axis, allow_cursor=allow_cursor, plot_parent=self, ) self.plot.zoom_changed.connect(self.zoom_changed) if self.plot.cursor1 is not None: self.plot.cursor1.show_circle = show_cursor_circle self.plot.cursor1.show_horizontal_line = show_cursor_horizontal_line self.plot.cursor1.line_width = cursor_line_width self.plot.cursor1.color = cursor_color self.lock = self.plot.lock self.cursor_info = CursorInfo( precision=QtCore.QSettings().value("plot_cursor_precision", 6), unit=self.x_unit, name=self.x_name, plot=self.plot, ) hbox = QtWidgets.QHBoxLayout() hbox.setSpacing(1) hbox.setContentsMargins(1, 1, 1, 1) vbox.addLayout(hbox) btn = QtWidgets.QPushButton("Cmd") menu = QtWidgets.QMenu() icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/home.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) menu.addAction( icon, "Home", lambda: self.plot.keyPressEvent( QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_W, QtCore.Qt.KeyboardModifier.NoModifier, ) ), ) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/axis.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) menu.addAction( icon, "Honeywell", lambda: self.plot.keyPressEvent( QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_H, QtCore.Qt.KeyboardModifier.NoModifier, ) ), ) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/fit.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) menu.addAction( icon, "Fit", lambda: self.plot.keyPressEvent( QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_F, QtCore.Qt.KeyboardModifier.NoModifier, ) ), ) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/stack.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) menu.addAction( icon, "Stack", lambda: self.plot.keyPressEvent( QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_S, QtCore.Qt.KeyboardModifier.NoModifier, ) ), ) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/increase-font.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) menu.addAction(icon, "Increase font", self.increase_font) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/decrease-font.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) menu.addAction(icon, "Decrease font", self.decrease_font) btn.setMenu(menu) hbox.addWidget(btn) btn.menu() btn = QtWidgets.QPushButton("") btn.clicked.connect( lambda x: self.plot.keyPressEvent( QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_I, QtCore.Qt.KeyboardModifier.NoModifier, ) ) ) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/zoom-in.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Zoom in") hbox.addWidget(btn) btn = QtWidgets.QPushButton("") btn.clicked.connect( lambda x: self.plot.keyPressEvent( QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_O, QtCore.Qt.KeyboardModifier.NoModifier, ) ) ) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/zoom-out.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Zoom out") hbox.addWidget(btn) if self.enable_zoom_history: self.undo_btn = btn = QtWidgets.QPushButton("") btn.clicked.connect(self.undo_zoom) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/undo.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Undo zoom") hbox.addWidget(btn) btn.setEnabled(False) self.redo_btn = btn = QtWidgets.QPushButton("") btn.clicked.connect(self.redo_zoom) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/redo.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Redo zoom") hbox.addWidget(btn) btn.setEnabled(False) self.lock_btn = btn = QtWidgets.QPushButton("") btn.setObjectName("lock_btn") btn.clicked.connect(self.set_locked) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/unlocked.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("The Y axis is unlocked. Press to lock") hbox.addWidget(btn) self.locked = False self.hide_axes_btn = btn = QtWidgets.QPushButton("") btn.setObjectName("hide_axes_btn") self.hide_axes_btn.clicked.connect(self.hide_axes) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/axis_on.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Hide axis") hbox.addWidget(self.hide_axes_btn) self.selected_channel_value_btn = btn = QtWidgets.QPushButton("") btn.setObjectName("selected_channel_value_btn") self.selected_channel_value_btn.clicked.connect(self.hide_selected_channel_value) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/number_on.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Hide axis") hbox.addWidget(self.selected_channel_value_btn) self.focused_mode_btn = btn = QtWidgets.QPushButton("") btn.setObjectName("focused_mode_btn") self.focused_mode_btn.clicked.connect(self.toggle_focused_mode) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/focus_on.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Toggle focused mode") hbox.addWidget(self.focused_mode_btn) self.delta_btn = btn = QtWidgets.QPushButton("") btn.setObjectName("delta_btn") self.delta_btn.clicked.connect(self.toggle_region_values_display_mode) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/delta_on.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Toggle region values display mode") hbox.addWidget(self.delta_btn) self.bookmark_btn = btn = QtWidgets.QPushButton("") btn.setObjectName("bookmark_btn") btn.clicked.connect(self.toggle_bookmarks) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/bookmark_on.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) btn.setIcon(icon) btn.setToolTip("Toggle bookmarks") hbox.addWidget(btn) hbox.addStretch() self.selected_channel_value = QtWidgets.QLabel("") self.selected_channel_value.setAlignment( QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter ) self.selected_channel_value.setAutoFillBackground(True) font = self.selected_channel_value.font() font.setBold(True) font.setPointSize(24) self.selected_channel_value.setFont(font) vbox.addWidget(self.selected_channel_value) vbox.addWidget(self.channel_selection) vbox.addWidget(self.cursor_info) self.range_proxy = pg.SignalProxy(self.plot.range_modified, rateLimit=16, slot=self.range_modified) # self.plot.range_modified.connect(self.range_modified) self.plot.range_removed.connect(self.range_removed) self.plot.range_modified_finished.connect(self.range_modified_finished) self.plot.cursor_removed.connect(self.cursor_removed) self.plot.current_uuid_changed.connect(self.current_uuid_changed) self.cursor_proxy = pg.SignalProxy(self.plot.cursor_moved, rateLimit=16, slot=self.cursor_moved) # self.plot.cursor_moved.connect(self.cursor_moved) self.plot.cursor_move_finished.connect(self.cursor_move_finished) self.plot.xrange_changed.connect(self.xrange_changed) self.plot.computation_channel_inserted.connect(self.computation_channel_inserted) self.plot.curve_clicked.connect(self.curve_clicked) self._visible_entries = set() self.visible_entries_modified = False self.lock = Lock() self._visible_items = {} self._item_cache = {} self._prev_region = None self.splitter.addWidget(self.plot) self.info = ChannelStats( self.x_unit, precision=self._settings.value("stats_float_precision", 6, type=int), ) self.info.hide() self.info.precision_modified.connect(self.info_precision_modified) self.splitter.addWidget(self.info) self.splitter.setStretchFactor(0, 0) self.splitter.setStretchFactor(1, 1) self.splitter.setStretchFactor(2, 0) self.plot.add_channels_request.connect(self.add_channels_request) self.plot.edit_channel_request.connect(self.edit_channel_request) self.setAcceptDrops(True) main_layout.addWidget(self.splitter) self.show() size = sum(self.splitter.sizes()) self.splitter.setSizes([600, max(size - 600, 1)]) nameColumnWidth = 5 * self.font().pointSize() if signals: nameColumnWidth = max([len(signal.name) + 10 for signal in signals]) unitColumnWidth = 3 * self.font().pointSize() if signals: unitColumnWidth = max([len(signal.unit) + 10 for signal in signals]) self.channel_selection.setColumnWidth(self.channel_selection.NameColumn, nameColumnWidth) self.channel_selection.setColumnWidth(self.channel_selection.ValueColumn, 83) self.channel_selection.setColumnWidth(self.channel_selection.UnitColumn, unitColumnWidth) self.hide() if signals: self.add_new_channels(signals) self.channel_selection.color_changed.connect(self.plot.set_color) self.channel_selection.unit_changed.connect(self.plot.set_unit) self.channel_selection.name_changed.connect(self.plot.set_name) self.channel_selection.conversion_changed.connect(self.set_conversion) self.channel_selection.itemsDeleted.connect(self.channel_selection_reduced) self.channel_selection.group_activation_changed.connect(self.plot.update) self.channel_selection.group_activation_changed.connect(self.cursor_moved) self.channel_selection.currentItemChanged.connect(self.channel_selection_row_changed) self.channel_selection.itemSelectionChanged.connect(self.channel_selection_changed) self.channel_selection.add_channels_request.connect(self.add_channels_request) self.channel_selection.set_time_offset.connect(self.plot.set_time_offset) self.channel_selection.show_overlapping_alias.connect(self._show_overlapping_alias) self.channel_selection.show_properties.connect(self._show_properties) self.channel_selection.insert_computation.connect(self.plot.insert_computation) self.channel_selection.edit_computation.connect(self.plot.edit_computation) self.channel_selection.itemClicked.connect(self.flash_curve) self.channel_selection.model().dataChanged.connect(self.channel_selection_item_changed) self.channel_selection.visible_items_changed.connect(self._update_visibile_entries) self.channel_selection.pattern_group_added.connect(self.pattern_group_added_req) self.channel_selection.double_click.connect(self.channel_selection_item_double_clicked) self.channel_selection.compute_fft_request.connect(self.compute_fft) self.channel_selection.itemExpanded.connect(self.update_current_values) self.channel_selection.verticalScrollBar().valueChanged.connect(self.update_current_values) self.disabled_keyboard_events = set() self.splitter.splitterMoved.connect(self.set_splitter) self.hide_selected_channel_value( hide=self._settings.value("plot_hide_selected_channel_value", False, type=bool) ) self.toggle_focused_mode(focused=self._settings.value("plot_focused_mode", False, type=bool)) self.toggle_region_values_display_mode(mode=self._settings.value("plot_region_values_display_mode", "value")) self.toggle_bookmarks(hide=not self._settings.value("plot_bookmarks", False, type=bool)) self.hide_axes(hide=self._settings.value("plot_hide_axes", False, type=bool)) self.set_locked(locked=self._settings.value("plot_locked", False, type=bool)) self.zoom_history = [] self.zoom_history_index = -1 self.update_zoom = False self.show() def add_new_channels(self, channels, mime_data=None, destination=None, update=True): initial = self.channel_selection.topLevelItemCount() == 0 def add_new_items(tree, root, items, items_pool): children = [] groups = [] for info in items: pattern = info.get("pattern", None) uuid = info["uuid"] name = info["name"] origin_uuid = info.get("origin_uuid", "000000000000") ranges = copy_ranges(info["ranges"]) if info.get("type", "channel") == "group": item = ChannelsTreeItem( ChannelsTreeItem.Group, name=name, pattern=pattern, uuid=uuid, origin_uuid=origin_uuid, ) children.append(item) item.set_ranges(ranges) groups.extend(add_new_items(tree, item, info["channels"], items_pool)) groups.append((item, info)) else: if uuid in items_pool: item = items_pool[uuid] children.append(item) del items_pool[uuid] if root and root.type() == ChannelsTreeItem.Group and root.pattern: y_range = root.pattern.get("y_range", (0, 100)) item.y_range = y_range if item.uuid == self.plot.current_uuid: self.plot.viewbox.setYRange(*y_range, padding=0) if root is None: root = self.channel_selection.invisibleRootItem() root.addChildren(children) else: if root.type() == ChannelsTreeItem.Group: root.addChildren(children) else: parent = root.parent() or self.channel_selection.invisibleRootItem() index = parent.indexOfChild(root) parent.insertChildren(index, children) return groups self.plot._can_paint = False descriptions = get_descriptions_by_uuid(mime_data) invalid = [] can_trim = True for channel in channels.values(): diff = np.diff(channel.timestamps) invalid_indexes = np.argwhere(diff <= 0).ravel() if len(invalid_indexes): invalid_indexes = invalid_indexes[:10] + 1 idx = invalid_indexes[0] ts = channel.timestamps[idx - 1 : idx + 2] invalid.append(f"{channel.name} @ index {invalid_indexes[:10] - 1} with first time stamp error: {ts}") if len(np.argwhere(diff < 0).ravel()): can_trim = False if invalid: errors = "\n".join(invalid) try: mdi_title = self.parent().windowTitle() title = f"plot <{mdi_title}>" except: title = "plot window" MessageBox.warning( self, f"Channels with corrupted time stamps added to {title}", f"The following channels do not have monotonous increasing time stamps:\n{errors}", ) self.plot._can_trim = can_trim or True # allow it for now valid = {} invalid = [] for uuid, channel in channels.items(): if len(channel): samples = channel.samples if samples.dtype.kind not in "SUV" and np.all(np.isnan(samples)): invalid.append(channel.name) elif channel.conversion: samples = channel.physical(copy=False).samples if samples.dtype.kind not in "SUV" and np.all(np.isnan(samples)): invalid.append(channel.name) else: valid[uuid] = channel else: valid[uuid] = channel else: valid[uuid] = channel if invalid: MessageBox.warning( self, "All NaN channels will not be plotted:", f"The following channels have all NaN samples and will not be plotted:\n{', '.join(invalid)}", ) channels = valid channels = self.plot.add_new_channels(channels, descriptions=descriptions) enforce_y_axis = False iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel: if item.checkState(item.CommonAxisColumn) == QtCore.Qt.CheckState.Unchecked: enforce_y_axis = False break else: enforce_y_axis = True iterator += 1 children = [] if self._settings.value("current_theme") == "Dark": background_color = QtGui.QColor(0, 0, 0) else: background_color = QtGui.QColor(255, 255, 255) new_items = {} items_map = {} for sig_uuid, sig in channels.items(): description = descriptions.get(sig_uuid, {}) if description: sig.format = description.get("format", "phys") sig.mode = description.get("mode", "phys") if "comment" in description: sig.comment = description["comment"] or "" sig.flags |= Signal.Flags.user_defined_comment item = ChannelsTreeItem( ChannelsTreeItem.Channel, signal=sig, check=QtCore.Qt.CheckState.Checked if sig.enable else QtCore.Qt.CheckState.Unchecked, ) if len(sig): raw_value, raw_kind, value, kind, fmt = sig.value_at_timestamp(sig.timestamps[0]) item.kind = kind item._value = "n.a." item.set_value(raw_value, value, force=True, update=True) if mime_data is None: children.append(item) else: new_items[sig_uuid] = item items_map[sig_uuid] = item ranges = description.get("ranges", []) if not ranges and self.pattern: ranges = self.pattern["ranges"] item.set_ranges(copy_ranges(ranges)) self.info_uuid = sig_uuid if mime_data: destination = destination or self.channel_selection.drop_target groups = add_new_items( self.channel_selection, destination, mime_data, new_items, ) if groups: self.channel_selection.blockSignals(True) for item, info in groups: item.setExpanded(info.get("expanded", False)) if item.pattern: item.setCheckState( item.NameColumn, QtCore.Qt.CheckState.Checked if info["enabled"] else QtCore.Qt.CheckState.Unchecked, ) else: if not item.childCount(): item.setCheckState( item.NameColumn, QtCore.Qt.CheckState.Checked if info["enabled"] else QtCore.Qt.CheckState.Unchecked, ) if info.get("disabled", False): item.set_disabled(info["disabled"]) self.channel_selection.blockSignals(False) self.channel_selection.refresh() # still have simple signals to add if new_items: self.channel_selection.addTopLevelItems(list(new_items.values())) elif children: destination = destination or self.channel_selection.drop_target if destination is None: self.channel_selection.addTopLevelItems(children) else: if destination.type() == ChannelsTreeItem.Group: destination.addChildren(children) if destination.pattern: y_range = destination.pattern.get("y_range", (0, 100)) for child in children: self.plot.set_y_range(child.uuid, y_range, emit=False) if child.uuid == self.plot.current_uuid: self.plot.viewbox.setYRange(*y_range, padding=0) else: parent = destination.parent() or self.channel_selection.invisibleRootItem() index = parent.indexOfChild(destination) parent.insertChildren(index, children) for sig_uuid, sig in channels.items(): description = descriptions.get(sig_uuid, {}) item = items_map[sig_uuid] if description: individual_axis = description.get("individual_axis", False) if individual_axis: item.setCheckState(item.IndividualAxisColumn, QtCore.Qt.CheckState.Checked) _, idx = self.plot.signal_by_uuid(sig_uuid) axis = self.plot.get_axis(idx) if isinstance(axis, FormatedAxis): axis.setWidth(description["individual_axis_width"]) if description.get("common_axis", False): item.setCheckState(item.CommonAxisColumn, QtCore.Qt.CheckState.Checked) item.precision = description.get("precision", 3) if description.get("conversion", None): conversion = from_dict(description["conversion"]) item.signal.flags |= Signal.Flags.user_defined_conversion item.set_conversion(conversion) if description.get("user_defined_name", None): item.name = description["user_defined_name"] if enforce_y_axis: item.setCheckState(item.CommonAxisColumn, QtCore.Qt.CheckState.Checked) if update: self.channel_selection.update_channel_groups_count() self.channel_selection.refresh() self.adjust_splitter(initial=initial) self.current_uuid_changed(self.plot.current_uuid) self.plot._can_paint = True self.plot.update() def adjust_splitter(self, initial=False): size = sum(self.splitter.sizes()) if Plot.dynamic_columns_width or initial: self.channel_selection.resizeColumnToContents(self.channel_selection.NameColumn) self.channel_selection.resizeColumnToContents(self.channel_selection.UnitColumn) width = sum(self.channel_selection.columnWidth(col) for col in range(self.channel_selection.columnCount())) if width > self.splitter.sizes()[0]: if size - width >= 300: self.splitter.setSizes([width, size - width, 0]) else: if size >= 350: self.splitter.setSizes([size - 300, 300, 0]) elif size >= 100: self.splitter.setSizes([50, size - 50, 0]) else: self.splitter.setSizes([width, size - width, 0]) def channel_group_item_to_config(self, item): widget = item pattern = widget.pattern channel_group = { "type": "group", "name": widget.name, "enabled": item.checkState(item.NameColumn) == QtCore.Qt.CheckState.Checked, "pattern": widget.pattern, "ranges": widget.ranges, "origin_uuid": item.origin_uuid, "expanded": item.isExpanded(), "disabled": item.isDisabled(), } return channel_group def channel_item_to_config(self, item): widget = item channel = {"type": "channel"} sig, idx = self.plot.signal_by_uuid(widget.uuid) if sig.flags & Signal.Flags.user_defined_name: channel["user_defined_name"] = sig.name channel["name"] = sig.original_name else: channel["name"] = sig.name channel["unit"] = sig.unit channel["flags"] = int(sig.flags) channel["enabled"] = item.checkState(item.NameColumn) == QtCore.Qt.CheckState.Checked if item.checkState(item.IndividualAxisColumn) == QtCore.Qt.CheckState.Checked: channel["individual_axis"] = True channel["individual_axis_width"] = self.plot.get_axis(idx).width() else: channel["individual_axis"] = False channel["common_axis"] = item.checkState(item.CommonAxisColumn) == QtCore.Qt.CheckState.Checked channel["color"] = sig.color channel["computed"] = bool(sig.flags & Signal.Flags.computed) channel["ranges"] = widget.ranges channel["precision"] = widget.precision channel["fmt"] = widget.fmt channel["format"] = widget.format channel["mode"] = widget.mode if sig.flags & Signal.Flags.computed: channel["computation"] = sig.computation if sig.flags & Signal.Flags.user_defined_comment: channel["comment"] = sig.comment if sig.flags & Signal.Flags.user_defined_unit: channel["unit"] = sig.unit channel["y_range"] = [float(e) for e in sig.y_range] channel["origin_uuid"] = str(sig.origin_uuid) if sig.flags & Signal.Flags.user_defined_conversion: channel["conversion"] = to_dict(sig.conversion) return channel def channel_selection_changed(self, update=False): def set_focused(item): if item.type() == item.Channel: item.signal.path = None item.signal.enable = True elif item.type() == item.Group: for i in range(item.childCount()): set_focused(item.child(i)) if self.focused_mode: for signal in self.plot.signals: signal.enable = False for item in self.channel_selection.selectedItems(): set_focused(item) self.plot.trim() self.plot.update() else: if update: for signal in self.plot.signals: signal.path = None signal.enable = False iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if ( item.type() == item.Channel and item.checkState(item.NameColumn) == QtCore.Qt.CheckState.Checked and not item.isDisabled() ): item.signal.enable = True iterator += 1 self.plot.trim() self.plot.update() def channel_selection_item_changed(self, top_left, bottom_right, roles): item = self.channel_selection.itemFromIndex(top_left) if item.uuid == self.info_uuid: palette = self.selected_channel_value.palette() brush = item.foreground(item.NameColumn) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.WindowText, brush) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.WindowText, brush) brush = QtGui.QBrush( item._current_background_color if item._current_background_color is not None else QtCore.Qt.BrushStyle.NoBrush ) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Window, brush) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Window, brush) self.selected_channel_value.setPalette(palette) value = item.text(item.ValueColumn) unit = item.unit metrics = QtGui.QFontMetrics(self.selected_channel_value.font()) elided = metrics.elidedText( f"{value} {unit}", QtCore.Qt.TextElideMode.ElideRight, self.selected_channel_value.width() - 10, ) self.selected_channel_value.setText(elided) # (f"{value} {unit}") if QtCore.Qt.ItemDataRole.CheckStateRole not in roles: return if item.type() != item.Channel or item.isDisabled(): return column = top_left.column() if column == item.NameColumn: enabled = item.checkState(column) == QtCore.Qt.CheckState.Checked if enabled != item.signal.enable: item.signal.enable = enabled self.plot.set_signal_enable(item.uuid, item.checkState(column)) if not enabled and self.channel_selection.hide_disabled_channels: item.setHidden(True) elif column == item.CommonAxisColumn: if not self.locked: enabled = item.checkState(column) == QtCore.Qt.CheckState.Checked if enabled != item.signal.y_link: item.signal.y_link = enabled self.plot.set_common_axis(item.uuid, enabled) elif column == item.IndividualAxisColumn: enabled = item.checkState(column) == QtCore.Qt.CheckState.Checked if enabled != item.signal.individual_axis: self.plot.set_individual_axis(item.uuid, enabled) def channel_selection_item_double_clicked(self, item, button): if item is None: return elif item.type() != item.Info: if item.type() == item.Channel: if not item.isDisabled(): if item.checkState(item.NameColumn) == QtCore.Qt.CheckState.Checked: item.setCheckState(item.NameColumn, QtCore.Qt.CheckState.Unchecked) else: item.setCheckState(item.NameColumn, QtCore.Qt.CheckState.Checked) elif item.type() == item.Group: if ( Plot.item_double_click_handling == "enable/disable" and button == QtCore.Qt.MouseButton.LeftButton ) or ( Plot.item_double_click_handling == "expand/collapse" and button == QtCore.Qt.MouseButton.RightButton ): if self.channel_selection.expandsOnDoubleClick(): self.channel_selection.setExpandsOnDoubleClick(False) if item.isDisabled(): item.set_disabled(False) else: item.set_disabled(True) self.plot.update() else: item.setExpanded(not item.isExpanded()) def channel_selection_reduced(self, deleted): self.plot.delete_channels(deleted) if self.info_uuid in deleted: self.info_uuid = None self.info.hide() count = 0 iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while iterator.value(): count += 1 iterator += 1 if not count: self.info_uuid = None self.info.set_stats(None) self.selected_channel_value.setText("") self.close_request.emit() def channel_selection_row_changed(self, current, previous): if not self.closed: if current and current.type() == ChannelsTreeItem.Channel: item = current uuid = item.uuid self.info_uuid = uuid self.plot.set_current_uuid(self.info_uuid) if self.info.isVisible(): stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) if len(self.channel_selection.selectedItems()) == 1: self.flash_curve(current, 0) def clear(self): event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_A, QtCore.Qt.KeyboardModifier.ControlModifier ) self.channel_selection.keyPressEvent(event) event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Delete, QtCore.Qt.KeyboardModifier.NoModifier ) self.channel_selection.keyPressEvent(event) def close(self): if self.closed: return self.closed = True self.channel_selection.blockSignals(True) self.channel_selection.model().blockSignals(True) self.channel_selection.verticalScrollBar().blockSignals(True) self.splitter.blockSignals(True) self.plot.blockSignals(True) self.plot._can_paint_global = False self.owner = None self._inhibit_timestamp_signals_timer.blockSignals(True) self._inhibit_timestamp_signals_timer.stop() self.info.blockSignals(True) tree = self.channel_selection tree.plot = None iterator = QtWidgets.QTreeWidgetItemIterator(tree) while item := iterator.value(): item.signal = None iterator += 1 tree.clear() tree.close() self._visible_items.clear() for sig in self.plot.signals: sig.enable = False del sig.plot_samples del sig.timestamps del sig.plot_timestamps del sig.samples del sig.phys_samples del sig.raw_samples sig._raw_samples = None sig._phys_samples = None sig._timestamps = None self.plot.signals.clear() self.plot._uuid_map.clear() self.plot._timebase_db.clear() for axis in self.plot.axes: if isinstance(axis, FormatedAxis): axis.blockSignals(True) self.plot.axes = None self.plot.plot_parent = None self.plot.close() bookmarks = self.plot.bookmarks self.plot.bookmarks = [] self.verify_bookmarks.emit(bookmarks, self) self.mdf = None super().close() def color_same_origin_signals(self, origin_uuid="", color=""): iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel and item.signal.origin_uuid == origin_uuid: item.color = color iterator += 1 def computation_channel_inserted(self, sig): sig.enable = True if self.channel_selection.selectedItems(): item = self.channel_selection.selectedItems()[0] item_below = self.channel_selection.itemBelow(item) if item_below is None or item_below.parent() != item.parent(): destination = item.parent() else: destination = item_below else: destination = None self.add_new_channels({sig.name: sig}, destination=destination) self.info_uuid = sig.uuid self.plot.set_current_uuid(self.info_uuid, True) def compute_fft(self, uuid): signal, index = self.plot.signal_by_uuid(uuid) try: window = FFTWindow(PlotSignal(signal), parent=self) window.show() except: pass def current_uuid_changed(self, uuid): self.info_uuid = uuid if uuid: palette = self.selected_channel_value.palette() sig, idx = self.plot.signal_by_uuid(uuid) brush = QtGui.QBrush(sig.color) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.WindowText, brush) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.WindowText, brush) self.selected_channel_value.setPalette(palette) item = self.item_by_uuid(uuid) if item is not None: value = item.text(item.ValueColumn) unit = item.unit metrics = QtGui.QFontMetrics(self.selected_channel_value.font()) elided = metrics.elidedText( f"{value} {unit}", QtCore.Qt.TextElideMode.ElideRight, self.selected_channel_value.width() - 10, ) self.selected_channel_value.setText(elided) else: self.selected_channel_value.setText("") def cursor_moved(self, cursor=None): if self.plot.cursor1 is None: return position = self.plot.cursor1.value() if not self.plot.region: self.cursor_info.update_value() for item in self._visible_items.values(): if item.type() == item.Channel: signal, idx = self.plot.signal_by_uuid(item.uuid) index = self.plot.get_timestamp_index(position, signal.timestamps) raw_value, raw_kind, value, kind, fmt = signal.value_at_index(index) item.set_prefix() item.kind = kind item.set_fmt(fmt) item.set_value(raw_value, value, update=True) if item.uuid == self.info_uuid: value = item.text(item.ValueColumn) unit = item.unit metrics = QtGui.QFontMetrics(self.selected_channel_value.font()) elided = metrics.elidedText( f"{value} {unit}", QtCore.Qt.TextElideMode.ElideRight, self.selected_channel_value.width() - 10, ) self.selected_channel_value.setText(elided) # (f"{value} {unit}") if self.info.isVisible(): stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) if not self._inhibit_timestamp_signals: self.cursor_moved_signal.emit(self, position) def cursor_move_finished(self, cursor=None): x = self.plot.get_current_timebase() if x.size: dim = len(x) position = self.plot.cursor1.value() right = np.searchsorted(x, position, side="right") if right == 0: next_pos = x[0] elif right == dim: next_pos = x[-1] else: if position - x[right - 1] < x[right] - position: next_pos = x[right - 1] else: next_pos = x[right] self.plot.cursor1.setPos(next_pos) def cursor_removed(self): iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel and not self.plot.region: self.cursor_info.update_value() item.set_prefix() item.set_value("", "") iterator += 1 if self.info.isVisible(): stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) self.cursor_removed_signal.emit(self) def curve_clicked(self, uuid): iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel and item.uuid == uuid: self.channel_selection.clearSelection() self.channel_selection.setCurrentItem(item) break iterator += 1 def decrease_font(self): font = self.font() size = font.pointSize() pos = bisect.bisect_left(FONT_SIZE, size) - 1 pos = max(pos, 0) new_size = FONT_SIZE[pos] self.set_font_size(new_size) def dragEnterEvent(self, e): if e.mimeData().hasFormat("application/octet-stream-asammdf"): e.accept() super().dragEnterEvent(e) def dropEvent(self, e): if e.source() is self.channel_selection: super().dropEvent(e) else: data = e.mimeData() if data.hasFormat("application/octet-stream-asammdf"): names = extract_mime_names(data) self.add_channels_request.emit(names) else: e.ignore() def flash_curve(self, item, column): if self.plot.cursor1: self.plot.flash_current_signal = 6 self.plot.update() def hide_axes(self, event=None, hide=None): if hide is None: hide = not self.hide_axes_btn.isFlat() self._settings.setValue("plot_hide_axes", hide) if hide: self.plot.y_axis.hide() self.plot.x_axis.hide() self.hide_axes_btn.setFlat(True) self.hide_axes_btn.setToolTip("Show axes") else: self.plot.y_axis.show() self.plot.x_axis.show() self.hide_axes_btn.setFlat(False) self.hide_axes_btn.setToolTip("Hide axes") if hide: png = ":/axis.png" else: png = ":/axis_on.png" icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(png), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.hide_axes_btn.setIcon(icon) def hide_selected_channel_value(self, event=None, hide=None): if hide is None: hide = not self.selected_channel_value_btn.isFlat() self._settings.setValue("plot_hide_selected_channel_value", hide) if hide: self.selected_channel_value.hide() self.selected_channel_value_btn.setFlat(True) self.selected_channel_value_btn.setToolTip("Show selected channel value panel") else: self.selected_channel_value.show() self.selected_channel_value_btn.setFlat(False) self.selected_channel_value_btn.setToolTip("Hide selected channel value panel") if hide: png = ":/number.png" else: png = ":/number_on.png" icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(png), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.selected_channel_value_btn.setIcon(icon) def increase_font(self): font = self.font() size = font.pointSize() pos = bisect.bisect_right(FONT_SIZE, size) if pos == len(FONT_SIZE): pos -= 1 new_size = FONT_SIZE[pos] self.set_font_size(new_size) def info_precision_modified(self): if not self.closed: if self.info_uuid is not None: stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) def _inhibit_timestamp_handler(self): self._inhibit_timestamp_signals = False def item_by_uuid(self, uuid): return self._item_cache.get(uuid, None) def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if event.keyCombination().toCombined() in self.disabled_keyboard_events: event.ignore() return if key == QtCore.Qt.Key.Key_M and modifiers == QtCore.Qt.KeyboardModifier.NoModifier: event.accept() ch_size, plt_size, info_size = self.splitter.sizes() if self.info.isVisible(): self.info.hide() self.splitter.setSizes((ch_size, plt_size + info_size, 0)) else: self.info.show() self.splitter.setSizes( ( ch_size, int(0.8 * (plt_size + info_size)), int(0.2 * (plt_size + info_size)), ) ) if self.info_uuid: stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) elif key == QtCore.Qt.Key.Key_2 and modifiers == QtCore.Qt.KeyboardModifier.NoModifier: self.focused_mode = not self.focused_mode if self.focused_mode: self.focused_mode_btn.setFlat(False) else: self.focused_mode_btn.setFlat(True) self.channel_selection_changed(update=True) event.accept() elif ( key in (QtCore.Qt.Key.Key_B, QtCore.Qt.Key.Key_H, QtCore.Qt.Key.Key_P, QtCore.Qt.Key.Key_T) and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier ): selected_items = self.channel_selection.selectedItems() or [ self.channel_selection.topLevelItem(i) for i in range(self.channel_selection.topLevelItemCount()) ] if key == QtCore.Qt.Key.Key_B: fmt = "bin" elif key == QtCore.Qt.Key.Key_H: fmt = "hex" elif key == QtCore.Qt.Key.Key_P: fmt = "phys" else: fmt = "ascii" for item in selected_items: item_type = item.type() if item_type == item.Info: continue elif item_type == item.Channel: signal, idx = self.plot.signal_by_uuid(item.uuid) if signal.plot_samples.dtype.kind in "uif": signal.format = fmt raw_value, raw_kind, value, kind, fmt = signal.value_at_timestamp(0) widget = self.item_by_uuid(signal.uuid) widget.kind = kind widget.set_fmt(fmt) widget.set_value(update=True) if self.plot.current_uuid == signal.uuid: self.plot.y_axis.format = fmt self.plot.y_axis.picture = None self.plot.y_axis.update() axis = self.plot.get_axis(idx) if isinstance(axis, FormatedAxis): axis.format = fmt axis.picture = None axis.update() elif item_type == item.Group: for i in range(item.childCount()): selected_items.append(item.child(i)) if item.pattern: item.pattern["integer_format"] = fmt if self.info.isVisible(): stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) self.current_uuid_changed(self.plot.current_uuid) self.plot.update() event.accept() elif ( key in (QtCore.Qt.Key.Key_R, QtCore.Qt.Key.Key_S) and modifiers == QtCore.Qt.KeyboardModifier.AltModifier and self._can_switch_mode ): selected_items = self.channel_selection.selectedItems() if not selected_items: signals = [(sig, i) for i, sig in enumerate(self.plot.signals)] uuids = [sig.uuid for sig in self.plot.signals] else: uuids = [item.uuid for item in selected_items if item.type() == ChannelsTreeItem.Channel] signals = [self.plot.signal_by_uuid(uuid) for uuid in uuids] if signals: if key == QtCore.Qt.Key.Key_R: mode = "raw" style = QtCore.Qt.PenStyle.DashLine else: mode = "phys" style = QtCore.Qt.PenStyle.SolidLine for signal, idx in signals: if signal.mode != mode: signal.pen = fn.mkPen(color=signal.color, style=style) buttom, top = signal.y_range try: min_, max_ = float(signal.min), float(signal.max) except: min_, max_ = 0, 1 if max_ != min_ and top != buttom: factor = (top - buttom) / (max_ - min_) offset = (buttom - min_) / (top - buttom) else: factor = 1 offset = 0 signal.mode = mode try: min_, max_ = float(signal.min), float(signal.max) except: min_, max_ = 0, 1 if max_ != min_: delta = (max_ - min_) * factor buttom = min_ + offset * delta top = buttom + delta else: buttom, top = max_ - 1, max_ + 1 signal.y_range = buttom, top item = self.item_by_uuid(signal.uuid) item._value = None if self.plot.current_uuid == signal.uuid: self.plot.y_axis.mode = mode self.plot.y_axis.picture = None self.plot.y_axis.update() self.plot.viewbox.setYRange(buttom, top, padding=0, update=True) self.plot.get_axis(idx).mode = mode self.plot.get_axis(idx).picture = None self.plot.get_axis(idx).update() for uuid in uuids: item = self.item_by_uuid(uuid) item.setText(item.UnitColumn, item.unit) self.plot.update() if self.plot.cursor1: self.plot.cursor_moved.emit(self.plot.cursor1) event.accept() elif key == QtCore.Qt.Key.Key_I and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: if self.plot.cursor1: position = self.plot.cursor1.value() comment, submit = QtWidgets.QInputDialog.getMultiLineText( self, "Insert comments", f"Enter the comments for cursor position {position:.9f}s:", "", ) if submit: visible = True for bookmark in self.plot.bookmarks: visible = bookmark.visible break bookmark = Bookmark( pos=position, message=comment, color="#FF0000", tool=Tool.__tool__, ) bookmark.visible = visible bookmark.edited = True self.plot.bookmarks.append(bookmark) self.plot.viewbox.addItem(self.plot.bookmarks[-1]) if not visible: self.toggle_bookmarks() self.update() event.accept() elif key == QtCore.Qt.Key.Key_I and modifiers == QtCore.Qt.KeyboardModifier.AltModifier: self.toggle_bookmarks(not self.show_bookmarks) event.accept() elif key == QtCore.Qt.Key.Key_G and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: selected_items = [ item for item in self.channel_selection.selectedItems() if item.type() != ChannelsTreeItem.Info ] channel_items = [item for item in selected_items if item.type() == ChannelsTreeItem.Channel] if not channel_items: channel_items = [item.first_signal() for item in selected_items] channel_items = [item for item in channel_items if item is not None] if selected_items: uuids = [item.uuid for item in channel_items] signals = {} for i, uuid in enumerate(uuids): sig, idx = self.plot.signal_by_uuid(uuid) if i == 0: y_range = sig.y_range signals[sig.name] = sig if not signals: signals["Demo signal"] = Signal( name="Demo signal", samples=[], timestamps=[], ) y_range = (0, 100) diag = ScaleDialog(signals, y_range, parent=self) if diag.exec(): offset = diag.offset.value() scale = diag.scaling.value() y_bottom = -offset * scale / 100 y_top = y_bottom + scale y_range = y_bottom, y_top for item in selected_items: item.y_range = y_range self.zoom_changed() self.plot.update() event.accept() elif key == QtCore.Qt.Key.Key_R and modifiers == QtCore.Qt.KeyboardModifier.NoModifier: iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel: item.set_prefix() item.set_value("", "") iterator += 1 self.plot.keyPressEvent(event) elif key == QtCore.Qt.Key.Key_C and modifiers in ( QtCore.Qt.KeyboardModifier.NoModifier, QtCore.Qt.KeyboardModifier.ControlModifier, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ): self.channel_selection.keyPressEvent(event) elif ( key == QtCore.Qt.Key.Key_R and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and self.can_edit_ranges ): self.channel_selection.keyPressEvent(event) elif key == QtCore.Qt.Key.Key_V and modifiers in ( QtCore.Qt.KeyboardModifier.ControlModifier, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ): self.channel_selection.keyPressEvent(event) elif key == QtCore.Qt.Key.Key_BracketLeft and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: self.decrease_font() elif key == QtCore.Qt.Key.Key_BracketRight and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: self.increase_font() elif key == QtCore.Qt.Key.Key_Backspace: if modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier: self.redo_zoom() else: self.undo_zoom() event.accept() elif key == QtCore.Qt.Key.Key_W and modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier: if self.enable_zoom_history and self.zoom_history: self.zoom_history_index = 0 snapshot = self.zoom_history[self.zoom_history_index] self.plot.block_zoom_signal = True for sig in self.plot.signals: y_range = snapshot["y"].get(sig.uuid, None) if y_range is None: continue self.plot.set_y_range(sig.uuid, y_range, emit=False) self.plot.viewbox.setXRange(*snapshot["x"], padding=0) self.undo_btn.setEnabled(False) if len(self.zoom_history) > 1: self.redo_btn.setEnabled(True) self.plot.block_zoom_signal = False event.accept() else: try: self.plot.keyPressEvent(event) except: print(format_exc()) def line_style_same_origin_signals(self, origin_uuid="", style=QtCore.Qt.PenStyle.SolidLine): for signal in self.plot.signals: if signal.origin_uuid == origin_uuid: signal.pen = fn.mkPen(color=signal.color, style=style) self.plot.update() def mousePressEvent(self, event): self.clicked.emit() super().mousePressEvent(event) def pattern_group_added_req(self, group): self.pattern_group_added.emit(self, group) def range_modified(self, region=None): if self.plot.region is None: return start, stop = sorted(self.plot.region.getRegion()) self.cursor_info.update_value() for item in self._visible_items.values(): if item.type() == item.Channel: signal, i = self.plot.signal_by_uuid(item.uuid) index = self.plot.get_timestamp_index(start, signal.timestamps) start_raw_v, raw_kind, start_v, kind, fmt = signal.value_at_index(index) index = self.plot.get_timestamp_index(stop, signal.timestamps) stop_raw_v, raw_kind, stop_v, kind, fmt = signal.value_at_index(index) if self.region_values_display_mode == "delta": item.set_prefix("Δ = ") item.set_fmt(signal.format) if "n.a." not in (start_v, stop_v): if kind in "ui": delta = np.int64(stop_v) - np.int64(start_v) delta_raw = np.int64(stop_raw_v) - np.int64(start_raw_v) item.kind = kind item.set_value(delta_raw, delta) item.set_fmt(fmt) elif kind == "f": delta = stop_v - start_v delta_raw = stop_raw_v - start_raw_v item.kind = kind item.set_value(delta_raw, delta) item.set_fmt(fmt) else: item.set_value("n.a.", "n.a.") else: item.set_value("n.a.", "n.a.") else: if self.plot.region_lock is not None: if start == self.plot.region_lock: value = stop_v raw_value = stop_raw_v else: value = start_v raw_value = start_raw_v else: if self._prev_region is None: value = start_v raw_value = start_raw_v else: if stop == self._prev_region[1]: value = start_v raw_value = start_raw_v else: value = stop_v raw_value = stop_raw_v item.set_prefix() item.set_fmt(signal.format) if value != "n.a.": if kind in "uif": item.kind = kind item.set_value(raw_value, value) item.set_fmt(fmt) else: item.set_value("n.a.", "n.a.") else: item.set_value("n.a.", "n.a.") if self.info.isVisible(): stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) self._prev_region = (start, stop) self.region_moved_signal.emit(self, [start, stop]) def range_modified_finished(self): if not self.plot.region: return start, stop = self.plot.region.getRegion() timebase = self.plot.get_current_timebase() if timebase.size: dim = len(timebase) if self.plot.region_lock is None: right = np.searchsorted(timebase, start, side="right") if right == 0: next_pos = timebase[0] elif right == dim: next_pos = timebase[-1] else: if start - timebase[right - 1] < timebase[right] - start: next_pos = timebase[right - 1] else: next_pos = timebase[right] start = next_pos right = np.searchsorted(timebase, stop, side="right") if right == 0: next_pos = timebase[0] elif right == dim: next_pos = timebase[-1] else: if stop - timebase[right - 1] < timebase[right] - stop: next_pos = timebase[right - 1] else: next_pos = timebase[right] stop = next_pos self.plot.region.setRegion((start, stop)) else: if start == self.plot.region_lock: pos = stop else: pos = start right = np.searchsorted(timebase, pos, side="right") if right == 0: next_pos = timebase[0] elif right == dim: next_pos = timebase[-1] else: if pos - timebase[right - 1] < timebase[right] - pos: next_pos = timebase[right - 1] else: next_pos = timebase[right] pos = next_pos self.plot.region.setRegion((self.plot.region_lock, pos)) def range_removed(self): self._prev_region = None iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel: item.set_prefix() item.set_value("", "") iterator += 1 self.cursor_info.update_value() if self.plot.cursor1: self.plot.cursor_moved.emit(self.plot.cursor1) if self.info.isVisible(): stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) self.region_removed_signal.emit(self) def redo_zoom(self): if self.enable_zoom_history and self.zoom_history: self.zoom_history_index = min(self.zoom_history_index + 1, len(self.zoom_history) - 1) snapshot = self.zoom_history[self.zoom_history_index] self.plot.block_zoom_signal = True for sig in self.plot.signals: y_range = snapshot["y"].get(sig.uuid, None) if y_range is None: continue self.plot.set_y_range(sig.uuid, y_range, emit=False) self.plot.viewbox.setXRange(*snapshot["x"], padding=0) if self.zoom_history_index == len(self.zoom_history) - 1: self.redo_btn.setEnabled(False) if len(self.zoom_history) > 1: self.undo_btn.setEnabled(True) self.plot.block_zoom_signal = False def selected_items(self): uuids = [ item.uuid for item in self.channel_selection.selectedItems() if item.type() == ChannelsTreeItem.Channel ] return set(uuids) def set_conversion(self, uuid, conversion): self.plot.set_conversion(uuid, conversion) self.cursor_moved() def set_font_size(self, size): font = self.font() font.setPointSize(size) self.setFont(font) self.channel_selection.set_font_size(size) self.plot.y_axis.set_font_size(size) self.plot.x_axis.set_font_size(size) def set_initial_zoom(self): self.zoom_history.clear() self.zoom_history_index = -1 self.zoom_changed(inplace=True) def set_locked(self, event=None, locked=None): if locked is None: locked = not self.locked self._settings.setValue("plot_locked", locked) if locked: tooltip = "The Y axis is locked. Press to unlock" png = ":/locked.png" self.lock_btn.setFlat(True) else: tooltip = "The Y axis is unlocked. Press to lock" png = ":/unlocked.png" self.lock_btn.setFlat(False) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(png), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.lock_btn.setToolTip(tooltip) self.lock_btn.setIcon(icon) self.channel_selection.setColumnHidden(self.channel_selection.CommonAxisColumn, locked) self.locked = locked self.plot.set_locked(locked) def set_splitter(self, pos, index): self.splitter_moved.emit(self, pos) def set_timestamp(self, stamp): if self.plot.cursor1 is None: event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.NoModifier, ) self.plot.keyPressEvent(event) self._inhibit_timestamp_signals = True self._inhibit_timestamp_signals_timer.start(50) self.plot.cursor1.setPos(stamp) self.cursor_move_finished() def shift_same_origin_signals(self, origin_uuid="", delta=0.0, absolute=False): uuids = [] iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel and item.signal.origin_uuid == origin_uuid: uuids.append(item.signal.uuid) iterator += 1 if not uuids: return self.plot.set_time_offset([absolute, delta, *uuids]) def update_missing_signals(self, uuids=()): model = self.channel_selection.selectionModel() model.clearSelection() iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel and item.signal.origin_uuid not in uuids: item.setSelected(True) iterator += 1 self.channel_selection.keyPressEvent( QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Delete, QtCore.Qt.KeyboardModifier.NoModifier ) ) self.plot.update() def _show_overlapping_alias(self, origin_uuid, uuid): for sig in self.plot.signals: if sig.uuid == uuid: self.show_overlapping_alias.emit(sig) def _show_properties(self, origin_uuid, uuid): for sig in self.plot.signals: if sig.uuid == uuid: if sig.flags & Signal.Flags.computed: try: view = ComputedChannelInfoWindow(sig, self) view.show() except: print(format_exc()) raise else: self.show_properties.emit(sig) def to_config(self): def item_to_config(tree, root): channels = [] for i in range(root.childCount()): item = root.child(i) if item.type() == item.Channel: channel = self.channel_item_to_config(item) elif item.type() == item.Group: channel = self.channel_group_item_to_config(item) channel["channels"] = item_to_config(tree, item) if not item.pattern else [] channels.append(channel) return channels config = { "channels": ( item_to_config(self.channel_selection, self.channel_selection.invisibleRootItem()) if not self.pattern else [] ), "pattern": self.pattern, "splitter": [int(e) for e in self.splitter.sizes()[:2]] + [ 0, ], "x_range": self.plot.viewbox.viewRange()[0], "y_axis_width": self.plot.y_axis.width(), "grid": [ self.plot.plotItem.ctrl.xGridCheck.isChecked(), self.plot.plotItem.ctrl.yGridCheck.isChecked(), ], "cursor_precision": self.cursor_info.precision, "font_size": self.font().pointSize(), "locked": self.locked, "common_axis_y_range": [float(e) for e in self.plot.common_axis_y_range], "channels_header": [ self.splitter.sizes()[0], [self.channel_selection.columnWidth(i) for i in range(self.channel_selection.columnCount())], ], "channels_header_sizes": [self.splitter.sizes()[0], self.channel_selection.header_sizes()], "channels_header_columns_visible": [ not self.channel_selection.isColumnHidden(i) for i in range(self.channel_selection.columnCount()) if i != self.channel_selection.RawColumn ], "channels_header_columns_visiblity": self.channel_selection.header_columns_visibility(), "hide_axes": self.hide_axes_btn.isFlat(), "hide_selected_channel_value_panel": self.selected_channel_value_btn.isFlat(), "focused_mode": not self.focused_mode_btn.isFlat(), "delta_mode": "value" if self.delta_btn.isFlat() else "delta", "hide_bookmarks": self.bookmark_btn.isFlat(), "hide_missing_channels": self.channel_selection.hide_missing_channels, "hide_disabled_channels": self.channel_selection.hide_disabled_channels, } return config def toggle_bookmarks(self, *args, hide=None): if hide is not None: self.show_bookmarks = hide self.show_bookmarks = not self.show_bookmarks if self.show_bookmarks: self.bookmark_btn.setFlat(False) else: self.bookmark_btn.setFlat(True) for bookmark in self.plot.bookmarks: bookmark.visible = self.show_bookmarks self.plot.update() if not self.show_bookmarks: png = ":/bookmark.png" else: png = ":/bookmark_on.png" icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(png), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.bookmark_btn.setIcon(icon) if hide is None: self._settings.setValue("plot_bookmarks", not self.bookmark_btn.isFlat()) def toggle_focused_mode(self, event=None, focused=None): if focused is not None: # invert so that the key press event will set the desider focused mode self.focused_mode = not focused key_event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_2, QtCore.Qt.KeyboardModifier.NoModifier ) self.keyPressEvent(key_event) if focused is None: self._settings.setValue("plot_focused_mode", self.focused_mode) if not self.focused_mode: self.focused_mode_btn.setFlat(True) self.focused_mode_btn.setToolTip("Switch on focused mode") else: self.focused_mode_btn.setFlat(False) self.focused_mode_btn.setToolTip("Switch off focused mode") if not self.focused_mode: png = ":/focus.png" else: png = ":/focus_on.png" icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(png), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.focused_mode_btn.setIcon(icon) def toggle_region_values_display_mode(self, event=None, mode=None): if mode is None: self.region_values_display_mode = "delta" if self.region_values_display_mode == "value" else "value" else: self.region_values_display_mode = mode if self.region_values_display_mode == "value": self.delta_btn.setFlat(True) self.delta_btn.setToolTip("Switch to region cursors delta display mode") else: self.delta_btn.setFlat(False) self.delta_btn.setToolTip("Switch to active region cursor value display mode") if self.delta_btn.isFlat(): png = ":/delta.png" else: png = ":/delta_on.png" icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(png), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.delta_btn.setIcon(icon) if mode is None: self._settings.setValue("plot_region_values_display_mode", self.region_values_display_mode) self.range_modified() iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == ChannelsTreeItem.Channel: item.set_value(update=True, force=True) iterator += 1 def toggle_same_origin_signals(self, origin_uuid="", visible=True): state = QtCore.Qt.CheckState.Checked if visible else QtCore.Qt.CheckState.Unchecked iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): if item.type() == item.Channel and item.signal.origin_uuid == origin_uuid: item.setCheckState(item.NameColumn, state) iterator += 1 def undo_zoom(self): if self.enable_zoom_history and self.zoom_history: self.zoom_history_index = max(self.zoom_history_index - 1, 0) snapshot = self.zoom_history[self.zoom_history_index] self.plot.block_zoom_signal = True for sig in self.plot.signals: y_range = snapshot["y"].get(sig.uuid, None) if y_range is None: continue self.plot.set_y_range(sig.uuid, y_range, emit=False) self.plot.viewbox.setXRange(*snapshot["x"], padding=0) if self.zoom_history_index == 0: self.undo_btn.setEnabled(False) if len(self.zoom_history) > 1: self.redo_btn.setEnabled(True) self.plot.block_zoom_signal = False def update_current_values(self, *args): if self.plot.region: self.range_modified(None) else: self.cursor_moved() def _update_visibile_entries(self): with self.lock: _item_cache = self._item_cache = {} _visible_entries = self._visible_entries = set() _visible_items = self._visible_items = {} iterator = QtWidgets.QTreeWidgetItemIterator(self.channel_selection) while item := iterator.value(): iterator += 1 if item.type() == ChannelsTreeItem.Channel: _item_cache[item.uuid] = item if item.uuid == self.info_uuid or ( item.exists and (item.checkState(item.NameColumn) == QtCore.Qt.CheckState.Checked or item._is_visible) ): entry = (item.origin_uuid, item.signal.name, item.uuid) _visible_entries.add(entry) _visible_items[entry] = item self.visible_entries_modified = True if self.plot.cursor1 is not None: self.cursor_moved() def visible_entries(self): return self._visible_entries def visible_items(self): return self._visible_items def xrange_changed(self, *args): if self.info.isVisible(): stats = self.plot.get_stats(self.info_uuid) self.info.set_stats(stats) if not self._inhibit_x_range_changed_signal: self.x_range_changed_signal.emit(self, self.plot.viewbox.viewRange()[0]) def zoom_changed(self, inplace=False): if self.enable_zoom_history and self.plot.signals and not self.plot.block_zoom_signal: snapshot = { "x": self.plot.viewbox.viewRange()[0], "y": {sig.uuid: sig.y_range for sig in self.plot.signals}, } if inplace: if not self.zoom_history: self.zoom_history.append(snapshot) self.zoom_history_index = 0 else: self.zoom_history[self.zoom_history_index] = snapshot else: if not self.zoom_history or self.zoom_history[self.zoom_history_index] != snapshot: self.zoom_history = self.zoom_history[: self.zoom_history_index + 1] self.zoom_history.append(snapshot) self.zoom_history_index = len(self.zoom_history) - 1 self.redo_btn.setEnabled(False) if len(self.zoom_history) > 1: self.undo_btn.setEnabled(True) class PlotGraphics(pg.PlotWidget): cursor_moved = QtCore.Signal(object) cursor_removed = QtCore.Signal() range_removed = QtCore.Signal() range_modified = QtCore.Signal(object) range_modified_finished = QtCore.Signal(object) cursor_move_finished = QtCore.Signal(object) xrange_changed = QtCore.Signal(object, object) computation_channel_inserted = QtCore.Signal(object) curve_clicked = QtCore.Signal(str) signals_enable_changed = QtCore.Signal() current_uuid_changed = QtCore.Signal(str) edit_channel_request = QtCore.Signal(object, object) add_channels_request = QtCore.Signal(list) zoom_changed = QtCore.Signal(bool) def __init__( self, signals=None, with_dots=False, origin=None, mdf=None, line_interconnect="line", x_axis="time", plot_parent=None, allow_cursor=True, *args, **kwargs, ): events = kwargs.pop("events", []) viewBox = ViewBoxWithCursor(plot=self) self.initial_x_range = "adjust" super().__init__(viewBox=viewBox) self.plotItem.vb.setLeftButtonAction(Plot.mouse_mode) self.lock = Lock() self.bookmarks = [] self.plot_parent = plot_parent self.setViewportUpdateMode(QtWidgets.QGraphicsView.ViewportUpdateMode.FullViewportUpdate) self.autoFillBackground() self._pixmap = None self._grid_pixmap = None self.locked = False self.cursor_unit = "s" if x_axis == "time" else "Hz" self.line_interconnect = line_interconnect if line_interconnect != "line" else "" self._can_trim = True self._can_paint = True self._can_compute_all_timebase = True self._can_paint_global = True self.mdf = mdf self.setAcceptDrops(True) self._last_size = self.geometry() self._settings = QtCore.QSettings() self.setContentsMargins(1, 1, 1, 1) self.xrange_changed.connect(self.xrange_changed_handle) self.with_dots = with_dots self.current_uuid = None self.standalone = kwargs.get("standalone", False) self.region = None self.region_lock = None self.cursor1 = None self.cursor2 = None self.signals = [] self.axes = [] self._axes_layout_pos = 2 self._timebase_db = {} self._timestamps_indexes = {} self.all_timebase = self.timebase = np.array([]) for sig in self.signals: uuids = self._timebase_db.setdefault(id(sig.timestamps), set()) uuids.add(sig.uuid) # self._compute_all_timebase() self.showGrid(x=True, y=True) self.plot_item = self.plotItem self.plot_item.hideButtons() self.plotItem.showGrid(x=False, y=False) self.layout = self.plot_item.layout self.scene_ = self.plot_item.scene() self.scene_.sigMouseClicked.connect(self._clicked) self.viewbox = self.plot_item.vb self.viewbox.border = None self.viewbox.disableAutoRange() self.viewbox.sigCursorMoved.connect(self._cursor_moved) self.viewbox.sigZoomFinished.connect(self._cursor_zoom_finished) self.viewbox.sigZoomChanged.connect(self._cursor_zoom) self.x_range = self.y_range = (0, 1) self._curve = pg.PlotCurveItem( np.array([]), np.array([]), stepMode=self.line_interconnect, skipFiniteCheck=False, connect="finite", ) self.scene_.contextMenu = [] self.plot_item.setMenuEnabled(False, None) self.common_axis_items = set() self.common_axis_label = "" self.common_axis_y_range = (0, 1) if allow_cursor: start, stop = self.viewbox.viewRange()[0] pos = QtCore.QPointF((start + stop) / 2, 0) if pg.getConfigOption("background") == "k": color = "white" else: color = "black" self.cursor1 = Cursor(pos=pos, angle=90, movable=True, pen=color, hoverPen=color) self.viewbox.cursor = self.cursor1 self.viewbox.addItem(self.cursor1, ignoreBounds=True) self.cursor1.sigPositionChanged.connect(self.cursor_moved.emit) self.cursor1.sigPositionChangeFinished.connect(self.cursor_move_finished.emit) self.cursor_move_finished.emit(self.cursor1) self.cursor1.show() else: self.cursor1 = None self.viewbox.sigYRangeChanged.connect(self.y_changed) self.viewbox.sigRangeChangedManually.connect(self.y_changed) self.x_axis = FormatedAxis( "bottom", maxTickLength=5, background=self.backgroundBrush().color(), linked_signal=(self, None) ) if x_axis == "time": fmt = self._settings.value("plot_xaxis") if fmt == "seconds" or not fmt: fmt = "phys" else: fmt = "phys" self.x_axis.format = fmt self.x_axis.origin = origin.astimezone(LOCAL_TIMEZONE) self.y_axis = FormatedAxis( "left", maxTickLength=-5, background=self.backgroundBrush().color(), linked_signal=(self, None) ) self.y_axis.setWidth(48) self.y_axis.scale_editor_requested.connect(self.open_scale_editor) self.y_axis.rangeChanged.connect(self.set_y_range) self.plot_item.setAxisItems({"left": self.y_axis, "bottom": self.x_axis}) def plot_item_wheel_event(event): if event is not None: pos = event.pos() if pos.x() <= self.y_axis.width(): self.y_axis.wheelEvent(event) else: for axis in self.axes: if isinstance(axis, FormatedAxis) and axis.isVisible(): rect = axis.sceneBoundingRect() if rect.contains(pos): axis.wheelEvent(event) break def plot_item_mousePressEvent(event): if event is not None: pos = event.pos() if pos.x() <= self.y_axis.width(): if not self.locked: self.y_axis.mousePressEvent(event) else: for axis in self.axes: if isinstance(axis, FormatedAxis) and axis.isVisible(): rect = axis.sceneBoundingRect() if rect.contains(pos): if not self.locked: axis.mousePressEvent(event) break else: self.plot_item._mousePressEvent(event) def plot_item_mouseMoveEvent(event): if event is not None: pos = event.pos() if pos.x() <= self.y_axis.width(): self.y_axis.mouseMoveEvent(event) else: for axis in self.axes: if isinstance(axis, FormatedAxis) and axis.isVisible(): rect = axis.sceneBoundingRect() if rect.contains(pos): if not self.locked: axis.mouseMoveEvent(event) break else: self.plot_item._mouseMoveEvent(event) def plot_item_mouseReleaseEvent(event): if event is not None: pos = event.pos() if pos.x() <= self.y_axis.width(): self.y_axis.mouseReleaseEvent(event) else: for axis in self.axes: if isinstance(axis, FormatedAxis) and axis.isVisible(): rect = axis.sceneBoundingRect() if rect.contains(pos): if not self.locked: axis.mouseReleaseEvent(event) break else: self.plot_item._mouseReleaseEvent(event) self.plot_item.wheelEvent = plot_item_wheel_event self.plot_item._mousePressEvent = self.plot_item.mousePressEvent self.plot_item._mouseMoveEvent = self.plot_item.mouseMoveEvent self.plot_item._mouseReleaseEvent = self.plot_item.mouseReleaseEvent self.plot_item.mousePressEvent = plot_item_mousePressEvent self.plot_item.mouseMoveEvent = plot_item_mouseMoveEvent self.plot_item.mouseReleaseEvent = plot_item_mouseReleaseEvent self.viewbox_geometry = self.viewbox.sceneBoundingRect().toRect() self.viewbox.sigResized.connect(partial(self.xrange_changed_handle, force=True)) self._uuid_map = {} self._enabled_changed_signals = [] self._enable_timer = QtCore.QTimer() self._enable_timer.setSingleShot(True) self._enable_timer.timeout.connect(self._signals_enabled_changed_handler) self._update_timer = QtCore.QTimer() self._update_timer.setSingleShot(True) self._update_timer.timeout.connect(self.update) self._update_timer.setInterval(16) self._inhibit = False self.viewbox.setXRange(0, 10, update=False) if signals: self.add_new_channels(signals) self.viewbox.sigXRangeChanged.connect(self.xrange_changed.emit) self.disabled_keyboard_events = set() events = events or [] for i, event_info in enumerate(events): color = serde.COLORS[serde.COLORS_COUNT - (i % serde.COLORS_COUNT) - 1] if isinstance(event_info, (list, tuple)): to_display = event_info labels = [" - Start", " - End"] else: to_display = [event_info] labels = [""] for event, label in zip(to_display, labels, strict=False): bookmark = Bookmark( pos=event["value"], message=event["description"], title=f"{event['type']}{label}", color=color, tool=event.get("tool", ""), ) self.bookmarks.append(bookmark) self.viewbox.addItem(bookmark) self.viewbox.sigResized.connect(self.update_views) if signals: self.update_views() self.zoom = None self.px = 1 self.py = 1 self.last_click = perf_counter() self.flash_current_signal = 0 self.flash_curve_timer = QtCore.QTimer() self.flash_curve_timer.setSingleShot(True) self.flash_curve_timer.timeout.connect(self.update) self.block_zoom_signal = False def add_new_channels(self, channels, descriptions=None): descriptions = descriptions or {} initial_index = len(self.signals) self._can_paint = False for sig in channels.values(): if not sig.flags & Signal.Flags.computed: sig.computation = {} if initial_index == 0: start_t, stop_t = np.inf, -np.inf for sig in channels.values(): if len(sig): start_t = min(start_t, sig.timestamps[0]) stop_t = max(stop_t, sig.timestamps[-1]) if (start_t, stop_t) != (np.inf, -np.inf): if self.initial_x_range == "adjust": self.viewbox.setXRange(start_t, stop_t, update=False) else: delta = self.viewbox.viewRange()[0][1] - self.viewbox.viewRange()[0][0] stop_t = start_t + delta self.viewbox.setXRange(start_t, stop_t, padding=0, update=False) (start, stop), _ = self.viewbox.viewRange() width = self.viewbox.sceneBoundingRect().toRect().width() trim_info = start, stop, width channels = [ PlotSignal(sig, i, trim_info=trim_info) for i, sig in enumerate(channels.values(), len(self.signals)) ] for sig in self.signals: sig.path = None self.signals.extend(channels) for sig in channels: uuids = self._timebase_db.setdefault(id(sig.timestamps), set()) uuids.add(sig.uuid) self._compute_all_timebase() self._uuid_map = {sig.uuid: (sig, i) for i, sig in enumerate(self.signals)} axis_uuid = None for index, sig in enumerate(channels, initial_index): description = descriptions.get(sig.uuid, {}) if description: sig.enable = description.get("enabled", True) sig.format = description.get("format", "phys") y_range = description.get("y_range", None) if y_range: mn, mx = y_range if mn > mx: y_range = mx, mn else: y_range = tuple(y_range) sig.y_range = y_range elif not sig.empty: sig.y_range = sig.min, sig.max self.axes.append(self._axes_layout_pos) self._axes_layout_pos += 1 if initial_index == 0 and index == 0: axis_uuid = sig.uuid if axis_uuid is not None: self.set_current_uuid(sig.uuid) if len(self.all_timebase) and self.cursor1 is not None: self.cursor1.set_value(self.all_timebase[0]) self.viewbox._matrixNeedsUpdate = True self.viewbox.updateMatrix() self.zoom_changed.emit(True) return {sig.uuid: sig for sig in channels} def auto_clip_rect(self, painter): rect = self.viewbox.sceneBoundingRect() rect.setX(rect.x() + 5) rect.setWidth(rect.width() - 5) rect.setHeight(rect.height() - 1) painter.setClipRect(rect) painter.setClipping(True) return rect def _clicked(self, event): modifiers = QtWidgets.QApplication.keyboardModifiers() pos = self.plot_item.vb.mapSceneToView(event.scenePos()).x() start, stop = self.viewbox.viewRange()[0] if not start <= pos <= stop: return scene_pos = event.scenePos() pos = self.plot_item.vb.mapSceneToView(scene_pos) x = pos.x() y = event.scenePos().y() for bookmark in self.bookmarks: if not bookmark.visible: continue rect = bookmark.label.textItem.sceneBoundingRect() if rect.contains(scene_pos): if bookmark.editable: edit_rect = QtCore.QRectF( rect.x() + rect.width() - 35, rect.y() + 1, 18, 18, ) if edit_rect.contains(scene_pos): comment, submit = QtWidgets.QInputDialog.getMultiLineText( self, "Edit bookmark comments", f"Enter new comments for cursor position {bookmark.value():.9f}s:", bookmark.message, ) if submit: bookmark.message = comment bookmark.edited = True delete_rect = QtCore.QRectF( rect.x() + rect.width() - 18, rect.y() + 1, 18, 18, ) if delete_rect.contains(scene_pos): bookmark.deleted = True bookmark.visible = False break else: if ( QtCore.QKeyCombination(QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier).toCombined() not in self.disabled_keyboard_events ): if self.region is not None: start, stop = self.region.getRegion() if self.region_lock is not None: self.region.moving_cursor.setPos(pos) else: if modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: self.region.setRegion((start, pos.x())) else: self.region.setRegion((pos.x(), stop)) else: if self.cursor1 is not None: self.cursor1.setPos(pos) self.cursor1.sigPositionChangeFinished.emit(self.cursor1) now = perf_counter() if modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: self.select_curve(x, y) elif now - self.last_click < 0.3: self.select_curve(x, y) self.last_click = perf_counter() def close(self): self.viewbox.blockSignals(True) self.scene_.blockSignals(True) if self.cursor1 is not None: self.cursor1.blockSignals(True) if self.region is not None: self.region.blockSignals(True) self._enable_timer.stop() self._enable_timer.blockSignals(True) self.flash_curve_timer.stop() self.flash_curve_timer.blockSignals(True) self.y_axis.blockSignals(True) if self.plotItem is not None: self._can_trim = False self._can_paint = False self._can_compute_all_timebase = False self._can_paint_global = False self.plot_parent = None self.mdf = None super().close() def _compute_all_timebase(self): if self._can_compute_all_timebase: if self._timebase_db: stamps = {id(sig.timestamps): sig.timestamps for sig in self.signals} timebases = [timestamps for id_, timestamps in stamps.items() if id_ in self._timebase_db] count = len(timebases) if count == 0: new_timebase = np.array([]) elif count == 1: new_timebase = timebases[0] else: try: new_timebase = np.unique(np.concatenate(timebases)) except MemoryError: new_timebase = reduce(np.union1d, timebases) self.all_timebase = self.timebase = new_timebase else: self.all_timebase = self.timebase = np.array([]) def _cursor_moved(self, event): pos = self.plot_item.vb.mapSceneToView(event.scenePos()).x() start, stop = self.viewbox.viewRange()[0] if not start <= pos <= stop: return scene_pos = event.scenePos() pos = self.plot_item.vb.mapSceneToView(scene_pos) x = pos.x() y = event.scenePos().y() if self.region and self.region.moving_cursor is not None: self.region.moving_cursor.setPos(pos) elif self.cursor1 is not None: self.cursor1.setPos(pos) self.cursor1.sigPositionChangeFinished.emit(self.cursor1) def _cursor_zoom(self, zoom): self.zoom = zoom if zoom is not None: self.update() def _cursor_zoom_finished(self, zoom=None): p1, p2, zoom_mode = zoom self.block_zoom_signal = True if zoom_mode in (self.viewbox.Y_zoom, *self.viewbox.XY_zoom) and not self.locked: y1, y2 = sorted([p1.y(), p2.y()]) y_bottom, y_top = self.viewbox.viewRange()[1] r_top = (y2 - y_bottom) / (y_top - y_bottom) r_bottom = (y1 - y_bottom) / (y_top - y_bottom) for sig in self.signals: sig_y_bottom, sig_y_top = sig.y_range delta = sig_y_top - sig_y_bottom sig_y_top = sig_y_bottom + r_top * delta sig_y_bottom = sig_y_bottom + r_bottom * delta sig, idx = self.signal_by_uuid(sig.uuid) axis = self.axes[idx] if isinstance(axis, FormatedAxis): axis.setRange(sig_y_bottom, sig_y_top) else: self.set_y_range(sig.uuid, (sig_y_bottom, sig_y_top)) if zoom_mode in (self.viewbox.X_zoom, *self.viewbox.XY_zoom): x1, x2 = sorted([p1.x(), p2.x()]) self.viewbox.setXRange(x1, x2, padding=0) self.block_zoom_signal = False self.zoom_changed.emit(False) def curve_clicked_handle(self, curve, ev, uuid): self.curve_clicked.emit(uuid) def delete_channels(self, deleted): self._can_paint = False needs_timebase_compute = False uuid_map = self._uuid_map indexes = sorted( [(uuid_map[uuid][1], uuid) for uuid in deleted if uuid in uuid_map], reverse=True, ) for i, uuid in indexes: item = self.axes.pop(i) if isinstance(item, FormatedAxis): self.layout.removeItem(item) item.scene().removeItem(item) item.unlinkFromView() sig = self.signals.pop(i) if uuid in self.common_axis_items: self.common_axis_items.remove(uuid) if sig.enable: try: self._timebase_db[id(sig.timestamps)].remove(sig.uuid) if len(self._timebase_db[id(sig.timestamps)]) == 0: del self._timebase_db[id(sig.timestamps)] needs_timebase_compute = True except KeyError: pass uuids = [sig.uuid for sig in self.signals] self._uuid_map = {sig.uuid: (sig, i) for i, sig in enumerate(self.signals)} if uuids: if self.current_uuid in uuids: self.set_current_uuid(self.current_uuid, True) else: self.set_current_uuid(uuids[0], True) else: self.current_uuid = None if needs_timebase_compute: self._compute_all_timebase() self._can_paint = True self.update() def dragEnterEvent(self, e): if e.mimeData().hasFormat("application/octet-stream-asammdf"): e.accept() super().dragEnterEvent(e) def draw_grids(self, paint, event_rect, ratio, clip_rect): if self._grid_pixmap is None: _pixmap = QtGui.QPixmap(ceil(ceil(event_rect.width()) * ratio), ceil(ceil(event_rect.height()) * ratio)) _pixmap.fill(QtCore.Qt.transparent) paint = QtGui.QPainter() paint.begin(_pixmap) paint.setCompositionMode(QtGui.QPainter.CompositionMode.CompositionMode_SourceOver) paint.setRenderHints(paint.RenderHint.Antialiasing, False) clip_rect.setSize(clip_rect.size() * ratio) clip_rect.moveTo(clip_rect.topLeft() * ratio) paint.setClipRect(clip_rect) if self.y_axis.grid or self.x_axis.grid: rect = self.viewbox.sceneBoundingRect() y_delta = rect.y() * ratio x_delta = rect.x() * ratio if self.y_axis.grid and self.y_axis.isVisible(): for pen, p1, p2 in self.y_axis.tickSpecs: pen2 = fn.mkPen(pen) pen2.setStyle(QtCore.Qt.PenStyle.DashLine) y_pos = p1.y() + y_delta paint.setPen(pen2) paint.drawLine( QtCore.QPointF(0, y_pos), QtCore.QPointF((event_rect.x() + event_rect.width()) * ratio, y_pos), ) if self.x_axis.grid and self.x_axis.isVisible(): for pen, p1, p2 in self.x_axis.tickSpecs: pen2 = fn.mkPen(pen) pen2.setStyle(QtCore.Qt.PenStyle.DashLine) x_pos = p1.x() + x_delta paint.setPen(pen2) paint.drawLine( QtCore.QPointF(x_pos, 0), QtCore.QPointF(x_pos, (event_rect.y() + event_rect.height()) * ratio), ) paint.end() _pixmap.setDevicePixelRatio(self.devicePixelRatio()) self._grid_pixmap = _pixmap return self._grid_pixmap def dropEvent(self, e): if e.source() is self.plot_parent.channel_selection: super().dropEvent(e) else: data = e.mimeData() if data.hasFormat("application/octet-stream-asammdf"): names = extract_mime_names(data) self.add_channels_request.emit(names) else: e.ignore() def edit_computation(self, item): signal = item.signal functions = self.plot_parent.owner.functions mdf = self.mdf or self.plot_parent.owner.generate_mdf() dlg = DefineChannel( mdf=mdf, computation=signal.computation, functions=functions, global_variables=self.plot_parent.owner.global_variables, parent=self, ) dlg.setModal(True) dlg.exec_() computed_channel = dlg.result if self.mdf is None: mdf.close() if computed_channel is not None: self.edit_channel_request.emit(computed_channel, item) def generatePath(self, x, y, sig=None): if sig is None or sig.path is None: if x is None or len(x) == 0 or y is None or len(y) == 0: path = QtGui.QPainterPath() else: path = self._curve.generatePath(x, y) if sig is not None: sig.path = path else: path = sig.path return path def get_axis(self, index): axis = self.axes[index] if isinstance(axis, int): sig = self.signals[index] position = axis axis = FormatedAxis( "left", pen=sig.pen, textPen=sig.pen, text=sig.name if len(sig.name) <= 32 else "{sig.name[:29]}...", units=sig.unit, uuid=sig.uuid, locked=self.locked, maxTickLength=5, background=self.backgroundBrush().color(), linked_signal=(self, sig.uuid), ) axis.scale_editor_requested.connect(self.open_scale_editor) if sig.conversion and hasattr(sig.conversion, "text_0"): axis.text_conversion = sig.conversion axis.setRange(*sig.y_range) axis.rangeChanged.connect(self.set_y_range) axis.hide() self.layout.addItem(axis, 2, position) self.axes[index] = axis return axis def get_current_timebase(self): if self.current_uuid: sig, _ = self._uuid_map[self.current_uuid] t = sig.timestamps if t.size: return t else: return self.all_timebase else: return self.all_timebase def get_stats(self, uuid): try: sig, index = self.signal_by_uuid(uuid) except KeyError: return {} else: return sig.get_stats( cursor=self.cursor1.value() if self.cursor1 else None, region=self.region.getRegion() if self.region else None, view_region=self.viewbox.viewRange()[0], precision=self._settings.value("stats_float_precision", sig.precision, type=int), ) def get_timestamp_index(self, timestamp, timestamps): key = id(timestamps), timestamp if key in self._timestamps_indexes: return self._timestamps_indexes[key] else: if timestamps.size: if timestamp >= timestamps[-1]: index = -1 elif timestamp <= timestamps[0]: index = 0 else: index = np.searchsorted(timestamps, timestamp, side="right") - 1 else: index = None if len(self._timestamps_indexes) > 100000: self._timestamps_indexes.clear() self._timestamps_indexes[key] = index return index def insert_computation(self, name=""): functions = self.plot_parent.owner.functions if not functions: MessageBox.warning( self, "Cannot add computed channel", "There is no user defined function. Create new function using the Functions Manger (F6)", ) return mdf = self.mdf or self.plot_parent.owner.generate_mdf() dlg = DefineChannel( mdf=mdf, computation=None, functions=functions, global_variables=self.plot_parent.owner.global_variables, parent=self, ) dlg.setModal(True) dlg.exec_() computed_channel = dlg.result if self.mdf is None: mdf.close() if computed_channel is not None: self.add_channels_request.emit([computed_channel]) def keyPressEvent(self, event): if event.keyCombination().toCombined() in self.disabled_keyboard_events: event.ignore() return key = event.key() modifier = event.modifiers() handled = True if key == QtCore.Qt.Key.Key_Y and modifier == QtCore.Qt.KeyboardModifier.NoModifier: if self.region is None: event_ = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_R, QtCore.Qt.KeyboardModifier.NoModifier ) self.keyPressEvent(event_) if self.region_lock is not None: self.region_lock = None for i in range(2): self.region.lines[i].setMovable(True) self.region.lines[i].locked = False self.region.movable = True self.region.moving_cursor = self.region.lines[0] else: self.region_lock = self.region.getRegion()[0] self.region.lines[0].setMovable(False) self.region.lines[0].locked = True self.region.lines[1].setMovable(True) self.region.lines[1].locked = False self.region.moving_cursor = self.region.lines[1] self.region.movable = False self.update() elif key == QtCore.Qt.Key.Key_Y and modifier == QtCore.Qt.KeyboardModifier.ShiftModifier: if self.region is None: event_ = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_R, QtCore.Qt.KeyboardModifier.NoModifier ) self.keyPressEvent(event_) self.region.lines[0].setMovable(False) self.region.lines[0].locked = True self.region.lines[1].setMovable(True) self.region.lines[1].locked = False self.region.movable = False self.region.moving_cursor = self.region.lines[1] self.region_lock = self.region.lines[0].value() else: if self.region.lines[0].isMovable(): self.region_lock = self.region.lines[0].value() self.region.lines[0].setMovable(False) self.region.lines[0].locked = True self.region.lines[1].setMovable(True) self.region.lines[1].locked = False self.region.moving_cursor = self.region.lines[1] else: self.region_lock = self.region.lines[1].value() self.region.lines[0].setMovable(True) self.region.lines[0].locked = False self.region.lines[1].setMovable(False) self.region.lines[1].locked = True self.region.moving_cursor = self.region.lines[0] self.update() elif key == QtCore.Qt.Key.Key_X and modifier == QtCore.Qt.KeyboardModifier.NoModifier: if self.region is not None: self.viewbox.setXRange(*self.region.getRegion(), padding=0) event_ = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_R, QtCore.Qt.KeyboardModifier.NoModifier ) self.keyPressEvent(event_) elif key == QtCore.Qt.Key.Key_F and modifier == QtCore.Qt.KeyboardModifier.NoModifier and not self.locked: self.block_zoom_signal = True if self.common_axis_items: if any( len(self.signal_by_uuid(uuid)[0].plot_samples) for uuid in self.common_axis_items if self.signal_by_uuid(uuid)[0].enable ): common_min = np.nanmin( [ self.signal_by_uuid(uuid)[0].min for uuid in self.common_axis_items if len(self.signal_by_uuid(uuid)[0].plot_samples) ] ) common_max = np.nanmax( [ self.signal_by_uuid(uuid)[0].max for uuid in self.common_axis_items if len(self.signal_by_uuid(uuid)[0].plot_samples) ] ) else: common_min, common_max = 0, 1 for i, signal in enumerate(self.signals): if len(signal.plot_samples): if signal.uuid in self.common_axis_items: min_ = common_min max_ = common_max else: samples = signal.plot_samples if len(samples): min_, max_ = signal.min, signal.max else: min_, max_ = 0, 1 if min_ != min_: # noqa: PLR0124 # min_ is NaN min_ = 0 if max_ != max_: # noqa: PLR0124 # max_ is NaN max_ = 1 delta = 0.01 * (max_ - min_) min_, max_ = min_ - delta, max_ + delta signal.y_range = min_, max_ if signal.uuid == self.current_uuid: self.viewbox.setYRange(min_, max_, padding=0) self.block_zoom_signal = False self.zoom_changed.emit(False) self.update() elif key == QtCore.Qt.Key.Key_F and modifier == QtCore.Qt.KeyboardModifier.ShiftModifier and not self.locked: self.block_zoom_signal = True parent = self.plot_parent uuids = [ item.uuid for item in parent.channel_selection.selectedItems() if item.type() == ChannelsTreeItem.Channel ] uuids = set(uuids) if not uuids: return for i, signal in enumerate(self.signals): if signal.uuid not in uuids: continue if len(signal.plot_samples): samples = signal.plot_samples if len(samples): min_, max_ = signal.min, signal.max else: min_, max_ = 0, 1 if min_ != min_: # noqa: PLR0124 # min_ is NaN min_ = 0 if max_ != max_: # noqa: PLR0124 # max is NaN max_ = 1 delta = 0.01 * (max_ - min_) min_, max_ = min_ - delta, max_ + delta signal.y_range = min_, max_ if signal.uuid == self.current_uuid: self.viewbox.setYRange(min_, max_, padding=0) self.block_zoom_signal = False self.zoom_changed.emit(False) self.update() elif key == QtCore.Qt.Key.Key_G: if modifier == QtCore.Qt.KeyboardModifier.NoModifier: next_grid = { (False, False): (True, False), (True, False): (True, True), (True, True): (False, True), (False, True): (False, False), } self.x_axis.grid, self.y_axis.grid = next_grid[(self.x_axis.grid, self.y_axis.grid)] self.x_axis.picture = None self.y_axis.picture = None self.update() elif modifier == QtCore.Qt.KeyboardModifier.ShiftModifier: if self.cursor1 is not None: value, ok = QtWidgets.QInputDialog.getDouble( self, "Go to time stamp", "Time stamp", value=self.cursor1.value(), decimals=9, ) if ok: self.cursor1.setPos(value) self.cursor_move_finished.emit(self.cursor1) elif key in (QtCore.Qt.Key.Key_I, QtCore.Qt.Key.Key_O) and modifier == QtCore.Qt.KeyboardModifier.NoModifier: x_range, _ = self.viewbox.viewRange() delta = x_range[1] - x_range[0] if key == QtCore.Qt.Key.Key_I: step = -delta * 0.25 else: step = delta * 0.5 if ( self.cursor1 and self.cursor1.isVisible() and self._settings.value("zoom_x_center_on_cursor", True, type=bool) ): pos = self.cursor1.value() x_range = pos - delta / 2, pos + delta / 2 self.viewbox.setXRange(x_range[0] - step, x_range[1] + step, padding=0) elif ( key in (QtCore.Qt.Key.Key_I, QtCore.Qt.Key.Key_O) and modifier == QtCore.Qt.KeyboardModifier.ShiftModifier and not self.locked ): self.block_zoom_signal = True self.viewbox.vertical_zoom(zoom_in=key == QtCore.Qt.Key.Key_I) self.block_zoom_signal = False self.zoom_changed.emit(False) elif key == QtCore.Qt.Key.Key_R and modifier == QtCore.Qt.KeyboardModifier.NoModifier: if self.region is None: color = self.cursor1.pen.color().name() self.region = Region( (0, 0), pen=color, hoverPen=color, show_circle=self.cursor1.show_circle, show_horizontal_line=self.cursor1.show_horizontal_line, line_width=self.cursor1.line_width, ) self.region.setZValue(-10) self.viewbox.addItem(self.region) self.region.sigRegionChanged.connect(self.range_modified.emit) self.region.sigRegionChanged.connect(self.range_modified_handler) self.region.sigRegionChangeFinished.connect(self.range_modified_finished_handler) start, stop = self.viewbox.viewRange()[0] view_range = abs(stop - start) start, stop = ( start + 0.1 * (stop - start), stop - 0.1 * (stop - start), ) if self.cursor1 is not None and abs(self.cursor1.value() - stop) >= 0.1 * view_range: self.cursor1.hide() self.region.setRegion(tuple(sorted((self.cursor1.value(), stop)))) else: self.region.setRegion((start, stop)) else: self.region_lock = None self.region.setParent(None) self.region.hide() self.region.deleteLater() self.region = None self.range_removed.emit() if self.cursor1 is not None: self.cursor1.show() self.update() elif key == QtCore.Qt.Key.Key_S and modifier == QtCore.Qt.KeyboardModifier.ControlModifier: file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Save as measurement file", "", "MDF version 4 files (*.mf4 *.mf4z)", ) if file_name: signals = [signal for signal in self.signals if signal.enable] if signals: with mdf_module.MDF() as mdf: groups = {} for sig in signals: id_ = id(sig.timestamps) group_ = groups.setdefault(id_, []) group_.append(sig) for signals in groups.values(): sigs = [] for signal in signals: if ":" in signal.name: sig = signal.copy() sig.name = sig.name.split(":")[-1].strip() sigs.append(sig) else: sigs.append(signal) mdf.append(sigs, common_timebase=True) file_name = Path(file_name) if file_name.suffix.lower() in (".zip", ".mf4z"): tmpf = Path(gettempdir()) / f"{perf_counter()}.mf4" mdf.save(tmpf, overwrite=True, compression=2) zipped_mf4 = ZipFile(file_name, "w", compression=ZIP_DEFLATED) zipped_mf4.write( str(tmpf), file_name.with_suffix(".mf4").name, compresslevel=1, ) tmpf.unlink() else: mdf.save(file_name, overwrite=True, compression=2) elif key == QtCore.Qt.Key.Key_S and modifier == QtCore.Qt.KeyboardModifier.NoModifier and not self.locked: self.block_zoom_signal = True parent = self.plot_parent uuids = [] iterator = QtWidgets.QTreeWidgetItemIterator(parent.channel_selection) while item := iterator.value(): if item.type() == ChannelsTreeItem.Channel and item.signal.enable: uuids.append(item.uuid) iterator += 1 uuids = reversed(uuids) count = sum( 1 for sig in self.signals if sig.min != "n.a." and sig.enable and sig.uuid not in self.common_axis_items ) if any(sig.min != "n.a." and sig.enable and sig.uuid in self.common_axis_items for sig in self.signals): count += 1 common_min_ = np.nanmin( [ self.signal_by_uuid(uuid)[0].min for uuid in self.common_axis_items if len(self.signal_by_uuid(uuid)[0].plot_samples) and self.signal_by_uuid(uuid)[0].enable ] ) common_max_ = np.nanmax( [ self.signal_by_uuid(uuid)[0].max for uuid in self.common_axis_items if len(self.signal_by_uuid(uuid)[0].plot_samples) and self.signal_by_uuid(uuid)[0].enable ] ) if count: position = 0 common_axis_handled = False for uuid in uuids: signal, index = self.signal_by_uuid(uuid) if not signal.empty and signal.enable: if signal.uuid in self.common_axis_items: if common_axis_handled: continue min_ = common_min_ max_ = common_max_ else: min_ = signal.min max_ = signal.max if min_ == -float("inf") and max_ == float("inf"): min_ = 0 max_ = 1 elif min_ == -float("inf"): min_ = max_ - 1 elif max_ == float("inf"): max_ = min_ + 1 if min_ == max_: min_, max_ = min_ - 1, max_ + 1 dim = (float(max_) - min_) * 1.1 max_ = min_ + dim * count - 0.05 * dim min_ = min_ - 0.05 * dim min_, max_ = ( min_ - dim * position, max_ - dim * position, ) if signal.uuid in self.common_axis_items: y_range = min_, max_ self.common_axis_y_range = y_range for cuuid in self.common_axis_items: sig, _ = self.signal_by_uuid(cuuid) sig.y_range = y_range common_axis_handled = True else: signal.y_range = min_, max_ if signal.uuid == self.current_uuid: self.viewbox.setYRange(min_, max_, padding=0) position += 1 else: xrange, _ = self.viewbox.viewRange() self.viewbox.autoRange(padding=0) self.viewbox.setXRange(*xrange, padding=0) self.viewbox.disableAutoRange() self.block_zoom_signal = False self.zoom_changed.emit(False) self.update() elif key == QtCore.Qt.Key.Key_S and modifier == QtCore.Qt.KeyboardModifier.ShiftModifier and not self.locked: self.block_zoom_signal = True parent = self.plot_parent uuids = [ item.uuid for item in parent.channel_selection.selectedItems() if item.type() == ChannelsTreeItem.Channel ] uuids = list(reversed(uuids)) uuids_set = set(uuids) if not uuids: return count = sum( 1 for i, sig in enumerate(self.signals) if sig.uuid in uuids_set and sig.min != "n.a." and sig.enable ) if count: common_axis_handled = False position = 0 for uuid in uuids: signal, index = self.signal_by_uuid(uuid) if not signal.empty and signal.enable: if uuid in self.common_axis_items: if common_axis_handled: continue min_ = np.nanmin( [ self.signal_by_uuid(uuid)[0].min for uuid in self.common_axis_items if uuid in uuids_set and len(self.signal_by_uuid(uuid)[0].plot_samples) and self.signal_by_uuid(uuid)[0].enable ] ) max_ = np.nanmax( [ self.signal_by_uuid(uuid)[0].max for uuid in self.common_axis_items if uuid in uuids_set and len(self.signal_by_uuid(uuid)[0].plot_samples) and self.signal_by_uuid(uuid)[0].enable ] ) else: min_ = signal.min max_ = signal.max if min_ == -float("inf") and max_ == float("inf"): min_ = 0 max_ = 1 elif min_ == -float("inf"): min_ = max_ - 1 elif max_ == float("inf"): max_ = min_ + 1 if min_ == max_: min_, max_ = min_ - 1, max_ + 1 dim = (float(max_) - min_) * 1.1 max_ = min_ + dim * count - 0.05 * dim min_ = min_ - 0.05 * dim min_, max_ = ( min_ - dim * position, max_ - dim * position, ) if signal.uuid in self.common_axis_items: y_range = min_, max_ self.common_axis_y_range = y_range for cuuid in self.common_axis_items: sig, _ = self.signal_by_uuid(cuuid) sig.y_range = y_range common_axis_handled = True else: signal.y_range = min_, max_ if signal.uuid == self.current_uuid: self.viewbox.setYRange(min_, max_, padding=0) position += 1 else: xrange, _ = self.viewbox.viewRange() self.viewbox.autoRange(padding=0) self.viewbox.setXRange(*xrange, padding=0) self.viewbox.disableAutoRange() self.block_zoom_signal = False self.zoom_changed.emit(False) self.update() elif ( key in (QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right) and modifier == QtCore.Qt.KeyboardModifier.AltModifier ): if self.region is None: pos = self.cursor1.value() sig, idx = self.signal_by_uuid(self.current_uuid) timestamp = sig.timestamp_of_next_different_value( pos, mode="different", previous=key == QtCore.Qt.Key.Key_Left ) self.cursor1.set_value(timestamp) view_range = self.viewbox.viewRange()[0] x_size = view_range[1] - view_range[0] self.viewbox.setXRange(timestamp - x_size / 2, timestamp + x_size / 2, padding=0) else: pos = self.region.moving_cursor.value() sig, idx = self.signal_by_uuid(self.current_uuid) timestamp = sig.timestamp_of_next_different_value( pos, mode="different", previous=key == QtCore.Qt.Key.Key_Left ) self.region.moving_cursor.set_value(timestamp) view_range = sorted([line.value() for line in self.region.lines]) x_size = view_range[1] - view_range[0] self.viewbox.setXRange(view_range[0] - x_size * 0.05, view_range[1] + x_size * 0.05, padding=0) elif key in (QtCore.Qt.Key.Key_PageUp, QtCore.Qt.Key.Key_PageDown) and modifier in ( QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, QtCore.Qt.KeyboardModifier.ControlModifier, ): if self.region is None: pos = self.cursor1.value() sig, idx = self.signal_by_uuid(self.current_uuid) timestamp = sig.timestamp_of_next_different_value( pos, mode="higher" if key == QtCore.Qt.Key.Key_PageUp else "lower", previous=modifier == QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.cursor1.set_value(timestamp) view_range = self.viewbox.viewRange() x_size = view_range[1] - view_range[0] self.viewbox.setXRange(timestamp - x_size / 2, timestamp + x_size / 2, padding=0) else: pos = self.region.moving_cursor.value() sig, idx = self.signal_by_uuid(self.current_uuid) timestamp = sig.timestamp_of_next_different_value( pos, mode="higher" if key == QtCore.Qt.Key.Key_PageUp else "lower", previous=modifier == QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.region.moving_cursor.set_value(timestamp) view_range = sorted([line.value() for line in self.region.lines]) x_size = view_range[1] - view_range[0] self.viewbox.setXRange(view_range[0] - x_size * 0.05, view_range[1] + x_size * 0.05, padding=0) elif key in (QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right) and modifier in ( QtCore.Qt.KeyboardModifier.NoModifier, QtCore.Qt.KeyboardModifier.ControlModifier, ): if self.region is None: if modifier == QtCore.Qt.KeyboardModifier.ControlModifier: increment = 20 else: increment = 1 prev_pos = pos = self.cursor1.value() x = self.get_current_timebase() dim = x.size if dim: pos = np.searchsorted(x, pos) if key == QtCore.Qt.Key.Key_Right: pos += increment else: pos -= increment pos = np.clip(pos, 0, dim - increment) pos = x[pos] else: if key == QtCore.Qt.Key.Key_Right: pos += increment else: pos -= increment (left_side, right_side), _ = self.viewbox.viewRange() if pos >= right_side: delta = abs(pos - prev_pos) self.viewbox.setXRange(left_side + delta, right_side + delta, padding=0) elif pos <= left_side: delta = abs(pos - prev_pos) self.viewbox.setXRange(left_side - delta, right_side - delta, padding=0) self.cursor1.set_value(pos) else: increment = 1 start, stop = self.region.getRegion() if self.region_lock is None: if modifier == QtCore.Qt.KeyboardModifier.ControlModifier: pos = stop second_pos = start else: pos = start second_pos = stop else: if start != stop: pos = start if stop == self.region_lock else stop else: pos = self.region_lock x = self.get_current_timebase() dim = x.size if dim: pos = np.searchsorted(x, pos) if key == QtCore.Qt.Key.Key_Right: pos += increment else: pos -= increment pos = np.clip(pos, 0, dim - increment) pos = x[pos] else: if key == QtCore.Qt.Key.Key_Right: pos += increment else: pos -= increment (left_side, right_side), _ = self.viewbox.viewRange() if pos >= right_side: self.viewbox.setXRange(left_side, pos, padding=0) elif pos <= left_side: self.viewbox.setXRange(pos, right_side, padding=0) if self.region_lock is not None: self.region.setRegion((self.region_lock, pos)) else: self.region.setRegion(tuple(sorted((second_pos, pos)))) elif ( key in (QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right) and modifier == QtCore.Qt.KeyboardModifier.ShiftModifier ): parent = self.plot_parent uuids = list( { item.uuid for item in parent.channel_selection.selectedItems() if item.type() == ChannelsTreeItem.Channel } ) if not uuids: return start, stop = self.viewbox.viewRange()[0] offset = (stop - start) / 100 if key == QtCore.Qt.Key.Key_Left: offset = -offset self.set_time_offset([False, offset, *uuids]) elif ( key in ( QtCore.Qt.Key.Key_Up, QtCore.Qt.Key.Key_Down, QtCore.Qt.Key.Key_PageUp, QtCore.Qt.Key.Key_PageDown, ) and modifier == QtCore.Qt.KeyboardModifier.ShiftModifier ): parent = self.plot_parent uuids = list( { item.uuid for item in parent.channel_selection.selectedItems() if item.type() == ChannelsTreeItem.Channel } ) if not uuids: return factor = 10 if key in (QtCore.Qt.Key.Key_PageUp, QtCore.Qt.Key.Key_PageDown) else 100 for uuid in uuids: signal, index = self.signal_by_uuid(uuid) bottom, top = signal.y_range step = (top - bottom) / factor if key in (QtCore.Qt.Key.Key_Up, QtCore.Qt.Key.Key_PageUp): step = -step signal.y_range = bottom + step, top + step self.zoom_changed.emit(False) self.update() elif key == QtCore.Qt.Key.Key_H and modifier == QtCore.Qt.KeyboardModifier.NoModifier: start_ts, stop_ts = self.viewbox.viewRange()[0] if len(self.all_timebase): min_start_ts = np.amin(self.all_timebase) max_stop_ts = np.amax(self.all_timebase) else: min_start_ts = start_ts max_stop_ts = stop_ts rect = self.viewbox.sceneBoundingRect() width = rect.width() - 5 dpi = QtWidgets.QApplication.primaryScreen().physicalDotsPerInchX() dpc = dpi / 2.54 physical_viewbox_width = width / dpc # cm time_width = physical_viewbox_width * HONEYWELL_SECONDS_PER_CM if self.cursor1.isVisible(): mid = self.cursor1.value() else: mid = self.region.getRegion()[0] if mid - time_width / 2 < min_start_ts: start_ts = min_start_ts stop_ts = min_start_ts + time_width elif mid + time_width / 2 > max_stop_ts: start_ts = max_stop_ts - time_width stop_ts = max_stop_ts else: start_ts = mid - time_width / 2 stop_ts = mid + time_width / 2 self.viewbox.setXRange(start_ts, stop_ts, padding=0) if self.cursor1: self.cursor_moved.emit(self.cursor1) elif key == QtCore.Qt.Key.Key_W and modifier == QtCore.Qt.KeyboardModifier.NoModifier: if len(self.all_timebase): start_ts = np.amin(self.all_timebase) stop_ts = np.amax(self.all_timebase) self.viewbox.setXRange(start_ts, stop_ts) if self.cursor1: self.cursor_moved.emit(self.cursor1) elif key == QtCore.Qt.Key.Key_Insert and modifier == QtCore.Qt.KeyboardModifier.NoModifier: self.insert_computation() else: handled = False if not handled: event.ignore() self.parent().keyPressEvent(event) else: event.accept() def open_scale_editor(self, uuid): uuid = uuid or self.current_uuid if uuid is None: return signal, idx = self.signal_by_uuid(uuid) signals = {signal.name: signal} diag = ScaleDialog(signals, signal.y_range, parent=self) if diag.exec(): offset = diag.offset.value() scale = diag.scaling.value() y_bottom = -offset * scale / 100 y_top = y_bottom + scale signal.y_range = y_bottom, y_top self.zoom_changed.emit(False) self.update() def paintEvent(self, ev): if not self._can_paint or not self._can_paint_global: return event_rect = ev.rect() super().paintEvent(ev) ratio = self.devicePixelRatio() if self._pixmap is None: self._grid_pixmap = None _pixmap = QtGui.QPixmap(ceil(ceil(event_rect.width()) * ratio), ceil(ceil(event_rect.height()) * ratio)) _pixmap.fill(QtCore.Qt.transparent) paint = QtGui.QPainter() paint.begin(_pixmap) paint.setCompositionMode(QtGui.QPainter.CompositionMode.CompositionMode_SourceOver) paint.setRenderHints(paint.RenderHint.Antialiasing, False) self.x_range, self.y_range = self.viewbox.viewRange() rect = self.viewbox.sceneBoundingRect() rect.setSize(rect.size() * ratio) rect.moveTo(rect.topLeft() * ratio) self.px = (self.x_range[1] - self.x_range[0]) / rect.width() self.py = rect.height() with_dots = self.with_dots delta = rect.x() x_start = self.x_range[0] no_brush = QtGui.QBrush() pen_width = self._settings.value("line_width", 1, type=int) dots_with = self._settings.value("dots_width", 4, type=int) paint.resetTransform() paint.translate(0, 0) paint.setBrush(no_brush) flash_current_signal = self.flash_current_signal if self._settings.value("curve_dots_cap_style", "square") == "square": cap_style = QtCore.Qt.PenCapStyle.SquareCap else: cap_style = QtCore.Qt.PenCapStyle.RoundCap curve = self._curve step_mode = self.line_interconnect default_connect = curve.opts["connect"] for i, sig in enumerate(self.signals): if not sig.enable or ( flash_current_signal > 0 and flash_current_signal % 2 == 0 and sig.uuid == self.current_uuid ): continue y = sig.plot_samples x = sig.plot_timestamps if len(x): x, y = self.scale_curve_to_pixmap(x, y, y_range=sig.y_range, x_start=x_start, delta=delta) sig.pen.setWidth(pen_width) paint.setPen(sig.pen) pth = self.generatePath(x, y, sig) paint.drawPath(pth) if with_dots: paint.setRenderHints(paint.RenderHint.Antialiasing, True) pos = np.isfinite(y) y = y[pos] x = x[pos] _pen = fn.mkPen(sig.color.name()) _pen.setWidth(dots_with) _pen.setCapStyle(cap_style) paint.setPen(_pen) poly, arr = polygon_and_ndarray(x.size) arr[:, 0] = x arr[:, 1] = y paint.drawPoints(poly) paint.setRenderHints(paint.RenderHint.Antialiasing, False) item = self.plot_parent.item_by_uuid(sig.uuid) if not item: continue ranges = item.get_ranges() if ranges: for range_info in ranges: val = range_info["value1"] if val is not None and isinstance(val, float): op = range_info["op1"] if op == ">": idx1 = sig.plot_samples < val elif op == ">=": idx1 = sig.plot_samples <= val elif op == "<": idx1 = sig.plot_samples > val elif op == "<=": idx1 = sig.plot_samples >= val elif op == "==": idx1 = sig.plot_samples == val elif op == "!=": idx1 = sig.plot_samples != val else: idx1 = None val = range_info["value2"] if val is not None and isinstance(val, float): op = range_info["op2"] if op == ">": idx2 = sig.plot_samples > val elif op == ">=": idx2 = sig.plot_samples >= val elif op == "<": idx2 = sig.plot_samples < val elif op == "<=": idx2 = sig.plot_samples <= val elif op == "==": idx2 = sig.plot_samples == val elif op == "!=": idx2 = sig.plot_samples != val else: idx2 = None if idx1 is not None or idx2 is not None: if idx1 is None: idx = idx2 elif idx2 is None: idx = idx1 else: idx = idx1 & idx2 if not np.any(idx): continue if step_mode == "right": idx_with_edges = get_idx_with_edges(idx) _connect = "finite" y = sig.plot_samples.astype("f8") y[~idx_with_edges] = np.inf x = sig.plot_timestamps elif step_mode == "": last = idx[-1] idx_with_edges = np.roll(idx, -1) idx_with_edges[-1] = last _connect = idx_with_edges.view("u1") y = sig.plot_samples.astype("f8") x = sig.plot_timestamps elif step_mode == "left": idx_with_edges = np.repeat(get_idx_with_edges(idx), 2) idx_with_edges = np.insert(idx_with_edges, 0, idx_with_edges[0]) _connect = idx_with_edges[:-1].view("u1") y = sig.plot_samples.astype("f8") x = sig.plot_timestamps curve.opts["connect"] = _connect x, y = self.scale_curve_to_pixmap(x, y, y_range=sig.y_range, x_start=x_start, delta=delta) color = range_info["font_color"] pen = fn.mkPen(color.name()) pen.setWidth(pen_width) paint.setPen(pen) paint.drawPath(self.generatePath(x, y)) curve.opts["connect"] = default_connect if with_dots: y = sig.plot_samples.astype("f8") y[~idx] = np.inf x = sig.plot_timestamps x, y = self.scale_curve_to_pixmap( x, y, y_range=sig.y_range, x_start=x_start, delta=delta ) paint.setRenderHints(paint.RenderHint.Antialiasing, True) pen.setWidth(dots_with) pen.setCapStyle(cap_style) paint.setPen(pen) pos = np.isfinite(y) y = y[pos] x = x[pos] poly, arr = polygon_and_ndarray(x.size) arr[:, 0] = x arr[:, 1] = y paint.drawPoints(poly) paint.setRenderHints(paint.RenderHint.Antialiasing, False) paint.end() _pixmap.setDevicePixelRatio(self.devicePixelRatio()) else: _pixmap = self._pixmap paint = QtGui.QPainter() vp = self.viewport() paint.begin(vp) paint.setCompositionMode(QtGui.QPainter.CompositionMode.CompositionMode_SourceOver) paint.setRenderHint(paint.RenderHint.Antialiasing, False) if self.y_axis.picture is None: self.y_axis.paint(paint, None, None) if self.x_axis.picture is None: self.x_axis.paint(paint, None, None) r = self.y_axis.boundingRect() r.setSize(self.y_axis.picture.size()) r.moveTo(r.topLeft() * ratio) paint.drawPixmap( self.y_axis.sceneBoundingRect(), self.y_axis.picture, r, ) r = self.x_axis.boundingRect() r.setSize(self.x_axis.picture.size()) r.moveTo(r.topLeft() * ratio) paint.drawPixmap( self.x_axis.sceneBoundingRect(), self.x_axis.picture, r, ) for ax in self.axes: if isinstance(ax, FormatedAxis) and ax.isVisible(): if ax.picture is None: ax.paint(paint, None, None) r = ax.boundingRect() r.setSize(ax.picture.size()) r.moveTo(r.topLeft() * ratio) paint.drawPixmap( ax.sceneBoundingRect(), ax.picture, r, ) r = self.viewbox.sceneBoundingRect() r.setLeft(r.left() + 5) r.setSize(r.size() * ratio) r.moveTo(r.topLeft() * ratio) t = self.viewbox.sceneBoundingRect() t.setLeft(t.left() + 5) clip_rect = self.auto_clip_rect(paint) grid_pixmap = self.draw_grids(paint, event_rect, ratio, clip_rect) paint.drawPixmap(t.toRect(), grid_pixmap, r.toRect()) paint.drawPixmap(t.toRect(), _pixmap, r.toRect()) if self.zoom is None: if self.cursor1 is not None and self.cursor1.isVisible(): self.cursor1.paint(paint, plot=self, uuid=self.current_uuid) if self.region is not None: self.region.paint(paint, plot=self, uuid=self.current_uuid) for bookmark in self.bookmarks: if bookmark.visible: bookmark.paint(paint, plot=self, uuid=self.current_uuid) else: p1, p2, zoom_mode = self.zoom old_px, old_py = self.px, self.py rect = self.viewbox.sceneBoundingRect() self.px = (self.x_range[1] - self.x_range[0]) / rect.width() self.py = rect.height() delta = rect.x() height = rect.height() width = rect.width() x1, y1 = self.scale_curve_to_pixmap( p1.x(), p1.y(), y_range=self.viewbox.viewRange()[1], x_start=self.viewbox.viewRange()[0][0], delta=delta, ) x2, y2 = self.scale_curve_to_pixmap( p2.x(), p2.y(), y_range=self.viewbox.viewRange()[1], x_start=self.viewbox.viewRange()[0][0], delta=delta, ) rect = None if zoom_mode == self.viewbox.X_zoom or (zoom_mode in self.viewbox.XY_zoom and self.locked): x1, x2 = sorted([x1, x2]) rect = QtCore.QRectF( x1, 0, x2 - x1, height, ) elif zoom_mode == self.viewbox.Y_zoom and not self.locked: y1, y2 = sorted([y1, y2]) rect = QtCore.QRectF( 0, y1, width + delta, y2 - y1, ) elif zoom_mode in self.viewbox.XY_zoom: x1, x2 = sorted([x1, x2]) y1, y2 = sorted([y1, y2]) rect = QtCore.QRectF( x1, y1, x2 - x1, y2 - y1, ) if rect is not None: color = fn.mkColor(0x62, 0xB2, 0xE2) paint.setPen(fn.mkPen(color)) color = fn.mkColor(0x62, 0xB2, 0xE2, 50) paint.setBrush(fn.mkBrush(color)) paint.setCompositionMode(QtGui.QPainter.CompositionMode.CompositionMode_SourceAtop) paint.drawRect(rect) self.px, self.py = old_px, old_py paint.end() if self._pixmap is None: self._pixmap = _pixmap if self.cursor1 and self.flash_current_signal > 0: self.flash_current_signal -= 1 self.flash_curve_timer.start(50) def range_modified_finished_handler(self, region): if self.region_lock is not None: for i in range(2): if self.region.lines[i].value() == self.region_lock: self.region.lines[i].pen.setStyle(QtCore.Qt.PenStyle.DashDotDotLine) else: self.region.lines[i].pen.setStyle(QtCore.Qt.PenStyle.SolidLine) self.range_modified_finished.emit(region) if self.region.moving_cursor is not None: self.cursor1.setPos(self.region.moving_cursor.pos()) def range_modified_handler(self, region): if self.region_lock is not None: for i in range(2): if self.region.lines[i].value() == self.region_lock: self.region.lines[i].pen.setStyle(QtCore.Qt.PenStyle.DashDotDotLine) else: self.region.lines[i].pen.setStyle(QtCore.Qt.PenStyle.SolidLine) if self.region.moving_cursor is not None: self.cursor1.setPos(self.region.moving_cursor.pos()) def scale_curve_to_pixmap(self, x, y, y_range, x_start, delta): if self.py: y_low, y_high = y_range y_scale = (np.float64(y_high) - np.float64(y_low)) / np.float64(self.py) x_scale = self.px if y_scale * x_scale: all_bad = False else: all_bad = True else: all_bad = True if all_bad: try: y = np.full(len(y), np.inf) except: y = np.inf else: # xs = x_start # ys = y_high # x = (x - xs) / x_scale + delta # y = (ys - y) / y_scale + 1 # is rewriten as xs = x_start - delta * x_scale ys = y_high + y_scale x = (x - xs) / x_scale y = (ys - y) / y_scale return x, y def select_curve(self, x, y): ratio = self.devicePixelRatio() rect = self.viewbox.sceneBoundingRect() rect.setSize(rect.size() * ratio) rect.moveTo(rect.topLeft() * ratio) delta = rect.x() x_start = self.x_range[0] y = y * ratio candidates = [] for sig in self.signals: if not sig.enable: continue raw_value, raw_kind, val, _1, _2 = sig.value_at_timestamp(x, numeric=True) if val == "n.a.": continue x_val, y_val = self.scale_curve_to_pixmap(x, val, y_range=sig.y_range, x_start=x_start, delta=delta) candidates.append((abs(y_val - y), sig.uuid)) if candidates: candidates.sort() self.curve_clicked.emit(candidates[0][1]) def selected_items(self): uuids = self.plot_parent.selected_items() if self.current_uuid: uuids.add(self.current_uuid) return uuids, self.current_uuid def set_color(self, uuid, color): sig, index = self.signal_by_uuid(uuid) if sig.mode == "raw": style = QtCore.Qt.PenStyle.DashLine else: style = QtCore.Qt.PenStyle.SolidLine sig.pen = fn.mkPen(color=color, style=style) if sig.individual_axis: self.get_axis(index).set_pen(sig.pen) self.get_axis(index).setTextPen(sig.pen) if uuid == self.current_uuid: self.y_axis.set_pen(sig.pen) self.y_axis.setTextPen(sig.pen) if not self._update_timer.isActive(): self._update_timer.start() def set_common_axis(self, uuid, state): signal, idx = self.signal_by_uuid(uuid) if state in (QtCore.Qt.CheckState.Checked, True, 1): if not self.common_axis_items: self.common_axis_y_range = signal.y_range else: signal.y_range = self.common_axis_y_range self.common_axis_items.add(uuid) else: self.common_axis_items.remove(uuid) self.common_axis_label = ", ".join(self.signal_by_uuid(uuid)[0].name for uuid in self.common_axis_items) self.set_current_uuid(self.current_uuid, True) if not self._update_timer.isActive(): self._update_timer.start() def set_conversion(self, uuid, conversion): sig, index = self.signal_by_uuid(uuid) axis = self.axes[index] if isinstance(axis, FormatedAxis): if sig.conversion and hasattr(sig.conversion, "text_0"): axis.text_conversion = sig.conversion else: axis.text_conversion = None axis.picture = None if uuid == self.current_uuid: axis = self.y_axis if sig.conversion and hasattr(sig.conversion, "text_0"): axis.text_conversion = sig.conversion else: axis.text_conversion = None axis.picture = None if sig.trim_info is not None: sig.trim(*sig.trim_info, force=True) self.update() def set_current_uuid(self, uuid, force=False): axis = self.y_axis viewbox = self.viewbox sig, index = self.signal_by_uuid(uuid) if sig.conversion and hasattr(sig.conversion, "text_0"): axis.text_conversion = sig.conversion else: axis.text_conversion = None axis.format = sig.format if uuid in self.common_axis_items: if self.current_uuid not in self.common_axis_items or force: match self._settings.value("plot_background"): case "Black": axis.set_pen(fn.mkPen("#FFFFFF")) axis.setTextPen("#FFFFFF") case "White": axis.set_pen(fn.mkPen("#000000")) axis.setTextPen("#000000") case _: plot_foreground = self._settings.value("plot_foreground", "#ffffff") axis.set_pen(fn.mkPen(plot_foreground)) axis.setTextPen(plot_foreground) axis.setLabel(self.common_axis_label) else: if len(sig.name) <= 32: if sig.unit: axis.setLabel(f"{sig.name} [{sig.unit}]") else: axis.setLabel(f"{sig.name}") else: if sig.unit: axis.setLabel(f"{sig.name[:29]}... [{sig.unit}]") else: axis.setLabel(f"{sig.name[:29]}...") axis.set_pen(sig.pen) axis.setTextPen(sig.pen) axis.update() self.current_uuid = uuid viewbox.setYRange(*sig.y_range, padding=0) self.current_uuid_changed.emit(uuid) self.update() def set_dots(self, with_dots): self.with_dots = with_dots self.update() def set_individual_axis(self, uuid, state): sig, index = self.signal_by_uuid(uuid) if state in (QtCore.Qt.CheckState.Checked, True, 1): if sig.enable: self.get_axis(index).show() sig.individual_axis = True else: self.get_axis(index).hide() sig.individual_axis = False if not self._update_timer.isActive(): self._update_timer.start() def set_line_interconnect(self, line_interconnect): self.line_interconnect = line_interconnect self._curve.setData(stepMode=line_interconnect) for sig in self.signals: sig.path = None self.update() def set_locked(self, locked): self.locked = locked for axis in self.axes: if isinstance(axis, FormatedAxis): axis.locked = locked self.viewbox.setMouseEnabled(y=not self.locked) def set_name(self, uuid, name): sig, index = self.signal_by_uuid(uuid) sig.name = name or "" sig_axis = [self.get_axis(index)] if uuid == self.current_uuid: sig_axis.append(self.y_axis) for axis in sig_axis: if len(sig.name) <= 32: if sig.unit: axis.setLabel(f"{sig.name} [{sig.unit}]") else: axis.setLabel(f"{sig.name}") else: if sig.unit: axis.setLabel(f"{sig.name[:29]}... [{sig.unit}]") else: axis.setLabel(f"{sig.name[:29]}...") axis.update() self.update() def set_signal_enable(self, uuid, state): signal, index = self.signal_by_uuid(uuid) if state in (QtCore.Qt.CheckState.Checked, True, 1): (start, stop), _ = self.viewbox.viewRange() width = self.width() - self.y_axis.width() signal.enable = True signal.trim(start, stop, width) if signal.individual_axis: self.get_axis(index).show() uuids = self._timebase_db.setdefault(id(signal.timestamps), set()) uuids.add(signal.uuid) else: signal.enable = False if signal.individual_axis: self.get_axis(index).hide() try: self._timebase_db[id(signal.timestamps)].remove(uuid) if len(self._timebase_db[id(signal.timestamps)]) == 0: del self._timebase_db[id(signal.timestamps)] except: pass for sig in self.signals: sig.path = None self._enable_timer.start(50) def set_time_offset(self, info): absolute, offset, *uuids = info signals = [sig for sig in self.signals if sig.uuid in uuids] if absolute: for sig in signals: if not len(sig.timestamps): continue id_ = id(sig.timestamps) delta = sig.timestamps[0] - offset sig.timestamps = sig.timestamps - delta uuids = self._timebase_db.setdefault(id(sig.timestamps), set()) uuids.add(sig.uuid) self._timebase_db[id_].remove(sig.uuid) if len(self._timebase_db[id_]) == 0: del self._timebase_db[id_] if sig.trim_info is not None: sig.trim(*sig.trim_info, force=True) else: for sig in signals: if not len(sig.timestamps): continue id_ = id(sig.timestamps) sig.timestamps = sig.timestamps + offset uuids = self._timebase_db.setdefault(id(sig.timestamps), set()) uuids.add(sig.uuid) self._timebase_db[id_].remove(sig.uuid) if len(self._timebase_db[id_]) == 0: del self._timebase_db[id_] if sig.trim_info is not None: sig.trim(*sig.trim_info, force=True) self._compute_all_timebase() self.update() def set_unit(self, uuid, unit): sig, index = self.signal_by_uuid(uuid) sig.unit = unit or "" sig_axis = [self.get_axis(index)] if uuid == self.current_uuid: sig_axis.append(self.y_axis) for axis in sig_axis: if len(sig.name) <= 32: if sig.unit: axis.setLabel(f"{sig.name} [{sig.unit}]") else: axis.setLabel(f"{sig.name}") else: if sig.unit: axis.setLabel(f"{sig.name[:29]}... [{sig.unit}]") else: axis.setLabel(f"{sig.name[:29]}...") axis.update() self.update() def set_y_range(self, uuid, y_range, emit=True): update = False if uuid is None: # y axis was changed if self.current_uuid is None: return uuid = self.current_uuid sig, idx = self.signal_by_uuid(uuid) if sig.y_range != y_range: sig.y_range = y_range axis = self.axes[idx] if isinstance(axis, FormatedAxis): axis.setRange(*y_range) update = True else: sig, idx = self.signal_by_uuid(uuid) if sig.y_range != y_range: sig.y_range = y_range if uuid == self.current_uuid: self.y_axis.setRange(*y_range) update = True if uuid in self.common_axis_items: for uuid in self.common_axis_items: sig, idx = self.signal_by_uuid(uuid) if sig.y_range != y_range: sig.y_range = y_range axis = self.axes[idx] if isinstance(axis, FormatedAxis): axis.setRange(*y_range) update = True if emit: self.zoom_changed.emit(False) if update: if not self._update_timer.isActive(): self._update_timer.start() def signal_by_name(self, name): for i, sig in enumerate(self.signals): if sig.name == name: return sig, i raise Exception(f"Signal not found: {name} {[sig.name for sig in self.signals]}") def signal_by_uuid(self, uuid): return self._uuid_map[uuid] def _signals_enabled_changed_handler(self): self._compute_all_timebase() if self.cursor1: self.cursor_move_finished.emit(self.cursor1) self.signals_enable_changed.emit() self.update() def trim(self, signals=None, force=False, view_range=None): signals = signals or self.signals if not self._can_trim: return if view_range is None: (start, stop), _ = self.viewbox.viewRange() else: start, stop = view_range width = self.viewbox.sceneBoundingRect().toRect().width() for sig in signals: if sig.enable: sig.trim(start, stop, width, force) def update(self, *args, pixmap=None, **kwargs): self._pixmap = pixmap for idx, sig in enumerate(self.signals): if sig.individual_axis: axis = self.get_axis(idx) if tuple(axis.range) != tuple(sig.y_range): axis.setRange(*sig.y_range) if sig.uuid == self.current_uuid: if tuple(self.y_axis.range) != tuple(sig.y_range): self.y_axis.setRange(*sig.y_range) if self.viewbox and self._can_paint_global: self.viewbox.update() def update_views(self): geometry = self.viewbox.sceneBoundingRect().toRect() if geometry != self.viewbox_geometry: self.viewbox_geometry = geometry def value_at_cursor(self, uuid=None): uuid = uuid or self.current_uuid if not uuid: y, sig_y_bottom, sig_y_top = "n.a.", 0, 1 elif self.cursor1: if not self.cursor1.isVisible(): cursor = self.region.lines[0] else: cursor = self.cursor1 timestamp = cursor.value() sig, idx = self.signal_by_uuid(uuid) sig_y_bottom, sig_y_top = sig.y_range raw_value, raw_kind, y, *_ = sig.value_at_timestamp(timestamp, numeric=True, strict_timebase=False) else: sig, idx = self.signal_by_uuid(uuid) sig_y_bottom, sig_y_top = sig.y_range if not len(sig): y = "n.a." else: y = sig.phys_samples[-1] if y.dtype.kind not in "uif": y = sig.raw_samples[-1] return y, sig_y_bottom, sig_y_top def xrange_changed_handle(self, *args, force=False): if self._can_paint: self.trim(force=force) self.update() self.zoom_changed.emit(False) def y_changed(self, *args): if len(args) == 1: # range manually changed by the user with the wheel or drag mask = args[0] if mask[1]: y_range = self.viewbox.viewRange()[1] else: return else: # range changed by the linked axis y_range = args[1] update = False if self.current_uuid in self.common_axis_items: for uuid in self.common_axis_items: sig, idx = self.signal_by_uuid(uuid) if sig.y_range != y_range: update = True if sig.individual_axis: axis = self.get_axis(idx) axis.setRange(*y_range) sig.y_range = y_range elif self.current_uuid: sig, idx = self.signal_by_uuid(self.current_uuid) if sig.y_range != y_range: update = True if sig.individual_axis: axis = self.get_axis(idx) axis.setRange(*y_range) sig.y_range = y_range if update: self.update() class CursorInfo(QtWidgets.QLabel): def __init__(self, precision, name="t", unit="s", plot=None, *args, **kwargs): super().__init__(*args, **kwargs) self.precision = precision self.name = name self.unit = unit self.plot = plot self.setTextFormat(QtCore.Qt.TextFormat.RichText) self.setAlignment( QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignTrailing | QtCore.Qt.AlignmentFlag.AlignVCenter ) self.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.open_menu) if precision == -1: self.setToolTip("Cursor information uses maximum precision") else: self.setToolTip(f"Cursor information precision is set to {self.precision} decimals") def open_menu(self, point): menu = QtWidgets.QMenu(self) menu.addAction("Set precision") action = menu.exec_(self.mapToGlobal(point)) if action is None: return if action.text() == "Set precision": precision, ok = QtWidgets.QInputDialog.getInt( self, "Set new precision (float decimals)", "Precision:", self.precision, -1, 15, 1 ) if ok: self.set_precision(precision) QtCore.QSettings().setValue("plot_cursor_precision", precision) def update_value(self): cursor_info_text = "" if not self.plot.region: if self.plot.cursor1 is not None: position = self.plot.cursor1.value() fmt = self.plot.x_axis.format if fmt == "phys" or not fmt: if self.precision == -1: cursor_info_text = f"{self.name} = {position}{self.unit}" else: template = f"{self.name} = {{:.{self.precision}f}}{self.unit}" cursor_info_text = template.format(position) elif fmt == "time": cursor_info_text = f"{self.name} = {timedelta(seconds=position)}" elif fmt == "date": position_date = self.plot.x_axis.origin + timedelta(seconds=position) cursor_info_text = f"{self.name} = {position_date}" if cursor_info_text: self.setText(cursor_info_text) else: self.setText("") else: start, stop = self.plot.region.getRegion() fmt = self.plot.x_axis.format if fmt == "phys": if self.precision == -1: start_info = f"{start}{self.unit}" stop_info = f"{stop}{self.unit}" delta_info = f"{stop - start}{self.unit}" else: template = f"{{:.{self.precision}f}}{self.unit}" start_info = template.format(start) stop_info = template.format(stop) delta_info = template.format(stop - start) elif fmt == "time": start_info = f"{timedelta(seconds=start)}" stop_info = f"{timedelta(seconds=stop)}" delta_info = f"{timedelta(seconds=(stop - start))}" elif fmt == "date": start_info = self.plot.x_axis.origin + timedelta(seconds=start) stop_info = self.plot.x_axis.origin + timedelta(seconds=stop) delta_info = f"{timedelta(seconds=(stop - start))}" self.setText( "" f"

{self.name}1 = {start_info}, {self.name}2 = {stop_info}

" f"

Δ{self.name} = {delta_info}

" "" ) def set_precision(self, precision): self.precision = precision if precision == -1: self.setToolTip("Cursor information uses maximum precision") else: self.setToolTip(f"Cursor information precision is set to {precision} decimals") self.update_value() try: import scipy # noqa: F401 from .fft_window import FFTWindow except ImportError: pass asammdf-8.5.1/src/asammdf/gui/widgets/plot_standalone.py000066400000000000000000000613661502633300400233360ustar00rootroot00000000000000from functools import partial import logging import webbrowser import pyqtgraph as pg from PySide6 import QtCore, QtGui, QtWidgets from .plot import Plot, PlotSignal bin_ = bin if not hasattr(pg.InfiniteLine, "addMarker"): logger = logging.getLogger("asammdf") message = ( "Old pyqtgraph package: Please install the latest pyqtgraph from the " "github develop branch\n" "pip install -I --no-deps " "https://github.com/pyqtgraph/pyqtgraph/archive/develop.zip" ) logger.warning(message) class PlotWindow(QtWidgets.QMainWindow): def __init__(self, signals, *args, **kwargs): super().__init__(*args, **kwargs) self.menubar = QtWidgets.QMenuBar() self.menubar.setObjectName("menubar") self.setMenuBar(self.menubar) self._settings = QtCore.QSettings() self.with_dots = self._settings.value("dots", False, type=bool) if isinstance(signals, (list, tuple)): signals = {sig.name: PlotSignal(sig) for sig in signals} self.plot = Plot({}, self.with_dots) self._light_palette = self.palette() menu = QtWidgets.QMenu("Settings", self.menubar) self.menubar.addMenu(menu) # search mode menu plot_background_option = QtGui.QActionGroup(self) for option in ("Black", "White"): action = QtGui.QAction(option, menu) action.setCheckable(True) plot_background_option.addAction(action) action.triggered.connect(partial(self.set_plot_background, option)) if option == self._settings.value("plot_background", "Black"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Plot background", self.menubar) submenu.addActions(plot_background_option.actions()) menu.addMenu(submenu) # plot X axis display mode plot_xaxis_option = QtGui.QActionGroup(self) for option in ("seconds", "time", "date"): action = QtGui.QAction(option, menu) action.setCheckable(True) plot_xaxis_option.addAction(action) action.triggered.connect(partial(self.set_plot_xaxis, option)) if option == self._settings.value("plot_xaxis", "seconds"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Plot X axis", self.menubar) submenu.addActions(plot_xaxis_option.actions()) menu.addMenu(submenu) # search mode menu theme_option = QtGui.QActionGroup(self) for option in ("Dark", "Light"): action = QtGui.QAction(option, menu) action.setCheckable(True) theme_option.addAction(action) action.triggered.connect(partial(self.set_theme, option)) if option == self._settings.value("theme", "Light"): action.setChecked(True) action.triggered.emit() submenu = QtWidgets.QMenu("Theme", self.menubar) submenu.addActions(theme_option.actions()) menu.addMenu(submenu) # plot option menu plot_actions = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/fit.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, f"{'Fit trace': <20}\tF", menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_F)) action.setShortcut(QtCore.Qt.Key.Key_F) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/grid.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tG".format("Grid"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_G)) action.setShortcut(QtCore.Qt.Key.Key_G) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/home.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tH".format("Home"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_H)) action.setShortcut(QtCore.Qt.Key.Key_H) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/list2.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tS".format("Stack"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_S)) action.setShortcut(QtCore.Qt.Key.Key_S) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/zoom-in.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tI".format("Zoom in"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_I)) action.setShortcut(QtCore.Qt.Key.Key_I) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/zoom-out.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tO".format("Zoom out"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_O)) action.setShortcut(QtCore.Qt.Key.Key_O) plot_actions.addAction(action) action = QtGui.QAction("{: <20}\t.".format("Toggle dots"), menu) action.triggered.connect(partial(self.toggle_dots, key=QtCore.Qt.Key.Key_O)) action.setShortcut(QtCore.Qt.Key.Key_Period) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/plus.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tIns".format("Insert computation"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_Insert)) action.setShortcut(QtCore.Qt.Key.Key_Insert) plot_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/save.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+S".format("Save active subplot channels"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_S, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+S")) plot_actions.addAction(action) # values display display_format_actions = QtGui.QActionGroup(self) action = QtGui.QAction("{: <20}\tCtrl+H".format("Hex"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_H, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+H")) display_format_actions.addAction(action) action = QtGui.QAction("{: <20}\tCtrl+B".format("Bin"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_B, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+B")) display_format_actions.addAction(action) action = QtGui.QAction("{: <20}\tCtrl+P".format("Physical"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_P, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+P")) display_format_actions.addAction(action) # scaled display samples_format_actions = QtGui.QActionGroup(self) action = QtGui.QAction("{: <20}\tAlt+R".format("Raw samples"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_R, modifier=QtCore.Qt.KeyboardModifier.AltModifier) ) action.setShortcut(QtGui.QKeySequence("Alt+R")) samples_format_actions.addAction(action) action = QtGui.QAction("{: <20}\tAlt+S".format("Scaled samples"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_S, modifier=QtCore.Qt.KeyboardModifier.AltModifier) ) action.setShortcut(QtGui.QKeySequence("Alt+S")) samples_format_actions.addAction(action) # info info = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tM".format("Statistics"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_M)) action.setShortcut(QtGui.QKeySequence("M")) info.addAction(action) # cursors cursors_actions = QtGui.QActionGroup(self) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/cursor.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tC".format("Cursor"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_C)) action.setShortcut(QtCore.Qt.Key.Key_C) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/right.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\t←".format("Move cursor left"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_Left)) action.setShortcut(QtCore.Qt.Key.Key_Left) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/left.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\t→".format("Move cursor right"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_Right)) action.setShortcut(QtCore.Qt.Key.Key_Right) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/range.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tR".format("Range"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_R)) action.setShortcut(QtCore.Qt.Key.Key_R) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/lock_range.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tY".format("Lock/unlock range"), menu) action.triggered.connect(partial(self.plot_action, key=QtCore.Qt.Key.Key_Y)) action.setShortcut(QtCore.Qt.Key.Key_Y) cursors_actions.addAction(action) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/comments.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) action = QtGui.QAction(icon, "{: <20}\tCtrl+I".format("Insert cursor comment"), menu) action.triggered.connect( partial( self.plot_action, key=QtCore.Qt.Key.Key_I, modifier=QtCore.Qt.KeyboardModifier.ControlModifier, ) ) action.setShortcut(QtGui.QKeySequence("Ctrl+I")) cursors_actions.addAction(action) icon = QtGui.QIcon() action = QtGui.QAction("{: <20}\tAlt+I".format("Toggle trigger texts"), menu) action.triggered.connect( partial(self.plot_action, key=QtCore.Qt.Key.Key_I, modifier=QtCore.Qt.KeyboardModifier.AltModifier) ) action.setShortcut(QtGui.QKeySequence("Alt+I")) cursors_actions.addAction(action) self.plot_menu = QtWidgets.QMenu("Plot", self.menubar) self.plot_menu.addActions(plot_actions.actions()) self.plot_menu.addSeparator() self.plot_menu.addActions(cursors_actions.actions()) self.plot_menu.addSeparator() self.plot_menu.addActions(display_format_actions.actions()) self.plot_menu.addSeparator() self.plot_menu.addActions(samples_format_actions.actions()) self.plot_menu.addSeparator() self.plot_menu.addActions(info.actions()) self.menubar.addMenu(self.plot_menu) menu = self.menubar.addMenu("Help") open_group = QtGui.QActionGroup(self) action = QtGui.QAction("Online documentation", menu) action.triggered.connect(self.help) open_group.addAction(action) menu.addActions(open_group.actions()) self.setCentralWidget(self.plot) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.setWindowIcon(icon) self.show() self.plot.add_new_channels(signals) def plot_action(self, key, modifier=QtCore.Qt.KeyboardModifier.NoModifier): event = QtGui.QKeyEvent(QtCore.QEvent.Type.KeyPress, key, modifier) self.plot.keyPressEvent(event) def toggle_dots(self, key): self.with_dots = not self.with_dots self._settings.setValue("dots", self.with_dots) self.plot.plot.update_lines(with_dots=self.with_dots) def set_plot_background(self, option): self._settings.setValue("plot_background", option) if option == "Black": pg.setConfigOption("background", "k") pg.setConfigOption("foreground", "w") else: pg.setConfigOption("background", "w") pg.setConfigOption("foreground", "k") def set_plot_xaxis(self, option): self._settings.setValue("plot_xaxis", option) if option == "seconds": fmt = "phys" elif option == "time": fmt = "time" elif option == "date": fmt = "time" plot = self.plot plot.plot.x_axis.format = fmt plot.plot.x_axis.updateAutoSIPrefix() if plot.plot.cursor1 is not None: plot.cursor_moved() if plot.plot.region is not None: plot.range_modified() def set_theme(self, option): self._settings.setValue("theme", option) app = QtWidgets.QApplication.instance() if option == "Light": app.setPalette(self._light_palette) else: palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Button, brush) brush = QtGui.QBrush(QtGui.QColor(82, 82, 82)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Light, brush) brush = QtGui.QBrush(QtGui.QColor(68, 68, 68)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Midlight, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Dark, brush) brush = QtGui.QBrush(QtGui.QColor(36, 36, 36)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Mid, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Text, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.BrightText, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.ButtonText, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Base, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Window, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Shadow, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.AlternateBase, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.ToolTipBase, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.ToolTipText, brush) brush = QtGui.QBrush(QtGui.QColor(100, 100, 100)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Highlight, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Button, brush) brush = QtGui.QBrush(QtGui.QColor(82, 82, 82)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Light, brush) brush = QtGui.QBrush(QtGui.QColor(68, 68, 68)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Midlight, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Dark, brush) brush = QtGui.QBrush(QtGui.QColor(36, 36, 36)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Mid, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Text, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.BrightText, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.ButtonText, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Base, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Window, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Shadow, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.AlternateBase, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.ToolTipBase, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.ToolTipText, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Button, brush) brush = QtGui.QBrush(QtGui.QColor(82, 82, 82)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Light, brush) brush = QtGui.QBrush(QtGui.QColor(68, 68, 68)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Midlight, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Dark, brush) brush = QtGui.QBrush(QtGui.QColor(36, 36, 36)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Mid, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Text, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.BrightText, brush) brush = QtGui.QBrush(QtGui.QColor(27, 27, 27)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Base, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Window, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Shadow, brush) brush = QtGui.QBrush(QtGui.QColor(55, 55, 55)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.AlternateBase, brush) brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ToolTipBase, brush) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ToolTipText, brush) app.setPalette(palette) def help(self, event): webbrowser.open_new(r"http://asammdf.readthedocs.io/en/master/gui.html") asammdf-8.5.1/src/asammdf/gui/widgets/python_highlighter.py000066400000000000000000000152151502633300400240370ustar00rootroot00000000000000#!/usr/bin/env python """PySide6 QPlainTextEdit syntax highlight for Python source code. The original code if found here https://wiki.python.org/moin/PyQt/Python%20syntax%20highlighting """ import builtins import keyword from PySide6 import QtCore, QtGui def format(color, style=""): """Return a QTextCharFormat with the given attributes.""" _color = QtGui.QColor(color) _format = QtGui.QTextCharFormat() _format.setForeground(_color) if "bold" in style: _format.setFontWeight(QtGui.QFont.Weight.Bold) if "italic" in style: _format.setFontItalic(True) _format.setBackground(QtGui.QBrush(QtGui.QColor("#131314"))) return _format # Syntax styles that can be shared by all languages STYLES = { "keyword": format("#ec6529"), "operator": format("#ff0000"), "brace": format("#ff0000"), "defclassname": format("#9e5fdd", "bold"), "defclass": format("#ec8549", "bold"), "string": format("#2f8f3d"), "string2": format("#2f8f3d"), "comment": format("#65c2e5", "italic"), "self": format("#93548b", "italic"), "numbers": format("#33ccff"), "builtins": format("#567ac5"), } class PythonHighlighter(QtGui.QSyntaxHighlighter): """Syntax highlighter for the Python language.""" # Python keywords keywords = keyword.kwlist + getattr(keyword, "softkwlist", []) builtins = dir(builtins) # Python operators operators = [ r"=", # Comparison r"==", "!=", "<", "<=", ">", ">=", # Arithmetic r"\+", "-", r"\*", "/", "//", r"\%", r"\*\*", # In-place r"\+=", "-=", r"\*=", "/=", r"\%=", # Bitwise r"\^", r"\|", r"\&", r"\~", ">>", "<<", ] # Python braces braces = [ r"\{", r"\}", r"\(", r"\)", r"\[", r"\]", ] def __init__(self, parent: QtGui.QTextDocument) -> None: super().__init__(parent) # Multi-line strings (expression, flag, style) self.tri_single = (QtCore.QRegularExpression("'''"), 1, STYLES["string2"]) self.tri_double = (QtCore.QRegularExpression('"""'), 2, STYLES["string2"]) rules = [] # Keyword, operator, and brace rules rules += [(rf"\b{w}\b", 0, STYLES["keyword"]) for w in PythonHighlighter.keywords] rules += [(o, 0, STYLES["operator"]) for o in PythonHighlighter.operators] rules += [(b, 0, STYLES["brace"]) for b in PythonHighlighter.braces] rules += [(rf"\b{b}\b", 0, STYLES["builtins"]) for b in PythonHighlighter.builtins] # All other rules rules += [ # 'self' (r"\bself\b", 0, STYLES["self"]), # 'def' followed by an identifier (r"\bdef\b\s*(\w+)", 0, STYLES["defclassname"]), (r"\bdef\b", 0, STYLES["defclass"]), # 'class' followed by an identifier (r"\bclass\b\s*(\w+)", 0, STYLES["defclassname"]), (r"\bclass\b", 0, STYLES["defclass"]), # Numeric literals (r"\b[+-]?[0-9]+\b", 0, STYLES["numbers"]), (r"\b[+-]?0[xX][0-9A-Fa-f]+\b", 0, STYLES["numbers"]), (r"\b[+-]?[0-9]+(\.[0-9]+)\b", 0, STYLES["numbers"]), (r"\b[+-]?[0-9]+([eE][+-]?[0-9]+)\b", 0, STYLES["numbers"]), (r"\b[+-]?[0-9]+(\.[0-9]+)([eE][+-]?[0-9]+)\b", 0, STYLES["numbers"]), # Double-quoted string, possibly containing escape sequences (r'"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES["string"]), # Single-quoted string, possibly containing escape sequences (r"'[^'\\]*(\\.[^'\\]*)*'", 0, STYLES["string"]), # From '#' until a newline (r"#[^\n]*", 0, STYLES["comment"]), ] # Build a QRegularExpression for each pattern self.rules = [(QtCore.QRegularExpression(pat), index, fmt) for (pat, index, fmt) in rules] def highlightBlock(self, text): """Apply syntax highlighting to the given block of text.""" self.tripleQuoutesWithinStrings = [] # Do other syntax formatting for expression, nth, format in self.rules: iterator = expression.globalMatch(text) while iterator.hasNext(): match = iterator.next() length = match.capturedEnd() - match.capturedStart() index = match.capturedStart() self.setFormat(index, length, format) self.setCurrentBlockState(0) # Do multi-line strings in_multiline = self.match_multiline(text, *self.tri_single) if not in_multiline: in_multiline = self.match_multiline(text, *self.tri_double) def match_multiline(self, text, delimiter, in_state, style): """Do highlighting of multi-line strings. ``delimiter`` should be a ``QRegularExpression`` for triple-single-quotes or triple-double-quotes, and ``in_state`` should be a unique integer to represent the corresponding state changes when inside those strings. Returns True if we're still inside a multi-line string when this function is finished. """ # If inside triple-single quotes, start at 0 if self.previousBlockState() == in_state: start = 0 add = 0 # Otherwise, look for the delimiter on this line else: match = delimiter.match(text) start = match.capturedStart() # skipping triple quotes within strings if start in self.tripleQuoutesWithinStrings: return False # Move past this match add = match.capturedLength() # As long as there's a delimiter match on this line... while start >= 0: # Look for the ending delimiter match = delimiter.match(text, start + add) end = match.capturedStart() # Ending delimiter on this line? if end >= add: length = end - start + add + match.capturedLength() self.setCurrentBlockState(0) # No; multi-line string else: self.setCurrentBlockState(in_state) length = len(text) - start + add # Apply formatting self.setFormat(start, length, style) # Look for the next match match = delimiter.match(text, start + length) start = match.capturedStart() # Return True if still inside a multi-line string, False otherwise if self.currentBlockState() == in_state: return True else: return False asammdf-8.5.1/src/asammdf/gui/widgets/range_widget.py000066400000000000000000000125371502633300400226030ustar00rootroot00000000000000from PySide6 import QtCore, QtGui, QtWidgets from ..ui.range_widget import Ui_RangeWidget class RangeWidget(Ui_RangeWidget, QtWidgets.QWidget): add_channels_request = QtCore.Signal(list) timestamp_changed_signal = QtCore.Signal(object, float) def __init__( self, name, value1="", op1="==", value2="", op2="==", font_color=None, background_color=None, brush=False, *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self._settings = QtCore.QSettings() if font_color is None: font_color = self._settings.value("range_font_color", "#ff0000") if background_color is None: background_color = self._settings.value("range_background_color", "#00ff00") self.name.setText(name) self.value1.textChanged.connect(self.value1_changed) self.value2.textChanged.connect(self.value2_changed) self.background_color_btn.clicked.connect(self.select_background_color) self.font_color_btn.clicked.connect(self.select_font_color) self.value1.setText(str(value1) if value1 is not None else "") self.value2.setText(str(value2) if value2 is not None else "") self.op1.setCurrentText(op1) self.op2.setCurrentText(op2) if isinstance(font_color, QtGui.QColor): font_color = font_color.name() elif isinstance(font_color, QtGui.QBrush): font_color = font_color.color().name() if isinstance(font_color, QtGui.QColor): font_color = font_color.name() elif isinstance(font_color, QtGui.QBrush): font_color = font_color.color().name() if isinstance(background_color, QtGui.QColor): background_color = background_color.name() elif isinstance(background_color, QtGui.QBrush): background_color = background_color.color().name() if isinstance(background_color, QtGui.QColor): background_color = background_color.name() elif isinstance(background_color, QtGui.QBrush): background_color = background_color.color().name() self.font_color = font_color self.background_color = background_color self.name.setStyleSheet(f"background-color: {background_color}; color: {font_color};") self.background_color_btn.setStyleSheet(f"background-color: {background_color};") self.font_color_btn.setStyleSheet(f"background-color: {font_color};") def value1_changed(self, text): if text.strip(): self.op1.setEnabled(True) else: self.op1.setEnabled(False) def value2_changed(self, text): if text.strip(): self.op2.setEnabled(True) else: self.op2.setEnabled(False) def select_background_color(self, event=None): color = self.background_color_btn.palette().button().color() color = QtWidgets.QColorDialog.getColor(color, self) if color.isValid(): color = color.name() self.background_color = color self.background_color_btn.setStyleSheet(f"background-color: {color};") self.name.setStyleSheet(f"background-color: {self.background_color}; color: {self.font_color};") def select_font_color(self, event=None): color = self.font_color_btn.palette().button().color() color = QtWidgets.QColorDialog.getColor(color, self) if color.isValid(): color = color.name() self.font_color = color self.font_color_btn.setStyleSheet(f"background-color: {color};") self.name.setStyleSheet(f"background-color: {self.background_color}; color: {self.font_color};") def to_dict(self, brush=False): value1 = self.value1.text().strip() if value1: try: value1 = float(value1) except: if value1.startswith("0x"): try: value1 = float(int(value1, 16)) except: pass elif value1.startswith("0b"): try: value1 = float(int(value1, 2)) except: pass else: value1 = None value2 = self.value2.text().strip() if value2: try: value2 = float(value2) except: if value2.startswith("0x"): try: value2 = float(int(value2, 16)) except: pass elif value2.startswith("0b"): try: value2 = float(int(value2, 2)) except: pass else: value2 = None font_color = self.font_color_btn.palette().button().color() background_color = self.background_color_btn.palette().button().color() if brush: background_color = QtGui.QBrush(background_color) font_color = QtGui.QBrush(font_color) return { "background_color": background_color, "font_color": font_color, "op1": self.op1.currentText(), "op2": self.op2.currentText(), "value1": value1, "value2": value2, } asammdf-8.5.1/src/asammdf/gui/widgets/search.py000066400000000000000000000044471502633300400214120ustar00rootroot00000000000000from PySide6 import QtCore, QtWidgets from ..ui.search_widget import Ui_SearchWidget class SearchWidget(Ui_SearchWidget, QtWidgets.QWidget): selectionChanged = QtCore.Signal() def __init__(self, sorted_keys, channels_db, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.channels_db = channels_db self.matches = 0 self.current_index = 1 self.entries = [] completer = QtWidgets.QCompleter(sorted_keys, self) completer.setCaseSensitivity(QtCore.Qt.CaseSensitivity.CaseInsensitive) completer.setModelSorting(QtWidgets.QCompleter.ModelSorting.CaseInsensitivelySortedModel) completer.setFilterMode(QtCore.Qt.MatchFlag.MatchContains) self.search.setCompleter(completer) self.search.textChanged.connect(self.display_results) self.up_btn.clicked.connect(self.up) self.down_btn.clicked.connect(self.down) def down(self, event): if self.matches: self.current_index += 1 if self.current_index >= self.matches: self.current_index = 0 self.label.setText(f"{self.current_index + 1} of {self.matches}") self.selectionChanged.emit() def up(self, event): if self.matches: self.current_index -= 1 if self.current_index < 0: self.current_index = self.matches - 1 self.label.setText(f"{self.current_index + 1} of {self.matches}") self.selectionChanged.emit() def set_search_option(self, option): if option == "Match start": self.search.completer().setFilterMode(QtCore.Qt.MatchFlag.MatchStartsWith) elif option == "Match contains": self.search.completer().setFilterMode(QtCore.Qt.MatchFlag.MatchContains) def display_results(self, text): channel_name = text.strip() if channel_name in self.channels_db: self.entries = self.channels_db[channel_name] self.matches = len(self.entries) self.label.setText(f"1 of {self.matches}") self.current_index = 0 self.selectionChanged.emit() else: self.label.setText("No match") self.matches = 0 self.current_index = 0 self.entries = [] asammdf-8.5.1/src/asammdf/gui/widgets/signal_scale.py000066400000000000000000000223241502633300400225630ustar00rootroot00000000000000from functools import partial from natsort import natsorted import numpy as np from pyqtgraph import functions as fn from PySide6 import QtCore, QtGui, QtWidgets from ..ui.signal_scale import Ui_ScaleDialog from ..utils import BLUE from .plot import PlotSignal PLOT_HEIGTH = 600 # pixels TEXT_WIDTH = 50 # pixels class ScaleDialog(Ui_ScaleDialog, QtWidgets.QDialog): def __init__(self, signals, y_range, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self.signals = signals self._inhibit = True self.signal.addItems(list(natsorted(signals))) self.signal.currentTextChanged.connect(self.signal_selected) self.setWindowTitle("Y scale configuration") self.scaling.setMinimum(0.000001) self.scaling.setMaximum(np.inf) self.target_min.setMinimum(-np.inf) self.target_min.setMaximum(np.inf) self.target_max.setMinimum(-np.inf) self.target_max.setMaximum(np.inf) self.offset.setMinimum(-np.inf) self.offset.setMaximum(np.inf) self.signal_selected(self.signal.currentText()) self.apply_btn.clicked.connect(self.apply) self.cancel_btn.clicked.connect(self.cancel) self.zoom_in_btn.clicked.connect(self.zoom_in) self.zoom_out_btn.clicked.connect(self.zoom_out) self.fit_btn.clicked.connect(self.fit) self.shift_up_btn.clicked.connect(partial(self.shift, step=1)) self.shift_down_btn.clicked.connect(partial(self.shift, step=-1)) self.fast_shift_up_btn.clicked.connect(partial(self.shift, step=10)) self.fast_shift_down_btn.clicked.connect(partial(self.shift, step=-10)) self.apply_btn.setAutoDefault(False) self.cancel_btn.setAutoDefault(False) self.zoom_in_btn.setAutoDefault(False) self.zoom_out_btn.setAutoDefault(False) self.fit_btn.setAutoDefault(False) self.shift_up_btn.setAutoDefault(False) self.shift_down_btn.setAutoDefault(False) self.fast_shift_up_btn.setAutoDefault(False) self.fast_shift_down_btn.setAutoDefault(False) self.offset.valueChanged.connect(self.draw_plot) self.scaling.valueChanged.connect(self.draw_plot) self.target_max.valueChanged.connect(self.set_target) self.target_min.valueChanged.connect(self.set_target) canvas = QtGui.QPixmap(PLOT_HEIGTH + 3 * TEXT_WIDTH, PLOT_HEIGTH) canvas.fill(QtCore.Qt.GlobalColor.black) self.plot.setPixmap(canvas) self.plot.setFocus() self._inhibit = False self.signal.setCurrentIndex(0) bottom, top = y_range if top == bottom: top += 1 bottom -= 1 scaling = 2 else: scaling = top - bottom self.scaling.setValue(scaling) self.offset.setValue(-bottom * 100 / scaling) def set_target(self, *args): original_change = not self._inhibit if original_change: self._inhibit = True if self.target_max.value() < self.target_min.value(): val = self.target_min.value() self.target_min.setValue(self.target_max.value()) self.target_max.setValue(val) self._inhibit = False self.draw_plot() def apply(self, *args): self.accept() def cancel(self): self.reject() def zoom_in(self, *args): self.scaling.setValue(self.scaling.value() * 0.9) def zoom_out(self, *args): self.scaling.setValue(self.scaling.value() * 1.1) def fit(self, *args): scaling = (self.target_max.value() - self.target_min.value()) or 2 pos = -(100 * self.target_min.value() / scaling) self.offset.setValue(pos) self.scaling.setValue(scaling) def draw_plot(self, *args): offset = self.offset.value() scale = self.scaling.value() y_bottom = -offset * scale / 100 y_top = y_bottom + scale self.y_bottom.setText(f"{y_bottom:.3f}") self.y_top.setText(f"{y_top:.3f}") canvas = self.plot.pixmap() canvas.fill(QtCore.Qt.GlobalColor.black) if self.samples is None: self.target_max.setEnabled(True) self.target_min.setEnabled(True) else: self.target_max.setEnabled(False) self.target_min.setEnabled(False) if self.samples is None: x = np.linspace(0, 2 * np.pi * 10, PLOT_HEIGTH) amp = (self.target_max.value() - self.target_min.value()) / 2 off = (self.target_max.value() + self.target_min.value()) / 2 y = np.sin(x) * amp + off x = np.arange(50, 50 + PLOT_HEIGTH) else: x = self.samples.plot_timestamps y = self.samples.plot_samples.copy() ys = y_top y_scale = (y_top - y_bottom) / PLOT_HEIGTH ys = ys + y_scale y = (ys - y) / y_scale polygon = fn.create_qpolygonf(len(x)) ndarray = fn.ndarray_from_qpolygonf(polygon) ndarray[:, 0] = x ndarray[:, 1] = y painter = QtGui.QPainter(canvas) pen = QtGui.QPen(QtCore.Qt.GlobalColor.white) painter.setPen(pen) step = PLOT_HEIGTH // 10 for i, x in enumerate(range(0, PLOT_HEIGTH + step, step)): if i == 0: painter.drawText(5, x + 15, f"{100 - 10 * i}%") elif i == 10: painter.drawText(5, x - 5, f"{100 - 10 * i}%") else: painter.drawText(5, x + 6, f"{100 - 10 * i}%") painter.drawText(PLOT_HEIGTH + TEXT_WIDTH, 15, f"{y_top:.3f}") painter.drawText( PLOT_HEIGTH + TEXT_WIDTH, PLOT_HEIGTH - 5, f"{y_bottom:.3f}", ) painter.setClipping(True) painter.setClipRect(QtCore.QRect(TEXT_WIDTH, 0, PLOT_HEIGTH, PLOT_HEIGTH)) pen.setStyle(QtCore.Qt.PenStyle.DotLine) painter.setPen(pen) for i, x in enumerate(range(0, PLOT_HEIGTH + step, step)): painter.drawLine(0, x, PLOT_HEIGTH + 2 * TEXT_WIDTH, x) pen = QtGui.QPen(BLUE) pen.setWidth(2) painter.setPen(pen) painter.drawPolyline(polygon) pen = QtGui.QPen("#18e223") pen.setWidth(2) pen.setStyle(QtCore.Qt.PenStyle.DashDotDotLine) painter.setPen(pen) offset = PLOT_HEIGTH - self.offset.value() * PLOT_HEIGTH / 100 p1 = QtCore.QPointF(0.0, offset) p2 = QtCore.QPointF(float(PLOT_HEIGTH + 2 * TEXT_WIDTH), offset) painter.drawLine(p1, p2) painter.end() self.plot.setPixmap(canvas) def shift(self, *args, step=1): self.offset.stepBy(step) def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if key == QtCore.Qt.Key.Key_I and modifiers in ( QtCore.Qt.KeyboardModifier.NoModifier, QtCore.Qt.KeyboardModifier.ShiftModifier, ): event.accept() self.zoom_in() elif key == QtCore.Qt.Key.Key_O and modifiers in ( QtCore.Qt.KeyboardModifier.NoModifier, QtCore.Qt.KeyboardModifier.ShiftModifier, ): event.accept() self.zoom_out() elif key == QtCore.Qt.Key.Key_F and modifiers in ( QtCore.Qt.KeyboardModifier.NoModifier, QtCore.Qt.KeyboardModifier.ShiftModifier, ): event.accept() self.fit() if ( key in ( QtCore.Qt.Key.Key_Up, QtCore.Qt.Key.Key_Down, QtCore.Qt.Key.Key_PageUp, QtCore.Qt.Key.Key_PageDown, ) and modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier ): offset = self.offset.value() delta = 10 if key in (QtCore.Qt.Key.Key_PageUp, QtCore.Qt.Key.Key_PageDown) else 1 if key in (QtCore.Qt.Key.Key_PageDown, QtCore.Qt.Key.Key_Down): delta = -delta self.offset.setValue(offset + delta) else: super().keyPressEvent(event) def signal_selected(self, name): signal = self.signals[name].copy() signal.flags &= ~signal.Flags.computed signal.computation = {} signal = PlotSignal(signal) if not isinstance(signal.min, str): self.target_max.setValue(signal.max) self.target_min.setValue(signal.min) if len(signal): self.samples = signal self.samples.trim( signal.timestamps[0], signal.timestamps[-1], PLOT_HEIGTH, ) self.samples.plot_timestamps -= self.samples.plot_timestamps[0] x_scale = self.samples.plot_timestamps[-1] / PLOT_HEIGTH self.samples.plot_timestamps /= x_scale self.samples.plot_timestamps += TEXT_WIDTH else: self.samples = None else: self.samples = None if self.samples is None: self.target_max.setEnabled(True) self.target_min.setEnabled(True) else: self.target_max.setEnabled(False) self.target_min.setEnabled(False) self.draw_plot() asammdf-8.5.1/src/asammdf/gui/widgets/tabular.py000066400000000000000000000116761502633300400216010ustar00rootroot00000000000000import logging import re import dateutil.tz import numpy as np import pandas as pd from PySide6 import QtCore, QtWidgets from ...blocks.utils import ( csv_bytearray2hex, ) from .tabular_base import TabularBase try: npchar = np.strings except: npchar = np.char logger = logging.getLogger("asammdf.gui") LOCAL_TIMEZONE = dateutil.tz.tzlocal() DATA_BYTES = re.compile(r"(?P.*?Data ?)Bytes(?P_\d+)?") def data_length_name(match): result = f"{match.group('data')}Length" if cntr := match.group("cntr"): result += cntr return result class Tabular(TabularBase): add_channels_request = QtCore.Signal(list) def __init__(self, signals=None, start=None, format="phys", ranges=None, owner=None, *args, **kwargs): # super().__init__(*args, **kwargs) self.signals_descr = {} self.start = start.astimezone(LOCAL_TIMEZONE) self.pattern = {} self.format = format self.owner = owner if signals is None: signals = pd.DataFrame() else: index = pd.Series(np.arange(len(signals), dtype="u8"), index=signals.index) signals["Index"] = index signals["timestamps"] = signals.index if ranges is not None: ranges["timestamps"] = [] signals.set_index(index, inplace=True) dropped = {} columns = list(signals.columns) columns.remove("Index") for name_ in signals.columns: col = signals[name_] if col.dtype.kind == "O": if match := DATA_BYTES.fullmatch(name_): length_name = data_length_name(match) try: sizes = signals[length_name].fillna(value=65535).astype("u2") sizes = [val if val != 65535 else None for val in sizes.to_list()] except KeyError: sizes = None dropped[name_] = pd.Series( csv_bytearray2hex( col, sizes, ), index=signals.index, ) elif col.dtype.name != "category": if len(col) and col.dtype.kind == "u" and col.dtype.itemsize == 1: try: dropped[name_] = pd.Series(csv_bytearray2hex(col), index=signals.index) except: pass self.signals_descr[name_] = 0 elif col.dtype.kind == "S": try: dropped[name_] = pd.Series(npchar.decode(col, "utf-8"), index=signals.index) except: dropped[name_] = pd.Series(npchar.decode(col, "latin-1"), index=signals.index) self.signals_descr[name_] = 0 else: self.signals_descr[name_] = 0 signals = signals.drop(columns=["Index", *list(dropped)]) for name, s in dropped.items(): signals[name] = s if dropped: signals = signals[columns] names = list(signals.columns) names = [ "timestamps", *[name for name in names if name.endswith((".ID", ".DataBytes"))], *[name for name in names if name != "timestamps" and not name.endswith((".ID", ".DataBytes"))], ] signals = signals[names] super().__init__(signals, ranges) self.format_selection.setCurrentText(format) self._original_timestamps = signals["timestamps"] self._original_ts_series = pd.Series( self._original_timestamps, index=index, ) # self.build(self.signals, True, ranges=ranges) prefixes = set() for name in signals.columns: while "." in name: name = name.rsplit(".", 1)[0] prefixes.add(f"{name}.") self.filters.minimal_menu = True self.prefix.insertItems(0, sorted(prefixes, key=lambda x: (-len(x), x))) self.prefix.setEnabled(False) self.prefix.currentIndexChanged.connect(self.prefix_changed) if prefixes: self.remove_prefix.setCheckState(QtCore.Qt.CheckState.Checked) self._settings = QtCore.QSettings() integer_mode = self._settings.value("tabular_format", "phys") self.format_selection.setCurrentText(integer_mode) self.tree.dataView.setAcceptDrops(True) self.tree.dataView.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove) self.tree.dataView.setDropIndicatorShown(True) self.tree.dataView.setDefaultDropAction(QtCore.Qt.DropAction.MoveAction) def close(self): self.owner = None super().close() asammdf-8.5.1/src/asammdf/gui/widgets/tabular_base.py000066400000000000000000002436331502633300400225730ustar00rootroot00000000000000# # this file contains substantial amount of code from https://github.com/adamerose/PandasGUI which is licensed as MIT: # # MIT License # # Copyright (c) 2018 Adam Rose # # 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. # # # import bisect import datetime import logging from traceback import format_exc import numpy as np import pandas as pd from PySide6 import QtCore, QtGui, QtWidgets import asammdf.mdf as mdf_module from ...blocks.utils import csv_bytearray2hex, pandas_query_compatible, timeit from ..dialogs.range_editor import RangeEditor from ..serde import extract_mime_names from ..ui.tabular import Ui_TabularDisplay from ..utils import ( copy_ranges, FONT_SIZE, get_colors_using_ranges, run_thread_with_progress, value_as_str, ) from .tabular_filter import TabularFilter try: npchar = np.strings except: npchar = np.char Qt = QtCore.Qt logger = logging.getLogger("asammdf.gui") LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo MONOSPACE_FONT = None class TabularTreeItem(QtWidgets.QTreeWidgetItem): DEFAULT_FLAGS = QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsSelectable def __init__(self, column_types, int_format, ranges=None, *args, **kwargs): self.column_types = column_types self.int_format = int_format self.ranges = ranges super().__init__(*args, **kwargs) self._back_ground_color = self.background(0) self._font_color = self.foreground(0) self._current_background_color = self._back_ground_color self._current_font_color = self._font_color self.check_signal_range() def __lt__(self, other): column = self.treeWidget().sortColumn() dtype = self.column_types[column] if dtype in "ui": if self.int_format == "hex": return int(self.text(column), 16) < int(other.text(column), 16) elif self.int_format == "bin": return int(self.text(column), 2) < int(other.text(column), 2) else: return int(self.text(column)) < int(other.text(column)) elif dtype == "f": return float(self.text(column)) < float(other.text(column)) else: return self.text(column) < other.text(column) def check_signal_range(self): if not self.ranges: return for column, channel_ranges in enumerate(self.ranges, 1): value = self.text(column) dtype = self.column_types[column] if dtype in "ui": if self.int_format == "hex": value = int(value, 16) elif self.int_format == "bin": value = int(value, 2) else: value = int(value) value = float(value) elif dtype == "f": value = float(value) new_background_color, new_font_color = get_colors_using_ranges( value, ranges=channel_ranges, default_background_color=self._current_background_color, default_font_color=self._current_font_color, ) self.setBackground(column, new_background_color) self.setForeground(column, new_font_color) class DataFrameStorage: """All methods that modify the data should modify self.df_unfiltered, then self.df gets computed from that. """ def __init__(self, df, tabular): super().__init__() self.df = df self.df.cached_size = df.shape self.df_unfiltered = df self.tabular = tabular self.sorted_column_name = None self.sorted_index_level = None self.sort_state = "None" self.dataframe_viewer = None self.filter_viewer = None self.filters = [] self.filtered_index_map = df.reset_index().index self.data_changed() @property def sorted_column_ix(self): try: return list(self.df_unfiltered.columns).index(self.sorted_column_name) except ValueError: return None ################################### # Changing columns def delete_column(self, ix): col_name = self.df_unfiltered.columns[ix] self.df_unfiltered = self.df_unfiltered.drop(col_name, axis=1) # Need to inform the PyQt model too so column widths properly shift self.dataframe_viewer._remove_column(ix) self.parent.apply_filters() def move_column(self, src, dest): cols = list(self.df_unfiltered.columns) cols.insert(dest, cols.pop(src)) self.df_unfiltered = self.df_unfiltered.reindex(cols, axis=1) self.dataframe_viewer.setUpdatesEnabled(False) # Need to inform the PyQt model too so column widths properly shift self.dataframe_viewer._move_column(src, dest) self.apply_filters() self.dataframe_viewer.setUpdatesEnabled(True) ################################### # Sorting def sort_column(self, ix, next_sort_state=None): col_name = self.df_unfiltered.columns[ix] # Determine next sorting state by current state if next_sort_state is None: # Clicked an unsorted column if ix != self.sorted_column_ix: next_sort_state = "Asc" # Clicked a sorted column elif ix == self.sorted_column_ix and self.sort_state == "Asc": next_sort_state = "Desc" # Clicked a reverse sorted column - reset to sorted by index elif ix == self.sorted_column_ix: next_sort_state = "None" if next_sort_state == "Asc": self.df_unfiltered = self.df_unfiltered.sort_values(col_name, ascending=True, kind="mergesort") self.sorted_column_name = self.df_unfiltered.columns[ix] self.sort_state = "Asc" elif next_sort_state == "Desc": self.df_unfiltered = self.df_unfiltered.sort_values(col_name, ascending=False, kind="mergesort") self.sorted_column_name = self.df_unfiltered.columns[ix] self.sort_state = "Desc" elif next_sort_state == "None": self.df_unfiltered = self.df_unfiltered.sort_index(ascending=True, kind="mergesort") self.sorted_column_name = None self.sort_state = "None" self.sorted_index_level = None self.tabular.apply_filters() def sort_index(self, ix: int): # Clicked an unsorted index level if ix != self.sorted_index_level: self.df_unfiltered = self.df_unfiltered.sort_index(level=ix, ascending=True, kind="mergesort") self.sorted_index_level = ix self.sort_state = "Asc" # Clicked a sorted index level elif ix == self.sorted_index_level and self.sort_state == "Asc": self.df_unfiltered = self.df_unfiltered.sort_index(level=ix, ascending=False, kind="mergesort") self.sorted_index_level = ix self.sort_state = "Desc" # Clicked a reverse sorted index level - reset to sorted by full index elif ix == self.sorted_index_level: self.df_unfiltered = self.df_unfiltered.sort_index(ascending=True, kind="mergesort") self.sorted_index_level = None self.sort_state = "None" self.sorted_column = None self.tabular.apply_filters() def change_column_type(self, ix: int, type): name = self.df_unfiltered.columns[ix] self.df_unfiltered[name] = self.df_unfiltered[name].astype(type) self.tabular.apply_filters() ################################### # Other def data_changed(self): self.refresh_ui() # Refresh PyQt models when the underlying pgdf is changed in anyway that needs to be reflected in the GUI def refresh_ui(self): self.models = [] if self.filter_viewer is not None: self.models += [self.filter_viewer.list_model] for model in self.models: model.beginResetModel() model.endResetModel() if self.dataframe_viewer is not None: self.dataframe_viewer.refresh_ui() class DataTableModel(QtCore.QAbstractTableModel): """Model for DataTableView to connect for DataFrame data.""" def __init__(self, parent, background_color, font_color): super().__init__(parent) self.dataframe_viewer = parent self.pgdf = parent.pgdf self.format = "phys" self.float_precision = -1 self.background_color = background_color self.font_color = font_color def headerData(self, section, orientation, role=None): # Headers for DataTableView are hidden. Header data is shown in HeaderView pass def columnCount(self, parent=None): return self.pgdf.df.cached_size[1] def rowCount(self, parent=None): return self.pgdf.df.cached_size[0] # Returns the data from the DataFrame def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole): row = index.row() col = index.column() cell = self.pgdf.df.iloc[row, col] name = self.pgdf.df_unfiltered.columns[col] if role == QtCore.Qt.ItemDataRole.DisplayRole: # Need to check type since a cell might contain a list or Series, then .isna returns a Series not a bool cell_is_na = pd.isna(cell) if type(cell_is_na) == bool and cell_is_na: return "●" elif isinstance(cell, (bytes, np.bytes_)): return cell.decode("utf-8", "replace") else: return value_as_str(cell, self.format, None, self.float_precision) elif role == QtCore.Qt.ItemDataRole.BackgroundRole: channel_ranges = self.pgdf.tabular.ranges[name] try: value = float(cell) except: value = str(cell) new_background_color, new_font_color = get_colors_using_ranges( value, ranges=channel_ranges, default_background_color=self.background_color, default_font_color=self.font_color, ) return new_background_color if new_background_color != self.background_color else None elif role == QtCore.Qt.ItemDataRole.ForegroundRole: channel_ranges = self.pgdf.tabular.ranges[name] try: value = float(cell) except: value = str(cell) new_background_color, new_font_color = get_colors_using_ranges( value, ranges=channel_ranges, default_background_color=self.background_color, default_font_color=self.font_color, ) return new_font_color if new_font_color != self.font_color else None elif role == QtCore.Qt.ItemDataRole.TextAlignmentRole: if isinstance(cell, str): return int(QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter) elif isinstance(cell, pd.Timestamp): return int(QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter) else: if self.float_precision == -1 and isinstance(cell, (float, np.floating)): return int(QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter) else: return int(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter) def flags(self, index): return TabularTreeItem.DEFAULT_FLAGS def setData(self, index, value, role=None): pass class DataTableView(QtWidgets.QTableView): add_channels_request = QtCore.Signal(list) def __init__(self, parent): super().__init__(parent) self.dataframe_viewer = parent self.pgdf = parent.pgdf self._backgrund_color = self.palette().color(QtGui.QPalette.ColorRole.Window) self._font_color = self.palette().color(QtGui.QPalette.ColorRole.WindowText) # Create and set model model = DataTableModel(parent, self._backgrund_color, self._font_color) self.setModel(model) # Hide the headers. The DataFrame headers (index & columns) will be displayed in the DataFrameHeaderViews self.horizontalHeader().hide() self.verticalHeader().hide() # Link selection to headers self.selectionModel().selectionChanged.connect(self.on_selectionChanged) # Settings # self.setWordWrap(True) # self.resizeRowsToContents() self.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) self.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) font = QtGui.QFont() font.fromString(MONOSPACE_FONT) self.setFont(font) self.setAcceptDrops(False) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.NoDragDrop) self.setDropIndicatorShown(False) def on_selectionChanged(self): """Runs when cells are selected in the main table. This logic highlights the correct cells in the vertical and horizontal headers when a data cell is selected. """ columnHeader = self.dataframe_viewer.columnHeader indexHeader = self.dataframe_viewer.indexHeader # The two blocks below check what columns or rows are selected in the data table and highlights the # corresponding ones in the two headers. The if statements check for focus on headers, because if the user # clicks a header that will auto-select all cells in that row or column which will trigger this function # and cause and infinite loop if not columnHeader.hasFocus(): selection = self.selectionModel().selection() columnHeader.selectionModel().select( selection, QtCore.QItemSelectionModel.SelectionFlag.Columns | QtCore.QItemSelectionModel.SelectionFlag.ClearAndSelect, ) if not indexHeader.hasFocus(): selection = self.selectionModel().selection() indexHeader.selectionModel().select( selection, QtCore.QItemSelectionModel.SelectionFlag.Rows | QtCore.QItemSelectionModel.SelectionFlag.ClearAndSelect, ) def sizeHint(self): # Set width and height based on number of columns in model # Width width = 2 * self.frameWidth() # Account for border & padding # width += self.verticalScrollBar().width() # Dark theme has scrollbars always shown for i in range(self.model().columnCount()): width += self.columnWidth(i) # Height height = 2 * self.frameWidth() # Account for border & padding # height += self.horizontalScrollBar().height() # Dark theme has scrollbars always shown height += 24 * self.model().rowCount() # for i in range(self.model().rowCount()): # height += self.rowHeight(i) return QtCore.QSize(width, height) def dragEnterEvent(self, e): e.accept() def dropEvent(self, e): if e.source() is self: e.ignore() else: data = e.mimeData() if data.hasFormat("application/octet-stream-asammdf"): names = extract_mime_names(data) self.add_channels_request.emit(names) e.accept() else: e.ignore() def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if key == QtCore.Qt.Key.Key_R and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() selected_items = {index.column() for index in self.selectedIndexes() if index.isValid()} if selected_items: ranges = [] for index in selected_items: original_name = self.pgdf.df_unfiltered.columns[index] ranges.extend(self.pgdf.tabular.ranges[original_name]) dlg = RangeEditor("", "", ranges=ranges, parent=self, brush=True) dlg.exec_() if dlg.pressed_button == "apply": ranges = dlg.result for index in selected_items: original_name = self.pgdf.df_unfiltered.columns[index] self.pgdf.tabular.ranges[original_name] = copy_ranges(ranges) else: super().keyPressEvent(event) class HeaderModel(QtCore.QAbstractTableModel): def __init__(self, parent, orientation): super().__init__(parent) self.orientation = orientation self.pgdf = parent.pgdf self.prefix = "" def columnCount(self, parent=None): if self.orientation == Qt.Orientation.Horizontal: return self.pgdf.df.columns.shape[0] else: # Vertical return self.pgdf.df.index.nlevels def rowCount(self, parent=None): if self.orientation == Qt.Orientation.Horizontal: return self.pgdf.df.columns.nlevels elif self.orientation == Qt.Orientation.Vertical: return self.pgdf.df.index.shape[0] def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole): row = index.row() col = index.column() if role == QtCore.Qt.ItemDataRole.DisplayRole: if self.orientation == Qt.Orientation.Horizontal: if isinstance(self.pgdf.df.columns, pd.MultiIndex): val = str(self.pgdf.df.columns[col][row]) else: val = str(self.pgdf.df.columns[col]) val = val[len(self.prefix) :] if val.startswith(self.prefix) else val return val elif self.orientation == Qt.Orientation.Vertical: if isinstance(self.pgdf.df.index, pd.MultiIndex): return str(self.pgdf.df.index[row][col]) else: return str(self.pgdf.df.index[row]) elif role == QtCore.Qt.ItemDataRole.DecorationRole: if self.pgdf.sort_state == "Asc": icon = QtGui.QIcon(":/sort-ascending.png") elif self.pgdf.sort_state == "Desc": icon = QtGui.QIcon(":/sort-descending.png") else: return if ( col == self.pgdf.sorted_column_ix and row == self.rowCount() - 1 and self.orientation == Qt.Orientation.Horizontal ): return icon elif role == QtCore.Qt.ItemDataRole.TextAlignmentRole: if self.orientation == Qt.Orientation.Horizontal: name = self.pgdf.df_unfiltered.columns[col] dtype = self.pgdf.df_unfiltered[name].values.dtype float_precision = self.pgdf.dataframe_viewer.dataView.model().float_precision if np.issubdtype(dtype, np.integer): return int(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter) elif float_precision != -1 and np.issubdtype(dtype, np.floating): return int(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter) else: return int(QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter) else: return QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter # The headers of this table will show the level names of the MultiIndex def headerData(self, section, orientation, role=None): # This was moved to HeaderNamesModel pass class HeaderView(QtWidgets.QTableView): """Displays the DataFrame index or columns depending on orientation.""" def __init__(self, parent, orientation): super().__init__(parent) self.dataframe_viewer = parent self.pgdf = parent.pgdf self.setProperty("orientation", "horizontal" if orientation == 1 else "vertical") # Used in stylesheet # Setup self.orientation = orientation self.table = parent.dataView self.setModel(HeaderModel(parent, orientation)) self.padding = 90 ############### # These are used in self.manage_resizing # Holds the index of the cell being resized, or None if resize isn't happening self.header_cell_being_resized = None # Boolean indicating whether the header itself is currently being resized self.header_being_resized = False ############### # Handled by self.eventFilter() self.setMouseTracking(True) self.viewport().setMouseTracking(True) self.viewport().installEventFilter(self) # Settings self.setIconSize(QtCore.QSize(16, 16)) self.setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Maximum) ) self.setWordWrap(False) self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) self.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) font = QtGui.QFont() font.fromString(MONOSPACE_FONT) font.setBold(True) self.setFont(font) # Link selection to DataTable self.selectionModel().selectionChanged.connect(lambda x: self.on_selectionChanged()) # self.set_spans() self.horizontalHeader().hide() self.verticalHeader().hide() self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) # Automatically stretch rows/columns as widget is resized if self.orientation == Qt.Orientation.Vertical: self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Stretch) # Set initial size self.resize(self.sizeHint()) def showEvent(self, a0: QtGui.QShowEvent) -> None: super().showEvent(a0) self.initial_size = self.size() def mouseDoubleClickEvent(self, event): point = event.pos() ix = self.indexAt(point) col = ix.column() if event.button() == QtCore.Qt.MouseButton.LeftButton: # When a header is clicked, sort the DataFrame by that column if self.orientation == Qt.Orientation.Horizontal: self.pgdf.sort_column(col) else: self.on_selectionChanged() else: super().mouseDoubleClickEvent(event) def mousePressEvent(self, event): point = event.pos() ix = self.indexAt(point) col = ix.column() if event.button() == QtCore.Qt.MouseButton.RightButton and self.orientation == Qt.Orientation.Horizontal: self.dataframe_viewer.show_column_menu(col) else: super().mousePressEvent(event) # Header def on_selectionChanged(self, force=False): """Runs when cells are selected in the Header. This selects columns in the data table when the header is clicked, and then calls selectAbove(). """ # Check focus so we don't get recursive loop, since headers trigger selection of data cells and vice versa if self.hasFocus() or force: dataView = self.dataframe_viewer.dataView # Set selection mode so selecting one row or column at a time adds to selection each time if self.orientation == Qt.Orientation.Horizontal: # This case is for the horizontal header # Get the header's selected columns selection = self.selectionModel().selection() # Removes the higher levels so that only the lowest level of the header affects the data table selection last_row_ix = self.pgdf.df.columns.nlevels - 1 last_col_ix = self.model().columnCount() - 1 higher_levels = QtCore.QItemSelection( self.model().index(0, 0), self.model().index(last_row_ix - 1, last_col_ix), ) selection.merge(higher_levels, QtCore.QItemSelectionModel.SelectionFlag.Deselect) # Select the cells in the data view dataView.selectionModel().select( selection, QtCore.QItemSelectionModel.SelectionFlag.Columns | QtCore.QItemSelectionModel.SelectionFlag.ClearAndSelect, ) if self.orientation == Qt.Orientation.Vertical: selection = self.selectionModel().selection() last_row_ix = self.model().rowCount() - 1 last_col_ix = self.pgdf.df.index.nlevels - 1 higher_levels = QtCore.QItemSelection( self.model().index(0, 0), self.model().index(last_row_ix, last_col_ix - 1), ) selection.merge(higher_levels, QtCore.QItemSelectionModel.SelectionFlag.Deselect) dataView.selectionModel().select( selection, QtCore.QItemSelectionModel.SelectionFlag.Rows | QtCore.QItemSelectionModel.SelectionFlag.ClearAndSelect, ) self.selectAbove() # Take the current set of selected cells and make it so that any spanning cell above a selected cell is selected too # This should happen after every selection change def selectAbove(self): # Disabling this to allow selecting specific cells in headers return if self.orientation == Qt.Orientation.Horizontal: if self.pgdf.df.columns.nlevels == 1: return else: if self.pgdf.df.index.nlevels == 1: return for ix in self.selectedIndexes(): if self.orientation == Qt.Orientation.Horizontal: # Loop over the rows above this one for row in range(ix.row()): ix2 = self.model().index(row, ix.column()) self.setSelection(self.visualRect(ix2), QtCore.QItemSelectionModel.SelectionFlag.Select) else: # Loop over the columns left of this one for col in range(ix.column()): ix2 = self.model().index(ix.row(), col) self.setSelection(self.visualRect(ix2), QtCore.QItemSelectionModel.SelectionFlag.Select) # This sets spans to group together adjacent cells with the same values def set_spans(self): df = self.pgdf.df self.clearSpans() # Find spans for horizontal HeaderView if self.orientation == Qt.Orientation.Horizontal: # Find how many levels the MultiIndex has if isinstance(df.columns, pd.MultiIndex): N = len(df.columns[0]) else: N = 1 for level in range(N): # Iterates over the levels # Find how many segments the MultiIndex has if isinstance(df.columns, pd.MultiIndex): arr = [df.columns[i][level] for i in range(len(df.columns))] else: arr = df.columns # Holds the starting index of a range of equal values. # None means it is not currently in a range of equal values. match_start = None for col in range(1, len(arr)): # Iterates over cells in row # Check if cell matches cell to its left if arr[col] == arr[col - 1]: if match_start is None: match_start = col - 1 # If this is the last cell, need to end it if col == len(arr) - 1: match_end = col span_size = match_end - match_start + 1 self.setSpan(level, match_start, 1, span_size) else: if match_start is not None: match_end = col - 1 span_size = match_end - match_start + 1 self.setSpan(level, match_start, 1, span_size) match_start = None # Find spans for vertical HeaderView else: # Find how many levels the MultiIndex has if isinstance(df.index, pd.MultiIndex): N = len(df.index[0]) else: N = 1 for level in range(N): # Iterates over the levels # Find how many segments the MultiIndex has if isinstance(df.index, pd.MultiIndex): arr = [df.index[i][level] for i in range(len(df.index))] else: arr = df.index # Holds the starting index of a range of equal values. # None means it is not currently in a range of equal values. match_start = None for row in range(1, len(arr)): # Iterates over cells in column # Check if cell matches cell above if arr[row] == arr[row - 1]: if match_start is None: match_start = row - 1 # If this is the last cell, need to end it if row == len(arr) - 1: match_end = row span_size = match_end - match_start + 1 self.setSpan(match_start, level, span_size, 1) else: if match_start is not None: match_end = row - 1 span_size = match_end - match_start + 1 self.setSpan(match_start, level, span_size, 1) match_start = None def eventFilter(self, object: QtCore.QObject, event: QtCore.QEvent): if event.type() in [ QtCore.QEvent.Type.MouseButtonPress, QtCore.QEvent.Type.MouseButtonRelease, QtCore.QEvent.Type.MouseButtonDblClick, QtCore.QEvent.Type.MouseMove, ]: return self.manage_resizing(object, event) return False # This method handles all the resizing of headers including column width, row height, and header width/height def manage_resizing(self, object: QtCore.QObject, event: QtCore.QEvent): # This is used for resizing column widths and row heights # For the horizontal header, return the column edge the mouse is over # For the vertical header, return the row edge the mouse is over # mouse_position is the position along the relevant axis, ie. horizontal x position for the top header def over_header_cell_edge(mouse_position, margin=3): # Return the index of the column this x position is on the right edge of if self.orientation == Qt.Orientation.Horizontal: x = mouse_position if self.columnAt(x - margin) != self.columnAt(x + margin): if self.columnAt(x + margin) == 0: # We're at the left edge of the first column return None else: return self.columnAt(x - margin) else: return None # Return the index of the row this y position is on the top edge of elif self.orientation == Qt.Orientation.Vertical: y = mouse_position if self.rowAt(y - margin) != self.rowAt(y + margin): if self.rowAt(y + margin) == 0: # We're at the top edge of the first row return None else: return self.rowAt(y - margin) else: return None # This is used for resizing the left header width or the top header height # Returns a boolean indicating whether the mouse is over the header edge to allow resizing def over_header_edge(mouse_position: QtCore.QPoint(), margin=7) -> bool: if self.orientation == Qt.Orientation.Horizontal: return abs(mouse_position - self.height()) < margin elif self.orientation == Qt.Orientation.Vertical: return abs(mouse_position - self.width()) < margin # mouse_position is the position along the axis of the header. X pos for top header, Y pos for side header if self.orientation == Qt.Orientation.Horizontal: mouse_position = event.pos().x() orthogonal_mouse_position = event.pos().y() else: mouse_position = event.pos().y() orthogonal_mouse_position = event.pos().x() # Set the cursor shape if over_header_cell_edge(mouse_position) is not None: if self.orientation == Qt.Orientation.Horizontal: self.viewport().setCursor(QtGui.QCursor(Qt.CursorShape.SplitHCursor)) elif self.orientation == Qt.Orientation.Vertical: self.viewport().setCursor(QtGui.QCursor(Qt.CursorShape.SplitVCursor)) elif over_header_edge(orthogonal_mouse_position): if self.orientation == Qt.Orientation.Horizontal: # Disabling vertical resizing of top header for now pass # self.viewport().setCursor(QtGui.QCursor(Qt.CursorShape.SplitVCursor)) elif self.orientation == Qt.Orientation.Vertical: self.viewport().setCursor(QtGui.QCursor(Qt.CursorShape.SplitHCursor)) else: self.viewport().setCursor(QtGui.QCursor(Qt.CursorShape.ArrowCursor)) # If mouse is on an edge, start the drag resize process if event.type() == QtCore.QEvent.Type.MouseButtonPress: if over_header_cell_edge(mouse_position) is not None: self.header_cell_being_resized = over_header_cell_edge(mouse_position) return True # Disabling vertical resizing of top header for now elif over_header_edge(orthogonal_mouse_position) and self.orientation == Qt.Orientation.Vertical: self.header_being_resized = True return True else: self.header_cell_being_resized = None # End the drag process if event.type() == QtCore.QEvent.Type.MouseButtonRelease: self.header_cell_being_resized = None self.header_being_resized = False # Auto size the column that was double clicked if event.type() == QtCore.QEvent.Type.MouseButtonDblClick: # Find which column or row edge the mouse was over and auto size it if over_header_cell_edge(mouse_position) is not None: header_index = over_header_cell_edge(mouse_position) if self.orientation == Qt.Orientation.Horizontal: self.dataframe_viewer.auto_size_column(header_index) elif self.orientation == Qt.Orientation.Vertical: self.dataframe_viewer.auto_size_row(header_index) return True # Handle drag resizing if event.type() == QtCore.QEvent.Type.MouseMove: # If this is None, there is no drag resize happening if self.header_cell_being_resized is not None: size = mouse_position - self.columnViewportPosition(self.header_cell_being_resized) if size > 10: if self.orientation == Qt.Orientation.Horizontal: self.setColumnWidth(self.header_cell_being_resized, size) self.dataframe_viewer.dataView.setColumnWidth(self.header_cell_being_resized, size) if self.orientation == Qt.Orientation.Vertical: self.setRowHeight(self.header_cell_being_resized, size) self.dataframe_viewer.dataView.setRowHeight(self.header_cell_being_resized, size) self.updateGeometry() self.dataframe_viewer.dataView.updateGeometry() return True elif self.header_being_resized: if self.orientation == Qt.Orientation.Horizontal: size = orthogonal_mouse_position - self.geometry().top() self.setFixedHeight(max(size, self.initial_size.height())) if self.orientation == Qt.Orientation.Vertical: size = orthogonal_mouse_position - self.geometry().left() self.setFixedWidth(max(size, self.initial_size.width())) self.updateGeometry() self.dataframe_viewer.dataView.updateGeometry() return True return False # Return the size of the header needed to match the corresponding DataTableView def sizeHint(self): # Columm headers if self.orientation == Qt.Orientation.Horizontal: # Width of DataTableView width = self.table.sizeHint().width() + self.verticalHeader().width() # Height # height = 2 * self.frameWidth() # Account for border & padding # for i in range(self.model().rowCount()): # height += self.rowHeight height = 24 * self.model().rowCount() # Index header else: # Height of DataTableView height = self.table.sizeHint().height() + self.horizontalHeader().height() # Width width = 2 * self.frameWidth() # Account for border & padding for i in range(self.model().columnCount()): width += max(self.columnWidth(i), 100) return QtCore.QSize(width, height) # This is needed because otherwise when the horizontal header is a single row it will add whitespace to be bigger def minimumSizeHint(self): if self.orientation == Qt.Orientation.Horizontal: return QtCore.QSize(0, self.sizeHint().height()) else: return QtCore.QSize(self.sizeHint().width(), 0) class HeaderNamesModel(QtCore.QAbstractTableModel): def __init__(self, parent, orientation): super().__init__(parent) self.orientation = orientation self.pgdf = parent.pgdf self.prefix = "" def columnCount(self, parent=None): if self.orientation == Qt.Orientation.Horizontal: return 1 elif self.orientation == Qt.Orientation.Vertical: return self.pgdf.df.index.nlevels def rowCount(self, parent=None): if self.orientation == Qt.Orientation.Horizontal: return self.pgdf.df.columns.nlevels elif self.orientation == Qt.Orientation.Vertical: return 1 def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole): row = index.row() col = index.column() if role == QtCore.Qt.ItemDataRole.DisplayRole: if self.orientation == Qt.Orientation.Horizontal: val = self.pgdf.df.columns.names[row] if val is None: val = "" val = val[len(self.prefix) :] if val.startswith(self.prefix) else val return str(val) elif self.orientation == Qt.Orientation.Vertical: val = self.pgdf.df.index.names[col] if val is None: val = "Index" return str(val) elif role == QtCore.Qt.ItemDataRole.DecorationRole: if self.pgdf.sort_state == "Asc": icon = QtGui.QIcon(":/sort-ascending.png") elif self.pgdf.sort_state == "Desc": icon = QtGui.QIcon(":/sort-descending.png") else: return if col == self.pgdf.sorted_index_level and self.orientation == Qt.Orientation.Vertical: return icon elif role == QtCore.Qt.ItemDataRole.TextAlignmentRole: return int(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter) class HeaderNamesView(QtWidgets.QTableView): def __init__(self, parent, orientation): super().__init__(parent) self.dataframe_viewer = parent self.pgdf = parent.pgdf self.setProperty("orientation", "horizontal" if orientation == 1 else "vertical") # Used in stylesheet # Setup self.orientation = orientation self.setModel(HeaderNamesModel(parent, orientation)) self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) self.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) self.horizontalHeader().hide() self.verticalHeader().hide() self.setSelectionMode(self.SelectionMode.NoSelection) # Automatically stretch rows/columns as widget is resized if self.orientation == Qt.Orientation.Horizontal: self.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Stretch) else: self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Stretch) font = QtGui.QFont() font.fromString(MONOSPACE_FONT) font.setBold(True) self.setFont(font) self.init_size() def mouseDoubleClickEvent(self, event): point = event.pos() ix = self.indexAt(point) if event.button() == QtCore.Qt.MouseButton.LeftButton: if self.orientation == Qt.Orientation.Vertical: self.pgdf.sort_index(ix.column()) else: super().mouseDoubleClickEvent(event) def init_size(self): # Match vertical header name widths to vertical header if self.orientation == Qt.Orientation.Vertical: for ix in range(self.model().columnCount()): self.setColumnWidth(ix, self.columnWidth(ix)) def sizeHint(self): if self.orientation == Qt.Orientation.Horizontal: width = self.columnWidth(0) height = 24 else: # Vertical width = self.dataframe_viewer.indexHeader.sizeHint().width() height = 24 return QtCore.QSize(width, height) def minimumSizeHint(self): return self.sizeHint() def rowHeight(self, row: int) -> int: return self.dataframe_viewer.columnHeader.rowHeight(row) def columnWidth(self, column: int) -> int: if self.orientation == Qt.Orientation.Horizontal: if all(name is None for name in self.pgdf.df.columns.names): return 0 else: return super().columnWidth(column) else: return self.dataframe_viewer.indexHeader.columnWidth(column) class ColumnMenu(QtWidgets.QMenu): def __init__(self, pgdf, column_ix, parent=None): super().__init__(parent) self.pgdf = pgdf self.column_ix = column_ix ######################## # Info idx = self.pgdf.dataframe_viewer.columnHeader.model().index(0, column_ix) self.name = self.pgdf.dataframe_viewer.columnHeader.model().data(idx, role=QtCore.Qt.ItemDataRole.DisplayRole) label = QtWidgets.QLabel(self.name) font = QtGui.QFont() font.setBold(True) label.setFont(font) self.add_widget(label) self.addSeparator() ######################## # Sorting self.add_widget(QtWidgets.QLabel("Set sorting")) def select_button(): self.sort_b1.setDown(self.pgdf.sort_state == "Asc" and self.pgdf.sorted_column_ix == column_ix) self.sort_b2.setDown(self.pgdf.sort_state == "Desc" and self.pgdf.sorted_column_ix == column_ix) self.sort_b3.setDown(self.pgdf.sort_state == "None" or self.pgdf.sorted_column_ix != column_ix) self.sort_b1 = QtWidgets.QPushButton("Asc") self.sort_b1.clicked.connect(lambda: [self.pgdf.sort_column(self.column_ix, "Asc"), select_button()]) self.sort_b2 = QtWidgets.QPushButton("Desc") self.sort_b2.clicked.connect(lambda: [self.pgdf.sort_column(self.column_ix, "Desc"), select_button()]) self.sort_b3 = QtWidgets.QPushButton("None") self.sort_b3.clicked.connect(lambda: [self.pgdf.sort_column(self.column_ix, "None"), select_button()]) select_button() sort_control = QtWidgets.QWidget() sort_control_layout = QtWidgets.QHBoxLayout() sort_control_layout.setSpacing(0) sort_control_layout.setContentsMargins(0, 0, 0, 0) sort_control.setLayout(sort_control_layout) [sort_control_layout.addWidget(w) for w in [self.sort_b1, self.sort_b2, self.sort_b3]] self.add_widget(sort_control) self.addSeparator() button = QtWidgets.QPushButton("Edit ranges") button.clicked.connect(self.edit_ranges) self.add_widget(button) self.addSeparator() action = self.addAction("Automatic set columns width") action.triggered.connect(self.automatic_columns_width) def edit_ranges(self, *args): self.hide() self.pgdf.tabular.edit_ranges(self.column_ix, self.name) self.close() def add_action(self, text, function): action = QtGui.QAction(text, self) action.triggered.connect(function) self.addAction(action) def add_widget(self, widget): # https://stackoverflow.com/questions/55086498/highlighting-custom-qwidgetaction-on-hover widget.setMouseTracking(True) custom_action = QtWidgets.QWidgetAction(self) widget.setStyleSheet(widget.styleSheet() + "margin: 5px;") custom_action.setDefaultWidget(widget) self.addAction(custom_action) def show_menu(self, point): screen_rect = self.screen().availableGeometry() self.move(point) self.show() menu_rect = self.geometry() if not screen_rect.contains(menu_rect): point.setX(point.x() - menu_rect.width()) self.move(point) def automatic_columns_width(self, *args): self.pgdf.dataframe_viewer.auto_size_header() class TabularBase(Ui_TabularDisplay, QtWidgets.QWidget): add_channels_request = QtCore.Signal(list) timestamp_changed_signal = QtCore.Signal(object, float) def __init__(self, df, ranges=None, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) if not ranges: self.ranges = {name: [] for name in df.columns} else: self.ranges = ranges df = DataFrameStorage(df, self) self.tree = DataFrameViewer(df) self.tree.dataView.selectionModel().currentChanged.connect(self.current_changed) self.tree.dataView.add_channels_request.connect(self.add_channels_request) self.horizontalLayout.insertWidget(0, self.tree) self.add_filter_btn.clicked.connect(self.add_filter) self.apply_filters_btn.clicked.connect(self.apply_filters) self.time_as_date.checkStateChanged.connect(self.time_as_date_changed) self.remove_prefix.checkStateChanged.connect(self.remove_prefix_changed) self.format_selection.currentTextChanged.connect(self.set_format) self.toggle_filters_btn.clicked.connect(self.toggle_filters) self.filters_group.setHidden(True) self.float_precision.addItems(["Full float precision"] + [f"{i} float decimals" for i in range(16)]) self.float_precision.setCurrentIndex(0) self.float_precision.currentIndexChanged.connect(self.float_precision_changed) self._timestamps = None # self.show() self.tree.auto_size_header() def float_precision_changed(self, index): self.tree.dataView.model().float_precision = index - 1 self.tree.pgdf.data_changed() def current_changed(self, current, previous): if current.isValid(): row = current.row() self._filtered_ts_series = self._original_ts_series.reindex(self.tree.pgdf.df.index) ts = float(self._filtered_ts_series.iloc[row]) self.timestamp_changed_signal.emit(self, ts) def toggle_filters(self, event=None): if self.toggle_filters_btn.text() == "Show filters": self.toggle_filters_btn.setText("Hide filters") self.filters_group.setHidden(False) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/up.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.toggle_filters_btn.setIcon(icon) else: self.toggle_filters_btn.setText("Show filters") self.filters_group.setHidden(True) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/down.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.toggle_filters_btn.setIcon(icon) def add_filter(self, event=None): filter_widget = TabularFilter( [ ( self.tree.pgdf.df_unfiltered.index.name, self.tree.pgdf.df_unfiltered.index.values.dtype.kind, 0, False, ) ] + [ ( name, self.tree.pgdf.df_unfiltered[name].values.dtype.kind, self.signals_descr[name], ) for name in self.tree.pgdf.df_unfiltered.columns ], self.format_selection.currentText(), ) item = QtWidgets.QListWidgetItem(self.filters) item.setSizeHint(filter_widget.sizeHint()) self.filters.addItem(item) self.filters.setItemWidget(item, filter_widget) def apply_filters(self, event=None): df = self.tree.pgdf.df_unfiltered.copy() friendly_names = {name: pandas_query_compatible(name) for name in df.columns} original_names = {val: key for key, val in friendly_names.items()} df.rename(columns=friendly_names, inplace=True) filters = [] count = self.filters.count() for i in range(count): filter = self.filters.itemWidget(self.filters.item(i)) if filter.enabled.checkState() == QtCore.Qt.CheckState.Unchecked: continue target = filter._target if target is None: continue if filters: filters.append(filter.relation.currentText().lower()) column_name = filter.column.currentText() if column_name == df.index.name: is_byte_array = False else: is_byte_array = self.signals_descr[column_name] column_name = pandas_query_compatible(column_name) op = filter.op.currentText() if target != target: # noqa: PLR0124 # target is NaN _nan = np.nan # used in pandas query if op in (">", ">=", "<", "<="): filters.extend((column_name, op, "@_nan")) elif op == "!=": filters.extend((column_name, "==", column_name)) elif op == "==": filters.extend((column_name, "!=", column_name)) else: if column_name == "timestamps" and df["timestamps"].dtype.kind == "M": ts = pd.Timestamp(target, tz=LOCAL_TIMEZONE) _ts = ts.tz_convert("UTC").to_datetime64() # used in pandas query filters.extend((column_name, op, "@_ts")) elif is_byte_array: target = str(target).replace(" ", "").strip('"') if f"{column_name}__as__bytes" not in df.columns: df[f"{column_name}__as__bytes"] = pd.Series([bytes(s) for s in df[column_name]], index=df.index) _val = bytes.fromhex(target) # used in pandas query filters.extend((f"{column_name}__as__bytes", op, "@_val")) else: filters.extend((column_name, op, str(target))) if filters: try: new_df = df.query(" ".join(filters)) except: logger.exception(f"Failed to apply filter for tabular window: {' '.join(filters)}") self.query.setText(format_exc()) else: to_drop = [name for name in df.columns if name.endswith("__as__bytes")] if to_drop: df.drop(columns=to_drop, inplace=True) new_df.drop(columns=to_drop, inplace=True) self.query.setText(" ".join(filters)) new_df.rename(columns=original_names, inplace=True) new_df.cached_size = new_df.shape self.tree.pgdf.df = new_df self.tree.pgdf.data_changed() else: self.query.setText("") df.rename(columns=original_names, inplace=True) df.cached_size = df.shape self.tree.pgdf.df = df self.tree.pgdf.data_changed() self.tree.pgdf.df_unfiltered.rename(columns=original_names, inplace=True) def add_new_channels(self, signals, mime_data=None): if len(self.tree.pgdf.df_unfiltered) != len(self.tree.pgdf.df): filtered = True else: filtered = False index = pd.Series(np.arange(len(signals), dtype="u8"), index=signals.index) signals["Index"] = index signals.set_index(index, inplace=True) dropped = {} ranges = dict(zip(self.tree.pgdf.df_unfiltered.columns, self.ranges.values(), strict=False)) for name_ in signals.columns: col = signals[name_] if col.dtype.kind == "O": if name_.endswith("DataBytes"): try: sizes = signals[name_.replace("DataBytes", "DataLength")] except: sizes = None dropped[name_] = pd.Series( csv_bytearray2hex( col, sizes, ), index=signals.index, ) elif name_.endswith("Data Bytes"): try: sizes = signals[name_.replace("Data Bytes", "Data Length")] except: sizes = None dropped[name_] = pd.Series( csv_bytearray2hex( col, sizes, ), index=signals.index, ) elif col.dtype.name != "category": try: dropped[name_] = pd.Series(csv_bytearray2hex(col), index=signals.index) except: pass self.signals_descr[name_] = 0 elif col.dtype.kind == "S": try: dropped[name_] = pd.Series(npchar.decode(col, "utf-8"), index=signals.index) except: dropped[name_] = pd.Series(npchar.decode(col, "latin-1"), index=signals.index) self.signals_descr[name_] = 0 else: self.signals_descr[name_] = 0 ranges[name_] = [] signals = signals.drop(columns=["Index", *list(dropped)]) for name, s in dropped.items(): signals[name] = s names = list(signals.columns) names = [ *[name for name in names if name.endswith((".ID", ".DataBytes"))], *[name for name in names if name != "timestamps" and not name.endswith((".ID", ".DataBytes"))], ] signals = signals[names] df = pd.concat([self.tree.pgdf.df_unfiltered, signals], axis=1) df.cached_size = df.shape self.tree.pgdf.df_unfiltered = self.tree.pgdf.df = df self.ranges = ranges if filtered: self.apply_filters() else: self.tree.pgdf.data_changed() self.tree.auto_size_header() self.tree.update_horizontal_scroll() def to_config(self): count = self.filters.count() config = { "sorted": True, "channels": list(self.tree.pgdf.df_unfiltered.columns) if not self.pattern else [], "filtered": bool(self.query.toPlainText()), "filters": ( [self.filters.itemWidget(self.filters.item(i)).to_config() for i in range(count)] if not self.pattern else [] ), "time_as_date": self.time_as_date.checkState() == QtCore.Qt.CheckState.Checked, "pattern": self.pattern, "format": self.format, "ranges": self.ranges, "header_sections_width": [ self.tree.columnHeader.horizontalHeader().sectionSize(i) for i in range(self.tree.columnHeader.horizontalHeader().count()) ], "font_size": self.tree.dataView.font().pointSize(), } return config def time_as_date_changed(self, state): count = self.filters.count() if state == QtCore.Qt.CheckState.Checked: for i in range(count): filter = self.filters.itemWidget(self.filters.item(i)) filter.dtype_kind[0] = "M" if filter.column.currentIndex() == 0: filter.column_changed(0) else: filter.validate_target() delta = pd.to_timedelta(self.tree.pgdf.df_unfiltered["timestamps"], unit="s") timestamps = self.start + delta self.tree.pgdf.df_unfiltered["timestamps"] = timestamps else: for i in range(count): filter = self.filters.itemWidget(self.filters.item(i)) filter.dtype_kind[0] = "f" if filter.column.currentIndex() == 0: filter.column_changed(0) else: filter.validate_target() self.tree.pgdf.df_unfiltered["timestamps"] = self._original_timestamps if self.query.toPlainText(): self.apply_filters() self.tree.pgdf.data_changed() self.tree.auto_size_column(0) def remove_prefix_changed(self, state): if state == QtCore.Qt.CheckState.Checked: self.prefix.setEnabled(True) self.tree.columnHeaderNames.model().prefix = self.prefix.currentText() self.tree.columnHeader.model().prefix = self.prefix.currentText() self.tree.prefix = self.prefix.currentText() else: self.prefix.setEnabled(False) self.tree.columnHeaderNames.model().prefix = "" self.tree.columnHeader.model().prefix = "" self.tree.prefix = "" self.tree.auto_size_header() def prefix_changed(self, index): self.remove_prefix_changed(QtCore.Qt.CheckState.Checked) def open_menu(self, position): menu = QtWidgets.QMenu() menu.addAction("Export to CSV") action = menu.exec_(self.tree.viewport().mapToGlobal(position)) if action is None: return if action.text() == "Export to CSV": file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Select output CSV file", "", "CSV (*.csv)", ) if file_name: self.progress = 0, 0 progress = QtWidgets.QProgressDialog(f'Data export to CSV file "{file_name}"', "", 0, 0, self.parent()) progress.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) progress.setCancelButton(None) progress.setAutoClose(True) progress.setWindowTitle("Export tabular window to CSV") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/csv.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) progress.setWindowIcon(icon) progress.show() target = self.tree.pgdf.df_unfiltered.to_csv kwargs = { "path_or_buf": file_name, "index_label": "Index", "date_format": "%Y-%m-%d %H:%M:%S.%f%z", } result = run_thread_with_progress( self, target=target, kwargs=kwargs, factor=0, offset=0, progress=progress, ) progress.cancel() def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if ( key in (QtCore.Qt.Key.Key_H, QtCore.Qt.Key.Key_B, QtCore.Qt.Key.Key_P) and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier ): event.accept() match key: case QtCore.Qt.Key.Key_H: self.format_selection.setCurrentText("hex") case QtCore.Qt.Key.Key_B: self.format_selection.setCurrentText("bin") case QtCore.Qt.Key.Key_P: self.format_selection.setCurrentText("phys") case QtCore.Qt.Key.Key_T: self.format_selection.setCurrentText("ascii") elif key == QtCore.Qt.Key.Key_S and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() file_name, _ = QtWidgets.QFileDialog.getSaveFileName( self, "Save as measurement file", "", "MDF version 4 files (*.mf4)", ) if file_name: with mdf_module.MDF() as mdf: mdf.append(self.tree.pgdf.df_unfiltered) mdf.save(file_name, overwrite=True) elif key == QtCore.Qt.Key.Key_BracketLeft and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() self.decrease_font() elif key == QtCore.Qt.Key.Key_BracketRight and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() self.increase_font() elif key == QtCore.Qt.Key.Key_G and modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier: event.accept() value, ok = QtWidgets.QInputDialog.getDouble( self, "Go to time stamp", "Time stamp", decimals=9, ) if ok: self.set_timestamp(value) else: self.tree.dataView.keyPressEvent(event) def set_format(self, fmt): self.format = fmt self.tree.dataView.model().format = fmt self.tree.pgdf.data_changed() self._settings.setValue("tabular_format", fmt) for row in range(self.filters.count()): filter = self.filters.itemWidget(self.filters.item(row)) filter.int_format = fmt filter.validate_target() if self.query.toPlainText(): self.apply_filters() def set_timestamp(self, stamp): self._filtered_ts_series = self._original_ts_series.reindex(self.tree.pgdf.df.index) if not len(self._filtered_ts_series): return if not (self._filtered_ts_series.iloc[0] <= stamp <= self._filtered_ts_series.iloc[-1]): return idx = self._filtered_ts_series.searchsorted(stamp, side="right") - 1 idx = max(idx, 0) self.tree.dataView.selectRow(idx) def edit_ranges(self, index, name): if index >= 0: original_name = self.tree.pgdf.df_unfiltered.columns[index] dlg = RangeEditor(name, "", self.ranges[original_name], parent=self, brush=True) dlg.exec_() if dlg.pressed_button == "apply": ranges = dlg.result self.ranges[original_name] = ranges def decrease_font(self): font = self.tree.dataView.font() size = font.pointSize() pos = bisect.bisect_left(FONT_SIZE, size) - 1 pos = max(pos, 0) new_size = FONT_SIZE[pos] self.set_font_size(new_size) def increase_font(self): font = self.tree.dataView.font() size = font.pointSize() pos = bisect.bisect_right(FONT_SIZE, size) if pos == len(FONT_SIZE): pos -= 1 new_size = FONT_SIZE[pos] self.set_font_size(new_size) def set_font_size(self, size): self.hide() font = self.tree.dataView.font() font.setPointSize(size) self.tree.dataView.setFont(font) font.setBold(True) self.tree.indexHeader.setFont(font) self.tree.indexHeaderNames.setFont(font) self.tree.columnHeader.setFont(font) self.tree.columnHeaderNames.setFont(font) self.show() self.tree.default_row_height = 12 + size self.tree.set_styles() class DataFrameViewer(QtWidgets.QWidget): def __init__(self, pgdf): super().__init__() global MONOSPACE_FONT if MONOSPACE_FONT is None: families = QtGui.QFontDatabase.families() for family in ( "Consolas", "Liberation Mono", "DejaVu Sans Mono", "Droid Sans Mono", "Liberation Mono", "Roboto Mono", "Monaco", "Courier", ): if family in families: MONOSPACE_FONT = f"{family},9,-1,5,400,0,0,0,0,0,0,0,0,0,0,1,Regular" break pgdf.dataframe_viewer = self self.pgdf = pgdf self.prefix = "" # Local state # How to color cells self.color_mode = None # Set up DataFrame TableView and Model self.dataView = DataTableView(parent=self) # Create headers self.columnHeader = HeaderView(parent=self, orientation=Qt.Orientation.Horizontal) self.indexHeader = HeaderView(parent=self, orientation=Qt.Orientation.Vertical) self.columnHeaderNames = HeaderNamesView(parent=self, orientation=Qt.Orientation.Horizontal) self.indexHeaderNames = HeaderNamesView(parent=self, orientation=Qt.Orientation.Vertical) # Set up layout self.gridLayout = QtWidgets.QGridLayout() self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setSpacing(0) self.setLayout(self.gridLayout) # Linking scrollbars # Scrolling in data table also scrolls the headers self.dataView.horizontalScrollBar().valueChanged.connect(self.columnHeader.horizontalScrollBar().setValue) self.dataView.horizontalScrollBar().valueChanged.connect(self.columnHeaderNames.horizontalScrollBar().setValue) self.dataView.verticalScrollBar().valueChanged.connect(self.indexHeader.verticalScrollBar().setValue) # Scrolling in headers also scrolls the data table self.columnHeader.horizontalScrollBar().valueChanged.connect(self.dataView.horizontalScrollBar().setValue) self.indexHeader.verticalScrollBar().valueChanged.connect(self.dataView.verticalScrollBar().setValue) # Turn off default scrollbars self.dataView.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.dataView.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) # Disable scrolling on the headers. Even though the scrollbars are hidden, scrolling by dragging desyncs them self.indexHeader.horizontalScrollBar().valueChanged.connect(lambda: None) class CornerWidget(QtWidgets.QWidget): def __init__(self): super().__init__() # https://stackoverflow.com/questions/32313469/stylesheet-in-pyside-not-working self.setAttribute(QtCore.Qt.WidgetAttribute.WA_StyledBackground) self.corner_widget = CornerWidget() self.corner_widget.setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) ) # Add items to grid layout # self.gridLayout.addWidget(self.corner_widget, 0, 0) self.gridLayout.addWidget(self.columnHeader, 0, 1, 2, 2, Qt.AlignmentFlag.AlignTop) self.gridLayout.addWidget(self.columnHeaderNames, 0, 3, 2, 1) self.gridLayout.addWidget(self.indexHeader, 2, 0, 2, 2, Qt.AlignmentFlag.AlignLeft) self.gridLayout.addWidget(self.indexHeaderNames, 1, 0, 1, 1, Qt.AlignmentFlag.AlignBottom) self.gridLayout.addWidget(self.dataView, 3, 2, 1, 1) self.gridLayout.addWidget(self.dataView.horizontalScrollBar(), 4, 2, 1, 1) self.gridLayout.addWidget(self.dataView.verticalScrollBar(), 3, 3, 1, 1) # Fix scrollbars forcing a minimum height of the dataView which breaks layout for small number of rows self.dataView.verticalScrollBar().setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Ignored) ) self.dataView.horizontalScrollBar().setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Ignored, QtWidgets.QSizePolicy.Policy.Fixed) ) # These expand when the window is enlarged instead of having the grid squares spread out # self.gridLayout.setColumnStretch(4, 1) # self.gridLayout.setRowStretch(5, 1) self.gridLayout.setColumnStretch(2, 1) self.gridLayout.setRowStretch(5, 1) # # self.gridLayout.addItem(QtWidgets.QSpacerItem(0, 0, # QtWidgets.QSizePolicy.Policy.Expanding, # QtWidgets.QSizePolicy.Policy.Expanding), 0, 0, 1, 1, ) self.default_row_height = 24 self.set_styles() self.indexHeader.setSizePolicy( QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.Maximum ) self.columnHeader.setSizePolicy( QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.MinimumExpanding ) # Set column widths for column_index in range(self.columnHeader.model().columnCount()): self.auto_size_column(column_index) self.columnHeader.horizontalHeader().setStretchLastSection(True) self.columnHeaderNames.horizontalHeader().setStretchLastSection(True) self.columnHeader.horizontalHeader().sectionResized.connect(self.update_horizontal_scroll) self.columnHeader.horizontalHeader().setMinimumSectionSize(1) self.dataView.horizontalHeader().setMinimumSectionSize(1) # self.show() self.auto_size_header() def set_styles(self): for item in [ self.dataView, self.columnHeader, self.indexHeader, self.indexHeaderNames, self.columnHeaderNames, ]: item.setContentsMargins(0, 0, 0, 0) # item.setItemDelegate(NoFocusDelegate()) self.indexHeaderNames.verticalHeader().setDefaultSectionSize(self.default_row_height) self.indexHeaderNames.verticalHeader().setMinimumSectionSize(self.default_row_height) self.indexHeaderNames.verticalHeader().setMaximumSectionSize(self.default_row_height) self.indexHeaderNames.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Fixed) self.indexHeader.verticalHeader().setDefaultSectionSize(self.default_row_height) self.indexHeader.verticalHeader().setMinimumSectionSize(self.default_row_height) self.indexHeader.verticalHeader().setMaximumSectionSize(self.default_row_height) self.indexHeader.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Fixed) self.dataView.verticalHeader().setDefaultSectionSize(self.default_row_height) self.dataView.verticalHeader().setMinimumSectionSize(self.default_row_height) self.dataView.verticalHeader().setMaximumSectionSize(self.default_row_height) self.dataView.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Fixed) self.columnHeader.verticalHeader().setDefaultSectionSize(self.default_row_height) self.columnHeader.verticalHeader().setMinimumSectionSize(self.default_row_height) self.columnHeader.verticalHeader().setMaximumSectionSize(self.default_row_height) self.columnHeader.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Fixed) def __reduce__(self): # This is so dataclasses.asdict doesn't complain about this being unpicklable return "DataFrameViewer" def auto_size_header(self): s = 0 for i in range(self.columnHeader.model().columnCount()): s += self.auto_size_column(i) delta = int((self.dataView.size().width() - s) // len(self.pgdf.df.columns)) if delta > 0: for i in range(self.columnHeader.model().columnCount()): self.auto_size_column(i, extra_padding=delta) self.dataView.horizontalScrollBar().hide() else: self.dataView.horizontalScrollBar().show() def update_horizontal_scroll(self, *args): s = 0 for i in range(self.columnHeader.model().columnCount()): s += self.columnHeader.columnWidth(i) + self.columnHeader.frameWidth() if self.dataView.size().width() < s: self.dataView.horizontalScrollBar().show() else: self.dataView.horizontalScrollBar().hide() def auto_size_column(self, column_index, extra_padding=0): """Set the size of column at column_index to fit its contents.""" width = 0 # Iterate over the data view rows and check the width of each to determine the max width for the column # Only check the first N rows for performance. If there is larger content in cells below it will be cut off N = 40000 // (self.dataView.model().columnCount() or 40000) if N > 100: N = 100 elif N < 5: N = 5 for i in range(self.dataView.model().rowCount())[:N]: mi = self.dataView.model().index(i, column_index) text = self.dataView.model().data(mi) w = self.dataView.fontMetrics().boundingRect(text).width() width = max(width, w) # Repeat for header cells for i in range(self.columnHeader.model().rowCount()): mi = self.columnHeader.model().index(i, column_index) text = self.columnHeader.model().data(mi) text = text[len(self.prefix) :] if text.startswith(self.prefix) else text w = self.columnHeader.fontMetrics().boundingRect(text).width() width = max(width, w) padding = 20 width += padding + extra_padding self.columnHeader.setColumnWidth(column_index, width) self.dataView.setColumnWidth(column_index, width) self.dataView.updateGeometry() self.columnHeader.updateGeometry() return width def auto_size_row(self, row_index): """Set the size of row at row_index to fix its contents.""" height = 24 self.indexHeader.setRowHeight(row_index, height) self.dataView.setRowHeight(row_index, height) self.dataView.updateGeometry() self.indexHeader.updateGeometry() def scroll_to_column(self, column=0): index = self.dataView.model().index(0, column) self.dataView.scrollTo(index) self.columnHeader.selectColumn(column) self.columnHeader.on_selectionChanged(force=True) def keyPressEvent(self, event): QtWidgets.QWidget.keyPressEvent(self, event) mods = event.modifiers() if event.key() == Qt.Key.Key_C and (mods & Qt.KeyboardModifier.ControlModifier): event.accept() self.copy(header=True) elif ( event.key() == Qt.Key.Key_C and (mods & Qt.KeyboardModifier.ShiftModifier) and (mods & Qt.KeyboardModifier.ControlModifier) ): event.accept() self.copy(header=True) else: self.dataView.keyPressEvent(event) @timeit def copy(self, header=False): """Copy the selected cells to clipboard in an Excel-pasteable format.""" # Get the bounds using the top left and bottom right selected cells fmt = self.dataView.model().format # Copy from data, columns, or index depending on which has focus if header or self.dataView.hasFocus(): selection_model = self.dataView.selectionModel() rows = [i for i in range(self.pgdf.df.cached_size[0]) if selection_model.rowIntersectsSelection(i)] cols = [i for i in range(self.pgdf.df.cached_size[1]) if selection_model.columnIntersectsSelection(i)] temp_df = self.pgdf.df df = temp_df.iloc[min(rows) : max(rows) + 1, min(cols) : max(cols) + 1] elif self.indexHeader.hasFocus(): selection_model = self.indexHeader.selectionModel() rows = [i for i in range(self.pgdf.df.cached_size[0]) if selection_model.rowIntersectsSelection(i)] cols = [i for i in range(self.pgdf.df.cached_size[1]) if selection_model.columnIntersectsSelection(i)] temp_df = self.pgdf.df.index.to_frame() df = temp_df.iloc[min(rows) : max(rows) + 1, min(cols) : max(cols) + 1] elif self.columnHeader.hasFocus(): selection_model = self.columnHeader.selectionModel() rows = [i for i in range(self.pgdf.df.cached_size[0]) if selection_model.rowIntersectsSelection(i)] cols = [i for i in range(self.pgdf.df.cached_size[1]) if selection_model.columnIntersectsSelection(i)] # Column header should be horizontal so we transpose temp_df = self.pgdf.df.columns.to_frame().transpose() df = temp_df.iloc[min(rows) : max(rows) + 1, min(cols) : max(cols) + 1] else: return if fmt in ("hex", "bin") and len(df): fmt = "{:X}" if fmt == "hex" else "{:b}" for name in df.columns: col = df[name] if isinstance(col.values[0], np.integer): col = pd.Series([fmt.format(val) for val in col], index=df.index) df[name] = col for name in df.columns: col = df[name] if isinstance(col.values[0], (bytes, np.bytes_)): df[name] = pd.Series(col, dtype=pd.StringDtype()) if self.dataView.model().float_precision != -1: decimals = self.dataView.model().float_precision for name in df.columns: col = df[name] if isinstance(col.values[0], np.floating): col = col.round(decimals) df[name] = col float_format = f"%.{decimals}f" else: float_format = "%.16f" # If I try to use df.to_clipboard without starting new thread, large selections give access denied error if df.shape == (1, 1): # Special case for single-cell copy, excel=False removes the trailing \n character. df.to_clipboard( index=False, header=False, excel=False, float_format=float_format, ) else: df.to_clipboard( index=header, header=header, float_format=float_format, ) def show_column_menu(self, column_ix_or_name): if isinstance(self.pgdf.df.columns, pd.MultiIndex): logger.info("Column menu not implemented for MultiIndex") return if isinstance(column_ix_or_name, str): column_ix = list(self.pgdf.df.columns).index(column_ix_or_name) else: column_ix = column_ix_or_name point = QtCore.QPoint( self.columnHeader.columnViewportPosition(column_ix) + self.columnHeader.columnWidth(column_ix) - 15, self.columnHeader.geometry().bottom() - 6, ) menu = ColumnMenu(self.pgdf, column_ix, self) menu.show_menu(self.columnHeader.mapToGlobal(point)) def _remove_column(self, ix): for model in [self.dataView.model(), self.columnHeader.model()]: parent = QtCore.QModelIndex() model.beginRemoveColumns(parent, ix, ix) model.endRemoveColumns() def _move_column(self, ix, new_ix, refresh=True): for view in [self.dataView, self.columnHeader]: model = view.model() column_widths = [view.columnWidth(ix) for ix in range(model.columnCount())] column_widths.insert(new_ix, column_widths.pop(ix)) # Set width of destination column to the width of the source column for j in range(len(column_widths)): view.setColumnWidth(j, column_widths[j]) if refresh: self.refresh_ui() def resizeEvent(self, event): super().resizeEvent(event) self.update_horizontal_scroll() def refresh_ui(self): self.models = [ self.dataView.model(), self.columnHeader.model(), self.indexHeader.model(), self.columnHeaderNames.model(), self.indexHeaderNames.model(), ] for model in self.models: model.beginResetModel() model.endResetModel() # Update sizing for view in [self.columnHeader, self.indexHeader, self.dataView]: view.updateGeometry() asammdf-8.5.1/src/asammdf/gui/widgets/tabular_filter.py000066400000000000000000000147501502633300400231420ustar00rootroot00000000000000import pandas as pd from PySide6 import QtCore, QtWidgets from ..dialogs.messagebox import MessageBox from ..ui.tabular_filter import Ui_TabularFilter class TabularFilter(Ui_TabularFilter, QtWidgets.QWidget): def __init__(self, signals, int_format, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) self._target = None self.names = [item[0] for item in signals] self.dtype_kind = [item[1] for item in signals] self.is_bytearray = [item[2] for item in signals] self.int_format = int_format self.relation.addItems(["AND", "OR"]) self.column.addItems(self.names) self.op.addItems([">", ">=", "<", "<=", "==", "!="]) self.target.editingFinished.connect(self.validate_target) self.column.currentIndexChanged.connect(self.column_changed) def column_changed(self, index): self.target.setText("") self._target = None def validate_target(self): idx = self.column.currentIndex() column_name = self.column.currentText() kind = self.dtype_kind[idx] target = self.target.text().strip() if target: if kind in "ui": if target.startswith("0x"): try: self._target = int(target, 16) except: MessageBox.warning( None, "Wrong target value", f"{column_name} requires an integer target value", ) elif target.startswith("0b"): try: self._target = int(target, 2) except: MessageBox.warning( None, "Wrong target value", f"{column_name} requires an integer target value", ) else: match self.int_format: case "hex": try: self._target = int(target, 16) self.target.setText(f"0x{self._target:X}") except: MessageBox.warning( None, "Wrong target value", f"{column_name} requires a hex-format integer target value", ) case "bin": try: self._target = int(target, 2) self.target.setText(f"0b{self._target:b}") except: MessageBox.warning( None, "Wrong target value", f"{column_name} requires a bin-format integer target value", ) case "ascii": try: self._target = ord(target) self.target.setText(target) except: MessageBox.warning( None, "Wrong target value", f"{column_name} requires a hex-format integer target value", ) case _: try: self._target = int(target) except: try: self._target = int(target, 16) self.target.setText(f"0x{self._target:X}") except: MessageBox.warning( None, "Wrong target value", f"{column_name} requires an integer target value", ) elif kind == "f": try: self._target = float(target) except: MessageBox.warning( None, "Wrong target value", f"{column_name} requires a float target value", ) elif kind == "O": is_bytearray = self.is_bytearray[idx] if is_bytearray: try: bytes.fromhex(target.replace(" ", "")) except: MessageBox.warning( None, "Wrong target value", f"{column_name} requires a correct hexstring", ) else: target = target.strip().replace(" ", "") target = [target[i : i + 2] for i in range(0, len(target), 2)] target = " ".join(target).upper() if self._target is None: self._target = f'"{target}"' self.target.setText(target) elif self._target.strip('"') != target: self._target = f'"{target}"' self.target.setText(target) else: self._target = f'"{target}"' elif kind == "S": self._target = f'b"{target}"' elif kind == "U": self._target = f'"{target}"' elif kind == "M": try: pd.Timestamp(target) except: MessageBox.warning( None, "Wrong target value", f"Datetime {column_name} requires a correct pandas Timestamp literal", ) else: self._target = target def to_config(self): info = { "enabled": self.enabled.checkState() == QtCore.Qt.CheckState.Checked, "relation": self.relation.currentText(), "column": self.column.currentText(), "op": self.op.currentText(), "target": str(self._target), } return info asammdf-8.5.1/src/asammdf/gui/widgets/tree.py000066400000000000000000003105231502633300400210770ustar00rootroot00000000000000from datetime import datetime from enum import IntFlag from functools import lru_cache import json import os import re from traceback import format_exc import numpy as np from pyqtgraph import functions as fn from PySide6 import QtCore, QtGui, QtWidgets from ...blocks.conversion_utils import conversion_transfer, from_dict, to_dict from ...signal import Signal from .. import utils from ..dialogs.advanced_search import AdvancedSearch from ..dialogs.conversion_editor import ConversionEditor from ..dialogs.messagebox import MessageBox from ..dialogs.range_editor import RangeEditor from ..serde import ExtendedJsonDecoder, ExtendedJsonEncoder, extract_mime_names from ..utils import ( copy_ranges, get_color_using_ranges, get_colors_using_ranges, SCROLLBAR_STYLE, unique_ranges, value_as_str, ) from .tree_item import MinimalTreeItem NOT_FOUND = 0xFFFFFFFF MINIMUM_COLUMN_WIDTH = 20 def substitude_mime_uuids(mime, uuid=None, force=False, random_uuid=False): if not mime: return mime new_mime = [] for item in mime: if item["type"] == "channel": if force or item["origin_uuid"] is None: item["origin_uuid"] = uuid new_mime.append(item) else: item["channels"] = substitude_mime_uuids(item["channels"], uuid, force=force, random_uuid=random_uuid) if force or item["origin_uuid"] is None: item["origin_uuid"] = uuid new_mime.append(item) if random_uuid: item["uuid"] = os.urandom(6).hex() return new_mime def add_children( widget, channels, channel_dependencies, signals, entries=None, origin_uuid=None, version="4.11", ): children = [] if entries is not None: channels_ = [channels[i] for _, i in entries] else: channels_ = channels for ch in channels_: if ch.added: continue entry = ch.entry child = MinimalTreeItem(entry, ch.name, strings=[ch.name], origin_uuid=origin_uuid) dep = channel_dependencies[entry[1]] if version >= "4.00": if dep and isinstance(dep[0], tuple): child.setFlags( child.flags() | QtCore.Qt.ItemFlag.ItemIsAutoTristate | QtCore.Qt.ItemFlag.ItemIsUserCheckable ) add_children( child, channels, channel_dependencies, signals, dep, origin_uuid=origin_uuid, ) if entry in signals: child.setCheckState(0, QtCore.Qt.CheckState.Checked) else: child.setCheckState(0, QtCore.Qt.CheckState.Unchecked) ch.added = True children.append(child) widget.addChildren(children) def add_new_items(tree, root, items, pos): for item in items: new_item = item.copy() new_widget = tree.itemWidget(item, 1).copy() new_item.widget = new_widget new_widget.item = new_item if pos is None: root.addChild(new_item) else: root.insertChild(pos, new_item) pos += 1 tree.setItemWidget(new_item, 1, new_widget) if item.type() == ChannelsTreeItem.Group: child_items = [item.child(i) for i in range(item.childCount())] add_new_items(tree, new_item, child_items, None) def valid_drop_target(target, item): if target is None: return True while target.parent(): if target.parent() is item: return False target = target.parent() return True def validate_drag_items(root, items, not_allowed): valid_items = [] for item in items: if item.type() == ChannelsTreeItem.Info: continue idx = root.indexOfChild(item) if idx >= 0: parents = [] parent = item.parent() while parent: parents.append(parent) parent = parent.parent() for parent in parents: if parent in not_allowed: break elif parent and parent.type() == ChannelsTreeItem.Group: if parent.pattern: not_allowed.append(parent) break else: not_allowed.append(item) valid_items.append(item) for item in valid_items: pos = items.index(item) items.pop(pos) for i in range(root.childCount()): child = root.child(i) if child.childCount(): valid_items.extend(validate_drag_items(child, items, not_allowed)) return valid_items def get_data(plot, items, uuids_only=False): data = [] for item in items: if item.type() == ChannelsTreeItem.Group: children = [item.child(i) for i in range(item.childCount())] if uuids_only: data.extend(get_data(plot, children, uuids_only)) else: group = plot.channel_group_item_to_config(item) group["uuid"] = os.urandom(6).hex() group["channels"] = get_data(plot, children, uuids_only) data.append(group) elif item.type() == ChannelsTreeItem.Channel: if uuids_only: data.append(item.uuid) else: channel = plot.channel_item_to_config(item) channel["uuid"] = os.urandom(6).hex() channel["group_index"], channel["channel_index"] = item.entry data.append(channel) return data class TreeWidget(QtWidgets.QTreeWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setSortingEnabled(False) self.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.DragOnly) self.setUniformRowHeights(True) self.mode = "Natural sort" def keyPressEvent(self, event): key = event.key() if key == QtCore.Qt.Key.Key_Space: event.accept() selected_items = self.selectedItems() if not selected_items: return elif len(selected_items) == 1: item = selected_items[0] checked = item.checkState(0) if checked == QtCore.Qt.CheckState.Checked: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) else: item.setCheckState(0, QtCore.Qt.CheckState.Checked) else: if any(item.checkState(0) == QtCore.Qt.CheckState.Unchecked for item in selected_items): checked = QtCore.Qt.CheckState.Checked else: checked = QtCore.Qt.CheckState.Unchecked for item in selected_items: item.setCheckState(0, checked) else: super().keyPressEvent(event) def startDrag(self, supportedActions): def get_data(item): data = [] count = item.childCount() if count: for i in range(count): child = item.child(i) if child.childCount(): data.extend(get_data(child)) else: if child.entry[1] != 0xFFFFFFFFFFFFFFFF: data.append( { "name": child.name, "group_index": child.entry[0], "channel_index": child.entry[1], "type": "channel", "ranges": [], "uuid": os.urandom(6).hex(), "origin_uuid": child.origin_uuid, "computed": False, "computation": None, } ) else: if item.entry[1] != 0xFFFFFFFFFFFFFFFF: data.append( { "name": item.name, "group_index": item.entry[0], "channel_index": item.entry[1], "type": "channel", "ranges": [], "uuid": os.urandom(6).hex(), "origin_uuid": item.origin_uuid, "computed": False, "computation": None, } ) return data selected_items = self.selectedItems() mimeData = QtCore.QMimeData() data = [] for item in selected_items: data.extend(get_data(item)) data = json.dumps(sorted(data, key=lambda x: (x["name"], x["group_index"], x["channel_index"]))).encode("utf-8") mimeData.setData("application/octet-stream-asammdf", QtCore.QByteArray(data)) drag = QtGui.QDrag(self) drag.setMimeData(mimeData) drag.exec(QtCore.Qt.DropAction.MoveAction) class FileTreeItem(QtWidgets.QTreeWidgetItem): def __init__(self, path, start_time, parent=None): if isinstance(start_time, datetime): start_time = start_time.isoformat() super().__init__(parent, [path, start_time]) def __lt__(self, otherItem): column = self.treeWidget().sortColumn() if column == 1: val1 = datetime.fromisoformat(self.text(column)) val2 = datetime.fromisoformat(otherItem.text(column)) return val1 < val2 else: return self.text(column) < otherItem.text(column) def __del__(self): self.entry = self.name = self.origin_uuid = None class FileTreeWidget(QtWidgets.QTreeWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove) self.setUniformRowHeights(True) self.mode = "Natural sort" class Delegate(QtWidgets.QItemDelegate): def __init__(self, *args): super().__init__(*args) def paint(self, painter, option, index): model = index.model() item = self.parent().itemFromIndex(index) if item.type() == item.Channel: brush = model.data(index, QtCore.Qt.ItemDataRole.ForegroundRole) if brush is not None: color = brush.color() complementary = fn.mkColor("#000000") if complementary == color: complementary = fn.mkColor("#FFFFFF") option.palette.setColor(QtGui.QPalette.ColorRole.Highlight, color) option.palette.setColor(QtGui.QPalette.ColorRole.HighlightedText, complementary) super().paint(painter, option, index) class ChannelsTreeFlags(IntFlag): DetailsEnabled = 1 HideMissingChannels = 1 << 1 HideDisabledChannels = 1 << 2 CanDeleteItems = 1 << 3 CanInsertItems = 1 << 4 class ChannelsTreeWidget(QtWidgets.QTreeWidget): itemsDeleted = QtCore.Signal(list) set_time_offset = QtCore.Signal(list) add_channels_request = QtCore.Signal(list) show_properties = QtCore.Signal(str, str) show_overlapping_alias = QtCore.Signal(str, str) insert_computation = QtCore.Signal(str) edit_computation = QtCore.Signal(object) pattern_group_added = QtCore.Signal(object) compute_fft_request = QtCore.Signal(str) conversion_changed = QtCore.Signal(str, object) color_changed = QtCore.Signal(str, object) unit_changed = QtCore.Signal(str, str) name_changed = QtCore.Signal(str, str) visible_items_changed = QtCore.Signal() group_activation_changed = QtCore.Signal() double_click = QtCore.Signal(object, object) NameColumn = 0 RawColumn = 1 ValueColumn = 2 UnitColumn = 3 CommonAxisColumn = 4 IndividualAxisColumn = 5 OriginColumn = 6 def __init__( self, hide_missing_channels=False, hide_disabled_channels=False, plot=None, *args, **kwargs, ): super().__init__(*args, **kwargs) self.plot = plot self.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove) self.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection) self.setUniformRowHeights(True) self.details_enabled = False self.hide_missing_channels = hide_missing_channels or False self.hide_disabled_channels = hide_disabled_channels or False self.filter_computed_channels = False self.can_delete_items = True self.setHeaderHidden(False) self.setColumnCount(7) self.setHeaderLabels(["Name", "Raw", "Value", "Unit", "\u290a", "\u21a8", "Origin"]) self.setDragEnabled(True) self.setExpandsOnDoubleClick(False) self.setMinimumWidth(5) header = self.header() header.setMinimumSectionSize(MINIMUM_COLUMN_WIDTH) header.resizeSection(self.CommonAxisColumn, MINIMUM_COLUMN_WIDTH) header.resizeSection(self.IndividualAxisColumn, MINIMUM_COLUMN_WIDTH) header.setSectionResizeMode(self.CommonAxisColumn, QtWidgets.QHeaderView.ResizeMode.Fixed) header.setSectionResizeMode(self.IndividualAxisColumn, QtWidgets.QHeaderView.ResizeMode.Fixed) header.setStretchLastSection(False) header.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) header.customContextMenuRequested.connect(self.open_menu) self.itemSelectionChanged.connect(self.item_selection_changed) self.itemCollapsed.connect(self.update_visibility_status) self.itemExpanded.connect(self.update_visibility_status) self.verticalScrollBar().valueChanged.connect(self.update_visibility_status) self.autoscroll_timer = QtCore.QTimer() self.autoscroll_timer.timeout.connect(self.autoscroll) self.autoscroll_timer.setInterval(33) self.context_menu_timer = QtCore.QTimer() self.context_menu_timer.timeout.connect(self.open_menu) self.context_menu_timer.setSingleShot(True) self.context_menu_pos = None self.context_menu = None self.autoscroll_mouse_pos = None self.drop_target = None self.idel = Delegate(self) self.setItemDelegate(self.idel) self.setColumnHidden(self.OriginColumn, True) self.setColumnHidden(self.RawColumn, True) self.disabled_keyboard_events = set() self.set_style() def autoscroll(self): step = max( (self.verticalScrollBar().maximum() - self.verticalScrollBar().minimum()) // 90, 1, ) if self.autoscroll_mouse_pos is not None: height = self.viewport().rect().height() y = self.autoscroll_mouse_pos if y <= 15: pos = max(self.verticalScrollBar().value() - step, 0) self.verticalScrollBar().setValue(pos) elif y >= height - 15: pos = min( self.verticalScrollBar().value() + step, self.verticalScrollBar().maximum(), ) self.verticalScrollBar().setValue(pos) def startDrag(self, supportedActions): selected_items = validate_drag_items(self.invisibleRootItem(), self.selectedItems(), []) mimeData = QtCore.QMimeData() data = get_data(self.plot, selected_items, uuids_only=False) data = json.dumps(data, cls=ExtendedJsonEncoder).encode("utf-8") mimeData.setData("application/octet-stream-asammdf", QtCore.QByteArray(data)) drag = QtGui.QDrag(self) drag.setMimeData(mimeData) drag.exec(QtCore.Qt.DropAction.MoveAction) def dragEnterEvent(self, e): self.autoscroll_timer.start() self.autoscroll_mouse_pos = e.answerRect().y() e.accept() def dragLeaveEvent(self, e): self.autoscroll_timer.stop() self.autoscroll_mouse_pos = None e.accept() def dragMoveEvent(self, e): self.autoscroll_mouse_pos = e.answerRect().y() e.accept() def dropEvent(self, e): self.autoscroll_timer.stop() self.autoscroll_mouse_pos = None self.drop_target = None if e.source() is self: item = self.itemAt(6, 6) self.blockSignals(True) super().dropEvent(e) self.blockSignals(False) self.scrollToItem(item) else: data = e.mimeData() if data.hasFormat("application/octet-stream-asammdf"): names = extract_mime_names(data) item = self.itemAt(e.pos()) if item and item.type() == item.Info: item = item.parent() self.drop_target = item self.add_channels_request.emit(names) e.accept() else: e.ignore() self.refresh() self.update_channel_groups_count() def header_columns_visibility(self): visibility = {} for name in ( "NameColumn", "RawColumn", "ValueColumn", "UnitColumn", "CommonAxisColumn", "IndividualAxisColumn", "OriginColumn", ): col = getattr(self, name) visibility[name] = not self.isColumnHidden(col) return visibility def header_sizes(self): sizes = {} for name in ( "NameColumn", "RawColumn", "ValueColumn", "UnitColumn", "CommonAxisColumn", "IndividualAxisColumn", "OriginColumn", ): col = getattr(self, name) sizes[name] = self.columnWidth(col) return sizes def is_item_visible(self, item): return item._is_visible def item_selection_changed(self): selection = list(self.selectedItems()) iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): widget = self.itemWidget(item, 1) if widget: if item in selection: widget.set_selected(True) selection.remove(item) else: widget.set_selected(False) iterator += 1 def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if event.keyCombination().toCombined() in self.disabled_keyboard_events: event.ignore() return if key == QtCore.Qt.Key.Key_Delete and self.can_delete_items: event.accept() selected_items = self.selectedItems() deleted = list(set(get_data(self.plot, selected_items, uuids_only=True))) self.setUpdatesEnabled(False) self.clearSelection() root = self.invisibleRootItem() for item in selected_items: (item.parent() or root).removeChild(item) self.setUpdatesEnabled(True) self.refresh() if deleted: self.itemsDeleted.emit(deleted) self.update_channel_groups_count() elif key == QtCore.Qt.Key.Key_Insert and modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: event.accept() if hasattr(self.plot.owner, "mdf"): mdf = self.plot.owner.mdf channels_db = None else: mdf = None channels_db = self.plot.owner.channels_db dlg = AdvancedSearch( mdf=mdf, show_add_window=False, show_apply=True, show_search=False, show_pattern=True, window_title="Add pattern based group", parent=self, channels_db=channels_db, ) dlg.setModal(True) dlg.exec_() pattern = dlg.result if pattern: group = ChannelsTreeItem(ChannelsTreeItem.Group, name=pattern["name"], pattern=pattern) item = self.currentItem() if item is None: self.addTopLevelItem(group) else: parent = item.parent() if parent: current_parent = parent can_add_child = True while current_parent: if current_parent.type() == ChannelsTreeItem.Group: if current_parent.pattern: can_add_child = False break current_parent = current_parent.parent() if can_add_child: index = parent.indexOfChild(item) parent.insertChild(index, group) else: self.addTopLevelItem(group) else: index = self.indexOfTopLevelItem(item) self.insertTopLevelItem(index, group) self.pattern_group_added.emit(group) self.refresh() self.update_channel_groups_count() elif key == QtCore.Qt.Key.Key_Insert and modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier: event.accept() text, ok = QtWidgets.QInputDialog.getText(self, "Channel group name", "New channel group name:") if ok: group = ChannelsTreeItem(ChannelsTreeItem.Group, name=text) item = self.currentItem() if item is None: self.addTopLevelItem(group) else: parent = item.parent() if parent: index = parent.indexOfChild(item) parent.insertChild(index, group) else: index = self.indexOfTopLevelItem(item) self.insertTopLevelItem(index, group) self.refresh() self.update_channel_groups_count() elif key == QtCore.Qt.Key.Key_Space: event.accept() selected_items = self.selectedItems() if not selected_items: return elif len(selected_items) == 1: item = selected_items[0] checked = item.checkState(self.NameColumn) if checked == QtCore.Qt.CheckState.Checked: item.setCheckState(self.NameColumn, QtCore.Qt.CheckState.Unchecked) if self.hide_disabled_channels: item.setHidden(True) else: item.setCheckState(self.NameColumn, QtCore.Qt.CheckState.Checked) else: if any(item.checkState(self.NameColumn) == QtCore.Qt.CheckState.Unchecked for item in selected_items): checked = QtCore.Qt.CheckState.Checked else: checked = QtCore.Qt.CheckState.Unchecked for item in selected_items: item.setCheckState(self.NameColumn, checked) if self.hide_disabled_channels and checked == QtCore.Qt.CheckState.Unchecked: item.setHidden(True) elif modifiers == QtCore.Qt.KeyboardModifier.NoModifier and key == QtCore.Qt.Key.Key_C: event.accept() selected_items = self.selectedItems() if not selected_items: return else: for item in selected_items: if item.type() == item.Channel: color = item.color break else: color = QtGui.QColor("#ffffff") color = QtWidgets.QColorDialog.getColor(color, parent=self) if color.isValid(): for item in selected_items: if item.type() != item.Info: item.color = color elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_X: event.accept() selected_items = validate_drag_items(self.invisibleRootItem(), self.selectedItems(), []) data = get_data(self.plot, selected_items, uuids_only=False) data = substitude_mime_uuids(data, None, force=True) QtWidgets.QApplication.instance().clipboard().setText(json.dumps(data, cls=ExtendedJsonEncoder)) if self.can_delete_items: deleted = list(set(get_data(self.plot, selected_items, uuids_only=True))) self.setUpdatesEnabled(False) self.clearSelection() root = self.invisibleRootItem() for item in selected_items: (item.parent() or root).removeChild(item) self.setUpdatesEnabled(True) self.refresh() if deleted: self.itemsDeleted.emit(deleted) self.update_channel_groups_count() elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_C: event.accept() selected_items = validate_drag_items(self.invisibleRootItem(), self.selectedItems(), []) data = get_data(self.plot, selected_items, uuids_only=False) data = substitude_mime_uuids(data, None, force=True) QtWidgets.QApplication.instance().clipboard().setText(json.dumps(data, cls=ExtendedJsonEncoder)) elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_V: event.accept() try: data = QtWidgets.QApplication.instance().clipboard().text() data = json.loads(data, cls=ExtendedJsonDecoder) data = substitude_mime_uuids(data, random_uuid=True) self.add_channels_request.emit(data) except: pass elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_N: event.accept() selected_items = self.selectedItems() if not selected_items: return else: text = "\n".join(item.name for item in selected_items) QtWidgets.QApplication.instance().clipboard().setText(text) elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier and key == QtCore.Qt.Key.Key_R: event.accept() selected_items = self.selectedItems() if not selected_items: return if len(selected_items) == 1: item = selected_items[0] type = item.type() if type == ChannelsTreeItem.Group: dlg = RangeEditor(f"channels from <{item._name}>", ranges=item.ranges, parent=self) dlg.exec_() if dlg.pressed_button == "apply": item.set_ranges(dlg.result) item.update_child_values() elif type == ChannelsTreeItem.Channel: dlg = RangeEditor(item.signal.name, item.unit, item.ranges, parent=self) dlg.exec_() if dlg.pressed_button == "apply": item.set_ranges(dlg.result) item.set_value(item._raw_value, item._value, update=True) else: ranges = [] for item in selected_items: ranges.extend(item.ranges) dlg = RangeEditor("", ranges=unique_ranges(ranges), parent=self) dlg.exec_() if dlg.pressed_button == "apply": for item in selected_items: if item.type() == item.Channel: item.set_ranges(copy_ranges(dlg.result)) item.set_value(item._raw_value, item._value, update=True) elif item.type() == item.Group: item.set_ranges(copy_ranges(dlg.result)) item.update_child_values() self.refresh() self.plot.plot.update() elif ( modifiers == (QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier) and key == QtCore.Qt.Key.Key_C ): event.accept() selected_items = [ item for item in self.selectedItems() if item.type() in (ChannelsTreeItem.Channel, ChannelsTreeItem.Group) ] if selected_items: item = selected_items[0] clipboard_text = item.get_display_properties() QtWidgets.QApplication.instance().clipboard().setText(clipboard_text) elif ( modifiers == (QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier) and key == QtCore.Qt.Key.Key_V ): event.accept() info = QtWidgets.QApplication.instance().clipboard().text() selected_items = self.selectedItems() if not selected_items: return try: info = json.loads(info, cls=ExtendedJsonDecoder) except: return plot = self.plot.plot if info["type"] == "channel": info["color"] = fn.mkColor(info["color"]) for item in selected_items: item.color = info["color"] item.precision = info["precision"] item.format = info["format"] item.setCheckState( self.IndividualAxisColumn, QtCore.Qt.CheckState.Checked if info["individual_axis"] else QtCore.Qt.CheckState.Unchecked, ) item.setCheckState( self.CommonAxisColumn, QtCore.Qt.CheckState.Checked if info["ylink"] else QtCore.Qt.CheckState.Unchecked, ) if item.type() == ChannelsTreeItem.Channel: sig, index = plot.signal_by_uuid(item.uuid) sig.y_range = info["y_range"] if plot.current_uuid == sig.uuid: plot.viewbox.setYRange(*sig.y_range, padding=0) item.set_ranges(info["ranges"]) if "conversion" in info and not item.signal.flags & Signal.Flags.computed: item.set_conversion(from_dict(info["conversion"])) elif item.type() == ChannelsTreeItem.Group: item.set_ranges(info["ranges"]) elif info["type"] == "group": for item in selected_items: if item.type() in (ChannelsTreeItem.Channel, ChannelsTreeItem.Group): item.set_ranges(info["ranges"]) plot.update() elif modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier and key in ( QtCore.Qt.Key.Key_Up, QtCore.Qt.Key.Key_Down, QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right, QtCore.Qt.Key.Key_I, QtCore.Qt.Key.Key_O, ): event.ignore() else: super().keyPressEvent(event) def mousePressEvent(self, event) -> None: if event.button() == QtCore.Qt.MouseButton.RightButton: self.context_menu_timer.start(300) self.context_menu_pos = event.position().toPoint() if self.context_menu is not None: self.context_menu.close() self.context_menu = None # If there was a click performed on disabled item, then clear selection position = event.position() item = self.itemAt(position.x(), position.y()) if item and item.isDisabled(): self.clearSelection() super().mousePressEvent(event) def mouseDoubleClickEvent(self, event): if event.button() == QtCore.Qt.MouseButton.RightButton: self.context_menu_timer.stop() self.context_menu_pos = None position = event.position() self.double_click.emit(self.itemAt(position.x(), position.y()), event.button()) def open_menu(self, position=None): position = position or self.context_menu_pos if position: item = self.itemAt(position) else: item = None count = 0 enabled = 0 iterator = QtWidgets.QTreeWidgetItemIterator(self) while cur_item := iterator.value(): if cur_item.type() == ChannelsTreeItem.Channel: count += 1 if cur_item.checkState(self.NameColumn) == QtCore.Qt.CheckState.Checked: enabled += 1 iterator += 1 self.context_menu = menu = QtWidgets.QMenu() menu.addAction(f"{count} items in the list, {enabled} enabled") menu.addSeparator() submenu = QtWidgets.QMenu("Columns") action = QtGui.QAction("Raw Column", submenu) action.setCheckable(True) action.setChecked(not self.isColumnHidden(self.RawColumn)) submenu.addAction(action) action = QtGui.QAction("Unit Column", submenu) action.setCheckable(True) action.setChecked(not self.isColumnHidden(self.UnitColumn)) submenu.addAction(action) action = QtGui.QAction("Common Axis Column", submenu) action.setCheckable(True) action.setChecked(not self.isColumnHidden(self.CommonAxisColumn)) submenu.addAction(action) action = QtGui.QAction("Individual Axis Column", submenu) action.setCheckable(True) action.setChecked(not self.isColumnHidden(self.IndividualAxisColumn)) submenu.addAction(action) action = QtGui.QAction("Origin Column", submenu) action.setCheckable(True) action.setChecked(not self.isColumnHidden(self.OriginColumn)) submenu.addAction(action) menu.addMenu(submenu) menu.addSeparator() menu.addAction(QtGui.QIcon(":/search.png"), "Search item") if item and item.type() in (ChannelsTreeItem.Channel, ChannelsTreeItem.Group): menu.addAction(QtGui.QIcon(":/down.png"), f"Find next {item.name}") menu.addSeparator() action = QtGui.QAction("Add channel group", menu) action.setShortcut(QtGui.QKeySequence("Shift+Insert")) menu.addAction(action) action = QtGui.QAction("Add pattern based channel group", menu) action.setShortcut(QtGui.QKeySequence("Ctrl+Insert")) menu.addAction(action) menu.addSeparator() action = QtGui.QAction("Insert computation", menu) action.setShortcut(QtGui.QKeySequence("Insert")) menu.addAction(action) menu.addSeparator() submenu = QtWidgets.QMenu("Copy names") submenu.setIcon(QtGui.QIcon(":/copy.png")) action = QtGui.QAction("Copy names", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+N")) submenu.addAction(action) submenu.addAction("Copy names and values") menu.addMenu(submenu) submenu = QtWidgets.QMenu("Display structure") submenu.setIcon(QtGui.QIcon(":/structure.png")) action = QtGui.QAction("Copy display properties", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+Shift+C")) submenu.addAction(action) action = QtGui.QAction("Paste display properties", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+Shift+V")) submenu.addAction(action) action = QtGui.QAction("Copy channel structure", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+C")) submenu.addAction(action) action = QtGui.QAction("Paste channel structure", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+V")) submenu.addAction(action) menu.addMenu(submenu) submenu = QtWidgets.QMenu("Enable/disable") if item and item.type() == item.Group and item.isDisabled(): submenu.addAction("Activate group") submenu.addAction("Deactivate groups") submenu.addAction("Enable all") submenu.addAction("Disable all") submenu.addAction("Enable selected") submenu.addAction("Disable selected") if item: submenu.addAction("Disable all but this") menu.addMenu(submenu) submenu = QtWidgets.QMenu("Show/hide") action = QtGui.QAction("Hide disabled items", submenu) action.setCheckable(True) action.setChecked(self.hide_disabled_channels) submenu.addAction(action) action = QtGui.QAction("Hide missing items", submenu) action.setCheckable(True) action.setChecked(self.hide_missing_channels) submenu.addAction(action) action = QtGui.QAction("Filter only computed channels", submenu) action.setCheckable(True) action.setChecked(self.filter_computed_channels) submenu.addAction(action) menu.addMenu(submenu) menu.addSeparator() submenu = QtWidgets.QMenu("Axis") action = QtGui.QAction("Edit Y axis scaling", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+G")) submenu.addAction(action) if item and item.type() == ChannelsTreeItem.Channel: submenu.addAction("Add to common Y axis") submenu.addAction("Remove from common Y axis") menu.addMenu(submenu) menu.addSeparator() submenu = QtWidgets.QMenu("Edit") submenu.setIcon(QtGui.QIcon(":/edit.png")) action = QtGui.QAction("Set color", submenu) action.setShortcut(QtGui.QKeySequence("C")) submenu.addAction(action) submenu.addAction("Set random color") submenu.addAction("Set precision") action = QtGui.QAction("Set color ranges", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+R")) submenu.addAction(action) submenu.addAction("Set channel conversion") submenu.addAction("Set channel comment") submenu.addAction("Set unit") if item: if item.type() == ChannelsTreeItem.Channel: if item.signal.flags & Signal.Flags.computed: submenu.addAction("Edit this computed channel") else: submenu.addAction("Rename channel") elif item.type() == ChannelsTreeItem.Group: submenu.addAction("Edit group") menu.addMenu(submenu) submenu = QtWidgets.QMenu("Display mode") # submenu.setIcon(QtGui.QIcon(":/edit.png")) action = QtGui.QAction("Ascii", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+T")) submenu.addAction(action) action = QtGui.QAction("Bin", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+B")) submenu.addAction(action) action = QtGui.QAction("Hex", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+H")) submenu.addAction(action) action = QtGui.QAction("Physical", submenu) action.setShortcut(QtGui.QKeySequence("Ctrl+P")) submenu.addAction(action) submenu.addSeparator() action = QtGui.QAction("Raw samples", submenu) action.setShortcut(QtGui.QKeySequence("Alt+R")) submenu.addAction(action) action = QtGui.QAction("Scaled samples", submenu) action.setShortcut(QtGui.QKeySequence("Alt+S")) submenu.addAction(action) menu.addMenu(submenu) menu.addSeparator() if item and item.type() == ChannelsTreeItem.Channel: menu.addSeparator() submenu = QtWidgets.QMenu("Time shift") submenu.addAction("Relative time base shift") submenu.addAction("Set time base start offset") # try: # import scipy # # menu.addAction("Compute FFT")) # except ImportError: # pass menu.addMenu(submenu) menu.addSeparator() if item: action = QtGui.QAction("Delete", menu) action.setShortcut(QtGui.QKeySequence("Delete")) menu.addAction(action) menu.addSeparator() menu.addAction("Toggle details") if item and item.type() == ChannelsTreeItem.Channel and item.exists: menu.addAction("File/Computation properties") menu.addAction("Show overlapping alias") elif item and item.type() == ChannelsTreeItem.Group: menu.addAction("Group properties") action = menu.exec(self.viewport().mapToGlobal(position)) if action is None: return action_text = action.text() if action_text == "Copy names": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_N, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) elif action_text == "Copy names and values": texts = [] t = self.plot.cursor_info.text() if t.startswith(""): start = t.index("

") + 3 stop = t.index("

") t = t[start:stop] for item in self.selectedItems(): texts.append( ", ".join( [ item.text(item.NameColumn), t, f"{item.text(item.ValueColumn)}{item.text(item.UnitColumn)}", ] ) ) QtWidgets.QApplication.instance().clipboard().setText("\n".join(texts)) elif action_text == "Activate group": # Selected Items will not be retrieved if there are disabled. # So Activating multiple groups will not be possible. # for item in self.selectedItems(): if item.type() == item.Group and item.isDisabled(): item.set_disabled(False) self.group_activation_changed.emit() elif action_text == "Deactivate groups": selectedItems = self.selectedItems() selectedItems.append(item) for item in selectedItems: if item.type() == item.Group and not item.isDisabled(): item.set_disabled(True) self.group_activation_changed.emit() elif action_text == "Set color": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.NoModifier, ) self.keyPressEvent(event) elif action_text == "Set random color": for item in self.selectedItems(): if item.type() == ChannelsTreeItem.Channel: while True: rgb = os.urandom(3) if 100 <= sum(rgb) <= 650: break item.color = f"#{rgb.hex()}" elif action_text == "Set color ranges": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_R, QtCore.Qt.KeyboardModifier.ControlModifier, ) self.keyPressEvent(event) elif action_text == "Set channel conversion": selected_items = self.selectedItems() if not selected_items: return if len(selected_items) == 1: item = selected_items[0] if item.type() == ChannelsTreeItem.Channel: conversion = item.signal.conversion channel_name = item.name try: if hasattr(self.plot.owner, "mdf"): mdf = self.plot.owner.mdf original_conversion = ( mdf.groups[item.signal.group_index].channels[item.signal.channel_index].conversion ) else: original_conversion = self.plot.owner.original_conversion(item.signal) except: print(format_exc()) original_conversion = None else: conversion = original_conversion = None channel_name = item.name else: conversion = original_conversion = None channel_name = "selected items" conversion = conversion_transfer(conversion, version=4) original_conversion = conversion_transfer(original_conversion, version=4) dlg = ConversionEditor(channel_name, conversion, original_conversion=original_conversion, parent=self) dlg.exec_() if dlg.pressed_button == "apply": conversion = dlg.conversion() for item in selected_items: if item.type() in ( ChannelsTreeItem.Channel, ChannelsTreeItem.Group, ): item.set_conversion(conversion) elif action_text == "Set channel comment": selected_items = self.selectedItems() if not selected_items: return for item in selected_items: if item.type() == ChannelsTreeItem.Channel: comment = item.comment new_comment, ok = QtWidgets.QInputDialog.getMultiLineText( self, "Input new comment", "New comment:", comment, ) if ok: for item in selected_items: item.comment = new_comment elif action_text == "Copy channel structure": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier, ) self.keyPressEvent(event) elif action_text == "Paste channel structure": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_V, QtCore.Qt.KeyboardModifier.ControlModifier, ) self.keyPressEvent(event) elif action_text == "Copy display properties": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_C, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.keyPressEvent(event) elif action_text == "Paste display properties": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_V, QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier, ) self.keyPressEvent(event) elif action_text == "Enable all": count = self.topLevelItemCount() for i in range(count): item = self.topLevelItem(i) if item.type() != item.Info: item.setCheckState(self.NameColumn, QtCore.Qt.CheckState.Checked) elif action_text == "Disable all": count = self.topLevelItemCount() for i in range(count): item = self.topLevelItem(i) if item.type() != item.Info: item.setCheckState(self.NameColumn, QtCore.Qt.CheckState.Unchecked) elif action_text == "Enable selected": selected_items = self.selectedItems() for item in selected_items: if item.type() in (item.Channel, item.Group): item.setCheckState(item.NameColumn, QtCore.Qt.CheckState.Checked) elif action_text == "Disable selected": selected_items = self.selectedItems() for item in selected_items: if item.type() in (item.Channel, item.Group): item.setCheckState(item.NameColumn, QtCore.Qt.CheckState.Unchecked) elif action_text == "Disable all but this": selected_items = self.selectedItems() count = self.topLevelItemCount() for i in range(count): item = self.topLevelItem(i) if item.type() != item.Info: item.setCheckState(item.NameColumn, QtCore.Qt.CheckState.Unchecked) for item in selected_items: if item.type() == item.Channel: item.setCheckState(item.NameColumn, QtCore.Qt.CheckState.Checked) elif item.type() == item.Group: count = item.childCount() for i in range(count): child = item.child(i) if child in selected_items: break else: item.setCheckState(item.NameColumn, QtCore.Qt.CheckState.Checked) elif action_text == "Hide disabled items": self.hide_disabled_channels = not self.hide_disabled_channels self.update_hidden_states() elif action_text == "Hide missing items": self.hide_missing_channels = not self.hide_missing_channels self.update_hidden_states() elif action_text == "Filter only computed channels": self.filter_computed_channels = not self.filter_computed_channels self.update_hidden_states() elif action_text == "Add to common Y axis": selected_items = self.selectedItems() if self.plot.locked: for item in selected_items: if item.type() == ChannelsTreeItem.Channel: item.signal.y_link = True else: for item in selected_items: if item.type() == ChannelsTreeItem.Channel: item.setCheckState(self.CommonAxisColumn, QtCore.Qt.CheckState.Checked) elif action_text == "Edit Y axis scaling": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_G, QtCore.Qt.KeyboardModifier.ControlModifier, ) self.plot.keyPressEvent(event) elif action_text == "Remove from common Y axis": selected_items = self.selectedItems() if self.plot.locked: for item in selected_items: if item.type() == ChannelsTreeItem.Channel: item.signal.y_link = False else: for item in selected_items: if item.type() == ChannelsTreeItem.Channel and item.signal.y_link: item.setCheckState(self.CommonAxisColumn, QtCore.Qt.CheckState.Unchecked) elif action_text == "Set unit": selected_items = self.selectedItems() unit, ok = QtWidgets.QInputDialog.getText(self, "Set new unit", "Unit:") if ok: for item in selected_items: if item.type() == ChannelsTreeItem.Channel: item.unit = unit elif action_text == "Set precision": selected_items = self.selectedItems() if not selected_items: return for item in selected_items: if item.type() == item.Channel: precision = item.precision break else: precision = 3 precision, ok = QtWidgets.QInputDialog.getInt( self, "Set new precision (float decimals)", "Precision:", precision, -1, 15, 1, ) if ok: for item in selected_items: if item.type() == ChannelsTreeItem.Channel: item.precision = precision elif item.type() == ChannelsTreeItem.Group: for channel_item in item.get_all_channel_items(): channel_item.precision = precision plot = self.plot.plot if plot.region is not None: self.plot.range_modified(plot.region) else: self.plot.cursor_moved(plot.cursor1) elif action_text in ( "Relative time base shift", "Set time base start offset", ): selected_items = self.selectedItems() if selected_items: if action_text == "Relative time base shift": offset, ok = QtWidgets.QInputDialog.getDouble( self, "Relative offset [s]", "Offset [s]:", decimals=6 ) absolute = False else: offset, ok = QtWidgets.QInputDialog.getDouble( self, "Absolute time start offset [s]", "Offset [s]:", decimals=6, ) absolute = True if ok: uuids = [] for item in selected_items: if item.type() == ChannelsTreeItem.Channel: uuids.append(item.uuid) self.set_time_offset.emit([absolute, offset, *uuids]) elif action_text == "Delete": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Delete, QtCore.Qt.KeyboardModifier.NoModifier ) self.keyPressEvent(event) elif action_text == "Toggle details": self.details_enabled = not self.details_enabled if self.details_enabled: iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): if item.type() == ChannelsTreeItem.Channel: item.details = ChannelsTreeItem( type=ChannelsTreeItem.Info, name=item.details_text, signal=item.signal, origin_uuid=item.signal.origin_uuid, uuid=item.signal.uuid, ) item.addChild(item.details) if count <= 200: item.setExpanded(True) iterator += 1 else: iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): if item.type() == ChannelsTreeItem.Channel: if item.details: item.removeChild(item.details) item.details = None iterator += 1 elif action_text in ("File/Computation properties", "Group properties"): selected_items = self.selectedItems() if len(selected_items) == 1: item = selected_items[0] if item.type() == ChannelsTreeItem.Channel: self.show_properties.emit(item.origin_uuid, item.uuid) elif item.type() == ChannelsTreeItem.Group: item.show_info() elif action_text == "Show overlapping alias": selected_items = self.selectedItems() if len(selected_items) == 1: item = selected_items[0] if item.type() == ChannelsTreeItem.Channel: self.show_overlapping_alias.emit(item.origin_uuid, item.uuid) elif action_text == "Edit this computed channel": self.edit_computation.emit(item) elif action_text == "Compute FFT": selected_items = self.selectedItems() if len(selected_items) == 1: item = selected_items[0] if item.type() == ChannelsTreeItem.Channel: self.compute_fft_request.emit(item.uuid) elif action_text == "Add channel group": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Insert, QtCore.Qt.KeyboardModifier.ShiftModifier ) self.keyPressEvent(event) elif action_text == "Add pattern based channel group": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Insert, QtCore.Qt.KeyboardModifier.ControlModifier ) self.keyPressEvent(event) elif action_text == "Rename channel": text, ok = QtWidgets.QInputDialog.getText( self, "Rename channel", "New channel name:", text=item.text(item.NameColumn), ) if ok and text.strip(): text = text.strip() item.name = text elif action_text == "Edit group": if item.pattern: mdf = None if self.plot: if hasattr(self.plot, "mdf"): mdf = self.plot.mdf pattern = dict(item.pattern) pattern["ranges"] = copy_ranges(item.ranges) dlg = AdvancedSearch( mdf, show_add_window=False, show_apply=True, show_search=False, window_title="Add pattern based group", parent=self, pattern=pattern, ) dlg.setModal(True) dlg.exec_() pattern = dlg.result if pattern: item.pattern = pattern item.name = pattern["name"] item.set_ranges(pattern["ranges"]) self.clearSelection() count = item.childCount() for i in range(count): child = item.child(i) child.setSelected(True) event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Delete, QtCore.Qt.KeyboardModifier.NoModifier, ) self.keyPressEvent(event) self.pattern_group_added.emit(item) self.refresh() else: text, ok = QtWidgets.QInputDialog.getText( self, "Edit channel group name", "New channel group name:", QtWidgets.QLineEdit.EchoMode.Normal, item.name, ) if ok: item.name = text.strip() elif action_text == "Search item": pattern, ok = QtWidgets.QInputDialog.getText(self, "Search item", "Item name:") if ok and pattern: original_pattern = pattern wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" pattern = pattern.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") compiled_pattern = re.compile(pattern, flags=re.IGNORECASE) start_item = item or self iterator = QtWidgets.QTreeWidgetItemIterator(start_item) while item := iterator.value(): if ( item is not start_item and item.type() in (ChannelsTreeItem.Channel, ChannelsTreeItem.Group) and compiled_pattern.search(item.name) ): self.scrollToItem(item) self.setCurrentItem(item) return iterator += 1 if start_item is self: MessageBox.warning( self, "No matches found", f"No item matches the pattern\n{original_pattern}", ) else: iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): if item is start_item: break if item.type() in ( ChannelsTreeItem.Channel, ChannelsTreeItem.Group, ) and compiled_pattern.search(item.name): self.scrollToItem(item) self.setCurrentItem(item) return iterator += 1 MessageBox.warning( self, "No matches found", f"No item matches the pattern\n{original_pattern}", ) elif action_text == f"Find next {item.name if item else ''}": start_item = item wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" pattern = start_item.name.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") compiled_pattern = re.compile(pattern, flags=re.IGNORECASE) iterator = QtWidgets.QTreeWidgetItemIterator(start_item) iterator += 1 while item := iterator.value(): if item.type() in ( ChannelsTreeItem.Channel, ChannelsTreeItem.Group, ) and compiled_pattern.fullmatch(item.name): self.scrollToItem(item) self.setCurrentItem(item) return iterator += 1 iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): if item is start_item: break if item.type() in ( ChannelsTreeItem.Channel, ChannelsTreeItem.Group, ) and compiled_pattern.search(item.name): self.scrollToItem(item) self.setCurrentItem(item) return iterator += 1 elif action_text == "Raw Column": self.setColumnHidden(self.RawColumn, not self.isColumnHidden(self.RawColumn)) elif action_text == "Unit Column": self.setColumnHidden(self.UnitColumn, not self.isColumnHidden(self.UnitColumn)) elif action_text == "Common Axis Column": self.setColumnHidden(self.CommonAxisColumn, not self.isColumnHidden(self.CommonAxisColumn)) elif action_text == "Individual Axis Column": self.setColumnHidden(self.IndividualAxisColumn, not self.isColumnHidden(self.IndividualAxisColumn)) elif action_text == "Origin Column": self.setColumnHidden(self.OriginColumn, not self.isColumnHidden(self.OriginColumn)) elif action_text == "Raw samples": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_R, QtCore.Qt.KeyboardModifier.AltModifier ) self.plot.keyPressEvent(event) elif action_text == "Scaled samples": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_S, QtCore.Qt.KeyboardModifier.AltModifier ) self.plot.keyPressEvent(event) elif action_text == "Ascii": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_T, QtCore.Qt.KeyboardModifier.ControlModifier ) self.plot.keyPressEvent(event) elif action_text == "Bin": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_B, QtCore.Qt.KeyboardModifier.ControlModifier ) self.plot.keyPressEvent(event) elif action_text == "Hex": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_H, QtCore.Qt.KeyboardModifier.ControlModifier ) self.plot.keyPressEvent(event) elif action_text == "Physical": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_P, QtCore.Qt.KeyboardModifier.ControlModifier ) self.plot.keyPressEvent(event) elif action_text == "Insert computation": event = QtGui.QKeyEvent( QtCore.QEvent.Type.KeyPress, QtCore.Qt.Key.Key_Insert, QtCore.Qt.KeyboardModifier.NoModifier ) self.plot.keyPressEvent(event) self.update_channel_groups_count() def refresh(self): self.updateGeometry() self.update_hidden_states() self.update_visibility_status() def resizeEvent(self, e: QtGui.QResizeEvent) -> None: if self.updatesEnabled(): super().resizeEvent(e) self.update_visibility_status() def setColumnWidth(self, column, width): if column not in (self.CommonAxisColumn, self.IndividualAxisColumn): width = max(width, MINIMUM_COLUMN_WIDTH) super().setColumnWidth(column, width) def set_font_size(self, size): font = self.font() font.setPointSize(size) self.setFont(font) dark = ( QtWidgets.QApplication.instance().palette().window().color().value() < QtWidgets.QApplication.instance().palette().windowText().color().value() ) if dark: color = ( QtWidgets.QApplication.instance() .palette() .brush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Highlight) .color() .name() ) self.setStyleSheet(SCROLLBAR_STYLE.format(font_size=size, color=color)) def set_header_columns_visibility(self, visibility): for name, is_visible in visibility.items(): col = getattr(self, name, -1) if col == -1: continue self.setColumnHidden(col, not is_visible) def set_header_sizes(self, sizes): for name, size in sizes.items(): col = getattr(self, name, -1) if col == -1: continue self.setColumnWidth(col, size) def set_style(self): dark = ( QtWidgets.QApplication.instance().palette().window().color().value() < QtWidgets.QApplication.instance().palette().windowText().color().value() ) item = QtWidgets.QTreeWidgetItem() background = item.background(0) color = ( QtWidgets.QApplication.instance() .palette() .brush(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Highlight) .color() .name() ) iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): item.set_default_background(background) iterator += 1 if dark: self.setStyleSheet(SCROLLBAR_STYLE.format(font_size=self.font().pointSize(), color=color)) else: self.setStyleSheet("") def update_channel_groups_count(self): iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): if item.type() == ChannelsTreeItem.Group: item.count = item.childCount() iterator += 1 def update_hidden_states(self): hide_missing_channels = self.hide_missing_channels hide_disabled_channels = self.hide_disabled_channels filter_computed = self.filter_computed_channels iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): hidden = False if filter_computed: hidden = item.filter_computed() else: if item.type() == ChannelsTreeItem.Channel: if hide_missing_channels and not item.exists: hidden = True if hide_disabled_channels and item.checkState(self.NameColumn) == QtCore.Qt.CheckState.Unchecked: hidden = True else: if hide_disabled_channels and item.checkState(self.NameColumn) == QtCore.Qt.CheckState.Unchecked: hidden = True item.setHidden(hidden) iterator += 1 def update_visibility_status(self, *args): tree_rect = self.viewport().rect() iterator = QtWidgets.QTreeWidgetItemIterator(self) while item := iterator.value(): try: if item.type() == item.Channel: rect = self.visualItemRect(item) item._is_visible = rect.intersects(tree_rect) else: item._is_visible = False except: print(item) iterator += 1 self.visible_items_changed.emit() class ChannelsTreeItem(QtWidgets.QTreeWidgetItem): Group = 2000 Channel = 2001 Info = 2002 NameColumn = 0 RawColumn = 1 ValueColumn = 2 UnitColumn = 3 CommonAxisColumn = 4 IndividualAxisColumn = 5 OriginColumn = 6 def __init__( self, type, signal=None, name="", pattern=None, parent=None, uuid="", check=None, ranges=None, origin_uuid=None, background_color=None, expanded=False, ): super().__init__(parent, type) self.exists = True self.resolved_ranges = None self.ranges = [] # bind cache to instance to avoid memory leaks self.get_color_using_ranges = lru_cache(maxsize=1024)(self._get_color_using_ranges) self._name = "" self._count = 0 if background_color is None: background_color = self.background(0) self._background_color = background_color self._current_background_color = background_color self._current_font_color = background_color.color() if type == self.Group: self.pattern = None self.set_pattern(pattern) self._is_visible = True self.uuid = uuid self.origin_uuid = origin_uuid or os.urandom(6).hex() self.count = 0 self.setFlags( QtCore.Qt.ItemFlag.ItemIsUserCheckable | QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsAutoTristate | QtCore.Qt.ItemFlag.ItemIsDragEnabled | QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsDropEnabled ) self.setCheckState(self.NameColumn, QtCore.Qt.CheckState.Unchecked) self.name = name.split("\t[")[0] # Store Previous State (Disabled/Enabled) self._previous_state = self.isDisabled() elif type == self.Channel: self.signal = signal self.details = None self._value_prefix = "" self._value = "n.a." self._raw_value = "n.a." self.uuid = signal.uuid self.origin_uuid = signal.origin_uuid self.set_ranges(ranges or []) self.resolved_ranges = None kind = signal.phys_samples.dtype.kind # if len(signal.samples) and signal.conversion: # kind = signal.conversion.convert(signal.samples[:1]).dtype.kind # else: # kind = signal.samples.dtype.kind self.kind = kind tooltip = getattr(signal, "tooltip", "") or f"{signal.name}\n{signal.comment}" if signal.source: details = signal.source.get_details() else: details = "" self.details_text = details or "\tSource not available" self.setToolTip(self.NameColumn, tooltip) self.setToolTip(self.ValueColumn, "") self.setToolTip(self.RawColumn, "") self.setToolTip(self.UnitColumn, "unit") self.setToolTip(self.CommonAxisColumn, "common axis") self.setToolTip(self.IndividualAxisColumn, "individual axis") self.setText(self.UnitColumn, signal.unit) if kind in "SUVui" or self.precision == -1: self.fmt = "{}" else: self.fmt = f"{{:.{self.precision}f}}" self.entry = signal.group_index, signal.channel_index self.setText(self.NameColumn, self.name) self.setForeground(self.NameColumn, signal.color) self.setForeground(self.RawColumn, signal.color) self.setForeground(self.ValueColumn, signal.color) self.setForeground(self.CommonAxisColumn, signal.color) self.setForeground(self.IndividualAxisColumn, signal.color) self.setForeground(self.UnitColumn, signal.color) self.setForeground(self.OriginColumn, signal.color) self._is_visible = True self.setFlags( QtCore.Qt.ItemFlag.ItemIsUserCheckable | QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsDragEnabled | QtCore.Qt.ItemFlag.ItemIsSelectable ) if check is None: self.setCheckState(self.NameColumn, QtCore.Qt.CheckState.Checked) else: self.setCheckState(self.NameColumn, check) self.setCheckState(self.CommonAxisColumn, QtCore.Qt.CheckState.Unchecked) self.setCheckState(self.IndividualAxisColumn, QtCore.Qt.CheckState.Unchecked) if signal.flags & Signal.Flags.computed: font = self.font(0) font.setItalic(True) for column in (self.NameColumn, self.RawColumn, self.ValueColumn, self.UnitColumn): self.setFont(column, font) if signal.group_index == NOT_FOUND: self.does_not_exist() elif type == self.Info: tooltip = getattr(signal, "tooltip", "") if tooltip: self.setText(self.ValueColumn, tooltip.split("@")[-1].strip()) self.name = name self.color = signal.color self.uuid = uuid self.origin_uuid = origin_uuid self.setTextAlignment(self.RawColumn, QtCore.Qt.AlignmentFlag.AlignRight) self.setTextAlignment(self.ValueColumn, QtCore.Qt.AlignmentFlag.AlignRight) self.setText(self.OriginColumn, self.origin_uuid) def __repr__(self): match self.type(): case 2000: type = "Group" case 2001: type = "Channel" case 2002: type = "Info" case _: type = self.type() return f"ChannelTreeItem(type={type}, name={self.name}, uuid={self.uuid}, origin_uuid={self.origin_uuid})" @property def color(self): type = self.type() if type == self.Channel: return self.signal.color else: return "" @color.setter def color(self, value): if self.type() == self.Channel: value = fn.mkColor(value) color_name = value.name() self.signal.color = value self.signal.pen = fn.mkPen(color_name) self.signal.color_name = color_name self.setForeground(self.NameColumn, value) self.setForeground(self.RawColumn, value) self.setForeground(self.ValueColumn, value) self.setForeground(self.CommonAxisColumn, value) self.setForeground(self.IndividualAxisColumn, value) self.setForeground(self.UnitColumn, value) self.setForeground(self.OriginColumn, value) if self.details is not None: self.details.color = value tree = self.treeWidget() if tree: tree.color_changed.emit(self.uuid, value) elif self.type() == self.Group: count = self.childCount() for row in range(count): child = self.child(row) child.color = value elif self.type() == self.Info: value = fn.mkColor(value) self.setForeground(self.NameColumn, value) self.setForeground(self.RawColumn, value) self.setForeground(self.ValueColumn, value) self.setForeground(self.CommonAxisColumn, value) self.setForeground(self.IndividualAxisColumn, value) self.setForeground(self.UnitColumn, value) self.setForeground(self.OriginColumn, value) @property def comment(self): type = self.type() if type == self.Channel: return self.signal.comment else: return "" @comment.setter def comment(self, value): value = value or "" type = self.type() if type == self.Channel: self.signal.comment = value self.signal.flags |= Signal.Flags.user_defined_comment tooltip = getattr(self.signal, "tooltip", "") or f"{self.signal.name}\n{value}" self.setToolTip(self.NameColumn, tooltip) def copy(self): type = self.type() if type == self.Channel: return ChannelsTreeItem( type, signal=self.signal, check=self.checkState(self.NameColumn), ) elif type == self.Group: return ChannelsTreeItem( type, name=self.name, pattern=self.pattern, uuid=self.uuid, ) else: return ChannelsTreeItem( type, name=self.name, ) @property def count(self): return self._count @count.setter def count(self, value): self._count = value if self.type() == self.Group: if self.pattern: if self._count: self.setText(self.ValueColumn, f"{self._count} matches") else: self.setText(self.ValueColumn, "no matches") else: self.setText(self.ValueColumn, f"{self._count} items") def does_not_exist(self, exists=False): if exists == self.exists: return if self.type() == self.Channel: if utils.ERROR_ICON is None: utils.ERROR_ICON = QtGui.QIcon() utils.ERROR_ICON.addPixmap(QtGui.QPixmap(":/error.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) utils.NO_ICON = QtGui.QIcon() if not exists: icon = utils.ERROR_ICON else: icon = utils.NO_ICON self.setIcon(self.NameColumn, icon) self.exists = exists def first_signal(self): if self.type() == self.Group: count = self.childCount() for i in range(count): item = self.child(i) if item.type() == self.Channel: return item for i in range(count): item = self.child(i) if item.type() == self.Group: if item_first_signal := item.first_signal(): return item_first_signal def filter_computed(self): if self.type() == self.Channel: hide = not (self.signal.flags & Signal.Flags.computed) else: hide = all(self.child(i).filter_computed() for i in range(self.childCount())) return hide def get_all_channel_items(self): children = [] count = self.childCount() for i in range(count): item = self.child(i) type = item.type() if type == self.Group: children.extend(item.get_all_channel_items()) elif type == self.Channel: children.append(item) return children @property def format(self): if self.type() == self.Channel: return self.signal.format else: return "phys" @format.setter def format(self, format): if self.type() == self.Channel: self.signal.format = format self.set_fmt(format) self.set_value(update=True) elif self.type() == self.Group: count = self.childCount() for row in range(count): child = self.child(row) child.set_fmt(format) def _get_color_using_ranges(self, value, pen=False): return get_color_using_ranges(value, self.get_ranges(), self.signal.color, pen=pen) def get_display_properties(self): if self.type() == ChannelsTreeItem.Group: info = { "type": "group", "ranges": self.ranges, } elif self.type() == ChannelsTreeItem.Channel: info = { "type": "channel", "color": self.color, "precision": self.precision, "ylink": self.checkState(self.CommonAxisColumn) == QtCore.Qt.CheckState.Checked, "individual_axis": self.checkState(self.IndividualAxisColumn) == QtCore.Qt.CheckState.Checked, "format": self.format, "ranges": self.ranges, } if self.signal.flags & Signal.Flags.user_defined_conversion: info["conversion"] = to_dict(self.signal.conversion) plot = self.treeWidget().plot.plot sig, index = plot.signal_by_uuid(self.uuid) info["y_range"] = tuple(float(e) for e in sig.y_range) return json.dumps(info, cls=ExtendedJsonEncoder) def get_ranges(self, tree=None): if self.resolved_ranges is None: tree = tree or self.treeWidget() if tree: parent = self.parent() if parent is None: self.resolved_ranges = self.ranges else: self.resolved_ranges = [*self.ranges, *parent.get_ranges(tree)] else: return self.ranges return self.resolved_ranges @property def mode(self): if self.type() == self.Channel: return self.signal.mode else: return "phys" @mode.setter def mode(self, mode): if self.type() == self.Channel: self.signal.mode = mode self.set_value(update=True) @property def name(self): type = self.type() if type == self.Channel: return self.signal.name else: return self._name @name.setter def name(self, text): text = text or "" type = self.type() if type == self.Group: self._name = text elif type == self.Channel: if text != self.signal.name: if self.signal.original_name is None: self.signal.original_name = self.signal.name self.signal.name = text if not self.signal.flags & Signal.Flags.computed: self.signal.flags |= Signal.Flags.user_defined_name else: self._name = text self.setText(self.NameColumn, self.name) if type == self.Channel: tree = self.treeWidget() if tree: tree.name_changed.emit(self.uuid, text) @property def precision(self): if self.type() == self.Channel: return self.signal.precision else: return 3 @precision.setter def precision(self, precision): if self.type() == self.Channel: self.signal.precision = precision if self.kind == "f": if precision >= 0: self.fmt = f"{{:.{self.precision}f}}" else: self.fmt = "{}" self.set_value(update=True) elif self.type() == self.Group: count = self.childCount() for row in range(count): child = self.child(row) child.precision = precision def reset_resolved_ranges(self): self.resolved_ranges = None count = self.childCount() for row in range(count): item = self.child(row) item.reset_resolved_ranges() def set_conversion(self, conversion): if self.type() == self.Channel: self.signal.conversion = conversion self.signal.flags |= Signal.Flags.user_defined_conversion self.signal.text_conversion = None if self.signal.conversion: samples = self.signal.conversion.convert(self.signal.samples, as_bytes=True) if samples.dtype.kind not in "SUV": nans = np.isnan(samples) if np.any(nans): self.signal.raw_samples = self.signal.samples[~nans] self.signal.phys_samples = samples[~nans] self.signal.timestamps = self.signal.timestamps[~nans] self.signal.samples = self.signal.samples[~nans] else: self.signal.raw_samples = self.signal.samples self.signal.phys_samples = samples else: self.signal.text_conversion = self.signal.conversion self.signal.phys_samples = self.signal.raw_samples = self.signal.samples self.unit = conversion.unit else: self.signal.phys_samples = self.signal.raw_samples = self.signal.samples self.set_value(update=True) tree = self.treeWidget() if tree: tree.conversion_changed.emit(self.uuid, conversion) elif self.type() == self.Group: count = self.childCount() for i in range(count): child = self.child(i) child.set_conversion(conversion) def set_default_background(self, brush): if self._current_background_color == self._background_color: self._current_background_color = brush self._current_background_color = brush def set_disabled(self, disabled, preserve_subgroup_state=True): if self.type() == self.Channel: for col in range(self.columnCount()): self.setForeground(col, QtCore.Qt.BrushStyle.NoBrush) self.setBackground(col, QtCore.Qt.BrushStyle.NoBrush) self._current_background_color = None self._current_font_color = None if self.parent().isDisabled() == disabled: self.setDisabled(disabled) if self.details is not None: self.details.setDisabled(disabled) if disabled: self.signal.enable = False else: enable = self.checkState(self.NameColumn) == QtCore.Qt.CheckState.Checked self.signal.enable = enable color = self.signal.color self.setForeground(self.NameColumn, color) self.setForeground(self.RawColumn, color) self.setForeground(self.ValueColumn, color) self.setForeground(self.CommonAxisColumn, color) self.setForeground(self.IndividualAxisColumn, color) self.setForeground(self.UnitColumn, color) self.setForeground(self.OriginColumn, color) elif self.type() == self.Group: # If the group is subgroup (has a parent) if self.parent() and not self.parent().isDisabled(): # And the action was triggered on it if preserve_subgroup_state: # Save current state self._previous_state = not self.isDisabled() # Restore state elif not disabled: disabled = self._previous_state if disabled: self.setIcon(self.NameColumn, QtGui.QIcon(":/erase.png")) elif not self.parent() or (self.parent() and not self.parent().isDisabled()): self.setIcon(self.NameColumn, QtGui.QIcon(":/open.png")) self.setDisabled(disabled) count = self.childCount() for i in range(count): child = self.child(i) child.set_disabled(disabled, preserve_subgroup_state=False) def set_fmt(self, fmt): if self.type() == self.Channel: if self.kind in "SUV": self.fmt = "{}" elif self.kind == "f": self.fmt = f"{{:.{self.precision}f}}" else: if fmt == "hex": self.fmt = "0x{:x}" elif fmt == "bin": self.fmt = "0b{:b}" elif fmt == "phys": self.fmt = "{}" def set_pattern(self, pattern): if pattern: self.setIcon(self.NameColumn, QtGui.QIcon(":/filter.png")) self.pattern = dict(pattern) self.pattern["ranges"] = copy_ranges(self.pattern["ranges"]) else: self.setIcon(self.NameColumn, QtGui.QIcon(":/open.png")) self.pattern = None def set_prefix(self, text=""): self._value_prefix = text def set_ranges(self, ranges): self.get_color_using_ranges.cache_clear() if utils.RANGE_INDICATOR_ICON is None: utils.RANGE_INDICATOR_ICON = QtGui.QIcon() utils.RANGE_INDICATOR_ICON.addPixmap( QtGui.QPixmap(":/paint.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off ) utils.NO_ICON = QtGui.QIcon() utils.NO_ERROR_ICON = QtGui.QIcon() if ranges: self.setIcon(self.ValueColumn, utils.RANGE_INDICATOR_ICON) self.setToolTip(self.ValueColumn, f"{self.name}\nhas color ranges defined") else: self.setIcon(self.ValueColumn, utils.NO_ICON) self.setToolTip(self.ValueColumn, "") if self.type() == self.Channel: brush = self._background_color self.setBackground(self.NameColumn, brush) self.setBackground(self.RawColumn, brush) self.setBackground(self.ValueColumn, brush) self.setBackground(self.UnitColumn, brush) self.setBackground(self.CommonAxisColumn, brush) self.setBackground(self.IndividualAxisColumn, brush) self.setBackground(self.OriginColumn, brush) self._current_background_color = self._background_color brush = fn.mkBrush(self.signal.color_name) self.setForeground(self.NameColumn, brush) self.setForeground(self.UnitColumn, brush) self.setForeground(self.RawColumn, brush) self.setForeground(self.ValueColumn, brush) self.setForeground(self.CommonAxisColumn, brush) self.setForeground(self.IndividualAxisColumn, brush) self.setForeground(self.OriginColumn, brush) self._current_font_color = self.signal.color self.ranges = copy_ranges(ranges) self.reset_resolved_ranges() def set_value(self, raw_value=None, value=None, update=False, force=False): if self.type() == self.Info: return update_text = (value != self._value) or force if value is not None: if self._value == value and update is False: return else: self._value = value else: value = self._value if raw_value is not None: if self._raw_value == raw_value and update is False: return else: self._raw_value = raw_value else: raw_value = self._raw_value default_background_color = None default_font_color = None ranges = self.get_ranges() if ranges and not self.isDisabled(): new_background_color, new_font_color = get_colors_using_ranges( value, ranges=self.get_ranges(), default_background_color=default_background_color, default_font_color=default_font_color, ) if new_background_color is None: if self._background_color != self._current_background_color: brush = self._background_color self.setBackground(self.NameColumn, brush) self.setBackground(self.RawColumn, brush) self.setBackground(self.ValueColumn, brush) self.setBackground(self.UnitColumn, brush) self.setBackground(self.CommonAxisColumn, brush) self.setBackground(self.IndividualAxisColumn, brush) self.setBackground(self.OriginColumn, brush) self._current_background_color = self._background_color else: if new_background_color != self._current_background_color: brush = fn.mkBrush(new_background_color.name()) self.setBackground(self.NameColumn, brush) self.setBackground(self.RawColumn, brush) self.setBackground(self.ValueColumn, brush) self.setBackground(self.UnitColumn, brush) self.setBackground(self.CommonAxisColumn, brush) self.setBackground(self.IndividualAxisColumn, brush) self.setBackground(self.OriginColumn, brush) self._current_background_color = brush if new_font_color is None: if self.signal.color != self._current_font_color: brush = fn.mkBrush(self.signal.color_name) self.setForeground(self.NameColumn, brush) self.setForeground(self.UnitColumn, brush) self.setForeground(self.RawColumn, brush) self.setForeground(self.ValueColumn, brush) self.setForeground(self.CommonAxisColumn, brush) self.setForeground(self.IndividualAxisColumn, brush) self.setForeground(self.OriginColumn, brush) self._current_font_color = self.signal.color else: if new_font_color != self.foreground(0).color(): brush = fn.mkBrush(new_font_color.name()) self.setForeground(self.NameColumn, brush) self.setForeground(self.RawColumn, brush) self.setForeground(self.ValueColumn, brush) self.setForeground(self.UnitColumn, brush) self.setForeground(self.CommonAxisColumn, brush) self.setForeground(self.IndividualAxisColumn, brush) self.setForeground(self.OriginColumn, brush) self._current_font_color = new_font_color if update_text: if value in ("", "n.a."): text = f"{self._value_prefix}{value}" self.setText(self.ValueColumn, text) else: if self.signal.text_conversion and self.mode == "phys": value = self.signal.text_conversion.convert([value], as_bytes=True)[0] if isinstance(value, bytes): try: text = value.decode("utf-8", errors="replace") except: text = value.decode("latin-1", errors="replace") text = f"{self._value_prefix}{text}" else: text = f"{self._value_prefix}{value}" else: string = value_as_str( value, self.format, self.signal.plot_samples.dtype, self.precision, ) text = f"{self._value_prefix}{string}" try: self.setText(self.ValueColumn, text) except (ValueError, TypeError): self.setText(self.ValueColumn, f"{self._value_prefix}{value}") if raw_value in ("", "n.a."): text = f"{self._value_prefix}{raw_value}" self.setText(self.RawColumn, text) else: string = value_as_str( raw_value, self.format, self.signal.raw_samples.dtype, self.precision, ) text = f"{self._value_prefix}{string}" try: self.setText(self.RawColumn, text) except (ValueError, TypeError): self.setText(self.RawColumn, f"{self._value_prefix}{raw_value}") def show_info(self): if self.type() == self.Group: ChannnelGroupDialog(self.name, self.pattern, self.get_ranges(), self.treeWidget()).show() @property def unit(self): match self.type(): case self.Channel: return self.signal.unit if self.signal.mode != "raw" else "" case self.Info: return self.origin_uuid case _: return "" @unit.setter def unit(self, text): text = text or "" if self.type() == self.Channel and self.signal.unit != text: self.signal.unit = text self.signal.flags |= Signal.Flags.user_defined_unit self.setText(self.UnitColumn, text) tree = self.treeWidget() if tree: tree.unit_changed.emit(self.uuid, text) def update_child_values(self, tree=None): tree = tree or self.treeWidget() count = self.childCount() for i in range(count): item = self.child(i) item.update_child_values(tree) if self.type() == self.Channel: self.set_value(update=True) @property def y_range(self): type = self.type() if type == self.Channel: return self.signal.y_range elif type == self.Group: count = self.childCount() if count: for row in range(count): return self.child(row).y_range else: return (0, 1) else: return (0, 1) @y_range.setter def y_range(self, value): if self.type() == self.Channel: self.signal.y_range = value elif self.type() == self.Group: if self.pattern: self.pattern["y_range"] = value count = self.childCount() for row in range(count): child = self.child(row) child.y_range = value class ChannnelGroupDialog(QtWidgets.QDialog): def __init__(self, name, pattern, ranges, *args, **kwargs): super().__init__(*args, **kwargs) self.setWindowFlags(QtCore.Qt.WindowType.Window) layout = QtWidgets.QGridLayout() layout.setColumnStretch(0, 0) layout.setColumnStretch(1, 1) self.setLayout(layout) if pattern: self.setWindowTitle(f"<{name}> pattern group details") for i, key in enumerate( ( "name", "pattern", "match_type", "case_sensitive", "filter_type", "filter_value", "raw", ) ): widget = QtWidgets.QLabel(str(pattern.get(key, "False"))) if key == "raw": key = "Use raw values" label = QtWidgets.QLabel(key.replace("_", " ").capitalize()) label.setStyleSheet("color:rgb(97, 190, 226);") layout.addWidget(label, i, 0) layout.addWidget(widget, i, 1) else: self.setWindowTitle(f"<{name}> group details") # self.setStyleSheet('font: 8pt "Consolas";}') icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) self.setWindowIcon(icon) self.setMinimumWidth(500) self.adjustSize() # screen = QtWidgets.QApplication.desktop().screenGeometry() # self.move((screen.width() - 1200) // 2, (screen.height() - 600) // 2) if __name__ == "__main__": pass asammdf-8.5.1/src/asammdf/gui/widgets/tree_item.py000066400000000000000000000065601502633300400221200ustar00rootroot00000000000000from time import perf_counter from PySide6 import QtWidgets from ..utils import get_colors_using_ranges class MinimalTreeItem(QtWidgets.QTreeWidgetItem): def __init__( self, entry, name="", parent=None, strings=None, origin_uuid=None, ): super().__init__(parent, strings) self.entry = entry self.name = name self.origin_uuid = origin_uuid class TreeItem(QtWidgets.QTreeWidgetItem): def __init__( self, entry, name="", parent=None, strings=None, origin_uuid=None, computation=None, ranges=None, ): super().__init__(parent, strings) self.entry = entry self.name = name self.origin_uuid = origin_uuid self.computation = computation or {} self.ranges = ranges or [] self._back_ground_color = self.background(0) self._font_color = self.foreground(0) self._current_background_color = self._back_ground_color self._current_font_color = self._font_color self._value = None self._sorting_column = 0 self._t = perf_counter() def __lt__(self, other): if self._sorting_column == 1: self_value = self._value if self_value is None: return True other_value = other._value if other_value is None: return False if self_value.dtype.kind in "fui": if other_value.dtype.kind in "fui": return self_value < other_value else: return True else: if other_value.dtype.kind in "fui": return False else: return super().__lt__(other) else: return super().__lt__(other) def __del__(self): self.entry = self.name = self.origin_uuid = None def check_signal_range(self, value=None): if value is None: value = self.text(1).strip() if value: try: value = float(value) except: if value.startswith("0x"): try: value = float(int(value, 16)) except: pass elif value.startswith("0b"): try: value = float(int(value, 2)) except: pass else: value = None default_background_color = self._back_ground_color default_font_color = self._font_color new_background_color, new_font_color = get_colors_using_ranges( value, ranges=self.ranges, default_background_color=default_background_color, default_font_color=default_font_color, ) if new_background_color is not default_background_color: self.setBackground(0, new_background_color) self.setBackground(1, new_background_color) self.setBackground(2, new_background_color) if new_font_color is not default_font_color: self.setForeground(0, new_font_color) self.setForeground(1, new_font_color) self.setForeground(2, new_font_color) asammdf-8.5.1/src/asammdf/gui/widgets/viewbox.py000066400000000000000000000434541502633300400216310ustar00rootroot00000000000000from functools import partial import weakref import numpy as np import pyqtgraph as pg import pyqtgraph.functions as fn from PySide6 import QtCore, QtGui, QtWidgets class ViewBoxMenu(QtWidgets.QMenu): pan = "Pan mode" cursor = "Cursor mode" def __init__(self, view): super().__init__() self._settings = QtCore.QSettings() self.view = weakref.ref( view ) ## keep weakref to view to avoid circular reference (don't know why, but this prevents the ViewBox from being collected) self.valid = False ## tells us whether the ui needs to be updated self.viewMap = weakref.WeakValueDictionary() ## weakrefs to all views listed in the link combos # mouse mode self.mouse_mode_menu = QtWidgets.QMenu("Mouse Mode") group = QtGui.QActionGroup(self) pan = QtGui.QAction(ViewBoxMenu.pan, self.mouse_mode_menu) cursor = QtGui.QAction(ViewBoxMenu.cursor, self.mouse_mode_menu) self.mouse_mode_menu.addAction(pan) self.mouse_mode_menu.addAction(cursor) pan.triggered.connect(partial(self.set_mouse_mode, "pan")) cursor.triggered.connect(partial(self.set_mouse_mode, "cursor")) pan.setCheckable(True) cursor.setCheckable(True) pan.setActionGroup(group) cursor.setActionGroup(group) self.mouseModes = [pan, cursor] self.addMenu(self.mouse_mode_menu) # X zoom mode self.x_zoom_mode_menu = QtWidgets.QMenu("X-axis zoom mode") group = QtGui.QActionGroup(self) center_on_cursor = QtGui.QAction("Center on cursor", self.x_zoom_mode_menu) center_on_cursor.setCheckable(True) center_on_cursor.setActionGroup(group) self.x_zoom_mode_menu.addAction(center_on_cursor) center_on_mouse = QtGui.QAction("Center on mouse position", self.x_zoom_mode_menu) center_on_mouse.setCheckable(True) center_on_mouse.setActionGroup(group) self.x_zoom_mode_menu.addAction(center_on_mouse) if self._settings.value("zoom_x_center_on_cursor", True, type=bool): center_on_cursor.setChecked(True) else: center_on_mouse.setChecked(True) center_on_cursor.triggered.connect(partial(self.set_x_zoom_mode, True)) center_on_mouse.triggered.connect(partial(self.set_x_zoom_mode, False)) self.addMenu(self.x_zoom_mode_menu) # Y zoom mode self.y_zoom_mode_menu = QtWidgets.QMenu("Y-axis zoom mode") group = QtGui.QActionGroup(self) center_on_cursor = QtGui.QAction("Center on cursor", self.y_zoom_mode_menu) center_on_cursor.setCheckable(True) center_on_cursor.setActionGroup(group) self.y_zoom_mode_menu.addAction(center_on_cursor) center_on_mouse = QtGui.QAction("Center on mouse position", self.y_zoom_mode_menu) center_on_mouse.setCheckable(True) center_on_mouse.setActionGroup(group) self.y_zoom_mode_menu.addAction(center_on_mouse) pin_zero_level = QtGui.QAction("Pin zero level", self.y_zoom_mode_menu) pin_zero_level.setCheckable(True) pin_zero_level.setActionGroup(group) self.y_zoom_mode_menu.addAction(pin_zero_level) zoom_y_mode = self._settings.value("zoom_y_mode", "") if not zoom_y_mode: if self._settings.value("zoom_y_center_on_cursor", True, type=bool): zoom_y_mode = "center_on_cursor" else: zoom_y_mode = "center_on_mouse" if zoom_y_mode == "pin_zero_level": pin_zero_level.setChecked(True) elif zoom_y_mode == "center_on_cursor": center_on_cursor.setChecked(True) elif zoom_y_mode == "center_on_mouse": center_on_mouse.setChecked(True) center_on_cursor.triggered.connect(partial(self.set_y_zoom_mode, "center_on_cursor")) center_on_mouse.triggered.connect(partial(self.set_y_zoom_mode, "center_on_mouse")) pin_zero_level.triggered.connect(partial(self.set_y_zoom_mode, "pin_zero_level")) self.addMenu(self.x_zoom_mode_menu) self.addMenu(self.y_zoom_mode_menu) self.view().sigStateChanged.connect(self.viewStateChanged) self.updateState() def viewStateChanged(self): self.valid = False self.updateState() def updateState(self): state = self.view().getState(copy=False) if state["mouseMode"] == ViewBoxWithCursor.PanMode: self.mouseModes[0].setChecked(True) elif state["mouseMode"] == ViewBoxWithCursor.CursorMode: self.mouseModes[1].setChecked(True) self.valid = True def popup(self, *args): if not self.valid: self.updateState() QtWidgets.QMenu.popup(self, *args) def set_mouse_mode(self, mode): self.view().setLeftButtonAction(mode) def set_x_zoom_mode(self, on_cursor=True): self._settings.setValue("zoom_x_center_on_cursor", on_cursor) def set_y_zoom_mode(self, zoom_mode="center_on_cursor"): if zoom_mode != "pin_zero_level": self._settings.setValue("zoom_y_center_on_cursor", zoom_mode == "center_on_cursor") self._settings.setValue("zoom_y_mode", zoom_mode) class ViewBoxWithCursor(pg.ViewBox): PanMode = 3 CursorMode = 2 RectMode = 1 sigCursorMoved = QtCore.Signal(object) sigZoomChanged = QtCore.Signal(object) sigZoomFinished = QtCore.Signal(object) hover_at = QtCore.Signal(object) X_zoom = QtCore.QKeyCombination( QtCore.Qt.KeyboardModifier.ShiftModifier, QtCore.Qt.Key.Key_Shift, ).toCombined() Y_zoom = QtCore.QKeyCombination( QtCore.Qt.KeyboardModifier.AltModifier, QtCore.Qt.Key.Key_Alt, ).toCombined() XY_zoom = ( QtCore.QKeyCombination( QtCore.Qt.KeyboardModifier.ShiftModifier | QtCore.Qt.KeyboardModifier.AltModifier, QtCore.Qt.Key.Key_Alt, ).toCombined(), QtCore.QKeyCombination( QtCore.Qt.KeyboardModifier.ShiftModifier | QtCore.Qt.KeyboardModifier.AltModifier, QtCore.Qt.Key.Key_Shift, ).toCombined(), ) def __init__(self, plot, *args, **kwargs): super().__init__(*args, **kwargs) self.setAcceptHoverEvents(True) self.menu.setParent(None) self.menu.deleteLater() self.menu = None self.menu = ViewBoxMenu(self) self.zoom = None self.zoom_start = None self._matrixNeedsUpdate = True self.updateMatrix() self.cursor = None self.plot = plot self._settings = QtCore.QSettings() def close(self): self.cursor = None self.plot = None super().close() def __repr__(self): return "ASAM ViewBox" def hoverMoveEvent(self, event): self.hover_at.emit(self.mapSceneToView(event.scenePos())) def setMouseMode(self, mode): """Set the mouse interaction mode. `mode` must be either ViewBoxWithCursor.PanMode, ViewBoxWithCursor.CursorMode or ViewBoxWithCursor.RectMode. In PanMode, the left mouse button pans the view and the right button scales. In RectMode, the left button draws a rectangle which updates the visible region (this mode is more suitable for single-button mice). """ if mode not in [ ViewBoxWithCursor.PanMode, ViewBoxWithCursor.CursorMode, ViewBoxWithCursor.RectMode, ]: raise Exception( "Mode must be ViewBoxWithCursor.PanMode, ViewBoxWithCursor.RectMode or ViewBoxWithCursor.CursorMode" ) self.state["mouseMode"] = mode self.sigStateChanged.emit(self) def setLeftButtonAction(self, mode="rect"): ## for backward compatibility if mode.lower() == "rect": self.setMouseMode(ViewBoxWithCursor.RectMode) elif mode.lower() == "pan": self.setMouseMode(ViewBoxWithCursor.PanMode) elif mode.lower() == "cursor": self.setMouseMode(ViewBoxWithCursor.CursorMode) else: raise Exception( f'graphicsItems:ViewBox:setLeftButtonAction: unknown mode = {mode} (Options are "pan", "cursor" and "rect")' ) def mouseDragEvent(self, ev, axis=None, ignore_cursor=False): ## if axis is specified, event will only affect that axis. ev.accept() ## we accept all buttons pos = ev.scenePos() dif = pos - ev.lastScenePos() dif = dif * -1 ## Ignore axes if mouse is disabled mask = np.array(self.state["mouseEnabled"], dtype=np.float64) if axis is not None: mask[1 - axis] = 0.0 if self.state["mouseMode"] == ViewBoxWithCursor.CursorMode and not ignore_cursor: if ev.button() == QtCore.Qt.MouseButton.LeftButton: self.sigCursorMoved.emit(ev) if self.zoom_start is not None: end = self.mapSceneToView(ev.scenePos()) self.sigZoomChanged.emit((self.zoom_start, end, self.zoom)) if ev.isFinish(): self.sigZoomFinished.emit((self.zoom_start, end, self.zoom)) self.zoom_start = None self.sigZoomChanged.emit(None) else: tr = self.childGroup.transform() tr = fn.invertQTransform(tr) tr = tr.map(dif * mask) - tr.map(pg.Point(0, 0)) x = tr.x() if mask[0] == 1 else None mask[1] = 0 self._resetTarget() if x is not None: self.translateBy(x=x, y=0) self.sigRangeChangedManually.emit(mask) else: ## Scale or translate based on mouse button if ev.button() in [ QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.MouseButton.MiddleButton, ]: tr = self.childGroup.transform() tr = fn.invertQTransform(tr) tr = tr.map(dif * mask) - tr.map(pg.Point(0, 0)) x = tr.x() if mask[0] == 1 else None y = tr.y() if mask[1] == 1 else None self._resetTarget() if x is not None or y is not None: self.translateBy(x=x, y=y) self.sigRangeChangedManually.emit(mask) elif ev.button() & QtCore.Qt.MouseButton.RightButton: if self.state["aspectLocked"] is not False: mask[0] = 0 dif = ev.screenPos() - ev.lastScreenPos() dif = np.array([dif.x(), dif.y()]) dif[0] *= -1 s = ((mask * 0.02) + 1) ** dif tr = self.childGroup.transform() tr = fn.invertQTransform(tr) x = s[0] if mask[0] == 1 else None y = s[1] if mask[1] == 1 else None center = pg.Point(tr.map(ev.buttonDownPos(QtCore.Qt.MouseButton.RightButton))) self._resetTarget() self.scaleBy(x=x, y=y, center=center) self.sigRangeChangedManually.emit(mask) def keyPressEvent(self, ev): if self.zoom_start is None: self.zoom = ev.keyCombination().toCombined() ev.ignore() def keyReleaseEvent(self, ev): if self.zoom_start is None: self.zoom = None ev.ignore() def mousePressEvent(self, ev): if self.state["mouseMode"] == ViewBoxWithCursor.CursorMode and self.zoom in ( self.X_zoom, self.Y_zoom, *self.XY_zoom, ): self.zoom_start = self.mapSceneToView(ev.scenePos()) ev.ignore() def setXRange(self, min, max, padding=None, update=True): min = round(min, 12) max = round(max, 12) return super().setXRange(min, max, padding, update) def updateScaleBox(self, p1, p2): r = QtCore.QRectF(p1, p2) r = self.childGroup.mapRectFromScene(r) self.rbScaleBox.setPos(r.topLeft()) tr = QtGui.QTransform.fromScale(r.width(), r.height()) self.rbScaleBox.setTransform(tr) self.rbScaleBox.show() def wheelEvent(self, ev, axis=None): if self.state["mouseMode"] == ViewBoxWithCursor.CursorMode: mask = [True, False] else: if axis in (0, 1): mask = [False, False] mask[axis] = self.state["mouseEnabled"][axis] else: mask = self.state["mouseEnabled"][:] pos = ev.pos() factor = self._settings.value("zoom_wheel_factor", 0.165, type=float) if ev.delta() > 0: s = [(None if m is False else 1 / (1 + factor)) for m in mask] else: s = [(None if m is False else 1 + factor) for m in mask] if any(np.isnan(v) for v in s if v is not None): return center = pg.Point(fn.invertQTransform(self.childGroup.transform()).map(pos)) self._resetTarget() if s is not None: x, y = s[0], s[1] affect = [x is not None, y is not None] if not any(affect): return scale = pg.Point([1.0 if x is None else x, 1.0 if y is None else y]) if self.state["aspectLocked"] is not False: scale[0] = scale[1] vr = self.targetRect() if center is None: center = pg.Point(vr.center()) else: center = pg.Point(center) tl = center + (vr.topLeft() - center) * scale br = center + (vr.bottomRight() - center) * scale x_range = tl.x(), br.x() y_range = br.y(), tl.y() if ( self._settings.value("zoom_x_center_on_cursor", True, type=bool) and self.cursor is not None and self.cursor.isVisible() ): delta = x_range[1] - x_range[0] pos = self.cursor.value() x_range = pos - delta / 2, pos + delta / 2 zoom_y_mode = self._settings.value("zoom_y_mode", "") if not zoom_y_mode: if self._settings.value("zoom_y_center_on_cursor", False, type=bool): zoom_y_mode = "center_on_cursor" else: zoom_y_mode = "center_on_mouse" if zoom_y_mode == "pin_zero_level": y_pos_val, sig_y_bottom, sig_y_top = self.plot.value_at_cursor() delta_proc = sig_y_top / (sig_y_top - sig_y_bottom) delta = sig_y_top - sig_y_bottom if ev.delta() > 0: delta *= 1 / (1 + factor) else: delta *= 1 + factor end = delta_proc * delta start = end - delta y_range = start, end elif zoom_y_mode == "center_on_cursor": y_pos_val, sig_y_bottom, sig_y_top = self.plot.value_at_cursor() if isinstance(y_pos_val, (int, float)): delta = y_range[1] - y_range[0] y_range = y_pos_val - delta / 2, y_pos_val + delta / 2 if not mask[0]: x_range = None if not mask[1]: y_range = None self.setRange(xRange=x_range, yRange=y_range, padding=0) ev.accept() self.sigRangeChangedManually.emit(mask) def vertical_zoom(self, zoom_in=True): if not self.state["mouseEnabled"][1]: return factor = self._settings.value("zoom_wheel_factor", 0.165, type=float) if zoom_in: scale = 1 / (1 + factor) else: scale = 1 + factor zoom_y_mode = self._settings.value("zoom_y_mode", "") if not zoom_y_mode: if self._settings.value("zoom_y_center_on_cursor", False, type=bool): zoom_y_mode = "center_on_cursor" else: zoom_y_mode = "center_on_mouse" selected_uuids, current_uuid = self.plot.selected_items() viewbox_y_range = None if zoom_y_mode == "pin_zero_level": for uuid in selected_uuids: sig, idx = self.plot.signal_by_uuid(uuid) y_pos_val, sig_y_bottom, sig_y_top = self.plot.value_at_cursor(uuid=uuid) if isinstance(y_pos_val, (int, float)): delta_proc = sig_y_top / (sig_y_top - sig_y_bottom) delta = (sig_y_top - sig_y_bottom) * scale end = delta_proc * delta start = end - delta y_range = start, end if uuid == current_uuid: viewbox_y_range = y_range else: sig.y_range = y_range elif zoom_y_mode == "center_on_cursor": for uuid in selected_uuids: sig, idx = self.plot.signal_by_uuid(uuid) y_pos_val, sig_y_bottom, sig_y_top = self.plot.value_at_cursor(uuid=uuid) if isinstance(y_pos_val, (int, float)): delta = (sig_y_top - sig_y_bottom) * scale new_y_range = y_pos_val - delta / 2, y_pos_val + delta / 2 if uuid == current_uuid: viewbox_y_range = new_y_range else: sig.y_range = new_y_range else: for uuid in selected_uuids: sig, idx = self.plot.signal_by_uuid(uuid) y_pos_val, sig_y_bottom, sig_y_top = self.plot.value_at_cursor(uuid=uuid) center = (sig_y_top + sig_y_bottom) / 2 half_range = (sig_y_top - sig_y_bottom) * scale / 2 new_y_range = center - half_range, center + half_range if uuid == current_uuid: viewbox_y_range = new_y_range else: sig.y_range = new_y_range if viewbox_y_range is not None: self.setRange(xRange=None, yRange=viewbox_y_range, padding=0) mask = [False, True] self.sigRangeChangedManually.emit(mask) asammdf-8.5.1/src/asammdf/gui/widgets/vrtt_widget.py000066400000000000000000000027571502633300400225110ustar00rootroot00000000000000import numpy as np from PySide6 import QtWidgets from ..ui.vrtt_widget import Ui_VRTT_Widget class VRTTWidget(Ui_VRTT_Widget, QtWidgets.QWidget): def __init__( self, lower=0, upper=0, text="", conversion=None, mode="text", *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self.text.setText(text) self.lower.setMaximum(np.inf) self.lower.setMinimum(-np.inf) self.lower.setValue(lower) self.upper.setMaximum(np.inf) self.upper.setMinimum(-np.inf) self.upper.setValue(upper) self.conversion = conversion self.mode_switch.currentIndexChanged.connect(self.mode.setCurrentIndex) if mode == "text": self.mode_switch.setCurrentIndex(0) else: self.mode_switch.setCurrentIndex(1) self.conversion_btn.clicked.connect(self.edit_conversion) def edit_conversion(self): dlg = ConversionEditor( f"Raw=[{self.lower.value()}, {self.upper.value()}) referenced", self.conversion, parent=self, ) dlg.exec_() if dlg.pressed_button == "apply": self.conversion = dlg.conversion() def reference(self): if self.mode.currentIndex() == 0: return self.text.text().strip().encode("utf-8") else: return self.conversion from ..dialogs.conversion_editor import ConversionEditor asammdf-8.5.1/src/asammdf/gui/widgets/vtt_widget.py000066400000000000000000000024421502633300400223160ustar00rootroot00000000000000import numpy as np from PySide6 import QtWidgets from ..ui.vtt_widget import Ui_VTT_Widget class VTTWidget(Ui_VTT_Widget, QtWidgets.QWidget): def __init__( self, value=0, text="", conversion=None, mode="text", *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self.text.setText(text) self.value.setMaximum(np.inf) self.value.setMinimum(-np.inf) self.value.setValue(value) self.conversion = conversion self.mode_switch.currentIndexChanged.connect(self.mode.setCurrentIndex) if mode == "text": self.mode_switch.setCurrentIndex(0) else: self.mode_switch.setCurrentIndex(1) self.conversion_btn.clicked.connect(self.edit_conversion) def edit_conversion(self): dlg = ConversionEditor(f"Raw={self.value.value()} referenced", self.conversion, parent=self) dlg.exec_() if dlg.pressed_button == "apply": self.conversion = dlg.conversion() def reference(self): if self.mode.currentIndex() == 0: return self.text.text().strip().encode("utf-8") else: return self.conversion from ..dialogs.conversion_editor import ConversionEditor asammdf-8.5.1/src/asammdf/gui/widgets/xy.py000066400000000000000000000247061502633300400206050ustar00rootroot00000000000000from functools import partial import numpy as np import pyqtgraph as pg from PySide6 import QtCore, QtGui, QtWidgets from ...signal import Signal from ..ui.xy import Ui_XYDisplay ARROW = pg.arrayToQPath(np.array([0.0, -1.0, 0.0, -1.0, 0.0]), np.array([0.0, 1.0, 0.0, -1.0, 0.0]), connect="all") class XY(Ui_XYDisplay, QtWidgets.QWidget): add_channels_request = QtCore.Signal(list) timestamp_changed_signal = QtCore.Signal(object, float) def __init__( self, x_channel=None, y_channel=None, color="#00ff00", *args, **kwargs, ): super().__init__(*args, **kwargs) self.setupUi(self) self.closed = False self.setContentsMargins(0, 0, 0, 0) self._settings = QtCore.QSettings() self.plot = pg.PlotWidget() self.plot_layout.addWidget(self.plot) self.plot.plotItem.scene().sigMouseClicked.connect(self.clicked) self._pen = color # self.curve = self.plot.plot(x=[], y=[], symbol="o", symbolSize=4) self.curve = pg.PlotCurveItem( size=0, pen=self._pen, antialias=False, ) self.arrows = pg.ScatterPlotItem( size=0, pen=self._pen, brush=self._pen, symbolPen=self._pen, symbolBrush=self._pen, symbolSize=4, antialias=False, useCache=False, ) self.plot.addItem(self.curve) self.plot.addItem(self.arrows) self.marker = self.plot.plot( x=[], y=[], symbol="o", symbolPen={"color": self._settings.value("cursor_color", "#ff0000"), "width": 2}, symbolBrush=QtGui.QBrush(), symbolSize=10, ) self.x_search_btn.clicked.connect(partial(self.search, target="x")) self.y_search_btn.clicked.connect(partial(self.search, target="y")) self.x_channel_edit.editingFinished.connect(partial(self.search, target="x", edit=True)) self.y_channel_edit.editingFinished.connect(partial(self.search, target="y", edit=True)) self.show() self.timestamp.valueChanged.connect(self._timestamp_changed) self.timestamp_slider.valueChanged.connect(self._timestamp_slider_changed) self._inhibit = False self._x = None self._x_interp = None self._y = None self._y_interp = None self._timebase = None self._timestamp = None self._requested_channel = None self.set_x(x_channel) self.set_y(y_channel) self.update_plot() def add_new_channels(self, channels): channel = channels[0] if self._requested_channel == "x": self.set_x(channel) elif self._requested_channel == "y": self.set_y(channel) self._requested_channel = None self.update_plot() def clicked(self, event): scene_pos = event.scenePos() pos = self.plot.plotItem.vb.mapSceneToView(scene_pos) x = pos.x() y = pos.y() if self._x is not None and self._y is not None: delta = (self._x_interp.samples - x) ** 2 + (self._y_interp.samples - y) ** 2 idx = np.argmin(delta).flatten()[0] x = self._x_interp.samples[idx : idx + 1] y = self._y_interp.samples[idx : idx + 1] self.marker.setData( x=x, y=y, ) self.timestamp_slider.setValue(idx) def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if key == QtCore.Qt.Key.Key_C and modifiers == QtCore.Qt.KeyboardModifier.NoModifier: event.accept() color = QtWidgets.QColorDialog.getColor(self._pen, parent=self) if color.isValid(): self._pen = color.name() self.update_plot() elif key in (QtCore.Qt.Key.Key_S, QtCore.Qt.Key.Key_F) and modifiers == QtCore.Qt.KeyboardModifier.NoModifier: if self._x and self._y and len(self._y): min_val, max_val = self._y.samples.min(), self._y.samples.max() if min_val == max_val: delta = 1 else: delta = 0.05 * (max_val - min_val) self.plot.setYRange(min_val - delta, max_val + delta, padding=0) elif key == QtCore.Qt.Key.Key_W and modifiers == QtCore.Qt.KeyboardModifier.NoModifier: event.accept() if self._x and self._y and len(self._x): min_val, max_val = self._x.samples.min(), self._x.samples.max() if min_val == max_val: delta = 1 else: delta = 0.05 * (max_val - min_val) self.plot.setXRange(min_val - delta, max_val + delta, padding=0) elif ( key in ( QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right, QtCore.Qt.Key.Key_PageUp, QtCore.Qt.Key.Key_PageDown, QtCore.Qt.Key.Key_Home, QtCore.Qt.Key.Key_End, ) and modifiers == QtCore.Qt.KeyboardModifier.NoModifier ): self.timestamp_slider.keyPressEvent(event) def search(self, *args, edit=False, target=None, **kwargs): self._requested_channel = target if edit: if target == "x": channels = [self.x_channel_edit.text().strip()] else: channels = [self.y_channel_edit.text().strip()] else: channels = [] self.add_channels_request.emit(channels) def set_timestamp(self, stamp, emit=True, spinbox=False): if stamp is None or self._timebase is None or not len(self._timebase): self.marker.setData(x=[], y=[]) else: idx = np.searchsorted(self._timebase, stamp, side="right") - 1 new_stamp = self._timebase[idx] if spinbox: if new_stamp == self._timestamp and stamp > new_stamp: idx += 1 new_stamp = self._timebase[idx] stamp = new_stamp x = self._x_interp.samples[idx : idx + 1] y = self._y_interp.samples[idx : idx + 1] self.marker.setData( x=x, y=y, ) self._inhibit = True self.timestamp_slider.setValue(idx) self.timestamp.setValue(stamp) self._inhibit = False if emit: self.timestamp_changed_signal.emit(self, stamp) self._timestamp = stamp def set_x(self, x): if isinstance(x, Signal): self._x = x self.x_channel_edit.setText(x.name) self.plot.plotItem.setLabel("bottom", x.name, x.unit) else: self._x = None self.x_channel_edit.setText("") self.plot.plotItem.setLabel("bottom", "", "") self.update_plot() self.update_timebase() def set_y(self, y): if isinstance(y, Signal): self._y = y self.y_channel_edit.setText(y.name) self.plot.plotItem.setLabel("left", y.name, y.unit) else: self._y = None self.y_channel_edit.setText("") self.plot.plotItem.setLabel("left", "", "") self.update_plot() self.update_timebase() def _timestamp_changed(self, stamp): if not self._inhibit: self.set_timestamp(stamp, spinbox=True) def _timestamp_slider_changed(self, idx): if not self._inhibit: if not len(self._timebase): return self.set_timestamp(self._timebase[idx]) def to_config(self): config = { "channels": [self._x.name if self._x else "", self._y.name if self._y else ""], "color": self._pen, } return config def update_plot(self): self.plot.plotItem.getAxis("left").setPen(self._pen) self.plot.plotItem.getAxis("left").setTextPen(self._pen) x, y = self._x, self._y if x is None or y is None: self.curve.clear() self.arrows.clear() self._timebase = None elif not len(x) or not len(y): self.curve.clear() self.arrows.clear() self._timebase = None else: self._timebase = t = np.unique(np.concatenate([x.timestamps, y.timestamps])) self._x_interp = x = x.interp(t) self._y_interp = y = y.interp(t) transform = QtGui.QTransform() angles = -np.arctan2(np.diff(y.samples.astype("f8")), np.diff(x.samples.astype("f8"))) * 180 / np.pi exit_spots = [ { "pos": (x.samples[0], y.samples[0]), "symbol": ARROW, "size": 6, "pen": self._pen, "brush": self._pen, } ] for angle, xpos, ypos in zip(angles.tolist(), x.samples[1:].tolist(), y.samples[1:].tolist(), strict=False): transform.reset() angle_rot = transform.rotate(angle) my_rotated_symbol = angle_rot.map(ARROW) exit_spots.append( { "pos": (xpos, ypos), "symbol": my_rotated_symbol, "size": 6, "pen": self._pen, "brush": self._pen, } ) # add the spots to the item self.arrows.setData(exit_spots) self.curve.setData( x=x.samples, y=y.samples, pen=self._pen, antialias=False, ) self.set_timestamp(self._timestamp) def update_timebase(self): if self._timebase is not None and len(self._timebase): count = len(self._timebase) min_, max_ = self._timebase[0], self._timebase[-1] self.timestamp_slider.setRange(0, count - 1) if count >= 2: self.timestamp.setSingleStep(0.5 * np.min(np.diff(self._timebase))) else: min_, max_ = 0.0, 0.0 self.timestamp_slider.setRange(0, 0) self.min_t.setText(f"{min_:.9f}s") self.max_t.setText(f"{max_:.9f}s") self.timestamp.setRange(min_, max_) self.set_timestamp(self._timestamp, emit=False) asammdf-8.5.1/src/asammdf/mdf.py000066400000000000000000007557551502633300400165000ustar00rootroot00000000000000"""Common MDF file format module""" import bz2 from collections.abc import Callable, Hashable, Iterable, Iterator, Sequence from copy import deepcopy import csv from datetime import datetime, timezone from enum import Enum from functools import reduce import gzip from io import BufferedIOBase, BytesIO import logging import mmap import os from pathlib import Path import re from shutil import copy, move import sys from tempfile import gettempdir, mkdtemp from traceback import format_exc from types import TracebackType import typing from typing import Literal, Optional, Union import xml.etree.ElementTree as ET import zipfile from canmatrix import CanMatrix import numpy as np from numpy.typing import NDArray import pandas as pd from pandas import DataFrame from typing_extensions import Any, LiteralString, Never, overload, TypedDict, Unpack from . import tool from .blocks import mdf_v2, mdf_v3, mdf_v4 from .blocks import v2_v3_blocks as v3b from .blocks import v2_v3_constants as v3c from .blocks import v4_blocks as v4b from .blocks import v4_constants as v4c from .blocks.conversion_utils import from_dict from .blocks.cutils import get_channel_raw_bytes_complete from .blocks.mdf_common import ( LastCallInfo, MdfCommonKwargs, MdfKwargs, ) from .blocks.mdf_v4 import BusLoggingMap from .blocks.options import FloatInterpolation, IntegerInterpolation from .blocks.source_utils import Source from .blocks.types import ( BusType, ChannelsType, CompressionType, DbcFileType, EmptyChannelsType, FloatInterpolationModeType, IntInterpolationModeType, RasterType, StrPath, ) from .blocks.utils import ( as_non_byte_sized_signed_int, ChannelsDB, components, csv_bytearray2hex, csv_int2hex, downcast, FileLike, Fragment, is_file_like, load_can_database, matlab_compatible, MDF2_VERSIONS, MDF3_VERSIONS, MDF4_VERSIONS, MdfException, plausible_timestamps, randomized_string, SignalDataBlockInfo, SUPPORTED_VERSIONS, Terminated, THREAD_COUNT, UINT16_u, UINT64_u, UniqueDB, validate_version_argument, VirtualChannelGroup, ) from .blocks.v2_v3_blocks import ChannelExtension from .blocks.v4_blocks import ( AttachmentBlock, EventBlock, FileHistory, FileIdentificationBlock, SourceInformation, ) from .signal import InvalidationArray, Signal try: import fsspec FSSPEF_AVAILABLE = True except: FSSPEF_AVAILABLE = False try: import polars as pl POLARS_AVAILABLE = True except: POLARS_AVAILABLE = False logger = logging.getLogger("asammdf") LOCAL_TIMEZONE = datetime.now(timezone.utc).astimezone().tzinfo target_byte_order = "<=" if sys.byteorder == "little" else ">=" __all__ = ["MDF", "SUPPORTED_VERSIONS"] Version = Literal[v3c.Version2, v3c.Version, v4c.Version] class SearchMode(Enum): plain = "plain" regex = "regex" wildcard = "wildcard" if sys.version_info >= (3, 12): _Quoting = Literal["ALL", "MINIMAL", "NONE", "NONNUMERIC", "NOTNULL", "STRINGS"] else: _Quoting = Literal["ALL", "MINIMAL", "NONE", "NONNUMERIC"] class _ExportKwargs(TypedDict, total=False): single_time_base: bool raster: RasterType | None time_from_zero: bool use_display_names: bool empty_channels: EmptyChannelsType format: Literal["4", "5", "7.3"] oned_as: Literal["row", "column"] reduce_memory_usage: bool compression: LiteralString | bool time_as_date: bool ignore_value2text_conversions: bool raw: bool delimiter: str quotechar: str escapechar: str | None doublequote: bool lineterminator: str quoting: _Quoting add_units: bool class _ConcatenateKwargs(TypedDict, total=False): process_bus_logging: bool use_display_names: bool class _StackKwargs(TypedDict, total=False): process_bus_logging: bool use_display_names: bool def get_measurement_timestamp_and_version( mdf: FileLike | mmap.mmap, ) -> tuple[datetime, str]: id_block = FileIdentificationBlock(address=0, stream=mdf) mdf_version = id_block.mdf_version header_cls: type[v4b.HeaderBlock] | type[v3b.HeaderBlock] if mdf_version >= 400: header_cls = v4b.HeaderBlock else: header_cls = v3b.HeaderBlock header = header_cls(address=64, stream=mdf) main_version, revision = divmod(mdf_version, 100) version = f"{main_version}.{revision}" return header.start_time, version def get_temporary_filename(path: Path = Path("temporary.mf4"), dir: StrPath | None = None) -> Path: folder: StrPath if not dir: folder = gettempdir() else: folder = dir mf4_path = path.with_suffix(".mf4") idx = 0 while True: tmp_path = (Path(folder) / mf4_path.name).with_suffix(f".{idx}.mf4") if not tmp_path.exists(): break else: idx += 1 return tmp_path class MDF: r"""Unified access to MDF v3 and v4 files. Underlying _mdf's attributes and methods are linked to the `MDF` object via `setattr`. This is done to expose them to the user code and for performance considerations. Parameters ---------- name : str | BytesIO | zipfile.ZipFile | bz2.BZ2File | gzip.GzipFile, optional MDF file name (if provided it must be a real file name), file-like object or compressed file opened as a Python object. .. versionchanged:: 6.2.0 Added support for zipfile.ZipFile, bz2.BZ2File and gzip.GzipFile. version : str, default '4.10' MDF file version from ('2.00', '2.10', '2.14', '3.00', '3.10', '3.20', '3.30', '4.00', '4.10', '4.11', '4.20'). This argument is only used for MDF objects created from scratch; for MDF objects created from a file the version is set to file version. channels : iterable, optional Channel names that will be used for selective loading. This can dramatically improve the file loading time. Default is None -> load all channels. .. versionadded:: 6.1.0 .. versionchanged:: 6.3.0 Make the default None. use_display_names : bool, default True For MDF v4 files, parse the XML channel comment to search for the display name; XML parsing is quite expensive so setting this to False can decrease the loading times very much. remove_source_from_channel_names : bool, default False Remove source from channel names ("Speed\XCP3" -> "Speed"). raise_on_multiple_occurrences : bool, default True Raise MdfException when there are multiple channel occurrences in the file and the `get` call is ambiguous. .. versionadded:: 7.0.0 temporary_folder : str | path-like, optional Folder to use for temporary files. .. versionadded:: 7.0.0 process_bus_logging : bool, default True Controls whether the bus processing of MDF v4 files is done when the file is loaded. .. versionadded:: 8.0.0 Examples -------- >>> mdf = MDF(version='3.30') # new MDF object with version 3.30 >>> mdf = MDF('path/to/file.mf4') # MDF loaded from file >>> mdf = MDF(BytesIO(data)) # MDF from file contents >>> mdf = MDF(zipfile.ZipFile('data.zip')) # MDF creating using the first valid MDF from archive >>> mdf = MDF(bz2.BZ2File('path/to/data.bz2', 'rb')) # MDF from bz2 object >>> mdf = MDF(gzip.GzipFile('path/to/data.gzip', 'rb')) # MDF from gzip object """ def __init__( self, name: StrPath | FileLike | zipfile.ZipFile | None = None, version: str | Version = "4.10", channels: list[str] | None = None, **kwargs: Unpack[MdfKwargs], ) -> None: if "callback" in kwargs: kwargs["progress"] = kwargs["callback"] del kwargs["callback"] temporary_folder = kwargs.get("temporary_folder", None) if temporary_folder: try: os.makedirs(temporary_folder, exist_ok=True) except: kwargs["temporary_folder"] = None self._mdf: mdf_v2.MDF2 | mdf_v3.MDF3 | mdf_v4.MDF4 if name: original_name: str | Path | None if is_file_like(name): if isinstance(name, (BytesIO, BufferedIOBase)): original_name = None file_stream = name do_close = False elif isinstance(name, bz2.BZ2File): original_name = Path(name.name) tmp_name = get_temporary_filename(original_name, dir=temporary_folder) tmp_name.write_bytes(name.read()) file_stream = open(tmp_name, "rb") name = tmp_name do_close = True elif isinstance(name, gzip.GzipFile): original_name = Path(name.name) tmp_name = get_temporary_filename(original_name, dir=temporary_folder) tmp_name.write_bytes(name.read()) file_stream = open(tmp_name, "rb") name = tmp_name do_close = True elif FSSPEF_AVAILABLE and isinstance(name, fsspec.spec.AbstractBufferedFile): original_name = "AzureFile" file_stream = name do_close = False else: raise MdfException(f"{type(name)} is not supported as input for the MDF class") elif isinstance(name, zipfile.ZipFile): archive = name files = archive.namelist() for fname in files: if Path(fname).suffix.lower() in (".mdf", ".dat", ".mf4"): original_name = fname break else: raise Exception("invalid zipped MF4: no supported file found in the archive") name = get_temporary_filename(Path(original_name), dir=temporary_folder) tmpdir = mkdtemp() output = archive.extract(fname, tmpdir) move(output, name) file_stream = open(name, "rb") do_close = True else: name = original_name = Path(name) if not name.is_file() or not name.exists(): raise MdfException(f'File "{name}" does not exist') if original_name.suffix.lower() in (".mf4z", ".zip"): name = get_temporary_filename(original_name, dir=temporary_folder) with zipfile.ZipFile(original_name, allowZip64=True) as archive: files = archive.namelist() for fname in files: if Path(fname).suffix.lower() in (".mdf", ".dat", ".mf4"): break else: raise Exception("invalid zipped MF4: no supported file found in the archive") tmpdir = mkdtemp() output = archive.extract(fname, tmpdir) move(output, name) file_stream = open(name, "rb") do_close = True file_stream.seek(0) magic_header = file_stream.read(8) if magic_header.strip() not in (b"MDF", b"UnFinMF"): if do_close: file_stream.close() raise MdfException(f'"{name}" is not a valid ASAM MDF file: magic header is {magic_header!r}') file_stream.seek(8) version = file_stream.read(4).decode("ascii").strip(" \0") if not version: _, version = get_measurement_timestamp_and_version(file_stream) if do_close: file_stream.close() common_kwargs = MdfCommonKwargs({**kwargs, "original_name": original_name, "__internal__": True}) if version in MDF3_VERSIONS: self._mdf = mdf_v3.MDF3(name, channels=channels, **common_kwargs) elif version in MDF4_VERSIONS: self._mdf = mdf_v4.MDF4(name, channels=channels, **common_kwargs) elif version in MDF2_VERSIONS: self._mdf = mdf_v2.MDF2(name, channels=channels, **common_kwargs) else: message = f'"{name}" is not a supported MDF file; "{version}" file version was found' raise MdfException(message) else: common_kwargs = MdfCommonKwargs({**kwargs, "original_name": None, "__internal__": True}) version = validate_version_argument(version) if version in MDF2_VERSIONS: version = typing.cast(v3c.Version2, version) self._mdf = mdf_v2.MDF2(version=version, **common_kwargs) elif version in MDF3_VERSIONS: version = typing.cast(v3c.Version, version) self._mdf = mdf_v3.MDF3(version=version, **common_kwargs) elif version in MDF4_VERSIONS: version = typing.cast(v4c.Version, version) self._mdf = mdf_v4.MDF4(version=version, **common_kwargs) else: message = ( f'"{version}" is not a supported MDF file version; Supported versions are {SUPPORTED_VERSIONS}' ) raise MdfException(message) # we need a backreference to the MDF object to avoid it being garbage # collected in code like this: # MDF(filename).convert('4.10') self._mdf._parent = self def __enter__(self) -> "MDF": return self def __exit__( self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> bool | None: try: self.close() except: print(format_exc()) return None def __del__(self) -> None: try: self.close() except: pass def __lt__(self, other: "MDF") -> bool: if self.header.start_time < other.header.start_time: return True elif self.header.start_time > other.header.start_time: return False else: t_min: list[float] = [] for i, group in enumerate(self.groups): group = typing.cast(mdf_v3.Group | mdf_v4.Group, group) cycles_nr = group.channel_group.cycles_nr if cycles_nr and i in self.masters_db: master_min = self._mdf.get_master(i, record_offset=0, record_count=1) if len(master_min): t_min.append(master_min[0]) other_t_min: list[float] = [] for i, group in enumerate(other.groups): group = typing.cast(mdf_v3.Group | mdf_v4.Group, group) cycles_nr = group.channel_group.cycles_nr if cycles_nr and i in other.masters_db: master_min = other._mdf.get_master(i, record_offset=0, record_count=1) if len(master_min): other_t_min.append(master_min[0]) if not t_min or not other_t_min: return True else: return min(t_min) < min(other_t_min) def _transfer_events(self, other: "MDF") -> None: def get_scopes(event: EventBlock, events: list[EventBlock]) -> list[tuple[int, int] | int]: if event.scopes: return event.scopes else: if event.parent is not None: return get_scopes(events[event.parent], events) elif event.range_start is not None: return get_scopes(events[event.range_start], events) else: return event.scopes if isinstance(other._mdf, mdf_v4.MDF4): for event in other._mdf.events: if isinstance(self._mdf, mdf_v4.MDF4): new_event = deepcopy(event) event_valid = True for i, ref in enumerate(new_event.scopes): if not isinstance(ref, int): dg_cntr, ch_cntr = ref try: self.groups[dg_cntr].channels[ch_cntr] except: event_valid = False else: dg_cntr = ref try: self.groups[dg_cntr] except: event_valid = False # ignore attachments for now for i in range(new_event.attachment_nr): key = f"attachment_{i}_addr" event[key] = 0 if event_valid: self._mdf.events.append(new_event) else: ev_type = event.event_type ev_range = event.range_type ev_base = event.sync_base ev_factor = event.sync_factor timestamp = ev_base * ev_factor try: comment_elem = ET.fromstring(event.comment.replace(' xmlns="http://www.asam.net/mdf/v4"', "")) pre_elem = comment_elem.find(".//pre_trigger_interval") if pre_elem is not None: pre = float(pre_elem.text) if pre_elem.text else 0.0 else: pre = 0.0 post_elem = comment_elem.find(".//post_trigger_interval") if post_elem is not None: post = float(post_elem.text) if post_elem.text else 0.0 else: post = 0.0 tx_elem = comment_elem.find(".//TX") if tx_elem is not None: comment = tx_elem.text if tx_elem.text else "" else: comment = "" except: pre = 0.0 post = 0.0 comment = event.comment if comment: comment += ": " if ev_range == v4c.EVENT_RANGE_TYPE_BEGINNING: comment += "Begin of " elif ev_range == v4c.EVENT_RANGE_TYPE_END: comment += "End of " else: comment += "Single point " if ev_type == v4c.EVENT_TYPE_RECORDING: comment += "recording" elif ev_type == v4c.EVENT_TYPE_RECORDING_INTERRUPT: comment += "recording interrupt" elif ev_type == v4c.EVENT_TYPE_ACQUISITION_INTERRUPT: comment += "acquisition interrupt" elif ev_type == v4c.EVENT_TYPE_START_RECORDING_TRIGGER: comment += "measurement start trigger" elif ev_type == v4c.EVENT_TYPE_STOP_RECORDING_TRIGGER: comment += "measurement stop trigger" elif ev_type == v4c.EVENT_TYPE_TRIGGER: comment += "trigger" else: comment += "marker" scopes = get_scopes(event, other._mdf.events) if scopes: for i, ref in enumerate(scopes): event_valid = True if not isinstance(ref, int): dg_cntr, ch_cntr = ref try: (self.groups[dg_cntr]) except: event_valid = False else: dg_cntr = ref try: (self.groups[dg_cntr]) except: event_valid = False if event_valid: self._mdf.add_trigger( dg_cntr, timestamp, pre_time=pre, post_time=post, comment=comment, ) else: for i, _ in enumerate(self.groups): self._mdf.add_trigger( i, timestamp, pre_time=pre, post_time=post, comment=comment, ) else: for trigger_info in other._mdf.iter_get_triggers(): comment = trigger_info["comment"] timestamp = trigger_info["time"] group = trigger_info["group"] if not isinstance(self._mdf, mdf_v4.MDF4): self._mdf.add_trigger( group, timestamp, pre_time=trigger_info["pre_time"], post_time=trigger_info["post_time"], comment=comment, ) else: if timestamp: ev_type = v4c.EVENT_TYPE_TRIGGER else: ev_type = v4c.EVENT_TYPE_START_RECORDING_TRIGGER event = EventBlock( event_type=ev_type, sync_base=int(timestamp * 10**9), sync_factor=10**-9, scope_0_addr=0, # type: ignore[call-arg] ) event.comment = comment event.scopes.append(group) self._mdf.events.append(event) def _transfer_header_data(self, other: "MDF", message: str = "") -> None: self.header.author = other.header.author self.header.department = other.header.department self.header.project = other.header.project self.header.subject = other.header.subject self.header.comment = other.header.comment if isinstance(self._mdf, mdf_v4.MDF4) and message: fh = FileHistory() fh.comment = f""" {message} {tool.__tool__} {tool.__vendor__} {tool.__version__} """ self._mdf.file_history = [fh] @staticmethod def _transfer_channel_group_data( out_group: v3b.ChannelGroup | v4b.ChannelGroup, source_group: v3b.ChannelGroup | v4b.ChannelGroup ) -> None: if not isinstance(out_group, v4b.ChannelGroup) or not isinstance(source_group, v4b.ChannelGroup): out_group.comment = source_group.comment else: out_group.flags = source_group.flags out_group.path_separator = source_group.path_separator out_group.comment = source_group.comment out_group.acq_name = source_group.acq_name acq_source = source_group.acq_source if acq_source: out_group.acq_source = acq_source.copy() def _transfer_metadata(self, other: "MDF", message: str = "") -> None: self._transfer_events(other) self._transfer_header_data(other, message) def __contains__(self, channel: str) -> bool: """If *'channel name'* in *'mdf file'*""" return channel in self.channels_db def __iter__(self) -> Iterator[Signal]: """Iterate over all the channels found in the file; master channels are skipped from iteration. """ yield from self.iter_channels() def configure( self, *, from_other: Optional["MDF"] = None, read_fragment_size: int | None = None, write_fragment_size: int | None = None, use_display_names: bool | None = None, single_bit_uint_as_bool: bool | None = None, integer_interpolation: IntInterpolationModeType | IntegerInterpolation | None = None, float_interpolation: FloatInterpolationModeType | FloatInterpolation | None = None, raise_on_multiple_occurrences: bool | None = None, temporary_folder: str | None = None, fill_0_for_missing_computation_channels: bool | None = None, ) -> None: """Configure `MDF` parameters. The default values for the options are the following: * read_fragment_size = 256 MB * write_fragment_size = 4 MB * use_display_names = True * single_bit_uint_as_bool = False * integer_interpolation = 0 (repeat previous sample) * float_interpolation = 1 (linear interpolation) * raise_on_multiple_occurrences = True * temporary_folder = "" * fill_0_for_missing_computation_channels = False Parameters ---------- from_other : MDF, optional Copy configuration options from other MDF. .. versionadded:: 6.2.0 read_fragment_size : int, optional Size hint of split data blocks. If the initial size is smaller, then no data list is used. The actual split size depends on the data groups' records size. write_fragment_size : int, optional Size hint of split data blocks. If the initial size is smaller, then no data list is used. The actual split size depends on the data groups' records size. Maximum size is 4 MB to ensure compatibility with CANape. use_display_names : bool, optional Search for display name in the Channel XML comment. single_bit_uint_as_bool : bool, optional Return single bit channels as np.bool arrays. integer_interpolation : int, optional Interpolation mode for integer channels. * 0 - repeat previous sample * 1 - linear interpolation * 2 - hybrid interpolation: channels with integer data type (raw values) that have a conversion that outputs float values will use linear interpolation, otherwise the previous sample is used .. versionchanged:: 6.2.0 Added hybrid interpolation mode. float_interpolation : int, optional Interpolation mode for float channels. * 0 - repeat previous sample * 1 - linear interpolation .. versionadded:: 6.2.0 raise_on_multiple_occurrences : bool, optional Raise MdfException when there are multiple channel occurrences in the file and the `get` call is ambiguous. .. versionadded:: 6.2.0 temporary_folder : str, optional Default folder for temporary files. .. versionadded:: 7.0.0 fill_0_for_missing_computation_channels : bool, optional When a channel required by a computed channel is missing, then fill with 0 values. If False, then the computation will fail and the computed channel will be marked as not existing. .. versionadded:: 7.1.0 """ if from_other is not None: self._mdf._read_fragment_size = from_other._mdf._read_fragment_size self._mdf._write_fragment_size = from_other._mdf._write_fragment_size self._mdf._use_display_names = from_other._mdf._use_display_names self._mdf._single_bit_uint_as_bool = from_other._mdf._single_bit_uint_as_bool self._mdf._integer_interpolation = from_other._mdf._integer_interpolation self._mdf._float_interpolation = from_other._mdf._float_interpolation self._mdf._raise_on_multiple_occurrences = from_other._mdf._raise_on_multiple_occurrences if read_fragment_size is not None: self._mdf._read_fragment_size = int(read_fragment_size) if write_fragment_size is not None: self._mdf._write_fragment_size = min(int(write_fragment_size), 4 * 1024 * 1024) if use_display_names is not None: self._mdf._use_display_names = bool(use_display_names) if single_bit_uint_as_bool is not None: self._mdf._single_bit_uint_as_bool = bool(single_bit_uint_as_bool) if integer_interpolation is not None: self._mdf._integer_interpolation = IntegerInterpolation(integer_interpolation) if float_interpolation is not None: self._mdf._float_interpolation = FloatInterpolation(float_interpolation) if temporary_folder is not None: try: os.makedirs(temporary_folder, exist_ok=True) self._mdf.temporary_folder = temporary_folder except: self._mdf.temporary_folder = None if raise_on_multiple_occurrences is not None: self._mdf._raise_on_multiple_occurrences = bool(raise_on_multiple_occurrences) @property def original_name(self) -> str | Path | None: return self._mdf.original_name @original_name.setter def original_name(self, value: str | Path | None) -> None: self._mdf.original_name = value @property def name(self) -> Path: return self._mdf.name @property def identification(self) -> v3b.FileIdentificationBlock | v4b.FileIdentificationBlock: return self._mdf.identification @property def version(self) -> str: return self._mdf.version @property def header(self) -> v3b.HeaderBlock | v4b.HeaderBlock: return self._mdf.header @property def groups(self) -> list[mdf_v3.Group] | list[mdf_v4.Group]: return self._mdf.groups @property def channels_db(self) -> ChannelsDB: return self._mdf.channels_db @property def masters_db(self) -> dict[int, int]: return self._mdf.masters_db @property def attachments(self) -> list[AttachmentBlock]: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("Attachments are only supported in MDF4 files") return self._mdf.attachments @attachments.setter def attachments(self, attachments_list: list[AttachmentBlock]) -> None: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("Attachments are only supported in MDF4 files") self._mdf.attachments = attachments_list @property def events(self) -> list[EventBlock]: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("Events are only supported in MDF4 files") return self._mdf.events @events.setter def events(self, events_list: list[EventBlock]) -> None: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("Events are only supported in MDF4 files") self._mdf.events = events_list @property def bus_logging_map(self) -> BusLoggingMap: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("Bus logging is only supported in MDF4 files") return self._mdf.bus_logging_map @property def last_call_info(self) -> LastCallInfo: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("last_call_info is only supported in MDF4 files") return self._mdf.last_call_info @property def file_history(self) -> list[FileHistory]: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("file_history is only supported in MDF4 files") return self._mdf.file_history @file_history.setter def file_history(self, file_history_list: list[FileHistory]) -> None: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("file_history is only supported in MDF4 files") self._mdf.file_history = file_history_list @property def virtual_groups(self) -> dict[int, VirtualChannelGroup]: return self._mdf.virtual_groups @virtual_groups.setter def virtual_groups(self, groups: dict[int, VirtualChannelGroup]) -> None: self._mdf.virtual_groups = groups @property def virtual_groups_map(self) -> dict[int, int]: return self._mdf.virtual_groups_map @virtual_groups_map.setter def virtual_groups_map(self, groups_map: dict[int, int]) -> None: self._mdf.virtual_groups_map = groups_map def add_trigger( self, group: int, timestamp: float, pre_time: float = 0, post_time: float = 0, comment: str = "", ) -> None: if isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("add_trigger is only supported in MDF2 and MDF3 files") return self._mdf.add_trigger( group, timestamp, pre_time=pre_time, post_time=post_time, comment=comment, ) def get_invalidation_bits( self, group_index: int, pos_invalidation_bit: int, fragment: Fragment ) -> InvalidationArray: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("get_invalidation_bits is only supported in MDF4 file") return self._mdf.get_invalidation_bits(group_index, pos_invalidation_bit, fragment) @overload def append( self, signals: list[Signal] | Signal, acq_name: str | None = ..., acq_source: Source | None = ..., comment: str = ..., common_timebase: bool = ..., units: dict[str, str] | None = ..., ) -> int: ... @overload def append( self, signals: DataFrame, acq_name: str | None = ..., acq_source: Source | None = ..., comment: str = ..., common_timebase: bool = ..., units: dict[str, str] | None = ..., ) -> None: ... @overload def append( self, signals: list[Signal] | Signal | DataFrame, acq_name: str | None = ..., acq_source: Source | None = ..., comment: str = ..., common_timebase: bool = ..., units: dict[str, str] | None = ..., ) -> int | None: ... def append( self, signals: list[Signal] | Signal | DataFrame, acq_name: str | None = None, acq_source: Source | None = None, comment: str = "Python", common_timebase: bool = False, units: dict[str, str] | None = None, ) -> int | None: return self._mdf.append( signals, acq_name=acq_name, acq_source=acq_source, comment=comment, common_timebase=common_timebase, units=units, ) def extend(self, index: int, signals: Sequence[tuple[NDArray[Any], NDArray[np.bool] | None]]) -> None: return self._mdf.extend(index, signals) def get_channel_name(self, group: int, index: int) -> str: return self._mdf.get_channel_name(group, index) def get_channel_metadata( self, name: str | None = None, group: int | None = None, index: int | None = None ) -> v3b.Channel | v4b.Channel: return self._mdf.get_channel_metadata(name=name, group=group, index=index) def get_channel_unit(self, name: str | None = None, group: int | None = None, index: int | None = None) -> str: return self._mdf.get_channel_unit(name=name, group=group, index=index) def get_channel_comment(self, name: str | None = None, group: int | None = None, index: int | None = None) -> str: return self._mdf.get_channel_comment(name=name, group=group, index=index) def attach( self, data: bytes, file_name: StrPath | None = None, hash_sum: bytes | None = None, comment: str = "", compression: bool = True, mime: str = r"application/octet-stream", embedded: bool = True, password: str | bytes | None = None, ) -> int: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("Attachments are only supported in MDF4 files") return self._mdf.attach( data, file_name=file_name, hash_sum=hash_sum, comment=comment, compression=compression, mime=mime, embedded=embedded, password=password, ) def close(self) -> None: return self._mdf.close() def extract_attachment( self, index: int | None = None, password: str | bytes | None = None ) -> tuple[bytes | str, Path, bytes | str]: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("Attachments are only supported in MDF4 files") return self._mdf.extract_attachment(index=index, password=password) def convert(self, version: str | Version, progress: Any | None = None) -> "MDF": """Convert `MDF` to other version. Parameters ---------- version : str New MDF file version from ('2.00', '2.10', '2.14', '3.00', '3.10', '3.20', '3.30', '4.00', '4.10', '4.11', '4.20'). Returns ------- out : MDF New `MDF` object. """ version = validate_version_argument(version) out = MDF(version=version, **self._mdf._kwargs) out.configure(from_other=self) out.header.start_time = self.header.start_time groups_nr = len(self.virtual_groups) if progress is not None: if callable(progress): progress(0, groups_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr) if progress.stop: raise Terminated # walk through all groups and get all channels for i, virtual_group in enumerate(self.virtual_groups): for idx, sigs in enumerate(self._mdf._yield_selected_signals(virtual_group, version=version)): if idx == 0: sigs = typing.cast(list[Signal], sigs) if sigs: cg = self.groups[virtual_group].channel_group cg_nr = out.append( sigs, common_timebase=True, comment=cg.comment, ) MDF._transfer_channel_group_data(out.groups[cg_nr].channel_group, cg) else: break else: sigs = typing.cast(list[tuple[NDArray[Any], None]], sigs) out.extend(cg_nr, sigs) if progress and progress.stop: raise Terminated if progress is not None: if callable(progress): progress(i + 1, groups_nr) else: progress.signals.setValue.emit(i + 1) progress.signals.setMaximum.emit(groups_nr) if progress.stop: raise Terminated out._transfer_metadata(self, message=f"Converted from {self.name}") return out def cut( self, start: float | None = None, stop: float | None = None, whence: int = 0, version: str | Version | None = None, include_ends: bool = True, time_from_zero: bool = False, progress: Any | None = None, ) -> "MDF": """Cut `MDF`. `start` and `stop` are absolute values or values relative to the first timestamp depending on the `whence` argument. Parameters ---------- start : float, optional Start time; default is None. If None, the start of the measurement is used. stop : float, optional Stop time; default is None. If None, the end of the measurement is used. whence : int, default 0 How to search for the start and stop values. * 0 : absolute * 1 : relative to first timestamp version : str, optional New MDF file version from ('2.00', '2.10', '2.14', '3.00', '3.10', '3.20', '3.30', '4.00', '4.10', '4.11', '4.20'); default is None and in this case the original file version is used. include_ends : bool, default True Include the `start` and `stop` timestamps after cutting the signal. If `start` and `stop` are not found in the original timestamps, then the new samples will be computed using interpolation. time_from_zero : bool, default False Start timestamps from 0s in the cut measurement. Returns ------- out : MDF New `MDF` object. """ if version is None: version = self.version else: version = validate_version_argument(version) out = MDF( version=version, **self._mdf._kwargs, ) integer_interpolation_mode = self._mdf._integer_interpolation float_interpolation_mode = self._mdf._float_interpolation out.configure(from_other=self) if whence == 1: timestamps: list[float] = [] for group in self.virtual_groups: master = self._mdf.get_master(group, record_offset=0, record_count=1) if master.size: timestamps.append(master[0]) if timestamps: first_timestamp = np.amin(timestamps) else: first_timestamp = 0 if start is not None: start += first_timestamp if stop is not None: stop += first_timestamp if time_from_zero: delta = start if start else 0.0 t_epoch = self.header.start_time.timestamp() + delta out.header.start_time = datetime.fromtimestamp(t_epoch) else: delta = 0 out.header.start_time = self.header.start_time groups_nr = len(self.virtual_groups) if progress is not None: if callable(progress): progress(0, groups_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr) # walk through all groups and get all channels for i, (group_index, virtual_group) in enumerate(self.virtual_groups.items()): included_channels = self.included_channels(group_index)[group_index] if not included_channels: continue idx = 0 signals: list[Signal] = [] for j, sigs in enumerate(self._mdf._yield_selected_signals(group_index, groups=included_channels)): if not sigs: break if j == 0: sigs = typing.cast(list[Signal], sigs) master = sigs[0].timestamps signals = sigs else: sigs = typing.cast(list[tuple[NDArray[Any], None]], sigs) master = sigs[0][0] if not len(master): continue needs_cutting = True # check if this fragmement is within the cut interval or # if the cut interval has ended if start is None and stop is None: fragment_start = None fragment_stop = None start_index = 0 stop_index = len(master) needs_cutting = False elif start is None: fragment_start = None start_index = 0 if master[0] > stop: break else: fragment_stop = min(stop, master[-1]) stop_index = np.searchsorted(master, fragment_stop, side="right") if stop_index == len(master): needs_cutting = False elif stop is None: fragment_stop = None if master[-1] < start: continue else: fragment_start = max(start, master[0]) start_index = np.searchsorted(master, fragment_start, side="left") stop_index = len(master) if start_index == 0: needs_cutting = False else: if master[0] > stop: break elif master[-1] < start: continue else: fragment_start = max(start, master[0]) start_index = np.searchsorted(master, fragment_start, side="left") fragment_stop = min(stop, master[-1]) stop_index = np.searchsorted(master, fragment_stop, side="right") if start_index == 0 and stop_index == len(master): needs_cutting = False # update the signal if this is not the first yield if j: sigs = typing.cast(list[tuple[NDArray[Any], None]], sigs) for signal, (samples, invalidation) in zip(signals, sigs[1:], strict=False): signal.samples = samples signal.timestamps = master signal.invalidation_bits = invalidation if needs_cutting: master = ( Signal(master, master, name="_") .cut( fragment_start, fragment_stop, include_ends, integer_interpolation_mode=integer_interpolation_mode, float_interpolation_mode=float_interpolation_mode, ) .timestamps ) if not len(master): continue signals = [ sig.cut( master[0], master[-1], include_ends=include_ends, integer_interpolation_mode=integer_interpolation_mode, float_interpolation_mode=float_interpolation_mode, ) for sig in signals ] if time_from_zero: master = master - delta for sig in signals: sig.timestamps = master if idx == 0: if start: start_ = f"{start}s" else: start_ = "start of measurement" if stop: stop_ = f"{stop}s" else: stop_ = "end of measurement" cg = self.groups[group_index].channel_group cg_nr = out.append( signals, common_timebase=True, comment=cg.comment, ) MDF._transfer_channel_group_data(out.groups[cg_nr].channel_group, cg) else: signals_samples = [(sig.samples, sig.invalidation_bits) for sig in signals] signals_samples.insert(0, (master, None)) out.extend(cg_nr, signals_samples) idx += 1 if progress and progress.stop: raise Terminated # if the cut interval is not found in the measurement # then append a data group with 0 cycles if idx == 0 and signals: for sig in signals: sig.samples = sig.samples[:0] sig.timestamps = sig.timestamps[:0] if sig.invalidation_bits is not None: sig.invalidation_bits = InvalidationArray(sig.invalidation_bits[:0]) if start: start_ = f"{start}s" else: start_ = "start of measurement" if stop: stop_ = f"{stop}s" else: stop_ = "end of measurement" cg = self.groups[group_index].channel_group cg_nr = out.append( signals, common_timebase=True, ) MDF._transfer_channel_group_data(out.groups[cg_nr].channel_group, cg) if progress is not None: if callable(progress): progress(i + 1, groups_nr) else: progress.signals.setValue.emit(i + 1) if progress.stop: print("return terminated") raise Terminated out._transfer_metadata(self, message=f"Cut from {start_} to {stop_}") return out @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., samples_only: Literal[False] = ..., data: tuple[bytes, int, int | None] | Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = 0, record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> Signal: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., *, samples_only: Literal[True], data: tuple[bytes, int, int | None] | Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: Literal[True], record_offset: int = 0, record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> tuple[NDArray[Any], None]: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., *, samples_only: Literal[True], data: tuple[bytes, int, int | None] | Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = 0, record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> tuple[NDArray[Any], NDArray[np.bool] | None]: ... @overload def get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: RasterType | None = ..., samples_only: bool = ..., data: tuple[bytes, int, int | None] | Fragment | None = ..., raw: bool = ..., ignore_invalidation_bits: bool = ..., record_offset: int = 0, record_count: int | None = ..., skip_channel_validation: bool = ..., ) -> Signal | tuple[NDArray[Any], NDArray[np.bool] | None]: ... def get( self, name: str | None = None, group: int | None = None, index: int | None = None, raster: RasterType | None = None, samples_only: bool = False, data: tuple[bytes, int, int | None] | Fragment | None = None, raw: bool = False, ignore_invalidation_bits: bool = False, record_offset: int = 0, record_count: int | None = None, skip_channel_validation: bool = False, ) -> Signal | tuple[NDArray[Any], NDArray[np.bool] | None]: if isinstance(self._mdf, mdf_v4.MDF4): if data is not None and not isinstance(data, Fragment): raise TypeError("'data' must be of type Fragment") return self._mdf.get( name=name, group=group, index=index, raster=raster, samples_only=samples_only, data=data, raw=raw, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=record_count, skip_channel_validation=skip_channel_validation, ) if data is not None and not isinstance(data, tuple): raise TypeError("'data' must be of type tuple[bytes, int, int | None]") return self._mdf.get( name=name, group=group, index=index, raster=raster, samples_only=samples_only, data=data, raw=raw, ignore_invalidation_bits=ignore_invalidation_bits, record_offset=record_offset, record_count=record_count, skip_channel_validation=skip_channel_validation, ) def included_channels( self, index: int | None = None, channels: ChannelsType | None = None, skip_master: bool = True, minimal: bool = True, ) -> dict[int, dict[int, list[int]]]: return self._mdf.included_channels( index=index, channels=channels, skip_master=skip_master, minimal=minimal, ) def reload_header(self) -> None: return self._mdf.reload_header() def get_master( self, index: int, data: tuple[bytes, int, int | None] | Fragment | None = None, record_offset: int = 0, record_count: int | None = None, one_piece: bool = False, ) -> NDArray[Any]: if isinstance(self._mdf, mdf_v4.MDF4): if data and not isinstance(data, Fragment): raise TypeError("'data' must be of type Fragment") return self._mdf.get_master( index, data=data, record_offset=record_offset, record_count=record_count, one_piece=one_piece, ) if data is not None and not isinstance(data, tuple): raise TypeError("'data' must be of type tuple[bytes, int, int | None]") return self._mdf.get_master( index, data=data, record_offset=record_offset, record_count=record_count, one_piece=one_piece, ) def iter_get_triggers(self) -> Iterator[mdf_v3.TriggerInfoDict]: if isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("iter_get_triggers is not supported in MDF4 files") return self._mdf.iter_get_triggers() def info(self) -> dict[str, object]: return self._mdf.info() def get_bus_signal( self, bus: BusType, name: str, database: CanMatrix | StrPath | None = None, ignore_invalidation_bits: bool = False, data: Fragment | None = None, raw: bool = False, ignore_value2text_conversion: bool = True, ) -> Signal: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("get_bus_signal is only supported in MDF4 files") return self._mdf.get_bus_signal( bus, name, database=database, ignore_invalidation_bits=ignore_invalidation_bits, data=data, raw=raw, ignore_value2text_conversion=ignore_value2text_conversion, ) def get_can_signal( self, name: str, database: CanMatrix | StrPath | None = None, ignore_invalidation_bits: bool = False, data: Fragment | None = None, raw: bool = False, ignore_value2text_conversion: bool = True, ) -> Signal: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("get_can_signal is only supported in MDF4 files") return self._mdf.get_can_signal( name, database=database, ignore_invalidation_bits=ignore_invalidation_bits, data=data, raw=raw, ignore_value2text_conversion=ignore_value2text_conversion, ) def get_lin_signal( self, name: str, database: CanMatrix | str | Path | None = None, ignore_invalidation_bits: bool = False, data: Fragment | None = None, raw: bool = False, ignore_value2text_conversion: bool = True, ) -> Signal: if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("get_lin_signal is only supported in MDF4 files") return self._mdf.get_lin_signal( name, database=database, ignore_invalidation_bits=ignore_invalidation_bits, data=data, raw=raw, ignore_value2text_conversion=ignore_value2text_conversion, ) def export( self, fmt: Literal["asc", "csv", "hdf5", "mat", "parquet"], filename: StrPath | None = None, progress: Any | None = None, **kwargs: Unpack[_ExportKwargs], ) -> None: r"""Export `MDF` to other formats. The `MDF` file name is used if available, otherwise the `filename` argument must be provided. The pandas export option was removed. You should use the method `to_dataframe` instead. Parameters ---------- fmt : str Can be one of the following: * `csv` : CSV export that uses the ',' delimiter. This option will generate a new csv file for each data group (_DataGroup_.csv) * `hdf5` : HDF5 file output; each `MDF` data group is mapped to an HDF5 group with the name 'DataGroup_' (where is the index) * `mat` : Matlab .mat version 4, 5 or 7.3 export. If `single_time_base=False`, the channels will be renamed in the mat file to 'D_'. The channel group master will be renamed to 'DM_' (** is the data group index starting from 0) * `parquet` : export to Apache parquet format * `asc` : Vector ASCII format for bus logging .. versionadded:: 7.3.3 filename : str | path-like, optional Export file name. Other Parameters ---------------- single_time_base : bool, default False Resample all channels to common time base. raster : float | array-like | str, optional Time raster for resampling. Valid if `single_time_base` is True. It can be: * a float step value * a channel name whose timestamps will be used as raster (starting with asammdf 5.5.0) * an array (starting with asammdf 5.5.0) See `resample` for examples of using this argument. time_from_zero : bool, default True Adjust time channel to start from 0. use_display_names : bool, default True Use display name instead of standard channel name, if available. empty_channels : {'skip', 'zeros'}, default 'skip' Behaviour for channels without samples. format : {'5', '4', '7.3'}, default '5' Only valid for *mat* export. oned_as : {'row', 'column'}, default 'row' Only valid for *mat* export. reduce_memory_usage : bool, default False Reduce memory usage by converting all float columns to float32 and searching for minimum dtype that can represent the values found in integer columns. compression : str | bool, optional Compression to be used. * for `parquet` : 'GZIP', 'SNAPPY' or 'LZ4' * for `hfd5` : 'gzip', 'lzf' or 'szip' * for `mat` : bool .. versionadded:: 8.1.0 Added LZ4 compression after changing to pyarrow. time_as_date : bool, default False Export time as local timezone datetime; only valid for CSV export. .. versionadded:: 5.8.0 ignore_value2text_conversions : bool, default False Valid only for the channels that have value to text conversions and if `raw=False`. If this is True, then the raw numeric values will be used, and the conversion will not be applied. .. versionadded:: 5.8.0 raw : bool, default False Export all channels using the raw values. .. versionadded:: 6.0.0 delimiter : str, default ',' Only valid for CSV: see cpython documentation for csv.Dialect.delimiter. .. versionadded:: 6.2.0 doublequote : bool, default True Only valid for CSV: see cpython documentation for csv.Dialect.doublequote. .. versionadded:: 6.2.0 escapechar : str, default '"' Only valid for CSV: see cpython documentation for csv.Dialect.escapechar. .. versionadded:: 6.2.0 lineterminator : str, default '\\r\\n' Only valid for CSV: see cpython documentation for csv.Dialect.lineterminator. .. versionadded:: 6.2.0 quotechar : str, default '"' Only valid for CSV: see cpython documentation for csv.Dialect.quotechar. .. versionadded:: 6.2.0 quoting : str, default 'MINIMAL' Only valid for CSV: see cpython documentation for csv.Dialect.quoting. Use the last part of the quoting constant name. .. versionadded:: 6.2.0 add_units : bool, default False Only valid for CSV: add the channel units on the second row of the CSV file. .. versionadded:: 7.1.0 """ header_items = ( "date", "time", "author_field", "department_field", "project_field", "subject_field", ) fmt = typing.cast(Literal["asc", "csv", "hdf5", "mat", "parquet"], fmt.lower()) if filename is None: message = "Must specify filename for export if MDF was created without a file name" logger.warning(message) return None single_time_base = kwargs.get("single_time_base", False) raster = kwargs.get("raster", None) time_from_zero = kwargs.get("time_from_zero", True) use_display_names = kwargs.get("use_display_names", True) empty_channels = kwargs.get("empty_channels", "skip") format = kwargs.get("format", "5") oned_as = kwargs.get("oned_as", "row") reduce_memory_usage = kwargs.get("reduce_memory_usage", False) compression = kwargs.get("compression") time_as_date = kwargs.get("time_as_date", False) ignore_value2text_conversions = kwargs.get("ignore_value2text_conversions", False) raw = bool(kwargs.get("raw", False)) if isinstance(compression, str) and compression.lower() == "snappy": try: import snappy # noqa: F401 except ImportError: logger.warning("snappy compressor is not installed; compression will be set to gzip") compression = "gzip" filename = Path(filename) if filename else self.name if fmt == "parquet": try: import pyarrow as pa from pyarrow.parquet import write_table as write_parquet except ImportError: logger.warning("pyarrow not found; export to parquet is unavailable") return None elif fmt == "hdf5": try: from h5py import File as HDF5 except ImportError: logger.warning("h5py not found; export to HDF5 is unavailable") return None elif fmt == "mat": if format == "7.3": try: from hdf5storage import savemat except ImportError: logger.warning("hdf5storage not found; export to mat v7.3 is unavailable") return None else: try: from scipy.io import savemat except ImportError: logger.warning("scipy not found; export to mat v4 and v5 is unavailable") return None elif fmt not in ("csv", "asc"): raise MdfException(f"Export to {fmt} is not implemented") if progress is not None: if callable(progress): progress(0, 100) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(100) if progress.stop: raise Terminated if fmt == "asc": self._asc_export(filename.with_suffix(".asc")) return None if single_time_base or fmt == "parquet": df = self.to_dataframe( raster=raster, time_from_zero=time_from_zero, use_display_names=use_display_names, empty_channels=empty_channels, reduce_memory_usage=reduce_memory_usage, ignore_value2text_conversions=ignore_value2text_conversions, raw=raw, numeric_1D_only=fmt == "parquet", ) units: dict[Hashable, str] = {} comments: dict[Hashable, str] = {} used_names = UniqueDB() groups_nr = len(self.groups) if progress is not None: if callable(progress): progress(0, groups_nr * 2) else: progress.signals.setMaximum.emit(groups_nr * 2) if progress.stop: raise Terminated for i, grp in enumerate(self.groups): grp = typing.cast(mdf_v3.Group | mdf_v4.Group, grp) if progress is not None and progress.stop: raise Terminated for ch in grp.channels: if use_display_names: channel_name = list(ch.display_names)[0] if ch.display_names else ch.name else: channel_name = ch.name channel_name = used_names.get_unique_name(channel_name) if hasattr(ch, "unit"): unit = ch.unit if ch.conversion: unit = unit or ch.conversion.unit else: unit = "" comment = ch.comment units[channel_name] = unit comments[channel_name] = comment if progress is not None: if callable(progress): progress(i + 1, groups_nr * 2) else: progress.signals.setValue.emit(i + 1) if progress.stop: raise Terminated if fmt == "hdf5": filename = filename.with_suffix(".hdf") if single_time_base: with HDF5(str(filename), "w") as hdf: # header information group = hdf.create_group(str(filename)) if self.version in MDF2_VERSIONS + MDF3_VERSIONS: for item in header_items: group.attrs[item] = getattr(self.header, item).replace(b"\0", b"") # save each data group in a HDF5 group called # "DataGroup_" with the index starting from 1 # each HDF5 group will have a string attribute "master" # that will hold the name of the master channel count = len(df.columns) if progress is not None: if callable(progress): progress(0, count * 2) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(count * 2) if progress.stop: raise Terminated samples: NDArray[Any] | pd.Series[Any] for i, channel in enumerate(df): samples = df[channel] unit = units.get(channel, "") comment = comments.get(channel, "") if samples.dtype.kind == "O": if isinstance(samples[0], np.ndarray): samples = np.vstack(list(samples)) else: continue if compression: dataset = group.create_dataset(channel, data=samples, compression=compression) else: dataset = group.create_dataset(channel, data=samples) unit = unit.replace("\0", "") if unit: dataset.attrs["unit"] = unit comment = comment.replace("\0", "") if comment: dataset.attrs["comment"] = comment if progress is not None: if callable(progress): progress(i + 1, count * 2) else: progress.signals.setValue.emit(i + 1) if progress.stop: raise Terminated else: with HDF5(str(filename), "w") as hdf: # header information group = hdf.create_group(str(filename)) if self.version in MDF2_VERSIONS + MDF3_VERSIONS: for item in header_items: group.attrs[item] = getattr(self.header, item).replace(b"\0", b"") # save each data group in a HDF5 group called # "DataGroup_" with the index starting from 1 # each HDF5 group will have a string attribute "master" # that will hold the name of the master channel groups_nr = len(self.virtual_groups) if progress is not None: if callable(progress): progress(0, groups_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr) if progress.stop: raise Terminated for i, (group_index, virtual_group) in enumerate(self.virtual_groups.items()): included_channels = self.included_channels(group_index)[group_index] if not included_channels: continue unique_names = UniqueDB() if progress is not None and progress.stop: raise Terminated if len(virtual_group.groups) == 1: comment = self.groups[virtual_group.groups[0]].channel_group.comment else: comment = "Virtual group i" group_name = r"/" + f"ChannelGroup_{i}" group = hdf.create_group(group_name) group.attrs["comment"] = comment master_index = self.masters_db.get(group_index, -1) if master_index >= 0: group.attrs["master"] = self.groups[group_index].channels[master_index].name master = self._mdf.get(group.attrs["master"], group_index) if reduce_memory_usage: master.timestamps = downcast(master.timestamps) if compression: dataset = group.create_dataset( group.attrs["master"], data=master.timestamps, compression=compression, ) else: dataset = group.create_dataset( group.attrs["master"], data=master.timestamps, dtype=master.timestamps.dtype, ) unit = master.unit.replace("\0", "") if unit: dataset.attrs["unit"] = unit comment = master.comment.replace("\0", "") if comment: dataset.attrs["comment"] = comment channels = [ (None, gp_index, ch_index) for gp_index, channel_indexes in included_channels.items() for ch_index in channel_indexes ] if not channels: continue signals = self.select(channels, raw=raw) for j, sig in enumerate(signals): if use_display_names: name = list(sig.display_names)[0] if sig.display_names else sig.name else: name = sig.name name = name.replace("\\", "_").replace("/", "_") name = unique_names.get_unique_name(name) if reduce_memory_usage: sig.samples = downcast(sig.samples) if compression: dataset = group.create_dataset(name, data=sig.samples, compression=compression) else: dataset = group.create_dataset(name, data=sig.samples, dtype=sig.samples.dtype) unit = sig.unit.replace("\0", "") if unit: dataset.attrs["unit"] = unit comment = sig.comment.replace("\0", "") if comment: dataset.attrs["comment"] = comment if progress is not None: if callable(progress): progress(i + 1, groups_nr) else: progress.signals.setValue.emit(i + 1) if progress.stop: raise Terminated elif fmt == "csv": delimiter = kwargs.get("delimiter", ",")[0] if delimiter == "\\t": delimiter = "\t" doublequote = kwargs.get("doublequote", True) lineterminator = kwargs.get("lineterminator", "\r\n") quotechar = kwargs.get("quotechar", '"')[0] quoting_name = kwargs.get("quoting", "MINIMAL").upper() quoting: Literal[0, 1, 2, 3, 4, 5] = getattr(csv, f"QUOTE_{quoting_name}") escapechar = kwargs.get("escapechar", '"') if escapechar is not None: escapechar = escapechar[0] if single_time_base: filename = filename.with_suffix(".csv") message = f'Writing csv export to file "{filename}"' logger.info(message) if time_as_date: index = ( pd.to_datetime(df.index + self.header.start_time.timestamp(), unit="s") .tz_localize("UTC") .tz_convert(LOCAL_TIMEZONE) .astype(str) ) df.index = index df.index.name = "timestamps" units["timestamps"] = "" else: units["timestamps"] = "s" if hasattr(self, "can_logging_db") and self.can_logging_db: dropped = {} for name_ in df.columns: if name_.endswith("CAN_DataFrame.ID"): dropped[name_] = pd.Series( csv_int2hex(df[name_].astype(np.dtype("\\/:"?*|': comment = comment.replace(char, "_") group_csv_name = filename.parent / f"{filename.stem}.ChannelGroup_{i}_{comment}.csv" else: group_csv_name = filename.parent / f"{filename.stem}.ChannelGroup_{i}.csv" df = self.get_group( group_index, raster=raster, time_from_zero=time_from_zero, use_display_names=use_display_names, reduce_memory_usage=reduce_memory_usage, ignore_value2text_conversions=ignore_value2text_conversions, raw=raw, ) if add_units: units = {} used_names = UniqueDB() for gp_index, channel_indexes in self.included_channels(group_index)[group_index].items(): for ch_index in channel_indexes: ch = self.groups[gp_index].channels[ch_index] if use_display_names: channel_name = list(ch.display_names)[0] if ch.display_names else ch.name else: channel_name = ch.name channel_name = used_names.get_unique_name(channel_name) if hasattr(ch, "unit"): unit = ch.unit if ch.conversion: unit = unit or ch.conversion.unit else: unit = "" units[channel_name] = unit else: units = {} if time_as_date: index = ( pd.to_datetime(df.index + self.header.start_time.timestamp(), unit="s") .tz_localize("UTC") .tz_convert(LOCAL_TIMEZONE) .astype(str) ) df.index = index df.index.name = "timestamps" units["timestamps"] = "" else: units["timestamps"] = "s" with open(group_csv_name, "w", newline="") as csvfile: writer = csv.writer( csvfile, delimiter=delimiter, quotechar=quotechar, escapechar=escapechar, doublequote=doublequote, lineterminator=lineterminator, quoting=quoting, ) if hasattr(self, "can_logging_db") and self.can_logging_db: dropped = {} for name_ in df.columns: if name_.endswith("CAN_DataFrame.ID"): dropped[name_] = pd.Series( csv_int2hex(df[name_] & 0x1FFFFFFF), index=df.index, ) elif name_.endswith("CAN_DataFrame.DataBytes"): dropped[name_] = pd.Series(csv_bytearray2hex(df[name_]), index=df.index) df = df.drop(columns=list(dropped)) for name_, s in dropped.items(): df[name_] = s names_row = [df.index.name, *df.columns] writer.writerow(names_row) if add_units: units_row = [units[name] for name in names_row] writer.writerow(units_row) if reduce_memory_usage: vals = [df.index, *(df[name] for name in df)] else: vals = [ df.index.to_list(), *(df[name].to_list() for name in df), ] for i, row in enumerate(zip(*vals, strict=False)): writer.writerow(row) if progress is not None: if callable(progress): progress(i + 1, gp_count) else: progress.signals.setValue.emit(i + 1) if progress.stop: raise Terminated elif fmt == "mat": filename = filename.with_suffix(".mat") if not single_time_base: def decompose(samples: NDArray[Any]) -> dict[str, NDArray[Any]]: dct: dict[str, NDArray[Any]] = {} for name in samples.dtype.names or (): vals = samples[name] if vals.dtype.names: dct.update(decompose(vals)) else: dct[name] = vals return dct mdict: dict[str, NDArray[Any]] = {} master_name_template = "DGM{}_{}" channel_name_template = "DG{}_{}" used_names = UniqueDB() groups_nr = len(self.virtual_groups) if progress is not None: if callable(progress): progress(0, groups_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr + 1) if progress.stop: raise Terminated for i, (group_index, virtual_group) in enumerate(self.virtual_groups.items()): if progress is not None and progress.stop: raise Terminated included_channels = self.included_channels(group_index)[group_index] if not included_channels: continue channels = [ (None, gp_index, ch_index) for gp_index, channel_indexes in included_channels.items() for ch_index in channel_indexes ] if not channels: continue signals = self.select( channels, ignore_value2text_conversions=ignore_value2text_conversions, raw=raw, ) master = signals[0].copy() master.samples = master.timestamps signals.insert(0, master) for j, sig in enumerate(signals): if j == 0: channel_name = master_name_template.format(i, "timestamps") else: if use_display_names: channel_name = list(sig.display_names)[0] if sig.display_names else sig.name else: channel_name = sig.name channel_name = channel_name_template.format(i, channel_name) channel_name = matlab_compatible(channel_name) channel_name = used_names.get_unique_name(channel_name) if names := sig.samples.dtype.names: sig.samples.dtype.names = tuple(matlab_compatible(name) for name in names) sigs = decompose(sig.samples) sigs = { channel_name_template.format(i, channel_name): _v for channel_name, _v in sigs.items() } mdict.update(sigs) else: mdict[channel_name] = sig.samples if progress is not None: if callable(progress): progress(i + 1, groups_nr) else: progress.signals.setValue.emit(i + 1) if progress.stop: raise Terminated else: used_names = UniqueDB() mdict = {} count = len(df.columns) if progress is not None: if callable(progress): progress(0, count) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(count) if progress.stop: raise Terminated for i, name in enumerate(df.columns): channel_name = matlab_compatible(name) channel_name = used_names.get_unique_name(channel_name) mdict[channel_name] = df[name].to_numpy() if hasattr(mdict[channel_name].dtype, "categories"): mdict[channel_name] = np.array(mdict[channel_name], dtype="S") if progress is not None: if callable(progress): progress(i + 1, groups_nr) else: progress.signals.setValue.emit(i + 1) progress.signals.setMaximum.emit(count) if progress.stop: raise Terminated mdict["timestamps"] = df.index.values if progress is not None: if callable(progress): progress(80, 100) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(100) progress.signals.setValue.emit(80) if progress.stop: raise Terminated if format == "7.3": savemat( str(filename), mdict, long_field_names=True, format="7.3", delete_unused_variables=False, oned_as=oned_as, structured_numpy_ndarray_as_struct=True, store_python_metadata=False, ) else: savemat( str(filename), mdict, long_field_names=True, oned_as=oned_as, do_compression=bool(compression), ) if progress is not None: if callable(progress): progress(100, 100) else: progress.signals.setValue.emit(100) if progress.stop: raise Terminated elif fmt == "parquet": filename = filename.with_suffix(".parquet") table = pa.table(df) if compression: write_parquet(table, filename, compression=compression) # type: ignore[arg-type] else: write_parquet(table, filename) else: message = 'Unsupported export type "{}". Please select "csv", "excel", "hdf5", "mat" or "pandas"' message.format(fmt) logger.warning(message) return None def filter( self, channels: ChannelsType, version: str | Version | None = None, progress: Any | None = None, ) -> "MDF": """Return new `MDF` object that contains only the channels listed in the `channels` argument. Parameters ---------- channels : list List of items to be selected; each item can be: * a channel name string * (channel name, group index, channel index) list or tuple * (channel name, group index) list or tuple * (None, group index, channel index) list or tuple version : str, optional New MDF file version from ('2.00', '2.10', '2.14', '3.00', '3.10', '3.20', '3.30', '4.00', '4.10', '4.11', '4.20'); default is None and in this case the original file version is used. Returns ------- mdf : MDF New `MDF` object. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> t = np.arange(5) >>> s = np.ones(5) >>> mdf = MDF() >>> mdf.configure(raise_on_multiple_occurrences=False) >>> for i in range(4): ... sigs = [Signal(s * (i * 10 + j), t, name='SIG') for j in range(1, 4)] ... mdf.append(sigs) Select channel "SIG" (the first occurrence, which is group 0 index 1), channel "SIG" from group 3 index 1, channel "SIG" from group 2 (the first occurrence, which is index 1), and channel from group 1 index 2. >>> filtered = mdf.filter(['SIG', ('SIG', 3, 1), ['SIG', 2], (None, 1, 2)]) >>> for gp_nr, ch_nr in filtered.channels_db['SIG']: ... print(filtered.get(group=gp_nr, index=ch_nr)) """ if version is None: version = self.version else: version = validate_version_argument(version) _raise_on_multiple_occurrences = self._mdf._raise_on_multiple_occurrences self._mdf._raise_on_multiple_occurrences = False names_map = {} for item in channels: name: str | None if isinstance(item, str): entry = self._mdf._validate_channel_selection(item) name = item else: if name := item[0]: entry = self._mdf._validate_channel_selection(*item) else: continue names_map[entry] = name self._mdf._raise_on_multiple_occurrences = _raise_on_multiple_occurrences # group channels by group index gps = self.included_channels(channels=channels) mdf = MDF( version=version, **self._mdf._kwargs, ) mdf.configure(from_other=self) mdf.header.start_time = self.header.start_time groups_nr = len(gps) if progress is not None: if callable(progress): progress(0, groups_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr) if progress.stop: raise Terminated for i, (group_index, groups) in enumerate(gps.items()): for idx, sigs in enumerate(self._mdf._yield_selected_signals(group_index, groups=groups, version=version)): if not sigs: break if idx == 0: sigs = typing.cast(list[Signal], sigs) if sigs: for sig in sigs: entry = sig.group_index, sig.channel_index if entry in names_map: sig.name = names_map[entry] cg = self.groups[group_index].channel_group cg_nr = mdf.append( sigs, common_timebase=True, comment=cg.comment, acq_name=getattr(cg, "acq_name", None), acq_source=getattr(cg, "acq_source", None), ) MDF._transfer_channel_group_data(mdf.groups[cg_nr].channel_group, cg) else: break else: sigs = typing.cast(list[tuple[NDArray[Any], None]], sigs) mdf.extend(cg_nr, sigs) if progress and progress.stop: raise Terminated if progress is not None: if callable(progress): progress(i + 1, groups_nr) else: progress.signals.setValue.emit(i + 1) if progress.stop: raise Terminated mdf._transfer_metadata(self, message=f"Filtered from {self.name}") return mdf @overload def iter_get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: float | None = ..., samples_only: Literal[False] = ..., raw: bool = ..., ) -> Iterator[Signal]: ... @overload def iter_get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: float | None = ..., *, samples_only: Literal[True], raw: bool = ..., ) -> Iterator[tuple[NDArray[Any], NDArray[Any] | None]]: ... @overload def iter_get( self, name: str | None = ..., group: int | None = ..., index: int | None = ..., raster: float | None = ..., samples_only: bool = ..., raw: bool = ..., ) -> Iterator[Signal] | Iterator[tuple[NDArray[Any], NDArray[Any] | None]]: ... def iter_get( self, name: str | None = None, group: int | None = None, index: int | None = None, raster: float | None = None, samples_only: bool = False, raw: bool = False, ) -> Iterator[Signal] | Iterator[tuple[NDArray[Any], NDArray[Any] | None]]: """Iterator over a channel. This is usefull in case of large files with a small number of channels. If the `raster` keyword argument is not None, the output is interpolated accordingly. Parameters ---------- name : str, optional Name of channel. group : int, optional 0-based group index. index : int, optional 0-based channel index. raster : float, optional Time raster in seconds. samples_only : bool, default False If True, return only the channel samples as np.ndarray; if False, return a `Signal` object. raw : bool, default False Return channel samples without applying the conversion rule. """ gp_nr, ch_nr = self._mdf._validate_channel_selection(name, group, index) grp = self.groups[gp_nr] data = self._mdf._load_data(grp) # type: ignore[arg-type] for fragment in data: yield self.get( group=gp_nr, index=ch_nr, raster=raster, samples_only=samples_only, ignore_invalidation_bits=samples_only, data=fragment, raw=raw, ) @staticmethod def concatenate( files: Sequence[Union["MDF", FileLike, StrPath]], version: str | Version = "4.10", sync: bool = True, add_samples_origin: bool = False, direct_timestamp_continuation: bool = False, progress: Any | None = None, **kwargs: Unpack[_ConcatenateKwargs], ) -> "MDF": """Concatenate several files. The files must have the same internal structure (same number of groups, and same channels in each group). The order of the input files is always preserved, only the samples' timestamps are influenced by the `sync` argument. Parameters ---------- files : list | tuple List of MDF file names or `MDF`, zipfile.ZipFile, bz2.BZ2File or gzip.GzipFile instances. .. versionchanged:: 6.2.0 Added support for zipfile.ZipFile, bz2.BZ2File and gzip.GzipFile. version : str, default '4.10' Merged file version. sync : bool, default True Sync the files based on the start of measurement. The order of the input files is preserved, only the samples' timestamps are influenced by this argument. add_samples_origin : bool, default False Option to create a new "__samples_origin" channel that will hold the index of the measurement from where each timestamp originated. direct_timestamp_continuation : bool, default False The timestamps from the next file will be added right after the last timestamp from the previous file. .. versionadded:: 6.0.0 use_display_names : bool, default False Use display name instead of standard channel name, if available. process_bus_logging : bool, default True Controls whether the bus processing of MDF v4 files is done when the file is loaded. .. versionadded:: 8.1.0 Returns ------- concatenated : MDF New `MDF` object with concatenated channels. Raises ------ MdfException If there are inconsistencies between the files. Examples -------- >>> conc = MDF.concatenate( [ 'path/to/file.mf4', MDF(BytesIO(data)), MDF(zipfile.ZipFile('data.zip')), MDF(bz2.BZ2File('path/to/data.bz2', 'rb')), MDF(gzip.GzipFile('path/to/data.gzip', 'rb')), ], version='4.00', sync=False, ) """ if not files: raise MdfException("No files given for merge") if progress is not None: if callable(progress): progress(0, 100) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(100) progress.signals.setWindowTitle.emit("Concatenating measurements") if progress.stop: raise Terminated mdf_nr = len(files) use_display_names = kwargs.get("use_display_names", False) input_types = [isinstance(mdf, MDF) for mdf in files] versions: list[str] = [] if sync: start_times: list[datetime] = [] for file in files: if isinstance(file, MDF): start_times.append(file.header.start_time) versions.append(file.version) else: if is_file_like(file): ts, version = get_measurement_timestamp_and_version(file) start_times.append(ts) versions.append(version) else: with open(file, "rb") as bytes_io: ts, version = get_measurement_timestamp_and_version(bytes_io) start_times.append(ts) versions.append(version) try: oldest = min(start_times) except TypeError: start_times = [timestamp.astimezone(timezone.utc) for timestamp in start_times] oldest = min(start_times) offsets = [(timestamp - oldest).total_seconds() for timestamp in start_times] offsets = [max(0, offset) for offset in offsets] else: file = files[0] if isinstance(file, MDF): timestamp = file.header.start_time version = file.version else: if is_file_like(file): timestamp, version = get_measurement_timestamp_and_version(file) else: with open(file, "rb") as bytes_io: timestamp, version = get_measurement_timestamp_and_version(bytes_io) oldest = timestamp versions.append(version) offsets = [0 for _ in files] included_channel_names: list[list[str]] = [] cg_map: dict[int, int] = {} if add_samples_origin: dict_conversion: dict[str, object] = {} for i, file in enumerate(files): dict_conversion[f"val_{i}"] = i dict_conversion[f"text_{i}"] = str(file._mdf.original_name if isinstance(file, MDF) else str(file)) origin_conversion = from_dict(dict_conversion) for mdf_index, (offset, file) in enumerate(zip(offsets, files, strict=False)): if not isinstance(file, MDF): mdf = MDF(file, use_display_names=use_display_names) close = True else: mdf = file close = False if progress is not None and not callable(progress): progress.signals.setLabelText.emit( f"Concatenating the file {mdf_index + 1} of {mdf_nr}\n{mdf._mdf.original_name}" ) if mdf_index == 0: version = validate_version_argument(version) first_version = mdf.version kwargs = dict(mdf._mdf._kwargs) # type: ignore[assignment] merged = MDF( version=version, **mdf._mdf._kwargs.copy(), ) merged.configure(from_other=mdf) merged.header.start_time = oldest reorder_channel_groups = False cg_translations: dict[int, int | None] = {} vlsd_max_length: dict[tuple[int, str], int] = {} if mdf_index == 0: last_timestamps = [None for gp in mdf.virtual_groups] groups_nr = len(last_timestamps) first_mdf = mdf if progress is not None: if callable(progress): progress(0, groups_nr * mdf_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr * mdf_nr) if progress.stop: raise Terminated if isinstance(first_mdf._mdf, mdf_v4.MDF4): w_mdf = first_mdf vlds_channels: list[tuple[str, int, int]] = [] for _gp_idx, _gp in enumerate(first_mdf._mdf.groups): for _ch_idx, _ch in enumerate(_gp.channels): if _ch.channel_type == v4c.CHANNEL_TYPE_VLSD: vlds_channels.append((_ch.name, _gp_idx, _ch_idx)) vlsd_max_length[(_gp_idx, _ch.name)] = 0 if vlsd_max_length: for i, _file in enumerate(files): if not isinstance(_file, MDF): _close = True _file = MDF(_file) else: _close = False _file._mdf.determine_max_vlsd_sample_size.cache_clear() for _ch_name, _gp_idx, _ch_idx in vlds_channels: key = (_gp_idx, _ch_name) for _second_gp_idx, _second_ch_idx in w_mdf.whereis(_ch_name): if _second_gp_idx == _gp_idx: vlsd_max_length[key] = max( vlsd_max_length[key], _file._mdf.determine_max_vlsd_sample_size(_second_gp_idx, _second_ch_idx), ) break else: raise MdfException( f"internal structure of file {i} is different; different channels" ) if _close: _file.close() else: if len(mdf.virtual_groups) != groups_nr: raise MdfException( f"internal structure of file <{mdf.name}> is different; different channel groups count" ) else: cg_translations = dict.fromkeys(range(groups_nr)) make_translation = False # check if the order of the channel groups is the same for i, group_index in enumerate(mdf.virtual_groups): included_channels = mdf.included_channels(group_index)[group_index] names = [ mdf.groups[gp_index].channels[ch_index].name for gp_index, channels in included_channels.items() for ch_index in channels ] if names != included_channel_names[i]: if sorted(names) != sorted(included_channel_names[i]): make_translation = reorder_channel_groups = True break # Make a channel group translation dictionary if the order is different if make_translation: first_mdf._mdf = typing.cast(mdf_v4.MDF4, first_mdf._mdf) mdf._mdf = typing.cast(mdf_v4.MDF4, mdf._mdf) for i, org_group in enumerate(first_mdf._mdf.groups): org_group_source = org_group.channel_group.acq_source for j, new_group in enumerate(mdf._mdf.groups): new_group_source = new_group.channel_group.acq_source if ( new_group.channel_group.acq_name == org_group.channel_group.acq_name and (new_group_source and org_group_source) and new_group_source.name == org_group_source.name and new_group_source.path == org_group_source.path and new_group.channel_group.samples_byte_nr == org_group.channel_group.samples_byte_nr ): new_included_channels = mdf.included_channels(j)[j] new_names = [ mdf.groups[gp_index].channels[ch_index].name for gp_index, channels in new_included_channels.items() for ch_index in channels ] if sorted(new_names) == sorted(included_channel_names[i]): cg_translations[i] = j break for i, group_index in enumerate(mdf.virtual_groups): # save original group index for extension # replace with the translated group index if reorder_channel_groups: cg_trans = typing.cast(dict[int, int], cg_translations) origin_gp_idx = group_index group_index = cg_trans[group_index] included_channels = mdf.included_channels(group_index)[group_index] if mdf_index == 0: included_channel_names.append( [ mdf.groups[gp_index].channels[ch_index].name for gp_index, channels in included_channels.items() for ch_index in channels ] ) different_channel_order = False else: names = [ mdf.groups[gp_index].channels[ch_index].name for gp_index, channels in included_channels.items() for ch_index in channels ] different_channel_order = False if names != included_channel_names[i]: if sorted(names) != sorted(included_channel_names[i]): raise MdfException( f"internal structure of file {mdf_index} is different; different channels" ) else: original_names = included_channel_names[i] different_channel_order = True remap = [original_names.index(name) for name in names] if not included_channels: continue last_timestamp = last_timestamps[i] first_timestamp = None original_first_timestamp = None mdf._mdf.vlsd_max_length.clear() mdf._mdf.vlsd_max_length.update(vlsd_max_length) for idx, signals in enumerate(mdf._mdf._yield_selected_signals(group_index, groups=included_channels)): if not signals: break if mdf_index == 0 and idx == 0: signals = typing.cast(list[Signal], signals) first_signal = signals[0] if len(first_signal): if offset > 0: timestamps = first_signal.timestamps + offset for sig in signals: sig.timestamps = timestamps last_timestamp = first_signal.timestamps[-1] first_timestamp = first_signal.timestamps[0] original_first_timestamp = first_timestamp if add_samples_origin: signals.append( Signal( samples=np.ones(len(first_signal), dtype=" 0: master = master + offset _copied = True if last_timestamp is None: last_timestamp = master[-1] else: if last_timestamp >= master[0] or direct_timestamp_continuation: if len(master) >= 2: delta = master[1] - master[0] else: delta = 0.001 if _copied: master -= master[0] else: master = master - master[0] _copied = True master += last_timestamp + delta last_timestamp = master[-1] signals_samples[0] = master, None if add_samples_origin: signals_samples.append( ( np.ones(len(master), dtype=" "MDF": """Stack several files and return the stacked `MDF` object. Parameters ---------- files : list | tuple List of MDF file names or `MDF`, zipfile.ZipFile, bz2.BZ2File or gzip.GzipFile instances. .. versionchanged:: 6.2.0 Added support for zipfile.ZipFile, bz2.BZ2File and gzip.GzipFile. version : str, default '4.10' Merged file version. sync : bool, default True Sync the files based on the start of measurement. use_display_names : bool, default False Use display name instead of standard channel name, if available. process_bus_logging : bool, default True Controls whether the bus processing of MDF v4 files is done when the file is loaded. .. versionadded:: 8.1.0 Returns ------- stacked : MDF New `MDF` object with stacked channels. Examples -------- >>> stacked = MDF.stack( [ 'path/to/file.mf4', MDF(BytesIO(data)), MDF(zipfile.ZipFile('data.zip')), MDF(bz2.BZ2File('path/to/data.bz2', 'rb')), MDF(gzip.GzipFile('path/to/data.gzip', 'rb')), ], version='4.00', sync=False, ) """ if not files: raise MdfException("No files given for stack") version = validate_version_argument(version) use_display_names = kwargs.get("use_display_names", False) files_nr = len(files) input_types = [isinstance(mdf, MDF) for mdf in files] if progress is not None: if callable(progress): progress(0, files_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(files_nr) if progress.stop: raise Terminated if sync: start_times: list[datetime] = [] for file in files: if isinstance(file, MDF): start_times.append(file.header.start_time) else: if is_file_like(file): ts, version = get_measurement_timestamp_and_version(file) start_times.append(ts) else: with open(file, "rb") as bytes_io: ts, version = get_measurement_timestamp_and_version(bytes_io) start_times.append(ts) try: oldest = min(start_times) except TypeError: start_times = [timestamp.astimezone(timezone.utc) for timestamp in start_times] oldest = min(start_times) offsets = [(timestamp - oldest).total_seconds() for timestamp in start_times] else: offsets = [0 for file in files] for mdf_index, (offset, mdf) in enumerate(zip(offsets, files, strict=False)): if not isinstance(mdf, MDF): mdf = MDF(mdf, use_display_names=use_display_names) if progress is not None: progress.signals.setLabelText.emit(f"Stacking file {mdf_index + 1} of {files_nr}\n{mdf.name.name}") if mdf_index == 0: version = validate_version_argument(version) kwargs = dict(mdf._mdf._kwargs) # type: ignore[assignment] stacked = MDF( version=version, **mdf._mdf._kwargs.copy(), ) stacked.configure(from_other=mdf) if sync: stacked.header.start_time = oldest else: stacked.header.start_time = mdf.header.start_time for i, group in enumerate(mdf.virtual_groups): included_channels = mdf.included_channels(group)[group] if not included_channels: continue for idx, signals in enumerate( mdf._mdf._yield_selected_signals(group, groups=included_channels, version=version) ): if not signals: break if idx == 0: signals = typing.cast(list[Signal], signals) if sync: timestamps = signals[0].timestamps + offset for sig in signals: sig.timestamps = timestamps cg = mdf.groups[group].channel_group dg_cntr = stacked.append( signals, common_timebase=True, ) MDF._transfer_channel_group_data(stacked.groups[dg_cntr].channel_group, cg) else: signals_samples = typing.cast(list[tuple[NDArray[Any], None]], signals) master = signals_samples[0][0] if sync: master = master + offset signals_samples[0] = master, None stacked.extend(dg_cntr, signals_samples) if progress and progress.stop: raise Terminated if dg_cntr is not None: for index in range(dg_cntr, len(stacked.groups)): stacked.groups[ index ].channel_group.comment = f'stacked from channel group {i} of "{mdf.name.parent}"' if progress is not None: if callable(progress): progress(mdf_index, files_nr) else: progress.signals.setValue.emit(mdf_index) if progress.stop: raise Terminated if mdf_index == 0: stacked._transfer_metadata(mdf) if not input_types[mdf_index]: mdf.close() if progress is not None and progress.stop: raise Terminated try: if kwargs.get("process_bus_logging", True): if not isinstance(stacked._mdf, mdf_v4.MDF4): raise MdfException("process_bus_logging is only supported for MDF4 files") stacked._mdf._process_bus_logging() except: pass return stacked def iter_channels( self, skip_master: bool = True, copy_master: bool = True, raw: bool | dict[str, bool] = False, ) -> Iterator[Signal]: """Generator that yields a `Signal` for each non-master channel. Parameters ---------- skip_master : bool, default True Do not yield master channels. copy_master : bool, default True Copy master for each yielded channel. raw : bool | dict, default False Return raw channels instead of converted. .. versionchanged:: 8.0.0 Provide individual raw mode based on a dict. The dict keys are channel names and each value is a boolean that sets whether to return raw samples for that channel. The key '__default__' is mandatory and sets the raw mode for all channels not specified. """ if isinstance(raw, dict): if "__default__" not in raw: raise MdfException("The raw argument given as dict must contain the __default__ key") for index in self.virtual_groups: channels = [ (None, gp_index, ch_index) for gp_index, channel_indexes in self.included_channels(index)[index].items() for ch_index in channel_indexes ] signals = self.select(channels, copy_master=copy_master, raw=raw) yield from signals def iter_groups( self, raster: RasterType | None = None, time_from_zero: bool = True, empty_channels: EmptyChannelsType = "skip", use_display_names: bool = False, time_as_date: bool = False, reduce_memory_usage: bool = False, raw: bool | dict[str, bool] = False, ignore_value2text_conversions: bool = False, only_basenames: bool = False, ) -> Iterator[pd.DataFrame]: """Generator that yields channel groups as pandas DataFrames. If there are multiple occurrences for the same channel name inside a channel group, then a counter will be used to make the names unique (_). Parameters ---------- raster : float | array-like | str, optional New raster that can be: * a float step value * a channel name whose timestamps will be used as raster (starting with asammdf 5.5.0) * an array (starting with asammdf 5.5.0) See `resample` for examples of using this argument. .. versionadded:: 5.21.0 time_from_zero : bool, default True Adjust time channel to start from 0. empty_channels : {'skip', 'zeros'}, default 'skip' Behaviour for channels without samples. .. versionadded:: 5.21.0 use_display_names : bool, default False Use display name instead of standard channel name, if available. .. versionadded:: 5.21.0 time_as_date : bool, default False The DataFrame index will contain the datetime timestamps according to the measurement start time. If True, then the argument `time_from_zero` will be ignored. reduce_memory_usage : bool, default False Reduce memory usage by converting all float columns to float32 and searching for minimum dtype that can represent the values found in integer columns. .. versionadded:: 5.21.0 raw : bool | dict, default False The DataFrame will contain the raw channel values. .. versionadded:: 5.21.0 .. versionchanged:: 8.0.0 Provide individual raw mode based on a dict. The dict keys are channel names and each value is a boolean that sets whether to return raw samples for that channel. The key '__default__' is mandatory and sets the raw mode for all channels not specified. ignore_value2text_conversions : bool, default False Valid only for the channels that have value to text conversions and if `raw=False`. If this is True, then the raw numeric values will be used, and the conversion will not be applied. .. versionadded:: 5.21.0 only_basenames : bool, default False Use just the field names, without prefix, for structures and channel arrays. .. versionadded:: 5.21.0 """ for i in self.virtual_groups: yield self.get_group( i, raster=raster, time_from_zero=time_from_zero, empty_channels=empty_channels, use_display_names=use_display_names, time_as_date=time_as_date, reduce_memory_usage=reduce_memory_usage, raw=raw, ignore_value2text_conversions=ignore_value2text_conversions, only_basenames=only_basenames, ) def master_using_raster(self, raster: RasterType, endpoint: bool = False) -> NDArray[Any]: """Get single master based on the raster. Parameters ---------- raster : float New raster. endpoint : bool, default False Include maximum timestamp in the new master. Returns ------- master : np.ndarray New master. """ if not raster: master = np.array([], dtype=" "MDF": """Resample all channels using the given raster. See `configure` to select the interpolation method for integer and float channels. Parameters ---------- raster : float | array-like | str New raster that can be: * a float step value * a channel name whose timestamps will be used as raster (starting with asammdf 5.5.0) * an array (starting with asammdf 5.5.0) version : str, optional New MDF file version from ('2.00', '2.10', '2.14', '3.00', '3.10', '3.20', '3.30', '4.00', '4.10', '4.11', '4.20'); default is None and in this case the original file version is used. time_from_zero : bool, default False Start timestamps from 0s in the resampled measurement. Returns ------- mdf : MDF New `MDF` object with resampled channels. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> mdf = MDF() >>> sig = Signal(name='S1', samples=[1, 2, 3, 4], timestamps=[1, 2, 3, 4]) >>> mdf.append(sig) >>> sig = Signal(name='S2', samples=[1, 2, 3, 4], timestamps=[1.1, 3.5, 3.7, 3.9]) >>> mdf.append(sig) Resample to a float step value. >>> resampled = mdf.resample(raster=0.1) >>> resampled.select(['S1', 'S2']) [, ] Resample to the timestamps of one of the channels. >>> resampled = mdf.resample(raster='S2') >>> resampled.select(['S1', 'S2']) [, ] Resample to an arbitrary array of timestamps. >>> resampled = mdf.resample(raster=[1.9, 2.0, 2.1]) >>> resampled.select(['S1', 'S2']) [, ] Resample to the timestamps of one of the channels, and adjust the timestamps to start at 0. >>> resampled = mdf.resample(raster='S2', time_from_zero=True) >>> resampled.select(['S1', 'S2']) [, ] """ if version is None: version = self.version else: version = validate_version_argument(version) mdf = MDF( version=version, **self._mdf._kwargs, ) integer_interpolation_mode = self._mdf._integer_interpolation float_interpolation_mode = self._mdf._float_interpolation mdf.configure(from_other=self) mdf.header.start_time = self.header.start_time groups_nr = len(self.virtual_groups) if progress is not None: if callable(progress): progress(0, groups_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr) if progress.stop: raise Terminated if isinstance(raster, (int, float)): raster = float(raster) if raster <= 0: raise MdfException("The raster value must be > 0") raster = self.master_using_raster(raster) elif isinstance(raster, str): raster = self._mdf.get(raster, raw=True, ignore_invalidation_bits=True).timestamps else: raster = np.array(raster) if time_from_zero and len(raster): delta = raster[0] new_raster = raster - delta t_epoch = self.header.start_time.timestamp() + delta mdf.header.start_time = datetime.fromtimestamp(t_epoch) else: new_raster = None mdf.header.start_time = self.header.start_time for i, (group_index, virtual_group) in enumerate(self.virtual_groups.items()): channels = [ (None, gp_index, ch_index) for gp_index, channel_indexes in self.included_channels(group_index)[group_index].items() for ch_index in channel_indexes ] if not channels: continue sigs = self.select(channels, raw=True) sigs = [ sig.interp( raster, integer_interpolation_mode=integer_interpolation_mode, float_interpolation_mode=float_interpolation_mode, ) for sig in sigs ] if new_raster is not None: for sig in sigs: if len(sig): sig.timestamps = new_raster cg = self.groups[group_index].channel_group dg_cntr = mdf.append( sigs, common_timebase=True, comment=cg.comment, ) MDF._transfer_channel_group_data(mdf.groups[dg_cntr].channel_group, cg) if progress is not None: if callable(progress): progress(i + 1, groups_nr) else: progress.signals.setValue.emit(i + 1) if progress.stop: raise Terminated mdf._transfer_metadata(self, message=f"Resampled from {self.name}") return mdf def select( self, channels: ChannelsType, record_offset: int = 0, raw: bool | dict[str, bool] = False, copy_master: bool = True, ignore_value2text_conversions: bool = False, record_count: int | None = None, validate: bool = False, ) -> list[Signal]: """Retrieve the channels listed in the `channels` argument as `Signal` objects. .. note:: The `dataframe` argument was removed in version 5.8.0, use the `to_dataframe` method instead. Parameters ---------- channels : list List of items to be selected; each item can be: * a channel name string * (channel name, group index, channel index) list or tuple * (channel name, group index) list or tuple * (None, group index, channel index) list or tuple record_offset : int, optional Record number offset; optimization to get the last part of signal samples. raw : bool | dict, default False Get raw channel samples. .. versionchanged:: 8.0.0 Provide individual raw mode based on a dict. The dict keys are channel names and each value is a boolean that sets whether to return raw samples for that channel. The key '__default__' is mandatory and sets the raw mode for all channels not specified. copy_master : bool, default True Option to get a new timestamps array for each selected Signal or to use a shared array for channels of the same channel group. ignore_value2text_conversions : bool, default False Valid only for the channels that have value to text conversions and if `raw=False`. If this is True, then the raw numeric values will be used, and the conversion will not be applied. .. versionchanged:: 5.8.0 record_count : int, optional Number of records to read; default is None and in this case all available records are used. validate : bool, default False Consider the invalidation bits. .. versionadded:: 5.16.0 Returns ------- signals : list List of `Signal` objects based on the input channel list. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> t = np.arange(5) >>> s = np.ones(5) >>> mdf = MDF() >>> mdf.configure(raise_on_multiple_occurrences=False) >>> for i in range(4): ... sigs = [Signal(s * (i * 10 + j), t, name='SIG') for j in range(1, 4)] ... mdf.append(sigs) Select channel "SIG" (the first occurrence, which is group 0 index 1), channel "SIG" from group 3 index 1, channel "SIG" from group 2 (the first occurrence, which is index 1), and channel from group 1 index 2. >>> mdf.select(['SIG', ('SIG', 3, 1), ['SIG', 2], (None, 1, 2)]) [, , , ] """ def validate_blocks(blocks: list[SignalDataBlockInfo], record_size: int) -> bool: for block in blocks: if block.original_size % record_size: return False return True if ( not isinstance(self._mdf, mdf_v4.MDF4) or not self._mdf._mapped_file or record_offset or record_count is not None or True # disable for now ): return self._select_fallback( channels, record_offset, raw, copy_master, ignore_value2text_conversions, record_count, validate ) if isinstance(raw, dict): if "__default__" not in raw: raise MdfException("The raw argument given as dict must contain the __default__ key") __default__ = raw["__default__"] else: __default__ = raw virtual_groups = self.included_channels(channels=channels, minimal=False, skip_master=False) for virtual_group, groups in virtual_groups.items(): if len(self._mdf.virtual_groups[virtual_group].groups) > 1: return self._select_fallback( channels, record_offset, raw, copy_master, ignore_value2text_conversions, record_count, validate ) output_signals: dict[tuple[int, int], Signal] = {} for virtual_group, groups in virtual_groups.items(): group_index = virtual_group grp = self._mdf.groups[group_index] grp.load_all_data_blocks() blocks = grp.data_blocks record_size = grp.channel_group.samples_byte_nr + grp.channel_group.invalidation_bytes_nr cycles_nr = grp.channel_group.cycles_nr channel_indexes = groups[group_index] pairs = [(group_index, ch_index) for ch_index in channel_indexes] master_index = self.masters_db.get(group_index, None) if master_index is None or grp.record[master_index] is None: return self._select_fallback( channels, record_offset, raw, copy_master, ignore_value2text_conversions, record_count, validate ) channel = grp.channels[master_index] master_dtype, byte_size, byte_offset, _ = typing.cast( tuple[np.dtype[Any], int, int, int], grp.record[master_index] ) signals = [(byte_offset, byte_size, channel.pos_invalidation_bit)] for ch_index in channel_indexes: channel = grp.channels[ch_index] if (info := grp.record[ch_index]) is None: print("NASOl") return self._select_fallback( channels, record_offset, raw, copy_master, ignore_value2text_conversions, record_count, validate ) else: _, byte_size, byte_offset, _ = info signals.append((byte_offset, byte_size, channel.pos_invalidation_bit)) raw_and_invalidation = get_channel_raw_bytes_complete( blocks, signals, self._mdf._mapped_file.name, cycles_nr, record_size, grp.channel_group.invalidation_bytes_nr, THREAD_COUNT, ) master_bytes, _ = raw_and_invalidation[0] raw_and_invalidation = raw_and_invalidation[1:] # prepare the master master = np.frombuffer(master_bytes, dtype=master_dtype) for pair, (raw_data, invalidation_bits) in zip(pairs, raw_and_invalidation, strict=False): ch_index = pair[-1] channel = grp.channels[ch_index] channel_dtype, byte_size, byte_offset, bit_offset = grp.record[ch_index] vals = np.frombuffer(raw_data, dtype=channel_dtype) data_type = channel.data_type if not channel.standard_C_size: size = byte_size if channel_dtype.byteorder == "=" and data_type in ( v4c.DATA_TYPE_SIGNED_MOTOROLA, v4c.DATA_TYPE_UNSIGNED_MOTOROLA, ): view = np.dtype(f">u{vals.itemsize}") else: view = np.dtype(f"{channel_dtype.byteorder}u{vals.itemsize}") if view != vals.dtype: vals = vals.view(view) if bit_offset: vals >>= bit_offset if channel.bit_count != size * 8: if data_type in v4c.SIGNED_INT: vals = as_non_byte_sized_signed_int(vals, channel.bit_count) else: mask = (1 << channel.bit_count) - 1 vals &= mask elif data_type in v4c.SIGNED_INT: view = f"{channel_dtype.byteorder}i{vals.itemsize}" if np.dtype(view) != vals.dtype: vals = vals.view(view) conversion = channel.conversion unit = (conversion and conversion.unit) or channel.unit source = channel.source if source: source = Source.from_source(source) else: cg_source = grp.channel_group.acq_source if cg_source: source = Source.from_source(cg_source) else: source = None master_metadata = self._mdf._master_channel_metadata.get(group_index, None) output_signals[pair] = Signal( samples=vals, timestamps=master, unit=unit, name=channel.name, comment=channel.comment, conversion=conversion, raw=True, master_metadata=master_metadata, attachment=None, source=source, display_names=channel.display_names, bit_count=channel.bit_count, flags=Signal.Flags.no_flags, invalidation_bits=invalidation_bits, encoding=None, group_index=group_index, channel_index=ch_index, ) indexes = [] for item in channels: if not isinstance(item, (list, tuple)): item = [item] indexes.append(self._mdf._validate_channel_selection(*item)) signals = [output_signals[pair] for pair in indexes] if copy_master: for signal in signals: signal.timestamps = signal.timestamps.copy() for signal in signals: if (isinstance(raw, dict) and not raw.get(signal.name, __default__)) or not raw: conversion = signal.conversion if conversion: samples = conversion.convert( signal.samples, ignore_value2text_conversions=ignore_value2text_conversions ) signal.samples = samples signal.raw = False signal.conversion = None if signal.samples.dtype.kind == "S": signal.encoding = "utf-8" if self.version >= "4.00" else "latin-1" if validate: signals = [sig.validate(copy=False) for sig in signals] for signal, channel in zip(signals, channels, strict=False): if isinstance(channel, str): signal.name = channel else: name = channel[0] if name is not None: signal.name = name unique = set() for i, signal in enumerate(signals): obj_id = id(signal) if id(signal) in unique: signals[i] = signal.copy() unique.add(obj_id) return signals def _select_fallback( self, channels: ChannelsType, record_offset: int = 0, raw: bool | dict[str, bool] = False, copy_master: bool = True, ignore_value2text_conversions: bool = False, record_count: int | None = None, validate: bool = False, ) -> list[Signal]: """Retrieve the channels listed in the `channels` argument as `Signal` objects. .. note:: The `dataframe` argument was removed in version 5.8.0, use the `to_dataframe` method instead. Parameters ---------- channels : list List of items to be selected; each item can be: * a channel name string * (channel name, group index, channel index) list or tuple * (channel name, group index) list or tuple * (None, group index, channel index) list or tuple record_offset : int, optional Record number offset; optimization to get the last part of signal samples. raw : bool | dict, default False Get raw channel samples. .. versionchanged:: 8.0.0 Provide individual raw mode based on a dict. The dict keys are channel names and each value is a boolean that sets whether to return raw samples for that channel. The key '__default__' is mandatory and sets the raw mode for all channels not specified. copy_master : bool, default True Option to get a new timestamps array for each selected Signal or to use a shared array for channels of the same channel group. ignore_value2text_conversions : bool, default False Valid only for the channels that have value to text conversions and if `raw=False`. If this is True, then the raw numeric values will be used, and the conversion will not be applied. .. versionchanged:: 5.8.0 record_count : int, optional Number of records to read; default is None and in this case all available records are used. validate : bool, default False Consider the invalidation bits. .. versionadded:: 5.16.0 Returns ------- signals : list List of `Signal` objects based on the input channel list. Examples -------- >>> from asammdf import MDF, Signal >>> import numpy as np >>> t = np.arange(5) >>> s = np.ones(5) >>> mdf = MDF() >>> mdf.configure(raise_on_multiple_occurrences=False) >>> for i in range(4): ... sigs = [Signal(s * (i * 10 + j), t, name='SIG') for j in range(1, 4)] ... mdf.append(sigs) Select channel "SIG" (the first occurrence, which is group 0 index 1), channel "SIG" from group 3 index 1, channel "SIG" from group 2 (the first occurrence, which is index 1), and channel from group 1 index 2. >>> mdf.select(['SIG', ('SIG', 3, 1), ['SIG', 2], (None, 1, 2)]) [, , , ] """ if isinstance(raw, dict): if "__default__" not in raw: raise MdfException("The raw argument given as dict must contain the __default__ key") __default__ = raw["__default__"] else: __default_ = raw virtual_groups = self.included_channels(channels=channels, minimal=False, skip_master=False) output_signals: dict[tuple[int, int], Signal] = {} for virtual_group, groups in virtual_groups.items(): cycles_nr = self._mdf.virtual_groups[virtual_group].cycles_nr pairs = [ (gp_index, ch_index) for gp_index, channel_indexes in groups.items() for ch_index in channel_indexes ] if record_count is None: cycles = cycles_nr - record_offset else: if cycles_nr < record_count + record_offset: cycles = cycles_nr - record_offset else: cycles = record_count signals: list[Signal] = [] current_pos = 0 for idx, sigs in enumerate( self._mdf._yield_selected_signals( virtual_group, groups=groups, record_offset=record_offset, record_count=record_count, ) ): if not sigs: break if idx == 0: sigs = typing.cast(list[Signal], sigs) next_pos = current_pos + len(sigs[0]) master = np.empty(cycles, dtype=sigs[0].timestamps.dtype) master[current_pos:next_pos] = sigs[0].timestamps for sig in sigs: shape = (cycles,) + sig.samples.shape[1:] samples = np.empty(shape, dtype=sig.samples.dtype) samples[current_pos:next_pos] = sig.samples sig.samples = samples signals.append(sig) if sig.invalidation_bits is not None: inval_array = np.empty(cycles, dtype=sig.invalidation_bits.dtype) inval_array[current_pos:next_pos] = sig.invalidation_bits sig.invalidation_bits = InvalidationArray(inval_array) else: sigs = typing.cast(list[tuple[NDArray[Any], None]], sigs) samples, _ = sigs[0] next_pos = current_pos + len(samples) master[current_pos:next_pos] = samples for signal, (samples, inval) in zip(signals, sigs[1:], strict=False): signal.samples[current_pos:next_pos] = samples if signal.invalidation_bits is not None: signal.invalidation_bits[current_pos:next_pos] = inval current_pos = next_pos for signal, pair in zip(signals, pairs, strict=False): signal.timestamps = master output_signals[pair] = signal indexes: list[tuple[int, int]] = [] for item in channels: name: str | None if not isinstance(item, (list, tuple)): name = item group = index = None elif len(item) == 2: name, group = item index = None else: name, group, index = item indexes.append(self._mdf._validate_channel_selection(name=name, group=group, index=index)) signals = [output_signals[pair] for pair in indexes] if copy_master: for signal in signals: signal.timestamps = signal.timestamps.copy() for signal in signals: if (isinstance(raw, dict) and not raw.get(signal.name, __default__)) or not raw: conversion = signal.conversion if conversion: samples = conversion.convert( signal.samples, ignore_value2text_conversions=ignore_value2text_conversions ) signal.samples = samples signal.raw = False signal.conversion = None if signal.samples.dtype.kind == "S": signal.encoding = "utf-8" if self.version >= "4.00" else "latin-1" if validate: signals = [sig.validate(copy=False) for sig in signals] unique = set() for i, signal in enumerate(signals): obj_id = id(signal) if id(signal) in unique: signals[i] = signal.copy() unique.add(obj_id) for signal, channel in zip(signals, channels, strict=False): if isinstance(channel, str): signal.name = channel else: name = channel[0] if name is not None: signal.name = name return signals @staticmethod def scramble( name: StrPath, skip_attachments: bool = False, progress: Callable[[int, int], None] | Any | None = None, **kwargs: Never, ) -> Path: """Scramble text blocks and keep original file structure. Parameters ---------- name : str | path-like File name. skip_attachments : bool, default False Skip scrambling of attachments data if True. .. versionadded:: 5.9.0 Returns ------- name : pathlib.Path Name of scrambled file. """ name = Path(name) mdf = MDF(name) texts: dict[int, bytes] = {} if progress is not None: if callable(progress): progress(0, 100) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(100) if progress.stop: raise Terminated count = len(mdf.groups) if isinstance(mdf._mdf, mdf_v4.MDF4): try: stream = mdf._mdf._file if not stream: raise ValueError("stream is None") if mdf.header.comment_addr: stream.seek(mdf.header.comment_addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[mdf.header.comment_addr] = randomized_string(size) for fh in mdf._mdf.file_history: addr = fh.comment_addr if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) for ev in mdf._mdf.events: for addr in (ev.comment_addr, ev.name_addr): if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) for at in mdf._mdf.attachments: for addr in (at.comment_addr, at.file_name_addr): if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) if not skip_attachments and at.embedded_data: texts[at.address + v4c.AT_COMMON_SIZE] = randomized_string(at.embedded_size) for idx, v4_gp in enumerate(mdf._mdf.groups, 1): addr = v4_gp.data_group.comment_addr if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) v4_cg = v4_gp.channel_group for addr in (v4_cg.acq_name_addr, v4_cg.comment_addr): if v4_cg.flags & v4c.FLAG_CG_BUS_EVENT: continue if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) source = v4_cg.acq_source_addr if source: source_information = SourceInformation( address=source, stream=stream, mapped=False, tx_map={} ) for addr in ( source_information.name_addr, source_information.path_addr, source_information.comment_addr, ): if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) for v4_ch in v4_gp.channels: for addr in (v4_ch.name_addr, v4_ch.unit_addr, v4_ch.comment_addr): if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) source = v4_ch.source_addr if source: source_information = SourceInformation( address=source, stream=stream, mapped=False, tx_map={} ) for addr in ( source_information.name_addr, source_information.path_addr, source_information.comment_addr, ): if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) conv = v4_ch.conversion_addr if conv: v4_conv = v4b.ChannelConversion( address=conv, stream=stream, mapped=False, tx_map={}, ) for addr in ( v4_conv.name_addr, v4_conv.unit_addr, v4_conv.comment_addr, ): if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) if v4_conv.conversion_type == v4c.CONVERSION_TYPE_ALG: addr = v4_conv.formula_addr if addr and addr not in texts: stream.seek(addr + 8) size = UINT64_u(stream.read(8))[0] - 24 texts[addr] = randomized_string(size) if v4_conv.referenced_blocks: for key, v4_block in v4_conv.referenced_blocks.items(): if v4_block: if isinstance(v4_block, bytes): addr = typing.cast(int, v4_conv[key]) if addr not in texts: stream.seek(addr + 8) size = len(v4_block) texts[addr] = randomized_string(size) if progress is not None: if callable(progress): progress(int(idx / count * 66), 100) else: progress.signals.setValue.emit(int(idx / count * 66)) if progress.stop: raise Terminated except: print(f"Error while scrambling the file: {format_exc()}.\nWill now use fallback method") texts = MDF._fallback_scramble_mf4(name) mdf.close() dst = name.with_suffix(".scrambled.mf4") copy(name, dst) with open(dst, "rb+") as bytes_io: count = len(texts) chunk = max(count // 34, 1) idx = 0 for index, (addr, bts) in enumerate(texts.items()): bytes_io.seek(addr + 24) bytes_io.write(bts) if index % chunk == 0: if progress is not None: if callable(progress): progress(66 + idx, 100) else: progress.signals.setValue.emit(66 + idx) if progress.stop: raise Terminated else: stream = mdf._mdf._file if not stream: raise ValueError("stream is None") if mdf.header.comment_addr: stream.seek(mdf.header.comment_addr + 2) size = UINT16_u(stream.read(2))[0] - 4 texts[mdf.header.comment_addr + 4] = randomized_string(size) texts[36 + 0x40] = randomized_string(32) texts[68 + 0x40] = randomized_string(32) texts[100 + 0x40] = randomized_string(32) texts[132 + 0x40] = randomized_string(32) for idx, v3_gp in enumerate(mdf._mdf.groups, 1): v3_cg = v3_gp.channel_group addr = v3_cg.comment_addr if addr and addr not in texts: stream.seek(addr + 2) size = UINT16_u(stream.read(2))[0] - 4 texts[addr + 4] = randomized_string(size) if v3_gp.trigger: addr = v3_gp.trigger.text_addr if addr: stream.seek(addr + 2) size = UINT16_u(stream.read(2))[0] - 4 texts[addr + 4] = randomized_string(size) for v3_ch in v3_gp.channels: for key in ("long_name_addr", "display_name_addr", "comment_addr"): if hasattr(v3_ch, key): addr = getattr(v3_ch, key) else: addr = 0 if addr and addr not in texts: stream.seek(addr + 2) size = UINT16_u(stream.read(2))[0] - 4 texts[addr + 4] = randomized_string(size) texts[v3_ch.address + 26] = randomized_string(32) texts[v3_ch.address + 58] = randomized_string(128) source = v3_ch.source_addr if source: channel_extension = ChannelExtension(address=source, stream=stream) if channel_extension.type == v3c.SOURCE_ECU: texts[channel_extension.address + 12] = randomized_string(80) texts[channel_extension.address + 92] = randomized_string(32) else: texts[channel_extension.address + 14] = randomized_string(36) texts[channel_extension.address + 50] = randomized_string(36) conv = v3_ch.conversion_addr if conv: texts[conv + 22] = randomized_string(20) v3_conv = v3b.ChannelConversion(address=conv, stream=stream) if v3_conv.conversion_type == v3c.CONVERSION_TYPE_FORMULA: texts[conv + 36] = randomized_string(v3_conv.block_len - 36) if v3_conv.referenced_blocks: for key, v3_block in v3_conv.referenced_blocks.items(): if v3_block: if isinstance(v3_block, bytes): addr = typing.cast(int, v3_conv[key]) if addr and addr not in texts: stream.seek(addr + 2) size = UINT16_u(stream.read(2))[0] - 4 texts[addr + 4] = randomized_string(size) if progress is not None: if callable(progress): progress(int(idx / count * 100), 100) else: progress.signals.setValue.emit(int(idx / count * 66)) if progress.stop: raise Terminated mdf.close() dst = name.with_suffix(".scrambled.mdf") copy(name, dst) with open(dst, "rb+") as bytes_io: chunk = count // 34 idx = 0 for index, (addr, bts) in enumerate(texts.items()): bytes_io.seek(addr) bytes_io.write(bts) if chunk and index % chunk == 0: if progress is not None: if callable(progress): progress(66 + idx, 100) else: progress.signals.setValue.emit(66 + idx) if progress.stop: raise Terminated if progress is not None: if callable(progress): progress(100, 100) else: progress.signals.setValue.emit(100) return dst @staticmethod def _fallback_scramble_mf4(name: StrPath | bytes | os.PathLike[bytes]) -> dict[int, bytes]: """Scramble text blocks and keep original file structure. Parameters ---------- name : str | path-like File name. Returns ------- name : pathlib.Path Name of scrambled file. """ pattern = re.compile( rb"(?P##(TX|MD))", re.DOTALL | re.MULTILINE, ) texts = {} with open(name, "rb") as stream: stream.seek(0, 2) file_limit = stream.tell() stream.seek(0) for match in re.finditer(pattern, stream.read()): start = match.start() if file_limit - start >= 24: stream.seek(start + 8) (size,) = UINT64_u(stream.read(8)) if start + size <= file_limit: texts[start + 24] = randomized_string(size - 24) return texts def get_group( self, index: int, raster: RasterType | None = None, time_from_zero: bool = True, empty_channels: EmptyChannelsType = "skip", use_display_names: bool = False, time_as_date: bool = False, reduce_memory_usage: bool = False, raw: bool | dict[str, bool] = False, ignore_value2text_conversions: bool = False, only_basenames: bool = False, ) -> pd.DataFrame: """Get channel group as a pandas DataFrame. If there are multiple occurrences for the same channel name, then a counter will be used to make the names unique (_). Parameters ---------- index : int Channel group index. raster : float | array-like | str, optional New raster that can be: * a float step value * a channel name whose timestamps will be used as raster (starting with asammdf 5.5.0) * an array (starting with asammdf 5.5.0) See `resample` for examples of using this argument. time_from_zero : bool, default True Adjust time channel to start from 0. empty_channels : {'skip', 'zeros'}, default 'skip' Behaviour for channels without samples. .. versionadded:: 5.8.0 use_display_names : bool, default False Use display name instead of standard channel name, if available. time_as_date : bool, default False The DataFrame index will contain the datetime timestamps according to the measurement start time. If True, then the argument `time_from_zero` will be ignored. reduce_memory_usage : bool, default False Reduce memory usage by converting all float columns to float32 and searching for minimum dtype that can represent the values found in integer columns. raw : bool | dict, default False The DataFrame will contain the raw channel values. .. versionadded:: 5.7.0 .. versionchanged:: 8.0.0 Provide individual raw mode based on a dict. The dict keys are channel names and each value is a boolean that sets whether to return raw samples for that channel. The key '__default__' is mandatory and sets the raw mode for all channels not specified. ignore_value2text_conversions : bool, default False Valid only for the channels that have value to text conversions and if `raw=False`. If this is True, then the raw numeric values will be used, and the conversion will not be applied. .. versionadded:: 5.8.0 only_basenames : bool, default False Use just the field names, without prefix, for structures and channel arrays. .. versionadded:: 5.13.0 Returns ------- dataframe : pandas.DataFrame Channel group data. """ channels = [ (None, gp_index, ch_index) for gp_index, channel_indexes in self.included_channels(index)[index].items() for ch_index in channel_indexes ] return self.to_dataframe( channels=channels, raster=raster, time_from_zero=time_from_zero, empty_channels=empty_channels, use_display_names=use_display_names, time_as_date=time_as_date, reduce_memory_usage=reduce_memory_usage, raw=raw, ignore_value2text_conversions=ignore_value2text_conversions, only_basenames=only_basenames, ) def iter_to_dataframe( self, channels: ChannelsType | None = None, raster: RasterType | None = None, time_from_zero: bool = True, empty_channels: EmptyChannelsType = "skip", use_display_names: bool = False, time_as_date: bool = False, reduce_memory_usage: bool = False, raw: bool | dict[str, bool] = False, ignore_value2text_conversions: bool = False, use_interpolation: bool = True, only_basenames: bool = False, chunk_ram_size: int = 200 * 1024 * 1024, interpolate_outwards_with_nan: bool = False, numeric_1D_only: bool = False, progress: Callable[[int, int], None] | Any | None = None, ) -> Iterator[pd.DataFrame]: """Generator that yields pandas DataFrames that should not exceed 200 MB of RAM. .. versionadded:: 5.15.0 Parameters ---------- channels : list, optional List of items to be selected; each item can be: * a channel name string * (channel name, group index, channel index) list or tuple * (channel name, group index) list or tuple * (None, group index, channel index) list or tuple The default is to select all channels. raster : float | array-like | str, optional New raster that can be: * a float step value * a channel name whose timestamps will be used as raster (starting with asammdf 5.5.0) * an array (starting with asammdf 5.5.0) See `resample` for examples of using this argument. time_from_zero : bool, default True Adjust time channel to start from 0. empty_channels : {'skip', 'zeros'}, default 'skip' Behaviour for channels without samples. use_display_names : bool, default False Use display name instead of standard channel name, if available. time_as_date : bool, default False The DataFrame index will contain the datetime timestamps according to the measurement start time. If True, then the argument `time_from_zero` will be ignored. reduce_memory_usage : bool, default False Reduce memory usage by converting all float columns to float32 and searching for minimum dtype that can represent the values found in integer columns. raw : bool | dict, default False The columns will contain the raw values. .. versionchanged:: 8.0.0 Provide individual raw mode based on a dict. The dict keys are channel names and each value is a boolean that sets whether to return raw samples for that channel. The key '__default__' is mandatory and sets the raw mode for all channels not specified. ignore_value2text_conversions : bool, default False Valid only for the channels that have value to text conversions and if `raw=False`. If this is True, then the raw numeric values will be used, and the conversion will not be applied. use_interpolation : bool, default True Option to perform interpolations when multiple timestamp rasters are present. If False, then DataFrame columns will be automatically filled with NaNs where the DataFrame index values are not found in the current column's timestamps. only_basenames : bool, default False Use just the field names, without prefix, for structures and channel arrays. chunk_ram_size : int, default 200 * 1024 * 1024 (= 200 MB) Desired DataFrame RAM usage in bytes. interpolate_outwards_with_nan : bool, default False Use NaN values for the samples that lie outside of the original signal's timestamps. numeric_1D_only : bool, default False Only keep the 1D-columns that have numeric values. .. versionadded:: 7.0.0 Yields ------ dataframe : pandas.DataFrame Pandas DataFrames that should not exceed 200 MB of RAM. """ if isinstance(raw, dict): if "__default__" not in raw: raise MdfException("The raw argument given as dict must contain the __default__ key") __default__ = raw["__default__"] else: __default__ = raw if channels: mdf = self.filter(channels) result = mdf.iter_to_dataframe( raster=raster, time_from_zero=time_from_zero, empty_channels=empty_channels, use_display_names=use_display_names, time_as_date=time_as_date, reduce_memory_usage=reduce_memory_usage, raw=raw, ignore_value2text_conversions=ignore_value2text_conversions, use_interpolation=use_interpolation, only_basenames=only_basenames, chunk_ram_size=chunk_ram_size, interpolate_outwards_with_nan=interpolate_outwards_with_nan, numeric_1D_only=numeric_1D_only, ) for df in result: yield df mdf.close() else: # channels is None self._mdf._set_temporary_master(None) masters = {index: self._mdf.get_master(index) for index in self.virtual_groups} if raster is not None: if isinstance(raster, (int, float)): raster = float(raster) if raster <= 0: raise MdfException("The raster value must be > 0") raster = self.master_using_raster(raster) elif isinstance(raster, str): raster = self._mdf.get(raster, raw=True, ignore_invalidation_bits=True).timestamps else: raster = np.array(raster) master = raster else: if masters: master = reduce(np.union1d, masters.values()) else: master = np.array([], dtype="= "4.00" else "latin-1" for s_index, sig in enumerate(signals): sig = sig.validate(copy=False) if len(sig) == 0: if empty_channels == "zeros": sig.samples = np.zeros( len(master) if virtual_group.cycles_nr == 0 else virtual_group.cycles_nr, dtype=sig.samples.dtype, ) sig.timestamps = master if virtual_group.cycles_nr == 0 else group_master signals[s_index] = sig if use_interpolation: same_master = np.array_equal(master, group_master) if not same_master and interpolate_outwards_with_nan: idx = np.argwhere((master >= group_master[0]) & (master <= group_master[-1])).flatten() cycles = len(group_master) signals = [ ( signal.interp( master, integer_interpolation_mode=self._mdf._integer_interpolation, float_interpolation_mode=self._mdf._float_interpolation, ) if not same_master or len(signal) != cycles else signal ) for signal in signals ] if not same_master and interpolate_outwards_with_nan: for sig in signals: sig.timestamps = sig.timestamps[idx] sig.samples = sig.samples[idx] group_master = master signals = [sig for sig in signals if len(sig)] if signals: diffs = np.diff(group_master, prepend=-np.inf) > 0 if group_master.dtype.byteorder not in target_byte_order: group_master = group_master.byteswap().view(group_master.dtype.newbyteorder()) if np.all(diffs): index = pd.Index(group_master, tupleize_cols=False) else: idx = np.argwhere(diffs).flatten() group_master = group_master[idx] index = pd.Index(group_master, tupleize_cols=False) for sig in signals: sig.samples = sig.samples[idx] sig.timestamps = sig.timestamps[idx] size = len(index) for sig in signals: if sig.timestamps.dtype.byteorder not in target_byte_order: sig.timestamps = sig.timestamps.byteswap().view(sig.timestamps.dtype.newbyteorder()) sig_index = index if len(sig) == size else pd.Index(sig.timestamps, tupleize_cols=False) # byte arrays if len(sig.samples.shape) > 1: if use_display_names: channel_name = list(sig.display_names)[0] if sig.display_names else sig.name else: channel_name = sig.name channel_name = used_names.get_unique_name(channel_name) if sig.samples.dtype.byteorder not in target_byte_order: sig.samples = sig.samples.byteswap().view(sig.samples.dtype.newbyteorder()) data[channel_name] = pd.Series( list(sig.samples), index=sig_index, ) # arrays and structures elif sig.samples.dtype.names: for name, series in components( sig.samples, sig.name, used_names, master=sig_index, only_basenames=only_basenames, ): data[name] = series # scalars else: if use_display_names: channel_name = list(sig.display_names)[0] if sig.display_names else sig.name else: channel_name = sig.name channel_name = used_names.get_unique_name(channel_name) if reduce_memory_usage and sig.samples.dtype.kind in "SU": unique = np.unique(sig.samples) if sig.samples.dtype.byteorder not in target_byte_order: sig.samples = sig.samples.byteswap().view(sig.samples.dtype.newbyteorder()) if len(sig.samples) / len(unique) >= 2: data[channel_name] = pd.Series( sig.samples, index=sig_index, dtype="category", ) else: data[channel_name] = pd.Series( sig.samples, index=sig_index, ) else: if reduce_memory_usage: sig.samples = downcast(sig.samples) if sig.samples.dtype.byteorder not in target_byte_order: sig.samples = sig.samples.byteswap().view(sig.samples.dtype.newbyteorder()) data[channel_name] = pd.Series( sig.samples, index=sig_index, ) if progress is not None: if callable(progress): progress(group_index + 1, groups_nr) else: progress.signals.setValue.emit(group_index + 1) strings: dict[str, pd.Series[Any]] = {} nonstrings: dict[str, pd.Series[Any]] = {} for col, series in data.items(): if series.dtype.kind == "S": strings[col] = series else: nonstrings[col] = series if numeric_1D_only: nonstrings = {col: series for col, series in nonstrings.items() if series.dtype.kind in "uif"} strings = {} df = pd.DataFrame(nonstrings, index=master) if strings: df_strings = pd.DataFrame(strings, index=master) df = pd.concat([df, df_strings], axis=1) df.index.name = "timestamps" if time_as_date: delta = pd.to_timedelta(df.index, unit="s") new_index = self.header.start_time + delta df.set_index(new_index, inplace=True) yield df @overload def to_dataframe( self, channels: ChannelsType | None = ..., raster: RasterType | None = ..., time_from_zero: bool = ..., empty_channels: EmptyChannelsType = ..., use_display_names: bool = ..., time_as_date: bool = ..., reduce_memory_usage: bool = ..., raw: bool | dict[str, bool] = ..., ignore_value2text_conversions: bool = ..., use_interpolation: bool = ..., only_basenames: bool = ..., interpolate_outwards_with_nan: bool = ..., numeric_1D_only: bool = ..., progress: Callable[[int, int], None] | Any | None = ..., use_polars: Literal[False] = ..., ) -> pd.DataFrame: ... @overload def to_dataframe( self, channels: ChannelsType | None = ..., raster: RasterType | None = ..., time_from_zero: bool = ..., empty_channels: EmptyChannelsType = ..., use_display_names: bool = ..., time_as_date: bool = ..., reduce_memory_usage: bool = ..., raw: bool | dict[str, bool] = ..., ignore_value2text_conversions: bool = ..., use_interpolation: bool = ..., only_basenames: bool = ..., interpolate_outwards_with_nan: bool = ..., numeric_1D_only: bool = ..., progress: Callable[[int, int], None] | Any | None = ..., use_polars: Literal[True] = ..., ) -> "pl.DataFrame": ... @overload def to_dataframe( self, channels: ChannelsType | None = ..., raster: RasterType | None = ..., time_from_zero: bool = ..., empty_channels: EmptyChannelsType = ..., use_display_names: bool = ..., time_as_date: bool = ..., reduce_memory_usage: bool = ..., raw: bool | dict[str, bool] = ..., ignore_value2text_conversions: bool = ..., use_interpolation: bool = ..., only_basenames: bool = ..., interpolate_outwards_with_nan: bool = ..., numeric_1D_only: bool = ..., progress: Callable[[int, int], None] | Any | None = ..., use_polars: bool = ..., ) -> Union[pd.DataFrame, "pl.DataFrame"]: ... def to_dataframe( self, channels: ChannelsType | None = None, raster: RasterType | None = None, time_from_zero: bool = True, empty_channels: EmptyChannelsType = "skip", use_display_names: bool = False, time_as_date: bool = False, reduce_memory_usage: bool = False, raw: bool | dict[str, bool] = False, ignore_value2text_conversions: bool = False, use_interpolation: bool = True, only_basenames: bool = False, interpolate_outwards_with_nan: bool = False, numeric_1D_only: bool = False, progress: Callable[[int, int], None] | Any | None = None, use_polars: bool = False, ) -> Union[pd.DataFrame, "pl.DataFrame"]: """Generate a pandas DataFrame. Parameters ---------- channels : list, optional List of items to be selected; each item can be: * a channel name string * (channel name, group index, channel index) list or tuple * (channel name, group index) list or tuple * (None, group index, channel index) list or tuple The default is to select all channels. raster : float | array-like | str, optional New raster that can be: * a float step value * a channel name whose timestamps will be used as raster (starting with asammdf 5.5.0) * an array (starting with asammdf 5.5.0) See `resample` for examples of using this argument. time_from_zero : bool, default True Adjust time channel to start from 0. empty_channels : {'skip', 'zeros'}, default 'skip' Behaviour for channels without samples. use_display_names : bool, default False Use display name instead of standard channel name, if available. time_as_date : bool, default False The DataFrame index will contain the datetime timestamps according to the measurement start time. If True, then the argument `time_from_zero` will be ignored. reduce_memory_usage : bool, default False Reduce memory usage by converting all float columns to float32 and searching for minimum dtype that can represent the values found in integer columns. raw : bool | dict, default False The columns will contain the raw values. .. versionadded:: 5.7.0 .. versionchanged:: 8.0.0 Provide individual raw mode based on a dict. The dict keys are channel names and each value is a boolean that sets whether to return raw samples for that channel. The key '__default__' is mandatory and sets the raw mode for all channels not specified. ignore_value2text_conversions : bool, default False Valid only for the channels that have value to text conversions and if `raw=False`. If this is True, then the raw numeric values will be used, and the conversion will not be applied. .. versionadded:: 5.8.0 use_interpolation : bool, default True Option to perform interpolations when multiple timestamp rasters are present. If False, then DataFrame columns will be automatically filled with NaNs where the DataFrame index values are not found in the current column's timestamps. .. versionadded:: 5.11.0 only_basenames : bool, default False Use just the field names, without prefix, for structures and channel arrays. .. versionadded:: 5.13.0 interpolate_outwards_with_nan : bool, default False Use NaN values for the samples that lie outside of the original signal's timestamps. .. versionadded:: 5.15.0 numeric_1D_only : bool, default False Only keep the 1D-columns that have numeric values. use_polars : bool, default False Return polars.DataFrame instead of pandas.DataFrame. .. versionadded:: 8.1.0 Returns ------- dataframe : pandas.DataFrame or polars.DataFrame Channel data. """ if isinstance(raw, dict): if "__default__" not in raw: raise MdfException("The raw argument given as dict must contain the __default__ key") __default__ = raw["__default__"] else: __default__ = raw if channels is not None: mdf = self.filter(channels) result = mdf.to_dataframe( raster=raster, time_from_zero=time_from_zero, empty_channels=empty_channels, use_display_names=use_display_names, time_as_date=time_as_date, reduce_memory_usage=reduce_memory_usage, raw=raw, ignore_value2text_conversions=ignore_value2text_conversions, use_interpolation=use_interpolation, only_basenames=only_basenames, interpolate_outwards_with_nan=interpolate_outwards_with_nan, numeric_1D_only=numeric_1D_only, use_polars=use_polars, ) mdf.close() return result target_byte_order = "<=" if sys.byteorder == "little" else ">=" data: dict[str, NDArray[Any] | pd.Series[Any]] | dict[str, pl.Series] = {} self._mdf._set_temporary_master(None) if raster is not None: if isinstance(raster, (int, float)): raster = float(raster) if raster <= 0: raise MdfException("The raster value must be > 0") raster = self.master_using_raster(raster) elif isinstance(raster, str): raster = self._mdf.get(raster).timestamps else: raster = np.array(raster) master = raster else: masters = {index: self._mdf.get_master(index) for index in self.virtual_groups} if masters: master = reduce(np.union1d, masters.values()) else: master = np.array([], dtype=" 0).flatten() master = master[idx] used_names = UniqueDB() used_names.get_unique_name("timestamps") groups_nr = len(self.virtual_groups) if progress is not None: if callable(progress): progress(0, groups_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr) if progress.stop: raise Terminated for group_index, (virtual_group_index, virtual_group) in enumerate(self.virtual_groups.items()): if virtual_group.cycles_nr == 0 and empty_channels == "skip": continue channels = [ (None, gp_index, ch_index) for gp_index, channel_indexes in self.included_channels(virtual_group_index)[ virtual_group_index ].items() for ch_index in channel_indexes if ch_index != self.masters_db.get(gp_index, None) ] signals = self.select(channels, raw=True, copy_master=False, validate=False) if not signals: continue group_master = signals[0].timestamps for sig in signals: if len(sig) == 0: if empty_channels == "zeros": sig.samples = np.zeros( len(master) if virtual_group.cycles_nr == 0 else virtual_group.cycles_nr, dtype=sig.samples.dtype, ) sig.timestamps = master if virtual_group.cycles_nr == 0 else group_master for signal in signals: if (isinstance(raw, dict) and not raw.get(signal.name, __default__)) or not raw: conversion = signal.conversion if conversion: samples = conversion.convert( signal.samples, ignore_value2text_conversions=ignore_value2text_conversions ) signal.samples = samples signal.raw = False signal.conversion = None if signal.samples.dtype.kind == "S": signal.encoding = "utf-8" if self.version >= "4.00" else "latin-1" for s_index, sig in enumerate(signals): sig = sig.validate(copy=False) if len(sig) == 0: if empty_channels == "zeros": sig.samples = np.zeros( len(master) if virtual_group.cycles_nr == 0 else virtual_group.cycles_nr, dtype=sig.samples.dtype, ) sig.timestamps = master if virtual_group.cycles_nr == 0 else group_master signals[s_index] = sig if use_interpolation or use_polars: same_master = np.array_equal(master, group_master) if not same_master and interpolate_outwards_with_nan and not use_polars: idx = np.argwhere((master >= group_master[0]) & (master <= group_master[-1])).flatten() cycles = len(group_master) signals = [ ( signal.interp( master, integer_interpolation_mode=self._mdf._integer_interpolation, float_interpolation_mode=self._mdf._float_interpolation, ) if not same_master or len(signal) != cycles else signal ) for signal in signals ] if not same_master and interpolate_outwards_with_nan and not use_polars: for sig in signals: sig.timestamps = sig.timestamps[idx] sig.samples = sig.samples[idx] group_master = master if any(len(sig) for sig in signals): signals = [sig for sig in signals if len(sig)] if group_master.dtype.byteorder not in target_byte_order: group_master = group_master.byteswap().view(group_master.dtype.newbyteorder()) index: NDArray[Any] | pd.Index[Any] if signals: diffs = np.diff(group_master, prepend=-np.inf) > 0 if np.all(diffs): if use_polars: index = group_master else: index = pd.Index(group_master, tupleize_cols=False) else: idx = np.argwhere(diffs).flatten() group_master = group_master[idx] if use_polars: index = group_master else: index = pd.Index(group_master, tupleize_cols=False) for sig in signals: sig.samples = sig.samples[idx] sig.timestamps = sig.timestamps[idx] else: if use_polars: index = group_master else: index = pd.Index(group_master, tupleize_cols=False) size = len(index) for sig in signals: if sig.timestamps.dtype.byteorder not in target_byte_order: sig.timestamps = sig.timestamps.byteswap().view(sig.timestamps.dtype.newbyteorder()) if use_polars: sig_index = index else: sig_index = index if len(sig) == size else pd.Index(sig.timestamps, tupleize_cols=False) # byte arrays if len(sig.samples.shape) > 1: if use_display_names: channel_name = list(sig.display_names)[0] if sig.display_names else sig.name else: channel_name = sig.name channel_name = used_names.get_unique_name(channel_name) if sig.samples.dtype.byteorder not in target_byte_order: sig.samples = sig.samples.byteswap().view(sig.samples.dtype.newbyteorder()) if use_polars: data = typing.cast(dict[str, pl.Series], data) data[channel_name] = pl.Series(name=channel_name, values=sig.samples) else: data = typing.cast(dict[str, Union[NDArray[Any], "pd.Series[Any]"]], data) data[channel_name] = pd.Series(list(sig.samples), index=sig_index) # arrays and structures elif sig.samples.dtype.names: if use_polars: data = typing.cast(dict[str, pl.Series], data) for name, values in components( sig.samples, sig.name, used_names, master=sig_index, only_basenames=only_basenames, use_polars=use_polars, ): data[name] = pl.Series(name=name, values=values) else: data = typing.cast(dict[str, Union[NDArray[Any], "pd.Series[Any]"]], data) for name, pd_series in components( sig.samples, sig.name, used_names, master=sig_index, only_basenames=only_basenames, use_polars=use_polars, ): data[name] = pd_series # scalars else: if use_display_names: channel_name = list(sig.display_names)[0] if sig.display_names else sig.name else: channel_name = sig.name channel_name = used_names.get_unique_name(channel_name) if reduce_memory_usage and sig.samples.dtype.kind not in "SU": if sig.samples.size > 0: sig.samples = downcast(sig.samples) if sig.samples.dtype.byteorder not in target_byte_order: sig.samples = sig.samples.byteswap().view(sig.samples.dtype.newbyteorder()) if use_polars: data = typing.cast(dict[str, pl.Series], data) data[channel_name] = pl.Series(name=channel_name, values=sig.samples) else: data = typing.cast(dict[str, Union[NDArray[Any], "pd.Series[Any]"]], data) data[channel_name] = pd.Series(sig.samples, index=sig_index) if progress is not None: if callable(progress): progress(group_index + 1, groups_nr) else: progress.signals.setValue.emit(group_index + 1) if progress.stop: raise Terminated if use_polars: data = typing.cast(dict[str, pl.Series], data) if not POLARS_AVAILABLE: raise MdfException("to_dataframe(use_polars=True) requires polars") if numeric_1D_only: data = {col: pl_series for col, pl_series in data.items() if pl_series.dtype.is_numeric()} if time_as_date: # FIXME: something is wrong with the type of timestamps/master master = self.header.start_time + pd.to_timedelta(master, unit="s") # type: ignore[assignment] elif time_from_zero and len(master): master = master - master[0] # FIXME: something is wrong with the type of timestamps/master data = {"timestamps": master, **data} # type: ignore[assignment] return pl.DataFrame(data) else: data = typing.cast(dict[str, Union[NDArray[Any], "pd.Series[Any]"]], data) strings: dict[str, NDArray[Any] | pd.Series[Any]] = {} nonstrings: dict[str, NDArray[Any] | pd.Series[Any]] = {} for col, vals in data.items(): if vals.dtype.kind == "S": strings[col] = vals else: nonstrings[col] = vals if numeric_1D_only: nonstrings = {col: vals for col, vals in data.items() if vals.dtype.kind in "uif"} strings = {} df = pd.DataFrame(nonstrings, index=master) if strings: df_strings = pd.DataFrame(strings, index=master) df = pd.concat([df, df_strings], axis=1) df.index.name = "timestamps" if time_as_date: delta = pd.to_timedelta(df.index, unit="s") new_index = self.header.start_time + delta df.set_index(new_index, inplace=True) elif time_from_zero and len(master): df.set_index(df.index - df.index[0], inplace=True) return df def extract_bus_logging( self, database_files: dict[BusType, Iterable[DbcFileType]], version: str | v4c.Version | None = None, ignore_value2text_conversion: bool = True, prefix: str = "", progress: Callable[[int, int], None] | Any | None = None, ) -> "MDF": """Extract all possible CAN signals using the provided databases. .. versionchanged:: 6.0.0 Renamed from `extract_can_logging`. Parameters ---------- database_files : dict Each key will contain an iterable of database files for that bus type. The supported bus types are "CAN" and "LIN". The iterables will contain the (database, valid bus) pairs. The database can be a str, pathlib.Path or canmatrix.CanMatrix object. The valid bus is an integer specifying for which bus channel the database can be applied; 0 means any bus channel. .. versionchanged:: 6.0.0 Added canmatrix.CanMatrix type. .. versionchanged:: 6.3.0 Added bus channel filter. version : str, optional Output file version. ignore_value2text_conversion : bool, default True Ignore value to text conversions. .. versionadded:: 5.23.0 prefix : str, default '' Prefix that will be added to the channel group names and signal names in the output file. .. versionadded:: 6.3.0 Returns ------- mdf : MDF New `MDF` object that contains the succesfully extracted signals. Examples -------- Extract CAN and LIN bus logging. >>> mdf = asammdf.MDF(r'bus_logging.mf4') >>> databases = { ... "CAN": [("file1.dbc", 0), ("file2.arxml", 2)], ... "LIN": [("file3.dbc", 0)], ... } >>> extracted = mdf.extract_bus_logging(database_files=databases) Extract just LIN bus logging. >>> mdf = asammdf.MDF(r'bus_logging.mf4') >>> databases = { ... "LIN": [("file3.dbc", 0)], ... } >>> extracted = mdf.extract_bus_logging(database_files=databases) """ if not isinstance(self._mdf, mdf_v4.MDF4): raise MdfException("extract_bus_logging is only supported in MDF4 files") if version is None: version = self.version else: version = validate_version_argument(version) out = MDF( version=version, password=self._mdf._password, use_display_names=True, ) if not isinstance(out._mdf, mdf_v4.MDF4): raise MdfException("extract_bus_logging is only supported in MDF4 files") out.header.start_time = self.header.start_time if database_files.get("CAN", None): out._mdf = self._mdf._extract_can_logging( out._mdf, database_files["CAN"], ignore_value2text_conversion, prefix, progress=progress, ) to_keep: list[tuple[None, int, int]] = [] all_channels: list[tuple[None, int, int]] = [] for i, group in enumerate(out._mdf.groups): for j, channel in enumerate(group.channels[1:], 1): if not all(self._mdf.last_call_info["CAN"]["max_flags"][i][j]): to_keep.append((None, i, j)) all_channels.append((None, i, j)) if to_keep != all_channels: tmp = out.filter(to_keep, out.version) out.close() out = tmp if database_files.get("LIN", None): out._mdf = self._mdf._extract_lin_logging( typing.cast(mdf_v4.MDF4, out._mdf), database_files["LIN"], ignore_value2text_conversion, prefix, progress=progress, ) return out @property def start_time(self) -> datetime: """Getter and setter of the measurement start timestamp. Returns ------- timestamp : datetime.datetime Start timestamp. """ return self.header.start_time @start_time.setter def start_time(self, timestamp: datetime) -> None: self.header.start_time = timestamp def save( self, dst: FileLike | StrPath, overwrite: bool = False, compression: CompressionType = v4c.CompressionAlgorithm.NO_COMPRESSION, progress: Any | None = None, add_history_block: bool = True, ) -> Path: if isinstance(self._mdf, mdf_v4.MDF4): return self._mdf.save( dst, overwrite=overwrite, compression=compression, progress=progress, add_history_block=add_history_block, ) if isinstance(dst, FileLike): raise TypeError(f"'dst' must be of type '{StrPath}'") return self._mdf.save( dst, overwrite=overwrite, compression=compression, progress=progress, add_history_block=add_history_block, ) def cleanup_timestamps( self, minimum: float, maximum: float, exp_min: int = -15, exp_max: int = 15, version: str | Version | None = None, progress: Callable[[int, int], None] | Any | None = None, ) -> "MDF": """Clean up timestamps and convert `MDF` to other version. .. versionadded:: 5.22.0 Parameters ---------- minimum : float Minimum plausible timestamp. maximum : float Maximum plausible timestamp. exp_min : int, default -15 Minimum plausible exponent used for the timestamps float values. exp_max : int, default 15 Maximum plausible exponent used for the timestamps float values. version : str, optional New MDF file version from ('2.00', '2.10', '2.14', '3.00', '3.10', '3.20', '3.30', '4.00', '4.10', '4.11', '4.20'); default is None and in this case the original file version is used. Returns ------- out : MDF New `MDF` object. """ if version is None: version = self.version else: version = validate_version_argument(version) out = MDF(version=version) out.header.start_time = self.header.start_time groups_nr = len(self.virtual_groups) if progress is not None: if callable(progress): progress(0, groups_nr) else: progress.signals.setValue.emit(0) progress.signals.setMaximum.emit(groups_nr) if progress.stop: raise Terminated # walk through all groups and get all channels for i, virtual_group in enumerate(self.virtual_groups): for idx, sigs in enumerate(self._mdf._yield_selected_signals(virtual_group, version=version)): if idx == 0: sigs = typing.cast(list[Signal], sigs) if sigs: t = sigs[0].timestamps if len(t): all_ok, indices = plausible_timestamps(t, minimum, maximum, exp_min, exp_max) if not all_ok: t = t[indices] if len(t): for sig in sigs: sig.samples = sig.samples[indices] sig.timestamps = t if sig.invalidation_bits is not None: sig.invalidation_bits = InvalidationArray(sig.invalidation_bits[indices]) cg = self.groups[virtual_group].channel_group cg_nr = out.append( sigs, acq_name=getattr(cg, "acq_name", None), acq_source=getattr(cg, "acq_source", None), comment=f"Timestamps cleaned up and converted from {self.version} to {version}", common_timebase=True, ) else: break else: sigs = typing.cast(list[tuple[NDArray[Any], None]], sigs) t, _ = sigs[0] if len(t): all_ok, indices = plausible_timestamps(t, minimum, maximum, exp_min, exp_max) if not all_ok: t = t[indices] if len(t): for i, (samples, invalidation_bits) in enumerate(sigs): if invalidation_bits is not None: invalidation_bits = invalidation_bits[indices] samples = samples[indices] sigs[i] = (samples, invalidation_bits) out.extend(cg_nr, sigs) if progress is not None: if callable(progress): progress(i + 1, groups_nr) else: progress.signals.setValue.emit(i + 1) if progress.stop: raise Terminated out._transfer_metadata(self) return out def whereis( self, channel: str, source_name: str | None = None, source_path: str | None = None, acq_name: str | None = None, ) -> tuple[tuple[int, int], ...]: """Get occurrences of channel name in the file. Parameters ---------- channel : str Channel name string. source_name : str, optional Filter occurrences on source name. source_path : str, optional Filter occurrences on source path. acq_name : str, optional Filter occurrences on channel group acquisition name. .. versionadded:: 6.0.0 Returns ------- tuple[tuple[int, int], ...] (gp_idx, cn_idx) pairs. Examples -------- >>> mdf = MDF(file_name) >>> mdf.whereis('VehicleSpeed') # "VehicleSpeed" exists in the file ((1, 2), (2, 4)) >>> mdf.whereis('VehicleSPD') # "VehicleSPD" doesn't exist in the file () """ occurrences = tuple( self._mdf._filter_occurrences( iter(self.channels_db.get(channel, ())), source_name=source_name, source_path=source_path, acq_name=acq_name, ) ) return occurrences def search( self, pattern: str, mode: Literal["plain", "regex", "wildcard"] | SearchMode = SearchMode.plain, case_insensitive: bool = False, ) -> list[str]: """Search channels. .. versionadded:: 7.0.0 Parameters ---------- pattern : str Search pattern. mode : {'plain', 'regex', 'wildcard'} or SearchMode, default SearchMode.plain Search mode. * `plain` : normal name search * `regex` : regular expression based search * `wildcard` : wildcard based search case_insensitive : bool, default False Case sensitivity for the channel name search. Returns ------- channels : list[str] Names of the channels. Raises ------ ValueError Unsupported search mode. Examples -------- >>> mdf = MDF(file_name) >>> mdf.search('*veh*speed*', case_insensitive=True, mode='wildcard') # case insensitive wildcard based search ['vehicleAverageSpeed', 'vehicleInstantSpeed', 'targetVehicleAverageSpeed', 'targetVehicleInstantSpeed'] >>> mdf.search('^vehicle.*Speed$', case_insensitive=False, mode='regex') # case sensitive regex based search ['vehicleAverageSpeed', 'vehicleInstantSpeed'] """ search_mode = SearchMode(mode) if search_mode is SearchMode.plain: if case_insensitive: pattern = pattern.casefold() channels = [name for name in self.channels_db if pattern in name.casefold()] else: channels = [name for name in self.channels_db if pattern in name] elif search_mode is SearchMode.regex: flags = re.IGNORECASE if case_insensitive else 0 compiled_pattern = re.compile(pattern, flags=flags) channels = [name for name in self.channels_db if compiled_pattern.search(name)] elif search_mode is SearchMode.wildcard: wildcard = f"{os.urandom(6).hex()}_WILDCARD_{os.urandom(6).hex()}" pattern = pattern.replace("*", wildcard) pattern = re.escape(pattern) pattern = pattern.replace(wildcard, ".*") flags = re.IGNORECASE if case_insensitive else 0 compiled_pattern = re.compile(pattern, flags=flags) channels = [name for name in self.channels_db if compiled_pattern.search(name)] else: raise ValueError(f"unsupported mode {search_mode}") return channels def _asc_export(self, file_name: Path) -> None: if not isinstance(self._mdf, mdf_v4.MDF4): return groups_count = len(self.groups) dfs = [] for idx in range(groups_count): group = self._mdf.groups[idx] if group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT: source = group.channel_group.acq_source names = {ch.name for ch in group.channels} columns: dict[str, object] if source and source.bus_type == v4c.BUS_TYPE_CAN: if "CAN_DataFrame" in names: data = self._mdf.get("CAN_DataFrame", idx) # , raw=True) elif "CAN_RemoteFrame" in names: data = self._mdf.get("CAN_RemoteFrame", idx, raw=True) elif "CAN_ErrorFrame" in names: data = self._mdf.get("CAN_ErrorFrame", idx, raw=True) else: continue df_index = data.timestamps count = len(df_index) columns = { "timestamps": df_index, "type": np.full(count, "CAN", dtype="O"), "Bus": np.zeros(count, dtype="u1"), "ID": np.full(count, 0xFFFFFFFF, dtype="u4"), "IDE": np.zeros(count, dtype="u1"), "Direction": np.full(count, "Rx", dtype="O"), "Event Type": np.full(count, "CAN Frame", dtype="O"), "Details": np.full(count, "", dtype="O"), "ESI": np.zeros(count, dtype="u1"), "EDL": np.zeros(count, dtype="u1"), "BRS": np.zeros(count, dtype="u1"), "DLC": np.zeros(count, dtype="u1"), "Data Length": np.zeros(count, dtype="u1"), "Data Bytes": np.full(count, "", dtype="O"), "Name": np.full(count, "", dtype="O"), } for string in v4c.CAN_ERROR_TYPES.values(): sys.intern(string) frame_map = None if data.attachment and data.attachment[0]: dbc = load_can_database(data.attachment[1], data.attachment[0]) if dbc: frame_map = {frame.arbitration_id.id: frame.name for frame in dbc} for name in frame_map.values(): sys.intern(name) if data.name == "CAN_DataFrame": columns["Bus"] = data["CAN_DataFrame.BusChannel"].astype("u1") vals = data["CAN_DataFrame.ID"].astype("u4") & 0x1FFFFFFF columns["ID"] = vals if frame_map: columns["Name"] = [frame_map.get(_id, "") for _id in typing.cast(list[int], vals.tolist())] columns["DLC"] = data["CAN_DataFrame.DLC"].astype("u1") columns["Data Length"] = data["CAN_DataFrame.DataLength"].astype("u1") data_bytes = csv_bytearray2hex( pd.Series(list(data["CAN_DataFrame.DataBytes"])).to_numpy(), typing.cast(int, columns["Data Length"]), ) columns["Data Bytes"] = data_bytes if "CAN_DataFrame.Dir" in names: if data["CAN_DataFrame.Dir"].dtype.kind == "S": columns["Direction"] = [ v.decode("utf-8").capitalize() for v in typing.cast(list[bytes], data["CAN_DataFrame.Dir"].tolist()) ] else: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["CAN_DataFrame.Dir"].astype("u1").tolist() ] if "CAN_DataFrame.ESI" in names: columns["ESI"] = data["CAN_DataFrame.ESI"].astype("u1") if "CAN_DataFrame.EDL" in names: columns["EDL"] = data["CAN_DataFrame.EDL"].astype("u1") if "CAN_DataFrame.BRS" in names: columns["BRS"] = data["CAN_DataFrame.BRS"].astype("u1") if "CAN_DataFrame.IDE" in names: columns["IDE"] = data["CAN_DataFrame.IDE"].astype("u1") elif data.name == "CAN_RemoteFrame": columns["Bus"] = data["CAN_RemoteFrame.BusChannel"].astype("u1") vals = data["CAN_RemoteFrame.ID"].astype("u4") & 0x1FFFFFFF columns["ID"] = vals if frame_map: columns["Name"] = [frame_map.get(_id, "") for _id in typing.cast(list[int], vals.tolist())] columns["DLC"] = data["CAN_RemoteFrame.DLC"].astype("u1") columns["Data Length"] = data["CAN_RemoteFrame.DataLength"].astype("u1") columns["Event Type"] = "Remote Frame" if "CAN_RemoteFrame.Dir" in names: if data["CAN_RemoteFrame.Dir"].dtype.kind == "S": columns["Direction"] = [ v.decode("utf-8").capitalize() for v in typing.cast(list[bytes], data["CAN_RemoteFrame.Dir"].tolist()) ] else: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["CAN_RemoteFrame.Dir"].astype("u1").tolist() ] if "CAN_RemoteFrame.IDE" in names: columns["IDE"] = data["CAN_RemoteFrame.IDE"].astype("u1") elif data.name == "CAN_ErrorFrame": if data.samples.dtype.names is None: raise ValueError("names is None") names = set(data.samples.dtype.names) if "CAN_ErrorFrame.BusChannel" in names: columns["Bus"] = data["CAN_ErrorFrame.BusChannel"].astype("u1") if "CAN_ErrorFrame.ID" in names: vals = data["CAN_ErrorFrame.ID"].astype("u4") & 0x1FFFFFFF columns["ID"] = vals if frame_map: columns["Name"] = [ frame_map.get(_id, "") for _id in typing.cast(list[int], vals.tolist()) ] if "CAN_ErrorFrame.DLC" in names: columns["DLC"] = data["CAN_ErrorFrame.DLC"].astype("u1") if "CAN_ErrorFrame.DataLength" in names: columns["Data Length"] = data["CAN_ErrorFrame.DataLength"].astype("u1") columns["Event Type"] = "Error Frame" if "CAN_ErrorFrame.ErrorType" in names: error_types = typing.cast(list[int], data["CAN_ErrorFrame.ErrorType"].astype("u1").tolist()) details = [v4c.CAN_ERROR_TYPES.get(err, "Other error") for err in error_types] columns["Details"] = details if "CAN_ErrorFrame.Dir" in names: if data["CAN_ErrorFrame.Dir"].dtype.kind == "S": columns["Direction"] = [ v.decode("utf-8").capitalize() for v in typing.cast(list[bytes], data["CAN_ErrorFrame.Dir"].tolist()) ] else: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["CAN_ErrorFrame.Dir"].astype("u1").tolist() ] dfs.append(pd.DataFrame(columns, index=df_index)) elif source and source.bus_type == v4c.BUS_TYPE_FLEXRAY: if "FLX_Frame" in names: data = self._mdf.get("FLX_Frame", idx, raw=True) elif "FLX_NullFrame" in names: data = self._mdf.get("FLX_NullFrame", idx, raw=True) elif "FLX_StartCycle" in names: data = self._mdf.get("FLX_StartCycle", idx, raw=True) elif "FLX_Status" in names: data = self._mdf.get("FLX_Status", idx, raw=True) else: continue df_index = data.timestamps count = len(df_index) columns = { "timestamps": df_index, "type": np.full(count, "FLEXRAY", dtype="O"), "Bus": np.zeros(count, dtype="u1"), "ID": np.full(count, 0xFFFF, dtype="u2"), "ControllerFlags": np.zeros(count, dtype="u2"), "FrameFlags": np.zeros(count, dtype="u4"), "Direction": np.full(count, "Rx", dtype="O"), "Cycle": np.full(count, 0xFF, dtype="u1"), "Event Type": np.full(count, "FlexRay Frame", dtype="O"), "Details": np.full(count, "", dtype="O"), "Data Length": np.zeros(count, dtype="u1"), "Payload Length": np.zeros(count, dtype="u1"), "Data Bytes": np.full(count, "", dtype="O"), "Header CRC": np.full(count, 0xFFFF, dtype="u2"), } if data.name == "FLX_Frame": columns["Bus"] = data["FLX_Frame.FlxChannel"].astype("u1") columns["ID"] = data["FLX_Frame.ID"].astype("u2") columns["Cycle"] = data["FLX_Frame.Cycle"].astype("u1") columns["Data Length"] = data["FLX_Frame.DataLength"].astype("u1") columns["Payload Length"] = data["FLX_Frame.PayloadLength"].astype("u1") * 2 data_bytes = csv_bytearray2hex( pd.Series(list(data["FLX_Frame.DataBytes"])), typing.cast(int, columns["Data Length"]), ) columns["Data Bytes"] = data_bytes columns["Header CRC"] = data["FLX_Frame.HeaderCRC"].astype("u2") if "FLX_Frame.Dir" in names: if data["FLX_Frame.Dir"].dtype.kind == "S": columns["Direction"] = [ v.decode("utf-8").capitalize() for v in typing.cast(list[bytes], data["FLX_Frame.Dir"].tolist()) ] else: columns["Direction"] = [ "Tx" if dir else "Rx" for dir in data["FLX_Frame.Dir"].astype("u1").tolist() ] if "FLX_Frame.ControllerFlags" in names: columns["ControllerFlags"] = np.frombuffer( data["FLX_Frame.ControllerFlags"].tobytes(), dtype="3} {dir:<4} {id:>8} {name:>32} {brs} {esi} {dlc:x} {data_length:>2} {data} 0 0 {flags:>8x} 0 0 0 0 0\n" ) else: dlc = row["DLC"] data = row["Data Bytes"] id = f"{row['ID']:x}" if row["IDE"]: id = f"{id}x" bus = row["Bus"] dir = row["Direction"] t = row["timestamps"] asc.write(f"{t: 9.6f} {bus} {id:<15} {dir:<4} d {dlc:x} {data}\n") elif row["Event Type"] == "Error Frame": asc.write(f" {row['timestamps']: 9.6f} {row['Bus']} ErrorFrame\n") elif row["Event Type"] == "Remote Frame": dlc = row["DLC"] id = f"{row['ID']:x}" if row["IDE"]: id = f"{id}x" bus = row["Bus"] dir = row["Direction"] t = row["timestamps"] asc.write(f" {t: 9.6f} {bus} {id:<15} {dir:<4} r {dlc:x}\n") elif row["type"] == "FLEXRAY": if row["Event Type"] == "FlexRay Frame": frame_flags = f"{row['FrameFlags']:x}" controller_flags = f"{row['ControllerFlags']:x}" data = row["Data Bytes"] header_crc = f"{row['Header CRC']:x}" data_length = f"{row['Data Length']:x}" payload_length = f"{row['Payload Length']:x}" bus = f"{row['Bus'] + 1:x}" slot = f"{row['ID']:x}" cycle = f"{row['Cycle']:x}" dir = row["Direction"] t = row["timestamps"] asc.write( f" {t: 9.6f} Fr RMSG 0 0 1 {bus} {slot} {cycle} {dir} 0 {frame_flags} 5 {controller_flags} {header_crc} x {payload_length} {data_length} {data} 0 0 0\n" ) elif row["Event Type"] == "FlexRay NullFrame": frame_flags = f"{row['FrameFlags']:x}" controller_flags = f"{row['ControllerFlags']:x}" header_crc = f"{row['Header CRC']:x}" payload_length = f"{row['Payload Length']:x}" bus = f"{row['Bus'] + 1:x}" slot = f"{row['ID']:x}" cycle = f"{row['Cycle']:x}" dir = row["Direction"] t = row["timestamps"] asc.write( f" {t: 9.6f} Fr RMSG 0 0 1 {bus} {slot} {cycle} {dir} 0 {frame_flags} 5 {controller_flags} {header_crc} x {payload_length} 0 0 0 0\n" ) if __name__ == "__main__": pass asammdf-8.5.1/src/asammdf/py.typed000066400000000000000000000000001502633300400170150ustar00rootroot00000000000000asammdf-8.5.1/src/asammdf/signal.py000066400000000000000000001712341502633300400171670ustar00rootroot00000000000000"""asammdf `Signal` class module for time-correct signal processing""" from collections.abc import Iterator import logging from pathlib import Path from textwrap import fill from typing import TYPE_CHECKING, Union import numpy as np from numpy.typing import ArrayLike, DTypeLike, NDArray from typing_extensions import Any, overload from .blocks import v2_v3_blocks as v3b from .blocks import v4_blocks as v4b from .blocks.conversion_utils import from_dict from .blocks.options import FloatInterpolation, IntegerInterpolation from .blocks.source_utils import Source from .blocks.types import ( ChannelConversionType, FloatInterpolationModeType, IntInterpolationModeType, SourceType, ) from .blocks.utils import extract_xml_comment, MdfException, SignalFlags from .version import __version__ if TYPE_CHECKING: from mpl_toolkits.mplot3d.art3d import Line3DCollection try: encode = np.strings.encode except: encode = np.char.encode logger = logging.getLogger("asammdf") ORIGIN_UNKNOWN = (-1, -1) class InvalidationArray(np.ndarray[tuple[int], np.dtype[np.bool]]): ORIGIN_UNKNOWN = ORIGIN_UNKNOWN def __new__(cls, input_array: ArrayLike, origin: tuple[int, int] = ORIGIN_UNKNOWN) -> "InvalidationArray": obj = np.asarray(input_array).view(cls) obj.origin = origin return obj def __array_finalize__(self, obj: NDArray[np.bool] | None) -> None: if obj is None: return self.origin: tuple[int, int] = getattr(obj, "origin", ORIGIN_UNKNOWN) class Signal: """The `Signal` represents a channel described by its samples and timestamps. It can perform arithmetic operations against other `Signal` objects or numeric types. The operations are computed in respect to the timestamps (time-correct). The non-float signals are not interpolated, instead the last value relative to the current timestamp is used. `samples`, `timestamps` and `name` are mandatory arguments. Parameters ---------- samples : array-like Signal samples. timestamps : array-like Signal timestamps. unit : str, optional Signal unit. name : str Signal name. conversion : dict | channel conversion block, optional Dict that contains extra conversion information about the signal. comment : str, optional Signal comment. raw : bool, default True Signal samples are raw values, with no physical conversion applied. master_metadata : tuple, optional Master name and sync type. display_names : dict, optional Display names used by MDF version 3. attachment : tuple, optional Channel attachment and name from MDF version 4. source : Source, optional Source information named tuple. bit_count : int, optional Bit count; useful for integer channels. invalidation_bits : array-like, optional Channel invalidation bits. encoding : str, optional Encoding for string signals. flags : int, optional Flags for user-defined attributes and stream sync. """ Flags = SignalFlags def __init__( self, samples: ArrayLike, timestamps: ArrayLike, unit: str = "", name: str = "", conversion: dict[str, object] | ChannelConversionType | None = None, comment: str = "", raw: bool = True, master_metadata: tuple[str, int] | None = None, display_names: dict[str, str] | None = None, attachment: tuple[bytes | str, Path, bytes | str] | None = None, source: SourceType | None = None, bit_count: int | None = None, invalidation_bits: ArrayLike | None = None, encoding: str | None = None, group_index: int = -1, channel_index: int = -1, flags: int = Flags.no_flags, virtual_conversion: dict[str, object] | ChannelConversionType | None = None, virtual_master_conversion: dict[str, object] | ChannelConversionType | None = None, ) -> None: if not name: message = ( '"samples", "timestamps" and "name" are mandatory ' f"for Signal class __init__: samples={samples!r}\n" f"timestamps={timestamps!r}\nname={name}" ) raise MdfException(message) else: self.samples: NDArray[Any] if not isinstance(samples, np.ndarray): samples = np.array(samples) kind = samples.dtype.kind if kind == "U": if encoding is None: encodings = ["utf-8", "latin-1"] else: encodings = [encoding, "utf-8", "latin-1"] for _encoding in encodings: try: self.samples = encode(samples, _encoding) break except: continue else: self.samples = encode(samples, encodings[0], errors="ignore") elif kind == "O": self.samples = samples.astype(np.bytes_) else: self.samples = samples else: self.samples = samples self.timestamps: NDArray[Any] if not isinstance(timestamps, np.ndarray): self.timestamps = np.array(timestamps, dtype=np.float64) else: self.timestamps = timestamps if self.samples.shape[0] != self.timestamps.shape[0]: message = "{} samples and timestamps length mismatch ({} vs {})" message = message.format(name, self.samples.shape[0], self.timestamps.shape[0]) logger.exception(message) raise MdfException(message) self.unit = unit self.name = name self.comment = comment self.flags = flags self._plot_axis: Line3DCollection | None = None self.raw = raw self.master_metadata = master_metadata self.display_names = display_names or {} self.attachment = attachment self.encoding = encoding self.group_index = group_index self.channel_index = channel_index self._invalidation_bits = InvalidationArray(invalidation_bits) if invalidation_bits is not None else None self.source: Source | None if source: if not isinstance(source, Source): self.source = Source.from_source(source) else: self.source = source else: self.source = None if bit_count is None: self.bit_count = self.samples.dtype.itemsize * 8 else: self.bit_count = bit_count self.conversion: ChannelConversionType | None if conversion: if not isinstance(conversion, (v4b.ChannelConversion, v3b.ChannelConversion)): self.conversion = from_dict(conversion) else: self.conversion = conversion else: self.conversion = None self.virtual_conversion: ChannelConversionType | None if self.flags & self.Flags.virtual: if not isinstance(virtual_conversion, (v4b.ChannelConversion, v3b.ChannelConversion)): self.virtual_conversion = from_dict(virtual_conversion) else: self.virtual_conversion = virtual_conversion else: self.virtual_conversion = None self.virtual_master_conversion: ChannelConversionType | None if self.flags & self.Flags.virtual_master: if not isinstance(virtual_master_conversion, (v4b.ChannelConversion, v3b.ChannelConversion)): self.virtual_master_conversion = from_dict(virtual_master_conversion) else: self.virtual_master_conversion = virtual_master_conversion else: self.virtual_master_conversion = None @property def invalidation_bits(self) -> InvalidationArray | None: return self._invalidation_bits @invalidation_bits.setter def invalidation_bits(self, value: ArrayLike | None) -> None: if value is None: self._invalidation_bits = None else: if not isinstance(value, InvalidationArray): value = InvalidationArray(value) if value.shape[0] != self.samples.shape[0]: message = "{} samples and invalidation bits length mismatch ({} vs {})" message = message.format(self.name, self.samples.shape[0], value.shape[0]) logger.exception(message) raise MdfException(message) self._invalidation_bits = value def __repr__(self) -> str: return f""" """ def plot(self, validate: bool = True) -> None: """Plot Signal samples. Pyqtgraph is used if it is available; in this case see the GUI plot documentation to see the available commands. Parameters ---------- validate : bool, default True Apply the invalidation bits. """ try: from .gui.plot import plot plot(self, validate=True) return except: try: import matplotlib.pyplot as plt from matplotlib.widgets import Slider from mpl_toolkits.mplot3d import Axes3D except ImportError: logging.warning("Signal plotting requires pyqtgraph or matplotlib") return if len(self.samples.shape) <= 1 and self.samples.dtype.names is None: fig = plt.figure() if fig.canvas.manager: fig.canvas.manager.set_window_title(self.name) fig.text( 0.95, 0.05, f"asammdf {__version__}", fontsize=8, color="red", ha="right", va="top", alpha=0.5, ) name = self.name if self.comment: comment = self.comment.replace("$", "") comment = extract_xml_comment(comment) comment = fill(comment, 120).replace("\\n", " ") title = f"{name}\n({comment})" plt.title(title) else: plt.title(name) try: if not self.master_metadata: plt.xlabel("Time [s]") plt.ylabel(f"[{self.unit}]") plt.plot(self.timestamps, self.samples, "b") plt.plot(self.timestamps, self.samples, "b.") plt.grid(True) plt.show() else: master_name, sync_type = self.master_metadata match sync_type: case 0 | 1: plt.xlabel(f"{master_name} [s]") case 2: plt.xlabel(f"{master_name} [deg]") case 3: plt.xlabel(f"{master_name} [m]") case 4: plt.xlabel(f"{master_name} [index]") plt.ylabel(f"[{self.unit}]") plt.plot(self.timestamps, self.samples, "b") plt.plot(self.timestamps, self.samples, "b.") plt.grid(True) plt.show() except ValueError: plt.close(fig) else: try: names = self.samples.dtype.names if names is None or len(names) == 1: if names: samples = self.samples[names[0]] else: samples = self.samples shape = samples.shape[1:] fig = plt.figure() if fig.canvas.manager: fig.canvas.manager.set_window_title(self.name) fig.text( 0.95, 0.05, f"asammdf {__version__}", fontsize=8, color="red", ha="right", va="top", alpha=0.5, ) if self.comment: comment = self.comment.replace("$", "") plt.title(f"{self.name}\n({comment})") else: plt.title(self.name) ax: Axes3D = fig.add_subplot(111, projection="3d") # Grab some test data. X = np.array(range(shape[1])) Y = np.array(range(shape[0])) X, Y = np.meshgrid(X, Y) Z = samples[0] # Plot a basic wireframe. self._plot_axis = plot_axis = ax.plot_wireframe(X, Y, Z, rstride=1, cstride=1) # Place Sliders on Graph ax_a = plt.axes((0.25, 0.1, 0.65, 0.03)) # Create Sliders & Determine Range sa = Slider( ax_a, "Time [s]", self.timestamps[0], self.timestamps[-1], valinit=self.timestamps[0], ) def update(val: float) -> None: plot_axis.remove() idx = np.searchsorted(self.timestamps, sa.val, side="right") Z = samples[idx - 1] self._plot_axis = ax.plot_wireframe(X, Y, Z, rstride=1, cstride=1) fig.canvas.draw_idle() sa.on_changed(update) plt.show() else: fig = plt.figure() if fig.canvas.manager: fig.canvas.manager.set_window_title(self.name) fig.text( 0.95, 0.05, f"asammdf {__version__}", fontsize=8, color="red", ha="right", va="top", alpha=0.5, ) if self.comment: comment = self.comment.replace("$", "") plt.title(f"{self.name}\n({comment})") else: plt.title(self.name) ax = fig.add_subplot(111, projection="3d") samples = self.samples[names[0]] axis1 = self.samples[names[1]] axis2 = self.samples[names[2]] # Grab some test data. X, Y = np.meshgrid(axis2[0], axis1[0]) Z = samples[0] # Plot a basic wireframe. self._plot_axis = plot_axis = ax.plot_wireframe(X, Y, Z, rstride=1, cstride=1) # Place Sliders on Graph ax_a = plt.axes((0.25, 0.1, 0.65, 0.03)) # Create Sliders & Determine Range sa = Slider( ax_a, "Time [s]", self.timestamps[0], self.timestamps[-1], valinit=self.timestamps[0], ) def update(val: float) -> None: plot_axis.remove() idx = np.searchsorted(self.timestamps, sa.val, side="right") Z = samples[idx - 1] X, Y = np.meshgrid(axis2[idx - 1], axis1[idx - 1]) self._plot_axis = ax.plot_wireframe(X, Y, Z, rstride=1, cstride=1) fig.canvas.draw_idle() sa.on_changed(update) plt.show() except Exception as err: print(err) def cut( self, start: float | None = None, stop: float | None = None, include_ends: bool = True, integer_interpolation_mode: ( IntInterpolationModeType | IntegerInterpolation ) = IntegerInterpolation.REPEAT_PREVIOUS_SAMPLE, float_interpolation_mode: ( FloatInterpolationModeType | FloatInterpolation ) = FloatInterpolation.LINEAR_INTERPOLATION, ) -> "Signal": """Cut the signal according to the `start` and `stop` values, by using the insertion indexes in the signal's time axis. Parameters ---------- start : float, optional Start timestamp for cutting. stop : float, optional Stop timestamp for cutting. include_ends : bool, default True Include the `start` and `stop` timestamps after cutting the signal. If `start` and `stop` are not found in the original timestamps, then the new samples will be computed using interpolation. integer_interpolation_mode : int, default 0 Interpolation mode for integer signals. * 0 - repeat previous sample * 1 - linear interpolation * 2 - hybrid interpolation: channels with integer data type (raw values) that have a conversion that outputs float values will use linear interpolation, otherwise the previous sample is used .. versionadded:: 6.2.0 float_interpolation_mode : int, default 1 Interpolation mode for float channels. * 0 - repeat previous sample * 1 - linear interpolation .. versionadded:: 6.2.0 Returns ------- result : Signal New `Signal` cut from the original. Examples -------- >>> from asammdf import Signal >>> import numpy as np >>> old_sig = Signal(np.arange(0.03, 100, 0.05), np.arange(0.03, 100, 0.05), name='SIG') >>> new_sig = old_sig.cut(1.0, 10.5) >>> new_sig.timestamps[0], new_sig.timestamps[-1] (1.0, 10.5) >>> new_sig = old_sig.cut(1.0, 10.5, include_ends=False) >>> new_sig.timestamps[0], new_sig.timestamps[-1] (1.03, 10.48) >>> new_sig = old_sig.cut(1.0, 10.5, float_interpolation_mode=0) >>> new_sig.samples[0], new_sig.samples[-1] (0.98, 10.48) """ integer_interpolation_mode = IntegerInterpolation(integer_interpolation_mode) float_interpolation_mode = FloatInterpolation(float_interpolation_mode) if self.samples.size == 0: return Signal( np.array([], dtype=self.samples.dtype), np.array([], dtype=self.timestamps.dtype), self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) invalidation_bits: NDArray[np.bool] | None if start is None: if stop is None: # return the channel uncut result = Signal( self.samples.copy(), self.timestamps.copy(), self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, invalidation_bits=self.invalidation_bits.copy() if self.invalidation_bits is not None else None, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) else: # cut from begining to stop if stop < self.timestamps[0]: result = Signal( np.array([], dtype=self.samples.dtype), np.array([], dtype=self.timestamps.dtype), self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) else: stop_idx = np.searchsorted(self.timestamps, stop, side="right") if include_ends and stop not in self.timestamps and stop < self.timestamps[-1]: interpolated = self.interp( [stop], integer_interpolation_mode=integer_interpolation_mode, float_interpolation_mode=float_interpolation_mode, ) if len(interpolated): samples = np.append(self.samples[:stop_idx], interpolated.samples, axis=0) timestamps = np.append(self.timestamps[:stop_idx], interpolated.timestamps) if self.invalidation_bits is not None and interpolated.invalidation_bits is not None: invalidation_bits = InvalidationArray( np.append( self.invalidation_bits[:stop_idx], interpolated.invalidation_bits, ), self.invalidation_bits.origin, ) else: invalidation_bits = None else: samples = self.samples[:stop_idx].copy() timestamps = self.timestamps[:stop_idx].copy() if self.invalidation_bits is not None: invalidation_bits = self.invalidation_bits[:stop_idx].copy() else: invalidation_bits = None if samples.dtype != self.samples.dtype: samples = samples.astype(self.samples.dtype) result = Signal( samples, timestamps, self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, invalidation_bits=invalidation_bits, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) else: if stop is None: # cut from start to end if start > self.timestamps[-1]: result = Signal( np.array([], dtype=self.samples.dtype), np.array([], dtype=self.timestamps.dtype), self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) else: start_idx = np.searchsorted(self.timestamps, start, side="left") if include_ends and start not in self.timestamps and start > self.timestamps[0]: interpolated = self.interp( [start], integer_interpolation_mode=integer_interpolation_mode, float_interpolation_mode=float_interpolation_mode, ) if len(interpolated): samples = np.append(interpolated.samples, self.samples[start_idx:], axis=0) timestamps = np.append(interpolated.timestamps, self.timestamps[start_idx:]) if self.invalidation_bits is not None and interpolated.invalidation_bits is not None: invalidation_bits = InvalidationArray( np.append( interpolated.invalidation_bits, self.invalidation_bits[start_idx:], ), self.invalidation_bits.origin, ) else: invalidation_bits = None else: samples = self.samples[start_idx:].copy() timestamps = self.timestamps[start_idx:].copy() if self.invalidation_bits is not None: invalidation_bits = self.invalidation_bits[start_idx:].copy() else: invalidation_bits = None if samples.dtype != self.samples.dtype: samples = samples.astype(self.samples.dtype) result = Signal( samples, timestamps, self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, invalidation_bits=invalidation_bits, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) else: # cut between start and stop if start > self.timestamps[-1] or stop < self.timestamps[0]: result = Signal( np.array([], dtype=self.samples.dtype), np.array([], dtype=self.timestamps.dtype), self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) else: start_idx = np.searchsorted(self.timestamps, start, side="left") stop_idx = np.searchsorted(self.timestamps, stop, side="right") if start_idx == stop_idx: if include_ends: if start == stop: ends = np.array([start], dtype=self.timestamps.dtype) else: ends = np.array( [start, stop], dtype=self.timestamps.dtype, ) interpolated = self.interp( ends, integer_interpolation_mode=integer_interpolation_mode, float_interpolation_mode=float_interpolation_mode, ) samples = interpolated.samples timestamps = ends invalidation_bits = interpolated.invalidation_bits else: samples = np.array([], dtype=self.samples.dtype) timestamps = np.array([], dtype=self.timestamps.dtype) if self.invalidation_bits is not None: invalidation_bits = self.invalidation_bits[0:0] else: invalidation_bits = None else: samples = self.samples[start_idx:stop_idx].copy() timestamps = self.timestamps[start_idx:stop_idx].copy() if self.invalidation_bits is not None: invalidation_bits = self.invalidation_bits[start_idx:stop_idx].copy() else: invalidation_bits = None if include_ends and stop not in self.timestamps and stop < self.timestamps[-1]: interpolated = self.interp( [stop], integer_interpolation_mode=integer_interpolation_mode, float_interpolation_mode=float_interpolation_mode, ) if len(interpolated): samples = np.append(samples, interpolated.samples, axis=0) timestamps = np.append(timestamps, interpolated.timestamps) if invalidation_bits is not None and interpolated.invalidation_bits is not None: invalidation_bits = InvalidationArray( np.append( invalidation_bits, interpolated.invalidation_bits, ), interpolated.invalidation_bits.origin, ) if include_ends and start not in self.timestamps and start > self.timestamps[0]: interpolated = self.interp( [start], integer_interpolation_mode=integer_interpolation_mode, float_interpolation_mode=float_interpolation_mode, ) if len(interpolated): samples = np.append(interpolated.samples, samples, axis=0) timestamps = np.append(interpolated.timestamps, timestamps) if invalidation_bits is not None and interpolated.invalidation_bits is not None: invalidation_bits = InvalidationArray( np.append( interpolated.invalidation_bits, invalidation_bits, ), interpolated.invalidation_bits.origin, ) if samples.dtype != self.samples.dtype: samples = samples.astype(self.samples.dtype) result = Signal( samples, timestamps, self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, invalidation_bits=invalidation_bits, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) return result def extend(self, other: "Signal") -> "Signal": """Extend Signal with samples from another Signal. Parameters ---------- other : Signal Returns ------- signal : Signal New extended `Signal`. """ if len(self.timestamps): last_stamp = self.timestamps[-1] else: last_stamp = 0 if len(other): other_first_sample = other.timestamps[0] if last_stamp >= other_first_sample: timestamps = other.timestamps + last_stamp else: timestamps = other.timestamps if self.invalidation_bits is None: if other.invalidation_bits is None: invalidation_bits = None else: invalidation_bits = InvalidationArray( np.concatenate((np.zeros(len(self), dtype=bool), other.invalidation_bits)), other.invalidation_bits.origin, ) else: if other.invalidation_bits is None: invalidation_bits = InvalidationArray( np.concatenate((self.invalidation_bits, np.zeros(len(other), dtype=bool))), self.invalidation_bits.origin, ) else: invalidation_bits = InvalidationArray( np.append(self.invalidation_bits, other.invalidation_bits), self.invalidation_bits.origin ) result = Signal( np.append(self.samples, other.samples, axis=0), np.append(self.timestamps, timestamps), self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, invalidation_bits=invalidation_bits, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) else: result = self return result def interp( self, new_timestamps: NDArray[Any] | list[float], integer_interpolation_mode: ( IntInterpolationModeType | IntegerInterpolation ) = IntegerInterpolation.REPEAT_PREVIOUS_SAMPLE, float_interpolation_mode: ( FloatInterpolationModeType | FloatInterpolation ) = FloatInterpolation.LINEAR_INTERPOLATION, ) -> "Signal": """Return a new `Signal` interpolated using the `new_timestamps`. Parameters ---------- new_timestamps : np.ndarray | list Timestamps used for interpolation. integer_interpolation_mode : int, default 0 Interpolation mode for integer signals. * 0 - repeat previous sample * 1 - linear interpolation * 2 - hybrid interpolation: channels with integer data type (raw values) that have a conversion that outputs float values will use linear interpolation, otherwise the previous sample is used .. versionadded:: 6.2.0 float_interpolation_mode : int, default 1 Interpolation mode for float channels. * 0 - repeat previous sample * 1 - linear interpolation .. versionadded:: 6.2.0 Returns ------- signal : Signal New interpolated `Signal`. """ integer_interpolation_mode = IntegerInterpolation(integer_interpolation_mode) float_interpolation_mode = FloatInterpolation(float_interpolation_mode) if not len(self.samples) or not len(new_timestamps): return Signal( self.samples[:0].copy(), self.timestamps[:0].copy(), self.unit, self.name, comment=self.comment, conversion=self.conversion, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=None, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) else: # # we need to validate first otherwise we can get false invalid data # # if the new timebase and the invalidation bits are aligned in an # # infavorable way # # if self.invalidation_bits is not None: # signal = self.validate() # has_invalidation = True # else: # signal = self # has_invalidation = False signal = self invalidation_bits: NDArray[np.bool] | None = signal.invalidation_bits if not len(signal.samples): return Signal( self.samples[:0].copy(), self.timestamps[:0].copy(), self.unit, self.name, comment=self.comment, conversion=self.conversion, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=None if invalidation_bits is None else np.array([], dtype=bool), encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) if len(signal.samples.shape) > 1: idx = np.searchsorted(signal.timestamps, new_timestamps, side="right") idx -= 1 idx[idx < 0] = 0 s = signal.samples[idx] if invalidation_bits is not None: invalidation_bits = invalidation_bits[idx] else: kind = signal.samples.dtype.kind if kind == "f": if float_interpolation_mode == FloatInterpolation.REPEAT_PREVIOUS_SAMPLE: idx = np.searchsorted(signal.timestamps, new_timestamps, side="right") idx -= 1 idx[idx < 0] = 0 s = signal.samples[idx] if invalidation_bits is not None: invalidation_bits = invalidation_bits[idx] else: s = np.interp(new_timestamps, signal.timestamps, signal.samples) if invalidation_bits is not None: idx = np.searchsorted(signal.timestamps, new_timestamps, side="right") idx -= 1 idx[idx < 0] = 0 invalidation_bits = invalidation_bits[idx] elif kind in "ui": if integer_interpolation_mode == IntegerInterpolation.HYBRID_INTERPOLATION: if signal.raw and signal.conversion: kind = signal.conversion.convert(signal.samples[:1]).dtype.kind if kind == "f": integer_interpolation_mode = IntegerInterpolation.LINEAR_INTERPOLATION if integer_interpolation_mode == IntegerInterpolation.HYBRID_INTERPOLATION: integer_interpolation_mode = IntegerInterpolation.REPEAT_PREVIOUS_SAMPLE if integer_interpolation_mode == IntegerInterpolation.LINEAR_INTERPOLATION: s = np.interp(new_timestamps, signal.timestamps, signal.samples).astype(signal.samples.dtype) if invalidation_bits is not None: idx = np.searchsorted(signal.timestamps, new_timestamps, side="right") idx -= 1 idx[idx < 0] = 0 invalidation_bits = invalidation_bits[idx] elif integer_interpolation_mode == IntegerInterpolation.REPEAT_PREVIOUS_SAMPLE: idx = np.searchsorted(signal.timestamps, new_timestamps, side="right") idx -= 1 idx[idx < 0] = 0 s = signal.samples[idx] if invalidation_bits is not None: invalidation_bits = invalidation_bits[idx] else: idx = np.searchsorted(signal.timestamps, new_timestamps, side="right") idx -= 1 idx[idx < 0] = 0 s = signal.samples[idx] if invalidation_bits is not None: invalidation_bits = invalidation_bits[idx] if s.dtype != self.samples.dtype: s = s.astype(self.samples.dtype) return Signal( s, new_timestamps, self.unit, self.name, comment=self.comment, conversion=self.conversion, source=self.source, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=invalidation_bits, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) def __apply_func(self, other: Union["Signal", NDArray[Any], float] | None, func_name: str) -> "Signal": """Delegate operations to the `samples` attribute, but in a time-correct manner by considering the `timestamps`. """ if isinstance(other, Signal): if len(self) and len(other): start = max(self.timestamps[0], other.timestamps[0]) stop = min(self.timestamps[-1], other.timestamps[-1]) s1 = self.physical().cut(start, stop) s2 = other.physical().cut(start, stop) else: s1 = self s2 = other time = np.union1d(s1.timestamps, s2.timestamps) s1 = s1.interp(time) s2 = s2.interp(time) invalidation_bits: NDArray[np.bool] | None if s1.invalidation_bits is not None or s2.invalidation_bits is not None: if s1.invalidation_bits is None: invalidation_bits = s2.invalidation_bits elif s2.invalidation_bits is None: invalidation_bits = s1.invalidation_bits else: invalidation_bits = s1.invalidation_bits | s2.invalidation_bits else: invalidation_bits = None func = getattr(s1.samples, func_name) conversion = None s = func(s2.samples) elif other is None: s = self.samples conversion = self.conversion time = self.timestamps invalidation_bits = self.invalidation_bits else: func = getattr(self.samples, func_name) s = func(other) conversion = self.conversion time = self.timestamps invalidation_bits = self.invalidation_bits return Signal( samples=s, timestamps=time, unit=self.unit, name=self.name, conversion=conversion, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=invalidation_bits, source=self.source, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) def __pos__(self) -> "Signal": return self def __neg__(self) -> "Signal": return Signal( np.negative(self.samples), self.timestamps, unit=self.unit, name=self.name, conversion=self.conversion, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=self.invalidation_bits, source=self.source, encoding=self.encoding, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) def __round__(self, n: int) -> "Signal": return Signal( np.around(self.samples, n), self.timestamps, unit=self.unit, name=self.name, conversion=self.conversion, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=self.invalidation_bits, source=self.source, encoding=self.encoding, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) def __sub__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__sub__") def __isub__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__sub__(other) def __rsub__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return -self.__sub__(other) def __add__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__add__") def __iadd__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__add__(other) def __radd__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__add__(other) def __truediv__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__truediv__") def __itruediv__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__truediv__(other) def __rtruediv__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__rtruediv__") def __mul__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__mul__") def __imul__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__mul__(other) def __rmul__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__mul__(other) def __floordiv__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__floordiv__") def __ifloordiv__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__truediv__(other) def __rfloordiv__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return 1 / self.__apply_func(other, "__rfloordiv__") def __mod__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__mod__") def __pow__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__pow__") def __and__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__and__") def __or__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__or__") def __xor__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__xor__") def __invert__(self) -> "Signal": s = ~self.samples time = self.timestamps return Signal( s, time, unit=self.unit, name=self.name, conversion=self.conversion, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=self.invalidation_bits, source=self.source, encoding=self.encoding, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) def __lshift__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__lshift__") def __rshift__(self, other: Union["Signal", NDArray[Any], float] | None) -> "Signal": return self.__apply_func(other, "__rshift__") def __lt__(self, other: Union["Signal", NDArray[Any]] | None) -> "Signal": return self.__apply_func(other, "__lt__") def __le__(self, other: Union["Signal", NDArray[Any]] | None) -> "Signal": return self.__apply_func(other, "__le__") def __gt__(self, other: Union["Signal", NDArray[Any]] | None) -> "Signal": return self.__apply_func(other, "__gt__") def __ge__(self, other: Union["Signal", NDArray[Any]] | None) -> "Signal": return self.__apply_func(other, "__ge__") def __eq__(self, other: Union["Signal", NDArray[Any]] | None) -> "Signal": # type: ignore[override] return self.__apply_func(other, "__eq__") def __ne__(self, other: Union["Signal", NDArray[Any]] | None) -> "Signal": # type: ignore[override] return self.__apply_func(other, "__ne__") def __iter__(self) -> Iterator[NDArray[Any] | str]: yield from (self.samples, self.timestamps, self.unit, self.name) def __reversed__(self) -> Iterator[tuple[int, tuple[Any, Any]]]: return enumerate(zip(reversed(self.samples), reversed(self.timestamps), strict=False)) def __len__(self) -> int: return len(self.samples) def __abs__(self) -> "Signal": return Signal( np.fabs(self.samples), self.timestamps, unit=self.unit, name=self.name, conversion=self.conversion, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=self.invalidation_bits, source=self.source, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) @overload def __getitem__(self, val: str) -> NDArray[Any]: ... @overload def __getitem__(self, val: int | slice) -> "Signal": ... def __getitem__(self, val: int | slice | str) -> Union[NDArray[Any], "Signal"]: if isinstance(val, str): return self.samples[val] else: return Signal( self.samples[val], self.timestamps[val], self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, invalidation_bits=self.invalidation_bits[val] if self.invalidation_bits is not None else None, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) def __setitem__(self, idx: Any, val: Any) -> None: self.samples[idx] = val def astype(self, np_type: DTypeLike) -> "Signal": """Return a new `Signal` with samples of dtype `np_type`. Parameters ---------- np_type : np.dtype New numpy dtype. Returns ------- signal : Signal New `Signal` with the samples of dtype `np_type`. """ return Signal( self.samples.astype(np_type), self.timestamps, unit=self.unit, name=self.name, conversion=self.conversion, raw=self.raw, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=self.invalidation_bits, source=self.source, encoding=self.encoding, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) def physical(self, copy: bool = True, ignore_value2text_conversions: bool = False) -> "Signal": """Get the physical sample values. Parameters ---------- copy : bool, default True Copy the samples and timestamps in the returned Signal. .. versionadded:: 7.4.0 ignore_value2text_conversions : bool, default False Make sure that the output signal has numeric samples by ignoring the value to text conversions. .. versionadded:: 8.3.0 Returns ------- phys : Signal New `Signal` with physical values. """ if not self.raw or self.conversion is None: if copy: samples = self.samples.copy() else: samples = self.samples encoding = None else: samples = self.conversion.convert(self.samples, ignore_value2text_conversions=ignore_value2text_conversions) if samples.dtype.kind == "S": encoding = "utf-8" if self.conversion.id == b"##CC" else "latin-1" else: encoding = None return Signal( samples, self.timestamps.copy() if copy else self.timestamps, unit=self.unit, name=self.name, conversion=None, raw=False, master_metadata=self.master_metadata, display_names=self.display_names, attachment=self.attachment, invalidation_bits=self.invalidation_bits, source=self.source, encoding=encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) def validate(self, copy: bool = True) -> "Signal": """Apply invalidation bits if they are available for this signal. Parameters ---------- copy : bool, default True Return a copy of the result. .. versionadded:: 5.12.0 """ if self.invalidation_bits is None: signal = self else: idx = np.nonzero(~self.invalidation_bits)[0] if len(idx) == len(self.samples): signal = self else: signal = Signal( self.samples[idx], self.timestamps[idx], self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, invalidation_bits=None, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) if copy: signal = signal.copy() return signal def copy(self) -> "Signal": """Copy all attributes to a new Signal.""" return Signal( self.samples.copy(), self.timestamps.copy(), self.unit, self.name, self.conversion, self.comment, self.raw, self.master_metadata, self.display_names, self.attachment, self.source, self.bit_count, invalidation_bits=self.invalidation_bits.copy() if self.invalidation_bits is not None else None, encoding=self.encoding, group_index=self.group_index, channel_index=self.channel_index, flags=self.flags, virtual_conversion=self.virtual_conversion, virtual_master_conversion=self.virtual_master_conversion, ) if __name__ == "__main__": pass asammdf-8.5.1/src/asammdf/tool.py000066400000000000000000000002321502633300400166540ustar00rootroot00000000000000"""asammdf tool module""" from .version import __version__ as v__ __tool__ = "asammdf" __tool_short__ = "amdf" __vendor__ = "asammdf" __version__ = v__ asammdf-8.5.1/src/asammdf/version.py000066400000000000000000000000641502633300400173670ustar00rootroot00000000000000"""asammdf version module""" __version__ = "8.5.1" asammdf-8.5.1/test/000077500000000000000000000000001502633300400141105ustar00rootroot00000000000000asammdf-8.5.1/test/__init__.py000066400000000000000000000000011502633300400162100ustar00rootroot00000000000000 asammdf-8.5.1/test/almost-J1939.dbc000066400000000000000000000104671502633300400166060ustar00rootroot00000000000000VERSION "" NS_ : NS_DESC_ CM_ BA_DEF_ BA_ VAL_ CAT_DEF_ CAT_ FILTER BA_DEF_DEF_ EV_DATA_ ENVVAR_DATA_ SGTYPE_ SGTYPE_VAL_ BA_DEF_SGTYPE_ BA_SGTYPE_ SIG_TYPE_REF_ VAL_TABLE_ SIG_GROUP_ SIG_VALTYPE_ SIGTYPE_VALTYPE_ BO_TX_BU_ BA_DEF_REL_ BA_REL_ BA_DEF_DEF_REL_ BU_SG_REL_ BU_EV_REL_ BU_BO_REL_ SG_MUL_VAL_ BS_: BU_: VCM BO_ 2364540158 EEC1: 8 Vector__XXX SG_ EngineSpeed : 24|16@1+ (0.125,0) [0|8031.875] "rpm" Vector__XXX BO_ 2566844926 CCVS1: 8 Vector__XXX SG_ WheelBasedVehicleSpeed : 8|16@1+ (0.00390625,0) [0|250.996] "km/h" Vector__XXX BO_ 1791 VCM_NetVer_C01: 8 VCM SG_ VCMNetVer_C01_Major : 8|16@1+ (1,0) [0|65535] "Not Applicable" Vector__XXX SG_ VCMNetVer_C01_Patch : 40|16@1+ (1,0) [0|65535] "Not Applicable" Vector__XXX SG_ VCMNetVer_C01_NetID : 0|8@1+ (1,0) [0|255] "NotApplicable" Vector__XXX SG_ VCMNetVer_C01_Minor : 24|16@1+ (1,0) [0|65535] "Not Applicable" Vector__XXX SG_ VCMNetVer_C01_Dirty : 56|8@1+ (1,0) [0|255] "NotApplicable" Vector__XXX CM_ BO_ 2364540158 "Electronic Engine Controller 1"; CM_ SG_ 2364540158 EngineSpeed "Actual engine speed which is calculated over a minimum crankshaft angle of 720 degrees divided by the number of cylinders.…"; CM_ BO_ 2566844926 "Cruise Control/Vehicle Speed 1"; CM_ SG_ 2566844926 WheelBasedVehicleSpeed "Wheel-Based Vehicle Speed: Speed of the vehicle as calculated from wheel or tailshaft speed."; CM_ BO_ 1791 "Version stuff"; CM_ SG_ 1791 VCMNetVer_C01_Major "Version stuff"; CM_ SG_ 1791 VCMNetVer_C01_Patch "Version stuff"; CM_ SG_ 1791 VCMNetVer_C01_NetID "Version stuff"; CM_ SG_ 1791 VCMNetVer_C01_Minor "Version stuff"; CM_ SG_ 1791 VCMNetVer_C01_Dirty "Version stuff"; BA_DEF_ SG_ "SPN" INT 0 524287; BA_DEF_ BO_ "VFrameFormat" ENUM "StandardCAN","ExtendedCAN","reserved","J1939PG"; BA_DEF_ BO_ "GenMsgSendType" ENUM "Cyclic","NotUsed","NotUsed","NotUsed","NotUsed","NotUsed","NotUsed","IfActive","NoMsgSendType","NotUsed"; BA_DEF_ BO_ "GenMsgCycleTime" INT 0 0; BA_DEF_ "DatabaseVersion" STRING ; BA_DEF_ "BusType" STRING ; BA_DEF_ "ProtocolType" STRING ; BA_DEF_ "DatabaseCompiler" STRING ; BA_DEF_ SG_ "GenSigCycleTimeActive" INT 0 0; BA_DEF_ SG_ "GenSigCycleTime" INT 0 0; BA_DEF_ SG_ "GenSigStartValue" INT 0 0; BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType","NotUsed","NotUsed","NotUsed","NotUsed","NotUsed"; BA_DEF_DEF_ "SPN" 0; BA_DEF_DEF_ "VFrameFormat" "J1939PG"; BA_DEF_DEF_ "DatabaseVersion" ""; BA_DEF_DEF_ "BusType" ""; BA_DEF_DEF_ "ProtocolType" ""; BA_DEF_DEF_ "DatabaseCompiler" ""; BA_DEF_DEF_ "GenMsgSendType" "Cyclic"; BA_DEF_DEF_ "GenMsgCycleTime" 0; BA_DEF_DEF_ "GenSigCycleTimeActive" 0; BA_DEF_DEF_ "GenSigCycleTime" 0; BA_DEF_DEF_ "GenSigSendType" "Cyclic"; BA_DEF_DEF_ "GenSigStartValue" 0; BA_ "ProtocolType" "J1939"; BA_ "BusType" "CAN"; BA_ "DatabaseCompiler" "CSS ELECTRONICS (WWW.CSSELECTRONICS.COM)"; BA_ "DatabaseVersion" "1.0.0"; BA_ "VFrameFormat" BO_ 2364540158 3; BA_ "VFrameFormat" BO_ 2566844926 3; BA_ "VFrameFormat" BO_ 1791 0; BA_ "GenMsgSendType" BO_ 1791 0; BA_ "GenMsgCycleTime" BO_ 1791 1000; BA_ "SPN" SG_ 2364540158 EngineSpeed 190; BA_ "SPN" SG_ 2566844926 WheelBasedVehicleSpeed 84; BA_ "GenSigSendType" SG_ 1791 VCMNetVer_C01_Major 0; BA_ "GenSigCycleTime" SG_ 1791 VCMNetVer_C01_Major 100; BA_ "GenSigCycleTimeActive" SG_ 1791 VCMNetVer_C01_Major 100; BA_ "GenSigStartValue" SG_ 1791 VCMNetVer_C01_Major 2; BA_ "GenSigSendType" SG_ 1791 VCMNetVer_C01_Patch 0; BA_ "GenSigCycleTime" SG_ 1791 VCMNetVer_C01_Patch 100; BA_ "GenSigCycleTimeActive" SG_ 1791 VCMNetVer_C01_Patch 100; BA_ "GenSigSendType" SG_ 1791 VCMNetVer_C01_NetID 0; BA_ "GenSigCycleTime" SG_ 1791 VCMNetVer_C01_NetID 100; BA_ "GenSigCycleTimeActive" SG_ 1791 VCMNetVer_C01_NetID 100; BA_ "GenSigStartValue" SG_ 1791 VCMNetVer_C01_NetID 1; BA_ "GenSigSendType" SG_ 1791 VCMNetVer_C01_Minor 0; BA_ "GenSigCycleTime" SG_ 1791 VCMNetVer_C01_Minor 100; BA_ "GenSigCycleTimeActive" SG_ 1791 VCMNetVer_C01_Minor 100; BA_ "GenSigStartValue" SG_ 1791 VCMNetVer_C01_Minor 7; BA_ "GenSigSendType" SG_ 1791 VCMNetVer_C01_Dirty 0; BA_ "GenSigCycleTime" SG_ 1791 VCMNetVer_C01_Dirty 100; BA_ "GenSigCycleTimeActive" SG_ 1791 VCMNetVer_C01_Dirty 100; asammdf-8.5.1/test/asammdf/000077500000000000000000000000001502633300400155205ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/__init__.py000066400000000000000000000000001502633300400176170ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/000077500000000000000000000000001502633300400163045ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/__init__.py000066400000000000000000000000001502633300400204030ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/dialogs/000077500000000000000000000000001502633300400177265ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/dialogs/__init__.py000066400000000000000000000000001502633300400220250ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/dialogs/test_FunctionsManagerDialog.py000066400000000000000000000447021502633300400257310ustar00rootroot00000000000000import copy import inspect import json import pathlib from unittest import mock from PySide6 import QtCore, QtTest from asammdf.gui.dialogs.functions_manager import FunctionsManagerDialog from test.asammdf.gui.resources.functions import ( Function2, gray2dec, maximum, rpm_to_rad_per_second, UnresolvedVariable, WrongDefinition, ) from test.asammdf.gui.test_base import TestBase class TestPushButtons(TestBase): def setUp(self) -> None: super().setUp() self.fm = FunctionsManagerDialog({}) def test_PushButton_Add(self): """ Test Scope: - Ensure that Functions can be added. Precondition: - Open Function Manager Widget Events: - Press PushButton "Add" - Press PushButton "Add" Evaluate: - Ensure that two items will be added in functions list """ # Events: QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(2, self.fm.widget.functions_list.count()) for index in range(3, 1): self.assertEqual(f"Function{index}", self.fm.widget.functions_list.item(index - 1)) def test_PushButton_DeleteAll(self): """ Test Scope: - Ensure that all Functions are deleted via PushButton DeleteAll. Preconditions: - Open Function Manager Widget Events: - Press PushButton "Add" - Press PushButton "Add" - Press PushButton "DeleteAll" Evaluate: - Evaluate that items are deleted from functions list. """ # Events: QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) self.assertEqual(2, self.fm.widget.functions_list.count()) for index in range(3, 1): self.assertEqual(f"Function{index}", self.fm.widget.functions_list.item(index - 1)) QtTest.QTest.mouseClick(self.fm.widget.erase_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(0, self.fm.widget.functions_list.count()) def test_PushButton_LoadDefinitions_0(self): """ Test Scope: - Ensure that Functions from '.def' file are loaded in function list Preconditions: - Open Function Manager Widget Events: - Press PushButton "Load Definitions" - Simulate that valid path is provided. Evaluate: - Evaluate that files are loaded into function list. """ definition_file = pathlib.Path(self.resource, "functions_definitions.def") with mock.patch( "asammdf.gui.widgets.functions_manager.QtWidgets.QFileDialog.getOpenFileName" ) as mc_getOpenFileName: mc_getOpenFileName.return_value = definition_file, None QtTest.QTest.mouseClick(self.fm.widget.import_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(4, self.fm.widget.functions_list.count()) self.assertEqual("Function1", self.fm.widget.functions_list.item(0).text()) self.assertEqual("gray2dec", self.fm.widget.functions_list.item(1).text()) self.assertEqual("maximum", self.fm.widget.functions_list.item(2).text()) self.assertEqual("rpm_to_rad_per_second", self.fm.widget.functions_list.item(3).text()) def test_PushButton_LoadDefinitions_1(self): """ Test Scope: - Ensure that Functions from nonexistent '.def' file is handled. Preconditions: - Open Function Manager Widget Events: - Press PushButton "Load Definitions" - Simulate that valid path is provided but file does not exist. Evaluate: - Evaluate that functions from file are loaded into function list. """ definition_file = pathlib.Path(self.test_workspace, "nonexistent.def") with mock.patch( "asammdf.gui.widgets.functions_manager.QtWidgets.QFileDialog.getOpenFileName" ) as mc_getOpenFileName: mc_getOpenFileName.return_value = definition_file, None QtTest.QTest.mouseClick(self.fm.widget.import_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(0, self.fm.widget.functions_list.count()) def test_PushButton_LoadDefinitions_2(self): """ Test Scope: - Ensure that case where import dialog is closed, is handled. Preconditions: - Open Function Manager Widget Events: - Press PushButton "Load Definitions" - Simulate that no valid path is provided. Evaluate: - Evaluate that no functions is loaded to function list. """ with mock.patch( "asammdf.gui.widgets.functions_manager.QtWidgets.QFileDialog.getOpenFileName" ) as mc_getOpenFileName: mc_getOpenFileName.return_value = None, None QtTest.QTest.mouseClick(self.fm.widget.import_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(0, self.fm.widget.functions_list.count()) def test_PushButton_LoadDefinitions_3(self): """ Test Scope: - Ensure that Functions from '.def' file are loaded in function list Preconditions: - Open Function Manager Widget Events: - Press PushButton "Load Definitions" - Simulate that valid path is provided but file does not have correct structure. Evaluate: - Evaluate that no functions is loaded to function list. """ definition_file = pathlib.Path(self.test_workspace, "invalid.def") with open(definition_file, "w+") as fpw: fpw.write(self.id()) with mock.patch( "asammdf.gui.widgets.functions_manager.QtWidgets.QFileDialog.getOpenFileName" ) as mc_getOpenFileName: mc_getOpenFileName.return_value = definition_file, None QtTest.QTest.mouseClick(self.fm.widget.import_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(0, self.fm.widget.functions_list.count()) self.mc_ErrorDialog.assert_called() def test_PushButton_LoadDefinitions_4(self): """ Test Scope: - Ensure that Functions from file with extension different from '.def' are not loaded in function list Preconditions: - Open Function Manager Widget Events: - Press PushButton "Load Definitions" - Simulate that valid path is provided but file does not have correct structure. Evaluate: - Evaluate that no functions is loaded to function list. """ definition_file = pathlib.Path(self.test_workspace, "wrong_extension.deff") with open(definition_file, "w+") as fpw: json.dump( {"Function1": "def Function1(t=0):\n return 0"}, fpw, sort_keys=True, indent=2, ) with mock.patch( "asammdf.gui.widgets.functions_manager.QtWidgets.QFileDialog.getOpenFileName" ) as mc_getOpenFileName: mc_getOpenFileName.return_value = definition_file, None QtTest.QTest.mouseClick(self.fm.widget.import_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(0, self.fm.widget.functions_list.count()) def test_PushButton_SaveDefinitions(self): """ Test Scope: - Ensure that Functions from '.def' file are loaded in function list Preconditions: - Open Function Manager Widget Events: - Press PushButton Add - Press PushButton Save Definitions Evaluate: - Evaluate that dialog is open and file can be saved. - Evaluate that new function is present in saved file. """ # Event QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) saved_file = pathlib.Path(self.test_workspace, f"{self.id()}.def") with mock.patch( "asammdf.gui.widgets.functions_manager.QtWidgets.QFileDialog.getSaveFileName" ) as mc_getSaveFileName: mc_getSaveFileName.return_value = str(saved_file), None QtTest.QTest.mouseClick(self.fm.widget.export_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertTrue(saved_file.exists()) with open(saved_file) as fpr: content = json.load(fpr) self.assertDictEqual( content, {"Function1": "def Function1(t=0):\n return 0", "__global_variables__": ""} ) def test_PushButton_CheckSyntax_0(self): """ Test Scope: - Ensure that valid Python Syntax is detected. Events: - Press PushButton Add - Edit Function1 content. Add valid python syntax - Press PushButton Check Syntax Evaluate: - Evaluate that python function is evaluated as valid. """ # Event QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) for f in ( gray2dec, maximum, rpm_to_rad_per_second, ): with self.subTest(f"{self.id}_{f.__name__}"): self.mc_ErrorDialog.reset_mock() source = inspect.getsource(f) self.fm.widget.function_definition.clear() self.fm.widget.function_definition.setPlainText(source) with mock.patch("asammdf.gui.utils.MessageBox.information") as mc_information: QtTest.QTest.mouseClick( self.fm.widget.check_syntax_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.mc_ErrorDialog.assert_not_called() mc_information.assert_called() def test_PushButton_CheckSyntax_1(self): """ Test Scope: - Ensure that invalid Python Syntax is detected. Events: - Press PushButton Add - Edit Function1 content. Add valid python syntax - Press PushButton Check Syntax Evaluate: - Evaluate that python function is evaluated as valid. """ # Event QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) for f in ( Function2, UnresolvedVariable, WrongDefinition, ): with self.subTest(f"{self.id}_{f.__name__}"): self.mc_ErrorDialog.reset_mock() source = inspect.getsource(f) self.fm.widget.function_definition.clear() self.fm.widget.function_definition.setPlainText(source) with mock.patch("asammdf.gui.utils.MessageBox.information") as mc_information: QtTest.QTest.mouseClick( self.fm.widget.check_syntax_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate mc_information.assert_not_called() self.mc_ErrorDialog.assert_called() def test_PushButton_StoreFunctionChanges_0(self): """ Test Scope: - Ensure that function changes are saved. Events: - Press PushButton Add - Edit Function content - Press PushButton Store Function Changes - Press PushButton Save Definitions Evaluate: - Evaluate that name of the Function was changed. - Evaluate that content of the function was changed. """ # Events: QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) self.mouseClick_WidgetItem(self.fm.widget.functions_list.item(0)) source = inspect.getsource(maximum) self.fm.widget.function_definition.clear() self.fm.widget.function_definition.setPlainText(source) QtTest.QTest.mouseClick(self.fm.widget.store_btn, QtCore.Qt.MouseButton.LeftButton) saved_file = pathlib.Path(self.test_workspace, f"{self.id()}.def") with mock.patch( "asammdf.gui.widgets.functions_manager.QtWidgets.QFileDialog.getSaveFileName" ) as mc_getSaveFileName: mc_getSaveFileName.return_value = str(saved_file), None QtTest.QTest.mouseClick(self.fm.widget.export_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertTrue(saved_file.exists()) with open(saved_file) as fpr: content = json.load(fpr) self.assertIn(maximum.__name__, content) self.assertIn(content["maximum"], source) def test_PushButton_StoreFunctionChanges_1(self): """ Test Scope: - Ensure that function changes are saved. Events: - Press PushButton Add - Press PushButton Add - Edit 2nd Function and rename as 1st Function - Press PushButton Store Function Changes Evaluate: - Evaluate that overwriting is not possible """ # Events: QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) self.mouseClick_WidgetItem(self.fm.widget.functions_list.item(0)) function1 = self.fm.widget.function_definition.toPlainText() self.mouseClick_WidgetItem(self.fm.widget.functions_list.item(1)) self.fm.widget.function_definition.clear() self.fm.widget.function_definition.setPlainText(function1) with mock.patch("asammdf.gui.widgets.functions_manager.MessageBox.information") as mc_information: QtTest.QTest.mouseClick(self.fm.widget.store_btn, QtCore.Qt.MouseButton.LeftButton) mc_information.assert_called() def test_PushButton_Apply(self): """ Test Scope: - Ensure that definitions are saved when apply button is pressed. Events: - Press PushButton Add - Press PushButton Add - Update content of current function - Press PushButton Store - Press PushButton 'Apply' Evaluate: - Evaluate that definitions attribute is the same. """ # Events QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) definitions = copy.deepcopy(self.fm.widget.definitions) self.fm.widget.function_definition.clear() source = inspect.getsource(maximum) self.fm.widget.function_definition.setPlainText(source) QtTest.QTest.mouseClick(self.fm.widget.store_btn, QtCore.Qt.MouseButton.LeftButton) QtTest.QTest.mouseClick(self.fm.apply_btn, QtCore.Qt.MouseButton.LeftButton) self.assertEqual("apply", self.fm.pressed_button) self.assertEqual(2, len(self.fm.modified_definitions)) def test_PushButton_Cancel(self): """ Test Scope: - Ensure that definitions are not saved when cancel button is pressed. Events: - Press PushButton Add - Press PushButton Add - Update content of current function - Press PushButton Store - Press PushButton Cancel Evaluate: - Evaluate that definitions attribute is the same. """ # Events QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) self.fm.widget.function_definition.clear() source = inspect.getsource(maximum) self.fm.widget.function_definition.setPlainText(source) QtTest.QTest.mouseClick(self.fm.widget.store_btn, QtCore.Qt.MouseButton.LeftButton) QtTest.QTest.mouseClick(self.fm.cancel_btn, QtCore.Qt.MouseButton.LeftButton) self.assertEqual("cancel", self.fm.pressed_button) self.assertDictEqual({}, self.fm.modified_definitions) class TestTreeWidget(TestBase): def setUp(self) -> None: super().setUp() self.fm = FunctionsManagerDialog({"Function10": "def Function10(t=0):\n return 0"}) def test_KeyPress_Delete(self): """ Test Scope: - Ensure that functions can be deleted from function list. Events: - Press PushButton Add - Press PushButton Add - Press PushButton Add - Select "Function2" - Press Key Delete Evaluate: - Evaluate that "Function2" is no longer part of function list. """ # Events: for _ in range(3): QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) self.assertEqual(4, self.fm.widget.functions_list.count()) self.mouseClick_WidgetItem(self.fm.widget.functions_list.item(2)) QtTest.QTest.keyClick(self.fm.widget.functions_list, QtCore.Qt.Key.Key_Delete) # Evaluate self.assertEqual(3, self.fm.widget.functions_list.count()) self.assertNotEqual("Function2", self.fm.widget.functions_list.item(0)) self.assertNotEqual("Function2", self.fm.widget.functions_list.item(1)) def test_FunctionDefinition_ContentUpdate(self): """ Test Scope: - Ensure that content is updated in Function Definition when Function is changed in FunctionList Events: - Press PushButton Add - Select Function1 - Select Function10 Evaluate: - Evaluate that content of function definition is changed. """ # Event QtTest.QTest.mouseClick(self.fm.widget.add_btn, QtCore.Qt.MouseButton.LeftButton) self.assertEqual(2, self.fm.widget.functions_list.count()) self.mouseClick_WidgetItem(self.fm.widget.functions_list.item(0)) function1 = self.fm.widget.function_definition.toPlainText() self.mouseClick_WidgetItem(self.fm.widget.functions_list.item(1)) function2 = self.fm.widget.function_definition.toPlainText() # Evaluate self.assertNotEqual(function1, function2) asammdf-8.5.1/test/asammdf/gui/dialogs/test_WindowsSelectionDialog.py000066400000000000000000000042531502633300400257630ustar00rootroot00000000000000from PySide6 import QtCore, QtTest from asammdf.gui.dialogs.window_selection_dialog import WindowSelectionDialog from test.asammdf.gui.test_base import TestBase class TestWindowSelectionDialog(TestBase): def test_RadioButtons(self): """ Test Scope: - Ensure that correct radio button is identified Events: - Check 1st Radio Button - Press Apply - Check 2nd Radio Button - Press Cancel - Check 3rd Radio Button Evaluate: - Evaluate that selected type correspond to RadioButton Checked """ options = ("Plot", "Numeric", "Tabular") self.ws = WindowSelectionDialog(options=options) for index, option in enumerate(options): with self.subTest(f"{self.id()}_{option}"): self.ws.showNormal() rb = self.ws.selection_layout.itemAt(index).widget() self.mouseClick_RadioButton(rb) ok, cancel = self.ws.buttonBox.buttons() QtTest.QTest.mouseClick(ok, QtCore.Qt.MouseButton.LeftButton) self.assertEqual(option, self.ws.selected_type()) def test_CheckBoxButton(self): """ Purpose: - Ensure that state of checkbox is stored. Event: - Mark CheckBox Button as checked. - Mark CheckBox Button as unchecked. Evaluate: - Evaluate checkbox state """ self.ws = WindowSelectionDialog() with self.subTest(f"{self.id()}_Checked"): self.ws.showNormal() self.mouseClick_CheckboxButton(self.ws.disable_channels) ok, cancel = self.ws.buttonBox.buttons() QtTest.QTest.mouseClick(ok, QtCore.Qt.MouseButton.LeftButton) self.assertTrue(self.ws.disable_new_channels()) with self.subTest(f"{self.id()}_UnChecked"): self.ws.showNormal() self.mouseClick_CheckboxButton(self.ws.disable_channels) ok, cancel = self.ws.buttonBox.buttons() QtTest.QTest.mouseClick(ok, QtCore.Qt.MouseButton.LeftButton) self.assertFalse(self.ws.disable_new_channels()) asammdf-8.5.1/test/asammdf/gui/resources/000077500000000000000000000000001502633300400203165ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/resources/ASAP2_Demo_V171.mf4000066400000000000000000044637501502633300400232410ustar00rootroot00000000000000MDF 4.10 TGT 15.0##HDh`do)Fuxi<##FH8`Nuxi<##MDFile was created.TgtSvrETAS GmbH7.2wen9feModule: mdf40plugin.dll, Product version: 7.2.10.0, File version: 17.7210.15.52380 Module: mdf_framework.dll, Product version: 7.2.10.0, File version: 17.7210.15.52380 @@@##TX!Engine_1@@@@@@@##TX!Engine_1@@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##TXtime@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MD0.001000@@@@@@##TXs@@@@@@##TX$Zero_to_one@@@@##TX%two_to_three@@@##TX&four_to_seven@@##TX.fourteen_to_seventeen@@##TX.eigteen_to_ninetynine@@##TX hundred##TX#hundredone@@@@@##TX#hundredtwo@@@@@##TX%hundredthree@@@##TX$hundredfour@@@@##TX$hundredfive@@@@##TXHASAM.M.SCALAR.UBYTE.VTAB_RANGE_NO_DEFAULT_VALUE##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.VTAB_RANGE_NO_DEFAULT_VALUE0.001000@@@@@@@##TX@@@@@@@##TXred@@@@##TXorange@##TXyellow@##TXgreen@@##TXblue@@@##TXviolet@##TXFASAM.M.SCALAR.UBYTE.TAB_VERB_NO_DEFAULT_VALUE@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with verbal conversionASAM.M.SCALAR.UBYTE.TAB_VERB_NO_DEFAULT_VALUE0.001000@@@##TX@@@@@@@##TXCASAM.M.SCALAR.UBYTE.TAB_INTP_DEFAULT_VALUE@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_INTP_DEFAULT_VALUE0.001000@@@@##TX"U/ min @@@@@@##TXCASAM.M.SCALAR.UWORD.IDENTICAL.BITMASK_0008@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with Bitmask for a single bitASAM.M.SCALAR.UWORD.IDENTICAL.BITMASK_00080.001000@@@@@@@##TXhours@@##TX6ASAM.M.SCALAR.SLONG.IDENTICAL@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.SLONG.IDENTICAL0.001000@@##TXhours@@##TX$Zero_to_one@@@@##TX%two_to_three@@@##TX&four_to_seven@@##TX.fourteen_to_seventeen@@##TX.eigteen_to_ninetynine@@##TX hundred##TX#hundredone@@@@@##TX#hundredtwo@@@@@##TX%hundredthree@@@##TX$hundredfour@@@@##TX$hundredfive@@@@##TX+out of range value@@@@@##TXEASAM.M.SCALAR.UBYTE.VTAB_RANGE_DEFAULT_VALUE@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.VTAB_RANGE_DEFAULT_VALUE0.001000@@##TX@@@@@@@##TXDASAM.M.SCALAR.UBYTE.IDENTICAL.STATUS_STRING@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with status stringDI.ASAM.M.SCALAR.UBYTE.IDENTICAL.STATUS_STRING0.001000@@@@@@##TXm/s@@@@##TX!SawTooth@@@@@@@##TXSquare@##TXSinus@@##TX,unknown signal type@@@@##TXCASAM.M.SCALAR.UBYTE.TAB_VERB_DEFAULT_VALUE@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_VERB_DEFAULT_VALUE0.001000@@@@##TX@@@@@@@##TXEASAM_[1][0].M.MATRIX_DIM_8_2.UBYTE.IDENTICAL@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[1][0].M.MATRIX_DIM_8_2.UBYTE.IDENTICAL0.001000@@@##TXhours@@##TX6ASAM.M.SCALAR.UBYTE.IDENTICAL@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementDI.ASAM.M.SCALAR.UBYTE.IDENTICAL0.001000@@@@@@@##TXhours@@##TX8ASAM.M.SCALAR.FLOAT32.IDENTICAL##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.FLOAT32.IDENTICAL0.001000##TXhours@@##TXHASAM.M.SCALAR.UBYTE.TAB_NOINTP_NO_DEFAULT_VALUE##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_NOINTP_NO_DEFAULT_VALUE0.001000@@@@@@@##TX"U/ min @@@@@@##TXFASAM.M.SCALAR.UBYTE.TAB_INTP_NO_DEFAULT_VALUE@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_INTP_NO_DEFAULT_VALUE0.001000@##TX"U/ min @@@@@@##TX6ASAM.M.SCALAR.ULONG.IDENTICAL@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.ULONG.IDENTICAL0.001000@@##TXhours@@##TXCASAM.M.SCALAR.UWORD.IDENTICAL.BITMASK_0FF0@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with Bitmask for a bit-areaASAM.M.SCALAR.UWORD.IDENTICAL.BITMASK_0FF00.001000@##TXhours@@##TX6ASAM.M.SCALAR.SBYTE.IDENTICAL@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.SBYTE.IDENTICAL0.001000@@##TXhours@@##TX6ASAM.M.SCALAR.UWORD.IDENTICAL@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.UWORD.IDENTICAL0.001000@@##TXhours@@##TXAASAM.M.SCALAR.FLOAT32.IDENTICAL.DISCRETE@@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.FLOAT32.IDENTICAL.DISCRETE0.001000@@@@@@@##TXhours@@##TX6ASAM.M.SCALAR.SWORD.IDENTICAL@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.SWORD.IDENTICAL0.001000@@##TXhours@@##TX7ASAM.M.SCALAR.UBYTE.HYPERBOLIC@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with status stringDI.ASAM.M.SCALAR.UBYTE.RAT_FUNC.HYPERBOLIC0.001000@@##TXkm/h@@@##TX<ASAM.M.SCALAR.UBYTE.RAT_FUNC.DIV_10@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with status stringDI.ASAM.M.SCALAR.UBYTE.RAT_FUNC.DIV_100.001000@@@@@@##TXkm/h@@@##TXEASAM.M.SCALAR.UBYTE.TAB_NOINTP_DEFAULT_VALUE@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_NOINTP_DEFAULT_VALUE0.001000@@##TX"U/ min @@@@@@##TXIASAM.M.SCALAR.UBYTE.RAT_FUNC.IDENT.STATUS_STRING@@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurement with status stringDI.ASAM.M.SCALAR.UBYTE.IDENTICAL.STATUS_STRING0.001000@@@@@@##TXm/s@@@@##TX!Engine_2@@@@@@@##TX!Engine_2@@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##TXtime@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MD0.001000@@@@@@##TXs@@@@@@##TXAASAM_[0].M.MATRIX_DIM_16.UBYTE.IDENTICAL@@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[0].M.MATRIX_DIM_16.UBYTE.IDENTICAL0.001000@@@@@@@##TXhours@@##TXGASAM_[13][0].M.MATRIX_DIM_16_1.UBYTE.IDENTICAL@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[13][0].M.MATRIX_DIM_16_1.UBYTE.IDENTICAL0.001000@##TXhours@@##TXBASAM_[10].M.MATRIX_DIM_16.UBYTE.IDENTICAL@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[10].M.MATRIX_DIM_16.UBYTE.IDENTICAL0.001000@@@@@@##TXhours@@##TXBASAM_[13].M.MATRIX_DIM_16.UBYTE.IDENTICAL@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[13].M.MATRIX_DIM_16.UBYTE.IDENTICAL0.001000@@@@@@##TXhours@@##TXBASAM_[14].M.MATRIX_DIM_16.UBYTE.IDENTICAL@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[14].M.MATRIX_DIM_16.UBYTE.IDENTICAL0.001000@@@@@@##TXhours@@##TX9ASAM.M.SCALAR.SBYTE.LINEAR_MUL_2@@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.SBYTE.LINEAR_MUL_20.001000@@@@@@@##TXm/s@@@@##TX!Engine_3@@@@@@@##TX!Engine_3@@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##TXtime@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MD0.001000@@@@@@##TXs@@@@@@##TXBASAM_[11].M.MATRIX_DIM_16.UBYTE.IDENTICAL@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[11].M.MATRIX_DIM_16.UBYTE.IDENTICAL0.001000@@@@@@##TXhours@@##TXAASAM_[1].M.MATRIX_DIM_16.UBYTE.IDENTICAL@@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[1].M.MATRIX_DIM_16.UBYTE.IDENTICAL0.001000@@@@@@@##TXhours@@##TX8ASAM.M.SCALAR.FLOAT64.IDENTICAL##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.FLOAT64.IDENTICAL0.001000##TXhours@@##TX"10ms_sync@@@@@@##TX"10ms_sync@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##TXtime@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MD0.010000@@@@@@##TXs@@@@@@##TXBASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL0.010000@@@@@@##TXhours@@##TX:ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4@@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.UBYTE.FORM_X_PLUS_40.010000@@@@@@##TXrpm@@@@##TX#100ms_sync@@@@@##TX#100ms_sync@@@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##TXtime@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MD0.100000@@@@@@##TXs@@@@@@##TX?ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MDScalar measurementASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE0.100000@##TXhours@@##TX$Leading_All@@@@##TX$Leading_All@@@@##TX@@@@@@@##TXtime@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MD0.001000@@@@@@##TXs@@@@@@##TX=ASAM.M.VIRTUAL.SCALAR.SWORD.PHYSICAL@@@##TX@@@@@@@##TX*ETK test device:1@@@@@@##MD>Virtual measurement with 2 * ASAM.M.SCALAR.SBYTE.LINEAR_MUL_2 as input (based on the phys value of ASAM.M.SCALAR.SBYTE.LINEAR_MUL_2ASAM.M.VIRTUAL.SCALAR.SWORD.PHYSICAL0.001000@@##TX@@@@@@@##TXNCalibrationRecordingSingleShotGroup\ETK test device:1@@##TXNCalibrationRecordingSingleShotGroup\ETK test device:1@@##TXINCA@@@##TX!OnChange@@@@@@@##TXtime@@@##TX@@@@@@@##TX>EtasCalibrationDefaultRecordingDevice@@##MD1.000000@@@@@@##TXs@@@@@@##TX($CalibrationLog##TX@@@@@@@##TX>EtasCalibrationDefaultRecordingDevice@@##MD$CalibrationLog1.000000@@@@@@##TX@@@@@@@##TX/$ActiveCalibrationPage@##TX@@@@@@@##TX>EtasCalibrationDefaultRecordingDevice@@##MD$ActiveCalibrationPage1.000000@@@@@@@##TX@@@@@@@##MD&[DATEFORMAT(%m/%d/%Y)]&[TIMEFORMAT(%I:%M:%S %p)]Database: Test Experiment: Experiment Workspace: Workspace Devices: ETK test device:1 Program Description: ASAP2_Demo_V171_draft_10 WP: ASAP2_Demo_V171_draft_11 RP: ASAP2_Demo_V171_draft_10 Date: &[DATE] Time: &[TIME] Pre-trigger Time: &[PRETRIGGERTIME] Recording Duration: &[RECORDINGDURATION] Post-trigger Time: &[POSTTRIGGERTIME] §@ INCA PC Reference Timewen9fe@##CC`po@@##CC`?##CC`x Pp o@?@@@@,@1@2@X@Y@Y@@Y@@Y@Y@Y@Y@Y@Z@Z@@Z@@Z@##CCo@?@@##CCPo@##CC`@h8` o@?@@@@,@1@2@X@Y@Y@@Y@@Y@Y@Y@Y@Y@Z@Z@@Z@@Z@##CC`?##CCP##CC##CC9@??##CCo@??##CCY@[@X@X@Y@@Y@@Z@@@Z@@Z@@Z@ @[@"@@[@$@[@*@[@##CC`?##CC`?##CC@0p@?@?##CC`?##CC`?##CC`@?##CCP##CC??##CC 8Xxo@@@@@@@##CC??##CCY@[@X@X@Y@@Y@@Z@@@Z@@Z@@Z@ @[@"@@[@$@[@*@[@##CCY@[@X@X@Y@@Y@@Z@@@Z@@Z@@Z@ @[@"@@[@$@[@*@[@##CCY@[@X@X@Y@@Y@@Z@@@Z@@Z@@Z@ @[@"@@[@$@[@*@[@##SI8`EE##CN(c@Eb[@FE@##SI8FF##CN`FbWGF`_@##SI8DE##CGhPbDcD| ##SI8@@##CNxep@hdZpA@@##SI8AA##CNPfA@eWC(Bo@##SI8`CC##CN Cf@[DC o@##SI8 @@@##CGhd?f? ##SI8x##CNhXgHSX@##SI8##CNxi8hhSo@##SI8 ##CNPj@i]P o@##SI8 ##CN(k` j^ o@##SI8(##CNl jW X 8@##SI8x##CNl0kUo@##SI80P##CNmlUpo@##SI8p##CNn(xmUo@##SI8(H##CN`oPnWPxo@##SI8##CN8pp(oWo@##SI8 @##CNqpW8p 8@##SI8##CNqXpao@##SI8h##CNr q_o@##SI88##CNsrW0 h 8@##SI8 ##CNptP `sW! O@##SI80"P"##CNHu!8tWH#" `_@##SI8####CN vh#uW$#!8@##SI8 %@%##CNv$uWH&p%# 8@##SI8&&##CNwh&vW'&'8@##SI8(0(##CNx'wWH)`()o@##SI8))##CNyh)pxpX*)*o@##SI8H+h+##CNXz+HypY,++o@##SI8-0-##CN0{, zXP.`-,o@##SI8h ##CN zW -?##SI8(##CGhg{r0.##SI80/P/##CN}/p|Z0/@##SI8x00##CNX~00H}W10o@##SI82(2##CN01 ~W03X2 o@##SI833##CNP3~W43 o@##SI8(5H5##CN4WP6x5 o@##SI866##CNp6W77 o@##SI8@8`8##CN8R`98 `_@##SI8..##CGh|p.X.r0##SI8@:`:##CN :@W ;:@##SI8;;##CN@;ЃW<;o@##SI8=8=##CN<W@>h= o@##SI8>>##CN`>W?> @8@##SI899##CGh09X9r0##SI8pHH##CNPH \PIH@##SI8II##CNpIЇ\J@##SI80H##CGh0GHr0 ##SI8hLL##CNXHLH\XML@##SI8MM##CN0xM 0]N##SI8NO##CNNh^XO##SI8L L##CGh`KЋK ##DG@##DG@##DG@p|##DG@(gh##DG@p؛##DG@0d0##DG@##TXQDate: 22.11.2018 Time: 15:26:35 Start event occurred@@@@@@@##TX($EVENT_COMMENTS##EV`0& .>##DLXx ##DL8( ##DL8y ##DL8##DL8##DL80##DL8##DT HSL,?d dCX2B,X ȱ99?d dCX2B,X E?d dCX2B,X$=樐?d dCX2B,X$ ?d dCX2B,X$/?d dCX2B,XdDT?d dCX2B,Xdsy?d dCX2B,XǕ?d dCX2B,Xl͖?d dCX2B,XJӗ?e!eCY2B-Y/' ژ?e!eCY2B-Y^2?e!eCY2B-Y$V?e!eCY2B-Y${?e!eCY2B-Yd웠?e!eCY2B-Ydy?e!eCY2B-YdJV?e!eCY2B-YҼ?e!eCY2B-YRT?e!eCY2B-Yv?f"fCZ2B.Zr律?f"fCZ2B.ZT?f"fCZ2B.Z㑢?f"fCZ2B.ZJ1?f"fCZ2B.Z?f"fCZ2B.Z2y?f"fCZ2B.Z}-?f"fCZ2B.ZR?!?f"fCZ2B.Z?ZR?f"fCZ2B.Zrd'?g#gC[2B/[n7w?g#gC[2B/[-?g#gC[2B/[?g#gC[2B/[53?g#gC[2B/[2?g#gC[2B/[d`9?g#gC[2B/[R弩?g#gC[2B/[ғ=??g#gC[2B/[r+ ê?g#gC[2B/[F?h$hC\2B0\rZ/ɫ?h$hC\2B0\AL?h$hC\2B0\fTϬ?h$hC\2B0\2!fR?h$hC\2B0\Cyխ?h$hC\2B0\RPX?h$hC\2B0\ ۮ?h$hC\2B0\R^?h$hC\2B0\?h$hC\2B0\9Wj2?i%iC]2B1] s?i%iC]2B1]$}?i%iC]2B1]:\?i%iC]2B1]Y8?i%iC]2B1]z?i%iC]2B1]?i%iC]2B1]i9+?i%iC]2B1]yp>?i%iC]2B1]9=?i%iC]2B1]L?j&jC^2B2^ɘP?j&jC^2B2^MD?j&jC^2B2^Y0b?j&jC^2B2^|dz?j&jC^2B2^t ?j&jC^2B2^+J?j&jC^2B2^i_b?j&jC^2B2^9δ?j&jC^2B2^Й?j&jC^2B2^B#Q?k'kC_2B3_??k'kC_2B3_Iv5Ե?k'kC_2B3_&?k'kC_2B3_qGW?k'kC_2B3_ј?k'kC_2B3_i TZڶ?k'kC_2B3_)U?k'kC_2B3_l]?k'kC_2B3_?k'kC_2B3_81?l(lC`2B4`Ih"?l(lC`2B4`Пc?l(lC`2B4`?l(lC`2B4`g?l(lC`2B4`iE-(?l(lC`2B4`)|i?l(lC`2B4`J??l(lC`2B4`?l(lC`2B4`y"R.?l(lC`2B4`I.Zo? m) mCa2 B5a zd? m) mCa2 B5a? m) mCa2 B5aw4? m) mCa2 B5ai]7v? m) mCa2 B5a)n? m) mCa2 B5a? m) mCa2 B5a@ݛ:? m) mCa2 B5ay%|? m) mCa2 B5aIK? m) mCa2 B5a $7? n* nCb2 B6bo@? n* nCb2 B6bI? n* nCb2 B6bY)ý? n* nCb2 B6b)S`\? n* nCb2 B6b鞗F? n* nCb2 B6bn? n* nCb2 B6by6ɾ? n* nCb2 B6b9= ? n* nCb2 B6b t M? n* nCb2 B6b? o+ oCc2 B7ceп? o+ oCc2 B7cX ? o+ oCc2 B7c)? o+ oCc2 B7ctD\J? o+ oCc2 B7cTJ k? o+ oCc2 B7c<{? o+ oCc2 B7c? o+ oCc2 B7c;n? o+ oCc2 B7cN3? o+ oCc2 B7cć? p, pCd2 B8d-/? p, pCd2 B8d!P? p, pCd2 B8dtyEq? p, pCd2 B8dTY ? p, pCd2 B8d4β? p, pCd2 B8dk? p, pCd2 B8d,X? p, pCd2 B8d? p, pCd2 B8d\c5? p, pCd2 B8dV? p, pCd2 B8djw? q- qCe2 B9elN6/? q- qCe2 B9eT? q- qCe2 B9e4m? q- qCe2 B9e@ }? q- qCe2 B9eA? q- qCe2 B9e܋@j?v2vCj3B>jԴ?v2vCj3B>jZ8Z?v2vCj3B>j@?v2vCj3B>j|o`?v2vCj3B>jdL ?v2vCj3B>jDl?v2vCj3B>j,B1?v2vCj3B>j >?v2vCj3B>jy?v2wCj3B>jԉ%?w3wCk3B?k/CF?w3wCk3B?kLg?w3wCk3B?k|{̇?w3wCk3B?kd!?w3wCk3B?kDV?w3wCk3B?k$m?w3wCk3B?k W ?w3wCk3B?k+?w3wCk3B?k^hL?x4xCl3B@l*-m?x4xCl3B@l?x4xCl3B@l|Pa?x4xCl3B@ldz?x4xCl3B@lD??x4xCl3B@l$B4?x4xCl3B@l 1?x4xCl3B@lkR?x4xCl3B@l3Rs?x4xCl3B@l٢?y5y Cm3BA m>۴?y5y Cm3BA m|%ڟ?y5y Cm3BA m\ud?y5y Cm3BA mDq)?y5y Cm3BA m$7?y5y Cm3BA m HX?y5y Cm3BA mbvy?y5y Cm3BA m;?y5y Cm3BA m?y5y Cm3BA mT?z6z Cn3BB n|R?z6z Cn3BB n\M?z6z Cn3BB nDF>?z6z Cn3BB n$%^?z6z Cn3BB n?z6z Cn3BB n7]`?z6z Cn3BB n$?z6z Cn3BB n?z6z Cn3BB n)0?z6z Cn3BB ntr#?{7{ Co3BC o\ug7D?{7{ Co3BC o<d?{7{ Co3BC o$?{7{ Co3BC og:?{7{ Co3BC o I?{7{ Co3BC o̲q?{7{ Co3BC oAVi?{7{ Co3BC oAJ?{7{ Co3BC oA:R".%?{7{ Co3BC oA.%p5?|8| Cp3BD pAE?|8| Cp3BD pA UV?|8| Cp3BD pAYf?|8| Cp3BD pApw?|8| Cp3BD pAC{?|8| Cp3BD pACޗ?|8| Cp3BD pA@?|8| Cp3BD pAޢ?|8| Cp3BD pA,?|8| Cp3BD pAbzg?}9} Cq3BE qA5?}9} Cq3BE qA,?}9} Cq3BE qArc ?}9} Cq3BE qAb?}9} Cq3BE qAVR+?}9} Cq3BE qAFTM;?}9} Cq3BE qA:'L?}9} Cq3BE qA*y\?}9} Cq3BE qA6l?}9} Cq3BE qA>}?~:~Cr3BFrArҠ?~:~Cr3BFrAE ?~:~Cr3BFrAne?~:~Cr3BFrAǾ?~:~Cr3BFrAƾ *?~:~Cr3BFrAW?~:~Cr3BFrAd?~:~Cr3BFrA7P?~:~Cr3BFrA A?~:~Cr3BFrA~ݎ!?;Cs3BGsArw1?;Cs3BGsAb*A?;Cs3BGsARVx?=Cu3CIuA6ь?=Cu3CIuA&L?=Cu3CIuAw(?=Cu3CIuA Jv?=Cu3CIuAs?=Cu3CIuA?=Cu3CIuA_8?=Cu3CIuAҕ ?>Cv3CJvAh?>Cv3CJvA;I_-?>Cv3CJvA=?>Cv3CJvA#N?>Cv3CJvA2^?>Cv3CJvAzn?>Cv3CJvAnZJ?>Cv3CJvA^-?>Cv3CJvARj?>Cv3CJvABӷq??Cw3CKwA6??Cw3CKwA&yS6??Cw3CKwAL??Cw3CKwA ??Cw3CKwA<]??Cw3CKwAĊ??Cw3CKwAޗ!#??Cw3CKwAj&3??Cw3CKwA=tC??Cw3CKwAHT? @ Cx4 CLxAd? @ Cx4 CLxA] u? @ Cx4 CLxAo? @ Cx4 CLxAz\ѕ? @ Cx4 CLxAj/G4? @ Cx4 CLxA^? @ Cx4 CLxAN? @ Cx4 CLxAB0[? @ Cx4 CLxA2{~? @ Cx4 CLxA"N?!A!Cy4!CMyA!?!A!Cy4!CMyAg?!A!Cy4!CMyAƵF)?!A!Cy4!CMyA9?!A!Cy4!CMyAlQ J?!A!Cy4!CMyA?mZ?!A!Cy4!CMyAj?!A!Cy4!CMyA:2{?!A!Cy4!CMyA?!A!Cy4!CMyA?"B"Cz4"CNzA^$Y?"B"Cz4"CNzAv1r?"B"Cz4"CNzAj?"B"Cz4"CNzAZ ?"B"Cz4"CNzAN[?"B"Cz4"CNzA>}D?"B"Cz4"CNzA2P?"B"Cz4"CNzA"#E ?"B"Cz4"CNzAk/?"B"Cz4"CNzA??#C#C{4#CO{A.0P?#C#C{4#CO{An|`?#C#C{4#CO{AAp?#C#C{4#CO{AW?#C#C{4#CO{Ae?#C#C{4#CO{A?#C#C{4#CO{A~?#C#C{4#CO{A`O?#C#C{4#CO{A3B?#C#C{4#CO{Av?$D$C|4$CP|Af8?$D$C|4$CP|AZi?$D$C|4$CP|AJ?$D$C|4$CP|A>R".%?$D$C|4$CP|A.%p5?$D$C|4$CP|AE?$D$C|4$CP|A UV?$D$C|4$CP|AYf?$D$C|4$CP|Apw?$D$C|4$CP|AC{?%E%C}4% CQ}ACޗ?%E%C}4% CQ}A@?%E%C}4% CQ}Aޢ?%E%C}4% CQ}A,?%E%C}4% CQ}Abzg?%E%C}4% CQ}A5?%E%C}4% CQ}A,?%E%C}4% CQ}Arc ?%E%C}4% CQ}Af?%E%C}4% CQ}AVR+?&F&C~4& CR~AJTM;?&F&C~4& CR~A:'L?&F&C~4& CR~A.y\?&F&C~4& CR~A6l?&F&C~4& CR~A>}?&F&C~4& CR~AsҠ?&F&C~4& CR~AE ?&F&C~4& CR~Ane?&F&C~4& CR~AǾ?&F&C~4& CR~Aƾ *?'G'C4' CSAW?'G'C4' CSAd?'G'C4' CSA7P?'G'C4' CSA A?'G'C4' CSAݎ!?'G'C4' CSArw1?'G'C4' CSAb*A?'G'C4' CSAVVx?)I)C4) CUA6ь?)I)C4) CUA*L?)I)C4) CUAw(?*J*C4*CVAJv?*J*C4*CVAs?*J*C4*CVA?*J*C4*CVA_8?*J*C4*CVAҕ ?*J*C4*CVAh?*J*C4*CVA;I_-?*J*C4*CVA=?*J*C4*CVA#N?*J*C4*CVA2^?+K+C4+CWA~n?+K+C4+CWAnZJ?+K+C4+CWAb-?+K+C4+CWARj?+K+C4+CWAFӷq?+K+C4+CWA6?+K+C4+CWA&yS6?+K+C4+CWAL?+K+C4+CWA ?+K+C4+CWA<]?,L, C4,CX AĊ?,L, C4,CX Aޗ!#?,L, C4,CX Aj&3?,L, C4,CX A=tC?,L, C4,CX AHT?,L, C4,CX Ad?,L, C4,CX A] u?,L, C4,CX Ao?,L, C4,CX Az\ѕ?,L, C4,CX An/G4?-M-!C4-CY!A^?-M-!C4-CY!AR?-M-!C4-CY!AB0[?-M-!C4-CY!A2{~?-M-!C4-CY!A&N?-M-!C4-CY!A!?-M-!C4-CY!A g?-M-!C4-CY!AƵF)?-M-!C4-CY!A9?-M-!C4-CY!AlQ J?.N."C4.CZ"A?mZ?.N."C4.CZ"Aj?.N."C4.CZ"A:2{?.N."C4.CZ"A?.N."C4.CZ"A?.N."C4.CZ"A^$Y?.N."C4.CZ"Az1r?.N."C4.CZ"Aj?.N."C4.CZ"A^ ?.N."C4.CZ"AN[?/O/#C4/C[#AB}D?/O/#C4/C[#A2P?/O/#C4/C[#A"#E ?/O/#C4/C[#Ak/?/O/#C4/C[#A??/O/#C4/C[#A.0P?/O/#C4/C[#An|`?/O/#C4/C[#AAp?/O/#C4/C[#AW?/O/#C4/C[#Ae?0P0$C50C\$A?0P0$C50C\$A~?0P0$C50C\$A`O?0P0$C50C\$A3B?0P0$C50C\$Av?0P0$C50C\$Aj8?0P0$C50C\$ -V4?0P0$C50C\$ ?e ?0P0$C50C\$ )?0P0$C50C\$ 8?1Q1%C51C]% ^"?1Q1%C51C]% *+?1Q1%C51C]% Ϭ[3?1Q1%C51C]% {ӌ;?1Q1%C51C]% C?1Q1%C51C]% m!K?1Q1%C51C]% tH T?1Q1%C51C]% _^oQ\?1Q1%C51C]% Gd?1Q1%C51C]% Q1l?2R2&CŠ52C^& t?2R2&CŠ52C^& C }?2R2&CŠ52C^& 1G?2R2&CŠ52C^& 5Xx?2R2&CŠ52C^& ?2R2&CŠ52C^& %ڝ?2R2&CŠ52C^& ?2R2&CŠ52C^& }I?<\<0C̔5< Ch0 ez?<\<0C̔5< Ch0 i ?<\<0C̔5< Ch0 ?<\<0C̔5< Ch0 Y ?<\<0C̔5< Ch0 ??<\<0C̔5< Ch0 K'p?<\<0C̔5< Ch0 řN?<\<0C̔5< Ch0 =u?=]=1C͕5=!Ci1 l?=]=1C͕5=!Ci1 /V4?=]=1C͕5=!Ci1 ?e ?=]=1C͕5=!Ci1 !)?=]=1C͕5=!Ci1 8?=]=1C͕5=!Ci1 ^"?=]=1C͕5=!Ci1 *+?=]=1C͕5=!Ci1 Ϭ[3?=]=1C͕5=!Ci1 }ӌ;?=]=1C͕5=!Ci1 C?>^>2CΖ5>"Cj2 o!K?>^>2CΖ5>"Cj2 tH T?>^>2CΖ5>"Cj2 a^oQ\?>^>2CΖ5>"Cj2 Gd?>^>2CΖ5>"Cj2 Q1l?>^>2CΖ5>"Cj2 t?>^>2CΖ5>"Cj2 C }?>^>2CΖ5>"Cj2 1G?>^>2CΖ5>"Cj2 5Xx?>^>2CΖ5>"Cj2 ??_?3Cϗ5?#Ck3 'ڝ??_?3Cϗ5?#Ck3 ??_?3Cϗ5?#Ck3 }I?HhH<Cؠ6H,Ct< ez?HhH<Cؠ6H,Ct< i ?HhH<Cؠ6H,Ct< ?IiI=C١6I-Cu= [ ?IiI=C١6I-Cu= ??IiI=C١6I-Cu= M'p?IiI=C١6I-Cu= řN?IiI=C١6I-Cu= ?u?IiI=C١6I-Cu= l?IiI=C١6I-Cu= /V4?IiI=C١6I-Cu= ?e ?IiI=C١6I-Cu= !)?IiI=C١6I-Cu= 8?JjJ>Cڢ6J.Cv> ^"?JjJ>Cڢ6J.Cv> *+?JjJ>Cڢ6J.Cv> Ϭ[3?JjJ>Cڢ6J.Cv> }ӌ;?JjJ>Cڢ6J.Cv> C?JjJ>Cڢ6J.Cv> o!K?JjJ>Cڢ6J.Cv> tH T?JjJ>Cڢ6J.Cv> a^oQ\?JjJ>Cڢ6J.Cv> Gd?JjJ>Cڢ6J.Cv> S1l?KkK?Cۣ6K/Cw? t?KkK?Cۣ6K/Cw? E }?KkK?Cۣ6K/Cw? 1G?KkK?Cۣ6K/Cw? 5Xx?KkK?Cۣ6K/Cw? ?KkK?Cۣ6K/Cw? 'ڝ?KkK?Cۣ6K/Cw? ?KkK?Cۣ6K/Cw? }I?UuUIC7U9CI ez?UuUIC7U9CI i ?UuUIC7U9CI ?UuUIC7U9CI [ ?UuUIC7U9CI ??UuUIC7U9CI M'p?UuUIC7U9CI ǙN?UuUIC7U9CI ?u?VvVJC7V:CJ l?VvVJC7V:CJ 1V4?VvVJC7V:CJ ?e ?VvVJC7V:CJ #)?VvVJC7V:CJ 8?VvVJC7V:CJ ^"?VvVJC7V:CJ *+?VvVJC7V:CJ Ϭ[3?VvVJC7V:CJ ӌ;?VvVJC7V:CJ C?WwWKC7W;CK q!K?WwWKC7W;CK tH T?WwWKC7W;CK a^oQ\?WwWKC7W;CK Gd?WwWKC7W;CK S1l?WwWKC7W;CK t?WwWKC7W;CK E }?WwWKC7W;CK 1G?WwWKC7W;CK 7Xx?WwWKC7W;CK ? XxX LC7XC"N 簱A?"ZzZ"NC7Z>C"N I?"ZzZ"NC7Z>C"N R?"ZzZ"NC7Z>C"N %EZ?"ZzZ"NC7Z>C"N }Lvb?"ZzZ"NC7Z>C"N vsj?"ZzZ"NC7Z>C"N o`r?"ZzZ"NC7Z>C"N I {?"ZzZ"NC7Z>C"N a3:?"ZzZ"NC7Z>C"N l?#[{[#OC7[?C#O S6?#[{[#OC7[?C#O \Λ?#[{[#OC7[?C#O Cك?#[{[#OC7[?C#O ª0?#[{[#OC7[?C#O 5a?#[{[#OC7[?C#O ?#[{[#OC7[?C#O '?#[{[#OC7[?C#O hF?#[{[#OC7[?C#O Rm&?#[{[#OC7[?C#O ;W?$\|\$PC7\@C$P %?$\|\$PC7\@C$P ?$\|\$PC7\@C$P ?$\|\$PC7\@C$P u/?$\|\$PC7\@C$P VM?$\|\$PC7\@C$P g}~?$\|\$PC7\@C$P ߝ?$\|\$PC7\@C$P Y?$\|\$PC7\@C$P p'?$\|\$PC7\@C$P IZC/?%]}]%QC7]AC%Q C@t7?%]}]%QC7]AC%Q ;-g??%]}]%QC7]AC%Q G?%]}]%QC7]AC%Q -P?%]}]%QC7]AC%Q 8X?%]}]%QC7]AC%Q j`?%]}]%QC7]AC%Q )h?%]}]%QC7]AC%Q Pp?%]}]%QC7]AC%Q wx?%]}]%QC7]AC%Q y.?&^~^&RC7^BC&R {b_?&^~^&RC7^BC&R K쐑?&^~^&RC7^BC&R m5™?&^~^&RC7^BC&R :?&^~^&RC7^BC&R _a$?&^~^&RC7^BC&R U?&^~^&RC7^BC&R Qۮ?&^~^&RC7^BC&R շ?&^~^&RC7^BC&R A?&^~^&RC7^BC&R #?'__'SC7_CC'S 3JK?'__'SC7_CC'S jq|?'__'SC7_CC'S %T?'__'SC7_CC'S =?'__'SC7_CC'S '?'__'SC7_CC'S  A?'__'SC7_CC'S 3r ?'__'SC7_CC'S Z?'__'SC7_CC'S ́?'__'SC7_CC'S s%?(`Ā`(TC8`DC(T 6-?(`Ā`(TC8`DC(T eg5?(`Ā`(TC8`DC(T r=?(`Ā`(TC8`DC(T W\DE?(`Ā`(TC8`DC(T EkM?(`Ā`(TC8`DC(T G/,V?(`Ā`(TC8`DC(T ]^?(`Ā`(TC8`DC(T 9f?(`Ā`(TC8`DC(T n?(`Ā`(TC8`DC(T +-v?)aŁa)UC8aEC)U T"?)aŁa)UC8aEC)U {S?)aŁa)UC8aEC)U ?)aŁa)UC8aEC)U {ɵ?)aŁa)UC8aEC)U d?)aŁa)UC8aEC)U N?)aŁa)UC8aEC)U y7>I?)aŁa)UC8aEC)U ez?)aŁa)UC8aEC)U k ?)aŁa)UC8aEC)U ?*bƂb*VC8bFC*V ] ?*bƂb*VC8bFC*V ??*bƂb*VC8bFC*V O'p?*bƂb*VC8bFC*V ǙN?*bƂb*VC8bFC*V ?u?*bƂb*VC8bFC*V l?*bƂb*VC8bFC*Va?*bƂb*VC8bFC*V2?*bƂb*VC8bFC*VK ?*bƂb*VC8bFC*VM d ?+cǃc+WC8cGC+W ~|?+cǃc+WC8cGC+WB?+cǃc+WC8cGC+Wg֭?+cǃc+WC8cGC+W?i?+cǃc+WC8cGC+WP!?+cǃc+WC8cGC+WŐ%?+cǃc+WC8cGC+Wt:$*?+cǃc+WC8cGC+W1(.?+cǃc+WC8cGC+W#KA2?+cǃc+WC8cGC+WY6?,dȄd,XC 8dHC,Xf rr:?,dȄd,XC 8dHC,X#>?,dȄd,XC 8dHC,XB?,dȄd,XC 8dHC,Xk,F?,dȄd,XC 8dHC,XXJ?,dȄd,XC 8dHC,XUSN?,dȄd,XC 8dHC,XS?,dȄd,XC 8dHC,X>zW?,dȄd,XC 8dHC,XJ 7[?,dȄd,XC 8dHC,X(O_?-eɅe-YC!8eIC-YÜ4hc?-eɅe-YC!8eIC-YȀg?-eɅe-YC!8eIC-Y;[k?-eɅe-YC!8eIC-Yo?-eɅe-YC!8eIC-Yos?-eɅe-YC!8eIC-Yqw?-eɅe-YC!8eIC-Y-Y{?-eɅe-YC!8eIC-Y<?-eɅe-YC!8eIC-YB,?-eɅe-YC!8eIC-YbcE?.fʆf.ZC"8fJC.Z,]?.fʆf.ZC"8fJC.Z۠v?.fʆf.ZC"8fJC.Z?.fʆf.ZC"8fJC.ZT?.fʆf.ZC"8fJC.ZD?.fʆf.ZC"8fJC.Zsؠ?.fʆf.ZC"8fJC.Zk?.fʆf.ZC"8fJC.ZF] ?.fʆf.ZC"8fJC.ZҒ"?.fʆf.ZC"8fJC.ZF&;?/gˇg/[C#8gKC/[{S?/gˇg/[C#8gKC/[70Ml?/gˇg/[C#8gKC/[?/gˇg/[C#8gKC/[t?/gˇg/[C#8gKC/[m?/gˇg/[C#8gKC/[)?/gˇg/[C#8gKC/[w.?/gˇg/[C#8gKC/[?/gˇg/[C#8gKC/[^aU?/gˇg/[C#8gKC/[0?0ḧh0\C$8hLC0\J|I?0ḧh0\C$8hLC0\b?0ḧh0\C$8hLC0\P4z?0ḧh0\C$8hLC0\ 6?0ḧh0\C$8hLC0\ʫ?0ḧh0\C$8hLC0\]?0ḧh0\C$8hLC0\B?0ḧh0\C$8hLC0\{?0ḧh0\C$8hLC0\?0ḧh0\C$8hLC0\we&?1i͉i1]C%8iMC1]3>??1i͉i1]C%8iMC1]NW ?1i͉i1]C%8iMC1]ep?1i͉i1]C%8iMC1]h8?1i͉i1]C%8iMC1]%?1i͉i1]C%8iMC1]! ?1i͉i1]C%8iMC1]?1i͉i1]C%8iMC1]Z G#?1i͉i1]C%8iMC1](?1i͉i1]C%8iMC1]m,?2jΊj2^C&8jNC2^i50?2jΊj2^C&8jNC2^LޔM4?2jΊj2^C&8jNC2^S(f8?2jΊj2^C&8jNC2^ǻ~?8pԐ p8dC,9 pTC8dB?8pԐ p8dC,9 pTC8dk,F?8pԐ p8dC,9 pTC8dXJ?9qՑ q9eC-9 qUC9eUSN?9qՑ q9eC-9 qUC9eS?9qՑ q9eC-9 qUC9e>zW?9qՑ q9eC-9 qUC9eJ 7[?9qՑ q9eC-9 qUC9e(O_?9qՑ q9eC-9 qUC9eÜ4hc?9qՑ q9eC-9 qUC9eȀg?9qՑ q9eC-9 qUC9e<[k?9qՑ q9eC-9 qUC9eo?9qՑ q9eC-9 qUC9eos?:r֒r:fC.9rVC:fqw?:r֒r:fC.9rVC:f-Y{?:r֒r:fC.9rVC:f<?:r֒r:fC.9rVC:fB,?:r֒r:fC.9rVC:fccE?:r֒r:fC.9rVC:f,]?:r֒r:fC.9rVC:fܠv?:r֒r:fC.9rVC:f?:r֒r:fC.9rVC:fT?:r֒r:fC.9rVC:fD?;sדs;gC/9sWC;gsؠ?;sדs;gC/9sWC;gk?;sדs;gC/9sWC;gF] ?;sדs;gC/9sWC;gҒ"?;sדs;gC/9sWC;gF&;?;sדs;gC/9sWC;g{S?;sדs;gC/9sWC;g80Ml?;sדs;gC/9sWC;g?;sדs;gC/9sWC;gt?;sדs;gC/9sWC;gm???=uٕu=iC19uYC=iNW ?=uٕu=iC19uYC=iep?=uٕu=iC19uYC=ii8?=uٕu=iC19uYC=i%?>vږv>jC29vZC>j! ?>vږv>jC29vZC>j?>vږv>jC29vZC>j[ G#?>vږv>jC29vZC>j(?>vږv>jC29vZC>jm,?>vږv>jC29vZC>ji50?>vږv>jC29vZC>jLޔM4?>vږv>jC29vZC>j S(f8?>vږv>jC29vZC>jǻ~vږv>jC29vZC>jD??wۗw?kC39w[C?k%vH??wۗw?kC39w[C?k L??wۗw?kC39w[C?ksP??wۗw?kC39w[C?k00U??wۗw?kC39w[C?k*Y??wۗw?kC39w[C?kmWC]??wۗw?kC39w[C?ke[a??wۗw?kC39w[C?k!W~te??wۗw?kC39w[C?ki?@xܘx@lC49x\C@l@m?@xܘx@lC49x\C@lW8q?@xܘx@lC49x\C@l*u?@xܘx@lC49x\C@lО_y?@xܘx@lC49x\C@l~?@xܘx@lC49x\C@lH ?@xܘx@lC49x\C@l9?@xܘx@lC49x\C@lqQ?@xܘx@lC49x\C@l~@j?@xܘx@lC49x\C@l:[Ԃ?AyݙyAmC 59y]CA mg?AyݙyAmC 59y]CA mD?AyݙyAmC 59y]CA mo̞?AyݙyAmC 59y]CA m,."?AyݙyAmC 59y]CA m袵?AyݙyAmC 59y]CA mI?AyݙyAmC 59y]CA ma.?AyݙyAmC 59y]CA mpG?AyݙyAmC 59y]CA mu`?AyݙyAmC 59y]CA mx?BzޚzBnC 69z^CB nS_*?BzޚzBnC 69z^CB nԽ?BzޚzBnC 69z^CB nHQ?BzޚzBnC 69z^CB n?BzޚzBnC 69z^CB nD2x?BzޚzBnC 69z^CB n ?BzޚzBnC 69z^CB n$?BzޚzBnC 69z^CB nz2=?BzޚzBnC 69z^CB n6U?BzޚzBnC 69z^CB nyYn?C{ߛ{CoC 79{_CC o?C{ߛ{CoC 79{_CC okc?C{ߛ{CoC 79{_CC o(?C{ߛ{CoC 79{_CC oL?C{ߛ{CoC 79{_CC o:?C{ߛ{CoC 79{_CC o]6?C{ߛ{CoC 79{_CC oa?C{ߛ{CoC 79{_CC o2?C{ߛ{CoC 79{_CC oK ?C{ߛ{CoC 79{_CC oO d ?D||DpC 89|`CD p ~|?D||DpC 89|`CD pB?D||DpC 89|`CD pg֭?D||DpC 89|`CD p@i?D||DpC 89|`CD pP!?D||DpC 89|`CD pŐ%?D||DpC 89|`CD pv:$*?D||DpC 89|`CD p2(.?D||DpC 89|`CD p#KA2?D||DpC 89|`CD pY6?E}}EqC 99}aCE qg rr:?E}}EqC 99}aCE q$>?E}}EqC 99}aCE qB?E}}EqC 99}aCE qk,F?E}}EqC 99}aCE qYJ?E}}EqC 99}aCE qUSN?E}}EqC 99}aCE qS?E}}EqC 99}aCE q>zW?E}}EqC 99}aCE qK 7[?E}}EqC 99}aCE q(O_?F~~FrC:9~bCFrÜ4hc?F~~FrC:9~bCFrȀg?F~~FrC:9~bCFr<[k?F~~FrC:9~bCFro?F~~FrC:9~bCFros?F~~FrC:9~bCFrqw?F~~FrC:9~bCFr.Y{?F~~FrC:9~bCFr<?F~~FrC:9~bCFrB,?F~~FrC:9~bCFrccE?GGsC;9cCGs ,]?GGsC;9cCGsܠv?GGsC;9cCGs?GGsC;9cCGsU?GGsC;9cCGsD?GGsC;9cCGssؠ?GGsC;9cCGsk?GGsC;9cCGsF] ?GGsC;9cCGsҒ"?GGsC;9cCGsF&;?HHtC<:dCHt|S?HHtC<:dCHt80Ml?HHtC<:dCHt?HHtC<:dCHtt?HHtC<:dCHtm?HHtC<:dCHt*?HHtC<:dCHtw.?HHtC<:dCHt?HHtC<:dCHt_aU?HHtC<:dCHt0?IIuC=:eCIuJ|I?IIuC=:eCIub?IIuC=:eCIuQ4z?IIuC=:eCIu 6?IIuC=:eCIuʫ?IIuC=:eCIu]?IIuC=:eCIuB?IIuC=:eCIu{?IIuC=:eCIu?IIuC=:eCIuxe&?JJvC>:fCJv4>??JJvC>:fCJvNW ?JJvC>:fCJvep?JJvC>:fCJvj8?JJvC>:fCJv&?JJvC>:fCJv! ?JJvC>:fCJv?JJvC>:fCJv[ G#?JJvC>:fCJv(?JJvC>:fCJvm,?KKwC?:gCKwi50?KKwC?:gCKwMޔM4?KKwC?:gCKw S(f8?KKwC?:gCKwǻ~?Q%Q}CE:%mCQ}B?Q%Q}CE:%mCQ}k,F?Q%Q}CE:%mCQ}YJ?R&R~CF:&nCR~USN?R&R~CF:&nCR~S?R&R~CF:&nCR~>zW?R&R~CF:&nCR~K 7[?R&R~CF:&nCR~(O_?R&R~CF:&nCR~Ĝ4hc?R&R~CF:&nCR~Ȁg?R&R~CF:&nCR~=[k?R&R~CF:&nCR~o?R&R~CF:&nCR~os?S'SCG:'oCSrw?S'SCG:'oCS.Y{?S'SCG:'oCS<?S'SCG:'oCSB,?S'SCG:'oCSdcE?S'SCG:'oCS ,]?S'SCG:'oCSܠv?S'SCG:'oCS?S'SCG:'oCSU?S'SCG:'oCSD?T(TCH:(pCTsؠ?T(TCH:(pCTk?T(TCH:(pCTG] ?T(TCH:(pCTҒ"?T(TCH:(pCTF&;?T(TCH:(pCT|S?T(TCH:(pCT90Ml?T(TCH:(pCT?T(TCH:(pCTt?T(TCH:(pCTn?U)UCI:)qCU+?U)UCI:)qCUw.?U)UCI:)qCU?U)UCI:)qCU`aU?U)UCI:)qCU0?U)UCI:)qCUJ|I?U)UCI:)qCUb?U)UCI:)qCUQ4z?U)UCI:)qCU6?U)UCI:)qCUʫ?V*VCJ:*rCV]?V*VCJ:*rCVC?V*VCJ:*rCV|?V*VCJ:*rCV?V*VCJ:*rCVxe&?V*VCJ:*rCV5>??V*VCJ:*rCVNW ?V*VCJ:*rCVep?V*VCJ:*rCVj8?V*VCJ:*rCV&?W+WCK:+sCW! ?W+WCK:+sCW?W+WCK:+sCW\ G#?W+WCK:+sCW(?W+WCK:+sCWm,?W+WCK:+sCWi50?W+WCK:+sCWMޔM4?W+WCK:+sCW S(f8?W+WCK:+sCWǻ~?^2^C&R;2zC^&B?^2^C&R;2zC^&k,F?^2^C&R;2zC^&ZJ?^2^C&R;2zC^&USN?^2^C&R;2zC^&S?^2^C&R;2zC^&>zW?^2^C&R;2zC^&L 7[?^2^C&R;2zC^&(O_?_3_C'S;3{C_'Ŝ4hc?_3_C'S;3{C_'Ȁg?_3_C'S;3{C_'=[k?_3_C'S;3{C_'o?_3_C'S;3{C_'os?_3_C'S;3{C_'sw?_3_C'S;3{C_'/Y{?_3_C'S;3{C_'<?_3_C'S;3{C_'B,?_3_C'S;3{C_'dcE?`4`C(T;4|C`(!,]?`4`C(T;4|C`(ݠv?`4`C(T;4|C`(?`4`C(T;4|C`(V?`4`C(T;4|C`(D?`4`C(T;4|C`(sؠ?`4`C(T;4|C`(k?`4`C(T;4|C`(H] ?`4`C(T;4|C`(Ғ"?`4`C(T;4|C`(F&;?a5aC)U;5}Ca)}S?a5aC)U;5}Ca)90Ml?a5aC)U;5}Ca)?a5aC)U;5}Ca)t?a5aC)U;5}Ca)o?a5aC)U;5}Ca)+?a5aC)U;5}Ca)w.?a5aC)U;5}Ca)?a5aC)U;5}Ca)`aU?a5aC)U;5}Ca)0?b6bC*V;6~Cb*J|I?b6bC*V;6~Cb*b?b6bC*V;6~Cb*R4z?b6bC*V;6~Cb*6?b6bC*V;6~Cb*ʫ?b6bC*V;6~Cb*]?b6bC*V;6~Cb*D?b6bC*V;6~Cb*|?b6bC*V;6~Cb*?b6bC*V;6~Cb*ye&?c7cC+W;7Cc+5>??c7cC+W;7Cc+NW ?c7cC+W;7Cc+ep?c7cC+W;7Cc+j8?c7cC+W;7Cc+'?c7cC+W;7Cc+! ?c7cC+W;7Cc+?c7cC+W;7Cc+\ G#?c7cC+W;7Cc+(?c7cC+W;7Cc+m,?d8dC,X;8Cd,i50?d8dC,X;8Cd,NޔM4?d8dC,X;8Cd, S(f8?d8dC,X;8Cd,ǻ~jC2^<>Cj2Ő%?j>jC2^<>Cj2w:$*?j>jC2^<>Cj24(.?j>jC2^<>Cj2#KA2?j>jC2^<>Cj2Y6?j>jC2^<>Cj2i rr:?j>jC2^<>Cj2%>?j>jC2^<>Cj2B?j>jC2^<>Cj2k,F?j>jC2^<>Cj2ZJ?k?kC3_<?Ck3USN?k?kC3_<?Ck3S?k?kC3_<?Ck3>zW?k?kC3_<?Ck3L 7[?k?kC3_<?Ck3 (O_?k?kC3_<?Ck3Ŝ4hc?k?kC3_<?Ck3Ȁg?k?kC3_<?Ck3>[k?k?kC3_<?Ck3o?k?kC3_<?Ck3os?l@lC4`<@Cl4sw?l@lC4`<@Cl4/Y{?l@lC4`<@Cl4<?l@lC4`<@Cl4B,?l@lC4`<@Cl4ecE?l@lC4`<@Cl4!,]?l@lC4`<@Cl4ޠv?l@lC4`<@Cl4?l@lC4`<@Cl4V?l@lC4`<@Cl4D?m A mC5a<ACm5sؠ?m A mC5a<ACm5k?m A mC5a<ACm5H] ?m A mC5a<ACm5Ғ"?m A mC5a<ACm5F&;?m A mC5a<ACm5}S?m A mC5a<ACm5:0Ml?m A mC5a<ACm5?m A mC5a<ACm5t?m A mC5a<ACm5o?n B nC6b<BCn6+?n B nC6b<BCn6w.?n B nC6b<BCn6?n B nC6b<BCn6aaU?n B nC6b<BCn60?n B nC6b<BCn6J|I?n B nC6b<BCn6b?n B nC6b<BCn6R4z?n B nC6b<BCn66?n B nC6b<BCn6ʫ?o C oC7c<CCo7]?o C oC7c<CCo7D?o C oC7c<CCo7|?o C oC7c<CCo7?o C oC7c<CCo7ye&?o C oC7c<CCo76>??o C oC7c<CCo7NW ?o C oC7c<CCo7ep?o C oC7c<CCo7k8?o C oC7c<CCo7'?p D pC8d<DCp8! ?p D pC8d<DCp8?p D pC8d<DCp8] G#?p D pC8d<DCp8(?p D pC8d<DCp8m,?p D pC8d<DCp8i50?p D pC8d<DCp8NޔM4?p D pC8d<DCp8 S(f8?p D pC8d<DCp8ǻ~j<JCv> ~|?vJvC>j<JCv>B?vJvC>j<JCv>g֭?vJvC>j<JCv>Bi?vJvC>j<JCv>P!?vJvC>j<JCv>Ő%?vJvC>j<JCv>x:$*?vJvC>j<JCv>4(.?vJvC>j<JCv>#KA2?vJvC>j<JCv>Y6?wKwC?k<KCw?i rr:?wKwC?k<KCw?&>?wKwC?k<KCw?B?wKwC?k<KCw?k,F?wKwC?k<KCw?[J?wKwC?k<KCw?USN?wKwC?k<KCw?S?wKwC?k<KCw?>zW?wKwC?k<KCw?M 7[?wKwC?k<KCw? (O_?xLxC@l=LCx@Ŝ4hc?xLxC@l=LCx@Ȁg?xLxC@l=LCx@>[k?xLxC@l=LCx@o?xLxC@l=LCx@os?xLxC@l=LCx@sw?xLxC@l=LCx@0Y{?xLxC@l=LCx@<?xLxC@l=LCx@B,?xLxC@l=LCx@ecE?yMyCA m=MCyA ",]?yMyCA m=MCyA ޠv?yMyCA m=MCyA ?yMyCA m=MCyA W?yMyCA m=MCyA D?yMyCA m=MCyA sؠ?yMyCA m=MCyA k?yMyCA m=MCyA H] ?yMyCA m=MCyA Ғ"?yMyCA m=MCyA F&;?zNzCB n=NCzB ~S?zNzCB n=NCzB :0Ml?zNzCB n=NCzB ?zNzCB n=NCzB t?zNzCB n=NCzB o?zNzCB n=NCzB ,?zNzCB n=NCzB w.?zNzCB n=NCzB ?zNzCB n=NCzB aaU?zNzCB n=NCzB 0?{O{CC o=OC{C J|I?{O{CC o=OC{C b?{O{CC o=OC{C S4z?{O{CC o=OC{C 6?{O{CC o=OC{C ʫ?{O{CC o=OC{C ]?{O{CC o=OC{C D?{O{CC o=OC{C |?{O{CC o=OC{C ?{O{CC o=OC{C ze&?|P|CD p=PC|D 6>??|P|CD p=PC|D NW ?|P|CD p=PC|D ep?|P|CD p=PC|D l8?|P|CD p=PC|D (?|P|CD p=PC|D ! ?|P|CD p=PC|D ?|P|CD p=PC|D ] G#?|P|CD p=PC|D (?|P|CD p=PC|D m,?}Q}CE q=QC}E i50?}Q}CE q=QC}E OޔM4?}Q}CE q=QC}E S(f8?}Q}CE q=QC}E ǻ~?WCKw=WCKB?WCKw=WCKk,F?WCKw=WCK[J? X CLx=XCLUSN? X CLx=XCLS? X CLx=XCL>zW? X CLx=XCLM 7[? X CLx=XCL (O_? X CLx=XCLƜ4hc? X CLx=XCLȀg? X CLx=XCL?[k? X CLx=XCLo? X CLx=XCLos?!Y!CMy=YCMtw?!Y!CMy=YCM0Y{?!Y!CMy=YCM<?!Y!CMy=YCMB,?!Y!CMy=YCMfcE?!Y!CMy=YCM",]?!Y!CMy=YCMޠv?!Y!CMy=YCM?!Y!CMy=YCMW?!Y!CMy=YCMD?"Z"CNz=ZCNsؠ?"Z"CNz=ZCNk?"Z"CNz=ZCNI] ?"Z"CNz=ZCNҒ"?"Z"CNz=ZCNF&;?"Z"CNz=ZCN~S?"Z"CNz=ZCN;0Ml?"Z"CNz=ZCN?"Z"CNz=ZCNt?"Z"CNz=ZCNp?#[#CO{=[CO-?#[#CO{=[COw.?#[#CO{=[CO?#[#CO{=[CObaU?#[#CO{=[CO0?#[#CO{=[COJ|I?#[#CO{=[COb?#[#CO{=[COS4z?#[#CO{=[CO6?#[#CO{=[COʫ?$\$CP|>\CP]?$\$CP|>\CPE?$\$CP|>\CP|?$\$CP|>\CP?$\$CP|>\CPze&?$\$CP|>\CP7>??$\$CP|>\CPNW ?$\$CP|>\CPep?$\$CP|>\CPl8?$\$CP|>\CP(?%]%CQ}>]CQ! ?%]%CQ}>]CQ?%]%CQ}>]CQ^ G#?%]%CQ}>]CQ(?%]%CQ}>]CQm,?%]%CQ}>]CQi50?%]%CQ}>]CQOޔM4?%]%CQ}>]CQ S(f8?%]%CQ}>]CQǻ~]CQ^CRAD?&^&CR~>^CR%vH?&^&CR~>^CR L?&^&CR~>^CRvP?&^&CR~>^CR30U?&^&CR~>^CR*Y?&^&CR~>^CRmWC]?&^&CR~>^CRh[a?&^&CR~>^CR$W~te?&^&CR~>^CRi?'_'CS>_CS@m?'_'CS>_CSZ8q?'_'CS>_CS*u?'_'CS>_CSҞ_y?'_'CS>_CS~?'_'CS>_CSK ?'_'CS>_CS9?'_'CS>_CSqQ?'_'CS>_CS@j?'_'CS>_CS=[Ԃ?(`(CT>`CTg?(`(CT>`CTD?(`(CT>`CTr̞?(`(CT>`CT/."?(`(CT>`CT뢵?(`(CT>`CTI?(`(CT>`CTd.?(`(CT>`CT pG?(`(CT>`CTu`?(`(CT>`CTx?)a)CU>aCUV_*?)a)CU>aCUԽ?)a)CU>aCUHQ?)a)CU>aCU?)a)CU>aCUG2x?)a)CU>aCU ?)a)CU>aCU$?)a)CU>aCU|2=?)a)CU>aCU9U?)a)CU>aCUyYn?*b*CV>bCV?*b*CV>bCVnc?*b*CV>bCV+?*b*CV>bCVL?*b*CV>bCV:?*b*CV>bCV`6?*b*CV>bCVH0@*b*CV>bCVz@*b*CV>bCVJJĥ@*b*CV>bCVȨ@+c+CW>cCWHW@+c+CW>cCWHey @+c+CW>cCW3 @+c+CW>cCW!4@+c+CW>cCWH~@+c+CW>cCWHb@+c+CW>cCWH<@+c+CW>cCWȚ[@+c+CW>cCW @+c+CW>cCWHWL,@,d,CX dCX H99@,d,CX dCX E@,d,CX dCX q{Q!@,d,CX dCX H5^#@,d,CX dCX H._j%@,d,CX dCX Hv'@,d,CX dCX d)@,d,CX dCX H=+@,d,CX dCX Hن-@,d,CX dCX HЧ/@-e-CY!eCY!cN1@-e-CY!eCY!d3@-e-CY!eCY!í5@-e-CY!eCY!H~}7@-e-CY!eCY!H7A9@-e-CY!eCY!:;@-e-CY!eCY!Ș=@-e-CY!eCY!f @@-e-CY!eCY!HU!hB@-e-CY!eCY!H۱"D@.f.CZ"fCZ".F@.f.CZ"fCZ"oPE;H@.f.CZ"fCZ"H GJ@.f.CZ"fCZ"H,SL@.f.CZ"fCZ"H"`N@.f.CZ"fCZ"9llP@.f.CZ"fCZ"FxR@.f.CZ"fCZ"HT@.f.CZ"fCZ"HiIV@.f.CZ"fCZ"Ha#X@/g/C[#gC[#ȿܩZ@/g/C[#gC[#&\@/g/C[#gC[#H|Rp^@/g/C[#gC[#H `@/g/C[#gC[#8b@/g/C[#gC[#ȖMd@/g/C[#gC[#;f@/g/C[#gC[#HSh@/g/C[#gC[#H* k@/g/C[#gC[#ktm@0h0C\$hC\$m%$o@0h0C\$hC\$1q@0h0C\$hC\$H*Q=s@0h0C\$hC\$HTIu@0h0C\$hC\$Uw@0h0C\$hC\$D.by@0h0C\$hC\$Hxn{@0h0C\$hC\$H>z}@0h0C\$hC\$H_ @0h0C\$hC\$ȽU@1i1C]%iC]%m@1i1C]%iC]%Hz'髅@1i1C]%iC]%H2@1i1C]%iC]%H6|ĉ@1i1C]%iC]%ȔVЋ@1i1C]%iC]%ݍ@1i1C]%iC]%HQY@1i1C]%iC]%H@1i1C]%iC]% @@1i1C]%iC]%k6@2j2C^&jC^&ɴ@2j2C^&jC^&H(o&@2j2C^&jC^&H)3@2j2C^&jC^&]?@2j2C^&jC^&BK@2j2C^&jC^&ȠXW@2j2C^&jC^&H;d@2j2C^&jC^&H]̈́p@2j2C^&jC^&Ȼ|@2j2C^&jC^&B@3k3C_'kC_'Hxa@3k3C_'kC_'Hֶ@3k3C_'kC_'H4q@3k3C_'kC_'Ȓ+?@3k3C_'kC_'ƴ@3k3C_'kC_'HOҶ@3k3C_'kC_'HZ߸@3k3C_'kC_'H f@3k3C_'kC_'iϯ@3k3C_'kC_'lj@4l4C`(lC`(H&DC@4l4C`(lC`(H@4l4C`(lC`((@4l4C`(lC`(@s 5@4l4C`(lC`(Ȟ-jA@4l4C`(lC`(HM@4l4C`(lC`(H[Y@4l4C`(lC`(ȹ\Gf@4l4C`(lC`(r@4l4C`(lC`(u~@5 m5Ca)mCa)Hԋ$@5 m5Ca)mCa)H2Fn@5 m5Ca)mCa)Ȑ@5 m5Ca)mCa)@5 m5Ca)mCa)HMuK@5 m5Ca)mCa)H/@5 m5Ca)mCa)H @5 m5Ca)mCa)g(@5 m5Ca)mCa)^r@5 m5Ca)mCa)H$@6 n6Cb*nCb*H@6 n6Cb*nCb*O@6 n6Cb*nCb*>H@6 n6Cb*nCb*H*@6 n6Cb*nCb*H,7@6 n6Cb*nCb*HYwvC@6 n6Cb*nCb*ȷ1O@6 n6Cb*nCb* \@6 n6Cb*nCb*HtSh@6 n6Cb*nCb*H`t@7 o7Cc+oCc+0@7 o7Cc+oCc+Ȏ0@7 o7Cc+oCc+z@7 o7Cc+oCc+HKJĥ@7 o7Cc+oCc+H@7 o7Cc+oCc+W@7 o7Cc+oCc+ey @7 o7Cc+oCc+3 @7 o7Cc+oCc+H"4@7 o7Cc+oCc+H~@8 p8Dd,pCd,b@8 p8Dd,pCd,<@8 p8Dd,pCd,H[@8 p8Dd,pCd,H @8 p8Dd,pCd,HWL,@8 p8Dd,pCd,ȵ99@8 p8Dd,pCd,E@8 p8Dd,pCd,Hr{Q!@8 p8Dd,pCd,H5^#@8 p8Dd,pCd,H._j%@9 q9@De-qCe-Ȍv'@9 q9@De-qCe-d)@9 q9@De-qCe-HI=+@9 q9@De-qCe-Hن-@9 q9@De-qCe-Ч/@9 q9@De-qCe-cN1@9 q9@De-qCe-d3@9 q9@De-qCe-H í5@9 q9@De-qCe-H~}7@9 q9@De-qCe-7A9@:r:Df.rCf.:;@:r:Df.rCf.Ș=@:r:Df.rCf.Hf @@:r:Df.rCf.HU!hB@:r:Df.rCf.ȳ۱"D@:r:Df.rCf..F@:r:Df.rCf.HpPE;H@:r:Df.rCf.H GJ@:r:Df.rCf.H,SL@:r:Df.rCf.Ȋ"`N@;s;Dg/sCg/9llP@;s;Dg/sCg/HGxR@;s;Dg/sCg/HT@;s;Dg/sCg/HiIV@;s;Dg/sCg/a#X@;s;Dg/sCg/ȿܩZ@;s;Dg/sCg/H&\@;s;Dg/sCg/H|Rp^@;s;Dg/sCg/ `@;s;Dg/sCg/8b@<t<Dh0tCh0ȖMd@<t<Dh0tCh0H;f@<t<Dh0tCh0HSh@<t<Dh0tCh0ȱ* k@<t<Dh0tCh0ktm@<t<Dh0tCh0m%$o@<t<Dh0tCh0H1q@<t<Dh0tCh0H*Q=s@<t<Dh0tCh0ȈTIu@<t<Dh0tCh0Uw@=u=@Di1uCi1HE.by@=u=@Di1uCi1Hxn{@=u=@Di1uCi1H>z}@=u=@Di1uCi1_ @=u=@Di1uCi1ȽU@=u=@Di1uCi1Hm@=u=@Di1uCi1Hz'髅@=u=@Di1uCi1H2@=u=@Di1uCi16|ĉ@=u=@Di1uCi1ȔVЋ@>v>Dj2vCj2Hݍ@>v>Dj2vCj2HQY@>v>Dj2vCj2ȯ@>v>Dj2vCj2 @@>v>Dj2vCj2k6@>v>Dj2vCj2Hʴ@>v>Dj2vCj2H(o&@>v>Dj2vCj2Ȇ)3@>v>Dj2vCj2]?@>v>Dj2vCj2BK@?w?Dk3wCk3HXW@?w?Dk3wCk3H;d@?w?Dk3wCk3]̈́p@?w?Dk3wCk3Ȼ|@?w?Dk3wCk3HB@?w?Dk3wCk3Hxa@?w?Dk3wCk3Hֶ@?w?Dk3wCk34q@?w?Dk3wCk3Ȓ+?@?w?Dk3wCk3Hƴ@@x@Dl4xCl4HOҶ@@x@Dl4xCl4ȭZ߸@@x@Dl4xCl4 f@@x@Dl4xCl4Hjϯ@@x@Dl4xCl4Hȉ@@x@Dl4xCl4H&DC@@x@Dl4xCl4Ȅ@@x@Dl4xCl4(@@x@Dl4xCl4HAs 5@@x@Dl4xCl4H-jA@AyA@Dm5yC m5M@AyA@Dm5yC m5[Y@AyA@Dm5yC m5ȹ\Gf@AyA@Dm5yC m5Hr@AyA@Dm5yC m5Hv~@AyA@Dm5yC m5ԋ$@AyA@Dm5yC m52Fn@AyA@Dm5yC m5Ȑ@AyA@Dm5yC m5H@AyA@Dm5yC m5HMuK@BzBDn6zC n6ȫ/@BzBDn6zC n6 @BzBDn6zC n6Hh(@BzBDn6zC n6H^r@BzBDn6zC n6H$@BzBDn6zC n6Ȃ@BzBDn6zC n6O@BzBDn6zC n6H?H@BzBDn6zC n6H*@BzBDn6zC n6H,7@C{CDo7{C o7YwvC@C{CDo7{C o7ȷ1O@C{CDo7{C o7H \@C{CDo7{C o7HtSh@C{CDo7{C o7`t@C{CDo7{C o70@C{CDo7{C o7Ȏ0@C{CDo7{C o7Hz@C{CDo7{C o7HKJĥ@C{CDo7{C o7ȩ@D|DDp8|C p8W@D|DDp8|C p8ey @D|DDp8|C p8H3 @D|DDp8|C p8H"4@D|DDp8|C p8Ȁ~@D|DDp8|C p8b@D|DDp8|C p8H=@D|DDp8|C p8H[@D|DDp8|C p8H @D|DDp8|C p8WL,@E}E@Dq9}C q9ȵ99@E}E@Dq9}C q9HE@E}E@Dq9}C q9Hr{Q!@E}E@Dq9}C q9H5^#@E}E@Dq9}C q9._j%@E}E@Dq9}C q9Ȍv'@E}E@Dq9}C q9Hd)@E}E@Dq9}C q9HI=+@E}E@Dq9}C q9ȧن-@E}E@Dq9}C q9Ч/@F~FDr:~Cr:cN1@F~FDr:~Cr:Hd3@F~FDr:~Cr:H í5@F~FDr:~Cr:~}7@F~FDr:~Cr:7A9@F~FDr:~Cr::;@F~FDr:~Cr:H=@F~FDr:~Cr:Hf @@F~FDr:~Cr:U!hB@F~FDr:~Cr:ȳ۱"D@GGDs;Cs;H.F@GGDs;Cs;HpPE;H@GGDs;Cs;H GJ@GGDs;Cs;,SL@GGDs;Cs;Ȋ"`N@GGDs;Cs;H9llP@GGDs;Cs;HGxR@GGDs;Cs;HT@GGDs;Cs;iIV@GGDs;Cs;a#X@HHDt<Ct<HܩZ@HHDt<Ct<H&\@HHDt<Ct<|Rp^@HHDt<Ct< `@HHDt<Ct<8b@HHDt<Ct<HMd@HHDt<Ct<H;f@HHDt<Ct<Sh@HHDt<Ct<ȱ* k@HHDt<Ct<ktm@II@Du=Cu=Hn%$o@II@Du=Cu=H1q@II@Du=Cu=*Q=s@II@Du=Cu=ȈTIu@II@Du=Cu=HUw@II@Du=Cu=HE.by@II@Du=Cu=Hxn{@II@Du=Cu=>z}@II@Du=Cu=_ @II@Du=Cu=HU@JJDv>Cv>Hm@JJDv>Cv>Hz'髅@JJDv>Cv>2@JJDv>Cv>6|ĉ@JJDv>Cv>HVЋ@JJDv>Cv>Hݍ@JJDv>Cv>HQY@JJDv>Cv>ȯ@JJDv>Cv> @@JJDv>Cv>Hl6@KKDw?Cw?Hʴ@KKDw?Cw?(o&@KKDw?Cw?Ȇ)3@KKDw?Cw?]?@KKDw?Cw?HCK@KKDw?Cw?HXW@KKDw?Cw?;d@KKDw?Cw?]̈́p@KKDw?Cw?Ȼ|@KKDw?Cw?HB@L LDx@Cx@Hxa@L LDx@Cx@ֶ@L LDx@Cx@4q@L LDx@Cx@H+?@L LDx@Cx@Hƴ@L LDx@Cx@HOҶ@L LDx@Cx@ȭZ߸@L LDx@Cx@ f@L LDx@Cx@Hjϯ@L LDx@Cx@Hȉ@M!M@DyACyAH&DC@M!M@DyACyAȄ@M!M@DyACyA(@M!M@DyACyAHAs 5@M!M@DyACyAH-jA@M!M@DyACyAM@M!M@DyACyA[Y@M!M@DyACyAȹ\Gf@M!M@DyACyAHr@M!M@DyACyAHv~@N"NDzBCzBԋ$@N"NDzBCzB2Fn@N"NDzBCzBȐ@N"NDzBCzBH@N"NDzBCzBHMuK@N"NDzBCzBȫ/@N"NDzBCzB @N"NDzBCzBHh(@N"NDzBCzBH^r@N"NDzBCzBH$@O#OD{CC{CȂ@O#OD{CC{CO@O#OD{CC{CH?H@O#OD{CC{CH*@O#OD{CC{CH,7@O#OD{CC{CYwvC@O#OD{CC{Cȷ1O@O#OD{CC{CH \@O#OD{CC{CHtSh@O#OD{CC{C`t@P$PD|DC|D0@P$PD|DC|DȎ0@P$PD|DC|DHz@P$PD|DC|DHKJĥ@P$PD|DC|Dȩ@P$PD|DC|DW@P$PD|DC|Dey @P$PD|DC|DH3 @P$PD|DC|DH"4@P$PD|DC|DȀ~@Q%Q@D}EC}Eb@Q%Q@D}EC}EH=@Q%Q@D}EC}EH[@Q%Q@D}EC}EH @Q%Q@D}EC}EWL,@Q%Q@D}EC}Eȵ99@Q%Q@D}EC}EHE@Q%Q@D}EC}EHr{Q!@Q%Q@D}EC}EH5^#@Q%Q@D}EC}E._j%@R&RD~FC~FȌv'@R&RD~FC~FHd)@R&RD~FC~FHI=+@R&RD~FC~Fȧن-@R&RD~FC~FЧ/@R&RD~FC~FcN1@R&RD~FC~FHd3@R&RD~FC~FH í5@R&RD~FC~F~}7@R&RD~FC~F7A9@S'SDGCG:;@S'SDGCGH=@S'SDGCGHf @@S'SDGCGU!hB@S'SDGCGȳ۱"D@S'SDGCGH.F@S'SDGCGHpPE;H@S'SDGCGH GJ@S'SDGCG,SL@S'SDGCGȊ"`N@T(TDHCHH9llP@T(TDHCHHGxR@T(TDHCHȥT@T(TDHCHiIV@T(TDHCHHb#X@T(TDHCHHܩZ@T(TDHCHH&\@T(TDHCH|Rp^@T(TDHCH `@T(TDHCHH9b@U)U@DICIHMd@U)U@DICI;f@U)U@DICISh@U)U@DICIȱ* k@U)U@DICIHktm@U)U@DICIHn%$o@U)U@DICI1q@U)U@DICI*Q=s@U)U@DICIȈTIu@U)U@DICIHUw@V*VDJCJHE.by@V*VDJCJȣxn{@V*VDJCJ>z}@V*VDJCJH` @V*VDJCJHU@V*VDJCJHm@V*VDJCJz'髅@V*VDJCJ2@V*VDJCJH7|ĉ@V*VDJCJHVЋ@W+WDKCKHݍ@W+WDKCKQY@W+WDKCKȯ@W+WDKCKH@@W+WDKCKHl6@W+WDKCKʴ@W+WDKCK(o&@W+WDKCKȆ)3@W+WDKCKH]?@W+WDKCKHCK@X,XDLC LȡXW@X,XDLC L;d@X,XDLC L]̈́p@X,XDLC LH|@X,XDLC LHB@X,XDLC Lxa@X,XDLC Lֶ@X,XDLC LH5q@X,XDLC LH+?@X,XDLC LHƴ@Y-Y@DMC!MOҶ@Y-Y@DMC!MȭZ߸@Y-Y@DMC!MH f@Y-Y@DMC!MHjϯ@Y-Y@DMC!MHȉ@Y-Y@DMC!M&DC@Y-Y@DMC!MȄ@Y-Y@DMC!MH(@Y-Y@DMC!MHAs 5@Y-Y@DMC!Mȟ-jA@Z.ZDNC"NM@Z.ZDNC"N[Y@Z.ZDNC"NH\Gf@Z.ZDNC"NHr@Z.ZDNC"Nv~@Z.ZDNC"Nԋ$@Z.ZDNC"N2Fn@Z.ZDNC"NH@Z.ZDNC"NH@Z.ZDNC"NMuK@[/[DOC#Oȫ/@[/[DOC#OH @[/[DOC#OHh(@[/[DOC#OH^r@[/[DOC#O$@[/[DOC#OȂ@[/[DOC#OHO@[/[DOC#OH?H@[/[DOC#OH*@[/[DOC#O,7@\0\ DPC$PYwvC@\0\ DPC$PH1O@\0\ DPC$PH \@\0\ DPC$PtSh@\0\ DPC$P`t@\0\ DPC$P0@\0\ DPC$PH0@\0\ DPC$PHz@\0\ DPC$PKJĥ@\0\ DPC$Pȩ@]1]@ DQC%QW@]1]@ DQC%QHfy @]1]@ DQC%QH3 @]1]@ DQC%Q"4@]1]@ DQC%QȀ~@]1]@ DQC%QHb@]1]@ DQC%QH=@]1]@ DQC%QH[@]1]@ DQC%Q @]1]@ DQC%QWL,@^2^ DRC&RH99@^2^ DRC&RHE@^2^ DRC&Rr{Q!@^2^ DRC&R5^#@^2^ DRC&RH/_j%@^2^ DRC&RHv'@^2^ DRC&RHd)@^2^ DRC&RI=+@^2^ DRC&Rȧن-@^2^ DRC&RHЧ/@_3_ DSC'SHdN1@_3_ DSC'Sd3@_3_ DSC'S í5@_3_ DSC'S~}7@_3_ DSC'SH7A9@_3_ DSC'SH;;@_3_ DSC'Sș=@_3_ DSC'Sf @@_3_ DSC'SU!hB@_3_ DSC'SH۱"D@`4` DTC(TH.F@`4` DTC(TpPE;H@`4` DTC(T GJ@`4` DTC(TH-SL@`4` DTC(TH"`N@`4` DTC(TH9llP@`4` DTC(TGxR@`4` DTC(TȥT@`4` DTC(THiIV@`4` DTC(THb#X@a5a@ DUC)UHܩZ@a5a@ DUC)U&\@a5a@ DUC)U|Rp^@a5a@ DUC)UH `@a5a@ DUC)UH9b@a5a@ DUC)UȗMd@a5a@ DUC)U;f@a5a@ DUC)USh@a5a@ DUC)UH* k@a5a@ DUC)UHktm@b6b DVC*Vn%$o@b6b DVC*V1q@b6b DVC*V*Q=s@b6b DVC*VHTIu@b6b DVC*VHUw@b6b DVC*VE.by@b6b DVC*Vȣxn{@b6b DVC*VH>z}@b6b DVC*VH` @b6b DVC*VHU@c7c DWC+Wm@c7c DWC+Wz'髅@c7c DWC+WH2@c7c DWC+WH7|ĉ@c7c DWC+WHVЋ@c7c DWC+Wݍ@c7c DWC+WQY@c7c DWC+WH@c7c DWC+WH@@c7c DWC+Wl6@d8d DXC,Xʴ@d8d DXC,X(o&@d8d DXC,XH)3@d8d DXC,XH]?@d8d DXC,XCK@d8d DXC,XȡXW@d8d DXC,X;d@d8d DXC,XH^̈́p@d8d DXC,XH|@d8d DXC,XB@e9e@ DYC-Yxa@e9e@ DYC-YH׶@e9e@ DYC-YH5q@e9e@ DYC-YH+?@e9e@ DYC-Yƴ@e9e@ DYC-YOҶ@e9e@ DYC-YHZ߸@e9e@ DYC-YH f@e9e@ DYC-YHjϯ@e9e@ DYC-Yȉ@f:f DZC.Z&DC@f:f DZC.ZH@f:f DZC.ZH(@f:f DZC.ZAs 5@f:f DZC.Zȟ-jA@f:f DZC.ZM@f:f DZC.ZH\Y@f:f DZC.ZH\Gf@f:f DZC.Zr@f:f DZC.Zv~@g;g D[C/[ԋ$@g;g D[C/[H3Fn@g;g D[C/[H@g;g D[C/[@g;g D[C/[MuK@g;g D[C/[H/@g;g D[C/[H @g;g D[C/[Hh(@g;g D[C/[^r@g;g D[C/[$@h<h D\C0\H@h<h D\C0\HO@h<h D\C0\?H@h<h D\C0\ȝ*@h<h D\C0\H,7@h<h D\C0\HZwvC@h<h D\C0\H1O@h<h D\C0\ \@h<h D\C0\tSh@h<h D\C0\H`t@i=i@ D]C1]H1@i=i@ D]C1]ȏ0@i=i@ D]C1]z@i=i@ D]C1]KJĥ@i=i@ D]C1]H@i=i@ D]C1]HW@i=i@ D]C1]fy @i=i@ D]C1]3 @i=i@ D]C1]"4@i=i@ D]C1]H~@j>j D^C2^Hb@j>j D^C2^=@j>j D^C2^ț[@j>j D^C2^H @j>j D^C2^HXL,@j>j D^C2^H99@j>j D^C2^E@j>j D^C2^r{Q!@j>j D^C2^H5^#@j>j D^C2^H/_j%@k?k D_C3_Hv'@k?k D_C3_d)@k?k D_C3_I=+@k?k D_C3_Hن-@k?k D_C3_HЧ/@k?k D_C3_dN1@k?k D_C3_d3@k?k D_C3_ í5@k?k D_C3_H}7@k?k D_C3_H7A9@l@l D`C4`;;@l@l D`C4`ș=@l@l D`C4`f @@l@l D`C4`HV!hB@l@l D`C4`H۱"D@l@l D`C4`.F@l@l D`C4`pPE;H@l@l D`C4`H GJ@l@l D`C4`H-SL@l@l D`C4`H"`N@ mA m@ Da C5a9llP@ mA m@ Da C5aGxR@ mA m@ Da C5aHT@ mA m@ Da C5aHiIV@ mA m@ Da C5aHb#X@ mA m@ Da C5aܩZ@ mA m@ Da C5a&\@ mA m@ Da C5aH}Rp^@ mA m@ Da C5aH `@ mA m@ Da C5a9b@ nB n Db C6bȗMd@ nB n Db C6b;f@ nB n Db C6bHTh@ nB n Db C6bH* k@ nB n Db C6bktm@ nB n Db C6bn%$o@ nB n Db C6b1q@ nB n Db C6bH+Q=s@ nB n Db C6bHTIu@ nB n Db C6bUw@ oC o Dc C7cE.by@ oC o Dc C7cHxn{@ oC o Dc C7cH>z}@ oC o Dc C7cH` @ oC o Dc C7cȾU@ oC o Dc C7cm@ oC o Dc C7cH{'髅@ oC o Dc C7cH2@ oC o Dc C7cH7|ĉ@ oC o Dc C7cȕVЋ@ pD pDd C8dݍ@ pD pDd C8dHRY@ pD pDd C8dH@ pD pDd C8d@@ pD pDd C8dl6@ pD pDd C8dʴ@ pD pDd C8dH)o&@ pD pDd C8dH)3@ pD pDd C8d]?@ pD pDd C8dCK@ qE q@De C9eȡXW@ qE q@De C9eH;d@ qE q@De C9eH^̈́p@ qE q@De C9eȼ|@ qE q@De C9eB@ qE q@De C9eHya@ qE q@De C9eH׶@ qE q@De C9eH5q@ qE q@De C9eȓ+?@ qE q@De C9eƴ@rFrDfC:fHPҶ@rFrDfC:fHZ߸@rFrDfC:f f@rFrDfC:fjϯ@rFrDfC:fHɉ@rFrDfC:fH'DC@rFrDfC:fH@rFrDfC:f(@rFrDfC:fAs 5@rFrDfC:fH-jA@sGsDgC;gHM@sGsDgC;g\Y@sGsDgC;gȺ\Gf@sGsDgC;gr@sGsDgC;gHw~@sGsDgC;gHՋ$@sGsDgC;g3Fn@sGsDgC;gȑ@sGsDgC;g@sGsDgC;gHNuK@tHtDhC<hH/@tHtDhC<h @tHtDhC<hh(@tHtDhC<hH^r@tHtDhC<hH%@tHtDhC<hH@tHtDhC<hO@tHtDhC<h?H@tHtDhC<hH*@tHtDhC<hH,7@uIu@DiC=iHZwvC@uIu@DiC=iȸ1O@uIu@DiC=i \@uIu@DiC=iHuSh@uIu@DiC=iH`t@uIu@DiC=i1@uIu@DiC=iȏ0@uIu@DiC=iz@uIu@DiC=iHLJĥ@uIu@DiC=iH@vJvDjC>jW@vJvDjC>jfy @vJvDjC>j3 @vJvDjC>jH#4@vJvDjC>jH~@vJvDjC>jb@vJvDjC>j=@vJvDjC>jH[@vJvDjC>jH @vJvDjC>jHXL,@wKwDkC?kȶ99@wKwDkC?kE@wKwDkC?kHs{Q!@wKwDkC?kH5^#@wKwDkC?kH/_j%@wKwDkC?kȍv'@wKwDkC?kd)@wKwDkC?kHJ=+@wKwDkC?kHن-@wKwDkC?kЧ/@xLxDlC@ldN1@xLxDlC@ld3@xLxDlC@lH!í5@xLxDlC@lH}7@xLxDlC@l7A9@xLxDlC@l;;@xLxDlC@lș=@xLxDlC@lHf @@xLxDlC@lHV!hB@xLxDlC@lȴ۱"D@yMy @DmCA m.F@yMy @DmCA mHqPE;H@yMy @DmCA mH GJ@yMy @DmCA mH-SL@yMy @DmCA mȋ"`N@yMy @DmCA m9llP@yMy @DmCA mHHxR@yMy @DmCA mHT@yMy @DmCA mHiIV@yMy @DmCA mb#X@zNz DnCB nܩZ@zNz DnCB nH&\@zNz DnCB nH}Rp^@zNz DnCB n `@zNz DnCB n9b@zNz DnCB nȗMd@zNz DnCB nH;f@zNz DnCB nHTh@zNz DnCB nȲ* k@zNz DnCB nktm@{O{ DoCC on%$o@{O{ DoCC oH1q@{O{ DoCC oH+Q=s@{O{ DoCC oȉTIu@{O{ DoCC oUw@{O{ DoCC oHF.by@{O{ DoCC oHxn{@{O{ DoCC oH>z}@{O{ DoCC o` @{O{ DoCC oȾU@|P| DpCD pHm@|P| DpCD pH{'髅@|P| DpCD p2@|P| DpCD p7|ĉ@|P| DpCD pHVЋ@|P| DpCD pHݍ@|P| DpCD pHRY@|P| DpCD pȰ@|P| DpCD p@@|P| DpCD pHm6@}Q} @DqCE qH˴@}Q} @DqCE q)o&@}Q} @DqCE qȇ)3@}Q} @DqCE q]?@}Q} @DqCE qHDK@}Q} @DqCE qHXW@}Q} @DqCE q;d@}Q} @DqCE q^̈́p@}Q} @DqCE qȼ|@}Q} @DqCE qHB@~R~DrCFrHya@~R~DrCFr׶@~R~DrCFr5q@~R~DrCFrH+?@~R~DrCFrHƴ@~R~DrCFrHPҶ@~R~DrCFrȮZ߸@~R~DrCFr f@~R~DrCFrHkϯ@~R~DrCFrHɉ@SDsCGsH'DC@SDsCGsȅ@SDsCGs(@SDsCGsHBs 5@SDsCGsH-jA@SDsCGsM@SDsCGs\Y@SDsCGsȺ\Gf@SDsCGsHr@SDsCGsHw~@TDtCHtՋ$@TDtCHt3Fn@TDtCHtȑ@TDtCHtH@TDtCHtHNuK@TDtCHtȬ/@TDtCHt @TDtCHtHi(@TDtCHtH^r@TDtCHtH%@U@DuCIuȃ@U@DuCIuO@U@DuCIuH@H@U@DuCIuH*@U@DuCIuH,7@U@DuCIuZwvC@U@DuCIuȸ1O@U@DuCIuH \@U@DuCIuHuSh@U@DuCIu`t@VDvCJv1@VDvCJvȏ0@VDvCJvHz@VDvCJvHLJĥ@VDvCJvȪ@VDvCJvW@VDvCJvfy @VDvCJvH3 @VDvCJvH#4@VDvCJvȁ~@WDwCKwb@WDwCKwH>@WDwCKwH[@WDwCKwH @WDwCKwXL,@WDwCKwȶ99@WDwCKwHE@WDwCKwHs{Q!@WDwCKwH5^#@WDwCKw/_j%@ X Dx CLxȍv'@ X Dx CLxHd)@ X Dx CLxHJ=+@ X Dx CLxȨن-@ X Dx CLxЧ/@ X Dx CLxdN1@ X Dx CLxHd3@ X Dx CLxH!í5@ X Dx CLx}7@ X Dx CLx7A9@!Y!@Dy!CMy;;@!Y!@Dy!CMyH=@!Y!@Dy!CMyHf @@!Y!@Dy!CMyV!hB@!Y!@Dy!CMyȴ۱"D@!Y!@Dy!CMyH.F@!Y!@Dy!CMyHqPE;H@!Y!@Dy!CMyH GJ@!Y!@Dy!CMy-SL@!Y!@Dy!CMyȋ"`N@"Z"Dz"CNzH9llP@"Z"Dz"CNzHHxR@"Z"Dz"CNzȦT@"Z"Dz"CNziIV@"Z"Dz"CNzHc#X@"Z"Dz"CNzHܩZ@"Z"Dz"CNzH&\@"Z"Dz"CNz}Rp^@"Z"Dz"CNz `@"Z"Dz"CNzH:b@#[#D{#CO{HMd@#[#D{#CO{;f@#[#D{#CO{Th@#[#D{#CO{Ȳ* k@#[#D{#CO{Hktm@#[#D{#CO{Ho%$o@#[#D{#CO{1q@#[#D{#CO{+Q=s@#[#D{#CO{ȉTIu@#[#D{#CO{HUw@$\$D|$CP|HF.by@$\$D|$CP|Ȥxn{@$\$D|$CP|>z}@$\$D|$CP|Ha @$\$D|$CP|HU@$\$D|$CP|Hm@$\$D|$CP|{'髅@$\$D|$CP|2@$\$D|$CP|H8|ĉ@$\$D|$CP|HVЋ@%]%@D}%CQ}Hݍ@%]%@D}%CQ}RY@%]%@D}%CQ}Ȱ@%]%@D}%CQ}H@@%]%@D}%CQ}Hm6@%]%@D}%CQ}˴@%]%@D}%CQ})o&@%]%@D}%CQ}ȇ)3@%]%@D}%CQ}H]?@%]%@D}%CQ}HDK@&^&D~&CR~ȢXW@&^&D~&CR~;d@&^&D~&CR~^̈́p@&^&D~&CR~H|@&^&D~&CR~HB@&^&D~&CR~ya@&^&D~&CR~׶@&^&D~&CR~H6q@&^&D~&CR~H+?@&^&D~&CR~Hƴ@'_'D'CSPҶ@'_'D'CSȮZ߸@'_'D'CSH f@'_'D'CSHkϯ@'_'D'CSHɉ@'_'D'CS'DC@'_'D'CSȅ@'_'D'CSH(@'_'D'CSHBs 5@'_'D'CSȠ-jA@(`(D(CTM@(`(D(CT\Y@(`(D(CTH\Gf@(`(D(CTHr@(`(D(CTw~@(`(D(CTՋ$@(`(D(CT3Fn@(`(D(CTH@(`(D(CTH@(`(D(CTNuK@)a)@D)CUȬ/@)a)@D)CUH @)a)@D)CUHi(@)a)@D)CUH^r@)a)@D)CU%@)a)@D)CUȃ@)a)@D)CUHO@)a)@D)CUH@H@)a)@D)CUH*@)a)@D)CU,7@*b*D*CVZwvC@*b*D*CVH1O@*b*D*CVH \@*b*D*CVuSh@*b*D*CV`t@*b*D*CV1@*b*D*CVH0@*b*D*CVHz@*b*D*CVLJĥ@*b*D*CVȪ@+c+D+CWW@+c+D+CWHgy @+c+D+CWH3 @+c+D+CW#4@+c+D+CWȁ~@+c+D+CWHb@+c+D+CWH>@+c+D+CWH[@+c+D+CW @+c+D+CWXL,@,d, D,CX H99@,d, D,CX HE@,d, D,CX s{Q!@,d, D,CX 5^#@,d, D,CX H0_j%@,d, D,CX Hv'@,d, D,CX Hd)@,d, D,CX J=+@,d, D,CX Ȩن-@,d, D,CX HЧ/@-e-!@D-CY!HeN1@-e-!@D-CY!d3@-e-!@D-CY!!í5@-e-!@D-CY!}7@-e-!@D-CY!H7A9@-e-!@D-CY!H<;@-e-!@D-CY!Ț=@-e-!@D-CY!f @@-e-!@D-CY!V!hB@-e-!@D-CY!H۱"D@.f."D.CZ"H.F@.f."D.CZ"qPE;H@.f."D.CZ" GJ@.f."D.CZ"H.SL@.f."D.CZ"H"`N@.f."D.CZ"H9llP@.f."D.CZ"HxR@.f."D.CZ"ȦT@.f."D.CZ"HiIV@.f."D.CZ"Hc#X@/g/#D/C[#HܩZ@/g/#D/C[#&\@/g/#D/C[#}Rp^@/g/#D/C[#H `@/g/#D/C[#H:b@/g/#D/C[#ȘMd@/g/#D/C[#;f@/g/#D/C[#Th@/g/#D/C[#H* k@/g/#D/C[#Hktm@0h0$D0C\$o%$o@0h0$D0C\$1q@0h0$D0C\$+Q=s@0h0$D0C\$HTIu@0h0$D0C\$HUw@0h0$D0C\$F.by@0h0$D0C\$Ȥxn{@0h0$D0C\$H>z}@0h0$D0C\$Ha @0h0$D0C\$HU@1i1%@D1C]%m@1i1%@D1C]%{'髅@1i1%@D1C]%H2@1i1%@D1C]%H8|ĉ@1i1%@D1C]%HVЋ@1i1%@D1C]%ݍ@1i1%@D1C]%RY@1i1%@D1C]%H@1i1%@D1C]%H@@1i1%@D1C]%m6@2j2&DŠ2C^&˴@2j2&DŠ2C^&)o&@2j2&DŠ2C^&H)3@2j2&DŠ2C^&H]?@2j2&DŠ2C^&DK@2j2&DŠ2C^&ȢXW@2j2&DŠ2C^&;d@2j2&DŠ2C^&H_̈́p@2j2&DŠ2C^&H|@2j2&DŠ2C^&B@3k3'DË3C_'ya@3k3'DË3C_'Hض@3k3'DË3C_'H6q@3k3'DË3C_'H+?@3k3'DË3C_'ƴ@3k3'DË3C_'PҶ@3k3'DË3C_'HZ߸@3k3'DË3C_'H f@3k3'DË3C_'Hkϯ@3k3'DË3C_'ɉ@4l4(DČ4C`('DC@4l4(DČ4C`(H@4l4(DČ4C`(H(@4l4(DČ4C`(Bs 5@4l4(DČ4C`(Ƞ-jA@4l4(DČ4C`(M@4l4(DČ4C`(H]Y@4l4(DČ4C`(H\Gf@4l4(DČ4C`(r@4l4(DČ4C`(w~@5m5)@Dō 5Ca)Ջ$@5m5)@Dō 5Ca)H4Fn@5m5)@Dō 5Ca)H@5m5)@Dō 5Ca)@5m5)@Dō 5Ca)NuK@5m5)@Dō 5Ca)H/@5m5)@Dō 5Ca)H @5m5)@Dō 5Ca)Hi(@5m5)@Dō 5Ca)^r@5m5)@Dō 5Ca)%@6n6*DƎ 6Cb*H@6n6*DƎ 6Cb*HO@6n6*DƎ 6Cb*@H@6n6*DƎ 6Cb*Ȟ*@6n6*DƎ 6Cb*H,7@6n6*DƎ 6Cb*H[wvC@6n6*DƎ 6Cb*H1O@6n6*DƎ 6Cb* \@6n6*DƎ 6Cb*uSh@6n6*DƎ 6Cb*H`t@7o7+DǏ 7Cc+H2@7o7+DǏ 7Cc+Ȑ0 @7o7+DǏ 7Cc+z @7o7+DǏ 7Cc+LJĥ @7o7+DǏ 7Cc+H @7o7+DǏ 7Cc+H W @7o7+DǏ 7Cc+gy @7o7+DǏ 7Cc+3 @7o7+DǏ 7Cc+#4 @7o7+DǏ 7Cc+H~ @8p8,DȐ 8Cd,Hb @8p8,DȐ 8Cd,> @8p8,DȐ 8Cd,Ȝ[ @8p8,DȐ 8Cd,H  @8p8,DȐ 8Cd,HYL, @8p8,DȐ 8Cd,H99 @8p8,DȐ 8Cd,E @8p8,DȐ 8Cd,s{Q! @8p8,DȐ 8Cd,H5^# @8p8,DȐ 8Cd,H0_j% @9q9-@Dɑ 9Ce-Hv' @9q9-@Dɑ 9Ce-d) @9q9-@Dɑ 9Ce-J=+ @9q9-@Dɑ 9Ce-Hن- @9q9-@Dɑ 9Ce-HЧ/ @9q9-@Dɑ 9Ce-eN1 @9q9-@Dɑ 9Ce-d3 @9q9-@Dɑ 9Ce-!í5 @9q9-@Dɑ 9Ce-H}7 @9q9-@Dɑ 9Ce-H7A9 @:r:.Dʒ:Cf.<; @:r:.Dʒ:Cf.Ț= @:r:.Dʒ:Cf.f @ @:r:.Dʒ:Cf.HW!hB @:r:.Dʒ:Cf.H۱"D @:r:.Dʒ:Cf..F @:r:.Dʒ:Cf.qPE;H @:r:.Dʒ:Cf.H GJ @:r:.Dʒ:Cf.H.SL @:r:.Dʒ:Cf.H"`N @;s;/D˓;Cg/9llP @;s;/D˓;Cg/HxR @;s;/D˓;Cg/HT @;s;/D˓;Cg/HiIV @;s;/D˓;Cg/Hc#X @;s;/D˓;Cg/ܩZ @;s;/D˓;Cg/&\ @;s;/D˓;Cg/H~Rp^ @;s;/D˓;Cg/H ` @;s;/D˓;Cg/:b @z} @=u=1@D͕=Ci1Ha  @=u=1@D͕=Ci1ȿU @=u=1@D͕=Ci1m @=u=1@D͕=Ci1H|'髅 @=u=1@D͕=Ci1H2 @=u=1@D͕=Ci1H8|ĉ @=u=1@D͕=Ci1ȖVЋ @>v>2DΖ>Cj2ݍ @>v>2DΖ>Cj2HSY @>v>2DΖ>Cj2H @>v>2DΖ>Cj2@ @>v>2DΖ>Cj2m6 @>v>2DΖ>Cj2˴ @>v>2DΖ>Cj2H*o& @>v>2DΖ>Cj2H)3 @>v>2DΖ>Cj2]? @>v>2DΖ>Cj2DK @?w?3Dϗ?Ck3ȢXW @?w?3Dϗ?Ck3H;d @?w?3Dϗ?Ck3H_̈́p @?w?3Dϗ?Ck3Ƚ| @?w?3Dϗ?Ck3B @?w?3Dϗ?Ck3Hza @?w?3Dϗ?Ck3Hض @?w?3Dϗ?Ck3H6q @?w?3Dϗ?Ck3Ȕ+? @?w?3Dϗ?Ck3ƴ @@x@4DИ@Cl4HQҶ @@x@4DИ@Cl4HZ߸ @@x@4DИ@Cl4 f @@x@4DИ@Cl4kϯ @@x@4DИ@Cl4Hʉ @@x@4DИ@Cl4H(DC @@x@4DИ@Cl4H @@x@4DИ@Cl4( @@x@4DИ@Cl4Bs 5 @@x@4DИ@Cl4H-jA @ AyA 5@DљAC m5HM @ AyA 5@DљAC m5]Y @ AyA 5@DљAC m5Ȼ\Gf @ AyA 5@DљAC m5r @ AyA 5@DљAC m5Hx~ @ AyA 5@DљAC m5H֋$ @ AyA 5@DљAC m54Fn @ AyA 5@DљAC m5Ȓ @ AyA 5@DљAC m5 @ AyA 5@DљAC m5HOuK @ BzB 6DҚBC n6H/ @ BzB 6DҚBC n6 @ BzB 6DҚBC n6i( @ BzB 6DҚBC n6H^r @ BzB 6DҚBC n6H& @ BzB 6DҚBC n6H @ BzB 6DҚBC n6O @ BzB 6DҚBC n6@H @ BzB 6DҚBC n6H* @ BzB 6DҚBC n6H,7 @ C{C 7DӛCC o7H[wvC @ C{C 7DӛCC o7ȹ1O @ C{C 7DӛCC o7 \ @ C{C 7DӛCC o7HvSh @ C{C 7DӛCC o7H`t @ C{C 7DӛCC o72 @ C{C 7DӛCC o7Ȑ0 @ C{C 7DӛCC o7z @ C{C 7DӛCC o7HMJĥ @ C{C 7DӛCC o7H @ D|D 8DԜDC p8 W @ D|D 8DԜDC p8gy @ D|D 8DԜDC p83 @ D|D 8DԜDC p8H$4 @ D|D 8DԜDC p8H~ @ D|D 8DԜDC p8b @ D|D 8DԜDC p8> @ D|D 8DԜDC p8H[ @ D|D 8DԜDC p8H  @ D|D 8DԜDC p8HYL, @ E}E 9@D՝EC q9ȷ99 @ E}E 9@D՝EC q9E @ E}E 9@D՝EC q9Ht{Q! @ E}E 9@D՝EC q9H5^# @ E}E 9@D՝EC q9H0_j% @ E}E 9@D՝EC q9Ȏv' @ E}E 9@D՝EC q9d) @ E}E 9@D՝EC q9HK=+ @ E}E 9@D՝EC q9Hن- @ E}E 9@D՝EC q9Ч/ @F~F:D֞FCr:eN1 @F~F:D֞FCr:d3 @F~F:D֞FCr:H"í5 @F~F:D֞FCr:H}7 @F~F:D֞FCr:7A9 @F~F:D֞FCr:<; @F~F:D֞FCr:Ț= @F~F:D֞FCr:Hf @ @F~F:D֞FCr:HW!hB @F~F:D֞FCr:ȵ۱"D @GG;DןGCs;.F @GG;DןGCs;HrPE;H @GG;DןGCs;H GJ @GG;DןGCs;H.SL @GG;DןGCs;Ȍ"`N @GG;DןGCs;9llP @GG;DןGCs;HIxR @GG;DןGCs;HT @GG;DןGCs;HiIV @GG;DןGCs;c#X @HH<DؠHCt<ܩZ @HH<DؠHCt<H &\ @HH<DؠHCt<H~Rp^ @HH<DؠHCt< ` @HH<DؠHCt<:b @HH<DؠHCt<ȘMd @HH<DؠHCt<H;f @HH<DؠHCt<HUh @HH<DؠHCt<ȳ* k @HH<DؠHCt<ktm @II=@D١ICu=o%$o @II=@D١ICu=H1q @II=@D١ICu=H,Q=s @II=@D١ICu=ȊTIu @II=@D١ICu=Uw @II=@D١ICu=HG.by @II=@D١ICu=Hxn{ @II=@D١ICu=H>z} @II=@D١ICu=a  @II=@D١ICu=ȿU @JJ>DڢJCv>Hm @JJ>DڢJCv>H|'髅 @JJ>DڢJCv>2 @JJ>DڢJCv>8|ĉ @JJ>DڢJCv>HVЋ @JJ>DڢJCv>Hݍ @JJ>DڢJCv>HSY @JJ>DڢJCv>ȱ @JJ>DڢJCv>@ @JJ>DڢJCv>Hn6 @KK?DۣKCw?H̴ @KK?DۣKCw?*o& @KK?DۣKCw?Ȉ)3 @KK?DۣKCw?]? @KK?DۣKCw?HEK @KK?DۣKCw?HXW @KK?DۣKCw?;d @KK?DۣKCw?_̈́p @KK?DۣKCw?Ƚ| @KK?DۣKCw?HB @LL@Dܤ LCx@Hza @LL@Dܤ LCx@ض @LL@Dܤ LCx@6q @LL@Dܤ LCx@H+? @LL@Dܤ LCx@Hƴ @LL@Dܤ LCx@HQҶ @LL@Dܤ LCx@ȯZ߸ @LL@Dܤ LCx@ f @LL@Dܤ LCx@Hlϯ @LL@Dܤ LCx@Hʉ @MMA@Dݥ!MCyAH(DC @MMA@Dݥ!MCyAȆ @MMA@Dݥ!MCyA( @MMA@Dݥ!MCyAHCs 5 @MMA@Dݥ!MCyAH-jA @MMA@Dݥ!MCyAM @MMA@Dݥ!MCyA]Y @MMA@Dݥ!MCyAȻ\Gf @MMA@Dݥ!MCyAHr @MMA@Dݥ!MCyAHx~ @NNBDަ"NCzB֋$ @NNBDަ"NCzB4Fn @NNBDަ"NCzBȒ @NNBDަ"NCzBH @NNBDަ"NCzBHOuK @NNBDަ"NCzBȭ/ @NNBDަ"NCzB @NNBDަ"NCzBHj( @NNBDަ"NCzBH^r @NNBDަ"NCzBH& @OOCDߧ#OC{CȄ @OOCDߧ#OC{CO @OOCDߧ#OC{CHAH @OOCDߧ#OC{CH* @OOCDߧ#OC{CH,7 @OOCDߧ#OC{C[wvC @OOCDߧ#OC{Cȹ1O @OOCDߧ#OC{CH \ @OOCDߧ#OC{CHvSh @OOCDߧ#OC{C`t @PPDD$PC|D2 @PPDD$PC|DȐ0 @PPDD$PC|DHz @PPDD$PC|DHMJĥ @PPDD$PC|Dȫ @PPDD$PC|D W @PPDD$PC|Dgy @PPDD$PC|DH3 @PPDD$PC|DH$4 @PPDD$PC|DȂ~ @QQE@D%QC}Eb @QQE@D%QC}EH? @QQE@D%QC}EH[ @QQE@D%QC}EH  @QQE@D%QC}EYL, @QQE@D%QC}Eȷ99 @QQE@D%QC}EHE @QQE@D%QC}EHt{Q! @QQE@D%QC}EH5^# @QQE@D%QC}E0_j% @RRFD&RC~FȎv' @RRFD&RC~FHd) @RRFD&RC~FHK=+ @RRFD&RC~Fȩن- @RRFD&RC~FЧ/ @RRFD&RC~FeN1 @RRFD&RC~FHd3 @RRFD&RC~FH"í5 @RRFD&RC~FȀ}7 @RRFD&RC~F7A9 @SSGD'SCG<; @SSGD'SCGH= @SSGD'SCGHf @ @SSGD'SCGW!hB @SSGD'SCGȵ۱"D @SSGD'SCGH.F @SSGD'SCGHrPE;H @SSGD'SCGH GJ @SSGD'SCG.SL @SSGD'SCGȌ"`N @TTH D(TCHH9llP @TTH D(TCHHIxR @TTH D(TCHȧT @TTH D(TCHiIV @TTH D(TCHHd#X @TTH D(TCHHܩZ @TTH D(TCHH &\ @TTH D(TCH~Rp^ @TTH D(TCH ` @TTH D(TCHH;b @UUI@ D)UCIHMd @UUI@ D)UCI;f @UUI@ D)UCIUh @UUI@ D)UCIȳ* k @UUI@ D)UCIHktm @UUI@ D)UCIHp%$o @UUI@ D)UCI1q @UUI@ D)UCI,Q=s @UUI@ D)UCIȊTIu @UUI@ D)UCIHUw @VVJ D*VCJHG.by @VVJ D*VCJȥxn{ @VVJ D*VCJ>z} @VVJ D*VCJHb  @VVJ D*VCJHU @VVJ D*VCJHm @VVJ D*VCJ|'髅 @VVJ D*VCJ2 @VVJ D*VCJH9|ĉ @VVJ D*VCJHVЋ @WWK D+WCKHݍ @WWK D+WCKSY @WWK D+WCKȱ @WWK D+WCKH@ @WWK D+WCKHn6 @WWK D+WCK̴ @WWK D+WCK*o& @WWK D+WCKȈ)3 @WWK D+WCKH]? @WWK D+WCKHEK @ XX L!D, XC LȣXW @ XX L!D, XC L;d @ XX L!D, XC L_̈́p @ XX L!D, XC LH| @ XX L!D, XC LHB @ XX L!D, XC Lza @ XX L!D, XC Lض @ XX L!D, XC LH7q @ XX L!D, XC LH+? @ XX L!D, XC LHƴ @!YY!M@!D- YC!MQҶ @!YY!M@!D- YC!MȯZ߸ @!YY!M@!D- YC!MHf @!YY!M@!D- YC!MHlϯ @!YY!M@!D- YC!MHʉ @!YY!M@!D- YC!M(DC @!YY!M@!D- YC!MȆ @!YY!M@!D- YC!MH( @!YY!M@!D- YC!MHCs 5 @!YY!M@!D- YC!Mȡ-jA @"ZZ"N!D. ZC"NM @"ZZ"N!D. ZC"N]Y @"ZZ"N!D. ZC"NH\Gf @"ZZ"N!D. ZC"NHr @"ZZ"N!D. ZC"Nx~ @"ZZ"N!D. ZC"N֋$ @"ZZ"N!D. ZC"N4Fn @"ZZ"N!D. ZC"NH @"ZZ"N!D. ZC"NH @"ZZ"N!D. ZC"NOuK @#[[#O!D/ [C#Oȭ/ @#[[#O!D/ [C#OH @#[[#O!D/ [C#OHj( @#[[#O!D/ [C#OH^r @#[[#O!D/ [C#O& @#[[#O!D/ [C#OȄ @#[[#O!D/ [C#OHO @#[[#O!D/ [C#OHAH @#[[#O!D/ [C#OH* @#[[#O!D/ [C#O,7 @$\\$P"D0 \C$P[wvC @$\\$P"D0 \C$PH1O @$\\$P"D0 \C$PH \ @$\\$P"D0 \C$PvSh @$\\$P"D0 \C$P`t @$\\$P"D0 \C$P2 @$\\$P"D0 \C$PH0 @$\\$P"D0 \C$PHz @$\\$P"D0 \C$PMJĥ @$\\$P"D0 \C$Pȫ @%]]%Q@"D1 ]C%Q W @%]]%Q@"D1 ]C%QHhy @%]]%Q@"D1 ]C%QH3 @%]]%Q@"D1 ]C%Q$4 @%]]%Q@"D1 ]C%QȂ~ @%]]%Q@"D1 ]C%QHb @%]]%Q@"D1 ]C%QH? @%]]%Q@"D1 ]C%QH[ @%]]%Q@"D1 ]C%Q  @%]]%Q@"D1 ]C%QYL, @&^–^&R"D2 ^C&RH99 @&^–^&R"D2 ^C&RHE @&^–^&R"D2 ^C&Rt{Q! @&^–^&R"D2 ^C&R5^# @&^–^&R"D2 ^C&RH1_j% @&^–^&R"D2 ^C&RHv' @&^–^&R"D2 ^C&RHd) @&^–^&R"D2 ^C&RK=+ @&^–^&R"D2 ^C&Rȩن- @&^–^&R"D2 ^C&RHЧ/ @'_×_'S"D3 _C'SHfN1 @'_×_'S"D3 _C'Sd3 @'_×_'S"D3 _C'S"í5 @'_×_'S"D3 _C'SȀ}7 @'_×_'S"D3 _C'SH7A9 @'_×_'S"D3 _C'SH=; @'_×_'S"D3 _C'Sț= @'_×_'S"D3 _C'Sf @ @'_×_'S"D3 _C'SW!hB @'_×_'S"D3 _C'SH۱"D @(`Ę`(T#D4 `C(TH.F @(`Ę`(T#D4 `C(TrPE;H @(`Ę`(T#D4 `C(T GJ @(`Ę`(T#D4 `C(TH/SL @(`Ę`(T#D4 `C(TH"`N @(`Ę`(T#D4 `C(TH9llP @(`Ę`(T#D4 `C(TIxR @(`Ę`(T#D4 `C(TȧT @(`Ę`(T#D4 `C(THiIV @(`Ę`(T#D4 `C(THd#X @)ařa)U@#D5 aC)UHܩZ @)ařa)U@#D5 aC)U &\ @)ařa)U@#D5 aC)U~Rp^ @)ařa)U@#D5 aC)UH ` @)ařa)U@#D5 aC)UH;b @)ařa)U@#D5 aC)UșMd @)ařa)U@#D5 aC)U;f @)ařa)U@#D5 aC)UUh @)ařa)U@#D5 aC)UH* k @)ařa)U@#D5 aC)UHktm @*bƚb*V#D6 bC*Vp%$o @*bƚb*V#D6 bC*V1q @*bƚb*V#D6 bC*V,Q=s @*bƚb*V#D6 bC*VHTIu @*bƚb*V#D6 bC*VHUw @*bƚb*V#D6 bC*VG.by @*bƚb*V#D6 bC*Vȥxn{ @*bƚb*V#D6 bC*VH>z} @*bƚb*V#D6 bC*VHb  @*bƚb*V#D6 bC*VHU @+cǛc+W#D7 cC+Wm @+cǛc+W#D7 cC+W|'髅 @+cǛc+W#D7 cC+WH2 @+cǛc+W#D7 cC+WH9|ĉ @+cǛc+W#D7 cC+WHVЋ @+cǛc+W#D7 cC+Wݍ @+cǛc+W#D7 cC+WSY @+cǛc+W#D7 cC+WH @+cǛc+W#D7 cC+WH@ @+cǛc+W#D7 cC+Wn6 @,dȜd,X$D8 dC,X̴ @,dȜd,X$D8 dC,X*o& @,dȜd,X$D8 dC,XH)3 @,dȜd,X$D8 dC,XH]? @,dȜd,X$D8 dC,XEK @,dȜd,X$D8 dC,XȣXW @,dȜd,X$D8 dC,X;d @,dȜd,X$D8 dC,XH`̈́p @,dȜd,X$D8 dC,XH| @,dȜd,X$D8 dC,XB @-eɝe-Y@$D9 eC-Yza @-eɝe-Y@$D9 eC-YHٶ @-eɝe-Y@$D9 eC-YH7q @-eɝe-Y@$D9 eC-YH+? @-eɝe-Y@$D9 eC-Yƴ @-eɝe-Y@$D9 eC-YQҶ @-eɝe-Y@$D9 eC-YHZ߸ @-eɝe-Y@$D9 eC-YHf @-eɝe-Y@$D9 eC-YHlϯ @-eɝe-Y@$D9 eC-Yʉ @.fʞf.Z$D: fC.Z(DC @.fʞf.Z$D: fC.ZH @.fʞf.Z$D: fC.ZH( @.fʞf.Z$D: fC.ZCs 5 @.fʞf.Z$D: fC.Zȡ-jA @.fʞf.Z$D: fC.ZM @.fʞf.Z$D: fC.ZH^Y @.fʞf.Z$D: fC.ZH\Gf @.fʞf.Z$D: fC.Zr @.fʞf.Z$D: fC.Zx~ @/g˟g/[$D; gC/[֋$ @/g˟g/[$D; gC/[H5Fn @/g˟g/[$D; gC/[H @/g˟g/[$D; gC/[ @/g˟g/[$D; gC/[OuK @/g˟g/[$D; gC/[H/ @/g˟g/[$D; gC/[H @/g˟g/[$D; gC/[Hj( @/g˟g/[$D; gC/[^r @/g˟g/[$D; gC/[& @0h̠h0\%D< hC0\H @0h̠h0\%D< hC0\HO @0h̠h0\%D< hC0\AH @0h̠h0\%D< hC0\ȟ* @0h̠h0\%D< hC0\H,7 @0h̠h0\%D< hC0\H\wvC @0h̠h0\%D< hC0\H1O @0h̠h0\%D< hC0\ \ @0h̠h0\%D< hC0\vSh @0h̠h0\%D< hC0\H`t @1i͡i1]@%D= iC1]H3 @1i͡i1]@%D= iC1]ȑ0 @1i͡i1]@%D= iC1]z @1i͡i1]@%D= iC1]MJĥ @1i͡i1]@%D= iC1]H @1i͡i1]@%D= iC1]H W @1i͡i1]@%D= iC1]hy @1i͡i1]@%D= iC1]3 @1i͡i1]@%D= iC1]$4 @1i͡i1]@%D= iC1]H~ @2j΢j2^%D> jC2^Hb @2j΢j2^%D> jC2^? @2j΢j2^%D> jC2^ȝ[ @2j΢j2^%D> jC2^H  @2j΢j2^%D> jC2^HZL, @2j΢j2^%D> jC2^H99 @2j΢j2^%D> jC2^E @2j΢j2^%D> jC2^t{Q! @2j΢j2^%D> jC2^H5^# @2j΢j2^%D> jC2^H1_j% @3kϣk3_%D? kC3_Hv' @3kϣk3_%D? kC3_d) @3kϣk3_%D? kC3_K=+ @3kϣk3_%D? kC3_Hن- @3kϣk3_%D? kC3_HЧ/ @3kϣk3_%D? kC3_fN1 @3kϣk3_%D? kC3_d3 @3kϣk3_%D? kC3_"í5 @3kϣk3_%D? kC3_H}7 @3kϣk3_%D? kC3_H7A9 @4lФl4`&D@ lC4`=; @4lФl4`&D@ lC4`ț= @4lФl4`&D@ lC4`f @ @4lФl4`&D@ lC4`HX!hB @4lФl4`&D@ lC4`H۱"D @4lФl4`&D@ lC4`.F @4lФl4`&D@ lC4`rPE;H @4lФl4`&D@ lC4`H GJ @4lФl4`&D@ lC4`H/SL @4lФl4`&D@ lC4`H"`N @5mѥ m5a@&DA mC5a9llP @5mѥ m5a@&DA mC5aIxR @5mѥ m5a@&DA mC5aHT @5mѥ m5a@&DA mC5aHiIV @5mѥ m5a@&DA mC5aHd#X @5mѥ m5a@&DA mC5aܩZ @5mѥ m5a@&DA mC5a &\ @5mѥ m5a@&DA mC5aHRp^ @5mѥ m5a@&DA mC5aH ` @5mѥ m5a@&DA mC5a;b @6nҦ n6b&DB nC6bșMd @6nҦ n6b&DB nC6b;f @6nҦ n6b&DB nC6bHVh @6nҦ n6b&DB nC6bH* k @6nҦ n6b&DB nC6bktm @6nҦ n6b&DB nC6bp%$o @6nҦ n6b&DB nC6b1q @6nҦ n6b&DB nC6bH-Q=s @6nҦ n6b&DB nC6bHTIu @6nҦ n6b&DB nC6bUw @7oӧ o7c&DC oC7cG.by @7oӧ o7c&DC oC7cHxn{ @7oӧ o7c&DC oC7cH>z} @7oӧ o7c&DC oC7cHb  @7oӧ o7c&DC oC7cU @7oӧ o7c&DC oC7cm @7oӧ o7c&DC oC7cH}'髅 @7oӧ o7c&DC oC7cH2 @7oӧ o7c&DC oC7cH9|ĉ @7oӧ o7c&DC oC7cȗVЋ @8pԨ p8d'DD pC8dݍ @8pԨ p8d'DD pC8dHTY @8pԨ p8d'DD pC8dH @8pԨ p8d'DD pC8d@ @8pԨ p8d'DD pC8dn6 @8pԨ p8d'DD pC8d̴ @8pԨ p8d'DD pC8dH+o& @8pԨ p8d'DD pC8dH)3 @8pԨ p8d'DD pC8d]? @8pԨ p8d'DD pC8dEK @9qթ q9e@'DE qC9eȣXW @9qթ q9e@'DE qC9eH;d @9qթ q9e@'DE qC9eH`̈́p @9qթ q9e@'DE qC9eȾ| @9qթ q9e@'DE qC9eB @9qթ q9e@'DE qC9eH{a @9qթ q9e@'DE qC9eHٶ @9qթ q9e@'DE qC9eH7q @9qթ q9e@'DE qC9eȕ+? @9qթ q9e@'DE qC9eƴ @:r֪r:f'DF rC:fHRҶ @:r֪r:f'DF rC:fHZ߸ @:r֪r:f'DF rC:ff @:r֪r:f'DF rC:flϯ @:r֪r:f'DF rC:fHˉ @:r֪r:f'DF rC:fH)DC @:r֪r:f'DF rC:fH @:r֪r:f'DF rC:f( @:r֪r:f'DF rC:fCs 5 @:r֪r:f'DF rC:fH-jA @;s׫s;g'DG sC;gHM @;s׫s;g'DG sC;g^Y @;s׫s;g'DG sC;gȼ\Gf @;s׫s;g'DG sC;gr @;s׫s;g'DG sC;gHy~ @;s׫s;g'DG sC;gH׋$ @;s׫s;g'DG sC;g5Fn @;s׫s;g'DG sC;gȓ @;s׫s;g'DG sC;g @;s׫s;g'DG sC;gHPuK @vڮv>j(DJ vC>j W@>vڮv>j(DJ vC>jhy @>vڮv>j(DJ vC>j3 @>vڮv>j(DJ vC>jH%4@>vڮv>j(DJ vC>jH~@>vڮv>j(DJ vC>jb@>vڮv>j(DJ vC>j?@>vڮv>j(DJ vC>jH[@>vڮv>j(DJ vC>jH @>vڮv>j(DJ vC>jHZL,@?wۯw?k(DK wC?kȸ99@?wۯw?k(DK wC?kE@?wۯw?k(DK wC?kHu{Q!@?wۯw?k(DK wC?kH5^#@?wۯw?k(DK wC?kH1_j%@?wۯw?k(DK wC?kȏv'@?wۯw?k(DK wC?kd)@?wۯw?k(DK wC?kHL=+@?wۯw?k(DK wC?kHن-@?wۯw?k(DK wC?kЧ/@@xܰx@l)DL xC@lfN1@@xܰx@l)DL xC@ld3@@xܰx@l)DL xC@lH#í5@@xܰx@l)DL xC@lH}7@@xܰx@l)DL xC@l7A9@@xܰx@l)DL xC@l=;@@xܰx@l)DL xC@lț=@@xܰx@l)DL xC@lHf @@@xܰx@l)DL xC@lHX!hB@@xܰx@l)DL xC@lȶ۱"D@AyݱyAm@)D M yCA m.F@AyݱyAm@)D M yCA mHsPE;H@AyݱyAm@)D M yCA mH GJ@AyݱyAm@)D M yCA mH/SL@AyݱyAm@)D M yCA mȍ"`N@AyݱyAm@)D M yCA m9llP@AyݱyAm@)D M yCA mHJxR@AyݱyAm@)D M yCA mHT@AyݱyAm@)D M yCA mHiIV@AyݱyAm@)D M yCA md#X@Bz޲zBn)D N zCB nܩZ@Bz޲zBn)D N zCB nH!&\@Bz޲zBn)D N zCB nHRp^@Bz޲zBn)D N zCB n `@Bz޲zBn)D N zCB n;b@Bz޲zBn)D N zCB nșMd@Bz޲zBn)D N zCB nH;f@Bz޲zBn)D N zCB nHVh@Bz޲zBn)D N zCB nȴ* k@Bz޲zBn)D N zCB nktm@C{߳{Co)D O {CC op%$o@C{߳{Co)D O {CC oH1q@C{߳{Co)D O {CC oH-Q=s@C{߳{Co)D O {CC oȋTIu@C{߳{Co)D O {CC oUw@C{߳{Co)D O {CC oHH.by@C{߳{Co)D O {CC oHxn{@C{߳{Co)D O {CC oH>z}@C{߳{Co)D O {CC ob @C{߳{Co)D O {CC oU@D||Dp*D P |CD pHm@D||Dp*D P |CD pH}'髅@D||Dp*D P |CD p2@D||Dp*D P |CD p9|ĉ@D||Dp*D P |CD pHVЋ@D||Dp*D P |CD pHݍ@D||Dp*D P |CD pHTY@D||Dp*D P |CD pȲ@D||Dp*D P |CD p@@D||Dp*D P |CD pHo6@E}}Eq@*D Q }CE qHʹ@E}}Eq@*D Q }CE q+o&@E}}Eq@*D Q }CE qȉ)3@E}}Eq@*D Q }CE q]?@E}}Eq@*D Q }CE qHFK@E}}Eq@*D Q }CE qHXW@E}}Eq@*D Q }CE q;d@E}}Eq@*D Q }CE q`̈́p@E}}Eq@*D Q }CE qȾ|@E}}Eq@*D Q }CE qHB@F~~Fr*DR ~CFrH{a@F~~Fr*DR ~CFrٶ@F~~Fr*DR ~CFr7q@F~~Fr*DR ~CFrH+?@F~~Fr*DR ~CFrHƴ@F~~Fr*DR ~CFrHRҶ@F~~Fr*DR ~CFrȰZ߸@F~~Fr*DR ~CFrf@F~~Fr*DR ~CFrHmϯ@F~~Fr*DR ~CFrHˉ@GGs*DS CGsH)DC@GGs*DS CGsȇ@GGs*DS CGs(@GGs*DS CGsHDs 5@GGs*DS CGsH-jA@GGs*DS CGsM@GGs*DS CGs^Y@GGs*DS CGsȼ\Gf@GGs*DS CGsHr@GGs*DS CGsHy~@HHt+DT CHt׋$@HHt+DT CHt5Fn@HHt+DT CHtȓ@HHt+DT CHtH@HHt+DT CHtHPuK@HHt+DT CHtȮ/@HHt+DT CHt @HHt+DT CHtHk(@HHt+DT CHtH^r@HHt+DT CHtH'@IIu@+DU CIuȅ@IIu@+DU CIuO@IIu@+DU CIuHBH@IIu@+DU CIuH*@IIu@+DU CIuH,7@IIu@+DU CIu\wvC@IIu@+DU CIuȺ1O@IIu@+DU CIuH \@IIu@+DU CIuHwSh@IIu@+DU CIu`t@JJv+DV CJv3@JJv+DV CJvȑ0@JJv+DV CJvHz@JJv+DV CJvHNJĥ@JJv+DV CJvȬ@JJv+DV CJv W@JJv+DV CJvhy @JJv+DV CJvH3 @JJv+DV CJvH%4@JJv+DV CJvȃ~@KKw+DW CKwb@KKw+DW CKwH@@KKw+DW CKwH[@KKw+DW CKwH @KKw+DW CKwZL,@KKw+DW CKwȸ99@KKw+DW CKwHE@KKw+DW CKwHu{Q!@KKw+DW CKwH5^#@KKw+DW CKw1_j%@L Lx,DX CLxȏv'@L Lx,DX CLxHd)@L Lx,DX CLxHL=+@L Lx,DX CLxȪن-@L Lx,DX CLxЧ/@L Lx,DX CLxfN1@L Lx,DX CLxHd3@L Lx,DX CLxH#í5@L Lx,DX CLxȁ}7@L Lx,DX CLx7A9@M!My@,DY !CMy=;@M!My@,DY !CMyH=@M!My@,DY !CMyHf @@M!My@,DY !CMyX!hB@M!My@,DY !CMyȶ۱"D@M!My@,DY !CMyH.F@M!My@,DY !CMyHsPE;H@M!My@,DY !CMyH GJ@M!My@,DY !CMy/SL@M!My@,DY !CMyȍ"`N@N"Nz,DZ "CNzH9llP@N"Nz,DZ "CNzHJxR@N"Nz,DZ "CNzȨT@N"Nz,DZ "CNziIV@N"Nz,DZ "CNzHe#X@N"Nz,DZ "CNzHܩZ@N"Nz,DZ "CNzH!&\@N"Nz,DZ "CNzRp^@N"Nz,DZ "CNz `@N"Nz,DZ "CNzH<b@O#O{,D[ #CO{HMd@O#O{,D[ #CO{;f@O#O{,D[ #CO{Vh@O#O{,D[ #CO{ȴ* k@O#O{,D[ #CO{Hktm@O#O{,D[ #CO{Hq%$o@O#O{,D[ #CO{1q@O#O{,D[ #CO{-Q=s@O#O{,D[ #CO{ȋTIu@O#O{,D[ #CO{HUw@P$P|-D\ $CP|HH.by@P$P|-D\ $CP|Ȧxn{@P$P|-D\ $CP|>z}@P$P|-D\ $CP|Hc @P$P|-D\ $CP|HU@P$P|-D\ $CP|Hm@P$P|-D\ $CP|}'髅@P$P|-D\ $CP|2@P$P|-D\ $CP|H:|ĉ@P$P|-D\ $CP|HVЋ@Q%Q}@-D] %CQ}Hݍ@Q%Q}@-D] %CQ}TY@Q%Q}@-D] %CQ}Ȳ@Q%Q}@-D] %CQ}H@@Q%Q}@-D] %CQ}Ho6@Q%Q}@-D] %CQ}ʹ@Q%Q}@-D] %CQ}+o&@Q%Q}@-D] %CQ}ȉ)3@Q%Q}@-D] %CQ}H]?@Q%Q}@-D] %CQ}HFK@R&R~-D^ &CR~ȤXW@R&R~-D^ &CR~;d@R&R~-D^ &CR~`̈́p@R&R~-D^ &CR~H|@R&R~-D^ &CR~HB@R&R~-D^ &CR~{a@R&R~-D^ &CR~ٶ@R&R~-D^ &CR~H8q@R&R~-D^ &CR~H+?@R&R~-D^ &CR~Hƴ@S'S-D_ 'CSRҶ@S'S-D_ 'CSȰZ߸@S'S-D_ 'CSHf@S'S-D_ 'CSHmϯ@S'S-D_ 'CSHˉ@S'S-D_ 'CS)DC@S'S-D_ 'CSȇ@S'S-D_ 'CSH(@S'S-D_ 'CSHDs 5@S'S-D_ 'CSȢ-jA@T(T.D` (CTM@T(T.D` (CT^Y@T(T.D` (CTH\Gf@T(T.D` (CTHr@T(T.D` (CTy~@T(T.D` (CT׋$@T(T.D` (CT5Fn@T(T.D` (CTH@T(T.D` (CTH@T(T.D` (CTPuK@U)U@.Da )CUȮ/@U)U@.Da )CUH @U)U@.Da )CUHk(@U)U@.Da )CUH^r@U)U@.Da )CU'@U)U@.Da )CUȅ@U)U@.Da )CUHO@U)U@.Da )CUHBH@U)U@.Da )CUH*@U)U@.Da )CU,7@V*V.Db *CV\wvC@V*V.Db *CVH1O@V*V.Db *CVH \@V*V.Db *CVwSh@V*V.Db *CV`t@V*V.Db *CV3@V*V.Db *CV$jF@V*V.Db *CV$GL@V*V.Db *CVd'%R@V*V.Db *CVdVY@W+W.Dc +CWd+_@W+W.Dc +CWPe@W+W.Dc +CWuk@W+W.Dc +CWwq@W+W.Dc +CWATw@W+W.Dc +CW$q1} @W+W.Dc +CW$ @W+W.Dc +CW$- @W+W.Dc +CWdR @W+W.Dc +CWd-w @X,X/D d ,CX \@X,X/D d ,CX `@X,X/D d ,CX =@X,X/D d ,CX  @X,X/D d ,CX $/@X,X/D d ,CX $HT@X,X/D d ,CX $wy@X,X/D d ,CX d@X,X/D d ,CX dl@X,X/D d ,CX J@Y-Y@/D!e -CY!3' @Y-Y@/D!e -CY!b2@Y-Y@/D!e -CY!V@Y-Y@/D!e -CY!{@Y-Y@/D!e -CY!$@Y-Y@/D!e -CY!$y@Y-Y@/D!e -CY!dNV@Y-Y@/D!e -CY!d}3 @Y-Y@/D!e -CY!d4 !@Y-Y@/D!e -CY!X"@Z.Z/D"f .CZ" }#@Z.Z/D"f .CZ"9$@Z.Z/D"f .CZ"h#%@Z.Z/D"f .CZ"$b)&@Z.Z/D"f .CZ"$?0'@Z.Z/D"f .CZ"$66(@Z.Z/D"f .CZ"d%Z<)@Z.Z/D"f .CZ"dTB*@Z.Z/D"f .CZ"H+@Z.Z/D"f .CZ"N,@[/[/D#g /C[#nT-@[/[/D#g /C[#L[.@[/[/D#g /C[#?)8a/@[/[/D#g /C[#$o]g0@[/[/D#g /C[#$m1@[/[/D#g /C[#ds2@[/[/D#g /C[#dy3@[/[/D#g /C[#d+{4@[/[/D#g /C[#ZX5@[/[/D#g /C[#5:6@\0\0D$h 0C\$_7@\0\0D$h 0C\$8@\0\0D$h 0C\$ͨ9@\0\0D$h 0C\$$Fͤ:@\0\0D$h 0C\$$u;@\0\0D$h 0C\$dd<@\0\0D$h 0C\$dA<=@\0\0D$h 0C\$a>@\0\0D$h 0C\$1?@\0\0D$h 0C\$`٪@@]1]@0D%i 1C]%䏶A@]1]@0D%i 1C]%侓B@]1]@0D%i 1C]%$pC@]1]@0D%i 1C]%$N>D@]1]@0D%i 1C]%$L+cE@]1]@0D%i 1C]%d{F@]1]@0D%i 1C]%dG@]1]@0D%i 1C]%H@]1]@0D%i 1C]%J@]1]@0D%i 1C]%7}K@^2^0D&j 2C^&fZ@ L@^2^0D&j 2C^&7eM@^2^0D&j 2C^&$N@^2^0D&j 2C^&$O@^2^0D&j 2C^&d#%P@^2^0D&j 2C^&dR+Q@^2^0D&j 2C^&d2R@^2^0D&j 2C^&fB8S@^2^0D&j 2C^&Cg>T@^2^0D&j 2C^&!DU@_3_0D'k 3C_'=JV@_3_0D'k 3C_'$mPW@_3_0D'k 3C_'$VX@_3_0D'k 3C_'$˕]Y@_3_0D'k 3C_'drDcZ@_3_0D'k 3C_'d)Pii[@_3_0D'k 3C_'X-o\@_3_0D'k 3C_' u]@_3_0D'k 3C_'{^@_3_0D'k 3C_'_@`4`1D(l 4C`(!`@`4`1D(l 4C`($DFa@`4`1D(l 4C`($s\kb@`4`1D(l 4C`(d9c@`4`1D(l 4C`(dd@`4`1D(l 4C`(d٦e@`4`1D(l 4C`(/f@`4`1D(l 4C`(^#g@`4`1D(l 4C`(䍋Hh@`4`1D(l 4C`(hmi@a5a@1D) m 5Ca) Ej@a5a@1D) m 5Ca) $#k@a5a@1D) m 5Ca) $Jl@a5a@1D) m 5Ca) dym@a5a@1D) m 5Ca) d%n@a5a@1D) m 5Ca) חJo@a5a@1D) m 5Ca) uop@a5a@1D) m 5Ca) 5Rq@a5a@1D) m 5Ca) d/r@a5a@1D) m 5Ca)  s@b6b1D* n 6Cb* $u@b6b1D* n 6Cb* $' v@b6b1D* n 6Cb* d!Lw@b6b1D* n 6Cb* dPqx@b6b1D* n 6Cb* ^y@b6b1D* n 6Cb* ;!z@b6b1D* n 6Cb* '{@b6b1D* n 6Cb*  .|@b6b1D* n 6Cb* ;)4}@b6b1D* n 6Cb* $kN:~@c7c1D+ o 7Cc+ $s@@c7c1D+ o 7Cc+ djF@c7c1D+ o 7Cc+ dGL@c7c1D+ o 7Cc+ d'%R@c7c1D+ o 7Cc+ VY@c7c1D+ o 7Cc+ +_@c7c1D+ o 7Cc+ 䴼Pe@c7c1D+ o 7Cc+ uk@c7c1D+ o 7Cc+ wq@c7c1D+ o 7Cc+ $BTw@d8d2D, p 8Dd, $q1}@d8d2D, p 8Dd, d @d8d2D, p 8Dd, d-@d8d2D, p 8Dd, R@d8d2D, p 8Dd, -w@d8d2D, p 8Dd, \@d8d2D, p 8Dd, `@d8d2D, p 8Dd, =樐@d8d2D, p 8Dd, $ @d8d2D, p 8Dd, $/@e9e@2D- q 9@De- $HT@e9e@2D- q 9@De- dwy@e9e@2D- q 9@De- dǕ@e9e@2D- q 9@De- l͖@e9e@2D- q 9@De- Jӗ@e9e@2D- q 9@De- 3' ژ@e9e@2D- q 9@De- b2@e9e@2D- q 9@De- V@e9e@2D- q 9@De- ${@e9e@2D- q 9@De- $@f:f2D.r :Df.dy@f:f2D.r :Df.dNV@f:f2D.r :Df.d}3@f:f2D.r :Df.4 @f:f2D.r :Df.X@f:f2D.r :Df. }@f:f2D.r :Df.9@f:f2D.r :Df.$i#@f:f2D.r :Df.$b)@f:f2D.r :Df.$?0@g;g2D/s ;Dg/d66@g;g2D/s ;Dg/d%Z<@g;g2D/s ;Dg/TB@g;g2D/s ;Dg/H@g;g2D/s ;Dg/N@g;g2D/s ;Dg/nT@g;g2D/s ;Dg/L[@g;g2D/s ;Dg/$@)8a@g;g2D/s ;Dg/$o]g@g;g2D/s ;Dg/dm@h<h3D0t <Dh0ds@h<h3D0t <Dh0dy@h<h3D0t <Dh0+{@h<h3D0t <Dh0ZX@h<h3D0t <Dh05:@h<h3D0t <Dh0_@h<h3D0t <Dh0@h<h3D0t <Dh0$ͨ@h<h3D0t <Dh0$Fͤ@h<h3D0t <Dh0du@i=i@3D1u =@Di1dd@i=i@3D1u =@Di1A<@i=i@3D1u =@Di1a@i=i@3D1u =@Di11ÿ@i=i@3D1u =@Di1`٪@i=i@3D1u =@Di1䏶@i=i@3D1u =@Di1$@i=i@3D1u =@Di1$p@i=i@3D1u =@Di1$N>@i=i@3D1u =@Di1dL+c@j>j3D2v >Dj2d{@j>j3D2v >Dj2@j>j3D2v >Dj2@j>j3D2v >Dj2@j>j3D2v >Dj27}@j>j3D2v >Dj2fZ@ @j>j3D2v >Dj2$7e@j>j3D2v >Dj2$@j>j3D2v >Dj2d@j>j3D2v >Dj2d#%@k?k3D3w ?Dk3dR+@k?k3D3w ?Dk32@k?k3D3w ?Dk3fB8@k?k3D3w ?Dk3Cg>@k?k3D3w ?Dk3!D@k?k3D3w ?Dk3$>J@k?k3D3w ?Dk3$mP@k?k3D3w ?Dk3$V@k?k3D3w ?Dk3d˕]@k?k3D3w ?Dk3drDc@l@l4D4x @Dl4)Pii@l@l4D4x @Dl4X-o@l@l4D4x @Dl4 u@l@l4D4x @Dl4{@l@l4D4x @Dl4$@l@l4D4x @Dl4$!@l@l4D4x @Dl4$DF@l@l4D4x @Dl4ds\k@l@l4D4x @Dl4d9@l@l4D4x @Dl4@m A m@4D5y A@Dm5٦@m A m@4D5y A@Dm5/@m A m@4D5y A@Dm5^#@m A m@4D5y A@Dm5䍋H@m A m@4D5y A@Dm5$hm@m A m@4D5y A@Dm5$E@m A m@4D5y A@Dm5d#@m A m@4D5y A@Dm5dJ@m A m@4D5y A@Dm5dy@m A m@4D5y A@Dm5%@n B n4D6z BDn6חJ@n B n4D6z BDn6uo@n B n4D6z BDn65R@n B n4D6z BDn6$e/@n B n4D6z BDn6$ @n B n4D6z BDn6$@n B n4D6z BDn6d' @n B n4D6z BDn6d!L@n B n4D6z BDn6Pq@n B n4D6z BDn6^@o C o4D7{ CDo7;!@o C o4D7{ CDo7'@o C o4D7{ CDo7 .@o C o4D7{ CDo7$<)4@o C o4D7{ CDo7$kN:@o C o4D7{ CDo7ds@@o C o4D7{ CDo7djF@o C o4D7{ CDo7dGL@o C o4D7{ CDo7'%R@o C o4D7{ CDo7VY@p D p5D8|DDp8+_@p D p5D8|DDp8䴼Pe@p D p5D8|DDp8uk@p D p5D8|DDp8$wq@p D p5D8|DDp8$BTw@p D p5D8|DDp8dq1} @p D p5D8|DDp8d @p D p5D8|DDp8- @p D p5D8|DDp8R @p D p5D8|DDp8-w @q E q@5D9}E@Dq9\@q E q@5D9}E@Dq9`@q E q@5D9}E@Dq9$=@q E q@5D9}E@Dq9$ @q E q@5D9}E@Dq9$/@q E q@5D9}E@Dq9dHT@q E q@5D9}E@Dq9dwy@q E q@5D9}E@Dq9@q E q@5D9}E@Dq9l@q E q@5D9}E@Dq9J@rFr5D:~FDr:3' @rFr5D:~FDr:b2@rFr5D:~FDr:$V@rFr5D:~FDr:${@rFr5D:~FDr:d@rFr5D:~FDr:dy@rFr5D:~FDr:dNV@rFr5D:~FDr:}3 @rFr5D:~FDr:4 !@rFr5D:~FDr:X"@sGs5D;GDs; }#@sGs5D;GDs;$:$@sGs5D;GDs;$i#%@sGs5D;GDs;$b)&@sGs5D;GDs;d?0'@sGs5D;GDs;d66(@sGs5D;GDs;%Z<)@sGs5D;GDs;TB*@sGs5D;GDs;H+@sGs5D;GDs;䲑N,@tHt6D<HDt<nT-@tHt6D<HDt<$L[.@tHt6D<HDt<$@)8a/@tHt6D<HDt<do]g0@tHt6D<HDt<dm1@tHt6D<HDt<ds2@tHt6D<HDt<y3@tHt6D<HDt<+{4@tHt6D<HDt<ZX5@tHt6D<HDt<5:6@uIu@6D=I@Du=_7@uIu@6D=I@Du=$8@uIu@6D=I@Du=$ͨ9@uIu@6D=I@Du=dFͤ:@uIu@6D=I@Du=du;@uIu@6D=I@Du=d<@uIu@6D=I@Du=A<=@uIu@6D=I@Du=a>@uIu@6D=I@Du=1?@uIu@6D=I@Du=`٪@@vJv6D>JDv>$A@vJv6D>JDv>$B@vJv6D>JDv>dpC@vJv6D>JDv>dN>D@vJv6D>JDv>L+cE@vJv6D>JDv>{F@vJv6D>JDv>G@vJv6D>JDv>H@vJv6D>JDv>J@vJv6D>JDv>$8}K@wKw6D?KDw?$gZ@ L@wKw6D?KDw?d7eM@wKw6D?KDw?dN@wKw6D?KDw?dO@wKw6D?KDw?#%P@wKw6D?KDw?R+Q@wKw6D?KDw?䁉2R@wKw6D?KDw?fB8S@wKw6D?KDw?Cg>T@wKw6D?KDw?$!DU@xLx7D@ LDx@ $>JV@xLx7D@ LDx@ dmPW@xLx7D@ LDx@ dVX@xLx7D@ LDx@ ˕]Y@xLx7D@ LDx@ rDcZ@xLx7D@ LDx@ )Pii[@xLx7D@ LDx@ X-o\@xLx7D@ LDx@ u]@xLx7D@ LDx@ ${^@xLx7D@ LDx@ $_@yMy@7DA!M@DyA!$!`@yMy@7DA!M@DyA!dDFa@yMy@7DA!M@DyA!ds\kb@yMy@7DA!M@DyA!9c@yMy@7DA!M@DyA!d@yMy@7DA!M@DyA!٦e@yMy@7DA!M@DyA!/f@yMy@7DA!M@DyA!^#g@yMy@7DA!M@DyA!$Hh@yMy@7DA!M@DyA!$hmi@zNz7DB"NDzB"dEj@zNz7DB"NDzB"d#k@zNz7DB"NDzB"dJl@zNz7DB"NDzB"ym@zNz7DB"NDzB"%n@zNz7DB"NDzB"חJo@zNz7DB"NDzB"uop@zNz7DB"NDzB"$6Rq@zNz7DB"NDzB"$e/r@zNz7DB"NDzB"$ s@{O{7DC#OD{C#du@{O{7DC#OD{C#d' v@{O{7DC#OD{C#!Lw@{O{7DC#OD{C#Pqx@{O{7DC#OD{C#^y@{O{7DC#OD{C#;!z@{O{7DC#OD{C#'{@{O{7DC#OD{C#$ .|@{O{7DC#OD{C#$<)4}@{O{7DC#OD{C#dkN:~@|P|8DD$PD|D$ds@@|P|8DD$PD|D$djF@|P|8DD$PD|D$GL@|P|8DD$PD|D$'%R@|P|8DD$PD|D$VY@|P|8DD$PD|D$+_@|P|8DD$PD|D$䴼Pe@|P|8DD$PD|D$$uk@|P|8DD$PD|D$$wq@|P|8DD$PD|D$dBTw@}Q}@8DE%Q@D}E%dq1}@}Q}@8DE%Q@D}E% @}Q}@8DE%Q@D}E%-@}Q}@8DE%Q@D}E%R@}Q}@8DE%Q@D}E%-w@}Q}@8DE%Q@D}E%\@}Q}@8DE%Q@D}E%$`@}Q}@8DE%Q@D}E%$=樐@}Q}@8DE%Q@D}E%$ @}Q}@8DE%Q@D}E%d/@~R~8DF&RD~F&dHT@~R~8DF&RD~F&wy@~R~8DF&RD~F&Ǖ@~R~8DF&RD~F&l͖@~R~8DF&RD~F&Jӗ@~R~8DF&RD~F&3' ژ@~R~8DF&RD~F&$c2@~R~8DF&RD~F&$V@~R~8DF&RD~F&d{@~R~8DF&RD~F&d@S8DG'SDG'dy@S8DG'SDG'NV@S8DG'SDG'}3@S8DG'SDG'4 @S8DG'SDG'X@S8DG'SDG'$ }@S8DG'SDG'$:@S8DG'SDG'$i#@S8DG'SDG'db)@S8DG'SDG'd?0@T9DH(TDH(66@T9DH(TDH(%Z<@T9DH(TDH(TB@T9DH(TDH(䃴H@T9DH(TDH($N@T9DH(TDH($nT@T9DH(TDH($L[@T9DH(TDH(d@)8a@T9DH(TDH(do]g@T9DH(TDH(m@U@9DI)U@DI)s@U@9DI)U@DI)y@U@9DI)U@DI)+{@U@9DI)U@DI)ZX@U@9DI)U@DI)$5:@U@9DI)U@DI)$_@U@9DI)U@DI)d@U@9DI)U@DI)dͨ@U@9DI)U@DI)dFͤ@U@9DI)U@DI)u@V9DJ*VDJ*d@V9DJ*VDJ*A<@V9DJ*VDJ*a@V9DJ*VDJ*$2ÿ@V9DJ*VDJ*$a٪@V9DJ*VDJ*$@V9DJ*VDJ*d@V9DJ*VDJ*dp@V9DJ*VDJ*N>@V9DJ*VDJ*L+c@W9DK+WDK+{@W9DK+WDK+@W9DK+WDK+@W9DK+WDK+$ @W9DK+WDK+$8}@W9DK+WDK+dgZ@ @W9DK+WDK+d7e@W9DK+WDK+d@W9DK+WDK+@W9DK+WDK+#%@ X :DL,XDL,R+@ X :DL,XDL,䁉2@ X :DL,XDL,fB8@ X :DL,XDL,$Cg>@ X :DL,XDL,$!D@ X :DL,XDL,d>J@ X :DL,XDL,dmP@ X :DL,XDL,V@ X :DL,XDL,˕]@ X :DL,XDL,rDc@!Y!@:DM-Y@DM-)Pii@!Y!@:DM-Y@DM-X-o@!Y!@:DM-Y@DM-$ u@!Y!@:DM-Y@DM-${@!Y!@:DM-Y@DM-$@!Y!@:DM-Y@DM-d!@!Y!@:DM-Y@DM-dDF@!Y!@:DM-Y@DM-s\k@!Y!@:DM-Y@DM-9@!Y!@:DM-Y@DM-@"Z":DN.ZDN.٦@"Z":DN.ZDN./@"Z":DN.ZDN.$_#@"Z":DN.ZDN.$H@"Z":DN.ZDN.dhm@"Z":DN.ZDN.dE@"Z":DN.ZDN.d#@"Z":DN.ZDN.J@"Z":DN.ZDN.y@"Z":DN.ZDN.䨺%@#[#:DO/[DO/חJ@#[#:DO/[DO/$uo@#[#:DO/[DO/$6R@#[#:DO/[DO/$e/@#[#:DO/[DO/d @#[#:DO/[DO/d@#[#:DO/[DO/' @#[#:DO/[DO/!L@#[#:DO/[DO/Pq@#[#:DO/[DO/^@$\$;DP0\ DP0;!@$\$;DP0\ DP0$'@$\$;DP0\ DP0$ .@$\$;DP0\ DP0d<)4@$\$;DP0\ DP0dkN:@$\$;DP0\ DP0ds@@$\$;DP0\ DP0jF@$\$;DP0\ DP0GL@$\$;DP0\ DP0'%R@$\$;DP0\ DP0VY@%]%@;DQ1]@ DQ1+_@%]%@;DQ1]@ DQ1$Pe@%]%@;DQ1]@ DQ1$uk@%]%@;DQ1]@ DQ1dwq@%]%@;DQ1]@ DQ1dBTw@%]%@;DQ1]@ DQ1q1} @%]%@;DQ1]@ DQ1 @%]%@;DQ1]@ DQ1- @%]%@;DQ1]@ DQ1R @%]%@;DQ1]@ DQ1-w @&^&;DR2^ DR2$]@&^&;DR2^ DR2$`@&^&;DR2^ DR2d=@&^&;DR2^ DR2d @&^&;DR2^ DR2/@&^&;DR2^ DR2HT@&^&;DR2^ DR2wy@&^&;DR2^ DR2䦏@&^&;DR2^ DR2l@&^&;DR2^ DR2$J@'_';DS3_ DS3$4' @'_';DS3_ DS3dc2@'_';DS3_ DS3dV@'_';DS3_ DS3d{@'_';DS3_ DS3@'_';DS3_ DS3y@'_';DS3_ DS3NV@'_';DS3_ DS3}3 @'_';DS3_ DS34 !@'_';DS3_ DS3$X"@(`(@*b*D@+c+T@,d,=DX8d DX8d!DU@-e-@=DY9e@ DY9d>JV@-e-@=DY9e@ DY9mPW@-e-@=DY9e@ DY9VX@-e-@=DY9e@ DY9˕]Y@-e-@=DY9e@ DY9rDcZ@-e-@=DY9e@ DY9)Pii[@-e-@=DY9e@ DY9$Y-o\@-e-@=DY9e@ DY9$ u]@-e-@=DY9e@ DY9${^@-e-@=DY9e@ DY9d_@.f.=DZ:f DZ:d!`@.f.=DZ:f DZ:DFa@.f.=DZ:f DZ:s\kb@.f.=DZ:f DZ:9c@.f.=DZ:f DZ:d@.f.=DZ:f DZ:٦e@.f.=DZ:f DZ:$0f@.f.=DZ:f DZ:$_#g@.f.=DZ:f DZ:dHh@.f.=DZ:f DZ:dhmi@/g/=D[;g D[;dEj@/g/=D[;g D[;#k@/g/=D[;g D[;Jl@/g/=D[;g D[;ym@/g/=D[;g D[;䨺%n@/g/=D[;g D[;$ؗJo@/g/=D[;g D[;$uop@/g/=D[;g D[;$6Rq@/g/=D[;g D[;de/r@/g/=D[;g D[;d s@0h0>D\<h D\<u@0h0>D\<h D\<' v@0h0>D\<h D\<!Lw@0h0>D\<h D\<Pqx@0h0>D\<h D\<$^y@0h0>D\<h D\<$;!z@0h0>D\<h D\<$'{@0h0>D\<h D\<d .|@0h0>D\<h D\<d<)4}@0h0>D\<h D\<kN:~@1i1@>D]=i@ D]=s@@1i1@>D]=i@ D]=jF@1i1@>D]=i@ D]=GL@1i1@>D]=i@ D]='%R@1i1@>D]=i@ D]=$WY@1i1@>D]=i@ D]=$+_@1i1@>D]=i@ D]=dPe@1i1@>D]=i@ D]=duk@1i1@>D]=i@ D]=dwq@1i1@>D]=i@ D]=BTw@2j2>D^>j D^>q1}@2j2>D^>j D^> @2j2>D^>j D^>-@2j2>D^>j D^>$R@2j2>D^>j D^>$.w@2j2>D^>j D^>$]@2j2>D^>j D^>d`@2j2>D^>j D^>d=樐@2j2>D^>j D^> @2j2>D^>j D^>/@3k3>D_?k D_?HT@3k3>D_?k D_?wy@3k3>D_?k D_?䦏Ǖ@3k3>D_?k D_?$l͖@3k3>D_?k D_?$Jӗ@3k3>D_?k D_?d4' ژ@3k3>D_?k D_?dc2@3k3>D_?k D_?dV@3k3>D_?k D_?{@3k3>D_?k D_?@4l4?D`@l D`@y@4l4?D`@l D`@NV@4l4?D`@l D`@}3@4l4?D`@l D`@$4 @4l4?D`@l D`@$X@4l4?D`@l D`@d }@4l4?D`@l D`@d:@4l4?D`@l D`@i#@4l4?D`@l D`@b)@4l4?D`@l D`@?0@5 m5@?DaAm@ DaA66@5 m5@?DaAm@ DaA%Z<@5 m5@?DaAm@ DaA$UB@5 m5@?DaAm@ DaA$H@5 m5@?DaAm@ DaA$N@5 m5@?DaAm@ DaAdnT@5 m5@?DaAm@ DaAdL[@5 m5@?DaAm@ DaA@)8a@5 m5@?DaAm@ DaAo]g@5 m5@?DaAm@ DaAm@6 n6?DbBn DbBs@6 n6?DbBn DbBy@6 n6?DbBn DbB$,{@6 n6?DbBn DbB$[X@6 n6?DbBn DbBd5:@6 n6?DbBn DbBd_@6 n6?DbBn DbBd@6 n6?DbBn DbBͨ@6 n6?DbBn DbBFͤ@6 n6?DbBn DbBu@7 o7?DcCo DcCd@7 o7?DcCo DcC$A<@7 o7?DcCo DcC$a@7 o7?DcCo DcC$2ÿ@7 o7?DcCo DcCda٪@7 o7?DcCo DcCd@7 o7?DcCo DcC@7 o7?DcCo DcCp@7 o7?DcCo DcCN>@7 o7?DcCo DcCL+c@8 p8@DdDpDdD{@8 p8@DdDpDdD$@8 p8@DdDpDdD$@8 p8@DdDpDdDd @8 p8@DdDpDdDd8}@8 p8@DdDpDdDdgZ@ @8 p8@DdDpDdD7e@8 p8@DdDpDdD@8 p8@DdDpDdD@8 p8@DdDpDdD#%@9 q9@@DeEq@DeER+@9 q9@@DeEq@DeE$2@9 q9@@DeEq@DeE$fB8@9 q9@@DeEq@DeEdCg>@9 q9@@DeEq@DeEd!D@9 q9@@DeEq@DeE>J@9 q9@@DeEq@DeEmP@9 q9@@DeEq@DeEV@9 q9@@DeEq@DeE˕]@9 q9@@DeEq@DeErDc@:r:@DfFrDfF$*Pii@:r:@DfFrDfF$Y-o@:r:@DfFrDfFd u@:r:@DfFrDfFd{@:r:@DfFrDfF@:r:@DfFrDfF!@:r:@DfFrDfFDF@:r:@DfFrDfFs\k@:r:@DfFrDfF9@:r:@DfFrDfF$@;s;@DgGsDgG$٦@;s;@DgGsDgGd0@;s;@DgGsDgGd_#@;s;@DgGsDgGdH@;s;@DgGsDgGhm@;s;@DgGsDgGE@;s;@DgGsDgG#@;s;@DgGsDgGJ@;s;@DgGsDgGy@;s;@DgGsDgG$%@<t<ADhHtDhH$ؗJ@<t<ADhHtDhHduo@<t<ADhHtDhHd6R@<t<ADhHtDhHe/@<t<ADhHtDhH @<t<ADhHtDhH@<t<ADhHtDhH' @<t<ADhHtDhH!L@<t<ADhHtDhH$Qq@<t<ADhHtDhH$^@=u=@ADiIu@DiI$;!@=u=@ADiIu@DiId'@=u=@ADiIu@DiId .@=u=@ADiIu@DiI<)4@=u=@ADiIu@DiIkN:@=u=@ADiIu@DiI䚍s@@=u=@ADiIu@DiIjF@=u=@ADiIu@DiIGL@=u=@ADiIu@DiI$(%R@=u=@ADiIu@DiI$WY@>v>ADjJvDjJd+_@>v>ADjJvDjJdPe@>v>ADjJvDjJduk@>v>ADjJvDjJwq@>v>ADjJvDjJBTw@>v>ADjJvDjJq1} @>v>ADjJvDjJ @>v>ADjJvDjJ$- @>v>ADjJvDjJ$R @>v>ADjJvDjJ$.w @?w?ADkKwDkKd]@?w?ADkKwDkKd`@?w?ADkKwDkK=@?w?ADkKwDkK @?w?ADkKwDkK/@?w?ADkKwDkKHT@?w?ADkKwDkKwy@?w?ADkKwDkK$@?w?ADkKwDkK$l@?w?ADkKwDkKdJ@@x@BDlLxDlLd4' @@x@BDlLxDlLdc2@@x@BDlLxDlLV@@x@BDlLxDlL{@@x@BDlLxDlL@@x@BDlLxDlLy@@x@BDlLxDlLNV@@x@BDlLxDlL$~3 @@x@BDlLxDlL$4 !@@x@BDlLxDlLdX"@AyA@BDmMy@D mMd }#@AyA@BDmMy@D mM:$@AyA@BDmMy@D mMi#%@AyA@BDmMy@D mMb)&@AyA@BDmMy@D mM?0'@AyA@BDmMy@D mM66(@AyA@BDmMy@D mM$&Z<)@AyA@BDmMy@D mM$UB*@AyA@BDmMy@D mM$H+@AyA@BDmMy@D mMdN,@BzBBDnNzD nNdnT-@BzBBDnNzD nNL[.@BzBBDnNzD nN@)8a/@BzBBDnNzD nNo]g0@BzBBDnNzD nNm1@BzBBDnNzD nNs2@BzBBDnNzD nN$y3@BzBBDnNzD nN$,{4@BzBBDnNzD nNd[X5@BzBBDnNzD nNd5:6@C{CBDoO{D oOd_7@C{CBDoO{D oO8@C{CBDoO{D oOͨ9@C{CBDoO{D oOFͤ:@C{CBDoO{D oOu;@C{CBDoO{D oO$d<@C{CBDoO{D oO$A<=@C{CBDoO{D oO$a>@C{CBDoO{D oOd2?@C{CBDoO{D oOda٪@@D|DCDpP|D pPA@D|DCDpP|D pPB@D|DCDpP|D pPpC@D|DCDpP|D pPN>D@D|DCDpP|D pP$M+cE@D|DCDpP|D pP$|F@D|DCDpP|D pP$G@D|DCDpP|D pPdH@D|DCDpP|D pPd J@D|DCDpP|D pP8}K@E}E@CDqQ}@D qQgZ@ L@E}E@CDqQ}@D qQ7eM@E}E@CDqQ}@D qQN@E}E@CDqQ}@D qQO@E}E@CDqQ}@D qQ$$%P@E}E@CDqQ}@D qQ$S+Q@E}E@CDqQ}@D qQd2R@E}E@CDqQ}@D qQdfB8S@E}E@CDqQ}@D qQdCg>T@E}E@CDqQ}@D qQ!DU@F~FCDrR~DrR>JV@F~FCDrR~DrRmPW@F~FCDrR~DrR䜸VX@F~FCDrR~DrR$̕]Y@F~FCDrR~DrR$rDcZ@F~FCDrR~DrR$*Pii[@F~FCDrR~DrRdY-o\@F~FCDrR~DrRd u]@F~FCDrR~DrR{^@F~FCDrR~DrR_@GGCDsSDsS!`@GGCDsSDsSDFa@GGCDsSDsSs\kb@GGCDsSDsS$9c@GGCDsSDsS$d@GGCDsSDsSd٦e@GGCDsSDsSd0f@GGCDsSDsSd_#g@GGCDsSDsSHh@GGCDsSDsShmi@HHDDtTDtTEj@HHDDtTDtT#k@HHDDtTDtTJl@HHDDtTDtT$zm@HHDDtTDtT$%n@HHDDtTDtTdؗJo@HHDDtTDtTduop@HHDDtTDtT6Rq@HHDDtTDtTe/r@HHDDtTDtT s@II@DDuU@DuUu@II@DDuU@DuU' v@II@DDuU@DuU$"Lw@II@DDuU@DuU$Qqx@II@DDuU@DuU$^y@II@DDuU@DuUd;!z@II@DDuU@DuUd'{@II@DDuU@DuU .|@II@DDuU@DuU<)4}@II@DDuU@DuUkN:~@JJDDvVDvV䚍s@@JJDDvVDvVjF@JJDDvVDvV$GL@JJDDvVDvV$(%R@JJDDvVDvVdWY@JJDDvVDvVd+_@JJDDvVDvVdPe@JJDDvVDvVuk@JJDDvVDvVwq@JJDDvVDvVBTw@KKDDwWDwWq1}@KKDDwWDwW$ @KKDDwWDwW$-@KKDDwWDwW$R@KKDDwWDwWd.w@KKDDwWDwWd]@KKDDwWDwW`@KKDDwWDwW=樐@KKDDwWDwW @KKDDwWDwW/@L LEDxXDxXHT@L LEDxXDxX$xy@L LEDxXDxX$Ǖ@L LEDxXDxXdl͖@L LEDxXDxXdJӗ@L LEDxXDxXd4' ژ@L LEDxXDxXc2@L LEDxXDxXV@L LEDxXDxX{@L LEDxXDxX@M!M@EDyY@DyYy@M!M@EDyY@DyY$OV@M!M@EDyY@DyY$~3@M!M@EDyY@DyYd4 @M!M@EDyY@DyYdX@M!M@EDyY@DyY }@M!M@EDyY@DyY:@M!M@EDyY@DyYi#@M!M@EDyY@DyYb)@M!M@EDyY@DyY?0@N"NEDzZDzZ$66@N"NEDzZDzZ$&Z<@N"NEDzZDzZdUB@N"NEDzZDzZdH@N"NEDzZDzZN@N"NEDzZDzZnT@N"NEDzZDzZL[@N"NEDzZDzZ@)8a@N"NEDzZDzZo]g@N"NEDzZDzZ$m@O#OED{[D{[$s@O#OED{[D{[dy@O#OED{[D{[d,{@O#OED{[D{[d[X@O#OED{[D{[5:@O#OED{[D{[_@O#OED{[D{[@O#OED{[D{[ͨ@O#OED{[D{[Fͤ@O#OED{[D{[$v@P$PFD|\D|\$d@P$PFD|\D|\dA<@P$PFD|\D|\da@P$PFD|\D|\2ÿ@P$PFD|\D|\a٪@P$PFD|\D|\@P$PFD|\D|\俓@P$PFD|\D|\p@P$PFD|\D|\$N>@P$PFD|\D|\$M+c@Q%Q@FD}]@D}]$|@Q%Q@FD}]@D}]d@Q%Q@FD}]@D}]d@Q%Q@FD}]@D}] @Q%Q@FD}]@D}]8}@Q%Q@FD}]@D}]gZ@ @Q%Q@FD}]@D}]7e@Q%Q@FD}]@D}]@Q%Q@FD}]@D}]$@Q%Q@FD}]@D}]$$%@R&RFD~^D~^dS+@R&RFD~^D~^d2@R&RFD~^D~^dfB8@R&RFD~^D~^Cg>@R&RFD~^D~^!D@R&RFD~^D~^>J@R&RFD~^D~^mP@R&RFD~^D~^$V@R&RFD~^D~^$̕]@R&RFD~^D~^$rDc@S'SFD_D_d*Pii@S'SFD_D_dY-o@S'SFD_D_ u@S'SFD_D_{@S'SFD_D_@S'SFD_D_!@S'SFD_D_DF@S'SFD_D_$t\k@S'SFD_D_$9@S'SFD_D_d@T(TGD`D`d٦@T(TGD`D`d0@T(TGD`D`_#@T(TGD`D`H@T(TGD`D`hm@T(TGD`D`E@T(TGD`D`#@T(TGD`D`$K@T(TGD`D`$z@T(TGD`D`d%@U)U@GDa@DadؗJ@U)U@GDa@Dauo@U)U@GDa@Da6R@U)U@GDa@Dae/@U)U@GDa@Da @U)U@GDa@Da@U)U@GDa@Da$' @U)U@GDa@Da$"L@U)U@GDa@Da$Qq@U)U@GDa@Dad^@V*VGDbDbd;!@V*VGDbDb'@V*VGDbDb .@V*VGDbDb<)4@V*VGDbDbkN:@V*VGDbDb䚍s@@V*VGDbDb$jF@V*VGDbDb$GL@V*VGDbDbd(%R@V*VGDbDbdWY@W+WGDcDcd+_@W+WGDcDcPe@W+WGDcDcuk@W+WGDcDcwq@W+WGDcDcBTw@W+WGDcDc$r1} @W+WGDcDc$ @W+WGDcDc$- @W+WGDcDcdR @W+WGDcDcd.w @X,XHDdD d]@X,XHDdD d`@X,XHDdD d=@X,XHDdD d @X,XHDdD d$/@X,XHDdD d$IT@X,XHDdD d$xy@X,XHDdD dd@X,XHDdD ddl@X,XHDdD dJ@Y-Y@HDe@D!e4' @Y-Y@HDe@D!ec2@Y-Y@HDe@D!eV@Y-Y@HDe@D!e{@Y-Y@HDe@D!e$@Y-Y@HDe@D!e$ y@Y-Y@HDe@D!edOV@Y-Y@HDe@D!ed~3 @Y-Y@HDe@D!ed4 !@Y-Y@HDe@D!eX"@Z.ZHDfD"f }#@Z.ZHDfD"f:$@Z.ZHDfD"fi#%@Z.ZHDfD"f$b)&@Z.ZHDfD"f$?0'@Z.ZHDfD"f$66(@Z.ZHDfD"fd&Z<)@Z.ZHDfD"fdUB*@Z.ZHDfD"fH+@Z.ZHDfD"fN,@[/[HDgD#gnT-@[/[HDgD#gL[.@[/[HDgD#g@)8a/@[/[HDgD#g$p]g0@[/[HDgD#g$m1@[/[HDgD#gds2@[/[HDgD#gdy3@[/[HDgD#gd,{4@[/[HDgD#g[X5@[/[HDgD#g5:6@\0\IDhD$h_7@\0\IDhD$h8@\0\IDhD$hͨ9@\0\IDhD$h$Gͤ:@\0\IDhD$h$v;@\0\IDhD$hdd<@\0\IDhD$hdA<=@\0\IDhD$ha>@\0\IDhD$h2?@\0\IDhD$ha٪@@]1]@IDi@D%i䐶A@]1]@IDi@D%i俓B@]1]@IDi@D%i$pC@]1]@IDi@D%i$N>D@]1]@IDi@D%i$M+cE@]1]@IDi@D%id|F@]1]@IDi@D%idG@]1]@IDi@D%iH@]1]@IDi@D%i J@]1]@IDi@D%i8}K@^2^IDjD&jgZ@ L@^2^IDjD&j7eM@^2^IDjD&j$N@^2^IDjD&j$O@^2^IDjD&jd$%P@^2^IDjD&jdS+Q@^2^IDjD&jd2R@^2^IDjD&jfB8S@^2^IDjD&jCg>T@^2^IDjD&j!DU@_3_IDkD'k>JV@_3_IDkD'k$nPW@_3_IDkD'k$VX@_3_IDkD'k$̕]Y@_3_IDkD'kdrDcZ@_3_IDkD'kd*Pii[@_3_IDkD'kY-o\@_3_IDkD'k u]@_3_IDkD'k{^@_3_IDkD'k_@`4`JDlD(l!`@`4`JDlD(l$EFa@`4`JDlD(l$t\kb@`4`JDlD(ld9c@`4`JDlD(ldd@`4`JDlD(ld٦e@`4`JDlD(l0f@`4`JDlD(l_#g@`4`JDlD(l䎋Hh@`4`JDlD(lhmi@a5a @JDm@D) mEj@a5a @JDm@D) m$#k@a5a @JDm@D) m$Kl@a5a @JDm@D) mdzm@a5a @JDm@D) md%n@a5a @JDm@D) mؗJo@a5a @JDm@D) muop@a5a @JDm@D) m6Rq@a5a @JDm@D) me/r@a5a @JDm@D) m s@b6b JDnD* n$u@b6b JDnD* n$' v@b6b JDnD* nd"Lw@b6b JDnD* ndQqx@b6b JDnD* n^y@b6b JDnD* n;!z@b6b JDnD* n'{@b6b JDnD* n .|@b6b JDnD* n<)4}@b6b JDnD* n$lN:~@c7c JDoD+ o$s@@c7c JDoD+ odjF@c7c JDoD+ odGL@c7c JDoD+ od(%R@c7c JDoD+ oWY@c7c JDoD+ o+_@c7c JDoD+ o䵼Pe@c7c JDoD+ ouk@c7c JDoD+ owq@c7c JDoD+ o$CTw@d8d KDpD, p$r1}@d8d KDpD, pd @d8d KDpD, pd-@d8d KDpD, pR@d8d KDpD, p.w@d8d KDpD, p]@d8d KDpD, p`@d8d KDpD, p=樐@d8d KDpD, p$ @d8d KDpD, p$/@e9e @KDq@D- q$IT@e9e @KDq@D- qdxy@e9e @KDq@D- qdǕ@e9e @KDq@D- ql͖@e9e @KDq@D- qJӗ@e9e @KDq@D- q4' ژ@e9e @KDq@D- qc2@e9e @KDq@D- qV@e9e @KDq@D- q$¾{@e9e @KDq@D- q$@f:fKDrD.rd y@f:fKDrD.rdOV@f:fKDrD.rd~3@f:fKDrD.r4 @f:fKDrD.rX@f:fKDrD.r }@f:fKDrD.r:@f:fKDrD.r$j#@f:fKDrD.r$b)@f:fKDrD.r$?0@g;gKDsD/sd66@g;gKDsD/sd&Z<@g;gKDsD/sUB@g;gKDsD/sH@g;gKDsD/sN@g;gKDsD/snT@g;gKDsD/sL[@g;gKDsD/s$A)8a@g;gKDsD/s$p]g@g;gKDsD/sdm@h<hLDtD0tds@h<hLDtD0tdy@h<hLDtD0t,{@h<hLDtD0t[X@h<hLDtD0t5:@h<hLDtD0t_@h<hLDtD0t@h<hLDtD0t$ͨ@h<hLDtD0t$Gͤ@h<hLDtD0tdv@i=i@LDu@D1udd@i=i@LDu@D1uA<@i=i@LDu@D1ua@i=i@LDu@D1u2ÿ@i=i@LDu@D1ua٪@i=i@LDu@D1u䐶@i=i@LDu@D1u$@i=i@LDu@D1u$p@i=i@LDu@D1u$N>@i=i@LDu@D1udM+c@j>jLDvD2vd|@j>jLDvD2v@j>jLDvD2v@j>jLDvD2v @j>jLDvD2v8}@j>jLDvD2vgZ@ @j>jLDvD2v$7e@j>jLDvD2v$@j>jLDvD2vd@j>jLDvD2vd$%@k?kLDwD3wdS+@k?kLDwD3w2@k?kLDwD3wfB8@k?kLDwD3wCg>@k?kLDwD3w!D@k?kLDwD3w$?J@k?kLDwD3w$nP@k?kLDwD3w$V@k?kLDwD3wd̕]@k?kLDwD3wdrDc@l@lMDxD4x*Pii@l@lMDxD4xY-o@l@lMDxD4x u@l@lMDxD4x{@l@lMDxD4x$@l@lMDxD4x$!@l@lMDxD4x$EF@l@lMDxD4xdt\k@l@lMDxD4xd9@l@lMDxD4x@ mA m@MDy @D5y٦@ mA m@MDy @D5y0@ mA m@MDy @D5y_#@ mA m@MDy @D5y䎋H@ mA m@MDy @D5y$hm@ mA m@MDy @D5y$E@ mA m@MDy @D5yd#@ mA m@MDy @D5ydK@ mA m@MDy @D5ydz@ mA m@MDy @D5y%@ nB nMDz D6zؗJ@ nB nMDz D6zuo@ nB nMDz D6z6R@ nB nMDz D6z$f/@ nB nMDz D6z$ @ nB nMDz D6z$@ nB nMDz D6zd' @ nB nMDz D6zd"L@ nB nMDz D6zQq@ nB nMDz D6z^@ oC oMD{ D7{;!@ oC oMD{ D7{'@ oC oMD{ D7{ .@ oC oMD{ D7{$=)4@ oC oMD{ D7{$lN:@ oC oMD{ D7{ds@@ oC oMD{ D7{djF@ oC oMD{ D7{dGL@ oC oMD{ D7{(%R@ oC oMD{ D7{WY@ pD pND| D8|+_@ pD pND| D8|䵼Pe@ pD pND| D8|uk@ pD pND| D8|$wq@ pD pND| D8|$CTw@ pD pND| D8|dr1} @ pD pND| D8|d @ pD pND| D8|- @ pD pND| D8|R @ pD pND| D8|.w @ qE q@ND} @D9}]@ qE q@ND} @D9}`@ qE q@ND} @D9}$=@ qE q@ND} @D9}$ @ qE q@ND} @D9}$/@ qE q@ND} @D9}dIT@ qE q@ND} @D9}dxy@ qE q@ND} @D9}@ qE q@ND} @D9}l@ qE q@ND} @D9}J@rFrND~D:~4' @rFrND~D:~c2@rFrND~D:~$V@rFrND~D:~$¾{@rFrND~D:~d@rFrND~D:~d y@rFrND~D:~dOV@rFrND~D:~~3 @rFrND~D:~4 !@rFrND~D:~X"@sGsNDD; }#@sGsNDD;$;$@sGsNDD;$j#%@sGsNDD;$b)&@sGsNDD;d?0'@sGsNDD;d66(@sGsNDD;&Z<)@sGsNDD;UB*@sGsNDD;H+@sGsNDD;䳑N,@tHtODD<nT-@tHtODD<$L[.@tHtODD<$A)8a/@tHtODD<dp]g0@tHtODD<dm1@tHtODD<ds2@tHtODD<y3@tHtODD<,{4@tHtODD<[X5@tHtODD<5:6@uIu@OD@D=_7@uIu@OD@D=$8@uIu@OD@D=$ͨ9@uIu@OD@D=dGͤ:@uIu@OD@D=dv;@uIu@OD@D=d<@uIu@OD@D=A<=@uIu@OD@D=a>@uIu@OD@D=2?@uIu@OD@D=a٪@@vJvODD>$A@vJvODD>$B@vJvODD>dpC@vJvODD>dN>D@vJvODD>M+cE@vJvODD>|F@vJvODD>G@vJvODD>H@vJvODD> J@vJvODD>$9}K@wKwODD?$hZ@ L@wKwODD?d7eM@wKwODD?dN@wKwODD?dO@wKwODD?$%P@wKwODD?S+Q@wKwODD?䂉2R@wKwODD?fB8S@wKwODD?Cg>T@wKwODD?$!DU@xLx PDD@ $?JV@xLx PDD@ dnPW@xLx PDD@ dVX@xLx PDD@ ̕]Y@xLx PDD@ rDcZ@xLx PDD@ *Pii[@xLx PDD@ Y-o\@xLx PDD@  u]@xLx PDD@ ${^@xLx PDD@ $_@yMy!@PD@DA!$!`@yMy!@PD@DA!dEFa@yMy!@PD@DA!dt\kb@yMy!@PD@DA!9c@yMy!@PD@DA!d@yMy!@PD@DA!٦e@yMy!@PD@DA!0f@yMy!@PD@DA!_#g@yMy!@PD@DA!$Hh@yMy!@PD@DA!$hmi@zNz"PDDB"dEj@zNz"PDDB"d#k@zNz"PDDB"dKl@zNz"PDDB"zm@zNz"PDDB"%n@zNz"PDDB"ؗJo@zNz"PDDB"uop@zNz"PDDB"$7Rq@zNz"PDDB"$f/r@zNz"PDDB"$ s@{O{#PDDC#du@{O{#PDDC#d' v@{O{#PDDC#"Lw@{O{#PDDC#Qqx@{O{#PDDC#^y@{O{#PDDC#;!z@{O{#PDDC#'{@{O{#PDDC#$.|@{O{#PDDC#$=)4}@{O{#PDDC#dlN:~@|P|$QDDD$ds@@|P|$QDDD$djF@|P|$QDDD$GL@|P|$QDDD$(%R@|P|$QDDD$WY@|P|$QDDD$+_@|P|$QDDD$䵼Pe@|P|$QDDD$$uk@|P|$QDDD$$wq@|P|$QDDD$dCTw@}Q}%@QD@DE%dr1}@}Q}%@QD@DE% @}Q}%@QD@DE%-@}Q}%@QD@DE%R@}Q}%@QD@DE%.w@}Q}%@QD@DE%]@}Q}%@QD@DE%$`@}Q}%@QD@DE%$=樐@}Q}%@QD@DE%$ @}Q}%@QD@DE%d/@~R~&QDDF&dIT@~R~&QDDF&xy@~R~&QDDF&Ǖ@~R~&QDDF&l͖@~R~&QDDF&Jӗ@~R~&QDDF&4' ژ@~R~&QDDF&$d2@~R~&QDDF&$V@~R~&QDDF&d¾{@~R~&QDDF&d@S'QDDG'd y@S'QDDG'OV@S'QDDG'~3@S'QDDG'4 @S'QDDG'X@S'QDDG'$ }@S'QDDG'$;@S'QDDG'$j#@S'QDDG'db)@S'QDDG'd?0@T(RD DH(66@T(RD DH(&Z<@T(RD DH(UB@T(RD DH(䄴H@T(RD DH($N@T(RD DH($nT@T(RD DH($L[@T(RD DH(dA)8a@T(RD DH(dp]g@T(RD DH(m@U)@RD@ DI)s@U)@RD@ DI)y@U)@RD@ DI),{@U)@RD@ DI)[X@U)@RD@ DI)$5:@U)@RD@ DI)$_@U)@RD@ DI)d@U)@RD@ DI)dͨ@U)@RD@ DI)dGͤ@U)@RD@ DI)v@V*RD DJ*d@V*RD DJ*A<@V*RD DJ*a@V*RD DJ*$3ÿ@V*RD DJ*$b٪@V*RD DJ*$@V*RD DJ*d@V*RD DJ*dp@V*RD DJ*N>@V*RD DJ*M+c@W+RD DK+|@W+RD DK+@W+RD DK+@W+RD DK+$ @W+RD DK+$9}@W+RD DK+dhZ@ @W+RD DK+d7e@W+RD DK+d@W+RD DK+@W+RD DK+$%@ X ,SD !DL,S+@ X ,SD !DL,䂉2@ X ,SD !DL,fB8@ X ,SD !DL,$Cg>@ X ,SD !DL,$!D@ X ,SD !DL,d?J@ X ,SD !DL,dnP@ X ,SD !DL,V@ X ,SD !DL,̕]@ X ,SD !DL,rDc@!Y!-@SD!@!DM-*Pii@!Y!-@SD!@!DM-Y-o@!Y!-@SD!@!DM-$ u@!Y!-@SD!@!DM-${@!Y!-@SD!@!DM-$@!Y!-@SD!@!DM-d!@!Y!-@SD!@!DM-dEF@!Y!-@SD!@!DM-t\k@!Y!-@SD!@!DM-9@!Y!-@SD!@!DM-@"Z".SD"!DN.٦@"Z".SD"!DN.0@"Z".SD"!DN.$`#@"Z".SD"!DN.$H@"Z".SD"!DN.dhm@"Z".SD"!DN.dE@"Z".SD"!DN.d#@"Z".SD"!DN.K@"Z".SD"!DN.z@"Z".SD"!DN.䩺%@#[#/SD#!DO/ؗJ@#[#/SD#!DO/$uo@#[#/SD#!DO/$7R@#[#/SD#!DO/$f/@#[#/SD#!DO/d @#[#/SD#!DO/d@#[#/SD#!DO/' @#[#/SD#!DO/"L@#[#/SD#!DO/Qq@#[#/SD#!DO/^@$\$0TD$"DP0;!@$\$0TD$"DP0$'@$\$0TD$"DP0$.@$\$0TD$"DP0d=)4@$\$0TD$"DP0dlN:@$\$0TD$"DP0ds@@$\$0TD$"DP0jF@$\$0TD$"DP0GL@$\$0TD$"DP0(%R@$\$0TD$"DP0WY@%]%1@TD%@"DQ1+_@%]%1@TD%@"DQ1$Pe@%]%1@TD%@"DQ1$uk@%]%1@TD%@"DQ1dwq@%]%1@TD%@"DQ1dCTw@%]%1@TD%@"DQ1r1} @%]%1@TD%@"DQ1 @%]%1@TD%@"DQ1- @%]%1@TD%@"DQ1R @%]%1@TD%@"DQ1.w @&^&2TD&"DR2$^@&^&2TD&"DR2$`@&^&2TD&"DR2d=@&^&2TD&"DR2d @&^&2TD&"DR2/@&^&2TD&"DR2IT@&^&2TD&"DR2xy@&^&2TD&"DR2䧏@&^&2TD&"DR2l@&^&2TD&"DR2$J@'_'3TD'"DS3$5' @'_'3TD'"DS3dd2@'_'3TD'"DS3dV@'_'3TD'"DS3d¾{@'_'3TD'"DS3@'_'3TD'"DS3 y@'_'3TD'"DS3OV@'_'3TD'"DS3~3 @'_'3TD'"DS34 !@'_'3TD'"DS3$X"@(`(4UD(#DT4$ }#@(`(4UD(#DT4d;$@(`(4UD(#DT4dj#%@(`(4UD(#DT4b)&@(`(4UD(#DT4?0'@(`(4UD(#DT466(@(`(4UD(#DT4&Z<)@(`(4UD(#DT4UB*@(`(4UD(#DT4$H+@(`(4UD(#DT4$N,@)a)5@UD)@#DU5$nT-@)a)5@UD)@#DU5dL[.@)a)5@UD)@#DU5dA)8a/@)a)5@UD)@#DU5p]g0@)a)5@UD)@#DU5m1@)a)5@UD)@#DU5s2@)a)5@UD)@#DU5y3@)a)5@UD)@#DU5,{4@)a)5@UD)@#DU5$\X5@)a)5@UD)@#DU5$5:6@*b*6UD*#DV6d_7@*b*6UD*#DV6d8@*b*6UD*#DV6dͨ9@*b*6UD*#DV6Gͤ:@*b*6UD*#DV6v;@*b*6UD*#DV6d<@*b*6UD*#DV6A<=@*b*6UD*#DV6$a>@*b*6UD*#DV6$3?@*b*6UD*#DV6$b٪@@+c+7UD+#DW7dA@+c+7UD+#DW7dB@+c+7UD+#DW7pC@+c+7UD+#DW7N>D@+c+7UD+#DW7M+cE@+c+7UD+#DW7|F@+c+7UD+#DW7G@+c+7UD+#DW7$H@+c+7UD+#DW7$ J@+c+7UD+#DW7d9}K@,d,8VD,$DX8dhZ@ L@,d,8VD,$DX8d7eM@,d,8VD,$DX8N@,d,8VD,$DX8O@,d,8VD,$DX8$%P@,d,8VD,$DX8S+Q@,d,8VD,$DX8䂉2R@,d,8VD,$DX8$fB8S@,d,8VD,$DX8$Cg>T@,d,8VD,$DX8d!DU@-e-9@VD-@$DY9d?JV@-e-9@VD-@$DY9nPW@-e-9@VD-@$DY9VX@-e-9@VD-@$DY9̕]Y@-e-9@VD-@$DY9rDcZ@-e-9@VD-@$DY9*Pii[@-e-9@VD-@$DY9$Z-o\@-e-9@VD-@$DY9$ u]@-e-9@VD-@$DY9${^@-e-9@VD-@$DY9d_@.f.:VD.$DZ:d!`@.f.:VD.$DZ:EFa@.f.:VD.$DZ:t\kb@.f.:VD.$DZ:9c@.f.:VD.$DZ:d@.f.:VD.$DZ:٦e@.f.:VD.$DZ:$1f@.f.:VD.$DZ:$`#g@.f.:VD.$DZ:dHh@.f.:VD.$DZ:dhmi@/g/;VD/$D[;dEj@/g/;VD/$D[;#k@/g/;VD/$D[;Kl@/g/;VD/$D[;zm@/g/;VD/$D[;䩺%n@/g/;VD/$D[;$ٗJo@/g/;VD/$D[;$uop@/g/;VD/$D[;$7Rq@/g/;VD/$D[;df/r@/g/;VD/$D[;d s@0h0<WD0%D\<u@0h0<WD0%D\<' v@0h0<WD0%D\<"Lw@0h0<WD0%D\<Qqx@0h0<WD0%D\<$^y@0h0<WD0%D\<$;!z@0h0<WD0%D\<$'{@0h0<WD0%D\<d.|@0h0<WD0%D\<d=)4}@0h0<WD0%D\<lN:~@1i1=@WD1@%D]=s@@1i1=@WD1@%D]=jF@1i1=@WD1@%D]=GL@1i1=@WD1@%D]=(%R@1i1=@WD1@%D]=$XY@1i1=@WD1@%D]=$+_@1i1=@WD1@%D]=dPe@1i1=@WD1@%D]=duk@1i1=@WD1@%D]=dwq@1i1=@WD1@%D]=CTw@2j2>WD¢2%D^>r1}@2j2>WD¢2%D^> @2j2>WD¢2%D^>-@2j2>WD¢2%D^>$R@2j2>WD¢2%D^>$/w@2j2>WD¢2%D^>$^@2j2>WD¢2%D^>d`@2j2>WD¢2%D^>d=樐@2j2>WD¢2%D^> @2j2>WD¢2%D^>/@3k3?WDã3%D_?IT@3k3?WDã3%D_?xy@3k3?WDã3%D_?䧏Ǖ@3k3?WDã3%D_?$l͖@3k3?WDã3%D_?$Jӗ@3k3?WDã3%D_?d5' ژ@3k3?WDã3%D_?dd2@3k3?WDã3%D_?dV@3k3?WDã3%D_?¾{@3k3?WDã3%D_?@4l4@XDĤ4&D`@ y@4l4@XDĤ4&D`@OV@4l4@XDĤ4&D`@~3@4l4@XDĤ4&D`@$4 @4l4@XDĤ4&D`@$X@4l4@XDĤ4&D`@d }@4l4@XDĤ4&D`@d;@4l4@XDĤ4&D`@j#@4l4@XDĤ4&D`@b)@4l4@XDĤ4&D`@?0@5m5A@XDť 5@&DaA66@5m5A@XDť 5@&DaA&Z<@5m5A@XDť 5@&DaA$VB@5m5A@XDť 5@&DaA$H@5m5A@XDť 5@&DaA$N@5m5A@XDť 5@&DaAdnT@5m5A@XDť 5@&DaAdL[@5m5A@XDť 5@&DaAA)8a@5m5A@XDť 5@&DaAp]g@5m5A@XDť 5@&DaAm@6n6BXDƦ 6&DbBs@6n6BXDƦ 6&DbBy@6n6BXDƦ 6&DbB$-{@6n6BXDƦ 6&DbB$\X@6n6BXDƦ 6&DbBd5:@6n6BXDƦ 6&DbBd_@6n6BXDƦ 6&DbBd@6n6BXDƦ 6&DbBͨ@6n6BXDƦ 6&DbBGͤ@6n6BXDƦ 6&DbBv@7o7CXDǧ 7&DcCd@7o7CXDǧ 7&DcC$A<@7o7CXDǧ 7&DcC$a@7o7CXDǧ 7&DcC$3ÿ@7o7CXDǧ 7&DcCdb٪@7o7CXDǧ 7&DcCd@7o7CXDǧ 7&DcC@7o7CXDǧ 7&DcCp@7o7CXDǧ 7&DcCN>@7o7CXDǧ 7&DcCM+c@8p8DYDȨ 8'DdD|@8p8DYDȨ 8'DdD$@8p8DYDȨ 8'DdD$@8p8DYDȨ 8'DdDd @8p8DYDȨ 8'DdDd9}@8p8DYDȨ 8'DdDdhZ@ @8p8DYDȨ 8'DdD7e@8p8DYDȨ 8'DdD@8p8DYDȨ 8'DdD@8p8DYDȨ 8'DdD$%@9q9E@YDɩ 9@'DeES+@9q9E@YDɩ 9@'DeE$2@9q9E@YDɩ 9@'DeE$fB8@9q9E@YDɩ 9@'DeEdCg>@9q9E@YDɩ 9@'DeEd!D@9q9E@YDɩ 9@'DeE?J@9q9E@YDɩ 9@'DeEnP@9q9E@YDɩ 9@'DeEV@9q9E@YDɩ 9##TXIDate: 22.11.2018 Time: 15:26:39 Test Comment@@@@@@@##TX($EVENT_COMMENTS##EV`K& .>##DT@'DeE̕]@9q9E@YDɩ 9@'DeErDc@:r:FYDʪ:'DfF$+Pii@:r:FYDʪ:'DfF$Z-o@:r:FYDʪ:'DfFd u@:r:FYDʪ:'DfFd{@:r:FYDʪ:'DfF@:r:FYDʪ:'DfF!@:r:FYDʪ:'DfFEF@:r:FYDʪ:'DfFt\k@:r:FYDʪ:'DfF9@:r:FYDʪ:'DfF$@;s;GYD˫;'DgG$٦@;s;GYD˫;'DgGd1@;s;GYD˫;'DgGd`#@;s;GYD˫;'DgGdH@;s;GYD˫;'DgGhm@;s;GYD˫;'DgGE@;s;GYD˫;'DgG#@;s;GYD˫;'DgGK@;s;GYD˫;'DgGz@;s;GYD˫;'DgG$%@v>JZDή>(DjJd+_@>v>JZDή>(DjJdPe@>v>JZDή>(DjJduk@>v>JZDή>(DjJwq@>v>JZDή>(DjJCTw@>v>JZDή>(DjJr1} @>v>JZDή>(DjJ @>v>JZDή>(DjJ$- @>v>JZDή>(DjJ$R @>v>JZDή>(DjJ$/w @?w?KZDϯ?(DkKd^@?w?KZDϯ?(DkKd`@?w?KZDϯ?(DkK=@?w?KZDϯ?(DkK @?w?KZDϯ?(DkK/@?w?KZDϯ?(DkKIT@?w?KZDϯ?(DkKxy@?w?KZDϯ?(DkK$@?w?KZDϯ?(DkK$l@?w?KZDϯ?(DkKdJ@@x@L[Dа@)DlLd5' @@x@L[Dа@)DlLdd2@@x@L[Dа@)DlLV@@x@L[Dа@)DlL¾{@@x@L[Dа@)DlL@@x@L[Dа@)DlL y@@x@L[Dа@)DlLOV@@x@L[Dа@)DlL$3 @@x@L[Dа@)DlL$4 !@@x@L[Dа@)DlLdX"@ AyA M@[DѱA@)D mMd }#@ AyA M@[DѱA@)D mM;$@ AyA M@[DѱA@)D mMj#%@ AyA M@[DѱA@)D mMb)&@ AyA M@[DѱA@)D mM?0'@ AyA M@[DѱA@)D mM66(@ AyA M@[DѱA@)D mM$'Z<)@ AyA M@[DѱA@)D mM$VB*@ AyA M@[DѱA@)D mM$H+@ AyA M@[DѱA@)D mMdN,@ BzB N[DҲB)D nNdnT-@ BzB N[DҲB)D nNL[.@ BzB N[DҲB)D nNA)8a/@ BzB N[DҲB)D nNp]g0@ BzB N[DҲB)D nNm1@ BzB N[DҲB)D nNs2@ BzB N[DҲB)D nN$y3@ BzB N[DҲB)D nN$-{4@ BzB N[DҲB)D nNd\X5@ BzB N[DҲB)D nNd5:6@ C{C O[DӳC)D oOd_7@ C{C O[DӳC)D oO8@ C{C O[DӳC)D oOͨ9@ C{C O[DӳC)D oOGͤ:@ C{C O[DӳC)D oOv;@ C{C O[DӳC)D oO$d<@ C{C O[DӳC)D oO$A<=@ C{C O[DӳC)D oO$a>@ C{C O[DӳC)D oOd3?@ C{C O[DӳC)D oOdb٪@@ D|D P\DԴD*D pPA@ D|D P\DԴD*D pPB@ D|D P\DԴD*D pPpC@ D|D P\DԴD*D pPN>D@ D|D P\DԴD*D pP$N+cE@ D|D P\DԴD*D pP$}F@ D|D P\DԴD*D pP$G@ D|D P\DԴD*D pPdH@ D|D P\DԴD*D pPd J@ D|D P\DԴD*D pP9}K@ E}E Q@\DյE@*D qQhZ@ L@ E}E Q@\DյE@*D qQ7eM@ E}E Q@\DյE@*D qQN@ E}E Q@\DյE@*D qQO@ E}E Q@\DյE@*D qQ$%%P@ E}E Q@\DյE@*D qQ$T+Q@ E}E Q@\DյE@*D qQd2R@ E}E Q@\DյE@*D qQdfB8S@ E}E Q@\DյE@*D qQdCg>T@ E}E Q@\DյE@*D qQ!DU@F~FR\DֶF*DrR?JV@F~FR\DֶF*DrRnPW@F~FR\DֶF*DrR䝸VX@F~FR\DֶF*DrR$͕]Y@F~FR\DֶF*DrR$rDcZ@F~FR\DֶF*DrR$+Pii[@F~FR\DֶF*DrRdZ-o\@F~FR\DֶF*DrRd u]@F~FR\DֶF*DrR{^@F~FR\DֶF*DrR_@GGS\D׷G*DsS!`@GGS\D׷G*DsSEFa@GGS\D׷G*DsSt\kb@GGS\D׷G*DsS$9c@GGS\D׷G*DsS$d@GGS\D׷G*DsSd٦e@GGS\D׷G*DsSd1f@GGS\D׷G*DsSd`#g@GGS\D׷G*DsSHh@GGS\D׷G*DsShmi@HHT]DظH+DtTEj@HHT]DظH+DtT#k@HHT]DظH+DtTKl@HHT]DظH+DtT${m@HHT]DظH+DtT$%n@HHT]DظH+DtTdٗJo@HHT]DظH+DtTduop@HHT]DظH+DtT7Rq@HHT]DظH+DtTf/r@HHT]DظH+DtT s@IIU@]DٹI@+DuUu@IIU@]DٹI@+DuU' v@IIU@]DٹI@+DuU$#Lw@IIU@]DٹI@+DuU$Rqx@IIU@]DٹI@+DuU$^y@IIU@]DٹI@+DuUd;!z@IIU@]DٹI@+DuUd'{@IIU@]DٹI@+DuU.|@IIU@]DٹI@+DuU=)4}@IIU@]DٹI@+DuUlN:~@JJV]DںJ+DvV䛍s@@JJV]DںJ+DvVjF@JJV]DںJ+DvV$GL@JJV]DںJ+DvV$)%R@JJV]DںJ+DvVdXY@JJV]DںJ+DvVd+_@JJV]DںJ+DvVdPe@JJV]DںJ+DvVuk@JJV]DںJ+DvVwq@JJV]DںJ+DvVCTw@KKW]DۻK+DwWr1}@KKW]DۻK+DwW$ @KKW]DۻK+DwW$-@KKW]DۻK+DwW$R@KKW]DۻK+DwWd/w@KKW]DۻK+DwWd^@KKW]DۻK+DwW`@KKW]DۻK+DwW=樐@KKW]DۻK+DwW @KKW]DۻK+DwW/@LLX^Dܼ L,DxXIT@LLX^Dܼ L,DxX$yy@LLX^Dܼ L,DxX$Ǖ@LLX^Dܼ L,DxXdl͖@LLX^Dܼ L,DxXdJӗ@LLX^Dܼ L,DxXd5' ژ@LLX^Dܼ L,DxXd2@LLX^Dܼ L,DxXV@LLX^Dܼ L,DxX¾{@LLX^Dܼ L,DxX@MMY@^Dݽ!M@,DyY y@MMY@^Dݽ!M@,DyY$PV@MMY@^Dݽ!M@,DyY$3@MMY@^Dݽ!M@,DyYd4 @MMY@^Dݽ!M@,DyYdX@MMY@^Dݽ!M@,DyY }@MMY@^Dݽ!M@,DyY;@MMY@^Dݽ!M@,DyYj#@MMY@^Dݽ!M@,DyYb)@MMY@^Dݽ!M@,DyY?0@NNZ^D޾"N,DzZ$66@NNZ^D޾"N,DzZ$'Z<@NNZ^D޾"N,DzZdVB@NNZ^D޾"N,DzZdH@NNZ^D޾"N,DzZN@NNZ^D޾"N,DzZnT@NNZ^D޾"N,DzZL[@NNZ^D޾"N,DzZA)8a@NNZ^D޾"N,DzZp]g@NNZ^D޾"N,DzZ$m@OO[^D߿#O,D{[$s@OO[^D߿#O,D{[dy@OO[^D߿#O,D{[d-{@OO[^D߿#O,D{[d\X@OO[^D߿#O,D{[5:@OO[^D߿#O,D{[_@OO[^D߿#O,D{[@OO[^D߿#O,D{[ͨ@OO[^D߿#O,D{[Gͤ@OO[^D߿#O,D{[$w@PP\_D$P-D|\$d@PP\_D$P-D|\dA<@PP\_D$P-D|\da@PP\_D$P-D|\3ÿ@PP\_D$P-D|\b٪@PP\_D$P-D|\@PP\_D$P-D|\@PP\_D$P-D|\p@PP\_D$P-D|\$N>@PP\_D$P-D|\$N+c@QQ]@_D%Q@-D}]$}@QQ]@_D%Q@-D}]d@QQ]@_D%Q@-D}]d@QQ]@_D%Q@-D}] @QQ]@_D%Q@-D}]9}@QQ]@_D%Q@-D}]hZ@ @QQ]@_D%Q@-D}]7e@QQ]@_D%Q@-D}]@QQ]@_D%Q@-D}]$@QQ]@_D%Q@-D}]$%%@RR^_D&R-D~^dT+@RR^_D&R-D~^d2@RR^_D&R-D~^dfB8@RR^_D&R-D~^Cg>@RR^_D&R-D~^!D@RR^_D&R-D~^?J@RR^_D&R-D~^nP@RR^_D&R-D~^$V@RR^_D&R-D~^$͕]@RR^_D&R-D~^$rDc@SS__D'S-D_d+Pii@SS__D'S-D_dZ-o@SS__D'S-D_ u@SS__D'S-D_{@SS__D'S-D_@SS__D'S-D_!@SS__D'S-D_EF@SS__D'S-D_$u\k@SS__D'S-D_$9@SS__D'S-D_d@TT``D(T.D`d٦@TT``D(T.D`d1@TT``D(T.D``#@TT``D(T.D`H@TT``D(T.D`hm@TT``D(T.D`E@TT``D(T.D`#@TT``D(T.D`$L@TT``D(T.D`${@TT``D(T.D`d%@UUa@`D)U@.DadٗJ@UUa@`D)U@.Dauo@UUa@`D)U@.Da7R@UUa@`D)U@.Daf/@UUa@`D)U@.Da @UUa@`D)U@.Da@UUa@`D)U@.Da$' @UUa@`D)U@.Da$#L@UUa@`D)U@.Da$Rq@UUa@`D)U@.Dad^@VVb`D*V.Dbd;!@VVb`D*V.Db'@VVb`D*V.Db.@VVb`D*V.Db=)4@VVb`D*V.DblN:@VVb`D*V.Db䛍s@@VVb`D*V.Db$jF@VVb`D*V.Db$GL@VVb`D*V.Dbd)%R@VVb`D*V.DbdXY@WWc`D+W.Dcd+_@WWc`D+W.DcPe@WWc`D+W.Dcuk@WWc`D+W.Dcwq@WWc`D+W.DcCTw@WWc`D+W.Dc$s1} @WWc`D+W.Dc$ @WWc`D+W.Dc$- @WWc`D+W.DcdR @WWc`D+W.Dcd/w @ XX daD,X/D d^@ XX daD,X/D d`@ XX daD,X/D d=@ XX daD,X/D d @ XX daD,X/D d$/@ XX daD,X/D d$JT@ XX daD,X/D d$yy@ XX daD,X/D dd@ XX daD,X/D ddl@ XX daD,X/D dJ@!YY!e@aD-Y@/D!e5' @!YY!e@aD-Y@/D!ed2@!YY!e@aD-Y@/D!eV@!YY!e@aD-Y@/D!e¾{@!YY!e@aD-Y@/D!e$@!YY!e@aD-Y@/D!e$!y@!YY!e@aD-Y@/D!edPV@!YY!e@aD-Y@/D!ed3 @!YY!e@aD-Y@/D!ed4 !@!YY!e@aD-Y@/D!eX"@"ZZ"faD.Z/D"f }#@"ZZ"faD.Z/D"f;$@"ZZ"faD.Z/D"fj#%@"ZZ"faD.Z/D"f$b)&@"ZZ"faD.Z/D"f$?0'@"ZZ"faD.Z/D"f$66(@"ZZ"faD.Z/D"fd'Z<)@"ZZ"faD.Z/D"fdVB*@"ZZ"faD.Z/D"fH+@"ZZ"faD.Z/D"fN,@#[[#gaD/[/D#gnT-@#[[#gaD/[/D#gL[.@#[[#gaD/[/D#gA)8a/@#[[#gaD/[/D#g$q]g0@#[[#gaD/[/D#g$m1@#[[#gaD/[/D#gds2@#[[#gaD/[/D#gdy3@#[[#gaD/[/D#gd-{4@#[[#gaD/[/D#g\X5@#[[#gaD/[/D#g5:6@$\\$hbD0\0D$h_7@$\\$hbD0\0D$h8@$\\$hbD0\0D$hͨ9@$\\$hbD0\0D$h$Hͤ:@$\\$hbD0\0D$h$w;@$\\$hbD0\0D$hdd<@$\\$hbD0\0D$hdA<=@$\\$hbD0\0D$ha>@$\\$hbD0\0D$h3?@$\\$hbD0\0D$hb٪@@%]]%i@bD1]@0D%i䑶A@%]]%i@bD1]@0D%iB@%]]%i@bD1]@0D%i$pC@%]]%i@bD1]@0D%i$N>D@%]]%i@bD1]@0D%i$N+cE@%]]%i@bD1]@0D%id}F@%]]%i@bD1]@0D%idG@%]]%i@bD1]@0D%iH@%]]%i@bD1]@0D%i J@%]]%i@bD1]@0D%i9}K@&^–^&jbD2^0D&jhZ@ L@&^–^&jbD2^0D&j7eM@&^–^&jbD2^0D&j$N@&^–^&jbD2^0D&j$O@&^–^&jbD2^0D&jd%%P@&^–^&jbD2^0D&jdT+Q@&^–^&jbD2^0D&jd2R@&^–^&jbD2^0D&jfB8S@&^–^&jbD2^0D&jCg>T@&^–^&jbD2^0D&j!DU@'_×_'kbD3_0D'k?JV@'_×_'kbD3_0D'k$oPW@'_×_'kbD3_0D'k$VX@'_×_'kbD3_0D'k$͕]Y@'_×_'kbD3_0D'kdrDcZ@'_×_'kbD3_0D'kd+Pii[@'_×_'kbD3_0D'kZ-o\@'_×_'kbD3_0D'k u]@'_×_'kbD3_0D'k{^@'_×_'kbD3_0D'k_@(`Ę`(lcD4`1D(l!`@(`Ę`(lcD4`1D(l$FFa@(`Ę`(lcD4`1D(l$u\kb@(`Ę`(lcD4`1D(ld9c@(`Ę`(lcD4`1D(ldd@(`Ę`(lcD4`1D(ld٦e@(`Ę`(lcD4`1D(l1f@(`Ę`(lcD4`1D(l`#g@(`Ę`(lcD4`1D(l䏋Hh@(`Ę`(lcD4`1D(lhmi@)ařa)m@cD 5a@1D) mEj@)ařa)m@cD 5a@1D) m$#k@)ařa)m@cD 5a@1D) m$Ll@)ařa)m@cD 5a@1D) md{m@)ařa)m@cD 5a@1D) md%n@)ařa)m@cD 5a@1D) mٗJo@)ařa)m@cD 5a@1D) muop@)ařa)m@cD 5a@1D) m7Rq@)ařa)m@cD 5a@1D) mf/r@)ařa)m@cD 5a@1D) m s@*bƚb*ncD 6b1D* n$u@*bƚb*ncD 6b1D* n$' v@*bƚb*ncD 6b1D* nd#Lw@*bƚb*ncD 6b1D* ndRqx@*bƚb*ncD 6b1D* n^y@*bƚb*ncD 6b1D* n;!z@*bƚb*ncD 6b1D* n'{@*bƚb*ncD 6b1D* n.|@*bƚb*ncD 6b1D* n=)4}@*bƚb*ncD 6b1D* n$mN:~@+cǛc+ocD 7c1D+ o$s@@+cǛc+ocD 7c1D+ odjF@+cǛc+ocD 7c1D+ odGL@+cǛc+ocD 7c1D+ od)%R@+cǛc+ocD 7c1D+ oXY@+cǛc+ocD 7c1D+ o+_@+cǛc+ocD 7c1D+ o䶼Pe@+cǛc+ocD 7c1D+ ouk@+cǛc+ocD 7c1D+ owq@+cǛc+ocD 7c1D+ o$DTw@,dȜd,pdD 8d2D, p$s1}@,dȜd,pdD 8d2D, pd @,dȜd,pdD 8d2D, pd-@,dȜd,pdD 8d2D, pR@,dȜd,pdD 8d2D, p/w@,dȜd,pdD 8d2D, p^@,dȜd,pdD 8d2D, p`@,dȜd,pdD 8d2D, p=樐@,dȜd,pdD 8d2D, p$ @,dȜd,pdD 8d2D, p$/@-eɝe-q@dD 9e@2D- q$JT@-eɝe-q@dD 9e@2D- qdyy@-eɝe-q@dD 9e@2D- qdǕ@-eɝe-q@dD 9e@2D- ql͖@-eɝe-q@dD 9e@2D- qJӗ@-eɝe-q@dD 9e@2D- q5' ژ@-eɝe-q@dD 9e@2D- qd2@-eɝe-q@dD 9e@2D- qV@-eɝe-q@dD 9e@2D- q$þ{@-eɝe-q@dD 9e@2D- q$@.fʞf.rdD:f2D.rd!y@.fʞf.rdD:f2D.rdPV@.fʞf.rdD:f2D.rd3@.fʞf.rdD:f2D.r4 @.fʞf.rdD:f2D.rX@.fʞf.rdD:f2D.r }@.fʞf.rdD:f2D.r;@.fʞf.rdD:f2D.r$k#@.fʞf.rdD:f2D.r$b)@.fʞf.rdD:f2D.r$?0@/g˟g/sdD;g2D/sd66@/g˟g/sdD;g2D/sd'Z<@/g˟g/sdD;g2D/sVB@/g˟g/sdD;g2D/sH@/g˟g/sdD;g2D/sN@/g˟g/sdD;g2D/snT@/g˟g/sdD;g2D/sL[@/g˟g/sdD;g2D/s$B)8a@/g˟g/sdD;g2D/s$q]g@/g˟g/sdD;g2D/sdm@0h̠h0teD<h3D0tds@0h̠h0teD<h3D0tdy@0h̠h0teD<h3D0t-{@0h̠h0teD<h3D0t\X@0h̠h0teD<h3D0t5:@0h̠h0teD<h3D0t_@0h̠h0teD<h3D0t@0h̠h0teD<h3D0t$ͨ@0h̠h0teD<h3D0t$Hͤ@0h̠h0teD<h3D0tdw@1i͡i1u@eD=i@3D1udd@1i͡i1u@eD=i@3D1uA<@1i͡i1u@eD=i@3D1ua@1i͡i1u@eD=i@3D1u3ÿ@1i͡i1u@eD=i@3D1ub٪@1i͡i1u@eD=i@3D1u䑶@1i͡i1u@eD=i@3D1u$@1i͡i1u@eD=i@3D1u$p@1i͡i1u@eD=i@3D1u$N>@1i͡i1u@eD=i@3D1udN+c@2j΢j2veD>j3D2vd}@2j΢j2veD>j3D2v@2j΢j2veD>j3D2v@2j΢j2veD>j3D2v @2j΢j2veD>j3D2v9}@2j΢j2veD>j3D2vhZ@ @2j΢j2veD>j3D2v$7e@2j΢j2veD>j3D2v$@2j΢j2veD>j3D2vd@2j΢j2veD>j3D2vd%%@3kϣk3weD?k3D3wdT+@3kϣk3weD?k3D3w2@3kϣk3weD?k3D3wfB8@3kϣk3weD?k3D3wCg>@3kϣk3weD?k3D3w!D@3kϣk3weD?k3D3w$@J@3kϣk3weD?k3D3w$oP@3kϣk3weD?k3D3w$V@3kϣk3weD?k3D3wd͕]@3kϣk3weD?k3D3wdrDc@4lФl4xfD@l4D4xd+Pii@4lФl4xfD@l4D4xZ-o@4lФl4xfD@l4D4x u@4lФl4xfD@l4D4x{@4lФl4xfD@l4D4x@4lФl4xfD@l4D4x!@4lФl4xfD@l4D4x$FF@4lФl4xfD@l4D4x$u\k@4lФl4xfD@l4D4xd9@4lФl4xfD@l4D4xd@5mѥ m5y@fDA m@4D5y٦@5mѥ m5y@fDA m@4D5y1@5mѥ m5y@fDA m@4D5y`#@5mѥ m5y@fDA m@4D5y䏋H@5mѥ m5y@fDA m@4D5yhm@5mѥ m5y@fDA m@4D5y$E@5mѥ m5y@fDA m@4D5y$#@5mѥ m5y@fDA m@4D5y$L@5mѥ m5y@fDA m@4D5yd{@5mѥ m5y@fDA m@4D5yd%@6nҦ n6zfDB n4D6zٗJ@6nҦ n6zfDB n4D6zuo@6nҦ n6zfDB n4D6z7R@6nҦ n6zfDB n4D6zf/@6nҦ n6zfDB n4D6z @6nҦ n6zfDB n4D6z$@6nҦ n6zfDB n4D6z$' @6nҦ n6zfDB n4D6zd#L@6nҦ n6zfDB n4D6zdRq@6nҦ n6zfDB n4D6zd^@7oӧ o7{fDC o4D7{;!@7oӧ o7{fDC o4D7{'@7oӧ o7{fDC o4D7{.@7oӧ o7{fDC o4D7{=)4@7oӧ o7{fDC o4D7{$mN:@7oӧ o7{fDC o4D7{$s@@7oӧ o7{fDC o4D7{$jF@7oӧ o7{fDC o4D7{dGL@7oӧ o7{fDC o4D7{d)%R@7oӧ o7{fDC o4D7{XY@8pԨ p8|gDD p5D8|+_@8pԨ p8|gDD p5D8|Pe@8pԨ p8|gDD p5D8|uk@8pԨ p8|gDD p5D8|wq@8pԨ p8|gDD p5D8|$DTw@8pԨ p8|gDD p5D8|$s1} @8pԨ p8|gDD p5D8|d @8pԨ p8|gDD p5D8|d- @8pԨ p8|gDD p5D8|dR @8pԨ p8|gDD p5D8|/w @9qթ q9}@gDE q@5D9}^@9qթ q9}@gDE q@5D9}`@9qթ q9}@gDE q@5D9}=@9qթ q9}@gDE q@5D9} @9qթ q9}@gDE q@5D9}$/@9qթ q9}@gDE q@5D9}$JT@9qթ q9}@gDE q@5D9}dyy@9qթ q9}@gDE q@5D9}d@9qթ q9}@gDE q@5D9}l@9qթ q9}@gDE q@5D9}J@:r֪r:~gDFr5D:~5' @:r֪r:~gDFr5D:~d2@:r֪r:~gDFr5D:~V@:r֪r:~gDFr5D:~$þ{@:r֪r:~gDFr5D:~$@:r֪r:~gDFr5D:~$!y@:r֪r:~gDFr5D:~dPV@:r֪r:~gDFr5D:~d3 @:r֪r:~gDFr5D:~4 !@:r֪r:~gDFr5D:~X"@;s׫s;gDGs5D; }#@;s׫s;gDGs5D;;$@;s׫s;gDGs5D;j#%@;s׫s;gDGs5D;$b)&@;s׫s;gDGs5D;$?0'@;s׫s;gDGs5D;d66(@;s׫s;gDGs5D;d'Z<)@;s׫s;gDGs5D;dVB*@;s׫s;gDGs5D;H+@;s׫s;gDGs5D;N,@@=u٭u=@hDIu@6D=3?@=u٭u=@hDIu@6D=b٪@@>vڮv>hDJv6D>䑶A@>vڮv>hDJv6D>$B@>vڮv>hDJv6D>$pC@>vڮv>hDJv6D>dN>D@>vڮv>hDJv6D>dN+cE@>vڮv>hDJv6D>d}F@>vڮv>hDJv6D>G@>vڮv>hDJv6D>H@>vڮv>hDJv6D> J@>vڮv>hDJv6D>9}K@?wۯw?hDKw6D?$iZ@ L@?wۯw?hDKw6D?$7eM@?wۯw?hDKw6D?$N@?wۯw?hDKw6D?dO@?wۯw?hDKw6D?d%%P@?wۯw?hDKw6D?T+Q@?wۯw?hDKw6D?2R@?wۯw?hDKw6D?fB8S@?wۯw?hDKw6D?Cg>T@?wۯw?hDKw6D?!DU@@xܰx@iD Lx7D@ $@JV@@xܰx@iD Lx7D@ $oPW@@xܰx@iD Lx7D@ dVX@@xܰx@iD Lx7D@ d͕]Y@@xܰx@iD Lx7D@ drDcZ@@xܰx@iD Lx7D@ +Pii[@@xܰx@iD Lx7D@ Z-o\@@xܰx@iD Lx7D@  u]@@xܰx@iD Lx7D@ {^@@xܰx@iD Lx7D@ _@AyݱyA@iD!My@7DA!$!`@AyݱyA@iD!My@7DA!$FFa@AyݱyA@iD!My@7DA!du\kb@AyݱyA@iD!My@7DA!d9c@AyݱyA@iD!My@7DA!d@AyݱyA@iD!My@7DA!٦e@AyݱyA@iD!My@7DA!1f@AyݱyA@iD!My@7DA!`#g@AyݱyA@iD!My@7DA!䏋Hh@AyݱyA@iD!My@7DA!$hmi@Bz޲zBiD"Nz7DB"$Ej@Bz޲zBiD"Nz7DB"$#k@Bz޲zBiD"Nz7DB"dLl@Bz޲zBiD"Nz7DB"d{m@Bz޲zBiD"Nz7DB"%n@Bz޲zBiD"Nz7DB"ٗJo@Bz޲zBiD"Nz7DB"uop@Bz޲zBiD"Nz7DB"7Rq@Bz޲zBiD"Nz7DB"f/r@Bz޲zBiD"Nz7DB"$ s@C{߳{CiD#O{7DC#$u@C{߳{CiD#O{7DC#d' v@C{߳{CiD#O{7DC#d#Lw@C{߳{CiD#O{7DC#dRqx@C{߳{CiD#O{7DC#^y@C{߳{CiD#O{7DC#;!z@C{߳{CiD#O{7DC#'{@C{߳{CiD#O{7DC#.|@C{߳{CiD#O{7DC#$>)4}@C{߳{CiD#O{7DC#$mN:~@D||DjD$P|8DD$$s@@D||DjD$P|8DD$djF@D||DjD$P|8DD$dGL@D||DjD$P|8DD$)%R@D||DjD$P|8DD$XY@D||DjD$P|8DD$+_@D||DjD$P|8DD$䶼Pe@D||DjD$P|8DD$uk@D||DjD$P|8DD$$wq@D||DjD$P|8DD$$DTw@E}}E@jD%Q}@8DE%ds1}@E}}E@jD%Q}@8DE%d @E}}E@jD%Q}@8DE%d-@E}}E@jD%Q}@8DE%R@E}}E@jD%Q}@8DE%/w@E}}E@jD%Q}@8DE%^@E}}E@jD%Q}@8DE%`@E}}E@jD%Q}@8DE%=樐@E}}E@jD%Q}@8DE%$ @E}}E@jD%Q}@8DE%$/@F~~FjD&R~8DF&dJT@F~~FjD&R~8DF&dyy@F~~FjD&R~8DF&Ǖ@F~~FjD&R~8DF&l͖@F~~FjD&R~8DF&Jӗ@F~~FjD&R~8DF&5' ژ@F~~FjD&R~8DF&d2@F~~FjD&R~8DF&$V@F~~FjD&R~8DF&$þ{@F~~FjD&R~8DF&$@GGjD'S8DG'd!y@GGjD'S8DG'dPV@GGjD'S8DG'3@GGjD'S8DG'4 @GGjD'S8DG'X@GGjD'S8DG' }@GGjD'S8DG';@GGjD'S8DG'$k#@GGjD'S8DG'$b)@GGjD'S8DG'd?0@HHkD(T9DH(d66@HHkD(T9DH('Z<@HHkD(T9DH(VB@HHkD(T9DH(䅴H@HHkD(T9DH(䴑N@HHkD(T9DH(nT@HHkD(T9DH($L[@HHkD(T9DH($B)8a@HHkD(T9DH(dq]g@HHkD(T9DH(dm@II@kD)U@9DI)s@II@kD)U@9DI)y@II@kD)U@9DI)-{@II@kD)U@9DI)\X@II@kD)U@9DI)5:@II@kD)U@9DI)$_@II@kD)U@9DI)$@II@kD)U@9DI)$ͨ@II@kD)U@9DI)dHͤ@II@kD)U@9DI)dw@JJkD*V9DJ*d@JJkD*V9DJ*A<@JJkD*V9DJ*a@JJkD*V9DJ*3ÿ@JJkD*V9DJ*b٪@JJkD*V9DJ*$@JJkD*V9DJ*$@JJkD*V9DJ*dp@JJkD*V9DJ*dN>@JJkD*V9DJ*dN+c@KKkD+W9DK+}@KKkD+W9DK+@KKkD+W9DK+@KKkD+W9DK+ @KKkD+W9DK+$:}@KKkD+W9DK+$iZ@ @KKkD+W9DK+$7e@KKkD+W9DK+d@KKkD+W9DK+d@KKkD+W9DK+%%@L LlD,X :DL,T+@L LlD,X :DL,2@L LlD,X :DL,fB8@L LlD,X :DL,Cg>@L LlD,X :DL,$!D@L LlD,X :DL,$@J@L LlD,X :DL,doP@L LlD,X :DL,dV@L LlD,X :DL,d͕]@L LlD,X :DL,rDc@M!M@lD-Y!@:DM-+Pii@M!M@lD-Y!@:DM-Z-o@M!M@lD-Y!@:DM- u@M!M@lD-Y!@:DM-{@M!M@lD-Y!@:DM-$@M!M@lD-Y!@:DM-$!@M!M@lD-Y!@:DM-dFF@M!M@lD-Y!@:DM-du\k@M!M@lD-Y!@:DM-9@M!M@lD-Y!@:DM-@N"NlD.Z":DN.٦@N"NlD.Z":DN.1@N"NlD.Z":DN.`#@N"NlD.Z":DN.$H@N"NlD.Z":DN.$hm@N"NlD.Z":DN.$E@N"NlD.Z":DN.d#@N"NlD.Z":DN.dL@N"NlD.Z":DN.{@N"NlD.Z":DN.%@O#OlD/[#:DO/ٗJ@O#OlD/[#:DO/uo@O#OlD/[#:DO/7R@O#OlD/[#:DO/$g/@O#OlD/[#:DO/$ @O#OlD/[#:DO/d@O#OlD/[#:DO/d' @O#OlD/[#:DO/d#L@O#OlD/[#:DO/Rq@O#OlD/[#:DO/^@P$PmD0\$;DP0;!@P$PmD0\$;DP0'@P$PmD0\$;DP0$.@P$PmD0\$;DP0$>)4@P$PmD0\$;DP0$mN:@P$PmD0\$;DP0ds@@P$PmD0\$;DP0djF@P$PmD0\$;DP0GL@P$PmD0\$;DP0)%R@P$PmD0\$;DP0XY@Q%Q@mD1]%@;DQ1+_@Q%Q@mD1]%@;DQ1䶼Pe@Q%Q@mD1]%@;DQ1$uk@Q%Q@mD1]%@;DQ1$wq@Q%Q@mD1]%@;DQ1dDTw@Q%Q@mD1]%@;DQ1ds1} @Q%Q@mD1]%@;DQ1d @Q%Q@mD1]%@;DQ1- @Q%Q@mD1]%@;DQ1R @Q%Q@mD1]%@;DQ1/w @R&RmD2^&;DR2^@R&RmD2^&;DR2$`@R&RmD2^&;DR2$=@R&RmD2^&;DR2d @R&RmD2^&;DR2d/@R&RmD2^&;DR2dJT@R&RmD2^&;DR2yy@R&RmD2^&;DR2@R&RmD2^&;DR2l@R&RmD2^&;DR2J@S'SmD3_';DS3$6' @S'SmD3_';DS3$e2@S'SmD3_';DS3$V@S'SmD3_';DS3dþ{@S'SmD3_';DS3d@S'SmD3_';DS3!y@S'SmD3_';DS3PV@S'SmD3_';DS33 @S'SmD3_';DS34 !@S'SmD3_';DS3X"@T(TnD4`(@V*VnD6b*D@W+WnD7c+T@X,XoD8d,=DX8$!DU@Y-Y@oD9e-@=DY9d@JV@Y-Y@oD9e-@=DY9doPW@Y-Y@oD9e-@=DY9dVX@Y-Y@oD9e-@=DY9͕]Y@Y-Y@oD9e-@=DY9rDcZ@Y-Y@oD9e-@=DY9+Pii[@Y-Y@oD9e-@=DY9Z-o\@Y-Y@oD9e-@=DY9 u]@Y-Y@oD9e-@=DY9${^@Y-Y@oD9e-@=DY9$_@Z.ZoD:f.=DZ:d!`@Z.ZoD:f.=DZ:dFFa@Z.ZoD:f.=DZ:u\kb@Z.ZoD:f.=DZ:9c@Z.ZoD:f.=DZ:d@Z.ZoD:f.=DZ:٦e@Z.ZoD:f.=DZ:1f@Z.ZoD:f.=DZ:$a#g@Z.ZoD:f.=DZ:$Hh@Z.ZoD:f.=DZ:$hmi@[/[oD;g/=D[;dEj@[/[oD;g/=D[;d#k@[/[oD;g/=D[;Ll@[/[oD;g/=D[;{m@[/[oD;g/=D[;䪺%n@[/[oD;g/=D[;ٗJo@[/[oD;g/=D[;uop@[/[oD;g/=D[;$8Rq@[/[oD;g/=D[;$g/r@[/[oD;g/=D[;d s@\0\pD<h0>D\<du@\0\pD<h0>D\<' v@\0\pD<h0>D\<#Lw@\0\pD<h0>D\<Rqx@\0\pD<h0>D\<^y@\0\pD<h0>D\<;!z@\0\pD<h0>D\<$'{@\0\pD<h0>D\<$.|@\0\pD<h0>D\<d>)4}@\0\pD<h0>D\<dmN:~@]1]@pD=i1@>D]=ds@@]1]@pD=i1@>D]=jF@]1]@pD=i1@>D]=GL@]1]@pD=i1@>D]=)%R@]1]@pD=i1@>D]=XY@]1]@pD=i1@>D]=+_@]1]@pD=i1@>D]=$Pe@]1]@pD=i1@>D]=$uk@]1]@pD=i1@>D]=dwq@]1]@pD=i1@>D]=dDTw@^2^pD>j2>D^>s1}@^2^pD>j2>D^> @^2^pD>j2>D^>-@^2^pD>j2>D^>R@^2^pD>j2>D^>/w@^2^pD>j2>D^>$_@^2^pD>j2>D^>$`@^2^pD>j2>D^>$=樐@^2^pD>j2>D^>d @^2^pD>j2>D^>d/@_3_pD?k3>D_?JT@_3_pD?k3>D_?yy@_3_pD?k3>D_?䨏Ǖ@_3_pD?k3>D_?l͖@_3_pD?k3>D_?Jӗ@_3_pD?k3>D_?$6' ژ@_3_pD?k3>D_?$e2@_3_pD?k3>D_?dV@_3_pD?k3>D_?dþ{@_3_pD?k3>D_?d@`4`qD@l4?D`@!y@`4`qD@l4?D`@PV@`4`qD@l4?D`@3@`4`qD@l4?D`@4 @`4`qD@l4?D`@$X@`4`qD@l4?D`@$ }@`4`qD@l4?D`@$<@`4`qD@l4?D`@dk#@`4`qD@l4?D`@db)@`4`qD@l4?D`@?0@a5a@qDA m5@?DaA 66@a5a@qDA m5@?DaA 'Z<@a5a@qDA m5@?DaA VB@a5a@qDA m5@?DaA 䅴H@a5a@qDA m5@?DaA $N@a5a@qDA m5@?DaA $nT@a5a@qDA m5@?DaA dL[@a5a@qDA m5@?DaA dB)8a@a5a@qDA m5@?DaA dq]g@a5a@qDA m5@?DaA m@b6bqDB n6?DbB s@b6bqDB n6?DbB y@b6bqDB n6?DbB -{@b6bqDB n6?DbB \X@b6bqDB n6?DbB $5:@b6bqDB n6?DbB $_@b6bqDB n6?DbB d@b6bqDB n6?DbB dͨ@b6bqDB n6?DbB Hͤ@b6bqDB n6?DbB w@c7cqDC o7?DcC d@c7cqDC o7?DcC A<@c7cqDC o7?DcC a@c7cqDC o7?DcC $4ÿ@c7cqDC o7?DcC $c٪@c7cqDC o7?DcC $@c7cqDC o7?DcC d@c7cqDC o7?DcC dp@c7cqDC o7?DcC N>@c7cqDC o7?DcC N+c@d8drDD p8@DdD }@d8drDD p8@DdD @d8drDD p8@DdD @d8drDD p8@DdD $ @d8drDD p8@DdD $:}@d8drDD p8@DdD diZ@ @d8drDD p8@DdD d7e@d8drDD p8@DdD d@d8drDD p8@DdD @d8drDD p8@DdD %%@e9e@rDE q9@@DeE T+@e9e@rDE q9@@DeE 䃉2@e9e@rDE q9@@DeE $fB8@e9e@rDE q9@@DeE $Cg>@e9e@rDE q9@@DeE $!D@e9e@rDE q9@@DeE d@J@e9e@rDE q9@@DeE doP@e9e@rDE q9@@DeE dV@e9e@rDE q9@@DeE ͕]@e9e@rDE q9@@DeE rDc@f:frDFr:@DfF+Pii@f:frDFr:@DfFZ-o@f:frDFr:@DfF u@f:frDFr:@DfF${@f:frDFr:@DfF$@f:frDFr:@DfFd!@f:frDFr:@DfFdFF@f:frDFr:@DfFu\k@f:frDFr:@DfF9@f:frDFr:@DfF@g;grDGs;@DgG٦@g;grDGs;@DgG1@g;grDGs;@DgG$a#@g;grDGs;@DgG$H@g;grDGs;@DgG$hm@g;grDGs;@DgGdE@g;grDGs;@DgGd#@g;grDGs;@DgGL@g;grDGs;@DgG{@g;grDGs;@DgG䪺%@h<hsDHt<ADhHٗJ@h<hsDHt<ADhHuo@h<hsDHt<ADhH$8R@h<hsDHt<ADhH$g/@h<hsDHt<ADhHd @h<hsDHt<ADhHd@h<hsDHt<ADhHd' @h<hsDHt<ADhH#L@h<hsDHt<ADhHRq@h<hsDHt<ADhH^@i=i@sDIu=@ADiI;!@i=i@sDIu=@ADiI$'@i=i@sDIu=@ADiI$.@i=i@sDIu=@ADiI$>)4@i=i@sDIu=@ADiIdmN:@i=i@sDIu=@ADiIds@@i=i@sDIu=@ADiIjF@i=i@sDIu=@ADiIGL@i=i@sDIu=@ADiI)%R@i=i@sDIu=@ADiIXY@j>jsDJv>ADjJ+_@j>jsDJv>ADjJ$Pe@j>jsDJv>ADjJ$uk@j>jsDJv>ADjJdwq@j>jsDJv>ADjJdDTw@j>jsDJv>ADjJds1} @j>jsDJv>ADjJ @j>jsDJv>ADjJ- @j>jsDJv>ADjJR @j>jsDJv>ADjJ/w @k?ksDKw?ADkK^@k?ksDKw?ADkK$`@k?ksDKw?ADkK$=@k?ksDKw?ADkKd @k?ksDKw?ADkKd/@k?ksDKw?ADkKJT@k?ksDKw?ADkKyy@k?ksDKw?ADkK@k?ksDKw?ADkKl@k?ksDKw?ADkKJ@l@ltDLx@BDlL$6' @l@ltDLx@BDlL$e2@l@ltDLx@BDlL$V@l@ltDLx@BDlLdþ{@l@ltDLx@BDlLd@l@ltDLx@BDlL!y@l@ltDLx@BDlLPV@l@ltDLx@BDlL3 @l@ltDLx@BDlL4 !@l@ltDLx@BDlLX"@m A m@tDMyA@BDmM$ }#@m A m@tDMyA@BDmM$<$@m A m@tDMyA@BDmMdk#%@m A m@tDMyA@BDmMdb)&@m A m@tDMyA@BDmMd?0'@m A m@tDMyA@BDmM66(@m A m@tDMyA@BDmM'Z<)@m A m@tDMyA@BDmMVB*@m A m@tDMyA@BDmM䅴H+@m A m@tDMyA@BDmM$N,@n B ntDNzBBDnN$nT-@n B ntDNzBBDnN$L[.@n B ntDNzBBDnNdB)8a/@n B ntDNzBBDnNdq]g0@n B ntDNzBBDnNm1@n B ntDNzBBDnNs2@n B ntDNzBBDnNy3@n B ntDNzBBDnN-{4@n B ntDNzBBDnN\X5@n B ntDNzBBDnN$5:6@o C otDO{CBDoO$_7@o C otDO{CBDoOd8@o C otDO{CBDoOdͨ9@o C otDO{CBDoOdHͤ:@o C otDO{CBDoOw;@o C otDO{CBDoOd<@o C otDO{CBDoOA<=@o C otDO{CBDoOa>@o C otDO{CBDoO$4?@o C otDO{CBDoO$c٪@@p D puDP|DCDpPdA@p D puDP|DCDpPdB@p D puDP|DCDpPdpC@p D puDP|DCDpPN>D@p D puDP|DCDpPN+cE@p D puDP|DCDpP}F@p D puDP|DCDpPG@p D puDP|DCDpP$H@p D puDP|DCDpP$ J@p D puDP|DCDpP$:}K@q E q@uDQ}E@CDqQdiZ@ L@q E q@uDQ}E@CDqQd7eM@q E q@uDQ}E@CDqQN@q E q@uDQ}E@CDqQO@q E q@uDQ}E@CDqQ%%P@q E q@uDQ}E@CDqQT+Q@q E q@uDQ}E@CDqQ䃉2R@q E q@uDQ}E@CDqQ$fB8S@q E q@uDQ}E@CDqQ$Cg>T@q E q@uDQ}E@CDqQd!DU@rFruDR~FCDrRd@JV@rFruDR~FCDrRdoPW@rFruDR~FCDrRVX@rFruDR~FCDrR͕]Y@rFruDR~FCDrRrDcZ@rFruDR~FCDrR+Pii[@rFruDR~FCDrRZ-o\@rFruDR~FCDrR$ u]@rFruDR~FCDrR${^@rFruDR~FCDrRd_@sGsuDSGCDsSd!`@sGsuDSGCDsSFFa@sGsuDSGCDsSu\kb@sGsuDSGCDsS9c@sGsuDSGCDsSd@sGsuDSGCDsS٦e@sGsuDSGCDsS$2f@sGsuDSGCDsS$a#g@sGsuDSGCDsS$Hh@sGsuDSGCDsSdhmi@tHtvDTHDDtTdEj@tHtvDTHDDtT#k@tHtvDTHDDtTLl@tHtvDTHDDtT{m@tHtvDTHDDtT䪺%n@tHtvDTHDDtTٗJo@tHtvDTHDDtT$ uop@tHtvDTHDDtT$8Rq@tHtvDTHDDtTdg/r@tHtvDTHDDtTd s@uIu@vDUI@DDuUdu@uIu@vDUI@DDuU' v@uIu@vDUI@DDuU#Lw@uIu@vDUI@DDuURqx@uIu@vDUI@DDuU^y@uIu@vDUI@DDuU$;!z@uIu@vDUI@DDuU$'{@uIu@vDUI@DDuU$.|@uIu@vDUI@DDuUd>)4}@uIu@vDUI@DDuUdmN:~@vJvvDVJDDvVs@@vJvvDVJDDvVjF@vJvvDVJDDvVGL@vJvvDVJDDvV)%R@vJvvDVJDDvVXY@vJvvDVJDDvV$+_@vJvvDVJDDvV$Pe@vJvvDVJDDvVduk@vJvvDVJDDvVdwq@vJvvDVJDDvVdDTw@wKwvDWKDDwWs1}@wKwvDWKDDwW @wKwvDWKDDwW-@wKwvDWKDDwWR@wKwvDWKDDwW/w@wKwvDWKDDwW$_@wKwvDWKDDwW$`@wKwvDWKDDwWd=樐@wKwvDWKDDwWd @wKwvDWKDDwW/@xLxwDX LEDxX JT@xLxwDX LEDxX yy@xLxwDX LEDxX 䨏Ǖ@xLxwDX LEDxX l͖@xLxwDX LEDxX $Jӗ@xLxwDX LEDxX $6' ژ@xLxwDX LEDxX $e2@xLxwDX LEDxX dV@xLxwDX LEDxX dþ{@xLxwDX LEDxX @yMy@wDY!M@EDyY!!y@yMy@wDY!M@EDyY!PV@yMy@wDY!M@EDyY!3@yMy@wDY!M@EDyY!4 @yMy@wDY!M@EDyY!$X@yMy@wDY!M@EDyY!$ }@yMy@wDY!M@EDyY!d<@yMy@wDY!M@EDyY!dk#@yMy@wDY!M@EDyY!b)@yMy@wDY!M@EDyY!?0@zNzwDZ"NEDzZ"66@zNzwDZ"NEDzZ"'Z<@zNzwDZ"NEDzZ"VB@zNzwDZ"NEDzZ"$H@zNzwDZ"NEDzZ"$N@zNzwDZ"NEDzZ"dnT@zNzwDZ"NEDzZ"dL[@zNzwDZ"NEDzZ"B)8a@zNzwDZ"NEDzZ"q]g@zNzwDZ"NEDzZ"m@{O{wD[#OED{[#s@{O{wD[#OED{[#y@{O{wD[#OED{[#$.{@{O{wD[#OED{[#$]X@{O{wD[#OED{[#$5:@{O{wD[#OED{[#d_@{O{wD[#OED{[#d@{O{wD[#OED{[#ͨ@{O{wD[#OED{[#Hͤ@{O{wD[#OED{[#w@|P|xD\$PFD|\$d@|P|xD\$PFD|\$A<@|P|xD\$PFD|\$$a@|P|xD\$PFD|\$$4ÿ@|P|xD\$PFD|\$dc٪@|P|xD\$PFD|\$d@|P|xD\$PFD|\$d@|P|xD\$PFD|\$p@|P|xD\$PFD|\$N>@|P|xD\$PFD|\$N+c@}Q}@xD]%Q@FD}]%}@}Q}@xD]%Q@FD}]%$@}Q}@xD]%Q@FD}]%$@}Q}@xD]%Q@FD}]%$ @}Q}@xD]%Q@FD}]%d:}@}Q}@xD]%Q@FD}]%diZ@ @}Q}@xD]%Q@FD}]%7e@}Q}@xD]%Q@FD}]%@}Q}@xD]%Q@FD}]%@}Q}@xD]%Q@FD}]%%%@~R~xD^&RFD~^&T+@~R~xD^&RFD~^&$2@~R~xD^&RFD~^&$fB8@~R~xD^&RFD~^&dCg>@~R~xD^&RFD~^&d!D@~R~xD^&RFD~^&d@J@~R~xD^&RFD~^&oP@~R~xD^&RFD~^&V@~R~xD^&RFD~^&͕]@~R~xD^&RFD~^&rDc@SxD_'SFD_'+Pii@SxD_'SFD_'$[-o@SxD_'SFD_'$ u@SxD_'SFD_'d{@SxD_'SFD_'d@SxD_'SFD_'!@SxD_'SFD_'FF@SxD_'SFD_'u\k@SxD_'SFD_'9@SxD_'SFD_'@TyD`(TGD`($٦@TyD`(TGD`($2@TyD`(TGD`($a#@TyD`(TGD`(dH@TyD`(TGD`(dhm@TyD`(TGD`(E@TyD`(TGD`(#@TyD`(TGD`(L@TyD`(TGD`({@TyD`(TGD`(䪺%@U@yDa)U@GDa)$ڗJ@U@yDa)U@GDa)$ uo@U@yDa)U@GDa)d8R@U@yDa)U@GDa)dg/@U@yDa)U@GDa)d @U@yDa)U@GDa)@U@yDa)U@GDa)' @U@yDa)U@GDa)#L@U@yDa)U@GDa)Rq@U@yDa)U@GDa)$^@VyDb*VGDb*$;!@VyDb*VGDb*$'@VyDb*VGDb*d.@VyDb*VGDb*d>)4@VyDb*VGDb*mN:@VyDb*VGDb*s@@VyDb*VGDb*jF@VyDb*VGDb*GL@VyDb*VGDb*)%R@VyDb*VGDb*$YY@WyDc+WGDc+$+_@WyDc+WGDc+dPe@WyDc+WGDc+duk@WyDc+WGDc+dwq@WyDc+WGDc+DTw@WyDc+WGDc+s1} @WyDc+WGDc+ @WyDc+WGDc+- @WyDc+WGDc+$R @WyDc+WGDc+$0w @ X d,XHDd,d_@ X d,XHDd,d`@ X d,XHDd,d=@ X d,XHDd, @ X d,XHDd,/@ X d,XHDd,JT@ X d,XHDd,yy@ X d,XHDd,$@ X d,XHDd,$l@ X d,XHDd,$J@!Y!?e-Y@HDe-d6' @!Y!?e-Y@HDe-de2@!Y!?e-Y@HDe-V@!Y!?e-Y@HDe-þ{@!Y!?e-Y@HDe-@!Y!?e-Y@HDe-!y@!Y!?e-Y@HDe-PV@!Y!?e-Y@HDe-$3 @!Y!?e-Y@HDe-$4 !@!Y!?e-Y@HDe-dX"@"Z"@f.ZHDf.d }#@"Z"@f.ZHDf.d<$@"Z"@f.ZHDf.k#%@"Z"@f.ZHDf.b)&@"Z"@f.ZHDf.?0'@"Z"@f.ZHDf.66(@"Z"@f.ZHDf.'Z<)@"Z"@f.ZHDf.$WB*@"Z"@f.ZHDf.$H+@"Z"@f.ZHDf.dN,@#[#@@g/[HDg/dnT-@#[#@@g/[HDg/L[.@#[#@@g/[HDg/B)8a/@#[#@@g/[HDg/q]g0@#[#@@g/[HDg/m1@#[#@@g/[HDg/s2@#[#@@g/[HDg/$y3@#[#@@g/[HDg/$.{4@#[#@@g/[HDg/$]X5@#[#@@g/[HDg/d5:6@$\$@h0\IDh0d_7@$\$@h0\IDh08@$\$@h0\IDh0ͨ9@$\$@h0\IDh0Hͤ:@$\$@h0\IDh0w;@$\$@h0\IDh0d<@$\$@h0\IDh0$A<=@$\$@h0\IDh0$a>@$\$@h0\IDh0d4?@$\$@h0\IDh0dc٪@@%]%@i1]@IDi1dA@%]%@i1]@IDi1B@%]%@i1]@IDi1pC@%]%@i1]@IDi1N>D@%]%@i1]@IDi1N+cE@%]%@i1]@IDi1$~F@%]%@i1]@IDi1$G@%]%@i1]@IDi1$H@%]%@i1]@IDi1d J@%]%@i1]@IDi1d:}K@&^&@j2^IDj2iZ@ L@&^&@j2^IDj27eM@&^&@j2^IDj2N@&^&@j2^IDj2O@&^&@j2^IDj2%%P@&^&@j2^IDj2$U+Q@&^&@j2^IDj2$2R@&^&@j2^IDj2dfB8S@&^&@j2^IDj2dCg>T@&^&@j2^IDj2d!DU@'_'@k3_IDk3@JV@'_'@k3_IDk3oPW@'_'@k3_IDk3䞸VX@'_'@k3_IDk3͕]Y@'_'@k3_IDk3rDcZ@'_'@k3_IDk3$,Pii[@'_'@k3_IDk3$[-o\@'_'@k3_IDk3d u]@'_'@k3_IDk3d{^@'_'@k3_IDk3_@(`(Al4`JDl4!`@(`(Al4`JDl4FFa@(`(Al4`JDl4u\kb@(`(Al4`JDl49c@(`(Al4`JDl4$d@(`(Al4`JDl4$٦e@(`(Al4`JDl4$2f@(`(Al4`JDl4da#g@(`(Al4`JDl4dHh@(`(Al4`JDl4hmi@)a)Am5a@JD m5Ej@)a)Am5a@JD m5#k@)a)Am5a@JD m5Ll@)a)Am5a@JD m5{m@)a)Am5a@JD m5$%n@)a)Am5a@JD m5$ڗJo@)a)Am5a@JD m5d uop@)a)Am5a@JD m5d8Rq@)a)Am5a@JD m5g/r@)a)Am5a@JD m5 s@*b* An6bJD n6u@*b* An6bJD n6' v@*b* An6bJD n6#Lw@*b* An6bJD n6$Sqx@*b* An6bJD n6$^y@*b* An6bJD n6d;!z@*b* An6bJD n6d'{@*b* An6bJD n6.|@*b* An6bJD n6>)4}@*b* An6bJD n6mN:~@+c+0Ao7cJD o7䜍s@@+c+0Ao7cJD o7jF@+c+0Ao7cJD o7$GL@+c+0Ao7cJD o7$*%R@+c+0Ao7cJD o7$YY@+c+0Ao7cJD o7d+_@+c+0Ao7cJD o7dPe@+c+0Ao7cJD o7uk@+c+0Ao7cJD o7wq@+c+0Ao7cJD o7DTw@,d,@Ap8 dKD p8s1}@,d,@Ap8 dKD p8 @,d,@Ap8 dKD p8$-@,d,@Ap8 dKD p8$R@,d,@Ap8 dKD p8d0w@,d,@Ap8 dKD p8d_@,d,@Ap8 dKD p8d`@,d,@Ap8 dKD p8=樐@,d,@Ap8 dKD p8 @,d,@Ap8 dKD p8/@-e-PAq9 e@KD q9JT@-e-PAq9 e@KD q9$zy@-e-PAq9 e@KD q9$Ǖ@-e-PAq9 e@KD q9$l͖@-e-PAq9 e@KD q9dJӗ@-e-PAq9 e@KD q9d6' ژ@-e-PAq9 e@KD q9e2@-e-PAq9 e@KD q9V@-e-PAq9 e@KD q9þ{@-e-PAq9 e@KD q9@.f.`Ar: fKDr:!y@.f.`Ar: fKDr:$QV@.f.`Ar: fKDr:$3@.f.`Ar: fKDr:d4 @.f.`Ar: fKDr:dX@.f.`Ar: fKDr:d }@.f.`Ar: fKDr:<@.f.`Ar: fKDr:k#@.f.`Ar: fKDr:b)@.f.`Ar: fKDr:?0@/g/pAs; gKDs;66@/g/pAs; gKDs;$(Z<@/g/pAs; gKDs;$WB@/g/pAs; gKDs;dH@/g/pAs; gKDs;dN@/g/pAs; gKDs;nT@/g/pAs; gKDs;L[@/g/pAs; gKDs;B)8a@/g/pAs; gKDs;q]g@/g/pAs; gKDs;m@0h0At< hLDt<$s@0h0At< hLDt<$y@0h0At< hLDt<$.{@0h0At< hLDt<d]X@0h0At< hLDt<d5:@0h0At< hLDt<_@0h0At< hLDt<@0h0At< hLDt<ͨ@0h0At< hLDt<Hͤ@0h0At< hLDt<w@1i1Au= i@LDu=$d@1i1Au= i@LDu=$A<@1i1Au= i@LDu=da@1i1Au= i@LDu=d4ÿ@1i1Au= i@LDu=dc٪@1i1Au= i@LDu=@1i1Au= i@LDu=@1i1Au= i@LDu=p@1i1Au= i@LDu=N>@1i1Au= i@LDu=$O+c@2j2Av> jLDv>$~@2j2Av> jLDv>$@2j2Av> jLDv>d@2j2Av> jLDv>d @2j2Av> jLDv>:}@2j2Av> jLDv>iZ@ @2j2Av> jLDv>7e@2j2Av> jLDv>@2j2Av> jLDv>@2j2Av> jLDv>$&%@3k3Aw? kLDw?$U+@3k3Aw? kLDw?d2@3k3Aw? kLDw?dfB8@3k3Aw? kLDw?dCg>@3k3Aw? kLDw?!D@3k3Aw? kLDw?@J@3k3Aw? kLDw?oP@3k3Aw? kLDw?䞸V@3k3Aw? kLDw?$Ε]@3k3Aw? kLDw?$rDc@4l4Ax@ lMDx@d,Pii@4l4Ax@ lMDx@d[-o@4l4Ax@ lMDx@d u@4l4Ax@ lMDx@{@4l4Ax@ lMDx@@4l4Ax@ lMDx@!@4l4Ax@ lMDx@FF@4l4Ax@ lMDx@$v\k@4l4Ax@ lMDx@$9@4l4Ax@ lMDx@$@5 m5AyA m@MDyAd٦@5 m5AyA m@MDyAd2@5 m5AyA m@MDyAa#@5 m5AyA m@MDyAH@5 m5AyA m@MDyAhm@5 m5AyA m@MDyAE@5 m5AyA m@MDyA#@5 m5AyA m@MDyA$M@5 m5AyA m@MDyA$|@5 m5AyA m@MDyAd%@6 n6AzB nMDzBdڗJ@6 n6AzB nMDzBd uo@6 n6AzB nMDzB8R@6 n6AzB nMDzBg/@6 n6AzB nMDzB @6 n6AzB nMDzB@6 n6AzB nMDzB' @6 n6AzB nMDzB$$L@6 n6AzB nMDzB$Sq@6 n6AzB nMDzBd^@7 o7A{C oMD{Cd;!@7 o7A{C oMD{C'@7 o7A{C oMD{C.@7 o7A{C oMD{C>)4@7 o7A{C oMD{CmN:@7 o7A{C oMD{C䜍s@@7 o7A{C oMD{C$jF@7 o7A{C oMD{C$GL@7 o7A{C oMD{C$*%R@7 o7A{C oMD{CdYY@8 p8A|D pND|Dd+_@8 p8A|D pND|DPe@8 p8A|D pND|Duk@8 p8A|D pND|Dwq@8 p8A|D pND|DDTw@8 p8A|D pND|Ds1} @8 p8A|D pND|D$ @8 p8A|D pND|D$- @8 p8A|D pND|DdR @8 p8A|D pND|Dd0w @9 q9A}E q@ND}Ed_@9 q9A}E q@ND}E`@9 q9A}E q@ND}E=@9 q9A}E q@ND}E @9 q9A}E q@ND}E/@9 q9A}E q@ND}E$KT@9 q9A}E q@ND}E$zy@9 q9A}E q@ND}E$@9 q9A}E q@ND}Edl@9 q9A}E q@ND}EdJ@:r:A~F rND~F6' @:r:A~F rND~Fe2@:r:A~F rND~FV@:r:A~F rND~Fþ{@:r:A~F rND~F@:r:A~F rND~F$"y@:r:A~F rND~F$QV@:r:A~F rND~Fd3 @:r:A~F rND~Fd4 !@:r:A~F rND~FdX"@;s;AG sNDG }#@;s;AG sNDG<$@;s;AG sNDGk#%@;s;AG sNDGb)&@;s;AG sNDG?0'@;s;AG sNDG$66(@;s;AG sNDG$(Z<)@;s;AG sNDGdWB*@;s;AG sNDGdH+@;s;AG sNDGN,@<t<AH!tODHnT-@<t<AH!tODHL[.@<t<AH!tODHB)8a/@<t<AH!tODHq]g0@<t<AH!tODH$m1@<t<AH!tODH$s2@<t<AH!tODH$y3@<t<AH!tODHd.{4@<t<AH!tODHd]X5@<t<AH!tODH5:6@=u=AI!u@ODI_7@=u=AI!u@ODI8@=u=AI!u@ODIͨ9@=u=AI!u@ODIHͤ:@=u=AI!u@ODI$x;@=u=AI!u@ODI$d<@=u=AI!u@ODIdA<=@=u=AI!u@ODIda>@=u=AI!u@ODI4?@=u=AI!u@ODIc٪@@>v>AJ!vODJ䒶A@>v>AJ!vODJB@>v>AJ!vODJpC@>v>AJ!vODJ$ N>D@>v>AJ!vODJ$O+cE@>v>AJ!vODJd~F@>v>AJ!vODJdG@>v>AJ!vODJH@>v>AJ!vODJ J@>v>AJ!vODJ:}K@?w?AK!wODKiZ@ L@?w?AK!wODK7eM@?w?AK!wODK$N@?w?AK!wODK$O@?w?AK!wODK$&%P@?w?AK!wODKdU+Q@?w?AK!wODKd2R@?w?AK!wODKfB8S@?w?AK!wODKCg>T@?w?AK!wODK!DU@@x@BL!xPD L@JV@@x@BL!xPD LoPW@@x@BL!xPD L$VX@@x@BL!xPD L$Ε]Y@@x@BL!xPD LdrDcZ@@x@BL!xPD Ld,Pii[@@x@BL!xPD Ld[-o\@@x@BL!xPD L u]@@x@BL!xPD L{^@@x@BL!xPD L_@AyABM!y@PD!M!`@AyABM!y@PD!M$GFa@AyABM!y@PD!M$v\kb@AyABM!y@PD!M$9c@AyABM!y@PD!Mdd@AyABM!y@PD!Md٦e@AyABM!y@PD!M2f@AyABM!y@PD!Ma#g@AyABM!y@PD!MHh@AyABM!y@PD!Mhmi@BzBBN!zPD"NEj@BzBBN!zPD"N$#k@BzBBN!zPD"N$Ml@BzBBN!zPD"Nd|m@BzBBN!zPD"Nd%n@BzBBN!zPD"NdڗJo@BzBBN!zPD"N uop@BzBBN!zPD"N8Rq@BzBBN!zPD"Ng/r@BzBBN!zPD"N s@C{C BO!{PD#Ou@C{C BO!{PD#O$' v@C{C BO!{PD#O$$Lw@C{C BO!{PD#OdSqx@C{C BO!{PD#Od^y@C{C BO!{PD#O;!z@C{C BO!{PD#O'{@C{C BO!{PD#O.|@C{C BO!{PD#O>)4}@C{C BO!{PD#OmN:~@D|DBP!|QD$P$s@@D|DBP!|QD$P$jF@D|DBP!|QD$P$GL@D|DBP!|QD$Pd*%R@D|DBP!|QD$PdYY@D|DBP!|QD$P+_@D|DBP!|QD$PPe@D|DBP!|QD$Puk@D|DBP!|QD$Pwq@D|DBP!|QD$PDTw@E}EBQ!}@QD%Q$t1}@E}EBQ!}@QD%Q$ @E}EBQ!}@QD%Qd-@E}EBQ!}@QD%QdR@E}EBQ!}@QD%Qd0w@E}EBQ!}@QD%Q_@E}EBQ!}@QD%Q`@E}EBQ!}@QD%Q=樐@E}EBQ!}@QD%Q @E}EBQ!}@QD%Q$/@F~FBR!~QD&R$KT@F~FBR!~QD&R$zy@F~FBR!~QD&RdǕ@F~FBR!~QD&Rdl͖@F~FBR!~QD&RJӗ@F~FBR!~QD&R6' ژ@F~FBR!~QD&Re2@F~FBR!~QD&RV@F~FBR!~QD&Rþ{@F~FBR!~QD&R$@GGBS!QD'S$"y@GGBS!QD'SdQV@GGBS!QD'Sd3@GGBS!QD'Sd4 @GGBS!QD'SX@GGBS!QD'S }@GGBS!QD'S<@GGBS!QD'Sk#@GGBS!QD'S$b)@GGBS!QD'S$?0@HH BT!RD(Td66@HH BT!RD(Td(Z<@HH BT!RD(TdWB@HH BT!RD(TH@HH BT!RD(TN@HH BT!RD(TnT@HH BT!RD(TL[@HH BT!RD(T$C)8a@HH BT!RD(T$r]g@HH BT!RD(T$m@II$BU!@RD)Uds@II$BU!@RD)Udy@II$BU!@RD)U.{@II$BU!@RD)U]X@II$BU!@RD)U5:@II$BU!@RD)U_@II$BU!@RD)U@II$BU!@RD)U$ͨ@II$BU!@RD)U$Iͤ@II$BU!@RD)Udx@JJ(BV!RD*Vdd@JJ(BV!RD*VdA<@JJ(BV!RD*Va@JJ(BV!RD*V4ÿ@JJ(BV!RD*Vc٪@JJ(BV!RD*V䒶@JJ(BV!RD*V@JJ(BV!RD*V$p@JJ(BV!RD*V$ N>@JJ(BV!RD*VdO+c@KK,BW!RD+Wd~@KK,BW!RD+W@KK,BW!RD+W@KK,BW!RD+W @KK,BW!RD+W:}@KK,BW!RD+WiZ@ @KK,BW!RD+W$7e@KK,BW!RD+W$@KK,BW!RD+W$@KK,BW!RD+Wd&%@L L0BX"SD,XdU+@L L0BX"SD,X2@L L0BX"SD,XfB8@L L0BX"SD,XCg>@L L0BX"SD,X!D@L L0BX"SD,X@J@L L0BX"SD,X$pP@L L0BX"SD,X$V@L L0BX"SD,XdΕ]@L L0BX"SD,XdrDc@M!M4BY"@SD-Yd,Pii@M!M4BY"@SD-Y[-o@M!M4BY"@SD-Y u@M!M4BY"@SD-Y{@M!M4BY"@SD-Y@M!M4BY"@SD-Y$!@M!M4BY"@SD-Y$GF@M!M4BY"@SD-Y$v\k@M!M4BY"@SD-Yd9@M!M4BY"@SD-Yd@N"N8BZ"SD.Z٦@N"N8BZ"SD.Z2@N"N8BZ"SD.Za#@N"N8BZ"SD.Z䐋H@N"N8BZ"SD.Zhm@N"N8BZ"SD.Z$E@N"N8BZ"SD.Z$#@N"N8BZ"SD.ZdM@N"N8BZ"SD.Zd|@N"N8BZ"SD.Zd%@O#O)4@P$P@B\"TD0\$nN:@P$P@B\"TD0\$s@@P$P@B\"TD0\$jF@P$P@B\"TD0\dGL@P$P@B\"TD0\d*%R@P$P@B\"TD0\YY@Q%QDB]"@TD1]+_@Q%QDB]"@TD1]䷼Pe@Q%QDB]"@TD1]uk@Q%QDB]"@TD1]wq@Q%QDB]"@TD1]$ETw@Q%QDB]"@TD1]$t1} @Q%QDB]"@TD1]d @Q%QDB]"@TD1]d- @Q%QDB]"@TD1]R @Q%QDB]"@TD1]0w @R&RHB^"TD2^_@R&RHB^"TD2^`@R&RHB^"TD2^=@R&RHB^"TD2^$ @R&RHB^"TD2^$/@R&RHB^"TD2^dKT@R&RHB^"TD2^dzy@R&RHB^"TD2^@R&RHB^"TD2^l@R&RHB^"TD2^J@S'SLB_"TD3_6' @S'SLB_"TD3_e2@S'SLB_"TD3_$V@S'SLB_"TD3_$ľ{@S'SLB_"TD3_$@S'SLB_"TD3_d"y@S'SLB_"TD3_dQV@S'SLB_"TD3_3 @S'SLB_"TD3_4 !@S'SLB_"TD3_X"@T(TPB`"UD4` }#@T(TPB`"UD4`<$@T(TPB`"UD4`$l#%@T(TPB`"UD4`$b)&@T(TPB`"UD4`d?0'@T(TPB`"UD4`d66(@T(TPB`"UD4`d(Z<)@T(TPB`"UD4`WB*@T(TPB`"UD4`H+@T(TPB`"UD4`䵑N,@U)UTBa"@UD5anT-@U)UTBa"@UD5a$L[.@U)UTBa"@UD5a$C)8a/@U)UTBa"@UD5a$r]g0@U)UTBa"@UD5adm1@U)UTBa"@UD5ads2@U)UTBa"@UD5ay3@U)UTBa"@UD5a.{4@U)UTBa"@UD5a]X5@U)UTBa"@UD5a5:6@V*VXBb"UD6b_7@V*VXBb"UD6b$8@V*VXBb"UD6b$ͨ9@V*VXBb"UD6bdIͤ:@V*VXBb"UD6bdx;@V*VXBb"UD6bdd<@V*VXBb"UD6bA<=@V*VXBb"UD6ba>@V*VXBb"UD6b4?@V*VXBb"UD6bc٪@@W+W\Bc"UD7c䒶A@W+W\Bc"UD7c$“B@W+W\Bc"UD7c$pC@W+W\Bc"UD7cd N>D@W+W\Bc"UD7cdO+cE@W+W\Bc"UD7c~F@W+W\Bc"UD7cG@W+W\Bc"UD7cH@W+W\Bc"UD7c J@W+W\Bc"UD7c:}K@X,X`Bd"VD8d$jZ@ L@X,X`Bd"VD8d$7eM@X,X`Bd"VD8d$N@X,X`Bd"VD8ddO@X,X`Bd"VD8dd&%P@X,X`Bd"VD8dU+Q@X,X`Bd"VD8d2R@X,X`Bd"VD8dfB8S@X,X`Bd"VD8dCg>T@X,X`Bd"VD8d!DU@Y-YdBe"@VD9e$AJV@Y-YdBe"@VD9e$pPW@Y-YdBe"@VD9edVX@Y-YdBe"@VD9edΕ]Y@Y-YdBe"@VD9edrDcZ@Y-YdBe"@VD9e,Pii[@Y-YdBe"@VD9e[-o\@Y-YdBe"@VD9e u]@Y-YdBe"@VD9e{^@Y-YdBe"@VD9e$_@Z.ZhBf"VD:f$!`@Z.ZhBf"VD:f$GFa@Z.ZhBf"VD:fdv\kb@Z.ZhBf"VD:fd9c@Z.ZhBf"VD:fd@Z.ZhBf"VD:f٦e@Z.ZhBf"VD:f2f@Z.ZhBf"VD:fa#g@Z.ZhBf"VD:f䐋Hh@Z.ZhBf"VD:f$hmi@[/[lBg"VD;g$Ej@[/[lBg"VD;gd#k@[/[lBg"VD;gdMl@[/[lBg"VD;gd|m@[/[lBg"VD;g%n@[/[lBg"VD;gڗJo@[/[lBg"VD;g uop@[/[lBg"VD;g8Rq@[/[lBg"VD;g$h/r@[/[lBg"VD;g$ s@\0\pBh#WD<hdu@\0\pBh#WD<hd' v@\0\pBh#WD<hd$Lw@\0\pBh#WD<hSqx@\0\pBh#WD<h^y@\0\pBh#WD<h;!z@\0\pBh#WD<h'{@\0\pBh#WD<h$.|@\0\pBh#WD<h$?)4}@\0\pBh#WD<h$nN:~@]1]tBi#@WD=ids@@]1]tBi#@WD=idjF@]1]tBi#@WD=iGL@]1]tBi#@WD=i*%R@]1]tBi#@WD=iYY@]1]tBi#@WD=i+_@]1]tBi#@WD=i䷼Pe@]1]tBi#@WD=i$uk@]1]tBi#@WD=i$wq@]1]tBi#@WD=idETw@^2^xBj#WD>jdt1}@^2^xBj#WD>jd @^2^xBj#WD>j-@^2^xBj#WD>jR@^2^xBj#WD>j0w@^2^xBj#WD>j_@^2^xBj#WD>j`@^2^xBj#WD>j$=樐@^2^xBj#WD>j$ @^2^xBj#WD>jd/@_3_|Bk#WD?kdKT@_3_|Bk#WD?kzy@_3_|Bk#WD?kǕ@_3_|Bk#WD?kl͖@_3_|Bk#WD?kJӗ@_3_|Bk#WD?k6' ژ@_3_|Bk#WD?k$f2@_3_|Bk#WD?k$V@_3_|Bk#WD?k$ľ{@_3_|Bk#WD?kd@`4`Bl#XD@ld"y@`4`Bl#XD@lQV@`4`Bl#XD@l3@`4`Bl#XD@l4 @`4`Bl#XD@lX@`4`Bl#XD@l }@`4`Bl#XD@l$=@`4`Bl#XD@l$l#@`4`Bl#XD@ldb)@`4`Bl#XD@ld?0@a5a Bm#@XDA md66@a5a Bm#@XDA m(Z<@a5a Bm#@XDA mWB@a5a Bm#@XDA m䆴H@a5a Bm#@XDA m䵑N@a5a Bm#@XDA m$nT@a5a Bm#@XDA m$L[@a5a Bm#@XDA m$C)8a@a5a Bm#@XDA mdr]g@a5a Bm#@XDA mdm@b6b Bn#XDB ns@b6b Bn#XDB ny@b6b Bn#XDB n.{@b6b Bn#XDB n]X@b6b Bn#XDB n5:@b6b Bn#XDB n$_@b6b Bn#XDB n$@b6b Bn#XDB ndͨ@b6b Bn#XDB ndIͤ@b6b Bn#XDB ndx@c7c Bo#XDC od@c7c Bo#XDC oA<@c7c Bo#XDC oa@c7c Bo#XDC o4ÿ@c7c Bo#XDC oc٪@c7c Bo#XDC o$@c7c Bo#XDC o$“@c7c Bo#XDC odp@c7c Bo#XDC od N>@c7c Bo#XDC oO+c@d8d Bp#YDD p~@d8d Bp#YDD p@d8d Bp#YDD p@d8d Bp#YDD p @d8d Bp#YDD p$;}@d8d Bp#YDD p$jZ@ @d8d Bp#YDD p$7e@d8d Bp#YDD pd@d8d Bp#YDD pd@d8d Bp#YDD p&%@e9e Bq#@YDE qU+@e9e Bq#@YDE q䄉2@e9e Bq#@YDE qfB8@e9e Bq#@YDE qCg>@e9e Bq#@YDE q$!D@e9e Bq#@YDE q$AJ@e9e Bq#@YDE qdpP@e9e Bq#@YDE qdV@e9e Bq#@YDE qΕ]@e9e Bq#@YDE qrDc@f:fBr#YDFr,Pii@f:fBr#YDFr[-o@f:fBr#YDFr u@f:fBr#YDFr${@f:fBr#YDFr$@f:fBr#YDFrd!@f:fBr#YDFrdGF@f:fBr#YDFrv\k@f:fBr#YDFr9@f:fBr#YDFr@g;gBs#YDGs٦@g;gBs#YDGs2@g;gBs#YDGs$b#@g;gBs#YDGs$H@g;gBs#YDGs$hm@g;gBs#YDGsdE@g;gBs#YDGsd#@g;gBs#YDGsM@g;gBs#YDGs|@g;gBs#YDGs䫺%@h<hBt#ZDHtڗJ@h<hBt#ZDHt uo@h<hBt#ZDHt$9R@h<hBt#ZDHt$h/@h<hBt#ZDHtd @h<hBt#ZDHtd@h<hBt#ZDHtd' @h<hBt#ZDHt$L@h<hBt#ZDHtSq@h<hBt#ZDHt^@i=iBu#@ZDIu;!@i=iBu#@ZDIu$'@i=iBu#@ZDIu$.@i=iBu#@ZDIu$?)4@i=iBu#@ZDIudnN:@i=iBu#@ZDIuds@@i=iBu#@ZDIujF@i=iBu#@ZDIuGL@i=iBu#@ZDIu*%R@i=iBu#@ZDIuYY@j>jBv#ZDJv+_@j>jBv#ZDJv$Pe@j>jBv#ZDJv$uk@j>jBv#ZDJvdwq@j>jBv#ZDJvdETw@j>jBv#ZDJvdt1} @j>jBv#ZDJv @j>jBv#ZDJv- @j>jBv#ZDJvR @j>jBv#ZDJv0w @k?kBw#ZDKw_@k?kBw#ZDKw$`@k?kBw#ZDKw$=@k?kBw#ZDKwd @k?kBw#ZDKwd/@k?kBw#ZDKwKT@k?kBw#ZDKwzy@k?kBw#ZDKw@k?kBw#ZDKwl@k?kBw#ZDKwJ@l@lBx$[DLx$7' @l@lBx$[DLx$f2@l@lBx$[DLx$V@l@lBx$[DLxdľ{@l@lBx$[DLxd@l@lBx$[DLx"y@l@lBx$[DLxQV@l@lBx$[DLx3 @l@lBx$[DLx4 !@l@lBx$[DLxX"@ mA mBy$ @[DMy$}#@ mA mBy$ @[DMy$=$@ mA mBy$ @[DMydl#%@ mA mBy$ @[DMydb)&@ mA mBy$ @[DMyd?0'@ mA mBy$ @[DMy66(@ mA mBy$ @[DMy(Z<)@ mA mBy$ @[DMyWB*@ mA mBy$ @[DMy䆴H+@ mA mBy$ @[DMy$N,@ nB nBz$ [DNz$nT-@ nB nBz$ [DNz$L[.@ nB nBz$ [DNzdC)8a/@ nB nBz$ [DNzdr]g0@ nB nBz$ [DNzm1@ nB nBz$ [DNzs2@ nB nBz$ [DNzy3@ nB nBz$ [DNz.{4@ nB nBz$ [DNz]X5@ nB nBz$ [DNz$5:6@ oC oB{$ [DO{$_7@ oC oB{$ [DO{d8@ oC oB{$ [DO{dͨ9@ oC oB{$ [DO{dIͤ:@ oC oB{$ [DO{x;@ oC oB{$ [DO{d<@ oC oB{$ [DO{A<=@ oC oB{$ [DO{a>@ oC oB{$ [DO{$5?@ oC oB{$ [DO{$d٪@@ pD pB|$ \DP|dA@ pD pB|$ \DP|d“B@ pD pB|$ \DP|dpC@ pD pB|$ \DP| N>D@ pD pB|$ \DP|O+cE@ pD pB|$ \DP|~F@ pD pB|$ \DP|G@ pD pB|$ \DP|$H@ pD pB|$ \DP|$ J@ pD pB|$ \DP|$;}K@ qE qB}$ @\DQ}djZ@ L@ qE qB}$ @\DQ}d7eM@ qE qB}$ @\DQ}N@ qE qB}$ @\DQ}O@ qE qB}$ @\DQ}&%P@ qE qB}$ @\DQ}U+Q@ qE qB}$ @\DQ}䄉2R@ qE qB}$ @\DQ}$fB8S@ qE qB}$ @\DQ}$Cg>T@ qE qB}$ @\DQ}d!DU@rFrB~$\DR~dAJV@rFrB~$\DR~dpPW@rFrB~$\DR~VX@rFrB~$\DR~Ε]Y@rFrB~$\DR~rDcZ@rFrB~$\DR~,Pii[@rFrB~$\DR~[-o\@rFrB~$\DR~$ u]@rFrB~$\DR~${^@rFrB~$\DR~d_@sGsB$\DSd!`@sGsB$\DSGFa@sGsB$\DSv\kb@sGsB$\DS9c@sGsB$\DSd@sGsB$\DS٦e@sGsB$\DS$3f@sGsB$\DS$b#g@sGsB$\DS$Hh@sGsB$\DSdhmi@tHtB$]DTdEj@tHtB$]DT#k@tHtB$]DTMl@tHtB$]DT|m@tHtB$]DT䫺%n@tHtB$]DTڗJo@tHtB$]DT$ uop@tHtB$]DT$9Rq@tHtB$]DTdh/r@tHtB$]DTd s@uIuB$@]DUdu@uIuB$@]DU' v@uIuB$@]DU$Lw@uIuB$@]DUSqx@uIuB$@]DU^y@uIuB$@]DU$;!z@uIuB$@]DU$'{@uIuB$@]DU$.|@uIuB$@]DUd?)4}@uIuB$@]DUdnN:~@vJvB$]DVs@@vJvB$]DVjF@vJvB$]DVGL@vJvB$]DV*%R@vJvB$]DVYY@vJvB$]DV$+_@vJvB$]DV$Pe@vJvB$]DVduk@vJvB$]DVdwq@vJvB$]DVdETw@wKwB$]DWt1}@wKwB$]DW @wKwB$]DW-@wKwB$]DWR@wKwB$]DW0w@wKwB$]DW$`@wKwB$]DW$`@wKwB$]DWd=樐@wKwB$]DWd @wKwB$]DW/@xLx B$^DX KT@xLx B$^DX zy@xLx B$^DX 䩏Ǖ@xLx B$^DX l͖@xLx B$^DX $Jӗ@xLx B$^DX $7' ژ@xLx B$^DX $f2@xLx B$^DX dV@xLx B$^DX dľ{@xLx B$^DX @yMy!B$@^DY!"y@yMy!B$@^DY!QV@yMy!B$@^DY!3@yMy!B$@^DY!4 @yMy!B$@^DY!$X@yMy!B$@^DY!$}@yMy!B$@^DY!d=@yMy!B$@^DY!dl#@yMy!B$@^DY!b)@yMy!B$@^DY!?0@zNz"B$^DZ"66@zNz"B$^DZ"(Z<@zNz"B$^DZ"WB@zNz"B$^DZ"$H@zNz"B$^DZ"$N@zNz"B$^DZ"dnT@zNz"B$^DZ"dL[@zNz"B$^DZ"C)8a@zNz"B$^DZ"r]g@zNz"B$^DZ"m@{O{#B$^D[#s@{O{#B$^D[#y@{O{#B$^D[#$/{@{O{#B$^D[#$^X@{O{#B$^D[#$5:@{O{#B$^D[#d_@{O{#B$^D[#d@{O{#B$^D[#ͨ@{O{#B$^D[#Iͤ@{O{#B$^D[#x@|P|$B%_D\$d@|P|$B%_D\$A<@|P|$B%_D\$$a@|P|$B%_D\$$5ÿ@|P|$B%_D\$dd٪@|P|$B%_D\$d@|P|$B%_D\$d“@|P|$B%_D\$p@|P|$B%_D\$ N>@|P|$B%_D\$O+c@}Q}%B%@_D]%~@}Q}%B%@_D]%$@}Q}%B%@_D]%$@}Q}%B%@_D]%$ @}Q}%B%@_D]%d;}@}Q}%B%@_D]%djZ@ @}Q}%B%@_D]%7e@}Q}%B%@_D]%@}Q}%B%@_D]%@}Q}%B%@_D]%&%@~R~&BŠ%_D^&U+@~R~&BŠ%_D^&$2@~R~&BŠ%_D^&$fB8@~R~&BŠ%_D^&dCg>@~R~&BŠ%_D^&d!D@~R~&BŠ%_D^&dAJ@~R~&BŠ%_D^&pP@~R~&BŠ%_D^&V@~R~&BŠ%_D^&Ε]@~R~&BŠ%_D^&rDc@S'BË%_D_',Pii@S'BË%_D_'$\-o@S'BË%_D_'$ u@S'BË%_D_'d{@S'BË%_D_'d@S'BË%_D_'!@S'BË%_D_'GF@S'BË%_D_'v\k@S'BË%_D_'9@S'BË%_D_'@T(BČ%`D`($٦@T(BČ%`D`($3@T(BČ%`D`($b#@T(BČ%`D`(dH@T(BČ%`D`(dhm@T(BČ%`D`(E@T(BČ%`D`(#@T(BČ%`D`(M@T(BČ%`D`(|@T(BČ%`D`(䫺%@U)Bō%@`Da)$ۗJ@U)Bō%@`Da)$ uo@U)Bō%@`Da)d9R@U)Bō%@`Da)dh/@U)Bō%@`Da)d @U)Bō%@`Da)@U)Bō%@`Da)' @U)Bō%@`Da)$L@U)Bō%@`Da)Sq@U)Bō%@`Da)$^@V*BƎ%`Db*$;!@V*BƎ%`Db*$'@V*BƎ%`Db*d.@V*BƎ%`Db*d?)4@V*BƎ%`Db*nN:@V*BƎ%`Db*s@@V*BƎ%`Db*Rf5L# @V*BƎ%`Db*^ @V*BƎ%`Db*rq) @V*BƎ%`Db*- @W+BǏ%`Dc+/ @W+BǏ%`Dc+2\^ @W+BǏ%`Dc+̺5 @W+BǏ%`Dc+2;͸ @W+BǏ%`Dc+"; @W+BǏ%`Dc+R @W+BǏ%`Dc+QB @W+BǏ%`Dc+r @W+BǏ%`Dc+d)H @W+BǏ%`Dc+; @ X ,BȐ% aDd,2ANN @ X ,BȐ% aDd,G` @ X ,BȐ% aDd,2sT @ X ,BȐ% aDd,v @ X ,BȐ% aDd,RZ @ X ,BȐ% aDd,j @ X ,BȐ% aDd,r=ټ` @ X ,BȐ% aDd,G @ X ,BȐ% aDd,lf @ X ,BȐ% aDd,% @!Y!-Bɑ%!@aDe-m @!Y!-Bɑ%!@aDe-23 @!Y!-Bɑ%!@aDe-p+s @!Y!-Bɑ%!@aDe-Rb= @!Y!-Bɑ%!@aDe-MPy @!Y!-Bɑ%!@aDe-rb @!Y!-Bɑ%!@aDe-(+u @!Y!-Bɑ%!@aDe- @!Y!-Bɑ%!@aDe-X @!Y!-Bɑ%!@aDe-v @"Z".Bʒ%"aDf.2律 @"Z".Bʒ%"aDf.T @"Z".Bʒ%"aDf.R @"Z".Bʒ%"aDf.M1 @"Z".Bʒ%"aDf.r @"Z".Bʒ%"aDf.| @"Z".Bʒ%"aDf.r}- @"Z".Bʒ%"aDf.?! @"Z".Bʒ%"aDf.CZR @"Z".Bʒ%"aDf.2d' @#[#/B˓%#aDg/r7w @#[#/B˓%#aDg/R - @#[#/B˓%#aDg/ҡ @#[#/B˓%#aDg/R93 @#[#/B˓%#aDg/ @#[#/B˓%#aDg/rh`9 @#[#/B˓%#aDg/ @#[#/B˓%#aDg/=? @#[#/B˓%#aDg//  @#[#/B˓%#aDg/F @$\$0B̔%$bDh02^/ @$\$0B̔%$bDh0AL @$\$0B̔%$bDh0RfT @$\$0B̔%$bDh0$fR @$\$0B̔%$bDh0rCy @$\$0B̔%$bDh0SX @$\$0B̔%$bDh0  @$\$0B̔%$bDh0^ @$\$0B̔%$bDh0 @$\$0B̔%$bDh02ld @%]%1B͕%%@bDi1I @%]%1B͕%%@bDi1RIj! @%]%1B͕%%@bDi1x ! @%]%1B͕%%@bDi1r'q" @%]%1B͕%%@bDi11" @%]%1B͕%%@bDi1?Dw# @%]%1B͕%%@bDi1rV# @%]%1B͕%%@bDi1nh}$ @%]%1B͕%%@bDi12P{% @%]%1B͕%%@bDi1% @&^&2BΖ%&bDj2R5-& @&^&2BΖ%&bDj2̛& @&^&2BΖ%&bDj2Rd ' @&^&2BΖ%&bDj2x׏' @&^&2BΖ%&bDj2r( @&^&2BΖ%&bDj2+V( @&^&2BΖ%&bDj2) @&^&2BΖ%&bDj22Z3!) @&^&2BΖ%&bDj23* @&^&2BΖ%&bDj22F* @'_'3Bϗ%'bDk3 X%+ @'_'3Bϗ%'bDk3Rj+ @'_'3Bϗ%'bDk3O\}+, @'_'3Bϗ%'bDk3rʏ, @'_'3Bϗ%'bDk3~91- @'_'3Bϗ%'bDk3- @'_'3Bϗ%'bDk37. @'_'3Bϗ%'bDk3Eٺ. @'_'3Bϗ%'bDk32=/ @'_'3Bϗ%'bDk3tb/ @(`(4BИ&(cDl4R D0 @(`(4BИ&(cDl4ң?#0 @(`(4BИ&(cDl4r;5J1 @(`(4BИ&(cDl4H1 @(`(4BИ&(cDl4jZP2 @(`(4BИ&(cDl4l2 @(`(4BИ&(cDl4hV3 @(`(4BИ&(cDl421ב3 @(`(4BИ&(cDl4E\4 @(`(4BИ&(cDl4R`4 @ )a) 5Bљ&)@cD m5"b5 @ )a) 5Bљ&)@cD m5r5 @ )a) 5Bљ&)@cD m5&h6 @ )a) 5Bљ&)@cD m5rn6 @ )a) 5Bљ&)@cD m5Vo7 @ )a) 5Bљ&)@cD m5K%7 @ )a) 5Bљ&)@cD m527u8 @ )a) 5Bљ&)@cD m5)J8 @ )a) 5Bљ&)@cD m5R\{9 @ )a) 5Bљ&)@cD m5Ko9 @ *b* 6BҚ&*cD n6rt: @ *b* 6BҚ&*cD n6z; @ *b* 6BҚ&*cD n6rR; @ *b* 6BҚ&*cD n6 < @ *b* 6BҚ&*cD n6A/ˍ< @ *b* 6BҚ&*cD n62ٝ= @ *b* 6BҚ&*cD n6p = @ *b* 6BҚ&*cD n6R{> @ *b* 6BҚ&*cD n6ҟ> @ *b* 6BҚ&*cD n6R7X'? @ +c+ 7Bӛ&+cD o79? @ +c+ 7Bӛ&+cD o7rf5L#@ @ +c+ 7Bӛ&+cD o7^@ @ +c+ 7Bӛ&+cD o7q)A @ +c+ 7Bӛ&+cD o7-A @ +c+ 7Bӛ&+cD o7/B @ +c+ 7Bӛ&+cD o72\^B @ +c+ 7Bӛ&+cD o7̺5C @ +c+ 7Bӛ&+cD o7R;͸C @ +c+ 7Bӛ&+cD o7";D @ ,d, 8BԜ&,dD p8rD @ ,d, 8BԜ&,dD p8QBE @ ,d, 8BԜ&,dD p8E @ ,d, 8BԜ&,dD p8d)HF @ ,d, 8BԜ&,dD p8;F @ ,d, 8BԜ&,dD p82ANNG @ ,d, 8BԜ&,dD p8G`G @ ,d, 8BԜ&,dD p8RsTH @ ,d, 8BԜ&,dD p8vH @ ,d, 8BԜ&,dD p8rZI @ -e- 9B՝&-@dD q9jI @ -e- 9B՝&-@dD q9=ټ`J @ -e- 9B՝&-@dD q9GJ @ -e- 9B՝&-@dD q9lfK @ -e- 9B՝&-@dD q92%K @ -e- 9B՝&-@dD q9mL @ -e- 9B՝&-@dD q9R3L @ -e- 9B՝&-@dD q9p+sM @ -e- 9B՝&-@dD q9Rb=M @ -e- 9B՝&-@dD q9MPyN @.f.:B֞&.dDr:rbN @.f.:B֞&.dDr:)+uO @.f.:B֞&.dDr:P @.f.:B֞&.dDr:2XP @.f.:B֞&.dDr:vQ @.f.:B֞&.dDr:2律Q @.f.:B֞&.dDr:TR @.f.:B֞&.dDr:RR @.f.:B֞&.dDr:M1S @.f.:B֞&.dDr:rS @/g/;Bן&/dDs;|T @/g/;Bן&/dDs;}-T @/g/;Bן&/dDs;?!U @/g/;Bן&/dDs;CZRU @/g/;Bן&/dDs;2d'V @/g/;Bן&/dDs;r7wV @/g/;Bן&/dDs;R -W @/g/;Bן&/dDs;ҡW @/g/;Bן&/dDs;r93X @/g/;Bן&/dDs;X @0h0<Bؠ&0eDt<h`9Y @0h0<Bؠ&0eDt<Y @0h0<Bؠ&0eDt<=?Z @0h0<Bؠ&0eDt<2/ Z @0h0<Bؠ&0eDt<F[ @0h0<Bؠ&0eDt<R^/[ @0h0<Bؠ&0eDt<AL\ @0h0<Bؠ&0eDt<rfT\ @0h0<Bؠ&0eDt<$fR] @0h0<Bؠ&0eDt<rCy] @1i1=B١&1@eDu=TX^ @1i1=B١&1@eDu= ^ @1i1=B١&1@eDu=2^_ @1i1=B١&1@eDu=_ @1i1=B١&1@eDu=2ld` @1i1=B١&1@eDu=I` @1i1=B١&1@eDu=RIja @1i1=B١&1@eDu=x a @1i1=B١&1@eDu=r'qb @1i1=B١&1@eDu=1b @2j2>Bڢ&2eDv>?Dwc @2j2>Bڢ&2eDv>rVc @2j2>Bڢ&2eDv>nh}d @2j2>Bڢ&2eDv>2P{e @2j2>Bڢ&2eDv>ҝe @2j2>Bڢ&2eDv>R5-f @2j2>Bڢ&2eDv>̛f @2j2>Bڢ&2eDv>rd g @2j2>Bڢ&2eDv>x׏g @2j2>Bڢ&2eDv>h @3k3?Bۣ&3eDw?+Vh @3k3?Bۣ&3eDw?i @3k3?Bۣ&3eDw?2Z3!i @3k3?Bۣ&3eDw?3j @3k3?Bۣ&3eDw?RFj @3k3?Bۣ&3eDw? X%k @3k3?Bۣ&3eDw?rjk @3k3?Bۣ&3eDw?O\}+l @3k3?Bۣ&3eDw?ʏl @3k3?Bۣ&3eDw?91m @4l4@Bܤ&4fDx@m @4l4@Bܤ&4fDx@27n @4l4@Bܤ&4fDx@Eٺn @4l4@Bܤ&4fDx@R=o @4l4@Bܤ&4fDx@tbo @4l4@Bܤ&4fDx@r Dp @4l4@Bܤ&4fDx@?#p @4l4@Bܤ&4fDx@;5Jq @4l4@Bܤ&4fDx@Hq @4l4@Bܤ&4fDx@jZPr @5m5ABݥ &5@fDyA2lr @5m5ABݥ &5@fDyAhVs @5m5ABݥ &5@fDyAR1בs @5m5ABݥ &5@fDyAE\t @5m5ABݥ &5@fDyAR`t @5m5ABݥ &5@fDyA"bu @5m5ABݥ &5@fDyAru @5m5ABݥ &5@fDyA'hv @5m5ABݥ &5@fDyAnv @5m5ABݥ &5@fDyA2Vow @6n6BBަ &6fDzBK%w @6n6BBަ &6fDzB27ux @6n6BBަ &6fDzB)Jx @6n6BBަ &6fDzBR\{y @6n6BBަ &6fDzBKoy @6n6BBަ &6fDzBrtz @6n6BBަ &6fDzBz{ @6n6BBަ &6fDzBR{ @6n6BBަ &6fDzB | @6n6BBަ &6fDzBA/ˍ| @7o7CBߧ &7fD{C2ٝ} @7o7CBߧ &7fD{Cp } @7o7CBߧ &7fD{CR{~ @7o7CBߧ &7fD{Cҟ~ @7o7CBߧ &7fD{Cr7X' @7o7CBߧ &7fD{C9 @7o7CBߧ &7fD{Cf5L# @7o7CBߧ &7fD{C^ @7o7CBߧ &7fD{Cq) @7o7CBߧ &7fD{C2- @8p8DB '8gD|D/ @8p8DB '8gD|DR\^ @8p8DB '8gD|D̺5 @8p8DB '8gD|Dr;͸ @8p8DB '8gD|D"; @8p8DB '8gD|Dr @8p8DB '8gD|DRB @8p8DB '8gD|DŅ @8p8DB '8gD|D2d)H @8p8DB '8gD|D;ˆ @9q9EB '9@gD}E2ANN @9q9EB '9@gD}EG`ч @9q9EB '9@gD}ERsT @9q9EB '9@gD}Ev׈ @9q9EB '9@gD}ErZ @9q9EB '9@gD}Ej݉ @9q9EB '9@gD}E=ټ` @9q9EB '9@gD}EG @9q9EB '9@gD}Elf @9q9EB '9@gD}E2% @:r:FB':gD~Fқm @:r:FB':gD~FR3 @:r:FB':gD~Fp+s @:r:FB':gD~Frb= @:r:FB':gD~FMPy @:r:FB':gD~Fb @:r:FB':gD~F)+u @:r:FB':gD~F @:r:FB':gD~F2X @:r:FB':gD~Fv @;s;GB';gDGR律 @;s;GB';gDGT @;s;GB';gDGr㑒 @;s;GB';gDGM1 @;s;GB';gDGr @;s;GB';gDG} @;s;GB';gDG}- @;s;GB';gDG2?! @;s;GB';gDGCZR @;s;GB';gDGRd' @v>JC'>hDJI @>v>JC'>hDJrIj @>v>JC'>hDJx @>v>JC'>hDJ'q @>v>JC'>hDJ1 @>v>JC'>hDJ?Dw @>v>JC'>hDJ2rV @>v>JC'>hDJnh} @>v>JC'>hDJRP{ @>v>JC'>hDJҝ @?w?KC'?hDKr5- @?w?KC'?hDK̛ @?w?KC'?hDKd @?w?KC'?hDKx׏ @?w?KC'?hDK @?w?KC'?hDK2+V @?w?KC'?hDK @?w?KC'?hDKRZ3! @?w?KC'?hDK3 @?w?KC'?hDKrF @ @x@ LC'@iD L X% @ @x@ LC'@iD Lrj @ @x@ LC'@iD LP\}+ @ @x@ LC'@iD Lʏ @ @x@ LC'@iD L291 @ @x@ LC'@iD L @ @x@ LC'@iD L27 @ @x@ LC'@iD LEٺ @ @x@ LC'@iD LR= @ @x@ LC'@iD Ltb @!AyA!MC'A@iD!Mr D @!AyA!MC'A@iD!M?#ǰ @!AyA!MC'A@iD!M;5J @!AyA!MC'A@iD!MHͱ @!AyA!MC'A@iD!MjZP @!AyA!MC'A@iD!M2lӲ @!AyA!MC'A@iD!MҙhV @!AyA!MC'A@iD!MR1בٳ @!AyA!MC'A@iD!ME\ @!AyA!MC'A@iD!Mr`ߴ @"BzB"NC'BiD"N"b @"BzB"NC'BiD"N @"BzB"NC'BiD"N'h @"BzB"NC'BiD"Nn @"BzB"NC'BiD"N2Vo @"BzB"NC'BiD"NK% @"BzB"NC'BiD"NR7u @"BzB"NC'BiD"N)J @"BzB"NC'BiD"Nr\{ @"BzB"NC'BiD"NKo @#C{C#OC'CiD#Ort @#C{C#OC'CiD#O{ @#C{C#OC'CiD#OR @#C{C#OC'CiD#O2 @#C{C#OC'CiD#OA/ˍ @#C{C#OC'CiD#ORٝ @#C{C#OC'CiD#Op @#C{C#OC'CiD#OR{ @#C{C#OC'CiD#O @#C{C#OC'CiD#Or7X' @$D|D$PC'DjD$P9 @$D|D$PC'DjD$Pf5L# @$D|D$PC'DjD$P^ @$D|D$PC'DjD$Pq) @$D|D$PC'DjD$P2- @$D|D$PC'DjD$P/ @$D|D$PC'DjD$PR\^ @$D|D$PC'DjD$P̺5 @$D|D$PC'DjD$Pr;͸ @$D|D$PC'DjD$P"; @%E}E%Q C'E@jD%Q @%E}E%Q C'E@jD%QRB @%E}E%Q C'E@jD%Q @%E}E%Q C'E@jD%Q2d)H @%E}E%Q C'E@jD%Q; @%E}E%Q C'E@jD%QRANN @%E}E%Q C'E@jD%QG` @%E}E%Q C'E@jD%QrsT @%E}E%Q C'E@jD%Qv @%E}E%Q C'E@jD%QZ @&F~F&R C'FjD&Rj @&F~F&R C'FjD&R=ټ` @&F~F&R C'FjD&R2G @&F~F&R C'FjD&Rlf @&F~F&R C'FjD&RR% @&F~F&R C'FjD&Rқm @&F~F&R C'FjD&RR3 @&F~F&R C'FjD&Rp+s @&F~F&R C'FjD&Rrb= @&F~F&R C'FjD&RMPy @'GG'S C'GjD'Sb @'GG'S C'GjD'S2)+u @'GG'S C'GjD'S @'GG'S C'GjD'S2X @'GG'S C'GjD'Sv @'GG'S C'GjD'SR律 @'GG'S C'GjD'ST @'GG'S C'GjD'Sr @'GG'S C'GjD'SN1 @'GG'S C'GjD'S @(HH(T C(HkD(T2} @(HH(T C(HkD(T}- @(HH(T C(HkD(T2?! @(HH(T C(HkD(TCZR @(HH(T C(HkD(TRd' @(HH(T C(HkD(Tr7w @(HH(T C(HkD(Tr - @(HH(T C(HkD(T @(HH(T C(HkD(T93 @(HH(T C(HkD(T @)II)U C(I@kD)Uh`9 @)II)U C(I@kD)U2 @)II)U C(I@kD)Uҗ=? @)II)U C(I@kD)UR/ @)II)U C(I@kD)UF @)II)U C(I@kD)Ur^/ @)II)U C(I@kD)UAL @)II)U C(I@kD)UfT @)II)U C(I@kD)U%fR @)II)U C(I@kD)UCy @*JJ*VC(JkD*V2TX @*JJ*VC(JkD*V @*JJ*VC(JkD*VR^ @*JJ*VC(JkD*V @*JJ*VC(JkD*Vrld @*JJ*VC(JkD*VI @*JJ*VC(JkD*VrIj @*JJ*VC(JkD*Vy @*JJ*VC(JkD*V'q @*JJ*VC(JkD*V21 @+KK+WC(KkD+W?Dw @+KK+WC(KkD+WRrV @+KK+WC(KkD+Wnh} @+KK+WC(KkD+WRP{ @+KK+WC(KkD+W򝾍 @+KK+WC(KkD+Wr5- @+KK+WC(KkD+W͛ @+KK+WC(KkD+Wd @+KK+WC(KkD+Wx׏ @+KK+WC(KkD+W @,LL,XC (LlD,X2+V @,LL,XC (LlD,X @,LL,XC (LlD,XRZ3! @,LL,XC (LlD,X3 @,LL,XC (LlD,XrF @,LL,XC (LlD,X X% @,LL,XC (LlD,Xj @,LL,XC (LlD,XP\}+ @,LL,XC (LlD,Xʏ @,LL,XC (LlD,X291 @-MM-YC!(M@lD-Y @-MM-YC!(M@lD-YR7 @-MM-YC!(M@lD-YEٺ @-MM-YC!(M@lD-Yr= @-MM-YC!(M@lD-Ytb @-MM-YC!(M@lD-Y D @-MM-YC!(M@lD-Y?# @-MM-YC!(M@lD-Y;5J @-MM-YC!(M@lD-Y2H @-MM-YC!(M@lD-YjZP @.NN.ZC"(NlD.ZRl @.NN.ZC"(NlD.ZҙhV @.NN.ZC"(NlD.ZR1ב @.NN.ZC"(NlD.ZE\ @.NN.ZC"(NlD.Zr` @.NN.ZC"(NlD.Z"b @.NN.ZC"(NlD.Z @.NN.ZC"(NlD.Z2'h @.NN.ZC"(NlD.Zn @.NN.ZC"(NlD.Z2Vo @/OO/[C#(OlD/[K% @/OO/[C#(OlD/[R7u @/OO/[C#(OlD/[)J @/OO/[C#(OlD/[r\{ @/OO/[C#(OlD/[Ko @/OO/[C#(OlD/[t @/OO/[C#(OlD/[{ @/OO/[C#(OlD/[R @/OO/[C#(OlD/[2 @/OO/[C#(OlD/[A/ˍ @0PP0\C$(PmD0\Rٝ @0PP0\C$(PmD0\p @0PP0\C$(PmD0\r{ @0PP0\C$(PmD0\ @0PP0\C$(PmD0\7X' @0PP0\C$(PmD0\9 @0PP0\C$(PmD0\f5L#!@0PP0\C$(PmD0\2^!@0PP0\C$(PmD0\q)!@0PP0\C$(PmD0\R-!@1QQ1]C%(Q@mD1]/!@1QQ1]C%(Q@mD1]r\^!@1QQ1]C%(Q@mD1]̺5!@1QQ1]C%(Q@mD1]r;͸!@1QQ1]C%(Q@mD1]#;!@1QQ1]C%(Q@mD1]!@1QQ1]C%(Q@mD1]2RB!@1QQ1]C%(Q@mD1]!@1QQ1]C%(Q@mD1]Rd)H!@1QQ1]C%(Q@mD1];!@2RR2^C&(RmD2^rANN!@2RR2^C&(RmD2^G`!@2RR2^C&(RmD2^rsT!@2RR2^C&(RmD2^w!@2RR2^C&(RmD2^Z !@2RR2^C&(RmD2^2j !@2RR2^C&(RmD2^=ټ` !@2RR2^C&(RmD2^RG !@2RR2^C&(RmD2^lf !@2RR2^C&(RmD2^R% !@3SS3_C'(SmD3_m !@3SS3_C'(SmD3_r3 !@3SS3_C'(SmD3_p+s !@3SS3_C'(SmD3_b= !@3SS3_C'(SmD3_MPy!@3SS3_C'(SmD3_b!@3SS3_C'(SmD3_2)+u!@3SS3_C'(SmD3_!@3SS3_C'(SmD3_RX!@3SS3_C'(SmD3_v!@4TT4`C((TnD4`r律!@4TT4`C((TnD4`T!@4TT4`C((TnD4`!@4TT4`C((TnD4`N1!@4TT4`C((TnD4`!@4TT4`C((TnD4`2}!@4TT4`C((TnD4`}-!@4TT4`C((TnD4`R?!!@4TT4`C((TnD4`CZR!@4TT4`C((TnD4`rd'!@5UU5aC)(U@nD5ar7w!@5UU5aC)(U@nD5a -!@5UU5aC)(U@nD5a!@5UU5aC)(U@nD5a93!@5UU5aC)(U@nD5a2!@5UU5aC)(U@nD5ah`9!@5UU5aC)(U@nD5aR!@5UU5aC)(U@nD5aҗ=?!@5UU5aC)(U@nD5aR/ !@5UU5aC)(U@nD5aF!@6VV6bC*(VnD6br^/!@6VV6bC*(VnD6bAL!@6VV6bC*(VnD6bfT!@6VV6bC*(VnD6b2%fR!@6VV6bC*(VnD6bCy!@6VV6bC*(VnD6b2TX!@6VV6bC*(VnD6b !@6VV6bC*(VnD6bR^!@6VV6bC*(VnD6b!@6VV6bC*(VnD6brld !@7WW7cC+(WnD7cI !@7WW7cC+(WnD7cIj!!@7WW7cC+(WnD7cy !!@7WW7cC+(WnD7c'q"!@7WW7cC+(WnD7c21"!@7WW7cC+(WnD7c?Dw#!@7WW7cC+(WnD7cRrV#!@7WW7cC+(WnD7cnh}$!@7WW7cC+(WnD7crP{%!@7WW7cC+(WnD7c򝾍%!@8XX8dC,)XoD8d5-&!@8XX8dC,)XoD8d͛&!@8XX8dC,)XoD8dd '!@8XX8dC,)XoD8d2x׏'!@8XX8dC,)XoD8d(!@8XX8dC,)XoD8dR+V(!@8XX8dC,)XoD8d)!@8XX8dC,)XoD8drZ3!)!@8XX8dC,)XoD8d3*!@8XX8dC,)XoD8drF*!@9YY9eC-)Y@oD9e!X%+!@9YY9eC-)Y@oD9ej+!@9YY9eC-)Y@oD9e2P\}+,!@9YY9eC-)Y@oD9eʏ,!@9YY9eC-)Y@oD9e291-!@9YY9eC-)Y@oD9e-!@9YY9eC-)Y@oD9eR7.!@9YY9eC-)Y@oD9eEٺ.!@9YY9eC-)Y@oD9er=/!@9YY9eC-)Y@oD9eub/!@:ZZ:fC.)ZoD:f D0!@:ZZ:fC.)ZoD:f?#0!@:ZZ:fC.)ZoD:f;5J1!@:ZZ:fC.)ZoD:f2H1!@:ZZ:fC.)ZoD:fjZP2!@:ZZ:fC.)ZoD:fRl2!@:ZZ:fC.)ZoD:fҙhV3!@:ZZ:fC.)ZoD:fr1ב3!@:ZZ:fC.)ZoD:fE\4!@:ZZ:fC.)ZoD:f`4!@;[[;gC/)[oD;g"b5!@;[[;gC/)[oD;g5!@;[[;gC/)[oD;g2'h6!@;[[;gC/)[oD;gn6!@;[[;gC/)[oD;gRVo7!@;[[;gC/)[oD;gK%7!@;[[;gC/)[oD;gr7u8!@;[[;gC/)[oD;g)J8!@;[[;gC/)[oD;g\{9!@;[[;gC/)[oD;gLo9!@<\\!@<\\!@<\\^–^>j"C2)^pD>jD!@>^–^>j"C2)^pD>j2RBE!@>^–^>j"C2)^pD>jE!@>^–^>j"C2)^pD>jRd)HF!@>^–^>j"C2)^pD>j;F!@>^–^>j"C2)^pD>jrANNG!@>^–^>j"C2)^pD>jG`G!@>^–^>j"C2)^pD>jsTH!@>^–^>j"C2)^pD>jwH!@>^–^>j"C2)^pD>jZI!@?_×_?k#C3)_pD?k2jI!@?_×_?k#C3)_pD?k=ټ`J!@?_×_?k#C3)_pD?kRGJ!@?_×_?k#C3)_pD?klfK!@?_×_?k#C3)_pD?kr%K!@?_×_?k#C3)_pD?kmL!@?_×_?k#C3)_pD?k3L!@?_×_?k#C3)_pD?kp+sM!@?_×_?k#C3)_pD?kb=M!@?_×_?k#C3)_pD?k2MPyN!@@`Ę`@l$C4)`qD@lbN!@@`Ę`@l$C4)`qD@lR)+uO!@@`Ę`@l$C4)`qD@lP!@@`Ę`@l$C4)`qD@lrXP!@@`Ę`@l$C4)`qD@lvQ!@@`Ę`@l$C4)`qD@lr律Q!@@`Ę`@l$C4)`qD@lTR!@@`Ę`@l$C4)`qD@lR!@@`Ę`@l$C4)`qD@l2N1S!@@`Ę`@l$C4)`qD@lS!@AařaAm%C 5)a@qDA m2}T!@AařaAm%C 5)a@qDA m}-T!@AařaAm%C 5)a@qDA mR?!U!@AařaAm%C 5)a@qDA mCZRU!@AařaAm%C 5)a@qDA mrd'V!@AařaAm%C 5)a@qDA ms7wV!@AařaAm%C 5)a@qDA m -W!@AařaAm%C 5)a@qDA mW!@AařaAm%C 5)a@qDA m93X!@AařaAm%C 5)a@qDA m2X!@BbƚbBn&C 6)bqDB nh`9Y!@BbƚbBn&C 6)bqDB nRY!@BbƚbBn&C 6)bqDB nҗ=?Z!@BbƚbBn&C 6)bqDB nr/ Z!@BbƚbBn&C 6)bqDB nF[!@BbƚbBn&C 6)bqDB n^/[!@BbƚbBn&C 6)bqDB nAL\!@BbƚbBn&C 6)bqDB nfT\!@BbƚbBn&C 6)bqDB n2%fR]!@BbƚbBn&C 6)bqDB nCy]!@CcǛcCo'C 7)cqDC oRTX^!@CcǛcCo'C 7)cqDC o ^!@CcǛcCo'C 7)cqDC or^_!@CcǛcCo'C 7)cqDC o_!@CcǛcCo'C 7)cqDC orld`!@CcǛcCo'C 7)cqDC oJ`!@CcǛcCo'C 7)cqDC oIja!@CcǛcCo'C 7)cqDC o2y a!@CcǛcCo'C 7)cqDC o'qb!@CcǛcCo'C 7)cqDC oR1b!@DdȜdDp(C 8)drDD p?Dwc!@DdȜdDp(C 8)drDD pRrVc!@DdȜdDp(C 8)drDD pnh}d!@DdȜdDp(C 8)drDD prP{e!@DdȜdDp(C 8)drDD pe!@DdȜdDp(C 8)drDD p5-f!@DdȜdDp(C 8)drDD p͛f!@DdȜdDp(C 8)drDD pd g!@DdȜdDp(C 8)drDD p2x׏g!@DdȜdDp(C 8)drDD pғh!@EeɝeEq)C 9)e@rDE qR+Vh!@EeɝeEq)C 9)e@rDE qi!@EeɝeEq)C 9)e@rDE qrZ3!i!@EeɝeEq)C 9)e@rDE q3j!@EeɝeEq)C 9)e@rDE qFj!@EeɝeEq)C 9)e@rDE q!X%k!@EeɝeEq)C 9)e@rDE qjk!@EeɝeEq)C 9)e@rDE q2P\}+l!@EeɝeEq)C 9)e@rDE qʏl!@EeɝeEq)C 9)e@rDE qR91m!@FfʞfFr*C:)frDFrm!@FfʞfFr*C:)frDFrr7n!@FfʞfFr*C:)frDFrEٺn!@FfʞfFr*C:)frDFr=o!@FfʞfFr*C:)frDFrubo!@FfʞfFr*C:)frDFr Dp!@FfʞfFr*C:)frDFr2?#p!@FfʞfFr*C:)frDFr;5Jq!@FfʞfFr*C:)frDFrRHq!@FfʞfFr*C:)frDFrjZPr!@Gg˟gGs+C;)grDGsrlr!@Gg˟gGs+C;)grDGshVs!@Gg˟gGs+C;)grDGs1בs!@Gg˟gGs+C;)grDGsE\t!@Gg˟gGs+C;)grDGs`t!@Gg˟gGs+C;)grDGs2"bu!@Gg˟gGs+C;)grDGsu!@Gg˟gGs+C;)grDGsR'hv!@Gg˟gGs+C;)grDGsҾnv!@Gg˟gGs+C;)grDGsrVow!@Hh̠hHt,C<*hsDHtK%w!@Hh̠hHt,C<*hsDHtr7ux!@Hh̠hHt,C<*hsDHt)Jx!@Hh̠hHt,C<*hsDHt\{y!@Hh̠hHt,C<*hsDHt2Loy!@Hh̠hHt,C<*hsDHttz!@Hh̠hHt,C<*hsDHt2{{!@Hh̠hHt,C<*hsDHtR{!@Hh̠hHt,C<*hsDHtR |!@Hh̠hHt,C<*hsDHtA/ˍ|!@Ii͡iIu-C=*i@sDIurٝ}!@Ii͡iIu-C=*i@sDIuq }!@Ii͡iIu-C=*i@sDIu{~!@Ii͡iIu-C=*i@sDIu~!@Ii͡iIu-C=*i@sDIu7X'!@Ii͡iIu-C=*i@sDIu29!@Ii͡iIu-C=*i@sDIuf5L#!@Ii͡iIu-C=*i@sDIuR^!@Ii͡iIu-C=*i@sDIuҕq)!@Ii͡iIu-C=*i@sDIur-!@Jj΢jJv.C>*jsDJv/!@Jj΢jJv.C>*jsDJv\^!@Jj΢jJv.C>*jsDJv̺5!@Jj΢jJv.C>*jsDJv;͸!@Jj΢jJv.C>*jsDJv2#;!@Jj΢jJv.C>*jsDJv!@Jj΢jJv.C>*jsDJvRRB!@Jj΢jJv.C>*jsDJvŅ!@Jj΢jJv.C>*jsDJvrd)H!@Jj΢jJv.C>*jsDJv;ˆ!@KkϣkKw/C?*ksDKwrANN!@KkϣkKw/C?*ksDKwH`ч!@KkϣkKw/C?*ksDKwsT!@KkϣkKw/C?*ksDKw2w׈!@KkϣkKw/C?*ksDKwZ!@KkϣkKw/C?*ksDKwRj݉!@KkϣkKw/C?*ksDKw=ټ`!@KkϣkKw/C?*ksDKwRG!@KkϣkKw/C?*ksDKwlf!@KkϣkKw/C?*ksDKwr%!@LlФlLx0C@*ltDLxm!@LlФlLx0C@*ltDLx3!@LlФlLx0C@*ltDLxp+s!@LlФlLx0C@*ltDLxb=!@LlФlLx0C@*ltDLx2MPy!@LlФlLx0C@*ltDLxґb!@LlФlLx0C@*ltDLxR)+u!@LlФlLx0C@*ltDLx!@LlФlLx0C@*ltDLxrX!@LlФlLx0C@*ltDLxv!@Mmѥ mMy1CA* m@tDMy律!@Mmѥ mMy1CA* m@tDMyT!@Mmѥ mMy1CA* m@tDMy㑒!@Mmѥ mMy1CA* m@tDMy2N1!@Mmѥ mMy1CA* m@tDMy!@Mmѥ mMy1CA* m@tDMyR}!@Mmѥ mMy1CA* m@tDMy}-!@Mmѥ mMy1CA* m@tDMyr?!!@Mmѥ mMy1CA* m@tDMyCZR!@Mmѥ mMy1CA* m@tDMyd'!@NnҦ nNz2CB* ntDNzs7w!@NnҦ nNz2CB* ntDNz -!@NnҦ nNz2CB* ntDNz2!@NnҦ nNz2CB* ntDNz93!@NnҦ nNz2CB* ntDNzR!@NnҦ nNz2CB* ntDNzh`9!@NnҦ nNz2CB* ntDNzR弙!@NnҦ nNz2CB* ntDNz=?!@NnҦ nNz2CB* ntDNzr/ Ú!@NnҦ nNz2CB* ntDNzF!@Ooӧ oO{3CC* otDO{^/ɛ!@Ooӧ oO{3CC* otDO{2AL!@Ooӧ oO{3CC* otDO{fTϜ!@Ooӧ oO{3CC* otDO{2%fR!@Ooӧ oO{3CC* otDO{ҼCy՝!@Ooӧ oO{3CC* otDO{RTX!@Ooӧ oO{3CC* otDO{ ۞!@Ooӧ oO{3CC* otDO{r^!@Ooӧ oO{3CC* otDO{!@Ooӧ oO{3CC* otDO{ld!@PpԨ pP|4CD* puDP|2J!@PpԨ pP|4CD* puDP|Ij!@PpԨ pP|4CD* puDP|2y !@PpԨ pP|4CD* puDP|'q!@PpԨ pP|4CD* puDP|R1!@PpԨ pP|4CD* puDP|?Dw!@PpԨ pP|4CD* puDP|rrV!@PpԨ pP|4CD* puDP|oh}!@PpԨ pP|4CD* puDP|P{!@PpԨ pP|4CD* puDP|!@Qqթ qQ}5CE* q@uDQ}5-!@Qqթ qQ}5CE* q@uDQ}2͛!@Qqթ qQ}5CE* q@uDQ}d !@Qqթ qQ}5CE* q@uDQ}Rx׏!@Qqթ qQ}5CE* q@uDQ}ғ!@Qqթ qQ}5CE* q@uDQ}r+V!@Qqթ qQ}5CE* q@uDQ}!@Qqթ qQ}5CE* q@uDQ}Z3!!@Qqթ qQ}5CE* q@uDQ}3!@Qqթ qQ}5CE* q@uDQ}F!@Rr֪rR~6CF*ruDR~2!X%!@Rr֪rR~6CF*ruDR~j!@Rr֪rR~6CF*ruDR~RP\}+!@Rr֪rR~6CF*ruDR~ʏ!@Rr֪rR~6CF*ruDR~r91!@Rr֪rR~6CF*ruDR~!@Rr֪rR~6CF*ruDR~r7!@Rr֪rR~6CF*ruDR~Fٺ!@Rr֪rR~6CF*ruDR~=!@Rr֪rR~6CF*ruDR~2ub!@Ss׫sS7CG*suDS D!@Ss׫sS7CG*suDSR?#ǰ!@Ss׫sS7CG*suDS;5J!@Ss׫sS7CG*suDSRHͱ!@Ss׫sS7CG*suDSjZP!@Ss׫sS7CG*suDSrlӲ!@Ss׫sS7CG*suDShV!@Ss׫sS7CG*suDS1בٳ!@Ss׫sS7CG*suDSE\!@Ss׫sS7CG*suDS`ߴ!@TtجtT8CH*tvDT2"b!@TtجtT8CH*tvDTҏ!@TtجtT8CH*tvDTR'h!@TtجtT8CH*tvDTn!@TtجtT8CH*tvDTrVo!@TtجtT8CH*tvDTK%!@TtجtT8CH*tvDT7u!@TtجtT8CH*tvDT)J!@TtجtT8CH*tvDT\{!@TtجtT8CH*tvDT2Lo!@Uu٭uU9CI*u@vDUt!@Uu٭uU9CI*u@vDUR{!@Uu٭uU9CI*u@vDUR!@Uu٭uU9CI*u@vDUr !@Uu٭uU9CI*u@vDUA/ˍ!@Uu٭uU9CI*u@vDUٝ!@Uu٭uU9CI*u@vDUq !@Uu٭uU9CI*u@vDU{!@Uu٭uU9CI*u@vDU2!@Uu٭uU9CI*u@vDU7X'!@VvڮvV:CJ*vvDVR9!@VvڮvV:CJ*vvDVf5L#!@VvڮvV:CJ*vvDVR^!@VvڮvV:CJ*vvDVq)!@VvڮvV:CJ*vvDVr-!@VvڮvV:CJ*vvDV/!@VvڮvV:CJ*vvDV\^!@VvڮvV:CJ*vvDV2̺5!@VvڮvV:CJ*vvDV;͸!@VvڮvV:CJ*vvDV2#;!@WwۯwW;CK*wvDWҺ!@WwۯwW;CK*wvDWRRB!@WwۯwW;CK*wvDW!@WwۯwW;CK*wvDWrd)H!@WwۯwW;CK*wvDW;!@WwۯwW;CK*wvDWANN!@WwۯwW;CK*wvDWH`!@WwۯwW;CK*wvDWsT!@WwۯwW;CK*wvDW2w!@WwۯwW;CK*wvDWZ!@XxܰxXC"N+zwDZ"r}!@Zz޲zZ>C"N+zwDZ"}-!@Zz޲zZ>C"N+zwDZ"r?!!@Zz޲zZ>C"N+zwDZ"DZR!@Zz޲zZ>C"N+zwDZ"d'!@Zz޲zZ>C"N+zwDZ"2s7w!@Zz޲zZ>C"N+zwDZ" -!@Zz޲zZ>C"N+zwDZ"R!@Zz޲zZ>C"N+zwDZ"93!@Zz޲zZ>C"N+zwDZ"R!@[{߳{[?C#O+{wD[#h`9!@[{߳{[?C#O+{wD[#r!@[{߳{[?C#O+{wD[#=?!@[{߳{[?C#O+{wD[#/ !@[{߳{[?C#O+{wD[#F!@[{߳{[?C#O+{wD[#^/!@[{߳{[?C#O+{wD[#2AL!@[{߳{[?C#O+{wD[#ҍfT!@[{߳{[?C#O+{wD[#R%fR!@[{߳{[?C#O+{wD[#Cy!@\||\@C$P+|xD\$rTX!@\||\@C$P+|xD\$ !@\||\@C$P+|xD\$^!@\||\@C$P+|xD\$!@\||\@C$P+|xD\$ld!@\||\@C$P+|xD\$2J!@\||\@C$P+|xD\$Ij!@\||\@C$P+|xD\$Ry !@\||\@C$P+|xD\$'q!@\||\@C$P+|xD\$r1!@]}}]AC%Q+}@xD]%?Dw!@]}}]AC%Q+}@xD]%rV!@]}}]AC%Q+}@xD]%oh}!@]}}]AC%Q+}@xD]%P{!@]}}]AC%Q+}@xD]%2!@]}}]AC%Q+}@xD]%5-!@]}}]AC%Q+}@xD]%R͛!@]}}]AC%Q+}@xD]%d !@]}}]AC%Q+}@xD]%Rx׏!@]}}]AC%Q+}@xD]%!@^~~^BC&R+~xD^&r+V!@^~~^BC&R+~xD^&!@^~~^BC&R+~xD^&Z3!!@^~~^BC&R+~xD^&23!@^~~^BC&R+~xD^&F!@^~~^BC&R+~xD^&2!X%!@^~~^BC&R+~xD^&Ҹj!@^~~^BC&R+~xD^&RP\}+!@^~~^BC&R+~xD^&ʏ!@^~~^BC&R+~xD^&r91!@__CC'S+xD_'!@__CC'S+xD_'7!@__CC'S+xD_'Fٺ!@__CC'S+xD_'=!@__CC'S+xD_'2ub!@__CC'S+xD_' D!@__CC'S+xD_'R?#!@__CC'S+xD_';5J!@__CC'S+xD_'rH!@__CC'S+xD_'jZP!@``DC(T+yD`(l!@``DC(T+yD`(hV!@``DC(T+yD`(1ב!@``DC(T+yD`(2E\!@``DC(T+yD`(`!@``DC(T+yD`(R"b!@``DC(T+yD`(ҏ!@``DC(T+yD`(r'h!@``DC(T+yD`(n!@``DC(T+yD`(rVo!@aaEC)U+@yDa)K%!@aaEC)U+@yDa)7u!@aaEC)U+@yDa)2)J!@aaEC)U+@yDa)\{!@aaEC)U+@yDa)2Lo!@aaEC)U+@yDa)t!@aaEC)U+@yDa)R{!@aaEC)U+@yDa)R!@aaEC)U+@yDa)r !@aaEC)U+@yDa)B/ˍ!@bbFC*V+yDb*ٝ!@bbFC*V+yDb*q !@bbFC*V+yDb*{!@bbFC*V+yDb*2!@bbFC*V+yDb*7X'!@bbFC*V+yDb*R9!@bbFC*V+yDb*f5L#"@bbFC*V+yDb*r^"@bbFC*V+yDb*q)"@bbFC*V+yDb*-"@ccGC+W+yDc+/"@ccGC+W+yDc+\^"@ccGC+W+yDc+2̺5"@ccGC+W+yDc+;͸"@ccGC+W+yDc+R#;"@ccGC+W+yDc+Һ"@ccGC+W+yDc+rRB"@ccGC+W+yDc+"@ccGC+W+yDc+d)H"@ccGC+W+yDc+;"@d dHC,X+ d,ANN"@d dHC,X+ d,2H`"@d dHC,X+ d,sT"@d dHC,X+ d,Rw"@d dHC,X+ d,Z "@d dHC,X+ d,rj "@d dHC,X+ d,=ټ` "@d dHC,X+ d,G "@d dHC,X+ d,mf "@d dHC,X+ d,% "@e!eIC-Y+!?e-2m "@e!eIC-Y+!?e-3 "@e!eIC-Y+!?e-Rp+s "@e!eIC-Y+!?e-b= "@e!eIC-Y+!?e-RMPy"@e!eIC-Y+!?e-b"@e!eIC-Y+!?e-r)+u"@e!eIC-Y+!?e-"@e!eIC-Y+!?e-X"@e!eIC-Y+!?e-2v"@f"fJC.Z+"@f.律"@f"fJC.Z+"@f.2T"@f"fJC.Z+"@f.Ҷ"@f"fJC.Z+"@f.RN1"@f"fJC.Z+"@f."@f"fJC.Z+"@f.r}"@f"fJC.Z+"@f.}-"@f"fJC.Z+"@f.?!"@f"fJC.Z+"@f.DZR"@f"fJC.Z+"@f.d'"@g#gKC/[+#@@g/2s7w"@g#gKC/[+#@@g/ -"@g#gKC/[+#@@g/R"@g#gKC/[+#@@g/93"@g#gKC/[+#@@g/r"@g#gKC/[+#@@g/h`9"@g#gKC/[+#@@g/"@g#gKC/[+#@@g/=?"@g#gKC/[+#@@g// "@g#gKC/[+#@@g/2F"@h$hLC0\,$@h0^/"@h$hLC0\,$@h0RAL"@h$hLC0\,$@h0ҍfT"@h$hLC0\,$@h0r%fR"@h$hLC0\,$@h0Cy"@h$hLC0\,$@h0rTX"@h$hLC0\,$@h0 "@h$hLC0\,$@h0^"@h$hLC0\,$@h02"@h$hLC0\,$@h0ld "@i%iMC1],%@i12J "@i%iMC1],%@i1Ij!"@i%iMC1],%@i1Ry !"@i%iMC1],%@i1'q""@i%iMC1],%@i1r1""@i%iMC1],%@i1@Dw#"@i%iMC1],%@i1rV#"@i%iMC1],%@i1oh}$"@i%iMC1],%@i1P{%"@i%iMC1],%@i12%"@j&jNC2^,&@j25-&"@j&jNC2^,&@j2R͛&"@j&jNC2^,&@j2d '"@j&jNC2^,&@j2rx׏'"@j&jNC2^,&@j2("@j&jNC2^,&@j2+V("@j&jNC2^,&@j2)"@j&jNC2^,&@j2Z3!)"@j&jNC2^,&@j223*"@j&jNC2^,&@j2F*"@k'kOC3_,'@k3R!X%+"@k'kOC3_,'@k3Ҹj+"@k'kOC3_,'@k3rP\}+,"@k'kOC3_,'@k3ʏ,"@k'kOC3_,'@k3r91-"@k'kOC3_,'@k3-"@k'kOC3_,'@k37."@k'kOC3_,'@k32Fٺ."@k'kOC3_,'@k3=/"@k'kOC3_,'@k3Rub/"@l(lPC4`,(Al4 D0"@l(lPC4`,(Al4R?#0"@l(lPC4`,(Al4;5J1"@l(lPC4`,(Al4rH1"@l(lPC4`,(Al4kZP2"@l(lPC4`,(Al4l2"@l(lPC4`,(Al4hV3"@l(lPC4`,(Al41ב3"@l(lPC4`,(Al42E\4"@l(lPC4`,(Al4`4"@m ) mQC5a,)Am5R"b5"@m ) mQC5a,)Am55"@m ) mQC5a,)Am5r'h6"@m ) mQC5a,)Am5n6"@m ) mQC5a,)Am5Vo7"@m ) mQC5a,)Am5K%7"@m ) mQC5a,)Am57u8"@m ) mQC5a,)Am52)J8"@m ) mQC5a,)Am5Ҵ\{9"@m ) mQC5a,)Am5RLo9"@n * nRC6b,* An6t:"@n * nRC6b,* An6r{;"@n * nRC6b,* An6R;"@n * nRC6b,* An6 <"@n * nRC6b,* An6B/ˍ<"@n * nRC6b,* An6ٝ="@n * nRC6b,* An62q ="@n * nRC6b,* An6{>"@n * nRC6b,* An6R>"@n * nRC6b,* An67X'?"@o + oSC7c,+0Ao7r9?"@o + oSC7c,+0Ao7f5L#@"@o + oSC7c,+0Ao7^@"@o + oSC7c,+0Ao7q)A"@o + oSC7c,+0Ao7-A"@o + oSC7c,+0Ao72/B"@o + oSC7c,+0Ao7\^B"@o + oSC7c,+0Ao7R̺5C"@o + oSC7c,+0Ao7ҋ;͸C"@o + oSC7c,+0Ao7r#;D"@p , pTC8d,,@Ap8D"@p , pTC8d,,@Ap8rRBE"@p , pTC8d,,@Ap8E"@p , pTC8d,,@Ap8d)HF"@p , pTC8d,,@Ap82;F"@p , pTC8d,,@Ap8ANNG"@p , pTC8d,,@Ap82H`G"@p , pTC8d,,@Ap8sTH"@p , pTC8d,,@Ap8RwH"@p , pTC8d,,@Ap8ZI"@q - qUC9e,-PAq9rjI"@q - qUC9e,-PAq9>ټ`J"@q - qUC9e,-PAq9GJ"@q - qUC9e,-PAq9mfK"@q - qUC9e,-PAq9%K"@q - qUC9e,-PAq92mL"@q - qUC9e,-PAq93L"@q - qUC9e,-PAq9Rp+sM"@q - qUC9e,-PAq9b=M"@q - qUC9e,-PAq9rMPyN"@r.rVC:f,.`Ar:bN"@r.rVC:f,.`Ar:)+uO"@r.rVC:f,.`Ar:P"@r.rVC:f,.`Ar:XP"@r.rVC:f,.`Ar:2vQ"@r.rVC:f,.`Ar:律Q"@r.rVC:f,.`Ar:RTR"@r.rVC:f,.`Ar:ҶR"@r.rVC:f,.`Ar:rN1S"@r.rVC:f,.`Ar:S"@s/sWC;g,/pAs;r}T"@s/sWC;g,/pAs;}-T"@s/sWC;g,/pAs;?!U"@s/sWC;g,/pAs;2DZRU"@s/sWC;g,/pAs;d'V"@s/sWC;g,/pAs;Rs7wV"@s/sWC;g,/pAs; -W"@s/sWC;g,/pAs;RW"@s/sWC;g,/pAs;93X"@s/sWC;g,/pAs;rX"@t0tXC<h,0At<i`9Y"@t0tXC<h,0At<Y"@t0tXC<h,0At<=?Z"@t0tXC<h,0At</ Z"@t0tXC<h,0At<2F["@t0tXC<h,0At<^/["@t0tXC<h,0At<RAL\"@t0tXC<h,0At<fT\"@t0tXC<h,0At<r%fR]"@t0tXC<h,0At<Cy]"@u1uYC=i,1Au=TX^"@u1uYC=i,1Au= ^"@u1uYC=i,1Au=^_"@u1uYC=i,1Au=2_"@u1uYC=i,1Au=ld`"@u1uYC=i,1Au=RJ`"@u1uYC=i,1Au=Ija"@u1uYC=i,1Au=ry a"@u1uYC=i,1Au='qb"@u1uYC=i,1Au=1b"@v2vZC>j,2Av>@Dwc"@v2vZC>j,2Av>rVc"@v2vZC>j,2Av>2oh}d"@v2vZC>j,2Av>P{e"@v2vZC>j,2Av>Re"@v2vZC>j,2Av>5-f"@v2vZC>j,2Av>R͛f"@v2vZC>j,2Av>d g"@v2vZC>j,2Av>rx׏g"@v2vZC>j,2Av>h"@w3w[C?k,3Aw?+Vh"@w3w[C?k,3Aw?2i"@w3w[C?k,3Aw?Z3!i"@w3w[C?k,3Aw?23j"@w3w[C?k,3Aw?҉Fj"@w3w[C?k,3Aw?R!X%k"@w3w[C?k,3Aw?jk"@w3w[C?k,3Aw?rP\}+l"@w3w[C?k,3Aw?ݏl"@w3w[C?k,3Aw?Ul1m"@x4x\C@l-4Ax@r m"@x4x\C@l-4Ax@7n"@x4x\C@l-4Ax@xںn"@x4x\C@l-4Ax@2=o"@x4x\C@l-4Ax@R5o"@x4x\C@l-4Ax@ҫDp"@x4x\C@l-4Ax@jS$p"@x4x\C@l-4Ax@,6Jq"@x4x\C@l-4Ax@pIq"@x4x\C@l-4Ax@R[Pr"@y5y]CA m-5AyA ynr"@y5y]CA m-5AyA AVs"@y5y]CA m-5AyA  s"@y5y]CA m-5AyA :\t"@y5y]CA m-5AyA 2ɸt"@y5y]CA m-5AyA tXbu"@y5y]CA m-5AyA Eu"@y5y]CA m-5AyA vhv"@y5y]CA m-5AyA 2v"@y5y]CA m-5AyA Óow"@z6z^CB n-6AzB "(w"@z6z^CB n-6AzB u:ux"@z6z^CB n-6AzB Q@Mx"@z6z^CB n-6AzB R/_{y"@z6z^CB n-6AzB ^ry"@z6z^CB n-6AzB 섁z"@z6z^CB n-6AzB {{"@z6z^CB n-6AzB  {"@z6z^CB n-6AzB 2 |"@z6z^CB n-6AzB (ύ|"@{7{_CC o-7A{C p}"@{7{_CC o-7A{C \F}"@{7{_CC o-7A{C RJ~"@{7{_CC o-7A{C 9d~"@{7{_CC o-7A{C ++"@{7{_CC o-7A{C >"@{7{_CC o-7A{C Q#"@{7{_CC o-7A{C r c"@{7{_CC o-7A{C /v)"@{7{_CC o-7A{C "@|8|`CD p-8A|D L/"@|8|`CD p-8A|D ۭ"@|8|`CD p-8A|D rj5"@|8|`CD p-8A|D Ҹ"@|8|`CD p-8A|D ;"@|8|`CD p-8A|D "@|8|`CD p-8A|D  B"@|8|`CD p-8A|D 6Ņ"@|8|`CD p-8A|D R/H"@|8|`CD p-8A|D R$TBˆ"@}9}aCE q-9A}E 2TN"@}9}aCE q-9A}E Argч"@}9}aCE q-9A}E 2SzT"@}9}aCE q-9A}E rf׈"@}9}aCE q-9A}E r{Z"@}9}aCE q-9A}E R݉"@}9}aCE q-9A}E Ҫ=`"@}9}aCE q-9A}E "@}9}aCE q-9A}E R[f"@}9}aCE q-9A}E 2"@~:~bCFr-:A~Fzm"@~:~bCFr-:A~Fr@ !"@~:~bCFr-:A~Fc3s"@~:~bCFr-:A~F҈'F"@~:~bCFr-:A~FXy"@~:~bCFr-:A~FREk"@~:~bCFr-:A~F}"@~:~bCFr-:A~F/d"@~:~bCFr-:A~F\󢅐"@~:~bCFr-:A~F"@;cCGs-;AGRȋ"@;cCGs-;AG"@;cCGs-;AG&0푒"@;cCGs-;AG]"@;cCGs-;AGrN"@;cCGs-;AG$"@;cCGs-;AGR m7"@;cCGs-;AGrKI!"@;cCGs-;AGR\"@;cCGs-;AGo'"@<dCHt-<AHr"@<dCHt-<AHU9-"@<dCHt-<AHȦ"@<dCHt-<AHrW3"@<dCHt-<AH20˶"@<dCHt-<AHr|v9"@<dCHt-<AH"@<dCHt-<AH@"@<dCHt-<AHRl$Ú"@<dCHt-<AH(F"@=eCIu-=AI2C;ɛ"@=eCIu-=AIRlML"@=eCIu-=AI2a`Ϝ"@=eCIu-=AIrR"@=eCIu-=AIR|՝"@=eCIu-=AIX"@=eCIu-=AIr:۞"@=eCIu-=AIr.^"@=eCIu-=AI"@=eCIu-=AIreMd"@>fCJv->AJ"@>fCJv->AJr5lk"@>fCJv->AJR"@>fCJv->AJ ,q"@>fCJv->AJ2{?"@>fCJv->AJ2Qw"@>fCJv->AJ2]9d"@>fCJv->AJv}"@>fCJv->AJRFX"@>fCJv->AJ盃"@?gCKw-?AK6w"@?gCKw-?AK"@?gCKw-?AK. "@?gCKw-?AKr%揧"@?gCKw-?AK,"@?gCKw-?AKD "@?gCKw-?AKr2"@?gCKw-?AKc0"@?gCKw-?AKr?B"@?gCKw-?AKrȂU"@ @ hCLx-@BLRSh%"@ @ hCLx-@BLz"@ @ hCLx-@BLn1+"@ @ hCLx-@BL"@ @ hCLx-@BLҐP1"@ @ hCLx-@BL$Ĵ"@ @ hCLx-@BLro7"@ @ hCLx-@BLQ麮"@ @ hCLx-@BL="@ @ hCLx-@BL"@!A!iCMy-ABM"!D"@!A!iCMy-ABMR=4ǰ"@!A!iCMy-ABMaFJ"@!A!iCMy-ABM]Yͱ"@!A!iCMy-ABMkP"@!A!iCMy-ABMM|~Ӳ"@!A!iCMy-ABM V"@!A!iCMy-ABM2ٳ"@!A!iCMy-ABMRI+\"@!A!iCMy-ABM2ߴ"@"B"jCNz-BBNҤJb"@"B"jCNz-BBN2U"@"B"jCNz-BBNji"@"B"jCNz-BBNr"@"B"jCNz-BBN2q%o"@"B"jCNz-BBN(8"@"B"jCNz-BBN2Ju"@"B"jCNz-BBNr8]"@"B"jCNz-BBNRZo{"@"B"jCNz-BBNX"@#C#kCO{-C BO甁"@#C#kCO{-C BOқw"@#C#kCO{-C BO_"@#C#kCO{-C BO% "@#C#kCO{-C BO&ߍ"@#C#kCO{-C BO"@#C#kCO{-C BOF"@#C#kCO{-C BO2O"@#C#kCO{-C BOf)"@#C#kCO{-C BO;"@$D$lCP|.DBPN"@$D$lCP|.DBPa#"@$D$lCP|.DBPks"@$D$lCP|.DBPB5)"@$D$lCP|.DBPRŘ"@$D$lCP|.DBPT/"@$D$lCP|.DBP佲"@$D$lCP|.DBPt5"@$D$lCP|.DBP2"@$D$lCP|.DBPv;"@%E%mCQ}.EBQZ$"@%E%mCQ}.EBQAB"@%E%mCQ}.EBQ(D-"@%E%mCQ}.EBQr?H"@%E%mCQ}.EBQcR"@%E%mCQ}.EBQdN"@%E%mCQ}.EBQڃw"@%E%mCQ}.EBQT"@%E%mCQ}.EBQR"@%E%mCQ}.EBQ3Z"@&F&nCR~.FBR"@&F&nCR~.FBRS`"@&F&nCR~.FBRR"@&F&nCR~.FBRҔsf"@&F&nCR~.FBR "@&F&nCR~.FBRm"@&F&nCR~.FBR#1"@&F&nCR~.FBRrCs"@&F&nCR~.FBRCV"@&F&nCR~.FBRhy"@'G'oCS.GBS2c{"@'G'oCS.GBSҰ"@'G'oCS.GBSR"@'G'oCS.GBS"@'G'oCS.GBSأ"@'G'oCS.GBS3؋"@'G'oCS.GBSr"@'G'oCS.GBST"@'G'oCS.GBSR'"@'G'oCS.GBSr?t""@(H(pCT.H BT2Y5"@(H(pCT.H BTtG"@(H(pCT.H BTR$Z!"@(H(pCT.H BTrl"@(H(pCT.H BTrD'"@(H(pCT.H BT2ԑ"@(H(pCT.H BTe-"@(H(pCT.H BT2@"@(H(pCT.H BT2h3"@(H(pCT.H BT2ܶ"@)I)qCU.I$BUҽ9"@)I)qCU.I$BUr5"@)I)qCU.I$BU@"@)I)qCU.I$BUKV&"@)I)qCU.I$BU~8F"@)I)qCU.I$BU2vK"@)I)qCU.I$BU^L"@)I)qCU.I$BU!p"@)I)qCU.I$BU['R"@)I)qCU.I$BU"@*J*rCV.J(BV2GX"@*J*rCV.J(BVغ"@*J*rCV.J(BVUh^"@*J*rCV.J(BVҘ"@*J*rCV.J(BVr݈d"@*J*rCV.J(BV#"@*J*rCV.J(BVRlk"@*J*rCV.J(BVR9*"@*J*rCV.J(BV2"@-M-uCY!.M4BY!*t"@-M-uCY!.M4BY!2D"@-M-uCY!.M4BY!#D"@-M-uCY!.M4BY!%WJ"@-M-uCY!.M4BY!%i"@-M-uCY!.M4BY!rF|P"@.N.vCZ".N8BZ"r-׎"@.N.vCZ".N8BZ"2gV"@.N.vCZ".N8BZ"<"@.N.vCZ".N8BZ"2Lj\"@.N.vCZ".N8BZ"rS"@.N.vCZ".N8BZ"rb"@.N.vCZ".N8BZ"2q:"@.N.vCZ".N8BZ"i"@.N.vCZ".N8BZ"[#"@.N.vCZ".N8BZ"2+5o"@/O/wC[#.O|#@1Q1yC]%.QDB]% <#@1Q1yC]%.QDB]%Ý#@1Q1yC]%.QDB]%҈.+B#@1Q1yC]%.QDB]%P=#@1Q1yC]%.QDB]%PPH#@1Q1yC]%.QDB]%b#@2R2zC^&.RHB^&2quN#@2R2zC^&.RHB^&r~#@2R2zC^&.RHB^&NT#@2R2zC^&.RHB^&r $#@2R2zC^&.RHB^&Z #@2R2zC^&.RHB^&E #@2R2zC^&.RHB^&Ҡ` #@2R2zC^&.RHB^&yg #@2R2zC^&.RHB^&T g #@2R2zC^&.RHB^&21 #@3S3{C_'.SLB_'/m #@3S3{C_'.SLB_'A #@3S3{C_'.SLB_';Ts #@3S3{C_'.SLB_'Rf #@3S3{C_'.SLB_']yy#@3S3{C_'.SLB_'2#@3S3{C_'.SLB_'Rk#@3S3{C_'.SLB_'2V#@3S3{C_'.SLB_'BÅ#@3S3{C_'.SLB_'R12#@4T4|C`(/TPB`(r!#@4T4|C`(/TPB`(T#@4T4|C`(/TPB`(R #@4T4|C`(/TPB`(u #@4T4|C`(/TPB`(R3#@4T4|C`(/TPB`(rE#@4T4|C`(/TPB`((X#@4T4|C`(/TPB`(2j!#@4T4|C`(/TPB`(J}#@4T4|C`(/TPB`(ۏ'#@5U5}Ca)/UTBa)Rl#@5U5}Ca)/UTBa)-#@5U5}Ca)/UTBa)ǰ#@5U5}Ca)/UTBa)R3#@5U5}Ca)/UTBa)r#@5U5}Ca)/UTBa) B9#@5U5}Ca)/UTBa)R#@5U5}Ca)/UTBa)&d$@#@5U5}Ca)/UTBa)r76#@5U5}Ca)/UTBa)IIF#@6V6~Cb*/VXBb*]\#@6V6~Cb*/VXBb*RsnL#@6V6~Cb*/VXBb*9#@6V6~Cb*/VXBb*2ʓR#@6V6~Cb*/VXBb*R[#@6V6~Cb*/VXBb*2X#@6V6~Cb*/VXBb*}#@6V6~Cb*/VXBb*r^#@6V6~Cb*/VXBb*=#@6V6~Cb*/VXBb*a1e #@7W7Cc+/W\Bc+ #@7W7Cc+/W\Bc+2S(k!#@7W7Cc+/W\Bc+:!#@7W7Cc+/W\Bc+vMq"#@7W7Cc+/W\Bc+0`"#@7W7Cc+/W\Bc+_rw##@7W7Cc+/W\Bc+)##@7W7Cc+/W\Bc+rº}$#@7W7Cc+/W\Bc+K%#@7W7Cc+/W\Bc+,ݼ%#@8X8Cd,/X`Bd,2dn&#@8X8Cd,/X`Bd,&#@8X8Cd,/X`Bd,ِ '#@8X8Cd,/X`Bd,"'#@8X8Cd,/X`Bd,T(#@8X8Cd,/X`Bd,D,(#@8X8Cd,/X`Bd,>)#@8X8Cd,/X`Bd,2gQ)#@8X8Cd,/X`Bd,2bc*#@8X8Cd,/X`Bd,v*#@9Y9Ce-/YdBe-%+#@9Y9Ce-/YdBe->+#@9Y9Ce-/YdBe-=+,#@9Y9Ce-/YdBe-,#@9Y9Ce-/YdBe-+`1-#@9Y9Ce-/YdBe-2~-#@9Y9Ce-/YdBe-҂7.#@9Y9Ce-/YdBe-( .#@9Y9Ce-/YdBe->/#@9Y9Ce-/YdBe-60/#@:Z:Cf./ZhBf.r5BD0#@:Z:Cf./ZhBf.ҒYU0#@:Z:Cf./ZhBf.gJ1#@:Z:Cf./ZhBf.R|z1#@:Z:Cf./ZhBf.2 P2#@:Z:Cf./ZhBf.r2#@:Z:Cf./ZhBf.0V3#@:Z:Cf./ZhBf.3#@:Z:Cf./ZhBf.rQS\4#@:Z:Cf./ZhBf.Ҽ4#@;[;Cg//[lBg/R*vb5#@;[;Cg//[lBg/R5#@;[;Cg//[lBg/ !i6#@;[;Cg//[lBg/|*46#@;[;Cg//[lBg/RFo7#@;[;Cg//[lBg/gMY7#@;[;Cg//[lBg/ku8#@;[;Cg//[lBg/rYp~8#@;[;Cg//[lBg/{9#@;[;Cg//[lBg/rR9#@<\<Ch0/\pBh0$:#@<\<Ch0/\pBh0rR;#@<\<Ch0/\pBh0RGۇ;#@<\<Ch0/\pBh0Y <#@<\<Ch0/\pBh02j<#@<\<Ch0/\pBh02h=#@<\<Ch0/\pBh02%=#@<\<Ch0/\pBh0}8>#@<\<Ch0/\pBh02 J>#@<\<Ch0/\pBh0B]?#@=]=Ci1/]tBi1+o?#@=]=Ci1/]tBi1re#@#@=]=Ci1/]tBi1R@#@=]=Ci1/]tBi1R鈧)A#@=]=Ci1/]tBi1A#@=]=Ci1/]tBi1r/B#@=]=Ci1/]tBi1R=߲B#@=]=Ci1/]tBi1T5C#@=]=Ci1/]tBi12`C#@=]=Ci1/]tBi1R^>Cj2/^xBj228)D#@>^>Cj2/^xBj2^>Cj2/^xBj2RNE#@>^>Cj2/^xBj2+9aHF#@>^>Cj2/^xBj2sF#@>^>Cj2/^xBj2r\NG#@>^>Cj2/^xBj22/G#@>^>Cj2/^xBj2TH#@>^>Cj2/^xBj2ҏH#@>^>Cj2/^xBj2BZI#@?_?Ck3/_|Bk34I#@?_?Ck3/_|Bk3`J#@?_?Ck3/_|Bk3RfXJ#@?_?Ck3/_|Bk3 gK#@?_?Ck3/_|Bk3r{-K#@?_?Ck3/_|Bk32 @mL#@?_?Ck3/_|Bk3YRL#@?_?Ck3/_|Bk31esM#@?_?Ck3/_|Bk3wM#@?_?Ck3/_|Bk3ҢTyN#@@`@Cl4/`Bl4iN#@@`@Cl4/`Bl41xO#@@`@Cl4/`Bl42 P#@@`@Cl4/`Bl4țԅP#@@`@Cl4/`Bl4ҕ-Q#@@`@Cl4/`Bl4reQ#@@`@Cl4/`Bl46Q R#@@`@Cl4/`Bl4 R#@@`@Cl4/`Bl4t1S#@@`@Cl4/`Bl4DS#@AaACm5/aB m5VT#@AaACm5/aB m5Rh*iT#@AaACm5/aB m5D{!U#@AaACm5/aB m5R"NU#@AaACm5/aB m5'V#@AaACm5/aB m5rqV#@AaACm5/aB m5-W#@AaACm5/aB m5ذW#@AaACm5/aB m5r'3X#@AaACm5/aB m5{X#@BbBCn6/bB n6reK:Y#@BbBCn6/bB n6Q"Y#@BbBCn6/bB n6?o5@Z#@BbBCn6/bB n62/HZ#@BbBCn6/bB n6 ZF[#@BbBCn6/bB n6%m[#@BbBCn6/bB n62 L\#@BbBCn6/bB n6I\#@BbBCn6/bB n6ڤR]#@BbBCn6/bB n62l]#@CcCCo7/cB o7RX^#@CcCCo7/cB o7r^#@CcCCo7/cB o72"^_#@CcCCo7/cB o7_#@CcCCo7/cB o72Fe`#@CcCCo7/cB o7R&`#@CcCCo7/cB o7Rj9ka#@CcCCo7/cB o7Ka#@CcCCo7/cB o7^qb#@CcCCo7/cB o7!qb#@DdDCp80dB p8+wc#@DdDCp80dB p8;Ec#@DdDCp80dB p8Mר}d#@DdDCp80dB p8aie#@DdDCp80dB p8Rv̓e#@DdDCp80dB p8Rf#@DdDCp80dB p82f#@DdDCp80dB p8 g#@DdDCp80dB p82Cg#@DdDCp80dB p8R*h#@EeECq90eB q9Rh=h#@EeECq90eB q9=Oi#@EeECq90eB q9`bi#@EeECq90eB q9uj#@EeECq90eB q9j#@EeECq90eB q9B%k#@EeECq90eB q9լk#@EeECq90eB q92-g+l#@EeECq90eB q9R[Ѯl#@EeECq90eB q9r1m#@FfFCr:0fBr:Rm#@FfFCr:0fBr: 8n#@FfFCr:0fBr:R&Bn#@FfFCr:0fBr:r].>o#@FfFCr:0fBr:fAo#@FfFCr:0fBr:2SDp#@FfFCr:0fBr: fp#@FfFCr:0fBr:2LyJq#@FfFCr:0fBr:2q#@FfFCr:0fBr:2APr#@GgGCs;0gBs;԰r#@GgGCs;0gBs;rWfVs#@GgGCs;0gBs;s#@GgGCs;0gBs;\t#@GgGCs;0gBs;2t#@GgGCs;0gBs;2 cu#@GgGCs;0gBs;A u#@GgGCs;0gBs;2iv#@GgGCs;0gBs;ofEv#@GgGCs;0gBs;Wow#@HhHCt<0hBt<2jw#@HhHCt<0hBt<p}ux#@HhHCt<0hBt<ɯx#@HhHCt<0hBt<$B{y#@HhHCt<0hBt<RԴy#@HhHCt<0hBt<fǁz#@HhHCt<0hBt<2@{#@HhHCt<0hBt<2{#@HhHCt<0hBt< |#@HhHCt<0hBt<k|#@IiICu=0iBu=2B$}#@IiICu=0iBu=R<6}#@IiICu=0iBu=RgI~#@IiICu=0iBu=2[~#@IiICu=0iBu=n#@IiICu=0iBu=2#@IiICu=0iBu=Re##@IiICu=0iBu=2C#@IiICu=0iBu=Nָ)#@IiICu=0iBu=rhˬ#@JjJCv>0jBv>?/#@JjJCv>0jBv>Һ#@JjJCv>0jBv>7 6#@JjJCv>0jBv>R#@JjJCv>0jBv>6E(<#@JjJCv>0jBv>:#@JjJCv>0jBv>=jMB#@JjJCv>0jBv>_Ņ#@JjJCv>0jBv>rJrH#@JjJCv>0jBv>!ˆ#@KkKCw?0kBw?_N#@KkKCw?0kBw?Fч#@KkKCw?0kBw?zټT#@KkKCw?0kBw?2 l׈#@KkKCw?0kBw?Z#@KkKCw?0kBw?1݉#@KkKCw?0kBw?r#a#@KkKCw?0kBw?2_#@KkKCw?0kBw?H,g#@KkKCw?0kBw?>#@LlLCx@0lBx@0nQm#@LlLCx@0lBx@d#@LlLCx@0lBx@rpvs#@LlLCx@0lBx@&#@LlLCx@0lBx@򶸛y#@LlLCx@0lBx@\K#@LlLCx@0lBx@#@LlLCx@0lBx@2p#@LlLCx@0lBx@rY慐#@LlLCx@0lBx@#@M mMCyA0mByA( #@M mMCyA0mByARf#@M mMCyA0mByAN0#@M mMCyA0mByAB#@M mMCyA0mByAsU#@M mMCyA0mByA:h#@M mMCyA0mByAz#@M mMCyA0mByAү+!#@M mMCyA0mByA2m#@M mMCyA0mByA,Q'#@N nNCzB0nBzBĪ#@N nNCzB0nBzBrv-#@N nNCzB0nBzBs 갗#@N nNCzB0nBzB93#@N nNCzB0nBzB/#@N nNCzB0nBzBr!:#@N nNCzB0nBzBT4#@N nNCzB0nBzB2dF@#@N nNCzB0nBzBR3zYÚ#@N nNCzB0nBzB lF#@O oOC{C0oB{C֟~ɛ#@O oOC{C0oB{C22L#@O oOC{C0oB{CRţϜ#@O oOC{C0oB{CrYXR#@O oOC{C0oB{C3՝#@O oOC{C0oB{C~X#@O oOC{C0oB{C۞#@O oOC{C0oB{CRˣ_#@O oOC{C0oB{C26#@O oOC{C0oB{C%e#@P pPC|D0pB|DRs\8#@P pPC|D0pB|DYJk#@P pPC|D0pB|DA]#@P pPC|D0pB|D+pq#@P pPC|D0pB|DR#@P pPC|D0pB|D;w#@P pPC|D0pB|Dͧ#@P pPC|D0pB|D`}#@P pPC|D0pB|D#@P pPC|D0pB|DR̆߃#@Q qQC}E0qB}E#@Q qQC}E0qB}EҺ#@Q qQC}E0qB}E? #@Q qQC}E0qB}Er)#@Q qQC}E0qB}Ee<#@Q qQC}E0qB}E2N#@Q qQC}E0qB}Era#@Q qQC}E0qB}E2t#@Q qQC}E0qB}E򵱆#@Q qQC}E0qB}ERD#@RrRC~F0rB~F׫%#@RrRC~F0rB~Fj#@RrRC~F0rB~FR+#@RrRC~F0rB~F㮬#@RrRC~F0rB~FR#1#@RrRC~F0rB~Fr#@RrRC~F0rB~FrJ8#@RrRC~F0rB~F20-#@RrRC~F0rB~FFp@>#@RrRC~F0rB~F_S#@SsSCG0sBG2yeD#@SsSCG0sBG)xǰ#@SsSCG0sBGJ#@SsSCG0sBG2Oͱ#@SsSCG0sBGRP#@SsSCG0sBGrvӲ#@SsSCG0sBG2; V#@SsSCG0sBGaٳ#@SsSCG0sBGR/\#@SsSCG0sBGr #@TtTCH1tBHrUc#@TtTCH1tBH1#@TtTCH1tBH=|Di#@TtTCH1tBHoW#@TtTCH1tBHio#@TtTCH1tBH5|#@TtTCH1tBH Ɏu#@TtTCH1tBH2F\#@TtTCH1tBHr{#@TtTCH1tBHr#@UuUCI1uBIRف#@UuUCI1uBI9#@UuUCI1uBIR{<#@UuUCI1uBIr #@UuUCI1uBIc##@UuUCI1uBIRJ5#@UuUCI1uBIҒH#@UuUCI1uBI2[#@UuUCI1uBI2)m#@UuUCI1uBI2wC#@VvVCJ1vBJ֒#@VvVCJ1vBJRj##@VvVCJ1vBJk#@VvVCJ1vBJ)#@VvVCJ1vBJ$ݬ#@VvVCJ1vBJ2p/#@VvVCJ1vBJJ#@VvVCJ1vBJ&6#@VvVCJ1vBJq'#@VvVCJ1vBJ:<#@WwWCK1wBKFL#@WwWCK1wBK+_B#@WwWCK1wBKq#@WwWCK1wBKruRH#@WwWCK1wBK2#@WwWCK1wBKHyN#@WwWCK1wBK #@WwWCK1wBK#T#@WwWCK1wBK3#@WwWCK1wBKZ#@XxXCL1xB LwZ#@XxXCL1xB LRa#@XxXCL1xB L2d+#@XxXCL1xB L>g#@XxXCL1xB LWP#@XxXCL1xB L;cm#@XxXCL1xB LRu#@XxXCL1xB Lbs#@XxXCL1xB LS#@XxXCL1xB LR׉y#@YyYCM1yB!M\#@YyYCM1yB!M#@YyYCM1yB!MrlD#@YyYCM1yB!M2#@YyYCM1yB!Mk #@YyYCM1yB!M#@YyYCM1yB!Mҡ/#@YyYCM1yB!M3&B#@YyYCM1yB!MRǹT#@YyYCM1yB!M\Mg#@ZzZCN1zB"Ny#@ZzZCN1zB"Nt#@ZzZCN1zB"N'!#@ZzZCN1zB"Ně#@ZzZCN1zB"Nrb/'#@ZzZCN1zB"Nr֪#@ZzZCN1zB"NrV-#@ZzZCN1zB"NH#@ZzZCN1zB"Nr}4#@ZzZCN1zB"N!#@[{[CO1{B#O=3:#@[{[CO1{B#O8F#@[{[CO1{B#O2X@#@[{[CO1{B#OrC`k#@[{[CO1{B#O}F#@[{[CO1{B#O#@[{[CO1{B#OrYL#@[{[CO1{B#O#@[{[CO1{B#ORBR#@[{[CO1{B#Or#@\|\CP1|B$P2:jX#@\|\CP1|B$P#@\|\CP1|B$Pr_#@\|\CP1|B$Pu%%#@\|\CP1|B$P77e#@\|\CP1|B$PLJ#@\|\CP1|B$P2\k#@\|\CP1|B$Pto#@\|\CP1|B$PQq#@\|\CP1|B$P#@]}]CQ1}B%Q/w#@]}]CQ1}B%Qù#@]}]CQ1}B%QRW}#@]}]CQ1}B%QZ#@]}]CQ1}B%Qr.#@]}]CQ1}B%Q2#@]}]CQ1}B%Qۦ#@]}]CQ1}B%QҴ:) #@]}]CQ1}B%Q;#@]}]CQ1}B%QlbN#@^~^CR1~B&RrK`#@^~^CR1~B&R+s#@^~^CR1~B&R#@^~^CR1~B&R#@^~^CR1~B&RE#@^~^CR1~B&RRٽ%#@^~^CR1~B&RmШ#@^~^CR1~B&Rғ+#@^~^CR1~B&R#@^~^CR1~B&Rro)2#@__CS1B'S_#@__CS1B'S2RQ-8#@__CS1B'SRF?#@__CS1B'S2#@__CS1B'S3 e#@__CS1B'S2-wD#@__CS1B'Sr(5#@__CS1B'Sr%ɜJ#@__CS1B'S2$]#@__CS1B'S$P#@``CT1B(T2'#@``CT1B(T2+V#@``CT1B(TR1#@``CT1B(T8A ]#@``CT1B(TrB#@``CT1B(TMi1c#@``CT1B(TZC#@``CT1B(TiVi#@``CT1B(TRz%i#@``CT1B(TҌ{o#@aaCU1B)UM#@aaCU1B)Uu#@aaCU1B)Uu#@aaCU1B)UR {#@aaCU1B)U#@aaCU1B)U 2#@aaCU1B)U?#@aaCU1B)U`Z#@aaCU1B)U2" #@aaCU1B)Ur5#@bbCV1B*VH#@bbCV1B*VrZ#@bbCV1B*V?m#@bbCV1B*VJ#@bbCV1B*Vwg#@bbCV1B*VҦ#@bbCV1B*V׏#$@bbCV1B*V2 $ʦ$@bbCV1B*V>)$@bbCV1B*VtL$@ccCW1B+WҬ0$@ccCW1B+Wt$@ccCW1B+W! '6$@ccCW1B+Wr_9$@ccCW1B+Wr1L<$@ccCW1B+Wr^$@ccCW1B+W"ZqB$@ccCW1B+Wf$@ccCW1B+WҬH$@ccCW1B+W$@d dCX2B,X>N$@d dCX2B,X2?$@d dCX2B,XT$@d dCX2B,X&h$@d dCX2B,Xw[ $@d dCX2B,Xʐ $@d dCX2B,X2%+a $@d dCX2B,Xru= $@d dCX2B,XMPg $@d dCX2B,X'b $@e!eCY2B-Y2vum $@e!eCY2B-Y $@e!eCY2B-Y?s $@e!eCY2B-Y3 $@e!eCY2B-Yȿy$@e!eCY2B-Yrh\$@e!eCY2B-Y$@e!eCY2B-Y7$@e!eCY2B-Y $@e!eCY2B-Y  $@f"fCZ2B.ZRzB/$@f"fCZ2B.ZA$@f"fCZ2B.ZZkT$@f"fCZ2B.Zf$@f"fCZ2B.ZrBy$@f"fCZ2B.Z($@f"fCZ2B.ZR1$@f"fCZ2B.ZRQ!$@f"fCZ2B.Z2'ä$@f"fCZ2B.ZҤz'$@g#gC[2B/[R$$@g#gC[2B/[r-$@g#gC[2B/[r(8$@g#gC[2B/[R 4$@g#gC[2B/[3a3$@g#gC[2B/[2E:$@g#gC[2B/[RFX$@g#gC[2B/[2k@$@g#gC[2B/[_}$@g#gC[2B/[rGF$@h$hC\2B0\Ҁܢ$@h$hC\2B0\qL$@h$hC\2B0\Ҩ$@h$hC\2B0\R?R$@h$hC\2B0\.$@h$hC\2B0\rX$@h$hC\2B0\X$@h$hC\2B0\$_$@h$hC\2B0\rK7$@h$hC\2B0\Je $@i%iC]2B1]\ $@i%iC]2B1]4?ok!$@i%iC]2B1]Ӂ!$@i%iC]2B1]hq"$@i%iC]2B1]."$@i%iC]2B1]ڑw#$@i%iC]2B1]R&#$@i%iC]2B1]8}$$@i%iC]2B1]O%$@i%iC]2B1]Ҝ%$@j&jC^2B2^Qy&$@j&jC^2B2^)&$@j&jC^2B2^2; '$@j&jC^2B2^{7N'$@j&jC^2B2^7`($@j&jC^2B2^`s($@j&jC^2B2^)$@j&jC^2B2^v)$@j&jC^2B2^R:*$@j&jC^2B2^r*$@k'kC_2B3_RH%+$@k'kC_2B3_+$@k'kC_2B3_rYr+,$@k'kC_2B3_%,$@k'kC_2B3_2-$@k'kC_2B3_0--$@k'kC_2B3_2?8.$@k'kC_2B3_hZR.$@k'kC_2B3_=d>/$@k'kC_2B3_w/$@l(lC`2B4`rD0$@l(lC`2B4`ȭ0$@l(lC`2B4`RBJ1$@l(lC`2B4`1$@l(lC`2B4`RblP2$@l(lC`2B4`D2$@l(lC`2B4`'V3$@l(lC`2B4` + 3$@l(lC`2B4`]4$@l(lC`2B4`T14$@ m) mCa2 B5aRCc5$@ m) mCa2 B5a~V5$@ m) mCa2 B5aҡii6$@ m) mCa2 B5a{6$@ m) mCa2 B5a=o7$@ m) mCa2 B5aRwҠ7$@ m) mCa2 B5algu8$@ m) mCa2 B5ac8$@ m) mCa2 B5a\{9$@ m) mCa2 B5arW&9$@ n* nCb2 B6bS:$@ n* nCb2 B6bRP;$@ n* nCb2 B6b2R";$@ n* nCb2 B6bTz5 <$@ n* nCb2 B6bWH<$@ n* nCb2 B6b]Z=$@ n* nCb2 B6bRd9m=$@ n* nCb2 B6bRm>$@ n* nCb2 B6bxc>$@ n* nCb2 B6b?$@ o+ oCc2 B7c?$@ o+ oCc2 B7c2"#@$@ o+ oCc2 B7cܦ@$@ o+ oCc2 B7cL)A$@ o+ oCc2 B7cRA$@ o+ oCc2 B7cv0B$@ o+ oCc2 B7c 'B$@ o+ oCc2 B7c)96C$@ o+ oCc2 B7cRF6LC$@ o+ oCc2 B7cd^mL$@ q- qCe2 B9er{L$@ q- qCe2 B9eHsM$@ q- qCe2 B9erݿM$@ q- qCe2 B9ej`wc$@v2vCj3B>jdc$@v2vCj3B>j}d$@v2vCj3B>j҄!e$@v2vCj3B>jRe$@v2vCj3B>jL)f$@v2vCj3B>jA;f$@v2vCj3B>jwN g$@v2vCj3B>jrs ag$@v2vCj3B>jsh$@w3wCk3B?kR8h$@w3wCk3B?kRKΘi$@w3wCk3B?kci$@w3wCk3B?kҎj$@w3wCk3B?k23Тj$@w3wCk3B?kr$%k$@w3wCk3B?krk$@w3wCk3B?k2+P,l$@w3wCk3B?kl$@w3wCk3B?k2{-2m$@x4xCl3B@lR3@m$@x4xCl3B@lRR8n$@x4xCl3B@lo$@x4xCl3B@lho$@x4xCl3B@lDp$@x4xCl3B@lsp$@x4xCl3B@lr/)Jq$@x4xCl3B@lq$@x4xCl3B@lTPr$@y5y Cm3BA m2mr$@y5y Cm3BA m/ Ws$@y5y Cm3BA mrs$@y5y Cm3BA m1]t$@y5y Cm3BA mADt$@y5y Cm3BA mMVcu$@y5y Cm3BA mmiu$@y5y Cm3BA mR|iv$@y5y Cm3BA mv$@y5y Cm3BA m.ow$@z6z Cn3BB nYijw$@z6z Cn3BB nR.Zux$@z6z Cn3BB nx$@z6z Cn3BB n܅{y$@z6z Cn3BB ny$@z6z Cn3BB nҒz$@z6z Cn3BB nrpG#{$@z6z Cn3BB nO5{$@z6z Cn3BB n1sH |$@z6z Cn3BB n [|$@{7{ Co3BC om}$@{7{ Co3BC o24}$@{7{ Co3BC oʒ~$@{7{ Co3BC o`~$@{7{ Co3BC o$@{7{ Co3BC oRʠ$@{7{ Co3BC oz"#$@{7{ Co3BC ol呂$@{7{ Co3BC o_N*$@{7{ Co3BC oS$@|8| Cp3BD pJz'0$@|8| Cp3BD pB:$@|8| Cp3BD p2=L6$@|8| Cp3BD p9<_$@|8| Cp3BD p6q<$@|8| Cp3BD pr6h$@|8| Cp3BD p7B$@|8| Cp3BD p:Ņ$@|8| Cp3BD p?*H$@|8| Cp3BD pFˆ$@}9} Cq3BE qNVN$@}9} Cq3BE qRYч$@}9} Cq3BE qReU$@}9} Cq3BE q2s؈$@}9} Cq3BE q҂+[$@}9} Cq3BE q2D>މ$@}9} Cq3BE qrPa$@}9} Cq3BE qrpc$@}9} Cq3BE q2vg$@}9} Cq3BE q뜈$@~:~Cr3BFr3m$@~:~Cr3BFrR"ɭ$@~:~Cr3BFr2@_s$@~:~Cr3BFr_$@~:~Cr3BFrRy$@~:~Cr3BFr!$@~:~Cr3BFrɷ $@~:~Cr3BFrM$@~:~Cr3BFrR/$@~:~Cr3BFrCzB $@;Cs3BGsoU$@;Cs3BGsg$@;Cs3BGsCv3CJv2ݬ$@>Cv3CJv@Ck$@>Cv3CJv2٧$@>Cv3CJvr pq$@>Cv3CJvrv$@>Cv3CJv2w$@>Cv3CJvM3$@>Cv3CJv~$@>Cv3CJv2,`$@>Cv3CJv)$@?Cw3CKw<$@?Cw3CKw2#O$@?Cw3CKwRa $@?Cw3CKwrwPt$@?Cw3CKwR$@?Cw3CKwn}$@?Cw3CKwR$@?Cw3CKwm$@?Cw3CKwr@$@?Cw3CKw2s㢪$@ @ Cx4 CLxm%$@ @ Cx4 CLx $@ @ Cx4 CLxR ,$@ @ Cx4 CLx21.$@ @ Cx4 CLx @2$@ @ Cx4 CLxR^S$@ @ Cx4 CLx?e8$@ @ Cx4 CLxыx$@ @ Cx4 CLxe">$@ @ Cx4 CLx2$@!A!Cy4!CMyOD$@!A!Cy4!CMy+ǰ$@!A!Cy4!CMy|J$@!A!Cy4!CMycͱ$@!A!Cy4!CMy2P$@!A!Cy4!CMyr@ Բ$@!A!Cy4!CMyDW$@!A!Cy4!CMym2ڳ$@!A!Cy4!CMy2E]$@!A!Cy4!CMy5W$@"B"Cz4"CNz1jc$@"B"Cz4"CNz|$@"B"Cz4"CNz6_i$@"B"Cz4"CNz$@"B"Cz4"CNzo$@"B"Cz4"CNz2H#$@"B"Cz4"CNzRu$@"B"Cz4"CNzP$@"B"Cz4"CNzi{$@"B"Cz4"CNz"~$@#C#C{4#CO{$$@#C#C{4#CO{6$@#C#C{4#CO{YBI$@#C#C{4#CO{R[ $@#C#C{4#CO{on$@#C#C{4#CO{$@#C#C{4#CO{f$@#C#C{4#CO{2.4$@#C#C{4#CO{ʸ$@#C#C{4#CO{a$@$D$C|4$CP|ҏݠ$@$D$C|4$CP|^#$@$D$C|4$CP|2/&$@$D$C|4$CP|*$@$D$C|4$CP|S($@$D$C|4$CP|ҫ:0$@$D$C|4$CP|rM$@$D$C|4$CP|\`6$@$D$C|4$CP|R8r$@$D$C|4$CP|RF<$@%E%C}4% CQ}Rܗ$@%E%C}4% CQ}sB$@%E%C}4% CQ}R $@%E%C}4% CQ}H$@%E%C}4% CQ}8$@%E%C}4% CQ}iN$@%E%C}4% CQ}Sf$@%E%C}4% CQ}>U$@%E%C}4% CQ}+,$@%E%C}4% CQ}+?[$@&F&C~4& CR~R Q$@&F&C~4& CR~Xda$@&F&C~4& CR~2v$@&F&C~4& CR~R膉g$@&F&C~4& CR~2$@&F&C~4& CR~ٴm$@&F&C~4& CR~RK$@&F&C~4& CR~s$@&F&C~4& CR~y$@&F&C~4& CR~y$@'G'C4' CSէ $@'G'C4' CSr>$@'G'C4' CS0$@'G'C4' CSlC$@'G'C4' CSrV $@'G'C4' CSh$@'G'C4' CSR 2{$@'G'C4' CSrɍ$@'G'C4' CSr*`$@'G'C4' CS=$@(H(C4( CTrQ$@(H(C4( CTg%؞$@(H(C4( CT!$@(H(C4( CTS$@(H(C4( CTR($@(H(C4( CTҁ"$@(H(C4( CT5.$@(H(C4( CTG$@(H(C4( CT5GZ4$@(H(C4( CT2Zl$@)I)C4) CUu:$@)I)C4) CU $@)I)C4) CUң@$@)I)C4) CUr:$@)I)C4) CU+F$@)I)C4) CU2[i$@)I)C4) CU2L$@)I)C4) CU2$@)I)C4) CU.S$@)I)C4) CU*&$@*J*C4*CVrb]9Y$@*J*C4*CVRK$@*J*C4*CV2؋^_$@*J*C4*CV#q$@*J*C4*CVUe$@*J*C4*CV2Q$@*J*C4*CVk$@*J*C4*CV$@*J*C4*CVRdq$@*J*C4*CV$@+K+C4+CWEw$@+K+C4+CWB$@+K+C4+CWRt~$@+K+C4+CW +$@+K+C4+CW0=$@+K+C4+CW:P$@+K+C4+CWb$@+K+C4+CWR/iu $@+K+C4+CW$@+K+C4+CWᗚ$@,L, C4,CX =/$@,L, C4,CX ƿ$@,L, C4,CX ]Ҝ$@,L, C4,CX R\$@,L, C4,CX $@,L, C4,CX R$$ &$@,L, C4,CX $@,L, C4,CX rR/,$@,L, C4,CX ]A$@,L, C4,CX ɁT2$@-M-!C4-CY!7g$@-M-!C4-CY!2y8$@-M-!C4-CY!H$@-M-!C4-CY!ҋߞ>$@-M-!C4-CY!w$@-M-!C4-CY!RwD$@-M-!C4-CY!$@-M-!C4-CY!2j=J$@-M-!C4-CY!r$@-M-!C4-CY!RdlQ$@.N."C4.CZ"!$@.N."C4.CZ"re3W$@.N."C4.CZ"2F$@.N."C4.CZ"mX]$@.N."C4.CZ"ak$@.N."C4.CZ"2}}c$@.N."C4.CZ"$@.N."C4.CZ"(i$@.N."C4.CZ"!$@.N."C4.CZ"rWo$@/O/#C4/C[#C$@/O/#C4/C[#Rֆu$@/O/#C4/C[#rk$@/O/#C4/C[#R|$@/O/#C4/C[#M%$@/O/#C4/C[#57$@/O/#C4/C[#|J$@/O/#C4/C[#o]$@/O/#C4/C[#o $@/O/#C4/C[#RC$@0P0$C50C\$T۔$@0P0$C50C\$r$@0P0$C50C\$ $@0P0$C50C\$I̚$@0P0$C50C\$29$@0P0$C50C\$$@0P0$C50C\$Ni$%@0P0$C50C\$%@0P0$C50C\$R)*%@0P0$C50C\$c0<%@1Q1%C51C]%N0%@1Q1%C51C]%_a%@1Q1%C51C]%s6%@1Q1%C51C]%C%@1Q1%C51C]%2'<%@1Q1%C51C]%R%@1Q1%C51C]%R~VB%@1Q1%C51C]%@%@1Q1%C51C]%H%@1Q1%C51C]%%@2R2&CŠ52C^&2O%@2R2&CŠ52C^&2YM%@2R2&CŠ52C^&#-U%@2R2&CŠ52C^&r|@%@2R2&CŠ52C^&S[ %@2R2&CŠ52C^&Ҏe %@2R2&CŠ52C^&`Dxa %@2R2&CŠ52C^&24܊ %@2R2&CŠ52C^& tg %@2R2&CŠ52C^& %@3S3'CË53C_'m %@3S3'CË53C_'; %@3S3'CË53C_'2qs %@3S3'CË53C_'Ok %@3S3'CË53C_'/ z%@3S3'CË53C_'%@3S3'CË53C_'r22%@3S3'CË53C_'D%@3S3'CË53C_'RbW%@3S3'CË53C_'Ri %@4T4(CČ54C`(R|%@4T4(CČ54C`(*%@4T4(CČ54C`(rq¡%@4T4(CČ54C`(aZ%@4T4(CČ54C`(SƘ%@4T4(CČ54C`(rG%@4T4(CČ54C`(="%@4T4(CČ54C`(r4!%@4T4(CČ54C`(-R%@4T4(CČ54C`((#(%@5U5)Cō55Ca)R%6%@5U5)Cō55Ca)#I.%@5U5)Cō55Ca)2$[%@5U5)Cō55Ca)2&Jn4%@5U5)Cō55Ca)2*‷%@5U5)Cō55Ca)/z:%@5U5)Cō55Ca)27%@5U5)Cō55Ca)@@%@5U5)Cō55Ca)KB%@5U5)Cō55Ca)rXF%@6V6*CƎ56Cb*gr%@6V6*CƎ56Cb*rw M%@6V6*CƎ56Cb*%@6V6*CƎ56Cb*:(S%@6V6*CƎ56Cb*R:%@6V6*CƎ56Cb*jMY%@6V6*CƎ56Cb*2`%@6V6*CƎ56Cb*Rr_%@6V6*CƎ56Cb*23%@6V6*CƎ56Cb*:˗e %@7W7+CǏ57Cc+R[c %@7W7+CǏ57Cc+}k!%@7W7+CǏ57Cc+!%@7W7+CǏ57Cc++q"%@7W7+CǏ57Cc+2"%@7W7+CǏ57Cc+\x#%@7W7+CǏ57Cc+C#%@7W7+CǏ57Cc+p,~$%@7W7+CǏ57Cc+$?%%@7W7+CǏ57Cc+мQ%%@8X8,CȐ58Cd,RUd&%@8X8,CȐ58Cd,6v&%@8X8,CȐ58Cd,rl '%@8X8,CȐ58Cd,2'%@8X8,CȐ58Cd,ݵ(%@8X8,CȐ58Cd,N(%@8X8,CȐ58Cd,U)%@8X8,CȐ58Cd,Ҕ~)%@8X8,CȐ58Cd,r*%@8X8,CȐ58Cd, *%@9Y9-Cɑ59Ce-2\G&+%@9Y9-Cɑ59Ce-0+%@9Y9-Cɑ59Ce-wC,,%@9Y9-Cɑ59Ce-r3V,%@9Y9-Cɑ59Ce-~h2-%@9Y9-Cɑ59Ce-@{-%@9Y9-Cɑ59Ce-ٍ8.%@9Y9-Cɑ59Ce-kq.%@9Y9-Cɑ59Ce- >/%@9Y9-Cɑ59Ce-R/%@:Z:.Cʒ5:Cf.rh:D0%@:Z:.Cʒ5:Cf.R0%@:Z:.Cʒ5:Cf.kJ1%@:Z:.Cʒ5:Cf.ru1%@:Z:.Cʒ5:Cf.қ"Q2%@:Z:.Cʒ5:Cf.1452%@:Z:.Cʒ5:Cf.rGW3%@:Z:.Cʒ5:Cf.dZ3%@:Z:.Cʒ5:Cf.RYl]4%@:Z:.Cʒ5:Cf.4%@;[;/C˓5;Cg/r'.c5%@;[;/C˓5;Cg/2Ƥ5%@;[;/C˓5;Cg/^i6%@;[;/C˓5;Cg/j6%@;[;/C˓5;Cg/ُo7%@;[;/C˓5;Cg/I(7%@;[;/C˓5;Cg/v8%@;[;/C˓5;Cg/1Y8%@;[;/C˓5;Cg/R&|9%@;[;/C˓5;Cg/R99%@<\<0C̔5< Ch02"L:%@<\<0C̔5< Ch0^;%@<\<0C̔5< Ch02Sq;%@<\<0C̔5< Ch0R <%@<\<0C̔5< Ch0R<%@<\<0C̔5< Ch0=%@<\<0C̔5< Ch0r=%@<\<0C̔5< Ch0N>%@<\<0C̔5< Ch0>%@<\<0C̔5< Ch01?%@=]=1C͕5=!Ci1r?%@=]=1C͕5=!Ci1J$@%@=]=1C͕5=!Ci12H+@%@=]=1C͕5=!Ci12k=*A%@=]=1C͕5=!Ci1yPA%@=]=1C͕5=!Ci1c0B%@=]=1C͕5=!Ci1)uB%@=]=1C͕5=!Ci12C6C%@=]=1C͕5=!Ci12[ܚC%@=]=1C͕5=!Ci1t^>2CΖ5>"Cj2r D%@>^>2CΖ5>"Cj23BE%@>^>2CΖ5>"Cj2>E%@>^>2CΖ5>"Cj2wHF%@>^>2CΖ5>"Cj2p F%@>^>2CΖ5>"Cj2OG%@>^>2CΖ5>"Cj2Rk/G%@>^>2CΖ5>"Cj2R:BUH%@>^>2CΖ5>"Cj22TH%@>^>2CΖ5>"Cj2nkg[I%@?_?3Cϗ5?#Ck3zI%@?_?3Cϗ5?#Ck3rϜaJ%@?_?3Cϗ5?#Ck3R5J%@?_?3Cϗ5?#Ck327αgK%@?_?3Cϗ5?#Ck3fK%@?_?3Cϗ5?#Ck3mL%@?_?3Cϗ5?#Ck32`L%@?_?3Cϗ5?#Ck31sM%@?_?3Cϗ5?#Ck3M%@?_?3Cϗ5?#Ck32b!zN%@@`@4CИ6@$Cl4Z3N%@@`@4CИ6@$Cl4FO%@@`@4CИ6@$Cl4R,YP%@@`@4CИ6@$Cl4kP%@@`@4CИ6@$Cl4rq^~ Q%@@`@4CИ6@$Cl4;Q%@@`@4CИ6@$Cl4R%@@`@4CИ6@$Cl4r(R%@@`@4CИ6@$Cl4S%@@`@4CИ6@$Cl4RvZۘS%@ AaA 5Cљ6A%C m5IT%@ AaA 5Cљ6A%C m5rT%@ AaA 5Cљ6A%C m52$"U%@ AaA 5Cљ6A%C m5ͽ%U%@ AaA 5Cљ6A%C m5V8(V%@ AaA 5Cљ6A%C m5JV%@ AaA 5Cљ6A%C m5a].W%@ AaA 5Cљ6A%C m5A!pW%@ AaA 5Cљ6A%C m5"4X%@ AaA 5Cљ6A%C m5SX%@ BbB 6CҚ6B&C n62:Y%@ BbB 6CҚ6B&C n6фY%@ BbB 6CҚ6B&C n6@Z%@ BbB 6CҚ6B&C n6Z%@ BbB 6CҚ6B&C n6OF[%@ BbB 6CҚ6B&C n6[%@ BbB 6CҚ6B&C n6nM\%@ BbB 6CҚ6B&C n6R`*\%@ BbB 6CҚ6B&C n6S j%@ EeE 9C՝6E)C q92&k%@ EeE 9C՝6E)C q9RpEk%@ EeE 9C՝6E)C q9R X,l%@ EeE 9C՝6E)C q9Rjl%@ EeE 9C՝6E)C q9?<}2m%@FfF:C֞6F*Cr:rlՏm%@FfF:C֞6F*Cr:n8n%@FfF:C֞6F*Cr:n%@FfF:C֞6F*Cr:>o%@FfF:C֞6F*Cr:20:o%@FfF:C֞6F*Cr:eDp%@FfF:C֞6F*Cr:Ҝlp%@FfF:C֞6F*Cr:Kq%@FfF:C֞6F*Cr:$q%@FfF:C֞6F*Cr:M87Qr%@GgG;Cן6G+Cs;rIr%@GgG;Cן6G+Cs;j\Ws%@GgG;Cן6G+Cs;r os%@GgG;Cן6G+Cs;2Q]t%@GgG;Cן6G+Cs;6t%@GgG;Cן6G+Cs;Ϧcu%@GgG;Cן6G+Cs;&iu%@GgG;Cן6G+Cs;qiv%@GgG;Cן6G+Cs;rv%@GgG;Cן6G+Cs; 5ow%@HhH<Cؠ6H,Ct<]w%@HhH<Cؠ6H,Ct<gvx%@HhH<Cؠ6H,Ct<)x%@HhH<Cؠ6H,Ct<rX;|y%@HhH<Cؠ6H,Ct<3Ny%@HhH<Cؠ6H,Ct<`z%@HhH<Cؠ6H,Ct<cfs{%@HhH<Cؠ6H,Ct<{%@HhH<Cؠ6H,Ct< |%@HhH<Cؠ6H,Ct<r2|%@IiI=C١6I-Cu=r˽}%@IiI=C١6I-Cu=2EeД}%@IiI=C١6I-Cu=~%@IiI=C١6I-Cu=R~%@IiI=C١6I-Cu={1%@IiI=C١6I-Cu=%@IiI=C١6I-Cu=RSd-$%@IiI=C١6I-Cu=?%@IiI=C١6I-Cu=R2R*%@IiI=C١6I-Cu=r0e%@JjJ>Cڢ6J.Cv>Rw0%@JjJ>Cڢ6J.Cv>2c%@JjJ>Cڢ6J.Cv>6%@JjJ>Cڢ6J.Cv>~%@JjJ>Cڢ6J.Cv>/<%@JjJ>Cڢ6J.Cv>vԿ%@JjJ>Cڢ6J.Cv>bB%@JjJ>Cڢ6J.Cv>uŅ%@JjJ>Cڢ6J.Cv>2 I%@JjJ>Cڢ6J.Cv>2|/̆%@KkK?Cۣ6K/Cw?1O%@KkK?Cۣ6K/Cw?bD҇%@KkK?Cۣ6K/Cw?VU%@KkK?Cۣ6K/Cw?2i؈%@KkK?Cۣ6K/Cw?+/|[%@KkK?Cۣ6K/Cw?ҹȎމ%@KkK?Cۣ6K/Cw?rJba%@KkK?Cۣ6K/Cw?%@KkK?Cۣ6K/Cw?pg%@KkK?Cۣ6K/Cw?/%@LlL@Cܤ6L0Cx@Rm%@LlL@Cܤ6L0Cx@7b%@LlL@Cܤ6L0Cx@t%@LlL@Cܤ6L0Cx@p#%@LlL@Cܤ6L0Cx@/6z%@LlL@Cܤ6L0Cx@H%@LlL@Cܤ6L0Cx@Qb[%@LlL@Cܤ6L0Cx@m%@LlL@Cܤ6L0Cx@%@LlL@Cܤ6L0Cx@C/ %@MmMACݥ 6M1CyARȥ%@MmMACݥ 6M1CyAb%@MmMACݥ 6M1CyAEʒ%@MmMACݥ 6M1CyA%@MmMACݥ 6M1CyAR/%@MmMACݥ 6M1CyAW%@MmMACݥ 6M1CyA c%@MmMACݥ 6M1CyA'"%@MmMACݥ 6M1CyAy:%@MmMACݥ 6M1CyAr30M(%@NnNBCަ 6N2CzB_%@NnNBCަ 6N2CzBcr.%@NnNBCަ 6N2CzBk%@NnNBCަ 6N2CzB+4%@NnNBCަ 6N2CzBR0%@NnNBCަ 6N2CzBʼ:%@NnNBCަ 6N2CzBxdϽ%@NnNBCަ 6N2CzB@@%@NnNBCަ 6N2CzBr Ú%@NnNBCަ 6N2CzB1G%@OoOCCߧ 6O3C{C2ʛ%@OoOCCߧ 6O3C{C2re,M%@OoOCCߧ 6O3C{C2C>М%@OoOCCߧ 6O3C{CQS%@OoOCCߧ 6O3C{C22d֝%@OoOCCߧ 6O3C{CRvY%@OoOCCߧ 6O3C{Crfܞ%@OoOCCߧ 6O3C{C2r_%@OoOCCߧ 6O3C{CM%@OoOCCߧ 6O3C{C+4e%@PpPDC 7P4C|D2 %@PpPDC 7P4C|D2gk%@PpPDC 7P4C|D%@PpPDC 7P4C|DR r%@PpPDC 7P4C|D5%@PpPDC 7P4C|D0x%@PpPDC 7P4C|DjiC%@PpPDC 7P4C|D2VV~%@PpPDC 7P4C|DCh%@PpPDC 7P4C|D27{%@QqQEC 7Q5C}E#э%@QqQEC 7Q5C}Ek%@QqQEC 7Q5C}E2  %@QqQEC 7Q5C}EŐ%@QqQEC 7Q5C}E8%@QqQEC 7Q5C}Eꖨ%@QqQEC 7Q5C}ERl%@QqQEC 7Q5C}E%@QqQEC 7Q5C}E2" %@QqQEC 7Q5C}E2:5%@RrRFC7R6C~F2G&%@RrRFC7R6C~FnZ%@RrRFC7R6C~FRm,%@RrRFC7R6C~Fr%@RrRFC7R6C~Fr =2%@RrRFC7R6C~FRפ%@RrRFC7R6C~F&q8%@RrRFC7R6C~F26 ʻ%@RrRFC7R6C~FRG>%@RrRFC7R6C~FRZ?%@SsSGC7S7CGoE%@SsSGC7S7CGsȰ%@SsSGC7S7CG 'K%@SsSGC7S7CG9α%@SsSGC7S7CGALQ%@SsSGC7S7CG^Բ%@SsSGC7S7CGvqW%@SsSGC7S7CG22ڳ%@SsSGC7S7CG2U]%@SsSGC7S7CGzD%@TtTHC7T8CH޻c%@TtTHC7T8CHx%@TtTHC7T8CH2i%@TtTHC7T8CH2%@TtTHC7T8CHLGp%@TtTHC7T8CHr|%@TtTHC7T8CHҭ{+v%@TtTHC7T8CH>%@TtTHC7T8CHP|%@TtTHC7T8CHrLJc%@UuUIC7U9CIu%@UuUIC7U9CI2~%@UuUIC7U9CI2%@UuUIC7U9CI9 %@UuUIC7U9CIxM%@UuUIC7U9CI%@UuUIC7U9CIR唽%@UuUIC7U9CI2B%@UuUIC7U9CI %@UuUIC7U9CIP%@VvVJC7V:CJ/%@VvVJC7V:CJhB$%@VvVJC7V:CJҵU%@VvVJC7V:CJg*%@VvVJC7V:CJWTz%@VvVJC7V:CJr0%@VvVJC7V:CJr%@VvVJC7V:CJ2V#6%@VvVJC7V:CJĹ%@VvVJC7V:CJR X<%@WwWKC7W;CKe%@WwWKC7W;CKrÌB%@WwWKC7W;CK2#'%@WwWKC7W;CK҄!I%@WwWKC7W;CK[4%@WwWKC7W;CKRMFO%@WwWKC7W;CK2Y%@WwWKC7W;CK+lU%@WwWKC7W;CKr~%@WwWKC7W;CK_[%@ XxX LC7XC"NRr %@"ZzZ"NC7Z>C"N*%@"ZzZ"NC7Z>C"N2A="%@"ZzZ"NC7Z>C"Nr2O%@"ZzZ"NC7Z>C"NRvb(%@"ZzZ"NC7Z>C"N2fu%@"ZzZ"NC7Z>C"N.%@"ZzZ"NC7Z>C"NF%@"ZzZ"NC7Z>C"NA4%@"ZzZ"NC7Z>C"N{%@#[{[#OC7[?C#O:%@#[{[#OC7[?C#O,%@#[{[#OC7[?C#O2K@%@#[{[#OC7[?C#OR| %@#[{[#OC7[?C#O'G%@#[{[#OC7[?C#O/%@#[{[#OC7[?C#OAM%@#[{[#OC7[?C#OR2QT%@#[{[#OC7[?C#O2fS%@#[{[#OC7[?C#Oy%@$\|\$PC7\@C$PM!Y%@$\|\$PC7\@C$P%@$\|\$PC7\@C$PV_%@$\|\$PC7\@C$Px%@$\|\$PC7\@C$Pr5e%@$\|\$PC7\@C$P&%@$\|\$PC7\@C$P2k%@$\|\$PC7\@C$PRv\%@$\|\$PC7\@C$P: r%@$\|\$PC7\@C$P3%@%]}]%QC7]AC%Q,Fx%@%]}]%QC7]AC%Q2X%@%]}]%QC7]AC%QR[bk~%@%]}]%QC7]AC%Q'}%@%]}]%QC7]AC%Q%@%]}]%QC7]AC%Q2%@%]}]%QC7]AC%Q͵%@%]}]%QC7]AC%Qlh %@%]}]%QC7]AC%QBې%@%]}]%QC7]AC%Q%@&^~^&RC7^BC&RR8%@&^~^&RC7^BC&Rr%@&^~^&RC7^BC&R2n%%@&^~^&RC7^BC&R҉ 8 %@&^~^&RC7^BC&RRjJ%@&^~^&RC7^BC&RrL?]&%@&^~^&RC7^BC&Rr0o%@&^~^&RC7^BC&R2u,%@&^~^&RC7^BC&R%@&^~^&RC7^BC&R窧2%@'__'SC7_CC'S2E%@'__'SC7_CC'S28%@'__'SC7_CC'Sҭ{߻%@'__'SC7_CC'Sr>%@'__'SC7_CC'S%@'__'SC7_CC'SLE%@'__'SC7_CC'Sz)%@'__'SC7_CC'S2r&@6nҎ n6bC*8 nRC6b:6>&@6nҎ n6bC*8 nRC6b2H?&@7oӏ o7cC+8 oSC7c2r[?&@7oӏ o7cC+8 oSC7cn$@&@7oӏ o7cC+8 oSC7crª@&@7oӏ o7cC+8 oSC7cF*A&@7oӏ o7cC+8 oSC7c⥭A&@7oӏ o7cC+8 oSC7c~0B&@7oӏ o7cC+8 oSC7c˳B&@7oӏ o7cC+8 oSC7c26C&@7oӏ o7cC+8 oSC7cr3SC&@7oӏ o7cC+8 oSC7crL=D&@8pԐ p8dC,9 pTC8dRgD&@8pԐ p8dC,9 pTC8d'(CE&@8pԐ p8dC,9 pTC8dr:E&@8pԐ p8dC,9 pTC8d_MIF&@8pԐ p8dC,9 pTC8d_F&@8pԐ p8dC,9 pTC8drrOG&@8pԐ p8dC,9 pTC8d-4G&@8pԐ p8dC,9 pTC8drUЗUH&@8pԐ p8dC,9 pTC8d~lH&@8pԐ p8dC,9 pTC8d[I&@9qՑ q9eC-9 qUC9e2֤I&@9qՑ q9eC-9 qUC9eAaJ&@9qՑ q9eC-9 qUC9e5J&@9qՑ q9eC-9 qUC9egyhK&@9qՑ q9eC-9 qUC9eK&@9qՑ q9eC-9 qUC9eб,nL&@9qՑ q9eC-9 qUC9eN?L&@9qՑ q9eC-9 qUC9eRAQtM&@9qՑ q9eC-9 qUC9eR|dM&@9qՑ q9eC-9 qUC9e2"wzN&@:r֒r:fC.9rVC:fN&@:r֒r:fC.9rVC:f28[O&@:r֒r:fC.9rVC:fRzP&@:r֒r:fC.9rVC:f2P&@:r֒r:fC.9rVC:f0 Q&@:r֒r:fC.9rVC:frKQ&@:r֒r:fC.9rVC:fҔhR&@:r֒r:fC.9rVC:f R&@:r֒r:fC.9rVC:f,S&@:r֒r:fC.9rVC:fr{=1S&@;sדs;gC/9sWC;gCT&@;sדs;gC/9sWC;g2vVT&@;sדs;gC/9sWC;g2ri"U&@;sדs;gC/9sWC;gȮ{U&@;sדs;gC/9sWC;gK(V&@;sדs;gC/9sWC;gx砫V&@;sדs;gC/9sWC;g2ԃ.W&@;sדs;gC/9sWC;g1 ƱW&@;sדs;gC/9sWC;g4X&@;sדs;gC/9sWC;grXX&@vږv>jC29vZC>jrx.rxc&@>vږv>jC29vZC>jR˄c&@>vږv>jC29vZC>jg~d&@>vږv>jC29vZC>jRe&@>vږv>jC29vZC>jre&@>vږv>jC29vZC>j1=f&@>vږv>jC29vZC>jRf&@>vږv>jC29vZC>jTv g&@>vږv>jC29vZC>j2g&@>vږv>jC29vZC>jrh&@?wۗw?kC39w[C?kRL,h&@?wۗw?kC39w[C?k>i&@?wۗw?kC39w[C?kLQi&@?wۗw?kC39w[C?k!d j&@?wۗw?kC39w[C?kvj&@?wۗw?kC39w[C?k)[&k&@?wۗw?kC39w[C?krk&@?wۗw?kC39w[C?kp,l&@?wۗw?kC39w[C?k1l&@?wۗw?kC39w[C?k2m&@@xܘx@lC49x\C@lhjm&@@xܘx@lC49x\C@lr8n&@@xܘx@lC49x\C@l n&@@xܘx@lC49x\C@lp@?o&@@xܘx@lC49x\C@l!0o&@@xܘx@lC49x\C@lyCEp&@@xܘx@lC49x\C@lVp&@@xܘx@lC49x\C@lR?hKq&@@xܘx@lC49x\C@lrO{q&@@xܘx@lC49x\C@lRQr&@AyݙyAmC 59y]CA mmr&@AyݙyAmC 59y]CA mr*&Ws&@AyݙyAmC 59y]CA ms&@AyݙyAmC 59y]CA m_]t&@AyݙyAmC 59y]CA mrmt&@AyݙyAmC 59y]CA m2cu&@AyݙyAmC 59y]CA mr5u&@AyݙyAmC 59y]CA m"jv&@AyݙyAmC 59y]CA mo5v&@AyݙyAmC 59y]CA m2V Hpw&@BzޚzBnC 69z^CB n#Zw&@BzޚzBnC 69z^CB nEmvx&@BzޚzBnC 69z^CB nRx&@BzޚzBnC 69z^CB n|y&@BzޚzBnC 69z^CB nky&@BzޚzBnC 69z^CB n2Bz&@BzޚzBnC 69z^CB nrV{&@BzޚzBnC 69z^CB n܈{&@BzޚzBnC 69z^CB nRЏ |&@BzޚzBnC 69z^CB n,|&@C{ߛ{CoC 79{_CC oR}&@C{ߛ{CoC 79{_CC ornf'}&@C{ߛ{CoC 79{_CC orQ:~&@C{ߛ{CoC 79{_CC o26L~&@C{ߛ{CoC 79{_CC o=_&@C{ߛ{CoC 79{_CC oq&@C{ߛ{CoC 79{_CC ov$&@C{ߛ{CoC 79{_CC o&@C{ߛ{CoC 79{_CC oȰ*&@C{ߛ{CoC 79{_CC o2M&@D||DpC 89|`CD pr0&@D||DpC 89|`CD p᳂&@D||DpC 89|`CD pR$6&@D||DpC 89|`CD p&@D||DpC 89|`CD pr^=&@D||DpC 89|`CD pz+&@D||DpC 89|`CD pv>C&@D||DpC 89|`CD pRt5Qƅ&@D||DpC 89|`CD pscI&@D||DpC 89|`CD p2uov̆&@E}}EqC 99}aCE qRx O&@E}}EqC 99}aCE q2}҇&@E}}EqC 99}aCE q҃FU&@E}}EqC 99}aCE qr؈&@E}}EqC 99}aCE q[&@E}}EqC 99}aCE qމ&@E}}EqC 99}aCE qa&@E}}EqC 99}aCE q2W &@E}}EqC 99}aCE qh&@E}}EqC 99}aCE q0&@F~~FrC:9~bCFr.Cn&@F~~FrC:9~bCFrU&@F~~FrC:9~bCFr)iht&@F~~FrC:9~bCFrrC{&@F~~FrC:9~bCFr_z&@F~~FrC:9~bCFr}@&@F~~FrC:9~bCFr2ݲ&@F~~FrC:9~bCFrz&@F~~FrC:9~bCFr؆&@F~~FrC:9~bCFr &@GGsC;9cCGs-R&@GGsC;9cCGsV&@GGsC;9cCGs"&@GGsC;9cCGs2)5&@GGsC;9cCGs2G&@GGsC;9cCGs dZ&@GGsC;9cCGs<m&@GGsC;9cCGso"&@GGsC;9cCGs;&@GGsC;9cCGsؤ(&@HHtC<:dCHtv&@HHtC<:dCHt2O.&@HHtC<:dCHtܱ&@HHtC<:dCHtM4&@HHtC<:dCHtr &@HHtC<:dCHt2K;&@HHtC<:dCHt%'&@HHtC<:dCHt9A&@HHtC<:dCHt`LĚ&@HHtC<:dCHtc^G&@IIuC=:eCIu2qʛ&@IIuC=:eCIu7M&@IIuC=:eCIuHՖМ&@IIuC=:eCIurS&@IIuC=:eCIur֝&@IIuC=:eCIu=Y&@IIuC=:eCIuRJܞ&@IIuC=:eCIuR_&@IIuC=:eCIuRC&@IIuC=:eCIu"f&@JJvC>:fCJvR+&@JJvC>:fCJvX]>l&@JJvC>:fCJvP&@JJvC>:fCJvcr&@JJvC>:fCJv~5v&@JJvC>:fCJv҈x&@JJvC>:fCJvJp&@JJvC>:fCJv ~&@JJvC>:fCJvR&@JJvC>:fCJvҊHӄ&@KKwC?:gCKw2&@KKwC?:gCKwRi&@KKwC?:gCKw2 &@KKwC?:gCKwN&@KKwC?:gCKwR[0&@KKwC?:gCKw;B&@KKwC?:gCKwU&@KKwC?:gCKw/4h&@KKwC?:gCKwz &@KKwC?:gCKwr*o&@L LxC@: hCLx &&@L LxC@: hCLx,&@L LxC@: hCLxrG,&@L LxC@: hCLx5ׯ&@L LxC@: hCLx22&@L LxC@: hCLxrF &@L LxC@: hCLxRѽ9&@L LxC@: hCLx^["&@L LxC@: hCLxr4?&@L LxC@: hCLx|G¯&@M!MyCA:!iCMy4ZE&@M!MyCA:!iCMylȰ&@M!MyCA:!iCMyR8oK&@M!MyCA:!iCMy α&@M!MyCA:!iCMyhQ&@M!MyCA:!iCMyHԲ&@M!MyCA:!iCMyW&@M!MyCA:!iCMy2?ڳ&@M!MyCA:!iCMyr ]&@M!MyCA:!iCMy&@N"NzCB:"jCNz%\d&@N"NzCB:"jCNzR&&@N"NzCB:"jCNzr9j&@N"NzCB:"jCNz5L&@N"NzCB:"jCNz2^p&@N"NzCB:"jCNzspq&@N"NzCB:"jCNz"v&@N"NzCB:"jCNzӫ&@N"NzCB:"jCNz2I|&@N"NzCB:"jCNzR9&@O#O{CC:#kCO{΂&@O#O{CC:#kCO{"&@O#O{CC:#kCO{_&@O#O{CC:#kCO{2^ &@O#O{CC:#kCO{&@O#O{CC:#kCO{+&@O#O{CC:#kCO{RW7>&@O#O{CC:#kCO{P&@O#O{CC:#kCO{rc&@O#O{CC:#kCO{rv&@P$P|CD:$lCP|k&@P$P|CD:$lCP|4L$&@P$P|CD:$lCP|魧&@P$P|CD:$lCP|̇*&@P$P|CD:$lCP|%ӭ&@P$P|CD:$lCP|Rl0&@P$P|CD:$lCP|>a&@P$P|CD:$lCP| 7&@P$P|CD:$lCP|&@P$P|CD:$lCP|r:0=&@Q%Q}CE:%mCQ}B&@Q%Q}CE:%mCQ}2uvUC&@Q%Q}CE:%mCQ}RRh&@Q%Q}CE:%mCQ}21zI&@Q%Q}CE:%mCQ}P&@Q%Q}CE:%mCQ}RO&@Q%Q}CE:%mCQ}؋&@Q%Q}CE:%mCQ})U&@Q%Q}CE:%mCQ}r&@Q%Q}CE:%mCQ}e[&@R&R~CF:&nCR~r{&@R&R~CF:&nCR~hb&@R&R~CF:&nCR~W?"&@R&R~CF:&nCR~RH4h&@R&R~CF:&nCR~:{G&@R&R~CF:&nCR~2/Zn&@R&R~CF:&nCR~2%l&@R&R~CF:&nCR~2Ut&@R&R~CF:&nCR~&@R&R~CF:&nCR~Rz&@S'SCG:'oCS/&@S'SCG:'oCSrɀ&@S'SCG:'oCSrk&@S'SCG:'oCS &@S'SCG:'oCSr &@S'SCG:'oCSE&@S'SCG:'oCS$&&@S'SC##DTt`ݼ?;? As8?A>Kڞj? Xh?( ӵ?2 ;?< o9?F %mO5?Pk,PA4?Z?d_tg?n9?xӒ?m,PA4??_tg?;?Ւ?7 @t@ѯA@Ȟ|@kISM@8 @t@үA@ȟ|@lISM@9 @"t@,ӯA @6Ƞ| @@mISM @J:  @Tt @^ԯA @hȡ|@rnISM@| T @dqvs@ @dQ>C@@䷤@d T @qvs@d @Q>C@@d@ T @dqvs@ @dR>C@@两@d T @qvs@&d @0R>C@@:d@D T @Ndqvs@X @bdS>C@@l乤@vd T @qvs@d @S>C@@d@ T @dqvs@ @dT>C@@交@d! T @qvs@d @T>C@@d@ * @28]9 @ rkl @**! @4]T @>2*!@Hr8]9!@Rkl!@\*!!@f2^T!@pr*"@z8]9"@2`l"@ro!"@U"@Q#@2ﳑ9#@̫l#@t"#@2lUU#@#6$@+Eٻ9$@rl$@ R4^"$@U$@/;%@(*'9%@2RXkl%@<~P"%@F؍U%@PR8&@Z|9&@d2l&@n(=#&@xvLV&@Ҏ'@Rqؼ9'@RIl'@e#'@RV'@R.(@;9(@rZzl(@Ғp#(@RbV(@@@@@##DT0 X3?_d?Rץ??!9ߪF ?#Ӣ?&(?(y%[? +9NG? - w׼?0ɡof?2?5FB?7 B?9l<"?,2KLa?&A _?)C't?,EԢV8?/G?2J?5Lt`?8NA.Gm+?? Q? gp? |4? ׭g? S? G>*? *|?ç (?ƨ qG' ?Ȫ )fq?˫ 1?έ ?Ѯ S;g?԰ ?ֱ E ?ٲ {q]?ܴ 3=P]?ߵ [H? zZ4S? ]? d ? H? n? ?? 2y>? Q? gp? !|4? ٭g? S? I>*?  *|? (? sG' ? +fq? 1?̐Q ?͐*3?ΐp`\?ϐ"Å?А>帮?ѐ?!Ґj?#ӐS=-)?&ԐR?(Ր \{?+Րgt{?-֐z7q?0א f?2ؐ|\?5ِ(RH?7ِ5AHq?9ڐG>?<ې3?>ېIf)?AܐK?Cݐ>?Eݐ^ g?Gސ?Jߐ3V?Lߐr?NQ ?Q+3?Sᐇp`\?U"Å?W?帮?Y␛?\j?^T=-)?`䐰R?b \{?dit{?fz7q?h! f?k}\?m(RH?o5AHq?q搒G>?s3?uJf)?w琦K?y>?{_ g?}琻?3V?s?Q ?,3?琈p`\?"Å?@帮?琝?j?U=-)?琱R? \{?it{?z7q?" f?~\?(RH?7AHq?搓G>?3?Kf)?吧K?>?` g?䐼?3V?t?Q ?-3?␉p`\?"Å?A帮??j?ߐV=-)?ߐR?ސ\{?ݐkt{?ݐz7q?ܐ# f?ې\?ې(RH?ڐ7AHq?ِG>?ِ3?ؐLf)?אK?֐>?Րa g?Ր?Ԑ3V?Ӑu?p@H@HE8f.@HB@Hr\W@OTk@V5R@ȫ͔@YG@.½@ȵu=@Hd@H}3@HL^@Hn?)$@ 8@#M@xka@۾&v@ܽ@ݼȂB @ݻH1h@޹HI@߸H+{@߷H;a @p@ȗ@E8f.@B@ȡr\W@OTk@HV5R@H͔@HZG@H.½@ȶu=@d@}3@L^@n?)$@ 8@H#M@Hyka@H'v@H@ȃB @1h@I@ȍ+{@;a @p@H@HF8f.@HB@Hr\W@PTk@V5R@Ȭ͔@ZG@}.½@{ȶu=@yHe@wH}3@uHL^@sHo?)$@q 8@o#M@myka@k'v@h@fȃB @dH2h@bHI@`H+{@^HL^@a @\Kp@YHȚ@WEH8f.@UBB@S?Ȥr\W@Q#L^@<q?)$@9 8@7H#M@5H|ka@2H*v@0H@- ȆB @+ 4h@(I@&Ȑ+{@#>a @!dvv@Mx @$X3@p!@c9+@5@䀫)@@WOfJ@ .T@ l^@:i@$M\s@$}@$b&/ׇ@$9ʟ@dnR@d@d̰@dYb @dlG@dCC@껤E@縤$@䵤Ȍ=@Ⲥ0{@߯vv@ܫMx @٨$X3@֥p!@Ԣc9+@џ5@Μ$)@@˙$XOfJ@Ȗ$/T@Ɠ$l^@Ðd:i@dM\s@d}@db&/ׇ@d9ʟ@dnR@}@z̰@wYb @tlG@qCC@nE@k$@hȌ=@e0{@bvv@_$Nx @\$%X3@Y$p!@V$c9+@Sd5@Pd)@@MdXOfJ@Jd/T@|Gdl^@yDd:i@vAM\s@s>}@p;b&/ׇ@m99ʟ@j6nR@g3@d0侵̰@a-Yb @^*lG@Z'CC@W$$E@T!$$@Q$Ɍ=@N$0{@Kdwv@HdNx @Ed%X3@Bdp!@?dc9+@< d5@8)@@5XOfJ@2/T@/l^@,:i@)M\s@&䋂}@#b&/ׇ@9ʟ@nR@$@$̰@$Yb @$mG@ dDC@ dE@d$@dɌ=@d0{@dwv@ӤNx @Ф%X3@Τp!@ˤc9+@5@䁫)@@XOfJ@/T@l^@޼:i@ں$M\s@׷$}@Ե$c&/ׇ@Ѳ$:ʟ@ΰdnR@ˮd@ȫd̰@ĩdYb @dmG@dDC@E@$@Ɍ=@0{@wv@Nx @%X3@p!@c9+@5@$)@@$YOfJ@$0T@$l^@d:i@dM\s@d}@|dc&/ׇ@zd:ʟ@xdnR@}v@zt̰@wrYb @tpmG@qnDC@nlE@kj$@hhɌ=@eg0{@bewv@_c$Ox @\a$&X3@Y_$p!@V]$c9+@S[d5@PZd)@@MXdYOfJ@JVd0T@GTdl^@DRd:i@AQM\s@>O}@;Mc&/ׇ@9L:ʟ@6JnR@3H@0G俵̰@-EYb @*DmG@'BDC@$@$E@!?$$@=$ʌ=@<$0{@:dxv@9dOx @7d&X3@6dp!@5dc9+@ 3d5@2)@@0YOfJ@/0T@.l^@,:i@+M\s@*䌂}@)c&/ׇ@':ʟ@&nR@%$@$$̰@#$Yb @!$nG@ dEC@dE@d$@dʌ=@d0{@dxv@Ox @&X3@p!@c9+@5@䂫)@@YOfJ@0T@l^@:i@$M\s@$}@$d&/ׇ@$;ʟ@dnR@ d@ d̰@ dYb @ dnG@ dEC@ E@ $@ʌ=@0{@xv@Ox @&X3@p!@c9+@5@$)@@$ZOfJ@$1T@$l^@d:i@dM\s@d}@|dd&/ׇ@zd;ʟ@xdnR@v@t̰@rYb @pnG@nEC@lE@j$@hʌ=@g0{@exv@c$Px @a$'X3@_$p!@]$c9+@[d5@Zd)@@XdZOfJ@Vd1T@Tdl^@Rd:i@QdM\s@Od}@Mdd&/ׇ@L;ʟ@JnR@H@G̰@EYb @DnG@BEC@@E@?$@=ʌ=@<$0{@:$yv@9$Px @7$'X3@6$p!@5$c9+@3d5@2d)@@0dZOfJ@/d1T@. l^@, :i@+ M\s@* }@) d&/ׇ@' ;ʟ@& nR@%@$̰@#Yb @!$oG@ $FC@$E@$$@$ˌ=@$0{@dyv@dPx @d'X3@dp!@c9+@5@)@@ZOfJ@1T@l^@:i@ M\s@!䍂}@#d&/ׇ@$$<ʟ@%$nR@ &$@ '$̰@ )$Yb @ *$oG@ +dFC@ ,dE@ .d$@/dˌ=@00{@2yv@3Px @5'X3@6p!@7c9+@95@:䃫)@@ @#2C @$O I @% 7)N @&GS @'xfX @),1] @*~b @+Сg @,2"Zl @.ztr @/2fw @0Q=| @2R=j;\ @3 (z @5R @6_d @7Rו @9 @:rU @<E3 @=rQ @?!Kp @@$pn @B'\& @D*GA̾ @E-3 @G0O @H32 7) @J6G @L92xf @M;,1 @O>R~ @QAңС @RDR"Z @TGzt @VJRf @XMQ= @ZPr=j;\!@[S(z!@]Vr !@_Y_d!@a\!@c_!@ebU !@geE3%!@hhQ*!@jkKp/!@lnpn4!@nq2\&9!@ptGA>!@rw23C!@tzO I!@v}R 7)N!@xGS!@zRxfX!@|,1]!@R~b!@Сg!@r"Zl!@ztr!@rfw!@R=|!@=j;\!@)z!@!@`d!@ו!@2!@U!@2E3!@Q!@RKp!@pn!@R\&!@GA̾!@R3!@O !@r 7)!@G!@rxf!@,1!@ג~!@С!@ޒ"Z!@{t!@f!@R=!@=j;\"@2)z"@ "@2`d"@"@R"@U "@RE3%"@ҙQ*"@RKp/"@ pn4"@ r\&9"@GA>"@r3C"@O I"@ 7)N"@GS"@xfX"@#,1]"@&~b"@)2Сg"@,rAZl"@/r"@2Riw"@5r=|"@86@\"@ s."@Av"@DyR,vz"@G|4"@Jri"@Mf="@P2q a\#@S{#@VC]ԙ #@Y8#@\G#@_R;Z#@brH #@eRt3%#@hz].R*#@k p/#@nw4#@qRg[9#@t?>#@wR/C#@zv I#@}'(B)N#@.GS#@R錵fX#@rV@o]#@Rv(b#@Hg#@^l#@Vr#@2w#@r=|#@R;\#@Ѳ<{#@Ҕ#@֒h#@$jו#@2##@d#@rY3#@{QR#@r q#@]ď#@ZU~#@ 8;#@m#@ #@I\e)#@RH#@rf#@2Ѩ#@cnL#@4#@r#@ Jy#@ ҧ3#@T=#@z\$@`{$@ $@2Ը$@R~L$@H$@!R $@#RU3%$@&uR*$@(rU/q/$@ +t&4$@ -29$@0\>$@2ۜC$@5Rcp I$@7D)N$@9DHS$@|ŷ]$@&Aqb$@)CR9t+g$@,ELl$@/G%r$@2JRXw$@5L>|$@8NG\$@$@F\%@2{%@g %@l!%@޹%@%@rۚO %@e 4%%@r~R*%@q}q/%@R4e74%@2Y9%@N>%@JDeC%@ҷ: I%@R1)N%@r)HS%@R."MgX%@e]%@Ob%@{g%@çr< 5l%@ƨ>r%@Ȫrw%@˫[c>|%@έ2u]%@ѮA{%@԰r%@ֱJ%@ٲRؕ%@ܴo%@ߵy%@Ҷ34%@Rf R%@繒 q%@Ra%@Ҥ%@;%@K&%@+.I %@R6*%@@H%@ÒIwg%@ĒT1%@r`%@l%@x_%@ ɲF%@ 2n%@2H>%@ղG]&@r|&@ΒԻ &@Ru&@/&@ &@!Ғ &@#83^4%&@&ZHS*&@(ղ/^q/&@+2t4&@-2F9&@0ݣ>&@2R}C&@5rt I&@7.*N&@9r HS&@2B]]&@Aܒ^b&@Cݲc|g&@ERl&@G޲Er&@J߲w&@Lrf>|&@Net]&@Q<.|&@Sr|^蚋&@UᲓ&@W]\ؕ&@Yr&@\ &@^4&@`r;ES&@bbq&@d&@frns&@h-ξ&@k&@mR1 &@o]\*&@qEI&@s2"g&@u璱㊆&@wE&@y2@&@{rp&@}Rs&@- &@2>&@2'6]'@Ki\|'@# '@й'@'@'@rC'@2A I'@~*N'@0EIS'@gX'@咁9]'@26ytb'@r.g'@Rl'@҃<r'@] w'@4?|'@r]'@ⲰJ|'@F'@'@2ؕ'@du'@/'@4'@ߒ]>S'@2^r'@Ri'@2ӯ'@ܒ?kξ'@6G'@ے '@2=T*'@RLvI'@0h'@ؒC'@ҩ'@֒_'@9'@O'@@ '@R4I?'@Ғ<^(@RF|(@в7x (@q2(@β(@h?(@2a (@(5%(@RNS*(@rr/(@RK4(@Dz c9(@Ʋ>(@r+zC(@G~4 I(@*N(@Ҙ>IS(@2͟chX(@۾2](@ܽMdإb(@ݼrǒg(@ݻr+Ml(@޹2Kr(@߸ w(@߷[|?|(@R6^(@ല *|(@Ჲ;(@re(@ⰲd ٕ(@(@R((@ (L5(@2'T(@)'r(@RB&t(@ %,(@r#ξ(@!(@栲T (@R +(@[I(@##DTG:'oCSR.9&@S'SCG:'oCS9L&@S'SCG:'oCS2G^&@T(TCH:(pCTRV[q&@T(TCH:(pCT2g&@T(TCH:(pCTy"&@T(TCH:(pCTr5&@T(TCH:(pCTӻ(&@T(TCH:(pCTҼqΫ&@T(TCH:(pCT.&@T(TCH:(pCT&@T(TCH:(pCTL5&@T(TCH:(pCT.&@U)UCI:)qCUO+;&@U)UCI:)qCUr&>&@U)UCI:)qCUPA&@U)UCI:)qCUrbc&@U)UCI:)qCUvG&@U)UCI:)qCU&@U)UCI:)qCU2;=M&@U)UCI:)qCUhۭ&@U)UCI:)qCUyS&@U)UCI:)qCU&@V*VCJ:*rCVY&@V*VCJ:*rCVr0T&@V*VCJ:*rCVf `&@V*VCJ:*rCV&@V*VCJ:*rCV.0f&@V*VCJ:*rCVB&@V*VCJ:*rCVrRkUl&@V*VCJ:*rCVґ h&@V*VCJ:*rCVҧzr&@V*VCJ:*rCVF&@W+WCK:+sCWZx&@W+WCK:+sCW&@W+WCK:+sCWr ~&@W+WCK:+sCWr3&@W+WCK:+sCWr]&@W+WCK:+sCW&@W+WCK:+sCWr&@W+WCK:+sCWm8"&@W+WCK:+sCW4&@W+WCK:+sCWuG&@X,XC L;,tCX lZ&@X,XC L;,tCX rıl&@X,XC L;,tCX P&@X,XC L;,tCX rz &@X,XC L;,tCX R،&@X,XC L;,tCX 7+&&@X,XC L;,tCX ɩ&@X,XC L;,tCX 2g,&@X,XC L;,tCX `&@X,XC L;,tCX Ǥ3&@Y-YC!M;-uCY!0C&@Y-YC!M;-uCY!r&9&@Y-YC!M;-uCY!r9&@Y-YC!M;-uCY!RtL?&@Y-YC!M;-uCY!^&@Y-YC!M;-uCY!2U[qE&@Y-YC!M;-uCY!r&@Y-YC!M;-uCY!R=K&@Y-YC!M;-uCY!6&@Y-YC!M;-uCY!,ջQ&@Z.ZC"N;.vCZ"Ҧs&@Z.ZC"N;.vCZ"#W&@Z.ZC"N;.vCZ"Ҡ&@Z.ZC"N;.vCZ" O^&@Z.ZC"N;.vCZ"&@Z.ZC"N;.vCZ"R%+d&@Z.ZC"N;.vCZ"R*>&@Z.ZC"N;.vCZ"1Pj&@Z.ZC"N;.vCZ"ҹgc&@Z.ZC"N;.vCZ"Dvp&@[/[C#O;/wC[#RФ&@[/[C#O;/wC[#R^Cv&@[/[C#O;/wC[#&@[/[C#O;/wC[#|&@[/[C#O;/wC[#&@[/[C#O;/wC[#&@[/[C#O;/wC[#>\&@[/[C#O;/wC[# &@[/[C#O;/wC[#r &@[/[C#O;/wC[#R80&@\0\C$P;0xC\$rB&@\0\C$P;0xC\$2LuU&@\0\C$P;0xC\$h&@\0\C$P;0xC\$Rz&@\0\C$P;0xC\$r6Q&@\0\C$P;0xC\$r&@\0\C$P;0xC\$2$'@\0\C$P;0xC\$0-ŧ'@\0\C$P;0xC\$*'@\0\C$P;0xC\$Rj'@]1]C%Q;1yC]%2; 0'@]1]C%Q;1yC]%'@]1]C%Q;1yC]%RF"7'@]1]C%Q;1yC]%U4'@]1]C%Q;1yC]% G='@]1]C%Q;1yC]%"Z'@]1]C%Q;1yC]%2lC'@]1]C%Q;1yC]%<`'@]1]C%Q;1yC]%I'@]1]C%Q;1yC]%Һ'@^2^C&R;2zC^&|'@`4`C(T;4|C`(P'@`4`C(T;4|C`(ҁc'@`4`C(T;4|C`(R v'@`4`C(T;4|C`(ҭ'@`4`C(T;4|C`(^'@`4`C(T;4|C`("'@`4`C(T;4|C`(҃'@`4`C(T;4|C`(y;('@a5aC)U;5}Ca)p'@a5aC)U;5}Ca)iy.'@a5aC)U;5}Ca)d '@a5aC)U;5}Ca)a5'@a5aC)U;5}Ca)R`V0'@a5aC)U;5}Ca)`B;'@a5aC)U;5}Ca)bU'@a5aC)U;5}Ca)f3hA'@a5aC)U;5}Ca)2lz'@a5aC)U;5}Ca)sqG'@b6bC*V;6~Cb*|'@b6bC*V;6~Cb*򇯲M'@b6bC*V;6~Cb*ҔN'@b6bC*V;6~Cb*RS'@b6bC*V;6~Cb*ҳ'@b6bC*V;6~Cb*+Y'@b6bC*V;6~Cb*'@b6bC*V;6~Cb*i"`'@b6bC*V;6~Cb*2 5'@b6bC*V;6~Cb* Gf '@c7cC+W;7Cc+;GZ '@c7cC+W;7Cc+Xll!'@c7cC+W;7Cc+2w!'@c7cC+W;7Cc+$r"'@c7cC+W;7Cc+ä"'@c7cC+W;7Cc+bx#'@c7cC+W;7Cc+#'@c7cC+W;7Cc+r+~$'@c7cC+W;7Cc+T@%'@c7cC+W;7Cc+%'@d8dC,X;8Cd,~&'@d8dC,X;8Cd,'&'@d8dC,X;8Cd,R 9''@d8dC,X;8Cd,>\L''@d8dC,X;8Cd,r^('@d8dC,X;8Cd,Ҩq('@d8dC,X;8Cd,r9)'@d8dC,X;8Cd,ٖ)'@d8dC,X;8Cd,2Ux *'@d8dC,X;8Cd,2*'@e9eC-Y;9Ce-Ѷ&+'@e9eC-Y;9Ce-V+'@e9eC-Y;9Ce-T,,'@e9eC-Y;9Ce-R,'@e9eC-Y;9Ce-R33-'@e9eC-Y;9Ce-2&+-'@e9eC-Y;9Ce-or>9.'@e9eC-Y;9Ce-Q.'@e9eC-Y;9Ce-2c?/'@e9eC-Y;9Ce-WPv/'@f:fC.Z;:Cf.ҧE0'@f:fC.Z;:Cf.R0'@f:fC.Z;:Cf.N.K1'@f:fC.Z;:Cf.1'@f:fC.Z;:Cf.rlQ2'@f:fC.Z;:Cf.2V 2'@f:fC.Z;:Cf.W3'@f:fC.Z;:Cf.K 3'@f:fC.Z;:Cf.m^4'@f:fC.Z;:Cf.Ή04'@g;gC/[;;Cg/21)Cd5'@g;gC/[;;Cg/U5'@g;gC/[;;Cg/ghj6'@g;gC/[;;Cg/c{6'@g;gC/[;;Cg/rͦp7'@g;gC/[;;Cg/8F7'@g;gC/[;;Cg/2v8'@g;gC/[;;Cg/R8'@g;gC/[;;Cg/2$|9'@g;gC/[;;Cg/9'@h<hC0\<<Ch02mc:'@h<hC0\<<Ch0;'@h<hC0\<<Ch0r[";'@h<hC0\<<Ch0RA5 <'@h<hC0\<<Ch0PG<'@h<hC0\<<Ch0R΀Z='@h<hC0\<<Ch0rM m='@h<hC0\<<Ch0Rο>'@h<hC0\<<Ch02Q_>'@h<hC0\<<Ch0?'@i=iC1]<=Ci1\?'@i=iC1]<=Ci1=$@'@i=iC1]<=Ci1mܧ@'@i=iC1]<=Ci1|*A'@i=iC1]<=Ci1A'@i=iC1]<=Ci1r1B'@i=iC1]<=Ci1R['B'@i=iC1]<=Ci12:97C'@i=iC1]<=Ci1ΚLC'@i=iC1]<=Ci12e:_=D'@j>jC2^<>Cj2rqD'@j>jC2^<>Cj2RyCE'@j>jC2^<>Cj23E'@j>jC2^<>Cj2иIF'@j>jC2^<>Cj2oXF'@j>jC2^<>Cj2OG'@j>jC2^<>Cj2G'@j>jC2^<>Cj2X7UH'@j>jC2^<>Cj2H'@j>jC2^<>Cj2rv\I'@k?kC3_<?Ck3rQ,I'@k?kC3_<?Ck32>bJ'@k?kC3_<?Ck3ҪUQJ'@k?kC3_<?Ck32ZchK'@k?kC3_<?Ck3r vK'@k?kC3_<?Ck3r4nL'@k?kC3_<?Ck3sԛL'@k?kC3_<?Ck3)ttM'@k?kC3_<?Ck3M'@k?kC3_<?Ck32zN'@l@lC4`<@Cl4XSN'@l@lC4`<@Cl4O'@l@lC4`<@Cl4RՒ P'@l@lC4`<@Cl42P'@l@lC4`<@Cl4Y0 Q'@l@lC4`<@Cl4rrCQ'@l@lC4`<@Cl42VR'@l@lC4`<@Cl4rhR'@l@lC4`<@Cl4wQ{S'@l@lC4`<@Cl4CS'@m A mC5a<ACm5rT'@m A mC5a<ACm50T'@m A mC5a<ACm5R"U'@m A mC5a<ACm5pإU'@m A mC5a<ACm5rZ(V'@m A mC5a<ACm51V'@m A mC5a<ACm5 P/W'@m A mC5a<ACm5"W'@m A mC5a<ACm555X'@m A mC5a<ACm5ҝ/HX'@n B nC6b<BCn6r}Z;Y'@n B nC6b<BCn6^omY'@n B nC6b<BCn6BAZ'@n B nC6b<BCn62'Z'@n B nC6b<BCn6 OG['@n B nC6b<BCn6['@n B nC6b<BCn6M\'@n B nC6b<BCn6.\'@n B nC6b<BCn6S]'@n B nC6b<BCn6n]'@o C oC7c<CCo72Z^'@o C oC7c<CCo7r'^'@o C oC7c<CCo7N:`_'@o C oC7c<CCo7r{L_'@o C oC7c<CCo7t_f`'@o C oC7c<CCo7n.r`'@o C oC7c<CCo7j΄la'@o C oC7c<CCo7hna'@o C oC7c<CCo7hrb'@o C oC7c<CCo7jb'@p D pC8d<DCp8mNxc'@p D pC8d<DCp8rc'@p D pC8d<DCp8y~d'@p D pC8d<DCp8r.e'@p D pC8d<DCp8Ҍe'@p D pC8d<DCp82n,f'@p D pC8d<DCp8R?f'@p D pC8d<DCp82Qg'@p D pC8d<DCp8Ndg'@p D pC8d<DCp8rvh'@q E qC9e<ECq9񎉗h'@q E qC9e<ECq9/i'@q E qC9e<ECq9r!Ϯi'@q E qC9e<ECq9;o j'@q E qC9e<ECq9rXԣj'@q E qC9e<ECq9v&k'@q E qC9e<ECq9Ok'@q E qC9e<ECq9R -l'@q E qC9e<ECq9ۏl'@q E qC9e<ECq92013m'@rFrC:f<FCr:2(Cm'@rFrC:f<FCr:2QpV9n'@rFrC:f<FCr:{in'@rFrC:f<FCr:r{?o'@rFrC:f<FCr:Po'@rFrC:f<FCr:Ep'@rFrC:f<FCr:r8p'@rFrC:f<FCr:l1Kq'@rFrC:f<FCr:q'@rFrC:f<FCr:qQr'@sGsC;g<GCs;r'@sGsC;g<GCs;rLXs'@sGsC;g<GCs;R#s'@sGsC;g<GCs;R5^t'@sGsC;g<GCs;RHt'@sGsC;g<GCs;RI3[du'@sGsC;g<GCs;mu'@sGsC;g<GCs;sjv'@sGsC;g<GCs;v'@sGsC;g<GCs;bpw'@tHtC<h<HCt<Tw'@tHtC<h<HCt<Rvx'@tHtC<h<HCt<Hx'@tHtC<h<HCt<5|y'@tHtC<h<HCt<z'@tHtC<h<HCt<>vz'@tHtC<h<HCt<2({'@tHtC<h<HCt<:{'@tHtC<h<HCt<DWM |'@tHtC<h<HCt<_|'@uIuC=i<ICu=Rr}'@uIuC=i<ICu=Z8}'@uIuC=i<ICu=2ؗ~'@uIuC=i<ICu=2y~'@uIuC=i<ICu='@uIuC=i<ICu=ϡ'@uIuC=i<ICu=NZ$'@uIuC=i<ICu=R'@uIuC=i<ICu=R"+'@uIuC=i<ICu=2;'@vJvC>j<JCv>,1'@vJvC>j<JCv>n|?'@vJvC>j<JCv>2R7'@vJvC>j<JCv>Td'@vJvC>j<JCv>]w='@vJvC>j<JCv>RA'@vJvC>j<JCv>C'@vJvC>j<JCv>5?ƅ'@vJvC>j<JCv>I'@vJvC>j<JCv>R1̆'@wKwC?k<KCw? O'@wKwC?k<KCw?3҇'@wKwC?k<KCw?a V'@wKwC?k<KCw?=و'@wKwC?k<KCw?RŢ1\'@wKwC?k<KCw?NCD߉'@wKwC?k<KCw?Vb'@wKwC?k<KCw?fi'@wKwC?k<KCw?$|h'@wKwC?k<KCw?Ŏ'@xLxC@l=LCx@Rfn'@xLxC@l=LCx@r'@xLxC@l=LCx@RBt'@xLxC@l=LCx@G'@xLxC@l=LCx@rsz'@xLxC@l=LCx@'@xLxC@l=LCx@)'@xLxC@l=LCx@rJ#'@xLxC@l=LCx@2j6'@xLxC@l=LCx@r I '@yMyCA m=MCyA 1['@yMyCA m=MCyA Ln'@yMyCA m=MCyA R퀓'@yMyCA m=MCyA ('@yMyCA m=MCyA 2.'@yMyCA m=MCyA Rϸ'@yMyCA m=MCyA 20p˟'@yMyCA m=MCyA "'@yMyCA m=MCyA r'@yMyCA m=MCyA GR)'@zNzCB n=NCzB '@zNzCB n=NCzB r(/'@zNzCB n=NCzB 2o4;'@zNzCB n=NCzB *M5'@zNzCB n=NCzB u`'@zNzCB n=NCzB s;'@zNzCB n=NCzB rg'@zNzCB n=NCzB *XA'@zNzCB n=NCzB RĚ'@zNzCB n=NCzB rG'@{O{CC o=OC{C R|:ʛ'@{O{CC o=OC{C EM'@{O{CC o=OC{C |М'@{O{CC o=OC{C T'@{O{CC o=OC{C ҭם'@{O{CC o=OC{C ~^-Z'@{O{CC o=OC{C RQ?ݞ'@{O{CC o=OC{C %R`'@{O{CC o=OC{C @e'@{O{CC o=OC{C wf'@|P|CD p=PC|D '@|P|CD p=PC|D R#l'@|P|CD p=PC|D fį'@|P|CD p=PC|D Eer'@|P|CD p=PC|D &'@|P|CD p=PC|D r x'@|P|CD p=PC|D G'@|P|CD p=PC|D  '@|P|CD p=PC|D 2'@|P|CD p=PC|D *2'@}Q}CE q=QC}E D'@}Q}CE q=QC}E lW'@}Q}CE q=QC}E Rn j'@}Q}CE q=QC}E R_|'@}Q}CE q=QC}E RO'@}Q}CE q=QC}E F𡗨'@}Q}CE q=QC}E ='@}Q}CE q=QC}E 252ǝ'@}Q}CE q=QC}E / '@}Q}CE q=QC}E *t죪'@~R~CFr=RC~FR(&'@~R~CFr=RC~F''@~R~CFr=RC~F(W$-'@~R~CFr=RC~F+6'@~R~CFr=RC~F20I3'@~R~CFr=RC~F6:\'@~R~CFr=RC~F>n9'@~R~CFr=RC~FH|'@~R~CFr=RC~FT?'@~R~CFr=RC~FRb¯'@SCGs=SCGq_E'@SCGs=SCGȰ'@SCGs=SCGҕK'@SCGs=SCGrBα'@SCGs=SCGR'@SCGs=SCGRلղ'@SCGs=SCGR%)X'@SCGs=SCGR;۳'@SCGs=SCG,hN^'@SCGs=SCGrL a'@TCHt=TCHmsd'@TCHt=TCHK'@TCHt=TCHrj'@TCHt=TCHۍ'@TCHt=TCHr/p'@TCHt=TCH.'@TCHt=TCHZqv'@TCHt=TCHR'@TCHt=TCHҷ}'@TCHt=TCH2T'@UCIu=UCI2-'@UCIu=UCI2Q@'@UCIu=UCI҇8S'@UCIu=UCIRe '@UCIu=UCIzx'@UCIu=UCI6'@UCIu=UCIrt'@UCIu=UCI^'@UCIu=UCIr›'@UCIu=UCI8'@VCJv=VCJr}B衿'@VCJv=VCJR$'@VCJv=VCJ '@VCJv=VCJ2W& +'@VCJv=VCJR2'@VCJv=VCJRhE1'@VCJv=VCJ@ X'@VCJv=VCJRj7'@VCJv=VCJL}'@VCJv=VCJ:='@WCKw=WCK'@WCKw=WCK20C'@WCKw=WCKrD'@WCKw=WCKҠsI'@WCKw=WCK'@WCKw=WCK^O'@WCKw=WCKW'@WCKw=WCKr#$V'@WCKw=WCK7'@WCKw=WCKr;J\'@ X CLx=XCL2X\'@ X CLx=XCL~ob'@ X CLx=XCL. '@ X CLx=XCLh'@ X CLx=XCL c'@ X CLx=XCLr~n'@ X CLx=XCL'@ X CLx=XCL2gGt'@ X CLx=XCL'@ X CLx=XCLV{'@!Y!CMy=YCMr+'@!Y!CMy=YCMM)'@!Y!CMy=YCMn<'@!Y!CMy=YCMKO'@!Y!CMy=YCMͱa '@!Y!CMy=YCMQSt'@!Y!CMy=YCMr'@!Y!CMy=YCMr]'@!Y!CMy=YCMr7'@!Y!CMy=YCMqپ'@"Z"CNz=ZCNrz'@"Z"CNz=ZCN'@"Z"CNz=ZCN"'@"Z"CNz=ZCN_ '@"Z"CNz=ZCNA)'@"Z"CNz=ZCNr֢.'@"Z"CNz=ZCNmDA/'@"Z"CNz=ZCNrS'@"Z"CNz=ZCNRf5'@"Z"CNz=ZCN=)y'@#[#CO{=[COʋ;'@#[#CO{=[CO2|l'@#[#CO{=[COA'@#[#CO{=[CO'@#[#CO{=[COgQG'@#[#CO{=[COr'@#[#CO{=[COrM'@#[#CO{=[CORb6'@#[#CO{=[CO T'@#[#CO{=[CO2y3'@$\$CP|>\CPRmFZ'@$\$CP|>\CPRX'@$\$CP|>\CP^k`'@$\$CP|>\CP~'@$\$CP|>\CP?f'@$\$CP|>\CPC'@$\$CP|>\CPҳl'@$\$CP|>\CPp'@$\$CP|>\CP/)r'@$\$CP|>\CPR'@%]%CQ}>]CQRly'@%]%CQ}>]CQu'@%]%CQ}>]CQ:%'@%]%CQ}>]CQR8'@%]%CQ}>]CQRJ'@%]%CQ}>]CQR]'@%]%CQ}>]CQb7p'@%]%CQ}>]CQ1ق'@%]%CQ}>]CQ{'@%]%CQ}>]CQ'@&^&CR~>^CR򧾺'@&^&CR~>^CR}`'@&^&CR~>^CRU'@&^&CR~>^CRR. '@&^&CR~>^CRr F'@&^&CR~>^CR2''@&^&CR~>^CRĉ*'@&^&CR~>^CR2+=-'@&^&CR~>^CRrO'@&^&CR~>^CRrkob3'@'_'CS>_CS2Qu'@'_'CS>_CS89'@'_'CS>_CS"U'@'_'CS>_CSR ?'@'_'CS>_CS2'@'_'CS>_CS:E'@'_'CS>_CSR'@'_'CS>_CS~K'@'_'CS>_CS '@'_'CS>_CSrR'@(`(CT>`CTd/'@(`(CT>`CTBX'@(`(CT>`CTT'@(`(CT>`CTҞJg^'@(`(CT>`CTy'@(`(CT>`CT2d'@(`(CT>`CTr0'@(`(CT>`CTұj'@(`(CT>`CTt'@(`(CT>`CT2p'@)a)CU>aCUһ'@)a)CU>aCUZv'@)a)CU>aCU'@)a)CU>aCU!}'@)a)CU>aCU@4'@)a)CU>aCUF'@)a)CU>aCU2Y'@)a)CU>aCUR0'l'@)a)CU>aCUH~ '@)a)CU>aCUak'@*b*CV>bCV} '@*b*CV>bCV'@*b*CV>bCV2Q'@*b*CV>bCVۛ'@*b*CV>bCVR'@*b*CV>bCV 8'@*b*CV>bCVF%(@*b*CV>bCVn|&(@*b*CV>bCV29+(@*b*CV>bCVK(@+c+CW>cCWb^1(@+c+CW>cCWq(@+c+CW>cCWP7(@+c+CW>cCWRI(@+c+CW>cCWҷ=(@+c+CW>cCW퍻(@+c+CW>cCW%0C(@+c+CW>cCW_(@+c+CW>cCW2tI(@+c+CW>cCWr(@,d,CX dCX P(@,d,CX dCX rX[+(@,d,CX dCX =V(@,d,CX dCX ߟP(@,d,CX dCX %Bc\ (@,d,CX dCX mu (@,d,CX dCX b (@,d,CX dCX 2) (@,d,CX dCX P˭h (@,d,CX dCX ҟm (@-e-CY!eCY!n (@-e-CY!eCY!C (@-e-CY!eCY!Tt (@-e-CY!eCY!r (@-e-CY!eCY!F{(@-e-CY!eCY!r;0(@-e-CY!eCY!B(@-e-CY!eCY!YU(@-e-CY!eCY!Ҹ"h(@-e-CY!eCY!z (@.f.CZ"fCZ"|g(@.f.CZ"fCZ"R (@.f.CZ"fCZ"G(@.f.CZ"fCZ"N(@.f.CZ"fCZ"י(@.f.CZ"fCZ"(@.f.CZ"fCZ"25(@.f.CZ"fCZ"b#(@.f.CZ"fCZ"z"(@.f.CZ"fCZ"F5)(@/g/C[#gC[#RG(@/g/C[#gC[#1bZ/(@/g/C[#gC[#m(@/g/C[#gC[#$5(@/g/C[#gC[#I(@/g/C[#gC[#;(@/g/C[#gC[#򜎷(@/g/C[#gC[#R1A(@/g/C[#gC[#2(@/g/C[#gC[#&vG(@0h0C\$hC\$(@0h0C\$hC\$4N(@0h0C\$hC\$]'(@0h0C\$hC\$J:T(@0h0C\$hC\$آL(@0h0C\$hC\$2hE_Z(@0h0C\$hC\$q(@0h0C\$hC\$`(@0h0C\$hC\$R!-(@0h0C\$hC\$ϩf (@1i1C]%iC]%rPr (@1i1C]%iC]%l!(@1i1C]%iC]%!(@1i1C]%iC]%$Zr"(@1i1C]%iC]%"(@1i1C]%iC]%rey#(@1i1C]%iC]%B,#(@1i1C]%iC]%>$(@1i1C]%iC]%RTQ%(@1i1C]%iC]%)d%(@2j2C^&jC^&v&(@2j2C^&jC^&2So&(@2j2C^&jC^&'(@2j2C^&jC^&'(@2j2C^&jC^&bW((@2j2C^&jC^&rӗ((@2j2C^&jC^&Rʜ)(@2j2C^&jC^&?)(@2j2C^&jC^&9 !*(@2j2C^&jC^&*(@3k3C_'kC_'R'1'+(@3k3C_'kC_'RnC+(@3k3C_'kC_'-mV-,(@3k3C_'kC_'i,(@3k3C_'kC_'Ҳ{3-(@3k3C_'kC_'wU-(@3k3C_'kC_'>9.(@3k3C_'kC_'.(@3k3C_'kC_'=?/(@3k3C_'kC_'2/(@4l4C`(lC`(2lE0(@4l4C`(lC`(;&0(@4l4C`(lC`( L1(@4l4C`(lC`(k#1(@4l4C`(lC`(26R2(@4l4C`(lC`(2H2(@4l4C`(lC`(eT[X3(@4l4C`(lC`(r@m3(@4l4C`(lC`(^4(@4l4C`(lC`(<4(@5 m5Ca)mCa)ߥd5(@5 m5Ca)mCa)r5(@5 m5Ca)mCa)%j6(@5 m5Ca)mCa)26(@5 m5Ca)mCa)Rlkp7(@5 m5Ca)mCa)U7(@5 m5Ca)mCa)?w8(@5 m5Ca)mCa),T(8(@5 m5Ca)mCa)R:}9(@5 m5Ca)mCa)R M:(@6 n6Cb*nCb*<`:(@6 n6Cb*nCb*r;(@6 n6Cb*nCb*䂅;(@6 n6Cb*nCb*% <(@6 n6Cb*nCb*Ȫ<(@6 n6Cb*nCb*k=(@6 n6Cb*nCb*2Е=(@6 n6Cb*nCb*Rʱ>(@6 n6Cb*nCb*rT>(@6 n6Cb*nCb*R?(@7 o7Cc+oCc+Ϛ?(@7 o7Cc+oCc+R=-%@(@7 o7Cc+oCc+r?@(@7 o7Cc+oCc+R+A(@7 o7Cc+oCc+R&eA(@7 o7Cc+oCc+w1B(@7 o7Cc+oCc+2 mB(@7 o7Cc+oCc+r7C(@7 o7Cc+oCc+R-C(@7 o7Cc+oCc+@V=D(@8 p8Dd,pCd,VD(@8 p8Dd,pCd,mCE(@8 p8Dd,pCd,?E(@8 p8Dd,pCd, JF(@8 p8Dd,pCd,RF(@8 p8Dd,pCd,(2PG(@8 p8Dd,pCd,DG(@8 p8Dd,pCd,oWVH(@8 p8Dd,pCd,BjH(@8 p8Dd,pCd,rh|\I(@9 q9@De-qCe-XI(@9 q9@De-qCe-ҸbJ(@9 q9@De-qCe-㞴J(@9 q9@De-qCe-BhK(@9 q9@De-qCe-?K(@9 q9@De-qCe-RonL(@9 q9@De-qCe-R+L(@9 q9@De-qCe-RuM(@9 q9@De-qCe- r$M(@9 q9@De-qCe-rB7{N(@:r:Df.rCf.{IN(@:r:Df.rCf.[\O(@:r:Df.rCf.rnP(@:r:Df.rCf.1P(@:r:Df.rCf.rrE Q(@:r:Df.rCf.覍Q(@:r:Df.rCf.R(@:r:Df.rCf.2>/̓R(@:r:Df.rCf.S(@:r:Df.rCf.uS(@;s;Dg/sCg/T(@;s;Dg/sCg/gT(@;s;Dg/sCg/_)#U(@;s;Dg/sCg/2v>Dj2vCj2%?3yc(@>v>Dj2vCj22Ec(@>v>Dj2vCj2,Xd(@>v>Dj2vCj2)ke(@>v>Dj2vCj2R:}e(@>v>Dj2vCj2pf(@>v>Dj2vCj2rOf(@>v>Dj2vCj2ܷg(@>v>Dj2vCj2k[ȑg(@>v>Dj2vCj2rh(@?w?Dk3wCk3h(@?w?Dk3wCk3R#Fi(@?w?Dk3wCk3ri(@?w?Dk3wCk3RQ%!j(@?w?Dk3wCk3208j(@?w?Dk3wCk3J'k(@?w?Dk3wCk3#x]k(@?w?Dk3wCk3p-l(@?w?Dk3wCk3cl(@?w?Dk3wCk3rc3m(@@x@Dl4xCl4Ҫm(@@x@Dl4xCl4Q9n(@@x@Dl4xCl4Mͼn(@@x@Dl4xCl4?o(@@x@Dl4xCl4rNo(@@x@Dl4xCl48Fp(@@x@Dl4xCl4p(@@x@Dl4xCl4[*Lq(@@x@Dl4xCl4$=q(@@x@Dl4xCl4ORr(@AyA@Dm5yC m5rykbr(@AyA@Dm5yC m51uXs(@AyA@Dm5yC m5R벇s(@AyA@Dm5yC m5V^t(@AyA@Dm5yC m5rdt(@AyA@Dm5yC m5#du(@AyA@Dm5yC m5Au(@AyA@Dm5yC m5jv(@AyA@Dm5yC m5lv(@AyA@Dm5yC m5r2- qw(@BzBDn6zC n6w(@BzBDn6zC n6t/wx(@BzBDn6zC n6RBx(@BzBDn6zC n6]T}y(@BzBDn6zC n6-`gz(@BzBDn6zC n62zz(@BzBDn6zC n6ѧ{(@BzBDn6zC n6ҥK{(@BzBDn6zC n62| |(@BzBDn6zC n6Tď|(@C{CDo7{C o7r.7}(@C{CDo7{C o72 }(@C{CDo7{C o7~~(@C{CDo7{C o72"~(@C{CDo7{C o7r!(@C{CDo7{C o7rj4(@C{CDo7{C o7pG%(@C{CDo7{C o7VY(@C{CDo7{C o7>Vl+(@C{CDo7{C o72)~(@D|DDp8|C p81(@D|DDp8|C p8B(@D|DDp8|C p827(@D|DDp8|C p8Rɺ(@D|DDp8|C p8r-=(@D|DDp8|C p82(@D|DDp8|C p8uD(@D|DDp8|C p8RDž(@D|DDp8|C p8r&J(@D|DDp8|C p8ra9͆(@E}E@Dq9}C q92LP(@E}E@Dq9}C q9ҭ^Ӈ(@E}E@Dq9}C q9MqV(@E}E@Dq9}C q92و(@E}E@Dq9}C q9\(@E}E@Dq9}C q99߉(@E}E@Dq9}C q9Rݻb(@E}E@Dq9}C q9rЁ(@E}E@Dq9}C q9%h(@E}E@Dq9}C q9r(@F~FDr:~Cr:mo(@F~FDr:~Cr:r (@F~FDr:~Cr:+u(@F~FDr:~Cr:3Z>(@F~FDr:~Cr:rJP{(@F~FDr:~Cr:cc(@F~FDr:~Cr:R}Fv(@F~FDr:~Cr:r(@F~FDr:~Cr:R(@F~FDr:~Cr:2 (@GGDs;Cs;(@GGDs;Cs;{(@GGDs;Cs;@擒(@GGDs;Cs;g(@GGDs;Cs;Rg (@GGDs;Cs;Һ (@GGDs;Cs;0(@GGDs;Cs;TC#(@GGDs;Cs;DU(@GGDs;Cs;Rvh)(@HHDt<Ct<@{(@HHDt<Ct</(@HHDt<Ct<(@HHDt<Ct<N-5(@HHDt<Ct<Ÿ(@HHDt<Ct<Ru;(@HHDt<Ct<R뾙(@HHDt<Ct<RCA(@HHDt<Ct<bŚ(@HHDt<Ct<r#H(@II@Du=Cu= 5˛(@II@Du=Cu=TOHN(@II@Du=Cu=rZќ(@II@Du=Cu=mT(@II@Du=Cu=((ם(@II@Du=Cu=DZ(@II@Du=Cu=Rݞ(@II@Du=Cu=m`(@II@Du=Cu=R(@II@Du=Cu=9f(@JJDv>Cv>](@JJDv>Cv>Rm(@JJDv>Cv>/m(@JJDv>Cv>r%s(@JJDv>Cv>298(@JJDv>Cv>RdJy(@JJDv>Cv>](@JJDv>Cv>.mo(@JJDv>Cv>ґӁ(@JJDv>Cv>9(@KKDw?Cw?V(@KKDw?Cw?(@KKDw?Cw?m(@KKDw?Cw?rxݑ(@KKDw?Cw?R9(@KKDw?Cw?5(@KKDw?Cw?(@KKDw?Cw?l'(@KKDw?Cw?RK9!(@KKDw?Cw?R9L(@L LDx@Cx@^'(@L LDx@Cx@Yq(@L LDx@Cx@l-(@L LDx@Cx@r ӕ(@L LDx@Cx@ra93(@L LDx@Cx@ҷ(@L LDx@Cx@R 9(@L LDx@Cx@bl߼(@L LDx@Cx@?(@L LDx@Cx@ 9ï(@M!M@DyACyAR[F(@M!M@DyACyAҬ)ɰ(@M!M@DyACyAk;L(@M!M@DyACyAMMϱ(@M!M@DyACyAҜ8`R(@M!M@DyACyArղ(@M!M@DyACyA8X(@M!M@DyACyAk۳(@M!M@DyACyArѩ^(@M!M@DyACyA8(@N"NDzBCzBgd(@N"NDzBCzBҰ(@N"NDzBCzBjj(@N"NDzBCzBA(@N"NDzBCzB7q(@N"NDzBCzBrϝ*(@N"NDzBCzB2=w(@N"NDzBCzBZjO(@N"NDzBCzBa}(@N"NDzBCzBr6t(@O#OD{CC{C#(@O#OD{CC{Ce(@O#OD{CC{Ci(@O#OD{CC{CϽ (@O#OD{CC{C2&6Џ(@O#OD{CC{Cd(@O#OD{CC{C(@O#OD{CC{Ch(@O#OD{CC{C(@O#OD{CC{C2W5,(@P$PD|DC|D>(@P$PD|DC|DQ%(@P$PD|DC|Dhc(@P$PD|DC|D?$Pe?$rH+c?%uk?%w?% wq?% ?& ;?& jh}?& ?& iP{?' 9NB?' ?' ű?' 1-?( Y}d)H?( ɛ?( ;˲?( ` ?) iANN?) 9x׏?) C`ѳ?) ?* sT?*I'V? *s״? *پ? + Z? +iV3!? +)jݵ? +3? ,9ټ`? ,F? ,IG? , X%? -hf? -j? -i%? -)L\}+? .m? .ʏ?.y/?.I{91?/ p+s?/?/^=?/Y7?0)MPy?0Aٺ?0b?0y=?1I%+u?1 qb?1ɼ?1D?1YT?2)?#Ǽ?2v?275J?2y律?39Hͽ?3 T?3fZP?3㑾?4YlӾ?4J1?4hV?4?5y-בٿ?5т< ?5Ђ|"R.?5ЂdO?6ЂD.Zo?6ς,?6ς zd?6ς-)?7΂?7΂kd?7΂w4?7΂|;U?8͂d]7v?8͂DĖ?8͂$n?8̂ O N?8̂?9̂ԚA?9˂@ݛ:?9˂x`[?9˂|%|?:ʂ\2?:ʂDK?:ʂ$~r?:ɂ $7?;ɂ?;ɂo@?;ɂVa?;ȂI?<Ȃ|a?<Ȃ\)? <ۿǂ<ė? <ۿǂ$S`\? =ۿǂ &?!=ۿƂ잗F?!=ۿƂD3g?!=ۿƂn?"=ۿłj3?">ۿłt6?">ۿł\ܡ?#>۾Ă<= ?#>ܾĂ$(E,?#?ܾĂt M?#?ܾĂsm?$?ܾÂ?$?ܾÂGX?$@ܾÂe?%@ܽ‚t ?%@ܽ‚\?%@ܽ‚?+Dݻ뼂T[ y_?+Dݻ뼂4=?+Eݻ꼂C?,Eݻ껂L?,Eݻ껂z?,Eݺ껂ĘP?-F޺麂>$?-F޺麂MD?-F޺麂le?-F޺躂T0b?.G޺蹂4 '?.G޺蹂|?.G޺蹂!X?/G޹縂t ?/G޹縂m9*?/H޹縂+J?0H޹緂k?0H޹淂l_b?0H޹淂TK?1I޹涂4?1I޸嶂Q5?1I޸嶂Й?2I߸嵂ܜl^0?2J߸嵂B#Q?2J߸䵂q?2J߸䵂??3J߸䴂l4p?3J߸䴂Tv5?3K߷㴂4?4K߷㳂&?4K߷㳂I6?4K߷ⳂqGW?5L߷Ⲃ x?5L߷Ⲃј?5L߷Ⲃc?6L߶᱂l TZ?6M߶᱂L?6M߶᱂4U?7M߶ᰂ&RکABq)?>RکA2D_'?>SکA&7??S٨AOH??S٨AHX??S٨Ai?@SاAbvy?@TاA52ى?@TاA;?@TاA͝?ATצA?AUצAib?AUצAT?BU֥A''?BU֥AzR?BU֥Aj͠ ?CV֤AZM?CVդANs<-?CVդA>F>?DVգA2tN?DWգA"%^?DWԣAs9o?EWԢA?EWԢAd?EWӢA7]`?EXӢA °?FXӡA$?FXӡAF?FXҡA?GYҠAVK?GYҠA)0?GYѠA}?HYџAvr#?HYџAj3?HZџAZug7D?IZОAJHT?IZОA>d?IZОA.P^u?I[ϞA"?J[ϝA"?J[ϝAg:?J[ϝA9?K[ΜA I?K\ΜA#?K\ΜAʲq?L\͛Ap?L\͛AX ?L]͛A+[5?M]͚A)?M]̚A9?M]̚AvD\J?M]̚AfwZ?N^̙AVJ k?N^˙AJ.{?N^˙A:{?O^˘A.G?O^ʘA?O_ʘAie ?P_ʗA?UcŒA,X?VcđAy?VcđA?VcđA։%?VdđA\c5?WdÐA/CF?WdÐAV?WdÐALg?XdAjw?XeA{̇?XeArN6/?YeŽAb!?YeAV?YfAFV?ZfA:m?ZfA*m?ZfA@ }?ZfAW ?[gAA?[g奿A+?[g奿A@۴?cl塸AR=?cl桸A~%ڟ?cl样An'?dm样A^ud?dm样AR?dm样ABq)?em栶A6D_'?em栶A&7?en柶AOH?en柵A HX?fn柵Ai?fn柵Abvy?fn柵A52ى?go柴A;?go枴A͝?go枴A?ho枳Aib?ho枳AT?hp枳A''?ip枳~AzR?ip杲~Aj͠ ?ip杲~A^M?iq杲~ANs<-?jq東}ABF>?jq東}A2tN?jq東}A&%^?kq東|As9o?kr朰|A?kr朰|Ad?lr朰{A7]`?lr术{A °?lr术{A$?ls术{AF?ms曮zA?ms曮zAVK?ms曮zA)0?ns曮yA}?nt曭yAzr#?nt曭yAj3?ot暭xAZug7D?ot暬xANHT?ot暬xA>d?pu暬wA2P^u?pu皬wA"?pu癫wA"?pu癫wAg:?qu癫vA9?qv癪vA I?qv癪vA#?rv癪uAʲq?rv瘪uAp?rv瘩uAX ?sw瘩tA+[5?sw瘩tA)?sw瘨tA9?sw瘨tAvD\J?tw痨sAfwZ?tx痧sAZJ k?tx痧sAJ.{?ux痧rA>{?ux痧rA.G?ux痦rA?vy疦qAie ?vy疦qA?{|瓠lA,X?||瓠kAy?|}瓠kA?|}瓠kA։%?}}璟jA\c5?}}璟jA/CF?}}璟jAV?}~璞jALg?~~璞iAjw?~~璞iA{̇?~~瑝iArN6/?~瑝hAb!?瑝hAV?瑝hAFV?瑜gA:m?瑜gA*m?琜gA@ }?琛fAW ?琛fAA?琛fA+?琛fA@۴?狓^AR=?狓^A~%ڟ?狓^An'?狒]A^ud?狒] )ac?犒] ?犒] ?犑\ ?犑\ u'$?犑\ ^$Y,?牐[ GK4?牐[ w1r ?焈S e?焈S 5ь?焈S "?焇R 'L*?焇R ~2?焇R w(:?烇R `OB?烆Q JvK?烆Q 3BS?烆Q s[?烅P sc?炅P k?炅P e8t?炄O _8|?炄O Wi?炄O ѕ?灄O I˔?灃N h?灃N ;R".?灃N ;I_?灂M -%p?瀂M ?瀂M ?瀁L #?瀁L  U?瀁L 2?瀁L Y?K {?K p?K kZJ?J C{?J ]-?~J C?~~J Oj ?~~I @(?~~I Aӷq0?~}I ޢ8?}}H 3@?}}H ,I?}}H %yS6Q?}|G bzgY?}|G La?||G 5i?|{G q?|{F ,z?|{F <]?|zF qc?{zE Ċ?{zE c?{zE ݗ!?{yE UR?{yD j&?zyD GTM?zxD =t?zxC 9'?zxC H?zwC +y?zwB ?ywB 6?ywB ] ?yvB >?yvA o?yvA rҠ ?xuA y\?xu@ E ?xu@ i/G4&?xt@ ne.?xt@ [6?wt? >?ws? MF?ws? ž *O?ws> ?0[W?ws> W_?vr> 1{~g?vr= do?vr= #Nx?vq= 7P?vq= !?uq< A?up< g?up< ݎ?up; ƵF?up; qw?to; ?to; c*?to: lQ ?tn: SVx ?lb/ e?lb. 5ь?kb. "?ka. 'L*?ka. ~2?ka- w(:?ka- `OB?j`- JvK?j`, 3BS?j`, s[?j_, uc?j_+ k?i_+ g8t?i^+ _8|?i^+ Yi?i^* ѕ?h^* I˔?h]* h?h]) ;R".?h]) ;I_?h\) -%p?g\) ?g\( ?g[( #?g[(  U?g[' 2?fZ' Y?fZ' {?fZ' p?fZ& mZJ?fY& C{?eY& _-?¦eY% C?¦eX% Oj ?¦eX% @(?¦dX% Aӷq0?çdW$ ޢ8?çdW$ 3@?çdW$ ,I?ħdV# %yS6Q?ħcV# bzgY?ħcV# La?ĨcV# 5i?ŨcU" q?ŨcU" ,z?ŨbU" <]?ƨbT! sc?ƨbT! Ċ?ƨbT! e?ƩaS! ݗ!?ǩaS WR?ǩaS j&?ǩaR GTM?ȩaR =t?ȩ`R 9'?Ȫ`Q H?Ȫ`Q +y?ɪ`Q ?ɪ`Q 6?ɪ_P ] ?ʪ_P >?ʪ_P o?ʫ_O sҠ ?ʫ^O y\?˫^O E ?˫^N k/G4&?˫^N ne.?̫^N ]6?̫]M >?̬]M OF?̬]M Ǿ *O?ͬ]M A0[W?ͬ]L W_?ͬ\L 1{~g?ͬ\L do?ά\K #Nx?έ\K 7P?έ[K !?ϭ[J A?ϭ[J g?ϭ[J ݎ?ϭ[I ƵF?ЮZI qw?ЮZI ?ЮZI c*?ѮZH lQ ?ѮYH UVx .0?ڳR> oUa?ڳR> n|?ڳR= aX?۳R= A?۳Q= S+%?۳Q< W?ܴQ< E> ?ܴQ< e?ܴQ< 7ь?ܴP; "?ݴP; 'L*?ݴP; ~2?ݴP: w(:?ݵO: `OB?޵O: JvK?޵O9 3BS?޵O9 s[?ߵO9 uc?ߵN8 k?ߵN8 g8t?ߵN8 _8|?N7 Yi?M7 ѕ?M7 K˔?M7 h?M6 =R".?M6 ;I_?L6 -%p?L5 ?L5 ?L5 #?K4  U?K4 2?K4 Y?K3 {?J3 p?J3 mZJ?J2 C{?J2 _-?J2 C?I2 Qj ?I1 @(?I1 Cӷq0?I1 ޢ8?H0 5@?H0 ,I?H0 'yS6Q?H/ bzgY?G/ La?G/ 5i?G. q?G. ,z?G. <]?F- uc?F- Ċ?F- e?F- ߗ!?E, WR?E, j&?E, ITM?E+ =t?D+ ;'?D+ H?D* -y?D* ?D* 6?C) ] ?C) >?C) o?C( sҠ ?B( {\?B( E ?B( m/G4&?B' ne.?A' ]6?A' >?A& OF?A& ɾ *O?A& A0[W?@% W_?@% 3{~g?@% do?@$ %Nx??$ 7P??$ !??# A??# g?># ݎ?># ƵF?>" sw?>" ?=" c*?=! lQ ?=! UVx ?4 e?3 7ь?3 "?3 )L*?3 ~2?2 w(:?2 `OB?2 JvK?2 3BS?1 s[?1 wc?1 k?1 i8t?1 _8|?0 [i?0 ӕ?0 M˔?0 h?/ =R".?/ ;I_?/ /%p?/ ?. !?. #?.  U?. 2?- Y?- }?- p?- oZJ?, C{?, a-?, C?, Sj ?+ @(?+ Cӷq0?+ ޢ8?+ 5@?* ,I?* 'yS6Q?* bzgY? * La? ) 5i? ) q? ) ,z? ) <]? ( uc? ( Ċ? ( g? ( ߗ!? ' YR? ' j&? ' KTM? ' =t? & ;'? & H? & -y? & ? % 6? % ] ?% >?% o?$ sҠ ?$ {\?$ E ?$ m/G4&?# ne.?# _6?# >?# QF?" ɾ *O?" A0[W?" W_?" 3{~g?! do?! %Nx?! 7P?! !? A? g? ݎ? ƵF? sw? ? e*? lQ ? WVxIp?ʐ1at?ʐ ezx?ʐ|?ɐf ?ɐ#Ą?ɐ܈?ɐhF?ȐX ?ȐRm&?Ȑ??Ȑ;W? ǐJ'p? ǐ%? ǐÙN? ǐ⹭?!Ɛ;uұ?!Ɛ?!Ɛl?!Ɛq/?"Ő-V4?"ŐVM?"Ő?e?"Őb}~?#Đ)?#Đ۝?#Đ8?#ĐT?$Ð^?$Ðp?$Ð*?$ÐFZC?%Ϭ[?%C@t?% {ӌ?% 7-g?& ?& ?& m! ?& )?' tH ?' 8?' ^^oQ?' j ?( ⿐G$?( ῐ)(?( ῐP1,?( ῐ P0?) ྐ4?) ྐw8?) ྐB =?) ߾x.A?* ߽1GE?*߽wb_I?*޽3XxM?*޽KQ?+޼U?+޼i5Y?+ݼ%]?+ݼ:a?,ݻ f?,ܻZa$j?,ܻ}?.ٹ"?.ٹ#?/ٸs 2?/ظ/JK?/ظc?/ظjq|?0طd?0׷!T?0׷+Ư?0׷=޳?1ֶVR?1ֶ'?1ֶϛy(?1ն A?1նHY?2յ3r?2ԵnNJ?2Ե}Z?2Ե:X?3Ӵ́?3ӴA?3Ӵo?3Ӵ++<?4ҳ6?4ҳcO?4ҳag?4ѳ?5Ѳr?5Ѳ簱?5вR\D?5в ?6бEk ?6ϱ?6ϱD/,?6ϱ%E?7ΰ]?7ΰyLv"?7ΰ6&?7ΰvs*?8ͯ.?8ͯk`2?8ͯ'-6?8̯I ;?8̯T"??9̮]3:C?9ˮ{SG?9ˮlK?9ˮO?:ʭN6S?:ʭ {ɵW?:ʭ\[?:ɭd_?;ɬ@كc?;ɬMh?;ɬª0l?;Ȭu7>Ip?<ȫ2at?<ȫ ezx?<ۿǫ|?<ۿǫg ?=ۿǪ#Ą?=ۿƪ܈?=ۿƪhF?=ۿƪY ?=ۿŪRm&?>ۿũ??>ۿũ;W?>۾ĩJ'p?>ܾĩ%??ܾĨÙN??ܾĨ⹭??ܾè?L߷ⲛ"?L߷ⲛ#?L߷ⲛt 2?L߶ᱛ0JK?M߶ᱚc?M߶ᱚjq|?M߶ᰚe?Mచ"T?Mచ+Ư?Nఙ=޳?N߯WR?N߯'?N߯Лy(?O߮ A?OޮIY?Oޮ3r?OޭnNJ?Oݭ~Z?Pݭ:X?Pݬ́?PݬA?Pܬo?Qܫ,+<?Qܫ6?QܫcO?Q۫ag?Q۪?R۪r?Rڪ簱?RکS\D?Rک ?SکEk ?S٨?S٨D/,?S٨%E?Sا]?TاzLv"?Tا6&?Tاvs*?Tצ.?Uצk`2?Uצ(-6?U֥I ;?U֥T"??U֥]3:C?V֤{SG?VդlK?VդO?VգO6S?Wգ {ɵW?Wԣ\[?WԢd_?WԢ@كc?WӢMh?XӢª0l?Xӡv7>Ip?Xӡ2at?Xҡ ezx?YҠ|?YҠg ?YѠ$Ą?Yџ܈?YџhF?ZџY ?ZОRm&?ZО??ZО;W?[ϞK'p?[ϝ%?[ϝÙN?[ϝ⹭?[ΜIp?s术{t2at?s曮zt ezx?s曮zt|?s曮zth ?s曮yt$Ą?t曭ys܈?t曭yshF?t暭xsY ?t暬xsRm&?t暬xs??u暬wr;W?u皬wrK'p?u癫wr%?u癫wręN?u癫vr⹭?v癪vq=uұ?v癪vq?v癪uql?v瘪uqr/?v瘩uq/V4?w瘩tpVM?w瘩tp?e?w瘨tpd}~?w瘨tp )?w痨spݝ?x痧so8?x痧soV?x痧ro^?x痧rop?x痦ro*?y疦qnGZC?y疦qnϬ[?y疥qnC@t?y疥pn}ӌ?y疥pn9-g?z疥pm?z畤pm?z畤omn! ?z畤om+?z畣omtH ?z畣nm8?{畣nl`^oQ?{產nlj ?{產mlG$?{產ml)(?{產mlR1,?|甡mkP0?|瓡lk4?|瓡lkw8?|瓠lkC =?|瓠kky.A?}瓠kj1GE?}瓠kjxb_I?}璟jj5XxM?}璟jjKQ?}璟jjU?~璞jij5Y?~璞ii']?~璞ii:a?~瑝ii f?~瑝hi\a$j?瑝hh}Ip?煊U\3at?煊U\ ezx?煉T\|?煉T\h ?煉T\%Ą?焈S\܈?焈S[hF?焈S[Z ?焇R[Rm&?焇R[??焇R[;W?烇RZL'p?烆QZ%?烆QZřN?烆QZ⹭?烅PZ=uұ?炅PZ?炅PYl?炄OYs/?炄OY/V4?炄OYVM?灄OY?e?灃NXd}~?灃NX!)?灃NXݝ?灂MX8?瀂MXV?瀂MX^?瀁LWp?瀁LW*?瀁LWHZC?瀁LWϬ[?KWC@t?KV}ӌ?KV9-g?JV?JV?~JVo! ?~~JV+?~~IUtH ?~~IU8?~}IU`^oQ?}}HUj ?}}HUG$?}}HU)(?}|GTR1,?}|GTP0?||GT4?|{GTw8?|{FTD =?|{FTy.A?|zFS1GE?{zESyb_I?{zES5XxM?{zESKQ?{yESU?{yDRk5Y?zyDR']?zxDR:a?zxCR f?zxCR\a$j?zwCR}O#T?ws>O+Ư?vr>O=޳?vr=OXR?vr=N'?vq=Nћy(?vq=N A?uqIp?md0G4at?md0G ezx?lc0G|?lc/Fi ?lc/F%Ą?lb/F܈?lb.FhF?kb.F[ ?ka.FRm&?ka.E??ka-E;W?ka-EL'p?j`-E %?j`,EřN?j`,E⹭?j_,D>uұ?j_+D?i_+Dl?i^+Ds/?i^+D0V4?i^*DVM?h^*D?e?h]*Ce}~?h])C!)?h])Cޝ?h\)C8?g\)CV?g\(C^?g[(Bp?g[(B*?g['BHZC?fZ'BϬ[?fZ'BC@t?fZ'B}ӌ?fZ&A:-g?fY&A?eY&A?eY%Ao! ?eX%A+?eX%AtH ?dX%A8?dW$@a^oQ?dW$@j ?dW$@G$?dV#@)(?cV#@R1,?cV#@P0?cV#?4?cU"?w8?cU"?D =?bU"?y.A?bT!?1GE?bT!?yb_I?bT!?6XxM?aS!>KQ?aS >U?aS >k5Y?aR >']?aR>:a?`R> f?`Q=]a$j?`Q=} 4Mh?R> 4ª0l?R> 4x7>Ip?R= 44at?R= 4 ezx?Q= 4|?Q< 4i ?Q< 3&Ą?Q< 3܈?Q< 3hF?P; 3[ ?P; 3Rm&?P; 3??P: 3;W?O: 2M'p?O: 2 %?O9 2řN?O9 2⹭?O92>uұ?N82?N82l?N82t/?N710V4?M71VM?M71?e?M71e}~?M61")?M61ޝ?L618?L50W?L50^?L50p?K40*?K40IZC?K40Ϭ[?K30C@t?J3/~ӌ?J3/:-g?J2/?J2/?J2/p! ?I2/,?I1/tH ?I1/8?I1.a^oQ?H0.j ?H0.G$?H0.)(?H/.S1,?G/.P0?G/.4?G.-w8?G.-E =?G.-y.A?F--1GE?F--zb_I?F--6XxM?F--KQ?E,-U?E,,l5Y?E,,(]?E+,:a?D+, f?D+,]a$j?D*,}#)nNJ?>#)Z?>"(=X?>"(́?="(A?=!(r?=!(.+<?=!(6?= (cO?< (dg?< ( ?<'r?<'簱?;'U\D?;' ?;'Ek ?;'?:'G/,?:'%E?:&]?:&|Lv"?9&9&?9&vs*?9&.?9&n`2?8&*-6?8&I ;?8%T"??8%_3:C?8%{SG?7%lK?7%O?7%Q6S?7%{ɵW?6%\[?6$d_?6$Cكc?6$Mh?5$ª0l?5$x7>Ip?5$4at?5$ ezx?4$|?4$j ?4#&Ą?4#܈?3#hF?3#[ ?3#Rm&?3#??2#;W?2#M'p?2" %?2"ƙN?1"⹭?1"?uұ?1"?1"l?1"t/?0"0V4?0"VM?0!?e?0!f}~?/!")?/!ޝ?/!8?/!W?.!^?.!p?. !*?. IZC?- Ϭ[?- C@t?- ~ӌ?- ;-g?, ?, ?, p! ?, ,?+ tH ?+ 8?+ a^oQ?+ j ?* G$?* )(?*S1,?*P0?)4?)w8?)E =?)y.A?(1GE?(zb_I?(6XxM?(KQ?'U?'l5Y?'(]?':a?& f?&]a$j?&}@4U@@HbB@HyYnD@O4zF@ȭH@H 6J@HjcL@HʫN@&P@Ȅ]R@HLT@HAV@H:X@{Z@[6]@H_@Haa@ve&c@2e@2>?g@HKi@HNWk@M dm@ȫepo@ ~|q@Hh8s@HBu@$w@Ȃg֭y@H! {@ H?i}@ H@ Pށ@ Y G@ HŐ@ H@ Ht:$@ m@ 0(@ Hi5@ H#KA@ KޔM@ ȩY@ S(f@ Hf rr@ Hǻ~@ "@ ߾Ȁz@ܻH*@ۺHI 7@ۺȧmWC@ۺ(O@ںHd[@ڹHœ4h@ڹ W~t@ٹ~Ȁ@ٹ@ٸH;[@ظH@@ظ@ظU8@طȳo@׷H*@׷Hp@׷Ξ_@ֶ,Y@ֶH@ֶH<@նHG @նȥB,@յ9@ԵHbcE@ԵHqQ@Ե,]@Ӵ|@j@ӴH۠v@ӴH9[Ԃ@ӴH@ҳg@ҳS@ҳHD@ѳHD@Ѳn@Ѳs@в*."@вHk@бH碵@ϱE] @ϱȣI @ϱҒ" @ΰH`.@ΰHF&;@ΰpG@ΰzS@ͯHu`@ͯ H70Ml@ͯ Hx@̯ @̯ Q_*@̮ Ht!@ˮ HԽ#@ˮ Hl%@ˮ HQ'@ʭ ()@ʭ H+@ʭ Hw.-@ɭ C2x/@ɬ ȡ1@ɬ 4@ɬ H^aU6@Ȭ H$8@ȫ 0:@ȫ x2=<@ۿǫ J|I>@ۿǫ H5U@@ۿǪ HbB@ۿƪ yYnD@ۿƪ O4zF@ۿƪ HH@ۿŪ H 6J@ۿũ HjcL@ۿũ ʫN@۾ĩ &P@ܾĩ H]R@ܾĨ HLT@ܾĨ HAV@ܾè ȟ:X@ܾè {Z@ܾç H\6]@ܽ§ H_@ܽ§ aa@ܽ§ ve&c@ܽ 2e@ܽ H3>?g@ܽ HKi@ܽ NWk@ܽ M dm@ܼ ȫepo@ݼ H ~|q@ݼ Hh8s@ݼ Bu@ݼ $w@ݼ Hg֭y@ݼ쾤 H! {@ݼ쾤 H?i}@ݻ콣 ȝ@ݻ콣 Pށ@ݻ뽣 HZ G@ݻ뼣 HŐ@ݻ뼣 H@ݻ꼢 t:$@ݻ껢 m@ݻ껢 H1(@ݺ껢 Hi5@޺麡 #KA@޺麡 KޔM@޺麡 ȩY@޺躡 HS(f@޺蹠 Hf rr@޺蹠 ǻ~@޺蹠 "@޹縠 Ȁz@߸䵝*@߸䴝I 7@߸䴝HmWC@߷㴜H(O@߷㳜Hd[@߷㳜œ4h@߷Ⳝ W~t@߷ⲛHȀ@߷ⲛH@߷ⲛ;[@߶ᱛș@@߶ᱚ@߶ᱚHV8@߶ᰚHo@చ*@చp@ఙΞ_@߯H-Y@߯H@߯<@߮G @ޮHB,@ޮH9@ޭHbcE@ݭqQ@ݭ,]@ݬH}@j@ݬH۠v@ܬH9[Ԃ@ܫȗ@ܫg@ܫHT@۫HD@۪D@۪n@ڪs@کH+."@کHk@ک碵@٨E] @٨ȣI @٨HҒ" @اH`.@اȾF&;@اpG@اH{S@צHu`@צH70Ml@צȕx@֥@֥HR_*@֥Ht!@֤HԽ#@դl%@դHQ'@գH))@գH+@ԣw.-@ԢC2x/@Ԣȡ1@ӢH 4@ӢH^aU6@ӡȼ$8@ӡ0:@ҡx2=<@ҠHJ|I>@ҠH5U@@ѠȓbB@џyYnD@џHP4zF@џHH@ОH 6J@ОjcL@ОʫN@ϞH'P@ϝH]R@ϝHLT@ϝAV@Μȟ:X@ΜH{Z@ΜH\6]@͛Ⱥ_@͛aa@͛ve&c@͚H2e@̚H3>?g@̚ȑKi@̚NWk@̙M dm@˙Hepo@˙H ~|q@˘h8s@ʘBu@ʘH%w@ʗHg֭y@ʗH! {@ɗ?i}@ɖȝ@ɖHPށ@ȖHZ G@ȖHŐ@ȕ@ȕt:$@ǕHm@ǔH1(@ǔHi5@Ɣ#KA@ƓKޔM@ƓHY@ƓHS(f@Œf rr@Œǻ~@Œ"@đHz@*@I 7@HmWC@H(O@Hd[@œ4h@奿 W~t@奿HȀ@夿H@夾;[@夾ș@@夾@夾HV8@夽Ho@壽*@壽~p@壼~Ξ_@壼~H-Y@壼~H@壼}<@壻}G @墻}HB,@墻}H9@墺}HbcE@墺|qQ@墺|,]@墹|H}@j@塹|H۠v@塹|H9[Ԃ@塹{ȗ@塸{g@塸{HT@桸{HD@样{D@样zn@样zs@样zH+."@栶zHk@栶z碵@柶yE] @柵yȣI @柵yHҒ" @柵yH`.@柵yȾF&;@柴xpG@枴xH{S@枴xHu`@枳xH70Ml@枳xȕx@枳w@枳~wHR_*@杲~wHt!@杲~wHԽ#@杲~vl%@東}vHQ'@東}vH))@東}vH+@東|vw.-@朰|uC2x/@朰|uȡ1@朰{uH 4@术{uH^aU6@术{uȼ$8@术{t0:@曮ztx2=<@曮ztHJ|I>@曮ztH5U@@曮ytȓbB@曭ysyYnD@曭ysHP4zF@暭xsHH@暬xsH 6J@暬xsjcL@暬wrʫN@皬wrH'P@癫wrH]R@癫wrLT@癫vrAV@癪vqH:X@癪vqH{Z@癪uqH\6]@瘪uqȺ_@瘩uqaa@瘩tpHwe&c@瘩tpH2e@瘨tp3>?g@瘨tpȑKi@痨spNWk@痧soHN dm@痧soHepo@痧ro ~|q@痧roh8s@痦roBu@疦qnH%w@疦qnHg֭y@疥qn! {@疥pn?i}@疥pnH@疥pmHPށ@畤pmHZ G@畤omȸŐ@畤om@畣omHu:$@畣nmHm@畣nlH1(@產nlȏi5@產ml#KA@產mlHLޔM@產mlHY@甡mkS(f@瓡lkf rr@瓡lkǻ~@瓠lkH#@瓠kkHz@瑝hh*@瑜ghHJ 7@瑜ghHmWC@琜ghH(O@琛fgd[@琛fgœ4h@琛fgH!W~t@琛fgHȀ@珚eg@珚eg;[@珚efș@@珙dfH@珙dfHV8@珙dfȴo@玘cf*@玘cep@玘ceHϞ_@玘ceH-Y@玗beȋ@獗be<@獗bdHH @獖adHB,@獖adH9@獖adbcE@獕`dqQ@猕`cH,]@猕`cH}@j@猕`cH۠v@猔_c9[Ԃ@猔_cȗ@狔_cHg@狓^bHT@狓^bȲD@狓^bD@狒]bn@狒]bHs@犒]aH+."@犒]aȉk@犑\a碵@犑\aE] @犑\aHI @牐[`HҒ" @牐[``.@牐[`ȾF&;@牐Z`HpG@牏Z`H{S@牏Z`Hu`@爏Z_70Ml@爎Y_ȕx@舎Y_H@爎Y_HR_*@爍X_Ȱt!@燍X^Խ#@燍X^Hm%@燍W^HHQ'@燌W^H))@燌W^ȇ+@燌W^w.-@熋V]HD2x/@熋V]H1@熋V] 4@熊U]^aU6@熊U]ȼ$8@煊U\H0:@煊U\Hy2=<@煉T\J|I>@煉T\5U@@煉T\ȓbB@焈S\HyYnD@焈S[HP4zF@焈S[ȮH@焇R[ 6J@焇R[HkcL@焇R[HʫN@烇RZH'P@烆QZȅ]R@烆QZLT@烆QZHBV@烅PZH:X@炅PZH{Z@炅PY\6]@炄OYȺ_@炄OYHaa@炄OYHwe&c@灄OY2e@灃NX3>?g@灃NXȑKi@灃NXHNWk@灂MXHN dm@瀂MXȬepo@瀂MX ~|q@瀁LWh8s@瀁LWHBu@瀁LWH%w@瀁LWȃg֭y@KW! {@KVH@i}@KVH@JVHPށ@JVZ G@~JVȸŐ@~~JVH@~~IUHu:$@~~IUHm@~}IU1(@}}HUȏi5@}}HUH#KA@}}HUHLޔM@}|GTȪY@}|GTS(f@||GTf rr@|{GTHǻ~@|{FTH#@|{FTȁz@zwBQH*@ywBQHJ 7@ywBQHmWC@yvBQ(O@yvAQd[@yvAQHÜ4h@xuAPH!W~t@xu@PȀ@xu@P@xt@P;[@xt@PH@@wt?PH@ws?OV8@ws?Oȴo@ws>O*@ws>OHq@vr>OHϞ_@vr=O-Y@vr=Nȋ@vq=NH<@vq=NHH @uq@lc/F5U@@lc/FHbB@lb/FHyYnD@lb.FP4zF@kb.FȮH@ka.FH 6J@ka.EHkcL@ka-EHʫN@ka-E'P@j`-Eȅ]R@j`,EHLT@j`,EHBV@j_,DH:X@j_+D{Z@i_+D\6]@i^+DH_@i^+DHaa@i^*Dwe&c@h^*D2e@h]*C3>?g@h])CHKi@h])CHNWk@h\)CN dm@g\)CȬepo@g\(C ~|q@g[(BHi8s@g[(BHBu@g['B%w@fZ'Bȃg֭y@fZ'BH! {@fZ'BH@i}@fZ&AH@fY&APށ@eY&AZ G@eY%AHŐ@eX%AH@eX%AHu:$@dX%Am@dW$@1(@dW$@Hi5@dW$@H#KA@dV#@LޔM@cV#@ȪY@cV#@S(f@cV#?Hg rr@cU"?Hǻ~@cU"?#@bU"?ȁ⯤@bT!?Hk,@aS!>%vȨ@aS >XԪ@aS >H @aR >HUS@aR>Hs@`R>@`Q=/0@`Q=H>z@`Q=H*@`Q=J 7@_P=ȨmWC@_P=H(O@_P=He[@_O<HÜ4h@^O<!W~t@^O<Ȁ@^N<H@^N<H<[@^N<Ț@@]M<@]M;V8@]M;Ho@]M;H*@]L;q@\L;Ϟ_@\L;-Y@\K;H@\K:H<@[K:H @[J:ȦB,@[J:H9@[J:HccE@[I:HqQ@ZI9,]@ZI9}@j@ZI9Hܠv@ZH9H:[Ԃ@YH9H@YH9g@YG9T@YG8HD@YG8HD@XF8o@XF8s@XF8+."@XE8Hk@WE8H袵@WE7F] @WE7ȤI @WD7Ғ" @WD7Ha.@VD7HF&;@VC7pG@VC7{S@VC6Hu`@UB6H80Ml@UB6Hx@UB6@UA6R_*@UA6Ht!@TA6HԽ#@T@5Hm%@T@5HQ'@T@5))@S@5H+@S?5Hw.-@S?5D2x/@S?5Ȣ1@S> 4 4@R> 4H_aU6@R> 4H$8@R= 40:@R= 4y2=<@Q= 4J|I>@Q< 4H6U@@Q< 3HbB@Q< 3yYnD@Q< 3P4zF@P; 3HH@P; 3H 6J@P; 3HkcL@P: 3ʫN@O: 2'P@O: 2H]R@O9 2HLT@O9 2HBV@O92Ƞ:X@N82{Z@N82H]6]@N82H_@N71aa@M71we&c@M712e@M71H4>?g@M61HKi@M61NWk@L61N dm@L50Ȭepo@L50H ~|q@L50Hi8s@K40Bu@K40%w@K40Hg֭y@K30H! {@J3/H@i}@J3/Ȟ@J2/Pށ@J2/H[ G@J2/HŐ@I2/@I1/ u:$@I1/ Hm@I1. H2(@H0. Hi5@H0. #KA@H0. LޔM@H/. HY@G/. H S(f@G/. g rr@G.- ǻ~@G.- #@G.- H⯤@F-- Ȝk,@F-- %vȨ@E,- HYԪ@E,, H @E,, US@E+, s@D+, H@D+, H00@D*, H>z@D*, *@D*, J 7@C)+ HmWC@C)+ H(O@C)+ He[@C(+ Ü4h@B(+ !W~t@B(+ HȀ@B(+ H@B'+ <[@A'* Ț@@A'* @A&* HW8@A&* Ho@A&* *@@%* q@@%* Ϟ_@@%* H.Y@@$) H@?$) <@?$) H @?#) HB,@?#) H9@>#) HccE@>#) qQ@>"( ,]@>"( H~@j@="( Hܠv@=!( H:[Ԃ@=!( Ș@=!( g@= ( HU@< ( HD@< ( D@<' o@<' s@;' H,."@;' Hk@;' 袵@;' F] @:' ȤI @:' HҒ" @:& Ha.@:& ȿF&;@9& pG@9& H|S@9& Hu`@9& H80Ml@8& Ȗx@8& @8% HS_*@8% Ht!@8%HԽ#@7%m%@7%HQ'@7%H*)@7%H+@6%w.-@6$D2x/@6$Ȣ1@6$H 4@5$H_aU6@5$Ƚ$8@5$0:@5$y2=<@4$HJ|I>@4$H6U@@4#ȔbB@4#yYnD@3#HQ4zF@3#HH@3#H 6J@3#kcL@2#ʫN@2#H(P@2"H]R@2"LT@1"BV@1"H:X@1"H{Z@1"H]6]@1"Ȼ_@0"aa@0"Hxe&c@0!H2e@0!4>?g@/!ȒKi@/!NWk@/!HO dm@/!Hepo@.! ~|q@.!i8s@. !Bu@. H&w@- Hg֭y@- ! {@- @i}@- H@, HPށ@, H[ G@, ȹŐ@, @+ Hv:$@+ Hm@+ H2(@+ Ȑi5@* #KA@* HMޔM@*HY@* S(f@)g rr@)ǻ~@)H$@)H⯤@(Ȝk,@(H%vȨ@'HYԪ@'ȷ @'US@'Ht@&H@&H00@&Ȏ>z@&*@%HK 7@%HmWC@%H(O@%e[@$Ü4h@$H"W~t@$HȀ@$@#<[@#Ț@@#H@#HW8@"ȵo@"*@"q@"HО_@!H.Y@!Ȍ@!<@!HI @ HB,@ H9@ ccE@ qQ@H ,]@H~@j@Hܠv@:[Ԃ@Ș@Hg@HU@ȳD@D@o@Hs@H,."@Ȋk@袵@F] @HI @HҒ" @a.@ȿF&;@HpG@H|S@Hu`@80Ml@Ȗx@H@HS_*@ȱt!@Խ#@Hn%@HHQ'@H*)@Ȉ+@w.-@HE2x/@H1@ 4@_aU6@Ƚ$8@H0:@Hz2=<@J|I>@6U@@ȔbB@HyYnD@HQ4zF@ȯH@ 6J@HlcL@HʫN@H(P@Ȇ]R@LT@HCV@H:X@H{Z@]6]@Ȼ_@Haa@Hxe&c@2e@4>?g@ȒKi@HNWk@HO dm@ȭepo@ ~|q@i8s@HBu@H&w@Ȅg֭y@! {@ HAi}@ H@ HPށ@ [ G@ ȹŐ@ H@ Hv:$@ Hm@ 2(@ Ȑi5@ H#KA@ HMޔM@ ȫY@  S(f@ g rr@ Hǻ~@ H$@ ߾Ȃ⯤@޽Hk,@޽H%vȨ@޼YԪ@޼ȷ @ݼHUS@ݼHt@ݻ H@ܻ 00@ܻ Ȏ>z@ܻ H*@ۺ HK 7@ۺ HmWC@ۺ (O@ں e[@ڹ HĜ4h@ڹ!H"W~t@ٹ!ȀȀ@ٹ!@ٸ!<[@ظ!H@@ظ!H@ظ!W8@ط!ȵo@׷!*@׷"Hr@׷"HО_@ֶ".Y@ֶ"Ȍ@ֶ"H<@ն"HI @ն"HB,@յ"9@Ե"ccE@Ե#HqQ@Ե#H ,]@Ӵ#~@j@Ӵ#ܠv@Ӵ#H;[Ԃ@Ӵ#H@ҳ#Hg@ҳ#U@ҳ$ȳD@ѳ$HD@Ѳ$Hp@Ѳ$s @в$,." @в$Ȋk @б$H颵 @ϱ$HG] @ϱ$ȥI @ϱ%Ғ" @ΰ%a. @ΰ%HF&; @ΰ%HpG @ΰ%|S @ͯ%u` @ͯ %H90Ml @ͯ %Hx @̯ &H @̯ &S_* @̮ &ȱt! @ˮ &HԽ# @ˮ &Hn% @ˮ &HHQ' @ʭ &*) @ʭ &Ȉ+ @ʭ 'Hw.- @ɭ 'HE2x/ @ɬ 'ȣ1 @ɬ ' 4 @ɬ '_aU6 @Ȭ 'H$8 @ȫ 'H0: @ȫ 'z2=< @ǫ (J|I> @ǫ (6U@ @Ǫ (HbB @ƪ (HyYnD @ƪ (Q4zF @ƪ (ȯH @Ū (H6J @ũ (HlcL @ũ (HʫN @ĩ )(P @ĩ )Ȇ]R @Ĩ )HLT @Ĩ )HCV @è )H:X @è ){Z @ç )]6] @§ *H_ @§ *Haa @§ *xe&c @ *2e @ *4>?g @ *HKi @ *HNWk @ *O dm @ +ȭepo @ + ~|q @ +Hj8s @ +HBu @ +&w @ +Ȅg֭y @쾤 +H! { @쾤 +HAi} @콣 ,H @콣 ,Pށ @뽣 ,[ G @뼣 ,HŐ @뼣 ,H @꼢 ,Hv:$ @껢 ,m @껢 ,2( @껢 -Hi5 @麡 -H#KA @麡 -MޔM @麡 -ȫY @躡 - S(f @蹠 -Hh rr @蹠 -Hǻ~ @蹠 -$ @縠 .Ȃz @䵝/H* @䴝/K 7 @䴝/ȩmWC @㴜0H(O @㳜0Hf[ @㳜0HĜ4h @Ⳝ0"W~t @ⲛ0ȀȀ @ⲛ0H @ⲛ0H=[ @ᱛ1ț@ @ᱚ1 @ᱚ1W8 @ᰚ1Ho @చ1H* @చ1r @ఙ1О_ @߯2.Y @߯2H @߯2H< @߮2I @ޮ2ȧB, @ޮ2H9 @ޭ2HdcE @ݭ2HqQ @ݭ3 ,] @ݬ3~@j @ݬ3Hݠv @ܬ3H;[Ԃ @ܫ3H @ܫ3g @ܫ3U @۫4HD @۪4HD @۪4p @ڪ4s @ک4,." @ک4Hk @ک4H颵 @٨5G] @٨5ȥI @٨5Ғ" @ا5Hb. @ا5HF&; @ا5pG @ا5|S @צ6Hu` @צ6H90Ml @צ6Hx @֥6 @֥6S_* @֥6Ht! @֤6HԽ# @դ7Hn% @դ7HQ' @գ7*) @գ7H+ @ԣ7Hw.- @Ԣ7E2x/ @Ԣ7ȣ1 @Ӣ8 4 @Ӣ8H`aU6 @ӡ8H$8 @ӡ80: @ҡ8z2=< @Ҡ8J|I> @Ҡ8H7U@ @Ѡ9HbB @џ9yYnD @џ9Q4zF @џ9HH @О9H6J @О9HlcL @О9ʫN @Ϟ:(P @ϝ:H]R @ϝ:HLT @ϝ:HCV @Μ:ȡ:X @Μ:{Z @Μ;H^6] @͛;H_ @͛;aa @͛;xe&c @͚;2e @̚;H5>?g @̚;HKi @̚ @ȕ>v:$ @Ǖ>Hm @ǔ>H3( @ǔ>Hi5 @Ɣ>#KA @Ɠ?MޔM @Ɠ?HY @Ɠ?H S(f @Œ?h rr @Œ?ǻ~ @Œ?$ @đ?Hz @A* @AK 7 @BHmWC @BH(O @BHf[ @BĜ4h @B"W~t @BHȀ @CH @C=[ @Cț@ @C @CHX8 @CHo @D* @~Dr @~DО_ @~DH/Y @~DH @}D< @}DI @}EHB, @}EH9 @}EHdcE @|EqQ @|E ,] @|EH@j @|FHݠv @|FH;[Ԃ @{Fș @{Fg @{FHV @{FHD @{GD @zGp @zGs @zGH-." @zGHk @zG颵 @yHG] @yHȥI @yHHҒ" @yHHb. @yHF&; @xHpG @xIH}S @xIHu` @xIH90Ml @xIȗx @wI @~wIHT_* @~wJHt! @~wJHԽ# @~vJn% @}vJHQ' @}vJH+) @}vJH+ @|vJw.- @|uKE2x/ @|uKȣ1 @{uKH 4 @{uKH`aU6 @{uKȾ$8 @{tK0: @ztLz2=< @ztLHJ|I> @ztLH7U@ @ytLȕbB @ysLyYnD @ysLHR4zF @xsMHH @xsMH6J @xsMlcL @wrMʫN @wrMH)P @wrNH]R @wrNLT @vrNCV @vqNH:X @vqNH|Z @uqNH^6] @uqOȼ_ @uqOaa @tpOHye&c @tpOH2e @tpO5>?g @tpOȓKi @spPNWk @soPHP dm @soPHepo @roP ~|q @roPj8s @roPBu @qnQH'w @qnQHg֭y @qnQ! { @pnQAi} @pnQH @pmQHPށ @pmRH\ G @omRȺŐ @omR @omRHw:$ @nmRHm @nlRH3( @nlSȑi5 @mlS#KA @mlSHNޔM @mlSHY @mkS S(f @lkTh rr @lkTǻ~ @lkTH% @kkTHz @hhV* @ghVHL 7 @ghVHmWC @ghWH(O @fgWf[ @fgWĜ4h @fgWH#W~t @fgWHȀ @egX @egX=[ @efXț@ @dfXH @dfXHX8 @dfXȶo @cfY* @ceYr @ceYHў_ @ceYH/Y @beYȍ @beZ< @bdZHJ @adZHB, @adZH9 @adZdcE @`dZqQ @`c[H!,] @`c[H@j @`c[Hݠv @_c[;[Ԃ @_c[ș @_c\Hg @^b\HV @^b\ȴD @^b\D @]b\p @]b\Hs @]a]H-." @]a]ȋk @\a]颵 @\a]G] @\a]HI @[`^HҒ" @[`^b. @[`^F&; @Z`^HpG @Z`^H}S @Z`^Hu` @Z__90Ml @Y__ȗx @Y__H @Y__HT_* @X__Ȳt! @X^`Խ# @X^`Ho% @W^`HHQ' @W^`H+) @W^`ȉ+ @W^`w.- @V]aHF2x/ @V]aH1 @V]a 4 @U]a`aU6 @U]aȾ$8 @U\bH0: @U\bH{2=< @T\bJ|I> @T\b7U@ @T\bȕbB @S\cHyYnD @S[cHR4zF @S[cȰH @R[c6J @R[cHmcL @R[cHʫN @RZdH)P @QZdȇ]R @QZdLT @QZdHDV @PZdH:X @PZeH|Z @PYe^6] @OYeȼ_ @OYeHaa @OYeHye&c @OYf2e @NXf5>?g @NXfȓKi @NXfHNWk @MXfHP dm @MXgȮepo @MXg ~|q @LWgj8s @LWgHBu @LWgH'w @LWgȅg֭y @KWh! { @KVhHBi} @KVhH @JVhHPށ @JVh\ G @~JViȺŐ @~~JViH @~~IUiHw:$ @~~IUiHm @~}IUi3( @}}HUjȑi5 @}}HUjH#KA @}}HUjHNޔM @}|GTjȬY @}|GTj S(f @||GTkh rr @|{GTkHǻ~ @|{FTkH% @|{FTkȃz @zwBQmH* @ywBQnHL 7 @ywBQnHmWC @yvBQn(O @yvAQnf[ @yvAQnHŜ4h @xuAPoH#W~t @xu@PoȁȀ @xu@Po @xt@Po=[ @xt@PoH@ @wt?PpH @ws?OpX8 @ws?Opȶo @ws>Op* @ws>OpHs @vr>OqHў_ @vr=Oq/Y @vr=Nqȍ @vq=NqH< @vq=NqHJ @uq @lc/F{7U@ @lc/F{HbB @lb/F{HyYnD @lb.F{R4zF @kb.F|ȰH @ka.F|H6J @ka.E|HmcL @ka-E|HʫN @ka-E|)P @j`-E}ȇ]R @j`,E}HLT @j`,E}HDV @j_,D}H:X @j_+D}|Z @i_+D~^6] @i^+D~H_ @i^+D~Haa @i^*D~ye&c @h^*D2e @h]*C5>?g @h])CHKi @h])CHNWk @h\)CP dm @g\)CȮepo @g\(C ~|q @g[(BHk8s @g[(BHBu @g['B'w @fZ'Bȅg֭y @fZ'BH! { @fZ'BHBi} @fZ&AH @fY&APށ @eY&A\ G @eY%AHŐ @eX%AH @eX%AHw:$ @dX%Am @dW$@3( @dW$@Hi5 @dW$@H#KA @dV#@NޔM @cV#@ȬY @cV#@ S(f @cV#?Hi rr @cU"?Hǻ~ @cU"?% @bU"?ȃ%vȨ @aS >ZԪ @aS >H @aR >HUS @aR>Hu @`R> @`Q=10 @`Q=H>z @`Q=H* @`Q=L 7 @_P=ȪmWC @_P=H (O @_P=Hg[ @_O<HŜ4h @^O<#W~t @^O<ȁȀ @^N<H @^N<H>[ @^N<Ȝ@ @]M< @]M;X8 @]M;Ho @]M;H* @]L;s @\L;ў_ @\L;/Y @\K;H @\K:H< @[K:J @[J:ȨB, @[J:H9 @[J:HecE @[I:HqQ @ZI9!,] @ZI9@j @ZI9Hޠv @ZH9H<[Ԃ @YH9H @YH9g @YG9V @YG8HD @YG8HD @XF8q @XF8s@XF8-."@XE8Hk@WE8Hꢵ@WE7H] @WE7ȦI @WD7Ғ" @WD7Hc.@VD7HF&;@VC7pG@VC7}S@VC6Hu`@UB6H:0Ml@UB6Hx@UB6@UA6T_*@UA6Ht!@TA6HԽ#@T@5Ho%@T@5HQ'@T@5+)@S@5H+@S?5Hw.-@S?5F2x/@S?5Ȥ1@S> 4 4@R> 4HaaU6@R> 4H$8@R= 40:@R= 4{2=<@Q= 4J|I>@Q< 4H8U@@Q< 3HbB@Q< 3yYnD@Q< 3R4zF@P; 3HH@P; 3H6J@P; 3HmcL@P: 3ʫN@O: 2)P@O: 2H]R@O9 2HLT@O9 2HDV@O92Ȣ:X@N82|Z@N82H_6]@N82H_@N71aa@M71ye&c@M712e@M71H6>?g@M61HKi@M61NWk@L61P dm@L50Ȯepo@L50H ~|q@L50Hk8s@K40Bu@K40'w@K40Hg֭y@K30H! {@J3/HBi}@J3/Ƞ@J2/Pށ@J2/H] G@J2/HŐ@I2/@I1/ w:$@I1/ Hm@I1. H4(@H0. Hi5@H0. #KA@H0. NޔM@H/. HY@G/. H S(f@G/. i rr@G.- ǻ~@G.- %@G.- Hz@D*, *@D*, L 7@C)+ HmWC@C)+ H (O@C)+ Hg[@C(+ Ŝ4h@B(+ #W~t@B(+ HȀ@B(+ H@B'+ >[@A'* Ȝ@@A'* @A&* HY8@A&* Ho@A&* *@@%* s@@%* ў_@@%* H0Y@@$) H@?$) <@?$) J @?#) HB,@?#) H9@>#) HecE@>#) qQ@>"( !,]@>"( H@j@="( Hޠv@=!( H<[Ԃ@=!( Ț@=!( g@= ( HW@< ( HD@< ( D@<' q@<' s@;' H.."@;' Hk@;' ꢵ@;' H] @:' ȦI @:' HҒ" @:& Hc.@:& F&;@9& pG@9& H~S@9& Hu`@9& H:0Ml@8& Șx@8& @8% HU_*@8% Ht!@8%HԽ#@7%o%@7%HQ'@7%H,)@7%H+@6%w.-@6$F2x/@6$Ȥ1@6$H 4@5$HaaU6@5$ȿ$8@5$0:@5${2=<@4$HJ|I>@4$H8U@@4#ȖbB@4#yYnD@3#HS4zF@3#HH@3#H6J@3#mcL@2#ʫN@2#H*P@2"H]R@2"LT@1"DV@1"H:X@1"H|Z@1"H_6]@1"Ƚ_@0"aa@0"Hze&c@0!H2e@0!6>?g@/!ȔKi@/!NWk@/!HQ dm@/!Hepo@.! ~|q@.!k8s@. !Bu@. H(w@- Hg֭y@- ! {@- Bi}@- H@, HPށ@, H] G@, ȻŐ@, @+ Hx:$@+ Hm@+ H4(@+ Ȓi5@* #KA@* HOޔM@*HY@* S(f@)i rr@)ǻ~@)H&@)Hz@&*@%HM 7@%HmWC@%H (O@%g[@$Ŝ4h@$H$W~t@$HȀ@$@#>[@#Ȝ@@#H@#HY8@"ȷo@"*@"s@"HҞ_@!H0Y@!Ȏ@!<@!HK @ HB,@ H9@ ecE@ qQ@H",]@H@j@Hޠv@<[Ԃ@Ț@Hg@HW@ȵD@D@q@$9ll@$r@dFx@du~@d@ˤӋ$@̤iI@1Fn@`#@$ @$ܩ @$ @d& @dLuK @Τ{Rp@Τ/@ @@$8@$g(@$M@d^r@d;@Ф#@ФR@@䰰* @ߍO@$kt@$>H@dm%$@d* @d1!@Ҥ,7"@Ӥ)Q=#@XwvC$@TI%@$1O&@$U'@$ \(@dD.b)@dsSh*@դxn+@դ`t,@դ>z-@/.@^ /@$00@$U1@dz2@dm3@dJJĥ4@פy'5@ؤ6@27@W8@5|9@$ey:@$V;@d3<@d=@ ڤ!4>@ ڤPY?@ ڤ~@@ 䮅A@ bB@ $ @D@ $<E@ $k6F@ d[G@ dɴH@ ܤ I@ ݤ'o&J@ VL,K@ )3L@ 99M@ $]?N@ $EO@ ߾dBKP@ ߽dq{QQ@߽dXWR@޽ߤ5^S@޽ߤ;dT@޼-_jU@޼\̈́pV@ݼ$vW@ݼ$|X@ݻ $dY@ܻ dBZ@ܻ dH=[@ܻ wa\@ۺ ⤦ن]@ۺ ն^@ۺ Ч_@ں 3q`@ڹ $cNa@ڹ!$+?b@ٹ!ddc@ٹ!dd@ٸ!díe@ظ!Nf@ظ!}}g@ظ!Zh@ط!7Ai@׷! fj@׷"$:k@׷"$iϯl@ֶ"dm@ֶ"dljo@ֶ"f p@ն"%DCq@ն"T!hr@յ"s@Ե"۱"t@Ե#$(u@Ե#$.v@Ӵ#d@s 5w@Ӵ#doPE;x@Ӵ#餞-jAy@Ӵ# Gz@ҳ#M{@ҳ#+S|@ҳ$ZY}@ѳ$$"`~@Ѳ$$\Gf@Ѳ$d9ll@в$dr@в$dFx@б$u~@ϱ$줤@ϱ$Ӌ$@ϱ%iI@ΰ%1Fn@ΰ%$a#@ΰ%$@ΰ%dܩ@ͯ%d@ͯ %&@ͯ %LuK@̯ &{RpŽ@̯ &/ȏ@̮ & ΐ@ˮ &$ ԑ@ˮ &$8ے@ˮ &$g(@ʭ &dM@ʭ &d^r@ʭ ';@ɭ '#@ɬ 'R@ɬ '@ɬ '䰰* @Ȭ '$O@ȫ '$kt@ȫ 'd>H@ǫ (dm%$@ǫ (d*@Ǫ (1@ƪ (,7@ƪ ()Q=@ƪ (XwvC@Ū ($TI@ũ ($1O@ũ ($U@ĩ )d \@ĩ )dD.b@Ĩ )sSh@Ĩ )xn@è )`t@è )>z@ç )/瀮@§ *$_ @§ *$0@§ *dU@ *dz@ *dm@ *JJĥ@ *y'髵@ *@ +2@ +W@ +$6|Ĺ@ +$eyʺ@ +dVл@ +d3ּ@쾤 +ݽ@쾤 +!4@콣 ,PY@콣 ,~@뽣 ,䮅@뼣 ,$b@뼣 ,$ @@꼢 ,$<@껢 ,dk6@껢 ,d[@껢 -ɴ@麡 - @麡 -'o&@麡 -VL,@躡 -)3@蹠 -$99@蹠 -$]?@蹠 -dE@縠 .dBK@縠 .dq{Q@縟 .XW@緟 .5^@淟 .;d@淟 .-_j@涞 .$]̈́p@嶞 /$v@嶞 /$|@嵞/dd@嵝/dB@䵝/H=@䵝/wa@䴝/ن@䴝/ն@㴜0$Ч@㳜0$4q@㳜0$cN@Ⳝ0d+?@ⲛ0dd@ⲛ0@ⲛ0í@ᱛ1N@ᱚ1}}@ᱚ1Z@ᰚ1$7A@చ1$ f@చ1d:@ఙ1diϯ@߯2d@߯2lj@߯2f @߮2%DC@ޮ2 T!h@ޮ2 $@ޭ2 $۱"@ݭ2 $(@ݭ3 d.@ݬ3 d@s 5@ݬ3 oPE;@ܬ3 -jA@ܫ3 G@ܫ3 M@ܫ3 +S@۫4 $[Y@۪4 $"`@۪4 d\Gf@ڪ4 d9ll@ک4 dr@ک4 Fx@ک4 u~@٨5䤮@٨5Ӌ$@٨5iI@ا5$2Fn@ا5$a#@ا5d @ا5dܩ @צ6 @צ6& @צ6LuK @֥6{Rp@֥6/@֥6$ @֤6$ @դ7$8@դ7dg(@գ7dM@գ7^r@ԣ7;@Ԣ7#@Ԣ7R@Ӣ8@Ӣ8$* @ӡ8$O@ӡ8dkt@ҡ8d>H@Ҡ8dm%$@Ҡ8* @Ѡ91!@џ9,7"@џ9)Q=#@џ9$YwvC$@О9$TI%@О9$1O&@О9dU'@Ϟ:d \(@ϝ:D.b)@ϝ:sSh*@ϝ:xn+@Μ:`t,@Μ:>z-@Μ;$0.@͛;$_ /@͛;d00@͛;dU1@͚;dz2@̚;m3@̚;JJĥ4@̚<y'5@̙<6@˙<27@˙<$W8@˘<$6|9@ʘ<dey:@ʘ<dV;@ʗ=3<@ʗ==@ɗ=!4>@ɖ=PY?@ɖ=~@@Ȗ=$A@Ȗ=$bB@ȕ>d @D@ȕ>d<E@Ǖ> k6F@ǔ> [G@ǔ> ɴH@Ɣ>! I@Ɠ?!'o&J@Ɠ?!$WL,K@Ɠ?!$)3L@Œ?"d99M@Œ?"d]?N@Œ?"dEO@đ?#BKP@đ@#q{QQ@đ@#XWR@đ@#5^S@Ð@$;dT@Ð@$$._jU@Ð@$$]̈́pV@A%dvW@A%d|X@A%dY@ŽA%BZ@A&H=[@A&wa\@A&ن]@B'$ֶ^@B'$Ч_@B'$4q`@B'dcNa@B(d+?b@B(dc@C(d@C)íe@C)Nf@C)}}g@C)$Zh@C*$7Ai@D*d fj@~D*d:k@~D+diϯl@~D+m@~D+ljo@}D+f p@}D,%DCq@}E,$U!hr@}E,$s@}E-$۱"t@|E-d(u@|E-d.v@|E.@s 5w@|F.oPE;x@|F.-jAy@{F. Gz@{F/M{@{F/$,S|@{F/$[Y}@{G0d"`~@zG0d\Gf@zG0d9ll@zG0r@zG1Fx@zG1u~@yH1䤮@yH2Ӌ$@yH2$iI@yH2$2Fn@yH2da#@xH3d@xI3ܩ@xI3@xI4&@xI4LuK@wI4{RpŽ@~wI4$/ȏ@~wJ5$ ΐ@~wJ5$ ԑ@~vJ5d8ے@}vJ6dg(@}vJ6M@}vJ6^r@|vJ6;@|uK7#@|uK7R@{uK7$@{uK8$* @{uK8dO@{tK8dkt@ztL9d>H@ztL9m%$@ztL9*@ytL91@ysL:,7@ysL:$*Q=@xsM:$YwvC@xsM;$TI@xsM;d1O@wrM;dU@wrM; \@wrNz@uqN=$0瀮@uqO=d_ @uqO>d0@tpO>U@tpO>z@tpO?m@tpO?JJĥ@spP?y'髵@soP@$@soP@$2@roP@dW@roP@d6|Ĺ@roPAdeyʺ@qnQAVл@qnQA3ּ@qnQBݽ@pnQB!4@pnQB$QY@pmQB$~@pmRC$@omRCdb@omRCd @@omRD<@nmRDk6@nlRD[@nlSEɴ@mlSE @mlSE$(o&@mlSE$WL,@mkSFd)3@lkTFd99@lkTFd]?@lkTGE@kkTGBK@kjTGq{Q@kjTGXW@jjUH5^@jjUH$;d@jjUH$._j@jiUId]̈́p@iiUIdv@iiUI|@iiVJd@hiVJB@hhVJH=@hhVJwa@ghVK$ن@ghVK$ֶ@ghWK$Ч@fgWLd4q@fgWLdcN@fgWL+?@fgWLd@egXM@egXMí@efXMN@dfXN$~}@dfXN$Z@dfXNd7A@cfYOd f@ceYOd:@ceYOiϯ@ceYO@beYPlj@beZPf @bdZP$&DC@adZQ$U!h@adZQ$@adZQd۱"@`dZRd(@`c[R.@`c[R@s 5@`c[RoPE;@_c[S-jA@_c[S G@_c\S$M@^b\T$,S@^b\Td[Y@^b\Td"`@]b\Ud\Gf@]b\U9ll@]a]Ur@]a]UFx@\a]Vu~@\a]V䤮@\a]V$ԋ$@[`^W$iI@[`^Wd2Fn@[`^Wda#@Z`^W @Z`^Xܩ @Z`^X @Z__X& @Y__YLuK @Y__Y$|Rp@Y__Y$/@X__Zd @X^`Zd @X^`Z8@W^`Zg(@W^`[M@W^`[^r@W^`[;@V]a\$$@V]a\$S@V]a\d@U]a]d* @U]a]dO@U\b]kt@U\b]>H@T\b^m%$@T\b^* @T\b^1!@S\c_$,7"@S[c_$*Q=#@S[c_dYwvC$@R[c`dTI%@R[c`1O&@R[c`U'@RZd` \(@QZdaD.b)@QZdasSh*@QZda$xn+@PZdb$`t,@PZeb$>z-@PYebd0.@OYecd_ /@OYec00@OYecU1@OYfcz2@NXfdm3@NXfdJJĥ4@NXfd$z'5@MXfe$6@MXged27@MXgedW8@LWgfd6|9@LWgfey:@LWgfV;@LWgf3<@KWhg=@KVhg$"4>@KVhg$QY?@JVhh$~@@JVhhdA@JVihdbB@~JVii @D@~IUii<E@~IUiik6F@}IUij[G@}HUjjɴH@}HUjj$ I@}HUjj$(o&J@|GTjkdWL,K@|GTjkd)3L@|GTkkd99M@{GTkl]?N@{FTklEO@{FTklBKP@zFSkmq{QQ@zESlmXWR@zESlm$5^S@zESlm$;dT@yESlnd._jU@yDRlnd]̈́pV@yDRmnvW@xDRmo|X@xCRmodY@xCRmoBZ@wCRmpH=[@wBQmp$xa\@wBQnp$ن]@wBQnp$ֶ^@vBQnqdЧ_@vAQnqd4q`@vAQnqcNa@uAPor+?b@u@Pordc@u@Pord@t@Posíe@t@Pos$Of@t?Pps$~}g@s?OptdZh@s?Optd7Ai@s>Optd fj@s>Opt:k@r>Oquiϯl@r=Oqu䘬m@r=Nquljo@q=Nqv$f p@q=Nqv$&DCq@qH@c0G{m%$@c/F{*@c/F{$1@b/F{$,7@b.F{d*Q=@b.F|dYwvC@a.F|TI@a.E|1O@a-E|U@a-E| \@`-E}D.b@`,E}$tSh@`,E}$xn@_,D}$`t@_+D}d>z@_+D~d0瀮@^+D~_ @^+D~0@^*D~佲U@^*Dz@]*Cm@])C$KJĥ@])C$z'髵@\)Cd@\)Cd2@\(CdW@[(B6|Ĺ@[(Beyʺ@['BVл@Z'B3ּ@Z'B$ݽ@Z'B$"4@Z&A$QY@Y&Ad~@Y&Ad@Y%Ab@X%A @@X%A<@X%Ak6@W$@[@W$@$ʴ@W$@$ @V#@d(o&@V#@dWL,@V#@d)3@V#?99@U"?]?@U"?E@U"?BK@T!?q{Q@T!?$XW@T!?$5^@S!>d;d@S >d._j@S >]̈́p@R >v@R>|@R>d@Q=B@Q=$I=@Q=$xa@Q=dن@P=dֶ@P=Ч@P=4q@O<cN@O<+?@O<d@N<$@N<$ í@N<dO@M<d~}@M;dZ@M;7A@M; f@L;:@L;iϯ@L;䘬@K;$ȉ@K:$f @K:d&DC@J:dU!h@J:@J:۱"@I:(@I9.@I9@s 5@I9$pPE;@H9$-jA@H9$ G@H9dM@G9d,S@G8[Y@G8"`@F8\Gf@F89ll@F8r@E8$Gx@E8$v~@E7d@E7dԋ$@D7diI@D72Fn@D7a#@C7 @C7ܩ @C6$ @B6$& @B6$MuK @B6d|Rp@A6d/@A6 @A6 @@58@@5g(@@5䖁M@@5$^r@?5$;@?5d$@?5dS@> 4d@> 4* @> 4O@= 4kt@= 4>H@= 4m%$@< 4$* @< 3$1!@< 3d,7"@< 3d*Q=#@; 3YwvC$@; 3TI%@; 31O&@: 3U'@: 2 \(@: 2$E.b)@9 2$tSh*@9 2$xn+@92d`t,@82d>z-@820.@82_ /@7100@71佲U1@71z2@71$m3@61$KJĥ4@61dz'5@61d6@50d27@50W8@506|9@40ey:@40V;@40$3<@30$=@3/$"4>@3/dQY?@2/d~@@2/A@2/bB@2/ @D@1/ <E@1/ $l6F@1. $[G@0. $ʴH@0. d I@0. d(o&J@/. WL,K@/. )3L@/. 99M@.- ]?N@.- EO@.- $CKP@-- $r{QQ@-- dXWR@-- d5^S@-- d;dT@,- ._jU@,, ]̈́pV@,, 䌪vW@+, 仇|X@+, $dY@+, $BZ@*, $I=[@*, dxa\@*, dن]@)+ ֶ^@)+ Ч_@)+ 4q`@(+ cNa@(+ +?b@(+ $dc@(+ $d@'+ d íe@'* dOf@'* d~}g@&* Zh@&* 7Ai@&* fj@%* :k@%* iϯl@%* $m@$) $ȉo@$) df p@$) d&DCq@#) ĤU!hr@#) Ĥs@#) Ĥ۱"t@#) (u@"( .v@"( $As 5w@"( $pPE;x@!( $-jAy@!( d Gz@!( dM{@ ( Ǥ,S|@ ( Ǥ[Y}@ ( "`~@' \Gf@' 9ll@' $r@' $Gx@' dv~@' d@' dԋ$@' ʤiI@& ʤ2Fn@& a#@& @& $ܩ@& $@& $&@& dMuK@& d|RpŽ@% ͤ/ȏ@% ͤ ΐ@%ͤ ԑ@%8ے@%g(@%$M@%$^r@%d;@$d$@$dS@$Ф@$Ф* @$O@$kt@$>H@$$n%$@$$*@#d1@#d,7@#Ӥ*Q=@#ӤYwvC@#ӤTI@#1O@#U@#$ \@"$E.b@"dtSh@"dxn@"դ`t@"֤>z@"֤0瀮@"_ @"0@"$U@!$z@!dm@!dKJĥ@!dz'髵@!ؤ@!٤2@!W@!6|Ĺ@ !eyʺ@ $Vл@ $3ּ@ dݽ@ d"4@ ۤQY@ ܤ~@ ܤ@ b@  @@ $=@ $l6@ $[@ dʴ@ d @ ޤ(o&@ߤWL,@)3@99@]?@$E@$CK@dr{Q@dXW@d5^@;d@._j@]̈́p@䌪v@$|@$d@$B@dI=@dxa@䤧ن@ֶ@Ч@4q@cN@$+?@$d@d@d í@dO@~}@褭Z@7A@ f@:@$jϯ@$@dȉ@df @&DC@U!h@뤄@۱"@(@$.@$As 5@$pPE;@d-jA@d G@M@,S@[Y@"`@\Gf@$9ll@$r@dGx@dv~@d@ԋ$@iI@2Fn@a#@$ @$ܩ @$ @d& @dMuK @|Rp@/@ @ @$9@$h(@$M@d^r@d;@$@S@@䱰* @O@$kt@$?H@dn%$@d* @d1!@,7"@*Q=#@YwvC$@TI%@$1O&@$U'@$ \(@dE.b)@dtSh*@xn+@`t,@>z-@0.@_ /@$00@$U1@dz2@dm3@dKJĥ4@z'5@6@27@W8@6|9@$fy:@$V;@d3<@d=@"4>@QY?@~@@䯅A@bB@$@D@$=E@$l6F@d[G@dʴH@ I@(o&J@WL,K@)3L@99M@$]?N@$EO@߾dCKP@߽dr{QQ@߽dXWR@޽ 5^S@޽ ;dT@޼ ._jU@޼ ]̈́pV@ݼ $vW@ݼ $|X@ݻ $dY@ܻ dBZ@ܻ dI=[@ܻ xa\@ۺ ن]@ۺ ֶ^@ۺ Ч_@ں 4q`@ڹ $dNa@ڹ! $+?b@ٹ!ddc@ٹ!dd@ٸ!d íe@ظ!Of@ظ!~}g@ظ!Zh@ط!7Ai@׷! fj@׷"$;k@׷"$jϯl@ֶ"dm@ֶ"dȉo@ֶ"f p@ն"&DCq@ն"U!hr@յ"s@Ե"۱"t@Ե#$(u@Ե#$.v@Ӵ#dAs 5w@Ӵ#dpPE;x@Ӵ#-jAy@Ӵ# Gz@ҳ#M{@ҳ#,S|@ҳ$[Y}@ѳ$$"`~@Ѳ$$\Gf@Ѳ$d9ll@в$dr@в$dGx@б$v~@ϱ$@ϱ$ԋ$@ϱ%iI@ΰ%2Fn@ΰ%$b#@ΰ%$@ΰ%dܩ@ͯ%d@ͯ %&@ͯ %MuK@̯ &|RpŽ@̯ &/ȏ@̮ & ΐ@ˮ &$ ԑ@ˮ &$9ے@ˮ &$h(@ʭ &dM@ʭ &d^r@ʭ ';@ɭ '$@ɬ 'S@ɬ '@ɬ '䱰* @Ȭ '$O@ȫ '$kt@ȫ 'd?H@ǫ ( dn%$@ǫ ( d*@Ǫ ( 1@ƪ (!,7@ƪ (!*Q=@ƪ (!YwvC@Ū ("$TI@ũ ("$1O@ũ ("$U@ĩ )#d \@ĩ )#dE.b@Ĩ )#tSh@Ĩ )#xn@è )$`t@è )$>z@ç )$0瀮@§ *%$` @§ *%$0@§ *%dU@ *&dz@ *&dm@ *&KJĥ@ *'z'髵@ *'@ +'2@ +(W@ +($7|Ĺ@ +($fyʺ@ +(dVл@ +)d3ּ@ +)ݽ@ +)"4@ ,*QY@ ,*䀨~@ ,*䯅@ ,+$b@ ,+$@@ ,+$=@ ,,dl6@ ,,d[@ -,ʴ@ -- @ --(o&@ --WL,@ --)3@ -.$99@ -.$]?@ -.dE@ ./dCK@ ./dr{Q@ ./XW@ .05^@ .0;d@ .0._j@ .1$^̈́p@ /1$v@ /1$|@/2dd@/2dB@/2I=@/2xa@/3ن@/3ֶ@03$Ч@04$5q@04$dN@04d+?@05dd@05@05 í@16O@16~}@16Z@17$7A@17$ f@17d;@17djϯ@28d@28ȉ@28f @29&DC@2 9U!h@2 9$@2 :$۱"@2 :$(@3 :d.@3 ;dAs 5@3 ;pPE;@3 ;-jA@3 < G@3 dr@4 >Gx@4 >v~@5?䥮@5?ԋ$@5?iI@5@$3Fn@5@$b#@5@d @5@dܩ @6A @6A& @6AMuK @6B|Rp@6B/@6B$ @6C$ @7C$9@7Cdh(@7DdM@7D^r@7D;@7E$@7ES@8E@8E$* @8F$O@8Fdkt@8Fd?H@8Gdn%$@8G* @9G1!@9H,7"@9H*Q=#@9H$ZwvC$@9I$TI%@9I$1O&@9IdU'@:Id \(@:JE.b)@:JtSh*@:Jxn+@:K`t,@:K>z-@;K$1.@;L$` /@;Ld00@;LdU1@;Mdz2@;Mm3@;MKJĥ4@<Mz'5@<N6@<N27@<N$W8@<O$7|9@<Odfy:@<OdV;@=P3<@=P=@=P"4>@=QQY?@=Q䀨~@@=Q$A@=Q$bB@>Rd@D@>Rd=E@> Rl6F@> S[G@> SʴH@>!S I@?!T(o&J@?!T$XL,K@?!T$)3L@?"Ud99M@?"Ud]?N@?"UdEO@?#VCKP@@#Vr{QQ@@#VXWR@@#V5^S@@$W;dT@@$W$/_jU@@$W$^̈́pV@A%XdvW@A%Xd|X@A%XdY@A%YBZ@A&YI=[@A&Yxa\@A&Zن]@B'Z$׶^@B'Z$Ч_@B'Z$5q`@B'[ddNa@B([d+?b@B([dc@C(\d@C)\ íe@C)\Of@C)]~}g@C)]$Zh@C*]$7Ai@D*^d fj@~D*^d;k@~D+^djϯl@~D+^m@~D+_ȉo@}D+_f p@}D,_&DCq@}E,`$V!hr@}E,`$s@}E-`$۱"t@|E-ad(u@|E-ad.v@|E.aAs 5w@|F.apPE;x@|F.b-jAy@{F.b Gz@{F/bM{@{F/c$-S|@{F/c$\Y}@{G0cd"`~@zG0dd\Gf@zG0dd9ll@zG0dr@zG1eGx@zG1ev~@yH1e䥮@yH2eԋ$@yH2f$iI@yH2f$3Fn@yH2fdb#@xH3gd@xI3gܩ@xI3g@xI4h&@xI4hMuK@wI4h|RpŽ@~wI4i$/ȏ@~wJ5i$ ΐ@~wJ5i$ ԑ@~vJ5id9ے@}vJ6jdh(@}vJ6jM@}vJ6j^r@|vJ6k;@|uK7k$@|uK7kS@{uK7l$@{uK8l$* @{uK8ldO@{tK8ldkt@ztL9md?H@ztL9mn%$@ztL9m*@ytL9n1@ysL:n,7@ysL:n$+Q=@xsM:o$ZwvC@xsM;o$TI@xsM;od1O@wrM;pdU@wrM;p \@wrNz@uqN=r$1瀮@uqO=rd` @uqO>rd0@tpO>sU@tpO>sz@tpO?sm@tpO?sKJĥ@spP?tz'髵@soP@t$@soP@t$2@roP@udW@roP@ud7|Ĺ@roPAudfyʺ@qnQAvVл@qnQAv3ּ@qnQBvݽ@pnQBw"4@pnQBw$RY@pmQBw$~@pmRCw$@omRCxdb@omRCxd@@omRDx=@nmRDyl6@nlRDy[@nlSEyʴ@mlSEz @mlSEz$)o&@mlSEz$XL,@mkSFzd)3@lkTF{d99@lkTF{d]?@lkTG{E@kkTG|CK@kjTG|r{Q@kjTG|XW@jjUH}5^@jjUH}$;d@jjUH}$/_j@jiUI}d^̈́p@iiUI~dv@iiUI~|@iiVJ~d@hiVJB@hhVJI=@hhVJxa@ghVK$ن@ghVK$׶@ghWK$Ч@fgWLd5q@fgWLddN@fgWL+?@fgWLd@egXM@egXM í@efXMO@dfXN$}@dfXN$Z@dfXNd7A@cfYOd f@ceYOd;@ceYOjϯ@ceYO@beYPȉ@beZPf @bdZP$'DC@adZQ$V!h@adZQ$@adZQd۱"@`dZRd(@`c[R.@`c[RAs 5@`c[RpPE;@_c[S-jA@_c[S G@_c\S$M@^b\T$-S@^b\Td\Y@^b\Td"`@]b\Ud\Gf@]b\U9ll@]a]Ur@]a]UGx@\a]Vv~@\a]V䥮@\a]V$Ջ$@[`^W$iI@[`^Wd3Fn@[`^Wdb#@Z`^W @Z`^Xܩ @Z`^X @Z__X& @Y__YMuK @Y__Y$}Rp@Y__Y$/@X__Zd @X^`Zd @X^`Z9@W^`Zh(@W^`[M@W^`[^r@W^`[;@V]a\$%@V]a\$T@V]a\d@U]a]d* @U]a]dO@U\b]kt@U\b]?H@T\b^n%$@T\b^* @T\b^1!@S\c_$,7"@S[c_$+Q=#@S[c_dZwvC$@R[c`dTI%@R[c`1O&@R[c`U'@RZd` \(@QZdaE.b)@QZdatSh*@QZda$xn+@PZdb$`t,@PZeb$>z-@PYebd1.@OYecd` /@OYec00@OYecU1@OYfcz2@NXfdm3@NXfdKJĥ4@NXfd${'5@MXfe$6@MXged27@MXgedW8@LWgfd7|9@LWgffy:@LWgfV;@LWgf3<@KWhg=@KVhg$#4>@KVhg$RY?@JVhh$~@@JVhhdA@JVihdbB@JVii@D@IUii=E@IUiil6F@IUij[G@HUjjʴH@HUjj$ I@HUjj$)o&J@GTjkdXL,K@GTjkd)3L@GTkkd99M@GTkl]?N@FTklEO@FTklCKP@FSkmr{QQ@ESlmXWR@ESlm$5^S@ESlm$;dT@ESlnd/_jU@DRlnd^̈́pV@DRmnvW@DRmo|X@CRmodY@CRmoBZ@CRmpI=[@BQmp$ya\@BQnp$ن]@BQnp$׶^@BQnqdЧ_@AQnqd5q`@AQnqdNa@APor+?b@@Pordc@@Pord@@Pos íe@@Pos$Pf@?Pps$}g@?OptdZh@?Optd7Ai@>Optd fj@>Opt;k@>Oqujϯl@=Oqu䙬m@=Nquȉo@=Nqv$f p@=Nqv$'DCq@z@+D~d1瀮@+D~` @+D~0@*D~侲U@*Dz@*Cm@)C$LJĥ@)C${'髵@)Cd@)Cd2@(CdW@(B7|Ĺ@(Bfyʺ@'BVл@'B3ּ@'B$ݽ@'B$#4@&A$RY@&Ad~@&Ad@%A¤b@%A¤@@%A¤=@%Al6@$@[@$@$˴@$@$ @#@d)o&@#@dXL,@#@d)3@#?Ĥ99@"?Ť]?@"?E@"?CK@!?r{Q@!?$XW@!?$5^@!>d;d@ >d/_j@ >Ǥ^̈́p@ >Ǥv@>Ȥ|@>d@=B@=$J=@=$ya@=dن@=d׶@=ʤЧ@=ʤ5q@<ʤdN@<+?@<d@<$@<$!í@<dP@<d}@;dZ@;̤7A@;ͤ f@;;@;jϯ@;䙬@;$ɉ@:$f @:d'DC@:dV!h@:Ϥ@:Ϥ۱"@:Ϥ(@9.@9As 5@9$qPE;@9$-jA@9$ G@9dM@9d-S@8Ҥ\Y@8Ҥ"`@8\Gf@89ll@8r@8$Hx@8$w~@7d@7dՋ$@7diI@7դ3Fn@7դb#@7 @7ܩ @6$ @6$& @6$NuK @6d}Rp@6d/@6פ @6פ @5ؤ9@5h(@5䗁M@5$^r@5$;@5d%@5dT@ 4d@ 4ڤ* @ 4ڤO@ 4kt@ 4?H@ 4n%$@ 4$* @ 3$1!@ 3d,7"@ 3d+Q=#@ 3ܤZwvC$@ 3ݤTI%@ 3ݤ1O&@ 3U'@ 2 \(@ 2$F.b)@ 2$uSh*@ 2$xn+@2d`t,@2d>z-@2ߤ1.@2ߤ` /@100@1侲U1@1z2@1$m3@1$LJĥ4@1d{'5@1d6@0d27@0W8@07|9@0fy:@0V;@0$3<@0$=@/$#4>@/dRY?@/d~@@/䤰A@/bB@/@D@/ =E@/ $m6F@. $[G@. $˴H@. d I@. d)o&J@. XL,K@. 礇)3L@. 99M@- ]?N@- EO@- $DKP@- $s{QQ@- dXWR@- d5^S@- d;dT@- /_jU@, ^̈́pV@, 䍪vW@, 伇|X@, $dY@, $BZ@, $J=[@, dya\@, dن]@+ ׶^@+ Ч_@+ 5q`@+ dNa@+ +?b@+ $dc@+ $d@+ d!íe@* dPf@* d}g@* 冷Zh@* 7Ai@* fj@* ;k@* jϯl@* $m@) $ɉo@) df p@) d'DCq@) V!hr@) s@) ۱"t@) (u@( .v@( $Bs 5w@( $qPE;x@( $-jAy@( d Gz@( dM{@( -S|@( \Y}@( "`~@' \Gf@' 9ll@' $r@' $Hx@' dw~@' d@' dՋ$@' iI@& 3Fn@& b#@& @& $ܩ@& $@& $&@& dNuK@& d}RpŽ@% /ȏ@% ΐ@% ԑ@%9ے@%h(@%$M@%$^r@%d;@$d%@$dT@$@$* @$O@$kt@$?H@$$o%$@$$*@#d1@#d,7@#+Q=@#ZwvC@#TI@#1O@#U@#$ \@"$F.b@"duSh@"dxn@"`t@">z@"1瀮@"` @"0@"$U@!$z@!dm@!dLJĥ@!d{'髵@!@!2@!W@!7|Ĺ@!fyʺ@ $Vл@ $3ּ@ dݽ@ d#4@ RY@ ~@ @ b@ @@$>@$m6@$[@d˴@d @)o&@XL,@ )3@ 99@ ]?@ $E@ $DK@ ds{Q@ dXW@ d5^@ ;d@ /_j@ ^̈́p@ 䍪v@ $|@ $d@ $B@ dJ=@ dya@ ن@ ׶@Ч@5q@dN@$+?@$d@d@d!í@dP@}@Z@7A@ f@;@$kϯ@$@dɉ@df @'DC@V!h@@۱"@(@$.@$Bs 5@$qPE;@d-jA@d G@M@-S@\Y@"`@\Gf@$9ll@$r@dHx@dw~@d@Ջ$@iI@3Fn@b#@$ @$ܩ @$ @d& @dNuK @}Rp@/@ @ @$:@$i(@$M@d^r@d;@%@T@@䲰* @O@$kt@$@H@do%$@d* @d1!@,7"@+Q=#@ZwvC$@TI%@$1O&@$U'@ $ \(@ dF.b)@ duSh*@ xn+@!`t,@!>z-@!1.@!` /@"$00@"$U1@"dz2@"dm3@#dLJĥ4@#{'5@#6@#27@$W8@$7|9@$$gy:@$$V;@%d3<@%d=@%#4>@%RY?@&~@@&䰅A@&bB@&$@D@'$>E@'$m6F@'d[G@'d˴H@( I@()o&J@(XL,K@()3L@)99M@)$]?N@)$EO@)dDKP@*ds{QQ@*dXWR@ *5^S@ *;dT@ +/_jU@ +^̈́pV@ +$vW@ +$|X@ ,$dY@ ,dBZ@ ,dJ=[@ ,ya\@ -ن]@ -׶^@ -Ч_@ -5q`@ .$eNa@! .$+?b@!.ddc@!.dd@!/d!íe@!/Pf@!/}g@!/Zh@!07Ai@!0 fj@"0$$1O@ (">$U@ )#>d \@ )#>dF.b@ )#?uSh@ )#?xn@ )$?`t@ )$?>z@ )$@1瀮@ *%@$a @ *%@$0@ *%@dU@ *&Adz@ *&Adm@ *&ALJĥ@ *'A{'髵@ *'A@ +'B2@ +(BW@ +(B$8|Ĺ@ +(B$gyʺ@ +(CdVл@ +)Cd3ּ@ +)Cݽ@ +)C#4@ ,*DRY@ ,*D䁨~@ ,*D䰅@ ,+D$b@ ,+D$@@ ,+E$>@ ,,Edm6@ ,,Ed[@ -,E˴@ --F @ --F)o&@ --FXL,@ --F)3@ -.G$99@ -.G$]?@ -.GdE@ ./GdDK@ ./Gds{Q@ ./HXW@ .0H5^@ .0H;d@ .0H/_j@ .1I$_̈́p@ /1I$v@ /1I$|@/2Idd@/2JdB@/2JdJ=@/2Jya@/3Jن@/3J׶@03KЧ@04K5q@04K$eN@04K$+?@05Ldd@05Ld@05L!í@16LP@16M}@16MZ@17M7A@17M$ f@17M$<@17N$kϯ@28Nd@28Ndɉ@28Nf @29O'DC@2 9OV!h@2 9O@2 :O۱"@2 :O$(@3 :P$.@3 ;PdBs 5@3 ;PdqPE;@3 ;Pd-jA@3 Rdr@4 >RdHx@4 >Sw~@5?S@5?SՋ$@5?SiI@5@S3Fn@5@T$c#@5@T$ @5@Tdܩ @6ATd @6AUd& @6AUNuK @6BU}Rp@6BU/@6BU @6CV @7CV$:@7CV$i(@7DVdM@7DWd^r@7DW;@7EW%@7EWT@8EW@8EX䲰* @8FX$O@8FX$kt@8FX$@H@8GYdo%$@8GYd* @9GY1!@9HY,7"@9HY+Q=#@9HZZwvC$@9IZTI%@9IZ$1O&@9IZ$U'@:I[d \(@:J[dF.b)@:J[duSh*@:J[xn+@:K[`t,@:K\>z-@;K\1.@;L\$a /@;L\$00@;L]$U1@;M]dz2@;M]dm3@;M]LJĥ4@<M]{'5@<N^6@<N^27@<N^W8@<O^$8|9@<O^$gy:@<O_dV;@=P_d3<@=P_d=@=P_#4>@=Q`RY?@=Q`䁨~@@=Q`䰅A@=Q`$bB@>R`$@D@>Rad>E@> Radm6F@> Sad[G@> Sa˴H@>!Sa I@?!Tb)o&J@?!TbXL,K@?!Tb$)3L@?"Ub$99M@?"Uc$]?N@?"UcdEO@?#VcdDKP@@#Vcs{QQ@@#VcXWR@@#Vd5^S@@$Wd;dT@@$Wd/_jU@@$Wd$_̈́pV@A%Xd$vW@A%Xed|X@A%XeddY@A%YedBZ@A&YeJ=[@A&Yfya\@A&Zfن]@B'Zf׶^@B'ZfЧ_@B'Zf$6q`@B'[g$eNa@B([gd+?b@B([gddc@C(\gd@C)\g!íe@C)\hPf@C)]h}g@C)]hZh@C*]h$7Ai@D*^h$ fj@~D*^i$z@qN=rv$2瀮@qO=rv$a @qO>rvd0@pO>swdU@pO>swz@pO?swm@pO?swLJĥ@pP?tw{'髵@oP@tx@oP@tx$2@oP@ux$ W@oP@ux$8|Ĺ@oPAuxdgyʺ@nQAvydVл@nQAvy3ּ@nQBvyݽ@nQBwy#4@nQBwyRY@mQBwz䁨~@mRCwz$@mRCxz$b@mRCxzd@@mRDxzd>@mRDyzdm6@lRDy{[@lSEy{˴@lSEz{ @lSEz{)o&@lSEz{$YL,@kSFz|$)3@kTF{|$99@kTF{|d]?@kTG{|dE@kTG||DK@jTG|}s{Q@jTG|}XW@jUH}}5^@jUH}};d@jUH}}$0_j@iUI}~$_̈́p@iUI~~dv@iUI~~d|@iVJ~~dd@iVJ~B@hVJJ=@hVJya@hVKن@hVK׶@hWK$Ч@gWL$6q@gWLdeN@gWLd+?@gWLd@gXM@gXM!í@fXMP@fXN}@fXN$Z@fXN$7A@fYO$ f@eYOd<@eYOdkϯ@eYO@eYPɉ@eZPf @dZP'DC@dZQV!h@dZQ$@dZQ$۱"@dZRd(@c[Rd.@c[RdBs 5@c[RqPE;@c[S-jA@c[S G@c\SM@b\T$.S@b\T$]Y@b\T$"`@b\Ud\Gf@b\Ud9ll@a]Ur@a]UHx@a]Vw~@a]V䦮@a]VՋ$@`^W$iI@`^W$4Fn@`^Wdc#@`^Wd @`^Xdܩ @`^X @__X& @__YNuK @__Y}Rp@__Y$/@__Z$ @^`Zd @^`Zd:@^`Zdi(@^`[M@^`[^r@^`[;@]a\%@]a\$U@]a\$@]a]$* @]a]dO@\b]dkt@\b]@H@\b^o%$@\b^* @\b^1!@\c_,7"@[c_$,Q=#@[c_$[wvC$@[c`dTI%@[c`d1O&@[c`dU'@Zd` \(@ZdaF.b)@ZdauSh*@Zda䤃xn+@Zdb`t,@Zeb$>z-@Yeb$2.@Yecda /@Yecd00@YecU1@Yfcz2@Xfdm3@XfdLJĥ4@Xfd{'5@Xfe$6@Xge$27@Xge$ W8@Wgfd8|9@Wgfdgy:@WgfV;@Wgf3<@Whg=@Vhg#4>@VhgRY?@Vhh$~@@Vhh$A@VihdbB@Viid@D@Uiid>E@Uiim6F@Uij[G@Ujj˴H@Ujj I@Ujj$*o&J@Tjk$YL,K@Tjk$)3L@Tkkd99M@Tkld]?N@TklEO@TklDKP@Skms{QQ@SlmXWR@Slm5^S@Slm$;dT@Sln$0_jU@Rlnd_̈́pV@RmndvW@Rmod|X@RmodY@RmoBZ@RmpJ=[@Qmpya\@Qnpن]@Qnp$ض^@Qnq$Ч_@Qnqd6q`@QnqdeNa@Por+?b@Pordc@Pord@Pos!íe@PosPf@Pps$}g@Opt$Zh@Opt$7Ai@Optd fj@Optdz@D~$2瀮@D~da @D~d0@D~dU@Dz@Cm@CLJĥ@C{'髵@C@C$2@C$ W@Bd8|Ĺ@Bdgyʺ@BVл@B3ּ@Bݽ@B#4@ARY@A$~@A$@A¦$b@A¦d@@A¦d>@A¦m6@@ç[@@ç˴@@ç @@ħ)o&@@ħ$YL,@@ħ$)3@?Ĩd99@?Ũd]?@?ŨdE@?ŨDK@?ƨs{Q@?ƨXW@?ƨ5^@>Ʃ$;d@>ǩ$0_j@>ǩ$_̈́p@>ǩdv@>ȩd|@>ȩd@=ȪB@=ȪJ=@=ɪya@=ɪن@=ɪ$ض@=ʪ$Ч@=ʪd6q@<ʫdeN@<ʫ+?@<˫d@<˫@<˫!í@<̫P@<̫$}@;̬$Z@;̬$7A@;ͬd f@;ͬd<@;ͬkϯ@;ͬ@;άɉ@:έf @:έ'DC@:ϭ$W!h@:ϭ$@:ϭd۱"@:ϭd(@9Юd.@9ЮBs 5@9ЮqPE;@9Ѯ-jA@9Ѯ G@9Ѯ$M@9Ѯ$.S@8ү$]Y@8үd"`@8үd\Gf@8ӯ9ll@8ӯr@8ӯHx@8ӯw~@7԰䦮@7԰$֋$@7԰$iI@7հd4Fn@7հdc#@7հd @7հܩ @6ֱ @6ֱ& @6ֱNuK @6ֱ}Rp@6ױ$/@6ױ$ @6ױd @5زd:@5زi(@5زM@5ز^r@5ٲ;@5ٲ%@5ٲ$U@4ڳ$@4ڳ$* @4ڳdO@4ڳdkt@4۳@H@4۳o%$@4۳* @3ܴ1!@3ܴ,7"@3ܴ$,Q=#@3ܴ$[wvC$@3ݴdTI%@3ݴd1O&@3ݴdU'@2ݵ \(@2޵F.b)@2޵uSh*@2޵䤃xn+@2ߵ$`t,@2ߵ$>z-@2ߵ$2.@2ߵda /@1d00@1ඤU1@1ඤz2@1ᶤm3@1LJĥ4@1{'5@1$6@0$27@0d W8@0d8|9@0dgy:@0㷤V;@0㷤3<@0=@/#4>@/$SY?@/$~@@/dA@/dbB@/d@D@/ 帤>E@/ 帤m6F@. [G@. ˴H@. $ I@. $*o&J@. $YL,K@. d)3L@. d99M@- 躤]?N@- 躤EO@- 躤DKP@- s{QQ@- XWR@- $5^S@- $;dT@- d0_jU@, d_̈́pV@, dvW@, 껤|X@, 뻤dY@, BZ@, J=[@, ya\@, $ن]@+ $ض^@+ dЧ_@+ d6q`@+ eNa@+ +?b@+ dc@+ d@+ !íe@* $Qf@* $}g@* $Zh@* d7Ai@* d fj@* z@"d2瀮@"Ťa @"Ť0@"ŤU@!z@!m@!$MJĥ@!$|'髵@!$@!d2@!d W@!Ƥ8|Ĺ@!Ƥgyʺ@ Vл@ 3ּ@ ݽ@ $$4@ $SY@ d~@ d@ db@ Ǥ@@Ȥ>@m6@[@$̴@$ @$*o&@dYL,@ d)3@ Ȥ99@ ɤ]?@ ɤE@ DK@ s{Q@ $XW@ $5^@ d;d@ d0_j@ d_̈́p@ ʤv@ ʤ|@ d@ B@ J=@ $za@ $ن@ dض@dЧ@ʤ6q@ˤeN@ˤ+?@d@@$"í@$Q@$}@dZ@d7A@̤ f@̤<@kϯ@䚬@ɉ@$f @$(DC@dW!h@d@d۱"@ͤ(@ͤ.@Bs 5@qPE;@$-jA@$ G@$M@d.S@d]Y@ͤ"`@Τ\Gf@Τ9ll@r@Hx@$x~@$@d֋$@diI@d4Fn@Τc#@Ϥ @ܩ @ @$ & @$OuK @d~Rp@d/@d @Ϥ @Ϥ:@i(@䘁M@$^r@$;@$&@dU@d@Ф* @ФO@Фkt@@H@o%$@$* @$1!@d,7"@d,Q=#@d[wvC$@ѤTI%@Ѥ1O&@U'@  \(@ F.b)@ $vSh*@ $xn+@!d`t,@!d>z-@!Ҥ2.@!Ҥa /@"Ҥ00@"俲U1@"z2@"$m3@#$MJĥ4@#$|'5@#d6@#d27@$Ӥ W8@$Ӥ8|9@$gy:@$V;@%3<@%$=@%$$4>@%dSY?@&d~@@&dA@&ԤbB@&Ԥ@D@'>E@'m6F@'$[G@'$̴H@($ I@(d*o&J@(dYL,K@(դ)3L@)դ99M@)դ]?N@)EO@)DKP@*$t{QQ@*$XWR@ *d5^S@ *d;dT@ +d0_jU@ +դ_̈́pV@ +դvW@ +佇|X@ ,dY@ ,BZ@ ,$K=[@ ,$za\@ -dن]@ -dض^@ -֤Ч_@ -֤6q`@ .֤eNa@! .+?b@!.dc@!.$d@!/$"íe@!/$Qf@!/d}g@!/dZh@!0פ7Ai@!0פ fj@"01O@ (">U@ )#> \@ )#>$G.b@ )#?$vSh@ )#?dxn@ )$?d`t@ )$?ܤ>z@ )$@ܤ2瀮@ *%@ܤa @ *%@0@ *%@俲U@ *&A$z@ *&A$m@ *&A$MJĥ@ *'Ad|'髵@ *'Ad@ +'Bܤ2@ +(Bݤ W@ +(B8|Ĺ@ +(Bgyʺ@ +(CVл@ +)C$3ּ@ +)C$ݽ@ +)Cd$4@ ,*DdSY@ ,*Dd~@ ,*Dݤ@ ,+Dݤb@ ,+D@@ ,+E>@ ,,E$n6@ ,,E$[@ -,E$̴@ --Fd @ --Fd*o&@ --FޤYL,@ --Fޤ)3@ -.Gޤ99@ -.G]?@ -.GE@ ./G$EK@ ./G$t{Q@ ./HdXW@ .0Hd5^@ .0Hd;d@ .0Hޤ0_j@ .1Iޤ_̈́p@ /1I䎪v@ /1I佇|@/2I$d@/2J$B@/2JdK=@/2Jdza@/3Jdن@/3Jߤض@03KߤЧ@04K6q@04KeN@04K$+?@05L$d@05L$@05Ld"í@16LdQ@16Mߤ}@16MߤZ@17Mߤ7A@17M f@17M<@17N$lϯ@28N$@28Ndʉ@28Ndf @29Od(DC@2 9OW!h@2 9Oआ@2 :O۱"@2 :O(@3 :P.@3 ;P$Cs 5@3 ;P$rPE;@3 ;Pd-jA@3 R$r@4 >R$Ix@4 >Sdx~@5?Sd@5?S֋$@5?SiI@5@S4Fn@5@Tc#@5@T @5@T$ܩ @6AT$ @6AUd & @6AUdOuK @6BUd~Rp@6BU᤭/@6BU @6CV @7CV:@7CV$j(@7DV$M@7DW$^r@7DWd;@7EWd&@7EWU@8EW⤄@8EX⤳* @8FXO@8FXkt@8FX$AH@8GY$p%$@8GYd* @9GYd1!@9HYd,7"@9HY,Q=#@9HZ[wvC$@9IZTI%@9IZ1O&@9IZU'@:I[$ \(@:J[$G.b)@:J[dvSh*@:J[dxn+@:K[`t,@:K\>z-@;K\2.@;L\a /@;L\00@;L]$U1@;M]$z2@;M]$m3@;M]dMJĥ4@<M]d|'5@<N^㤫6@<N^27@<N^ W8@<O^8|9@<O^gy:@<O_$V;@=P_$3<@=P_d=@=P_d$4>@=Q`SY?@=Q`䤂~@@=Q`䱅A@=Q`bB@>R`@D@>Ra$?E@> Ra$n6F@> Sad[G@> Sad̴H@>!Sa I@?!Tb*o&J@?!TbYL,K@?!Tb)3L@?"Ub99M@?"Uc$]?N@?"Uc$EO@?#Vc$EKP@@#Vcdt{QQ@@#VcdXWR@@#Vd5^S@@$Wd;dT@@$Wd0_jU@@$Wd_̈́pV@A%Xd䎪vW@A%Xe$|X@A%Xe$dY@A%YedBZ@A&YedK=[@A&Yfdza\@A&Zf天ن]@B'Zfض^@B'ZfЧ_@B'Zf6q`@B'[g$fNa@B([g$+?b@B([g$dc@C(\gdd@C)\gd"íe@C)\hQf@C)]h夀}g@C)]h夯Zh@C*]h7Ai@D*^h fj@D*^i$=k@D+^i$lϯl@D+^idm@D+_idʉo@D+_jdf p@D,_j(DCq@E,`jW!hr@E,`js@E-`j۱"t@E-ak(u@E-ak$.v@E.ak$Cs 5w@F.akdrPE;x@F.bkd-jAy@F.bl Gz@F/blM{@F/cl.S|@F/cl]Y}@G0cl"`~@G0dm$\Gf@G0dm$9ll@G0dm$r@G1emdIx@G1emdx~@H1en椧@H2en֋$@H2fniI@H2fn4Fn@H2fnc#@H3go$@I3go$ܩ@I3god@I4hod &@I4hodOuK@I4hp~RpŽ@I4ip椭/ȏ@J5ip ΐ@J5ip ԑ@J5iq$;ے@J6jq$j(@J6jq$M@J6jqd^r@J6kqd;@K7kr&@K7krU@K7lr椄@K8lr䳰* @K8lrO@K8ls$kt@L9ms$AH@L9msdp%$@L9msd*@L9nsd1@L:nt,7@L:nt,Q=@M:ot[wvC@M;otTI@M;ot$1O@M;pu$U@M;pud \@Nz@N=rv2瀮@O=rv$b @O>rv$0@O>sw$U@O>swdz@O?swdm@O?swMJĥ@P?tw|'髵@P@tx礫@P@tx2@P@ux W@P@ux$9|Ĺ@PAux$hyʺ@QAvydVл@QAvyd3ּ@QBvydݽ@QBwy$4@QBwySY@QBwz䂨~@RCwz䱅@RCxzb@RCxz$@@RDxz$?@RDyzdn6@RDy{d[@SEy{̴@SEz{ @SEz{*o&@SEz{YL,@SFz|)3@TF{|$99@TF{|$]?@TG{|$E@TG||dEK@TG|}dt{Q@TG|}礣XW@UH}}5^@UH}};d@UH}}0_j@UI}~_̈́p@UI~~$v@UI~~$|@VJ~~dd@VJ~dB@VJdK=@VJza@VK礩ن@VKض@WKЧ@WL$7q@WL$fN@WL$+?@WLdd@XMd@XM"í@XMQ@XN礀}@XNZ@XN7A@YO$f@YO$=@YOdlϯ@YOd@YPdʉ@ZPf @ZP(DC@ZQW!h@ZQ@ZQ۱"@ZR$(@[R$.@[RdCs 5@[RdrPE;@[S礡-jA@[S G@\SM@\T.S@\T]Y@\T$"`@\U$\Gf@\U$9ll@]Udr@]UdIx@]Vx~@]V礧@]V֋$@^WiI@^W4Fn@^W$d#@^W$ @^Xdܩ @^Xd @_X & @_YOuK @_Y~Rp@_Y/@_Z @`Z$ @`Z$;@`Zdj(@`[dM@`[^r@`[;@a\&@a\U@a\@a]$* @a]$O@b]$kt@b]dAH@b^dp%$@b^礟* @b^1!@c_,7"@c_,Q=#@c_[wvC$@c`$TI%@c`$1O&@c`dU'@d`d \(@dadG.b)@davSh*@da礥xn+@db`t,@eb>z-@eb$3.@ec$b /@ec$00@ecdU1@fcdz2@fdm3@fdMJĥ4@fd|'5@fe6@ge27@ge$ W8@gf$9|9@gfdhy:@gfdV;@gfd3<@hg=@hg$4>@hgSY?@hh䂨~@@hh䱅A@ih$bB@ii$@D@iid?E@iidn6F@ij礝[G@jj̴H@jj I@jj*o&J@jkYL,K@jk$)3L@kk$99M@kl$]?N@kldEO@kldEKP@kmt{QQ@lm礣XWR@lm5^S@lm;dT@ln0_jU@ln$`̈́pV@mn$vW@mod|X@moddY@modBZ@mpK=[@mpza\@npن]@npض^@nq$Ч_@nq$7q`@nq$fNa@ord+?b@orddc@ord@os"íe@osQf@ps}g@ptZh@pt$7Ai@pt$fj@ptd=k@qudlϯl@qudm@quʉo@qvf p@qv(DCq@rvW!hr@rw$s@rw$۱"t@rwd(u@rwd.v@sxdCs 5w@sxrPE;x@sx椡-jAy@sy Gz@syM{@ty$/S|@tz$^Y}@tz$"`~@tzd\Gf@t{d9ll@u{r@u{Ix@u{x~@u|䧮@u|֋$@v|$iI@v}$5Fn@v}dd#@v}d@v~dܩ@w~@w~ &@w~OuK@w~RpŽ@x/ȏ@x$ ΐ@x$ ԑ@xd;ے@xdj(@y椙M@y^r@y;@y&@yU@z$@z$* @z$O@zdkt@zdAH@{p%$@{椟*@{1@{,7@{,Q=@|$\wvC@|$TI@|d1O@|dU@|d \@}G.b@}vSh@}䥃xn@}`t@}$>z@~$3瀮@~$b @~d0@~dU@z@m@MJĥ@|'髵@@$2@$ W@d9|Ĺ@dhyʺ@dVл@3ּ@ݽ@$4@SY@䂨~@$@¦$b@¦d@@¦d?@¦n6@ç䤝[@ç̴@ç @ħ*o&@ħ$ZL,@ħ$)3@Ĩ$99@Ũd]?@ŨdE@ŨEK@ƨt{Q@ƨXW@ƨ5^@Ʃ;d@ǩ$1_j@ǩ$`̈́p@ǩdv@ȩd|@ȩd@ȪB@ȪK=@ɪza@ɪن@ɪ$ٶ@ʪ$Ч@ʪd7q@ʫdfN@ʫ㤕+?@˫d@˫@˫"í@̫Q@̫$}@̬$Z@̬$7A@ͬdf@ͬd=@ͬlϯ@ͬ㤛@άʉ@έf @έ(DC@ϭ$X!h@ϭ$@ϭd۱"@ϭd(@Юd.@ЮCs 5@ЮrPE;@Ѯ-jA@Ѯ G@Ѯ$M@Ѯ$/S@ү$^Y@үd"`@үd\Gf@ӯ9ll@ӯr@ӯIx@ӯx~@԰䧮@԰$׋$@԰$iI@հd5Fn@հdd#@հd @հܩ @ֱ @ֱ & @ֱOuK @ֱ~Rp@ױ$/@ױ$ @ױd @زd;@زj(@زᤙM@ز^r@ٲ;@ٲ&@ٲ$V@ڳ$@ڳ$* @ڳdO@ڳdkt@۳AH@۳p%$@۳* @ܴ1!@ܴ,7"@ܴ$-Q=#@ܴ$\wvC$@ݴdTI%@ݴd1O&@ݴdU'@ݵ \(@޵G.b)@޵vSh*@޵䥃xn+@ߵ$`t,@ߵ$>z-@ߵ$3.@ߵdb /@d00@U1@z2@ߤm3@MJĥ4@|'5@$6@$27@d W8@d9|9@dhy:@ߤV;@ߤ3<@=@$4>@$TY?@$~@@dA@dbB@d@D@ ޤ?E@ ޤn6F@ [G@ ̴H@ $ I@ $+o&J@ $ZL,K@ d)3L@ d99M@ ޤ]?N@ ޤEO@ ޤEKP@ t{QQ@ XWR@ $5^S@ $;dT@ d1_jU@ d`̈́pV@ dvW@ ݤ|X@ ݤdY@ BZ@ K=[@ za\@ $ن]@ $ٶ^@ dЧ_@ d7q`@ ݤfNa@ ݤ+?b@ ݤdc@ d@ "íe@ $Rf@ $}g@ $Zh@ d7Ai@ dfj@ ܤ=k@ ܤlϯl@ 䛬m@ ʉo@ f p@ $)DCq@ $X!hr@ ds@ d۱"t@ d(u@ ۤ.v@ ۤCs 5w@ rPE;x@ -jAy@ $ Gz@ $M{@ $/S|@ d^Y}@ d"`~@ ۤ\Gf@ ۤ9ll@ ۤr@ Ix@ x~@ $@ $׋$@ diI@ d5Fn@ dd#@ ڤ@ ڤܩ@ @ &@ OuK@ $RpŽ@ $/ȏ@ d ΐ@d ԑ@٤;ے@٤j(@٤M@^r@;@$'@$V@$@d* @dO@٤kt@٤AH@p%$@*@1@$,7@$-Q=@d\wvC@dTI@ؤ1O@ؤU@ \@G.b@vSh@$xn@$`t@d>z@d3瀮@פb @פ0@פU@z@m@$NJĥ@$}'髵@$@d2@d W@֤9|Ĺ@֤hyʺ@Vл@3ּ@ݽ@$%4@$TY@d~@d@db@֤@@֤?@n6@[@$ʹ@$ @$+o&@dZL,@ d)3@ դ99@ դ]?@ դE@ EK@ t{Q@ $XW@ $5^@ d;d@ d1_j@ d`̈́p@ Ԥv@ Ԥ|@ d@ B@ K=@ ${a@ $ن@ dٶ@dЧ@Ӥ7q@ӤfN@Ӥ+?@d@@$#í@$R@$}@dZ@d7A@Ҥf@Ҥ=@lϯ@䛬@ʉ@$f @$)DC@dX!h@d@d۱"@Ѥ(@Ѥ.@Cs 5@rPE;@$-jA@$ G@$M@d/S@d^Y@Ѥ"`@Ф\Gf@66 @rH @$Z< @Вhm @TB @вE @2H @в# @RN @I @rnT @x @ϒL[ @% @ϲ?)8a @2חJ @ϲn]g @Ruo @ҝm @r5R @s @Βd/ @y @Β @2+{ @β @RZX @'  @R5: @ L @r_ @Pq @͒ @2^ @Ͳͨ @2;! @Eͤ @R' @t @ r . @ d @ ̒;)4 @ A< @!̲jN: @!2a @!ҙs@ @!R1 @"jF @"r`٪ @"GL @"˒ @#'%R @#˒ @#2VY @#˲p @$R+_ @$N> @$rPe @$K+c @%ruk @%{ @%ʒwq @%2 @&ʲATw @&2 @&p1}! @&R" @' " @'r7}# @'-# @'ɒfZ@ $ @(R$ @(ɲ7e% @(2-w% @(& @)R\& @)' @)r`' @)"%( @*Ȓ=( @*R+) @ *Ȳ ) @ *22* @ +Ȳ/* @ +RfB8+ @ +GT+ @ +rCg>, @ ,vy, @ ,r!D- @ ,- @ ,ǒ=J. @ -2l. @ -DzlP/ @ -RJ/ @ -қV0 @ .R3' 0 @! .ʕ]1 @!.rb21 @!.rDc2 @!/ƒV2 @!/)Pii3 @!/Ʋ{3 @!/2X-o4 @!04 @!0R u5 @"0y5 @"0r{6 @"1MV6 @"1Œ7 @"1}38 @"1Ų!8 @"124 9 @"2CF9 @"2RX: @#2r\k: @#2r }; @#39; @#3Ē9< @#3< @#3IJh#= @#42٦= @#4җb)> @$4R/> @$4?0? @$5r^#? @$566@ @$5ÒH@ @$5%Zۿr'S @(">ۿtS @)#>۾r .T @)#>ܾdT @)#?ܾ;)4U @)#?ܾ2A\ @+(BݼrPe] @+(CݼK+c] @+)Cݼuk^ @+)Cݼ{^ @+)Cݼwq_ @,*Dݻ2_ @,*DݻATw` @,*DݻR` @,+Dݻp1}a @,+Dݻrb @,+Eݻ b @,,Eݻ7}c @,,Eݻ-c @-,EݺfZ@ d @--F޺2Rd @--F޺7ee @--F޺R-we @--F޺f @-.G޺R\f @-.G޺g @-.G޺r`g @./G޹#%h @./G޹=h @./H޹2R+i @.0H޹ i @.0H޹22j @.0H޹/j @.1I޹RfB8k @/1I޸GTk @/1I޸rCg>l @/2I߸wyl @/2J߸!Dm @/2J߸2m @/2J߸=Jn @/3J߸2ln @/3J߸lPo @03K߷RJo @04K߷Vp @04K߷r3' p @04K߷˕]q @05L߷b2q @05L߷rDcr @05L߷Vr @16L߶2)Piis @16M߶{s @16M߶RX-ot @17M߶t @17Mr uu @17Myu @17Nඒ{v @28NNVv @28N൲w @28N2}3x @29O൲!x @2 9OR4 y @2 9OCFy @2 :OrXz @2 :Or\kz @3 :Pr }{ @3 ;P9{ @3 ;Pഒ9| @3 ;P2| @3 R᳒H @4 >R%Z< @4 >Sᳲhm @5?S2TB @5?SEł @5?SRH @5@S#˃ @5@TrN @5@TIф @5@TᲒnT @6ATy؅ @6AUᱲL[ @6AU2%ކ @6BUᱲ?)8a @6BURחJ @6BUn]g @6CVruo @7CVm @7CVⰒ5R @7DVs @7DWⰒd/ @7DW2y @7EWⰲ @7EWR+{ @8EW @8EXRZX @8FX' @8FXr5: @8FX!L @8GY⯒_ @8GY2Pq @9GY⮲ @9HY2^ @9HYͨ @9HZR;! @9IZEͤ @9IZr' @9IZt @:I[㭒 . @:J[d @:J[㭲;)4 @:J[2A< @:K[jN: @:K\Ra @;K\ҙs@ @;L\r1× @;L\jF @;L]㬒`٪ɘ @;M]GL @;M]㬒ϙ @;M]2'%R @<M]㫲՚ @<N^RVY @<N^pܛ @<N^r+_ @<O^N> @<O^rPe @<O_L+c @=P_㪒uk @=P_2{ @=P_㪲wq @=Q`R @=Q`ATw @=Q`r @=Q`p1} @>R`r @>Ra @> Ra䩒7} @> Sa2- @> Sa䩲fZ@ @>!SaRR @?!Tbҕ7e @?!TbR-w @?!Tb @?"Ubr\ @?"Uc @?"Uc䨒` @?#Vc#% @@#Vc䧲=樨 @@#Vc2R+ @@#Vd @@$WdR2 @@$Wd/ @@$WdrfB8 @A%XdGT @A%Xe䦒Cg> @A%Xewy @A%Ye䦲!D @A&Ye2ǭ @A&Yf妲=J @A&ZfRlͮ @B'ZflP @B'ZfrJӯ @B'ZfV @B'[g奒3' ڰ @B([g˕] @B([g奒b2 @C(\g2rDc @C)\g夲V @C)\hR)Pii @C)]h{ @C)]hRX-o @C*]h @D*^hr u @D*^iy @D+^i壒{ @D+^i2NV @D+_i売 @D+_j2}3 @D,_j! @E,`jR4 @E,`jCF @E-`jrX @E-akr\k @E-ak墒 } @E.ak9 @F.ak塲9 @F.bk2 @F.blh# @F/blR٦ @F/clҗb) @F/clr/ @G0cl?0 @G0dm栒^# @G0dm66 @G0dm栒H @G1em2%Z< @G1em栲hm @H1enRTB @H2enE @H2fnrH @H2fn# @H2fnrN @H3goJ @I3go枒nT @I3go2y @I4ho枲L[ @I4ho2% @I4hp?)8a @I4ipRחJ @J5ipn]g @J5ipruo @J5iqm @J6jq杒5R @J6jqs @J6jq杲d/ @J6kq2y @K7krғ @K7krR+{ @K7lr @K8lrrZX @K8lr' @K8ls朒5: @L9ms!L @L9ms曲_ @L9ms2Pq @L9ns曲 @L:ntR^ @L:ntͨ @M:otr;! @M;otEͤ @M;ot暒' @M;puu @M;pu皲 . @NrvjF @O>sw瘒`٪ @O>sw2GL @O?sw瘲 @O?swR'%R @P?twҾ @P@txRVY @P@txp @P@uxr+_ @P@uxN> @PAux痒Pe @QAvy2L+c @QAvy疲uk @QBvy2{ @QBwywq @QBwyR @QBwzATw @RCwzr @RCxzp1} @RCxz畒 @RDxz @RDyz畲7} @RDy{2- @SEy{fZ@ @SEz{RR @SEz{ҕ7e @SEz{r-w @SFz| @TF{|瓒\ @TF{| @TG{|瓒` @TG||2#% @TG|}瓲= @TG|}RR+ @UH}} @UH}}r2 @UH}}/ @UI}~rfB8 @UI~~HT @UI~~璒Cg> @VJ~~2wy @VJ~瑲!D @VJ2 @VJ=J @VKRl @VKlP @WKrJ @WLV @WL琒3' @WL˕] @WL琲b2 @XM2rDc @XMґV @XMR)Pii @XN{ @XNrX-o @XN @YO玒 u @YOy @YO玲{ @YO2NV @YP玲 @ZPR}3 @ZP! @ZQr4 @ZQCF @ZQrX @ZRs\k @[R猒 } @[R29 @[R猲9 @[SR @[Sh# @\SR٦ @\Tb) @\Tr/ @\T?0 @\U狒^# @\U66!@]U犲H!@]U2%Z<!@]VҼhm!@]VRTB!@]VE!@^WrH!@^W#!@^W牒N!@^WJ!@^X牲nT!@^X2y!@_XL[!@_YR%!@_Y?)8a!@_YrחJ!@_Zn]g!@`Z燒uo!@`Zm !@`Z燲5R !@`[2s !@`[d/ !@`[Ry !@a\ғ !@a\r+{ !@a\ !@a]熒ZX !@a]' !@b]煒5:!@b]2!L!@b^煲_!@b^RPq!@b^!@c_r^!@c_ͨ!@c_r;!!@c`Fͤ!@c`焒'!@c`2u!@d`烲 .!@da2d!@da;)4!@daRA<!@dbjN:!@ebra!@ebs@!@ec炒1!@ecjF!@ec炲`٪!@fc2GL!@fdҏ!@fdR'%R!@fdҾ!@ferVY!@gep!@ge瀒+_!@gfN>!@gf瀲Pe!@gf2L+c!@gf瀲uk!@hgR{!@hgwq!@hgr!@hhATw !@hhr !@ih~q1}!!@ii~"!@ii~2 "!@ii~7}#!@ij~R-#!@jj}fZ@ $!@jj}RR$!@jj}7e%!@jk}r-w%!@jk}&!@kk|\&!@kl|'!@kl|`'!@kl|2#%(!@km|Һ=(!@lm{RR+)!@lm{ )!@lm{r2*!@ln{/*!@ln{fB8+!@mnzHT+!@mozCg>,!@moz2wy,!@moz!D-!@mpzR-!@mpz=J.!@npyrl.!@npylP/!@nqyJ/!@nqyV0!@nqy3' 0!@orx2˕]1!@orxb21!@orxRrDc2!@osxґV2!@osxR)Pii3!@psw{3!@ptwrX-o4!@ptw4!@ptw u5!@ptw2y5!@quv{6!@quv2NV6!@quv7!@qvvR}38!@qvv!8!@rvur4 9!@rwuDF9!@rwuX:!@rwu2s\k:!@rwu };!@sxt29;!@sxt9!@tzs/>!@tzs?0?!@tzs^#?!@t{s266@!@u{rҍH@!@u{rR%Z\!@gPe]!@g2L+c]!@fuk^!@fR{^!@fwq_!@fr_!@fATw`!@e`!@¦eq1}a!@¦eb!@¦e2 b!@¦d7}c!@çdR-c!@çdfZ@ d!@çdrRd!@ħd7ee!@ħc-we!@ħcf!@Ĩc\f!@Ũc2g!@Ũc`g!@ŨbR#%h!@ƨbҺ=h!@ƨbrR+i!@ƨb i!@Ʃar2j!@ǩa/j!@ǩafB8k!@ǩa2HTk!@ȩaCg>l!@ȩ`Rwyl!@Ȫ`!Dm!@Ȫ`rm!@ɪ`=Jn!@ɪ`rln!@ɪ_mPo!@ʪ_Jo!@ʪ_2Vp!@ʫ_3' p!@ʫ^R˕]q!@˫^b2q!@˫^RrDcr!@˫^Vr!@̫^r)Piis!@̫]{s!@̬]X-ot!@̬]t!@ͬ] uu!@ͬ]2yu!@ͬ\Ҷ{v!@ͬ\RNVv!@ά\w!@έ\r}3x!@έ[!x!@ϭ[4 y!@ϭ[DFy!@ϭ[Xz!@ϭ[2s\kz!@ЮZ }{!@ЮZR9{!@ЮZ9|!@ѮZr|!@ѮYh#}!@ѮY٦}!@ѮYb)~!@үY/~!@үY2?0!@үX^#!@ӯXR66!@ӯXҍH!@ӯXR%Z!@KPe!@KRL+c!@Kuk!@Kr{!@Jwq!@J!@JBTw!@J!@J2q1}!@I!@IR !@I7}!@Ir-!@HfZ@ !@HR!@H7e!@H-w!@G2!@G\!@GR!@Gҋ`!@GR#%!@F=樨!@FrR+!@F !@F2!@E2/!@EfB8!@E2HT!@ECg>!@DRwy!@D!D!@Drǭ!@D=J!@Dlͮ!@CmP!@CJӯ!@C2V!@C3' ڰ!@BR˕]!@Bb2!@BrrDc!@BV!@A)Pii!@A{!@AX-o!@A2!@A u!@@Ry!@@Ҷ{!@@rNV!@@!@?r}3!@?!!@?4 !@?2DF!@>X!@>2s\k!@> }!@>R9!@=9!@=r!@=i#!@=٦!@=b)!@!@.ҴPe!@.rL+c!@-uk!@-r{!@-wq!@-!@,2BTw!@,!@,2q1}!@,!@+R !@+7}!@+r-!@+gZ@ !@*R!@*7e!@*-w!@ *2!@ )\!@ )R!@ )ҋ`!@ )r#%!@ (=!@ (R+!@ ( !@ (2!@ '2/!@ 'fB8!@ 'RHT!@ 'Cg>!@ &rwy!@ &!D!@ &r!@ &>J!@ %l!@ %2mP!@%J!@%RV!@$3' !@$R˕]!@$b2!@$rrDc!@#V!@#)Pii!@#{!@#X-o!@"2!@"҇ u!@"Ry!@"{!@!rNV!@!!@!}3!@!!!@ 4 !@ 2DF!@ X!@ Rs\k!@ }!@r9!@9!@!@i#!@٦!@2b)!@/!@R?0!@^#!@R66"@H"@r%Z<"@hm"@TB"@2E"@H"@2#"@ҲN"@RJ"@nT"@ry"@L["@%"@2@)8a"@חJ"@2o]g"@uo"@Rm "@5R "@rs "@e/ "@y "@ "@+{ "@2 "@ZX "@R' "@҉5:"@r!L"@_"@Pq"@"@^"@2ͨ"@;!"@RFͤ"@'"@ru"@  ."@ rd"@ <)4"@ A<"@!2kN:"@!a"@!Rs@"@!1"@"RjF"@"`٪"@"rGL"@""@#'%R"@#"@#VY"@#2p"@$҅+_"@$RN>"@$Pe"@$rL+c"@%uk"@%{"@% wq"@% "@& 2BTw "@& "@& Rq1}!"@& ""@' r ""@' 7}#"@' -#"@' gZ@ $"@( R$"@( 27e%"@( -w%"@( R&"@) \&"@) R'"@) `'"@) r#%("@* =("@*R+)"@ *2 )"@ *2*"@ +2/*"@ +ҰfB8+"@ +RHT+"@ +Cg>,"@ ,rwy,"@ ,!D-"@ ,-"@ ,>J."@ -l."@ -2mP/"@ -J/"@ -RV0"@ .3' 0"@ .r˕]1"@.b21"@.rDc2"@/V2"@/)Pii3"@/2{3"@/X-o4"@0R4"@0҇ u5"@0ry5"@0{6"@1rNV6"@17"@1}38"@12!8"@14 9"@2RDF9"@2X:"@2rs\k:"@2 };"@3r9;"@3:<"@3<"@32i#="@4٦="@4Rb)>"@4/>"@4R?0?"@5^#?"@5r66@"@5H@"@5%Zۿ'S"@">ۿruS"@#>۾ .T"@#>ܾdT"@#?ܾ<)4U"@#?ܾA\"@(BݼPe]"@(CݼrL+c]"@)Cݼuk^"@)Cݼ{^"@)Cݼ2wq_"@*Dݻ첪_"@*Dݻ2BTw`"@*Dݻ`"@+DݻRq1}a"@+Dݻb"@+Eݻr b"@,Eݻ8}c"@,Eݻ-c"@,EݺgZ@ d"@-F޺Rd"@-F޺27ee"@-F޺-we"@-F޺Rf"@.G޺\f"@.G޺rg"@.G޺`g"@/G޹#%h"@/G޹=h"@/H޹R+i"@0H޹2 i"@0H޹沁2j"@0H޹R/j"@1I޹ҰfB8k"@1I޸rHTk"@1I޸Cg>l"@2I߸yl"@2J߸rXDm"@2J߸RRDM"@ >Rڒ=`<"@ >S8r"@?SR49B"@?Sr2ȗł"@?S22WH"@@S3˃"@@T27uN"@@TR<ф"@@TRCT"@ATL"؅"@AUגV["@AUb@,ކ"@BUp>a"@BU^Q"@BU֒cg"@CV|v"@CVR m"@CVrҚ"@DV2)s"@DWղ"@DW2"Hy"@EWR@"@EWR`f"@EW "@EXӒ"@FX0 "@FXB"@FX2U"@GYҲEg"@GY2rPz"@GYrߌ"@HYrn"@HYR"@HZ5!"@IZrkפ"@IZВ'"@IZr:"@I[R."@J[RY!"@J[R34"@J[RwF"@K[RY:"@K\Vk"@K\r%~@"@L\㴐×"@L\,DF"@L]Ͳwӵɘ"@M]RbL"@M]̲ϙ"@M]bR"@M]֚"@N^Y"@N^R^/%ܛ"@N^˲7_"@O^NJ"@O^ʲi\e"@O_rlo"@P_$k"@P_2"@P_Rq"@Q`2K"@Q`Ұ9w"@Q`R"@Q`rX}"@R`Ȓ"@RaRYw"@ Ra)"@ Sa28;"@ Sar%N "@!SaR`"@!TbDs"@!TbƲ ԅ"@!Tbc"@"Ub󪜦"@"Uc|"@"UcrТ"@#Vc|%"@#Vc20"@#VcR,"@#VdP"@$Wdò,2"@$Wdo?"@$Wd2Q8"@%Xd21d"@%Xew>"@%Xe’P"@%Yerv瘩qF"@>sw瘩"@>sw瘩%L"@?sw瘨S""@?sw瘨RR"@?tw痨B"@@tx痧"Y"@@tx痧c5"@@ux痧RSG_"@@ux痧ҋZ"@Aux痦me"@Avy疦"@Avy疦?4k"@Bvy疥Ĥ"@Bwy疥Tq"@Bwy疥2"@Bwz疥Iuw"@Cwz畤ҏ"@Cxz畤rؕ~"@Cxz畤"&"@Dxz畣n&"@Dyz畣ҼF9"@Dy{畣 K"@Ey{產^g^ "@Ez{產Rp"@Ez{產r"@Ez{產2]"@Fz|甡򵨨"@F{|瓡R9"@F{|瓡rl"@G{|瓠rY"@G||瓠2*%"@G|}瓠ҋz"@G|}瓠2 ,"@H}}璟RT*"@H}}璟2+=2"@H}}璟#O"@I}~璞rLb8"@I~~璞t"@I~~璞hm>"@J~~瑝"@J~瑝RJD"@J瑝ҽ"@J瑝2J"@K瑜?"@K瑜"P"@K琜r` "@L琛W"@L琛җ."@L琛A]"@L琛S"@M珚3fc"@M珚Rx"@M珚r)Ti"@N珙R"@N珙 #@]熊7P #@]煊Jc#@]煊Ru#@^煉k#@^煉#@^煉ƍ#@_焈r#@_焈Ҟ#@_焈R@!#@`焇R#@`焇2b (#@`焇y#@`烇2s/.#@a烆nB#@a烆rkT4#@a烆Rj7g#@b烅jy:#@b炅RmY#@b炅rq@#@c炄Rw{#@c炄 F#@c炄#@c灄.L#@d灃#@d灃үPS#@d灃r #@e灂r3Y#@e瀂2F#@e瀂2X_#@f瀁&k#@f瀁.}e#@f瀁IH#@f瀁2g٢k#@gj#@gҦq#@gRɌ#@hw #@h #@h~;@~!#@i~~Re$"#@i~~b7"#@i~~I##@j~}\##@j}}o $#@j}}rP$#@j}}҄8%#@k}|ɦ%#@k}|Z&#@k||,˜&#@l|{Rh}'#@l|{'#@l|{&(#@m|z%1(#@m{zRh(,)#@m{zS;)#@m{zM2*#@n{y;v`*#@n{y҄s8+#@nzyИ+#@ozx*>,#@ozxm,#@ozxLD-#@pzw-#@pzwreoJ.#@pyw.#@pywQ/#@qyvm#/#@qyvrɴ,W0#@qyv&F?0#@rxu2Q]1#@rxuRhd1#@rxuJvc2#@sxt2#@sxt2i3#@swtR}3#@twsR?o4#@twsS4#@twsbu5#@tws05#@uvr |6#@uvr6#@uvr҈07#@vvqR9C8#@vvqwU8#@vuq\h 9#@wupmz9#@wup2:#@wupj:#@wup뢲;#@xton4Ś;#@xto<#@xto2zW<#@ytn#=#@ytnҌz=#@ysn "*>#@zsmR4>#@zsm5/G0?#@zsm2Y?#@{slRZRl6@#@{rl~@#@{rlul#@ȩ`R l#@Ȫ`Q>xDm#@Ȫ`Qp m#@ɪ`QJn#@ɪ`Q.n#@ɪ_PQo#@ʪ_PrJS+o#@ʪ_PR=Wp#@ʫ_ORwPp#@ʫ^O c]q#@˫^O2Auq#@˫^Nr.cr#@˫^NRr#@̫^N Sis#@̫]MTs#@̬]Mҝwot#@̬]M t#@ͬ]M5uu#@ͬ]L. u#@ͬ\L|v#@ͬ\LR'S/v#@ά\KR{Aw#@έ\K2wTx#@έ[K( gx#@ϭ[J2y y#@ϭ[Jr.y#@ϭ[JR:z#@ϭ[ISz#@ЮZI{#@ЮZI[x֚{#@ЮZI2 |#@ѮZH%|#@ѮYHҍ/$}#@ѮYH2 }#@ѮYGrbT3*~#@үYGE~#@үYGR>yX0#@үXF k#@ӯXFR!}6#@ӯXF0#@ӯXE â<#@ӯWERU#@԰WEB#@԰WE2xzł#@԰WDr H#@հWDRt˃#@հVD1O#@հVCw$҄#@հVCV7U#@ֱVCI؅#@ֱUB |\[#@ֱUBRoކ#@ֱUBa#@ױUA3#@ױUA:Ʀg#@ױTAX#@زT@R^m#@زT@}#@زT@҈s#@زS@ #@ٲS?r5z#@ٲS?V(#@ٲS?RZ;#@ڳS>RM#@ڳR>23`#@ڳR>s #@ڳR=Rz#@۳R= 8#@۳Q=ʪ#@۳Q#@D+}#@D+2D#@D*ۣǭ#@D*6K#@D*ή#@C)]*Q#@C)3<ԯ#@C)MOW#@C(ibڰ#@B(t]#@B(R<#@B(ϙc#@B'b#@A'2i#@A'7#@A&`o#@A&#@A&RB v#@@%R#@@%2i.|#@@%F@#@@$zS#@?$R"f#@?$2x#@?#I #@?#rYܝ#@>#o#@>#Ô#@>"#@>"rU)蚻#@="Ҙ#@=!O #@=!%$#@=!mv2#@= r E*#@< W#@< S0j0#@<|#@<V6#@;2H꡹#@;}<#@;ǿ#@;MB#@:R7#@:H#@:b^#@:#O#@9$6#@9rIU#@9[#@9T?n[#@8Ҁ#@8(fa#@8R#@8g#@8s #@7m#@72YG#@7t#@7En#@6(z#@69:#@6r(M#@64_#@5Or#@57 #@5Һv#@5r@ #@4ǝ#@4P1#@4#@4rhX#@3#@32"#@3R,#@32>(#@2B:Q#@22c.#@2rsav#@2r4#@12#@1I:#@12#@1RC@#@120#@0jF#@0r} #@0&M#@0%0#@/~BS#@/2-MU#@/gY#@/tz#@.C_#@.#@. r/e#@. j#@- %Wk#@- #@- r~q#@- b#@, R$!x#@, R94#@, RF~#@, uaY#@+ r?k#@+ ~#@+ #@+ r #@* vD#@* rI#@*lۖ#@ *#@ )R˓#@ )Ҥ' #@ )2%#@ )2]O8&#@ (2#@ &s#@ &rbD#@ &2S#@ &E>K#@ %2:)#@ %20fa$@,$@rg$@'U$@ym $@} $@ t $@rw' $@::z $@*L $@c_ $@q $@2C $@r $@$@rlI$@2Β$@;r$@$@$@/$@R+"$@`X>$@P($@Hc$@ 쒿v.$@ 28$@ r>4$@ .ӭ$@!rg:$@!2,ҽ$@!겭@$@!0%$@" G$@",$@ ,ݲ8,$@ ,E-$@ ,-$@ ,)K.$@ -ے|G<.$@ -RNQ/$@ -R)qa/$@ -2tW0$@ .ݚ0$@ .ڲ/]1$@.ī1$@.2xYc2$@/Z2$@/=i3$@/r#3$@/ p4$@0A4$@0-v5$@0Rk@5$@0ҹS|6$@1e6$@1*x7$@1򏿊8$@1ՒT8$@1| 9$@2v~Ž9$@2q:$@2m:$@2Rl=;$@3Ӳl ;$@3ng<$@3Ӳr1<$@3RxD$=$@4&W=$@4i*>$@4P|>$@40?$@5ђz?$@56@$@52Ҥƹ@$@59"R$@"=ۿR QR$@">ۿc(S$@">ۿ[5vS$@#>۾2ʈ.T$@#>ܾ `T$@#?ܾIJb4U$@#?ܾU$@$?ܾr :V$@$?ܾRzV$@$@ܾJ@W$@%@ܽ= W$@%@ܽuGX$@%@ܽR 0X$@&Aܽ2pBMY$@&Aܽ5UY$@&AܽEgSZ$@'AܽҲ`zZ$@'Aܽ!Y[$@'BܼҒ[$@(Bݼr!_\$@(Bݼy\$@(BݼKe]$@(Cݼ2h]$@)Cݼvk^$@)Cݼ쾒] ^$@)Cݼڡ!r_$@*DݻZ74_$@*DݻFx`$@*Dݻ]bY`$@+Dݻrk~a$@+Dݻ뼲h~b$@+Eݻ"b$@,Eݻ껲zc$@,EݻRNc$@,Eݺғ d$@-F޺#yېd$@-F޺2e$@-F޺Fe$@-F޺r9f$@.G޺q%f$@.G޺ e8 g$@.G޺2Jg$@/G޹?]&h$@/G޹r%ph$@/H޹縲|,i$@0H޹Qi$@0H޹2j$@0H޹re|j$@1I޹ 8k$@1I޸2߻k$@1I޸2^=>l$@2I߸ l$@2J߸嵲hEm$@2J߸g)m$@2J߸R y$@9OޮsՎy$@:Oޭz$@:Oݭ͞z$@:PݭҪ4 {$@;Pݬ{$@;Pݬk`2|$@;PܬROD|$@RکRٹ$@>Rک;<$@>Sک$@?S٨gC$@?S٨R#Ƃ$@?S٨{6I$@@Sاw)Ĩ$@@Tاu[O$@@TاuUn҄$@@TاrwU$@ATצz؅$@AUצ[$@AUצ򆭸ކ$@BU֥Ca$@BU֥2$@BU֥rog$@CV֤$@CVդrěn$@CVդ1($@DVգ:t$@DWգ]M$@DWԣ_z$@EWԢ.r$@EWԢRI $@EWӢe$@EXӢ҃L$@FXӡ $@FXӡxό$@FXҡ2$@GYҠ$@GYҠ5;$@GYѠ^$@HYџ2g,$@HYџ>$@HZџQ"$@IZО*d$@IZОEv($@IZОryV$@I[Ϟ.$@J[ϝ悮$@J[ϝ4$@J[ϝYӷ$@K[ΜRE:$@K\Μ$@K\Μr A$@L\͛Vė$@L\͛r0G$@L]͛4Cʘ$@M]͚2'UM$@M]̚2pahЙ$@M]̚2zS$@M]֚̚$@N^̙2V$Y$@N^˙rܛ$@N^˙RP_$@O^˘2L$@O^ʘ}e$@O_ʘ2$@P_ʗ2Rl$@P_ʗ2@"$@P_ɗ 4r$@Q`ɖrhmG$@Q`ɖZx$@Q`Ȗ*l$@Q`Ȗ0~$@R`ȕRƑ$@Raȕ[]$@RaǕ$@Saǔ0Ɋ$@SaǔҜ $@SaƔR $@TbƓ{M$@TbƓ$@TbƓaz&$@UbŒ9$@UcŒNK $@UcŒR=^$@VcđrCp&$@VcđRj$@Vcđ>,$@Vdđr$@WdÐA.2$@WdÐ͵$@WdÐK[8$@Xd$@Xe\?$@Xe¬$@YeŽt*E$@YeRL=ȭ$@YfғOK$@Zf2&ybή$@Zf2uQ$@Zf2Pԯ$@Zf$@_i壼y$@_j壼R$@_j壻UÈ$@`j墻 > $@`j墻r莹$@`j墺}k$@ak墺r8$@ak墺 $@ak墹/3$@ak塹ruE$@bk塹8]X$@bl塹Rj$$@bl塸rŠ}$@cl塸R!*$@cl桸T$@cl样O0$@dm样dz$@dm样|6$@dm样$@em栶r_<$@em栶3A$@en柶 $C$@en柵n7$@fn柵JI$@fn柵R\$@fn柵t3oO$@go柴Sʁ$@go枴4aU$@go枴r$@ho枳[$@ho枳2%$@hp枳Rʼa$@ip枳~2S$@ip杲~h$@ip杲~R$@iq杲~r|)n$@jq東}m;$@jq東}R`FNt$@jq東}T`$@kq東|2Ktsz$@kr朰|RC $@kr朰|R=$@lr朰{99$@lr术{6н$@lr术{5g $@ls术{7$@ms曮z9$@ms曮zr>,$@ms曮zD$@ns曮y2MZ-$@nt曭y2W?$@nt曭ybR$@ot暭xpe"$@ot暬xw$@ot暬x2M($@pu暬w䜫$@pu皬wҸ{.$@pu癫wr±$@pu癫w4$@qu癫vA$@qv癪v:$@qv癪vr;o $@rv癪uZA$@rv瘪u|1$@rv瘩u4DG$@sw瘩tV$@sw瘩tbiM$@sw瘨t{$@sw瘨t=S$@tw痨si($@tx痧sҖY$@tx痧sRV$@ux痧r_$@ux痧r*$@ux痦r_e$@vy疦qR$@vy疦qJ#l$@vy疥q 5$@wy疥p2EyHr$@wy疥p[$@wz疥p§mx$@wz畤p?$@xz畤o2G֒~$@xz畤o2m$@xz畣o$@yz畣n$@y{畣ne3݊$@y{產nұ $@z{產ma$@z{產mO$@z{產m'$@z|甡mR':$@{|瓡lRIL$@{|瓡l2V_ $@{|瓠lq$@||瓠kRS&$@|}瓠kr$@|}瓠kr ,$@}}璟j2mK$@}}璟j2$@}}璟j22z$@}~璞j28$@~~璞i2$@~~璞if@?$@~~瑝iR+$@~瑝h=o>E$@瑝hQ$@瑝hcK$@瑜g25v$@瑜g͈Q$@琜gud$@琛fW$@琛fe$@琛f2*]$@琛f\$@珚eYc$@珚eZ $@珚er܈j$@珙d_ 0$@珙dRBp$@珙dRlOU$@玘cRgv$@玘c~z$@玘cR |$@玘c$@玗b*E$@獗br$@獗bOt׈$@獖aR $@獖a|$@獖ar;$@獕`2!$@猕`Lj4$@猕`G$@猕`Y$@猔_,1l$@猔_~$$@狔_v`$@狓^r*$@狓^RƏ$@狓^2q'0$@狒]۳$@狒]2V6%@犒]r|%@犒]R.=%@犑\2&%@犑\8C%@犑\NMK%@牐[]I%@牐[|p%@牐[O%@牐Z>%@牏ZrCU%@牏Zrۺ%@爏ZRs[%@爎YI %@舎Y2a%@爎Yr:%@爍Xrh%@燍X2rj*%@燍X@=n %@燍W2O %@燌W21bt %@燌Wt %@燌WҌaz %@熋VRd %@熋V= %@熋V) %@熊Urц %@熊UX %@煊Ur%@煊UҖ %@煉Tz %@煉T`.%@煉THPA%@焈SR1S%@焈Sf%@焈Sr y"%@焇R2%@焇RG(%@焇R߰%@烇Rw.%@烆Qֱ%@烆Q4%@烆Q?%@烅P2 ;%@炅P2o %@炅P3A%@炄OE%@炄Oү7XG%@炄Oj%@灄Og}M%@灃N%@灃N2˗S%@灃Nr/%@灂MY%@瀂Mr_%@瀂M2_%@瀁L%@瀁L)(f%@瀁L?$%@瀁LWX7l%@K2qI%@K\r%@K o%@Jȸx %@JRP %@~J ~!%@~~J20"%@~~IRV̄"%@~~I2~#%@~}IҧI#%@}}HR$%@}}Hz$%@}}H/)%%@}|GR`;%%@}|GBN&%@||GR`&%@|{Grrs '%@|{F5 '%@|{F2o&(%@|zFҪ;(%@{zEӽ,)%@{zE2'lЯ)%@{zEh2*%@{yE*%@{yDR49+%@zyDr5+%@zxDr}e-?,%@zxCR?,%@zxCRE-%@zwCr`.e-%@zwBwK.%@ywB_.%@ywBRSQ/%@yvBҧ/%@yvA2'W0%@yvARV0%@xuARX]1%@xu@ 1%@xu@Ri d2%@xt@!2%@xt@)1j3%@wt?RD3%@ws?2Vp4%@ws?Wi4%@ws>ҿ|v5%@ws>)5%@vr>L|6%@vr=6%@vr=rr}Ƃ7%@vq=8%@vq=V8%@uq<2F 9%@up%@sm9Dʭ>%@sm9l0?%@sm9[?%@sl87@%@rl82x6@%@rl8 '=A%@rl7g:A%@rk7r1MCB%@rk7Ș_B%@qk6`1rIC%@qj6ɄC%@qj6bOD%@qj64D%@qi52ԓUE%@pi5u,E%@pi5[F%@pi4]F%@ph4rdbG%@oh4 G%@oh42',hH%@og3Rc>H%@og32YQnI%@og3cI%@nf22rvtJ%@nf2%#J%@nf2ڻzK%@ne2rTK%@ne1IL%@me1RM%@me1M%@md0r~ N%@md0R>P N%@md0O%@lc02Á0O%@lc/2CP%@lc/OUP%@lb/LhQ%@lb.2zQ%@kb.}"R%@ka.|R%@ka.RL(S%@ka-HūS%@ka-R.T%@j`-yT%@j`,r4U%@j`,RvU%@j_,PD";V%@j_+-4V%@i_+R vGAW%@i^+ZW%@i^+̧lGX%@i^*R@X%@h^*ّMY%@h]*|rY%@h])re SZ%@h])2PZ%@h\)r<=Y[%@g\)*[%@g\(o`\%@g[(r \%@g[(&f]%@g['R99]%@fZ'Kl^%@fZ'rk^^%@fZ'qr_%@fZ&ܝ_%@fY&6x`%@eY&Ϩ`%@¦eY%h~a%@¦eX%rb%@¦eX%b%@¦dX%3c%@çdW$c%@çdW$fd%@çdW$r *d%@ħdV#=e%@ħcV#+1Pe%@ħcV#=bf%@ĨcV#Qcuf%@ŨcU"g g%@ŨcU"R~g%@ŨbU"r.&h%@ƨbT!Rǿh%@ƨbT!`,i%@ƨbT!ri%@ƩaS! 2j%@ǩaS /, j%@ǩaS rS9k%@ǩaR y^/k%@ȩaRrA?l%@ȩ`RɐTl%@Ȫ`Q)gEm%@Ȫ`Q2!ym%@ɪ`QO\Kn%@ɪ`Qn%@ɪ_P2Qo%@ʪ_P'o%@ʪ_PWp%@ʫ_O2SZp%@ʫ^OR]q%@˫^Ornjq%@˫^N2&!dr%@˫^NB3r%@̫^N2XFjs%@̫]MRXs%@̬]MR kpt%@̬]MO$~t%@ͬ]Mvu%@ͬ]LVu%@ͬ\L+|v%@ͬ\Lwv%@ά\K"ۂw%@έ\Kx%@έ[K2iUx%@ϭ[JR y%@ϭ[J%y%@ϭ[Jj!8z%@ϭ[I2ĺJz%@ЮZIRT]{%@ЮZIR|o{%@ЮZIۆ|%@ѮZH; |%@ѮYH򝹧$}%@ѮYHS}%@ѮYGg*~%@үYGυ߭~%@үYG290%@үXFR%@ӯXFRR7%@ӯXFR)%@ӯXE<=%@ӯWERcO%@԰WEr׷aC%@԰WEMQtƂ%@԰WD2I%@հWD>̃%@հVD2O%@հVC27҄%@հVC2PU%@ֱVC6؅%@ֱUBR[%@ֱUB= ߆%@ֱUBöb%@ױUAKP.%@ױUA2@h%@ױTA`S%@زT@fn%@زT@|x%@زT@ Pt%@زS@%@ٲS?4z%@ٲS?%@ٲS?bՀ%@ڳS> RO%@ڳR> %@ڳR> 5 %@ڳR=  %@۳R= u2%@۳Q= PE%@۳Q< W%@ܴQ< Rbj%@ܴQ< R }%@ܴQ< 2%@ܴP; _P"%@ݴP; 괥%@ݴP; 2(%@ݴP: mګ%@ݵO: .%@޵O: RP%@޵O9 5%@޵O9 B$%@ߵO97;%@ߵN8RI%@ߵN8uQ\A%@ߵN85nė%@N7G%@M7Ҹʘ%@M7r}M%@M7CRЙ%@M6 S%@M6Յ֚%@L6Y%@L52oݛ%@L5r>S`%@L5(%@K4r;f%@K42 N%@K4`l%@K3eTs%@J3?r%@J3%@J2R!x%@J2ػ%@J2U~%@I2Ҝ%@I1%@I12h#%@I1P%@H0:W-%@H0r&?%@H0RR%@H/%e%@G/w%@G/X%@G. %@G.rӌ%@G.&&%@F-ԩ%@F-Z,%@F-ҿ%@F-R 3%@E,(%@E,19%@E,\D%@E+rV?%@D+אi¬%@D+2*|E%@D*RĎȭ%@D*^K%@D* ή%@C)2Q%@C)r0-ԯ%@C)REW%@C(\aڰ%@B(t^%@B(#%@B(2/6d%@B'H%@A'c[j%@A'R m%@A&-p%@A&R2%@A&y̥v%@@%2f%@@%|%@@%%@@$&5%@?$V%@?$Ri%@?#( %@?#:%@>#'8M%@>#R`_%@>"lr%@>"2%@="R%@=!2U;%@=!Җռ$%@=!Roϧ%@= r *%@< f%@< R>1%@<%@<RFs,7%@;r ?%@;rQ=%@;6Bd%@;vC%@:v%@:6I%@:򎫮%@:EO%@92F%@9RzU%@9R%@92f \%@8I%@82/0b%@8R~C%@8RVh%@8jh%@7M{n%@7D%@7t%@7&%@6쒚z%@6R%@6R%@6R%@5R{!%@5" %@5RvV5%@5rG%@4RxZ%@42%m%@4鲁%@4 [%@32%@32"%@3ҩ*ʥ%@3R8(%@2_%@2Z/%@2%@2/'5%@19%@1粴dL;%@1O^%@1qA%@14%@0r+ϖG%@0i%@0qM%@02%@/䲾9S%@/g%@/oZ%@/ %@.n+`%@.?>%@. 2Pf%@. 2tc%@- ;vl%@- %@- Dr%@- g߭%@, #zx%@, %@, 2~%@, eJ%@+ ) %@+ %@+ 20%@+ ߒB%@* KPU%@* g%@*߲z%@ *2 %@ )ޒ%@ )^V %@ )޲4ģ%@ )r &%@ (&%@ (R,%@ (R\%@ (2}!3%@ ']4%@ 'R@-G9%@ '۲$Y%@ '۲ cl?%@ &r~%@ &ܘE%@ &r3%@ &ڲζK%@ %ڒi%@ %rQ%@%%@%2{:X%@$Rq%@$2ip&^%@$b 9%@$R^Kd%@#ؒ[A^%@#زZpj%@#r[w%@#2^p%@"rb%@"ײhHv%@"ֲp%@"Rz~|%@!%@!R%@!rO%@!R*%@ Ņ= %@ Ւ P%@ Բb%@ Wu%@Բ"%@R>%@Ӳ[(%@zÿ%@^$%@Ҳ%@R*%@Ғ 0 %@Ҳ11%@Ѳ[f/%@RB7&@T&@7g=&@Ry&@HnC&@в| &@2I&@R?&@r%O&@av&@ҞU&@ެ&@RH!\&@2b3&@Ҧ~Fb&@rY&@Ͳ5kh&@P~&@Ͳn &@R &@h"t &@ &@ Yz &@a &@r &@˲+ &@j% &@a8 &@ʒ$J&@2]&@r3p&@ɒHς&@rj&@&@ɒ|&@Ȳ<"&@Rߥ&@Ȓs(&@0&@ ǒ/&@ DzF*&@ Dz<5&@ r}O&@!yb;&@!Rt&@!RoOA&@!R&@"lG&@"r!&@"ŲqM&@"ŲX&@#Ē}S&@#2 &@#Ē+Z&@#.&@$ҪbA`&@$Ò:S&@$̙ff&@$r_5y&@%rЋl&@%rl&@% $r&@% ’&@& Z?x &@& &@& Ҙv~!&@& R:"&@' ݭ "&@' I3#&@' )E#&@' ҀX$&@( R}k$&@( ῲ)}%&@( S%&@( ῒ&&@) r9&&@) & '&@) 2ڣ'&@) ߾2Y^&(&@* ߽2(&@*߽̕-)&@*޽1%)&@*޽RG73*&@+޼RiJ*&@+޼2]9+&@+ݼo+&@+ݼR&@4ҳ( >&@4ѳR21?&@5Ѳ`E?&@5ѲW7@&@5вrj@&@5в4}=A&@6бrяA&@6ϱmCB&@6ϱ& B&@6ϱrۿũT)S&@>ۿũ+S&@>۾ĩ-/T&@>ܾĩ2Gd@T&@?ܾĨrS5U&@?ܾĨeU&@?ܾèrI9x;V&@?ܾèՊV&@@ܾçqAW&@@ܽ§[W&@@ܽ§ҺGX&@@ܽ§GX&@Aܽ~MY&@AܽY&@AܽH TZ&@AܽZ&@AܽRU2Z[&@BܼD[&@Bݼ2W`\&@Bݼ2b*j\&@Bݼ|f]&@CݼEc]&@CݼRl^&@Cݼ쾤r0^&@Cݼ쾤r8r_&@Dݻ콣R"_&@Dݻ콣ҝqx`&@Dݻ뽣R`&@Dݻ뼣ra&@Dݻ뼣rG$b&@Eݻ꼢6b&@Eݻ껢"Ic&@Eݻ껢\c&@Eݺ껢1nd&@F޺麡Ud&@F޺麡Fe&@F޺麡Ԏe&@F޺躡Rc+f&@G޺蹠R˝f&@G޺蹠2d g&@G޺蹠g&@G޹縠R'h&@G޹縠rJ:h&@H޹縟R(-i&@H޹緟s;i&@H޹淟N3j&@H޹淟`j&@I޹涞^Is9k&@I޸嶞慼k&@I޸嶞?l&@I߸嵞2Ll&@J߸嵝rEm&@J߸䵝rXm&@J߸䵝RJKn&@J߸䴝n&@J߸䴝r.Ro&@K߷㴜Xo&@K߷㳜 h-Xp&@K߷㳜R@p&@K߷ⳜvR^q&@L߷ⲛ2/>eq&@L߷ⲛRwdr&@L߷ⲛRwr&@L߶ᱛbjs&@M߶ᱚR"s&@M߶ᱚMpt&@M߶ᰚt&@Mచkvu&@Mచ22$u&@Nఙ }v&@N߯]w&@N߯Ґ1w&@N߯^Dx&@O߮2.4Wx&@Oޮi y&@Oޮm|y&@Oޭ z&@OݭR~z&@PݭVD{&@Pݬ21ƛ{&@Pݬ2 ~|&@Pܬ2|&@Qܫʷ$}&@QܫT}&@Qܫr#+~&@Q۫Rt6~&@Q۪2[+I1&@R۪C[&@Rڪ.en7&@RکR&@Rک2=&@Sک;&@S٨rظC&@S٨uƂ&@S٨I&@Sاȯ̃&@TاrLP&@Tاһӄ&@Tا(V&@Tצ#;م&@UצҵM\&@Uצr]`߆&@U֥Һrb&@U֥&@U֥4h&@V֤Ѫ&@Vդ2nn&@Vդ &@Vգt&@WգF&@WԣR{&@WԢ)&@WԢ>-&@WӢU?&@XӢnWR&@Xӡrd &@Xӡҥw&@Xҡ.&@YҠ˜&@YҠi&@YѠ2)™&@YџN&@Yџu@矑&@Zџ"&@ZО2z &@ZО)&@ZО#1&@[ϞTRD/&@[ϝ҅V&@[ϝi5&@[ϝ)|&@[Μ&ǎ;&@\Μ_d&@\ΜҙA&@\͛r֞ė&@\͛w&@p枳w2W܉b&@p枳~w;z&@p杲~w!h&@p杲~w &@q杲~vSn&@q東}v&@q東}v̏t&@q東}v2- &@q東|v{&@r朰|uҟi1&@r朰|uD&@r朰{uҊV&@r术{uCi&@r术{u|{ &@s术{tx&@s曮zt2v&@s曮ztru&@s曮ztvY&@s曮ytryؙ&@t曭ys~&@t曭ys3&@t暭xsҌ#&@t暬xsҖo#&@t暬xs 6)&@u暬wr2H&@u皬wrI[/&@u癫wrm&@u癫wrㅀ5&@u癫vrr#&@v癪vq¥;&@v癪vqR'`&@v癪uqRAA&@v瘪uq2]&@v瘩uqz:G&@w瘩tpR&@w瘩tpvN&@w瘨tp(&@w瘨tpR:T&@w痨sp*QM&@x痧soRR_Z&@x痧so|r&@x痧ro+`&@x痧roRɗ&@x痦rohf&@y疦qn7&@y疦qnRjl&@y疥qn2B&@y疥pnr&@y疥pnR&@z疥pmHy&@z畤pm,&@z畤omrY?&@z畤omQ&@z畣omrCd&@z畣nm4w&@{畣nl҉&@{產nlRq&@{產mlZ&@{產ml2&@{產mlrKԗ&@|甡mkR?&@|瓡lk&@|瓡lkr& !&@|瓠lk3&@|瓠kk҈c1'&@}瓠kjD&@}瓠kjR8V-&@}璟jj>i&@}璟jj{3&@}璟jjL{&@~璞ji9&@~璞ii2&@~璞iiqV?&@~瑝ii&@~瑝hi=E&@瑝hh21&@瑝hhL&@瑜gh}n#&@瑜gh2 6R&@琜ghZH&@琛fgI[X&@琛fg@m&@琛fg2^&@琛fgR,%&@珚egåd&@珚egb&@珚efj&@珙df&@珙df=p&@珙df&@玘cfRzw&@玘ce$(&@玘ce:}&@玘ce4VM&@玗be2_&@獗beKr&@獗bd1&@獖adiЗ &@獖adn&@獖ad2 &@獕`d$ϕ&@猕`cһJ&@猕`cT&@猕`cr&@猔_c&&@猔_cR*,%&@狔_cRc?&@狓^bRlR+&@狓^bd&@狓^bR?w1&@狒]b\މ&@狒]b}7'@犒]ar'@犒]a]='@犑\ar Y'@犑\aC'@犑\am'@牐[`R!5 J'@牐[`'@牐[`2r1P'@牐Z`RGD'@牏Z`2VV'@牏Z`ҾNi'@爏Z_r}{\'@爎Y_='@舎Y_*b'@爎Y_rɳ'@爍X_hh'@燍X^P'@燍X^n '@燍W^D '@燌W^ru '@燌W^# '@燌W^RP!6{ '@熋V]R"H '@熋V]R^[ '@熋V]m '@熊U]r '@熊U]|; '@煊U\Wڥ'@煊U\4y'@煉T\2˓'@煉T\'@煉T\U'@焈S\ҹ'@焈S['@焈S[22(#'@焇R[p:'@焇R[[pM)'@焇R[H`'@烇RZR7r/'@烆QZ'M'@烆QZ5'@烆QZ'@烅PZ*;'@炅PZϾ'@炅PYgA'@炄OYR'@炄OY2H'@炄OYD'@灄OY,N'@灃NX?'@灃NX!RT'@灃NXd'@灂MX`wZ'@瀂MX2 '@瀂MX`'@瀁LW"='@瀁LWr1f'@瀁LW2B{'@瀁LWTl'@KWh'@KV~X s'@KV'@JV21y '@JV5D '@~JVV!'@~~JVti"'@~~IUr(|"'@~~IUJ#'@~}IU2oQ#'@}}HUR$'@}}HU2Ƒ$'@}}HU.%'@}|GTR%'@}|GTr?m&'@||GTn &'@|{GTR#!''@|{FTJ6''@|{FTRH'('@|zFS<[('@{zESrt(n-)'@{zES2ǀ)'@{zESf3*'@{yES'*'@{yDR2f9+'@zyDRD˼+'@zxDR?,'@zxCR2.,'@zxCRrt"F-'@zwCR-'@zwBQRa(L.'@ywBQQ;.'@ywBQRMR/'@yvBQr>`/'@yvAQr?rX0'@yvAQ2}0'@xuAP^1'@xu@P=1'@xu@P2[d2'@xt@P2'@xt@PJj3'@wt?PR93'@ws?Oq4'@ws?Ohx4'@ws>Or-w5'@ws>O/?5'@vr>OrVR}6'@vr=Od7'@vr=Nhw7'@vq=Nr48'@vq=NBԜ8'@uq'@sm9LM|>'@sm9Lt1?'@sm9Lr?'@sl8K,7@'@rl8K ƺ@'@rl8Kҙk=A'@rl7Kr' A'@rk7KCB'@rk7KRHJB'@qk6Jr#JC'@qj6J2p6C'@qj6J)IPD'@qj6JR[D'@qi5J9hnVE'@pi5JE'@pi5JRs\F'@pi4IGF'@ph4IRbG'@oh4IrWG'@oh4Ir%hH'@og3IH'@og3IKeoI'@og3HI'@nf2H(uJ'@nf2HOD;J'@nf2HM{K'@ne2H`K'@ne1H2d#sL'@me1G2ÅM'@me1GbM'@md0G N'@md0GCN'@md0G2AO'@lc0G2O'@lc/F|P'@lc/Fr>!P'@lb/FQ'@lb.F`-Q'@kb.Fҍ@#R'@ka.FrVRR'@ka.E @e)S'@ka-E2wS'@ka-E2/T'@j`-ET'@j`,E\5U'@j`,E0_¸U'@j_,D2;V'@j_+DܞV'@i_+D>AW'@i^+Dr W'@i^+Dk~HX'@i^*DI2X'@h^*D)DNY'@h]*Cr ^WY'@h])CiTZ'@h])C2ԝ|Z'@h\)C2=Z['@g\)C2ݡ['@g\(C}`\'@g[(B{\'@g[(BRif]'@g['BRY]]'@fZ'BKl^'@fZ'B>^'@fZ'B3=$s_'@fZ&A+6_'@fY&A#}Iy`'@eY&A\`'@eY%A2na'@eX%Ar]b'@eX%Ab'@dX%ARc'@dW$@=c'@dW$@R$d'@dW$@+}ޑd'@dV#@4e'@cV#@R?e'@cV#@K]f'@cV#?RZ(f'@cU"?rj;!g'@cU"?R|=Ng'@bU"?2`'h'@bT!?}sh'@bT!?Ҽ-i'@bT!?սi'@aS!>]3j'@aS >r j'@aS >+9k'@aR >2L>k'@aR>n?l'@`R>~l'@`Q=Fm'@`Q=޾-m'@`Q=_@Ln'@`Q=2Rn'@_P=_eRo'@_P=2?xo'@_P=ߊXp'@_O<p'@^O 4r'@R> 4'@R> 4Ҡ6 '@R= 4:Ս'@R= 4w'@Q= 4Rs'@Q< 4R '@Q< 3RY '@Q< 3U2'@Q< 3RE'@P; 3;X#'@P; 3rHj'@P; 3R|})'@P: 3ҝ'@O: 2RK/'@O: 2r^'@O9 2r5'@O9 2^ڸ'@O92A;'@N82'@N82B'@N82:#%ŗ'@N71r7H'@M71dJ˘'@M712s]N'@M7124oљ'@M61FT'@M61ך'@L61Z'@L50J)ݛ'@L50`'@L50j'@K40R f'@K40|'@K40MMm'@K30 )'@J3/Ry''@F--ߋ'@F--r-'@F-- !'@F--3'@E,-cֶ'@E,,9'@E,,R'@E+,E@'@D+, ì'@D+,3F'@D*,r )Fɭ'@D*,XL'@D*,2 kkϮ'@C)+2, ~R'@C)+2:կ'@C)+INX'@C(+[۰'@B(+rn^'@B(+R1'@B(+2d'@B'+s'@A'*k'@A'*2%'@A&*W8q'@A&*&J'@A&*RH]w'@@%*k:p'@@%*ۂ}'@@%*r|'@@$)2'@?$) '@?$)6`͉'@?#)d '@?#)'@>#)2C'@>#)r'@>"(.*'@>"(e'='@="(RO'@=!(ib'@=!( u%'@=!(2S'@= (M+'@< ('@< (21'@<'R]1Ҵ'@<'r7'@;'2s'@;'7 >'@;'2'@;'rW/D'@:'R"A'@:'sTJ'@:&;g'@:&yP'@9&s~'@9&V'@9&r''@9&b\'@8&2'@8&2Bb'@8%F'@8%i'@8%m!'@7%2*4o'@7%2=F'@7%ҧmYu'@7%rl'@6%~{'@6$Q'@6$d'@6$rؔ'@5$M6ɇ'@5$2 '@5$2>y'@5$'@4$5'@4$]&'@4#248'@4#2K'@3#9B^'@3#p#'@3#F'@3#&)'@2#ZȨ'@2#i/'@2"v β'@2"R5'@1"rN'@1"2,<'@1"'@1"RY3+B'@1"r='@0"rvPH'@0"2*c'@0!ȹuN'@0!2i['@/!2 T'@/!2'@/!T@Z'@/!r'@.!`'@.!P%'@. ! g'@. 2h'@- \ 0m'@- B'@- MUs'@- xg'@, 20zy'@, 2'@, ԟ'@, av'@+ R Ņ'@+ '@+ 2['@+ 2g'@* 2-'@* @"'@*R4'@*rG'@)rV&Z'@)R%l!'@)i'@)R ''@(R'@(RrO-'@(Jɰ'@(#3'@'4'@':'@'x'@''@'@&}9'@&2b^LF'@&2H_'@&0qL'@%D'@%R'@%2'@%)X'@$'@$rm^'@$Ҹ'@$Үe'@#S'@#r+k'@#қ>'@#29Qq'@"2c'@"}vw'@"'@"}'@!2c'@!2'@!'@!rI'@  '@ ߍ '@ /'@ 0'@tC'@R.V'@RFh'@`Z{'@{%'@2'@r@+'@RŮ'@1'@ ''@G7(@2ok(@ #>(@į5(@RQHD(@!Z(@RmJ(@r8(@2ڒP(@|(@(V(@b(@c\(@2(@rc(@\J(@'i(@R:(@*1Mo (@2s_ (@2uru (@ (@V{ (@\ (@R (@RJ (@C (@ (@N(@R*(@2,(@ao?(@rR(@"d(@҅Vw(@#(@rQ(@ҹ=)(@#(@/(@$(@m5(@i (@R <(@Ǯ1(@=QDB(@RV(@0iH(@8|(@*ێN(@2}(@+ T(@(@4eZ(@Һ(@rC`(@L(@Y#g(@6(@w4Im(@R [(@ yns(@ 1(@ Ⱦy (@ Raa (@ !(@ "(@ 26Iޅ"(@ #(@ w#(@ 1$(@ 2($(@ 2gv;%(@ N%(@ r`&(@ f^s&(@ !'(@ ģ'(@ ߾vF'((@ ߽*齪((@߽Rߋ-)(@޽R.)(@޽RO3*(@޼ t*(@޼R:+(@ݼr-+(@ݼrD\@@,(@ݻRR,(@ܻɡeF-(@ܻ2Dx-(@ܻRVL.(@ۺR.(@ۺ,R/(@ۺr/(@ں҄rX0(@ڹT0(@ڹ&^1(@ٹRZ 1(@ٹe2(@ٸ22(@ظCEk3(@ظZW3(@ظR7jq4(@ط,}4(@׷Ώw5(@׷q5(@׷}6(@ֶ7(@ֶrZڃ7(@ֶrq8(@նr\8(@նIC 9(@յ7$9(@Ե'7:(@Ե,J:(@Ե \;(@Ӵro;(@Ӵ<(@Ӵ󷔢<(@ӴZ%=(@ҳr=(@ҳ+>(@ҳRC߮>(@ѳR1?(@ѲR?(@Ѳ,8@(@вR)@(@вs<>A(@бOA(@ϱaDB(@ϱ-\tB(@ϱ=JC(@ΰOC(@ΰcEPD(@ΰryD(@ΰVE(@ͯR.E(@ͯ R\F(@ͯ 2t F(@̯ cG(@̯ R!.G(@̮ C^AiH(@ˮ gTH(@ˮ foI(@ˮ 2GyI(@ʭ uJ(@ʭ J(@ʭ 61{K(@ɭ eK(@ɬ wցL(@ɬ RM(@ɬ M(@Ȭ r2a N(@ȫ 2j!N(@ȫ 3O(@ۿǫ JFO(@ۿǫ XP(@ۿǪ ZkP(@ۿƪ r4~Q(@ۿƪ אQ(@ۿƪ "{#R(@ۿŪ hR(@ۿũ ү)S(@ۿũ rd۬S(@۾ĩ D/T(@ܾĩ T(@ܾĨ N6U(@ܾĨ 1%U(@ܾè 8y(@ޭjOQz(@ݭ2(@کjh(@٨V{D(@٨D1ǂ(@٨r4ՠJ(@ا%y̓(@اRP(@اRӄ(@اReV(@צم(@צR](@צP#(@֥5c(@֥rH(@֥<[i(@֤rm(@դo(@դr)(@գ2 ͥu(@գq(@ԣ#{(@Ԣ1(@Ԣ@](@ӢR(@Ӣf(@ӡr{I( (@ӡr:(@ҡRM(@Ҡ5`(@Ҡ2r(@Ѡr~(@џR "(@џ2Bƪ(@џej#(@ОЦ(@О)(@ОV(@Ϟ0(@ϝ2(@ϝr`C-6(@ϝr?(@Μ2‹R<(@Μ/e(@Μ2+wB(@͛rbxŗ(@͛rH(@͛˘(@͚eN(@̚Q љ(@̚2T(@̚Qך(@̙ [(@˙R\ޛ(@˙r>2a(@˘D(@ʘr7Wg(@ʘGj(@ʗ|m(@ʗ2(@ɗrSs(@ɖ깳(@ɖU y(@Ȗr(@Ȗ((@ȕS(@ȕ(@Ǖ2_ " (@ǔ2ņ4(@ǔR*F(@ƔSY(@ƓRk(@ƓU ~(@Ɠ2(@ŒR(@ŒxS!(@ŒrعǤ(@đ27 '(@đR쪨(@đ-(@đOS(@Ð#4(@Ð 6(@Ð_H:(@Z(@Sm@(@Riì(@Ž2F(@rɭ(@kL(@rRϮ(@2R(@2gկ(@rY(@ ܰ(@奿r[R%_(@奿27(@夿RJe(@夾H\(@夾nk(@夾Q(@夾.q(@夽y(@壽Ąw(@壽~ (@壼~RVQ}(@壼~2(@壼~r(@壼}+(@壻}rq&(@墻}P9 (@墻}K(@墺}R=^(@墺|p(@墺|r(@墹|2P(@塹|RB(@塹|r(@塹{%(@塸{ި(@塸{r:O+(@桸{v(@样{2(@样zR((@样z2&:8(@样z_NM(@栶zR_>(@栶zr(@柶y2D(@柵y:(@柵yoMJ(@柵y2(@柵yP(@柴x2 (@枴x;V(@枴xlL(@枳xR](@枳x*(@枳wr~(@曮ztX{P(@曮ztzb(@曮ztGu(@曮ytR(@曭ys(@曭ysy(@暭xs#(@暬xsR6FѦ(@暬xsR)(@暬wrn(@皬wrrx0(@癫wr@@@@##DTh H俋?di@ [A.̍?di@ ȹw؏?di@$ `?di@$;?di@$j?di@dr?di@dO ?di@,?di@& >?di@Ub?e i@ć#?e i@䳡)?e i@$~/?e i@$\5?e i@dA9d?g`i@?g`i@rmij?hi@?hi@Fp?hi@4?hi@#$w?hi@2c6?hi@I}?hi@Ro[?hi@)m?hi@`&@?hi@y]D?ii@IR?ii@ Dǰ?ii@ɏe ?ii@:J?ii@Y'rw?ii@)sα?ii@?ii@ Q?ii@yVO?ii@9%Բ?ji@ ?ji@97W?ji@,?ji@YcJڳ?ji@?ji@h\]?ji@ 枴?ji@yAo?ji@9Lx!?ji@ c?ki@ ?ki@/?ki@Y{U(?ki@nji?ki@/?ki@^?ki@i2B.?ki@9io?ki@AT?ki@ɍ?lj@g4?lj@Y%Gu?lj@q~y?lj@ټ?lj@:?lj@iT$|?lj@9[?lj@'?lj@7ʰ@?lj@:? m j@I8ú? m j@pL? m j@fF? m j@^? m j@iɻ? m j@)JMq ? m j@L? m j@ể? m j@- м? m j@Iy*? n@j@ aS? n@j@? n@j@\1ֽ? n@j@i? n@j@)>DY? n@j@?v͚? n@j@Vܾ? n@j@y? n@j@I#i_? n@j@ oS? o`j@ٺ{? o`j@La? o`j@,2? o`j@OS? o`j@3Pt? o`j@ܚ? o`j@@kٵ? o`j@? o`j@b? o`j@d2>'? pj@L8? pj@,~uY? pj@$uz? pj@ɬ9? pj@oH? pj@? pj@? pj@aL? pj@d?? pj@DR_? pj@,S? qj@ ^? qj@%#? qj@D? qj@\? qj@p$? qj@|65E? qj@d/e? qj@D˾? qj@,(g?rj@ H?rj@s ?rj@: ?rj@Օ*?rj@eqZK?rj@| l?rj@d?rj@DWD?rj@$l?rj@ {1?sj@H?sj@0?sj@NQ?sj@:Cr?sj@|?sj@\!ͳ?sj@D,?sj@$XV?sj@ x?sj@6?tk@+W?tk@ihx?tk@c-?tk@|?tk@\[?tk@<6{?tk@$??tk@Mm=?tk@]?tk@̘~?u k@>@R?u k@?u k@tw?u k@\0?u k@<֮d"?u k@$|J)C?u k@"c?u k@ǁ?u k@mw?u k@;?v@k@T?v@k@t_?v@k@\(?v@k@<'NI?v@k@Qj?v@k@^׊?v@k@?v@k@B`?v@k@1%?v@k@ ?v@k@t4i.?w`k@TsO?w`k@<7p?w`k@&B?l@A2Ð?l@A"H?l@Ai,?l@AŻm?l@A. ?l@A"kW2?l@A>!?l@A1?l@A@YB?l@A궎R?l@Aډc?l@A\*s?l@A/x?l@AD?l@A?l@Aa ?l@A{k?l@AvN?l@Af!K0?l@AZ?l@AJ?l@A>4W?l@A.m'?l@A@8?l@A~H?l@AkX? m@ABi? m@Ay? m@A^U? m@A1i? m@A˪? m@A>.? m@A? m@A}? m@AP(U? m@Ar#v?! m@Af ?! m@AV|?! m@AJ_-?! m@A:o@>?! m@A.BN?! m@AI_?! m@Ago?! m@A?! m@A2,?! m@A`?"@m@A3?"@m@AS?"@m@Ai?"@m@A?"@m@Az?"@m@ARS?"@m@A%>?"@m@Ar#?"@m@Ab<4?"@m@AVeD?#`m@AFqT?#`m@A:D&*e?#`m@A*tu?#`m@A?#`m@AQ?#`m@A]?#`m@Ab?#`m@A5w?#`m@AG?#`m@A۔Żm?*@n@A2 ?*@n@A"kW2?*@n@A>!?*@n@A1?*@n@A@YB?*@n@A궎R?*@n@Aډc?+`n@A\*s?+`n@A/x?+`n@AD?+`n@A?+`n@Aa ?+`n@A{k?+`n@AvN?+`n@Af!K0?+`n@AZ?+`n@AJ?,n@A>4W?,n@A.m'?,n@A@8?,n@A~H?,n@AkX?,n@ABi?,n@Ay?,n@A^U?,n@A1i?,n@A˪?-n@A>.?-n@A?-n@A}?-n@AP(U?-n@Ar#v?-n@Af ?-n@AV|?-n@AJ_-?-n@A:o@>?-n@A.BN?.n@AI_?.n@Ago?.n@A?.n@A2,?.n@A`?.n@A3?.n@AS?.n@Ai?.n@A?.n@Az?/n@ARS?/n@A%>?/n@Ar#?/n@Ab<4?/n@AVeD?/n@AFqT?/n@A:D&*e?/n@A*tu?/n@A?/n@AQ?0o@A]?0o@Ab?0o@A5w?0o@AG?0o@A۔?3`o@ eM?3`o@ ~?3`o@ ಯ?3`o@ ?3`o@ ?3`o@ 'C?3`o@ uNt?3`o@ ou ?3`o@ gY?4o@ B?4o@ Y,8#?4o@ j+?4o@ K73?4o@ ^;?4o@ =҅C?4o@ .L?4o@ /_T?4o@ \?4o@ x!d?5o@ aHl?5o@ Ko$u?5o@ 4U}?5o@ ?5o@ }䷍?5o@ ?5o@ m1?5o@ XK?5o@ _|?5o@ ٖ?6o@ Q޾?6o@ i?6o@ CSA?6o@ m?9p@ A(*?9p@ [?: p@ 3?: p@ ?: p@ %/?: p@ V ?: p@ }Q'?: p@ /?: p@ t˳7?: p@ ]??: p@ FH?: p@ q0@GP?;0p@ gxX?;0p@ c`?;0p@ h?;0p@ U q?;0p@ Ͽ=y?;0p@ G)n?;0p@ P?;0p@ 9|wБ?;0p@ e?;0p@ +O2?<@p@ 8c?<@p@ "?<@p@ :ƺ?<@p@ `?<@p@ އ(?<@p@ ǮY?<@p@ yՊ?<@p@ ?<@p@ k#?<@p@ mJ?=Pp@ ]WqO?=Pp@ @?=Pp@ M* ?=Pp@ ?=Pp@ ? ?=Pp@ 3E%?=Pp@ 1Zv-?=Pp@ 5?=Pp@ #=?=Pp@ F?>`p@ v:N?>`p@ _lV?>`p@ ID^?>`p@ 2kf?>`p@ n?>`p@ q0w?>`p@ a?>`p@ c?>`p@ -ď?>`p@ ST??pp@ ͔{&??pp@ E~W??pp@ gɈ??pp@ 7Q??pp@ :??pp@ )$>??pp@ eM??pp@ ~??pp@ ಯ??pp@ ?@p@ ?@p@ 'C?@p@ wNt?@p@ ou ?@p@ iY?@p@ B?@p@ [,8#?@p@ j+?@p@ K73?@p@ ^;?Ap@ =҅C?Ap@ .L?Ap@ /_T?Ap@ \?Ap@ !x!d?Ap@ aHl?Ap@ Ko$u?Ap@ 4U}?Ap@ ?Ap@ }䷍?Bp@ ?Bp@ o1?Bp@ XK?Bp@ a|?Bp@ ٖ?Bp@ Q޾?Bp@ i?Bp@ CSA?Bp@ m?Fp@ C(*?Fp@ [?Fp@ 3?Fp@ ?Fp@ %/?Fp@ V ?Fp@ }Q'?Gp@ /?Gp@ t˳7?Gp@ ]??Gp@ FH?Gp@ s0@GP?Gp@ gxX?Gp@ e`?Gp@ h?Gp@ W q?Gp@ Ͽ=y?Hq@ I)n?Hq@ P?Hq@ ;|wБ?Hq@ e?Hq@ +O2?Hq@ 8c?Hq@ "?Hq@ :ƺ?Hq@ `?Hq@ އ(?Iq@ ȮY?Iq@ yՊ?Iq@ ?Iq@ k#?Iq@ mJ?Iq@ ]WqO?Iq@ @?Iq@ O* ?Iq@ ?Iq@ A ?J q@ 3E%?J q@ 1Zv-?J q@ 5?J q@ #=?J q@ F?J q@ v:N?J q@ _lV?J q@ ID^?J q@ 2kf?J q@ n?K0q@ q0w?K0q@ a?K0q@ c?K0q@ -ď?K0q@ UT?K0q@ ͔{&?K0q@ G~W?K0q@ gɈ?K0q@ 9Q?K0q@ :?L@q@ )$>?L@q@ eM?L@q@ ~?L@q@ ಯ?L@q@ ?L@q@ ?L@q@ 'C?L@q@ wNt?L@q@ ou ?L@q@ iY?MPq@ B?MPq@ [,8#?MPq@ j+?MPq@ M73?MPq@ ^;?MPq@ ?҅C?MPq@ .L?MPq@ /_T?MPq@ \?MPq@ !x!d?N`q@ aHl?N`q@ Ko$u?N`q@ 4U}?N`q@ ?N`q@ }䷍?N`q@ ?N`q@ o1?N`q@ XK?N`q@ a|?N`q@ ٖ?Opq@ S޾?Opq@ i?Opq@ ESA?Opq@ m?Rq@ C(*?Rq@ [?Sq@ 5?Sq@ ?Sq@ '/?Sq@ V ?Sq@ }Q'?Sq@ /?Sq@ t˳7?Sq@ ]??Sq@ FH?Sq@ u0@GP?Tq@ gxX?Tq@ e`?Tq@ h?Tq@ W q?Tq@ ѿ=y?Tq@ I)n?Tq@ ÒP?Tq@ ;|wБ?Tq@ e?Tq@ -O2?Uq@ 8c?Uq@ "?Uq@ :ƺ?Uq@ `?Uq@ އ(?Uq@ ȮY?Uq@ {Պ?Uq@ ?Uq@ m#?Uq@ mJ?Vq@ ]WqO?Vq@ @?Vq@ O* ?Vq@ ?Vq@ A ?Vq@ 3E%?Vq@ 3Zv-?Vq@ 5?Vq@ %=?Vq@ F?Wq@ v:N?Wq@ _lV?Wq@ ID^?Wq@ 2kf?Wq@ n?Wq@ s0w?Wq@ a?Wq@ c?Wq@ -ď?Wq@ UT?Xr@ ϔ{&?Xr@ G~W?Xr@ gɈ?Xr@ 9Q?Xr@ :?Xr@ +$>?Xr@ eM?Xr@ ~?Xr@ ಯ?Xr@ ?Yr@ ?Yr@ 'C?Yr@ yNt?Yr@ ou ?Yr@ kY?Yr@ B?Yr@ [,8#?Yr@ j+?Yr@ M73?Yr@ ^;?Z r@ ?҅C?Z r@ .L?Z r@ 1_T?Z r@ \?Z r@ #x!d?Z r@ aHl?Z r@ Ko$u?Z r@ 4U}?Z r@ ?Z r@ ䷍?[0r@ ?[0r@ q1?[0r@ XK?[0r@ c|?[0r@ ۖ?[0r@ U޾?[0r@ i?[0r@ ESA?[0r@ m?_pr@ C(*?_pr@ [?_pr@ 5?_pr@ ?_pr@ '/?_pr@ V ?_pr@ }Q'?`r@ /?`r@ t˳7?`r@ ]??`r@ FH?`r@ u0@GP?`r@ gxX?`r@ g`?`r@ h?`r@ Y q?`r@ ѿ=y?ar@ K)n?ar@ ÒP?ar@ ;|wБ?ar@ e?ar@ -O2?ar@ 8c?ar@ "?ar@ :ƺ?ar@ `?ar@ އ(?br@ ȮY?br@ {Պ?br@ ?br@ m#?br@ mJ?br@ _WqO?br@k L@?br@(X?br@ sq ?br@~?cr@]?cr@h-?cr@?cr@QT?cr@O#?cr@ ;{'?cr@ǯ6+?cr@$N/?cr@@5g3?cr@ 7?dr@\;?dr@v??dr@2lC?dr@G?dr@UK?dr@g=P?dr@$?+T?dr@dDX?dr@(\\?dr@Yu`?er@d?er@҆h?er@El?er@Kpp?er@lt?er@Y y?er@Γ!}?er@?gr@nKV?hs@*fo?hs@4?hs@?hs@_!?hs@?hs@H?hs@|?hs@Qn?hs@ f4?hs@ڕL?is@O)e?is@Cļ} ?is@8P?is@?is@x"w?is@4 ?is@ ?is@1%?is@j))?is@&jXB-?j s@Z1?j s@Ss5?j s@[9?j s@==?j s@Ա9A?j s@&E?j s@M`I?j s@ N?j s@ƄR?j s@8V?k0s@?nPZ?k0s@Ai^?k0s@WՁb?k0s@thf?k0s@0Aj?k0s@n?k0s@*#r?k0s@ev?k0s@"J{?k0s@ވ-?l@s@pF?l@s@Wr_?l@s@w?l@s@[+?l@s@о?l@s@IER?l@s@ٛ?l@s@.y?l@s@~ ?l@s@:#?mPs@3?ts@nKV?ts@*fo?ts@4?ts@?ts@`!?ts@?us@H?us@|?us@Qn?us@f4?us@ڕL?us@O)e?us@Cļ} ?us@8P?us@?us@x"w?vs@5 ?vs@ ?vs@1%?vs@j))?vs@&jXB-?vs@Z1?vs@Ss5?vs@\9?vs@==?vs@Ա9A?ws@&E?ws@M`I?ws@ N?ws@ƄR?ws@8V?ws@?nPZ?ws@Ai^?ws@WՁb?ws@thf?ws@1Aj?xt@n?xt@*#r?xt@fv?xt@#J{?xt@߈-?xt@pF?xt@Xr_?xt@w?xt@[+?xt@о?yt@JER?yt@ٛ?yt@.y?yt@ ?yt@;#?yt@3?t@nKV?t@+fo?t@4?t@?t@`!?t@?t@H?t@|?t@Rn?t@f4?t@ڕL?t@O)e?t@Dļ} ?t@9P?t@?t@y"w?t@5 ?t@ ?t@1%?t@k))?t@'jXB-?t@Z1?t@Ss5?t@\9?t@==?t@ձ9A?t@&E?t@N`I?t@ N?t@DŽR?t@8V?t@@nPZ?t@Ai^?t@WՁb?t@uhf?t@1Aj?t@n?t@*#r?t@gv?t@#J{?t@߈-?t@pF?t@Xr_?t@w?t@[+?t@о?t@JER?t@ٛ?t@.y?t@ ?t@<#?t@3C':?0u@R?0u@,Nk?0u@sჍ?0u@/u?0u@?0u@͙?0u@et/?@u@!?@u@]V?@u@/?@u@WG}H?@u@a?@u@0y?@u@7?@u@H˪?@u@^?@u@?Pu@~x?Pu@: ?Pu@a%?Pu@?>?Pu@oKV?Pu@,fo?Pu@4?Pu@?Pu@a!?Pu@?`u@H?`u@|?`u@Sn?`u@f4?`u@ڕL?`u@O)e?`u@Dļ} ?`u@9P?`u@?`u@y"w?pu@6 ?pu@ ?pu@1%?pu@k))?pu@(jXB-?pu@Z1?pu@Ss5?pu@]9?pu@==?pu@ֱ9A?u@&E?u@N`I?u@ N?u@DŽR?u@8V?u@@nPZ?u@Ai^?u@WՁb?u@uhf?u@2Aj?u@n?u@*#r?u@gv?u@#J{?u@-?u@pF?u@Yr_?u@w?u@[+?u@о?u@JER?u@ٛ?u@.y?u@ ?u@<#?u@3C':?u@R?u@,Nk?v@tჍ?v@0u?v@?v@͙?v@et/?v@"?v@]V?v@/?v@WG}H?v@a?v@0y?v@7?v@I˪?v@^?v@?v@~x?v@: ?v@a%?v@?>?v@pKV? v@,fo? v@4? v@? v@a!? v@? v@H? v@|? v@Sn? v@f4? v@ڕL?0v@O)e?0v@Eļ} ?0v@9P?0v@?0v@z"w?0v@6 ?0v@ ?0v@1%?0v@l))?0v@(jXB-?@v@Z1?@v@Ss5?@v@]9?@v@==?@v@ֱ9A?@v@&E?@v@O`I?@v@ N?@v@ȄR?@v@8V?Pv@AnPZ?Pv@Ai^?Pv@WՁb?Pv@vhf?Pv@2Aj?Pv@﵏n?Pv@*#r?Pv@gv?Pv@$J{?Pv@-?`v@pF?`v@Yr_?`v@w?`v@[+?`v@о?`v@KER?`v@ٛ?`v@.y?`v@ ?`v@<#?pv@3? v@pKV? v@,fo? v@4? v@? v@b!? v@? v@H? v@|? v@Sn? v@f4? v@ڕL? v@O)e? v@Eļ} ? v@9P? v@? v@z"w? w@7 ? w@ ? w@1%? w@l))? w@(jXB-? w@Z1? w@Ss5? w@^9? w@==? w@ֱ9A? w@&E? w@O`I? w@ N? w@ȄR? w@8V? w@AnPZ? w@Ai^? w@WՁb? w@vhf? w@3Aj? w@﵏n? w@*#r? w@hv? w@%J{? w@-? w@pF? w@Zr_? w@w? w@[+? w@о?0w@LER?0w@ٛ?0w@.y?0w@ ?0w@=#?0w@3?w@pKV?w@-fo?w@4?w@?w@b!?w@?w@H?w@|?w@Tn?w@f4?w@ڕL?w@O)e?w@Fļ} ?w@9P?w@?w@{"w?w@7 ?w@ ?w@1%?w@m))?w@)jXB-?w@Z1?w@Ss5?w@^9?w@==?w@ױ9A?w@&E?w@P`I?w@ N?w@ɄR?w@8V?w@BnPZ?w@Ai^?w@WՁb?w@whf?w@3Aj?w@n?w@*#r?w@iv?w@%J{?w@-?w@pF?w@Zr_?w@w?w@[+?w@о?w@LER?w@ٛ?w@.y?w@ ?w@>#?x@3?#px@qKV?#px@-fo?#px@4?#px@?#px@b!?#px@?$x@H?$x@|?$x@Tn?$x@f4?$x@ڕL?$x@O)e?$x@Fļ} ?$x@9P?$x@?$x@{"w?%x@7 ?%x@ ?%x@1%?%x@m))?%x@)jXB-?%x@Z1?%x@Ss5?%x@^9?%x@==?%x@ױ9A?&x@&E?&x@P`I?&x@ N?&x@ɄR?&x@8V?&x@BnPZ?&x@Ai^?&x@WՁb?&x@whf?&x@3Aj?'x@n?'x@*#r?'x@iv?'x@%J{?'x@-?'x@pF?'x@Zr_?'x@w?'x@[+?'x@о?(x@LER?(x@ٛ?(x@.y?(x@ ?(x@>#?(x@3@-y@ȟ@@-y@H[]B@-y@H\D@. y@ȺF@. y@:H@. y@HwEJ@. y@HL@. y@H3N@. y@ȑtaP@. y@. S@. y@HNU@. y@H>$W@. y@H ^0Y@/0y@h<[@/0y@I]@/0y@H%eU_@/0y@HGaa@/0y@mc@/0y@?Bze@/0y@ȝvg@/0y@H0֒i@/0y@HZk@/0y@ȸim@0@y@`o@0@y@tq@0@y@HFs@0@y@H1u@0@y@ȏIw@0@y@$y@0@y@HLm|@0@y@Hx ~@0@y@H3@0@y@fJ&@1Py@ħ2@1Py@H#b>@1Py@H(K@1Py@HqW@1Py@=c@1Py@țKp@1Py@HO|@1Py@HX@1Py@ȶz└@1Py@5,@2`y@ru@2`y@Hѩ@2`y@H/d Ɯ@2`y@ȍSҞ@2`y@؜ޠ@2`y@I@2`y@HM0@2`y@Hz@2`y@d@2`y@| @3py@H!7W(@3py@H4@3py@Hݫ@@3py@;f4M@3py@ș ~Y@3py@He@3py@HVr@3py@HO[~@3py@ @3py@p@4y@H~8@4y@H-9@4y@ȋ˻@4y@@4y@Gh_@4y@H"@4y@H@4y@b<@4y@Q@4y@ @5y@H}@5y@Hۀc*@5y@9;6@5y@ȗB@5y@H@O@5y@HTj[@5y@H$g@5y@t@5y@ng@5y@HS@6y@H+@6y@ȉD@6y@炎@6y@HF=ؽ@6y@H!@6y@Hk@6y@`l@6y@Ⱦ&@6y@HH@6y@H{@7y@U@7y@7& @7y@ȕo,@7y@H8@7y@HR?E@7y@ȰLQ @7y@] @7y@lni @7y@H(*v@7y@H)s@8y@ȇ@8y@W@8y@HDQ@8y@H̚@8y@H@8y@^A.@8y@ȼw@8y@H!@8y@Hyp #@8y@H*U%@9y@5 (@9y@ȓ*@9y@HY2",@9y@HP|..@9y@Ȯ:0@9y@ G2@9y@jCYS4@9y@H_6@9y@H'k8@9y@ȅr6x:@:y@,<@:y@Aɐ>@:y@H@@:y@H[]B@:y@\D@:y@ȺF@:y@H:H@:y@HwEJ@:y@HL@:y@3N@;y@ȑtaP@;y@H. S@;y@HNU@;y@H>$W@;y@ ^0Y@;y@h<[@;y@HI]@;y@H%eU_@;y@ȃGaa@;y@mc@<z@?Bze@<z@Hvg@<z@H0֒i@<z@Zk@<z@ȸim@<z@`o@<z@Huq@<z@HFs@<z@1u@<z@ȏIw@=z@H$y@=z@HLm|@=z@Hx ~@=z@3@=z@fJ&@=z@Hŧ2@=z@H#b>@=z@H(K@=z@qW@=z@=c@> z@HKp@> z@HO|@> z@X@> z@ȶz└@> z@5,@> z@Hsu@> z@Hѩ@> z@/d Ɯ@> z@ȍSҞ@> z@؜ޠ@?0z@HJ@?0z@HM0@?0z@z@?0z@d@?0z@H| @?0z@H!7W(@?0z@H4@?0z@ݫ@@?0z@;f4M@?0z@H ~Y@@@z@He@@@z@Vr@@@z@ȴO[~@@@z@H @@@z@Hq@@@z@H~8@@@z@-9@@@z@ȋ˻@@@z@H@@@z@HHh_@APz@Ȧ"@APz@@APz@b<@APz@HQ@APz@H @APz@}@APz@ۀc*@APz@9;6@APz@HB@APz@H@O@B`z@Tj[@B`z@Ȳ$g@B`z@Ht@B`z@Hog@B`z@HS@B`z@+@B`z@ȉD@B`z@H肎@B`z@HF=ؽ@B`z@H!@Cpz@k@Cpz@`l@Cpz@H&@Cpz@HH@Cpz@{@Cpz@U@Cpz@7& @Cpz@Ho,@Cpz@H8@Cpz@R?E@Dz@ȰLQ @Dz@] @Dz@Hmni @Dz@H(*v@Dz@)s@Dz@ȇ@Dz@HW@Dz@HDQ@Dz@H̚@Dz@@Ez@^A.@Ez@Hw@Ez@H!@Ez@Hyp #@Ez@*U%@Ez@5 (@Ez@H*@Ez@HY2",@Ez@P|..@Ez@Ȯ:0@Fz@ G2@Fz@HkCYS4@Fz@H_6@Fz@'k8@Fz@ȅr6x:@Fz@,<@Fz@HBɐ>@Fz@H@@Fz@[]B@Fz@\D@Gz@HF@Gz@H:H@Gz@HwEJ@Gz@L@Gz@3N@Gz@HtaP@Gz@H. S@Gz@HNU@Gz@Ȭ>$W@Gz@ ^0Y@Hz@Hi<[@Hz@HI]@Hz@%eU_@Hz@ȃGaa@Hz@mc@Hz@H@Bze@Hz@Hvg@Hz@0֒i@Hz@Zk@Hz@ȸim@Iz@H`o@Iz@Huq@Iz@Fs@Iz@1u@Iz@HIw@Iz@H$y@Iz@HLm|@Iz@Ȫx ~@Iz@3@Iz@HgJ&@Jz@Hŧ2@Jz@H#b>@Jz@ȁ(K@Jz@qW@Jz@H>c@Jz@HKp@Jz@HO|@Jz@X@Jz@ȶz└@Jz@H5,@Kz@Hsu@Kz@ѩ@Kz@/d Ɯ@Kz@ȍSҞ@Kz@H؜ޠ@Kz@HJ@Kz@ȨM0@Kz@z@Kz@d@Kz@H| @L{@H!7W(@L{@4@L{@ݫ@@L{@H@Sp{@H@@Sp{@[]B@Sp{@\D@Sp{@HF@Sp{@H:H@Sp{@HwEJ@Sp{@L@Sp{@3N@T{@HtaP@T{@H. S@T{@NU@T{@Ȭ>$W@T{@H ^0Y@T{@Hi<[@T{@HI]@T{@%eU_@T{@ȃGaa@T{@Hmc@U{@H@Bze@U{@Ȟvg@U{@0֒i@U{@Zk@U{@Him@U{@H`o@U{@uq@U{@Fs@U{@1u@U{@HIw@V{@H$y@V{@Lm|@V{@Ȫx ~@V{@H 3@V{@HgJ&@V{@Hŧ2@V{@#b>@V{@ȁ(K@V{@HqW@V{@H>c@W{@HKp@W{@O|@W{@X@W{@Hz└@W{@H5,@W{@su@W{@ѩ@W{@/d Ɯ@W{@HSҞ@W{@H؜ޠ@X{@J@X{@ȨM0@X{@z@X{@He@X{@H| @X{@!7W(@X{@4@X{@Hޫ@@X{@H@_0|@Ƞ@@_0|@[]B@_0|@H]D@`@|@HF@`@|@:H@`@|@wEJ@`@|@HL@`@|@H4N@`@|@HtaP@`@|@. S@`@|@NU@`@|@H>$W@`@|@H ^0Y@aP|@Hi<[@aP|@I]@aP|@%eU_@aP|@HGaa@aP|@Hmc@aP|@@Bze@aP|@Ȟvg@aP|@0֒i@aP|@H[k@aP|@Him@b`|@`o@b`|@uq@b`|@Fs@b`|@H2u@b`|@HIw@b`|@$y@b`|@Lm|@b`|@Hx ~@b`|@H 3@b`|@HgJ&@cp|@ŧ2@cp|@#b>@cp|@H(K@cp|@HqW@cp|@H>c@cp|@ȜKp@cp|@O|@cp|@HY@cp|@Hz└@cp|@5,@d|@su@d|@ѩ@d|@H0d Ɯ@d|@HSҞ@d|@؜ޠ@d|@J@d|@ȨM0@d|@Hz@d|@He@d|@| @e|@!7W(@e|@H4@e|@Hޫ@@e|@H@l}@Ƞ@@l}@H[]B@l}@H]D@l}@ȻF@l}@:H@l}@HxEJ@l}@HL@l}@H4N@ m}@ȒtaP@ m}@. S@ m}@HOU@ m}@H>$W@ m}@H ^0Y@ m}@i<[@ m}@I]@ m}@H&eU_@ m}@HGaa@ m}@mc@ n }@@Bze@ n }@Ȟvg@ n }@H0֒i@ n }@H[k@ n }@ȹim@ n }@`o@ n }@uq@ n }@HFs@ n }@H2u@ n }@ȐIw@ o0}@$y@ o0}@HMm|@ o0}@Hx ~@ o0}@H 3@ o0}@gJ&@ o0}@ŧ2@ o0}@H$b>@ o0}@H(K@ o0}@HqW@ o0}@>c@ p@}@ȜKp@ p@}@HO|@ p@}@HY@ p@}@ȷz└@ p@}@5,@ p@}@su@ p@}@Hҩ@ p@}@H0d Ɯ@ p@}@ȎSҞ@ p@}@؜ޠ@ qP}@J@ qP}@HM0@ qP}@Hz@ qP}@e@ qP}@| @ qP}@H"7W(@ qP}@H4@ qP}@Hޫ@@ qP}@@x}@H@@x}@H[]B@x}@]D@y}@ȻF@y}@H:H@y}@HxEJ@y}@HL@y}@4N@y}@ȒtaP@y}@H. S@y}@HOU@y}@H>$W@y}@ ^0Y@z}@i<[@z}@HI]@z}@H&eU_@z}@ȄGaa@z}@mc@z}@@Bze@z}@Hvg@z}@H0֒i@z}@[k@z}@ȹim@{}@`o@{}@Hvq@{}@HFs@{}@2u@{}@ȐIw@{}@H$y@{}@HMm|@{}@Hx ~@{}@ 3@{}@gJ&@|~@HƧ2@|~@H$b>@|~@Ȃ(K@|~@qW@|~@H?c@|~@HKp@|~@HO|@|~@Y@|~@ȷz└@|~@H5,@}~@Htu@}~@ҩ@}~@0d Ɯ@}~@ȎSҞ@}~@H؜ޠ@}~@HK@}~@ȩM0@}~@z@}~@e@}~@H| @~ ~@H"7W(@~ ~@Ȁ4@~ ~@ޫ@@~ ~@H=f4M@~ ~@H ~Y@~ ~@He@~ ~@Wr@~ ~@ȵO[~@~ ~@H @~ ~@Hr@0~@H~8@0~@.9@0~@Ȍ˻@0~@H@0~@HIh_@0~@ȧ"@0~@@0~@c<@0~@HQ@0~@H @@~@~@@~@܀c*@@~@:;6@@~@HB@@~@H@O@@~@Uj[@@~@ȳ$g@@~@Ht@@~@Hpg@@~@HS@P~@,@P~@ȊD@P~@H邎@P~@HG=ؽ@P~@H!@P~@k@P~@al@P~@H&@P~@HH@P~@|@`~@U@`~@8& @`~@Ho,@`~@H8@`~@S?E@`~@ȱLQ @`~@] @`~@Hnni @`~@H(*v@`~@*s@p~@Ȉ@p~@HW@p~@HEQ@p~@H̚@p~@@p~@_A.@p~@Hw@p~@H!@p~@Hzp #@p~@*U%@ ~@6 (@ ~@H*@ ~@HY2",@ ~@Q|..@ ~@ȯ:0@ ~@ G2@ ~@HlCYS4@ ~@H_6@ ~@(k8@ ~@Ȇr6x:@!~@,<@!~@HCɐ>@!~@H@@!~@[]B@!~@]D@!~@HF@!~@H:H@!~@HxEJ@!~@L@!~@4N@"~@HtaP@"~@H. S@"~@OU@"~@ȭ>$W@"~@H ^0Y@"~@Hj<[@"~@HI]@"~@&eU_@"~@ȄGaa@"~@Hmc@#~@HABze@#~@ȟvg@#~@0֒i@#~@[k@#~@Him@#~@H`o@#~@vq@#~@Fs@#~@2u@#~@HIw@$~@H$y@$~@Mm|@$~@ȫx ~@$~@H 3@$~@HhJ&@$~@HƧ2@$~@$b>@$~@Ȃ(K@$~@HqW@$~@H?c@%~@HKp@%~@O|@%~@Y@%~@Hz└@%~@H5,@%~@tu@%~@ҩ@%~@0d Ɯ@%~@HSҞ@%~@H؜ޠ@&~@K@&~@ȩM0@&~@z@&~@Hf@&~@H| @&~@"7W(@&~@Ȁ4@&~@H߫@@&~@H=f4M@&~@H ~Y@'~@e@'~@Wr@'~@HO[~@'~@H @'~@Hr@'~@~8@'~@.9@'~@H˻@'~@H@'~@Ih_@(@ȧ"@(@@(@Hd<@(@HQ@(@ @(@~@(@܀c*@(@H;;6@(@HB@(@@O@)@Uj[@)@H$g@)@Ht@)@Hpg@)@S@)@,@)@HD@)@H邎@)@HG=ؽ@)@ȥ!@* @k@* @Hbl@* @H&@* @H@* @|@* @U@* @H9& @* @Ho,@* @8@* @S?E@+0@ȱLQ @+0@H] @+0@Hnni @+0@(*v@+0@*s@+0@H@+0@HW@+0@HEQ@+0@ȣ̚@+0@@,@@H`A.@,@@Hw@,@@!@,@@zp #@,@@H*U%@,@@H7 (@,@@H*@,@@Y2",@,@@Q|..@,@@H:0@-P@HG2@-P@lCYS4@-P@_6@-P@(k8@-P@Hr6x:@-P@H,<@-P@Cɐ>@-P@ȡ@@-P@[]B@-P@H^D@.`@HF@.`@:H@.`@xEJ@.`@HL@.`@H5N@.`@HtaP@.`@. S@.`@OU@.`@H>$W@.`@H ^0Y@/p@Hj<[@/p@I]@/p@&eU_@/p@HGaa@/p@Hmc@/p@ABze@/p@ȟvg@/p@0֒i@/p@H\k@/p@Him@0@`o@0@vq@0@Fs@0@H3u@0@HIw@0@$y@0@Mm|@0@Hx ~@0@H 3@0@HhJ&@1@Ƨ2@1@$b>@1@H(K@1@HqW@1@H?c@1@ȝKp@1@O|@1@HZ@1@Hz└@1@5,@2@tu@2@ҩ@2@H1d Ɯ@2@HSҞ@2@؜ޠ@2@K@2@ȩM0@2@Hz@2@Hf@2@| @3@"7W(@3@H4@3@H߫@@3@H=f4M@3@ț ~Y@3@e@3@HXr@3@HO[~@3@H @3@r@4@~8@4@H/9@4@H˻@4@@4@Ih_@4@ȧ"@4@H@4@Hd<@4@Q@4@ @5@~@5@H݀c*@5@H;;6@5@șB@5@@O@5@HVj[@5@H$g@5@Ht@5@pg@5@S@6@H-@6@HD@6@邎@6@G=ؽ@6@H!@6@Hk@6@Hbl@6@&@6@H@6@H}@7@HU@7@9&  @7@ȗo, @7@8 @7@HT?E @7@HLQ @7@] @7@nni @7@(*v @7@H+s @8@H @8@W @8@EQ @8@H̚ @8@H @8@H`A. @8@Ⱦw @8@! @8@H{p # @8@H*U% @9@H7 ( @9@ȕ* @9@Y2", @9@HR|.. @9@H:0 @9@G2 @9@lCYS4 @9@_6 @9@H)k8 @9@Hr6x: @:@,< @:@Cɐ> @:@ȡ@ @:@H\]B @:@H^D @:@ȼF @:@:H @:@HyEJ @:@HL @:@H5N @;@ȓtaP @;@. S @;@HPU @;@H>$W @;@H ^0Y @;@j<[ @;@I] @;@H'eU_ @;@HGaa @;@mc @< @ABze @< @ȟvg @< @H0֒i @< @H\k @< @Ⱥim @< @`o @< @vq @< @HFs @< @H3u @< @ȑIw @=(@$y @=(@HNm| @=(@Hx ~ @=(@H 3 @=(@hJ& @=(@Ƨ2 @=(@H%b> @=(@H(K @=(@HqW @=(@?c @>0@ȝKp @>0@HO| @>0@HZ @>0@ȸz└ @>0@5, @>0@tu @>0@Hө @>0@H1d Ɯ @>0@ȏSҞ @>0@؜ޠ @?8@K @?8@HM0 @?8@Hz @?8@f @?8@|  @?8@H#7W( @?8@H4 @?8@H߫@ @?8@=f4M @?8@ț ~Y @@@@He @@@@HXr @@@@ȶO[~ @@@@ @@@@Hs @@@@H~8 @@@@H/9 @@@@ȍ˻ @@@@ @@@@HJh_ @AH@H" @AH@ @AH@d< @AH@Q @AH@H!  @AH@H @AH@݀c* @AH@;;6 @AH@șB @AH@H@O @BP@HVj[ @BP@ȴ$g @BP@t @BP@Hqg @BP@HS @BP@H- @BP@ȋD @BP@邎 @BP@HH=ؽ @BP@H! @CX@Hk @CX@bl @CX@& @CX@HH @CX@H} @CX@U @CX@9&  @CX@ȗo, @CX@H8 @CX@HT?E @D`@ȲLQ @D`@] @D`@nni @D`@H(*v @D`@H+s @D`@ȉ @D`@W @D`@HFQ @D`@H̚ @D`@H @Eh@`A. @Eh@Ⱦw @Eh@H! @Eh@H{p # @Eh@H*U% @Eh@7 ( @Eh@ȕ* @Eh@HY2", @Eh@HR|.. @Eh@Ȱ:0 @Fp@G2 @Fp@lCYS4 @Fp@H_6 @Fp@H)k8 @Fp@ȇr6x: @Fp@,< @Fp@Cɐ> @Fp@H@ @Fp@H\]B @Fp@^D @Gx@ȼF @Gx@H:H @Gx@HyEJ @Gx@HL @Gx@5N @Gx@ȓtaP @Gx@H. S @Gx@HPU @Gx@H>$W @Gx@ ^0Y @H@j<[ @H@HI] @H@H'eU_ @H@ȅGaa @H@mc @H@ABze @H@Hvg @H@H0֒i @H@\k @H@Ⱥim @I@`o @I@Hwq @I@HFs @I@3u @I@ȑIw @I@H$y @I@HNm| @I@Hx ~ @I@ 3 @I@hJ& @J@Hǧ2 @J@H%b> @J@ȃ(K @J@qW @J@H@c @J@HKp @J@HO| @J@Z @J@ȸz└ @J@H5, @K@Huu @K@ө @K@1d Ɯ @K@ȏSҞ @K@H؜ޠ @K@HL @K@ȪM0 @K@z @K@f @K@H|  @L@H#7W( @L@ȁ4 @L@߫@ @L@H>f4M @L@H ~Y @L@He @L@Xr @L@ȶO[~ @L@H @L@Hs @M@H~8 @M@/9 @M@ȍ˻ @M@H @M@HJh_ @M@Ȩ" @M@ @M@d< @M@HQ @M@H!  @N@ @N@݀c* @N@;;6 @N@HB @N@H@O @N@Vj[ @N@ȴ$g @N@Ht @N@Hqg @N@HS @O@- @O@ȋD @O@Hꂎ @O@HH=ؽ @O@H! @O@k @O@bl @O@H& @O@HH @O@} @P@U @P@9&  @P@Ho, @P@H8 @P@T?E @P@ȲLQ @P@] @P@Honi @P@H(*v @P@+s @QȀ@ȉ @QȀ@HW @QȀ@HFQ @QȀ@H̚ @QȀ@ @QȀ@`A. @QȀ@Hw @QȀ@H! @QȀ@H{p # @QȀ@*U% @RЀ@7 ( @RЀ@H* @RЀ@HY2", @RЀ@R|.. @RЀ@Ȱ:0 @RЀ@G2 @RЀ@HmCYS4 @RЀ@H_6 @RЀ@)k8 @RЀ@ȇr6x: @S؀@,< @S؀@HDɐ> @S؀@H@ @S؀@\]B @S؀@^D @S؀@HF @S؀@H:H @S؀@HyEJ @S؀@L @S؀@5N @T@HtaP @T@H. S @T@PU @T@Ȯ>$W @T@H ^0Y @T@Hk<[ @T@HI] @T@'eU_ @T@ȅGaa @T@Hmc @U@HBBze @U@Ƞvg @U@0֒i @U@\k @U@Him @U@H`o @U@wq @U@Fs @U@3u @U@HIw @V@H$y @V@Nm| @V@Ȭx ~ @V@H 3 @V@HiJ& @V@Hǧ2 @V@%b> @V@ȃ(K @V@HqW @V@H@c @W@HKp @W@O| @W@Z @W@Hz└ @W@H5, @W@uu @W@ө @W@1d Ɯ @W@HSҞ @W@H؜ޠ @X@L @X@ȪM0 @X@z @X@Hg @X@H|  @X@#7W( @X@ȁ4 @X@H@ @X@H>f4M @X@H ~Y @Y@e @Y@Xr @Y@HO[~ @Y@H @Y@Hs @Y@~8 @Y@/9 @Y@H˻ @Y@H @Y@Jh_ @Z@Ȩ" @Z@ @Z@He< @Z@HQ @Z@!  @Z@ @Z@݀c* @Z@H<;6 @Z@HB @Z@@O @[@Vj[ @[@H$g @[@Ht @[@Hqg @[@S @[@- @[@HD @[@Hꂎ @[@HH=ؽ @[@Ȧ! @\ @k @\ @Hcl @\ @H& @\ @H @\ @} @\ @U @\ @H:&  @\ @Ho, @\ @8 @\ @T?E @](@ȲLQ @](@H] @](@Honi @](@(*v @](@+s @](@H @](@HW @](@HFQ @](@Ȥ̚ @](@ @^0@HaA. @^0@Hw @^0@! @^0@{p # @^0@H*U% @^0@H8 ( @^0@H* @^0@Y2", @^0@R|.. @^0@H:0 @_8@HG2 @_8@mCYS4 @_8@_6 @_8@)k8 @_8@Hr6x: @_8@H,< @_8@Dɐ> @_8@Ȣ@ @_8@\]B @_8@H_D @`@@HF @`@@:H @`@@yEJ @`@@HL @`@@H6N @`@@HtaP @`@@. S @`@@PU @`@@H>$W @`@@H ^0Y @aH@Hk<[ @aH@I] @aH@'eU_ @aH@HGaa @aH@Hmc @aH@BBze @aH@Ƞvg @aH@0֒i @aH@H]k @aH@Him @bP@`o @bP@wq @bP@Fs @bP@H4u @bP@HIw @bP@$y @bP@Nm| @bP@Hx ~ @bP@H 3 @bP@HiJ& @cX@ǧ2 @cX@%b> @cX@H(K @cX@HqW @cX@H@c @cX@ȞKp @cX@O| @cX@H[ @cX@Hz└ @cX@5, @d`@uu @d`@ө @d`@H2d Ɯ @d`@HSҞ @d`@؜ޠ @d`@L @d`@ȪM0 @d`@H z @d`@Hg @d`@|  @eh@#7W( @eh@H4 @eh@H@ @eh@H>f4M @eh@Ȝ ~Y @eh@e @eh@HYr @eh@HO[~ @eh@H @eh@s @fp@~8 @fp@H09 @fp@H˻ @fp@ @fp@Jh_ @fp@Ȩ" @fp@H @fp@He< @fp@Q @fp@!  @gx@ @gx@Hހc* @gx@H<;6 @gx@ȚB @gx@@O @gx@HWj[ @gx@H$g @gx@Ht @gx@qg @gx@S @h@H. @h@HD @h@ꂎ @h@H=ؽ @h@H! @h@Hk @h@Hcl @h@& @h@H @h@H~ @i@HU @i@:&  @i@Șo, @i@8 @i@HU?E @i@HLQ @i@] @i@oni @i@(*v @i@H,s @j@H @j@W @j@FQ @j@H̚ @j@H @j@HaA. @j@ȿw @j@! @j@H|p # @j@H*U% @k@H8 ( @k@Ȗ* @k@Y2", @k@HS|.. @k@H:0 @k@G2 @k@mCYS4 @k@_6 @k@H*k8 @k@Hr6x: @l@,< @l@Dɐ> @l@Ȣ@ @l@H\]B @l@H_D @l@ȽF @l@:H @l@HzEJ @l@HL @l@H6N @m@ȔtaP @m@. S @m@HQU @m@H>$W @m@H ^0Y @m@k<[ @m@I] @m@H(eU_ @m@HGaa @m@mc @n@BBze @n@Ƞvg @n@H0֒i @n@H]k @n@Ȼim @n@`o @n@wq @n@HFs @n@H4u @n@ȒIw @o@$y @o@HOm| @o@Hx ~ @o@H 3 @o@iJ& @o@ǧ2 @o@H&b> @o@H(K @o@HqW @o@@c @p@ȞKp @p@HO| @p@H[ @p@ȹz└ @p@5, @p@uu @p@Hԩ @p@H2d Ɯ @p@ȐSҞ @p@؜ޠ @qȁ@L @qȁ@HM0 @qȁ@H z @qȁ@g @qȁ@|  @qȁ@H$7W( @qȁ@H4 @qȁ@H@ @qȁ@>f4M @qȁ@Ȝ ~Y @rЁ@He @rЁ@HYr @rЁ@ȷO[~ @rЁ@ @rЁ@Ht @rЁ@H~8 @rЁ@H09 @rЁ@Ȏ˻ @rЁ@ @rЁ@HKh_ @s؁@H" @s؁@ @s؁@e< @s؁@Q @s؁@H"  @s؁@H @s؁@ހc* @s؁@<;6 @s؁@ȚB @s؁@H@O @t@HWj[ @t@ȵ$g @t@t @t@Hrg @t@HS @t@H. @t@ȌD @t@ꂎ @t@HI=ؽ @t@H! @u@Hk @u@cl @u@& @u@H H @u@H~ @u@U @u@:& @u@Șo,@u@H8@u@HU?E@v@ȳLQ @v@] @v@oni @v@H(*v@v@H,s@v@Ȋ@v@W@v@HGQ@v@H̚@v@H@w@aA.@w@ȿw@w@H!@w@H|p #@w@H*U%@w@8 (@w@Ȗ*@w@HY2",@w@HS|..@w@ȱ:0@x@G2@x@mCYS4@x@H_6@x@H*k8@x@Ȉr6x:@x@,<@x@Dɐ>@x@H@@x@H\]B@x@_D@y@ȽF@y@H:H@y@HzEJ@y@HL@y@6N@y@ȔtaP@y@H. S@y@HQU@y@H>$W@y@ ^0Y@z@k<[@z@HI]@z@H(eU_@z@ȆGaa@z@mc@z@BBze@z@Hvg@z@H0֒i@z@]k@z@Ȼim@{@`o@{@Hxq@{@HFs@{@4u@{@ȒIw@{@H$y@{@HOm|@{@Hx ~@{@ 3@{@iJ&@| @Hȧ2@| @H&b>@| @Ȅ(K@| @qW@| @HAc@| @HKp@| @HO|@| @[@| @ȹz└@| @H5,@}(@Hvu@}(@ԩ@}(@2d Ɯ@}(@ȐSҞ@}(@H؜ޠ@}(@HM@}(@ȫM0@}(@ z@}(@g@}(@H| @~0@H$7W(@~0@Ȃ4@~0@@@~0@H?f4M@~0@H ~Y@~0@He@~0@Yr@~0@ȷO[~@~0@H @~0@Ht@8@H~8@8@09@8@Ȏ˻@8@H@8@HKh_@8@ȩ"@8@@8@e<@8@HQ@8@H" @@@Ȁ@@@ހc*@@@<;6@@@HB@@@H@O@@@Wj[@@@ȵ$g@@@Ht@@@Hrg@@@HS@H@.@H@ȌD@H@H낎@H@HI=ؽ@H@H!@H@k@H@cl@H@H&@H@H H@H@~@P@U@P@:& @P@Ho,@P@H8@P@U?E@P@ȳLQ @P@] @P@Hpni @P@H(*v@P@,s@X@Ȋ@X@HW@X@HGQ@X@H̚@X@@X@aA.@X@Hw@X@H!@X@H|p #@X@*U%@`@8 (@`@H*@`@HY2",@`@S|..@`@ȱ:0@`@G2@`@HnCYS4@`@H_6@`@*k8@`@Ȉr6x:@h@,<@h@HEɐ>@h@H@@h@\]B@h@_D@h@HF@h@H:H@h@HzEJ@h@L@h@6N@p@HtaP@p@H. S@p@QU@p@ȯ>$W@p@H^0Y@p@Hl<[@p@HI]@p@(eU_@p@ȆGaa@p@Hmc@x@HCBze@x@ȡvg@x@0֒i@x@]k@x@Him@x@H`o@x@xq@x@Fs@x@4u@x@HIw@@H$y@@Om|@@ȭx ~@@H 3@@HjJ&@@Hȧ2@@&b>@@Ȅ(K@@HqW@@HAc@@HKp@@O|@@[@@Hz└@@H5,@@vu@@ԩ@@2d Ɯ@@HSҞ@@H؜ޠ@@M@@ȫM0@@ z@@Hh@@H| @@$7W(@@Ȃ4@@H@@@H?f4M@@H ~Y@@e@@Yr@@HO[~@@H @@Ht@@~8@@09@@H˻@@H@@Kh_@@ȩ"@@@@Hf<@@HQ@@" @@Ȁ@@ހc*@@H=;6@@HB@@@O@@Wj[@@H$g@@Ht@@Hrg@@S@@.@@HD@@H낎@@HI=ؽ@@ȧ!@@k@@Hdl@@H&@@ H@@~@@U@@@@L7@@{\@@䪟@@|@@$ Zˮ@@$87@@dg@@d9@@^ @@ @@# @@Rf @@C @@$ @@$;@@d`@@d>@@m@@r@@O @@,@@) >@@$Yb@Ȃ@$ć#@Ȃ@d)@Ȃ@d~/@Ȃ@d\5@Ȃ@D9<@Ȃ@s@B@Ȃ@dH@Ȃ@ЉN @Ȃ@T!@Ȃ@$0Z"@Ђ@$_h`#@Ђ@dEg$@Ђ@d"Bm%@Ђ@fs&@Ђ@݋y'@Ђ@J(@Ђ@yՅ)@Ђ@t*@Ђ@$Q+@Ђ@$/D,@؂@$6 i-@؂@de鍤.@؂@dƲ/@؂@ãװ0@؂@1@؂@!^!2@؂@P;F3@؂@k4@؂@$5@؂@$Ҵ6@@d 7@@d<8@@dkj#9@@GH:@@$m;@@<@@'߶>@@$W?@@$ @@@$v%A@@dSJB@@d1oC@@B%D@@q+E@@1F@@ϥ8G@@'>H@@$.`LDI@@$]=qJJ@@dPK@@dVL@@d\M@@cN@@H)iO@@wlNoP@@IsuQ@@&{R@@$S@@$4T@@dcU@@d+V@@xPW@@UuX@@3Y@@NZ@@}[@@$\@@$ܧ-]@@$ R^@@d:bw_@@di?`@@a@@b@@ c@@%/d@@TTe@@$nyf@@$Kg@@d(i@@dj@@d@ k@@o1l@@Vm@@z{!n@@W'o@@$,5-p@@$[3q@@$:r@@d3@s@@dXFt@@}Lu@@FdRv@@uAXw@@^x@@$ey@@$5kz@@$2Zq{@@daw|@@dp}}@@MɃ~@@*@@@@L7@@{\@@$@@$|@@d Zˮ@@d87@@dg@@9@ @^lj@ @͊@ @#Ӌ@ @$Sfٌ@ @$Cߍ@ @$ @ @d;@ @d`@ @>@ @m@(@r@(@O @(@,@(@$* >@(@$Yb@(@dć#@(@d)@(@d~/@(@\5@(@D9<@0@s@B@0@dH@0@ЉN@0@$T@0@$0Z@0@d_h`@0@dEg@0@"Bm@0@fs@0@݋y@8@J@8@yՅ@8@$t@8@$Q@8@$/D@8@d6 i@8@de鍤@8@Ʋ@8@ãװ@8@@@@!^!@@@P;Fó@@@$kɴ@@@$ϵ@@@dҴն@@@d ۷@@@d<@@@kj#@@@GH@@@$m@H@@H@$(߶@H@$W@H@$ @H@dv%@H@dSJ@H@1o@H@B%@H@q+@H@1@P@ϥ8@P@$'>@P@$.`LD@P@d]=qJ@P@dP@P@dV@P@\@P@c@P@H)i@P@wlNo@X@Isu@X@$&{@X@$@X@d4@X@dc@X@+@X@xP@X@Uu@X@3@X@N@`@$~@`@$@`@dܧ-@`@d R@`@:bw@`@i?@`@@`@@`@ @`@$&/@ h@$UT@ h@dny@ h@dK@ h@d(@ h@@ h@@ @ h@o1@ h@䞝V@ h@z{!@ h@$W'@ p@$,5-@ p@d[3@ p@d:@ p@3@@ p@XF@ p@}L@ p@FdR@ p@uAX@ p@$^@ p@$e@ x@$5k@ x@d2Zq@ x@daw@ x@p}@ x@MɃ@ x@*@ x@@ x@L7@ x@$|\@ x@$@ @d|@ @d Zˮ@ @d87@ @g@ @9@ @^ @ @ @ @$$ @ @$Sf @ @$C @ @d @ @d;@ @`@ @>@ @m@ @r@ @O @ @$,@ @$* >@ @dYb@@dć#@@d)@@~/@@\5@@D9<@@s@B@@dH@@$ЉN @@$T!@@d0Z"@@d_h`#@@Eg$@@"Bm%@@fs&@@݋y'@@J(@@$zՅ)@@$t*@@$Q+@@d/D,@@d6 i-@@e鍤.@@Ʋ/@@ãװ0@@1@@!^!2@@$Q;F3@@$k4@@d5@@dҴ6@@d 7@@<8@@kj#9@@GH:@@$m;@@$<@@$(߶>@@$W?@@d @@@dv%A@@SJB@@1oC@@B%D@@q+E@@$1F@@$Х8G@@$'>H@@d.`LDI@@d]=qJJ@@PK@@VL@@\M@@cN@@H)iO@@$xlNoP@@$IsuQ@@d&{R@@dS@@d4T@@cU@@+V@@xPW@@UuX@@$ 3Y@@$OZ@@$~[@@d\@@dܧ-]@@ R^@@:bw_@ȃ@i?`@ȃ@a@ȃ@b@ȃ@$ c@ȃ@$&/d@ȃ@dUTe@ȃ@dnyf@ȃ@dKg@ȃ@(i@ȃ@j@Ѓ@@ k@Ѓ@o1l@Ѓ@䞝Vm@Ѓ@$z{!n@Ѓ@$W'o@Ѓ@d,5-p@Ѓ@d[3q@Ѓ@:r@Ѓ@3@s@Ѓ@XFt@؃@}Lu@؃@FdRv@؃@$vAXw@؃@$^x@؃@$ey@؃@d5kz@؃@d2Zq{@؃@aw|@؃@p}}@؃@MɃ~@@*@@@@$M7@@$|\@@d@@d|@@d Zˮ@@87@@g@@9@@^lj@@$͊@@$$Ӌ@@$Sfٌ@@dCߍ@@d @@;@@`@@>@@m@@r@@$O @@$,@@d* >@@dYb@@dć#@@)@@~/@@\5@@D9<@@s@B@@$dH@@$ЉN@@dT@@d0Z@@_h`@@Eg@@"Bm@@fs@@݋y@@$K@@$zՅ@@dt@@dQ@@/D@@6 i@@e鍤@@Ʋ@@ãװ@@$@@$"^!@@dQ;Fó@@dkɴ@@dϵ@@Ҵն@@ ۷@@<@@kj#@@GH@@$$m@@$@@d(߶@@dW@@ @@v%@@SJ@@1o@@B%@@$r+@@$1@@$Х8@@d'>@@d.`LD@@]=qJ@@P@@V@@\@@c@@$I)i@@$xlNo@ @dIsu@ @d&{@ @d@ @4@ @c@ @䒛+@ @xP@ @$Uu@ @$ 3@ @$O@!(@d~@!(@d@!(@ܧ-@!(@ R@!(@:bw@!(@i?@!(@@!(@$@!(@$ @!(@d&/@"0@dUT@"0@dny@"0@K@"0@(@"0@@"0@@ @"0@o1@"0@$V@"0@$z{!@"0@dW'@#8@d,5-@#8@[3@#8@:@#8@3@@#8@XF@#8@}L@#8@$GdR@#8@$vAX@#8@$^@#8@de@$@@d5k@$@@2Zq@$@@aw@$@@p}@$@@MɃ@$@@*@$@@$@$@@$M7@$@@d|\@$@@d@%H@d|@%H@ Zˮ@%H@87@%H@g@%H@9@%H@$^ @%H@$ @%H@$$ @%H@dSf @%H@dC @&P@ @&P@;@&P@`@&P@>@&P@$n@&P@$r@&P@$O @&P@d,@&P@d* >@&P@Yb@'X@ć#@'X@䷡)@'X@~/@'X@\5@'X@$E9<@'X@$t@B@'X@ddH@'X@dЉN @'X@dT!@'X@0Z"@(`@_h`#@(`@Eg$@(`@"Bm%@(`@$fs&@(`@$݋y'@(`@$K(@(`@dzՅ)@(`@dt*@(`@Q+@(`@/D,@)h@6 i-@)h@e鍤.@)h@Ʋ/@)h@$ģװ0@)h@$1@)h@d"^!2@)h@dQ;F3@)h@dk4@)h@5@)h@Ҵ6@*p@ 7@*p@<8@*p@kj#9@*p@$GH:@*p@$$m;@*p@d<@*p@d(߶>@*p@W?@*p@ @@*p@v%A@+x@SJB@+x@1oC@+x@$C%D@+x@$r+E@+x@$1F@+x@dХ8G@+x@d'>H@+x@.`LDI@+x@]=qJJ@+x@PK@,@VL@,@\M@,@$cN@,@$I)iO@,@dxlNoP@,@dIsuQ@,@d&{R@,@S@,@4T@,@cU@-@䒛+V@-@$xPW@-@$UuX@-@$ 3Y@-@dOZ@-@d~[@-@\@-@ܧ-]@-@ R^@-@:bw_@.@i?`@.@$a@.@$b@.@d c@.@d&/d@.@dUTe@.@nyf@.@Kg@.@(i@.@j@/@@ k@/@$p1l@/@$Vm@/@dz{!n@/@dW'o@/@,5-p@/@[3q@/@:r@/@3@s@/@XFt@0@$}Lu@0@$GdRv@0@dvAXw@0@d^x@0@ey@0@5kz@0@2Zq{@0@aw|@0@p}}@0@$MɃ~@1@$*@1@d@1@dM7@1@d|\@1@@1@|@1@ Zˮ@1@87@1@g@1@$9@2@$^lj@2@d͊@2@d$Ӌ@2@Sfٌ@2@Cߍ@2@ @2@;@2@`@2@$?@2@$n@3@$r@3@dO @3@d,@3@* >@3@Yb@3@ć#@3@䷡)@3@~/@3@$\5@3@$E9<@4@dt@B@4@ddH@4@dЉN@4@T@4@0Z@4@_h`@4@Eg@4@$"Bm@4@$fs@4@$݋y@5Ȅ@dK@5Ȅ@dzՅ@5Ȅ@t@5Ȅ@Q@5Ȅ@/D@5Ȅ@6 i@5Ȅ@e鍤@5Ȅ@$Ʋ@5Ȅ@$ģװ@5Ȅ@d@6Є@d"^!@6Є@dQ;Fó@6Є@kɴ@6Є@ϵ@6Є@Ҵն@6Є@ ۷@6Є@<@6Є@$lj#@6Є@$GH@6Є@d$m@7؄@d@7؄@(߶@7؄@W@7؄@ @7؄@v%@7؄@SJ@7؄@$1o@7؄@$C%@7؄@$r+@7؄@d1@8@dХ8@8@'>@8@.`LD@8@]=qJ@8@P@8@V@8@$\@8@$c@8@dI)i@8@dxlNo@9@dIsu@9@&{@9@@9@4@9@c@9@$+@9@$xP@9@$Uu@9@d 3@9@dO@:@~@:@@:@ܧ-@:@ R@:@$;bw@:@$j?@:@$@:@d@:@d @:@&/@;@UT@;@ny@;@K@;@(@;@$@;@$A @;@dp1@;@dV@;@dz{!@;@W'@<@,5-@<@[3@<@:@<@$3@@<@$XF@<@$}L@<@dGdR@<@dvAX@<@^@<@e@=@5k@=@2Zq@=@aw@=@$p}@=@$MɃ@=@d*@=@d@=@dM7@=@|\@=@@>@|@>@ Zˮ@>@87@>@$h@>@$9@>@d^ @>@d @>@$ @>@Sf @>@C @?@ @?@;@?@$`@?@$?@?@$n@?@dr@?@dO @?@,@?@* >@?@Yb@@ @ć#@@ @䷡)@@ @$~/@@ @$\5@@ @dE9<@@ @dt@B@@ @ddH@@ @ЉN @@ @T!@@ @0Z"@A(@_h`#@A(@$Eg$@A(@$"Bm%@A(@$fs&@A(@d݋y'@A(@dK(@A(@zՅ)@A(@t*@A(@Q+@A(@/D,@B0@6 i-@B0@$f鍤.@B0@$Ʋ/@B0@dģװ0@B0@d1@B0@d"^!2@B0@Q;F3@B0@k4@B0@5@B0@Ҵ6@C8@ 7@C8@$=8@C8@$lj#9@C8@dGH:@C8@d$m;@C8@<@C8@(߶>@C8@W?@C8@䆙 @@C8@v%A@D@@$SJB@D@@$1oC@D@@dC%D@D@@dr+E@D@@1F@D@@Х8G@D@@'>H@D@@.`LDI@D@@]=qJJ@D@@$PK@EH@$VL@EH@d\M@EH@dcN@EH@dI)iO@EH@xlNoP@EH@IsuQ@EH@&{R@EH@S@EH@4T@EH@$dU@FP@$+V@FP@dxPW@FP@dUuX@FP@ 3Y@FP@OZ@FP@~[@FP@\@FP@ܧ-]@FP@$ R^@FP@$;bw_@GX@$j?`@GX@da@GX@db@GX@ c@GX@&/d@GX@UTe@GX@nyf@GX@Kg@GX@$(i@GX@$j@H`@dA k@H`@dp1l@H`@dVm@H`@z{!n@H`@W'o@H`@,5-p@H`@[3q@H`@$:r@H`@$3@s@H`@$XFt@Ih@d}Lu@Ih@dGdRv@Ih@vAXw@Ih@^x@Ih@ey@Ih@5kz@Ih@2Zq{@Ih@$bw|@Ih@$p}}@Ih@dMɃ~@Jp@d*@Jp@d@Jp@M7@Jp@|\@Jp@䫟@Jp@|@Jp@ Zˮ@Jp@$97@Jp@$h@Jp@d9@Kx@d^lj@Kx@͊@Kx@$Ӌ@Kx@Sfٌ@Kx@Cߍ@Kx@ @Kx@$;@Kx@$`@Kx@$?@Kx@dn@L@dr@L@O @L@,@L@* >@L@Yb@L@ć#@L@$)@L@$~/@L@d\5@L@dE9<@M@dt@B@M@dH@M@ЉN@M@T@M@0Z@M@$`h`@M@$Eg@M@$"Bm@M@dfs@M@d݋y@N@K@N@zՅ@N@t@N@Q@N@$/D@N@$7 i@N@$f鍤@N@dƲ@N@dģװ@N@@O@"^!@O@Q;Fó@O@kɴ@O@ϵ@O@$Ҵն@O@$۷@O@d=@O@dlj#@O@dGH@O@$m@P@@P@(߶@P@W@P@$ @P@$v%@P@$SJ@P@d1o@P@dC%@P@r+@P@1@Q@Х8@Q@'>@Q@.`LD@Q@$^=qJ@Q@$P@Q@dV@Q@d\@Q@dc@Q@I)i@Q@xlNo@R@Isu@R@&{@R@@R@$5@R@$d@R@d+@R@dxP@R@Uu@R@ 3@R@O@S@~@S@@S@$ݧ-@S@$ R@S@$;bw@S@dj?@S@d@S@@S@ @S@&/@T@UT@T@ny@T@$K@T@$(@T@d@T@dA @T@dp1@T@V@T@z{!@T@W'@Uȅ@,5-@Uȅ@$\3@Uȅ@$:@Uȅ@$3@@Uȅ@dXF@Uȅ@d}L@Uȅ@GdR@Uȅ@vAX@Uȅ@^@Uȅ@e@VЅ@5k@VЅ@$3Zq@VЅ@$bw@VЅ@dp}@VЅ@dMɃ@VЅ@d*@VЅ@@VЅ@M7@VЅ@|\@VЅ@䫟@W؅@|@W؅@$ Zˮ@W؅@$97@W؅@dh@W؅@d9@W؅@^ @W؅@ @W؅@$ @W؅@Sf @W؅@C @X@$ @X@$;@X@d`@X@d?@X@n@X@r@X@O @X@,@X@* >@X@$Zb@Y@$ć#@Y@d)@Y@d~/@Y@d\5@Y@E9<@Y@t@B@Y@dH@Y@ЉN @Y@T!@Y@$1Z"@Z@$`h`#@Z@dEg$@Z@d"Bm%@Z@fs&@Z@݋y'@Z@K(@Z@zՅ)@Z@t*@Z@$Q+@Z@$/D,@[@$7 i-@[@df鍤.@[@dƲ/@[@ģװ0@[@1@[@"^!2@[@Q;F3@[@k4@[@$5@[@$Ҵ6@\@d7@\@d=8@\@dlj#9@\@GH:@\@$m;@\@<@\@(߶>@\@$X?@\@$ @@\@$v%A@]@dSJB@]@d1oC@]@C%D@]@r+E@]@1F@]@Х8G@]@'>H@]@$/`LDI@]@$^=qJJ@]@dPK@^@dVL@^@d\M@^@cN@^@I)iO@^@xlNoP@^@IsuQ@^@&{R@^@$S@^@$5T@^@ddU@_@d+V@_@xPW@_@UuX@_@ 3Y@_@OZ@_@~[@_@$\@_@$ݧ-]@_@$ R^@_@d;bw_@` @dj?`@` @a@` @b@` @ c@` @&/d@` @UTe@` @$nyf@` @$Kg@` @d(i@` @dj@a(@dA k@a(@p1l@a(@Vm@a(@z{!n@a(@W'o@a(@$-5-p@a(@$\3q@a(@$:r@a(@d3@s@a(@dXFt@b0@}Lu@b0@GdRv@b0@vAXw@b0@^x@b0@$ey@b0@$5kz@b0@$3Zq{@b0@dbw|@b0@dp}}@b0@MɃ~@c8@*@c8@@c8@M7@c8@|\@c8@$@c8@$|@c8@d Zˮ@c8@d97@c8@dh@c8@9@d@@^lj@d@@͊@d@@$Ӌ@d@@$Tfٌ@d@@$Cߍ@d@@$ @d@@d;@d@@d`@d@@?@d@@n@eH@r@eH@O @eH@,@eH@$+ >@eH@$Zb@eH@dć#@eH@d)@eH@d~/@eH@\5@eH@E9<@fP@t@B@fP@dH@fP@ЉN@fP@$T@fP@$1Z@fP@d`h`@fP@dEg@fP@"Bm@fP@fs@fP@݋y@gX@K@gX@zՅ@gX@$t@gX@$Q@gX@$/D@gX@d7 i@gX@df鍤@gX@Ʋ@gX@ģװ@gX@@h`@"^!@h`@Q;Fó@h`@$kɴ@h`@$ϵ@h`@dҴն@h`@d۷@h`@d=@h`@lj#@h`@GH@h`@$m@ih@@ih@$)߶@ih@$X@ih@$ @ih@dv%@ih@dSJ@ih@1o@ih@C%@ih@r+@ih@1@jp@Х8@jp@$'>@jp@$/`LD@jp@d^=qJ@jp@dP@jp@dV@jp@\@jp@c@jp@I)i@jp@xlNo@kx@Isu@kx@$&{@kx@$@kx@d5@kx@dd@kx@+@kx@xP@kx@Uu@kx@ 3@kx@O@l@$@l@$@l@dݧ-@l@d R@l@;bw@l@j?@l@@l@@l@ @l@$'/@ m@$VT@ m@dny@ m@dK@ m@d(@ m@@ m@A @ m@p1@ m@䟝V@ m@z{!@ m@$W'@ n@$-5-@ n@d\3@ n@d:@ n@3@@ n@XF@ n@}L@ n@GdR@ n@vAX@ n@$^@ n@$e@ o@$5k@ o@d3Zq@ o@dbw@ o@p}@ o@MɃ@ o@*@ o@@ o@M7@ o@$}\@ o@$@ p@d|@ p@d Zˮ@ p@d97@ p@h@ p@9@ p@^ @ p@ @ p@$% @ p@$Tf @ p@$C @ q@d @ q@d;@ q@`@ q@?@ q@n@ q@r@ q@O @ q@$,@ q@$+ >@ q@dZb@r@dć#@r@d)@r@~/@r@\5@r@E9<@r@t@B@r@dH@r@$ЉN @r@$T!@r@d1Z"@s@d`h`#@s@Eg$@s@"Bm%@s@fs&@s@݋y'@s@K(@s@${Յ)@s@$t*@s@$Q+@s@d/D,@t@d7 i-@t@f鍤.@t@Ʋ/@t@ģװ0@t@1@t@"^!2@t@$R;F3@t@$k4@t@d5@t@dҴ6@uȆ@d7@uȆ@=8@uȆ@lj#9@uȆ@GH:@uȆ@$m;@uȆ@$<@uȆ@$)߶>@uȆ@$X?@uȆ@d @@uȆ@dv%A@vІ@SJB@vІ@1oC@vІ@C%D@vІ@r+E@vІ@$1F@vІ@$ѥ8G@vІ@$'>H@vІ@d/`LDI@vІ@d^=qJJ@vІ@PK@w؆@VL@w؆@\M@w؆@cN@w؆@I)iO@w؆@$ylNoP@w؆@$IsuQ@w؆@d&{R@w؆@dS@w؆@d5T@w؆@dU@x@+V@x@xPW@x@UuX@x@$!3Y@x@$PZ@x@$[@x@d\@x@dݧ-]@x@ R^@x@;bw_@y@j?`@y@a@y@b@y@$ c@y@$'/d@y@dVTe@y@dnyf@y@dKg@y@(i@y@j@z@A k@z@p1l@z@䟝Vm@z@$z{!n@z@$W'o@z@d-5-p@z@d\3q@z@:r@z@3@s@z@XFt@{@}Lu@{@GdRv@{@$wAXw@{@$^x@{@$ey@{@d5kz@{@d3Zq{@{@bw|@{@p}}@{@MɃ~@|@*@|@@|@$N7@|@$}\@|@d@|@d|@|@d Zˮ@|@97@|@h@|@9@}@^lj@}@$͊@}@$%Ӌ@}@$Tfٌ@}@dCߍ@}@d @}@;@}@`@}@?@}@n@~@r@~@$O @~@$,@~@d+ >@~@dZb@~@dć#@~@)@~@~/@~@\5@~@E9<@@t@B@@$dH@@$ЉN@@dT@@d1Z@@`h`@@Eg@@"Bm@@fs@@݋y@ @$L@ @${Յ@ @dt@ @dQ@ @/D@ @7 i@ @f鍤@ @Ʋ@ @ģװ@ @$@(@$#^!@(@dR;Fó@(@dkɴ@(@dϵ@(@Ҵն@(@۷@(@=@(@lj#@(@GH@(@$$m@0@$@0@d)߶@0@dX@0@ @0@v%@0@SJ@0@1o@0@C%@0@$s+@0@$1@8@$ѥ8@8@d'>@8@d/`LD@8@^=qJ@8@P@8@V@8@\@8@c@8@$J)i@8@$ylNo@ @@dIsu@ @@d&{@ @@d@ @@5@ @@d@ @@䓛+@ @@xP@ @@$Uu@ @@$!3@ @@$P@!H@d@!H@d@!H@ݧ-@!H@ R@!H@;bw@!H@j?@!H@@!H@$@!H@$ @!H@d'/@"P@dVT@"P@dny@"P@K@"P@(@"P@@"P@A @"P@p1@"P@$V@"P@$z{!@"P@dW'@#X@d-5-@#X@\3@#X@:@#X@3@@#X@XF@#X@}L@#X@$HdR@#X@$wAX@#X@$^@#X@de@$`@d5k@$`@3Zq@$`@bw@$`@p}@$`@MɃ@$`@*@$`@$@$`@$N7@$`@d}\@$`@d@%h@d|@%h@ Zˮ@%h@97@%h@h@%h@9@%h@$^ @%h@$ @%h@$% @%h@dTf @%h@dC @&p@ @&p@;@&p@`@&p@?@&p@$o@&p@$r@&p@$O @&p@d,@&p@d+ >@&p@Zb@'x@ć#@'x@両)@'x@~/@'x@\5@'x@$F9<@'x@$u@B@'x@ddH@'x@dЉN @'x@dT!@'x@1Z"@(@`h`#@(@Eg$@(@"Bm%@(@$fs&@(@$݋y'@(@$L(@(@d{Յ)@(@dt*@(@Q+@(@/D,@)@7 i-@)@f鍤.@)@Ʋ/@)@$ţװ0@)@$1@)@d#^!2@)@dR;F3@)@dk4@)@5@)@Ҵ6@*@7@*@=8@*@lj#9@*@$GH:@*@$$m;@*@d<@*@d)߶>@*@X?@*@ @@*@v%A@+@SJB@+@1oC@+@$D%D@+@$s+E@+@$1F@+@dѥ8G@+@d'>H@+@/`LDI@+@^=qJJ@+@PK@,@VL@,@\M@,@$cN@,@$J)iO@,@dylNoP@,@dIsuQ@,@d&{R@,@S@,@5T@,@dU@-@䓛+V@-@$xPW@-@$UuX@-@$!3Y@-@dPZ@-@d[@-@\@-@ݧ-]@-@ R^@-@;bw_@.@j?`@.@$a@.@$b@.@d c@.@d'/d@.@dVTe@.@nyf@.@Kg@.@(i@.@j@/@A k@/@$q1l@/@$Vm@/@dz{!n@/@dW'o@/@-5-p@/@\3q@/@:r@/@3@s@/@XFt@0@$}Lu@0@$HdRv@0@dwAXw@0@d^x@0@ey@0@5kz@0@3Zq{@0@bw|@0@p}}@0@$MɃ~@1ȇ@$*@1ȇ@d@1ȇ@dN7@1ȇ@d}\@1ȇ@@1ȇ@|@1ȇ@ Zˮ@1ȇ@97@1ȇ@h@1ȇ@$9@2Ї@$^lj@2Ї@d͊@2Ї@d%Ӌ@2Ї@Tfٌ@2Ї@Cߍ@2Ї@ @2Ї@;@2Ї@`@2Ї@$@@2Ї@$o@3؇@$r@3؇@dO @3؇@d,@3؇@+ >@3؇@Zb@3؇@ć#@3؇@両)@3؇@~/@3؇@$\5@3؇@$F9<@4@du@B@4@ddH@4@dЉN@4@T@4@1Z@4@`h`@4@Eg@4@$"Bm@4@$fs@4@$݋y@5@dL@5@d{Յ@5@t@5@Q@5@/D@5@7 i@5@f鍤@5@$Ʋ@5@$ţװ@5@d@6@d#^!@6@dR;Fó@6@kɴ@6@ϵ@6@Ҵն@6@۷@6@=@6@$mj#@6@$GH@6@d$m@7@d@7@)߶@7@X@7@ @7@v%@7@SJ@7@$1o@7@$D%@7@$s+@7@d1@8@dѥ8@8@'>@8@/`LD@8@^=qJ@8@P@8@V@8@$\@8@$c@8@dJ)i@8@dylNo@9@dIsu@9@&{@9@@9@5@9@d@9@$+@9@$xP@9@$Uu@9@d!3@9@dP@:@@:@@:@ݧ-@:@ R@:@$0@|@>0@ Zˮ@>0@97@>0@$i@>0@$9@>0@d^ @>0@d @>0@% @>0@Tf @>0@C @?8@ @?8@;@?8@$`@?8@$@@?8@$o@?8@dr@?8@dO @?8@,@?8@+ >@?8@Zb@@@@ć#@@@@両)@@@@$~/@@@@$\5@@@@dF9<@@@@du@B@@@@ddH@@@@ЉN @@@@T!@@@@1Z"@AH@`h`#@AH@$Eg$@AH@$"Bm%@AH@$fs&@AH@d݋y'@AH@dL(@AH@{Յ)@AH@t*@AH@Q+@AH@/D,@BP@7 i-@BP@$g鍤.@BP@$Ʋ/@BP@dţװ0@BP@d1@BP@d#^!2@BP@R;F3@BP@k4@BP@5@BP@Ҵ6@CX@7@CX@$>8@CX@$mj#9@CX@dGH:@CX@d$m;@CX@<@CX@)߶>@CX@X?@CX@䇙 @@CX@v%A@D`@$SJB@D`@$1oC@D`@dD%D@D`@ds+E@D`@1F@D`@ѥ8G@D`@'>H@D`@/`LDI@D`@^=qJJ@D`@$PK@Eh@$VL@Eh@d\M@Eh@dcN@Eh@dJ)iO@Eh@ylNoP@Eh@IsuQ@Eh@&{R@Eh@S@Eh@5T@Eh@$eU@Fp@$+V@Fp@dxPW@Fp@dUuX@Fp@!3Y@Fp@PZ@Fp@[@Fp@\@Fp@ݧ-]@Fp@$ R^@Fp@$@L@Zb@L@ć#@L@$)@L@$~/@L@d\5@L@dF9<@M@du@B@M@dH@M@ЉN@M@T@M@1Z@M@$ah`@M@$Eg@M@$"Bm@M@dfs@M@d݋y@N@L@N@{Յ@N@t@N@Q@N@$ /D@N@$8 i@N@$g鍤@N@dƲ@N@dţװ@N@@O@#^!@O@R;Fó@O@kɴ@O@ϵ@O@$Ҵն@O@$۷@O@d>@O@dmj#@O@dGH@O@$m@P@@P@)߶@P@X@P@$ @P@$v%@P@$SJ@P@d1o@P@dD%@P@s+@P@1@QȈ@ѥ8@QȈ@'>@QȈ@/`LD@QȈ@$_=qJ@QȈ@$P@QȈ@dV@QȈ@d\@QȈ@dc@QȈ@J)i@QȈ@ylNo@RЈ@Isu@RЈ@&{@RЈ@@RЈ@$6@RЈ@$e@RЈ@d+@RЈ@dxP@RЈ@Uu@RЈ@!3@RЈ@P@S؈@@S؈@@S؈@$ާ-@S؈@$ R@S؈@$@X@$[b@Y@$ć#@Y@d)@Y@d~/@Y@d\5@Y@F9<@Y@u@B@Y@dH@Y@ЉN @Y@T!@Y@$2Z"@Z@$ah`#@Z@dEg$@Z@d"Bm%@Z@fs&@Z@݋y'@Z@L(@Z@{Յ)@Z@t*@Z@$Q+@Z@$ /D,@[@$8 i-@[@dg鍤.@[@dƲ/@[@ţװ0@[@1@[@#^!2@[@R;F3@[@k4@[@$5@[@$Ҵ6@\ @d7@\ @d>8@\ @dmj#9@\ @GH:@\ @$m;@\ @<@\ @)߶>@\ @$Y?@\ @$ @@\ @$v%A@](@dSJB@](@d1oC@](@D%D@](@s+E@](@1F@](@ѥ8G@](@'>H@](@$0`LDI@](@$_=qJJ@](@dPK@^0@dVL@^0@d\M@^0@cN@^0@J)iO@^0@ylNoP@^0@IsuQ@^0@&{R@^0@$S@^0@$6T@^0@deU@_8@d+V@_8@xPW@_8@UuX@_8@!3Y@_8@PZ@_8@[@_8@$\@_8@$ާ-]@_8@$ R^@_8@d@eh@$[b@eh@dć#@eh@d)@eh@d~/@eh@\5@eh@F9<@fp@u@B@fp@dH@fp@ЉN@fp@$T@fp@$2Z@fp@dah`@fp@dEg@fp@"Bm@fp@fs@fp@݋y@gx@L@gx@{Յ@gx@$t@gx@$Q@gx@$ /D@gx@d8 i@gx@dg鍤@gx@Ʋ@gx@ţװ@gx@@h@#^!@h@R;Fó@h@$kɴ@h@$ϵ@h@dҴն@h@d۷@h@d>@h@mj#@h@GH@h@$m@i@@i@$*߶@i@$Y@i@$ @i@dv%@i@dSJ@i@1o@i@D%@i@s+@i@1@j@ѥ8@j@$'>@j@$0`LD@j@d_=qJ@j@dP@j@dV@j@\@j@c@j@J)i@j@ylNo@k@Isu@k@$&{@k@$@k@d6@k@de@k@+@k@xP@k@Uu@k@!3@k@P@l@@l@$@l@$ާ-@l@d R@l@d@qȉ@$[b@rЉ@$ć#@rЉ@d)@rЉ@d~/@rЉ@\5@rЉ@F9<@rЉ@u@B@rЉ@dH@rЉ@ЉN @rЉ@$T!@rЉ@$2Z"@s؉@dah`#@s؉@dEg$@s؉@d"Bm%@s؉@fs&@s؉@݋y'@s؉@L(@s؉@{Յ)@s؉@t*@s؉@$Q+@s؉@$ /D,@t@d8 i-@t@dg鍤.@t@Ʋ/@t@ţװ0@t@1@t@#^!2@t@R;F3@t@$k4@t@$5@t@$Ҵ6@u@d7@u@d>8@u@mj#9@u@GH:@u@$m;@u@<@u@)߶>@u@$Y?@u@$ @@u@dv%A@v@dSJB@v@1oC@v@D%D@v@s+E@v@1F@v@ѥ8G@v@$'>H@v@$0`LDI@v@d_=qJJ@v@dPK@w@VL@w@\M@w@cN@w@J)iO@w@ylNoP@w@$IsuQ@w@$&{R@w@$S@w@d6T@w@deU@x@+V@x@xPW@x@UuX@x@!3Y@x@PZ@x@$[@x@$\@x@dާ-]@x@d R^@x@d@~0@$[b@~0@dć#@~0@d)@~0@~/@~0@\5@~0@F9<@8@u@B@8@dH@8@$ЉN@8@$T@8@d2Z@8@dah`@8@dEg@8@"Bm@8@fs@8@݋y@@@L@@@$|Յ@@@$t@@@dQ@@@d /D@@@d8 i@@@g鍤@@@Ʋ@@@ţװ@@@@H@$$^!@H@$S;Fó@H@$kɴ@H@dϵ@H@dҴն@H@۷@H@>@H@mj#@H@GH@H@$m@P@$@P@$*߶@P@dY@P@d @P@dv%@P@SJ@P@1o@P@D%@P@s+@P@1@X@$ҥ8@X@$'>@X@d0`LD@X@d_=qJ@X@P@X@V@X@\@X@c@X@J)i@X@$zlNo@`@$Isu@`@$&{@`@d@`@d6@`@e@`@+@`@xP@`@Uu@`@!3@`@$Q@h@$@h@d@h@dާ-@h@d R@h@@@d[b@@ć#@@)@@~/@@\5@@F9<@@$v@B@@$dH@@$ЉN @@dT!@@d2Z"@@ah`#@@Eg$@@"Bm%@@fs&@@݋y'@@$M(@@$|Յ)@@dt*@@dQ+@@d /D,@@8 i-@@g鍤.@@Ʋ/@@ţװ0@@$1@@$$^!2@@$S;F3@@dk4@@d5@@Ҵ6@@7@@>8@@mj#9@@GH:@@$$m;@@$<@@d*߶>@@dY?@@d @@@v%A@@SJB@@1oC@@D%D@@s+E@@$1F@@$ҥ8G@@d'>H@@d0`LDI@@_=qJJ@@PK@@VL@@\M@@cN@@$K)iO@@$zlNoP@@$IsuQ@@d&{R@@dS@@6T@@eU@Ȋ@䔛+V@Ȋ@xPW@Ȋ@UuX@Ȋ@$"3Y@Ȋ@$QZ@Ȋ@d[@Ȋ@d\@Ȋ@dާ-]@Ȋ@ R^@Ȋ@@@d[b@@dć#@@)@@~/@@\5@@F9<@@u@B@@$dH@@$ЉN@@dT@@d2Z@@ah`@@Eg@@"Bm@@fs@@݋y@@$M@@$|Յ@@$t@@dQ@@d /D@@8 i@@g鍤@@Ʋ@@ţװ@@@@$$^!@@$S;Fó@@dkɴ@@dϵ@@dҴն@@۷@@>@@mj#@@GH@@$$m@@$@@$*߶@@dY@@d @@v%@@SJ@@1o@@D%@@s+@@$1@ @$ҥ8@ @d'>@ @d0`LD@ @d_=qJ@ @P@ @V@ @\@ @c@ @J)i@ @$zlNo@(@$Isu@(@d&{@(@d@(@6@(@e@(@+@(@xP@(@Uu@(@$"3@(@$Q@0@d@0@d@0@dާ-@0@ R@0@@X@d[b@`@ć#@`@)@`@~/@`@\5@`@F9<@`@$v@B@`@$dH@`@dЉN @`@dT!@`@d2Z"@ h@ah`#@ h@Eg$@ h@"Bm%@ h@fs&@ h@݋y'@ h@$M(@ h@$|Յ)@ h@dt*@ h@dQ+@ h@ /D,@ p@8 i-@ p@g鍤.@ p@Ʋ/@ p@ţװ0@ p@$1@ p@$$^!2@ p@$S;F3@ p@dk4@ p@d5@ p@Ҵ6@ x@7@ x@>8@ x@mj#9@ x@GH:@ x@$$m;@ x@$<@ x@d*߶>@ x@dY?@ x@ @@ x@v%A@ @SJB@ @1oC@ @D%D@ @$t+E@ @$1F@ @dҥ8G@ @d'>H@ @0`LDI@ @_=qJJ@ @PK@ @VL@ @\M@ @$cN@ @$K)iO@ @$zlNoP@ @dIsuQ@ @d&{R@ @S@ @6T@ @eU@@䔛+V@@xPW@@$UuX@@$"3Y@@dQZ@@d[@@d\@@ާ-]@@ R^@@@@[b@@ć#@@)@@~/@@\5@@$G9<@ȋ@$v@B@ȋ@ddH@ȋ@dЉN@ȋ@dT@ȋ@2Z@ȋ@ah`@ȋ@Eg@ȋ@"Bm@ȋ@$fs@ȋ@$݋y@Ћ@dM@Ћ@d|Յ@Ћ@dt@Ћ@Q@Ћ@ /D@Ћ@8 i@Ћ@g鍤@Ћ@$Ʋ@Ћ@$ƣװ@Ћ@$@؋@d$^!@؋@dS;Fó@؋@kɴ@؋@ϵ@؋@Ҵն@؋@۷@؋@>@؋@$nj#@؋@$GH@؋@d$m@@d@@d*߶@@Y@@ @@v%@@SJ@@1o@@$E%@@$t+@@d1@@dҥ8@@'>@@0`LD@@_=qJ@@P@@V@@$\@@$c@@$K)i@@dzlNo@@dIsu@@&{@@@@6@@e@@䔛+@@$xP@@$Uu@@d"3@@dQ@@d@@@@ާ-@@ R@@@ @[b@!(@ć#@!(@乡)@!(@$~/@!(@$\5@!(@$G9<@!(@dv@B@!(@ddH@!(@ЉN @!(@T!@!(@2Z"@"0@ah`#@"0@Eg$@"0@$"Bm%@"0@$fs&@"0@d݋y'@"0@dM(@"0@d|Յ)@"0@t*@"0@Q+@"0@ /D,@#8@8 i-@#8@$h鍤.@#8@$Ʋ/@#8@$ƣװ0@#8@d1@#8@d$^!2@#8@S;F3@#8@k4@#8@5@#8@Ҵ6@$@@7@$@@$?8@$@@$nj#9@$@@dGH:@$@@d$m;@$@@d<@$@@*߶>@$@@Y?@$@@䈙 @@$@@v%A@%H@SJB@%H@$1oC@%H@$E%D@%H@dt+E@%H@d1F@%H@ҥ8G@%H@'>H@%H@0`LDI@%H@_=qJJ@%H@PK@&P@$VL@&P@$\M@&P@$cN@&P@dK)iO@&P@dzlNoP@&P@IsuQ@&P@&{R@&P@S@&P@6T@&P@eU@'X@$+V@'X@$xPW@'X@dUuX@'X@d"3Y@'X@dQZ@'X@[@'X@\@'X@ާ-]@'X@ R^@'X@$=bw_@(`@$l?`@(`@$a@(`@db@(`@d c@(`@(/d@(`@WTe@(`@nyf@(`@Kg@(`@(i@(`@$j@)h@$C k@)h@dr1l@)h@dVm@)h@dz{!n@)h@W'o@)h@.5-p@)h@]3q@)h@:r@)h@$3@s@)h@$XFt@*p@d}Lu@*p@dIdRv@*p@dxAXw@*p@^x@*p@ey@*p@5kz@*p@4Zq{@*p@$dw|@*p@$p}}@*p@$MɃ~@+x@d*@+x@d @+x@O7@+x@~\@+x@@+x@|@+x@ Zˮ@+x@$;7@+x@$j@+x@d9@,@d^lj@,@d͊@,@&Ӌ@,@Ufٌ@,@Cߍ@,@ @,@;@,@$`@,@$A@,@dp@-@dr@-@O @-@,@-@, >@-@[b@-@ć#@-@$)@-@$~/@-@$\5@-@dG9<@.@dv@B@.@dH@.@ЉN@.@T@.@2Z@.@ah`@.@$Eg@.@$"Bm@.@dfs@.@d݋y@/@dM@/@|Յ@/@t@/@Q@/@ /D@/@$9 i@/@$h鍤@/@$Ʋ@/@dƣװ@/@d@0@$^!@0@S;Fó@0@kɴ@0@ϵ@0@Ҵն@0@$۷@0@$?@0@dnj#@0@dGH@0@d$m@1@@1@*߶@1@Y@1@䈙 @1@v%@1@$SJ@1@$1o@1@dE%@1@dt+@1@1@2@ҥ8@2@'>@2@0`LD@2@_=qJ@2@$P@2@$V@2@$\@2@dc@2@dK)i@2@zlNo@3@Isu@3@&{@3@@3@6@3@$f@3@$+@3@dxP@3@dUu@3@"3@3@Q@4@@4@@4@ާ-@4@$R@4@$=bw@4@dl?@4@d@4@@4@ @4@(/@5Ȍ@WT@5Ȍ@ny@5Ȍ@$K@5Ȍ@$(@5Ȍ@$@5Ȍ@dC @5Ȍ@dr1@5Ȍ@V@5Ȍ@z{!@5Ȍ@W'@6Ќ@.5-@6Ќ@]3@6Ќ@$:@6Ќ@$3@@6Ќ@dXF@6Ќ@d}L@6Ќ@dIdR@6Ќ@xAX@6Ќ@^@6Ќ@e@7،@5k@7،@$5Zq@7،@$dw@7،@$p}@7،@dMɃ@7،@d*@7،@ @7،@O7@7،@~\@7،@䭟@8@|@8@$ Zˮ@8@$;7@8@dj@8@d9@8@d^ @8@ @8@& @8@Uf @8@C @9@ @9@$;@9@$`@9@dA@9@dp@9@r@9@O @9@,@9@, >@9@[b@:@$ć#@:@$)@:@$~/@:@d\5@:@dG9<@:@v@B@:@dH@:@ЉN @:@T!@:@2Z"@;@$bh`#@;@$Eg$@;@d"Bm%@;@dfs&@;@d݋y'@;@M(@;@|Յ)@;@t*@;@Q+@;@$ /D,@<@$9 i-@<@$h鍤.@<@dƲ/@<@dƣװ0@<@1@<@$^!2@<@S;F3@<@k4@<@5@<@$Ҵ6@=@$7@=@d?8@=@dnj#9@=@dGH:@=@$m;@=@<@=@*߶>@=@Y?@=@$ @@=@$v%A@>@dSJB@>@d1oC@>@dE%D@>@t+E@>@1F@>@ҥ8G@>@'>H@>@$1`LDI@>@$`=qJJ@>@$PK@?@dVL@?@d\M@?@cN@?@K)iO@?@zlNoP@?@IsuQ@?@&{R@?@$S@?@$7T@?@dfU@@ @d+V@@ @dxPW@@ @UuX@@ @"3Y@@ @QZ@@ @[@@ @\@@ @$ߧ-]@@ @$R^@@ @d=bw_@A(@dl?`@A(@a@A(@b@A(@ c@A(@(/d@A(@WTe@A(@$nyf@A(@$Kg@A(@$(i@A(@dj@B0@dC k@B0@r1l@B0@Vm@B0@z{!n@B0@W'o@B0@.5-p@B0@$^3q@B0@$:r@B0@d3@s@B0@dXFt@C8@d}Lu@C8@IdRv@C8@xAXw@C8@^x@C8@ey@C8@$5kz@C8@$5Zq{@C8@$dw|@C8@dp}}@C8@dMɃ~@D@@*@D@@ @D@@O7@D@@~\@D@@䭟@D@@$|@D@@$ Zˮ@D@@d;7@D@@dj@D@@d9@EH@^lj@EH@͊@EH@&Ӌ@EH@Ufٌ@EH@Cߍ@EH@$ @EH@$;@EH@d`@EH@dA@EH@p@FP@r@FP@O @FP@,@FP@, >@FP@$\b@FP@$ć#@FP@$)@FP@d~/@FP@d\5@FP@G9<@GX@v@B@GX@dH@GX@ЉN@GX@T@GX@$3Z@GX@$bh`@GX@dEg@GX@d"Bm@GX@fs@GX@݋y@H`@M@H`@|Յ@H`@t@H`@$Q@H`@$ /D@H`@d9 i@H`@dh鍤@H`@Ʋ@H`@ƣװ@H`@@Ih@$^!@Ih@S;Fó@Ih@$kɴ@Ih@$ϵ@Ih@$Ҵն@Ih@d۷@Ih@d?@Ih@nj#@Ih@GH@Ih@$m@Jp@@Jp@*߶@Jp@$Z@Jp@$ @Jp@dv%@Jp@dSJ@Jp@d1o@Jp@E%@Jp@t+@Jp@1@Kx@ҥ8@Kx@$'>@Kx@$1`LD@Kx@$`=qJ@Kx@dP@Kx@dV@Kx@\@Kx@c@Kx@K)i@Kx@zlNo@L@Isu@L@$&{@L@$@L@d7@L@df@L@d+@L@xP@L@Uu@L@"3@L@Q@M@@M@$@M@$ߧ-@M@dR@M@d=bw@M@l?@M@@M@@M@ @M@(/@N@$XT@N@$ny@N@$K@N@d(@N@d@N@C @N@r1@N@䡝V@N@z{!@N@W'@O@$/5-@O@$^3@O@d:@O@d3@@O@dXF@O@}L@O@IdR@O@xAX@O@^@O@$e@P@$5k@P@$5Zq@P@ddw@P@dp}@P@MɃ@P@*@P@ @P@O7@P@~\@P@$@Q@$|@Q@d Zˮ@Q@d;7@Q@dj@Q@9@Q@^ @Q@ @Q@& @Q@$Vf @Q@$C @R@d @R@d;@R@d`@R@A@R@p@R@r@R@O @R@$,@R@$- >@R@$\b@S@dć#@S@d)@S@~/@S@\5@S@G9<@S@v@B@S@dH@S@$ЉN @S@$T!@S@d3Z"@T@dbh`#@T@dEg$@T@"Bm%@T@fs&@T@݋y'@T@M(@T@|Յ)@T@$t*@T@$Q+@T@d /D,@Uȍ@d9 i-@Uȍ@h鍤.@Uȍ@Ʋ/@Uȍ@ƣװ0@Uȍ@1@Uȍ@$^!2@Uȍ@$T;F3@Uȍ@$k4@Uȍ@$5@Uȍ@dҴ6@VЍ@d7@VЍ@?8@VЍ@nj#9@VЍ@GH:@VЍ@$m;@VЍ@<@VЍ@$+߶>@VЍ@$Z?@VЍ@d @@VЍ@dv%A@W؍@dSJB@W؍@1oC@W؍@E%D@W؍@t+E@W؍@1F@W؍@$ӥ8G@W؍@$'>H@W؍@$1`LDI@W؍@d`=qJJ@W؍@dPK@X@VL@X@\M@X@cN@X@K)iO@X@zlNoP@X@$IsuQ@X@$&{R@X@dS@X@d7T@X@dfU@Y@+V@Y@xPW@Y@UuX@Y@"3Y@Y@QZ@Y@$[@Y@$\@Y@dߧ-]@Y@dR^@Y@=bw_@Z@l?`@Z@a@Z@b@Z@ c@Z@$)/d@Z@$XTe@Z@$nyf@Z@dKg@Z@d(i@Z@j@[@C k@[@r1l@[@䡝Vm@[@z{!n@[@$X'o@[@$/5-p@[@d^3q@[@d:r@[@3@s@[@XFt@\@}Lu@\@IdRv@\@xAXw@\@$^x@\@$ey@\@d5kz@\@d5Zq{@\@dw|@\@p}}@\@MɃ~@]@*@]@ @]@$P7@]@$\@]@$@]@d|@]@d Zˮ@]@;7@]@j@]@9@^@^lj@^@͊@^@$'Ӌ@^@$Vfٌ@^@dCߍ@^@d @^@d;@^@`@^@A@^@p@_@r@_@$O @_@$,@_@$- >@_@d\b@_@dć#@_@)@_@~/@_@\5@_@G9<@` @v@B@` @$dH@` @$ЉN@` @dT@` @d3Z@` @dbh`@` @Eg@` @"Bm@` @fs@` @݋y@a(@M@a(@$}Յ@a(@$t@a(@dQ@a(@d /D@a(@9 i@a(@h鍤@a(@Ʋ@a(@ƣװ@a(@@b0@$%^!@b0@$T;Fó@b0@$kɴ@b0@dϵ@b0@dҴն@b0@۷@b0@?@b0@nj#@b0@GH@b0@$m@c8@$@c8@$+߶@c8@dZ@c8@d @c8@dv%@c8@SJ@c8@1o@c8@E%@c8@t+@c8@$1@d@@$ӥ8@d@@$'>@d@@d1`LD@d@@d`=qJ@d@@P@d@@V@d@@\@d@@c@d@@K)i@d@@${lNo@eH@$Isu@eH@d&{@eH@d@eH@d7@eH@f@eH@+@eH@xP@eH@Uu@eH@$#3@eH@$R@fP@d@fP@d@fP@dߧ-@fP@R@fP@=bw@fP@l?@fP@@fP@$@fP@$ @fP@$)/@gX@dXT@gX@dny@gX@K@gX@(@gX@@gX@C @gX@r1@gX@$V@gX@$z{!@gX@dX'@h`@d/5-@h`@d^3@h`@:@h`@3@@h`@XF@h`@}L@h`@IdR@h`@$yAX@h`@$^@h`@de@ih@d5k@ih@5Zq@ih@dw@ih@p}@ih@MɃ@ih@*@ih@$!@ih@$P7@ih@$\@ih@d@jp@d|@jp@ Zˮ@jp@;7@jp@j@jp@9@jp@^ @jp@$ @jp@$' @jp@dVf @jp@dC @kx@d @kx@;@kx@`@kx@A@kx@p@kx@$r@kx@$O @kx@$,@kx@d- >@kx@d\b@l@ć#@l@)@l@~/@l@\5@l@G9<@l@$w@B@l@$dH@l@dЉN @l@dT!@l@d3Z"@ m@bh`#@ m@Eg$@ m@"Bm%@ m@fs&@ m@݋y'@ m@$N(@ m@$}Յ)@ m@dt*@ m@dQ+@ m@ /D,@ n@9 i-@ n@h鍤.@ n@Ʋ/@ n@ƣװ0@ n@$1@ n@$%^!2@ n@$T;F3@ n@dk4@ n@d5@ n@Ҵ6@ o@7@ o@?8@ o@nj#9@ o@GH:@ o@$$m;@ o@$<@ o@d+߶>@ o@dZ?@ o@ @@ o@v%A@ p@SJB@ p@1oC@ p@E%D@ p@$u+E@ p@$1F@ p@dӥ8G@ p@d'>H@ p@1`LDI@ p@`=qJJ@ p@PK@ q@VL@ q@\M@ q@$cN@ q@$L)iO@ q@${lNoP@ q@dIsuQ@ q@d&{R@ q@S@ q@7T@ q@fU@r@䕛+V@r@xPW@r@$UuX@r@$#3Y@r@dRZ@r@d[@r@d\@r@ߧ-]@r@R^@r@=bw_@s@l?`@s@$a@s@$b@s@$ c@s@d)/d@s@dXTe@s@nyf@s@Kg@s@(i@s@j@t@C k@t@$s1l@t@$Vm@t@dz{!n@t@dX'o@t@d/5-p@t@^3q@t@:r@t@3@s@t@XFt@uȎ@}Lu@uȎ@$JdRv@uȎ@$yAXw@uȎ@d^x@uȎ@dey@uȎ@5kz@uȎ@5Zq{@uȎ@dw|@uȎ@p}}@uȎ@MɃ~@vЎ@$*@vЎ@$!@vЎ@$P7@vЎ@d\@vЎ@d@vЎ@|@vЎ@ Zˮ@vЎ@;7@vЎ@j@vЎ@9@w؎@$^lj@w؎@$͊@w؎@d'Ӌ@w؎@dVfٌ@w؎@dCߍ@w؎@ @w؎@;@w؎@`@w؎@A@w؎@$q@x@$r@x@$O @x@d,@x@d- >@x@\b@x@ć#@x@)@x@~/@x@\5@x@$H9<@y@$w@B@y@ddH@y@dЉN@y@dT@y@3Z@y@bh`@y@Eg@y@"Bm@y@$fs@y@$݋y@z@dN@z@d}Յ@z@dt@z@Q@z@ /D@z@9 i@z@h鍤@z@$Ʋ@z@$ǣװ@z@$@{@d%^!@{@dT;Fó@{@kɴ@{@ϵ@{@Ҵն@{@۷@{@?@{@$oj#@{@$GH@{@d$m@|@d@|@d+߶@|@Z@|@ @|@v%@|@SJ@|@1o@|@$F%@|@$u+@|@d1@}@dӥ8@}@'>@}@1`LD@}@`=qJ@}@P@}@V@}@$\@}@$c@}@$L)i@}@d{lNo@~@dIsu@~@&{@~@@~@7@~@f@~@䕛+@~@$xP@~@$Uu@~@d#3@~@dR@@d@@@@ߧ-@@R@@=bw@@$m?@@$@@$@@d @@d)/@ @XT@ @ny@ @K@ @(@ @@ @$D @ @$s1@ @dV@ @dz{!@ @dX'@(@/5-@(@^3@(@:@(@3@@(@XF@(@$}L@(@$JdR@(@dyAX@(@d^@(@e@0@5k@0@5Zq@0@dw@0@p}@0@$MɃ@0@$*@0@ H @0@2 @0@?a.N @0@R@ @8@n>ST @8@re @8@xZ @8@r5 @8@` @8@dg @8@2f @8@D @8@R+l @8@! @ rZ s @  @ rm0y @ !B @ JU @ 2Pg @ 'z @ R @  @ Rs @!?EÑ @!?rP @!?u @!? . @!?  @!?; ! @!?2y2 @!?jD' @!?RWW @!?i- @"@r14| @"@Ȣ3 @"@` @"@9 @"@ż @"@2']? @"@ @"@RV:E @"@ @"@r"L @#@4 @#@FR @#@LcY @#@kX @#@2{@~ @#@^ @#@R @#@Ad @#@R @#@pij @$@r @$@Fp @$@7 @$@2#$w @$@f6 @$@2I} @$@ҕo[ @$@R-m @$@L @$@r\ @%@) ! @%@! @%@#" @%@uܕ" @%@2R# @%@R# @%@R$ @%@0&$ @%@r8%% @%@G K% @&@{]+& @&@wo& @&@Y1' @&@2ǔ' @&@=67( @&@Rդ( @&@l=) @&@r) @&@C* @&@r3_* @'@J+ @'@b<(+ @'@2:P, @'@M, @'@2)_V- @'@q- @'@RXe\. @'@Ӗ. @'@rBb/ @'@/ @( @h0 @( @N0 @( @n1 @( @2}k1 @( @u2 @( @RH*2 @( @C<{3 @( @r%O3 @( @ra4 @( @ t5 @)"@q5 @)"@9 6 @)"@2N6 @)"@h7 @)"@R,Г7 @)"@җ8 @)"@r/ 8 @)"@w9 @)"@^9 @)"@T,#: @*$@>: @*$@2%2Q); @*$@c; @*$@RTv/< @*$@}< @*$@r5= @*$@[= @*$@ɿ;> @*$@J8Ҿ> @*$@A? @+&@2y? @+&@ H@ @+&@R@ @+&@?a.NA @+&@R@A @+&@n>STB @+&@reB @+&@xZC @+&@5C @+&@2`D @,(@dgD @,(@2fE @,(@ғDE @,(@R+lF @,(@!F @,(@rZ sG @,(@G @,(@m0yH @,(@!BH @,(@JUI @-*@2PgJ @-*@'zJ @-*@RK @-*@K @-*@rsL @-*@EÑL @-*@PM @-*@uM @-*@ .N @-*@2 N @.,@; !O @.,@Ry2O @.,@jD'P @.,@rWWP @.,@i-Q @.,@r14|Q @.,@ɢ3R @.,@`R @.,@29S @.,@żS @/.@2']?T @/.@ҾT @/.@RV:EU @/.@U @/.@r"LV @/.@4V @/.@FRW @/.@LcYW @/.@kXX @/.@2{@~X @00@^Y @00@RY @00@AdZ @00@rZ @00@pij[ @00@[ @00@Fp\ @00@7\ @00@2#$w] @00@f6] @11@RI}^ @11@ҕo[_ @11@r-m_ @11@L` @11@r\` @11@) a @11@a @11@2#b @11@uܕb @11@RRc @22@Rc @22@Rd @22@0&d @22@r8%e @22@H Ke @22@{]+f @22@wof @22@Y1g @22@2ǔg @22@=67h @33@Rդh @33@l=i @33@ri @33@Cj @33@3_j @33@Jk @33@b<(k @33@2:Pl @33@ґMl @33@R)_Vm @44@qm @44@rXe\n @44@Ӗn @44@Bbo @44@o @44@hp @44@2Np @44@nq @44@R}kq @44@ur @55@rH*r @55@C<{s @55@%Os @55@sat @55@ tu @55@2qu @55@9 v @55@RNv @55@hw @55@r,Гw @66@x @66@r/ x @66@wy @66@^y @66@2T,#z @66@>z @66@2%2Q){ @66@Ҽc{ @66@RTv/| @66@}| @77@r5} @77@[} @77@ɿ;~ @77@J8Ҿ~ @77@A @77@2y @77@ H @77@Rˀ @77@?a.N @77@r@с @88@n>ST @88@eׂ @88@xZ @88@5݃ @88@2` @88@dg @88@Rf @88@ғD @88@r+l @88@! @99@rZ s @99@ @99@m0y @99@2!B @99@JU @99@RPg @99@'z @99@R @99@ @99@rs @::@FÑ @::@P @::@u藍 @::@ . @::@2 @::@; ! @::@Ry2 @::@jD' @::@rWW @::@i- @;;@14| @;;@ɢ3 @;;@` @;;@29 @;;@ż @;;@R']? @;;@Ҿ” @;;@rV:E @;;@ɕ @;;@"L @<<@4ϖ @<<@FR @<<@2LcY՗ @<<@kX @<<@R{@~ۘ @<<@^ @<<@R @<<@Ad @<<@r @<<@qij @==@ @==@2Fp @==@7 @==@2#$w @==@f6 @==@RI} @==@o[ @==@r-m @==@L @==@\ @>>@2) @>>@ @>>@2# @>>@Һuܕ @>>@RR @>>@R @>>@r @>>@0& @>>@8% @>>@H K @??@{]+ @??@2wo @??@Y1 @??@Rǔ @??@=67 @??@rդ @??@l= @??@ @??@C @??@3_Ǫ @@@@2J @@@@b<(ͫ @@@@R:P @@@@ґMӬ @@@@r)_V @@@@q٭ @@@@rXe\ @@@@Ӗ߮ @@@@Bb @@@@2 @A@@h @A@@RN @A@@n @A@@R}k @A@@u @A@@rH* @A@@D<{ @A@@%O @A@@sa @A@@ t @BA@2q @BA@9 @BA@RN @BA@h @BA@r,Г @BA@ @BA@/ @BA@w @BA@^ @BA@2T,# @CA@> @CA@R%2Q) @CA@Ҽc @CA@rTv/ @CA@} @CA@5 @CA@[ @CA@ɿ; @CA@2J8Ҿ @CA@A @DB@RyĿ @DB@ H @DB@R @DB@?a.N @DB@r@ @DB@o>ST @DB@e @DB@2xZ @DB@5 @DB@2` @EB@dg @EB@Rf @EB@D @EB@r+l @EB@! @EB@Z s @EB@ @EB@m0y @EB@2!B @EB@ҸJU @FC@RPg @FC@'z @FC@r @FC@ @FC@s @FC@FÑ @FC@P @FC@2u @FC@ . @FC@R @GC@; ! @GC@ry2 @GC@jD' @GC@rWW @GC@i- @GC@14| @GC@2ɢ3 @GC@` @GC@R9 @GC@ҏż @HD@r']? @HD@ @HD@rV:E @HD@ @HD@"L @HD@24 @HD@FR @HD@RLcY @HD@kX @HD@R{@~ @ID@^ @ID@r @ID@Bd @ID@ @ID@qij @ID@ @ID@2Fp @ID@7 @ID@R#$w @ID@f6 @JE@rI} @JE@o[ @JE@-m @JE@L @JE@\ @JE@2) @JE@ @JE@R# @JE@Һuܕ @JE@rR @KE@R @KE@ @KE@0& @KE@8% @KE@2H K @KE@{]+ @KE@Rwo @KE@Y1 @KE@Rǔ @KE@=67 @LF@rդ @LF@m= @LF@ @LF@2C @LF@3_ @LF@2J @LF@b<( @LF@R:P @LF@M @LF@r)_V @MF@q @MF@Xe\ @MF@Ӗ @MF@Bb @MF@2 @MF@Ҷh @MF@RN @MF@n @MF@r}k @MF@u @NG@H* @NG@D<{ @NG@%O @NG@2sa @NG@ t @NG@Rq @NG@9 @NG@rN @NG@h @NG@r,Г @OG@ @OG@/ @OG@2w @OG@^ @OG@2T,# @OG@ҍ> @OG@R%2Q) @OG@c @OG@rTv/ @OG@} @PH@5 @PH@[ @PH@ɿ; @PH@2J8Ҿ @PH@A @PH@Ry @PH@ H!@PH@r!@PH@?a.N!@PH@@!@QH@o>ST!@QH@e!@QH@2xZ!@QH@5!@QH@R`!@QH@dg!@QH@rf!@QH@D!@QH@+l!@QH@!!@RI@Z s!@RI@2!@RI@m0y!@RI@R!B!@RI@ҸJU !@RI@rPg !@RI@'z !@RI@ !@RI@ !@RI@s !@SI@2FÑ !@SI@P !@SI@Ru !@SI@ .!@SI@R !@SI@; !!@SI@ry2!@SI@kD'!@SI@WW!@SI@2i-!@TJ@14|!@TJ@2ɢ3!@TJ@`!@TJ@R9!@TJ@ż!@TJ@r']?!@TJ@!@TJ@V:E!@TJ@!@TJ@"L!@UJ@24!@UJ@ҴFR!@UJ@RLcY!@UJ@kX!@UJ@r{@~!@UJ@^!@UJ@!@UJ@Bd!@UJ@!@UJ@2qij!@VK@!@VK@RFp!@VK@7!@VK@r#$w!@VK@f6!@VK@rI}!@VK@o[!@VK@-m!@VK@2L !@VK@\ !@WK@2) !!@WK@ҋ!!@WK@R#"!@WK@uܕ"!@WK@rR#!@WK@R#!@WK@$!@WK@0&$!@WK@8%%!@WK@2H K%!@XL@{]+&!@XL@Rwo&!@XL@Y1'!@XL@rǔ'!@XL@=67(!@XL@դ(!@XL@m=)!@XL@)!@XL@2C*!@XL@3_*!@YL@RJ+!@YL@b<(+!@YL@r:P,!@YL@M,!@YL@r)_V-!@YL@q-!@YL@Xe\.!@YL@2Ӗ.!@YL@Bb/!@YL@R/!@ZM@Ҷh0!@ZM@RN0!@ZM@n1!@ZM@r}k1!@ZM@u2!@ZM@H*2!@ZM@D<{3!@ZM@%O3!@ZM@2sa4!@ZM@ t5!@[M@Rq5!@[M@9 6!@[M@rN6!@[M@h7!@[M@,Г7!@[M@8!@[M@/ 8!@[M@2w9!@[M@^9!@[M@RT,#:!@\N@>:!@\N@r%2Q);!@\N@c;!@\N@Tv/!@\N@RJ8Ҿ>!@\N@A?!@]N@ry?!@]N@ H@!@]N@@!@]N@@a.NA!@]N@@A!@]N@2o>STB!@]N@eB!@]N@RxZC!@]N@5C!@]N@r`D!@^O@dgD!@^O@rfE!@^O@DE!@^O@+lF!@^O@2!F!@^O@Z sG!@^O@2G!@^O@҉m0yH!@^O@R!BH!@^O@JUI!@_O@rPgJ!@_O@'zJ!@_O@K!@_O@K!@_O@sL!@_O@2FÑL!@_O@PM!@_O@RuM!@_O@ .N!@_O@r N!@`P@; !O!@`P@y2O!@`P@kD'P!@`P@WWP!@`P@2i-Q!@`P@14|Q!@`P@Rɢ3R!@`P@`R!@`P@r9S!@`P@żS!@a@P@r']?T!@a@P@T!@a@P@V:EU!@a@P@2U!@a@P@"LV!@a@P@R4V!@a@P@ҴFRW!@a@P@RLcYW!@a@P@kXX!@a@P@r{@~X!@bP@^Y!@bP@Y!@bP@BdZ!@bP@Z!@bP@2qij[!@bP@[!@bP@RFp\!@bP@7\!@bP@r#$w]!@bP@f6]!@cP@I}^!@cP@o[_!@cP@-m_!@cP@2L`!@cP@\`!@cP@R) a!@cP@ҋa!@cP@r#b!@cP@uܕb!@cP@Rc!@dQ@Rc!@dQ@d!@dQ@20&d!@dQ@8%e!@dQ@RH Ke!@dQ@{]+f!@dQ@Rwof!@dQ@Y1g!@dQ@rǔg!@dQ@>67h!@e@Q@դh!@e@Q@2m=i!@e@Q@i!@e@Q@2Cj!@e@Q@3_j!@e@Q@RJk!@e@Q@b<(k!@e@Q@r:Pl!@e@Q@Ml!@e@Q@)_Vm!@fQ@2qm!@fQ@Xe\n!@fQ@2Ӗn!@fQ@҇Bbo!@fQ@Ro!@fQ@hp!@fQ@rNp!@fQ@nq!@fQ@}kq!@fQ@ur!@gQ@H*r!@gQ@2D<{s!@gQ@%Os!@gQ@Rsat!@gQ@ tu!@gQ@rqu!@gQ@9 v!@gQ@Nv!@gQ@iw!@gQ@,Гw!@hR@2x!@hR@/ x!@hR@Rwy!@hR@^y!@hR@rT,#z!@hR@>z!@hR@r%2Q){!@hR@c{!@hR@Tv/|!@hR@2}|!@i@R@5}!@i@R@R[}!@i@R@Ҳɿ;~!@i@R@RJ8Ҿ~!@i@R@A!@i@R@ry!@i@R@ H!@i@R@ˀ!@i@R@@a.N!@i@R@@с!@jR@2o>ST!@jR@eׂ!@jR@RxZ!@jR@5݃!@jR@r`!@jR@dg!@jR@f!@jR@D!@jR@+l!@jR@2!!@kR@Z s!@kR@R!@kR@҉m0y!@kR@r!B!@kR@JU!@kR@Pg!@kR@'z!@kR@!@kR@2!@kR@s!@lS@RFÑ!@lS@P!@lS@Ru藍!@lS@ .!@lS@r !@lS@< !!@lS@y2!@lS@2kD'!@lS@WW!@lS@2i-!@m@S@14|!@m@S@Rɢ3!@m@S@`!@m@S@r9!@m@S@ż!@m@S@']?!@m@S@”!@m@S@V:E!@m@S@2ɕ!@m@S@҅"L!@nS@R4ϖ!@nS@ҴFR!@nS@rLcY՗!@nS@kX!@nS@{@~ۘ!@nS@^!@nS@!@nS@2Bd!@nS@!@nS@Rqij!@oS@!@oS@rFp!@oS@7!@oS@r#$w!@oS@g6!@oS@I}!@oS@2o[!@oS@-m!@oS@RL!@oS@\!@pT@r) !@pT@򋘷!@pT@r#!@pT@uܕ!@pT@R!@pT@2R!@pT@!@pT@R0&!@pT@Ұ8%!@pT@RH K!@q@T@{]+!@q@T@rwo!@q@T@Y1!@q@T@ǔ!@q@T@>67!@q@T@դ!@q@T@2m=!@q@T@!@q@T@RC!@q@T@3_Ǫ!@rT@rJ!@rT@b<(ͫ!@rT@:P!@rT@MӬ!@rT@)_V!@rT@2q٭!@rT@Xe\!@rT@RӖ߮!@rT@҇Bb!@rT@r!@sT@h!@sT@N!@sT@n!@sT@}k!@sT@2u!@sT@H*!@sT@RD<{!@sT@%O!@sT@Rsa!@sT@ t!@tU@rq!@tU@: !@tU@N!@tU@2i!@tU@,Г!@tU@2!@tU@/ !@tU@Rw!@tU@^!@tU@rT,#!@u@U@>!@u@U@%2Q)!@u@U@c!@u@U@Tv/!@u@U@2}!@u@U@҃5!@u@U@R[!@u@U@Ҳɿ;!@u@U@rJ8Ҿ!@u@U@A!@vU@yĿ!@vU@ H!@vU@!@vU@2@a.N!@vU@@!@vU@Ro>ST!@vU@e!@vU@rxZ!@vU@5!@vU@r`!@wU@eg!@wU@f!@wU@2D!@wU@+l!@wU@2!!@wU@Z s!@wU@R!@wU@m0y!@wU@r!B!@wU@JU!@xV@Pg!@xV@'z!@xV@!@xV@2!@xV@Үs!@xV@RFÑ!@xV@P!@xV@ru!@xV@ .!@xV@ !@y@V@< !!@y@V@y2!@y@V@2kD'!@y@V@WW!@y@V@Ri-!@y@V@14|!@y@V@rɢ3!@y@V@`!@y@V@9!@y@V@ż!@zV@']?!@zV@2!@zV@V:E!@zV@R!@zV@҅"L!@zV@r4!@zV@FR!@zV@LcY!@zV@kX!@zV@{@~!@{V@2^!@{V@!@{V@RBd!@{V@!@{V@Rqij!@{V@!@{V@rFp!@{V@8!@{V@#$w!@{V@2g6!@|W@I}!@|W@2o[!@|W@-m!@|W@RL!@|W@\!@|W@r) !@|W@򋘷!@|W@#!@|W@uܕ!@|W@R!@}@W@2R!@}@W@ҁ!@}@W@R0&!@}@W@Ұ8%!@}@W@rH K!@}@W@{]+!@}@W@wo!@}@W@Y1!@}@W@ǔ!@}@W@2>67!@~W@դ!@~W@Rm=!@~W@!@~W@rC!@~W@3_!@~W@rJ!@~W@c<(!@~W@:P!@~W@2M!@~W@)_V!@W@2q!@W@Xe\!@W@RӖ!@W@Bb!@W@r!@W@h!@W@N!@W@n!@W@}k!@W@2u!@X@ҬH*!@X@RD<{!@X@%O!@X@rsa!@X@ t!@X@q!@X@: !@X@N!@X@2i!@X@,Г!@@X@R!@@X@/ !@@X@rw!@@X@^!@@X@rT,#!@@X@>!@@X@%2Q)!@@X@2c!@@X@Tv/!@@X@R}!@X@҃5!@X@R[!@X@ɿ;!@X@rJ8Ҿ!@X@A!@X@y!@X@ H"@X@"@X@2@a.N"@X@@"@X@Ro>ST"@X@e"@X@rxZ"@X@5"@X@`"@X@eg"@X@f"@X@2D"@X@+l"@X@R!"@Y@Z s"@Y@r"@Y@m0y"@Y@!B"@Y@JU "@Y@Pg "@Y@2'z "@Y@ "@Y@R "@Y@Үs "@@Y@rFÑ "@@Y@P "@@Y@u "@@Y@ ."@@Y@ "@@Y@2< !"@@Y@y2"@@Y@RkD'"@@Y@WW"@@Y@ri-"@Y@14|"@Y@rɢ3"@Y@a"@Y@9"@Y@2ż"@Y@']?"@Y@2"@Y@V:E"@Y@R"@Y@"L"@Y@r4"@Y@FR"@Y@LcY"@Y@kX"@Y@{@~"@Y@2^"@Y@Ҫ"@Y@RBd"@Y@"@Y@rqij"@Z@"@Z@Fp"@Z@8"@Z@#$w"@Z@2g6"@Z@I}"@Z@Ro["@Z@-m"@Z@rL "@Z@\ "@@Z@r) !"@@Z@!"@@Z@#""@@Z@2uܕ""@@Z@R#"@@Z@RR#"@@Z@ҁ$"@@Z@R0&$"@@Z@8%%"@@Z@rH K%"@Z@{]+&"@Z@wo&"@Z@Y1'"@Z@ǔ'"@Z@2>67("@Z@դ("@Z@Rm=)"@Z@)"@Z@rC*"@Z@3_*"@Z@J+"@Z@c<(+"@Z@:P,"@Z@2M,"@Z@)_V-"@Z@Rq-"@Z@Xe\."@Z@rӖ."@Z@Bb/"@Z@/"@[@h0"@[@N0"@[@2n1"@[@}k1"@[@Ru2"@[@ҬH*2"@[@RD<{3"@[@%O3"@[@rsa4"@[@ t5"@ @[@q5"@ @[@2: 6"@ @[@N6"@ @[@2i7"@ @[@,Г7"@ @[@R8"@ @[@/ 8"@ @[@rw9"@ @[@_9"@ @[@T,#:"@ [@2>:"@ [@%2Q);"@ [@2c;"@ [@Tv/<"@ [@R}<"@ [@5="@ [@r[="@ [@ɿ;>"@ [@J8Ҿ>"@ [@A?"@ [@y?"@ [@2 H@"@ [@Ҩ@"@ [@R@a.NA"@ [@@A"@ [@ro>STB"@ [@eB"@ [@xZC"@ [@6C"@ [@`D"@ \@2egD"@ \@fE"@ \@RDE"@ \@+lF"@ \@r!F"@ \@Z sG"@ \@rG"@ \@m0yH"@ \@!BH"@ \@2JUI"@ @\@PgJ"@ @\@R'zJ"@ @\@K"@ @\@RK"@ @\@sL"@ @\@rFÑL"@ @\@PM"@ @\@uM"@ @\@ .N"@ @\@ N"@\@2< !O"@\@y2O"@\@RkD'P"@\@WWP"@\@ri-Q"@\@14|Q"@\@ɢ3R"@\@aR"@\@9S"@\@2żS"@\@']?T"@\@RT"@\@V:EU"@\@rU"@\@"LV"@\@4V"@\@FRW"@\@LcYW"@\@2kXX"@\@{@~X"@]@R^Y"@]@ҪY"@]@RBdZ"@]@Z"@]@rqij["@]@ ["@]@Fp\"@]@28\"@]@#$w]"@]@2g6]"@@]@I}^"@@]@Ro[_"@@]@-m_"@@]@rL`"@@]@\`"@@]@) a"@@]@a"@@]@#b"@@]@2uܕb"@@]@Rc"@]@RRc"@]@ҁd"@]@r0&d"@]@8%e"@]@H Ke"@]@{]+f"@]@wof"@]@2Y1g"@]@ǔg"@]@R>67h"@]@դh"@]@rm=i"@]@i"@]@rCj"@]@4_j"@]@Jk"@]@2c<(k"@]@:Pl"@]@M5Ml"@]@2_Vm"@^@RRrm"@^@l\n"@^@$pn"@^@bo"@^@2o"@^@2Yhp"@^@p"@^@r9nq"@^@q"@^@bWur"@@^@)+r"@@^@Rt>{s"@@^@ҼQs"@@^@ct"@@^@W!vu"@@^@&u"@@^@r> v"@@^@ͭv"@@^@\w"@@^@xғw"@^@Pzx"@^@R+ x"@^@ y"@^@&y"@^@ŵ/#z"@^@RDBz"@^@ҊT){"@^@pbg{"@^@Wy/|"@^@@|"@^@*5}"@^@}"@^@2-;~"@^@־~"@^@JA"@^@r"@^@hH"@^@ ˀ"@^@ҿ3N"@^@Fс"@_@XT"@_@R3kׂ"@_@R}Z"@_@2Q݃"@_@Һ`"@_@2o"@_@rf"@_@rЍ"@_@Rl"@_@"@@_@:s"@@_@R$"@@_@2Y7y"@@_@+I"@@_@RAw\"@@_@Xo"@@_@q"@@_@$"@@_@R"@@_@B"@_@ˑ"@_@ a"@_@-"@_@RS"@_@z"@_@ң(!"@_@,;"@_@rM'"@_@)K`"@_@2Zr-"@_@Ri"@_@23"@_@"@_@R-9"@_@rfϼ"@_@5?"@_@R”"@_@TF"@_@R]ɕ"@_@r,L"@`@r?ϖ"@`@)QR"@`@p d՗"@`@vX"@`@?ۘ"@`@QΛ^"@`@]"@`@d"@`@RC|"@`@R j"@ `@2"@ `@D* q"@ `@2"@ `@RH0w"@ `@RVB"@ `@gU}"@ `@rg"@ `@wz"@ `@"@ `@A"@@`@4 "@@`@ď"@@`@R~S"@@`@R镢"@@`@2Zr"@@`@"@@`@2=!"@@`@R 4"@@`@R'F%"@@`@?Y"@``@k+"@``@^~"@``@1"@``@}"@``@ 7"@``@Ⱥ"@``@r,="@``@r"@``@R%KD"@``@Ǫ"@ `@R:j%J"@ `@7ͫ"@ `@VJP"@ `@R]Ӭ"@ `@yoV"@ `@28٭"@ `@rǔ\"@ `@Rj"@)a@"@)a@_q"@)a@r9-"@)a@t@w"@)a@RS"@*a@Re}"@*a@2.0x"@*a@o"@*a@RP"@*a@௉"@*a@r?q "@*a@RՏ"@*a@ґ"@*a@R""@*a@rm "@+a@rB"@+a@21"@+a@bcD"@+a@V%"@+a@i"@+a@g|+"@+a@¤"@+a@51"@+a@R}ų"@+a@RU7"@,b@2?غ"@,b@v="@,b@2"@,b@RoD"@,b@2'#"@,b@B5J"@,b@rHH"@,b@ZP"@,b@im"@,b@V"@- b@rs"@- b@\"@- b@2`"@- b@2;b"@- b@T"@- b@\h"@- b@O"@- b@R}o"@- b@2Q'"@- b@՞9u"@.@b@Z/L"@.@b@^{"@.@b@jPq"@.@b@"@.@b@q"@.@b@"@.@b@R "@.@b@R3#΍"@.@b@2dz"@.@b@\D"@/`b@2"@/`b@re"@/`b@r(*"@/`b@ņ="@/`b@cP#"@/`b@b"@/`b@28u)"@/`b@Jɇ"@/`b@Y/"@/`b@Rꬲ"@0b@@{5"@0b@ Ҹ"@0b@r;"@0b@2G-"@0b@ B"@0b@N"@0b@].H#@0b@pA#@0b@2TN#@0b@rf#@1b@?"yT#@1b@#@1b@2CZ#@1b@{԰#@1b@>e`#@1b@2#@1b@džf#@1b@#@1b@Y m#@1b@R$9 #@2b@R2s#@2b@ZE#@2b@Wy#@2b@c|j#@2b@R7 } #@2b@2  #@2b@. #@2b@r #@2b@PNj #@2b@v #@3b@Ur #@3b@r6 #@3b@ #@3b@$$#@3b@6#@3b@FI!#@3b@r[#@3b@ҟhn'#@3b@#@3b@{-#@4c@l#@4c@R_3#@4c@S=˶#@4c@I9#@4c@A_#@4c@2;@#@4c@6#@4c@3(F#@4c@2:#@4c@34ML#@5 c@r6_#@5 c@:VrR#@5 c@@#@5 c@HxX#@5 c@R #@5 c@R^^#@5 c@k+#@5 c@zd#@5 c@M#@5 c@2k#@6@c@Ҳo#@6@c@,q#@6@c@>#@6@c@"Qw#@6@c@rc#@6@c@3Ev}#@6@c@Sֈ#@6@c@tg#@6@c@Җ #@6@c@R #@7`c@ !#@7`c@ !#@7`c@3="#@7`c@r_ "#@7`c@_##@7`c@2/##@7`c@RB$#@7`c@2 U$#@7`c@Tg%%#@7`c@R5z%#@8c@rƌ+&#@8c@RW&#@8c@291'#@8c@vzĴ'#@8c@2 7(#@8c@2(#@8c@2:.=)#@8c@~)#@8c@RP!D*#@8c@ 3*#@9c@WsFJ+#@9c@Y+#@9c@RkP,#@9c@@'~,#@9c@򑸐V-#@9c@I-#@9c@9۵\.#@9c@Rl.#@9c@b/#@9c@B/#@:c@ i0#@:c@0#@:c@[C%o1#@:c@R71#@:c@R fJu2#@:c@2\2#@:c@o{3#@:c@RT3#@:c@4#@:c@*=5#@;c@rι5#@;c@` 6#@;c@Ryލ6#@;c@7#@;c@ra7#@;c@Rإ8#@;c@P7)8#@;c@2;9#@;c@2GZN9#@;c@2`#:#@<d@D}s:#@<d@2);#@<d@I;#@<d@r1/<#@<d@RUý<#@<d@T5=#@<d@rh=#@<d@w;>#@<d@r >#@<d@RB?#@= d@,-?#@= d@27?H@#@= d@2OR@#@= d@cdNA#@= d@rwA#@= d@2TB#@= d@2B#@= d@'ZC#@= d@rpC#@= d@K`D#@>@d@rD#@>@d@ZnfE#@>@d@ E#@>@d@rmF#@>@d@T#1F#@>@d@2CsG#@>@d@rFVG#@>@d@R_hyH#@>@d@j{H#@>@d@rI#@?`d@yJ#@?`d@0J#@?`d@K#@?`d@RB؋K#@?`d@`L#@?`d@fL#@?`d@M#@?`d@"M#@?`d@Rd5N#@?`d@)GN#@@d@>Z!O#@@d@lO#@@d@rb'P#@@d@PP#@@d@-Q#@@d@2Q#@@d@3R#@@d@Ҕ;ܶR#@@d@2j9S#@@d@RA_S#@Ad@r@T#@Ad@&T#@Ad@9FU#@Ad@KU#@Ad@R8^LV#@Ad@2rpV#@Ad@U\RW#@Ad@r;W#@Ad@"XX#@Ad@ X#@Bd@^Y#@Bd@R5Y#@Bd@dZ#@Bd@YZ#@Bd@k[#@Bd@ҧ}*[#@Bd@r=q\#@Bd@ҔO\#@Bd@3bw]#@Bd@t]#@Cd@W}^#@Cd@2_#@Cd@r{_#@Cd@ `#@Cd@rщ`#@Cd@1 a#@Cd@a#@Cd@ҠU b#@Cd@b#@Cd@y.c#@De@2 Ac#@De@םSd#@De@/fd#@De@x%e#@De@Te#@De@++f#@De@rDxf#@De@r_ 1g#@De@r|մg#@De@.7h#@E e@h#@E e@R >i#@E e@i#@E e@'w2Dj#@E e@RO Ej#@E e@xWJk#@E e@-jk#@E e@п|Pl#@E e@Ql#@E e@R0Vm#@F@e@bvm#@F@e@\n#@F@e@̚n#@F@e@R-bo#@F@e@=o#@F@e@yQip#@F@e@2#p#@F@e@u6oq#@F@e@5Iq#@F@e@x[ur#@G`e@2,nr#@G`e@R{s#@G`e@IQs#@G`e@r㥁t#@G`e@uu#@G`e@+ˇu#@G`e@z v#@G`e@,v#@G`e@2w#@G`e@rrQw#@He@r'x#@He@r v:x#@He@yMy#@He@r՚_y#@He@2-r#z#@He@z#@He@rQ){#@He@T䩬{#@He@rv/|#@He@ ϲ|#@Ie@5}#@Ie@2-}#@Ie@\<~#@Ie@R~#@Ie@9+B#@Ie@w>#@Ie@ QH#@Ie@cˀ#@Ie@R/vN#@Ie@2с#@Je@ST#@Je@tׂ#@Je@xZ#@Je@2q ݃#@Je@`#@Je@t0#@Je@r g#@Je@U#@Je@/m#@Je@zB#@Ke@R Us#@Ke@Ҫg#@Ke@:2zy#@Ke@Č#@Ke@]W#@Ke@#@Ke@҈|ą#@Ke@!#@Ke@鋋#@Ke@V4#@Lf@R#@Lf@Y!#@Lf@43#@Lf@~F#@Lf@R|Y#@Lf@"k!#@Lf@6~#@Lf@uɐ'#@Lf@ \#@Lf@-#@M f@}Ȱ#@M f@2/3#@M f@#@M f@Җ9:#@M f@rM#@M f@_%@#@M f@7Ô#@M f@{JF#@M f@r9]ɕ#@M f@oL#@N@f@2<ϖ#@N@f@R}ϔR#@N@f@Bb՗#@N@f@X#@N@f@чۘ#@N@f@R^#@N@f@Rg#@N@f@5@e#@N@f@#@N@f@e)k#@O`f@2;#@O`f@~Nq#@O`f@Ta#@O`f@R-sw#@O`f@D#@O`f@֘}#@O`f@ri#@O`f@2#@O`f@#@O`f@e"㉠#@Pf@J #@Pf@r1H#@Pf@2#@Pf@rn-#@Pf@@#@Pf@ޓR#@Pf@R&e#@Pf@ҿw#@Pf@L%#@Pf@2ߜ#@Qf@r+#@Qf@®#@Qf@1#@Qf@R+紧#@Qf@r7#@Qf@Q #@Qf@ҍ>#@Qf@w1#@Qf@R DD#@Qf@2VǪ#@Rf@0iJ#@Rf@{ͫ#@Rf@ҼVP#@Rf@Ӭ#@Rf@|V#@Rf@R٭#@Rf@\#@Rf@6߮#@Rf@2,b#@Rf@D\#@Sf@_"i#@Sf@{5#@Sf@Ho#@Sf@Z#@Sf@;mu#@Sf@r#@Sf@$b{#@Sf@K#@Sf@t#@Sf@R#@Tg@ˮ܇#@Tg@A #@Tg@2*#@Tg@[h#@Tg@r&#@Tg@Ď9#@Tg@!L#@Tg@25^#@Tg@oHq#@Tg@Rۃ##@U g@n#@U g@*)#@U g@l#@U g@r(/#@U g@಼#@U g@2=O5#@U g@2#@U g@u<#@U g@ +#@U g@2l=B#@V@g@R/Pſ#@V@g@2bH#@V@g@bVu#@V@g@N#@V@g@}#@V@g@hT#@V@g@ã#@V@g@7Z#@V@g@2~#@V@g@]`#@W`g@@ #@W`g@rg#@W`g@ /#@W`g@rqAm#@W`g@>T#@W`g@Efs#@W`g@rey#@W`g@!y#@W`g@r#@W`g@ #@Xg@rw#@Xg@2Fօ#@Xg@d#@Xg@m#@Xg@Y#@Xg@Ք #@Xg@T(3#@Xg@ԻE#@Xg@RWOX#@Xg@2j#@Yg@av}!#@Yg@ #@Yg@q'#@Yg@20#@Yg@-#@Yg@Xڰ#@Yg@R3#@Yg@;#@Yg@:#@Yg@e$#@Zg@R97@#@Zg@I#@Zg@2a\F#@Zg@n#@Zg@mL#@Zg@r#@Zg@ҰR#@Zg@TC#@Zg@X#@Zg@j#@[g@2L^#@[g@#@[g@%e#@[g@rS(#@[g@2M;k#@[g@M#@[g@jt`q#@[g@ s#@[g@؛w#@[g@r/#@\h@Mê}#@\h@ W#@\h@σ#@\h@~#@\h@2M#@\h@r #@\h@9#@\h@,#@\h@Ria?#@\h@4Q#@] h@d#@] h@w#@] h@ҡ#@] h@tD%#@] h@Hخ#@] h@2l+#@] h@Ӯ#@] h@Г1#@] h@r'#@] h@ 8#@^@h@hO#@^@h@I0>#@^@h@,wC#@^@h@ VD#@^@h@2h#@^@h@R2{J#@^@h@2ƍ#@^@h@ҴZP#@^@h@2#@^@h@rV#@_`h@r#@_`h@2u\#@_`h@i>#@_`h@2`c#@_`h@RXf"#@_`h@2R4i#@_`h@MG#@_`h@rK"Zo#@_`h@Jl#@_`h@KJu#@`h@Nޑ#@`h@RSr{#@`h@Y#@`h@aɁ#@`h@l.#@`h@w#@`h@rV #@`h@#@`h@ҥ~&#@`h@Ҹ9#@ah@ͦK#@ah@:^#@ah@Rp#@ah@rc#@ah@R2##@ah@O#@ah@ro)#@ah@ͬ#@ah@G/#@ah@r#@bh@o6#@bh@r'#@bh@Q*<#@bh@},=#@bh@ROB#@bh@Tb#@bh@2 tH$@bh@2?}$@bh@2tN$@bh@Ҫ$@ch@R9T$@ch@$@ch@YbZ$@ch@r$@ch@֊ a$@ch@r$@ch@[.g$@ch@GA$@ch@RSm$@ch@/pf$@di@2zys$@di@RƘ$@di@2-y$@di@c$@di@rU $@di@ $@di@]~ $@di@ $@di@ $@di@g;  $@e i@2 $@e i@!dE $@e i@rW $@e i@j$@e i@rF!}$@e i@r!$@e i@rJ$@e i@{޴'$@e i@rǪ$@e i@Q-$@f@i@$@f@i@/03$@f@i@r$@f@i@Y$:$@f@i@6$@f@i@I@$@f@i@y\$@f@i@RnF$@f@i@p?$@f@i@ӓL$@g`i@nh$@g`i@R$@g`i@s$@g`i@R%X$@g`i@R$@g`i@R O_$@g`i@$@g`i@R x(e$@g`i@ ;$@g`i@>Mk$@hi@R5`$@hi@crq$@hi@R^$@hi@rw$@hi@R)$@hi@2}$@hi@`$@hi@E$@hi@ $@hi@@o $@ii@ !$@ii@,!$@ii@21-?"$@ii@2Q"$@ii@Vd#$@ii@1v#$@ii@$$@ii@2$$@ii@B%%$@ii@=%$@ji@r+&$@ji@bg&$@ji@1'$@ji@֐ '$@ji@r%8($@ji@Q0($@ji@OC>)$@ji@U)$@ji@җxhD*$@ji@] {*$@ki@$J+$@ki@26+$@ki@˲P,$@ki@`,$@ki@RTV-$@ki@$-$@ki@\.$@ki@ʳ.$@ki@rH"c/$@ki@w4/$@lj@QrGi0$@lj@2,Z0$@lj@lo1$@lj@01$@lj@őu2$@lj@Z2$@lj@2{3$@lj@s3$@lj@[܁4$@lj@D5$@ m j@/C5$@ m j@ 6$@ m j@r m&6$@ m j@97$@ m j@RK7$@ m j@r+^8$@ m j@2p8$@ m j@U9$@ m j@Rꕠ9$@ m j@#:$@ n@j@r:$@ n@j@2);$@ n@j@>;$@ n@j@2/<$@ n@j@Rh<$@ n@j@26=$@ n@j@Ւ*=$@ n@j@r'=<>$@ n@j@O>$@ n@j@QbB?$@ o`j@t?$@ o`j@R|H@$@ o`j@(@$@ o`j@i$@w`k@҇hi$@w`k@+S{Dj$@w`k@j$@w`k@v~Jk$@w`k@2k$@w`k@rɩPl$@w`k@u?l$@w`k@r#Vm$@xk@jm$@xk@]n$@xk@7"n$@xk@+5co$@xk@Go$@xk@2\WZip$@xk@rlp$@xk@҂oq$@xk@q$@xk@RPur$@yk@Dr$@yk@2{s$@yk@2os$@yk@2at$@yk@)u$@yk@R0u$@yk@r& v$@yk@\9v$@yk@R^Kw$@yk@/^w$@zk@Rqx$@zk@rسx$@zk@Iy$@zk@2ߨy$@zk@bu#z$@zk@? Φz$@zk@2){$@zk@6{$@zk@0|$@zk@Rb|$@{k@r*6}$@{k@r=}$@{k@Rw$P<~$@{k@ab~$@{k@rNPuB$@{k@<$@{k@r,|H$@{k@Rˀ$@{k@N$@{k@2>с$@|l@2T$@|l@2iׂ$@|l@ [$@|l@Rރ$@|l@+/a$@|l@A$@|l@WTg$@|l@f$@|l@rym$@|l@$@} l@s$@} l@F$@} l@y$@} l@r-r$@} l@=$@} l@rO$@} l@2c4$@} l@x $@} l@`3$@} l@E$@~@l@ÌX$@~@l@"k$@~@l@}$@~@l@2O$@~@l@A增$@~@l@d{!$@~@l@rȤ$@~@l@ұ'$@~@l@=$@~@l@-$@`l@2j$@`l@2a%4$@`l@r7$@`l@,J:$@`l@R\$@`l@-Yo@$@`l@rdÔ$@`l@ҝF$@`l@ɕ$@`l@rL$@l@THϖ$@l@rR$@l@t՗$@l@ Y$@l@2`ܘ$@l@ҧ7)_$@l@;$@l@R$@l@G|$@l@RʚD$@l@rN1Ǫ$@ m@dzJ$@ m@r\^ͫ$@ m@P$@ m@rqӬ$@ m@!V$@ m@ڭ$@ m@rO#]$@ m@5$@ m@RE|Hc$@ m@[$@! m@Rsmi$@! m@ @$@! m@֒o$@! m@Em$@! m@u$@! m@$@! m@R(1{$@! m@$@! m@r^$@! m@$@"@m@ċ'$@"@m@rp": $@"@m@L$@"@m@O_$@"@m@}q$@"@m@0}$@"@m@$@"@m@R$@"@m@RSA$@"@m@R #$@#`m@nᦺ$@#`m@r)$@#`m@E$@#`m@30$@#`m@R+$@#`m@`>6$@#`m@RTP$@#`m@rc<$@#`m@r$v$@#`m@2B$@$m@Rſ$@$m@NH$@$m@ $@$m@N$@$m@ǭ$@$m@DT$@$m@Rv $@$m@RPr[$@$m@2, 0$@$m@ Ba$@%m@26U$@%m@Rgg$@%m@2dz$@%m@m$@%m@rx$@%m@`)s$@%m@J$@%m@6Wy$@%m@r$$@%m@$@&m@2$@&m@2!$@&m@I4 $@&m@F$@&m@wY$@&m@2l$@&m@2ҥ~$@&m@<$@&m@rӣ$@&m@j$@'m@!$@'m@ؘۤ$@'m@/'$@'m@$@'m@R].$@'m@R%$@'m@2 84$@'m@#K$@'m@R-]:$@'m@r@Qp$@(n@RU@$@(n@2l$@(n@F$@(n@$@(n@2DL$@(n@2$@(n@rR$@(n@R $@(n@=Y$@(n@b8*$@) n@<_$@) n@fO$@) n@rae$@) n@t$@) n@6,k$@) n@fÙ$@) n@Zq$@) n@$@) n@w$@) n@r7 $@*@n@Rp}$@*@n@N $@*@n@$@*@n@%}.$@*@n@dA$@*@n@S $@*@n@Bf$@*@n@R/x$@*@n@Rvq$@*@n@$@+`n@ $@+`n@U7$@+`n@2բ$@+`n@e%$@+`n@E$@+`n@R ,$@+`n@+ $@+`n@E22$@+`n@ZE$@+`n@RW8$@,n@Uj$@,n@ }>$@,n@$@,n@uOD$@,n@r$@,n@>~J$@,n@$@,n@P$@,n@yD$@,n@2W$@-n@rTs$$@-n@ 7]$@-n@r6I$@-n@29\c$@-n@n$@-n@Җhi$@-n@$@-n@o$@-n@R/$@-n@u$@.n@^$@.n@҇{$@.n@ $@.n@2$$@.n@r($@.n@S;$@.n@r,M $@.n@`$@.n@Gs$@.n@ױ$@/n@iI$@/n@ચ$@/n@Rx$@/n@*Р$@/n@ç#$@/n@^?$@/n@*$@/n@Rn$@/n@:-0$@/n@ܝ?$@0o@5R6$@0o@R&d$@0o@dw<$@0o@w$@0o@"B$@0o@+$@0o@}H%@0o@.[%@0o@RN%@0o@R%@1 o@J" U%@1 o@%@1 o@Q1[%@1 o@vC%@1 o@3Va%@1 o@i%@1 o@R{g%@1 o@tH%@1 o@8m%@1 o@rw%@2@o@s%@2@o@%@2@o@Z?y%@2@o@'%@2@o@n %@2@o@2# %@2@o@5 %@2@o@m6H %@2@o@CZ %@2@o@Rfm %@3`o@ %@3`o@2Е %@3`o@2- %@3`o@ŷ%@3`o@l]ʞ%@3`o@2O!%@3`o@r3%@3`o@%(%@3`o@R%@3`o@T'.%@4o@R9%@4o@RÄL4%@4o@r_%@4o@q:%@4o@L%@4o@@%@4o@|%@4o@wF%@4o@q%@4o@mDL%@5o@Rj%@5o@RitS%@5o@2j %@5o@l+Y%@5o@2q<>%@5o@RwP_%@5o@2lc%@5o@ve%@5o@%@5o@4k%@6o@̭%@6o@dq%@6o@%@6o@w%@6o@R,%@6o@R ~%@6o@21]%@6o@L/%@6o@2jB %@6o@r%U %@7o@Rg !%@7o@2Uz!%@7o@"%@7o@"%@7o@2@#%@7o@jĜ#%@7o@ҕN$%@7o@2$%@7o@~%%%@7o@#%%@8p@RV!,&%@8p@G4&%@8p@rF2'%@8p@wY'%@8p@3l8(%@8p@ro~(%@8p@@>)%@8p@Rأ)%@8p@r-qD*%@8p@Rp *%@9p@2J+%@9p@9+%@9p@CQ,%@9p@j,%@9p@&W-%@9p@r'8-%@9p@v3K].%@9p@2].%@9p@dpc/%@9p@o/%@: p@rƔi0%@: p@-0%@: p@yźo1%@: p@]1%@: p@2u2%@: p@22%@: p@r&|3%@: p@V3%@: p@RW*4%@: p@"<5%@;0p@rO5%@;0p@ b 6%@;0p@`t6%@;0p@Q7%@;0p@2>Ꙕ7%@;0p@8%@;0p@"8%@;0p@9%@;0p@rL9%@;0p@#:%@<@p@2} :%@<@p@R}*;%@<@p@2.;%@<@p@zFA0<%@<@p@RS<%@<@p@wf6=%@<@p@y=%@<@p@R<>%@<@p@A>%@<@p@rٰB?%@=Pp@*r?%@=Pp@ H@%@=Pp@2H@%@=Pp@;NA%@=Pp@m A%@=Pp@Rm UB%@=Pp@23B%@=Pp@1E[C%@=Pp@R6XC%@=Pp@hjaD%@>`p@h}D%@>`p@rgE%@>`p@HE%@>`p@r1mF%@>`p@F%@>`p@7csG%@>`p@RG%@>`p@yH%@>`p@27-H%@>`p@r$I%@?pp@R^7J%@?pp@FIJ%@?pp@r\ K%@?pp@(oK%@?pp@fL%@?pp@ZL%@?pp@2M%@?pp@M%@?pp@T$N%@?pp@ޞN%@@p@U!O%@@p@2O%@@p@_(P%@@p@& )P%@@p@;.Q%@@p@RQNQ%@@p@҆`4R%@@p@UsR%@@p@%:S%@@p@S%@Ap@M@T%@Ap@T%@Ap@RwFU%@Ap@RPU%@Ap@+LV%@Ap@JV%@Ap@SW%@Ap@{-W%@Ap@2@YX%@Ap@ҋRX%@Bp@RqFe_Y%@Bp@XwY%@Bp@AxeZ%@Bp@,Z%@Bp@2k[%@Bp@C[%@Bp@q\%@Bp@t\%@Bp@ w]%@Bp@RӦ ]%@Cp@?~^%@Cp@1_%@Cp@qD_%@Cp@ W`%@Cp@i`%@Cp@R<| a%@Cp@rՎa%@Cp@Rnb%@Cp@b%@Cp@R͠c%@Dp@9ٜc%@Dp@d%@Dp@kd%@Dp@&e%@Dp@r #e%@Dp@76,f%@Dp@3Hf%@Dp@rIi[2g%@Dp@`ng%@Dp@Rz8h%@Ep@R4h%@Ep@2ͥ>i%@Ep@fi%@Ep@RDj%@Ep@j%@Ep@72Jk%@Ep@]k%@Ep@dQl%@Ep@'l%@Ep@ٖ:Wm%@Fp@0Mm%@Fp@r5_]n%@Fp@ebrn%@Fp@Rco%@Fp@r̔o%@Fp@r.ip%@Fp@:Ǽp%@Fp@rs`oq%@Fp@Үq%@Fp@ur%@Gp@*,r%@Gp@Rk|s%@Gp@^,s%@Gp@>t%@Gp@7Qu%@Gp@*du%@Gp@2v v%@Gp@]v%@Gp@aw%@Gp@w%@Hq@R)x%@Hq@SӚx%@Hq@2[y%@Hq@2y%@Hq@U $z%@Hq@'z%@Hq@ 0*{%@Hq@RhZC{%@Hq@RU0|%@Hq@2(h|%@Iq@&{6}%@Iq@}%@Iq@2UY<~%@Iq@~%@Iq@&B%@Iq@R%%@Iq@H%@Iq@nXˀ%@Iq@O%@Iq@2R"ҁ%@J q@$5U%@J q@%@N`q@Ye%@N`q@%@N`q@Ҝk%@Opq@j&%@Opq@:q%@Opq@r Z%@Opq@x%@Opq@r!%@Opq@2'4~%@Opq@bF%@Opq@<[Y%@Opq@k%@Opq@~%@Pq@r( %@Pq@£%@Pq@\%@Pq@2Ȗ%@Pq@f%@Pq@O*%@Pq@9 %@Pq@%^%@Pq@%&%@Pq@8%@Qq@2+K,%@Qq@r]%@Qq@r_p2%@Qq@r%@Qq@̓8%@Qq@r-%@Qq@Ǻ>%@Qq@a%@Qq@rD%@Qq@ÕǪ%@Rq@r/K%@Rq@Ϋ%@Rq@c*Q%@Rq@2<Ԭ%@Rq@OW%@Rq@1bڭ%@Rq@t]%@Rq@f%@Rq@!c%@Rq@25%@Sq@rJ4i%@Sq@Ra%@Sq@2zho%@Sq@Ҕ%@Sq@2 v%@Sq@R6%@Sq@R.|%@Sq@kA%@Sq@4T%@Sq@Yf%@Tq@9y%@Tq@Ӌ %@Tq@m%@Tq@%@Tq@R/Ô%@Tq@R_<%@Tq@2蚸%@Tq@p%@Tq@ %@Tq@R1 $%@Uq@2j?3%@Uq@E*%@Uq@sX%@Uq@k0%@Uq@`}%@Uq@ҡB6%@Uq@ܢ%@Uq@+w<%@Uq@rrȿ%@Uq@rB%@Vq@2Fſ%@Vq@RH%@Vq@2z%@Vq@r%O%@Vq@rC7%@Vq@RIJU%@Vq@\%@Vq@D~o[%@Vq@R%@Vq@a%@Wq@TM%@Wq@Rg%@Wq@%@Wq@um%@Wq@rٶ%@Wq@2?Qt%@Wq@%@Wq@)z%@Wq@z <%@Wq@N%@Xr@2VUa%@Xr@rs%@Xr@8 %@Xr@$%@Xr@2"%@Xr@ҙY%@Xr@%@Xr@2%@Xr@ )%@Xr@%@Yr@ ^"%@Yr@2-%@Yr@R@(%@Yr@-S%@Yr@e.%@Yr@bx%@Yr@224%@Yr@%@Yr@M2:%@Yr@r½%@Z r@pg@%@Z r@%@Z r@F%@Z r@R27 %@Z r@M%@Z r@gl2%@Z r@ES%@Z r@ҢW%@Z r@rC%@^`r@%@^`r@dD%@^`r@~%@^`r@RaK%@^`r@E5-%@^`r@,?Q%@^`r@kR%@^`r@eW%@_pr@w%@_pr@;]%@_pr@R֜%@_pr@Rqc%@_pr@ %@_pr@i%@_pr@B%@_pr@o%@_pr@x %@_pr@v%@`r@21%@`r@ID|%@`r@V%@`r@ri%@`r@|%@`r@%@`r@P %@`r@볎%@`r@%@`r@!ٔ%@ar@ɼ%@ar@W%@ar@%@ar@R#%@ar@)6$%@ar@21H%@ar@2K_[*%@ar@gm%@ar@0%@ar@0%@br@r˥6%@br@rf%@br@R <%@br@3ݿ%@br@\8B%@br@R%@br@RnI&@br@ (&@br@:O&@br@@@M&@cr@s_U&@cr@Ҩvr&@cr@[&@cr@&@cr@RRHa&@cr@2&@cr@2~g&@cr@ &@cr@2Mm&@cr@RP&@dr@2t&@dr@,&@dr@rd"?z&@dr@Q&@dr@Xd &@dr@Hv &@dr@ &@dr@* &@dr@R=Ʈ &@dr@Ra &@er@2Ӓ &@er@A &@er@3 &@er@R &@er@RVj&@er@21"&@er@C&@er@{_~&@hs@q&@hs@]u&@hs@ &@hs@ &@is@R3H !&@is@ΐ!&@is@Ru"&@is@"&@is@r#&@is@eR#&@is@+ $&@is@r>$&@is@f%Q&%&@is@rc%&@j s@\v,&&@j s@v&&@j s@R*2'&@j s@/'&@j s@8(&@j s@RPgӻ(&@j s@ >)&@j s@Ǟ)&@j s@2: E*&@j s@rF*&@k0s@r0K+&@k0s@R C+&@k0s@ґUQ,&@k0s@RYEh,&@k0s@r"zW-&@k0s@r|-&@k0s@2].&@k0s@҈.&@k0s@YPc/&@k0s@+/&@l@s@i0&@l@s@#0&@l@s@2p1&@l@s@r["1&@l@s@r`4v2&@l@s@R=G2&@l@s@/Z|3&@l@s@Rl3&@l@s@rf4&@l@s@5&@mPs@R5&@mPs@: 6&@mPs@2yɎ6&@mPs@2dr7&@mPs@2Q7&@mPs@?8&@mPs@r0F8&@mPs@"&9&@mPs@~99&@mPs@ L$:&@n`s@^:&@n`s@Qq*;&@n`s@탭;&@n`s@0<&@n`s@%<&@n`s@26=&@n`s@r]ι=&@n`s@<>&@n`s@>&@n`s@2 2C?&@ops@?&@ops@j+I@&@ops@*>@&@ops@9POA&@ops@J>cA&@ops@]uUB&@ops@2qvB&@ops@2[C&@ops@򞮭C&@ops@rJaD&@ps@D&@ps@gE&@ps@E&@ps@0 nF&@ps@2SWF&@ps@w/tG&@ps@BG&@ps@r+UzH&@ps@gH&@ps@dzI&@qs@GJ&@qs@vJ&@qs@8 K&@qs@2ČK&@qs@qL&@qs@D L&@qs@|M&@qs@rEM&@qs@!N&@qs@2/~4N&@rs@RnG"O&@rs@2YO&@rs@Rl(P&@rs@26~P&@rs@|.Q&@rs@'Q&@rs@rĶ4R&@rs@Y`ɷR&@rs@R:S&@rs@S&@ss@rG5AT&@ss@RT&@ss@m&GU&@ss@2E 9U&@ss@2KMV&@ss@B^V&@ss@RpSW&@ss@2{W&@ss@YX&@ss@pX&@ts@RP_Y&@ts@7Y&@ts@ReZ&@ts@&Z&@ts@rpl[&@ts@R^[&@ts@I*r\&@ts@=\&@ts@R*4Px]&@ts@2b]&@us@mu~^&@us@R _&@us@_&@us@zB`&@us@r޿`&@us@2t{ a&@us@a&@us@tb&@us@P b&@us@r|c&@vs@/c&@vs@R&B d&@vs@Td&@vs@r_g&e&@vs@/ye&@vs@,f&@vs@O5f&@vs@ѱ2g&@vs@wnĵg&@vs@ 8h&@ws@h&@ws@AD>i&@ws@i&@ws@z}!Ej&@ws@4j&@ws@һFKk&@ws@_SYk&@ws@kQl&@ws@~l&@ws@2S)Wm&@xt@rţm&@xt@b]n&@xt@RWn&@xt@co&@xt@r8o&@xt@kjp&@xt@ rp&@xt@r&pq&@xt@8q&@xt@rJHKvr&@yt@]r&@yt@āp|s&@yt@2s&@yt@Et&@yt@ Xu&@yt@2u&@yt@ v&@yt@].v&@yt@2(w&@yt@rgw&@z t@rx&@z t@2*x&@z t@c>=y&@z t@27Oy&@z t@R xb$z&@z t@ruz&@z t@*{&@z t@N{&@z t@r0|&@z t@Q|&@{0t@0%6}&@{0t@}&@{0t@^<~&@{0t@R ~&@{0t@r˜C&@{0t@25/&@{0t@ҕAI&@{0t@2oT̀&@{0t@Rp gO&@{0t@r`yҁ&@|@t@RFU&@|@t@E؂&@|@t@:[&@|@t@2ރ&@|@t@+a&@|@t@%W&@|@t@2"g&@|@t@r &@|@t@r .!n&@|@t@R"3&@}Pt@%hFt&@}Pt@r+Y&@}Pt@2kz&@}Pt@;?~&@}Pt@RFܐ&@}Pt@Ry&@}Pt@2a&@}Pt@Rq &@}Pt@RPی&@}Pt@&@~`t@r&@~`t@'&@~`t@%&@~`t@a8&@~`t@2J&@~`t@2]"&@~`t@R9p&@~`t@tւ(&@~`t@s&@~`t@2.&@pt@孺&@pt@K4&@pt@9߷&@pt@rf:&@pt@Ҕ"&@pt@2ſA&@pt@2\*Ĕ&@pt@2+&@u@2Ć &@u@rK%&@u@ &@u@r_b3&@u@2F&@u@zX&@u@ >k&@u@}&@u@0{$&@u@r&@u@]*&@u@Vȭ&@u@0&@u@.&@u@R27&@u@m&@u@p%=&@u@8&@u@RYJC&@u@L]&@u@oI'@u@2U'@u@(O'@u@Ƨ'@u@aeU'@u@2'@u@2Ǣ['@u@|A'@u@4b'@u@~'@u@*h'@u@e<'@u@$[On'@u@2a'@u@rtt'@u@k7'@u@R1֙z'@u@t'@u@r '@u@ '@u@ZQ '@u@r) '@u@ '@u@r- '@u@. '@u@rvkA '@u@2N T '@u@'f'@u@Hy'@u@2"'@u@򾅞'@u@$('@u@ë'@u@2fb.'@v@RL'@v@44'@v@?'@v@ ;'@v@2|3'@v@2FA'@v@պX'@v@rYkG'@v@}'@v@򲗐M'@v@6'@v@RյS'@v@ҟt'@v@Y'@v@2'@v@Q`'@v@r'@v@%f'@v@.8'@v@Jl'@ v@һl]'@ v@r pr'@ v@Ԫ'@ v@Ix'@ v@'@ v@R~'@ v@''@ v@2߄'@ v@Je '@ v@c '@0v@r!'@0v@B*!'@0v@<"'@0v@2݀O"'@0v@b#'@0v@R$t#'@0v@J^ $'@0v@r$'@0v@Ҝ&%'@0v@r;%'@@v@,&'@@v@2%z&'@@v@2V2''@@v@ ''@@v@W9('@@v@2.('@@v@R,A?)'@@v@Rf5T)'@@v@fE*'@@v@sy*'@Pv@K+'@Pv@`+'@Pv@QQ,'@Pv@,'@Pv@2.W-'@Pv@v/-'@Pv@].'@Pv@ n.'@Pv@Z !d/'@Pv@r3/'@`v@KFj0'@`v@MX0'@`v@kp1'@`v@)~1'@`v@rQɐv2'@`v@h2'@`v@r|3'@`v@Re3'@`v@Fۂ4'@`v@&5'@pv@5'@pv@$ 6'@pv@T%6'@pv@c87'@pv@R'K7'@pv@R]8'@pv@2Bp8'@pv@p9'@pv@2―9'@pv@RU $:'@v@2ʿ:'@v@@_*;'@v@r߭;'@v@30<'@v@ү=<'@v@-7='@v@r|*='@v@.==>'@v@O>'@v@7[bC?'@v@t?'@v@FI@'@v@9@'@v@]٬OA'@v@xA'@v@zUB'@v@R B'@v@W[C'@v@4 C'@v@˖bD'@v@Rd6/D'@v@AhE'@v@uTE'@v@9gnF'@v@شyF'@v@zTtG'@v@G'@v@ÓzH'@v@j3H'@v@րI'@v@RrJ'@v@iJ'@v@ K'@v@Q!K'@v@ry3L'@v@,FL'@v@0YM'@v@2kM'@v@Rp~N'@v@ N'@v@ɯ"O'@v@ROO'@v@RG(P'@v@۫P'@v@..Q'@v@Q'@v@Yn5R'@v@!&R'@v@8;S'@v@2MKS'@ v@r]AT'@ v@WpT'@ v@R)-GU'@ v@̕U'@ v@rlMV'@ v@ V'@ v@SW'@ v@r]LW'@ v@:YX'@ v@RX'@ v@r+`Y'@ v@r*Y'@ v@k=fZ'@ v@ PZ'@ v@bl['@ v@tKu['@ v@^r\'@ v@rK\'@ v@9+x]'@ v@2*˿]'@ v@2k~^'@ v@ _'@ v@_'@ v@J `'@ v@`'@ v@/a'@ v@*Ba'@ v@RTb'@ v@jgb'@ v@ zc'@ w@򪌝c'@ w@2J d'@ w@걣d'@ w@&e'@ w@+שe'@ w@ ,f'@ w@R/kf'@ w@? 3g'@ w@Q!g'@ w@eK49h'@ w@{Fh'@ w@Y?i'@ w@r+li'@ w@~Ej'@ w@rkj'@ w@ Kk'@ w@#k'@ w@ELQl'@ w@il'@ w@Wm'@ w@R,m'@ w@^n'@ w@ m&n'@ w@8 9do'@ w@gKo'@ w@2M^jp'@ w@rpp'@ w@pq'@ w@4.q'@ w@2lΨvr'@0w@nr'@0w@|s'@0w@s'@0w@\Ot'@0w@ru'@0w@ߏu'@0w@$0+ v'@0w@j=v'@0w@ұpPw'@0w@Rcw'@@w@Fux'@@w@ғQx'@@w@y'@@w@r3y'@@w@҅2$z'@@w@2ҧz'@@w@20s*{'@@w@2{'@@w@ 1|'@@w@2=T|'@Pw@r/7}'@Pw@RB}'@Pw@2Z5U=~'@Pw@g~'@Pw@!vzC'@Pw@2'@Pw@ﶟI'@Pw@XẀ'@Pw@RO'@Pw@1ҁ'@`w@8U'@`w@؂'@`w@2y\'@`w@"߃'@`w@n4b'@`w@ZG'@`w@`Yh'@`w@Rܛl'@`w@Y<n'@`w@ܑ'@pw@Y}t'@pw@r'@pw@`z'@pw@R^'@pw@Ro'@pw@2'@pw@@'@pw@R& '@pw@9'@pw@2"L'@w@R^'@w@Zcq'@w@R'@w@'@w@r"E'@w@R"'@w@[Υ'@w@&('@w@2'@w@?h/'@w@'@w@2+5'@w@r2J>'@w@P;'@w@Rc'@w@5,vA'@w@R̈Ĕ'@w@mG'@w@rIʕ'@w@2M'@w@ҴOЖ'@w@mS'@w@2'֗'@w@1 Z'@w@ݘ'@w@R`s0`'@w@r!C'@w@Uf'@w@RUh'@w@pzl'@w@r8'@w@8r'@w@ز'@w@Ryx'@w@k'@w@2=~'@w@r\'@w@R'@w@"'@w@>5'@w@nG'@w@JZ'@w@(!m'@w@R'@w@b'@w@'@w@򱤷 '@w@Eʣ'@w@R&'@w@k贈'@w@W(-'@w@E'@w@R5j'3'@w@& :'@w@2L9'@w@RM_'@w@q?'@w@©'@w@2/E'@w@rЩȪ'@w@rqK'@w@2Ϋ'@w@Q'@w@2TԬ'@w@RX'@w@Rۭ'@w@ 8,^'@w@>'@w@#zQd'@w@1d'@w@Avj'@w@RS]'@w@fp'@w@|'@w@2@v'@w@'@w@rƂ|'@w@#'@w@ '@w@!f'@x@B1'@x@RfC '@x@IV'@x@h'@x@ۋ{'@x@2-'@x@2Π'@x@`o'@x@ơ'@x@±$'@x@RR맺'@x@+*'@x@b'@x@6#1'@x@5'@x@2yH7'@x@Q['@x@m='@x@\'@x@2C'@ x@\ƿ'@ x@@I'@ x@'@ x@7O'@ x@r$'@ x@V'@ x@#g'@ x@t(\'@ x@ȩ:'@ x@RKMb'@0x@u_'@0x@΍rh'@0x@)/'@0x@rЗn'@0x@q'@0x@2Et'@0x@2'@0x@ Vz'@0x@p'@0x@ؘ'@ @x@RA:'@ @x@R,'@ @x@}? '@ @x@R'@ @x@d'@ @x@2jaw'@ @x@'@ @x@S'@ @x@2E'@ @x@D'@!Px@"'@!Px@r<*'@!Px@2('@!Px@;m '@!Px@ҽ/'@!Px@A1'@!Px@QD5'@!Px@2OV'@!Px@ؔi;'@!Px@c6|'@"`x@׎A'@"`x@Ry'@"`x@G'@"`x@2'@"`x@26^M'@"`x@2'@"`x@cS'@"`x@2B'@"`x@r#Z'@"`x@r56'@#px@R'I`'@#px@t['@#px@2knf'@#px@r '@#px@Ral'@#px@ P'@#px@r'@#px@]'@#px@ 5x'@#px@ҹ'@$x@jx'@$x@'@$x@Rѻ('@$x@R];'@$x@?M'@$x@`'@$x@Bs'@$x@Rq'@$x@20'@$x@''@%x@ɽ'@%x@wk '@%x@= '@%x@&'@%x@P'@%x@-'@%x@2h-'@%x@R76@3'@%x@R'@%x@ye9'@&x@x'@&x@R?'@&x@R]_'@&x@6E'@&x@'@&x@DK'@&x@'@&x@Q'@&x@* '@&x@2wX'@'x@R]n2'@'x@rEE^'@'x@R/W'@'x@Tjd'@'x@R|'@'x@rj'@'x@9'@'x@R۴p'@'x@}'@'x@2v'@(x@R'@(x@Rc|'@(x@'@(x@$'@(x@I7'@(x@ұI'@(x@\ '@(x@R/o'@(x@ҿс'@(x@s'@)x@'@)x@ݷ'@)x@RY'@)x@ޡ'@)x@ $'@)x@@'@)x@r3+'@)x@J)'@)x@Rb&<1'@)x@R|N'@*x@Rja7'@*x@ҵ t'@*x@Rծ='@*x@P'@*x@C'@*x@r>'@*x@d7I(@*x@R(@*x@r{O(@*x@r (@+x@2V(@+x@@b.(@+x@rA\(@+x@S(@+x@Hfb(@+x@x(@+x@2Ih(@+x@R/(@+x@rѰn(@+x@2s(@,y@<t(@,y@2~(@,y@RZz(@,y@R (@,y@M (@,y@A3 (@,y@E (@,y@,X (@,y@y(k (@,y@} (@-y@2m (@-y@Rn (@-y@Rñ (@-y@2T(@-y@rڟ(@-y@R͘"(@-y@r);(@-y@r)(@-y@2%(@-y@H"8/(@. y@J(@. y@g]5(@. y@x p(@. y@ૂ;(@. y@2KN(@. y@rA(@. y@r%(@. y@r5G(@. y@(@. y@rzzM(@/0y@(@/0y@fT(@/0y@ra*(@/0y@Y=Z(@/0y@R֦O(@/0y@rTIb`(@/0y@Rt(@/0y@Vf(@/0y@r0(@/0y@^Ӭl(@0@y@u(@0@y@nr(@0@y@R(@0@y@]x(@0@y@ (@0@y@(@0@y@5E/(@0@y@RA(@0@y@^T (@0@y@,g (@1Py@Ҏy!(@1Py@)r!(@1Py@"(@1Py@Rd"(@1Py@rZ#(@1Py@2֝#(@1Py@I $(@1Py@RA$(@1Py@'%(@1Py@?!%(@2`y@R)4-&(@2`y@F&(@2`y@REoY3'(@2`y@l'(@2`y@r~9((@2`y@2[W((@2`y@?)(@2`y@ǜ)(@2`y@?E*(@2`y@;*(@3py@K+(@3py@'+(@3py@2wR,(@3py@R9m&,(@3py@9X-(@3py@²K-(@3py@U^^.(@3py@RSp.(@3py@Rd/(@3py@=/(@4y@j0(@4y@҉0(@4y@[&p1(@4y@/1(@4y@rlv2(@4y@2(@4y@2}3(@4y@RT+4(@4y@n=4(@4y@LP5(@5y@-=c5(@5y@2u 6(@5y@R󂈏6(@5y@%7(@5y@ȭ7(@5y@k8(@5y@ӛ8(@5y@9(@5y@pT9(@5y@a %:(@6y@RS:(@6y@rG=0+;(@6y@2=B;(@6y@4U1<(@6y@R.&h<(@6y@)z7=(@6y@r&l=(@6y@2%=>(@6y@%>(@6y@(UC?(@7y@R,?(@7y@22I@(@7y@9>@(@7y@rCPA(@7y@N"A(@7y@['5VB(@7y@jGB(@7y@R{mZ\C(@7y@mC(@7y@ҡbD(@8y@ҷVD(@8y@hE(@8y@2霷E(@8y@@nF(@8y@!F(@8y@@tG(@8y@Ra)G(@8y@{H(@8y@o'H(@8y@R:I(@9y@LJ(@9y@Y_J(@9y@2Kq K(@9y@RxK(@9y@rBL(@9y@2婓L(@9y@ M(@9y@2?,ϙM(@9y@RuN(@9y@RrN(@:y@#O(@:y@"O(@:y@_\,)P(@:y@Ҟ>P(@:y@ߢQ/Q(@:y@r"FdQ(@:y@fv5R(@:y@R(@:y@/;S(@:y@>ӮS(@;y@rvAT(@;y@T(@;y@'GU(@;y@x`U(@;y@ NV(@;y@RV(@;y@uJ1TW(@;y@CW(@;y@'VZX(@;y@R4iX(@<z@{`Y(@<z@@{Y(@<z@fZ(@<z@³Z(@<z@rhel[(@<z@[(@<z@7r\(@<z@O\(@<z@ y](@<z@Rz#](@=z@96^(@=z@ZH_(@=z@̀[_(@=z@RB$n`(@=z@Ҹǀ`(@=z@1ka(@=z@a(@=z@'b(@=z@U˗b(@=z@#c(@> z@2c(@> z@2(@!d(@> z@d(@> z@r3('e(@> z@һ*;e(@> z@EM-f(@> z@q`f(@> z@_s3g(@> z@︅g(@> z@r\9h(@?0z@rh(@?0z@2?i(@?0z@>Gi(@?0z@REj(@?0z@qj(@?0z@r 2Lk(@?0z@Rk(@?0z@Jy-Rl(@?0z@R@l(@?0z@RRXm(@@@z@R4dem(@@@z@x^n(@@@z@rn(@@@z@-Odo(@@@z@o(@@@z@҇jp(@@@z@r7:p(@@@z@pq(@@@z@q(@@@z@Q% wr(@APz@r(@APz@rl2}s(@APz@zEt(@APz@6Wt(@APz@Wju(@APz@|u(@APz@v v(@APz@r9Cv(@APz@w(@APz@RŊǕw(@B`z@.x(@B`z@rXx(@B`z@$vy(@B`z@y(@B`z@½$%z(@B`z@2a7z(@B`z@rgJ+{(@B`z@<\{(@B`z@Mo1|(@B`z@r|(@Cpz@Ɣ7}(@Cpz@28}(@Cpz@Rܹ=~(@Cpz@2a~(@Cpz@B$C(@Cpz@R&(@Cpz@ lJ(@Cpz@̀(@Cpz@r۳)P(@Cpz@W<Ӂ(@Dz@rNV(@Dz@aق(@Dz@Ct\(@Dz@R߃(@Dz@ub(@Dz@2k/(@Dz@RbӾh(@Dz@2[w(@Dz@Un(@Dz@rR(@Ez@Pc u(@Ez@P(@Ez@R.{(@Ez@2VOA(@Ez@[S(@Ez@bf(@Ez@k;y(@Ez@rvߋ (@Ez@(@Ez@R'(@Fz@rÓ(@Fz@ro(@Fz@降(@Fz@ܷ(@Fz@[(@Fz@ !#(@Fz@'3(@Fz@RDHF)(@Fz@bX(@Fz@k/(@Gz@4~(@Gz@ؐ5(@Gz@R|(@Gz@!;(@Gz@>Ⱦ(@Gz@iiA(@Gz@r Ĕ(@Gz@űH(@Gz@RU˕(@Gz@R'%N(@Hz@2[8і(@Hz@ҐBKT(@Hz@R]ח(@Hz@rpZ(@Hz@r?0Pe?0rH+c?(uk?(w?(wq? ? ;? jh}??iP{?9NB??ű?1-?Y}d)H?ɛ?;˲?` ?iANN?9x׏?C`ѳ??sT?I'V?s״?پ? Z?iV3!?)jݵ?3?9ټ`?F?IG? X%?hf?j?i%?)L\}+?m?ʏ?y/?I{91? p+s??^=?Y7?)MPy?Aٺ?b?y=?I%+u? qb?ɼ?D?YT?)?#Ǽ?v?75J?y律?9Hͽ? T?fZP?㑾?YlӾ?J1?hV??y-בٿ?< ?|"R.?dO?D.Zo?x,?x zd?x-)?p?pkd?pw4?p|;U?hd]7v?hDĖ?h$n?` O N?`?`ԚA?X@ݛ:?Xx`[?X|%|?P\2?PDK?P$~r?H $7?H?Ho@?HVa?@I?@|a?@\)?8<ė?8$S`\?8 &?0잗F?0D3g?0n?(j3?(t6?(\ܡ? <= ? $(E,? t M? sm??GX?e?t ?\??T[ y_?4=?C?L?z?ĘP?>$?MD?le?T0b?4 '?|?!X?t ?m9*?+J?k?l_b?TK?4?Q5?Й?ܜl^0?B#Q?q???l4p?Tv5?4?&?I6?qGW? x?ј?c?l TZ?L?4U?&F>?A2tN?A"%^?As9o?A?Ad?A7]`?A °?A$?AF?A?AVK?A)0?A}?Avr#?Aj3?AZug7D?AJHT?A>d?A.P^u?A"?A"?Ag:?A9?A I?A#?Aʲq?Ap?AX ?A+[5?A)?A9?AvD\J?AfwZ?AVJ k?AJ.{?A:{?A.G?A?Aie ?A?A,X?Ay?A?A։%?A\c5?A/CF?AV?ALg?xAjw?xA{̇?xArN6/?pAb!?pAV?pAFV?hA:m?hA*m?hA@ }?hAW ?`AA?`A+?`A@۴? AR=? A~%ڟ? An'?A^ud?AR?ABq)?A6D_'?A&7?AOH?A HX?Ai?Abvy?A52ى?A;?A͝?A?Aib?AT?A''?AzR?Aj͠ ?A^M?ANs<-?ABF>?A2tN?A&%^?As9o?A?Ad?A7]`?A °?A$?AF?A?AVK?A)0?A}?Azr#?Aj3?AZug7D?ANHT?A>d?A2P^u?A"?A"?Ag:?A9?A I?A#?Aʲq?Ap?AX ?A+[5?A)?A9?AvD\J?AfwZ?AZJ k?AJ.{?A>{?A.G?A?Aie ?A?`A,X?XAy?XA?XA։%?PA\c5?PA/CF?PAV?PALg?HAjw?HA{̇?HArN6/?@Ab!?@AV?@AFV?8A:m?8A*m?8A@ }?0AW ?0AA?0A+?0A@۴?AR=?A~%ڟ?An'?A^ud? )ac? ? ? ? u'$? ^$Y,? GK4? w1r ? e? 5ь? "? 'L*? ~2? w(:? `OB? JvK? 3BS? s[? sc? k? e8t?x _8|?x Wi?x ѕ?x I˔?p h?p ;R".?p ;I_?h -%p?h ?h ?` #?`  U?` 2?` Y?X {?X p?X kZJ?P C{?P ]-?P C?P Oj ?H @(?H Aӷq0?H ޢ8?@ 3@?@ ,I?@ %yS6Q?8 bzgY?8 La?8 5i?8 q?0 ,z?0 <]?0 qc?( Ċ?( c?( ݗ!?( UR?  j&?  GTM?  =t? 9'? H? +y? ? 6? ] ? >? o? rҠ ? y\? E ? i/G4&? ne.? [6? >? MF? ž *O? ?0[W? W_? 1{~g? do? #Nx? 7P? !? A? g? ݎ? ƵF? qw? ? c*? lQ ? SVx ?x e?p 5ь?p "?p 'L*?p ~2?h w(:?h `OB?h JvK?` 3BS?` s[?` uc?X k?X g8t?X _8|?X Yi?P ѕ?P I˔?P h?H ;R".?H ;I_?H -%p?H ?@ ?@ #?@  U?8 2?8 Y?8 {?8 p?0 mZJ?0 C{?0 _-?( C?( Oj ?( @(?( Aӷq0?  ޢ8?  3@?  ,I? %yS6Q? bzgY? La? 5i? q? ,z? <]? sc? Ċ? e? ݗ!? WR? j&? GTM? =t? 9'? H? +y? ? 6? ] ? >? o? sҠ ? y\? E ? k/G4&? ne.? ]6? >? OF? Ǿ *O? A0[W? W_? 1{~g? do? #Nx? 7P? !? A? g? ݎ? ƵF? qw? ? c*? lQ ? UVx ?X e?X 7ь?X "?P 'L*?P ~2?P w(:?P `OB?H JvK?H 3BS?H s[?@ uc?@ k?@ g8t?@ _8|?8 Yi?8 ѕ?8 K˔?0 h?0 =R".?0 ;I_?0 -%p?( ?( ?( #?(  U? 2? Y? {? p? mZJ? C{? _-? C? Qj ? @(? Cӷq0? ޢ8? 5@? ,I? 'yS6Q? bzgY? La? 5i? q? ,z? <]? uc? Ċ? e? ߗ!? WR? j&? ITM? =t? ;'? H? -y? ? 6? ] ? >? o? sҠ ? {\? E ? m/G4&? ne.? ]6? >? OF? ɾ *O? A0[W? W_? 3{~g? do? %Nx? 7P? !? A? g? ݎ? ƵF? sw? ? c*? lQ ? UVx ?H e?H 7ь?H "?@ )L*?@ ~2?@ w(:?@ `OB?8 JvK?8 3BS?8 s[?8 wc?0 k?0 i8t?0 _8|?( [i?( ӕ?( M˔?( h? =R".? ;I_? /%p? ? !? #?  U? 2? Y? }? p? oZJ? C{? a-? C? Sj ? @(? Cӷq0? ޢ8? 5@? ,I? 'yS6Q? bzgY? La? 5i? q? ,z? <]? uc? Ċ? g? ߗ!? YR? j&? KTM? =t? ;'? H? -y? ? 6? ] ? >? o? sҠ ? {\? E ? m/G4&? ne.? _6? >? QF? ɾ *O? A0[W? W_? 3{~g? do? %Nx? 7P? !? A? g? ݎ? ƵF? sw? ? e*? lQ ? WVxIp?P1at?P ezx?P|?Hf ?H#Ą?H܈?HhF?@X ?@Rm&?@??@;W?8J'p?8%?8ÙN?8⹭?0;uұ?0?0l?0q/?(-V4?(VM?(?e?(b}~? )? ۝? 8? T?^?p?*?FZC?Ϭ[?C@t?{ӌ?7-g???m! ?)?tH ?8?^^oQ?j ?G$?)(?P1,? P0?4?w8?B =?x.A?1GE?wb_I?3XxM?KQ?U?i5Y?%]?:a? f?Za$j?}?"?#?s 2?/JK?c?jq|?d?!T?+Ư?=޳?VR?'?ϛy(? A?HY?3r?nNJ?}Z?:X?́?A?o?++<?6?cO?ag??r?簱?R\D? ?Ek ??D/,?%E?]?yLv"?6&?vs*?x.?xk`2?x'-6?xI ;?xT"??p]3:C?p{SG?plK?pO?hN6S?h {ɵW?h\[?hd_?`@كc?`Mh?`ª0l?`u7>Ip?X2at?X ezx?X|?Xg ?P#Ą?P܈?PhF?PY ?PRm&?H??H;W?HJ'p?H%?@ÙN?@⹭?@?"?#?t 2?0JK?c?jq|?e?"T?+Ư?=޳?WR?'?Лy(? A?IY?3r?nNJ?~Z?:X?́?A?o?,+<?6?cO?ag??r?簱?S\D? ?Ek ??D/,?%E?]?zLv"?6&?vs*?.?k`2?(-6?I ;?T"??]3:C?{SG?lK?O?O6S? {ɵW?\[?d_?@كc?Mh?xª0l?xv7>Ip?x2at?x ezx?p|?pg ?p$Ą?p܈?phF?hY ?hRm&?h??h;W?`K'p?`%?`ÙN?`⹭?`Ip?2at? ezx?|?h ?$Ą?܈?hF?Y ?Rm&???;W?K'p?%?ęN?⹭?=uұ??l?r/?/V4?VM??e?d}~? )?ݝ?x8?xV?x^?xp?x*?pGZC?pϬ[?pC@t?p}ӌ?p9-g?h?h?hn! ?h+?htH ?h8?``^oQ?`j ?`G$?`)(?`R1,?XP0?X4?Xw8?XC =?Xy.A?P1GE?Pxb_I?P5XxM?PKQ?PU?Hj5Y?H']?H:a?H f?H\a$j?@}Ip?3at? ezx?|?h ?%Ą?܈?hF?Z ?Rm&???;W?L'p?%?řN?⹭?=uұ??l?s/?/V4?VM??e?d}~?!)?ݝ?8?V?^?p?*?HZC?Ϭ[?C@t?}ӌ?9-g???o! ?+?tH ?8?`^oQ?j ?G$?)(?R1,?P0?4?w8?D =?y.A?1GE?yb_I?5XxM?KQ?U?k5Y?']?:a? f?\a$j?}Ip?84at?8 ezx?8|?0i ?0%Ą?0܈?0hF?0[ ?0Rm&?(??(;W?(L'p?( %?(řN?(⹭? >uұ? ? l? s/? 0V4? VM? ?e?e}~?!)?ޝ?8?V?^?p?*?HZC?Ϭ[?C@t?}ӌ?:-g???o! ?+?tH ?8?a^oQ?j ?G$?)(?R1,?P0?4?w8?D =?y.A?1GE?yb_I?6XxM?KQ?U?k5Y?']?:a? f?]a$j?}Ip?4at? ezx?|?i ?&Ą?܈?hF?[ ?Rm&???;W?M'p? %?řN?⹭?>uұ??l?t/?0V4?VM??e?e}~?")?ޝ?8?W?^?p?*?IZC?Ϭ[?C@t?x~ӌ?x:-g?x?x?xp! ?x,?xtH ?x8?pa^oQ?pj ?pG$?p)(?pS1,?pP0?p4?hw8?hE =?hy.A?h1GE?hzb_I?h6XxM?hKQ?hU?`l5Y?`(]?`:a?` f?`]a$j?`}Ip? 4at?  ezx? |? j ?&Ą?܈?hF?[ ?Rm&???;W?M'p? %?ƙN?⹭??uұ??l?t/?0V4?VM??e?f}~?")?ޝ?8?W?^?p?*?IZC?Ϭ[?C@t?~ӌ?;-g???p! ?,?tH ?8?a^oQ?j ?G$?)(?S1,?P0?4?w8?E =?y.A?1GE?zb_I?6XxM?KQ?U?l5Y?(]?:a? f?]a$j?}@4U@@HbB@HyYnD@O4zF@ȭH@H 6J@HjcL@HʫN@&P@Ȅ]R@HLT@HAV@H:X@{Z@[6]@H_@Haa@ve&c@2e@2>?g@HKi@HNWk@M dm@ȫepo@ ~|q@Hh8s@HBu@$w@Ȃg֭y@H! {@H?i}@H@Pށ@Y G@HŐ@H@Ht:$@m@0(@Hi5@H#KA@KޔM@ȩY@S(f@Hf rr@Hǻ~@"@Ȁz@H*@HI 7@ȧmWC@(O@Hd[@Hœ4h@ W~t@~Ȁ@@H;[@H@@@U8@ȳo@H*@Hp@Ξ_@,Y@H@H<@HG @xȥB,@x9@xHbcE@xHqQ@x,]@x|@j@xH۠v@xH9[Ԃ@xH@xg@xS@xHD@xHD@pn@ps@p*."@pHk@pH碵@pE] @pȣI @pҒ" @pH`.@pHF&;@ppG@pzS@pHu`@hH70Ml@hHx@h@hQ_*@hHt!@hHԽ#@hHl%@hHQ'@h()@hH+@hHw.-@hC2x/@hȡ1@h 4@`H^aU6@`H$8@`0:@`x2=<@`J|I>@`H5U@@`HbB@`yYnD@`O4zF@`HH@`H 6J@`HjcL@`ʫN@`&P@XH]R@XHLT@XHAV@Xȟ:X@X{Z@XH\6]@XH_@Xaa@Xve&c@X2e@XH3>?g@XHKi@XNWk@XM dm@Xȫepo@PH ~|q@PHh8s@PBu@P$w@PHg֭y@PH! {@PH?i}@Pȝ@PPށ@PHZ G@PHŐ@PH@Pt:$@Pm@PH1(@PHi5@H#KA@HKޔM@HȩY@HHS(f@HHf rr@Hǻ~@H"@HȀz@@*@@I 7@@HmWC@@H(O@@Hd[@@œ4h@@ W~t@@HȀ@@H@@;[@@ș@@@@@HV8@@Ho@8*@8p@8Ξ_@8H-Y@8H@8<@8G @8HB,@8H9@8HbcE@8qQ@8,]@8H}@j@8H۠v@8H9[Ԃ@8ȗ@8g@8HT@8HD@0D@0n@0s@0H+."@0Hk@0碵@0E] @0ȣI @0HҒ" @0H`.@0ȾF&;@0pG@0H{S@0Hu`@0H70Ml@0ȕx@0@0HR_*@0Ht!@0HԽ#@(l%@(HQ'@(H))@(H+@(w.-@(C2x/@(ȡ1@(H 4@(H^aU6@(ȼ$8@(0:@(x2=<@(HJ|I>@(H5U@@(ȓbB@(yYnD@(HP4zF@(HH@(H 6J@(jcL@(ʫN@ H'P@ H]R@ HLT@ AV@ ȟ:X@ H{Z@ H\6]@ Ⱥ_@ aa@ ve&c@ H2e@ H3>?g@ ȑKi@ NWk@ M dm@ Hepo@ H ~|q@ h8s@ Bu@ H%w@ Hg֭y@ H! {@ ?i}@ ȝ@HPށ@HZ G@HŐ@@t:$@Hm@H1(@Hi5@#KA@KޔM@HY@HS(f@f rr@ǻ~@"@Hz@*@I 7@HmWC@H(O@Hd[@œ4h@ W~t@HȀ@H@;[@ș@@@HV8@Ho@*@p@Ξ_@H-Y@H@<@G @HB,@H9@HbcE@qQ@,]@H}@j@H۠v@H9[Ԃ@ȗ@g@HT@HD@D@n@s@H+."@Hk@碵@E] @ȣI @HҒ" @H`.@ȾF&;@pG@H{S@Hu`@H70Ml@ȕx@@HR_*@Ht!@HԽ#@l%@HQ'@H))@H+@w.-@C2x/@ȡ1@H 4@H^aU6@ȼ$8@0:@x2=<@HJ|I>@H5U@@ȓbB@yYnD@HP4zF@HH@H 6J@jcL@ʫN@H'P@H]R@LT@AV@H:X@H{Z@H\6]@Ⱥ_@aa@Hwe&c@H2e@3>?g@ȑKi@NWk@HN dm@Hepo@ ~|q@h8s@Bu@H%w@Hg֭y@! {@?i}@H@HPށ@HZ G@ȸŐ@@Hu:$@Hm@H1(@ȏi5@#KA@HLޔM@HY@S(f@f rr@ǻ~@H#@Hz@*@HJ 7@HmWC@H(O@d[@œ4h@H!W~t@HȀ@@;[@ș@@H@HV8@ȴo@*@p@HϞ_@H-Y@ȋ@<@HH @HB,@H9@bcE@qQ@H,]@H}@j@H۠v@9[Ԃ@ȗ@Hg@HT@ȲD@D@n@Hs@H+."@ȉk@碵@E] @HI @HҒ" @`.@ȾF&;@HpG@H{S@Hu`@70Ml@ȕx@H@HR_*@Ȱt!@Խ#@Hm%@HHQ'@H))@ȇ+@w.-@HD2x/@H1@ 4@^aU6@ȼ$8@H0:@Hy2=<@J|I>@5U@@ȓbB@HyYnD@HP4zF@ȮH@ 6J@HkcL@HʫN@H'P@ȅ]R@LT@HBV@H:X@H{Z@\6]@Ⱥ_@Haa@Hwe&c@2e@3>?g@ȑKi@HNWk@HN dm@Ȭepo@ ~|q@h8s@HBu@H%w@ȃg֭y@! {@H@i}@H@HPށ@Z G@ȸŐ@H@Hu:$@Hm@1(@ȏi5@H#KA@HLޔM@ȪY@S(f@f rr@Hǻ~@H#@ȁz@H*@HJ 7@HmWC@(O@d[@HÜ4h@H!W~t@Ȁ@@;[@H@@H@V8@ȴo@*@Hq@HϞ_@-Y@ȋ@H<@HH @HB,@9@bcE@HqQ@H,]@}@j@۠v@H:[Ԃ@H@Hg@T@ȲD@HD@Ho@s@+."@ȉk@H袵@HF] @ȤI @Ғ" @`.@HF&;@HpG@{S@u`@H80Ml@Hx@H@R_*@Ȱt!@HԽ#@Hm%@HHQ'@))@ȇ+@Hw.-@HD2x/@Ȣ1@ 4@^aU6@H$8@H0:@y2=<@J|I>@5U@@HbB@HyYnD@P4zF@ȮH@H 6J@HkcL@HʫN@'P@ȅ]R@HLT@HBV@H:X@{Z@\6]@H_@Haa@we&c@2e@3>?g@HKi@HNWk@N dm@Ȭepo@ ~|q@Hi8s@HBu@%w@ȃg֭y@H! {@H@i}@H@Pށ@Z G@HŐ@H@Hu:$@m@1(@Hi5@H#KA@LޔM@ȪY@S(f@Hg rr@Hǻ~@#@ȁ⯤@Hk,@%vȨ@XԪ@H @HUS@Hs@@/0@H>z@H*@ J 7@ ȨmWC@ H(O@ He[@ HÜ4h@ !W~t@ Ȁ@ H@ H<[@ Ț@@ @ V8@ Ho@ H*@ q@ Ϟ_@ -Y@ H@ H<@ H @ ȦB,@ H9@ HccE@ HqQ@(,]@(}@j@(Hܠv@(H:[Ԃ@(H@(g@(T@(HD@(HD@(o@(s@(+."@(Hk@(H袵@(F] @(ȤI @(Ғ" @(Ha.@(HF&;@(pG@({S@0Hu`@0H80Ml@0Hx@0@0R_*@0Ht!@0HԽ#@0Hm%@0HQ'@0))@0H+@0Hw.-@0D2x/@0Ȣ1@0 4@0H_aU6@0H$8@00:@0y2=<@0J|I>@8H6U@@8HbB@8yYnD@8P4zF@8HH@8H 6J@8HkcL@8ʫN@8'P@8H]R@8HLT@8HBV@8Ƞ:X@8{Z@8H]6]@8H_@8aa@8we&c@82e@@H4>?g@@HKi@@NWk@@N dm@@Ȭepo@@H ~|q@@Hi8s@@Bu@@%w@@Hg֭y@@H! {@@H@i}@@Ȟ@@Pށ@@H[ G@@HŐ@@@Hu:$@HHm@HH2(@HHi5@H#KA@HLޔM@HHY@HH S(f@Hg rr@Hǻ~@H#@HH⯤@HȜk,@H%vȨ@PHYԪ@PH @PUS@Ps@PH@PH00@PH>z@P*@PJ 7@PHmWC@PH(O@PHe[@PÜ4h@P!W~t@PHȀ@PH@X<[@XȚ@@X@XHW8@XHo@X*@Xq@XϞ_@XH.Y@XH@X<@XH @XHB,@XH9@XHccE@`qQ@`,]@`H~@j@`Hܠv@`H:[Ԃ@`Ș@`g@`HU@`HD@`D@`o@`s@`H,."@`Hk@h袵@hF] @hȤI @hHҒ" @hHa.@hȿF&;@hpG@hH|S@hHu`@hH80Ml@hȖx@h@hHS_*@hHt!@pHԽ#@pm%@pHQ'@pH*)@pH+@pw.-@pD2x/@pȢ1@pH 4@pH_aU6@pȽ$8@p0:@py2=<@xHJ|I>@xH6U@@xȔbB@xyYnD@xHQ4zF@xHH@xH 6J@xkcL@xʫN@xH(P@xH]R@xLT@xBV@H:X@H{Z@H]6]@Ȼ_@aa@Hxe&c@H2e@4>?g@ȒKi@NWk@HO dm@Hepo@ ~|q@i8s@Bu@H&w@Hg֭y@! {@@i}@H@HPށ@H[ G@ȹŐ@@Hv:$@Hm@H2(@Ȑi5@#KA@HMޔM@HY@ S(f@g rr@ǻ~@H$@H⯤@Ȝk,@H%vȨ@HYԪ@ȷ @US@Ht@H@H00@Ȏ>z@*@HK 7@HmWC@H(O@e[@Ü4h@H"W~t@HȀ@@<[@Ț@@H@HW8@ȵo@*@q@HО_@H.Y@Ȍ@<@HI @HB,@H9@ccE@qQ@H ,]@H~@j@Hܠv@:[Ԃ@Ș@Hg@HU@ȳD@D@o@Hs@H,."@Ȋk@袵@F] @HI @HҒ" @a.@ȿF&;@HpG@H|S@Hu`@80Ml@Ȗx@H@HS_*@ȱt!@Խ#@Hn%@HHQ'@H*)@Ȉ+@w.-@HE2x/@H1@ 4@_aU6@Ƚ$8@H0:@Hz2=<@J|I>@6U@@ȔbB@HyYnD@HQ4zF@ȯH@ 6J@HlcL@HʫN@H(P@Ȇ]R@LT@HCV@H:X@H{Z@]6]@Ȼ_@Haa@Hxe&c@2e@4>?g@ȒKi@HNWk@HO dm@ȭepo@ ~|q@i8s@HBu@H&w@Ȅg֭y@! {@HAi}@H@HPށ@[ G@ȹŐ@H@Hv:$@Hm@2(@Ȑi5@H#KA@HMޔM@ȫY@ S(f@g rr@Hǻ~@H$@Ȃ⯤@Hk,@H%vȨ@YԪ@ȷ @HUS@Ht@H@00@Ȏ>z@H*@HK 7@HmWC@(O@e[@HĜ4h@H"W~t@ȀȀ@@<[@H@@H@W8@ȵo@*@Hr@HО_@.Y@Ȍ@H<@HI @HB,@9@ccE@HqQ@H ,]@~@j@ܠv@H;[Ԃ@H@Hg@U@ ȳD@ HD@ Hp@ s @ ,." @ Ȋk @ H颵 @ HG] @ ȥI @(Ғ" @(a. @(HF&; @(HpG @(|S @(u` @(H90Ml @(Hx @0H @0S_* @0ȱt! @0HԽ# @0Hn% @0HHQ' @0*) @0Ȉ+ @8Hw.- @8HE2x/ @8ȣ1 @8 4 @8_aU6 @8H$8 @8H0: @8z2=< @@J|I> @@6U@ @@HbB @@HyYnD @@Q4zF @@ȯH @@H6J @@HlcL @@HʫN @H(P @HȆ]R @HHLT @HHCV @HH:X @H{Z @H]6] @PH_ @PHaa @Pxe&c @P2e @P4>?g @PHKi @PHNWk @PO dm @Xȭepo @X ~|q @XHj8s @XHBu @X&w @XȄg֭y @XH! { @XHAi} @`H @`Pށ @`[ G @`HŐ @`H @`Hv:$ @`m @`2( @hHi5 @hH#KA @hMޔM @hȫY @h S(f @hHh rr @hHǻ~ @h$ @pȂz @xH* @xK 7 @xȩmWC @H(O @Hf[ @HĜ4h @"W~t @ȀȀ @H @H=[ @ț@ @ @W8 @Ho @H* @r @О_ @.Y @H @H< @I @ȧB, @H9 @HdcE @HqQ @ ,] @~@j @Hݠv @H;[Ԃ @H @g @U @HD @HD @p @s @,." @Hk @H颵 @G] @ȥI @Ғ" @Hb. @HF&; @pG @|S @Hu` @H90Ml @Hx @ @S_* @Ht! @HԽ# @Hn% @HQ' @*) @H+ @Hw.- @E2x/ @ȣ1 @ 4 @H`aU6 @H$8 @0: @z2=< @J|I> @H7U@ @HbB @yYnD @Q4zF @HH @H6J @HlcL @ʫN @(P @H]R @HLT @HCV @ȡ:X @{Z @H^6] @H_ @aa @xe&c @2e @H5>?g @HKi @NWk @O dm @ȭepo @H ~|q @Hj8s @Bu @&w @Hg֭y @H! { @HAi} @ȟ @Pށ @H\ G @HŐ @ @v:$ @Hm @H3( @Hi5 @#KA @MޔM @HY @H S(f @h rr @ǻ~ @$ @Hz @* @K 7 @HmWC @H(O @Hf[ @Ĝ4h @"W~t @HȀ @H @=[ @ț@ @ @HX8 @Ho @ * @ r @ О_ @ H/Y @ H @ < @ I @(HB, @(H9 @(HdcE @(qQ @( ,] @(H@j @0Hݠv @0H;[Ԃ @0ș @0g @0HV @0HD @8D @8p @8s @8H-." @8Hk @8颵 @@G] @@ȥI @@HҒ" @@Hb. @@F&; @@pG @HH}S @HHu` @HH90Ml @Hȗx @H @HHT_* @PHt! @PHԽ# @Pn% @PHQ' @PH+) @PH+ @Pw.- @XE2x/ @Xȣ1 @XH 4 @XH`aU6 @XȾ$8 @X0: @`z2=< @`HJ|I> @`H7U@ @`ȕbB @`yYnD @`HR4zF @hHH @hH6J @hlcL @hʫN @hH)P @pH]R @pLT @pCV @pH:X @pH|Z @pH^6] @xȼ_ @xaa @xHye&c @xH2e @x5>?g @xȓKi @NWk @HP dm @Hepo @ ~|q @j8s @Bu @H'w @Hg֭y @! { @Ai} @H @HPށ @H\ G @ȺŐ @ @Hw:$ @Hm @H3( @ȑi5 @#KA @HNޔM @HY @ S(f @h rr @ǻ~ @H% @Hz @* @HL 7 @HmWC @H(O @f[ @Ĝ4h @H#W~t @HȀ @ @=[ @ț@ @H @HX8 @ȶo @* @r @Hў_ @H/Y @ȍ @< @HJ @HB, @H9 @dcE @qQ @H!,] @H@j @Hݠv @;[Ԃ @ș @Hg @HV @ȴD @D @p @Hs @H-." @ȋk @颵 @G] @HI @HҒ" @b. @F&; @HpG @H}S @Hu` @90Ml @ȗx @H @HT_* @Ȳt! @Խ# @Ho% @HHQ' @H+) @ȉ+ @w.- @HF2x/ @H1 @ 4 @`aU6 @Ⱦ$8 @H0: @H{2=< @J|I> @7U@ @ȕbB @HyYnD @HR4zF @ȰH @6J @HmcL @HʫN @ H)P @ ȇ]R @ LT @ HDV @ H:X @(H|Z @(^6] @(ȼ_ @(Haa @(Hye&c @02e @05>?g @0ȓKi @0HNWk @0HP dm @8Ȯepo @8 ~|q @8j8s @8HBu @8H'w @8ȅg֭y @@! { @@HBi} @@H @@HPށ @@\ G @HȺŐ @HH @HHw:$ @HHm @H3( @Pȑi5 @PH#KA @PHNޔM @PȬY @P S(f @Xh rr @XHǻ~ @XH% @Xȃz @hH* @pHL 7 @pHmWC @p(O @pf[ @pHŜ4h @xH#W~t @xȁȀ @x @x=[ @xH@ @H @X8 @ȶo @* @Hs @Hў_ @/Y @ȍ @H< @HJ @HB, @9 @dcE @HqQ @H!,] @@j @ݠv @H<[Ԃ @H @Hg @V @ȴD @HD @Hq @s @-." @ȋk @Hꢵ @HH] @ȦI @Ғ" @b. @HF&; @HpG @}S @u` @H:0Ml @Hx @H @T_* @Ȳt! @HԽ# @Ho% @HHQ' @+) @ȉ+ @Hw.- @HF2x/ @Ȥ1 @ 4 @`aU6 @H$8 @H0: @{2=< @J|I> @7U@ @HbB @HyYnD @R4zF @ȰH @H6J @HmcL @HʫN @)P @ȇ]R @HLT @HDV @H:X @|Z @^6] @H_ @Haa @ye&c @2e @5>?g @HKi @HNWk @P dm @Ȯepo @ ~|q @Hk8s @HBu @'w @ȅg֭y @H! { @HBi} @H @Pށ @\ G @HŐ @H @Hw:$ @m @3( @Hi5 @H#KA @NޔM @ ȬY @ S(f @ Hi rr @ Hǻ~ @ % @(ȃz @8H* @8L 7 @@ȪmWC @@H (O @@Hg[ @@HŜ4h @H#W~t @HȁȀ @HH @HH>[ @HȜ@ @P @PX8 @PHo @PH* @Ps @Xў_ @X/Y @XH @XH< @`J @`ȨB, @`H9 @`HecE @`HqQ @h!,] @h@j @hHޠv @hH<[Ԃ @pH @pg @pV @pHD @pHD @xq @xs@x-."@xHk@Hꢵ@H] @ȦI @Ғ" @Hc.@HF&;@pG@}S@Hu`@H:0Ml@Hx@@T_*@Ht!@HԽ#@Ho%@HQ'@+)@H+@Hw.-@F2x/@Ȥ1@ 4@HaaU6@H$8@0:@{2=<@J|I>@H8U@@HbB@yYnD@R4zF@HH@H6J@HmcL@ʫN@)P@H]R@HLT@HDV@Ȣ:X@|Z@H_6]@H_@aa@ye&c@2e@H6>?g@HKi@NWk@P dm@Ȯepo@H ~|q@Hk8s@Bu@'w@Hg֭y@H! {@HBi}@Ƞ@Pށ@H] G@HŐ@@w:$@Hm@H4(@Hi5@#KA@NޔM@HY@H S(f@i rr@ǻ~@%@Hz@*@L 7@ HmWC@ H (O@ Hg[@ Ŝ4h@(#W~t@(HȀ@(H@(>[@0Ȝ@@0@0HY8@0Ho@0*@8s@8ў_@8H0Y@8H@@<@@J @@HB,@@H9@HHecE@HqQ@H!,]@HH@j@PHޠv@PH<[Ԃ@PȚ@Pg@PHW@XHD@XD@Xq@Xs@`H.."@`Hk@`ꢵ@`H] @hȦI @hHҒ" @hHc.@hF&;@ppG@pH~S@pHu`@pH:0Ml@xȘx@x@xHU_*@xHt!@xHԽ#@o%@HQ'@H,)@H+@w.-@F2x/@Ȥ1@H 4@HaaU6@ȿ$8@0:@{2=<@HJ|I>@H8U@@ȖbB@yYnD@HS4zF@HH@H6J@mcL@ʫN@H*P@H]R@LT@DV@H:X@H|Z@H_6]@Ƚ_@aa@Hze&c@H2e@6>?g@ȔKi@NWk@HQ dm@Hepo@ ~|q@k8s@Bu@H(w@Hg֭y@! {@Bi}@H@HPށ@H] G@ȻŐ@@Hx:$@Hm@H4(@Ȓi5@#KA@HOޔM@HY@ S(f@i rr@ǻ~@H&@Hz@*@HM 7@HmWC@H (O@g[@Ŝ4h@H$W~t@HȀ@@ >[@ Ȝ@@ H@ HY8@(ȷo@(*@(s@(HҞ_@0H0Y@0Ȏ@0<@0HK @8HB,@8H9@8ecE@8qQ@@H",]@@H@j@@Hޠv@@<[Ԃ@HȚ@HHg@HHW@HȵD@PD@Pq@P$9ll@P$r@XdFx@Xdu~@Xd@XӋ$@`iI@`1Fn@``#@`$ @h$ܩ @h$ @hd& @hdLuK @p{Rp@p/@p @p@x$8@x$g(@x$M@xd^r@d;@#@R@@䰰* @ߍO@$kt@$>H@dm%$@d* @d1!@,7"@)Q=#@XwvC$@TI%@$1O&@$U'@$ \(@dD.b)@dsSh*@xn+@`t,@>z-@/.@^ /@$00@$U1@dz2@dm3@dJJĥ4@y'5@6@27@W8@5|9@$ey:@$V;@d3<@d=@!4>@PY?@~@@䮅A@bB@$ @D@$<E@$k6F@d[G@dɴH@ I@'o&J@VL,K@)3L@99M@$]?N@$EO@dBKP@dq{QQ@dXWR@5^S@;dT@-_jU@\̈́pV@$vW@$|X@$dY@dBZ@dH=[@wa\@ن]@ն^@Ч_@3q`@$cNa@$+?b@ddc@dd@ díe@ Nf@ }}g@ Zh@(7Ai@( fj@($:k@($iϯl@0dm@0dljo@0f p@8%DCq@8T!hr@8s@8۱"t@@$(u@@$.v@@d@s 5w@@doPE;x@H-jAy@H Gz@HM{@H+S|@PZY}@P$"`~@P$\Gf@Xd9ll@Xdr@XdFx@Xu~@`@`Ӌ$@`iI@`1Fn@h$a#@h$@hdܩ@hd@p&@pLuK@p{RpŽ@x/ȏ@x ΐ@x$ ԑ@x$8ے@$g(@dM@d^r@;@#@R@@䰰* @$O@$kt@d>H@dm%$@d*@1@,7@)Q=@XwvC@$TI@$1O@$U@d \@dD.b@sSh@xn@`t@>z@/瀮@$_ @$0@dU@dz@dm@JJĥ@y'髵@@2@W@$6|Ĺ@$eyʺ@dVл@d3ּ@ݽ@!4@PY@~@䮅@$b@$ @@$<@dk6@d[@ɴ@ @'o&@VL,@)3@$99@$]?@dE@dBK@dq{Q@XW@5^@;d@-_j@$]̈́p@$v@$|@dd@dB@H=@wa@ن@ն@ $Ч@ $4q@ $cN@(d+?@(dd@(@(í@0N@0}}@0Z@0$7A@8$ f@8d:@8diϯ@@d@@lj@@f @@%DC@HT!h@H$@H$۱"@P$(@Pd.@Pd@s 5@PoPE;@X-jA@X G@XM@X+S@`$[Y@`$"`@`d\Gf@hd9ll@hdr@hFx@hu~@p䤮@pӋ$@piI@x$2Fn@x$a#@xd @xdܩ @ @& @LuK @{Rp@/@$ @$ @$8@dg(@dM@^r@;@#@R@@$* @$O@dkt@d>H@dm%$@* @1!@,7"@)Q=#@$YwvC$@$TI%@$1O&@dU'@d \(@D.b)@sSh*@xn+@`t,@>z-@$0.@$_ /@d00@dU1@dz2@m3@JJĥ4@y'5@6@27@$W8@$6|9@dey:@dV;@3<@=@!4>@PY?@~@@$A@$bB@d @D@d<E@k6F@[G@ɴH@ I@'o&J@$WL,K@$)3L@d99M@d]?N@dEO@BKP@q{QQ@XWR@5^S@ ;dT@ $._jU@ $]̈́pV@(dvW@(d|X@(dY@(BZ@0H=[@0wa\@0ن]@8$ֶ^@8$Ч_@8$4q`@8dcNa@@d+?b@@dc@@d@Híe@HNf@H}}g@H$Zh@P$7Ai@Pd fj@Pd:k@Xdiϯl@Xm@Xljo@Xf p@`%DCq@`$U!hr@`$s@h$۱"t@hd(u@hd.v@p@s 5w@poPE;x@p-jAy@p Gz@xM{@x$,S|@x$[Y}@d"`~@d\Gf@d9ll@r@Fx@u~@䤮@Ӌ$@$iI@$2Fn@da#@d@ܩ@@&@LuK@{RpŽ@$/ȏ@$ ΐ@$ ԑ@d8ے@dg(@M@^r@;@#@R@$@$* @dO@dkt@d>H@m%$@*@1@,7@$*Q=@$YwvC@$TI@d1O@dU@ \@D.b@sSh@䢃xn@$`t@$>z@$0瀮@d_ @d0@U@z@m@JJĥ@y'髵@$@$2@dW@d6|Ĺ@deyʺ@Vл@3ּ@ݽ@!4@$QY@$~@$@db@d @@ <@ k6@ [@(ɴ@( @($(o&@($WL,@0d)3@0d99@0d]?@8E@8BK@8q{Q@8XW@@5^@@$;d@@$._j@Hd]̈́p@Hdv@H|@Pd@PB@PH=@Pwa@X$ن@X$ֶ@X$Ч@`d4q@`dcN@`+?@`d@h@hí@hN@p$~}@p$Z@pd7A@xd f@xd:@xiϯ@x@lj@f @$&DC@$U!h@$@d۱"@d(@.@@s 5@oPE;@-jA@ G@$M@$,S@d[Y@d"`@d\Gf@9ll@r@Fx@u~@䤮@$ԋ$@$iI@d2Fn@da#@ @ܩ @ @& @LuK @$|Rp@$/@d @d @8@g(@M@^r@;@$$@$S@d@d* @dO@kt@>H@m%$@* @1!@$,7"@$*Q=#@dYwvC$@dTI%@1O&@U'@ \(@D.b)@sSh*@$xn+@$`t,@$>z-@d0.@d_ /@00@U1@z2@ m3@ JJĥ4@ $z'5@($6@(d27@(dW8@0d6|9@0ey:@0V;@03<@8=@8$"4>@8$QY?@@$~@@@dA@@dbB@H @D@H<E@Hk6F@P[G@PɴH@P$ I@P$(o&J@XdWL,K@Xd)3L@Xd99M@`]?N@`EO@`BKP@hq{QQ@hXWR@h$5^S@h$;dT@pd._jU@pd]̈́pV@pvW@x|X@xdY@xBZ@H=[@$xa\@$ن]@$ֶ^@dЧ_@d4q`@cNa@+?b@dc@d@íe@$Of@$~}g@dZh@d7Ai@d fj@:k@iϯl@䘬m@ljo@$f p@$&DCq@$U!hr@ds@d۱"t@(u@.v@@s 5w@oPE;x@$-jAy@$ Gz@$M{@d,S|@d[Y}@"`~@\Gf@9ll@r@Fx@$v~@$@dԋ$@diI@d2Fn@a#@@ܩ@@$&@$MuK@$|RpŽ@d/ȏ@d ΐ@ ԑ@8ے@g(@䖁M@^r@$;@$$@dS@d@d* @O@kt@>H@ m%$@ *@ $1@($,7@(d*Q=@(dYwvC@0TI@01O@0U@0 \@8D.b@8$tSh@8$xn@@$`t@@d>z@@d0瀮@H_ @H0@H佲U@Hz@Pm@P$KJĥ@P$z'髵@Xd@Xd2@XdW@`6|Ĺ@`eyʺ@`Vл@h3ּ@h$ݽ@h$"4@h$QY@pd~@pd@pb@x @@x<@xk6@[@$ʴ@$ @d(o&@dWL,@d)3@99@]?@E@BK@q{Q@$XW@$5^@d;d@d._j@]̈́p@v@|@d@B@$I=@$xa@dن@dֶ@Ч@4q@cN@+?@d@$@$ í@dO@d~}@dZ@7A@ f@:@iϯ@䘬@$ȉ@$f @d&DC@dU!h@@۱"@(@.@@s 5@$pPE;@$-jA@$ G@dM@d,S@[Y@"`@\Gf@9ll@r@$Gx@$v~@d@dԋ$@diI@2Fn@a#@ @ ܩ @ $ @($& @($MuK @(d|Rp@0d/@0 @0 @88@8g(@8䖁M@8$^r@@$;@@d$@@dS@Hd@H* @HO@Pkt@P>H@Pm%$@X$* @X$1!@Xd,7"@Xd*Q=#@`YwvC$@`TI%@`1O&@hU'@h \(@h$E.b)@p$tSh*@p$xn+@pd`t,@xd>z-@x0.@x_ /@00@佲U1@z2@$m3@$KJĥ4@dz'5@d6@d27@W8@6|9@ey:@V;@$3<@$=@$"4>@dQY?@d~@@A@bB@ @D@<E@$l6F@$[G@$ʴH@d I@d(o&J@WL,K@)3L@99M@]?N@EO@$CKP@$r{QQ@dXWR@d5^S@d;dT@._jU@]̈́pV@䌪vW@仇|X@$dY@$BZ@$I=[@dxa\@dن]@ֶ^@Ч_@4q`@cNa@+?b@$dc@$d@d íe@dOf@d~}g@Zh@7Ai@ fj@:k@iϯl@$m@$ȉo@df p@d&DCq@ U!hr@ s@ ۱"t@ (u@(.v@($As 5w@($pPE;x@0$-jAy@0d Gz@0dM{@8,S|@8[Y}@8"`~@@\Gf@@9ll@@$r@H$Gx@Hdv~@Hd@Hdԋ$@PiI@P2Fn@Pa#@X@X$ܩ@X$@`$&@`dMuK@`d|RpŽ@h/ȏ@h ΐ@h ԑ@p8ے@pg(@p$M@p$^r@xd;@xd$@xdS@@* @O@kt@>H@$n%$@$*@d1@d,7@*Q=@YwvC@TI@1O@U@$ \@$E.b@dtSh@dxn@`t@>z@0瀮@_ @0@$U@$z@dm@dKJĥ@dz'髵@@2@W@6|Ĺ@eyʺ@$Vл@$3ּ@dݽ@d"4@QY@~@@b@ @@$=@$l6@$[@dʴ@d @(o&@WL,@)3@99@]?@$E@$CK@dr{Q@dXW@d5^@;d@._j@]̈́p@䌪v@$|@$d@$B@ dI=@ dxa@ ن@(ֶ@(Ч@(4q@0cN@0$+?@0$d@8d@8d í@8dO@@~}@@Z@@7A@H f@H:@H$jϯ@H$@Pdȉ@Pdf @P&DC@XU!h@X@X۱"@`(@`$.@`$As 5@h$pPE;@hd-jA@hd G@pM@p,S@p[Y@p"`@x\Gf@x$9ll@x$r@dGx@dv~@d@ԋ$@iI@2Fn@a#@$ @$ܩ @$ @d& @dMuK @|Rp@/@ @ @$9@$h(@$M@d^r@d;@$@S@@䱰* @O@$kt@$?H@dn%$@d* @d1!@,7"@*Q=#@YwvC$@TI%@$1O&@$U'@$ \(@dE.b)@dtSh*@xn+@`t,@>z-@0.@_ /@$00@$U1@dz2@dm3@dKJĥ4@z'5@6@27@W8@6|9@$fy:@$V;@d3<@d=@"4>@QY?@~@@䯅A@ bB@ $@D@ $=E@ $l6F@(d[G@(dʴH@( I@0(o&J@0WL,K@0)3L@899M@8$]?N@8$EO@@dCKP@@dr{QQ@@dXWR@H5^S@H;dT@H._jU@H]̈́pV@P$vW@P$|X@P$dY@XdBZ@XdI=[@Xxa\@`ن]@`ֶ^@`Ч_@h4q`@h$dNa@h$+?b@pddc@pdd@pd íe@xOf@x~}g@xZh@x7Ai@ fj@$;k@$jϯl@dm@dȉo@f p@&DCq@U!hr@s@۱"t@$(u@$.v@dAs 5w@dpPE;x@-jAy@ Gz@M{@,S|@[Y}@$"`~@$\Gf@d9ll@dr@dGx@v~@@ԋ$@iI@2Fn@$b#@$@dܩ@d@&@MuK@|RpŽ@/ȏ@ ΐ@$ ԑ@$9ے@$h(@dM@d^r@;@$@S@@䱰* @$O@$kt@d?H@dn%$@d*@1@,7@*Q=@YwvC@$TI@$1O@$U@d \@dE.b@tSh@xn@ `t@ >z@ 0瀮@($` @($0@(dU@0dz@0dm@0KJĥ@8z'髵@8@82@@W@@$7|Ĺ@@$fyʺ@@dVл@Hd3ּ@Hݽ@H"4@PQY@P䀨~@P䯅@X$b@X$@@X$=@`dl6@`d[@`ʴ@h @h(o&@hWL,@h)3@p$99@p$]?@pdE@xdCK@xdr{Q@xXW@5^@;d@._j@$^̈́p@$v@$|@dd@dB@I=@xa@ن@ֶ@$Ч@$5q@$dN@d+?@dd@@ í@O@~}@Z@$7A@$ f@d;@djϯ@d@ȉ@f @&DC@U!h@$@$۱"@$(@d.@dAs 5@pPE;@-jA@ G@M@,S@$\Y@$"`@d\Gf@d9ll@dr@Gx@v~@䥮@ԋ$@iI@$3Fn@$b#@d @dܩ @ @& @MuK @|Rp@/@$ @$ @$9@dh(@ dM@ ^r@ ;@($@(S@(@($* @0$O@0dkt@0d?H@8dn%$@8* @81!@@,7"@@*Q=#@@$ZwvC$@H$TI%@H$1O&@HdU'@Hd \(@PE.b)@PtSh*@Pxn+@X`t,@X>z-@X$1.@`$` /@`d00@`dU1@hdz2@hm3@hKJĥ4@hz'5@p6@p27@p$W8@x$7|9@xdfy:@xdV;@3<@=@"4>@QY?@䀨~@@$A@$bB@d@D@d=E@l6F@[G@ʴH@ I@(o&J@$XL,K@$)3L@d99M@d]?N@dEO@CKP@r{QQ@XWR@5^S@;dT@$/_jU@$^̈́pV@dvW@d|X@dY@BZ@I=[@xa\@ن]@$׶^@$Ч_@$5q`@ddNa@d+?b@dc@d@ íe@Of@~}g@$Zh@$7Ai@d fj@d;k@djϯl@m@ȉo@f p@&DCq@$V!hr@$s@$۱"t@d(u@d.v@As 5w@pPE;x@-jAy@ Gz@M{@$-S|@$\Y}@d"`~@ d\Gf@ d9ll@ r@(Gx@(v~@(䥮@(ԋ$@0$iI@0$3Fn@0db#@8d@8ܩ@8@@&@@MuK@@|RpŽ@H$/ȏ@H$ ΐ@H$ ԑ@Hd9ے@Pdh(@PM@P^r@X;@X$@XS@`$@`$* @`dO@`dkt@hd?H@hn%$@h*@p1@p,7@p$+Q=@x$ZwvC@x$TI@xd1O@dU@ \@E.b@tSh@䣃xn@$`t@$>z@$1瀮@d` @d0@U@z@m@KJĥ@z'髵@$@$2@dW@d7|Ĺ@dfyʺ@Vл@3ּ@ݽ@"4@$RY@$~@$@db@d@@=@l6@[@ʴ@ @$)o&@$XL,@d)3@d99@d]?@E@CK@r{Q@XW@5^@$;d@$/_j@d^̈́p@dv@|@d@B@I=@xa@$ن@$׶@$Ч@d5q@ddN@+?@d@@ í@O@$}@$Z@d7A@ d f@ d;@ jϯ@ @(ȉ@(f @($'DC@0$V!h@0$@0d۱"@8d(@8.@8As 5@8pPE;@@-jA@@ G@@$M@H$-S@Hd\Y@Hd"`@Pd\Gf@P9ll@Pr@PGx@Xv~@X䥮@X$Ջ$@`$iI@`d3Fn@`db#@h @hܩ @h @h& @pMuK @p$}Rp@p$/@xd @xd @x9@h(@M@^r@;@$%@$T@d@d* @dO@kt@?H@n%$@* @1!@$,7"@$+Q=#@dZwvC$@dTI%@1O&@U'@ \(@E.b)@tSh*@$xn+@$`t,@$>z-@d1.@d` /@00@U1@z2@m3@KJĥ4@${'5@$6@d27@dW8@d7|9@fy:@V;@3<@=@$#4>@$RY?@$~@@dA@dbB@@D@=E@l6F@[G@ʴH@$ I@$)o&J@dXL,K@d)3L@d99M@]?N@EO@CKP@r{QQ@XWR@$5^S@$;dT@d/_jU@d^̈́pV@vW@|X@ dY@ BZ@ I=[@($ya\@($ن]@($׶^@(dЧ_@0d5q`@0dNa@0+?b@8dc@8d@8 íe@8$Pf@@$}g@@dZh@@d7Ai@Hd fj@H;k@Hjϯl@P䙬m@Pȉo@P$f p@P$'DCq@X$V!hr@Xds@Xd۱"t@`(u@`.v@`As 5w@`pPE;x@h$-jAy@h$ Gz@h$M{@pd-S|@pd\Y}@p"`~@p\Gf@x9ll@xr@xGx@$w~@$@dՋ$@diI@d3Fn@b#@@ܩ@@$&@$NuK@$}RpŽ@d/ȏ@d ΐ@ ԑ@9ے@h(@䗁M@^r@$;@$%@dT@d@d* @O@kt@?H@n%$@*@$1@$,7@d+Q=@dZwvC@TI@1O@U@ \@E.b@$uSh@$xn@$`t@d>z@d1瀮@` @0@侲U@z@m@$LJĥ@${'髵@d@d2@dW@7|Ĺ@fyʺ@Vл@3ּ@$ݽ@$#4@$RY@d~@d@b@@@=@l6@[@$˴@$ @ d)o&@ dXL,@ d)3@ 99@(]?@(E@(CK@0r{Q@0$XW@0$5^@0d;d@8d/_j@8^̈́p@8v@@|@@d@@B@@$J=@H$ya@Hdن@Hd׶@PЧ@P5q@PdN@P+?@Xd@X$@X$!í@`dP@`d}@`dZ@`7A@h f@h;@hjϯ@h䙬@p$ɉ@p$f @pd'DC@xdV!h@x@x۱"@x(@.@As 5@$qPE;@$-jA@$ G@dM@d-S@\Y@"`@\Gf@9ll@r@$Hx@$w~@d@dՋ$@diI@3Fn@b#@ @ܩ @$ @$& @$NuK @d}Rp@d/@ @ @9@h(@䗁M@$^r@$;@d%@dT@d@* @O@kt@?H@n%$@$* @$1!@d,7"@d+Q=#@ZwvC$@TI%@1O&@U'@ \(@$F.b)@$uSh*@$xn+@d`t,@d>z-@1.@` /@00@侲U1@z2@$m3@$LJĥ4@d{'5@d6@d27@W8@7|9@fy:@V;@$3<@$=@ $#4>@ dRY?@ d~@@ A@(bB@(@D@(=E@($m6F@0$[G@0$˴H@0d I@8d)o&J@8XL,K@8)3L@899M@@]?N@@EO@@$DKP@@$s{QQ@HdXWR@Hd5^S@Hd;dT@P/_jU@P^̈́pV@P䍪vW@P伇|X@X$dY@X$BZ@X$J=[@`dya\@`dن]@`׶^@`Ч_@h5q`@hdNa@h+?b@h$dc@p$d@pd!íe@pdPf@pd}g@xZh@x7Ai@x fj@;k@jϯl@$m@$ɉo@df p@d'DCq@V!hr@s@۱"t@(u@.v@$Bs 5w@$qPE;x@$-jAy@d Gz@dM{@-S|@\Y}@"`~@\Gf@9ll@$r@$Hx@dw~@d@dՋ$@iI@3Fn@b#@@$ܩ@$@$&@dNuK@d}RpŽ@/ȏ@ ΐ@ ԑ@9ے@h(@$M@$^r@d;@d%@dT@@* @O@kt@?H@$o%$@$*@d1@d,7@+Q=@ZwvC@TI@1O@U@$ \@$F.b@duSh@dxn@`t@>z@1瀮@` @0@$U@$z@dm@dLJĥ@d{'髵@@2@ W@ 7|Ĺ@ fyʺ@ $Vл@($3ּ@(dݽ@(d#4@(RY@0~@0@0b@8@@8$>@8$m6@8$[@@d˴@@d @@)o&@@XL,@H)3@H99@H]?@H$E@P$DK@Pds{Q@PdXW@Pd5^@X;d@X/_j@X^̈́p@`䍪v@`$|@`$d@`$B@hdJ=@hdya@hن@h׶@pЧ@p5q@pdN@p$+?@x$d@xd@xd!í@xdP@}@Z@7A@ f@;@$kϯ@$@dɉ@df @'DC@V!h@@۱"@(@$.@$Bs 5@$qPE;@d-jA@d G@M@-S@\Y@"`@\Gf@$9ll@$r@dHx@dw~@d@Ջ$@iI@3Fn@b#@$ @$ܩ @$ @d& @dNuK @}Rp@/@ @ @$:@$i(@$M@d^r@d;@%@T@@䲰* @O@$kt@$@H@do%$@d* @d1!@,7"@+Q=#@ZwvC$@TI%@$1O&@$U'@$ \(@dF.b)@duSh*@xn+@`t,@>z-@1.@` /@$00@$U1@dz2@dm3@dLJĥ4@{'5@6@27@ W8@ 7|9@ $gy:@ $V;@(d3<@(d=@(#4>@(RY?@0~@@0䰅A@0bB@0$@D@8$>E@8$m6F@8d[G@8d˴H@@ I@@)o&J@@XL,K@@)3L@H99M@H$]?N@H$EO@HdDKP@Pds{QQ@PdXWR@P5^S@P;dT@X/_jU@X^̈́pV@X$vW@X$|X@`$dY@`dBZ@`dJ=[@`ya\@hن]@h׶^@hЧ_@h5q`@p$eNa@p$+?b@pddc@pdd@xd!íe@xPf@x}g@xZh@7Ai@ fj@$z@1瀮@$a @$0@dU@dz@dm@LJĥ@{'髵@@2@W@$8|Ĺ@$gyʺ@dVл@d3ּ@ݽ@#4@ RY@ 䁨~@ 䰅@ $b@ $@@($>@(dm6@(d[@(˴@0 @0)o&@0XL,@0)3@8$99@8$]?@8dE@8dDK@8ds{Q@@XW@@5^@@;d@@/_j@H$_̈́p@H$v@H$|@Hdd@PdB@PdJ=@Pya@Pن@P׶@XЧ@X5q@X$eN@X$+?@`dd@`d@`!í@`P@h}@hZ@h7A@h$ f@h$<@p$kϯ@pd@pdɉ@pf @x'DC@xV!h@x@x۱"@x$(@$.@dBs 5@dqPE;@d-jA@ G@M@-S@\Y@$"`@$\Gf@$9ll@dr@dHx@w~@@Ջ$@iI@3Fn@$c#@$ @dܩ @d @d& @NuK @}Rp@/@ @ @$:@$i(@dM@d^r@;@%@T@@䲰* @$O@$kt@$@H@do%$@d* @1!@,7"@+Q=#@ZwvC$@TI%@$1O&@$U'@d \(@dF.b)@duSh*@xn+@`t,@>z-@1.@$a /@$00@$U1@dz2@dm3@LJĥ4@{'5@6@27@W8@$8|9@$gy:@dV;@d3<@d=@#4>@RY?@䁨~@@䰅A@$bB@$@D@d>E@dm6F@d[G@˴H@ I@)o&J@XL,K@$)3L@$99M@$]?N@dEO@dDKP@s{QQ@XWR@ 5^S@ ;dT@ /_jU@ $_̈́pV@ $vW@(d|X@(ddY@(dBZ@(J=[@0ya\@0ن]@0׶^@0Ч_@0$6q`@8$eNa@8d+?b@8ddc@8d@8!íe@@Pf@@}g@@Zh@@$7Ai@@$ fj@H$z@$2瀮@$a @d0@dU@z@m@LJĥ@{'髵@@$2@$ W@$8|Ĺ@dgyʺ@dVл@3ּ@ݽ@#4@RY@䁨~@$@$b@d@@d>@dm6@[@˴@ @)o&@$YL,@$)3@$99@d]?@dE@DK@s{Q@XW@5^@;d@$0_j@$_̈́p@dv@d|@dd@B@J=@ya@ن@׶@$Ч@$6q@deN@d+?@d@@!í@P@}@$Z@$7A@$ f@d<@dkϯ@@ɉ@f @'DC@V!h@$@$۱"@d(@ d.@ dBs 5@ qPE;@ -jA@ G@ M@($.S@($]Y@($"`@(d\Gf@(d9ll@0r@0Hx@0w~@0䦮@0Ջ$@8$iI@8$4Fn@8dc#@8d @8dܩ @8 @@& @@NuK @@}Rp@@$/@@$ @Hd @Hd:@Hdi(@HM@H^r@H;@P%@P$U@P$@P$* @PdO@Xdkt@X@H@Xo%$@X* @X1!@X,7"@`$,Q=#@`$[wvC$@`dTI%@`d1O&@`dU'@h \(@hF.b)@huSh*@h䤃xn+@h`t,@h$>z-@p$2.@pda /@pd00@pU1@pz2@xm3@xLJĥ4@x{'5@x$6@x$27@x$ W8@d8|9@dgy:@V;@3<@=@#4>@RY?@$~@@$A@dbB@d@D@d>E@m6F@[G@˴H@ I@$*o&J@$YL,K@$)3L@d99M@d]?N@EO@DKP@s{QQ@XWR@5^S@$;dT@$0_jU@d_̈́pV@dvW@d|X@dY@BZ@J=[@ya\@ن]@$ض^@$Ч_@d6q`@deNa@+?b@dc@d@!íe@Pf@$}g@$Zh@$7Ai@d fj@dz@$2瀮@da @d0@dU@z@ m@ LJĥ@ {'髵@ @ $2@ $ W@(d8|Ĺ@(dgyʺ@(Vл@(3ּ@(ݽ@(#4@0RY@0$~@0$@0$b@0d@@0d>@0m6@8[@8˴@8 @8)o&@8$YL,@8$)3@@d99@@d]?@@dE@@DK@@s{Q@@XW@@5^@H$;d@H$0_j@H$_̈́p@Hdv@Hd|@Hd@PB@PJ=@Pya@Pن@P$ض@P$Ч@Pd6q@XdeN@X+?@Xd@X@X!í@XP@X$}@`$Z@`$7A@`d f@`d<@`kϯ@`@`ɉ@hf @h'DC@h$W!h@h$@hd۱"@hd(@pd.@pBs 5@pqPE;@p-jA@p G@p$M@p$.S@x$]Y@xd"`@xd\Gf@x9ll@xr@xHx@xw~@䦮@$֋$@$iI@d4Fn@dc#@d @ܩ @ @& @NuK @}Rp@$/@$ @d @d:@i(@M@^r@;@%@$U@$@$* @dO@dkt@@H@o%$@* @1!@,7"@$,Q=#@$[wvC$@dTI%@d1O&@dU'@ \(@F.b)@uSh*@䤃xn+@$`t,@$>z-@$2.@da /@d00@U1@z2@m3@LJĥ4@{'5@$6@$27@d W8@d8|9@dgy:@V;@3<@=@#4>@$SY?@$~@@dA@dbB@d@D@>E@m6F@[G@˴H@$ I@$*o&J@$YL,K@d)3L@d99M@]?N@EO@DKP@s{QQ@XWR@$5^S@$;dT@d0_jU@d_̈́pV@dvW@|X@dY@BZ@J=[@ya\@$ن]@$ض^@dЧ_@d6q`@eNa@+?b@dc@d@!íe@$Qf@$}g@$Zh@d7Ai@d fj@z@(d2瀮@(a @(0@(U@0z@0m@0$MJĥ@0$|'髵@0$@0d2@0d W@08|Ĺ@0gyʺ@8Vл@83ּ@8ݽ@8$$4@8$SY@8d~@8d@8db@8@@@>@@m6@@[@@$̴@@$ @@$*o&@@dYL,@@d)3@@99@H]?@HE@HDK@Hs{Q@H$XW@H$5^@Hd;d@Hd0_j@Hd_̈́p@Pv@P|@Pd@PB@PJ=@P$za@P$ن@Pdض@PdЧ@P6q@XeN@X+?@Xd@X@X$"í@X$Q@X$}@XdZ@Xd7A@` f@`<@`kϯ@`䚬@`ɉ@`$f @`$(DC@`dW!h@`d@`d۱"@h(@h.@hBs 5@hqPE;@h$-jA@h$ G@h$M@hd.S@hd]Y@h"`@p\Gf@p9ll@pr@pHx@p$x~@p$@pd֋$@pdiI@pd4Fn@pc#@x @xܩ @x @x$ & @x$OuK @xd~Rp@xd/@xd @x @x:@i(@䘁M@$^r@$;@$&@dU@d@* @O@kt@@H@o%$@$* @$1!@d,7"@d,Q=#@d[wvC$@TI%@1O&@U'@ \(@F.b)@$vSh*@$xn+@d`t,@d>z-@2.@a /@00@俲U1@z2@$m3@$MJĥ4@$|'5@d6@d27@ W8@8|9@gy:@V;@3<@$=@$$4>@dSY?@d~@@dA@bB@@D@>E@m6F@$[G@$̴H@$ I@d*o&J@dYL,K@)3L@99M@]?N@EO@DKP@$t{QQ@$XWR@d5^S@d;dT@d0_jU@_̈́pV@vW@佇|X@dY@BZ@$K=[@$za\@dن]@dض^@Ч_@6q`@eNa@+?b@dc@$d@$"íe@$Qf@d}g@dZh@7Ai@ fj@z@2瀮@a @0@俲U@$z@$m@$MJĥ@d|'髵@d@2@ W@8|Ĺ@gyʺ@Vл@$3ּ@$ݽ@d$4@dSY@d~@@b@@@>@$n6@$[@$̴@d @d*o&@YL,@)3@99@]?@E@$EK@$t{Q@dXW@d5^@d;d@0_j@_̈́p@䎪v@佇|@$d@$B@dK=@dza@dن@ض@Ч@6q@eN@$+?@$d@$@d"í@dQ@}@Z@7A@ f@<@$lϯ@$@dʉ@df @d(DC@W!h@@۱"@(@.@$Cs 5@$rPE;@d-jA@d G@M@.S@]Y@"`@\Gf@$9ll@$r@$Ix@dx~@d@֋$@iI@4Fn@c#@ @$ܩ @$ @d & @dOuK @d~Rp@/@ @ @:@$j(@$M@$^r@d;@d&@U@@* @O@kt@$AH@$p%$@d* @d1!@d,7"@,Q=#@[wvC$@TI%@1O&@U'@$ \(@$G.b)@dvSh*@dxn+@`t,@>z-@2.@a /@00@$U1@$z2@$m3@dMJĥ4@d|'5@6@27@ W8@8|9@gy:@$V;@$3<@d=@d$4>@SY?@ ~@@ 䱅A@ bB@ @D@ $?E@ $n6F@ d[G@ d̴H@ I@ *o&J@ YL,K@ )3L@ 99M@ $]?N@ $EO@ $EKP@ dt{QQ@ dXWR@ 5^S@ ;dT@ 0_jU@ _̈́pV@ 䎪vW@ $|X@ $dY@ dBZ@ dK=[@(dza\@(ن]@(ض^@(Ч_@(6q`@($fNa@($+?b@($dc@(dd@(d"íe@(Qf@(}g@(Zh@(7Ai@( fj@($=k@($lϯl@(dm@(dʉo@(df p@((DCq@(W!hr@(s@(۱"t@((u@($.v@($Cs 5w@(drPE;x@(d-jAy@( Gz@(M{@(.S|@0]Y}@0"`~@0$\Gf@0$9ll@0$r@0dIx@0dx~@0@0֋$@0iI@04Fn@0c#@0$@0$ܩ@0d@0d &@0dOuK@0~RpŽ@0/ȏ@0 ΐ@0 ԑ@0$;ے@0$j(@0$M@0d^r@0d;@0&@0U@0@0䳰* @0O@0$kt@0$AH@0dp%$@0d*@0d1@0,7@0,Q=@0[wvC@0TI@0$1O@0$U@8d \@8dG.b@8dvSh@8xn@8`t@8>z@82瀮@8$b @8$0@8$U@8dz@8dm@8MJĥ@8|'髵@8@82@8 W@8$9|Ĺ@8$hyʺ@8dVл@8d3ּ@8dݽ@8$4@8SY@8䂨~@8䱅@8b@8$@@8$?@8dn6@8d[@8̴@8 @8*o&@8YL,@8)3@8$99@8$]?@8$E@8dEK@8dt{Q@8XW@85^@8;d@80_j@8_̈́p@8$v@8$|@8dd@8dB@8dK=@8za@8ن@8ض@8Ч@8$7q@8$fN@8$+?@8dd@8d@8"í@8Q@8}@8Z@87A@8$f@8$=@8dlϯ@8d@8dʉ@8f @8(DC@8W!h@8@8۱"@8$(@8$.@8dCs 5@8drPE;@8-jA@8 G@8M@8.S@8]Y@8$"`@8$\Gf@8$9ll@8dr@8dIx@8x~@8@8֋$@8iI@84Fn@8$d#@8$ @8dܩ @8d @8 & @8OuK @@~Rp@8/@8 @8$ @8$;@8dj(@8dM@8^r@8;@8&@8U@8@8$* @8$O@8$kt@8dAH@8dp%$@8* @81!@8,7"@8,Q=#@8[wvC$@8$TI%@8$1O&@8dU'@8d \(@8dG.b)@8vSh*@8xn+@8`t,@8>z-@8$3.@8$b /@8$00@8dU1@8dz2@8m3@8MJĥ4@8|'5@86@827@8$ W8@8$9|9@8dhy:@8dV;@8d3<@8=@8$4>@8SY?@8䂨~@@8䱅A@8$bB@8$@D@8d?E@8dn6F@8[G@8̴H@8 I@8*o&J@8YL,K@8$)3L@8$99M@8$]?N@8dEO@8dEKP@8t{QQ@8XWR@85^S@8;dT@80_jU@8$`̈́pV@8$vW@8d|X@8ddY@8dBZ@8K=[@8za\@8ن]@8ض^@8$Ч_@8$7q`@8$fNa@8d+?b@8ddc@8d@8"íe@8Qf@8}g@8Zh@8$7Ai@8$fj@8d=k@8dlϯl@8dm@8ʉo@8f p@8(DCq@8W!hr@8$s@8$۱"t@8d(u@0d.v@0dCs 5w@0rPE;x@0-jAy@0 Gz@0M{@0$/S|@0$^Y}@0$"`~@0d\Gf@0d9ll@0r@0Ix@0x~@0䧮@0֋$@0$iI@0$5Fn@0dd#@0d@0dܩ@0@0 &@0OuK@0~RpŽ@0/ȏ@0$ ΐ@0$ ԑ@0d;ے@0dj(@0M@0^r@0;@0&@0U@0$@0$* @0$O@0dkt@0dAH@0p%$@0*@(1@(,7@(,Q=@($\wvC@($TI@(d1O@(dU@(d \@(G.b@(vSh@(䥃xn@(`t@($>z@($3瀮@($b @(d0@(dU@(z@(m@(MJĥ@(|'髵@(@($2@($ W@(d9|Ĺ@(dhyʺ@(dVл@(3ּ@(ݽ@($4@(SY@(䂨~@ $@ $b@ d@@ d?@ n6@ [@ ̴@ @ *o&@ $ZL,@ $)3@ $99@ d]?@ dE@ EK@ t{Q@ XW@ 5^@ ;d@ $1_j@ $`̈́p@ dv@ d|@ d@ B@ K=@ za@ن@$ٶ@$Ч@d7q@dfN@+?@d@@"í@Q@$}@$Z@$7A@df@d=@lϯ@@ʉ@f @(DC@$X!h@$@d۱"@d(@d.@Cs 5@rPE;@-jA@ G@$M@$/S@$^Y@d"`@d\Gf@9ll@r@Ix@x~@䧮@$׋$@$iI@d5Fn@dd#@d @ܩ @ @ & @OuK @~Rp@$/@$ @d @d;@j(@M@^r@;@&@$V@$@$* @dO@dkt@AH@p%$@* @1!@,7"@$-Q=#@$\wvC$@dTI%@d1O&@dU'@ \(@G.b)@vSh*@䥃xn+@$`t,@$>z-@$3.@db /@d00@U1@z2@m3@MJĥ4@|'5@$6@$27@d W8@d9|9@dhy:@V;@3<@=@$4>@$TY?@$~@@dA@dbB@d@D@?E@n6F@[G@̴H@$ I@$+o&J@$ZL,K@d)3L@d99M@]?N@EO@EKP@t{QQ@XWR@$5^S@$;dT@d1_jU@d`̈́pV@dvW@|X@dY@BZ@K=[@za\@$ن]@$ٶ^@dЧ_@d7q`@fNa@+?b@dc@d@"íe@$Rf@$}g@$Zh@d7Ai@dfj@=k@lϯl@䛬m@ʉo@f p@$)DCq@$X!hr@ds@d۱"t@d(u@.v@Cs 5w@rPE;x@-jAy@$ Gz@$M{@$/S|@d^Y}@d"`~@\Gf@9ll@r@Ix@x~@$@$׋$@diI@d5Fn@dd#@@ܩ@@ &@OuK@$RpŽ@$/ȏ@d ΐ@d ԑ@;ے@j(@M@^r@;@$'@$V@$@d* @dO@kt@AH@p%$@*@1@$,7@$-Q=@d\wvC@dTI@1O@U@ \@G.b@vSh@$xn@$`t@d>z@d3瀮@b @0@U@z@m@$NJĥ@$}'髵@$@d2@d W@9|Ĺ@hyʺ@Vл@3ּ@ݽ@$%4@$TY@d~@d@db@@@?@n6@[@$ʹ@$ @$+o&@dZL,@d)3@99@]?@E@EK@t{Q@$XW@$5^@d;d@d1_j@d`̈́p@v@|@d@B@K=@${a@$ن@dٶ@dЧ@7q@fN@+?@d@@$#í@$R@$}@dZ@d7A@f@=@lϯ@䛬@ʉ@$f @$)DC@dX!h@d@d۱"@(@.@Cs 5@rPE;@$-jA@$ G@$M@d/S@d^Y@"`@\Gf@66 @rH @$Z< @hm @TB @E @2H @# @RN @I @xrnT @xx @xL[ @x% @x?)8a @x2חJ @xn]g @xRuo @xҝm @xr5R @ps @pd/ @py @p @p2+{ @p @pRZX @p'  @pR5: @p L @hr_ @hPq @h @h2^ @hͨ @h2;! @hEͤ @hR' @ht @hr . @`d @`;)4 @`A< @`jN: @`2a @`ҙs@ @`R1 @`jF @`r`٪ @`GL @X @X'%R @X @X2VY @Xp @XR+_ @XN> @XrPe @XK+c @Pruk @P{ @Pwq @P2 @PATw @P2 @Pp1}! @PR" @P " @Pr7}# @H-# @HfZ@ $ @HR$ @H7e% @H2-w% @H& @HR\& @H' @Hr`' @@"%( @@=( @@R+) @@ ) @@22* @@/* @@RfB8+ @@GT+ @@rCg>, @8vy, @8r!D- @8- @8=J. @82l. @8lP/ @8RJ/ @8қV0 @8R3' 0 @0ʕ]1 @0rb21 @0rDc2 @0V2 @0)Pii3 @0{3 @02X-o4 @04 @0R u5 @(y5 @(r{6 @(MV6 @(7 @(}38 @(!8 @(24 9 @(CF9 @(RX: @ r\k: @ r }; @ 9; @ 9< @ < @ h#= @ 2٦= @ җb)> @R/> @?0? @r^#? @66@ @H@ @%Z\ @rPe] @K+c] @uk^ @{^ @wq_ @2_ @ATw` @R` @p1}a @rb @ b @7}c @-c @fZ@ d @2Rd @7ee @R-we @f @R\f @g @r`g @#%h @=h @2R+i @ i @22j @/j @RfB8k @GTk @rCg>l @wyl @!Dm @2m @=Jn @2ln @lPo @RJo @Vp @r3' p @˕]q @b2q @rDcr @Vr @2)Piis @{s @RX-ot @t @r uu @yu @{v @NVv @w @2}3x @!x @R4 y @CFy @rXz @r\kz @r }{ @9{ @9| @2| @h#} @R٦} @җb)~ @R/~ @?0 @r^# @66 @H @%Z< @hm @2TB @Eł @RH @#˃ @rN @Iф @nT @y؅ @L[ @2%ކ @?)8a @RחJ @n]g @ruo @m @5R @s @d/ @2y @ @R+{ @x @xRZX @x' @xr5: @x!L @x_ @x2Pq @p @p2^ @pͨ @pR;! @pEͤ @pr' @pt @h . @hd @h;)4 @h2A< @hjN: @hRa @`ҙs@ @`r1× @`jF @``٪ɘ @`GL @`ϙ @`2'%R @X՚ @XRVY @Xpܛ @Xr+_ @XN> @XrPe @XL+c @Puk @P2{ @Pwq @PR @PATw @Pr @Pp1} @Hr @H @H7} @H2- @HfZ@ @HRR @@ҕ7e @@R-w @@ @@r\ @@ @@` @@#% @8=樨 @82R+ @8 @8R2 @8/ @8rfB8 @0GT @0Cg> @0wy @0!D @02ǭ @0=J @0Rlͮ @(lP @(rJӯ @(V @(3' ڰ @(˕] @(b2 @ 2rDc @ V @ R)Pii @ { @ RX-o @  @r u @y @{ @2NV @ @2}3 @! @R4 @CF @rX @r\k @ } @9 @9 @2 @h# @R٦ @җb) @r/ @?0 @^# @66 @H @2%Z< @hm @RTB @E @rH @# @rN @J @nT @2y @L[ @2% @?)8a @RחJ @n]g @ruo @m @5R @s @d/ @2y @ғ @R+{ @ @rZX @' @5: @!L @_ @2Pq @ @R^ @ͨ @r;! @Eͤ @' @u @ . @2d @;)4 @RA< @jN: @ra @s@ @1 @jF @`٪ @2GL @ @R'%R @Ҿ @RVY @p @r+_ @N> @Pe @2L+c @uk @2{ @wq @R @ATw @r @p1} @ @ @7} @2- @fZ@ @RR @ҕ7e @r-w @ @\ @ @` @2#% @= @RR+ @ @r2 @/ @rfB8 @HT @Cg> @2wy @!D @2 @=J @Rl @lP @rJ @V @3' @˕] @b2 @x2rDc @xґV @xR)Pii @x{ @xrX-o @x @p u @py @p{ @p2NV @p @hR}3 @h! @hr4 @hCF @hrX @hs\k @` } @`29 @`9 @`R @`h# @XR٦ @Xb) @Xr/ @X?0 @X^# @X66!@PH!@P2%Z<!@PҼhm!@PRTB!@PE!@HrH!@H#!@HN!@HJ!@HnT!@H2y!@@L[!@@R%!@@?)8a!@@rחJ!@@n]g!@8uo!@8m !@85R !@82s !@8d/ !@8Ry !@0ғ !@0r+{ !@0 !@0ZX !@0' !@(5:!@(2!L!@(_!@(RPq!@(!@ r^!@ ͨ!@ r;!!@ Fͤ!@ '!@ 2u!@ .!@2d!@;)4!@RA<!@jN:!@ra!@s@!@1!@jF!@`٪!@2GL!@ҏ!@R'%R!@Ҿ!@rVY!@p!@+_!@N>!@Pe!@2L+c!@uk!@R{!@wq!@r!@ATw !@r !@q1}!!@"!@2 "!@7}#!@R-#!@fZ@ $!@RR$!@7e%!@r-w%!@&!@\&!@'!@`'!@2#%(!@Һ=(!@RR+)!@ )!@r2*!@/*!@fB8+!@HT+!@Cg>,!@2wy,!@!D-!@R-!@=J.!@rl.!@lP/!@J/!@V0!@3' 0!@2˕]1!@b21!@RrDc2!@ґV2!@R)Pii3!@{3!@rX-o4!@4!@ u5!@2y5!@{6!@2NV6!@7!@R}38!@!8!@r4 9!@DF9!@X:!@2s\k:!@ };!@29;!@9!@/>!@?0?!@^#?!@266@!@ҍH@!@R%Z\!@8Pe]!@82L+c]!@0uk^!@0R{^!@0wq_!@0r_!@0ATw`!@(`!@(q1}a!@(b!@(2 b!@ 7}c!@ R-c!@ fZ@ d!@ rRd!@ 7ee!@-we!@f!@\f!@2g!@`g!@R#%h!@Һ=h!@rR+i!@ i!@r2j!@/j!@fB8k!@2HTk!@Cg>l!@Rwyl!@!Dm!@rm!@=Jn!@rln!@mPo!@Jo!@2Vp!@3' p!@R˕]q!@b2q!@RrDcr!@Vr!@r)Piis!@{s!@X-ot!@t!@ uu!@2yu!@Ҷ{v!@RNVv!@w!@r}3x!@!x!@4 y!@DFy!@Xz!@2s\kz!@ }{!@R9{!@9|!@r|!@h#}!@٦}!@b)~!@/~!@2?0!@^#!@R66!@ҍH!@R%Z!@XPe!@XRL+c!@Xuk!@Xr{!@Pwq!@P!@PBTw!@P!@P2q1}!@H!@HR !@H7}!@Hr-!@@fZ@ !@@R!@@7e!@@-w!@82!@8\!@8R!@8ҋ`!@8R#%!@0=樨!@0rR+!@0 !@02!@(2/!@(fB8!@(2HT!@(Cg>!@ Rwy!@ !D!@ rǭ!@ =J!@ lͮ!@mP!@Jӯ!@2V!@3' ڰ!@R˕]!@b2!@rrDc!@V!@)Pii!@{!@X-o!@2!@ u!@Ry!@Ҷ{!@rNV!@!@r}3!@!!@4 !@2DF!@X!@2s\k!@ }!@R9!@9!@r!@i#!@٦!@b)!@/!@2?0!@^#!@R66!@ҍH!@r%Z!@pҴPe!@prL+c!@huk!@hr{!@hwq!@h!@`2BTw!@`!@`2q1}!@`!@XR !@X7}!@Xr-!@XgZ@ !@PR!@P7e!@P-w!@P2!@H\!@HR!@Hҋ`!@Hr#%!@@=!@@R+!@@ !@@2!@82/!@8fB8!@8RHT!@8Cg>!@0rwy!@0!D!@0r!@0>J!@(l!@(2mP!@(J!@(RV!@ 3' !@ R˕]!@ b2!@ rrDc!@V!@)Pii!@{!@X-o!@2!@҇ u!@Ry!@{!@rNV!@!@}3!@!!@4 !@2DF!@X!@Rs\k!@ }!@r9!@9!@!@i#!@٦!@2b)!@/!@R?0!@^#!@R66"@H"@r%Z<"@hm"@TB"@2E"@H"@2#"@ҲN"@RJ"@nT"@ry"@L["@%"@2@)8a"@חJ"@2o]g"@uo"@Rm "@5R "@rs "@e/ "@y "@ "@+{ "@2 "@ZX "@R' "@҉5:"@r!L"@_"@Pq"@"@^"@2ͨ"@;!"@RFͤ"@'"@ru"@ ."@rd"@<)4"@A<"@2kN:"@a"@Rs@"@1"@RjF"@`٪"@rGL"@"@'%R"@"@xVY"@x2p"@x҅+_"@xRN>"@pPe"@prL+c"@puk"@p{"@hwq"@h"@h2BTw "@h "@`Rq1}!"@`""@`r ""@`7}#"@X-#"@XgZ@ $"@XR$"@P27e%"@P-w%"@PR&"@P\&"@HR'"@H`'"@Hr#%("@H=("@@R+)"@@2 )"@@2*"@@2/*"@8ҰfB8+"@8RHT+"@8Cg>,"@8rwy,"@0!D-"@0-"@0>J."@(l."@(2mP/"@(J/"@(RV0"@ 3' 0"@ r˕]1"@ b21"@ rDc2"@V2"@)Pii3"@2{3"@X-o4"@R4"@҇ u5"@ry5"@{6"@rNV6"@7"@}38"@2!8"@4 9"@RDF9"@X:"@rs\k:"@ };"@r9;"@:<"@<"@2i#="@٦="@Rb)>"@/>"@R?0?"@^#?"@r66@"@H@"@%Z\"@hPe]"@hrL+c]"@huk^"@`{^"@`2wq_"@`_"@`2BTw`"@X`"@XRq1}a"@Xb"@Pr b"@P8}c"@P-c"@PgZ@ d"@HRd"@H27ee"@H-we"@@Rf"@@\f"@@rg"@@`g"@8#%h"@8=h"@8R+i"@82 i"@02j"@0R/j"@0ҰfB8k"@(rHTk"@(Cg>l"@(yl"@(rXDm"@ Ra"@^Q"@cg"@|v"@R m"@rҚ"@2)s"@"@2"Hy"@R@"@R`f"@ "@"@0 "@B"@2U"@Eg"@2rPz"@rߌ"@rn"@R"@5!"@rkפ"@'"@r:"@xR."@xRY!"@xR34"@xRwF"@pRY:"@pVk"@pr%~@"@h㴐×"@h,DF"@hwӵɘ"@hRbL"@`ϙ"@`bR"@`֚"@`Y"@XR^/%ܛ"@X7_"@XNJ"@Pi\e"@Prlo"@P$k"@P2"@HRq"@H2K"@HҰ9w"@@R"@@rX}"@@"@@RYw"@8)"@828;"@8r%N "@0R`"@0Ds"@0 ԅ"@0c"@(󪜦"@(|"@(rТ"@ |%"@ 20"@ R,"@ P"@,2"@o?"@2Q8"@21d"@w>"@P"@"@"@RJD"@ҽ"@2J"@?"@"P"@r` "@W"@җ."@A]"@S"@3fc"@Rx"@r)Ti"@R"@ #@P7P #@PJc#@PRu#@Hk#@H#@Hƍ#@@r#@@Ҟ#@@R@!#@8R#@82b (#@8y#@82s/.#@0nB#@0rkT4#@0Rj7g#@(jy:#@(RmY#@(rq@#@ Rw{#@  F#@ #@ .L#@#@үPS#@r #@r3Y#@2F#@2X_#@&k#@.}e#@IH#@2g٢k#@j#@Ҧq#@RɌ#@w #@ #@;@~!#@Re$"#@b7"#@I##@\##@o $#@rP$#@҄8%#@ɦ%#@Z&#@,˜&#@Rh}'#@'#@&(#@%1(#@Rh(,)#@S;)#@M2*#@;v`*#@҄s8+#@И+#@*>,#@m,#@LD-#@-#@reoJ.#@.#@Q/#@m#/#@rɴ,W0#@&F?0#@2Q]1#@Rhd1#@Jvc2#@2#@2i3#@R}3#@R?o4#@S4#@bu5#@05#@ |6#@6#@҈07#@R9C8#@wU8#@\h 9#@mz9#@2:#@j:#@뢲;#@xn4Ś;#@x<#@x2zW<#@p#=#@pҌz=#@p "*>#@hR4>#@h5/G0?#@h2Y?#@`RZRl6@#@`~@#@`ul#@ l#@>xDm#@p m#@Jn#@.n#@Qo#@rJS+o#@R=Wp#@xRwPp#@x c]q#@x2Auq#@pr.cr#@pRr#@p Sis#@hTs#@hҝwot#@h t#@h5uu#@`. u#@`|v#@`R'S/v#@XR{Aw#@X2wTx#@X( gx#@P2y y#@Pr.y#@PR:z#@HSz#@H{#@H[x֚{#@H2 |#@@%|#@@ҍ/$}#@@2 }#@8rbT3*~#@8E~#@8R>yX0#@0 k#@0R!}6#@00#@( â<#@(RU#@(B#@(2xzł#@ r H#@ Rt˃#@ 1O#@w$҄#@V7U#@I؅#@ |\[#@Roކ#@a#@3#@:Ʀg#@X#@R^m#@}#@҈s#@ #@r5z#@V(#@RZ;#@RM#@23`#@s #@Rz#@ 8#@ʪ#@Rr]#@Ϙ#@R˂#@rz#@r+"#@:#@,(#@H`?#@Q.#@d#@vw4#@4#@R=:#@2Ю#@wc@#@;×#@F#@2ɘ#@2 M#@_AЙ#@r-0S#@fC֚#@UY#@Ҡhܛ#@ru{_#@K#@2$Ee#@2ײ#@jk#@#@q#@Rx##@R[x#@?I"#@r&4~#@oG#@Z#@l#@'#@º #@RM#@R#@x2sɖ#@xґ#@xR#@pr, #@pR#@p2~R&&#@h}8#@h2xK,#@h2 ^#@h2p2#@`ҍ1#@`Rĕ8#@`W#@X>#@X}#@X2D#@Pۣǭ#@P6K#@Pή#@H]*Q#@H3<ԯ#@HMOW#@@ibڰ#@@t]#@@R<#@@ϙc#@8b#@82i#@87#@0`o#@0#@0RB v#@(R#@(2i.|#@(F@#@ zS#@ R"f#@ 2x#@I #@rYܝ#@o#@Ô#@#@rU)蚻#@Ҙ#@O #@%$#@mv2#@r E*#@W#@S0j0#@|#@V6#@2H꡹#@}<#@ǿ#@MB#@R7#@H#@b^#@#O#@$6#@rIU#@[#@T?n[#@Ҁ#@(fa#@R#@g#@s #@m#@2YG#@t#@En#@(z#@9:#@r(M#@4_#@Or#@7 #@Һv#@r@ #@ǝ#@P1#@#@rhX#@#@2"#@R,#@2>(#@B:Q#@2c.#@rsav#@r4#@2#@I:#@2#@RC@#@20#@jF#@r} #@&M#@x%0#@x~BS#@x2-MU#@xgY#@ptz#@pC_#@p#@hr/e#@hj#@h%Wk#@`#@`r~q#@`b#@XR$!x#@XR94#@XRF~#@PuaY#@Pr?k#@P ~#@H#@Hr #@HvD#@HrI#@@lۖ#@@#@@R˓#@8Ҥ' #@82%#@82]O8&#@02#@ s#@ rbD#@2S#@E>K#@2:)#@20fa$@,$@rg$@'U$@ym $@} $@ t $@rw' $@::z $@*L $@c_ $@q $@2C $@xr $@x$@xrlI$@p2Β$@p;r$@p$@p$@h/$@hR+"$@h`X>$@`P($@`Hc$@`v.$@X28$@Xr>4$@X.ӭ$@Prg:$@P2,ҽ$@P@$@H0%$@H G$@H,$@8,$@E-$@-$@)K.$@|G<.$@RNQ/$@R)qa/$@2tW0$@ݚ0$@/]1$@ī1$@2xYc2$@Z2$@=i3$@r#3$@ p4$@A4$@-v5$@Rk@5$@ҹS|6$@e6$@*x7$@򏿊8$@T8$@| 9$@v~Ž9$@q:$@m:$@Rl=;$@l ;$@ng<$@r1<$@RxD$=$@&W=$@i*>$@P|>$@0?$@z?$@6@$@2Ҥƹ@$@9"R$@(R QR$@(c(S$@([5vS$@ 2ʈ.T$@  `T$@ b4U$@ U$@r :V$@RzV$@J@W$@= W$@uGX$@R 0X$@2pBMY$@5UY$@EgSZ$@Ҳ`zZ$@!Y[$@Ғ[$@r!_\$@y\$@Ke]$@2h]$@vk^$@] ^$@ڡ!r_$@Z74_$@Fx`$@]bY`$@rk~a$@h~b$@"b$@zc$@RNc$@ғ d$@#yېd$@2e$@Fe$@r9f$@q%f$@ e8 g$@2Jg$@?]&h$@r%ph$@|,i$@Qi$@2j$@re|j$@ 8k$@2߻k$@2^=>l$@ l$@hEm$@g)m$@R y$@psՎy$@hz$@h͞z$@hҪ4 {$@`{$@`k`2|$@`ROD|$@X24W$}$@X"j}$@X|*~$@XM~$@P20$@Py$@P6$@HRٹ$@H;<$@H$@@gC$@@R#Ƃ$@@{6I$@8w)Ĩ$@8u[O$@8uUn҄$@8rwU$@0z؅$@0[$@0򆭸ކ$@(Ca$@(2$@(rog$@ $@ rěn$@ 1($@:t$@]M$@_z$@.r$@RI $@e$@҃L$@ $@xό$@2$@$@5;$@^$@2g,$@>$@Q"$@*d$@Ev($@ryV$@.$@悮$@4$@Yӷ$@RE:$@$@r A$@Vė$@r0G$@4Cʘ$@2'UM$@2pahЙ$@2zS$@֚$@2V$Y$@rܛ$@RP_$@2L$@}e$@2$@2Rl$@2@"$@ 4r$@rhmG$@Zx$@*l$@0~$@RƑ$@[]$@$@0Ɋ$@Ҝ $@R $@{M$@$@az&$@9$@NK $@R=^$@rCp&$@Rj$@>,$@r$@A.2$@͵$@K[8$@x$@x\?$@x¬$@pt*E$@pRL=ȭ$@pғOK$@h2&ybή$@h2uQ$@h2Pԯ$@h$@@y$@@R$@@UÈ$@8 > $@8r莹$@8}k$@0r8$@0 $@0/3$@0ruE$@(8]X$@(Rj$$@(rŠ}$@ R!*$@ T$@ O0$@dz$@|6$@$@r_<$@3A$@ $C$@n7$@JI$@R\$@t3oO$@Sʁ$@4aU$@r$@[$@2%$@Rʼa$@2S$@h$@R$@r|)n$@m;$@R`FNt$@T`$@2Ktsz$@RC $@R=$@99$@6н$@5g $@7$@9$@r>,$@D$@2MZ-$@2W?$@bR$@pe"$@w$@2M($@䜫$@Ҹ{.$@r±$@4$@A$@:$@r;o $@ZA$@|1$@4DG$@V$@biM$@{$@=S$@i($@ҖY$@RV$@_$@*$@_e$@R$@J#l$@ 5$@2EyHr$@[$@§mx$@?$@x2G֒~$@x2m$@x$@p$@pe3݊$@pұ $@ha$@hO$@h'$@hR':$@`RIL$@`2V_ $@`q$@XRS&$@Xr$@Xr ,$@P2mK$@P2$@P22z$@P28$@H2$@Hf@?$@HR+$@@=o>E$@@Q$@@cK$@825v$@8͈Q$@8ud$@0W$@0e$@02*]$@0\$@(Yc$@(Z $@(r܈j$@ _ 0$@ RBp$@ RlOU$@Rgv$@~z$@R |$@$@*E$@r$@Ot׈$@R $@|$@r;$@2!$@Lj4$@G$@Y$@,1l$@~$$@v`$@r*$@RƏ$@2q'0$@۳$@2V6%@r|%@R.=%@2&%@8C%@NMK%@]I%@|p%@O%@>%@rCU%@rۺ%@Rs[%@I %@2a%@r:%@rh%@2rj*%@@=n %@2O %@21bt %@t %@Ҍaz %@Rd %@= %@) %@rц %@X %@r%@Җ %@z %@`.%@HPA%@R1S%@f%@r y"%@2%@G(%@߰%@w.%@ֱ%@4%@?%@2 ;%@2o %@3A%@xE%@xү7XG%@xj%@xg}M%@p%@p2˗S%@pr/%@hY%@hr_%@h2_%@`%@`)(f%@`?$%@`WX7l%@X2qI%@X\r%@X o%@Pȸx %@PRP %@P ~!%@P20"%@HRV̄"%@H2~#%@HҧI#%@@R$%@@z$%@@/)%%@8R`;%%@8BN&%@8R`&%@8rrs '%@05 '%@02o&(%@0Ҫ;(%@(ӽ,)%@(2'lЯ)%@(h2*%@(*%@ R49+%@ r5+%@ r}e-?,%@R?,%@RE-%@r`.e-%@wK.%@_.%@RSQ/%@ҧ/%@2'W0%@RV0%@RX]1%@ 1%@Ri d2%@!2%@)1j3%@RD3%@2Vp4%@Wi4%@ҿ|v5%@)5%@L|6%@6%@rr}Ƃ7%@8%@V8%@2F 9%@A9%@w#:%@46:%@H;%@-A[;%@m<%@2.r<%@R $=%@5=%@;*>%@Dʭ>%@l0?%@[?%@7@%@2x6@%@ '=A%@g:A%@r1MCB%@Ș_B%@`1rIC%@ɄC%@bOD%@4D%@2ԓUE%@u,E%@[F%@]F%@rdbG%@ G%@2',hH%@Rc>H%@2YQnI%@cI%@2rvtJ%@%#J%@ڻzK%@rTK%@IL%@RM%@M%@r~ N%@R>P N%@O%@2Á0O%@x2CP%@xOUP%@xLhQ%@p2zQ%@p}"R%@p|R%@pRL(S%@hHūS%@hR.T%@hyT%@`r4U%@`RvU%@`PD";V%@X-4V%@XR vGAW%@XZW%@X̧lGX%@PR@X%@PّMY%@P|rY%@Hre SZ%@H2PZ%@Hr<=Y[%@H*[%@@o`\%@@r \%@@&f]%@8R99]%@8Kl^%@8rk^^%@8qr_%@0ܝ_%@06x`%@0Ϩ`%@(h~a%@(rb%@(b%@(3c%@ c%@ fd%@ r *d%@=e%@+1Pe%@=bf%@Qcuf%@g g%@R~g%@r.&h%@Rǿh%@`,i%@ri%@ 2j%@/, j%@rS9k%@y^/k%@rA?l%@ɐTl%@)gEm%@2!ym%@O\Kn%@n%@2Qo%@'o%@Wp%@2SZp%@R]q%@rnjq%@2&!dr%@B3r%@2XFjs%@RXs%@R kpt%@O$~t%@vu%@Vu%@+|v%@wv%@"ۂw%@x%@2iUx%@R y%@%y%@j!8z%@2ĺJz%@RT]{%@R|o{%@ۆ|%@; |%@򝹧$}%@S}%@g*~%@υ߭~%@290%@R%@RR7%@R)%@<=%@RcO%@r׷aC%@MQtƂ%@2I%@>̃%@2O%@27҄%@2PU%@6؅%@R[%@= ߆%@öb%@KP.%@2@h%@`S%@xfn%@x|x%@x Pt%@x%@p4z%@p%@pbՀ%@hRO%@h%@h5 %@h %@`u2%@`PE%@`W%@XRbj%@XR }%@X2%@X_P"%@P 괥%@P2(%@Pmګ%@P.%@HRP%@H5%@HB$%@@7;%@@RI%@@uQ\A%@@5nė%@8G%@8Ҹʘ%@8r}M%@0CRЙ%@0 S%@0Յ֚%@0Y%@(2oݛ%@(r>S`%@((%@(r;f%@ 2 N%@ `l%@ eTs%@?r%@%@R!x%@ػ%@U~%@Ҝ%@%@2h#%@P%@:W-%@r&?%@RR%@%e%@w%@X%@ %@rӌ%@&&%@ԩ%@Z,%@ҿ%@R 3%@(%@19%@\D%@rV?%@אi¬%@2*|E%@RĎȭ%@^K%@ ή%@2Q%@r0-ԯ%@REW%@\aڰ%@t^%@#%@2/6d%@H%@c[j%@R m%@-p%@R2%@y̥v%@2f%@|%@%@&5%@V%@Ri%@( %@:%@'8M%@R`_%@lr%@2%@R%@2U;%@Җռ$%@Roϧ%@r *%@f%@R>1%@%@RFs,7%@r ?%@rQ=%@6Bd%@vC%@v%@6I%@򎫮%@EO%@2F%@xRzU%@xR%@x2f \%@xI%@p2/0b%@pR~C%@pRVh%@hjh%@hM{n%@hD%@ht%@`&%@`z%@`R%@`R%@XR%@XR{!%@X" %@XRvV5%@PrG%@PRxZ%@P2%m%@H%@H [%@H2%@H2"%@@ҩ*ʥ%@@R8(%@@_%@@Z/%@8%@8/'5%@89%@8dL;%@0O^%@0qA%@04%@(r+ϖG%@(i%@(qM%@(2%@ 9S%@ g%@ oZ%@ %@n+`%@?>%@2Pf%@2tc%@;vl%@%@Dr%@g߭%@#zx%@%@2~%@eJ%@) %@%@20%@B%@KPU%@g%@z%@2 %@%@^V %@4ģ%@r &%@&%@R,%@R\%@2}!3%@]4%@R@-G9%@$Y%@ cl?%@r~%@ܘE%@r3%@ζK%@i%@rQ%@%@2{:X%@Rq%@2ip&^%@b 9%@R^Kd%@[A^%@Zpj%@r[w%@2^p%@rb%@hHv%@p%@Rz~|%@%@R%@rO%@R*%@Ņ= %@ P%@b%@Wu%@"%@R>%@[(%@zÿ%@^$%@%@R*%@ 0 %@11%@[f/%@RB7&@T&@7g=&@Ry&@HnC&@| &@2I&@xR?&@xr%O&@xav&@xҞU&@pެ&@pRH!\&@p2b3&@pҦ~Fb&@hrY&@h5kh&@hP~&@hn &@`R &@`h"t &@` &@` Yz &@Xa &@Xr &@X+ &@Xj% &@Pa8 &@P$J&@P2]&@Pr3p&@HHς&@Hrj&@H&@H|&@@<"&@@Rߥ&@@s(&@@0&@8/&@8F*&@8<5&@8r}O&@0yb;&@0Rt&@0RoOA&@0R&@(lG&@(r!&@(qM&@(X&@ }S&@ 2 &@ +Z&@ .&@ҪbA`&@:S&@̙ff&@r_5y&@rЋl&@rl&@$r&@&@Z?x &@ &@Ҙv~!&@R:"&@ݭ "&@I3#&@)E#&@ҀX$&@R}k$&@)}%&@S%&@&&@r9&&@& '&@2ڣ'&@2Y^&(&@2(&@̕-)&@1%)&@RG73*&@RiJ*&@2]9+&@o+&@R&@( >&@R21?&@`E?&@W7@&@rj@&@4}=A&@rяA&@mCB&@& B&@req&@Rwdr&@Rwr&@bjs&@R"s&@Mpt&@t&@kvu&@22$u&@ }v&@]w&@Ґ1w&@^Dx&@2.4Wx&@i y&@m|y&@ z&@R~z&@VD{&@21ƛ{&@2 ~|&@2|&@ʷ$}&@T}&@r#+~&@Rt6~&@2[+I1&@C[&@.en7&@R&@2=&@;&@rظC&@uƂ&@I&@ȯ̃&@rLP&@һӄ&@(V&@#;م&@ҵM\&@r]`߆&@Һrb&@&@4h&@Ѫ&@2nn&@ &@t&@F&@R{&@)&@>-&@U?&@xnWR&@xrd &@xҥw&@x.&@p˜&@pi&@p2)™&@pN&@pu@矑&@h"&@h2z &@h)&@h#1&@`TRD/&@`҅V&@`i5&@`)|&@`&ǎ;&@X_d&@XҙA&@Xr֞ė&@Xw&@2W܉b&@;z&@!h&@ &@Sn&@&@̏t&@2- &@{&@ҟi1&@D&@ҊV&@Ci&@|{ &@x&@2v&@ru&@vY&@ryؙ&@~&@3&@Ҍ#&@Җo#&@ 6)&@2H&@I[/&@m&@ㅀ5&@r#&@¥;&@R'`&@RAA&@2]&@z:G&@R&@vN&@(&@R:T&@*QM&@xRR_Z&@x|r&@x+`&@xRɗ&@xhf&@p7&@pRjl&@p2B&@pr&@pR&@hHy&@h,&@hrY?&@hQ&@hrCd&@h4w&@`҉&@`Rq&@`Z&@`2&@`rKԗ&@XR?&@X&@Xr& !&@X3&@X҈c1'&@PD&@PR8V-&@P>i&@P{3&@PL{&@H9&@H2&@HqV?&@H&@H=E&@@21&@@L&@@}n#&@@2 6R&@@ZH&@8I[X&@8@m&@82^&@8R,%&@8åd&@8b&@0j&@0&@0=p&@0&@0Rzw&@($(&@(:}&@(4VM&@(2_&@(Kr&@ 1&@ iЗ &@ n&@ 2 &@ $ϕ&@һJ&@T&@r&@&&@R*,%&@Rc?&@RlR+&@d&@R?w1&@\މ&@}7'@r'@]='@r Y'@C'@m'@R!5 J'@'@2r1P'@RGD'@2VV'@ҾNi'@r}{\'@='@*b'@rɳ'@hh'@P'@n '@D '@ru '@# '@RP!6{ '@R"H '@R^[ '@m '@r '@|; '@Wڥ'@4y'@2˓'@'@U'@ҹ'@'@22(#'@p:'@[pM)'@H`'@R7r/'@'M'@5'@'@*;'@Ͼ'@gA'@R'@2H'@D'@,N'@?'@!RT'@d'@`wZ'@2 '@`'@"='@r1f'@2B{'@Tl'@h'@~X s'@'@21y '@5D '@V!'@ti"'@r(|"'@J#'@2oQ#'@R$'@2Ƒ$'@.%'@R%'@r?m&'@n &'@R#!''@J6''@RH'('@<[('@rt(n-)'@2ǀ)'@f3*'@'*'@2f9+'@D˼+'@?,'@2.,'@rt"F-'@-'@Ra(L.'@Q;.'@RMR/'@r>`/'@r?rX0'@2}0'@^1'@=1'@2[d2'@2'@Jj3'@R93'@xq4'@xhx4'@xr-w5'@x/?5'@xrVR}6'@xd7'@phw7'@pr48'@pBԜ8'@pRs 9'@p"9'@pR:'@h R:'@h;'@h ;'@hr0<'@h1<'@`rloD%='@`W='@`li+>'@`M|>'@`t1?'@`r?'@X,7@'@X ƺ@'@Xҙk=A'@Xr' A'@XCB'@XRHJB'@Pr#JC'@P2p6C'@P)IPD'@PR[D'@P9hnVE'@PE'@PRs\F'@HGF'@HRbG'@HrWG'@Hr%hH'@HH'@HKeoI'@@I'@@(uJ'@@OD;J'@@M{K'@@`K'@@2d#sL'@82ÅM'@8bM'@8 N'@8CN'@82AO'@82O'@0|P'@0r>!P'@0Q'@0`-Q'@0ҍ@#R'@0rVRR'@( @e)S'@(2wS'@(2/T'@(T'@(\5U'@(0_¸U'@ 2;V'@ ܞV'@ >AW'@ r W'@ k~HX'@ I2X'@ )DNY'@r ^WY'@iTZ'@2ԝ|Z'@2=Z['@2ݡ['@}`\'@{\'@Rif]'@RY]]'@Kl^'@>^'@3=$s_'@+6_'@#}Iy`'@\`'@2na'@r]b'@b'@Rc'@=c'@R$d'@+}ޑd'@4e'@R?e'@K]f'@RZ(f'@rj;!g'@R|=Ng'@2`'h'@}sh'@Ҽ-i'@սi'@]3j'@r j'@+9k'@2L>k'@n?l'@~l'@Fm'@޾-m'@_@Ln'@2Rn'@_eRo'@2?xo'@ߊXp'@p'@r$ ^q'@2Zq'@`dr'@r'@js'@BA s'@2qt'@2t'@"Ewu'@GWu'@bj}v'@}w'@Rw'@riCx'@R㴉x'@ y'@rU$ڏy'@z'@dz'@rQ{'@2${'@rF7|'@]I|'@\%}'@R'o}'@yǁ+~'@2g~'@r@1'@R'@ I7'@rw޺'@='@O*'@D'@R/k)ǂ'@ y''@hߋ'@hr-'@h !'@h3'@hcֶ'@`9'@`R'@`E@'@` ì'@`3F'@`r )Fɭ'@`XL'@`2 kkϮ'@X2, ~R'@X2:կ'@XINX'@X[۰'@Xrn^'@XR1'@X2d'@Xs'@Pk'@P2%'@PW8q'@P&J'@PRH]w'@Pk:p'@Pۂ}'@Pr|'@H2'@H '@H6`͉'@Hd '@H'@H2C'@Hr'@@.*'@@e'='@@RO'@@ib'@@ u%'@@2S'@@M+'@@'@@21'@8R]1Ҵ'@8r7'@82s'@87 >'@82'@8rW/D'@8R"A'@8sTJ'@0;g'@0yP'@0s~'@0V'@0r''@0b\'@02'@02Bb'@(F'@(i'@(m!'@(2*4o'@(2=F'@(ҧmYu'@(rl'@(~{'@ Q'@ d'@ rؔ'@ M6ɇ'@ 2 '@ 2>y'@ '@ 5'@ ]&'@248'@2K'@9B^'@p#'@F'@&)'@ZȨ'@i/'@v β'@R5'@rN'@2,<'@'@RY3+B'@r='@rvPH'@2*c'@ȹuN'@2i['@2 T'@2'@T@Z'@r'@`'@P%'@ g'@2h'@\ 0m'@B'@MUs'@xg'@20zy'@2'@ԟ'@av'@R Ņ'@'@2['@2g'@2-'@@"'@R4'@rG'@rV&Z'@R%l!'@i'@R ''@R'@RrO-'@Jɰ'@#3'@4'@:'@x'@'@'@}9'@2b^LF'@2H_'@0qL'@D'@R'@2'@)X'@'@rm^'@Ҹ'@Үe'@S'@r+k'@қ>'@29Qq'@2c'@}vw'@'@}'@2c'@2'@'@rI'@ '@ߍ '@/'@0'@tC'@R.V'@RFh'@`Z{'@{%'@2'@r@+'@RŮ'@1'@ ''@G7(@2ok(@ #>(@į5(@RQHD(@!Z(@RmJ(@r8(@2ڒP(@|(@(V(@b(@c\(@2(@rc(@\J(@'i(@R:(@*1Mo (@2s_ (@2uru (@ (@V{ (@\ (@R (@RJ (@C (@ (@N(@R*(@2,(@ao?(@rR(@"d(@҅Vw(@#(@rQ(@ҹ=)(@#(@/(@$(@m5(@i (@R <(@Ǯ1(@=QDB(@RV(@0iH(@8|(@*ێN(@2}(@+ T(@(@4eZ(@Һ(@rC`(@L(@Y#g(@6(@w4Im(@R [(@yns(@1(@Ⱦy (@Raa (@!(@"(@26Iޅ"(@#(@w#(@1$(@2($(@2gv;%(@N%(@r`&(@f^s&(@!'(@ģ'(@vF'((@*齪((@Rߋ-)(@R.)(@RO3*(@ t*(@R:+(@r-+(@rD\@@,(@RR,(@ɡeF-(@2Dx-(@RVL.(@R.(@,R/(@r/(@҄rX0(@T0(@&^1(@RZ 1(@e2(@22(@CEk3(@ZW3(@R7jq4(@,}4(@Ώw5(@q5(@}6(@7(@rZڃ7(@rq8(@r\8(@xIC 9(@x7$9(@x'7:(@x,J:(@x \;(@xro;(@x<(@x󷔢<(@xZ%=(@xr=(@x+>(@xRC߮>(@xR1?(@pR?(@p,8@(@pR)@(@ps<>A(@pOA(@paDB(@p-\tB(@p=JC(@pOC(@pcEPD(@pryD(@pVE(@pR.E(@hR\F(@h2t F(@hcG(@hR!.G(@hC^AiH(@hgTH(@hfoI(@h2GyI(@huJ(@h J(@h61{K(@heK(@hwցL(@hRM(@`M(@`r2a N(@`2j!N(@`3O(@`JFO(@`XP(@`ZkP(@`r4~Q(@`אQ(@`"{#R(@`hR(@`ү)S(@`rd۬S(@`D/T(@XT(@XN6U(@X1%U(@X8y(@8jOQz(@82(@0jh(@0V{D(@0D1ǂ(@0r4ՠJ(@0%y̓(@0RP(@0Rӄ(@0ReV(@0م(@0R](@0P#(@05c(@0rH(@0<[i(@0rm(@(o(@(r)(@(2 ͥu(@(q(@(#{(@(1(@(@](@(R(@(f(@(r{I( (@(r:(@(RM(@(5`(@(2r(@(r~(@(R "(@(2Bƪ(@(ej#(@(Ц(@()(@(V(@ 0(@ 2(@ r`C-6(@ r?(@ 2‹R<(@ /e(@ 2+wB(@ rbxŗ(@ rH(@ ˘(@ eN(@ Q љ(@ 2T(@ Qך(@  [(@ R\ޛ(@ r>2a(@ D(@ r7Wg(@ Gj(@ |m(@ 2(@ rSs(@ 깳(@U y(@r(@((@S(@(@2_ " (@2ņ4(@R*F(@SY(@Rk(@U ~(@2(@R(@xS!(@rعǤ(@27 '(@R쪨(@-(@OS(@#4(@ 6(@_H:(@Z(@Sm@(@Riì(@2F(@rɭ(@kL(@rRϮ(@2R(@2gկ(@rY(@ ܰ(@r[R%_(@27(@RJe(@H\(@nk(@Q(@.q(@y(@Ąw(@ (@RVQ}(@2(@r(@+(@rq&(@P9 (@K(@R=^(@p(@r(@2P(@RB(@r(@%(@ި(@r:O+(@v(@2(@R((@2&:8(@_NM(@R_>(@r(@2D(@:(@oMJ(@2(@P(@2 (@;V(@lL(@R](@*(@r~(@X{P(@zb(@Gu(@R(@(@y(@#(@R6FѦ(@R)(@n(@rx0(@@@@@##DT*CZf(@@@@@@@##FH8Hzxi<##MDDate: 22.11.2018 Time: 15:27 Recording Duration: 00:00:12 §@ Database: Test Experiment: Experiment Workspace: Workspace Devices: ETK test device:1 Program Description: ASAP2_Demo_V171 WP: ASAP2_Demo_V171_1 RP: ASAP2_Demo_V171 Date: 11/22/2018 Time: 03:26:35 PM Pre-trigger Time: 0[s] Recording Duration: 00:00:12 Post-trigger Time: 0[s]INCA PC Reference TimeTestVehicleP2016_09_AE_MCD_2MC_BS_V1_7_1_mainCompanyNameUserName@@##MDTool Initial CreateTGTFCompany1ToolModule: mdf40plugin.dll, Product version: 7.2.10.0, File version: 17.7210.15.52380 Module: mdf_framework.dll, Product version: 7.2.10.0, File version: 17.7210.15.52380 >@@@@@@@##MD (re)write header comment to file DTL_3.0 Continental 3.8.3.0147 uidn3651 Version 1.5.101.0 licensed to Continental Teves AG & Co. oHG Tool 'Datalyser' (50253000003) Datalyser3.exe version 3.8.3.147 t>##FH8H |ͺ,x##MD( Date: 22.11.2018 Time: 15:27 Recording Duration: 00:00:12 §@ Database: Test Experiment: Experiment Workspace: Workspace Devices: ETK test device:1 Program Description: ASAP2_Demo_V171 WP: ASAP2_Demo_V171_1 RP: ASAP2_Demo_V171 Date: 11/22/2018 Time: 03:26:35 PM Pre-trigger Time: 0[s] Recording Duration: 00:00:12 Post-trigger Time: 0[s] ##MD Min/max values changed ... CANape Vector Informatik GmbH 12.0.70.58902 uidn3651 ##FH8nY;x##MD Min/max values changed (37 times) CANape Vector Informatik GmbH 12.0.70.58902 uidn3651 ##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`x`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV` p`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`h`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`0`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`(x`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`8`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`0`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`(`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`8`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`0`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`(`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`@`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`P`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`H`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`@`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`X`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`P`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV```ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`X`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`P`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`h`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV```ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`x`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`x`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`(`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV` `ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`0`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`(`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`@`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`X`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`P`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`H`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV```ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV` X`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV` P`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV` h `ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`0 ` `ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`( x `ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`  `ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV` `ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`0`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`(x`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV` `ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`8`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`0`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`H`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV```ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`X`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`P`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`H`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV``ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`X`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`P`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`H`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV```ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`X`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`p `ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`!`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`" `ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`x#!`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`p$"`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`h%#`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`$`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`x'%`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`p(&`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`h)'`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`*(`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`x+)`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`,*`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`-+`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`.,`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`/.`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`0/`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`1/`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`20`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`1`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`42`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`53`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`64`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`75`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`86`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`97`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`:8`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`;:`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`< ;`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`=<`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`>=`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`?>`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`@?`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`?`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`B@`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`CA`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`DC`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`EC`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`FD`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`GF`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`HG`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`IH`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`J0I`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`K(J`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`L K`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`ML`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`NM`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`ON`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`O X3?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`QO`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`RP`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`SR`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`TS`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`US`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`VU`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`WV`ݼ?##TX test.unit.daxil.gui.widgets.test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`X W`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`Y8X`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`Z0Y`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`[(Z`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`\ [`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`]\`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`^]`ݼ?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`_^ X3?##TX test_KeyboardShortcuts.TestKeyboardShortcuts.test_Shortcut_Ctrl_I DAXil ##EV`_ X3?##TXh dztfgbsrftgbasrt asammdf ##EV`_m @##MD Date: 22.11.2018 Time: 15:27 Recording Duration: 00:00:12 §@ Database: Test Experiment: Experiment Workspace: Workspace Devices: ETK test device:1 Program Description: ASAP2_Demo_V171 WP: ASAP2_Demo_V171_1 RP: ASAP2_Demo_V171 Date: 11/22/2018 Time: 03:26:35 PM Pre-trigger Time: 0[s] Recording Duration: 00:00:12 Post-trigger Time: 0[s] ##MD Date: 22.11.2018 Time: 15:27 Recording Duration: 00:00:12 §@ Database: Test Experiment: Experiment Workspace: Workspace Devices: ETK test device:1 Program Description: ASAP2_Demo_V171 WP: ASAP2_Demo_V171_1 RP: ASAP2_Demo_V171 Date: 11/22/2018 Time: 03:26:35 PM Pre-trigger Time: 0[s] Recording Duration: 00:00:12 Post-trigger Time: 0[s] D:\TT2\m.dspf asammdf-8.5.1/test/asammdf/gui/resources/functions.py000066400000000000000000000024041502633300400227000ustar00rootroot00000000000000import numpy as np def Function1(t=0): sequence = range(10) filtered = list(filter(lambda i: i % 2, sequence)) if filtered: for _ in filtered: if not _: continue try: int(_) except ValueError: print(str(_)) break else: return 1 return 2 else: return 0 def Function2(t=0): sequence = range(10) filtered = filter(lambda i: i % 2, sequence) if len(filtered): for _ in filtered: if not _: continue try: int(_) except ValueError: print(str(_)) break else: return 1 else: return 0 def UnresolvedVariable(t=0): a, b = 0, 1 if a: c = 0 return c def WrongDefinition(): return 1 def gray2dec(position_sensor_value=0, t=0): for shift in (8, 4, 2, 1): position_sensor_value = position_sensor_value ^ (position_sensor_value >> shift) return position_sensor_value def maximum(channel1=0, channel2=-1, channel3=0, t=0): return max(channel1, channel2, channel3) def rpm_to_rad_per_second(speed=0, t=0): return 2 * np.pi * speed / 60 asammdf-8.5.1/test/asammdf/gui/resources/functions_definitions.def000066400000000000000000000010071502633300400253770ustar00rootroot00000000000000{ "maximum": "def maximum(channel1=0, channel2=-1, channel3=0, t=0):\n return np.maximum.reduce([channel1, channel2, channel3])", "gray2dec": "def gray2dec(position_sensor_value=0, t=0):\n\n for shift in (8, 4, 2, 1):\n position_sensor_value = position_sensor_value ^ (position_sensor_value >> shift)\n\n return position_sensor_value", "rpm_to_rad_per_second": "def rpm_to_rad_per_second(speed=0, t=0):\n return np.diff(speed) / np.diff(t)", "Function1": "def Function1(t=0):\n return 0" }asammdf-8.5.1/test/asammdf/gui/resources/invalid_EmptySection.lab000066400000000000000000000000061502633300400251230ustar00rootroot00000000000000[lab] asammdf-8.5.1/test/asammdf/gui/resources/invalid_JsonDecodeError.dspf000066400000000000000000000072121502633300400257330ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Plot 0", "configuration": { "channels": [ { "type": "channel", "name": "NotExistingSignal", "unit": "hours", "flags": 0, "enabled": true, individual_axis": false, "common_axis": false, "color": "#1f77b4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -419.06000000000006, 135.34000000000003 ], "origin_uuid": "e038b3c7fd55" }, { "type": "channel", "name": "ASAM.M.SCALAR.ULONG.IDENTICAL", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff7f0e", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -54.94500000000001, 2142.855 ], "origin_uuid": "e038b3c7fd55" } ], "pattern": {}, "splitter": [ 487, 267, 0 ], "y_axis_width": 48.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": false, "common_axis_y_range": [ 0.0, 1.0 ], "channels_header": [ 487, [ 292, 83, 42, 35, 35 ] ], "hide_axes": false, "hide_selected_channel_value_panel": false, "focused_mode": false, "delta_mode": "value", "hide_bookmarks": true }, "geometry": [ 778, 497, 777, 496 ], "maximized": false, "minimized": false, "type": "Plot" }, { "title": "Numeric 0", "configuration": { "format": "Physical", "mode": "offline", "channels": [ { "origin_uuid": "0", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "ranges": [], "format": "phys" }, { "origin_uuid": "2", "name": "ASAM.M.SCALAR.ULONG.IDENTICAL", "ranges": [], "format": "phys" } ], "pattern": {}, "float_precision": -1, "header_sections_width": [ 343, 126, 138, 132 ], "font_size": 9 }, "geometry": [ 778, 0, 777, 497 ], "maximized": false, "minimized": false, "type": "Numeric" }, { "title": "Tabular 0", "configuration": { "sorted": true, "filtered": false, "filters": [], "time_as_date": false, "pattern": {}, "format": "phys", "ranges": { "timestamps": [], "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE": [], "ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4": [], "Index": [] }, "header_sections_width": [ 201, 124, 299 ], "font_size": 9 }, "geometry": [ 0, 0, 778, 993 ], "maximized": false, "minimized": false, "type": "Tabular" } ], "functions": {} }asammdf-8.5.1/test/asammdf/gui/resources/invalid_MissingSection.lab000066400000000000000000000003101502633300400254340ustar00rootroot00000000000000ASAM.M.SCALAR.FLOAT64.IDENTICAL ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4 ASAM_[1].M.MATRIX_DIM_16.UBYTE.IDENTICAL ASAM_[11].M.MATRIX_DIM_16.UBYTE.IDENTICAL ASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL time timeasammdf-8.5.1/test/asammdf/gui/resources/invalid_NumericSectionKeyError.dspf000066400000000000000000000074251502633300400273240ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Plot 0", "configuration": { "channels": [ { "type": "channel", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#1f77b4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -419.06000000000006, 135.34000000000003 ], "origin_uuid": "e038b3c7fd55" }, { "type": "channel", "name": "ASAM.M.SCALAR.ULONG.IDENTICAL", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff7f0e", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -54.94500000000001, 2142.855 ], "origin_uuid": "e038b3c7fd55" } ], "pattern": {}, "splitter": [ 487, 267, 0 ], "y_axis_width": 48.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": false, "common_axis_y_range": [ 0.0, 1.0 ], "channels_header": [ 487, [ 292, 83, 42, 35, 35 ] ], "hide_axes": false, "hide_selected_channel_value_panel": false, "focused_mode": false, "delta_mode": "value", "hide_bookmarks": true }, "geometry": [ 778, 497, 777, 496 ], "maximized": false, "minimized": false, "type": "Plot" }, { "title": "Numeric 0", "configuration": { "FORMAT": "Physical", "mode": "offline", "channels": [ { "origin_uuid": "0", "name": "", "ranges": [], "format": "phys" }, { "origin_uuid": "2", "name": "ASAM.M.SCALAR.ULONG.IDENTICAL", "ranges": [], "format": "phys" } ], "pattern": {}, "float_precision": -1, "header_sections_width": [ 343, 126, 138, 132 ], "font_size": 9 }, "geometry": [ 778, 0, 777, 497 ], "maximized": false, "minimized": false, "type": "Numeric" }, { "title": "Tabular 0", "configuration": { "sorted": true, "channels": [ "timestamps", "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4" ], "filtered": false, "filters": [], "time_as_date": false, "pattern": {}, "format": "phys", "ranges": { "timestamps": [], "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE": [], "ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4": [], "Index": [] }, "header_sections_width": [ 201, 124, 299 ], "font_size": 9 }, "geometry": [ 0, 0, 778, 993 ], "maximized": false, "minimized": false, "type": "Tabular" } ], "functions": {} }asammdf-8.5.1/test/asammdf/gui/resources/invalid_PlotSectionKeyError.dspf000066400000000000000000000074251502633300400266400ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Plot 0", "configuration": { "channels": [ { "type": "channel", "name": "", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#1f77b4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -419.06000000000006, 135.34000000000003 ], "origin_uuid": "e038b3c7fd55" }, { "type": "channel", "name": "ASAM.M.SCALAR.ULONG.IDENTICAL", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff7f0e", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -54.94500000000001, 2142.855 ], "origin_uuid": "e038b3c7fd55" } ], "pattern": {}, "splitter": [ 487, 267, 0 ], "y_axis_width": 48.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": false, "common_axis_y_range": [ 0.0, 1.0 ], "channels_header": [ 487, [ 292, 83, 42, 35, 35 ] ], "hide_axes": false, "hide_selected_channel_value_panel": false, "focused_mode": false, "delta_mode": "value", "hide_bookmarks": true }, "geometry": [ 778, 497, 777, 496 ], "maximized": false, "minimized": false, "type": "Plot" }, { "title": "Numeric 0", "configuration": { "format": "Physical", "mode": "offline", "channels": [ { "origin_uuid": "0", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "ranges": [], "format": "phys" }, { "origin_uuid": "2", "name": "ASAM.M.SCALAR.ULONG.IDENTICAL", "ranges": [], "format": "phys" } ], "pattern": {}, "float_precision": -1, "header_sections_width": [ 343, 126, 138, 132 ], "font_size": 9 }, "geometry": [ 778, 0, 777, 497 ], "maximized": false, "minimized": false, "type": "Numeric" }, { "title": "Tabular 0", "configuration": { "sorted": true, "channels": [ "timestamps", "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4" ], "filtered": false, "filters": [], "time_as_date": false, "pattern": {}, "format": "phys", "ranges": { "timestamps": [], "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE": [], "ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4": [], "Index": [] }, "header_sections_width": [ 201, 124, 299 ], "font_size": 9 }, "geometry": [ 0, 0, 778, 993 ], "maximized": false, "minimized": false, "type": "Tabular" } ], "functions": {} }asammdf-8.5.1/test/asammdf/gui/resources/invalid_TabularSectionKeyError.dspf000066400000000000000000000072401502633300400273070ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Plot 0", "configuration": { "channels": [ { "type": "channel", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#1f77b4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -419.06000000000006, 135.34000000000003 ], "origin_uuid": "e038b3c7fd55" }, { "type": "channel", "name": "ASAM.M.SCALAR.ULONG.IDENTICAL", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff7f0e", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -54.94500000000001, 2142.855 ], "origin_uuid": "e038b3c7fd55" } ], "pattern": {}, "splitter": [ 487, 267, 0 ], "y_axis_width": 48.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": false, "common_axis_y_range": [ 0.0, 1.0 ], "channels_header": [ 487, [ 292, 83, 42, 35, 35 ] ], "hide_axes": false, "hide_selected_channel_value_panel": false, "focused_mode": false, "delta_mode": "value", "hide_bookmarks": true }, "geometry": [ 778, 497, 777, 496 ], "maximized": false, "minimized": false, "type": "Plot" }, { "title": "Numeric 0", "configuration": { "format": "Physical", "mode": "offline", "channels": [ { "origin_uuid": "0", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "ranges": [], "format": "phys" }, { "origin_uuid": "2", "name": "ASAM.M.SCALAR.ULONG.IDENTICAL", "ranges": [], "format": "phys" } ], "pattern": {}, "float_precision": -1, "header_sections_width": [ 343, 126, 138, 132 ], "font_size": 9 }, "geometry": [ 778, 0, 777, 497 ], "maximized": false, "minimized": false, "type": "Numeric" }, { "title": "Tabular 0", "configuration": { "sorted": true, "filtered": false, "filters": [], "time_as_date": false, "pattern": {}, "format": "phys", "ranges": { "timestamps": [], "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE": [], "ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4": [], "Index": [] }, "header_sections_width": [ 201, 124, 299 ], "font_size": 9 }, "geometry": [ 0, 0, 778, 993 ], "maximized": false, "minimized": false, "type": "Tabular" } ], "functions": {} }asammdf-8.5.1/test/asammdf/gui/resources/missingItems.dspf000066400000000000000000000255611502633300400236600ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Plot 0", "configuration": { "channels": [ { "type": "channel", "name": "ASAM.M.SCALAR.SBYTE.LINEAR_MUL_2", "unit": "m/s", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#1f77b4", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ -256.0, 254.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "1stMissingItem", "unit": "", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#7975eb", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ -256.0, 254.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.SLONG.IDENTICAL", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff7f0e", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ 0.0, 999.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.SWORD.IDENTICAL", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#2ca02c", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ 0.0, 999.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4", "unit": "rpm", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#d62728", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ 4.0, 259.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.HYPERBOLIC", "unit": "km/h", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#c94597", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ 0.00392156862745098, 1.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.IDENTICAL", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#8c564b", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ 0.0, 255.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.IDENTICAL.STATUS_STRING", "unit": "m/s", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#e377c2", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ 0.0, 255.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.RAT_FUNC.DIV_10", "unit": "km/h", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#7f7f7f", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ 0.0, 25.5 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.RAT_FUNC.IDENT.STATUS_STRING", "unit": "m/s", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#bcbd22", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ 0.0, 255.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.TAB_INTP_DEFAULT_VALUE", "unit": "U/ min", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#17becf", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ 100.0, 111.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.TAB_INTP_NO_DEFAULT_VALUE", "unit": "U/ min", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#1f77b4", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ 100.0, 111.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.TAB_NOINTP_DEFAULT_VALUE", "unit": "U/ min", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff7f0e", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ 100.0, 111.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.TAB_NOINTP_NO_DEFAULT_VALUE", "unit": "U/ min", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#2ca02c", "computed": false, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "y_range": [ 100.0, 111.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "ASAM.M.SCALAR.UBYTE.TAB_VERB_DEFAULT_VALUE", "unit": "unknown signal type", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#d62728", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ 0.0, 255.0 ], "origin_uuid": "ae683e64a806" }, { "type": "channel", "name": "FirstVirtualChannel", "unit": "", "flags": 32, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#85cf0c", "computed": true, "ranges": [], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "computation": { "args": {}, "channel_comment": "", "channel_name": "FirstVirtualChannel", "channel_unit": "", "computation_mode": "sample_by_sample", "function": "TestVirtualChannel", "triggering": "triggering_on_channel", "triggering_value": "MAIN_CLOCK", "type": "python_function" }, "y_range": [ -1.0, 0.0 ], "origin_uuid": "ae683e64a806" } ], "pattern": {}, "splitter": [ 394, 284, 0 ], "x_range": [ -0.7252090113273859, 13.152907274715773 ], "y_axis_width": 0.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": false, "common_axis_y_range": [ 0.00392156862745098, 1.0 ], "channels_header": [ 394, [ 366, 83, 122, 35, 35 ] ], "hide_axes": true, "hide_selected_channel_value_panel": false, "focused_mode": false, "delta_mode": "delta", "hide_bookmarks": true }, "geometry": [ 0, 0, 688, 646 ], "maximized": true, "minimized": false, "type": "Plot" } ], "functions": { "TestVirtualChannel": "def TestVirtualChannel(t=0):\n return 1" } }asammdf-8.5.1/test/asammdf/gui/resources/saved.dspf000066400000000000000000000103361502633300400223010ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Display channels", "configuration": { "channels": [ { "type": "channel", "name": "ASAM.M.SCALAR.FLOAT32.IDENTICAL", "unit": "hours", "flags": 1, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff0000", "computed": false, "ranges": [ { "background_color": "#ffffff", "font_color": "#00ff00", "op1": "<=", "op2": "<=", "value1": 0.0, "value2": 100.0 }, { "background_color": "#ffffff", "font_color": "#ff0000", "op1": "<=", "op2": "<=", "value1": 100.0, "value2": 200.0 } ], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "comment": "", "y_range": [ -27.75, 1026.75 ], "origin_uuid": "95f656e7a338" }, { "type": "group", "name": "Group01", "enabled": true, "pattern": null, "ranges": [], "origin_uuid": "000000000000", "expanded": false, "disabled": false, "channels": [ { "type": "group", "name": "Group0101", "enabled": true, "pattern": null, "ranges": [], "origin_uuid": "000000000000", "expanded": false, "disabled": false, "channels": [ { "type": "channel", "name": "ASAM.M.SCALAR.SLONG.IDENTICAL", "unit": "hours", "flags": 1, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#a0a0a4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "comment": "", "y_range": [ -27.75, 1026.75 ], "origin_uuid": "95f656e7a338" } ] }, { "type": "channel", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL", "unit": "hours", "flags": 1, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#a0a0a4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "comment": "", "y_range": [ -135.08336345098002, 134.08336654901996 ], "origin_uuid": "95f656e7a338" } ] } ], "pattern": {}, "splitter": [ 394, 122, 0 ], "y_axis_width": 48.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": true, "common_axis_y_range": [ 0.0, 1.0 ], "channels_header": [ 394, [ 254, 83, 42, 0, 35 ] ], "hide_axes": false, "hide_selected_channel_value_panel": true, "focused_mode": false, "delta_mode": "value", "hide_bookmarks": false }, "geometry": [ 0, 0, 526, 646 ], "maximized": true, "minimized": false, "type": "Plot" } ], "functions": {} }asammdf-8.5.1/test/asammdf/gui/resources/test_batch.mf4000066400000000000000000000210701502633300400230460ustar00rootroot00000000000000MDF 4.10 amdf8.0.##HDhDVR##MDPBLTIAHKJAAAIBYWSNHGUWQCDSDBMLGNSXRAMHHVENKUACUKAVITKXWB##DZDTRx^ 6 \pQrl~ԭ~.8|T"TJ&]kq`pd<F)7|iBE#.ޠl@$  $J@I`0J"`Qp $ 8 A `,E% J# d,Ppp-A#P$F%THB2FRq0N'  HLq(F£:AH0( X$,%J&p&f(<C!|D$@$ A8Kb0D:@@$F 8 K Q'R`(K ӖD8Eǂ Pf 02BJ 8A%aX2IA1$LH@0*V R0 ,%2 L R$0d#t @%`G t"H DB$D NFPŢcإ2 - 10 BFNP0B~f’fmYK%?^hH`0K؟wR :J!/8,B"0 i(* Y[aI+@X, K -M0  G̈́%ڲlUQ -0 >beǸcpW R1RGmgc݊ML!f<))-+~^CyYu]]7 MTjssKkk[{{GggWwww7F0N}>0g2 &L|Z` Lfd<bXb1XE/cZx1܋Y "jK!K!^K!kBt)ĖbR[ X ɥXH4?͆F槑g2J>|}0=N{|־cF|ƹ =}.|"/f^!Ѹn+R_7^0%}j*gL%˦GnAQ}Owe]։z 9sd٫YF֭Bz!f=nGta *^NcZЗa|z cnP}~N'ma_1?;3뫏hom6BQQVR^ !"ZHc j*[6ʬ]-ec|ltxM]-yU% /7;#=5a⽸;7WBp|.vh+KǏ29hoz;Z0e-7AdKY _ dgc]yFCozh]m-T uu_վy^]U\VZɓRAqūCw`v\W4t6]Zn[wu  v?ej*#mKp0Bk:!vlj JN^AuU4; 8wtƸ`ϢN8ffb]MEQ^VJ\TXVjsd*ɥ%O de$=LMyf8z!wo SW|QF2,j^?U 9;> /';333+;7MsGԗ¢R2PE%:5mp(*o %)Vlja!AU|<`0'''`|rN sss&<7x73p2`ҿsiW[\*K?vSe|,3&s"2g.aY\}\X.C ,2d;5%Qabx{Z&jXƩd;HM v8[W.db-udۇBdJ[JMYQ-r,^ppf%[/:gR|hIkz#H˟^LN]L[I%,tѲMf 'KO4òRyU0DNWC^;ej*cS6K&W[?65h۾i|sӖHx`':Qy 21P,Yt:3M zֽc1K(; O׺WC̮6 ^%f Q6$p9}dk<#g䳵=y#Fi%tu5FgPiBJw |WwvHmjgyPVn@5zJU0$9}]Lp("lB=TO¶i=/p]}ٯKޯs.]B_X]ܑ*Rjz]8H.ytwhDT(=(?o-{ʗ!%Z[7k>Ȝ{/gc3kr5㍥Y%߲Hꞹr"$E.$#ij[b<%3氩/ \,Y뽱G}ن7|6n+[^M'̃70{7<=˓O\xt@,M+Tש(?\gu7e)rfqJ&CЎt^u6 57+yf|2ւ6z? 9wPq6Y1ahWCeɇUA2g¡'޶8z˗Khy?e1hj1Z̹KZwWE4t8h|)Ѥ14*V&wf6V?%oWT;>b»^Hُsmה;d~VuDzXþnsxԢ;䛱b;MpӼT@Pص[2}z98m+EUn>vj; ltnd3~*ֵ;Dg R45#Q;*ȵN>,A+;z0Inell+!=7??7=v-MO±g5eu*{(N@\հ)Yu-,VnkDg|a33s&ff?TXKgڠ}H㽈;Y@y8X>\H8ٶ^14 hqphQ?FGt:}`;…Ș4=meu挵5mcck{3r9WWW777ww{xxxxzzzyyyaX/L.xcΞ>vpVia֚G˞G 57ca w5R*󳉩IRR3sIO*k^5t|`LςX9y0_ `[e~nHN2>NL&q=Cy[ ^ L\/%% F 򛀘oVTܲeV *}ǼCc2ʩy.2[uLYٻz\~36!nLl\\|||\\ll(Ȉ7+!.x{yyzxgs?E?? |ҥK!K \9E{+;"`NPCd^~?ÏEYfeJ5ZW"R*  @+ʢnk ip\$ʏkd4>Q }lCvcFJ:yJҌl[scg@W+ޯ^ơ!^*~ߔ_'u.qǘxY+niMVO)&*+kڠO巛,:$f#U]45˕]IWMX{brړKlHCsMwprR;VOΜvBmkM9)i'9k͔U]>-1_}Q!W=5ByuYS=E:m;8pVTke%=eV+)!mà.YWXߏxZ̟=-'>\𐕫+L)n'rOij٨-*4u螘GWim6{db8Jyk1,<*j mrWYԘV6oB[o#>DΘN?tvÕ?^4NJ珷:ej+e,m-~zk!ڶI{e*ɇlۧYwٱzf*,'kkI\YqC+E**P1ΉTC Ya&[K°6 r< 4wv|+>-LiYſzܦ-4k::::pmO8ɮfT7>XwSLAI[o@嫡W/\rs=}~9 U,3#oۚ^>$?}RX¢RrųJ7M-m]ݴ`ۅp½dbN~QI)\ ؼ()~ݨ7î^ e|}}|bX/On0Nv6g,O7?tpU6Iag<tH41=lv1ԉXm;8:9M038>? 00|)򕫡׮oܼy! X߻aRrrʣԴt"1#3+;;'q^^>ɓ⒒edryEEgUUϟԼxAy De"E@ߢڛj+ OU".\o0\pp(rn}]z{\mTx<##DG@!##TX MCSAKJB##TX TZYQXJD##CNh8X@##TX(BNXJPMAPAVZXPSX##TX HBUNLOS##CN8 H ##TX(XMFJPKJRIVXIQNR##CN! H ##TX(JIYWKIEOINKVADJ##CN H ##TX TZNSSNK##CGhx!asammdf-8.5.1/test/asammdf/gui/resources/test_batch_cut_0.mf4000066400000000000000000000065101502633300400241420ustar00rootroot00000000000000MDF 4.10 amdf8.0.##HDhH  )Fuxi<##MD  Date: 22.11.2018 Time: 15:27 Recording Duration: 00:00:12 §@ Database: Test Experiment: Experiment Workspace: Workspace Devices: ETK test device:1 Program Description: ASAP2_Demo_V171 WP: ASAP2_Demo_V171_1 RP: ASAP2_Demo_V171 Date: 11/22/2018 Time: 03:26:35 PM Pre-trigger Time: 0[s] Recording Duration: 00:00:12 Post-trigger Time: 0[s] C:\Users\uidn3651\Downloads\ASAP2_Demo_V171.dsp ##DZDT l[x^c0Y[^e_h}AXI`!e60xo9``098 L0|o?~R*z-Xe n1##MD Cut from 1.0s to 2.0s asammdf asammdf 8.0.2.dev4 ##FH8X"Tx##MD updated asammdf asammdf 8.0.2.dev4 ##FH8XTx##DG@( ##TX time##TX s##CNX @##TX@ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE##TX hours##MDScalar measurementASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE0.100000##CCP##TX0ETK test device:1##SI8 ##CNp ##TX(100ms_sync##CGh  ##EV`p  & .>##TX($EVENT_COMMENTS##TXXDate: 22.11.2018 Time: 15:26:35 Start event occurred##EV` K& .>##TX($EVENT_COMMENTS##TXPDate: 22.11.2018 Time: 15:26:39 Test Commentasammdf-8.5.1/test/asammdf/gui/resources/test_batch_cut_1.mf4000066400000000000000000000066401502633300400241470ustar00rootroot00000000000000MDF 4.10 amdf8.0.##HDhx )Fuxi<##MD  Date: 22.11.2018 Time: 15:27 Recording Duration: 00:00:12 §@ Database: Test Experiment: Experiment Workspace: Workspace Devices: ETK test device:1 Program Description: ASAP2_Demo_V171 WP: ASAP2_Demo_V171_1 RP: ASAP2_Demo_V171 Date: 11/22/2018 Time: 03:26:35 PM Pre-trigger Time: 0[s] Recording Duration: 00:00:12 Post-trigger Time: 0[s] C:\Users\uidn3651\Downloads\ASAP2_Demo_V171.dsp ##DZDT x^cx ?m`7;RhK] GkN<]+4"{%0чBhN8 L00u^Ft~&xo:,C#,s\ RRR222rrr J_DRNYCהy+69v֓w?xL Cut from 6.0s to 9.0s asammdf asammdf 8.0.2.dev4 ##FH8hy]x##MD updated asammdf asammdf 8.0.2.dev4 ##FH8]x##DG@ ##TX time##TX s##CN @##TX@ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE##TX hours##MDScalar measurementASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE0.100000##CCP##TX0ETK test device:1##SI8H ##CNx  ( ##TX(100ms_sync##CGh X x X  ##EV` H p & .>##TX($EVENT_COMMENTS##TXXDate: 22.11.2018 Time: 15:26:35 Start event occurred##EV`( P K& .>##TX($EVENT_COMMENTS##TXPDate: 22.11.2018 Time: 15:26:39 Test Commentasammdf-8.5.1/test/asammdf/gui/resources/test_insert_cfg.dspf000066400000000000000000000033521502633300400243610ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Plot 0", "configuration": { "channels": [ { "type": "channel", "name": "ASAM_[13][0].M.MATRIX_DIM_16_1.UBYTE.IDENTICAL", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#1f77b4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ 0.0, 255.0 ], "origin_uuid": "8b499db8ee08" } ], "pattern": {}, "splitter": [ 364, 68, 0 ], "x_range": [ -1.2266879363388932, 13.654530499727267 ], "y_axis_width": 0.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": false, "common_axis_y_range": [ 0.0, 1.0 ], "channels_header": [ 364, [ 334, 83, 42, 35, 35 ] ], "hide_axes": true, "hide_selected_channel_value_panel": false, "focused_mode": false, "delta_mode": "value", "hide_bookmarks": false }, "geometry": [ 0, 0, 438, 646 ], "maximized": true, "minimized": false, "type": "Plot" } ], "active_window": "Plot 0", "functions": { "Function1": "def Function1(t=0):\n return 0" } }asammdf-8.5.1/test/asammdf/gui/resources/test_metadata.mf4000066400000000000000000000471501502633300400235540ustar00rootroot00000000000000MDF 4.10 dax3.0.0##HDhxBL[i##MD  Date: 22.11.2018 Time: 15:27 Recording Duration: 00:00:12 §@ Database: Test Experiment: Experiment Workspace: Workspace Devices: ETK test device:1 Program Description: ASAP2_Demo_V171 WP: ASAP2_Demo_V171_1 RP: ASAP2_Demo_V171 Date: 11/22/2018 Time: 03:26:35 PM Pre-trigger Time: 0[s] Recording Duration: 00:00:12 Post-trigger Time: 0[s] C:\Users\uidn3651\Downloads\ASAP2_Demo_V171.dsp ##DZ?DT x^c@##DZ|DT.\Lx^c@Oh3$Whff<Nh pv9by&Dp6N_#v32J##MD Resampled from __new__.mf4 DAXil Continental Automotive Romania 3.0.0.dev_3.0.x_213 ##FH89ECx##MD updated DAXil Continental Automotive Romania 3.0.0.dev_3.0.x_213 ##FH8iCx##DG@ ##DG@@B##TX time##TX s##CN @`@##TX@ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE##TX hours##MDScalar measurementASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE0.100000##CCP##TX0ETK test device:1##SI8 ##CN( X h ##TX(100ms_sync##CGh  ##CN@`@##TXHASAM.M.SCALAR.UBYTE.VTAB_RANGE_NO_DEFAULT_VALUE##TX(hundredfive##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.VTAB_RANGE_NO_DEFAULT_VALUE0.001000##TX(Zero_to_one##TX(two_to_three##TX(four_to_seven##TX0fourteen_to_seventeen##TX0eigteen_to_ninetynine##TX hundred##TX(hundredone##TX(hundredtwo##TX(hundredthree##TX(hundredfour##TX(hundredfive##CC`8 h@` o@?@@@@,@1@2@X@Y@Y@@Y@@Y@Y@Y@Y@Y@Z@Z@@Z@@Z@##CN (8 ` ##TXHASAM.M.SCALAR.UBYTE.TAB_VERB_NO_DEFAULT_VALUE##TX violet##MDScalar measurement with verbal conversionASAM.M.SCALAR.UBYTE.TAB_VERB_NO_DEFAULT_VALUE0.001000##TX red##TX orange##TX yellow##TX green##TX blue##TX violet##CC x(o@@@@@@@##CN 0 Hx ##TXHASAM.M.SCALAR.UBYTE.TAB_INTP_DEFAULT_VALUE##TX U/ min##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_INTP_DEFAULT_VALUE0.001000##CCY@[@X@X@Y@@Y@@Z@@@Z@@Z@@Z@ @[@"@@[@$@[@*@[@##CN  ##TX8ASAM.M.SCALAR.SLONG.IDENTICAL##MDScalar measurementASAM.M.SCALAR.SLONG.IDENTICAL0.001000##CNx X h  ##TXHASAM.M.SCALAR.UBYTE.VTAB_RANGE_DEFAULT_VALUE##TX0out of range value##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.VTAB_RANGE_DEFAULT_VALUE0.001000##TX0out of range value##CC`h@` o@?@@@@,@1@2@X@Y@Y@@Y@@Y@Y@Y@Y@Y@Z@Z@@Z@@Z@##CNp ##TXHASAM.M.SCALAR.UBYTE.IDENTICAL.STATUS_STRING##TX m/s##MDScalar measurement with status stringDI.ASAM.M.SCALAR.UBYTE.IDENTICAL.STATUS_STRING0.001000##CCPo@##CN#  xh##TXHASAM.M.SCALAR.UBYTE.TAB_VERB_DEFAULT_VALUE##TX0unknown signal type##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_VERB_DEFAULT_VALUE0.001000##TX(SawTooth##TX Square##TX Sinus##TX0unknown signal type##CC !"0"P"o@?@@##CN$p " ##TXHASAM_[1][0].M.MATRIX_DIM_8_2.UBYTE.IDENTICAL##MDScalar measurementASAM_[1][0].M.MATRIX_DIM_8_2.UBYTE.IDENTICAL0.001000##CN&# X h ###TX8ASAM.M.SCALAR.UBYTE.IDENTICAL##MDScalar measurementDI.ASAM.M.SCALAR.UBYTE.IDENTICAL0.001000##CN((x% X h %##TX8ASAM.M.SCALAR.FLOAT32.IDENTICAL##MDScalar measurementASAM.M.SCALAR.FLOAT32.IDENTICAL0.001000##CN0+(' X h `' ##TXHASAM.M.SCALAR.UBYTE.TAB_NOINTP_NO_DEFAULT_VALUE##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_NOINTP_NO_DEFAULT_VALUE0.001000##CCY@[@X@X@Y@@Y@@Z@@@Z@@Z@@Z@ @[@"@@[@$@[@*@[@##CN -( *)##TXHASAM.M.SCALAR.UBYTE.TAB_INTP_NO_DEFAULT_VALUE##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_INTP_NO_DEFAULT_VALUE0.001000##CN.+  ,##TX8ASAM.M.SCALAR.ULONG.IDENTICAL##MDScalar measurementASAM.M.SCALAR.ULONG.IDENTICAL0.001000##CN0- X h . ##TXHASAM.M.SCALAR.UWORD.IDENTICAL.BITMASK_0FF0##MDScalar measurement with Bitmask for a bit-areaASAM.M.SCALAR.UWORD.IDENTICAL.BITMASK_0FF00.001000##CNP2p/ X h /##TX8ASAM.M.SCALAR.SBYTE.IDENTICAL##MDScalar measurementASAM.M.SCALAR.SBYTE.IDENTICAL0.001000##CN3P1 X h 1 ##TX8ASAM.M.SCALAR.UWORD.IDENTICAL##MDScalar measurementASAM.M.SCALAR.UWORD.IDENTICAL0.001000##CN52 X h 03!##TXHASAM.M.SCALAR.FLOAT32.IDENTICAL.DISCRETE##MDScalar measurementASAM.M.SCALAR.FLOAT32.IDENTICAL.DISCRETE0.001000##CNh74 X h 4# ##TX8ASAM.M.SCALAR.SWORD.IDENTICAL##MDScalar measurementASAM.M.SCALAR.SWORD.IDENTICAL0.001000##CN9h6 X h 6'##TX8ASAM.M.SCALAR.UBYTE.HYPERBOLIC##TX km/h##MDScalar measurement with status stringDI.ASAM.M.SCALAR.UBYTE.RAT_FUNC.HYPERBOLIC0.001000##CC##CN <8 P9H8h8)##TX@ASAM.M.SCALAR.UBYTE.RAT_FUNC.DIV_10##MDScalar measurement with status stringDI.ASAM.M.SCALAR.UBYTE.RAT_FUNC.DIV_100.001000##CC9@??##CN>x: ;H8:*##TXHASAM.M.SCALAR.UBYTE.TAB_NOINTP_DEFAULT_VALUE##MDScalar measurement with verbal conversion and default valueASAM.M.SCALAR.UBYTE.TAB_NOINTP_DEFAULT_VALUE0.001000##CN?< *=+##TXPASAM.M.SCALAR.UBYTE.RAT_FUNC.IDENT.STATUS_STRING##CCo@??##CNpA> ?h,##TXHASAM.M.SCALAR.UWORD.IDENTICAL.BITMASK_0008##MDScalar measurement with Bitmask for a single bitASAM.M.SCALAR.UWORD.IDENTICAL.BITMASK_00080.001000##CN0@ X h x@-##TX(Engine_1##CGhH B B.##EV`CC0C& .>##TX($EVENT_COMMENTS##TXXDate: 22.11.2018 Time: 15:26:35 Start event occurred##EV`CDK& .>##TX($EVENT_COMMENTS##TXPDate: 22.11.2018 Time: 15:26:39 Test Comment##MD C:\Users\uidn3651\Downloads\ASAP2_Demo_V171.dsp ##MD D:\GHP\C-Test-Iasi\DAXi-3.0.x\test\unit\resources\ASAP2_Demo_V171.dspf ##MD D:\GHP\C-Test-Iasi\DAXi-3.0.x\test\unit\resources\ASAP2_Demo_V171.dspf ##MDX valid.dspf asammdf-8.5.1/test/asammdf/gui/resources/valid.dsp000066400000000000000000000027131502633300400221300ustar00rootroot00000000000000 asammdf-8.5.1/test/asammdf/gui/resources/valid.dspf000066400000000000000000000165101502633300400222760ustar00rootroot00000000000000{ "selected_channels": [], "windows": [ { "title": "Display channels", "configuration": { "channels": [ { "type": "channel", "name": "ASAM.M.SCALAR.FLOAT32.IDENTICAL", "unit": "hours", "flags": 1, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#ff0000", "computed": false, "ranges": [ { "background_color": "#ffffff", "font_color": "#00ff00", "op1": "<=", "op2": "<=", "value1": 0.0, "value2": 100.0 }, { "background_color": "#ffffff", "font_color": "#ff0000", "op1": "<=", "op2": "<=", "value1": 100.0, "value2": 200.0 } ], "precision": 3, "fmt": "{:.3f}", "format": "phys", "mode": "phys", "comment": "", "y_range": [ -27.75, 1026.75 ], "origin_uuid": "117366e58983" }, { "type": "group", "name": "Group01", "enabled": true, "pattern": null, "ranges": [], "origin_uuid": "000000000000", "expanded": false, "disabled": false, "channels": [ { "type": "group", "name": "Group0101", "enabled": true, "pattern": null, "ranges": [], "origin_uuid": "000000000000", "expanded": false, "disabled": false, "channels": [ { "type": "channel", "name": "ASAM.M.SCALAR.SLONG.IDENTICAL", "unit": "hours", "flags": 1, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#a0a0a4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "comment": "", "y_range": [ -27.75, 1026.75 ], "origin_uuid": "117366e58983" } ] }, { "type": "channel", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL", "unit": "hours", "flags": 1, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#a0a0a4", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "comment": "", "y_range": [ -135.08336345098002, 134.08336654901996 ], "origin_uuid": "117366e58983" } ] }, { "type": "channel", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "unit": "hours", "flags": 0, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#d62728", "computed": false, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "y_range": [ -128.0, 124.0 ], "origin_uuid": "117366e58983" }, { "type": "channel", "name": "_C_PositiveValues", "unit": "", "flags": 32, "enabled": true, "individual_axis": false, "common_axis": false, "color": "#b8f11b", "computed": true, "ranges": [], "precision": 3, "fmt": "{}", "format": "phys", "mode": "phys", "computation": { "args": { "a": [] }, "channel_comment": "", "channel_name": "_C_PositiveValues", "channel_unit": "", "computation_mode": "sample_by_sample", "definition": "", "function": "PositiveValues", "triggering": "triggering_on_channel", "triggering_value": "ASAM.M.VIRTUAL.SCALAR.SWORD.PHYSICAL", "type": "python_function" }, "y_range": [ 0.0, 0.0 ], "origin_uuid": "117366e58983" } ], "pattern": {}, "splitter": [ 453, 304, 0 ], "y_axis_width": 48.0, "grid": [ false, false ], "cursor_precision": 6, "font_size": 9, "locked": true, "common_axis_y_range": [ 0.0, 1.0 ], "channels_header": [ 453, [ 293, 83, 42, 0, 35 ] ], "hide_axes": false, "hide_selected_channel_value_panel": true, "focused_mode": false, "delta_mode": "value", "hide_bookmarks": false }, "geometry": [ 767, 2, 775, 940 ], "maximized": false, "minimized": false, "type": "Plot" }, { "title": "Numeric 0", "configuration": { "format": "Physical", "mode": "offline", "channels": [ { "origin_uuid": "0", "name": "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE", "ranges": [], "format": "phys" } ], "pattern": {}, "float_precision": -1, "header_sections_width": [ 323, 106, 118, 112 ], "font_size": 9 }, "geometry": [ 0, 467, 776, 473 ], "maximized": false, "minimized": false, "type": "Numeric" }, { "title": "Tabular 0", "configuration": { "sorted": true, "channels": [ "timestamps", "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE" ], "filtered": false, "filters": [], "time_as_date": false, "pattern": {}, "format": "phys", "ranges": { "ASAM.M.SCALAR.SBYTE.IDENTICAL.DISCRETE": [], "timestamps": [] }, "header_sections_width": [ 355, 278 ], "font_size": 9 }, "geometry": [ 14, 0, 754, 472 ], "maximized": false, "minimized": false, "type": "Tabular" } ], "functions": { "PositiveValues": "def PositiveValues (a=0, t=0):\n\tif a > 0:\n\t\treturn a\n\telse:\n \treturn 0" } }asammdf-8.5.1/test/asammdf/gui/resources/valid.lab000066400000000000000000000003161502633300400220750ustar00rootroot00000000000000[lab] ASAM.M.SCALAR.FLOAT64.IDENTICAL ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4 ASAM_[1].M.MATRIX_DIM_16.UBYTE.IDENTICAL ASAM_[11].M.MATRIX_DIM_16.UBYTE.IDENTICAL ASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL time timeasammdf-8.5.1/test/asammdf/gui/test_base.py000066400000000000000000000436131502633300400206360ustar00rootroot00000000000000#!/usr/bin/env python """ Base Module for Testing GUI - responsible to set up Qt in order to run on multiple platforms - responsible to set up Application class TestBase - responsible to set up and tearDown test workspace - responsible to create easy access to 'resource' directory - responsible to set up ErrorDialog for easy evaluation of raised exceptions - provide method `manual_use` created to help test development process class DragAndDrop - responsible to perform Drag and Drop operations from source widget - specific point, to destination widget - specific point """ from collections.abc import Iterable import os import pathlib import shutil import sys import time import unittest from unittest import mock from h5py import File as HDF5 import pyqtgraph from PySide6 import QtCore, QtGui, QtTest, QtWidgets from asammdf import mdf from asammdf.gui.utils import excepthook if sys.platform == "win32": os.environ["QT_QPA_PLATFORM"] = "windows" elif sys.platform == "linux": os.environ["QT_QPA_PLATFORM"] = "xcb" elif sys.platform == "darwin": os.environ["QT_QPA_PLATFORM"] = "cocoa" else: os.environ["QT_QPA_PLATFORM"] = "windows" app = pyqtgraph.mkQApp() app.setOrganizationName("py-asammdf") app.setOrganizationDomain("py-asammdf") app.setApplicationName("py-asammdf") @unittest.skipIf(sys.platform == "darwin", "Test Development on MacOS was not done yet.") class TestBase(unittest.TestCase): """ - setUp and tearDown test workspace - provide method to execute widget - setUp ErrorDialog for evaluation raised exceptions """ pyqtgraph.setConfigOption("background", "k") pyqtgraph.setConfigOption("foreground", "w") settings = QtCore.QSettings() settings.setValue("zoom_x_center_on_cursor", True) settings.setValue("plot_cursor_precision", 6) longMessage = False resource = os.path.normpath(os.path.join(os.path.dirname(__file__), "resources")) test_workspace = os.path.join(os.path.dirname(__file__), "test_workspace") screenshots = os.path.join(os.path.dirname(__file__).split("test")[0], "screenshots") patchers = [] # MockClass ErrorDialog mc_ErrorDialog = None def shortDescription(self): return self._testMethodDoc @staticmethod def manual_use(w, duration=None): """ Execute Widget for debug/development purpose. Parameters ---------- duration : float | None duration in seconds """ if duration is None: duration = 3600 else: duration = abs(duration) w.showMaximized() loop = QtCore.QEventLoop() QtCore.QTimer.singleShot(int(duration * 1000), loop.quit) loop.exec_() w.showMaximized() @staticmethod def processEvents(timeout=0.001): QtCore.QCoreApplication.processEvents() QtCore.QCoreApplication.sendPostedEvents() QtCore.QEventLoop.processEvents(QtCore.QEventLoop()) if timeout: time.sleep(timeout) QtCore.QCoreApplication.processEvents() QtCore.QCoreApplication.sendPostedEvents() def setUp(self) -> None: if os.path.exists(self.test_workspace): try: shutil.rmtree(self.test_workspace) except PermissionError as e: print(e) if not os.path.exists(self.screenshots): os.makedirs(self.screenshots) os.makedirs(self.test_workspace) self.mc_ErrorDialog.reset_mock() self.processEvents() @classmethod def setUpClass(cls): sys.excepthook = excepthook for patcher in (mock.patch("asammdf.gui.utils.ErrorDialog"),): _ = patcher.start() cls.patchers.append(patcher) cls.mc_ErrorDialog = _ @classmethod def tearDownClass(cls): for patcher in cls.patchers: patcher.stop() def tearDown(self): self.processEvents() path_ = os.path.join(self.screenshots, self.id().split("gui.")[-1].rsplit(".", 1)[0]) if not os.path.exists(path_): os.makedirs(path_) w = getattr(self, "widget", None) if w: w.grab().save(os.path.join(path_, f"{self.id().split('.')[-1]}.png")) self.destroy(w) self.mc_ErrorDialog.reset_mock() if self.test_workspace and pathlib.Path(self.test_workspace).exists(): try: shutil.rmtree(self.test_workspace) except PermissionError as e: self.destroy(w) print(e) @staticmethod def destroy(w): w.close() w.destroy() w.deleteLater() def mouseClick_RadioButton(self, qitem): QtTest.QTest.mouseClick( qitem, QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, QtCore.QPoint(2, qitem.height() / 2), ) self.processEvents() def mouseClick_CheckboxButton(self, qitem): # Same function self.mouseClick_RadioButton(qitem) def mouseClick_WidgetItem(self, qitem): if isinstance(qitem, QtWidgets.QTreeWidgetItem): widget = qitem.treeWidget() elif isinstance(qitem, QtWidgets.QListWidgetItem): widget = qitem.listWidget() else: raise NotImplementedError QtTest.QTest.mouseClick( widget.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, widget.visualItemRect(qitem).center(), ) self.processEvents(0.5) def mouseDClick_WidgetItem(self, qitem): if isinstance(qitem, QtWidgets.QTreeWidgetItem): widget = qitem.treeWidget() elif isinstance(qitem, QtWidgets.QListWidgetItem): widget = qitem.listWidget() else: raise NotImplementedError QtTest.QTest.mouseDClick( widget.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, widget.visualItemRect(qitem).center(), ) self.processEvents(0.5) def avoid_blinking_issue(self, w): self.processEvents(0.01) # To avoid blinking issue, click on a center of widget QtTest.QTest.mouseClick( w, QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, w.rect().center() ) class DragAndDrop: def __init__(self, src_widget, dst_widget, src_pos, dst_pos): QtCore.QCoreApplication.processEvents() # hack QDrag object with mock.patch(f"{src_widget.__module__}.QtGui.QDrag") as mo_QDrag: src_widget.startDrag(QtCore.Qt.DropAction.MoveAction) mo_QDrag.assert_called() mime_data = mo_QDrag.return_value.setMimeData.call_args.args[0] event = QtGui.QDragEnterEvent( dst_pos, QtCore.Qt.DropAction.MoveAction, mime_data, QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, ) with mock.patch.object(event, "source", return_value=src_widget): dst_widget.dragEnterEvent(event) event = QtGui.QDropEvent( dst_pos, QtCore.Qt.DropAction.MoveAction, mime_data, QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, ) with mock.patch.object(event, "source", return_value=src_widget): dst_widget.dropEvent(event) QtCore.QCoreApplication.processEvents() class Pixmap: COLOR_BACKGROUND = "#000000" COLOR_RANGE = "#000032" COLOR_CURSOR = "#e69138" @staticmethod def is_black(pixmap) -> bool: """ Excepting cursor """ image = pixmap.toImage() for y in range(image.height()): for x in range(image.width()): color = QtGui.QColor(image.pixel(x, y)) if color.name() not in (Pixmap.COLOR_BACKGROUND, Pixmap.COLOR_CURSOR): return False return True @staticmethod def is_colored(pixmap, color_name, x, y, width=None, height=None): image = pixmap.toImage() offset = 1 y = y + offset if not width: width = image.width() if not height: height = image.height() for _y in range(offset, image.height()): for _x in range(image.width()): color = QtGui.QColor(image.pixel(_x, _y)) if _x < x or _y < y: continue # De unde 2? elif (_x > width - x) or (_y > height - y - 2): break if color.name() != color_name: print(x, y, width, height) print(_x, _y, color.name()) return False return True @staticmethod def has_color(pixmap, color_name): """ Return True if "pixmap" has "color_name" color """ image = pixmap.toImage() if not isinstance(color_name, str): if hasattr(color_name, "color"): color_name = color_name.color.name() elif hasattr(color_name, "name"): color_name = color_name.name() else: raise SyntaxError(f"Object {color_name} doesn't have the attribute <> or <>") for y in range(image.height()): for x in range(image.width()): color = QtGui.QColor(image.pixel(x, y)) if color.name() == color_name: return True return False @staticmethod def color_names(pixmap): """ Parameters ---------- pixmap: QPixmap object of PlotGraphics object Returns ------- All colors from pixmap including default colors """ color_names = set() image = pixmap.toImage() for y in range(image.height()): for x in range(image.width()): color = QtGui.QColor(image.pixel(x, y)) color_names.add(color.name()) return color_names @staticmethod def color_names_exclude_defaults(pixmap): """ Parameters ---------- pixmap: QPixmap object of PlotGraphics object Returns ------- All colors from pixmap excluding default colors """ color_names = set() defaults = (Pixmap.COLOR_BACKGROUND, Pixmap.COLOR_CURSOR, Pixmap.COLOR_RANGE) image = pixmap.toImage() for y in range(image.height()): for x in range(image.width()): color = QtGui.QColor(image.pixel(x, y)) if color not in defaults: color_names.add(color.name()) return color_names @staticmethod def color_map(pixmap): """ return dict, where: > keys are line of pixmap > values is a list of color names ordered by columns of pixmap """ color_dict = {} line = [] image = pixmap.toImage() for y in range(image.height()): for x in range(image.width()): line.append(QtGui.QColor(image.pixel(x, y)).name()) color_dict[y] = line line = [] return color_dict @staticmethod def cursors_x(pixmap): """ Parameters ---------- pixmap: QPixmap object of PlotGraphics object Returns ------- list of cursors line from pixmap """ image = pixmap.toImage() cursors = [] possible_cursor = None for x in range(image.width()): count = 0 for y in range(image.height()): color = QtGui.QColor(image.pixel(x, y)) # Count straight vertical line pixels with COLOR_CURSOR color if color.name() == Pixmap.COLOR_CURSOR: count += 1 if count >= (image.height() - 1) / 2 - 1: # For Y shortcut tests, one cursor is a discontinuous line cursors.append(x) return cursors @staticmethod def search_signal_extremes_by_ax(pixmap, signal_color, ax: str): """ Return column where signal start and end If ax = Y: Return a list with extremes of signal by 0Y axes If ax = X: Return a list with extremes of signal by 0X axes """ if not isinstance(signal_color, str): if hasattr(signal_color, "color"): signal_color = signal_color.color.name() elif hasattr(signal_color, "name"): signal_color = signal_color.name() else: raise SyntaxError(f"Object {signal_color} doesn't have the attribute <> or <>") from_to = [] image = pixmap.toImage() if ax in ("x", "X"): for x in range(image.width()): for y in range(image.height()): if image.pixelColor(x, y).name() == signal_color: from_to.append(x) break if from_to: break if not from_to: return for x in range(image.width() - 1, from_to[0], -1): for y in range(image.height()): if image.pixelColor(x, y).name() == signal_color: from_to.append(x) break if len(from_to) == 2: break return from_to elif ax in ("y", "Y"): for y in range(image.height()): for x in range(image.width()): if image.pixelColor(x, y).name() == signal_color: from_to.append(y) break if from_to: break if not from_to: return for y in range(image.height() - 1, from_to[0], -1): for x in range(image.width()): if image.pixelColor(x, y).name() == signal_color: from_to.append(y) break if len(from_to) == 2: break return from_to @staticmethod def search_y_of_signal_in_column(pixmap_column, signal_color): """ Return the first pixel line number where the signal color was found. """ image = pixmap_column.toImage() if image.width() > 1: raise TypeError(f"<<{image.width()} != 1>>. Please check pixmap width!") if not isinstance(signal_color, str): if hasattr(signal_color, "color"): signal_color = signal_color.color.name() elif hasattr(signal_color, "name"): signal_color = signal_color.name() else: raise SyntaxError(f"Object {signal_color} doesn't have the attribute <> or <>") line = None for y in range(image.height()): if QtGui.QColor(image.pixel(0, y)).name() == signal_color: line = y break return line class OpenFileContextManager: """ Generic class for opening a file using context manager. Methods: __enter__: return opened file object. __exit__: close file object. If exc_type, exc_val, exc_tb, raise exception. """ def __init__(self, file_path: str | pathlib.Path): """ Parameters ---------- file_path: file path as str or pathlib.Path object """ self.file = None if isinstance(file_path, str): self._file_path = pathlib.Path(file_path) else: self._file_path = file_path assert self._file_path.exists(), "Provided file does not exist" def __enter__(self): pass def __exit__(self, exc_type, exc_val, exc_tb): self.file.close() for exc in (exc_type, exc_val, exc_tb): if exc is not None: print(exc) class OpenMDF(OpenFileContextManager): """ Open MDF file using context manager. """ def __enter__(self): self.file = mdf.MDF(self._file_path, process_bus_logging=("process_bus_logging", True)) return self.file class OpenHDF5(OpenFileContextManager): """ Open HDF5 file using context manager. """ def __enter__(self): self.file = HDF5(self._file_path) return self.file class DBC: class BO: def __init__(self, lines: Iterable[str]): for line in lines: if line.startswith("BO_ "): self.data = line def __repr__(self): return self.data @property def name(self) -> str: if self.data: return self.data.split()[2].strip(":") @property def id(self) -> str: if self.data: return self.data.split()[1] @property def data_length(self) -> int: if self.data: return int(self.data.split()[3]) class SG: def __init__(self, name: str, lines: Iterable[str]): self.name = name self.data = None for line in lines: if "SG_ " in line and name in line: self.data = line.split("SG_ ")[1] def __repr__(self): return self.data @property def unit(self) -> str: return self.data.split('"')[1] # middle value, ex: "blah blah "unit" blah @property def bit_count(self) -> int: return int(self.data.split("|")[1].split("@")[0]) # is complicated this CAN :) @property def conversion_a(self) -> float: return float(self.data.split("(")[1].split(")")[0].split(",")[0]) @property def conversion_b(self) -> float: return float(self.data.split("(")[1].split(")")[0].split(",")[1]) asammdf-8.5.1/test/asammdf/gui/test_util.py000066400000000000000000000142251502633300400206760ustar00rootroot00000000000000import inspect import unittest from asammdf.gui.utils import generate_python_function from test.asammdf.gui.resources.functions import ( Function1, gray2dec, maximum, rpm_to_rad_per_second, ) class TestUtils(unittest.TestCase): def test_GeneratePythonFunction_InvalidArgs(self): """ Events: - Call function 'generate_python_function' with invalid args type. Evaluate: - Evaluate return type is tuple - Evaluate func is always None. (position 0) - Evaluate trace. (position 1) """ # 'definition' argument is not string. with self.subTest(f"{self.id()}_0"): trace = "The function definition must be a string" # Event result = generate_python_function(None, None) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertEqual(trace, result[1]) # 'in_globals' argument is not dict. with self.subTest(f"{self.id()}_1"): trace = "'in_globals' must be a dict" # Event result = generate_python_function(self.id(), True) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertEqual(trace, result[1]) def test_GeneratePythonFunction_InconsistentArgs(self): """ Events: - Call function 'generate_python_function' with valid args type but inconsistent content. Evaluate: - Evaluate return type is tuple - Evaluate func is always None. (position 0) - Evaluate trace. (position 1) """ # Empty definition with self.subTest(f"{self.id()}_0"): trace = "The function definition must not be empty" # Event result = generate_python_function("", None) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertEqual(trace, result[1]) # Function Name absent with self.subTest(f"{self.id()}_1"): trace = "The function name must not be empty" # Event result = generate_python_function("\t", None) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertEqual(trace, result[1]) def test_GeneratePythonFunction_Exception(self): """ Events: - Call function 'generate_python_function' with syntax errors in definition. Evaluate: - Evaluate return type is tuple - Evaluate func is always None. (position 0) - Evaluate trace. (position 1) """ # Event result = generate_python_function(r"def Function1(t=0):\n return true", None) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertIn( "SyntaxError: unexpected character after line continuation character", result[1], ) def test_GeneratePythonFunction_Args(self): """ Events: - Call function 'generate_python_function' without argument 't=0' in definition or on wrong position Evaluate: - Evaluate return type is tuple - Evaluate func is always None. (position 0) - Evaluate trace. (position 1) """ with self.subTest(f"{self.id()}_0"): trace = 'The last function argument must be "t=0"' # Event result = generate_python_function("def Function1():\n\treturn 0", None) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertIn(trace, result[1]) with self.subTest(f"{self.id()}_1"): trace = 'The last function argument must be "t=0"' # Event result = generate_python_function("def Function1(t=0, x=0):\n\treturn 0", None) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertIn(trace, result[1]) with self.subTest(f"{self.id()}_2"): trace = 'The last function argument must be "t=0"' # Event result = generate_python_function("def Function1(t=1):\n\treturn 0", None) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertIn(trace, result[1]) with self.subTest(f"{self.id()}_3"): trace = 'All the arguments must have default values. The argument "channel" has no default value.' # Event result = generate_python_function("def Function1(channel, t=0):\n\treturn 0", None) # Evaluate self.assertIsInstance(result, tuple) self.assertEqual(None, result[0]) self.assertIn(trace, result[1]) def test_GeneratePythonFunction_Valid(self): """ Event: - Call function 'generate_python_function' with valid definition. Evaluate: - Evaluate return type is tuple - Evaluate func is always None. (position 0) - Evaluate trace. (position 1) """ with self.subTest(f"{self.id()}_0"): # Event result = generate_python_function("def Function1(t=0):\n\treturn 0", None) # Evaluate self.assertIsInstance(result, tuple) self.assertTrue(callable(result[0])) self.assertEqual(None, result[1]) for f in ( Function1, gray2dec, maximum, rpm_to_rad_per_second, ): with self.subTest(f"{self.id}_{f.__name__}"): source = inspect.getsource(f) # Event result = generate_python_function(source, None) # Evaluate self.assertIsInstance(result, tuple) self.assertTrue(callable(result[0])) self.assertEqual(None, result[1]) asammdf-8.5.1/test/asammdf/gui/widgets/000077500000000000000000000000001502633300400177525ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/000077500000000000000000000000001502633300400217505ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/Shortcuts.json000066400000000000000000000072441502633300400246500ustar00rootroot00000000000000{ "FileWidget": [ { "search": "Ctrl+F", "toggle_full_screen": "F11", "tile_sub_windows_vertically": "Shift+V", "tile_sub_windows_horizontally": "Shift+H", "cascade_sub_windows": "Shift+C", "tile_sub_windows_in_a_grid": "Shift+T", "toggle_sub_windows_frames": "Shift+Alt+F", "toggle_channel_view": "Shift+L", "set_line_style": "." } ], "TableView": [ { "delete_items": "Delete", "set_color_ranges": "Ctrl+R", "copy_display_properties": "Ctrl+Shift+C", "paste_display_properties": "Ctrl+Shift+V" } ], "MainWindow": [ { "toggle_full-screen": "F11", "create_plot_window": "F2", "create_numeric_window": "F3", "create_tabular_window": "F4" } ], "Numeric": [ { "bin": "Ctrl+B", "hex": "Ctrl+H", "physical": "Ctrl+P", "ascii": "Ctrl+T", "move_cursor_left_1x": "Left", "move_cursor_right_1x": "Right", "save_active_subplot_channels": "Ctrl+S", "increase_font": "Ctrl+[", "decrease_font": "Ctrl+]", "go_to_timestamp": "Shift+G" } ], "Plot": [ { "statistics": "M", "focused_mode": "2", "bin": "Ctrl+B", "hex": "Ctrl+H", "physical": "Ctrl+P", "ascii": "Ctrl+T", "raw_samples": "Alt+R", "scaled_samples": "Alt+S", "insert_bookmark": "Ctrl+I", "toggle_bookmarks": "Alt+I", "edit_y_axis_scaling": "Ctrl+G", "range": "R", "set_color": "C", "copy_channel_structure": "Ctrl+C", "copy_display_properties": "Ctrl+Shift+C", "paste_channel_structure": "Ctrl+V", "paste_display_properties": "Ctrl+Shift+V", "increase_font": "Ctrl+[", "decrease_font": "Ctrl+]", "undo_zoom": "Backspace", "redo_zoom": "Shift+Backspace", "x_default_zoom": "Shift+W" } ], "PlotGraphics": [ { "toggle_range": "Y", "zoom_to_range": "X", "fit_all": "F", "fit_selected": "Shift+F", "grid": "G", "go_to_timestamp": "Shift+G", "x_zoom_in": "I", "x_zoom_out": "O", "y_zoom_in": "Shift+I", "y_zoom_out": "Shift+O", "range": "R", "save_active_subplot_channels": "Ctrl+S", "stack_all": "S", "stack_selected": "Shift+S", "move_cursor_left_1x": "Left", "move_cursor_right_1x": "Right", "move_cursor_left_20x": "Ctrl+Left", "move_cursor_right_20x": "Ctrl+Right", "shift_channels_left": "Shift+Left", "shift_channels_right": "Shift+Right", "shift_channels_up_1x": "Shift+Up", "shift_channels_down_1x": "Shift+Down", "shift_channels_up_10x": "Shift+PgUp", "shift_channels_down_10x": "Shift+PgDown", "honeywell": "H", "home": "W", "insert_computation": "Insert" } ], "DataTableView": [ { "set_color_range": "Ctrl+R" } ], "Tabular": [ { "bin": "Ctrl+B", "hex": "Ctrl+H", "physical": "Ctrl+P", "save_active_subplot_channels": "Ctrl+S", "increase_font": "Ctrl+[", "decrease_font": "Ctrl+]" } ], "DataFrameViewer": [ { "copy": "Ctrl+C" } ], "TreeWidget": [ { "toggle_check_state": "Space" } ], "ChannelsTreeWidget": [ { "delete_items": "Delete", "add_pattern_based_group": "Ctrl+Insert", "add_channel_group": "Shift+Insert", "toggle_check_state": "Space", "set_color": "C", "copy_channel_structure": "Ctrl+C", "paste_channel_structure": "Ctrl+V", "copy_names": "Ctrl+N", "set_color_range": "Ctrl+R", "copy_display_properties": "Ctrl+Shift+C", "paste_display_properties": "Ctrl+Shift+V" } ] }asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/__init__.py000066400000000000000000000000001502633300400240470ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/test_FileWidget_Shortcuts.py000066400000000000000000000434361502633300400274740ustar00rootroot00000000000000#!/usr/bin/env python\ from math import ceil, sqrt import pathlib from random import randint from unittest import mock from PySide6.QtCore import QRect from PySide6.QtGui import QKeySequence, Qt from PySide6.QtTest import QTest from PySide6.QtWidgets import QTreeWidgetItemIterator from test.asammdf.gui.test_base import OpenMDF, Pixmap from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget class TestFileWidgetShortcuts(TestFileWidget): """ Test for F11 shortcut was moved to Main Window tests """ def setUp(self): """ Events: Open measurement file "ASAP2_Demo_V171.mf4" as FileWidget Evaluate: - Evaluate that widget didn't have active sub-windows """ super().setUp() # Open measurement file self.measurement_file = str(pathlib.Path(TestFileWidget.resource, "ASAP2_Demo_V171.mf4")) self.setUpFileWidget(measurement_file=self.measurement_file, default=True) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) # Get shortcuts self.assertIsNotNone(self.load_shortcuts_from_json_file(self.widget)) def test_search_and_select_channels_shortcut(self): """ Test Scope: Check if advanced search widget is called by shortcut Ctrl+F and founded items are added to plot. Events: - Press "Ctrl+F" -> search signals -> Add channels -> 'New plot window' -> Ok - Press "Ctrl+F" -> search pattern-based signals -> Apply -> 'New pattern based plot window' -> Ok - Press "Ctrl+F" -> search signals -> Add channels -> 'Existing pattern based window' -> Ok Evaluate: - Evaluate that widget isn't full-screen at start - Evaluate that widget was switched to full-screen mode after key F11 was pressed """ # Setup matrix_items = {} u_word_items = {} matrix_pattern = "matrix" u_word_pattern = "uWord" # Search signals with specific patter with OpenMDF(self.measurement_file) as mdf: for ch in mdf.iter_channels(): if matrix_pattern.upper() in ch.name.upper(): matrix_items[(ch.group_index, ch.channel_index)] = ch.name if u_word_pattern.upper() in ch.name.upper(): u_word_items[(ch.group_index, ch.channel_index)] = ch.name sw_count = 0 # Sub-windows # Mock for Advanced search and windowSelectionDialog objects with ( mock.patch("asammdf.gui.widgets.file.AdvancedSearch") as mo_AdvancedSearch, mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mo_WindowSelectionDialog, ): with self.subTest("test_search_shortcut_new_window"): mo_AdvancedSearch.return_value.result = matrix_items mo_AdvancedSearch.return_value.pattern_window = False mo_WindowSelectionDialog.return_value.dialog.return_value = 1 # Ok mo_WindowSelectionDialog.return_value.selected_type.return_value = "New plot window" mo_WindowSelectionDialog.return_value.disable_new_channels.return_value = False # Press Ctrl+F QTest.keySequence(self.widget, QKeySequence(self.shortcuts["search"])) self.processEvents(0.01) mo_AdvancedSearch.assert_called() mo_WindowSelectionDialog.assert_called() self.assertEqual(len(self.widget.mdi_area.subWindowList()), sw_count + 1) channel_selection = self.widget.mdi_area.subWindowList()[sw_count].widget().channel_selection sw_count += 1 # Evaluate plot widget self.assertEqual(len(matrix_items), channel_selection.topLevelItemCount()) iterator = QTreeWidgetItemIterator(channel_selection) while item := iterator.value(): self.assertIn(item.name, matrix_items.values()) iterator += 1 with self.subTest("test_search_shortcut_pattern_window"): # Setup mo_AdvancedSearch.return_value.pattern_window = True mo_AdvancedSearch.return_value.result = { "case_sensitive": False, "filter_type": "Unspecified", "filter_value": 0.0, "integer_format": "phys", "match_type": "Wildcard", "name": matrix_pattern.upper(), "pattern": f"*{matrix_pattern}*", "ranges": [], "raw": False, } mo_WindowSelectionDialog.return_value.dialog.return_value = 1 # Ok mo_WindowSelectionDialog.return_value.selected_type.return_value = "New pattern based plot window" mo_WindowSelectionDialog.return_value.disable_new_channels.return_value = False # Event # Press Ctrl+F QTest.keySequence(self.widget, QKeySequence(self.shortcuts["search"])) self.processEvents(0.01) mo_AdvancedSearch.assert_called() mo_WindowSelectionDialog.assert_called() self.assertEqual(len(self.widget.mdi_area.subWindowList()), sw_count + 1) self.assertEqual(self.widget.mdi_area.subWindowList()[sw_count].windowTitle(), f"*{matrix_pattern}*") channel_selection = self.widget.mdi_area.subWindowList()[sw_count].widget().channel_selection # Evaluate plot widget self.assertEqual(len(matrix_items), channel_selection.topLevelItemCount()) iterator = QTreeWidgetItemIterator(channel_selection) while item := iterator.value(): self.assertIn(item.name, matrix_items.values()) iterator += 1 # New setup mo_WindowSelectionDialog.return_value.dialog.return_value = 1 # Ok mo_WindowSelectionDialog.return_value.selected_type.return_value = f"*{matrix_pattern}*" mo_WindowSelectionDialog.return_value.disable_new_channels.return_value = False mo_AdvancedSearch.return_value.result = u_word_items mo_AdvancedSearch.return_value.pattern_window = False # Press Ctrl+F QTest.keySequence(self.widget, QKeySequence(self.shortcuts["search"])) self.processEvents(0.01) mo_AdvancedSearch.assert_called() mo_WindowSelectionDialog.assert_called() self.assertEqual(len(self.widget.mdi_area.subWindowList()), sw_count + 1) final_items = {**matrix_items, **u_word_items} channel_selection = self.widget.mdi_area.subWindowList()[sw_count].widget().channel_selection # Evaluate plot widget self.assertEqual(len(final_items), channel_selection.topLevelItemCount()) iterator = QTreeWidgetItemIterator(channel_selection) while item := iterator.value(): self.assertIn(item.name, final_items.values()) iterator += 1 def test_cascade__grid__vertically__horizontally_sub_windows_shortcuts(self): """ Test Scope: - To check if sub-windows layout can be properly changed to vertically, horizontally and grid one using Shift V, Shift H and Shift_T shortcuts. Events: - Add random number of sub-windows, between 3 and 30. - Press "Shift+V". - Press "Shift+H". - Press "Shift+T". Evaluate: - For vertical layout: > each sub-window starts from the new x coordinate; > each sub-window starts from the same y coordinate; > each sub-window has the same length and width. - For horizontal layout: > each sub-window starts from the same x coordinate; > each sub-window starts from the new y coordinate; > each sub-window has the same length and width. - For grid layout: > each sub-window starts from ceil value of square root number of sub-windows for x coordinate; > each sub-window starts from round value of square root number of sub-windows for y coordinate; > there are only two sizes for sub-windows widths, one of sizes is step for sub-window starts by x-axis; > there are only two or three sizes for sub-windows heights, one of sizes is step for sub-window starts by y-axis; - For cascade layout: > each sub-window starts from the new x coordinate; > all sub-windows is grouped in columns in order to fit all sub-windows top bar in mdi area; > all sub-windows must have the same width; > there are only two or three sizes for sub-windows heights. """ def g(list_: list): x_ = {widget.geometry().x() for widget in list_} y_ = {widget.geometry().y() for widget in list_} w_ = {widget.geometry().width() for widget in list_} h_ = {widget.geometry().height() for widget in list_} return x_, y_, w_, h_ def get_step(set_: set): list_ = list(set_) list_.sort() return list_[1] - list_[0] # Setup max_square = 5 sub_windows = randint(5, max_square * (1 + max_square)) for _ in range(sub_windows): self.create_window(window_type="Plot") self.processEvents(0.01) # Press Shift+V -|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|- QTest.keySequence(self.widget, QKeySequence(self.shortcuts["tile_sub_windows_vertically"])) self.processEvents(0.1) x, y, width, height = g(self.widget.mdi_area.subWindowList()) # Evaluate self.assertEqual(len(x), sub_windows) self.assertEqual(len(y), 1) self.assertEqual(len(width), 1) self.assertEqual(len(height), 1) # Press Shift+H -|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|- QTest.keySequence(self.widget, QKeySequence(self.shortcuts["tile_sub_windows_horizontally"])) x, y, width, height = g(self.widget.mdi_area.subWindowList()) # Evaluate self.assertEqual(len(x), 1) self.assertEqual(len(y), sub_windows) self.assertEqual(len(width), 1) self.assertEqual(len(height), 1) # Press Shift+T -|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|- QTest.keySequence(self.widget, QKeySequence(self.shortcuts["tile_sub_windows_in_a_grid"])) self.processEvents() x, y, width, height = g(self.widget.mdi_area.subWindowList()) # Evaluate self.assertEqual(len(x), ceil(sqrt(sub_windows))) self.assertEqual(len(y), round(sqrt(sub_windows))) self.assertEqual(len(width), 2) self.assertIn(get_step(x), width) self.assertIn(len(height), range(2, 5)) self.assertIn(get_step(y), height) # Press Shift+C -|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|- QTest.keySequence(self.widget, QKeySequence(self.shortcuts["cascade_sub_windows"])) self.processEvents(0.01) x, y, width, height = g(self.widget.mdi_area.subWindowList()) # Evaluate self.assertEqual(len(x), sub_windows) self.assertGreaterEqual(len(y), ceil(sub_windows / 6)) self.assertEqual(len(width), 1) self.assertIn(len(height), range(1, 4)) def test_toggle_sub_windows_frame_shortcut(self): """ Test Scope: Check if sub-windows frame was toggled after pressing keys "Shift+Alt+F" Events: - Press twice "Shift+Alt+F" Evaluate: - Evaluate that by default sub-windows are not frameless - Evaluate that sub-windows is frameless, and widget size was reduced after pressing "Shift+Alt+F" for the first time - Evaluate that sub-windows is not frameless, and widget size was increased after pressing "Shift+Alt+F" second time """ # Setup self.create_window(window_type="Plot") self.processEvents(0.01) # Evaluate self.assertFalse(self.widget._frameless_windows) # Setup previous_size = self.widget.mdi_area.subWindowList()[0].widget().frameSize() # Press Shift+Alt+F first time QTest.keySequence(self.widget, QKeySequence(self.shortcuts["toggle_sub_windows_frames"])) # Evaluate self.assertTrue(self.widget._frameless_windows) self.assertLess(previous_size.width(), self.widget.mdi_area.subWindowList()[0].widget().frameSize().width()) self.assertLess(previous_size.height(), self.widget.mdi_area.subWindowList()[0].widget().frameSize().height()) # Setup previous_size = self.widget.mdi_area.subWindowList()[0].widget().frameSize() # Press Shift+Alt+F second time QTest.keySequence(self.widget, QKeySequence(self.shortcuts["toggle_sub_windows_frames"])) # Evaluate self.assertFalse(self.widget._frameless_windows) self.assertGreater(previous_size.width(), self.widget.mdi_area.subWindowList()[0].widget().frameSize().width()) self.assertGreater( previous_size.height(), self.widget.mdi_area.subWindowList()[0].widget().frameSize().height() ) def test_toggle_channel_list_shortcut(self): """ Test Scope: Check if by pressing the combination of keys "Shift+L", visibility of a channel list is changed Events: - Press twice combination "Shift+L". Evaluate: - Evaluate that channel list is visible by default, and its width is greater than 0. - Evaluate that channel list is hidden and its width is equal to 0 after pressing first time .Shift+L. - Evaluate that channel list is visible and its width is greater than 0 after pressing second time Shift+L. """ # Setup self.processEvents() # Evaluate self.assertTrue(self.widget.channel_view.isVisible()) self.assertGreater(self.widget.splitter.sizes()[0], 0) # Press "Shift+L" first time QTest.keySequence(self.widget, QKeySequence(self.shortcuts["toggle_channel_view"])) self.processEvents() # Evaluate self.assertFalse(self.widget.channel_view.isVisible()) self.assertEqual(self.widget.splitter.sizes()[0], 0) # Press "Shift+L" second time QTest.keySequence(self.widget, QKeySequence(self.shortcuts["toggle_channel_view"])) self.processEvents() # Evaluate self.assertTrue(self.widget.channel_view.isVisible()) self.assertGreater(self.widget.splitter.sizes()[0], 0) def test_toggle_dots_shortcut(self): """ Test Scope: Check if dots appear on plot after pressing key Period Events: - Press key "Period" <<.>> twice Evaluate: - Evaluate number of background colors, it must be greater when signal is without dots """ # Setup self.create_window("Plot") self.add_channels(channels_list=[35]) plot = self.widget.mdi_area.subWindowList()[0].widget() # Remove bookmarks if plot is with bookmarks if not plot.bookmark_btn.isFlat(): QTest.mouseClick(plot.bookmark_btn, Qt.MouseButton.LeftButton) if not plot.plot.with_dots: plot.plot.set_dots(True) # Remove grid if plot is with grid if not plot.hide_axes_btn.isFlat(): QTest.mouseClick(plot.hide_axes_btn, Qt.MouseButton.LeftButton) self.processEvents(0.1) # Displayed signal sig = plot.plot.signals[0] # Coordinates for viewbox, second dot in the center of visual box x_step = (sig.timestamps[1] - sig.timestamps[0]) / 10 y_step = (sig.samples[1] - sig.samples[0]) / 10 x, y = sig.timestamps[1] - x_step, sig.samples[1] - y_step w, h = sig.timestamps[1] + x_step, sig.samples[1] + y_step # Set X and Y ranges for viewbox plot.plot.viewbox.setXRange(x, w, padding=0) plot.plot.viewbox.setYRange(y, h, padding=0) self.processEvents(0.1) # Get rect from the center of graphical plot rect = QRect(int(plot.plot.width() / 2) - 4, int(plot.plot.height() / 2) - 4, 8, 9) # Color map of selected rect pm_with_dots = Pixmap.color_map(plot.plot.grab(rect)) # Black coverage with_dots_black_coverage = 0 for cov in pm_with_dots.values(): with_dots_black_coverage += cov.count(Pixmap.COLOR_BACKGROUND) # Event QTest.keySequence(self.widget, QKeySequence(self.shortcuts["set_line_style"])) self.processEvents(0.1) # Gat new pixmap pm_without_dots = Pixmap.color_map(plot.plot.grab(rect)) # New black coverage without_dots_black_coverage = 0 for cov in pm_without_dots.values(): without_dots_black_coverage += cov.count(Pixmap.COLOR_BACKGROUND) # Evaluate self.assertGreater(without_dots_black_coverage, with_dots_black_coverage) # Event QTest.keySequence(self.widget, QKeySequence(self.shortcuts["set_line_style"])) self.processEvents(0.1) # Gat new pixmap pm_with_dots = Pixmap.color_map(plot.plot.grab(rect)) # New black coverage new_with_dots_black_coverage = 0 for cov in pm_with_dots.values(): new_with_dots_black_coverage += cov.count(Pixmap.COLOR_BACKGROUND) # Evaluate self.assertEqual(new_with_dots_black_coverage, with_dots_black_coverage) asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/test_MainWindow_Shortcuts.py000066400000000000000000000210031502633300400275070ustar00rootroot00000000000000#!/usr/bin/env python from pathlib import Path from unittest import mock from PySide6.QtGui import QKeySequence from PySide6.QtTest import QTest from PySide6.QtWidgets import QApplication, QTreeWidgetItemIterator from asammdf.gui.widgets import numeric, plot, tabular from asammdf.gui.widgets.file import FileWidget from asammdf.gui.widgets.main import MainWindow from test.asammdf.gui.test_base import TestBase from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget class TestShortcuts(TestBase): def setUp(self): """ Events: Open Main window Returns ------- """ super().setUp() self.measurement_file = str(Path(TestBase.resource, "ASAP2_Demo_V171.mf4")) self.mw = MainWindow(files=(self.measurement_file,)) self.mw.showNormal() self.processEvents(1) # get shortcuts self.shortcuts = TestFileWidget.load_shortcuts_from_json_file(self, self.mw) self.assertIsNotNone(self.shortcuts) def destroyMW(self): if self.mw: self.mw.close() self.mw.deleteLater() def tearDown(self): if self.mw: self.destroyMW() def test_fullscreen_shortcut(self): """ Test scope: Ensure that F11 shortcut will toggle full-screen mode for opened file widget, and after closing the main window, file widget will be destroyed. Events: - Open valid measurement file - Press key `F11` - Close MainWindow Evaluate: - Evaluate that file widget isn't in full-screen mode by default. - Evaluate that after pressing key F11, file widget is in full-screen mode - Evaluate that after closing the main window, there are no more opened widgets. :return: """ # Setup self.processEvents(0.01) # file widget file_widget = self.mw.files.widget(0) # Evaluate self.assertFalse(file_widget.isFullScreen()) # Event QTest.keySequence(self.mw, QKeySequence(self.shortcuts["toggle_full-screen"])) # Press F11 self.processEvents() # Evaluate self.assertTrue(file_widget.isFullScreen()) # Close MainWindow self.destroyMW() self.processEvents() # Evaluate for w in QApplication.topLevelWidgets(): if isinstance(w, FileWidget): self.assertFalse(w.isVisible()) def test_create_plot__numeric__tabular_sub_window_shortcut(self): """ Test scope: Ensure that Plot, Numeric and Tabular sub-windows can be created by pressing keys F2, F3 and F4 Events: - Open valid file - Press key F2. - Press key F3. - Press key F4. - Search all "*matrix*" channels and set all of them checked - Press key F2. - Press key F3. - Press key F4. Evaluate: - Evaluate that after pressing key F2, there is one new Plot type sub-window. - Evaluate that after pressing key F3, there is one new Numeric type sub-window. - Evaluate that after pressing key F4, there is one new Tabular type sub-window. - Evaluate that after pressing key F2, there is one new Plot type sub-window with checked channels. - Evaluate that after pressing key F3, there is one new Numeric type sub-window with checked channels. - Evaluate that after pressing key F4, there is one new Tabular type sub-window with checked channels. :return: """ # Setup windows_count = 0 # file widget file_widget = self.mw.files.widget(0) with self.subTest("test_shortcut_F2_without_selected_channels"): # Event QTest.keySequence(self.mw, QKeySequence(self.shortcuts["create_plot_window"])) # Press F2 self.processEvents() # Evaluate self.assertEqual(len(file_widget.mdi_area.subWindowList()), windows_count + 1) self.assertTrue(isinstance(file_widget.mdi_area.subWindowList()[windows_count].widget(), plot.Plot)) windows_count += 1 with self.subTest("test_shortcut_F3_without_selected_channels"): # Event QTest.keySequence(self.mw, QKeySequence(self.shortcuts["create_numeric_window"])) # Press F3 self.processEvents() # Evaluate self.assertEqual(len(file_widget.mdi_area.subWindowList()), windows_count + 1) self.assertTrue(isinstance(file_widget.mdi_area.subWindowList()[windows_count].widget(), numeric.Numeric)) windows_count += 1 with self.subTest("test_shortcut_F4_without_selected_channels"): # Event QTest.keySequence(self.mw, QKeySequence(self.shortcuts["create_tabular_window"])) # Press F4 self.processEvents() # Evaluate self.assertEqual(len(file_widget.mdi_area.subWindowList()), windows_count + 1) self.assertTrue(isinstance(file_widget.mdi_area.subWindowList()[windows_count].widget(), tabular.Tabular)) windows_count += 1 # Setup matrix_items = {} pattern = "matrix" # Search signals with specific patter iterator = QTreeWidgetItemIterator(file_widget.channels_tree) while item := iterator.value(): if pattern.upper() in item.name.upper(): matrix_items[item.entry] = item.name iterator += 1 sw_count = 0 # Sub-windows # Mock for Advanced search and windowSelectionDialog objects with mock.patch("asammdf.gui.widgets.file.AdvancedSearch") as mo_AdvancedSearch: mo_AdvancedSearch.return_value.result = matrix_items mo_AdvancedSearch.return_value.pattern_window = False mo_AdvancedSearch.return_value.add_window_request = False # Check some channels QTest.keySequence(self.mw, QKeySequence("Ctrl+F")) # Press Ctrl+F self.processEvents(0.01) # Evaluate mo_AdvancedSearch.assert_called() with self.subTest("test_shortcut_F2_with_selected_channels"): # Event QTest.keySequence(self.mw, QKeySequence(self.shortcuts["create_plot_window"])) # Press F2 self.processEvents() # Evaluate self.assertEqual(len(file_widget.mdi_area.subWindowList()), windows_count + 1) self.assertTrue(isinstance(file_widget.mdi_area.subWindowList()[windows_count].widget(), plot.Plot)) cs = file_widget.mdi_area.subWindowList()[windows_count].widget().channel_selection # Evaluate plot widget self.assertEqual(len(matrix_items), cs.topLevelItemCount()) iterator = QTreeWidgetItemIterator(cs) while item := iterator.value(): self.assertIn(item.name, matrix_items.values()) iterator += 1 windows_count += 1 with self.subTest("test_shortcut_F3_with_selected_channels"): # Event QTest.keySequence(self.mw, QKeySequence(self.shortcuts["create_numeric_window"])) # Press F3 self.processEvents() # Evaluate self.assertEqual(len(file_widget.mdi_area.subWindowList()), windows_count + 1) self.assertTrue(isinstance(file_widget.mdi_area.subWindowList()[windows_count].widget(), numeric.Numeric)) signals = file_widget.mdi_area.subWindowList()[windows_count].widget().channels.backend.signals self.assertEqual(len(matrix_items), len(signals)) for sig in signals: self.assertIn(sig.name, matrix_items.values()) windows_count += 1 with self.subTest("test_shortcut_F4_with_selected_channels"): # Event QTest.keySequence(self.mw, QKeySequence(self.shortcuts["create_tabular_window"])) # Press F4 self.processEvents() # Evaluate self.assertEqual(len(file_widget.mdi_area.subWindowList()), windows_count + 1) self.assertTrue(isinstance(file_widget.mdi_area.subWindowList()[windows_count].widget(), tabular.Tabular)) signals = file_widget.mdi_area.subWindowList()[windows_count].widget().tree # channels columns count - timestamp column self.assertEqual(len(matrix_items), signals.columnHeader.model().columnCount() - 1) for key in matrix_items.values(): self.assertIn(key, signals.pgdf.df.keys()) asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/test_NumericWidget_Shortcuts.py000066400000000000000000000413241502633300400302110ustar00rootroot00000000000000#!/usr/bin/env python\ import json import os import pathlib from unittest import mock from PySide6.QtGui import QColor, QKeySequence from PySide6.QtTest import QTest from asammdf import mdf from asammdf.gui.utils import copy_ranges from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget class TestTableViewShortcuts(TestFileWidget): def setUp(self): """ Events: - Open measurement file. - Create a Numeric window. Evaluate: - Evaluate that there is one active sub-window created. Returns ------- """ super().setUp() # Open measurement file measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Open measurement file self.setUpFileWidget(measurement_file=measurement_file, default=True) self.create_window(window_type="Numeric") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) self.numeric = self.widget.mdi_area.subWindowList()[0].widget() self.table_view = self.numeric.channels.dataView # get shortcuts self.assertIsNotNone(self.load_shortcuts_from_json_file(self.table_view)) def test_delete_shortcut(self): """ Test Scope: - Ensure that key Delete will remove selected channels Events: - Add some channels to Numeric widget. - Select first item and press key Delete. - Select all items and press key delete. Evaluate: - Evaluate that there are all items added to a numeric windget - Evaluate that first row is removed from a list after it became selected and key Delete is pressed - Evaluate that all rows after they became selected are removed by pressing key delete """ # Setup self.processEvents() # Add one channel to the widget self.assertIsNotNone(self.add_channels([10, 11, 12, 13]), self.numeric) self.processEvents() channel_count = len(self.channels) # Events # Select first row self.table_view.selectRow(0) self.processEvents() # Press key Delete QTest.keySequence(self.table_view, QKeySequence(self.shortcuts["delete_items"])) # Evaluate self.assertEqual(len(self.table_view.backend.signals), channel_count - 1) # Events # select all items QTest.keySequence(self.table_view, QKeySequence("Ctrl+A")) # Press key Delete QTest.keySequence(self.table_view, QKeySequence(self.shortcuts["delete_items"])) # Evaluate self.assertEqual(len(self.table_view.backend.signals), 0) def test_set_color_range_shortcut(self): """ Test Scope: Check if color range is triggered after pressing key Ctrl+R. Events: - Display a few signals on numeric widget. - Select first signal. - Press "Ctrl+R" -> ranges from 0 to 40% of y value and colors green and red -> apply. Evaluate: - Evaluate RangeEditor object was called - Evaluate that selected item has color range variable, and its value is equal to the expected value """ # Setup value1 = 0.0 value2 = 100 # Add items to the widget self.assertIsNotNone(self.add_channels([10, 11, 12, 13]), self.numeric) self.processEvents() green = QColor.fromRgbF(0.000000, 1.000000, 0.000000, 1.000000) red = QColor.fromRgbF(1.000000, 0.000000, 0.000000, 1.000000) expected_value = [ { "background_color": green, "font_color": red, "op1": "<=", "op2": "<=", "value1": value1, "value2": value2, } ] # Events # Select first row self.table_view.selectRow(0) self.processEvents() with mock.patch("asammdf.gui.widgets.numeric.RangeEditor") as mo_RangeEditor: mo_RangeEditor.return_value.result = expected_value mo_RangeEditor.return_value.pressed_button = "apply" # Press "Alt+R" QTest.keySequence(self.table_view, QKeySequence(self.shortcuts["set_color_ranges"])) # Evaluate mo_RangeEditor.assert_called() row_0 = True for value in self.table_view.ranges.values(): if row_0 is True: # Evaluate range for first row self.assertDictEqual(value[0], expected_value[0]) row_0 = False else: self.assertListEqual(value, []) def test_copy_display_properties_shortcut(self): """ Test Scope: - Ensure that key "Ctrl+Shift+C" can copy display properties of selected item Events: - Open Numeric widget with one channel - Select this channel - Press Ctrl+Shift+C Evaluate: - Evaluate that there is added one item to widget - Evaluate that in clipboard is display properties of selected item """ # Setup # Add item to the widget self.assertIsNotNone(self.add_channels(["ASAM_[14].M.MATRIX_DIM_16.UBYTE.IDENTICAL"])) channel = self.table_view.backend.signals[0] expected_ch_info = { "format": channel.format, "ranges": copy_ranges(self.table_view.ranges[channel.entry]), "type": "channel", "color": channel.color.name(), "precision": self.table_view.model().float_precision, "ylink": channel.signal.y_link, "individual_axis": channel.signal.individual_axis, "y_range": channel.y_range, "origin_uuid": channel.origin_uuid, } # expected_ch_info = json.dumps(expected_ch_info) # Events with mock.patch("asammdf.gui.widgets.numeric.QtWidgets.QApplication.instance") as mo_instance: # Click on a first channel self.table_view.selectRow(0) # Press Ctrl+Shift+C QTest.keySequence(self.table_view, QKeySequence(self.shortcuts["copy_display_properties"])) # Evaluate mo_instance.return_value.clipboard.return_value.setText.assert_called_with(json.dumps(expected_ch_info)) def test_paste_display_properties_shortcut(self): """ Test Scope: - Ensure that key "Ctrl+Shift+V" can paste from clipboard display properties to selected item. Events: - Open Numeric widget with two channels. - Copy display properties of the first item. - Select second item -> press Ctrl+Shift+C. Evaluate: - Evaluate that to the widget are added two items. - Evaluate that after selecting second channel and hit keys "Ctrl+Shift+V", the second channel has the same display properties with the first channel. """ # Setup # Add items to the widget self.assertIsNotNone( self.add_channels( ["ASAM_[14].M.MATRIX_DIM_16.UBYTE.IDENTICAL", "ASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL"] ) ) # Evaluate precondition signal_0 = self.table_view.backend.signals[0] expected_ch_info = { "format": signal_0.format, "ranges": copy_ranges(self.table_view.ranges[signal_0.entry]), } with mock.patch("asammdf.gui.widgets.numeric.QtWidgets.QApplication.instance") as mo_instance: mo_instance.return_value.clipboard.return_value.text.return_value = expected_ch_info # Click on a first channel self.table_view.selectRow(1) # Press Ctrl+Shift+C QTest.keySequence(self.table_view, QKeySequence(self.shortcuts["paste_display_properties"])) # Evaluate mo_instance.return_value.clipboard.return_value.text.assert_called() signal_1 = self.table_view.backend.signals[1] self.assertEqual(signal_1.format, signal_0.format) self.assertEqual(self.table_view.ranges[signal_1.entry], self.table_view.ranges[signal_0.entry]) class TestNumericShortcuts(TestFileWidget): def setUp(self): """ Events: - Open measurement file. - Create a Numeric window. Evaluate: - Evaluate that there is one active sub-window created. Returns ------- """ super().setUp() # Open measurement file measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Open measurement file self.setUpFileWidget(measurement_file=measurement_file, default=True) self.create_window(window_type="Numeric") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) self.numeric = self.widget.mdi_area.subWindowList()[0].widget() self.table_view = self.numeric.channels.dataView # get shortcuts self.assertIsNotNone(self.load_shortcuts_from_json_file(self.numeric)) def test_ascii__bin__hex__physical_shortcuts(self): """ Test Scope: Check if values is converted to int, hex, bin after pressing combination of key "Ctrl+||

" Events: - Display 1 signal on Numeric - Press "Ctrl+B" - Press "Ctrl+H" - Press "Ctrl+P" - Press "Ctrl+T" Evaluate: - Evaluate that signal format is changed to BIN after pressing key "Ctrl+B" - Evaluate that signal format is changed to HEX after pressing key "Ctrl+H" - Evaluate that signal format is changed to PHYS after pressing key "Ctrl+P" - Evaluate that signal format is changed to ASCII after pressing key "Ctrl+T" """ # add channels to numeric self.assertIsNotNone(self.add_channels([35])) # Setup bin_format = "bin" hex_format = "hex" phys_format = "phys" ascii_format = "ascii" # Select first row (0) self.table_view.selectRow(0) self.processEvents() # Press "Ctrl+B" QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["bin"])) self.processEvents() # Evaluate self.assertEqual(self.table_view.backend.signals[0].format, bin_format) self.assertEqual(self.table_view.model().format, bin_format) # Select first row (0) self.table_view.selectRow(0) # Press "Ctrl+H" QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["hex"])) self.processEvents() # Evaluate self.assertEqual(self.table_view.backend.signals[0].format, hex_format) self.assertEqual(self.table_view.model().format, hex_format) # Select first row (0) self.table_view.selectRow(0) # Press "Ctrl+P" QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["physical"])) self.processEvents() # Evaluate self.assertEqual(self.table_view.backend.signals[0].format, phys_format) self.assertEqual(self.table_view.model().format, phys_format) # Select first row (0) self.table_view.selectRow(0) # Press "Ctrl+T" QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["ascii"])) self.processEvents() # Evaluate self.assertEqual(self.table_view.backend.signals[0].format, ascii_format) self.assertEqual(self.table_view.model().format, ascii_format) def test_move_timestamp_cursor_left__right_shortcuts(self): """ Test Scope: Check that Arrow Keys: Left & Right ensure navigation on channels evolution. Ensure that navigation is working. Events: - Display one signals to the widget - Send KeyClick Right 25 times - Send KeyClick Left 15 times Evaluate: - Evaluate that timestamp slider value is equal to the expected value """ # Setup # Add channels to numeric self.assertIsNotNone(self.add_channels(["ASAM_[13][0].M.MATRIX_DIM_16_1.UBYTE.IDENTICAL"])) left_clicks = 15 right_clicks = 25 # Get current timestamp slider value (TSV) ts_slider_value_at_start = self.numeric.timestamp_slider.value() # Add to TSV right clicks value and reduce it with left clicks value expected_ts_slider_value = ts_slider_value_at_start + right_clicks - left_clicks # Events # Select first row (0) self.table_view.selectRow(0) self.processEvents() # Press right key right_clicks time for _ in range(right_clicks): QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["move_cursor_right_1x"])) # Press left key left_clicks time for _ in range(left_clicks): QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["move_cursor_left_1x"])) # Evaluate self.assertEqual(self.numeric.timestamp_slider.value(), expected_ts_slider_value) def test_save_active_subplot_channels_shortcut(self): """ Test Scope: Check if by pressing "Ctrl+S" is saved in the new measurement file only active channels. Events: - Select 3 signals and create a numeric. - Ensure that the first sub-window is selected. - Press Key "Ctrl+S" -> input name for new file -> Save - Open recently created measurement file in a new window Evaluate: - Evaluate that object getSaveFileName() was called after pressing combination "Ctrl+S". - Evaluate that in measurement file is saved only active channels. """ # Setup self.assertIsNotNone(self.add_channels([10, 11, 12, 13])) # Create a new Numeric widget window with few different from first widget items self.create_window(window_type="Numeric", channels_indexes=(20, 21, 22)) expected_channels = [channel.name for channel in self.channels] expected_channels.append("time") file_path = os.path.join(self.test_workspace, "file.mf4") # Events # Select first row (0) self.table_view.selectRow(0) # mock for getSaveFileName object with mock.patch("asammdf.gui.widgets.numeric.QtWidgets.QFileDialog.getSaveFileName") as mo_getSaveFileName: mo_getSaveFileName.return_value = (file_path, "") # Press Ctrl+S QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["save_active_subplot_channels"])) # Evaluate mo_getSaveFileName.assert_called() # get waved file as MDF process_bus_logging = ("process_bus_logging", True) mdf_file = mdf.MDF(file_path, process_bus_logging=process_bus_logging) # Evaluate for name in expected_channels: self.assertIn(name, mdf_file.channels_db.keys()) mdf_file.close() def test_increase__decrease_font_shortcuts(self): """ Test scope: Ensure that Ctrl+[ and Ctrl+] will change font size Events: - Press Ctrl+[ - Press Ctrl+] Evaluate: - Evaluate that font size was increased after shortcut Ctrl+[ was pressed - Evaluate that font size was decreased after shortcut Ctrl+] was pressed """ font_size = self.numeric.font().pointSize() QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["decrease_font"])) self.assertLess(font_size, self.numeric.font().pointSize()) font_size = self.numeric.font().pointSize() QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["increase_font"])) self.assertGreater(font_size, self.numeric.font().pointSize()) def test_go_to_timestamp_shortcut(self): """ Test scope: Ensure that Shift+G switch to selected timestamp Events: - Display one item to the widget. - Press Shift+G -> input some value -> "Ok". Evaluate: - Evaluate that there is added one item to the widget. - Evaluate that getDouble object was called. - Evaluate that timestamp value is almost equal with the inputted value. Returns ------- """ # Setup # Add one item to the widget self.assertIsNotNone(self.add_channels([10])) # Event with mock.patch("asammdf.gui.widgets.numeric.QtWidgets.QInputDialog.getDouble") as mo_getDouble: expected_pos = 2 mo_getDouble.return_value = expected_pos, True # Press Shift+G QTest.keySequence(self.numeric, QKeySequence(self.shortcuts["go_to_timestamp"])) # Evaluate mo_getDouble.assert_called() self.assertAlmostEqual(self.numeric.timestamp.value(), expected_pos, delta=0.01) asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/test_PlotGraphicsWidget_Shortcuts.py000066400000000000000000001510101502633300400312000ustar00rootroot00000000000000#!/usr/bin/env python\ import os import sys import unittest from unittest import mock from PySide6.QtCore import QPoint, QRect, QSettings, Qt from PySide6.QtGui import QGuiApplication, QKeySequence from PySide6.QtTest import QTest from PySide6.QtWidgets import QTreeWidgetItemIterator from asammdf import mdf from test.asammdf.gui.test_base import Pixmap from test.asammdf.gui.widgets.test_BasePlotWidget import TestPlotWidget class TestPlotGraphicsShortcuts(TestPlotWidget): def setUp(self): """ Events: Open test measurement file Set sort method: Natural sort Create new plot widget with following setup: - Without dots - Without grid - With hidden bookmarks - Cursor without circle Evaluate: - Evaluate that one widget was created - Evaluate that plot is black """ super().setUp() settings = QSettings() settings.setValue("zoom_x_center_on_cursor", True) settings.setValue("plot_cursor_precision", 6) # Open measurement file self.setUpFileWidget(measurement_file=self.measurement_file, default=True) # Switch ComboBox to "Natural sort" self.widget.channel_view.setCurrentText("Natural sort") # Select channels -> Press PushButton "Create Window" -> "Plot" self.create_window(window_type="Plot") # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) # Plot object self.plot = self.widget.mdi_area.subWindowList()[0].widget() # Preset for plot # Remove dots if self.plot.plot.with_dots: self.plot.plot.set_dots(False) # check if grid is available -> hide grid if not self.plot.hide_axes_btn.isFlat(): QTest.mouseClick(self.plot.hide_axes_btn, Qt.MouseButton.LeftButton) # hide bookmarks if it's available if self.plot.show_bookmarks: self.plot.toggle_bookmarks(hide=True) # Ensure that plot is not` in Focused mode if self.plot.focused_mode: self.plot.toggle_focused_mode() # Ensure that plot cursor is not with circle if self.plot.plot.cursor1.show_circle: self.plot.plot.cursor1.show_circle = False self.pg = self.plot.plot # PlotGraphics object self.processEvents(0.01) # Evaluate that plot is black self.assertTrue(Pixmap.is_black(self.pg.grab())) # get shortcuts self.assertIsNotNone(self.load_shortcuts_from_json_file(self.pg)) self.processEvents() def test_lock_unlock_range_shortcut(self): """ Test Scope: Check if Range Selection cursor is locked/unlocked after pressing key Y. Events: - Set default cursor color, without horizontal line and circle, with 1px line width - Press Key Y for range selection - Move Cursors - Press Key R for range selection Evaluate: - Evaluate that at start is only one cursor available - Evaluate that two cursors are available after key Y was pressed - Evaluate that new rectangle with different color is present - Evaluate that sum of rectangle areas is same with the one when plot is full black. - Evaluate that range selection disappear. """ # Setup for cursor self.widget.set_cursor_options(False, False, 1, Pixmap.COLOR_CURSOR) # Save PixMap of clean plot clean_pixmap = self.pg.grab() # Evaluate that plot is black self.assertTrue(Pixmap.is_black(clean_pixmap)) # Get position of Cursor cursors = Pixmap.cursors_x(clean_pixmap) # Evaluate that there is only one cursor self.assertEqual(1, len(cursors)) # Press Key 'Y' for range selection QTest.keySequence(self.pg, QKeySequence(self.shortcuts["toggle_range"])) self.processEvents(timeout=0.1) # Save PixMap of Range plot range_pixmap = self.pg.grab() self.assertFalse(Pixmap.is_black(range_pixmap)) # Get X position of Cursors cursors = Pixmap.cursors_x(range_pixmap) # Evaluate that two cursors are available self.assertEqual(2, len(cursors)) # Evaluate that new rectangle with different color is present self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=0, y=0, width=min(cursors) - 1, ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_RANGE, x=min(cursors) + 1, y=0, width=max(cursors), ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=max(cursors) + 1, y=0, ) ) # Move Cursors QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_left_1x"])) self.processEvents(timeout=0.01) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_left_20x"])) self.processEvents(timeout=0.01) # Save PixMap of Range plot range_pixmap = self.pg.grab() self.assertFalse(Pixmap.is_black(range_pixmap)) # Get X position of Cursors new_cursors = Pixmap.cursors_x(range_pixmap) # Evaluate that two cursors are available self.assertEqual(2, len(new_cursors)) self.assertEqual(cursors[0], new_cursors[0], "First cursor have new position after manipulation") self.assertNotEqual(cursors[1], new_cursors[1], "Second cursors have same position after manipulation") # Evaluate that new rectangle with different color is present self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=0, y=0, width=min(new_cursors) - 1, ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_RANGE, x=min(new_cursors) + 1, y=0, width=max(new_cursors), ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=max(new_cursors) + 1, y=0, ) ) cursors = new_cursors # Press Key 'R' for range selection QTest.keySequence(self.pg, QKeySequence(self.shortcuts["toggle_range"])) self.processEvents(timeout=0.01) # Move Cursors QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_right_1x"])) self.processEvents(timeout=0.01) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_left_20x"])) self.processEvents(timeout=0.01) # Save PixMap of Range plot range_pixmap = self.pg.grab() self.assertFalse(Pixmap.is_black(range_pixmap)) # Get X position of Cursors new_cursors = Pixmap.cursors_x(range_pixmap) # Evaluate that two cursors are available self.assertEqual(2, len(new_cursors)) for c in cursors: self.assertNotIn(c, new_cursors, f"cursor {c} is the same") # Evaluate that new rectangle with different color is present self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=0, y=0, width=min(new_cursors) - 1, ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_RANGE, x=min(new_cursors) + 1, y=0, width=max(new_cursors), ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=max(new_cursors) + 1, y=0, ) ) # Press Key 'R' for range selection QTest.keySequence(self.pg, QKeySequence(self.shortcuts["range"])) self.processEvents(timeout=0.01) # Save PixMap of clear plot clean_pixmap = self.pg.grab() self.assertTrue(Pixmap.is_black(clean_pixmap)) def test_zoom_to_range_shortcut(self): """ Test Scope: Check if fitting between cursors is released after pressing key "X". Events: - Display 1 signal on plot - Maximize window - Mouse click in the middle of plot - Press "R" - Press "X" Evaluate: - Evaluate that intersection of signal and midd line is exactly how much it intersects between cursors - Evaluate X range, it must be almost equal as range value after pressing key R """ # Setup self.add_channels([35]) channel_color = self.channels[0].color.name() # Count intersections between middle line and signal initial_intersections = Pixmap.color_map(self.pg.grab(QRect(0, int(self.pg.height() / 2), self.pg.width(), 1)))[ 0 ].count(channel_color) self.assertTrue(initial_intersections) # Setup for cursor self.widget.set_cursor_options(False, False, 1, Pixmap.COLOR_CURSOR) # Mouse click on a center of plot QTest.mouseClick( self.pg.viewport(), Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier, self.pg.rect().center(), ) # Press R QTest.keySequence(self.pg, QKeySequence(self.shortcuts["range"])) self.processEvents() x_range = self.pg.region.getRegion() self.assertNotIn(x_range[0], self.pg.x_range) self.assertNotIn(x_range[1], self.pg.x_range) # Get X position of Cursor cursors = Pixmap.cursors_x(self.pg.grab()) # Ensure that both cursors were found self.assertEqual(len(cursors), 2) # Get a set of colors founded between cursors colors = Pixmap.color_names_exclude_defaults( self.pg.grab(QRect(cursors[0], 0, cursors[1] - cursors[0], self.pg.height())) ) # Exclude channel original color if channel_color in colors: colors.remove(channel_color) # caught ya color = colors.pop() # Evaluate if color was found, in set must remain only the new channel color situated between cursors self.assertTrue(color) # Count intersection of midd line and signal between cursors expected_intersections = Pixmap.color_map( self.pg.grab(QRect(cursors[0], int(self.pg.height() / 2), cursors[1] - cursors[0], 1)) )[0].count(color) self.assertTrue(expected_intersections) # Press key "X" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["zoom_to_range"])) self.processEvents() # Evaluate how much times signal intersect midd line actual_intersections = Pixmap.color_map(self.pg.grab(QRect(0, int(self.pg.height() / 2), self.pg.width(), 1)))[ 0 ].count(channel_color) self.assertEqual(actual_intersections, expected_intersections) self.assertLess(actual_intersections, initial_intersections) # Evaluate ranges of signal self.assertAlmostEqual(self.pg.x_range[0], x_range[0], delta=0.001) self.assertAlmostEqual(self.pg.x_range[1], x_range[1], delta=0.001) @unittest.skip("FIXME: test keeps failing in CI") def test_fit__stack_shortcuts(self): """ Test Scope: Check if: > all signals is stack after pressing key "S" > only selected signal is fitted after pressing combination "Sift + F" > only selected signal is stacked after pressing combination "Shift + S" > all signals is fitted after pressing key "F" Events: - Display 3 channels to plot - Press Key "S" - Press combination "Shift + F" - Press combination "Shift + S" - press key "F" Evaluate: - Evaluate that signals are separated in top, midd and bottom third of plot after pressing key "S" - Evaluate that only selected signal is fitted after pressing combination "Shift + F" - Evaluate that only selected signal is stacked after pressing combination "Shift + S" - Evaluate that all signals are fitted after pressing key "F" Additional Evaluation - Evaluate that all signals are continuous on plot """ def continuous(ch): pixmap = self.pg.grab() image = pixmap.toImage() signal_color = ch.color.name() start, stop = Pixmap.search_signal_extremes_by_ax(pixmap, signal_color=signal_color, ax="x") for x in range(start, stop + 1): for j in range(self.pg.height()): if image.pixelColor(x, j).name() == signal_color: break else: raise Exception(f"column {x} doesn't have color of channel {ch.name} from {start=} to {stop=}") self.pg.cursor1.color = "#000000" settings = QSettings() settings.setValue("zoom_x_center_on_cursor", True) self.add_channels([35, 36, 37]) channel_35 = self.channels[0] channel_36 = self.channels[1] channel_37 = self.channels[2] # Press "S" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["stack_all"])) self.processEvents() # Evaluate with self.subTest("test_stack_all_shortcut"): # First 2 lines self.assertTrue(Pixmap.is_black(self.pg.grab(QRect(0, 0, self.pg.width(), 1)))) # Top pixmap = self.pg.grab(QRect(0, 0, self.pg.width(), int(self.pg.height() / 3))) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_37.color.name())) # Midd pixmap = self.pg.grab( QRect( 0, int(self.pg.height() / 3), self.pg.width(), int(self.pg.height() / 3), ) ) self.assertFalse(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_37.color.name())) # Bottom pixmap = self.pg.grab( QRect( 0, int(self.pg.height() / 3) * 2, self.pg.width(), int(self.pg.height() / 3), ) ) self.assertFalse(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_37.color.name())) # Last 2 lines pixmap = self.pg.grab(QRect(0, self.pg.height() - 3, self.pg.width(), 2)) cn = Pixmap.color_names_exclude_defaults(pixmap) self.assertEqual(len(cn), 0) # select the first channel self.mouseClick_WidgetItem(channel_35) # Press "Shift+F" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["fit_selected"])) self.avoid_blinking_issue(self.plot.channel_selection) for _ in range(50): self.processEvents() # Evaluate with self.subTest("test_fit_selected_shortcut"): # First line self.assertTrue(Pixmap.is_black(self.pg.grab(QRect(0, 0, self.pg.width(), 1)))) # Top pixmap = self.pg.grab(QRect(0, 0, self.pg.width(), int(self.pg.height() / 3))) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_37.color.name())) # Midd pixmap = self.pg.grab( QRect( 0, int(self.pg.height() / 3), self.pg.width(), int(self.pg.height() / 3), ) ) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_37.color.name())) # Bottom pixmap = self.pg.grab( QRect( 0, int(self.pg.height() / 3) * 2, self.pg.width(), int(self.pg.height() / 3), ) ) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_37.color.name())) # Last line self.assertTrue(Pixmap.is_black(self.pg.grab(QRect(0, self.pg.height() - 2, self.pg.width(), 1)))) # select second channel self.mouseClick_WidgetItem(channel_36) # Press "Shift+F" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["stack_selected"])) self.avoid_blinking_issue(self.plot.channel_selection) # Evaluate with self.subTest("test_stack_selected_shortcut"): # First line self.assertTrue(Pixmap.is_black(self.pg.grab(QRect(0, 0, self.pg.width(), 1)))) # Top pixmap = self.pg.grab(QRect(0, 0, self.pg.width(), int(self.pg.height() / 3))) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_37.color.name())) # Midd pixmap = self.pg.grab( QRect( 0, int(self.pg.height() / 3), self.pg.width(), int(self.pg.height() / 3), ) ) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertFalse(Pixmap.has_color(pixmap, channel_37.color.name())) # Bottom pixmap = self.pg.grab( QRect( 0, int(self.pg.height() / 3) * 2, self.pg.width(), int(self.pg.height() / 3), ) ) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_37.color.name())) # Last line self.assertTrue(Pixmap.is_black(self.pg.grab(QRect(0, self.pg.height() - 1, self.pg.width(), 1)))) # Press "F" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["fit_all"])) self.avoid_blinking_issue(self.plot.channel_selection) # Evaluate with self.subTest("test_fit_all_shortcut"): # First line self.assertTrue(Pixmap.is_black(self.pg.grab(QRect(0, 0, self.pg.width(), 1)))) # Top pixmap = self.pg.grab(QRect(0, 0, self.pg.width(), int(self.pg.height() / 3))) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_37.color.name())) # Midd pixmap = self.pg.grab( QRect( 0, int(self.pg.height() / 3), self.pg.width(), int(self.pg.height() / 3), ) ) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_37.color.name())) # Bottom pixmap = self.pg.grab( QRect( 0, int(self.pg.height() / 3) * 2, self.pg.width(), int(self.pg.height() / 3), ) ) self.assertTrue(Pixmap.has_color(pixmap, channel_35.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_36.color.name())) self.assertTrue(Pixmap.has_color(pixmap, channel_37.color.name())) # Last line self.assertTrue(Pixmap.is_black(self.pg.grab(QRect(0, self.pg.height() - 1, self.pg.width(), 1)))) # deselect all channels for channel in self.channels: self.mouseDClick_WidgetItem(channel) # search if all channels are fitted into extremes self.mouseDClick_WidgetItem(channel_35) continuous(channel_35) self.mouseDClick_WidgetItem(channel_35) self.mouseDClick_WidgetItem(channel_36) continuous(channel_36) self.mouseDClick_WidgetItem(channel_36) self.mouseDClick_WidgetItem(channel_37) continuous(channel_37) def test_grid_shortcut(self): """ Test Scope: Check if grid is created properly after pressing key "G". Events: - If axes are hidden - press "Show axes" button - Press Key "G" 20 times Evaluate: - Evaluate that grid is displayed in order after pressing key "G": 1. Is only X axis grid. 2. Is X and Y axes grids. 3. Is only Y axis grid 4. There is no grid. """ # Check if the grid is available if self.plot.hide_axes_btn.isFlat(): QTest.mouseClick(self.plot.hide_axes_btn, Qt.MouseButton.LeftButton) next_grid = { (False, False): (True, False), (True, False): (True, True), (True, True): (False, True), (False, True): (False, False), } current_grid = self.pg.x_axis.grid, self.pg.y_axis.grid for i in range(20): # press key "G" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["grid"])) self.processEvents() # Evaluate current_grid = next_grid[current_grid] self.assertEqual(current_grid, (self.pg.x_axis.grid, self.pg.y_axis.grid)) def test_go_to_timestamp_shortcut(self): """ Test scope: Ensure that Shift+G will switchto selected timestamp Events: - Display one item to the widget. - Press Shift+G -> input some value -> "Ok". Evaluate: - Evaluate that there is added one item to the widget. - Evaluate that getDouble object was called. - Evaluate that timestamp value is almost equal with the inputted value. Returns ------- """ # Setup # Add one item to the widget self.assertIsNotNone(self.add_channels([10])) # Event with mock.patch("asammdf.gui.widgets.plot.QtWidgets.QInputDialog.getDouble") as mo_getDouble: expected_pos = 3.0 mo_getDouble.return_value = expected_pos, True # Press Shift+G QTest.keySequence(self.plot, QKeySequence(self.shortcuts["go_to_timestamp"])) self.processEvents(0.1) self.processEvents(0.01) # Evaluate mo_getDouble.assert_called() ci = self.plot.cursor_info pos = float(ci.text().split()[2].split(ci.unit)[0]) self.assertAlmostEqual(expected_pos, pos, delta=0.01) def test_zoom_in__out_shortcuts(self): """ Test Scope: Check if zooming is released after pressing keys "I", "Shift+I", "O", "Shift+O". Events: - Display 1 signal on plot - Select signal, click in the middle of plot - Press "I". - Press "O". - Press "Shift+I". - Press "Shift+O". Evaluate: - Evaluate ranges of the "X" and the "Y" asis. """ def get_expected_result(step, is_x_axis: bool): if is_x_axis: delta = self.pg.x_range[1] - self.pg.x_range[0] val = self.pg.cursor1.value() step = delta * step return val - delta / 2 - step, val + delta / 2 + step else: val, bottom, top = self.pg.value_at_cursor() delta = (top - bottom) * step return val - delta / 2, val + delta / 2 # Setup if self.plot.lock_btn.isFlat(): QTest.mouseClick(self.plot.lock_btn, Qt.MouseButton.LeftButton) y_step = 0.165 x_step = 0.25 self.assertIsNotNone(self.add_channels([35])) self.mouseClick_WidgetItem(self.channels[0]) self.processEvents() self.pg.viewbox.menu.set_x_zoom_mode() self.pg.viewbox.menu.set_y_zoom_mode() # click con center QTest.mouseClick( self.plot.plot.viewport(), Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier, QPoint(int(self.pg.width() / 2), int(self.pg.height() / 2)), ) self.processEvents() # Events Without Pressed Shift expected_x_zoom_in_range = get_expected_result(-x_step, True) # Press "I" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["x_zoom_in"])) self.processEvents() x_zoom_in_range = self.pg.x_range expected_x_zoom_out_range = get_expected_result(x_step * 2, True) # Press "O" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["x_zoom_out"])) self.processEvents() x_zoom_out_range = self.pg.x_range # Events with pressed Shift expected_y_zoom_in_range = get_expected_result(1 / (1 + y_step), False) # Press "I" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["y_zoom_in"])) self.processEvents() y_zoom_in_range = self.pg.signals[0].y_range expected_y_zoom_out_range = get_expected_result(1 + y_step, False) # Press "O" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["y_zoom_out"])) self.processEvents() y_zoom_out_range = self.pg.signals[0].y_range # Evaluate delta = pow(10, -4) # Key Shift wasn't pressed self.assertAlmostEqual(x_zoom_in_range[0], expected_x_zoom_in_range[0], delta=delta) self.assertAlmostEqual(x_zoom_in_range[1], expected_x_zoom_in_range[1], delta=delta) self.assertAlmostEqual(x_zoom_out_range[0], expected_x_zoom_out_range[0], delta=delta) self.assertAlmostEqual(x_zoom_out_range[1], expected_x_zoom_out_range[1], delta=delta) # Key Shift was pressed self.assertAlmostEqual(y_zoom_in_range[0], expected_y_zoom_in_range[0], delta=delta) self.assertAlmostEqual(y_zoom_in_range[1], expected_y_zoom_in_range[1], delta=delta) self.assertAlmostEqual(y_zoom_out_range[0], expected_y_zoom_out_range[0], delta=delta) self.assertAlmostEqual(y_zoom_out_range[1], expected_y_zoom_out_range[1], delta=delta) def test_range_shortcut(self): """ Test Scope: Check if Range Selection rectangle is painted over the plot. Events: - Press Key R for range selection - Move Cursors - Press Key R for range selection Evaluate: - Evaluate that two cursors are available - Evaluate that new rectangle with different color is present - Evaluate that sum of rectangle areas is same with rectangle of full black plot. - Evaluate that range selection disappears after pressing key R second time. """ self.widget.set_cursor_options(False, False, 1, Pixmap.COLOR_CURSOR) # Save PixMap of clear plot clear_pixmap = self.pg.grab() self.assertTrue(Pixmap.is_black(clear_pixmap)) # Get X position of Cursor cursors = Pixmap.cursors_x(clear_pixmap) # Evaluate that there is only one cursor self.assertEqual(1, len(cursors)) # Press Key 'R' for range selection QTest.keySequence(self.pg, QKeySequence(self.shortcuts["range"])) self.processEvents(timeout=0.01) # Save PixMap of Range plot range_pixmap = self.pg.grab() self.assertFalse(Pixmap.is_black(range_pixmap)) # Get X position of Cursors cursors = Pixmap.cursors_x(range_pixmap) # Evaluate that two cursors are available self.assertEqual(2, len(cursors)) # Evaluate that new rectangle with different color is present self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=0, y=0, width=min(cursors) - 1, ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_RANGE, x=min(cursors) + 1, y=0, width=max(cursors), ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=max(cursors) + 1, y=0, ) ) # Move Cursors QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_right_1x"])) self.processEvents(timeout=0.01) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_left_20x"])) self.processEvents(timeout=0.01) # Save PixMap of Range plot range_pixmap = self.pg.grab() self.assertFalse(Pixmap.is_black(range_pixmap)) # Get X position of Cursors new_cursors = Pixmap.cursors_x(range_pixmap) # Evaluate that two cursors are available self.assertEqual(2, len(cursors)) for c in cursors: self.assertNotIn(c, new_cursors, f"cursor {c} is the same") # Evaluate that new rectangle with different color is present self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=0, y=0, width=min(new_cursors) - 1, ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_RANGE, x=min(new_cursors) + 1, y=0, width=max(new_cursors), ) ) self.assertTrue( Pixmap.is_colored( pixmap=range_pixmap, color_name=Pixmap.COLOR_BACKGROUND, x=max(new_cursors) + 1, y=0, ) ) # Press Key 'R' for range selection QTest.keySequence(self.pg, QKeySequence(self.shortcuts["range"])) self.processEvents(timeout=0.01) # Save PixMap of clear plot clear_pixmap = self.pg.grab() self.assertTrue(Pixmap.is_black(clear_pixmap)) def test_save_active_subplot_channels_shortcut(self): """ Test Scope: Check if by pressing "Ctrl+S" is saved in the new measurement file only active channels. Events: - Open 'FileWidget' with valid measurement. - Select 3 signals and create a new plot - Deselect first channel from first plot - Press Key "Ctrl+S" - Open recently created measurement file in a new window. Evaluate: - Evaluate that object getSaveFileName() was called after pressing combination "Ctrl+S" - Evaluate that in measurement file is saved only active channels """ # Setup file_path = os.path.join(self.test_workspace, "test_file.mf4") self.create_window(window_type="Plot", channels_indexes=(20, 21, 22)) self.processEvents() second_plot_items = [] iterator = QTreeWidgetItemIterator(self.widget.mdi_area.subWindowList()[1].widget().channel_selection) while item := iterator.value(): second_plot_items.append(item.name) iterator += 1 self.assertIsNotNone(self.add_channels([10, 11, 12, 13])) expected_channels = [channel.name for channel in self.channels] expected_channels.append("time") self.processEvents() # select all channels excluding the first one for _ in range(1, len(self.channels)): self.channels[_].setSelected(True) expected_channels.remove(self.channels[0].name) self.processEvents() with mock.patch("asammdf.gui.widgets.plot.QtWidgets.QFileDialog.getSaveFileName") as mo_getSaveFileName: mo_getSaveFileName.return_value = (file_path, "") # Press Ctrl+S QTest.keySequence(self.plot, QKeySequence(self.shortcuts["save_active_subplot_channels"])) # Evaluate mo_getSaveFileName.assert_called() # get waved file as MDF process_bus_logging = ("process_bus_logging", True) mdf_file = mdf.MDF(file_path, process_bus_logging=process_bus_logging) # Evaluate for name in expected_channels: self.assertIn(name, mdf_file.channels_db.keys()) for name in second_plot_items: self.assertNotIn(name, mdf_file.channels_db.keys()) mdf_file.close() def test_move_cursor_left__right_shortcuts(self): """ Test Scope: Check that Arrow Keys: Left & Right ensure navigation on channels evolution. Ensure that navigation is working. Events: - Display one signal to plot - Click Right key specific number of times. - Click Left key specific number of times. - Click Ctrl+Right key specific number of times. - Click Ctrl+Left key specific number of times. Evaluate: - Evaluate values from selected channel value and cursor info, it must be equal to the expected values. """ # Setup if self.plot.selected_channel_value_btn.isFlat(): QTest.mouseClick(self.plot.selected_channel_value_btn, Qt.MouseButton.LeftButton) self.add_channels([37]) ch = self.channels[0] # Number of times that specific key will be pressed right_clicks = 50 ctrl_right_clicks = 20 left_clicks = 30 ctrl_left_clicks = 15 ci = self.plot.cursor_info # Select channel self.mouseClick_WidgetItem(ch) self.pg.setFocus() self.processEvents(0.1) pos = 0 cursor_prev = Pixmap.cursors_x(self.pg.grab())[0] c1_pos = self.pg.cursor1.getXPos() # Evaluate self.assertEqual(f"{ch.signal.samples[pos]} {ch.unit}", self.plot.selected_channel_value.text()) self.assertEqual(f"{ci.name} = {round(ch.signal.timestamps[pos], ci.precision)}{ci.unit}", ci.text()) self.assertEqual(ch.signal.timestamps[pos], self.pg.cursor1.getXPos()) # Event for _ in range(right_clicks): QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_right_1x"])) self.processEvents(0.01) self.processEvents(0.5) pos += right_clicks cursor_now = Pixmap.cursors_x(self.pg.grab())[0] # Evaluate self.assertGreater(cursor_now, cursor_prev) self.assertEqual(f"{ch.signal.samples[pos]} {ch.unit}", self.plot.selected_channel_value.text()) self.assertEqual(f"{ci.name} = {round(ch.signal.timestamps[pos], ci.precision)}{ci.unit}", ci.text()) self.assertEqual(ch.signal.timestamps[pos], self.pg.cursor1.getXPos()) # New setup pos -= left_clicks # Send Key strokes for _ in range(left_clicks): QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_left_1x"])) self.processEvents(0.01) self.processEvents(0.5) cursor_prev = cursor_now cursor_now = Pixmap.cursors_x(self.pg.grab())[0] # Evaluate self.assertLess(cursor_now, cursor_prev) self.assertEqual(f"{ch.signal.samples[pos]} {ch.unit}", self.plot.selected_channel_value.text()) self.assertEqual(f"{ci.name} = {round(ch.signal.timestamps[pos], ci.precision)}{ci.unit}", ci.text()) self.assertEqual(ch.signal.timestamps[pos], self.pg.cursor1.getXPos()) # Send Key strokes for _ in range(ctrl_right_clicks): QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_right_20x"])) self.processEvents(0.01) self.processEvents(0.1) pos += 20 * ctrl_right_clicks cursor_prev = cursor_now cursor_now = Pixmap.cursors_x(self.pg.grab())[0] # Evaluate self.assertGreater(cursor_now, cursor_prev) self.assertEqual(f"{ch.signal.samples[pos]} {ch.unit}", self.plot.selected_channel_value.text()) self.assertEqual(f"{ci.name} = {round(ch.signal.timestamps[pos], ci.precision)}{ci.unit}", ci.text()) self.assertEqual(ch.signal.timestamps[pos], self.pg.cursor1.getXPos()) # Send Key strokes for _ in range(ctrl_left_clicks): QTest.keySequence(self.pg, QKeySequence(self.shortcuts["move_cursor_left_20x"])) self.processEvents(0.01) self.processEvents(0.1) pos -= 20 * ctrl_left_clicks cursor_prev = cursor_now cursor_now = Pixmap.cursors_x(self.pg.grab())[0] # Evaluate self.assertLess(cursor_now, cursor_prev) self.assertEqual(f"{ch.signal.samples[pos]} {ch.unit}", self.plot.selected_channel_value.text()) self.assertEqual(f"{ci.name} = {round(ch.signal.timestamps[pos], ci.precision)}{ci.unit}", ci.text()) self.assertEqual(ch.signal.timestamps[pos], self.pg.cursor1.getXPos()) @unittest.skip("FIXME: test keeps failing in CI") @unittest.skipIf(sys.platform != "win32", "RuntimeError. C++ object <> already deleted.") def test_shift_channels_shortcut(self): """ Test Scope: Check that Shift + Arrow Keys ensure moving of selected channels. Events: - Create plot with 2 channels - Press key "S" to separate signals for better evaluation - Click on first channel - Press "Shift" key + arrow "Down" & "Left" - Click on second channel - Press "Shift" key + arrow "Up" & "Right" Evaluate: - Evaluate that first signal is shifted down & left after pressing combination "Shift+Down" & "Shift+Left" - Evaluate that second signal is shifted up & right after pressing combination "Shift+Up" & "Shift+Right" """ if self.plot.lock_btn.isFlat(): QTest.mouseClick(self.plot.lock_btn, Qt.MouseButton.LeftButton) self.add_channels([36, 37]) channel_36 = self.channels[0] channel_37 = self.channels[1] QTest.keySequence(self.pg, QKeySequence(self.shortcuts["stack_all"])) self.processEvents(0.01) # Zoom out x = round(self.plot.plot.width() / 2) y = round(self.plot.plot.height() / 2) QTest.mouseClick(self.pg.viewport(), Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier, QPoint(x, y)) self.wheel_action(self.pg.viewport(), x, y, -1) self.processEvents(0.1) # Find extremes of signals old_from_to_y_channel_36 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_36.color.name(), "y") old_from_to_x_channel_36 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_36.color.name(), "x") old_from_to_y_channel_37 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_37.color.name(), "y") old_from_to_x_channel_37 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_37.color.name(), "x") # Select first channel and move signal using commands Shift + PgDown/Down/Left self.mouseClick_WidgetItem(channel_36) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["shift_channels_down_10x"])) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["shift_channels_down_1x"])) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["shift_channels_left"])) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["shift_channels_left"])) self.avoid_blinking_issue(self.plot.channel_selection) self.processEvents() # Select second channel and move signal using commands Shift + PgUp/Up/Right self.mouseClick_WidgetItem(channel_37) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["shift_channels_up_10x"])) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["shift_channels_up_1x"])) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["shift_channels_right"])) QTest.keySequence(self.pg, QKeySequence(self.shortcuts["shift_channels_right"])) self.avoid_blinking_issue(self.plot.channel_selection) self.processEvents() # Find new extremes new_from_to_y_channel_36 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_36.color.name(), "y") new_from_to_y_channel_37 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_37.color.name(), "y") new_from_to_x_channel_36 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_36.color.name(), "x") new_from_to_x_channel_37 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_37.color.name(), "x") # Evaluate self.assertLess(old_from_to_y_channel_36[0], new_from_to_y_channel_36[0]) self.assertLess(old_from_to_y_channel_36[1], new_from_to_y_channel_36[1]) self.assertGreater(old_from_to_x_channel_36[0], new_from_to_x_channel_36[0]) self.assertGreater(old_from_to_x_channel_36[1], new_from_to_x_channel_36[1]) self.assertGreater(old_from_to_y_channel_37[0], new_from_to_y_channel_37[0]) self.assertGreater(old_from_to_y_channel_37[1], new_from_to_y_channel_37[1]) self.assertLess(old_from_to_x_channel_37[0], new_from_to_x_channel_37[0]) self.assertLess(old_from_to_x_channel_37[1], new_from_to_x_channel_37[1]) def test_test_honeywell_shortcut(self): """ Test Scope: Check if honeywell function is applied to signal after pressing key "H" Events: - Display 1 signal on plot - Select signal - Press "H" - Set window mode to full screen - Pres "H" Evaluate: - Evaluate the range of x-axis after pressing key "H", "honey range" must be respected - Evaluate the range of x-axis is same for maximized window - Evaluate the range of x-axis after pressing key "H" second time, "honey range" must be respected """ def find_honey_range(plot): rect = plot.plotItem.vb.sceneBoundingRect() dpi = QGuiApplication.primaryScreen().physicalDotsPerInchX() dpc = dpi / 2.54 # from inch to cm physical_viewbox_width = (rect.width() - 5) / dpc # cm return physical_viewbox_width * 0.1 # Setup self.add_channels([35]) expected_normal_screen_honey_range = find_honey_range(self.pg) # Press "H" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["honeywell"])) self.avoid_blinking_issue(self.plot.channel_selection) delta_normal_screen_x_range = self.pg.x_range[1] - self.pg.x_range[0] # Evaluate self.assertAlmostEqual(delta_normal_screen_x_range, expected_normal_screen_honey_range, delta=0.0001) # Minimize widget self.widget.setFixedSize(int(self.widget.width() * 0.9), int(self.widget.height() * 0.9)) self.processEvents() # Evaluate self.assertAlmostEqual(self.pg.x_range[1] - self.pg.x_range[0], delta_normal_screen_x_range, delta=0.0001) expected_full_screen_honey_range = find_honey_range(self.pg) # Press "H" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["honeywell"])) self.avoid_blinking_issue(self.plot.channel_selection) delta_full_screen_x_range = self.pg.x_range[1] - self.pg.x_range[0] # Evaluate self.assertNotEqual(delta_full_screen_x_range, delta_normal_screen_x_range) self.assertAlmostEqual(delta_full_screen_x_range, expected_full_screen_honey_range, delta=0.0001) @unittest.skip("FIXME: test keeps failing in CI") def test_home_shortcuts(self): """ Check if the signal is fitted properly after pressing key "W". Events: - Create a plot window with 2 signals - Press key "I" - Press key "W" Evaluate: - Evaluate that there is at least one column with first signal color - Evaluate first and last columns where is first signal: > first column after pressing "I" is full black => signal colors are not there > signal is zoomed => is extended to left side => last column contain signal color - Evaluate that after pressing key "W", signal is displayed from first to last column """ settings = QSettings() settings.setValue("zoom_x_center_on_cursor", True) self.assertIsNotNone(self.add_channels([35])) channel_35 = self.channels[0] # check if the grid is available if not self.plot.hide_axes_btn.isFlat(): QTest.mouseClick(self.plot.hide_axes_btn, Qt.MouseButton.LeftButton) # Press "W" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["home"])) self.processEvents(0.01) # search first and last column where is displayed first signal extremes_of_channel_35 = Pixmap.search_signal_extremes_by_ax(self.pg.grab(), channel_35.color.name(), ax="x") # Evaluate that there are extremes of first signal self.assertTrue(extremes_of_channel_35) # Press "I" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["x_zoom_in"])) self.processEvents(0.5) # save left and right pixel column x_left_column = self.pg.grab(QRect(extremes_of_channel_35[0], 0, 1, self.pg.height())) x_right_column = self.pg.grab(QRect(extremes_of_channel_35[1], 0, 1, self.pg.height())) self.assertTrue(Pixmap.is_black(x_left_column)) self.assertTrue(Pixmap.has_color(x_right_column, channel_35.color.name())) # press "F" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["fit_all"])) # Press "W" QTest.keySequence(self.pg, QKeySequence(self.shortcuts["home"])) self.processEvents() # Select all columns from left to right for x in range(self.pg.height() - 1): column = self.pg.grab(QRect(x, 0, 1, self.pg.height())) if x < extremes_of_channel_35[0] - 1: self.assertTrue(Pixmap.is_black(column), f"column {x} is not black") elif extremes_of_channel_35[0] <= x <= extremes_of_channel_35[1]: self.assertTrue( Pixmap.has_color(column, channel_35.color.name()), f"column {x} doesn't have {channel_35.name} color", ) else: self.assertTrue(Pixmap.is_black(column), f"column {x} is not black") def test_insert_computation_shortcut(self): """ Test Scope: Check Insert key shortcut action Events: - Press Insert with preconditions: > There is no user defined functon > There is user defined functon, button Cancel or "X" was pressed > There is user defined function, button Apply was pressed Evaluate: - Evaluate that channel selection area is empty Evaluate (0): - Evaluate that warning message box was triggered after pressing key insert - Evaluate displayed warning message - Evaluate that channel selection area is empty Evaluate (1): - Evaluate that channel selection area is empty - Evaluate that DefineChannel object was called Evaluate (2): - Evaluate that there is one channel in channel selection area - Evaluate that the name of this channel is correct - Evaluate that DefineChannel object was called """ # Evaluate precondition self.assertEqual(0, self.plot.channel_selection.topLevelItemCount()) with self.subTest("_0_test_warning_no_user_function_defined"): warnings_msgs = [ "Cannot add computed channel", "There is no user defined function. Create new function using the Functions Manger (F6)", ] # mock for warning message box with mock.patch("asammdf.gui.widgets.plot.MessageBox.warning") as mo_waring: # Press key Insert QTest.keySequence(self.plot.channel_selection, QKeySequence(self.shortcuts["insert_computation"])) # Evaluate self.assertEqual(0, self.plot.channel_selection.topLevelItemCount()) mo_waring.assert_called() for w in warnings_msgs: self.assertIn(w, mo_waring.call_args.args) with self.subTest("_1_test_cancel_dlg_with_user_function_defined"): file_name = "test_insert_cfg.dspf" file_path = os.path.join(self.resource, file_name) self.load_display_file(file_path) self.plot = self.widget.mdi_area.subWindowList()[0].widget() with mock.patch("asammdf.gui.widgets.plot.DefineChannel") as mo_DefineChannel: # Press key Insert QTest.keySequence(self.plot.channel_selection, QKeySequence(self.shortcuts["insert_computation"])) # Evaluate self.assertEqual(1, self.plot.channel_selection.topLevelItemCount()) mo_DefineChannel.assert_called() with self.subTest("_2_test_apply_dlg_with_user_function_defined"): file_name = "test_insert_cfg.dspf" file_path = os.path.join(self.resource, file_name) self.load_display_file(file_path) self.plot = self.widget.mdi_area.subWindowList()[0].widget() computed_channel = { "type": "channel", "common_axis": False, "individual_axis": False, "enabled": True, "mode": "phys", "fmt": "{:.3f}", "format": "phys", "precision": 3, "flags": 0, "ranges": [], "unit": "", "computed": True, "color": "#994380", "uuid": "525ad72a531a", "origin_uuid": "812d7b792168", "group_index": -1, "channel_index": -1, "name": self.id(), "computation": { "args": {}, "type": "python_function", "definition": "", "channel_name": "Function_728d4a149b44", "function": "Function1", "channel_unit": "", "channel_comment": "", "triggering": "triggering_on_all", "triggering_value": "all", "computation_mode": "sample_by_sample", }, } with mock.patch("asammdf.gui.widgets.plot.DefineChannel") as mo_DefineChannel: mo_DefineChannel.return_value.result = computed_channel # Press key Insert QTest.keySequence(self.plot.channel_selection, QKeySequence(self.shortcuts["insert_computation"])) # Evaluate self.assertEqual(2, self.plot.channel_selection.topLevelItemCount()) self.assertEqual(self.plot.channel_selection.topLevelItem(1).name, self.id()) mo_DefineChannel.assert_called() asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/test_PlotWidget_Shortcuts.py000066400000000000000000000767441502633300400275430ustar00rootroot00000000000000#!/usr/bin/env python from unittest import mock from PySide6.QtCore import QPoint, QRect, Qt from PySide6.QtGui import QColor, QKeySequence from PySide6.QtTest import QTest from PySide6.QtWidgets import QMessageBox from asammdf.gui.serde import COLORS from test.asammdf.gui.test_base import Pixmap from test.asammdf.gui.widgets.test_BasePlotWidget import TestPlotWidget class TestPlotShortcuts(TestPlotWidget): def setUp(self): """ Events: - Open measurement file. - Create plot sub-window. - Ensure that signal isn't with dots. - Ensure that there is no grid displayed. - Ensure that there are no bookmarks shown. Evaluate - Evaluate that there is one active sub-window. Returns ------- """ super().setUp() # Open measurement file self.setUpFileWidget(measurement_file=self.measurement_file, default=True) # Switch ComboBox to "Natural sort" self.widget.channel_view.setCurrentText("Natural sort") # Select channels -> Press PushButton "Create Window" -> "Plot" self.create_window(window_type="Plot") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) self.plot = self.widget.mdi_area.subWindowList()[0].widget() # Preset for plot # Remove dots if self.plot.plot.with_dots: self.plot.plot.set_dots(False) # check if grid is available -> hide grid if not self.plot.hide_axes_btn.isFlat(): QTest.mouseClick(self.plot.hide_axes_btn, Qt.MouseButton.LeftButton) # hide bookmarks if it's available if self.plot.show_bookmarks: self.plot.toggle_bookmarks(hide=True) # Ensure that plot is not` in Focused mode if self.plot.focused_mode: self.plot.toggle_focused_mode() # Ensure that plot cursor is not with circle if self.plot.plot.cursor1.show_circle: self.plot.plot.cursor1.show_circle = False # get shortcuts self.assertIsNotNone(self.load_shortcuts_from_json_file(self.plot)) self.processEvents() def tearDown(self): # Ensure that at the end, button "No" is pressed for MessageBox question window with mock.patch("asammdf.gui.widgets.mdi_area.MessageBox.question") as mo_question: mo_question.return_value = QMessageBox.StandardButton.No super().tearDown() def test_statistics_shortcut(self): """ Test Scope: To check if after pressing key "M", info about the selected channel is displayed properly, and after deleting all channels, buffer is clean and info about the last channel isn't displayed, Events:. - Select 3 signals and create a plot. - Press Key "M". - Select First channel. - Pres key "Down". - Delete all channels. Evaluate: - Evaluate that Statistics isn't visible by default. - Evaluate that Statistics is visible after pressing key "M". - Evaluate that displayed info is related to the first channel. - Evaluate that displayed info is related to the second channel. - Evaluate that buffer is clear, so the displayed message is the default one. """ # Setup default_message = "Please select a single channel" # add channels to plot self.assertIsNotNone(self.add_channels([35, 36, 37])) # Evaluate if info isn't visible before pressing key M self.assertFalse(self.plot.info.isVisible()) # Event QTest.keySequence(self.plot, QKeySequence(self.shortcuts["statistics"])) # Evaluate if info is visible after pressing key M self.assertTrue(self.plot.info.isVisible()) # click on a first channel self.mouseClick_WidgetItem(self.channels[0]) # Evaluate with self.subTest("test_key_M_click_on_first_channel"): self.assertEqual(self.plot.info._name, self.channels[0].name) self.assertEqual(self.plot.info.color, self.channels[0].color.name()) # Press key "Down" QTest.keySequence(self.plot.channel_selection, QKeySequence("Down")) # Evaluate with self.subTest("test_key_M_press_key_Down_on_channel_selection"): self.assertEqual(self.plot.info._name, self.channels[1].name) self.assertEqual(self.plot.info.color, self.channels[1].color.name()) # delete all channels QTest.keySequence(self.plot, QKeySequence("Ctrl+A")) QTest.keySequence(self.plot.channel_selection, QKeySequence("Delete")) # Evaluate with self.subTest("test_key_M_delete_all_channels"): # The default message is displayed instead of channel name self.assertNotEqual(self.plot.info._name, default_message) def test_focused_mode_shortcut(self): """ Test Scope: To check if is displayed only selected channel after pressing key "2" Events: - Select 3 signals and create a plot - Press Key "2" - Select first channel - Pres key "Down" - Select third channel Evaluate: - Evaluate that three signals are available. - Evaluate that plot is not black and contains colors of all 3 channels. - Evaluate that plot is black after pressing key "2". - Evaluate that plot contains only color of first channel after clicking on first channel. - Evaluate that plot contains only color of second channel after pressing key "Down". - Evaluate that plot contains only color of third channel after clicked on third channel. - Evaluate that plot contains colors of all 3 channels after pressing key "2". """ # Setup if not self.plot.focused_mode_btn.isFlat(): QTest.mouseClick(self.plot.focused_mode_btn, Qt.MouseButton.LeftButton) # add channels to plot self.assertIsNotNone(self.add_channels([35, 36, 37])) pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertTrue(Pixmap.has_color(pixmap, self.channels[0].color.name())) self.assertTrue(Pixmap.has_color(pixmap, self.channels[1].color.name())) self.assertTrue(Pixmap.has_color(pixmap, self.channels[2].color.name())) # case 0 QTest.keySequence(self.plot, QKeySequence(self.shortcuts["focused_mode"])) self.processEvents(1) for _ in range(100): self.processEvents(0.01) # Evaluate self.assertTrue(Pixmap.is_black(self.plot.plot.viewport().grab())) # case 1 self.mouseClick_WidgetItem(self.channels[0]) for _ in range(50): self.avoid_blinking_issue(self.plot.channel_selection) pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertTrue(Pixmap.has_color(pixmap, self.channels[0].color.name())) self.assertFalse(Pixmap.has_color(pixmap, self.channels[1].color.name())) self.assertFalse(Pixmap.has_color(pixmap, self.channels[2].color.name())) # case 2 QTest.keyClick(self.plot.channel_selection, Qt.Key_Down) for _ in range(50): self.avoid_blinking_issue(self.plot.channel_selection) pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertFalse(Pixmap.has_color(pixmap, self.channels[0].color.name())) self.assertTrue(Pixmap.has_color(pixmap, self.channels[1].color.name())) self.assertFalse(Pixmap.has_color(pixmap, self.channels[2].color.name())) # case 3 self.mouseClick_WidgetItem(self.channels[2]) for _ in range(50): self.avoid_blinking_issue(self.plot.channel_selection) pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertFalse(Pixmap.has_color(pixmap, self.channels[0].color.name())) self.assertFalse(Pixmap.has_color(pixmap, self.channels[1].color.name())) self.assertTrue(Pixmap.has_color(pixmap, self.channels[2].color.name())) # case 4 QTest.keySequence(self.plot, QKeySequence(self.shortcuts["focused_mode"])) self.processEvents(0.1) pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertTrue(Pixmap.has_color(pixmap, self.channels[0].color.name())) self.assertTrue(Pixmap.has_color(pixmap, self.channels[1].color.name())) self.assertTrue(Pixmap.has_color(pixmap, self.channels[2].color.name())) def test_ascii__bin__hex__physical_shortcuts(self): """ Test Scope: Check if values are converted to hex, bin, phys and ascii after pressing the combination of key "Ctrl+||

|" Events: - Display 1 signal on plot. - Press "Ctrl+B". - Press "Ctrl+H". - Press "Ctrl+P". - Press "Ctrl+T". Evaluate: - Evaluate that unit is changed to hex after pressing key "Ctrl+H". - Evaluate that unit is changed to bin after pressing key "Ctrl+B". - Evaluate that unit is changed to phys (int value) after pressing key "Ctrl+P". - Evaluate that unit is changed to ascii after pressing key "Ctrl+T". """ # add channels to plot and select it self.assertIsNotNone(self.add_channels([35])) self.mouseClick_WidgetItem(self.channels[0]) # Store text from the selected channel physical = self.plot.selected_channel_value.text() physical_hours = int(physical.split(" ")[0]) # Press "Ctrl+B" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["bin"])) bin_ = self.plot.selected_channel_value.text() bin_hours = int(bin_.split(" ")[0].replace(".", ""), 2) # Evaluate self.assertNotEqual(physical, bin_) self.assertEqual(physical_hours, bin_hours) # Press "Ctrl+H" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["hex"])) hex_ = self.plot.selected_channel_value.text() # Convert hex value to Int hex_hours = int(hex_.split(" ")[0], 16) # Evaluate self.assertNotEqual(physical, hex_) self.assertIn("0x", hex_) self.assertEqual(physical_hours, hex_hours) # Press "Ctrl+P" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["physical"])) new_physical = self.plot.selected_channel_value.text() new_physical_hours = int(new_physical.split(" ")[0]) # Evaluate self.assertEqual(physical, new_physical) self.assertEqual(physical_hours, new_physical_hours) # Press "Ctrl+P" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["ascii"])) ascii_value = self.plot.selected_channel_value.text() ascii_int = ascii(ascii_value.split(" ")[0]) ascii_int = ascii_int.split("'")[1] ascii_int = "0" + ascii_int.split("\\")[1] ascii_int = int(ascii_int, 16) # Evaluate self.assertNotEqual(physical, ascii_value) self.assertEqual(physical_hours, ascii_int) def test_raw__scaled_samples_shortcuts(self): """ Test Scope: Check functionality of key "Alt+R" and "Alt+S". They must convert samples to raw and scaled forms. Events: - Display 1 signal on plot - Press "Alt+R" - Press "Alt+S" Evaluate: - Evaluate that signal mode is raw and line style is DashLine after pressing key "Alt+R" - Evaluate that signal mode is phys and line style is SolidLine after pressing key "Alt+S" """ # add channels to plot self.assertIsNotNone(self.add_channels(["ASAM.M.SCALAR.SBYTE.LINEAR_MUL_2"])) phys_value = self.plot.selected_channel_value.text().split()[0] expected_raw_value = float(phys_value) / self.channels[0].signal.conversion.a # Press "Alt+R" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["raw_samples"])) self.processEvents(1) # Evaluate # Signal mode = raw self.assertEqual(self.channels[0].mode, "raw") # Signal line style = Dash line self.assertEqual(self.plot.plot.signals[0].pen.style(), Qt.PenStyle.DashLine) # Raw value self.assertEqual(expected_raw_value, float(self.plot.selected_channel_value.text())) # Press "Alt+S" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["scaled_samples"])) self.processEvents(1) # Evaluate # Signal mode = raw self.assertEqual(self.channels[0].mode, "phys") # Signal line style = Dash line self.assertEqual(self.plot.plot.signals[0].pen.style(), Qt.PenStyle.SolidLine) def test_insert_bookmark_shortcut(self): """ Test Scope: Check if bookmark is created after pressing key "Ctrl+I" Events: - Open 'FileWidget' with valid measurement. - Display 1 signal on plot - Press "Ctrl+I" and hit "Ok" Evaluate: - Evaluate that bookmarks are not displayed before pressing "Ctrl+I" - Evaluate that bookmarks are displayed after pressing "Ctrl+I" and the message of the last bookmark is the first element of the returned list of mock object """ QTest.mouseClick( self.plot.plot.viewport(), Qt.MouseButton.LeftButton, pos=self.plot.plot.viewport().geometry().center() ) self.processEvents() timestamp = self.plot.plot.cursor1.value() # mock for bookmark with mock.patch("asammdf.gui.widgets.plot.QtWidgets.QInputDialog.getMultiLineText") as mo_getMultiLineText: mo_getMultiLineText.return_value = [self.id(), True] # Press "Ctrl+I" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["insert_bookmark"])) mo_getMultiLineText.assert_called() # Destroy current widget with mock.patch("asammdf.gui.widgets.mdi_area.MessageBox.question") as mo_question: mo_question.return_value = QMessageBox.StandardButton.Yes self.destroy(self.widget) # Open file with new bookmark in new File Widget self.setUpFileWidget(measurement_file=self.measurement_file, default=True) self.processEvents(0.1) self.widget.channel_view.setCurrentText("Natural sort") # Select channels -> Press PushButton "Create Window" -> "Plot" self.create_window(window_type="Plot") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) self.plot = self.widget.mdi_area.subWindowList()[0].widget() self.processEvents(0.1) pg_colors = Pixmap.color_names_exclude_defaults(self.plot.plot.viewport().grab()) bookmarks_colors = COLORS[: len(COLORS) - len(self.plot.plot.bookmarks) - 1 : -1] # Evaluate self.assertTrue(self.plot.show_bookmarks) self.assertEqual(self.plot.plot.bookmarks[len(self.plot.plot.bookmarks) - 1].message, self.id()) self.assertEqual(self.plot.plot.bookmarks[len(self.plot.plot.bookmarks) - 1].value(), timestamp) for bookmark, color in zip(self.plot.plot.bookmarks, bookmarks_colors, strict=False): self.assertEqual(bookmark.color, color) self.assertIn(color, pg_colors) def test_toggle_bookmarks_shortcut(self): """ Test Scope: Check functionality of key "Ctrl+I". It must toggle bookmarks visibility on plot. Events: - Display 1 signal on plot - Press 3 times "Alt+I" Evaluate: - Evaluate that bookmarks are not displayed before pressing "Alt+I" - Evaluate that bookmarks are displayed after pressing "Alt+I" first time - Evaluate that bookmarks are not displayed after pressing "Alt+I" second time - Evaluate that bookmarks are displayed after pressing "Alt+I" third time """ # Evaluate self.assertFalse(self.plot.show_bookmarks) # Press "Al+I" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["toggle_bookmarks"])) # Evaluate self.assertTrue(self.plot.show_bookmarks) # Press "Al+I" QTest.keySequence(self.plot, QKeySequence(self.shortcuts["toggle_bookmarks"])) # Evaluate self.assertFalse(self.plot.show_bookmarks) def test_edit_y_axis_scaling_shortcut(self): """ Test Scope: Check if signal is changed his Y limits by setting it with ScaleDialog object called with "Ctrl+G" Events: - Create a plot widget with signals - Click on first channel - Press Ctrl+G - Set scaling and offset values - Hit "Ok" Evaluate: - Evaluate that Signal is on top and bottom part of plot - Evaluate that mock object was called - Evaluate that after pressing Ctrl+G, selected channel is situated on top and not on bottom part of plot - Evaluate if y_range of signal is identical with expected range """ # add channels to plot self.assertIsNotNone(self.add_channels([35])) self.processEvents() # Setup offset = 50.0 scale = self.plot.plot.y_axis.range[1] - self.plot.plot.y_axis.range[0] y_bottom = -offset * scale / 100 y_top = y_bottom + scale expected_y_range = y_bottom, y_top # Top pixmap = self.plot.plot.grab(QRect(0, 0, self.plot.plot.width(), int(self.plot.plot.height() / 2))) self.assertTrue(Pixmap.has_color(pixmap, self.channels[0].color.name())) # Bottom pixmap = self.plot.plot.grab( QRect(0, int(self.plot.plot.height() / 2), self.plot.plot.width(), int(self.plot.plot.height() / 2)) ) self.assertTrue(Pixmap.has_color(pixmap, self.channels[0].color.name())) # Click on the first channel self.mouseClick_WidgetItem(self.channels[0]) with mock.patch("asammdf.gui.widgets.plot.ScaleDialog") as mo_ScaleDialog: mo_ScaleDialog.return_value.offset.value.return_value = offset mo_ScaleDialog.return_value.scaling.value.return_value = scale # Press Ctrl+Shift+C QTest.keySequence(self.plot, QKeySequence(self.shortcuts["edit_y_axis_scaling"])) # Evaluate # Evaluate that ScaleDialog object was created, and it's exec() method was called mo_ScaleDialog.return_value.exec.assert_called() self.processEvents(1) # Evaluate y_range tuple self.assertTupleEqual(self.plot.plot.signals[0].y_range, expected_y_range) # Top pixmap = self.plot.plot.grab(QRect(0, 0, self.plot.plot.width(), int(self.plot.plot.height() / 2))) # Evaluate plot, top half of plot must contain channel color self.assertTrue(Pixmap.has_color(pixmap, self.channels[0].color.name())) # Bottom pixmap = self.plot.plot.grab( QRect(0, int(self.plot.plot.height() / 2 + 2), self.plot.plot.width(), int(self.plot.plot.height() / 2 - 2)) ) # Evaluate plot, bottom half of plot must not contain channel color self.assertFalse(Pixmap.has_color(pixmap, self.channels[0].color.name())) def test_color_shortcut(self): """ Test Scope: - Ensure that channel color is changed. Events: - Open Plot with two channels. - Press C. - Select one channel -> press C. - Select all channels -> press C. Evaluate: - Evaluate that color dialog is not open if the channel is not selected. - Evaluate that channel color is changed only for the selected channel. """ # add channels to plot self.assertIsNotNone(self.add_channels([35, 36, 37])) with self.subTest("test_WOSelectedChannel"): with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: QTest.keySequence(self.plot, QKeySequence(self.shortcuts["set_color"])) mo_getColor.assert_not_called() with self.subTest("test_1SelectedChannel"): with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: # Setup self.mouseClick_WidgetItem(self.channels[1]) previous_color = self.channels[1].color.name() color = QColor("magenta") mo_getColor.return_value = color # Event QTest.keySequence(self.plot, QKeySequence(self.shortcuts["set_color"])) # Evaluate mo_getColor.assert_called() self.assertNotEqual(previous_color, self.channels[1].color.name()) self.assertEqual(color.name(), self.channels[1].color.name()) with self.subTest("test_AllSelectedChannel"): with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: # Setup color = QColor("black") mo_getColor.return_value = color # Set selected both channels QTest.keySequence(self.plot.channel_selection, QKeySequence("Ctrl+A")) # store previous colors of channels previous_ch_35_color = self.channels[0].color.name() previous_ch_36_color = self.channels[1].color.name() previous_ch_37_color = self.channels[2].color.name() color = QColor("black") mo_getColor.return_value = color # Event QTest.keySequence(self.plot, QKeySequence(self.shortcuts["set_color"])) # Evaluate mo_getColor.assert_called() self.assertNotEqual(previous_ch_35_color, self.channels[0].color.name()) self.assertNotEqual(previous_ch_36_color, self.channels[1].color.name()) self.assertNotEqual(previous_ch_37_color, self.channels[2].color.name()) self.assertEqual(color.name(), self.channels[0].color.name()) self.assertEqual(color.name(), self.channels[1].color.name()) self.assertEqual(color.name(), self.channels[2].color.name()) def test_copy__paste_channel_structure_shortcut(self): """ Test Scope: - Ensure that selected channel is copied to clipboard and pasted into a plot. Events: - Open Plot with 2 channels - Select first channel - Press Ctrl+C - Press Ctrl+V - Open new plot window - Press Ctrl+V Evaluate: - Evaluate that is one more channel in channel selection area with the same properties as selected channel - Evaluate that channel is inserted in new window with the same properties """ # add channels to plot self.assertIsNotNone(self.add_channels([35, 36])) self.mouseClick_WidgetItem(self.channels[0]) # Press Ctrl+C -> Ctrl+V QTest.keySequence(self.plot, QKeySequence(self.shortcuts["copy_channel_structure"])) QTest.keySequence(self.plot, QKeySequence(self.shortcuts["paste_channel_structure"])) self.processEvents() # Evaluate that now is three channels available self.assertEqual(3, self.plot.channel_selection.topLevelItemCount()) original_name = self.channels[0].name original_color_name = self.channels[0].color.name() original_origin_uuid = self.channels[0].origin_uuid original_signal = self.channels[0].signal replica = self.plot.channel_selection.topLevelItem(1) # Evaluate channels essential attributes self.assertEqual(original_name, replica.name) self.assertEqual(original_color_name, replica.color.name()) self.assertEqual(original_origin_uuid, replica.origin_uuid) self.assertEqual(original_signal, replica.signal) # Uncheck channels ch = self.find_channel(self.widget.channels_tree, self.channels[0].name) ch.setCheckState(0, Qt.CheckState.Unchecked) ch = self.find_channel(self.widget.channels_tree, self.channels[1].name) ch.setCheckState(0, Qt.CheckState.Unchecked) # Press PushButton "Create Window" -> "Plot" self.create_window(window_type="Plot") # Evaluate that second window is created self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) # Second window self.plot = self.widget.mdi_area.subWindowList()[1].widget() # Press Ctrl+V QTest.keySequence(self.plot, QKeySequence(self.shortcuts["paste_channel_structure"])) self.processEvents() # Evaluate that now is three channels available self.assertEqual(1, self.plot.channel_selection.topLevelItemCount()) replica = self.plot.channel_selection.topLevelItem(0) # Evaluate channels essential attributes self.assertEqual(original_name, replica.name) self.assertEqual(original_color_name, replica.color.name()) self.assertEqual(original_origin_uuid, replica.origin_uuid) self.assertEqual(original_signal, replica.signal) def test_copy__paste_display_properties_shortcuts(self): """ Test Scope: Check if only display properties of selected channels is copied on another channel by shortcuts "Ctrl+ShiftC"->"Ctrl+Shift+V" Events: - Select 2 signals and create a plot - Click on first channel - Press key Ctrl+Shift+C - Click on second channel - Press key Ctrl+Shift+V Evaluate: - Evaluate that names and colors are different for both channels - Evaluate that after pressing shortcuts combination, names are different, but colors are the same for both channels """ # add channels to plot self.assertIsNotNone(self.add_channels([35, 36, 37])) # Evaluate precondition self.assertNotEqual(self.channels[1].name, self.channels[2].name) self.assertNotEqual(self.channels[1].color.name(), self.channels[2].color.name()) # Click on channel 36 self.mouseClick_WidgetItem(self.channels[1]) # Press Ctrl+Shift+C QTest.keySequence(self.plot, QKeySequence(self.shortcuts["copy_display_properties"])) self.mouseClick_WidgetItem(self.channels[2]) QTest.keySequence(self.plot, QKeySequence(self.shortcuts["paste_display_properties"])) # Evaluate self.assertNotEqual(self.channels[1].name, self.channels[2].name) self.assertEqual(self.channels[1].color.name(), self.channels[2].color.name()) self.assertEqual(self.channels[1].precision, self.channels[2].precision) self.assertEqual(self.channels[1].format, self.channels[2].format) self.assertEqual(self.channels[1].signal.y_link, self.channels[2].signal.y_link) self.assertEqual(self.channels[1].signal.individual_axis, self.channels[2].signal.individual_axis) self.assertListEqual(self.channels[1].ranges, self.channels[2].ranges) self.assertEqual(self.channels[1].signal.y_range[0], self.channels[2].signal.y_range[0]) self.assertEqual(self.channels[1].signal.y_range[1], self.channels[2].signal.y_range[1]) def test_increase__decrease_font_shortcuts(self): """ Test scope: Ensure that Ctrl+[ and Ctrl+] will change font size Events: - Press Ctrl+[ - Press Ctrl+] Evaluate: - Evaluate that font size was increased after shortcut Ctrl+[ was pressed - Evaluate that font size was decreased after shortcut Ctrl+] was pressed """ font_size = self.plot.font().pointSize() QTest.keySequence(self.plot, QKeySequence(self.shortcuts["decrease_font"])) self.assertLess(font_size, self.plot.font().pointSize()) font_size = self.plot.font().pointSize() QTest.keySequence(self.plot, QKeySequence(self.shortcuts["increase_font"])) self.assertGreater(font_size, self.plot.font().pointSize()) def test_navigate_trough_zoom_history_shortcuts(self): """ Test Scope: Test functionality of keys Backspace, Shift+Backspace, Shift+W. Those keys must change zoom history Events: - Add one channel to plot - Perform some zoom actions - Press key Backspace - Press Shift+backspace - Press Shift+W Evaluate: - Evaluate that after pressing keys "Shift+W", y_range is equal with y_range at start - Evaluate that after pressing keys "Shift+Backspace", y_range is equal with y_range after zoom action - Evaluate that after pressing key "Backspace", y_range isn't equal with previous ranges """ # Setup if not self.plot.focused_mode_btn.isFlat(): QTest.mouseClick(self.plot.focused_mode_btn, Qt.MouseButton.LeftButton) self.plot.plot.viewbox.menu.set_x_zoom_mode() self.plot.plot.viewbox.menu.set_y_zoom_mode() self.plot.plot.viewbox.setMouseMode(self.plot.plot.viewbox.PanMode) self.plot.plot.setFocus() self.processEvents(0.1) # add channel to plot self.assertIsNotNone(self.add_channels([35])) x = round(self.plot.plot.width() / 2) y = round(self.plot.plot.height() / 2) # Y range at start y_range = self.plot.plot.signals[0].y_range # Events self.mouseClick_WidgetItem(self.channels[0]) self.avoid_blinking_issue(self.plot.channel_selection) # Click in the center of the plot QTest.mouseClick( self.plot.plot.viewport(), Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier, QPoint(int(x), int(y)), ) self.processEvents(0.01) # Rotate mouse wheel self.wheel_action(self.plot.plot.viewport(), x, y, 2) self.processEvents(0.01) # Click on plot QTest.mouseClick( self.plot.plot.viewport(), Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier, QPoint(int(x * 0.5), int(y * 0.8)), ) self.processEvents(0.01) # Rotate mouse wheel self.wheel_action(self.plot.plot.viewport(), x, y, -3) self.processEvents(1) self.processEvents(0.1) new_y_range = self.plot.plot.signals[0].y_range # Evaluate self.assertNotEqual(new_y_range, y_range) # click on Backspace QTest.keySequence(self.plot, QKeySequence(self.shortcuts["undo_zoom"])) self.processEvents() undo_zoom_y_range = self.plot.plot.signals[0].y_range # click on Shift + Backspace QTest.keySequence(self.plot, QKeySequence(self.shortcuts["redo_zoom"])) self.processEvents() redo_zoom_y_range = self.plot.plot.signals[0].y_range # click on Shift + W QTest.keySequence(self.plot, QKeySequence(self.shortcuts["x_default_zoom"])) self.processEvents() default_zoom_y_range = self.plot.plot.signals[0].y_range # Evaluate # Shift+W self.assertEqual(y_range[0], default_zoom_y_range[0]) self.assertEqual(y_range[1], default_zoom_y_range[1]) # Shift + Backspace self.assertEqual(new_y_range[0], redo_zoom_y_range[0]) self.assertEqual(new_y_range[1], redo_zoom_y_range[1]) # Backspace self.assertNotIn(undo_zoom_y_range[0], [y_range[0], new_y_range[0]]) self.assertNotIn(undo_zoom_y_range[1], [y_range[1], new_y_range[1]]) asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/test_Tabular_BaseWidget_Shortcuts.py000066400000000000000000000350301502633300400311300ustar00rootroot00000000000000#!/usr/bin/env python\ from os import path from pathlib import Path from sys import platform from unittest import mock, skipIf import numpy from PySide6 import QtGui, QtTest from PySide6.QtCore import QPoint, QRect from PySide6.QtWidgets import QApplication from asammdf import mdf from test.asammdf.gui.test_base import Pixmap from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget class TestDataTableViewShortcuts(TestFileWidget): def setUp(self): """ Events: - Open valid measurement file in ASAMMDF - Create a Tabular window with two channels on it Evaluate: - Evaluate that is one active sub-window Returns ------- """ super().setUp() # Open measurement file measurement_file = str(Path(self.resource, "ASAP2_Demo_V171.mf4")) # Open measurement file self.setUpFileWidget(measurement_file=measurement_file, default=True) # Create a tabular window self.create_window(window_type="Tabular", channels_indexes=(35, 36)) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) self.tabular = self.widget.mdi_area.subWindowList()[0].widget() self.dtw = self.tabular.tree.dataView # Load shortcuts self.assertIsNotNone(self.load_shortcuts_from_json_file(self.dtw)) self.processEvents(0.01) def test_set_color_range_shortcut(self): """ Test Scope: Ensure that after pressing key Ctrl+R, range editor will be triggered Events: - Click on first channel - Press Ctrl+R - Add range - Ok Evaluate: - Evaluate that range editor was triggered after pressing key Ctrl+R - Evaluate that range was applied for only for selected signal - Evaluate that only cells with value within range are colored Returns ------- """ # Setup col = 1 value1 = 0.0 value2 = 150.0 self.processEvents() green = QtGui.QColor.fromRgbF(0.000000, 1.000000, 0.000000, 1.000000) green_brush = QtGui.QBrush(green, QtGui.Qt.SolidPattern) red = QtGui.QColor.fromRgbF(1.000000, 0.000000, 0.000000, 1.000000) red_brush = QtGui.QBrush(red, QtGui.Qt.SolidPattern) range_editor_result = [ { "background_color": green_brush, "font_color": red_brush, "op1": "<", "op2": "<", "value1": value1, "value2": value2, } ] # Select first row self.dtw.selectColumn(col) # QtTest.QTest.keySequence(self.dtw, QtGui.QKeySequence(self.shortcuts["set_color_range"])) self.processEvents() with mock.patch("asammdf.gui.widgets.tabular_base.RangeEditor") as mo_RangeEditor: mo_RangeEditor.return_value.result = range_editor_result mo_RangeEditor.return_value.pressed_button = "apply" # Press "Ctrl+R" QtTest.QTest.keySequence(self.dtw, QtGui.QKeySequence(self.shortcuts["set_color_range"])) self.processEvents() self.dtw.selectColumn(col) self.processEvents(0.01) # Evaluate mo_RangeEditor.assert_called() col_0 = True for value in self.tabular.ranges.values(): if col_0 is True: # Evaluate range for first row self.assertDictEqual(value[0], range_editor_result[0]) col_0 = False else: self.assertListEqual(value, []) # Evaluate cell color row = 0 # Find regular cell for row in range(self.dtw.pgdf.df.values.size - 1): if self.dtw.pgdf.df.values[row][1] > value2: break # GoTo regular row self.dtw.selectRow(row) self.dtw.selectRow(row) self.processEvents(0.01) # Cell to evaluate pm = self.dtw.grab( QRect( self.dtw.columnViewportPosition(col), self.dtw.rowViewportPosition(row), self.dtw.columnWidth(col), self.dtw.rowHeight(row), ) ) # Evaluate self.assertFalse(Pixmap.has_color(pm, red)) self.assertFalse(Pixmap.has_color(pm, green)) # Find colored row for row in range(self.dtw.pgdf.df.values.size - 1): if value1 < self.dtw.pgdf.df.values[row][1] < value2: break # GoTo colored row self.dtw.selectRow(row) self.dtw.selectRow(row) self.processEvents(0.01) # Cell to evaluate pm = self.dtw.grab( QRect( self.dtw.columnViewportPosition(col), self.dtw.rowViewportPosition(row), self.dtw.columnWidth(col), self.dtw.rowHeight(row), ) ) # Evaluate self.assertTrue(Pixmap.has_color(pm, green)) self.assertTrue(Pixmap.has_color(pm, red)) class TestTabularBaseShortcuts(TestFileWidget): def setUp(self): """ Events: - Open valid measurement file in ASAMMDF - Create a Tabular window with two channels on it Evaluate: - Evaluate that is one active sub-window Returns ------- """ super().setUp() # Open measurement file measurement_file = str(Path(self.resource, "ASAP2_Demo_V171.mf4")) # Open measurement file self.setUpFileWidget(measurement_file=measurement_file, default=True) self.create_window(window_type="Tabular", channels_indexes=(35, 36)) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) self.tabular = self.widget.mdi_area.subWindowList()[0].widget() self.assertIsNotNone(self.load_shortcuts_from_json_file(self.tabular)) self.processEvents(0.01) def test_bin__hex__physical_shortcuts(self): """ Test scope: Ensure that data format is changed after pressing keys - Ctrl+B -> to binary - Ctrl+H -> to hexadecimal - Ctrl+P -> to physical Events: - Press Ctrl+H - Press Ctrl+B - Press Ctrl+P Evaluate: - Evaluate that data format and value were changed to bin after pressing key Ctrl+H - Evaluate that data format and value were changed to hex after pressing key Ctrl+B - Evaluate that data format and value were changed to physical after pressing key Ctrl+P Returns ------- """ # Setup self.tabular.set_format("phys") data_view = self.tabular.tree.dataView # index for first cell of first signal index = data_view.indexAt(QPoint(data_view.columnViewportPosition(1), data_view.rowViewportPosition(0))) self.processEvents(0.01) # Store value from cell data = data_view.model().data(index) # Event # Press Ctrl+H QtTest.QTest.keySequence(self.tabular, QtGui.QKeySequence(self.shortcuts["hex"])) self.processEvents(0.1) # Store value from cell hex_data = data_view.model().data(index) # Evaluate self.assertEqual(self.tabular.format, "hex") self.assertIn("0x", hex_data) self.assertEqual(int(hex_data, 16), int(data)) # Event # Press Ctrl+B QtTest.QTest.keySequence(self.tabular, QtGui.QKeySequence(self.shortcuts["bin"])) self.processEvents(0.1) # Store value from cell bin_data = data_view.model().data(index) # Evaluate self.assertEqual(self.tabular.format, "bin") self.assertIn(".", bin_data) self.assertEqual(int(bin_data.replace(".", ""), 2), int(data)) # Event # Press Ctrl+P QtTest.QTest.keySequence(self.tabular, QtGui.QKeySequence(self.shortcuts["physical"])) self.processEvents(0.1) # Store value from cell phys_data = data_view.model().data(index) # Evaluate self.assertEqual(self.tabular.format, "phys") self.assertTrue(phys_data.isdecimal()) self.assertEqual(int(phys_data), int(data)) def test_save_active_subplot_channels_shortcut(self): """ Test scope: Ensure that window Save as file was called and all active subplots were saved into a new file Events: - Open second sub-window - Select first one - Press Ctrl+S - Set new name for file and click "Save" button Evaluate: - Evaluate that there are two active sub-windows - Evaluate that "Save as file" window was called - Evaluate that in new saved file is only channels from selected active sub-window Returns ------- """ # Setup self.create_window(window_type="Tabular", channels_indexes=(10, 11)) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) self.processEvents() expected_channels = ["time"] for key in self.tabular.ranges.keys(): expected_channels.append(key) file_path = path.join(self.test_workspace, "file.mf4") # mock for getSaveFileName object with mock.patch("asammdf.gui.widgets.tabular_base.QtWidgets.QFileDialog.getSaveFileName") as mo_getSaveFileName: mo_getSaveFileName.return_value = (file_path, "") # Press Ctrl+S QtTest.QTest.keySequence(self.tabular, QtGui.QKeySequence(self.shortcuts["save_active_subplot_channels"])) # Evaluate mo_getSaveFileName.assert_called() # get saved file as MDF process_bus_logging = ("process_bus_logging", True) mdf_file = mdf.MDF(file_path, process_bus_logging=process_bus_logging) # Evaluate for name in mdf_file.channels_db.keys(): self.assertIn(name, expected_channels) expected_channels.remove(name) self.assertEqual(len(expected_channels), 0) mdf_file.close() def test_increase__decrease_font_shortcuts(self): """ Test scope: Ensure that Ctrl+[ and Ctrl+] will change font size Events: - Press Ctrl+[ - Press Ctrl+] Evaluate: - Evaluate that font size was increased after shortcut Ctrl+[ was pressed - Evaluate that font size was decreased after shortcut Ctrl+] was pressed """ font_size = self.tabular.tree.dataView.font().pointSize() QtTest.QTest.keySequence(self.tabular, QtGui.QKeySequence(self.shortcuts["decrease_font"])) self.assertLess(font_size, self.tabular.tree.dataView.font().pointSize()) font_size = self.tabular.tree.dataView.font().pointSize() QtTest.QTest.keySequence(self.tabular, QtGui.QKeySequence(self.shortcuts["increase_font"])) self.assertGreater(font_size, self.tabular.tree.dataView.font().pointSize()) @skipIf(platform != "win32", "Failed on linux. Shortcut can copy only value for one cell") class TestDataFrameViewerShortcuts(TestFileWidget): def setUp(self): """ Events: - Open valid measurement file in ASAMMDF - Create a Tabular window with two channels on it Evaluate: - Evaluate that is one active sub-window Returns ------- """ super().setUp() # Open measurement file measurement_file = str(Path(self.resource, "ASAP2_Demo_V171.mf4")) # Open measurement file self.setUpFileWidget(measurement_file=measurement_file, default=True) self.create_window(window_type="Tabular", channels_indexes=(35, 36)) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) self.tabular = self.widget.mdi_area.subWindowList()[0].widget() self.dfw = self.tabular.tree self.assertIsNotNone(self.load_shortcuts_from_json_file(self.dfw)) self.processEvents(0.01) def test_copy_shortcut(self): """ Test scope: Ensure that Ctrl+C shortcut will copy value from selected row to clipboard Events: - Select one row. - Press Ctrl+C. Evaluate: - Evaluate that value from the selected row was copied to clipboard after shortcut Ctrl+C was pressed. Returns ------- """ def copy_header(): df = self.dfw.pgdf.df copied_values = "" for name in df.columns: copied_values += "\t" + name return copied_values + "\n" def copy_row(r): df = self.dfw.pgdf.df fp = self.dfw.dataView.model().float_precision copied_values = "" for name in df.columns: x = df[name][r] # if x == r: # continue if isinstance(x, numpy.floating): if fp != -1: x = f"\t{x:.16f}" else: x = f"\t{x:.16f}" else: x = f"\t{x}" copied_values += x return copied_values + "\n" # -|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|- # Setup row = 0 expected_data = copy_header() + "0" + copy_row(row) # Event self.dfw.dataView.selectRow(row) self.processEvents(0.1) QtTest.QTest.keySequence(self.dfw, QtGui.QKeySequence(self.shortcuts["copy"])) self.processEvents(1) data = QApplication.instance().clipboard().text() # Test failed, because of clipboard buffer on linux # Evaluate self.assertEqual(expected_data, data) # -|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|- # Setup 2 expected_data = copy_header() for row in range(len(self.dfw.pgdf.df.values)): expected_data += str(row) + copy_row(row) # Event 2 QtTest.QTest.keySequence(self.dfw, QtGui.QKeySequence("Ctrl+A")) self.processEvents() QtTest.QTest.keySequence(self.dfw, QtGui.QKeySequence(self.shortcuts["copy"])) self.processEvents(1) data = QApplication.instance().clipboard().text() # Evaluate self.assertEqual(expected_data, data) asammdf-8.5.1/test/asammdf/gui/widgets/Shortcuts/test_TreeWidget_Shortcuts.py000066400000000000000000000603061502633300400275070ustar00rootroot00000000000000#!/usr/bin/env python\ import pathlib from unittest import mock from PySide6.QtCore import QPoint from PySide6.QtGui import QColor, QKeySequence, Qt from PySide6.QtTest import QTest from PySide6.QtWidgets import QTreeWidgetItemIterator from test.asammdf.gui.test_base import OpenMDF, Pixmap from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget from test.asammdf.gui.widgets.test_BasePlotWidget import TestPlotWidget class TestTreeWidgetShortcuts(TestFileWidget): def setUp(self): """ Events: - Open measurement file Returns ------- """ super().setUp() # Open measurement file measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Open measurement file self.setUpFileWidget(measurement_file=measurement_file, default=True) self.tw = self.widget.channels_tree # TreeWidget # get shortcuts self.assertIsNotNone(self.load_shortcuts_from_json_file(self.tw)) def test_toggle_select_channel_shortcut(self): """ Test scope: Check if by pressing key Space, check status of tree item is changed Events: - Select all even channels and press key Space - Select the same channels and press again key Space Evaluate: - Evaluate that check state of all channels is "Unchecked" at start - Evaluate that check state of even channels is "Checked" after even channels became selected and key Space is pressed - Evaluate that check state of all channels is "Unchecked" after even channels became selected second time and key Space is pressed Returns ------- """ items_count = self.tw.topLevelItemCount() for _ in range(items_count - 1): # Evaluate that all items is ... self.assertEqual(self.tw.topLevelItem(_).checkState(0), Qt.CheckState.Unchecked) # Select all impar items and hit the Space key if _ % 2 == 1: self.tw.topLevelItem(_).setSelected(True) QTest.keySequence(self.tw, QKeySequence(self.shortcuts["toggle_check_state"])) self.tw.topLevelItem(_).setSelected(False) self.processEvents() # Evaluate that all impar items are checked for _ in range(items_count - 1): if _ % 2 == 1: self.assertEqual(self.tw.topLevelItem(_).checkState(0), Qt.CheckState.Checked) # Select item and hit again the Space key self.tw.topLevelItem(_).setSelected(True) QTest.keySequence(self.tw, QKeySequence(self.shortcuts["toggle_check_state"])) self.tw.topLevelItem(_).setSelected(False) else: self.assertEqual(self.tw.topLevelItem(_).checkState(0), Qt.CheckState.Unchecked) # Evaluate that all items are unchecked for _ in range(items_count - 1): self.assertEqual(self.tw.topLevelItem(_).checkState(0), Qt.CheckState.Unchecked) class TestChannelsTreeWidgetShortcuts(TestPlotWidget): """ Tests for Ctrl+C, Ctrl+V was tested in test_PlotWidget_Shortcuts """ def setUp(self): """ Events: - Open measurement file - Create a plot window Returns ------- """ super().setUp() # Open measurement file measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Open measurement file self.setUpFileWidget(measurement_file=measurement_file, default=True) # Select channels -> Press PushButton "Create Window" -> "Plot" self.create_window(window_type="Plot") self.ctw = self.widget.mdi_area.subWindowList()[0].widget().channel_selection # ChannelsTreeWidget # get shortcuts self.assertIsNotNone(self.load_shortcuts_from_json_file(self.ctw)) def test_delete_shortcut(self): """ Test Scope: - Ensure that key Delete will remove selected channels. Events: - Add some channels to plot. - Select first item and press key Delete. - Select all items and press key delete. Evaluate: - Evaluate that there are all items added to plot. - Evaluate that first item is removed from a list after it became selected and key Delete is pressed. - Evaluate that all items after they became selected are removed by pressing key delete. Returns ------- """ self.assertIsNotNone(self.add_channels([10, 11, 12, 13])) channel_count = self.ctw.topLevelItemCount() # Click on last channel channel_0 = self.channels.pop() self.mouseClick_WidgetItem(channel_0) # Press key Delete QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["delete_items"])) # Evaluate self.assertEqual(self.ctw.topLevelItemCount(), channel_count - 1) iterator = QTreeWidgetItemIterator(self.ctw) while item := iterator.value(): self.assertNotEqual(channel_0, item) iterator += 1 # select all items QTest.keySequence(self.ctw, QKeySequence("Ctrl+A")) # Press key Delete QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["delete_items"])) # Evaluate self.assertEqual(self.ctw.topLevelItemCount(), 0) def test_add_pattern_based_channel_group_shortcut(self): """ Test Scope: Check if a new pattern-based channel group can be created by pressing shortcut "Ctrl+Insert" Events: - Press "Ctrl+Insert" - Simulate dialog window fill with: "pattern": f"*{Filter}*", "match_type": "Wildcard", "case_sensitive": False, "filter_type": "Unspecified", "filter_value": 0.0, "raw": False, "ranges": [], "name": "Matrix", "integer_format": "phys". Evaluate: - Evaluate that method exec_() of AdvancedSearch object was called. - Evaluate that in plot channel selection exists a new group with specific name and pattern dict. - Evaluate that group contains all channels from measurement with a specific sequence of string in their name. """ group_name = "Matrix" result = { "pattern": f"*{group_name}*", "match_type": "Wildcard", "case_sensitive": False, "filter_type": "Unspecified", "filter_value": 0.0, "raw": False, "ranges": [], "name": f"{group_name}", "integer_format": "phys", } # mock for QInputDialog object with mock.patch("asammdf.gui.widgets.tree.AdvancedSearch") as mo_AdvancedSearch: mo_AdvancedSearch.return_value.result = result # Press Ctrl+Insert QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["add_pattern_based_group"])) # Evaluate mo_AdvancedSearch.return_value.exec_.assert_called() self.assertEqual(1, self.ctw.topLevelItemCount()) group = self.ctw.topLevelItem(0) self.assertEqual(group.name, result["name"]) self.assertDictEqual(group.pattern, result) # Store all channels names from a group in a list group_channels_name = [channel.name for channel in group.get_all_channel_items()] # Store all channels with specific pattern in their names in a list items = [] with OpenMDF(self.measurement_file) as mdf: items.extend(ch.name for ch in mdf.iter_channels() if group_name.upper() in ch.name.upper()) self.assertEqual(len(group_channels_name), len(items)) for channel_name in group_channels_name: self.assertIn(channel_name, items) # To avoid duplicates items.remove(channel_name) def test_add_channel_group(self): """ Test Scope: Check if a new channel group can be created by pressing shortcut "Shift+Insert" Events: - Press "Shift+Insert" - Type some text and press "Ok" Evaluate: - Evaluate that method getText() of QInputDialog object was called - Evaluate that in plot channel selection exist new group with specific name """ # mock for QInputDialog object with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog") as mo_QInputDialog: mo_QInputDialog.getText.return_value = (self.id(), True) # Press Shift+Insert QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["add_channel_group"])) # Evaluate mo_QInputDialog.getText.assert_called() self.assertEqual(self.ctw.topLevelItem(0).name, self.id()) def test_select_channel_shortcut(self): """ Test scope: Ensure that key Space change checks state for selected item. Events: - Add few channels to plot - Click on first channel -> press key Space. - Click on rest channels -> press key Space. - Click in first channel -> press key Space. Evaluate - Evaluate that all items are checked by default. - Evaluate that by selecting one item from a list and pressing key space, it states became "Unchecked". - Evaluate that by selecting all checked items and pressing key space, its states became "Unchecked". - Evaluate that by selecting one unchecked item and pressing key space, it states became "Checked". Returns ------- """ self.assertIsNotNone(self.add_channels([10, 11, 12, 13])) iterator = QTreeWidgetItemIterator(self.ctw) while item := iterator.value(): self.assertEqual(item.checkState(0), Qt.CheckState.Checked) iterator += 1 # Select click on first item -> press key space self.mouseClick_WidgetItem(self.ctw.topLevelItem(0)) QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["toggle_check_state"])) self.assertEqual(self.ctw.topLevelItem(0).checkState(0), Qt.CheckState.Unchecked) for _ in range(1, self.ctw.topLevelItemCount()): self.mouseClick_WidgetItem(self.ctw.topLevelItem(_)) QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["toggle_check_state"])) iterator = QTreeWidgetItemIterator(self.ctw) while item := iterator.value(): self.assertEqual(item.checkState(0), Qt.CheckState.Unchecked) iterator += 1 # Select click on first item -> press key space self.mouseClick_WidgetItem(self.ctw.topLevelItem(0)) QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["toggle_check_state"])) self.assertEqual(self.ctw.topLevelItem(0).checkState(0), Qt.CheckState.Checked) def test_color_shortcut(self): """ Test Scope: - Ensure that channel color is changed. Events: - Add 2 channels to Plot. - Press C - Select 1 Channel -> Press C - Select 2 Channels -> Press C Evaluate: - Evaluate that there is successful added channels to plot. - Evaluate that color dialog is not open if channel is not selected. - Evaluate that channel color is changed only for a selected channel. """ self.assertIsNotNone(self.add_channels([10, 11, 12])) with self.subTest("test_WOSelectedChannel"): with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["set_color"])) mo_getColor.assert_not_called() with self.subTest("test_1SelectedChannel"): with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: # Setup self.mouseClick_WidgetItem(self.channels[0]) previous_color = self.channels[0].color.name() color = QColor("magenta") mo_getColor.return_value = color # Event QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["set_color"])) # Evaluate mo_getColor.assert_called() self.assertNotEqual(previous_color, self.channels[0].color.name()) self.assertEqual(color.name(), self.channels[0].color.name()) with self.subTest("test_allSelectedChannel"): with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: # Setup # Set selected both channels QTest.keySequence(self.ctw, QKeySequence("Ctrl+A")) # store previous colors of channels previous_ch_colors = [channel.color.name() for channel in self.channels] color = QColor("cyan") if "#00FFFF" not in previous_ch_colors else QColor("black") mo_getColor.return_value = color # Event QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["set_color"])) # Evaluate mo_getColor.assert_called() for channel in self.channels: self.assertNotIn(channel.color.name(), previous_ch_colors) self.assertEqual(channel.color.name(), color.name()) def test_copy_display_properties_shortcut(self): """ Test Scope: - Ensure that key "Ctrl+Shift+C" can copy display properties of selected item Events: - Open Plot with one channel - Select this channel - Press Ctrl+Shift+C Evaluate: - Evaluate that there is added one item to plot - Evaluate that in clipboard is display properties of selected item """ self.assertIsNotNone(self.add_channels([10])) # Evaluate precondition ch_0_display_properties = self.ctw.topLevelItem(0).get_display_properties() with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QApplication.instance") as mo_instance: # Click on a first channel self.mouseClick_WidgetItem(self.channels[0]) # Press Ctrl+Shift+C QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["copy_display_properties"])) # Evaluate mo_instance.return_value.clipboard.return_value.setText.assert_called_with(ch_0_display_properties) def test_paste_display_properties_shortcut(self): """ Test Scope: - Ensure that key "Ctrl+Shift+V" can paste from clipboard display properties to selected item. Events: - Open Plot with two channels. - Copy display properties of the first item. - Select second item -> press Ctrl+Shift+C. Evaluate: - Evaluate that to plot are added two items. - Evaluate that display properties of channels are not identical. - Evaluate that after selecting second channel and hit keys "Ctrl+Shift+V", the second channel has the same display properties with the first channel. """ self.assertIsNotNone(self.add_channels([10, 11])) # Evaluate precondition ch_0_display_properties = self.ctw.topLevelItem(0).get_display_properties() self.assertNotEqual(ch_0_display_properties, self.ctw.topLevelItem(1).get_display_properties()) with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QApplication.instance") as mo_instance: mo_instance.return_value.clipboard.return_value.text.return_value = ch_0_display_properties # Click on a first channel self.mouseClick_WidgetItem(self.channels[1]) # Press Ctrl+Shift+C QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["paste_display_properties"])) # Evaluate mo_instance.return_value.clipboard.return_value.text.assert_called() self.assertEqual( self.ctw.topLevelItem(0).get_display_properties(), self.ctw.topLevelItem(1).get_display_properties() ) def test_copy_names_shortcut(self): """ Test Scope: - Ensure that key "Ctrl+Shift+V" can paste from clipboard display properties to selected item. Events: - Open Plot with few channels. - Select first item -> press Ctrl+N. - Select all items -> press Ctrl+N. Evaluate: - Evaluate that to plot are added few items. - Evaluate that after selecting one channel and pressing key Ctrl+N, in clipboard is added it name. - Evaluate that after selecting all channels and pressing key Ctrl+N, in clipboard is added items names. Returns ------- """ self.assertIsNotNone(self.add_channels([10, 11, 12, 13])) expected_cb_all_items_call = "" iterator = QTreeWidgetItemIterator(self.ctw) while item := iterator.value(): expected_cb_all_items_call += "\n" + item.name iterator += 1 expected_cb_all_items_call = expected_cb_all_items_call.split("\n", 1)[1] channel_0 = self.ctw.topLevelItem(0) with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QApplication.instance") as mo_instance: # Select click on first item -> press key Ctrl+N self.mouseClick_WidgetItem(channel_0) QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["copy_names"])) # Evaluate mo_instance.return_value.clipboard.return_value.setText.assert_called_with(self.ctw.topLevelItem(0).name) # Select all items QTest.keySequence(self.ctw, QKeySequence("Ctrl+A")) # Press key Ctrl+N QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["copy_names"])) # Evaluate mo_instance.return_value.clipboard.return_value.setText.assert_called_with(expected_cb_all_items_call) def test_set_color_range_shortcut(self): """ Test Scope: Check if color range is triggered after pressing key Ctrl+R. Events: - Open 'FileWidget' with valid measurement. - Display 1 signal on plot. - Select signal. - Press "Ctrl+R" -> set ranges from 0 to 40% of y value and colors green and red -> apply. - Click on unchanged color part of signal on plot. - Click on changed color part of signal on plot. - Click Ctrl+G to shift plot from and to 40% of y range. Evaluate: - Evaluate that plot is not black. - Evaluate that plot selected channel value has channel color. - Evaluate RangeEditor object was called. - Evaluate that plot selected channel value area doesn't have red and green colors, only the original one, when the cursor does not intersect the red part of the signal. - Evaluate that after clicking on part that enter in selected ranges, plot selected channel value area has only red and green colors. - Evaluate using Y axis scaling if plot is correctly painted: from 0 to 40% it is red, from 40% is not affected. """ # Setup # add channels to plot self.assertIsNotNone(self.add_channels([35])) plot = self.widget.mdi_area.subWindowList()[0].widget() self.processEvents(0.01) if plot.selected_channel_value_btn.isFlat(): QTest.mouseClick(plot.selected_channel_value_btn, Qt.MouseButton.LeftButton) if not plot.bookmark_btn.isFlat(): QTest.mouseClick(plot.bookmark_btn, Qt.MouseButton.LeftButton) self.mouseClick_WidgetItem(self.channels[0]) plot.plot.set_dots(False) # Evaluate self.assertTrue(Pixmap.has_color(plot.selected_channel_value.grab(), self.channels[0].color.name())) y_range = plot.plot.y_axis.range[1] - plot.plot.y_axis.range[0] offset = 40 red_range = y_range * offset / 100 green = QColor.fromRgbF(0.000000, 1.000000, 0.000000, 1.000000) red = QColor.fromRgbF(1.000000, 0.000000, 0.000000, 1.000000) range_editor_result = [ { "background_color": green, "font_color": red, "op1": "<=", "op2": "<=", "value1": 0.0, "value2": red_range, } ] # Click on channel self.mouseClick_WidgetItem(self.channels[0]) # Sometimes, because small display resolution, mouse click on qItem isn't performed properly on linux if not plot.channel_selection.topLevelItem(0).isSelected(): plot.channel_selection.topLevelItem(0).setSelected(True) self.processEvents(0.01) with mock.patch("asammdf.gui.widgets.tree.RangeEditor") as mo_RangeEditor: mo_RangeEditor.return_value.result = range_editor_result mo_RangeEditor.return_value.pressed_button = "apply" # Press "Alt+R" QTest.keySequence(self.ctw, QKeySequence(self.shortcuts["set_color_range"])) # Evaluate mo_RangeEditor.assert_called() self.assertEqual(self.channels[0].ranges, range_editor_result) self.mouseClick_WidgetItem(self.channels[0]) for _ in range(100): self.processEvents(None) # Displayed signal sig = self.channels[0].signal # Coordinates for viewbox, second dot in the center of visual min_ = med_ = max_ = None for _ in range(len(sig)): if sig.samples[_] == 0 and (sig.samples[_ + 10] - sig.samples[_ - 10]) < (sig.samples.max() / 10): min_ = _ break for _ in range(min_, len(sig)): if sig.samples[_] == red_range: med_ = _ break for _ in range(med_, len(sig)): if sig.samples[_] == sig.samples.max(): max_ = _ break x, y, w, h = sig.timestamps[min_], sig.samples[min_], sig.timestamps[med_], sig.samples[med_] # Set X and Y ranges for viewbox plot.plot.viewbox.setXRange(x, w, padding=0) plot.plot.viewbox.setYRange(y, h, padding=0) self.processEvents(None) # Click in the middle of the plot QTest.mouseClick( plot.plot.viewport(), Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier, QPoint(int(plot.plot.width() / 2), int(plot.plot.height() / 2)), ) self.processEvents(0.1) for _ in range(100): self.processEvents(0.01) selected_channel_value = plot.selected_channel_value.grab() plot_graphics = plot.plot.grab() # Evaluate self.assertTrue(Pixmap.has_color(selected_channel_value, red)) self.assertTrue(Pixmap.has_color(selected_channel_value, green)) self.assertFalse(Pixmap.has_color(selected_channel_value, self.channels[0])) self.assertTrue(Pixmap.has_color(plot_graphics, red)) self.assertFalse(Pixmap.has_color(plot_graphics, self.channels[0])) x, y, w, h = sig.timestamps[med_], sig.samples[med_], sig.timestamps[max_], sig.samples[max_] # Set X and Y ranges for viewbox plot.plot.viewbox.setXRange(x, w, padding=0) plot.plot.viewbox.setYRange(y, h, padding=0) self.processEvents(0.1) # Click in the middle of the plot QTest.mouseClick( plot.plot.viewport(), Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier, QPoint(plot.plot.width() // 2, plot.plot.height() // 2), ) self.processEvents(1) selected_channel_value = plot.selected_channel_value.grab() plot_graphics = plot.plot.grab() # Evaluate self.assertFalse(Pixmap.has_color(selected_channel_value, red)) self.assertFalse(Pixmap.has_color(selected_channel_value, green)) self.assertFalse(Pixmap.has_color(plot_graphics, red)) self.assertTrue(Pixmap.has_color(selected_channel_value, self.channels[0])) self.assertTrue(Pixmap.has_color(plot_graphics, self.channels[0])) asammdf-8.5.1/test/asammdf/gui/widgets/__init__.py000066400000000000000000000000001502633300400220510ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/batch/000077500000000000000000000000001502633300400210335ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/batch/__init__.py000066400000000000000000000000001502633300400231320ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/batch/test_BatchWidget_FilesList.py000066400000000000000000000033301502633300400266060ustar00rootroot00000000000000#!/usr/bin/env python from pathlib import Path from PySide6 import QtCore, QtTest from test.asammdf.gui.widgets.test_BaseBatchWidget import TestBatchWidget # Note: If it's possible and make sense, use self.subTests # to avoid initializing widgets multiple times and consume time. class TestPushButtons(TestBatchWidget): test_file = "test_batch.mf4" def test_PushButtons_Sort(self): """ Events: - Open 'BatchWidget' with 2 valid measurements. - Press PushButton "Sort by start time" - Press PushButton "Sort alphabetically" Evaluate: - Files are sorted by start time - Files are sorted alphabetically """ # Setup file_0 = Path(self.test_workspace, self.default_test_file) file_1 = Path(self.test_workspace, self.test_file) alpha_sort = [str(file_0), str(file_1)] time_sort = [str(file_1), str(file_0)] self.copy_mdf_files_to_workspace() self.setUpBatchWidget(measurement_files=alpha_sort) # Event with self.subTest("test sort by start time btn"): # Press `Sort by start time` button QtTest.QTest.mouseClick(self.widget.sort_by_start_time_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual([self.widget.files_list.item(row).text() for row in range(2)], time_sort) with self.subTest("test sort alphabetically btn"): # Press `Sort by start time` button QtTest.QTest.mouseClick(self.widget.sort_alphabetically_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual([self.widget.files_list.item(row).text() for row in range(2)], alpha_sort) asammdf-8.5.1/test/asammdf/gui/widgets/batch/test_BatchWidget_Tab_BusLogging.py000066400000000000000000000371431502633300400275470ustar00rootroot00000000000000#!/usr/bin/env python import codecs from pathlib import Path import sys from unittest import mock import urllib import urllib.request from zipfile import ZipFile import numpy as np import pandas as pd from PySide6 import QtCore, QtTest from test.asammdf.gui.test_base import DBC, OpenMDF from test.asammdf.gui.widgets.test_BaseBatchWidget import TestBatchWidget # Note: If it's possible and make sense, use self.subTests # to avoid initializing widgets multiple times and consume time. class TestPushButtons(TestBatchWidget): def setUp(self): super().setUp() url = "https://github.com/danielhrisca/asammdf/files/4328945/OBD2-DBC-MDF4.zip" urllib.request.urlretrieve(url, "test.zip") ZipFile(r"test.zip").extractall(self.test_workspace) Path("test.zip").unlink() temp_dir = Path(self.test_workspace) # Get test files path self.mdf_path = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".mf4"][0] self.dbc_path = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".dbc"][0] self.setUpBatchWidget(measurement_files=[str(self.mdf_path)]) # Go to Tab: "Bus logging": Index 3 self.widget.aspects.setCurrentIndex(self.bus_aspect) # Ensure that CAN & LIN lists are empty self.assertEqual(self.widget.can_database_list.count(), 0) self.assertEqual(self.widget.lin_database_list.count(), 0) def load_database(self, path: Path | str | None = None, is_can=True): """ Load database to CAN/LIN database list Parameters ---------- path := path to .dbc file; if None: default .dbc path will be used is_can := CAN or LIN """ if not path: path = self.dbc_path with mock.patch("asammdf.gui.widgets.batch.QtWidgets.QFileDialog.getOpenFileNames") as mo_getOpenFileNames: mo_getOpenFileNames.return_value = [str(path)], None if is_can: QtTest.QTest.mouseClick(self.widget.load_can_database_btn, QtCore.Qt.MouseButton.LeftButton) else: QtTest.QTest.mouseClick(self.widget.load_lin_database_btn, QtCore.Qt.MouseButton.LeftButton) def get_prefix(self): """ Get prefix for channels names. Example: - 'CAN1.OBD2.' Returns ------- prefix: str """ # Prepare expected results # Linux cannot decode using 'utf-8' standard codec with OpenMDF(self.mdf_path) as mdf_file, codecs.open(str(self.dbc_path), encoding="ISO-8859-1") as dbc_file: for key, value in mdf_file.bus_logging_map.items(): if value: prefix = key for new_key, new_value in value.items(): if value: prefix += str(new_key) self.assertTrue(prefix) # there is a suffix for feature channels prefix += "." + DBC.BO(dbc_file.readlines()).name + "." return prefix def test_load_can_database_btn(self): """ Events: - Press Load CAN database button. Evaluate: - There is one item in can database list - The item's text is .dbc path """ # Event self.load_database() # Evaluate self.assertEqual(self.widget.can_database_list.count(), 1) self.assertEqual( self.widget.can_database_list.itemWidget(self.widget.can_database_list.item(0)).database.text(), str(self.dbc_path), ) def test_load_lin_database_btn(self): """ Events: - Press Load LIN database button. Evaluate: - There is one item in lin database list - The item's text is .dbc path """ # Event self.load_database(is_can=False) # Evaluate self.assertEqual(self.widget.lin_database_list.count(), 1) self.assertEqual( self.widget.lin_database_list.itemWidget(self.widget.lin_database_list.item(0)).database.text(), str(self.dbc_path), ) def test_extract_bus_btn(self): """ When QThreads are running, event-loops needs to be processed. Events: - Set prefix text - Press PushButton Extract Bus signals. Evaluate: - File was created. - New channels was created from .dbc and .mf4 files. - There is no channel from original measurement file, only from .dbc file """ # Expected result output_file = Path.with_suffix(self.mdf_path, f".bus_logging{self.mdf_path.suffix}") # Precondition self.load_database() self.assertFalse(output_file.exists()) self.assertEqual(self.widget.output_info_bus.toPlainText(), "") # bus output info tab is clean # Set Prefix prefix = self.id().split(".")[-1] self.widget.prefix.setText(prefix) # Event self.mouse_click_on_btn_with_progress(self.widget.extract_bus_btn) self.assertTrue(output_file.exists()) # Evaluate bus output info self.assertIn(str(self.dbc_path), self.widget.output_info_bus.toPlainText()) self.assertIn(str(self.mdf_path), self.widget.output_info_bus.toPlainText()) # because linux UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb0 in position 943: invalid start byte with ( OpenMDF(output_file) as bus_file, OpenMDF(self.mdf_path) as mdf_file, codecs.open(str(self.dbc_path), encoding="ISO-8859-1") as dbc_file, ): dbc_lines = dbc_file.readlines() source = DBC.BO(dbc_lines) self.assertNotEqual(len(mdf_file.groups), len(bus_file.groups)) for channel in bus_file.channels_db: self.assertNotIn(channel.replace(prefix, ""), mdf_file.channels_db) # Evaluate Source: for name, group_index in mdf_file.channels_db.items(): group, index = group_index[0] if name.endswith("ID"): self.assertEqual(mdf_file.get(name, group, index).samples[0], int(source.id)) if name.endswith("DataLength"): self.assertEqual(mdf_file.get(name, group, index).samples[0], int(source.data_length)) if "time" in name.lower(): max_from_mdf = mdf_file.get(name, group, index).samples[-1] min_from_mdf = mdf_file.get(name, group, index).samples[0] size_from_mdf = mdf_file.get(name, group, index).samples.size timestamps_size = set() timestamps_min = set() timestamps_max = set() for name, group_index in bus_file.channels_db.items(): group, index = group_index[0] if not name.endswith("time"): self.assertIn(prefix, name) channel = bus_file.get(name, group, index, raw=True) signal = DBC.SG(name.replace(self.id().split(".")[-1], "").split(".")[-1], dbc_lines) if not ("service" in name or "response" in name): self.assertEqual(channel.bit_count, signal.bit_count, name) self.assertEqual(channel.unit, signal.unit) if hasattr(channel.conversion, "a"): self.assertEqual(channel.conversion.a, signal.conversion_a, name) self.assertEqual(channel.conversion.b, signal.conversion_b, name) timestamps_size.add(channel.timestamps.size) timestamps_min.add(channel.timestamps.min()) timestamps_max.add(channel.timestamps.max()) for group in bus_file.groups: self.assertEqual(self.id().split(".")[-1], group.channel_group.acq_name.split(":")[0]) for group in mdf_file.groups: self.assertNotIn(self.id().split(".")[-1], group.channel_group.acq_name) self.assertEqual(max(timestamps_size), size_from_mdf) self.assertEqual(min(timestamps_min), min_from_mdf) self.assertEqual(max(timestamps_max), max_from_mdf) def test_extract_bus_csv_btn_0(self): """ When QThreads are running, event-loops needs to be processed. This test will use mf4 generated file for feature evaluation. If `test_extract_bus_btn` is failed: this test must be ignored. Events: - Set prefix text - Ensure that all checkboxes are unchecked - Press PushButton Export to csv. Evaluate: - CSV files was created. - New channels was created from .dbc and .mf4 files - CSV files is mf4 channels groups - Channels names and groups names contain prefix - Signals samples are added to CSV """ # Prepare expected results prefix = self.get_prefix() to_replace = [" ", '"', ":"] # Precondition self.load_database() for file in Path(self.test_workspace).iterdir(): self.assertNotEqual(file.suffix, ".csv") self.assertEqual(self.widget.output_info_bus.toPlainText(), "") self.toggle_checkboxes(widget=self.widget.extract_bus_tab, check=False) # uncheck all checkboxes # Expected results compare_to_file_path = Path.with_suffix(self.mdf_path, ".bus_logging.mf4") # Set Prefix self.widget.prefix.setText(self.id().split(".")[-1]) # Get new mdf file self.mouse_click_on_btn_with_progress(self.widget.extract_bus_btn) # Event self.mouse_click_on_btn_with_progress(self.widget.extract_bus_csv_btn) csv_tables = [ (file, pd.read_csv(file)) for file in sorted(Path(self.test_workspace).iterdir()) if file.suffix == ".csv" ] with OpenMDF(compare_to_file_path) as mdf_file: for group, (path, table) in zip(mdf_file.groups, csv_tables, strict=False): comment = group.channel_group.comment for char in to_replace: comment = comment.replace(char, "_") # Evaluate CSV name self.assertIn(self.id().split(".")[-1], str(path)) self.assertTrue(str(path).endswith(comment + ".csv")) self.assertTrue(str(path.stem).startswith(compare_to_file_path.stem)) # Evaluate channels for channel in group.channels: if channel.name != "time": name = prefix + channel.name self.assertIn(name, table.columns) ch = mdf_file.get(channel.name) # Evaluate samples self.assertEqual(ch.samples.size, table[name].size) if np.issubdtype(ch.samples.dtype, np.number): self.assertAlmostEqual(ch.samples.min(), table[name].min(), places=10) self.assertAlmostEqual(ch.samples.max(), table[name].max(), places=10) else: self.assertEqual( str(min(ch.samples)).replace(" ", ""), str(table[name].min()).replace(" ", ""), ) self.assertEqual( str(max(ch.samples)).replace(" ", ""), str(table[name].max()).replace(" ", ""), ) # Evaluate timestamps self.assertEqual(ch.timestamps.size, table.timestamps.size) self.assertAlmostEqual(ch.timestamps.min(), table.timestamps.min(), places=10) self.assertAlmostEqual(ch.timestamps.max(), table.timestamps.max(), places=10) def test_extract_bus_csv_btn_1(self): """ When QThreads are running, event-loops needs to be processed. This test will use mf4 generated file for feature evaluation. If `test_extract_bus_btn` is failed: this test must be ignored. Events: - Set prefix text - Ensure that all checkboxes are checked - Press PushButton Export to csv. Evaluate: - CSV file is created - Timestamps start from 0 + measurement start time - CSV file contain new channels from .mf4 file - Channels names contain prefix - Signals samples are added to CSV """ prefix = self.get_prefix() # Precondition self.load_database() for file in Path(self.test_workspace).iterdir(): self.assertNotEqual(file.suffix, ".csv") self.assertEqual(self.widget.output_info_bus.toPlainText(), "") self.toggle_checkboxes(widget=self.widget.extract_bus_tab, check=True) # uncheck all checkboxes # Expected results csv_path = Path.with_suffix(self.mdf_path, ".bus_logging.csv") compare_to_file_path = Path.with_suffix(self.mdf_path, ".bus_logging.mf4") # Set Prefix self.widget.prefix.setText(self.id().split(".")[-1]) # Get new mdf file self.mouse_click_on_btn_with_progress(self.widget.extract_bus_btn) # Event self.mouse_click_on_btn_with_progress(self.widget.extract_bus_csv_btn) csv_table = pd.read_csv(csv_path, header=[0, 1], engine="python", encoding="ISO-8859-1") with OpenMDF(compare_to_file_path) as mdf_file: # Get channels timestamps max, min, difference between extremes min_ts = min(channel.timestamps.min() for channel in mdf_file.iter_channels()) max_ts = max(channel.timestamps.max() for channel in mdf_file.iter_channels()) seconds = int(max_ts - min_ts) microseconds = np.floor((max_ts - min_ts - seconds) * pow(10, 6)) delay = np.datetime64(mdf_file.start_time) # - np.timedelta64(3, "h") # idk from why, local fail... csv_table.timestamps = pd.DatetimeIndex(csv_table.timestamps.values, yearfirst=True).values - delay # Evaluate timestamps min self.assertEqual(np.timedelta64(csv_table.timestamps.values.min(), "us").item().microseconds, 0) self.assertEqual(np.timedelta64(csv_table.timestamps.values.min(), "us").item().seconds, 0) # Evaluate timestamps max self.assertEqual( np.timedelta64(csv_table.timestamps.values.max(), "us").item().microseconds, int(microseconds) ) self.assertEqual(np.timedelta64(csv_table.timestamps.values.max(), "us").item().seconds, seconds) for ch in mdf_file.iter_channels(): name = prefix + ch.name self.assertIn(name, csv_table.columns) column = csv_table[name] if ch.unit and (sys.platform == "win32"): self.assertEqual(ch.unit, column.columns[0]) # Evaluate channel samples if np.issubdtype(ch.samples.dtype, np.number): self.assertAlmostEqual(ch.samples.min(), column.values.min(), places=10) self.assertAlmostEqual(ch.samples.max(), column.values.max(), places=10) else: self.assertEqual( str(min(ch.samples)).replace(" ", ""), str(column.values.min()).replace(" ", ""), ) self.assertEqual( str(max(ch.samples)).replace(" ", ""), str(column.values.max()).replace(" ", ""), ) asammdf-8.5.1/test/asammdf/gui/widgets/batch/test_BatchWidget_Tab_Concatenate.py000066400000000000000000000050101502633300400277170ustar00rootroot00000000000000#!/usr/bin/env python from pathlib import Path from unittest import mock import numpy as np from test.asammdf.gui.test_base import OpenMDF from test.asammdf.gui.widgets.test_BaseBatchWidget import TestBatchWidget # Note: If it's possible and make sense, use self.subTests # to avoid initializing widgets multiple times and consume time. class TestPushButtons(TestBatchWidget): test_file_0_name = "test_batch_cut_0.mf4" test_file_1_name = "test_batch_cut_1.mf4" output_file_name = "output.mf4" def setUp(self): super().setUp() self.test_file_0 = Path(self.test_workspace, self.test_file_0_name) self.test_file_1 = Path(self.test_workspace, self.test_file_1_name) self.copy_mdf_files_to_workspace() self.setUpBatchWidget(measurement_files=[str(self.test_file_0), str(self.test_file_1)]) # Go to Tab: Concatenate self.widget.aspects.setCurrentIndex(self.concatenate_aspect) self.processEvents(0.1) def test_PushButton_Concatenate(self): """ Events: - Open 'BatchWidget' with created measurement. - Go to Tab: "Concatenate": Index 0 - Press PushButton "Concatenate" Evaluate: - New file is created - All channels samples and timestamps from test files are concatenated intro selected output file """ # Get evaluation data output_file = Path(self.test_workspace, self.output_file_name) # Event with mock.patch("asammdf.gui.widgets.batch.QtWidgets.QFileDialog.getSaveFileName") as mo_getSaveFileName: mo_getSaveFileName.return_value = output_file, "" self.mouse_click_on_btn_with_progress(self.widget.concatenate_btn) # Evaluate that file exist self.assertTrue(output_file.exists()) # Evaluate with ( OpenMDF(output_file) as new_mdf_file, OpenMDF(self.test_file_0) as original_mdf_0, OpenMDF(self.test_file_1) as original_mdf_1, ): # Evaluate saved file for ch in new_mdf_file.iter_channels(): if ch.name in original_mdf_0.channels_db: # avoid `__samples_origin` channel ch_0 = original_mdf_0.get(ch.name) ch_1 = original_mdf_1.get(ch.name) self.assertTrue(np.array_equal(np.concatenate([ch_0.samples, ch_1.samples]), ch.samples)) self.assertTrue(np.array_equal(np.concatenate([ch_0.timestamps, ch_1.timestamps]), ch.timestamps)) asammdf-8.5.1/test/asammdf/gui/widgets/batch/test_BatchWidget_Tab_ModifyAndExport.py000066400000000000000000001046241502633300400305620ustar00rootroot00000000000000#!/usr/bin/env python import datetime from math import ceil from pathlib import Path from random import randint import unittest from unittest import mock import urllib import urllib.request from zipfile import ZipFile from can.io import ASCReader import numpy as np import pandas as pd from PySide6 import QtCore, QtTest, QtWidgets import scipy from test.asammdf.gui.test_base import OpenHDF5, OpenMDF from test.asammdf.gui.widgets.test_BaseBatchWidget import TestBatchWidget # Note: If it's possible and make sense, use self.subTests # to avoid initializing widgets multiple times and consume time. class TestPushButtonScrambleTexts(TestBatchWidget): def test_ScrambleTexts(self): """ Events: - Open 'BatchWidget' with valid measurement. - Go to Tab: "Modify & Export": Index 1 - Press PushButton "Scramble texts" Evaluate: - New file is created - No channel from first file is found in 2nd file (scrambled file) """ # Prepare workspace self.copy_mdf_files_to_workspace() test_file = Path(self.test_workspace, self.default_test_file) scrambled_filepath = Path(self.test_workspace, self.default_test_file.replace(".", ".scrambled.")) # Evaluate self.assertFalse(scrambled_filepath.exists()) # Setup self.setUpBatchWidget(measurement_files=[str(test_file)]) channels = [] iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.filter_tree) while item := iterator.value(): iterator += 1 channels.append(item.name) # Go to Tab: "Modify & Export": Index 1 self.widget.aspects.setCurrentIndex(self.modify_aspect) # Events QtTest.QTest.mouseClick(self.widget.scramble_btn, QtCore.Qt.MouseButton.LeftButton) # Wait for Thread to finish self.processEvents(1) # Evaluate self.assertTrue(scrambled_filepath.exists()) # get saved file as MDF with OpenMDF(scrambled_filepath) as mdf_file: # Evaluate file for name in channels: self.assertNotIn(name, mdf_file.channels_db) class TestPushButtonApply(TestBatchWidget): def setUp(self): """ Events - Open 'BatchWidget' with valid measurement. - Go to Tab: "Modify & Export": Index 1 - Set "channel_view" to "Natural sort" - Select some channels - Set test workspace directory as output folder Evaluate Output folder text is changed to test workspace directory """ super().setUp() self.measurement_file = str(Path(self.resource, self.default_test_file)) self.setUpBatchWidget(measurement_files=None) # Go to Tab: "Modify & Export": Index 1 self.widget.aspects.setCurrentIndex(self.modify_aspect) self.widget.filter_view.setCurrentText("Natural sort") self.processEvents(0.1) # set test_workspace folder as output folder with mock.patch( "asammdf.gui.widgets.batch.QtWidgets.QFileDialog.getExistingDirectory" ) as mo_getExistingDirectory: mo_getExistingDirectory.return_value = self.test_workspace QtTest.QTest.mouseClick(self.widget.modify_output_folder_btn, QtCore.Qt.MouseButton.LeftButton) self.assertEqual(self.widget.modify_output_folder.text().strip(), self.test_workspace) self.tested_btn = self.widget.apply_btn def generic_setup(self, name: str = "MDF", check: bool = True): # Parquet is removed? """ Add default test file to files list Check checkboxes for random channels. Set check state for output options widget checkboxes . Parameters ---------- name: name of output options widget check: check state for output options widget checkboxes """ self.widget.files_list.addItems([str(Path(self.resource, self.default_test_file))]) self.select_random_channels() for q_widget in self.widget.output_format.children(): if name in q_widget.objectName(): break else: unittest.skip(f"{name} output option widget is not defined") self.toggle_checkboxes(widget=self.widget.output_options, check=check) self.processEvents(0.01) def select_random_channels(self): count = self.widget.filter_tree.topLevelItemCount() self.select_channels(set(np.random.randint(0, count, size=randint(int(count / 4), int(count / 2))))) self.processEvents(0.01) def get_mdf_from_git(self) -> Path: url = "https://github.com/danielhrisca/asammdf/files/4328945/OBD2-DBC-MDF4.zip" urllib.request.urlretrieve(url, "test.zip") ZipFile(r"test.zip").extractall(self.test_workspace) Path("test.zip").unlink() temp_dir = Path(self.test_workspace) # Get mdf file path return [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".mf4"][0] @staticmethod def interpolated_timestamps(mdf, channels: set): all_ts = [] for group_index, gp in enumerate(mdf.groups): if gp.channel_group.cycles_nr and (channels - {ch.name for ch in gp.channels}) != channels: all_ts.append(mdf.get_master(group_index)) if all_ts: return np.unique(np.concatenate(all_ts)) else: return np.array([], dtype="f8") def test_output_format_MDF(self): """ When QThreads are running, event-loops needs to be processed. Cut and resample features will be tested in separate tests. Events: - Ensure that output format is MDF - Press PushButton Apply. Evaluate: - File was created. - Ensure that output file has only selected channels """ # Expected result saved_file = Path(self.test_workspace, self.default_test_file) # Ensure output format name = "MDF" self.widget.output_format.setCurrentText(name) self.generic_setup(name, check=False) # Event self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(saved_file.exists()) # get saved file as MDF with OpenMDF(saved_file) as mdf_file: # Evaluate saved file for channel in self.selected_channels: self.assertIn(channel, mdf_file.channels_db) def test_output_format_ASC(self): """ When QThreads are running, event-loops needs to be processed. Events: - Ensure that output format is ASC - Press PushButton Apply. Evaluate: - File was created. - Ensure that output file has only selected channels data """ # Get test file from git archive mdf_path = self.get_mdf_from_git() # Add extracted file to files list self.widget.files_list.addItems([str(mdf_path)]) # Expected results asc_path = Path.with_suffix(Path(self.test_workspace, mdf_path.stem), ".asc") # Ensure output format self.widget.output_format.setCurrentText("ASC") # Event self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(asc_path.exists()) with OpenMDF(mdf_path) as mdf_file: start_datetime = mdf_file.start_time.strftime("%a %b %d %I:%M:%S.%f %p %Y") for index, group in enumerate(mdf_file.groups): names = [ch.name for ch in group.channels if "time" not in ch.name.lower()] if not names: continue for channel_name in names: if "." not in channel_name: names.remove(channel_name) break if channel_name: channel = mdf_file.get(channel_name, index) if not channel.samples.size: continue with ASCReader(asc_path) as asc_file: for row, msg in enumerate(asc_file): if "Error" in channel_name: self.assertTrue(msg.is_error_frame) continue elif "Remote" in channel_name: self.assertTrue(msg.is_remote_frame) # Evaluate timestamps self.assertAlmostEqual(msg.timestamp, channel.timestamps[row], places=10) # Evaluate other fields for name in names: if name.endswith(".DataBytes"): self.assertEqual(msg.data, channel[name][row][: msg.dlc].tobytes()) else: data = channel[name].astype(" display_name, _ = zip(*channel.display_names.items(), strict=False) channel_name = display_name[0] else: channel_name = channel.name self.assertIn(channel_name, pandas_tab.columns.get_level_values(0)) if channel.unit: self.assertIn(channel.unit, pandas_tab.columns.get_level_values(1)) def test_output_format_MAT_0(self): """ When QThreads are running, event-loops needs to be processed. Events: - Ensure that output format is MAT, no checkboxes checked - Press PushButton Apply. Evaluate: - File was created. - Ensure that output file has only selected channels """ # Setup name = "MAT" self.widget.output_format.setCurrentText(name) self.generic_setup(name, check=False) # Expected results mat_path = Path(self.test_workspace, self.default_test_file.replace(".mf4", ".mat")) groups = self.get_selected_groups(channels=self.selected_channels) # Mouse click on Apply button self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(mat_path.exists()) mat_file = scipy.io.loadmat(str(mat_path)) to_replace = {" ", ".", "[", "]"} with OpenMDF(Path(self.resource, self.default_test_file)) as mdf_file: for index, channels_list in enumerate(groups.values()): for name in channels_list: signal = mdf_file.get(name) for character in to_replace: name = name.replace(character, "_") name = f"DG{index}_{name}" self.assertIn(name, mat_file) if np.issubdtype(signal.samples.dtype, np.number): self.assertTrue(np.array_equal(signal.samples, mat_file[name][0])) def test_output_format_MAT_1(self): """ When QThreads are running, event-loops needs to be processed. Events: - Ensure that output format is MAT, no checkboxes checked - Press PushButton Apply. Evaluate: - File was created. - Ensure that output file has only selected channels """ # Setup name = "MAT" self.widget.output_format.setCurrentText(name) self.generic_setup(name) # Expected results mat_path = Path(self.test_workspace, self.default_test_file.replace(".mf4", ".mat")) # Mouse click on Apply button self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(mat_path.exists()) mat_file = scipy.io.loadmat(str(mat_path)) to_replace = {" ", ".", "[", "]", ":"} with OpenMDF(Path(self.resource, self.default_test_file)) as mdf_file: # get common timestamps common_timestamps = self.interpolated_timestamps(mdf_file, set(self.selected_channels)) for channel in self.selected_channels: mdf_signal = mdf_file.get(channel, raw=True).interp( common_timestamps, integer_interpolation_mode=self.widget.integer_interpolation, float_interpolation_mode=self.widget.float_interpolation, ) if mdf_signal.display_names: display_name, _ = zip(*mdf_signal.display_names.items(), strict=False) channel = display_name[0] for character in to_replace: channel = channel.replace(character, "_") if channel + "_0" in mat_file.keys() and "RAT" in mdf_signal.name: channel += "_0" self.assertIn(channel[:60], mat_file.keys()) # limit of maximum 60 ch for channel name np.testing.assert_almost_equal( mdf_signal.samples, mat_file[channel[:60]][0], decimal=3, err_msg=mdf_signal.name ) common_timestamps -= common_timestamps[0] # start from 0 np.testing.assert_almost_equal(mat_file["timestamps"][0], common_timestamps, decimal=3) def test_output_format_HDF5_0(self): """ When QThreads are running, event-loops needs to be processed. Events: - Ensure that output format is HDF5, no checked checkboxes - Press PushButton Apply. Evaluate: - File was created. - Ensure that output file has only selected channels """ # Setup name = "HDF5" self.widget.output_format.setCurrentText(name) self.generic_setup(name, check=False) # Expected results hdf5_path = Path(self.test_workspace, self.default_test_file.replace(".mf4", ".hdf")) groups = self.get_selected_groups(channels=self.selected_channels) groups = list(groups.values()) # Mouse click on Apply button self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(hdf5_path.exists()) with OpenHDF5(hdf5_path) as hdf5_file, OpenMDF(self.measurement_file) as mdf_file: self.assertEqual(len(hdf5_file.items()) - 1, len(groups)) # 1th item is file path for hdf5_group in hdf5_file: hdf5_group = hdf5_file[hdf5_group] if hdf5_group.name.startswith("ChannelGroup"): index = int(hdf5_group.name.split("_")[1]) mdf_group = groups[index] for name in hdf5_group: if name != "time": # Evaluate channels self.assertIn(name, mdf_group) mdf_channel = mdf_file.select([name])[0] hdf5_channel = hdf5_group.get(name) if np.issubdtype(mdf_channel.samples.dtype, np.number): # samples are numbers np.testing.assert_almost_equal(mdf_channel.samples, hdf5_channel, decimal=3) else: # Evaluate samples shape self.assertEqual(mdf_channel.samples.size, hdf5_channel.size) else: # evaluate timestamps hdf5_channel = hdf5_group.get( name ) # for evaluation will be used latest mdf channel from group np.testing.assert_almost_equal(mdf_channel.timestamps, hdf5_channel, decimal=3) def test_output_format_HDF5_1(self): """ When QThreads are running, event-loops needs to be processed. Events: - Ensure that output format is HDF5, all checkboxes are checked - Press PushButton Apply. Evaluate: - File was created. - Ensure that output file has only selected channels """ # Expected results hdf5_path = Path(self.test_workspace, self.default_test_file.replace(".mf4", ".hdf")) # Ensure output format name = "HDF5" self.widget.output_format.setCurrentText(name) self.generic_setup(name) # Mouse click on Apply button self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(hdf5_path.exists()) with OpenHDF5(hdf5_path) as hdf5_file, OpenMDF(self.measurement_file) as mdf_file: self.assertEqual(len(hdf5_file.items()), 1) # 1 item # Prepare results common_timestamps = self.interpolated_timestamps(mdf_file, set(self.selected_channels)) hdf5_channels = hdf5_file[str(hdf5_path)] for channel in self.selected_channels: mdf_channel = mdf_file.get(channel, raw=True).interp( common_timestamps, integer_interpolation_mode=self.widget.integer_interpolation, float_interpolation_mode=self.widget.float_interpolation, ) if mdf_channel.display_names: display_name, _ = zip(*mdf_channel.display_names.items(), strict=False) channel = display_name[0] if channel + "_0" in hdf5_channels.keys() and "RAT" in mdf_channel.name: channel += "_0" hdf5_channel = hdf5_channels.get(channel) # Evaluate self.assertIn(channel, hdf5_channels) np.testing.assert_almost_equal(mdf_channel.samples, hdf5_channel, decimal=3) def test_output_format_Parquet_0(self): """ When QThreads are running, event-loops needs to be processed. Events: - Ensure that output format is Parquet - Press PushButton Apply. Evaluate: - File was created. - Ensure that output file has only selected channels with expected values """ # Expected results parquet_path = Path(self.test_workspace, self.default_test_file.replace(".mf4", ".parquet")) # Setup name = "Parquet" self.widget.output_format.setCurrentText(name) self.generic_setup(check=False) # Mouse click on Apply button self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate if parquet file exist self.assertTrue(parquet_path.exists()) with OpenMDF(self.measurement_file) as mdf_file: pandas_tab = pd.read_parquet(parquet_path) # open parquet file as pandas tab # Get common timestamps common_timestamps = self.interpolated_timestamps(mdf_file, set(self.selected_channels)) # Evaluate np.testing.assert_almost_equal(common_timestamps, pandas_tab.index.values, decimal=9) for name in self.selected_channels: channel = mdf_file.get(name).interp( common_timestamps, integer_interpolation_mode=self.widget.integer_interpolation, float_interpolation_mode=self.widget.float_interpolation, ) if np.issubdtype(channel.samples.dtype, np.number): # problematic conversion np.testing.assert_almost_equal(channel.samples, pandas_tab[name].values, decimal=9) def test_output_format_Parquet_1(self): """ When QThreads are running, event-loops needs to be processed. Events: - Ensure that output format is Parquet - Press PushButton Apply. Evaluate: - File was created. - Ensure that output file has only selected channels with expected values """ # Expected results parquet_path = Path(self.test_workspace, self.default_test_file.replace(".mf4", ".parquet")) # Setup name = "Parquet" self.widget.output_format.setCurrentText(name) self.generic_setup() # Mouse click on Apply button self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate if parquet file exist self.assertTrue(parquet_path.exists()) # Evaluate with OpenMDF(self.measurement_file) as mdf_file: pandas_tab = pd.read_parquet(parquet_path) # open parquet file as pandas tab # get common timestamp common_timestamps = self.interpolated_timestamps(mdf_file, set(self.selected_channels)) # Evaluate np.testing.assert_almost_equal(common_timestamps - common_timestamps[0], pandas_tab.index.values, decimal=9) for name in self.selected_channels: channel = mdf_file.get(name, raw=True).interp( common_timestamps, integer_interpolation_mode=self.widget.integer_interpolation, float_interpolation_mode=self.widget.float_interpolation, ) if channel.display_names: display_name, _ = zip(*channel.display_names.items(), strict=False) name = display_name[0] if name + "_0" in pandas_tab.columns and "RAT" in channel.name: name += "_0" if np.issubdtype(channel.samples.dtype, np.number): # problematic conversion np.testing.assert_almost_equal(channel.samples, pandas_tab[name].values, decimal=3) def test_cut_checkbox_0(self): """ Events - Check cut group checkbox - Set cut start and stop time - Check whence checkbox - Check cut time from zero checkbox - Press Apply bush button Evaluate - In test workspace folder was created file with same name as original measurement file - Start time for mdf file is updated - Timestamps start for all channels is equal to 0 - Timestamps stop for all channels is equal to difference between stop and start time """ # Setup name = "MDF" self.widget.output_format.setCurrentText(name) self.generic_setup(check=False) # Expected values output_file = Path(self.test_workspace, self.default_test_file) with OpenMDF(self.measurement_file) as mdf_file: self.start_time = mdf_file.start_time.astimezone().replace(tzinfo=None) self.ts_min = min( [ ch.timestamps.min() for ch in mdf_file.iter_channels() if ch.timestamps.min() != 0 and ch.name in self.selected_channels ] ) start_cut = randint(1, 42) / 10 stop_cut = randint(60, 90) / 10 expected_start_time = self.start_time + datetime.timedelta(milliseconds=(start_cut + self.ts_min) * 1000) # Setup QtTest.QTest.keyClick(self.widget.cut_group, QtCore.Qt.Key.Key_Space) self.widget.cut_start.setValue(start_cut) self.widget.cut_stop.setValue(stop_cut) for checkbox in self.widget.cut_group.findChildren(QtWidgets.QCheckBox): if not checkbox.isChecked(): self.mouseClick_CheckboxButton(checkbox) self.processEvents(0.01) # Event self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(output_file.exists()) with OpenMDF(output_file) as mdf_file: time_dif = expected_start_time - mdf_file.start_time self.assertEqual(time_dif.microseconds, 0) self.assertEqual(time_dif.seconds, 0) self.assertEqual(time_dif.days, 0) for channel in mdf_file.iter_channels(): self.assertEqual(channel.timestamps.min(), 0) self.assertAlmostEqual(channel.timestamps.max(), stop_cut - start_cut, 3) def test_cut_checkbox_1(self): """ Events - Check cut group checkbox - Set cut start and stop time - Press Apply bush button Evaluate - In test workspace folder was created file with same name as original measurement file - Start time for mdf file is updated - Timestamps start for all channels is equal to 0 - Timestamps stop for all channels is equal to difference between stop and start time """ # Setup name = "MDF" self.widget.output_format.setCurrentText(name) self.generic_setup(check=False) # Expected values output_file = Path(self.test_workspace, self.default_test_file) with OpenMDF(self.measurement_file) as mdf_file: self.start_time = mdf_file.start_time self.ts_min = min( [ ch.timestamps.min() for ch in mdf_file.iter_channels() if ch.timestamps.min() != 0 and ch.name in self.selected_channels ] ) start_cut = randint(1, 42) / 10 stop_cut = randint(60, 90) / 10 # Setup QtTest.QTest.keyClick(self.widget.cut_group, QtCore.Qt.Key.Key_Space) self.widget.cut_start.setValue(start_cut) self.widget.cut_stop.setValue(stop_cut) for checkbox in self.widget.cut_group.findChildren(QtWidgets.QCheckBox): if checkbox.isChecked(): self.mouseClick_CheckboxButton(checkbox) self.processEvents(0.01) # Event self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(output_file.exists()) with OpenMDF(output_file) as mdf_file: self.assertEqual(self.start_time, mdf_file.start_time) for channel in mdf_file.iter_channels(): self.assertEqual(channel.timestamps.min(), start_cut) self.assertEqual(channel.timestamps.max(), stop_cut) @unittest.skip("FIXME: test keeps failing in CI") def test_resample_by_step_0(self): """ Events - Check resample group checkbox - Set step time - Press Apply bush button Evaluate - In test workspace folder was created file with same name as original measurement file - Start time for timestamps is not updated - Timestamps step for all channels is the same as step time value """ # Expected values output_file = Path(self.test_workspace, self.default_test_file) step = randint(1, 100) / 10 # Setup name = "MDF" self.widget.output_format.setCurrentText(name) self.generic_setup(check=False) QtTest.QTest.keyClick(self.widget.resample_group, QtCore.Qt.Key.Key_Space) self.widget.raster_type_step.setChecked(True) self.widget.raster.setValue(step) for checkbox in self.widget.resample_group.findChildren(QtWidgets.QCheckBox): if checkbox.isChecked(): self.mouseClick_CheckboxButton(checkbox) self.processEvents(0.01) # Event self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(output_file.exists()) with OpenMDF(output_file) as mdf_file: for channel in mdf_file.iter_channels(): size = ceil((channel.timestamps.max() - channel.timestamps.min()) / step) + 1 # + min self.assertEqual(size, channel.timestamps.size) for i in range(size): self.assertAlmostEqual(channel.timestamps[i], channel.timestamps.min() + step * i, places=12) @unittest.skip("FIXME: test keeps failing in CI") def test_resample_by_step_1(self): """ Events - Check resample group checkbox - Set step time - Check Time from zero checkbox - Press Apply bush button Evaluate - In test workspace folder was created file with same name as original measurement file - Start time for timestamps is 0 - Timestamps step for all channels is the same as step time value """ # Expected values output_file = Path(self.test_workspace, self.default_test_file) step = randint(1, 100) / 10 # Setup name = "MDF" self.widget.output_format.setCurrentText(name) self.generic_setup(check=False) QtTest.QTest.keyClick(self.widget.resample_group, QtCore.Qt.Key.Key_Space) self.widget.raster_type_step.setChecked(True) self.widget.raster.setValue(step) for checkbox in self.widget.resample_group.findChildren(QtWidgets.QCheckBox): if not checkbox.isChecked(): self.mouseClick_CheckboxButton(checkbox) self.processEvents(0.01) # Event self.mouse_click_on_btn_with_progress(self.tested_btn) # Evaluate self.assertTrue(output_file.exists()) with OpenMDF(output_file) as mdf_file: for channel in mdf_file.iter_channels(): size = ceil((channel.timestamps.max() - channel.timestamps.min()) / step) + 1 # + min self.assertEqual(size, channel.timestamps.size) for i in range(size): self.assertAlmostEqual(channel.timestamps[i], step * i, places=12) asammdf-8.5.1/test/asammdf/gui/widgets/batch/test_BatchWidget_Tab_Stack.py000066400000000000000000000046421502633300400265520ustar00rootroot00000000000000#!/usr/bin/env python from pathlib import Path from unittest import mock import numpy as np from test.asammdf.gui.test_base import OpenMDF from test.asammdf.gui.widgets.test_BaseBatchWidget import TestBatchWidget # Note: If it's possible and make sense, use self.subTests # to avoid initializing widgets multiple times and consume time. class TestPushButtons(TestBatchWidget): default_test_file = "ASAP2_Demo_V171.mf4" class_test_file = "test_batch.mf4" def setUp(self): """ Events - Open 'BatchWidget' with 2 valid measurement. - Go to Tab: "Stack" """ super().setUp() self.copy_mdf_files_to_workspace() # Setup self.measurement_file_1 = Path(self.test_workspace, self.default_test_file) self.measurement_file_2 = Path(self.test_workspace, self.class_test_file) self.saved_file = Path(self.test_workspace, self.id().split(".")[-1] + ".mf4") self.setUpBatchWidget(measurement_files=[str(self.measurement_file_1), str(self.measurement_file_2)]) self.widget.aspects.setCurrentIndex(self.stack_aspect) def test_PushButton_Stack(self): """ Events: - Press PushButton "Stack" - Save measurement file Evaluate: - New file is created - All channels samples and timestamps from both input files can be found in selected output file """ # Event with mock.patch("asammdf.gui.widgets.batch.QtWidgets.QFileDialog.getSaveFileName") as mo_getSaveFileName: mo_getSaveFileName.return_value = str(self.saved_file), "" self.mouse_click_on_btn_with_progress(self.widget.stack_btn) # Evaluate self.assertTrue(self.saved_file.exists()) # Evaluate saved file with ( OpenMDF(self.saved_file) as new_mdf_file, OpenMDF(self.measurement_file_1) as mdf_test_file_0, OpenMDF(self.measurement_file_2) as mdf_test_file_1, ): for channel in mdf_test_file_1.iter_channels(): new_file_channel = new_mdf_file.get(channel.name) self.assertTrue(np.array_equal(channel.samples, new_file_channel.samples)) for channel in mdf_test_file_0.iter_channels(): new_file_channel = new_mdf_file.get(channel.name) self.assertTrue(np.array_equal(channel.samples, new_file_channel.samples)) asammdf-8.5.1/test/asammdf/gui/widgets/file/000077500000000000000000000000001502633300400206715ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/file/__init__.py000066400000000000000000000000001502633300400227700ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/file/test_FileWidget_TabChannels.py000066400000000000000000001234061502633300400265750ustar00rootroot00000000000000#!/usr/bin/env python import pathlib from unittest import mock from PySide6 import QtCore, QtTest, QtWidgets from asammdf.gui.dialogs.channel_group_info import ChannelGroupInfoDialog from asammdf.gui.dialogs.channel_info import ChannelInfoDialog from asammdf.gui.widgets.numeric import Numeric from asammdf.gui.widgets.plot import Plot from asammdf.gui.widgets.tabular import Tabular from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget # Note: If it's possible and make sense, use self.subTests # to avoid initializing widgets multiple times and consume time. class TestTabChannels(TestFileWidget): def tearDown(self): if self.mc_ErrorDialog.call_args: if ( "" in self.mc_ErrorDialog.call_args.kwargs["message"] and self.mc_ErrorDialog.call_count == 1 ): self.mc_ErrorDialog.reset_mock() self.mc_ErrorDialog.assert_not_called() self.mc_widget_ed.assert_not_called() super().tearDown() def test_load_file_with_metadata(self): """ Events: - Open 'FileWidget' with valid measurement which has valid display file in metadata. - Store opened sub-windows typy, titles and channels names - Close all sub-windows - Press PushButton: "Load offline windows" - Simulate that dspf file from metadata was selected Expected: - Loaded sub-windows are the same as sub-windows opened with measurement file """ def get_dspf_data(iterator): data = [] for sub_win in iterator: w = sub_win.widget() if isinstance(w, Plot): data.append( { "channels": [ w.channel_selection.topLevelItem(_).name for _ in range(w.channel_selection.topLevelItemCount()) ], "plot_bg_color": w.plot.backgroundBrush().color().name(), } ) elif isinstance(w, Numeric): data.append([sig.name for sig in w.channels.dataView.backend.signals]) elif isinstance(w, Tabular): data.append(list(w.tree.pgdf.df.columns)) return data # Setup measurement_file = str(pathlib.Path(self.resource, "test_metadata.mf4")) # valid_dsp = str(pathlib.Path(self.resource, "valid.dsp")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) # Prepare expected results dspf_file = self.widget.mdf.header._common_properties.get("pr_display_file", "") dspf_path = str(pathlib.Path(self.resource, dspf_file)) sub_windows = self.get_sub_windows() titles = sorted(w.windowTitle() for w in self.widget.mdi_area.subWindowList()) dspf_data = get_dspf_data(self.widget.mdi_area.subWindowList()) # Close all sub-windows for w in self.widget.mdi_area.subWindowList(): w.close() # Evaluate that all sub-windows was closed self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) # Open DSPF with mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName: mo_getOpenFileName.return_value = dspf_path, None QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) self.processEvents() # Evaluate self.assertListEqual(sub_windows, self.get_sub_windows()) self.assertListEqual(titles, sorted(w.windowTitle() for w in self.widget.mdi_area.subWindowList())) for old, new in zip(dspf_data, get_dspf_data(self.widget.mdi_area.subWindowList()), strict=False): if isinstance(old, dict): self.assertListEqual(new["channels"], old["channels"]) self.assertEqual(new["plot_bg_color"], old["plot_bg_color"]) elif isinstance(old, list): self.assertListEqual(old, new) def test_PushButton_LoadOfflineWindows_DSP(self): """ Events: - Open 'FileWidget' with valid measurement. - Press PushButton: "Load offline windows" - Simulate that valid file was selected Expected: - Evaluate that Plot Window is added in "mdi_area" """ # Setup measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) valid_dsp = str(pathlib.Path(self.resource, "valid.dsp")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) with mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName: mo_getOpenFileName.return_value = valid_dsp, None QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) widget_types = self.get_sub_windows() self.assertIn("Plot", widget_types) @mock.patch("asammdf.gui.widgets.file.ErrorDialog") def test_PushButton_LoadOfflineWindows_DSPF(self, mc_file_ErrorDialog): """ Events: - Open 'FileWidget' with valid measurement. - Case 0: - Press PushButton: "Load offline windows" - Simulate that no file was selected - Case 1: - Press PushButton: "Load offline windows" - Simulate that file with non-supported extension was selected - Case 2: - Press PushButton: "Load offline windows" - Simulate that invalid "dspf" file was selected: json decode error - Case 3: - Press PushButton: "Load offline windows" - Simulate that invalid "dspf" file was selected: Plot Section Key Error - Case 4: - Press PushButton: "Load offline windows" - Simulate that invalid "dspf" file was selected: Numeric Section Key Error - Case 5: - Press PushButton: "Load offline windows" - Simulate that invalid "dspf" file was selected: Tabular Section Key Error - Case 6: - Press PushButton: "Load offline windows" - Simulate that valid "dspf" file was selected Expected: - Case 0: No dpsf file was selected - Evaluate that method "load_window" is not called - Case 1: File with non-supported extension was selected - Evaluate that method "load_window" is not called - Case 2: Json Decode Error - Evaluate that method "load_window" is not called - Evaluate that "ErrorDialog" widget is called - Case 3: Plot Section Key Error - Evaluate that there is no Plot window in "mdi_area" - Evaluate that "ErrorDialog" widget is called - Case 4: Numeric Section Key Error - Evaluate that there is no Numeric window in "mdi_area" - Evaluate that "ErrorDialog" widget is called - Case 5: Tabular Section Key Error - Evaluate that there is no Tabuler window in "mdi_area" - Evaluate that "ErrorDialog" widget is called - Case 6: - Evaluate that there 3 sub-windows in "mdi_area" when measurement file is loaded - Numeric, Plot, Tabular """ # Setup measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) valid_dspf = str(pathlib.Path(self.resource, "valid.dspf")) invalid_json_decode_error_dspf = str(pathlib.Path(self.resource, "invalid_JsonDecodeError.dspf")) invalid_numeric_section_key_error_dspf = str(pathlib.Path(self.resource, "invalid_NumericSectionKeyError.dspf")) invalid_plot_section_key_error_dspf = str(pathlib.Path(self.resource, "invalid_PlotSectionKeyError.dspf")) invalid_tabular_section_key_error_dspf = str(pathlib.Path(self.resource, "invalid_TabularSectionKeyError.dspf")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) # Case 0 with self.subTest("test_PushButton_LoadOfflineWindows_DSPF_0"): with ( mock.patch.object(self.widget, "load_window", wraps=self.widget.load_window) as mo_load_window, mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, ): mo_getOpenFileName.return_value = None, None QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate mo_load_window.assert_not_called() self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) # Case 1 with self.subTest("test_PushButton_LoadOfflineWindows_DSPF_1"): with ( mock.patch.object(self.widget, "load_window", wraps=self.widget.load_window) as mo_load_window, mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, ): mo_getOpenFileName.return_value = valid_dspf[:-2], None QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate mo_load_window.assert_not_called() self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) # Case 2 with self.subTest("test_PushButton_LoadOfflineWindows_DSPF_2"): with ( mock.patch.object(self.widget, "load_window", wraps=self.widget.load_window) as mo_load_window, mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, ): mo_getOpenFileName.return_value = ( invalid_json_decode_error_dspf, None, ) QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate mo_load_window.assert_not_called() self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) self.mc_ErrorDialog.assert_called() self.mc_ErrorDialog.reset_mock() # Case 3 with self.subTest("test_PushButton_LoadOfflineWindows_DSPF_3"): with ( mock.patch("asammdf.gui.widgets.file.ErrorDialog") as mc_ErrorDialog, mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, ): mo_getOpenFileName.return_value = ( invalid_plot_section_key_error_dspf, None, ) QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) mc_ErrorDialog.assert_called() mc_ErrorDialog.reset_mock() widget_types = self.get_sub_windows() self.assertNotIn("Plot", widget_types) # Case 4 with self.subTest("test_PushButton_LoadOfflineWindows_DSPF_4"): with ( mock.patch("asammdf.gui.widgets.file.ErrorDialog") as mc_ErrorDialog, mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, ): mo_getOpenFileName.return_value = ( invalid_numeric_section_key_error_dspf, None, ) QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) mc_ErrorDialog.assert_called() mc_ErrorDialog.reset_mock() widget_types = self.get_sub_windows() self.assertNotIn("Numeric", widget_types) # Case 5 with self.subTest("test_PushButton_LoadOfflineWindows_DSPF_5"): with ( mock.patch("asammdf.gui.widgets.file.ErrorDialog") as mc_ErrorDialog, mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, ): mo_getOpenFileName.return_value = ( invalid_tabular_section_key_error_dspf, None, ) QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) mc_ErrorDialog.assert_called() mc_ErrorDialog.reset_mock() widget_types = self.get_sub_windows() self.assertNotIn("Tabular", widget_types) # Case 6 with self.subTest("test_PushButton_LoadOfflineWindows_DSPF_6"): with ( mock.patch.object(self.widget, "load_window", wraps=self.widget.load_window) as mo_load_window, mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, ): mo_getOpenFileName.return_value = valid_dspf, None QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate mo_load_window.assert_called() self.assertEqual(len(self.widget.mdi_area.subWindowList()), 3) widget_types = self.get_sub_windows() self.assertListEqual(["Numeric", "Plot", "Tabular"], widget_types) mc_file_ErrorDialog.assert_not_called() def test_PushButton_LoadOfflineWindows_LAB(self): """ Events: - Open 'FileWidget' with valid measurement. - Ensure that Channels View is set to "Internal file structure" - Case 0: - Press PushButton: "Load offline windows" - Simulate that "lab" file with empty section was selected - Case 1: - Press PushButton: "Load offline windows" - Simulate that "lab" with no sections was provided - Case 2: - Press PushButton: "Load offline windows" - Simulate that valid "lab" file was selected Expected: - Case 0 & 1: - Evaluate that no channel is checked - Case 2: - Evaluate that 7 channels are checked """ # Setup valid_lab = str(pathlib.Path(self.resource, "valid.lab")) invalid_missing_section_lab = str(pathlib.Path(self.resource, "invalid_MissingSection.lab")) invalid_empty_section_lab = str(pathlib.Path(self.resource, "invalid_EmptySection.lab")) measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) # Switch ComboBox to "Internal file structure" self.widget.channel_view.setCurrentText("Internal file structure") # Case 0: with self.subTest("test_PushButton_LoadOfflineWindows_LAB_0"): with mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName: mo_getOpenFileName.return_value = ( invalid_empty_section_lab, None, ) QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) checked_items = [] iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() if item.parent() is None: iterator += 1 continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: checked_items.append(item.text(0)) iterator += 1 self.assertEqual(0, len(checked_items)) self.assertNotRegex( str(self.mc_ErrorDialog.mock_calls), r"local variable .* referenced before assignment", ) # Case 1: with self.subTest("test_PushButton_LoadOfflineWindows_LAB_1"): with mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName: mo_getOpenFileName.return_value = ( invalid_missing_section_lab, None, ) QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) checked_items = [] iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() if item.parent() is None: iterator += 1 continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: checked_items.append(item.text(0)) iterator += 1 self.assertEqual(0, len(checked_items)) self.assertNotRegex( str(self.mc_ErrorDialog.mock_calls), r"local variable .* referenced before assignment", ) # Case 2: with self.subTest("test_PushButton_LoadOfflineWindows_LAB_2"): with ( mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, mock.patch("asammdf.gui.widgets.file.QtWidgets.QInputDialog.getItem") as mo_getItem, ): mo_getOpenFileName.return_value = valid_lab, None mo_getItem.return_value = "lab", True QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) checked_items = [] iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() if item.parent() is None: iterator += 1 continue if item.checkState(0) == QtCore.Qt.CheckState.Checked: checked_items.append(item.text(0)) iterator += 1 self.assertEqual(7, len(checked_items)) self.assertSetEqual( { "ASAM.M.SCALAR.FLOAT64.IDENTICAL", "ASAM.M.SCALAR.UBYTE.FORM_X_PLUS_4", "ASAM_[1].M.MATRIX_DIM_16.UBYTE.IDENTICAL", "ASAM_[11].M.MATRIX_DIM_16.UBYTE.IDENTICAL", "ASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL", "time", }, set(checked_items), ) def test_PushButton_SaveOfflineWindows(self): """ Events: - Open 'FileWidget' with valid measurement. - Ensure that Channels View is set to "Internal file structure" - Press PushButton: "Load offline windows" - Simulate that valid "dspf" file was selected - Close all Numeric and Tabular windows - Add new Plot window with few channels - Press PushButton: "Save offline windows" - Close all windows. - Press PushButton: "Load offline windows" - Simulate that saved valid "dspf" file was selected Evaluate: - Evaluate that new dspf file was saved. - Evaluate that two Plot Windows are loaded. """ # Setup valid_dspf = str(pathlib.Path(self.resource, "valid.dspf")) saved_dspf = pathlib.Path(self.test_workspace, f"{self.id()}.dspf") measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) self.setUpFileWidget(measurement_file=measurement_file, default=True) # Switch ComboBox to "Internal file structure" self.widget.channel_view.setCurrentText("Internal file structure") # Load Display File self.load_display_file(display_file=valid_dspf) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 3) # Close all Numeric and Tabular windows for window in self.widget.mdi_area.subWindowList(): if window.widget().__class__.__name__ in ("Numeric", "Tabular"): window.close() # Drag Part # Add a new Plot window with few channels self.create_window(window_type="Plot", channels_names=["ASAM.M.SCALAR.UBYTE.VTAB_RANGE_NO_DEFAULT_VALUE"]) # Press PushButton: "Save offline windows" with mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getSaveFileName") as mo_getSaveFileName: mo_getSaveFileName.return_value = str(saved_dspf), None QtTest.QTest.mouseClick( self.widget.save_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Evaluate self.assertTrue(saved_dspf.exists()) # Event self.load_display_file(display_file=saved_dspf) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) widget_types = {w.widget().__class__.__name__ for w in self.widget.mdi_area.subWindowList()} self.assertSetEqual({"Plot"}, widget_types) def test_PushButton_SelectAll(self): """ Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton: "Select all the channels" - Clear selection - Switch ComboBox to "Internal file structure" - Press PushButton: "Select all the channels" - Switch ComboBox to "Selected channels only" Evaluate: - Evaluate that all channels from "channels_tree" are checked. """ measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) # Switch ComboBox to "Natural sort" self.widget.channel_view.setCurrentText("Natural Sort") # Press PushButton: "Select all the channels" QtTest.QTest.mouseClick(self.widget.select_all_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() self.assertTrue(item.checkState(0)) iterator += 1 # Clear all iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) self.assertEqual(item.checkState(0), QtCore.Qt.CheckState.Unchecked) iterator += 1 # Switch ComboBox to "Internal file structure" self.widget.channel_view.setCurrentText("Internal file structure") # Press PushButton: "Select all the channels" QtTest.QTest.mouseClick(self.widget.select_all_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() self.assertTrue(item.checkState(0)) iterator += 1 # Switch ComboBox to "Selected channels only" self.widget.channel_view.setCurrentText("Selected channels only") # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() self.assertTrue(item.checkState(0)) iterator += 1 def test_PushButton_ClearAll(self): """ Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Select all channels - Press PushButton: "Clear all selected channels" - Switch ComboBox to "Internal file structure" - Select all channels - Press PushButton: "Clear all selected channels" - Switch ComboBox to "Selected channels only" Evaluate: - Evaluate that all channels from "channels_tree" are unchecked. """ measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) # Switch ComboBox to "Natural sort" self.widget.channel_view.setCurrentText("Natural Sort") # Select all iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() item.setCheckState(0, QtCore.Qt.CheckState.Checked) self.assertEqual(QtCore.Qt.CheckState.Checked, item.checkState(0)) iterator += 1 # Press PushButton: "Clear all selected channels" QtTest.QTest.mouseClick(self.widget.clear_channels_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() self.assertEqual(QtCore.Qt.CheckState.Unchecked, item.checkState(0)) iterator += 1 # Switch ComboBox to "Internal file structure" self.widget.channel_view.setCurrentText("Internal file structure") while iterator.value(): item = iterator.value() item.setCheckState(0, QtCore.Qt.CheckState.Checked) self.assertEqual(QtCore.Qt.CheckState.Checked, item.checkState(0)) iterator += 1 # Press PushButton: "Clear all selected channels" QtTest.QTest.mouseClick(self.widget.clear_channels_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() self.assertEqual(QtCore.Qt.CheckState.Unchecked, item.checkState(0)) iterator += 1 # Switch ComboBox to "Selected channels only" self.widget.channel_view.setCurrentText("Selected channels only") # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() self.assertEqual(QtCore.Qt.CheckState.Unchecked, item.checkState(0)) iterator += 1 def test_PushButton_Search(self): """ Events: - Open 'FileWidget' with valid measurement. - Case 0: - Press PushButton: "Search and select channels" - Simulate that "AdvancedSearch" was closed/cancelled (no signal was selected) - Case 1: - Press PushButton: "Search and select channels" - Simulate that 2 channels were selected and PushButton "Check channels" was pressed. - Case 2: - Clear 'channel_tree' selection - Press PushButton: "Search and select channels" - Simulate that 2 channels were selected and PushButton "Add Window" was pressed. Evaluate: - Case 0: - Evaluate that no channel is selected in "channel_tree" - Case 1: - Evaluate that 2 channels are selected in "channel_tree" - Case 2: - Evaluate that 2 channels are selected in "channel_tree" - Plot Window is added. """ # Setup measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) # Case 0: with self.subTest("test_PushButton_Search_0"): with mock.patch("asammdf.gui.widgets.file.AdvancedSearch") as mc_AdvancedSearch: mc_AdvancedSearch.return_value.result = {} mc_AdvancedSearch.return_value.pattern_window = False mc_AdvancedSearch.return_value.add_window_request = False # - Press PushButton: "Search and select channels" QtTest.QTest.mouseClick(self.widget.advanced_search_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() self.assertEqual(item.checkState(0), QtCore.Qt.CheckState.Unchecked) iterator += 1 # Case 1: with self.subTest("test_PushButton_Search_1"): with mock.patch("asammdf.gui.widgets.file.AdvancedSearch") as mc_AdvancedSearch: mc_AdvancedSearch.return_value.result = { (4, 3): "ASAM.M.SCALAR.FLOAT64.IDENTICAL", (2, 10): "ASAM.M.SCALAR.FLOAT32.IDENTICAL", } mc_AdvancedSearch.return_value.pattern_window = False mc_AdvancedSearch.return_value.add_window_request = False # - Press PushButton: "Search and select channels" QtTest.QTest.mouseClick(self.widget.advanced_search_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate checked_channels = 0 iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() if item.checkState(0) == QtCore.Qt.CheckState.Checked: checked_channels += 1 iterator += 1 self.assertEqual(2, checked_channels) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) # Case 2: with self.subTest("test_PushButton_Search_2"): # - Clear 'channel_tree' selection iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 with ( mock.patch("asammdf.gui.widgets.file.AdvancedSearch") as mc_AdvancedSearch, mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog, ): mc_AdvancedSearch.return_value.result = { (4, 3): "ASAM.M.SCALAR.FLOAT64.IDENTICAL", (2, 10): "ASAM.M.SCALAR.FLOAT32.IDENTICAL", } mc_AdvancedSearch.return_value.pattern_window = False mc_AdvancedSearch.return_value.add_window_request = True mc_WindowSelectionDialog.return_value.result.return_value = True mc_WindowSelectionDialog.return_value.selected_type.return_value = "New plot window" mc_WindowSelectionDialog.return_value.disable_new_channels.return_value = False # - Press PushButton: "Search and select channels" QtTest.QTest.mouseClick(self.widget.advanced_search_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate checked_channels = 0 iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.channels_tree) while iterator.value(): item = iterator.value() if item.checkState(0) == QtCore.Qt.CheckState.Checked: checked_channels += 1 iterator += 1 self.assertEqual(2, checked_channels) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) widget_types = self.get_sub_windows() self.assertIn("Plot", widget_types) def test_PushButton_CreateWindow(self): """ Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Case 0: - Press PushButton "Create Window" - Simulate that "WindowSelectionDialog" is cancelled/closed. - Case 1: - Press PushButton "Create Window" - Simulate that Window Type is Plot. - Case 2: - Select one channel - Press PushButton "Create Window" - Simulate that Window Type is Numeric. - Case 3: - Press PushButton "Create Window" - Simulate that Window Type is Tabular. - Case 4: - Press PushButton "Create Window" - Simulate that Window Type is Plot. Evaluate: - Evaluate that 4 sub-windows are created. - Check if windows contain channel selected. """ # Setup measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) self.widget.channel_view.setCurrentText("Natural sort") # Case 0: with self.subTest("test_PushButton_CreateWindow_0"): with mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog: mc_WindowSelectionDialog.return_value.result.return_value = False # - Press PushButton "Create Window" QtTest.QTest.mouseClick(self.widget.create_window_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 0) # Case 1: with self.subTest("test_PushButton_CreateWindow_1"): with mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog: mc_WindowSelectionDialog.return_value.result.return_value = True mc_WindowSelectionDialog.return_value.selected_type.return_value = "Plot" # - Press PushButton "Create Window" QtTest.QTest.mouseClick(self.widget.create_window_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) widget_types = self.get_sub_windows() self.assertIn("Plot", widget_types) # Case 2: with self.subTest("test_PushButton_CreateWindow_2"): with mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog: mc_WindowSelectionDialog.return_value.result.return_value = True mc_WindowSelectionDialog.return_value.selected_type.return_value = "Numeric" # - Select one channel channel = self.widget.channels_tree.topLevelItem(0).text(0) self.widget.channels_tree.topLevelItem(0).setCheckState(0, QtCore.Qt.CheckState.Checked) # - Press PushButton "Create Window" QtTest.QTest.mouseClick(self.widget.create_window_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) widget_types = self.get_sub_windows() self.assertIn("Numeric", widget_types) numeric_data = self.widget.mdi_area.subWindowList()[1].widget().channels.dataView numeric_channel = numeric_data.model().data(numeric_data.model().index(0, 0)) self.assertEqual(channel, numeric_channel) # Case 3: with self.subTest("test_PushButton_CreateWindow_3"): with mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog: mc_WindowSelectionDialog.return_value.result.return_value = True mc_WindowSelectionDialog.return_value.selected_type.return_value = "Tabular" # - Press PushButton "Create Window" QtTest.QTest.mouseClick(self.widget.create_window_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 3) widget_types = self.get_sub_windows() self.assertIn("Tabular", widget_types) # Case 4: with self.subTest("test_PushButton_CreateWindow_4"): with mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog: mc_WindowSelectionDialog.return_value.result.return_value = True mc_WindowSelectionDialog.return_value.selected_type.return_value = "Plot" # - Press PushButton "Create Window" QtTest.QTest.mouseClick(self.widget.create_window_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertEqual(len(self.widget.mdi_area.subWindowList()), 4) widget_types = self.get_sub_windows() self.assertIn("Plot", widget_types) plot_widget = self.widget.mdi_area.subWindowList()[3].widget() plot_channel = plot_widget.channel_selection.topLevelItem(0).text(0) self.assertEqual(channel, plot_channel) def test_DoubleClick_Channel(self): """ Events: - Open 'FileWidget' with valid measurement. - Ensure that "channel_view" is set to "Internal file structure" - Case 0: - DoubleClick on Channel Group - Case 1: - DoubleClick on Channel Evaluate: - Evaluate that new dialog is visible and display channel meta-data. """ # Setup measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) self.widget.channel_view.setCurrentText("Internal file structure") first_item = self.widget.channels_tree.topLevelItem(0) first_item_center = self.widget.channels_tree.visualItemRect(first_item).center() QtTest.QTest.mouseClick( self.widget.channels_tree.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, first_item_center, ) self.processEvents() # Case 0: with mock.patch( "asammdf.gui.widgets.file.ChannelGroupInfoDialog", wraps=ChannelGroupInfoDialog, ) as mc_ChannelGroupInfoDialog: QtTest.QTest.mouseDClick( self.widget.channels_tree.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, first_item_center, ) # Evaluate mc_ChannelGroupInfoDialog.assert_called() # Identify child: ChannelGroupInfoDialog for child in self.widget.children(): if child.__class__.__name__ == "ChannelGroupInfoDialog": break if hasattr(child, "isVisible") and hasattr(child, "close"): self.assertTrue(child.isVisible()) child.close() self.assertFalse(child.isVisible()) # Case 1: child_item = first_item.child(0) child_item_center = self.widget.channels_tree.visualItemRect(child_item).center() QtTest.QTest.mouseClick( self.widget.channels_tree.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, child_item_center, ) self.processEvents() with mock.patch( "asammdf.gui.widgets.file.ChannelInfoDialog", wraps=ChannelInfoDialog, ) as mc_ChannelGroupInfoDialog: QtTest.QTest.mouseDClick( self.widget.channels_tree.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, child_item_center, ) # Evaluate mc_ChannelGroupInfoDialog.assert_called() # Identify child: ChannelInfoDialog for child in self.widget.children(): if child.__class__.__name__ == "ChannelInfoDialog": break if hasattr(child, "isVisible") and hasattr(child, "close"): self.assertTrue(child.isVisible()) child.close() self.assertFalse(child.isVisible()) asammdf-8.5.1/test/asammdf/gui/widgets/file/test_FileWidget_TabModifyAndExport.py000066400000000000000000000117201502633300400301110ustar00rootroot00000000000000#!/usr/bin/env python import pathlib import shutil import time from unittest import mock from PySide6 import QtCore, QtTest, QtWidgets from test.asammdf.gui.test_base import OpenMDF from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget # Note: If it's possible and make sense, use self.subTests # to avoid initializing widgets multiple times and consume time. class TestTabModifyAndExport(TestFileWidget): def test_PushButton_ScrambleTexts(self): """ Events: - Open 'FileWidget' with valid measurement. - Go to Tab: "Modify & Export": Index 1 - Press PushButton "Scramble texts" Evaluate: - New file is created - No channel from first file is found in 2nd file (scrambled file) """ # Setup measurement_file = str(pathlib.Path(self.test_workspace, "ASAP2_Demo_V171.mf4")) shutil.copy(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4"), measurement_file) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) # Go to Tab: "Modify & Export": Index 1 self.widget.aspects.setCurrentIndex(1) # Press PushButton ScrambleTexts QtTest.QTest.mouseClick(self.widget.scramble_btn, QtCore.Qt.MouseButton.LeftButton) channels = list(self.widget.mdf.channels_db) # Evaluate scrambled_filepath = pathlib.Path(self.test_workspace, "ASAP2_Demo_V171.scrambled.mf4") # Wait for Thread to finish time.sleep(0.1) with OpenMDF(scrambled_filepath) as mdf_file: result = filter(lambda c: c in mdf_file.channels_db, channels) self.assertFalse(any(result)) def test_ExportMDF(self): """ When QThreads are running, event-loops needs to be processed. Events: - Open 'FileWidget' with valid measurement. - Go to Tab: "Modify & Export": Index 1 - Set "channel_view" to "Natural sort" - Select two channels - Ensure that output format is MDF - Case 0: - Press PushButton Apply. - Simulate that no valid path is provided. - Case 1: - Press PushButton Apply. - Simulate that no valid path is provided. Evaluate: - Evaluate that file was created. - Open File and check that there are only two channels. """ # Setup measurement_file = str(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4")) # Event self.setUpFileWidget(measurement_file=measurement_file, default=True) # Go to Tab: "Modify & Export": Index 1 self.widget.aspects.setCurrentIndex(1) self.widget.filter_view.setCurrentText("Natural sort") count = 2 selected_channels = [] iterator = QtWidgets.QTreeWidgetItemIterator(self.widget.filter_tree) while iterator.value() and count: item = iterator.value() item.setCheckState(0, QtCore.Qt.CheckState.Checked) self.assertTrue(item.checkState(0) == QtCore.Qt.CheckState.Checked) selected_channels.append(item.text(0)) iterator += 1 count -= 1 # Evaluate that channels were added to "selected_filter_channels" for index in range(self.widget.selected_filter_channels.count()): item = self.widget.selected_filter_channels.item(index) self.assertIn(item.text(), selected_channels) self.widget.output_format.setCurrentText("MDF") # Case 0: self.processEvents() with self.subTest("test_ExportMDF_0"): with ( mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getSaveFileName") as mc_getSaveFileName, mock.patch("asammdf.gui.widgets.file.setup_progress") as mo_setup_progress, ): mc_getSaveFileName.return_value = None, None QtTest.QTest.mouseClick(self.widget.apply_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() # Evaluate # Progress is not created mo_setup_progress.assert_not_called() # Case 1: self.processEvents() with self.subTest("test_ExportMDF_1"): saved_file = pathlib.Path(self.test_workspace, f"{self.id()}.mf4") with mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getSaveFileName") as mc_getSaveFileName: mc_getSaveFileName.return_value = str(saved_file), None QtTest.QTest.mouseClick(self.widget.apply_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents(1) # Wait for thread to finish self.processEvents(1) # Evaluate self.assertTrue(saved_file.exists()) # TearDown Widget with OpenMDF(saved_file) as mdf_file: for sig in mdf_file.iter_channels(): self.assertIn(sig.name, selected_channels) asammdf-8.5.1/test/asammdf/gui/widgets/plot/000077500000000000000000000000001502633300400207305ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/plot/__init__.py000066400000000000000000000000001502633300400230270ustar00rootroot00000000000000asammdf-8.5.1/test/asammdf/gui/widgets/plot/test_PlotWidget_ContextMenu.py000066400000000000000000001740521502633300400267650ustar00rootroot00000000000000#!/usr/bin/env python import json from json import JSONDecodeError import pathlib import re import sys import unittest from unittest import mock from unittest.mock import ANY from PySide6 import QtCore, QtGui, QtTest, QtWidgets from test.asammdf.gui.widgets.test_BasePlotWidget import TestPlotWidget class TestContextMenu(TestPlotWidget): # Note: Test Plot Widget through FileWidget. def setUp(self): super().setUp() self.setUpFileWidget(measurement_file=self.measurement_file, default=True) # Switch ComboBox to "Natural sort" self.widget.channel_view.setCurrentText("Natural sort") self.create_window(window_type="Plot", channels_indexes=[10, 11, 12, 13, 15]) self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) # Drag and Drop channel from FileWidget.channel_tree to Plot self.plot = self.widget.mdi_area.subWindowList()[0].widget() self.plot_channel_a = self.plot.channel_selection.topLevelItem(0) self.plot_channel_a.setCheckState(self.Column.NAME, QtCore.Qt.CheckState.Checked) self.plot_channel_b = self.plot.channel_selection.topLevelItem(1) self.plot_channel_b.setCheckState(self.Column.NAME, QtCore.Qt.CheckState.Checked) self.plot_channel_c = self.plot.channel_selection.topLevelItem(2) self.plot_channel_c.setCheckState(self.Column.NAME, QtCore.Qt.CheckState.Checked) self.plot_channel_d = self.plot.channel_selection.topLevelItem(3) self.plot_channel_d.setCheckState(self.Column.NAME, QtCore.Qt.CheckState.Checked) self.plot_channel_e = self.plot.channel_selection.topLevelItem(4) self.plot_channel_e.setCheckState(self.Column.NAME, QtCore.Qt.CheckState.Checked) self.processEvents() def test_Action_SearchItem_Cancel(self): """ Test Scope: Ensure that action 'Search Item' call 'QtWidgets.QInputDialog.getText' in order to get a channel name. The Dialog is canceled and nothing happens. Events: - Open Context Menu - Trigger 'Search Item' action - Simulate that the dialog is canceled. Evaluate: - Ensure that there is no selected channel because performing Right Click for ContextMenu will clear selection of the tree. """ QtTest.QTest.keyClick(self.plot.channel_selection.viewport(), QtCore.Qt.Key.Key_Down) self.assertEqual(1, len(self.plot.channel_selection.selectedItems())) with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = None, None self.context_menu(action_text="Search item") self.assertEqual(0, len(self.plot.channel_selection.selectedItems())) def test_Action_SearchItem_NonexistentChannel(self): """ Test Scope: Ensure that action 'Search Item' call 'QtWidgets.QInputDialog.getText' in order to get a channel name. The Dialog is filled with non-existing channel name. Events: - Open Context Menu - Trigger 'Search Item' action - Simulate that the dialog is filled with non-existing channel name. Evaluate: - Ensure that selection is cleared. - Ensure that MessageBox informs user. """ QtTest.QTest.keyClick(self.plot.channel_selection.viewport(), QtCore.Qt.Key.Key_Down) self.assertEqual(1, len(self.plot.channel_selection.selectedItems())) with ( mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText, mock.patch("asammdf.gui.widgets.tree.MessageBox.warning") as mo_warning, ): mo_getText.return_value = self.id(), True self.context_menu(action_text="Search item") self.assertEqual(0, len(self.plot.channel_selection.selectedItems())) mo_warning.assert_called_with(self.plot.channel_selection, "No matches found", ANY) def test_Action_SearchItem_ExistentChannel(self): """ Test Scope: Ensure that action 'Search Item' call 'QtWidgets.QInputDialog.getText' in order to get a channel name. The Dialog is filled with existing channel name. Found channel is selected on tree Events: - Open Context Menu - Trigger 'Search Item' action - Simulate that the dialog is filled with existing channel name. Evaluate: - Ensure that selection is set on the found channel. """ QtTest.QTest.keyClick(self.plot.channel_selection.viewport(), QtCore.Qt.Key.Key_Down) self.assertEqual(1, len(self.plot.channel_selection.selectedItems())) with ( mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText, mock.patch("asammdf.gui.widgets.tree.MessageBox.warning") as mo_warning, ): mo_getText.return_value = self.plot_channel_b.text(self.Column.NAME), True self.context_menu(action_text="Search item") self.assertEqual(1, len(self.plot.channel_selection.selectedItems())) mo_warning.assert_not_called() def test_Action_AddChannelGroup_Cancel(self): """ Test Scope: - Ensure that action 'Add channel group' will add new item (type Group) on tree. Events: - Open Context Menu - Trigger 'Add channel group' action - Simulate that the dialog is canceled. """ channels_nr = self.plot.channel_selection.topLevelItemCount() with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "FirstGroup", None self.context_menu(action_text="Add channel group") self.assertEqual(channels_nr, self.plot.channel_selection.topLevelItemCount()) def test_Action_AddChannelGroup(self): """ Test Scope: - Ensure that action 'Add channel group' will add new item (type Group) on tree. Events: - Open Context Menu - Trigger 'Add channel group' action - Simulate that the dialog is confirmed. Evaluate: - Check if there is one extra element in tree. """ channels_nr = self.plot.channel_selection.topLevelItemCount() with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "FirstGroup", True self.context_menu(action_text="Add channel group") self.assertEqual(channels_nr + 1, self.plot.channel_selection.topLevelItemCount()) def test_Action_CopyNames(self): """ Test Scope: - Ensure that action 'Copy Names' will place channel names in clipboard. Events: - Select one channel - Open Context Menu - Trigger 'Copy Names' action - Select two channels - Open Context Menu - Trigger 'Copy Names' action Evaluate: - Evaluate that channels names are placed in clipboard. """ with self.subTest("1Channel"): position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text="Copy names", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() self.assertEqual(self.plot_channel_a.text(self.Column.NAME), clipboard) with self.subTest("2Channels"): self.plot_channel_a.setSelected(True) self.plot_channel_b.setSelected(True) position_1 = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() self.context_menu(action_text="Copy names", position=position_1) clipboard = QtWidgets.QApplication.instance().clipboard().text() channels = (self.plot_channel_a.text(self.Column.NAME), self.plot_channel_b.text(self.Column.NAME)) self.assertEqual("\n".join(channels), clipboard) def test_Action_CopyNamesAndValues(self): """ Test Scope: - Ensure that action 'Copy names and value' will place channel names in clipboard. Events: - Select one channel - Open Context Menu - Trigger 'Copy names and value' action - Select two channels - Open Context Menu - Trigger 'Copy names and value' action Evaluate: - Evaluate that channels names are placed in clipboard. """ with self.subTest("1Channel"): position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text="Copy names and values", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() pattern_name = re.escape(self.plot_channel_a.text(self.Column.NAME)) pattern_unit = re.escape(self.plot_channel_a.text(self.Column.UNIT)) self.assertRegex(clipboard, expected_regex=f"{pattern_name}, t = \\d+[.]?\\d+s, \\d+[.]?\\d+{pattern_unit}") with self.subTest("2Channels"): self.plot_channel_a.setSelected(True) self.plot_channel_b.setSelected(True) position_1 = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() self.context_menu(action_text="Copy names and values", position=position_1) clipboard = QtWidgets.QApplication.instance().clipboard().text() expected_regex = [] for channel in (self.plot_channel_a, self.plot_channel_b): pattern_name = re.escape(channel.text(self.Column.NAME)) pattern_unit = re.escape(channel.text(self.Column.UNIT)) expected_regex.append(f"{pattern_name}, t = \\d+[.]?\\d+s, \\d+[.]?\\d+{pattern_unit}") self.assertRegex(clipboard, "\\n".join(expected_regex)) def test_Action_CopyDisplayProperties_Channel(self): """ Test Scope: - Ensure that channel display properties are copied in clipboard. Events: - Select one channel - Open Context Menu - Trigger 'Copy display properties' action Evaluate: - Evaluate that channel display properties are stored in clipboard in json format. """ position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text="Copy display properties", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() try: content = json.loads(clipboard) except JSONDecodeError: self.fail("Clipboard Content cannot be decoded as JSON content.") else: self.assertIsInstance(content, dict) def test_Action_PasteDisplayProperties_Channel(self): """ Test Scope: - Ensure that channel display properties can be pasted over different channel. Events: - Select one channel - Open Context Menu - Trigger 'Copy display properties' action - Select a different channel - Open Context Menu - Trigger 'Paste display properties' action - Select dst channel - Open Context Menu - Trigger 'Copy display properties' action Evaluate: - Evaluate that display properties are transferred from one channel to another """ action_copy = "Copy display properties" action_paste = "Paste display properties" position_src = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text=action_copy, position=position_src) channel_a_properties = QtWidgets.QApplication.instance().clipboard().text() # Paste position_dst = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() self.context_menu(action_text=action_paste, position=position_dst) # Copy position_src = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() self.context_menu(action_text=action_copy, position=position_src) channel_b_properties = QtWidgets.QApplication.instance().clipboard().text() self.assertEqual(channel_a_properties, channel_b_properties) def test_Action_CopyChannelStructure_Channel(self): """ Test Scope: - Ensure that channel structure is copied in clipboard. Events: - Select one channel - Open Context Menu - Trigger 'Copy channel structure' action Evaluate: - Evaluate that channel structure is stored in clipboard in json format. """ position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text="Copy channel structure", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() try: content = json.loads(clipboard) except JSONDecodeError: self.fail("Clipboard Content cannot be decoded as JSON content.") else: self.assertIsInstance(content, list) for channel_properties in content: self.assertIsInstance(channel_properties, dict) def test_Action_PasteChannelStructure_Channel(self): """ Test Scope: - Ensure that channel and structure is duplicated and structure is kept. Events: - Select one channel - Open Context Menu - Trigger 'Copy display properties' action - Trigger 'Copy channel structure' action - Open Context Menu - Trigger 'Paste channel structure' action - Select dst channel - Open Context Menu - Trigger 'Copy display properties' action Evaluate: - Evaluate that channel is duplicated and structure is kept. """ action_copy_dsp_properties = "Copy display properties" action_copy = "Copy channel structure" action_paste = "Paste channel structure" position_src = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() # Copy Channel Structure self.context_menu(action_text=action_copy, position=position_src) channels_count = self.plot.channel_selection.topLevelItemCount() # Paste Channel Structure self.context_menu(action_text=action_paste) self.assertEqual(channels_count + 1, self.plot.channel_selection.topLevelItemCount()) channels = self.plot.channel_selection.findItems( self.plot_channel_a.text(self.Column.NAME), QtCore.Qt.MatchFlags() ) self.assertEqual(2, len(channels)) # Copy DSP Properties channel_properties = [] for channel in channels: position_src = self.plot.channel_selection.visualItemRect(channel).center() self.context_menu(action_text=action_copy_dsp_properties, position=position_src) channel_properties.append(QtWidgets.QApplication.instance().clipboard().text()) self.assertEqual(channel_properties[0], channel_properties[1]) self.processEvents(0.2) def test_Menu_EnableDisable_Action_DeactivateGroups_Channel(self): """ Test Scope: - Ensure that group items can be disabled from Context Menu. Events: - Select 1 channel - Open Context Menu - Trigger "Enable/Disable -> Deactivate Groups" action Expected: - Individual channels that are not part of group should not be affected """ # Events position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text="Deactivate groups", position=position) # Evaluate self.assertEqual(False, self.plot_channel_a.isDisabled()) def test_Menu_EnableDisable_Action_DisableAllButThis(self): """ Test Scope: - Ensure that all channels are disabled except the item selected. Events: - Open Context Menu - Select action "Disable all but this" from sub-menu "Enable/disable" Expected: - Evaluate that all channels are disabled except selected item. """ with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "A", True self.context_menu(action_text="Add channel group") positions_src = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() self.context_menu(action_text="Disable all but this", position=positions_src) # Evaluate self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.NAME)) count = self.plot.channel_selection.topLevelItemCount() for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info and item != self.plot_channel_b: self.assertEqual(QtCore.Qt.CheckState.Unchecked, item.checkState(self.Column.NAME)) def test_Menu_ShowHide_Action_HideDisabledItems(self): """ Test Scope: - Ensure that item is hidden from channel selection when is disabled. Events: - Disable 1 channel by key Space - Disable 1 channel by mouseClick on item CheckBox Evaluate: - Evaluate that items that are unchecked are not present anymore on channel selection """ self.context_menu(action_text="Hide disabled items") with self.subTest("DisableBySpace"): # Select one channel self.mouseClick_WidgetItem(self.plot_channel_a) # Event QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Space) # Evaluate self.assertTrue(self.plot_channel_a.isHidden()) with self.subTest("DisableByClick"): pos = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() # Magic Number to detect center of checkbox pos = QtCore.QPoint(28, pos.y()) # Event QtTest.QTest.mouseClick( self.plot.channel_selection.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, pos, ) # Evaluate self.assertTrue(self.plot_channel_b.isHidden()) def test_Menu_ShowHide_Action_ShowDisabledItems(self): """ Test Scope: - Ensure that item is showed on channel selection when is disabled. Events: - Disable 1 channel by key Space - Disable 1 channel by mouseClick on item CheckBox Evaluate: - Evaluate that items that are unchecked are not present anymore on channel selection """ with self.subTest("DisableBySpace"): self.context_menu(action_text="Hide disabled items") # Select one channel self.mouseClick_WidgetItem(self.plot_channel_a) # Event QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Space) # Evaluate self.assertTrue(self.plot_channel_a.isHidden()) self.context_menu(action_text="Hide disabled items") self.assertFalse(self.plot_channel_a.isHidden()) with self.subTest("DisableByClick"): self.context_menu(action_text="Hide disabled items") pos = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() # Magic Number to detect center of checkbox pos = QtCore.QPoint(28, pos.y()) # Event QtTest.QTest.mouseClick( self.plot.channel_selection.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, pos, ) # Evaluate self.assertTrue(self.plot_channel_b.isHidden()) self.context_menu(action_text="Hide disabled items") self.assertFalse(self.plot_channel_b.isHidden()) def test_Menu_ShowHide_Action_HideMissingItems(self): """ Test Scope: - Ensure that missing item is hidden from channel selection. Events: - Disable 1 channel by key Space - Disable 1 channel by mouseClick on item CheckBox Evaluate: - Evaluate that missing items are not present anymore on channel selection """ dspf_filepath = pathlib.Path(self.resource, "missingItems.dspf") self.load_display_file(display_file=dspf_filepath) self.plot = self.widget.mdi_area.subWindowList()[0].widget() plot_channel = self.find_channel(channel_tree=self.plot.channel_selection, channel_name="1stMissingItem") self.processEvents() self.assertFalse(plot_channel.isHidden()) # Events self.context_menu(action_text="Hide missing items") # Evaluate self.assertTrue(plot_channel.isHidden()) self.processEvents(timeout=0.01) def test_Menu_ShowHide_Action_ShowMissingItems(self): """ Test Scope: - Ensure that missing item is visible from channel selection. Events: - Open Context Menu - Select action: Hide missing items - Disable 1 channel by key Space - Disable 1 channel by mouseClick on item CheckBox Evaluate: - Evaluate that missing items are present anymore on channel selection """ dspf_filepath = pathlib.Path(self.resource, "missingItems.dspf") self.load_display_file(display_file=dspf_filepath) self.plot = self.widget.mdi_area.subWindowList()[0].widget() self.context_menu(action_text="Hide missing items") plot_channel = self.find_channel(channel_tree=self.plot.channel_selection, channel_name="1stMissingItem") self.processEvents() self.assertTrue(plot_channel.isHidden()) # Events self.context_menu(action_text="Hide missing items") # Evaluate self.assertFalse(plot_channel.isHidden()) self.processEvents(timeout=0.01) def test_Menu_ShowHide_Action_FilterOnlyComputedChannels(self): """ Test Scope: - Ensure that all channels are hidden from channel selection except VirtualChannels. Events: - Open Context Menu - Select Filter Only Computed Channels Evaluate: - Evaluate that channels items are not present anymore on channel selection except VirtualChannels. """ dspf_filepath = pathlib.Path(self.resource, "missingItems.dspf") self.load_display_file(display_file=dspf_filepath) self.plot = self.widget.mdi_area.subWindowList()[0].widget() iterator = QtWidgets.QTreeWidgetItemIterator(self.plot.channel_selection) while iterator.value(): item = iterator.value() if item: self.assertFalse(item.isHidden()) iterator += 1 # Events self.context_menu(action_text="Filter only computed channels") # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.plot.channel_selection) while iterator.value(): item = iterator.value() if item and item.text(0) == "FirstVirtualChannel": self.assertFalse(item.isHidden()) else: self.assertTrue(item.isHidden()) iterator += 1 def test_Menu_ShowHide_Action_UnfilterComputedChannels(self): """ Test Scope: - Ensure that all channels are hidden from channel selection except VirtualChannels. Events: - Open Context Menu - Select Filter Only Computed Channels Evaluate: - Evaluate that channels items are not present anymore on channel selection except VirtualChannels. """ dspf_filepath = pathlib.Path(self.resource, "missingItems.dspf") self.load_display_file(display_file=dspf_filepath) self.plot = self.widget.mdi_area.subWindowList()[0].widget() # Events self.context_menu(action_text="Filter only computed channels") # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.plot.channel_selection) while iterator.value(): item = iterator.value() if item and item.text(0) == "FirstVirtualChannel": self.assertFalse(item.isHidden()) else: self.assertTrue(item.isHidden()) iterator += 1 # Events self.context_menu(action_text="Filter only computed channels") # Evaluate iterator = QtWidgets.QTreeWidgetItemIterator(self.plot.channel_selection) while iterator.value(): item = iterator.value() if item: self.assertFalse(item.isHidden()) iterator += 1 def test_Action_EditYAxisScaling(self): """ Test Scope: - Ensure that action forwards the request to plot. Event: - Select channel - Open Context Menu - Select 'Edit Y axis scaling' Evaluate: - Evaluate that event is forwarded to plot """ # Setup position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() with mock.patch.object(self.plot, "keyPressEvent") as mo_keyPressEvent: self.context_menu(action_text="Edit Y axis scaling", position=position) mo_keyPressEvent.assert_called() event = mo_keyPressEvent.call_args.args[0] self.assertEqual(QtCore.QEvent.Type.KeyPress, event.type()) self.assertEqual(QtCore.Qt.Key.Key_G, event.key()) self.assertEqual(QtCore.Qt.KeyboardModifier.ControlModifier, event.modifiers()) def test_Action_AddToCommonYAxis(self): """ Test Scope: - Ensure that action will mark as checked checkbox for Y Axis. Event: - Select one channel - Open Context Menu - Select 'Add to common Y axis' - Select two channels - Open Context Menu - Select 'Add to common Y axis' Evaluate: - Evaluate that checkbox on column COMMON_AXIS is checked. """ with self.subTest("1Channel"): self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.COMMON_AXIS)) position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text="Add to common Y axis", position=position) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.COMMON_AXIS)) self.context_menu(action_text="Add to common Y axis", position=position) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.COMMON_AXIS)) with self.subTest("2Channels"): self.plot_channel_b.setSelected(True) self.plot_channel_c.setSelected(True) self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.COMMON_AXIS)) self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_c.checkState(self.Column.COMMON_AXIS)) position = self.plot.channel_selection.visualItemRect(self.plot_channel_c).center() self.context_menu(action_text="Add to common Y axis", position=position) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.COMMON_AXIS)) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_c.checkState(self.Column.COMMON_AXIS)) self.context_menu(action_text="Add to common Y axis", position=position) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.COMMON_AXIS)) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_c.checkState(self.Column.COMMON_AXIS)) def test_Action_RemoveFromCommonYAxis(self): """ Test Scope: - Ensure that action will mark as unchecked checkbox for Y Axis. Event: - Select one channel - Open Context Menu - Select 'Remove from common Y axis' - Select two channels - Open Context Menu - Select 'Remove from common Y axis' Evaluate: - Evaluate that checkbox on column COMMON_AXIS is unchecked. """ with self.subTest("1Channel"): # Setup position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() # Pre-evaluation self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.COMMON_AXIS)) # Event self.context_menu(action_text="Remove from common Y axis", position=position) # Evaluate self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.COMMON_AXIS)) # Event self.context_menu(action_text="Add to common Y axis", position=position) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.COMMON_AXIS)) self.context_menu(action_text="Remove from common Y axis", position=position) # Evaluate self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.COMMON_AXIS)) # Event self.context_menu(action_text="Remove from common Y axis", position=position) # Evaluate self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.COMMON_AXIS)) with self.subTest("2Channels"): # Setup self.plot_channel_b.setSelected(True) self.plot_channel_c.setSelected(True) position_c = self.plot.channel_selection.visualItemRect(self.plot_channel_c).center() # Pre-evaluation self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.COMMON_AXIS)) self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_c.checkState(self.Column.COMMON_AXIS)) # Event self.context_menu(action_text="Remove from common Y axis", position=position_c) # Evaluate self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.COMMON_AXIS)) self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_c.checkState(self.Column.COMMON_AXIS)) # Event self.context_menu(action_text="Add to common Y axis", position=position_c) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.COMMON_AXIS)) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_c.checkState(self.Column.COMMON_AXIS)) self.context_menu(action_text="Remove from common Y axis", position=position) # Evaluate self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.COMMON_AXIS)) self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_c.checkState(self.Column.COMMON_AXIS)) # Event self.context_menu(action_text="Remove from common Y axis", position=position) # Evaluate self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.COMMON_AXIS)) self.assertNotEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_c.checkState(self.Column.COMMON_AXIS)) def test_Action_SetColor(self): """ Test Scope: - Ensure that channel color is changed. Events: - Open Context Menu - Select 'Set color [C]' - Select 1 Channel - Open Context Menu - Select 'Set color [C]' - Select 2 Channels - Open Context Menu - Select 'Set color' Evaluate: - Evaluate that color dialog is not open if channel is not selected. - Evaluate that channel color is changed. """ action_text = "Set color" # Event with self.subTest("NoChannelSelected"): with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: self.context_menu(action_text=action_text) mo_getColor.assert_not_called() with self.subTest("1ChannelSelected"): position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: # Setup previous_color = self.plot_channel_a.color.name() color = QtGui.QColor("red") color_name = color.name() mo_getColor.return_value = color # Event self.context_menu(action_text=action_text, position=position) # Evaluate current_color = self.plot_channel_a.color.name() mo_getColor.assert_called() self.assertNotEqual(previous_color, current_color) self.assertEqual(color_name, current_color) with self.subTest("2ChannelsSelected"): self.mouseClick_WidgetItem(self.plot_channel_b) self.plot_channel_b.setSelected(True) self.plot_channel_c.setSelected(True) position = self.plot.channel_selection.visualItemRect(self.plot_channel_c).center() with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: # Setup previous_b_color = self.plot_channel_b.color.name() previous_c_color = self.plot_channel_c.color.name() color = QtGui.QColor("blue") color_name = color.name() mo_getColor.return_value = color # Event self.context_menu(action_text=action_text, position=position) # Evaluate current_b_color = self.plot_channel_b.color.name() current_c_color = self.plot_channel_c.color.name() mo_getColor.assert_called() self.assertNotEqual(previous_b_color, current_b_color) self.assertNotEqual(previous_c_color, current_c_color) self.assertEqual(color_name, current_b_color) self.assertEqual(color_name, current_c_color) def test_Action_SetRandomColor(self): """ Test Scope: - Ensure that channel color is changed. Events: - Open Context Menu - Select 'Set random color' - Select 1 Channel - Open Context Menu - Select 'Set random color' - Select 2 Channels - Open Context Menu - Select 'Set random color' Evaluate: - Evaluate that color dialog is not open if channel is not selected. - Evaluate that channel color is changed. """ action_text = "Set random color" # Event with self.subTest("NoChannelSelected"): with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QColorDialog.getColor") as mo_getColor: self.context_menu(action_text=action_text) mo_getColor.assert_not_called() with self.subTest("1ChannelSelected"): position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() # Setup previous_color = self.plot_channel_a.color.name() # Event self.context_menu(action_text=action_text, position=position) # Evaluate current_color = self.plot_channel_a.color.name() self.assertNotEqual(previous_color, current_color) with self.subTest("2ChannelsSelected"): self.mouseClick_WidgetItem(self.plot_channel_b) self.plot_channel_b.setSelected(True) self.plot_channel_c.setSelected(True) position = self.plot.channel_selection.visualItemRect(self.plot_channel_c).center() # Setup previous_b_color = self.plot_channel_b.color.name() previous_c_color = self.plot_channel_c.color.name() # Event self.context_menu(action_text=action_text, position=position) # Evaluate current_b_color = self.plot_channel_b.color.name() current_c_color = self.plot_channel_c.color.name() self.assertNotEqual(previous_b_color, current_b_color) self.assertNotEqual(previous_c_color, current_c_color) self.assertNotEqual(current_b_color, current_c_color) @unittest.skipIf(sys.platform == "win32", "times out on Windows") def test_Action_CopyDisplayProperties_Group(self): """ Test Scope: - Ensure that first channel display properties are copied in clipboard if item selected is group item. Events: - Insert Empty Group - Select Group - Trigger 'Copy display properties' action - Add items to group - Open Context Menu - Trigger 'Copy display properties' action - Remove channel from group - Open Context Menu - Trigger 'Copy display properties' action Evaluate: - Evaluate that channel display properties are stored in clipboard in json format. """ with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "A", True self.context_menu(action_text="Add channel group") mo_getText.return_value = "B", True self.context_menu(action_text="Add channel group") mo_getText.return_value = "C", True self.context_menu(action_text="Add channel group") group_channel_a = self.plot.channel_selection.findItems("A", QtCore.Qt.MatchFlags())[0] group_channel_b = self.plot.channel_selection.findItems("B", QtCore.Qt.MatchFlags())[0] group_channel_c = self.plot.channel_selection.findItems("C", QtCore.Qt.MatchFlags())[0] QtWidgets.QApplication.instance().clipboard().clear() with self.subTest("EmptyGroup_0"): position = self.plot.channel_selection.visualItemRect(group_channel_a).center() self.context_menu(action_text="Copy display properties", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() try: content = json.loads(clipboard) except JSONDecodeError: self.fail("Clipboard Content cannot be decoded as JSON content.") else: self.assertIsInstance(content, dict) self.assertTrue(content["type"] == "group") with self.subTest("PopulatedGroup"): # Add Channels to Group self.move_item_inside_channels_tree_widget(src=self.plot_channel_a, dst=group_channel_a) position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text="Copy display properties", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() try: content = json.loads(clipboard) except JSONDecodeError: self.fail("Clipboard Content cannot be decoded as JSON content.") else: self.assertIsInstance(content, dict) self.assertTrue(content["type"] == "channel") with self.subTest("EmptyGroup_1"): group_channel_a.removeChild(self.plot_channel_a) position = self.plot.channel_selection.visualItemRect(group_channel_a).center() self.context_menu(action_text="Copy display properties", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() try: content = json.loads(clipboard) except JSONDecodeError: self.fail("Clipboard Content cannot be decoded as JSON content.") else: self.assertIsInstance(content, dict) self.assertTrue(content["type"] == "group") with self.subTest("EmptyGroup_2"): # Add Channels to Group self.move_item_inside_channels_tree_widget(src=group_channel_c, dst=group_channel_b) group_channel_a.setExpanded(True) group_channel_b.setExpanded(True) group_channel_c.setExpanded(True) self.move_item_inside_channels_tree_widget(src=group_channel_b, dst=group_channel_a) group_channel_a.setExpanded(True) group_channel_b.setExpanded(True) group_channel_c.setExpanded(True) position = self.plot.channel_selection.visualItemRect(group_channel_a).center() self.context_menu(action_text="Copy display properties", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() try: content = json.loads(clipboard) except JSONDecodeError: self.fail("Clipboard Content cannot be decoded as JSON content.") else: self.assertIsInstance(content, dict) self.assertTrue(content["type"] == "group") def test_Action_PasteDisplayProperties_Group(self): """ Test Scope: - Ensure that channel display properties can be pasted over different channel. Events: - Select one channel - Open Context Menu - Trigger 'Copy display properties' action - Select a group channel - Open Context Menu - Trigger 'Paste display properties' action - Select group channel - Open Context Menu - Trigger 'Copy display properties' action - Select a channel - Open Context Menu - Trigger 'Paste display properties' action Evaluate: - Evaluate that display properties are transferred from one channel to another """ action_copy = "Copy display properties" action_paste = "Paste display properties" # Insert Group with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "A", True self.context_menu(action_text="Add channel group") mo_getText.return_value = "B", True self.context_menu(action_text="Add channel group") mo_getText.return_value = "C", True self.context_menu(action_text="Add channel group") # Add Channels to Group group_channel_a = self.plot.channel_selection.findItems("A", QtCore.Qt.MatchFlags())[0] group_channel_a.setExpanded(True) group_channel_c = self.plot.channel_selection.findItems("C", QtCore.Qt.MatchFlags())[0] group_channel_c.setExpanded(True) self.move_item_inside_channels_tree_widget(src=group_channel_c, dst=group_channel_a) group_channel_a.setExpanded(True) group_channel_c.setExpanded(True) self.move_item_inside_channels_tree_widget(src=self.plot_channel_b, dst=group_channel_c) # Add Channels to Group group_channel_b = self.plot.channel_selection.findItems("B", QtCore.Qt.MatchFlags())[0] group_channel_b.setExpanded(True) self.move_item_inside_channels_tree_widget(src=self.plot_channel_d, dst=group_channel_b) with self.subTest("FromChannel_ToGroup"): position_src = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text=action_copy, position=position_src) channel_a_properties = QtWidgets.QApplication.instance().clipboard().text() channel_a_properties = json.loads(channel_a_properties) # Paste position_dst = self.plot.channel_selection.visualItemRect(group_channel_a).center() self.context_menu(action_text=action_paste, position=position_dst) # Copy position_src = self.plot.channel_selection.visualItemRect(group_channel_a).center() self.context_menu(action_text=action_copy, position=position_src) group_channel_properties = QtWidgets.QApplication.instance().clipboard().text() group_channel_properties = json.loads(group_channel_properties) # Evaluate self.assertEqual(channel_a_properties["ranges"], group_channel_properties["ranges"]) with self.subTest("FromGroup_ToChannel"): position_src = self.plot.channel_selection.visualItemRect(group_channel_a).center() self.context_menu(action_text=action_copy, position=position_src) # Paste position_dst = self.plot.channel_selection.visualItemRect(self.plot_channel_c).center() self.context_menu(action_text=action_paste, position=position_dst) # Copy position_src = self.plot.channel_selection.visualItemRect(self.plot_channel_c).center() self.context_menu(action_text=action_copy, position=position_src) channel_c_properties = QtWidgets.QApplication.instance().clipboard().text() channel_c_properties = json.loads(channel_c_properties) # Evaluate self.assertEqual(channel_c_properties["ranges"], group_channel_properties["ranges"]) with self.subTest("FromGroup_ToGroup"): self.move_item_inside_channels_tree_widget(src=self.plot_channel_a, dst=group_channel_a) position_src = self.plot.channel_selection.visualItemRect(group_channel_b).center() self.context_menu(action_text=action_copy, position=position_src) group_channel_b_properties = QtWidgets.QApplication.instance().clipboard().text() group_channel_b_properties = json.loads(group_channel_b_properties) # Paste position_dst = self.plot.channel_selection.visualItemRect(group_channel_a).center() self.context_menu(action_text=action_paste, position=position_dst) # Copy position_src = self.plot.channel_selection.visualItemRect(group_channel_a).center() self.context_menu(action_text=action_copy, position=position_src) group_channel_a_properties = QtWidgets.QApplication.instance().clipboard().text() group_channel_a_properties = json.loads(group_channel_a_properties) # Evaluate self.assertEqual(group_channel_a_properties, group_channel_b_properties) @unittest.skipIf(sys.platform == "win32", "times out on Windows") def test_Action_CopyChannelStructure_Group(self): """ Test Scope: - Ensure that channel structure is copied in clipboard. Events: - Select one group - Open Context Menu - Trigger 'Copy channel structure' action Evaluate: - Evaluate that group channel structure is stored in clipboard in json format. """ with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "FirstGroup", True self.context_menu(action_text="Add channel group") # Add Channels to Group group_channel = self.plot.channel_selection.findItems("FirstGroup", QtCore.Qt.MatchFlags())[0] self.move_item_inside_channels_tree_widget(src=self.plot_channel_a, dst=group_channel) position = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text="Copy channel structure", position=position) clipboard = QtWidgets.QApplication.instance().clipboard().text() try: content = json.loads(clipboard) except JSONDecodeError: self.fail("Clipboard Content cannot be decoded as JSON content.") else: self.assertIsInstance(content, list) for channel_properties in content: self.assertIsInstance(channel_properties, dict) def test_Action_PasteChannelStructure_Group(self): """ Test Scope: - Ensure that channel and structure is duplicated and structure is kept. Events: - Create group - Add channels to group - Open Context Menu - Trigger 'Copy channel structure' action - Trigger 'Paste channel structure' action over new group Evaluate: - Evaluate that group channel is duplicated and structure is kept. """ action_copy = "Copy channel structure" action_paste = "Paste channel structure" with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "FirstGroup", True self.context_menu(action_text="Add channel group") # Add Channels to Group group_channel = self.plot.channel_selection.findItems("FirstGroup", QtCore.Qt.MatchFlags())[0] group_channel.setExpanded(True) self.move_item_inside_channels_tree_widget(src=self.plot_channel_c, dst=group_channel) self.move_item_inside_channels_tree_widget(src=self.plot_channel_d, dst=group_channel) # Copy Channel Structure position_src = self.plot.channel_selection.visualItemRect(group_channel).center() self.context_menu(action_text=action_copy, position=position_src) channels_count = self.plot.channel_selection.topLevelItemCount() # Paste Channel Structure position_src = self.plot.channel_selection.visualItemRect(self.plot_channel_a).center() self.context_menu(action_text=action_paste, position=position_src) self.processEvents(0.1) self.assertEqual(channels_count + 1, self.plot.channel_selection.topLevelItemCount()) self.assertEqual(2, len(self.plot.channel_selection.findItems("FirstGroup", QtCore.Qt.MatchFlags()))) def test_Menu_EnableDisable_Action_DisableSelected(self): """ Test Scope: - Ensure that channel selected is disabled. Events: - Disable all - Open Context Menu - Select action "Disable selected" from sub-menu "Enable/disable" - Select two channel items - Open Context Menu - Select action "Disable selected" from sub-menu "Enable/disable" - Select channel group - Open Context Menu - Select action "Disable selected" from sub-menu "Enable/disable" Expected: - Evaluate that selected items were disabled. """ with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "A", True self.context_menu(action_text="Add channel group") # Add Channels to Group group_channel = self.plot.channel_selection.findItems("A", QtCore.Qt.MatchFlags())[0] self.move_item_inside_channels_tree_widget(src=self.plot_channel_c, dst=group_channel) self.context_menu(action_text="Disable selected") # Ensure that all items are disabled count = self.plot.channel_selection.topLevelItemCount() for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: self.assertEqual(QtCore.Qt.CheckState.Checked, item.checkState(self.Column.NAME)) # Select two channels self.plot_channel_a.setSelected(True) self.plot_channel_b.setSelected(True) position_src = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() self.context_menu(action_text="Disable selected", position=position_src) self.assertEqual(QtCore.Qt.CheckState.Unchecked, self.plot_channel_a.checkState(self.Column.NAME)) self.assertEqual(QtCore.Qt.CheckState.Unchecked, self.plot_channel_b.checkState(self.Column.NAME)) # Select group position_src = self.plot.channel_selection.visualItemRect(group_channel).center() self.context_menu(action_text="Disable selected", position=position_src) self.assertEqual(QtCore.Qt.CheckState.Unchecked, group_channel.checkState(self.Column.NAME)) def test_Menu_EnableDisable_Action_DeactivateGroups_Group(self): """ Test Scope: - Ensure that group items can be disabled from Context Menu. Events: - Add two groups - Add channels to group - Add group in group - Select 1 group - Open Context Menu - Trigger "Enable/Disable -> Deactivate Groups" action Expected: - Group Items should be disabled - Sub-groups should be disabled """ with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "Group_A", True self.context_menu(action_text="Add channel group") mo_getText.return_value = "Group_B", True self.context_menu(action_text="Add channel group") # Add Channels to Group group_a_channel = self.plot.channel_selection.findItems("Group_A", QtCore.Qt.MatchFlags())[0] group_a_channel.setExpanded(True) self.move_item_inside_channels_tree_widget(src=self.plot_channel_a, dst=group_a_channel) self.move_item_inside_channels_tree_widget(src=self.plot_channel_b, dst=group_a_channel) # Add Channels to Group group_b_channel = self.plot.channel_selection.findItems("Group_B", QtCore.Qt.MatchFlags())[0] group_b_channel.setExpanded(True) self.move_item_inside_channels_tree_widget(src=self.plot_channel_c, dst=group_b_channel) self.move_item_inside_channels_tree_widget(src=self.plot_channel_d, dst=group_b_channel) self.move_item_inside_channels_tree_widget(src=group_b_channel, dst=group_a_channel) group_a_channel.setExpanded(True) group_b_channel.setExpanded(True) position = self.plot.channel_selection.visualItemRect(group_b_channel).center() self.context_menu(action_text="Deactivate groups", position=position) # Evaluate self.assertEqual(False, group_a_channel.isDisabled()) self.assertEqual(True, group_b_channel.isDisabled()) for child_index in range(group_b_channel.childCount()): child = group_b_channel.child(child_index) self.assertEqual(True, child.isDisabled()) for child_index in range(group_a_channel.childCount()): child = group_a_channel.child(child_index) if child.type() == child.Channel: self.assertEqual(False, child.isDisabled()) position = self.plot.channel_selection.visualItemRect(group_a_channel).center() self.context_menu(action_text="Deactivate groups", position=position) # Evaluate self.assertEqual(True, group_a_channel.isDisabled()) self.assertEqual(True, group_b_channel.isDisabled()) for child_index in range(group_b_channel.childCount()): child = group_b_channel.child(child_index) self.assertEqual(True, child.isDisabled()) for child_index in range(group_a_channel.childCount()): child = group_a_channel.child(child_index) self.assertEqual(True, child.isDisabled()) def test_Menu_EnableDisable_Action_DisableAll(self): """ Test Scope: - Ensure that all channels are disabled. Events: - Open Context Menu - Select action "Disable All" from sub-menu "Enable/disable" - Disable elements - Open Context Menu - Select action "Disable All" from sub-menu "Enable/disable" Expected: - Evaluate that all items are disabled. """ with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "A", True self.context_menu(action_text="Add channel group") # Add Channels to Group group_channel = self.plot.channel_selection.findItems("A", QtCore.Qt.MatchFlags())[0] self.move_item_inside_channels_tree_widget(src=self.plot_channel_a, dst=group_channel) self.processEvents(1) # Ensure that all items are enabled count = self.plot.channel_selection.topLevelItemCount() for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: self.assertEqual(QtCore.Qt.CheckState.Checked, item.checkState(self.Column.NAME)) self.context_menu(action_text="Disable all") # Ensure that all items are disabled count = self.plot.channel_selection.topLevelItemCount() for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: self.assertEqual(QtCore.Qt.CheckState.Unchecked, item.checkState(self.Column.NAME)) # Disable items item.setCheckState(self.Column.NAME, QtCore.Qt.CheckState.Checked) self.context_menu(action_text="Disable all") for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: self.assertEqual(QtCore.Qt.CheckState.Unchecked, item.checkState(self.Column.NAME)) def test_Menu_EnableDisable_Action_EnableSelected(self): """ Test Scope: - Ensure that channel selected is enabled. Events: - Disable all - Open Context Menu - Select action "Enable selected" from sub-menu "Enable/disable" - Select two channel items - Open Context Menu - Select action "Enable selected" from sub-menu "Enable/disable" - Select channel group - Open Context Menu - Select action "Enable selected" from sub-menu "Enable/disable" Expected: - Evaluate that selected items were enabled. """ with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "A", True self.context_menu(action_text="Add channel group") # Add Channels to Group group_channel = self.plot.channel_selection.findItems("A", QtCore.Qt.MatchFlags())[0] self.move_item_inside_channels_tree_widget(src=self.plot_channel_c, dst=group_channel) # Disable all items count = self.plot.channel_selection.topLevelItemCount() for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: item.setCheckState(self.Column.NAME, QtCore.Qt.CheckState.Unchecked) self.context_menu(action_text="Enable selected") # Ensure that all items are disabled count = self.plot.channel_selection.topLevelItemCount() for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: self.assertEqual(QtCore.Qt.CheckState.Unchecked, item.checkState(self.Column.NAME)) # Select two channels self.plot_channel_a.setSelected(True) self.plot_channel_b.setSelected(True) position_src = self.plot.channel_selection.visualItemRect(self.plot_channel_b).center() self.context_menu(action_text="Enable selected", position=position_src) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_a.checkState(self.Column.NAME)) self.assertEqual(QtCore.Qt.CheckState.Checked, self.plot_channel_b.checkState(self.Column.NAME)) # Select group position_src = self.plot.channel_selection.visualItemRect(group_channel).center() self.context_menu(action_text="Enable selected", position=position_src) self.assertEqual(QtCore.Qt.CheckState.Checked, group_channel.checkState(self.Column.NAME)) def test_Menu_EnableDisable_Action_EnableAll(self): """ Test Scope: - Ensure that all channels are enabled. Events: - Open Context Menu - Select action "Enable All" from sub-menu "Enable/disable" - Disable elements - Open Context Menu - Select action "Enable All" from sub-menu "Enable/disable" Expected: - Evaluate that all items are enabled. """ with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mo_getText: mo_getText.return_value = "A", True self.context_menu(action_text="Add channel group") # Add Channels to Group group_channel = self.plot.channel_selection.findItems("A", QtCore.Qt.MatchFlags())[0] self.move_item_inside_channels_tree_widget(src=self.plot_channel_a, dst=group_channel) # Ensure that all items are enabled: count = self.plot.channel_selection.topLevelItemCount() for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: self.assertEqual(QtCore.Qt.CheckState.Checked, item.checkState(self.Column.NAME)) self.context_menu(action_text="Enable all") # Ensure that all items are enabled: count = self.plot.channel_selection.topLevelItemCount() for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: self.assertEqual(QtCore.Qt.CheckState.Checked, item.checkState(self.Column.NAME)) # Disable items item.setCheckState(self.Column.NAME, QtCore.Qt.CheckState.Unchecked) self.context_menu(action_text="Enable all") for i in range(count): item = self.plot.channel_selection.topLevelItem(i) if item.type() != item.Info: self.assertEqual(QtCore.Qt.CheckState.Checked, item.checkState(self.Column.NAME)) asammdf-8.5.1/test/asammdf/gui/widgets/plot/test_PlotWidget_DoubleClick.py000066400000000000000000001050711502633300400266670ustar00rootroot00000000000000#!/usr/bin/env python import sys import unittest from unittest import mock from PySide6 import QtCore, QtGui, QtTest from test.asammdf.gui.test_base import Pixmap from test.asammdf.gui.widgets.test_BasePlotWidget import TestPlotWidget class TestDoubleClick(TestPlotWidget): # Note: Test Plot Widget through FileWidget. def setUp(self): super().setUp() # Open File Widget self.setUpFileWidget(measurement_file=self.measurement_file, default=True) # Switch ComboBox to "Natural sort" self.widget.channel_view.setCurrentText("Natural sort") # Create a plot window self.create_window(window_type="Plot") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) # Drag and Drop channel from FileWidget.channel_tree to Plot self.plot = self.widget.mdi_area.subWindowList()[0].widget() # Press PushButton 'FocusMode' - disabled (easy for evaluation) if not self.plot.focused_mode_btn.isFlat(): QtTest.QTest.mouseClick(self.plot.focused_mode_btn, QtCore.Qt.MouseButton.LeftButton) # Press PushButton "Hide axis" if not self.plot.hide_axes_btn.isFlat(): QtTest.QTest.mouseClick(self.plot.hide_axes_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() def test_ChannelSelection(self): """ Test Scope: Validate that doubleClick operation will activate deactivate channels. Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. - Drag and Drop channel from FileWidget.channel_tree to Plot - Press mouse double click on added channel - Press mouse double click on added channel Evaluate: - Evaluate that channel checkbox is unchecked. - Evaluate that channel checkbox is checked. """ # Event plot_channel = self.add_channel_to_plot() # Pre-evaluation self.assertEqual(QtCore.Qt.CheckState.Checked, plot_channel.checkState(0)) # Press mouse double click on channel self.mouseDClick_WidgetItem(plot_channel) # Evaluate self.assertEqual(QtCore.Qt.CheckState.Unchecked, plot_channel.checkState(0)) # Press mouse double click on channel self.mouseDClick_WidgetItem(plot_channel) self.assertEqual(QtCore.Qt.CheckState.Checked, plot_channel.checkState(0)) def test_EnableDisable_Group(self): """ Test Scope: Validate that doubleClick operation will activate deactivate groups. Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. - Drag and Drop channels from FileWidget.channel_tree to Plot - Press 'Shift-Insert' in order to Insert Group - Drag and Drop some channels to new Group - Press mouse double click on added group - Press key Down few times - Press mouse double click on added group - Press key Down few times Evaluate: - Evaluate that group is disabled (not selectable anymore). - Evaluate that channel is enabled (selectable). - Evaluate that channel is not present on plot when is disabled. """ # Event # Drag and Drop channel from FileWidget.channel_tree to Plot plot_channel_0 = self.add_channel_to_plot(channel_index=10) _ = self.add_channel_to_plot(channel_index=11) plot_channel_2 = self.add_channel_to_plot(channel_index=12) # Press 'Shift-Insert' in order to Insert Group # Create Channel Group. Drag channels inside the group one by one with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mc_getText: # Create Channel Group mc_getText.return_value = "FirstGroup", True QtTest.QTest.keySequence(self.plot.channel_selection, QtGui.QKeySequence("Shift+Insert")) self.processEvents() # Get Group Position for index in range(self.plot.channel_selection.topLevelItemCount()): item = self.plot.channel_selection.topLevelItem(index) if item.text(self.Column.NAME) == "FirstGroup": first_group = item break else: self.fail("FirstGroup is not present on Plot Channel Selection.") first_group.setExpanded(True) # Get the Name of the first channel first_channel = plot_channel_0.text(self.Column.NAME) # PreEvaluation: Ensure that group has no child self.assertEqual(0, first_group.childCount()) self.move_item_inside_channels_tree_widget(src=plot_channel_0, dst=first_group) # PreEvaluate: Ensure that channel was added to group self.assertEqual(1, first_group.childCount()) self.assertEqual(first_channel, first_group.child(0).text(self.Column.NAME)) self.assertEqual(3, self.plot.channel_selection.topLevelItemCount()) enabled_groups_pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertTrue( Pixmap.has_color( pixmap=enabled_groups_pixmap, color_name=plot_channel_0.color, ) ) # Press mouse double click on Group self.mouseDClick_WidgetItem(first_group) # Evaluate for _ in range(10): self.processEvents(0.05) disabled_groups_pixmap = self.plot.plot.viewport().grab() self.assertFalse( Pixmap.has_color( pixmap=disabled_groups_pixmap, color_name=plot_channel_0.color, ) ) for _ in range(4): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Evaluate that item is still 2nd one because selectedItems = self.plot.channel_selection.selectedItems() self.assertEqual(1, len(selectedItems)) selectedItem = selectedItems[0].text(self.Column.NAME) self.assertEqual(plot_channel_2.text(self.Column.NAME), selectedItem) # Press mouse double click on channel self.mouseDClick_WidgetItem(first_group) self.processEvents() for _ in range(4): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Evaluate that item is the one from the group selectedItems = self.plot.channel_selection.selectedItems() self.assertEqual(1, len(selectedItems)) selectedItem = selectedItems[0].text(self.Column.NAME) self.assertEqual(plot_channel_0.text(self.Column.NAME), selectedItem) # Evaluate # After channels are enabled, they first flash a few times on plot. # ProcessEvents few times for channels to be present for _ in range(20): self.processEvents(0.05) enabled_groups_pixmap = self.plot.plot.viewport().grab() self.assertTrue( Pixmap.has_color( pixmap=enabled_groups_pixmap, color_name=plot_channel_0.color, ), msg=f"Color of channel {plot_channel_0.text(self.Column.NAME)} is not present on plot.", ) @unittest.skipIf(sys.platform == "win32", "fails on Windows") def test_EnableDisable_ParentGroup(self): """ Test Scope: Validate that doubleClick operation will activate deactivate subgroups when parent is disabled. Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. - Drag and Drop channels from FileWidget.channel_tree to Plot - Press 'Shift-Insert' in order to Insert Group: A - Press 'Shift-Insert' in order to Insert Group: B - Press 'Shift-Insert' in order to Insert Group: C - Drag and Drop some channels to new Group: A - Drag and Drop some channels to new Group: B - Drag and Drop some channels to new Group: C - Move Group C inside Group B - Move Group B inside Group A - Press mouse double click on added group: A - Press key Down few times - Press mouse double click on added group: A - Press key Down few times Evaluate: - Evaluate that subgroups are disabled (not selectable anymore). - Evaluate that channels are enabled (selectable). - Evaluate that channel is not present on plot when is disabled. - Evaluate channel color is darkGray when it's disabled. """ # Event # Drag and Drop channel from FileWidget.channel_tree to Plot plot_channel_a = self.add_channel_to_plot(channel_index=10) plot_channel_b = self.add_channel_to_plot(channel_index=11) plot_channel_c = self.add_channel_to_plot(channel_index=12) plot_channel_d = self.add_channel_to_plot(channel_index=13) self.processEvents() # Press 'Shift-Insert' in order to Insert Group # Create Channel Group. Drag channels inside the group one by one groups = {} with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mc_getText: for group_name in ("A", "B", "C"): # Create Channel Group mc_getText.return_value = group_name, True QtTest.QTest.keySequence(self.plot.channel_selection, QtGui.QKeySequence("Shift+Insert")) self.processEvents() # Get Groups Position for index in range(self.plot.channel_selection.topLevelItemCount()): item = self.plot.channel_selection.topLevelItem(index) group_name = item.text(self.Column.NAME) if group_name in ("A", "B", "C"): groups[group_name] = item item.setExpanded(True) # Get the First Item that will be moved for group_name, plot_channel in zip( ("A", "B", "C"), (plot_channel_a, plot_channel_b, plot_channel_c), strict=False ): # PreEvaluation: Ensure that group has no child self.assertEqual(0, groups[group_name].childCount()) self.move_item_inside_channels_tree_widget(src=plot_channel, dst=groups[group_name]) self.assertEqual(1, groups[group_name].childCount()) self.processEvents() # Move Group C inside Group B self.move_item_inside_channels_tree_widget(src=groups["C"], dst=groups["B"]) # Move Group B inside Group A self.move_item_inside_channels_tree_widget(src=groups["B"], dst=groups["A"]) groups["A"].setExpanded(True) groups["B"].setExpanded(True) groups["C"].setExpanded(True) self.processEvents() enabled_groups_pixmap = self.plot.plot.viewport().grab() # Evaluate for channel in (plot_channel_a, plot_channel_b, plot_channel_c): self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=channel.color), msg=f"Color of Channel: {channel.text(self.Column.NAME)} not present on 'plot'.", ) color_name = channel.foreground(self.Column.NAME).color().name() self.assertNotEqual(color_name, "#808080") # Press mouse double click on Group A self.mouseDClick_WidgetItem(groups["A"]) # Evaluate for _ in range(10): self.processEvents(0.05) disabled_groups_pixmap = self.plot.plot.viewport().grab() for channel in (plot_channel_a, plot_channel_b, plot_channel_c): self.assertFalse( Pixmap.has_color( pixmap=disabled_groups_pixmap, color_name=channel.color, ), msg=f"Color of Channel: {channel.text(self.Column.NAME)} present on 'plot'.", ) QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Up) for _ in range(4): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Evaluate that item is still plot_channel_d selectedItems = self.plot.channel_selection.selectedItems() self.assertEqual(1, len(selectedItems)) selectedItem = selectedItems[0].text(self.Column.NAME) self.assertEqual(plot_channel_d.text(self.Column.NAME), selectedItem) # Press mouse double click on channel self.mouseDClick_WidgetItem(groups["A"]) self.processEvents() for _ in range(8): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Evaluate that item is the one from the group C selectedItems = self.plot.channel_selection.selectedItems() self.assertEqual(1, len(selectedItems)) selectedItem = selectedItems[0].text(self.Column.NAME) self.assertEqual(plot_channel_c.text(self.Column.NAME), selectedItem) # Evaluate # After channels are enabled, they first flash a few times on self.plot. # ProcessEvents few times for channels to be present for _ in range(20): self.processEvents(0.05) enabled_groups_pixmap = self.plot.plot.viewport().grab() for channel in ( plot_channel_a, plot_channel_b, plot_channel_c, plot_channel_d, ): self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=channel.color), msg=f"Color for Channel: {channel.text(self.Column.NAME)} not present on 'plot'", ) @unittest.skipIf(sys.platform == "win32", "fails on Windows") def test_EnableDisable_Subgroup(self): """ Test Scope: Validate that doubleClick operation will activate deactivate subgroups and keep parent enabled. Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. - Drag and Drop channels from FileWidget.channel_tree to Plot - Press 'Shift-Insert' in order to Insert Group: A - Press 'Shift-Insert' in order to Insert Group: B - Press 'Shift-Insert' in order to Insert Group: C - Drag and Drop some channels to new Group: A - Drag and Drop some channels to new Group: B - Drag and Drop some channels to new Group: C - Move Group C inside Group B - Move Group B inside Group A - Press mouse double click on added group: B - Press key Down few times - Press mouse double click on added group: B - Press key Down few times Evaluate: - Evaluate that subgroups are disabled (not selectable anymore). - Evaluate that channels are enabled (selectable). - Evaluate that channel is not present on plot when is disabled. """ # Event # Drag and Drop channel from FileWidget.channel_tree to Plot plot_channel_a = self.add_channel_to_plot(channel_index=10) plot_channel_b = self.add_channel_to_plot(channel_index=11) plot_channel_c = self.add_channel_to_plot(channel_index=12) plot_channel_d = self.add_channel_to_plot(channel_index=13) # Press 'Shift-Insert' in order to Insert Group # Create Channel Group. Drag channels inside the group one by one groups = {} with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mc_getText: for group_name in ("A", "B", "C"): # Create Channel Group mc_getText.return_value = group_name, True QtTest.QTest.keySequence(self.plot.channel_selection, QtGui.QKeySequence("Shift+Insert")) self.processEvents() # Get Groups Position for index in range(self.plot.channel_selection.topLevelItemCount()): item = self.plot.channel_selection.topLevelItem(index) group_name = item.text(self.Column.NAME) if group_name in ("A", "B", "C"): groups[group_name] = item item.setExpanded(True) # Get the First Item that will be moved for group_name, plot_channel in zip( ("A", "B", "C"), (plot_channel_a, plot_channel_b, plot_channel_c), strict=False ): # PreEvaluation: Ensure that group has no child self.assertEqual(0, groups[group_name].childCount()) self.move_item_inside_channels_tree_widget(src=plot_channel, dst=groups[group_name]) self.assertEqual(1, groups[group_name].childCount()) self.processEvents() # Move Group C inside Group B self.move_item_inside_channels_tree_widget(src=groups["C"], dst=groups["B"]) # Move Group B inside Group A self.move_item_inside_channels_tree_widget(src=groups["B"], dst=groups["A"]) groups["A"].setExpanded(True) groups["B"].setExpanded(True) groups["C"].setExpanded(True) enabled_groups_pixmap = self.plot.plot.viewport().grab() self.processEvents() # Evaluate for channel in (plot_channel_a, plot_channel_b, plot_channel_c): self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=channel.color), msg=f"Color of Channel: {channel.text(self.Column.NAME)} not present on 'plot'.", ) # Press mouse double click on Group B self.mouseDClick_WidgetItem(groups["B"]) disabled_groups_pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=plot_channel_a.color), msg=f"Color of Channel: {plot_channel_a.text(self.Column.NAME)} not present on 'plot'.", ) for channel in (plot_channel_b, plot_channel_c): self.assertFalse( Pixmap.has_color( pixmap=disabled_groups_pixmap, color_name=channel.color, ), msg=f"Color of Channel: {channel.text(self.Column.NAME)} present on 'plot'.", ) QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Up) for _ in range(4): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Press mouse double click on group B self.mouseDClick_WidgetItem(groups["B"]) self.processEvents() for _ in range(8): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Evaluate # After channels are enabled, they first flash a few times on self.plot. # ProcessEvents few times for channels to be present for _ in range(20): self.processEvents(0.05) enabled_groups_pixmap = self.plot.plot.viewport().grab() for channel in ( plot_channel_a, plot_channel_b, plot_channel_c, plot_channel_d, ): self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=channel.color), msg=f"Color for Channel: {channel.text(self.Column.NAME)} not present on 'plot'", ) def test_EnableDisable_Preserve_Subgroup_State_0(self): """ Test Scope: Validate that doubleClick operation will activate/deactivate subgroups and preserve state when parent is disabled/enabled. Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. - Drag and Drop channels from FileWidget.channel_tree to Plot - Press 'Shift-Insert' in order to Insert Group: A - Press 'Shift-Insert' in order to Insert Group: B - Press 'Shift-Insert' in order to Insert Group: C - Drag and Drop some channels to new Group: A - Drag and Drop some channels to new Group: B - Drag and Drop some channels to new Group: C - Move Group C inside Group B - Move Group B inside Group A - Press mouse double click on added group: C - Press mouse double click on added group: B - Press key Down few times - Press mouse double click on added group: B - Press key Down few times Evaluate: - Evaluate that subgroups are disabled (not selectable anymore). - Evaluate that channel is not present on plot when is disabled. - Evaluate that subgroup C state is maintained after subgroup B is enabled. """ # Event # Drag and Drop channel from FileWidget.channel_tree to Plot plot_channel_a = self.add_channel_to_plot(channel_index=10) plot_channel_b = self.add_channel_to_plot(channel_index=11) plot_channel_c = self.add_channel_to_plot(channel_index=12) plot_channel_d = self.add_channel_to_plot(channel_index=13) # Press 'Shift-Insert' in order to Insert Group # Create Channel Group. Drag channels inside the group one by one groups = {} with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mc_getText: for group_name in ("A", "B", "C"): # Create Channel Group mc_getText.return_value = group_name, True QtTest.QTest.keySequence(self.plot.channel_selection, QtGui.QKeySequence("Shift+Insert")) self.processEvents() # Get Groups Position for index in range(self.plot.channel_selection.topLevelItemCount()): item = self.plot.channel_selection.topLevelItem(index) group_name = item.text(self.Column.NAME) if group_name in ("A", "B", "C"): groups[group_name] = item item.setExpanded(True) # Get the First Item that will be moved for group_name, plot_channel in zip( ("A", "B", "C"), (plot_channel_a, plot_channel_b, plot_channel_c), strict=False ): # PreEvaluation: Ensure that group has no child self.assertEqual(0, groups[group_name].childCount()) self.move_item_inside_channels_tree_widget(src=plot_channel, dst=groups[group_name]) self.processEvents(0.05) self.assertEqual(1, groups[group_name].childCount()) # Move Group C inside Group B self.move_item_inside_channels_tree_widget(src=groups["C"], dst=groups["B"]) # Move Group B inside Group A self.move_item_inside_channels_tree_widget(src=groups["B"], dst=groups["A"]) groups["A"].setExpanded(True) groups["B"].setExpanded(True) groups["C"].setExpanded(True) enabled_groups_pixmap = self.plot.plot.viewport().grab() self.processEvents() # Evaluate for channel in (plot_channel_a, plot_channel_b, plot_channel_c): self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=channel.color), msg=f"Color of Channel: {channel.text(self.Column.NAME)} not present on 'plot'.", ) # Press mouse double click on Group C self.mouseDClick_WidgetItem(groups["C"]) # Press mouse double click on Group B self.mouseDClick_WidgetItem(groups["B"]) disabled_groups_pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=plot_channel_a.color), msg=f"Color of Channel: {plot_channel_a.text(self.Column.NAME)} not present on 'plot'.", ) for channel in (plot_channel_b, plot_channel_c): self.assertFalse( Pixmap.has_color( pixmap=disabled_groups_pixmap, color_name=channel.color, ), msg=f"Color of Channel: {channel.text(self.Column.NAME)} present on 'plot'.", ) QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Up) for _ in range(4): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Press mouse double click on group B self.mouseDClick_WidgetItem(groups["B"]) self.processEvents() for _ in range(8): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Evaluate # After channels are enabled, they first flash a few times on self.plot. # ProcessEvents few times for channels to be present for _ in range(20): self.processEvents(0.05) enabled_groups_pixmap = self.plot.plot.viewport().grab() self.assertFalse( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=plot_channel_c.color), msg=f"Color for Channel: {plot_channel_c.text(self.Column.NAME)} present on 'plot'", ) for channel in (plot_channel_a, plot_channel_b, plot_channel_d): self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=channel.color), msg=f"Color for Channel: {channel.text(self.Column.NAME)} not present on 'plot'", ) def test_EnableDisable_Preserve_Subgroup_State_1(self): """ Test Scope: Validate that doubleClick operation will activate/deactivate subgroups and preserve state when parent is disabled/enabled. Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. - Drag and Drop channels from FileWidget.channel_tree to Plot - Press 'Shift-Insert' in order to Insert Group: A - Press 'Shift-Insert' in order to Insert Group: B - Press 'Shift-Insert' in order to Insert Group: C - Drag and Drop some channels to new Group: A - Drag and Drop some channels to new Group: B - Drag and Drop some channels to new Group: C - Move Group C inside Group B - Move Group B inside Group A - Press mouse double click on added group: C - Press mouse double click on added group: B - Press key Down few times - Press mouse double click on added group: B - Press mouse click on group B: - Use supposed to simulate Deactivate group from ContextMenu for group: C but the bug is related to previous enabled group which remains selected. - Press key Down few times Evaluate: - Evaluate that subgroups are disabled (not selectable anymore). - Evaluate that channels are enabled (selectable). - Evaluate that channel is not present on plot when is disabled. """ # Event # Drag and Drop channel from FileWidget.channel_tree to Plot plot_channel_a = self.add_channel_to_plot(channel_index=10) plot_channel_b = self.add_channel_to_plot(channel_index=11) plot_channel_c = self.add_channel_to_plot(channel_index=12) plot_channel_d = self.add_channel_to_plot(channel_index=13) # Press 'Shift-Insert' in order to Insert Group # Create Channel Group. Drag channels inside the group one by one groups = {} with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mc_getText: for group_name in ("A", "B", "C"): # Create Channel Group mc_getText.return_value = group_name, True QtTest.QTest.keySequence(self.plot.channel_selection, QtGui.QKeySequence("Shift+Insert")) self.processEvents() # Get Groups Position for index in range(self.plot.channel_selection.topLevelItemCount()): item = self.plot.channel_selection.topLevelItem(index) group_name = item.text(self.Column.NAME) if group_name in ("A", "B", "C"): groups[group_name] = item item.setExpanded(True) # Get the First Item that will be moved for group_name, plot_channel in zip( ("A", "B", "C"), (plot_channel_a, plot_channel_b, plot_channel_c), strict=False ): # PreEvaluation: Ensure that group has no child self.assertEqual(0, groups[group_name].childCount()) self.move_item_inside_channels_tree_widget(src=plot_channel, dst=groups[group_name]) self.processEvents(0.05) self.assertEqual(1, groups[group_name].childCount()) # Move Group C inside Group B self.move_item_inside_channels_tree_widget(src=groups["C"], dst=groups["B"]) # Move Group B inside Group A self.move_item_inside_channels_tree_widget(src=groups["B"], dst=groups["A"]) groups["A"].setExpanded(True) groups["B"].setExpanded(True) groups["C"].setExpanded(True) enabled_groups_pixmap = self.plot.plot.viewport().grab() self.processEvents() # Evaluate for channel in (plot_channel_a, plot_channel_b, plot_channel_c): self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=channel.color), msg=f"Color of Channel: {channel.text(self.Column.NAME)} not present on 'plot'.", ) # Press mouse double click on Group C self.mouseDClick_WidgetItem(groups["C"]) # Press mouse double click on Group B self.mouseDClick_WidgetItem(groups["B"]) disabled_groups_pixmap = self.plot.plot.viewport().grab() # Evaluate self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=plot_channel_a.color), msg=f"Color of Channel: {plot_channel_a.text(self.Column.NAME)} not present on 'plot'.", ) for channel in (plot_channel_b, plot_channel_c): self.assertFalse( Pixmap.has_color( pixmap=disabled_groups_pixmap, color_name=channel.color, ), msg=f"Color of Channel: {channel.text(self.Column.NAME)} present on 'plot'.", ) QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Up) for _ in range(4): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Press mouse double click on group B self.mouseDClick_WidgetItem(groups["B"]) self.mouseClick_WidgetItem(groups["B"]) self.processEvents() # Evaluate selected items selectedItems = self.plot.channel_selection.selectedItems() self.assertEqual(1, len(selectedItems)) self.assertEqual("B", selectedItems[0].text(self.Column.NAME)) # Disable group C from context-menu # Disclaimer: Group C is already disabled # Simple Click on group C is enough. The bug was that when you click disabled item, # the previous selected item remains in selectedItems. # Basically, the disabled item is not selectable and selection is kept. # In case that previous item was a group, and 'Disable groups' is selected from the context-menu # then, unintended parent and subgroups disable will happen. self.mouseClick_WidgetItem(groups["C"]) # Evaluate that selection was changed. selectedItems = self.plot.channel_selection.selectedItems() self.assertEqual(0, len(selectedItems)) for _ in range(8): QtTest.QTest.keyClick(self.plot.channel_selection, QtCore.Qt.Key.Key_Down) self.processEvents() # Evaluate # After channels are enabled, they first flash a few times on self.plot. # ProcessEvents few times for channels to be present for _ in range(20): self.processEvents(0.05) enabled_groups_pixmap = self.plot.plot.viewport().grab() self.assertFalse( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=plot_channel_c.color), msg=f"Color for Channel: {plot_channel_c.text(self.Column.NAME)} present on 'plot'", ) for channel in (plot_channel_a, plot_channel_b, plot_channel_d): self.assertTrue( Pixmap.has_color(pixmap=enabled_groups_pixmap, color_name=channel.color), msg=f"Color for Channel: {channel.text(self.Column.NAME)} not present on 'plot'", ) asammdf-8.5.1/test/asammdf/gui/widgets/plot/test_PlotWidget_DragAndDrop.py000066400000000000000000000635341502633300400266430ustar00rootroot00000000000000#!/usr/bin/env python from unittest import mock from PySide6 import QtCore, QtGui, QtTest, QtWidgets from test.asammdf.gui.test_base import DragAndDrop from test.asammdf.gui.widgets.test_BasePlotWidget import TestPlotWidget class TestDragAndDrop(TestPlotWidget): # Note: Test Plot Widget through FileWidget. def setUp(self): super().setUp() self.setUpFileWidget(measurement_file=self.measurement_file, default=True) # Switch ComboBox to "Natural sort" self.widget.channel_view.setCurrentText("Natural sort") self.create_window(window_type="Plot") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) def test_Plot_ChannelSelection_DragAndDrop_fromFile_toPlot_0(self): """ Test Scope: - Test DragAndDrop Action from FileWidget.channel_tree to Plot.channel_selection and to Plot.plot. - Channels are selection one by one. - Ensure that Drag and Drop Action allow channels to be added to Plot.channel_selection Precondition: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. Events: - Drag and Drop channel from FileWidget.channel_tree to Plot - Drag and Drop same channel from FileWidget.channel_tree to Plot Evaluate: - Evaluate that two channels are added to Plot "channel_selection" """ # Event # Select channel channel_tree = self.widget.channels_tree plot = self.widget.mdi_area.subWindowList()[0].widget() item = channel_tree.topLevelItem(0) item.setSelected(True) channel_name = item.text(self.Column.NAME) drag_position = channel_tree.visualItemRect(item).center() drop_position = plot.channel_selection.viewport().rect().center() # PreEvaluation self.assertEqual(0, plot.channel_selection.topLevelItemCount()) DragAndDrop( src_widget=channel_tree, dst_widget=plot.channel_selection, src_pos=drag_position, dst_pos=drop_position, ) # Evaluate plot_channel = plot.channel_selection.topLevelItem(0) plot_channel_name = plot_channel.text(self.Column.NAME) self.assertEqual(1, plot.channel_selection.topLevelItemCount()) self.assertEqual(channel_name, plot_channel_name) drop_position = plot.plot.viewport().rect().center() DragAndDrop( src_widget=channel_tree, dst_widget=plot.plot, src_pos=drag_position, dst_pos=drop_position, ) self.assertEqual(2, plot.channel_selection.topLevelItemCount()) def test_Plot_ChannelSelection_DragAndDrop_fromFile_toPlot_1(self): """ Test Scope: - Test DragAndDrop Action from FileWidget.channel_tree to Plot.channel_selection and to Plot.plot. - Multiple Channels are selected and dragged. - Ensure that Drag and Drop Action allow channels to be added to Plot.channel_selection Precondition: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. Events: - Select 3 channels from FileWidget.channel_tree - Drag and Drop channels from FileWidget.channel_tree to Plot Evaluate: - Evaluate that 3 channels are added to Plot "channel_selection" """ # Event channel_tree = self.widget.channels_tree plot = self.widget.mdi_area.subWindowList()[0].widget() # Select 3 from channels but not from beginning # Avoid $ChannelLog because it's empty channel iterator = QtWidgets.QTreeWidgetItemIterator(channel_tree) count = 6 selected_channels = [] item = None while iterator.value() and count: count -= 1 if count > 2: iterator += 1 continue item = iterator.value() item.setSelected(True) selected_channels.append(item.text(0)) iterator += 1 drag_position = channel_tree.visualItemRect(item).center() drop_position = plot.channel_selection.viewport().rect().center() # PreEvaluation self.assertEqual(0, plot.channel_selection.topLevelItemCount()) DragAndDrop( src_widget=channel_tree, dst_widget=plot, src_pos=drag_position, dst_pos=drop_position, ) # Evaluate self.assertEqual(3, plot.channel_selection.topLevelItemCount()) iterator = QtWidgets.QTreeWidgetItemIterator(plot.channel_selection) plot_channels = [] while iterator.value(): item = iterator.value() plot_channels.append(item.text(self.Column.NAME)) iterator += 1 self.assertListEqual(selected_channels, plot_channels) def test_Plot_ChannelSelection_DragAndDrop_fromPlotCS_toSamePlotCS(self): """ Test Scope: - Test DragAndDrop Action from Plot.channel_selection to Plot.channel_selection - Case 0: Channels are selected one by one. - Case 1: Multiple Channels are selected. - Case 2: Create Channel Group. Drag channels inside the group one by one - Case 3: Create Channel Group. Drag multiple channels at once inside the group. - Case 4: Drag Group inside the Group - Case 5: Drag Group outside the Group - Ensure that Drag and Drop Action allow channels to be sorted to Plot.channel_selection Precondition: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. Events: - Select 5 channels and DragAndDrop them to Plot.channel_selection. - One channel should be duplicated. - Case 0: - DragAndDrop first channel to 3rd position. - Case 1: - DragAndDrop 2nd and 3rd channels on last position. - Case 2: - Create ChannelGroup - DragAndDrop first channel inside the group. - DragAndDrop 2nd channel inside the group. - Case 3: - Create ChannelGroup - DragAndDrop last two channels inside the group. - Case 4: - Drag Group inside the Group - Case 5: - Drag Group outside the Group Evaluate: - Case 0: - Evaluate that channel changed the position in the tree. - Case 1: - Evaluate that channels changed their position in the tree. - Case 2: - Evaluate that channel group was created. New item is present on the tree. - Evaluate that channel was moved as child to this item. Item should no longer exist outside the group. - Evaluate that duplicated channel was moved inside the group, and there is still one more wo parent on the tree - Case 3: - Evaluate that channels were moved inside the group and does no longer exist outside. - Case 4: - Evaluate that group was moved inside the group. - Case 5: - Evaluate that group was moved outside the group. """ # Event channel_tree = self.widget.channels_tree plot = self.widget.mdi_area.subWindowList()[0].widget() # Select 5 from channels but not from beginning # Avoid $ChannelLog because it's empty channel iterator = QtWidgets.QTreeWidgetItemIterator(channel_tree) count = -1 selected_channels = [] drag_item = None while iterator.value(): count += 1 # Skip over first 3 if count < 2: iterator += 1 continue item = iterator.value() if item and count < 7: drag_item = item item.setSelected(True) item.setCheckState(0, QtCore.Qt.CheckState.Checked) selected_channels.append(item.text(0)) iterator += 1 drag_position = channel_tree.visualItemRect(drag_item).center() drop_position = plot.channel_selection.viewport().rect().center() # PreEvaluation self.assertEqual(0, plot.channel_selection.topLevelItemCount()) DragAndDrop( src_widget=channel_tree, dst_widget=plot, src_pos=drag_position, dst_pos=drop_position, ) self.assertEqual(5, plot.channel_selection.topLevelItemCount()) # Add one channel twice # Switch ComboBox to "Selected channels only" self.widget.channel_view.setCurrentText("Selected channels only") duplicated_channel = channel_tree.topLevelItem(0) duplicated_channel.setSelected(True) drag_position = channel_tree.visualItemRect(duplicated_channel).center() duplicated_channel = duplicated_channel.text(0) DragAndDrop( src_widget=channel_tree, dst_widget=plot, src_pos=drag_position, dst_pos=drop_position, ) self.assertEqual(6, plot.channel_selection.topLevelItemCount()) # Case 0: with self.subTest("test_test_Plot_ChannelSelection_DragAndDrop_fromPlotCS_toPlot_0"): # DragAndDrop first channel to 3rd position. first_channel = plot.channel_selection.topLevelItem(0) third_channel = plot.channel_selection.topLevelItem(2) self.move_item_inside_channels_tree_widget(src=first_channel, dst=third_channel) # Get Names first_channel = first_channel.text(self.Column.NAME) third_channel = third_channel.text(self.Column.NAME) # Evaluate # First channel position was changed. new_first_channel = plot.channel_selection.topLevelItem(0).text(self.Column.NAME) self.assertNotEqual(first_channel, new_first_channel) # Evaluate that first channel was moved to third channel position. new_third_channel = plot.channel_selection.topLevelItem(2).text(self.Column.NAME) new_fourth_channel = plot.channel_selection.topLevelItem(1).text(self.Column.NAME) self.assertEqual(first_channel, new_third_channel) self.assertEqual(third_channel, new_fourth_channel) # Case 1: with self.subTest("test_test_Plot_ChannelSelection_DragAndDrop_fromPlotCS_toPlot_1"): # DragAndDrop 2nd and 3rd channels on last position. second_channel = plot.channel_selection.topLevelItem(1) third_channel = plot.channel_selection.topLevelItem(2) last_channel = plot.channel_selection.topLevelItem(5) # Select second_channel.setSelected(True) third_channel.setSelected(True) self.move_item_inside_channels_tree_widget(src=third_channel, dst=last_channel) # Get Names second_channel = second_channel.text(self.Column.NAME) third_channel = third_channel.text(self.Column.NAME) # Evaluate new_second_channel = plot.channel_selection.topLevelItem(1).text(self.Column.NAME) new_third_channel = plot.channel_selection.topLevelItem(2).text(self.Column.NAME) self.assertNotEqual(second_channel, new_second_channel) self.assertNotEqual(third_channel, new_third_channel) new_fifth_channel = plot.channel_selection.topLevelItem(4).text(self.Column.NAME) new_sixth_channel = plot.channel_selection.topLevelItem(5).text(self.Column.NAME) self.assertEqual(second_channel, new_fifth_channel) self.assertEqual(third_channel, new_sixth_channel) # Case 2: with self.subTest("test_test_Plot_ChannelSelection_DragAndDrop_fromPlotCS_toPlot_2"): # Create Channel Group. Drag channels inside the group one by one with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mc_getText: # Create Channel Group mc_getText.return_value = "FirstGroup", True QtTest.QTest.keySequence(plot.channel_selection, QtGui.QKeySequence("Shift+Insert")) # PreEvaluation: Check if there is one extra-item self.assertEqual(7, plot.channel_selection.topLevelItemCount()) # Get Group Position first_group = None for index in range(plot.channel_selection.topLevelItemCount()): item = plot.channel_selection.topLevelItem(index) if item.text(self.Column.NAME) == "FirstGroup": first_group = item break else: self.fail("FirstGroup is not present on Plot Channel Selection.") first_group.setExpanded(True) # Get First Item that will be moved first_channel = plot.channel_selection.topLevelItem(1) if first_channel.text(self.Column.NAME) == duplicated_channel: first_channel = plot.channel_selection.topLevelItem(2) # Get the Name of first channel first_channel_ = first_channel first_channel = first_channel.text(self.Column.NAME) # PreEvaluation: Ensure that group has no child self.assertEqual(0, first_group.childCount()) self.move_item_inside_channels_tree_widget(src=first_channel_, dst=first_group) # Evaluate self.assertEqual(1, first_group.childCount()) self.assertEqual(first_channel, first_group.child(0).text(self.Column.NAME)) self.assertEqual(6, plot.channel_selection.topLevelItemCount()) second_channel = None for index in range(plot.channel_selection.topLevelItemCount()): item = plot.channel_selection.topLevelItem(index) if item.text(self.Column.NAME) == duplicated_channel: second_channel = item break else: self.fail("Duplicate Channel is not found anymore.") self.move_item_inside_channels_tree_widget(src=second_channel, dst=first_group) # Evaluate self.assertEqual(2, first_group.childCount()) self.assertEqual(duplicated_channel, first_group.child(1).text(self.Column.NAME)) self.assertEqual(5, plot.channel_selection.topLevelItemCount()) # Case 3: with self.subTest("test_test_Plot_ChannelSelection_DragAndDrop_fromPlotCS_toPlot_3"): # Create Channel Group. Drag multiple channels inside the group with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QInputDialog.getText") as mc_getText: # Create Channel Group mc_getText.return_value = "SecondGroup", True QtTest.QTest.keySequence(plot.channel_selection, QtGui.QKeySequence("Shift+Insert")) # PreEvaluation: Check if there is one extra-item self.assertEqual(6, plot.channel_selection.topLevelItemCount()) # Get Group Position second_group = None for index in range(plot.channel_selection.topLevelItemCount()): item = plot.channel_selection.topLevelItem(index) if item.text(self.Column.NAME) == "SecondGroup": second_group = item break else: self.fail("SecondGroup is not present on Plot Channel Selection.") second_group.setExpanded(True) # Get Channels last_channel_0 = plot.channel_selection.topLevelItem(plot.channel_selection.topLevelItemCount() - 1) last_channel_1 = plot.channel_selection.topLevelItem(plot.channel_selection.topLevelItemCount() - 2) last_channel_0.setSelected(True) last_channel_1.setSelected(True) self.move_item_inside_channels_tree_widget(src=last_channel_1, dst=second_group) # Evaluate self.assertEqual(2, second_group.childCount()) self.assertEqual(4, plot.channel_selection.topLevelItemCount()) # Case 4: with self.subTest("test_test_Plot_ChannelSelection_DragAndDrop_fromPlotCS_toPlot_4"): # Drag Group inside the Group # Get Group Positions first_group, second_group = None, None for index in range(plot.channel_selection.topLevelItemCount()): item = plot.channel_selection.topLevelItem(index) if item.text(self.Column.NAME) == "FirstGroup": first_group = item elif item.text(self.Column.NAME) == "SecondGroup": second_group = item if first_group and second_group: break else: self.fail("Groups are not present on Plot Channel Selection.") self.move_item_inside_channels_tree_widget(src=second_group, dst=first_group) # Evaluate self.assertEqual(3, first_group.childCount()) self.assertEqual(3, plot.channel_selection.topLevelItemCount()) # Case 5: with self.subTest("test_test_Plot_ChannelSelection_DragAndDrop_fromPlotCS_toPlot_5"): # Drag Group outside the Group # Get Group Positions first_group, second_group = None, None for index in range(plot.channel_selection.topLevelItemCount()): item = plot.channel_selection.topLevelItem(index) if item.text(self.Column.NAME) == "FirstGroup": first_group = item break else: self.fail("FirstGroup is not present on Plot Channel Selection.") for index in range(first_group.childCount()): item = first_group.child(index) if item.text(self.Column.NAME) == "SecondGroup": second_group = item break else: self.fail("SecondGroup is not present on Plot Channel Selection.") self.move_item_inside_channels_tree_widget(src=second_group, dst=plot.channel_selection) # Evaluate self.assertEqual(2, first_group.childCount()) self.assertEqual(4, plot.channel_selection.topLevelItemCount()) def test_Plot_ChannelSelection_DragAndDrop_fromPlot_toPlot(self): """ Test Scope: Validate that channels can be dragged and dropped between Plot windows. (Ex: from Plot 0 to Plot 1) Precondition: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as a window type. Events: - Select one channel and drag it to the 'Plot 0' - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. - Select one channel and drag it to the 'Plot 1' - Select channel from 'Plot 0' and drag it to the 'Plot 1' Evaluate: - Validate that channel from 'Plot 0' is added to 'Plot 1' """ # Event channel_tree = self.widget.channels_tree plot_0 = self.widget.mdi_area.subWindowList()[0].widget() # Random Channels channel_0 = channel_tree.topLevelItem(8) channel_1 = channel_tree.topLevelItem(13) # Drag one Channel from FileWidget channel_tree to Plot_0 drag_position = channel_tree.visualItemRect(channel_0).center() drop_position = plot_0.channel_selection.viewport().rect().center() self.mouseClick_WidgetItem(channel_0) # PreEvaluation self.assertEqual(0, plot_0.channel_selection.topLevelItemCount()) DragAndDrop( src_widget=channel_tree, dst_widget=plot_0, src_pos=drag_position, dst_pos=drop_position, ) self.assertEqual(1, plot_0.channel_selection.topLevelItemCount()) # Create New Plot Window self.create_window(window_type="Plot") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) plot_1 = self.widget.mdi_area.subWindowList()[1].widget() # Drag one Channel from FileWidget channel_tree to Plot_0 drag_position = channel_tree.visualItemRect(channel_1).center() drop_position = plot_1.channel_selection.viewport().rect().center() self.mouseClick_WidgetItem(channel_1) # PreEvaluation self.assertEqual(0, plot_1.channel_selection.topLevelItemCount()) DragAndDrop( src_widget=channel_tree, dst_widget=plot_1, src_pos=drag_position, dst_pos=drop_position, ) self.assertEqual(1, plot_1.channel_selection.topLevelItemCount()) # Select the channel from 'Plot 0' and drag it to 'Plot 1' # Drag one Channel from FileWidget channel_tree to Plot_0 plot_0_channel = plot_0.channel_selection.topLevelItem(0) plot_0_channel_name = plot_0_channel.text(self.Column.NAME) drag_position = plot_0.channel_selection.visualItemRect(plot_0_channel).center() drop_position = plot_1.channel_selection.viewport().rect().center() self.mouseClick_WidgetItem(plot_0_channel) # PreEvaluation self.assertEqual(1, plot_1.channel_selection.topLevelItemCount()) DragAndDrop( src_widget=plot_0.channel_selection, dst_widget=plot_1, src_pos=drag_position, dst_pos=drop_position, ) # Evaluate plot_1_new_channel = plot_1.channel_selection.topLevelItem(1) plot_1_new_channel_name = plot_1_new_channel.text(self.Column.NAME) self.assertEqual(2, plot_1.channel_selection.topLevelItemCount()) self.assertEqual(plot_0_channel_name, plot_1_new_channel_name) def test_Plot_ChannelSelection_DragAndDrop_fromNumeric_toPlot(self): """ Test Scope: Validate that channels can be dragged and dropped between Plot window and Numeric. Ex: from 'Numeric 0' to 'Plot 0' Precondition: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Simulate that Plot window is selected as window type. Events: - Select one channel and drag it to the 'Plot 0' - Press PushButton "Create Window" - Simulate that Numeric window is selected as window type. - Select one channel and drag it to the 'Numeric 0' - Select channel from 'Numeric 0' and drag it to the 'Plot 0' Evaluate: - Validate that channel from 'Numeric 0' is added to 'Plot 0' """ # Event channel_tree = self.widget.channels_tree plot_0 = self.widget.mdi_area.subWindowList()[0].widget() # Random Channels channel_0 = channel_tree.topLevelItem(8) channel_1 = channel_tree.topLevelItem(0) # Drag one Channel from FileWidget channel_tree to Plot_0 drag_position = channel_tree.visualItemRect(channel_0).center() drop_position = plot_0.channel_selection.viewport().rect().center() self.mouseClick_WidgetItem(channel_0) # PreEvaluation self.assertEqual(0, plot_0.channel_selection.topLevelItemCount()) DragAndDrop( src_widget=channel_tree, dst_widget=plot_0, src_pos=drag_position, dst_pos=drop_position, ) self.assertEqual(1, plot_0.channel_selection.topLevelItemCount()) # Create New Numeric Window self.create_window(window_type="Numeric") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2) numeric = self.widget.mdi_area.subWindowList()[1].widget() # Tile Horizontally QtTest.QTest.keySequence(plot_0.plot, "Shift+H") # Drag one Channel from FileWidget channel_tree to Numeric_0 drag_position = channel_tree.visualItemRect(channel_1).center() drop_position = numeric.channels.dataView.viewport().rect().center() self.mouseClick_WidgetItem(channel_1) DragAndDrop( src_widget=channel_tree, dst_widget=numeric.channels.dataView, src_pos=drag_position, dst_pos=drop_position, ) # Evaluate numeric_data = numeric.channels.dataView # Select first row numeric_data.selectRow(0) numeric_channel = numeric_data.model().data(numeric_data.model().index(0, 0)) self.assertEqual(channel_1.text(self.Column.NAME), numeric_channel) # Drag one Channel from Numeric_0 to Plot_0 index = numeric_data.model().index(0, 0) drag_position = numeric_data.visualRect(index).center() drop_position = plot_0.channel_selection.viewport().rect().center() DragAndDrop( src_widget=numeric_data, dst_widget=plot_0.channel_selection, src_pos=drag_position, dst_pos=drop_position, ) # Evaluate plot_0_new_channel = plot_0.channel_selection.topLevelItem(1) plot_0_new_channel_name = plot_0_new_channel.text(self.Column.NAME) self.assertEqual(2, plot_0.channel_selection.topLevelItemCount()) self.assertEqual(numeric_channel, plot_0_new_channel_name) asammdf-8.5.1/test/asammdf/gui/widgets/plot/test_PlotWidget_PushButtons.py000066400000000000000000000777641502633300400270260ustar00rootroot00000000000000#!/usr/bin/env python from PySide6 import QtCore, QtTest from PySide6.QtWidgets import QPushButton as QBtn from PySide6.QtWidgets import QTreeWidgetItemIterator from asammdf.gui.serde import COLORS from asammdf.gui.utils import BLUE from test.asammdf.gui.test_base import Pixmap from test.asammdf.gui.widgets.test_BasePlotWidget import TestPlotWidget class TestPushButtons(TestPlotWidget): def setUp(self): super().setUp() self.channel_0_name = "ASAM_[14].M.MATRIX_DIM_16.UBYTE.IDENTICAL" self.channel_1_name = "ASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL" # Open test file in File Widget self.setUpFileWidget(measurement_file=self.measurement_file, default=True) # Switch ComboBox to "Natural sort" self.widget.channel_view.setCurrentText("Natural sort") # Press PushButton "Create Window" self.create_window(window_type="Plot") self.assertEqual(len(self.widget.mdi_area.subWindowList()), 1) self.plot = self.widget.mdi_area.subWindowList()[0].widget() # Press PushButton "Hide axis" if not self.plot.hide_axes_btn.isFlat(): QtTest.QTest.mouseClick(self.plot.hide_axes_btn, QtCore.Qt.MouseButton.LeftButton) # Press PushButton "Hide bookmarks" if not self.plot.bookmark_btn.isFlat(): QtTest.QTest.mouseClick(self.plot.bookmark_btn, QtCore.Qt.MouseButton.LeftButton) if not self.plot.focused_mode_btn.isFlat(): QtTest.QTest.mouseClick(self.plot.focused_mode_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents(0.1) # Save PixMap of clear plot clear_pixmap = self.plot.plot.viewport().grab() self.assertTrue(Pixmap.is_black(clear_pixmap)) # Add Channels to Plot self.add_channels([self.channel_0_name, self.channel_1_name]) self.plot_tree_channel_0 = self.channels[0] self.plot_tree_channel_1 = self.channels[1] self.assertEqual(2, self.plot.channel_selection.topLevelItemCount()) # Identify PlotSignal self.plot_graph_channel_0, self.plot_graph_channel_1 = None, None for channel in self.plot.plot.signals: if channel.name == self.channel_0_name: self.plot_graph_channel_0 = channel elif channel.name == self.channel_1_name: self.plot_graph_channel_1 = channel def test_Plot_ChannelSelection_PushButton_ValuePanel(self): """ Test Scope: Check that Value Panel label is visible or hidden according to Push Button Check that Value Panel label is updated according signal samples Precondition: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Drag and Drop 2 channels from FileWidget.channels_tree to Plot.channels_selection Events: - Press PushButton "Show selected channel value panel" - Press PushButton "Hide selected channel value panel" - Press PushButton "Show selected channel value panel" - Select one channel - Use navigation keys to change values - Select 2nd channel - Use navigation keys to change values Evaluate: - Evaluate that label is visible when button "Show selected channel value panel" is pressed. - Evaluate that label is hidden when button "Hide selected channel value panel" is pressed. - Evaluate that value from label is equal with: Channel Value + Channel Unit - Evaluate that value is updated according channel selected and current value """ # Event if self.plot.selected_channel_value.isVisible(): # Press PushButton "Hide selected channel value panel" QtTest.QTest.mouseClick(self.plot.selected_channel_value_btn, QtCore.Qt.MouseButton.LeftButton) # Press PushButton "Show selected channel value panel" QtTest.QTest.mouseClick(self.plot.selected_channel_value_btn, QtCore.Qt.MouseButton.LeftButton) self.assertTrue(self.plot.selected_channel_value.isVisible()) # Press PushButton "Hide selected channel value panel" QtTest.QTest.mouseClick(self.plot.selected_channel_value_btn, QtCore.Qt.MouseButton.LeftButton) self.assertFalse(self.plot.selected_channel_value.isVisible()) # Press PushButton "Show selected channel value panel" QtTest.QTest.mouseClick(self.plot.selected_channel_value_btn, QtCore.Qt.MouseButton.LeftButton) self.assertTrue(self.plot.selected_channel_value.isVisible()) # Select Channel self.mouseClick_WidgetItem(self.plot_tree_channel_0) # Evaluate plot_channel_0_value = self.plot_tree_channel_0.text(self.Column.VALUE) plot_channel_0_unit = self.plot_tree_channel_0.text(self.Column.UNIT) self.assertEqual( f"{plot_channel_0_value} {plot_channel_0_unit}", self.plot.selected_channel_value.text(), ) # Event self.plot.plot.setFocus() self.processEvents(0.1) # Send Key strokes for _ in range(6): QtTest.QTest.keyClick(self.plot.plot, QtCore.Qt.Key.Key_Right) self.processEvents(0.1) self.processEvents(0.1) # Evaluate plot_channel_0_value = self.plot_tree_channel_0.text(self.Column.VALUE) plot_channel_0_unit = self.plot_tree_channel_0.text(self.Column.UNIT) self.assertEqual( f"{plot_channel_0_value} {plot_channel_0_unit}", self.plot.selected_channel_value.text(), ) # Select 2nd Channel self.mouseClick_WidgetItem(self.plot_tree_channel_1) # Evaluate plot_channel_1_value = self.plot_tree_channel_1.text(self.Column.VALUE) plot_channel_1_unit = self.plot_tree_channel_1.text(self.Column.UNIT) self.assertEqual( f"{plot_channel_1_value} {plot_channel_1_unit}", self.plot.selected_channel_value.text(), ) # Event self.plot.plot.setFocus() self.processEvents(0.1) # Send Key strokes for _ in range(6): QtTest.QTest.keyClick(self.plot.plot, QtCore.Qt.Key.Key_Right) self.processEvents(0.1) self.processEvents(0.1) # Evaluate plot_channel_1_value = self.plot_tree_channel_1.text(self.Column.VALUE) plot_channel_1_unit = self.plot_tree_channel_1.text(self.Column.UNIT) self.assertEqual( f"{plot_channel_1_value} {plot_channel_1_unit}", self.plot.selected_channel_value.text(), ) def test_Plot_ChannelSelection_PushButton_FocusedMode(self): """ Test Scope: Check if Plot is cleared when no channel is selected. Check if Plot is showing all channels when Focus Mode is disabled. Check if Plot is showing only one channel when Focus Mode is enabled. Precondition: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Press PushButton HideAxis (easy for evaluation) - Drag and Drop channels from FileWidget.channels_tree to Plot.channels_selection: # First - ASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL # Second - ASAM_[14].M.MATRIX_DIM_16.UBYTE.IDENTICAL Events: - Press PushButton FocusMode - Press PushButton FocusMode Evaluate: - Evaluate that channels are displayed when FocusMode is disabled. - Evaluate that selected channels is displayed when FocusMode is enabled. """ # Events if not self.plot.focused_mode_btn.isFlat(): QtTest.QTest.mouseClick(self.plot.focused_mode_btn, QtCore.Qt.MouseButton.LeftButton) channels_present_pixmap = self.plot.plot.viewport().grab() self.assertFalse(Pixmap.is_black(pixmap=channels_present_pixmap)) self.assertTrue( Pixmap.has_color( pixmap=channels_present_pixmap, color_name=self.plot_graph_channel_0.color_name, ) ) self.assertTrue( Pixmap.has_color( pixmap=channels_present_pixmap, color_name=self.plot_graph_channel_1.color_name, ) ) # Press Button Focus Mode QtTest.QTest.mouseClick(self.plot.focused_mode_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate focus_mode_clear_pixmap = self.plot.plot.viewport().grab() # No Channel is selected self.assertTrue(Pixmap.is_black(pixmap=focus_mode_clear_pixmap)) # Select 2nd Channel QtTest.QTest.mouseClick( self.plot.channel_selection.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, self.plot.channel_selection.visualItemRect(self.plot_tree_channel_1).center(), ) # Process flash until signal is present on plot. for _ in range(10): self.processEvents(timeout=0.01) focus_mode_channel_1_pixmap = self.plot.plot.viewport().grab() if Pixmap.has_color( pixmap=focus_mode_channel_1_pixmap, color_name=self.plot_graph_channel_1.color_name, ): break # Evaluate focus_mode_channel_1_pixmap = self.plot.plot.viewport().grab() self.assertFalse(Pixmap.is_black(pixmap=focus_mode_channel_1_pixmap)) self.assertFalse( Pixmap.has_color( pixmap=focus_mode_channel_1_pixmap, color_name=self.plot_graph_channel_0.color_name, ) ) self.assertTrue( Pixmap.has_color( pixmap=focus_mode_channel_1_pixmap, color_name=self.plot_graph_channel_1.color_name, ) ) def test_Plot_ChannelSelection_PushButton_RegionDelta(self): """ Test Scope: Check if computation is done when Region is selected. Events: - Open 'FileWidget' with valid measurement. - Switch ComboBox to "Natural sort" - Press PushButton "Create Window" - Press PushButton HideAxis (easy for evaluation) - Drag and Drop channels from FileWidget.channels_tree to Plot.channels_selection: # First - ASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL # Second - ASAM_[14].M.MATRIX_DIM_16.UBYTE.IDENTICAL - Press PushButton Delta (range is not active) - Press Key 'R' for range selection - Press PushButton Delta (range is active) - Move cursors - Press Key 'R' for range selection - Press PushButton Delta (range is not active) Evaluate: - Evaluate that 'delta' char is present on channel values when range selection is active - Evaluate that 'delta' is correctly computed and result is updated on channel value """ channel_0 = "ASAM_[14].M.MATRIX_DIM_16.UBYTE.IDENTICAL" channel_1 = "ASAM_[15].M.MATRIX_DIM_16.UBYTE.IDENTICAL" # Event if not self.plot.delta_btn.isFlat(): QtTest.QTest.mouseClick(self.plot.delta_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() # Ensure that delta char is not present on channel values self.assertNotIn("Δ", self.plot_tree_channel_0.text(self.Column.VALUE)) self.assertNotIn("Δ", self.plot_tree_channel_1.text(self.Column.VALUE)) # Press PushButton Delta (range is not active) QtTest.QTest.mouseClick(self.plot.delta_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() # Ensure that delta char is not present on channel values even if button is pressed self.assertNotIn("Δ", self.plot_tree_channel_0.text(self.Column.VALUE)) self.assertNotIn("Δ", self.plot_tree_channel_1.text(self.Column.VALUE)) # Press Key 'R' for range selection QtTest.QTest.keyClick(self.plot.plot, QtCore.Qt.Key.Key_R) self.processEvents(timeout=0.01) # Ensure that delta char is present on channel values even if button is pressed self.assertIn("Δ", self.plot_tree_channel_0.text(self.Column.VALUE)) self.assertIn("Δ", self.plot_tree_channel_1.text(self.Column.VALUE)) # Move cursor # Select channel_1 QtTest.QTest.mouseClick( self.plot.channel_selection.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, self.plot.channel_selection.visualItemRect(self.plot_tree_channel_1).center(), ) self.plot.plot.setFocus() self.processEvents(0.1) # Move a little bit in center of measurement for _ in range(15): QtTest.QTest.keyClick(self.plot.plot, QtCore.Qt.Key.Key_Right) self.processEvents(timeout=0.1) # Get current value: Ex: 'Δ = 8'. Get last number old_channel_0_value = int(self.plot_tree_channel_0.text(self.Column.VALUE).split(" ")[-1]) old_channel_1_value = int(self.plot_tree_channel_1.text(self.Column.VALUE).split(" ")[-1]) for count in range(5): QtTest.QTest.keyClick(self.plot.plot, QtCore.Qt.Key.Key_Right) self.processEvents(timeout=0.1) # Evaluate channel_0_value = int(self.plot_tree_channel_0.text(self.Column.VALUE).split(" ")[-1]) channel_1_value = int(self.plot_tree_channel_1.text(self.Column.VALUE).split(" ")[-1]) self.assertLess(old_channel_0_value, channel_0_value) self.assertGreater(old_channel_1_value, channel_1_value) old_channel_0_value = channel_0_value old_channel_1_value = channel_1_value # Press Key 'R' for range selection QtTest.QTest.keyClick(self.plot.plot, QtCore.Qt.Key.Key_R) self.processEvents(timeout=0.01) # Ensure that delta char is not present on channel values even if button is pressed self.assertNotIn("Δ", self.plot_tree_channel_0.text(self.Column.VALUE)) self.assertNotIn("Δ", self.plot_tree_channel_1.text(self.Column.VALUE)) def test_Plot_ChannelSelection_PushButton_ToggleBookmarks(self): """ Precondition - Events: - Display 1 signal on plot - Press 3 times `Toggle bookmarks` button Evaluate: - Evaluate that bookmarks are not displayed before pressing `Toggle bookmarks` button - Evaluate that bookmarks are displayed after pressing `Toggle bookmarks` button first time - Evaluate that bookmarks are not displayed after pressing `Toggle bookmarks` button second time """ # Hide channels iterator = QTreeWidgetItemIterator(self.plot.channel_selection) while iterator.value(): item = iterator.value() if item.checkState(0) == QtCore.Qt.CheckState.Checked: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 # Press `Toggle bookmarks` button QtTest.QTest.mouseClick(self.plot.bookmark_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents(0.1) # Get expected colors pg_colors = Pixmap.color_names_exclude_defaults(self.plot.plot.viewport().grab()) bookmarks_colors = COLORS[: len(COLORS) - len(self.plot.plot.bookmarks) - 1 : -1] # Evaluate self.assertTrue(self.plot.show_bookmarks) for color in bookmarks_colors: self.assertIn(color, pg_colors) self.assertIn(BLUE, pg_colors) # Press `Toggle bookmarks` button QtTest.QTest.mouseClick(self.plot.bookmark_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() # Evaluate self.assertFalse(self.plot.show_bookmarks) self.assertTrue(Pixmap.is_black(self.plot.plot.viewport().grab())) def test_Plot_ChannelSelection_PushButton_HideAxes(self): """ Events: - Display 2 signal on plot - Press 3 times `Show axes` button Evaluate: - Evaluate that bookmarks are not displayed before pressing `Hide axes` button - Evaluate that bookmarks are displayed after pressing `Hide axes` button first time - Evaluate that bookmarks are not displayed after pressing `Hide axes` button second time _ Evaluate that only y_axis color are the same as selected channel color """ # Hide channels iterator = QTreeWidgetItemIterator(self.plot.channel_selection) while iterator.value(): item = iterator.value() if item.checkState(0) == QtCore.Qt.CheckState.Checked: item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) iterator += 1 if self.plot.plot.y_axis.isVisible() or self.plot.plot.x_axis.isVisible(): QtTest.QTest.mouseClick(self.plot.hide_axes_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertFalse(self.plot.plot.y_axis.isVisible()) self.assertFalse(self.plot.plot.x_axis.isVisible()) # Press `Show axes` button QtTest.QTest.mouseClick(self.plot.hide_axes_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() # Evaluate self.assertTrue(self.plot.plot.y_axis.isVisible()) self.assertTrue(self.plot.plot.x_axis.isVisible()) with self.subTest("test pen color of axes"): self.assertNotEqual(self.plot_tree_channel_0.color.name(), self.plot_tree_channel_1.color.name()) x_axis_color = self.plot.plot.x_axis.pen().color().name() # Event self.mouseClick_WidgetItem(self.plot_tree_channel_0) self.processEvents() # Evaluate self.assertEqual(x_axis_color, self.plot.plot.x_axis.pen().color().name()) self.assertEqual(self.plot.plot.y_axis.pen().color().name(), self.plot_tree_channel_0.color.name()) self.assertTrue(Pixmap.has_color(self.plot.plot.viewport().grab(), self.plot_tree_channel_0.color.name())) # Event self.mouseClick_WidgetItem(self.plot_tree_channel_1) self.processEvents() # Evaluate self.assertEqual(x_axis_color, self.plot.plot.x_axis.pen().color().name()) self.assertEqual(self.plot.plot.y_axis.pen().color().name(), self.plot_tree_channel_1.color.name()) self.assertTrue(Pixmap.has_color(self.plot.plot.viewport().grab(), self.plot_tree_channel_1.color.name())) # Press `Hide axes` button QtTest.QTest.mouseClick(self.plot.hide_axes_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertFalse(self.plot.plot.y_axis.isVisible()) self.assertFalse(self.plot.plot.x_axis.isVisible()) self.assertTrue(Pixmap.is_black(self.plot.plot.viewport().grab())) def test_Plot_ChannelSelection_PushButton_Lock(self): """ Events: - Display 2 signal on plot - Press `Lock` button to lock y-axis - Move signal using drag-and-drop technique on both axis - Press `Lock` button to unlock y-axis - Move signal using drag-and-drop technique on both axis Evaluate: - Evaluate that if y-axis is locked, signal cannot be moved only on y-axis and common axis column is hidden - Evaluate that if y-axis is unlocked, signal can be moved on both x and y axes and common axis column isn't hidden """ def move_signal(x, y): def drag_and_drop(): center = self.plot.plot.viewport().geometry().center() QtTest.QTest.mouseMove(self.plot.plot.viewport(), QtCore.QPoint(center.x() + x, center.y() + y)) QtTest.QTest.mouseRelease( self.plot.plot.viewport(), QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier, QtCore.QPoint(center.x() + x, center.y() + y), 20, ) self.mouseClick_WidgetItem(self.plot_tree_channel_0) QtCore.QTimer.singleShot(100, drag_and_drop) QtTest.QTest.mousePress(self.plot.plot.viewport(), QtCore.Qt.MouseButton.LeftButton) if self.plot.locked: QtTest.QTest.mouseClick(self.plot.lock_btn, QtCore.Qt.MouseButton.LeftButton) # Evaluate self.assertFalse(self.plot.locked) self.assertFalse(self.plot.channel_selection.isColumnHidden(self.plot.channel_selection.CommonAxisColumn)) # Evaluate that signal wasn't moved on x-axis self.assertIsNone(self.plot_graph_channel_0.trim_info) # Press `Lock` button QtTest.QTest.mouseClick(self.plot.lock_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() sig_0_y_range = self.plot_graph_channel_0.y_range # move channels on plot graphics move_signal(50, 50) self.processEvents(0.5) # Evaluate self.assertTrue(self.plot.locked) self.assertTrue(self.plot.channel_selection.isColumnHidden(self.plot.channel_selection.CommonAxisColumn)) self.assertTupleEqual(sig_0_y_range, self.plot_graph_channel_0.y_range) self.assertIsNotNone(self.plot_graph_channel_0.trim_info) # Press `Lock` button QtTest.QTest.mouseClick(self.plot.lock_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() # get trim info trim_info = self.plot_graph_channel_0.trim_info # move channels on plot graphics move_signal(-50, 50) self.processEvents(0.5) # Evaluate self.assertFalse(self.plot.locked) self.assertFalse(self.plot.channel_selection.isColumnHidden(self.plot.channel_selection.CommonAxisColumn)) self.assertNotEqual(sig_0_y_range, self.plot_graph_channel_0.y_range) self.assertGreater(self.plot_graph_channel_0.trim_info[0], trim_info[0]) # start self.assertGreater(self.plot_graph_channel_0.trim_info[1], trim_info[1]) # stop self.assertEqual(self.plot_graph_channel_0.trim_info[2], trim_info[2]) # width def test_Plot_ChannelSelection_PushButtons_Zoom(self): """ This method will test 4 buttons: zoom in, zoom out, undo zoom, redo zoom. Precondition: - Zoom history is clean - trim info must be None - Cursor is on center of plot. This step is required for easiest evaluation # Event - Press button `Zoom in` - Press button `Undo zoom` - Press button `Redo zoom` - Press button `Zoom out` - Press button `Zoom in` # Evaluate - Evaluate that `zoom` action was performed (zoom in will be tested at the end) - Evaluate that `undo zoom` action was performed - Evaluate that `redo zoom` action was performed and channels timestamp trim info is equal with its value before undo zoom action was performed - Evaluate that zoom `out action` was performed - Evaluate that zoom `in action` was performed """ # Precondition self.assertIsNone(self.plot_graph_channel_0.trim_info) QtTest.QTest.mouseClick(self.plot.plot.viewport(), QtCore.Qt.MouseButton.LeftButton) buttons = self.plot.findChildren(QBtn) zoom_in_btn = "Zoom in" zoom_out_btn = "Zoom out" for btn in buttons: if btn.toolTip() == zoom_in_btn: zoom_in_btn = btn continue elif btn.toolTip() == zoom_out_btn: zoom_out_btn = btn continue # buttons was found self.assertIsInstance(zoom_in_btn, QBtn) self.assertIsInstance(zoom_out_btn, QBtn) # Event QtTest.QTest.mouseClick(zoom_in_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() trim_info_0 = self.plot_graph_channel_0.trim_info # Evaluate self.assertIsNotNone(trim_info_0) # zoom was performed # Store previous zoom prev_zoom = trim_info_0[1] - trim_info_0[0] # Event QtTest.QTest.mouseClick(self.plot.undo_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() trim_info_1 = self.plot_graph_channel_0.trim_info # Evaluate self.assertGreater(trim_info_1[1] - trim_info_1[0], prev_zoom) # Store previous zoom prev_zoom = trim_info_1[1] - trim_info_1[0] # Event QtTest.QTest.mouseClick(self.plot.redo_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() trim_info_2 = self.plot_graph_channel_0.trim_info # Evaluate self.assertLess(trim_info_2[1] - trim_info_2[0], prev_zoom) self.assertTupleEqual(trim_info_0, trim_info_2) prev_zoom = trim_info_2[1] - trim_info_2[0] # Event QtTest.QTest.mouseClick(zoom_out_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() trim_info_3 = self.plot_graph_channel_0.trim_info # Evaluate self.assertGreater(trim_info_3[1] - trim_info_3[0], prev_zoom) # store previous zoom prev_zoom = trim_info_3[1] - trim_info_3[0] # Event QtTest.QTest.mouseClick(zoom_in_btn, QtCore.Qt.MouseButton.LeftButton) self.processEvents() trim_info_4 = self.plot_graph_channel_0.trim_info # Evaluate self.assertLess(trim_info_4[1] - trim_info_4[0], prev_zoom) self.assertTupleEqual(trim_info_2, trim_info_4) def test_Plot_ChannelSelection_PushButtons_CMD(self): """ This method will test 6 actions from Cmd menu: Home, Honeywell, Fit, Stack, Increase font, Decrease font. Precondition: - No zoom actions performed. Y range for both signals are identical and timestamp trim info is None # Event -[0] Press `Cmd` button to open menu, after that select `Stack` action from menu -[1] Press `Cmd` button to open menu, after that select `Fit` action from menu -[2] Press `Cmd` button to open menu, after that select `Honeywell` action from menu -[3] Press `Cmd` button to open menu, after that select `Home` action from menu -[4] Press `Cmd` button to open menu, after that check common axis checkboxes and select `Stack` action from menu -[5] Press `Cmd` button to open menu, after that select `Increase font` action from menu -[6] Press `Cmd` button to open menu, after that select `Decrease font` action from menu # Evaluate -[0] Evaluate that signals Y ranges were modified, also Y range for first signal is less than Y range of second signal timestamp trim info is None -[1] Evaluate that signals Y ranges for both signals are identical, timestamp trim info is still None -[2] Evaluate that signals Y ranges for both signals are identical, timestamp trim info was modified, also trim info for both signals are identical -[3] Evaluate that signals Y ranges for both signals are identical, also timestamp trim info are identical, timestamp range became greater -[4] Evaluate that signals Y ranges for both signals are identical, also timestamp trim info are identical -[5] Evaluate that widget font size was increased -[6] Evaluate that widget font size was decreased """ def click_on_cmd_action(btn: QBtn, action_text: str): for n, action in enumerate(btn.menu().actions(), 1): if action.text() == action_text: break else: n = 0 QtTest.QTest.mouseClick(btn, QtCore.Qt.MouseButton.LeftButton) for _ in range(n): QtTest.QTest.keyClick(btn.menu(), QtCore.Qt.Key.Key_Down) QtTest.QTest.qWait(100) QtTest.QTest.keyClick(btn.menu(), QtCore.Qt.Key.Key_Enter) # Precondition self.assertTupleEqual(self.plot_graph_channel_0.y_range, self.plot_graph_channel_1.y_range) self.assertIsNone(self.plot_graph_channel_0.trim_info) self.assertIsNone(self.plot_graph_channel_1.trim_info) buttons = self.plot.findChildren(QBtn) cmd_btn = "Cmd" for btn in buttons: if btn.text() == cmd_btn: cmd_btn = btn break self.processEvents(0.1) with self.subTest("PlotGraphics tests"): # Event click_on_cmd_action(cmd_btn, "Stack") self.processEvents(0.1) # Evaluate self.assertLess(self.plot_graph_channel_0.y_range[0], self.plot_graph_channel_1.y_range[0]) self.assertLess(self.plot_graph_channel_0.y_range[1], self.plot_graph_channel_1.y_range[1]) self.assertIsNone(self.plot_graph_channel_0.trim_info) # zoom on timestamp axis wasn't performed self.assertIsNone(self.plot_graph_channel_1.trim_info) # Event click_on_cmd_action(cmd_btn, "Fit") self.processEvents(0.1) # Evaluate self.assertTupleEqual(self.plot_graph_channel_0.y_range, self.plot_graph_channel_1.y_range) self.assertIsNone(self.plot_graph_channel_0.trim_info) self.assertIsNone(self.plot_graph_channel_1.trim_info) # Event click_on_cmd_action(cmd_btn, "Honeywell") self.processEvents(0.1) # Evaluate self.assertEqual(self.plot_graph_channel_0.y_range[0], self.plot_graph_channel_1.y_range[0]) self.assertEqual(self.plot_graph_channel_0.y_range[1], self.plot_graph_channel_1.y_range[1]) self.assertTupleEqual(self.plot_graph_channel_0.trim_info, self.plot_graph_channel_1.trim_info) # save previous trim info prev_trim_info = self.plot_graph_channel_0.trim_info[1] - self.plot_graph_channel_0.trim_info[0] # Event click_on_cmd_action(cmd_btn, "Home") self.processEvents(0.1) # Evaluate self.assertEqual(self.plot_graph_channel_0.y_range[0], self.plot_graph_channel_1.y_range[0]) self.assertEqual(self.plot_graph_channel_0.y_range[1], self.plot_graph_channel_1.y_range[1]) self.assertLess( prev_trim_info, self.plot_graph_channel_0.trim_info[1] - self.plot_graph_channel_0.trim_info[0] ) self.assertTupleEqual(self.plot_graph_channel_0.trim_info, self.plot_graph_channel_1.trim_info) # Event # Set checked individual axis for both channels common_axis_column = self.plot_tree_channel_0.CommonAxisColumn if self.plot_tree_channel_0.checkState(common_axis_column) == QtCore.Qt.CheckState.Unchecked: self.plot_tree_channel_0.setCheckState(common_axis_column, QtCore.Qt.CheckState.Checked) if self.plot_tree_channel_1.checkState(common_axis_column) == QtCore.Qt.CheckState.Unchecked: self.plot_tree_channel_1.setCheckState(common_axis_column, QtCore.Qt.CheckState.Checked) click_on_cmd_action(cmd_btn, "Stack") self.processEvents(0.1) # Evaluate self.assertTupleEqual(self.plot_graph_channel_0.y_range, self.plot_graph_channel_1.y_range) self.assertTupleEqual(self.plot_graph_channel_0.trim_info, self.plot_graph_channel_1.trim_info) with self.subTest("text actions tests"): prev_text_size = self.plot.font().pointSize() # Event click_on_cmd_action(cmd_btn, "Increase font") self.processEvents(0.1) # Evaluate self.assertGreater(self.plot.font().pointSize(), prev_text_size) prev_text_size = self.plot.font().pointSize() # Event click_on_cmd_action(cmd_btn, "Decrease font") self.processEvents(0.1) # Evaluate self.assertLess(self.plot.font().pointSize(), prev_text_size) asammdf-8.5.1/test/asammdf/gui/widgets/test_BaseBatchWidget.py000066400000000000000000000127071502633300400243520ustar00rootroot00000000000000from collections.abc import Iterable, Sequence import itertools import os from pathlib import Path import shutil from unittest import mock from PySide6 import QtCore, QtWidgets from PySide6.QtTest import QTest from PySide6.QtWidgets import QPushButton, QTreeWidgetItemIterator, QWidget from asammdf.gui.widgets.batch import BatchWidget from test.asammdf.gui.test_base import TestBase class TestBatchWidget(TestBase): testResult = None concatenate_aspect = 0 modify_aspect = 1 stack_aspect = 2 bus_aspect = 3 default_test_file = "ASAP2_Demo_V171.mf4" def setUp(self): super().setUp() self.widget = None self.plot = None patcher = mock.patch("asammdf.gui.widgets.file.ErrorDialog") self.mc_widget_ed = patcher.start() self.addCleanup(patcher.stop) patcher_settings = mock.patch("asammdf.gui.widgets.batch.QtCore.QSettings", spec=QtCore.QSettings) self.mc_settings = patcher_settings.start() self.mc_settings.return_value.value.side_effect = itertools.chain(["Natural sort"], itertools.repeat(None)) self.mc_settings.return_value.setValue.return_value = None self.addCleanup(patcher_settings.stop) patcher_restore = mock.patch.object(BatchWidget, "restore_export_settings") self.mc_restore = patcher_restore.start() self.addCleanup(patcher_restore.stop) self.processEvents() def setUpBatchWidget(self, *args, measurement_files: Sequence[str] | None): """ Created because a lot of testcases, we do not need other parameters for BatchWidget initialization. """ if measurement_files is None: self.widget = BatchWidget(*args) self.processEvents() else: self.widget = BatchWidget(*args) self.processEvents() for file in measurement_files: self.assertTrue(Path(file).exists()) self.widget.files_list.addItems(measurement_files) # Evaluate that all files was opened self.assertEqual(self.widget.files_list.count(), len(measurement_files)) self.widget.showNormal() def copy_mdf_files_to_workspace(self): # copy mf4 files from resources to test workspace for file in os.listdir(self.resource): if file.endswith((".mf4", ".mdf")): shutil.copyfile(Path(self.resource, file), Path(self.test_workspace, file)) def select_channels(self, channels_list: Iterable[str | int]) -> list: """ Select channels from a list of names or indexes. Parameters ---------- channels_list: a list of channel names or indexes Returns ------- channels names list """ self.selected_channels = [] iterator = QTreeWidgetItemIterator(self.widget.filter_tree) count = 0 while iterator.value(): item = iterator.value() if ( (item.name in channels_list or count in channels_list) and "time" not in item.name.lower() and "$" not in item.name ): # by name or index, exclde time and calibration channels item.setCheckState(0, QtCore.Qt.CheckState.Checked) self.assertTrue(item.checkState(0) == QtCore.Qt.CheckState.Checked) self.selected_channels.append(item.name) self.processEvents() iterator += 1 count += 1 # Evaluate that channels were added to "selected_filter_channels" for index in range(self.widget.selected_filter_channels.count()): item = self.widget.selected_filter_channels.item(index) self.assertIn(item.text(), self.selected_channels) return self.selected_channels def get_selected_groups(self, channels: list) -> dict: self.widget.filter_view.setCurrentText("Internal file structure") self.processEvents(1) groups = {} iterator = QTreeWidgetItemIterator(self.widget.filter_tree) count = 0 while iterator.value(): item = iterator.value() if item.text(0) in channels and item.text(0) != "time": if item.parent().text(0) not in groups.keys(): groups[item.parent().text(0)] = [item.text(0)] else: groups[item.parent().text(0)].append(item.text(0)) iterator += 1 count += 1 return groups def mouse_click_on_btn_with_progress(self, btn: QPushButton): """ Click on the button with progress bar and wait until progress bar will be closed. Parameters ---------- btn := QPushButton """ # Mouse click on button QTest.mouseClick(btn, QtCore.Qt.MouseButton.LeftButton) # Wait for progress bar thread to finish while self.widget._progress: self.processEvents(0.01) self.processEvents() def toggle_checkboxes(self, widget: QWidget, check=True): """ Iterate given widget to find QCheckBox items. All founded checkboxes will have 'check' check state Parameters ---------- widget := widget to iterate check := check state (True/False) """ # set checkboxes check state for checkbox in widget.findChildren(QtWidgets.QCheckBox): if checkbox.isChecked() != check: self.mouseClick_CheckboxButton(checkbox) asammdf-8.5.1/test/asammdf/gui/widgets/test_BaseFileWidget.py000066400000000000000000000166771502633300400242220ustar00rootroot00000000000000import json import os import pathlib from random import randint import shutil from unittest import mock from PySide6 import QtCore, QtTest, QtWidgets from asammdf.gui.widgets.file import FileWidget from asammdf.gui.widgets.numeric import Numeric from asammdf.gui.widgets.plot import Plot from test.asammdf.gui.test_base import TestBase class TestFileWidget(TestBase): testResult = None def setUp(self): super().setUp() self.widget = None self.plot = None patcher = mock.patch("asammdf.gui.widgets.file.ErrorDialog") self.mc_widget_ed = patcher.start() self.addCleanup(patcher.stop) self.measurement_file = shutil.copy(pathlib.Path(self.resource, "ASAP2_Demo_V171.mf4"), self.test_workspace) def tearDown(self): if self.widget is not None: self.widget.close() super().tearDown() def setUpFileWidget(self, *args, measurement_file, default): """ Created because for a lot of testcases, we do not need other parameters for FileWidget initialization. """ if default: self.widget = FileWidget( measurement_file, True, # with_dots True, # subplots True, # subplots_link False, # ignore_value2text_conversions False, # display_cg_name "line", # line_interconnect "", # password False, # hide_missing_channels False, # hide_disabled_channels ) else: self.widget = FileWidget(measurement_file, *args) self.processEvents() self.widget.showMaximized() def create_window(self, window_type, channels_names=(), channels_indexes=()): channel_tree = self.widget.channels_tree channel_tree.clearSelection() for channel in channels_names: channel = self.find_channel(channel_tree, channel_name=channel) channel.setCheckState(0, QtCore.Qt.CheckState.Checked) for channel in channels_indexes: channel = self.find_channel(channel_tree, channel_index=channel) channel.setCheckState(0, QtCore.Qt.CheckState.Checked) with mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog: mc_WindowSelectionDialog.return_value.result.return_value = True mc_WindowSelectionDialog.return_value.selected_type.return_value = window_type # - Press PushButton "Create Window" QtTest.QTest.mouseClick(self.widget.create_window_btn, QtCore.Qt.MouseButton.LeftButton) widget_types = self.get_sub_windows() self.assertIn(window_type, widget_types) @staticmethod def find_channel(channel_tree, channel_name=None, channel_index=None): selected_channel = None if not channel_name and not channel_index: selected_channel = channel_tree.topLevelItem(0) elif channel_index: selected_channel = channel_tree.topLevelItem(channel_index) elif channel_name: iterator = QtWidgets.QTreeWidgetItemIterator(channel_tree) while iterator.value(): item = iterator.value() if item and item.text(0) == channel_name: selected_channel = item break iterator += 1 return selected_channel def add_channels(self, channels_list: list, widget=None): """ Add channels to the widget from a list using channels indexes or channels names Add channels to the list Parameters channel_list: a list with existent channels names and indexes; widget: the widget where the channels will be inserted. Returns None: if one channel or widget does not exist; self.channels: if all channels were found. """ if channels_list is None: channels_list = [randint(5, self.widget.channels_tree.topLevelItemCount() - 10)] if not isinstance(channels_list, list): return [] # Ensure "Natural sort" mode for channel view self.widget.channel_view.setCurrentIndex(0) self.processEvents(0.1) windows_list = self.widget.mdi_area.subWindowList() if len(windows_list) == 0: return [] else: if widget is None: widget = windows_list[0].widget() else: if widget not in [w.widget() for w in windows_list]: return [] channels = [] for channel in channels_list: found_channel = None if isinstance(channel, int): found_channel = self.find_channel(channel_tree=self.widget.channels_tree, channel_index=channel) elif isinstance(channel, str): found_channel = self.find_channel(channel_tree=self.widget.channels_tree, channel_name=channel) self.processEvents(0.1) if found_channel is not None: channels.append(found_channel) self.assertEqual( len(channels_list), len(channels), msg=f"Not all channels from given list was found! \n" f"Given channels:\n{channels_list} \nFounded channels: \n" f"\n{channels}\n++++++++++++++++++++\nwidget:\t\t{widget}", ) # add channels to channel selection self.widget.add_new_channels([channel.name for channel in channels], widget) if isinstance(widget, Numeric): cw = widget.channels.dataView self.channels = cw.backend.signals elif isinstance(widget, Plot): cw = widget.channel_selection self.channels = [cw.topLevelItem(_) for _ in range(cw.topLevelItemCount())] else: return [] self.processEvents(0.01) return self.channels def load_shortcuts_from_json_file(self, widget): """ Used to store widget shortcuts into variable "self.shortcuts" Parameters ---------- widget: tested widget Returns ------- None: if class not exist in json Dict: if class was found; dict contains all shortcuts applied to selected class """ # get a json path json_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "Shortcuts", "Shortcuts.json")) widget_name = widget.__class__.__name__ self.shortcuts = None with open(json_path) as json_file: data = json.load(json_file) if widget_name in data.keys(): self.shortcuts = data[widget_name][0] json_file.close() return self.shortcuts def get_sub_windows(self): widget_types = sorted(w.widget().__class__.__name__ for w in self.widget.mdi_area.subWindowList()) return widget_types def load_display_file(self, display_file): with ( mock.patch.object(self.widget, "load_window", wraps=self.widget.load_window) as mo_load_window, mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName") as mo_getOpenFileName, ): mo_getOpenFileName.return_value = display_file, None QtTest.QTest.mouseClick( self.widget.load_channel_list_btn, QtCore.Qt.MouseButton.LeftButton, ) # Pre-Evaluate mo_load_window.assert_called() asammdf-8.5.1/test/asammdf/gui/widgets/test_BasePlotWidget.py000066400000000000000000000143001502633300400242360ustar00rootroot00000000000000import threading as td from unittest import mock import pyautogui from PySide6 import QtCore, QtTest, QtWidgets from PySide6.QtCore import QCoreApplication, QPoint, QPointF, Qt from PySide6.QtGui import QInputDevice, QPointingDevice, QWheelEvent from PySide6.QtWidgets import QWidget from test.asammdf.gui.test_base import DragAndDrop from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget class QMenuWrap(QtWidgets.QMenu): return_action = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def exec(self, *args, **kwargs): if not self.return_action: return super().exec_(*args, **kwargs) return self.return_action class TestPlotWidget(TestFileWidget): class Column: NAME = 0 RAWVALUE = 1 VALUE = 2 UNIT = 3 COMMON_AXIS = 4 INDIVIDUAL_AXIS = 5 ORIGIN = 6 def add_channel_to_plot(self, plot=None, channel_name=None, channel_index=None): if not plot and self.plot: plot = self.plot # Select channel channel_tree = self.widget.channels_tree channel_tree.clearSelection() selected_channel = self.find_channel(channel_tree, channel_name, channel_index) selected_channel.setSelected(True) if not channel_name: channel_name = selected_channel.text(self.Column.NAME) drag_position = channel_tree.visualItemRect(selected_channel).center() drop_position = plot.channel_selection.viewport().rect().center() # PreEvaluation DragAndDrop( src_widget=channel_tree, dst_widget=plot.channel_selection, src_pos=drag_position, dst_pos=drop_position, ) self.processEvents(0.05) plot_channel = None iterator = QtWidgets.QTreeWidgetItemIterator(plot.channel_selection) while iterator.value(): item = iterator.value() if item and item.text(0) == channel_name: plot_channel = item iterator += 1 return plot_channel def context_menu(self, action_text, position=None): self.processEvents() with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QMenu", wraps=QMenuWrap): mo_action = mock.MagicMock() mo_action.text.return_value = action_text QMenuWrap.return_action = mo_action if not position: QtTest.QTest.mouseClick(self.plot.channel_selection.viewport(), QtCore.Qt.MouseButton.RightButton) else: QtTest.QTest.mouseClick( self.plot.channel_selection.viewport(), QtCore.Qt.MouseButton.RightButton, QtCore.Qt.KeyboardModifier.NoModifier, position, ) self.processEvents(0.01) while not mo_action.text.called: self.processEvents(0.02) def move_item_inside_channels_tree_widget(self, plot=None, src=None, dst=None): if src is None or dst is None: raise Exception("src and dst is cannot be None") channels_tree_widget = src.treeWidget() if channels_tree_widget.headerItem().sizeHint(0).height() == -1: channels_tree_widget.headerItem().setSizeHint(0, QtCore.QSize(50, 25)) # height of header item header_item_h = channels_tree_widget.headerItem().sizeHint(0).height() # height of regular item item_h = channels_tree_widget.visualItemRect(src).height() correction = 0.2 # start drag coordinates drag_x, drag_y = ( channels_tree_widget.visualItemRect(src).center().x(), channels_tree_widget.visualItemRect(src).center().y() + header_item_h + int(item_h * correction), ) # stop drag (drop) coordinates if dst is channels_tree_widget: # destination is channel tree widget drop_x, drop_y = dst.rect().center().x(), dst.rect().center().y() else: if dst.type() == dst.Channel: # for insertion below channel correction = 0.5 drop_x, drop_y = ( channels_tree_widget.visualItemRect(dst).center().x(), channels_tree_widget.visualItemRect(dst).center().y() + header_item_h + int(item_h * correction), ) QtTest.QTest.mouseMove(channels_tree_widget, QPoint(drag_x, drag_y)) # minimum necessary time for drag action to be implemented t = 1 def call_drop_event(x, y, duration, h): x *= h / y pyautogui.drag(int(x), y, duration=duration) td.Timer(0.0001, call_drop_event, args=(int(drag_x * 0.5), drop_y - drag_y, t, item_h)).start() self.manual_use(self.widget, duration=t + 0.002) def wheel_action(self, w: QWidget, x: float, y: float, angle_delta: int): """ Used to simulate mouse wheel event. Parameters ---------- w: widget - widget object x: float - x position of cursor y: float - y position of cursor angle_delta: int - physical-wheel rotations units Returns ------- """ pos = QPointF(x, y) widget_x, widget_y = self.widget.geometry().x(), self.widget.geometry().y() widget_width, widget_height = self.widget.width(), self.widget.height() global_pos = QPointF(widget_width + widget_x - x, widget_height + widget_y - y) pixel_d = QPoint(0, 0) angle_d = QPoint(0, angle_delta * 120) buttons = Qt.MouseButton.NoButton modifiers = Qt.KeyboardModifier.NoModifier phase = Qt.ScrollPhase(0x0) inverted = False source = Qt.MouseEventSource(0x0) device = QPointingDevice( "core pointer", 1, QInputDevice.DeviceType(0x1), QPointingDevice.PointerType(0x0), QInputDevice.Capability.All, 1, 3, ) # Create event event = QWheelEvent(pos, global_pos, pixel_d, angle_d, buttons, modifiers, phase, inverted, source, device) # Post event QCoreApplication.postEvent(w, event) self.assertTrue(event.isAccepted()) QCoreApplication.processEvents() asammdf-8.5.1/test/requirements.txt000066400000000000000000000001311502633300400173670ustar00rootroot00000000000000PyAutoGUI pytest pytest-cov pytest-timeout python-can xmlrunner; python_version < "3.12" asammdf-8.5.1/test/run_all.py000066400000000000000000000007031502633300400161160ustar00rootroot00000000000000#!/usr/bin/env python """ Main test function to execute all tests found in the current directory """ from pathlib import Path import sys import unittest import xmlrunner def main() -> bool: tests = unittest.TestLoader().discover(".", "test_*.py") testResult = xmlrunner.XMLTestRunner(output=str(Path(".").resolve() / "test-reports")).run(tests) return not testResult.wasSuccessful() if __name__ == "__main__": sys.exit(main()) asammdf-8.5.1/test/test_CAN_bus_logging.py000066400000000000000000000112161502633300400205020ustar00rootroot00000000000000#!/usr/bin/env python import os from pathlib import Path import tempfile import unittest import urllib import urllib.request from zipfile import ZipFile import numpy as np from asammdf import MDF class TestCANBusLogging(unittest.TestCase): tempdir_obd: tempfile.TemporaryDirectory[str] tempdir_j1939: tempfile.TemporaryDirectory[str] @classmethod def setUpClass(cls) -> None: cls.tempdir_obd = tempfile.TemporaryDirectory() cls.tempdir_j1939 = tempfile.TemporaryDirectory() url = "https://github.com/danielhrisca/asammdf/files/4328945/OBD2-DBC-MDF4.zip" urllib.request.urlretrieve(url, "test.zip") ZipFile(r"test.zip").extractall(cls.tempdir_obd.name) Path("test.zip").unlink() url = "https://github.com/danielhrisca/asammdf/files/4076869/J1939-DBC-MDF4.zip" urllib.request.urlretrieve(url, "test.zip") ZipFile(r"test.zip").extractall(cls.tempdir_j1939.name) Path("test.zip").unlink() def test_obd_extract(self) -> None: print("OBD extract") temp_dir = Path(TestCANBusLogging.tempdir_obd.name) for file in temp_dir.iterdir(): print(file) path = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".mf4"][0] mdf = MDF(path) dbc = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".dbc"][0] signals = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".npy"] out = mdf.extract_bus_logging({"CAN": [(dbc, 0)]}, ignore_value2text_conversion=True) for signal in signals: name = signal.stem target = np.load(signal) sig = out.get(name) if sig.samples.dtype.kind == "S": sig = out.get(name, raw=True) self.assertTrue(np.array_equal(sig.samples, target), f"{name} {sig} {target}") def test_j1939_extract(self) -> None: print("J1939 extract") temp_dir = Path(TestCANBusLogging.tempdir_j1939.name) path = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".mf4"][0] mdf = MDF(path) dbc = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".dbc"][0] signals = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".npy"] out = mdf.extract_bus_logging({"CAN": [(dbc, 0)]}, ignore_value2text_conversion=True) for signal in signals: name = signal.stem target = np.load(signal) values = out.get(name).samples if values.dtype.kind == "S": values = out.get(name, raw=True).samples self.assertTrue(np.array_equal(values, target)) def test_almost_j1939_extract(self) -> None: print("non-standard J1939 extract") temp_dir = Path(TestCANBusLogging.tempdir_j1939.name) path = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".mf4"][0] mdf = MDF(path) # dbc = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".dbc"][0] # This dbc throws exception without the suggested changes in branch "relaxed_j1939"... # else it is identical to the CSS Electronics demo file in test package d = os.path.dirname(__file__) dbc = os.path.join(d, "almost-J1939.dbc") # Pls replace with file from expanded zip file signals = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".npy"] out = mdf.extract_bus_logging({"CAN": [(dbc, 0)]}) for signal in signals: name = signal.stem target = np.load(signal) values = out.get(name).samples self.assertTrue(np.array_equal(values, target)) def test_j1939_get_can_signal(self) -> None: print("J1939 get CAN signal") temp_dir = Path(TestCANBusLogging.tempdir_j1939.name) path = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".mf4"][0] mdf = MDF(path) dbc = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".dbc"][0] signals = [input_file for input_file in temp_dir.iterdir() if input_file.suffix == ".npy"] for signal in signals: name = signal.stem target = np.load(signal) values = mdf.get_can_signal(name=name, database=str(dbc)).samples self.assertTrue(np.array_equal(values, target)) values = mdf.get_bus_signal("CAN", name=name, database=str(dbc)).samples self.assertTrue(np.array_equal(values, target)) if __name__ == "__main__": unittest.main() asammdf-8.5.1/test/test_cantp.py000066400000000000000000000016011502633300400166240ustar00rootroot00000000000000import unittest import numpy as np from asammdf.blocks import bus_logging_utils as blu class TestCANTP(unittest.TestCase): tempdir = None payload = np.vstack( [ np.frombuffer(b"\x10\x0b\x52\x49\x47\x20\x20\x39", dtype="uint8"), # Initial part np.frombuffer(b"\x30\xff\x00\x4c\x40\x00\xd5\x54", dtype="uint8"), # Flow control np.frombuffer(b"\x21\x30\x30\x30\x38\x33\x00\x00", dtype="uint8"), # Final (second) part np.frombuffer(b"\x10\x0b\x52\x49\x47\x20\x20\x39", dtype="uint8"), # Initial part of next frame... ] ) ts = np.array([0.112, 0.113, 0.116, 0.201]) def test_merge_cantp(self) -> None: merged, t = blu.merge_cantp(TestCANTP.payload, TestCANTP.ts) assert merged.shape == (1, 11) assert merged[0, -1] == 0x33 assert t.shape == (1,) assert t[0] == 0.116 asammdf-8.5.1/test/test_endianess.py000066400000000000000000000365731502633300400175100ustar00rootroot00000000000000#!/usr/bin/env python from pathlib import Path import tempfile import typing import unittest import numpy as np from asammdf import MDF, Signal from asammdf.blocks import mdf_v3, mdf_v4 import asammdf.blocks.v2_v3_constants as v23c import asammdf.blocks.v4_constants as v4c class TestEndianess(unittest.TestCase): tempdir: tempfile.TemporaryDirectory[str] @classmethod def setUpClass(cls) -> None: cls.tempdir = tempfile.TemporaryDirectory() def test_mixed(self) -> None: t = np.arange(15, dtype=" None: t = np.arange(15, dtype="> 5) & (2**21 - 1)] * 15, ) assert np.array_equal( mdf.get("NotAlignedIntel").samples, [(0xF8040200 >> 6) & (2**21 - 1)] * 15, ) def test_not_aligned_mdf_v4(self) -> None: t = np.arange(15, dtype="> 5) & (2**21 - 1)] * 15, ) assert np.array_equal( mdf.get("NotAlignedIntel").samples, [(0xF8040200 >> 6) & (2**21 - 1)] * 15, ) def test_overlapping_channels_mdf_v3(self) -> None: t = np.arange(15, dtype="> 5) & (2**21 - 1)] * 15, ) assert np.array_equal( mdf.get("OverlappingIntel").samples, [(0xF8040200 >> 6) & (2**21 - 1)] * 15, ) def test_overlapping_channels_mdf_v4(self) -> None: t = np.arange(15, dtype="> 5) & (2**21 - 1)] * 15, ) assert np.array_equal( mdf.get("OverlappingIntel").samples, [(0xF8040200 >> 6) & (2**21 - 1)] * 15, ) ch3 = mdf4.groups[0].channels[2] ch3.byte_offset = 3 + t.itemsize ch3.data_type = v4c.DATA_TYPE_UNSIGNED_MOTOROLA ch3.bit_count = 2 ch3.bit_offset = 1 ch4 = mdf4.groups[0].channels[3] ch4.byte_offset = 3 + t.itemsize ch4.data_type = v4c.DATA_TYPE_UNSIGNED_INTEL ch4.bit_count = 2 ch4.bit_offset = 1 outfile = mdf_source.save(Path(TestEndianess.tempdir.name) / "out", overwrite=True) with MDF(outfile) as mdf: assert np.array_equal(mdf.get("OverlappingMotorola").samples, [0x1] * 15) assert np.array_equal(mdf.get("OverlappingIntel").samples, [0x1] * 15) if __name__ == "__main__": unittest.main() asammdf-8.5.1/test/test_mdf.py000066400000000000000000001170701502633300400162750ustar00rootroot00000000000000#!/usr/bin/env python from io import BytesIO from pathlib import Path import random import tempfile import unittest import urllib import urllib.request from zipfile import ZipFile import numexpr import numpy as np import numpy.typing as npt from pandas import DataFrame from typing_extensions import Any from asammdf import MDF, Signal, SUPPORTED_VERSIONS from asammdf.blocks.utils import MdfException from asammdf.mdf import SearchMode from .utils import cycles, generate_arrays_test_file, generate_test_file SUPPORTED_VERSIONS = tuple(version for version in SUPPORTED_VERSIONS if "4.20" > version >= "3.20") # type: ignore[misc] CHANNEL_LEN = 100000 class TestMDF(unittest.TestCase): tempdir_demo: tempfile.TemporaryDirectory[str] tempdir_array: tempfile.TemporaryDirectory[str] tempdir_general: tempfile.TemporaryDirectory[str] tempdir: tempfile.TemporaryDirectory[str] def test_measurement(self) -> None: self.assertTrue(MDF) @classmethod def setUpClass(cls) -> None: url = "https://github.com/danielhrisca/asammdf/files/4078993/test.demo.zip" urllib.request.urlretrieve(url, "test.zip") cls.tempdir_demo = tempfile.TemporaryDirectory() cls.tempdir_general = tempfile.TemporaryDirectory() cls.tempdir = tempfile.TemporaryDirectory() cls.tempdir_array = tempfile.TemporaryDirectory() ZipFile(r"test.zip").extractall(cls.tempdir_demo.name) Path("test.zip").unlink() for version in ("3.30", "4.10"): generate_test_file(cls.tempdir_general.name, version) generate_arrays_test_file(cls.tempdir_array.name) def test_mdf_header(self) -> None: mdf = BytesIO(b"M" * 100) with self.assertRaises(MdfException): MDF(mdf) mdf.close() def test_wrong_header_version(self) -> None: mdf = BytesIO( b"MDF AAAA amdf500d\x00\x00\x00\x00\x9f\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" ) with self.assertRaises(MdfException): MDF(mdf) mdf.close() def test_read(self) -> None: print("MDF read big files") for input_file in Path(TestMDF.tempdir_general.name).iterdir(): print(input_file) equal = True for inp in (input_file, BytesIO(input_file.read_bytes())): with MDF(inp) as mdf: for i, group in enumerate(mdf.groups): v: npt.NDArray[Any] if i == 0: v = np.ones(cycles, dtype=np.uint64) for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] if not np.array_equal(vals, v * (j - 1)): equal = False elif i == 1: v = np.ones(cycles, dtype=np.int64) for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] if not np.array_equal(vals, v * (j - 1) - 0.5): equal = False elif i == 2: v = np.arange(cycles, dtype=np.int64) / 100.0 form = "{} * sin(v)" for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] f = form.format(j - 1) if not np.array_equal(vals, numexpr.evaluate(f)): equal = False elif i == 3: v = np.ones(cycles, dtype=np.int64) form = "({} * v -0.5) / 1" for j in range(1, 20): f = form.format(j - 1) vals = mdf.get(group=i, index=j, samples_only=True)[0] if not np.array_equal(vals, numexpr.evaluate(f)): equal = False elif i == 4: for j in range(1, 20): target = np.array([f"Channel {j} sample {k}".encode("ascii") for k in range(cycles)]) vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) self.assertTrue(cond) elif i == 5: v = np.ones(cycles, dtype=np.dtype("(8,)u1")) for j in range(1, 20): target = v * j vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) self.assertTrue(cond) elif i == 6: for j in range(1, 20): target = np.array([b"Value %d" % j for _ in range(cycles)]) vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) self.assertTrue(cond) if isinstance(inp, BytesIO): inp.close() self.assertTrue(equal) def test_read_arrays(self) -> None: print("MDF read big array files") for input_file in Path(TestMDF.tempdir_array.name).iterdir(): print(input_file) equal = True for inp in (input_file, BytesIO(input_file.read_bytes())): with MDF(inp) as mdf: mdf.configure(read_fragment_size=8000) for i, group in enumerate(mdf.groups): if i == 0: samples_list = [ np.ones((cycles, 2, 3), dtype=np.uint64), np.ones((cycles, 2), dtype=np.uint64), np.ones((cycles, 3), dtype=np.uint64), ] for j in range(1, 20): types: list[npt.DTypeLike] = [ (f"Channel_{j}", "(2, 3) None: print("MDF read tests") mdf_files = [file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix in (".mdf", ".mf4")] signals = [file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix == ".npy"] for file in mdf_files: print(file) for inp in (file, BytesIO(file.read_bytes())): with MDF(inp, use_display_names=True) as input_file: for signal in signals: name = signal.stem target = np.load(signal) values = input_file.get(name, *input_file.whereis(name)[0]).samples self.assertTrue(np.array_equal(target, values)) if isinstance(inp, BytesIO): inp.close() def test_convert(self) -> None: print("MDF convert big files tests") for out in SUPPORTED_VERSIONS: for input_file in Path(TestMDF.tempdir_general.name).iterdir(): for compression in (0, 1, 2): print(input_file, out, compression) with MDF(input_file) as mdf: mdf.configure(read_fragment_size=8000) converted = mdf.convert(out) outfile = converted.save( Path(TestMDF.tempdir.name) / f"tmp_convert_{out}", overwrite=True, compression=compression, ) converted.close() equal = True with MDF(outfile) as mdf: mdf.configure(read_fragment_size=8000) for i, group in enumerate(mdf.groups): v: npt.NDArray[Any] if i == 0: v = np.ones(cycles, dtype=np.uint64) for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] if not np.array_equal(vals, v * (j - 1)): equal = False print(outfile) print(vals, len(vals)) print(v * (j - 1), len(v)) raise Exception elif i == 1: v = np.ones(cycles, dtype=np.int64) for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] if not np.array_equal(vals, v * (j - 1) - 0.5): equal = False raise Exception elif i == 2: v = np.arange(cycles, dtype=np.int64) / 100.0 form = "{} * sin(v)" for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] f = form.format(j - 1) if not np.array_equal(vals, numexpr.evaluate(f)): equal = False raise Exception elif i == 3: v = np.ones(cycles, dtype=np.int64) form = "({} * v -0.5) / 1" for j in range(1, 20): f = form.format(j - 1) vals = mdf.get(group=i, index=j, samples_only=True)[0] if not np.array_equal(vals, numexpr.evaluate(f)): equal = False target = numexpr.evaluate(f) print(i, j, vals, target, len(vals), len(target)) raise Exception elif i == 4: for j in range(1, 20): target = np.array( [f"Channel {j} sample {k}".encode("ascii") for k in range(cycles)] ) vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) raise Exception self.assertTrue(cond) elif i == 5: v = np.ones(cycles, dtype=np.dtype("(8,)u1")) for j in range(1, 20): target = v * j vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) raise Exception self.assertTrue(cond) elif i == 6: for j in range(1, 20): target = np.array([b"Value %d" % j for _ in range(cycles)]) vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) raise Exception self.assertTrue(cond) self.assertTrue(equal) def test_convert_demo(self) -> None: print("MDF convert demo tests") mdf_files = [file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix in (".mdf", ".mf4")] signals = [file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix == ".npy"] for file in mdf_files: for inp in (file, BytesIO(file.read_bytes())): with MDF(inp, use_display_names=True) as input_file: for out in SUPPORTED_VERSIONS: print(file, out, type(inp)) converted = input_file.convert(out) outfile = converted.save(Path(TestMDF.tempdir_demo.name) / "tmp", overwrite=True) converted.close() with MDF(outfile, use_display_names=True) as mdf: for signal in signals: name = signal.stem target = np.load(signal) values = mdf.get(name, *mdf.whereis(name)[0]).samples self.assertTrue(np.array_equal(target, values)) if isinstance(inp, BytesIO): inp.close() def test_cut(self) -> None: print("MDF cut big files tests") for input_file in Path(TestMDF.tempdir_general.name).iterdir(): for whence in (0, 1): for compression in (0, 1, 2): mdf = MDF(input_file) mdf.configure(read_fragment_size=8000) cut = mdf.cut(stop=-1, whence=whence, include_ends=False) outfile0 = cut.save(Path(TestMDF.tempdir.name) / "tmp0", overwrite=True) cut.close() mdf.configure(read_fragment_size=8000) cut = mdf.cut(stop=105, whence=whence, include_ends=False) outfile1 = cut.save(Path(TestMDF.tempdir.name) / "tmp1", overwrite=True) cut.close() mdf.configure(read_fragment_size=8000) cut = mdf.cut(start=105.1, stop=201, whence=whence, include_ends=False) outfile2 = cut.save(Path(TestMDF.tempdir.name) / "tmp2", overwrite=True) cut.close() mdf.configure(read_fragment_size=8000) cut = mdf.cut(start=201.1, whence=whence, include_ends=False) outfile3 = cut.save(Path(TestMDF.tempdir.name) / "tmp3", overwrite=True) cut.close() mdf.configure(read_fragment_size=8000) cut = mdf.cut(start=7000, whence=whence, include_ends=False) outfile4 = cut.save(Path(TestMDF.tempdir.name) / "tmp4", overwrite=True) cut.close() concatenated = MDF.concatenate( [outfile0, outfile1, outfile2, outfile3, outfile4], version=mdf.version, sync=bool(whence), ) outfile = concatenated.save( Path(TestMDF.tempdir.name) / "tmp_cut", overwrite=True, compression=compression, ) mdf.close() concatenated.close() with MDF(outfile) as mdf: for i, group in enumerate(mdf.groups): v: npt.NDArray[Any] if i == 0: v = np.ones(cycles, dtype=np.uint64) for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] cond = np.array_equal(vals, v * (j - 1)) if not cond: print(i, j, vals, v * (j - 1), len(vals), len(v)) self.assertTrue(cond) elif i == 1: v = np.ones(cycles, dtype=np.int64) for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] cond = np.array_equal(vals, v * (j - 1) - 0.5) if not cond: print(vals, v * (j - 1) - 0.5, len(vals), len(v)) self.assertTrue(cond) elif i == 2: v = np.arange(cycles, dtype=np.int64) / 100.0 form = "{} * sin(v)" for j in range(1, 20): vals = mdf.get(group=i, index=j, samples_only=True)[0] f = form.format(j - 1) target = numexpr.evaluate(f) cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) self.assertTrue(cond) elif i == 3: v = np.ones(cycles, dtype=np.int64) form = "({} * v -0.5) / 1" for j in range(1, 20): f = form.format(j - 1) vals = mdf.get(group=i, index=j, samples_only=True)[0] target = numexpr.evaluate(f) cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) self.assertTrue(cond) elif i == 4: for j in range(1, 20): target = np.array( [f"Channel {j} sample {k}".encode("ascii") for k in range(cycles)] ) vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) self.assertTrue(cond) elif i == 5: v = np.ones(cycles, dtype=np.dtype("(8,)u1")) for j in range(1, 20): target = v * j vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) self.assertTrue(cond) elif i == 6: for j in range(1, 20): target = np.array([b"Value %d" % j for _ in range(cycles)]) vals = mdf.get(group=i, index=j + 1, samples_only=True)[0] cond = np.array_equal(vals, target) if not cond: print(i, j, vals, target, len(vals), len(target)) self.assertTrue(cond) def test_cut_arrays(self) -> None: print("MDF cut big array files") for input_file in Path(TestMDF.tempdir_array.name).iterdir(): for whence in (0, 1): print(input_file, whence) mdf = MDF(input_file) mdf.configure(read_fragment_size=8000) cut = mdf.cut(stop=105.5, whence=whence, include_ends=False) outfile1 = cut.save(Path(TestMDF.tempdir.name) / "tmp1", overwrite=True) cut.close() cut = mdf.cut(start=105.5, stop=201.5, whence=whence, include_ends=False) outfile2 = cut.save(Path(TestMDF.tempdir.name) / "tmp2", overwrite=True) cut.close() cut = mdf.cut(start=201.5, whence=whence, include_ends=False) outfile3 = cut.save(Path(TestMDF.tempdir.name) / "tmp3", overwrite=True) cut.close() concatenated = MDF.concatenate([outfile1, outfile2, outfile3], mdf.version) outfile = concatenated.save(Path(TestMDF.tempdir.name) / "tmp_cut", overwrite=True) mdf.close() concatenated.close() equal = True with MDF(outfile) as mdf: mdf.configure(read_fragment_size=8000) for i, group in enumerate(mdf.groups): if i == 0: samples_list = [ np.ones((cycles, 2, 3), dtype=np.uint64), np.ones((cycles, 2), dtype=np.uint64), np.ones((cycles, 3), dtype=np.uint64), ] for j in range(1, 20): types: list[npt.DTypeLike] = [ (f"Channel_{j}", "(2, 3) None: print("MDF cut demo tests") mdf_files = [file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix in (".mdf", ".mf4")] signals = [file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix == ".npy"] for file in mdf_files: print(file) for inp in (file, BytesIO(file.read_bytes())): with MDF(inp, use_display_names=True) as input_file: for whence in (0, 1): print(file, whence) cut = input_file.cut(stop=2, whence=whence, include_ends=False) outfile1 = cut.save(Path(TestMDF.tempdir.name) / "tmp1", overwrite=True) cut.close() cut = input_file.cut(start=2, stop=6, whence=whence, include_ends=False) outfile2 = cut.save(Path(TestMDF.tempdir.name) / "tmp2", overwrite=True) cut.close() cut = input_file.cut(start=6, whence=whence, include_ends=False) outfile3 = cut.save(Path(TestMDF.tempdir.name) / "tmp3", overwrite=True) cut.close() concatenated = MDF.concatenate( [outfile1, outfile2, outfile3], version=input_file.version, use_display_names=True, ) outfile = concatenated.save(Path(TestMDF.tempdir.name) / "tmp", overwrite=True) print("OUT", outfile) concatenated.close() with MDF(outfile, use_display_names=True) as mdf2: for signal in signals: target = np.load(signal) sig = mdf2.get(signal.stem, *mdf2.whereis(signal.stem)[0]) timestamps = input_file.get(signal.stem, *input_file.whereis(signal.stem)[0]).timestamps self.assertTrue(np.array_equal(sig.samples, target)) self.assertTrue(np.array_equal(timestamps, sig.timestamps)) if isinstance(inp, BytesIO): inp.close() def test_filter(self) -> None: print("MDF read tests") mdf_files = [file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix in (".mdf", ".mf4")] signals = {file.stem: file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix == ".npy"} for file in mdf_files: print(file) for inp in (file, BytesIO(file.read_bytes())): with MDF(inp, use_display_names=True) as input_file: names = [ch.name for gp in input_file.groups for ch in gp.channels[1:]] channels_nr = np.random.randint(1, len(names) + 1) channel_list = random.sample(names, channels_nr) filtered_mdf = input_file.filter(channel_list) target_names = set(filtered_mdf.channels_db) self.assertFalse(set(channel_list) - (target_names - {"time"})) for name in channel_list: target = np.load(signals[name]) filtered = filtered_mdf.get(name) self.assertTrue(np.array_equal(target, filtered.samples)) filtered_mdf.close() if isinstance(inp, BytesIO): inp.close() def test_select(self) -> None: print("MDF select tests") mdf_files = [file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix in (".mdf", ".mf4")] signals = {file.stem: file for file in Path(TestMDF.tempdir_demo.name).iterdir() if file.suffix == ".npy"} for file in mdf_files: print(file) for inp in (file, BytesIO(file.read_bytes())): with MDF(inp, use_display_names=True) as input_file: names = [ch.name for gp in input_file.groups for ch in gp.channels[1:]] input_file.configure(read_fragment_size=200) channels_nr = np.random.randint(1, len(names) + 1) channel_list = random.sample(names, channels_nr) selected_signals = input_file.select(channel_list) target_names = {s.name for s in selected_signals} self.assertFalse(set(target_names) - set(channel_list)) for name, sig in zip(channel_list, selected_signals, strict=False): target = np.load(signals[name]) self.assertTrue(np.array_equal(target, sig.samples)) if isinstance(inp, BytesIO): inp.close() def test_scramble(self) -> None: print("MDF scramble tests") for input_file in Path(TestMDF.tempdir_demo.name).iterdir(): if input_file.suffix.lower() in (".mdf", ".mf4"): scrambled = MDF.scramble(input_file) self.assertTrue(scrambled) Path(scrambled).unlink() def test_iter_groups(self) -> None: dfs = [ DataFrame( { f"df_{i}_column_0": np.ones(5) * i, f"df_{i}_column_1": np.arange(5) * i, } ) for i in range(5) ] mdf = MDF() for df in dfs: mdf.append(df) for i, mdf_df in enumerate(mdf.iter_groups()): self.assertTrue(mdf_df.equals(dfs[i])) mdf.close() def test_resample_raster_0(self) -> None: sigs = [ Signal( samples=np.ones(1000) * i, timestamps=np.arange(1000), name=f"Signal_{i}", ) for i in range(20) ] mdf = MDF() mdf.append(sigs) mdf.configure(read_fragment_size=1) with self.assertRaises(MdfException): mdf = mdf.resample(raster=0) mdf.close() def test_resample(self) -> None: raster = 1.33 sigs = [ Signal( samples=np.arange(1000, dtype="f8"), timestamps=np.concatenate([np.arange(500), np.arange(1000, 1500)]), name=f"Signal_{i}", ) for i in range(20) ] mdf = MDF() mdf.append(sigs) resampled = mdf.resample(raster=raster) mdf.close() target_timestamps = np.arange(0, 1500, 1.33) target_samples = np.concatenate( [ np.arange(0, 500, 1.33), np.linspace(499.00215568862274, 499.9976646706587, 376), np.arange(500.1600000000001, 1000, 1.33), ] ) for i, sig in enumerate(resampled.iter_channels(skip_master=True)): self.assertTrue(np.array_equal(sig.timestamps, target_timestamps)) self.assertTrue(np.allclose(sig.samples, target_samples)) resampled.close() def test_to_dataframe(self) -> None: dfs = [ DataFrame( { f"df_{i}_column_0": np.ones(5) * i, f"df_{i}_column_1": np.arange(5) * i, } ) for i in range(5) ] mdf = MDF() for df in dfs: mdf.append(df) target: dict[str, npt.NDArray[Any]] = {} for i in range(5): target[f"df_{i}_column_0"] = np.ones(5) * i target[f"df_{i}_column_1"] = np.arange(5) * i df = DataFrame(target) self.assertTrue(df.equals(mdf.to_dataframe())) mdf.close() def test_search(self) -> None: sigs = [ Signal( samples=np.ones(1), timestamps=np.arange(1), name=ch_name, ) for ch_name in ["foo", "Bar", "baz"] ] mdf = MDF() mdf.append(sigs) # plain text matching self.assertEqual(["foo"], mdf.search(pattern="foo"), msg="name match full") self.assertEqual(["foo"], mdf.search(pattern="oo", mode="plain"), msg="name match part") self.assertEqual( [], mdf.search(pattern="FOO", mode=SearchMode.plain, case_insensitive=False), msg="name match case-sensitive (no match)", ) self.assertEqual( ["foo"], mdf.search(pattern="FOO", mode=SearchMode.plain, case_insensitive=True), msg="name match case-insensitive (match)", ) # regex matching self.assertEqual(["Bar"], mdf.search(pattern="^Bar$", mode="regex"), msg="regex match full") self.assertEqual( ["baz"], mdf.search(pattern="z$", mode=SearchMode.regex), msg="regex match part", ) self.assertEqual( ["baz"], mdf.search(pattern="b.*", mode=SearchMode.regex, case_insensitive=False), msg="regex match case-sensitive", ) self.assertEqual( ["Bar", "baz"], mdf.search(pattern="b.*", mode=SearchMode.regex, case_insensitive=True), msg="regex match case-insensitive", ) # wildcard matching self.assertEqual( ["Bar"], mdf.search(pattern="Bar", mode="wildcard"), msg="wildcard match full", ) self.assertEqual( ["foo"], mdf.search(pattern="*oo", mode=SearchMode.wildcard), msg="wildcard match part", ) self.assertEqual( ["baz"], mdf.search(pattern="b*", mode=SearchMode.wildcard, case_insensitive=False), msg="wildcard match case-sensitive", ) self.assertEqual( ["Bar", "baz"], mdf.search(pattern="b*", mode=SearchMode.wildcard, case_insensitive=True), msg="wildcard match case-insensitive", ) if __name__ == "__main__": unittest.main() asammdf-8.5.1/test/test_mdf23.py000066400000000000000000000111011502633300400164260ustar00rootroot00000000000000#!/usr/bin/env python from pathlib import Path import tempfile import unittest import numpy as np from asammdf import MDF, Signal from asammdf.blocks.mdf_v2 import MDF2 from asammdf.blocks.mdf_v3 import MDF3 CHANNEL_LEN = 10000 class TestMDF23(unittest.TestCase): tempdir: tempfile.TemporaryDirectory[str] @classmethod def setUpClass(cls) -> None: cls.tempdir = tempfile.TemporaryDirectory() def test_measurement(self) -> None: self.assertTrue(MDF2) self.assertTrue(MDF3) def test_read_mdf2_00(self) -> None: seed = np.random.randint(0, 2**31) np.random.seed(seed) print("Read 2.00 using seed =", seed) sig_int = Signal( np.random.randint(-(2**15), -1, CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Integer Channel", unit="unit1", ) sig_float = Signal( np.random.random(CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Float Channel", unit="unit2", ) with MDF(version="2.00") as mdf: mdf.append([sig_int, sig_float], common_timebase=True) outfile = mdf.save(Path(TestMDF23.tempdir.name) / "tmp", overwrite=True) with MDF(outfile) as mdf: ret_sig_int = mdf.get(sig_int.name) ret_sig_float = mdf.get(sig_float.name) self.assertTrue(np.array_equal(ret_sig_int.samples, sig_int.samples)) self.assertTrue(np.array_equal(ret_sig_float.samples, sig_float.samples)) def test_read_mdf2_14(self) -> None: seed = np.random.randint(0, 2**31) np.random.seed(seed) print("Read 2.14 using seed =", seed) sig_int = Signal( np.random.randint(-(2**29), 2**29, CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Integer Channel", unit="unit1", ) sig_float = Signal( np.random.random(CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Float Channel", unit="unit2", ) with MDF(version="2.14") as mdf: mdf.append([sig_int, sig_float], common_timebase=True) outfile = mdf.save(Path(TestMDF23.tempdir.name) / "tmp", overwrite=True) with MDF(outfile) as mdf: ret_sig_int = mdf.get(sig_int.name) ret_sig_float = mdf.get(sig_float.name) self.assertTrue(np.array_equal(ret_sig_int.samples, sig_int.samples)) self.assertTrue(np.array_equal(ret_sig_float.samples, sig_float.samples)) def test_read_mdf3_00(self) -> None: seed = np.random.randint(0, 2**31) np.random.seed(seed) print("Read 3.00 using seed =", seed) sig_int = Signal( np.random.randint(-(2**16), 2**16, CHANNEL_LEN, np.int32), np.arange(CHANNEL_LEN), name="Integer Channel", unit="unit1", ) sig_float = Signal( np.random.random(CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Float Channel", unit="unit2", ) with MDF(version="3.00") as mdf: mdf.append([sig_int, sig_float], common_timebase=True) outfile = mdf.save(Path(TestMDF23.tempdir.name) / "tmp", overwrite=True) with MDF(outfile) as mdf: ret_sig_int = mdf.get(sig_int.name) ret_sig_float = mdf.get(sig_float.name) self.assertTrue(np.array_equal(ret_sig_int.samples, sig_int.samples)) self.assertTrue(np.array_equal(ret_sig_float.samples, sig_float.samples)) def test_read_mdf3_10(self) -> None: seed = np.random.randint(0, 2**31) np.random.seed(seed) print("Read 3.10 using seed =", seed) sig_int = Signal( np.random.randint(-(2**9), 2**7, CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Integer Channel", unit="unit1", ) sig_float = Signal( np.random.random(CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Float Channel", unit="unit2", ) with MDF(version="3.10") as mdf: mdf.append([sig_int, sig_float], common_timebase=True) outfile = mdf.save(Path(TestMDF23.tempdir.name) / "tmp", overwrite=True) with MDF(outfile) as mdf: ret_sig_int = mdf.get(sig_int.name) ret_sig_float = mdf.get(sig_float.name) self.assertTrue(np.array_equal(ret_sig_int.samples, sig_int.samples)) self.assertTrue(np.array_equal(ret_sig_float.samples, sig_float.samples)) if __name__ == "__main__": unittest.main() asammdf-8.5.1/test/test_mdf4.py000066400000000000000000000113101502633300400163470ustar00rootroot00000000000000#!/usr/bin/env python from pathlib import Path import tempfile import unittest import numpy as np from asammdf import MDF, Signal from asammdf.blocks.mdf_v4 import MDF4 CHANNEL_LEN = 100000 class TestMDF4(unittest.TestCase): tempdir: tempfile.TemporaryDirectory[str] @classmethod def setUpClass(cls) -> None: cls.tempdir = tempfile.TemporaryDirectory() def test_measurement(self) -> None: self.assertTrue(MDF4) def test_read_mdf4_00(self) -> None: seed = np.random.randint(0, 2**31) np.random.seed(seed) print("Read 4.00 using seed =", seed) sig_int = Signal( np.random.randint(-(2**31), 2**31, CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Integer Channel", unit="unit1", ) sig_float = Signal( np.random.random(CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Float Channel", unit="unit2", ) with MDF(version="4.00") as mdf: mdf.append([sig_int, sig_float], common_timebase=True) outfile = mdf.save(Path(TestMDF4.tempdir.name) / "tmp", overwrite=True) with MDF(outfile) as mdf: ret_sig_int = mdf.get(sig_int.name) ret_sig_float = mdf.get(sig_float.name) self.assertTrue(np.array_equal(ret_sig_int.samples, sig_int.samples)) self.assertTrue(np.array_equal(ret_sig_float.samples, sig_float.samples)) def test_read_mdf4_10(self) -> None: seed = np.random.randint(0, 2**31) np.random.seed(seed) print("Read 4.10 using seed =", seed) sig_int = Signal( np.random.randint(-(2**31), 2**31, CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Integer Channel", unit="unit1", ) sig_float = Signal( np.random.random(CHANNEL_LEN), np.arange(CHANNEL_LEN), name="Float Channel", unit="unit2", ) with MDF(version="4.10") as mdf: mdf.append([sig_int, sig_float], common_timebase=True) outfile = mdf.save(Path(TestMDF4.tempdir.name) / "tmp", overwrite=True) with MDF(outfile) as mdf: ret_sig_int = mdf.get(sig_int.name) ret_sig_float = mdf.get(sig_float.name) self.assertTrue(np.array_equal(ret_sig_int.samples, sig_int.samples)) self.assertTrue(np.array_equal(ret_sig_float.samples, sig_float.samples)) def test_attachment_blocks_wo_filename(self) -> None: original_data = b"Testing attachemnt block\nTest line 1" mdf = MDF() mdf.attach( original_data, file_name=None, comment="", compression=True, mime=r"text/plain", embedded=True, ) outfile = mdf.save(Path(TestMDF4.tempdir.name) / "attachment.mf4", overwrite=True) with MDF(outfile) as attachment_mdf: data, filename, md5_sum = attachment_mdf.extract_attachment(index=0) self.assertEqual(data, original_data) self.assertEqual(filename, Path("bin.bin")) mdf.close() def test_attachment_blocks_w_filename(self) -> None: original_data = b"Testing attachemnt block\nTest line 1" original_file_name = "file.txt" mdf = MDF() mdf.attach( original_data, file_name=original_file_name, comment="", compression=True, mime=r"text/plain", embedded=True, ) outfile = mdf.save(Path(TestMDF4.tempdir.name) / "attachment.mf4", overwrite=True) with MDF(outfile) as attachment_mdf: data, filename, md5_sum = attachment_mdf.extract_attachment(index=0) self.assertEqual(data, original_data) self.assertEqual(filename, Path(original_file_name)) mdf.close() def test_channel_with_boolean_array(self) -> None: timestamps = np.array([0.1, 0.2, 0.3, 0.4, 0.5], dtype=np.float32) samples = [np.ones((5, 2), dtype=np.uint8)] types = [("boolean_array_channel", "(2, ) None: s = Signal([], [], name="s") self.assertEqual(len(s), 0) def test_init_errors(self) -> None: with self.assertRaises(MdfException): Signal([], [1], name="s") with self.assertRaises(MdfException): Signal([1], [], name="s") with self.assertRaises(MdfException): Signal([1, 2, 3], [1, 2], name="s") with self.assertRaises(MdfException): Signal(np.array([]), np.array([1]), name="s") with self.assertRaises(MdfException): Signal(np.array([1]), np.array([]), name="s") with self.assertRaises(MdfException): Signal(np.array([1, 2, 3]), np.array([1, 2]), name="s") with self.assertRaises(MdfException): Signal(np.array([]), np.array([])) def test_cut_int(self) -> None: s = Signal(np.arange(5), np.arange(5, dtype=" None: s = Signal(np.arange(5, dtype=" None: s = Signal(np.arange(5, dtype=" None: s = Signal(np.arange(5, dtype=" None: s = Signal(np.arange(5, dtype=" None: s = Signal(np.arange(1, 5, dtype=" None: s = Signal(np.arange(1, 5, dtype=" None: cls.compressed = BytesIO() cls.compressed.write( b"\x00##TX\x00\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00embedded.txt\x00\x00\x00\x00##TX\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00example of embedded attachment\x00\x00##AT\x00\x00\x00\x00\xd3\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\xeb\x825\x1a\x0cri\xb9\xca\xfb\xde\xb6pT\x17k\x85\x01\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x00\x00\x00\x00x\x9c5\xd0\xb9\r\xc3P\x0c\x04\xd1\\U\xb8\x04\xed\xe1C\x0590 \xa8\xffP08?\x9a\x88\x0f$\xcf\xdf\xf5}\xec\xdb\xf9\x8f&\x9ed\xd2\xc9s\xf2\x9a\xbc'\x9f\xc9\xc1\xf8bp\x04$$A\tK`B\x13\x9c\xf0\x8c\xe7\xb5\x17\x9e\xf1\x8cg<\xe3\x19\xcfx\xc6\x0b^\xf0\xb2\x0e\xc5\x0b^\xf0\x82\x17\xbc\xe0\x05\xafx\xc5+^\xd7\xe7\xf0\x8aW\xbc\xe2\x15\xaf\xc7\r\xca\xd1m \x00\x00\x00\x00" ) cls.uncompressed = BytesIO() cls.uncompressed.write( b"\x00##TX\x00\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00embedded.txt\x00\x00\x00\x00##TX\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00example of embedded attachment\x00\x00##AT\x00\x00\x00\x00\xe5\x01\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\xeb\x825\x1a\x0cri\xb9\xca\xfb\xde\xb6pT\x17k\x85\x01\x00\x00\x00\x00\x00\x00\x85\x01\x00\x00\x00\x00\x00\x00line 0\nline 1\nline 2\nline 3\nline 4\nline 5\nline 6\nline 7\nline 8\nline 9\nline 10\nline 11\nline 12\nline 13\nline 14\nline 15\nline 16\nline 17\nline 18\nline 19\nline 20\nline 21\nline 22\nline 23\nline 24\nline 25\nline 26\nline 27\nline 28\nline 29\nline 30\nline 31\nline 32\nline 33\nline 34\nline 35\nline 36\nline 37\nline 38\nline 39\nline 40\nline 41\nline 42\nline 43\nline 44\nline 45\nline 46\nline 47\nline 48\nline 49\x00\x00" ) def test_read_compressed(self) -> None: self.compressed.seek(0) block = AttachmentBlock(address=97, stream=self.compressed) self.assertEqual(block.file_name, self.filename) self.assertEqual(block.extract(), self.data) self.assertEqual(block.comment, self.comment) def test_read_uncompressed(self) -> None: self.uncompressed.seek(0) block = AttachmentBlock(address=97, stream=self.uncompressed) self.assertEqual(block.file_name, self.filename) self.assertEqual(block.extract(), self.data) self.assertEqual(block.comment, self.comment) def test_read_wrong_id(self) -> None: self.compressed.seek(0) stream = BytesIO(self.compressed.read()) stream.seek(97) stream.write(b"_NOK") with self.assertRaises(MdfException): AttachmentBlock(address=97, stream=stream) def test_bytes_compressed(self) -> None: attachment = AttachmentBlock(file_name=self.filename, data=self.data, embedded=True, compression=True) attachment.comment = self.comment stream = BytesIO() stream.write(b"\0") blocks: list[bytes | SupportsBytes] = [] attachment.to_blocks(1, blocks, {}) for block in blocks: stream.write(bytes(block)) address = attachment.address block = AttachmentBlock(address=address, stream=stream) self.assertEqual(block.comment, self.comment) self.assertEqual(block.file_name, self.filename) self.assertEqual(block.extract(), self.data) def test_bytes_uncompressed(self) -> None: attachment = AttachmentBlock(file_name=self.filename, data=self.data, embedded=True, compression=False) attachment.comment = self.comment stream = BytesIO() stream.write(b"\0") blocks: list[bytes | SupportsBytes] = [] attachment.to_blocks(1, blocks, {}) for block in blocks: stream.write(bytes(block)) address = attachment.address block = AttachmentBlock(address=address, stream=stream) self.assertEqual(block.comment, self.comment) self.assertEqual(block.file_name, self.filename) self.assertEqual(block.extract(), self.data) if __name__ == "__main__": unittest.main() asammdf-8.5.1/test/test_v4_blocks/test_txblock.py000066400000000000000000000041751502633300400221230ustar00rootroot00000000000000#!/usr/bin/env python from io import BytesIO import typing import unittest from asammdf.blocks.utils import MdfException from asammdf.blocks.v4_blocks import TextBlock class TestATBLOCK(unittest.TestCase): plain_text: str plain_bytes: bytes plain_stream: BytesIO meta_text: str meta_bytes: bytes meta_stream: BytesIO @classmethod def setUpClass(cls) -> None: cls.plain_text = "sample text" cls.plain_bytes = b"##TX\x00\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00sample text\x00\x00\x00\x00\x00" cls.plain_stream = BytesIO() cls.plain_stream.write(cls.plain_bytes) cls.meta_text = "sample text" cls.meta_bytes = b"##MD\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00sample text\x00\x00\x00\x00" cls.meta_stream = BytesIO() cls.meta_stream.write(cls.meta_bytes) def test_read(self) -> None: self.plain_stream.seek(0) block = TextBlock(address=0, stream=self.plain_stream) self.assertEqual(block.id, b"##TX") self.assertIsInstance(block.text, bytes) block.text = typing.cast(bytes, block.text) self.assertEqual(block.text.strip(b"\0").decode("utf-8"), self.plain_text) self.meta_stream.seek(0) block = TextBlock(address=0, stream=self.meta_stream) self.assertEqual(block.id, b"##MD") self.assertIsInstance(block.text, bytes) block.text = typing.cast(bytes, block.text) self.assertEqual(block.text.strip(b"\0").decode("utf-8"), self.meta_text) def test_read_wrong_id(self) -> None: stream = BytesIO(self.plain_bytes) stream.seek(0) stream.write(b"_NOK") with self.assertRaises(MdfException): TextBlock(address=0, stream=stream) def test_bytes(self) -> None: block = TextBlock(text=self.plain_text, meta=False) self.assertEqual(bytes(block), self.plain_bytes) block = TextBlock(text=self.meta_text, meta=True) self.assertEqual(bytes(block), self.meta_bytes) if __name__ == "__main__": unittest.main() asammdf-8.5.1/test/utils.py000066400000000000000000000205161502633300400156260ustar00rootroot00000000000000from pathlib import Path import numpy as np import numpy.typing as npt from typing_extensions import Any from asammdf import MDF, Signal, SUPPORTED_VERSIONS import asammdf.blocks.v2_v3_blocks as v3b import asammdf.blocks.v2_v3_constants as v3c import asammdf.blocks.v4_blocks as v4b import asammdf.blocks.v4_constants as v4c SUPPORTED_VERSIONS = SUPPORTED_VERSIONS[1:] # type: ignore[misc] cycles = 500 channels_count = 20 array_channels_count = 20 def get_test_data(filename: str = "") -> Path: """ Utility functions needed by all test scripts. """ return Path(__file__).resolve().parent.joinpath("/data/", filename) def generate_test_file(tmpdir: str, version: str = "4.10") -> Path | None: mdf = MDF(version=version) if version <= "3.30": filename = Path(tmpdir) / f"big_test_{version}.mdf" else: filename = Path(tmpdir) / f"big_test_{version}.mf4" if filename.exists(): return filename t = np.arange(cycles, dtype=np.float64) cls = v4b.ChannelConversion if version >= "4.00" else v3b.ChannelConversion # no conversion sigs = [] for i in range(channels_count): sig = Signal( np.ones(cycles, dtype=np.uint64) * i, t, name=f"Channel_{i}", unit=f"unit_{i}", conversion=None, comment=f"Unsigned int 16bit channel {i}", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # linear sigs = [] for i in range(channels_count): conversion: dict[str, Any] = { "conversion_type": v4c.CONVERSION_TYPE_LIN if version >= "4.00" else v3c.CONVERSION_TYPE_LINEAR, "a": float(i), "b": -0.5, } sig = Signal( np.ones(cycles, dtype=np.int64), t, name=f"Channel_{i}", unit=f"unit_{i}", conversion=cls(**conversion), comment=f"Signed 16bit channel {i} with linear conversion", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # algebraic sigs = [] for i in range(channels_count): conversion = { "conversion_type": v4c.CONVERSION_TYPE_ALG if version >= "4.00" else v3c.CONVERSION_TYPE_FORMULA, "formula": f"{i} * sin(X)", } sig = Signal( np.arange(cycles, dtype=np.int32) / 100.0, t, name=f"Channel_{i}", unit=f"unit_{i}", conversion=cls(**conversion), comment=f"Sinus channel {i} with algebraic conversion", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # rational sigs = [] for i in range(channels_count): conversion = { "conversion_type": v4c.CONVERSION_TYPE_RAT if version >= "4.00" else v3c.CONVERSION_TYPE_RAT, "P1": 0, "P2": i, "P3": -0.5, "P4": 0, "P5": 0, "P6": 1, } sig = Signal( np.ones(cycles, dtype=np.int64), t, name=f"Channel_{i}", unit=f"unit_{i}", conversion=cls(**conversion), comment=f"Channel {i} with rational conversion", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # string sigs = [] encoding = "latin-1" if version < "4.00" else "utf-8" for i in range(channels_count): strings = [f"Channel {i} sample {j}".encode(encoding) for j in range(cycles)] sig = Signal( np.array(strings), t, name=f"Channel_{i}", unit=f"unit_{i}", comment=f"String channel {i}", raw=True, encoding=encoding, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # byte array sigs = [] ones = np.ones(cycles, dtype=np.dtype("(8,)u1")) for i in range(channels_count): sig = Signal( ones * i, t, name=f"Channel_{i}", unit=f"unit_{i}", comment=f"Byte array channel {i}", raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) # value to text sigs = [] ones = np.ones(cycles, dtype=np.uint64) conversion = { "raw": np.arange(255, dtype=np.float64), "phys": np.array([f"Value {i}".encode("ascii") for i in range(255)]), "conversion_type": v4c.CONVERSION_TYPE_TABX if version >= "4.00" else v3c.CONVERSION_TYPE_TABX, "links_nr": 260, "ref_param_nr": 255, } for i in range(255): conversion[f"val_{i}"] = conversion[f"param_val_{i}"] = conversion["raw"][i] conversion[f"text_{i}"] = conversion["phys"][i] conversion[f"text_{255}"] = "Default" for i in range(channels_count): sig = Signal( ones * i, t, name=f"Channel_{i}", unit=f"unit_{i}", comment=f"Value to text channel {i}", conversion=cls(**conversion), raw=True, ) sigs.append(sig) mdf.append(sigs, common_timebase=True) name = mdf.save(filename, overwrite=True) mdf.close() return None def generate_arrays_test_file(tmpdir: str) -> Path | None: version = "4.10" mdf = MDF(version=version) filename = Path(tmpdir) / f"arrays_test_{version}.mf4" if filename.exists(): return filename t = np.arange(cycles, dtype=np.float64) # lookup tabel with axis sigs = [] for i in range(array_channels_count): samples: list[npt.NDArray[Any]] = [ np.ones((cycles, 2, 3), dtype=np.uint64) * i, np.ones((cycles, 2), dtype=np.uint64) * i, np.ones((cycles, 3), dtype=np.uint64) * i, ] types: list[npt.DTypeLike] = [ (f"Channel_{i}", "(2, 3)=1.2 ldfparser extras = decode encryption export export-matlab-v5 gui symbolic-math commands = pyinstaller asammdf.spec {posargs} [gh-actions] python = 3.10: py310, mypy, ruff, doc 3.11: py311 3.12: py312 3.13: py313, mypy [pytest] python_classes = testpaths = test addopts = -vv --color=yes --code-highlight=yes --junitxml=test-reports/unit-tests-results.xml timeout = 600 asammdf-8.5.1/types-requirements.txt000066400000000000000000000002121502633300400175520ustar00rootroot00000000000000pandas-stubs pyarrow-stubs scipy-stubs; python_version >= '3.10' types-lxml types-psutil types-PyAutoGUI types-python-dateutil types-zstd

yOxyHs{9Ķ{^wG$$zկW÷ΆKbA`{9lGI8QfE*HKL"H! !;!<қ^0џ~_v'Q{?=>Doooo8- Pr&,105 ,pd*EaY/p0 POOt "0fn.0 p Ꮀ% R /ap  a"fmsPyHՐo!0 /p@!° pm0[ B*! 1%q)!")q=3b0N`PuPaf/alq1uqy}}FiQ =ocf"6!1q1(2a"H q0 F=!H1L`dAN!A!]A,"12#5,O  O ["YrS$^1 a NRʘZ'3%%&CLUq!S!W(Jr(?Dr1)Qr]'+**RR $R''+r.iJ,1+p+w󼯔20. /P/q'J03Se 3Sq/CR%15S#m"sR1;s4I4;32E4Y5]Ўh!5us7yӲMj8n)s78~3 熓+139s:4/87Π);;f9kNM;'3=s=F<7/;W=s>R;3>s??)>mN8-@4A@92 TA%tB)409/ 7 B9C=t 8>5CMDQ4HsDDSEaB/2874Fq4GsFT?uGtGWAkt;3H4IwGIFI5En4J4KAF;aٹ9y鹞9y:z :z!:%z)!ỤY XְLg8pYx9!ezimq:uzy}:z:z:z:zg: ]kҊ!Z;VIyTxax+z;{ ;{!;%{)-1;5{9=A; {8Zn",Gz("U䚥Ty};{;{;{;{;{{uaY^gl`وMZ9D)xZ<| <|!<%|)-1<5|9=A~!>%~)-1>5~9=A>E~IMQ>U~Y)meˆ!ƍEz~~艾>~陾>~ꩾ>~빾>~ɾ끞\!m>^E:~? ?!?%)-1?59=A?E~`g!ba?eimq?uy}????}S?"]_ɿ?ٿ??" <0… :|1ĉ+Z1ƍ;*,2$<<)ʕ,[D ̐4kڼ3Ν<{ 4СD=4ҥL:} 5ԩTZ5֭Jeҥر`cz=6ڵlۺ} 7ܹtڽ7޽| 8 >8Ō ;6ǔ+[9͜;{ :ѤK>:լ[~ ;ٴk۾MZdq <ċ?<̛;{w@!,@<22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇ#JH3jȱǏɓ(S`ʗ0cʄɲ%ə8sܙM@ MУHB,jTӧN6JN \ZUTvKvWĖ]˶Y KO[oݚ DAtY&ncĐX ʆ#k*I T0ڪ,M۸sͻ Nȓ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&e>㣎N*P;J 9j6iJ#zP%&d*J/Z)J+b:줔"!,! .22BCM$ KLW,,8((4CDN..:33?ablH` *\p #6PŃ+^8`ƍ;zrȑ%MrɁ X|9̒4>1@Z Qub֟;#9kڭ>7!,*  22BCM KLW,,8((4$CDN..:33?ablo @A4 BlP"E#Zǃ(|d`d ,@PK B8 1 ``-0@&@@ (`"Υ!,* #22>?I# GHS&&2))5곴++700?I# GHS&&2))5곴++700x ǎ?HI'5$PNj_*)q%H*kɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝ@I@^7_ >X8aƉ/&8ǔ#'r=Gn0`.YT` 4XP6 mpHa'(촠!,T22#>?I,-7 JKV$,,8''322>BCMABL곴_`j--9 @ 4xPC "QBR4Ɗ ?r(rdȒ 5LI KZIaK1GbxgF< JѣH*]ʴӧPJJիXjʵW @@ʞlGlվe׭DtޥnBt)˗Xb(@[1+T &X30 m@dX@ XAh"@C!,22ABL$#&&22GHS  @928@J,,8,-7@AK곴 v7%%&5?@: @1( ì{G?8**6?@J00<67{ھx'22hn/0m[\f8AC 40B >q"E#xQ"ǎ?bx- `C bʜ ܹs͛9yh*%*́Fe &jS0`@W2H,!8T=m*AN4#*P1B 7P# N4 V# <x A)8@I!,%P22FF@AK#ܙABLssGHS$sFݚۙF*ؙF FF&&2FsGGFFFژFssssGGr sFrFrrrrܳr(:LZ8GGs++7>?IrAB;Y;ۙFFܙF3A:3ۙFFGG78|00 J4'ТD-MBJիVi bxٳX][Jۖ,ۻi˷߿~ň!@6A҉# @3k+pXd@PA3] 2eB; LhA`ۜ فe  @bwqݞ;NԿ!   y HOZa@m %| bw! *TP߱  '`(&p0a^(BF#$   ~xwwxxxwwwt VPK!F1B9@<7A&yIpNlQ jV i] hdeldqUrLqCo)mbM-*9DJMI D<#s;-61111111122222222222121H0~"me zȈ0ΐBNlÙ֕ښ؝ҠǦúؖѐʆ|wwHA*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cx͛gɳϟ@ JѣH*iA>PJJիXjʵׯ`ÊKٳhӪ]˶ץpʝKH5Ʒ߿ LÈ+^̸ǐ!Lʘ _̹sA|Mix&빵װc˞ x3Ŷo?έЧ N8G Y^μ絡-}06νq2T^|̷O}7uǮ7(g=W`v(|5Ҕ~|`!8 f {\$h95;Ӎ`߄4br7Bc1x@ٝA)g7xcM` #`P:|u1%Xf)Y_@@Hcؘŕme pCe(|9*e᠁d`QV'7V磐 evYsEy_aY؝|眗u瘣Fވ~*@rZX(qB)啍*ךi&`~`*vK8;ή4DGh!ЦܼJWl9+Ǧ3甦טU4׻+Νs@:6i9/hZy/z~k(gn|[.<*( C Q-7hF '̉lM 3h=8̙m7, 7&0;M֎w-l)ŬL!7ZθM;TB0"@"n  &1lmNq_[j +ܰޭjΜk;}}+<}CAEC/|oO00g \XOSO"[E$ƫG&>0{9ỳqb sC vU BnqGC 0ǥ o!ș4; K4:hX( kAș.u3mkC:8@Mט>v|o[C=dRmOC;ְ5O" u~W*pCx_!.U6 }+=pW0lD>^q 8r{ 08Pg\/wENr!%7󍛼)y(s|"Ё,o̗ #0/}7A~?hyX^Vp.uGxhʑU|Żq`y#/ە{7yO|S=<&TzlW=sCo2>>GC[{t=i{+~{O~@8A}7Ӈs/3\_|탽??|w;|vb"tpUhzo (zxWy^p7$X*Lu +-v0 4;~>(*㠃3.xIX/h}7Bh}}EvPR؃S+hHPj,ȃI0LH=THnnz|8(ax؁(pЁȈHpµw@o|@x T0h8BLZ gx]'؅w8]؊֧ȅmS~氌(Z̈qewr(-x}8aW7@oo8H联]{` PxאpXoXQW$ X㠅! Ќ׋i-X`'rDW^ȄU8=9_x3؊+= (Pd⸍ȎSh2b8^WYp{yes)xy 9\u{wgy"Yv  P{ݨ(:~qi}h Y(Y}ș'gȘ5əX y)J隚p/؛zɛtfؙ)de W~hYfȞ؞ȏy[wXeٟz p@ j瀠D9Iz :Diz Iy Zj׹:*i&*9:Ș1h ;zY;0 MڝVzW1vzW\ox7yeJfI[ og yyxf ~p J*Zg@ Zj(F*ڍ J֨  x~jjj~JXڨ:0::jکTzںڭݪ0 {'~%Vwpj Yo\@Uɗv{ ۰; X zXj^ {\P&{(*,.02;4 ({X*@;ygEձL۴5AR;T[V{X5;wxHWJXN[fOl۶npr;t[v{xz|۷~}`be5gBi{;[{۹;+c <U{ۻ;[{țʋb˺[&[{U۽;[{۽xI;ak;GUpۿ<\| <\{4U#! #&|(,#"\-<4\ܰ6Ù02@B\čñ!FNDR,)/ J|4Wdܱ O'p@.J0ҥ޽AgHH @ЗG- \ ӛ-\EלܡNQ7!0]Lٿ3֙D}H85/}p ]-}ԍ>:<Юo-$~B"oѣt~~L*]8T>Km4DNoRN_=ArSe. P4^g.;@E]ya?MNfn~=I9S>6NTqۘ?n)]O44/PQ?7`c֮)~-WTof*-/-J=zu_kGnjԲ\S}ѣLnoʘݿ>=I3I_H8f}.IDRQ_ HUA8B >QD-^ĘQF=~RHn%MDRJ-]Sf15myң=+9RPEMBB6iTU^ŚU՜]~MpzhovIrAu_eK+^`6iⓊeC-_ֹUfΝGbzlٚgzCՙKٳsֶl sYwc\y]ҥwf\x􆶏/]%n)+w97#v9M9Qߌi/;-< ?Sм{@Ϭ8bA Y"Z/C Rq"F?ū84qFQ*Ѷ RLERrId ~q>>2K-K/3L1$L3D3M5dM7߄3N9N3sr#?/OY?5ye=ŶMXa+ T\ie9 ;n׿%KhgɍꬽVuC~loֺTNq[赕Z%@۲ַۛЗ[V:2e_{q- r͕|YcyEw63,A$:Bd'o-_3b:́d ?0YP!pQNO~ҋto/E7ZzP2q:ѯDp ]ה- @=%4d Әr^"3=N6\b>Z k,$թ CRL9tȧ)/tCAjZ#ui #JΒʰj8vW4)r;|&0WrTmMŸeu<=m@բPѓ_C{,>J0UiXj{۬N-boc[jk : `. G Ư Dm@w*5BvX47BbHo~%oS[O`vcB[u%J߲ p=3p?pRB~Gx/x%Ox5oyE.p'Gy=X/ka>sհ<.yWb\%}> GvkV#MWle G}Oz_2u7xuu%\CÜm7;1ENpuGxqu7Tr>}9Sew~w<~o|Ay}<&׿.o祗<Нz>#iyAzrݓ7{ݿy1{6v-N|~#|kO~N}oEpzlotW$@WٿDT8t @ @,$D3dL=sAkbsA d+rA!4#D$T+" @S'(˶"+,,6lB/0,5.A'3D432$ <58C537+;SϤڨZZڬMɭZکڱʰS=ϲU[d۶KJVKV=KVPη܂UKK5UܷD\l\w}ܽdʕ\xUrLSҥE]tU]u]56ڝńMe}%^5mU^dXЬEL_N$ES-va.S/,`#2ֵ3Fc\S56vcp8fH8cV;9><PA6?6{DF>`FvGn*IJKLMNOPQ&R6SFTVUfVvWXYZeI\n i_`a&b6cFdVeffvghijklmnVff_q&r6sFtVufvvwxgmy|}~z{&Vfv臆舖 1hlFV芾6FV.iff阖陦隶集fvfC8&6F.j?8v꧆ꨖ.ffC8\&뱎k@Vkjv뷆븖keA58k?&¶h8kkvljÖɦʶFliVM8lT@Ȏhjfvmh#Ə8ێS10ܾm~hC06F®kemՐ8mގnhnhS胵>0&o^dnnhZ 0azo* )_o>8xg(1nRphn>hx}) b 0w( p/q N8kV8+|hq@h.P "RrYX(n*(*-8pg7 20/.b(r`s7?os|w:syp>q$sy7O9en2PIJKLMNOPQ'R7SGTWUgV;sq7ن|0vqX+GXd/vJ*fi?a? n0nv4W?] 'b ttu/hHqq߇wsuPqn?X7GWgw'7G/y<{u/th"e_'ܢv'y rfڪ0fzwpp|wz@yx p?z>wx0PqnC'7GWgwLJȗɧʷ8hsws^o*r'WvؗrGzj!7߁È8`7/fz_{[ww;ws{{6!r{nCWgwP,h „ 2l!Ĉ'Rh"ƌ7rQ!*"Gb\rKR*P2l㖯v)=F&]J -KEF}8@Z-W姼F@$ڴU,[ܸ2csL,/ޓ~Y\^y[Z\ X6`|e'ТEGkC&ԪWn5زgӮm6ܺw7‡/n8ʗ3?ΧZ|Ur8vY 2zv~kw!uu˵o|W_?xzѥ2ʬ2G 1* .cM\P x{ɠWu 2V hx?a򱃊,^a#@13=3mtEy$I*$M:$QJ9%UZy%Yj%]z%H8&ey&fNO+rv`FnA%^OiVA_ (=\qR|袈eWzRj)i`0+ &HaM٩~:(0aDK,ąҺע^c*֙@*s)a:,J;-Z{-jz- *_D@.MEs .;/hő ɠ2䛌2r[!8 (!;0K<1[|j[/9q8?7iri93>9[~9'y9衋>:O9yn魻:˾m굓;{J {<+K?=|ϣe={=Kbd>髏k??#տ?O6?<  ] E 3"nKX0!`40zۖ2|$LaM%>^-F]rGflXĊ&X:A:u %/It+U3"ӨF n[ɇx*e$8r!^]g843#<.kr0 2IU޴IR6k#غ*ObHQkA  Zʊ-#("-Z%05/a _8kB%s>0e25CK\R .)0*IJ L a!~A &Z+SxӐ7b}sJ<E+PPAp0GyȠkZ'y|iBAPo)(HCj"=)JSK̤*})Lc@˥2)Ns*%̦:)PzB=*ReJԭoI}*TOTqXD$խr^*X*ֱf=+ZӪֵn}+\*׹ҵv+^׽~+`+H)P2},d#+R,f3r,hC+ђ=-jSղ}-lc+Ҷ5"P򶷾-p+=.r2}.t+Rֽ.vr.x+6w v w ݢ}/|+ҷ/~Kpy\B>03~0# %p-/ s0C,g3L.~1c,'ְi>1\\X92%3NF/ #?V2eGY,1foa{l`p3=~3-AЭÜԬE8C׼:in ajpӞ4C-Qm!qUծ~rO[MֵHPT+ӹ-a}*e3~6mׇ{4E v6 n_A>7ӭu>w~hӻ7}-޾-p/#'uw1q3v#w4".S83.qv8C.򑓼8o?S*h72@n, v8s2>9Ѓ.G 79ғ3$7z.>szF$( %\^9f?;u;n;.wԭ]?T6O𰣽?|.3<_CC^Fpw+ƀsr?`qճ=cgL#K/.`D:tnNng4e`s>O 1Р)ڛ)=/^k~', E_ `[303\80=3|;@>l@6"7b!b-'Vb!&^%!~"%;#<b7#7~#,by2a2#?cp`2a&` !pEa2KdI|@'Tf!p!qx'oz^'y'jg91~uD*''缡'{((%.(6 [l6}2%dK2n(v^(XoUڱ!/(ƨ((2ôֱy(]֊(ih򖷡(\/A!n)YNT5)Z.)֩)橞).Ǜ*ZǟVǠ6>*Fw-V^*f*Qv~**q****t֪***-nx*+&rY>+F>뗦~.+fntU۵r+* ܻAw빾+멪inʫ+B*+ݫvklIh;(h8 ]щ"^,Y])^xUlƦʮŁNJ,,Ξfʲ,:˲^:z,&R>-jX_&-v3TFwF-؆Wz;`z`fD-ݺWz ڮڶbW-)Ǣ- ꣵz>.F.rQx)(CQu~.,T.\.z,Ú$Z.ƮnX,/f/Kdx9jox/xP/(2TAv׺B/D ZGnw ]0GO0g0VpM\0, pJ0 + 0 Zpְp00{ 1'M?1C*X" bgo1w111߅Uaa1DZ1ױ11q_OT 2!r氎!'"/28#?2$G28$W%_2 &o2'w2h'( )2*2S2+r"w+Dz,KU!,\AX22BCM$ KLW,,8˲((4CDN..:33?abl@*\ȰÇ#JHŋ3j8qCIɓ(Sʗ0cʜIF-Aɳϟ@ѣHv4RӧPJԫXjHέ`Êu@cӪ];5alʝ,A p]LXPU(\c8, ǘ3ge)>kMpH};,I``]x „+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫸*무j뭸뮼+k&6F+Vkfv+k覫@ o;kƊoojJpXPD,q<̪;` tlj$@Ȱ"'#|0r1D͵3 !,ws22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ#JHŋ Ǐ CIK\ɲK'Qr|I͛5cɳϟuJќS]ʴ)F:JAHʵ+Q(lJK5˶-HpKӂ ;׮߿c(+Nxr0q!/xc&`FL]8XϨ@Bu,`۸sͻ Nȓ+_μУKNسkνNjOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4.@5t#9v=b#AV#D)ёH2CN&dCN69%x%CU6H*%}i%9fNmn 'RYVitƹvR9f@!,22BCM$ KLW,,8((4CDN..:33?ablH*\ȰÇHŋ368QǏ CZ(Qɓ(Av,˗;` M2gɳ'ŝ4} `PHԹ4ӚM9>j)SX[Zՙ+΁+9nJ6@G˪ɔصp6݄R龽(ɾ7 LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνˋOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($F6 - s."s5\:.c@3"'$iܑ<$qLFddIq5P@@xI@RfpnH t @9(!,Lb22$BCM>?I# GHS&&2))5곴++7󑒕00(p=h8  284` \u0 ` t`!,#22#ABL>?I BCM&&2!!-GHSDEP곴56@ ,IJU++7ɯ--9[\f@ C>hDBԈ1!Nj G$Kܸ#0c(IP͛8mSΞ8YODzfP |zp*R~-5,ֱe͎Vh.Tk["+D ` ^@ǏHBNFPAR:AC L <-aA v`B!,22#>?Iݼ$ GHS@AK&&2ABL))5?@J56@++700<ڶ[\f@D0† PD-b,h1X!A 0yb" 2C.%TS@z(jER4 JTVfx1@/P""#Va€Pjê `bް!VUT%1b Hpa#U,`2fRpP"} LDH X` 1` !,22#>?I $GHSABL&&2@AK))5++700[\f<@A,$@q ThXa)h #(00` ,iRB%H `6 @@AX 'AB0b =0j Z=PWZ@! ?EP` i ` $nxt!4$! !, h22tHߜHVttߜHtߜttHttHHHHHHttt %,Ht[HHxR>?IHW朿H[[[߿zHHttHH~|(ltt HHtttHHHmmm#H߄utHHʁGHSHtjmzt&&2T))5xKe¨tpklllctH`ttttknHk'fbzȎw-Dq̳Hyqj++7(gg~sfg:HHtt^aȅxH35j00J$ѦXjʵ֩U +ƫ^Ӫ]˶-[f[ۻx;q.]~KoU.8̀#A2A /l\联-cC2{0irڧ0+oߺW> 5{&9t /8;ͶuO}!\mPa!*$ &gFLUpAG .`~6*8cX))f myg" Ѕ8G9A{x0Byq@m'bf)AlKd6|[WL0* }M88Hl miI衁aS,@q9P&)udmmtI`ha&)dz獗lŊmci \ QƖ]{ڧɁɇ Xv{ˮv:hQ yvI f,rZdAKgZR޶zd< DuBFoA o|u-;A}u+¸NN7 Rm$#b4\$ؽQ0BF,Pkڽ%64˭%"%8}; t1άt@j=3kY{}~٬mP|sV/} Iq.`n^ն;BAl APv.SGA3# /gK¥Wi)J~1pEҿUbR6K}tЄ*pvk,GOh;sZ~)n{ ȢĵQ p-a. {oJ ӓE (&Ŋ@ġd)񘲈h8 r'rkUghB 4o*?!%5^pdnwvP! yN%x1H-m!d$I=L4fd<*zw(rj;_WhOB[D5`@Bc4)0N%Lbɘ*&({ٱ7KpB\|6٦ =c9cS1qY@)'3= *7܌ggx)KfŋTѓˉ> *KD%]~D R^虛 CJ>0 DkKBř1^Lw0r7lO蕙Ԩ6=)OeԦ:&HE`T껧Xj_&Z Xz2ƬG%ZV ƭRe\UŮ=+]׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZeV ٰK9k#6k{ms@|3/~L'nu5'<*X/mX&8#MxC6qO8뭮v\fg (OXβ.{`L2hN6pL:xγ>πMBЈNhGy}M~Ƶ+44;Mjs=uW\Yլ5q1lM`^E{|M=vf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆GRY0Z h75p~~Xp00 }x}pLzP7pq@ ؉`0 x5؉R}0X`XF*Ћlg8U h_ hFY}x5xx~0AhxوV*`riV 9 1p:Pu6H ,bI6h%Б $I((*ip@ 9&h@<ٓ>@I@DI*ɒ-)i bi0 `Z\ٕ^9 b)K6@ 0 1E>PvIUp ٗ}9  ,PhrW02\w<0<whYU `r3Q\g yЕYXa)| wN`v%xX_ s0)` 9]ye~h{`6 Y 3@ߗx)P p驞r` Pr01 ʠIp  n ~9 jXQ@Թ[5W9`P~9Y[P :z=*Y` 緣Ȥ>!,o22V,% tttߜH[tߜHHߜttxR>?IHtttHttHHWtzHHH(~|ʁlHt H#tttGHSmjuztHk&&2HxK))5ettHHkc`kn)bTЎwTg۳̊qj++7gHHp(~stHHrUQ|~Z[.ݪߜt?@J00Y I@( #o9#RRiL\YQtf\djb)99c a9t$eA{I7 |0 ?Z6(PZ0#LczjjB@ 3ڊ+*,Dk֘Sf( .;Ψd+I覫+k,l'@$f= @ (`R\wq\f L/ в*8BJl$=PJ.MADh4A*&4Tu%N\c IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ49'-Z\!8yH:yԠgH'Trfꄂ@VPhm0jeiJUf|BЪ55xPj@28d'KFvȬfײ&@`H PKU[6PSFlgK2ȭnP VTo%>Wj%&G1ktKZإ.vmUu߾ xCr5ܾ|Kw~ J- А 55:%YpV'8I4CAdqBթ V  7bp(7$B\ bi_]qRt*A_BJ :B3PrWqbNt /DU%EHXrySsbMl eؠ0@kJFgAu# jeχA,4ڧY)BA  9!A0=3!uW0@^J% M: !,o22V%, ߜtt[ttHHtHt>?IߜHxRHHttWztttHl( #~|ʁtHttGHStmHHHuztHHtߜtk&&2TxK))5eHtHHpjHtkctHH`_tkFn)ЎwbTg^̊q++7g~sjtee8rUxQ|~ݪ?@J00FyD 'D]˶[edJT˷/֏2Z<+^\jP1:ȸˋQZ,gaDbM֛M 5װc˞M۸sͻ Nȓ+_μУKNسkνO)8 |`z@>}´>@0!`X X .8@-!``LLПhqYyx`#.Xƨ ,\6#>h$F4Z@l`=U .Q%E4A~@ V]ZafuI&x#S~Xr2@'|"&[L`)):f'$7u'R覜v駠*ꨤjꩨꪬ*무j뭸뮼Ղ_ ^ !#fȆ X״2wmurGuΖ-Q^;[/ދvV^0M0G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2h\6&D 0 :ЁS]ǂ1 )`"8tTEZ2B$79H 'G)J\#I/ tT DMΒtb@ZB2y].20xcT2pg W6+Ք2)AҠH:I fVI%!LO|a 'p@ h iSng>#A8 юzF:*84"(@ OPA48)NP%RA(8HNJժZ}P@uEUi$5qpKp\*WH?IxRtttHHtttο z#(~|lGHSWHHHuʁzHt؛)k&&2))5xKeHHmkctHtt[ttknFbT|wrȇ̳bq֣j++7zpg~s~jtn3x{2H?@J00@D4L?-z4-Eʵׯ`u`>uH٫Kݻx#M+WVX eÈ+^*պ˺۶k V.<ɳk~.aŃq ˟OϿ(h& 6F(Vhfv ($h(b,H@ *0`c]-xc;hdW0@4T2ဎu%dOF9eWy=  0W @wl2&dSkp :g4  } jJJi2L2B G4fu:jiAZ(]iP| '_@%pX+-Cb0Xպں:k覫+k,Ln$)9pA 7lZ2&A Vqe IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4똄$ A XЃ)/ 8@L':y0O']j@u3[pe h:~4`@*} Ѐn(D2.thDsz4p a$5S3X?a 0J #xQﲃ>`M#tQF 7 q04 ph*xyفB 8 k(ЇoS FL0H𯪊2cs@!,h22V%, t:ߛoH$__ttHttߜHt[$߿ttHHNߜH>?IHHHHxR:Htt:HHHttH z#o~|(ltGHSW$uʁz:kؿ)&&2))5xKemttkt_ctttH[tknF$bT$w|rtȇ̳bq֣++7zjpgN~j~st$nH3x{2ߜt?@J00AOl{'zi y>P'} 6~5`FEf=&! zhh]veC|݅"p-G!-x@"G8@ℤFK{=)eiQ @UQ vcG\eXokqlXijCefVg&'~>fsU(i1U),iz_?49$y'Υxf3)l;@LдQ%@ IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgK[q මi`+ i t8lLZx aͼx`$tM2;^x^ۍy@cַkс~bqBs|^ FpX`ZhPaZj!NX"t01)[/$,8ŏ\"<αnBbB Xp)Hfsk # RK \ 9~X #d{ѐMBЈNKя悛  QFB`< qcKԨNWVհ65&Z@APiKHPD" !H@ЎMj[ζ݉!x{{mF m@Á/k;η~7*Aܺ&FPcB 0eϸ7>Q@Z 5RegNq];6\L#Ap <sW.څn><{x |^e@!{8W 8D 6s8N`\Nw]ħ;z@`^?x` ]  A#$~:|`Nx !f uPdH@!(,h22ߜHtߜVHHߜHHtt%t, [HttxRHHH>?ItHHHtzt~|(W ttt#HttHʁlGHSmHuztHHt؜)k&&2))5xKeHHjktctt[FtktbT|w݉rȇ۳̊q++7l~sgjɼ<=GHHtt3x{2?@J00/=?3sX/ ɛIE4 x<-_Q8Qy{K[^.8pSa\@Px[` 07 ^8( 1~X&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pK\1 M.B' r&%H xxj@R ~"=|I|ۃw~[׾_ /G]uF|]'f/Q '70{Aaw!wQ\b *[xGvlA ߵ1)ށ|J`R %;G3j~(P \3 i̅y%Eifex s 0SMqhl&P8ѐAJ[Z yw 0  ,p#ff&(VVՋ f=k=| ŀkغP,0f;ِЁ[ ؁B5j- ؀((qHnusF` QR+iLX Tpo|!a1qr} V!"!bWDrVۓ y8P 3l`D谂``Jayh:Xwɀб_7oBN pT*ߵ17{A sG)zx >T A/!B'2!!,h22t:ߛo__H$tHttH$[:ߜHߜtHtt>?ItxRHttHNt:HHHHHotHtHt z#H~|(lGHSWuʁz؛)k&&2$xK))5e$ttHmHߜtkÜH:c[tknFbTw|Nۛtrȇ̳bq֣++7jzpgN~j~sɼn3x{2?@J00\{?-ő (wްb h{`|?_~}˟/qI{ƾ% gWz 1x |E(cVaHHF ؠG(:g_Gg^s7ق h$~hb<׊X"(m\zyH6$>F)X@nToJ/ !ۗaZ@og &kpUUe HI \FfZYZZ(h;Gљ*OWB?7 2)TyQq}/D{DtSO~f{e1K!74|lwyּ@@_W&3 ;X@ A}0#ܠ W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hG(' A18 b !\ lg@ȭns+`AypW`Ap+*%@=.A[]tn vWՁx[tnכ[ ?@dmn?e_Dg $5 [ZAN`~FXGFRxG8@*ظP8f<L 4[A> @m$n71[.9e0hвY Xh2l#aIxs^;%BAЀ56AIPD" XҘ46w+ NMEpD67" m` >@Z2ק'2VB)baՊnuFHЎ]-03Y! S"@ `|`7N|I]^:yUoh; 8;7'-%0@ě%|ʅwXN "N!`4ALs |@ [(Hus C\;HV 5^ TaR(l C R@&]z !,o22HߜHttttHtH$ߛotߜ( >?I#t:GHS_tHHHNHtk؛)&&2))5txR$jHttot:ktHtH:_[WtF$$|z݉rȇ۳Hm++7NlԜHHHHɼ2tt<=GH:3x{00bKٳVDiraŢKݻ݊ӏ%xKTRXƈ#KLfAnϠCB&_\ͺװc˞M۸sͻ Nȓ+_μУKNسkνOX 8CZݣ/?>G߀v% ,`e  Ղ%xՅnaVh"V1U)b'8U~`PH:裍D~8aUG耒 )eQ* A @YU^SGw_9f@b)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL X62  @4< H6!&`!>B0m8aD0By Nd4 1l`C,D]@@C<`^"B fB@ ZԀEq h BŁ(lw#q o@Z-}MXBB`FBB!h@ V1J l hS: p`@BdA:5(ƒC@B u L m86n &@< #g 30aM\BJaD ^  =@!|AB6ІN &*P n $J@AfP3\6B  a@!,o22tߛo[tߜߜHHttH$HHHtt_>?Io t#tt:(ltHttGHSW$uz:HNk؛)t$&&2xK))5eHxRHHmHHH㫫HkctH[tknF$bwT$z|ۛtrȇb̳q$֣圷++7zjpgN~j~st$ؿ:n2H3x{:?@J00<ʁ߿R~|$nzz_[\fbc6l5麺DH*\ȰÇ#JHŋh@ }@ I\ɲ˗0cʜI7D @IB熚H*]ʴӧ (Ѡ5xׯ`ÊK3"$rpD dW)ʝKݧ=5Jȴq Laۖbu>LJTϠ3hf Oаccǁ ! Nȓ+_μУKNسkνOӫ_Ͼ˟O_g h@ ڕ (edUNaa.#4t`j4X!Aҕ>zdY +6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH,.xCBP +(A9\ x9@!6"LpELr!xbDDʕ)#NdA qC?IߛoH$t:HttxR(lGHSW)V#ouH:HN$knzf&&2t))5xKe$ttH%ttHmt,Hk:Hzʁ~||tc_tǔ5yzcF $VW*bwIᯯT׳|56@פHHHqp++7gHHNj~sHH\HttvSy J00; ЊV !C!Trw (rTЈ`@]0 e DdJŢ((|@R6 !,h22ߜHtߜttHHVtߜHtHtt[tH%, 빹HxR>?IttzHHt Hl(ʁ~|WGHSHt)t#Hunkf&&2))5xKetmHtk|tHzcttǔ5yzcFVW*ߜbIHTwᯯ׳|56@qפH++7~sgpj\HyHttvSJ?@J00<ۇڽ`[\fl|}9:DH*\ȰÇ#JHE2jȱǏ Cj ɓ'/\ɲ˗0cʜ͛!Iɳ#͟@ J̞HQLTѧPJJbӫb곪ׯ`ÊȕֲeǪ]˶TX붮ݻx+m*w/Ӽ W d<8c(Xq Qs-μ猃S^p922p[%|`6o+$@⽏pԬK> 5b}c_۵;H`|g @۫go:[.[F6IGA}ɗ AHUhgq܀q!hgڇ0߉y! Ѩ@."hHe]x1&N%7_\*b` kQ+t!yt#s$qstbT=bWR1ء%~YF)z禜Nk~R꒨7H*F+OjBj]민M{ ,6kYA[Vkfv+k覫KG<@[{oaD[/NЛ@k:U>:箟.t-\u7:Uھ`.:E<Ѐx;A-\@Wڋνؗo觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪV.x`'< ] )1@׺ҕ50W`o]AkWn5A[Wm`'KYB:;FYᴘCH+[\V,nm 䖲-d7Zזue{0 !` c{` Fwۃ5`X'@ `P$!zD ޝo}7Ȗb0`:o6(q`׻>{@G܁u A)/r wc3?= "2cȸa ?XX$e bD.xQ!$" 1z(E@:?f"y>@ " d |#IFO` "&R?{j @':l ?IxRHߜHtHttHttH z#(~|GHSWHHulʁz؛)k&&2))5xKemk[tknFbwT|rȇb̳֣qHHH圷++7zjHHpg~j~sɼn3x{2?@J00 IBL"F:򑐌$'IJZ̤&7Nz(GIJ Le*P A \&PD ` ^0\R 0K* LfNT3Yene2 M`R '*aprTgpwӖSgr{T ρ4- =zl0 @ъB S8χ.S(HCP FF, XL%,a p| ġX'{>]L"t!(Mg "r&ȓ@?XX*!DU>8Mjtp` DǾDUUp[ aصp@ Gtlx(C&:؁dwկcC9UOzwҚZ1Xvݫ@|v]j,@ @6 ю6~/w&5 (Q]!X$:/X"tW `+פ!t0ExؐFh mP0h0X6fDaWʁH%p0S ? "v*L@I"8&DB !,o22Vttt[%, ߜHߜHtHt>?IߜHtHtWߜHHxRttHHttHHt zt#t(lGHSpHmuʁ~|ztk&&2xK))5eHHxkctttH`_ktFn)bT$wTg۳̊q++7jf~sgHHjfg:nrUQ|~ݪ?@J00$ W~]Ͽ(h& 6F(Vhfv ($h(,0(4"4@>@"0; Yݘc>56a$p01P%XxRRie[v@TJ9^blhiߜlf@A~ҙ@(yv$hq5: ϵ04P(b@A9 J':*DLi  Z5RkmiNy IrIÐV-צ+k,l' 7 БI # IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZSȦ6mzӛiB rx 9A|vjs 2@z7@@䰟4@ZO#TC'*ߔ@хrA37o .!6T@X ULiNi HR%CUi@]:%X`ύFU@լ&Y(V@VH=U&`Z&3sWL:u\@YXk5A JDb=>നMjQzp@f;[n X [FHeY %@݃"?Ȗf3D! Ce x^H8sx.m4a [B c%^6[5hdh2P.e<*/!W,k ),R @!,o22V%, Ht[ߜtttߜHߜHttH>?ItHHxRtHHHHWtHHtzttl(濿 #~|ʁGHSHmHuHztt؜k&&2TxK))5eHHjpkctH`_tkFn)ЎwbTg^̊q++7g~sjtee8rUxQ|~ݪ?@J00<߿h ]sv꡿ƀ[\fH*\ȰÇ#JHŋ@ @y0@ G7vH $#@@ƛ8sɳϟ@ jpC4 D`C-GzlhҖ`@@M`ÊKٳh!r惚6 M3b 6nڿ Lι-ch Fnx!^_ k̹:mL%VEP9&̠c˞M6ZSdIԇx:j_ȓ+_μځm;H9rwפ-ZOXzO}$gpq{!}& 6F(Vhfv ($h(,0(4h8<@)DiH7 P@ 4@0L֒4$Q0%U&)X2IA4PN~Yefyfkxnx@e$Z{矁t Dy=餕2iw.YK'J~*wJNZ 砲:꫼2Mf9د~ I)l<Uڀi-ނ覫+k,l' 7찘!@)fs9djmf D "P\!짦 i!S`nrf3ܰXfI n&5ջBݰ1xdmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v a t:~ ;@ЂCPw 0D H @0юPhFTmHGѓv eJ1 t2)CPSvTNztEPՠMURYV,UTHZՊbjY 2HzW24p&VpTu"axIj'xhz N@Z^xMAr0 ZXu1@jDavpˇHPjp ^XЧHf=\vzx"W^5`"պ``[+`f>T~WB`7/h"2QYbflh'?IHHHtHW漽οttHtzHHHHH(~|l t#uʁttGHSHtHjmztHt&&2T))5xKeHHHpHkctH`g\tknkɃb⯎wz곴H̊qy++7j(gm~s=ɾHfg:xHtt8?@J000ޭ^~ܜꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩN#P:(?~`COWЃ X zYJU-AVNJU(_Bֶ`LPVOW uP*c5` ( J,V1[Y,@Z O*KdU >xBfK[Xk*֬J pˀ2H}-E)e{U#X`/q-`h{ۚ.\GTLza*i5]hm; UI N0!h`^PJX Qϡmp@uIn(N0+܄ TB'egsRt%ف"GD#!1%74n cג 3{'l!Hi_ !JA67ku-4"XtqLW-k^J%` , ,,%{4@%ZzUzPBؕlm˴"8Ї9 Nc0Aj"(M2=V{WB.D%-@[ @="IH`^ &­YpXwB`HB&0!!,o22Vttߜ%, ߜHHHH[ttߜxR>?IHHtWzt~|tttHH(ʁtHl tt#ttGHSHtHHmuzT&&2H))5xKetjHHtktc`jkg\tnkɃb⯛zw{̳Hqyi(++7jYpgm~s=Hƙ'HHtt8?@J00)b f韓2pvz%Y&Fj*IТOQ襐Ji{":E IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:4%@9r< g8 2@L':e`Q@u3Z h:~MCsTh@N:6@D^TJF7jO|S B{)XNL8it1 @hN HMjRqt1@ҹ/(Xͪp` TFjATG `5iЪ* \k4@JWM U4>ಘͬf3+xy@F,vEA QxldQ #@% vAHP2 :Zd$Ѝt+Gn~ۀw @pƬb/ z+ 0 p .R0:*A@iaC~\xX |`/(hZN$a [R L'M u0\,⠖T$+a@MA rCDe.x=+y_2<wI$ă&dg6A(YD "bD`3 Mj"< 0&ቆn0H@ . !,o"22VtH[%, tttߜߜxR߿t>?IHHߜHHtWHtzttttʁ~|HtHlttH #Hu(GHSHmz`&&2T))5xKeHttH(jHHHktHcttWj}tkntbw\ꓔ!۳̊qipjg++7~sHHgYfg:~\vSxrU_00hA`NvK6dGfYb [\ %bje0@Vm'As'eB&p;Ig ( {FJa @~XQj)hʩ:XXh[?*k\<\c9j뛽j\b@C?2rE: fv+k覫+k,Jb[: IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:vAG%hEtQ=h`C$GȠErEx^"঍Qӈ.ಘͬfz °L&[֋lgK[5ම! D8G>4uQЍt;Xmo `-W+`"Z+AZb1|]nQ2׹ *kY`g; Zpo8)($GFMb` Z Q`oB FtMxCObB8A?I#V%, GHS&&2))5O۶ɳ++7 ~ٺ00QFؚDQPA †ma0$b` bCT\ 7G6tC!>,? 22;@A D B ~ @Jw@ @4}h$(B-u  JҒ(MJWҖx@:u^LiSԜRgPySs @"pz xKMz|Kͯ~Le|^3ؼ v [ΰ7{ GL(NW0gL8αwf +ka!6r `D@NL*[Xβ.{`L2hN6pL:xγ|tR3( zЗ)F;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZ:ȵwkH׺5hNf;ЎMj[ζn{MrNvwBzη~NO;'N[ϸ7{" GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙٝ9Yy虞깞ٞ9Yyٟ:Zz ڠ:Zzڡ ":$Z&z(*,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`b:dZfzhjlڦnpr:tZvzxz|ڧ~:Zzڨ:Zzک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰8K`[{۱ ";$[&{(*,KRB 44[6{8,i@B;D&h ӱL۴NPkW0-{XZ\۵^`!Made with ScreenToGif;asammdf-8.5.1/doc/images/open_files.gif000066400000000000000000017607021502633300400177720ustar00rootroot00000000000000GIF89a"$A-V4`0[9UES9VUL_Y[eadggiiijkkkkkkkooooooooooooooopoo}oaoTlFj:l?}Pc~phc_djuܚڕݛ! NETSCAPE2.0! ,"H*\ȰÇ#JHŋ3jȱǏ CIɓ\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧ<BJիXjʵׯ`B*ٳhӪ]˶۷iKݻx{W.߿ L~+^̸ǐ&^˘_D̹Ϡ+p3iˡS^ͺ멓UV0*ͻ߭c#|m+_<9У3:~ƍ7rA^F gh=T2*Y|_  7SzP13(|(XUh[aJ]WJv.1| g7^{R6A,-B|T0XS=JLb(TaKW&"2[-Є64 ( N`ÓWXdJ"s|.QJdyLSPg6NY)Rv%,ug"쐂2 2hvs{*6'{) j}Y@>WHpkj-*J#޲к:}"8,"QQhɐ2|" X|ߏ 'X5 &, |H+U\Ϻ028Z{L;i1n5< oEN½B )4 1 ) ] x ɶwn]S/y̬+. ){K c+:x.pg6Sڋ4Q][ *tJtt ~`6e?y'[^ߝ,9qnzn˞~ْog37%B @u-X6 /1<ދ|q#xqLI" {+lc ^sG&yrJWA K`>x79᚟2EU&$!+UX ,qЃ,$Aq@3Ig) ^^&q#HŠ4щ9\U.zLlĝ A`L(5p,^H:QJsG,@}  L"bE:򑐤K##IJZ+&7I (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f2"p4IjZ̦6[mztfpL:NTvg; ŗ>8 (3Yr MBz 5 4@U(7ҢpJй(HmR04/(A К8ݧ??Z2(|R%I`TPB-U9S` X)*OPr@hiS[>jS{jո2~i`e{MbkYV hCҿY@ ";YR,eY ѶA XxiAdVW+_E@%*oq[MִJ :]B@n*-#0. ^^ mm Uh}-0*U+hunj ̅3~.j ;* n+%k>ahWi7 ֱN][v.CL"Y%`KcWZ4)/Zcxʕ{ٺ3G9Uce0g\I|:L{i+7 vϮd*2DY*ޭ}ըVsgG]rYbԨN0fN".ZUmX󴵟5Qb H,kL63y.[ wCUvnZ54q.%/餧E dA]o0$@H@N Kh7NV7A + 8Ϲw@ЇNHOҗs "`ԧN[XϺַ{`9I@hOpNxϻOO;񐏼'O[ϼ7{GOқOWֻ;OϽwOþ ;ЏO;ʷ{OgO>O8x H|؀8XG|؁ 8$X&x'(,؂.h{084X6*x:<؃뗃>B8Dh|$p~EL؄Nz$ITXVxS\؅^Z_8dX-fjlprXvxGx|؇ڧ~8xP(byXxxhXf8hC؊8XQxG$PxmH، 88Hؘg؍8xX}明؎˷{8xǧz؏Yyx  9y"!9&ٌ%y*).-2196i5y:9>i=BA9FyEyJINyMR Q9VUyZY^y]ba9fIeyjكinimrq9vuyz9y~Ɂ}99ɀyy 9yI~ ~9}y9}y}9|y{~9ƹzyizɹzy9yyy)yٹމ |9Y9虞Ϲ친9Yyٟ99z : ڠ:Y:":$Zy(*w٢.:0o946zg::<ڣ_@B:WYF:HOLNGR:TZ?yXZ7٥^:`/9dfz'j:lڦpr:Yv:x|~ZZ*بJ :z9*کʑ:): Y*JZI*(y*8ʒziʺڬ0*:XJҚܪ8*Zxʓ亮z@ٮ*zJگjɯ;H+ ˔Z[P+rرKJ $&{X9*+)۲d0˕,;:)6˅8`Y<+;TBK>[*IH GnڴNPt:T{V{zZۧ\۵`;b;Zfј>lkhr t[.xx˂zx~kh {:۸R[;X[^d{[j{}غۀϘˌ{;ۻz+;ƫ̫k[)+׻y 㪽䛍{!8 ۾~;Ǿ{ܷ[,}  |  h \@4DL+|įJzL9P̊R;8 5,2L/l,)&# ,Ll  ,Lk +Kk +Kk̋ɫ ҽ+ҺKҷkҴұҮҫҨ ӥ+ӢKӟkӜәӖӓӐ ԍ+ԊKԇkԄԁ~{x u+rKoklifc` ]+ZKWkTQNKH E+BK?k<9630 -+*K'k$! +Kk  *Jj *Jj܊٪ *JjĊܾܻܸ ݵ*ݲJݯjݬݩݦݣݠ ޝ*ޚJޗjޔޑގދވ ߅*߂Jj|yvsp m*jJgjda^[X U*RJOjLIFC@ =*:J7j41.+( %*"Jj * Jj )Ii )Iiډɒ\jnol|9tqΨv~(|yޞ{i9N^萎^y阮nn~^MJNΟ^딹~~9>n.Ȟ{΃>yؾҾp;~~>>WZN} _\/,?XO-"o$_~(! .?{0o52?wš:>NB*_IHz<JP?R?f\VXl|\o[rb_^_Hhj~|npܮtOmzsv?+߿|MOOoOߡ߭_?/ooo֨x?_ȟʿ΅ПxĨ_؟ڿ?_?_OQA@ DPB >QD-^ĘQF=~H%MD-]b@!, {&22ABL$ JKV,,8((4BCM곴..:33?`akH*\ȰC?I# JKVر,,8((4BCM,-7곴..: 33? #`ak89CE@*\Ȑ!JHq"+jX"ƈC,ȓKDR"0ad )ČiACM .$f~r 4BEx@TcS F@īXj*aׯ`Ԫ怷oJL T 2@.Eu-A~;MpS$P (W\B^H4FpXZ-{ƫVp !,*(22𫫫ABL$>?I# JKVر,,8((4BCM,-7곴L..:   33? #`ak89CQ@*$x"#"!`D+ @!G!$ɇ) dy˘2gnG1u$X§ *2PӦ-jZT ,ٳ~0ٳpP+Gx{VmP_^.6B}pA8!4`,?I ABLJKVر,,8((4BCM,-7 $@..: ` 33?89C`ak5< x`$2hh@R``F;z%,¤ +,L(H6@A @CM*`R p ="x ƒ h@DV .H |KA)64!(,)22𫫫#>?IABL$ JKVر,,8((4BCM66`,-7곴..: 33?·689C`ak`H f00Xbā@xÄ d'/$%J+Ytҡ77Y N:)0 : (]ʔ 8EիX ' KV@]qRHPm8L@۲p,`A@%vo(D|01L< pli<PB"#$tȂ!,&) 22ABL$#>?I JKVثر,,8((4BCM,-7곴..: 33?89C`ak@A4PB|1D 8/z#9:l tPa (@` >00(R2iPE耯_.P k i`!(`TB(}@`Ht !,',22ABL$>?I# JKVر,,8((4BCM,-7곴j..: 33? 89C`ak @A$6<(p‚ ,xHÇ Hh'.\ȂbʌyPɛ%0,gOn޼`H< &z Ӧ@@@*X3@:+֛U Ip5x (@0J"oղVpA\FFZHE<03e!$@0 !,'G22xםՕpG`ݗimpGpxpGpGpGpnݗGljBCMGGpfx׶GGڸ C$ _۾GGGk:xf:ɡxޕ떖  ꏐp۾ֱppGꗗpo:x8rrݗ,,8'(2ospGG_q򳴼 CDN..:LɅ#2YKLW "$7O33?,=Q0ҏGp 4GGablvwzRHXȰÇ#JHŋ3j@Ǐ CIR@(S\ɲƎ%cyҥ͛8s9g̚: J!OHC-ʴӌA<˜@|$C:8ܐނ). (9r7s<:@gA@`B*"W@OgIWTG]Fl ]jbGg;rp~2 5, T؇w~-n-wlbÚ\Op $p9룯^qI޳^s&* gS @5Z& 7Iw 68Y/o_WCݺʦɱv7(:`*4}Vi \PGHBVpPy#WX"L{ gHC28s@4 "ZFL&Nb(*JVbEp1a(Ahh!(p%:r/5 Wө-N;eG/afcs&?J6mT< e&i?KB͔d%yF4Qu{"p[K^=UPSC%I6BD'M" %6u@˘BUwr~2-DgJQ,Om?ݨH$R n,gEjf=ijIxxT<šo^G"2&hMZ3p:`yk!K5ePӍ|5lԠX+G:hzģ&ՍK#$K- ,T,+8֐UR8N2vm#cK;BM pKMr ׅ p0, ͮvz xKEN+@ 88Kͯ~<` lp3'L [ΰ7{ֶ` 9 W0gL8αw,,b!0 NP"HN&;PL*[yA@@!,'+:22xAҫf:x䏐^ېff:c_:fd[:Ef Cafx۾_! :`&ffٶې:::f::Z::x`$K :BCMff:.f۾%{第됶1U::XxYZ !/]l\Y F$܊Y:h!!C DH_ꐐf}::򳴼y/CMie2:ff::a./E3w~1$7I!_f%ہH *\ȰÇ#JHŋǏ CI0$S\ɲeÓ&]ʜI&D1m3%Μ= 'PHMiSP~@իXjʵׯ`ÊKV]˶۷pʝK]˷߿;0-#+^̸] 4M0<2)M1dagt:t۸s`Hd>ØC^\76JEO@n 1FP~7/P# $OQBlQ!2{k- 01(߄ PD 3ؐIe€ FaFOXZ"7PtD@Ir?ndS GgDAl phԍj}XP!`%AFB+ 9,qSPSJyFz&%bDQfthL' Pp~2RJ{"{jIY?5ZP¤^)z"Shyj&8:r\ *`u`OA>úX1L0f"Tr wU.Yn ġE]_TApE]/~Qq(l !C,֕ ͻl,Lt@w iM8ҢEM@ TϧstT5`%dmhsRJt{7l׭f|.@~]@Rp 4-.:ޒ!!PAO@ $04n:FlAB+>P lā7?FlgA`#[!@!&w3􆇃 ?I..: 666`33?```ak89C``6`HP*\Ȱ!‚#JHŋ3jQÏ vIɓ(M\2˗0cʄȲǙ8sѦυ< r`MEJ*MvDpS74Sfӭ ʝ,B,pp#@8PVa@fH%[@m ) հथQ- \>(8m+\d}9gGI/oC`+t}?OߪOS#6g`I# Dx@@-HTfv! b CD,0(4h8#1@" 4DiH&L6PF)TVd?)$AVv`)Mbe\lffeoixV+Ig*h>fI"h袌YdVj)Bjv)R@驨Y(@@ " ꬴ# @ !ZZlpg6ˤl@ P@fmm=`BC @ .jQnv:o6zo oo9pyp {pOp;9q'yqq r"q&7r r.p2Ksތs:o> tMFmJ7t> MMpVun5^s@!,*22ABL$#>?I JKV ,,8((4BCM곴j..: n33?`ak#6I\@!A xp (x@F8vHQdG&/p 'T"Vpxsf)HZ'Hx*S7&p U  @T p 4v)B { !2EȷU0b N8 !,G22xҫ^`f:ېxf:f:ff::{ffBCMch𴴴z:$ _ Cd_::::f  ff: ۾ޛ:::p:fxׇz琐,,8ې:jcf{琶etKLWvq_~ljxea85N F"%3'(2_ꦹpr CDNL..:6Md/E33?/T !/CKǶvwzH*\ȰÇ#JHŋ  ȱǏ`Iɓ'5\R$ʗ0cʤ͐3siM.y J4#(P* ZU5Juկ`Ifk˰hFu֮.:0ڻx&UmԮK8,ۣU @"ŏz3n')=me X/}t7Ar"q&Oݼѥܺ;f FRpJ_(=_I*(h&` ؃°B fv (4ء54 #0b @Ž;@! 9!40 !PF"  aZQI As|)dɘ)!XX}$ g)]F&v:i|( -Bn!$\MXaTjAf*zh MJfhֺAB bȇ"%0{l@! *5z O|୷+ .۬70@gl;aT{ rƆUQr)EXd0oC(Zr9,cJ +;Ho.7w3/a68q*enȚX9q!@FD'_RO `.Ҝ=T5rRyܑ $c`Q'|bԀW"CzB"Rn<9%P1Wۮ;.o>J5Zry | 'I Rz:;=ɤլ|İmOC ː(Jli[5.+]j׻&/z5^+ŷdlfH@慷/zXF0=0,cƺ@] YNY`WbaDlC(3!Poh -!Q.vtWlAi/hC+ 45͂f縗:N쎉d2j6l~ٮ(6fi]TD)]mĐ5Q2o؛E"pfbr+x+=.rƤ90 4y;Wf(u 7nI{Dө]⳴ ~!-_4 !9=HZSa!:xJZ3zM+V]&H!z_7f!HP`*\ȰÇ#JHQA3jȱdž |IɍR<ɲK*UIØ2m9gN@zSѣ(]ӠJJիXjʵׯ`KٳhӪ]˶بnʝKݘp.8p߿w]/È@]˘ V#@5Rl8l7dA2kP8rh*- T%q[Q K,Dq ;@ ͆*dp0a/bI{bRN )'(DÀ 7o%ODYN7TDs[0DHXЀ8($uQV 46@ Ab¹e}1EFeh@sFB`PZ([ h؛DfJXN喌Mu T@ @ ۠nnqLx@if[xytJ^މ]v&iJE's"7 l4^v\9h*ݚvj7fFQjkTT~FCuJvr= ^`ݒku(ܣ>>A2,MyXh |ܤ~jnD Ql>eg] n\zACs⾤,B $Â\69prKqf nZ1\0g&S]ߛknz^m*$NyNC7aJ#`=.nzr-t]ӑZ\t!߷H6~nKۼ14 ~o˿HGLX2c+ ZT*zu GHE&L Wx0!Q\8̡s(4THDHd`P&0P*@Xb++:Q` c̨xCPhxp$EEВ3q#y4`6YbF4z J"UH4R ]C=ВDc0H3R̉TH%|dR9@|M KXFCK21q>A+)K[%o3_BKd:ҚKbz8Ѐ?PT o*rhԀJw61#1W @E!$g=p3͌=Yб&c?7PP%s )'ْJ(h{p<=D3eiǕⱥ7i(J)˖BSǝ),eW4>I UԕXGFo=<(D4}LJJ4DU+9*Jh`=j^Wr(> HyaشUcͬʊV8էAN%jczڼ'3kcԈf] Ql2Dd8ʲլrOoT)H̤ΔN>s<6ۥm^[6|*b mIF;X oښ{V`ma2o@&c޽J5M(_]`QVEEBކ$Fx~WπL%HF;ѐ'MJ[Ҙvt7 C$ӠGMRSӨVUbVհ6ugU ָεwM^[FMbȮic;nt&6kgn5]o(Mvff5M0tv3cnQƷs[ߡ7= A;ǎ3LW7NrÜ .)-p\%` ϻ%,gwh/ yKT,Ht%f8:_ӥCTb[` RzȭNv`]:u)@T/rf?w|7K} B;, $X@ H`|yD^`",^cyRF,p1>=TZj"r=uO|nx J9~i[(ҧ} %_ON6a(oN th'Wxǀ(G hvǁ!(G%)g-~1ȂGg'9pǃ'Gh֧'Ȅ3(GOE Uȅ`8Nbdxahlp8!txax|ᇀ8!xayሐ8t!xmahaበ8\!x-$gaLኰ8G!xBa=883!x.aȸ>88Xָؘ8⸊Xx8긎؎88x؏99Xw 9oYgx9Zؑ B8$i&y**,ْ0Y296 5<~>=BDYxHJؔNYP8TVyZ\ٕ`yb9 Yfِhl9nrtYyxz"ٗ~Y(9y.٘4y镕IAy2Yrٙq9WoInImYvk֛j6Yhynfٜ`Љe9VVd@Yc+_YuY깞b՞R4yKyFٟZE:QTDG C2 CZ,tB&ԡJB  4$A&z*zA,ڢ0 A2:J$6:m5 B?DZdH*J٤NP9TVzљZJ\ڥ`b:Yf h㹦ljnrʞtZyx*z٧~9ꟆzJڨ: Z jʡZz*%ڪ+:ꢶz1Jګ7 vZq ʺCڬjIJXjav*ںy8>1ڇz̕Z:ڮ :QZ욯/z{*[qۈPذ["{v[۱ ";&[%',++21[bq8 :^ѳ>[4u8D;@{XJkL۴TP R;NQVFʵ1`[[;XfbCln?rۋh[{x;{;Bt۷;5Q[[kA;-Qȹ +Kk˺뺃 +}K{kxur˻ol i+fKck`^\˼YV S+PKMkJGD˽A> ;+8K5k2/,˾)& #+ Kk˿ +Kk *Jj *JjԊѪ *Jjýú÷ôñ Į*īJĨjĥĢğĜę Ŗ*œJŐjōŊŇńŁ ~*{Jxjuroli f*cJ`j]ZWTQ N*KJHjEB?<9 6*3J0j-*'$! *Jj *Jj )Ii )Ii͉ʩ ξ)λIθiεβίάΩ Ϧ)ϣIϠiϝϚϗϕϓ А)ЍIЊiЇЄЁ~{ x)uIriolifc `)]IZiWTQNK H)EIBi?<963 0)-I*i'$! )Ii  )Hh(Hh߈ܨ(HhˈȨ踞K='k X٘ݲm@͋3Tڸxڪ<;۴}Bڴ۾]N{ʽT}ZK#:9֝=ڽd ަݬH=C޹ 捊m_]v03ߤIz Δ.Ή . .n^41ᔨUXQ"h[I{*(/n-e,>,Y68;N"=AN?.d:C·I~E>KOMGnQNWޖSU>Y_[aΆe>cngkni]mNsoNuyΗwކq{N}N⃎.΃^nnN΀8^~븞뺾>^~ȞʾЮDB~؞!,";ݎދ~gXbiy콈œҠҧױtb]i{텺ꏿƙgΔJO|lnlim|xmbD<80{zuaRR&Xi4wNQSifvy|stznl|hgtlkonnnkkko]\>'< @0 u fc/e?VH4R B # H96j)Fڙ#BQ Ώ5'VaZڜQ G E4iˉ)PQ#M?b"┞#rt Sfőm'ƚcr&G+i菞'fHWPӪ]˶۷pʝKݻx˷߿kBLp&>ShN3hji[ 4ذIcZMb5ףbҌ]G cެ3RMG>=aՄP4y;8Z%k";wǣ% ,kVeLӫ_Ͼ >Sr($HHPF)TViXf\v`)dihY%4QfD qι4Ӥuh8_ԠeH`9a4pzc(,YiEVؒEQz衑.)Gb vj V H駴VѨTlXa1**J&6F+Vkfv* kh(ф)F+M%8( J䛯 SQSUsUa/pE b0: GЃvkd 1C,,l14+`#\23k@,p@-DmH'L7PG-TWmXguЅu B# Т|hl}p-tmx|=n'7G.Wn匣 .褗n騧ꬷCA n/on Wogw0T觯/oG3M%  :'H Z̠7z GH(L W0g( Ѐ$@>@ H"HL&:PH*ZX̢.z` ȇhHy$C#!H:x̣> IBL"F:򑐌$'IJZ$4o#! aHL*WV򕰌,gIZ̥.w^ 0IbL2iJipl %)M9K\"؄6nz 8IrL:v~0#4uȇQB⚛'B!QD'JъZͨF7юz HGJҒ(MJWҖ0LgJӚŒD q⡦8*RUHMRԦ:PTJժZXͪVծz` XJֲhMZVVl2!2R"h+^ XB`KMb:d'KZͬf7z hGKҚ\OOW㵰lgKͭnw pKMr:ЍtK]C`h)R Zc xKMz|Kͯ~L 5*^a'L [ΰ77](*Z![8(NW07ʼng@LdG㡧X,t\&;PLGAe,j*{`L_#-xcBmeL:9iq^9of۝MBЈp[ݓ&M=%Ҙδ7]hUɹxy%MR[ӨNWj{/ 3 iukδu?/7C=$ VvMj[[+ ZzH zP:HXñh = ^|_b˹6!jhް< ƁG(tSqpn{m/ j Wƫm  t51lq;:1l^<~ 6QlR?nvd+ v)ϻ.敷< 14 @|Cv>^}v6l#ꐗ6xqa Ŷ'8}=|.ߣk_^y;}$W6[C^&3gB3Ҙh(zӣ-}ݤw~?d=~_~h<>+N]>'@(h@ ׷Ɔz݇} }}xux mTvGt 7{l&x((arm|'Q B(vy=Gz9^}^ΦyȰ Ho~N#mQXZ_ x3oLGW~p~\Gwu''}xpft{Xrv~'?f[؈h∘ox 0 u Pxx։h|h8XaƊ h؋8h芿8XUƸ،<8aШ՘ڸvXxE踎ȍ(_Ў8%_׏Ey)p 8_9L )eyiيX_9dU&y(*,ْ.0294Y6y8:<ٓ>@B9DIU>8A& 'Ee* !dX`bK fpX^iY^kaZId_YvyviFg֖ٗG, - xyz~9eᅙFL^ ^s _i`{0p嘏I_0l  ^`UæE0l氘ś U^ʩ_ȩa͙_ 9F `i^ƙ P А )ٚy|i_ө՜0+YP_Y^ꟺɠz P _kI$i^9_ ^ *j e텞y^^&$ZI^u ɟE ^ jŤN^ә ZQ_j^X*ɥ5쥡j^h _]@ @&zU ϐ 1^ +- ^8^:^=@^''`9I{YyڟE 0 YYйɝS f^Uݹ͙ Pp:l ڬ@Y絫Z^ z% Zj Y jㅭKjJ РtZ 5( p_^+Ш;^  ^B @|E)IZ%pd9ЮP%Ù 7Y靹H A?MPʵ+ )酳:˴ =ˤOY^f b kKoۮ];d^uE`^ ;^ а ![^-U 鰢9 *: +93Z/ k+06 e +^{^TU^'Z%^˲+/j9zI0p^ °:[es^ߛዶ ۥj@kڸ|j{^J z̯+z{)`s ٢B ╖Őڹ+ P 7̘56ZZ H\` ,^ ^`à5^P uͫ^Тz|P^LL數{<E˾L0 ;G ^yg{ɥjǷ:l ȉ<"Lܸ|s+^1^ * DA@^ϐ{^k X+Z U ^0ʨ ^?  u|5۫گ*9y f U\*qCK]۾ y[-ʦ\z %^|^`m*㵲|˩6}^9 Ӏ२pe 5 Lm+P[K<`ӫkۻbڤO"[^oʴ9Z*Ҧ|sܹP6Aۛdͪq^5Mm׌mLi=n,%3ï ^> 2{ 1:àĿ+kHMGԛR՟_Le ^^3X4:]-KH]3^Z^?`͖M}R@ ˰b^_ ۠.L _֖P Q +Bb ypIh_92^"^OF۽(6s6S;ny/>hBJdI^F~vK^t_O^..u^`b>d^f~hj>G.Vr_p>v~Ux|n^zn^^凞ni>^~阞难>^~ꨞꪾ>^趞뺾>^~쮎Ⱦ>^Ů֞ھӎ^~>>^.~?_Q ?QP N `p.48:%o5",h`-(~+No$FNnfojlXO]5 b@]@Pٰ*cz_x?魀 N 7x I`{_"K}ovOmNbZp Au/,?&E/ N7QQ" M%uȏO/߿ a@@ cQ)C^9ᨈ8+ h .x񊁔+DSL5męSN=}TPEETRҤ]4*ի[tրf.!U\ȵǐC:u&rz-,ɁcŬƄ E5p2%ߔ~dXbƍ?Ydʕ:*UQ0ˬH1e]W虭”4m؉>hZ-}u辈-?]tխ_ǾsԩUyFXN-Zk( e80M9/CqO,%C0AdAll;ͼSJ-/0C 7C?I8KJ@D1EWdE[qSOo1GwGbG!$H#HdI'2JʔJ+2K-rK/3L17rL3D3M5+sM7߄3N9 hsN;3O&ԳO?C%?!PCE4QEeQG4RI'RK/4SM7SO?5TQG%TSOE5G\UW_5VYgV[o5W]w}_6XCZM`:E6YeeYg6ZidH k[oŅZ^%\smte]su7^tᕷVV7_}q_5[&m߀x5a w}'8Wz+8t58do_F9eE:~Yxeg^6biGƹ^sݞyb&=fedafi!hu jaz]whFhafZ嗶h{{YWl`6mgqǓZ·|+sw=y=/Uԛelř1G?}o6Va'~4D~ b)ɦ kvz !-/X5`iO{B۫# *7BҌ}r3>m*z 7\Őv㵳ia>hCW. j |AAx#r-!%bf3sXԀR1_1!҈@Ј: \E|#*5PNbEA_4C~DzE-V26E@t,ˌ+2hH@m/~-}ت c W²U ?v!d -R,k % Vr~ fe=S*)E)ٌ4g1V +s :LaW=-O-'ad~ `> 9S !-QYNTn<IQv.h Wp1oL5骠Җ/|Rz5; +9I:'g6Yw!dO/r@_EgOe-!k*,Hk1 Ս;WeZ &NYJ$f^5d:Ue ^P"R<;d;T:jS}k{(f MkWzײv]7UP@nḭvB)Czz*o3asV0E1q ,!1u賳M kP@WUʯ5=(ZzQkƷ %5z5ΨP򢫬q)jU *sTE#XY6=_R^/Nb(/;*fcAe-: $kM՘u1D>hOx^֏Ci`pVEEe.7@N'N֕+Vͱ:⬫Y_\< +@?<YvnWffDMsU-Wt0< }?C[9kCrQc :{3=w@ 6#5hp"k>(+=A§3{;*dC'l91ԿuA4T5dk0wɆlxp] <ӫ3,6?VYs7Co@dFtDĭ[DrzKGMspZIJDKNDTlH:QR,STYE dŬs]aBz`BY?`\=.l—;8,F&TviVѽc\ie|BF+=p)pwPWuȂXeXurIu\r4XW r)10ƴ{ ; e;cT7$%ɱNO.HwP2I˸ Q'+&Rt*RtLrT3ΏΊ$5*[64?|^SPrPM}&@œGD͈+AS7iXDM;{FDEƴA-AHƖ{;5Q9 =R0}L9UYz %4.1R|Y[RePH6 1KgH3R`:(@RXL,iES :=Ŗ|D qׄ–ӻflJE%Pq(SИ=O=\Q U |SW)lQωUWZS4ȮXwH`Gn]duNi}KeNd+ֲYYVKǐYXqӉOtO1מC[ZYBalW5Fa<@u̿dцأxN PYqp,A(hԻ]\TL«U M5F=P^dd:0Qڴ^${gj5F<(~=Xq= uVfǰLȕV_ VLMV >Z\\TH# 'HVd7p`6v76;5cZګE;Es ?8װ!N{DCZ{G^^d=dTc@d?d3[<՜jEv95 %4neM:]NOXd5ޞ9eTNWaX&b^M@^Eu=ã;0dB^Kȅ\fT&af>4q&gCdeֻ=E֛LaynKX;mr耎sFgS>~=Xʞzy}~~]<#ht\:=@e]~9vfƗ`\a蚶+NμxAK]g]U^wh駆f>c8C~OYv0v]d[!FhڗѬFFjfFH;jOೳpQ|F&||΁L/ǧ4n}TG{duGxDH}Ά׈H\} בImuk^I^dBIs9fRc$JyPʻDaXDpsTQ&b[Qλ)nLVX_Dގ 0K!prٽ+Nn2uOvL ~E?ީTXmfP f@lfEaQTXrWBfQ;ړ MF/R'nX-%`!]G"5]]l_Msǝ*O.u/uq&&v3UY:|SS/8n=SDW TTs/nkFIgjTPI%JmXmM5wGaGWaHex˩kU[-H]],Uh-V[e}VLe΍Sm9n'63v@qZNCp/nW{W=z`A^FhjWXr(Xk[Fgذu95aޜQSрհLYuY % Gqu%s-&%Ɨ_{\ vm%_Ob@fSrJlI;^wڸEuXq:/^'P_r|p'x텾 ϛ s\B,P\l\pϥ\{s-\ߘ'Zq+ԥbe}yDX]u>I-${?Og IOVIbK mFQ CΖ%Gf,j *M"SgHQ0U(֬Zr$kBqf״IiTWܩk.ޮ]+o?zS-"2qA'ncȒ BDV㈓+Sɿʛ&<83} ԗ-moGlhhV8\< Ιüڍt"ϝ4eQ2wפ[hnF iN( It{}㕷GMxRHM?J}W-P{HfŖ[pE)(_- qYeѸ"9#=Ftw> 9$E"o5׊8D8%2FUr]l%e}y%ei&&i"*f dSX%}g(zKuyh^z'Zz)jdv^ehu թjD:+Zq2!wnjZ԰\]B 5Fꋰ,J;-Z庨+E6Vb$nV"Ei.z- ,r-)k/f6[rF]K."KL+/{1+'*/[9c,s^Nwʦݼ2{DlI+4 5OCMsMZ+`mCho`; YFsn.͋X7=>;^^78A82n2<9B8XЖ=&3VuNM捴V}; {l ?ilkp9\Ͱ@%Q+12Qy "Hr̍7a`2lKщ*(! " UԜ-44Tw4$D Ûp"CHYдcG$eYmmDGx7ZM<"ndFBp926OB eP}$ YA! @D# ICiQnH<OqeQ#;lf{1K7%Rrn3NSU: e0-ApBïҝStAu"D ί0eECԧF59 P Ѥ "FiD'H9 I:W,)X(~B|iا$LiЇ38x? "FbR"4BǴyѨ1DNa_kiff<&t~!7)(c VJ&y D!$?iM£u|UI2_/?rdO07C7*pFU dZA[`g$shir wm]a<\ȥ9=} ۥ']s3OycbѨA0؝2H \\ lA F i/Hk4K(?EN󺞺(@ y,U_Mgu7X@鄠<\K˜sCBSH&+',/1gjžO;jGLDج gJIa&,34-n[ۃ 7bטE&9a Wu0 M~^Z?bL´>-N[;dK'G;&X%ݍN!;T|oS:EU\E|Z ?/(Tm0- w*ۦ=DN݋HP=#Tz>?>4Ll1Mɿ>g_>B0+ H`e}8 n` [D]?ZDq4A74<ǥ,j f VЉ(@@C?(KaƠ jE4`7A7 2 b e, >!N fE4H] >(T%\m)8rDpѕ R` Z෹8a!bE~!a  ܤuW FpM0pEPC-bDT~"(E`&@D3OqMX Eԍd&=PXZBloJ )qMJ4.n ͓n%ޡEQR|#NLM7DDU#itV}\{ (4H@1$"+FZ焍1"T apυaZ8P]$dnE &%"I<,4RMjI9RmlKxPI(-/Q^QRR@-)5]-SR/T/ J201YDAf1A@ r'}<ؕ,Re&EhtϟJa'7PM&𜊣Iݓ;meE"hZBG1TYD]ŮADkT#n2OJIԆ#dFdBC9@^2(DrsآL-8P!G6iEd.Ex|"Q!.!TRmd~^i?pNZ#%ugAh U8W]fcD^1a])b }d\bnIoja!&geDyh5MVMS\uF@:Ȋ-cDmZ7b2&>'-wٌ!NVFth Qףaaڐ)#Ag-Ē1%z}(Z*|Yů c״iHEWY!^-MѲ#Lqߐnu>/Ɔ-HLjXO1.O`XՕIǍhۂ !%␥-bmh+eaQ\QYG\Yf-֖u~z)јA(eR^ȝYLAΡj ,쒪߫ύt?-ڗæJf$a +viDr k]e!OZA&N@Rǰ=֢Z 'A@*\v<>>C:dV&^kT١W![L^CjνQgg:RD\۷_VU`6vlLFq(ŝ\NLĦzͦVhF&XZМYY Ԏ^Z׊Mժyf pg' v`gPXr'ld|p בt`J0ނxQCq񄇄cByVŵɝ]eU =B^I9sVĠ1l(6͡/ov뱞e/0E90@0gߊo0pt|0  p0 װ ^Բp00魰51O0!07qFBqQHqk/P`cJcrbG;$11 D⚴I{/11_P!ġz^Qe0Юb1nh|P6= YK5ZPlc P.:C4PA41~-!gv6vX1H)dqEXf8USf^ӧ}<[l?94+"ƶ{kK3F̦DmD&W2uHHqgI|r"rҴ3oK':@/AP3D7kXe&߅.M.'YV|}Nݧ!9UU/s&0SF!PAL(hi\Ybkbs(_)_r֌]0ŋzcinbV(:hh9v{ C9:C5Px6^΄t$cf j3Vk`imiCJTjfzWqiΠrAihgmf7"nx#ilRz>%w}h~Aj_ ϣ]j0e*|pXM|ck:\5T1.yk7bjbziG)#oEOq#Sb'֪""R~Fxvؑir,m{ղ"\q#QktɎmk㷆7杹vwFĺxW9+J}}+͜.þI?I6500fG+ r]tLw^:ԑgEz9K5'.V$n6WSDbE.:5famE6ʮ[&Z}+Ѭu*GzϊKl}w̒FGXxh~O14 <1{-Ѝ[Eo?ʿ$Q-&GQGL-|U "*`&7F UK8ƽGq"9_/N*HE7JDBܽMf%gLvKBwq gxӯfZem/|+_.Hh NoKޔ5s~ q+M3 sE??08_SX?w kp? ?Ȉ?Ǡ?Ǹ?'?C!3@08&TaC!FWE1:`B@בdI'QTeK/aƔ9fM7ql(MڥNR&"G5bN%1FqǓCkW_;lYg T(њF*]SwZ5/=|' _~^ Fa0ݶ2]^dÉ{Ix:4,<AdvΝReYC5Pq9 \ݽ2Ox>(&qӓ ugKesg(Co6G~kݹ,~ j*bRBb.JrAĐX ;<(| W8BQl`,14N+'2C()kcp$%'bL5-Br`& yK$-[J"![!T. =4,M,rJrMgxL<<7>B08?i0 U$d5)UcdrJLI"a"I \YBNm2Fa!DrpT!)B*K=is=>z;nyܛx j;Z@hJs9瘥N!ţP0lɡxHd-';]I HV҉mɜ8!\Hyf5zę!i,ui.4H7x,'MI3>gH[̼{nվ`~[}iBoݚ͌[,lp;EƧ|0F$$p;< h3(L0ރqOɁ&4h<(@*tJL&|RV(WsDd%J%|贆el/"PΚb(\35j0hp~2 d #";M8.0`q[ވƑ%*G8M~e :hAKbVX$IYh!0 YC XPPfGıPd) !1! }e`fcd%% %!PO\I_E+ %i !I, ,^Pb2R#rKO>!:k$b"ϥVs1x)q*0|z(*6(艹ʪ>3&h,+XdFS(J\* f`SX!bЅjQ欤*q% 8 RD1'F G;EnS.R:~ Kg 1%0b0?0!CN>S C~1h0WJt/RoM ]@d\I"`AZ#bBr$"__]#Tn<%% Qi\jT C>"+<&"/1>ωS="$Mڼ?KŴ%,R%J3jn#FKdnJ$$~lL%4%Δs:G kJ0I jSnQ;"˔R)uĘ(ulJ04FPD=RMTQ&%Ts"`j4UmVSuUOBU,V%bQOpXXu$x^V9RgƒZUL$J[Z/[u\m[WV5]5u]5^]I]^u __Zu` V_/56a5\ aVaa-b{l_Embb1cA4686`=6dQ6e1ed[ J`OVeif-b{0AX,fufm6h+X!|y|vauhi.%O"NIKSXBW`ihvlV%!V`%bbkr&lln;l#F/GUMkUbnVl6q!v!oS}iNFPt6Te*v'D4kiwuYqqVSb=ǧ p=9vĈB/=c uWPwiuiW!rԕx+s4J}w 4m(1A=t{g7yͷf7!5ST^Izϧft%G6_J~Wb0Cn`|c|ϷC6}b}]P)HuQ%5ӳW6wMs )XpNK x-"PZ_Bw T@T9Oą;L5jn/@cE`MxZW7vYWi"ON3/"U_.Ϭ˼Qx V] ,xM8Վ ו͏U y M9su %)Ց͒1T=y͍8u՘Y\)%vgaV[KINgdmLm_MnIb@7p|Մj##"Acj+ٚҎrNhsoIIP/@۹SH # Y d76c&T8X`(QPx"ӛiZ xw% =Z)M`v&$(ʢΡ}t5A ؁Y/F_6Oz +zXAG_$X|ZΌ lK@Gxz8F`XrKki$zI[R a_bVsy ,ɖ%Dï9 Ì̌yY"fZ{̄9ϼ5z9LuQ]{Mi;Ls u¶̷Aq{sBL;i¹ _geͺ{MBX;o¼IM[;;[!ػ;;Q¿l | {d!<%<B!`ˠ; @πc1B7 < B `b-ùn23IbQU=\c\94pFd<]că!tjJ<ʗíFcs7żʼnʹ\FGyPdQonEtM<1|?a\Lf?}| c\5я\DOs'aT]=s w,Fg;}q&bXŢm=ّ});؝GP!ױ=۱⶛}|Bɽܩ¹/{՝]iݽ;ޅL==߁\[ ]~{ޤZ1` Ơ %^$0 XË @㣝; @Ë<`R!^W?~"ڀ ` d>a|r5I_lz:|% .@zNFxn(&"^  Go!W]b^ fG:rhaZB  G'JVqxWk?C ?K6Wz_iosK(\wzːY? "473(Wԭ:q>;aA⛷ "A%D'  ^…#L(C菟,[|i(̙4 L2Ν<{ 4СD=4ҥL:} 5ԩPIiTWA26mΜ!7n8qRo۞5ʼ97޽| 8 ﴊU+WOÎ%kڵu2Kav :ѤK>%[J"Lٳi]{3 DÜzN <ċ?tbT936k=ܻ{5ӼN>ۻ~9?sϜ|g~` .U UƄ^^a8LMh}Hb&bMX.cs(P Xc:ȣK4Ӎ"IdF, iN> ~IBdV^wS.N^~ f8UefږJMn5T6=uhgpڦPH; WDgNuȔih#WN28$ʪO"nvJ7ȳG*ݺQG 3RHY4.,h6N(J*RPfH,M6n|>kTR[*A7ư&,F[rsm+.8pN[B (\pD&\%1pCq"!+2t4# Lt*[*T-ٰDgJ{C>zkf% nidltf[PᜐVnO5_ʞw -T~g^u]z8{|c7x_w'y-_9rhy5vz&z|N{UHChλQè{/O|d/}4MVE}4l?9McN` " y~8 00M'Do7t g4蒨f /9zxDW8X,̛Y p xY2V T~I t/H4$$P$lI5W3a4dlՔRD F G:`jp+! E`K! "1t rD.1 3th/|}`A#Kؿ>4Fq\4$PX* j@,X $(=Y+_[AxErj+b qC3 ,Y ?9pP,1)he2s~r&,cքHvE]d$ AI9NpQ [CJTJv*dΌ%jF LB/ڮrhE.Y ST}EG SJ9xMtL/O D=Zbvu0 ԨȩT!2ȪXj zu*)$V?`UPZ Ppt[z׼h/{]?Z uY5[Wnե %c {TI}]=ʜc?{ VV';VQ4&ӳm K QT{ͨյhgY[A!$HH0rє!HILOm`M]n{Vy.0$ NhH_]1!H\7n#۠mFGMB2A+૔d?󔝍 Ьw lD.d+{n hK{Ԯlk{vo8p{.ύt{n w{|{v |/q; oK|^8/k|︹-|$/'|,o_|4orm }D/я+}LoӟK}Tկk׿}^ `]O}t;~y]#e{ua ~s{߽wc<Nx8>򜇼)̼]6WINYs"ڈ>@|ܯ2e_ڧbx9Ch~T>MOD>MhBw= pC2ȱ Wsw~—~~H7 nG7xGx ՇHsh~Q5_  1\0`,p[Ԃ`)M0o@ǀ -12zUjW(# O P5lPEo'  8sWg@‡~Mp#x01A}M{_>8@CP Q @Fvoׄ]}w p wRlp{z3!iH9)k|芥H\&a8SwpǁG8Oh!V ؉Y]h~1؊s({_0(XXsGl@}ĸ[HwdsjxmW~{݈~u؆7Shw vYx8Xqǁt؏g0)|V `  q+ sKukwy{˷} +Kk˸븏 +Kk{9U=  f @ p ˺뺯 +Kk˻뻿 +KkNjɫ˼6U=`௟ P +Kk狾髾˾ +Kk˿ ,Ll@вX ` K 𽶠 !,#L%l')+-/ 1,3L5l79;=>Ӱ P SLUlWY[]_ a,cLelgikmo q,sLulv௝IīN ȉȋȍȏ ɑ,ɓLɕlɗəɛɝɟ ʡ,ʣLʥlʧʩʫAL| l K쫻˽˿ ,Llnjɬ̄z˜Ǚ Pˢ0 Ħ ,Ll ,Ll=Փ<IJܹ \ˡ  -Mm !-#M%m')+-/ 1-= 0}< ? A-CMEmGIKMO Q-SMUmWY[]_ a-c-46M1ѹ~Йq-sMumwy{} ؁-؃M؅m؇؉؋؍؏ ّ-ٓMٕmP DI]=֐֓ ڣMڥmڧکګڭگ ۱-۳M۵m۷۹ۻ۽ۿ -Mmm4МǞ=Ӎ }֛zC܀ Mm -Mm .Nn^=R-I6ݍ-Nn!.#N%n')+-/1.3N5n{ŠR٭gBi-CNEnGIKMOQ.SNUnWY[]_a.cNen9.+=oq.sNunwy{}.Nn臎艮r;lD.Nn꧎ꩮ.Nn뷎빮I4锞>+eNnǎɮ.Nn׎ٮ.N@>.Nn/Ooj T>n!/#O%o')+-/1/3O5o*/;=?A/COEoGIK!, g222121222222221)2!7 :#I<[Wkou|~|e}Nc.R C2 0 - &s "h$gfff)e7e-1$+%% $)H+N-@g)ŁCERQ+˦nVQrŀWt'\xM2,捇Lť{đ|xA}u!`tA.ەx= \0ŵ1a# 8 W\4 BцRXF-p\f"MŘd"õ8 bx@67\(qi"Q@B"Hy_ޔ٧YFpWx@ H婨bԨLa].)P( tŭ!h ugs6tǢ2ԜZj"hʡ&*nDA.h{ ^p.₼낽{6 !aJ= E^@ZZmD߸XDhp++kr8,($[ Bl=jsh7qX禋-B0"G-" a̹Є\㊳w ) i}AW&؎}J#ӈG7Dh<^t4RVF~z)J MxW ʼnE-O.@n-k{F;h/[Ы|CT/Ad#їާˋǏ*Ϊo?+?S_򗻅_B3gԜB@</Nq RA/(B} iWBS8̡H~{_5?D)5&#>`}&E`S.z{DZXČ Y(Øpp!‘R| (A5yIBpQ\Tx1T @$P"AH!7eEMbXdGU~&"%#!h%_^-%,@ O #.IMi]BЅnz, F=C iV 1_z^Ц^Qpdf6J`AZD4IJ,!v2ͨBT`HG  ǜzRF'+fԡ¢(DEh;uўT d3 h-haR:m-H7a YaYӆT 9OOb HP ʗT]JyM`cvv2䫰OJX] IH(3 fk9W !he}pnf,.<3ii[$1Z%L .5l%kk-ȶյGTݭ]g_Q0:WlHt Y9\(BV>]Lx O.C:Ѽ ѩ-ڙ!׽ ᛐU~L`!o;0_| (Tه 7H$A[!xz=b:ƄoZ04$FIBh@h{dxaCc<8M|E5|@J$\A-~\XF/gf(Lx3 gFt"#(hSFqCdяƄ/a CQV$=h :sf]sgHgBҘt/JIrՃ4(2֤vt'm KTdEP V&qYժįa@"K ^KTMB B Ho!_Kۈ,@v$ !emNV4[N@.]H@0$0 T Fn'w$"C4B8)8* ?4 ZYHץpч<?H@ qM⁛oisrK>'_^O;3]?Xttj;5u1T~C=N$ Wϥ.8 < Of3jnn:~6}1?z7>L>~cnamX:oa}v~}/6gC9G~)}cۻwMmK 9 b׌|>Sw{(}'v{WnmSh'7|J{IlnOGo^WCEuƀ&/A+52-"5yow5@(5&m&$J$3t5P@Vqq+qUYQ0a&p,r8s+U+baf>Ww -3Sp؇ !Urt5u=R{⇌X70vXF(wq(xg ax?}׊7y0JXB؋ht}k9d_P8k(eXu.to8{P}W~eX`efh~踌}y}zHz@fxǎGi!Hld(yt]ȏ f†Evǐ쵀8mx#f# QfRS,!\H\g[P3i[7l6-Z+ؑ4&4o_=_CA o"9#sƒ5#X78# #11$>\Xű5ehTn'w2 J(t+O8xJ,u{Y䤖5miqb/ÅlxY`s^B!\7^d8r/WjkXqх2 223Is ^rXgqsZs2BS|Xp-„eWYЗriPvI]H@/(#WXY[T`Yx_u/SI#΅(xT9b7QJIVڠg؊(f~DT<ƒ汏&yH*zl,Zmk6X?dãYXBJM{gc)2M:MOjjk~0fj[K] i9 fW0Xi*GkT.AV+9(fx6ȧ1'Kfm@ n<٨ cVrVB+2 I6;pVYb$_WdopniuI1R͉p'uҪMpqхF əZhU>a$W'r riϺ~qAҙsU3e\V`K&(RU%#5?Y6D922KX۸W+"H:cVPU:yR)ڻ. J0>pYbU#+ WKRN˿=eZL3W[k[ҹ%?$1W+/%7+ B:x\VTGCxE,j.\Hpn$8mw` W}UZ3L]H?S6ߕcf2\B QL>ʍVRńK %Ge/la `P oe ``Z`Pwbf|0VȇȋVP%VɳJ<ʤ\ʐIuO}\V+(5).ˤ| ʩ dƬR(/ <˞L<œT"ṵLq \P "PL1;\q! ڌ#0s"sH ('lleϮiW*+jZU\MM mwl "^ҶMѿ}ͮ@O BU$PϙK.=0Ӫ WL5^ 6}7JB+c[cG-I=eXMOPpxF-p{ QlpmO ]0wm|=րN\ MeUeJ@ W؏9@Z[ ԣ(EF"T!f,I82 e׹iy`xF}}[K=GI`w(FaG MM}h5Wd]KK]cS=N>wS n5]y;B ~RBWYslO0ɠ͓Chl')&@ C@P56e2>TP㍺&$]'W̖d\NZ<#W-%ژ jVXZNUqu+80AnN7VZ,e{Gw+Ͼ'n\(Luq+Q_XAqo1dء*Q& B 6//1/"$*'IN:(#;q#eId'=aR&er&Q'lx'|'(2<(6*@+W{^:/zXJ:S.5*nWjH{,m581!/H2x MWA}YOxO5V5V#/6-u2^6.֙?c O4QD-^ĘQF=~RA%A 4P!-SN=}TG(UyMYӦN-`zuV]~v#ԃFS"}&^|+V\uhveķf` Fx"ْz:| |4܁IInpj;(д-IJƬXlڵ2& *F$bUD# AQPVVᕋ# W^x@Aw(,01~2ȬO-ꬲ ͠k;f>#/B ' /o?Ъ@>ۯA1Bo-.İ 9 D9X.E1/E%c;1K-j5L$Ȳ1Һ G*3mi5K=#/yOA%4?-4QEmGD4RII/4SbҴSO?] @%TLE-TUW-UJSX_ 'X5נ\Z_%aqW]E6"^MVM5#ceGmhŖ_j=loBۨW]%7^Vq;^{5$_F^v]wEo%Tz3AaLCMW`~ÅJ/.8LNxaLv]`VviVf5fQ3J yvQc*bQn9E9K*26Qؕԃ>D፺kR:jVZ+ɆL0 q[j+ :[-ECJ:n:*ӬqP ɻj#\6>whBY镪vcױuO]6أ!MbjX=It$$c 3(eJY.vG$̘ڇִA%^GS? Ad0"8la, & 1TMMpThEer{ }OӅV׺5׉:չUx|FMv۹\ABۇw/~ωFAutPRGeѐVTHqO RēMq^lFoc<<2S}< C(;2! !yv!,?11111111221212121212.7(B#KoumhYM?;%0'%r) h*[,M/9016'= FLR X'\,a/g$0k-=w9FGQRN]Oi\potu}vw|w{ys|l_[WY^dm}t|z{ytvwwwwusqtz~}rmvׅ׊ՎԒљΞʤǦƪŮïƩɨ˪ͬίʴȸŷƵĸݸ۷۴ٱ֪ӥϡ͛˝ʞM#@*\ȰÇ#JHŋ3jȱǏ CP@(S\ɲ˗0cʜI@5sɳϟ@]˶۷Gv ݻxf<6޿ n7+^Xha7Lrj̹ `Ө9װ4ظsjfmۻ tē+_dУK{سkνOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($gʉ(,0(4h8<@)DiL6PF)TVi%I^\v`)YИhlfx&tixig'Ω矀*蠄ȧ)~˜B)Q"(."=jdȉ)Ċ)|jJJZzȎ (*Nɉ3Z?A" MhH ϢhxCP&Ⲉ[д\k lLƲ-,AߚŽDʹbB2sA 0L0'#¥F)7<PjFīj(28|A+qט󌔊JpS#"bC 6=C-⯼X/-?o°5h5K)T{Cn|Vםf N*(n8 A 3jSk^)\t# o>x",Urbn.ltjdUi*g[BF_7 cW\Ń@$MyA`/y-K Ooك ׼_., 5>y+ZV/)6orHSd08@ 28gpOվ~h rڔKс"# JeإnJߥHB:F"F7%DQ^_$F,{KJ\^11Db)(ŧC,VBH+eKě r;Da`B_7oSdT*g$_;g):Pc^v!EL)8ssJIvpdFEomwbAU5$`V;kxü-q `3Bv1g?GY  '@/i 'i H7N{ӠGMRԐfW]#G+i ĈgMX :!@w^MbkN ľ5/jWζn[7]}$h[м.xkpތI&2tA]" @ r-h7Nw' po<j6Bޖ69g 26yYڐ3فcAc y8,  4hCby%q4#=t ?4΋9w yC.9p#Tx7B>rv p!<'hg!|0!p!^3b8'Nl܀-o~x Ջ@@?r {W{q{A pC\ups{W%`)^p{Guxx7`w &%P#w7 t(pwxnH0/Gysħwcp?G fp0vz'oT w'r Npwf|TynS 8{b8QBh}eP}r2x.pr >1/p7$| xg 79@ ApJp} g7P v0f j`|<BpGW'_ *WH 3PAX`&h^P{#̸[7O| )xp 4@Z@q[`.Y`7hr艂pY] |~~c Y {0xa)d x`@XW hA ~UǗZ9i a ǐ=AI 1{ YfI~o I)i9@əIɖgT@{nt6P| ɲp/(69㶎ݳ! (͈xlP&n{оh]n~L`xy٢9|;>")}{('Jn)Qăyr5F@F=~RH%MDRJ-]SfirSN=}TPEE4Ō3>UTU^=Y3V]~VXe͞EVZf1bW\uZL^}X`… FXbM>Yd/]ƜYfΝ=ZhҥMFmj֭] !,>P222121212122222222?/[/ua#sK)w<%s4)o-,j$/d3Z7X 8\:\;\<\;];V8UDRLQTL XI_E&jF6uHH}:Y?`Ndnh{kpmlomrtu}vvz|ȵѵ޸㽋佌޿ھ׻ԸӵҶͷɻĺŵȩ̛ώҁ{u{|~޸߸޶߲ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sꄈϞ; JѣGDʴӧPJԫXjʕbU  ħbs=\Sv5ٷ=[.fe l)f^cP 2ΙYe NLA 5#3hxZo끻1r$1 G lEgLp~mDO<}rF`׺LP Dpw ~W{ZH Z % xH7r:P /n:PtHۇ(&*YHurŅȢf#%cZ)Y$C`9@S DQiW|H(x^Qxgr{%p o. C ޙPPDj :@>T^ ZУV@p If 䤍Y)jzMܦ!`Rrck!6ɠ_fOdГk頬 et^l)-Bߪ#_q[d{E{]1BGIHf:tϑ\vP\/g Jk !~daG+HNГn+J'JW4a^G ^e@GYr)栽ɘ\ neMwIt&|K(< ^6ntXkUq#i'>%DAu)b/S,@#y{Lg Ʃ!aKÛBĦ4}J-JԢ$:5RO.PE RժZXTծz`-Vֲ Zֶ_?JWxͫ^׾ `K,]:d' Y2 e7z hGKҚMjWֺeͭnwu-͂[2%r:Ѝf+]Auz.uû2c Hozx%+2t\ma)Cc[Z?B@Ⅾ{kY n/Ѕ30}p\b[C&v/,zṮČgـ.fqcqLW'qaZƳOZyJf,\\0ָ'D2~L(#ˑ ea\/,6_m<3u`-Uׅ| 9e3mAi}:Ļ ^iFr=]z7mW|X%b[v%rx{aLzveEq`7m"{kvZ5q lgf>{Kwt'azimaggcXGu_#uBXu%c" Tgipfiifxn^|%' 'f': 6`rfe=qwbW(ǁE?f)ez<=-[+Viƀ s6e>7WJ:8`Cx28|Fxih؄MHǂpr'w\_Le@thƄʸx=ߕ|we/GD@f7fmgfQd(z6xZHPEH|䖉mbcyU}owO_V}gȃgPjBeXn dRpxusXS_ʨixF֑ p~j qmH^vsxր?&ȁ8s*}XXlUx[pb@ָ3F@eBi_&dԘZ8LtsæQQZ}8Q&7$%:it^ \U^9qD(Z9ęeK9fy%|ٝ9Yy虞깞ٞYV՟J-( \:]@W֠ZXlx "Z&z(*E> ? J2J8,0>|գ? 76ФMPR:T:.GI0Z7tG\\_1kJU:X: r vzxzmA= D`ɡ,e`Pꨄʣ{ptJک ze GШ`D4ШM2Z @tczAG7t?B*XJJЪ/ ڬ*[Zګ[ :U0D@_p|"Da`z0?@Dp Ț @0: x@H ? 1 ?xpZ搬6jQd @z>jfp D@UCЭJ>@{j7 pm0Dj "5JJHꪴgP  PGzc '@V@jJ 2PPalaP HSlu犳T<[A[{(:EK L|P[P}6 Da A:fڲ˨/* a@ J q qZLj?mP\ۯ[VKF k;뭔;ًۢk?V{ + JQSR@P6: `K?@g௾";[>˯0JKt@ZPɪRL2" wp6`нR*[B4lҜ\ ݻ%/,j?!lѼˆ=L͢ج3 <{̸:JQçl#M+\ІPʧ\%=5-И@}$ 5ʢL>ʯlJplL"]Lm%̢ܸ2ǧ yļӚV_bp@Iiٻ{Z=̀QlȌհI R;bjm͘¾+{\4PNؾ`@][ϥV|{.= k :p j :.]J`d0\3J o) ) }G:P>ྐྵvшn=?S/-R> &.M iPJ|O@L?ɽPXJ/j\jSU[o8b/CM> D0_@b K t`:@+> cAv#D|F7BȔ %U8(: eTqb ?1d?nr!Bv b?Me] Y hˊWf_%)>Hb[j2 #0v%͞cRO_;ncv&bd"y7=d֮%2 bL`0x2P(&6n"bR0ڵ>VDve>Nmoǝ5ۺc 1 ^8A  0"#c@˷~B"~!|bs١^უ?)ڽ_<"d좗 v` u6E(Rw6  1rq A `@`P>H1pa 6NJb9< br@ <]%bCa$ޯ~H:ukHF vOrIЌgɺ.bYt_P>p )'X (Cr`)s:r&axb͊;HMi L++#e9Kn8BbO\'JA40DAmB ЇtE GD| ؉!Sį2g9I6v] i9Ozu?B!$'1[^/*ap,9 Ȓ: . wyRm&KN#())cT*ϙW4gNItp^bP6ݱ2=0`\9#R(6sD;UF2o/ vSr4HMkKrW AjUu@wU&|Ut=hBЇFthF7яt%=iJWҗt5iNwӟuE=jRԧFuUjVկue=kZַuuk^׿v=lbFvlf7φv=mjWvmnww=nrFwսnvw=ozwo~x>pGxp7x%>qWx5qwyE>r'GyUr/ye>s7yus?zЅ>tGGzҕt7Ozԥ>uWWzֵuw_{>vgG{վvo{>ww{w|?xG|x7|%?yW|A'я1G7P7r{Ӈq~5}j , !,b22f:fې:fffffې::f:f:f::::::ff$;@MBCM::$ ̐f::f۶fKLW,,8((4 Hd+CDN..:ɀ33?u;@:;@DablH*\ȰÁ<oc#ؼYg+˽<:b|^]0qhף.ڬsv6[!\uռPnKq3 ?kNsE@Tp ?2'h& 6FQoVhfv (bIhE-w"0RVb4HfaN$(x|㑊ؚF@D긣XFV$xeO7^oR&%#2!f*wB&V(@e0PsW@a)jR8C@gv2j9 {Iy@א@ %'*Fs. vhv(` 8z(TK)J@{범ZCsflj"Z]:b"m;k ت,Cٛn(:biܲ:,``|*\rB 7_r0|:+l@gk|Lp xi)Һ,P@qy,p4xt_zs{@SԲ? oky Ohv&k,AR/nz\~/O`Z~\剃 l AF@Ֆ ,n$EKNȢ)RDVEq"$1*fDh uyJw?LM};b@6c\XGa]pWX/u1lHFiIzV UlJ+Y;&SԬuY09So>-s]z]k0p<<=YuٰEzƳ:ٌ9w뜦z &zaW]ޥ^h9t6vn'Og n}n͟"ɖo; lh>UgW,_i\IY3Z(3e I|Kjyf:5~[.葃V4h 8( +e)Ӷ^ ?8Z)v^S~sS֭?"O HT3j+$TQ~Bs%O6:r! %׆&xm0Q#Ga?f>e OJ1;OϾ|s,!,>P22vvvʯWuԫWWW䯀ʒmmuf:\:WWWWuې3۠mfѐmuWW޹:ۇaWWѠȠʼn:WuʒWf\fffuWuWҳ\ې:蹇[puuff\fuummWWumѠmm::mѿm:fa6mѠmm:::m3fm366:fuWuu36::WʯBCM̯ʒuummmmmmmmmffWum$$afu $;@Mu ȹgƞl[[KLWuuuѯϞlѹ!7M36f3::f,,8чf::((4f::㠇::f\6:f:%) ! !砇۶CDNFvz\6ۀѶ m(l家 aNC;@:\宐sEH d̒uum H13a *H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sϞ; JѣGDʴӧPJԫXjʕbU @!8gb>ᓂ@0=c\SG0v ٷ=[.Če l鍞2^`Ё,0q24=P` sHϠ ٧a !Hw%YMO/e& yYkC~ F, M`[ֽ|9EBB@XzGd)ZQ8QAu4aPrFC Z'PkK(Ru#d"yFp.RWr؈#@L2CIĐ@C\8v)(ab@o7rCZA(\!AE\9 ȝ\Hަu6*jwAy`Z;}c>p'W! vB{DEq-^){ K(",\nP-Fajk(RpC6:btY4 CRb )ŭjJ*H-YdǞj+~hlq3$6'@v+GZ1K7D k9V\Q&/z2&Y[P6hlE/VmՃ)6SAv 5ճI9J>b̵qx<ěX FhxT8) q7Qrё-#R@@ueH@#8\ٮ ArBjhКķ8zJC'&6\O]\B|sSD@gۛC OɏETXL;RX8pp@דcQAҷ1I|Kq>6@>-jg^ >JDb#T` 1ϷFIj& m#_C0UR|#4/x0T%9<iz̏oJp4e)Aits98#8 ,8TAJGw7YJiUCkZp-k25˔=!}<}gZRPX̑s̱X3ęބΦD C#*eFOYO.͈9o\E1T$7OҕX2"PJTP{9jRŠ(Y&TJժvVIsFծz XJֲ#b=ZֶR%n\xͫ^׾ծ`ؿMb:d'WZͬf7z hGKҚMjWֺlgKͭnwpKMr[2ЍtKZνvzf0'#,y $ COR` ~oOv bI{^yЄAOr X { {L`a¦XG(C ۅ wmG<O >ib<y0Ï3pb j[X `̅#`ʚJgY ckH/ pX29|/܄5 f !W.t}!43GgV:{`8#m@ < @qzd,[ġ=ua Rk9re,XLεljyɭ6xm[Nm!Z `~ah[=R0ԂwK ` t34wVt pTxlqZ/{Ghyށ;oGhl B:A!8-9oA" uhawX&1]픏<ں-y4 y`ٟ`aK•vL`/s 9amsa7^PoݲqGg#XY8 ?ǹlGq:vQ.9>_Dam PTS< \瘟ksJ6[V2oky(۸`6-ٽP; xC>4a/J y{^Jsѯ]x{Gx , F"0zrpjpxP"p{ `՚*Kʱ{>Z=1 P(0J"Pzp [O۪;${Jʳb{> 4oSd;'S& *t[vX4&`ZjDk%P[XMkZ۵WBmCYN` pW4 xP&з ;{P@{Ԫۻ;+;;[Wq˶l۶Keʺp {+PJk>qKKzO{+[";$pk۳[[ۛg ⋺;@ " K  P|z{cڸˊCk. Ó E|;,lW|ԽXhP #^|+S;W,<+oNv|ǠTVzT f;ńGe\x˺h xȎzƦǣ:dLBq Ǥ{oŊ<\ʦɓȡƒlPƛLVBɎsLʧ˾\W|˲.Ȝ̇5Z-<̵̜L`\Lϼ,<| Ǭ|,|ϣJ=} mt(M] v ŇὫN]Kʗڮ &;{ >A ĝ 𻬑Z  `z[ {K"Q \;N=!?Q=E6:{\~ZE{R$M{VkTkԚ"[,XͯL;z \{έΰK 暎ʚ˷;ăM9꩞K{ C' Z?Q ?SLԾ̝nˎ';U풫=1&,Į=^cҎ~^OF\R ;ۻŠ"蒛K"{^|E"I,;9IÕ宽;&?y149UNpOly\q7:OxOLIm~_)kJX}?n$J.\?3kX'`˕o`J;ʿ{𔥴&Pֽi}QQ*& S&LH=ZhҥMU_Ub[#A~}+Cj&`뫲QpÇ'|,O0JǙc:ASx͟G>V)5 [|_3ʩ ʍ[9N; p( C 4 E=G$DO=+)/,#;fϾ׬ 0;X kÔ8z&C;4D1/4SMM$2$C9L(IUJ';*4VYgZO<փ`Z@,5XaubUW^}Xg6=c5-cZm6n^\sEhue]w߅7^y祷^{7_}W\f8`p H@@8afa8b'b/8mV`?&` dOF9eWfe_9fgf9giY:h&hF:ifiFܝ:L:kk;l&lF;m;mE4 n离n;oox'xG>ygy矇>z駧z>{{?|'|G?}g}߇?~秿~?`8@ЀD`@6Ё`%8A VЂ`5AvЃaE8BЄ'Da UBЅ/a e8CІ7auCЇ?b8D"шGDbD&6щOb8E*VъWbE.vы_c8F2ьgDcոF6эoc8G:юwcG>яd 9HBҐDd"HF6ґd$%9IJVҒd&5INvғe(E9JRҔDe*UJVҕe,e9KZҖe.uK^җf09LbӘDf2Lf6әτf49MjVӚf6Mnvӛg89NrӜDg:չNvӝg<9OzӞg>O~ӟh@:PԠEhBP6ԡhDxΊE1)nS@R0^2IQR-%Ka*"4=5yp씧@ !,>X22121212121212121212140n('(!le_"V+P4H89n(R@IDG=P8]8j:uB|Kam}sxzr~pqsvxɴܵ纉‘ǜŧűøȿȾǾĽθկۤޚ⓿ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sϞ; JѣGDʴӧPJԫXjʕbU OH 'b=\Sv)ٷ=K^ `wqސe+lBrS&= ]4@44=POWd sϡɎSygnҭ]K ŵ#_Ex_. B g] .n+o`wq/Z/'|w`swᲟ{RD :Vbu`Rq,@1ÅCm|@m"b"l (ը?&vs:"f9XM8T_y ^Ggbd%%}d` qk2DnJV!9Рz>gċ-'"`fآH&aj([9bAKFKc^:ق\ `%=)zB\AEJLքD'eI]z`[\l(pt162?)Aǝrg(S!q mb RPN\17פ =zF.7tGc }esAz)aF c`K)A%WY v`,_ ٗ[imгYmW`p)dNx 'RҬGiCҜgrovfd5wZJ1AۏpdASve|fLEێ+=IyuZ˭jH'݊d/<6Getfw(׆GqZۆbf#W8^B~hqN#1Fe5TQVWzJcYԦ4@eB5j@sҼ0N࢓BH}z6 TnZNw"K5 bR"fȈSYGf!bRJ2'#K1d%fKA0b--fc#6rUpKRٶǴ呆ycjy NHzC Fm15_Q+ _ӆ@EPI(Ỳki0ä+dUZ/Zq#|"hQ&c\gե|mjţZ$k L̂!v֐]YaxgRx "0j̔"Z,آIntB @pɷ)| eD矹\޲Le"}JUbJ08e ^ħ1NNˡH͒ZPT9RZXͪVծz` XJֲSMZ]R JT\J׺xͫ^׾Vk `KV@)u~Mb:vlVKZ+6z hGKҚMjWZlg>ͭnw pK7mr:MKZͮvzmr9K hNA&Ж7r7 ]o{\ LfN\ϖe{#_淳.y?{av@pG|ZtW.;͖ݬb[| ٽG}d PNLøXβmk,a E7En|+ $s 3f8%қۙB|.͗`sB+z p~/"7Ҭ@)kӠk :mo ~&n[]݋mꞼ-D1r~p 6UzJ6ty{jkn3+½nAt;+d/``  c2|W8vhpNl &g npκ lYF8 n&9 myٗS?qk`W@%ҫ> {ٹKt5}VЏ[{}[uRvUwbm] uG`PqD&f^v^WfDm7dfhx6Cd  (fg&wWz5  7n?YcA @pL_qYsX0Z8X}ϧ}ާ~\XeLP2·X}w[p~tHlGWtmt6Tk}vJj4U&0zXvz[`X~8lsL~Q79 Ɗ0 p+&wZf9C f}cxefF_mPyepwezW^=l uZLphp{ Yi^ap}QgrhrwHe9IeW|(}G@[[ɆU[ij,o;&uDu,y[BnjYXyy 5Mp^oiՍ0o)P`{{0n7p0 F@4=pYY^%w}|I0rf}9Sb}Y@׏Z[J- ě:i< x 4٣9+y"BגЩҹ[A:Fsɓj Y +!\oK{GhWYd n轢l:Mr ڙ?j"ey[a8}2kȆ/jl^lٝ8k'5Vx_PfLHvH R'u8vGQJWzY鹞_\GJۨpw׬pوYya'y@Khx!7r:cgϧrrIPr**,j[09iMڣۄ XNH;GN> O# ùZYj ֗ g`pz٬i~{u:z{qj?H5y05@ǯə|>!+@s=GTRg@@R Ze/۶%n[aiv{U~]zշ,ƶVZ zIqx\(Z\s۸;2F` |t븤e{{Z[ۻE[ ʻ+kƸ˼K[؛ڻWP;[yURpr `;|ս?+X諾ۿ<\LW۾\|lY  t+,&|(, s)ØE,6|8l+?!p> W UA n@WDlVO ?BUR.5d\fLY;?|`@ L\ NzPv>~Wx tlMLzXĈ{_,|pƚɜ|_Dp,p< ,}==1ǕJC|W ˲njF?lj|^ 8ʼ!b L!.  @|,ZlcǚWȹ ſ@P@Ll`4=e쓡@am?cʽΈ|ϯWˈx |>(Ϗ`,A8&P5 NU`@lmĿ u.` v:7pĀJ@ lĐH/p ?!y4: l`v*v- |wW,mӌ> Ha ? `t @r KʻL̠-ڈ, +3 q`>NnJPUY>Q I0> Op8`Bڊ|=btY ?p>JA.  ٖ-"pOڣMS=̽߈1 İ_@j@˅lL ?j @͠}ݷ?J >Ab0*>A 70p}M`Y؃ߩ }םg: }JHnb<܂d ,@CHO`Y`"=_kOp0@.1؍<ᐌZGk E$^mu=5+~>!M@s^^ߓnN-UNݢNRڸ=GN~ݡn^ H=s. #n3 ק.=!.n㝾~hrN睞E~~rONY`J=N<bP8 l_!!o3z%4,}g@P KoN ;n=*Ll~=m쒰nJsMU!l_ao3+hs-V/ q<_u/?vnX ׽9î*/^ l_S0Ʈ}՝>;~nn~M|]c>ZbO.?ql)L% @@ DPB qQD-^Ęb)gBQH%MDRJ!SL=SN=}4r`0$Y шb.m:Sn6E6YDtãSը@.1Ymݾ;SS EG%$ j4`he҉בb7uAbOƀbx1B in"jQrtڸ}aOZa*8+ #dcJ㡑 +VJ$F%%sR~/E;o>Rͅ,.AdZj09d8*AB ;#*^#8`C 7Ȱ J L½ǪɁ( >t>)o"7h0L1$ЀKXA.HShY64*GV ːpJDB⯬5*Nf,Fn.4著1=*9͈֓1Ӥ`_̮u-O* 6Xa!P #¸SHb+dD.+.<OJs4MؕHYOS=HJUJ[ZxK*P8b !~"I.DYbF3+׺ݓ\Jl+*M{(̾4Bc+&-0 #YmR NMj&*8c$6n#.6=JezOv 2[8JUW9~3P[5s 11u_m#8[F6.`*CZosw[,p gμ6t+OS-~Y>%&5}271x}a´#=|B 4#RsE+6 '=k B$:p<+_+6:Dn$ c4=҂Єb 'vD-*a }B*>3XC0'4atD"%E@bD&6щOb8E*VъWbBы_4 2`!3HgDcոF6эoc8G:юwlMvF>Q"b$9HBҐDd"HF6ґd$%9IEЏ$C)Nvғe(E9JRҔDe*UJVҔ]d,e 1–e.uK^җf0.9LbӘg/"Ùτf49MjVӚf6Mnvӛ&3! ,>(11111111111111111111111111111111.:(K ]u }snkhda^[W OF=:%50,u9$m=h:a?Y@R@MC GFFIGOISLYLZDW !^h^K$]V *Gw(X̍F@~?zaB5q617 C]SVi+^X_v^jd]'F}yw)xu|r|vZ犜f^2202=lJ#B!]+yEFH]aZ#5"jxchJK4+K,hN걗@v]R[f^eg~힑{)€x˗' 6(^Ȓ ,Лź"1'NZdO/˄@ ?x:sx=={kmwb^_‹h1ah' u3K`x@huuG{Ufwf}赭ƽ(#73 LG3?Sّvw@UA?Jy.\"s&PG@ *2H(dgb(Ed;,g"it4-yς%yg^d.;޽LDˌ;c1GnzEJe!Kw P!"92ApD&=bK{%ɎkH!2\IR! ["hG9Bɻ [ux"V~Tϸ&QF wK.ϖԫz_Ff~[YZ A!lK5%hU# `mTKR@, r'ƹ@ړľ:q='-ؿ3>Ja xT$GWdAb\5uN\\(%l Oɜ⟸"eV%,\9;JIgjeDLM\/L=aM{_̞G7bk햻؋­kрX@-㾒C(A*H1GL8j$Im*"$!EutH*TFJJ| :LFb>u P.q ~YMtz}Yk\ɐw9gfbw VK_A{e/?B8M03{MpFf3LC0vx7tIWW 012!C/~w@B"+H 8L6L*?$#Vβel#Lv̍.X>6K`VǜdkEI3>[qN\f?&z>hh#Ѓ~6*JO$іδ7$9@@ 6"Ag.Pdc _(0էfB rkC H1PjVפ"S8foQ6A٘B$Dlc \жAZ մȷ]jkXaȺ}%{ 8mp' M/܀l nT4HŚqkcپ@]+\D2n]_Ƃ]mx:n|1 jb@5pX)X?^qۨQa3 ރ@pqozK8k,7.dG!7 HaP/h`"P Sxu[8G|])#?sO6(5p)x/B.FXo353 ` 0Ik}"FO3FΫO~ Q  @g /o.9P|y%}yAypj]vP~AiAi x!s޶~$X=~G&mp'P WdHoxv"v֐npݦ jۧyIyh'y(nx"l&\(~4@z` 3{W~A~'с"ak{` '%"W 6~ȶ×^ׄglgN68W!|]x&2h I1~pHᆠrlOxXǁTX'Z(¸Lp (،X!yh78HȊiØX!֨x(T8mh~ȋ ꘐȎz8XxXH؋؍%(I ٌՈmؒ ,i-7銥x!0I)Y)\Fٔs([ƔNY5 )ZFVٕ͆^9di`YUƕhvlIdjrf ̸B('zq9yfwGjQ HƋk@Xj&k&)Qki7yĶusɦVV֠e`Ij&3|6o'pzxojۗoйf{5X )W HzY}r$vrK}/x'se9sePٟ {VؓYvRvU XZqɞuAvN}0'/vpw(euwwa` ?: yɘ9*Fy'ryzyK$y!v'vW"z)z22*-zLBi;p蠁HrG|f|{y|ɡyyW.q~ZZR*襭y ȝ8~yl xqa–T*TF'ڪLg9"(G*DhzȊoyz:F)H7:q BZkzXj|Z&nXzͺI:B$~~zhʯȏg; {e  ۰{'1[{ ";۱&$*,'Ѳ2;4[ 8˫6<۳&@+>;D[cHJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@Bpe`/L:q& $ u l~Zښe`,˺εoZw&- I\~Ao}2az׉oM - E`}\0mƜ̼s0 {:W=zw#6wlI],5)ww#LLh],,e+z< 30aA@ЯG{zQ-%l Mj,1~/"LE=̠mʌ˒};w@jѲL{i$M!}ML$L( ۊz&m!\}\үܩмـ}۵\0*Lٲ=GR#˺"mؽLmۍ^* ; ' j;}\ꚯmط)ԅ[ϲ}ǝtw( 2ڌjʉد a̭]]mW|~ !]Jm!A\̨,Y=ߕ ">nl T.oU!,>#22Cym\:3ѐm޹fȠaʼn:\ҳ\R:\fsmmamѿm6m$m3f6:366;@M3̂mmmmmaf.RȐȹ̀KLWѴ36f̦f 3:.4 :((4(*8R\6:BCM!7Mf$4s磮 $D*@M..:Ѷ\6家. 33?lI ڕѴq4[Įsl 06x'6Zri|&օjf]j*GgʵjwFUXV ZܠLJ1Q@DjLoD8]KbImbV0s_SRZBS$!uZӀ%‘m R )$TIh"sMJPmϝ`m'Cr!JĤvg\ j!]auTrXjXT)mB_7`"8>:~vg.IN0'Lmq 8p$6Ł+wf*DrѲdY IIS%KZJ|b!۽)AȳZ]w5zbd# `p5-{Njii9$f FW6 pۜfsVP>HA@ЈNtяV'MJ(9@XӠ%tL FV)@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8'fxhjl؆npr8tXvxxz|؇~8,!dш)(x舗XN$8؉8((!OU(8hH(a A_h]Q8Xx蘎!,>22zzzmmf:\::ѐmmې޹3ffȠѠafې:\ʼn:fҳ\f蹇\fffmmmїmmfmр6aѠm:mmmmm3f:f:::::3663;@M6::$̇mmmmmmmmmmffafѹ ȹ̐KLWѹѹ36f3: ؇ѣ:: 家((4f::(*8d̠::f\6:BCMT!7Mf::f$۶ $;.%Ѷ..:f\6m Ѡ a\X'BHA%ƕ~d,pRCz&><'k%_ʸ\޶j쫫B8ET=/aYJzu}v`(}n4Xc ~Zc=.`I^XZc _e/0h].Rvmuֶh֞mmgr%ʼns@9ϡcGz&󍠺AV|-uk KWIVٍ 7Jbv#r(]g?~آl! jёڤ`GD4@=ǢnrNX*o0áf$#I\糭iSh+MNZNWf[LawdCz3 :&dUF ŋ*]BM/$y[fjL=_@ b@(*q3rxÊj>҅v|h;~uq2T:I9PeS<:+E@CYL3R{ Xyȱl+w֜5+AkM*׺c^[R5 ,Z&=MlXb':lQTXZ[!f7z hGKڮനEmiWֺlgKڶͭnw pKMr:ЍtKZͮvz x;]ӒMz5/|Kͯ~u+<%H2"xAUpZ PpU0,] p8H0 S#.qjY`-G WwOiU*@%`up!rnZ% "WHN`H9Vi |`2#PErS[8;`3[qh-[EOP2xt*b[z/1tCX 5(Q{Tg8`kY# ՜&nyk+63u[ H ]dA(3lfo ihʨ݀!gn[F[#{s"ז mv!7pB\pQkpoӻ iJ:֍7j7;[©&u.܈ R;[8AA] bw[hÙEyh2Ӻ8PsjW9#AzU!TGnRxgȶ~&Cx~ԥdaCXfmUa~wņV[Hx/ &{$GqW%@Ww[vW r r*y`8b yqi&qef{2(e4hmev7~UAfV^vuJBtDtWZB|j]u}oV0`h]?d(off̈oo8Zr($rWr'k8ixs7k"%5*rHHaЉ3 `ip~WHufumUtNj(hn)MlP0 VT~;7u!)o dV|&x@a"p"'x.zq wFIَ8{8hkZ"jHɉH Goa{{ƃWfL0]DŽB|DZG8}Ǘׅs錺qɌ[_ Dƃ~ipݸhcxz ;cVxizk9#WbHy$Zbx3`wb)faYfYYZlswF0fgyV"fjXyee{uowZv(o\gD`o{ن)w9Vs\y &'\\:^` z\ڡ[ud%*oR2:4Z`@R;j>@U` BLڤN:\ZWpXu[\ڥ^vPjlڦnpr:tڦ0Tw0 u:Zzw:  ک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;[{۱ ";$[&{(*,.02;4[6{8:<۳>@B;D[F{HJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@:D\F|HJLNPR%22{ѐf:smR:趮ې:ےffmې:f.ۏmȐչfffͦf~]:Rې:RfRfmȐmm~:fmչf̦fs4]mm:::::::螃m۽.f.44s4::.mmf:ۑ]:fff~mm~mm~m$ѐ]fBCMs::f::$::f5=Ms~.:.4f~R4:ўR4m:fͦ؎۶Rێf.]~̦sȶͦ $q ,,82&8(:(7M۳P1CDNx ("#((4KLW KA6( ̦H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sϞ; JѣGDʴӧPJԫXjʕbU H煁b*P*P,XkzL+l]gZ P6/Ar6dY2@DC@F͗ 4Hʞ`1[ ]AYC귶f]go_ػr XpbhW/y>A$v /71RX`p˭EXgـ[!`qMVقNv[n$!@ PGP@UX C-bw7ЊMw恥G'kcyYݱ| mcH9df9DQ&f4\l^p[#HYnfB)&w%jEctxӒ1a=هA&zl\L餃e&x[mn9`'F K&nGkOk)l~ιlW(1Un}7]YW@Eg] ]j|tXPq AYF60lT(qGF6ܰ6mcykmFi`e"ʆlAIVFBIFO|x-ȡu]UI*ڕ=Ѫ2yVSpÆOQ"p  X\]?u)Yѫ]XDCq p4&fv -ᅛO[qO,OfgT}2w)|a֘`f;yG=!0ўh0 (a#P !2%ʘhND;̃$3@F&e#s "8ǍoZ1F&!C8B,j[ HetafDSFZӳ S[ )‡ULLN־n'&,YB$Ċ&N i!f9^$oi 2ԓ5oD IJz̤&S-b&RQLQV򕰌,gIZ̥.wX 0IbL2f:Ќ4IjZ̦6nzS 8Ir,Ivs%|W]?8@/ š|▃N ,AOVpĆ죂6'%H3 cV B 3% T"Ku 榪iP01e @1yTw L$9 `Q89qX-Ik[-ZN^ၨ_9/ [عBıQ 8>m0U/d?CTT: A4 -XR@dXahG*h{KDA @Y妴- T.}uXȎG tݑ]s֎REo{0zrG xI i  CuM#<'BkYdª ] $U*z&+ط/pn$ #7bxA߻T]g(+XCQU aI@^k_-IXAw#` HVd= GU7pA+bX )v0\W+uj +! Bs+3T] DWXVtkCxrOeՈ6WWt/:mcעAv, < ّE lz^(RAy=B׌Bt]}Љ:oFQ81` 2Tێ+T a 3 nZnݞ[e4j`o|/Un -K 1> G25UAьt͡l}?͘=A-z"EX>HYkmc߼j-\^[YN_u^}b oNiWs.:w-WX /-vC{ΥcLoYmg9'UV)8͢Viu9m\g1|$Q-v.]l_D賽X$EA~*P_-hx݀lg2kd~}@LڟzYi{ 9mnS=IA6AM?Y^-k~r xAA~Fw@Ͽ eu~gEwUb7u}38ɍ`zYP>J>=I=1Q SٍLf+\F; QI@-)(ōjI(VEŎmjiSxD0ݨg%Wp)H >1藀RXx-J1ʕܙer:+P E`,ZJe  bzZʪY<ک:47Z!X©-ГVgٙnedW[4^6~8:<>@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~舞芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_pX0 =="PS0Po_ Pß=/ Ŀ}@?Fq -HAİ`A>< B %ZxQǐ%MDi$D0P|cG0Knh!ɗ #.XRА8h‚6eDf"ɒXFP -{Ɯ͜ v3hXud mt4PA eUs (MQc.n[>Ї`ѱ>P3쭹KV{V%u7dɻCȹɲ1K8:(e7H~aVqNC|02ʣP3+; kSnr@7p!:J4E ( E㰷s CSNLJzDPSpDzl$$+GH!9K E )D#kE0BGZ֊( zI(>-W਒,=/ 13FqtF83 (5LTqd 3Qi (`>lU\{-U2 C0B#?+]qW^ m:`DFWc@$Z+(D4 Ts:]m1Xݚ(Xu$]$֥`GԑYp҉i%Zx? $n qC8-vbwez _K?I` 5;>I]BCN5][5##/[56̳&>ɇ35`]3`i?oHTǷ찻ϗL~d{ ˟po(`]8X` 6 :(!~0ᅫUnxa XA]J`(,b] 4h8h#:5D)@E&i(PMd59.PVb `\Ugf0#pfxbY@\Qk&< d RAN@ţQi:AT ~DBZfZ6 eAy)``%gP m2Jcn˭3&*B'2)B0r[BBPP H¿@UB@C+Wl+:PC@!,6922d言[63Ã6Dž;?Lύ\9]$ʴ^3ף[\34[\46^`x׀63[^3d$K؀69]&&2(*7]4d 4  GHS`\`93^ 4^1d(R괾39;7/>?I++7 <@M;?9U34^d]600<_36H1.L $C[4[\f!7LdDž[46ƀ]H* Ç#J(qŋ3FǍC($F&S|"B 4hȌQ ,0@44̜L52AkU+å<46T` @@E늀0Fݧ ,@&( V3*#ӼˇN@ǎePn 0kܴxɂɠf V! 0!2?~xvx[ _,gӸhyM|}DU~|[|ÛO~}G7]Ͽ(h& 6F(~R`fva]( @(nb,b0b4X23xC PA ;hVX 1@4QW`p)D4:VR0$t$AʐA#UZr$;`0*&J Q&B(>z7LĹevP$Ni Z<bZ(k@Pš2~䯱Na#"aFź Ѐβ,6 պ+3AZmK :]P$<>P -& p1bP!,";222222222222111111111111111122221111111111""tD % #1= LZ b f $k%o%r+(s8-oE>qTNn``mjlnnnnnnnnonnonnonnonoooooosve^as҆˒ŔãʧѬسڹڽ«HF:p0#B,dҹ'V,eǻs=;G E4 E?,=&QQ#M iZ  ϋ9)F@YQ'ƚMrɑ%i9fHפPӪ]˶۷pʝKݻx˷߿kLp=&>Q0"9vؑCu,r$s>jTlW+8͚;#&EtFMxE]FKdMԊ^߱m[5XOӫ_/qtF_w8t`άóf<9M#M0)BSV[mM'tP-Sh%pVD>5wlaa\YBpe7ӂ%ތ4h8kx\?} CFcږ2QTѭVDq9G8!܂bMR5"U^$>x&5m㠄j衈&:1אBB6WG"i饠]T<@a`%ICYrXbPP VQa #oG`:hvz]i)F+3f}YcتE)T)H覫K׷+ZA;:*' 7.G,Wl_w8f $l(#fd,0K1l8:@BmHLtL7ΌTWmXg\w`-dmhlp-tmx-u|߀.n'8{/G.WnGxw砇.ꬷOմDD$^v;X S$\N||<%_~<ܵ?ƫ]W}wW~c;ٽ|غ3TW_~՛u_Hi@wZ`΂ }'@owgA"(L ׃f }wpph!oyԀHІ^'xD8;x, Bo>xDE~@%p/7>>1j H\A|A@@RëX<- Q < ^ ŖQ3(==0ąV}`hJ >F&hM폛_$lIưĜb'iJaJ`dh^b )#,IrSl7P h.NdjК+)~љ<XFu&hb BB~AL(NW0;,ba8αw@w\HN&;J> l *[Xβe"ۀ]L2K.26p,:xγeL=π#`̄NFWώ'MJҖδ7NzĞGMj?cԨNWeȬgMkDuw^z"Mbf:ΎjhSζn{q6MroYN=dt-z7~'X.8r+.[7Ns '\&WrKng.ǜ8Ϲmrp9ЇNt7 HO;0ӧN3X:{=WNⰓh7xn ;vd;uT7<t3Cw<'sS-<7_rs_l3v>lSޖ>/rs>ǟi5>kv?ojݿY7e%]f Xƀ8fx&LG 8Vg$xl&(|f,a08)&4xe8Mf<@8&DxfHL`P8,TxeXZT؅^`L8dfxDjl؆BيDYxH9JؔNP8TVy˜ZY\ٕ`b9XfhԸlynrٍtYxx9zؗ~8y򘘊Y٘9Xy ِYYXٚ^9ydyٛjٖ9pY9șv̙|YyYڹٝ޹9yyٞٙ9Y9R*Zy ٠9Jzڡ #zxYw(Zz*w.k0עn 8:<ڣ>@B:DZFzHJLڤNPR:TgbVZ\ڥ^`b:dZCZk3aA lڦnpr:tZvzxz|ڧ~:ZzVjija?:Zzک:Zzڪ?jJa=ꦕ ګ:ZzȚʺڬ:=ja@B;D[F{HJL۴NPR;T[V{<+ *8 6 8˳жnpr;t[v{xz|۷~;[{n[۰Ҁ-˦::j`d f 6˰i[ 붽0[{ۺ;[{ۻk8 9*j`dаi˶0T ؛ڻ۽;[{蛾껾۾;T3m;˰PՆMe{ PS <\| "<$\&|(*¦ S +ag l  HJLNPR̰ ܃pV~XZ4oߥ,j=ǃ{>v0 x>[|~N4`_dMeN ׁt)皾Mev-}ʇ^ⱌÜrzǑ^@u$H=4@m݃`!c D~⫮{˙ oPs)U@pm n\Pp4l]ng N$ `>{}$"85/-a~ _.Box0u})QF_xM&R_=l0x,fm g<>Bږ׏HA>.N@4@/|6PAy8{}MnĎPO)@xo_~"pSa^Χ^橎vvO ?_C$9soP("pwUpNH!"ݿ%_/O"0Qeãs$=r<@D-^ĘQF=~RH%MvH44)I#L7xB )U|C&MYm߾CTRM>UTU!BU]~vmՔICV.U@]" u{Gp hģP4(H QxWȔ-p@Ǎ`Ə;jěWƝ[n޽}w7ƖhI&N<}JԨXխ_U+vݽ%kZnʥ{n^46a0 Roɰ ^,#P?3,"p25#h8 /0C 7A6<CJrک1JFo.ZK }r"[&!J׬DM*.xG ϡ`Kה,hC9N;)A G%J\EVEE+eQtGLOr!M7Gp#6O+21lmK@Ͱ .HQ #͂6SUVi]uMD3Yee Vp*Bc?g2cQE%QHy|E7^x%)Nl6_}_OTEqfXsJwRw.8cwB6P_G&d XA a[e{ؗ*ޓlu&h(eA Й*f׭.xFk;lߔB:VmVRno%o)nٵtgq{&+opZ?=tyhtH~Fc",@rFOt yEVҒV&=F;W&Y1D^ҔM#C 3H2F *e9KeR`|C]iP*L!-9k)疒{/KeF$f49U63,̴ؽِg8+Rlz6"ӝ$':rNy"'1Yϩгg@eO~^Hv ԡ$(BOyMdD%Ӣi5Qt iJ8R -:)ԦUdiKMMԧ,)Iwj͞Ԩ F̢թ LD̦>ժ*B˪^իjAˮ~լWLAmB9owe^X9VW%cZu/5S XMeҷNV2mX΂N*Yv m(G[ZL'WZڒm$g[[̭#w[6 .![\ﱸe@.EsV&x.vŋ6u x;6ݭyӘ77U|H_$~_D%l'+`- 9K2p/]Zp%aWzX IJnk0S<Pk)l1&a0 7`',p3`!W#4(L|BUp _{byS՜,J,;f2ksu/YΔ,uyCdk+P!LqƴL`B ;yE/~1 t4_ J[zFL< ӝ*B=RLuUaNp2cM60%kQ:3| W@]e vqN>2ks6ʂtI=5 4tB:ֶ͂@:]8Ͼme̺ֈvw d7nwAUr/ye>s7yus?zЅ>tosS^c?WQ DvxԀ2! agG{վvo{>ww{w| j8w=Wpd^ UA i0NҗG}Uzַ}e?{}u{~B5 pCo3N4Էǽap{&/ 2yg m`C?~Gտ~? mp7xÃ@[S\ QB 31{:A3mBsOD@B  ,01$243D4T5d6t789:;<=1"B#D$b 5a&@²)T BP@-A@ANOPQ$R4SDTTUdVtWXYZ[\$" AOCB\腟HELȓ<)_JD(KDC(.$mnopq$r4sDtTudvtwxyzGz@B0-O؉BF_5s蓾sF*UFQj ‹ȌȍȎȏɐɑ$ɒ4ɓDɔTɕdɖtɗɘɍLS(P#HDt8F;'B lh$0jLʩʪʫʬʭʮʯ˰˱$˲4˳D˴T˵d˶t˩섛ITC,F(JeGT8ehSWȦȉ|dtDŽȔɤʴ$4PI$Ƽ8Adl4JpFI \ʶFS$4DTdtΜ NT(ĺąK3KLHLLzĤ \5U%5EUeu PϞɟKٜM$ʢ@H|O>ʃhdu !%"5#mF< PeO\m@܄)`02`264_4V6_6v8>_8:_:a<@f^@B^B6D`>VF`DvH~]HJ[JL68LN~@%P`NR)R6T*FVVcVvXcXZcP\_T^#^`^Zb^`6d dVfVfvhvhj]bldlnp]jr!n6t*tVvn`\vx65vz.1z|a|~`~n"r肞'6 V膞.vN舦n.&|6铮Vxff hixe x颶 a6ꦎ NꃆgjD꨾ Fji.ejke.ÚjvP۶~jijkiN.lkV쩀j 9KŦl@j j̮.6PFfLvHnD.@&<6V8fn4.0,(&oG%V?w!  c"h mlwk!,R}22BCM$ KLW,,8((4CDN..:33?abl@*\ȰÇ#JHZȱǏ C^Qɓ(S\8`ɕ0cʜɰK4s M@ mУHy5ӔK4xUQPzW pJlV ]keKM"_HῈ }K*F 03TL:,^ͺװc˞M۸sͻ Nȓ+_μУKNسkν΋Oӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PFPHe^eZna^ffIff9ajFf grcjWХTZf'!,"22pppkkkf:fې:fې:ff:YdlMV`ABL$Z_df:::f:f::::: PPPcccJKVfff:ر,,8::((4f:::f:SBCMdppffQ_d:f:f۶곴f+G_..:f:33?(:SkG_k_kkWpp::f`akېH*\ȰÇ#JHŋ3jȱǏ CIɓ\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧ<BJիXjʵׯ`B*ٳhӪ]˶۷iKݻx{W.߿ L~+^̸ǐ&L˘3k~dϠCMҨS^ͺӮc˞MJsfJKt>\paA ,iife*0|zoe} 0^?N!]@0.K{-AS7!H9Ia Z8߈$}-T* 5+qJ\K 4 xK=$䡐LP+1 E>nnnq1H@if[x )>DJ^މ]v&iJE's"7(Ct`^FA9h*ݚvj7fFQjkTT~DCuJFr% :`ݒkҘu(ܣ>&@ ,MyXh|ܤ~jnD Ql>eg] n\z)0Bs⾤,B $Â\9^prKqB nZ1\0g&S]ߛknz^m*$Ny0C7aJ#`=.nzrt]ӑZ\t!߷H6~nKۼ14>~o˿HGLX2cR+ ZT*zu GHE&L Wx0!Q\(3!w갇@ b ("т(DP"(*Z}PPES@] C1y"FԨpcf(:ڱ1t< !IBE)0"PX2HIZX$&7Ih %Q>)RR'<*W Tt%,gYJ&Tn^nR &#)bLQKe:s|4iZsռ6mz387ΙvBq)z'~Ɛ *ЂMhІF!*ъ0ю @*Ғƌ&MPҖBitLcfΙڔ]`MwO)P:"1*R2q*T:R*Vjr*XǪA+Zxq+\:l+^z`+`V1,b2Jq,d'[R@,f7r6,hGђ,1-jQՒ-lc-es[򶷌-p+,r2}.]+]Rl.vѪ풵+x=/Uӫ^L}/|**~L,`*=0M(# SآD3ar 0 * &'S؞.~&|!yF>3de2|2))V%L-s^2+,fU̦<3E5n$9ْvs$gFϊ3 )AІ#E3~t#-8Rm4רMӞ#CQ>S*Q|5(Y/ֶ6"s-]5-l6<6eeðf!iSۄ־6 mr63(q_ u~-oһN4+g}۸17k ޑ@ ^CXxYGu8#-~qj|w?Ȑ$7O.ݔr:xu]Nȕ# 2.is 9 {T,MWGy)kq +?BxA_O` l}flJp - YKػn )Aw7x%?yQ<橬_2Cѓ̦?Sz3i~=,ٿ3s_Ͼ/|?>> W4Sֿ}Ks>9-5_/Wӿ?iߺk6lxÖ hl ؀l8V(mնm"m$Xv(Hn*ւ.n064o6x:ho<؃vu7FxHJL؄NPR8TXVxXZ\؅^`bC-1hjl؆npr8Q=fHxz|؇~Xk#tXx{3;Lj8X3.g؉NS?xXxx.)؄8u1.Nj8h*HȘʸWx*ȌҘhp1ؘ8hoȉ.x蘎X뢎x*Xx^X*؏=mY َ .yIّi*9$!Y*%*' %+0Ii1Y6y3ɑ7<9)=B?CyH)E%IٔNKO9T Q$UZW$[Uٕ&dbY"eGy$nٓl9"o96Axv)yٗ%ᗂ鑀 yYِY!ُ9Y8a %) xɋ©řx ̉9AYIٝi)yX칈 8ɛ4)|ZA՛imZa8aڅjYء$*%9."J/:IA86 9J;=:?ACEGIKMOQZSzUJWjY [Z]_Jac:eg*ijkmZo qsu wyʠ{}zjJʟj*' jzjJ*:*ʔʞz -)ڝ:JNJ:ږ*JJ٪ۊz 2Zj jHYY1zi㯛)k#J뗎s9 v8pZuy?f(ѱ  |1$&{q*-K~/F)uŲ4 7+F3d{%bJ+L۴P+O;]QV[XR\^bTd[h jNѶnput[s{Gz[Yv۷+;=Y]K[7q[9DGѹ{-ۺ+Kk˻뻘 +Kk˼뼀 }+zKwktqn˽kh e+bK_k\YV˾SP M+JKGkDA?˿<9 7+4K1k/-*'$ !+KBh@=:741(.H+h(%"(Hh (Gg'Ggݧ'GgȇŧƿƼǹ'ǶGdzgǰǭǪǧȡ'ȞGțgȘȕȓȑȏɍ'ɋGɉg&Ff&FfцΦ&̿F̼f̶̹̳̰̭ͪ&ͧFͤf͕͛͘͡͞Β&ΏFΌfΉΆ΃΀}z&wFtfqnkheb&_F\fYVSPMJ&GFDfA>;852&/F,f)&# &Ff &Ee7;N^S=qQWAU}^[qPm`]qb=yQ#wh}j]vm-qAoxsw@u wy} ؁탃M؅=@{tlH R'C̅Aؖm\=\ \[[}[M[[ZZZ_1ۧۯS۾=]}ȝʽ=]}؝MA$=!(>,$ ee\G;99!8378899;9@;w>>g<:Y42U&$VPNUP![5`:b@`UcbbeZe ?e:e9e9e9`6.=Obehu599:-J^chS$212222212222222222222222==HHUS`_i^ε՗R׎;׍9ڐ;Ocegw˃Ӌԏُ͎ؑԌ}rifec``]S<:8}HЊPx#Jh@D= NPƏ $MhaFW)f2sɳϟ@ JѣH*]ʴӧ5qR_sa@)B4ȊiSZpʝKݻx-՝;G_sA1[}kb|3k̹ϠCm+g#HtNCIG2ܙF="#N]rqO(sp::L6j@h7NkaѺea_ӫ_Ͼ۵nyi@ dFAd_NS}D6d+XI@`ݱYiA`ldhފ,0iP=8u@`<6rU uL# y}3cbQ#ma~2ihf\4bٛɰn$Rf I zwzeX[ycC$]ukVj饘fjfR9S}# ga+xjX>H`5i8Vvh^a6w~jj&l]GB[I1ᦕHemc9wF|C-tتf>X;ku@ݲSl,؊#G,qR bgw ,$l(,2{,4l8<@-DmH'BQTWmXg\w`-6uhlp-tmx]|ts!n'7G.15gw[Fޤn騧zo@'n/?|'17G/=ȗg<요o觯/o?t XY{Lx={'H Z'$z '(D!Bq00 gh N8̡5H@D [HDpHLg%:I-H*ZX̢.z` H2h6n-(2x̣G;1HBL"W>:򑐌$11d $^(qIaL*WIgDqpxLh./ & rb )Yf:Ix-(̦҈in/ ,_ 0$ Liqsό<%㋔pn ` Ԧ@Muvԉ_M!J8A'z>F u - AL!IG+' Bb"j:z:D5-:"b"@S* Z\u@ J(_ P5k :4P  y H&,VێwXM$+W) Sְ m[Vjbul] >c_[>SlkK[U~}ewiEB49jtCHpOZ$oz]a)CSx^Z oKs"vH 85hP 8@#x$,Ix@:C,dV>vZ_@JPh,d͇b̚çAeY<Gzp>Xp1  u%: ;6p5vPnmG,@W*m>Xs*|>"9I4go ՕJΝ>sϕ|.P -Tu"EEUL?y G`U"D XteVP\ѠA +C$ۭ2ֲ`W #t^+|`-]Lnj}v칢{;H2jqc{NqЊ+to v@C˾e;VcDZǝvv3j{lp5X{ju>ش"wlq yorOQj#/y=7#*MR~xvwG/kjZo=W襫(vpz'x[S?=PiM+v"x@xaf+*. 'Nq]\g!Y<`m :bo듎#N0 nS~2o>d? Phe9N<{:ȼ}EzAtc:ijv׿Ch2_wjTuTT%j -vjv6PQ#^XEQ`d" VW4}YV[pUWd zWez8(bY[2 fy;(#VzvzzrԆMH/X{_IsHꃂ3P.X v|58Py[6l>&oee'&oQxOSXcGdWkY~Tv^#ugtfjxE5WW-h hEZE58`jG njUD `]9FVdM2"vp oehcȆpĥsufv>wnj燭PCd& ewp\n*Ȉշ"׌b8mD>WY؍-u@戎鷎\av=E@]&^viuhUGTUGuVEtVht8Ex]T5TTuRQkFx3y h Jk"P`ԋ8P}VRr$a' xO|WQy} g׈epzkY>F|> tF`` QkUYzU\rdUF8PG6o׶gYf^;%}鄴Y"pc# h5ULjR.QUw1vHuj6"2^-S^TMWa(`@'upP6exMUy&dFf)HWemE}qf c#ҙ*Pp栾EWYZs{ਐ݇>I0숟x!% #נ e6:W{ɡJn!ِwi*,YPLP > PL9aMEQrj>K @ o„0:z>uzu{ڧɦqu$C!JojKqJAA"bY?SZ5>#ԥI:{TLڬ#êjhĬ\x>1JDo Pz蚮꺮ڮ:Zj0گ Bo` а;[{۱뱖;$[&{(#k k @o@ P6{8:<۳>@B;D[Fk~JGL۴NPGK -벟1 >>P\۵^`b;d[f{hjl۶npr;t[v˶V{pp|۷~b;[zQ{h۸;[{۵Q6jE;[[p6k;[{ۻ;[{țʻ+Cg/[{؛ڻ۽ K ;껾۾;{,ۿ[Ϋ\" K[k[ +{\&|( E#L*2<4L,"R<> |i: 9GI@PRB6D/KܹkğVxT6Q6y*1f|hƺ[KE@&/e t\v|xz|yLD!ABa ƊȌllTh~/D[ ɞɠ-[\ʦU;ʬ'ȩh~F^R7 ˼˾˹<̼Ȝ[K-]?W˷,DQĜ|< 9/\v˿ |L&A̼,#TԬΥ3ʿ Ű ѿm"=Ҽk4 u=7, 8= 9=À@@ANPm#RR= )[M]=,q#8mGm9] pH JmGJ= A PzMR]_@>A؃*Ma-o3P r-ɰsِ= ٚ-lٜ{}ڨRh;} &kvjjK6m3` ܓ ʀH] M mݦ=f,f6<5p4Eu! w~P<۽]$OqȽ6ݓm Mˍݓ L@lͷte۳(N∭-nMA6l p8~=9P=>p=JX*%'m-2>g3h栍i`jϐEiIzlRDUm!YgA mdN7 p阞f̠ p׀頞|Ui∞5һ.$P1dꞮ霞옾k~P IE=c} n.~ξ.b3> __ ?:UT N}p40!o4#*/r6\%_4'O5O47+>/?/fmCu PR? 4TToX?bo./YiQq@ EC qq?(?z.hg_:4p+5JOe)aR)+iZ|{y}?9ɮʳx|ȟʿ?ίؿ}S^<?_/JV=|K@ DPB yQD[,^ĘQF=~RH%MDRJ-]SL!J,K[=}IQPe~CTRM>UTU^ŚU+_7VVXe͞EVZ'mN̹S'P?#쎘^[ J`… F^m?Ydʕ-|S\@ʘh`Æ J4n]Zlحi^n޽}\p⻁y{Yr͝?8ͱ~&.he+&AvGo[zջu|ǟ_~'%0$&ao侊.AdA)Þc 8 L$hb 0aqDD64A /qXGF!$H#D2I%dI'4?'!z0K-K//0.nI C0&d|t3>x3q 5|tN:߼@dj@d?O74RI'RK/4SM7S@%I$$Ԙ+2UUWeղœ(YՄz}`pIԮN/~ǹ;p +{{?|'|gƎg}L'B"-j`8@ЀD`@6P_D7A V9ՅhjDaE8BЄ'Da UBЅ/a S j!uau f'tCH@"шGDbDRġ7a8EЇSWP.vы_c8F2ьgDcոF6эf|HE:ю+ \buE,͏d 9HBҐc"iGŃ :聍Ғd&5M.ғ!豏re0G%եVҕe,e9KZҖe.uK^җ#(9Ln9~ r$R.9MjVӚf6Mnvӛg89NrS $f:y5I6al,g>O~ӟ<9P =B}ED%:QVԢhF5QvԣiHE:ҏ1EiJ[l#@1>汋U6Ħ7iNuSԧ?*ALըZ/qectSCb:UVժWEPtTv5:= `C$Th hTWծwMVU2()\cc!;YVֲ,o*vֳm.1^. TA\Sؖgmnu[glpKC.rsCǐb5ˇbcP\T[PBozջ^׽4dž;_:~Rڳ] #Xч 0`!G C .0"H8wX5aw~X|V_&yL|ryjxV5 È|c »A~GFr䪉x}&r5b]@9z7G6sfy#e>3*gsqWx5 Oh7'GyUr :EJZ:7ǹNtGGzҕt10gXؼ puw_{؍]S*׷>W{>wwf;nOr脸:Ί ::+>7:##9{EaWLǂ:@Xf*C'o|w?|~ϯ`P1Mo}uZO'{qn3B7>/^?Eu#cg%;HSc<Ї {8??p@p 2׋ʃ<&$pdݣ=SA> ,Ak:,&H#"5`cیӼ,X`< T?{=?S>2<<+B33Ӽ-dp@>kC8=>0AA$Dձ?:O`FtG|DK$;9BP= >@ \ >@7.$TCūStEP̓BX7,- DBFvBEԄdTedeJJTsͳ<7Fm4͸\XBT rESG.v$q$Y|_Dt~\C|OhƁgFD۾u xG D@Ol5<uH94C/LCs@CuBH5D=TE`C}L`ǛHd4Hi?K܌܃-Լi =ڣ_\Kr<ȧ<TrĽX< IIKVɞɟDiJI~bK˯P¥"#9#˼C;DϴKl̂F LB$l,f|LL9:ߴ;ϔD*$tK+ &ΛMΒ1ΝDNeͤ͡sΝ`B#4OȠԄDԉ{؛=R0:1%E E6758L@% XSx|1ȣxHsLR lE{E(FupdQ(rdMtY1NUZeR Y=Z}dMSڗMڥZZ5k ثM U[ٮYiY!U"]۾ƭuE %XMTȵKF9ۉkMu?݌yBѕ l4UT>}?+]UR\ X[Ktel<酻^SClQ?0ˉ=PF0xE]UV=+9]%HKm9oB­dC?w$ <&@l` N`O^=Eŝ+_ɍ-LeFjZl JzLUra#>@tNw&'vW$(@eͽ,^bT>B.ڍJ{afW VKᥥ\> [%̕ 1P)(|+VABN%G@=ЅKR4:=FFnF؃ ߝa6FG\8a}-`um3=¤EC_veMe|Le0fYBe}_I4^c$V7v:8fM^k[UEA4YacvvgNJ^5 TuF=aR dܵRgnU[: bAP*6VC-5C>Ghtϔ7DHABK@~LV ,fW} =`YTZ;Jt-|X*V،jJJKDBgL]5ea.3P ^30Neaܯ=\6Uejtڿ쮅[jg\V`&m3ͮpNĝe,FmF}c]߮Ӯ.@.= P/Q]nn#3\3I5oV>Gnݨ|]]Kƺ^V۽MS+.^6gUeZklM0dDnfnށDpo^_?\}j6X h]E袓XHlhhfMO`'_ͤgcfeEr,laS|DOfG%as=VTqWpGoL#Н;<)j(Fa>b5ؖ-pbmj{a 6#d37^56ws8seX5.r _N6o@>րgI&W&Sxo0Բ l>}vxZތN MM>I>ؾgfEJfVh e^j>{Nj`/(ioj~n ϏM}ї99휣l#l/mw ؏I'(6M}g7x-te ~7Bg;[L'mo6W0~u~~8mΏ/%qI?~/X,h 2l!Ĉ'Rh7rܸ#Ȑ"G,i$ʔ!E(d˃8Ti&Μ:w'РB-j(He:xIԨP/GOK0@&#&hv #g ܂uLm,V0vn,F |+0 e YY˒.!\\ĊՉ,1ƮL G%"bAQ7‡/nxpLbjI޾}ЙU+WEwtKB[B/q풎>{O~ZA Xl t^z p ik' Xir=I,"-"1֦\Ga% =(9Ym5܁^BD ?H Gaz%Yb $e,~aSu%cL&`9d$edjVj^HМd ڜgi@"8PӠ*(:(U$9#aB;< Y<ɃT1pW7 hF Q{A W2 &iF9#p^?!3BФmN{M Qu#l()RY Tq.yc]^'Q$DӨ5P(9q'X :.#zD9#ACE2oM#)IP9wDgl$(C)Q%SUΒQ1GUF?+d 7С%0Ȏ<&\) -GiR4hBv1] *93A{K\86 5Ahd2y3b<ϙҴvr0+B DQG \0BI pJ`_6& Y-5Z)*m*׹5)8NhbpECSH'()FKKi [%.a݊$2_ cʕ΂Pٶr!p+jS{Org+P _bU^e+ VVj[_ a-n`/cakT+ Vz[чVn1Yڽ W$/mk`2ރb,>kSzC0iZ]AnmiO S8+y} 5kQ۴FܧWjg9riuuŀhݻ n,^x;#Ngvl2gJysk:ht/ YPj2Wzg[%<9ӹwN[Zw1w=}LmKKtW#f?Dhp]Urm\.'&sK8KƼ{-nKx6>:$+D5f˪K"IeLdi8ׄKa\c혴uO]]~KW{W P}-L kLԀ:݀RTFXy>M]la yPqؙh֬%!aYP`Ȗ0!=[B^OIQ@0FU@XYxߑouYiLÈitfY,!La'Dښ|I,ڤG,&XEU,"G\deZek (#T]|֙5z*_ )- Q H88 cII"d>pt5)^ANX6z ZC[5D֔xT8 `6D%CD\UEf B^IƤLn M$L9`|zdDƹLe)EM.1%$@-]5 RV0$Sf7U G'Q!Y%Y2Rj%ZZXNMkP"T]ż%CBQ[_D#EAX٣4fuO ] -b%fiK>%L2\~USa@SmX& i@JPWHNj>T]ff$E~g%h {HceU9tVqw"&<#͉&RZP( V{W~?e\`h. q_}{oQI* c)K&4tXr͊nzqVS߬5dHz Ҡ  G׋ yI (aF"aV&Af)9D eG*(dX`v LɗPmΏD[8(y^~'9qT$'\~4! דI"($"jeTNl'ZkNyfj bhΩ9iT\:'/Z,BZ!9/A"ruy4[9- ",F X,.kiKJ*s}"# :[[;;rN8-:9 e_F]^ך]& `j`^aaF!KKPkA[d^,f@B-xuQ'F}&iZ{'j=kJlrTV mNmF VZ 5K-J9=8}ېIteIuFRei'FGu'z(2Iv֤ʡlFo>uݸCJ+_g~* ~ F ⊀NXZڸh6od 辊rp$D9_"- A ܭW | p `z_"/_0X.MF0p9C98Ӻ(nosv/yfi0C}ېa@>>4ZaRE` o  _1RQ9>9DBd&q {hY!BY 혦M#?B"*ghImnΡb e.'OXR,QIx( ꪺbբrr^J(_0V*3:cH@ kA"QNJE9L9r0®xY8cczTaX:3_L)`Zh83_N-&.sIV$F'RDKt"L.NlOt03~(R Ae]ډ_-I anpܶbTܾbmZ SR3u*YZʦ!nUM5GnQf ʵdӵQ5RkzbfuUnaV)?pd 4egQ+sVg/~/(xo0\sl>XⰋZow)80 vwhk jaP07y*0rIAvMN7S6vmOiT^)^V7pp]լ"v Cڷ OI'vjsȈ#&j$.&Cvi35}tkOWu+ #0Z`2.W0zbci/"c Xjˡ48A5-K][b+9*8ra#8h6ɺV5'@adw;9 &ur9u_wWC‰T'ܾ휧B5¶8/k1\eCDJJ:f/lYӶ5:+g-U {/Tv?Us-VVwuuO~nڎzKY-5&u(_k#r7?{Quc/},7nkFUifX&db/wEMA s#g;d-[n1vȇgiiSϬg|n<ˆy/n7n/iG/}77#9x&w*߶?[_<ǣww7K7F0°({=rE}r|Ts-c:c{閖x"xi)>)ԓgKyG㽗뽺Y{%7{/pqߡfx qgOy 1V;gm2;P {*?#*Ʈ*qY*^W1$jkw繮a9B4c59yzs}9I gIe7w>@F`A&TaC!F8bE5>0fԘqKGA9dI'QTeK/aƔ9fM7qc>|4hQF/Qs뼑::Ofպ+WF,F.EwUm[oƕ;˞?zHd%tYN&Vqce k;re˗1gּݍy X^Q‘} Jj7tǖ=6D9ֽwo߿'{#aT)jOP>tgvd?|fU?t3~}.<+J3=SAj ?"K JB@ Yذ?,F @0JPįǠKǰt!q/kgܸ UXbxURf]M #^JtQҖQ!w~裑NZ5, J3Mسn3߭1E@ FCIgD1r coWo uVG,T!$2MMXM؆|vQt ysiTKG\F\Qo+5M)7M@hFK驯`ʏ:PҤN 9t~|T|a]}~tW=sOgUS?D?xȶomEдMbdnscJ$r d[ݲ PCRG! lRl\;֦Wfa(ys 87w˓Ԣ<)) ѓE->+msSv|aq)PEfrhQaqc1:%6Q_w3m7AbtdE)Cv"GJQr.ϯ󖘑s?oSnXfHW!F`gFս&] T..c~OFf6VXu4{GKҡX%v]C 2vׄEt"RNq4t,/ zI l#mG<ϝx02#d%wDb :Z׆.oOOätWy¶UBltt~ܞ}tV)7_'^}oHo%7E6q'rE)qz1q~薫'٩aBК]17Qs4ѡN#U:*N'dy;Q|@4#-Tn>u*DTeIqoQַ[boԫxRN7>6w+,M`:VSkUÉ"5y5gM*k>N "%>p{xx"D,,B;)Rui|Z欶l B6O4J4$B5Gq (0--7l&"I8[Z:+f3P˶d /Op 3838]Lfj3412&>0j+]*.,<%Kn Z^dqPu^$L}ێ0ÄPݎ=pf, 57'4GˣBB'2Cvtu0x Qg KpE۫TLz3BuKɃG9S-#EI4J@SSY 0!)PU/RP4JTLMomGRdsJ}gjTFd\p!1;pob\=ufY3l9O:%^S; ó2ir?(qY3Z^\ ,SFA'f>F&Sd ?@G@gċքly]Wu7%g8WC? l LBD׆{DgE F/Dd7m'EЙRzW@^wl6V6TH  A OIUI I4:i6Re nKtbfpeY"C1X1qMTN$1.N?4pÒB7~;z?llUSS|xQR:!5ZE<T65xmZ}[7w82UuW ;Wmu5qKEGMYlTY k8咈cVfx=xGX"ε5]p)yqŒ/VٓUY+8)Fϸa7bW&[ٕ՟@8@:n*sYu@n,4CxQ$٘F%vbv/61/iG7jj1VTWM(z jd9W UԖ4vP:Enn 7VUVp 6[] W?湃Ӊ4Ɣٟr1k:7r?ryu;\d(6tlyi?Z&wͱv7wwwwPw^@ofyw檑M֟h *y{gP|yGDmkWC lmw]tz~D~K寵9nןјѐ Tr HI3E4x+d0Y9J RVyVXNa*1+p턇ԫWO57c˸ m1{؋[3щ-O04u?Dմcm+x{ 5ۋP=։ڲ_vQyUWuYxRXj9ݴ/X Tl[Yw&H#i2Y|Bu3b]m@ٺ7"skM*J7ȝ"cŏkwL$q|ʁ -ʻwA9d\ϜT\׼bNvL.֛ehDwj;ykxNipmici0;S_H+{/OV)QmXnڢDˆ5dJXzZ"7@?Kנ:wWtzxW<ϫ췬K?HYy͛ݵ=D纯>AZ5w5SMfoPȽ.L0=__1޷PEۀxIIMq,g=7 >nÍ,\wYZޯ9Or- SXמGq_8tOShРq}(ukzP'Qu\ȼA۽Sk~s-Sf+t8/!~ϳ;oՐXW-}.QiÕ-9 љ $F4IZO%ޒa*al}>in˩%1&+|5O?# "!v! ,AB_9M $x :&ĉ+ZHƍ5ҹ2ȑ$K<2ʕ,<|p̙4kڼ3Ν<{ 4СD=4ҥL:}*ao>H>s&\aDP;67dۺ} 7\.:7޽| 8DR +At{ WM_2KHs;{ :4ź}>:լ[~=êWGo!TX3K!W#&|"#)N:׳O\y,V0z,F S.q:(~F%|܀ihtwiana&C%fA<]­dE1JDHxG6MtAB4 MM_xcᜑ@)(ǀ~Iހr`.fvoRX%ZVXZLg~ (k!64b&h$Uf*XeyC)I(X)ꇥߥ9Ѥ R*z{,+2D9ɟ:t*+L,y mNKm3 P%jn3OAͨ:7.0;7sڋ$Vn.klk,|6tV:5 *Iem"Lr|a냶1dcиa9͸ne:W۞~M*0{|4zk45~ZŻ=VcMz{qv#}rMwvoʗh5YWh$͘WbgʵDn?iíxNJkM2yꮳ29q 0yvwߎy#&%7 Egj3}.+D |߻eZ:LҚG D]Rzxf3yHpÔ{^_eD"xLh"r450lkzPۄ9 >\CuLpis1 y4.uKjÂml8ᐬ8j$*q9_bAJ#W[m,ycb`]=cئ6 CA*Άn]Y) TھdAO"q__ vHaet-@z-➿8UCD+|ԑELW&TM%gv ĸSx.51i?+% c!خD59u,8dI=qkMKnvǖmbV\ohזw Q~b$.Kl9(33|8y6rҺ$41U֓6w:sbG>X[-Y鰕,-s9 xQy,Ͷx|s }4Wp>rS- wtK}FOǜk]Q/^!ҕN*ۭ'Қʰv'ҵѹ2MM?Nw^S댯x~ujgiejX˚U$aHWu)BQ5vb51Sn4`_4 k/g1JlV=fd;E*T&,Uov׈qIqEڕׄ^]j/{m&ݽO.v./_`͊000>Ead]6qg~hr|A`y3P_s__H_L_`AE`5&6 &6a'{$ }XeȃWT |P vGvT.&c0V@d17jNH%c\:FF)d\(nh:d:M׃oZ2 4 s(Gp5p<_fqf#fpY+s&h3Hv4}F+*chSVS?p(5Q`xpjiFjg}QjijFB-T/4WFCYCgCCDdhlmDT4vHFyuEnexC6nicf醎unR6oWSotGVH ⏉oXl{وTn(O[G DcgQnq_r)tiÄM81u%y5Js='?KiC X>0^]ñtit@I:x!D$0/GUI$Ye<(9'Qvw$eR"%GoR,oV*,hr't0i.wQFwSTviKy n r9IyTyS$ZCDbB5zlzh ɉD鷇 ԇŗXC'***LV7dhuYשWWZewZ|W{gI78'Q\~#/W?D`&7A^,595}[} S]ghh!Z7H-ٔ8'SÁUc_G_3v <5x'_cw&4)3_ 9 ;(S:kmyǑKtɄst%1CcS(?s6 meJ3򩛠#^ J29ɥ)jv3g\Ĉ1mVC>Exђw.C'd}*j"Qs[JX]8XjXGy8j!uAj8cd94ٺ'+'EzmVFfȎ8:d*9k h$Vw*\d%AIjwR%iDڪҪa5ei ~œ&Ge!y%q) -;Pq&+P*kA ;e>9A;~zE2 Vh1B[jW܊N)bIT+Ve?,2. x;)u9gR}cYStzoWRq'7u /$ӵm{gR#y_bx)AfMq4 N8WRysyy["{e$$9Vzk"W雐$1@/Ɋ|I|Y˧:9YudһRfu̢Slj z##0\jpr[/*E+ Ei<)Kd[ ±#n^˳`OâAXnúKx'a䖁5ꫤ89HwIg``7XB!,E4] +b:V3c8SbËd*Ɨ3K:l,/֋"U&w4 ¥D>^=} 8aH-0&._ FL5Xr]:~,2gSa*NǟWNH^dh66^hau0@à cE$t!D cHB@[C6d%C2]ΤP9uOA%ZQI.eSQNZUY6Yf74%;YKe^$N55|3a]X;bƆ{7\ĒL 򢟇 :v rA"Xc/FHG.+f2x8%џGdm9]7Zqɕ/gsO~ }YpqK~$cJ`gݛ5nIyn;B%S>dc2*)I/@bBmDfԈv.c%Z&RҰ UNVpw\rVlպ\uZxw^z۷w_~79tk]\]Nv7a#8USb3x%xR+% jJ65xe[߯6yfkf?VݷTevyh flVziVg Yב3"=z눑i{줠zݭ.Mm'>{^< {pMbW|q}ޛ|Th4m0/Ha= ͭ-|qSWfiNr>r&r Kc- IhW7xY :by裗>zK8v!qOܷG~O|*` a^zT)K0?Pg|P,[%WY@,,1P$7=z;b,{K tA+a 0.jӉdBPīlxD$2q[+kS xE,:m;lbE0NJY$c9f@鐋ߡ@Q.xơQjs e  y"Q,b&P PJ\9\+@5&?$\nKd&3+/c) s<T<2MV|$$o+~W nsg=YV @Qmd:$mO#=Pv2 1QyABat(DM NB(F5s3݃ϑ')2[I|Xԟ@F`$Ӭi *^p=*[eؙ9AEUdU͊Rq*,QJqsYz%b9 WѹaukaLI9Ӎ l`JXFDVWrttX!+YnP0X6ƴgCtcq)fSQ΄5kaPe5X&U5} \.{_\ܮVm.I]r3H{մG e{nxkV0[E@hw;epdkܮ׋EoWPu .܂ἥU`hbKx6^h3N]~{~pMo c˘CN܃M,Hw4Yj[BYk&rӌꨔKIe+\)e{S5~r!,f8kԃi T(1݊qZ(EyUKv{izջnbiHgT]0-k^':sJ%CC#kY\ֻ^ܚv˪}mt'å mSXdWns:=6XI,y|Кj8׹p0;طvn1Ԑʗs8=N1RXim_Zx17T\79cP&U'?̍ޜ7Q\x=E?zՑʀ'ufV'j9{HBZrvUߢKr,{Two1z)gTG|wҒ\%X[^Kq>G 4O)?K||a{:w:Ao{!yOx·>sOE>,1yhγsՎ+Gvܯy?%ӯ~N;N>!CÿDӛr{?s,4=ӛyԇm{@K@ 39 @KؿӇH@ܾ<@zK8zspy`AtAD̎y옇r?DB T;!B+ӽ'@xX@ \)#*3K@.d#0t3"$÷=MH4Ԏ »kCCB8=K @)CT>BSh??<$ĆzCL<9Ԅ K mkAI&JD/OԩPE#E:EPCU;V4?WTE~ޫ/C\/]?^[Et F0Fj+FclKd]TF!f.d4Ei$FXFKL۽VeFng\#a#r\E!pEuFClG !}JyjGbb,a luGz\HFSH Ȇ4,|G}jH6ȋdƌD4ݫRɮɑdǒ6RTI<HI0N-Xc6b2 3)DMR9`b:[dB.dC>dB2dDnFVӉdGdCdJdM-EMddPvdH S>eDNavhz@FzzfhlsFhn~ ig#g~FjaFNaHlH`iANhtb?Hni>htȎNh}Hi>gVhsȑx@ N&iyk^@.lÖWj_Z>k__#lͦil?e8慼^_ lʦAlئlfMdD֞._0bmg՞l}ktnnևaƖ^2`8o`P@$fol@op6ol{i Fo`Hro`m>ot0pnzP}xom .6vr(o&&z,׆pn=GU_,`!N !p!l$ o@r%p r,r'a!o?ts",'}(,r/w+a A#$,Fsrr0zy@צrq<9"OCE ?JGrs@d@A}t:F\d0sKbhp23Gr}('߄68g4Glh'tsWi?'y0s!D$_tFRmkbbP?nvbpvlW@}n7wpw+'wpb8k xgqwl7Vk~w{s|?xAzkwxkO;Wlpl0x{k|s.cOkgv^wh2rb07d(y's/p:ԇk/M(r_yyOw?zy'AsPyWrD'z}CG@/i>y؝Zirzc8tope{fz9'z/yP2 zgutzgWyurB߇xɯz|{貟cOx?Tݿ6ddz}ݷ}7p}ׇ}k76wr0X~w~uOkm'nW~߷}l}N?}H3a$p +*c!Æ>$S&Q}&bn^d F^ƒqX !bs},3HնL KѪ7/mһ. fxAѽyqΟ^erfʕOkΡ.}|lw˕ǖyqX"fi֙%w36`5`>mTWZnI7oA^qɖr33TQW"iC< ѳO39"[O46=n')$;Nhٴ>>IE0^CڨO<7jm[d.)AtY3PK&b&T-3M[-=t[Vmk.pXcnm%zCM\9Y+u&;V3c<׹#f ARܲ/| 5Y 57㜳;Ll6l>4WZ>' 4Ln³L?#5:MpVKs(I۳`MJ(RS=aݶ%]ww^'<CBp#nvUo'uӍ#NאMSNbN/u]駣z|wܺ /)^ 5o,{4ʐ#O˞<=S< 6ϭ_^ )LJu,,?`?ϯ~. @4 *h bXKǾ7!"! KX7~ 4! KBl+l! OͰ,|!KdCpG>o8D"Ј 'h h+b1Z"/ b#8)j`\#7эf#D4fQq#?jю$!OG,\$#BB2!HGb2$ 'OL%9iSR\%+[YQN%-k>W24 ,9(K[3%1i^\&35igBtikb3&7o3'9is3\';1'=i{3'?4(A jЃ"4 ](CЇB4(E+jц.$ !,&{Rk22)*4}~/0;(%pqv곴 ,)*+5=>H󁁅 @*\ȰC |Hŋ Ǐ7NH"M\ eJ0;|Ù4mLǝ@ pgPC@0zfR 4݉ҀJPh@]P*Z,@@m&` G$ pP *`0̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУK_ [cN};ջ+W {OO_z=߇4}ݣ֯x'~!,GdG22",-7=>H $JKVABL,,8!((4BCM곴..:Д幺<=G33?12<:;E`ak@*\ȰÇ ŋ-01Ǐ !nH1ɓGDɲC?I LjdyS;f B]zQJ`J!O-PkXNplE%Y` 8pAo󂝫 M H c qY &6tMӨS^ͺװc˞M۸sͻ Nȓ+_μtЯcw};ޕ.|HEFQ  %%1//; "+ B++>HN K,HYZd=>7**6h4 @*\ȰÇ000ŋ3f,Ə Cbرȓ(Q,ˑb|If•1=Yg (x m3 .* Y4&J4S6`\SC _ê5HrXpX+u<Q KUX@"48x'@@Z42\̳g#*XAzif[۸#0Pl-0wVȓK` qKRسkn}( ݮ]u͏`zۗt>!,D/622=>H"# >?I^EFQ^5((4%%1^^//;^Ʉ^55^^곴^ɔ󹺽 5^12<**6YZd89C @*\ #Jh3j\0]` `_adhosvwwwxyz{{{{| ~*7HR]fnvyᆻܲԳ̳Ƶ¿ȿʽμһ۽ÛǛˡѨ׵ټHXȰÇ#JHŋ3j%Ǐ CI2 (S\ɲƎ%cyҥ͛8s9g̚: J!OHC-ʴӌ<4;62b%ׯ_6s5ԫY [bڴkX7d0/޽;Xwk˘-e\eJLvtl[97.Y+bʵAX1ְL hp;ur£gl\H1Z*kK`ՎVo=~xүq~X N";t߂ԠOBHvQB ;*<(TȊ,-N h8<@P!iH&iPF)TViXf啅8I.`)ddlp)d :Bg89*蠄z9N袌6裐F*餄‹/ Ƨ gKꪬh.nП2#/˧ Zjk,* -R2Gjb9J v""J-*-rb,B 3@ aܠ*Eؑ *R 'b K1˻H31lH%.ŀ>& ρЭ""ɹ*x| C # 7x|*<ܠF> $ݭ7M)҂,]KӀ>]hԁְ'*0tB$h[mw畯Q zJ + ͒=)~" HLۡ6بOpN.j+V&9(" @ xiІdPn}ģ(Hp#@"C&!h>#V3qmJE!xQqᢈ MNq7"Vd(/#3zBZpTTaR%Mࢠz4P_4 (> O(Z–`3 ^2SQ 8M2140e1(Ie^v=Y84$" ;G2jJPP%2kLu:Pe4k}:-"0MB&Z7s**!) H` xŸ@Y89b|PF/zqKbIQVѦ*F%PC aRժT#ՕebX` H)9]Zd1P%LS@]=3SMF֧sP`@T*DQQf*ZCKZuPn-D%h qj Y$5u* ]Àԡo(O*eO(U|2]94K\ftLHюִm!*Q jxc)Ũ@d!3,5XYN1-+(QBͦZ`P&lr.dl#)BջeBLgٻ(bQӔe$N8Wv˱V"F1@j0`"Q j+b0_afRޱG%[7&nhNefp.T@Fxxγ>πMB|̈H #AJ!AUN{ӠGMRԨN oӎ" GָQ 75MbNf;625MX;Ҭ-mZb۳n>`v@Mz{ۥЁ~ow$`XBBH7|`_3/Cϸ7{ H67a͆-77=w5w|/x$9Aشp.A 2!/D kXx׿|A @stk:ڳu}tz|Xpg}S'|@ Rv0XqR!h\q8{]8y7'f 8)؅ ' Gx8x 'ks?8Hl؈(r8 s@V~{ `H\h? g)rx)zi8XxK8XxHDLƋ، (ڸ؍(F$x=bhЎ𨎌0N ` 9Yyh ِh0Yy c  0$Y&y(*,ْ 0294Y6y87 &ɓ->2 P JLٔNPR9T pXZ\ٕ^`镑Д fyhjc Bv%tYt ꐗz|ٗ~ $ivjvii$!,'.89E7"& #!,1'4K14'6-51212211111111121211212121212121307+H&Y!l ~|yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyz{|} !""!  "$'*-15;=?@@@@@@@@@@@@@AAACDEFIMPSWY[\^_`adflqsttsuw|ۀمՇӊҋыϋȋ'HA9r\ȰÇ#JHŋ*ȱǏ CDqɓ(St1ʗ0cʌأ͙8s<(ϟ@ JѣH*]ʴS崜JիXjʵׯ`nUٳhӪ]*YRʝKݱeZ!D߿LpNgSlaD&[7-JP*S^QNb?WMi*U\wi7M\Md~?vX~ 'κ\9~MhYh K9FXp[-;_V)ZQj+SV}U9ހb1,F]uUErA? Õ?%$܅P8 ^r5GVU5hՃTz&hb"p^dG>(eU2&8_K6VcUr䒚 nG~xa`㛒SY%]w#~VΗkpAdr^KhZ`BYRF^bg"zDI("ꩧYKLhN5igq8*mN(kh(ɫ4Y+ZJx~ӆ{PK!źG`阢f,0&f=0.5 /lqf|3O%E?X$lO5*+0 s 8<@3+*wò<\H7PG43-uJ/}\wT[yYkht+]j--KҌ2$".x#:96ӭ^ 0D|O"e!73.H/H?\x0~a7\;7#2;?N@|?-xCN"o>#ճXSğ~~|˃oy.{.zp d0vDp D@ :L D_΄oGAI֫׈=5G:uif] CP_Z@pc]ø!"jTPqoi^=lrA9~, ]Z¦l:F>*}"F>ޮp3ӝSԹ`0 ~Y @H*6@bbc6kc)Q{Z \ E|/؀E&q+Y)'&+V $1`pe5YЏ2! 00!/0Ta h:HFR& Lڰ:"Ȇ%uTVJ (fnkp gZyWE\󛧴8IrdU@!), 221212121212121111111111111111111111111122212222O7|>}Ds9[.G1:"1 v( j c _[ "W *V0F28 .* &    '5@NW\8a;`@,bA3b98m/807&8!:%>$I#U*c4v=RlƸf___bhuݜِ؎׌҇{pvшۓ-H*\ȰÇ!Şg#*ȱFPHɓ(S\ɲ˗0cʜI͛8seb #A:*]ʴӧPJJՏC-d-hƁHKٳhӪ]˖`O `⅑uPw(1^ 1g<7*Zh{f8HZFӨS^ͺTw3EQK33qċ39-dAԵOgß*a}=@y5PVF(eQuޅg}e_APgS vE8<ΔH6XUqsqIIAS6Rg"]w=v`#wgb"EP} nWYF&nhz 'v1^q)案&袪uM褔Vj:9*TNq*ꨤo Af*무j뭸뮼+k&6F+Vkf8j+~{Z[+oUkM,I,'A"nPbu+8$h&&O\j,(qI#<! -,>̮+8l>G-w(/C 0 zx`]q3±lqSm"Aس| &&΁5,ƀX@}嘓}7ҳ\ޝ|y)JȓnA,qϜOK kBs|z DG/}N#.X;,j4ܒ/ ӧKkcl=qhYxt[[Lt@.V  Z<7Ad_ B(L Whc gH1wH"Qu;!ZPH*ZX̢58-z` H2]:6pcH:xc> wAL"XE:򑐌$pY mȤ&7Nj (GIRL*WV򕰌,gIZfv^ 0IbL2f:Ќ4˄ V86nn 8IrL:v۠S @JЂMBІ:DJk Fώz HGJҒ0і0LgJӚڴ)W2n@ PJԢ՜*KmԦ:PT'Sk)7ծz` +JNhMZVV :V9*ֺxͫWjֶ `ւ5sիb:|d'Kʶ9lGz W#kҚ(fYplgK|6ͭnwZ#pKMr ZqK2ͮvTBW xkTrMoC{Uj|yoG;.nNKzN0;~'LaW\u-75 􂻼^iWb^8\.7s$@k"/Wxx!9RyTF@ZҸ']θ3A z$Zv6PlZBH=}lbbA5Šo.ͅl=3W:˩gzw. Be'-pľjeu3uKٙc'8CrVs@Pl3Y >yrYw$eG1|/tUh^>ϝu?Vi#|wsw|^"wu[P $W{g= @rqftf!Q~'ysiP'Q@އy:U'v&!i@׃nE(8G J8Zϥbdoaذ|fϠ)r(Nm5?z_rV>x!W{|l}v{ l{؇tl{~x{G`tFgD{gӦ"'WqcZƅjaafHNhPgNցQ&W07!$_ad` ` N{S$lg(N(!ʘ,ƌMeH$ŋh&UQ討_.hU"e(Rؐ%a9E6R'RGqϠ "iOH(].8޴ }F%Q$yt)ٓʵM0Q=KN O*W}{*ᮎyzj56 اc|/ᇖ7 jwFqZ+l;~f ~9JT*,!Xc:H"xNAw1ߖsl;v6x3ȉst;0jy,O{׃j4W 3[;n-Mbjlrw1|Pq"zH5w9g6bz8n> g"[$K冀]*Ѡc#z$$$OV۸KOX+{6q!ۄ`Ka!N`۽ *⻿g^kq4^6`-~Nz-ʸ K~wi&L..xlK(p1*^@c'~hjl`K=]eBNs]yQFØEYn]= n>^~꜎tnĹ}Iw ] gfGghޏmp쮠27 Ϯn~؞ھ>AZ ]Kri`׺>h1ww6NXԂ0^}?_pA>EmY̼g002?4_,#al}pwd,JLNPR?T_VXZ/\A?|@CW8IR^`ϜVLBOD?osb/vogdZ0 nGr>wsI\`/w=x_6\_)ɲ}>@]5*\O,ڿn||m_TԯO?ɯ?T폜ϝ;}fAB =QD-^ĘQF=~cCEDRJm4DL5męSN=}TPEETgd`>M D$ÉN~VXe͞EVZmݾVuśW^{/)`… FXN>~:f֫ޝXfΝ=&F/FZj֭q: YrM-Rn޽}p[>=Zr͝[*U6]v+wc͟Gut鑩Vh]7~䓫0@^b;0B#0C 7iABO܏BWL C_1F{A$ !XY=W98m!!h7M3Nq{0`ˇ`0]1`"}k<?>|?!0 OZІ7auCЇ?w<cyiH9i ^=5M":XCr!n@`q?X/h-޸9@bF4i= eĠ!8H|G"EWqb,xĤA0 Y((Q IRe4#e9KZҖe.uKYbx0D-qD$q$Z(Ef^{"2BL5(\ pӕf5 Ni8c@Ӕ%> zʓ7BqbAizꓗhD%KC,!$&0Lzb3L+F5l4@NӜ  LSSW> DuE(:ԥUrw2- ґv06G~ѥ-iaJ؇(E~^TJ}6*hYE~x8#?AQ5/Qư򃵟uEPہ%ZОָEnr\6׹υ.?AWպR&$2Eto{AxƱ|l8ŷ!/@6'H@vmڇ?1F/AE睡/|^!`T |*p5awq1ݭ'Vv=$%o:+bc5qucx(]%=+^-ǸGmG?g暚%6sʼ~яt%=iJWҗt5iNwӔKAHˡhYA se=kZz֣B6dSFf-t^wV'Miφv=mj 5} {!&݇dyFwGP Q>IVٽoߺr7~oDwpTwgM-n\ W0pmCWqm $Ƿ7%xAr|Ed;3.wˁɮb[MHя>uќ.A PAPS`͋>pA cOa=l*ȢㅽJv>YQ@# [$xȓg^)H\yy#*H&WSԗhY|^{ azKh`;/&N^o__Hٙ~C=gϥ/~~MOj$l'>8 $@CC>cl ˞A9ٓKX>?-z y) zӾb0y)Iz%Kb!;,>ts{<@ϳ}Phÿ|8:4ʩê).@0L3ڀ#/< #k,; D=!+BsÛ=p@ؽpên&l RBu)8r)ȣҳ;\=@ r@?B7Z,b)Z8#m Z?pZ'b).,DDP<׃%= ؂(DVtJC43&,R)oDJC=bialb4FS1a=%f H)ƈxp"/DhȺIȇHH/t:/L-BSHsǽx4B@e,~܊B?D I+I:;1|IGcI?;;lʘEGʧJʭ =pMMDXˆ 'l:W%ͨmzW|#UU[|A M0a2۳ʴ][u?@UƍƤWǂ,ɢ_6QezE\E_V5z 5A٠` \=D=>CzA//-ɹyȑ% ׽ZFUD]ݙZ5"5^uџ҈X>SX%AQYeR2B ( !%#o@`$`^ Ŗ9[`*`>@AL$1-a/3]aF>EEXQ-X Ջ mL= wR |>_-ҪbYa.ӄ\.޶X%>aM@AfkO c/F@x^3>t9LyJPAFvap䕳K\%f&PR6dbzaue卓YR:u.处e`a6UVcdef{qf"e>fkN1m܈tVufvvwg'8yz{&9g!d@`h|&6F輠C}F1d4fe g~JiM޼h&m3HfLhh~b揎MniBi".C3iN8iAi">j1f7j.i"MY4fpj~֒꫾ꬎ޷#)jFjf7nS3.i]t뽎+)jnoF6Mlnfp욄6=F &Nm mf3ΎfؖxK[ m۾F?mn#FltnmmNn8nQh.^nL#o7z7WcGXvp?i' ;lmnGow#ieF~+v'5wawPw9w}#azxawGy @&E @nxw,x7@ A?ثGVyynwA [>A_̛yAFxA$֢7zGTwTV@>c7?hz A>aWg̽=^{x ?DzGq:#|/9l^|@ =(͟GIVG{{W{p_AmP|'W}ao9eCL~寉n~8~량_:~x~n~g`ȯN׌޿M5yf „ 2l!Ĉ'Rh"ƌ7r"G*Wle#F,g&Μ:w'РB-j(R,L)ԨR}Y#֬Zr+X!KiJ+aISԸrҭkWښw˳a.l0ǖ-K,Ȓ'SȊ^7s,5ofϢG,PԪWn:"d{m6aB]pmʗ3o1lsS{xڷޔ;Q;/o<У|2ʗyow ? ziwl}9\A8Q x!j$ya! vx"^¡_Vm"1*W {@""m =(>Z(#E)V#٘c$~$,%Cy%Y^Dct2Q9&S9Z&q)IcgYwf})㛍řay(xy"Z:5ps䢙5 )6')Yf)ʪ%ukpꩋ ;bzV҉ժJ,beHddh~櫹Mk-ZHڦĭǸˊ.GAۯx;0;| KԿ۵ng|IȞZy2iMiM2TiOSN1A)ҊjTmC蒥ҩj:UMYPz7%ƺҳYhQΔlS*Ert] DJ5*[ms)DZN:6Q5d'+7t:O]_Y@f-ٶDxӴmjGړNh[nI[pxiL ]袶 [WGbם\.w59hj-JM}vMo9\sI߁鷛]|Pf%O$W.Q`Dy`:x?+{aʞ,fK c Dzqmc86 D&xɬr P AɢE>y紤{fǸa'e3͒Nu\pƲL?V3\e?y̠-fȬYm3 :t?Lo&봧3iŤ֌TkeKj_XkִƒoQ/旯}U ieOvm^O&DmMGQg,\ێMUu&q*0o\'Mx/r>^?CE1~yg>D9yM>dzΖnͭ ⲇɏ;{煚=eΒ 0>yx䧯:/Otԟ]rp]7X{W_gWu:،e _ KqJYΊR``BBȂD`  & \-ϷxШJ V!%!7 B!U Ra$Y֠MD!}! SDРa_B8!va! A! ޠ`!<# $FW6 !rbᴡJ`\X"#a&&"W"] b",ja}"]"ᢦ.^K 2l!&",1bD՞3#4*4N#X_]6S7z#fc#:n:b|ø,18CrSlBb99nd =`Y$A$JF)zHadd ;¤F$O'($dQO!PPQ6yMrRSZe)RjahW2"e_坠eZ*")]]"%9neu\ ` f.TFUUe%xe{EEfd%b.9XBKeeVgzlMj*hFiiV&f*&gg~Lf[&I(&ojo6[a':qM"N6'='tH}nbivHw~'xJyQ>唵&&Ħbr^gegbfdVapg{(8's'ZV!х&~ (qFc~(sd8'h*(S¨W,F舾֍h,ZM|熶ҤYǥ-6(7hFYG*Wf)2NZ晢bN_ F|`I#)yidީI橞 c >$*bO&h.h6vןbrh1饖Gi^((rUʞ(n$(*. Lj*iRiP.PvEN.iFϠMgޱ)\h#* kk Bb\Ek껲"cV+.2b3&*i2O^IBvrB%>Flvz#acR%ǚ@&⪵jJ,b*X F D㥫N͢,*-j:)kjl,RDݥymkJ@ς]Bzʆ콂slv"v˲ irc^DmΆޞmfnN.V rjmvv鯦.b"&ۦ"%kdޢ-x.>G:.B6"z:߫A̓q  f.-zl2a0nnbDeMͽ4&.{"kGJdaEoo^"ᑮ,dFIZ*noެ0&.N-{/ꮛ, 06,-Jڰ(K7mEp0<:n0 lGp30)L0p Dq m HK0Zp/Elt7/>˵1־&or1 {qoD'$/GDd ov'Fjvqr## ],or+.^Rq/7%B (7 B{ l. '3D&e.18߱/ f7gr1r;+n ["ACs{31ϯ1/23BdN 8!W9:(t);g@#A$B hsC('0!ײF7H 8sCt!;-C; DXNIqJJg43pPq-.3f4E4)jB+t%I'Luxs:k:s2FsrI7{:?r+s5*ѭmU3 B"I#3\\Qڗ45N?F5(-vQ/Qu*u=u/`{p.#1U3\sQ2 cEkY'hne5;cC6ucCVs5l.>6WF6jO6gghmvpWNlE6 L)ɩeЩj=iڙzhuV*o{qixFwNZr,uuOƔ6wŷ.7&)6YYC@j(lJ׶B77wǂ06JQB85kq"+n;8K+ҳv[=2x_+kt#*vZ4)ttdAKWv#tw"[>>9iGE˸ZƫQe{9]*K,wi#.@-/&;2wr" u{RԢgG,*"3ovC9s7/9㰐{Sk/xC7:w9$F> ::)!"r9v',2atyqyG;y{.* ;;C:0 {@5bMy9g|~W KC} >@h"`A&TaC!F8bE1fԸ32@9rHPL)ȏ>~)t%#DY,PgO?:hQG&UiSLuFiUWfF_;lYg~$IoQZ 4W̚7jջo_N pa[UqcǏ!U˖&pSZć3glytiӧ uk\Cz蜮'W~Xϗ);wuױgǸwɓbzy6'}aǗ?~nCA TM@=FI)uPmnQH9MNϓQIRp3JPa-X[qԵI_ VXaFZkd5gEkW^kV0e۬5g-܎%Wme6Wަ4rW߉WGZFރa7$_1X%D)Յ9Jj$ (b5N䗑{# 22Uxg㠱s9S `ꪌFQ^շxj.Ь:c7축"D[Ȧ~o(J8oĉ\y$\Q[f|-q97QrM)g;sP1ݧ;OϙVrә-rPWX^Hkg']_ SsBŃ@r YᑧUvkg^|Oklсz l"@?_Ab3T> aً)scжw8@H-0s |ſ 9y C7 a8V(% ,AѭK-d cDt0Hp B퐇Xa(D)nC61KO[F~U1)ـIEqc'F92f%nC}8GA*[X?-td3` DjɍI#:P''X#T~2tFr>Kx{*ȶrZŤ>aO{8%.Ka%>e2fJq XcZF؜6B8-5INjL' IJSQ'yxa-~nD @h7z31P54hh>I(8:3~T|D  ^Ԥ'e?7R.h'&:?NmSPCPJavTE(WPXPU0t;/?8i$aw+݌^S9|Q$WjPdX^2qlDKa:f.5O 1lX\J^<|G'򔑜@+_NA/3" fobs`<8sd meUуr<;56EJ;"Չ\WݟuzEw}Oկ~}^/_,O?hw;;pp 0a̯sL?(2c>d-P LQ0UpY]pepimq0݁"6`K,b*B)y" E s a 0 p pp p ɰ 0 6F)fpv8 p 0  p mw19q p MPb3s)(\1_ 9p lq1uqys1K1ap l4w1 ODH,_Q  WQ Q妰!qqL]!ڒ@^@,IjLz " R!2"'"/2"q$I$'ܰ!#rBڮbU.iQ$}'t !9R!e>@! n(f!RA2++((Q %X fr +p''.p /30s0 0q0(  #//*/*S3 33/) 4M4RB-/ .M/kR?6u&Q7q a38s888sp8o@8 2@:):P9;3;2s:;393=s8a5i]sd~ndr6.7r 4@t@ @ @p@1*Ia: RB/B22@sC &T<(C4AYE]t@=W2>Pqs7m3(r6>s6EH tAwB 2F;?S,T,3gDsJt.E4L_4FղhT.-0G2HGy4/- 4OtOOOp/P P P5QuOɔLu+MHw(S&)F!TEuTITMTQ5UTU]Ua5VeuVId>!$MqG;U5NWSu AUJpY5ZuZ5n5sflR9UG3''ZS/\uY5]u]ٵ]CZQ5v5&WX5\cfNuX55'@a` `6avaaa!6b%vb)Va2u^qFg|>YM5d@ F]UveYeEb@[5dD_%g`<07G[۴\uSy2'N6iii@fgv-kV>u]ek]zXv76h6N pjEg΄dtlShc99iFV2Xn_X6_ wh wpho9mUpCnn-llU=vm%T(Y-w)8w\Ŗlw_q=\6DwteIt"uVdYsq{t!vmRJY[ucWu47x;yUqx %yEhy/|w|ɷ|7{l{wP|7~w~sH}wNڷ|8x npw$ !8%x)-185x9=A8ExIMQ8 X]a8eximq8uxy}8x8x8x8x8xɸ8xٸ8x鸎8x9y 9y!9%y)-195y!9 !,4E$22ABL$َ99BCM 12< 89D ((4!!- ,,8CDN..:>?I#9ɼeKLWe9e33?"`ak @"$0`‡0Ň):ȑ DQH!NH VFl ऀ#e*yuli`BR+<@tQ H ,(0⡃ &h0E,P(tC}{@ :;b0BF>AL&xrϠ>@@ ϡA?T1 ԩ?'=;삵m6ުw{8ߪuxq !,-'+22>?I#sss觧))) ))523>((4iiiJKVBCMwx} ꨩ..:((( 33??@J`ak89C @*P#,ċ)V|cA=ddDvYҢJ,[r|0f .i& ENy(CHKV `4- HeڔDX HPAW`6%C 4(@bn '+^̸4,yʖcάxό`q&?I GHS))5JKV',-7ꆇ((4n 33?+?@J89C`ak|@Ap 6D‰qFXD I Iqc ,?RA m|@@@g 0ӇH 4ς X!)d(kP[aJh`]!#,G11111111111111111111111111111111111111111111111111111111111111111111222275<9B=IBOETIXLaSl[ub~~btal`g_c^`b]k\k\f\][W[UZRXNVKUHREPB|N>wL;sJo/ 8o|:J鮹̿ )pW IwϯQΐxo>؏2$RN12oJJG'rg' b+} Y3Da0es3:p@QO~( CFcB 084GR\$p<)(!h8a0z a"Ċ [SbB}`)ip !32bKV'pa P0ߺ#(?>)iDq- C6s_p(?&R}daDCt$0 PG|#^A 0.W5iHlĖS5^##щ8‹80,azB\0QC"qs\k t&439 izʴD6˱10 `QUB'"TCy=\ .1 5.$pW,i !yl&EyMdv|Tf$sHjOdGqR`P,'-[$p8Ń+c # )щjҢ)_nC )7-Pr SMiU=ї Bjj;Dy,}m[@UH0pF2EGLKH$ L #XM+fufWX1fYtT}P+ Xt) X =,Qs%$^@ºvCCv%Á=ЂhJC"$ \#%YҖ,e# 2KɌd K SLWmw:],c{Eǐ6b|F1L7eLX25w,d{/A,,F-&芜8*PaHy+:ikqҊQ!_sW!9IVH qbwȇoc >Fd I"Jbm^Tr^ln5mpY5;H," E*-s3ѐ40)`4 ?=Ytc%ʑӥNy.4UYO>2wu{z <" aA?!,,:1212221212222223559:=@; D'P;q Slvwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwxxyyzzz{{{{||||||}} } ~ ~  #19=?@@@@@@@AABBDDEHINQTWY[\\]^^_cflsuvwwwy|Ӏ΄Ήɐľķ H`(# *\ȰÇ#JH(-jȱǏ 1fIɓEDɲ˒*WIfØ2m2ϟ>y ѣH*]ʴӧPJJ҂pjʵׯ`ÊK,F@Xͪ]˶۷* ݻxH7߿W1cP ̸c@"G.Iq̹]@!ӈȉZL:bL3 \yӌlCBfk+ `U31G0P!i *VpQ2}Q+R}rݵLӴrɍ_!N]v9Fjdxe9,&#UhE\>3)=9K v[Y[eXe([.]9FygJ"]dťZ\at0rElM9jVxGG$WVMw"c4]Z6zjw [%2{,y%(7U`Κ]rC.amZ}q2KPHX +l'[/Ȼ袓.꫟I2װ)3xS^︃-|?PܘabϦ&;3t9<ù*o_tsՌtXFd.T8.q.s]xAeh`@v.:rvDZ(i\M0榗a 2P@@b9B>n̪ +5(a 9z<*q_H1Z 7e4$J!nȱp|ư3D"=RZqd4[B9?,Љ kqL%?fI]ȥ.Ko(@gILZPhʠD&1NŌfjIo\̦8&WaJ";INQ"L9NuS$~ =Unch* eD'JъZͨF7юz؅n dcJU84 )VJӚڔ6ͩNwӞ@ *.v dp 2a b8թ8ԪZVU` XJֲh%h 6$C׺u6׽u`KE,7ںqC r9<ͬf3 qxY7͚ fS[Ӻֵ} lg+y1 !,/xr22ԇrx~ Cx׮rxЀx|r\k}vxvKLW_r r:~r {((4xyrw  8KABCM$Mx[x$`x%3tľ\Å$$|m{!C6wt)ziM }|x"t~+t^..:vt^|xd#txatu/UdSx#\33?tiꪫČ)wwD[1v~qxx)KO閤 ,98BY*B@hFmSp6!4 8! =Ufpcq L ]ԩoq-@*2wjHe30NI OOЅBP. 5CL"%. Pz K@G)@ @ ``%41GB $C* P 8 pPc)&8 .W lFg$D1AB%~!,"xkeZHDG|Ttcp{kmmlllooollllllkkkllliiigggfff\_cUWaIN`A=^>2[<*U?BD2; '/%( ),13@"/0.0/0212121112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 H*\ȰÇ#JHŋ3jȱǏ CIɓ\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧ<BJիXjʵׯ`B*ٳhӪ]˶۷iKݻx{W.߿ L~+^̸ǐ&L˘3k~YϠCMҨS^ͺӮc˞MJsfZ KtZ\7˪Tt`Jh$sܙ`>y ns{Vӫ_28g}SqÓ_FhJB߱ 4ג1 Xq1ht2UhM^S-aN7W~6RTE.y.2b@aKC*߇ (u1٢qcWw7 Wz7/o ؾJπ*-$ ^AV WB{m''l  :aGh~Vc0+r\djH:4 D'JъZͨF7юz e~BJҎƭ(MJWҖ0LgJӚ8iG. PHMRԦ:PTJժ6@?VͪT q h` XJֲhMZֶp*% T"^ `KMb觱5,Zͬf7z hGKҚVsEO:~l#@ͭnw pKMr:ЍtKZn* ޵F}m_e JMz|Kͯ~LN` T"veQ;w7{ GL(NW0gL8αwx]'J X&;PL*[Xβ.{`L2hN6p3) 7@ Y8MBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRt/l! $8z !εw^MbNf;ЎMj[ζn}-hE8&8Mzη~NO;'Nq'ά&7p%8 R,h(OW0gN8Ϲw@ЇNHOҗt-T>0TXXϺַ{`NhOpNxϻWPT O;񐏼'O[ϼ7{GOқOWzE``ϽwOҿ>HBP;ЏO[>%`)h ϾOOO[A[CWϿS"Wb~w ؀ɷ|e`P ؁nݧ^xxP,؂.0xz!~p0*1T3Ã=*1B8DXX _ '53PdTXVxXX}HTapM 5 5Pjx 0 5xP o V` ^dY(zHqSx0@ ` Wr8/B~yux ؉xxnP0a ih4Ј8S@chG@'gAJ ~PPGxUp q,~، X p ph u rrXxɎ@v()"9$hp d**It(}x9Y،HH9y@~p808FɎ}@BmGD[kyϩP-KղEO[_m)Y-FMf`Ml\ֶCԮum״BxԮ0c~}܊F=؎}n}؈xj=E؏]ԑ-UZ՘MԄdՆ٬AٍMRڟM8לڲڱ۫0HMm֧=e}ݠ]}Iޢ-Mߛ.->ߢS^mߗ ΂N}ᕑ+]4(e@/m♁,.0ށ257΁9;=?ACE>GIK>M̓>%<^^`.}X4~1$%o#) Mw.3>z~|.xс.vN~ㇾ.nэ^䓞yQ>n^ޗn䧾>tNۊ]ꛮ긎>®qRwXMZ찾쬮pa v!Hl.Y_.x-N깎f n.OaGm!Ϊ~Ǽ,ofGmj02򵎮z$&;*\z5ACN/4yl| Z\^_`bɦUiYgOqsOoowk ?}yu?ȃ=ZQXxtl/OXWe,ƎVAVhUNjU(Kn|ϭOO?ٯo?O;u@w /OO|o;l 4H2 >QD-^ĘaB=~$QH%MDRJ-]r`$$J\O*=}TP@ETM}ȱAU&,S֖OArVXeؓ͞M:yzW\J"eJWPN{5pP iXbƍ?ƨ͜;_ƜY]y5Nq`XZ$bխ]d߂Ɲ.绞uwB{xr͝?Kխu;f B^~^z\;2wd_j{pcN*Ko@D1ښO?sOJ0C 7|iA&Q )O p.WdE>JQڮF\̰@@ӱȧn,#G#E @2JL% I%P2L1A.HK4dMDŽ3ʜM4մ3O=kO?6"OBE?e@3 RKl4SM+R)4TQڴTSzQAuUW_TYOVZ5WQgZuW`MWc3߄UY;d3Shh(l sZg?c[q\(peOsvZw^{7_w7%C~n^`-WKa쳇u{һ{]s6Q|~w?T+^~W)5U] T@) @v]y`8.~M!UB tSXB4pn1 iH. CVpw=86+I,hD=Ԛ,+^DYE/Z"ސXFڝQibو/7& SG;1my#}(; T qV\Q"5>rX#mHK.$8I}rd|(IS R*1SN2k%hW .1Q*È)*c3.T-LgR[fYM\|6Yo+8YVN^hT'aNUIwUd< 8OsRY.Z @UJLR(*)>;;VQ Кh8Q|HIjhQ*(KOZOA$)ej, )OQ>4)У*{Zj@:)3jp~T[SWiֳic% ٪)I+]5ƵymT]tWn6{=[_CJ oSbXRdDȞUSrVNeai>vMu&kOXeX\{'nc7E\o}kFv Sr\ZVUGtJ( PbxU^НTo%3Mʗs{!wI% XQp =?7vUbE.I}MzgH" )֊OIƗM=b9i$NyCB.-i |=1]#'Qϔ)ZYue,[\槜Abf'Ykf< 8?H΁3@<h.٠XhCщ=C6hK鳃OZtSꗝVWXP ֱȬiױҵljmQ19 }k;6îO)E7.!Lg';6mmR2ھ]mHFnf{v"mᛋ5U`<O n/"2 ïu4) 1xc ^C1dx?nw-x\y[/+憞aj'1sz!o矗-:~C(e^Y 1e:hë|:>+Q;,s[i-xv=ŧI۝+ea>3[!bx E)CCO%-ly0^]0%wR}J<Ǜ0+Y^Z׫$z=kz̻~_gy%=]|G~W|;Џ>F[?I{GE~_E_F? =? $>t4 t@d@ѿ | @,@& $n2TKQ$̖uJ BO ¬1#\$#@'<4(,ȝk+*B&\-,7&2D0AI!C7((CC:,)8\BC=4GD3NDOPBI@R,E`KBLl UtBVBF,ģ#E;E AEaXl6;DC,Ƅ Dd?e(>lE.djƋ:EQdh4iAqTFrc P>{#O; PPxP ,Qu;QKeXQ>%?8]ӳ U>QQѿQt$e%]JR"=Rp3 R&R, zR EQ!Q1-ShӀ;S%*0e'R֜S`5e5S1SRC4S@  B8H5PDF\T,mTKe9M>*:@ :5TAL9R >SM?UG}ZURIST"]UNUTdUnsUghiUIVVgְ&c ׻-r=s 6PlWw{e }y%W~X~׀%z-؄-ׁU؆̓uVge؉Ԉ؎ъؐLْ]Q5Y]rؔuEٗ ؕ]fٛ-ИY|{lٝZ٠]XNeY%ڤuϡU]YئdکeӧYZ׭TEZڱRUU[ڵPEUl۹UP%֨۽Eͺ[[vۿ%\PEƕu\T\zȵƄ]Zٴυ] \ E-[օR}]Oe\ߜOۭ\5^ٽU-N^}N%҅ZM]5߇ެM_E_}܌1Xߵ_}d_V,U`M]e_ .֥τ#P' vO>$0᜸fa]OF&-9abG(#a-8"^["<$,2x)[)bG"a/Z/V 1V)`Tc:W<=W0?@A&B6CFDVEfFvGHIJKG~:N?OPQ&R6SMdN~G+,/x;Eh@@^_eA> b6cFdVeffvghijklmnQJЃq&r6sFtVufvvwxyz{|}փJ^G xa/2Pq?]舖]J&6FVfv闆铮vJ&6FVfv꧆Jxxe6-/x8<=؃>FF~1p뷆븖빦뺶&6Jȃ΃JdžȖɦʶ&6fnh2)-F7;;`^m=F&6FVfv9o9- 6FVfv-pxp),H/12m9^, '7GWgw7Jpp) !'"7#G$W%g&w)rF16p(E/07E4W5g6w789:;<=>?@? 8 F z "՗1qW`UJHᇁ!8"%x")b|4 8#5x#9#=#A 9$Ey$I* /:9,8\ >2Yj, w{,9&ey&i&m_uy'y'}' :(z(*( 'E)Ah)rZz4:*z**H_}z+++ ;,{,*, +}5 V@ '"A*骻.- {/// <0|0 +0 /AMk-Ŕ4qqp&wD͚|2)2-2̸5o5|393=3A =4E}4I+4M'q24HS OLtR>e}6i6mv<u}7y7}7 >8~8+8#EP2c)UlI=ӡ>:饛~:ꩫzΉP>;~;;; ?<<JN9[b>}石~=k={ϳ®<>髿>3< G?????(< 2| #( &br 3 r C( S.|! c(4!s>!m!F<"D qN|"()RqM"-r^(1f<È5n|#8ұv#}8<~# %@<$"4D2| IR$/Mri'C)Q,%*SU*|%,cSʲ%i]eԥ/)aB<&2iEW*| iRd5m>P&8=o&9ϩu&3|';'953;(u@oE hIeUb[S[>[8`9e9f9p8"4&.)" #g ;$ *C5 )!#$'(&.0'64)D5*[2(o/(*..0.1122222222222222BIMVYnd[bgXcpTcv\_xf]zkguoorztv~vnnmlggikpu|{vttu}|“səqרu|}yshc]TNJE?ܖ:ؐ7ӈ/zoheefmzX!N A'222222222222222222222222222222222222222222222222222222222222222222222222 H*\ȰCz+"JHŋ3jȱǏ CIɓ(S\ɲ˗0cd(sÛ8s ϟ@ JѣH*]ʴӧ;W蔺*ԫXZׯʌeKٳhӪ]˶ևomKVe:ͻc LJ\O Ļo߿3k̹ W Z*e 联gtWDpw@-H-T O ʖswU6m&x ]Js!y Bue aX"!= &%o@"z,S\ i'POW5_gPz H B@%Q܈ UyBܥs[ZfV.TIP:!HBryș.g{-A1HO -ģ !¢T$RHP -_M:YRPBr q-!!!P ֪+=wv myx`Vޱ A{ ZkkB~h٢X+]-J]y-`ʤ@Nthӣ7M&C =ij>IeNyP+p5 @ 6D&'.ĝ "& x"6ѽEMO(Q:4s\n)vMxm6qKo}x3,PcW 1=Tg@BҹA(8ˍ`j@ #.CB;N`ƓP1V(̚G 5ָ4φ# ~G-DP?|ߙ <'Z: ҧɯ ᪟ Y#@L0vU~} B$' m 8fF K[tF*.nHc:zi *bHAp$%'^Dn5r)==M{;H2ƹ)KγHX1Ď+̒.d";$ثɐ{e@M8t_7)fpww$ɧq|L`' G1-!#hHKˆ $bAcbY Vw#-F1q 9B@X̜,)#N5 6p\K71 *!3PXmlU E7)l@3]qhJIM} v &ɵѣ(B6hEwJ"]t%+mo*$`@3eR3>:Qo ;/A .$m Uqs-z E_㨺dXC'aWz_fUKɲmZHW`yd:,򉪁 SI%Z0KBqDEDH |&/c)imE uQk^DCajSA7Fu pK\[nHBѻ)O5`'bjvQ-4m'ԟHónv$>-iN|KS zL B+N8;NpT2]f΃\L,1C{τ b(NUzwZgLc1Snkqrs dHN&;P|e~COhO8wkUֻV..8>tE]зßs]o\C|2{G{|z})w GyD . 0yhx~D"8$jGtƷ{'|=q 7|Gxitj7p5 |P*s{+W%L؄v5wsurY(v b0vt‡}l{p_yGg8vOr8txi Xxz8r{fvx؈8Xx؉8Xx(oЊ8Xx؋8XxȘʸ،҈xM%pؘڸ؍8X٘渎؎A@%)Fa6؏ y8 A9Y(PTّ ) Y*툑ظ,8f'))> XT@YHh;M`R9TYߨ攙O=ib9dXZ`^k er9xݘ ֖np* N* C@Fih3p I3 ` 1 Q y _&əY|ٗXXf)!NpyY`K^i`BIaX P 虞3ia9Yәҹi> !Дɍ M`Y) H ٠% !Y  NZj Y4 `) I@ٚعCщɢ@:HڣL 13yțliI?p{%z?!I$ (-:I_ʙ)y J;*ZɩI`*ʥ? 1iqڈN9ɡ9|zss* z*K:z)j ZZ:٭> iYAjjީx) H0 *C+)I:I* j DzG0I%;! 1k鯄:?@V٬:ZyDڜy kJJRz6 ^ SɢIJh=' ^œ3R0RP0h|WPǰA Np=|3@s\nLԀ;\w\vJ@<`ypÀLȋ\c\@`\ɖB0JfQ0M` {L Ls u=L\=ʆJm<l<ɗ<ļKlPNqr = Rk`4| E@OO~|ȣJξ|,ż\.'0N,! arPy٨[ |pw`ڪ]۶`mA}:}:\u94y ;"܉7|}l KTm>p#H0> `40 P Pޛ1 :JŴ* 6` @pp#C.>  ׹]}0 b <6ϰy!zlL JPZ`RL݂cmC1sVDnu2}ވA eߥi6g>syy~mp~#^a4p6狮藻w^z+0$\=N@lT,VB8W8 nҴ.^;|ʽL\ ^ > N. ~N.k 0ٞ>m~o[Ðw.j qwK<ݼ^ mȈ|\ I]/n<8| ZM =mL,R k@ ˝#O\ ۾nk#> P k^En`^ޮNP^~:a~w^*oZO_Վ,"pW&m }Ź"y2l5^uM, X|YUl_Q|? ~|ݾK_mJog.'>LPLC?>pV .) s/5Yi@O>(@'~%kVzo cKFQ^XfvlٳajXce[fΝ=6`•J[7VԠ][lڟ f^nKqg'g%H@u Q@0&=X Ҕ#iD);˃Y~&NJ}*߼p)ջ{D ^ K1L+*O#ĊQb BBL -$ ;2Ec3+CEwGn,-c79,Rck%x %'%% 9'.NgXO<2h`"Ԩc)L0Ӽ1?ѰZK*|І%TD-h1HCOkT5VcI2;q CzTE$4V_V? =H#\4/݈ٞ-MS#3mU4U3p*7j#:hrW2jWȞqNvPmOr,lGְ3҂RHdQT</ TT^;lUSw꓈f1rԘ-(j+vg9h팷":if:jN(:묁84/\hZ8Cvl{Tun;溺ֺ﫹v7tR.l`#_3[o5Gr/oivdwJt}1>SoƳ~i~wBf"; 'P~e_%8A Vi\Dx9N"+M '? Ѕ/a ]AA V<<ZˈND&50 D&614Ě oȒfKw WrkxN&@[ _u$6!INc8`]!\RG.УhSF(`6;Lڈ,:6ґk~6ɝ)OG"E1e(E)4L6MNɍusj .;ieHe|}^dlu _ӛ3ZLzQ dM`2rTdlBFST*" UnP8q͛} 60p/,IQVT$o1arRPE} 7,a%Z.q7%vϵ ~=7"L(,Ek6E0/ʡ*zܔS R2̄DQ# NTPV~6nLlB cru;:*qD:R."GU%jOEv8ҳ9YrAebRQ-Kq־Jz:MISbYtbIʜ(]* +iHC[p,MqRSO:qޠTUZC2A;&rIezj嘯4]@u~{͒+&i#1=Lyd[4q5-|/~=%`Rg(,ab+LlBw3{ި k߫YpUfާ\>=}m ND3 n„ӟ6w3v' ta/P?ÿҿ3D` @*)5J T@+q@$rT<9CL4(pA.0(/!F{Z‰m-1: q-. 8CH1J1y>hA/>?Y@'B܂B'َiЎIXDxi-(hI= NjQ$E@q:Z脏D 3I8"E+a$F:T@ :x4$LH19: #JE+r4G9Tteo [H<.(,WB2#4LsX9ƃ񙥋PkШ0&.ۈz ef"y½rb knI覻=0["ؾ]IՑ)Hʥ$E,L:#x «.PΠA$K;,hp"> R58Т,Il"{ҀBB|ڈ\x-io*BX.#犮̃ڮ kP#/r6E"/ r ]M0[*Ty* 0ꑅOb00Omw0(11t12x1H27Cʖ3-ʹ)92Ӣ(YތSE2W2 ,㵅C3#>9_[V!ӝ\ck3&[ɸ:K%R193˹} H]5iԠQX^hI齟쥞^C X"U`p@!]i_E  _%E)Ȁ&P[ȶԛ d! URPXC`M(Ap[~[(()&&(U|VFoݤE"OVbn_`AE 17BBbj,PRyBH$%fmBc89(EO&mC`16y=;tNDcP6Fda(v9NWXeZMO}#)b $~ $+jBWV̏\ؤ+TUT]jTěN(N\;LuN,ۻkk6<*d] DLnGZ6nz//GǦ&d-QIޭ:2ٰ*6Oyu.ry&.;PJ /\U- PLPPAe'E 3Ѫnhi zQэI 8Fi6vl6#<|Q5@Q#ҞI#U.!X%' "3"*+urԔJo-Kӌ Է:BΝDmn F3H%&4I]vDLfWH0S4Kmm Y5K. zZ q]eVUXZYּ V5-Z[ V+[boC6 Yo ևilE]E~Gw__puHT6C7rs+DX7r7zQyPW ~Q֫5E5]>Xl[? vUQq%: m kv[;uMҒjӆmF8;1w ^}JYOӴ˻Z/ngZ otb[rǀmȔF[M+)*zGF6pat ƵLܣܼ=G }xAgڕMuu5 ^ݰDEyx{ψ^{{޼  '|9GħWw|aǗɏȧͿJN? wlAܻPnqvч|%ڷ}ڧJ(ia/Cᗾ/!0$PWܯٲͥ!b_< JMWtPeȮ%Z6RȞH٦B%]N&{eufgIcV'4e'hd+Xp' ?1Dbpث6aJa) 7r#Ȑ"G,i _ dČRʢɜ:wEO%4 "DQz>7XS^"Q͠'Ϭ:WL4ӟ< [## r\[#WI)=e:6R߂S}TNB1) azԜ #C%eQ':/VK#SQx(*7Iܸ›?|TD64N$̧s}鿳o#s#y`Ob -0$(HR-XTUd]ViSDf@\qevѕI8bA춑,l3Aގ#TiɑEtHM$ŐZA =Y_)pIwZrey+q@/ʥpbTfFm4 rvy&zYy(%Yq %y~&:F>a%B`p 2UYE#4VdcXB#fZ(ry y#TR&+U k!GdUiVS3WMjm,=KBu1Zhyh2{VBfImy8aql& fL0$KJ8p~ Dn q>,w'\0gz'/XΤ'cy 3>!H"A'r&8#3:UqTҷ\󪅯dAg6N3h1Kޫ-YT߲crԶJ֘ݤdIsoqL7+NK)ܥuAUӍʣ0t<+LF>90-%%*N3$S-tcHtDa($ bBc2~ɑ"4t[^GIHуH#ƠN}*T*N^/'YgN]up~ DC,G>o\;g= UdQGx7tU``2Ǩ+_}buN VR#YKS:u8*yJ  詎s1!=F(+RIea1vzOO tmIjC&=.rOr2}.ta&.vr$<.x+vw=/zǙ-}/|eҷ/~_Dw/,s>03 ~0#, 03 0C,qVIVc,ce&SO>2t ! y;PbN~xL" 1GuEsWRհws2̆Ḵ4tMhm}X'YpVK͉ hǂ .UI #QH"% 'em YHیIq+^)F^Zڷb9HG=0~̃68cLj٨Q6!Hl ^/3R$Gzw>\b)mZfbdqm%FlǟITv5|$F eUMP!I΁NXec;K.4O6Ec;ɶ{9oo+fFPFxOczW <Jc!Mp E5̋Zʫ`Po)\^MyYqDJknR[ l!I2nɥyhM6Z)=/GVH~諕Il `<&8M ^fdcF2wU]@F[ukUߨ$i6 ?m6Wlە :WAx#܄^ots@K(9=?SќgK}wKYFP H )# \Z P!p d9`W-h"ި`ԬmĎ Eaҩ<)-%}a\mDaDOb ^ ݔ }PݎFٔH!TMނeQjBa)U5WhR"!\ޱbW"RqM1 X)-$ͮfS R'KafEf(ȭU% =ʅaRRɐ.i/%`--׷e3qai,6Q3N_Mҁ$_tYBR%d%2 r "mMԵU>] @őT]F4T+?#&T]%#! LNTDUJNMLG aB&PRxeC5@ (",«j3 W!bhuX5b%Y-M_Yn UBr#ݕ(^ueVWEQa͠*cGɄj0e6i-N@iEZG~7Be$$2l1XmD_neZ6W6/h"ФMNUS)dz!9rkvT6fҤ6z=W!Rv]W-vǽI|q&g,ق%Ԧ"dCfHPC+Wo*jdjwRJdC6$M2}ݵ~ew{%g602'~Z'|j'(( &.~2>(RF(V-9^(vQP.}(NJj艮(^Hx2Tnٍ^oYYFuT͑S6OɹUĢIڠUڟ֔nD=ģ&>DBtrLyE0ZKD фMHcw֘͘mͭHFƯ%<^Fu|ٙ>[`UGId"Mn\gH|e[̛vtuܛvpǨ>{]ؿ%HqڑE]lG8:v[J%Q\nFia"m'plꥂl+l!1A^M ]G _) 3jX1b(]O)NgJ]G]enNi *E˴aYV~x+c!=O(Kb `eXءhgܬʻlŲȑ^De%^-/8㕞ca$+oL akmJZA]e$GFj^8, U m]lΎPݘl`BOMMl]e<6PZ֝DҪ ʔ9&^aZ.I"Xe^ӥJbIjmdYAh~ؤ`2" Zjj *b(KZ(}ɚRU@nP(6J F)a H.L<a 1 ©1>C|kDaL!a>5Qm}XkcʡR.D$W"^,#$ kj%/&'.("NՈ/FŖU*#+G[ c2-ԢRFb3J{tGbH 1vm. k5em\.yڢ]^Y"te9nՆ):S:ɚ? KT+8%B9>U@Q'+`X[O"M%?H1Or(a.DC"DLUG\䑞-*$ӡad0QQK0"1K**$$ cV(YRr5%ZYT:Ӡ[ G\ee=_X^Gf8+ͺ`X ?Z&Z/H%0k\Z\*fq^60. 1sOu5mnz5~6=Q)Wk*L7zM۠" ׄ2)qbjToDUr P2ds(k$*x=Vw5Lwun:ͳih::Z5^[[[Z^`W{IX,`/6c3WWa'zuc_6f{~n6g+,Yvfh''hi6j6kj6lǶ1m׶m߶Al6ommvo7qCppr/7p'7sGtߗs6tO7vWuvAvv7Uuwm_7ybgz6{7~yp=Təf{k}wx7u[_ⰱmaD3}'18884WWexg87ּ\ Yܬse 4ّń$lS=\88_h5u: p65XC9tmH'{LuMRGg "[$/hynf#SWUy樣F찝y3xdu)aXsXk<9Ɠ#:LzWVCvǵklh͵:nQڑ7˺gg`dWų_;Fy8o\lLI\u7=6_O{{wr6/|S;[߻;;;;;| <|{Qe^fffguUjz<'e;GlΦf'SO s:'tJgb7V'Jx'yg_dg5߿'}ggY'Wy͡G>]sױg׎vk2|y\ w}\ď$%KGX{O#/? &t5 4"<:Bzfc/D ?I,Q:+@ zB%3s [>د a!]GF +gR#h % bZÉ&!p)ьE蠱o;W"  //HXϙ=Iu?H),c0[!Q֫6$=UIP FH BykA,$ ʯUޛ\>W(B 9MuX)ba#   ]8xIA-4eW-aAphLpԄ/2 '\Iܕ<ꑑAR Ip16A%-.uN26#"dmԡ*mKR/}LS1̊!S$3MKT5MaS4Nq 7ٗ+Dt;˙= xc9g:9u쌧898wXg>}$ I;x*ME˲Pӡ%>'j|5T&Ţu)X4(t4~۟ئciB8к./5UbQZ [Oj/)zT% ]*$k Bg)E[weD -QCti.t&Ŋ\۹+1o:9tUbVn6(W&=e E Y.JYϤhv5 jB[=o[7;%qc\.w9es\NW7ҥuec]nW5.uo^e]" ڋ 2U/s^$d@[!̀2"U@_ V*d-  HlB?B%%61o٫0}zR( Jžan. c<٘ƶe %1~F4\Puݏ[gB"9zy! Z[@ݛz26Koy[ﶷ9ȸ[  }x'5Yx!N3w :' O8$3qv㰕E.L{Ǟ'Fh)A("1mD|Ni D(LFr jrHFz(9*SJuΡ:8^fpc34Ӡ?IٍRsU3@^ YYPXw3C;usYS\/3]j]CsW^D'g1D'9Ci1`j`_a] b5Qbb+T=cPc/bGGADvdddQVeM6QAeQaeU!, g2121212121212121212121215.8%7FTqw^ P A : -reZH=6%  &@)V 5] 7a9b9d9e:e:c>]ETNCY:^7c7l3&t,-z)6~):7>PIyjWrdvjmt~rfXH>|0x(u"ts qrt { ,8BOMKJJLRY]aeelv~Ǽ±ʹܴ܎׋ф|rhd]UPNLKLLڱOիQҰXѮ^֫\H*\ȰÇ#Dŋ3jȱǏ C*ȫ(S\ɲ,0cʜI͛8sɳϟ?[ J(W<8iӧ_JիXj(ԯ`Ò bӪ )۷pʝKn͵xDZYzmkÈ t1ǏR\W_%N SML6E)gM>۸sMߧSJϪUbUAfNXi A~ enF_Ͼ˟k-Z?jHr \y M<]"mCmCUhsѧ2 %ZbE aF(;3챕*Ɣ d 4GA^㏗eDn)+(@TpƊ7QZ$Q';UhGYpB# d-`H&sD"䟀V䠄yJ&h=M rDi@[(^Cyy`<[ (@{<B'dt焘#y d+&D &,FB쳤q)BY,(gt;Pr+ dG>I j68!~xoJ$s 6 E)DlqF*:y-m-{ #mȘa2 Ӭ; mVDd2"F*h@QN|nB K!(A3< B=рV/ӊ;$qNG VJ^zn;2"֋'{7y;h߸GnSҭ/|1_(Ҏ?Dx-,觯q/1 1> G.;oHAzπ #>TﻠGX4L W7E Q?As! w8," OCH\ydD!BHDX"O@%6ձH(*6Č"bbB-pEbэb >'j9Wɑ䲴.L{XҖAa64,'ΓN51ap:A{tz6f@R˪6+XϚ尵,{2$5U H 9&6e=Z"%-2,ٕwj6Qvg>E9&t\X69Ё{KN87:t-!stx|w\]1#:ˉN#誠DJ>6hG;ҥto]GhOއU"n{|(D{OաSbo HT񘧺(B}t/H$һ\|`71?^񵿽ў~轧2<1ȯen"͸|~sXgPOOOϿ_Ta}gnhODlԖ\68Xx gmH2hT*,؂.02=QivivlmMJŗJط3JL؄NP~>omfkVF=g@h|EhᇄQXfxhjx?jfll%VA(6n'}@q8X׆ohw %)tΦ|8~h7R~"v~~װ7w7H (G  e ~(}f8 '0~]`g'@G8(ٸ8h~8h8 TI (9>jpmLjr spWdFIY1~~`)0k}%yw ,,I 2鋦88He QHE *iF<~9iP1وy?BPj~cY` ef}aiiHgkGpryg@tP7p]%,'[ & ΘxW}:ULiFy ;Ќ7YyAI iU~IЕP8 X 8 dٖHyf`(~ Yᩘy⩟9  timGqI%àv7.0- S xh: ڌ)~) 2Y-ZЊ.٢؜9ؕ'Z~<(YH%(?1:XL0exعf9+ y`]` 칦m9Xi0쩐j_J쨐ѐt o7q JT`#)"5c#h47!JXz5IWVʕ++vp+z08zH٣7?IGؤٓȫx!ʥQʝqi)䊍pi Atvz'IQY)u@}Z"*s:.=sO"WEӁG}!~%`B&W:JjPڤ89Y8 ~z飸؜CJ~ ~I*)O(ٳS˓TKPqj aY` (JIup7Y s9}˶Ұ'my qٸR`%tNDZ(QW8ZQ~3+ײ1#0ZD?k?kبE`zgOkY;ʳY;Jx 9e婸݉ڦ)y9۷IKj׽8 tLu9WR-5zK ]`ZEX=YXn{ΉP99E;~@*I-n hjlʵO)Y؏HZ~x{w ~:@˟ ' רD &+q7wʠSw&r6|;*{KFUK4ZO*:ɢ!˓lŠQxx,O<Ɋ UO(9 kmᘊSé`)4J9r;$+)`f"v$4q9sѱg( +y籤7r-`lNۙ}WY>^YqiRΑc5B.cb5m~辱ܬuS5bWrP(7%*-FN㝪2^N~qi8.9 r .Q-u`.($*pvr%9N]˴y8CcjB0Nt#M%>^n@vAǃvE]IC|ޭ ? C_Jg /S_M$82݀Xfl}"G$iٕվ.eoLj<(|}6Jf>?q(ܝnBPّTn䈺:_j̆h_om]Soim9| p8.wK9$YeR IU}<r47rz'`f%R**_9!s3Ws7Uu0C惞Y9Z5at3tKttWqse?:+2_0unw{,n^^^֟vmz~"rWn9C aڮo@T @| <QDSQF=~RH%MDRJ-]SL5m, -lnETRM>UT+E= U U͞EVZmݾ+@?Ë_\}X`H1Fpaƍ?Yd-cYfΝ=yY1hҥMF:&[lڳY[n޽=^[pō"k?]%v|vݽw<"ڿG^!om~|l?~0ӯ<D0A#"0B kp&0C {!61DO oDOD1EWdE1Fg\EoQ%q 5H#H3 C 1j1I%Lj 7H!4I&+-iA9K` bM7MtL*!.hOax9D4 wq402R&Ϗ3,BS2HH#5r҉,rHBL"aSW<5WQ4H%TPՠx03)NE(]% `C.kՈ,[E7] m[/tX!!Mhd"`6Y?=XxP'X6aiƄ.&VtMi+F9Πaeoн{Peo.-Eg& [.&hmCin-㦝:jrjQi0{© l@;mѴ>禛3c7&pgg|%ARq'O||\ о5~,u.}U@Vߥ@ ˷:ЁQUTPZT@ e"lz?AE,BD ""SQ„y)[ Bp@cqHD#gZbDAQQL8$6IPkF>f%,F8:*^bGJfwˆ## )c}R;$TVPU"IUҖ9.! 0ױåP{Dr* KRY!/6в{'l.Dg0MApKIp4p`N_3 RB)3YGq( iIsReM*-:UuŪ<Ӎԩ2kJ:X5n[e*I9|+Y*:UV5qk`RWVu aЮm'5,b%6y&Ŭ*ۙfֳgEЎִ4BjUZN4=ml_2,ֶm];.^Od le;\ǽnUm$_p;ݒU.Ɗ< *uŻ^72ؾhKQᲤʷKxˑ YzŤH+nF&BM1~û_ Bd#S[a?·pn#St%ΰ'N%,hLbSSd#+8>ʊ6ÑZ25'bb\CXrM*tfSNAN''` s3&etnkUKF7:А&T C#ũ޾Zev)6[Wzg=[TB-v4?}UzO *z¶nSpFvU aԳNvo"Zז ]mlw)=玌3=#7da z83w߄w*R?bΈžVC>dxơ {kA 0Q1JQJ Jh!VDdKI S"!gE͙5`ϷT{{v\CXRyu qҼkU)%<@l9PDHb0MS,8pT},܃x{+%Ds@O2!ʗMUxfo/z>ڦw2Z$?1JUcBuHf6E{lS)~o~/e~߄B,p4TBYZnC,5 ̩ x@Z+z@At+Az5j6\Ao%p4+)N+Ax*0'.X2qA` «B]36c$@BsjB V)|N9*l5rz##1:23B2, 702*'}JC3$껗%iþ+UY.١=? D h(k;c0#}8D&h?DFs.xC~tKDKnj$ÍHHd?LCkd,6qBt"'BfCIjɂ")ɞ̴BD J#ܵ)JϺ {ʮ{KxJ 䵲,a q$r$˪'(I(lKKr({ɞI4(<,qr0$-ģjz5,4LG6 A MMt؋˻9HK@Ԍ-ѰL4tpͽ+Uk-8 FKKMM|[<Sg؉DXP,Qpь5mP=Q %Y5Ya]Y%eIYSɜEN$%ڢ5ڣEڤUڥeڦuڧڨ%ڠmګڬZZ&گ۰ۧ%۳E۴ڲU [0J1ۡe$ۭT\{[۬J]N\ \Iܫ[QE\ .h\]\TQLh:ܤ\9]uͨ05uuZV=Z \_(ڵ]9^U]-ޡ]ީM^VtN|:^5EseJx@ `5]_M}_O}]_pӥP_UXe_ ^uFmQ&[6&ZFa5ia_PёM|}anuYF &b!.$v#%vbfb y)>(Jj#J$b6@.V/K4ӻ|J23K4V*Jq7^ۯ KYT;ss5\82M3QI(\B4E>Fv䚕ILx\=-T?U g*ZLN6ֈT1;22mmf:\::fmېmѐ3޹ffې:ѠȠa\fʼn:f\ҳf蹇\ffmmmmmmѿm6Ѡmamm:f:fmm:::3f366::36::BCM;@Mmmmm$mmmmmm$afff̹ѫȹѠѹѹ36f3:Ѡч::f::㫅::f\6:ɰH/:ff: BC:q,,8 ɓ۶ "4CDN$Ѷf\6.(&家Ѡm * KLW \宐mKA6aTB3aс46H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sϞ; JѣGDʴӧPJԫXjʕbU p Hb`3@"='\SG"vPٷ=KŐ( `wqސeBrS=G < p`"gh.xz ȼ@琟C}^;+JrƑ5y[( ¯ - #BO^n+H/`q/ZA_x s#y0}J`D:Vb`RTu8Dž-`r@ZD"b'P}@br4t݉p#q2"s$p/vwJbfKFX0Q@^Y_~ B߂u`}yLFP &_^'P G uX] \$ iAJG4˅ unZ꒠jʤ$B$ے~AKƦؚ ;لi`%f=I؀آB\a v%[Jk6Ɓ `2Fc *,S (q$ZaeO<8G*Ib ٰuh@*Ƴ6G=Y eȤR"YjAݭ-mr '9ˬ@0lߘTaR0Z%WY`mmR&Y[QK&; _s=!#p':%:$A9+*$tǓz"ޛНzA-c'8c4n2ޝ7/4,AK] Jٻ~f!-AS+.t;=dl)MM@;C}.lO OyH@&hmNתƝ8H9P$Jfs`:`HC wKQ BV<2q`-}Yv4佉A+|I ɲYzE >;[W}dLE ZM Dשa#qрT T(N wDm# "AĤj-↨f M^SִH z S-DwB c11q;&ú52}F8?,)dR-ArhH`Lu˄@>f8`]-Š+N8@ Q ,[''Z=9O!`Sٯ:b4PhKC~"OW.QvQRC%Zbgp& ^⑂_&2g0rϨȑ%aT*LbӼMgW1A8z9oZ+̩Rrǥ:CHP0*T2ӭz[*X:h*ֶ#J׺ ׾5)r `ְMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMru;:ЍtKZͽvz h+MzK^O"`0 d s =0ߞW > |ГV / [2!=K%@hv@kS\ĠaW &F1T[0F}Dž]7`%3@= =!rplyRKb x0@_ ࡰosa 8v|>  -뛂  .a ik"s0[HzN-~-gXȌ-oA+f<Ę26bfq X-gm%[Qò:)k`.sN|n'=A]ڰf  ޳1MgfZЕ8Mv:}+[FmO`%<$8 pj17kh2 Pv88hO;ʇ}ݒ9(&_r_{%vqON hS+8f'0`CsXT}pІzƀz>a)8p~`0]N_y}޺@_$hWaL"Uy2eX} ݓly$a-y7^z[%3U+3۪irc!B.3bצ@5ZAzHJL5=R*MZVzXZ:Yl a@ [Zfzh>ڥa` tZvzxYlp  dZzt =Q q :Z ک zڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;[{۱ ";$[&{(*,.02;4[6{8:<۳>@B;D[F{HJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@B;22mmf:\:3fmېѐm:޹aʼn:ѠȠfې:\ffҳ\蹇fff\fmmmmmmѿmѠma6m:m:mm3ff:f::366:::36:BCṀ̴mmmmmm$mmmm$;@Mffafѐȹ рѹѹ36fѠ3:؇ч::f::㠇::f\6:K7*0 $-*:ff:۶PTɓ꣮ CDNR3ۿf\6Ѷm/  .(4家ѠabP((4 6LW\&D宐fm %:M,3a ѶH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sϞ; JѣGDʴӧPJԫXjʕbU p HgbPS='\SvPٷ=K& `wqސeAr=A ; `"gh.xz`!ȼ@琟C^;+JF6y[( ¯ /$‘O^n+H/`q/ZA_x sa"y0}F`D:Vb`R`u 81r@ZD"b'P}@br4t݉p#q2"s$/vփwJb׃fKFX}0Q@^Y_~ ߂u`}yLFP &_^'PвG[ uX] [$ iAJ C˅ unZ꒠jʤ$FB$ ے~AKؚ ;لi`%v=IؚA\a v5[Jk6Ɓ2Fc ,S (q$JaeO;8G*Ib rl@*Ƴ6G=Y eȤR"YbAݭ-m:r '9ˬ@bh4g7fUXLdeU*XKG|oA+@䅯i5[OH%ɼN n$ bЂ{F"gʨ](ȅ"t& ywGs؍8̤w KŒi-DbfYH}NJM)! !(i}m=M7]7&G6SSoI[ӵqg@?)~683^}XrHBrx]n)JAG&0[u; >΃^AĆdU,K"Cj" -۾z2-aQRFT@հQqX@VD]J'KZG':6RNX bSnqCS3)kZა#Go=O Ҋ;hHk{s{!>DVQCB~B2 Dr$ /Q:Hel`yENFgeK 'KDsWQƄ7eBE \{Z}Փr" B.=ՉA9-CN 1.TeZiP)؁A ɣ"u 9Yló(rdI( "e;4/S狴P:]dVPz:HU D USڔRX͊լlg>X:-dMZ֑]m\J׺p^Zס `Kj! W :d'KZͬf7& hGKҚMg)PAlgKͭnw pK\в-r:ЍtQ7l#\{z x\w){|k6{n}M|>@b '@,z:'-2F@`vB B[b".Ė AODX? @ `>Fc&9,>?n"# >irIPXBh@o܂E #n/},Na b1ğ1hX՗~5a:xŐ>[ < 3 ܡxƁclfk 3b} K9 mىmf|,,"-o=i{d.vb KoX2 M:ѽ30cЄ$QXz8yq jPP( Yb9 PCxcn2At:Ae 7BqMG}L7:tW` @ ?9-psNX{w ú#F-ЄH e(< J@FI! D 1ݿ׀4uVm᳹>ԁmd< v{s{g+wIKX輻|o]Sz/p'(k$FcVa%krpyT0 @ai*Yj&`j(aw1-$ix{{}hoko6<dcp&f}TG}`}osle ڠ` )EJyڡz[G:$Z&z(*,ڢ.02:4:pX8: \գU]rB:DZFzHJLڤAR:TZVzXZYP[`b:dZcڥ^jjlڦnni tZvzx%~rzzUʨ:xgxgpI_ $ ڪ*+ZzګڪqvZƚ IpvڬΚv:Zgڧ֚ں!,>P22mmf:\:f:ѐmmfې޹3ۂȠې:Ѡf\fffҳʼn:f蹇\fa\mmmїmm36fmѣa6Ѡm:mmm6:fmm6::::::3f:3;@MBCM$mmmmmmmmmff$afm̫ѹ ȹрѹѹ 36f3:Ѡ,,8ч::f::\㠇::f3a\6:f::f:*AW̐۶..4% CDN*@Mf\6ѶmSblѠ((4 #KLW宐-r33?f6 mѶH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sϞ; JѣGDʴӧPJԫXjʕbU } §b8S@=9\SGvٷ=[.ȇe li^`pW@0q24=p` sHϠ F٧ja y Hw%"I e&8 9k s l5h[ֽ|9EKď00@XzGud)Z48QXAu41rFCZ'PkmH(Ru#d"yFp.RWr"؈#@L2C,p@*\8v)(%,A{ @ށ)_oe(Ae@, C И}iYn+a>2o!lqCZA( { A(4\9 ȝ\Hަu6 jwAyV`Z;}cp'WaS$A{lDK q-^){ a K ",D:P-Fajk(R B6Zat94]CRbul)ŭjJ*H-YdǞj+Yhlq52$6'@v+GZ1Kڧk9V\Q&z2&Y[P6hlEVՃ)6Sv ) 5ճI9J>b̵qx<ě@FhxT8) q7Qrё-#R@@ueH@#8\ٮ ArBjhКķ8zZ&8P{@T7B4<_PDY&PSc,p7CM8dg`XAFBi$1-Re MOڙCdBĪH5 B )[f#$$D5[P/MQ**>`kC (BAgF4d=+G7%9Āt`:ZD]* %A,%c~Ҵy}ٵpm]q@p-k2$%{'a\yLC j\gK>"9r-m&81_ٔ(a(FSFI0G=8?`71 iz쓦HԦ$ڻTRTJ!SuSծzfUWҜьhJXŚֶpZ׺xE\}KMb}r8H>KZͬf7z hGYȚMjWֺCj1a2ͭnw pKMr٦V`tKZͮvz kMzw}/u;3l"|>n|l\֗ x!L;vZ`Ik>Icy >1qqyL.vā` U`M!0T,#7NcE'$xpZܠ});i *#X`e9fFc e ` ಄%rO:~ŵ8D D ac3i"f BSsèn `<s=B&4a[Ă%E?acΎ5l]=m.hr p8B=72n=n tۏv,m3?Vht\Gu|{9ސKETBh DYomOn+ tܱc;Vǚڎm^mji{}ymj2p ܴ>(wmE &(# mF|iVbih;@ϐM::Rlv+|]_8v/ni'<^y.k#<W2tK@@zSa&AGy\w1+?/@.|ڡ/(O1V߀ϛ^CF;;XǍw3[fxOzPJ 7pk 8N֧2MW?1E뽺Whkvu`p '}Xyr>vm r&j"b'vyB`6aIa&cy}rџ ڠ҅*aꨕUj "[#z(:|,ڢ.q0:4Z6^ z:<ڣE>B:GZFz0GLڤNPR:TZVjYIW\ڥ^`b:Ihjlڦnʦfzo:tZvzxzq*yڧ~zY/@ @B;D[F{HJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@B\22mf:ېm:Ѡffffې:蹇ffmѠmm::f::mѠm::m:f:#$?AKmmmmfḟmBCM ѠKLWѹ./9:f,,8чf::((4f::?@J::f<=H:f:۶糴CDN..:mɇFGJ33?f""ablH*\ȰC+T@D1Zj_Y){e \:`3kQ&$!q2thf21!;@fRQC8فgigh& 0ѳ$Zr_7/E/|UrR\^n8 Lӕ^9vIt89ENS"S´/L*5_1bތ%96xSYp0`[``? ;;):Y]Z'=ҭSCz(-l*֩ (Pج9L* =Z)MOXј SSm wRZij s(ͺ"ڿ?/d:޲;n#WT ,]:96*mv:<҄UC6T+㥥7<%y 7zL5E0sBbJ{ 571]ԣ7z*X[۱QgX28!K#ռٿf`zfL `zGJK@FU\`dqx}RUXf`"%3Lyè%)7yzL`zSZjyLy곴fy+/>9?Lf`fyzy⥱'*9{H*\ȰÇ Hŋ3jȱG'~Iɓ(SB )R˗0cLɲ̛8sYΟ@ УH,jTӧP?2mի hWŠKٳhӪ]˶۷ct`ݻx˷߿2ݫyW0˘2̹cb+LҨSeЃc=-ޭ6ߥ 8Ɠ?F`rA,fޜv^Q"os>vxW|{/hy*@Pv Pu=@ #d 8~rPAaw}h8\hv׆i j@b9 `ߑU8Pu:ޅ 5m BPA F" t)e^8pCg&ހRaf7t5 WD8@Cꉠ0I([pfh'@Z*'wL CN6j\ ) .k 4i0q >0kײ*Ԑl6C,[؞n!,22#8>K @FU%)7((4BCM 곴..:9?LKLW33?ablH*\ȰCq7&zMȓ+_μУKNسkνOӫ_ϾH˟O_?A(h_& .X`Vh|^J`T a$_&~J%+X"2Xc)DdH&G.PZd}`T @\ve Qeh$e `t֩"rj]f0@| P``'iejYe 4 4:gBj*WI)|B0@)t婸0r5g"@k dpC~*ꬮ+*@*[*[eϚZա :pg~ i֫oz xl!B]k‘" G ߮,V+wR$'}2,^TX!,E22'((^_`@BMBCM$̊ $@@A?@AKLW,,8233wxz((4㶷MNO NOP ..: ɽ  33??AM"237./:$abl9:DCDEH*\ȰÇ Hŋ3jȱGCIɄ\ɲ˗0c|rfrS@ *ͣH4*gϧ;JjPJjy)TRK l# U+L=+t(!jٿ 0wY XU"d8Pg˘Mkbm2R_s Q9g̰c;dj@` ε0( .P@b -{Y2UiHMA.34`w,v+8C7w[yw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:vD'AzjО'yA~ZП(:AJРD(!,_?b 22챲$ABM̊BCM?@AJKW 223@@AxyzXYZ))6@BM +,8$<>H$%1%%2^_`   '(4JLO窫57A 89CHH@ȰÇ#J$‰3jHE Cȓ(!*1˗ 9@ .ɳϟ;cМYУH ӧOJիX*:`J ;uiFcɪ k k#ڸxnުs8xRE'[k݃,{Ub\p`1b#\19[yo4xq@:sxhP@8|D Lmcf 3@ dx: : & }Axva<@y8lUA 0@&$v^d]weU50|eVfi5o'iI T dFb-ԜvV@27q ,00PzTc8AYT|JDA1Da#p&W%gs!l@)lTu %梖B7%UCԠzJЦiYpF:}Q\@rjEHJ&KpT,*+i,NXt-n+.h)T‹Ӽ 0pE1+D/'ܐ3$P Cl1B_qA!,_?b22@BM$``` AAA?@Aض (((IKW'((333"++8wyzZZZ<=HGJWACN #EEE02?--:((4PPP '(457AablH@ȰÇ#J$pċ3j@Ə CrhQɓKzDɲ%A0c:pr͛8sɳϟ@+ JTH*]ʴ) J(UjjW DJԬ[Ӛ%;ulu6ֹ  BIb^_2[t 6=EJPJ9ܴ @APHS_5 !Cv*aYS\`B@ R,*4DS. ʫ* vՊ# ``aB$9^p;BBQZ^%r5eVc)@d|pgp D |i{Z7y*^p]R%b(8hdK1YRFcEtP 9_} :7_J'V1jrb5^y3%A =i xoJp|$F @RIPm(@ZTn)TtjvΖ]d:Uj :gnњ pRXF!A|knl&ec%knP=[M@+R@!,E22ѽ %(5=Mq $MX`4W((4BCM$  #19H++7..: xɎ󄗨@AL6>NkablH*\ȰÇ Hŋ3jȱcď CI2(S\ɲ˗0[@@ɛ8s9ϟ@YisѣHq ?,ի&lV>bKT @W T`c@ڵaÖW˻lMI`aA@۷e5@bH!B,L̺5¥Р9Ң`@A@ma BQ|zEi]k> j]& q Pԯޡ`@gj\%Xuxx@ JjuJx@|(F`A* C#oդ8b՝agփC / )|@@g U-l6B@@i & rZFp%nH:EUm`vsʹ5gKm9A$hn(Oj0 HvʐZ5`8!p)yDZQ P`?F[ 't P 6A;l` Vl уv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w3@ HDDž nG|[ݶĶ5mO\[6ŴUmW<[ͶŲul_[!, E1111111122111111111111111111111111112111111111:&:Y 3?"!$$4.<1F3P-@[GRh\bpjntlt|pxq{syowv˷ռx޽icfu݇ߡߵݴٳطվ H*\ȰÇ#JHŋ3FDZǏ CII(S\ɲ˗0cʜI͛8s,hϟ@EJѣH*]ʴSAJիXjʵׯ {ٳhӪluE-R;"9EBԫM=ѭÈmb"6H` UNPe}]@Hf՞N7S?*; 樐 _ȥqՉUh5o*H﫲*T>OeM#vckݼůx0r_dvLu9~!)u Cio fXX\uȑ&8""Tap Tu3 cjzwߎ<@!sFUBvT RmڈUwPnh"CMNu'uXV1B*PtG@dqf Z uYv`n`!xf{ɓGs֧E6Jin-z'E!(YqtE #0֩#EqK& jNIҚSgtQm9 [tPZC*wC  F+q*@&kL&&J cܒF[e1j,&nНR^g wTWVl1N\TpŏAPqe j;%+SxFFfP/GBeE!ԼQZ|C]d"8W>)uc5Uh&u(vNW>:B?24R5oJiBЃ87Ciy>c6M"PBYaNN@+Pt]2v66bp_Qj.3o;Fq] \MAgѶ )vy:V*d$sWuqY|5d޾Ͽݥ=츹26LviJ@Ż9 Xѱ kC!X*WVm)i"tg2K꓀%.,Z0h2(ѩْAZJ&P&+ ~87/S9$V1AOǘ ^ א`pX|'9'x#NZF=>v ؠ?Ld$'Iɳ*J%7Nz)K(7R,}0VfX%(!^ 0IbL2f:Ќ4IjZϰnz,ʾIr)؇8v'T8Iz"=~&$@ZOM7 zP:d ъZ (zюz8ђ4!McNҖz2SgfR'@c:wJ NAMR!@RJQ`*>z  ֲ9K@ֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xUBMz|Kͯ~kN;[`ΰ j0{ GL嵁V60gL81ibαL"G,{PL*W>豓^"TV3e ' K2 g(̒03gZʀp^滍D(9ςfshGY.=a3@.Mj3 &|@ؙ(P,g(sQ=YҴ<5Y}H'xذ4Of"ս.5lNw^-bY}>y>{;7ln=v gwmonvq 7O% D{a\ 47[޷!nv 3X@٩tG@WЬF 왷@横9k8̻Yb'NѧO6Y7:>غG^s4'hSnF|NcIsn3ǹswLA" Oy[rN4vA3x|[گ&3 ʽ՗,X mn﹫g::]~5Hyf>0f[ mS^y>~OruZy}SiW\(~3!0j20jD H_vogxwrćzwHs~vnvGl<ׁ#f7x׷Ɨit 30Y<(_xwjVF{fk͗^fwFs#is~=sk3Wkg@{փee8tGlc׆pafi8qx%6{xf5ȇ(ahVke؈ƈ8XD& 6^[v6PX*Lb?N|xKA>f؋FMi50A!@:rGCGγ&@'[rF|xhmd`0ah-(nЎHx!J4UfmHzpӘ*،I*$@11n+pCd@% nVIN8?H1aq! y#TUm7I4Ǹ6#xBٔ48 Vy+"$:Q /1#:y(<:X;۪.Z(ZO;ʌ컪˺][Jg;,!xz֋<˽{!y{T{[[+b epD+šr\(̶E۴K ۷VA>\J{ʏ 囸D\{j8Epk|<\ E);a][+Ŵ[G*qLi+FZK5z;ks ƛii zȿxU̿cX?ʙHKH,VLn4˼˾<\|2 *MK -2R)ĥ{Ρ\LʍlؼHk+ŵܢ[zպZ˺,hKiK:,̫Ώ~|+^Uk\-ʘŎ[φ8x ]׼ͮx\SkǾۚ qݪyxqD F-ϸL6|c5=KK[Y6@ ӱ:IK[%K|~{m˙:+XQOhm ŝצʦUhC@-lI @8R}9 $K{]l)<_2 Ĉl ϖHr}L,N M*1Ś-;66]Ãl< em_ɍKɒ #\ܚ/оCںګK[Ƚ _}fK١;v+wl >e>L զY ͉y+ä.^$~*,.02>4X]u8]:M٣ },l%1JΡݯ)k)n^ƽݥnka]]Bb]Y.G{ Y-{޶=mn-m3Iָɉpli=IaҴ]y~ؚ{nu|ϧL[]=ʼnM;ljֲMƝB>ưɏ.>LF}>*}_ L.g\Xn~.+ɀ|5!*|KN*MN<<^>p&;}X\zQ WMX<3 vA)Ԏ&K;&Lǃ£$7.-䈌F1EO3=N,J C_ <'=>xK_BO\=>Uo\@>ӜsTOCke?kA/ڲ{匽>`s۾dhj.Ҥ{npN3 t;7=;/en4sk^_XmҠn_Pܽ{]ž?o4XP A 6THCZQE=~RHJ"ʄ+zly2%ˊ+_$ʍ;d3NEEZ4Р29&UTU^͹ѥϟ]yr<ɎZ)6#X8!2Ui2"Pp]bxo莅m<즯v\˻Wv 4s;g)n>[0B ', @hC,D17(:+Z*A$;ϱӑEպ4~$H KSFb DEzCD\̑{QI' 35/+ޤNА3O=4 B>4PA%2C eF4RI'RK RM7SO?5TQG%TSOE5UUWeUW_5VYgV[o5W]wW_6Xa%Xc}4f+LE7: a<ю\mL{3jPMj,MrkThi"V?eon 7Qp$ ׵DaNi<ثZ?bpOx5$ ǤtW,+W0iqRay,p3^ᎎwģ= EGBҐ!HF6ґd$%9IJVҒd&5INvғe(E9JRҔDe*UJVҕe,e9KZҖe.uK^җf09LbӘDf2Lf6әτf49MjVӚf6Mnvӛg89NrӜDg:չNvӝg<9OzӞg>O~ӟh@:PԠEhBP6ԡhD%:QVԢhF5QvԣiHE:RԤ'EiJURԥ/iLe:SԦ7iNuSԧ?jP:TըGEjRT6թOjT:UVժWjVUvի_kX:VլgEkZպVխok\:Wծwk^Wկl`;XְElbX6ֱld%;YVֲlf5YvֳmhE;ZҖִEmjUZֵֶmle;[ֶut[ַnp;\׸Enq6׹υntMJ׺nvK]Mj׻/t6w$5(oz;^L$qo|yKʗo|kw$%Z]3@ < .~p Q-+ A7?2=o?x} hK͆tow6яmN|;*_yОej)ͤ2#lF:QA_<9f1ˌO'®1yH_@Ykc[ڦm܎4MlBe!=oƻw|c>p'p7/qW /qw`> 7^!Wlys}48 8c|PG<@Ljz9T7QOӑM >j׀\ϺNg~eQk!T ~7H 8=y{Cn5 r/᷅ě)!>tt7|h)?4IJyCѿ[}^/C>ֲg/+"{g '&ẎǜWV@!,L22?AK#((4 KLWظ㹹BCM $곴..:33?"abl@BLH*\ȰÇ#JH` *jȱǏ 7BH cȓ(S\ &YʜI&J\ɳϟ]JQ#K]ʴ)ċ1JJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx^ @_1`ˆ)>ŌKF9+[,YfΉ==XhzMF}Wuֈ]&,zvh϶c9wý}-`nd (q1?G\[g=ݽ=|乛/;~r_m~ П[)` 8 [)@Po ,@[8@E#Ѐ|b\< 3µ'@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`=ْڐێݨ܌ҽ݊❨ ވ}߆!,q>I22ўmչ~mюmm5=Mm$m~~mm~mmmmmmꞃmR̦f] ~s4KLW:Ȑ~m؎$,,8].۞((4Rfsmm$BCM~R4R::4R4fю.4f..:(8N~~ ё.33?Qjt.f̦kablH*\ȰÇ#.0@ŋ3jȱǏ CIɓ(3R˗0cʜI͛6Wɳϟ@ JTΝE*]ʴӧC"JիX>:Uׯ`Ê kWhӪ]֧ٳmʝK÷p˷Wy LM +^̸J#KL ʘ3kvϠvMtӨS[5֯]Maöͻ Nckœ+_μУKNسkνOӫ_Ͼ˟OϿ(h& 6F(Vhfvt($h(,0(4h8<@DiH&L6PF)TViXf\v`)&!clp)tYf թ|矀*w砈&袌6F:䡐Vj饘f)@: Pjj @x GF2AT*C E ,@ )@ B"EF;vi `@ a| `E`kJ*+D.C;Z&F2>Lp A B:L-00  ° P1(<3Ks L3KX/ۦ\"/BG@j$AÐ$0%3$kC`@+pК^ьmA*ѵ` K va qE,Q-ȺkY+xU7H4쬇8 NqHW9ukdA6㐎ȌfE)jrJfy"њf%8y1li!]`3YSor;ɨNYΐL;~SL>M(5n`}AJъZHA|L 4JҒ(MJWҖֈ.1P`6N)+PӢ:4 n