pax_global_header00006660000000000000000000000064151247410350014514gustar00rootroot0000000000000052 comment=8f4a8f91507ab3c3721e8d3f73e73ecca373546a ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/000077500000000000000000000000001512474103500205015ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/.flake8000066400000000000000000000001211512474103500216460ustar00rootroot00000000000000[flake8] extend-ignore = E203,E501,E701 max-line-length = 88 exclude = [".eggs"] ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/.flake8_nb000066400000000000000000000000771512474103500223370ustar00rootroot00000000000000[flake8_nb] extend-ignore = E203,E501,E701 max-line-length = 88ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/.gitignore000066400000000000000000000004041512474103500224670ustar00rootroot00000000000000# Hidden files .* !.gitignore !.gitlab-ci.yml !.readthedocs.yaml !.flake8 !.flake8_nb # Byte / compiled / optimized *.py[cod] __pycache__/ *.so # Distribution / packaging /build/ /dist/ *.egg-info/ .eggs/ /doc/reference/_generated # Dask dask-worker-space/ ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/.gitlab-ci.yml000066400000000000000000000053101512474103500231340ustar00rootroot00000000000000include: - project: dau/ci/pyci file: .gitlab-ci-template.yml variables: WARNING1: "ignore::DeprecationWarning:jupyter_client.session" WARNING2: "ignore::DeprecationWarning:orangecanvas.utils.localization" WARNING3: "ignore::DeprecationWarning:orangecanvas.utils.localization.si" WARNING4: "ignore::DeprecationWarning:matplotlib._fontconfig_pattern" # https://github.com/matplotlib/matplotlib/issues/30617 WARNING5: "ignore::DeprecationWarning:matplotlib._mathtext" IGNORE_WARNINGS: "-W ${WARNING1} -W ${WARNING2} -W ${WARNING3} -W ${WARNING4} -W ${WARNING5}" flake8_nb: extends: .flake8_nb isort: extends: .isort test-3.8_glx: extends: .test-3.8_glx variables: JUPYTER_PLATFORM_DIRS: 1 PYTEST_WARNINGS: "-W error ${IGNORE_WARNINGS}" test-3.9_glx-win: extends: .test-3.9_glx-win variables: JUPYTER_PLATFORM_DIRS: 1 PYTEST_WARNINGS: "-W error ${IGNORE_WARNINGS}" timeout: 15m test-3.13_glx: extends: .test-3.13_glx variables: JUPYTER_PLATFORM_DIRS: 1 PYTEST_WARNINGS: "-W error ${IGNORE_WARNINGS}" build_sdist: extends: .build_sdist test_sdist-3.8_glx-win: extends: .test_sdist-3.8_glx-win script: - !reference [.test_sdist-3.8_glx-win, script] - python -m pip install ewokscore[test] - python -m pytest -v --pyargs ewokscore.tests - python -m pytest -v --pyargs ewoksppf.tests - python -m pytest -v --pyargs ewoksdask.tests #- python -m pytest -v --pyargs ewoksorange.tests variables: JUPYTER_PLATFORM_DIRS: 1 PYTEST_WARNINGS: "-W error ${IGNORE_WARNINGS}" timeout: 15m test_sdist-3.9_glx: extends: .test_sdist-3.9_glx script: - !reference [.test_sdist-3.9_glx, script] - python -m pip install ewokscore[test] - python -m pytest -v --pyargs ewokscore.tests - python -m pytest -v --pyargs ewoksppf.tests - python -m pytest -v --pyargs ewoksdask.tests - python -m pytest -v --pyargs ewoksorange.tests variables: JUPYTER_PLATFORM_DIRS: 1 PYTEST_WARNINGS: "-W error ${IGNORE_WARNINGS} -W ignore::RuntimeWarning:networkx.utils.backends" #https://github.com/networkx/networkx/issues/7372 timeout: 15m test_sdist-3.13_glx: extends: .test_sdist-3.13_glx script: - !reference [.test_sdist-3.13_glx, script] - python -m pip install ewokscore[test] - python -m pytest -v --pyargs ewokscore.tests - python -m pytest -v --pyargs ewoksppf.tests - python -m pytest -v --pyargs ewoksdask.tests - python -m pytest -v --pyargs ewoksorange.tests variables: JUPYTER_PLATFORM_DIRS: 1 PYTEST_WARNINGS: "-W error ${IGNORE_WARNINGS}" timeout: 15m build_doc: extends: .build_doc pages: extends: .pages assets: extends: .assets testpypi: extends: .testpypi pypi: extends: .pypi ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/.readthedocs.yaml000066400000000000000000000011421512474103500237260ustar00rootroot00000000000000# 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-20.04 tools: python: "3.9" # Build documentation in the docs/ directory with Sphinx sphinx: configuration: doc/conf.py # If using Sphinx, optionally build your docs in additional formats such as PDF # formats: # - pdf # Optionally declare the Python requirements required to build your docs python: install: - method: pip path: . extra_requirements: - docewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/CHANGELOG.md000066400000000000000000000133321512474103500223140ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [4.0.0] - 2025-12-30 ### Changes - Depend on `ewokscore 4.x`. ## [3.0.0] - 2025-12-12 ### Added - `execute_graph`: ICAT startDate and endDate are the start and end of the workflow by default. ### Changes - Depend on `ewoksorange 3.x`. ## [2.1.2] - 2025-11-07 ### Fixed - Handle failure of requirement generation when `pip` is not installed. ## [2.1.1] - 2025-11-03 ### Fixed - Improved "requires package" error messages. ## [2.1.0] - 2025-10-31 ### Added - Add `ewoks cancel` CLI command. ### Changed - CLI: refactor and rename modules. ## [2.0.1] - 2025-08-15 ### Fixed - Try the `core` engine first when (de)serializing graphs. ## [2.0.0] - 2025-07-25 ### Added - Use `ewoks.engines` entry points to find engines by name. - Use `ewoks.engines.serialization.representations` entry points to find engines by graph representation. ## [1.3.0] - 2025-06-26 ### Added - Ewoks CLI `install` command: sanitize requirements, especially handling editable installations without a remote. ## [1.2.0] - 2025-06-12 ### Added - Ewoks CLI `show` command: print all workflow parameters that are not connected to outputs from other nodes. ## [1.1.0] - 2025-04-07 ### Added - The base class to create Ewoks tasks can be imported from `ewoks`: `from ewoks import Task`. - `submit_graph` can be imported from `ewoks`: `from ewoks import submit_graph`. - Task inputs can be defined via a Pydantic model (`input_model`) instead of `input_names`, `optional_input_names`. The model needs to derive from `BaseInputModel`: `from ewoks import BaseInputModel`. ### Changed - Drop Python 3.6 and 3.7 and add support for Python 3.13. ## [1.0.0] - 2024-12-25 ### Changed - Remove deprecated argument `binding` from `execute_graph`. ## [0.6.0] - 2024-11-08 ### Added - Add graph installation to the python API (`install_graph`) and CLI (`ewoks install`). - Add requirements when converting a graph so the graph becomes installable. This is an opt-out feature. - Add task options to python API (`execute_graph` and `submit_graph`) and CLI (`ewoks install` and `ewoks submit`). ## [0.5.0] - 2024-06-23 ### Changed - Client-side graph resolution by default for submitting workflows. ### Fixed - The pyyaml 6.0.2rc1 package is broken. ## [0.4.3] - 2024-02-13 ### Changed - Ewoks CLI workflow search: sort by creation date. - Ewoks CLI `convert` command: support multiple workflow arguments. ## [0.4.2] - 2024-02-05 ### Added - CLI support for multiple workflows (explicit or with search pattern). ## [0.4.1] - 2023-12-15 ### Added - Improved documentation. ### Fixed - Fix test dependencies. ## [0.4.0] - 2023-12-15 ### Added - Add support for jupyter notebooks as workflow tasks. ## [0.3.0] - 2023-06-09 ### Changed - Update dependency bounds. ## [0.2.0] - 2023-03-27 ### Changed - CLI: rename --output to --outputs. - Add celery options to `submit_graph` and `ewoks submit`. ## [0.1.5] - 2023-03-23 ### Changed - Add 'esrf-data-portal' as extra pip requirement. ## [0.1.4] - 2023-03-23 ### Added - Add saving and uploading to graph execution. ## [0.1.3] - 2023-03-20 ### Added - Workflow caching when loading. ### Fixed - CLI binding argument no longer exists for `ewoks submit`. ## [0.1.2] - 2023-03-09 ### Deprecated - Ewoks event field "binding" is deprecated in favor of "engine". ## [0.1.1] - 2023-03-08 ### Changed - Pin minor versions of ewoks projects. ## [0.1.0] - 2023-01-11 ### Added - `ewokscore` dependency. - `ewoksdask` dependency. - `ewoksorange` dependency. - `ewoksppf` dependency. - Command-line interface. [unreleased]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v4.0.0...HEAD [4.0.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v3.0.0...v4.0.0 [3.0.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v2.1.2...v3.0.0 [2.1.2]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v2.1.1...v2.1.2 [2.1.1]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v2.1.0...v2.1.1 [2.1.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v2.0.1...v2.1.0 [2.0.1]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v2.0.0...v2.0.1 [2.0.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v1.3.0...v2.0.0 [1.3.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v1.2.0...v1.3.0 [1.2.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v1.1.0...v1.2.0 [1.1.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v1.0.0...v1.1.0 [1.0.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.6.0...v1.0.0 [0.6.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.5.0...v0.6.0 [0.5.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.4.3...v0.5.0 [0.4.3]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.4.2...v0.4.3 [0.4.2]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.4.1...v0.4.2 [0.4.1]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.4.0...v0.4.1 [0.4.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.3.0...v0.4.0 [0.3.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.2.0...v0.3.0 [0.2.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.1.5...v0.2.0 [0.1.5]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.1.4...v0.1.5 [0.1.4]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.1.3...v0.1.4 [0.1.3]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.1.2...v0.1.3 [0.1.2]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.1.1...v0.1.2 [0.1.1]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/compare/v0.1.0...v0.1.1 [0.1.0]: https://gitlab.esrf.fr/workflow/ewoks/ewoks/-/tags/v0.1.0 ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/CONTRIBUTING.md000066400000000000000000000001541512474103500227320ustar00rootroot00000000000000CONTRIBUTING.mdewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/LICENSE.md000066400000000000000000000021161512474103500221050ustar00rootroot00000000000000# MIT License **Copyright (c) 2021 European Synchrotron Radiation Facility** 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. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/README.md000066400000000000000000000024411512474103500217610ustar00rootroot00000000000000# Ewoks: Extensible Workflow System Many [workflow management systems](https://s.apache.org/existing-workflow-systems) exist to deal with data processing problems that can be expressed as a graph of tasks, also referred to as a *computational graph* or *workflow*. The main purpose of a workflow management system is to provide a framework for implementing tasks, creating graphs of tasks and executing these graphs. The purpose of *ewoks* is to provide an abstraction layer between graph representation and execution. This allows using the same tasks and graphs in different workflow management systems. *ewoks* itself is **not** a workflow management system. ## Install ```bash pip install ewoks[orange,dask,ppf,test] ``` ## Test ```bash pytest --pyargs ewoks.tests ``` ## Getting started Workflows can be executed from the command line ```bash ewoks execute /path/to/graph.json [--engine dask] ``` or for an installation with the system python ```bash python3 -m ewoks execute /path/to/graph.json [--engine dask] ``` Workflows can also be executed from python ```python from ewoks import execute_graph result = execute_graph("/path/to/graph.json", engine="dask") ``` When no engine is specified it will use sequential execution from `ewokscore`. ## Documentation https://ewoks.readthedocs.io/ ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/000077500000000000000000000000001512474103500212465ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/_static/000077500000000000000000000000001512474103500226745ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/_static/custom.css000066400000000000000000000001171512474103500247170ustar00rootroot00000000000000button.copybtn { opacity: 0.3; } button.copybtn:hover { opacity: 1; } ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/_templates/000077500000000000000000000000001512474103500234035ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/_templates/autosummary/000077500000000000000000000000001512474103500257715ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/_templates/autosummary/class.rst000066400000000000000000000002571512474103500276340ustar00rootroot00000000000000{{ fullname | escape | underline}} .. currentmodule:: {{ module }} .. autoclass:: {{ objname }} :members: :undoc-members: :show-inheritance: :inherited-members: ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/_templates/autosummary/module.rst000066400000000000000000000021451512474103500300120ustar00rootroot00000000000000{{ fullname | escape | underline}} .. automodule:: {{ fullname }} {% block attributes %} {% if attributes %} .. rubric:: Module Attributes .. autosummary:: :toctree: {% for item in attributes %} {{ item }} {%- endfor %} {% endif %} {% endblock %} {% block functions %} {% if functions %} .. rubric:: {{ _('Functions') }} .. autosummary:: :toctree: {% for item in functions %} {{ item }} {%- endfor %} {% endif %} {% endblock %} {% block classes %} {% if classes %} .. rubric:: {{ _('Classes') }} .. autosummary:: :toctree: {% for item in classes %} {{ item }} {%- endfor %} {% endif %} {% endblock %} {% block exceptions %} {% if exceptions %} .. rubric:: {{ _('Exceptions') }} .. autosummary:: :toctree: {% for item in exceptions %} {{ item }} {%- endfor %} {% endif %} {% endblock %} {% block modules %} {% if modules %} .. rubric:: Modules .. autosummary:: :toctree: :recursive: {% for item in modules %} {{ item }} {%- endfor %} {% endif %} {% endblock %}ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/_templates/footer_end.html000066400000000000000000000000341512474103500264120ustar00rootroot00000000000000{{ project }} {{ release }} ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/conf.py000066400000000000000000000036441512474103500225540ustar00rootroot00000000000000# -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information import importlib.metadata release = importlib.metadata.version("ewoks") project = "ewoks" version = ".".join(release.split(".")[:2]) copyright = "2021-present, ESRF" author = "ESRF" docstitle = f"{project} {version}" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ "sphinxarg.ext", "sphinx.ext.autodoc", "sphinx.ext.autosummary", "sphinx.ext.viewcode", "sphinx_autodoc_typehints", "nbsphinx", "nbsphinx_link", "sphinx_copybutton", ] templates_path = ["_templates"] exclude_patterns = ["build", "**.ipynb_checkpoints"] always_document_param_types = True autosummary_generate = True autodoc_default_flags = [ "members", "undoc-members", "show-inheritance", ] copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " copybutton_prompt_is_regexp = True # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = "pydata_sphinx_theme" html_title = docstitle # html_logo = "_static/logo.png" html_static_path = ["_static"] html_template_path = ["_templates"] html_css_files = ["custom.css"] html_theme_options = { "icon_links": [ { "name": "gitlab", "url": "https://gitlab.esrf.fr/workflow/ewoks/ewoks", "icon": "fa-brands fa-gitlab", }, { "name": "pypi", "url": "https://pypi.org/project/ewoks", "icon": "fa-brands fa-python", }, ], "logo": { "text": docstitle, }, "footer_start": ["copyright"], "footer_end": ["footer_end"], } ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/explanations.rst000066400000000000000000000002431512474103500245040ustar00rootroot00000000000000Explanations ============ Explanations of some Ewoks concepts. .. toctree:: :maxdepth: 1 explanations/task_errors explanations/task_input_priority ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/explanations/000077500000000000000000000000001512474103500237535ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/explanations/task_errors.rst000066400000000000000000000045751512474103500270560ustar00rootroot00000000000000Errors raised when executing an Ewoks task ========================================== .. warning:: To showcase the errors raised when executing a task, we use the task execution mechanism described in `Execute a task from Python <../howtoguides/task_python>`_. Be sure to read `Execute a task from Python <../howtoguides/task_python>`_ before reading this page. The principle stays the same when executing a task in a workflow. An exception encountered when running an Ewoks task will always be chained with a ``RuntimeError`` telling which task failed: .. code-block:: python >>> from ewokscore.tests.examples.tasks.sumtask import SumTask >>> task = SumTask(inputs={"a": 'a_string', "b": 10}) >>> task.execute() Traceback (most recent call last): <...> TypeError: can only concatenate str (not "int") to str The above exception was the direct cause of the following exception: Traceback (most recent call last): <...> RuntimeError: Task 'ewokscore.tests.examples.tasks.sumtask.SumTask' failed The top-level exception will always be ``RuntimeError`` while the real exception (in this case ``TypeError``) is one level below. This is particularly important when testing or catching exceptions: .. code-block:: python >>> task = SumTask(inputs={"a": 'a_string', "b": 10}) >>> try: ... task.execute() ... except TypeError as e: ... print('TYPE_ERROR') ... exception = e ... except RuntimeError as e: ... print('RUNTIME_ERROR') ... exception = e RUNTIME_ERROR >>> exception RuntimeError("Task 'ewokscore.tests.examples.tasks.sumtask.SumTask' failed") We see here that the error caught is indeed the ``RuntimeError`` and not the ``TypeError``. To retrieve the original error, we have to go back to the ``RuntimeError`` cause: .. code-block:: python >>> original_exception = exception.__cause__ >>> original_exception TypeError('can only concatenate str (not "int") to str') Full code --------- .. code-block:: python from ewokscore.tests.examples.tasks.sumtask import SumTask task = SumTask(inputs={"a": 'a_string', "b": 10}) try: task.execute() except TypeError as e: print('TYPE_ERROR') exception = e except RuntimeError as e: print('RUNTIME_ERROR') exception = e original_exception = exception.__cause__ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/explanations/task_input_priority.rst000066400000000000000000000100561512474103500306310ustar00rootroot00000000000000Priority of task inputs ======================= Details ------- A node in a workflow can get inputs from three different sources: 1. Via the ``data_mapping`` link attribute of an incoming link (see `Link attributes `_) 2. Via the ``parameters`` CLI argument (or ``inputs`` for Python) when executing/submitting the workflow (see `ewoks execute reference `_) 3. Via the ``default_inputs`` node attribute of the node itself (see `Node attributes `_) If the same input is specified by these different sources, *ewoks* applies the following priorities: - **Data mapping takes precedence over workflow parameters and default inputs** - If the input is not specified by the data mapping, **the workflow parameters takes precedence over the default inputs** - If the input is not specified by the data mapping nor the workflow parameters, **default inputs are used as last resort** TL;DR ----- .. code-block:: Data mapping > Workflow parameters > Node default inputs Example ------- Consider the following workflow made of `SumTask` nodes from `ewokscore` (`SumTask` takes two inputs `a` and `b` and sums them): .. code-block:: python wf = { "graph": {"id": "Sum"}, "nodes": [ { "id": "sum_node", "task_type": "class", "task_identifier": "ewokscore.tests.examples.tasks.sumtask.SumTask", "default_inputs": [{"name": "a", "value": 1}, {"name": "b", "value": 2}], }, ], "links": [], } In this case, we have given two ``default_inputs`` to our ``sum_node``: - ``a = 1`` - ``b = 2`` If we execute the workflow with no parameters/inputs: .. code-block:: python-console >>> execute_graph(graph=wf) {'result': 3} There is no incoming link with data mapping, no workflow inputs, the two default inputs are summed to get ``3``. --- If we specify a value for ``b`` when executing the workflow: .. code-block:: python-console >>> execute_graph( ... graph=wf, ... inputs=[ ... { ... "name": "b", ... "value": 20, ... "id": "sum_node", ... } ... ], ... ) {'result': 21} ``a`` is still ``1`` but the default value of ``b`` was replaced by the workflow input value (``20``), changing to result to ``21``. --- If we change our workflow to include a ``SumTask`` before our ``sum_node`` with an incoming data mapping that sets ``b`` value to its result (in this case ``200``): .. code-block:: python new_wf = { "graph": {"id": "Sum"}, "nodes": [ { "id": "first_node", "task_type": "class", "task_identifier": "ewokscore.tests.examples.tasks.sumtask.SumTask", "default_inputs": [{"name": "a", "value": 100}, {"name": "b", "value": 100}], }, { "id": "sum_node", "task_type": "class", "task_identifier": "ewokscore.tests.examples.tasks.sumtask.SumTask", "default_inputs": [{"name": "a", "value": 1}, {"name": "b", "value": 2}], }, ], "links": [ { "source": "first_node", "target": "sum_node", "data_mapping": [{"source_output": "result", "target_input": "b"}], } ], } Then, if we execute as before (with the workflow input): .. code-block:: python-console >>> execute_graph( ... graph=new_wf, ... inputs=[ ... { ... "name": "b", ... "value": 20, ... "id": "sum_node", ... } ... ], ... ) {'result': 201} We see that both the default input and the workflow input for ``b`` of ``sum_node`` are ignored, the data mapping taking precedence to change the result to ``201``. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides.rst000066400000000000000000000011501512474103500243360ustar00rootroot00000000000000How-to Guides ============= *Ewoks* is versatile with respect to workflow creation, edition, and execution across different environments and interfaces. This guide presents several possible ways of handling workflows with *Ewoks*, whether through command-line tools, Python APIs, graphical interfaces, or REST services. .. toctree:: :maxdepth: 1 howtoguides/running_workflows howtoguides/python howtoguides/inspect_workflows howtoguides/job howtoguides/gui howtoguides/rest howtoguides/benchmark howtoguides/ewoks_events howtoguides/task_python howtoguides/task_inputs ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/000077500000000000000000000000001512474103500236075ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/benchmark.nblink000066400000000000000000000001011512474103500267300ustar00rootroot00000000000000{ "path": "../../src/ewoks/tests/notebooks/benchmark.ipynb" }ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/ewoks_events.rst000066400000000000000000000016041512474103500270560ustar00rootroot00000000000000Enable Ewoks events during execution ==================================== Events can be emitted by *ewoks* during the execution of a workflow to notify about progress and potential errors. For this you can specify one or more destinations where the events should be send to. To specify event handlers from python: .. code-block:: python from ewoks import execute_graph execinfo = { "job_id": "1234", "handlers": [ { "class": "ewokscore.events.handlers.Sqlite3EwoksEventHandler", "arguments": [{"name": "uri", "value": "file:/tmp/ewoks_event.db"}], } ], } results = execute_graph("/path/to/file.json", execinfo=execinfo) To specify event handlers from the command line: .. code-block:: bash ewoks execute /path/to/file.json -j 1234 --sqlite3 /shared/path/test.dbewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/gui.rst000066400000000000000000000017141512474103500251300ustar00rootroot00000000000000.. _gui: Use Ewoks graphical interfaces ============================== Ewoks comes with two graphical interfaces. You can either of the two to create and edit workflows. .. _ewoksweb: ``ewoksweb``: full-stack web application ---------------------------------------- Install ``ewoksweb`` .. code-block:: bash pip install ewoksweb Start ``ewoksweb`` .. code-block:: bash ewoksweb ``ewoksweb`` will create folders to store the tasks/workflows that you will create when using it. For more information see the `ewoksweb documentation `_. .. _ewoks-canvas: ``ewoks-canvas``: the Orange desktop graphical interface -------------------------------------------------------- Install requirements .. code-block:: bash pip install ewoksorange[orange] Launch the graphical interface .. code-block:: bash ewoks-canvas For more information see the `ewoksorange documentation `_. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/images/000077500000000000000000000000001512474103500250545ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/images/inspect_desktop.png000066400000000000000000002616341512474103500307740ustar00rootroot00000000000000PNG  IHDRA`ϢsBIT|dtEXtSoftwaregnome-screenshot> IDATxw|SME.{(P DETĽ:P\QTp" *e "{BwKG-mHJ#&䞓McTV4MӉi|Y*R7 l4U}] m>ѬRl#Zm޿qWv̎5dF7ڇ 'rHyv< ߿˼,Q(n Z;?KXͻ=S~XOKCMV}'KN@H8Ft se\v;v*tm`DHXz (rWK-o(SVK9q߯*pK5|0}=OCwOXΰ{j3XӕQwT`j3h%I?nۘc y5$cV{*t׏!,sVF~T9y˶r^uhR%'@n){b{(F~}b6z/]/}~h?͏0Eq 9[>UUn۾#1+~I[1oJh}x Kb,ܑJv0E~Dw ^O|$k uU!vJf4h~8^#9 N3gWb__ha3m(ČinB4f?[ @tUv0- {_M0zBy|#ftwMڈ@~18Z㮧0+Ǧ_Z\}-H>j%Y~|c\5ey^Řa)9s#9]{}?+oOy׽g^o~ 5GOa) ȼXs+Ud:N*U@HH;EDDDDDDDDDKLp1 ͆QvmVLӉ*PL5jb{^RRS np8 LAzz:kzzqMDDDDDDDDDvja)\*.S!\LP*"""""""""W6"""""""""rEwDDDDDDDDDDr s TDDDDDDDDDJCCv6p8HNJ".&^U*""""""""".0(r0 #6@&&:V*"""""""""ŪBJuabX,D<}#fuM?E_oAAnYt8-X/"""R\lu3NDe߫:ǼG?~G;N{_~Ğe/o2T彊""""rf#\l۾r T%\"^4yTFblxehؤ)u*D[*l/1[w2u8S#Gw\ lYf ˖-vlΝ gҤIy|@PPȥaGLjJxt+Li^2,X-yWfyl#L$22ÇcZYd :ubذaL>=3TDDDmZ8S'JYL<3í aҧ# |۞]Lrٞ<=cd?ͮaS')eOSbvs+}Ugڏǿ%0ч5&pR>yf 4.A;-U2n@!Zӈ7W7?XOt\Qp篹w;.בV;>;ǖ៉񣹺Q *Pƚɝ+"Z]{ҪV `oތMę|8Ç3}P4+Պv=s)#_j`sd:Z1Wűl\GۦW`_R4&jUlV>u< Iѯax %9U[o\Cj'şVbd+G Ӈ&Bc8KPҒ oB2H#>͛$b"ϥ;Sڝ 1KZn7Ў=P3Q$q"'<;^8]Th|L!1I:tI1-iܡ%ʘ%oRN7<ڌzlMQ3;c_)kDDDDXaꫯj7/"""RО2 _F~3'Dk:bZ}NjH=oO7o4bBÆ[\$n\v^ҿ:Ir; ֒hP!zvO=]-6)OMfe%2 ̴M|}?zCG{1f?~ x-7#!h?w(4wG3pږ7ݹ&dwrɘ[Y31t𝼷!G6>s[oGEQ&Coeŗ;/5""""R2.ۙDDDDJ0[40<q'sc|P8e kJH$k91|Шn5ǕD:MWaX܌v3zk, Y÷ e,Y=x?kYsޭ;uoNNU \D蒵3Ñ%eˣzhGaRL.0,x+];paߟܞ$'۝`եnsru?.5""""RWuiӦ1l0uN3si8ai{Hfm&I'` 2(7լDdZHJ#OHYаv)'>*KO m 7qhvuK¶_13V`> ,3#uȻanKaa*L?/5""""%Jq^8\.y:uuЌ9Bs t8 TA!{I#@ԤC*L߹cKμ$w3=d V`lp\dlA=+)9B[=֛Csi׈$%)T4M f1Ghxx8K.ͶB|RRRR*"""kyOE:!ݕ@_T>y3֞ϲc2Vլ8cN6xƥkI4z.fTlVN¼' u{fmCÛo$H#4:m,,/8ຄKןɬuG8\~ j |n{Oޓ9_Džs]^˥ԹItڊ'1B:3hd - ږ Z๑.Wչ++$3nI7ȱ+yX4~)6c/[Ǻgh[g4sNglI篇Z3&4TkUy1԰^چLxmce_J&ń#hP"5ǙO"e|i̻~r.[PydQ6O庪}rUl-LΓ^sر3#yF& ֍5153rvU^ӣNoFw6'CLe TY B' U;µ08ur6ltf.)hQ67 ]oW>zH2^dΖϷŋʔ׀HVnV/Q0b3_>HZEjmlG3s<}ԠF6 |wf95}zq2m3Ļ.t?, m9>$[3kNc t,O?X3xv]ΚBnEDSD>0װt g]m#"<#Ph3f%oN5i.>ޔ$O٥>a5Wxv?{Ngb kMf㛣\p _!hf{ݵ<6=#ZҲ׃/95f&{zѤFUiug7 48OP>: p}> 2b~D(f2CzP; :)oͤksjpϽx&mgX̱c'Rk6Dnw5=ۇsCEDDDDDDv}[ߊg9p`Ӯ;K#dùc Lֱ{"^exGAټgoxe]`KIXVqp~ύA@xu7`]*NamrB6`c&2 M.bܶLxDvZK )VYG؂SV|{W(>;q  5WGN?ϞoΆ\ۓ/}ˆa j=7gꭕ/y1}K,\ϻm`+D13ogRPr}+ߤEx;^hξĚf+Vવ$bf{wyJ6 ֒c#`Xƌ.!#|V<fo]B~aͬ}d=G}xe}/%r#xtBb5x{c<92TG[ mc|gyE[ʬ?Xbbk븂g}⹙3Vԩ]ڵkS[8i1T)nkH;b`qUgGl[j׮M>few{yc(6?Gc`1כCYogS?gVscڎvYkWqXFTʝv׬bw ʰR};6bC6QCwɶmMoV2k~7?tu} <\#w%M27u?LuI_EGl4.>4[9(5 wςG<@2ml^t6B{b 6q&jvhKE$b҂(|~Hn % )[ ހ܅n fU}1eq ,Эlၧ5`ڴjPs:O*#M]L>~/mC=Go%d2 10Zw%ul\B nza\>Ï ']'9v"STIJ'%^~}_cK]@yQWrrV-l3ó`__9CޫyOSAύ myc6BN/ey-9.tΣiZ;^f?ZM!![gEF6丟xt+ !իѵ(5bʓJC΄\5qq}<˞P#=t\$3Or*2*{WFpINR=lȫ}/n ;RO0A^qG}Z3 %7B VG𰙤Օ7g~j'Q1߼3דr,܌fi$8;ۜ ʅ{!ݝ?q35HʁŠ<3Ky_ΊE>R&J+ IH`<\ɽ``bl<W}+;X5#̍o͡iӘӇ[..(L[:69 <ޒl`Lxk-ڴor^ PBb9L n|)?۵̡X*#J9)Pq EQtI_ pe+P>w}ӓs$B؏D`yB.֥Xo綫|9;&l/vŐRTR3.iv\Xuu?–쀋S@!h@09peR4Z&>O([[scخMez\:T*?ۨtlzA'llԞ4nׂ]S?aM@8kzEpm8m &i_$cDG\+n%$v|I$( &>櫀טW$ݛ_-Ʌ=j9YDhhuD3[t[/ڴ#mrQA=y{HI#yϚ{c>MN7M 0؏u73i ȱN\륚zC Ӟ'…[ɽ9SauW=kӬ~DDDDDDDx\ $fU5ܯ{sV $ۨ^2.a򸉵|LEܙ^ ?ҭiɌ܇0y[-j-?/u iˑ^ *!?7ְ J:&`Q3`npcڮMfŠwv4?M=sHߗ>ݏҫm;߻=<ѨVcWxX-Zӭ ੇ/|uc}yK/76NXu>{ٙQ EP/-Z x#)i r1 IDAT6N&Z< 6:W;meP iYL5^㏁o֫(,ɾxP}̇+ WTkĀ/.f/r<ܵUեG-1ZLۈZMo犏Ʉp.j*^)VFlllO(@jɔ soإ+L9wMƷqAɓd)O鬈daE=9~ u{lll7 y=kor*9.]ѰN,o_o\hRg\1111%Oi쳈ȕ*P""""R AKRWڒUImWn.m[MNa8Ԅk_˜Sv!K:s` nvvm.DU\ 7>V *""""JE.;!6)- 19N&qS~a+1"""ea~lv\S""""RcǎwDJ>嶽0aO) Zvl^W*""""y}wU}^ACoq  % 8o_a+""""M{.$T(;rw3DD+(x/zL!y4M""""MAH~_i\TD Yznq BEDDD$+UP ~sTDVP[EgaUU%~ BEDDD$*AENfy]wJ )]ܙ3׬e~hn >T$W]@rSS689 IհX,;].Ng1XDD.9g9BH^T *hAg^udiѣG)as1 ^.S!H)WWЌH^T *Ņ%&&ratũ o;NG1XDD.ʜr ZJ""""RT$ w*9M3,+%u:02o;;BP+T~!%}-WPTDDDR*rVAh^Ah~__PYQoooʗ/OTTPI9|(UL->y""V*мМim˘gr84^ËWBBBq8ma$S""W:wvq\g׬Ab ?dq۝EDDDDtP%_ؙz B˖lٲgr-nKݡ }^fY## ؗ5̸SDDDD2TJ=wtn'%%̹2z ws%w?$w3DDoP 3zfE@@˗73#ܪP%HV+4MDp9xyzbZs)=#يE YQ܍4M.>>>ӇmRz|f/ B!T)}T *;sT j&D8_2\$%%iK `1 ,V+i:kWs]wQ~}VkcYͭS$*ATo.Pw?3*@O?7qq 2M\3 NIpgqرbfͿ W*)]T *ZaCМΩS"!!Ჷ_DDJIhh(2;se^ՠ""""R:TmrWr\?+c˅" bbc=y8"""R*$%%dڶm4׌׳ҢH""""-88Ąxcc-"E^!hDdYfĜ: \I̩SQZU].WUHeZhݲeqCov=RL-XP)IKK <3.MW24Q֪Une9f ?3.^^^Z^DD2p9BМU9Ϭ'TDDDwDC^ R^!䮢 g+cӭX,gUhex"r.WqtV=\Bo'mYxa"ٓYq^[ ئit:3мg=^קbҤIn???Zh+arSYPR~^ j3617s.T4M) AN'}&%%r8q"ݺunMK\GYy 8=M>]~ ELr׾h"""T8<(0`xp*wyo^DDDDWpɓ'`yyD&LW_婧r,Cuf #hܹ+ d>MR6 yh&Dr"mXrմ>`A\֠4z~7k[|:'hFsh8N> d @{1~…X;A69{bb֬㞌?Eܕp*MD2\=ǡݜ(hY{Q!4APgưR}BSXA}_T`c[jg}vA!aa|TQNǀ{Sqf~\|4y)2M^l]8ś$^' r>uZٷpMq@T}0o>˫m;6\҇]nb}iW"$qlrfNyI@$YjU;vP585xBSH[+)vOxu@ 3PL%g>@{l6Uue֭←Y%4B¹ڐ39Ղ!BXm323J~c] K:R4.k*"ajaw{ylNHVx5/o~%Ad+,( P97]./̓y_c~wDgϞW%?ݭŐ2RHfĉk(sa„ ̜9VZeV\IZ7nUT)iuy酯%{i$&)[tf =ӗ2hH4'H dw pOĉgيL%64>~0??bG@_y~>pZY*$-9ϰ%c_blx#sxilKvmʛ3 SDr"R>{ ~ ď8ox|VւCP'ȅ*0l,^W^y3f駟RV-}Qf͚Ů]޽;K,r?,suAe)BۡZ?5@Y YVE\"%s/ߎ>'h[mO(ܝ m4+gaW`5*{x:İ0@?<5Ev-z%o>KOeG16gGʼnSU+K)qם,}8ЌۚTDDDtrOW~imFzz:;w^cԩS]vѭ[7=zIiK\FG Z4aj&:ٽidRfN/1kX)&bW( 3sL!H b)O{ ,f~m} 0PVP:?2;^;}K9{ ">ҞɈĭ}o.#N;Of9@>/smy_3gV{nVu*UtRuƮ]4hE@[X:omΐ{R-Ys>t/rEL:SwlI%Bv'چჃ#X#D-T2(mKOS~b 33&NĔ1a AӾhڭ37w=ƕLI'zC O4B:/2#f붔|ű*{I082(cXw!1GhyA[B~v=1)} Tre,Y A^zw艹lL{ϼYgɸUNS;Ө-49B;1j|қ3Oiq#2n{4/RJiYLK"nOEj؟6OBV?ޛ΅6͝yyxw*#סsj|W_&7V=`7DO _Âwǁ1GW̟mM{w\t gKQ*R\0JPbͧ!^H>WʵGP5Uz gS&('k3y3? ?KpS$3}x73F=Eqg[q\gA$OΊ_jPE܋óR}GM˯4~ y:{͝M`%R\'百jqNbł_XM[ZƳlOn|wC uJj^*tVOoOʱZI,.z٧Kuh2tMv`,K`zo{ }GwUDY~=ݻw4e\풱pgEDDDDD?P1a AaOaX>[,0+PPzѭ8S9w +{ok+4r)CDDDDDDt(Taբl à[y< z_{Kܻoe>2ٰ9ԭU/l݆}B `7ZY1#̼9[r43R,=;wk4w{7/_b0CjХEz0TRq{ iy; ⸌9%=땡sFJ><,x74K%) DDDDDDDD+0=0ٱZ[}= #Qz-*WO~C?xYN'%meVn^l]`oZ*6l EX0} L3dj®Wr+_ߗc?i=KKj7gLeD0< tKEFX,< $|E١̘ -v̆eyGoV}/Оz󿘅k  _s)L@SG֮<;tlLRߔ6P(_ /_֚n=CQLo~%ͭ|Ӫ eX6KV& ?&>x,@&k2U_]ņ'Q/]?||4jg60n[~<{NwSD.+иrczٳe+hns\)̙MaҫY5fi$E r6%㶡=H6z Gtd:׶'u[kV419zu;dɯHLnhݥ'#[T}>;~tџ=3WY܇sĤ}~^2%sv.W3'3oeAȳR3<߯dFTm P1 }0LRu [Kk ']בZm5MLjWSbc}yޘSxT^۩vno&Ot͟ޢk{T ]YWè>ԫga?8uBs#P=bsEzIiir2ӮT__:Z{O(Rkނ__ۮ TDDDDDD4['Ou߾coy: )9:Sw0{m">D5ִ3Mwj iPMG/O>Is!}gƯK¸kh`<'}M\r?yh}7&lOL~b*vwWRݕCP+k ~,뚻1y"0ߐ!CͪiiG΢N#gg 4is_ [ùfB A5+nZƶ:/cA< D&nQF'\6pJo8cǎ8N\.q:yÁ4ay(~ v>a6uuزe fQ49hwZo6?ɞxV-S'u-A-[C[p2{}L2a/qb^,}| %x67vMkS]pw2ܵ}fRZ4o~.!#ٜ) k~ρ+. :c|EDN@ ճS^bsY]{pgH g mpKzX;㟒 씿v}QJ85bpn*"""""R9mRJ4;wb#|K3/ȓ}$S1m @N iywIب5kSÉ$eԤGM{]Pl,;] /~?'ACxlی$*ﰄzʷ=;Z-|wMOqMҿKԬ٘;w".sO&Y0&=`""""""Rb΢* o j]+"1_r[uXDq]y=)FfkzwSxV"%rugqM o[1TdNJE$9ntD*TKP"EQ!o55p8p8]&&&*UwuDDDDS!hzzz4UV1tPfϞRul۲0 7$۲0RD 0 (*TzcILLaÆ]%9Ŕi:yc>VbɌ3 j%R:ԍ⥟sp96⥟]MN'UTrwUD$0HMM-j)LCЩSBPn; >_̟wuDD1Ř~mʻ*RxQ) e&A:eENVw_U^sSDDDDJYKKK+"""""""""")TDDDDDDDDDiwx)͛7BRRRyWE_&<xٿoEѴV[_^@U4&fxy[mx~sw|_{9;ԩSKfԩ3!cmϖ~V7??<&|aoYi,4Uz}嵙3<}<DӪ[4`e 6`( W|Ɣ7_IR%"""""""ǫX!uJ"]*>f?w1AC vxe:/iUllM2N଎/Nu ՜9ffN%hV{v'ywd%yl-/"%lGUbjס+oLxx&-ŖI2A5w;~x!a$[ٞnӪJ \,Vvj;O(j AԪu),HׯVDDDDDDb(V;ҮGuSCyx/Xn22HK^Af?z;ߴ|7_{ X|.I!#h?yj=6l^={p?ؖjagU$zlmhc7գطuius1y_ؖja{RI\7sv'"""""""r)Vz嗗v=JMET|F x5Yӷ4oCSGyjyeovkyy)mסA^\5q.{2-lg;5nz~PeoF}# 0L֍g `OuڕIyMWf7|C3;AM8e4lKQo$sv'"""""""r2)Vw#G2eʔ 7C|||<#G,jH!/x]5sӋoGu͛?HWxh#ʷwe]!uqGrX!hHHӦMcС&gڴiwUS8\t΋HEP쉑իٳ㈜,JelJHEFFbYa`YVyWGLeYDFFwUDDDDDDD֮]K\\awuDʄeY]򮊈BPRҬY36l+8x`yWGLDFFAfʻ*"""""""~ AEJQ˻ """"""""Y)M AEDDDDDDDD䔦TDDDDDDDDDNi AEDDDDDDDD䔦TDDDDDDDDDNi AEDDDDDDDD, HevyWADDDDHe444TʊLCиR)+RiݫѢQ#Z\;M#hxԀGDDDDDDDNqe^~RV"?H"#Iݦ}-si_=nVp(Ɖgl?eV"E:얙Z).""""""""%S!ȑ#/\||<#G,1g#} Y;O vz|͡24 *"""""""r(4$$iӦ3gڴiaDʎptG&]{$~Inw3WUúoك/#Ѳ5 xj1G~uOwqhոu[>fYcl]6?ŭ]spwҮ ^Y˿V"fU_~e{y!''Z4k>_~c]w]LMBxY[Xw 'h$<o1c믿w^˯ʘ1cT*j4QGH>dso{Y 6 .Њ߾=ม0&Djt{}dGUk̚gpf&^ө~u vɈL}Wp8Ķk~؍zS:(/]>ā0" <{wF5BPreo,օk\R+b^yz/k;~|l4kEԯ޶+Ǎ>ʑ0 .y+c.;+,Eb.nܾY9YX]Ljt_}\qt0 &"""""""Š"expgepdz~FGZfGxZ&/d "qGLx:!#"̝l{L& lA|<@֎o$虿.v z 81aL>DDDDDDDؔ#%RK 9G`?3ut.WIн9\8n-{U,|+4A 0&&^@EDDDDDDÇ*"ζm܋eYXgxpݸnzVVYYY/r~f'\F矇fʥT-Iet޽yx0 $$$Y19sp饗w5D/袋J}vsAbcc>>cǎ8N\.q:yÁ4aySDDDDN]/@9).2*6Czz:7>{l8js8&# 60.6b816lJHM>T AEDDDDDDًerz6z\IGmlf7ѹ i GmAC 9pݢ?WzVY:""BP9 bmWw=DDDDDo ==xly&)¶yaC@\?S3lf>1LF:4=3[vaqo]dED*#"""t$ IDAT""$$ 3+uj%VXy;7lvPxh۰'fa 򆞦zNc9lxyPHC.򆠾̵ DwAhVؖXq+m[6Jȿ{]DRԳL_,w3vU ɛٞ/1  <>`A<*̔SKeTd"ëZF]bE*Y ag_0 s{u XP\7,,=|G'."ס#)$Lnה!a~o+9M3;>Th>Ĝa8iSzl ڵh꿝x0#))2RJ:۞g2.ƿ3"Gv c_෧^eOor+\QF:MyC>p'v3M>y ~ h]+"""""㱊,k? hLJ>YmzPMjΕ}o{<0MN'Lt 맾^‹W?ɛf׹:j'J`H "Eټy3)))$%%wU$Mxx85*愈kS`A.'))DG(KlVY\=>`q^+CW,$\=g^܆֖X&\0>$φg9u#6oތ}])cgK.)c-[֭[H! w~NNlY]bvOؓKlIQ|ǚ.-Yi+nK} U0Xg3xf "%uphG^ {ׯ'+l'`s76~ӏ~}U)3t6o_CvgZd; OCPE߅X[cZ:dӠzՏa뮽lܱK!Tz% ={Yk; zބ@(jT _}uv|⃌MH0D39ئӛQjaVc[xoL y{ΨY"WJJ }-jH9)iѩS'͛WJnݺuŕsM<81DUX]b CJ%Xl}]bަEcVt 0(qrJ%˦$m\%VIaᛏideeEVf&2.]{Ձίt Ex9peoST22;iULI)V@>CWN_>[XwwNmZCL^M!T^% A͆o"Ĥ.p'tݨz6OLp7y.WYGxMC IwM;٫aw~2"Wn% A_ 5nݺuY3֫U݉q94_vul,ڇtu:YG_5t6LuīW6\bΚ[6>Zժ~r41\A\\d~f%-r;}"7Ov^¨j Rr ZLQ5E%@f=` P oݲ!)&ZȰ0\.2ϽK,"Rc\DD+/[?z5_f%)nh̡ˎ5yb-C]@fi~>w3*@Vi{G0mɦP;C̞Ę>fy[z6}ɣl#tqrwΏqC#!ѿwr V'Jه/xNDWgOÎ= AERS*""M>!C'S¨KlS`EeFB4lقf$FPάL2*dsz @f˜U:ojTǕ}okFRYiMRЀՍ-cL;NKqtax{82LMCCGSܬЇmi/Xb9+78WCz %3!(l?&6W!cQ8E*Q ŵQz'T//v= YVwǻS۲xrmZ`z }:mBED*tCzV%pHul3X :fs={ʿoa' ;`\'ݡ̙{vmǶcypEi_'nMf&69V=*o|ua޾S3zHewbT'Υ/2|PlOvq~(|TV|>XqGAjVmLpҥm|-%VԳm>z#xYZ|fit_Y{a)@Xx&Ź/+0a{HA ={Hv"0ok4mC+^d\rd,:atnO]?e}ӢQǟWqf3C/ӝ۽Sb& qWn}TJ>0]LxYwq}\!*[3luԟ!hƶmlfРAAi"%Ȳn\޶N#gK,'G%6}]bE* vvVL v(7DesNhZRG1WlaN29ٴ- T|I%V*2˲, ˶X6e,êa6$g.oY5neYgsN¶szxAXoWz/g_XQngeYyz6cDz9WwatDzصo?qﳭC[,cAiJX>v_ׅUBIxjDW#"5cjL9E))v>jE]Jz1)DMg[ >bC&i[3oNp؀%\1/<3tfs7> U[ ;dWM7L]cxFj 8'kF!T&b"ٹw?i%<[ԪCǮ=n,A4oX@Y)"Dl Dm4IJmVߔe{s ˲y<9\q~?<. 0Mh eܢ=4kXz}1{CPXnצsƭ-NyHIM+e| i餦j^8 ߗMͨԭC򫨈 T5 px8 ԬJ-׍Ex{dy5ou~vGK.6~9 fOqQFޝw#؉L{t#utfZ:Ƶhh|!… IJ Htt4ݻw/j 08m˼CSYֈj-BoT^w1/ ٳoi͗ b6wƶmp i}7ƶm`Xi}vIJl~G1BDXG `aCBD0kⅈapf׎`޷XL4 aiILӠft$]40 v_YO>۷lgao]oapF[n/?ӽuϾhFvj&C-X._32qfVӤnцI&❺`_}N]{VfL;t<4M>-Ye;êQV ׫MRyN""eAIH9pu8[9xǿQ;l(S<˰pdo!_oޑ}ihм.UMp)?úWA /po; -iҏey68jle63'zw\P]]h*-Z/rzCD_?4CD4q3D?$!"%)~PVRP0k6m Y4dfG7>9o(7a < NH%n͏j6W^UҝI(wK._9i$h""%s5*Q.SaSڱD"ʿѰNM t'6;{1 u e窟S`Wc~ j:f}3Mֈvmؑ[vso"U}$&^*UCBDNnj *rfb){HP3**coW*"m,[CzuSp%݉EN5[*s 33ƒ fD(.v5`9(:ه?p7|=܅o'<`{[נLӠaX։hZ:AdYLv-ЮESNqCD4R)Ӣ3z<#ˈ.%**ZDD*bA.wX4 .a%i 7>s7uϧyz9s?Kȩi89oڙPLT]Vq [0Ϧ9qvi=jDxXv< v껢T}t_JGGl z9䋪iXET$)OF n+rjVuW4ȳa@ Ԍ존9xϽ=\zQݨlP-rވNl%N$?k[֮5K8ٕHiR*"l2:w\UrP,b͚5bDDJOTD8%t:q{<8y{LKȩ~l `r2C fދ$ZnoܷZ=@+PK6FnID1oO6͒UHJ>ѰN,odMD<450o?w?7UbQFlٲ9s搔TՑ26k֬b"<<ƍbDDJ$3Mp BPT%A n vwhZ4j_7#G S&CNӷ:l IDATŐb]-V1}À#GKa4kPFub{fVĶ IL~4X4V/so𿮔Z""RY7o{hٸ>Ċ«U!48 ^Oӻ)2!#VNHs.WO 9Pҏ<VrlJ #5L\CV6!cl\9IhpaU`Y9""T UEsǶ,}Z:?oK][Y|ȉUJm7jh]4y{kjD]bE*& jw$X^i%ne9/Fwg?4nD~GBYŨ͉U%$zwO,^_,:UD,%%+m3\MXRu+0卧ؽ/zN=FEDDDDJĊ:5gmϵЪY2jIO+ܷ 0}qCVә]כB!n/^RML, KbK,L^7VheJ*JPX7]+D]`gޠJn2K4sMfYI 9 ;{ cwϝ0JmK+E>,{J.luurζLj9hdՖ2NF\Wpώ %+Bcwa+YWrbs=j ('IfNL,Ίʥ?bċLJwQLgt@CxϾ}1ףy~BWʽ}~;\aWS%fkwxh]L[>4;ؗ9v@v8Z0άu3qtz3{ ml='Y~"_n[k0яn<"G$Bf~!h6q|Ř@ǂ }: 2%Ȭng^ArAYd64nYmͪXM$p'.zV:J4fNbR|4z(u3#یIϳO;V|43@^Kزçbl7w#K8B?h?mo p藙,Z+(֮8yvg_:+.. k;Q9;;cooOm"7MNJTnOI[ \ZbϢ  .Z$ezRKbKw וPɿ@f.FL; &Τ(W99+^0FCɺ=N̹_a/ѫ{@^.6)(tVkсBR lŠ;173|c!A&A2F9z0c} 5YL&#RnHKM"{C`m[Sh7? \PxzKM]1Cz:> *Ww/ߓ]2Ƶ(x1W6ě_cؼMn!9)QS!-s?#r[`89>~ #6qܼc;ZaNXImn! Ǐ]7J%GϴM{ʏ &K^"[TFtYD:gbֆLz҈Y6uHA2͜y3}NQ쎱a|̣ 'd,ZŘa?)yti>9TFDz}M9M}z#..VK@@@m"j؆ Xɓ'%*ZzrYĚi8$#d(LzJbKʹ]Kb+--iқC'HJ\$IL|^)8>\gv:w驯SAt=? {=!)PcZ`miys'jwdԀŔK?Gf޵4 pSc] +w]$j2qx.ŮM0u7nYS;jzy?{"m—na -lL`S%kzc /lb3v&~O{^zлPxtti Ш m*]ٓo}a;N3s "dvG\Osoߍ\QjX>b9Fx[_]Kk*"|ŘnP!o;Y]DM[K/cGϘ፽XZư+a3& q=?:ϵ/r/iӊvZhup*ӧzS;u͛oQ4BQsmmiuMFr 8VP6ZX{bEž`&EA f.JWKb.%+S~O~By=-oljd]ɟ 2:Fθ9;in`e!.ɄTghaZx2a/T,YG-`*ܥS}辵!m|4[k+ iIU1qqa@o&~F]+6m2W]]ڄ"Q;K-=-I+ñ*-`UCe>g{z3ޏ3{̔^?È0U=A]߹ļ D$ X5ϟm 4O^) !~fN̩v=JGu  R9 %,|bmX}?Dy61 bEPsچ= ;<Ԍ WPv EЈV(8K$=$$h(%)œB䈱d~+YرE:MӠiKIEU1L(Yp$l9Φ× ;²')~Oq Ws._Fރ!fDf6%`em {?3p}L~IҰJbmtxd4dr+HY꠽(>PRz[EG b,6/GsTrrzKiڼ+9BTJV6vt;o+Sr1ogNrd,oa+hsϼ)]ƮZE*l76Hyh`WqȬ0kԋֆp\jPUm;𻸙%aNP{]^aBAшdf,ܮ Nj=ֺt2ҍEۛOq>xRWFb2*ydAQQcvcdz>nX앢xᭋ%#w?Qpk>9+WhhH.ț4*!Kt !DQc -\5(( RXq2// ^ p8Z_Kbm5} ߢyyGEW^Qc-vPn4YzpXKc;1 m&`,߾/U>q]diaО8ڐr9U[%*VU5Q% gUU%lb>xq8nѦw8CWأ0uA{l"չ+f~aB})4_d8u~9?^CBS9U -`ym-=Nj 9A҅c\c^xyUx {w:zidvI+mzlClC@O[?nCkc7l m0J>_a7*YAr 0eDZq'΁ UxKɫcU>v9–MgjJ'׷Yc?6dK♽=.(Emt$Eq N[ǚ'hG6 vnX$Ds˗R#i,^cr) qvpXv*=xBԀ BNv8‰3Mv8II OH@[|==[ZV>SV kiB)(Rc*`mICZ:*h+,ͯQ/zX[Y2W(v6^Ngp%*& Zlu?dƸ7'Lo7MjPm&]:XQ}93sĴO|_3ַ< z O?FyI4*KG0/@wd\mǠcd:8J:t"'@n8*cSGۇbahp~e˖lٲrۍ1#F( ˖-O>e RSSqww/ءCڵu]RC Q벎*)DPn_~!00NYѢJ,ZVF)(Rb)#qɺr边[r-F^VIȯdQb3DWңbu?[ M*qWo·B޲,lYٸ:3` !D):UZR3̩OgMc]ğ%rĨ{]z{Z?)eBcRwSٳh: MQ (-6\K%]wST|I}M?sӾ.uĢ?Mm2AN4F6QXv|.> *5kc _̴nSXa%9KRJfJEjFBX(8Z+8[WGXC+B+K ʲm$\LfPa !1]Uжԕg*/)>R21#hծ?~ {ɉi1D8\8@WÚ(ņ(Ԣdc-?/OgAL'?jƷ:c^mgDs$ӏ'FdN~d.rvtཱྀĤ$^Ux-$lZ֮]gy7.멡e!DSrt|>:0S~9|RwSUc7֙EwuMpt:Rl!L@%3# lC#IP!č!%&wDp.1w\~Mzdb?g~a8.]FےtgieW>*V)VɄIL$޾ƤOt#1&s.!ȟŐpdGWuֳ-~6_qp08(6m&% Jcǎ$''ٙ]dXB!BhIe]x${wΦlCX%>;=dݍ.!Dҩ&z/n'A MKmPMj]ޣ߸t}9]Iw_#X{ y$|N._EdRUV|ǤXyj)*!B! $'$f.F鎥5fT ŅsW>9up:!Dç3IMTUULW)ZD5m;;̟ULg:3)R>[}W~_&þ-#^_쾶fziӦHEE>> !BQr/nG{^k##>dHBt7U+D=RqOPrbcr=BkkɯV"}g)gk;qKO&=?2 B!)f:wvҰm\HNeP~cK d@B%A 5;h1AjB^?a(L:v% *B!j%vfy6bOՙޞe* ^H TRZ%J&Dzh4b41  yyya0a00XTB%5z}IT!B&'wl{'ʴiuj&iVJjTۉ@UEQ0LEIڒ@BB$dB!nS|hh$!) T[ IDATaw}}ٷ,N!Dݠu=v(\DG&hoaDזΝ;pww'((N !Bn. 14{ bL5/v3[,)DC'r!>>>8q0k;Q֭[Wz{{{|}}oaDU-[ ںLB!htZ-.zk/<=k]V.cyql[yM$;"D'/s!D2lْXؼy3^/B!j^BR /&s!9W#Ύ?gج8~9b[XF WBzm۶t &OYNN۶m#>>#B!6لx>ڎMsoL&W~CS*1`;޲)?sT !j$AB[^^^t ={aÆZL! JqI52/JDkNk)8;:7x0٧ /F!!Zy9rs2j(vJnL:?̬hBez={4==}bTB>TUE!DK{h^F*FCN8u.CNTb5eSR.HQ!Mݛ~1g֭[ǡC8x 'Od׮]|ĢcoY5Gagv?Lbʥ߉)] d~[ VXGeϞ=NNNaff1Loz"""СCa֬Y̙3A!D͛*ZgggG@@@-F%hj$/ۍ֘[iqIC Q;&Þ'fwf{8s2'W'{~dֶ{&'kת !WLLL &K^M4M6 >֭[HRR3ǧD -wu3gdРA :cǎg֬Y(kPh 99Cu3v(UEбcGj92!y/`Z'Gy| ZDN?ʷB Mi=L10rDRlgJή{l~k(?ok?>J|wBJLmVХɩ$\bs>tRF.lWWZz-\xMw'~. ]q$?%...,^2qz)oΩSHKK7ŋ%ګʂ ?~|1_M8oJaް'^kz)i`WvP!DqKǏٳ%lܸ1|M B .dȑ$''˗mҥK%*MȠO>%;QINؼy-r %2w_0мB܈ص,=+E0qھ3S~A6Ndh(( ԴX^$@J9%s>|v>#=KLW#Lm" P!jR:7s-GVˆgZ2ayfq߷u߳|;ɀ0<09'!a8N<T\"kc/|J*y*bT(B֕Pb%}a&)Mx=(XxEN-tlذ,VVVKѣ.]5z-[Fǎo:^!nwR{ٝj;lѣGH]Cxs2E4γ t(PZ_; -N2@8hfZҮsk O? ~^N 3u~;mjȄWYXTL2V3LDv,Y++]i} Wp&~dž$T, "*j 3{Z? $wErF&KmfdORf.U,WL9{fVXxBv˒oFޛ߿h۶-M!&@tW!nލ$Ak;!!!Nw F%l1ǰ%N/M;3cCFm&mL%i<ןf^^xb/ȸZ{_7 j[;bKbeJb2[3CsqATQeLkAn[=v?{c|y_;asx G=^AHb3Yc_6kR0wh;7BAg낛1v68ۑ}%,q/{H7|k&=U&%""");|[; 9s-[KVe,Bqs.]ҥKk; R.<;<<_csN~Vx7mNX|J~{M6iּ%m ]y&f<ՄdgJIeO8!.<ŚEd,p kMhs6tbxNaC%a@g?,ߞSPF2'90I[)a%đ1@̮+K|F_ssZ1Gز=ơ4ag9|>˩$7ch^a癯@v gV/}D#㖥Z[d Qbeaι$-M Sc8OhHnI"--:[[*OIHH(q ,,3BTҽ< K]zKXՌwn"|,ֿҸ"߈s|/y}ic|G 'q>Myػw7ߎm\0Ds$ӏGCB4($ĵLwN < Wrr14a!U--ñKhh'Kz$O![ /%ښQFUӧɷ\Y3j&T!D5,FTTTYXXV\&xI ™3geF5֏^=n 2G]F t$>|xn gZR|Ľw3zEO^A~6vb'0C^*9wj=gAs bfU/BqQ,Y"KJ$p<8A^Z_BBG^w 233ˬwtt6%@eّzs QkT,[UQ;ʩN,&+.]A70mvxERC%/ {<0nS灙  /YѺ7o'EaѢ#8̩˃Z{ 9n$B>yVqB\yBQXY7$EQ=}ܼ72k d~=kUL(;$hlll3;99>..Cuwwgܹ,MJJ*3'x0ݬji~$qux+|k1/I)|C#I(8ˢN,y-Ѿ]ql@<EP+_;0GG'f2LcCFBV`(v]9r!y;fZ3eϖ~,U1M}닙׶_!rs'8ܬJh;|cRRRJ l%B!DhȊۉ>~w}Q2,:r#+[bvGw|uN ZQI0ڤIVZUHLL$++LۼcѧCFs+Ҫ4͂űAVVVXYkqdpO^ϴiprr*ZĴixB!vH[D'-dϕ8OAQ3a'BԪjϺT4RjjjQ4!!㞞\__SRR(Sn2I ~o9+rzmES!L0D (,L~'%B!k܇N9φ{޻ZmUT}˳ž.&&c^0-[Qu՞(xbb"C… edժUy,99lZVz !D5)L:v% *B!IF4EӽSko^"˧yhܼ{w͜Ϝ[eRY!j/ʪsΕb&@!'h,>++„BSX^|%JK/B!B4$ff:vBpiԵXx#lĻ{a"w#rYY:ړYo2AiӦ^oo \fR$-Z\Bk;Q*Jt(dBvB!BT+=];`۞\J(e#Tnag<8ܧ6'i^!ͨd@@@;ͪUhڴ5呙YvPQQ=%Ty1L:tHeB! Rk_/Z4m 󲝼Pܸk\8wu /"|y2n1A5 ݺuc۶maʕxyyUL٥XWp HNNpD [n]zLd'B!DCqGh4E!r:Nve(}iՖ& i i] !ړzbʕ+t?N"55l R- !B!BP43lj8x;:uoJVYg$gpneM*jO߿ V8iFU˖-ܼ:Fرco:N!Bqd4! U~ZsG!\qv,gH(3G\{?!DPc۷#FTXJHTTT믿Q‚wyB!B!LMmdb=j;$! $ha4%%6.]bƌUʕ+xbu666888TB!B!UgG{22BܠjIFEE1bĈrJVܧӫWk/""ӧPNҹsgMV! QcLPnw^!B4$Z!08q<퐄7ওFhVptt,ZB||< (3|nn.fG!>>j ^^^,_fFAZ!B!!g"ԹJB57=1Vdذa%[n͊+psss$%%Ę1cHKKM6sҕҽ<0[A&x IDATƃm Ch)ϾیM8h(]UosopK4oGIsy&%I~x!B!ꊠv lUU ۵Sgj;$!n[oS<?_^2 US7E~_/ּ/Oƿio͸#ٿ?{ЍS?Bi9Y3o4,\M6i'{_籟(1j%<9{ j꿬J|`ʽΜV&nǻx-Tdt}7苯k;İ`3lh.c]&M?K'kY5`giwFWi1_xNG"K*+7rίU1['<:/&93<ɉM|DGZ wWyB!5SVtj UUCGQz81$A5:}ޮZ}bu [`X'ݫ%;9tff&D(Vwǻp>fkEi޼%]NEOy5um2eS4\AԲ'OM텛#aKOYkû\ARW_Oߺ5-|gkl:=-[QO0#?i;?}ilk oÖ[Ե.kzi=ojȑ-)Y|n$nv}7BcC_azޜQ&:e6|pܬjiq3h/@9j_`K j gτ% i3 !B!jI`EQc]\ɩU\q牎=qUrdđ=Eh~Oﲠp2c=/ޞ5ߴ=xΝHk'_̧aGxk]y}6_Ɯ LƒL+HcCOriP)̸Ap ddBiN'1>߯`>8u8 qNcs:‚"rorr/ٝQIQ!|n:m 4jXvAO"]=yތ}LaSUQڮ\LG>d͌^[X|K֍b;t"--Nt 3HIٿ/Aheq#<H%@!KYjY o^M'nx%1B4I)Ld:HitS(,pM5x6=ϯ_ukX?;6˙G,ݼdі|mI$;0M#@f#I1c,[(*.g<Ǐ/촖g%d%\!=2%6Xl^+ _΢~Krsqtz -8@]̖?ʫgphpa`|ME{6\EvW8X5\5-c]v)N|D"7`7rs^:ew)/kxi-##:q f@tB=/o81''yflھJRF¹:Kfgn|'b8kWh{qdp-S{pw/dgt5߯GK2_ g#J׌!} ,Uњt6~~腜)pYXzvǴmnxQ.H6OfFS}\pFsOùL6_|ȾޑJd}׍Gn szWtc~[O`-<%BEDDDDZ9äO,]n䓅K(*) rdP*Uk}ۦI < kfYd[v&VwmCf,RwP epG]Wq]1 ,w=۶-eaYVuǃvv}TTT^=Vϖ'|N^4ٷ!֭cѵַ]o9G!++cX pE; ~m&OܤcL>OvGjjjc̙СCq:Ymq88LӬQm|?EDD!'0[00b=i'(.Nk0tLJp :ҍݨJ`z4^?vuj,j4#$.,WKg!2<˧{ m*AEDDDDDDD$9!'sdlfo9|z_Sg4e5¶TnFʥs3=sYtqՠi[5"cRmi|PQTDDDDDDD$BɉG)[u'ťy$H+}֫+H{a}ztɧ18v ٶgqocWu7 Flwjvo*?Ka!f<{jpP_ehյ[. 5gכ-Z9uCfҋގgͧs+k.go;O垗^seyv#*"%NlT$y||ڋ³}|o=dx6lɮΚܷ82n;|k[Vel#%;) 9Z,3\{?uۨoWVoo뉧ۅK[{Wm~&f>ϋ^獍g195~,p3.\͜ǟcR<$0;iE<esǎ\(6>_fPZ$}97ƷL t|pRl.x âQtw>4 :na!N{\˰eL㛥Vx/35z`Vu<~}ov1{KbPgyfj7 :y/eFkvCF z'1g><5͈lbbb0 X$"mmضMii)t=!)I<{"vc=clܾzuL)tHL4' ?U}~Gɐ<6($5VI$gCmTVZU綼׶Su8jcI}Xi;Ya+o=jwk9p+dp8pX:U;>( `+΍dC}kl-z?r ㆘r эKY;[pzt^aFqV ]н+~ ȯշXc{A,}遣nSE$22`"b àefiOI]ӣ+yl޹-*.aƭڸIޥ{B|L4aIWnŠ8Me^kӆxQ~_{jR˂}m׾Zdv;=H&7q­#:է29'$W,}^^_S| ˷s-ۈlR&Ńgw0U?ɥJXDi}gQgTɲ홛sE -һ IPm[9R6уymV*^G"fҽZ^]o@(Nƌ>b/yW]GP'Q;ds%qY y>g6C2OjmoBoC^y&bo95:@o|'bSrd,>{o-6@99[wW]\JC߳x}fؽ Tgk JXH E †3{v@9_=3cl,]̮^X9jDѮ,QX9D.V,QHRxiog^DDDD8L.S8uH.^$/ԟ{ʗ{r.v@Jri]hOL_o%{͋7p`ҟ(?QysF{vinQ.u'Q1g@Tgg5;rO3_󻎉ǑXFuFs# &ǮeеWC7I pʈ(,>4%?zgK?Y_=Uqaa0qr~Wq .Q^QA^2V}Vzw#1QRs|'nۤF%ǒ lF ׌4:&w.~F $ǜ!Kfs'0cq7rjccݷ5^ c&I$sm<Ј%=%5w0/x#pΕFQn~ֻN}Lۑ1717_mf\/{7z^ 󭈈IaILT$]z{<_6$K'߶džrzxXC0è OxljM9՗=\Tx[|uXB'9ٙ}:P]D|n݊"//n%$$GzzzCVt^DDDarڨ?kkaL9k *Arwzve)Qգ5oW*ni6gݪfJPm`"-l̜9رCPTYYo0 .r&f2΂_^eb܏ܷ۶~ ƴdBx䁀0L:ugO%&>zLbKك9|IIۧ$r>|xÐ ijeְaX_bDDDDDu>0鬕(PY˽wLafi7 YM3bbx<#qJ"qeʉwgPQTD;!9Qm޼͛7קOH}JJ|!aTYbn*Yu8 m|z}sz߯X0?|0mUU{ֈYcF`6/ֽ'0vl/wޟJH@.Wwttt#ED"""Wy!G6xK=^a5Y]X5<cLDzx{n.7̜ѨXߩ|ux&p]rMS9Gu)nF?|0oT{}6U}n~Aוiܬ|p"٧ROKksL?{5LcAjVQQQ~jIO%@EDDD`FRQ5gPߘ1R#/.& *UyuLJv]u=-r תS-6UMw#qY~H^_YcߩCzSN{w 0(W~_kn+Ev_1O<%-G}˟ǎʸ:y$XV]QJ< IDATNRo4#±rKc Ӱm"""""KVm\/s,F()ʃVM"nWE9bN<s?&snl۪-Y%?aq=vb}\at܍ϞJL|"}$ΰ:&(߭Sz㑶EIP XMᱟ& |gt~>W \+t'm-bde…x t-7 ~ؾx:ߏdln>xw^w.)M^Z,LL0cQTDDDD} ;2ӮmyL9}džxVیOˮ4*4z?@IбgQ഼U5|JUo5W{鐜Xo<Ҷ8=u ~+x9֡eYxwTpǓ".]+?,l2mEaL/Z&9,ޞ"?닱3 >;3oj1XXO2cXm"""""c^+)+g\x#+'F;g Qw5ѪUiFe5m۳߷p8M=ٶ' #iá|$LCJCwKaۨw͢D|=k$wz;2N\Η,gͤ& bfPZjCؔam7 ZVVe5M KDNME_GyEY9HI'¢Zm*nvdP DUq;|# JJzzލ0GvEE7o)-!'O\秼E6P^p7VL,>^_s l* _Ɖ"Jֻ3Q&39OLhQM Ԍ&1Pp GBYY%%%Ֆ2BBTGDDDDDZ =YYf| _|ݙ)c"$jF5+2Th6iuT-༫@r |];4cr"P%H0bsۧsS$$┉ AҔxA1ܛYFX\O)1yB'8[oϼiw̰ikbvEC-W&jփ{m~KNR4[Hq@ՈIyW,ӣ1F''%AE zȍ0j<;?yoMލPz]$s/o0WT,ii p!Ci:G$)=6_~BZ КEDDDD$xZr^KI'-%N阘zRoV\atOKZ I&9֑D#~G/jYu(6֨ڕ5+SSbLBd_W=HJltd"mg<#7ufLjAtto~%AEDDDD϶m19PrIэ{=7 q,]em*Hgu̪U Ъ1BKr__jU&t rݓ[յs#FIP6Gas yhi%5]STDDDD$vZr qxbc8g(Rq8kj:&Gê [9^9 koaW} ᭪g?Y3ɑ83H+6lTj0AIP6Y6qn$mVSibŸAYymb]DED&:! cR<rXy[$(@h\Aۮ6;__5w1NY{*PT4 tBCf89iv .. 6; 0Xźu눍 v"""""\ޙ wad0 tJI:>ط^v|Zm zfL5NSn t~Y[[D:$'6Ul߾˗p͛7m%##8F$"""""n5m8&BBlL;.&xq6J'Fd2MfWv-lO@cRpS0qS39.(=MdJKYyo;%!QTD|i]n߬XͶ=8_/ÿ9f8KlllorqŅt7ٛgaG ȃ=^]}&Ƀ=GL|bjMDeC%K}C9z1'9q;H+nُS3|@fODӿwwvNaVmmjAZR _̿ޙ""2(ƞvzg>_\qaSMc6sH^= o[&'U2e儇2wO1OFu˩cO&ťe,_NT{Rh9UUeWUMKБcyagįԷ^ 4+Uz 7$p#5-iE./ƭѬ6d1Ƒ4_G8`۸0::u8:Z>Yyͺ.-a0epD$5۶Hr(-+'+V vFG2䁾mc_S^^}t]Zjk)d`jIyo7x,ژ٬HNLJهtWЭS=¯*^ 7߮Z_g{ÀiRb*SMGĘ NscPvz*^vl7C *">[nrPKHH ..H7SQ{Z*F 4W6jHJKٱ7q-ޠSbbro1$4T 34H4im=czNTQTDmddd;ia˗/g̙M>fǎJ4 -YNE$&i|hMF cGLJK߻'Fxl8TlSPfSVn#UQM9$ ,b # GO=yQDD޹SO m"bCc 6 hDDDDD۶ꇕH嬱ױ&DD{jJV%AE@]۹$778D"""""Ҿ,_Yلr8`$&) *""YDDDD$lۦUaL5Ȉ`$f) *""\.HSV^AXhF #;/`$Ҧo1{9?v$"@7媶/"""""G+bY"-@"R?O1{pp)G8]Fi[EEEIШ`&""""Ҧض͂+),*&P DZ*AEwN c`f$PB+؁I3YZWeAEDDDDͲuw P=&BiJMᲱ1Iš|"RlPm&6###III DFF* *""""r vdmU! DH"-HIP`llY&d>MYFycWRfnTbUVBr`mJ,"""""x.-QOSJR#i_ μLt` gӏX]X,LL)L Km"rHlq{!W$î9$F$ZÁ<J6*$$ZP4=0Fπ:;bĈcH02r`?޹Si Gή౩!ӦYx~HBW5&1i=g'cbmkՖaS-j&111ժ2Ktt4DD4nLSgeHk_"&*~=ሴkJC(\M/n, qDң/)C+.Dhaa!@h"""""R[sƏ"*"dbwn{.N?))p<5g-`oY5).dK^wqB9SS{tYGϯ.7.',%AEGI-x=ѥcJ ng\N7sǸkv<S ٲ{1k FT#ˢ?LͯF?qfjOGo.{b7 Kg ?;7U/15-*NjEDDDDDDDўa?M7Iڕ=pl\"l#*xոG|͋/l~Ť~*G:.=Q{s$nzq%ŚJ^FIP9jm7yiCC}kԚk)*n|ջkf^f!W@˟w?rPP#|z&1|~ZCzNGSH( *"""""""r l&%1ie@`b ۷]ޢLWq,=u%GY M KKRr:p2Sc7pl3^b {r (Z{g1ut{H4KsRTDDZTDDDCi6e߰r< Vyd>f~t'ϯ8Y ge1 2zJPd.xKt">.3>ϣOp]7ԔA„I,f*_x˵fMch3&qғx縴C<41Qڸc=pZVh~~_ Zɯ;0H:o磕7gN) *">[nrPKHH ..GDDDD$ U0b@vU*rQTDmddd;ia˗/g̙M>fǎMN\.mV5IRZ2dH#""""mIIY) pDJP>|xÐ ilÆ c…MNtt4cƌ6CtC3H۶nDDDDDҲrVoĠ~AFD$ |;$(@nnn\P"i~ܴ 7;pDJQ%AEDDDD+Wq 9@DDZ'˅ v""""" [X]H v8"ZEEEQQQ7G>>mfԩL:!""""܊Kغk/a0`#"$SL=8\N|jW$Gv\ҬEEE].mJ?6mSNU}i"8q#6yGGIPEd90lvlIfX?h4ěp:^ӧc۶/hmIId_4m`"""rT q:LbIS7x"`c`{Na]N3; Kš|"D͎C.bb5pM:FFF`MJ>|xC )cXņ C>r=:;i%AE&eb۹18?Zl.vE)eV8Iޘ #±rKc k=1 vћ vQ=رc , 7772FMLL$66_b,IǤ`#"M$H0<Ȥ/=/O]ܜ?:$`y01J>M  +xQqc름Hټ=hD 7gc`9S[Y"t`baYny,p ( *""""m)z3r㈋ħap$u^ `P]D"A=K;7t3.a_ '̡Ԇh)-- K!D]o \k&aa[DDDDNL>n0yy{Yu]DO}{rXMzN^$H.#='[<j2I]rHH&<y=ZmTHHiLP0 UH>q>}*f<= m׹8K+ظ}7lpEyyyzvHN],.ǷjKEEx<V^_w&"ME||t+Z8>inJHIn݂]}}ֱ@n!NbchDigiZO??X;ەkyE=}|CJPiʖ7NV'yqD^{9t0:$P"r<TDDDDDDDڮvp:7>yo~GYi+{g0:i T *"""""""mXa_«xٿ2r9Dh~K^PTDDDDDDDڰ"|}2nK8zM8gBB6i+T-"""""""m-Yu687yED(ypsp~c3[ҳn%QV^ǒ߂HKQTuUUII _~9hT;2g""1M,>\.w}7n~3gr2k|C߽ IDAT,T9x<+ےZsl""R{Rdž4/i-Ӊ;'o~ ^s'M;PV^NJb"m&FCSchm1 , )) .QF1tP."uGsHKKcʕiLԇĞ۲G䧉[t8hevKɐ1'"ǟ*AEh U_}\.ϧL>+jsNvÇk q88N^{5jӃKMNX~a.{4ED-d䵷c [!\I8RʃɁ?ݏhuزaHR%HJx|/ٳx7ӧ=zW^aĉ-ض=+®]Z,m-**{~&""yOv̈cwoql} U^+xFm՛0oO}qxvk1Aݺum/Zog}9sp-p)4)v 7n\SRRp8{tMbn ~! , 55 ::{wxK&Ѳe3f 4>H{Fryy`~?6K =Y+($*"]Zb׆16ߧz ύ7*М.b/S3?]wӧ3eʔZ?\.fϞw 9 *DED/G98GXh}ӻpT" zlv)P7;N:u7.&LNgŶmfϞ͵^ۤz<8ɱ% 3qHm˖-#44:45nxUTN=q>L=tKk%7m4߃iӎCQQW^y%z v(dggCiP mH{av[8u}[t阂ei,BIPiuTARs4&c[ nʬY\!33)SXINN&33U&"Ҟw_~UY_TIQ{.\/>~_a QwMT.BIP:z:֮-=&Ç2e :tŮ[۶q߲Czy<%@EDFDDŞgL$nrz== :*.aՆ-@D#םxv1%?MĶmiӧO箻^r4sfҤI}Q}Zؒ{ m C(<@;!@H!7iB'`Հئ$ٲ$J;آ-M\xgw̜]yfOs:[xEhK,99ȟy{|+R~~ŀ=dnLPÁi5w\ΝϧߞE>;|p48FDD:W. w9L'qkϾ7v`;"Nfl"Y,] ^'zKPYY࣭G {H'(yW-y=pX wxוQioj *Fx7B[K- YA΂tto;|kZ *H*"rr3 dW`2Kl w0zȀG91(*/J[T'Kx[jL-AED:>Go[Oe^܍t$/'gLDN8 i+5%/ix<LIJ,<eaf`l,yGk׻W{gEDDI[jpt:96UWx f&k T3ST:% ;6x<@1|A-C;$.):s"""@K1c ~? ~ H}o5ud+k{gGDډ"sAh3 ]4<#E..ΊN838- ?]DDHJH +=@s-΃qehk4M̠:=֞6lBۜQ88W\`_b  ^ڭe||D{.""'(V^6FZZ:KFf/Kzzϼ\zvF&";!tR Û[@3 Ltiz}-˷nw<hgZv%H˸9l)AED:t%<_J9{(?xo<{pxj_cA?|]2ڿ.g^DN)'wD?֟KX"EԮV#TYӉ˥:vfkжLRDDbtUk^ϯQ+.=΂}(eH1"r"r9΃qR4x 3pD:Etoa"ւvy(\TDC%vhC-@ED:q?g-.|wdi%yz(>/qj!. NxwIƒ'30@38][f "&F Z{n- mZڵUTD2v\8nj~-n/b8N{("'.?p#ҙDk lK𖢖e@lvi)|]kX'G[ymy^#wsߺf萾HLФ"ᥓl b&Mi!u:TDkmfւuqoK7x*"񤌿_ac" `G947tJA]Yۂ}e n]<1pN2!R0AED:X?bm)詀 um<<~-;,{t|&"',9yiтmKߑ""@[Z[/4%ڱEDsopy^FιiO1|Y'Y&At:qlMt8P 0Qa[ tl;+i9( !b@v33A3zΣ`d@h۝KDD:(+g`P J5hzK-B[|htá H'@hc,->t,er;+"rRT:=@(b4c QÁp1HElmW^W F"AAP" h֠;{0 |EDk,m p]Po"+0rH{gGDN@;jmc`}9vRA}[jPHSKP'֖ mkhHbYk6o` g v 5L^9 SqL2d+@q9Z8ug,C_ Yk PKPΦ5y,aϾbUUD^=;;"r V`.G"xAuTo Hj)h k.w|7*^Ų,Aq8t{APs(}yK0p4A(^]}3>L8h]aW%d )M篐6l~A0/0 V| \ë7©g&Egd΂^}"cUk:$߅SD5&qv6{-Xg'%ږ㊈HDz`U$'%2_ΎZ&L] $>"?&8дV]  7-߄8~f\)xp&Z Ț &8<ee=?5/y烣}Eu]X-5? n죦 'Mm[=""_x4'""iZ,_qkFxiQh1NC]Pt4} :)11 '@~hx~o f8P}[9 ògj(#jX@έ047T%ת{>~2@JgVNv֚%}wiY޴ #w&9/¹{U#@ I#x7qV|g5 >kiA,waP^ Y߂I/ L2~ AV?p=9P:= ZσOpnDDD}HKi3d }{wvD$Z ^Brwx/hhiz0@Iu&h0D0ˀBI@!p>o|^vzA[po΃nrxTPNY9 n7 FS0aΎ$‚p߰xܾ֙~) =|'}j4uXoϚXT7~__zFOH*7 (K· kyO"""""""Ҫa.&};;"rc}fAjpX`tI0Ix/a"zzG=TO@kt0dv`g07[>olue&wFs38j zmi(=['Ի`'n`[DTqlYG_u[wпgwۀJD- %4ķyfA^o39<NB""i͖m45yu~*6\L=hYڢ4׶hҏl{ Z@IIY tKsbD=Δٳo?MmIFj CvTq}~3%$&3{@E䘲)>ygX1؋mffb30=7V@#^ JZj=_"go*fNǐ~ÙO9d>'ƅ9;e\3@~8x$7>.ѕԴ^7سu~ddӋ|=f m9bv @=`!E 6Xx"mY C&k<9d Q Z0޹HUY]UN9xq`~}A븍}KZ;dnI}}7tKW~F"T|UY)PZ`{-;ZΣloǚ"EUVrΔÉs57Ym'w9XY5cgNGJrR{gID: hn#㯸K%~)^u/W.`w>q#߁gRM\Z?~=%/m~/Z]¡lya.ޢ Kr{lߵiDZmZPl1;`eTbQt1[Dl|oܰ!_AIE#~J%,.ZK"?/[/+ "J>@72e#)99n4{ Rq*nZu!ſ֕QQǕwOu yo❟͞Kfwy9 W& 3㢢:nlbH^QӪ@$1,X3p;mi)ɶi+,6{p7Y閮Xn򞳢Fœ7?3-IPDZwOZ 1nHgu,z?2.9Ͼи%^~3ֳ?Ra7{c$;cO\֮FIj#~|S3d">srjVƯ |rNLak/a|NO) ^/|Pe.#HygrZOl.8-EBy\<3FLb ݻ=ޠ,E<8)Cy|9LnR|8ҭPPˈ CPTDp & @~xmD:֬!|tδMb[e6_b ߾r3a@:߾r+X`wL˄m%&ݲ3?|pym}ZDceixԧ'm,H'c3)> .p.l8{ 0K)C4{8z8W_zS~ ᳟9y(VSVl/r >YO>”Ĥ^H=ÁrzIKqqnwdD2Gx]$&Ɠ{ Xnw%҃ѽW>uJ,PO]=C2tPF\{=Ty`dqǹv|w ;=vI""r,:j(zvgҘ$%&5Q IDATQHcg݁966jr30_ _ubQW[C]m K>~.\!bޫů. *"rdDv"-H"Kc~ 9f7Vz:tQtJmǒ?j$_|ՀU?WO{1y]5Zny4QSw>MNjw-/>ʥF?ę?c8Oi`:w'!oiYAf<[w#5+O㪑}=cHb7""šض/mj1zAl];PH2N>+KJZ|M`=b!i, fhJh}OPpO v6Mo&M0r-d:/qdUJ-k)k!IWYk…t􉧶wVDZUY]aydEo,@F:G鄃e(). sߣyh ,oݴY?IM_D/'bU%%,pHn7O>Çv-0ZRW}Ck1/q=!׿{4m^p=0`~rV3k>;Uw׾\Q %Oijg駋kx77R03.8ëb{k;s#=^'K).+^pNDNz7l=|?ͽ-;oڬ\Ļ F9/=Bܾy9Y7c|Zme@gNkVq;H05b6z-<1{p=ඛ f1L՛G7bJ?kWxwn[7ރI_xZ 7/` VY}|q[ڽnn7w֢|.M*X]d/#_شt@=W ,1%$JK>ŕ&/ bmm: yc]muE?~v1-5_eTKdl*e÷x7?sCbh!EO`ix Zv).knr2ؾj+ CZF޷ևֱ,Dw}Q1_`}i9ni@ԑCv HXωH DΚ9;o`.ht)_D"4@[W=?']l}o޵So w~w#-y{}ݦMt1b70-w̻>ge[c/gߥئ,m-?q5 ׇGcmgcϾz4`dx`2'(C^4?V{۶0t^V< 9;_<6=k7uws_>~q͚m,x/=Keml;;U|k`u6zEDug\ r1Wm-hj8mx/jjܮyXŜxسk1WyCV-?wo{n_79?p%W[ vDL  Ct4n_ʜaiXY3u\NfY_=~7OiijӐFɫs~dtЏ9Y?bzrkOA9WK[ݸ"4PVm\U`8ch|׺;E=$?I\Ǎ®bTVג|9Lvo>ly:Zosޥ!-WaLǬͨ\ +5ĈտzKy{އگUտL12̹&O_Kn}?N׺+|P=$T|D uBGpWx2| ߐ71fPz y^y9k~co&4f8#ke/cOAP(z3/7-0{@4#3S'NO8g_>ˋ>,΢)hVY0HJN D-uD~79<5)|o~.g?0=x,0.\  uRr 1$݄ōį3ott:i$sA?^y#JKj;ۢk _x?ڲy82SD)!}Hx OA-(K d1'zrx6-XE_pSrut XzOT>ξD[8TV~,§͌y4&iK+IA5xV|54g+(.=`)#ܷQ=RTDD0I趛c_QAXǎ 'RYq'Lӌq|뻷&J8 DVE++9.>UV>8;cMJ݊Y[Dˉt:NNOSXFy /%hທ^{Bcz]ϓ .N5l;j_XɴPڪ+,ih G,A3WR}% p$ϛ9C俐z]_^² Yaˋ)9w=8߫S (IEu@}{ElXPB+>he9'^r^\m᱈_@fK!~҃;&_M^7+v S9ǃi9wR XpI vn8|Ӵ閝I]}gNGRB[Dha0յ,,|$%٦9=wҚ0PAʷ@7@8_LEYVj")ƛ)u\Zbiy|n[v4ilj"Υi"rJDD$HcSqޯG ;QQJO(?XƕfնJػ{'O %a]|};[54\6*+Z}e,HMKsο94w:iP߳XAP4Tz6Mp821Ct귃 r2Ԅ&Z(g.hN'6@r弳ٰnM1 $jp74qZ^xih'䥖`"1ٺ;vغA}zkll/G\'h㭪r 9ݺsiSC7ٺwP7lMvFzT{GqY9dW]srHS"'9FDD$eGIR(c@9vYi W\xVDoKJJH[7 ?8-+E:ZXXKUMmHZOck_p63y}fYhU|kh@_%Pa<*kشco~߳;sϘœiZ間%x&a&Z(BX۷nv8j bm Đa#yg!m>DG-N|eaYGb5kBҙAd+[Ÿ[މA,bޢqeaf9ezcYbҘ@ʵXVqCw~gMeY-~͞eY4ys((.cc(eh1aK/Dˋv(/WyA?^wxsgڧ;EgM9]sϘO>wK4tdz ˾c7SW#߷0yH>[&w1D|>vc߶3$GkH?oo+͏_|v ͟\hߏU>ϾJتk4ݾmP]S#/'.ɁOǞ;b[XiJ*8PVNzJ.:k:}zrVɰ}蒔xLߓȱ H08uԐD+AX LBU!i 4 feӆvkn۷m&1~sZ-f,73.I9,臨.",ܬ a-x YЯg>emOaoP,VmgM;˲X|MZ:x&eC htL⥅G4 0 =LW޶6ompѹXŴ,Zsz.AX~s&{cJWtM+}-F]q7-ĊE$ jwQl-APrvA eAЕƔY[mJ/kW?Xܦ z~ݘ҇i銵;<I \1@p[Dd HE++a 555QVrҒb.;,n GСx~6AMQޖ`/1uyXզBeYZ-Zh-Z35WԆ mNl@H00|̌氺a$'%Z/egz[~, y?;4 zH:O79 via.9g[n8kp#l<Ám\piSX{1͏qM}vc5'7{:)]z6sg/ .sfs.5ͷf VsO.|~'σz Ƅ y~ Kȉ<6)5# C| 3܁GA"A|lYir@@JrR%}’AhҩLO%'#feMB|\`"(*""r:eYݻK>m[6^w8wx`ΰIHa4A/ F zHbʿ?>=ܟa?h=(8m6L`4?3`鯿ܐnw3p860[ZŢG6o8u]:nTu0x4-}ko>ݻ:].nnmW!*08}(S[ZUvFZf(HymJAA؍>M'ަ'iSٓ')y t͞z 9M9WTt88kHG HE+Y+6q <)?pU}?j&oiKgX jk۔~F m " ۫M黷1Ȓ"1?ԧ'lr1&2}WXПlĩ/O?SS#Z}cA\\A}zcE:U|DV|(*""""A,b-4y#fgDV _WM|]xhHLL tkot#o\q -?XJ}]swc#I(@$Ғ>ݻnUukwK:c& `Yf-YIJOɧ`׻a8ћg%5# ʟ՜τ(7kn-GPŇ*>DQTDD$Hqi9A#EAh{ϞG ޠzCR[O,C@$Ң9Yu˲pLJIK08Tv=M+ax[^FdC:vw1X7=!-!w!c#"*>T!" Z0iGFP"Z!QrrߝʊC!s:Ǹ=$Pijb-S"q98< 3إY{chCZF%#Z7- ;\![G%l.7F¦`AW V54obtZOбF;ݱ`Vo9b&VDDgp\4ٴ +TDFB7"btӆu46C^ 9v,wDw4K|sGkGhKֵ3=wIL ҁ+>D^YZ+:g*>DD\av/>vۓa>3H=TYG{L*-@˅R IDAT-c;S pٿ0XaP[Sb}. |?QH< }i!4IFh=Cuhs]͟&Q"A?s kPe`W~mL""M)'\eA4p |P 5}aP k3Hp~ `d ; hDDDԟ8#ilk`n.?6wn8eY|Iۼ\qD6oswwc#UUi-U fX`hBam%?6A*܍]PŇHY32!?v g3L7Xt޼oBopBodAXV1͡롩 AUaJINdԠtIJ&c.`Ϯ}].7r /Z>zL󥋹۹+(9 RsWߠ1LRBB#9 ;q@hp?I[Y\y 'AMӇOZJaL䦊'F2!}@_k { 6\HLEDDN"] *B V ;/|KmM5.? . `R4= ք;4%8| עa& iw0Hٻ$>Wr#+>oIB+>JUg>~k0&G -֊TU|9Ar zT׃>ٗBaayv(/,haOh7 )jC"""][ZMx:| 3_]>L52}Y$%%O" ~LTFLJKnU-DqCYx<Vmi@4GD]`$ք> %:$(O40+6nS38e6~J"G*>uN}$d_U|{ jow'rLZ, ?%á{C@= A^`-B>͛`1FEDDPt8ޖ`NG_n!3+*jnoSO}];&!1}rꤩ8+,j &r-;rnX a~AY \*jn 51Zo` k{.k֝LclD:qC~n T|_}L,eBM_+}P񑗮hBA/$ xW`͑# .2`F츎sϳZ}?"""GMR_F Z J b u˯؆*OƏwnjb͌>$$a\=XfNh6 h}mu͛asn3I >~T? D""ChTNMDD8]Jm)y"lA1U 9nSS̠7[M1aI 8VP0k=x+@""_O#EDDA|\ed9Gh D")ς,~g.=Gr޿fdˇƏnOSS1.|ofd oawt`_pXsT!"H"""[ZJ\NoDFB@dȐ (lyKۂ>Jp D"G$91WNb3 $r0HJBRrqOia EibJ6_F KrbDNjUQ+>+>+Vujp"+>Z+>zdCD$G01H7f*kj蒘p[) ~TK0v1ivGm}7l!k6ݲ3#$9Qjb{~-"SNcϿq<5|cEL{@N뾸ɉ L3͟HGXu\a7>A!oz8v)9ݺ?ϊ/0)|݌8;w>AC""maXRqpBddqS;+"jCfwb:hp6zd\ ZakȁiEeu-/1g3HKIM_[KLMVt$xXuc`P}oj^~o1}a\|Q/=@=cm@E\[ηӖT|2QHNLftD/"ǝZOW^Yu[^\~ֺy|K[  ̍UK0Ó̔#Mɫ.vۦOt<1yca@~ynW>42v"-8oFs[?6mznN]P7>=ghUu5o08oƔcI\i/nbgA@]H(D:!{3r`&5a@Tݝzrn3|Mu0FI@c'|~ "*>DD:&AEDD*\޼ưT x&N牉q4wNzd:HN0[ f =2w3y3_EbG#Azj 7y^Fg_ ⤰¢. ?6ۻ{J DȢD Hhzoj^@+`HP0*DPH( d_q!!93L>+/&9y~Bb%F=0ϸK.ҁsJi$8x\FHVVAÎ1S!8آ`)*Ԣm =t .JI?{v NSyU<"ɹ Q:VaՉ k-V9)"Ԣp (ӗ}ߪ3fU'Dq7L HqEx΄VU999v.1ץn{ԪOBO("Iڝ"3ApAng&x #k!(F k!(F k!(F LzוBPV$Eg,UՃ_%),0L׭,` yShYz\tYsa:1/]8QjR{tUЮ9_9buyHR՞ńGg zyxHnQe袔drkԄ}ġ0WNcعDG&)6֐i+uÙG'_O5R`qn;P=BETe=L~QoݫGhj7~XZA @GTC n}@;._ǿ?kĠU )rS~P?R%kp=jAoNWw$k^{*:~\ڮ+BkMz&V YO ^Gy ([R.oT-!(8y넨v+zzx S o巘 /sŭxa{5ud~+@ *B S-djzź\n}^M^qъ\g8y(X{vp`]n| Ҟ[u8`UɇOǥ+wo%%WUVV.&ᯚ\DS%瀫4kyl=Oj 5.|Uk3u#g UeRxaEa(+g&(3揽wIwoTTO+~C݂Lԯ[m`}zИ nVz}W~sT tsz*!9]f(Sw*@F Ǚ}BdQDdTQ 1*+!|K =_EeUV \~k GwJ 0u@C(fԣ^OԜ wQ_[jY*UUW2^h(' N T8!k4%إ*O~vS狻{1Am\wnIWhϕ<%I:SS}>}nQכ/wdipH_ȡ2Caak]ohƅk>S:Y gOpI Ql.({"F*Lz-"Vn-WwH=T'^}B/Ɉ#5w}66%}:EzԫI7O>蜱O鳃P̫ SuugT_S4tyH#Fl>6Ե >؎hQS4o:͏.Oc}]93,V&''Gcu|] 9kSO3MUo;! \7R^'=v{u_-w˞5~ s5qrqwUm{BSԃϼ_#3*BPm<_#un^D k!(F k!(F kbЉk!(F k!(F k!( G~_#A5BP~_#A5BP~_#u.t"!(F O>5$,,L.e[PI}]>'_: \֑k}UPPPmϗDA}CBBL8]yMڷo$jhhp_{EC?o+] ).]I%%_%f۶.J^r;|KǨەA)22R+VPUU6'Cм<{f!{gu#G:= Z <䅇+++CGZr~6Էc4v4 ) P["寖*&]pv4Y)w1;MAnl'>hƌ2ؒL9NRR%IFj>j(Y,%''+))ɴƝ;rö38춎WSSZ>2337mbbW1klt=@k˥wZ%*% - )\-Y덶w3LPIҥ߯"h>|}梧=iӦ_W[TZZ}_O6M]|kj˗/WUU=jս1llݺUS.]L ZЯ_? 2a}+ζ{f˜ytȘ9i[ߦ cs+5n|7ug6S2V3fJJJ7[a-lIHHH 5~U\\bmx _}ΝzW,p*CЖۺWf<4onJJ'%՘ ' _pUR]1X, tKueI29qℽf9s_=ɽ{jjhhd,3m4{o*77ͪO3;sgv###C-mٲEk׮igRzy[TtjvyҀ[.. C3t=|VN8'O6ikiwq͛7+--MZl=˖-ӓO>hnט7BPO:41bDm999ڰauڙ/%@8-2 U}cӽS+ L 竪-)dhKڶxm榙(!hppn&Y,&O?5m,NL8#l3cv-mVvD:gGK03AoF 2Duuu?YwC:#&LPlllmuuuZrve8ulҦUH?.}1g+,,L FYDZoX/CЎ:O>=ztmUUUZt L%vb)Ɵ[r/U]+7Tn Q@@T?g?~|w 3fRSS%Is^|& #u]X,JMMW\M6չ^XIu7fI*-- /C}tڅJvIIWJAaM js) H:y[P|ae;>}FlڴIط$??2>kG53.\?_ ,p/##CgϞ6u&h^T^^R?^cǎSI3 Ϧ})5SzUMzؼ7Hכ.]?Jx33A[ ALмӋOc_()$$DUWWk޽noV=)))0a֭[g5,I?'OUb:3Af,vthtt[p4FcJnwpCppp5kt׶F δvZM4a3AmӇ- ;vY:㥗^NJJ̙3^{M~a}iɪŋUTTt\YFVttnV-YD-ܞ!6J/6=ZG%6 5IKCvv֬Ykvj?\ڵk%ajLPŢ &ѣǿ 36L UPP46kM7ݤ=^cu&httt=s66봷KRA)wx4IDAT4 gݫץRi 3nO@s}Ml{>>@ZjLPժEy5َ^W IDATxw|[׹lyc'8LHV ZhE~| Y H dl'{I$!8<?lIGGGɺosZt;!B!B!nB!B!Bn$8B!B!B$8B!B!B$8B!B!B$8B!B!B$8B!B!B$8B!B!B$8B!B!B$8B!B!B$8B!B!B$8B!B!B#!B!T `HF1\6 ;̑n8ȈS!B!  qS F`LGzB!BsJxXBcrB!B!)@H7A1/%B!Bs6$}/ NB!B! NB!B! NB!B! NB!B!H7@跄jvnc%?oOɯo2 * :h釳yLK;X¹1F~ _QxgCD`csxwB!B!@Sq4䗲P;CMӁ\~ia#(8.NJ%B^n> I\:'T\x(pˑB!B!48;yڷfcE4p"fC!8G]'O'!Э|d3ilL'8n)7!(0¸ti$/Qƨ\1 #=B!B1t 3Ͽ|dZuv!8U\w=ҧլ=w(ud^xt, x.ђ%/z_HU]lyC3 L!h{q#T,S%X#0YaKkluqH32짮qr{(Ɣ.8)f|i Yn<Ý|K%B!|=YF| :> x-|5tk?yM<J\( vs bUܶ$ 6Ts y{y|>*L>iMk]M<%7$1-[?^ϓ !BKRB0,J"s\1v\šEԵ^B.^Okyߧ{x5YlʺivQWNk?YN۹qɢHM #f3бuQZ*8ɶ0#=vrpɛ~.Rvu?0j6o9$_M2vWF篛o>mȽ2KP@E׊}Z2'@՚"v92b o㛳-c{Q̟#3bx'G^^`*OmfcoP;wϰ~a!s~}[4j6-̌yIp,S-pVQU%*X'i !Bqn6a6t ˗yomN!z;SWiꕐ2j:; n@n+` (5$KJ61.HbrH{[DŽѧȓy}80G^.azqO&0}uckWaˣQU'o(.fUx̲Fl_@̫Vc0zїLفkOJ<5(;Kg뷏5;Uh/x\[ cvsCJXxaMK[7Ex`iɭ%5)VP02Rkr4#2|i B2yb8֭586rKes3:ư,%E壻YS٪x4 =Hg3boZGs4y%״yqtpd=OhNY  ZDZdZGv"df\W1l=FLV8VG'p]Ät;Ɓ.5rj6WrV@mWQ3HGjnB;1Lo&o38ߤ,;Ҩ^A֔p~lVn tPXJUPc#XtLƟJ̘ J(2+`'wz7Ii˕w0o> eM!!`sFqdR;5nEHˊeʘ GsEǪ>D?Ec(M ^Gsoc}|bt]T\sr(=9-1bܸ0kp`ah˜q9ÙȞωs|۝6o $ml0!0"cw&s=ljM„aQv.~]'+Tc%{]-0_LVǗK#;`VrJ3%^ag\j* KZ =?QR5!dxCQmwQ0nfghM'e(7Ll^gUvz$apMPpfC}^ Xe!خ' M:(,[Xzh8;tI$ֶJVmhDatqV A_d4Ӯ!6-R*+ کo}nt`l#Xi;TEq[5?{0KIs󽯎ebpŠLPşbčNJ8>~{YVģ?G1B[@+&z>!yI )eM#D~h MO'8d%}d~$RLK*yhU][!PQ|I &\g!8K,Y0% FXÍ%|Hsh x [+F5/8WN{(yk<6K8s<'܏ĬaXKr<̪h@4k<[ϭnk֟sē81|~")b OJdh.~N[4@ @iuii'cz f8Ba8f3ɮ#d*|Y qA'.¬i̚[ xU줏 YTʾxT3slAh֊(v 4LqkYevk)/lhS&F3wj8VT{;%Gغ)&^Q-lxܾΩ b31Q̖VNV=ų<"u8k^ ¬&elQIa5=3bd''5lUKe;`1dFd;IՉ*6F9-yў#O%4=CIa_NZi2w}"YQ䠱I{G4Gjð&fQ5LqbF Y!Fg;r;O"=AizQ/Me1 pxMȈ "1br`C %:Vi%$#+'& n _e6u8̙%;nVj㳷=#dx0?WA!a}nuqdukDb lݏe:BxR6;>Bܳc"*)IbS2R~llǿ-R6‚FB.5,^sgEuHL(VZTT91"o.YED]-T}-ͥɨȼX>.;4GsPTq%>*fs)I\:md1*tشl.2%:ybQO{B 뿬 14װ㼷[j< '>Wr=CR MoXqܑn~N7wӾk#Nl)=[031 ;ƅ1kF8VuW`0m̙!Fvo,yiltejYUٹkoy]6;DZd'cZ"-N ەyrJsZBb0({^'&89Жb(ՇzOM3++~|yiﵴ:Qc"bz_ }r("QKĴyLhg۳O'.BsUk b@Xt%ngc>)]4h !뺼BmZ;i,!Bq s7;m5O[ʊc,sɢ$v`:AO6>w4m&f0vr$ռZ L%S#HL55e4RȆbTM%iSq+f&fjø#EL]ulU>^kgCv /dBl-*4iL oե@U*F~`ւrkt?V}Ùgv\#38y/b?n&`q[t3o>hrxu0J1nXZ'XPh vUr"4c-L? C5՞MMzAppаᢹYںE矆=c<\]o4v[E7SYJ .ghM`tB)+)&(W8ML2f%q5nc {kd*&$qek'9?8gMiK} ,ۨٹ$A>.}k-PCO[aD8 DXZ͇+{LY:#RyK"x [HvMd֜&Va_:y)&[rr|>o_~qJ)@jR_g3AN|>ۗjyżQhr0ϒ@v Sed0vǛ-h:+XCKw;Fj/oBeAUcpAlFEcemVE6ӑCE{gTpzڎTHbn"lv"s la{v.\{q (/33#,as 7qf KLt;Gl+f_lAVhqz©=Ԑfe eg֍\я;8[.kYL˺ww{U`Rl:0Uss=gײ>r4ly}4Kna˓kXdv=c󓍇ng \J!j#%/K\ug&8 Řyܽ0:gU8yomW8w5T_0 v򝗪i1})x7F2?4{Npe!.W. .>g!Nťͤ [KfU^6NbaҮ!0V* ̐(@u?N GqKH e1Nva U!%Nm.0b1= j /i,ϗoDkْ]1"֥u} =(, ̚ ՀU4 H IDATz 6nxfyTOgzkm}ȱ/idsLEscI[='H%);ZٻŽz-v[WLw\%5Hx5yjzpՒuVMH, X< vJ:B{aP!,_wI`V̲zv`5r#B:|!NH㱧.W.SI֮Kј|}8Ж .^yi+HcRyRGȘEϥ ˗IjwfYZ!m Wqec:.-Fc뙑(+1V L0h?Zۛ0☟n74.ں-h%Ȼ@?U6+Ap8L=rUU?[ *Ĺ%IrYd'1I&򍻳F8F_-~ޅtK)'l'`6@ nw_O;F*r1{jY[o-U~~łXRR#RĬ_`Ӡ_iJo.S(eeƭY\k;.)OG'3&P5>'v\kOfW[Zͪ:Vj%x69{@ksB3'ݻqL^˿EfpxZ2ûes#_9UUQ0#ԝk?݄BSϤty\>5=lhi+_+okYZﻸپ}G;}&ej~r?4F |f} L^w>{qb(r>E)$ *Cw䥦Gzssp$(.i60[\8vKbX5lfON+fz/W s!kT4> )AD))g@+} h?˃t. %⤲uᅏ8=_B!Bqfnvta"/N&*2p;#{ok?.fCS\YƬXbX`W8h5)*mvZPx&;ωx٨;%R-NQn1o]>vs[ F0w>n+a˜q,hjmpt?ysm=L??pk:F&-yF Y 14M5}BCq*{>!?xÈٸFE׽#CB!B3R2 梌ꏔ&3_:CꎠTDqH7AA}ĩB!B!NBޭ%S;N \#B!Bq6&UG4B3B!B!8Mho# !@KB!B!B^$8B!B!Bd_Z2M8)$'s_%<B!B!OS!N+ܬ!O!LB!B!MS!N\針vuUS!B!B}$8o2UC~CT OB!BqT(ӾAT :{ @+@7<B!B!8 1b|e:h`:XHcq+S!B!B$8bD 54/0rJ^ô[r>T!B!g6 N8] v H_=zg:@{x*B!BqfSZebzu]7MsC(L>+et^g…aX0MWk|AŏZR OyrN}+o(GaywFc_J9ڗ4JP(L=Jp׾}o/E/W ־4}طC >mH_F/(P HLq3 B!JF q woO_u;]3T+>P Tg`J@1M0QVk4 i*[ mz|,pCkç ^^{j,hlp]^{|=m )F)־[M ="}ao܍1/|,?Ծ0}yw/k_ρ!\%PBӁӞy{ozMNP`(. \o6z=Bj[g`}B!B!8Hp*jhjfސTk͡&n x#TմMv Q$IKbBzcSB1MaG(e(3px:N!B!TSץ M].-oネTNEUku78inqRTb9V fRp;OxmKt$NB!BqTa+k^W)ܶ6y]҅\tab`) Yykx:بS OB!BqTaϺ=CSoPj&irX^:JSu2⦫`f$ZC5 =UJvmB!B!8[Hp*oi M{ħe:'Ͽrxnj4`4Ҹ\&3s_QT8B!B!YഴMUk3 /i!$DF5`M{^睎ョkhrp:fQ6ކ}Z[[X,})b4Q'Ꞙ\eԩB!B!:/na\;#8ħ݅-Ή: 'r:?աWjVwߚpvmdB!B!8 NmaHh9 !wa Szep 7_RbMK YTk"]F*z^;cEax׀uT[anuLhCy.6{=>ۣWg`v~/ϵn. ׯvy~~ oPg0mm_P=}Aw[_BqUs9l5=9rFD_!imq MmJYD ðR, `(vaFGHqСsj~g0Z{Rhp&SoW}gz=x {8xyó ^޷ ﶗ7 sb9ݠ/ھB }ag|_.|ڠJ!8w^Tk/{TDP]Oںv^~i(C>U(\8P JsC > oy LŰx H ˻ڢ—m1k,QhM{|ٖJhp˶g[׾%}?o_3/ 2p=J_ >+!\ɡ'Wuijv6sy*E%=LmӉi:f6r(Z!B!B3Bd=C_Nsԩ֚V}<”v{yS{ohwF=qc27ώ=ub]VW6b\\ .ťx#EHåiQ{ә4C9zp&qUiM JZ;)k !BZZ]<ܑnB񩝶Y<;܊6^_&V}cw$<{HeBM_)"fz$S;Cl5ܿtTG N9_@|׳koyK =|ǚLOi| :9tR\:i]CӊVO=忧6\.'4}M~5ʗB!⌲sO%+tSBſzR>8M \ O'syvC\6WcUT6:ƒ8VD2V1io[mn4?z4L@q+m bjrǕ8/'nLQ84OfePV+46#\;=vL VkSܱ݃Lo@[R`\\`z klm \qf.x0~^o/Zz4yF} =R\7IZSU{>9)@M]{g[齮7 KP*Bqnx̛GlLBqT^/qgn?zMbC1#%65 $cT UqHf _tIcjKҗpg׉.ͥ»dRcOQ Džr(ndCn#K2XuKs̨nse͢0dGmNvF'"-6pHJ?$5Ww N ՝|u7ώ"-&۫v2×<W.;omotmjmuM'40] PZ@) (\(:;|׿4ZP2b7}*?6MP9hAi'K-[mJ҇t}(|߽|}/  'S}C h ~5 #}] ӫ/'+3fN43xOJj 51NczVtq8M^y(RZBhYc >ְB^s r),_!_ !ĐHѓqӨp+}Yoܛت2~V &  c|U@;:{ZWL '4u, ?{ac Pqpg==/tfϷn15C r^ZMmc ϯK"3srf$YˣL|>|/[7}jl_Wʻ=]>mkyۦ/ }/a hO1}~?\(59M/ R^ֽ|ٖC Jc_pX|m_f6(g".Y7m/ǿ0 JUu+q[|.cӥvc+*"@ k?.a[v.p4y׻ظ 1!C)ygABTD;7uޑ=?Y$E=:\ ruW?' kY;{&'@ڪA6+Fj=?#{QlѤ͈.ک@'zRFjjܷ(vK&*^ˮ5j(0ƒ]+쟏җҺL]FXS*0#:oh!=)@Pf#جGtd 6n74;``ׇ}~ 4vZ~ dZ+`uuRD) ˁ˚sM{;=](~H_~~-}![ }V/}|޷C > /oRF$7^o0{z,Q(.m0tu65}Pǟ^8Dzj꜁ٱ{?xvVVc'|/b2RCC3>9[7; 73$l!g3*Ỷvn//0&:&c(>1kfFdj IDATJM\N+ɧƇ29/%E@=L,6bZRPu7Ί5୒>ć[5?3Fٙ;65|n^O5Ĺchtmkۻc0ڷmc~U. 0p x޾su/c/ V^m[/o_pO_n`2 Kxb~}hk?{w'Eusga0QQ\!)IKnH\1qWQ&bAq b[F70fPdS@af鞭O7~`fut=]gNU1|}v: ͌wLă=?75kkk <?垿/>``7t,[}X \~eVիgiП>O{liOȿC{]IDDDDR^s1^x_n>^] GɚE/0o}N)̏Wҥ}yzr~R&?1vL .]1Xo^ZNne+tW%G{'Օ]ƉM6[?T]H?c1yX?|"o2{u%u7ЁG׏yj)7>g]?='h{?mW(m8sc9+1ok!' ;g\ةg>ChVmSȶmݺqܸG9;5YbxV]ճ:YְcexvttMY:>d'/,"š07I;e^ҼS>Ǎ'/o>nHs@^~}K?wdݗ_՟[ Cݾk9kƧ2{ sZyMVQbmMMF""m&=,X-1٫Y_6ǍN:pG1ҿ`ؒnەQ#)""""ҒR\_3yʫO8ttm:5]wkz2w>7g;戾\EDҟD6٦nm}ݩ#{Q2 y}n鹉L`Z뙛T.F-iC=NX]vDng4Z拵`kQ{#{ogM>޼VP[8<;ViƩ&g}`d.pAyݧ6ayOJj}K'x֩,ӆiFHұ" ^o*8S潵;fwNޕtZxKxpā21tl?~5}!<>~#AO䚩Yi;q3S=c_L]ܷ'WMkӮ 6ByG&>H<HRxǁ#=ʦԫ?nz?YO|DYjC|NȨ;-wQ_[+>G?]:QXr=+ў}.lz~g^wzhONJ4˾dݗut֎o_""f>yZ|'t:MNJ:NF7yxu[A H||bLY|?gØ<yk4q`1bLT-[kdLm% Ϥ5bmα>f%pMơ6.u ]x[}g-T_dne ,4OYhX$l$`qV%g:=Ӓ~2eYp~/1 &枅M뼳0|9Gۓ;o},f-KRQf;p10|}/ݛ.P+#יz?8㱧3ֲ̿vގcksȶo2P"7eCڭ]S? ?A@]]]޿Z֯_ꫯxoWlt(/oOy#NJk*gg 7yX~mX n]-Ag ]ꍱ,u;$$fl(vOv]ZŬ]{eiBKܶEo-/ Ify+ }e9[nj= Z|6%UرwgO,c_DDd[hie_{o6l]4R4jH(++}5ڛvĨa5x~ /|0iIc/!xYah)8 wV˨Zp ·k9+PO9혙 ư})n2K/bN5XYK[u,4׾BgKsM( 6,XB+ o#Y.sxBLYi K akl4K8h;k8mdf}rR)2 eeewz` ۭ3!.}2R~٤&J{6a,)ccmteSz,Xaucm}lpkp۱ KԗaNVm|ȝs 0JKx۶,An,@|&땅hgB1/> ϩ,آ,4[,hfg͘-% 'p[A1Yi VvIsȮu<'c߽FvK{jFNeeeA; t؍g_Zh_م}w_OYt:M*S.?KQDDDDDDDdkš*9~v/"mFSAތh4:Z˘7P}{f=9뾬ۤ>VN_Q.'NSNSVx@ G5X*"""""""ۂ&NEd5u~SEѠd&! _AJAȠ]jx4]Iޝzڷ4-+T:z^|A1 kDDDDDDDD8̢ޖ{~: {HpЈ 93\XrCQ}]{ nπ>5tlevi8X S)|?;4Г9T_"""""""H :0mrZit| -+>'|>^ag\]W_igiwѹb=OH,t:E:QgH 09LӜs>ǦօB" kE-P[[KYYYASZd2Tء[ >Z՟`Lb R{){>TT:MY4)?giTdr<:x`43PFvh }*$57xxRьV80ϏgF}5Ƙpؼ٥ gF5nmv'(pY?X=c}W6.;~56gO/{=:=ݶmY0fw)LYhYMB1Egf:,O: ۶,8`-v[]hZKMM ڵk>lӚXTmG?A4wViSѬT*gQn/䅇c =&) 4o3Xklπ%[,A`ԇs}gzu'c:ۈfZ;&Kcx$ _&źgum?-. xU,~Y ,_o͂{P}e9/ n,;8M2 &^nYifnذ5"fE34 A@*g6ʨ^G@ xQMǍ>\;Em? ;*g3:8Nˌ6^oAhv%}бcǂ8قt~5Dm|X;pj/J]""""6]ӿ ω""EֲtRϟϰa jTd Ѧnk8{_ڦ~DDDDTVVvWDDD 2Ŀ ɸGmD\1c]O6 ,e9f!j?,d͂vYp/- ꕅB+ ͉อJ͂J. nYp?wNE-ݯyᅞ<l+S.U?p48kY/l nϷ,m$`mDDD. le0̂x*l]aMfԆŒ XpXsӾu X Vͷ` o2)>aGeF6n\H8L 1Ѷm>_Pd}Y06eBKh[%h[%k΂cf<0X,HYh0 gP,'sDDD.>t~/Bʂ͂ۺ/9 e* -S\/f/-2 """mNEA Ru) SDDDDDDDDDئNl嶩SMAA&i.H8}?~< bܸq<3}'x"w^smm-Coo[x1cܹqu]~ǠA8c3gN}:u*k^]wnƸq={v2k׮'? #F`wgĉ,\0f޼yL03b~򓟰f͚x~qw{3i$"ۦŋ7CODDDDDDDDU"fse׿fȐ!L4Ep+ _~%=\|kFv{/Rɓyя~ĭJ:SOeҥ;L8:p-0yd|I7?̏~#>l"۞'xiӦ1o޼fk͛ΓO>{&""""""""-Im g\ve;7xロ)Spr-ijJ̙СCy7ҥ #G 2{lZN>d9>SZ?_?1&MSNo;w.C嬳`Ѭ]_=w}z;; ۏ8Yfq9p7ӣGNRpۗ'׿cƏww;;R)̜96lXg̙Xk}z)"""""""" mEQ]][o0l0:u+B~x!…^WOp 7pG2dn_c p@|[v={6@8ziŃ?=zW_8ѣGQE=~8555<R)  1cp'lXmWA jØ+Ȑ~u7XgΕ\ T6,{emaYȮa}Y0`[}Y0lB3BPq/- {֕l._;/<+~Aw̙ȑ#`ժUtԉ:׳gO|'iz- :wdܫ IDATO8 nnvzw?ԩS<icݺuٳٳ'K,٨"ۦ: 3f~L&Ì3AӨ&9;Z<Ϳe)l->(hYp+K_LcV1q)C)vWoͮd*eZe9),`q]e/5 .gR GYh?+ 6,ğ ""Җmӊ jc˙9zhnxcǎz7t=z`tڕ5k, 4o &pWp7&7Yb?8?0pgңG&',[} >|׋l:(R>,ӧO'2 z(ƍK3A}:,LPSƹgLPxG[XGd;`  $cNgKX'W,)?9͛b|m[l|L,4CYh,jk΂ g&ɸn) -gP*6 ut̂H[/5p@:vŋ}}gBxKroٰawuGkGWc1p@uW)S0{lfϞw 'lq 67|#F`ͻpU&裏殻On/|CK]/7ncƌL&Ø1c6ˠ)dg9dA8"3GSꭥz/SLkM7%zK4 f( –h{%uYjK͂u]ʂY(?[c?MEDDDm?1sru>cǎeŊtM?K./Էo_>x4NsSO~7nsv裏?)k֬k_goqǜ9s+{qg}կ~Evuҹ1z^:3ݡˀ YKK`kS_梥Z"گM, ᕘT&h[) + ͷ_l2@X|/AYpV%fxNeaꕅBBg^Z\UYh=%رy?޷Ν)ZSiM.69NEDDDDDDDDDvl-[G}jkke]0a;S^ݛo?Ί+ի'|2k|_dݺu׏SN9EG\H4TDDDDDD8x㍬Y38s9c SN6G#`ĉXkXn]|}O?93ٰaz+Al%""[8-N|ߦo߾TTTйsgj>cŵs;3 ?1/ƍcҥKr)ŅO~x Fl%4p*""""""[rvi'?pBVZ͝M PYYߵkWCUU .`]vG|G8fiT `3kg 3lg\᪴U{!bUo c,84ou5nX[qxu^b](,־k+,+ QZR\U2YFYK. Hn[Yl)> ơ^YhВleYߓ`ςf??tܙ &н{wVX-RpN:_f.FuW޴mNEDDDDDdpB/_~"Nֺ ]=zUc _|1EiNEڀs~fx2P[-#Y-~}O`fq7`ugݥ>ֺZ`PO]v[B6,@dH* VYh|f!ܶIe$mmK͂:+ ( ͷ͂{xiY}kg!z-& #}Q~i|UV;>Xk/>|xN.]꽈l ߔ""""""ڰa ,ht{~0`ڵCaҥ<3rlNEDDDDDUXS6K._~L43grRYYɤIxBx('#<ի?СC\sg3k,|I֭[G=85h*""-2A acDd۱l, 8z7w~X~1zg(l(l/E"x]\vh_t!0kBx,& ѶRWo,d"-2 ›d-) ·sóBgPġdCB,YƎwy-6w\8~lI\~\ZDDDDDDDDDMH8i@"""""""""" 4:35!"""""""""8@]U9|~׷Vo%~ڏp?ֆ˘ʱه(}3w[Y@eBY(fMY(fBۧ,uIfu[}[K̂kʂ2B FX,%fADD-j4pA l}1c<.n3k3n;6Q5uNkoHB>[&t0z(c\꽰ZAn;ekvlhn).QxH4 რ,4CYtij\ ,XZj>eaӵ_zܶUY0K6*omlm,ţc<,~eGFEnѰu[cp f`8֓kY)rN{f;TEoש37hqMn Gn}O: sM* eiBBM& ȂI: 험<\&E) ͫς[Jς۶J2 nBuҥKDDD6Kҭ[u8i,mvQ5X 9[renwnt`}\Nmӡt8f T;KIfڀpK2Y0,4e9f$༭Ĵs}iYBYpVf}[%?۵O>̟?={j橈lѬ,]E1lذ8tؑaÆQUUŢEZ;"""u֍aÆѱcǂ8uؑv7DDD69+) Yg=AqsWz2?~'2x`F}ݗF&[nagvN> 8cmݸ{I'{ȑ#⋷ Ȗmk>q}?7QFaokm|HRZfΜ 6,3sL :"htP8Q1mNs,n~um|uXl75}-Uh Nl[\k^RY0QBR` 0$`u|/- âcBaBsQSj- """mW"8.ߟ3fh"?~|}ݗz+޽{ߗӾ}{VXܹs8#vzE߾}y뭷nݺ NՋUV |rꨩFvSSS?O*bȐ!,X￟ 3f ~xbLZp9m 탸g[Ds`v<@1C -n;asČ3AӨ&)p.mt{SLad6-o]zk]ۏvSkrm7d׍cƂwc(ƚP~2YֽLw/. ѠERY#,Xm[j\}Y^Y(e7g\G+Yiq:d^/=zرc\]$ꫯf=Xʽk:t=@8SûpkN?`,:Z.9֛ k}i fо2X`,uk5^5dwlRNSr,WmX[\6CRY0&j_Yh}e˂16,x'/,P_jcP^YhalH,6 d~,& """mU"0a=Xr8p ;vd}ҿ{ ˗ӳgOrXk "@dS7ncƌL&Ø1c6ˠ/?1tI<3L<~#G~z̙üy \{.]w3vXVXM7KoC/O>aРA,\onc6!½ɓ;v,/"<_~q*\!I/""""""""Kd$pSNeԩ,Y] DS- A@MM WW^'Ė-_3uq:YX&{^W ϛ8, \F1z~JlΉKK`kωfZ_X+K" ѶRWo,d ,̂*1 s:fYp=P^YhlK˂J6 Ϳd;!Û?ȶ.sltE)ڵkbʕuF>}رcZ |'^z<])17FʀvWDYv-ϧ 4c @DDXkYt)gذaO5p*""[ sڕL+tsؖ=ҳ\z֙\z֙ݕ\C fVUUEldgUUU1x5p*&wƄrqzNx}^@8փu| |ή6l.l ƄUa /Op{O& ѶtYr.֖)_kP\:66}9m5\,`-֡~SeGHw1 /( MoswYeu[%h[f+W2hРnGDDdsٳ'-*XS6˙f?\{N,Lv3;]b=8x@,б>܁rQΖK&jXa=֭ޡmDr7> M[fnz7;R{_z4+'c\,GDɽ/( LYpO0 gA,EDdkK"m^[c lcҟ!aێM`{=Av7Ը{a¾d˜-LY(m-0젬oX_ĎS4XJ& x&,l},DQY֤kx/1 fVt~G }_PZZע`}'gb ""Vm[{ """[ """"""4p*""lh. lF^8R<'\ς)_w|=;6 lF|qkwA6 >-ٸ̢{>1"""""hTDDF-^'uy4ZRguR_g3X~3/8 gNZ[t?&|w~.т_/-n]Xsʈ3FQ֊EDDDDDhl6rV`P} ?ź3y֎-R?z L*?-/ Vjt|x-`H;2ឺoqz=[DDDDdK Cmmms"kZ$Y rگr|7!ӹ+K|Md u߅/{1ZNߺc]ƩgovCu</2;5K#N٢ 0oN_-ϛ!>5x}t8;yх?e"`m&>z_(Оռt+Mȳ?oat@swt: Rᾟi;sD^=7k.gwR^ fR`|r,m,t͂Hە2Ƅ;nPVVڵkyӧڵkH֯_OUUeeesL>䇃[O\6dwp VG7NQa!۾ێG1Ƅ;q뎇Ͷ#0l`g΂M4 gy,Ѭ/3 Oouv߲Orcە<Y^ɽ/$Š>7\4Q7's =ZcZ{bzr:PVFȔ==<lxLN]v.q'`0[e9) 6 M2 m%""v3N}'NөS'VZ[oڵk ?@UD<чdc t;ҭ[7:uD]P3C{dWokL퇻`f`DzoIgwuǂ1Xkpy}c KpmPQ.5K+S~{(]7{+Wf]z  Ʈg䅳Ÿ=~dϽO}?~ss{qMS6,XK͂1ǤnB6Wm[%=q[ehCOEEׯ5'"%HRk׎S^^k x_>u} Gip`֛֭L';zgm]ku`kqi?:;gme-NhYl(&l#8)cHϗ!++{|>#G) -,9;I/lMo0 n۪,\j¹t.d\ a} BfuYZ\UY(H8yeeexGyy9Lxfl=YfyT iNM0+?>['. Z$8uhTdk{辈l9>8;6\D~zȖjÆ <`tԉ=ܓ?^+VIm4""" /qkwADDdd曩fܸqTVVR]]͓O>Iuu5~kwq>}:UUU\~i@gٌ֯vڷv7DDDZݜ9sXx1\r oݻ7z+gذaCi4p*""FXtP__zޠ)!CaXxqc?Fc7l7ވSN9T*SO=/~ ꪼ̿vit҅/<<3{챜xd̙Ջ}7^nܹz}Ѽ;<̟?#GrE|rO#<駟ҥK0`g}6K,at9odĉ|ɼ _~TVVrW2k,vmiTDDd3Z݅6k /X ~vdwl={0x`.wQ?AB@zX"UPAD@ gSQY~wzP=ADE@DQ** "U5y~&$&~<̗ٙoyqb/BڷoѣYl;vy,Yח)ݛ:+|rrss=z4J)ZhA^XfMh9sP^=nܹ3{ae _|qh^F7nUVhтzG-]B!\"S!kSj4Z#)^x:G K>>}ml ƛl[P:"nBޭ\(Or¶#m_PysqonγKyL] [3\@k8jwvu }?>\0V5+ܡwuh۶mh P^=N;4~2e~I&eb)^BBB)))$&&ypr޽;v}vXlšFJt#>>\B;R8P 9H,ex0q~}MQ6'hۤxDW>s;tBNE&:=Ƚ3s&4L/3uMSyvzOvq9h\(k m|MA14E>M |6E>MygS 5v^Zᷝm_+lmk16@s*S൘:S:W] Xx2C!?m&C^NhHrQ&\|G)+lĽw:Prs`}X7sV&2\Pʰ0b.sdBdE룚$ۊcѢE,Z8BT) Qh)jm{**@E)K2@`u!rVI [(MN빐_beYJ-}Pد9;m|SBX;56Ŷ&GUx£qXq²%X c99daK)BqY~~,gCGqbx,aZVPMsxCqx vH \%aIG"ww~µT!G8FrxF \ i.C)E˖-_Lk7tˆ#_>YYYGڹ|0޶ Jy Nm4V`e8%t$OcMNCK`VdG ZXJ_A.^sh 3y"&k>reꪜ0S"!)Fy^xY{T$x- hHLv$M²Y Goǂ8k9X8&9c۰@f-e\[y=|K>Wi}Ŵ1c,͘o&s2cqxVZu}޽;^odgwweqٿ3%]SC*}Xs.d3-\5oL\#P=dʕL2CҰaC~W>:t@.]۷/ ,駟f1o<<ob#FrgcY}s=_tRN:2rB[R8BQ]Щ+3|.q;,lڀSxq"ۙ~.#(lPuZiMjRp$(xw <׎?OB^|EXl[L2%JIP?1u Nx眔9'%ywol qr㄰ !DUz~̞=y摓C ݻ7#G %$$pw{1uTlO檫"---fnc̙w@\:t`„ ӯ_?֬Y;Ø1cp*5rWj!y{ JrF5[w.U؁++si^\䞫~;Fa:RGP, ƛj(CK9;\)ZײqL:;HBEL//ikGljt`~M=ZT;& :kr N.T'ﲸo#ꕌeE 6.4ѽ**nߏsy;ˏֶQj{.G \xs{&-Z5)k6tF!"&a2T!DVU#:=it c߁${)=Ǔp( (98dޏvi_;I B!8վG !U@aE~gS`aR{$f6ům){Y7οU[ƺkGQ7ƶf<7B!"p*N֎\iWLqC^o8Ov.JDz[:q/gZnZkVXA֭i֬Y/D:5K3_iad6o!B!jq*TTTď?XveTe Yق;+~(֚]vkÆƱڵkSLa#g~q|ߓ'VcŮV=vU^z cгM"ٜfO:o!B!j q*D~ؠ3],'04 :iõo@<ǏY6WFcq5Fk;px5Jن ۊw+NumѮ]2 [+X{{݂U[-s_W?ɓ'_P%*8l/M6\mkNl\N7mIG Fy οC۵~!\hPs<\P~1΅y.!uNCk,JX cxYӾiBp@c+Eg~:lN-mQ@mn֭\.<*WS [ !.4r ;o67o.^QQ/'OQ д~.;slz5Fzj6߶8^.]|e^k),,d՜~gFm OϊmLߜxd"ʵHs,\G\^ qB 悍 cA\B!.) QغD2WDm8"T㌑uXJ'km'MVlx9Bc WѬN{L1O\d8ar+hkPP kɅ#/`Ү gz믿N=bݾ&Ov^+v[Y~dmFF*=ӡ}>[naXSΎ?\m<8oT@.hk{.Xw4%~(rҶ%' d <4!©uB F5( '޹$Wxܬ}5h:pjV80W5;q֣seԗeIVu;e][ہ^ аa#Ʌ0G _hѢE<xϡCBc١<+lD˯O΢^ܑZok.&Ov4qM$gmsr ][ܒ" ((wQO BPy_\0VinBX0\B!*) !8fԆOq}]DQCҹsg?|,lᡞkNm`4r{ӝzE~Oti1l0纩kDHswm;}!B!=R8BqLKаaC ??rwK,IM( 0[+ 3+R={ViOL[i'B!©BcRM-l޽+xQ9Z뼜ӛogůxj!XGq9ǻѩIrB!8վv! K-Qtk qE{jwx(5vɼ#w9ȼu 9~D<[Cq7>7rJtdάjN.`.K1~M!©uR%GZk CZQ\l+r֒ G ~6h9υ+z֊lf~ESG Z+4kNW nBpy,I|=FJsrr 6d4kB!ݻiذa8) Q'>pFNp! Ħ2Bó IDATl?x92W:0x6l_70;Qq/tYmrAczV.NZ+TK;%ʛ"5W AU qx񋃌蔎7$QRFq;"xy[Ju nBp`jn.*]#rA$*ֺuk[6m*#OBhZkvͦMҥKx) !hÆurJXwCch߁<\0VB3iѪI]1Bq,:v[,B!Mx+{6/!B!) !B*1GfX!/]B!IT!BTzWHe{c!B!<J:@Q\R}B('{Q CaQߠ?op2lP Ym,ڤ?hǤ:kνLn1 ڹQ|`r.(ws$*BE"ͅ`B \Pڎ2Jŏ[_`H:,>\Pm/ͅkh.nhs|[ %p\B!2) QR ZXdoLNm$>Xpeg\!R`kv#ze6"[^Ձx;m,>br6xj.8'$*#Pi7\Ր }gP$K?a ˅\0[sl[ cA";B!") Q~b4>aWD)1y-0Jo\ƶ-'kllS]B!R8B!.F y3?.Cӄj|=]=][ 27K4bvow5B!KB!KzޡZ/&#Kھj{BcNB!k~wV#ocCB!©B!pMT/tl?']B!""R8B!l,bXwE!BcR8B!j\<06:B!"Xw@>KʼV؀:2[ ^i,LڷQh@c)80^) 2[Zợ8ŇRWYAk,(|a"Akj.^ /P uV.j.({ukL\vQ.(:x\ *7\[s/Bm1!.;6(aЏ6J^zux훵׆} ;} Z^IaRQL78t(]\Vsr.hsrA&'=Iqc4]y.D%|,8rb`ՠh!/}yG[ rqPѺB!jq*D`ka}֞*Nk]F6c)? m~Fh46ak;wGҤ}JM*n?:a9#GLw;R.hlɅ I.Ta.XEV.XʏֺVi&7caCD Uh!(|y=<пO(+n9/B =q,?[E;Ka/Rҩro F B!D$#NT;J~?:ԂY|ɪ fQuY2EomI.H. Hs!t3"k;\0>cqyxv~UBfO nP|2S]qlB}CÝ OK䯟gMw !4) !Bj/#3J*(PoʰA#_8 ˚ {wf}h3Y}Էᦄbv͟b̧l ػ<~ :zر}?û\'e>T!p*B!5b\Z뮔ê"Z" }7w'Q?Xp(%LYOɏ[kQTh9O\>Ǝo[n/.(llu];bg,ۼ߿}ҡCnWg222teucΝܹ_t$6B!Z5o妳ڐ੹;E)zo,=zc+NQ?;Ez;oMl΋ޙz(yVUђy?9OIY,%snuIo0zJ/f9)%CcDO>w]RRR8S1bcƌ!...\\2޾}={67o&!!̙3x {ެY2e =\η* '.6m MlfƍL6~!p8B!c#2m 8)N.zc0^9%PD{y=%C7Tm4|{ vLͨC&zD<|ݻ,ye>Xfw~s&-f{xcR7wm=?[Lj[q-[[n 6)S0zhV\\&v…=N:ѱcG.21ƍcܸq{/|ᇀsiG}ĥ^Jڵ+]v~ih}K[l ?eʔreӦMddd`Eɓ#Z' . nK.tڕ믿۷Y挌 .B1`ڷoψ#BdLaeȑ#ywˌHaa!zE֭[Ӻu#_{ !j) !B+͓8};O҅5\tQtƌ\}|Ws![nFO@ZZiiܸ1Ο"~anV\INN٬X믿zziܸ1(hܸ1)))Qy]w'p!O8qq}O<;v젰k2qDVZU0uT&Nʕ+Cロ?Oa۟7o///vŢE"Z!) !BEI*~7c;~!@k'̌3֭9t<  ?>ꪫʝn׮]xHII^`l߾}6h]G{%>ؓN:)k.ӫr &Mb֭5T Z%ź[5Emχ~2dP6i$?낂ß*tR֭[}W\޽{NK\wh5k(զMR\\rh+''n?lݺ?,^9sp=ЬYrW6H !DM$S!BQ4kqmג\ί\V:מXeX=KE4ҥK]Qt*gmk.~̙35kݺucذa :GyBxlۦcǎlٲ'xpwT:/ݱc[˗KHH --pB/_eYe /%edddFϺ<#\p|嗡{Xr )))L0۶KF6m8SYx1@mڴ)'//*!%%M]BKR8B!5ׂoDsV&s2{#Ok@R\e=Û2G>NhWv؏φ1ݝiN%{&/m6"%^qN8͌ }Yॗ^⥗^*^ǎyB7mڔ|ロ}q뭷/,,䦛nti^hٲ%;v/`Kjj*#F୷bϞ=;({pwٳZ3qD믿n<}^x^xkˤIB#Ycƌ̝;88#[hQa,ˢG,ZÍ8ٳѨT!%) !BWDNlry9hcf7y;.eY]uעLv>|8cƌ!>K.VZ/zji޼9Æ [4 oW_wޜx)G$VnGkNjO >0|.CHIMeڊ2pI״# hG >ϯΣ|~_kl >[u1(+'5}()''>kkmm|Za;}kvhl<55 Mx K,9ٝnUCxz4Oq\ń,İF wnϤE&e^w&Geܸq,[tV\Yv-oqeY\wuxbBXB!rj2CNMfC|c.+;(ؐY{>4ut=&硋bM6SG]fdT|H{K4(OwxRxPC,弯R z_;qcXJc) W>{JFY ?.g;E)qɑ's +;vdܸqL>Cʓȸqh*5p*B!j]>fͬ5hKWh%x=^NaP)g[QNq3ǣ4QxSz⧥Z^\$#kUۋX˺rs<L ^Y1׮u_xZ}ƾKrI"V:wL֭7o}>_?f$&&ҥK DݓZ!bI B!xf>^^6iqcd N~qZ:8>?f N>wOj^_}UW^ŏڀSxq"^}L㒮tkY^qoPS }{NM~AWلmq۱7eΤ^b"vMᆾB3zhF۱mgux<&TBEq*DP%2(Ch.5ށ@u&&(hmݛPG)ctAlv>ԁuiҾqZn[`=R.`-P s$i|Թ{vBn׈ݝф_ug5dd6E~Y|kr/8*E`k8./-^~刦 >]KLN)طPWsAa_F˟kǰlT>)VۼƎe+&= IDATNBRdĩu@@kbZw,xf)m,D(ؾХFQ΃%³Z^iN4Σ2*rxtov.AFwNB%s;BpK.Or2Bɶ\@a-st=w"˜Z$C0?9^ &5Qst9!]s%9ZC+~*sDЄ..Gm4J%em6wF+?hm0"Dءxi<ɴ68,]m,6  J.T?Υv526<;\8PS3<()U \p¡dJsglY<Ԅ~˗/STTT !""\!HT!BE6.~ק15O1i$fΜڵkM? >T;&xJ3ydl_em.BpB!xb^{mt*{wظqcRL2xMүf>]WgO4]fիWꫯy϶mXv-;vm.BHHT!B?.dY=m< ~L:?&Mݕ¢dAKwu4z[n<ӡ>'|$)U3B!NB!DL.J&2͛yOШQ#nV<Om?kB,ܞ-w<3qĪZaHB!"!S!Bsc}f!eLiݺ5Æ ;0&NH=@f~}K0ohV?SW8ÙgI݉(ls!B#NС(ZeޯG)RGSĢQ8h@M'A;mQ?֥;Y_ȅ@I.H. /C.iQq|֚?Uge=2y<.2H./\PB.(p1u`C>Y~>au56 s!rZ+(GF]\eX̅pP{бq.Df,^* 3<֭[Gbbb达G64h/_~%9Xt)mӢE :u^ !Nty,68 ƣ&yR*0B2O}ڷ:y6/i(RPVf;!||0¬n炳nBB$*i.l\wr\Pni2{<gr ;ڔi.DC)c撙LZB1MR@l9\i.Tdf̘8OGE-BKuF&MdŊpp0xXvOQL:@S~B2xX`~0^kxlk@f:iO@n'Fj.\\\s!Ծ`u.D_:VqO1c70l\><*%+UJ+KPy.:9}Un:>r?/,,䡇⬳΢SN=:tI++dҤIt҅:??Otܙ^zoigtЁÇWɲuAN9N9rrr2e ?zhƎڞk׮ gnF:ugP[I)XdI9۹s'7t=z{g裏k`oQFѾ}{ ?_B!"fj?wNAb{^.j&5 >{1^}UN?tڶm̙3kYpa(fҥ 0N;e˖q7!C={6>  u,Zɓ'FϞ=Yz5'NdΜ9o߾:]F޽Yx1K,aС,ZC+9N?t,Y7,nUVѥKy瞫4hӦMcL<͛7cի_=k׮eĈ8pٳgSPP?)((3`<$%%qoa!DՑ©B!Y,ؘǜ뎏uW5qXwAT3G/##/~;4roV&L@ _Xr%7n t֍W^yON(,,7ߤE2o<֯_O֭C/tڕ ?3fpWr 3Ce,\: ҫW/V^ 8W_Ekȑ#Yf Vj*uƔ)S?~<#+++U>}ڵk9p@2x(..cȑ\{бcG-[z-rss꫹ꪫ8p#GdR8ER8B!11uAl[V]V4#D!ۼj? ]4p@~a CduNOx<ԫWBD[[n|n҉1d~-ZggȐ!x>>o!XF8q"O>$s-_|M7̷~xCEUƍGݦpOzz:gqK.W^^88 ns9ѣGkݺK=;w.X|9IIIpp5PXX_WN>d.b\TT8#wztYQjͤB!1 $)>XQ\{4m4TZb , =)"RЩ @vv6fРAٳ.]U=B7|iiǶm~?_~%|h[oذ>}0x`N8}iЀcΜ9ү_?駟ʢC\|_>@Qe>.-[4hƶm:uƢ !dĩB!v3bi(!ܐmwzO)ʼn'Ⱥukc͚5Х4iޝGQ $$!@N"0Pd2 ^:23.`(,2"谈 EGuwHҧ;iݟRw:UuΝZ.~isqC\\7|s-:OΘܹso>:vHn~- cǎlذ$>cT5|qWo_Y۶mb|wض P 7o6l`>0ao&+WdȐ!dzi&FŌ3µB{rƩB!rՏyZ=g R_ҭJNJ7{lw͛~駐q3{l:tM8}4=7tS/#!!+(24ڴiÁHKK^@)Rsr7sY6nHyWh㻧iDD߬Y3fϞM6mׯ:t믿{Xσ>Xf͚[oѻwoϞ={1bD?N!+.x,0i߹yEapo[I./P~Ö .˃vst[ 6wrN|oZW6ȝssŷ{6W4ck?ׅ\v` {~?f'k QCHjr0߇:MK֭m0 D@dddˆ goذQFѧO|jB8R}!w1d"Gc>vcڶ.4Z{aQh2OC)ăWo~1eu W.(_ e\ܟ ErAarA)m-r|m4:ͅ!gƼjq?-w]ȅ wheq &e06*Zۀ&0}քUgժUL813!ą${)!{pm]R2@R6Z߾mܾ?h,F !m{׻lk.Arf ߺ\(BEܶب0悯p&mD< ˬ7ϒWcJ}?UԾSZ >:oOxsA;r4ޟ fw*Q΅ rl]_rXm+Dۗz#ITz3!s t} 6m7Rfg`9F+UFLqC4h}1&xʅÓ u/PNw$*h?\-• y5ٶ 5L=>؞GFj,ёk\ô}Ʌ Sr!5;LsA*4zhF]g={d޽GBQ1) QRhF)=Ȝ35`i{)  G;2Fg߿(^y5hx/Cl4.0WބQI܃L(Z+Sr4}-uQr{axrA)_ e/PR6`Y\› Byc+B!B$S!BqA|#A B!B©B!|f3sluwE!B#R8B!a4vѣutuwE!B#r7p!Bv%#5B㧟~.!CڵkW](E B!"ݚgxeTմBQR}!BVŗTwWB!0&S!BVk~%#5^.B!\/D`RRb R`vvʧkx7i 2>hilrdkDOm,KAJk4:pIeaK\m+Ʌr%o :̹A05*Z"y"\@kQ%*\(悶5a߱y.!N,vy|N@c{n8_:x2$4TrO@e{ _K• %ۯ\{Ʌڗ\(_۶V κ/;}yD)zܒ _sQ.(2-D)|ǂ B_R8кa[QGilA) mWJckwΦ0O3A,6Zcc18}?-m[460BlZr, d.XA m\Pt] įٕGKhBKrڒ Ƃ߱q.!N4/4JY,v?Qx֪t;M.g00F qN N(-L&h\]z-~ NbѺ]\R˅3v$"h\!• /_.C̅r=6ݝwc>BYB/`w : 3H _.x!©B!ϣУܰ"B!Pv*iy󄐧udggU©B!O3Ч},F7B!BZk6nƍٷo`Y)))\ytyb©B!5?rߵWw7B!Dp1x >Lׯ[ƶm:Dff& .>c4iҤ©B!r{~):WwWBAÆ n`ʔ) x裏8s z'E5!E^^>W #ѕn3++9s0n8.R^oܸe˖ /pNB!Bi]f9BQM>3k,.\HNN<@uwKjϚ5׬YO^^~,((`(:uyEӒz)S(**bx}hѢR<|0Ǐ'==w?]v{<3c=СCׯ7ofڴi<dee/_Yx1)))L<YC=?ҥKyWKrJTTC !.*e˖q5הzO:3|`b2|`.sHm>x222O1b7|3HJJܺ1cW]u_|۷gʕ?;dٲe%%%?Oy睥_`O={ 6l`,[h;u999,^iFM&MhڴO IDAT)LJR) Q(Ufw= 6q}; rEX of`rqC{79-:tؙ0k.ֽB$*F\pbsD>s9%9}Ʌ2Ա\0m^`BÙ :mD^}UEQQs~i&NGaʔ)T1W)ϣ>ʡC4iK.`ҤIddd裏V8m~~>{/^{QUawBvv6M4aҤIF9rT©B񯺭5w8wJ #0]eok f`4^y>)ѥwZ^77hIEޟo+BÑ brV /P~l5;lN|xsl[ oeӯC. ιt&Gr \ٺ -LU8s!c|W 8?`8ֹpM8sL8{'N~ڵkG˖-),,tp8+,,=˲5kƍ㮻 55YfaYO6hf̘Qɥںu'{DFF?bc3Yz))Bibb" 6d۶m 2Ajխ[Obbb©B!2呁ͫBj|_D(Y( 癦,_}RPP?_6ϟϥ^J۶m3g͛7O>\. iӘ>}: ̜9f͚SOUftt4cȑ̛7-K/_`;?66V+#W##Wö5mCjӲ,zپ};Fmڴh\l-NB!D>6}/iX]BT)Sp&MDBB> s!;;VZUwD.ĥ'Of߾}qjՊ!CcǎJ9n8ϟϖ-[HNN__?sL|I.R 4~ب݄֮]k܏_Zc3Ϙ/\\\,}Yz=k֬5} _tRZh~YYY,_|6iV>_Rn=L.r{ [p7=_^^ xA\ . x}7K9<_\p!\V K.~$7<|3LU,lŋcWv/ڲrAc],(B`54 o.?t zݭ[hg !۲y^NM7O0߶mx7fԨQy_v+69T!BTOsǕMB!2|x>0==oŋoBiݺ5EEE:t{?wQ)HT!BTSn+d@B!vJ6mXr%[la޽>W^dddTp*B!*toC' !B&M0fnV8m\.ڴiqU©B!OfpB!LM.$''}>rJB!cygp) !BC8PxJV Z>7k_` DCm_iڷAiжA۾Aiif;pu\В Gr ۿÚ n`s;NޢMc Z.uvj_r\\0`mUrA!p*D=TAs=X62<G8۾&(x6/޴}_m+tP+Q |Jmpk.8FrArl s.pqއ w BJPJr!@Mp ζ2YR0X<BK BZYsPm& ΰ|m>Xhx dYN 0i_ak\ضÉwxa0X`k]7f-gXbɺwUrxۆ' \r$ʠ4)dӁM 8Ʌ\m֬\0޶ g.4BK B팝:&(e2]g>ڹ|0޶3Ara m4VZ.TI{/8?6&n:ul.hmc)e~`)pά\(;^rg\Û f vqibEC <\І\\Pʷ/; -L߱y._6E4yB 9/D}NB!DV8 Vw75DMDy!6) !Bdt+B!uQ_!B!m hH/B!) !B|}.Uw7B! ) !B;Vȏ RB!p*B!lIzIN !BInH%^>l+>Y[] MpumjuwEcO|ǵ6\;. |l o;Ŵ:!B!Na#n~?s7JHf{Iᴦk^yOyit<Ю}1Jhl:FhmphQmkۙΨl*ew_F2͊OXZw ć x}~|ȫߖxYVme ˷.qDGxץ6s(/΅╍6Rh #wDUBqg۪y<9ǂ B_R8PƲ(>Hc)bh_SoXqXwؘ -=>b̶ W.oh}βJ.L.(@ xm.kRκ nۖ[x(hoɴ`s,>칠;·a\(3^rrl× cA\B!/) Qغ-gAK_F+_J9CSj@Jg(4Rd wb _`0+BF{FFY Cڴ}-X&g~BΎrm'i8-cm~m˷2 xYô_\(6 Ǜ 2:F g.sA!8_v*iy󄐧udggUkR8^(0h4ZR.0H8% oAeV58h$AV;\;6<`k eOO\(`sY^x}-d\+׾K&}˟ ((wBTÙ 0ewBBԑ\0Vi߱`0 BZk6nƍٷoPcY)))\yt֭ʮ,oJ!Badˡ|/`e+BZcF_~9+Vs:EEEgudd#66mfee1gƍ_^s7l2^x~BB!D ۞c{ l` uUBt,êrsE!FYh> zO>L6[t\$//5k_YJYPPQJ1u%у)SPTTĂ *}vN_s8F UG#$F{+5+|N5Pe [gt~}_x9fBH`t|y,yp4Ư"pg.dmL||mf֘1>̔;Ӹ<MTJ/z#%WP O[WU!3<pB"##m6>V\I޽N^?"&7xf1Ge/pk1NiiOLIDY`}#FyMc4N o=E.vjX]Bo bĉtؑw$%%?׹馛1bڵG)U-W^ݛVZ1aǩSh֬zbժU|駴lْ]^eV^#܎e\vY`s3t{w(.INakוɦM/?~,C}+{fiES( ""˲3^hd%ۋ.qƴmۖKqРAnw{#>:tI&tR&MDFF>h5oޜ+Vp5jħ~JӦM袋>B7}Je%S!6QQʉר)_9+l%eSİe ]Y(47\D'^)7fO}َ޷ o.(U?WIzq{xW@1Dj:huœ= h'H8 QQ_v?sk oѮ.ِ\(;AӟTRݵ^gURX7u.Π+Ӽv)^7FʅgmWxD,u.wYR`=y8R m5;"\^GruZ.XʃCkP. 99[z䀷Cܹv=HW_1p@%4iB>}>}:qqq\qU(u޹Mk(>Rؒg>Ų,f͚Ÿq뮻HMMe֬YXVGJ)Zdɒ~l95ڤI&Md4#GJ ) Q(U|ĭF)߿S 0~e/lͻo$K?[ ,<0KB-Xfg]5GyקҶ3q{5.uWQo>;?2)3j,ެeq%yunݻy_B[dޟGl{HIi}Niذ!۶mcȐ!y5[n%>>`HTz֮s^{|, ¶M*`WEak.P^@udah\Fg,509_fl[g˘ hl-ڤ} (ޅ{ɅR!,lmP`kb so.s!4ٶi}`BpGX#BɅ` >&v}{;l "wW裏/K/1b.R]v套^b̙̙3m2cƌ2SLL4|ACvZj8>C ,t/_N߾})((矯tK/m۶̙3͛ӧO\. `ڴiL>fΜIfxꩧڵk˳>7|õ^˲eV4\ 9-{psW^mkۆԦeYу׳}vӍ۴i999 8RT©Bs48fg:ጚ]DHf'޼K M׿\^[FAeԾo@_I.5Eh╦x]֕}չJ.[2υ"[ؿmR6(7җ ΩwaÝ ˳u0ol._`V 5t& &0a„r?|t\L|*XM/Thf=/ٙ Ko}6- "|0S&гm|Pյ'OYLՄI}.FI !B'S!D-˷.5 Eå<nф;ݭgx{L,½OĐ[sϯ:;ϰ&(e2Lج{V(pu6#.oLnGxiH?.;I+\-\ iCfh7l3kDK !BQITz@Q|٥R B_KJ7o3Dr=9˺=gdYr݌u+.uwwqҦN?r24lR0#aPڮ`Bm\(>3!>©@K/,Z Q<~,׈@X&,=}^&S,GbCgв7qi#w`8Ś@Wr{4EBbOi'Nk x[(eMiloˬ;7ެ}]:m,>mU_slyCm\ b/W}F]eѵe4[劤fŊ$22b-͉rԨAXDr}AN0)7,lmP,6ecZ&i…6[A9yl6K9Y7D=KSmk.˛C0X8S"|d !") Q/(b'wXF> fSad]70Urkadʼey@h"iliԗN9;Ӽ"؁ GSދ"]b/ڊ.NMu KOo7|4eꪫw7$qQofnqߵMx=siŊ^aRSh ~*rs 2+(1Qqޣ {5ُa[')bՕ[vkĨ7O~'iEy5N͢eT 9CӼWJy>9P1F[rMEp_AT0Oq%o?|.8}\ BQITQ&_=@3<gv~up1nۻ 0Ⲇޢwg@8\iA3cy⩷Cj{ܹDZ&+_mT8oxbHSXڢJAk(bĹw|S ՗[>&y{ !B!M B*@nj19~; W|oXpjEӪ`JM?_ 큾Mh9+O،rAާ:rK B!BT-) !j4)l vqLOpLkVB+22)Sl2o~dQ S}VTU(dnp]+~;lfܹU fB!Duٹs'| ;w>hZR.XG}O?t{,D#g QX]lK۵7Ϗy_a$&&V~m2YcQep}+4NLfbܹL2~Σ=9+dcOӷ>c*ݚ"qo[pM}hxԴ~-K̶),,d$|.(40dTC Ur;dErAkPsA)Ać+|. xN|X "Q|hn֮\BL,_[n͛OzuW⣏>cʔ)(!!S!r;H186-R~ao۶m8pNe v ~ѳgO|~mڷoށe֙xLޜݒO5:e'I s]qnYfh,B} .|kdyNpjGn/Wq)|p݇ 6&J=.!P^.T.n0X05ӷ~ӧi֬]v z^zgqQvE.]K!j?) Q:WEظCkmԆù\4ڻ.MnnquOfc-pցRNnj,A pO-J9s&_|1SN=/$WQ.ݻɅʶCgG3FI57].U{Ld.`j.rp}|gks P |`~xsd\Bwڵ /BfJ}rcܹL4r睕@ǎCNX~= !:) !j[|ubԨQ~, bdH>H87]#|,ˢUiQ+Hn !׎;hԨM6e֭ 0J)1yjՊٳgcǎRgx^tE4k֌f͚K/'|7XϞ= @Fizsw_NN" QD!_!..ϛŜʤ, |Ň+~)+>4nܸBzZ+NFR6.esAHt #%B=[l!--4l0>!!.]urc\.z0q 86 / QBZ/>?hG)y΋̸4=-%*ErK![Ξ=޽{8p ,_CѲe kڴ)v0Yf>}|ˌiԨG%''DLRߙs1[BITQHA[C%2$BcѪU+ٺukill,c -hтG{n4Xn> QITQHAT;?]]uBQmٲK/:--uq 7TӼ<4hPag8 :ub֭lذk&s ܹsP QHTQIA˽[]uBQ?O?pxؿ?ڵ+w#Gдi &..ܳM)ԮYcǎҽ{oɓ\|R8R8BXR|tUWUwD%%Bm۶m㢋.b_b[l)pzQvxIOOr-,X+Vкuk7o^*{Ç'"BJCBG~;5B!5͖-[HKKYfڵ+k֬aСscǰm,VZEjjjKN:űcah0`@~tЁAfΝmFjjjZkn{gm :³cR8^Tg5hmc)`j_̹{{EDDDDDDȦh.;pVKE[ z,HyJnz_)NEl>dZ]lfY9gFDDDDDDDDDDH8C""""""""""uP",ul՛.}o?o1q cɗ(t<3[",WLY(fMY(fBۧ,ʙ}UO m_b|W|Q,.c=QWa,ETZ_Wa,R>i|4p*.a;I[v^YH|&G⊨7{08 "$ 8pɁjji?LW{?p>rg!U_,OqYWn ʙ`YIYm,,B5Ag! CBK`aod,$µb1\ٷk YO?]6DDD6.]}^"@.ιhsGYG~l9GSDf~Jmڏ qvSW˞ʚEPrP}W,/_Y0u-5 ^DYEYh}`f$!Za0ܷA4,1JePwl< pl4p*5ߛǹ#Vxd}ta`qYa] z8 1f$-e%B cFY0B,X +qbVK lY0 HP,8BBZe!@X,@Y0}Ub\O}iY0ze@<'C.;l!|RbA,<ק͂HcCun7H8C""""""""""uhTDDDDDDDDD ԡS!""ҨiTDDDDDDDDD Y,8gvr03zG~haw'$pSR:Z OQ꓋ g}SM+kKeLY0#mⲐ' /g|}Y/- x{O[jðZ_|͂H㥁SF pfK~Hxn>\;"A`ɃBB<Y`ץc,\NC}[,VԶWrBve} Yp!sNY۾K- ޖ>Y0 ➟qF8'p.kҟ ""xiT=¹9BT=yMHB3D7\I7.pAɫ>H]%gx^RGcM_; Ѻ+ )BvBnff' 3 IDAT+w|/1 1[YAYȭ& ~͂gP5snJDD1H#`T|o` /7yen?]o1K~!it~bjh$"9?Pq>)T',P,3 fѩʂ#Lne!{\͂#/ ˘}UbK˂y+ WrIgs_f!u=9c=cqz}:]u==~23^u^u>c0 vʀׯι SMNEDDDDD62O<ĆBIV\Ɍ3??8-e˖1i$zυaȇ~ȇ~ȋ/O˖-7@/ED6}:U_DDDDDDĴiXvmgyzg…r-YM?>r ˗/_=H2:gr e{զ|ۮi?ףފOǕ3?ŧ6UGYƑ+sBLsپ,{RzևB}Jg[w=}!֬YôiӲΞ=C9=z0p@z5't]v[n^:e]F׮]ڵ+| o?8p ;3#G{:ܸqK=={^{qWfg}yNng}7n\yqgҿw~ǝwYz>w}}ǚ5k=׹sg:w\oO>)NiW!aj}\X'!q\3Q.ear3>U9)wjˑԶWS)r t+ ˙}[D=2fjPSIfs[f0KzO^7K\Y%Y}oܹ̙3OywxWС L7˗SQQu]3<1k7~__Ӽysy>hqx㍢9͠r={6g|eED$;8ijnq.F /\vrp<-pQ}a郞.b Z4k֌#GryGKf`=䤓NgϞL:ErK ̙3ӳLSBĉ4i҄6m~sLN:ey̘1TUUQUUŮYd D"};=/gΜ9aȲeOy뭷8W\c=F"^`]w^\>z-ߠ)ŋꫯb- D4p*"""""Rf+W]({+Vglْޛ^x?\tETTTlٲ`^2vyQF1sL͛_|yڳgOn;ڵkǃ>?|7| \'gEEEFŋ}quUUU<_xwuwuW-ZT:gjժϧw'Of8)NEDDDDDʬe˖u\^^ivZ/_?1gĈTVVR]]w^~e PMy衇g}֭~!3g,ub3xN:e:t(zG _)L""""""REe>ˣ>@6mhڴ)~-^Fe [ny0aBze4իWgYG?[oOSڵK>J?!7x#fƠA2b?dv֬YC&MZlr˼\mѢkHD""""""R?Sܯjqx饗5k/]v 2gy^z{wOQxO0$ C-[ʕ+YjӦM+yb#F`ڴio_~L: &) gϞ̝;~mن}ݗ{+WrRYYY:վ}{7o7|B[l۷/nC4r8N|9#xCᥗ^"H0uTN;4:,y3finf]k>]jf^wg_f]w||?|^|EVXE]\7?~<s Vbܸq7.]׬Y3>#w^:OdB3N }=UZDDDDDD_?Ç4AOdٳ'w}a6C\ve 6,lkx㍜tIl4oޜ0~s)z:uԩS9蠃hݺ5UUU㎜<kٓiӦqGо}{***h۶-rӧO{%s6Æ *s'OycM2dȐ"8󽠊l/]S'#pq H/0_n>Fhq._8Bbߊd=XQYGAE he.AWBze!wf!eB,H`9 ,Ы,Q,Wr̂{_̌xu5kWݶ>YB&TTV]=|t.~-ohsSN9vء~ҌSM;quvo]M4ᤓNҠHtSF!L, IG ׻tO''\&ĹJOSx{"?FKʚQ,^Y(ؾYHDʙm_j|׵,`y_Y[,xbBrBjfςYQ>}ܹ3>,o6x<&Mзo_F[nz)"H#N1@Eç>:>jJ QVd=x$B #~qѩVsR>= K\Ozn:-)WjYHm{e!WBnEAfTZm,ꏲPo .ൎ #p K ςYUV89Ù?~ܹs""R: 4V^Bp8`5Œ(>ӟS3AkE=!!G}'{q1|H&˼-FHY(wBn3â&1S,5q,<˓/ .=lBg!5 U,>=|Y/1 fW 5,_BYoC̭h}ce]ɂHc?1ԡ""""""Pw<7o^z""""iTDDDDDd@IꋈԡS:4p*"""""""""RNEDDDDDDDDDH"R~0a!pT8 c\Ư}џ‚03^CF01uQ Z0¢g]˛k,%SYѡuo,YH_,XYPLKɂK.SPC( >YH'/ ĥkm[Y7 """NE5?XC~4QX뽎;թ蠨l@z碃Ò{G m_3e΂5 m,d,S%mYbPBBBM/ s~}n(%p.7+v_4^8iB#>Y;+\F? ՛ l߯>Z_9>D j߈Eqb$mʜ-Wp\܊Bj_mYfӿǚ6mZkm .{=OQ'""8)+Wn.lzD"A,>/RC񥈈KꋈY˖-Wco0zhzIKꫯO<]2qDvm78s'NdȐ!ٓ<~:+V0vXK~83{aذaՋ8iӦ52e s8}7aՋQF׿5݁2vX>hwO?;<ƌwݻ7'xbK,ږsG 6z% nH^3f ~a&"1ьS٤?cr-,_n>x vʔ)\|t￟n>~1k,8 w}1w}ǵ^˚5kkI$|Y#prEѣGpҺukv}wynF͛ǝwI/oͅ^Hy83;n'ओNO9W^I&wcʕ+䮻ޖW㏧e˖\}8v饗OrСCNN:$^xM~48w}ի3kڴ)9~Ҷm[?PQnwq̜9C8q"]twy'?O9묳{y7o&MbСL2>~nݺѩ_|1Gv^wޜr) ӭ[7rKmp tЁm=ܓ?O8=蠃K?i&k{l~~3T}ɓYr%SLav>#&O̕W^O~zŐ!Cxg9SDdcS;c*m۶套^b̘1>Nio۶-Zi۶m,Yg;~x ڵ+;D48^ց=؃~n\Se 13BBz q,LxMr[D.y G}ʕ9 2d,O1YHre!fڿ rזh_ԗ^Y0GBr{oB"zh{6;n͛Ak[p!fjEٳg֚f͚ѫW/zm69>C9CYlӧOk9'~ժUL>>8hEE׶l۶-|A޶5kF38ڊ?'|7|3]#I"$ k?zRRl˾}2m4ѹsg,YnF,]?ŋ^@DdcSFԖ(f:xswҤIzɻ[oW\СO==k׮׏nX,F<g„ ^)|ѣ;~s뮌vvuW΅^Ȃ ѣsooXiT0Sւ:Zp.S_sZgXtg}cNQ0rԩq' g>\z |g/ ь~YNL( 9땅}\YH*^,kT_|u-_̳Bze!Q~/ ?%{5װ{pQGe5jTzk?pJm]R)ի> _=g}6͚5cĈW*x 'w}ǃ>ҥKa;ҳ$[hɓkKH$ݛI&q_͛? ҡC.ƌ9c9s&+ڵ+v]v^{--[_o- W m٬Y3>.R.:vرc 2ں۹Yb]t+Рl25\~٨-^OF8A:Y[Ktj\=gD~6.hY@+ɾ̀M^Ѷ4B,XY_U~uٲ!f# },Wr_lk+ YX,BҲ`^3㔅BBY~˂fmj۶vRva=_|1Y'KhRՄ|`b:vjs~S)wIDATmz*&L^!ihߟ?1lcw(<{z葈N٠z!CgH""""""ZnӧܗM6 #uSEDDDDDd}l%/ߩS'9쑈ȺьS [nacw[7g{99Գۗ}nn48ـnV{buzz葈flP͛7筷ޢsδjՊݻg<+V-bRDDH#H,8,QT}rQz0.UZPa?̣C$#pwbm\x:g8!fs!KͶ)Hmre7 $mͲWrSֻlY3 9}UrkMK΂W_ee!w,xf¼yx1bw}w7|33f.Xm] ""x9'"˾Jof jFE]=$f>O!~r;g8K$$&B̯?SԶWS)r6,`̂W}e!% fFuu5k׮˶=> ̚gAgaVбS /_mef4rsqBB3sF͗9PB(̷>:l yp[K'a^f.91{5ןϾhRTʔBp,j_Y~YYQeʂ7 پP}e!wۆZ Ų8M}ςH㥁SFfw8>:%wYt`3#00YQ>ͳߌ XZ_h;FZ^}I&(Y}Kr绮aٲZEyU+ /& Y3B,Y_,Ⳁ K͂e!gP}K~1뗅h0>ɛF%Y,4VM)"""""""""RNEDDDDDDDDDH8C7)+Wn.H4p*"""""Rf-[\/|:"""NF)Hl.FL3NEDDDDDd[L: |8#ݻwqƱh"~3lذlz4p*8 8Yed{ԓl?Q\л>I_8Y<%۷DO鬚d ',W>Yiq"!L:% Xٞ>zlW,ؾoR^YU,o? .Y_,k1 l/5keMY(T,oYip̑gA,!57a„?SY$5ZO?tի={6_|1o&W_}uQxpw6lcƌx K/~xCwEDdH#Zωg【hL `xO-1BB 48,:l #"1b^e j?Zӯ}л,$U`P?e!UFٲ$uʙ轹|Y(=,9c]Y(LY՟d0z,f!MJh1b[h"ݻ7ÇG?+^x!n/Eeg:u^B,?}YʼnDXoي ^}U?qGԾȦH7iZ_ч贵_賙2jS_m>t~dL<Om\Y0e!Q}tFI=81cFѣGgN5*ٳ9#ӧ /dʕ_0z׺iv\8p cǎ裏{̝;ɓ'ӵkW&Nng1bݻwgȐ!L0!= pyqAqҫW/&M~{u]MYhgu}wޜtI̛7/fŊyn?0ً|RDd}~;|q~w]h90`of>s]w;sgn&N;4 뮻xw9q0aW]u?weu/r?歏^:㫺:'`]vnSNǧL_sy."̄ 8?~k .o̲h:HDر#]v[׻99眓K.ĉҥ  ?>+"wucƌIȩcǎL0N:qYgq 7pG0`z5'O>cƌl 4(={E1w\f͚_ϑG ϐ!CaXp_8 :>zJ9>|޼y,\#G,cy睼t!}9sXt)xkײvZʶ)p?2رcϩAߺj?˗sgr!~A֭[uMԓO>K/ӧ{~;=h ѵdΫ D\Lbkή˾iH8Huؑ_|qCwcӤI5kҥK4z̝;;tMnݚ'|ol}]vnNve<޾}{ϟ_r7#w͛7کש]v,^6ی-2˾iH8^暜w֍)S.^m0W^_~A>}dVT?2e -Z`ܸq[nQ-BZl DzJ?pBi߿?Gnc̘1^{YhQu۶mڵkꫯb-ƺKi󋈈|kyO$\O4L#ve׶n;쐷j,uO oӦ -x, ambGjՊz*iӦQQQڤźi֬&Mx|;|VZ̙38p }k&g믿X,СCYl7t#G䢋.y :t(/"SN;WUU1h &MĕW^^{ſ/x}n۶-L2n˂ ^]v٥|***;v,]v-Z`;SNyblْ_WuQL4N8s9*&L@ee%v ׿fʕtؑ~8=#m_4$ lDZns=Ǽy=ztR}rwЬY3z 7!Qs'Ӽys?p}ѦM9=ܼm2+'30h nVnVϟOV1b{.='Ofw?)v+++袋[><1cưf1qDxڷoرcӃ cʔ)kBo~a~p嗓H$0`7pCƵOo.2nF5kG]KO"I[9 s$S8GUa_ ufTza(?AXf%ǼfA6bhO S + Kj/Oba΂0܄@@-BN5YWY03^Cm;.N;4f̘6l5jT/SNǟ|AUUYZkU,|>;Phm׫SO`„ 4""" M3NEڟB 7k!Ĺbꓯg9Ah!]FHc/n}WגaQ퇡_}įbmV,D|cEoqY,x,폲PY[bP$?}ݗ/e+Yľ4&8iB_Fx.FZp=9ZG=$p]BHB\w8D \msMt3}&ʗ"͂ |Ծ*_R|Y0+sNhHn=¾uT*boF["""~SԡS:4p*"""""RV4Z"""oƩH8G8V~u>a\DAzNE3~v@HciKCǟxmI} c1v;s,GHm<5"""SF0|<߲SOފk?:Jǧ/.:0+r8 :Ge̒۾QZ5GÈy8ZGI`Xr[Y}䶧hoQ}&ʔ q.TrRrEʕ%0M: %gG,@am~OrO<OYTΪ8>w"lAC>fQձ?wݖf|7ο?_-qϽ1/*ſ`UWONA!^ܗg84@s-fٜ!ú٢yVo7,~?AH)(>X>t; ђ'Esfg݆i?5K97k9sK5#9Ƿ?QvV{_Bfʑ5WY(gPhAbR3ʙϾS1Y,,.,dY|RcZ/VXo~#~}&3ۍ؞WV}ءlkΘG_uovbf+?`2kOYl>k9Ȍ}H}fo?dY|G.\N5,ޑ6VЬ}_ߓ""""""E3V7X:A#ػ |BV-M AmYmM٪}%~7a|Z:Mj2w܍fhݗ|5W̢@S8]Z-KtК }#=[ҕlE zuEK-}}+l4p*"""""R4ǖ݆s@֬xI^+0V=Gok]'l1l磿OzŨUlqӚddM܆=Y5[ϮiL|nU+""""""Ylգ7M?~lv+VTk f-߭ ۅ,2m j3_x-@HzL m >[AOXִIv?|kߞVb\h5-u4(""f&۳sw+fx/=l%7A=vnʬgenӭif$?ςܓo6kN bsoCbֳncm{:}@^veZdkzct;Ц4m:vmu0(""R3l/]S'#pq H>wꣻx%㮷]u!%]GY;fH$Q$}* fWwGj"گ.[ $p ʕԾRr+ /6 ,[bA"yrfw_z՗#<ꕅBBY(7H,YsTVDs!::vjy뷭W"""G:9CDDDDDDDDD ԡS:t=pF uC3ea_m^Xto9WqMjb"fsFhqG5ZB`Vxm^.R,־o) ( }U,`/ o_VdvςWSIft$چ? 7 zʳ>> ͬEm/""xiƩHE,=oHJfXvHVF],#ڜVm:yf+""""F,:hibX .S{IENDB`ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/images/inspect_web_open.png000066400000000000000000002117311512474103500311120ustar00rootroot00000000000000PNG  IHDRPCsBIT|dtEXtSoftwaregnome-screenshot> IDATxw|}}aP@YN:]e_[;n[Z[Z+*A 3! '9=$#9u$x@}!B!B!MwNt#B!B!b2RET!B!B!B!B!B1 PB!B!b !B!B!B!B!BAT!B!B!@B!B!B1H*B!B!U!B!B!Fa!B!lR 0cPnLu&9$=PB!B\p&p6BlV6&ɓ!B!B\`/ɒU!B!j1Lt@ũU!B!Gz qa}q*$@B!B!BQH*B!B!U!B!B!F!B!B!B8 b,%Xḥ.nxh(fV?oj_ߵ:(f.b=?>ÛiC y| w'*8P5[_<K.tvfwB!B!9BTqi/aQ'cD<^J@ BtV`` ^q~9=+\(!bU*Y1'n{!B!BLfqj;U tLp /o` vOtNBf6I?T#"$x \2m׬5tB!B!NݒQWq'^:s/;C:3@UH+x\/ZyC>O?L&Z~u`@d_.$tO|lrbߜChgCiKdGo!D.W3CPH^tc]LIƝ(h.Ą3͞K&uoo噢jT 4f5=4U;~c!_;ɏF_ZOWp?mWFiڏ.߈gۓB.㉵~PV_/DoyץsdDZj7=o>r$*g?[G#B!&"<䳃{oO!jo8玐S?am9{yI&(f$[Qt])̈U|ߨddaTwji %t ZOۅdg͙ܽ2 f6/Z\_]f~]fSf=z֩|-{i V6m5q}ٹ91W>i#}F KGP嗊 ZI }|`w˜ nK9P $]2{e^梪w^=ƿ;{ywp_8fEY- q!PXse(!89ރ1u PG]^"[A&f5ٌp^7OX[N-@=6:G=ڜ\'VJ5eBRJfThI !o +fd/RCH %{oH6uMlA_K?7 EzS=h6H)IkqnR(RI,\MGe[ΊgU44nd+/?"6Lsa-F f4?'g~ -Rd&^ŎwJx]ܼj:?9̯G O= d]/ Gjh4ؙ( gS;{g%$~Cu^=;k9MT1)pkte4pyTex2QĊXGoK)EnۘB<׳;5K= e*?A: VheۭqPwCy˨VUvTҷCPL,^MźCT+fj6?UY)| 1f2߃qr wϏc_5w|aLIb)-`qu]4\tku;;Eu~oW!9JfqoqQԓ=]PCG,>EXn`ݶaUQ5 \ʻ#ɚ+11 wBd< !ą&egxL.ϟж!J`,YIܵ6K1kTks1@˻̴/FUK+JG/C\:|?n(DG4{h1T˨$!130<b[ѢnBqa۶mj' Pf\j'=ՌRԃس™n.7#,S ]j#==5s[#ȁT"BY1<^.rݣByܛ O{~&'}_F?d*3\HLD&21e+ibO 3HKPؘ5e4`VL ĸ7RR8SVã#sXdyøuT󽧥-LJV83mX\]=To"H''sGF1,9:^ގc"%0m{[f`mSqI.;”)7١f{jP8 (Hz|oz&XCܷS]sSWNf!%َpx:_?QڤHy.ߺ̆Atǽ A| Sΰqnn V0GpRyb 4̈R@2%Ɍ߃!%V^BdF0J3UiᨮQtr)C?<57۩,$ 4)&}GK(׆~LV6*%d#YGٹu`k=Ph7bnU7흣-4( @W=d{=v\?BC`U@g8ڝ8u? 3V*F 8i]n®q!>G ϋ9ҩc{@._?_hş`]oOL<*,? یt)ÿV-|}I}yL,# ZG#A^}_'LP):DMa*cS!zv8INvt NS^%@2*+ggs$i\k8(EQu? itCܠş(v=NoG_sMN{1{+!|1D:5rytI]6<G‚i56sZWq}/9ZY2SV"q@;1;p}1-ޚ,:ؼ *50$ƱVϋιBOኸ^I,`ku,3k^ͺBxeo²bI,LIRjxU+f0dg2N'sBMvG:^wCnA3T{fM ɈdNWػk>50Ky{ΫA)1QzBT O/,ݗEx|>7OX[ƞc)h/\11 p+!h ÈR (%h_:6ygW,,Zw쇨u6asg_GI)齘Rڷ2'1gc:V{e:9I|X'mpwG+tIaY30h=+gǦwsļi÷uhV)NYQ;^.8 enq_5:?ғey SROyf)*ZRQ#I:+ݞqFfr 5tt U2Ёn aL }Gg )@w4@=̤iề6%2/Ӳ5_l”gQ=n4Խu6@Z7s2%qq~` X3{w@-A,aj94%F;"6{UVi9TAŠۧ5F 7cibÇg6B񍞴0-=+͏@Pfj=S/pP;E%-3̴T]f %05tx7 @盼9QPȏ{bi =qw8rHqpb"7X%S!hvALKP]--q:jĨC^FPjaOͰ7侵8G(hAwq`o3O t|+)0' fFaͭ> |] .I0le Ꚛ\U ABLrKG^U"BO5B?4trot[cxW, !Vk4AFIJ(ž2am@j W/Gj`U(t>#+gZ U#HxfZCX8]07xoOX0 0^)o”t3Lj K%<=5_Wϼϼ.朴=GyU'Eχ'-U?~OTEZU>%b7"Yng[7NO1<=&^EڙAӪDΈaY vfͰ9^Ŧ.Ɣc e[[ؾ;i#N>ʱp`[UΌ@'ߩ@tҨXya0~uձp9Ȃ+#_64@'gNޙ>:9vղmWD78HS8ꔙtP)@yM)ć}q" Zs) oR}hKC(WNӃwM5|ՎAZzW+?/( eVf1~ b$aQ:? y"ݭjjg$޶yR% 8m1ybM~Aǀk( ׀pywOY6pf3o#T9A!pJ,ksg ϽߊKw;nc&^+i⃧wq }_ywjxTYGX[vFJj͵/tΖq,Oùj ⽅b>(?QÑKUs], W%cU?]W]!c*<m2+CcBPoiS?x+?E'eX#"Igs_ 5JXO7=յS4?P7q%hO!.: VI1 8⚥~ V<$CYa`bA™jo-: Oo13ڕ <).lǽ4CZs*wȬ9!*[)laQr:V]:t{q.:s+3!kpi;|H;⭗ Ckڱj] PdN@!03[.cmƎJeUq ?{WuЪF3; ˡ zkwBYih]HTS?6OoR+!dvk#\{m2=N U Iqb%*Ls *^Rp1Ŋ Y5R[e(ҮA#;[:h %6\娯ĝu]P5"m͔u58h&/@u9ܸ{KpQa@d${wK6_~N/s|W cY9x*;8autmXJ=TAA!!#`&23x۩AwpdB̊Ⱥe7KLSTt<-lZ7GuJ4Kc)[;?֍6͎6WƁ. ;j@3zF^р+ Ai <*ջ8<䶘fRO%)ɯoн-+ _GKCߴO^wGoa 4*SiNͶrvbh|OWPe ytԂ{~%%MwqP+V_nWO;!f{:kD'ń< E1.NI (mxC?1mT4q?,U D2m$GL-j}י$0`N1hӐR$%pjHI Oܔɨ;eDn9AS$ sFX!Ŭ69==޺C[{xNãiVd&ގRq`(-z ;|>:Sld|"f^̯J"7^vush[}5`4=NVCf%:Ey"IӝWs?ML_q߯Km#?UY̯o&aKB"k/2~:uG!¡3Pk>x1U

6<ުQ܃I󛓧5UP)^:v5t>OQi_>~k@ȧSۄwNˁzݽgG}NK 9;@uTbp|F1P3Zm@>EpY~pp+*6E諁!\{s,A݃>gU d\`퀛Gt]lpbm aAV!vEk0J!!UDB 1ٍG-kRľT[; 8:Fb$<̈}j]:m%ռ-.ũQKgP>[oفQ^ ri'w-c;+F+ąq hɩ{,I+ϚжZTc(?G87ur0ρ6'K+=,-upHϠ yPnSP ~\RNLr7yhÏOE9e<}1u\H!R-)ܮ7@c,㇚h: Si ?vk "6@=s])N :z't1jMر>_|sI!fVvo)oS=dF4O!5MNNsuso;KD+laڍ!;n[W0[s[S=11{հ ݾ:G+Yĝ׹q*& ȉ|[nMѥ:ض\#eeO|uFClP*;jxPqQp|GOŽ1vkbpG +ƒ0p[֤'<x󽊓kMqi3Bކ%&ia;;:8J+Т`PGBԻmԙm'pO0~kr kfjz2]Jۊl\>7PZo颶';ξQ kUo0~D.5yufMe1FbUpp 1yW&vyQkԉnIhUJ``>wտN 7]³w+qջ*y[o?}gފ]CCֵR`.[wXx'Kkm䙟_þ \|gw}?$ ~%|qvᄉVCFp:KO) ]B!B!pH*Ĥvk~2 !B!B$@bG"z:Gh} QB!8]0C1\!8c\]e} 1 iUeh:0U !Bq.ta &&ЉnB1MMܾ{t^43i}ccB!b[:h O罰PnӳUIc rsT?ɯq{ UBT!B!&;%zʕ~!& zvtOj*C.?$  B!B!GT!&N}{Da1kaAYL0%B!BBLS OO.8SF ZтFU!B!> PL ONC1B!B!>#vqAG @<6>iژA+2}iÞWFu44:zl;d}>YO'd}>YjOK\qsϰ0*Yw2HHx>#=/B!Bq.UTӱӡ߻:(T}Ma =R%DB!B!ąBT!&Щ qѢN ),oSU%$Bt8;i~&4mPxj_S]zeTS!B!BO$@,Xˍ Jճy{ݰZu9x{ !B!B+Ta58ox,`DO{{w43`[; Qj>B!B3MNRsd.=O``9pniu˥RXF%Y~h **&dB!l:7Bm segeb8/o<;7?/V,Zwn%.%2э!@Bv oiާSGg_ɑc-_FXj0WT*B}7U}s=(Rh)N \ Q( PDEAAD@KҖҝ<I,x}rrrΡo!ĝȑ#/|SB*Ut/+2pY]^#jnpi°#N{Ms~v/b鼻/+xVR IDAT}[|@UŒ.ycP&2rt.=vL3'C 5lb9+Ү>WiN;zL;~BJNI=T+6+I޽Ј XlHȤ|D 5}񺞜rM sXV" p̱տbmڷwT!qxgKmҮ /?ATc骳Kb]wn)v-T/B!ĝ… ]#))FOʄsbtR6gMyhՄe ݘٻb)2yL=e+%ն2%maDnb z.éxh@֫YW^Żpm$,թW@̙ 6d˅lޗ|cM^!čPxkb>].Tžש*'Neq۵oFzL&پiIE!B!nŠv,=U惚+skTdfd+xIpzmtnaW+ahZ:+Vj7Snv(ͽ^̜۷u{P8/f\ՏijTX*!ćs se\+'q5ɠd+o-yGRuRma)7@J6T*܅:+]/ N5<}~R.\/u[RƘ?޼'Q!B!noNNNoڴi;۷ҪU+\]7nӦ NNNėҍ'ZO>da_kXo`iٰ.u߲-zC mfNƃ+V!?5pP&و:Z&l:f=I݈gdfG}A?c>J6~0Zw{~N|h^jFS؛qiԡ{^ 5uХk>'AjGѹ?wюõi0ha1/5㾉__pO(vۑ#! CXUTRI?9sfΜ{AK"[;زls^ȎK}ZH?wc)Wr5.R<*S'Anuue2g~[]g/uo97q_X{Œ履Xe?įObfod7(JK;%{!.;Ofd֍(-DV}[CK)?d`N\? !B![nmڷo-[O?;m۶l`U/,wF~Ԓ^dl'-A< U$0Y14YNb^LY%ﵔifR36 Rų9q}ѣVp2$,ߗ2emz"hճ^Smb@vաeLxDU׺#m뗻 QqHDhgwHv~ ? w_ո( >u}3JyW{xzlf6fS#8UQnF4TU_?~YQłFYROI='ԓzROIl6FDDeϭV j1߸{|~_3jR '~Cyn 5-oCצ3]Ҍ m%&dٮ*ԫuUvbmrl#ϔ'*6"Y@Tl-_NSG)XIB«s~!6lΤQ`9i=K} N3z&O Ùf<9z|;xS[Ꮿ|R=EBZY/8YULc_:>g_o⮷MЄl8dYΎe KYu  fۆU_KNخ8eI/okhPpnLlJ;9s1u䐕g#VM1֥ H*UV=r~Bo,oHD/T+s.D_'W?}7q2k8K%#O'. 慄ѫmjOJ/Y*{7'Au4Ljpï@=w\ݜO%i' 1lxЫ(~ @J2):҈F^ML#f.@zcl<LLt;k 9WR4r&0sv:Xj4|ֽ24%3WgsEAjzp>z@Ǩ)\4|EI%=b:EjY~qɢY-=j t.Rxr.+\HomKe偋ćc C=x:ڪ'}f"2gs @Ǽ]߆nE;g.yRq3솇ɩ9uI*g!B!D٣:,Ys璔ŋYxqsgϞMpp0`͚5dd\rey>'}|Y`7T ;-D/ Պ%*W-:Fémjd\ܜN'Q|5s⍵YSX֭3mrVnm8Y ғH*'&7ޗy y|K5&Gb@#zmDA)޾XIdO\⥻9~q>xRVD'/* O8L6>ȹ-IZMi[?:c'U䒓ŇO'.Pne˫<\?3ǖsy,_(JoQՈZG-{QX|tΓY5Omv.ĄLJS@hPŕʾN:xf3F½}hҢ"ԣ~x:&5r,YC累ɂl?I\ߋG8q9\=TuAc5 QrJ>%n{*]Xo-:_dZ)[[ł$[w9jTa )lbkP>_ݡF7n5|iΦ鎽RMDJ.[c}m/Jbd{QS@6`sr^SM'*_,;G|q!]\C_W:W7?hPy|A BuqQ\9!B!lޗ?2|||Ja$R7yu!ۚwgL$hX֋YΔoK/#UyNpobwZִ%Qq]&T+E[ȑV4 iDWt@: cG0~KJ8?]v?+y!|b.Ɨ#37Ϙ33{Q|8s0WrVب[2vA\ o_uWhwq1}ێgy>VǚdYY{_=fUiPŕ#D?#X`grYJI&~#*s<fOypR5׭)3598~GLxt_=*ѳ_mNx^^ĠqۑZ:]Xb({Ng<:eZyscy _p$BP|ݴ^￾ݕyj2u%''x) m o"R_byW2gg1 FTTUEQ>+J)<ߠףWMROI='ԓzROIb=@x25kְsNNWJ44h@ӦMKeBq);w{eccɹ7g,U a7^;s'g4坩mѦ~|. gJ?CM `sbBM|1jWtv_U--L_Ėcԫʅ,3o;t3} 6kGpߗ q=YW\pB5 wwf7=Aב%OB!&::VC!n2.ؑ;R 0ЩC:۵~ZAW<+?@! Ӟjߘi 0dZHSѾ3= 00}M?mNT_|VQFYr m8 FF{x1/хZOS5oHjN\'q77~WgH2SljwVŏQ/+GI<+ R)n?W̺!jr CVs>t֪\)0P긱l0%B!BLy^'Lw~(yms(ifٌd*0l>už)2x~R Q J%S jZj]p(m5II='ԓzROI;^iNBXS O6ry𻾮&䷅GTqDt{]"k !B!B܉nH*6UrpIQTU%nY8D Qw/ANїpU!B!w PlSً;n MEA˛ߨn,SWQ7a5TUA YUJ~nB!B!eUDJq\\ǯCI_oh"$^|Aa^yj7KGQTTE G:M/uZB!B!; PTUl6ZI7VY@zK ;M#tE`PU͡T!B!wI: j8UU>uvh4ҭ߭2]Z`4PU[u*(ZsB!B!(ˊP' q}t4;YIS fo[`0?׫i]M> 4kЫ _Rp*AB!B!ʪbԐ'ϼcێgp;i O}4@``0Df6cEtd6F͐7}_QO54UCq@JR!B!BI Pdo[gJ'(:x&KUV()H,_ IDAT-H6F]tF''  TUCQHBV!B!Bn"UH=ΒigBH=RxGs(TxmS]NNNX,=c7tqMbYP5M3:_[PQ$KI='ԓzROI='F(6@kz-.,EqaX,{Uu, ӲI6T3JNn[RR:FрѨ7RE5[P]ϧs4tݥԓzROI='ԓzB!JO$wںNf3b`0M9< w{Ur7quf0PT'TՈ*QT  EQ*jvѱә,ԓzROI='BQ$@춯m>;NWZ4Φam/v'ذ-W5?'v%48w FNFgF#F'#F`[:.EUAiiDŽB!B!2 P.ׅ +`No=DLIJYg͜9238z9oJ9\|<243f` NN ֯U-o @4B˭}*B!BQH*Mpi_Fվhrssqrr*jb20͔7(CD91t]#BbL(h}U'Av yjg̀h--:B!B!DYRlz囿!F៭K9b؍j6 ܦuN5X,jZޓQy!ZThTQUT5/E)0KT!B!eU,(L_;N}M4 v{*`wT[WdhEUUCUm]jw4 @xibZOB!B!*{뺽[ȑ#5 Q(]W::& f{Gj츾Wj-Lu(XT뚧mxLB!B!ĝ@bd2r#Մ018ppx?,׶QTUA!?LU5 EDZKx*B!l6[_s!C]VK;ZqJ9sobO׷e؁ YgcPU{5/8VmajF)iqAB!Bܹ֮]ˎ;0W^;ޢQt.l׿Ti${ Q@ξUc?8^Z,  VC(MwBm]ր~|J6B!B99/Rm 7?D:_?eܕ9sP-Ëvmz%gg7vT&߅5`v8Y2W7ƼwpK_/5a~,۟YGB.T(9DT4Ϯ-ucѐXJy!ifTj܄B!wK޾d,YRmҠAzۀt?;hs xx)f~ӛNP|tNV(^hւ8`n $׻&-z gcT&oۃ-?]1UwO1˩#W}Ã)vW3Y։+Go[F}8v"˭2 ;W%Kt}#od۩,<3#>G OfPJ{_Wϴ[5bw١r)rE\=u3F`p|xO7-&I^>GO}Ì%/!Er߀BX4]4zsl4M8knkuZh<%]!B!n}ܧܨ!Ň߸ ƾI<L_aew ~,/8J~[~ O3v<'bm]}r2{_1?O(=\I#lc {DVyB!Bq险(z3]tt[V)u4V >|s'mɏ[zf,3 3s`Ў>Ȯ`U.u!/繌ܼtB*4gԪꇓbr-jVW^>=y'b/~14t.=†YUP G>8_'?g7%?4u2m|8wD:Iv.›vf>4wGC1SsBOy { wQ^67٪UJ*xxx\Q P\jJ 0JR NB!o*{8zQ\\pq+% kY, prdƺ϶3 Gby;tYQ. C%wKF:Wa8i;7dP΄;.U[S(ۓ54O/C+QP4H=~&ۅ Sû9~2!e(QҐ#nAAAw16H@h4=H#Mi?C!oCȱ$CSRRX,䐒B nשpz61u#(M5@'ԓzROI='MwL8֬YΝ;1n;#MhРM6-q\ЈǞgOMXTqkܵVZEll%kKwB!BQXtt4ѷzBqSHB!B!B@sμ[z(B!B!m8qNa!@B!B!BHz\B!B!B[ ,SNԮ];xbm> /Ϲ3qDjԨU5(j׮wҥK/9?M:֭[Sn]:vȼy ŋ :ƍAϞ=ٳgOs6oLݩS7fСoQ'OI& 03%$$\C݄!B!Bq_Ǘ_~Iz0` >>u_nc6lŅ&M+wѧO&L@HH}aŎaΜ93ÇӺuk~Fc=ƤIhԨ bʕ+ 2qa4y8s {gϞ1vX^y.\HfȐ!L4͛7x͛8q" .#B!B!sC6X,|Gtԉ7|VZeOÉgر.ӥKΖ-[HMMۛ 6дiSٳgcȑ<iӆSN1rHΝ[` +V7`}ŋ9|0qqq۷E1ydڵk@TTc̘12e % gϞ,[VZoTZ t]ghFddd۷mٳuMn(B!B!DqnH9}4:ul6c6X,4oޜ;v _~?xV^ w]^oNffءC0`mڴao޼9;w?f׮](¸qٳ'6mBQbccqqqa޼yt ;w111 "<۷e˖X,f͚Ů]ڵYfaXhٲ%۷#B!B!ݐD^x/_MӈaݺuDEEq ZhڵkYt)M6رc599OOO BuN} \uw.]`0Xd ӦMb`6i۶-;vB!B!Ÿ!S !!GppKI9sξSLL L:8рu{G',, ??֪UÇ3o<͛g[n|O֭[hܸ1l6ӵkWNjlf L"\;ve˖b6iٲB!B!5jѪU+=z4:u^/s{j4gѢE^nݺtڕwy4UƼyظq#_u{Yt)Æ I&TXf͚1a\\\S;wd۶mۀ5С:& Yfq :tXw֍gy{ӸqcSs]ĝqLB!B!ݰy< L2iӦ}ǠA ϊ+ t`k׎?@*'|ѣ4iɄ2q6|p:w/̌3ЂujQA<MfmI$N6['C~w::B$B!B!Iٿ?/&!!OjnEQ_KdDѓ?&x|wie)hEpn#Y/f,6.ck,i>M Ca﷟ӌ=߉#2 ůBj",m_eܔI g[;+k'|W>|sUF>}0ovܚ 'ׯS][S t5O qTvJ&lZփRaͲ-dͶ QԾ7GlEUwGl$לEV.`˶9TjՎNcES>ہ-B!B+c QNj_ 5$$޽{- IDATc0ܚɯzz"獂Njp,w\ݜO@7QqdOYǮ ?v4Qd^lؒAxgΣ;߿ڠ(( ( #!o[RﱓI<νOdqzؾ8c'I;IIcNtLvw۝V[ju$$@DU=*@hix󫧖[vN6~ n2`A"=cWH `CG>}kK ]D~Y?ah/DR5S4MBȽ0RN|\){oS*6T`[h?`u51F>`#k7x,l!7[#qRNtVR+pCzmGREt~Aya.Ii*|-Ή?(yxsM"i b{ 0 l6y 9>Oaٰ7>aCG?}= ;X?yHD!2՟#l+(+ks lvz`l=Lw>[y;r'ۋ/Ȟ I˯/oRFG1iRes3Izcc 7d_nd MsDdNL)v/_my[&`!;5G.r쭃qmy7W `_;?|+/:O,5?ٷ U5QG;t-YcWkNCNWϚ|/2jmPD2^ Nt%"slzmIL$mͷS<)OySL^Ow UI;&=Y>6;|0S{nKIa101 )OyS<)OyzRATD."%"{o`(OyS<)OyʻDDFU1gC$&s8IyS<)OySނ剈ȍ""""""""""w+PEDDDDDDDDDf T@ """"""""""3PUDDDDDDDDD(iXPEDDDDDDDDݍձ*4MB.\bV8M"""""""""" S|>jjj͝U """""""""r_ P?Ú5kؿ?_җιRYYɹs)"""""""""rq~WN~˗sE{9= /@VV|]^DDDDDDDDD[.?d;wOOO|J*n/hDDDDDDDDD5oCiӦ)ygx<_z%z)֬YÓO>~3kŋ'>ڵkٳgwJ?SvMUU9g駟sUUU-o6ذa۶ms=7̀ZZZnxLkkh܌y+={ioh /ۿٳ`ݺuo.\8_e^|E{1/d__OOF|S"JY444?#GCC'Yb=_W8z(_ȃ_ĉ3s o+ȍX,F"ږJ~deeN׾SO=Ew]X|(_Yv----?#__5ػw/*Ї(++瞳wuu|]vaPg}4m"p`&?SZZ:kNRw5e_(񼦦&~~___:>G-r#8x %[c_hf&&S<)OyS0 CdZ+y끺n:?nq!qI>6llcft:3x??׾5 f}]?wC:&J裏OӦ͂Hbb*OyS<)Oyʻn.\onypS__nܢ0t@ ^&-y+ʯ w~Og컺'իͥznJ:'xCIIɌ% L$N[C:@d<$I<޽{HTDDDDDd 144DVV@߿ :9riUWW[aִrq>L6)rQ***Xt)B!:O<í? H$ldggSXX8㽹4ikk=F H$v\.`A  ''gwttPPP@^^u^__\+V$ :;;gD"  V@>~3>mۈb8p'N3so6_W۷~SO~Vۼy3<|2k֬g}o~۷oy~}[o//O[?EDDDDD8tvv w999lڴipFyٵk ݜ9ׇiup8 ^4tuuh"l60у%KX pK~~>i2<˷-"K,~f,D/_% |- """""rIRC~~>%%%wlxАn.344Daa!:::)!Hdޭx::ȴ-((`dd>ʀul6=Us3^900@:&300PO_lNrĴs5<)OyS򔧼;uU݆H$… fulvv6%%%KO<?<<1yW(//g֭D԰rJ#rdڵVN"4> 6XŴ#Gؿuٳgihh7emu1M&Z[[|>6m4md2ɋ/ƍx<﷊j--->˗ dgggkooR@T|kQQb1v;v .bj.`ѢEE˖-EQzzzρɟ~͗ӷO//l2 >3coX,F{{;'Oyii$Ɍ?=鲲N>s"ü ۊٻw/\x:.]J$G0 N>d׮]v hf-[ ޽\\\K/D{{rVDmM6|r`b/Lgg'-8{WWtuun:`8C|I%%%'?ٳTWW[Y/f54.<#VDcϷfӆ@ ӧ&//P(DAApx<墯;`i .+t: ^c?ZIR$I`bXa|>LӤp8LnnnpŋO;݂'ltj' L)~:;;IR:QQQ1B """""""rL׫vy<mۖy#7okF$aŊ=E&W\\L[[T|unc===DkxD"3Pp0889pXt:ޞ 3L\.`FO`"LGޓitK^^/_SNMEE}}}VN퍊s^mXm6044(CCCx<3su!fa٬"혜j.]~vd"R[[itwwSWWGMMͬ*Ȭ% 6^Qf 3nnε)..Ŕxkpx9_4_DDDDDDDn0LttCMپj**++ijjbŊF555?ٻw/9rN `֭Vֶm8uN"NطoK*ZZZhmm+Vpy+fQ]]MSSCCCsN8s xƍ[,tY(QWVVF|}QWWlj'0M"m6ד9u`p=Bo @ & N!1 m'eeex"Jzeeelٲi0h0p:9w:OVVVϟ ɂk~~~ƂRvB6%i8V_D=}S皹v[4I<)OyS<)nanC$… x[ SDNih<}ϽÇS[[{ ߯"""""""2{ng,l#"r?SUDDDDDDDfMSyh)*"""""""""2 y@m914&<)OyS<)^(Pyf\%ib<)OyS<)0 Ns!#" H6=m7S<)OyS<1kT0l8NBBID"""""""" 7 E:X,hnn&N/tSDDDDDDDDI~08ND"322B"OyEd]e$77G^^IPEDDDDDDDnڔEN'999v<XdRkٸnY{2zfra"Jy*r/j۱l8 Mj&a\)p*r/zH<ǵ-"rXDDDDDDDL)NREDDDDDDDDDtnJT*"""""""""2PEDDDDDDDDDf0"R""""""""1Mh4i7M<˗/p[%"2T@Y!SXXwU""GTa>O=KE䁠ܲh4J("LNٗŒ%K0 c^p%u֩+"sBT6/30<)OyS򔧼{=o.477O[?16m:ȑ#DQ{1#rdڵ3-LHgg'RUUEyyu0uuuc@-%r-tDDDDDDDϊ+yGM(//֌ŋj*`zAٶmv0 :d`KJJ|u~: `o`ٹs'466:cێ=JGGׯgϞ=;000L|뭷l߾7ˑ#GQTWEMiieoܸt:ǩKcLd۶mr^{5|TTTp $ɤU@=}4N]va DQYlٴm[b999x<ikke=q:ּ6"wEDDDDDDdE";6e{:8oΚ5khmmVپ};vÁ0::jVqqB- GNN,Zf;YMR)m?vFGGI$I뚹nH& `pNPEDDDDDDzaÆ \xǏȆ HR8p,6l؀attz:r +W&zqZZZhiir1rssl?z(lذl6f~8qD@ zpDV*"""""""AXjn0Xt)/_& aF^0YQQɓ'D"h"+nSQQ˧7y% .]ĦMXxErrrزe 7o&s)<ȇ>i{ȝEDDDDDDDd\tiʾX,f+6 LVVVF*ߟQ-**b`` ),,i -FI$.]W^!H`~*ljF "2UDDDDDDDf-//իWONzTVVR__%%%IGGp-[OcXbÜ;wd2i9NJKK|27n̸VUUoo6V6H#Liqi NsYkvsV\i={M^^P[[f#rQ6olmll$LRSS37YDT@s8Vqnyf immŋv^/w怜 ljkkرcx^񌼊 ._l ߟٻw/9rN `֭3mΝ8qSNrT*L ߻w/N&[lzb1HRl68BT###=[Edn^\vLmmu3~@[wHs}BSUDDDDDDDnvyl"""""""r˖-[FiiibL3x""""""""""3/tDDDDDDDDDDJ*"""""""""2PEDDDDDDDDDfEDvۍWĜ Hc`bS<)OyS<i>VT|0 L)OyS<)Oy~ȃ7cU@y@M؍$&<)OyS򔧼 ODAc&\pYܗ>kITTTPQQMYp*-;{쬎ۺu뼵p ߗ.]믿λ?>o׽|x*PEDDDDDDp8XnGb`dشiu{ PWWG8rQYYڵkx9`_ŋ}wykۛoa}&vލn7̙39s]vQ^^>m8{,hMee%W L/qF*++68phiiɓ<8*U.tDDDDDDDDTQQpv Ν;իپ};dCaüvvIee%~֭[g\]]=btd>z{{I& op8رctttpȑ)/^dÆ Vajmmm>}M6 |<8*++y'k^cǎؽ{7K,&`@(U<^"-9'90<)OySd׮]v hf-[F^^nky***pK^^dggL&顬>Unll$;;={X=o&PR+Nnww7Ǐg͚5VQÁ0 \.׌sMӤŋqFJKK1M3gΰ|r\.@[uuuQPP@WWU|볮/2>~KWWvEaaM]_Va}pҥ& """""""r& v5lǺ\)n銗s^II 'OҥK$ Iӌ FV/M0p8VQjcccLדώ;8p'N`ǎ7>NII QII ^M6q%ox&{^t)c{{{5%@ @oo/===A`b*nU@q7Ӓ$P.yU ;vKss3JƊWbpp~.BXfGsy DьKRdbllÇseZ[[yw-^ Y d֭ŋ 8}4gΜaժUCKKKb8kfe[iFGG9taM0dڵSܹΜ9C<qƌ~?{#G` lݺ: 2 eeeRԴǬ5[*"""""""lrxJH@T*"""""""""2PEDDDDDDDDDf T@ """"""""""3PUDDDDDDDDDd*@T8"rgm914&<)OySw`e*Oy""2{*< LӜ$0ML<)OyS<;=J8alG;]>)N䉈ȍ*H9ɱILL)m+T1x =T,`ώm7y&} 8?Eʚ./ W!n}w8/ԁ.Kк9 ׇn[Yl﮾wEI-=]so&/OQ^^|okL͟Æ<(%+oSRVdOg ީQ~THvO}>}Sݒ'""79PEDDf˖ŊMQ|('nLHsZqCLͺmӛ Iλ>#;@mN|9oX<1@6eZH=PEDDfF~`o_PCEEANs _ll2fB\X27 #}dNHDDDCUU}YUe!~v`wBCyT3eaZ6oʥaIz΅8r1P (  \u/ v\)W"ґ~^9lWٿVbput 1,tKr]{9`d`]!]ܓ6>ƙ~$;匫l\<Αp?DW7/gR =6ʙ-qb<.k Y7qBz(¿}1[KR;&#m:'wY1,aCqKx?ti.5zټ>=4ELkWC'_^LV?e0G ӝqƸid=y3ܻ'.ay❋IVbV{?=3=E{]/'Bil^j^R|+gkl'W/3eBgțqAv=8ȑc Q ӑ̢jc{k$i;;ٿ_f ǻiQ^0{g(E Po@rStsfʚm.$#\~gߵ5BBǮMK' LN&A'5xugf?sx|Skk>v;K7J6 /≭^<5G(GHȕ&c$L{rCl>OEDD5*""r; ;Y@,͸ɕ6Ulz)Zw+B} L #5YZgI^p̗wS(JO,a[kUVLZN$)dyu8 \Roͼ6A7D;grKFB m98S>y-[Y;jOj3ư/ {zn ˼zn*L`g˺\ l||[ͺˁ$u`&iMAV{^JpaMʊ #1zb|,-17>Gw[R '{ߘ{9T#{y);|m;NdžJDLM5÷ե^A_pЉ94ȩEl]y&4|٬{n6";o{iK3MiM9t g!V0HHqibe=*+j$m!{K]uDGq..wXƖq$oI6F͢z1T>;zhb}MNF*&S P?ff-RlTSvf/3{F'>+-샇)0 Q>O,E=5҆]#B9A+EI6$YlqJT466<ؿ?w}7g̟;N?|JKK_& !)!H ![0bCa-">׬ՙN2u9@2D1?j&P=R :ay^BT9&b6߶QUZV#>bbd_m]m@QP7K6Md؆ Ţ96eҒl{ILKb1Lk@Oӟ1-puv6kY'VcEZLB,=r-w'>9ƕv:Pn[6TT4RÎMN♄kXWFj&RhA#GDH5SQj&aG7FiK r$:V ɀ =_ydI-XBQvL((6̽}>y'S,)1 Î-'F\#߆;5ȎiE6 vrqv$Q}VחxF";濆ySЊ$Tôټc}ocfu5ny j9?q㝷T T!brtur,݇b텲tsbQ{ئ8pRG(c*3waG%-n'j8`i Q(. l̘jȱ=}ug|kYHMݜ@; g8~ۛ8vZ7VZ0&133~ ~,8vM[Ø,(;HJW6 ^6oTIW(Pt ;=<@}wCj7S쁦B**X?{ ˤp76l4MS%7HSSׂr~îݾ w8؜uSV1RŘ|ע9 kaQ:i9dk%`8W0S^aT+L=M LFfWCc5gO)}wQQȔ]l}5Ln-́Q r,`Mۺ؜v=yP8vwia"ʆ t,j0ECsZ tv'N=M[KN<~8V7%CH-4hIZY7'Z覮t}p" fԻ|9+\XwQu:[ԭGmvMT F_@;N6?uܩ2_ynVϟW_cg̓ē4]ijG3lO6x(fئsU:Nי$PB4oYQ0 8v0c8V̬EE$´lA).b~4FP8# -Dk;Ue[d!*E,ʆM1/h]] \6#t3gƦ2ݜ](v]Nvo?Q] Yۢa)`Fʞd(}gc~8)ܴ5qSgp9,Yc[cqژO|OPŬbw|N>6**E<9vYn S]44_&P[ C-=O똬f,j|D1RU_)Ž=4uL6 5'y:]͛3;'dbA 4ٹ=i:T/.xe1E N)Vz y &>Lj7F{YM 8nVsRs:(vfٰ :L$+1lgrjCqTʷOjvcOb[C4fDpi0{R`oUPJ 1dc vo$8PiF5SG!-qJ7(cDaRT0T- (f2}plY)m2&n|vr3>l;Lo`WNɑ$JQІS"e6(<gÕ'@g2[DH>{c$ߠ.s{[!ĿrXnu:5_ j]S3+ēxoFFQhPS]Ϋ9pqҋGSxqf2Y+$etztlWEf?׮i_LsoxZ8ğפ:AS$ޛ;^w^վz̛7kG}[MYYmmmww/3=K~s87x3>x>6|"̀޿ϛż;ۧcn^ͺʕ}n+c_z73F͜0_:c*V]u o凅?8H`A *q-_K*Ʈ~,#^ o?oР۹vaCȦַm$,znC _oN~}X*Wq' ݿcMK >>sSO4DwsoլZ1|>Ty !meM8=ql GbjkN !4;W(twmCꊱz"E V7N3Z^qK8)CU便tM׏xjw^SCM󏾣z9nﺜj<~|E ~~~n;?œwo>&Ǯ慒cO/E=Ԓwt"qr~ﭳqwqeֻKÏ-[i=|jQ~8 ZO|C|YKo_۳o^)~}0?&Gos%_oWɞ?%p'-˝0qvȧs'/{Wpw7|"CBӂJѬ"ꚢM4 ijKNnMJ53އ;Ms*No{6NbTظ5f\ljf(;MT3XI, ^{-F+v:;;zx򗿜pev%wQ㼜[ZDOæPl,}x>Qe Mly:֬On̡j_O_B?M[zEo?@.po'zz? `e1׿ZGy.'JA/xً(.:.(~>Y_ [K [Vl+7w_3r=`6e꺵llq< J\?-R7I ! isL!zol 勪x !N3F̝jqx$qUOn9P*^/&~<\wunZWzmJȖw/> m Azbå,'P > \z:c$9I)5 "@j-'qtB[9dc}l6Y}y m,xN-nUYOr0w.3*ܼ}8U?5cȾšWL-DV9=ӫ^|<}>QJA0P4#|R^4_N~ qB!B!EQTO\|>nV |O2`O͑kz7Pd ]M3oL Dh [3'%Ǜ3cƌu|?;uX?8<׈t*~d *xޑ)>^X$F7\Y}V <׮fS7xS T!B!BLTjgP O(:-CGuλ{O~ S`o|u"w[.'9qTNJ2B8y$j/x u#S5ϴKv@Xk1 ]go(N鰓'sDեD7Mk=_:j3_\M7I / fO(H<'$ēxOI<'x'K#4c. KWp<|%ԫEFVA9Krm;hUNЉ(/2?zP5'CU~ÌE,t=Hq#ꃽD ,(RRyq]?_̿i}_l+y⹿sco'ksdED<+vz{)Qsφ'yWxӑ"F?%~ @G=xOI<'$ēxO❙&oժU:tpp饗2]Ӥ.wfMdV=]T'敄NDk⺳~q[{G, Tp>qhSkOCW'-W㊼#}ޅP&tvaS3/͇.ֻGK0[2MMH"4}1'Ϡd%ēxOI<'$ēxoxq8o kx 3{lW7Eţ_9.{p?O78ZcU﹖iqy|[Ne;Ə>})j)W~-ڍpB·pCq,s>*[w>̗>v/I{/nYR wƏ3D9˘wHoBc!;I !9-g{{$uAM)|A܋Ql\GgY)M-_VR>쌰yW?L=,)y8cO/ĉ'5sR.=i$tp̥h\ɶi󃬜  qÏe{JR.7 IDAT^3+[ѭ]N^ڙVŬe&˚{|rqAc^T; Y2Lu29a~BGS,)Qt lV69KLQ4fv9ETͲ\p~ˠsG7;#CgghEcJYMpEͤPaM&&# B' % +{Z} SX^=zSnV؀sTUA.9yn^l@/|YE"M+Eddĺ$, 0sB! B!il@-`fA>HMcK9֡!*bIcIaciR#bi̐Эcl=#8S]'P ?K|TBIϑJXwZ(!#d ~veT33W;y9MAʎ'#)>ܫt> XF5`1bR G԰SiI5J;ʎf;*<+́~#qE>.^@ҼaPoddBJ5qMXPLF\.#hl(_FPq0`8]}:&Gqhw `PMl9&̎.Jڨ]`v޿Қj0MԞSDKj@ P%T5O՜c.e.rVߝ5dzYJadj5 Y\\ԍ_ъ 0DxTe>J^a[K5'fZ"qT)3n"LA ? -+J jlG g=&h?{zd~Ƚ.+6JNlol>:X%IoRQ`ȞokG 358:v CXYVj`̿T k\]ʃcpγN-fU%3=$P2tdqM tq2u\SVB!&H*PBӖFO(VX@ 5"x(A߰D -8HsK4)M?s8q(MЇ]4jЉDRSߨ蓮,T8ALW{T@[`/ՖaI.0 P.+8fXf< z6CdP#JFhO/n9Dd7}͌_9:Z7IbeJ԰b܊җ'5NZ2+vP8<ZuzB﭂axhb7bihB)thC}&MͦaI,IAjYȌe_Ob]ц];x} ^5"ݼ=Kl/&,[;Zl5]Ig_+rŻh5>fڇaUZ"4yk/fi3}Cݞ::n0c9o*E3$BG(Yٸ#N8xo 43HRUPb b-5Ok1`bVJתF"AegJ'5El-S!B@WW^wBJU!8])*fs>xo~T*bROK9Z`C(NKj4h+I)s1xB!Ŀ4]ꢥOh BT~3jt+,vX}V\~$vdNRl"7,Ѿy@aŜrh>^+z ooo݀>Vc<N UlO$M9-DKP-T>4T@O 'uв™&S-^+nx֨h/w )S*y30[cV}NJ~aZsd9Bliˡ`xN?ODdcWySC1Ri6ˈFdm^+N=IkװV=ˡ$JrLP:+(E'~˰/ax=(xf4 eI݈cdsԾ|tn%ܧm6B  9P6 Ix 2OD6,7Wbz{M~ߍGuZ5:;>t;*,XBQvL((6̡~vh'?B!lWo͚5D"ϟ8qU!8Lq1@mg9(Tti,响eZ*Qv51VZQq4:Rq l vAT=2|UP=njl܉9 X8,)>68,K8}=<3*E5fjdZd4(:\ K).5=iA *;SH*N 4;{i- 2et9jf+aBk_ ?"*GU flAvQ(t4ZΟ`KO}Z9hRQrY $S獕՜Ejdo?{m|\nJX欛!.R1mTSiӼsdఋ%jL.%MFKJ*=Tb34qHgy*'s‑a64k[4BQZtxNY.Dxic)f,zQ]\ʍ,EY?͌_R0t 1®^L3 ZwDML Uuo:t>8bMۺ؜v=yP9ގf~EՇ5,21yg| S:ɞ]nc]c Sנ0<ߛ&R"s*%+ vEI_sk}`{z%^Q2jO]Qѯ !ıU!B!g>X![hwFvmIc1{|%d3oYƜ9,?o*/>sXX3 Ou! |jfͼp2s;Ql;/{o_9ںE\x͗x91 q΍ᆷ,cZ]zmؖZU{8wa- =>LC,?]Afq_19Z~f- GO/d~Op>zvҵ\tfaOaśWu35o%oys:[J̸ NS@B!B!ę)ν0e\IO+0~->c୷7,ƂF瓷o姹E=7Y=psJ<ǽ?;OSȡ&vO|QOnYK iJ !B!bR{1"?яFzy{{J'*8c8.7N7Zw=oq W_<J+x'3§,Ηؒ~3уפ`La)·^V~|T~\z7?w3+͆Zn\=_]-9.]<@c,LѸqW}Qu8+qu Φ5[̸ *|{sf[v@bU ɍh־HC[?hon2Ϊ;:} \sY,^09 ?oC:d2,>ǃK|Gzb ?n1:fF T!B!BLXk]uaZ{&LrO$;1rKTlm)-**-VcG/z=XDr."$$+$<ϼ0{yY{͇>$9312䡾[&IW亳uxwoJwi~NcQY~ݻ7W.[ޗԝ9rކΘQR,O}1*/]%-wHޚ/)9k_CnQZ5ey$_~Ƿ{G7;?)fG>Or1౿vWRzjLUa`@vN~tG3eW.}/8=Mx='c9+{ϸ5%[O6Wݝ$%c'GTۓj̉yIk<\֭QIϘ:G=;LUϱ?o>s%fԴIyAnme 2n+.]ݐOmy=o&y3m̃ ?ӷO.zrlGy{ܵ_͞3cU+WXwkY.7Y UJJ{}u:y}rzf3[#`%Ms܃3k>ww=7'=]|}\ѝ{/yn~Ni>F')̪>0[hϜ.87_[ՓxmyuW]9%<̝B&y篻&S]Veժ_5)S'%tm>g}%]ݼ|FMʿyti9GI+_μzwiM{_;yޕ.^7R'rybIy5?3w}6[6~=ϋ?'||ޟKV\:^\_)CJM>:/\/&?1f >rG eo/WQ-n/{s?_\7:9}wq;JYy;W~'s}̼Of]wK2ve>d@MRM<)WdE_,yb8ͫOy'Q7g'eL Oȁ|?m}0K`wg`aYKg_=4}%wҟ_s͊zB;+i IDATΉ=P+or;#.+׏O5~7%<ёNO)%MOޒwC9vw,\ޛ2TA[ɼ 0de} !tٲ7#-*cLʯ-],C6uZGz];ԩk]ոqc3g{GzT!ZuG:UNzu'gɿ饔:vR̽#ug@ҩ7<` 0BKwG:?%EOOOOOOOOOOOol D Ap#jJIU OCǀ #D)S Os2*ݑNOIz= hTU;UJJOOOOOOOOOOOoxz :T!J)*%DOOOOOOOOOOOoxz PahtZUJNyh`@h`@h`@h`@h`@h`@h`@h`@h`@h`@h`@h`@؄n*@>(<]5XUUmիWP5vvJm?_PU]^2)ng200Mw5?.[ުj=*UUaPahTU;UJJOOOOOOOOOOoWRX߾;ߒ{[*I~Kq*0t 0B<===========]٥mh[xfo}eT!ڥ#V՟=t0vJ)iTN_mwTTTTY9s1 *@*@*@*@>x߸џ}ݍ]uULKww;PMQz73[z;PPPP%R/|aPahTU;UJJOOOOOOOOOOoWRҮӪ:V=ORUfϷR|:T!J)*%DOOOOOOOOOOoWP57~T!ڥ#V՟ I ҕR.ݩ~= |@oop`a@60a„!βއ:φ404040404040404040404;9slN'T` Hc@UwSUT)*==========]WJIOH{0Z@?JUU=JDB`Pa(t==========]W_Ce3PahtZUJ.[3d&2twKWJNtwvl 404040404040404;>À l`„ Creu h`@h`@h`@h`@h`@h`@ӟt;̙3'gyFy晙3gN=\s5pBCUwSUT)*==========]WJIO\p7o^^eW"|p\xyk_j*UUm|+`1QJT))%%zzzzzzzzzzzR6gʕy^8L\s56-^ss2*ݑNOIzk̤]6y2u-Nym{ڥ+t]Se;P;~jP7̟?`xh@*@*0h^zi.\[pa.!8e@.ˢE}-e]6'ؾ)`zzzrg֬Y8qb< ^;|?̸qc@sꫯK_\q8_}#t38#gqFTvv РkXz{{; * & u><$x6|;PahTU;UJJOOOOOOOOOOoWRҮӪ:V=ORUfϷR *NRR+Jykl~CyF*ݑNOIzk̤]vJ)iTN_mwTTYs)cp<xV:z9묳2k֬,X`1@> @GP9sfz{{#V+s4~kܹsTۇ;Pr7or-Ctˀ lRNPm6iҤvmk6󪪆De@ѣSuƌ3G.)`=97G. V ?кt-~fVyի^wߜtICx"VY`A,X0@h`@h#0Bt*%Uƌ5`wRJIHzTUl:('IW&W6ۅFRJJI))Q{ZU|wIcvY61np ~nFvHURľjzKRi%uRꔴ69nt>ao `=Cxv|@֨u彫-uZk!z*2.|?ݩJ=sL*uJ] n<-/ɜ}&κܗҏWdQkԮY9ԹyGVN]p~a2.|d^z!驞ʒ|)dzĤrlz0?z7yZ%3Sr׻yTV' ;*2eƔVeœVwtH2}O>;G`ks[{r|-'=W|7qv^Kkη0'{ubNI>++fLOW3} /`UǏ/}}}}`;[R.zzzzzzzzzzz;hgvJR:Pe?{03KrtL │ SumTask │ task1 │ ├────────┼────────────────┼───────────────────┼───────┤ │ a │ 2 │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task3 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 3 │ SumTask │ task3 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task4 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 4 │ SumTask │ task4 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task5 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task6 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 6 │ SumTask │ task6 │ ╘════════╧════════════════╧═══════════════════╧═══════╛ Parameters with `` do not have a value. If a missing parameter is **required**, it is marked with a `(*)`. For example: .. code-block:: bash Workflow: example.json Id: demo Description: demo ╒════════╤════════════════╤═══════════════════╤═══════╕ │ Name │ Value │ Task identifier │ Id │ ╞════════╪════════════════╪═══════════════════╪═══════╡ │ a⁽*⁾ │ │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ list │ [0, 1, 2] │ SumList │ task0 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumList │ task0 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ │ SumTask │ task1 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task1 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 3 │ SumTask │ task3 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task3 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 4 │ SumTask │ task4 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task4 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task5 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 6 │ SumTask │ task6 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task6 │ ╘════════╧════════════════╧═══════════════════╧═══════╛ ⁽*⁾ Value is required for execution. In this case, the `a` parameter for task `SumTask` at node `task2` is required and must be provided before execution. Workflow nodes can be identified by: - **Task identifier** – the identifier of the code to be executed. - **Id** – the unique identifier of the node within the workflow. - **Label** (if present) – a human-readable tag, which may not be unique. If no labels are defined, the `Label` column is omitted from the output. Validating Execution Arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To override workflow parameters for execution, use the `-p` option: .. code-block:: bash ewoks execute example.json -p SumTask:delay=99 --input-node-id taskid Before executing the workflow, you can verify that your arguments are applied as intended using `ewoks show` with the same arguments: .. code-block:: bash ewoks show example.json -p SumTask:delay=99 --input-node-id taskid The output will reflect the overridden `delay` values: .. code-block:: bash Workflow: example.json Id: demo Description: demo ╒════════╤════════════════╤═══════════════════╤═══════╕ │ Name │ Value │ Task identifier │ Id │ ╞════════╪════════════════╪═══════════════════╪═══════╡ │ list │ [0, 1, 2] │ SumList │ task0 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumList │ task0 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 99 │ SumTask │ task1 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ │ SumTask │ task1 │ ├────────┼────────────────┼───────────────────┼───────┤ │ a │ 2 │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 99 │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 99 │ SumTask │ task3 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 3 │ SumTask │ task3 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 99 │ SumTask │ task4 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 4 │ SumTask │ task4 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 99 │ SumTask │ task5 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 99 │ SumTask │ task6 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 6 │ SumTask │ task6 │ ╘════════╧════════════════╧═══════════════════╧═══════╛ The value before the colon in `-p :=` refers to the node identifier, which defaults to the `Id` column. You can change this behavior with the `--input-node-id` option to use the `Label` or `Task identifier` instead. Graphical Interfaces -------------------- You can also inspect input parameters using graphical tools. Desktop GUI ~~~~~~~~~~~ To use the :ref:`desktop GUI ` based on Orange: .. code-block:: bash ewoks execute example.json --engine=orange -p SumTask:delay=99 --input-node-id taskid Then double-click on each node to inspect or edit parameters: .. image:: images/inspect_desktop.png :alt: Double-click on each node to inspect input parameters. Web GUI ~~~~~~~ To inspect parameters via the :ref:`web interface `: 1. Convert the workflow while applying overrides: .. code-block:: bash ewoks convert example.json example_with_params.json --test -p SumTask:delay=99 --input-node-id taskid 2. Start the web server: .. code-block:: bash ewoksweb You should see: .. code-block:: bash INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) 3. Open the workflow file in your browser: .. image:: images/inspect_web_open.png :alt: Open the workflow file from disk in the web UI. 4. Click on a node to view or edit its parameters: .. image:: images/inspect_web_node.png :alt: Click on each node to inspect input parameters. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/job.rst000066400000000000000000000032651512474103500251210ustar00rootroot00000000000000Submit a job to a worker ======================== The client may want to start a workflow execution remotely and wait for the result while doing other work. Installation ------------ Install on the client side .. code-block:: bash pip install ewoksjob[redis] Install on the worker side .. code-block:: bash pip install ewoksjob[worker,redis,monitor] The communication between client and worker goes through *Redis*, *RabbitMQ* or *Sqlite3*. Depending on which one you choose, the `redis` installation option may vary. Both client and worker need access to a configuration that specifies the URL of the database and/or broker. For more information see the `ewoksjob documentation `_. Submit a workflow ----------------- Start a worker that can execute *ewoks* graphs .. code-block:: bash ewoksjob worker Submit a workflow from python, possible from another machine .. code-block:: python from ewoksjob.client import submit workflow = {"graph": {"id": "mygraph"}} future = submit(args=(workflow,)) result = future.get() Submit a workflow from the command line, possible from another machine .. code-block:: bash ewoks submit empty --test Submit a workflow in *BLISS* ---------------------------- In the context of *Bliss* .. code-block:: bash BEACON_HOST=hostname:25000 ewoksjob worker Submit a workflow as usual .. code-block:: bash BEACON_HOST=hostname:25000 ewoks submit empty --test The environment variables are needed for communication between worker and client via the message broker. Workflow monitoring ------------------- Start a web server for monitoring jobs .. code-block:: bash ewoksjob monitor ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/python.rst000066400000000000000000000017001512474103500256600ustar00rootroot00000000000000.. _execute_python: Execute a workflow from Python ============================== Install requirements .. code-block:: bash pip install ewoks Execute a workflow .. code-block:: python from ewoks import execute_graph result = execute_graph("/path/to/graph.json", engine=None) The :ref:`hello world ` example provides a small but complete example of task implementation, workflow definition and workflow execution. The *engine* argument can be * *ppf*: required to execute cyclic workflows * *dask*: required to parallelize workflow execution (thread, processes, cluster) * *orange*: required to execute workflows with a graphical interface When no *engine* is specified it will use sequential execution in the current process. Bindings can be installed as follows .. code-block:: bash pip install ewoks[orange,dask,ppf] For more information see the `ewokscore documentation `_. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/rest.rst000066400000000000000000000006101512474103500253130ustar00rootroot00000000000000Set up a REST Ewoks server ========================== Install requirements .. code-block:: bash pip install ewoksserver Start the REST server .. code-block:: bash ewoks-server or for an installation with the system python .. code-block:: bash python3 -m ewoksserver.server For more information see the `ewoksserver documentation `_. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/running_workflows.nblink000066400000000000000000000001111512474103500305740ustar00rootroot00000000000000{ "path": "../../src/ewoks/tests/notebooks/running_workflows.ipynb" }ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/task_inputs.rst000066400000000000000000000204131512474103500267050ustar00rootroot00000000000000Define Task class inputs ======================== There are two ways of defining task inputs in Ewoks when using the `Task` class: - :ref:`Input names`: inputs are defined by their names, given as lists of strings - :ref:`Input model`: inputs are defined by a `Pydantic model `_ These two methods are incompatible and only one should be picked (see :ref:`Incompatibility`). .. _Input names: Input names ----------- Required input names are given as a list of strings via the ``input_names`` subclass argument of ``Task``. They can then be retrieved in the task via ``self.inputs`` or ``self.get_input_value``: .. code-block:: python from ewoks import Task class ExampleTask(Task, input_names=["a", "b"]): def run(self): a = self.inputs.a b = self.get_input_value("b") print(f"a={a} b={b}") For demonstration purposes, we can `execute a task from Python <./task_python.rst>`_. .. code-block:: python-console >>> task = ExampleTask(inputs={"a": 1, "b": 2}) >>> task.run() a=1 b=2 Since these are **required** input names, Ewoks will throw a ``TaskInputError`` if one is missing .. code-block:: python-console >>> task = ExampleTask(inputs={"a": 1}) ewokscore.task.TaskInputError: Missing inputs for : {'b'} We can allow optional inputs by giving a list of strings to a ``optional_input_names`` subclass argument of ``Task`` .. code-block:: python class ExampleTaskWithOptional(Task, input_names=["a", "b"], optional_input_names=["c"]): def run(self): a = self.inputs.a b = self.get_input_value("b") c = self.inputs.c print(f"a={a} b={b} c={c}") These optional inputs can be specified .. code-block:: python-console >>> task = ExampleTaskWithOptional(inputs={"a": 1, "b": 2, "c": 3}) >>> task.run() a=1 b=2 c=3 or omitted. In this case, they will be set to the special object ``MISSING_DATA``: .. code-block:: python-console >>> task = ExampleTaskWithOptional(inputs={"a": 1, "b": 2}) >>> task.run() a=1 b=2 c= Default values can be given thanks to ``get_input_value`` .. code-block:: python class ExampleTaskWithDefault(Task, input_names=["a", "b"], optional_input_names=["c"]): def run(self): a = self.inputs.a b = self.get_input_value("b") c = self.get_input_value("c", 0) # <-- Default value print(f"a={a} b={b} c={c}") .. code-block:: python-console >>> task = ExampleTaskWithDefault(inputs={"a": 1, "b": 2}) >>> task.run() a=1 b=2 c=0 Subclassing ^^^^^^^^^^^ Subclasses of a task will inherit the input names from the base class and any additional input name will be added to those: .. code-block:: python class ChildExampleTask(ExampleTaskWithOptional, input_names=["d"]): def run(self): print(self.get_input_values()) .. code-block:: python-console >>> task = ChildExampleTask(inputs={"a": 1, "b": 2, "c": 3, "d": 4}) >>> # Accepts `a`, `b` and `c` in addition to `d` ^ >>> task.run() {'a': 1, 'b': 2, 'c': 3, 'd': 4} .. _Input model: Input model ----------- .. versionadded:: 1.1.0 Instead of input names, it is possible to provide a `Pydantic model `_ for inputs. The model needs to derive from ``ewoks.BaseInputModel`` and must be provided via ``input_model`` to the task. Inputs can then be retrieved in the task via ``self.inputs`` or ``self.get_input_value``: .. code-block:: python from ewoks import Task from ewoks import BaseInputModel class Inputs(BaseInputModel): a: int b: int class ExampleTaskWithModel(Task, input_model=Inputs): def run(self): a = self.inputs.a b = self.get_input_value("b") print(f"a={a} b={b}") .. code-block:: python-console >>> task = ExampleTaskWithModel(inputs={"a": 1, "b": 2}) >>> task.run() a=1 b=2 The advantage of using a model is that **inputs are validated by Pydantic** .. code-block:: python-console >>> task = ExampleTaskWithModel(inputs={"a": 1}) ewokscore.task.TaskInputError: 1 validation error for Inputs b Field required [type=missing, input_value={'a': 1}, input_type=dict] For further information visit https://errors.pydantic.dev/2.10/v/missing >>> task = ExampleTaskWithModel(inputs={"a": 1, "b": "not_a_number"}) ewokscore.task.TaskInputError: 1 validation error for Inputs b Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='not_a_number', input_type=str] For further information visit https://errors.pydantic.dev/2.10/v/int_parsing All Pydantic features such has `Default values `_, `Constraints `_ or `Custom validation `_ are available. For example, we can add an optional input to our model by giving it a default value .. code-block:: python from ewoks import Task from ewoks import BaseInputModel class Inputs(BaseInputModel): a: int b: int c: int = 0 # <-- `c` is optional class ExampleTaskWithModel(Task, input_model=Inputs): def run(self): a = self.inputs.a b = self.get_input_value("b") c = self.inputs.c print(f"a={a} b={b} c={c}") .. code-block:: python-console >>> task = ExampleTaskWithModel(inputs={"a": 1, "b": 2}) >>> task.run() a=1 b=2 c=0 .. note:: It is possible to reproduce the default behaviour of `optional_input_names` that are set to ``MISSING_DATA`` if not set. For this, add ``MissingData`` as a possible type for the input in the model and use ``MISSING_DATA`` as the default value .. code-block:: python from ewoks import Task from ewoks import BaseInputModel from ewokscore.missing_data import MissingData, MISSING_DATA class Inputs(BaseInputModel): a: int b: int c: int | MissingData = MISSING_DATA # <-- `c` is optional class ExampleTaskWithModel(Task, input_model=Inputs): def run(self): a = self.inputs.a b = self.get_input_value("b") c = self.inputs.c print(f"a={a} b={b} c={c}") .. code-block:: python-console >>> task = ExampleTaskWithModel(inputs={"a": 1, "b": 2}) >>> task.run() a=1 b=2 c= .. _Subclassing models: Subclassing ^^^^^^^^^^^ Subclasses of tasks with input models will inherit the model if they do not implement a model themselves .. code-block:: python class ChildTask(ExampleTaskWithModel): def run(self): print(self.get_input_values()) .. code-block:: python-console >>> task = ChildTask(inputs={"a": 1, "b": 2, "c": 3}) >>> task.run() {'a': 1, 'b': 2, 'c': 3} If the subclass does have an input model, it must be inherit from the model of the base class to have compliant inputs .. code-block:: python class NewInputs(Inputs): d: int class ChildTaskWithModel(ExampleTaskWithModel, input_model=NewInputs): def run(self): print(self.get_input_values()) .. code-block:: python-console >>> task = ChildTaskWithModel(inputs={"a": 1, "b": 2, "c": 3, "d": 4}) >>> task.run() {'a': 1, 'b': 2, 'c': 3, 'd': 4} .. _Incompatibility: Incompatibility between methods ------------------------------- .. danger:: It is **not possible to mix** ``input_names``/``optional_input_names`` and ``input_model``! This means a ``Task`` **cannot** have both ``input_names``/``optional_input_names`` and ``input_model`` defined. But also, **a subclass must use the same input definition method as its base class**: - If the base class task uses ``input_names``/``optional_input_names``, the subclass must use ``input_names``/``optional_input_names`` as well. - If the base class task uses ``input_model``, the subclass must use an ``input_model`` that subclasses the model of the base task (see :ref:`above `). ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/howtoguides/task_python.rst000066400000000000000000000043161512474103500267100ustar00rootroot00000000000000Execute a task from Python ========================== Walkthrough ----------- This page shows to instantiate a task from Python, set its inputs, execute it and retrieve its outputs. It can be useful for debugging a single task for example. To illustrate it, we will use the `SumTask` below that adds two numbers `a` and `b`, and stores the result in `result`: .. code-block:: python class SumTask( Task, input_names=["a"], optional_input_names=["b"], output_names=["result"] ): def run(self): result = self.inputs.a if self.inputs.b: result += self.inputs.b self.outputs.result = result .. admonition:: Tip This task can be imported from ``ewokscore.tests.examples.tasks.sumtask`` Task inputs need to be set via the ``inputs`` argument when creating the task before executing via ``execute``: .. code-block:: python >>> task = SumTask(inputs={"a": 5, "b": 10}) >>> task.execute() The results can then be retrieved from ``outputs`` or using ``get_output_value``: .. code-block:: python >>> task.outputs["result"] 15 >>> task.get_output_value('result') 15 Limitations ----------- Inputs cannot be modified once the task is instantiated .. code-block:: python >>> task = SumTask(inputs={"a": 5, "b": 10}) >>> task.inputs.a = 10 ... ewokscore.variable.ReadOnlyVariableError: a A new task instance needs to be created to execute it with different inputs .. code-block:: python >>> task = SumTask(inputs={"a": 10, "b": 10}) >>> task.execute() >>> task.get_output_value("result") 20 Outputs will be missing before the task is executed. More specifically, the outputs are set to `MISSING_DATA `_ until they are set by the execution: .. code-block:: python >>> task = SumTask(inputs={"a": 5, "b": 10}) >>> task.get_output_value("result") Full code --------- .. code-block:: python from ewokscore.tests.examples.tasks.sumtask import SumTask task = SumTask(inputs={"a": 5, "b": 10}) task.execute() print(task.get_output_value("result")) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/index.rst000066400000000000000000000022611512474103500231100ustar00rootroot00000000000000ewoks |version| =============== .. image:: https://img.shields.io/badge/DOI-10.1080/08940886.2024.2432305-blue :target: https://doi.org/10.1080/08940886.2024.2432305 Many `workflow management systems `_ exist to deal with data processing problems that can be expressed as a graph of tasks, also referred to as a *computational graph* or *workflow*. The main purpose of a workflow management system is to provide a framework for implementing tasks, creating graphs of tasks and executing these graphs. The purpose of *ewoks* (Extensible Workflow System) is to provide an abstraction layer between graph representation and execution. This allows using the same tasks and graphs in different workflow management systems. *ewoks* has been developed by the `Software group `_ of the `European Synchrotron `_. .. admonition:: Quick Start Install *ewoks* .. code-block:: bash pip install ewoks Execute the demo workflow .. code-block:: bash ewoks execute demo --test .. toctree:: :hidden: tutorials howtoguides explanations reference ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/reference.rst000066400000000000000000000002201512474103500237300ustar00rootroot00000000000000Reference ========= Command-Line Interface (CLI) and Python API reference. .. toctree:: :maxdepth: 1 reference/cli reference/api ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/reference/000077500000000000000000000000001512474103500232045ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/reference/api.rst000066400000000000000000000001421512474103500245040ustar00rootroot00000000000000API reference ============= .. autosummary:: :toctree: _generated :recursive: ewoks ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/reference/cli.rst000066400000000000000000000065641512474103500245200ustar00rootroot00000000000000.. _cli: CLI reference ============= ewoks install ------------- .. argparse:: :module: ewoks.__main__ :func: create_argument_parser :prog: ewoks :path: install **Install the packages required to run a workflow**. **ewoks install** relies on the existence of the ``requirements`` field in the ``graph`` field of the workflow. If no ``requirements`` field exist, **ewoks install** will try to extract requirements from the tasks in the workflows before installing them. Unless ``--yes`` is provided, **ewoks install** will ask for confirmation before installing the packages. By default, packages are installed in the current Python environment: if **ewoks install** is run in a virtual environment, the packages will be installed in this virtual environment. ewoks convert ------------- .. argparse:: :module: ewoks.__main__ :func: create_argument_parser :prog: ewoks :path: convert **Convert a source workflow in another format supported by Ewoks**. The source workflow is untouched: a new destination workflow is created. .. important:: **ewoks convert** will save the packages installed in the current environment as `requirements` in the destination workflow. ⚠️ If the source workflow has a `requirements` field, it will therefore be replaced by this package list. This can be disabled by using the ``--exclude-requirements`` argument. **ewoks convert** can also be used to store `inputs` inside the destination workflow. ewoks execute ------------- .. argparse:: :module: ewoks.__main__ :func: create_argument_parser :prog: ewoks :path: execute **Execute a workflow using one of the Ewoks-supported engine**. The workflow can have any format as long it is supported by Ewoks. Inputs can be provided only for this execution. .. tip:: Using the execution option ``convert_destination`` (``-o convert_destination=``) runs `ewoks convert` on the executed workflow, producing a new workflow that stored the inputs and the requirements inside. The produced workflow can then be used as a provenance document since it can reproduce the source workflow execution in exactly the same way. ewoks submit ------------ .. argparse:: :module: ewoks.__main__ :func: create_argument_parser :prog: ewoks :path: submit **Execute a workflow remotely, in a worker**. Very similar to ``ewoks execute`` except the execution does not run in this environment (client) but in a remote one (worker). Requires the `EWOKS_CONFIG_URI` environment variable to be set. .. tip:: Before running this command, the client and the worker must have agreed on a messaging protocol to communicate. See the `ewoksjob documentation `_ to see how to set-up this. ewoks show ---------- .. argparse:: :module: ewoks.__main__ :func: create_argument_parser :prog: ewoks :path: show **Display the workflow parameters with their default values and descriptions**. Required parameters without default value are highlighted. Parameters which get their value at runtime from upstream nodes in the workflow are not shown. Parameters values in the displayed table can be provided in the same way as inputs for ``ewoks execute``. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials.rst000066400000000000000000000003521512474103500240260ustar00rootroot00000000000000Tutorials ========= .. toctree:: :maxdepth: 1 tutorials/getting_started tutorials/hello_world tutorials/create_and_edit tutorials/execute tutorials/infrastructure tutorials/external tutorials/develop ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials/000077500000000000000000000000001512474103500232745ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials/create_and_edit.rst000066400000000000000000000011021512474103500271120ustar00rootroot00000000000000Create and edit workflows ========================= Documentation on the different interfaces to create and edit workflows: * `ewoks tutorial on workflow creation `_: create a workflow from the Python interface * `ewoksorange `_ : create and execute workflows with a desktop GUI * `ewoksweb `_: web frontend to create, visualize and execute workflows * `ewokscore `_ : create workflows and implement tasks ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials/develop.rst000066400000000000000000000004661512474103500254720ustar00rootroot00000000000000Ewoks core development ====================== Documentation on libraries used for core development: * `ewoksutils `_ : developer utilities shared by client and worker side * `ewokscore `_ : developer utilities for engine implementation ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials/execute.rst000066400000000000000000000020461512474103500254720ustar00rootroot00000000000000Execute workflows ================= Ewoks workflows can be executed via several interfaces and with several workflow engines. The :ref:`python interface ` for executing workflows is a function .. code-block:: python from ewoks import execute_graph result = execute_graph("/path/to/graph.json", engine=None) The equivalent exists for the :ref:`command-line `. The :code:`engine=None` argument selects the default engine. Documentation on different engines: * `ewoksppf `_ : execute cyclic workflows * `ewoksdask `_ : parallel and distributed workflow execution * `ewoksorange `_ : execute with desktop GUI Documentation on other interfaces than python and the command-line interface: * `ewoksweb `_ : execute with web GUI * `ewoksserver `_ : execute with REST API * `ewoksjob `_ : job scheduling for Ewoks workflows ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials/external.rst000066400000000000000000000015011512474103500256450ustar00rootroot00000000000000More tutorials ============== - Tutorial on `workflow creation in Python `_. - `Documentation `_ on creating and executing workflows with a desktop GUI. - `Documentation `_ on creating and executing workflows with a web GUI. - `Ewoks training `_ on task implementation, workflow creation/execution and job scheduling. - Tutorial on `Ewoks for Online Data Processing `_ with `blissdata `_ which is a python library to store and access scientific data during and after experiment at large-sclae facilities like `ESRF `_. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials/getting_started.rst000066400000000000000000000017211512474103500272160ustar00rootroot00000000000000Getting started =============== Install *ewoks* .. code-block:: bash pip install ewoks Create a test workflow in JSON format (“acyclic1” is an test workflow that ships with ewoks) .. code-block:: bash ewoks convert acyclic1 --test test.json Inspect workflow parameters before executing the workflow .. code-block:: bash Inspect the demo workflow .. code-block:: bash ewoks show test.json Execute a workflow and print the output of all tasks .. code-block:: bash ewoks execute test.json --outputs all For a desktop GUI, install *ewoks* with the orange binding .. code-block:: bash pip install ewoks[orange] Open the test workflow in the GUI .. code-block:: bash ewoks execute test.json --engine orange For a web GUI, install *ewoksserver* with the frontend .. code-block:: bash pip install ewoksserver[frontend] Start the *ewoks* web server, open the link in a web browser and load the `test.json` file .. code-block:: bash ewoks-server ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials/hello_world.rst000066400000000000000000000057521512474103500263510ustar00rootroot00000000000000.. _hello_world: Hello world =========== This script demonstrates how to define an Ewoks workflow from the ground up. The only thing needed to run it is the ``ewoks`` Python package .. code-block:: bash pip install ewoks The script defines defines two tasks, one that ask for a name and the other that creates a greeting, creates a workflow out of these and executes it. .. code-block:: python from ewokscore import Task from ewoks import execute_graph # Define a workflow task with an output class AskForName(Task, output_names=["input_name"]): def run(self): name = input("What is your name?") if not name: name = "World" self.outputs.input_name = name # Define a workflow task with inputs and outputs class SayHello( Task, input_names=["name"], optional_input_names=["in_french"], output_names=["greeting"], ): def run(self): name = self.inputs.name if self.inputs.in_french: hello = "Bonjour" else: hello = "Hello" self.outputs.greeting = f"{hello}, {name}!" # Define nodes: entities that will execute tasks nodes = [ { "id": "ask_for_name", "task_type": "class", "task_identifier": "__main__.AskForName", }, { "id": "say_hello", "task_type": "class", "task_identifier": "__main__.SayHello", }, ] # Define links that make data flow from one node to another links = [ { "source": "ask_for_name", "target": "say_hello", "data_mapping": [{"source_output": "input_name", "target_input": "name"}], } ] # Define a workflow from nodes, links and graph metadata workflow = {"graph": {"id": "hello_world"}, "nodes": nodes, "links": links} # Execute a workflow result = execute_graph(workflow) print(result) print('----') # Optionally, define inputs inputs = [{"id": "say_hello", "name": "in_french", "value": True}] # Execute a workflow with inputs result = execute_graph(workflow, inputs=inputs) print(result) This is the output you should get .. code-block:: bash $ python hello_world.py What is your name? Ewoks # <--- `input` waits for some input. `Ewoks` was typed here and Enter pressed. {'greeting': 'Hello, Ewoks!'} ---- What is your name? # <--- Enter was pressed without typing anything {'greeting': 'Bonjour, World!'} .. note:: Ewoks developers rarely design workflows by hand like this but instead use graphical interfaces to produce the dictionnary (usually stored in JSON). See :ref:`this page about the Ewoks graphical interfaces `. .. note:: For all the fields that can be set when creating the dictionnary representing the workflow, see the `Ewoks specification `_. ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/doc/tutorials/infrastructure.rst000066400000000000000000000005261512474103500271110ustar00rootroot00000000000000Infrastructure for workflow management ====================================== Documentation related to workflow infrastructure (servers, message brokers): * `ewoksjob `_: job scheduling for Ewoks workflows * `ewoksserver `_: REST server to manage and execute workflows ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/pyproject.toml000066400000000000000000000040021512474103500234110ustar00rootroot00000000000000[build-system] requires = ["setuptools>=46.4"] build-backend = "setuptools.build_meta" [project] name = "ewoks" version = "4.0.0" authors = [{ name = "ESRF", email = "dau-pydev@esrf.fr" }] description = "Extensible Workflow System" readme = { file = "README.md", content-type = "text/markdown" } license = { file = "LICENSE.md" } classifiers = [ "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", ] requires-python = ">=3.8" dependencies = [ "ewokscore >=4.0.1,<5", "ewoksutils >=1.6.0,<2", "tabulate", "importlib_resources; python_version < '3.9'", ] [project.urls] Homepage = "https://gitlab.esrf.fr/workflow/ewoks/ewoks/" Documentation = "https://ewoks.readthedocs.io/" Repository = "https://gitlab.esrf.fr/workflow/ewoks/ewoks/" Issues = "https://gitlab.esrf.fr/workflow/ewoks/ewoks/issues" Changelog = "https://gitlab.esrf.fr/workflow/ewoks/ewoks/-/blob/main/CHANGELOG.md" [project.optional-dependencies] dask = ["ewoksdask >=2,<3"] ppf = ["ewoksppf >=2,<3"] orange = ["ewoksorange >=3,<4"] esrf-data-portal = ["pyicat-plus"] notebooks = ["ewokscore[notebooks]"] test = [ "ewoksutils[test]", "ewoks[dask]", "ewoks[ppf]", "ewoks[orange]", "ewoks[esrf-data-portal]", "pytest >=7", "testbook", "ipykernel", "importlib_resources", "pyqt5", "pytest-venv", ] dev = [ "ewoks[test]", "black[jupyter] >=25", "flake8 >=4", "flake8_nb >= 0.3.1", "isort", ] doc = [ "ewoks[test]", "sphinx >=4.5", "sphinx-autodoc-typehints >=1.16", "ipykernel", "nbsphinx", "nbsphinx_link", "pydata-sphinx-theme", "sphinx-argparse", "sphinx-copybutton", ] [tool.setuptools] package-dir = { "" = "src" } [tool.setuptools.packages.find] where = ["src"] [tool.coverage.run] omit = ['*/tests/*'] [tool.isort] profile = "black" force_single_line = "True" [project.scripts] ewoks = "ewoks.__main__:main" [tool.setuptools.package-data] "ewoks.tests.notebooks"= ["*.ipynb"] ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/000077500000000000000000000000001512474103500212705ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/000077500000000000000000000000001512474103500224205ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/__init__.py000066400000000000000000000006051512474103500245320ustar00rootroot00000000000000from ewokscore import Task # noqa: F401 from ewokscore.model import BaseInputModel # noqa: F401 from .bindings import convert_graph # noqa: F401 from .bindings import execute_graph # noqa: F401 from .bindings import load_graph # noqa: F401 from .bindings import save_graph # noqa: F401 from .bindings import show_graph # noqa: F401 from .bindings import submit_graph # noqa: F401 ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/__main__.py000066400000000000000000000157521512474103500245240ustar00rootroot00000000000000import sys import traceback from argparse import ArgumentDefaultsHelpFormatter from argparse import ArgumentParser from argparse import Namespace from pprint import pprint from subprocess import CalledProcessError from typing import Any from typing import List from typing import Literal from typing import Optional from typing import Union from ewoksutils.cli_utils import cli_cancel_utils from ewoksutils.cli_utils import cli_execute_utils from ewoksutils.cli_utils import cli_submit_utils from ewoksutils.cli_utils.cli_argparse import add_to_parser from .bindings import _load_graph from .bindings import convert_graph from .bindings import execute_graph from .bindings import install_graph from .bindings import show_graph from .cli_utils import cli_convert_utils from .cli_utils import cli_install_utils from .cli_utils import cli_show_utils from .errors import AbortException try: from ewoksjob.cli_utils.cancel import command_cancel as _command_cancel from ewoksjob.cli_utils.submit import command_submit as _command_submit except ImportError: _command_submit = None _command_cancel = None def create_argument_parser(shell: bool = False) -> ArgumentParser: parser = ArgumentParser( description="Extensible WOrKflow System CLI", prog="ewoks", formatter_class=ArgumentDefaultsHelpFormatter, ) subparsers = parser.add_subparsers(help="Commands", dest="command") execute = subparsers.add_parser( "execute", help="Execute a workflow", formatter_class=ArgumentDefaultsHelpFormatter, ) submit = subparsers.add_parser( "submit", help="Schedule a workflow execution", formatter_class=ArgumentDefaultsHelpFormatter, ) cancel = subparsers.add_parser( "cancel", help="Abort a scheduled workflow execution", formatter_class=ArgumentDefaultsHelpFormatter, ) convert = subparsers.add_parser( "convert", help="Convert a workflow", formatter_class=ArgumentDefaultsHelpFormatter, ) install = subparsers.add_parser( "install", help="Install requirements of a workflow", formatter_class=ArgumentDefaultsHelpFormatter, ) show = subparsers.add_parser( "show", help="Show workflow information", formatter_class=ArgumentDefaultsHelpFormatter, ) add_to_parser(execute, cli_execute_utils.execute_arguments(shell=shell)) add_to_parser(submit, cli_submit_utils.submit_arguments(shell=shell)) add_to_parser(cancel, cli_cancel_utils.cancel_arguments(shell=shell)) add_to_parser(convert, cli_convert_utils.convert_arguments(shell=shell)) add_to_parser(install, cli_install_utils.install_arguments(shell=shell)) add_to_parser(show, cli_show_utils.show_arguments(shell=shell)) return parser def command_execute( cli_args: Namespace, shell: bool = False ) -> Union[List[dict], Literal[0, 1]]: cli_execute_utils.parse_execute_argument(cli_args, shell=shell) return_code = 0 keep_results = [] for workflow, graph in zip(cli_args.workflows, cli_args.graphs): print("###################################") print(f"# Execute workflow '{workflow}'") print("###################################") try: results = execute_graph( graph, engine=cli_args.engine, **cli_args.execute_options ) except Exception as ex: traceback.print_exc() print("FAILED") results = ex return_code = 1 else: if cli_args.outputs == "none": if results is None: print("FAILED") else: print("FINISHED") else: print("") print("RESULTS:") pprint(results) print("") print("FINISHED") if results is None: return_code = 1 finally: print() if not shell: keep_results.append(results) if shell: return return_code return keep_results def command_submit( cli_args: Namespace, shell: bool = False ) -> Union[List[dict], Literal[0, 1]]: if _command_submit is None: raise RuntimeError("requires the 'ewoksjob>=1.3' package") return _command_submit(cli_args, _convert_graph=_load_graph, shell=shell) def command_cancel(cli_args: Namespace, shell: bool = False) -> Optional[Literal[0, 1]]: if _command_cancel is None: raise RuntimeError("requires the 'ewoksjob>=1.3' package") return _command_cancel(cli_args, shell) def command_convert( cli_args: Namespace, shell: bool = False ) -> Optional[Literal[0, 1]]: cli_convert_utils.parse_convert_arguments(cli_args, shell=shell) for workflow, graph, destination in zip( cli_args.workflows, cli_args.graphs, cli_args.destinations ): convert_graph(graph, destination, **cli_args.convert_options) print(f"Converted {workflow} -> {destination}") if shell: return 0 return None def command_install( cli_args: Namespace, shell: bool = False ) -> Optional[Literal[0, 1]]: cli_install_utils.parse_install_arguments(cli_args, shell=shell) for workflow, graph in zip(cli_args.workflows, cli_args.graphs): try: install_graph(graph, cli_args.yes, cli_args.python) except CalledProcessError as e: print(f"Install failed for {workflow}: {e}") except AbortException: print(f"Install aborted for {workflow}") else: print(f"Installed requirements for {workflow}") if shell: return 0 return None def command_show(cli_args: Namespace, shell: bool = False) -> Optional[Literal[0, 1]]: cli_show_utils.parse_show_arguments(cli_args, shell=shell) for workflow, graph in zip(cli_args.workflows, cli_args.graphs): show_graph(graph, original_source=workflow, **cli_args.show_options) if shell: return 0 return None def command_default( cli_args: Namespace, shell: bool = False ) -> Optional[Literal[0, 1]]: if shell: return 1 return None def main(argv=None, shell: bool = True) -> Union[Any, Literal[0, 1]]: parser = create_argument_parser(shell=shell) if argv is None: argv = sys.argv cli_args = parser.parse_args(argv[1:]) if cli_args.command == "execute": return command_execute(cli_args, shell=shell) elif cli_args.command == "submit": return command_submit(cli_args, shell=shell) elif cli_args.command == "cancel": return command_cancel(cli_args, shell=shell) elif cli_args.command == "convert": return command_convert(cli_args, shell=shell) elif cli_args.command == "install": return command_install(cli_args, shell=shell) elif cli_args.command == "show": return command_show(cli_args, shell=shell) else: parser.print_help() return command_default(cli_args, shell=shell) if __name__ == "__main__": sys.exit(main()) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/_engines.py000066400000000000000000000064341512474103500245700ustar00rootroot00000000000000import logging from functools import lru_cache from typing import Any from typing import Callable from typing import Generator from typing import List from typing import Optional from typing import Tuple from ewokscore.engine_interface import WorkflowEngine from ewokscore.engine_interface import WorkflowEngineWithSerialization from ewokscore.entry_points import EntryPoint from ewokscore.entry_points import entry_points _logger = logging.getLogger(__name__) @lru_cache(1) def get_engine_names() -> List[str]: return [name for name, _ in _iter_engine_class_loaders_with_name()] @lru_cache(1) def get_graph_representations() -> List[str]: return [ representation for representation, _ in _iter_engine_class_loaders_with_representation() ] def get_execution_engine(engine_name: Optional[str]) -> WorkflowEngine: if not engine_name or engine_name.lower() == "none": engine_name = "core" for name, load_engine_cls in _iter_engine_class_loaders_with_name(): if name == engine_name: try: engine_cls = load_engine_cls() except Exception as e: _logger.warning( f"Unable to properly load '{name}' engine. Error is {e}" ) continue else: return engine_cls() raise RuntimeError(f"No engine found for graph execution: '{engine_name}'") def get_serialization_engine( graph: Any, representation: Optional[str] = None ) -> Tuple[WorkflowEngine, str]: core_representation = representation if representation: for ( representations, load_engine_cls, ) in _iter_engine_class_loaders_with_representation(): if representation in representations: engine_cls = load_engine_cls() engine = engine_cls() return engine, representation else: for name, load_engine_cls in _iter_engine_class_loaders_with_name(): try: engine_cls = load_engine_cls() except Exception as e: _logger.warning( f"Unable to properly load serialization engine '{name}'. Error is {e}" ) continue if not issubclass(engine_cls, WorkflowEngineWithSerialization): continue engine = engine_cls() representation = engine.get_graph_representation(graph) if representation: return engine, representation return get_execution_engine("core"), core_representation def _iter_engine_class_loaders_with_name() -> ( Generator[Tuple[str, Callable[[], None]], None, None] ): try: eps = entry_points(group="ewoks.engines") except Exception: return eps = sorted(eps, key=_sort_ewoks_engines) for ep in eps: yield ep.name, ep.load def _iter_engine_class_loaders_with_representation() -> ( Generator[Tuple[str, Callable[[], None]], None, None] ): try: eps = entry_points(group="ewoks.engines.serialization.representations") except Exception: return eps = sorted(eps, key=_sort_ewoks_engines) for ep in eps: yield ep.name, ep.load def _sort_ewoks_engines(item: EntryPoint): return (item.name != "core", item) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/_requirements/000077500000000000000000000000001512474103500253025ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/_requirements/__init__.py000066400000000000000000000000351512474103500274110ustar00rootroot00000000000000"""Workflow requirements.""" ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/_requirements/pip/000077500000000000000000000000001512474103500260725ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/_requirements/pip/__init__.py000066400000000000000000000000561512474103500302040ustar00rootroot00000000000000"""Workflow requirements managed by `pip`.""" ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/_requirements/pip/extract.py000066400000000000000000000035261512474103500301240ustar00rootroot00000000000000import logging import subprocess import sys from typing import List from ewokscore.graph import TaskGraph logger = logging.getLogger(__file__) def extract_pip_requirements(graph: TaskGraph) -> List[str]: imports: set[str] = set() for node_id, node in graph.graph.nodes.items(): task_identifier = node["task_identifier"] task_type = node["task_type"] if task_type in ("class", "method", "ppfmethod", "ppfport"): package = task_identifier.split(".")[0] if package in ("__main__", ""): logger.warning( f"Could not extract requirements for node {node_id}: the task identifier is a relative import or an import from __main__." ) continue imports.add(package) elif task_type == "notebook": logger.warning( f"Requirement extraction may be incomplete for node {node_id}: {task_type} is only partially supported." ) imports.add("ewokscore[notebook]") elif task_type == "script": logger.warning( f"Requirement extraction cannot be done for scripts (node {node_id})." ) else: logger.warning( f"Could not extract requirements for node {node_id}: unsupported task type {task_type}." ) return list(imports) def add_current_env_pip_requirements(graph: TaskGraph) -> TaskGraph: try: freeze_output = subprocess.check_output( [sys.executable, "-m", "pip", "freeze"], text=True ) except subprocess.CalledProcessError as ex: logger.warning("Cannot generate list of requirements with 'pip' (%s).", ex) return graph requirements = freeze_output.strip().split("\n") graph.graph.graph["requirements"] = requirements return graph ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/_requirements/pip/install.py000066400000000000000000000007721512474103500301200ustar00rootroot00000000000000import logging import subprocess from typing import Sequence from .sanitize import sanitize_requirements logger = logging.getLogger(__name__) def pip_install(requirements: Sequence[str], python_path: str) -> int: requirements, warnings = sanitize_requirements(requirements) for warning in warnings: logger.warning(warning) # https://pip.pypa.io/en/stable/user_guide/#using-pip-from-your-program return subprocess.check_call([python_path, "-m", "pip", "install", *requirements]) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/_requirements/pip/sanitize.py000066400000000000000000000113161512474103500302740ustar00rootroot00000000000000import os import re from typing import List from typing import Sequence from typing import Tuple from urllib.parse import ParseResult from urllib.parse import parse_qs from urllib.parse import urlparse from urllib.parse import urlunparse from packaging.requirements import InvalidRequirement from packaging.requirements import Requirement def sanitize_requirements(requirements: Sequence[str]) -> Tuple[List[str], List[str]]: """Sanitize a list of requirements coming from 'pip freeze'. Returns a sanitized with warnings regarding applied changes. """ sanitized = [] warnings = [] previous_comment = "" for requirement in requirements: requirement = requirement.strip() if not requirement: continue if requirement.startswith("#"): previous_comment = requirement continue editable = requirement.startswith("-e ") if editable: requirement = requirement[2:].strip() if editable and _is_path(requirement): requirement, warning = _handle_editable_path(requirement, previous_comment) if warning: warnings.append(warning) if _is_path(requirement): sanitized.append(f"-e {requirement}") continue requirement, warning = _normalize_vcs_url(requirement) if warning: warnings.append(warning) requirement, warning = _normalize_requirement(requirement) if warning: warnings.append(warning) sanitized.append(requirement) previous_comment = "" return sanitized, warnings def _is_path(requirement: str) -> bool: """Return True if requirement looks like a local path (not a URL).""" return "://" not in requirement and ("/" in requirement or "\\" in requirement) def _normalize_requirement(requirement: str) -> Tuple[str, str]: """Normalize the requirement or pass-through with warning when not valid.""" try: req = Requirement(requirement) except InvalidRequirement: warning = f"Possibly invalid requirement format: {requirement!r}" return requirement, warning replacement = _format_requirement(req) if requirement.replace(" ", "") != replacement.replace(" ", ""): warning = f"Normalize requirement {requirement!r} to {replacement!r}" return replacement, warning return requirement, "" def _format_requirement(req: Requirement) -> str: """Convert requirement to a string and replace ssh with https""" if req.url and req.url.startswith("git+ssh://"): https_url = re.sub(r"^git\+ssh://git@", "git+https://", req.url) return f"{req.name} @ {https_url}" return str(req) def _normalize_vcs_url(requirement: str) -> Tuple[str, str]: """Normalize VCS URLs to the PEP 508 spec (name @ url).""" parsed = urlparse(requirement) if not parsed.fragment or "egg=" not in parsed.fragment: return requirement, "" qs = parse_qs(parsed.fragment) egg_names = qs.get("egg") if not egg_names: return requirement, "" egg_name = egg_names[0] base_url = _remove_url_fragment(parsed) new_requirement = f"{egg_name} @ {base_url}" warning = f"Normalize VCS requirement '{requirement}' to '{new_requirement}'" return new_requirement, warning def _remove_url_fragment(parsed: ParseResult) -> str: return urlunparse( ParseResult( scheme=parsed.scheme, netloc=parsed.netloc, path=parsed.path, params=parsed.params, query=parsed.query, fragment="", ) ) def _handle_editable_path(requirement: str, comment: str) -> Tuple[str, str]: """Replace editable path with comment substitution if available.""" replacement = _requirement_from_comment(comment) if replacement: warning = f"Replaced editable install '{requirement}' with '{replacement}'." return replacement, warning if os.path.exists(requirement): warning = f"Editable path exists locally: '{requirement}'" else: warning = f"Editable path does not exist locally: '{requirement}'" return requirement, warning _REQUIREMENT_COMMENT_RE = re.compile(r"\(([\w\.\-\[\]]+[=> str: """Extract requirement from a 'pip freeze' comment.""" # When doing "pip freeze" in the same envrinment where "git status" gives this # fatal: detected dubious ownership in repository at '/path/to/repo' # the requirements list will contain "-e /path/to/repo" with a warning that # contains a requirement message. match = _REQUIREMENT_COMMENT_RE.search(comment) if match: return match.group(1) return "" ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/bindings.py000066400000000000000000000211451512474103500245720ustar00rootroot00000000000000import datetime import logging import os import sys from contextlib import contextmanager from pathlib import Path from typing import Any from typing import Dict from typing import Generator from typing import List from typing import Optional from typing import Union from ewokscore.events.contexts import RawExecInfoType from ewokscore.events.contexts import job_context from ewokscore.graph import TaskGraph from ewokscore.graph.inputs import graph_inputs_as_table from tabulate import tabulate from . import _engines from . import graph_cache from ._requirements.pip.extract import add_current_env_pip_requirements from ._requirements.pip.extract import extract_pip_requirements from ._requirements.pip.install import pip_install from .errors import AbortException try: from ewoksjob.bindings import submit_graph as _submit_graph from ewoksjob.client.futures import FutureInterface except ImportError: _submit_graph = None FutureInterface = Any try: from pyicat_plus.client import defaults as icat_defaults from pyicat_plus.client.main import IcatClient except ImportError: IcatClient = None icat_defaults = None __all__ = ["execute_graph", "load_graph", "save_graph", "convert_graph", "submit_graph"] logger = logging.getLogger(__name__) def execute_graph( graph, engine: Optional[str] = None, inputs: Optional[List[dict]] = None, load_options: Optional[dict] = None, varinfo: Optional[dict] = None, execinfo: RawExecInfoType = None, task_options: Optional[dict] = None, outputs: Optional[List[dict]] = None, merge_outputs: Optional[bool] = True, environment: Optional[dict] = None, convert_destination: Optional[Any] = None, save_options: Optional[dict] = None, upload_parameters: Optional[dict] = None, **execute_options, ) -> Optional[dict]: with job_context(execinfo, engine=engine) as execinfo: with _upload_context(upload_parameters): if environment: environment = {k: str(v) for k, v in environment.items()} os.environ.update(environment) # Load the graph if load_options is None: load_options = dict() graph = load_graph(graph, inputs=inputs, **load_options) # Save the graph (with inputs) if convert_destination is not None: convert_graph(graph, convert_destination, save_options=save_options) # Execute the graph engine_api = _engines.get_execution_engine(engine) result = engine_api.execute_graph( graph, varinfo=varinfo, execinfo=execinfo, task_options=task_options, outputs=outputs, merge_outputs=merge_outputs, **execute_options, ) return result @contextmanager def _upload_context(upload_parameters: Optional[dict]) -> Generator[None, None, None]: if upload_parameters is None: yield return if IcatClient is None: raise RuntimeError("requires the 'pyicat-plus' package") metadata = upload_parameters.setdefault("metadata", {}) if "startDate" not in metadata: metadata["startDate"] = datetime.datetime.now().astimezone() yield # Only upload when no exception is raised. if "endDate" not in metadata: metadata["endDate"] = datetime.datetime.now().astimezone() metadata_urls = upload_parameters.pop( "metadata_urls", icat_defaults.METADATA_BROKERS ) client = IcatClient(metadata_urls=metadata_urls) logger.info( "Upload processed dataset '%s' metadata to ICAT: %s", upload_parameters.get("dataset"), upload_parameters.get("path"), ) client.store_processed_data(**upload_parameters) def submit_graph( graph, _celery_options: Optional[dict] = None, resolve_graph_remotely: Optional[bool] = None, load_options: Optional[dict] = None, **options, ) -> FutureInterface: """Submit a workflow to be executed remotely. The workflow is resolved on the client-side by default (e.g. load from a file) but can optionally be resolved remotely. """ if _submit_graph is None: raise RuntimeError("requires the 'ewoksjob' package") return _submit_graph( graph, _convert_graph=_load_graph, _celery_options=_celery_options, resolve_graph_remotely=resolve_graph_remotely, load_options=load_options, **options, ) def _load_graph(graph, load_options: Optional[dict] = None) -> dict: return convert_graph( graph, None, load_options=load_options, save_requirements=False ) @graph_cache.cache def load_graph( graph: Any, inputs: Optional[List[dict]] = None, representation: Optional[str] = None, root_dir: Optional[Union[str, Path]] = None, root_module: Optional[str] = None, **load_options, ) -> TaskGraph: """When load option `graph_cache_max_size > 0` is provided, the graph will cached in memory. When the graph comes from external storage (for example a file) any changes to the external graph will require flushing the cache with `graph_cache_max_size = 0`. """ engine_api, representation = _engines.get_serialization_engine( graph, representation=representation ) return engine_api.deserialize_graph( graph, inputs=inputs, representation=representation, root_dir=root_dir, root_module=root_module, **load_options, ) def save_graph( graph: TaskGraph, destination, representation: Optional[str] = None, **save_options, ) -> Union[str, dict]: engine_api, representation = _engines.get_serialization_engine( destination, representation=representation ) return engine_api.serialize_graph( graph, destination, representation=representation, **save_options ) def convert_graph( source, destination, inputs: Optional[List[dict]] = None, load_options: Optional[dict] = None, save_options: Optional[dict] = None, save_requirements: bool = True, ) -> Union[str, dict]: if load_options is None: load_options = dict() if save_options is None: save_options = dict() graph = load_graph(source, inputs=inputs, **load_options) if save_requirements: graph = add_current_env_pip_requirements(graph) return save_graph(graph, destination, **save_options) def show_graph( source, inputs: Optional[List[dict]] = None, load_options: Optional[dict] = None, original_source: Optional[str] = None, column_widths: Optional[Dict[str, Optional[int]]] = None, ) -> Union[str, dict]: if load_options is None: load_options = dict() graph = load_graph(source, inputs=inputs, **load_options) _print_graph(graph, column_widths=column_widths, original_source=original_source) def _print_graph( graph: TaskGraph, column_widths: Optional[Dict[str, Optional[int]]] = None, original_source: Optional[str] = None, ) -> None: column_names, rows, metadata, footnotes = graph_inputs_as_table( graph, column_widths=column_widths ) print() if original_source: print(f"Workflow: {original_source}") else: print("Workflow:") for key, value in metadata.items(): label = key.replace("_", " ").capitalize() print(f"{label}: {value}") if rows: print(tabulate(rows, headers=column_names, tablefmt="fancy_grid")) else: print("No workflow inputs parameters detected!") for footnote in footnotes: print(footnote) def install_graph( source, skip_prompt: bool = False, python_path: Optional[str] = None, load_options: Optional[dict] = None, ): if load_options is None: load_options = dict() graph = load_graph(source, **load_options) requirements = graph.requirements if requirements is None: logger.warning( "Requirements field is empty. Trying to extract requirements automatically..." ) requirements = extract_pip_requirements(graph) logger.info(f"Extracted the following requirements: {requirements}") if python_path is None: python_path = sys.executable if skip_prompt: pip_install(requirements, python_path) return requirements_as_str = "\n".join(requirements) answer = input( f"{requirements_as_str}\nThis will install the above packages via {python_path} -m pip install. Do you want to proceed (y/N)?" ) if answer.lower() == "y" or answer.lower() == "yes": pip_install(requirements, python_path) else: raise AbortException() ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/cli_utils/000077500000000000000000000000001512474103500244075ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/cli_utils/__init__.py000066400000000000000000000000001512474103500265060ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/cli_utils/cli_convert_utils.py000066400000000000000000000062161512474103500305150ustar00rootroot00000000000000from argparse import Namespace from typing import List from ewoksutils.cli_utils import cli_arguments from ewoksutils.cli_utils import cli_log_utils from ewoksutils.cli_utils import cli_parse from ewoksutils.cli_utils.cli_spec import CLIArg from .._engines import get_graph_representations from .cli_parse import parse_destinations def convert_arguments( shell: bool = False, default_log_level: str = "warning" ) -> List[CLIArg]: if shell: args_list = cli_log_utils.log_arguments(default_log_level=default_log_level) else: args_list = [] args_list += cli_arguments.workflow_arguments("convert") args_list += cli_arguments.ewoks_inputs_arguments() args_list += [ CLIArg( "destination", [], type=str, help="Destination of the conversion (e.g., JSON filename).", ), CLIArg( "source_representation", ["--src-format"], type=str.lower, choices=get_graph_representations(), help="Source format.", ), CLIArg( "destination_representation", ["--dst-format"], type=str.lower, choices=get_graph_representations(), help="Destination format.", ), CLIArg( "load_options", ["-o", "--load-option"], action="append", metavar="OPTION=VALUE", help="Load options.", ), CLIArg( "save_options", ["-s", "--save-option"], action="append", metavar="OPTION=VALUE", help="Save options.", ), CLIArg( "exclude_requirements", ["--exclude-requirements"], action="store_true", help="Do not include the packages of the current Python environment as requirements in the destination workflow.", ), ] return args_list def parse_convert_arguments(cli_args: Namespace, shell: bool = False) -> None: if shell: cli_log_utils.parse_log_arguments(cli_args) cli_args.workflows, cli_args.graphs = cli_parse.parse_workflows(cli_args) cli_args.destinations = parse_destinations(cli_args) load_options = dict(cli_parse.parse_option(item) for item in cli_args.load_options) if cli_args.source_representation: load_options["representation"] = cli_args.source_representation if cli_args.test: load_options["representation"] = "test_core" if cli_args.root_module: load_options["root_module"] = cli_args.root_module if cli_args.root_dir: load_options["root_dir"] = cli_args.root_dir save_options = dict(cli_parse.parse_option(item) for item in cli_args.save_options) if cli_args.destination_representation: save_options["representation"] = cli_args.destination_representation convert_options = { "save_options": save_options, "load_options": load_options, "inputs": cli_parse.parse_ewoks_inputs_parameters(cli_args), } if cli_args.exclude_requirements: convert_options["save_requirements"] = False cli_args.convert_options = convert_options ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/cli_utils/cli_install_utils.py000066400000000000000000000023601512474103500304770ustar00rootroot00000000000000import logging from argparse import Namespace from typing import List from ewoksutils.cli_utils import cli_arguments from ewoksutils.cli_utils import cli_log_utils from ewoksutils.cli_utils import cli_parse from ewoksutils.cli_utils.cli_spec import CLIArg logger = logging.getLogger(__name__) def install_arguments( shell: bool = False, default_log_level: str = "info" ) -> List[CLIArg]: if shell: args_list = cli_log_utils.log_arguments(default_log_level=default_log_level) else: args_list = [] args_list += cli_arguments.workflow_arguments("install") args_list += [ CLIArg( "yes", ["--yes"], action="store_true", help="Automatically accept installation prompts.", ), CLIArg( "python", ["-p", "--python"], type=str, help="Python interpreter of the environment where the packages should be installed. Default: current environment Python.", ), ] return args_list def parse_install_arguments(cli_args: Namespace, shell: bool = False) -> None: if shell: cli_log_utils.parse_log_arguments(cli_args) cli_args.workflows, cli_args.graphs = cli_parse.parse_workflows(cli_args) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/cli_utils/cli_parse.py000066400000000000000000000014521512474103500267240ustar00rootroot00000000000000import os from typing import List def parse_destinations(args) -> List[str]: dest_dirname = os.path.dirname(args.destination) basename = os.path.basename(args.destination) dest_basename, dest_ext = os.path.splitext(basename) if not dest_ext: dest_ext = dest_basename dest_basename = "" if not dest_ext.startswith("."): dest_ext = f".{dest_ext}" if len(args.workflows) == 1 and dest_basename: return [os.path.join(dest_dirname, f"{dest_basename}{dest_ext}")] destinations = list() for workflow in args.workflows: basename, _ = os.path.splitext(os.path.basename(workflow)) destination = os.path.join(dest_dirname, f"{basename}{dest_basename}{dest_ext}") destinations.append(destination) return destinations ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/cli_utils/cli_show_utils.py000066400000000000000000000036031512474103500300120ustar00rootroot00000000000000from argparse import Namespace from typing import List from ewoksutils.cli_utils import cli_arguments from ewoksutils.cli_utils import cli_log_utils from ewoksutils.cli_utils import cli_parse from ewoksutils.cli_utils.cli_spec import CLIArg from .._engines import get_graph_representations def show_arguments( shell: bool = False, default_log_level: str = "warning" ) -> List[CLIArg]: if shell: args_list = cli_log_utils.log_arguments(default_log_level=default_log_level) else: args_list = [] args_list += cli_arguments.workflow_arguments("show") args_list += cli_arguments.ewoks_inputs_arguments() args_list += [ CLIArg( "source_representation", ["--src-format"], type=str.lower, choices=get_graph_representations(), help="Source format.", ), CLIArg( "load_options", ["-o", "--load-option"], action="append", metavar="OPTION=VALUE", help="Load options.", ), ] return args_list def parse_show_arguments(cli_args: Namespace, shell: bool = False) -> None: if shell: cli_log_utils.parse_log_arguments(cli_args) cli_args.workflows, cli_args.graphs = cli_parse.parse_workflows(cli_args) load_options = dict(cli_parse.parse_option(item) for item in cli_args.load_options) if cli_args.source_representation: load_options["representation"] = cli_args.source_representation if cli_args.root_module: load_options["root_module"] = cli_args.root_module if cli_args.root_dir: load_options["root_dir"] = cli_args.root_dir if cli_args.test: load_options["representation"] = "test_core" show_options = { "load_options": load_options, "inputs": cli_parse.parse_ewoks_inputs_parameters(cli_args), } cli_args.show_options = show_options ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/errors.py000066400000000000000000000000521512474103500243030ustar00rootroot00000000000000class AbortException(Exception): pass ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/graph_cache.py000066400000000000000000000022221512474103500252140ustar00rootroot00000000000000from collections import OrderedDict from functools import wraps from typing import Dict from typing import Optional from ewokscore.graph import TaskGraph from ewokscore.hashing import uhash _GRAPH_CACHE: Dict[int, TaskGraph] = OrderedDict() _GRAPH_CACHE_MAX_SIZE: int = 0 def cache(load_method): @wraps(wraps) def wrapper(*args, graph_cache_max_size: Optional[int] = None, **kw): set_cache_max_size(graph_cache_max_size) if _GRAPH_CACHE_MAX_SIZE <= 0: return load_method(*args, **kw) graph_id = uhash((args, kw)) graph = _GRAPH_CACHE.pop(graph_id, None) if graph is None: graph = load_method(*args, **kw) _GRAPH_CACHE[graph_id] = graph _check_cache_size() return graph return wrapper def set_cache_max_size(graph_cache_max_size: Optional[int] = None) -> None: global _GRAPH_CACHE_MAX_SIZE if graph_cache_max_size is not None: _GRAPH_CACHE_MAX_SIZE = graph_cache_max_size _check_cache_size() def _check_cache_size() -> None: while _GRAPH_CACHE and len(_GRAPH_CACHE) > _GRAPH_CACHE_MAX_SIZE: _GRAPH_CACHE.popitem(last=False) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/000077500000000000000000000000001512474103500235625ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/__init__.py000066400000000000000000000000001512474103500256610ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/conftest.py000066400000000000000000000011601512474103500257570ustar00rootroot00000000000000from unittest.mock import MagicMock import pytest @pytest.fixture def mock_icat_client(monkeypatch): mock_defaults = MagicMock() mock_defaults.METADATA_BROKERS = ["mock://broker"] # Create a mock for IcatClient mock_client = MagicMock() mock_client_instance = mock_client.return_value mock_client_instance.store_processed_data.return_value = None # Patch the imports in your module (replace 'your_module' with actual module name) monkeypatch.setattr("ewoks.bindings.icat_defaults", mock_defaults) monkeypatch.setattr("ewoks.bindings.IcatClient", mock_client) return mock_client ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/notebooks/000077500000000000000000000000001512474103500255655ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/notebooks/__init__.py000066400000000000000000000010241512474103500276730ustar00rootroot00000000000000import sys from contextlib import contextmanager from pathlib import Path from typing import Generator if sys.version_info < (3, 9): import importlib_resources else: import importlib.resources as importlib_resources @contextmanager def notebook_path(*args) -> Generator[Path, None, None]: source = importlib_resources.files(__name__).joinpath(*args) with importlib_resources.as_file(source) as path: if not path.is_file(): raise FileNotFoundError(f"Not a file: '{source}'") yield path ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/notebooks/benchmark.ipynb000066400000000000000000007260671512474103500306040ustar00rootroot00000000000000{ "cells": [ { "cell_type": "markdown", "id": "090e06c3-02d4-48f7-9442-e81db4ae06bc", "metadata": {}, "source": [ "# Benchmark workflow execution\n", "\n", "This notebook checks the overhead added to the actual computations by ewoks." ] }, { "cell_type": "code", "execution_count": 1, "id": "75f296a5-0dbd-4313-9c15-bb9e31f10acd", "metadata": {}, "outputs": [], "source": [ "import time\n", "import matplotlib.pyplot as plt\n", "from ewoksutils.import_utils import qualname\n", "from ewoks import execute_graph\n", "from ewokscore.tests.examples.tasks.addfunc import addfunc" ] }, { "cell_type": "markdown", "id": "92f9a606-7cbf-45b8-b9f8-0a1aa182e0a8", "metadata": {}, "source": [ "Exclude importing from the benchmark" ] }, { "cell_type": "code", "execution_count": 2, "id": "d008ea63-82c4-4802-9d6a-c6320b83f706", "metadata": {}, "outputs": [], "source": [ "import ewoksppf # noqa F401\n", "import ewoksdask # noqa F401" ] }, { "cell_type": "markdown", "id": "c69d9db9-6056-4492-be02-1f32784d92e9", "metadata": {}, "source": [ "Define a workflow for benchmarking" ] }, { "cell_type": "code", "execution_count": 3, "id": "adfb071b-7f84-4822-86dc-126c6a27af0b", "metadata": {}, "outputs": [], "source": [ "def generate_graph(nbranches=1, nodes_per_branch=10):\n", " task_identifier = qualname(addfunc)\n", " nodes = []\n", " links = []\n", " for ibranch in range(nbranches):\n", " node_id1 = None\n", " for inode in range(nodes_per_branch):\n", " node_id2 = f\"{ibranch}-{inode}\"\n", " nodes.append(\n", " {\n", " \"id\": node_id2,\n", " \"task_type\": \"method\",\n", " \"task_identifier\": task_identifier,\n", " \"default_inputs\": [{\"name\": \"arg\", \"value\": 0}],\n", " }\n", " )\n", " if node_id1:\n", " links.append(\n", " {\n", " \"source\": node_id1,\n", " \"target\": node_id2,\n", " \"data_mapping\": [\n", " {\"source_output\": \"return_value\", \"target_input\": \"arg\"}\n", " ],\n", " }\n", " )\n", " node_id1 = node_id2\n", " return {\"graph\": {\"id\": \"test\"}, \"nodes\": nodes, \"links\": links}" ] }, { "cell_type": "markdown", "id": "854582a9-3c7b-445d-9875-176922853d48", "metadata": {}, "source": [ "Pure python equivalent of the workflow" ] }, { "cell_type": "code", "execution_count": 4, "id": "0a144804-e8af-4439-ab19-cc53108d2999", "metadata": {}, "outputs": [], "source": [ "def prefunc_raw(**kw):\n", " return kw\n", "\n", "\n", "def timefunc_raw(kw, **_):\n", " result = dict()\n", " for ibranch in range(kw[\"nbranches\"]):\n", " arg = 0\n", " for inode in range(kw[\"nodes_per_branch\"]):\n", " arg = addfunc(arg)\n", " name = f\"{ibranch}-{inode}\"\n", " result[name] = arg\n", " return result" ] }, { "cell_type": "markdown", "id": "efa80a05-b2fa-4d0a-b035-91d346a4b5e9", "metadata": {}, "source": [ "Benchmark with varying number of nodes and branches" ] }, { "cell_type": "code", "execution_count": 5, "id": "d2f19a58-ad55-4696-9ac1-f9f8802c5d9c", "metadata": {}, "outputs": [], "source": [ "def bench(prefunc, timefunc, title, nrepeats=3, nnodesmax=200, **timefuncopts):\n", " plt.title(title)\n", " for i in range(0, 7, 2):\n", " nbranches = max(i, 1)\n", " x = []\n", " y = []\n", " nnodespbmax = nnodesmax // nbranches\n", " for j in range(0, nnodespbmax, max(nnodespbmax // 10, 1)):\n", " n = dt = 0\n", " for k in range(nrepeats):\n", " nodes_per_branch = max(j, 1)\n", " graph = prefunc(nbranches=nbranches, nodes_per_branch=nodes_per_branch)\n", " t0 = time.perf_counter_ns()\n", " timefunc(graph, **timefuncopts)\n", " t1 = time.perf_counter_ns()\n", " nk = nbranches * nodes_per_branch\n", " n += nk\n", " dt += (t1 - t0) * 1e-6 / nk\n", " x.append(n / nrepeats)\n", " y.append(dt / nrepeats)\n", " x, y = list(zip(*sorted(zip(x, y))))\n", "\n", " plt.plot(x, y, label=f\"{nbranches} branches\")\n", " plt.xlabel(\"# nodes\")\n", " plt.ylabel(\"Time/# nodes (msec)\")\n", " plt.legend()\n", " plt.gca().set_prop_cycle(None)" ] }, { "cell_type": "code", "execution_count": 6, "id": "3e7b8d52-0717-4818-939d-9e6ecd39c30e", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "

" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bench(prefunc_raw, timefunc_raw, \"python\")" ] }, { "cell_type": "code", "execution_count": 7, "id": "e4bac3a3-e60c-4753-88bb-630d139dd237", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bench(generate_graph, execute_graph, \"ewoks: sequential\")" ] }, { "cell_type": "code", "execution_count": 8, "id": "557ba7eb-2a3b-4bd3-a0c5-ae419e28ff17", "metadata": {}, "outputs": [ { "data": { "image/png": "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YsUKkpKSGDduXFW+nzVr1rBhwwbCwsIoLy/n448/pk2bNmRlZTFixAimTp0KwM6dO5k3bx6vv/46l19+OR999BEzZsxg+vTp3H///Vx88cUUFxdTUVHBvn37akxbPXz4cO644w4WLFhAZGQk8+fP56GHHmL27Nk8+eSTJCcn4+vra9JQG5oMa/bm8If315OcdZiZoxO4d1IP/LxNioiGok5DICKfA+nAAuAJ4CDgh9WbHwcsEJHnVPXTU3h2KpCtqoeBwyKyBBgAnGAImjrl5eWsWbOGf//73wwfPpy77rqLJ598kscee+yEupdffjkeHh5069aNzp07s22bZbQmTpxIWJg19V1VefDBB1myZAkeHh6kpaVx4MABABISEhg4cCAAQ4YMISUlhYKCAtLS0rj44osBjslWWlPa6tDQUDZt2sTEiRMBa4nN6OhoAPr378/06dO56KKLuOiiixq+sQyGk6C0vIJ/f7eTl77fRXSIP+/eNJxRXSLcLVaLo743gqtVNeu4skJgjb09KyKn+qssAF4UES/ABxgO/PMU71VFXT13VxEbG0tsbCzDhw8H4NJLL+XJJ5+ssa4zaajfeecdMjMzWb16Nd7e3sTHx1NcXAycmFa60jVUG7Wloe7Tp0+NA9qLFi1iyZIlfPbZZzzxxBNs3LjRjFkY3MKOAwXc8/46NqXlc+mQWB65oDdt/LzdLVaLpE7nWqUREJEEEanqZoqIf+VAcA2GorLOPGA50ENEUkVkpojcKiK32tdtBb4ANgArgP+q6qYG+E6NTvv27enYsSPbt28H4Ntvv6V379411v3ggw+oqKggKSmJ3bt306NHjxPq5OXlERUVhbe3N99//z179uyp8/nBwcHExsbyySefAFBSUlLnYHWPHj3IzMysMgRlZWVs3ry5yp00btw4nnrqKfLy8qqWsDQYGosdBwr4/fx1nPv8T2TkFvPq1UP4x2UDjBFwIc529T4ARlU7dthlQ2u7QFWn1XdTVX0GeMZJGZo0//73v5k+fTqlpaV07tyZN954o8Z6cXFxDBs2jPz8fF555ZVj3DiVTJ8+nQsuuIB+/fqRmJhIz549633+3LlzueWWW3jkkUfw9vbmgw8+qLWuj48PH374IXfeeSd5eXmUl5dz99130717d2bMmEFeXh6qyp133lnroLfB0NCs25fLy9/v4qstB/D3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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bench(generate_graph, execute_graph, \"ewoks: dask - sequential\", engine=\"dask\")" ] }, { "cell_type": "code", "execution_count": 9, "id": "aff976e9-7a8c-41ed-ab34-ec45c750555f", "metadata": {}, "outputs": [ { "data": { "image/png": "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vn07q1ev5tZbb2X37t0A7N27lzVr1uDv709paSnff/89fn5+pKamcv3119e4lOoKKz18+HCuvfZaFi1axLBhwygsLMTf3x+A7du3s23bNnx9fYmLi+O+++7D39+fJ598kuXLlxMYGMizzz7L888/zz333MPnn39OcnIyIqLDUGvqxOFCICJBwKfAg0qpOn0wIjIBQwguruu4UuoNTLfR0KFDm7XpnhB9auaQFgJNNV9//TXt27dnyJAhrFq1qsGy119/PQBjx46lsLCwprKdOXNmTeVdVVXFvffey/bt2/H09GTfvn0159cVVjokJITo6GiGDRsGcFoI7EmTJhESEgJAnz59OHz4MPn5+ezdu5fRo0cDUFlZyahRowgJCcHPz4/bbruNyy+/XKe51NSJQ4VARLwxROADpdRn9ZQZALwFTFNKnXSkPXXRs30QHmIkqZneP7qlb69pAo213B3B2rVrWbx4Md9++y3l5eUUFhZyww038P77759VtilhqF944QU6dOjAjh07sNvtpwWmqyusdEPUF4b60ksvZeHChWeV37hxIytWrOCTTz7hlVde4Ycffmjk02vcDUfOGhJgHpCklHq+njJdgM+AG5VS++oq42j8vD3pHhmk01ZqTuPpp58mPT2dtLQ0PvroIyZOnFinCAAsWrQIgDVr1hASElLTWq9NQUEB0dHReHh4sGDBAmw2W4P3j4uLIzMzk02bNgFQVFTUoECMHDmStWvX1mRHKykpYd++fRQXF1NQUMD06dN54YUX2LFjR5M+v8a9cGSPYDRwI7BLRLab+x4DugAopV4H/gJEAP81W1HW+qLjOZL4KAs70vNb+raaNoKfnx+DBg2iqqqKt99+u84yd999N1deeSXvvfceU6dOPa23UBc+Pj4sWrSI++67j7KyMvz9/Vm+fHm95SMjI5k/fz7XX389FRUVADz55JNYLBZmzZpFeXk5Simef77ONpnGzXHbMNS1eXXlfv71XQq7npiMxc+7Wa+tOT90aOSWQz9r90CHoW6E6mT2+7K1e0ij0bgfWgiAeHPmUJJeYazRaNwQLQRAxxA/LH5eeoWxRqNxS7QQYEz3S4gK1jGHNBqNW6KFwMSIOVREaxs812g0mgtFC4FJfFQwxRVW0vPKnG2KRqPRtChaCExO5SbQ7iGNQX5+fk0wuISEBNavX39WmZtvvplP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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bench(\n", " generate_graph,\n", " execute_graph,\n", " \"ewoks: dask - multithreading\",\n", " engine=\"dask\",\n", " scheduler=\"multithreading\",\n", ")" ] }, { "cell_type": "code", "execution_count": 10, "id": "40fb0fdf-d166-495c-9f9b-e24d7afa167c", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bench(\n", " generate_graph,\n", " execute_graph,\n", " \"ewoks: dask - multiprocessing (spawn)\",\n", " engine=\"dask\",\n", " scheduler=\"multiprocessing\",\n", " scheduler_options={\"context\": \"spawn\"},\n", ")" ] }, { "cell_type": "code", "execution_count": 11, "id": "494c1759-d9a0-4b1f-942e-a271ec4816e0", "metadata": {}, "outputs": [ { "data": { "image/png": "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+++/n1Ao1OXnT5o0icrKSt59910A6urquqwQ5s6dyxtvvNH69K89e/bw0UcfUV9fT01NDaeccgq//e1vee+99+L6+buSkmf84wqG4PMIayprmX9ocbLDMcYkWUZGBtOnTycQCHDPPffELPPNb36ThQsXct9993HyySe3uxqIJS0tjYcffphLL72UxsZGMjMzeeGFFzotX1BQwL333su5555Lc7PzPaPrrruOnJwcTj/9dJqamlBVfvOb3+z7D+pKqWGZo51882sU52dyzwWH9ep+jTEOG5a5b9mwzHEoLcyxoRuMMSkpdRN/US5ba5qobmhJdijGGNOnUjfxRx6+bjd4jTEpJmUTf+tDWay5xxiTYlI28RfkpDM0O83O+I0xKSdlE7+IUFqYY335jTEpJ2UTPzhDNH+0rY5QuP93aTXG9Fx1dXXr4GllZWX85z//2avMBRdcwKOPPtpnMb3yyiu9MuzC/kjJL3BFlBbl0BgI8fGuPYwtGJLscIwxvezyyy/n5JNP5tFHH6WlpYWGhoZ92k8wGMTnGzzpMqXP+MvsoSzGDFo1NTW89tprXHjhhYDzTdr8/PyYZV944QVmzZrFxIkTefrppwHngSnz589n3rx5HHfccdTX13PccccxY8YMpk6dyhNPPAHApk2bKCsr46KLLmLKlCmceOKJNDY2ArBu3TqOP/54Dj30UGbMmMH69esBqK+vjzmM85IlSzjmmGOYOXMmJ510EpWVlQDceuutrcMyn3POOft9bLqtwkTkcOA84CigCGgEVgDPAH9W1Zr9jiJJJowcgkecnj2nTC1KdjjGDFrbbriB5tW9OyxzelkphT/4QafrN27cSEFBAV/5yld47733mDlzJrfcckvMoRY2bdrEO++8w/r16zn22GNbx8tZunQp77//PkOHDiUYDPL444+Tm5vLzp07mTt3LvPnzwdg7dq1PPjgg9x1112cffbZPPbYY5x33nksWrSIq6++mgULFtDU1EQ4HGbz5s0xh3GeM2cOl156KU888QQFBQU8/PDDXHPNNdxzzz3ceOONbNy4kfT09F4ZlrnLM34ReRb4GvAv4GScxD8Z+CGQATwhIvP3O4okyfB7GVswxG7wGjMIBYNBli5dyje+8Q2WLVtGdnY2N954Y8yyZ599Nh6PhwkTJjB27FjWrHEqqRNOOIGhQ4cCoKr84Ac/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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bench(\n", " generate_graph,\n", " execute_graph,\n", " \"ewoks: dask - multiprocessing (fork)\",\n", " engine=\"dask\",\n", " scheduler=\"multiprocessing\",\n", " scheduler_options={\"context\": \"fork\"},\n", ")" ] }, { "cell_type": "code", "execution_count": 12, "id": "481d39f0-8098-4917-8ceb-ed33d22aef40", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bench(\n", " generate_graph,\n", " execute_graph,\n", " \"ewoks: pypushflow - multiprocessing (fork)\",\n", " engine=\"ppf\",\n", ")" ] }, { "cell_type": "code", "execution_count": 13, "id": "7c1bf6a5-7444-4a5d-b542-5009e9b3acf0", "metadata": {}, "outputs": [ { "data": { "image/png": "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egDPATeravhagpcCT7WQ9SRVnQicBVwnIqdESqSqD6nqJFWdlJub25Z2M6PADXet8Qfa7LyGYXQsFi1axOOPP857773H+PHjGT9+PK+99lrEtObuuw0RkRTgFeBNVX0gLD4Z2AYcq6pbYzjPXUCFqv6ypXSH6u67OXPXFvHtRz/hsSsnc8qIthMfwzAaMXff7UeHcfft9TH8FVgTLg4epwFro4mDiGR5HduISBZwBrAyXrZGY8rwHNKSfTbc1TCMbkk8m5imApcDp4rICu9ztnfsEpo1L4nIQBEJ1ev6AwtF5FNgMfCqqr4RR1sjkpGaxJThOdYPYRhGtySeo5gWAhLl2BUR4rYDZ3v7m4Bx8bLtQJhRkMtdL6+mcHclQ/tltZ7BMAyji2AzqVthunl3NQyjm2IC0QpD+2UxvF8W876wfgjDMLoXJhAxML0gjw83llBdZ8NdDcPoPphAxMD0glxq64N8tKkk0aYYhhEnAoEAEyZMiOpie/r06bTlMPrWePTRR7n++uvb7XqRMIGIgcnDsslISbJFhAyjC/Ob3/zmkOdjmLvvbkh6ShJTj8xh7roi4jmx0DCMxLB161ZeffVVrr766hbTPf7444wfP56jjz6axYsXA3DXXXdx+eWXM3XqVC6//HIKCws5+eSTmThxIhMnTuSDDz4A3AJA06dPj+i++5NPPuHEE09k3LhxTJ48mfLycgC2b9/OrFmzOOqoo/jBD37QYMdbb73FCSecwMSJE/nGN77R4FLjtttua3D3/f3vf/+Q70s8vbl2KaYX5PHOmiI27a7kiNweiTbHMLok9y2+j7Wla9v0nCOzR3Lr5FtbTHPzzTfz85//vKFgjkZVVRUrVqxgwYIFXHnllaxc6ebvrl69moULF5KRkUFVVRVvv/026enprF+/nksvvbShaSqS++7JkyfzzW9+kzlz5nDcccexb98+MjIyAFixYgXLly8nLS2NgoICbrjhBjIyMrj77rt55513yMrK4r777uOBBx7guuuu4/nnn2ft2rWISId3992lmF7gXG3MXVtkAmEYXYhXXnmFvLw8jj32WObNm9di2ksvvRSAU045hX379jUUwuedd15Doe73+7n++utZsWIFSUlJfPHFFw35I7nv7t27NwMGDOC4444DaOJqfObMmfTu3RuA0aNHs3nzZvbu3cvq1auZOnUqAHV1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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bench(\n", " generate_graph,\n", " execute_graph,\n", " \"ewoks: pypushflow - scaling multiprocessing (fork)\",\n", " engine=\"ppf\",\n", " scaling_workers=False,\n", ")" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 } running_workflows.ipynb000066400000000000000000000477721512474103500323670ustar00rootroot00000000000000ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/notebooks{ "cells": [ { "cell_type": "markdown", "id": "68fe18a0", "metadata": {}, "source": [ "# Use different engines\n", "\n", "This notebook demonstrates how to execute a workflow with different engines." ] }, { "cell_type": "code", "execution_count": 1, "id": "9c0eb2c7", "metadata": {}, "outputs": [], "source": [ "import os\n", "import shutil\n", "\n", "from ewoks import execute_graph\n", "from ewokscore.variable import value_from_transfer\n", "from ewokscore.tests.utils.show import show_graph\n", "from ewokscore.tests.examples.graphs import get_graph" ] }, { "cell_type": "markdown", "id": "47adb79c", "metadata": {}, "source": [ "## Select and configure a task scheduler" ] }, { "cell_type": "code", "execution_count": 2, "id": "e0b355d2", "metadata": {}, "outputs": [], "source": [ "scheduler = None # select any of the schedulers shown below\n", "\n", "execute_options = dict()\n", "\n", "if scheduler == \"dask_multithreading\":\n", " # tasks are distributed by a local scheduler over multiple threads\n", " execute_options[\"engine\"] = \"dask\"\n", " execute_options[\"scheduler\"] = \"multithreading\"\n", "elif scheduler == \"dask_multiprocessing\":\n", " # tasks are distributed by a local scheduler over multiple processes\n", " execute_options[\"engine\"] = \"dask\"\n", " execute_options[\"scheduler\"] = \"multiprocessing\"\n", "elif scheduler == \"dask_local_cluster\":\n", " # tasks are distributed by a local scheduler\n", " execute_options[\"engine\"] = \"dask\"\n", " execute_options[\"scheduler\"] = \"cluster\"\n", "elif scheduler == \"dask_remote_cluster\":\n", " # tasks are distributed by a remote scheduler\n", " execute_options[\"engine\"] = \"dask\"\n", " execute_options[\"scheduler\"] = \"127.0.0.1:40331\"\n", "\n", " # There are different ways to start a remote scheduler\n", " #\n", " # Start a dask scheduler on any host:\n", " # >>> from ewoksdask.schedulers import local_scheduler\n", " # >>> scheduler = local_scheduler(n_workers=5)\n", " #\n", " # Start a dask scheduler on a host that can launch slurm jobs:\n", " # >>> from ewoksdask.schedulers import slurm_scheduler\n", " # >>> scheduler = slurm_scheduler(maximum_jobs=5)\n", "\n", "elif scheduler == \"pypushflow\":\n", " # tasks are distributed by a local scheduler over multiple processes\n", " execute_options[\"engine\"] = \"ppf\"\n", "else:\n", " # tasks are executed in a single thread\n", " scheduler = None\n", " pass" ] }, { "cell_type": "markdown", "id": "7bce49c6", "metadata": {}, "source": [ "## Select a task graph" ] }, { "cell_type": "code", "execution_count": 7, "id": "52a3e417", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "taskgraph, expected_results = get_graph(\"acyclic1\")\n", "show_graph(taskgraph, stdout=False, plot=True)" ] }, { "cell_type": "markdown", "id": "af5e69b3", "metadata": {}, "source": [ "## Configure storage of results (if any)" ] }, { "cell_type": "code", "execution_count": 4, "id": "085f154b", "metadata": {}, "outputs": [], "source": [ "def prepare_storage(clean=True):\n", " if not varinfo[\"root_uri\"]:\n", " return # results are not persisted by ewoks\n", " if clean:\n", " shutil.rmtree(varinfo[\"root_uri\"], ignore_errors=True)\n", " os.makedirs(varinfo[\"root_uri\"], exist_ok=True)\n", "\n", "\n", "varinfo = {\"root_uri\": None} # folder where all results will be saved\n", "execute_options[\"varinfo\"] = varinfo\n", "prepare_storage(clean=True)" ] }, { "cell_type": "markdown", "id": "0b3cfedd", "metadata": {}, "source": [ "## Execute the workflow" ] }, { "cell_type": "code", "execution_count": 5, "id": "0e52aac1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Execution options:\n", "{'varinfo': {'root_uri': None}}\n" ] } ], "source": [ "print(\"Execution options:\")\n", "print(execute_options)\n", "results = execute_graph(taskgraph, **execute_options)" ] }, { "cell_type": "markdown", "id": "577fc5a9-c215-458f-afe1-b5b354e90d10", "metadata": {}, "source": [ "## Inspect results" ] }, { "cell_type": "code", "execution_count": 6, "id": "8fb1abbb-9c09-4465-85c5-237b9c8a193c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " result = 16\n" ] } ], "source": [ "for name, result in results.items():\n", " value = value_from_transfer(result, varinfo=varinfo)\n", " print(f\" {name} =\", value)" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 } ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_cli.py000066400000000000000000000041451512474103500257460ustar00rootroot00000000000000from ewoksutils.tests.conftest import cli_interface # noqa F401 from ewoksutils.tests.conftest import graph_directory # noqa F401 from ..cli_utils import cli_convert_utils def test_cli_convert(cli_interface): # noqa F811 argv = [ "acyclic1", "test.json", "--test", "-p", "a=1", "-p", "task1:b=test", "--src-format", "yaml", "--dst-format", "json", ] cli_args = cli_interface( argv, cli_convert_utils.convert_arguments, cli_convert_utils.parse_convert_arguments, ) assert list(cli_args.graphs) == ["acyclic1"] convert_options = { "inputs": [ {"all": False, "name": "a", "value": 1}, {"id": "task1", "name": "b", "value": "test"}, ], "load_options": {"representation": "test_core"}, "save_options": {"representation": "json"}, } assert cli_args.convert_options == convert_options argv = ["acyclic1", "test.json"] cli_args = cli_interface( argv, cli_convert_utils.convert_arguments, cli_convert_utils.parse_convert_arguments, ) assert cli_args.destinations == ["test.json"] argv = ["acyclic1", ".json"] cli_args = cli_interface( argv, cli_convert_utils.convert_arguments, cli_convert_utils.parse_convert_arguments, ) assert cli_args.destinations == ["acyclic1.json"] argv = ["acyclic1", "json"] cli_args = cli_interface( argv, cli_convert_utils.convert_arguments, cli_convert_utils.parse_convert_arguments, ) assert cli_args.destinations == ["acyclic1.json"] def test_cli_convert_search(cli_interface, tmp_path, graph_directory): # noqa F811 argv = [ str(tmp_path / "subdir" / "*.json"), str(tmp_path / "*.json"), "_suffix.json", "--search", ] cli_args = cli_interface( argv, cli_convert_utils.convert_arguments, cli_convert_utils.parse_convert_arguments, ) assert len(cli_args.graphs) == 22 assert cli_args.graphs == graph_directory ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_convert_cli.py000066400000000000000000000063621512474103500275110ustar00rootroot00000000000000import os import sys from xml.etree import ElementTree import pytest from ewokscore import load_graph from ewokscore.graph import TaskGraph from ewokscore.task import Task from ewokscore.tests.examples.graphs import graph_names from ewoksutils.import_utils import import_qualname from orangewidget.widget import OWBaseWidget from ewoks.__main__ import main from ewoks.tests.utils import has_default_input from ewoks.tests.utils import no_widget_registry def _ewokscore_in_graph_requirements(graph: TaskGraph) -> bool: ewokscore_in_req = False for requirement in graph.graph.graph["requirements"]: if "ewokscore" in requirement: ewokscore_in_req = True break return ewokscore_in_req @pytest.mark.parametrize("graph_name", graph_names()) def test_convert_to_json(graph_name, tmpdir): destination = str(tmpdir / f"{graph_name}.json") argv = [ sys.executable, "convert", graph_name, destination, "--test", "-s", "indent=2", ] main(argv=argv, shell=False) assert os.path.exists(destination) graph = load_graph(destination) assert graph.graph.graph["requirements"] is not None assert _ewokscore_in_graph_requirements(graph) def test_convert_with_all_inputs(tmpdir): graph_name = "demo" destination = str(tmpdir / f"{graph_name}.json") argv = [ sys.executable, "convert", graph_name, destination, "--test", "-p", "value=10", "--inputs=all", ] main(argv=argv, shell=False) assert os.path.exists(destination) graph = load_graph(destination) for node in graph.graph.nodes.values(): assert has_default_input(node, "value", 10) def test_convert_with_taskid_inputs(tmpdir): graph_name = "demo" destination = str(tmpdir / f"{graph_name}.json") taskid = "ewokscore.tests.examples.tasks.sumtask.SumTask" argv = [ sys.executable, "convert", graph_name, destination, "--test", "-p", f"{taskid}:value=test", "--input-node-id", "taskid", ] main(argv=argv, shell=False) assert os.path.exists(destination) graph = load_graph(destination) for node in graph.graph.nodes.values(): if node["task_identifier"] == taskid: assert has_default_input(node, "value", "test") @pytest.mark.parametrize("graph_name", graph_names()) def test_convert_to_ows(graph_name, tmpdir): destination = str(tmpdir / f"{graph_name}.ows") argv = [ sys.executable, "convert", graph_name, destination, "--test", ] DAGs = ["acyclic1", "demo", "empty"] if graph_name not in DAGs: with pytest.raises(RuntimeError): main(argv=argv, shell=False) return # Run `convert` with no_widget_registry(): main(argv=argv, shell=False) assert os.path.exists(destination) tree = ElementTree.parse(destination) root = tree.getroot() for node in root.findall("./nodes/node"): try: assert issubclass(import_qualname(node.get("qualified_name")), OWBaseWidget) except ImportError: assert issubclass(import_qualname(node.get("name")), Task) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_engines.py000066400000000000000000000025261512474103500266300ustar00rootroot00000000000000import pytest from .._engines import get_engine_names from .._engines import get_execution_engine from .._engines import get_serialization_engine def test_engine_name_discovery(): names = get_engine_names() expected = {"core", "dask", "ppf", "orange"} assert expected.issubset(names) def test_execution_engine_discovery(): core_engine = get_execution_engine("core") for name in (None, "none", "None"): engine = get_execution_engine(name) assert engine.__class__ is core_engine.__class__ for engine in ("ppf", "dask", "orange"): _ = get_execution_engine(engine) with pytest.raises(RuntimeError): _ = get_execution_engine("__wrong_value__") def test_serialization_engine_discovery(): orange_engine = get_execution_engine("orange") engine, representation = get_serialization_engine("test.ows") assert engine.__class__ is orange_engine.__class__ assert representation == "ows" core_engine = get_execution_engine("core") engine, representation = get_serialization_engine("test.json") assert engine.__class__ is core_engine.__class__ assert representation == "json" core_engine = get_execution_engine("core") engine, representation = get_serialization_engine("{}") assert engine.__class__ is core_engine.__class__ assert representation == "json_string" ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_execute_cli.py000066400000000000000000000061571512474103500274750ustar00rootroot00000000000000import os import sys import pytest from ewokscore import load_graph from ewokscore.graph import TaskGraph from ewokscore.tests.examples.graphs import get_graph from ewokscore.tests.examples.graphs import graph_names from ewokscore.tests.utils.results import assert_execute_graph_default_result from ewoks.__main__ import main from ewoks.tests.utils import has_default_input def _ewokscore_in_graph_requirements(graph: TaskGraph) -> bool: ewokscore_in_req = False for requirement in graph.graph.graph["requirements"]: if "ewokscore" in requirement: ewokscore_in_req = True break return ewokscore_in_req @pytest.mark.parametrize("graph_name", graph_names()) @pytest.mark.parametrize("scheme", (None, "json")) @pytest.mark.parametrize("engine", (None, "dask", "ppf")) def test_execute(graph_name, scheme, engine, tmpdir): if graph_name == "self_trigger": pytest.skip( "Self-triggering workflow execution is inconsistent: https://gitlab.esrf.fr/workflow/ewoks/ewoksppf/-/issues/16" ) graph, expected = get_graph(graph_name) argv = [sys.executable, "execute", graph_name, "--test", "--merge-outputs"] if engine: argv += ["--engine", engine] if engine == "ppf": argv += ["--outputs", "end"] else: argv += ["--outputs", "all"] if scheme: argv += ["--data-root-uri", str(tmpdir), "--data-scheme", scheme] varinfo = {"root_uri": str(tmpdir), "scheme": scheme} else: varinfo = None keep = graph ewoksgraph = load_graph(graph) non_dag = ewoksgraph.is_cyclic or ewoksgraph.has_conditional_links results = main(argv=argv, shell=False) assert len(results) == 1 if non_dag and engine != "ppf": assert isinstance(results[0], RuntimeError) else: assert_execute_graph_default_result(ewoksgraph, results[0], expected, varinfo) assert keep == graph def test_execute_with_convert_destination(tmpdir): destination = str(tmpdir / "convert.json") argv = [ sys.executable, "execute", "demo", "--test", "-p", "task1:b=42", "-o", f"convert_destination={destination}", ] main(argv=argv, shell=False) assert os.path.exists(destination) graph = load_graph(destination) task1_node = graph.graph.nodes["task1"] assert has_default_input(task1_node, "b", 42) assert graph.graph.graph["requirements"] is not None assert _ewokscore_in_graph_requirements(graph) def test_execute_with_convert_destination_inputs_all(tmpdir): destination = str(tmpdir / "convert.json") argv = [ sys.executable, "execute", "demo", "--test", "-p", "b=42", "--inputs=all", "-o", f"convert_destination={destination}", ] main(argv=argv, shell=False) assert os.path.exists(destination) graph = load_graph(destination) for node in graph.graph.nodes.values(): assert has_default_input(node, "b", 42) assert graph.graph.graph["requirements"] is not None assert _ewokscore_in_graph_requirements(graph) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_icat.py000066400000000000000000000030341512474103500261130ustar00rootroot00000000000000from ..bindings import execute_graph def test_upload_context(mock_icat_client): graph = { "graph": {"id": "demo", "label": "demo", "schema_version": "1.1"}, "links": [], "nodes": [ { "default_inputs": [ {"name": "a", "value": 42}, {"name": "delay", "value": 0}, ], "id": "task0", "task_identifier": "ewokscore.tests.examples.tasks.sumtask.SumTask", "task_type": "class", }, ], } execute_graph( graph, inputs=[{"name": "delay", "value": 0, "all": False}], upload_parameters={}, ) args, kwargs = mock_icat_client.return_value.store_processed_data.call_args assert not args assert set(kwargs) == {"metadata"} assert set(kwargs["metadata"]) == {"startDate", "endDate"} duration = kwargs["metadata"]["endDate"] - kwargs["metadata"]["startDate"] delay = 1 margin = 0.5 execute_graph( graph, inputs=[{"name": "delay", "value": delay + margin, "all": False}], upload_parameters={}, ) args, kwargs = mock_icat_client.return_value.store_processed_data.call_args assert not args assert set(kwargs) == {"metadata"} assert set(kwargs["metadata"]) == {"startDate", "endDate"} duration_with_delay = ( kwargs["metadata"]["endDate"] - kwargs["metadata"]["startDate"] ) difference = duration_with_delay - duration assert difference.total_seconds() > delay ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_install_cli.py000066400000000000000000000024331512474103500274720ustar00rootroot00000000000000import json import subprocess import pytest def test_install(venv): with pytest.raises(Exception, match="package is not installed"): venv.get_version("ewoksdata") subprocess.check_call( [ "ewoks", "install", "--yes", '{"graph": {"id": "test_install", "requirements": ["ewoksdata"]}}', "-p", f"{venv.python}", ] ) assert venv.get_version("ewoksdata") is not None def test_install_with_extract(venv): with pytest.raises(Exception, match="package is not installed"): venv.get_version("ewoksdata") nodes = [ { "id": 1, "task_identifier": 'ewoksdata.tasks.normalization.Normalization"', "task_type": "class", }, { "id": 2, "task_identifier": "path/to/my/script", "task_type": "script", }, # Check that unsupported task type goes though without error ] graph = {"graph": {"id": "test_install"}, "nodes": nodes} subprocess.check_call( [ "ewoks", "install", "--yes", json.dumps(graph), "-p", f"{venv.python}", ] ) assert venv.get_version("ewoksdata") is not None ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_notebooks.py000066400000000000000000000024001512474103500271720ustar00rootroot00000000000000import asyncio import sys from typing import Generator if sys.platform.startswith("win"): asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) import pytest import testbook from testbook.client import TestbookNotebookClient from .notebooks import notebook_path _NOTEBOOK_OUTPUTS = {"running_workflows.ipynb": "result = 16"} @pytest.mark.parametrize("name", _NOTEBOOK_OUTPUTS) def test_notebooks(name): expected_output = _NOTEBOOK_OUTPUTS[name] with notebook_path(name) as filename: decorator = testbook.testbook(filename) output_found = False def verify_notebook(tb: TestbookNotebookClient) -> None: tb.execute() nonlocal output_found for output in _iter_cell_outputs(tb): print(output) if expected_output in output: output_found = True break decorator(verify_notebook)() assert output_found def _iter_cell_outputs(tb: TestbookNotebookClient) -> Generator[str, None, None]: for cell in tb.nb.cells: output_nodes = cell.get("outputs", []) for output_node in output_nodes: if output_node["output_type"] == "stream": yield output_node["text"] ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_projects.py000066400000000000000000000003021512474103500270170ustar00rootroot00000000000000import importlib import pytest @pytest.mark.parametrize( "project", ["ewokscore", "ewoksdask", "ewoksppf", "ewoksorange"] ) def test_import(project): importlib.import_module(project) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_requirements.py000066400000000000000000000061151512474103500277210ustar00rootroot00000000000000import pytest from .._requirements.pip.sanitize import sanitize_requirements def test_normal_requirement(): req = ["ewoks==1.1.0"] sanitized, warnings = sanitize_requirements(req) assert sanitized == ["ewoks==1.1.0"] assert warnings == [] def test_editable_ssh_vcs_url_normalized(): ssh_project_name = "querypool" ssh_project_url = "gitlab.esrf.fr/dau/querypool.git" ssh_project_commit = "ab6acc7e140ed33eb896b1336a5a5aac6b60cc0f" req = [ f"-e git+ssh://git@{ssh_project_url}@{ssh_project_commit}#egg={ssh_project_name}" ] sanitized, warnings = sanitize_requirements(req) expected_sanitized = [ f"{ssh_project_name} @ git+https://{ssh_project_url}@{ssh_project_commit}" ] expected_warnings = [ f"Normalize VCS requirement 'git+ssh://git@{ssh_project_url}@{ssh_project_commit}#egg={ssh_project_name}' " f"to '{ssh_project_name} @ git+ssh://git@{ssh_project_url}@{ssh_project_commit}'", f"Normalize requirement '{ssh_project_name} @ git+ssh://git@{ssh_project_url}@{ssh_project_commit}' " f"to '{ssh_project_name} @ git+https://{ssh_project_url}@{ssh_project_commit}'", ] assert sanitized == expected_sanitized assert warnings == expected_warnings @pytest.mark.parametrize("exists", [True, False]) def test_editable_local_path_with_comment_replacement(tmp_path, exists): path = tmp_path / "repo_name" if exists: path.mkdir() comment = "# Editable Git install with no remote (project_name==1.0.0)" replacement = "project_name==1.0.0" req = [comment, f"-e {path}"] sanitized, warnings = sanitize_requirements(req) assert sanitized == [replacement] assert warnings == [f"Replaced editable install '{path}' with '{replacement}'."] @pytest.mark.parametrize("exists", [True, False]) def test_editable_local_path_without_comment_replacement(tmp_path, exists): path = tmp_path / "repo_name" if exists: path.mkdir() warning = f"Editable path exists locally: '{path}'" else: warning = f"Editable path does not exist locally: '{path}'" req = [f"-e {path}"] sanitized, warnings = sanitize_requirements(req) assert sanitized == [f"-e {path}"] if exists: assert warnings == [warning] else: assert warnings == [warning] def test_branch_specified_requirement(): project_name = "ewoksutils" project_url = "gitlab.esrf.fr/workflow/ewoks/ewoksutils.git" project_branch = "main" req = [f"{project_name}@ git+https://{project_url}@{project_branch}"] sanitized, warnings = sanitize_requirements(req) # No warnings expected here (assuming valid format) assert sanitized == [f"{project_name}@ git+https://{project_url}@{project_branch}"] assert warnings == [] def test_invalid_requirement_warning(): project_url = "gitlab.esrf.fr/workflow/ewoks/ewoksutils.git" req = [f"git+https://{project_url}"] sanitized, warnings = sanitize_requirements(req) assert sanitized == [f"git+https://{project_url}"] assert any("Possibly invalid requirement format" in w for w in warnings) ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/test_show_cli.py000066400000000000000000000304731512474103500270110ustar00rootroot00000000000000import os import sys from ewoks.__main__ import main from .utils import no_widget_registry def test_show(capsys): argv = [sys.executable, "show", "demo", "--test"] main(argv=argv, shell=False) captured = capsys.readouterr() expected = """ Workflow: demo Id: demo Description: demo ╒════════╤════════════════╤═══════════════════╤═══════╕ │ Name │ Value │ Task identifier │ Id │ ╞════════╪════════════════╪═══════════════════╪═══════╡ │ list │ [0, 1, 2] │ SumList │ task0 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumList │ task0 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ │ SumTask │ task1 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task1 │ ├────────┼────────────────┼───────────────────┼───────┤ │ a │ 2 │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task2 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 3 │ SumTask │ task3 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task3 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 4 │ SumTask │ task4 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task4 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task5 │ ├────────┼────────────────┼───────────────────┼───────┤ │ b │ 6 │ SumTask │ task6 │ ├────────┼────────────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task6 │ ╘════════╧════════════════╧═══════════════════╧═══════╛ """ assert captured.out == expected assert captured.err == "" def test_show_with_inputs(capsys): argv = [sys.executable, "show", "demo", "--test", "-p", "b=999", "--inputs=all"] main(argv=argv, shell=False) captured = capsys.readouterr() expected = """ Workflow: demo Id: demo Description: demo ╒════════╤═══════════╤═══════════════════╤═══════╕ │ Name │ Value │ Task identifier │ Id │ ╞════════╪═══════════╪═══════════════════╪═══════╡ │ list │ [0, 1, 2] │ SumList │ task0 │ ├────────┼───────────┼───────────────────┼───────┤ │ delay │ 0 │ SumList │ task0 │ ├────────┼───────────┼───────────────────┼───────┤ │ b │ 999 │ SumTask │ task1 │ ├────────┼───────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task1 │ ├────────┼───────────┼───────────────────┼───────┤ │ a │ 2 │ SumTask │ task2 │ ├────────┼───────────┼───────────────────┼───────┤ │ b │ 999 │ SumTask │ task2 │ ├────────┼───────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task2 │ ├────────┼───────────┼───────────────────┼───────┤ │ b │ 999 │ SumTask │ task3 │ ├────────┼───────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task3 │ ├────────┼───────────┼───────────────────┼───────┤ │ b │ 999 │ SumTask │ task4 │ ├────────┼───────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task4 │ ├────────┼───────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task5 │ ├────────┼───────────┼───────────────────┼───────┤ │ b │ 999 │ SumTask │ task6 │ ├────────┼───────────┼───────────────────┼───────┤ │ delay │ 0 │ SumTask │ task6 │ ╘════════╧═══════════╧═══════════════════╧═══════╛ """ assert captured.out == expected assert captured.err == "" def test_show_with_convert_ows(capsys, tmpdir): # Generate an OWS file graph_name = "demo" destination = str(tmpdir / f"{graph_name}.ows") argv = [ sys.executable, "convert", graph_name, destination, "--test", ] with no_widget_registry(): main(argv=argv, shell=False) assert os.path.exists(destination) capsys.readouterr() # Show the OWS file argv = [sys.executable, "show", destination] main(argv=argv, shell=False) captured = capsys.readouterr() expected = f""" Workflow: {destination} Id: demo Description: demo ╒════════╤════════════════╤═══════════════════╤══════╤═════════╕ │ Name │ Value │ Task identifier │ Id │ Label │ ╞════════╪════════════════╪═══════════════════╪══════╪═════════╡ │ list │ [0, 1, 2] │ SumList │ 0 │ task0 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ delay │ 0 │ SumList │ 0 │ task0 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ b │ │ SumTask │ 1 │ task1 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ delay │ 0 │ SumTask │ 1 │ task1 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ a │ 2 │ SumTask │ 2 │ task2 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ b │ │ SumTask │ 2 │ task2 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ delay │ 0 │ SumTask │ 2 │ task2 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ b │ 3 │ SumTask │ 3 │ task3 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ delay │ 0 │ SumTask │ 3 │ task3 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ b │ 4 │ SumTask │ 4 │ task4 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ delay │ 0 │ SumTask │ 4 │ task4 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ delay │ 0 │ SumTask │ 5 │ task5 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ b │ 6 │ SumTask │ 6 │ task6 │ ├────────┼────────────────┼───────────────────┼──────┼─────────┤ │ delay │ 0 │ SumTask │ 6 │ task6 │ ╘════════╧════════════════╧═══════════════════╧══════╧═════════╛ """ assert captured.out == expected assert captured.err == "" ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/tests/utils.py000066400000000000000000000007771512474103500253070ustar00rootroot00000000000000from contextlib import contextmanager from typing import Any def has_default_input(node: dict, input_name: str, value: Any) -> bool: for default_input in node["default_inputs"]: if default_input["name"] == input_name: return default_input["value"] == value else: return False @contextmanager def no_widget_registry(): try: yield finally: from orangecontrib.ewoksnowidget import global_cleanup_ewoksnowidget global_cleanup_ewoksnowidget() ewoks-v4.0.0-8f4a8f91507ab3c3721e8d3f73e73ecca373546a/src/ewoks/utils.py000066400000000000000000000000001512474103500241200ustar00rootroot00000000000000