diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e316f2a6..b0818696 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -19,7 +19,7 @@ If you'd like to write some code for nf-core/airrflow, the standard workflow is 1. Check that there isn't already an issue about your idea in the [nf-core/airrflow issues](https://github.com/nf-core/airrflow/issues) to avoid duplicating work. If there isn't one already, please create one so that others know you're working on this 2. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [nf-core/airrflow repository](https://github.com/nf-core/airrflow) to your GitHub account 3. Make the necessary changes / additions within your forked repository following [Pipeline conventions](#pipeline-contribution-conventions) -4. Use `nf-core schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). +4. Use `nf-core pipelines schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). 5. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged If you're not used to this workflow with git, you can start with some [docs from GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests) or even their [excellent `git` resources](https://try.github.io/). @@ -40,7 +40,7 @@ There are typically two types of tests that run: ### Lint tests `nf-core` has a [set of guidelines](https://nf-co.re/developers/guidelines) which all pipelines must adhere to. -To enforce these and ensure that all pipelines stay in sync, we have developed a helper tool which runs checks on the pipeline code. This is in the [nf-core/tools repository](https://github.com/nf-core/tools) and once installed can be run locally with the `nf-core lint ` command. +To enforce these and ensure that all pipelines stay in sync, we have developed a helper tool which runs checks on the pipeline code. This is in the [nf-core/tools repository](https://github.com/nf-core/tools) and once installed can be run locally with the `nf-core pipelines lint ` command. If any failures or warnings are encountered, please follow the listed URL for more documentation. @@ -75,7 +75,7 @@ If you wish to contribute a new step, please use the following coding standards: 2. Write the process block (see below). 3. Define the output channel if needed (see below). 4. Add any new parameters to `nextflow.config` with a default (see below). -5. Add any new parameters to `nextflow_schema.json` with help text (via the `nf-core schema build` tool). +5. Add any new parameters to `nextflow_schema.json` with help text (via the `nf-core pipelines schema build` tool). 6. Add sanity checks and validation for all relevant parameters. 7. Perform local tests to validate that the new code works as expected. 8. If applicable, add a new test command in `.github/workflow/ci.yml`. @@ -86,11 +86,11 @@ If you wish to contribute a new step, please use the following coding standards: Parameters should be initialised / defined with default values in `nextflow.config` under the `params` scope. -Once there, use `nf-core schema build` to add to `nextflow_schema.json`. +Once there, use `nf-core pipelines schema build` to add to `nextflow_schema.json`. ### Default processes resource requirements -Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/master/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. +Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/main/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. The process resources can be passed on to the tool dynamically within the process with the `${task.cpus}` and `${task.memory}` variables in the `script:` block. @@ -103,7 +103,7 @@ Please use the following naming schemes, to make it easy to understand what is g ### Nextflow version bumping -If you are using a new feature from core Nextflow, you may bump the minimum required version of nextflow in the pipeline with: `nf-core bump-version --nextflow . [min-nf-version]` +If you are using a new feature from core Nextflow, you may bump the minimum required version of nextflow in the pipeline with: `nf-core pipelines bump-version --nextflow . [min-nf-version]` ### Images and figures diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1c3a0658..10c78756 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,7 +17,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/airr - [ ] If you've fixed a bug or added code that should be tested, add tests! - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/airrflow/tree/master/.github/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/airrflow _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. -- [ ] Make sure your code lints (`nf-core lint`). +- [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 9c799e4b..9f62bde3 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -1,18 +1,35 @@ name: nf-core AWS full size tests -# This workflow is triggered on published releases. +# This workflow is triggered on PRs opened against the master branch. # It can be additionally triggered manually with GitHub actions workflow dispatch button. # It runs the -profile 'test_full' on AWS batch on: - release: - types: [published] + pull_request: + branches: + - master workflow_dispatch: + pull_request_review: + types: [submitted] + jobs: run-platform: name: Run AWS full tests - if: github.repository == 'nf-core/airrflow' + # run only if the PR is approved by at least 2 reviewers and against the master branch or manually triggered + if: github.repository == 'nf-core/airrflow' && github.event.review.state == 'approved' && github.event.pull_request.base.ref == 'master' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: + - uses: octokit/request-action@v2.x + id: check_approvals + with: + route: GET /repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - id: test_variables + if: github.event_name != 'workflow_dispatch' + run: | + JSON_RESPONSE='${{ steps.check_approvals.outputs.data }}' + CURRENT_APPROVALS_COUNT=$(echo $JSON_RESPONSE | jq -c '[.[] | select(.state | contains("APPROVED")) ] | length') + test $CURRENT_APPROVALS_COUNT -ge 2 || exit 1 # At least 2 approvals are required - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3ff5e02..015a1439 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,9 +7,14 @@ on: pull_request: release: types: [published] + workflow_dispatch: env: NXF_ANSI_LOG: false + NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity + NXF_SINGULARITY_LIBRARYDIR: ${{ github.workspace }}/.singularity + ACTIONS_RUNNER_DEBUG: true + ACTIONS_STEP_DEBUG: true concurrency: group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" @@ -17,30 +22,68 @@ concurrency: jobs: test: - name: Run pipeline with test data + name: "Run pipeline with test data (${{ matrix.NXF_VER }} | ${{ matrix.test_name }} | ${{ matrix.profile }})" # Only run on push if this is the nf-core dev branch (merged PRs) if: ${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/airrflow') }} runs-on: ubuntu-latest strategy: matrix: NXF_VER: - - "23.04.0" + - "24.04.2" - "latest-everything" + profile: + - "docker" + - "singularity" + test_name: + - "test" + isMaster: + - ${{ github.base_ref == 'master' }} + # Exclude conda and singularity on dev + exclude: + - isMaster: false + profile: "conda" + - isMaster: false + profile: "singularity" steps: - name: Check out pipeline code uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - - name: Install Nextflow + - name: Set up Nextflow uses: nf-core/setup-nextflow@v2 with: version: "${{ matrix.NXF_VER }}" - - name: Disk space cleanup + - name: Set up Apptainer + if: matrix.profile == 'singularity' + uses: eWaterCycle/setup-apptainer@main + + - name: Set up Singularity + if: matrix.profile == 'singularity' + run: | + mkdir -p $NXF_SINGULARITY_CACHEDIR + mkdir -p $NXF_SINGULARITY_LIBRARYDIR + + - name: Set up Miniconda + if: matrix.profile == 'conda' + uses: conda-incubator/setup-miniconda@a4260408e20b96e80095f42ff7f1a15b27dd94ca # v3 + with: + miniconda-version: "latest" + auto-update-conda: true + conda-solver: libmamba + channels: conda-forge,bioconda + + - name: Set up Conda + if: matrix.profile == 'conda' + run: | + echo $(realpath $CONDA)/condabin >> $GITHUB_PATH + echo $(realpath python) >> $GITHUB_PATH + + - name: Clean up Disk space uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - name: Run pipeline with test data + - name: "Run pipeline with test data ${{ matrix.NXF_VER }} | ${{ matrix.test_name }} | ${{ matrix.profile }}" run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results + nextflow run ${GITHUB_WORKSPACE} -profile ${{ matrix.test_name }},${{ matrix.profile }} --outdir ./results test_profile: name: Run workflow test with different profiles @@ -49,7 +92,7 @@ jobs: strategy: matrix: NXF_VER: - - "23.04.0" + - "24.04.2" - "latest-everything" profile: [ @@ -62,14 +105,18 @@ jobs: "test_10x_sc", "test_clontech_umi", "test_nebnext_umi", + "test_rnaseq_bulk", + "test_rnaseq_sc", + "test_maskprimers_extract", + "test_maskprimers_align", ] fail-fast: false steps: - name: Check out pipeline code - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 with: version: "${{ matrix.NXF_VER }}" @@ -79,7 +126,7 @@ jobs: - name: Upload logs on failure if: failure() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: logs-${{ matrix.profile }} path: | diff --git a/.github/workflows/ci_immcantation.yml b/.github/workflows/ci_immcantation.yml index 9301f01a..04162975 100644 --- a/.github/workflows/ci_immcantation.yml +++ b/.github/workflows/ci_immcantation.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: NXF_VER: - - "23.04.0" + - "24.04.2" - "latest-everything" profile: [ @@ -34,7 +34,7 @@ jobs: uses: actions/checkout@v3 - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 with: version: "${{ matrix.NXF_VER }}" @@ -44,7 +44,7 @@ jobs: - name: Upload logs on failure if: failure() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: logs-${{ matrix.profile }} path: | diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 2d20d644..713dc3e7 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -1,4 +1,4 @@ -name: Test successful pipeline download with 'nf-core download' +name: Test successful pipeline download with 'nf-core pipelines download' # Run the workflow when: # - dispatched manually @@ -8,7 +8,7 @@ on: workflow_dispatch: inputs: testbranch: - description: "The specific branch you wish to utilize for the test execution of nf-core download." + description: "The specific branch you wish to utilize for the test execution of nf-core pipelines download." required: true default: "dev" pull_request: @@ -39,9 +39,11 @@ jobs: with: python-version: "3.12" architecture: "x64" - - uses: eWaterCycle/setup-singularity@931d4e31109e875b13309ae1d07c70ca8fbc8537 # v7 + + - name: Setup Apptainer + uses: eWaterCycle/setup-apptainer@4bb22c52d4f63406c49e94c804632975787312b3 # v2.0.0 with: - singularity-version: 3.8.3 + apptainer-version: 1.3.4 - name: Install dependencies run: | @@ -54,33 +56,64 @@ jobs: echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> ${GITHUB_ENV} echo "REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> ${GITHUB_ENV} + - name: Make a cache directory for the container images + run: | + mkdir -p ./singularity_container_images + - name: Download the pipeline env: - NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_CACHEDIR: ./singularity_container_images run: | - nf-core download ${{ env.REPO_LOWERCASE }} \ + nf-core pipelines download ${{ env.REPO_LOWERCASE }} \ --revision ${{ env.REPO_BRANCH }} \ --outdir ./${{ env.REPOTITLE_LOWERCASE }} \ --compress "none" \ --container-system 'singularity' \ - --container-library "quay.io" -l "docker.io" -l "ghcr.io" \ + --container-library "quay.io" -l "docker.io" -l "community.wave.seqera.io" \ --container-cache-utilisation 'amend' \ - --download-configuration + --download-configuration 'yes' - name: Inspect download run: tree ./${{ env.REPOTITLE_LOWERCASE }} + - name: Count the downloaded number of container images + id: count_initial + run: | + image_count=$(ls -1 ./singularity_container_images | wc -l | xargs) + echo "Initial container image count: $image_count" + echo "IMAGE_COUNT_INITIAL=$image_count" >> ${GITHUB_ENV} + - name: Run the downloaded pipeline (stub) id: stub_run_pipeline continue-on-error: true env: - NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_CACHEDIR: ./singularity_container_images NXF_SINGULARITY_HOME_MOUNT: true run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test,singularity --outdir ./results - name: Run the downloaded pipeline (stub run not supported) id: run_pipeline if: ${{ job.steps.stub_run_pipeline.status == failure() }} env: - NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_CACHEDIR: ./singularity_container_images NXF_SINGULARITY_HOME_MOUNT: true run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -profile test,singularity --outdir ./results + + - name: Count the downloaded number of container images + id: count_afterwards + run: | + image_count=$(ls -1 ./singularity_container_images | wc -l | xargs) + echo "Post-pipeline run container image count: $image_count" + echo "IMAGE_COUNT_AFTER=$image_count" >> ${GITHUB_ENV} + + - name: Compare container image counts + run: | + if [ "${{ env.IMAGE_COUNT_INITIAL }}" -ne "${{ env.IMAGE_COUNT_AFTER }}" ]; then + initial_count=${{ env.IMAGE_COUNT_INITIAL }} + final_count=${{ env.IMAGE_COUNT_AFTER }} + difference=$((final_count - initial_count)) + echo "$difference additional container images were \n downloaded at runtime . The pipeline has no support for offline runs!" + tree ./singularity_container_images + exit 1 + else + echo "The pipeline can be downloaded successfully!" + fi diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 1fcafe88..a502573c 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -1,6 +1,6 @@ name: nf-core linting # This workflow is triggered on pushes and PRs to the repository. -# It runs the `nf-core lint` and markdown lint tests to ensure +# It runs the `nf-core pipelines lint` and markdown lint tests to ensure # that the code meets the nf-core guidelines. on: push: @@ -41,17 +41,32 @@ jobs: python-version: "3.12" architecture: "x64" + - name: read .nf-core.yml + uses: pietrobolcato/action-read-yaml@1.1.0 + id: read_yml + with: + config: ${{ github.workspace }}/.nf-core.yml + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install nf-core + pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + + - name: Run nf-core pipelines lint + if: ${{ github.base_ref != 'master' }} + env: + GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} + run: nf-core -l lint_log.txt pipelines lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md - - name: Run nf-core lint + - name: Run nf-core pipelines lint --release + if: ${{ github.base_ref == 'master' }} env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} - run: nf-core -l lint_log.txt lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md + run: nf-core -l lint_log.txt pipelines lint --release --dir ${GITHUB_WORKSPACE} --markdown lint_results.md - name: Save PR number if: ${{ always() }} diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 40acc23f..42e519bf 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download lint results - uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3 + uses: dawidd6/action-download-artifact@bf251b5aa9c2f7eeb574a96ee720e24f801b7c11 # v6 with: workflow: linting.yml workflow_conclusion: completed diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 03ecfcf7..c6ba35df 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -12,7 +12,7 @@ jobs: - name: get topics and convert to hashtags id: get_topics run: | - echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" >> $GITHUB_OUTPUT + echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" | sed 's/-//g' >> $GITHUB_OUTPUT - uses: rzr/fediverse-action@master with: diff --git a/.github/workflows/template_version_comment.yml b/.github/workflows/template_version_comment.yml new file mode 100644 index 00000000..e8aafe44 --- /dev/null +++ b/.github/workflows/template_version_comment.yml @@ -0,0 +1,46 @@ +name: nf-core template version comment +# This workflow is triggered on PRs to check if the pipeline template version matches the latest nf-core version. +# It posts a comment to the PR, even if it comes from a fork. + +on: pull_request_target + +jobs: + template_version: + runs-on: ubuntu-latest + steps: + - name: Check out pipeline code + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Read template version from .nf-core.yml + uses: nichmor/minimal-read-yaml@v0.0.2 + id: read_yml + with: + config: ${{ github.workspace }}/.nf-core.yml + + - name: Install nf-core + run: | + python -m pip install --upgrade pip + pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + + - name: Check nf-core outdated + id: nf_core_outdated + run: echo "OUTPUT=$(pip list --outdated | grep nf-core)" >> ${GITHUB_ENV} + + - name: Post nf-core template version comment + uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 + if: | + contains(env.OUTPUT, 'nf-core') + with: + repo-token: ${{ secrets.NF_CORE_BOT_AUTH_TOKEN }} + allow-repeats: false + message: | + > [!WARNING] + > Newer version of the nf-core template is available. + > + > Your pipeline is using an old version of the nf-core template: ${{ steps.read_yml.outputs['nf_core_version'] }}. + > Please update your pipeline to the latest version. + > + > For more documentation on how to update your pipeline, please see the [nf-core documentation](https://github.com/nf-core/tools?tab=readme-ov-file#sync-a-pipeline-with-the-template) and [Synchronisation documentation](https://nf-co.re/docs/contributing/sync). + # diff --git a/.gitignore b/.gitignore index 9f348012..a42ce016 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,4 @@ results/ testing/ testing* *.pyc -node_modules/ -package-lock.json -.idea/ -nf-params.json -.vscode/ -tests/ -test_flow/ +null/ diff --git a/.gitpod.yml b/.gitpod.yml index 105a1821..46118637 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -4,17 +4,14 @@ tasks: command: | pre-commit install --install-hooks nextflow self-update - - name: unset JAVA_TOOL_OPTIONS - command: | - unset JAVA_TOOL_OPTIONS vscode: extensions: # based on nf-core.nf-core-extensionpack - - esbenp.prettier-vscode # Markdown/CommonMark linting and style checking for Visual Studio Code + #- esbenp.prettier-vscode # Markdown/CommonMark linting and style checking for Visual Studio Code - EditorConfig.EditorConfig # override user/workspace settings with settings found in .editorconfig files - Gruntfuggly.todo-tree # Display TODO and FIXME in a tree view in the activity bar - mechatroner.rainbow-csv # Highlight columns in csv files in different colors - # - nextflow.nextflow # Nextflow syntax highlighting + - nextflow.nextflow # Nextflow syntax highlighting - oderwat.indent-rainbow # Highlight indentation level - streetsidesoftware.code-spell-checker # Spelling checker for source code - charliermarsh.ruff # Code linter Ruff diff --git a/.nf-core.yml b/.nf-core.yml index da47f3f0..159deec3 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,3 +1,4 @@ +bump_version: null lint: files_exist: - conf/igenomes.config @@ -11,5 +12,18 @@ lint: - params.report_logo - params.report_logo_img - params.config_profile_url + included_configs: False +nf_core_version: 3.0.2 +org_path: null repository_type: pipeline -nf_core_version: "2.14.1" +template: + author: Gisela Gabernet, Susanna Marquez, Alexander Peltzer, Simon Heumos + description: B and T cell repertoire analysis pipeline with the Immcantation framework. + force: false + is_nfcore: true + name: airrflow + org: nf-core + outdir: . + skip_features: null + version: 4.1.0 +update: null diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4dc0f1dc..9e9f0e1c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - prettier@3.2.5 - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - rev: "2.7.3" + rev: "3.0.3" hooks: - id: editorconfig-checker alias: ec diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..cee7b74a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.formatting.provider": "none" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index a9cf4c5e..f63d8f7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,38 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [4.1.0] - +## [4.2.0] - Evanesco + +### `Added` + +- [#334](https://github.com/nf-core/airrflow/pull/334) Added TRUST4 support. +- [#344](https://github.com/nf-core/airrflow/pull/344) Added option to remove V and C primer region when sequence is unknown. +- [#344](https://github.com/nf-core/airrflow/pull/344) Added option to save non-productive sequences +- [#344](https://github.com/nf-core/airrflow/pull/344) Allow for maskprimers align with UMI on both V gene and C gene primers. +- [#344](https://github.com/nf-core/airrflow/pull/344) Update pipeline template to nf-core tools v3.0.2. +- [357](https://github.com/nf-core/airrflow/pull/357) Deprecate isotype_column parameter in favor of annotating C region from internal c_region alignment or c_primer alignment into the c_call column. + +### `Fixed` + +- [#344](https://github.com/nf-core/airrflow/pull/344) Avoid saving pRESTO intermediate fastq files in results directory. +- [#344](https://github.com/nf-core/airrflow/pull/344) Simplified pRESTO Maskprimers score and Maskprimers extract processes. +- [#344](https://github.com/nf-core/airrflow/pull/344) Fix clustersets approach, consider both reads clusters annotation. +- [#344](https://github.com/nf-core/airrflow/pull/344) Allow for partial alignments in MakeDB for mouse TCR data, to bypass junction check for TRAV germlines with additional positions (e.g. 84A). +- [#344](https://github.com/nf-core/airrflow/pull/344) Fix parse logs merging dataframes using pandas join to produce logs even when there are failing samples. +- [#344](https://github.com/nf-core/airrflow/pull/344) Use pRESTO Collapseseq with n=0 by default due to runtime issues. + +### `Dependencies` + +| Dependency | Old version | New version | +| ---------- | ----------- | ----------- | +| enchantr | 0.1.16 | 0.1.19 | +| presto | 0.7.1 | 0.7.2 | + +### `Deprecated parameters` + +- `isotype_column`: if `c_call` column value is NA, now `c_region` and `c_primer` column values respectively are annotated into the `c_call` column. + +## [4.1.0] - Avenseguim ### `Added` diff --git a/CITATIONS.md b/CITATIONS.md index 4300d353..2c952cc7 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -4,7 +4,7 @@ > **nf-core/airrflow: an adaptive immune receptor repertoire analysis workflow employing the Immcantation framework** > -> Gisela Gabernet, Susanna Marquez, Robert Bjornson, Alexander Peltzer, Hailong Meng, Edel Aron, Noah Y. Lee, Cole Jensen, David Ladd, Friederike Hanssen, Simon Heumos, nf-core community, Gur Yaari, Markus C. Kowarik, Sven Nahnsen, Steven H. Kleinstein. BioRxiv. 2024. doi: [10.1101/2024.01.18.576147](https://doi.org/10.1101/2024.01.18.576147). +> Gisela Gabernet, Susanna Marquez, Robert Bjornson, Alexander Peltzer, Hailong Meng, Edel Aron, Noah Y. Lee, Cole G. Jensen, David Ladd, Mark Polster, Friederike Hanssen, Simon Heumos, nf-core community, Gur Yaari, Markus C. Kowarik, Sven Nahnsen, Steven H. Kleinstein. (2024) PLOS Computational Biology, 20(7), e1012265. doi: [https://doi.org/10.1371/journal.pcbi.1012265](https://doi.org/10.1371/journal.pcbi.1012265). Pubmed PMID: 39058741. ## [nf-core](https://pubmed.ncbi.nlm.nih.gov/32055031/) @@ -18,7 +18,7 @@ - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) - > Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. +> Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. - [Fastp](https://doi.org/10.1093/bioinformatics/bty560) @@ -62,7 +62,7 @@ - [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) - > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. +> Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. ## Software packaging/containerisation tools diff --git a/LICENSE b/LICENSE index 2a949fd4..206fa6b6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) Gisela Gabernet, Susanna Marquez, Alexander Peltzer, Simon Heumos +Copyright (c) Gisela Gabernet, Susanna Marquez, Alexander Peltzer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 28a2428b..93d8d057 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ [![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/airrflow/results) [![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.2642009-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.2642009) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A523.04.0-23aa62.svg)](https://www.nextflow.io/) + +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A524.04.2-23aa62.svg)](https://www.nextflow.io/) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) @@ -180,13 +181,14 @@ nf-core/airrflow was originally written by: - [Gisela Gabernet](https://github.com/ggabernet) - [Susanna Marquez](https://github.com/ssnn-airr) -- [Alexander Peltzer](@apeltzer) -- [Simon Heumos](@subwaystation) +- [Alexander Peltzer](https://github.com/apeltzer) We thank the following people for their extensive assistance in the development of the pipeline: - [David Ladd](https://github.com/dladd) -- [Friederike Hanssen](https://github.com/ggabernet/friederikehanssen) +- [Friederike Hanssen](https://github.com/friederikehanssen) +- [Simon Heumos](https://github.com/subwaystation) +- [Mark Polster](https://github.com/mapo9) ## Contributions and Support @@ -196,13 +198,11 @@ For further information or help, don't hesitate to get in touch on the [Slack `# ## Citations -If you use nf-core/airrflow for your analysis, please cite the preprint as follows: +If you use nf-core/airrflow for your analysis, please cite the article as follows: > **nf-core/airrflow: an adaptive immune receptor repertoire analysis workflow employing the Immcantation framework** > -> Gisela Gabernet, Susanna Marquez, Robert Bjornson, Alexander Peltzer, Hailong Meng, Edel Aron, Noah Y. Lee, Cole Jensen, David Ladd, Friederike Hanssen, Simon Heumos, nf-core community, Gur Yaari, Markus C. Kowarik, Sven Nahnsen, Steven H. Kleinstein. -> -> BioRxiv. 2024. doi: [10.1101/2024.01.18.576147](https://doi.org/10.1101/2024.01.18.576147). +> Gisela Gabernet, Susanna Marquez, Robert Bjornson, Alexander Peltzer, Hailong Meng, Edel Aron, Noah Y. Lee, Cole G. Jensen, David Ladd, Mark Polster, Friederike Hanssen, Simon Heumos, nf-core community, Gur Yaari, Markus C. Kowarik, Sven Nahnsen, Steven H. Kleinstein. (2024) PLOS Computational Biology, 20(7), e1012265. doi: [https://doi.org/10.1371/journal.pcbi.1012265](https://doi.org/10.1371/journal.pcbi.1012265). Pubmed PMID: 39058741. The specific pipeline version using the following DOI: [10.5281/zenodo.2642009](https://doi.org/10.5281/zenodo.2642009) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 23dcd315..8adc84c9 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,8 @@ report_comment: > - This report has been generated by the nf-core/airrflow + + This report has been generated by the nf-core/airrflow analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. module_order: - fastqc: diff --git a/assets/repertoire_comparison.Rmd b/assets/repertoire_comparison.Rmd index b16a9cf4..70225fda 100644 --- a/assets/repertoire_comparison.Rmd +++ b/assets/repertoire_comparison.Rmd @@ -74,13 +74,13 @@ tryCatch( { write.table(tab_seqs, file=paste0(seq_dir,"/Table_sequences_assembly.tsv"), sep="\t", quote=F, row.names=F) plot_table <- tidyr::pivot_longer(tab_seqs, - cols=Sequences_R1:Igblast, + cols=Sequences:Igblast, names_to = "steps", values_to ="count") - plot_table$steps <- factor(plot_table$steps, levels=c("Sequences_R1", "Sequences_R2", "Filtered_quality_R1", - "Filtered_quality_R2", "Mask_primers_R1", "Mask_primers_R2", - "Paired", "Build_consensus", "Assemble_pairs", "Unique", - "Representative_2", "Igblast")) + firstcol = which(colnames(tab_seqs) == "Sequences") + lastcol = which(colnames(tab_seqs) == "Igblast") + plot_table$steps <- factor(plot_table$steps, levels=colnames(tab_seqs)[firstcol:lastcol]) + seqs_plot <- ggplot(data=plot_table, aes(x=steps, y=count, group=sample_id)) + geom_line(aes(colour=sample_id)) + diff --git a/assets/schema_input.json b/assets/schema_input.json index bb0ee0ba..686f8ef7 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://raw.githubusercontent.com/nf-core/airrflow/master/assets/schema_input.json", "title": "nf-core/airrflow pipeline - params.input schema", "description": "Schema for the file provided with params.input", @@ -37,7 +37,7 @@ "errorMessage": "Sex must be provided, specify NA if unknown." }, "age": { - "type": "string", + "type": ["string", "integer"], "errorMessage": "Age must be provided, specify NA if unknown." }, "biomaterial_provider": { @@ -48,6 +48,26 @@ "type": "boolean", "pattern": "^\\S+$", "errorMessage": "Single cell must be provided as a TRUE/FALSE value." + }, + "filename_R1": { + "type": "string", + "pattern": "^\\S+$", + "errorMessage": "Filename for R1 cannot contain spaces." + }, + "filename_R2": { + "type": "string", + "pattern": "^\\S+$", + "errorMessage": "Filename for R2 cannot contain spaces." + }, + "filename_I1": { + "type": "string", + "pattern": "^\\S+$", + "errorMessage": "Filename for I1 cannot contain spaces." + }, + "filename": { + "type": "string", + "pattern": "^\\S+$", + "errorMessage": "Filename cannot contain spaces." } }, "required": [ diff --git a/assets/tutorial/airrflow.sh b/assets/tutorial/airrflow.sh index 34022df7..97fcf1e1 100644 --- a/assets/tutorial/airrflow.sh +++ b/assets/tutorial/airrflow.sh @@ -1,9 +1,7 @@ -nextflow run nf-core/airrflow -r 4.1.0 \ +nextflow run nf-core/airrflow -r 4.2.0 \ -profile docker \ --mode assembled \ --input samplesheet.tsv \ --outdir results \ -w work \ ---max_cpus 12 \ ---max_memory 12.GB \ --skip_multiqc diff --git a/bin/log_parsing.py b/bin/log_parsing.py index d262f51b..554c7d05 100755 --- a/bin/log_parsing.py +++ b/bin/log_parsing.py @@ -244,7 +244,7 @@ with open(logfile, "r") as f: for line in f: if "PASS>" in line: - s_code.append(logfile.split("/")[1].split("_command_log")[0]) + s_code.append(logfile.split("/")[1].split("_makedb_command_log")[0]) pass_blast.append(line.strip().removeprefix("PASS> ")) elif "FAIL>" in line: fail_blast.append(line.strip().removeprefix("FAIL> ")) @@ -368,9 +368,7 @@ # Getting table colnames colnames = [ - "Sample", - "Sequences_R1", - "Sequences_R2", + "Sequences", "Filtered_quality_R1", "Filtered_quality_R2", "Mask_primers_R1", @@ -386,24 +384,24 @@ print(df_process_list[0].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")) values = [ - df_process_list[2].sort_values(by=["Sample"]).iloc[:, 0].tolist(), - df_process_list[0].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")["start"]["R1"].tolist(), - df_process_list[0].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")["start"]["R2"].tolist(), - df_process_list[0].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")["pass"]["R1"].tolist(), - df_process_list[0].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")["pass"]["R2"].tolist(), - df_process_list[1].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")["pass"]["R1"].tolist(), - df_process_list[1].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")["pass"]["R2"].tolist(), - df_process_list[2].sort_values(by=["Sample"]).loc[:, "pass_pairs"].tolist(), - df_process_list[4].sort_values(by=["Sample"]).loc[:, "pass_pairs"].tolist(), - df_process_list[5].sort_values(by=["Sample"]).loc[:, "pass_pairs"].tolist(), - df_process_list[6].sort_values(by=["Sample"]).loc[:, "unique"].tolist(), - df_process_list[7].sort_values(by=["Sample"]).loc[:, "repres_2"].tolist(), - df_process_list[7].sort_values(by=["Sample"]).loc[:, "pass_igblast"].tolist(), + df_process_list[0].pivot(index="Sample", columns="readtype")["start"]["R1"], + df_process_list[0].pivot(index="Sample", columns="readtype")["pass"]["R1"], + df_process_list[0].pivot(index="Sample", columns="readtype")["pass"]["R2"], + df_process_list[1].pivot(index="Sample", columns="readtype")["pass"]["R1"], + df_process_list[1].pivot(index="Sample", columns="readtype")["pass"]["R2"], + df_process_list[2].set_index("Sample").loc[:, "pass_pairs"], + df_process_list[4].set_index("Sample").loc[:, "pass_pairs"], + df_process_list[5].set_index("Sample").loc[:, "pass_pairs"], + df_process_list[6].set_index("Sample").loc[:, "unique"], + df_process_list[7].set_index("Sample").loc[:, "repres_2"], + df_process_list[7].set_index("Sample").loc[:, "pass_igblast"], ] +final_table = pd.concat(values, axis=1, join="outer") +final_table.columns = colnames +final_table = final_table.reset_index().rename(columns={"index": "Sample"}) + -final_table = dict(zip(colnames, values)) -print(final_table) df_final_table = pd.DataFrame.from_dict(final_table) df_final_table = df_final_table.sort_values(["Sample"], ascending=[1]) diff --git a/bin/log_parsing_no-umi.py b/bin/log_parsing_no-umi.py index 98367764..417a1367 100755 --- a/bin/log_parsing_no-umi.py +++ b/bin/log_parsing_no-umi.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Written by David Ladd and released under the MIT license (2020). +# Written by David Ladd, Gisela Gabernet and released under the MIT license (2020). # log_parsing_no-umi.py # Parsing log files for each of the steps for QC analysis. @@ -23,7 +23,7 @@ df_process_list = [] for process in processes: - find = subprocess.check_output(["find", process, "-name", "*command_log.txt"]) + find = subprocess.check_output(["find", process, "-name", "*command_log*"]) log_files = find.decode().split("\n") log_files = list(filter(None, log_files)) @@ -59,49 +59,67 @@ df_process_list.append(df_process) - elif process in ["mask_primers", "filter_by_sequence_quality"]: + if process in ["filter_by_sequence_quality"]: s_code = [] + pass_pairs = [] + fail_pairs = [] + process_name = [] + + for logfile in log_files: + with open(logfile, "r") as f: + for line in f: + if " START>" in line: + s_code.append(logfile.split("/")[1].split("_command_log")[0]) + process_name.append(process) + elif "PASS>" in line: + pass_pairs.append(line.strip().removeprefix("PASS> ")) + elif "FAIL>" in line: + fail_pairs.append(line.strip().removeprefix("FAIL> ")) + + df_process = pd.DataFrame.from_dict( + { + "Sample": s_code, + "pass_pairs": pass_pairs, + "fail_pairs": fail_pairs, + "process": process_name, + } + ) + + df_process_list.append(df_process) + + elif process in ["mask_primers"]: + s_code = [] + s_readtype = [] output_file = [] - seqs_R1 = [] - seqs_R2 = [] - pass_R1 = [] - pass_R2 = [] - fail_R1 = [] - fail_R2 = [] + n_seqs = [] + n_pass = [] + n_fail = [] process_name = [] for logfile in log_files: - c = 0 + if "_R1" in logfile: + s_readtype.append("R1") + elif "_R2" in logfile: + s_readtype.append("R2") with open(logfile, "r") as f: - # print(f.read()) for line in f: if " START>" in line: - if c < 1: - s_code.append(logfile.split("/")[1].split("_command_log")[0]) - process_name.append(process) + s_code.append(logfile.split("/")[1].split("_command_log")[0]) + process_name.append(process) elif "SEQUENCES>" in line: - if c < 1: - seqs_R1.append(line.strip().removeprefix("SEQUENCES> ")) - else: - seqs_R2.append(line.strip().removeprefix("SEQUENCES> ")) + n_seqs.append(line.strip().removeprefix("SEQUENCES> ")) elif "PASS>" in line: - if c < 1: - pass_R1.append(line.strip().removeprefix("PASS> ")) - else: - pass_R2.append(line.strip().removeprefix("PASS> ")) + n_pass.append(line.strip().removeprefix("PASS> ")) elif "FAIL>" in line: - if c < 1: - fail_R1.append(line.strip().removeprefix("FAIL> ")) - c += 1 - else: - fail_R2.append(line.strip().removeprefix("FAIL> ")) + n_fail.append(line.strip().removeprefix("FAIL> ")) df_process = pd.DataFrame.from_dict( { "Sample": s_code, - "start_R1": seqs_R1, - "pass_R1": pass_R1, - "fail_R1": fail_R1, + "readtype": s_readtype, + "start": n_seqs, + "pass": n_pass, + "fail": n_fail, "process": process_name, } ) @@ -282,23 +300,13 @@ "Sequences", "Assemble_pairs", "Filtered_quality", - "Mask_primers", + "Mask_primers_R1", + "Mask_primers_R2", "Unique", "Representative_2", "Igblast", ] -values = [ - df_process_list[0].sort_values(by=["Sample"]).iloc[:, 0].tolist(), - df_process_list[0].sort_values(by=["Sample"]).loc[:, "start_pairs"].tolist(), - df_process_list[0].sort_values(by=["Sample"]).loc[:, "pass_pairs"].tolist(), - df_process_list[1].sort_values(by=["Sample"]).loc[:, "pass_R1"].tolist(), - df_process_list[2].sort_values(by=["Sample"]).loc[:, "pass_R1"].tolist(), - df_process_list[3].sort_values(by=["Sample"]).loc[:, "unique"].tolist(), - df_process_list[4].sort_values(by=["Sample"]).loc[:, "repres_2"].tolist(), - df_process_list[4].sort_values(by=["Sample"]).loc[:, "pass_igblast"].tolist(), -] - # Tables provide extra info and help debugging df_process_list[0].to_csv( path_or_buf="Table_all_details_assemble_mates.tsv", @@ -316,6 +324,18 @@ df_process_list[3].to_csv(path_or_buf="Table_all_details_deduplicate.tsv", sep="\t", header=True, index=False) df_process_list[4].to_csv(path_or_buf="Table_all_details_igblast.tsv", sep="\t", header=True, index=False) +values = [ + df_process_list[0].sort_values(by=["Sample"]).iloc[:, 0].tolist(), + df_process_list[0].sort_values(by=["Sample"]).loc[:, "start_pairs"].tolist(), + df_process_list[0].sort_values(by=["Sample"]).loc[:, "pass_pairs"].tolist(), + df_process_list[1].sort_values(by=["Sample"]).loc[:, "pass_pairs"].tolist(), + df_process_list[2].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")["pass"]["R1"].tolist(), + df_process_list[2].sort_values(by=["Sample"]).pivot(index="Sample", columns="readtype")["pass"]["R2"].tolist(), + df_process_list[3].sort_values(by=["Sample"]).loc[:, "unique"].tolist(), + df_process_list[4].sort_values(by=["Sample"]).loc[:, "repres_2"].tolist(), + df_process_list[4].sort_values(by=["Sample"]).loc[:, "pass_igblast"].tolist(), +] + final_table = dict(zip(colnames, values)) print(final_table) df_final_table = pd.DataFrame.from_dict(final_table) diff --git a/conf/base.config b/conf/base.config index 6606bdac..9d512264 100644 --- a/conf/base.config +++ b/conf/base.config @@ -9,9 +9,10 @@ */ process { - cpus = { check_max( 1 * task.attempt, 'cpus' ) } - memory = { check_max( 6.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } + + cpus = { 1 * task.attempt } + memory = { 6.GB * task.attempt } + time = { 4.h * task.attempt } errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'finish' } maxRetries = 1 @@ -24,30 +25,30 @@ process { // adding in your local modules too. // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors withLabel:process_single { - cpus = { check_max( 1 , 'cpus' ) } - memory = { check_max( 6.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } + cpus = { 1 } + memory = { 6.GB * task.attempt } + time = { 4.h * task.attempt } } withLabel:process_low { - cpus = { check_max( 2 * task.attempt, 'cpus' ) } - memory = { check_max( 12.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } + cpus = { 2 * task.attempt } + memory = { 12.GB * task.attempt } + time = { 4.h * task.attempt } } withLabel:process_medium { - cpus = { check_max( 6 * task.attempt, 'cpus' ) } - memory = { check_max( 36.GB * task.attempt, 'memory' ) } - time = { check_max( 8.h * task.attempt, 'time' ) } + cpus = { 6 * task.attempt } + memory = { 36.GB * task.attempt } + time = { 8.h * task.attempt } } withLabel:process_high { - cpus = { check_max( 12 * task.attempt, 'cpus' ) } - memory = { check_max( 72.GB * task.attempt, 'memory' ) } - time = { check_max( 16.h * task.attempt, 'time' ) } + cpus = { 12 * task.attempt } + memory = { 72.GB * task.attempt } + time = { 16.h * task.attempt } } withLabel:process_long { - time = { check_max( 20.h * task.attempt, 'time' ) } + time = { 20.h * task.attempt } } withLabel:process_high_memory { - memory = { check_max( 200.GB * task.attempt, 'memory' ) } + memory = { 200.GB * task.attempt } } withLabel:error_ignore { errorStrategy = 'ignore' @@ -57,8 +58,8 @@ process { maxRetries = 2 } withLabel:process_long_parallelized { - time = { check_max( 30.h * task.attempt, 'time' ) } - cpus = { check_max( 16 * task.attempt, 'cpus' ) } - memory = { check_max( 72.GB * task.attempt, 'memory' ) } + time = { 30.h * task.attempt } + cpus = { 16 * task.attempt } + memory = { 72.GB * task.attempt } } } diff --git a/conf/clontech_umi_bcr.config b/conf/clontech_umi_bcr.config index d2d17e01..9433db7a 100644 --- a/conf/clontech_umi_bcr.config +++ b/conf/clontech_umi_bcr.config @@ -30,12 +30,12 @@ params { // Mask primer options - maskprimers_align = true - primer_extract_len = 7 - primer_mask_mode = 'cut' + maskprimers_align_race = true + primer_r2_extract_len = 7 + primer_r1_mask_mode = 'cut' + primer_r2_mask_mode = 'cut' primer_maxlen = 70 primer_r1_maxerror = 0.2 assemblepairs_sequential = true primer_consensus = 0.6 - isotype_column = 'cregion' } diff --git a/conf/clontech_umi_tcr.config b/conf/clontech_umi_tcr.config index 34aad8ab..d6b71d28 100644 --- a/conf/clontech_umi_tcr.config +++ b/conf/clontech_umi_tcr.config @@ -30,9 +30,10 @@ params { // Mask primer options - maskprimers_align = true - primer_extract_len = 7 - primer_mask_mode = 'cut' + maskprimers_align_race = true + primer_r2_extract_len = 7 + primer_r1_mask_mode = 'cut' + primer_r2_mask_mode = 'cut' primer_maxlen = 70 primer_r1_maxerror = 0.2 assemblepairs_sequential = true diff --git a/conf/igenomes_ignored.config b/conf/igenomes_ignored.config new file mode 100644 index 00000000..b4034d82 --- /dev/null +++ b/conf/igenomes_ignored.config @@ -0,0 +1,9 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for iGenomes paths +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Empty genomes dictionary to use when igenomes is ignored. +---------------------------------------------------------------------------------------- +*/ + +params.genomes = [:] diff --git a/conf/modules.config b/conf/modules.config index 3dc63fa9..c947dfce 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -54,7 +54,7 @@ process { ext.args = [ "--disable_quality_filtering --disable_length_filtering", params.trim_fastq ?: "--disable_adapter_trimming", params.clip_r1 > 0 ? "--trim_front1 ${params.clip_r1}" : "", // Remove bp from the 5' end of read 1 - params.clip_r2 > 0 ? "--trim_front2 ${params.clip_r2}" : "", // Remove bp from the 5' end of read 2 + params.clip_r2 > 0 ? "--trim_front2 ${params.clip_r2}" : "", // Remove bp from the 5' end of read 2 params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed params.three_prime_clip_r2 > 0 ? "--trim_tail2 ${params.three_prime_clip_r2}" : "", // Remove bp from the 3' end of read 2 AFTER adapter/quality trimming has been performed params.trim_nextseq ? "--trim_poly_g" : "", // Apply the --nextseq=X option, to trim based on quality after removing poly-G tails @@ -118,7 +118,7 @@ process { publishDir = [ path: { "${params.outdir}/presto/01-filterseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] } @@ -126,61 +126,139 @@ process { publishDir = [ path: { "${params.outdir}/presto/02-filterseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] } - withName: PRESTO_MASKPRIMERS_UMI { + withName: PRESTO_MASKPRIMERS_SCORE_UMI_R1 { publishDir = [ path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] + ext.args2 = '-f ID PRIMER ERROR' } - withName: PRESTO_MASKPRIMERS_ALIGN { + withName: PRESTO_MASKPRIMERS_SCORE_UMI_R2 { publishDir = [ path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" + ] + ext.args2 = '-f ID PRIMER ERROR' + } + + withName: PRESTO_ALIGN_PRIMERS { + publishDir = [ + path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" ] - ext.args = '--skiprc --pf CREGION' - ext.args2 = '-f ID CREGION ERROR' + ext.args = '--skiprc --pf C_PRIMER' + ext.args2 = '-f ID PRIMER ERROR' } withName: PRESTO_ALIGN_CREGION { publishDir = [ path: { "${params.outdir}/presto/internal_cregion/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] - ext.args = '--skiprc --revpr --pf CREGION' + ext.args = '--skiprc --revpr --pf C_REGION' ext.args2 = '-f ID PRIMER ERROR --outname cregion_alignment' } - withName: PRESTO_MASKPRIMERS_EXTRACT { + withName: 'PRESTO_MASKPRIMERS_EXTRACT' { publishDir = [ path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" + ] + ext.args2 = '-f ID PRIMER ERROR PRSTART' + } + + withName: 'PRESTO_MASKPRIMERS_ALIGN_UMI_R1' { + publishDir = [ + path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" + ] + ext.args2 = '-f ID PRIMER ERROR PRSTART' + } + + withName: 'PRESTO_MASKPRIMERS_ALIGN_UMI_R2' { + publishDir = [ + path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" + ] + ext.args2 = '-f ID PRIMER ERROR PRSTART' + } + + withName: PRESTO_MASKPRIMERS_EXTRACT_R1 { + publishDir = [ + path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" + ] + ext.args = '--pf EXTRACT_PRIMER_R1' + ext.args2 = '-f ID PRIMER ERROR PRSTART' + } + + withName: PRESTO_MASKPRIMERS_EXTRACT_R2 { + publishDir = [ + path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" ] - ext.args = '--barcode --bf BARCODE' + ext.args = '--pf EXTRACT_PRIMER_R2' ext.args2 = '-f ID PRIMER ERROR PRSTART' } - withName: PRESTO_MASKPRIMERS_POSTASSEMBLY_SANS_UMI { + withName: PRESTO_MASKPRIMERS_SCORE_SANSUMI_FWD { publishDir = [ path: { "${params.outdir}/presto/03-maskprimers/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] + ext.args2 = '-f ID PRIMER ERROR' } + withName: PRESTO_MASKPRIMERS_SCORE_SANSUMI_REV { + publishDir = [ + path: { "${params.outdir}/presto/03-maskprimers/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" + ] + ext.args2 = '-f ID PRIMER ERROR' + } + + withName: PRESTO_MASKPRIMERS_ALIGN_SANSUMI_FWD { + publishDir = [ + path: { "${params.outdir}/presto/03-maskprimers/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" + ] + ext.args = '--pf FWD_PRIMER' + ext.args2 = '-f ID PRIMER ERROR' + } + + withName: PRESTO_MASKPRIMERS_ALIGN_SANSUMI_REV { + publishDir = [ + path: { "${params.outdir}/presto/03-maskprimers/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" + ] + ext.args = '--revpr --pf REV_PRIMER' + ext.args2 = '-f ID PRIMER ERROR' + } + + withName: PRESTO_PAIRSEQ { publishDir = [ path: { "${params.outdir}/presto/03-pairseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] ext.args = "--coord illumina" } @@ -189,46 +267,94 @@ process { publishDir = [ path: { "${params.outdir}/presto/03-pairseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" + ] + ext.args = '--1f C_REGION --coord illumina' + } + + withName: PRESTO_PAIRSEQ_EXTRACT { + publishDir = [ + path: { "${params.outdir}/presto/03-pairseq/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" ] - ext.args = '--1f CREGION --coord illumina' + ext.args = '--coord illumina' } - withName: PRESTO_CLUSTERSETS { + withName: PRESTO_CLUSTERSETS_UMI { publishDir = [ path: { "${params.outdir}/presto/04-clustersets/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] + ext.args = '--exec vsearch --ident 0.9' + ext.args2 = '-f ID BARCODE SEQCOUNT CLUSTERS' } withName: PRESTO_PARSE_CLUSTER { publishDir = [ path: { "${params.outdir}/presto/05-parse-clusters/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] } + withName: PRESTO_PAIRSEQ_CLUSTERSETS { + publishDir = [ + path: { "${params.outdir}/presto/05-parse-clusters/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" + ] + ext.args = '--coord illumina' + } + withName: PRESTO_BUILDCONSENSUS_UMI { publishDir = [ path: { "${params.outdir}/presto/06-build-consensus/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] - ext.args = '--pf PRIMER' - ext.args2 = '--pf PRIMER' + ext.args = ["--pf PRIMER --maxerror ${params.buildconsensus_maxerror} --maxgap ${params.buildconsensus_maxgap}", + params.primer_consensus ? "--prcons $params.primer_consensus" : "", + params.cluster_sets ? "--bf CLUSTER" : "--bf BARCODE", + ].join(" ").trim() + ext.args2 = ["--pf PRIMER --maxerror ${params.buildconsensus_maxerror} --maxgap ${params.buildconsensus_maxgap}", + params.primer_consensus ? "--prcons $params.primer_consensus" : "", + params.cluster_sets ? "--bf CLUSTER" : "--bf BARCODE", + ].join(" ").trim() ext.args3 = '-f ID BARCODE SEQCOUNT PRIMER PRCOUNT PRCONS PRFREQ CONSCOUNT ERROR' } - withName: PRESTO_BUILDCONSENSUS_ALIGN { + withName: PRESTO_BUILDCONSENSUS_ALIGN_RACE { publishDir = [ path: { "${params.outdir}/presto/06-build-consensus/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] - ext.args = '--pf CREGION' - ext.args2 = '--pf CREGION' + // Use homogeneous C_PRIMER for consensus + ext.args = ["--pf C_PRIMER --maxerror ${params.buildconsensus_maxerror} --maxgap ${params.buildconsensus_maxgap}", + params.primer_consensus ? "--prcons $params.primer_consensus" : "", + params.cluster_sets ? "--bf CLUSTER" : "--bf BARCODE", + ].join(" ").trim() + // Do not use homogeneous linker for consensus + ext.args2 = ["--maxerror ${params.buildconsensus_maxerror} --maxgap ${params.buildconsensus_maxgap}", + params.cluster_sets ? "--bf CLUSTER" : "--bf BARCODE", + ].join(" ").trim() + ext.args3 = '-f ID BARCODE SEQCOUNT PRIMER PRCOUNT PRCONS PRFREQ CONSCOUNT ERROR' + } + + withName: PRESTO_BUILDCONSENSUS_EXTRACT { + publishDir = [ + path: { "${params.outdir}/presto/06-build-consensus/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{txt,log,tab}" + ] + ext.args = ["--maxerror ${params.buildconsensus_maxerror} --maxgap ${params.buildconsensus_maxgap}", + params.cluster_sets ? "--bf CLUSTER" : "--bf BARCODE", + ].join(" ").trim() + ext.args2 = ["--maxerror ${params.buildconsensus_maxerror} --maxgap ${params.buildconsensus_maxgap}", + params.cluster_sets ? "--bf CLUSTER" : "--bf BARCODE", + ].join(" ").trim() ext.args3 = '-f ID BARCODE SEQCOUNT PRIMER PRCOUNT PRCONS PRFREQ CONSCOUNT ERROR' } @@ -236,7 +362,7 @@ process { publishDir = [ path: { "${params.outdir}/presto/07-postconsensus-pairseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] } @@ -244,7 +370,7 @@ process { publishDir = [ path: { "${params.outdir}/presto/08-assemble-pairs/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] ext.args = '--coord presto --rc tail --1f CONSCOUNT PRCONS --2f CONSCOUNT PRCONS' ext.args2 = '-f ID BARCODE SEQCOUNT PRIMER PRCOUNT PRCONS PRFREQ CONSCOUNT LENGTH OVERLAP ERROR PVALUE' @@ -254,7 +380,7 @@ process { publishDir = [ path: { "${params.outdir}/presto/08-assemble-pairs/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] ext.args = '--coord presto --rc tail --1f CONSCOUNT --2f CONSCOUNT PRCONS --minlen 8 --maxerror 0.3 --alpha 1e-5 --scanrev --minident 0.5 --evalue 1e-5 --maxhits 100 --aligner blastn' ext.args2 = '-f ID REFID LENGTH OVERLAP GAP ERROR PVALUE EVALUE1 EVALUE2 IDENTITY FIELDS1 FIELDS2' @@ -264,9 +390,9 @@ process { publishDir = [ path: { "${params.outdir}/presto/01-assemble-pairs/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] - ext.args = '--rc tail' + ext.args = '--rc tail --coord illumina' ext.args2 = '-f ID SEQCOUNT PRIMER PRCOUNT PRFREQ LENGTH OVERLAP ERROR PVALUE' } @@ -290,7 +416,7 @@ process { enabled: false ] ext.subcommand = 'rename' - ext.args = '-f PRCONS -k CREGION' + ext.args = '-f PRCONS -k C_REGION' } withName: PRESTO_PARSEHEADERS_PRIMERS_SANS_UMI { @@ -311,9 +437,9 @@ process { publishDir = [ path: { "${params.outdir}/presto/09-collapseseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] - ext.args = '-n 20 --inner --uf PRCONS --cf CONSCOUNT --act sum' + ext.args = '-n 0 --inner --uf PRCONS --cf CONSCOUNT --act sum --keepmiss' ext.args2 = '-f HEADER DUPCOUNT CONSCOUNT' } @@ -321,9 +447,9 @@ process { publishDir = [ path: { "${params.outdir}/presto/09-collapseseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] - ext.args = '-n 0 --inner --uf CREGION --cf CONSCOUNT --act sum --keepmiss' + ext.args = '-n 0 --inner --uf C_REGION --cf CONSCOUNT --act sum --keepmiss' ext.args2 = '-f HEADER DUPCOUNT CONSCOUNT' } @@ -331,9 +457,9 @@ process { publishDir = [ path: { "${params.outdir}/presto/09-collapseseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] - ext.args = '-n 0 --inner --uf PRCONS CREGION --cf CONSCOUNT --act sum --keepmiss' + ext.args = '-n 0 --inner --uf PRCONS C_REGION --cf CONSCOUNT --act sum --keepmiss' ext.args2 = '-f HEADER DUPCOUNT CONSCOUNT' } @@ -341,9 +467,9 @@ process { publishDir = [ path: { "${params.outdir}/presto/04-collapseseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] - ext.args = '-n 20 --inner' + ext.args = '-n 0 --inner --keepmiss' ext.args2 = '-f HEADER DUPCOUNT' } @@ -351,7 +477,7 @@ process { publishDir = [ path: { "${params.outdir}/presto/10-splitseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] ext.args = '-f CONSCOUNT --num 2' } @@ -360,7 +486,7 @@ process { publishDir = [ path: { "${params.outdir}/presto/05-splitseq/${meta.id}" }, mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + pattern: "*{txt,log,tab}" ] ext.args = '-f DUPCOUNT --num 2' } @@ -369,7 +495,7 @@ process { // V(D)J annotation // ----------------- - withName: FETCH_DATABASES { + withName: 'FETCH_*' { publishDir = [ path: { "${params.outdir}/databases" }, mode: params.publish_dir_mode, @@ -422,6 +548,14 @@ process { ] } + withName: CHANGEO_PARSEDB_SELECT_LOCUS { + publishDir = [ + path: { "${params.outdir}/vdj_annotation/select-locus/${meta.id}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + withName: CHANGEO_PARSEDB_SPLIT { publishDir = [ path: { "${params.outdir}/vdj_annotation/04-select-productive/${meta.id}" }, diff --git a/conf/nebnext_umi_bcr.config b/conf/nebnext_umi_bcr.config index d6bb6d5b..7467bffe 100644 --- a/conf/nebnext_umi_bcr.config +++ b/conf/nebnext_umi_bcr.config @@ -35,5 +35,4 @@ params { cregion_maxlen = 100 cregion_maxerror = 0.3 cregion_mask_mode = 'tag' - isotype_column = 'cregion' } diff --git a/conf/test.config b/conf/test.config index af9618ce..642670fc 100644 --- a/conf/test.config +++ b/conf/test.config @@ -10,15 +10,18 @@ ---------------------------------------------------------------------------------------- */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + params { config_profile_name = 'Test profile' config_profile_description = 'Minimal test dataset to check pipeline function' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - // Input data input = pipelines_testdata_base_path + 'testdata-bcr/Metadata_test_airr.tsv' cprimers = pipelines_testdata_base_path + 'testdata-bcr/C_primers.fasta' @@ -34,7 +37,6 @@ params { umi_start = 6 umi_position = 'R1' index_file = true - isotype_column = 'c_primer' lineage_trees = true } diff --git a/conf/test_10x_sc.config b/conf/test_10x_sc.config index e9b9e5a8..3fc23f69 100644 --- a/conf/test_10x_sc.config +++ b/conf/test_10x_sc.config @@ -7,15 +7,18 @@ * nextflow run nf-core/airrflow -profile test_10x_sc, */ +process { + resourceLimits = [ + cpus: 2, + memory: '6.GB', + time: '6.h' + ] +} + params { config_profile_name = 'Test 10xGenomics single cell data' config_profile_description = 'Minimal test dataset to check pipeline function with raw single cell data from 10xGenomics' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = 6.GB - max_time = 48.h - // params mode = 'fastq' library_generation_method = 'sc_10x_genomics' diff --git a/conf/test_assembled_hs.config b/conf/test_assembled_hs.config index 9e3d7f5b..cfba51b5 100644 --- a/conf/test_assembled_hs.config +++ b/conf/test_assembled_hs.config @@ -7,15 +7,18 @@ * nextflow run nf-core/airrflow -profile test, */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + params { config_profile_name = 'Test assembled mode' config_profile_description = 'Minimal test dataset to test assembled mode' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = 6.GB - max_time = 6.h - // Input data mode = 'assembled' input = pipelines_testdata_base_path + 'testdata-reveal/test_assembled_metadata_hs.tsv' diff --git a/conf/test_assembled_immcantation_devel_hs.config b/conf/test_assembled_immcantation_devel_hs.config index c842e002..4b295024 100644 --- a/conf/test_assembled_immcantation_devel_hs.config +++ b/conf/test_assembled_immcantation_devel_hs.config @@ -7,15 +7,18 @@ * nextflow run nf-core/airrflow -profile test_assembled_immcantation_hs_devel, */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + params { config_profile_name = 'Test assembled mode with Immcantation custom_container' config_profile_description = 'Minimal human test dataset to check pipeline function on assembled mode with Immcantation custom_container' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = 6.GB - max_time = 6.h - // Input data mode = 'assembled' input = pipelines_testdata_base_path + 'testdata-reveal/test_assembled_metadata_hs.tsv' diff --git a/conf/test_assembled_immcantation_devel_mm.config b/conf/test_assembled_immcantation_devel_mm.config index e148abe8..f1eb5bfe 100644 --- a/conf/test_assembled_immcantation_devel_mm.config +++ b/conf/test_assembled_immcantation_devel_mm.config @@ -7,15 +7,18 @@ * nextflow run nf-core/airrflow -profile test_assembled_immcantation_devel_mm, */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + params { config_profile_name = 'Test assembled mode with Immcantation custom_container' config_profile_description = 'Minimal mouse test dataset to check pipeline function on assembled mode with Immcantation custom_container' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = 6.GB - max_time = 6.h - // Input data mode = 'assembled' input = pipelines_testdata_base_path + 'testdata-reveal/test_assembled_metadata_mm.tsv' diff --git a/conf/test_assembled_mm.config b/conf/test_assembled_mm.config index 43e8275e..aa65f4c1 100644 --- a/conf/test_assembled_mm.config +++ b/conf/test_assembled_mm.config @@ -7,15 +7,18 @@ * nextflow run nf-core/airrflow -profile test, */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + params { config_profile_name = 'Test assembled mode' config_profile_description = 'Minimal mouse test dataset to test assembled mode' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = 6.GB - max_time = 6.h - // Input data mode = 'assembled' input = pipelines_testdata_base_path + 'testdata-reveal/test_assembled_metadata_mm.tsv' diff --git a/conf/test_clontech_umi.config b/conf/test_clontech_umi.config index e1bf317e..cfb48f66 100644 --- a/conf/test_clontech_umi.config +++ b/conf/test_clontech_umi.config @@ -11,15 +11,18 @@ */ includeConfig 'clontech_umi_bcr.config' +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '6.h' + ] +} + params { config_profile_name = 'Test profile for TAKARA protocol' config_profile_description = 'Minimal test dataset to check pipeline function' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - // Input data input = pipelines_testdata_base_path +'testdata-clontech/samplesheet.tsv' diff --git a/conf/test_fetchimgt.config b/conf/test_fetchimgt.config index 468bb52d..149bf382 100644 --- a/conf/test_fetchimgt.config +++ b/conf/test_fetchimgt.config @@ -9,16 +9,18 @@ ---------------------------------------------------------------------------------------- */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} params { config_profile_name = 'Test IMGTdb fetch' config_profile_description = 'Test pipeline when fetching the latest version of the IMGT references.' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - // Input data input = pipelines_testdata_base_path + 'testdata-bcr/Metadata_test_airr.tsv' cprimers = pipelines_testdata_base_path + 'testdata-bcr/C_primers.fasta' @@ -33,7 +35,6 @@ params { umi_start = 6 umi_position = 'R1' index_file = true - isotype_column = 'c_primer' } process{ diff --git a/conf/test_full.config b/conf/test_full.config index 9c652c8f..ac584bc5 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -9,6 +9,13 @@ ---------------------------------------------------------------------------------------- */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} params { config_profile_name = 'Full test profile' @@ -29,7 +36,6 @@ params { umi_length = 15 umi_start = 0 umi_position = 'R1' - isotype_column = 'c_primer' } process { diff --git a/conf/test_maskprimers_align.config b/conf/test_maskprimers_align.config new file mode 100644 index 00000000..4c9416a1 --- /dev/null +++ b/conf/test_maskprimers_align.config @@ -0,0 +1,40 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running minimal tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a fast and simple pipeline test. + + Use as follows: + nextflow run nf-core/airrflow -profile test_maskprimers_align, --outdir + +---------------------------------------------------------------------------------------- +*/ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + +params { + config_profile_name = 'Test maskprimers align' + config_profile_description = 'Minimal test dataset to check pipeline function' + + // Input data + input = pipelines_testdata_base_path + 'testdata-bcr/Metadata_test_airr.tsv' + cprimers = pipelines_testdata_base_path + 'testdata-bcr/C_primers.fasta' + vprimers = pipelines_testdata_base_path + 'testdata-bcr/V_primers.fasta' + reference_fasta = pipelines_testdata_base_path + 'database-cache/imgtdb_base.zip' + reference_igblast = pipelines_testdata_base_path + 'database-cache/igblast_base.zip' + + mode = 'fastq' + + library_generation_method = 'specific_pcr_umi' + cprimer_position = 'R1' + umi_length = 8 + umi_start = 6 + umi_position = 'R1' + index_file = true + maskprimers_align = true +} diff --git a/conf/test_maskprimers_extract.config b/conf/test_maskprimers_extract.config new file mode 100644 index 00000000..fe365915 --- /dev/null +++ b/conf/test_maskprimers_extract.config @@ -0,0 +1,51 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running minimal tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a fast and simple pipeline test. + + Use as follows: + nextflow run nf-core/airrflow -profile test, --outdir + +---------------------------------------------------------------------------------------- +*/ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + +params { + config_profile_name = 'Test extract primers profile' + config_profile_description = 'Minimal test dataset to check pipeline function' + + // Input data + input = pipelines_testdata_base_path + 'testdata-bcr/Metadata_test_airr.tsv' + reference_fasta = pipelines_testdata_base_path + 'database-cache/imgtdb_base.zip' + reference_igblast = pipelines_testdata_base_path + 'database-cache/igblast_base.zip' + + mode = 'fastq' + + library_generation_method = 'specific_pcr_umi' + maskprimers_extract = true + cprimer_position = 'R1' + umi_length = 8 + umi_start = 6 + umi_position = 'R1' + index_file = true + lineage_trees = false + primer_r1_mask_mode = 'trim' + primer_r2_mask_mode = 'cut' + primer_r1_extract_len = 28 + primer_r2_extract_len = 29 +} + +process{ + withName:"DEFINE_CLONES*"{ + ext.args = ['outname':'', 'model':'hierarchical', + 'method':'nt', 'linkage':'single', + 'outputby':'sample_id', 'min_n':10] + } +} diff --git a/conf/test_nebnext_umi.config b/conf/test_nebnext_umi.config index b26fa7cd..80e5a345 100644 --- a/conf/test_nebnext_umi.config +++ b/conf/test_nebnext_umi.config @@ -12,15 +12,18 @@ includeConfig 'nebnext_umi_bcr.config' +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + params { config_profile_name = 'Test profile for NEBNext protocol' config_profile_description = 'Minimal test dataset to check pipeline function' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - // Input data input = pipelines_testdata_base_path + 'testdata-neb/samplesheet.tsv' diff --git a/conf/test_no_umi.config b/conf/test_no_umi.config index 3a4fad63..19004b3b 100644 --- a/conf/test_no_umi.config +++ b/conf/test_no_umi.config @@ -6,16 +6,18 @@ * to run a fast and simple test. Use as follows: * nextflow run nf-core/airrflow -profile -c conf/test_no-umi.config */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} params { config_profile_name = 'Test profile without UMIs' config_profile_description = 'Test dataset without UMIs to check pipeline function.' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = 6.GB - max_time = 6.h - mode = 'fastq' cprimer_position = 'R1' @@ -24,7 +26,6 @@ params { vprimer_start = 4 primer_revpr = true umi_length = 0 - isotype_column = 'c_primer' // Input data input = pipelines_testdata_base_path + 'testdata-no-umi/Metadata_test-no-umi_airr.tsv' diff --git a/conf/test_nocluster.config b/conf/test_nocluster.config index 4a3fb0b7..70a11e56 100644 --- a/conf/test_nocluster.config +++ b/conf/test_nocluster.config @@ -9,16 +9,18 @@ ---------------------------------------------------------------------------------------- */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} params { config_profile_name = 'Test profile no cluster sets' config_profile_description = 'Test pipeline without the cluster sets process' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - // Input data input = pipelines_testdata_base_path + 'testdata-bcr/Metadata_test_airr.tsv' cprimers = pipelines_testdata_base_path + 'testdata-bcr/C_primers.fasta' @@ -36,7 +38,6 @@ params { cluster_sets = false index_file = true clonal_threshold = 0.15 - isotype_column = 'c_primer' } process{ diff --git a/conf/test_raw_immcantation_devel.config b/conf/test_raw_immcantation_devel.config index 567629a9..6db19108 100644 --- a/conf/test_raw_immcantation_devel.config +++ b/conf/test_raw_immcantation_devel.config @@ -9,16 +9,18 @@ ---------------------------------------------------------------------------------------- */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} params { config_profile_name = 'Test immcantation raw profile' config_profile_description = 'Minimal test dataset to check pipeline function with the immcantation container' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - // Input data input = pipelines_testdata_base_path + 'testdata-bcr/Metadata_test_airr.tsv' cprimers = pipelines_testdata_base_path + 'testdata-bcr/C_primers.fasta' @@ -35,7 +37,6 @@ params { umi_start = 6 umi_position = 'R1' index_file = true - isotype_column = 'c_primer' } process{ diff --git a/conf/test_rnaseq_bulk.config b/conf/test_rnaseq_bulk.config new file mode 100644 index 00000000..a98d790c --- /dev/null +++ b/conf/test_rnaseq_bulk.config @@ -0,0 +1,28 @@ +/* + * ------------------------------------------------- + * Nextflow config file for running tests + * ------------------------------------------------- + * Defines bundled input files and everything required + * to run a fast and simple test. Use as follows: + * nextflow run nf-core/airrflow -profile test_rnaseq_bulk, + */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + +params { + config_profile_name = 'Test bulk RNA-seq based workflow using TRUST4' + config_profile_description = 'Minimal test dataset to check pipeline function with raw bulk RNA-seq data' + + // params + mode = 'fastq' + library_generation_method = 'trust4' + clonal_threshold = 0 + + // Input data + input = 'https://raw.githubusercontent.com/nf-core/test-datasets/airrflow/testdata-rnaseq/rnaseq_metadata.tsv' +} diff --git a/conf/test_rnaseq_sc.config b/conf/test_rnaseq_sc.config new file mode 100644 index 00000000..8749a5b4 --- /dev/null +++ b/conf/test_rnaseq_sc.config @@ -0,0 +1,31 @@ +/* + * ------------------------------------------------- + * Nextflow config file for running tests + * ------------------------------------------------- + * Defines bundled input files and everything required + * to run a fast and simple test. Use as follows: + * nextflow run nf-core/airrflow -profile test_rnaseq_sc, + */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + +params { + config_profile_name = 'Test single-cell RNA-seq based workflow using TRUST4' + config_profile_description = 'Minimal test dataset to check pipeline function with raw single-cell RNA-seq data' + + // params + mode = 'fastq' + library_generation_method = 'trust4' + clonal_threshold = 0 + cell_barcode_read = "R1" + umi_read = "R1" + read_format = "bc:0:15,um:16:27" + + // Input data + input = 'https://raw.githubusercontent.com/nf-core/test-datasets/airrflow/testdata-rnaseq/sc_rnaseq_metadata.tsv' +} diff --git a/conf/test_tcr.config b/conf/test_tcr.config index 7572f099..e23871d3 100644 --- a/conf/test_tcr.config +++ b/conf/test_tcr.config @@ -7,15 +7,18 @@ * nextflow run nf-core/airrflow -profile test_tcr, */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + params { config_profile_name = 'Test TCR' config_profile_description = 'Minimal test dataset to check pipeline function with TCR data' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = 6.GB - max_time = 48.h - // params mode = 'fastq' umi_length = 12 diff --git a/docs/images/airrflow_workflow_overview.ai b/docs/images/airrflow_workflow_overview.ai new file mode 100644 index 00000000..86741528 --- /dev/null +++ b/docs/images/airrflow_workflow_overview.ai @@ -0,0 +1,2342 @@ +%PDF-1.6 % +1 0 obj <>/OCGs[27 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + uuid:b17673ba-5812-6b41-bf00-6734514c6aac + xmp.did:1ca32fba-0681-44d7-8183-fe32d1a56391 + xmp.did:69d83c10-8d4f-4ec0-af65-570c895026fb + proof:pdf + + uuid:983c0211-8cce-1a42-b26b-f301c39ac5a6 + xmp.did:c76e89d6-49c7-4d6d-bb98-fe1e229aa3f4 + xmp.did:69d83c10-8d4f-4ec0-af65-570c895026fb + default + + + + + saved + xmp.iid:b2ce2c5d-096e-4302-916e-3291ccba2077 + 2022-09-16T15:41:56+02:00 + Adobe Illustrator 26.5 (Macintosh) + / + + + saved + xmp.iid:1ca32fba-0681-44d7-8183-fe32d1a56391 + 2024-03-11T16:47:32-04:00 + Adobe Illustrator 28.3 (Macintosh) + / + + + + Adobe Illustrator 29.1 (Macintosh) + 2024-12-10T08:48:38-05:00 + 2024-12-10T08:48:38-05:00 + 2024-12-10T08:48:38-05:00 + + + + 256 + 124 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAfAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FXYqkWoeaJrbWZdJtNFvtTngtobuaS1azSNUuJJo41rc3Fuxats9aLTpvirz3WvJvmPUtV1LUIZf Oum/pQ8pbayv9HhijcNDRoQt1VaR2yx7k7Fu7NVVJpvyo8wTz+tLq35hOwNUDarpB4fGkg41uthy hX7vHFVeX8sNZktLW3F156Rra5munuV1LSRPKZxEhWSX63zPGOHgprWjMOhOKsv8h2mueUtEbSjp nmbXF9ZpY7rVbvSriZFKqohRvropGvCqj3OKsx0DWo9Z00XyW01n++uLeS2ufT9VJLWd7eQN6LzR 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 + + + + application/pdf + + + airrflow_workflow_overview + + + AIRobin + Document + Adobe PDF library 17.00 + 1 + True + False + + 173.916905 + 85.569281 + Millimeters + + + + + MavenPro-Regular + Maven Pro + Regular + TrueType + Version 2.102 + False + MavenPro-Regular.ttf + + + MavenPro-Medium + Maven Pro + Medium + TrueType + Version 2.102 + False + MavenPro-Medium.ttf + + + MavenPro-Bold + Maven Pro + Bold + TrueType + Version 2.102 + False + MavenPro-Bold.ttf + + + ArialMT + Arial + Regular + Open Type + Version 5.01.2x + False + Arial.ttf + + + Helvetica + Helvetica + Regular + TrueType + 17.0d1e1 + False + Helvetica.ttc + + + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + R=36 G=175 B=99 1 + RGB + PROCESS + 36 + 175 + 99 + + + K=39 1 + GRAY + PROCESS + 100 + + + K=55 1 + GRAY + PROCESS + 141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 5 0 obj <>/Font<>/ProcSet[/PDF/Text]/Properties<>/Shading<>/XObject<>>>/Thumb 85 0 R/TrimBox[0.0 0.0 492.993 242.559]/Type/Page/PieceInfo<>>> endobj 29 0 obj <>stream +HWۊ|ﯨGk~yv-l,Za9c#K] +X BLGdfDE{֙7߽5ř͹ԃ=u |/x|55yo bwxyٛmi%_ gsy\%wCcoh1u˲aͩ=MkY0S`VL.xLxY.cYNtY7"&MLױ|+fP[FNd +D~02u +\ܓq)͌ O2N>ͥz,)u>/tnpΣʯ99y7)oX$:JMԜv6a8]hȡubǻ Pr쑕̌h`FDtݱ.w 羮FP#0*P-P9W40tX*Oeq8&p@"EElX='$jcGk6ZpS|h.ѝN-3HtRUYeL*J-`LE7".1nSS5RR B >L2St@Бs'-BIXp{=@UY+K~fs6U~ +# |i~נ5 +߅vʝ@ॡ$?.H~D*## jҏv<ӷ\w|\AR3HFeoy*TQk(I%|ꔠ\UR7jRF'~ +{ 4 cBIɂ4"BK ֒S:)1Yt B$c`EL]x%r=h(& 4*Gu~.8t\Sku)}]RҢTגµrBWq[]xw3_>BY'QKjG0<9Uzle^I r(ξB%[HF$En#o7ִёh2`-b9j-ʥ7ЧDr l+X1McourߑۃEcb:)Ev#9GzIOZwMpcnJp9Hjۓp^| 74gx?3keÔPLyyaDGJ_\-W/jPv 0N+#IB@񕑏ucq 4nثcyFdȿ^d{U.HZThl\${"zۼ>ǀ3ɳ4YZ4_GS +V=LNALoω7&bw~T!9:ll]qI@9!Vk{P(7m=@"=5}@,! fi&ϐ}~ [#sp>/Έ2yߴ D)ڢ E NQo7lGF:J󄆔 l$Ovß7H#&?Y aja?U+9 m1㏏)rytj0wDgȯsԢhF2_u+"H|$Jxq(qX)u)PDQϻPA.5W+,`*(,Dh*x ǘ͂4$ (fQRb~Oܿg.{O +w4}o4/3=]m7{pڷs:m4$!I8CTĕUu_>G{Ohq8cnWrf?Y4gt}|$:}H]>2:Bvo>-ddDljJ fƖH?>ɤUfKT:4x3+H!kפ>O%Z2 E4pږG>\ +'5̪@z0L@ႁn8aO PH(;p5ج.Pؓك)?5- WЃ,Nyah$ܓcn.7x҉gƊVsu0'+,)ɺHӺdvzjx#40yHVYU/k0hbH./1- +%&mz@cMFXr_E,@&Γ"0E1Y1/aWk!J:+8*m/_̚l#&q5==CzP#KIޒT {5ΒH4gC"/fm/0=6_h6 +mN"8ِ-as?v>:AgJxWJ>}~7Up/?ΒsBcԸ/fHȞ~MN; ш嶄e"r$ mЫ tԁ0vhS8|ey,ͷ/ 0 ]Q'[EHbSߢ +mN !Y30)s1W Yz(!y=B1ހq8F(*^la+}S YUE4&+Yz9 Lsaՙ->isfK-|@$h'd 2\ Hi d)`p-4 ̨gxi9+ǾQZ@_H181[:>;vr?ޫ8'+؂Am׫\|ys:Ns"ʈs +k. $#|, +A"y*`!zW~XPrbLKY;| ~a|aͯÚ )?YXݐ]dSTvӛ7бONGѫ_Sunfj74\4we߲prprdex3Z}ؚ۠m$s%+5,܃z99;re.θlqpX#s# f" "Hj )d]c6XIT;.(0zcj!>s^Y(ٶꍜ5` ezaM*UWCEQ37VrVr+@7U*uEIo 6,MH dbY;UI'?@zwJo.UbIED4tO6iwU~|@TkLļGLϠUf~3SWzc>Tɺdn$IJ2]Ouy*5 duIFF>q뤯`B4ҋ8"NH1@> 9Z˟!ɐ{ G*??!s?'fIxɚxSoDm ~vǻAc]1zw8/ t*PJ2kG bu"MbPo.֑uw5xTC#] ik"t@y#ƣ!*H>a=;i4c`WZnSkjƛ:=ЎM;}DMsK/8X)ص1ҖGu=ur? 3^]3|CGyB/VOIschHˍk{9nwF~`%|at?/}q|9 P1db蠌] +8ohT.:ן[jxw@5vˢbe/L"_>wP0}R.^Ͽ{gxyyy:cόcdzSľ2Be^֤$ȔdWlT&.ɼ]&* HQfeRE27ي7uIݷQ>:di튴XI*ȵC[[N;M\SkdKJ[u*1442-!.B^gCanmmC>=5wSemy]5wa o_̓}YkF2>A6Jͻ.3z]D@PWqYuCZbF|P KuUBncc0_=(V!,tH#=SfaJHr/CQKlK^gk~yE2ֶV)2#"3KiSgw{.LBv)]4rA_ o>Ø1U WHP  \e󿗟Wo`E/ˆ&S(俦\^Moo)זr]6}]ݻD{(:nQ]s=чF V_뚈%PBrXb)'f MktT .=Ԍ7G+mu6Q)F;6Tsz^<=ct +Ů=vmvࡧyu뛇1}L Xtև>\@G9HIx|hˍk{9nwF~`(|aDKf,_CTLoaCtP.W3^GWp)}=ٚ(6և t} MzU70R%y!p?ogcy\~#lePh Ew ,U>s)ZBO) tbu̶M3A:P"+(ѐBfteed0RR|zUB͡{]٘ db`$u׾V8̂xLܛ%5n*NHBqjm.d5fju6DTk%'2 +*3C3m +bdrUVHZZ,NbCMxڋijMJZWd=v+AO;݄`g-Oty +6> 7mg?75V'E3e툹E04yȥuWS[FqˣXq_ TxEP)4>ަCh?9R&jlԩ&p6wBF @[1Lcm3CHj(koLGT*xӪٰmr]ܢjf6(0Ij! LHifbe;AHSlBtkl-ێ#rqSK8cFHt #)Aro\M[W@ͣ}ը$@yي`;2uWpV;Iypo\'9JM6.0fVu66xTk2bY^<ޙC,.\[~ҙB[B)xrFuuR> vM܁*LgMp:gw%k~X+{/ejú&lEtQȍB*Uq0XoXkS(`ZDdo[CXe_3 &ĤNr*Zy J]XmK$sxbMP*PH ByHi:!nQjr&&;M@AQ8D54ExT9' +䏑D\mP}NKJ4U]PSV hLƁ-\Z+Qbnr{S*n8YڶFX"uz]\[wq9*iNGUl {5 8bTJ9 _.+鞍d[wQkoC@ҭ@E\(=dY~Mb+ڢi17*g֕]A՝kWQ@Wy0' gS#7h YGo]VLL6i:(Ud"Q!ONVB!t vXcBLY,N.1N􁘎1@kE\,`Uj)3Rv$KV*j= !`=ѻQVW3fW uMRI bs&u8 ڈ@ǎ3EG,`en#\~Js:H8*9 N2DQ]+Q9J?BMHf}r5bP- HQYZgX2ŸR:$V+YI[f^VT [-yzl;1K͸|ڡ=R+6{?l *ߖp~HyF3&?(ޗ!ҎTih lA3'$c^[E e mSS/St2Voty=)bїibl52>@fqnJ% 8pW~͗.FP.UA@JPc׃׼ x>Рd1Xki=8ug^W?-VˆuX6]IOO_]zm%#Q +x ?lhZ(X:~ꑰED)-K3I5HE v$qH>Ȋʝnق~Lm#(Ŋ{jkj7l|ג)hǜGǤ{a%GKR__^ّ$)g,p( gqVg"$+_|쩝k7 0҉nԷKgkԬf'!i}Ruޱ~dhy:Gü9"H"!eyZ ŵWѵΰcpWd:B4o tG*Ez'%*c+$ATPd׈Z֘O Җퟫ}R:}6JQdxtn2*s#H+^|X~-u4;@tڳ[dQMk'8Th땕AT5Iϵ:z3|y꾝)jL!%H +ӟ#P54nӓ|0vc/9R=ɵVjKBaY(}YRi[Y"c|uYvCh#Xvo; KFI"8vo{Xv5GX XϮ6WSR`"tG$벊h1Pz({U*bC#EiA(YB+Y&hǛ+pHE=hzz +?@hL?S;<s_)R {5e`wtC zo됛s- w{X̶7ӸS|d鰏7l`qkJ/V=&&8{Ty%37SC&ƌ;IFbg^IEuAR$ۣ'5orڅKurff8xk~nb)owQ${qnK`RaKbV cM8Rد]nktI^[S~Rad Y {1B );! 1 zUÚJrUף6T:m%9b8= Vw˒SũP^++c _c^6APg7]j4T'=ҘVt<8ž$n*NJW7NGvkfdt;j,7ѳF޲$ea#T~uq9m<(.abv$T@ &'4xzm*`vRd/8W>(l|J]z~;8ltYܰ.@J=73vO k0|f' F@ wd04qK~sOB3sP FGo,H&-Qh__0ڜ"+V>w"h_mdY6dF 'BtP[~;ޭl ʙ a ǫ߭ޏedyZ8O%(;P7eC(+4]t h1/JU.ƒr< OwMVRBuA/s1|N9ŗYQG.&|bUI}9L6wc_vP7V08i>^YTZZv]I^$᯻r 2C7UQ*a`pF)$Dۆt ԋ쳥 㛒XeqMbeq"K >PF5K۰f[p1 +8qZV!T0%4Uf:mnU#׍Du +]@#8ޔ7^ dB7 Peg1!DL_oqY']T]zh؃h& c$`k]5"["?삑g DnYMK%v[S2gj&9LflAŝ%2WUtfv)謁4$7ꬥJ҇C@0on(6NV15nL=l,> + لbgN\m*Fhm8}d043d/ i^[yHld8D=^Sʛn7vg s<]ije MʞhWǺM4r[֙7bUߙ֦¿Կ(_׆y"cJGOT3u..gqE]!eXwF&ȗ^{n3++Ut.b9YI!@({M1TI3U"g^ 4T]G:&g7f)4i% Tcd/yKjvϊ +vh#[r{МTSwePR%rJg,R ܽ@[B7몰wD-8x ާ lgo r|́GA.&yRIJ +Wo]N2j= $+Lڙl/2r3vt. +a V)B\8Vg}~EqZMɍT -1#%nv~Ds7+ GA6쉔}6MRlqHy$D/ޏ&Lz0 +g]V +Gg}``͓WTKcoI1q&?19ҷC!imܮ_?m1cue :dZh(~9*uPD8p!xIa۔0`iC48[頬m +~HUtJFjBAp+tn᩿kऋ9oyI܎2q@KWeb4R#(c;)y@t*kFz -UE/\ñ٧Ky1ZqQЋ1Ysu˘YC@5!q_il J!Vn?⎰چpJu=qTVArCͧ i=e(! ^ڃdj"J5PtpNPlV#1>XS~IQ޾ EjyH ?,}AU :M;\1J/]CP KCe?|Xla3jt -{ hk?U6Waq_ml,5xaq;TeIqhFCMjT lWcޠ~B`J^ez{ ra7MO@; ̆lFC ,'ddzu~پڞKˆ8Zqap.#tQhhD\WgUͺh5fRH-![²7Ї}I)@razR_xd:9]+wFjY8.މXrKU5&1v?[*4SHW#O8n+_*<nkؕ_X/4 {J>E/!'͘dkڃ5<($e{u3'A-@W/EB  ahipJ?6hUrsK!;5]-Ns;*|s!"#Yd~qևQm"+rF2O$Fk5_a UT/)p!!%ƭY Kd*€1i͖Y~~7墸rfDퟅ +8j[7F.R9\縎dǢxqSP+)Ûzr`]!VPސ?,[3ը#TcM؍S.jabBPh_^X\-gB'o K)G>% " +lMR1_qyif9$׵#v6 z:pq'Aj8[3W ׺!ah.џ: f63M*~:*ǣBwsa86vG1{[]?IYFHk[qKy&`V Y24Y =dށg7wȕ%ۢ}9SjIQ݅eͦA:Q3W}$Ir`&$R>x/>lq8]T$3\2&1$ug6Z.^A +DŽ"gpM񇾓ɅV$#S^XJ볬*_u?΁Ruz%#0MAJ +Fqz$n:LG諬*@qGb5!06'kf} oyxu3 _*AqJF}2Xt)qY@/C~w†)H[vpyo 9I(y](BR&L\zg+6/ti_5NmW!k +A@Tg%_o(*B?oo<*Q׼OI2#aFLe'xz?O_hYrtB07,\Uip~sU6NZc:vdy!T0U>յH/B}y$[L;,ѷ]]J3^#X `Q:$&ъ+3-Ì:mAS86(g[E%ц&K|f_B+TTxL,/)EL6!2)XrӖ/K7Xnσ>d݇/3X߄9Oc!WMs+95AɌ'nJP+GSNbdK~[jgs##oᒐjlЭSxJHo)naBU;,6GsPb }1=[!yp'Y\ !x0#md?g?_U +Qp!9MYeIh] +#ІLNڤ +mW= +r$L٪r9ĺ#M9SUO@A21X˱ΗlmϗBѿ4,mTu!xcY"JM":LZ&/yl|{|w6PӪ` 9Ѩ`lgO:N}~5N1/;jkF'f`UOH&ju [!k ,n!ޫ;,[\{8A!oYjFrl65hd5,Ä$AͦJqMPy?}YRZm"Zz sP-pE FB= ~IZzD[+[_sߢlj4.pD,7ASN\J8$ۛW{VL梺G!5g[$txcLZ4`p坐|-8vԻ) І:XjҚYϞWy5tdjG6;5~5RNgެlzr1;y u{Us:2AYyOFA#rZʍ?4i9N`y?7G k|dHZ*6Sng!ӕ,CZ .kDJA% +~] `ٶLR]B=. %Zn)U4\KW^߆*^ *oΜ]~ B.6GTl4:->q?Ky$;.g[#|J*7l "bL}ѯٿ$0%%mQV ЎJB#M)\4 =T>.CBVm\TƠ~ry.~ٗJ3;yͲ{sH XJ jf-ִ@2{ͷvf~qc>:7k t2<2񥙃mq1C‘ j +De @!|S5,cPAph#܁n|>Rl5InSDŽFB|ACV$¬C }Z{a]4=#Y-T+U‹^jMWiMɗ&)ԡoRRQ|KDGdp:=߬jz :>M RQ?s|J >w`-g`O 1j/;-r:HIѬ9Rw6 + >Wx<~bvx>"0vj3X4R0('m5ߨ?MUTcKmgdzX[sjeiX5I X-Rz+W}/B;+g\G3F(:( Y T,\uY^D5=d`k Vؼ? tL[MM7:|NpvN s/C[;*7&d!u|XxIܚ߰Uߐ礙ܺF-wl#dx޸¯e,nHQd5IY<}I Is^&u"C(![Cύ +< 3UgELCmzVyPԃE(FpK$~&/HLO"T[{ <_&t)>]A@K:pCϯC[;j'%)|OU yGstQ_ĮAk +?[ ([훭TeHBhE@e?z"y=Y@g4faQ  + qm)uo}z|E}+tȑiO|uudkFd&bM# :Hfw&E=B$C@LfWKpC + ] /8Y.4})9|P~QSdEY[ՕpYS@ؗ4-&na<䌮E +%wimҁ$)V=VI+ \^洔X +($YL>*AU8T@Y{Ѳv UP[yT;%UUy3KXH<4\(i>?uJ f(/MG:vq G]Rtu'#*"֝&[RNJ*iĶ=Cܘ$I!bO9~J&JL}9.1([Nި _R:&_HsgkR5r*Y!bYh\SZdž8>MBL跲5)C+-AWJz]2>\IOSJƍ}XmkdPzٳ^Җ+*,hp$o>>aY1Q=طpjɖ@.#S{䶮:nJ{j᳷s]QUͲ:-z`Q‘b=vq!$Ʒx850UŀK2JpHڔ7x6' ^e]bc|O+ (7%u[pʶ#v(rLdw +Edf~Su2]<j1U*ڭT^ [l%èعN@R(v?5Jk3`xbG)ݻo~=Avt$vP׃4.T|jnE*l`&gٙbUo~_=f^_?>^0F_әMcqosr5O;ճk]cG^w޿6uk4?#}u\S_eΏۇImtCl̎=Ϳ-1j +{]w_`yWNDk1ټGq]PI,Iu%M~Ƚ"h4c>d{WZ={z|,r8HxR 1+-r{6?Ym%2>&Mc{ Ve6i쬃ʴ%lSxCP?k &; +I){a]Jx'}BjmUSլTY܁>Q jȖJ~L7j[V#wpRhwiZۖjod4/ o;-TT3!{vǠ޷{,e=*u^$ hQ 0嚁mXwjG+4Np޴z2~.RhD7#S9ܽqQyZits3?Փ˶~K. g[)2}лQ7mldKFm(ĔT2+ k6I1>YtNiF<{tmv-n7";Շ"DsGlD ;yDM]N'9W|,WE9"dy?X27Bqz&BHVDm@xmň is;WKgT(#m6 Ili=BE-*% +pQ*ow3p.{A5(mT&ke|d@^g}]: +yvvEp]miguNjV%AD;5+fGȊMBX&DY-{=]JgXq^)HCW/{F3I9]Kշ$H "MD2]Di1uR oN.a?MO,|G=fLo Z{P~ O$shnȓCV;<8H9J˴w;nw|_Kޜ +QfPA!>&un>fPK4mHʷ3e)<:rǥkp'DkbGgnۑVV]+2d)W TK<:\S$Dph@Ҧ"a[neKiҫH؜-0D w j<96FV*A-r5'N|J#՝YW u\8E մ :R@oO:=z%}D>l&:lcӞ3nj(f;D xY֏Սha Dq}Q,8vnC&4O.)cϯa [D7}Utpt*R.!eXU.*|YO&BpM,4Z'-)N1ZjS4F7[f^/mmZX緗6z9gG|˹]BoW}{Q_ 42m1;Ebӡ,r3΁)R7L!# gKV@(n(Fe{s27)_뮥zhfְBVn;9ķ]Wx'Z#^iލ4oe4E\iPGZoɏXzRڥV2#ln.m}\ ,p=$&E=y/w4߿kR)Eqs%o&LH6͝z,q] +.`D{o@b/d4LQc!oh䐡^e5hQAC f%5ep[w&~&N;o|`d5?_/!fm|#.T~hL#)B{SZ C{]dz@m.LS$b+ $h4LTGa7z}L"EN " D־b}4e]p֭{+!j:S<Z<7Œ+GݾWҒAIHPrgk ٌ{@ 4ЮJ.sa}DilSt d%:6u +#Ub.~T@MDW bEyk sm&OR\M}ŰVDlA +!ʔt2XEh/} h׆&z?LǨ.&jb3+֌n3 Te*٩flPof5ADi1EZ@%E&z]7l?[Ralq â=q4#Wqƒgw=,kbm'StnyPg|!m >h![~!EڂfM^Rz(-8g}7\7V\ral*r̈}r@#+7!]R1q1Fu&1_%/%̈|,= +#)Voy2\kkc* eޢϽDc2%lg*"r:*:) tvTACQXB$u킦5 h1,H$ZB*Dݗ#/z9ti8Tv*R I_ +6[4R]ŋe">'GF̔ ګD9nWڿC*|w^Iź%`(ޮѧk}QEKw +L'yR,;$O +hQQKV2Zj{;fxx ;ȼ&a&OAbKJ2$KdxO~Do&o&^bkjv\#gdO-G'Jt&zK^f-^Qqv~~JZ.vD ̎ =[+?^] *[x{-7X+naJ?ez"QzMݤ} %y #%(p'4n~khJ'guxS̔aN9K_G4*{7]yyk%*!4a]VѧdySHRf{FCtT{O0rdzݒg>ۊ)_NPn8cWj͠Tj +Zct˰ ij +J~Jo&dom) 1;E젯_nx+JޒMڛwً7MHanĨ〪:UX/w7ˇnk<b IJ$<|!=D %D[d:0[R|?8HT<;N$tP"Uք>w4.>DiZu,remMvݚrx[orzW_*:iwY0H*uZ'""7mE5Y]AI#[aƭ{j7_T=h$|N!4x:{9(h +)Q+e56Z[h5u>YFu Hrm=5o 7^SLΔ22(VP@EQ| '^s*gzmhSʽ^:oޑZUqfci%k+!Kll#^KsL^1.r٥zښi1DQ<)$K;9RIic~a+dÐ *x XCi[)=[f϶y+\V~ _k#$~CQWO>!٨a&)EQh# c۶`1ex~Q 5?%9#{n4 LsdiC&*pomّ ⮋<4P{:$^~!M})eVx~D,wȾܥA͠ n 昉|.V >ثAg*Wא(1ʺ}ز.`+J?[0 ɵ( h/_iKkK . (1p-ס 8b<6+{݇qj3n<\KrQCNH=t("[CZDuEEO_;UxW%K+ʯ$Xjr Bs|oqIDd^&XurVrkF AETSoQkQ>כ h׺hE!.ggk%Eξ&Bw7I/ZL3i_3~1E}TN;,-R'sxW[yv^_D1== zOݓ_὎)OA wm?'L\u6\2˽Vum< HE? ]gFC֮Il(]"2 O +aˎcI;ɹM ƃ6-FC33kR5(MEՁwe$ Ⱦyz41;l6Z,T&fSB"4b2vԧ8FȆ;^sCqņ+))G;l]V( + Vƫ6SaW*ǻumv]ş qD<|XEYSa"i?cU!i i_ծhT&1h,_-Zb *( +/^LJ?NtBs՝Ȧ)p5s97jØr4W \{K]MFI)7ЪjjIF`b%KTr!qM~t0f[nDyq- g=Xlѹ )a\z)A 3{}"e(!οDibSO To):֩x*J1U +nG`(5<#68`շk0:EƮ :>^b㽭>mYS[7o`,dElj@ݵG]Z+ŵ-hJ/=D"JwO +|g8f#4Nzdߟ99/3w3irFֽRz2͙S;-xGsin#e{k5t}F+ZW +zX?FC/" /soWw|XM}T[Z«P')g!TuZ* &YB~"2@fUSπ_+}eUY͡YwkiC>zrki*Sh:R.GC Ud ӕȉ\ c 1 iJMۆq3)9 6l*iKn{)6H=X؈a€a:#h1޽M ɟ~j҂˹J]fhVBvdy2^=?CKCef=@5IebmWM[(]9Jy&H `)8R:J$WacLd%]sBJƙ(ŸC4Fc<%RSk2h17^'j2U39INqtr:6p+nrhL; F߫9ꮫCq\9r-"rCOW1[UKUKm.KY0 ].HIgR +0pW'?g?orL{R>裾~g]~Tj&Laɜe8*-c?5b{bKt +&ٹqI !~;3_s 7$EӱAaWt 0\߸)R7'qQcIn+M%R"m+kN%Le^Zh֧6+-Z#c׆otц{=Qa$y2cTmU;FDǘ&C r''xCS T-*lt9^Suw4beƸ.功i{Զ]}Ӽ1wRf7\ʧ;Nt @MtGY1̠t1RLvav\M6x թpq(0(UpT*E2j@3i b2 :L}d̙$uu^&ʜ;JI@%3-9[ʑSD- +V/I6PzN *dEXK.e]Rs6O7AqNşTO-D(fk=[MgӉ[g.uZFq+diGȱ<Ș FpH s<62xGZ2+w}zP")jju1$0Ag Q]. !e.d+ i 98xB}Pz^*5=mTCQ&502}>ۭ r`xoSo㽡B(YIWzil[_-ФEG=u3^;z6I%5ALJdNfjsa4y+]Dj-9*v vq2 lqhM ]k|MUzx|3XRx;8h!2 0@ꏦ98Ӽ _9JVЈۭ;3P;V}EIC87iF9b oU:^Xpu endstream endobj 30 0 obj <> endobj 85 0 obj <>stream +8;XEI4aP!g%+S=$l-s3&Mn^g6HjhXC8]Us3:;YM=FR#di<"b!/#H(=#3KWDO*g6:Q +ikHC2gE1Kkb;,+uo#$$''m_3QVZ-I./C+2pr5i5TqXjtEmq^&9LtJDrYQea1c_i3_ +*nZO+!Rc1P_?.l+db=Q=#8W9!hXgXhgl-n5*Y-PW?^IWXWc1L<9e$t(:4Mqf)T.Xj +4+n!4+&MoM!g\0P/2tA`-;E?+>k +X]Ta/3jNWF"W<$6*"\lbkn/VJZ"%C9G'fTM2ASCN9BUi4GJm6$[qQM>`Eg_d;7VmM +U-78h$41:`p2!ec?^1Z1(>cam7)sQM8oM)E4YFGL%u[&SqbN?8Hp#sC;uT/jYo`rG +!<<'!!!*'!!s"3$1fX~> endstream endobj 9 0 obj <> endobj 10 0 obj <> endobj 11 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 24.0 %%AI8_CreatorVersion: 29.1.0 %%For: (Gisela Gabernet Garriga) () %%Title: (airrflow_workflow_overview.ai) %%CreationDate: 10/12/2024 08:48 %%Canvassize: 16383 %%BoundingBox: 6 136 498 375 %%HiResBoundingBox: 6.9267578125 136.123687744177 497.3203125 374.553863525427 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 14.0 %AI12_BuildNumber: 142 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 0 137.024773044061 492.992801317298 379.583365716733 %AI3_TemplateBox: 386.5 209.076812744177 386.5 209.076812744177 %AI3_TileBox: -156.503599341351 -21.195930619604 626.496400658649 537.804069380397 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 1 %AI24_LargeCanvasScale: 1 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI17_Begin_Content_if_version_gt:24 4 %AI10_OpenToVie: -13 455.576812744177 2.10441133337193 0 8101.55287728424 8101.29160120465 1500 828 18 1 0 6 58 0 0 0 1 1 0 1 1 0 1 %AI17_Alternate_Content %AI9_OpenToView: -13 455.576812744177 2.10441133337193 1500 828 18 1 0 6 58 0 0 0 1 1 0 1 1 0 1 %AI17_End_Versioned_Content %AI5_OpenViewLayers: 7 %AI17_Begin_Content_if_version_gt:24 4 %AI17_Alternate_Content %AI17_End_Versioned_Content %%PageOrigin:-34 -386.423187255823 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 12 0 obj <>stream +%AI24_ZStandard_Data(/X *K(DJ{/s OKJP:ޔl*N$ d M +/Φu$Z%ybr}F0. 1Rb_#*q!lc?/r:poosӘvO" <2jYtѭ|1 58,S8:5wP!=[k0 CǭAQ4cou )`'vE]lba`zc=``FrQPty0xvˁժFD,K+/ɸ +~ K3r6j0.E9ѥL-؃u}Z5m}ɥ?.?~#1oso\iܻwocr58:腗[sݵ? PzԤ.OT_zw6-q>7ӭw<"9Kn<{^:~}d/ώko{}腞镞꥞ǿy___] ;!(#H%h')^`b8dXfxhZ"艟x(b))b*q|7~#88#99#:&7NzGdHHdIIdJ^%/{_ a)cIeigimr9Yy'? yxgyygzjt~(((NwӞz闂i阒i院izhG7D4$O;O}ifih&hz&7gYc_]IHGrRhG=)^E-a~aw'X# 3ACu_QE:ߗH|#zGvR/]C9rq_4ɋ$EPxhXQEQ}ח~w~gC{ vo=9GCI[kɕY^%9a uK]eJ$JIIIdI$I$IHdHdH$H~GzGv&7tDGtDsˑqQ|hH(]"4D Ͱ p 0 <ܡu(x&X$8" 5~W~'~~}C3#= =50W7m1mM` 1Cc}g0.ZշE I\o^XC[`Ml/iW'i1I)m0G>j>ENxȶ_%\>s-nPo?I +-vy}]n@qc"1}=ȿz{} $-vy!3tjI6Io%)X1F[.,{QMO>׳pfjx_1$[HD7{:' k0cbAi (~8zAAol}{}?mPsǁb+=w7pE>=ltCk.DVuÿm ѴKc;,BjUN u ]ҪaݶUՇS)鳐ڥ2n ]׋u~=j`: ]ؔeof~eOMB}ؿŽ}|w;P;7-_=hG@ \ޖ}[piW;15vDԘ5 ~^n m ޝ[] XQzUFA^D i<58Z0 yԴ \̒& j'T9Z:j[Nbγ +hPJP +؋Θe%&Eqeɵ++TGh=P@8rndڥCGFܑ $ =i݁c:̕H7Eq:oơ7, t?a T +F^9Y0u#䠳ʖ)wdδePƑ ,0Aں-? +B4eH5dv"6J9? +$g4c][V Gv2Ѧ٨iduL[QIl%e,b:GbJ iK!4<Ȟ5qsPbp0 mߟPiIš eOK"~@V`@q(G B*|rŝOy>Eg}aUG $[C鴀fa˴rdGǘEcRFZ1(N`R\R|L4{ \f95@Ly +geJ$&i֮4XJ%[6b:wQI,4^ə`{- -G$GƙtV,r" x%1̧fOy>Qcu->P/'pۮoiJy~zu,kf~z¾֯k &r{6HZW-Zz@Շ̟\?][֯u_ )=7~ ~L&mEIBۺԞܠ,`j5&6n<6cOg_8U? I_lPw5;R/^> n)nU2WP=j]wo]6w= 8Yvg9Yqr?~܏?%o{1~s?_T+{+?|פ*ꖸίo?p*nS̱߄0{w`rd9voJ>̱4`%{,ƟSP-i}7|r{*dn~Oݶ&v99]S2'dz99?q뚸v~W\ @ M +'[bk6c~^a+yuV5`eV&|zz T+Tu5%?t]gbm1bKލme|c!gXa݉oY~ad soCnx+ziIHX)i ß>8Տ&\Ǒ\ا9;lK1a?l3QmFnWۏmܟA=B=퐧>jKoj-$~Y2nK5@$UȜ`rD_uWzz7^2$gnim1 +9n;w:ەLl0VuxS o7̭RyۦL]ȝGXՇA)=9::<x= ¯ ,dB6V O#l7WgS{zzNkjո Ƙs^+00su[Tqrں+ +zsϘ[wn'i5^fznX_Z5>el`Ȼw7)S<awosN,'m#zs}8cO9]KzӚ'<5?˧A +ǐoNs\7Ia o{ xnd`]%&uWЁ2ʻ%ϫ -V}16jcۏ^X~?E^?؇]؄K_sˢ `>]`܊ Qk Z5ؼI1 ۨsdz}:j,0R|;ͭxn`d`[ލW [פ4=chzWw-apzcȾwkm0|/cߟ0-$sa=<8CyLz@Ԟ |yz۔ܾð=xWRY]) n^"bg gVl6Jт hWāȶ>FV bm!$U&,ϛbdH"(CUU1s6~d1*Z +Ee.+Y@PLJWvHHWPzRͦYD"o  +&Eȣy0PIp 6zpFbphdtJ769[!z:\|]ܪ!E>) +gxZ83{qd  t.&23dC2m];<%m,U䢐\qȂ c@NYp33d.ʘXPdCP"f'c!H7zIU>dQ+(uLf+ +ZYLl(TujJe-REo()Ę,x"+E%ʪ$]l$" M2*YVvjK Vk3Om + I *PRp3v5ڠEb1mhɆ.v#Ta^]Ѝ6hWl!ҮN* u!?DގJqH+LZ1{2\rZr`r@m'# H)*zVzIHiw,F]PdClu:}(Sv2\n\XzH6nG&uheTI6SKCՅCAeR +FGxm"Iϙh %Uu _v9HPl§ `R!Os2|H&PE5OE9A&袑K9 pЎMd8ǧrA# +R!/ (:>JKW $ +$@ܚ"dR2] F)vs"V(+f:rUwah.d[dcYpWZE;P]΁8#39#KU-R$86$dQBHٵ䨚XiGEAi0 |3d D8af_v8 ;( (P/TDzd فIp؈> yV?n.1 ҈%.+(V qDԈQ;^@VPV.ä?VX2?YAUTbBNdJp g":%@] d`VZgNEjtN_idJbU~._ʐb`dQd +L40$#@l(w#PBh9(`!t:I ISF!ŶY!Bfa =4ވ<0A{#&eI)9GY#Oc +VS@Q]:#=y>⪝A~ h7#%TG ű-HCp:(a&֮qtfg F%.]ttcvGH\5% ?(7ˀ U(*֮+XUV>t) + oB[>*LUxDeѢVvjVNTќR ~"yR]|QLZ"vb%qLLtPj B!? 9 df̴+)8Ɂ V[CE{ztCP^{ +Vk„жC:90l10!U?66vU ٴqW*Z"s~]P7 +%%YUp`Ѯc0(qeG7=䬬O8y)ek8&6[ 9^"J 3cadRRQ- !bqVaH\(crX5]hǑ'FL[&>Gfi82F lJkFHiۉ?tSR~pLf!jY"HUp0WhMh`,e"D#<~3<2NLRL. -[5mBAB!˞v>X!L_lV M&cYkaH&d:H)]^If(53R!GA(ȸFFI#+AO ݠ8ǥ= kҭ#i_HaXOŌm"rK3'2A.BL5]с)~Qs0̩¹# ׺xC 'BMa;3e`6jf> +"ٛ!bՀRviviWÂ).rLBhL6#4vJe3m}dmd 9ʁFY#,G +[];ޣW`@ ,R5T ]j'][LvLI:PE@@X׮G'ARL(=5:@J"ѻPX490< +LaWIpg_4)A(F][v̏MBP``3H^"[ . I4 +"`:648e,-(3jW{f욌X!+z3 ńPuн"+KTp,FFѮ\0dt +xDAJSyfRj|(#k- +4ph pҚ( + P6LJAwj- +n٢xȔBrphϓ$ي$c]_I:RiֲU@źNVT!UU=GvI2EK!FL42xnOrɢvSA U]G!hN?V&/:r`ݭIih12$TIhu `9RY|(륨P̞I' x*i2BSݣ ! ZU厢 +9 +}\Ub uDt4ARN_`:J;vAd֘-BA`a20X[pgI_!|@FʙEZƂVWڕQIUd53I؈}2Z'kZt,|(mS^' fp:^ WfYmTI'4G*ڄ8T9TIZfdZ¤D.eue!}OeKWABeWh;iLfɦ]YXYUFe2K6UeUYetMC"! hC$Fυs# hd[,6͹X.vv>|hIЊ͐DC )RuE e8_B =.TQH$͙'8lX b&b4kF:J}cQ,E#d-NzK?*Q% !FNɁmdC 6!@&F$a b013ȤEY@˞\VQ.{rY~Y]{ҊG._bm 1a [Y2P+(^AU JJΆJ]KvhEЗaš(BfD  G:92$FBF.,$,*"8$aFRF J (X7@eQW'w{PSS&C2mNM)E{mM#jۛhHIοU)V֔1r?FM a==2b`OZeM+(aV{WE;q>O ;W!˚^TyHHG% 1'7xOY dm)ag#c{gK>Ұb1dք 'Tfg3'rfOޥ @-O+mr1.ѻ3tYU+d%uc!j *Ǻf[SN[/bC3_C+/cY^ /Օǫ~Kiת bF,^sEv=LB#Qur\ 8&&m;ys)8 6Y!<&!Y{u3=!ޅqM,辒("'U]NжMjmڀ;Zʒ凌4wZ8?nl>I?ʱ.DzƤdO]P`-;[%2N(Oy;,^c5`9l±1BB|WI"`30q2ʹvEO-ddBG$p͋׻iBup6ĤCuǨLK)kg K#WeTs"M#TPfSzw kR.-'x 'R8f' 1aԕsxSJbG7~ $xGJ +Hn$vzk\?境d4єs'얟0WDAޟܟ^F2SCTc{_J}18cjd%%p]1/a31TCLf l}AG;_355A؜hs ڱN2?Z24six F `'6x$o-d7e'KgR| R%iL7=?q^NW^]/c Oۧs>ۼ!}.h8{)>]2 )AtѢTt姼$ Y)mo#ȕ` y7-PhRnpye]1Qhk矔sdKY1$Q]f^r` +Gq~X-xp霅TJ2=rչO%中tL'J"pO +l9{$O.s+C:]Y[Z&7sʼy ”]l2.sk/"X93 q۱12DxgL9/8 +k% +Q& +u {swZbkQHpha[~ˉaR{voU"͵N~X=O(|-z,*冴+#5,9t;~*ݍU79tF Ĉ`؄{=w\ }ag[b0Ĝ\Ou.ԦPJ)cVnkɽxln޷c[raʏW(,yjǡ.EޣF ~nQMpxwpے/O#siNy31aۄ&8诔sNS+~YX=%d2?b):WkȸWxsްss +: {tfºOoq ވ>Rs#!R{%&e1nٽij"cFDȧ2 +"v,wcgQӗb%T317۸mv#޹ +i&_w1=AZÙX)C4XTiw/Gaf2`&FbYW%LvC9|y2t,C] <ƅ-Q|\LdS?rr ̉00 _Ns~ȲC1HG1@zҢر]Z;`蝀4r~&R˭YJu]y*;ĨF3ǘ<Čڙw6~}GY/No][ yL^ ƭs,TF,|(.,a\LW-FJ1lMM7f>~-{=ɏ!fTzTBWz2.|7Dfvjpaa UFƲIK._)QF2;ֹ=XmaWWF+;xhԳjBJ>)zR/OPe{E k%?[;﫤Av2^G4 Z2Ήj;r|Y-ԝŪJkEq*uI_)&$F_KӾ11IP3%B[1dnUuHN]C^3Cz +B~LE+oi{`-V\mڹ K}Em*+6n0\\ PH##uMnYwvJuÌ~^uQ2B}K(e#G2uS2F@T:Kx5ީ+`$!SX+WJ]ߓ +J?u ~¦%6o]+ g@{ha+#epF+Lvd-6SuS5g{KI SU$`dg.8\`qD@Pƚg;iKcOi 88'gWEƭCcK +v{[>~-_≕.qfI95ux(D|`^rd!hǩqJ'YY<Qj<㘴f6?(y2=%uL \L%LvJ-w6v+sGPȼI' %˶c/hj]Рݸ@?^}?VeyE1qIW0rd5i{aIW#qY3DKHЇI +}`a@MDxB)U,>ĵdVI+pc`ATBE:p.vRsoM"dK3>^)Wf|-єE v x]v@ Y +uWHV_O1F;'|&[C$hLUeז-!s+*`p:@* +̭˫Zb_L2 +5EEGذܢ<˞/1tXVZB"("j5_:r+6dq{nI AEҬr+ [/#&/YGZ@B~;J"MuP) -~ +3$ЋQw?Lj#~=0(|nz=?PnQ"F/Ф4QraI}ӊi %ti脶L <1:8a3)e5KZ}~j-.jD&? =ќ3͍BAm'q?W۲HlJ\= Wwņl ,'>i#[ptdi, Z%ڠK\#1>Tz0ɺDd&J׏g:O(A/7BzA(D#` 2NVn#-ةXԒ`lqQY%*^J\ D&E:E(aLI?)§BnA_ŦhZ5OZx,A/dU5'#¬o +Q'{=_yD1ݎlsoF} +_YXEqxiM0=6(iD:@ +w78apY[z6H,ljC,v<@RЈ8A@|?@T#"I@;B dr,;ݵ_ MtY>Vv53G!ɬ$k(ЛZuAЇX~hxNفfgc ?a[do=Meƻ}kԃ=A>_QR@xG Ko3݉uxYG^mnmv+ޒ{E-@p1)́ ˕AG(eQDP[6O-TqE7g #{ Dd nmF*W ‰ }w 2ϧ{FӜw4 jGg2Pgh/^^ElȖ,cӤcްPNeDPg;ihmI@tZFT:5?/B˲sVQPg#-9 +{R`:"A]4T |}_Q*) +qw}4']!zipr\*dЀ'EЛo#80YkSMcyTL/(1!TG\9goʲ8 Y. "2)-gñ 9,, ưT"Sc5TybjqLJe),J:4ʧ$U@{•?Y + d,0Ѭ斊wrGtXY=Q9L,(g[3K$؟ytsRlZ{v{r dR{[O&٘lueՑ$!0 pyl*$ -c"R7o]C1nTo#W-0Ny&ԖSҿF5>ZÆ?+"ggJd!?!y{0{%DG$}bz UO~U5 ሉ;/~n0:{毣wh>+YPޟ `Qy+xsƃBZ;rqY.>[=[di~z^vJ8ayg/6@D҂\qwm4{16^zȂ + +u`M F%x,oM02@bab䤧T9^/-&.-m3v?wC04xKp]=6Wǽp,Yao\moZR@ S 긨r3-HşkXR̿p9%Cz IN3iOK8;>h,=BJfgOTBb띣~m:8ZA 撒ܾ*)k Q#c; "`&dRc0(_+q_y8M~8Km̲r(fe\,_ q]Fr?Eb;fj+fV ,< a#f8IU)ckyg L.IBBnͫ<6TԊ/ ]j#-:6p?Lfw l>C$z|bxpra;Wb^&`wy{mB^5PYj``ƴ8K71KM"6иy341C"XS\H ln"N!WRGܾTx82 dF IAa蔝1⥛,B.M чߒ:{ 7>g07#L,p8iPEz엇= ( 2pNNi'ŰK5& +-AEcs|icf*Ns;e<: 6R Oǻs'cZ8$8S%AcoLGu68]=kgoH$9W#`R"*>j5ͬo jXEy 6ռ Hx} F5r^is;Ժ#䑗nf9a#V 5OLڊy@/9vmY}9?L#-9(.~md\X!X +ޏR:Աy`ϲ@)|jax8,m^BhoG梵Eߺ$?p//'[u:,?kبQ{SXD&aFwEcpHM'3"@4U@֤UmTm#@8Ab}>emde#/a(V3g-଻-kùr]t,)~N|12ļ_̚?Gi"m,Ԁ'frz}. |z'Ghڂ(yb7pih, KwmWKbbcm8LaGA ? `43BwuP1=+ @́1uSE +Ϩzh!e O _-[3R3"ߚΔ4?UHce.AWLF&Jl㐢3\[v8Ƌ1N{oAPt1C5!dH;HKҍvN0+5,l]G[HL)VKPNCq.<yvIn[3M~~ H@3k^JeCm$lо)ŽMJ0[e*5f(c6_HuvҞoO4v/ *dRAGc'M9D$K7?z̖ƞ*%*$/0;#&XDefczB,Af.UpdC: %jqeOEd /s/˜p*Y&fxl9֗/5٦.bl/xXN0kwqmɍ5{vVF@W1*M EjX.iޗhN5O+@`e;E{n4 t+XE+ąǫ'2NsR,O2/\ A%a-}n[ ixBdxI\}q=U5kf/3 BϢ%",V; 6 =O!rҜR?NE{ i/2jTSpj~9-} WV +i  £nqoȘdE Rť62W!ߋ С2̢̂lwQKCwbR+YȌ=q(˚tQ6#%{7Ӻӄ"A拹߹-k6tqcu uD+61n{t pw9GͪpH 9;3FU?yIX^Nm)S +9;k&F/& Vƛ@PC31 +,ʊ^ xQdYI~u_&ALR^+Cq^֒RrմZu$V`BP]l=%o%/GX|Bp,`GVwMf' +'UDoj{`P6o YՅ-g2k?N48㑮@^󩾀 i#Dr!6[ +v{A41i1{H qҡ8& 3a/I\4-5IN_P \FnH3ޯ&">J + :/0Հy)e/\-  U"^&Ŏu%2f-؁"iI,H 7tƒKFM-3)71'J6߶۞^PNbznmv~尫݄\mÙ2ڕaK[KmdH>5Mw(%үʶ-sVgBC־߳ѸypX D?uQ !ߵޞ!ka>|ȈR F-a8@ou8wuDj)~.|״8ɪNr27 F<Q>7Iws_nK_@z\)X. b[b"AqcX :^W 0ɿQÓyJLXA~7+E +ur.˘ ruu +=>X~c8X^U=U(ovuv+'PAneO5w+orH&IgJVm47xKD)׋i2nLLe\bG\Fmn+2)afGΓatZ>s`^A~0YRkg- adlؔAB2 *F@A8;u0΂*.g759 (f\vH_JhTESĬP&A{?siNuRw^xI6-6-ɖ|˺7vp%?rWB?A=/=)C7|3jZT3A;y OSHoAq.pw` y0U/EgvH':T!L;EKi}5=LW%ke,3~cĪ›!1λR];]+QZd< @?3>+1qs\1I6)]ZZ88vQl ,H/ku^@]S_y{wPKnЇ۸6r"4yLbyyO='+X1H[̓cX(ir>dc849֨8 +l|96`Y?'].+ `ɐ"d2ʜe'VlY +r&wjwo-d~^'fbMCLj']Q<]i]@f]$05~n0S %3NZHv0S;& +=ުoTHT0,B_ `j?·ŏ4M~v煭"IzS3jnΆh%1[#ߙy &x9t|53~T=i,*^,RU2_^kNy[4OrBNqtJIcB"ajJv wpEܟX+.Xj׌@J` +̗ +N K`@O_PgPВ>` Ao&s$(q[u㥼z BJ2b +z, +Hᥛ &W7L'z.sƽ7ͩ+‘?܅*\h`5I;+J֜ട $9>N@LMlI94L/Dպnw@^E2C [ V5 خMJtIusp&m88Z-`xh+*< ٙ>W`wR:?Uq$O0  +m(Ŀ幱W 0" M=\:o͐߯xxq.MsX#;tF,7mJzLtwyH\̹fW& kP`(J3(BiKI(D'e8H< wd[0I^>^(9W:E!k2J[<2h$lèq8=)|Xv{/3 ycPˬU~e,u٦B_9VY2%wQZ,Ϙ[BFKau҅)y.zvr-qWOD3lW.@qbwb%gX΁p_K$>e|.2,mE;KtfXWΏȓ^!7^SAZmHJET ޒ>d$(Jz9y*wYd1|2G5* +udDo`QҳC_RÊ~6 9_a@>^Κ8E#([O. ZlyfZ'kJGa +8OYm:t=PBS rtQї IAj_:5fp-^ËF-Ŕ91VcGz@b61ğ=9뫕ѰUjD4ȑb*lŃQ*N,3=]:қTm`_Waa TuxRo pvMP"q}u(Iq2W;SKX1X3* b蹊M4lu=QH:wu$n(ÂRԦWQY?2Y x,L(omY%;^*hG5, ,BĻ.mwA9ױ}ݍDA9"m\(> NNBz]}f_DXb%ny^B@vKi =߬͏0I}m0N-4돋 ѵA}]V D!>pw db>X1jcs?drg `~V!~!A@,&0kǥdoE1-g^`P\Hl%2ge !Kq&[} V@"2J5d`JB!Id̞(I_Af7+ɦdW!w; qR5AY-o F d~p*^t). rHmX,3Q7 )%.mѼX:kNEe'JXWhu͗^Dtx![7 l$rf'ZG/,Y-biG0]3q/Xyk~:X9 r+W3kxF/=0XPF}1ez%/h_u֊ӫY0.JAz3z_vob0F'=G;oNz!;zc]94Xx`sM ~H/׵K2>݌Vxpְo ߭z/wEH8jxӞ#/@wIGy)Fb~sRZ0H:b+Q^[ZX*!vt8G{cLeDxK"kl2Ul7lFڿ]H;r# eDBૻ3E 1D1Dڏ3E +o0fALe!2mpZX"zSc/5NV`&qPgEB_6ڍFCfwa(*l]~>]GךkZkݟ2^EMHQ)ݧ N's['D8ӕUa5ԄAhm:IC6'Őwq:n‰PȊ"\G ˙nYŸs +wzD MTL"G^@:Y@si9riOdtH mMU #᜿#-+#⋘rw+̺Bf_YL|ڠ5^.Rv5%g$ȀYtAvN`|ӣՈux(4kv)`̷٨_0V>b' c7v0|f]>.QxJIЋl-()my/Oۭ2wɗ`i^4wǙr,vq-2U4XPLIjk9{~zci8} ~Rlt<+0"9t|sՀLS)d +>I ,wQ!XH/%L 5 " )ehMSo.?ҴѼ60(,7%(0P24 %ٗHg` J{॒|XI[~hCO}j8 =0w.9Kc5d*+x9U_h!ݻQ\w ۮw[\(KNBcEsxnGŲEH=]b\_h@0"t7ߺ +!}2h>Sͩ^&bDwgJ]]/Yl2!B; b(ѮW`b@Ϊn5:2;>ʜQx5 6UQ2; +#] VX&R|k˘i#ڀ流Z)6](rIQnvB饔Xq +OU )G ?x< |DDɠ%VV[8@3MazMDo|!XG_{JgcL&X2ㆰkjǬ%gXO\u3GC)k? Rw% frK)Ü'78,hwU dym ,{K[uw(e\:s1~ux%h{B@QAC2b{ŜDU7Vnד((;*3~7M m>xisc&!iZ h^B_$Q #PIf]o(VwÅM(bPͼy +&ݼqѧU)DKyP6nhwd-8'5( 6ݛWDy˄@/ :qUu z>0TJFq홭H] cW + +wUX҆Yrs9)wC\cG+F<=' +7#X_ "$ Az +ڎYm xtmb-@~L-?3AfWw0woTA 6m@(ckWez*`;MrMh`9r.) +JnK]jfI۵bLORAR{2:]i\UrIwCw*)YJڙK|DBrAfmzmaPHoLX(ħ=JH "u`Ƀ*0[eJ&o$]usM0>Zc %ʶ~wYWj2wg&4"i 4к=XD +DQ爿;<g}a gڧ "Liϳ)ֱlek qK+V"t+VeZ6Aʬ1šQy|9e3ÞU=&JaӿhHEQ@ݐC*'4kV" Kmxx,}.e9 [%'sbpӏ(Qe/F"wą*+_k%uRʍ@ ,Mo' ZB1 RzMV% bمnY~^N)dZd$=0Y ڀOF +do(ܺF#K;=kaQl8zg剖K6=1;jD+rF!:AH2+ +we NMv%Uդ#f,k̐ ;ŸT `H+@c#WM,i*֕cJ*_,,%)݇︂9 BlӧWCR`J0j8'_5gycK߼ژK"Lrf9(6C}dKO_%6%'ĄĥN_ +NDho7hDŽh0Q29AKqz\<ȫh1 G_H\pGϧb9g#"%*h+聜*'Ļ$/X%EAQ³rmI@xSkw)bJN7M_Qe?ҫeh'"P8.OdvW@z#TFoG+%J&zkIyci^p;bpd$txKtcL-jE_m⁡}$by $0@gI)[؈]݅ST|X)  `/4iQL t fiAFHcyn7 k3eB ڠ0o,X@pH%6P [$D^抱be%6{wlC"LzL\.ˢ-ۼ6 X >o`˗Q@<y>Ihw zb"GG)'iyVE ߻#Mq#̓%m0i3[yˆgYuؒ88h5uL4i)%θTDs݊֫Ua,gť"?5'eβ.WѣsmdPcf֐2DzDE6Cټ6hweB8P\'B ^Wfᬽ|ъ;Qr&Dd6Pu't2zkV]o*D³+ +e֎v?1~`"_' c답r\hGV,5${ QQH{)v1'8Y  Ԁ˵zArDt|"d,^v6gTZ kuvQ^+ +Ljj!{܌PH;TAǪAG]rDǴrx@xfZ9򤸛5?`^!ݠv~\,20w+R# .euÞ! WhZPe,#IqSͺDg2zJrr~=RI:| :|,(Nc#[P8m)T\"? +ʴ`,#l)-ꆒiq +LHm ӪxiC`x EY^sV#M߳V'浠a0}SHg8:k +k +.8\&GY<LFFgvd.!cj;O$n>m=E|mЁ6W6.՝8 Z%Z+tD|u99ɇ^JYyHz!)gs7B|.r+it7Acw>O?$X\[DŽhDUr|@ۜiwsj$l'w6/)t)/ ?"U<$"M/]W:io?a-34̛'o֋(ڀ1m#X.)v`͟-d9y v#|>N(*V:鮲l4LVZyg h ѧK$ɳrlqPH[\F3.w}kho\ K3mB`"⭁SUA6PhRn 6ٮIyQҥf48N<p6"ގ4L6^?:Ŵx)H[3 "SdH7UIbb΀eH|BxBqwȘ}m>]Y[b lN8L5GYl' Dݠ%`v#Di;K;grm!*kBg\U1=wx +u?΢ۼH'*2v &>ϘudH"wЬQCi (%Vr!ލՍ!R.d/˴xY2o7Y'xdXRPf4G5HQ&V[,m6L= W/80Xꂹ&ڼJeY%fyBARoyGB6igI=O)x ez hbBRg$ȳ\>)qmHNnT}"JC$ߛ`}dhKimd@B7zL!~@_׿;,=ݲBfxuu6X=PriF+?_DŽqPf Qޛ]|\gO w^a֢6*V?pZycVY/iDzƂe22k60h"&/(DžK7IsmH6wW:t)Fߓu֋V|ڴV &ڿ>Y X ECrQX6\pV_#wf R :,"N+/Ki?d"~rL=!w _Y,ʾ@NXG[aZj\ߣͬ,9\Yuvr& +V?O*_%͟/o|)g[ߣja0mgQX^ᬵ6=Yԫc﵁DgB3 ^6 -YcYBzpHo5@j" "A9+$+0C]`v}{/pͰې+єڿ:Yom{sW3uusоb n_U7YK~TPr=K'6ڱ:DY`y+Y^AGJ9x/Eԇy'dη3#3\^dbB;jY=Y'bW: +ٮD{oeEw>B\]]Q Z\p}(T\g 1E7^6(J'}͒e +=s_PڊN#X&jF3m^sxiG2b#KU%}=L7On)E}[ZOu\_H{,ߟ8E:Y5bҞ@,[q}, .b$rg_>_ +'sҍPdU lu $ 4Yd섈 q244,v2Ⱦ "2nv6(5Gड़D kV 0iƃ誒'֒- W,D/DwzU2DwJɚ=NT$" -mmRes|v>+QFo"99?. +r zi`f_ + =uF/6h"]HcpPf5Yˎހ>Th/qw\W'PV^^v0G\WdMpik`n?6R"~9"nGvwyBcyzRH[lI8 $|rm,d|\%U\gD4vymh Cߌ T|\牡m TBoA||Zʿ2zkh+3iL Gzu I"~Pݭ)PYBAEw 0QӬqWnw T\R܍8Jy(\²pJ2{f.bͯ>rHZDї Kv5D+ KΏ0]Yᬹv!򬜟"O-r!u͓oke +/}8lO'0L3x_x [nO<~E+lZ^!HO!ޭW0x%H"@q-Rfm7)+\h_:u@IZnYէ݌zH=@fyQ8j2}\x74+  |H(t 6;է :l}:щF6"+˧DO͊R y|Y'pa{m~,)T+ce( ٢U&Rӗt^p@ Vr*wҊ8B#m~zLϚL8h״}6(Ќ^Y/i^!&= M0w|u6p/fꡍ7f s@BaaFNN(u3Q:mNf6Pb\'GmLS>$?9GʳʁRVXT7)kV=JC\,I+wˢK4/RP*-/ Q`LŢdyf7UKOiI;詗I- 0r_ q7vvm@$TP\8:glc #hub;Hb?]!o^e>=6ĥ C5HКU0rw V,_3 !¬+"ܿ5EB{hRMD hR20O=V<;2ER`yzp\]DUF};q*7<*%R1)n01<'z,F:_`=Y#@rhf.+l,OSNRNMux<+lkCAoMo\:}` ".ׅ  \ - Y/%e +e&e$C>R+Js]T+HhFN!72lWwhx-:^pD<kǼyѕ6Dcv6n nelG)pŠ z]HOHl1@3ToA)J,m8|\m{g=PGI7&xa6+i>,W6uvM[C򉷠!JeY̕r F.668OEnՄ=ҪirB`EouKgiKLY4KIi1 `y hm=0w^-Z%"Ji2 2hdL< +UA|e<3}|Yed/c"/ B̬hfT* d6I{m ^01?RuhSV'+C\zcbviO%OC! Q>4W=&DOxP|F"{׊2ޮ4׳0km~,pmqVЮ+%Zyq7|!Rܭ s ¹ ӵK30zV hr](=#~D~`Nfͺh AW]V۬j`12Dcmt޻^wkn\d<`A;%>^L͏ Xy3p]@2cUh֚B"]ފD\|;,^duF\V9Zl6|ʸ[Bm;Qgib*n5pgь(kFon5c:60>GVvI$~h#G\+ڠKH}%pitI [~-ヘ pfeeZAd$*]'L-(a#@U]ؕ(.S/eI4{~ReOg8xbV2}^Dq!@?s PI5TW`~K*eRDAi*@fWC׮a!YnN_U=¢]L\HF*2 {Cz^”Y3&E=0~"GH=\3Z2{}VrBObҋ%ѝ}1z>"N:цY>;1parDg#͋GO07F, j=Ҍ^e`\V;Χen8}߬=Pڞ2Ey3Ѯ8:=R6lOE S/vNrao7hOvz8C +:kuLy5<-W'=!C߼Y+/G xއ%4#i&_=-jBm rļL ,]Hu˴Ab/A77 e}&0f\_wR_0q/r# Ϸz%h*@)c*֕aڂ(4ij` xYy;|%CU wF,CwZyw(5z/D}W†"mv4Ly _ +uu)ro +w$V'?S iWG `)ޡOi >!֓fʘ`\=)<T 2Xn :bMGΏ(|&Ǵr eSK +3w#A#("ř2)(d@tJLʚR3 8oiݲVT@aAYFBgb}JY)Kvy@A翢`VZ[Cvw&Xk&_JfNB6H:fB|6!0"N2.Wg6pFhavvLB:?D +c68|p`g +çQ ⡌Yo~[4sm? |c!;|Lx\i#e=fDlb Ҋz/wV~pi<ا*E,m2! + +ƃ#=~ YRHlȘ=ud&Nemt#k)RBX3$zk!E)ۯd-8)SN߳ЬP큒a^(H?``ÿY%rrJ-@yjD,{mBD7kw}Os嫬M:6M *36}| Sf CwxGbimZۼH"`PH|p&cvk"d(@Χ7z( Y[zrT@3 +R@6.1:\ Ts1Uἂ:^,&z9`=hyKKm6eZ +Xo ڭM17p)K¬IE³rȹz@V'}Y#=HϯwwNh8B ȡ7xA#'XC~9b? -68C9wi +$_4, V'͎( IY#TbiX-@ZWAOE@aP86 /L!RŲ0T@MmKmoEBܓט,˵q n<~ʳ!R`+SNe<"cB-_͌!j`6\\Yg +0r bBܻ 4gD"0o>T;Rm7U`Bt/vKC"cb +S"N񭏃CRB/QBX(_yWfSAY{aVJ)J!ߟdv`(`(BBd\2V fȡ]viF/-ijCB9Wrj%HyO`42{ghͬç'OrxV}¬^>=W'L!~X9B;B+piC=ct6< /if.+$$C| +~>1rOA4V"^đh(1I*wo=#ӑuݑvWU&D^xB +RǪĒ60G&DwPЬd"͚ћ`0/-*^ڤaiop-BCaRڋԧL +i'mYւ\7Cw/"d}߸TDfHeN)R ,x@kb?a7h:hwиc{w+Ǵrm)  'i+.h'#;$>KyguPw"I/初P#9tC秌}2f»~ +M4x)DAʘ]A!N I71˝|>#o@l4(Ԧ 7 Cnm ]!ޝ `YD_i +^ȖC@avDkڅbe)퀁4)JuQ)'#UND7TIlc(c[*n'v ,復vU߲V<_ʢXr!1DW.Z ,kYߓ. G}qJt\)ǍMÛ3)w%#/J,me`9G +%4Mʘ=H{RC&GEn>5fh9 6豆~)nxtf/!w'\dPx7 u R., +nms]}Zf--i,m#;$"G=Bɳ6׷a2H#(TDD!)bm9 \NnmjEHztOm@T4Sm.76+jhʂ!itc0C%o`^ڠ^)& G) V[I12ZG7}nF)R XT"@l&t(,:ˉoz-qƊJ@x EcV!hhK'6Knm25Z*5@ #YTJ2)(D/$}(* !R|&VM3/l(<ۥ!:emL0[O}P)"Fag:ެYEkh6 Q&u.^{qb!C"{9C|s#  Fn=VV)" Z[r5ub`Ŭ_Vܗi<Jpvnâ,a8<^9 +xU\+rΫ 6Sv.iq@;؆H۴T "  67WT K{11s8yQ>ifj2!i?TI;|xϖB$ªn S茬va)KiAD4O&1B2"<̮-56hWT\/; 6PN $]Zk2f7;UrIQPz(wqrJ6,1S6` FXw_~ @s]LͧI _)12$uY%WCy!f .t=nG&Dg(V'W18: t/xzEr)>ߙ?&ǵyzk +wm Kz5_OR\/Gۉ ݚ(KM{\>jȈX6$KRP0¡\-pb:뉀?2kf~Di-d.HW `ZxYP>]ҦGUi"la;f Y&6@XG GOBڒ̪!$V']zJ,= "W#Ge366dG9;UPpE$ Rn]8hN캓EhwYyX+nH #t"m.:evW1,RO =64HCz$H9y᥉۶J%$b!ϓdw@PE>FY':&bTςDcy72t;B!% 9tlͷ\%$)x*B0חviQ4϶X*S%[h@)DݲL%4kx!*i5#Zt'XEz^ R6ڡ~DY 9Iya2X.qq_v B6w--N/t +K0[Nt%f, e6J֋ex:J2xl9f0'Tٵy`zb^Grm^!%Eڋ'68p r%?:zjuv"*c^G)M\

X+_اͬa;ZK^zJۼPfh9 +DE||//BMW.@Hnxrw#{"x7ݭzDX6ZR48KAΧ  +LOnC!ޝpXgc+~ڀB)`%]1'uߌ$yx?B]y} JOKfAGʐ3Ǣ Z+iju4|2ZeFG@yPZdhY^p}%|#BuC!}ci +7C`bJ|%loJ ` G2ɁCl ;,!" mN4-$vZ+_88\=Y{dZ6s`Lʘ=8> K7khܝ~wGF](œB2rCVo +qImI#k`N$RWl" V8[6i*|_F.KL߻ Ia|4 +q2Z|6f"vXB$I?=6XW)wBlq7[:r0!2}Ku_+gAgi4DO*. +؞!P,Wa29Xqĥ-ʮ7Ĕɍx!#a 9 ߥx,!O\/dy +Z +qK%2kࡽ^ qi ,"<٦H19\ߏg;96R}¼3Eڤj`Ev]g0hG/Di'_9zZ/KYX 𾍶 `_3N#RHlC]X+'8@i!`"j V' ymJZVvvاìdiG) d)ѬFVګOF"˗"HR}sR`cO!BB"%k>r +'+^NU"JRLPhneR}UYCU@[$.kuQIwOj@N~ (>QU鯰QРW1$R +#%qp'^eL2sx.%6qI1D\ϰsѧ{Pz`|tv\*!O&aq= p׊8U#| +G s8@YOXڑNO #/`cP _Ngyse G2DgXsi*>PrALL,Ђ bea>@{]JNcQr̺%gd#_,JB zוX>J6O˗(DŽ_̺w(E,mmP| üQ\tuuYگɄ`3 Z'աt%;^d#djܽ]&@Hk+otm,$5]dxXK`hp'nxigR% +s͡H67"[s0*Wz-Xzm4RM]DЦ P]V4 DiAel7rCPI^br6XGYlp@ssB5 +fwT$gY 7JxV6"$E/D쑓O7:R'm~q(%YdyAѢ=@@{U l3.Hﬦ.,xo'U:+iP1+U"K ++tx߲,]rH( J)B3cHnX2`NH&FH (!81!wI?i&cm~҃h!X~Y>t[EyseY1|Áҥ:nI+H3e4t(4W MiqԥJt-\I1cڻS3sl~3ie$(1rot3Vr%QuӸ<(,NėG:&Q:P`<I(|]3+ƻ?JK <ֹ,@ugvhD$+f\RxNЉ[I\±R.mxl`1B&Ъe`#ʖXP& `a0eZ*˭dä +[O>$' +@pYQ8XIkU2~t +K!/-e&K7xԽbC ׁd :y}5Ǖ |&"N0RTp4YJl (YyI4r,L&=䲃r}:{ص2|C1H Z}}Q쇉ޖ5q"ncj'MZEGdDFFTD_oLu1gw)VFYWܟ43Tb:ĒFDptd34V>t +Mǰ{L`: 'hҎ:8Ec^u.S1@7MMX,[E"n~Ҹ] +W6[d+]A3{uf-n4.-c+ +pN +; 42`gTBa& q8XWE$rAOF7yOt<6ˏ[v9 i+9]f3JKWFS6hxѐ[:CF7j0)E=.Ʊu։?hsGT#A~tuPlǪ:A˺:C ug.xtí:ơ[R u-b +\iMW@S_ `9T4:T@*us]:㰊F 7N;Uu6fvey[yWf9{tBE#4Ћ>G}p뜬o79Y0aRo=:*#F8g4F"GhoHU?nTWض/ƭA):։l&>;gE2`) +f!_hBъy! M.p`PRۗu   +VF=;W!d..ؔ"#dm2Ko@$uUM1MH(9J3nT.=_u/At#F +xN琥g,OWDu '3O3?m8W^DRtrG-Pg!|?! 3pKx*y#j.q娷&k'-rք] +,Y,R]eU^YzS+:5ыe&RN=+:d߉4,;;}!<;U0\š^T&0+;}Iic0ā&itOi]C>Mݺ6Z <ǃ-rG6Di !]-}ZirLl%X@(9:DP+REc/x8z2Mi'C_x47UWz<(ޢm"8UDMS/e!zrpNoI?lfHR`: g aUNPb&1°γȒ@ ,͐ 'p.DpVn? D(a'Je{|RLВ'$ +c>gOXu T +ݥbQPȦp15P@9Y`trEW_ ~J +~_}g$ZUeDY˗$6u dj3'n&駰O[2Zu82e.S *C]nwt}TC!f\Px}:H +t,HT+/Up3R\34% b̲Q`TA`I2ޜ6FFl8-tbS:5r +8 W &-%@2JD݉%8_KUO=<~NL6<{=h@0n/l̏F\ի A,uWj.9|3x 瀇x1#@4ԮS^[ F+W%0M"V5f:\R`-sa-tq0w&vdЈc<5c!}И$n?XzV.!.Z?ỉ; l d=ZWSW2SC59U3in]qhB C>tO`^eYmk=a[a~:@ +S#%bBt=CFK;)puIR6!3:W>. ТͷX:$_$)#~( HIcSs->%`ȴ8aL3RM 0 +L +H,}Lk=0yx;Ig%ܔf]=/{I>@=c CM{%tflWa`5RcM#^K"S%:3%5+Sw:_)׳7z\ Es\J/ϏcM|1ydyPIXAsI`D@Mc UaKcPn(U9yIs rٜZڟJWy2QH r*cnQ& +࢙h%_Ri&*+S`X?vSrSkU| +{bwV)9*)oPIt9#hDoj=IWF)SX:/T2yɀLQ`CqtBV3sy52~G/eor\TBfB9'0?Ӊywxsn<<+`867蕕+/Pp7@,r5 h˫aS?1lG B(et\D|KBLyX8Qŗ>R&ImNwT;u\L#l}"Aƹwifj3U%63k1;`e+zn7Fތ?u7CLH`9r +=Dx?ٵ4)`*V/Ѣ \>LVG{7P ±4+ ?dx)߈7*dVb{.`+P4Xsԃs ^Lv.UuCy@&ObQ~5Onc<Z\$Yb|C -Nw8ԝ,#c fP3!,cQ ?1du<Ϗ$[dj#׸t LHoX%0GzuFP3mڞ!/)  [3=T0,0f`/zɪXDQ &f#TIl>l]W@VNo +)rfM*Svҽi]%^+RbZB:X +LsOFGD1$cڛdB;1MGD}0W)+ P ,(O +7 B-KJXA&P'35:19(=42Em9hAs5lD:Vs}N(m`ZC7Nc`qfXec4w-tRsKùz|JaEDѩ$A(%ńʈD89p2C^ȑK8 A+&p|8j(fj~T;_FG^ZǶ<"F\oʵ3 +S?DPM~aغB4se + 0FA Yތ =J~`$2n]t.@P?E!籶+pBv`]NoknUX_goVU;8c2X6u[s'QKxr0K^Jc(pnf {<@~>J:sVؔ)0RnïC A5&B5ikv +{?+6[uK#o/٬6zө8k?g6~?b)8k7KЪ |?2!Kowk((9%LgtdF8ɎpRhƩr%2Q^RӨN<PЧ{f0) #)0DVTToDQnVX<1H(OV~xmZVuӅݜ*L}D$iJEmFb3-~kN +1g8];7:a)ҹ +ѽx4ET)}ϞF.8X?Yߝ($ށ*T"dT!'d +1&A ED‹C֥z\Ҕ)a +H Tw +V-b ;OL]"vF_SuLZlLGխKȂ{G5.@8sB [w:%Pi +y֬~7|XR=p*@7,jʉ/оHln3?ύPSDyuT.Rzڑfo +Q ]:8]*s:C&lS}N߸UB)"#MN4 A:4XL&|Z.)9V M4e `L`&f6Ԑ**<{\VHee*F.܂Zer @niڨHY~]g1=>+!Hxŷ2~ʡ#Y^IfqB.EpR,-utaA [a񷍺W]BJ_SWˌ$N]b!4y[܋JpXۥ̀Tl}8'à~1 <ĹK옘었+;d-!E䞭DIrfl'w$e_xEΟ:A-(%}"kW> U:!#j)F@2r*b>r?Z3~-YX8y&7b˛YqwھN(̽Gyj tQpM"O6?lF`#BA|@Mv)Ktb!*c  f7%n8{KYY|IUTapg#yX.Ȫ;v!`txfH0E>ظox ɥh(&98Ffg7#Q׺9ݷIs;IS($"2tfj>hO p-~RAJ +SutGUg:⭱HgyU;rOׇS{t909NC(ssDKl'_ߝ":߶g㭲A}{XQAFU[!lgS1Lh|v׍-%wVU^X8[`j2>'w%8o\|;UUQVZNAQH|d/42:Hph;$e96rpZgA"N5BE 6H4(]8YޡEdI݃ D`ՎaTi=f,"&g'0|vKotj#g>2 ^O#FS^3 a6sO3B.W`.g{+jS(jThfqIƞE$}*[Y~-lҽc\3(IwSP)4I`cDy'ww6ΓF1KWIT! 6_A{Cw?? #kDS1aZ.Sr‘KO/"p)u ?a=SD T3XRoAv,5z@BR{q'X9 '%7koBmδܤ n)JloɮUaCțSzyT-ǑFR䨝(k~zW dF_yQLcTRͲ9Ne%O1{l|.hF؀TnɻD,pG(/b9v]D +)τE_QP +8%APf/Kvkd|ǁ4z&adY:^|AIQ {q201m 9 ӳdpA6=4@JW{ =6S> kVp̚[!9. )ی _Jzrs#MA;S n>M&AB!f2jLњ]JJX̯<k{ 07d8mD4SNαg]Mn5`;> T4~nKKI:w/@UE ڦL5䬖I0AF@KNzi(Y'ΰFgA̧PXcv3T)PK=fRynkfiif.M!Rx , i fmiln'FĚ8H| + M- g r{??s4sw09`| +W5%$!9;F :ҷJuR2J@^t7> ٿ:DG3 +qȐ1dy̭3g4v$O/ԏ! g3:pB]Hp{uh<կU \ qDB<Ɏ]-9 ֭UOsSs;RVQwc6+$. Yt ϐWJ   ZW1]F6SD&zH$%u{V[tNM_NfU.G*FT[*,jҖt.RtíMs zzl.;'6!VyTL @iʇV3w(c*zۓXO,\GKuϒird#KC9.yBP{k{/Q MclD>5i6YǿDC]ONJGlPh܈DRAV[]%sVlD|dJp })W>Pv 68h-g6pkIĤV" X fρ޴ E֑[m!h"ab!`E' +z.[|,kpq%ߋVտ媻$\xdK%t+빬7:4On-,_b񧹎i)%(:|Xa|(5O0soƣowo0/\M8:\;ʨym5wb`X4*-E4'W&h[ً xXN^;z\{ᮆp`.C/j$O GW|hiJ7ʽ-hi娤2-tNTp9;e -|d#>ura>6=!< EGVvTXѫz a*x6LLY#Z022ї6b}-,)!d/8:0|\;RTǷڣg7J*A;$5u *-2Sck\`RF_m*N` >ߚƧbVX6A /nP1.~rXݤ90qhjʣE׮ô/6]JocKv$R/=|p osF/mP)6^NKW<\"K5XZ ^e6.ߗ+D2g}wh䭽o h@ճ@p'VGdǵhԷ#&_#(-֛}0 ):DЍQc,:3A~8E ˘IG1/[1A4b'~"Or;sLќv/:+ܹב K~G8dE\6EE~x͈CHI &Nu19-۴o:|42UΜbmw4wv32 ,8rOcN$"EՒ|k7/"ͼ}%գ\T}\Or44̟$ )9Dzeu!q2yap?YS@M{K~ ҾҵSKiJI^q3+qZ]&:hR!_#KZZ7Tu(7xqp)OC(/5/a"A5)ieS;Y""jd2U N }p*wLX:7Sc"G#|11Ƭ + ㍵Qz9.Ibzdz?_L_h7GҹQ@;T N?;yEKi7%$y(obANW̢nŇ)!bIG . +D'1sU9ʜFn?e>*!RKjDDM'zJN40=n;kבNnr$ z@,hͥmMY0H;S)LT.$w +eu'撡0a}7r4(Y;=3j~1&ѽ;~X BT9SP!u @Z͡Bdʤ0/~tvqNk*bY!MdE/ZϓzI!-S5c$' BC"3L;&`$ u%e.E;a[;[gUCoEnHIl%n vƖDd$+ d`\ߌa!/=B1`wZe@2Vz9ds*pd^9{@&65\lK͇'-zY#_T଍@0'ɬc: W F/`pYr N6;³8QGG3SVqjB/Fk4X8ꟼЖBflP-4fuAf0%|m ÓtR# ]4}Ur?NWŢB׉ۀQ̕p83#Z( 3a(~QӖ޾(]rme޵L2X~ { 67NŽt&g"ry&869C +Tz.o6OrY ^KkQHVoBԇ:QD~&9Ivz|N8o> +kuGS1U4ꃩԿQN +_H.~!6 \D¤|G"{Dæ@oy:'(Q}rFJ^>G7-I䣹ɼ}W{أbaTz>S+6(_J/b%ԣm_M!rt>uMecr)YWRni1ؒHoT ~$Fv8{eӳ4B-Mi]:uf4m{]$9hL8rehIX|6Pn`U2{#n:⡫J"g)䵷Oڮe8kfHkfwАKO-Ed L}-vXԒdс$U:#;X5t74i6 W@* P(3"+i xb'2MKji#eqN'qbqt|9I(S7&q"`81VO䟆XDDQ¤sh+_;pa5VoM~mIN/;ᷪH*S#']#"d@"='~8Gv@ʇ?ߋcn`ģ@U,Bq0bG&FH B3N&ş އL qP8TK36%Y?R{eֈ2]-U1Kwt_z?4vS '4?,Sg>7(gp]20P+,3Pɗ3"ښ+~{:nUTE3\*ʂ:jZ"[ؔM +69iю +i{W|PQ-S~GYyҵbb7ɻ)'NGoZ|-pDfw׹`M=_?DTpj:ޝCݵ1Z/~:=n='QD8gۦy™ˢ$9e&C(m6It֡ض$CAkޡ"SiBмm,L +auC{5]yR +t,\>/|Hk3&J dRTza\< Dz6:E;m!fᰵ大L6GI Z{3mBx_zbmL D 2 %!dX_@d=q^l8*2`0K=%n2M^xX@aKp6 C{(ߠX jL:i DTYFs +)>i74sOp/vy!N m㿃iFfcaI/Q>W/s+hH78d1S욷"h.khVL=LgL8/+1Y=6]LH:u@R۲tm1ؑtKZ?6CտιKp-dK$L&?0؉f:c0!`dh*Mh!1K*$ފPΰwlrc[Lb?PT`tb}ޱ?ʐnEٛD}d} +zH4@RD $ +Z?C1iϥ'1! S(Ҩ~&VsThؙ zܓ>| +aڷ_v:E\Ж^bxYRb2%=3$СqfxpMKJf^ʹp )ӑʀAOu_~|qz1Ҡr? \!suWT~7)5y_$Ԑ(g3xs)Cf*OȊT>n }-;Ca0!9>d~ +nl#:7`!448{R^]OQvN*ҟib*!Na, >4 VmS:w4Fj۾kIs@SVщ!O@$\30M~쳦٧$鐯;ŗ#FM:ix1/6|]{PATU>1P +፿s&v)-or a uWbS +8a= d$qUH|ϓʁm[1>{jg@>JPO$l+J5H$~&ï`5fY%Qޠ4w-gJ!51 +X Hj +L]J cZ0TXĺWzLANe;("C03$,!i(|>@A Dwȧ,D1-VSAno$@YpLQ{9Xb '0$h> 8ɾIV3)|3Ym?^]@!}.*[$2(;бh i4PmF0'AR68LI6 ;dڧj(Z<7!ظ}{㑠dE_ g_ެFz +A5|Mj30F *jEmceϪ蔌PfqW׊!՟!-n(85`@c:2)8"XX?)q񎹯x{fX@UChuץ*pwKe x@FkSD@~G3uĘ&5>!p9SI6g# G! +.">?# 9z+LiUN-Sʷa8ja}/آm%ВzAGGpȣ9ĶlV|j|% P'y탸77Aig.uۜ>S>9N;ml?kUH s/h\V(?L4/XiaMENwTͲ2[q<5{"В&XĜG +Y6M|,,iRc\D"D_Cu<Êw@}tybo `(̣*awf2Su9c bKM \{Ӓ3]wC1:hy5}oPcBF\ꇉ$X]QcUZ);K'D5tj'Zh;TQbӗ;a!I6Lo̓ ۋEt=Hd"Rށy#_]P⿩lb,o6ގS_G ޟ'<7ikMяDJ: Eړ*B2T vMl + wX{Jʹ/8`R^;P@1??4ltM!0tl8mr!;Ct2ql{̊|.b^?'te}XFh?$+};VB}CiƵ*XX[f섯^+7)mlrz8ms_7}˔ tXU~ ZcHї>?,gOPHSpF*?re ؆#oa-K"I!}q:$6K1P$;8c!YPuٙ}HlLGˎ_m>s@ eҀ·h[lA`_|#(mt:EOɣH +hfR\cL)I j#v{].kYQ YtulN=-TT*D& ]1Prv +(fIh;Ȉ&kAd$TikK79G(F WH>L#X$9&'}m*XS!uqDƉ)|GWqeHmo% KAO'.oS̆"q'+j#b9|G_|H_Jؔ ~u֭ 7 endstream endobj 13 0 obj <>stream +P2|_Ae  ۞ɻ=v9]>\^RTй[ydkFcQ Ñ!o=5S̐>vFA˙f5{$8AJ*w{9 +BRhQQR8#EixdN%wTFwtסflvWǫcAh+E/;wmJIgh?V:lƷ Qېꀗ܌c1X֫m@U^}AFh[|QH <g@+6 NL>ɺ辧WHIFWC:`v4e5$ 8i% Z`h`B,>!':# Y@t #0Ҍ¼Ml*RAZ:D2!4dJ@eA$+6##=PiDZ:AJ$T2L MⱠexTfb048 i''CDp*taV $ +2m2\x0 L x'HQ hUT)<:p% +I[+x pXll&,4[ "!s` hl@$lh'eMln!L-b89`Y䄩pX  QrDXt"Q'%*Z.˕Y.VWt(:D8ZƂ&-2 + +0Q`˥0(RH: i#i!84yre]6PDp`vppo@^iC$*S"ӪTJ#B@,P0`e)%Q0I +&@2$/%@X*% ySr 0\!a[B$O0X +a\,]h`T =($d@ʨ% ͢1!t`Ph<0@,Ǫ]f3`6)M *t * bᕔ1RfVQXCmB@aPl +0,&jCpup8"8"`S6.\>8ZTeh`4B\l2Ma![΀sd%&C$!GSӱR˥Y.u\"`6 b(gtÞJQlh:+ `XNx4eBCjXL +fD"a>+% .(Js0UB EB }8<>{y\6[eB#X >1}L EvH'@"rX.7\wpt0pt I`CCp6Ph TfQ"48txB$ \!OrD)xK2<}LLh # 0&DrqH `*\@(H,Sah " ʔaV[Ydؓ!Gȣ`i0 @ `hIhB5#C1Z  r-u ΀ P)Ɋj sRX@Z.L( Y\ax<8s0`fu0W^uuw7L=K稛Y/g+~.^(,w:W=?BNk~p[l`pcH&+mdtX:QT&j3TTlSH A "wiDR.*ӈJJIɥjlTuJd,uYPY$pBPo<dԶZ45k2N jtwo+ؗizj 5L! shDv bl- : bR'"Zm'& ;fH=0Ir;1Q߷U5N DLNNF"[F4ZNP"L[Gʵu:X^"ZuD5`&MjT*R*JU8F۪T*!RQ+VٮUĴX\n4h`j\f$֖rJ%X)ȈEd0*LTL$N#%@P*m39<ȗ" F`]m#-URN&ɤbi0 $y멛Q za;X%Rj3`H >UGYW +aEac/Wt=L ˥UahB& .VJ,c( Z(Ԫ$SdJ +PJA!R$dEB:!8H<* E@@lJe*!Xm (ЉCQHG46B k@P Y4B!  I}XH!q +,Wh CDl2mdB3M&ۀLfh6 GW(T 0kI8 0VM!3BRDEo2JU(E*Ib.|qڡ"L8$pB'!EjG$T8 l[^RQT4R.04M%BBtp*NHԓQN,WE f 2ytr%^o2   +s`(m]5)Ow|?* ]fXBn1ƈC[nMͩwdH03nuY| {у†^.}?6|S wz.|sӭcە:w՗n`wFgѱ.֬1/t| ??Xd|MFOo܇d~y0sً-lU_:qߺS罘B:Cf>toQ: -;|ӱ/ Y_ Ls/!0e +?F|qӵ!vf;;r>{_Ԙp:?n{w1b7~| KߣVYGըi\~LnB1 asf1GR.gL0={UQ6|3?Fק!{|m{e{ )oٙsw槻\@?߭tϪޙv`儑}#oԘ._uA1g2|1}n/֫q_/]_ ,kV yQȩ1Şggjzt/9+=ɽ2j̾G;33i__Gvz<_9:_s5jstw}=/t0Wa֘нjNF].^ 3ٹvе2=E׫;~t1{Pߡaqv0M:aNy:9tf Tw8L%,Ƨ W_|=m/;Cskv;ߍv5]bǻXkvu;:#WWv/?6֨.r>9K^,r7‡V?~ +a.p{ٷy{˃mto7*~ +k^,VUɯ ;=~;o82܏СwAGT1fa=OTzb$:b3 DhD#(b@B0,$& aH$Ca` H$ag1>vE$fb#~_ h8l*!SrBם^ )|d%xQWJQ+)uX`蔢g S{pTĞBbц[}HLNa%ج 3vB)AGb׋ +zBP|!-~Y1+wFu~Gc0"IQڱZnK, TFOFWj#6lǎ)cr~Ly˧\TVWe9lXj2Z@3kE 7\2|_M݀4b0*ĊXLzb_A'8m/ZNddG WWo&8ĪkX+ +Z\1\W]O}>9G{=uXDW%s۹zzu zz􄻙}, ᗴKy8v0P8 HN޼*by놄^<+`y]Dd:)Cj{5GMPVTq^2_)%U|ʇo Z "#ވMe(Q*V\*x };0 +d+]+8ߢ8ទ7aImUAVxg˥|5F ^AhyEIgI8w%#BJc$呂VOu +*Y0P?zAS@HョM&P?Ew1r3\nޓX{ Pf7f}lu)F?x@l~r>>J?tiKaΪhoA&"4HX. 3y_w(,O +raus(&_GongPjа|HYS}ܖDQXD/m1ޏAA81\a<SVp:J,kKL/=!Qؐ7f8Rl7.RO62I ;m@Dě[GI<)e!V@. +AѵGE㪇u{ׯWət]?L!}hlM)h{?(ݲR{.˴nES<qx= +ˈ G墥IB^m]kTԃGb YI?QLb-E-){ޙ/h D Y@w>/S ucnTXp1=*AoDc2ÈMQNw鹓AS?p#:7F:eyaD($]|1!}uN@*{oz~ H17[CΜ-Xï;H &S"un+kA<< +E6EIu ʤH'9N:n{7i d>S$:v;O5p m__bSٜO"8͹9|J{N;ABs]ť4 * A* +g%|m8 +:yO p>uii)O/| +aSUm2| 8ǒF1?91&~e2:."@m*C:CyG@pwS%G +RrH[ԥ\0"Up\Vr:0JBHA{j.^~(rr$.y $R2x4=;3")x)!1K2 .V(%4nRiguíGWm{8%kpt- +R2BƆ{C@Ej'Y2py_ &4 ~^.*Oؠp/@HqF"(]DLB Q\{ell'MQ-byО5Q#O~ td!9" E;Mq.zFp7P9,h^$oG/I`C ߾S&ϕ위b%FB1{9QSs^ e'ٍ !ldP 8BnQ=K>tolIlL^sOjvdJj0^_#mq7)( X'F+{]BF݇x_WMd](Y+x.?sQ9-R иHz/w%J#F' r92 EæP9DDvL;w%.LhxvWͭ9HlezK'_5;n1"ŗdTVCpdY~Nn-/?a*!*%Q~D>JHr C؁nV)53zb{萋W|0USbɿ}~^̴9?)Z rDd6gXO7(̫`BHwS4]0);qĊ3OIOg˱MZmq0]@/q9 RWdC%D~8 "w뷰9ȶp.DY``w(\?8ܝ3(mޱ4{?5C?[s\ f)5[jy#SjlJB 4[6B}V̥DEaRJfoJS : +﬈Wi0dOw/16lvy;ʓ+jq = wrf[n\gnQQ&&r6?Tx)жtc8EzzʼѰ6%zEV~HT[ z]=ȩ[ +ɧmp j`$_ WR̥P +LIKthmԶΉq!Z67kc/^@8zL!Ȇ)1o7kbΗlc8$\bmgOv!sd.wm:nLvO3j+O6`bth2<rYgǚq{/7w[MiXryJ +&va1'涟I$!g(rfn<Lx%zٌCyE(Q6St:ut~noQGBLH9G+#(ehja遒O%fv|QAtt%@lHh˜M6Q5U\M<|9ľ+D0WAځ3(n'7vέ a]1ef:d=i`!_aUr␸d$if;/ޖ8g:z EvqÕ]yk`S>-+a*Ou?jRqwNj(瓬R}"_g<zGR r:X)εb3Vp ~"~.ɊѱXiQ6'.^L5(*~% `>c[BhnR@svI;B;1zitAKw@yptL.'2%?1QBE O06*n#Gc&SJM|{MlQ\@0>4PWtߜD91{>(H|l/Q(9ꬖ]X!&f+{ QmvRez~Rb.l,م9^!bph4YNS$&ӆ4'Q"J(^SWqtjk=+#5_} + k˼ pО\@{J;hO*N}!S|l܄[ RA{?~wIKax~e +`QƇd</Ry麆pBcZQu>sB A"N!HЊlKiG"MqBI{ϩEyE5WluWКP1":a k$lcLUo<`nP\[JH r'1 Kibg$֙MFCҭ:-R%3CIwS u8 ) B{_x?S +ȄMiztpLw5ǐVMNDZ?=n/ l4T=N'dHngfkh[g11 OС>fruSlQj1 "Zupb7 W:͖"JlֹME>֙*"8sAl߿Za~43oIu'dg?Z5@"X9[8z$['֙|N_ uJ O*.[5Gpfl'w5^+Df_9  )Ǎφ0[ϜIʲgN#9/-< mo^eXluIp:.k\J=<aZt!#nrZ+p݋(+[g[Jv1ocqo3qn qyD7JphtTϭk9Eah 9fbB-!Lh*LNm9v~Lcb%fc+[}2Hyo: fa⾦­3Z =PJXΙ)(]Y a?pAw)4V2dSJXdGe&wqx|CLuM뒮/h ˧P:qPu1[K^x2f!|/sO#$F%t2L0TCKSQgpbG5Ren v-+k/`)ngh1!% s'L&vLPWn=؉m2 8d&t'I=]=iVc / nS*i8-!L;0UN(F_:͝RBuҵ2_I.@ܱL1[jQ]P1rr%koQxgZx 6;7P u ܫ\#_$$=Υbp27G L/PQ歓sI+Ov%nm:%a1#P &ځomze$NThxL:Lnf][|uy3UK'9V1['099EgtSlWnb +JL?#^"6HYo[gƕ4-`l +nW*U]'X::)) pso3pneoXĭ+:ݚu:n 1:8DǭfN_Fhϭ3[: h^^í3,ʅ[瘚NkD:3 +irmhApr%íN!^ as|䶈 s2,ļ\b$;[Dů%M(rȱ:bos|*I"82. Ñ[gD3c~TQKW,g ~V̈ԔbmGKPHvƮDwMg4u2Qx/ ̭ctb :oh\j:8sd$P̭ ;'/ͭs߮b!vQq <[g=^F[%bu/a(uy^XI~$5+??orES,o; c7 ßNj\a\:\㭓4F cۇ?P_ +`nXKk]FIlqVM;A.)"ɕ3: /To2:q\o1cKO~.u^INhD':7s +bPuNXC­>PM.: H*7juBYl7]snd,MN;J[6su~~>N˃o9b2,d,Wx5ЮV8$5 hNLn#zxyHgl['fg@cj;@J +lkX7@c|*W΀D qmGtNXRn,n~P]! JuRq댐YLɺn(Al lMI[gl6K JIT,Ep-'!w-K:pb5f+jQQC^-s (%֨X]%zaҫy +^9sԿIIݜ LUy3:+g(eT$W~ z1;&9{$5E6a9c6}0TJ+ ~\A!kY& NHj#yo*od"\m݌*N.٥ u$['Ibݳ41v/r,2o-0zqf +),HV뎄:͙UA*n`n5~8>qᦩ6tT|Ⱦ-]8NTR +W6"=+^?[Z^+f`We$"1PD2 \'ciDB[g17]1䀍>aY>(b7K/l[YazutJуn](yTӦ5VQʭv(zT[ș'`_`WE[_[~ƭSUJѣGLJ@W/0uBnn+ydX, t-:֙*zK5 pytͥuzvC]]~9ay4c_WDz\a(Va+9γQT4m)˖WHy`Beiu{o+ŔV7sP;ˬ;K1'eBPЧV_yT:c3n4[ -׉Y9#y[nwF ֹ30Vp3n[eln B2qEexVIIHxP"['и:oq*T<쫛 luc:@*=hQ-,@r5G$-ܪE1"@$A~,< 2s봎Ǚ` b +"\,dR]vR,gKϥ_Kʯ+ \b>ĭwc ׈1@KtNfsMQwNuR;o>HֹM~M15HfHSJX4t9̚\ {nVQ !hc3: u|QH&l̥ u.f^AnM߲ӕjWhj5/%öQcCM3=A V[uJ5]xY!IOo0\Tg[*ٔtO8p%AG<:[ 'o@n҂lTݦGGD Nq sJU~="ƭo%eYT|q++I-CHBC9@` UX S}:G4 \2:#[ĥfN~{]uK ʦĭ]n^'/Jm'D,>U{UBΔVc~Xu q@c_7k+|c".1T/`=u*9+Ur8o!ZvoxpW] ͜>-!Zdunft%Vj`=ʀANLufD()Uϸ0uVLkKp쒷*Cp+WXANYzZؿ0J|;e `ΏGC|5 NR1}z񶤹p< < Ɛ[孢gcq2sI`Qޭuo$3_M$ s/o\!}l304S =I 6 "&aJf]+ZjE ͯC\B(赢IX*߭2w&wyo'4K!>3w+EFӣ ~qgKU\?3` _7 +l +|0c7+?u uΊz\h`l|y|%(%="1_I>}U +0g|٤ xGgUybL~fg ͛?sY^]* cQ)6~ *4oY,=74uYv@43+tNUl[P~fBs9kP_hv?E(Yfo  8u@./ /'/x|IIUN|9J([C hr#a OoQ$\Xp|b; +.IEq3N(Y<­@]zGt@y\6QySnXNL>~cY{{d&B:+u5O [`NoI|[ "]))љK:)eo\~# dznCnZTnr-8Hv[gO '+ /j_%K⨉euo.[}i%@5*>oy]24I5[77b0<-{5/hCJڦxlT+L3'M~PFLE~Z\ [s8@DGL=['I1W#GX=í 1ĸN2`|yyU TN *Kizڈ['K9'Js|Kĭq)j['}~ís ,^fCϭ3Mc0[Y/4] ٱG͹u6[码}XS.iun㭓Jts,A::3Y#*r |['|ASuQ +ۜ[':p̔Vc l:LSW_AnЛ#PDǐ*'kL԰ae%m%ەYpMI;KˠŚX\ngj^(dlnIcz0c]UFVz~ChJT*`s&l5^n%#0bvۇN3)y]pMfAmm&-MkI;k-)bL,i)L\Ťt^9M* $cHj2ȐA'qyo;5G3:J`ԝN(̆wuY`04RoRQkzϛTg-_9TƘTġJY5.Ɣ؁Scr̐%$7SCh=Be·=6;i։ vuRRzcMK=v.c~4pUOJU@ϰԟ?[gppz؆[NJ.&2N8 ԡjImw. (:?b=UĭS/+9>,YG yY?| q5-Ā`9o +dOssT: +.?5X;|P% +㴏m_n$f}Ͱ}̅>pK- +쌕MęT~QTda7:ǧcf50 ?Uݸ2@ ~.'@Nc uFx([?8>/ @u* Q1a$L( Pr;|&Mt9NFk@7:oTv.[q)moLO;Rkaco u ^(o]:]Y0KT&$40{u +"s &(i1-L-,P:\@(Wa/~2ΏMYIx>} nϔ(+3 L['836 `C%Gb!l(cX^.g)4fk@Gm&_#oؙ"Dcsu8-7tcE=muj&|-KۗyLMCgvNgjԇ [g/fd"BTKB#Ԓ/(lD'`ՙʖɏ{(LVBJ4 ֙FѴT.2waw<і])^Oc? %z~[,8Naƪ(}GDQK0;T98-ǚ EnLo#bS8zkwLm`IFϫ+1 %И$m@>DD\^igJQ.# -47y!V̹bt+R$V2 / - tenթrQ):11Ӣ ;ycB? +ofV;2es8Hz#Z`XX,P([$|P(`+\LŠZ b8 aX8 ]h1b*DE}eџT7%uVDeyf3:ibUt!k ƆGd'CHu~5n6DtF>WutJWF^uf?<"Sݍ!'ec'*k^3  k:IR#4yh^UJQ(7q0<-*LYvяeRc(55$ʓq*΃Ļۊt37#~bjVb#Ž̍xt,}\bTHjwƪ4cWqHG7cno1{Um!"{elu%Ab3]5SJvT\gDhiVbHH~y&w/$Ingc#?wLo$Ӝ7ac)ZLqI\:"j57wHX\$_gwۙ9\$kDwƑ91|_MֺѨTGbsS G :Ze:rK0#aoAO$#Aiq<q+Ҭ!rz՘;r.Lް!Ftdƍh4U濒:x/9 V + +@.`SoHUMYQGYՉG 6opɯ3}0Ȣaᮨ +I`P8( ,+ZED 2&nz44h"`N.92wAd;ލUK=ʾ^|Mφsrb?1.ZѬ(Eq $}!]%b՝,FQJodF;?.* jn{]8\tby~G817W"62,DK:4Z*ZIN1oE"`E+U :^\p"CD ++EMBITT! +,pD x(4i:4ψs1Q$| a:^knd-d)39}ƅR[Fƅ'sTW^&2P4fv$dֱD/m9;)-zNnXS"LV$i-vAs#WᔷTCC]!:mD.w_чKtq>nQ%fl5 2RICw (RL82\F ~ iZ hND՘ʌM6ROz2V0"Tv'7/JqU!G` +5_(WE! BWx@ 9<\ [`p`TU~f^U651C.z AG'wW:e N~r\l4@\F$3cnch؏H4ӑ؆x!00PBX`Ck6, +r=Xg[F] \8$\ +B ςBA^-pq%$X +3+ض3^XkExNQ ftZLHgT +I(څU&/QV5}5>λ> , VutWgsbڐ2;27%&G J/f`1Ŋ1EIN(8oѹܺP}6~֓SQ@CRGh qaz2` J0*p] E\5Cpm5ph1 +]Dp0E1,\p8P` +4"*g" ЂV`7jG 7d%W)z\]TJ]9o 21Q<9 3xT G)h7{﨡xN0`a )8)gF0` R;Иө5">0`lpmPAH  (8F P`( +*`"8`@ + p 8KQ*߫ZL} {;9IUudJpz-DXf*R(JPP8(ڄ[BD  ֋!fpG+0|`PCхud9Bt3v)J{X7OU!o^TlO~*S␈H\zFFz:uw/YN2B|GS $\tAVqݭh=Fl#dXPǡ"cbYwZiV),Cfh}mt͈Q$1XQ +dp넄N^m֘H#IjþkPd9Ǧ모i$59.ܸkvY픈]3νEa)rVfǜzmnE)s;!M::S~9P]H?r.T֊lrH8gdFB٧#4G_s%5ׇOVBF&ěf5d9ȦLFd|Va'[6!*+< :RH?!b"Pyx+vF'%Cv**[QmS^fagҸi:?J;GJgԵ^b#*3gB!g&uiJ )^nkBU哚l︐S,#uk&#sUwd^""XYhz6$+>:ngV3ȉΛVjrjf94DGd 2 ]57F& N҈~2Hœec3]R#eӣYfǒMې9 S0!+Ai.8*#-ʪWiF I^h2>;u:czA?֍Ejͩ7 15 -:+ZTs6~c7O#S.G7=͚;~fg'Ϊc|%\ pe+ADt6!G?}YqEDu|i.5xQFhDB7Rv!-8Q&|f:F'SWOy eCfY?q*ЧjvGL*Y񿩸FMϟSP$B*\*o ]JWIvDŽJ$xj,aUlq\$Eõ;Gi&J+vhy{nene!b#챣ܐN%ңQ[wF%QQjX8 }+7߉t򛩣'ȣ87>r64t\ǑIQU$"3wO}2eN٘37kMjeыZ$YQS~5accT1h,C62^6U6"jX8Dq?rSfa4;;tLiηQkMOh$4l[f5&dIccF*'$ol8 ]r9T#!ujԧqf՘ʕ=S25Xf(S͐2ydC J%ƺht); eOAX\"DCvr t#Lgٰ&|cQ-($(r(H Bh-XQ ` G%*߄vvHc~3Ӕՙvolk&v oVr( 9/*pP_1}aCH]f3Y_c" YĪuAF3##[XgC >-[aU먪'f7GT ̝M53hB Ѩ!ꜚI 2Y j:(5Ē :iIUs#\F'FUS}C J@FbukCjPs ݹD&V:7+ݍ**!v#sMk* |ʡdRްX+!U=Z֐*m.UdH,c"HI+MoQt-sm[ 4ZɮJD-1TގH=ә'.+Ú⢟:2C4"+MswܱT3!s*Ci@enϕ*TfGD$÷={;Ⱥ ь""L.%)B.G>vav/2,QO6ސ;-Kjټg^٘*=є4"*isۨ9m6aUJ'8IBDh\z=1݋ ѱU5:2)Gl'Cf\{]({vۜjݔoIA] ~aSU3U94ȵQ&r˻bUhd^Ϙ832YR'!3?es\|heyuf~565$c.f>±;qD.CxhҝCwB,Nه+R!'zڐVQT=oFN{3zTQGHRXɜM f5CTb;T-jFɐN$4C5%-rYu~Tq=.8“ӯΦh663ws%?|Dlwy/+EȻ~~>uu:n4wb:&3+Fh3ڋV9! _=2*:ǹٮ66gm:Ww:јn⩥rfbjyF.kr3*0zH=74ʊh\H'A%҇}ܳgءPXx P,| +"ZQ1Ep>X9/R2Җf3RJ@ˆBC`p-zjxv8z&"'On]! 5;hTݸHs,zvJ>e/W"uX߮5FmG,IFe'E wug>ѹzе ][bN){4UxY7Dm<2ݨ1OGEQE2rq##T͐n♓ʸmWuƗVY!7ԓz7WYyWz~Lo|֑A/e1>'&Bm\*S'1# ~;)34@5vඌ鈈='1rѝc*ykheG3?JC!JhhnnTSg9p0;0pE5$XhH,3zL;Έ7;yETp:@Q|5A 0$0A FB8X 0($+8 * Aс`0A'h  + J@4@8` Pp +V0u7f$jÜƄ*:;1|`4 t9qG 9Аɵ|"r,PBBFB1"t$^bwRc5lٸc >J7C UN5,p\CJ Ww?[dטՈPȤu)޿1=^\Y֚j5FCZtw:QӺmևmf}tl /s6-h,hGAaT5v_K'Δt|4qٜqv33('sC,i֏PhX=ٸzFé׽poUu6ZFjLL̳l#~X4ٿ>JTa#YݕSk,x:޽dMWr3񱤌v7)^Lo+IN;L~̨f$ .~UI~L,F$r991 = #N/x71=mdHX)}ϋl"r;;nɤ糧uJ]Sc~gXXFM:#41491: ֙ڷZd^{)4G{wJWש&dd84u̡qUXCTLJQkm9_:Tf\S"n$ݏW&UiVeTfQ6%!NLZvB?kȧ*HO.#qL$Cd3!qHl܍Z,"rEι'-6ZjoxuY}>:$rW|dIvhV2fHkyѽ<,Y'}蟔dȐ\nBT&VI(u6sZ(Nds›Ԓ.Hl*>;+vn1U\,*bdwcWiˡZJ 1ZIn,C}[i/;zuVC7]͇b&8#ZYV%.!";S]dVƮhF1&hLqƍ#,Qw7(rX; ~B%/nV;jDǦ+QJ~+]Ih:CC2vFE?o,|2)VoTWR4Fg%Z"MLed ИQtÒ< IShFP2-~.*( (1 @!d19AE>Ԅ)ɶ$وUTpiC/?"O]zsv엩Ӓ5g*ah1}\[Nۘ4J݄5D NEX(ܜʼdSЇfqSpBZ쪩aY'ӏ1?ILZr׬#E VD'Ax1Ul5!JXڠ|#(kь ] ,cρw_I%7MTĸ lWC79p.5T6妄bcm L9mYt%xj r3|1;"#-`D jėCa`2 +ޔyTڇ}U*73K2ro";X FO2n ,n%]N:eIe["lBI8RNs:,q{񪷑ĤMd~<Ѐa$P&m&-$k ڮt=h۱.a #DGxDԶ!ᡤD# +28^HS]~ܴ6_]*Ҥ#l8H}LE2Ɉ#;#Ts+b5K>[ƫ)`✈cbj:niDn +hJ<MxdB%_=tz~=Po-0[&uZgtߕ ^~rPdx2|#TAn]s+3̩d`ڍJU4,mR{j~n<~ :8lWH9bցj7VEGىL``jrZ}B LKUnI'X}=EbuV/,էgĆ @=ߕD:/|mA;՝v^=>`dDyEܛQn1~~$ݿB%L˘MpRwԋJV7\UnA <4 aN5<M@#Nݎ@jxm?{ [U%0.H2Lz/wтv؃$Pr&d%Z,Z }Uw +RYJU +~PL( ;&zERhE!F|R]-{^ L}rU|7&dDhp:=T`8Sm?Ѯ{XxӚ΃W}2Ap`sU}cpiX{bOLP A|/joʙ/[ '~VUcd7iJś˥ Bz/!Q|s|ww\:3 |\de* ブ,cVhgz:{_Q 9z[}:O[4#G,Y + `'s"=Jx>fwotL65r8ȧ=םFM u<ؠwT&KCf,[*M, T$=S,%Z Q5WAI~U 40j403/]++uȿ q )Ård;c xof_ϝ +tDlKH0W5-j6)D⧴ϲPLt3@.UoW頿Z'iղ0hY[pesF>VTX qJR'}gSMZ@T)Q]X])%PFjG}"-je;_ Pf)YE|+v5/ } L6W~ PNqҖ ]ːC;'T0\abT)D$-ǹF22X<EL!jte"EaQ5lD2[UQE.6 +ō܌: ]bO1 +zya(8B蓽FM-rs 2.pQ^IL4:-}| lF"{˥긗{lR$dɑn_[nep/>C~~k>^ +@RMi> +D^H`y4d-ÊP|7fXS])@b01{>řzio.&E'9crKȌޭY/SYp#Ѣ"e͹Qyoe*=-.)m%Sh셝ML҇;10_DO.L滺>|p!˞h! +$0&QczEϢ+"F@SY(+;%[<Un@㿘vj&=piRIA懁ji/H]r,{ +oB:6'K* 1iH\pf3=lzIyf4E?2;eacJ)2AUB;aX9jwkdx8 ~Kw.a}+"ژZK~oFՠ 㯢:x:LAmŢf +9kfE-!qS -0XǓԉ +(6A.RʗH ڵ.z\*eV[bHGW$sbb,qMi-'c +a>q!k9BV=m,*,;4 +zpzL쩿B"qHDP`O$B!P? £A8j[v/gsH%n%sNMDx +xu3E)#J]Vɫ.KpzFZ̆mUjeG65̕qOff#»Nh!K8r` O78^T-D[Ci}zS~: m.NAћb `bBjNwg(BX g`Ŀ;Za#5( +`!;7xe M:Y \ӄ [#Ֆ( ctcef_$ +̗fqK|9sc_Ӻޑ"yWp=53! +3m4@B쑶:0q@% o.I `QNcvrDʸUwQ0|[#nvڨ"C:]Ē9jiXP`ʃD(v)!_ +ģզ GwJyI3d~a%]IƐĒVz>H0\V(v:/Vc< +P + ֡}Ȗ +x4)"rM)(-Ƕi.<%иXmQ$aoGA +RRI;[f$bA+^kqh{)j]64*`(:1[Kb]xu۰p%G,ځ(@s]0!uu'!JrYi[$ӱrc%1KfcTZ|#IA)Wn/Yh(/ք,z+[֭0qnaұY'H.*vSУti/*S:|lx{joݬs,9M^@.QC6~@h6g-&BOLNo&+293<~܄abjo*+u= ++?0 77j1ƀ˜'?ceb<ȯ2x!}d4e,U(H]WH;;2Xb kOP)kN)kvj%OkR=lU}2WƁG 5utj"EN6xR#dp`iA2,e)'Ywis0J>Mv"3@Ctv@&n{E& ڥ{{Lڂ%b)8D9{]3Ρ;$t:l{A6Ν"N3 Sk3c& ψ**N/0ޣXWڱ|zz2܀% 8\d|ᓣ1Cp cf:`p  4ّ>T;GV)0*UXZ+=paN Mrh{xh=G6*d.CY™ +A6)nKSM}vpaIl#vlW12`*pTs 5ջ)~u~Z`3 *FkXƜ"N+%uq` q +@aOxզHOP3hًʂRf2o"bڨo80o*bsdE+ZGbm&j^o[D7V- =Ԑ@Gx\S6uC.+Fh^2{G" :l5]E~y_r Դ;lE[elc?8gQPIPw=hݫ Sv:odB?+GMPIg-+2lHh> U&t Ωj^R⮐*$*ddISgoPvTmB,_ m3Y6`g,Jr9]DN)Ro#^ކI3}a8[ab@c$yпbK4GTz,ӑ +,@y 92Q5 e%'kjL*5Y؃5I?*dXc)BV'8{C!2=RZF[|eWrkSR\5 IsSa3YURW2*rxɒx<쁢ߒ[,Vm%+5ef\cK5ʐNEͲ۝*dN ݌'s!k1()#^-@0>)ɔ%n3h7gÿ۶͈% OpX!;U2"d)ɇ.-2\4Ry<4&auw~=T,bZP%gm-.Pc Y̼Sm^%/d>"z;l (Kܢp};||2TU9С68O0 GYo:w'~(9jlhG=qhN"F'`qo9w`[ ]`W0>qtѷx^3OĻOݼ+:0dB9jiORy8t߀n-~ۉnЁʗ""i2|b1>#--f<D i3Tga}8 m +Rkes!eSUb:#DބBZ ^YAM)-qTtΤZ%X<'ЌZ='@ N{IDoY*tt-2}CH_8jRUY>D Mբ'MI\%]vqD]Zə!j*AIIFMPTj^`XNX(ѕPL:%uBRP.v#W%/E\X\dy`=dRG7}o$D^螘$ i$c4q"TC+{QG1~K-ū uN7L1!**0IaJB/Hsf{ r\ƈ%7 bzU;"o>e`Qqi`R/o=GxgyR +ȫ9T fhtܘ˵ 6hG>ǽWxxE=7'SSON=cp/UZQYWڇ|\uu;S^OJE(b(blb9)f—/J[6E 9 H{%ґQ ύh6$Y٠=U6 l#U؅g5X9|*O_ c6?7;V"-  L"/{X\^ dSIװcEYٿQTK +Q/>Uɻ`aT/VYfpx}+{-~z3 +T++sL.K~s-SR|%8O~=CD$Jj9\bb + >_ |qD\~xleFPd/6lR;|3 QIxq ֔B*3uu@Jl{"*WLV&%3*G?-sp/7lf6 fE B2TNBMcW<6&*8ʤ ž\1b1!-ϭ YƂydLabW R9t/]Ió]Wuu%|eS҄}oBnDg1 +V/l[?'~0IV㴗d(1UeԸY^^PxQYt#|+ĉ R0_1ȡ}E#eq@@k{b!Gx~i$ŸŽIa4F9zBKVoEPI5!;R9wN8~=7IhɌ^)W 2ZJY`x ,C".#Wȕ?̟_=ݫ柡+w*{a#RΓmMI:3diHZ^(llCדXz5r4$: +W~zJM<̎lϮfY%ֆ~?r*cƹIKk*: }H mRN|eP0!};+prxuO8B<|*+nWʿuͰnr>ȆB}lh-%/n=}P4Υ* Q#@ŷ8R~u%o ,^ir޽h{.^b=O `,NsScPmXs|J"49Tf' OFc2-OFW9& +R{6L"c\vQiO ǡPȂN/;m+)#[o(VvK?|^j1,ܗz5\&@_"agyJeG0[AXI|ؑM@y-(f7V--ٿ}MőZ13-).pi#+hJcЂe#HM*ny}KL> ksУ"^;Sp9&GeiRqrЗBHfxۃ{ +') <]=cRu^nI%= sawdA檀}/A#`[߻YjnkmvV/kx{U\!V[|.$\j0S7|eD +RQe~T&Y +x0$jQ?BEί(ve:sTW&S;mY" 6u MD?֠ 0y`0eg匉XRzUΘ>v#OG A[C DգZ۟}z?:~dfsjҐ(E"H䣂;{d7$f(l$8ęSil{6D j)Pzl+09}E7rXH#KL UFv֏"FEGEGyN,#NwɰZBB?zhboE9j2N7aJb+"Άo)ٹd1b̕y=r/>BߙgfC7ZF5ސ p$6A)b,R4l!&&č +kЌ&D!cADDaav}aq^*IʄhΔJctNh)ކvgUU6u!ֵ.'=EeȋvU"#Yy{dԚJ,FXl +Օl%d*y,S"Zcl瘓ovx 'i>9'rTƗ-VRnYlՑ"a[1)iNcLX; R5VWRs;jؒokZvtjl3wRFI̝erRpvozϑRtg;xRFu\Hsv;G^ϏIgDM(zDd74Z:G}b"#_rTS4Ry7 I\4QY}^N._x6~llaYgܿ)G [DWܛfd*9oG&sٽ$<ǭ+kDuPuF9vI!qzLuxexf;k?IwSHUwZSwљq{udrѢ;ռAt2sc]&{*+uıc,}.kM2cS'޴Ǹ|UXOI Uf9糙jb}֙ԫ|ZIX,YA9t~Q%ާf'=d},=?~rU? Oie92*df,)'hjo| 7LOiβMj#ZDtUyjDzr*?2z^;Uujײ[Gԍ UňbR4vEgh#=v9ά1!ܪZWdcUM*c*NJ:B*Ndct{R6svdS#"=* + , 6Q<ׯ㤖αNzXRkEHE;n?֎1Mͱ>^O9<\ǮO9ihc%|aH&:ȴR->غm*|\'t&XUѬ&H.a-QPv<=fAdt9AR͌,y~t&*uCH3vl|{g6Wn̪&9sxi#:&BA%vVIiAQq?2vD Ň)RxЕ&tƔY.4ee>u4ũ9m7g%:|7b+9HNn~%"uth0FHMaIh)S; ь!IH|b ȑi~T9^Ǧjjd|bq*ٌL=F\HvE㲟:Vxi:^+ ;hx:W*B3Rj 63 }tRui8u)IRFn!ɕk.Y&O>pΌr|bU[Uln'g>F4(M]9rFba; ia6bqOat-ّ*M^8dA3iPb:NJ%WwVt{YOx?1U4;Èwhd1W̉3Td <[~\zaպ+M1N9srX OGQNscVsa;U# Ql;6uCjO#~+Ggh:N" Ie8">UafBrBTW.sL4bzͨ=.:bo2b-C%"=~sCSMuH3|h77:U]j͘Ȯg14deLv:"#1zz6U"^sP\eU2AT+Ae&!oوd{U"Cy^14;t~d'D(,ܨI JѤ(RܸXX4.ܰ 7~a.L\V&%L pzuje%>D[gk"cŢ(rcHE+T"2Xr]Nغ1 N{QC o>Y _> ijՊ4kw+H3nAAeL!rjy8N3Η=#Dwj+ADr9:~Yx;niW$n~ľ3lB$ SN$, C@z`Aj>D&;\62aD(A`(B.L >T(#tCmf/a, Q1GP` +A5\TpB 740q- 1* 'Q!; k/z$v +Nȁa $ + + A~P7N00!H#, c"\` +C +, !A>PF<4X ^XBR`x Al + 0P3<-G#tx:\C + 0D( P6'z$x +v:@.X!5(g1p@&#CROM%#$j0! N!`s(A,~`Qj0`JCf؆12.  a$-ZWW$a `l(@qQ (B%<ch@ DP4wnƌ(..n\dzjnj'1}Gij띳Y(.'; + HuXId|?̵+TT0~+~<9^xf|gx*" )(Y((Pa1)aq 5E +01eq!p'HuoC]M *L1y"̨=s|fx縙\t&'(EPX¢ְ ++̎IWZ-ZUΦܕ8)G*9+:Fd.9,ŨM'~ytCVDʷ)mZ*9q d}pI aپ`nSEĝޭJ'6= /5 IknSO: 1 4KpgXA\(q;b u,zZ!!`llf[ͱAaWd)9ęu3>)U:ha] !Xs#׏Zf <8],bbe&}Sflre 4# \B nEBbcH) 3a!ֽek685'Co?k%q6n4!BlpAx,i =:Npv)>cζ}[WK3zmk69i*}T,Q>!E?.k(w3l 0$`??`6o6k, ?1-Q@oi8 (+!F Q4rcBIV\Pd+LTw+ \Gc~+O7 40ESju߄vZK E{j48 +b#ؚ :v$31#fEܥ|z =6mZ/!33'J _%jLqp듙-,d$zv̩!+8=_x N0X=$rD4|e獎1ʊ&X䫄P,ĞY,0u>|VN8)"Upm5=JJp%E//4n|z:Lm7, +uugliq ?(p!-h\f &&[3 ͭ9}-ҌO;ZP|< )iv#,N7l8Ayl.{015@RG_@|RhZΤ'Crt̠oIFG\`*;9!1^ Xh9x[L3eR\@ȶ7;HN ʮRZ-ww!iQfpkTW=Jut6ҥ Cb Hbopڔx Ų1K<;~A /@.:4p&"nX4mmVΔԒR +à..ÏN 9Σw:fÈ1+d̺Z +hP4tRrǓН eIr-sۙږD[3=?I\±EDX[{݁ B +"c7?/8hPU]$!N XBׇ5ٺ۪q$JYUOj0P;caxg|؂gEUӷKH }CU|3n#✄&9ʡNM}$^VgLWo3H@CO.h `&nU +XȐZ>c_F$i +56F1oTt'&} 0C.MOԻQcׁg5Ǖ(4E&@AbH{ ˤo͋gW@᷻Mv2 ؜:?sBۍEֿ@cݍ/&1;`W#!3/ܫ4/7硈I4*!KʦKR}(9-#.u7Z]Q:NDl K0J1|.櫘DAO&2p|px[M=fJ;XoN;|xKvvVݦB{H%T8 c?ؒ{la xm98E)Oh/id]cYx9ƅ+#nes +]ŐBκf=EF|tw@G`17|SìB%iNQv`W}ͺ! \erj' +/φF@$(cxczNy }+DZVu g7,-Df"7x|@UB TuJ;JH@Mo՚ep(X}<:\I/ŨLp:Jn,t;_w1Lxߧ~l3 䓀LHڛ@/_/+[Bxw o1}mLkD & M!j %7~zXuؽfOs}l-v 񨋽CTɯY9b6ǚz7jiRgTJay@dC7Rj˂TkX"&,@e/ÁRU0 Qa" @ԩ aj։H$ +/Lb9yHZSAQXVsq]OtC4,j*etإ2N;hd uJqW=X)T~࢕h4tüP3&gwH"ld赥L/#dFG-ȏɃtqGY ^3j~S#,{]$1` +R D$0o0R3[Z:m֬Ovy4I&.sLmb Ð-Έl!c'@HبVmZ&-mON|H(}Qۼ(TS˻t紜FT{H+nHAgj_TT5?z%X~8q~A{h^y7G?5Arh@g v2X9=%tPn>)jj#pqW-.]kVtc_?l7pjOnuOX+fq"U;(]uQY1$& + k% _vty4ëtmUq >jNmXCcx+tuk?!mBoZ-90Q^MpjrWɩk+e9!'v3dP@AF_>CøJ"Z qۅ\rAճurTЍD&U R1Acihs܇+T;,BS(ɆeWD*^5kŶ4jsTK8|glBO~\+z匌ݱ 0 rA7TA'_L:7OT,x[sD4aJWhP4u%sro;d8jr0N\A‚Wa`VYl, 졀K0Ȱǹ[\ +-PWB*pX럩r?RX4) JRHJ6vʰѪ([yqwpm1͞{z@^)hu6Κ⨭,5T ],H 6ntJ|ј0Y HUK f @}kuS_ʚ`n! +|"6MX `(B(ən٧ cQ^ +o$ `pU?tũ)'Yk3%5  M)E~jW ~Q:(D7A1IJ1gHճeqr$c,#cE+@269S3⟐p$S_qeSncYb#"Wy|SfzD/'dh.AA4uHH?^lDpV;o +>$B `PB_`~&v +@!9f3WJdRPSBx]P'%UNXT 1¦GAwyb?X)Og[ +ucҳ"7c>ٻJIr̄iOKݽJk#D#a;uV +sk{#Ǿ6Q"|*?g^h3&r՚ )xB+\߀lP\2AGBݕDV5>jRNo^+E\Y{3{sKP9pF**y.99}w!j8I7NR磢ņ +ԦN_.ST2H5ZO:D_!jȱX)F/i* +' QTh>åSt)Uן;@W2']9')N88L!`~9 :¦āB9/b%vVy(~ +w(HHjZհg\J.HC>= b>*n8-06t-0**0bE~)"Se b*4znfuO)v9(Dtdd %f<PZo!]I7XhXSeb'qhn 47O$uvDMf9N%JLKhJ9_0E0g{(*đMQ(s:WA,M"J!7'pTτ] T?R/}Rtj|iS>`N@$Yə~.٘8z=8) +%tjmy(צ%te8!*`{d)Uq>` S$AV#IQTd \[5jŃM}b}Rᣣ3-WZhcCQ +. i閌XSƊ +HS_fQvéi@;+}B:@uP]TXȳV-_jijW+h',AQlɨ$`ЍYJKL{+iKL4Hdd{]B{ 6,vW#"U!Uw8ڝcNcaF٠[+A#BAK9 adg㢞V9p$?TD^`F;~/| fr5$ƵRbM7OO nO4t8x>;hRLԫ-mp|a#)-bD9ۺlWl8¦2B XzKru9P^%Fu̶S˝PXcx6N껼N("QZ+yTdp n Bxy~Ag22繿 +MC>bh +ы Olρ*ֽ2M - MRlZA&+3vCvQFXVrZ,[s#M'z+ZFu ޖ/@"/qx6CYNL`8.H.YK-YLoQ5Ɉ{)?oՎ_Ew9C@ƤnW Ps]K3-=oGzߐsO.z;=}l` X}}8YFy@Uզ3ܹ'Uv $cݟ1L c GpۙqVoψLlJdBS# 5{1n:pF ` ߣXɭUU} [k/et6]̌(\cMVb&[mUeڞ}(`) :6ǥykA\璪VR~ӆJC<&l:N_jcEq:i9a]gg]!p%8伩Š펽(mڀUIbebxbI~ AOn +_#q?c7Sb4#I p\5B@*+F ,:2k;pIAgsV: +;&'`Xv FzBNlhPƆʜX._@_k Y)c/"!3ED_pQ&Nʄ3Bfc&>.`s9&F3玼%WU,A />Rch4b/qBsT9)YMYJyzp5ٸ!xR,s6R; 5Ҧ lzRD +1md|Phm%3ѽ~9DC pQTh{{{{{{{{{{{{{{{{{{{{ޑ#NH!^S9|sCKBDJG,[`aePIiBrY"sp=Oꆎ>Hp8^ H%1>F`,JVml|hpRl +Rn ."R, \!(),D.`2ًErHLAȇ*h86f;Bp>%Azfif$#Mn Y*&].JRdDr*͒6I1Qjj7H8-Yʥ00GK0Q.JdC!pENa" ^`CApJ)@msU^Mt6_ic8\9w3Kg3r#%@T#Ȕ`!Ʀ1.79`LE9y +L3PR! sZt nbC3v3M &A󠁌8FD̈́0,< \.&gn2XG/oK ARw9f԰) P@O^xoT=SJ%Hl,6?L%N3=\JeC+ +҉q +%H)d8[$Mz]Rਔ0q݀aSbsfSG2KT!MNYH$3& 18 E%2AB~S<W)p= yp%'. !H@ղl6T7Arr&#U`i6 +B +PVnXHFAb:VeFb07#ISlBQ BpX +!1 P QL-U:B)N +Rm.45l| +#*+R|L؉m&. 9. z),>_4T1>n6XP\ \>"osٚ%p%<qGva!UV$-T 4G.m#QR7ћ,Z|!WJ|Kca¸ ^Z] a! +0!ndƄ_L: *ئB,ʤ6&59ߋ;GǖD٩bq&U)X0Еg tI2ܠq_#"I\دD (uŏfypiA6W#I{djl~]TҶ& VIUxH:f;[9D >Z_msK䏍WOK"SxӺvxCCQ(.WSBvAviBn*e3'\z' + P:HE 82+@6B%WU'Ͽ5`0 btN +bUUyyޭw>sb'ЇEgIz[GbVPܝ;Ys;$ɍYmCnwD]nu$cB,T&4# x,ո-Xy: mH:j0Q +H&0 |SsDq-jt;%0NGѤw]\F.`6'N$#4ߧ`ot [&= +qTb#c +m]G6's^n={txL CjALcK^ң1Iu/uƗPcA4b ]oԜB:8xǟN:mm* %&w +cԮ5=xnw-)0XNZ@ꪄR2g P*:dsILˢ L] )[Sh.M1. 6ziIB*)Q8'Ɵ%A +v# Y͢&hX7In4Q1(kd.3wLα& ֣Aϵ, +h I^4%QU]<5Lwذ^1Ĵv7tҴۯ~51r?Cp,ޓv 3kʍYR2*Κٕ~\Q|3<3vANJu$%Tu%w6 i'Z5rϦS2 !R7NIVh;sޘ3*wY{FzU׋ qXWt,hy`"}w+TMQopȨ. ,ۜVWn.AZ{vfFdWh.{թڨna,3#sIy&3׊/i**sVFZ4`7YZ;эioTr*&j&RL͖VTO݌U#{>1hcvvMδ#!i3tf8{mit'V;S5*: gj52^tG4yn IZiXp|R19rGcCr4lإuva. : 11ђ'4G O1أ}kFyed3F(5֒˰z&i*w2#X=>/k QIQQ,#2 qP2s2wb|]ATw4X.)6" հuO_;cCdGT%މ5I^MԍR}2]Vxb Oi6ܣtLvWWU;rM! 9x.1/ sӠȌU©KZA1 ZR5SkoCU_hLs3ס2il^Ercf~ȾקR̜:]pXF>:$6V3| Vt*n* dՏ0vvp!&ړf7Fc'gyoِWwPnClG"IKCLnǖ^VBe62t$A' Ei \׬5ljl=9 +ON?qPF2N@Qv" 6u~Lf*'E((|E^X5JmZF95J6>uT,}mLҙ 9"Y7EM6rAVE؃YJ4fiTFvy{S|jn>mlSqGzx}ÑQ)G2lQ2u3̬a5ם?BQuQa)-F*+Z2\t"U}ˈБ:_RŪ>3ФQmdɯv2lcΒQBTbEmyLyt:4q d&QƤx0-SkUju4^!qVR7NERts[9e@@F#t蟘GMj+-6kJTvAoVڪ[Ϫlc\B4gQTu iu{Vf ;mH}$A!*TQcHNŮX|LG1WYVHso9AqGm 9%^%ӄ2 M_R+aQҋ_VL{ۯ#V;c^OD㖱!weC6Gpyhv"r̸c=S"CCdԬ'U7fVb:/chh6eȌђwOj)kоb 9!z51I.ˋqMsSByw#퉋td!;ҘzLE=oHo~ik݆Nmmb"B7om:Ĕ-zVkr"3R) tuЍ;3dm5שJ. FX7(Fy熱!N"2M_$hl+fR\\5s&lp=exd47]Wyn!$QcnREV ꑴb:!4]h +ɰ= xkN l'6K ;7FA6hҏL:GRόey]9\B$#V孝Y㵑ҧcyM$Ui 3 к!i9֐mԚQf2Z3rRkͨD:+FkGa 묿1/Z+nƼأ3u\WhjnnMgl7*o~~JhXDfE>~eɤa) :MRFVo5֏F"^n>F=Djm\}J:KqN[5h~sQUjH4\2ՒZU^eU)bKaLޠ<W3g3l;ڎ! [W .i]k8|4 +KN.ePXaY Fc6V󇨎Sf:؊AɐgR D3izqƽ=T<.%EGQ|>D, _C&Qg5CS+̍7noUGtwϙc\qjgiZ&m4EFR!#i2SyMZ e;;5̜r~<͔)U'zCTn^3u ĤΈug׆Oc"{L̲Nbu7{:{^VU6 Q-[Nck:֐٦g+ِ Y;[g9joKK|ُ_SK6t @%4FwQh۸e\D"d1d2 y*;Ť>*63Qb3B7}lҟ"QRmUstuutYesX4D{%t6Le*нU?Q5&njSR"fNhvl,ȏKcCX߆˪J٧+) +1TM2|tPÞ, P ?f(.]a|ѥLSo/_*K5Q?S|mk~a7,7rM]11+,_hV*ciOsrt"[9ʙ5.@S]itSgTX[x+N땱jJ:7ϡ;#XsE)l=*ϡeYDM endstream endobj 14 0 obj <>stream +Yj" ))s24.JЦW",Mj)#)/}E%~ +xXiqB:Mew)] h8Ny4G_friƲ#N3&)eS$jSFYэZGEWy(6GI-7+++yȁnї9k[3g H4v:T :cºUW8JZ̃X}Z%e!"~.?wtDL*%!} Hbr*3OÑIHBH2^V2&dd &7k߸uϜ،{| {52ai3̀ޜϯOL>fF) RJJnL`8 &TP;2%N^%5 [" Qc4 9hT6ea~4+6ԫ$ *NAQD Ⲏڗrsܛ3P}u~gtjl^FUK򬦤DDGj|?_B~T.+W?]4zMݴi2$iEi(D]GE<2mGsW##t s&Ʊ@7 ~/ sҗ'۟sѷ$RvrC l;i,I$vXVݸ8C2_aJh ( 221b, 8qd@UYt򊋕[q\z 8\FF{0(ut>73+yȋ:ƨP[Gx#m5V5lϫ"-:.T(n;R/D¬.[~Điq'7jq3_9ʝ/D!d@k? ^ڀY9deljpA$_30(IM ;ҝB$dG<"Ƣ!rj>&msb{;#Jr%Hi( M(OV$wgiTf/\Uem.3*3w :-s ǔv6Q*ݦty!,7)[KKi1f8[c\-4}ʬ8)k-jo-i^z|p+w@lܨK9ez/t&<''7E{qJ_F.P~҈GTt)?$E4!x'?!wFe +wQYc?Q~7̷L#Hs5H +4k7>ZuEgU,Z;Ia+At_wǎqOdKأm)/,pl,or,8Od⁊ETzjoxaGm/˶ Nv+Y@:I J 7D M`q'h޸Gu [}_g- *ޜniiv4ɦ"/K4$n)=щRAjlS!Da,ڢS>ǂ{ J~%3 +<<"6p>mVpkYBgH>kN~=*(KEԽn)9U +hmkj*d}~k_#WY{rLe8x[:ˆ{@Sh/dNdţH>6vA gj"Nt\X&dzNuH>71吨3Zq.W~9^D+m{4i^};`w#S#,nxNO:r<}=-"HKEwz[Iwf'Ƃ7e7,Nޤ}llxRm`nfb cdyI.4"EjJvUƚmh_&ۢ./Sq3]WS>pu;t$P'w.F%,Oh *%3<i`U&vj{۵DQ7'DbT Ք@n$/&JG)v; 9Jѵ,?~g ߨ*lԄl͕p&uML h'm=VM$H}x0 ;{ӯݐt䘄tL_2L@r[~̤ uYFVAǮ7BdA6 @mipBU8,n\7^X)qZݸ;}e$?2v2kr~50j .iqe GGVھEMbUK_F/<5RKH:k׍ +!rWBqeDax&@`CIxֲ ɱcꌙQV܎&T 3-Yk5LSXdK+39İz}Nc;s:gņhUt i*y"{ٱo]Ѩm"(=w2ǥ~)@Kzg%~܊h5}J,n EH:9Ϧ7*e،ˣ &I`C_| ]Og +,R-̶vfN7mtLj Tg0 prWdS>KL׃F uxEtJ lC=B?,?KG;4C47 oi4sve;e\)NMf!i9d?ߤiT>L*"xH_n]Ǥn&>RR+^T?(_6Ť+YxxGbL*}\SRQI#BT/9;.R }`d/BB%_a|! C8Vm#'Sߏ*ٿk8/KP$|&wrxNLxY8^j^8f2/|ԄHfViBAIf#4^eM 4qoRjY|ma&;&s$j6OulF!ێ˷!;t ѐ +^;mV* +V EHҶ_ScIS/B(|bb -gzc ђɭV&zg(.LτF:R\OSad8-~VAQ0:6(Y O`W, hW} +G28(Lr+qP@Il qY;V +YlhKaw%1g mo?/GI*C~'͵&D2qžEbRTK.R=y"o׫3!gz6SGA@uNaaT_JU +D}1),u_%fZ՗K1kY,ʺSwLܗ;Q0hzMa|YM;jKW,v%94UZkk$\SKB/yZGD? ȼ<`45+*)I,EP4?zeՂuC0Td"ܻ͎5p8󘍆nE3[.{, +! +ڂ7N {DjK]6'奭Ζ=@yn@RARh&YM>^>II/".Vu@4ce~cpAӅHLMgmXjwք}a͖$?0SI3Ibfr=p咶h&BJKrթu71sÖwv&f2{9tosk^rtSJK6|2 +Gj'ddlyGmqrp/HF1S @e3]2l |6Oo .QyZy>ʒ~D(9,sܓru*^aLѣMK}#&Z@㎳ m&$e=o#m.0d4w&<.ʺm1y=R k[܁Cv-D+w7g1x!@51K ,YܤX8"{ba`;p p}C5㡖$Tm,zK.|h>aؾ́ u}G_5F4FfOk,>.{g(s5qu)0*'( #O'$&&a>4e+}2:Xa6Bf V:ȼѓ [RRMSԽTzZG O(қL-ptlcItnP聄*ʲetCbP6< }Plf~|HJj ' C1T>2ur83E׵sQgb3l~Aj DeRZR 7f=f9oZQ͘;AP˞}rg,FaO&6M.i I.t _T%#ɝvCHTUϪŞ(Nk6Synĵ^Z\2]b\I\"/Z)xH3֌3Lz$ݕu 1W,{c!+hlIdܹ&V08ob&~ȴqC^lW.icQE_?~?;z6)V1P0(FX]J; wkG2,!. kFT"O^\90CƑ`D㪬Wlgw _ XNz`qUK%K|`|ej>i*z8ihW_gtnMfb[U}n3.Ii66"š~E\(e;je*tw5:&)+e4[( EI6zJ %G{z&{#J6C>D"r҇6?qI +S0[\1Pґi9,TRIٖbn~q 2?ldTAɴQ@t8E[bNt HK谰o/.wJv K)0HƲn{$Xbkf%ŇV0 #P?Q1W _«(_Q-P5]k`%cK /L +? ]J0˲,J6_dZkXu1lRjkbՔ,|=L9?Qo%]rіl@\o Zl\280 +|)9$Kr3cO(d[jCn?9OѥuY2CGQ9n - +bp4_m(trཥEl&{Tҿ$=3N64wA4ƦI1lc(vC] +|Y,y)ڦ)+_ NwlZ +vX d G#W@t3e{ƈ$Q'__!DBOMru,т'}$ut#c̓$M9%Fxã_$F?{žqFWbFlس^U+Er;E|x SN,6'-(Zj ,ĶZg isI2MG27/M4<դ|vP3r0sWuiFVR JQP sBo'"QѧcixE$dlZݜ6!5<{$k14 St&-YO$CuAMr +7=!y!o1 C)V1ʊ[}JDvqLPXhdK]0-1)O#t[-jU4tXRà}[=,drYt6.eM- ђNaGcK{F:Tb5xC"~{/U!뀍]q_] 30aہu%:5Хqx]H٤:Bk:o]fb%0Oq۳~ݫzHcwg򕓝[fU{m%͗A~B;VّWZr+E(4a%1 +B݂3cec WdJ33V{SaNl>=XF-CN1q[rfD"Xy/hkZāx'a= u Sn3V Nv:IXH~^W i{5G1؉gbV8# OT6ލ #qU_ $%Dgq˚zC +=NOjgh)+|J6]11tRf$vL-\5 An^Cl/ӑ;#ɋ v`$Z@|x(6ꁶYtGH +PUr:M1*|ķP jŖ#irucRX"wE2{GLͥQ-`KvP%KqHJJG+n*UqvMeQDd\LH-$2} 4(r TH+E*˗D|(WIxH|P)x~.&Gٖh`SUOmW) e&0z5?P)m]*1+rX-~<"F<,G8a "W1tR6g{Pus(o$_VS&XXh=R*F42`4,: TPãRm)N 5ǘi:{l_p;?9κa",3_GIƻ"ü5"V`Ęzu`CGZ7;IġpҼs<9iar/X wЗ(wĭLzvTAd:.T+8cǶs'0YSVӕ%3>T !]yߡ1i =Coh<:S69s]`͋U"D]S20TN;ڏB_Uy`@^,BPs-0]֝[qw졿}E +kg&:Ȓ]*zV""s 2ec\;?/F덼$.%7ӭ^)G*U+DK%1Bo1+(o֊f#tgV}![}%VL 'sǨrxӹ_U+OB ėm5+I;F(_w&U g1 +th !.'qk le& {FCZ$mm,rb6##'2:C8uZfԽD{Blt{i!10 /D?!=rAg& G8"x] toZ&V7>U j D7N{Iӹ#,|3pĤ Q&rڳl2G+`W,L=!iwѾTzV*c2!f>攡=v8SBO#5W/ fIH;C:%fMc6Å +yPzzQ%-&pa7U=V?`#9)HfbDT~)OEugljbcC,'6Jӟ l)eG!G-#6SrqA4 +̿66 pR0 c\U!!ج=JILF QvO!0{suw&LQEl%}$jL1pQQOՊF&wK.tq&)Ja)$Kz jKJY_2aSƻ,-5[$)4W(T7H[%$%,#?HOMEfxpK?M rLBd~I'{Mqd ]6`KlptcgĜ/1Kx,_,q$#/0T'քJ#b9eϘ&zFLV mNngV*ݦs}{ojW 3e&t$m r0.Gdb99az26ud>P)D#xɚmsMz / +}Һl%*HPL[+2c֖<֠G<Ҧ㨔=t'Ck"2|Y.E=$U.۝E+aLjP,tP;Tpec9ΗMYx +á5r@e͵t9<6M?mlb7;?QLDyA+n۳[k:eMŶl9K<%;2͊ *SP,uTO@PGK'AL S6zm{id(/P~(Rźq^\EEQ&;T&GCӜh}'mt'sɳ5+M0v,eF/[F[r|<~,r8NSQ,X]qa΋X: [K&*.JŠ }~AE/nTy.OQ;x\N@ӁS6F|Į,h&—E6b%GE L z|ߏNbr7,Crʩ+2 +jِzv.gh4Da"Nc^LqB˓dkAl/?Khf2!L|Tܗ \}0J/n=g5'wh}hfy_i/=6%{Zd?NN)0Et|?/dsTN~Qm}QϦSlh|Jr2g Y\N>18A,gzѳ k0m23?~6aRc;:D x'sǬwЊY?ΎC +g t¥|uwLW)NyK> SW\N07<г5Yn`0^hHdxG +VIjrԛ%YO\s]#z5{N Hs4wQ́'APQQJѴ!|Ң(2@ Ƀ~J+=XqaȩAЫk0ZiA9 3rlC M{& &FvXLD73-Q@ +1` hDriZv.J+MKfq7~|%FFyR=G;bP%`.aj%l@I@^+7\j[[Fg4#p8IGizg=AXiR3~^"=kJk:بE(D|ޔ 1E?`b6޿4OMb\4+J,+KVpx=:tPZL?(AdjC%ȇm=ϰ3c- Gm7_̐+z -"L Iw0Mo;#ũ!&|?*1~ ifkzT0CiVdĔ(PQ,/@yO"brYv SM W%K~7g)xҳퟔ"ʟ(mKWU[9Bz ^EBTl)*IHrjd_ o^ KnK/,swM[{s~bw[4H"OCPX% +rl\V\G:ӃĞb9}Hb*3zYȗMPaNos$6^ E sɕU1D* ւC])5AY69Z#ehF8~EoO_cf2̰a Sh7v,f9'L Ɠ@_)1mStI<\d2qPB HW+n & C|K`j%z*j3DBYceOT%[HpC[=L9Z@l.x#^ pނT[zCQ"[A=yLJ ӗF|"nXwEUMٷdK47*@cp`"R56|5D'dL <\2j8\h\8 CE?k Ʊ* 3gܴq-~"|I?ȉNPbPq$byk@=z5 ױT_#݉neΩ1#"FB4)ct?85^"<.Uݠz91;$D$ciLD#x %Ⴜq mC|ǣ<Ԑϼ5S4>Bѵ[^b9'6bƦݔȴo jn.E`U/&,*0@;vRZdz`r[f@5#X;},?׍D*Sxy@gɬ˄TD[\GDgdNcclY։نp]u + _"Cn5~-z Nt%k ʿ:O*59I@Zps1U2hR5\g# +6-1Bz`q8IKd?i>$'+ubí!;(ΞP|)3| H|FAo!IˈCɞUXU@ {d}*w^/%G" +J?i^qFRb|wUpz_cGIRԝTv 篗P"w5Mx1vKF,V+z:N\p'*H-%"E,c9Z:MM)dMvW[ y" \MHRQߞ B2cH##=SI +E,F)bCu] Cڲ|Mcit OJq!2dNkfχ&~:`fŜ9i+RqBkEfc !|$| 0sCկ'DNzT}&G[vvV~7{Eg~[@Wj4엩I̢pBK;ܑ(`} i<]+H-ҘO=O>h~$/ onLl2=E"A뢛Qom܄GxlQՍK98;!VJV  gǐ֩/ЧE+JizfPbh|]ItvR M!5wc [BLfx4I+jVF9,rTNxމX=_Msԛг,xs&3~2@kQG;@zA8HGnxٷO3RId'?J?@kQyQ^;Ӎ-TɒƮIĭnoAHt?lqRjÝ ,]3t,Á i\j[QKI'/t5!8 *N] }JS+۔E;X|$y6Ati?T]:xVR$ ; 5T qɂ+ɂrR #}5'Ӹ`4տ(>(q 93iO>gnթ( p> pE}OoBb !6aBbV +/VRfNOgnDvлĎlv>Ascnҽt*jgE3M!$a6n)=삼&c 9%g(`(7liL_6+-;Grx2gs1WϔxDS`/bǗ6M%9CP?sI ^r&:jbZ*te7cLGv0\ \OwZYWs +Cj(®yR*$I(LKR\ }V=[ x#t.7<L͐@֜JK7Kk:$mY?O(䑋hHu83Ħ~i-L;Ĝ5ֲW9WoO?;_lS8 L-jp5*r`>CsقnX,ź`talxZMX HԳ-/02HTm2jW?h TE~VZfV #=M/&L%&#m.v;Er"G /$@tWOǴ:Aˀn=gOuԇ(`zLμNX+Kx=MEի۞Y#'(Zޥlrlp3 oJ +[y~HQ${Gz~%vK=,ygJKpv}!DY"9@ +I[oSR|K7nx]([ފSqn@e{x&~ t EV$*7K8hg%-TpU1ȫ'"}&(BA㚇6/pV*^0~+!X{y'Or +@qB+z4<*4eno} xl y7*ɰTؾ f?lt +J[g`$Opz e3d-u6ILŰ4Jݤak*5Ѡt"kB)7#&؄[KS$A,7KLnR +6oe5 nh>= L枬wRV%G}ҫ(@A]qrGS^iw- S *˩A/x\ ,;}8@?da*-MgJ~EF=+ZP65$+JwKraGmI~&0)+R 4 +QО4i`˃0$|UO?1.Un'rT)j.8m٦ Ï2 cdr] S#FIZ6rV0 `<9Dq$ QXeMmݥu):ʍG-cE]yUކ ̦Jl@2=籺Ǒ +e4׳ A;9B k9[lJ^\B=s@iLeIE*IӣLR >zMhp$a8Hipwwn4юCHXTzBBReJWZXTҧ'O^F/^ @Vt8<_2[k sP'1\.Z8%xRrDa,^SgU).y:tK^BAh:>Hb2Td0_)f\lʦ.U4뭀b| !1Gci/H5ҊHF-ɎY3fal׾apMP+ܮSӶ+i_EQhEev_}8VJCOB Ni<8GfնvVPUxOIRrҥ΁zKoAG29r%CWإGUQ|@֞ǍME>EH~S^!ڰ_[ ERZ +=R*110$h|Di= 2ΕrTe֙E$-Viؔpwj +{!*9eܴ^"|9e?0yQ +?:]E|ں[>)} +0C>uɶbeaCuP(ѕ.?)9v6 tA%Kc ~Q.-sG|0iMuc{:X +:(C/  iSIiIh=S&|%C\iC[ݒIBA{ 1M;*጖`WԒ6ƉWuP\ +8Epl,^\QBl\hyX-h l)^?9%lca$w*!0ɛ!C45m{/QLyUC3?B(M3BFhs\̪9`q7R=x5nivO4INf\6@mF5BQ]VLCFsn8HCCͭl;+ d<&AozG=JJPtd IBc $ %ej-"dzBM"wz4OnU`#iWHAgV\Ӎ&iLHQ$5!WL}I6j`gT$"Oz9=7?yFؑfdDD #*I#>>4σ%D P` ͏`5u^X):[NWteU wW q#]kd Mk&.}USmظRuʌ v"zF~#u,Z瑳\>QU- +Tf!sq5 hW`k Ƥ.הުE41m*Oayf" l7A hKEPE#Zf#\5=j#ݬuwbG=H,h)a9 k:&IXE3lΌ_&aUF11/0hyl3F,djbߕ :|'lߊ;I) +2r6jj2B)7'P.YN=f؛2tuv)gi-+d8:c~%w?Mϴn +'!@M`,IP.XAvc†kʚiݭl(VCH(UWm\5<0fTRMɱKR^Qu̙S˜CƉQfM $ 5dktzܪU#$f/_K<`jA* +}Aו2/EMJzͬXJD~#7BN`@fj0EɓA_'v`YU-KY8Hz传ukEzl|bϬ+:qJĢM35XeVo'/;:;<ʉsࠏrv87v0:YK5HH-8h#?63E j1כdAC&y fb w!hQ}n&>H"Ђ&Z2 Vbۙ&ΣDahfgf3{VLv +2 nZ"cx|4 /kf^:CRg_בlR'7gQ-%Rz(z:!ss4銢\`#񀽙?41oeȟc + bXP\c( WӱɠxȘKtdcJ?iv_Qjgj6QÛpUCsl97:0pS]p IzD-@VW~#$cu)mcJU䱭]cK#*UЄoa[ã %!QDo%ضz Rem納BqeJ. +lr0Eb3(c;7} ▵Y¥̚ãicjD) rːOÙVK,P0ng@dQZ9 +Av$/ +Oӹ7).A*1>Db^ K6^Rf*FG}ku&$^‚ XErHPp$ tTG_ Џ".Bd4`7#4KוF*ү=A^; c se'ϓU4b:pCw;YMnc5F#KUa<差5Y`t\`vWU'ȫT*g.Ȋə >wMUHVvcL0#oi,`YE 8cP!56q>fAQȒ3 _J: +Oٝ:x>V*di,B KWc} !{< TqIPr+UL5ޣYkIW|Cqj邆bJ? etqJָ%\&* 3b^p-R7sO7L#!3)^0ʳWo6.H'0ъ X(N +#IR$`RovW$Ҍ 0guT>䭅v6e*P`yxW `hUV ~5 z +r;լ8F^y2=Nm$Y-wmz[ Z=fa82EЙ{cQ רŏ\Ξ3!k HC"!~<|38#_\~ZHBKr?f(FKzʲ[zWP$ 0eC*\%\&Z{/κ?(Ѩ_ N8˒B8ᾌіw Zi@;nch3U-f(kD*'܀0%A:% IܘVVeC[F}56 &a3@8䖹ʫr#ppK(LÛ4AX1joP|uF~EBCfYEan#&o :AmS4@GGS;]yW1ĝEKUVͽx1:bjⅱ{C*3~ˠ 'h[%tm=$M1ɾ(~ܞy7EK'v.s^EÅVgǒ3OłmoA-GTg7 5l5U#Z=D0yN(ksޡ \#.仺ɧ-M0ߺD<[Ґ+ +3$.BYN # Ί!Yhya #&eC[ +,ewՀ4g 1bIג~&>7ZiƘ7ROC`H?g{"LP]g*$%qr7+ΙM;!8I r'^Em҅+-γ?DIs5W@DK|C/TL%̻b)hUƺb$Q&G@oLFȏ?zF#UPTK}VLQ=W3h!^#}\9RTYl*LER]sY#q +$C.SX+!řIͲ́g7AU2P1G3(zG][3>Qҕ4\aM|[?p\d4s?FŪ`W/͈\(ƀQtt:ћM@qcOQհ=ekB?^t}B\"˩j8[M7T ץKH=,ݙ XH6 hɼnxtW}I\s qfڮ=&ÊAOquo֩ħ7ܱGo~ Rc,VCBZw2"n|Fn/ZWXC^ 'Ưtko9m,{+goЪxFuG4/۳-0um˽~[doCH1\kx:h S4!\F"',Ϫ*N/8L#Yr _kVDs]͍t#(%(˥h]הJֶAjefï\X MdzDWqDzlѷ@5U;H0$.ec'h}A7l4-)T8%>xl8+Atź7ʱcD^[#Ax֋HӔ +>DUX#$!԰H(9Z/ph/B/I=2H wB\7k%_؁z-|R,i`7=MScdf7?E SS۰nO _Qp4[0@nS{H]`J7n=NJ")m>'oԓv0Xn[GT`@$*wtNKR%~LNJkLo`p7[(NY\aWTC6wnlⅥF;d9.}tck8KtLMv4K@Fb[B4 gFaq #G"zx>kq=\0L,醏4Tf%lj!hjzy&%a@iqlQ"]1SϤ& + oDԉӬv RfU!Ft';, bqDy2"}úV>쉷8۱-ݤ& , 0J_#H$l/:6LJ{JDʖzP'ji,Fi-52vNLJ)nb}?ʶV"+()ΰ&|DdsL? +9XBsX"Bf!,D--zʠcE0">F!` rYLJJ$ipWEO= ]s+CLwV7W$\'L4$h;86&kFof\6e=9B.Ydwy@,MYY=5UKI[`ǚi#K [&z7D~spZ +O.= pwF[#W)٧zAT)(Uh0GbX^{@350Q8+#.d8poDI 6 CeMHRׯduAӐ#[yA?MN ZE}J{o_tappƓf-]* h *Z〯6JhMtaS jϳB|X{,N\v +'acR^קB/O"$l4'#aq*;tv u]x}bH(%hTQjsA'_Z,> H}5Kh@aX2ze͊5iGMLVnC~BWRzkyջwtuq V([fuxڣq(jxWݪShx j멜ʜTzQ GY9׼L6>{6@SYᵱ9 +> ҿ?WR#h~}O2TԃQ#@{D)JF%dҽNS>sȸ},*N51p=nu[?SٕBZO2ea!z%[ 7`]i j("蒱ڒTC=!># )M uY^~`^zjM bt8 8j/MM]l{Y~qҡ~ YrNWey:\"q׉NWm\Nb@+mFOtmIe:@vܫ1Ǧ9LPzzH]aRtA.4qa [~_P2jgr7|CciZieib ЗK"<8&m nǃ8t:~tQ+ aв{N݈d͂r9-\\sm"p+,򮂜CGPyʊ1 yGd YBL WCLk+;QmY2ߤp=7ӤtW,՚OG;r%VmRA !x5 /G& +]häᬉ;ծ0bK)EFnl^ppzeN)b#4o8ӛEdO!\P^p;[1pxq9p{o,3zt=Z1Pj1Έё>MfE]U}ՠԖTU K'yC"m>7:M ]5Q40"Z7|$JӾ=gB/L/Ռ ~n͵c%=M<1D}}iYPP?`MjΡ$K bdvͿIw"w sCikVre,#7p!>^ [=KXٳG"kvGKja,E}&RMC|cF$'MJ~,,(mERjyYaȒ|5OGۍ-+CkĂ/[AVlI%a|'hhN ϋ믛?ol4tںdf\FlXPVAv˧?iRgbI=+{ll%T Mػ帙 JW#vׂp~$=.p)<'Y+]y:bk6'?#zoY~k27Qjh~{oD +JqL,C#l\{d f)x&h%GM ρSA?s L'q}_R鑚P ,m:?]9+pPD>ͯW#8}Z p:Ff۽!WfFB'2cKkpzFt?LOz=fpf7=J-|U! UR鿺5/ +H5TpAQWDq8榼95hNhCuQɔ0Мp`P|"Lp$ \|^Tx7Ib ,\>&כ}.T%@`U/BpUEUX[(ġZ=I 'J6 ,hpXئrtPVBz,"WTIx)1+뾬 s}c:mb9!EE E2.1DR(#\rKx D:FxyQ!RhӿX>Pujyjõ%A uAiuLة`UCL9D +~y]s((1вbԳQf1UBN'6-C)I/ ֬x9WXK"%LjҎON1D!ϓ n*JBa2}q-mђBw; ')+,t!& M_S1)Fq,s TeQjɢdmL&Qa,wΑx/!WYyp؁Rj $>kRiaCKncr +i.*h)zB9 G\e{;`a/3%#d{0רf\IDdHFEb 9 +,x40rc<,E}w,$St@ΊH@BZ{FfNRbG:aqyTJ)B2#1 sDZ6b"D$PwbyoY(bE* qu'V#p.|pdd$00E&ՆG%9?r7ۡJOgKyD+2֩3)Ո׋#b :u4N"O/7!Ϩ3/>bHx6!y`A:+ŏC [h#LPBMЎzzSr6Lx{?&p!a `U,EoYjbN=.-c"ƢSM2ʌTH1ԯPs2*#n( M20.u9yUd3Rzti%jzvDhd0Y4#aD&RSOA *MQ$EPi:"zB/fؑJTR gqEMJ+jy0&s2ubWhƥt,Шd"ܳʹZ&ơ))y{fxVLp%FJrU횐 jE-dT(EHbh`E^bȮjUEGkrAh SH,; :Y]CTdPTaIWe +EI1&5Jd&Z w4EA.{$ RFBq 74A&RHQ`iMbfTԩhA!C0UBP +Q`: +^A@>@ 0 +(0 PPTЁpX0Al"! +40u#&> 8~.Rnnwq#2ϮIOf.AOEtwTl((fQQ]{&`2XI$r9f Wb!gU 0;"*N<Gq4I=0԰LؾRu֞4*p1q)>b)AUOshJȻF^pdruaL}f\UǷO*2 S!,at)%L'uS_iE#C +0"/KeQѰG̙#tVb̭6Nmf/%dj-J{_I3 +` M-a!C1 r:)\H YNdzECrAwy"coq$| **7z_bhJJWM]d".1;TUjz7(K(6 +5a-,BɆ+|gjTtȸwHC+-,B3Cϫ!1_ +{jo/Sz/G1e +³ jbFޚ8Х։rtw B&%S5(mŷP5' )mdļ)%=A*W({f&{B&f*DRL(1EzT4NJNzH>\>4h=y]0Au!PC{ΐ;#qF$5:½#H^N!ub{كח5sl"e)KYv) zzPGJ ijYA +  +,0 +<|X@(@ l` (>`@@&` +J0lhX  h@^! ٦èo b_XFDM +?̆f}#ђXTp*SD[ѱ^ji9F"/:0Sd*lwi:5QRҷZ5>d>ԇT%-CߨRb ]c| +_RKm|A.TT?"fz(ސ9WH]v*\(,R!R'b,$R5oA! JCg P›TcL-c*h2Rcu45zT,u7Gk A(~͇((pFժ<&1hЌk[V(h Ed!c18t/#(& Ȣ*775`J#+?HZSB% G Mmпp(%#Ŋ4H"DplR*WD? GhlUj6_`/,ZyȴC3qQSLɰ)#F"XDKWUwԇ5L,l.ŷ3lW@9q>' +QJ) b\9"c&dhY%**9U$h/0&PxDg QL} W??s)(#DB1T$?\, e_lV %c2,[*\"[wR1m\T!)z˰n9C]# -N%s*I*+AřyE꼩l%5J\ *{Z37aȯ>y aZ>Ҫkjz4^JCۥidcеqɛh3`Ngt,ihxHYu& K*Q'9摷&,-uF +k_|NBȅ^ApzQR1e3ONSV-6d*;~2x~1!< +:!26ES-2d +BD 7 6(h@*3.# 2!b12-CPBCQdPA]]AR ePEI2v $փ +|% ejb0M7t0ޭ8O}-w僅n +0emq@5cdQ6# Eg zCO܌(7;ÉACp'; ^Z;'.*bnf 6QY|KOr<q^<fFB^ae Дd 輪fV9VO WF˺/zƽ?L-r!?5/!F+jDJ@̮Փ|Q@:NjXd%D g1y\]̉оg-VK +Jzza$gsQxu% 1(poU4"sRi>ʳ5m>cAS۬h@N.^2@6:i=_分s&&i2qj +k]FDz~u+w"z*&$A1C|VGA b^ + +ǂC}t3F.gB[tf/V7nEi,)ߑ[$4XZ]<8<ϤN@@Z??* :xYv,6 Xs˓DXj`T/e^ķe֒BFs̍[tA2 _r+7A'3rH +]!: n PuW9`8L:-d$iil1z2* z5_\Me 6[kUqt"u1u?4 :';Z!1G<"D25E*rr~S^w%' +'ŴJr]G7+_zњBD.+h{pOfFs/ƝyED AǃǓ- D#yD5 G!26w/ 1}2G:dcIxÒV1 4#_#VQ_.q(^}QO@„mAjz'\]Dp^'._d]MVLתcԻخzMm"`@'6A'_}y +A>sЧ`5ԁP!*~.Cѽ0;bF? [G֦mb +TD-&fxuys. 3,pF?Y1ZiBcV/lsٰF 2ޤ9&/ +'^3y } gNjv J$z:Y[G;r.1x-wEL2Kied ob ZrWj/yv>$qmHkXg^D]~\c=HޅʹHI ZbgB#qI"Mzl޵a A + i#8;%B~2躻 ()sZ+E59"b9Zx9T$UOx0)jT*"6[=fznFZ/ڙ*Dq$)NB/Pvok^C&%o'gYW>]dn#XQKL芧=iˎU'oͺI N]U2;*MO rɕm kIhh9$?OR離UFׄYUtR;LmIV[P BE9BYB=HaŻG=^obGk>a8^I?,+IZb)Rqcu~+婜vx_la] @B {lW[~\`:-Tz.{!'9b+;Νn ~0lLj'øvmB.nLT6iye^!Δ6iDBSk@)k*AфQrz$]=s/` FV][i383 C@Jwee3ŏ.s//sNN/ƥʎ#P $k3oaN[I]d `;o!/(zU:{1?l֛!|drN{36c@-r =#& w RW-$ DŽ3`Ý\c@~иCzF]-EXsJ1, qETVWTXL>NUJGNRK(4з)1#(mAJVZvZ(!$PZ*E8]p:lۦ96%gaT!`k Yޝچ˥L$I (:gyαTf?!#G +' +Bk e& O/WN7On{<.V}-d0NDmj!Yۤ!mrVP@3(s?+I2j^ Ow{DrÃ*u_,aa蟉K xVeuYڥ zsKȜjze> I=ö( J$\QVt[J٘bO5MA9ۻ j-o$$G )EYX ۞mIe''0x}(O&//LE6Ims[N6ES#wlI^R)\m'rMӛ/{$'6$3D#fl0fk}PqƄc`ߘ5T3'_Y;"45ݑwvWNON"^&X }h&d #F2-QK;P;Aь(^JZe.QU֡ب aF+8% L#w]NG#dZ rZG {xķ k5@=pM{r3lWBCsvk|4nqD YMN>RO%c"Յd\ tצqڎw.faH*?)R衴["WcPgj'I{q_ g)nɜ}xIX;r +47$Fc!XPid/&&s& +}ܬk437-$~>oC`xa;>}Tfh Gw;TE^<%m-oR8оk`_Ԍ)uyXPבAЉFt~I;'6->X^A*}Rr(Ǝ*^Rzn'w]/Iք =VX1$OU +U{aE4){΍뒫Ӽv: LԦB26H۸|Z@"Y%s&<ߘ5Z<46j-t!Z}N^ 8^khS.L[,9a[,p;xMU{IW`aZ=!ƒ;V>FڂjQC +F jN^EXoOkz=cWO3Jŷc% ihYcL$H]fwITmYuR7[.3f:h s%plusZ4Vjv3 ]&v!XLcmCe{,L:5Q@f,PT'$[`0B ``z)Tz+lҕ#Y(΢UʼnZE}KI2a Uj"(ޤI\c"fLgͷu=)A[rr ! g@ ap@tuOM{mӼS(?3NkdEȫhSS6Lw䯳Rm';ɘGPqmBPE3PpV#JD fg+T8t +n\PbFWJ1i!1U5ҿ3_eoJO:bQucsMwOs(8g[A ?n h b*8_M!BzV e!)= ) q"i_\Mb tW78@C?u܁0b.@;{+y&ogQҭr|OS)>}h؄<.8-Ray=5sGA_BXwPzڬM~ntE&wW>?;@&7g ȩm}lJ3m mVۚV22 ,G7:/RzB(P_\-B^j# †ʼnN{'`[i}̀ӅwFjgu+ n9Cª1tcBb b׍1wlߡcAuuR}pʘxv#jPn.6:+tLwNĤqH;)%D#b|z 'iۚ]E6>/MUw"a9ɛ$;hMM;/1&pTd3BLG}L:H1IywMQyP"h5 +"TͅvPҽq煹u8O5*@w6 rA픐qQ0_:Y]bغ(2ͤ[)} 'ŴQ{vvJ(9CR 6|kv P]c>p=!-rE?"x :H)?b \3ϕd,* 8Xdyˀ2eulTjY&p?.m8ŝiB)UxRlѷ,?tPҬN>'W8'Ht[ݚh7k^R:kCl4z-lna `LG+m~ [o]W|eLyj +i+îkJmR{,lӻcvvהi^0M^F1_|75]4%&,SΞ|){ה>2WpxC7nwcH&*f)7g +)qָLH6+-7jts(ß LjKB6[zvTkZydr%ynbŒ=RiF  Y6}äksg򷍘`骶mDrO^ۈ?Ԓm/-jEGh1˕<[OaM!-;>/}GiU0 Ȧ1>TG [2< hM/}b)KKzPiò7ŸdĖn ?ZUB$b +\il2iI0ZbJCLv SАUEk!yh8{ iy#fшP@)|9?fsOM4;U*eY#9_F!ApѺ&2:Uy۸9.iu:5w$.CQ3pAy$gdpfROV‘u@-F ti,CE3Xf -ƉÑ0=8.Τr&q1abB?\\vMfY *] |'hv;7Q8 Pl1_Zi3RnBvMmDၴ\=#JK ƤEAㇱ\#*,PV n`D@p{r͹:^>NTgؑ XRbe%ŨZ]6cim-m 7 D0Mp"yFLj -*R_}:>$VYluѥU|lezK[K"e{i6mR-?b9=YVrY) +E~V_L=nHX$6)9~_G޸;G3I ߅#%պ WI0[[i&VfNMVH% dQ8'h&=m $sj+Фgf+i +EulkK Y 2PO9jh?`2Yd$SpSĜE#~ݵhgFksG$)_ +MȆCho!0%@B{JPzs-dİ(`hX1Q9u7nl*qx[!GMx˲'qDGQZr:ˍL 􃷜"w>wxJ9<%E"dUv \@ rxKQsLr +>l\6՗3YCE^Ԭ9了/'vjr'6U'kuKz⮁Fz!<Я(ц5/=>{7'Ujdup26ڜs_nWݟUDtQYo!6ZY#^vc:f|7R?XNbL>πLPf(A LBQ͢=LosqWkws1Fba'fp,!3PdtOU=9s=ܞJsHbf Tp(zrrp?R :<[9oҽwp;7,VAdd}~8y+;`zfV^PoEХHEPexY-V3[膕ِ*}"BC4@ %h0@w-ֈA;*L5xPжZXqL'>zϦ; {Xr\ M|,'TUs=)71NY:0 gdsHߨkpIW,k  Tmey!hsW4===7 C"Po H6W!A-=b}Mkҟ̭ٞn[m O`%yWha>jHo!7ϞuuD! >0JUM< CfFH7Ĝ^p |.CN10J!kP.Kz1p.p-~oABU}zy ,Vܗ."d&9h|i\RVU?Tbgn7akXTHi|\'_2ݲSk,{@*7{CwE +3q3ӛъbw]A.+wH61 YY`qI/`AoI9pt s0\Şń/6UY2vcY}4tLJs4G'{J'5]Pb\|'z*].J0Go74Ta_*EuDHΠ W)bIJlsj`:*Z^EiYxmw'c||)weU1`1*EV+؄(NIyKgI:%EW +Z6E d pOH0;r h KBp)!{YlsLԴ2$l 9a';b &9X'PgZ\, +}ka~9z SN &mEXkKY g̘'E(~: I@A+BlFDdqs#cN)ϑFZ<1~"_F\ʕWO=ͰOX/',8JnȦ&|1L_h ]"Y K # Kvr@qg1&~?7ww77\𕉝sIu4PortmJ ="CmץbX)Rvyuul4JӐ$dEh)+N`<>BtJ4RV>c{ljhQJfk|7))l V@?}<ԟPK[_e]<U&ɌQϗ:JzзjmPOyNdh#bO)-PjB`z|`? UI AEs1y"\hF,"g:~;vZ'īDObWu%`" ʣL2ަrn2ykNҪUNiLÎ,\g/,2S?wQ{= x//C=ؔ}GBk +9⯩VL9`ޮnFT-o*>?NYc[cU2*|*PU `U-8M i,؁)_k)f"r'"vy"~lrBCѦJܕݔ2Jf5ݜ\Ц̑Ҵ't-u̬Bu>ywP*]GCH\Ux :S?{ pJ*,d-..քۍ=&wm2&@JdxtQ?d +ʖǶȻmxvGyۍ|gqx#m<0HPq"nO;-?s &x ][D` Q$u;8iK(IBG2hG h?'AݱdXd)g.vY"8k)G~ݓ#oIhѶ|}Вpd"y:VIOx##'PT0.@tІ+l'ŷ%cWQ W@Eآr!h$<%}mѨ¹/P.2)&Ȟ*Q\H}+̋ҔYEuςfvEq,r "3 +~N4Z.8c؝- P+(I\X +Leℛjo^2YO]&ƑET)vtTXVgRQe!cg:PӉm2\N*Ɠp2R O\\W -GҜ+izrMʜ13RUfQ"45zJ?m#R,oqrz:ۄU~̑vK`рi׾T,"D>ؙ7Ovg>khj(oLV' +]Rp2kP_Z{YIGlݵi.k~<'D=(VJ99diA1oa݇3cHP~hchh{ =K!A3g > H8\p85|Y%l*b.G,#kcط7p2O.Ԁ- w۾x@> VIj B9" Oo OMЂ;zJ܈:%P39Vx3hUejo{F+ J=%z+CLÕF4}²Og'r9HL(qS̹)qLw1?LbH2JF= YS?R;C~A~ۗ܎+,Vߥt4fKJ0%*3P5Ir7 djʈ Wwg~7:$1m+ 3 +Qk$+~gNZHu& +cg-(4:@X-@iip`elq>fϐA'(>ʡb}Q>ºB~|V*е&ڿm^ { ?9Td|[ =6o rrgtjm1c[M,[x;QΘRkbu7ۿ:`$ҙW %Q01x%oK[:MFfxDjb +-έ-ӈa)C}B4m$0&Qh"UC͏ȹKȏ;I_9SC)u8SlB + n4X='+\ZϚl}?LDWc7fWȑ_yу\#2K I +W׈pXHQbx$QϤqȚ`QQC?7."&~(K~ +aDR"ˤ+\{mA9o\p-^E 0=cdpm[֨bu #`Tb$ pzㄒDow=?r]a_MgP)鑶l[S lIJzRd9c(9;WGRoYYyц!$MџTk|8Z.KQYdw$ncmQձϧLiΙ/|yޞz xC4 d[,4wrE֎~ؚ|\A-3>AuW%nKjPE9%XKvsMTNŗ! c4:M,J5I HDLhM@rJXam*_ug(V!j\♍ϗq@yf\DR)g4VMͬ?g*1}/lb@&@XD &=K@gɒyK#/}DSUS'"e&ɼOq_uN泠c5'ȯ\d 4)W'arP%3OnUei4(!73L K(<Ov-ti,l= +_wY#ţ}e%|":ÛpMfҬJ&WjdMB ;l8[) T'L[Ůqʬiݽ7{T4מE(LYBcFL ;܇1Lw/]>  >fOQ (NR$&g +hJܐ^Xwd{"#A{9 8,xf],ioF>FnF# RA2X^ukoʟz/lr" gqM;H& +ޔi?"s萧- ;PJ^*|sX1|Ê~] Š %]Yw. J>/>sP[ IYdx^((L@$vKk $lL7%Ylp ̦m 1=-íX'S a|gF,+ d5R/m \a|D4f:~.M,3wmR4 HIϒ@߄A/fԺ4#`\hE5JsLKm+#4TCʈS~2(3FEc z)be8[һT + H&y~O9 ,N/_4Bk +\G L{qZU"odȍ?s?1SEI@`%J"8H-${k1uƟO]Z@5o(gG7 +V \|3D Q M^+|=ȳs@p[[3 ާ*آ"}Z@9dI9QowWUX!-в.!%&6D<Vhc=tJ!,m%~r M ƲTPJ-[IURABcY kf'I*ei?ntc +{몮a6CxEopEjyD~';P,7"^[Aſ ^L~P7$n߫ + f'n0X9p1X&JUgh:Q" =;=-' }5gbl< E-qo&G0l\48MeJ0ǀOΔ'KMԻ3]T%Ǧmv>uHqi&a?#-;mc! ks? Vo0!3aQZ1:7fg:F\&:П2"Z6tIB-jʸ@*+3wgi1X/Pg3+­b3FqCC3|g=M|E? +pa4,qu; +sAI= uiLG^Ao uQkd^+y0)%OgӈTElYhxygq~=̬)]?A*H, 8E?U{'f}974.H6=77lJ%@'l];{ܴw<Y 0X%c}2cΦ +/Q VM`L8iWdE.D39!<S]N▅>?wJtMlJrx4?hu%wҮRlv٠N +ɑ{J:!իm}+4nNp77T١s|3+!mr~(_sY$5)"Fl1Q!![2^kc ICHk= GRx ,%D{Cj>э=}}4ii K:)̶I)e  L VWXHGZUD֕DU-% a:;Ө00m;X,J 9/VB]Yi@Qƃ3gxlJӡуa\iiXQ^jO]q49RG$K1\d2JX'+n+Vnyzlwwj=r]I:J$kJKS W>p7HyX>E΁+~xڸJ͗'@`"M 45`'TxGӷZYc! _0XBF#n2Y I;Fڇڪ=1Y8AhK5׭g1C~;'T +&$ >QtTQVց>kFE] ;Q ӐQ^$2JjŏpQ?R{04)F? hV栁5dB@R "pER,z\k 59643-UnGRj#>na&jAքek}MhiCt zCP#rApUފMk<*RB :/T t@EeXs[k;y;;QX%T:YvAh$֡ncخssIR85Z)V$ 1|QdH)߫Z#6$WRU v3s>*6X8NM%{^l2ݭ^I`X1ļV8ycY/PGn1Q/?߻7HŘ*% +)3AiZMڣ$tlsԊ#|_W>xx)HMi~0:Bb3ӫAao`dydQE<H#uqEGWB!ڒUȽjIъ(aJ)k㌹tϤJ;o;/k)&␛93NLRi@a#ةFVGN?ƘB׸ Z(K-|FDV` Om"#m"䤮=.m(G遨̢ A|C Bob +hI+I,Ft`Ͷ,R M|Yl?f1Q&HJĈNYI8rh3@ +擮C ʀR; f@)Y^#[JXSRch-=,v%r,>wApQeFoSfd"kH]m h^f&gzlO*T8Xd]\ʤY{#:wl<_>Ю|-99>y5YRVAPbiU["Ö0;IBmo0 LHƍmvzh&>ǡ&4*7hd/5RK'}z9bG]6H{[ݚĘU_.;_~ȁ#ŤL%K#aWES?8Ĭ|RS,BsykOz SG +vFCUy0-*Ɍ:RF)AM9"4# KOv#÷gyz 1CG\N-dZ32,,zdrڠ]qqp3hbظe yrM_>}tߋi\{4㽂 V C.nZDF J2NLA]PLlM%@Eoy*#'+_1/Y#{rZ/]Hz:W:WБ@w<*H>fDj%.u2 szbT]L^:.[D䈲dž=dsRZU{M`xޜ4 y] 'ׅhF\{ӡF^D)=>/jC[c5`kx1T(8)e[u:RcaђJ~9!$s@ cꔳao%$IS-+m^@/^DXD4/YJ)`!$xԝ{J,hSq8~ er'Ɛ/-a5dҸq+ Ǚz-s)\;Ӻw:~8e_Nzt:HuQa$;H}Ŧ7abv2"@lZ' +)bl_!c!'j{m,vN _1E>5) -!D@ !<U}~S1{6V 1gBTcuEݼsi +۪T/ն"ֈ +&̊,_ +ZabͥXVF5IDI߄Pow뉺+&O}qY'XLHɠGP# .3BJ-4mέئ -Hp67FZ5˳8R:3b#E5a6cGb\1ap;((gc71 ?):845G#(m%OQoa!(gq!,F@; hقpOFRE:{OI8&E#3',s( 0M%t]i?qn;Tg46C,$|^Ӻt.X:D,:#B&J:hX6;P='螴x0Fh\lQ0'X1\)`Ca`<Yc vCH,&%!Kb%%db)!lK7j_v 3[e 60itآ!У Q; X& +ԻNh(Q3t*50*"茔դ ' +Et,=#F-(S헔XȧEp(t"*TNj9e$@?k8хNf,֪KtfcVLWQz_c ĊJI7Ŵ9#ExYK$nٲH,ZK4>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX$6Ra!<<'!!!*'!!rrmPX()~> endstream endobj 41 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0.142 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 42 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.417 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 43 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 93.9468 149.1024 Tm +(fastp)Tj +ET + endstream endobj 44 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 78.3385 143.301 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 78.3385 143.301 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 45 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 90.1192 137.2082 Tm +[(pREST)14.9 (O)]TJ +ET + endstream endobj 46 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 164.2197 154.9572 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 164.2197 154.9572 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 47 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 172.8116 148.8641 Tm +(Change-O)Tj +ET + endstream endobj 48 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 164.2464 142.8427 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 164.2464 142.8427 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 49 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 175.3897 136.7501 Tm +(IgBLAST)Tj +ET + endstream endobj 50 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 164.2464 131.3661 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 164.2464 131.3661 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 51 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 173.4763 125.2731 Tm +(EnchantR)Tj +ET + endstream endobj 52 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.417 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 53 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.417 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 54 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 420.1394 154.8562 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 420.1394 154.8562 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 55 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 429.369 148.763 Tm +(EnchantR)Tj +ET + endstream endobj 56 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 420.1394 143.1153 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 420.1394 143.1153 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 57 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 431.9212 137.0226 Tm +(MultiQC)Tj +ET + endstream endobj 58 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 249.1391 155.018 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 249.1391 155.018 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 59 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 261.5588 148.9254 Tm +(SCOPer)Tj +ET + endstream endobj 60 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 249.1391 142.8731 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 249.1391 142.8731 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 61 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 261.5586 136.7802 Tm +(SHazaM)Tj +ET + endstream endobj 62 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 249.1391 130.776 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 249.1391 130.776 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 63 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 259.0068 124.6828 Tm +(EnchantR)Tj +ET + endstream endobj 64 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.417 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 65 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 335.1909 154.657 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 335.1909 154.657 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 66 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 347.611 148.564 Tm +[(Do)25.1 (wser)]TJ +ET + endstream endobj 67 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 335.1909 143.0541 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 335.1909 143.0541 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 68 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 345.4485 136.993 Tm +(EnchantR)Tj +ET + endstream endobj 69 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 2 w 10 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 70 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 2 w 10 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 71 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 420.1394 131.2018 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 420.1394 131.2018 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 72 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 429.0948 124.9925 Tm +(Alakazam)Tj +ET + endstream endobj 73 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 78.1834 131.2018 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 78.1834 131.2018 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 74 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 81.6714 125.1093 Tm +[(cellranger v)35 (dj)]TJ +ET + endstream endobj 75 0 obj <>/Font<>/ProcSet[/PDF/Text]/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0.142 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q +BT +0.702 0.702 0.702 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 5.1033 0 0 5.1033 6.9268 2.5459 Tm +[(CC-BY)18.1 ( 4.0. Design originally by Zandra Fagern\344s)]TJ +ET + endstream endobj 76 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 2 w 10 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 77 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 78.1834 118.7107 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 78.1834 118.7107 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 78 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3791 -0.0316 0.0316 6.3791 90.6714 112.6181 Tm +(TRUST4)Tj +ET + endstream endobj 79 0 obj <>/ExtGState<>/ProcSet[/PDF/ImageC/ImageI]/XObject<>>>/Subtype/Form>>stream +q +/GS0 gs +80.4262487 0 0 44.7387171 348.6249084 190.8651342 cm +/Im0 Do +Q + endstream endobj 80 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0.142 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 81 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0.142 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 82 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0.142 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 83 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0.142 w 11.339 M 2 j 2 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 84 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 78.3385 155.1956 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 78.3385 155.1956 cm +0 0 m +46.356 0 l +48.733 0 50.659 -1.93 50.659 -4.311 c +50.659 -6.691 48.733 -8.621 46.356 -8.621 c +0 -8.621 l +-2.376 -8.621 -4.302 -6.691 -4.302 -4.311 c +-4.302 -1.93 -2.376 0 0 0 c +h +S +Q + endstream endobj 147 0 obj <> endobj 31 0 obj <> endobj 145 0 obj <> endobj 146 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 147.9771 5.7393 Tm +[<00A40114012C>17 <0114018E>17 <0114015B01070114023F010E00EA01A100EA023F022F0167018B01A101380167015B00EA01500230>]TJ +ET + endstream endobj 148 0 obj <> endobj 22 0 obj <> endobj 149 0 obj [151 0 R] endobj 150 0 obj <>stream +H\ۊ0}\$`/vC>9e]պn +3z,Lönp'$S};ovh;ufjݍ^1.lW{ +llU^̿>8ss^ |jO`YP1`2M w2^β{Zːln ;9Q#HHHJYR,"╤$LN2r&D QJ1/*RDtF.H bʒPGDJC"D-/PQ! +3Ir#ꨊց8"pۜE{a-k݂pN{ ϻ3aε~/ endstream endobj 151 0 obj <> endobj 152 0 obj <> endobj 153 0 obj <> endobj 154 0 obj <>stream +Hj```d@0P!Pch`Bh`l`t endstream endobj 155 0 obj <>stream +HV{lSαc';vl'׏,#Q$^_EQNOyG(;b'Z6mml.wH8fbu[Q.nP6/F{cʢ7k41lae2бR+^FR4dLI.HEZ*cC!kHG;p&I anhާ𴫳̊t̒@nuer2 WpL +& X̰P ˧GYYS*jհRΧ5Ǘu.[圂NDNJ$-fB[Z =ms*]q2ADrP;;g-NB֦{B˶:ig6;L6?1"no:>H# +m +KugtSNIhnga MqoHj2Q?4YYWjAaC۴"2S#=N9lD<= eK)RѪ\і1PEzWZ!u,E *j6nXWgZ.7Ǘy9[4$K Yb+11zUzk&B +T*SY,xiTi̟vz8y#L.[2ԝc&nmڢM&GnCIH,ۮ;Gք|h)iL$:EšYD}6+%N!s0Q%Y3.o2,1 I~h݌OyIµ*{̻Q奬AAeAA$}<W!Y@UPIcI*_ diLmb5!55jwgoɥ@]Z4)_>Ι3g=sYy4dwMSEoWFvav5נ"d7K,ϔ_G3b<`JyB3גyzΕ؍Ȃ\W1Yg RV~-P.NuqlcͺVfpGyl⺷vPhT(9X*I%rv3_+>*m y8u'#؀R7p=6y9̣]^}N VJs"bZ$?N]=ʣ.ϰn(0pkND jP 'U?c쳸E}˵Ь`$zx6w 1˹hU`ε7F%19|9};T"%!l%Zr;]_gMk-r|Yeůo!wY.].LN')4i빧PwF `g?~'^ ~1Pýw<8Ў+G +ټm6Y%ȟv Uv "N:-зZ\wQx Éd-۟Cqز0OxrV^qg+RZlWwnоԟt'ӖQGBwu4G'bpbad7SFq >~8+[njm(80}G=zT=R-1uqFF1Q8[=9HYFu +l9~śA#c5zi /q^m2-,~Dxv(C^Se?4DDƣoFqZ%?=ݖ_g/oPRqLт endstream endobj 143 0 obj <> endobj 144 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 5.7412 0 0 5.7412 433.4414 89.9082 Tm +(bcftools)Tj +ET + endstream endobj 156 0 obj <> endobj 24 0 obj <> endobj 157 0 obj <> endobj 158 0 obj <>stream +H TT}/3DBUJ%mc$6q "⚨AK@ n+((8e,F''Ϲ=ӦNgH" 7#l Cܾ&o}'Bӄǽ47b< ( +I` / +HHNo[1RO1%OI0c{LKB.@m?uj\G| cp\&vZ_@NP9 '`@jo1t [OV+;W/Ni`ہE6Tl{xzyv]d?@ѿn~^'7!o߅~QxE ?OdX䧟 |Q|56:Ŏ01qRR)SM1s9_}=womƂ.+{%,]|U׬6n/ؼe¢;vrv)޻oJ)+?zps/T]tjvM}`k5]4]U`Vsøn:7q5 +9QxEyIԏ*&ՓԧUjff%i4R-})͕J3RdKVEzKɡr%()hfOnZb Y[YYZZ>jylmgSJp\7`Ԗpj ߅3B#92jR8Ej`ԒgԭФk4/%|%Y"EvP+KJtWz)AvgrNjZFͻPphF-UFMjrQJc| +e ZԖp@`K9%ܚnf}9Z֏>dVpmfV`{ 6W7_\l +x? +`Uav3NfG,,9 o d^Qg.}֗鬆̗5,1/5 +LmzX2Pc_cQg3zd0۲ +C) Π5hi8pT.T\/׊kIO)sS\l[bݒc]È b.d2L8̢Px=Nä]ovy&o۪{ _1Ì?&^/1Q#>ӊw uL6C,Ȇ +d1r^bX=}a^+(]p*a7XȁPqp.2PWhp j);H0 ! &CH0 C̀f _\J!< `.Brȣhո:hV$7F܄y耎^܂[qbnwn܃Ÿ~<똅Xat.x] ݡzb9E/Ex +8x +}a/vnxϠvG5j,V[܇(Z9< +/%WPA=^jZkP!fB[i$*v.M{>OO R:LG( +:N'$tR%t"]tR5̷U $`/8TCTGݤ[ttLTO tzH1@OX7ߩ oMEWMt=DOK}D_'vբFDYԊ:\AZIz`yͻ KPsPC䌄*Ds݉ur +dsΰ ,7WW555U]yBRXH~9-g䬜rA.%,WCr#=q{枻hUQlEolM6Ŧbb;Ҏ;֎;N;N ;β;78#v]`kŖإv~ ǃS]n_vʮ]kv`7Jq)!%2+e8 %^$Q""Ad5FԘP jFͩVԚP[jGuNԙPWFݩ^2>72W%ER%MҥT *ܐ)U*Mi4fLEiͥy4BbZHXu[Qw uOWTQcD\T=SUV "`CAAA~P +AaU @QUYe@1(%$PbhS|ވS +TPU"C$B$C +JTrBN--w.m4HJP2 @UȂjPj0>1|#a10q0vNEi}Пta:BGtNi:Cg t.eB:ݠtnK>=M91 P.=łXs,E(<X1`q,#l21sKb),e0rq~rX\ s.Ÿ8\Ks\sWN$NN4Ε2gp&W᪜ո: ȵ6܀r#nM,jh܂[r+nm-܁;r']+wF1ܝ{pO/so}~_~:<<43`&̂0}P'Y}Q_7m}=!dC<š(kkY+Tss<' O<<hAk1 ӰƺXϟn 6;`bo|6Ct">18'$pHsp.rNť~+p5~;܄?o6;pxq704Ʀij榅iiZ֦ikڙh:Φj)dC-o>kM|+JX\Kqi.efk:nn(ţ%IuJVgYu T!:Іr0 1a`X(,Ϋ HNQqI$Wv+d?rD +l $Ee_`}!MxCWS4٦;.;N0Oࡺ,J@-%2"Qw+VbnLcf`y0KLW5SRjdUM(?ɿgE66v. {`/pNi8g p.e;ag]Vu7׽Ӷ{}/V[ Vm'8{NI:YxpK='{TU麒3t,>l/[iZwzfk~.{ 3xyp7MLtm`2&j?W}tTvÒ# -Ϥ͊RBHÒ. _ IIb BCA*j[TPZPi#U=BѶb{Q zD?&Ĥtg{wޙsΝMǓtMiDEFcY)0F.zm$@h!66\AtNni43vsx˼A)~ u_(#z<9v ;L^̲?f#If.5. nTFݬ1z]dila}aqy`کl6w)fMc1J:p&/N4餓Kn̈́Xi"Mg)`2%QC\||dKś2`S2|0v2x0dzd*Y~I'k[bdH6kҀdO~}|1 b|YG{l>F|Vξ֊ӷg*~/nF\(Av)cK3Dde`3t.0yN2[T(!f,tbSx*E[fBܑ{q9HpBˠUxPf<]3*'^[Jx97(uR +0VO>Ҍ%, ;ÊE#6?/zQkkY'MYig+a7@3D+e'f#_P.Wy-=Ư9wJx>]*Rv,Q4xRc8᠌T8StYHՓpkZS棅m$T0 w R*ƺ`_]Nr 8]79)gM@O$b$dG8ǎ7l`7K+-R)c/(2y?3E *DCfo;u}Ԟ05`8s!vVnjCCKUYZU!p-MbF.i_ц[Qh틼 9 +b9:L +0=>Y}:eSݟ7D!hԹ7]:Ύgw~rgS\S|Cgo 'My.;%N2pªw]ݨV *[rnLD +΁Tr4DT:sdD)LAoty ++}NV[v`i,^h9HѼ$J8^fr4{;^GM3Q6>FsJaÝJuL7drEZIwJ(c)W6-p8\4gQX^RRjҔj%RjY ܧL{$bNI_ L"/x;|^{;=t,Px+dA&k0ĞrNJW[m.Ix$]~Ԧ;K')[kYqu]xz#301F w* IU) +vE҈}^q65  It]lkٰ{Cٴh?$殚=~ּZu2ߒw*>t3[/Q]KQԿl +ʔ]5XZ˴( a[ +C1,ק ] 3l8a#*r$Z@[}ȷ2o 0pI%2Y%{*_>YŒS aZ쉨\qJzՄQq(Ոլlf &D ď"%kh+feh?}=7|otcg~q۟Pͯ\o?X8i0]x8NCKpeyTlWmh$JMOR_woM)W=c+vȋTB0 +A!dN~v;AĒF Y S8Z/%) NV_d%ޝũǪe^|tIO/~wzWF>WwAe 8Jy(u`qaDϢУ )T8YD'$p *7Nr.`;YkP.'3:}:91o5jo:-J8!q]T+rB 8&{1=Zb\FarYp>! $p2De+ˊ j͍* Z,K̜$`I̒eE"nW^BH#](-R$H<[0;%|, zڀ:ݬŘ"cz`Bp u (ڢ%UI +9g6V,~#IeBi Vl޽bNbQ} 8~#[:5ٶ:vjnv^Uf. ą'D&7WN95DTQ#As sƇYl)`1d*r"-2z.+% Sp,fWC Q(. +# ؤQrb _EAK6C3nS3mM{ -3<:&l:r2!`fMKRK@,L2O9YbŎ^p44vg̱j\SCZB@?LW{p$t't:CeIdm0CHP" L `B0 B 5$z# cOM[B1f`߮큱{;k'q`jB Z$D$)9є6 wE}odF +IţcډY폑.;w͈m`1Ini%v]Ql#C5x4Yiϱ̎/-mqcqLE*&ղ!H&)[._ʄX$W,@^ŧ"g5|}ٳ}[){N4Jv5ڸukT]swUD! 96L4ϼWg.q{ZnFt)P<;ʼ? m"Z_wp̾ QyA[f +r\_B/r,Pk׭+i\^=ʠ0gk]sH)tPG}cFg{2" GL%ޟ@THv$GFliUj%̑ia, fR8qY'w Ke֧ctK\757Y0D8!%Gt-E%$cZ*00<$0fUgЬk1(`9<SkWw/d(-[?}iG̻ZEƬT4xA^Ȥ)kįb[7W6/vAm ([ǟOGK{VOs7˴rVv/Q>Tїm1>&hId@;f8w qQM\ZT) > ۜm@/!93M#R:Aj`:GTao X !_TB)b(2N1JQ0^(/LLyBr[w7KwV,hz 2@(2RnDžkxV뗔3G#VhI;p\pJ,>HHfKa)GiQC"͘n$(&)Mƚi41qXqoSv`/bxİ#~"@QIi@@j5sCEF3V%·zFaZv+J~"_,^OĂx /ǹIy|m^MѢEE븕y+xo᭼cg"#N"R%GZNJ,Q;>o"pdW lwwپ;In8Ii}o$ u*)tXW~2 +cE Mg2uh-H @mUve&ƺvi9vs>-ZnX qZ8Yifg * {f(x +Zj\Юiڈ*6-mZIܦqnӜںj[Ak 7|^ 4-[`ǬdY199pj!ꧭaїz?z7]{_o|آW,i}|]zٵpK!{Sp_u)M9nҫ+ʐ"RY(Jn*#ZS$)D\-vddR?ba)v10aqT|*]FC|&HEY3_ `9?ٵll`Fcw]"ʲ_K^C3gDa[_ :qVG&V́Ð׈=(!ȣDQ$IAM$l ג(_"FxXVU, 9.t`Jxo޷;F]SIpL?3%zm +tOnߴGlG"pR `Yvq 6<Ɓn%Ÿo*W`K Dpc?h4!RKN˕]mh*(6/4z![Xc{~>!X3 Z)+H  @VB 3)j{k- +rY&P}Ac2 { E,(phhluHd%TrFQħ?Z~]yaֺXvk^'o^>];tK"}LƝgG΋E]?˪)/:>%<%hggfmb2Woګ +}uxulU$17_. Wd $8&xȰwe.$K&dk 0<`f eJd]NH4 <$2$X#7̇-9$ ) Ɖ 𕕤M>{crɭjim\e8OyV|Va}1KLFXB~dilӝ|WOڶ`/}w~D+hWn\Pj >::Uy9IWJ4i )AUS:eRSHݸw |cAp꒻nwgUt 9tP"9Qwv^5 ťGE*XYS,.Q< @ar7t$=EyJY^ެl5߮/Xqۚ8^OUߦm`[ߩt`g/ۗrL.PSf8""j}'Gy޺M<2ܑl,@LUAf4 JѠj4ȌgG+&/窃*Q_Gqvr;q#iN=gaOyrn:uT TSXs eFmʅdTf3 EY&&%*4q\.#qRx»wpG35p5w &5zXS/ԣLKy( x?hH4_)|Vŗ'wgRɾ+AajDւ`-K[0_5oyi5n>)J%T|x;*AU!5A9EjYT8 juށkjlBLsT1fs#\67$aW06dobDP3ZGIIm/7VﹴGj~:%Fop]XlBb녽 ;.u_3},BUOni!_Y;kܶUrS4Lܶ}P#';D1!q@ C*jK&i +W쟡X.{2#^_.K2p*3χب>,i [79!RixO>'t6xk-}~."xUAbB蝌fR7[]Uuӧ|š+ EU_kxuqh8,ijD|IG Kt#`J=f6Qܾwt\8JҒTC*Y,Ԏ>7jO,xJ8ù@. 5Be@>7g#Az)+٧ cV?W}pTW?.ɒf!_|@$l]BD>$i[ +ڡ%LJ +ikJ (aPPiЎE3T;<{qy(;9wϽ;׷w#?`H33">|zݏ~h,"KHKK Rzɞa (^ ?nt@LulL5S->E,")ÑbįU2mES3Vd'3ۣՃz#cj1׽IzWR}..,Zq%=wE>Q*o7Y>&]$<VҘ O(ߟ:fc^D2a‚n)s>-0,~75 ^EF鹚 KD=hO<¶_ U@ < +Tp}-XHj܃h^evcIz؁6qv!ZNDE6=1v@G ag=q5SK~$`7G{ +Je,0i@9 IjRNmxI@%K1:/]6xNPRHMcغ$wMN|, 0T !D3|\4-_!ڪ_$q?+m`J[N-5w%8:UJa*kz%ov86hž\|}0R<`sw'g!X;smc x/Imӌ RA{0\ڀ( P܄y5Wp)n'C&9[iy{)jaœ/93J_u2z%rO\Ap˖wa3Mz,gK sM9apZd@jDC-ҎE|vbGŨ)-T*EwiJ4FσAe>Nhou- W 8َxvK]ꤜ xKFU?P_.z^p]V@0ʝlqGN k2؟ M5V^gY(ru]m4sanc< .3uc#4DiUvz9}_Uҿ>>Z¾J[D}m)YT OITӫ͸LE%jqZ{`xݫ;:E[k1. BX#8; }xVi!2w0cA' C:j5*sAڍ1ބ]%ty^o"PPsHƼc=ϢZbNzbk/c0'6K"QjYGļ{]AV&̽z- 8_\ +u@`~Sjʨ <ބ8Ѡ4_b,lA|1 |<|3$|k뢊k㐻4Z +zk^6r[hݒ֫jDMpה ^N<Ɇׂrj*Vo{ìfR- }Y-Ǫʰoix:y\qˆY`XLUhQOi3;n:́(PVcDX  +싵qw+uȃ]PP!Kv[_M='H_l:۷w H*c$yJ9C>m8=O{;\!Sl;^m A/^I Q>E{xޝmQ6 ̹m̦ _9?DK k@ʈk!U{o/̀,e|:֩k8r#ߍ?i/ઊ;r+1nR*7K@M3yERM$}Ŕ̒h='׭s3s.@8_`F-b2nu}~EvfP{~# ³||W-NjVK?vt/ {|6oh?|7kZa[> o7oobQ˻;ק?y떚fTu ٖfO֥8{=zu{RvH7T}ꃺ%5жkY+uG-4 mԬ_HkNbCt Bk| Όk+wt]g_߂1֜Rg qW9RլIݼRz)|ЛÙqۻ/5ϲDz&~8Grn{ehFxm"2F^3QJ7CkJϫtjikD{δv*yRܔ/(;f@MmoƜ3!T0`mXeT,J6 +)(%-B!E1GJ?!RшPSZwfwcWhkaNs$) eI]]VV~b.b Ew-=Y}4jWu뮁Nїd$0̻}gᎹlYW- VQKԵz8SO^w3up6uU'nQ=5}ey.9!Ȳ찓=t1_~V=v{4NFbpT/brE}qN/<qo}\ZS垁\ToZDl'߰c;'!<Ď:Nji +'QNȘk,^gxU?k ~ eL!| GmĞ>7ӎ2"N []W|%' }dH:u;u.\N`ĞMp?N#nj?x.r[y>) s9ч>y.p10勽 tM7}Z㟐ec|b/:SO`>7t:kMwB4v+̎T9lxho'aWȸl#{шM&w (}e;ml-&nh L| +BP( +BP( +BP( +BP( +BP( +BP(L e'1"Wr闐Z)A}ٿI̱5e+{c{`w z=̕%dͨ/tlN|ckplm}&#BTk2Fj("S;H3!̆ [f܏Ux6\-ý5.E(%#c+dfН>"Zm-Ëo7V7nP`ȶ[e_ z +zܹΈXDhH4'wq<4oOtƢ]U1^Iif{*J9vu9qrA;LhQm MHV뇵r89]jR!o!@DJi@A.j LpA ˧0 hZQ}rm AjhX@#2A=#ˉ;q_哰6*}|^ڶtmkOH7b-viv'ڷl]LJLsB"Z!d!:oG+CkNXOB=iELD1%sBlnA'_ܼPOd!LAh21= NAu_"/4 ~ k!}w  䔩Ҩ :>1F}1 C XQ4VfQVޫNΈ)RgNXfe2f(371s 3g0̬df3 3{CawSãy0fgf3 6%K jzTTD|t3g!xy Fk1! yX Qj4UQkUB|ޏ~z0AXFh x!kA8<(]wK Z6ANʎN *UKž"_o]ļ~V| +""e_}r(+_TbLCT +ЏP'QQ%C5o2rE0^>ma_'NniWuƮTlTXKm ES(R$'QC%*4.H;/@H[)r:3h8)pJ@!%u7Cv|vJgvg1Hfjfu4U+iɼ^O˿_Ml <Wӛր`AD_'J9!/8`ŜN3rDWr4% R$/|*%$E.l+XZ%/f!G9ATDJ/ )r#FȞȔ1#fSfvv˰;72|gS׃˭ƍۆvaiݠivY ;TW +Z1X[\v +*`檘5^ufIXWOQ32<~(iк~]B<b+]\gy(=?n'<<%Wk_pYo);w@b"1QZ*8]#=?fŸ/sN]GAl-߃)h#>sm^܊Ǩ'tGS2.8Yl> endobj 142 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 163.1152 232.2119 Tm +(Assembled data)Tj +ET + endstream endobj 159 0 obj <> endobj 21 0 obj <> endobj 160 0 obj <> endobj 161 0 obj <>stream +H| xNW~$$n/{HJ(NJm$ !b ZcؗXPZ-0ӄN;mM7L3>={wd ЪOjdjIUGf䙞dΙ>ʳfUj{(_POr&H3p`g[QW c|FnV+or.o|=|aMʪjR& .AjGm4D1Uk_Cݧwmh)_6ԉT3L媽N՝ "s8+YMCɯ-4_-2X&E$i&Ys4_-@ "ZvZo޺zӻ)z>F+fG1tl#3Kco6'S^??,fcds9+rg^yzXpQ:29~ol,&X.(4:+O70=BzSOsP_ag)3܍aYYBŲ(W,{ +r8 :7u,^}NUQڐ!8Vs?PӦ]Qsjjs\ue[GYGܗo^S[{f~vcuMʪަFvUwR]bNUUVʬTuV5}/}kN?9pnq9m$j]DilU[{JRmN[m6ke6mV]nh{UR<.MTbZ}amV:.bHW(ʎe)`m a&fu4G Z a*c + +5,\jQf)~ϕQU5z:88mO} YOx +ye|)-7*ˁxlBKUtHf$Pa1~jxx$,DɹRV *07b 'c `)KrD*9.d"I̗yR"Kd,F'#ъMFa0;!0b"0Ә&.fcc-aW7(7c? 1na9Nr'n4]GG?;/TS43 ?TFPe@33b?@,_BuD1C89 "BN"as:ggcg+!2 +G|xTEǸk+?(i- N,->,=tWR^Oƪ4PI+tQ1\epGE-^ vA>7*^dEMSԪ|]EP?1X[k %6bFߔq[tm%/quq0ƾftFlץeEBS[w?;w*QIؘ(/oϠ K+޳p|m;csc !0-Ư[/*|P?FlDQ}jynHڸVBt+ +iH`|`I@l|v삏mئ۱c&mti6if:it:f2NMêd_|zbw{ҥkzW%_}WLJF6V%RR3YtOxAA +,JN`2,moB.`sI'Sb5vk6hKs/.KU+56Ui]{9V; b 1aSj6@sg2s1 4%[ a l2.`-/⥶'B~wK).iڲ21kh^rD}0e-=D纔}KUgB}07 nj墨BR;õl[přV+ש)_0:a z*]i3=` 7UѩJ7أsEb 9X?$t K"%\/ynӸ^ʾ.$;RoQ3=RVYxf; a@=hm'"􎮉'sׄڛsK4F~ {<)`dҒ8úEfw${%ICK6mahBVhmf6qKPw(h>.p?u⬋3Z2\#Bц۲&ղƪK١4f3)nSwhVĻv¬)5mQޥlu/VD)ve=MxjDgϡO ޾{cN(}G-hOz$E3^I-cx)ձ<>zdGrFRw[BnI̕T '%|%JzrY| D!}Sjs@se(»+7T[5no:9^б]\Ku]ٜ\$mbt u +2bqCXz锝JFwW⌫3,5%6ҍi;7;fjm/ED0|z^m]Kv1KҜጔY"^ƛʱv'Rų1=uFUQҀHƸTa1hBap%M.1h3yޒDoqEq3GVvt<=:Jtn5UmvĶmVu~U /DA4NV#o_kGƒH8AA!z0SgG/<@ {:"( +x2tx0A2W]޸yg#C5@7LيN + + /c|#Y6$>Z5buVE){vݶKwҙ_V1 +.im98F~- kn; [5m,e?@NKD0$s̈́BvLhskS}}y[ȁ\n |TZNe֣g3`:Gɏ_^ya}z[C'&vMAl_Xk'! Of|u/d>=)|@h_ K@>CdɝK-j;Ƨ"*O5$@+mM gEL'J=@ [$ȿ"X  +-/lU7Dt%=/ب0 ߹!\(R@Z> K[@-bptwZHF\QĵK"b4F*b44bm3v7O|;s9|r<8nTAÑ̈g>-<9bݍd7;:FXB.BHSg:66?G`Q8xwv8ia>Ox[]xT, |8RęWڶ'u^>ELT.[º(w7 I{;j,$~;DRyN[q <]}Ayv)y8TV y믓Z֌*7^uUAj9'|I0Ѻi/OȊ1pO|12>QG;Xӆ#g,amy==r6\KTCNRU(S!UbA +TE,.#^J.\pjxaTbC"NqLyu@"ޘT^ /m5LFd:TQ<)[؂mjFLJyi)\I4?2/rςno90gh=H0`µ%m +!,X/ȔO- +Y6wO9OqMx~ͱ:y'p3 ~5p !}:qeqRWYpξh=^kgOrk[bvu.YGfldP=Z錳]ke6-[6KHe"x3hb&Z~,ү]_mz7wH xԨ{1qownդgsc+Vͯ El䳻&#:k8B k( endstream endobj 139 0 obj <> endobj 140 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 18.9141 179.21 Tm +(Raw data)Tj +ET + endstream endobj 162 0 obj <> endobj 135 0 obj <> endobj 138 0 obj <>stream +HgcD/K B - Zfj0$9ih$)ugl|I9e[KkSf,nygkk^yO?&.CSpi;po\|[e +|Exv?ɻGwњ6a16:_rDN۶|=w<~Zjm᫊TƠk-mk+^m@[meжmm󯟾ˏ\upQEZ2m/llloyC7\н׬U&3PmP<6.ml,m.mbVYR\[WrǘUV7 +ںc.LuS2#zK1-VSaPQ?jJc1ڂBDb"Kjiyo5[>')MƐ¬@[K&`FMƐ2'-EzZ+MƐ½Dv6~C +)>  +} +k ? (ݫIw6< h%Y(a".vB(yjB&yJB$JBT 8Hө"yqi:M +hs>w#htѡeۭ}SASaCjo"">1R &RsrC̘ZT]'6ΏzUbX4_<,hy1[=Ђi \Vnm>/Filter/FlateDecode/Height 173/Intent/RelativeColorimetric/Length 4261/Name/X/Subtype/Image/Type/XObject/Width 311>>stream +HDd]cd$c$##k%IX#+YI$+YVF^++k$Zd%ce%YXYIFYc1;=<9|ys3{Nt?jqԖU%?O-\ &}f 2w~~4G4zr%{kMe2EʲFS6Z#hb%SlN\9+ )7(G)u4q-=eˑ@eԙO ?|WdajaK`5ejka-GIwuZU=+Gu5Q[WY&Й-j F ؜htFF-r}cػŏf5@ineÅ"㱜|ma,Zַ?BViGƾ(q{[eR$pe@K7 ˙RQ|TYS+ /V/OͼBDKt{JD^G +=)Lep\I3q.qf$HW X_HXR`{G":BԈl"dS<6Q[7(uVq%6"3`-W5HSarEחa{C9غ GM{%AR`zK=kiºLwX]P3Q&<-G+I\ \E*@ 9 Tm%f%?!ėۻb6Y7+DI{aik+%UƖzz}ۢ/7ח6&3LD|^K:2Y-Y!~roAe hP#`bɵ5͢?%21eL!l8D`=3š=4 %l<yG]SC#-D~"XMPut`)C +?Ve +B#> vۡ M +WQdi[m +-M.)6 8:0_Ȣ䗱Gp#Nd[aƤ(`®'RxfD[Znȩ"؆%e +=3ؑDAl>jDӧI`9`KWY[݄A䑧2i5U;ld:ŞȠJۖ*Q"6^T"lN'E .SR=dCOۮ*)"ZCĞC, +؈ؐZU<`O!DG KdR 3J}RMK+HFI#Y$ȶ *^l)Hӭ\-)142a`-5>Y!ASp^.u7 +k Re ȍ зonx"l^%lυ\`A55"2E-O䜹FYWbشL [bDfŅPgikB؜p +΁u+;rGWNH = Md(Lq UyIvC0lSͅ,@6*I%j?8"6+-} W} U +L nTZ^fe`l֧ a5԰I%BD&l\ 5*MWJ_M7Fp!tjt*jhW>+l'":)&*6]/xUL7f-L ؚ) +܏,w#}-v$ɲ8sMp#a=*aՐf l;9 EWSg _-w.ca +\Ea"~/Ad'") UsK/Su7WBKcv!wJV TYtiv!wJ-XBjy5U&&&&&&&&}['.Ht' m[\ ԿV-¶ T%MAw%mp fՅ9M9Mip [ڇk2'pp ݍUW-C  [ jEMIL'.v=lFPXlfIqLJPf;l5YJYSēxҰM`}طsvH/7&%^C+x2|F)'\x! +،]s[LΕMF| b6C~ke=Oq"Hgĵ'YrlfܿeNL笟s)׼b͋߰ld5o +˽&#C,GQxTOFDޞ6Oޓ}6u0ɮ;X!W5je͹KZ,6LOpL+,l3` ;K;&# sPG]b?-3ً ( 0(v!]^ ƭ(c G!ltoq AmBK=7‡ncGe;hU6E_.]X`;c{T `R(2 M1ay!+[æç[lmN2ۛk_wÉlӽͿ ˜\b!jwYMa02- +_cXk'*VE?**"j菊<QD**ʏZS**?""Zk̛{ι;>#{|{]BH[T;PnkԐM-.$,D8d{K,4vH?PɦW1@'-2bWѪf)(;H į$:̋-:8(ٲ&9(spd5Kݻ@=G+&pWfQCϿTTu#<](k]C?79l|,g0E 5TCsanLg+{`=L T5M5u.?}K[ll~DS<r +Rg#rlڴadC`-6۹0+,7S |x©@(lAD5:TgNYnlaEYQ[d4} `j9$lhlmɟzg=SN6BZ(?:&E+6pXA8koY r]LiG~ևM3DoS%`g 9}eZ]~C߃ #wq/Ƭyp([3Ã]&ٸh2K4FCq_`-HY .sS aܘg]w\{|ukNE [5J;Z_R)ANKf,El9PKeqBGu뒋o&[ߡc[^1q}K.YBlc"i1٢.oƴ$̰ +tj +:Y5z`=_U6z:bq{H. 3m6}s> $aW6kD9^&y#W'}dᅬ_I'~y6 M!倪 fOu2V[ê +(7$]\dcIo[w}CZ +|M^7d}k"E>stream +!Q!P!O!O!N!N!M!L d d c b S R R O M L K K JbaUTTLKIHbdaaa`[VVHG_^]]YXWUHFFF]\[ZZYXED~D}D]T|C{B|BzBzAx@w@w?u?t>r=t>s=m9u>q<p<p;n;n:m:l9k8j8i8g6h7g6f6f5d5d4c4b2b3a2`2`1_1]0Z._1^1]0[/Z.Y-X,W,V+U+U*T*  endstream endobj 137 0 obj <> endobj 165 0 obj <> endobj 166 0 obj [0.0 0.0 0.0] endobj 167 0 obj <>/ProcSet[/PDF/ImageB]/XObject<>>>/Subtype/Form>>stream +q +/GS0 gs +80.4262487 0 0 44.7387171 348.6249084 190.8651342 cm +/Im0 Do +Q + endstream endobj 168 0 obj <> endobj 169 0 obj <>/Filter/FlateDecode/Height 173/Intent/RelativeColorimetric/Length 4261/Name/X/Subtype/Image/Type/XObject/Width 311>>stream +HDd]cd$c$##k%IX#+YI$+YVF^++k$Zd%ce%YXYIFYc1;=<9|ys3{Nt?jqԖU%?O-\ &}f 2w~~4G4zr%{kMe2EʲFS6Z#hb%SlN\9+ )7(G)u4q-=eˑ@eԙO ?|WdajaK`5ejka-GIwuZU=+Gu5Q[WY&Й-j F ؜htFF-r}cػŏf5@ineÅ"㱜|ma,Zַ?BViGƾ(q{[eR$pe@K7 ˙RQ|TYS+ /V/OͼBDKt{JD^G +=)Lep\I3q.qf$HW X_HXR`{G":BԈl"dS<6Q[7(uVq%6"3`-W5HSarEחa{C9غ GM{%AR`zK=kiºLwX]P3Q&<-G+I\ \E*@ 9 Tm%f%?!ėۻb6Y7+DI{aik+%UƖzz}ۢ/7ח6&3LD|^K:2Y-Y!~roAe hP#`bɵ5͢?%21eL!l8D`=3š=4 %l<yG]SC#-D~"XMPut`)C +?Ve +B#> vۡ M +WQdi[m +-M.)6 8:0_Ȣ䗱Gp#Nd[aƤ(`®'RxfD[Znȩ"؆%e +=3ؑDAl>jDӧI`9`KWY[݄A䑧2i5U;ld:ŞȠJۖ*Q"6^T"lN'E .SR=dCOۮ*)"ZCĞC, +؈ؐZU<`O!DG KdR 3J}RMK+HFI#Y$ȶ *^l)Hӭ\-)142a`-5>Y!ASp^.u7 +k Re ȍ зonx"l^%lυ\`A55"2E-O䜹FYWbشL [bDfŅPgikB؜p +΁u+;rGWNH = Md(Lq UyIvC0lSͅ,@6*I%j?8"6+-} W} U +L nTZ^fe`l֧ a5԰I%BD&l\ 5*MWJ_M7Fp!tjt*jhW>+l'":)&*6]/xUL7f-L ؚ) +܏,w#}-v$ɲ8sMp#a=*aՐf l;9 EWSg _-w.ca +\Ea"~/Ad'") UsK/Su7WBKcv!wJV TYtiv!wJ-XBjy5U&&&&&&&&}['.Ht' m[\ ԿV-¶ T%MAw%mp fՅ9M9Mip [ڇk2'pp ݍUW-C  [ jEMIL'.v=lFPXlfIqLJPf;l5YJYSēxҰM`}طsvH/7&%^C+x2|F)'\x! +،]s[LΕMF| b6C~ke=Oq"Hgĵ'YrlfܿeNL笟s)׼b͋߰ld5o +˽&#C,GQxTOFDޞ6Oޓ}6u0ɮ;X!W5je͹KZ,6LOpL+,l3` ;K;&# sPG]b?-3ً ( 0(v!]^ ƭ(c G!ltoq AmBK=7‡ncGe;hU6E_.]X`;c{T `R(2 M1ay!+[æç[lmN2ۛk_wÉlӽͿ ˜\b!jwYMa02- +_cXk'*VE?**"j菊<QD**ʏZS**?""Zk̛{ι;>#{|{]BH[T;PnkԐM-.$,D8d{K,4vH?PɦW1@'-2bWѪf)(;H į$:̋-:8(ٲ&9(spd5Kݻ@=G+&pWfQCϿTTu#<](k]C?79l|,g0E 5TCsanLg+{`=L T5M5u.?}K[ll~DS<r +Rg#rlڴadC`-6۹0+,7S |x©@(lAD5:TgNYnlaEYQ[d4} `j9$lhlmɟzg=SN6BZ(?:&E+6pXA8koY r]LiG~ևM3DoS%`g 9}eZ]~C߃ #wq/Ƭyp([3Ã]&ٸh2K4FCq_`-HY .sS aܘg]w\{|ukNE [5J;Z_R)ANKf,El9PKeqBGu뒋o&[ߡc[^1q}K.YBlc"i1٢.oƴ$̰ +tj +:Y5z`=_U6z:bq{H. 3m6}s> $aW6kD9^&y#W'}dᅬ_I'~y6 M!倪 fOu2V[ê +(7$]\dcIo[w}CZ +|M^7d}k"E> endobj 26 0 obj <> endobj 170 0 obj <> endobj 171 0 obj <>stream +H| xNW~"du%UBHBK4!$ o)mXbi;-JhQeFg&2VۙR*o%ә>g}{99߹r &MɄ!orX$jM7=?46gyk@nקj|Lꨝ_Vn/'oTzj1*7}Z~޿ƄL~Q`@ϛ\` g>Rf0%azj2zzLA$C_W`cĿ}Ih,j |coZuQJQ %0ٗ:);PO (d!Wx-xI36%2L&%,4@s\fjZvFwԝu]}=L;zw=Y3J}Qp5 0Fg$tcfl7v{CQq1$lgv671ͺ9ĜdN3gR\bGCE8ձq?+>%XX.*;4:_7,zsЃP=Fӻz/=EէE +K4(R,[rŲ8X'eQX~e]rsZ,rVOۊd њv5-_|gӺܬyZ2R`UweeTwTiWUUVtSeM9άܢzvTvRYlYi+NUȮȨTtQ%cE/^wˍ*NϜݶYpr]M34`ڂ:kVh^bD[i뵍ZEۥӮi7;}ۈ +S`ZfKLTlZ;}QmkV:.~bHLPJ”yPi|Gl*#%E2QhVhx$7#1،؆8S?/yJ̑@ҎlDWfe;`o0X.k\9|Iӗnx%v3p*E$#@E}b^,*Z}Oe>cCl e#hOA3DFcчHgwҘlQLa_d?38<EGb*S1)|Ә,* p% ؽq8uǵxp[q[O:O4w&?'{#*]C%?AK~*!qA,-ޒ$=tO%WYidK)tU1'Oep{EɌx~{?p:%Փ* (yԼ*.QnvvXk߀Ș趡];ސV.r{3Tb;>/_/#B[6n5&>9 Ilt`}B6a a?XSYDt]Ht]ЌQQ2BD=vH򊛞:=+I(U9Tˣ0l;u׉vvqPP(P`XB ui[Є +*V&ۊZ6Pmf߹эsy};wffN>0{r;g|75y$p;OT2t_@o#/&!S5%z ֳ,7CNs7PAXM[Dq+Jаs%aVϪ"*,,U,gMhC`Ank{OV~K +ƺ F\P4ڴ`r8"O>ϻ=(GJ(L:2i+ۗvvs2`![X9<]d%Ju-/;$zEnT[bs#Ęg4~@SװWgR Lpڑun7^FG[6mڂyf_S͛(-܂KǺ,dB?`!{0rmםrt3d>l2>a:ی +e$jYBowYTjz4kh@ >niIڛ{-L:<00l0*:1Ii|a۹gc~q+HzBi/ڿݛKHz5 jd˔*bq~uQ ꒓4O74erD* ÇD}0mSR#InkHp6'Dx˜ NcY /8~-a6@ ]܅d+[_4:5eFgY]FtgnhKVCoD*ƣKT"*dlhVlޙGu3&8' WpHej^il,fZjZFLF=C|b$W}yt&$E( RRI[mN"D>4Qհ\<ϟh0E8 - Z +71y;] qI'Y^~) xQ-Bq,cV6. 8 3 =CQ&c1(3/SX Y>,!DII2( +jܳsbKStW$՘Q}{ p+Wm54o-E5 氤0ۢi%6mlN7&]*%s;&+5!]-wM,{S`)&\PUTy\.-VӈUQ%Var=ZR&rAy'c3w:u]#jt#10)u6KA#R=急F`5zX͟6a_C$!qI˧zuvY*oPgW{--T3156$m +תp7>]#Ea?C +nQj/uOj~ހXruuuj N]=wT} }P~4{`$KV\E?q+`&7B?2P; +:ڈCvs_TC1?hm.Qҽ+9tۑ݊I&Q ޏĤԘ&6X>cm_h 1DŘM~3naeAo̙3gf su 23 +H,!9Ep"cJރ2#_ZV)A985Dҭ혉.m1+Oߤ{kj߶?RfUW ~5uL guUYK`xz˔3ay.r=-ÌEGIU[p<β3jNj݌Yh8sܣĹT|3(_F<˳pUk)gh^WU5ȱ(3O ȗd)`KUȠw}Ir$#oYIڞAd 5쓓xU +RJF +qp_~ DZS2GNV4J3FD\cvˇbj eFriF2S"IS|])ѷzya_XgW&29ߏxެ"_c%um)gv|u{z1W>"g-%Bnr-Mah(p]ñ9-H[&UF@wN-gc>]W"lXеaq8f-$WbZVqfn2[JڲE}-;(Xʗlyzi]Ӟja;Л vyS0\faN&1r '񳬆)PvӶwgzc!g=xm|` ~O.|,ٳ39؄Lzb [ɀkv=f=mf:|S9J)S}*Ѐi,㽍sbKJDKPed&IG7$NTѲ1q./yl7syq/J|F endstream endobj 133 0 obj <> endobj 131 0 obj <> endobj 132 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 12.9146 197.8643 Tm +(SINGLE CELL / )Tj +2.216 -1.2 Td +(BULK)Tj +ET + endstream endobj 172 0 obj <> endobj 129 0 obj <> endobj 130 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0.702 0.702 0.702 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 5.1033 0 0 5.1033 36.7803 1.5527 Tm +(.)Tj +ET + endstream endobj 173 0 obj <> endobj 23 0 obj <> endobj 174 0 obj <> endobj 175 0 obj <>stream +HV{|G?w'4!$].EYxʮ]IWމK^ +g^hREV%J.hIѠh +jy5h?KӄQ_e}RRbJ{<+ݤ2^_$,lP5jޅ[*!RI3S`4zBZVkWHk5mmkikk-ؿcl@T@\@z`@-Wz65k:ss3t. ax_p-n͘Cxa->ԑ ?P$H4F˘.?͔+Le||lW +i@DHbX/rVq\UFԩyZl̻LkiڛZMs~P;kst>Rd}/~L?_ү%^?3hdIFmیc.[LhvfC1{9yX{w`ޛZڼ/~<רa|2 OU|7x۪n[N>pP+V ۛjuYc +lc$Jp򬡮VǾkWcWvEŅ** ++NVPΑwLuLqD;G# ^c4O8V}ussJ?*?r'«clWėL(^T}E?ڏE) )~yQ=#9dž(ɼ1.50Q¨*0g҇KH%AY2KY+=])']C᯶\Q3ՕfWu綫筆biͰ-,b]K>!KO-sug=d{߆ o;| + `!*>A, p1,"=a5,#P ?ǰ'|4A8dCH8'3pnC\p|4܅;ba +LxȁDI )}CdL`6{`#́L~-̃*!UgPkD@Ow!{)RduLS^ԛIqJn[v?GiTHEt5*tJtʨrI7ݦ +<S0J_x*^r .|k(e"C'r̔a2\FH̦zCYqcA:r\Cm5ډoE5L52|OmLwj4D^SeL':EAΒƹLש3up*vj:U\X\%r(EIQ-s^%(vP<T[qTi7˸:?M)=iس6՞B\؞dop.Ÿ_~e}}hXgӬy8!Y897Bt]K ºz^m.t 'SẔ.z^lu]pY^Lr&;Sxg%D8JNe':uND;m[Abt-bCm!'=Җᶔ-(~GYTWM\ GY̮jRZ;UN3' +K#h %f*BաŪQxK֪9P(UKEh6&FQ=UoNmMՋ֛pSc8N5P}T)d0Sؔ0%MQnML(Fܐr3S7M 5y3|',S|}S9(pZgÙ`أv؁=f{L {Ch[R}iaiLxo$*kFe6t]M/2#-f"P6.6ȟrQRn +<Ly)TP\= +TSN4T*T*+;BUUT^ר|u(R=O !ERES#jLM)5CB潖ԊZSjK=uԉ^?7zmYtnwi؞ұeH6^:kҮC_Iþ+u}i}>=KԇC4IaLiMWSf,isiF 4>OHZcףKl5zqHIYJh;%G"'Aq +"1d?Mg$SI=ϒp9l\çϰ w|//K ˱+ +=cp*·B |LN|38Ty\E\e|+?%Wq q7!a;nN@2Rpk؂؆؁؅؃ +_؇8888&Dy$Pf&xu4uo9GҺ]9Ǚ<~6 !(pP/gyT˨( +⑀ 5AמB=Gdz&Dxph$1 2Z{BkhNx]:ʡ+C7TDf_MG7{$8jՔuFy.9UwO9rG*;8\X-\d<|d$I81C;T^זoHwPUVsv'G7܅2y7Vv[-~^b7G;nVVv~$mD/.Ր!m<6ُr; +yrGT_piBcP2AR{{"%d{!0IV#r N{$PJ+,Fw>n>_o{W NLH b :Xa;I8JK!C-Ԍ1SmuN\S!s.=O~ Pߝ0ɷ5~H$CeTvʨx5A-V[M|Eu]vAL +(KmG A"KbdئNKY $ɴP;Zg1LĤ6!mdFmw͏s{{>-KyErC]ڠvb^o+R|ӞS[q⽹o>~ΈZ 1kROE-u=笈妌Dr)ϓ6yߑJRlRZa<P.)۪Q3ԍj V?Su'\[kZP+E倥r3bfS2UZ@;Wl J~g) 1>M#O*RTYmx^#)Cx羌_<=b #뿇mvqlYZXRd|Bk6}y9Y_͘;'=-)MUdFO7}oTWsß3utUM1u0'[:`{#j阰RJ,.݆n2ԲE1 %?fݝMɧͪ}!w`Vq_,Ja&m̂` cfc [=nWE=XCFPAm>S{MǾ +Lef~Z֗͸>0h*G +6}FI[cJcApݮh|ݺl8PRD#m]^<'٢Q\t*@ ?Ux= +[ց?Kv?m @╌ib)ԾfJf`ʨnjlvH=^Bk S =tBc=XŞzXDO +>A /etr~cm#˝Ё6S1se {¢0%7x~)I}ް9&W)PvpZ Q\NJ*8ZCz&ҫNj!o l'چ ]?%G~B^xy.b 35./=1!q^/J'"ߕyb.-Rp -f rC|ƢDS;0 `4,Pа +m ay(xEiŃ^*DR0z.kpDڇI ?` Gs0]b}p̓ޔp-$ JPaJ* +$ ]y:RL~NcQsix N/|#6պۿtk;H,-33G +PlYֻ;\J*0/^||7[RyҒD{W!c踳(h-4a/EgY/!-at,hO/Z:@$O`L~սf/9yԚ+Ѐ&c1݋hՉ_b'6)hP)ؾk7usѮQB@VSS;} 72DN*שc-x/<'ߤ +*i'[@SXF@-C}Źb~Wnzh| 'ιLJI`>sx>|=[g8Arus RdAg@2XxAAuu/ן>9g1X-ǩx F|nx.o1|Slř\oKן*~p>!W@SP 2* 1'`uskL|"y <?!!r-%yw)| ybwa!Z+{7ǀqh{hNr@ϐmmdǝ*ڱA~R{Ү]AJ~ (Ϛ,>3ܯGzrQ=L9W)1`'OaW-l2-S\(qXv@#X#}.䵾)K{xHyBK;ʵb?ߥWo/\M̭dRnᅯ{pƟ,:DnCԐ!Bí\ +$ )D[Rf€RhKւ VQ@ HP l=߷|}&=M命E|d`_~Tw*]oM=W& ׶P]C jjQRRCR10fpqYq7Y"[OX:6G&d;W_*3~1K=`E0_g568ب4UKG *r)btU4S]/$||{TLñ};Oc}^c&'YD{|C.:5z@jbլcs`<;ۻ}]$̕V3Q9u mFJpy*Gef!O@ځ|'qӆ$KnUzEk*|UnN❗D> sŏQll(vny+fxcq9U4/{7> L]w8ވߒfx|Ciono>s@^3sLo6Fg-&6Fo(}Җm 6[V&~<͙q˩~C/>+~ocroSN~Z)v3-F:'jßk8Yj鞶`mV:VWOZ]-[~n?Ǹl&K|~E)cFRsu-uc rI+1̻*A:TR?*r18ÚD=RS3a|ɂjDvPdMdxeu<\b}@{Zݥ^}m&\(ck/۩0Og yb/Y۰Fy> 5yue> ƒ1N-6} F D/;窖S5DI,?+{$Uۉ$IY"yumoAge~}NBpa6U xdI|M29[1g>K̻}d EǔkPhBg]YGlTŐ&8RI +b.".&:TRP$H<Ҍ!d`ŸCYcG\w-*66Bl`@PsͿEG[~H`Ma+Wcz]ynj9ҿn[BG3d%B~ﵺ/jMH= 2B[a{\A8BcݜJ~%Hs0nCȳ漍t$ퟑϔ5 'ȧ,9OK_8vzVy8Bۅ}7s% mK~}OۧP8T.j'j掯|ݬ5lu&>zֻoj]8ss DjᷨS+WSl]-҆m2r5e.Sz5W~ .`CT3o9˦a(vDm {_i<%2꧹~j";9K (7:cU1årrFŲΫ^~V*@?᳢/ +4C4!z ,J[%^ +p,=@+a?;j5|Oi> #GICV&p 1NqXH0oҟaV FyHp6#v "G"r}d.`A7B7t1fY8zg +n=B db21|9ȵf!w;<`CWk,{{)XBfP'..!-p{!Ek#oEx$Y>p)uT2Bo'5 aH3s^8>GZs7Y{߆#?s \Q:2$>B\W܇ f +X<@3ɣdٯ+3wf2!aႲ-$a H0@tH.@2fA  ""/"* +EZZZK-u;c@!ܙs9w5a,i^ȳ}${l'DKn!c3\dGd8$LY(gSKv y'+&\<>&Vr>Dk!W#}(+WE7mgo;}MevE#C8嬏`y>[mT{ +j9p_õ&R3uFr|r-HAˬW"L>r6Eem1J'2S/*X5uն\:=[.c2y1<ȕ=Wz6KyoefXko.pIUBY4t 3t`2F92*n#̔g\rv-@_*̔Fm.A|PdKz@N^!\lոQ FTN͜Ô_B0Y? ,X` ,X` ,X` ,X` /@ (pc<\!YBE̻`!pB7~UN.qxv4Dw kc)mqҰOq +o7=ve#=&3+ޑw*w*p⃚]&Bk;|NlKw)Z,ٶ*VCWR'(yپVUUJfՊ7T 7RoloޖJ^vSkq*WlUL@s^MW<5VMkd# +Y0PS^OJQQZZl轂%шT}?L.5zě5%9h AQ<ш}Ch/tک Hy<)oJZn9uuúOg葐(7р҄,( hZ]?`F|!#01 vLdΓ_Ƃ "A_\! +a +"_(-t#6!n(Z274ǖW,$}+U ÜI 5Qǜ$/.+IC +:!4v`Yɛe!c_r& {}}}`}줛 |M^rO\|wxZG0_؍WA\kjL-C~CR$&UOj_|VSKůGt=Eqgkۺ{}^_^78^g3g[g/g2![|#=&&(qҿQ HDnUYIUTCu@MBmA]C}4v܁&hfhh)F +Ho U];GtD'Ë肮@7܉Rc=.z.ud/?`kt߻%9{+.#1 +p|Uc%[Eqͺ HJ1AD%3`Ta*A<$}a#x31 `.qڰ`)2,4x+? +/`5XCuX%l7-x [:a;v`'v1{W 8x oQûx8N)|pg[8Dvs|/qG _ϸ<_[ Wo|~$HV$dVfVe5Vg d-fe=g6Fly)9[%[5S؆ma*؎فى3+3؍w;{'{7bf2}ُ9A̻99{a#9x?}|X~xY 1v3ʉ|8SXƩa#|39p.q.".\¥|˸OW,\g9>U|ko븞/r_FMW*5ný|&-wxGy=<x(䡀|/lZU˶m۶lcYk\mvs.8\.jp-nnp/<i,x^m.x|>k-Ȉ舁؈ ## "#R"R# "#2"2'dȊlȎȉ_+r!77E>GD!F((?PPePPPPUPP5PPuPP M-m]=}00C00#00c0000S0Bϐ2 3Bf`fB +Y٘XXXXXXX[۰cNn^~AaQqI¿838s8 K+k[;{xGx'xgxxWx7xwxO/oI ð Ȍ¨، #3 23S2S3 23323'fl_+s177e>gd!f,,?XXeXXXXUXX5XXuXX ؘؐMؔ؜-ؚؒmؖ؞ؙؑ]ؕ؝=ؓ؛}ؗ؟88C88#88c8888S8B3388s88 K˸+kBm븞FZjý<<<£<<<ygxxxxWxx7xxwxxO/o_]! +QFaNAIEQMC1K'T6qO@ (ODILɕB)JFiNAIC %TCYMٕC9!Rn Q^S~PARaQP3SqXIRiQYSyUPEUReUQUUSuPMRmQ]S}5PC5Rc5QS5SsPKRkQ[S{uPGuRguQWuSwPORoQ_S @ ` P pHhXxMDMdMTMӟY9yZEZ%ZeZZUZ5KkNAIE[Mv.>!1 )::󺠋˺뺡ۺzzzzzzzzq`0pH(hX8q ?:89S8S9893839rſ:s;s^s~pAraqQb.%]ʥ]e]]]ɕ]U]]5]˵]u] ȍM-ʭmɝ]=˽}==ȃ=C==#=ʣ=c===ɓ=S=zgxgyxyxyxyWxWy/:o&oo6oӻ{|Ї|G||'|ҧBtg||Btɗ}W}E3C +( (bH ! Jm.\; HoA .* (EbW@TK?;3ίhdlbjfn;O4v=^c8`4#ƿQq8a4NNC]Rtd G8 g h q>Z%.@+\N'mp).C[\+.vVip5p=nanBGtBg܌.nLBz#}9\܊|G +qv ܁;1C0`xa>R!rB*a#*]1q I)1 qf`&fa6}`A<`!a1cxOI< Y<^KXx+ + +`-^kxzlFl[،-x[ ۱]>GS|W[|~OWNn`/a? 0_1 ):R1rb+i3*]1q I)ʻ9ygp&gq6}pA>ćp!q1c|OI>ŧ Y>織_K\|+ +p-_k|znFn[-|[۹]?GS~W[~OWNnſp/q? 0_1 )::MuuRdzJUҕ3T_ t,Fj&:G窩S35j@t.Rk]KF2Bt*]ktS]tnRGuRgݬ.nLRz+[}W9\:lѭWPin@ S5DC5LWS*U*WP!URŠ((ݥ񚠉ɚ[4]hfjf^\ݧiCzXhjQ=SzZhsz^KL/EZRZhU׵NoMm&ڢU۴];Nz( Eʨ8#r3gMߓ|ͬC#6)Q;԰2s @ŞiX,[CA[m `&BP*`ZDˋ4O-O EL +FR=5==fқf&#YHN$+V ef2 2G+iYl|lj|5TYL>Xi]6%UG% uPFPl7'E- +"mᖧH ɨ _N F9ǗHzMH-;G8݈a}wo&ؕAjrNobQ8{@( Y[z;dFҳ"-n-"-nkU϶ʨ>*5*T>b XpizYV0`cS#QP=+@;lylW[sT `m_=3$8 LJ&/[ +X/a]eËj}pAS&"MhPrQ"Hʣ[xL&'/4W +z2F#->@-D"2ݏ2>Z @?F8CSh1z¸K ئPܑ4Ȣ D|)LWuCB0>@*q~'F_Y-BǤH?E)8GHZ#̢?+V_gU!}`н&}@0Wl>X~pر=\K5sKqS +˓mG K+Jjgmf`)!-"1eRĨygd=hRp(MfAMC_MA:N\@E4 6ٽϯ)yK'4f ,Jh.wL 3cF)dE3Nh Kyk4OZ:\*Ж{֔ʥD끲+g:ґʍ3e<Y|ɲ9$5vXє,aIttz/| 8k|x]އ.*zKLTIo&D;Vdߦ^F"1$_8!\;SG "jSr;Yλg9[8mfSd4--uNyB#8GUo;s%Y=5|_o8">sd47%Ifڒ*$SEf;e9g֛3<t\::NlNFj]F+)1P)1T=4uehe݃eJgWW^TȤ;]^#4$w*PU(qT5`:SuճlmV[v+X{)@CֻJ;R4v y]̉呒~-Cz=r`cP=G +==r!(ǰܣ(;ZJ ON.ߵjy嵖=-}-U2?9=X-U19ΜlNi؅ +^-JF":Wix7ȹ˿u=O6il}w{;v :+T M}:5?jsSKUbp}|qׁɅoQ[snpc[5p}S +;(tg isg +5p[3{rbJj^JVWn +-c`y3.zwf硺6qPb=!?!D-l-l%c5kg{nXImMle``f)_JpfsOS7zTZY'#E3 3,Ä6?i/{MٚyAc]ɪGL qvtzky l+r-#=gO>Qv:LOBcJO}cI/ZfdI%.uU]y~Ճmxu|{;=EE_u}tG yZR(u\̝u3ڭЯrJvyd %}O6Q^r^F3G]&!#l,2}A0o, z;l"-}K +_^/sա%m"|&̛&ߗlgWO6s9EuOp^9|zs%9Bo) RTs|qюs]@CO}rY,yE|Q'R +͞:t]B2/6Kͯ]tN~m8ˌrkԏxI'6~\HVsŏgjxV|[?Wa՝wϗ4GЌ6j>z)'ed*'3U-V@h|KXsqo*bx +,{IuyM]#G|L!æ^XW^?a^Lj/xb5ļ +a\3WxԹ2XVCq$2ci&Bht XMk6гooAׂ:,6,< < < < < <||||||||||[U*je-~ϑXhKX vzծU_C[Zyq{UglvՂfdAIdͯ7I9~;e}es*N[veIY)ZfUEDi3-Sj岠{V% + + kڰ j+o9||||||<<<<<<*UWB_TOOOOOOmxXikkkkkkkkkkkkkkk7o@߀}g`}8F7oB߄ }&MX X 3kc................>|Cχ=z>|7@ @7n!B B?~!FuGЍA7^z"EЋ Sod_Rv/I%S,(CgEMb҅{ zaz]cwS܁ ^3swdK (A.fٖVYoygv"g oɖԵ}#%;;% u-0a.SnryuK)t}w7yApYwx,t6Gw>^*B DQ&Žwպ}t|qt|,w|xcx"A~㲂x94p'@㟆|/EDJa)]tU\U]au,9?n*߭gYF#[(9`ɟᚗ_HH\߄4YdXˡhUeIyF޷s_~6kEYV`uXւoOfmXօ`iJe[%ESݏۯ##DmFbN%#7-;&&t0j]\937M$_ӳ_> l~2pKC[u?0@L7ݑ0R&Ylͱ[wTqUU׻wioZ7%칠ٗ|Y3/躝s谛_Fï)xMWl]?\qKan(s]~Q1om1ơɱc;Wܛݽ;΂ZY;gƮ*>DRHHi^ (a#@ mҗU[HggI32P*bn\@,pI,PTONGe7jޭp=?Xס@ 4<~ hF*^7ZbQCppb̵Q`@4@th?dៅ-hE/D7֍lrhshձrY阯A#0" #0"#ϭ#F+-/g$Cv K)ܞͥ˥۩KqR6˞_mEU'{R95zxW޼ܘm1hxCbzws\$xuM0h~t@q q}5J!>Y{+b3x,xtRZ8iJ~e1^'RPݶ+M$Zǵ\vSa]n}|}1>vE:1/"ET^xHt3#U^xho߇v|>~ŧQG];/0MU^sIׯ/*Vn0 @;4 xÁy_5*7adfrI|!k`D36NC[S*~{ݫ  ǬMԪ~ 90#fz%еpZՆrZd3gfA4@́A7".u`@,=ttO%-LǧT0h90@kYk%sy + ,[w FcD:FcD:m: f 04 7o߀| e(g(gq90.q1Dzf\q5kb&ƛA> rhgb^&≮0Ɠ3nЊY"aa_EMqj ߛ\~?7Q6%9T*jgz4>l.1|m0mwR^Z^Tu'˥ŖW_ ;f|j3kKFMYdF\hR܆BkE( %+Qfl˔~!Fj$~kZooz5n{kU]GVnEgںx3YȘXqVƺ 28/れ-2.ؑ1\sϥ>\sϥ>\sϥ>\sϥ>w+]J}WR:QjX2Lt}_n ,h90@ "q0:/-[o߂ -[o߂ 6mo߆ X u.}1;dlN2O~\Kyd!K'?SJ 6ɑF#ߑ% 9#zGR>g9HIm$=V/ur&jꜨKE->Szw> * _vR !"7Gu{An<lJTT2B;%>V&6y&/l]7ՂgO5oF7-W͔l6,DGWO)>vJgE?=>I1ݭF@uvt}<;1qvlt::ᎍ;I4ԒxDkAe@W)^EQiONet+(L<dϔҥe0d0)x-S}=Ra*!+XD"&]T"H<&?;rzۇ Uܮ8տ!lҹ穫ەckEKk[+77F'\Pvyxb\uG> endobj 127 0 obj <> endobj 126 0 obj <> endobj 125 0 obj <> endobj 123 0 obj <> endobj 124 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.1096 0 0 6.1096 30.5 120.0732 Tm +(+)Tj +ET + endstream endobj 176 0 obj <> endobj 121 0 obj <> endobj 122 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.1096 0 0 6.1096 195.0586 207.0488 Tm +(or)Tj +ET + endstream endobj 177 0 obj <> endobj 120 0 obj <> endobj 119 0 obj <> endobj 118 0 obj <> endobj 117 0 obj <> endobj 115 0 obj <> endobj 116 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 413.7871 169.752 Tm +[<00A40114018B0114018E01A101670138018E>16.9 <0114023F00EA015B00EA015001C8>25.1 <019501380195>]TJ +1.269 -1.2 Td +[<00EA015B010E023F00A3001F023F018E>17.1 <0114018B0167018E01A1>]TJ +ET + endstream endobj 178 0 obj <> endobj 114 0 obj <> endobj 113 0 obj <> endobj 112 0 obj <> endobj 111 0 obj <> endobj 110 0 obj <> endobj 109 0 obj <> endobj 108 0 obj <> endobj 107 0 obj <> endobj 106 0 obj <> endobj 105 0 obj <> endobj 103 0 obj <> endobj 104 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 249.71 169.752 Tm +[(Clonal analy)25 (sis)]TJ +/C2_0 1 Tf +0.152 -1.2 Td +<00EA015B010E023F012D0114018E015901500138015B01140195>Tj +ET + endstream endobj 179 0 obj <> endobj 101 0 obj <> endobj 102 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 346.4434 169.8809 Tm +(Lineage)Tj +/C2_0 1 Tf +-1.629 -1.2 Td +[<018E>17 <011401070167015B019501A1018E01A8010701A101380167015B>]TJ +ET + endstream endobj 180 0 obj <> endobj 100 0 obj <> endobj 99 0 obj <> endobj 98 0 obj <> endobj 97 0 obj <> endobj 96 0 obj <> endobj 95 0 obj <> endobj 94 0 obj <> endobj 93 0 obj <> endobj 92 0 obj <> endobj 90 0 obj <> endobj 91 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 160.6001 169.9937 Tm +(V\(D\)J assignment)Tj +/C2_0 1 Tf +1.247 -1.2 Td +<00EA015B010E023F01D6015001A10114018E0138015B012D>Tj +ET + endstream endobj 181 0 obj <> endobj 88 0 obj <> endobj 89 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 6.3792 0 0 6.3792 75.394 169.9365 Tm +(QC and sequence)Tj +1.713 -1.2 Td +(assembly )Tj +ET + endstream endobj 182 0 obj <> endobj 40 0 obj <> endobj 183 0 obj <> endobj 184 0 obj <> endobj 27 0 obj <> endobj 185 0 obj [/View/Design] endobj 186 0 obj <>>> endobj 25 0 obj <> endobj 187 0 obj <> endobj 188 0 obj <>stream +H| xNW~lnB ED PkľmV;-J֢E4vRoN>sssyϽ.7 ءBBQV-5=;-xl@OȄYh|h423#msMb.`GgSΟ0^d大j_ PN[o1%-;fUj<rs-[l2Gse47Q&c4RkWp5ӯg +9 ?& Yh-)_ku:~/%u7J*^4VٌM٠jtD m<KK?i'^F4,Wsͤ54GC`-LMtUu/=Hz=Is%Z}^d8n ?#Ԉ1b\cf0v{q8exRb1;_4;ͺ9oN5g^ZWsZgbX_GsE5 /K>cS+K m`XjlX5_8鞺уh=F=[k,eF 4 +KG+KQXeqX4N’XZ2JgXSl_%kj;&mϿjjo>T}uR`gɷd32ޒ^^-Qm߭S'VU[uj:3*%UEVYZ5Lɕc+WP-sρ{F v?ܱzpTfhf5Z/(* uM[}["X[m6iRL+j'-vߺT'VZr0F_XFn'SJ#W.*6[cdY*rዶ8 `8G.aa;v`N 3Ken,%@}-ĶlHv`_ `2'pWs _W/ޒ -meC$Vɗ#2w%J2$Rf[2K!~ɒ<?hqyQASx- 3:aE +\Fb.],ÿ $MlJo:% d 83\i*<+,5¢շpSc1 >l/6A_@ ѕ~ : ` B> Eoїa(ư7RDB:#L$&a"1C(Lg +Gc&b= 1*ìN. +7YC܄܈w'YOn^'1.///?׼6p&.lCfs3 +U,U!!xNA+6B Ԣ=[ }"qXƩxأ9un +a+W`%WޔrPQ9!oI9.d,Ui,@d,et?BXg,T4apJ{GX܀|ǹ8]ͳw/Or=aG.UvOޮ~[.UFS\:]>7'y  bq`1W ,Y_mȬ* ח[ k㒓,%Ac,hdL,kwW 3s{جK@8۱^We?j2t6EN36UC'qk]'D*ETU/B/IL煱.6N0ˍZK§-KAu` VggtVɖhJ''}sKL6?_*o5ͭeEf[Bg:8U=1h{Rɹf)5Aq9,CۥLZ1w?[^XA`<. ōօZ[w4"MZ4Y:|j'WÙԸ Wm!p*\|e}tݾp!'sRnʺӾ5$Ew^9^:ToPމF)/ ~՛Jn4^p_"r q>QhQU<yӐy0p=--^ ?@vg=o\}Z^f>H6~k VyށNTWo<oF*cAd~Q:󑃅i~:O__T@NDeRdQ;h`/Kl΂6x.jb3Ch +g90'܆3$ |Z֝]ZVQ+q + wsr/'ǁY +*ц"? )ߴu*1YRGN w^A\nt|Fϋ`;=GZ˽- +"&?{h~hov!V b)brV~mtBZj/b "=Gm4%u:yA=R`|@5 +@0hIJPVhPo?*ߩѬ霠=OCL##:;T-X7i}Uѣ̇|W@-"?1w(HMۇGq,oMQyhԅ}~].߈rjBɅ;KX^_/pw46ZTr=U%J?SQb|9e> +h+VxNɬK%) +KWniƎ–[ n-j]޾QZi!mz Gd-VJe(VjGK/h up[/1=(?mC /kyK[r)0 ׏Zh1FnYd%TY1*,kRzAYn=Z E1Fo=^fS#uP8DZ0,ϴ\?iW%=˞ ^ًO8[q CX 193Sա= endstream endobj 32 0 obj <> endobj 33 0 obj <> endobj 34 0 obj <> endobj 35 0 obj <> endobj 36 0 obj <> endobj 37 0 obj <> endobj 38 0 obj <> endobj 39 0 obj <> endobj 195 0 obj <> endobj 196 0 obj <>/Shading<>>>/Subtype/Form>>stream +q +0 g +/GS0 gs +13.9381847 0 0 14.870286 393.4586792 122.2235107 cm +BX /Sh0 sh EX Q + endstream endobj 197 0 obj <> endobj 198 0 obj <> endobj 199 0 obj <> endobj 200 0 obj <> endobj 194 0 obj <> endobj 201 0 obj <>/Shading<>>>/Subtype/Form>>stream +q +0 g +/GS0 gs +0 14.353096 -15.3129435 0 186.1180725 49.6956406 cm +BX /Sh0 sh EX Q + endstream endobj 202 0 obj <> endobj 193 0 obj <> endobj 203 0 obj <>/Shading<>>>/Subtype/Form>>stream +q +0 g +/GS0 gs +0 -14.353096 15.3129435 0 188.1518555 191.8651886 cm +BX /Sh0 sh EX Q + endstream endobj 204 0 obj <> endobj 192 0 obj <> endobj 205 0 obj <>/Shading<>>>/Subtype/Form>>stream +q +0 g +/GS0 gs +14.353096 0 0 15.3129444 136.9708405 120.8885498 cm +BX /Sh0 sh EX Q + endstream endobj 206 0 obj <> endobj 191 0 obj <> endobj 207 0 obj <>/Shading<>>>/Subtype/Form>>stream +q +0 g +/GS0 gs +14.353096 0 0 15.3129435 308.0059204 120.8035965 cm +BX /Sh0 sh EX Q + endstream endobj 208 0 obj <> endobj 190 0 obj <> endobj 209 0 obj <>/Shading<>>>/Subtype/Form>>stream +q +0 g +/GS0 gs +14.353096 0 0 15.3129435 222.5567169 120.6567307 cm +BX /Sh0 sh EX Q + endstream endobj 210 0 obj <> endobj 189 0 obj <> endobj 211 0 obj <>/Shading<>>>/Subtype/Form>>stream +q +0 g +/GS0 gs +14.353096 0 0 15.3129435 51.7137222 120.6398163 cm +BX /Sh0 sh EX Q + endstream endobj 212 0 obj <> endobj 28 0 obj [27 0 R] endobj 213 0 obj <> endobj xref +0 214 +0000000004 65535 f +0000000016 00000 n +0000000147 00000 n +0000026870 00000 n +0000000000 00000 f +0000026921 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000057493 00000 n +0000057566 00000 n +0000057762 00000 n +0000059389 00000 n +0000124977 00000 n +0000190565 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000296669 00000 n +0000268386 00000 n +0000322865 00000 n +0000273726 00000 n +0000351617 00000 n +0000315518 00000 n +0000351429 00000 n +0000360845 00000 n +0000028014 00000 n +0000056805 00000 n +0000267705 00000 n +0000356610 00000 n +0000356726 00000 n +0000356842 00000 n +0000356958 00000 n +0000357074 00000 n +0000357190 00000 n +0000357306 00000 n +0000357419 00000 n +0000351094 00000 n +0000247598 00000 n +0000247887 00000 n +0000248175 00000 n +0000248518 00000 n +0000249215 00000 n +0000249568 00000 n +0000250270 00000 n +0000250617 00000 n +0000251318 00000 n +0000251664 00000 n +0000252364 00000 n +0000252712 00000 n +0000253003 00000 n +0000253294 00000 n +0000253996 00000 n +0000254341 00000 n +0000255043 00000 n +0000255390 00000 n +0000256091 00000 n +0000256436 00000 n +0000257139 00000 n +0000257484 00000 n +0000258185 00000 n +0000258533 00000 n +0000258823 00000 n +0000259523 00000 n +0000259876 00000 n +0000260579 00000 n +0000260926 00000 n +0000261210 00000 n +0000261491 00000 n +0000262194 00000 n +0000262541 00000 n +0000263242 00000 n +0000263601 00000 n +0000264106 00000 n +0000264390 00000 n +0000265091 00000 n +0000265436 00000 n +0000265774 00000 n +0000266065 00000 n +0000266357 00000 n +0000266649 00000 n +0000266941 00000 n +0000056870 00000 n +0000247024 00000 n +0000247072 00000 n +0000350600 00000 n +0000350662 00000 n +0000350040 00000 n +0000350102 00000 n +0000349978 00000 n +0000349915 00000 n +0000349853 00000 n +0000349790 00000 n +0000349728 00000 n +0000349665 00000 n +0000349603 00000 n +0000349540 00000 n +0000349477 00000 n +0000348909 00000 n +0000348972 00000 n +0000348341 00000 n +0000348404 00000 n +0000348277 00000 n +0000348214 00000 n +0000348150 00000 n +0000348087 00000 n +0000348023 00000 n +0000347960 00000 n +0000347896 00000 n +0000347833 00000 n +0000347769 00000 n +0000347706 00000 n +0000347079 00000 n +0000347142 00000 n +0000347015 00000 n +0000346952 00000 n +0000346888 00000 n +0000346825 00000 n +0000346367 00000 n +0000346430 00000 n +0000345917 00000 n +0000345980 00000 n +0000345853 00000 n +0000345790 00000 n +0000345726 00000 n +0000345663 00000 n +0000322397 00000 n +0000322460 00000 n +0000321905 00000 n +0000321968 00000 n +0000321841 00000 n +0000315455 00000 n +0000303544 00000 n +0000305369 00000 n +0000310348 00000 n +0000303607 00000 n +0000303084 00000 n +0000303147 00000 n +0000296199 00000 n +0000296262 00000 n +0000273263 00000 n +0000273326 00000 n +0000267818 00000 n +0000267881 00000 n +0000267641 00000 n +0000268323 00000 n +0000268523 00000 n +0000268550 00000 n +0000268983 00000 n +0000269331 00000 n +0000269401 00000 n +0000269674 00000 n +0000269801 00000 n +0000273663 00000 n +0000274328 00000 n +0000274577 00000 n +0000296606 00000 n +0000297089 00000 n +0000297348 00000 n +0000303481 00000 n +0000305419 00000 n +0000309931 00000 n +0000310465 00000 n +0000310531 00000 n +0000310562 00000 n +0000310866 00000 n +0000310943 00000 n +0000315947 00000 n +0000316208 00000 n +0000322334 00000 n +0000322802 00000 n +0000323024 00000 n +0000323279 00000 n +0000346304 00000 n +0000346762 00000 n +0000347643 00000 n +0000348846 00000 n +0000349414 00000 n +0000350537 00000 n +0000351031 00000 n +0000351241 00000 n +0000351338 00000 n +0000351499 00000 n +0000351531 00000 n +0000351923 00000 n +0000352191 00000 n +0000360419 00000 n +0000359992 00000 n +0000359565 00000 n +0000359138 00000 n +0000358710 00000 n +0000358283 00000 n +0000357535 00000 n +0000357590 00000 n +0000357884 00000 n +0000357962 00000 n +0000358111 00000 n +0000358208 00000 n +0000358338 00000 n +0000358632 00000 n +0000358765 00000 n +0000359060 00000 n +0000359193 00000 n +0000359487 00000 n +0000359620 00000 n +0000359914 00000 n +0000360047 00000 n +0000360341 00000 n +0000360474 00000 n +0000360767 00000 n +0000360870 00000 n +trailer <<296329B56FA44223B652AFFD8184DC92>]>> startxref 361077 %%EOF \ No newline at end of file diff --git a/docs/images/airrflow_workflow_overview.pdf b/docs/images/airrflow_workflow_overview.pdf index b081f97c..58e69bd1 100644 Binary files a/docs/images/airrflow_workflow_overview.pdf and b/docs/images/airrflow_workflow_overview.pdf differ diff --git a/docs/images/airrflow_workflow_overview.png b/docs/images/airrflow_workflow_overview.png index d930c4d2..beccef1c 100644 Binary files a/docs/images/airrflow_workflow_overview.png and b/docs/images/airrflow_workflow_overview.png differ diff --git a/docs/images/metro-map-airrflow.ai b/docs/images/metro-map-airrflow.ai new file mode 100644 index 00000000..0ca76908 --- /dev/null +++ b/docs/images/metro-map-airrflow.ai @@ -0,0 +1,3615 @@ +%PDF-1.6 % +1 0 obj <>/OCGs[26 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + Adobe Illustrator 29.1 (Macintosh) + 2024-12-10T08:22:32-05:00 + 2024-12-10T08:22:32-05:00 + 2024-12-10T08:22:32-05:00 + + + + 256 + 84 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAVAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A7tb6f5vOp6lOq20tuYFb SRNyANxxk5i4IqSjPw+z2rtXNLp9NMzEiO+7ciUxSUh/zyOjwk6P5ZGrOkv1j99crFG9AIQi8JC+ +71Ye1e+28GHcPk0cRVNSufzqjvWj0/y75duLQvKIriS7nQ8FJ9JnT0di602Umh74+DDuHyXiK5J vzo9K5L6B5bEqqPqireXRVmLjkHY2ykAJU9OuPgw7h8l4i0ZPzscyAaH5Zg+FfSJu7uf4qoG5f6P DsFLNt4U78sfBh3D5LxFmejQ3cuk2kur2dvbanJEjXlvBSSOOUirIrkDkFO1e+Pgw7h8l4irXtpW 1l+qxRi44n0iVWlfpFMBwwrkPkiUpVsd3n50r83YNW+sTappjaJ6rFoHsokmWJmqq+t6vEsBRK8R 4+2Q8EfzR9jRxZa/sTvzTpnni40uOLy5PaWV/JGge7mgjnVGr+8YRkoGPH7O9K4fBHcPkGRlk2Y7 onlz86LXUI7jWdfsb6yBPrWsen20FRwKrxkDMy/GQxrXpQUwHCP5o+xBnk6fem3mjQfzEudVWTRd TsbDTQkYaN7USu0occ/iaRAFZaqBxrXevbE4Y9wWRyX+1D+WNA/NWDUGbzDqGm3dmJF9Nba1MLFK fFz5Sy9z0HYdd9nwI9w+xf3ljc/Nvzh5e/NK8uuflnWLbSo1LKY5bK1uY2U1ow58XDCo/ap7YfBH 80fYniyWi/Juk/mHausHmi4tNRjSn+mpFDE8lQS3KKNFCcTQLRmr1Phj4Mb+kfIKJZL8mW0b6x9V DH06epWprx6cQevXIb8XBe3P4dzkdLYV+Zuk+aIoP0zpHm+38q6TYwltR+sWFtdx7E/vS8qs4+0A R7D3rd4MO4fJjxF5/bfmPJMdMsYPzN0ae5aJ0nuU0N5luZ4KzS8JI3WOPjBNECOPYnxGPgw7h8l4 ijdB81axrOqWWn6d+Z+g3t1ctSG3j0Ycpq1dgD6yjYRvwp2G/I7h8GHcPkvEWe+ZfLXmm5sdCS21 NYbqyntJdXuYIvTS6EW1wgi5ERrOT4tx+dDmv1eAg2I3Gq9x722EmY2qSpbxrKayBQGPXfNhhjIQ Alzapc1XLEOxVBayLs6bN9UIEwFQTWm3jTenjmLrBLwzw/gM8dXuw22g/Mm38mxFV0qfzUCiyfXv WSybduZQLSRajj8t+vQ0aTDz4h6enEnJKuq+zuvzMbkbvTPL0YC23BI7mZizMU+s1JiHHh8fDry2 rTMzwodwa+PzQUt7+dCemBoflnk0fOQveXCoG5MOKH0SzfCoNSo607E4+FDuHyXj83oAXTzQARBj /KQDX2IocfCh3BePza5Sl/q/M/a3k/a4cQaV8d6VyuzfBfXn5M/N5PrXnj8zPLTxReZrfypYrN6r xXsl9exq8ayxxqREYZGBUzIrVfctUeGW+DHuY8RSeD88tSis7SbUr3ynbyXlmLqKN7u+hYmYP6B4 yQEiNqLyJ3WpBG274Me5eIo3y3+annHX9dk0TTz5UudTSOdvqkF5es6vb0HFw8MbDkzUPw/BxNa1 Ax8GPcvEWZ31v5//AMX6YYPQXQ/q0h1BAztKLk8eHpMRT01Na1pmrzY5iZA4uK/T3U3RIpV84+fN S8rJaiDy7c6xbzQvIbi3uLWFY2jYclcTyRtThVuS18O+bTD9IaZc0Kv5iedGuXMXkDULnSySbTUb a902VZ4iT6cqIZ1PGRAGG/f77EMz0bUJdR0u2vprKfTpZ05SWN0FE0TdCrhGda/JjiqMxV5GfNem XesQWdn5o0t9YOrN9RdLu0YGKe6fjCFWPm7tb8o+PqmrDxFMVd5A85+WrnzBpMMfmfSp759PFleW 8N9Zu086GMwpFFEkRYqxlK0LbE+OKs083+ab6zYaJ5dt11DzVdxlre25JwtY3DKt5dhnjpArr0B5 PQhakGiryTz55d1QatbeVLvzTHPayV1zVvrHKWKOf1DLPe3sc8xENnbiMCztYm4tJ/ecgCSRE9zI RJ6Ij8pj5ju/N5vJb2b/AAx5eilk/eX001qqX8TTgvKiRW9xclXR2VGaCCOgUc2qoYorzv8AmRBr 1yEtXWfyvblJYoVl9GLUByX/AEq/nKslvpSMsiF2/vXVlFQKMqlNhd+cvNWt6Hb2WsPfCcjWp7Zi v1fl6apDqFwAwkhtFqrWlmE5SupZ2/bCr3Ly3o/6C0K3sZrua8lhUvdXt1K8rySuS8rlnJ4qWJIU UVRsABirBT+dLarrsmkeUNIbWGcFLC9kaSC2nkSaOOaUOIpCLWFXblPTizcVj5ltlWZeTvL13omk +nqF9LqGrXcj3Wp3LySvEbmZi8gt45GYQwqTxjRaUUCu9TiqE89Xel2umzvqlzNZ2Mv1S3lure5m spI/rF7FCrfWYCskahpByYEDjWpArmN/lv8AN/Sz/h+LzG8u/JlxZ6vcWHmK8dtHMoktbnzNq3pX KxksBbyG4j51RdyVccjxBIAJyWDMdQ/Mry7ZaPftZpDb3FjbLNFaa4ZNPlujV0kCG5USSELB/eKH DkgV74qzi2t9MvIrK/FogdEEto0sSiWH1UoeNRVG4niafLFURc/3J+a/8SGV5fp/HemPNVyxDsVd iqldf7yzf6jfqOV5voPuKY82Ifmm+kJ5duTqkF3c2rW86TW9iGaZ43Ti6xhfi5kHbjvjPo42arDy 3ypd+R59dja0s/NEFzMCYm1D6/8AVOnqEVkLwrx4CnKg3oK1OQLTKq/sZP8AmkPKUmlWNvrdtqtx YzCPawW5eRSqOQW+rfveFNttq4U7WK7mK+Wbj8v4fMllNZ2XmV9QmIhEt6mpPFCJeTHmbkmJNzx2 6H6cSg/jk9/X/e37/wDiK5Af3n47g7Dop6zqWi6XYyahrNxBaWUA/eXNyypGoYjqzbbmmZLFVay0 52S4eCFmjSiTFFJVKh6BqbCorira2GnG4jvFt4TcIrLFcBF5qkhDOFelQGKgmnXFV7f71R/6j/rT Kz9Y9x/Qnow3zna2Ny9kJ3k9aDT7+59CG/m05nt4XtjPV4mVWXdFPqDiOVeS44fpCy5oC98++W/J Hkyysbe+TUL+30+xfTRdzOgulu2MMEjT8ZNmZGZjQmmWEoT3yb5pju9Ht49V1azv9aVWe8lskkjg +JyVEavU0VSq1J3pXauUfmcfe2jDM70nNzr+i2yq1xeRxI7BFdzReR6VJ2HTvj+Zx/zgvgT7mNX/ AOYf5ZQ2t88Gv6Sk2nfvH4zwirJS44qQfj5d+FdzTrlwN8mpOYdU0SK1g+qzW97cOoMckbIVYt8R dpByCKT8VT9FTmJl12KOwkDL3/eejfHAecvTH8cu9LdI0i4s77Wb+TVNPW71e4SUzwwn1VhjiSNI WkknfkqMHK0AFWJABJycNZjA3lDi9+33/pWJgDyJ+P7E1jSCOvC7sAWXg7elVmXrRmM1T175XLV2 bOTH+P8APWU4k2RL5/8AHUm8z+Xl1fQp9Ig1DTora5aD1raSJ/q7RxTI7qUiuIm+JEK0DAHvXLBr IkerJA/j+sVnOJFUb9/7EruPJlxcX9xPPf6LJBd6pDeXKNays72trCFt4GY3W/pyDkF2TcnjuwaH 5qH+qQ5fb/pvs+1h6e4/Pp8vx3Jt5Pt7Ty/FdxajJYjUtSupry7v7MOkM7yOeHL1HlZCkfFApbjQ fD4ZEa/HxcMpR8je37GYwGQuO/l1/amK+adG1eycaJeWl+kvqRG4LiS1UoxjcOQfjowI4A7+3XJZ tZGMuEGPF5mgEQxbcUth9pSDyNouk+UILiTU5rJtU1ArJe6vbqkUJWJFjjt1UAehDBGirGtePU9S ciNfjE+EmO/Ig38+77kjDxRuO56j9Xemy/ml+WxVG/xRpYDrE68ryFTxnNI9iwO/4d8zmhTn84+R L9ZZ/wDEOn/USv1f64t3AFS4R+YCyFuPqLTmv35jf5b/ADf0s/4fi858vfm7oS6aLHVIZdXu/wB9 Hql0dS0iJpGWaWILLG1zaJKjQxoUI5qValTQ5ksGYjztNrFst7Z+UL7VLO4VopJrO802aMqqhvRn 9K7Kvu7oV+JQe9GrirOpL23hEfrt6UkoqsR3fpUii8q070xVgNt+a1hfa3b6ZE8bifVbzR5IePCe OW0aQpJx5u5Qi3NWZFXcUavwmvL9P470x5vRcsQ7FXYqpXX+8s3+o36jleb6D7imPNUeNHFHUMB2 IrliCFGeKOOCSSK2WaRFZkhAVS7AVCgtQCvTfBSOEMSbzZ5uJVpPy+1Fkq6gLd6Q0ihVQqSrXirR izDZ6jj03GGloIg63r1wPq/+ENTsWnRgL1JdHY27GOoYhrqQc1c0HwOtRvtgpeEIbyV5qtJ/LOi3 2tarF+kLqxt7m9e6kt4n9S4hVzyWL00UVJCgDoPGuY4/vPx3Bs6MG8y3l55n/MNLdvMumWul6Ysk 2mXlvIk0NrUwgPKJZPQmv+SP6SMhWFfj+IkDMlgyDzbrVh5uvrjyq2saba+VP9GXVL2O9hkubx2l DNp6RRSK8SyDgJHavJWKBfiqqrKb3W7Dy3bS2en6fENM0W2hkube1Kw/V7ZiwqkXBYgsccbOQXX4 RtU4qyBv96o/9R/1plZ+se4/oT0eUfmtcaU2q6VbXfmHy9pV0lnO9paa/YC8L+ow5ujvLGkaH0V5 HiT8OOH6QsuaL8i+YmbU9J06fzj5c1SK6iRLLTtNsWguZY4bZpolVjdTcVjT97T09vbkMsQzjzRr GkaFpk2sajeLYRwinrmhLtQlYghp6jNT4VG9emUZMHEeKJ4Zd/6+9NsV0fzbqMnlLQruRjrvmTVo i9lbukdtECDV7i5EBuBbxRKRzf4itQvHm3DHwLlxSN1yHQftW0r8rXHmTzDBLa6TqvqQXU8V15g8 22zR3Fq8wRDJZaSsqujxKiRxGRkpQt/uyoF6Hq+KuxV2KuxVK7/zPoNhrem6FdXkcer6v6v6Psus kggjMkjADoqqp3OKoXzhYeZ9R00adoV1BYfXCYb6/k9T14IHFGe1WMr++pXgWYBTQ79MVTLRtJtN I0q10y05m3tI1ijaVjJIQo+07tuzHqTirzv8zvzNuLSC60Xywq3Wo1a1vrlJAGt5HWOiQVosk4Sb 1GBZViQF5GUUDKvOrC681an5jj0fSNQcXb3EK2aJbTy2Qt7GJ5LLlOzoRZW7Vb1yC15JUBQoVyq9 z8o+Xn0C2h0+a8fULwxyXF9fyDiZ7meYyzSBKsI1aRjxQGijbMb/AC3+b+ln/D8UBP5I80PqE11D 551aGCX1CtoIdNeOMyEleJa1LUjr8IYntWu9clgwvVtDm8u/mObxvNUln9ftZb+91KdbWJ0gs4pz LE0MMUMFwvGRH9SZGdBHs2+xra0XvSQeWfzR1nVtYul0bUdR1e/lhgI0y2k8uTzUX1TPKjJcfYRg q8duoYDfAl6d5Vn1UMmmalo+pxTWcfqS65dvbra3E5dQ/CGG5lYO/qM28YGxNela8v0/jvTHmzbL EOxV2KqV1/vLN/qN+o5Xm+g+4pjzVcsQkOv+SdF125FzfSXqSBY4yLS9urRWSJnYK628kasCZTyr 9ravQUVYf5h/Jy9vNZkv9G8w3enwzAyzQz3WqzsbqjASIY9QtkRKFQU4dBsV2IVSm68m+Y/KOoJq 36fa9JaeHRdGjl1R7m5uJYp/Qi5XOoXUMrJJLzd5YWCotTQLUKso/Kvy9o9l5D8tW8VlAofTLWWa kUY5yy26SSO1FFWZ3LE9STU75jD+8/HcGfRla6H5dtBNKun2duJW9W4kEMScnIC83NBU0AFTmS1k 0laT/lvMX9OXR3MzLNIUa2q7RkBHJU1JUxgA+2CwjjHeo615E8j+bLptTvLWz1GSSIW0k5t7O65R ozMF9SWKZloXP2WGG0gg8mTN/vVH/qP+tMrP1j3H9DLo84/M/wAv6XqkdokmuHQNSubOeKG6e5WC J4YpYpGi4Sh4ubOU+PiSBXHD9IWXNHflx+lXs01ma8vNVttQtIWht5EswlvIjyrIsMqJbO6mgpyr tQ7VplwiK5sDI3yTHzb5P0rzSqHULG+iuIo3ihuraeKOREl2kCfvWQM6VTnx5AMeJB3w8I7x9v6l 4j3fd+tW0nyn5a0i4muNP8tiCaeEWjvxt2YWwAAt1LSkrD8I/dj4fbHhHePt/UvEe77v1r9dvL/T PLrQaJpdzbSr6VtZi1gt7gQ+pIsYf0BNGCicqtvsN+2AxHf96iR7lby3Y3ei6RFYOt9qM6s8txe3 L25klmmcySvRZAqBnckIoCqNhth4R3j7f1LxHu+79aafXbn/AJYJ/wDgoP8AqrjwjvH2/qXiPd93 63fXbn/lgn/4KD/qrjwjvH2/qXiPd9362mvLoqQtjOGI2NYDQ/L1ceEd4+39S8R7vu/WwD8u/Lfm Cw1zV/MeqvfX1zqIFqYr63toZ42tZpQ0kLi7m4W8vOscSBV40b4mLMwER3qZHuegfXbn/lgn/wCC g/6q4eEd4+39S8R7vu/WsluJpYnik0+cpIpVxyhFQRQ7iWuPCO8fb+peI933frYnpv5b+VdPvLy6 TRJ52u4GtPTuGt5o44HCGVFR5GVjLJH6kjycndj8TEUAeEd4+39S8R7vu/WmHk3yxY+U9LNhp1le zGRhJcXVxLA8sjBQi1pIqIqooVUjVUUdFGPCO8fb+peI933frTf61P8AX+f1Obl6VPTrDypy6/3n Gn05jcI8bn/D597PiPDy6q5vLw7JYS8j0LvCF+kq7n7hmTwjv+9r4j3MG1ePV1/MDTpLW3trnUZL TUgsk7skUUsdvA0SCiOxRmlVXIptU+2QMrO3IMgKG/VMrW4/MyOxofL+iw6oY3USRX0xtgyg8OX+ ipJxZqbAGg+VCpZNE95JpcEl9EkF68cTXUEbmRElPEuiyFULqrVAbiK+GV5fp/HemPNGZYh2KuxV Suv95Zv9Rv1HK830H3FMearliFC/tWu7G4tVnktWnieJbmAhZYy6lecZIYBlrVajrirG5fJmvvpk NonnLVoriOnq3ypp5lkFWNCGtWRftD7KjoPfFUnvdPufLnmryxqes6pc6ppsMN/p8mp3iwD0bq/l t2tmlMMcSorLE0IegoSor8ZxVN/y2DL5J8rqzc2GkWIZ+nI/VIt/pzGH95+O4M+ie68qNpM4eIzL QfAux6jf6MvnyaMv0l89NomhyNEZvyfmeRok5FTprcTx4+lyd0+FFUAdu1Blfxce/P7/ANT2X8rb eCDyvFHFoR8uhWYfowmNhF8R2Bh/d7/a+HxycG7D1ZU3+9Uf+o/60wH6x7j+hv6MB/MHzvpPl+fS 7S+niha6tLySNzqVtpkqyRmJYiHuZbdXVmY1HI9K8Wps4fpCy5o/yT+ZfkzV9K0W1TW9LOt3lvEs ml2l3BOy3PorJNFGI2PP0yTUgZYhmmKvMNd/PfRdG8zaloV3bQRNp0yQtdzajZRRt6sBkjJRpPVT 94vpspWoqG6cuKrJZ/PWharpV3J5Y1izv57aSFJZreZZI4w8yI9ZES4UEK38rU6kUxVS8n655muP 0uuqQreRW17HFYXNvJG4eKWGORl2SEfuS9GYgcjXoMBNJAZK99Kil3tJVVd2YtCAB8zJg4j3LSWe XPNS6/po1K0066SyldhaTSG3pPED8E8fGVqxyDdSe2N+S0mn1uf/AJYpvvh/6qY8R7lpj/lr8w9K 8wXuoWVlA/1ixldBH6tqzSxRt6ZuEVZifT9TkgbxGN+S0ns2oNDC801rLHFEpeSRmhCqqipJJk2A GPEe5aQHl3zQNd0qLVLbTbuK1nZ/q5m9AGSNXKpKvGVvgkA5Ie4OJPktLPMfm+20GzSe6sriWedj HZWUJgM9xKFL+lChlXk/FSafdvQYg+S0mi3k5UH6lOKitCYaj/kpjxHuWkO91Ot/zFnMzelT0wYe VOX2t5AtPpzG4j43L+H9LOvSq/XL5xxjsJEc9GmeIIPn6byN9wzI4j3MaHe8x8zRvDr2reY57u4j ufKdzpsFiyKTETfSRPfExRlmkE8U6wkEfCqKV33yURSCWa335gaTZpctLYas5tZZIHSHS72ZmaNy lY/TibmjceSutVI74UJ2l3FeaelzCHWOTiVEsbxOPip8SSBXX6RleX6fx3pjzReWIdirsVWyIHjZ D0YEH6dsjKNgjvUFTS44gLMCrjqQpKn3BAysZK2lzZV3N/WYfE/8C39Ml4sfxaOEu+sw+J/4Fv6Y +LH8WvCULqltpmqabd6bfRG4sr2F7e5gKseccqlWXYdwcHix/AK8KS/l7aTWvkPy0DIty8OmWSGS OvGRVtY05pzCn4uPIVAyHDL6q37vL9bKxyTvUaXVlJAkrQu4ADcGBG9fDvkjlBHX5FrnAkU8wu/y e16f1uHn7W4RIwZArRgRjkGIWkIbxG5OR4x+AWoYZeT0bQrRtNtDBNdPctUUZlYnYAV6VqclHIB/ YWePEYjdMU5STerxKoqlVqKE8iCTTt0wxuUr6Np5Ka2lrcWqrcQxzKyFGWRQwKt1BqDscOH6QiXN XSCCMkxxqhJJJVQKk9TtliF+KsD1v8rbrUvMUmuQebNXsJWZnhs4vqclvCZIlhb00mt5CKqtdyd8 VVPNcN5oH5ftDNfXt/eJPbrJqVtYrdXki/WkYsba3iMbsIhxr6fHuR2xVIPy98+2enaRqv19tc1C IX7y2fqaDeW8qRSqi+iIoIODH6wktSgABPxccVeh+Y/Llh5gsF0/UGl+peqks8ET8FmVN/SlpuYy aEgEVpiqZQwwwxJDCixRRgLHGgCqqjYAAbADFWPfmF5d1vzF5VvdJ0bVX0e9uEZVuo9iaqQELirI rNTkVHKmwp1xV3kvyHoPlKzkSwi9W/uuJ1HVJQDc3LIOKepJ14ovwolaKPepKqv5l8rtr72sVxqN xbaZCxe6sbbin1rpRJZCGPp07JRq0IYUxVOJEeO2ZLVEEiIRAjfDGCB8IPEGi/IYqxzyt5SvLWca 55juY9T81yxNDNeQo0VvBC8nqfVraJmfiikD4mJdiNzSiqqyfFUL/wBLP/nh/wAb5jf5b/N/Sz/h +KKzJYPMPMlzcp/jlbWJZLpNR0Vo0mf00cOLRftAOR9kj7PXFWWXV7+YSvN9V0nTHRZZFg9S/mUy Qgt6TvS1Pps1F5gcuNTQtSjKt6Pded5jcDzFpunWUA4m2ewvZrtieQqrrLbWoFP5gTXwGV5fp/He mPNOo4kmHqyjnyJ4q24ArtQZCEBP1S3STXJi/wCZh1O38tH9DNbWU8k0Ylv5bmOyMCITJyR3tr5X Z2QR8DE1Qx2wyx4xzAZQEpGhZYH5R1Xz1ceVLxbvUdPv5NQQXek6yL5RMokeLjFwXSrZEURc2q0b Et8NADURIxDoPkzGHIRYBTD8p9Q8z6pr1zcarq9pqWmvHcqlrFdwT8Jo7hUrHCNL06bgnCROTSsP Y7HCIYyaqNsTCYHEbplPnjzzp3lKa3S50kXMVzFJKkwutMtAPRK+oKX1zak8VcMStQO9Mn4MO4fJ r4inL6tp0Hl2HW7qyaOOSGGV7aNEuJFafiAlYS6PRnoWVivetN8fBh3D5LxFA+W/OvlXzDOtvYQX Edwyyv6dzYz29BDJ6bcmkjVFY15KrHkV3A64+DDuHyXiLI/qlr/vlP8AgRj4MO4fJeIpF+X00svk zQWlbk0ml2MxIAUAyQKSAFAAFRsBghsTHoksiy1i7FXYq7FVBGaEem6sUBPB1BbYnoQKmoymJMNi NmR3XfWY/B/+Rb/0yXijz+R/Ujhd9Zj8H/5Fv/THxR5/I/qXhd9Zj8H/AORb/wBMfFHn8j+peFIf NFt5tvXt/wDD2sR6RGsVwl0J7BrtnkcL9XkQlownpMrVBBDA022IfFHn8j+peFIp9I/N5b57i283 ae1u1QtnPokpRRUEHmlykhbqOtPbHxR5/I/qXhZe8moPZW6iUR3g4G6dIZCjEL8YQMpIBbpmPqJT kB4Z4Te/pPL5JASG1tPzHivrtp9dsJ7B5HNnE2lXAmjjaXkivItwquViqlQg33zI8UefyP6kcKYW 0XmZNGtYLrUo59XSQteX0Nm8EUkZZiFWFjccKKVH2zWle9Mx9RKcgPDJib/mnl8m7DwAnjFiu/qk yaX+aCXNzL/imzkie4Z7W3k0eQrHblnpG7JOjO3ErRhxoRuGzI8UefyP6mnhTbRx5pXS7tNU1S3v dRecm2ubOyltoY4lCKYzG8l0S3NXJJfvTtk8eaAPqBI9xZ4wBL1bhLtR078x5NZNxp/mS1ttJ9SB xp82kyTS8ERFmT6ws0W0jBmH7uor1yJyxvYH5H9TEjfZDrY/m5SDl5j0omPks4Gj3Q9VedQ4P1r9 23AUpRhUnrtg8UefyP6kcKa+Wo/O9tdXH+ItTs9TtWWtsbOwns5FcsSVbnNcKyhdgdj44+KPP5H9 S8KeIrm9ErjiWjYBe4VWWlfffKog+JxHqD+hkeSKJAFTsB1OZLB4h5487/lzceadC8xWeqafqenV eLV4o9Us7VJZrB459P8AUS4kj9U2807OOJ+EmrbUGKs18vfmdN5ktZLvQNFOqW0T+lLLaahp0qq9 A3Fis5oaMDiqZTeYvNDRkN5UukGx5G6sSKg1A2mPU7ZXl+n8d6Y83Q6hr83NZ3j0WFVIt1ki+ss/ /FjSK4iH+oKnuTkcWPIYiiK+1t8TFHmCT8h+n8dFOGwnF8L6616O7ukBWAyWyhIQevpIHAUnu27e 9MI02S7Js+5sOsxcPCI0Pfz9+yP+s3n/AFeYf+kf/m/LPByd/wBjT42Lu+39iSa9PbolqureYYke 4u44NNmjtGEsdxJXgEdGbjUChLfDTY7ZVLTTPM/Y3Y9Xjj9Mffvz+xj1z+VdtcX9vdv5w1GiySPe xi81NBcJIrDgeF8ix0duXwKOlKUyyOHIBub+DVPPiJ2jXxTeDyB5ajs7yymvV1Cx1D0zd2eptdaj AxibmhEV5cTop5b1UAk9cPg5O/7EeNi7vt/Ylvl38vdC8syQz6Ta6TqOsWk8stp6Olx2soSQMqIJ oiwjZYmCGVgeXVtzhOHJz2+P4/QiOXFyIPw/V+0Ml1O+/MDVrOTT9O0caHJcq0UmrXd1DI1srggy wQ25m9SVeqqzItep7YsGQ6Tp1tpltBptqCLWytYLaAMakRxBkWp+S5WPrPuH6U9EdliHYq7FXYq7 FXYq7FWN+cvMt9occU9vHFLGkTz3Ecgbk6pPbw8EYMOBP1gnkVbp0yrJMxcXU5zj3H43A/SraPqG scT9Zim1EXF7dxi4hW3ijtYoJjCquHlSRgeBYFVdux7VlEn7WWKUq339R+G9MFk/NfzBH5ftNT5a a13cpd3MunKkheK7tkt3i8ssfW5fpWb6w6hioasbUtm7TchQ84/m75r0O2tNTt7Syk0+/wBZ1DS4 UuPTto4V0l7uF457+5vLaFZL2W1DRP6YES8xxmYKGVZ9od/qWsajrl5FcenpEMh0zSlCq1Z7NpEv brcK/wDvSxt/TcUHoc1JWTFXldp+ZfnzTNV1g6tcpqtv5RVra+jtDaxLdT3DSCGW4duAiVeAWkY5 cqLxNTmWccDVfxfY0CUhd9HflR+YiyWl/pGrXc82p6iWvXv7fjLMpKcZKnk+37scQq/AW47bZDVQ j/D3NcZHhN/Y9W8jx2cegRiyknksy7NA9wCCVIB+AsAxWvc965g4OLh9XNvx1WxJHmn+XNjsVdiq hM/CYPQtxikPFdyaFTQZVL6x7j+hN7PPbn88NHttVbTJtH1T11lEPqpZ3MkJrsHEscTJwrtWuHjc bx9rr7U88j+dNJ82xXMtppVxZR2ztH/pts9uzEBasqSojcTy607HwyQlbZDJZplcUMMS8YkWNTuQ oAFaU7fLJNiy5/uT81/4kMry/T+O9MebrX/edPljh+kLLmq5Yh2KsOb8qvLTXFzP9b1hGumZnEer 6lGql3EjemEnXhyZR9n6Niaqpjp3lG30PTdSh0GaeO7vEcwS3lxLdCOXi3pkGcytxDvypv8AwyMw aNc2eMxEhxbxvf3IOHR/zGNzYSS+YbVLaKO3Go24shI8ssdyXnKTcogiy25EdPT+EjkO4IxiQiOL cssxgZkwFR6IjWNN8+XEco0nWbTT5RdCSF57T62htgkgMLxh7dqlmQ8g/b3y6ZjQrn1ceIlZtCWG lfmkqacL/wAwaW7JOJNU9HTZVMkPNWMELNckJsGQOVO1GpXIM2VL/vVJ/qJ+t8rH1n3D9KeirliH Yq7FXYq7FXYq7FXnv5pfmLqPlPWPK9hYLDLLrd2sMltNCrmWL63aW7iKU3VsyShbyqqkE5bqVVVZ sVYlrv5u+dtF0TzXq0ZsruDy0LmQQXNu/qzNca9qel2iiWKWJEjtksomYekzSCo5KTzCqB178x/z LsPzOudKj1Fbqw03VtD0uTSbO0t4vrZvtLnvJ/TkuXdojLNDxUNN8Ip8exJVbsPzw/MuXy3Dqo0e y1E3l1aaXp8tnC6Qy6hqmmCeCJjJeH01stRItblnYBufw8HjZWVes/l/5guvMXltNblREtb65u30 oJBLbF9PW5kSzmZJiXJngVJuXFQQ2yjFXzf+aOhaRF51826kl0LfULe+tltdMSL1HuZLpTK78yw9 NUEbMx4kGoFRXNnppEcHCLJ/QXDygeq0J5d0m21q6sbC/vm0wXcz2a3iwC5C3FyqrbCVARRWKOql W+FiKmmZOvJiAaG/Nx9OATT6w0TSLbR9JttNtizQ2ycQ7mruxPJ3Y/zOxLHNJKRJsuzjEAUEdgS7 FXYqoXPIOpDcCyvGr9eLNQqf+FyqZqQPvH3JqwXnV75V/O0Xcklh5o002zSlo7e5t7gsIzJUL6kc i/Zj23U1YV2rQS4S44xy7/tZH5W0bzvZtqB17WYb/wBdVFisETxiEiNQxPNnJrIGb6cQCyjCQ6sY 1Lyj+d02qXUmn+bbC000n/Q4HtpZpFBRa+o/JK0etKf2YiJYjHKuf2sk8s6X5r0fRVi8yauNb1BU /eXKoI/UYOX5CMAKnFNtuuUaiXDEltwwlxbnZC6R+ZemXVpr0kEFxd/4bkmgvLe1haSdpYI1kZIk B/eEq4pTvlGk1EyRGQ5iw3ziOYQEX516a8Qnbyv5kjtTai7Wc6Y7jiZWi4ERs5Enw8uPXia5sWpN 9B/M7RNZ12LRI9P1ayvpopJ4v0hp9xaRtHEFLEPKqj/dg26g7GhxVl2KvPvMWs/nBDrEkehaPp9z pfw8ZLmaWOUEMeYASKRWqtOO4365Cy0cUkR5Q1b81bnVnTzNpNhZ6cY/3RtZpZXEgJ+2zxRDiRSl B44glMZStK9X8wfnlBe3p03y9pt5Yo3+hh7qWGZlC1IYejIhJPT4h9PXBZYiUvwGQeT9S/MK6v7h fM2nWlnaCOM2xtpJJG9Qj96HLpEKBqcaDcdaYQSyhKRO7KIyGuJWG4AVCf8AKBYkf8NkYm5k+4fe 3nkq5ah2KuxV2KuxV2KuxV2KuxV2KuxV2KpN5j/wb9Ql/wAS/o79H+onrfpL0PR9Tj8HL1vh5cel d6YRfRBrqx3yj/ypX9KRf4X/AEJ+ld/q31X0PrH2W5+l+39mvLh265KXFW90gcPRneQZOxV2KuxV qThwPqU4U+Ll0p71yMqrfkoQw+q0+H1ePbj6tPoptlHo6cX+yZ7u/wBH/wCL/wDktj6f6X+zXfy+ x3+j/wDF/wDyWx9P9L/Zrv5fYqRfVatx+3T4udeVPflvTJw4OnPz5/ag2g7X9B85fqnDnyPq+hXl y2rXhvlEPAv08/K/0MjxdUR/o/8Axf8A8lss9P8AS/2aN/L7Hf6P/wAX/wDJbH0/0v8AZrv5fY7/ AEf/AIv/AOS2Pp/pf7Nd/L7Hf6P/AMX/APJbH0/0v9mu/l9jv9H/AOL/APktj6f6X+zXfy+x3+j/ APF//JbH0/0v9mu/l9jv9G7+tTvX1qfTXH0f0v8AZLv+KREXpemvpU9Onw8elPamXwqvTyYldkkO xV2KuxV//9k= + + + + 1 + True + False + + 1042.289885 + 343.045198 + Millimeters + + + + + MavenPro-Regular + Maven Pro + Regular + TrueType + Version 2.102 + False + MavenPro-Regular.ttf + + + MavenPro-Bold + Maven Pro + Bold + TrueType + Version 2.102 + False + MavenPro-Bold.ttf + + + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + R=203 G=219 B=44 + RGB + PROCESS + 203 + 219 + 44 + + + R=255 G=153 B=20 1 + RGB + PROCESS + 255 + 153 + 20 + + + R=126 G=178 B=221 1 + RGB + PROCESS + 126 + 178 + 221 + + + R=255 G=153 B=255 1 + RGB + PROCESS + 255 + 153 + 255 + + + R=36 G=175 B=99 1 + RGB + PROCESS + 36 + 175 + 99 + + + R=212 G=71 B=21 + RGB + PROCESS + 212 + 71 + 21 + + + R=191 G=166 B=121 + RGB + PROCESS + 191 + 166 + 121 + + + + + + + application/pdf + + + metro-map-airrflow-scfastq + + + AIRobin + Document + xmp.did:332df25d-484e-41e5-8e83-14e36ee848f7 + uuid:b1852339-693f-5f4e-8133-ec64f15280c4 + xmp.did:9daff3f4-49ec-4ac4-8db6-2f537f662f45 + proof:pdf + + uuid:e94ca79a-c8ea-e24c-bd7a-fa9a2fd56a86 + xmp.did:1ad4a472-8dd1-4b75-9baf-dcd2a5fda51d + xmp.did:9daff3f4-49ec-4ac4-8db6-2f537f662f45 + proof:pdf + + + + + saved + xmp.iid:9daff3f4-49ec-4ac4-8db6-2f537f662f45 + 2022-09-30T16:01:10+02:00 + Adobe Illustrator 26.5 (Macintosh) + / + + + saved + xmp.iid:332df25d-484e-41e5-8e83-14e36ee848f7 + 2024-03-11T15:47:15-04:00 + Adobe Illustrator 28.3 (Macintosh) + / + + + + Adobe PDF library 17.00 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 5 0 obj <>/Font<>/ProcSet[/PDF/Text]/Properties<>/XObject<>>>/Thumb 146 0 R/TrimBox[0.0 0.0 2954.52 972.412]/Type/Page/PieceInfo<>>> endobj 28 0 obj <>stream +HWَ}_HTA Q|yX)v:@v7Y{:/ ftsCo#m~0ӛ128ˉ7J&6 D62|7}O?~phy9xd)ӏ7㍳eM2DPImduYr2pÿof +C![ 8XSQ l>> +cjxYyHN y(fyŏ1f A(&& pl V-.YQ֬|?ow?іP%86jL!S<q4տO72II0`3)Og|h&԰vmI0} jΎ|D:Fӧ>2{Oއ}wZ(xl<ϹU%}dfRp 3߂w;q8+˪"O:O:Bt+;\^}C˜ =WkO`R[+qpcK)売l1<$zzjJouOM{olR流뇛C2>* gub~oMY2kR}"+:K^O;yUY 7t?#! sy21qxl}XCl=7uft>bJZP L0S}ↈ%ۙ9T`>||>{!_MY:. ҽЋ.Y.{~N%_U Il@ҖQ)1dPވJxA +EOXoJbie_KV|,5d ]e*eқ'sUVkbn=S=$XC6bVG r#t/ܫc1ՆbR +r}oRn\\>!v=gaT|Nu9f#քd+jӺ;ZMz-4A}y}Ţ~*kbUvPd; XF`]w.AZZ۹&8Ar+'둷M97Z>>'v,eTvlv3r9 % GPOu[Ʈm$\vzP_*AY/_M9:RfAYM UL"[>a å/A-ټ/ۢqúB¶"GI?=rm2t0{.e˖4nX&]cCc)=g;~NV;ۻvrC;\]-12%d21Gwlh8&FWO `%'6E`4<@q\'8P +l} }//`R_0#B=h-bB*0k Sa^ӡi+JC9*qKӶ/װW2p7N@UjPC>?Z)5ْЪ}qϩ?; ~q+ 4Yr4"tډ.$ZE0'8a.*m""!3L h-+`rKH2Y%Kl|^Gۡi!mO(),Pp+/WTk45ON}.T4;u}gJ 66D( ,I9#ޝht}Ie. ,KЍc" Cj^²+Ίz%&un&E X9~Ck!B򉽩¡k գLZ:#g mg[oϗ, 7 d6vw),Ts^ϰ,!&F6Mֳbsf[>|ϳ-HIJnM#ql6)o%,QGQUGv. *,1>lʌbe`c*DGqha0a*u* + ؒ k.f}ʕr7ޞ7/ٴOaR]I5`q.0){_ HAxÄAGzؗxݫQg?)LOa҈0 9Y̢X;㋄ ZjK*E^!X,/_̧0Kl]Ky%ޯ<C?v( +.YJ33箈|D-.Q0O~H K%7!ZDƼ}eLx R2n5*Q Y(}Ѯh!)7hO.^k +2)ta\9zylG?㫘̈@$#ˌwc799׮{HVpY:I15%:)UӘ]^JNohJohvuU;wMϴǗ9%D/Ep͵g,je- =S8@` <ÜhKP[ս)!t=o^C jC˓7nq}bG)=qRC :,PzG,Uq(Љy), 3X%&:Ut*1l%L}$^o͹a m.6r.m?pkpwXtr:T̉3Sl#x)EcL'13$ŌkH"4FT +Jdmo~k?MޭMbS7W]6B~'5CHt KAt{I]hmHPm o"aa"!T)|.CDtҥ,)q MqKQ\( PDa+!W  +lӀJ )&9aBB;C"<bpA]`'+nwX+0>l + "DE.^(#DQ^R0} ^OFɆ IVGR#r>+#6.ZH"V1`* +J؊An(dpFDyV .dZUc7/q2|+4aӑ+|4Td ِMՕH*:X"1GaClPyCɪ`T4(^0p@ +gՌ(P+"H#-74kP얄*Mه|&K3rr"GCfF}#Ү]#DbmvbŬY?4czmeֿn-@_׾hLҿ~f6 o ~󛻷~|ݿ6Sn1 !yW~ÿSG}w4+Ĕo3@eZSJ, Q crFDkjH\:=l=A>bi4>o$H>A dIҜ<󣁇S# g*Kɠ^K/fa릖 ` `q(;]{>VZYe*Ѕ5ҪrK3nW߱=m(G_\67}|bYf>=IkG-H暾ǐɤ&mQMJ*a^IaYPB 틚!czW1"޼@Ρ/d%ұ5a ; cg,7‰IH3C&C!ց)N&T$ej4rdMzNz'ͳ] #>I+>I擅ɭ)"WhcH?~UE~.zDbB̘̘ۛn̾+hDQiü|녌=*\ ft߇nY6|Mҋt);KCڴt.P;A/JЊj%$̝vٺV ^,? =h +/,H;90I/qeBx4 ׂVP%z AocGIld)}s*Imvw4KbR|HRNG-_<ˠZA+ }gaǍa|Y%# oY +#>U0L&P`L/4:tvGE 6"8QMm75 + +;ze>7+W K栣 +o QH--8>bO$j x,D-/DB_Qw^_QW8? O3(k$)K^~w!7rcz̍cn,>ƇxF.zft#'EL.zƋ6uTҘ0,*^ƿveU㮢Yjժ.F|?qn/4]8cuHQ)EEas 3W6oXQxynGo,u{س R;Cd"ևg@W5c˷s`QjpYcT8ZSqlE2ʆ+|LsrB@4S2L Vb O$4MKC!^GQp&#rX+mC2֝Qbb M)$#ˇ`r9"VmQeM˩~6Gv+`䯵ze^Y۪wz%G;}Pݢ}줊ɰԷ \]&IؾPdF5MQBZ!cwWEY|K9&?NT6 ).h')j$HJiQBǦEVYgI};TrhfR6gke7z< al1zxNprএ6\e j%'2\T6n0"|Yb%b ֟?k~[~f#]zK_dۤh?~WzH$;[X,uJ)'56͏E'5~zXv_4oܞ`ܙʉ%&&3BL;%#DUx. SEMX ʻ|x\yx<~U^ ts,顕OZ]Mj'$7ԄKfsDНs kdvVs"ιλlnW`5n{9{w).PS'>( PTVw!=1RdI+OcB))W xxqG@IOހNj*y^~Y4W lZESTgf N=?;$ީqi3>EwDW/%%),oWiM򵄱5è^=.GsG`_׉b7 AGOw׻&ZpC#4wl^2i@SKVY,eʡ̘;J0 ǎ#M+iIR u3sb\,?Է?]]pW3aN;.:)\ "go9Z_i ZصłX9GإsվFr߇R5e?l -qGKKF]ʊFV(ȗx$1xVgf~fr+rm՛IkFWeY `3Irr>d:IQNQ/v,ӝEO_ 3X!mkʢh=hKx Brf xвFLI$eo5bH{ j؉{˯?H&4]\1 + FGRS웮5~'xjf4ʮ6Yن4LHp  KǑ[!+KŸEK8ewM,I]@7=Y3gPNEћMKhMQ`` +e$%*B)IPޔ*!v蝢 ~$A +R'l3s8B\b#[5h׽YC S p4 R"~R!(YSQW P!qbĈ2Jj +%`5_ԫ;t.`tu5dӭYˊ}[:KC.M.g:CVb3t z ̓ =GT "<+old-l&ObȖ+wat"*sS_ν1U@O3Voq}oPjm8D:1jTj%h[.2t*$27\#{*ux@ڽvMKo?~xwo5*h 3ڱI3еi/S{g E'%O}iTl!m,6{61+yP)^" R tfZk4_ʂi6%cVf=oi]Hr@u@+>v ͢7OFQ,Tz( ,a(utnNf` hd`-(U-u3~cjoc4 |[:ϊOVL32jN xY}RlA7:w$ݧkY6X!6./#BfEZfh4b. +s=` n/s!UI89}ǎ_Bcd1q WˊPic[JW-ݦi5 m_&U8f^bq l|]b]7WՋ7GoQMkA‘H +ET0vEc1N< =j{o'@OUzOpӥϻa#&UiŨ,tZA( ^ ޻^jL>!:,]ܳ%>w2>+s ǩNTށ~+D|J./B:icݐcYU-0-e/a5rg* n&.B[!XTbT+Pyғ4*)pjvf +}؇eC`i;@Z6lrkHLVu3rHٟsUuK*sOgl=X>\8+xrD)>^5! 3З۾ 7/[$ ^ \. xWfa`xqz +SQHbm=^t>b@lQdnuM4pQ~p}4/ofnYx}rn @_iץb Ltѝذ*}Q](ٻƷ5T1ud%"|0ˑ*JO^NZ`!,t w>FIrs'?Ƨ(nmobT9]BG}ک-abpuv5b񄊅KXL4Uh4Qod-+@aSăXZ50.hz'X]\3 뗨y0On90DTNqT +hGMTWIԌo*}jx,[QS3u$)lFԛ3Wp: X9BD.W.4?RP.j`%@$C #m0by<òIȽR.blP1,;IJi8ΦzfP[{̓VNfԋ'VT~U-rcqKoFB O hT/"ZVEZYgȩGVNʪW%D@G+dE,[9&PIAq|dQwpm"_xE V4'st/2CG/L^.䉊WV o|JP]7#LUqi[KҪkfX;NDµyjh0D>xȚS9(vzeB$oT粂,AhhaY(Òn7qb򭫞GɅ\,? Kz˗ښm{,z oJ 5S U go,&E_/r$#ZUhRؼ\ rSN]oHDZ.&Qecجc#?t 6rݮƋ~%̟ נ9ͱ2'h$_c l-d16vU0x/Dčn0?ձGr}|ULJ 1\,` 4K78Cx#^1~tG@x'͊4A#|^}U"sڑ@N^5گxHq pNS#H>kswLLfdeoIA )azlq-`i%͝3z`>sXv5:f%+/4Vjy\>p˽+A\g#޽d|xPlddIhhSϙ㇧L7p+ LWZ0v +\I ɆCdVO-V\< J-̧Dtbjߨo)yu6t(w4wRnn\ekV @X|= ;&Fx`1ym)tȚ<ֳ#'w? +&y;^;i$N"E]ʫZ=;}ܲV~fiƀSp ";p]2C]beE\ Ȗ.yƋLӣw$회;.Eԏ@9Le&9i=V4Lbcx-fX{8 LEЬn9^P'j<%b%a,h{pk&c Dm[097t%H"#uy zW(zQM-P 3+ڏ5׹cD?FQ(L;8axs1oi@"l1mɂN/-ϥ"Q< !,/TN*5PVEZ9f-_yk 5|vTFOn a%srxqexp4ҵj9lKs(6&ZZ(K)bShv1`S;wai"pst +1ř_&@fջ`AtJH͕ЭMPGZFyЭi ̉4sR sva$XΔM fB ? +i"0PEt{WߍTGCVA!lL= $ 9V|u׼]_ Q6qYޒM >Iur w¤;.?3 2X_xF!dq S2uښQh /q475$2(EK֡Tu +{3CN䫵geOPNLv޶8?aE o 4JQ=zT_s;bk JRqΧۢ^y137;LHS:73D }&Â~Q'tPHowTR\6_p{XGN_-2wWqPZ^0Ƥ84A>N ,RI޷ǹ"%W4LWeЏ+~5awTmTz҅Bµ0ZŭVtYUGjqUo]~tY* + AOףjH4_=co) >2mܧd4r~5HH;8ߋȘ!.b6v1Tҙ1ZݷJwtat DTWpw"/iC 5d$'N{Wδ27K}K2AV0' 97ZJO(;١ ljނQui$SlIU&^5999AsFKaH\+M 4]]ՖdVCZ '"Isvo_."JPskHm۳i0ECIF/>Kl/qϑd,Y@MhRzvu@kW!%R~BG%(da0Zkj"$f)xK!𫌜=1Hhرؓ1&m Xؠo0]L!˛bsqHY==|T>-~xp0E6 !,#nD{|3ԠZ3cK +x)}7cquQ2`v6-UqgР6jo>a0<c^Y&/t'eDvd#5\5 +GAaQu}Gڝ8k,Y:nlI/@/9r$u +hӋԶ}<2j4Qt҆?nM}1*=ο8H6oATnZZL~ j?rk ]c~~Se\)uYy;A([{ mukA/q3zY L6K@ip-l_WihnZL˴'MPSkQLz8.u  BxKeJ#Cuye7mԙ`DoGVqFhư>f*Skv^NRe|,+eZau}'nuDI2 m`8l mVmG.AAc>m) R5㏈ɼm;OOYsNk_"9hVҴ3#1MF;#O-q8𯹧40JO(҅K]`T1§%Lް3VecQzGve/Ib\o-ߨ"hרх*8WxDM/X$/g7F<'+?ЍRIBy#[x$*U͋[5}B 1Es<9k<66å~y폘!nDs +F@2}_\sk➄$Tݖ0Q ţ_n1g,W[i ߸XsB0;3mz&He5QLW.+)x,T#Hs$+%jG -#MWfkҌ򺘢몑5<݌5gz/2]'z DMviv*e5!Nt{><Y˒e{ఴץuҴLlįBզ+Ղ$Wps+E?ѡ5N iiq"A͙zcG5_s BulbщFjZJ̐KA +c"NTkF%#::[Zϥh)~AA>,W ct+fZPtߌ&QŨ %|Mz{㒿6Z5"j'0ihɶ<1Jyl|;s|{MXs0ڞrI-ܙ<~+oH6@䓁v@bqI?>t--"!X;k dQ=ӅAtmHث\#M֒?NȒMuuDG:FNopwݢcr{`45^VM|qL{: rsJv(&#Br؞[3>i**:bv +Pj!k +0` +SyHi,|¤[r̘B_9ed$;&>GS<yB <ʹ=񭬆?4pcnZF:H~Q-KgFf|A(?!^(Is2{b]}ġg䍦i1^Ә)'F |?_0a%&*/2G:Q^u Y/Retc}Qv0pssP7#ĚA_ڳ5T+BaȭŌjΜUv=HdM]1[1S*U:NV%IHNe1HʈFNuh5=Ť7H-0UI4gaȰK#.z6FZBc){G,]2ɍ#I螧Ry8 xG2PhTAL 0O5DGk\n=ZЍZj;r6'\@nDΜpj# Id{wSZLF +G`(,_C 5m T@.(i'ϹƗα@FMF6Y\)Q c abuw}|N?JTX<|zJ=m$ˌlM_u>Vn+#`X8%;H6HfSviZ>2#I0Jy*ףAɡt}В`5G|Rb}h?D>vΣ 9PƳyoQ$ٴ%9Bf; a7VtM7jSSGq1/9aJtIsٞ_fg'AAqޭZBɳOoTܭiFFn ̖A8 J^$[N{bb! t Yz6 m h$ᴄopB51Zjݕ(ͪK)=B:FϨ'ʶ2a +M3[_O +oa>K2n +-AGTr}م{K9 +3ڬ@u ߃OxPDH?0.pP[6ƉHV퍤\w 3.F +l*Vy;a|kj0e_^ K[Onuz/m6m/9(pS +ȴ:qxכv<cby=]#S4p=MĢ=Uj1%ˤKu_:ʋI򶼃ͻ{>Ml`VsoGџsX׾ۊq}$i:*fonFjȞ s_(x1~ ~Ƽb-Chk>3j,Ͽшm)q/z8%a`ˋ[exT*q"C8qH.dڔА٤ՂXbis2U QU;j3J#sXeM&_pT}۰4Xc}d`vobؕYX:6!9x;С SdLMtRR) 3%l5 (0V`A,^w_z?|n5,Z .{vݨ4D"MU\#ULYѤ:ř^YmR鼪36ixQc +c CF֣h_5a#iP (zaǕeDՔBlSOvjqŸRv>r,Q^|(3p> +[_1]z7eسRŶA5v:.U>>ug-r!:;bW@z.ؼ Sn i@\'׃kuaܮ.I@dge-j¢Ķw]Upu(*}F%&mÆ ^3 v-DXuSCz9ӵ =av1=1\kF;O2W^ }ԐGb2|F;>K($n[@bx|`uBuX)Z\6>0i)SX% 5ŖGAD7&΀!x)wp,ٝЃL*Vz6!؃J!,ϬլG-7o+̬͌ͅbw@X:Ĥ8-ƟBDd4to y>jS~~!i='xM7(pJTD;Nt"[ v~XLI>@Īж3D=^PG:V-jUu5i0Is#nXk!Nb{oԠ=P{pTU$˅QgJ#~8\Q\جa* +cn縔 ,lr^,`azdW:Jw z$0wN(ruE( 0D0EE_yN{y)Dn7U A=~hs +$\_}&^m\xYy<ƽ>f§ Td['[g&3$WP\փ=ԝrתZ>mt0*Wѡ :اA[YxE5ߙMJfa^$?" (%@nQ Sq_ + \#q S. +! BЎlCL!-" $Vv8T:ypL{hC2K +`%P[k!MZL`&t1v\wyk*n(zؙz%UZ2}rҋ #Wޡ$2MlK1/*kbk#TLuaRKnЯ#hPrsKA/[ȓHhzC`覻= ˊ'"ZݴpU+]$+4Ghcܑk= })NsNp#o#(NDėaO4yVZ z9)!=>n`g؟\rC |(Q9˺ѵBq,?PvD<((Ts>_ +Azwim94m78&XduexٶUG4D%I2ǫ-(fĝkDJa$-y`B-f6 ;6AkFҚIVA26 d +L`B3B ^`2x΍3bT"j…=7C@vF=J? T[#lNcLyҝ:pv KXb$-h\Z M +[Ai=yFsD3G0>CX6Yy25 wrG-6̽Rj7Y]O\ӔaQ.]T<fMyHIk4:}<K>-_[͏hNɂ Rn[ #6XD#y~_@ܷMf"7sW}r`#/.?7qtKJdx)Lf2#->X%/{ŀ<@Ǡ @٦aQX:=4}nЗ{-i,uF[i$R9i+gٍDX=o_w?z51k\_K,M>@1Ŭq`6ˌ sz0 PCBTac-- +Ϭ$H WEd M|58rpU蘄t1O*@z N:y'*gjfbBGj48_tlڶK'v,dzfUlhmGcWf} ,#ds_mɿ|ZɏESnή33HS8}ruծwZۑ\ PP$^Q&{vՅ8ս%7}b8lZ/;,:V0GJ8)%c.)]7/얗nEuM]_y$hN%` P$ u0~bXv\+Mh?sp(A׊R`'[4iae.cDqU^>4)byj, U:ZQPB' Kt+QEN%: VgnVOw.XN[nlu 95Z䤭+Ujv_ȁXf4b-+4aLsw7(c7 !R’\Ž +J\F9V>R_<ꪶ܃]rUdy0նui ZZ~A,*XXT )Xlt 0cǙuEaLa )tvp׎[j+"  +<5Ύ,ؾ^9_rB+*٢bpYGؙz"# ;\Vr hO$@K tnB=,(Y9kx0|d'>?a(T+O EhOwy\*L)?6~}U.}CE)jQun9L/-kջ?7r ?Uw8NI,OܣL+I^ULnDٳ/0|v"D0!܇SZn'2 ˠǴ-SCXJZo@܈t*W:@?SW{wNì0?X *e l)r :(*Kնk؄H`$RaCC٪t껡 zP#TQF׃,=#XK"/M]}JA(~'gLy=c]N~7 guD +a\.O.>fDC}~K([AI)Ə""PnJ %򄉦PbgeeB 4-u!15{P>۔gT-ˏi +8Jy4(LTnvTʜ?7S:"$~;]#M:*;Q2tU=*2]ӎ_\~TU%*WAg5Q UEOzFtm?w߰85mYBÕGVv]f?Gglj截%]¿oA )oV=]/j:&^=X{`MsZB54|I@%v-%i;٪soWvS~{nչ45mVRYţWMn҈ &@䩗>w{g;ݺ/- Y.0#e޾A];P{u&IҨZ~ƠX˄vKi*n;.uyeU2nTTɜAudr$ulGbbحcRŇ^ 1`S zND669M7a0!E,d_ m[*1d誣06gѹixzeqo~^6{mo}tlNFPͤڲ4-aK_"Md"U!>]!W)r )\WmGZqh.&.g!c86u1BJaq*SmExU +29THȴjf +ҢN8dq^Q@*ј +:}#pun7<@W6qc@)c2,ǹllbPSwOe~BQL>TSsZ^#< jGkխע7ZVZkHA$ +&XCAs "R TG4ֈy 67N@P=D9[4ET +AMdѮ j_@H.kp"]^EK$pKCK'Ira:~zU~ +d"F,Nl*,["ٹL^m z7ѕ+vi``L@m2**[Ñ r6Io[<pրo *[kRPCv +tNAG.Ltp {)|`B6|z8UD1ZMp Xy*:El8 p.€BEŚ,ĥ̴>j@-ހ/ Yc3-i_y/v/֭/5~^_;u0P|Ij +JƂZ/*CbADǨ/g]XTFퟑ2U҅THN}Y NSF .df,璃4uYYx:~6K]lhZd>:HԞ=[ssGXYUpgqOŒD!,KB:.iN]țPpOʴZTtN  %`MxTM Gu7s JSe<SB8A_Vf V]h+1h~8 m6[_=+¹dyOН]!xد&NJ-يqG?maO,.QԧvdڧJ%bUТ eFq$>BeyLr*10F݁egSPL2Ta0"Qko+9i/|?QllQ((ޭhNGdoF,U~AI%o5i8`X%+K-\Jn /U" 'C$R_?Wޱ?>xf3)tf,u!sGs?5lOE〬WqnFF'Ĥ XV{iiD9h<tr8QtPN@ MeUF#}YĎ`{e˥]Fq)?FК8ÈhpYL.*ذ^8JMxn>az>к8O񈺈.hTLn-QAԍ̎{}}z1?kU_|M:|I&(љ2 +64 +MHJ6͹ՈKl`u>pSUP7ux?Psor[WOl(_ނo_[w}&`977I[f(|zU&fyaKF3ɽ͔chf'-h>^fޛ#%0X EGgƟ@$Ma@0 J #I 9e5]vEEn {%W]@B̦b +5'tia `tsl.{Ѝ/%ct +`:L\FlՒ_iewadMh!}Ӑ`D&E"$ptrdn/gCQh:>ӮCJFW[GNZ%m׀a"[-F7?HVu>:U& ?AV[6RFb!0Q)OGheGVGn =U~/%'6A F,M^T01w3Gf^Vax /3:R\'^~ BZteiԏ™pߏ(=-@cMAmE>hۏw8Q!pjEH_kkpLYx۞h}ޖ83(T]3%^=m^sN_ 𞑡7V›ީ怂MR? B'- x6VcS?`nu6GP4 \^,YK5?h/EhhYA (@e6l)~,(j8L?=խN?@6k&UFTXt&N;o3!"7PO8B#v),Ұ6Uъ<{Z,ֈ}2DLf T6#؛cQE %ka[w^lt/pq`7-bc{kcGuxwA4x@) 9(o[!ٕoV/h#"#RҥdDLLzAŃ+Ɗ, EO\V G׬S +ݑ'j] J4'Q'WњyaОKPױΛ[~'&$(ac LE-(xsVoO];zl5Hm.әiwN75mP='UZN4Ծv+&£yW)Tmev~;~g~ϊ|뻖V O|wwg}uݟ=:u^Jl'.(}9xej8_GG Զr,F,/g?bk暶e0W6-IQ~dќXьdy[7vsgkۘkTц  u +hmQr7S wZMiV"'+ J^ ¬aaf ,VoBep}|iiܓenpb$u.8ۇ՗= ZPgzvgkgePOYY "A#ťu!l4}c8Q҂HW8 $d~A>SŻF_h}9G!~ _ O=6QxLu7$GhYjnySnDtu[Ci/)ޢ`%!Q3?QcnlGK}Eq[2r?JQܷ ]FDχ5e4UbͰd]B]+jאÂf3Tq~)\(@Hz^LtܵF̩&j`=徫;V,QBG)sO^U?fX5r| DUEИ灦m-䣓b"P~k9S ~G'гߜ8U,6C_{s#}fǴ']1&bcmwG+6"IٜaCA't1c(wgY61~j֐rqyګMzMgP7c~IzRS*?q|Y6AMzЖ74:J Xmt*ϵϴk ^kY6Cj/3U=|ay%>͏'T-daϫf Ok|sDm3%gzd6c"?qu}m~a=ގqSoYva閖; k^6WwKNtnPo&=,OJFX樿<$ڭnUkVMX9.7KbXqq=hU<_˽aeX3ZV]fr@JSAwErhW쬣oUV~t^#4폌.` H7I$ +n?M*!zXW/* JTFFM)R@;K5WhB +c Q|_UB2Wυ5*TH ++bGR^p?,@~^zkdZx}w@ښS:2CYT)ʁOtնZ(24u#+B3"~a B Ov+?e7# +h/@ޏv>iyaK#"ze MpzefdDP&VաW7;|M9j57;?tǿ? ʦ,jHWfs(| ExXncU`b%4eN ˺{${YNcYaTcJMZB +7ƈSuqgb]?;bG, U\yc{@ω%F@xLl裰4De%vHUh%ζi;xS9]i\A# !Gg22e(pMh@U=&3@PBӯЭT%Stq'ХԔU) %/,y]:[vPiVjVC Τec.Ʒ Jso@Gi*I7Qnj̦&=~eʮD|"j&Ӻ ",!~$ނقҼ7~Mhm: .8&hzCT"`jXI9)|B ^/U'j?gUj3h5Ъq J4+V=?JBZ[?ϺXw>́2+V,%LY; UuG7j7Nl|R8 5,hz.Uj-u#P\"{-8<$e:ˢNhXεAlYGugU&yjEFMF[T1zoQkKb봣M0Z:Prjmլ)h-4cgv sq~F)Â,k{/ѻR89ܡ]?A19v1fnd\ne?0> +#Iٟ3[ɀJNNedвr2-q;2vفehh u1I\׆w+ݔӽ|'m_'i'i'||pϾw>n>$--2 +0ʟG>6ǢN0mbTv:Pz {{Xd)>@J~n=*k2J:dUjЪ9 m~[Pu.1!HI[jv$Q%\y[9nUAyʧA9&J lJ~'ߜJ<`&}ǛSSx)}'88OK=O= ˠ2 +-!Z\k}3M +1]At#!KoZ\}RRARRcwK~;%0AdJJ ԳifZJtMQJڅ/2bgYmZkoK.2F}P(/` ٸF!U+I&NauِVtP, eK2ԃ='[\47̡+ T,OZ2[$X3I&yC3YI˴f No5a14MѬbh+>V&,[޴K=0)wb[4c0omA f y(ahH=>[ޢ +Vd k10g4.{#cȸBI~-Eo2Xѽ rd3o2k57y7Cnd 8 3L΍[ɥȹ"a<5%4ޗ>6['sK\sKP!s걘L ʅ3~ϴThUR-?dZzAF9Ǹy) 1ov_}_~ܽ8HVCجg+ƩGʼnq@]i@4I3\R'@,U^: ԯ:@Huְ̖ \ +(u+8Ebѳx'IcHzX'$3$3TnEZޠfhuQ(qҳٯHDEFcY\cjpŘyz ȓ@ə)je3pQ|}#Q3Ű c[%zWJ@>= "1<_p 9܀~N` +VV`E2z> endobj 146 0 obj <>stream +8;Xu[]oj9g%0"ZpM=![7RDlfM/&5,4`hk^,cG8T7_8K]JI:hi4Xql +K[k'r0glcaOb+aq\t+u4[>g>/O.q5G7'c8BO2d"IBYh4%>fdF\kL!ZWh]NXG%Hu(p +,9R>kjHfE$&OUjI;8+q@#,mSYag?/J9e+4p=2RMW2p-+:4[djGnu!N1,-#SP&_>g= +on\oX&VWAg-XYmnk0Y426CA.'L(MJ*;ZRKdB[)O8qcN9Q+)nmJ"!fO^A?EB?%O.p` +3o=H3A<=1eEQ&SLaaG49,BC&-FO)k/NUYsYdDpNs&<4=Vb,LFJX==ceY=EWFHm(Ua +84Q'q+,/B]>G*PVPs5*jU/:N=g/%`Lq%T-6KkTZZA.JqF3sUJm"fR>Bdd=2S4o]C_ +XENbj4,TXCObf5T0H1@0FJ%lI/8\Qog-GkN#Ral8OFGHKGENY:7]=US`ObG5j-IZmk2pnZE\C1h.35oG-Mc]`lU5I=q!pEF9WenXc +<;7>;eoc4G)mOS9!kNk$O!ZPNn"5>PL'#b0!!!$!rr<$! +s8N0$Z!e+?~> endstream endobj 9 0 obj <> endobj 10 0 obj <> endobj 11 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 24.0 %%AI8_CreatorVersion: 29.1.0 %%For: (Gisela Gabernet Garriga) () %%Title: (metro-map-airrflow-scfastq.ai) %%CreationDate: 10/12/2024 08:22 %%Canvassize: 16383 %%BoundingBox: -1269 -177 1644 763 %%HiResBoundingBox: -1268.55072187979 -176.920162098366 1643.733903047 762.862254875029 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 14.0 %AI12_BuildNumber: 142 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: -1291.10472769326 -170.767342301026 1663.41778130721 801.644242667737 %AI3_TemplateBox: 612.5 276.949401855505 612.5 276.949401855505 %AI3_TileBox: -216.843473193026 35.9384501833556 566.156526806974 594.938450183356 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 1 %AI24_LargeCanvasScale: 1 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI17_Begin_Content_if_version_gt:24 4 %AI10_OpenToVie: -1416.13017805341 1166.17139302767 0.358728967948805 0 7984.5794088157 8131.59492098325 1500 828 18 1 0 6 58 0 0 0 1 1 0 1 1 0 1 %AI17_Alternate_Content %AI9_OpenToView: -1416.13017805341 1166.17139302767 0.358728967948805 1500 828 18 1 0 6 58 0 0 0 1 1 0 1 1 0 1 %AI17_End_Versioned_Content %AI5_OpenViewLayers: 7 %AI17_Begin_Content_if_version_gt:24 4 %AI17_Alternate_Content %AI17_End_Versioned_Content %%PageOrigin:192 -318.550598144495 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 12 0 obj <>stream +%AI24_ZStandard_Data(/X'VkiT|ݷ\ &NmGM8nD" G n  +{ߡriz^ER;p[{r^ߗ?0k.c,gWD2I&৭ƨ`nr Bp:Pi bO+"Yđk"$>f3"¯k܄if&(ZMk#VE'r_5 0=Q*jDttGf";DIzZRb4+hJQB=oH) E2' :LX\\@MB)\}Zݥ8Y YE.(T+IC~66KzBGR-jiO LGP6Ypz=tlI:aSK by’n{w7msgwy;1&?yt;u}؅]nȮ첧q<@/'zGzgz?_y_OƏ/ ;=A0;(#H%h'C]_aCL,C3O~vw~'xg?s<ɳ<1ֺv~a}u#->~ۣyΦg%6Hzi/5Ű|otgRul[4KEQ.v1CPO:|Zb~ve';.vc_׻uw= Ͱ$1!zap;asx&X$v0A=9A foO~}ǿ/Wz7z =<No=Y?|On5}9btZmMj/nQ[hG~CsOW-j1]C//^Y[)c:nor[w)jxUMYvƈ-Ȥl*2,;*H@8}Mvp7]W7mAF"P@Q?YϾ+KB(ZͰlzYEq'Mӻ`B{U +l31ճjzm˱11WvowUikG2շkʗmU+ӆSB YTvϲP){>~ջS?J]l*ž- +sGk̩ޔ>ԏs'·+>*ծ^cT?=l/rq:`.nSz7U6n]J~+_Ž#Z]YX6uQ~˽^ +̽SzTJm68_u[\ A %eKh]YZ(]B_K\RM[zN.D$ꘙnWڦY1"ˊg5f_"ekcuFV/'>bgqC0*v zt_l!yiPwO{92zȁ~Q ƔHVMEWx#tÞCq]]<vAާWׁ vt`<\G}붪g\V؃~!!wAˍF˶qZzm$ ~Wu*c)]8Uطzm!^u[@Uِ"({_ 1NyMCu߽K'5ҳ4Tb[ [)MQqza=H#?ĈyܷʦA,83߮lrS^rɳ2Q-]SPjѿB:өH=Oo.^ ]Uv1hm>qk|o}*#85 EϞo3ֲ8ɲ\ϧyy xum*˞>bS<q=c^ طҟv0"+k ʮrט& pkpu0]& dqZv5Mv 'c}gr{e0k ޽ z_aan͹y_<{{OL4:sys9 ޠZ{_ww!AܞӺɘyg.g\rց yL}|YZ vtd̸'hy;sY!r >r츜ud̺4yO> ,%er}]au9u^>݅:^عow}9e SDZgӎښZ4+Mrܺn1M(L8Hpܻ=o7h9tpp7:BԟARq +o.ݜ `RP]|k}|g: v^Νo@ӊIWR~A@Dzݷïk] 龽w=.];o{\/ruӻs9^C/}apY]x=0aD2 V5|~Իwg.X ub݌=2*VQRFƦ>=2}ldv1ȫ.jm"ó6Q^m_ Ϯg$so5p򩔙#HUQh@XTHW +c$(Dd-pd*ÃА`",\‘`J}^` p 3f :18@9 +7txIS|`@]#E(VylB +װjtE>/HO ^KI@;U^4/]exHifR(gqP'HSJh_EF]H[eۏ+̈́?(( cPs+x +.يI kXOªc(E&xsl0@"uQ#4Kpn 5lg' (!xȏ΄>~%a~)?MD a9`$9~C YC يNaC9Kp)GC#i1~j^\-u(aFCc`'DŸ6IY$ЩEi$J3WlZ,l!A<|vgb43n  VAIP!p9cp!148gCXаQ,LI0"8UF.`FY|9^22 E  E`CcEZD9Ϣ4A)uK0WkDzR^es%ac)H!4w(~xr d0 9II$M, !]r,RM<,v]PyL lQ*M(,SҀ>p`C&~ H4 1YE=fq EXZ|*` qRgv=m:!gT5 +%HT5jxbB' +.p)e$qf bB0ChH|R$П)=\2@W4lLOVjv 57,TM?4"y*HXs@J8zm*c%WiXö: 'B ^ A&Df扁Lp9 %jA,4(5 "{fX!ryܓIo?˃#ȳlE Sn KmA7+"ga 4>r3O"va!R'R9,"1v$X0DDzp$@jKhX ! 'P+(-pr]qʼn‰8' Bv|7yd}PJ +<8zPT(QI +`h䠏6JHJ#$X=B +HP\4Da NU$]#>mK<lLWZ0%X^F\1ȇ"$@l߃GG{>@ ZpNj< T:VQP3cEr$lG4yE 1$F2I|HkXéTjDE*S*(;Q&P_"*ۮf#ʧ>ɛϲSMcPi'Ck؇EZ9aDYpy8%$ + C)[ {A)dT )h)5lAr;C9 J\4ʳA2 *eF|▰ + +ҿ!Ź6GPi »8bрƑAWiC 8QF"Z"MA* tT3Dv#.2z(R(|S,Pс<釂!ԅ|p#C\Z&5XEa-O5L&*J?)H@ ncG$̥qGh<V2ؓ*2$j Ta:W߃Ŧ39Y9pM)jB*kc/(+S` p\G cti[HW +fK.B%2mX_([tF X)Tc\\*}!5Aђ8($/ +ǟ.rlyk Sekbz ָzSbh$0 i4Έ:\HWA@V[E\Y1hoS6 +BbY"2R*@1@)] J@ ([Cᒹ^8b E0E)FA*4;9<%:!fRJ!rJܙIJWv, mubs`ҁ +L3[:T";AIԬi (7J(X d-zWk~lQTi!@x%FL j64]=+P VEQYɥ}wPJh@9)&1&0 +Afo'z_H4HU qÈ@/Bcc"x]2uA77P_ NdK,B0dH1%'bp1\ '2# \`G`$r1R.F*/^&Wa-"΅BCo2KLٸ2@Dx,b؋VnwAd$cuI$Ȁ;Bz9Tq 5¿a!CH[8xhh x9p $fҡ-А|q4!t!p0 L%䠑K;a=<ÔnVsiȪSPp q8 CBc}N 3v%=l$QH9XHV)!VLeGmV˭y,JD`sٍ䌓Bp'ęH9>'~T~qP!I}ƚ06=[.H=\[BE$I[`]#@Z|kA(g᳆5<ϭN:(D"%LKL5F<%TxܑT2^qL%@W2-S +DX}kA<ivQqҸ/MM(*qa.JJLЍ !y6n™$Ezn"}GtX@LHt0DI@`4)@$ +D]<\F{-:_t,"^( 4lA4l-,eڡv#~"-eY\y ,$y3 ɦapp$OhT*~B5G8 GCpE7TSbp16N|Ko J$b6GPW&@|`Kx$1/v*/x5,8iegtE0[QQ1 Sbiܗ}Q=8쇭IWqq'N!K>J)15%vGn:x#H0:aN4M4ns[En [M䥀x,-PıC7>ԣi$I!I}J&MnHR9^06&! + (tCHGjŀR>N`!HH%7 4#D +N Kv<\2ylK&p<\2[r0L%Tx]8<PT++V++V㙖#3А pi%&.R6@8F%V ʦА`J4&Ҹ#y/*w0eQty oE4LC=+dUSaR>J.E FQA]lʾΆ @J(/¢N#ap*PtHҡE4LKPj{'a4B) )N!rsC!1APuBK0>EAAS)_(䞙9g@3GS7A@ + 6х 9 l:%+(a@:;V)_$ J xrfiMG, ѩPx!F WE6AJ,z)7,ydkD4,ŋvW1h>L|rIbҸIEHS !Df C3 ɼ?2FJH2*0* G"0(qbFdNAvvn,t +mB*0_1R&{|nTd{wHk zP>?akj5K ,rcbX7qvkeI&{t3֏bUЎކm sEӑD1&I`,$[-w/Yx{ UHoL _+ݲItuSVWUt +W(u19,r[ JT}0456ȉj/j^ӣ7Qӿ>T&݋~a&&~Ģ|2jEG4.uEA 8B**O'v.p3LJ"6tהޝwZ"|#*]}ԘJlgAj\EΦmVcʦx7Nǀu_ l(?␢WmuաJdIhY,?vR<0^+C$}&1;XVJyEҹ,ºSמQƿʉsÆDe슳ZKn"@ + ,y/NKX872fx{RܗwTAX`{-T^!'Cc,8|Q:x]r[CN=; +7ֹ @O@U\s\#_u~%HR?)vGZ_I뜖\_ps^~Q @k +gu C1P8Q)Lo0a)6 tf_б7Ʃ"/&}o,͍3yuΰ}`wW 𙃁9f)#k_M S^Xm̓>Y1փ'w;0';.Hb6 bֈ;"L+G[̽K>"8F3ЉtQ/ qStQZ .{|B^Ľq>:2s}T#V)G`s- ?Gb?dI :LD;yX_f76U??dFu>+?9yAn&vA؋K 0Q,& +#4Ԩtm@}Ck3u0esO=ڊ3^X|HtR?yHΉOX| +mk%lMRbR>ClϘV1XO knb2EJ$4-pd+F {u p| H/K aMd77L$}͸m<Ͷ;ݑ0l5k \Nn$̥z@AYx#('v',vɔ+#?{Aiuy|Eĸ3|Q̛\1}J3DĄC"2ɇwtp)Drw*YhCQ #Iʸ$K[ngyWU6W8LoGR0㹔[ +\.c%(n"vaCivEIz7eX4o5>^bC7?r@%0Y`ʠ$2ZF`[e{9Sv)."#nsb2OQWy;%Qd2nkBH(+ lv_BX]S|wYS5۳ +jG܂꿐~ݿL + +'[j@g%w1cɲ=%;X3omŖh,~xjv& .4ßa٩3n@KN @mV(^0qΥ%krxwڎe;09Ͼ վCk'Bs}|PeYqLV'Y3m2AS)}7*X[Oĭe/sRNJɽy1+XR/m Ia&E=$U&bNюύ8zj,4"7i[Z:"iԥ{a- K A8gm' +0XAfTF.:{Hx*n?XE`P ?;md~57SWsZUT4)/~/료9.yhVȢ=S<_Ju12F!GO ȗUe,ԅ(fqTQ3YPW.cv=}ouwBPZuQ^`j<6bDnε;N]C/+Nn鏺eo'( APk6X*vB(槞on6p*5E OU|s#2Hj"+8%A^H$x:MI&W +)%jskz8"*;w`u[2qW7t&p_&|5 q(H>SәHH,\oAd~. UU@+S1:'ąOխ!|}=ɨP>i ~t3x\C$ZX;sBYaM]_p*IJr9w+Iu +,$c~^iDi$5#4&LsX_R|f^r(SABE)M-_OX"˩ .h)RW$=W.򟪧O۪o+$t%v75-s6ޞ eX@% r eo[ $P˰䴆B0^ eZ?`GegYԾ~إ0i3oA{\m |VN|VN!}[SAqЉ +KqS#/L<Tr6D?xǞfy^?Tf} jX4"?atb?O/)!=쯿3ˀWcBX 9Yhjdq=v<ΗX%@lq<2e C^I*/?pS &]aϰ~ءʅWW2d}-iITiC)!ޓp>@^7rbJz*ҩ%CWPgXI r``C AGRY E590A{!N>Xxe./ mFKsZ 1b:^M8~pKZϊU@5.쒴vnjۤ.J' +&I +q_yUe%DG>Rt nqEX #nѸo{' +kf[XHDqvׂZO Y,WA:lX:C! 4& V8:#\5^'W4!((R8ĵ5JjHWI፩NÌz%b=L?o,GN)jDW}œrUZfer0)ܺdcL ӓ["[Uv.ܺPnA1XiD]V@W s(BPTv]j< UxSn+0knCʨU7mt^!1T|.RA. t.pvFZ%ϩ6|o kY]_)̳s,}LӑDyݳi4i"M+="F7Zq@/l&hn_0@޵~ʖCsU;Mi-$Z}6 +.BZ>cR )@InY*vdZ*bA1%V,}]ApK_lX=b[c>Xc¡܄^YO5F>Я ['RGb*ŷ^A fP [,83T Я{a\f87534/r2yUQLS*WxByKq1E!=idbH +6 +uN4x#*=ma u紐M1mzߦݮHxh.ա*n 2$cBcL;G%TYآ-$޾D; 0`4,({& +ې=2tZf@W^diA :3__mm|Çz4@ ذӱ|eN$ңO%\/š_ KO3e VoX@kszO؀7b"nře/:ն(Bn6!$Xbr!k"NR/8)D 4slmj/ u u7 y%zQ5TIl"/|F36(gfטjIkV\nJ'8gEHdeHQR <”j^f'+x>|ϖYaF!<6z'Fj6J*tIhtU?͍3.TL-&؋okX%mc0Gm3Pzm &k2UZh%>9; mćfbc1TP#Rab{g>8Py6BˣxH&\J<V9L%brչj4YG>}#Su+A. ΞIhAЖoF^rUp4g A{;:k?i2K1Cu^<ȸS 3D:~Ҋ:#<U9Q0mdo8É +j50,&ڼ7!\,B3.+A4?sfB3F*,e# C+;,Sh6&CeEJi_B39L.937Ь[u߻>3bJ| |NP3#81[Y{?3Zͯbgܡ9g~;4W's~f#xDžCs檚Ң?ßYmTg>K~dh^b}74#r;c1phZ ,ߨ%f")lm5٣Pup3g&4Uf p 7W][L/xإ)B"P&r. 8B׶:f`&ء0)&!]1ߡXM}/ūuig[uN ԩXZ=Ixqz/NaD[7DX=O5"W'5kfꓢ" I`VbߍT8|;4&fLس:0!̎`#9h5O\JN;Y˺Rd0Hd-0œL4M|+G_s\H,i +gSDZ>Kz\PU'L%'M ]̂dz,:o&Ժ^hxßsJYNIJ%8cNh۽EcBUXKa~:̘V I5XW\\R{aM-u @9:reT*ʶ]ߪkޮƳcpRg-ܟfyg,Tgg$ wS}xǁ%EOl^ 9^rhyђ/Lbt R +B< XܦfeMA lMf_NLn*uyp7pIaՐoioA`5)i]|7̂goi sP&:6[,Q?O"[p|ـl]@cK^,oH6j$+hlr@@!!:@z:9Keb*!֏عWap[<{5pb܌{)[ ܧN>ʧ޽W$L[Roi ;6}dRri7]BL PB ˦>"O]baȠZi|aulF_3L>^j ?DŽ[_baP {xVuW˧Es<^Lj1K'Lkr+*qTDY'U2ƔBrЃ~M xoz/pBM17!5_!N;^KgYDDv*7-L=8ޢS4%ڧyF] _:)]]^J#,&mkjP"94[hL]Qu .F&#-TChЭ6a«P4)\]B0_nP5L=_}qYfvƵ{99>֔aQ+۵!ҡM4kLU'˅!po-Yo]= x$%F=Hj0`zW>Ie;* pZy'T뇻RߛTh{}>{+axGH!CTd#q#rκlu.U`|?VF{{ga>\56lK~>Qaf¹aJ涢1vw2NoWיUkOdHn`ZZfx>2%*[>\kP[O;Z=.^,02?56B,kpqYl^8;_ek{L#dH¸a[ W(|'hnlhTc8 yΐABzQEh_R㗲:7{mzy^ƌ|Yˈ$䕕>`! ϊ'Afa~?jY +W;eD +&dZc.6-I 5 +&kX ADA;UgQg_IMl3 kN瑪,эuj+tq.,5 .d QaclPyGݚK\OKJ X<4FFUQA0lV&i*Ye-Ťs'7t ,,r׵},vPx7cYjw|pUOfjO9_ˆ/ +mʲxApL_}Ǐ#|xіIaoc%xmSN&J0*vtS^36mK?LyP&3Vm:bSݡ=M ǵ&(^}07dV,"*z@2BrFHYf!ZᏧ>:ؚL&p̝B أiH0畀L)`X6 a&h C Å=(zR> +.z0D.e]6sQ© r"U/W-AMWϨjb|H),\,:'8X&"o"L[2;˰o¯ #Ġ6Nnq)yN*໿O"b=FK޿o.H["(j Xʖ] &Bj]BvBaG*kR ?SwrH4UY@]42ę` +.kZL?'ĭ;L`Deu51}#1Q+(5I@ (ȌIX^ хvOb>)aHF3-o'+0|OڬKVeT4.hZm6!_ıJYZ` HYH\ xٱWf!(058>vXq7Qs묑s+L9 +gؔiļ%J(^d<y{,NjG&ݏV& hWU2z 뙫 Q62f0P`&By\Z0 oNPzE׍#BKiE +aϣL; 蘛irѸo=XƑ'mI=c.ps9,> +8ONaR ]vR5~GWDҝ1k5}h"HB4`V>+j/H'HnbAQ2}G*|tJ#j]OkgN$mʍ)J_&r2,Hl!YE؈~CBS_x'rZ=x +!c$X&.U{ Qe +dQ^&Õb[\ś %`E@$J&i! Ex!DYד7`&)e,V}ǵQ~_\cެPm[<3ʛ$C ++S۽]]45Lzb|C@-EDI&HBrIcRIݿ2HgގsIzdHuB7| +>W3.یl-evfp BgJ?jcN G!A _qAw'U&yh5hzf 0! ~xVR2&dANw…,)\`b<k(tƺ9 *?2E n]H'GHFJOl&} 4tpJ(!kpPpRbK5;{zL^{ Q ?p7ؕhfmŸ՗~2K8ԟ{z-Rr姈`J߈ +%jc!7  ̺y`%pMgi&ϰ$ /Wotv^މ $ gĊhjCDdS =2ƾcm%֕@ibȡtgD+íwj gF7Di]hM}yL^,tVXXi$ZPv3cgLx)V$)R|DR`YM?HݹZ*5.~Z%/dYySe!+70@v--ɒG/lcN7;#uXz^^ZG!Qߵ1mj*XIƵ9h62*EK]W(}m$;?SP(L0y\^Dx8jM.^WdsxoHꝞ/TB}Q@)#,LHBF2x !*%J^=k2B|.cq׹D{\B&g(6z$de<ƒӨJAd1ѵ{B/_ۭ2`}C<p^h-1=xFVY/2 ].9jRV_X;E\|!V5lXqC:h[ 2 ~Qc.7)6/,>!.!+HlҡO+kpdkD B"K gA#mA.(=3'̌,>}pDTNdUɫ`V q qJ`Aa\E&-@+pDp}-L*BcXq +OrH4HDE7/ aAhRAaI؏1|tX!Hϴ$T>+7pzDĵ bA\P(D +Bғ b nPGD 'B\%!QkA\!tnH7$J[AĠA)Au˩ NCa凔ǬR*Oc8Eczv?êmm=ls@'t7|jّ. +ƑJ诼һEH:%SI(Ӳb4pȟ7^ʼn^-,9?xfg$f4KkNst5Y3TPG%у +O[Xp!HƈkgA,NzbJd9Z8a;~|{xzyNXyigU;;Ar.cV_V>\glןY4ujV&ςy~.?bE; +P˛_1A;~?ּf':Etf'j!/y.ʯq!5%#*5W4MD6"uųXHzImq;o/η90 n1VxYWrV/p!Y{8EQy(ʚ-RuՎqZԊ]'3cj)-6%H;xF&gau̒h&"7>e]d_CW6VZPQ,]+A9bg?~7"\aުf +l`*8)#L| ++կ\N2p' .+onĈGDrG9Y1,g(YoKȽ"m^8U]>*S.Xz44B$[g72OD#|)]C'$|@JiZ2XUJ8َVוR\ e[J;|S^~~&@~r4> l*w4Xv0 `qn*Y <tYcZh-U]E"͗M"Ԧ +0 &h]Dл!#$ &&p_t&/p"y[rټZy:N3<[>Z9i[嫐r^.ɡం@'.mXjn le +#wglF-S8:^ 2Qt8࠽>Xn5V.C/`p')&}C:6~i7(ΕoYY9W^aX&t}ky!'C/H)[;ߓV| NYPķ2 q7Nfme{U#M"p:[R o:VŰr7%܍yI>ϽzY(E\!8f&6Yj +:#s>h?_? 5u?&%{cepg!ZWlNl8B;EvIuKYMp~5f}1i⣣+HL+rNҵ&t +>˷d"n 0"kL>]w6֕- &>-ۜTفT9%1Ut2x `齴o-*Xnpq/L4>Λt:L#}{@Cmg01Q2ƚ%`8s\ݪJ #ͬGEIB|"PeE~#􄂑YȎZ;2 C.~aRb\W'h'^U!()m-;_^R +X쭊upP>ecHJEmJ$*Vl(Yֆz9o"Y#d`4aM?JQAL. +H EneqD-퀒FrEUh]ݾOO,:cIyr =.}S&P+ϥ\"@k]H)-G} ^~)͜'UQ:-KFpR"iWEu0ER[C;RjFd=оe~ Op)lJzr_{̈́fzM!O%0wǴ[F:|m +ڋ_w*w@ԐWݑ:jvJrD|Є6VuݭN +<{&Q-+ 'r;%!@OR /_r9-L9## XG9PCgu2'xOkY}J;Y*6 @,>1x/L?aYrD|#az$ Mwm7rk'V%U~-!Xx TZ;1o鹬y zhOߊ87^^w8:9x^{n-O8P]EN"w&q`y9K[Iu%zJ@IvNZ"roG'L4IFWC̠(EuZ%XJ&Yo>:U\`Rm~:Nfح3`7D]O7GYGFp t],!%XNTedhw  2،Z56&CGwvDžW0sg}SWt*-X6< +JsNOM [dlnvw*"Y;oƅ1Y:"#u], 0W)u6 +kMe>~s}(1u{8눅b$夁NJ~jX +,r5A^rҖD@r"[y;j`m}J;:`,rGv@-e?OHza&0t]f=-*̲:uLcZpPH}6bi:aJ)ъ8%}7 ZGFϧP`*jFη %LTZgM +K) Z.TQ~ջi쿀tbίPUhO1eKyp~fT̜é[V"0CQk4 +Oڧۆ09'*! +:@ )8^VG|U]\K +,2adՁmPʉ1B-U餏OV@5 dpɨ^=\t"#!qv4#k;?C;YqԬ8~gKV-1vb a*s*t`SMt9q:Ӱt93$u-1>뎪Q>[@kłEHA6Q:`)׋q.~oakEG,>:S0`| )[U~88tmη$|tHS! A0rȽo2\}6GĈ'ԥN B 1 ,A j뺌tF tQGceL|-qt 0R`5]-yT?U7lDV7E~&D@GBH/߲Az7.,#2q L\sya MRI}50FjV̏o˶-PGb'нs*Wԧ] [(0UƎR +8䣳Y/mUB"hn\[6)%ؿe9aTǕ09!r0T)7{2t5 ) ୼2e3R" +[6( x]5BXJ˨ +`RGq:aN3Chi(Ho W~@% CpB&&ѧI208ṼKdힸ~"bov +/(x岆[X)ۼat7:IY-ەz[e>Ht!I$qTv`-4 *,pOeG$z+@2˷Lѻ k\f`Pjej5j4 j IE9OO@`|;H}Zi|Z\С+(U& <5v@<%֧W]J,wp! @n"g +5~lS'yYZw2VXCԋ;-mDA!$eS&'cvm[NJd/l!0ISR{quh{i; +-[!7J32=\'`V,r48N#ḤցAGzlY2hm圔v&i _.X-xheAU7 ₶_BI 0Ǐݭ+wJ0@37rm +F4]/О`I}4x@ 5JDͧxE"m=ZX.vk ޕÅC,U8" G߫ 7g2kCdV-q*wj(m]__q[N7npYy3"4H;0,'_y6$ԦB?;?K4@Hn(u2:]HQV*cvE{2fߓ#ZN_ @ +a`2fW^O=z[|X5u#!!F/YH,@7)"g$vp6 :So F"ͥV +YqH Q-Qg&c +ӰAniLHKH-%! nH-h΄X7- /[[2au)"FȲ + #0z?7"z,Q!&d\Xw-GyCK"}p^-iN_ڮ`*E j0 %d`P^^/U]GYOAtwq)o(tB`t0rGA)dNy~af&(7 +6~mX$"('D{b$=Ygv'^ YN &7HSf +y:,Ė O(Z hoZgBW[e9zԋF[|/$I +8~ Dr7y6@u +񷄑 t\7[EU @Ml,' 7uJ)A-P3VNV C5Ywe%Nhi73gi 1/L1 Pq*c]}cZ _Ho +o>H$$A;CE2(~{Åe5F?}Rb$[%#:[>+8F+!qPӾiAi`j`(hJ.BR(05-PrvNNgLL68?OJ0UoW}CxaYB" + A +zN5p$旯-gQ0@\ކ˵Pl~FTǕZ`Ʊeji[N%Nۈ>&Q; t 7ZMB[ +DYݍEڋFi;Ni+A8]| A@''ؿ9x\AZԹ2\' zJnbE((ʢnD2+}eˣ;akeV-;PZ/ $<}F A\ҁv|B6P! JJh(k[vB I<"q 1>xVC@Z d2Zm:xVLI9eݫ9PW"Wn5L5p z51ʳ + [VW-XZMʘP;J,LJC|LVrw: +ѾCCTiQJ">6! -hQ b,io @}uM.Mk88 " ✗R^ 9bTCv}z{,2MO쫮Ö͇ W}".\ +ZZ ߲UC9YV%uIQkwy9 .+| epiR"+e„M `9ŧݓDR) SO;lY@)2Fm4ƺ,l"hߕot6_W3Kcf`\hf>TNXts)`bva|ʺg-O_ȷzЎBAnه<<ܞZ:+WpTVq7 B@=2x@a1r,q'K@8* zXhD@zӾΣyyAȈPF/keUNnY>J }DWXhRa\//*Gڷl5if0R%l+i(Pڧ&F bSES/s"5s^ ̀^TɕY[c[ +e`, +[FX/Ԑa s3sof5Kі]\f5UW@[F "~xi'&d5BՇs06)Ht5U 8izW^/ל0'yaZJ'XKL'doa#Dk<e4?X\./ !wl}" S5'_WEᅧID,[:qwd;ߖhL4M"2Bb8 Ttac7ɠߏd֭r~,a8Q78y7,ȷ,8Qq-@/6d EE`&!ڇC3 o2c{#SHq#4b>ex{NLJzjJ33ƺ,N=3] @>V}B 2c c>TWwfmyJQB.&l7Y$5>Ըy0(1KZ# ՠ"b }˺B2'n0T?钁"@]{΋)GWN-c0!bG~qۚ'sHI t¦=nŠt``ڄ|hMùQJZ~J薰[;r_3NEnE4"x}8zpne=J(bu ӏMWEo"[~rF%Kx.+\ Q"X**~#b* +X[ FBnY! yK$xO_.ȜI'U^vGQހ[6J']CXMOr7]Fϥt0b0o@:e#TNzCQtr@ϡ݄`Ma9]g V>!AH(Nv_HIْs)c^|Ts4JO2|c"E8C}58k@S`?-k\xiȁC(H7_NgUp֊E'cTiPʖ5QJTt+OZxK"[o\+ׄ^ȧj^EĿW5 ^Cʼnieʜ|yJGo od*m,/!k2o٣w䧂X!v|]]q +a0ցsª菢 +$qgS{Ӕn=E6f%&?8q#< D@;j];޲G+cng` G@{ w-./ +Ku;5VYvWq?eJY KՄ}-0@*5,AR-56?Vay= uP]wo׋oY^(}ՊV醜Ϳ +XN:.79>Nn/(Nd0VGEIe߯+i*2-keh'Oq286h`/[b'*߯_yDn׷$=˖3/⁑v9J{9/jRyBÿX \ob!s+qTCK{' auґ r_J,aA(c%J}k?|IW## {2z8Ro<taZ"lEI@᷐qObĥM_>-_9ё},a "`TO(3[X) +eEub Nc3 (V"vb^Ogzg#Κca1$n.cxV+D_F0x\ ),MX=H;٢>1N+'M/M@ +},t ('SOn@!Vxi/LO @ +qzSh6 t/ |XM"&]Xu_R㇘ rPGB?h2f [)?!x>&Q/NDh*H'b9Dgz13RMΕ/TM,yC!Q e(D{+m D;[FdgXr=8#T?!㬽Q }$A±q!c\HXN d~V!4ζ[Μ0wODtV&1nR /6 ޒ.5 OL{C5B_ +Ą;ōRR)h;ʼ26sE +R"^]?c&n|TG#2 0Tute ELFX.@b8yL!@9Y#:1eGXqgf ?*"nzL+WxMhԥ6ifS 䔍O/h9+e2QL8ūyCTqp\66dɬ h4P[vI͜GM iK\6l(P, *>&<=N$U# cs~+EqA{@m/7\ zP [6S +[6JX=U֊EURJ [t)H+FT3XD3弈)cr|&G|!9rnbN~'_("<-u>3ZB8-sTOKh?}\^yyCCV ^'J6f-P ~l!W,["L+VP/?(<  H8m3l>m[NZn@n\v}͙HIzl0]9o* +9#]9g Ԋvv G͍4+$LTR=apDCRt4FlM:ZPJܲDd{g[KńyCh18`Y߅ϖGRĿiVQONh F٨db~ױԌ0b a 4ؠi1IS+ ni2VcV@-Vil"QU~yby*JHck^z*A )ƈA~gz6LyUv },^5MyWa/wP:ke,7(ˊ3KL |if `0˱SU%| xcZʢ[=#br7f/M<./h^LE8eh5r/tNHхf8O 7[ `%pu *UD_j}jR^aSBv O|Դ0)cTa +rw,=FjeȆXVm ++M [`,Xfz)F O%[v:Ki]!#7q.prd<+'c ӫ׊F)HQ @߅{vjزȨh8:5N9/KyC1!cawݤtҔy"n&nuGnYDY({|}8oayاm"4S3kNEɨXI[~ebjZERM!'/[hET--~n1^H"Ҧg> _$v /h^D Җ#:ogz5jMoi3 !ww&Hayƅ"'4kĤObU$<"nm Y^ڨ)Gb) rɪg<>n&F" :]|{ڀRjʊ"y)hf:`GL!/Wd*vYG-k.+o-IɖF*/ѭ* +[&"J>O7CM}@ <zH-(*(D"#Xt㻐>Bs^MR\qoQcHjb?9Exڣ[زu[8/[K+eÏ[V#4;mPi T!-t)] V,XO6JJ4O<,ZW+KV'P&U?q>)P;|煷 +VY#/rL8PdI+F[,S(u,ow8dCK|BښG(.[CNi} +>q @J<-[V'-1r )AŢӛ@eh^:=q}HV&8hw[ +dNAj& .ؘʑ$bJ ҡ8诎àʵZ=Z=t_mj|հri( ; }~M$;e5sGwUOE=8 OJ ԅ6}'Nz/`n&3(ole2kfȃ,XmБ9fBQn 2fYMF`jy@ i mF3Cgy@GZa]y+,)[g'TR=t]U 1ChfZBkT"& @ix#8azZG j 4qږj6]|,@H1U f=LJ2y ҡJ+Ec9xزlL6 xF}Z𾇰`8k3;t=Ư0 ^ i;ցO|vB-n4I4RblQu}"_M]_COQď8[KL/Vę19M?/#ee{ C![ܲoDاuE},y8ʹl<(hc4wMKwi;p"GڹQvEn'UG2ӈlUqlѧ/[ ?ɬB d~/&C_ '+JiGL΀@6J'`I(DJfx7ҿ# [ ߳%p[ڨ7b@H@3@c UUw32Lė,/Yl׷TKiu֢;r.r}8Mb +(ҢKH:Eʘݯ $ʘF:}qp>.ʝ$8#Lf>Rs͆8G?(DCw['ӷL%(:4q! 89"I__!Ye-+6-;b ڷGe8\m""??Tћpcr#Γ6@%Jr'[Q(. +!@#޵oCJ)D!2>p)g+:H*E}`8j; +~F>Q{A^ .IKc'ן@.::Rr^\o"V''@4~V:"Q> ̜̗;4q֘Fm:j +]e<>nNwQWƁ堪qwb?tt ]-̜Xt@ +#w1lN~=m= v1H8ݠ}D8RmkHQ[2KCgUX9)YShxp*+2+QW/Q;Xb1G1_-Ȉξʍ1}ڋE--Hy>޶w`!mEǬ׀QGY7w3K{@ng @-Y{PźeGMlDo_ɘM֏D X/~(fc + "⛚~ߚ+ɟcN]Bn*vQ>xAs{[[2H>G/ːz?"* rFP@A9?0ؓ7Ư$Ȯk~?NY,o5cVh3rWGM0d֚6q}`SΗ' ,%ЬE{Q!Yq֨wݲ:j=i"CM?:m^ +ҮXU[yU(MFaRH*,<k9Lܽ@w"@Ǯ‰fXfJ&F|? A`gIyA8-т&wt{ߋgf5B`pN֌_^ڪF03}'xS(Y#R]:5~QUB-4&=BYn/ GPoUx'8K{(Yf ߨ$K=%("JYcD!cTI{m}e~=X+_-0-W'WǑq1F& ȘcA +lF :[/)` &}N;$"j2=a@J`k q4}a=hP1mRF邛@Y ,ByC@i/i"iɖ}%~Q1W{QGu|QNrGUBzIxyqq@6V' & )#7ڬv +N?,Y(-Ljo +gB͊&{\M<H; +2z'̚2fPRΣ SsҸPD,'m7༢D8Bz{u1  3dHZ&TTӷrM'  ?5*W)% + `eh(HCrHK47ؑlֺe$Bt7{-G X|L(%g^_oyqr+PBw9:.cQ mV(4~[66.,̉- L?(\`Ƚ"? ,NU.1m2 ƥI ŢE%tR=kioBG+i@/]VEOh\&wB6tѼVnR^ qj@3~vn~@CM s:jYڍ8(v|~)/Mw,+DU!wzZNpXYY +_+2fOнq rw1!m#G6ŢuP@]qE&ĥ 1pefcX +L,wP 0M)R U[ Y`C7Vq*!w?r OPT+XnO7f R FhΟs ~ĜgyJ]gD$ +[Vz(.\(  i߀pWS"*_#7ڜYP"TwDIP#]q~;Q[a B{r_o٨rf'*epj + +v f7HI:oCC!1r0ath3iRB)dA+XO0Pr>S]P(I*skOmBDFQO/֛u,#DbO\Ne? +/1DK2fg piG<YC?CAb2 aIuFi %T畬ı < +џ1zs~W:u,4~爵E$L$΄#oiVĊ@XgdTfwFG^ΕGK8oBP'emzr EaЋi?ERtơuE JBiK(PoYD4 W4KTY{MHUR>H3 `t V~z6D 7_p%BzI;Q6HA"m7u{#ͬ{(cv:(2ωj)KLoC2528oJN%0XFκz +PnلB?62#B׿q 尭l|V@>-PO}q g"sRԧJ/u9W^132I`"Cߐ\g k[0d闀RG@`*CE2z 'X%xT; ?Bt0vA\ږq կ#QHy@[Raͬ=":90ʏ~^c.)jZĘ E_ϫD + :'(yC<:HR2)E"&g2yB s CdWptJ`2GBYI ݄wg6= 1ܛH؊eˈXA(#yQM!®of }6> sEqSg +%IDU{1U4g?%(SHjW܍ɂvPӰZш\ÅW[nY ؑh?_#P Q6;J~:O+^1/$"I '*d֖N*&7ҹC0@8m$ 鴄#i-#·@Xxeϡݘb"=-*ݞkKNp&GAe@m*W@i}aDY-L247/pqtbS&d0!H3}WV8u~RЮh1"⠎s![Cq^sΕh;+7ڂIr_p_N^E:kŤƁ>`KjU9@/K[&QYRZ(Q.u|[оb f >' IlZ::$ۀ8]ȩ+ci Rh(4~[uou ў>8_V.+_A;J@#rYC -ӫ}BsqZ#MGhz˗h:QA_keAYZ+ϼ2'PsB (zGd_F;Zycvb@w %XFi% 篙(.!U_Ki +4u}q6+]2V}мMS {33⻐}]J{ 9]Wе/:~.9NRnLE" + {|+O4]߲g=rp:_u~e[FErp>Ĝ_R& c0@vX|s(Dv΂8oSkՂ\[&+xb蘠َ2`Yǯs4JgRֱhp$8O:0]+΀>U|lj^^v} zAʘ=ºX9M,st%Y,D36x4b/&U]HPe&_-up* Rn&TG@T! %|`8 | qOЮ"Y&=>490.kMٜrw1:rlY3һ,a:xyWB MȄ +0k-+r +T /"P ŀd&~ 9XhWl’xΧǫ gQ8׊w8HO, HM~FFd"ɘ]h2Fƃ@YtiwF`UE֌l4H86Pt-MEVc #"zZrs&PJp +>Q0MÔf//rVx@/=5F 䪏wlNg#ܿx,Gum:k!w/!tg- cHi qt(<)o(AGBTѧoٖ6ApEow(HQ[&P'e>-Q]3;'HaQ!JZ-B|pNRs +^P-' -gJҖ[><Ώ ivGPKy}c'BtwaYMR[̈JG<y?Ln{9.SKyH<[A}y΃.X1!V'r "tFu?8/ΊƥG]2[M&/Pn#/B$w _~0rG/A[ ?񆬖ٍH+XSqxR6R>H(#8 (H!$:ёp(+md.(%mk +TS-b[+UBJ[ jH?AE{u +కݢ̾qQ]Ô1'fкɼbz/'y$") +={(6Lrlttcp>>JR'L4p}wEP%'CZTZ ҥE!ِcs2,xVi)%+2ZT2 +NAU{r3w3,ѾYd3 _> UrCw,kD'YDLYh: +{17Hn!QܰDA(E/ 1FI.BQ p|Q9$22?3}*?ӡ-˨JmOJyņP{LhEDe"liu$|,ă cB\y1Mf=`نioS rGAoń40;a^ o@0XBȧCE8?dB7 QxǪ9@k\ JCUݲ01*@|9`!T*zP]&9H~bb1'A%Xt6L bp4nnOi!?F8jMu84' kqc45éWN>nTDi冚ىFV1ͨNhVɓͮƪ+kבz!f߯! DJ"8j2.]Gf1Jof(C37TT3$|0Bew=]he .=W%@0B_@eSYv5Ajwr? |6h!u}Xʳ.&S:FYY7NQ#q@yjI" `rRi:J +DK>b!}fͤK3ArJe|=afgGM0v 33QUIf|&6~ R#=M`+0# JOt9z,*QR +"-uو D K@f&~d J.9#0 RDغGem<~e@FXgz xv Lܳ3{Ž,O;N[?W? 7c*=;'6RϠ 3 !6Uc~1s"^nj-jtmKlRSnV0OG']IlPx *{VtB3k?]7YCa;[Gmݍn+ɯj*LE+if`Xl0s'RO.!K~g$lsĉ&[KKp&M21لri qa @_+ ̉~ iiԀ5_rwd='.7z1(o>s^:~Xw3<$gK(ZpMQ~@`Ǟ(JIohfl +ҧwq3. g'e "Av"JիkgK5fg!3~[E<8iQ2 籂BBj<7.V6og{< t%2/M!ǀ:t?CTw=4 Dɏ1-4YhT<ؗAY}I2>t)Yn헍!@.(2`BF#w@hk JbY@t68VT}~_ȄtU/Fe i+f[EBXB݂~Of"ppQ7zV*[d͖l u0Y$?4d4Ξ~T)D Fcn߶:+~rӝa/@OP`þB2: " ẃcCEsABV9dW} (ms9_ĥioSi_Ҽr}#PWR[Op)D Y^*nFJjd}@Kcc3 k@ju=Ipp9nM*Ǻ3n1M1E, .HcLL?D @L7 +d!?r4j BK僟ıç~Ena<2t5o@\*쇶ᱛ;az)C{!$=X şҕw:) noSnF{3~8ʳ?$ҁQz3sȾ /]'U0S0.+%trPEMʊ16|˓^%TQh㴅sRS!!Ủ-Nj8 =zU/-"t)Kmv3GiR+BD#̂*hYev9OwfT /oRvPE-_npbI2l憜[ 7L[+*3d'~B`޴ߨ39ʒBy}6*[ͻD@yKjf-g©$lb}2gM7K}DM֗՞,Wl5[d6n8S<$k#2DPwuZ%ZyP]{eO&4[S.%!{zQ,sZ?dLR4O %?JyA}{r*fT;hM͞[A1X](E+ɐ;P)"ǡOM(E¥_S^[L2 ţ@>`YBז<9y8t@x +~zQH̰h9}qDa`HLY y_s^,j̜ETߺ +OQv& { jy +B*1"0N00B49&< DtU7]-bCD~#b 2Lq:hH`/?< WE'UW"J*KJ$E&cpk$`\NjCRz i='P +7=TI'"P՝?I(}+@9diQQ0 +ah,b1wس HDW2TjVn{J4DL| 9yH6$)>Ti* H&F@VUYh|$65 <}"2sQG)İ/6w> aإ +u\ ge$ +,K3J +e-"X[v!#q%x!c}#5g%x~sj3-j^#›Ϝ{F?m6t |T nPZ[B-x8ewl3HwȧUM* +BLH)=ɫ FFEamb;^v$Ba aDv>%hݙ5 əZoF0hgaY6V2夠JZ*kkWupP&%eX{E+3 4TXl2NK{.PYihz\xh5:QKW4i Y{vׯ*qK2/=pPn!{|@e&4=j-_w,:r߻ڤ^@jQ{MEhL +SJM΄ +RF2SheE94DYJB'E !]>ظ1s_t:e-pSf~:{zPGmgHlT\9Z=j ٯ0nr B}Q rY論ɨcZjWʨ(B]:wU[!J.%LRbj:C-9$Cm2>ŁzẆХ?*& +Lnj 6Hs6>o[}V' aޅ8Lb5^PA. {+`& .cCaf'ʩ%iH9]eY2T#;Dl=4mv.ZgVnHVGӂ( JDӄY7؇Q-&ZL/vݴaJSdj~ DP3ƙ`9 +W7Q >qoh./Fpe!7!g' +wQIȇDVVچ1aJV|lO2bx"|C=E19ƜЄh(y%=)w 7EitSTfgbgt$#(0l\[&Gw, w/e;p{r!_xlk=u0?pSS>GrtƸY􇀵eOX-;%ݠ?XIB$01CC%jӲȃ#VgFr+iB1PmJ͖`>kԭ|lht.D.־G͒Лe\,+AR <<Kk|?F|{Yy3{|sG?bQH|lhd5$ysV߼E{n4 !F +<#h{SŗWd\4#ZNU}ë+Ubm^B>SSv Ql)yUbmCk%z*ksq*HG0NʚW^NHmGYC]28\eqgbZ*~ѥ)5\hubF;!EQ,$HꛜG;C;cX }lN"֡P*Ξ*]);>Viȁ˷x>85t"A^TIC97-hnc_gF.X*@aZr6vcqU; yuvL=;2,y-X$ y+#&ZR@`dw%S +d fl/`َ}H[?*v}:^pDDq12kyMO8 7J14u`Kvg +"Son ?[V1 +:B48bH$P0G`Kʻ2pyܳ9݉H ׬L\-FGDiBBpWehCѫo9 ^ﺱZG?!mÏ&p +9 +MC. 3Z k+.jvǮ+E^f8qunU*֫H!0i[smfjRu,pݡͿv4e>~m4}M+!a19nah-<&ek>7Vרm^p-ӑVM%91ID=I`x">, Wp1s:^A߁6ވl&6kB;tX Nu+ I&_ɜX +)uCt܇+9?gl`_(ޗPKyWVAriKw//0TUy\vYvk/aT%*]i_ ~LrQ-C=LYг*{ oG)7> +x0MVfwп2 0%0(Hs3CƅG.'Z*L*E-91% /L P\M\KI{Lz$FEa,soaq_)Qg4q 7aAd ˾z,(F°]aƂ) *@?` IB=!!`X3SeX%\B-Z:C+^% KK^ +c&gY_%ⱟ@*GW~ 8QtY/'5 OMN^&pQ+DbvSٜ:gWCiU2{qAI1V9s:;ͨs^`Hj.6a@Wbr9j:n!C);g B@pϡZ\W\~9l_~jʝ)amrT.'}A ef p-@ne^[vz/anȢP! +Zi#P 怢(p]BGb栀&o_ ˦!Dj0}(~[@G#@RP8L+˺o/: [A] +IS]tz6DgBku gI㷃΀|L22'm >̝(\k풌擰8)H8:ZxN:>?yF]FB'`5 +٘uDEwGśm +)8Dm/Umu7 Y$TGZZ^Gw 2PCy3->-ehOdZEg~y>/>i+{~v\u;` w%AqĨNKI rcL(ﯟU9!q#>Vn>k6&jT|+Fu.T)%8|f 7[L3Q~RaI ʻ ڛe\y*F;eDeBV[TD"+;H@X\=t#f͠t3ѻJTEZS o8ٚVgs/b^k~%-Gr @p%c"+HLV`T%Jv)-lkc ?^'PB%-+\SZD{@.Z,p3/Vjh835~no\VcƔiQKr*@ϴDJ*@7xn)ʍTL+L5*yhJ9,cc1˃)1ƔI,=R6Ԩ@!mJhEjiz(F.˻%IRz˔G^G +hP($,,r2 M*d m&Q* ୔iO.ҍ)-e(xބQL9Ig :1 V3BWJ +VhPRUz?[٭Xn>4S1"&_[ BTPy8 [,T~}WN%Z!t281kq*.[$3V <,ds1[ا\15"KV,_etUFL_\?DD>)48B.XfsljP[8}|fJ,{ V +;oeb N0bqYV+nphd#|I(`9R /"]MR۲LHI1o2ʪ0Gu[ :/pVcΥP{Ŀ|(яFbH7"۷'(c~LL7(*Y}OJ&`YjG At& +R2vn$G񏦳dl2`*!?.nOJD.fJqfC%H}b#(K%pqح"12Jyw4A_d@'-[.7Ps#;X%r5q޹JnQ FVXsAf22@0&4o"֢7?w#uN ^ {Do>w.?ViCs!zoKEb7W3D0Q4yS +}"=9J@4eY/NbyNB\>1$Ll͟F@L +H)g!z;Y 9)_KR䰠ASN#rztNEUcSv)**%ŎZRMgy -1^Vaͅ'sG$O3 ʑv)8'QYU{\| g- +9 bG*+cz0H93k-%d@1+B⺰*aJI WbwHk1YGi!&R#+e' +4&PU#20J)EW/i[AAv{A"Co;!X>o샔q-E:g(U5Mo8ٻ,[Zt- +|[/K\3ҞzC4^  i Ooh="xI@dEk:qb +.a\giARugv$UR (FhC 1$\=%;Ȯ!7C*(n*[b)( ZBx4s/yͷ5 B +(] ?-& prGW{7r-i="$BMwS. /d#9N?+pZ + +A2$=MEE VLNw?lDQ X!aEb,xcpضw Q$/"أH|!  &U +X+4Q|#ƚˋ覽g<m B,"814(+t1BB <[@yrv?헻x7_)FPnuWী,Wps赂.)}4gRMBH*>H-tg3l4i|oGʼC%>FG8Lrd +6ڑȃ8Ig |U}zA|A@jQp&]L e^.+4OzWѢLZ2 "tI&wy$bV@3wL@Kdj2 @f|=Sagxy]8pLhc%1YhDSv*4̚z6P@Xq~V ThAz@f!8Ji>Vhh%|[dNWc/ + ]4yv`?C5$lG`GwԐAm,U:Ʊp=5/Pvcb$OqAI`~τf{m4/SĐPE.PZ3!eXV*2_m'9]^W$h>}spP&uMWJ#iҗT!ji_`-Zʤ}W*|^;o _HCFйةf%ne$+l/<؇vĹ aw +WL۪%nm`#5!ٜu(WʼnWWU*bɠd˃+9^qS+ds<t^h.dPeit0x[4% QP.ӞwV%%-vF׀ZePIn9O€c\Cݭ!E*/Rfo?+#B<$9}fKp{5omy l4= +`JKH:0&2$h)ey(;LIBSglJ) ւMU ʤ#}; /i3MgbNN#&6kn@||r۔DKݶE\ "0k)S&FS "C8' f}7Sq;CJNaS/|XsT0@?)fO1VJ_ zC' $( ʚPF!?pO)EKxȡl{Yry2J<O:OBhGiƟlүi#ȱV}4u#WhQC?&1MHЍ2Q'PO`_UInr |=gdw{SylV9H$̧#tRz1c.n2F<0U!֊0B}&,%c{th$.JHErwgPL!F-)[M\ΙRӐ{faC cI,x~ɴq 4td<T&Qr0TL۱^@<6G"^wOH:C7xűX Ath|X^/ jD.~c)C+2ԑA>TIm"!MH f8-%1=9tBR=-fD1. APܖ܏hUSn*  A@k0.\1iXaCU>eY/1FK)K(6;ɛW\䂺[zM";nS--aI +̖H Bq(εp,; +Ԣ|/ª/)Q{ )!+^f&99,)VvW`h$GtbmWoۚA .2ftTݤ-qʱ84o_z܇6ZdvrK6mN%:?@7pxu3]ܭJTrI%?N peG`ɼ N`uIʄa +|Ga֧{#F%њ5ZqAk%۾ހL^NFr~g 7&Qv*kkXMXֺ8ےU[ t"I!qUT%ŀ JB_EZ<4)`7bMr)N8|GDŵE6Y:a2~C"팸#P~?rLBx&_*YKTN}6u_u;?M3d5_f%Բ$`z%%iz[Qn7^ߺ7}.hԆڥÑu3.)i2';(B芙0P̉MJ, 6'9sL:?s@9Rtӌ1XqE18󷀏yZid]`#yI_\P?>$;JLGr_A(D\$b9[R$řmxAIx|li-V7 ;r sktCv!)MϷSrVV!š5TCeԔb){ 1Aah}QJҧ`C(o`inB ˳ ]3:nE\"]}`4=mJ4"{nD>Ay'\V~_UL("ڎGӊج;*dsJv'DOS w//Uy WD5H ܷo$yL,~bڨ U]6 ~ ;V|&kc׀W8.l<;_+v' +7 Xg:Зed +nJד%DlʎQJ^}ѵ߉fujNA FQ 4˜"ujh! $XuLC/I=Bi +gWHRSvCiW>cmk J|:8J'&K5u2T.e|@78XU;]V3'odk R`)e{㈵ʝ +=K~3TgBf"g03(T]'Sљej2KᆉVz<Di_Bv|aNה&ʐ:-J &B,WT绱;H++7I.M2ֶZ"`Lmã!$YdnVNAX8$G*Te@b=iId=O-FhZ7)8o6eaP%i7f\X5~2( B¬녪!*9߱OئtgeEě߈g\z]*❦DhX D%X[u{6QuT#*ܵ Ŀ?;XaXuUTߑƥ3b,U@r +{,uھQk>5HOՃI*|ԧ=Ƀ Fp@ ު +!K߅-2|. +r՟܆͆,M|ˮtg*>)aaE1 KF}4MBsCa܃GL|Q<&XUފsԀ[Q+Z P֎b) 1Wf>Yfxre#[±(k@h=OGHEH7Axp}?EwE3 ̜sP{ rC4/ `ߣ̑U/Ïi!%/SE6쇮416c$md^Y0h>f aN"5Z%Ll8 ðUCv-C +h09_,\DL麅M"͂CDJ8(~l oT 015#i官A^][N~!pLy x}9|0 %c\e-S$%*{KF۟nlnR6N0ӌx;@9%jiu$<=o/$8+BJ$n OVoB+CD1Tʐ T.[3lS%, +H,{ n,MBvu9cv0|Hֵ +z>z9yC7{&WA̗ +m2YϜ"RI^׎",sI<ˎA}AԨgl 8HjWuا3TOhc@'#!?[ sT'-$ srtMf=a}Lf&8B ^!a4-݌FR9Vi OR4//D,2iAV2 Զ,#I+; '_^J֘UB{ +>R׭FL>"8W{c(Z15bx +nJ^zJ˰t:И9cc(mK{K`2H#25%&`[zBX>]ON߻#ͬygKi²Ki %VutqBzɪ}J{B QTonU o4.79!wr +!hi +Ys_8J?:2FNPe1}&KD1(3.:llcw ou!vÒ]gPHe`g)tҒX'`?zP&CM iOt7FMבs9tܕ[R}z޶-2buQ@4)9!#Sӓ&E-oB=aЉ/ OoX:tQ|@8 %D endstream endobj 13 0 obj <>stream +ypq5=kMͧ[1B; +΂`~pz""#G3k/' 9i`A~o.bb(sBڈƥ4~qoY,YĜ aBbA/mRHCG6!S"sA RѾ!!Hnjѧ{[-݉5y9K{l\HAlYv=aerp^ɯ-jgi Ĝ7Nv]AܶMhV*婙`G(Ee;gYHEĻK=? +~ +>\:ʓW!}V"hǬ5(Q`-uk(p)e (~K"p>IyX,Zق-/WHSe(V ::=թyq LK"rOG' c{Ο74I(DbQu? |lDhdwa8b$=ߔ&S//mGYQ) +FcЬ/. F<^U&kb?Ãز(:# ,=q{tB[&~&1)d;'9X \T UQ g8s^=;p*j$tEE8rwE,aŇ-# %}ZZ?=@-"<0^P0jvCvqT^BV [']G7G!%Ä!V'55/cX\e. .ޫnG P0Iiw b n'8LH.9F_xP޲BqF6Xkzw}]W=4ύA{Ipo7=y2o,| aAHGOJc_6փ1=siiSJx*߻B\S,[|BmdZf˾*D{zpG ,pIQ/_G&C*N ' 1<ƱO WHt}:p7 X i` w8+aZ̙:>8 ]@B"V]? `&!;\ݭ#*#s~LiiO{* Ra?1֘W[&AM*Vx]:Z/SbJ͂Ycm`$e%gx_bүt":~$a"g2př 8krMUU vT8 #(4">r 6W~ؤrw(^]?h;!U0]V(fAW{Qfw".;dw5xp^mQo(HSXNfΣ8뀈gT)AB[6i:mU;i V󖍈f@p)SDX2T*&&;V#q,?=/,c=hpD5>@ +IJ|,uJT"[cm|E+Wy@*hOO Y\ͬC7ڧҌaiW0VLptdF+cvb⠬=5/4O@3N!FI4)?~ +SlWTӁR>2 +J)SJI p%YX)e[M ic0*8.mSڣjX9e/L H=F[o{:" ΃@кu憔-/OJ{+4Bo9(d +qVh$N>]ܠɬC'/Ps[p#fl—"^Lh^/_'MƩ +W@,;6}bbJC2 +%'9@/Ng9iSpa[?*GY@+/^[Cw ơti⑆| +Db81 f.c 8oTɉ]'[ :Q(ٞvpTXtϥt56PX!c !,[@WFd K[elӆMZd*q=,c-\{DMbs'0< p +퐯tҝZ1NAC;|@2e#7W>"&. S *liNY'<喭䧻^XSRey[@#{+4QEKB Ь`/GZ'- fGrooBs}?4ftRy +[9%0}:bIu2(91IsJun baJ$iYZ%] '3(6=&CorƀP[ⴀKO9Un(OftwY`K F}%)3ٰ%BQJ6[ga>S=  $[Ju +KiGT J̵ְČƣ`<#!j95RW0F~p",|pag */j Db-3P#>(A!A8@3r:jg#|(cGߧ*A]wu"`9{G.< +C1zL+]g1:-)X^D ط]߲B޸о# }Q(DFN3 +oyI`G=Ϝ^gA!clHe5 LxV~jWB "q wboG^z3 OGsBڋN!kA;`eրx҆a =HEf^hu"Fxy[j_Vc3|dit8Xnj9/-qgMLpj 2mDv =ॽf`qO\xBUݥ߲W!DS'66,Xd2k<+/`& +U?8٭+Rκۃwtgy>U-<4IƖ?̻r2L7+P6NݮXúu)(v c +[MwbY0@X0Bbi[,xpZРq w9`pߛCw[a+lAx6lm0SO.mw! T¡˽Pe ƬE R*=mŤD*49b?r?&r,wRqwB%yߤ,y=-آ>yS\w=rسܲp-d +`Fe%߲`8(` w6nP BubȌcC-T)1=?VF/E|XZ+*chEqN(=- +'uNJ`mh^7< L>" ƥ1/®ϕ떱[Ɖ1TH;lvB5)d?d) D_[# ec-|S9_!Ҷ̤Owo٪T4]oK(Tl Bf|&UQWT9®& F6U*b +Zb:czbȮ&nv<^W-#w| Rr8+hi>-, DrUcuwF3| qiy@!,eO{?*oi]4qCi)~ݹ,ba `S·(OH{ź^rpŅꂇ))tʘP8ijDj! ԺeV6+ 4mQB`Uh7 LEnSO4<<}Xu Du/M/B8!I&dΛq֋:~CD [/0qMt_Ѽ-|1J yv}J'&)hWF!n-ZG:Q2# p-04>v|B ͬ%X~HPt]eh^gS{2zPÓ)Ѭ&i#K|Lb-X.$뛄0t8 Ò允HUB=+a'}|cU K3 `gd,-X^m"m@u|IߓnP̥}WejJm׿3U4|$EڨJifi\au>|]V! +[zKܚ> 75gqs@OI G~rw;[ +AE1-İ'^Jzw#{vP/b +]T=΍'ݛ7"qX)t"m! _"ifaoAE6Vv:% vτCKA&COd: +-)d 891٦V2F:iv[qX:ԋ!4di-`׋Ӷl/`Vyo+W+5ˡiBէw:bI(uWZ"|i4 D6IO/'"ےQ Լ*CDif A +>GVܡ}%Ў Vf,F/Ϝ~VvIs&oC]g6uTC]*lZ9LLC]=]9]&Ǣc1F=o|bxޤJR5UN%_VAJ)y/ie%mz$pO0*"@AD88o⬹==$׭= mc ˜&%TnRJsN-wS#nG#nE@;by2;X1hJkH8K8lio7h/F Xq7YǏ,'+YFdmQq-LޥЬ3R̜Fj~e%AYrK5"^L WG+eYڪoe٢>a(`=Cǖq/1q3MJ4jLG5 1*nB+OӯH]O@wDܝ]O-oYGGvfYk*ZxajrOYF?ڼ<.^\E|xKr"Qt(xiGx/Rķlo֑U@3Yiv7 q7HQ^Iai92Su)6c|nѓ:c CHu_H `)X.%o,><'cv]"Nc B}AT;BLUԥ`46wvj2~[+GXV3Kr7[t c'Г;BqCBvk_#^n!-t[vR!*q"T\#nQb9(Z /250H.PkWq9e7*3)hor'{ 6JΚA-.;PDF);P(AkGP2B&?^[Pu] C43 FWu}.BI>ސоe0Ah KCd'fxR]DTh?MXfq r^Ѹv[Fh 'R}V --vǷ+ E,-1[VoX4|p~)T"޿WW6֮?T4J>mY,'ۜqby҈h!>|kiӳi,-S 6f־ cvuA;ާKj+묻HED}(v@ĘڀNM oĨ\| 8K(%~$ZA 1K:덺A` SK r'n$>:BJB5IGL# #jB8Z\G)Od֊[ҒK+}P]3M&p|1p7[:6nNW+c ,joq}DŽ9'_a$=Hm039Be&lU}p O IJT>}Tm6ʏHɀmYlFRMM9o: xoDXFի[ct [. +`T~ke`RN$D>7T,}_rHprBtu!W!N+Oc&< N 'uP쏶1۲"ˉgK7U"Fm4b\_ĽFӹEnnR}}:y)/((S$lʶpbB Y^/`ɫ-T/0egzoF*A!wK,v#c`W~Ow8b 5.!81;8:A}ع$7yfuw #(ig[BX{AP 5_Jѻrst)6KmzXtx4Mˊл b|+{y"Jݩ'98k͈He^natś` U;+xBsׂҎfLp8'(<η_7)#\ѡxU(]oT]мAUNVJ+_zL5z[,3/%̈| ʽ@Bw`R;P1~txhZfbJX +[淬 kX 4*h2 8pR^ + +RXBj`|YoۆQNhna!g:sy2sgB[τL+_91PKȝjrKG"en`nq"nO7p@e,<+cMip'mFiz/,Ko /U>>'p)W[#/&҇%ke~dzr79 +v"r :!mduy<Q8!sX^-o^R0^TZ 3lj@@pѷ"OO蒀rDG]?u[&tOlYD402hj 8NClY?@9Xw U~4J;"qw9}m%߂Qvk-Cp Å/3(ě`~i}'k r}#xyWN|-pM&C'&9 8?x+9tN (a:b҇Rj +P[u6buһL^2٨~^š0 @va + +\ +11߂&TR*T#ݲȖqLSA۲:MN -#Vp~ȥL!Z wX'YriD + XJo8W4w.N|L I"~@*VEΪ-F9Y짯I +#U\]gjY@A +Rf/=*cX@d +-wl|Sv6- NY-UٮP-P[V9#HQX6]qxFY/8,`֋Cˌ! nZ!'@)TD܋(m}CQ!Y~ׄWv5.YSy 3WY^gM)rWx !Q:Ikk\IU v28߶# z_Bs |Nc/(wC(b]/>6 pEpʰ=Bb޵1¹-},zî/<}8n{B_kJK '+<ݠrUh|lBq!U է%`i2~gzC~K(ma>Vn>Y#B:1N2 +pʹ 5s5E]m^1c7nf4uc*Vw/>KԼ.[A~%?w/%@hErݽAE!ί/eǨMVFDN +ĀYWᜲ<ʸ{"1Lz eתqX;}sև'6ncD6Q@NZ\RRB~TtNT:tLQSt묯00˗eZ,0/cZ"1"]55tT@sJ< !ьZ4|R,VD>$CH QADq q<.T^!CvglR!zu=#yS*8^hˁL +ET c z8bR ~J _:Q0yh]qKlLt>ZڀPb%%/>iC"D4q"yko]WUm71LI \c`m1KnHtSD+j +{ +/>S}0 mq2x)ɬw(Z%. ,weZ+S.%\}drZN_$͔DGtoMTz5,%ňZ۴~LϏ.##]nK<~^f6Wk{2rrS#YfBT- y;4.8tyN Gܗsۼ =I +( b1>&/ǓSQ{3FPrzUg5gC$v-~ +7 6 i+ƒCztKU2NɆԜ +nxʓ m/W"Т*m>ܨ¬d|ڦIX0sIl!to:5*m1Uv¤$#/ nFkf l aātm.hXH`:vu4OLtVV9ĴVR:"Bxq5\wvh 2 ޴\C ;LV0z:jUc +59^>ؿQ +,FU#a+jA8Ћ+D9enq6c(4[4Ǎw+`a?BhW0X&þ$?ǢjNgeyh܇wL EcE`^%C`zڋE`b~Sޤ5m¶n?h7tCo OZ^ OAғo_$3i?퓶8w[C"[;4o%d ;twxU}ɇyd;*fDŽgHڥg<޲ 5_揩PC =2PP V|FEP߁ -rU +!EP)IEg;Xp?Bb!\ugF WlXN + sxh x`EҘiT6޵c;mA6(=HDZ\ 4,Bg⋨$ 'K1`DK8V]#Ih]KU~n8tRBo|+R hmϿZ^I.+23bIgpMϒS1:,>0GrU_8qQFn͋7.E|6: "+ƽXXkѤ%N % +5S\ax"{:A.˓9wX̙IKB6s߰;^2-R{]D0~ۖ A+_g;ut0-}I'j| i(a0$ S1)?hmV=z$M!8mj-z6'\ ~'Talu"LZ1q}vI}\k)P8G-'ni/<_Ďw ۉYsj'@[62)vxMYG!2^VfXM 5y%Mm +ג,7]8t3|&5QHp*b p7rRr2B|㬻{Mr3 @zR1 e9=9HMGe_ x~c[{ ^<~=9|9dG 3`5\'}@a*8TLtҎ;vã!Vä=xP82 +nwXh.X -.UX]mb` >UEpwPؠa|TMBP"8ڲ$)5P}rxŮ ʡ b! B"aY7*H)}6K"_S{UnpxTwqn.+ ou'Dj &RWt`Y{ \ix7==~3+Ve6il4 +ȳ/ۚ"cUz>aLC hckH(L9:ו !0tQa ;?2QBPi* zqȠ߀ KƤ15af*i2a sH_疹uɄqAz[Fw!&O)žpU卆{*V\=̢*#> K{LmAtWVvsqk Us3V)Ӂ!`EV cKĮg7>"C(َ3ɔ-BΔVu,lF +›,>¢ B:Wd`F?t4 4hjYnKt$M9y 8WUꙅXVaY%r hit=ݧěQS|fTk$2ˆ ̪@޶cAd]? c~1(ὴc4&AQp_dZOQlʾz~W5G/EA4x,TV7i ib2] à`J&5ӎF,?. +~*<# N^SҨEJ $|JgI VH.zM亏I;tfȕ1e= !"wC,µ>#fNdd[+m~v%;Q..~B;0šsyU9-R޿ N\C㰌i?2j}9`,@ 2 +UO-6p3yv ,?eЉ”YMl`tRc!U4IGa*v1髍Mt{Zv;oTynI{UA8$a8` 7Ax4xEMm'* o*RpKCV/ȡ.oSaQ:wk&Mn 9SB-a~{(8 #M[VӉ{iB?/+p IR ZΙxO=CV 섽@p ͌ʔ ZQUN%tJFKcUϠHG^$r\<[ɷG9 +SOb8NJV21F4Օ\h†tZv qp˦@_61b獹6Л\̯I-r0[pWi1(qa}Udbࣇӯ|-Vhq8/Td9kv2#6߳W|fK.VDHv[hM1-  9z襅*ECs\LhcZJ<dSĴM;O,8ŴГh)NJp)woV -9Ŵ/jGG=żߎi)\fX'Vm3>0%>oR*ɉSͦgf!0<)3mN',~o͊ \e;?P\ɛq>s +CFȳ`QRfm: vt$@`gs9i7S_tEK{}!B45z2gWۋaId;}Mke Lˎ=wZ;S'>3B]o Swr܉/=$'4a^WzӪߎ{ R 5W3$bSɇ {\ +i!62i%"yBU1qgw-m)i &3EѯFCAǤ_#1@Gúk*1.3m`J,\#ˀgeNw_D%]A9]དྷB{m*b A~:c"nZ͛)^2}}o;R3@=Q?}-qxejٳ[:qeax%j &A;20VɸNwjB4Qa`q׹;.a^i~[@`a=D()l<>^82H QK_$RI[$9`J7=XaV{GU\H?bMb͂olMZ+A#Z}7A$UUָPuV7Zݺ3 1$]#prw +^*&U&9*^6Ort~•tp0CO_ĬLLg7v}GjmpK +en [ kOo<rPs{IR6CP/U*e (1ܲ%y$ r6uwFvw-se.GoAt%+4-2g{S5?3yVhI#Ԫ1Sǩ?.簽Ne'}7[sΖ_EyJ9Ne'G%d t& LwĺUTvd2vKx{J1g\iNԀ;[ LV/ߋy>Wy+k#$/V`8s:O^:~%yU+0oYR{TNnmjq u qÆg,(8'ڀy@E7b?X|C({_zziڙ4IAz ]VwrѫBx;옃'1LʌPw.Zu޸ȗǟ>H2Fl]a6JNʭxE[=ȊMUxWyl1Q&[97$ b!S%"?P5q>[{cqOWX}l)DRi=.RFb<ti)]P"GVk1:G_cK"9cv] .\ Grɾ=x] +R +QM&B3 6 3Ԉ)vG<}[kK_lS^a*v#~k% H5Q\HF?=~-vuPn;gYثsܙ.%tjuZfwt?6'K>;€5|%vKN"}pxe;"$)TkHpT mnSk. {[9JmQN%ۀ}D'H2!iY-VdU6% s0;ZnHm7qmH3V[1-3`Eamv GTBoŞ-!qQmxl!>w9su6U9`y6Goh+8R2:3=ɑH 0q!tq/v1߼TՎ%QǍRZ,,:5^aNJ"l˽gZ=苇 āo+F`=pOuf_Ǎ}=)?]pT`kT-XzBTe0W,09Ye zʲ/V+u5B=ZhQG@BX%{Qw7-Ui*J5kʗe|*Ew\WWIw#b[P۳!m+PAmŠ1"oݾ6lJAUb]*._\7|BW`7F5$ 1z|NRT.) phI&HoR@CWFl(;k.V($|SyQw +@*2K]bB +MZR (pM&40U=و+[n/++3⳪s*/2)ZiQ*q* p^l5.)>($TQNR +ys(K1,_ߩJUbb+ղ>U_ǞVQf ipGUB;/a3<O W1DcRН$ 1v}h)>HB&-ۨ;RU7CPFp;qWUeiFjŮo.@p4;B"es gh^ V B" p!z1OR\cMU7rl3l epzSu lm)ŊyS: 'Vʹכ~n+Yzڥb@̚Jg׍w-:6nZdfȄ4tEGVi7v"Qtz3V[c9(Ѱ%:";~{}Vq.͓uqѡ@ 2l$;{Al|Ġh~DTͺ6"k*h ʼFIz&q;XdTo7Pt ]שvl= ^\;+#9/aYN B4aNC).uhl2= gr&tf頚9&6+[!!촞h'&.Y$"fZlۜ`Plh VgjqtmZOf ?q&ĒIw&)L*T6'Tv<#dKBuQu`inbqLj9f*?X,2n x!Hk=\lI%Fn]%hJ0m޷^<`5ĥeIBpc3qAFJjؖ^OD2U_Ę# +z2P4 +lXĈi;4% qˉlXbyl!!Qjφ!S}l >0@¿+@cXB¾rbI$%^@^1 1=,#0 DtD̫cT3$]IS!V|mug|2-l(@{ܘAgYSd8? +Ysk@fbȣ+B$Rθ|Oz}ν*q,Wߖ:.8?7s#8銔ֲa:J'yTŬd ?lO2,AM}rIf|Qx(9=)ez-?%&YZ+!"h4Ziyf?ژvo瞍J0|;BMo_XrOM1כU:"$]Jxbb `4(J䩨7)TH:3)ՊwLGKh/n8إ` +c>`f=44oCu? ^vҶ}|=+^9-']wmP:=i2$D/({4x7wU6 Cl*]+~YH9BcNv(f}{Ewm{]=:x>DW|^F2(}ŋEYFS]"z E# jF ?%y\IpdyѮD4LSt7u"Fh4;#z6@yeF1jj ש{9;fT&W9Qh[5[d8 homFԊ]GϤ[ޫj(7ht+6+ +|]K'N(ҋ`GBe@]H[3h XyCD6Q|j(f/qws $,pa)g"UsHڵX7}Ď;Hc6๲oCwpgkLZ:+ZƈhIkUYT3 bE;l= P'FI w/KB:[keF(^&@`k )}U @0{ +m8> A ִϿEo2# \ee#Q7v?#qb~_ zTC.UaXV&Yu0P +þ;m 7=!ɜ6߰ՒT׆QNG$2OY>Ta,+Y({6HcL9`v)J@^zi13vG齕!le:Rc9ߣi3ue.QX9 ] #8I S,D_s}_?sYT y_q/JЎaqV[ ס0Nt?;̯rx10i>͉ͤH&֩R.&cCdb%8eeN[oEjTSf)IDGGb ڐ9$-* nHƲ.JQfu5/=46&x>O_~5I\&Bў>55nVP/YV'CDONN:ƹfT&K>v bξZr%3ig5|!"nʥ`l7n%ӯ& +l;}-3{>]wD=?ȫ4T@Rbtb|`GCFhu3ӪRqoTrPARtFe[]ѵ-\[nקPa8ձG` 9;u( JH3@Jջ{ԃsV4UoYk{:Z8rTܛ.V?cq&Ps)y!q#ȭ"t5cʓhXDq8'D~x +^|Ğ=}j wi^F=ݢbYt^j$L/(b|{ԀQmI Fp5q;e!afs8ŧG}_, ifuv"LEhj.3N-4d>A59ŋdf^)>-خ"*UĿ@F O2m-q3;+Xac C\|? fTb%L +V2yUO,nxhlk!)Mp*Tc@?+2[+q& o ^ae/B7-DlΨ f7|JXZس1^ӝ*T +UQjHaȔ +UoSp<'m< UeW=ƿZ&L6ITU ۻq*,U4Ưpxu/,VL5D4~cL7VBfnQM ! +-:K; h>kʉ"*]ui[wDQ_rI0uc]/t'6B^|(Ju:)&$)* fA lKgQ;K[,e%Z#'ӘVm;4`h/[Q> six6V# ^ƨF&D04b`+y7]tbvVp,.8O.RN_,KJ1<= ]a1`ıKBpl3 yL<.0p:(Pc[TFDJacZQ96ZwQ X_3, μu +SF؎Ɖ(\~  P 0Qtai\Egc[ҪxV|dkn6sX2*MOC#A5)ӾJ@!lW]a֙&Q=ci-_b˴#J5g?ֆX f.X#f\oy }ckcDE(nlAքgacOd~w!wodd\gЯH;wQP<"RQhke,q ڐaYH?#QW`lDC px, kM5tiOr@:nP>2[I-f+Ba.R̂nK+7;#['D@FD C~"˱] ~С%:_XS86~"A"{ódrpU k팩^bc @`_vL-qybIn?Hv6LM,sgs +tREAw ]Jk+rs:g @Сa!ҏ}To>juk K{*܋z=!ڈÝ (:Cca[Ob'LH?5Ztd,sP) OtXk^p2ij-!}L;dX)m d}1}3U(M Bɥ(|qÝ7| .]Pg.q5TX 庾q6 \ ~0}XH~3զc + Hsq~523r~d뙧|^uA82 um@8M)8+TUq^ˉ斱]2W< tZaWU TNy?{Q^PRx/0ZRxw4BC=nz$uAu$p^LZH]N([tiu*ɋd!Pw(lXH%P? vAUvS=:RL4[KXW@&ƕ5KN6ؑ 6``-Rer(5\Q?r>W;~ >A3{,e7# +xFwh'隮fㅝm˴[鉷)>>n@PIBԽwW$i#ʿfF{eAf~$9̬ _GMȈ ŔڧD_Oi\@碏.*,r,ܕ#VQ7O5 v3 dF,K1 CN%.t >&&nmxڷz6܃?],HP×M !r LْǴ}q@e:32 I bz&6r<=N:Då*Q޵`gOebu(s6__ol/B>3vn& qYeRLPj5P,vm!r$ZcҞ3%3P_z$H ҭ}WglHUuR*4/t + +h>+E9*(b-V]"r5|{ .d4V]P3Ƒښp&7H<_g`A6wfU|Ua[/$[׳QAuUM>qji'܅d#7zr0Oñ v}"kU*}QbD N }aӽG$]q$3jL0v"tKjg3kv–gU&hu3DZ=oe\("]#:cp8 4Z N +0":>pDx3>Q=^56 hi=xm)D%p[=+l6AG17qf h Jʪ6{eTc)#k Ef5ZPD"z!HiVԮSQ17٩˜w{$raر08@YS  *@MCx"Odm jqxʗ)kX +.bQRa.QG%eHO)L&. +'z lwF)yEAf4azjEhK.@ڢ@{#vɐ+G!GcsHD%$%1oD;͊z1ƚm@j]+j֌ܬq SHZ>n="ʏ򃫒áG8 d޾WabdSapNO8Q@2h;S_gꗞ0> ]~X/8h}ILjМ۶7c ?5n2O-Ћ2&C)5+N9֎jFzan/S w!_ܨB-_DžDQ̨|nb^GӞOT ){1E )kdHe +%ȍOSOqeqI'DD#NW +Rf@ī #ywyk;)L]bU3S&sW & ATHET.:u@J)[IN~+e]OV#a!#ovDP6NiBL8kkT`Gpk4QQAت`3yqwhNdD<~^8>v"y?NIDH:|cϧ+/ϋtP+<;QJWv =p?4ݗjD_?ܿvX- +~#B2*3)$3+ /{wop{O :K3Z"?7w"|t)˩ebuk >Cl"&z{~~01_Q tjG1UyR*bxF*&z;^6\wń5z~(n+ԀEzߏTȣ8C"Ψj?z@ςLAe)QqPʔi3hYc/zb $]W߶ѹ G†Ÿ:?y|_]_gjk< Ġ^C2դCT /Tצ&އ3iIޕ_'!GXWZ+.mJpP 8H$Q%ؗ-d}QxtQqH; z(QYBxIG`קyV-q4pws=mGZA[u &c [: 黢")q8 =p 3v\S8&Nɟ&U5㻃;\Tr b)Y b->.#l`8RҔAoe\ %arGyeY}Ơzo 3R][p= Z-"3 w ]Z#2<~mSHwnܬ񈝯Hi5̧b>"CL$;3R? R!q& *T[*pP}02@F q7&k~s+"ECU:<1c8h|ү&4א]FB\:uɊ^qYzZ p">Ϝ kD0`?[QpjmJK0UuYetOaun{J;pk%UuM{c)fQI5IT幩N`v0|wt%B8'/0plG*pu{ZG FOTIQqhZ +L]`+DG2dJC]6_u|#CC?lJ/YHr%.*+^Epr5%?R"O~k!?TR<鏸\)/$C+b^`k,(K~hāꯎVR_oAUqPT?[Tq}.o5]S +Sb9')ؽ u;WI%A,E=rD#D +]?z!~e '\>r\Ë ,|i1IU?:N#Fi*RaSxF +D =rB($zjFx鑓8~G:/F£D#öLkީxVhT$% ovPq/&j>׸Z]ы~saD]0rfx\P˃? DSYbELMZSHnSGClf W `FN8-K> P_1yԄuF0x6O -|gTk;\z<_|3%jY]JKdGLȩGwhڈh>b Vn4/ǿ3b)f2>'ې9)}mm(c2Υtj.iV< 1W:Q_(/|CD0/30oVZr,zEFqTogXK_~me@ tv\asW!u$" v\Llm/RY{v"W#oLf\m_F ȿRhEo)YnORJM;فսU{c- ohUmmqA"jղ?L\/5v^9A`aF E^(`7+*3 |-}iHjT1Q1V¾BҮ +EgZ!5b3~AbT.f׸68B7ԏ"F6ƨ"תpeK"ޮai굘SOta1$n%''EO4=ie)i=y~&}Oz3Mf? (,@@Cփ=pf"%nJE+,_1ȇnFf<Aؤ&)%p S$56 ч1V7:`}"e!N]x="AK]*Ȕ&E,K\:QrL*@_UZ (8Ahdͳ]_kQ":BPp&7O3釵ÔBgO(|S58Ut1C30JBNWϤ|{ƫ0+5!t!WJ׸vVje􈧉"RJ=j;\h2\z,:O$?jpG>;$H@DNM(є⺉h5U4ɝH9$E829̡pedS TJ B:"Uq|` Ͻ]34=^FXFI +C DR D&@K >Bտ͛!i +]0#4RXdzv6r}9A]gR4jH&Ty/HkWz7dz/Q{Ty@Eqel#㆒d0Bu&(6=tQ݈ħnH&eA};>"cåeRFn;eۢt±|$gr-yb]Hч K8+ 11|R~z=*zZ݋EQ +r/`hyC#bGiIDD3A +cNJ?&z'l1'@ǩ] 5Ye;?OTIEñO]3β ͍jCV g!'Ik:6wڱ-@)[_2٫[dȽQyP`8rkX$, +[K Ca uJ(b-iaFotqsD.3\񈅹IT$URud3 +,.3ojuqm~t`I[Ýtk(09)ec +Pb׋|Z$fsyƳ{Jow3v9*طb6"EOZ7bDK1ցdqT8\^w8XHRR6s{2JCy/}K $59` \Oy&@C&wRI@;jY[9@hE` wC3R,}S!4sêDF!"' +w1Ϩ# };Ri옋0/) .wqi['V4e69J{kWL&n>fNGǻێ^YE-2{řBDo/UBjPN0盳KԲafP;YN|6%.@Jdª< |WPpʤCR[R"HS?j۩e١mmIsX?R]?FK7^af '"#}у!(6/h nY!B~nHM44_P- ybtpңU~yhC0g(#q^ , ++5k[E C0l1=vU>ĝlŖ CO3/T"Ŗf.:dEw[s,'V:Mba[ݥ Fce 2#8دK(WyeL fq[Wau]Ҹ҅|U.;7`B].#;͖ckrAHy0!iJ\M;*WاFC\NbhCO{G11)T)ܪ:H9HV=`]DMep]72W_feUfP((hPd]pU=q-DCO[hZCwsĝ'x*lPI4ԭ?}V(Q>.Vg˳4SZ +e7<|W@s:rY'YJ[Ky2k0V[5Yh˚#1?'-iA[AZ)E=oMBIòѵ.ÿЏ*/U|@ˇvްY `:esj>9 MU"BlѮ~'ڮ2Y8QkKsWS.ջze5fp' ~N;:up`:F3x`E;>+ .[p+S~? +$9.p++Ìr4D]g0+"˹$a=됒/9d -|>|:FGX_Pؖ [^X79g@ ey]R{s./Iq+_A {mܭ;Žfz8 m3E2Ph3* +kU,1 +bJY3Qh8kBGD4}5u>Nb *t&VtA)1 ܇G&x<2Γ7yr\:B84;g&vKR<;߻1C9|q _=&?YS㍩W0&~yR3ߐfWM( pX7, 7GòHyp^J{epzf=l׫~8 I4,ۛ7ԁyjo0'4$걈 kᜇ9,56@W`^'wTEʒ2uWd Ć 2{Lm g6s:6ϊrkg?q^?eJd>l~Zߚc7ЈxXb$\GD>(NGgby# +11%gbU˶p%Rn]XiCzB,Ⱥkvjv fEꌌϟp!K͉w(SNf?m!R-On.gQ`ؘ0ML|_ZU?aX&"AHPz:\p؀ &]:Kp{M9bs-m ,4s{y$9 #:<%\r+P7q}<]BpXlJpX(N´駬h{0[IX"7zR:VJB5B]W +2nsȅzZY'y&ë3X `+їp&8p'ī)DXqɀJoQ'7.O(3 ܒӶ*(y9?ߐg|{ +$]ZJ)mďuJRRJ-1OI ([)fR‚d82zꢑPQ>L +9_KVIuH?%k1C!] 5)~f0悗9R8 +apXYW 0D(mSVuP +<'J#yz8@;;SE6/w@ր kgKOeY.vJCf]}L&"j4ul@>y=՘_vW26Ў<.J2눥+l?4<>ODws$2*?_;}2aB"9᰿lBujob0H1M}38]/9OfVI2SLuk MUUv3q莉?Y\Qx!oޑ0m?ZʲY23;69sZW*03̚[2-z9"*F2[VB܋"BX>Ès~^aR֟K}8LSmQpD5pݏ'q1n2p%k1aYY/9n=SDBbhIྫs8>,U"*5]9ݞ,8 1"\c}-?dsaN"F/v7;\xi+WnOtX\Sl DYZy9BX/lnLPԎ~|YB1^tl`5BkͥuupV4Eo_Q~}I@L.y2j-eHɏPhIsՙ%W`5)i2_+؇U$x!OC&L<0Sp3a?qZDF{#a!H iqkZ$AURm.g֯V"h("+JߍxQzWJ#o ;6ߞn/o_S0x t#0X d /bCM%&y8, 3gkUsV째c0Hq(45 +vd8C ľ Pό޵C\hf`cSR6LL^ZK/_F+p +f!abG.V ?4)CCcg|Og6%14@gk +ypB%&(o,0}\ #-)BsO>{_*\SCs1VZ$OC ԬABICjS Wދ5^B4qLW8l&Q6zեJ3Z{bN?%?Ý_goBr).5iSى8 s& ϨpkMXͤQ?FWraeaÙ8o0[bOKBǎaZc\dPu5'|@㘃qnZb>曪%b2a ~89줶pXM#](pރ\-o\v>Xo-4K!e~8LI*݄qX.0,@$ofO(f\Ďl -I2h +#4_IfCy4K)}IVfoO4ϓFT$& 1<L]IsN@4s# pXi$x{+btc3lqSB#+eaQ{)p7)Z,Gh0 "6s+~p12O8u` ~8p~y8"K5$l'[! [4(LR gEO3.T{t}pXuUhᰔ9:gzTSs.8nQ9:؆'F*dC`~xʂpޱkѐ܈L J@s|8qQhLa5 }hqmp؎oN'|X^]M;^KH+F= ا!elhIh~Wc_0)^ eUAf5K.ʨ! y1G=l}c鎭$h9cKoRJ.5Jl v2܈i" 5*(LR8 \#0oS +Mm'+?|rLm-5w)|y2~#3N&2k,JP YG +qƇePZd,i^ñ>&>8(A-$bb5o|lƭm K|81EK*rRPa;Qq|8 5=f8=(a =l]uSٺ[,jDdnOP4b&>Aҟ5_#kwg~|LWI%~g;R& /;j@jE):Vzxi_pXI_p2'aH\S$XoW.hlkTQ`{nreǘip.: TGc/ eg.w AaF0k-L5T# ka5!a!%% "0; qj=)(88,gZ)8 D'%ⰤOsy?t=v}[FS>(Qo!k17y 5ϿÎF-̬f9dTE`4Zf56*ïL YYmity.qp9@^!Jk + ꝵA.AQJ%zMl5_J Fd5J}?th lexnwHA8D1&; /./JMRSt(dFӚDh +"#HnQ`)O~̔&}6HLnPNaFr4䨴?d9lv$?y~9lTHzRkea~8̟X(&I%ΎfG:TF襻SYg|B0C7{$npfAC#gcb۟bZQ[qTizgքE럭)z^[SJZp4)6fba-{0)<}u5 Re3dkm[O* VFPIA}e`7{&_L)vY!Vȯ0?yo&Ma*ÖYE9(~I06=4lJ0ԉUN &ߥu!yfo@^`7Ɓ\7îTÔ8D`LU;\7y  pX&hꀿ dggz˥'pґpZƿmaHh^%CaZgmLc#Ε)pm`hawEa/ۏ\C<'kp0#hLK΀SbzSw^i_x8,(/ua/K1ؼ^blR8')Lñg$܂|5h 0w?)8 f}8L;)88 olt 8y(=6%< + h0sGj/{.-9?57ʔ~5u H #I{ʮ$^d8lE}ulSា-lepxZ&S5MI{Y^iUENDMQ%2+ g tRjQF +&{82XkAb +e9X-0S:2^,H-0-t;5-IoU N,pح}{k&eS :_ Ym<L?zQ'Y2L=e쟹fiU[ +e&Jn|aƸʇ js  j-`?@| 3pE~ˎ6D ^N4#K%oYv'ҠD:nz>)PG'- )6dmuƑ-96D+X&H;I0܌Tde8'򜩔X%EDʦz4E*WL9V0iODDaЅM.a-p1hfp[Zurp"Ⱇ˦pؿ~vT̨a:k-YoH>0&RGõWnT wNd`lKn4CؼZXJuLld5MxrJQXa~\ӡ:Ԇ5R7 + MYV*QʔJZ`cUKIFv*/`0Kt /b-ee<a&i4UR#xΨ ~KE?cS.;e3Vǵv>>~I.Eo1XX "9 +t^rqL3-E^KT/mw=5J –1}ﯿ; +&ިZ^П,= :`6AF+k"ߡi*920J"-;o @ػj3$g|gؙ1f`+9e[a5CHMNvW// +f!LV̜!x n/ot,q4=M7O~ +| +cwNU+BCioWnjKJh@.o%Ze:V>n+"=vĪeF -uXCTî~#61+1$IҸf a-EMu3>f^sQLtuDLUY9¼NѨCD7aFܡ)l;I$ȁU`yL^ ,C|m"=ziX*>,B #X44ډt35ͱ;6ӠVa\X}-ޛ[NG?+pڊ0KRjL|P0+qƾm*FU_IcgsGq ary 2׌ޥdC`/4@Ү&$TabĨ@&͈Jwh!_ Jp$hj +[7ܲ4b\%\% Xhc௱iV+Z]uf01COX1?s=^o-E>nu\@>s u=!JfpjrWʝZD~xp$K?l@Y9njh]q*vWZ&KYH2e0C`GorO&,,Z'ո+B3 "A҉#@<$%?g{ `>anwHza +<Պda[<~_(Ӭ-l 4,X.c-0zx҉D;`dϷoX1LIfʢe\?c2ALË8#i1Y[(/L?lR|9˕vw@u&ZODp,BdJRsjHDhȁX?D=0\{r{]=F}[B{N{RN {n3K;G>1H^II#}%};OQG=,/`"RI/">~!}6__`maۯb= BX{|$Zܗﶭ%ZG̘P!o'_udxA% d"!ñflg0Ϫl9UzqFzy18V/& A@g +Sާ-ht+ j1 ܚ?"vhUgg2FW{e::UZ2yZ+qaqɗ O$WF[Ed'rbr4c&2(!3@ P~mp,y)BP y ^)@bI"}@wYc,J F)^p|5kk;Nd$ٌpwccL=5z8W?VU6Ѩ M3y%A'*TTY%Jc#즪CgeU%8br5U٧E՚~0N|O2$ >ƼdHƨݻN7]uH",%4X,}syRC,NYKzlB A!:ǖ$mTxNSu ="W!J ?+,<&߿sS]ep$DrGv Cѳ*gU՛t4JbD >yjXFI45`$O)^V$e1簒0 ` )DFD'E,p :xqDNRq8rqL(p$b8ʎ\U !}Vb +(&. X a!C?+s5_ց#Fzig{ ]! j mYDHLuln]Mk]2֤o.hEL+)1e X-BFWHG +q$lM.Q9*@'3 pzsb + % 5DN 2,zB" "bF4GmyR<1)ABDL!b<ũ-xXMF!rdd&]Dci%Mp_HaHùI*T@ v/v_ݳ*S4h.-Lm.˝-Y\2X|*L0J.`$Fu:a 2(IT2 !h 00@ ( H0d`"h0@ <0. !B 0 +* Zf$ 2Hl@VHH <0 A 2P "P$(vR[AEL@i@B @ +#B( F$0x +(P0a`z; jpAEBBC}*6 _授0aB9!a@(*(AQ!l @ \`XX +.pAC1;[fiw:. 0ǭ2"^ZV@Ըnl*;hz9C۠q +<ޯatAՊhAI<>MB.+*#0'Vdy^ea9sweW0&!8sDf3$0.dja=q-CT bt,?Fy\hTfw5ż粒xdXHV 9BHdH']w36 Aq*h |dFh& +SC__"qѸG)uWx+#Y(>qjyF4 Jt4r?tmlgaF 8W_ZyJz*vȋXu̬wuѦGUYߕf +ڸ"Ն33{p:JD;+*Q3LzM]3YΦuMUg芡8D$5)B3 +>zes>]E'4bxWOҴJ,L0U^;1H/7XOUAC;W +]YMK byt*z?O*yjZ96l"UYNt" Hj*f6yP)oň|<{eSI3y#š[Sxbe* &\0jfVie#ǙԺ8e}2#/ϥzO~2?qб=cJ- F}#̮E*s)f:^fyI6Q +wVrr\%&{5BܭX~JDD+:U֪a} ְ6n7ej +=WP?L4/ͪ?pxfK|{N+Yz+Y%`2'laaȉ%gJ +FE4MoJ䢒Q_=,ylIe $BAqXb"O gbGD 1qVY9g7W7pl-~I"l%:%gQSSd}3/V4O^cwuVd|;&f]4) ٨3f\z-?x)ah˨}<X] =>#! nug"$4Ώ&MJ"YKRp"AI8(C$^24!IzIBQO@ sA aB :I@\~SyIlKbJ5,RZ4iH+GH +o$Oq +G[8cņ@%dHXPSĉ INR00-((IdHX("tdP4@!2 .P qnZ"q5 N@fx"AFJB0HI'N`E)q#*)# d|8abq;sa)A(DhN@ `EhAP BpLcB !bBN1m +eRJTa܆k7"wfEg+`\* +hɷ 'JQE@_)| "u9 % ɾ|TĖ{YU֌)P)!>]r;=DŐ2@<_ZXMڀ:%~@DJhDjx(*2֡eG+i6҇)PL&1gxZiظgDXER] qCATՠ坳1 C`&ȑP]F5y2yft3xPB?jaEH'F;32HztRq !bS$ON~y:)q]j$0kNd`b\Tq{` /@ƃDaC &,'Pk,K'ߕj"u*t؆I4 +>jxc>Xm*~{Mhb-b(6rK*:-=ŏorHLivGz*r ĢT%{pZ)z .`|K 9/5GZ\7 +2.'5)X ՛'x^F@ȯt7CVm %8zXu[ixZo1S{!D%:Jh4.ZbHXxkwIVl *۔+#&˸-eM?癜zSQ»[Q3A cW0~Pߛ)N)}Fi%.k$"p3vT|]مΙ/2( 2 d6_;{K: AwHPR)U[skSyPG9>F't-x{˙eKba2b_!.nȕSdjn21wx/z!zY Oc\c1#?Cu\glUh7@(.s5P1VHJy}w& M.@b5G/xb/jr|Lk1M +o(/)K0-g5CC< ܬ*G/`eԖ` :O,P*6FüKJRuE!si)ڰyj"OUKIE Xu JW ȒÕ%:EAqBW'ӣp$ >Zc@qS2,Pӛtސt:n0)P h/Q&BMS + ]蜛Y̊i|]kuެh+g#QiYO5>]^T8ovF(F˚HU\Pj% -et^{k!u\Bz1:um +Mhʉfp!UNe(> +ɔ4גq[ŭgAq2 ÇJvy $3Ins4Ŷ}%{yPC"g[G{@1$ćr7A%'OQw?Ǭ^ Bd<=Ӧ h7TDIB60O@Cь1<8*U{&C-cV ܶFQ:=V"#R58CtO7x^CCȧ:JQF$"{fn6`aR Q̓zRٌ^hJL c19EWZkt(rV|^u}oU|Qx5! J\dk;0e:56h +*7Vo#7m#fageZEJn\6:'ܓTщN\Yn ?-(ET=I`Յ6`He .i<0iZjWWGȈL2r&mZ}cLف㐐#tRžq{[1 Uk1i׳aV6U(i%XGbj`5[ff0rkMwIlbODjl  {;'H#~$DYrgS2+ϔ7B蠐0NoMn_w +(EM hSa4F@$'M*'g`dq~JqC֤PrĜEPx:)52Kvc@.m,)Ff8e\#:CW''#ljFB8qMTf2(Z[g#:ҧU7Jƹ.8nB +fWXL7BVgRQ[wZ;FAEh73ll7!zi@ڛsY?}:j\+7#;V)$T5}}Q $ ->fsuK^(YJ8PҴ (=C>Ӗ`Oo(\z?jgzY+pVa>+ + av??U+Nm,ki)< Ta`$[=~yc(B)׫ Trz^cF\~W<)H TxSMһ`NU-}g3%K&*:p,[ȱ.1{VyYŠ{$eu_! X; X/ 4W;}B5C)yЙf5YY+.@Ww:߶@8J" J3U6Uq9O>"yw' 멖g`όZ!PXsnK,6Syf+w4%ٞPEi 0a{ N}IdJ}d/8|e$/:9e:{}{I+n(u}__v|_=u#U J>d-7my>Oh>. .ҨCߝ9H_YÊt܂' 4y5)bt$L ׹w <!)6¸Sԁ?cGs!]Uş '\ƭ_ro jIcT0b3gxA͝)-(t;8@j. Ⳋ PXU6* l9 5-?"BkbD;߭0ZTq..Kцoh23EU^f}qv[Q_VfEZT#"WRv]7Z>G˖CB?S';,%oxn p(FO|/EPaCeh +3QSc 7yW)." 3=.>*gd;U< ѹD2Z[}xqlGţcCCE{Lv! I +i`L%Rv7xhi/K%n,RQi?/c +D{}O#&cuhzL9cОqgOǢ8SWB!e8=THmL)/\k>?łzIcrb*DY @8z4vuEq8/( +)خ.ӝA90!z4)/VaQ=^ayf**ć =} +sb ,YwNˮ{~9/n +0a1*R; +!0qR ɓMC$e)%YdT o !GB Z ״ҲҁAkȒ!=0b +ndj=aLfAM=`& HpH` 4J'5kPhj+< bJb-N(!ˌHPb@MD$02qf +.ɼMs4l'R莛L;aհ8L 8:YU}V|&`sPAA,,VL6F Ԃ8A +"  4s1 Z)snl*YzQ"J/0f@B,JS|=dBC|t6Jnp"Gk,&e֫!G4LI%FݸuX"k9ԡ能\ڔX ,efGI=D2͔$"~D"Np0\PZ; +$q0%31t.pst1jw`QU͚U%O"'RJv0aphB K  x}X̎v`0Xܪ!MJD=F Z1-XlГ 90h-$Q֬Ck;U*B8&*@ځUaPB*" lبa+w SC6I]-K31UoWLCjȁAmS8`:%mPkU4xJDPg+!gŒ^STUU16* +6''s0TsJ7rg4¢e&gSϭ~x0r4^JB]YU +EcFS7ͫ3 A OWi,BD/ c'IΒDeK"1;LըFwo0l=" +HdLL$Vz`0~5!j6z`@(7||ވ@_1# +Qݢ }g,[BeG\HaǩNa)PWazDr 0_Ӡkk(ACM!n\Va5h`WWApLb6Ib90j( t 䓩;u=ͳZr5)'t8Ƽ"Mho<^C! <@˦3"VH™q40ON$ J$Bp"ӡGjp1M9pEHAMH#*'SkFǞ|1s UKQ:!AjɶjHDl[ 8@:lP֣hSXOh؀}AQ /1iԜ^ESch)뒵&iBkQex)fcTݢN''&zhlML6 +:0]QRJDK$0KWT) Hk&aNS< 6 I /L$dV Bt . +[.6C%( QhfPcDjΊ͵Fgl>֪K(TQp2F5ajjd\HuIK`馪d4kFŚvшJPN]6s1l e6cX*#%U59ѢrdBJ1d *c0RV`o|SՇnTUn2I UBN(ȉ0(HXb*L2I& Yx>"!qE޴\ 2f9%*)ɈT":STؑ :UP;=)!v) k٨9uL H 0 H 0@4$8@, xӄdTuh"FN(U3Mʖ/Ŀ Kd&'ZnLTx'h(*E2w&h0aK5fJDdjс"v4 9eP\**C"4jDZ.bE04`PߋB&{L8A߷fz "t`*9j-PCRZ@{$4"U]I|AQϭdSrrxv"11AnP;rΥ abX+NB4HFw*MUQN"!t*$jn NQBUIӴazlO$">9̦3T!/}? Cѐ;.eh )qia Hh$_ Dx&% ~ZiJq +焄W*/ VquRs`0Eh@WӚ\|D?M 2|zy05f?IQ?0( 3urLN`D90 ꐌC˜k3eRѨ*iv@Si%*dr){6PP(8I ;00k&/xJ52a1i u`)OdN1%6 VHfՌL ja*1-Ozǰ+R*(3;dv#5HvQz~`Ig~4BCψj/5⦶ubvD%ѡ"'BGͩOy!'f?CJNѰB[pid6TXB#Z&Yabx>0YM"ȅ?5̕І8XӉ)J8^V:49aBDOK '|R*9k +ZR\>#~pJ ']<"B^ rLYZz)wOVQ_=x=*& kQ">stream +FFQHMgA>M,I'fpzCQF9chޛH/ w4UGH( + =HDNCBbƆr g;(7{" +JTjzUS4l׉X (UXo@!;Z8m kSH0ĬȦdgV ˌ>B!dK&brrL;?#6 [JuL& rb2C'TA8ف_6;vj]Qi8ۼ(2qS)&Db$Bp{CEU4Z%ch"tCC~_M~6B/>c% H1߹CF(zLBШUǏ"W&d^suؚb'Ug>kXM݉,t莥({?͊ +EDA$L# N95+)OT/1B>BN>и4gd&\:$j14FVcZ4aդ;y~Xwz4f +Q}펄Ƞ!)KIѹ̴H]#ѡ= B6hk\هb2R{3n&pҊr6 +pNL;{0DpPTpE` +H"9҈u:8eVCGr3bc+S9Fk}؝`jQ P`npadRtaG72f)Yo{hyH:QXN#`0"q y<$Do)@#(bbG J *Q\Lx,ņm!1QYc|8\Cα,se8)5@h hZ>!کh&ZjT \(+qסOf6wr,`p@|@FĚ\gk#ŻqV)z2 K6ĐUPB@B3ɫuGmPZWD&K[x.IQu'a5WhݔSHQKdZre([$"8-DDJ$HA!1H de`(X &@x ݁AhTV z +$XT@uG@ ˂U (Ab +*D(Z"NnT7'oku+mHFD4MƥEyKK c6(@ `=6a~xLo +GD;ʐ?j5hTqT:O1X TgѷcT+:q}TЈ?Uaqn8k_6ɐ*5 ӲrQM|DA_f.$oR6)XQt +ZO,Ag,-? \4>HBhK5'F(O<V{UCf{N;|Fߣ>ِ;)OD0.͟ZkK 4 + )!5 "sXSƺn01u/Wd% &(H=q."b0Rb, 2jh4oP% ՌMh}J +ϷvlT1Wd<0Y!4sK|TLSAdلB8Bcy b^T-\"N61A⨢ 1 L:I2G2Ź#U^ ayeHḅ3BDUS1J"攕DE͌^5)]K$S%#cX1vbƞ}d 5C.wPЈaAgi}A9ht,S1tTģ*X[|11-ѝ\H0 aI0)FC +|j$M iL` +|$,sPAcA'FEQu~"T 99W[fYVNg?VA*BNY%C]HҦNʉ39&(Si)(ePL.a +=J|!{dsh(Ȏ"-dsP.T|+x1#qzMgh +c?Dx|X#Ba8dZLkY[̔!!}5ITt-zq 3* ҹcJ0*Q1 $3 +Umtt"8!ͤ4 [W-*LU +=*#̔j-e{z,.!M/d|΁ҡϣJHk,"w//R!N4P)GjBsn*2EYGЈZRCjx41.T\ʘ͛!V|f&ޔMRgBMg4TT +"G==1A+ +: +P +zP`Y'TJqVWQHqf#h! }rzMOUE!_،=AŖ&ө|J\6PioZ_T! jE +-T[qgy%pU*&m=jwtsk7EY|ET sÙUP9IT;#W%b8AC ĝa Mdj,j$n*ًɶ Lb1ONhS~Ȅk=1K x,yWq&C*r%elfcc@&8S4Dd QhF38p Ca Abb +o`3y?.+D-LFؤVcЦ5{>DJQ܄St/3s~pA$:5%3$P.Ζ2]"ʖD""߭RCJ2DEEo1w3]i۽-> sz[aO-j '-Z>kQy[EQOC#GF“m 1pL-˘3jFoKh@wVLڪuMF5†HPk rq._Y(Tw,`TGU6GkPe3EѿvdM-RC]mC7۲Yh2u.zwmk+:FV.-6s92<|ZbsOiqL ~hŦOoW;O6N;ُ1D%9LYMvit8$AyS~SCBX,[_tB4Z3t+ 'N5|Ÿ&f=fcؾn)󤊝\}h{~FVsedcCʏȳPj2+6<+wHc+u}Χ3z&:w7툙L9t3YL7bt3S@6j[1 +TTjv_")؃nU鞧 HezY2bGp"==6?x3;BrFE8;]]ϭQMѱ[-S p*?)#'qbH4#('eWqȢ>mwn #U i=1\h49Aܞ,Gb +DԹА|9>9 &%10 *9FK-52fl \|[iOqEA(]W(om.Jm[dBEvX!ٝwq]0Ѯmgeu~mہ(^ʊ-&|‚d[OHqMɣmW)F>3@Izr#'P7ׄ50(I7b-3;Yjj;X&TDA +B63F#";5(őnZNkg XJI8ھrf]e-n&I?dS>v{{Y>twt{?%.9|gpWw'e+"JY +Yp%8,`gїO8zYT/1PW%? f-{Ϧu^rK8<ǽv}?94TJisyL@Ю<ƣ 66p2kt/㎥F-w%DwelJYN9xaBIDjDժj[8g(r-FŎ`WC/Ilw۩ K +o$C;6Cq7֝ܙW;9XBeGތZA{Bg4`Ǡ r N_ՙ֒|WK,}4#\lLK{,w"״),6S@sD"@R!{)#vdنPhAz<4Ի5K%uAתNEF0c:nxR;#6mb\8G@p}[A0y+Io+aBNIM s* ti2T2XB_1yͮQע9y3r->-9im\6ͬA3!VQ}W٣^~VNRIwb+ְ/5-;XK VM`WJl䊘d#Clޝ TgE& + + ?M!pL]:&"nq,ˈ? +tWس +Iðm9cOErE#AH.C[02$<-dM bBdCstDN3G2#MES/d>AJg SbDeQDT;Hk%DAUi4ҋCFIS +xx9)RyH`!$/Q ,b 9pf2YMd ߿DW%KICo*? '( u>.5E$fYVHВ2 !JeMA: Ҫ1$C (vXWfbg] :IIIrzk-$>)ylV0)Bm v'Ӌ&D_r}#bX"#[ 9HjKOWxAbK;mSmLs~eA'D#Ց ]Rg,WrGуټ:dnjftxx~^ Ԫc~1&StT.bh/ d{ok6ydr5s&^Yih e,fKI+dSc;{Z܇d@4k)BO`'p-sSidZԓ!9>GNeD(\qPvk0{]ԨN!/6ad^@/2pYO7 Z!fĚf +CЖ˩bVaHz`ndf2R-Ȥ'#$C1^ַP䙰U.YRR1r`))lSZTR*<-M4&M@sebٍRsC5REvBxѽ)SBE* {R4ZR MDl<\C\h]zU;+UNԕK=$nr@,,U,`x,ԘdJ;bI h@A$؛,uѾI{y&J˰68qoY>Ȝ +!{I,s$!::BNrW/fY\L[3Wd8 fj#""-ӠS=_,{ ̂2',VU&Y7c`"D +􎩔OzkE8F!*D̋|b4ITT:4Jؕba,xm%}QY½yL# o \![:Y* r;JV& e,DZb9P޸3  IRPS*PQOѷr.VS_k#ABgQlשdn}:TH6?(|44`@0,xvj.s^˖n.>|iOM?9#!W!L82r4DpZZs nN|iWXD,Pd~=oV3}xCFsfȤF~CTExZÑ~/?ΐpoq0W#!Fo'j5+v)N+\GխՉ@3F;PA1#^N+P~-Wk^ɤP+!ěAeWrwsuW۶X<**N]R3QET< +ўGqHT?(K>CLeWG 2,i@ :#q/y8 +=IF]:}h|&(Ṿѷza2>\w}7+^3i sJ `b0N10т,V"7tۈf~ZW.OQ&lӝ3a YM})tFK,E%jW!'~ zyf[ =iV@<>ت]"&j(}=gcR=D+D9h]TL@+Ee[լQ2஍o缹]oNt fH鱚[˰JYA!%9a捭sVNW0I&yڨC9 + +MTYGVcoKݙWz'2W!;AtYim?v^'jnudutyWYeqVѦG#po/g6CJ^I1|^wL=O\UCbaP lS(QTn$@li,1xV({{x " xE$ 5r@N@ gPґY>N'x+e 0uZ`+!5Q3uQ'@oth e1b\ k1qs G<uԯHfgɷYOtu,i1B!F:M.pFT3Ap7ލ%jj x˯vZWwQv>D󯘫ǣLL3UmN}"ÓW&]TG)r`!x_s0 ++Ξ>,,^X5Iץku{F-nͫ]q0LŚe 'EЊVK+`GMᒓɌG*ZM2t/Xɛד!W$zk&O@MCIHhEҊ\$M+_X22Q9$$'9F(Nƻ +*CΔ5O4 '/d +x&v_*:OSȖΙU8@L|}p2+f''\Z +/,.$>C#JCՂ˜-luќazu7.oŢ5\IE,k"HKy@% +3j"AzRo(%=`:ܜ1ʨu c@SDuxXG}b&u3i+Ҫ6je + 4 :D Wel$;QcNbNב +M$CX%yZKZwSd@s0Vo\_|I(={,4 zRHІ; ߑW2JtO}'*ĵ,c5/ٍ7ݫQC//k%qj=r2@ +DVD&B+L^uw):Wq|<- (!c d&ȋ|*I)Z=H|@VIA΍X e^ d8~-pMN~޷{Vwj5[ ɰ©3-5P\TJϹrP'IH.rwOpJ_MWD;iY tmV1y~t GwHMnBDxV:Q>ff!#yVUs2a*t݃#OJ7g>0xH͓'I4X<Z!у"Y^,!'))Loj?קT ң_/A W,8S}[_^KBz{]fR ^U1mJs]4F/y906%TxO(%\ _ 'LU_Ϝ'c#=p,1U0vlm<[Ry%3"p@T+)sS9=͟ċGGmkˏ+#'-M`X-mwNjhž2ehIGLYtk IyXl&5!X`U,+߽dm 0z:S oˍ%av`T[JۛJw*fؐFǠE+tA^5) Y3G`b*񬭸T뤸-g"/\NUKzboGl!Vp#u#b%ZPtw] ;Is&v6_`'RYM/Zeg/;G'ͧD jwrݔ_k^"7n)Ff {"aOrmW;l(E:t +$؀qy.V`1Be@HQE )G;ܢmm78ִK v#z% +_@b%^!ڙtcҿJ@)qtÐ +5a>Zğs <^>p"{ʹz:cJ Vb~|?S ۩S(.5J)D\ ?r'$VfJZ2w;ѝ/0J>hizzOp"펣ch)#5-Y h T@ԾbAèAK t?g-!pw)m$EWNc4ގCtJmHBzҽjMj\Jmt#W5iR*")$cOv4DOҍWp3R?K5zEtݻZ*OBSA k{p-(o^~4[KS;wznh,HQ-yXK:">Ivbw)D[L.VO^!VC'ׇSX=FTHi\dM@z~:V0\=ơ\ A@|<;EM .o{"Gʧp;Ʀ"z騪84mbnXz ٲkxJL +|GZTjƏvą,Rp)$W'=$!KE۴>. +$g G!R4ZŚM63Ra0%_g1U073I\#؝j<#@W~2PBGe,g3KE\ZeuxFYLMJoW H.,Fj|vGytGt/Ò~Rr m$A]kv dB/XȮ~KD%H̊}өx28S'E&$cɚ V$[yaM(ɀzul䖊#(H\6|qMo^5}Q*p"jYϳ|5g +^5zF&z:O7gHQoZ}|lB0ha<9|Il'Qdg9 ?Tݿp hK#C N8]ezjBFI僯F8wǮVV(#È=!"`XFUzËhE,1LI{ 10pRq_CcaZW֛hw){DSAox2 ,*JO2";S7w*=Ks,Z?b4 %/cH1Tr 63W=-"`}6.ހ V =%E=4lxqA*ưO}7PŖ=9fSy`d3y:\a&$z#^JުG(_kPr8`B[&iz WpgF.J0H? uoT[W>3q .`\ۅTu#__2)TU7 _|BBI,EEx(EL䏧u_oSa`8(9s[#i VH |&Ͷb +W>8p]%P +~`9%⡏}̰U * 7b'4>,\j~C</ +tS^3F#v!˂D!#~*qxU.NGnȫ)7d)Yt4@I6PK03333333333840midZIʔdroVRT.7'uN}ھM{SHF}M|#eB"*"IȄx0 g"Ϯʍ!JCxјKB<#+e%VC=B֙AZ2!4à Ll莲w3L9vi &_n:YhP *?TI,pP% | BPq -$(\pX$4p YO$ $:pAUUw +-pA +x pv֑~zT 2`P.8l@Xp\x$4 l q2 @Db $5 +dqi;h` ժxcIf5b>43fQڒK]&eLCa3bkJl>GbPfddKî2s1 ]F8KD%ҮrPQN*@D2jD ^({A +m0IqIu+D4Cv*u^EcpXt,R\9{ o%޽6w+g*TbUēKz5vݜFdHy(6ݝNz˴ɫ 3s9+)%5ײln%v*1LeFR#~?>DH3؞Ddv;-]mz݊xg2Hڳ hf(9ZfU:_'q:4:ͨGj##' $k]DS됣2!>9ٌu785WoϪgRb<]կڻ8d徙zh,M**FGگnqHnʜDBcJ?3.Q5PbmLnh0vsBʜjNUfW2=3o b3Bq(, ̮|*B6 7!nt]fph$ՌYnwa*rHe_ K!ᐘ[{AX!@LVKlX8\($0%Z4X 㹍SlFF cŢcYɔxc{]d2bxG[v2!~]HBkcDr eh7s=&rb{b:onUVQźjuFutSyt2)e\VLqqֻIFnK,D<v. +?fWE2J.MIGڑ٤mfib7^uE62f|fXY&MSHfY ,"澗 5>I3RsD6eSQ2ʪU@uiÇ.' g 1DfXMꍊ L]}H B +H šd! ]݄CƲ+I̙4ЅT?cϜ@fnǩѸJ$xD!\ EZLPhP#̊3td&)vH*5;J#t7Jկ Pkjj~[ ʗ<:uBX @PŅ($'b7{GDzwB \GZU*k 0 }\ z:!RC-";il޴nDD%XPwf/%yјW&Ϧ5 \ CBD :ݱO lᖂ΄B!ZX%ڂ7UNHR 64lO),QP - +Rp0Ig4[f[4*\p'DbPP +&^Hb +M+cFbseBwPƙ>vVAS)bA +Ă% +D [ q(,*, H[usvR">GGQ;d+VG2ymBrpH4|AyW?Yޅ Z#PZ,,MHkX«bEXWc̐ .%a}ZA{yLaJOLF]{K=w BtVܹ +HЧ  D\$LaËLVˍqJ6"gSs'ⱌMWXo~ pZC޴m)1)*Q)g&G;yXgGR`(lKꉕ)ZH'7ڠmq#<چeZo q i465RӠPe=v+SR+z=9q M%ã;ə?E's~"ܸ4 3i{n 9xc0[iM>j@Sk6\l4ӘZ("m.1Nr+nNf~.+mԺN!4KK"~?5ݗXT'饹ayesg#}ICe K;f&VsD&yʫ}~ŚH\i#ؔ"=%V"|z&-kLԕ_Rì+ՕiDuG2s PZz%_!C#259'cQzwlthGK ?79w-qZ|؍}]U1BfǪ!YE6#a,Dvv9Fkg%"Iњh*6#U8 |J#gfTs yyl0ц3um1iҩ!ӏ_C#O5_.d9.QcolƉ.COx'&'c'߹j UF kIO%=Yڏk >iI퀁)!q]F)!3٩X*|we&47#z 1T+iOݼ\cl5si|Fь9pHppa8x2j2D3+GU psv=isֲd0HqhăTLvhZf91"˦?Ma ]t+;,tn d64l2ٷ9Eb;@Ld_q4זl19s}̘@*PP]A +I^$Fx*X [4y QIjB{xc)kd#ȤEFF\Eg1hj#$p0, 8$@ bF d0 0uB +8@(`$PH@pD8p +,@6C9ir a1"eP[5tvQ7_~^!R~NXfԴL()R~ط!TGI%39ޣ8q[96މR\ Ȇy@r]hwM_uO,SH(Z MPTSIʑFDB˴DIx T%"ę%M(phq!*ĄΌH uٌ SYkq;Yo vz\:F;UuT)㱱 ,8@:df״2u(̐l* tEXÏ W"o])ө߲TLxvdVgOSRR>KcWC{c2chhjvMp1Tg~'j!T-IeJEcıq)Й..ERN9$_t3ilSCOYf܈0PdQ1/ +J# y.~ڙe4\" j0S*7Jc` h#՘f\R?$.SsvT*ث a +uO\veӐ<9!sy p;kO.=qi(~\!'J&?!J+p8,1?:뎀х* &>; X?!s?eޝ1b:؉,w'f` pYBhWs N~67.Z:̡Y ~dcQ +DyIKIę@?IcF +( FgM*u܉DӮy'EӍȰd/;eϛ;, {IFd:$ʯU<0Mck[&;,&g5J?^5}3l}GUg" :1Ls +WddLr7AwيbXe8<-tbm},7af`<(Ym; @P*.ҏ)k."z~,|.߮ё)sBlvv엮x]> k-][)Gz]Tܑy Ϳo+T~/U2 p[K!%"+lǡ|َ`A2~B&_xpKMvPGt#uO _c }Bs~6 +&+aSs 9>Ѿ+(||n\WpB=O,g*Tvifx1cb*]Nt]EKc&rtuRkp?ޮ( i`=BKGϜ}k\kМw)ˈo&]M#Jog^x? \\5vVF; +b+1J\U4M/zDEVEiGzg^Z/azU &;kPoS_=uW/&'3~/:{RMQ?½QLH L/'1×032jKdz@V^'.!$kf,g[p,9BGGEpTV8a[E?Q3G/@СfWpI6>z3"Jg4l4!IgǛӟι-m d RNE{K{5RrRP0|V@evݸ>02r,ŤN enL#* ~թw9IJA2~GǍMOA c2 x!{T})! dd1[1-l*SU#]KP՗\98d@ ]%m]~ȷŏ 薞 8{oتyTMTw(W"cԒJ0S;K'#](?,@BͿ +{&lW@0eTP T[Ti@4kiQ.Aq/Ap 1L+$87G%؆)s:&+K "zsDϦ:/PRPoN'xKFAϝFVt }͹$7j`ֶ~ `|[X<&CX%1ċRGʚomZF:/JK E!ib,CHS9T6ԻCڍ Pڙ.|zVBgqU!ָb^~w+a.RvvzrxgPeQq?e+#gK>Oredhqesb7ZTAS#:.TcMޯ/Jr[Tn0~[峲l.HgD?& %B?ΨY; yBp~jUX;NG{EiB| lYP.+ogqo0BneL*s)_XO1,[N^B%7owG0亅v%~5ߴ$0e;6_Ӹm_`c^IZԃ7<-;ً϶#Zy,?IX|,( P;lƥP + jR+;ͅK݆[-WH?f-~ AIRñH v~% 5n)"$Ip$#Jf͎չ T 5Q$Yw8Aɏ%(TU;ғdjwƊؒy)-^e 2uՅH!2:tt ׬vn]nR$P@X3FK*{m=n F1K H(R/a(⏑ua `.=d/eo8-)@?U5!?v/xОxj%_DLvcs]hb*jZBҟVt42)^8W1PT*zGPml͞#j2+̫ΣDuA}rMBfQ@{*#f}Q]uX1P%KxN'@rҬ|PwqY6qJX]Zf0BƑMpc»s>^sdu+N} J<݄rnpjkC%J]Cos&*UDe85:EZOzZIhopcɔiۑ[tF@ʌD[ +W cGx@l{(*s!opfHRZw!Jb[\.kXk(,9*CS9;4`ςVAH븣s"#  duGE nE)x [5"??E%kNv 5O'lby‘J+PUm6ÀU.w&s[8=_=2~ +2-J#ZEV 8Y +N߫M^&8Ky,lZSƠ^˩ݺbX7 DbӜgwSx w{0O,~mH{ 2dP$|WV Bno&k Ioڞ |< u$!&'g@^s09St&a{BgڙcaSHE77 +*q~vW0`AuQxJF +lyOKfAݏkp #r_2 z[k=Dde$>Gs&ĒP/lh,iBG]b@BC:Sw|C̆Bl:",n?~ m-?:2Ӎ:)T)J_nwzž,bYX^DSW у, HaH#LRcKtr2@Pap$1Ly?gJiOu# HjqB;Wnl>B=LP>0'2ǖjV=`S{&M8,>ɰ" ,gMdtJg}s)d4$A7pⱜf@5qAsg)@`Gr|.b0’g)o#9[g,[g YO-W)BPO@'hdE1%7_+xN=rV+&!"Be/țO@ӕK6d +r"f^*}- a\7,DŽH8(Yۇ6{pYLYG,(%%Gkqr>Sqlo(ezrXp_K^ZzD)"8D$U{"[|637Ò릘BI^0i,8QYbq(pj&Ѝ,%Fe41_|J"!S$ycZNJ jBU:xQȢGKll[jZk0 ;mX. + c**40TxGZP9^ԮI*ǠxЁA /Rtadm^;P>To<)y=KK_S,SҲ^MzR#Qh \7YB}$ZH3U^!ok oQJ. !Ph %YIQFJȏpS(c?8°wd/@,)a;:|fv6VSlӖZ +L89C' +ͅ"$CSHXwj w)SZM!&+1̻5߂TqyKD3JܝfNcthǷiy+n:ě |2_^z7,p)6ffx6X|"˘.B +,\DuB(<49va`1d5V MrViH\8$HyE΂޽M v =qVEPc̾Bxʑ|LT-J`a4wOrzMbt, ZsƻSFha}%|ˢ.3" WM*[/ТazQޘ$/8n 2ɶ2^ +|dJӪBPYlхU˱<+|L9ȃzQuSÓaõg +RQItC:>1sh?U]z:ߛ o海j#4mu }^`/E͞{TػĪȧ] ܽAZmIJ艱!gтĎH%j=RaM8ܽg}*'|i}nOUQ|>\@l:}ďddJ?a X@'[ >4`f)W[<<{DeLvq4wAlt߁fLKv}8[XBo,]P6>#5MS aTg&oAχp~)u,0v]Q^atVPhmϴL +R9/nqA8,&uCM,##̏A^(P9ӆ u) 0M,!-:dTz;tUR%EkC2mꔝZbƅk!l O.zz(4,At"?\zhwn҂ JI b=+ 5f%xoS|Y$[=|nb{2Vy/R#cid>0BB#1X$FX btv)5hq n~{+lp)(>e MV($BtE&]8`iz(_O~N]~$6gns`NE>q6{ ]L+HgrimUP-U44{M{'0xbA|ՐQ[k+]""wp;PLO'|f=,q\gk Gs:mt$O#_ex; bt +Գ:^9tDHR|'o`i" ڀso6[z"v ]HAl!AfZFE,t PLHG +jYuE}q)vT`hrQy|lF$(;mV &F 6x dj2ms؎Z ngеvF@EfNi^+XleʙCѲ-~=^syP<2/$K +J3 eOC=bE߃\IdzΠ9K3UT}LO4*f4YQ= ΫѰ ~eUFF!3Jz{c yσ[pr[A݅5?33'cZbdG +gG_ey.ߡahXf>첽n)?4a][ +.ť\7ۥBfe,?uk-%146gT޽b&ݳa6G : "re% $F2(6 ?P Qfٌ#XN\{ +n'Ip@ r@\P-Ta 15 x$[3PwF +Z'u2\*~HyJЬP\kJJ`B rX VᳫۥSMJve<t |q5hR?R%f“L [SpbmN%%)Q ɹ}+ip\tzФ){2x̟ +s(4F(x|h?<;g{&^#WHmց4mKXLvl89|~|D)˶^7K Osc(Xq%96m~q.i@ydAFGd"M~FQMc#bДXWBv|27hX00??P?42X?I㠤1Oh/^ $Ƥ!zD0ce րD@OQsc8r^ks +4ٔ]?sl;q咿wA'N`L* 51"@ȾOdlZ31>IY;87BE<}M"P|zs g&@i00 30 3̏YSqMR3'Bوh.&calRj{8%u?/.Dmi ɱMK#X5HD'Rm ,,q;4br^hݐ`VV.Xj敚yr`ȠhAM\#χ!#!,ZpNXb+! rR9J.X(ڐk< 82~|tvt=Km(n / Tܐh$jV5GWS'Fd{%6 ~zx=:09J.TnFlVT.X +CA`K:E>%B 0^h1(J:`r͢<- ȗؐщ1-"Xb*YŋMلlx|vtph:2@hт`ƪ Rn 9~t>L "{!$ +bAc`p 1,05HAPZ֮U;({v|REk1 )G r}J#T3]?BS^M$?bLGucV]6LsG3,[ibM*-D6{FW8CxxQEu;8?NJ٣yYϦv0{3($ӓIxKpn;bS41#Ғ'$'r +nr3&r/!@#UzEO>ebkuX#Rh`T>Fb1= zt 7A0mXMħ{^|zt v\}C'EI2>s/XEqa2W$GtM, + 5gͤ kjob ]5ՌO3adaAZ#?KAY뜆[-Yckj +B~ Il5yP+qF6R@/SXi=q8T&h8a( TZ_R Ih{ ރj`M5=:">Xalw 36r<8,)JwqrD4UIJ/EQsb@sU_P0='i3!}i.(-Ɂwu ҿ:2Mj1=4e RgՉUEZ4ul`Drت^H=uI)1K;d. +!ѻa*i3[|/) )u$륺 61M=A߉jC3DT\\WKKI+c^Xʿ$+N$}!ԏǍő!,12?I +'? +@q8ᢁJ,`mGعa Vem ~ }%Ԧna8w0N\P<vJ!;#'3j.[K# P^ɘPU;9RXs)g}#'nBӲ^q03S,퍢J{#Ţnl40W& FMxO+tJB 3}=^5L}2o$4!ϱ% EY¦cI3u[;\ǪM{TFdIыdW7ju+=r +kJ!/%+w"KB輰DZpRȪ +Gb wVګINg`]9GJSq28 du#ΰav71 +c#&E}.KΞz8;Өnt6tb ԪNdРt+>T{VE #lf6jjyy`ˊ#m[ IX9[I ?vX(5Ka7JMLn6XXX-SaFW&YC*m eЀb-Q<"zc[ŷ t?kMx1 㙝UDiGX?"^ v.UɎ]\鴇.`{~TeGC "sQp((xFHkE5F߸Y.;x2zA^o7K5LA~74P¡ߣR>jXiFHIԚiUERe,KT%+2%9l” =ӘJOFΈe;cx+"> [V%vA6橂575HITw)eiE +z-.0 Y}$f O/cd$:o.f^tQetvq?=閉] +S|iJ3ga,cw%q_FwHQa₴wf֝ZւjM].evdבk4`ȤR~@Cx +'*xu{WvT-)@ƣ\)&>W]|Ar}!zE;_)BJgUVwKD@ * r ٲ.G4ΎKoRT~_ +DX)g 890ҡ IylJ3 +. U 0 IeeNi^}bsiKI &SeWZޕ'ԾU|~el _!3Rٍ77&j֯m ޑzm߸Xuv{^_5{ct>^/)oqS;=ZuX댊wOy:mJhP'ʯ?ceEEDh\_?sO;T*ʫF'iگle˒sBґyz$vvtH4k7v ;sҳ( BgGV.J\c3G.eFou'Lv4jWW)Eu4YLv4#^ZЎ%fs25tq(;yĦCL^o9CeiT""RjZC2'VUlh"RȘGv%3w4Jnɕ`ex&Qbiǔ;+v4LƜD;;̾cӺc8'sv4gǹK8oQoN!ݿL<8/bh޼meoƞFǵL6(ɝqAIgQ _fhS|1jf9t6i9wX+sU:p&Fj&`9Tż!f,m*a9ѭ̓M\嬛+p0r$s.3CDxIRfG#,涣4;Vд%a^ |(nH=izcJ:U}"FMVDX$ƫ/KޔM4cv!s489+:+Oe$=wnlLvXFFr4jd:[6m̊Nؔ1N):i8l̤~7BhX}Vx1`Tt4 +gs)F4{;^V|99>UFX9&H31H иp ?`怩p>=| = :|QvZX`@(A0dAN 2 ?,4EE5HZpA (60ŋNjKa!(JI +D(0ÄP.Rp # a +"K`aH1@‰&rpD < !x 8 +$0 8@)^8P ,8 @2@ؐ HaC( X A K (;܀b +Q8PCC-6`x!&e{;+kCEe7OlXvĆ1J>,h(IYsڊًfKll&v4|]Ma5qө+~f5%Nf9#IM\B)7h&iz]/8Kij*glo=;iV#O_/xO⪣:;Rv\xVľexGϦNfT3WEtI($&dl2]'(YuT]އ=:$i)kP*EjLƲ&7sFT6rfM/e}CJ;YQ!_\CI)O]Ujl˅gRdchtƚjABi\FDpP Z9HVh*Ȕ!ydSgO͊jJ>fߜm%"]9Q5x6ѿ1): ǧv9HȟKvRIO5cM3jA;Q~jP:Gcr*,b}!1Ip K˫3Tr4ڇ,OQmWhiG62;*mr:[O3<5^k_u^ST},y9+cG;(Z!agnZײ6c3>&U%KX`aU{Y_8F.kdDf5DzuOL˺^lJל\ړj\.QʈБ^DeU2$zJ⽞x6I2rV,d;8K;쓧*(f^< + H訑HWx,^VBس,+|Yy\()ino,yLQD2uGc$ѰgWh'=KLVHfbhyņf{۫TL_idyYe3+򶛜ǎݪn<}Hx$vObuıe='lc;Ft;F{vYeI&_5tI*/ceG<֤| .'J{QևVr)!яyVFw|wԗf,c'?[x{LB;z% xUՑ3,K/(ݑyhXsb%v(dhުp mɘ[d5M_"*v4r.6MOdk-J{*sg/̐3&QhYraJS稯7/mm(Ų&0ŦO4_lrzibP8S8%Djiq: +،yslT}̯)SٛiuH^={dl +{+J33w5S3Kk갊6F:Fe;Zn&Ӱ̑4ђ,I`vHWG'^^ҔGXբ|չh|O|c.#oWW*<Q]ēbOҳYc5wW{O:h2H[I/qz$}RVeVF2W泹pd\ $&f9t-jtOfDRdFr6ʖsU/:v)vs5$>'Kz*7ִƑŸVDM,)::?TxNtnٹ],l:].=GevBs3hJWV4[l^+2)b ѥ JJ*Rt"^&hOYg+?’FL#;+ih-IjٜQRYJ%dZ`-:v4=;S啫tV.}:vI!e)#eI,R*5tԒZVUe\ H:n{|~LHsiRّ[bY^8չ9Lp89;*UiV VGir=DʊKTu`37v#YTYZ3$ +:0d5%J$*/lOͩI<-.~AKh9֯Bo5Z;WTyrsG#.h7L!;sYdDjwcMꈌx3e5-IJ7\C=ӡ{hw1s4|M陓fM̮|YX2ə]hHhu1XPui9u7l2!tRemΟu|;|T)C 3SCXFMPcljr 5IR7z&ؒiJq? 6oLy#K1jذӜ5RV˓?Mۇ7Bt+ם^S q4#ɓ&uB9ϕ?ֻܸ_TRވJȇMFi\ooV4>:l ?V5R[BaǺ6kN2BWOV ɎT 4mZzץOeYEhqSxD4*6}xegګ~=cLj\Ƥ sI`=%V&EĹLı`N2)B5\YWEbmPMQ$jҦ~gC.~ͩZ?ѕ]V[F ϭ(EϪhͺ 0Ө*%|?$sfg uĮ:feM̙[DŽީV+}>MXʼ͗n^ώDx*ٵѸH4;^p,2VgF(I!I3jbUvF!=4ؑC80g4Ğ19o$8HxY;/4W- zWis4{r3&&e֣snƱh1keV}UC;?G,{5ZI=F^Qp0)O +4*#ft.Uӣ[X݈FRv䓚eQn|3e;G_ԅ&F5ٵsQ(l̦P$MN^ZrdB#ڍ}*Cgu8R>g~W"[g +3dϰH/ypJz(HNVN'?w-GNEskfwWGVV%Iqk4+Y3hYtƺ>xW #]cR԰AΘ)EVyG:5)I|N2m^g,A*KNhjx;vIK+oKsڕy̲b1iJGNIcrVpshS,^ O֒CtÏ#C1re*ߞ|#oi>S/XM\Kj˲ctwzh,dUv.eKb5GZLיHG-¢"3^WTrOLOUO$-nhɦ$Pvf2BU^'7]f#E$SǏu˯agHhGfIñI;,r4Δ#\ ^tAlI%ʱ 5x-OfW*YlY>1s,:~qά~l7M)ۤs d5l{t $6U*=+3c٠~U;Syߙ]$SXů; NEVLJǪ& + ul#VctG#o־+3lXIuGXYCGWe1}E'c6h)3u$۩zϓ'lB tun~BG5xiqʮZBB2w9ڗsvw.JY9.`=Uzڔ7´YsOJVcvt u\OW4v=m:2Kl 1|z?~w=)MrTԪiҐԲ<,ڑt5a]}+pNd]̳VBy X*vh.I)cU{tsY/YLOOb'e7M^Z5[%oRc! ٓwTXroʐai&nƫkMt48AReg^ReF21s=}QH~jo6/i(65Qkd 7cjW&hHnh~2{nFESs/4&ZNEeUfv̷j˥:Kt6V|u >K6^KLW~$yQ:3ZSB3\wX)+Cyv)cwR )Tx}n+pp]᫄z69$63%:+<L4QX?̱9%ޔbX)û»HU0KMM +ٮ)V&ˢׇ_?V`ӉXLZlĭxX:bdKybe,Z*ipJTr2nJ(慟 WhL׌Td2;+$UT:fj7D<;ZM1dV_V̜R_^I34Fk}X2ۘe,Ј!z13FSV5a/ϩ˦X LJ>s%UV??efi#0aRTf2neǗӌf5tcͤ2h+QFbtZ&R+5bv zL 86tĥ/ ^b" zNV)hEEAMs&,5{(FvJʫgLN]ڗ3W=ѠK&|RDٴ\`v a\Ɏb\%=x&N+y#F_CydmՎFʰY4C߫yK II2{Oɘᥜ NQl'Kg =2N7%e<ηN,)lЍ~jK ?Xr+Uf׬Ř9,1CH{7V}neF'sj-Yl긯9oHT K(TM1 ( +Bt<`o.,A +B 1`"DfW ?;=m0S&*]jb$t8増wSwz i$i]\FC:/yw^S-%;)q1bT>Yr>1;S-#`}`#T%|T]@{}l]HdBxwMڰ>6/*&+U +F${NÓ4 YDY&BZ]ĨYW# Sȵ/>\*Jt |Ħ/B?SXhnUjMabL?@Q6&VO77 >(4d)ĩx +{-N +,ORljy6įɟ7<HU]SVQ0' MA\y{>IYkhbHJ_dhb2UZ 6SXL fzsk&IV*[:j + xR}-K0rQk22k\DOJt4i9!xGr I7kHv9;Sw:i "=+ʺ[/ݏ-#\=jbܝҚjEbG_F+:)ynk6S:T &hrSA/\^4Ld5R!<ׇE{%ǭLع6)г8SW{ ˘`nyݦ.y+ +bpV3JaM=M>K7ܞ*xi`K+ _1XtøMOOvR0 O3bG` &5 +!Nϫ vhfG܂i_|&+KíP:::-o<'ĪTN +. +MNѶhBu%.5$~Eb 4hsש$̾ TN*6-xeA =jaWoL_V]Q ?ڑ(@L%y77;:]w+W笛 x< ;yQ:lHC-N\恴IgsC-w7M.+c3JTLŻDeF4QPy +2j/'#RzQ*9_azw@qx~6LM+e+Dޔjtp.Tׁ e3CZjjUnሎg&𺙐sWtBo/ b" d6">d:X[t4k_鬺-+\mJ2AGeK!f59n5~7  _@9خa5WF*.2U- 1geIԟV,KDqAh%#RLRQŕP 5ʯ$tȧ;&vY:/ZϏp32z{Lr!hT7;D{<z~w/)u=0??S22(k誅lmFΟP4CLr *W44ЪB}nó~ u +N] IHYM9.aZ՘amO: G~FM0y2>02`b4LJ߃ KDB*1}9CI .G2iFdYw4Z,MxeJ/Mw177&)2G8QZ$/T/:ZSOֽo$6ͣø% +X'HeIc-dBd*\!xaszƃl̇J9\'Đ[O8jida]a.Ke]?OxUJR'Hy(Gf6M VoW]JSZ zk%=1/c; igq eulH%3gAOg*$jg<49:dms ņM<ލD|/!(gȈXA*|I-1@8$³?Wxy3D<.,g#bѻYqt:b!ܣ&GJ#} m!LBs_qj3PijHk¯bBOn +>e|;I;U~> .UNbR>t)ʒ&3c@]ih2k1 h7&6MWm>4kj1H~>i1 UhVe`)4[V."K⨒π{KεXZ(=j'|h܋ 'Xx&F͖)x +=OĨЄ-GL\a|||$ VzI(IB7 ܘ_E[DGӇSԈKǼ-jXaq]NR b&2_lV_ߨ2᡽M$WXN =go+jF҄ҐDkۍLʘ*äNVݫ0Q&LpFf:^Ȋ@WO~c@%l%϶M ba腮ER[ps h qu$W𐻩q.n+R (rY1m#]U237a 䌉_O4vd}׭^l6~=O[K4"6T?jt;'`q23.r08i(W%J5"20)ԲDk98@1_,ʱl8K5Ґ6+J4]Dt ǗI!Cӝ$W[tw +)] I,0ueXキs0|eB?QO$`h^<==g)yCv>%)ȿ֯1F$-imV۷#8i3@fuO;J+lkQ"I,+(<|U U!>nQE<[ԻwoϙMk}<1S_K%[_6}~2S1S+ŇnYڮb1]~ōH!r4lDM_DxX|wD$:C9и~9^X>mŲ4<g-UbpAZ +?&H],12s] Ų3l$4͐ᬭ"Hp Vrt EmZ,gKqGR {`KːUU䞖쬲BGwY+F8b7JV Wxt9iji*)ʉˆC!ԓPIٻLI)17yPՀ__B6Srjh8[aԃRTzr@U|=>9fՐG?]p.MW sAc#pB 1 x3٣,(0Ե;"7};4-ŅL; +,,FS8\3#B,pdj`yF0'S-%pi% ѣ0A1Ws}eeb}u8%IJ'R&}X@X(IgJ>8$gCJ+ !QdTȿY0ҕxVx8H46ZDr/:b8 XɄ$+[;T17L0LƖ_})aB"0\ Ha8K}B H1Di)(]BEJSs2"7HqDJeVN^Mu*'=QxP끊L#^1P'x=7VZ %zNhybTK*zI@Ι h(DWn}S)_߯521qbEw ^$H9 &Uվ`L0~M "|ZmN!(/G@U4#4R +=?_b+ OaD ^f}(asSгB8'}2FA\9?y8] 3{&aiɗ:,UFdt=B$sD_FЇb!a(lZjҝՄ&lōe9dq"G k=,';fV: 7ꚆeU{-T$j ݃HH]1A/mр5_c3/8]5FEJ}OKo +^Q⓹ǁߓ2j˜%Ys$&Y ze b,]Bd+#O'=W\a Ie}SUϢe$9K8Qk,'*4z +էy[8z bj(\il萐G qy(A*uT)7w>|7/!^?Q R]_8Y]f{U'I}u(!+e_|`"~@5"n˲H_tJQ ~@ը$9^S%πK +J 9FHX!f`Ґc3 $&WûA#KV +th5vC =N&Aul2YzhP\kHHxEԛ?Hdv>3D4O8"-JZP-[6B!i!c P +Z|Wѭ$ ƩVx]pT\U]ċ$v,M2s5ˎe7 ;T݂fQҭT^ZH( ;1ՠbMgsf+NQ?`bDoBqqSDL# +x@Zii6s5Q[QO+\JAkj'ΗTO@{ɡڞ/J4%,NLƹ'B$Avx8AN3Qv +7Qq(FN2,zLJ/QcIlZkD^22JI=Trg#nH^Mnkl]Wxn?SɅ>`S; pm%9=8.-o٦iBkȝC9ZP]0?@a)Bjg4]]x44y֡HWeòpa آHc;9 зc X֘W[ `p[)PU`%=E|zy\3F w&SqMOiDs`xF;2;d/MgRZ9 +DqP0aDg@O/(U6D'%Z벶vn}!@0V,E>1 cPVP0ԽDKJH &7#: Hom +1m{!9xt;j"fڸN<\35Gn!.L(^l }%$QG^c\Fq[X+Z 9 +-],kW%'! ;nI*BoM/lgw+X8(>*sd[q )$Ͽ(o@cK +sk7WNZ/YDUoP*usMi>fPZoht"q*0Ӥgr _ @mh~܃ieꚡꪂѥʔ"vhD\si0noLְM$tjAxcS@.dD%"وL({c2.sTAk02 Ypi6ԺT|] H*I K`l`.[Q}7+){U.oV͔ l{2p4bmNC(tq `^"PMC~M"#6~24ɲ1((:ORGd[J1`D;G6a"hMXWI\(7搟<7:N&bz}on +yp00xq)?2ݕLr/tڻ@)zfJdl;4 P4lavʹMA[ቮ4K.%DՂ=7 ,3H 7=*FTlkN,kuR.BKqW0W'Z;q{uX4"-%Zw4rm^! IDeIm\Ei1UE793H]h4pUqzZx}H™T$(~ůFjN[8T^RAL69bLN2ΠFhT 5@R  -# d!t'@٩O}//Cst'bqb*WEvxmzN!,J Kٲ [h l/sS> 0knQs:>U_REsփ 6b"#oC4)K&A.߹Fv>ۣ4lx@J `XN|;hg%" + a7?+\jd`8#\&g-%*%6R|lK-^p +ò&aģ*#N"d|le4誔z6w{z0zKܱueQ"%-B; O4TY(~*4s՟ ^5e%dzWo݇Tb '@i/X`h~''dGr&(nqMa^#RFPR s5_ )[mP *!ri̓ .Dy*}s7-M!VNQHH=&8kSN +g.$Jtm0e+Ƚekkjc'PMukX83 (AJ9g* C^.{2fw1D{a}{9௕E ۟gG?1R- Z h{^v*L.fOr]$ Ȩ5v "]E )3Sj7٨ipkj υ:(S-$Mr53 d,Js +8B(ť&J8Iq +cLZ' )PJdy1' +oͼUeʍd0a#u# +JK6:JRAf*mo~ogHp0Вp[~p*#M0H;]tS?Xl>"sV?$~=9sXפ"VIr'?Dn0?7►3}0 +(ٮb&SWr]V7y u Bm*H5v~)&3-~w^'tZas;~bE|R"hf0|ס2?UɎfB$%PB/JLYא26o3 +O@e"+nn+Jfm >ưst+) V״GdT/&"~R[(+`pK`ז[g[@M73@!/%YSPK/h?#Q!Irz cى ܳ)LR}@ xL̙X1ȝ~K~fe!o/nT- א4YsLJSh7˾T[C~u/t^fyj %.{L7|;^{B:-"&_bU_~-u+8.q!ԃl !]@EA!vU3Aq[]̨-n_4ʦǘQu+`k*"-'"zi *wyvk_vvEQۢ +/Ϊvz.TAM N'֏;bZ9 peѭ8&XX=. j f VGr--Ӵ1ğCXK ;s%r?"dܼ $et͹s1 a~^*%o.!7AlCg +npPw l09lv9(Sd%te?C$~Nq΍S(V5+ȩ`O,N  RI!u2Iv4u_&,+^~r1*82P2he*a71DÁaʒ|5CH foFaxDDG|R|l!te]o^pO%\10&"i@Ap +LuRK&eZv:n343%ZĚB 3ƐSo~.udp{9ۑNa9;$];!{QnXN- C_n[Ֆi+S 6{t0!Trw}[m@\Òc?E94>a9nyFcُy{:nK+S) Y/%NYh_bK%< aڟ=pOsD$!Q<0`h>:b!"0A\U(hZT3m=`lRxcU$žЃ_璺 5AB +K]][l)l74+%./=jIJǺk[+-(@&ȭYh~($X_.yCiEc9sŇ?=gڣA;nУ0|88sﴟ66T4a|h,f7셅Pb8TT^dP^pJ@%5(VvsJ޼|GvJ |2> +ِ2=g!Iܩʇp>DB{rC,1+0( Q'P5Hمqyg\;8 >BLIT$ ^qk9lP=xi[ƘTfd81zQoI,#C3hU%ixƹ~J4vx|g6yXQ!,"~Q80n,c@soIGYhI}_ }-M,: T FwtDhps8l?FB0 RF%xKSg߂Bi8X3$"{4l$D_y](ɼZ]ɉ`0 $+M5:|VNרC_MDtyOF73UM[ħrО]}}8XXpiWL)B/dب|= &3YMcܖs=h=l81'h)ht2_h` C=ЮEAq!;̠L,ܶSE/Az H^+J7HÄJ Yb&8 D^G[S ds4 ݍF+Ƶ½5cKa> {֬fۀzؚ8) R}<^jtَs6Es@ oKZM⹣Cw?7P{W3̾ b f8ynUԵ".*oUvP!}baݶH3g, c!1lsCJڶ[/ g>uiO*& cA6M1ᘈar!j}SP-o[=ԗ {vxz:+֣WwW t|e3lLN|Tg6WT6Aq,S}+%/VL?A^9agf.-c7-[;Q#((3%o9H"-1acz5/` 5-1#ߩ2[M9o4550T:J|Ͳu`G*k}"gr*mo;Cc:מEVr|`m֭jfS i4:-OsD5rWPz:ULG +^ AҽqN#QPzp +|'XG(}+9Æ|R4t`w}49Y1`1˔]'Q\зf 3=𖘲 J:!bk=6j1SR#q]|Y'PAS7P[V\鮖A9zkH0Fg2LT 2<-MlD錏>/B%zEܩc֑bP?}`,}bӂ^1N(ʕԙz`,i?*!(|t`Z@%N0qM <Y=NIU +N;?Qp} 0Z/}F}6󉃵vI@׏0ܑXC(` +997lOdV DDEEt\F<""&% ^aq`nU|`C') TZIŒ_&.Y[2n(3rkI}%`%iM]l~h/E\X`sE\+@[{ gA wu̩ iШJ4A ` 9=JŕdmFud?zX=ǒ979eŬATgfEߨF+暺~~SG׺#yf? W" +A0aAj ri HrvO&p+AR.@>miM~t$PI̸yZOuDqmSV G5i逫r%j!p嵜^o 4h`1;5ŠA5. + xcΝ[sA1 9u1Dwni;T{Ƣ]+(k0Y`'ȳqEXĂ |nmsg14.=~^Xg.zݟ^LxcY]V;MQl#K>GHᑟЎHξ.T(R[^B΂$yEƸY,* +|$@gרz͑@ۻdudHq6HuH;DJ~CMwo5 ],>,ju^ d.+A2%Gy~JݐqHn24&*BVP9F3uFGVaJЏ#-zu +Ly:8=jmbAAmPby`6=Yq+.Ԥn՛{`zZ űKErU[q%"=e9kZ?VaQ֘9TJR1e/&Z0,jp< TJgJ@_sä#D3aKJzg PF:,zENP+2' +͒ףSZXttZ&:IJ'KG@# Z)Z\(p:\qZWs[q1HXa/Do] E vjHoToM;"@5+ Ӥ߯9QLU.EgZXo@RX(Edz9P;CoO +ή뮂D<ڷS54l2Zlh FBP䱬>z-3DbZc$YiOk#l (}$ݸxq;}m$0X:W}y7~Br%͑E1--RijQarKg\Ua sFyHeWa$7ͶbwJ&h[H +K?[-+2pH59OU@VQmfCJ?P5SMr9l= +TjrAxd1Nx%#J8sW" W;}#K3׈E_)x>7V[MHJOGp+gTG'HY4UOb('%COn5,,&5*0kOV^r5; T[BeD!UiM]UO c= ?qa$tZI?Zn_b 9QACxzɭ%U}DRC'㴊HtͣguƛG~eTJl8bJ +c4MfȎvzˋb326K2xQ/3s`0Jk:qke!CRLҧ-]9̽uDv[ Vu7A۾N@ji[^Sf+eV-NQ2^t=%[9h[F["M)5| yѳZ$]B  +CxIZG*%XAz?554*K XPp/=)REŰ ˫J tfydgI/=At]0#އKv OSu\`ҾqH]#k*Б ȁV)sȠ<--9Ԑ⅏Y 3 NݒA'0 +0&735tw~ĭqJM"̛p +joQ/`鐱v+n :,$>QECs-6Gt<2l;N vqQEr]PMAc JPd R ͵bs+vcABU8 )`M\=aI',5/26PzЅ+Ns߱Yo8kRS:I4;_60KĪs(^m!vwxUk,. LJ[MvC/fMGBAq꣧ Jn Җp:ӵ9" 6;;xXJA/2cԿBwֱb2=kdllq|л%VOV4(rb/bJܒ9":'~j&H3H)yCׇ%<4ab4 ~nV$=p'pڗ>vH*-~3ؑ#Al7̈́ A=|,:V_?̧<Da$M^Qi4LpNf?3h2,<+tyZia ޙ& +DAlg4RKgt0NKz5 n1uQ_m +r qCȬ:SCn2[}u?< FL[ VB;?$݄Mn~Jwz?]Kv\@`T>ia9P#:W1}|~LB% CrA=|T>ذ+k#oR$-i1kg2kAp_p$Y͏_wG_) `^$ +)@]Kۮ1Rپqn"s}Kli65U:Z9aɇ1DYWСeU)t[զK L_go:Y.c!ƅN,UV$찴nF7z&fBGYivgʳ(AKY:&槄Flsn0S'H6dyBntt4lN u9ZpBYvl.6:jBevK *0muDn, a$o:&KX# :qզe:&JP_)5Q+n66zJ +K9[8j:l~wϜl5@0:q&DZTaj3,|@e?:!=(W'Je%8G-^tr:~hc|E:Z"O< 4Q;P+Ѷ:߱։͈m@9B-L4Q3oo;#}w/5rj!m&ۑn +6,O_gl:::-a:|6pp4b1%LJ+ؕJSIળAm&ClՀU IexC!h"` 2zMaTP5z;!aM|Q#Yt3dn90*&YJ %=4Cw ` 2P_sQ!bL,N%I]k'L wPcȨp_LIA$DG0P{unګA0:jF`R'R2%IǿQ7.R,8H0jaTŀNSv %s4XM; +MqPO*H JI)eJ)` _POI4f5YBbqՔw=(Tw' +%a 1$νBWԗ1SϜN+cg 8"CҢ =V4FŢXEwQd b`$%R"aɇjp:%{2 HHS mS+r^D+,䝘EjW=3"d>c!Rcr-ёU9 +֔HcwF)B7zUb HFkh(pc(YB1eB* "H:Ehx1]s\ HS3S}£uaV +8,U#HA sPR쥛9\74.%/j@(2"D}C49;LEU. b:'Xfn"ƣZ<^kp7$$U91YMnQ!6ļ&*@.$I*Bģs]H\T%SP9侚$2Qtɸ xQzD͌)K)C;Q!0@=B> $H㰦5c:i2 y9dNjw*TKKTy5%t0J)bHTKj 5/TQBF\Efyhph|T¨@"S3҄TFf +cE2IH:Su݉#^-dbmpnBVd+mUTn̓K +,PP]PF7I7 + 쩎*EI{JmvL/U41菣~,Jr^R4T2R,B%!U x +;Au`$p',"1AsL yQqX(cd42pB-xE>bߟ_k|BLeul\qT2UB 5tJ j5WAG h^DBիUua?p4f&f#BA\pR[C A$$ +][L@:ܳM`PoU`É(@_ܑ-aO+=ĦS}!^RguHlN) X!3 d~j$&&*|ٔ} qQR +q 0HH}vAɘ-U\43?hA£_2NK"VPڑRGmOU$KyŐz+ŋBSS&] LKBCE$QgWjD2g  +SZBJDazg NoJbS@jcΰ NDa@=x=J$PP `U1H$H]Z2n&da 8UR+P7JsPEcg9d*>Xj';gC=Mˊ0" P9$Ya;lOaù?W2I\ӑg0k'` P`[W &|C{LP=Lv`7lEӌe*j 7?hgB p ➏3 + + fO;0ɐưt>G-֖ZX*Hd㩗3DWA]|MEHe> ܝlԘKIvXw/GS' Okbdנ"bB +ZC(ِGRm[KƌV0\ݾ0e(CRF$Fz3,954O IJu|q%AY(tua;Eb(i}+ +S}*},{0!%yH ,.ZY:A ^ VOK *pxh +*B *eGB", e[{5uq 6u>wOa2ek/B 5t !cѨ-&&*0R3haQdZ *&D ϴOV9=JK#Q6M]n`nxE%JQ. ȄWȧw^+!UBB7ʬK]NH@ +jN%?CF;& Q[$vw<!*0S1T=^4Y8XN%ac^y_RT3O8&RL0 +ȨGȃG3$0Nq=־6q$AϡJ +u1uyGJBC%W K_`!iNDꓢ%p!ˠ+|"p&q314TG M 뫓f#44 + v桷Eʛ0gBV] >@Ƃ侥L@aam?VzHF ^E,'Ƚ}`nFd G)7l%>3aM*Vk&Lkhjd\S#ɸD K*STf|9@'3CH͎$HfD"ʉRxMVTeD'55L/xyr7*Y Y6h ɐC/'-A*%DIE(T{Aґg81)ʦE$x"!fz<6CkC ?f\ϗP|8̔TY)L105,}g$r I2A&V lQYp@z񈰱  !"%(jyXbN안 K@sķ+8 7: 3V4jaL̇zմxC Yb L)NVrhh$pt iX^8#Th5Q`7nH&+ 5 +( +!WCTeA˘Z@yY(*LUUG+@:fS;7 !yEkh5өLU)~zUԘW!R(rC;m-S8.da-^Lbb2#E o"Q^ ʟt?jd]ֈVtMQ_C᱙Ftm)&CbTM?b:E~&l}ZA' 5Q`pi[&𔸕1IXH%2" ;*b tv&V *2ɆdJd'Q? &[E# z ';bՈVkak+EY_IEb.bT +bYDߗ*q' +>FBwNM0>g+ߨ#!:R =Tn4Іw&{]1MQ?gxT!1vF*B%4JjVQBs<ፙ N;l;3XOgQ,koȰ$DdAbHeEʓpK +kLY$KNT\$ 5K.8 8c(&"ijBcE,ka +lKqZI@1$+01^5 )zWI>stream +UHi㽋#1%B&UihhHhuI-^V\EIgXELU5G=Y2dOdΈ<31!3q,^1S~yȢhB y1Q$HS!|nԌVRHkHT&~PL"*>f\2ʫ@Vsš+o @PPPT2 +Eͤpd5*E6/V|E "aTXUu217YB:H[ +Sb*~{H  PRuV +D^F$vR/|M[~u(T "R5*N.]lIC@k(`;h>-օB>zTUY *|k{"ny V rI0a>/YT--版vJhFDs* 5LlRYjƞS? ,#0<\03TLb^2MؾyKsH,Od' )[!ʑ]!TCZPÓooJ?D ˢb*AAS.uHLīJ3""TDRc0fFgo'>k Y0>k Ό!2vK ZϓGTU+Ua'#!GLDâ"d$Ɖ{ZXb"puB& ilÊ#{VPڄLq5ME;Z:%3"[ ˊSZ 1\T4'^* +ipIarcQ sG| UJFFSAxM7D!r4J ͞H8DZS T I MD%;騰p +~:H&3)) VKfݿǺ|2Ez~Fp؄E_ gr_ADNkHT k`(.3I5ab\qը.iHLR2X!m\D4eEvD%L+-(s+iRϸf>!n+&¸"@0yN _0Z0) +ʤ`<P8HH:Q'vAIl5sG9y_c:! {B\X$E!QOΐ8u +{+"'gaRq ѐD#a1,(ΖšTH8G&ՓuOTdX+%AIR# + KH3A|1 Ĝ͋bd3կHpP/ +;-C +,ΰ]r恠p3T40+x( +vw +RE@frԊJT $#Рhbh02Jg"G,Q`H aQN4C k iQ%l\WS,e?!Fx6<O8;Y]]h(FzUgpBW,ӄ@ @ P 8@", [G xa@" p@ +" H8(7Y6H < +qucr=|(1hbڄ8<*ꁶׂFrmcID +G%R z"8,UN%(N1!;ATfzcBTУ3V&T ]C@{1<Hs%!ղyFٮ_24'j% Ҋ(UN ť]cL"9MO_dRߌR4ꁪ̠TCXBQMo: _UQ.H- Q|"au._CV$_VA< +sf + 2G@r.DP1eZ NTK` ni:5qCIxKk nͧɉ(2w54 +; vb:ZmIbHgfeZn* %XTӃwD"OddJQ{äj>%I{&dx&6 m>)'HH5@tO1DEYѴ.DX Dpk@dEV"y(E XD [|EdzfCr4údz Q[~ըela=Nt꡽NW5PJ\G 0 x?6pXZ4@/o@!a,#;pzDM.tJF1!.qMD)uN*QrodwM$Ofn; #cR%Or0Sں*֌?~#Sa0<_c4JlEEs +UaOM3,qgAbTVc6c!rC%P s}aiMܫ +U'%Vʫ Q T/ +a +5BATM!rγZ Ǒ=LMG M"v?QQA,Jg3:^pOdЕaBI"=Pt|4XR*L`SĄK JfxDYDQxh +93C")f +%)]`$9^cs)53\Qu ee'RA8a+," XM ++j$Aof&P  ŃAݞ8, AF!e1dD p`+r%!Df({EGFIvʳ's,a"]aSNiדS;+0u*eX1ނExŤߖSM(#j "rdA dɛYwhkLBH ~kq-tdvk/-4 lU . (^'61aXeB2&[|iAa>_.H M8dq?w%Ufu ag2=B]]#Pv$fo_<b+{#MzJw-ƺt@,'AkA33;3>oeqL1AcًrY'Q=3O /ݔ\rMwD,A-VØt骅=Y!s:o@7@ +<"/Նӱ rϷ(Do4K6_ /DJka/79b |Y"W)=KB5{xJ$FѨ퐾VA&9 iVfDDNy"{![B|VP -[6mt>ÝG="-p3-{JDza^S-Mi.Y/d"]w7ŒICq:14z$@W|oYG[SHގWMσb*U'/F4C)->|Ipk6@yB !3ֿ^KaB= +HoK% +n?kZ[s|MɧISSN^HmuTAf{W!Qs[AB +ꛮ}N k =vDl1Rh\pBJZ{hPm;ࣨ Rz*0iv`@զ$CXh, +V^.hp jG>F^j^6D,;}i)OR W3ıdL;Faa3mCDnM 㾗D"c˾OӮz (>!挔0y|a\f*`v;Oiѱ1J_ e}?࢝]Q$k)Ұ}Eqp#㾦tVk~~!H_Fd} ` Yzv~Y]i0K۴j*/,}L<m3=EXRbXeE1]<ެI'slWӽЖJ1X1 r& I|^c3MZsFuOWRm%9A&U5}gؔ( }`6c*TBܲ4"]Cd +eb3Dk&LrXCrs;GVVLl2^J>H1XPLD,pGNڄmg' OZ'$.>1Ɛhvb&y8BMy󥣍ɼ$LǜWS y e62dd7ݿJ"xsp7\Q%p7 a '5@u%v/Eުb5LYSj{@Kӿwm\u͈2]SDd 8Nmiz?*矝@pޏ}pxtzjGB,hDȇNUć5*EGE]Z-srFݷ|"c8$ f~_=X*Dvka6<_?:Zvlqc`u!lXeOV9礽m{Y\-OfP#w4$SRP@~F B%vͳʩtx u&‰E!6V͠LkT[囤CD= a,hf5DNv}$YD1jX9W;ЗBlH991 +4ۃzNsؙ$'dï\۳ś1V8ojezmlcCN-k$w67J&*5dGIxmW| ^!AӐ27c2Ε F$::Y +UTmй3z"]\$8TObr3ʐ=~Y* R. 4BW1'bA‰U7ҕHKqhliX\8@"y$;-w (+6'H2F!I +VCc{eɟ |\r6 Uv +JEs?tJw3 R7\/їgDPyn2(f\h.JhGpIdc٣DjjFpsO@uըǼ[p= ہ!AKK2"7)HqY~gJD U]ZN1଴[y&NӌH =HjXeޥN Z%z",0D_˸djJ5N7,-=j)ք[C蓩.&cI+ T0u='Lc{gJW_ +]f %i?ρo/õ8&_߈cq܍tl-2ij5u)w=5O#DMH{5R"4p…WeO%νrkmq +Gch_RTt:SSg4=#^ Lg ZHtI9 NᄕzAЀ˦="+f.3_%g e.%;t 4YzjyM`%:R LLצ͓SҖʜ=QT'v}']UH1xCO.PIB{Yk(32)gh+ 2G3W{ aќS i_i%yܤxVq4ws ߩm, 8 +m*YWj>q- 8޵2Q+sGDE-O09\r5B,M \OYHz/r1ɚȇ P!? CNWXqamktb$\Bi}s Ѵ7g7Ɓ-Hz%5" 34K0?oFBV\f'KK͇5zbfTbs +R=)ؖ?6 z$7w?!5{PXRdւpೕ x7m7>E٧htl>㇤hnr'tEK Zʩp|ܤBY+PۨD/廡B[vu9q 3,8tÇK ޯTnC+G 85DeYsfDL.[-JLDySUӛi]I(u)s5EZ56"?lH7W%Qʧb I`|b#ġU(lr"@:nICX+KWjlmD~;l"\rc ܷ>D\F{L!^@ 0|[~ENkWrDF1&A-(Hy@B> |gwr^@O{Xe&>G)v!͊:ɜZj̊4yFf̩c'\ & +B FzT,]aD{¢nd<8PŧHTZ^ī/aX%$MvA6ZZ{<K{6ķ @ty"9:BN%o |D'FC^QWscy +չs%VJi[4T"^O)z2fj"GΧ ,z 6Ei:xmK~݉$qۇ$WAQg*E5)W֦a2''H +2M]ǵ&Ҁ kvg8˲D k\`lRvעt.P>Zp*vh^Z64fmRkI4Y,$Wc "G8_21pX'gsG{ijXt`^E[g̐O +RRl.P LX[e9ػwn/8}iQvx,@{>0VERbÎKL:)րiImca5RZ$,L hI]bԙfϞ3ND9϶@.[xu@Ats~20k K~n$~!~d2lB=sy`p0Lcٺy`ͩ~ .uVhC8ÊDخ)eŵ1.a4RҤH7t@βl~e\lFXjV5}/ɆeݱH 9,ItLMOlMڮ">n41I_dw?HhwQ6ZHf8AqNo|%&*uIooz$/1o ebqy*9U9dVyrBdzdU.mwQbarb )%k q8']WýC9)ZBaL!Qw0Yr&cywG"YpDlb fh3Bϭ @3:]smc +Z'ӡt1)׭arv}Ƥ: IyDy +t֨0 -mݥkH5>A[\(MZQqkwb~;ư%ʎA>CPl!K.0'G*Sw;!hNŲIe i3J歄O9{ers|%A]e1 |/B)i&A<|8ĪE=k(H OLT>rMS}}aJ/L%T0Q3G+lW)$@F&jv]YAe}"}_uw&#ŏr$E< D.j/>N.ts-\>q=ilE" 덴"RNJ%Bi+U "ѽIQѦ\;\ѻL9KCs) %5~k\j͎m 3p^ tPV:SǜYԿ(X1cC̳S,a h p5rkc i6oN+%D6 e CiLp<ԅ44J/FX@"6G! bG OZX~P_!pԘ8X4 ز%Q$F$16_ARt(D:# *^5I!^ 1/LSgTb NS}g3d8VhIO>pb@kzb jX7(:e6Y*M Q,q*Lrp"QҙA͇d=݊=2 +!R{u"zF`jk^C ݭ A3 3q‰R;S7Y]Pjf}0d%d!41UP–w"4Mi|SGh4}QV3~bNy34;'!.:09=/#,e 3끡(kQeX'*u͇̗?JȸN3Q/rqdd{7=P-CڃYU6Z:KM߉YkYnнR(~2Y#&rA.q'h%Oce&*뵖ʺb:7I1_iPCdT|Jm܀Onpy?A[ #4sxLE0KĬ$ڜL鰂MbeLG>C2=\\wh`M=)g% 8|CLѫ[P1tV 9ڄhnFؔJz s\;Pt{qt%T Ŧ&'YN zG?ĩC]ڹB(9ҭԋVr2H)@j^' /O-ұ _jVolAgӁx%6i nԃ +c4 қ{r!BJ!$T|1_p=I8gW +7v)pfZ]I,/L.!KtU:d}SuQJ]h7GWL"Z3}QP|l`11w%P])ǵA• 9@FIՒI`Ua9".G `}Nj:>̤mFyaN6z3ⷷJoI]_y) ;"!< +@UμV +"W~M F!d8F Eƙ-)QAiKe wpq7a.IJy?Ky6" %\d|>_H@-4{䏳ڀx]&ϵ^NvPuӁ-O=}RC%-pG~aAO0XSrh@˳f3g&ny@W/l +@eJtR`SVe܌D\):P D@'p1& : /`-}Mh0۵V\&ތpb׹+@Ankf5%#$3MǶ'> Ca M,Hᢪ)7"=oYz:F{<=1a9a)BjYk@5kܸ. EHso5JO |[<$(Ez Ӈ|t[sGc#Wf[K! GUTUunMMK6+Όe;B=/찼eD)J ??ϙɬ Q5DKݵxV;g## 99JҖ!7q.U'L+hnhB4 +z'eт0yl+ivKA;?1 (g6qk +$G(_9"L J[=t|/JUUKL;rD`ѷL!iaadU%+K]eiwUf(N4V9MT’lե +tt>_j]$w>obY?;]z1Yh9my?m%5xU}׽sۧ?l,O갿5S ^oua!h~Wql`'9gxHH`Џ1RX,U!  S+NK%*zc $"rPM32Ĺ`fAl3e_*Hm wRW ')oF\w-&gfa+ S .RvGέW}뜏ky~xw|6(5(7-1-7h.8ˣD\(rF0_!%ʦ~nUG]ﳺ] +?hbTk 7wr@ƁNДm i?=~s` +8H\dBUm^=Cjg0|Њ(C/EqsECJBRi4 nߎWd 3+sa:E>3j҆*j Л*PRB\o g-q`$mb~İ#F>-}>\ojdV)#"}B% +SWNoX(k =OОDd r,ivSctɎ?T?ֻZWz/JN)n8n&'nCA~ȬhL< ޜTU#Y:۔V*Ġu'N:HLѪkHs>^pjKso{.5ruId$W''qOjz ',.O(U*ؤ)V~O)ڔr>7]EZL\&i/JXױZƶ_wPik˗H=gYD{F΍uS MM(7ęOvlT<{iq. Q1gĪuA9?m ӆ0U< iW6bK*\ť^u&p:}v yjpo6Z!PzA_=7re}P ༓g!K>CCB,Xq_NTaɥ@Za-%eI;nۿ^|^RaA{BsYҸW387Lf72 QZWK +~s%{Uz +#!PE]/vJG>KoE5NJ٬*oے=[_hK~6HkȈg9BgYuDdž([6@ `&ߦ%Y$4-e@+^F !V7ɖ{P_B|+E Z8^@ y8 v"*+ +}umir'Ct T~L"j*!)ΤpWg50XvUOؒspuW0,Vyn q}ÏAߺpB_ٝ̒m #qn EK)צ&۰H +㨧rL?:KhUP8K +96 + jS4R*C<@} jMAHtU"Y˻+ѪdNzA\4@@>܄$[zj0JO~tGMhv#$U(K8+s*2Ȑ=[D?"q+]̄~vM՞#ƫ|nv{ Qc+lYAd uBjGY 66IcjDqU9KbN="ËMHheYkR^m*hz hlz74xgMetL0VXFqG>$2qoX?t eIiQi{6"æHTQY =? £T3X<:tF=FgK2> Ȃ0w+3i+F.Z g.GѪZX D,-@!?Ũ.L=Hq#VT6#`rG+AAV9%W42,e2,ɇzPMʉJv\6X-ohBy5VVmKDZ71['M'^)8``M0"@E1[rG#h)Ťoz7X~Fnq1?l.0)=<FՀ6ўԨo.<*a.<Dnr,vjCJeuJg@=|VvL=o%`@ =VQy&&:js+&~-EQ k3rty6r,=Zw\Y me]2'F%v40jW ,3;{!_v1tl- sxHPXu/`G Y%NQgp^t҅Ͷ{ +up("m OuNZJ[h 2V+$ @3+'#+ +!wxcmD4oySfikRYHfaAhMҵGEOI,MKLhf w_DA2Kdlcg\ ,ڡY Q< YwؾFh 2 v.*8`ٶRSIm'D@Zh((# -xcɘׂuQt :ﵯ2O֊y)"Bd91Ҫ3 +>*5ƢQDNHM@,$ .̪h|<"DL~dF2F3Yɗ;TIuR¦ksw0a6oP4RZ TN]|ڞܫs +?} +2´hzHQ5dJjHFK9mo(qSX;ϺScY &ix|d%2$qSQ%ݘ!g0 gDI3AD a} 4Af$t'&єv ͚bMB1"`0'm6Otdx)v'z>J#^tPu ` X~*J/_3[ǧWUG )6"(IW.Gg.Ce #o:-f +\keVzf]ˤ$vwP?n:kȰIh!4SD3΅'AhnyQ3G7H"qAdPe[P8֖ VSb B|mx9RS6o3DoXXwCן[raXr)=qX=aNjƸtx MJd`KyrcDF_y' _QUXUS_fHNl+39CJ + !rnI κw9^Ji0VV\2onV.3Y_1Jr"4h}Jb}{zH& pcVD)F ΐQI +f۞o(CƁ\W˗mI>]'QI4_x4=#^JHpS(w6QRe[;ix}S쐥y[mA `Ǵ;jr9A:r82 +Ke zSE#Va}6ϑy8 @/yt< +Iy!:^ߨ'R%.}$:l½ +Ic7kˣNеZMTb UBSmCW6'&G_|Y6kNtYb6CǢD8ڄIS…^2'MrH@>lPj J4{.͝RC#d* ]GO_ϗsq?Բ m?+Rx7j;K}C00w8&℞T[k4d0056rzl;,i>@F`΍bE_*ƭ|D/Dm1x-#)v-;S Wa$ _#Xd,;yakUoO=paBdbl"7V ph8DӦPo4hL2H_̓&",~HGåg%ܯsz#\mTa[.ĄUPմ&Tc88T^DGVv%oxX-G~ɔ\]RrH# |߄x$]!4$N Z`nhʰS5+BS~8@?2:؆"UK/F򚛇qg*1eA`>ݔ<*$Jk{0"YTFs#Rݸ4 }1>X1kc0k d>hGBQ*v。h~(c&v?4jPțco폮*nЫ8P.>"aa6&hTM(n<ԙװcL척h>t¶wԻ$|j {/ m2]*jU]YSS)EHCòlZS EyZ-YuykB+(=_qPUap HݳiA8f8 LDA[}Me +m`:߂ad_=|>BճU)֋tVEGcjjO-uz?92#h:;l!FSdzi m +smǣY:$dkPo)aOr6eCh(CG7m[q`CRa]~cȎ c#cuTe[yJ)$uf. nK]&/+x^y\jIS&W8*Y.j4 9 ƿE;Ƨ| Iڍ"k;b펊8WMb`eF&hIub]"{3d`lt=Ƃ&o_GL֯k s[^":e@piѮcоaF*㈉;|0xlV]˴X2&m+vfn.9M>f2L:Ń&6kް_a*\❯:؍=2 ?{*V{)0Q{+ HKEc<{(0 Oa4Ji+UNvΙR$1BXFpOQEMHp ǥTo22t{o + +==k 7rcAgpX2RV8?I{fMIv9!J*ql6xE`.m +NHk1q i^P?4[vpX +db) Ώ0sR7wǞ MM^ua;:3# 4aK T?z?"`?"(=RgѼ>4Jh#֊R@U$6ыDLkt'@`.~+R0l3pDVzv:5m'9m)='g:)2'cC]yC;Vȗ$J0nKBD8NҍRqBi),o7C IO|nu5oɌᔖRbmia4ARP>zg`-SK<֋! #mr9@S/U+)ʃAI wS{QHB_d }SYZ|+aF8)!+7]/e9tq(V/88f3u +ϵJ^nwVlKۀqIi;*pZD++"]- hGvErfC%x!X^{ݶg9Of6/z *#DpxOxdB`w7x;yJbeA8@:`W4z,VPQm";ݳ?ce='uUuILm RՇ+Puua';)lt<-B 1gaT"X<< GL7Un養@v5U#MgLЛ֯LK}(X '\B:N;V6KwiF +t: ;Q 5, bW+ EDMfvlg-r*A=Ϙ#ʸ͞|ݸ;'lqMG<0سa25x=;Or-Gʀ:GsKyC-!擰b@1Yz`c15Ptˬ-ZR`R|'KCܕ|7_9'tM YJT$)ΥvfPuXr-P{[R_>5^UhG9,^q'.7|I'~l=?& dy(IBJ5*9xM2q5%Gf!YUvdY*W_ k Xу煠'1+Q($P]dZt8sc%@\ȋZA|FK^*ƕP6L"Hxޡc̠˫üYo6>i2tIU_c`!Ҫ;N?"¹_:D5'-=:2lz2wI`]JF!&e\:Ck%WIАaOChxNb"?]Tta=%'Уb$՜i"e9D, "2 1}g3qg< sk0d@ tRyv`&tU]07=/=`c)lzp54Z!R?N*~"g ]mSAR^!;+5HCtѯv,nb!)(76[җd;Eq*\{DX\#B L#< m4pR#XEV$f}4 X4M>}麈1t=烔\*6zeǓ!gt84nbmITpJLoFl0k6:Bo-("l3CX@<pWQʦ-a'%&`DtcҸ_Mq*}.jܵZ6@7[CuA٥∰qҽx\Ljsug&KՃt,@8@ ڪHgτxnF+֡̏!b9 )[mE{i +E^;=u(d o.G?H> ͟(LSeS!T|kO +َ'6za\+\:DtD>o݆G۟8$Z*)IZeC%JtNNu9YH4 c5(:U"/`j{L9PH)}u W k @o>>X^ZjAwLZ_}3<{I)0zc^!'6 *ϛ@B "c101E&PbO7A0 W$+B2rTEVw{hsKڇߗ?[%lO:Ĥ}vrư+*a ^r, 9BGm>YCEAHDW0(sCM¯T^{ǿ7tH&EeڴwX$A"`pE~-sxu=Pq ~؈ 2#Wj +2L>5c[ K"LW,O3BM2Cu?ה;cnHQ IB"7$WjOҙyvgYrt]㫜Q ۾%/])*my-Iz +M)kC&2+(#˛Ma,=rkt|@80SW=nYK+ujO$;kzJ3@(~IV1H)qGH1Ϝ#{TC1丟,y١(eUs)&[:0Gӑ9+C^ +G4"=4GxSGC3fq6 _H _!Jw(yl&65I"ﳑ,Zp1m3?XgdC@ohw]>2 +ܹߌ6^ @wfwbZH! TX[U/7w7$K?.y%w p(R`x95 eG'#k*OaMsۏ OȷzAydzZpasmfxL?%GKB$0V|oͼbnE"DVi,KD0.b +|ȃ*R.}TAs~Cʾi HH`* #} fdRH" Q<98e?b.NoJ<ż\H@4$v^{W- +(xД0RCndZN\=ywYXPicƯ$#^1@dRw`sO'kmGAx~\qYcahiWUZa]L@T6^>J7K&p l1Ku+$$"Micm"J=;Ʈ /'ZMK4Z5Z¶fH^GLq|VNLANzcmn)=59 EbF|7ZeS>ׅb~ 7tII$q1xLTeiR:f0(an 1 Bѕ\͍Ȝn*L1JJU2%q?TVRv56FA|L2?&3>gy7{;UQi556++WRkCFQhrќL6ҐC6FҙF2%E -1תʯ\mȏBw26Όkݩ1mch̦/2 2Mm(,}:;~TV©j&j&D>KQ]!3F.FԒ6eHnP*vS%!}]膴"~hj~4UqĦƅ 5n>5Ċ4!a4UײEik/AvhTC솘~QbゟlϨ}v٭1a+ѕVwT>٬f2BN07R#l ORU+cH31.NN'C5D:>}rn$F$QSU\s*7-g.x_NH자sMj^/ǫ nDy%sR2 Z !1|n*?Ɏm&>2Xl4b#R}Djr2#U9)qG>'s&$UmhehEe·DH GԏgNfl~qR•{[2d\I|3B_7GEl=Dr oC*)Io>ls51T*3t|7dfYe$"lk26u[:#z|E-2[glu^l3+͔}h9xWM{Ur!iFdNb/̞V=5ִJtEsU1TMON.ȕg+U#VgR$sQ)1Gbkd7i6FD\\]f+ȑ8'C4R)3?CSr`͕VdIJ7SLE\S3rO4W*QQcTSQ})R>UCYu,&Jd YcGCXb2( &VX/zfBAUXD$R`p0BSp CᄃV YV}9UEbw;\G*Xly֛5GlH#7bI:SH퀟䷞"x2UZPYtĖYMȈPkiJX+ϰjѐPnSRwdfNm3MĆF5DTB'W\3!eʷgLx,2u%XK IF^O/Iw+TVB(׌|fnu#jZj|F[vtd:Z/ء+Z,F.t(0vPH.$#W׵S(> 3rvd2"D+I 6)1* <_ +* +LbDCxp +^W(CM be9W *<"CEWdͱ^- +JS>C<͋fr鐍/"fߧ55On%-͙^r~UI1oԙsWd>ɨTAgϥ_gSNO&!TRe +2UT,+N  +Yq(rXa# &vbpހP@sGʝ' VbAў1@|RM6F})ؕt +jФH5H`` A + +܃ !sd;:m"7t:)$(J!A4(@2]|@WuQ16U{I]UD]3xE(wYZoD*uJ39# #+~3N^AGh6/Aj.JBqnympݚ@ndJ/+Qb %$1#r"(v A*6ony/'7k%dZn9ɘH%GPp A Jݔf:C3R 4 YT{S2;E&%QDqu^yBF3DLjV#4~ӂ5=N6:y؂" 1gԍ)ًJ4n:tx Aѱ61~7pXL[DCܯf͝^BA(7ot_ tn%aQY_$}<85dL'kW$m:>,!<Ǭᔍt*/lč yJxh]_Ҿ$_@5w =V2sB)̄8\\)EWegtPDg/7dChyɆܝiBkYєQuLK?w22G2䫱/oB<4Mg 3utq<.=cliY\5<3%冔KFeT+(:KjcRǙٜF"e46TUk )wg]ʪc1O7Ud$H/ȞAXF䐎WTS^ HК*z Y. )O)Og"FJ]:t37lD*fJzGwc=hCHeb;vS@|j"gdoAw(.\q:p1kQC*e( +O%+ =yVٰ|9SUi2/ˍl&YCd'֢ Ł +!t΋ꤖL@@1@BP,&Z2* b 1@1 O ./9f]+ dz|#FN5gH\X(EJ}ՅmJs ֶ!ȞrsV 9EE˘J<'  "kxFkQ[/ D3*珈yb%E{w@5L`/=n Te/w1-{P#/2DUl$wt #im]wV^Gmkrzj,;JU(8Щ]sZ,5gO-N÷w-O,p,$݇RZ7_&#Ax +ÃѹZnhz $Yx*5Lꝸ̅㰢qdC+-Xd="~sGA'yV$.X,[1@n"q3^.: ,,Ina/x,14H/M:/&cL#m +UUM)e7Ҥ<1#5!o_ zd=*2TJ9!6jOoe%;'c5 PZ8pF] k/N?CB aG)-j3~%>Hs.BB}zgԑzQؓΒl?~AA:ԃf8BnϦz*S5#wԲ26e)0(w7< If!mƛ!w,wH.5cCT-L=q<5Qt|l*&Ţ0*1"_6;xv!=;)DЖ`0H8cEL0RĚ@Zgav J\?7,J +'5ۑ,3f?q~3OVW?/ +y2 1Pˤ" d* )i8@^ ]b&(?>2dqKJ0? | u9ZKcە0؅Lk]k.PaPAbc.f}_N q]|_kb +' 74 <습*dntW=ݰ:'ϕ"s;hwr3YM\Xt5,c񩾠NJ1m5w5QJ${BASB7u4 B;GY2Ϗ}4DP Y"Nq1qroHEƲt#gßcdMWB,=p\v^2KiQfoHF#i2s}bu1a,OꀽC<$,芭VT]^iSt>VlQIƭ#5*h̊ +ERA6- `ɸ})o-+~h ҨRM:%w cK\_xdvTMG &A8Md҇Un{$ v NÈ2 {SV +K H1mSN#Cأ\Qp֕" L-*( +pC&؞# x|+ʡ?~z/^&pԚ}^إlqxȜBˢl FD1 +5e?(n'"c|+qlr:KB.& i!*>2mZ,nS1 +) +Dn_Z}{ b|AV,L$G\=i{6OW=s^~'fS%Ƃ=J)bDޤ•(Ux8b@m'dF7 EqisVЌ*|LďuiL!+*3Y 0|nS`LyŨHȴ[#G V׎DF˟=tmH{LV8;nyCk$1goQָŞá;W +\evA~I>:(ǐEDGETi%_I]-ϻ?z4&4Q,yE2/ɓ +(r|xQv&ުt(tOB0=OĪTZ{{f~xrẗkDf0]%Ut%fFt\!@l .nd0~y0lYJ؏S!29dE̵o3:}AAMR(`ʹ#GTg?aĨDjs鉀 avkr+.g5Y!*e}Gt68}@Ae@!CpCdKNI9*a[aP2>CB lff}1fz#7!')ZVT + -#N9RTs`uB6_YX وDu a$]D)`vC?ԛdIBqjt-lʾO=h R dөgjhL@yғ xl?.)i{N5FWUMȉ R1+n*Kyu΁Us+ Qo- _R_?ʋua w\(jWT`} +q)bjq/ ζ;VAڤȣp;Itv:,_hD`{ORtFȼN+q@ Wd?Z]}/e%U'x-V8Ra^)E6*s D?!$4aIHLa;|n>bżaw)ftU cNm[CBZ{T3\Qh%c]%Ή1ܗ +t &ifI_Wg̈ ( Y{5Ra=PB} ID d0cr(W>i>DiPs\YXeQk Ѭ0$ZƊ"ѣxQfG`֬\{Γw| 2I̪;~Zg# 0¬I9?Lz&-Nj X*|M>NU Oj.IԢDw )^F>; %}kb_yM6/)ᗖYdK 7}Fm6>nGkhC"q##`: +Ixu)>@r>#:sw۰Zа48@Q$RP+ `ƁZwbdAIHH²/TϢ9:L g4J>.ƤRݦn)19FzW\f5V+ūIRvȼ$ˆA=pv5V&{) {Q*rByQ%~h#HpXd$xA^5SHҽgrФBDְ3z+_T1 +tpVCP-fA!9EmdeE8MQ#ܚ?~\J8\O3SlFn,-f6ŠL37G?'0v9keF_kS ePtJU 0[@i.&SA  E IN~C$R2_~: =L"zLsy87{X<{}i0s gX([2&)Qm nCV_mN 6*بuT֟s v*Q$)[\G)+Һ ,ysCHeͬ)hc4om]A1Ȋ<πL!CAaX"RIv#(qޙAb5&nFw!Y^p07=j#MxvQ$Ll-I Wf])q@4G +vmUjYN=P+.\/g̊rEXj8W|z@Ua׫8Ku)Hl 㻉̌KF9KQic= r4KeQόaa ը CAP+/y,M+wyQQ\"  +j㼝T=E$),.D: 2ïMB2Eŝ/Ye%`|+לܩ#N[_I62$]&ՅX& ߛ;r%eډnO妮^B:nЀn2fb`xG;Ոl&\ eyND]&x+; + mw`&B(DVkkl0KP^zɌQ1V$sVe/Y"4FdC֨_KZF?x"!C*mJ{|oBȠ4mJ1?X>SNMWH*ez[hYjNgx m]h.lc@eJCH +(?C\]y*+޽Qho/Σ>{F01/Mc<½ttA7B%>TS,w—q +K/*ыH%) +@21oN+c%D +O?h_BZP,l%# F%Ss?#Z3N> s,>Th?$8ݘKªq|+мxl_X^%d@ UMx-L<R ɶYhyӶbݜOvEO~mLb e6AF%Ed]I& #-q6-ݬw+I6{M S q3Qm3^l%O&>iFٲp3C^ L+G0p(*p;g~`kߕ*iEɷ>-Aݦfe`%_ѷV ґR TYsnomZP@*[ilmL)NGJ ƟW%[<9l!ҧoi\I*$.L+c #YJԾ9]$qo|9UzCVk9&h٤OI1VײDa1 m!7y/f1Onkd1 E9[#koNe5D>AL?9 JB^4mړ;bNK;YU + Fpv#6;?vo#F9.dƈ8'G b=:l?IV;1JFuնQ1٢T9'UN1Ǧk)ZGL'֋{xBQڢXgWXsm;ڨ(SfC`ӟ(qޝJYύy_E` fFI͒W?wK[l~܈j>T2$:1o'F_LDcv2,EyEF^i[J2-'((( ^~մZ|`kx6?D=!7BN%,l ?tI]c'&LJhH[ ڌYS;<]7O%BUi%,x6kt.BG"am_i ()]i~?zlCzBĎ=kL  t610q!*_S%IenϏ*hjٚ->@>藦uv'Vپ>umM+1 3و'`Q܂Glܶo"!9#""C7ZLwŐx^>`tP,Y3ba +t5vp=BKo\Qu$ʂu(kaټuk`Y wUD$u'/S)D~!fQ)7-`sw +HoB.jCVp &)bgt,.";|3 -c’2Ja_=c5T<M<|㿎D/TJ; ɲqde4IcA3/to&nGIim&rfp%]cG^FzfFۙȽBmڴ^@ee0gfׇ ˽GmB{?2 "b ₈/-p 5}Ͻa:'lIF Ld&kfrfU"o_fp mz:"o[aL``\=̚J8,k &5h磦XܷvQۄF-YW_QQ,SǽoTn_{:oe&̀gw8747Bv}Ћ]nò>x!cii;%J-N+r60\ hoy]#0^YfkfY + Q(C;|gRoPIGG8'x6Ɛ*  *ݬb_ +hi;(yva-+ ;: +c8bw|g}*F`Xr'.p( ˘DHSӊ"~":nho7(ƂgE`u;Fӄy=77Ŀ/.]S +^U:tEHn@ =YRy+ +|kٝ܂>]{:h7ބFD`,bNm2 +Hh`r})O!XM[ScWFY)`?"ЩlR{Uˬɿ=@+բӣsTP-7ߧ!lUE(Qv3A 統s/ ,-u 0FlΩ~OЗUšf5ڞ8ly.'afq(7vM!kFBUrdJA67h~ KK;rH:D ^^%g [߹ l`'A<!T KsfTHHB?|߭JhvdcڂWKpn6(zuSܯBNa.٬tMY^wNh1uĮzӟH#a2Y2ٌ>G?s散%KVM_n+e Ӆvs9?fڮ ;`ǓH4x@Z&QK]FqCnтq:.SګUxxU/m%3U8[dF h/paL7ɒm8^f&@G=dn@1Aޗ)3uyر*en{ n$ +iKuz(w,.VډU.Xy6n\__E=> >뵵+hp6 RjF 3mGxu }Օ3Ҙ5/A=U|̡uV.yݪ1J_cgVAWK,J{*`17W.M>KQX&mmqی-3yiؼ߱/lU= oPDg}Lo">t6Sg݃H{itfjݍ"tK(he$'2tpúۇ#%ëeC]lH)㣌]_7hV\c|Q6]ZՑ, 'cخl!U,CR zE Rd6Eq#>sH;}.F gs/W%8„0l$.Z Do8#[i +bYYNvŏq^QfwYz}}@CT_ JY"-B;}8{!BGƠ3gNxM_wOA9Dp51ɖ"w2 +$Lm~俹VR#J[\@cw&hm)V%[ڲ.0m; JO@(A wff@N7,8~Did\UHWj:WsF (0ju wInIHIBM` z?W*2#YmCS [`R/kN,N6@˜[onuξRIZBa%t +@Y/6ؚ[]-pe }4cT= %GNo""M ZEU7i1]}jl:~wIS}x.y>h5sL3VJ7VhEh[^ +.C `;isJmƏE?Y"Ա3/ȳk[{񽳀i>)>;|PS#Di=jOw2`?1spQr1LB5*T9Oqh\oc%K +|8R &K`yݸ0?KN,fcc;H (Ru=p:}#dm)Wb7:^)^H2>d[`B}z*$1uks!(/nQr p "Aە^g$gA[T2(劸! +FrA $G@–(W&bbyXg=^LIwCW]w (]Ȳu U 2)=7` (}=8H!b㺨VoB\$S%3g?>=P_sbґײ$X* p)_(lA{վW;^=\,'ٳ( +ŞUC^csP /eI`+B*yżg=+ N$$eCކU|&ij օҁͣw67`{/I{lGp2Zu^AL:(h!sFe+JI戼WϺXH~vA 59c t$RR.@1Ԝ8 Ud`hծ4: &soRy^.NC#O\㠟IƬj^Bj(ѹ*5DcH ]CB@eh$~w"ڤX +`r[3F[6@e'?}و)1/>|lATa%NϠ˛H*UC-r{$vNBt?m&`1J˛C* H`bgԆ}]x%Œ\80!Xܽ. Z4E+cʒ9e`eQ @E7H;%kaFAi؝%*t^$5&n'WgܑE[6gbEp?M.'82b|Il%$u:s0j kF}ljH:|o"QdH$+iu4Q@G0%k>~;:;ϐ؝n= ws/t V9AAN }UZ˞CvQVM-ۘYp`OEp謤*O@Âv8 POG27ne,;$ĔMJఐ}=ÉpS%W XPYf H.Yqn\*ؕ-AӰ5бl;3|P?4^T.8BlHbpP-WOF&Vr5eo3 }gcR$?sSS``S]&a^s0yN|sV'Km"ϷһY-(F`LX4H]|D bMd~$#$ܴN`0@7F̲*q*D3H ݫ$DoueG|§ nC.qS`/yZRd#st+JMX_[a lFF5PD/"po57e1(cF_ރ?iH"ሐ ~~:N&60jU\CW>+7W-LuiSmU8ZN +;0xSA'-޾>hE夭\C ҇.m"ף&;jK-O;} 4a +6֛BL?֐%DI.᠃x5* M2T +.q: Ret˺oCsq$p@iQ 7 ˎ8hEu@6gXEGTJH&Q` t&G0X<M$5BpϏJEz,{I)bW眪OPr,cORӓ>t>t~m'O3J&r4F^;Ί\+E]EL^!SՀN w?|NEQxQyP7X3)wr$7Eì;Vu%K^X4}I*r֞C8^>JzVT㒒Omc@5~㎳*&ۈNum2‘Nnˆg"찫/`&ڹ'7RHhp-Z?H{Q%0]0TϾ*s: >ZyInT`Xܸ c^sLLR?Uz4R(є@ĭ|YAZMKR-LhyyED 3lhPR ]>s?K#:S$#rŭ8+0:Y@ Ѷ<_#/HލM094n@( .ff ebG{ГYhoOrdDh +qï0xPt'K0sw]Z5>!o}l=ƀcnNW]GʒJ1aX uX`w!JX&f2KT7,t$4\ŽkN,x%48t S̯i"2/b(hGX6NqqK)gU4`<ʈ*#2`3P)_p2q2wP,VeZnt(_%Nznx%+Y?fj&꾴q GWKF6%>tP?" +YB{22%02997WgGEAOq%)OuU|tIx}&4 ;C5)C2n +Y!S1b $$a럈3:T_1<0'% ܴC<slwxLxUN曔UMݘn:("|Qwpc2X1tot|p_"'ګ;vw{_$Cu&楢>=WLbULԃl{ƱO~%q"u/آ֎İťK( u1)fK(Z:Ҹ94H0ìeHM`;⴫ĪCZkHڍaos{3שVZ2)v#_e˥~%ާFf꾅v cRk;i͂D6t6 ˃LR_4&!`D6!*18\ҎveКb ȽFЬ1Y)F@6̏~04KEZ{0"zЧ +!Zj#-{Ii& Mwj/B[DZd IP`lڎFyq9|۸h R;vӑKHi{8@?/ln _ba4Zh#y7enԖtҤQJ#zzL?Aau+gq{/}ͻSD~MlMx9E:ſGMmXLp d3RnЁvDl+,xa tQ]ܥǞ(}uc(Z`odʏՃĬpSZwϹuM [0}H>4}ΒHB\`"Z1)r7ݞ%)RplHFڇ7U$cx.61Plr.%2:)c&W/hr"d6*Mя[F3T~M׺GNTL, C'5>ο[^D@V'РXݸtCj&,>h3O|Fd?𸇓Rgր6^/ZܼM֏AN.BR$.IE~bOhdKT)}4G\f%LD+u@p+~9s T]uyMf?].@4 b"L} +wBe'x խ* oͷNBsC3C*Mf$iQR!QHrl&5 `qddi(D&۩2._i݋a4OY7 yнJ/9irOG1_ +.NhE(Dd;! endstream endobj 147 0 obj [/Indexed/DeviceRGB 255 148 0 R] endobj 148 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX$6Ra!<<'!!!*'!!rrmPX()~> endstream endobj 35 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 36 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 37 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm1 Do +Q + endstream endobj 38 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 1155.6207 882.8037 Tm +(TRUST4)Tj +ET + endstream endobj 39 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 964.4318 911.4349 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 964.4318 911.4349 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 40 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 969.174 884.1221 Tm +<0107011401500150018E00EA015B012D0114018E>Tj +ET + endstream endobj 41 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 42 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 43 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 44 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 45 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 46 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 314.8913 412.502 Tm +<001E01A80150014D023F0227023F>Tj +0 -1.2 Td +<01950138015B012D0150011402330107011401500150023F>Tj +0 -1.2 Td +<00A40072000101950114018D>Tj +ET + endstream endobj 47 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 48 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm1 Do +Q +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm2 Do +Q + endstream endobj 49 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 8.504 w 42.52 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 50 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm1 Do +Q + endstream endobj 51 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 52 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 53 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 54 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 55 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 56 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 57 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm1 Do +Q + endstream endobj 58 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 59 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 60 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 61 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 62 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 63 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 64 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 65 0 obj <>>>/Subtype/Form>>stream +0 0 0 RG +7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +q 1 0 0 1 156.4448 670.5146 cm +0 0 m +99.421 -0.792 l +S +Q + endstream endobj 66 0 obj <>>>/Subtype/Form>>stream +0 0 0 RG +7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +q 1 0 0 1 412.6205 668.9421 cm +0 0 m +-59.999 0.297 l +S +Q + endstream endobj 67 0 obj <>>>/Subtype/Form>>stream +1 0.6 1 RG +7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +q 1 0 0 1 835.1846 711.6359 cm +0 0 m +-18.707 0.093 l +-28.003 0.139 -37.042 7.338 -43.575 15.344 c +-49.774 22.939 l +S +Q + endstream endobj 68 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 69 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 70 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 71 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 72 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 73 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 74 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 75 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 76 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 77 0 obj <>>>/Subtype/Form>>stream +0 0 0 RG +7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +q 1 0 0 1 153.4415 684.0294 cm +0 0 m +0 -27.593 l +S +Q + endstream endobj 78 0 obj <>>>/Subtype/Form>>stream +0 0 0 RG +7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +q 1 0 0 1 1411.6636 721.5707 cm +0 0 m +-27.592 0.15 l +S +Q + endstream endobj 79 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 29.9997 -0.1488 0.1488 29.9997 104.0402 882.0098 Tm +(QC and sequence assembly)Tj +ET + endstream endobj 80 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 81 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 29.9997 -0.1488 0.1488 29.9997 1424.6973 884.1832 Tm +(V\(D\)J annotation )Tj +/C2_0 1 Tf +1.255 -1.2 Td +<00EA015B010E023F01D6015001A10114018E0138015B012D>Tj +ET + endstream endobj 82 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 651.6687 910.1168 cm +0 0 m +104.107 0 l +109.029 0 113.02 -8.912 113.02 -19.906 c +113.02 -30.9 109.029 -39.812 104.107 -39.812 c +0 -39.812 l +-4.922 -39.812 -8.913 -30.9 -8.913 -19.906 c +-8.913 -8.912 -4.922 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 651.6687 910.1168 cm +0 0 m +104.107 0 l +109.029 0 113.02 -8.912 113.02 -19.906 c +113.02 -30.9 109.029 -39.812 104.107 -39.812 c +0 -39.812 l +-4.922 -39.812 -8.913 -30.9 -8.913 -19.906 c +-8.913 -8.912 -4.922 0 0 0 c +h +S +Q + endstream endobj 83 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 674.5909 884.1875 Tm +(fastp)Tj +ET + endstream endobj 84 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 795.6336 910.1168 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 795.6336 910.1168 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 85 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 815.3756 882.8037 Tm +[(pREST)4 (O)]TJ +ET + endstream endobj 86 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 1391.5535 156.8407 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.139 -30.9 -12.139 -19.906 c +-12.139 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 1391.5535 156.8407 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.139 -30.9 -12.139 -19.906 c +-12.139 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 87 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 1403.3634 129.5278 Tm +(EnchantR)Tj +ET + endstream endobj 88 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 1391.5535 99.9452 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.139 -30.9 -12.139 -19.906 c +-12.139 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 1391.5535 99.9452 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.139 -30.9 -12.139 -19.906 c +-12.139 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 89 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 1401.2955 72.6323 Tm +<001F013400EA015B012D01140233007D>Tj +ET + endstream endobj 90 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 1571.4724 99.9452 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 1571.4724 99.9452 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 91 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 92 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 1589.2145 72.6323 Tm +<0051012D001E0066000100AB00B8>Tj +ET + endstream endobj 93 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 29.9997 -0.1488 0.1488 29.9997 1828.5469 33.2921 Tm +<00A3001F023F01D6015001A10114018E0138015B012D>Tj +ET + endstream endobj 94 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2135.0818 80.4583 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.139 -30.9 -12.139 -19.906 c +-12.139 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2135.0818 80.4583 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.139 -30.9 -12.139 -19.906 c +-12.139 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 95 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2146.8918 53.1455 Tm +(EnchantR)Tj +ET + endstream endobj 96 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2308.3052 80.9029 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2308.3052 80.9029 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 97 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2318.0476 53.5899 Tm +<001F013400EA015B012D01140233007D>Tj +ET + endstream endobj 98 0 obj <>>>/Subtype/Form>>stream +0 0 0 RG +7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +q 1 0 0 1 1671.1589 615.7047 cm +0 0 m +0.15 27.592 l +S +Q + endstream endobj 99 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +-0.009 Tc 0.009 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2239.7627 160.0706 Tm +(Bulk)Tj +ET + endstream endobj 100 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +-0.009 Tc 0.009 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2355.9163 160.2197 Tm +(Single-cell)Tj +ET + endstream endobj 101 0 obj <>>>/Subtype/Form>>stream +0 0 0 RG +7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +q 1 0 0 1 2496.8623 722.3652 cm +0 0 m +-27.592 0.15 l +S +Q + endstream endobj 102 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 103 0 obj <>>>/Subtype/Form>>stream +0 0 0 RG +7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +q 1 0 0 1 2739.1147 647.0047 cm +0 0 m +0.15 27.592 l +S +Q + endstream endobj 104 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 29.9997 -0.1488 0.1488 29.9997 2177.595 878.0566 Tm +[(Clonal analy)25 (sis)]TJ +ET + endstream endobj 105 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2337.7021 844.7442 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2337.7021 844.7442 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 106 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2359.7747 817.4316 Tm +(SHazaM)Tj +ET + endstream endobj 107 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2171.488 845.4617 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2171.488 845.4617 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 108 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2194.2302 818.1484 Tm +[<00250167>32 <01C201950114018E>]TJ +ET + endstream endobj 109 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +-0.009 Tc 0.009 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 668.8971 255.1445 Tm +(Sans-umi)Tj +ET + endstream endobj 110 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +-0.009 Tc 0.009 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 850.1027 255.1455 Tm +(UMI-based)Tj +ET + endstream endobj 111 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +-0.009 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 1045.0675 255.1455 Tm +(Similarity clustering)Tj +ET + endstream endobj 112 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 113 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 114 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 115 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 29.9997 -0.1488 0.1488 29.9997 2573.2378 878.5613 Tm +[<00A40114018B0114018E01A101670138018E>17 <0114023F00EA015B00EA015001C8>25 <019501380195023F>]TJ +1.484 -1.2 Td +[<00EA015B010E023F018E>17.1 <0114018B0167018E01A10138015B012D>]TJ +ET + endstream endobj 116 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2650.0701 580.4716 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2650.0701 580.4716 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 117 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2661.1423 553.1592 Tm +<0001015000EA014D00EA01D200EA0159>Tj +ET + endstream endobj 118 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2650.0701 525.3039 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2650.0701 525.3039 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 119 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2661.8801 497.9912 Tm +(EnchantR)Tj +ET + endstream endobj 120 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2650.0701 470.1362 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2650.0701 470.1362 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 121 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2666.8801 442.8232 Tm +(MultiQC)Tj +ET + endstream endobj 122 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 123 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 124 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm1 Do +Q + endstream endobj 125 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2171.488 790.0267 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2171.488 790.0267 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 126 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2191.2302 762.7139 Tm +<00AB001F007D00A10114018E>Tj +ET + endstream endobj 127 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 128 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 129 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 8.504 w 42.52 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 130 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 8.504 w 42.52 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 131 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 2337.7021 790.0267 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 2337.7021 790.0267 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 132 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 2350.4446 762.7139 Tm +(EnchantR)Tj +ET + endstream endobj 133 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 8.504 w 42.52 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 134 0 obj <>/ExtGState<>/ProcSet[/PDF/ImageC/ImageI]/XObject<>>>/Subtype/Form>>stream +q +/GS0 gs +421.2616775 0 0 234.335274 309.5232239 -6.1528094 cm +/Im0 Do +Q + endstream endobj 135 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 1.425 w 11.339 M 0 j 0 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 136 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 137 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +-0.009 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 431.7926 255.1455 Tm +(Bulk AIRRseq:)Tj +ET + endstream endobj 138 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 139 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 62.7941 776.3721 Tm +<001E01A80150014D023F0001005100A400A401950114018D>Tj +ET + endstream endobj 140 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 23.9998 -0.119 0.119 23.9998 61.4679 570.0137 Tm +<00AB0138015B012D0150011402330107011401500150023F>Tj +0 -1.2 Td +<0001005100A400A401950114018D>Tj +ET + endstream endobj 141 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 142 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 143 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 144 0 obj <>/XObject<>>>/Subtype/Form>>stream +q +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 7.5 w 11.339 M 0 j 1 J []0 d +/GS0 gs +0 TL/Fm0 Do +Q + endstream endobj 145 0 obj <>>>/Subtype/Form>>stream +0.141 0.686 0.388 rg +/GS0 gs +q 1 0 0 1 1135.8784 910.1168 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +f +Q +0.141 0.686 0.388 RG +0.85 w 11.339 M 2 j 2 J []0 d +q 1 0 0 1 1135.8784 910.1168 cm +0 0 m +130.79 0 l +137.494 0 142.928 -8.912 142.928 -19.906 c +142.928 -30.9 137.494 -39.812 130.79 -39.812 c +0 -39.812 l +-6.704 -39.812 -12.138 -30.9 -12.138 -19.906 c +-12.138 -8.912 -6.704 0 0 0 c +h +S +Q + endstream endobj 324 0 obj <> endobj 30 0 obj <> endobj 322 0 obj <> endobj 323 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +-0.035 Tc 0.035 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 872.5543 520.1307 Tm +[(vd)-35 (j)]TJ +ET + endstream endobj 325 0 obj <> endobj 22 0 obj <> endobj 326 0 obj <> endobj 327 0 obj <>stream +H| XUs""ʮ^{ (F+//l}#Q#.]5רiibXb:*CuNwoFv̺v!蛕36u֚NԙzJS]o]j|3-ϺjOkSQ&먧Ʈ5kk&!A1~BK`5:(%5Q %0ٗ:);RONAYüGOTI[h!S\Ik9k.Z3W Ђ0-R;םu]zGXOsb}^ߢlކnX ?#Ԉ1\#Xnl3v=q8m5 ŜhNlibqx[tK%bIoubmՅU^j;'Eֱ/+~[6@ cXiX|4_uCԃ(=F}$=[l,FShn66b9eeTbe\ժ/hy9>پ$kNTTzަu]XՕZku5Ϛ xjJF=kꇾ5⧇]*+USwzvճ¶"̨HZ~dyfyZH* ʛ}_fT:t|5/4C(ӺZq6Y-.)*mޫVk FmE+նk{ vO{hQn*V~PlL+lrIqL~/-uYJW vZI#.͕of[2Z"Sh6El_:`c ^4wlz'Cуpb0TD2{`0;" >Hg?Gb1pq4f0ә14c!q"ֲ@ExkPb~07 7=i)ng7yp/n}|“gqg^x k*͡Yx!BKTtH`BxSЂPhjD%:$1K9orv{T~8S8MXiX<rLNʻrJNBY$KTFZ)d̗"Y.e)2]Pz"}vE`2a +G22\-\ \\c܌܂\C| 'e8]sG^x1R*W~3W2pcQZЉ@MND#0qnXxb9X\,d6V3k8Ŝ78s..>1\ \;*hw/KHG sdxKUz)2Ie)ZmpekQOJ^0V| +WZtwwwsץl,>>~>>C Kn)0&CA-m'v +mة~QM#B<چąaD[̺S ["E=|,vvnjhF¬%%#LJE Όl;߻wGWL~rr~W:dE"R-°Q_\W{lSwMv\ׯؾ~_;_o'~Ic]|+;wi]lk0TQQEk [QZdz +{;3.vl/a][$'AF pݬ=+V'e J :g;_8+e>.<. +'vb kџSeeu%[ʢILuXe33+Dj`D1C+/ f1W/Mj̘KWHK4O'M@uX+6 =$؋#O F2hF" Ј(9y!5h\:.Oʼq4O3wcR~yipʥ\-B;FBbSް&e!Ab*f''g}%gT)|faV)uh /Fi UF#![-z dJD.;y\R3K/uJ RncLYR:2Rsi1jaK\uy`gOF4g˱s$ ޺v;ΜOVrʱQluA=JJJe5PqK8TK7֘ +:tϣ.Ȑr| P^[NQJ?xs( đD8r}PWe_xLst lOeN8FF% +N%sdXgEYFpmHmvUjwr *||A܁/3#5T,5Y}?<);gz>EҸ < Ⱦ'B$gv~ F@6$ÌBVg3DgpTۣQBNB%7w ^)j]sv +xހyߨ疰%qS8+Z)>ۢ8HCW*2ʺe,Wt&&4ۭs8Ff=ˆ(uIfm^3oqhzG:c}YM2Hmvڴn,قL>Mj`K`"֐[ vGq``/i/Ncgz4QvZcDa@6HhkKĆC5 nh1 O-,nE'Sfp[GJq0""zl/$vӦE7bS ޢg9SY?jIVǢDdHKqہQXoR5+iq6@ɫ{mmX8lB[̆-İm?o\Ϗf Kr}ξ!:jt_ `֕-ɰ=Y Y9 6=cIOY,.ͥo{} [tb-)bo@u<1IEZZ,_gX:JӖF^ VZ"WQc@E/mx0Wx -B']-Bxnm} ܌ hZs¨qwwk4qG? BA7V<1Ikbv74 @{?UAgc[H l0-k6̖TUtZ>Vق\𴺰w."3qDV.sYa/zN;Sjl!#2(W IA Q뚿vʃ5L ZAY 6 C_1UVa\L4R!QS0QS)ErAAq+*tAIM]Sq#cfꏬV[N+n?aژlL,{=ŋ>ys9dgƠ%O5XV =؀ Ig],8a+눓77:O#݂ +YbYNىbyWUR̺-ÈO% Í.F+FJݟD>MPhxL6q6qnG^R;w~KoŹL/P`Y^L[|Xrſ翸/0 E?/!J} ?3:5[~}9vzM,|[e^TE_9qXȫH<qlxr,/a𿕉YHy cE EHd4#HEl$+"ݰxI!YBI d┿3T}Wq]8+,x18O{Fb1IxwLq{wshsx9Z +̩ruw,-@> ߅+~Ar<4%rz'Hoշfm  Ch$!# !1H>|$Hdaɵ[%\}+*PHl2~ Q.]X+z2?bc[6M{]j9ey j&[A-Ϭ +#X2Rb1/u>HG$|*ڕ~Fw6+{H==Wˈ- XWϨ$=]ϋ_λrB8>_jq endstream endobj 320 0 obj <> endobj 321 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 847.0328 522.368 Tm +(Cellranger)Tj +ET + endstream endobj 328 0 obj <> endobj 318 0 obj <> endobj 319 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 19.9996 -0.0992 0.0992 19.9996 61.4224 619.297 Tm +(Samplesheet)Tj +ET + endstream endobj 329 0 obj <> endobj 316 0 obj <> endobj 317 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 19.9996 -0.0992 0.0992 19.9996 66.5806 382.5641 Tm +(Samplesheet)Tj +ET + endstream endobj 330 0 obj <> endobj 315 0 obj <> endobj 25 0 obj <> endobj 331 0 obj [333 0 R] endobj 332 0 obj <>stream +H\j0E +-E$[ >hpIjhd8}"8ܹ8]7{׍"}}sQ:z7ߐ8ҹsҢ16zH`>ܯ#]'˥H?x]̪?S|b>> endobj 334 0 obj <> endobj 335 0 obj <> endobj 336 0 obj <>stream +H4 :@ psvHj Y  {*Z)њ25|*P endstream endobj 337 0 obj <>stream +HlViPO @Jbн:BJFs;`c5\ckZnZڸ uLmO#m:m:64L#v:θA]vy}Vf@ X2"@\Gtq5|ʷR6 M<rg5#BӔ^./ZpeHգ @P)=MX @p|7h_]Q#3g߹uĜwZzz}fyRaDň.Q2WXY1|_h?>?8:>xLetIH qx/vxV)" ], /AYn]}sCװf}Wx89p֥n.G3nw&mvKon'{::w:8`<HR9ujaV*i呉y .3Y𯽊FVtzfgyq}+WD*嬦*.x6ҵpޖj*@|ݛܝ} +{T+R*Un }ήp:0f-0>S1to򂫙Wwo9] ^Bvԕ$lݧ/ć‚a+4"iŢP{C2>D"> +#H$0VzۚCPepKR0YS}+StZ#f&)f!z%u9sE2k*HeACH f;RY gTrX~~VxçCX(VxupEBڅ:ι9Aڭj]fX +k4:oCkEEXlUKPB>}Bk.ʓGApT,ոXq"Qf /zln2j}NfAK2m&R=V۽{@ "H +z(V;;rD =`X n+,Bжp$P4WR,q߫Eh#"oL0؁9hlj7':.Mjķ[uiтQ0Kp/l%۠@Z]֣*I5-T͜IYXxB&u*;'[ \ 3X'.h+gc14 $m#aOaQSz6Pk +`Їx&)>47G$jSbRO...q:;+'cuRA_IU'sKS#NC'tugo`$Vdalt{ QRG%x|UvE}qvvg/ރg_|*6d~'R#q?Z\RT6( %wXw)dXRҞ2ƫZ"[}E}~|]۳`3j<{^Ail]c؎)"ǞMzT~RtrH~XC~ ivg^@г_1]{j]i4F\0kΜ|ip3lCeUbM'Dڰ?);[eB0G v) +G&I[/x{#tyL_ȐFN\)jtpl9mfIͿ +Eb0-[(v&﯄R.fHy@uglqV,e@Мl&*Kv>e ڤqJ}OԹsSe>9?{oLTGr'ݘO7['f~n/&|fw &aaZ5=tPZ.n2OH\:},#闂9;ByuNTqnLsB\aJ}hv +)Jn<e\W6Jv3،Y/%9AF2r|o|Is<&dQ2˾+/^"zI ˮEyuL Fګ]arpyɗW%Z~[6ĚR؟cp_avxۦR<;@k[ʼnc=H-?bDޅ<[~o;vߎZ*&UӝUmnnڱ}<s+ִQ ~Z]=*.-A/l>F_ʀl^uB͞>2; DN͠=jZYSN.;~-{oMge%6'd ydΩՎ9uң'^oo >fc3‘mxH: 8 endstream endobj 314 0 obj <> endobj 312 0 obj <> endobj 313 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 469.0025 520.1552 Tm +[(F)60 (astp)]TJ +ET + endstream endobj 338 0 obj <> endobj 311 0 obj <> endobj 309 0 obj <> endobj 310 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 913.5838 732.7853 Tm +[(\(Align C-r)35 (egion\))]TJ +ET + endstream endobj 339 0 obj <> endobj 307 0 obj <> endobj 308 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2034.4385 186.8799 Tm +(Single cell QC)Tj +ET + endstream endobj 340 0 obj <> endobj 303 0 obj <> endobj 306 0 obj <>stream +HgcD/K B - Zfj0$9ih$)ugl|I9e[KkSf,nygkk^yO?&.CSpi;po\|[e +|Exv?ɻGwњ6a16:_rDN۶|=w<~Zjm᫊TƠk-mk+^m@[meжmm󯟾ˏ\upQEZ2m/llloyC7\н׬U&3PmP<6.ml,m.mbVYR\[WrǘUV7 +ںc.LuS2#zK1-VSaPQ?jJc1ڂBDb"Kjiyo5[>')MƐ¬@[K&`FMƐ2'-EzZ+MƐ½Dv6~C +)>  +} +k ? (ݫIw6< h%Y(a".vB(yjB&yJB$JBT 8Hө"yqi:M +hs>w#htѡeۭ}SASaCjo"">1R &RsrC̘ZT]'6ΏzUbX4_<,hy1[=Ђi \Vnm>/Filter/FlateDecode/Height 173/Intent/RelativeColorimetric/Length 4261/Name/X/Subtype/Image/Type/XObject/Width 311>>stream +HDd]cd$c$##k%IX#+YI$+YVF^++k$Zd%ce%YXYIFYc1;=<9|ys3{Nt?jqԖU%?O-\ &}f 2w~~4G4zr%{kMe2EʲFS6Z#hb%SlN\9+ )7(G)u4q-=eˑ@eԙO ?|WdajaK`5ejka-GIwuZU=+Gu5Q[WY&Й-j F ؜htFF-r}cػŏf5@ineÅ"㱜|ma,Zַ?BViGƾ(q{[eR$pe@K7 ˙RQ|TYS+ /V/OͼBDKt{JD^G +=)Lep\I3q.qf$HW X_HXR`{G":BԈl"dS<6Q[7(uVq%6"3`-W5HSarEחa{C9غ GM{%AR`zK=kiºLwX]P3Q&<-G+I\ \E*@ 9 Tm%f%?!ėۻb6Y7+DI{aik+%UƖzz}ۢ/7ח6&3LD|^K:2Y-Y!~roAe hP#`bɵ5͢?%21eL!l8D`=3š=4 %l<yG]SC#-D~"XMPut`)C +?Ve +B#> vۡ M +WQdi[m +-M.)6 8:0_Ȣ䗱Gp#Nd[aƤ(`®'RxfD[Znȩ"؆%e +=3ؑDAl>jDӧI`9`KWY[݄A䑧2i5U;ld:ŞȠJۖ*Q"6^T"lN'E .SR=dCOۮ*)"ZCĞC, +؈ؐZU<`O!DG KdR 3J}RMK+HFI#Y$ȶ *^l)Hӭ\-)142a`-5>Y!ASp^.u7 +k Re ȍ зonx"l^%lυ\`A55"2E-O䜹FYWbشL [bDfŅPgikB؜p +΁u+;rGWNH = Md(Lq UyIvC0lSͅ,@6*I%j?8"6+-} W} U +L nTZ^fe`l֧ a5԰I%BD&l\ 5*MWJ_M7Fp!tjt*jhW>+l'":)&*6]/xUL7f-L ؚ) +܏,w#}-v$ɲ8sMp#a=*aՐf l;9 EWSg _-w.ca +\Ea"~/Ad'") UsK/Su7WBKcv!wJV TYtiv!wJ-XBjy5U&&&&&&&&}['.Ht' m[\ ԿV-¶ T%MAw%mp fՅ9M9Mip [ڇk2'pp ݍUW-C  [ jEMIL'.v=lFPXlfIqLJPf;l5YJYSēxҰM`}طsvH/7&%^C+x2|F)'\x! +،]s[LΕMF| b6C~ke=Oq"Hgĵ'YrlfܿeNL笟s)׼b͋߰ld5o +˽&#C,GQxTOFDޞ6Oޓ}6u0ɮ;X!W5je͹KZ,6LOpL+,l3` ;K;&# sPG]b?-3ً ( 0(v!]^ ƭ(c G!ltoq AmBK=7‡ncGe;hU6E_.]X`;c{T `R(2 M1ay!+[æç[lmN2ۛk_wÉlӽͿ ˜\b!jwYMa02- +_cXk'*VE?**"j菊<QD**ʏZS**?""Zk̛{ι;>#{|{]BH[T;PnkԐM-.$,D8d{K,4vH?PɦW1@'-2bWѪf)(;H į$:̋-:8(ٲ&9(spd5Kݻ@=G+&pWfQCϿTTu#<](k]C?79l|,g0E 5TCsanLg+{`=L T5M5u.?}K[ll~DS<r +Rg#rlڴadC`-6۹0+,7S |x©@(lAD5:TgNYnlaEYQ[d4} `j9$lhlmɟzg=SN6BZ(?:&E+6pXA8koY r]LiG~ևM3DoS%`g 9}eZ]~C߃ #wq/Ƭyp([3Ã]&ٸh2K4FCq_`-HY .sS aܘg]w\{|ukNE [5J;Z_R)ANKf,El9PKeqBGu뒋o&[ߡc[^1q}K.YBlc"i1٢.oƴ$̰ +tj +:Y5z`=_U6z:bq{H. 3m6}s> $aW6kD9^&y#W'}dᅬ_I'~y6 M!倪 fOu2V[ê +(7$]\dcIo[w}CZ +|M^7d}k"E>stream +!Q!P!O!O!N!N!M!L d d c b S R R O M L K K JbaUTTLKIHbdaaa`[VVHG_^]]YXWUHFFF]\[ZZYXED~D}D]T|C{B|BzBzAx@w@w?u?t>r=t>s=m9u>q<p<p;n;n:m:l9k8j8i8g6h7g6f6f5d5d4c4b2b3a2`2`1_1]0Z._1^1]0[/Z.Y-X,W,V+U+U*T*  endstream endobj 305 0 obj <> endobj 343 0 obj <> endobj 344 0 obj [0.0 0.0 0.0] endobj 345 0 obj <>/ProcSet[/PDF/ImageB]/XObject<>>>/Subtype/Form>>stream +q +/GS0 gs +421.2616775 0 0 234.335274 309.5232239 -6.1528094 cm +/Im0 Do +Q + endstream endobj 346 0 obj <> endobj 347 0 obj <>/Filter/FlateDecode/Height 173/Intent/RelativeColorimetric/Length 4261/Name/X/Subtype/Image/Type/XObject/Width 311>>stream +HDd]cd$c$##k%IX#+YI$+YVF^++k$Zd%ce%YXYIFYc1;=<9|ys3{Nt?jqԖU%?O-\ &}f 2w~~4G4zr%{kMe2EʲFS6Z#hb%SlN\9+ )7(G)u4q-=eˑ@eԙO ?|WdajaK`5ejka-GIwuZU=+Gu5Q[WY&Й-j F ؜htFF-r}cػŏf5@ineÅ"㱜|ma,Zַ?BViGƾ(q{[eR$pe@K7 ˙RQ|TYS+ /V/OͼBDKt{JD^G +=)Lep\I3q.qf$HW X_HXR`{G":BԈl"dS<6Q[7(uVq%6"3`-W5HSarEחa{C9غ GM{%AR`zK=kiºLwX]P3Q&<-G+I\ \E*@ 9 Tm%f%?!ėۻb6Y7+DI{aik+%UƖzz}ۢ/7ח6&3LD|^K:2Y-Y!~roAe hP#`bɵ5͢?%21eL!l8D`=3š=4 %l<yG]SC#-D~"XMPut`)C +?Ve +B#> vۡ M +WQdi[m +-M.)6 8:0_Ȣ䗱Gp#Nd[aƤ(`®'RxfD[Znȩ"؆%e +=3ؑDAl>jDӧI`9`KWY[݄A䑧2i5U;ld:ŞȠJۖ*Q"6^T"lN'E .SR=dCOۮ*)"ZCĞC, +؈ؐZU<`O!DG KdR 3J}RMK+HFI#Y$ȶ *^l)Hӭ\-)142a`-5>Y!ASp^.u7 +k Re ȍ зonx"l^%lυ\`A55"2E-O䜹FYWbشL [bDfŅPgikB؜p +΁u+;rGWNH = Md(Lq UyIvC0lSͅ,@6*I%j?8"6+-} W} U +L nTZ^fe`l֧ a5԰I%BD&l\ 5*MWJ_M7Fp!tjt*jhW>+l'":)&*6]/xUL7f-L ؚ) +܏,w#}-v$ɲ8sMp#a=*aՐf l;9 EWSg _-w.ca +\Ea"~/Ad'") UsK/Su7WBKcv!wJV TYtiv!wJ-XBjy5U&&&&&&&&}['.Ht' m[\ ԿV-¶ T%MAw%mp fՅ9M9Mip [ڇk2'pp ݍUW-C  [ jEMIL'.v=lFPXlfIqLJPf;l5YJYSēxҰM`}طsvH/7&%^C+x2|F)'\x! +،]s[LΕMF| b6C~ke=Oq"Hgĵ'YrlfܿeNL笟s)׼b͋߰ld5o +˽&#C,GQxTOFDޞ6Oޓ}6u0ɮ;X!W5je͹KZ,6LOpL+,l3` ;K;&# sPG]b?-3ً ( 0(v!]^ ƭ(c G!ltoq AmBK=7‡ncGe;hU6E_.]X`;c{T `R(2 M1ay!+[æç[lmN2ۛk_wÉlӽͿ ˜\b!jwYMa02- +_cXk'*VE?**"j菊<QD**ʏZS**?""Zk̛{ι;>#{|{]BH[T;PnkԐM-.$,D8d{K,4vH?PɦW1@'-2bWѪf)(;H į$:̋-:8(ٲ&9(spd5Kݻ@=G+&pWfQCϿTTu#<](k]C?79l|,g0E 5TCsanLg+{`=L T5M5u.?}K[ll~DS<r +Rg#rlڴadC`-6۹0+,7S |x©@(lAD5:TgNYnlaEYQ[d4} `j9$lhlmɟzg=SN6BZ(?:&E+6pXA8koY r]LiG~ևM3DoS%`g 9}eZ]~C߃ #wq/Ƭyp([3Ã]&ٸh2K4FCq_`-HY .sS aܘg]w\{|ukNE [5J;Z_R)ANKf,El9PKeqBGu뒋o&[ߡc[^1q}K.YBlc"i1٢.oƴ$̰ +tj +:Y5z`=_U6z:bq{H. 3m6}s> $aW6kD9^&y#W'}dᅬ_I'~y6 M!倪 fOu2V[ê +(7$]\dcIo[w}CZ +|M^7d}k"E> endobj 302 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 40 0 0 40 2883.1919 877.0273 Tm +(5)Tj +ET + endstream endobj 348 0 obj <> endobj 24 0 obj <> endobj 349 0 obj <> endobj 350 0 obj <>stream +H|V XUsAA"z +(U"((*(*7]#1j\ +n41Q5FSmM&&V^=0m7g9gfgISRh, j#ӓ2,GN>jU +Ըl}/)T5QnBi瀳_ڄI^g|tʚi|EI)I?U˘09ӶLkI)G +ITQKe^3a u<[C^{>B`o m;d}7u#j(U_;TYݔhf6W1o=ԕzlM%\eLrI,Z Usi~Zc-X "zuUuGқz+U}Nߢb^nb4b c7;BcQb6N|<| ''t5_7Af3LixlӳO&O#Q&Pn ohEs E`a#s %p#ŗ(`5ʺ4ؑ-نQTBN!"N!p/q96~@e>5ǚau4f- m`z}=ѕ!e03 >F/F"]1x.g cgd{#}1q~70ɡ4Z`6` UY +;;p-s;NpC\ |"O6/ ?Ƿ&Vr.bmF:`2f09ʗNЅ.\Z(G4 b "gcsQUG 7a 'c+`)3W^b/r\aVw'Fj_X(+;0~ذYiGvZJ١i}UcyײlZU);l[$?l,H)^LɚG\dՉ""n4 +oӳOI0]\buqSjm>o<귲%[Z$K+kWJ:W%ɲeY>`P @rBZZK1IӁRҐ4m'!i'C36zMCUd[TX<|w3RԹ sƅwPܼ/(O/ Erf6Y<3rm~W/zX,v5O\}׮Z_;bEAs@8SYd a,r>Q*_z UiQRo%!ʚ 't[hUw߸z[7v։66ڴAިS9l[;⣇m +' +jA8!FJ2nݻ~pDS4;]غ-0O +x.,r% ؚ2 +]Rt)@RR1+bc+NnO8{sJe6t2ْnw4 +va\ N֔hp8̶FB:-bMs`[_}.I0;b ǨمK /~AO}D +.qj;8\{g8r +]6 ډ}jr9ãҘ1$}׮ .,hax%[*d'KL8/HG.Qˍhv8Ewp141_["fݑ3F(Ժױ]Pޣ1k +*a0oko,gJ--[: jIGglVî@1l0a½aQ<-i (7zcle3'v^JU6XV63Xor2]Lf0maԍݛs?%2=VSzѵt,ZU^VDjm߁x:zj7'qkO~hcwe5P:}L)ᙣZ;N)_afFSZQ[=`Ku5xf/\e[ +Cjn,ڎ#1K#xKnuh=zAm?RE!R%XԔ"_:lђ2e eI;hI"!sHa L5#|AB8%l/tJ=ϣ j,3=-)gnOӌ.vY|t%$K$Y1yYSAS?a9@9C17:X?1JIR&E?SZ3djPOjEG)d.a}S- 

u鍆LNJZ2LshrAȯtOti<"">@~\Q-صGx۳~/1kϞFϏZC%=debx$ٜ(E5anK8h1Ț9g|~7|g5:ˌL61Je@ `ZX38(č(\ (/5ޜ{i#9 +) `%J"뗝 -prv|dnk%=aZE;=)ܳnMqnhR49M C%^3}0~,I/F9]nɪH4 o93jc21.nvY:ppxǨU\%Bf[Ln$iz9zb,1@fz?oD*yȊ:k^Y#ke?)rI57Kq^m_,"om"[(6VB[ۂ- p-lKih\Bl Q+h܍AƘ +A !(x9zB%>xoo33gf? +ӴQ"GubO '(G–5 B>~H%)K9pH"r %N"/0/ 6sr +Q|s41|ƨrV6\[9~zcXrL3|[OÀtsSu!Ā,+`Y?ǼCo\D`;Ac=A!ys*`٨Jderl&fmHx~?K T ^>TRL\k;.d=S=WO!VTNü ƿ{dC PYlBB*G[Gp Y#vnE32sV7H%&ko,TrlRIBL@Q[YO!T^ݣ0ݦ?vbP!4!H*{XJrqި׹NwcRy<עTfKZdsshUR bU ͈>+]%K ⥀ ++OV`Ttc\9:\] nLD,?RÍlڕH2+eIYFryks-=خ'A /-RDgܳ[<4y s?3jD[q?e-miǽ )(ȕCH=[1m +>_p v:{_9'G]Ke1A)d$$'f`5FXͳgr!s[a+f[8/ lMmbI6í~{u4u}@uu{C1a^Յ e}̒{H4=2h8\{A6q"/%_$XFH*YD$'$;;N"'|HԟU)w#4_I7qa|~ ٜxyKdF4\[گ %>i$;!QBRnPMgG9J RQuzce)j~t|VA *UAۃ :O+UF'Qlż~6'݀Ë7.f2WD +w.d v&O:ap0Z/ Y\Xhb t<s+L-{z.oKm`j.Mֆvg:X{*Z񬧞kd6%7ңV]wf dz]s$ou,Y\˯)ktmF|T-@,ݧZzmk?_c^GM:W6_$=k|#R(?=kc> endobj 299 0 obj <> endobj 297 0 obj <> endobj 298 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 40 0 0 40 2109.252 877.3154 Tm +(4)Tj +ET + endstream endobj 351 0 obj <> endobj 295 0 obj <> endobj 296 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 40 0 0 40 1764.7329 28.2334 Tm +(3)Tj +ET + endstream endobj 352 0 obj <> endobj 293 0 obj <> endobj 294 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 39.4246 0 0 39.4372 47.6694 882.2129 Tm +(1)Tj +ET + endstream endobj 353 0 obj <> endobj 291 0 obj <> endobj 292 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2244.8135 634.8359 Tm +[(Cr)35 (eate clonal germlines)]TJ +ET + endstream endobj 354 0 obj <> endobj 290 0 obj <> endobj 289 0 obj <> endobj 286 0 obj <> endobj 287 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1911.6846 350.5664 Tm +[(Cr)35 (eate)]TJ +ET + endstream endobj 288 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1898.6807 328.0664 Tm +(germlines)Tj +ET + endstream endobj 356 0 obj <> endobj 355 0 obj <> endobj 284 0 obj <> endobj 285 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1396.6621 623.2197 Tm +(Assign genes)Tj +ET + endstream endobj 357 0 obj <> endobj 282 0 obj <> endobj 283 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1489.2524 758.6719 Tm +(or)Tj +ET + endstream endobj 358 0 obj <> endobj 281 0 obj <> endobj 280 0 obj <> endobj 279 0 obj <> endobj 278 0 obj <> endobj 277 0 obj <> endobj 276 0 obj <> endobj 275 0 obj <> endobj 273 0 obj <> endobj 274 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 2698.5427 683.7921 Tm +[(QC r)35 (eports)]TJ +ET + endstream endobj 359 0 obj <> endobj 271 0 obj <> endobj 272 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1423.0049 687.001 Tm +[(Conv)35 (ert to fasta)]TJ +ET + endstream endobj 360 0 obj <> endobj 269 0 obj <> endobj 270 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 2595.5935 692.8517 Tm +[(Repertoir)34.9 (e )]TJ +0 -1.2 Td +(analysis)Tj +ET + endstream endobj 361 0 obj <> endobj 268 0 obj <> endobj 267 0 obj <> endobj 266 0 obj <> endobj 265 0 obj <> endobj 264 0 obj <> endobj 263 0 obj <> endobj 262 0 obj <> endobj 261 0 obj <> endobj 260 0 obj <> endobj 258 0 obj <> endobj 259 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1569.1494 595.5898 Tm +[(F)25 (etch databases)]TJ +ET + endstream endobj 362 0 obj <> endobj 257 0 obj <> endobj 256 0 obj <> endobj 255 0 obj <> endobj 254 0 obj <> endobj 253 0 obj <> endobj 252 0 obj <> endobj 251 0 obj <> endobj 250 0 obj <> endobj 249 0 obj <> endobj 248 0 obj <> endobj 246 0 obj <> endobj 247 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1477.4814 208.9844 Tm +(Add metadata)Tj +ET + endstream endobj 363 0 obj <> endobj 245 0 obj <> endobj 244 0 obj <> endobj 243 0 obj <> endobj 242 0 obj <> endobj 241 0 obj <> endobj 240 0 obj <> endobj 239 0 obj <> endobj 238 0 obj <> endobj 237 0 obj <> endobj 236 0 obj <> endobj 234 0 obj <> endobj 235 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1581.2959 330.5322 Tm +(mod3 junction)Tj +ET + endstream endobj 364 0 obj <> endobj 233 0 obj <> endobj 232 0 obj <> endobj 231 0 obj <> endobj 229 0 obj <> endobj 230 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 1211.9506 532.4607 Tm +(Filter dupl. count)Tj +ET + endstream endobj 365 0 obj <> endobj 227 0 obj <> endobj 228 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 1141.9166 532.4603 Tm +(Annot. metadata)Tj +ET + endstream endobj 366 0 obj <> endobj 225 0 obj <> endobj 226 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 1116.8398 738.1879 Tm +(Collapse )Tj +0 -1.2 Td +(consensus count)Tj +ET + endstream endobj 367 0 obj <> endobj 223 0 obj <> endobj 224 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 953.7936 731.8389 Tm +(Assemble pairs)Tj +ET + endstream endobj 368 0 obj <> endobj 221 0 obj <> endobj 222 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 870.0613 731.3513 Tm +(Pair sequences)Tj +ET + endstream endobj 369 0 obj <> endobj 219 0 obj <> endobj 220 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 828.4294 731.3517 Tm +(Build consensus)Tj +ET + endstream endobj 370 0 obj <> endobj 217 0 obj <> endobj 218 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 759.48 774.2938 Tm +(Annotate)Tj +0 -1.2 Td +(cluster)Tj +ET + endstream endobj 371 0 obj <> endobj 215 0 obj <> endobj 216 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1579.8442 394.5234 Tm +[(Pr)35 (oductiv)35 (e)]TJ +ET + endstream endobj 372 0 obj <> endobj 213 0 obj <> endobj 214 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 695.6918 784.6553 Tm +(Similarity)Tj +0 -1.2 Td +(clustering)Tj +ET + endstream endobj 373 0 obj <> endobj 212 0 obj <> endobj 211 0 obj <> endobj 210 0 obj <> endobj 208 0 obj <> endobj 209 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 322.5063 543.1027 Tm +[(Filter b)34.9 (y quality)]TJ +ET + endstream endobj 374 0 obj <> endobj 206 0 obj <> endobj 207 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 991.8264 599.0601 Tm +[(F)60 (astQC )]TJ +ET + endstream endobj 375 0 obj <> endobj 204 0 obj <> endobj 205 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 1198.1951 552.9022 Tm +(Collapse dupl.)Tj +ET + endstream endobj 376 0 obj <> endobj 202 0 obj <> endobj 203 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 1118.6957 545.0618 Tm +(Annot. primers)Tj +ET + endstream endobj 377 0 obj <> endobj 200 0 obj <> endobj 201 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 597.1017 733.1662 Tm +(Pair sequences)Tj +ET + endstream endobj 378 0 obj <> endobj 198 0 obj <> endobj 199 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 388.523 552.9022 Tm +(Mask primers)Tj +ET + endstream endobj 379 0 obj <> endobj 196 0 obj <> endobj 197 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1557.2593 511.3867 Tm +(Filter quality)Tj +ET + endstream endobj 380 0 obj <> endobj 193 0 obj <> endobj 194 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 253.1434 542.3017 Tm +(Assemble)Tj +ET + endstream endobj 195 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 282.6407 539.8449 Tm +(pairs)Tj +ET + endstream endobj 382 0 obj <> endobj 381 0 obj <> endobj 191 0 obj <> endobj 192 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 192.4777 684.0383 Tm +[(F)60 (astp)]TJ +ET + endstream endobj 383 0 obj <> endobj 189 0 obj <> endobj 190 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 17.9998 -0.0893 0.0893 17.9998 478.5751 748.5795 Tm +(vprimers)Tj +ET + endstream endobj 384 0 obj <> endobj 187 0 obj <> endobj 188 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 17.9998 -0.0893 0.0893 17.9998 392.4072 749.7679 Tm +(cprimers)Tj +ET + endstream endobj 385 0 obj <> endobj 185 0 obj <> endobj 186 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/C2_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2334.8994 614.6328 Tm +<0025011401D6015B0114023F010701500167015B01140195>Tj +ET + endstream endobj 386 0 obj <> endobj 23 0 obj <> endobj 387 0 obj [389 0 R] endobj 388 0 obj <>stream +H\j0EY& q8 xu4N,de`& +,8̽;#ڴV+NC<ݭ@4rJ-Fnn&RU@?|qvv͓zf%Zoj-n0k8F/ܼFۮܲ?bY +#&-7$OMPSr֫3vj}(+(kE%e9RF:.KҝYӭ9BNNx,AܭǝJYdG~" endstream endobj 389 0 obj <> endobj 390 0 obj <> endobj 391 0 obj <> endobj 392 0 obj <>stream +Hj````a 8F0 S̈́ 8& endstream endobj 393 0 obj <>stream +HkP뢀.岰r_X E6WQA,1LM;ӴNI:if:mMk2mltҘ8L46} +N;3}<=9{λ?a +48'mۻuוO* _X>nWh+!䮰= +De LJbk9}{C7eO!0C~=m~E ö9|zapy> ߰Tr\3hgMυ 6;-fQ,um?8~X 0vH?}35cGADT\E +ȗ咽,v-h13b46ҥl{-6;60,11=[cbjh..2UlJJ8>"ݝף§--sĽɊguQ)ky93bwu4UG6gv{7l2Gכ8J63,O"YU (SKf:ёeL;rD<[qEY)R\=\zՅ`.K*k&f<%mX 9hӞ#bJ%ay]5yJҪ3k 9&_쬄n.=)):3G[SꩨI}YծnwEgaI<@gJMbw+7-~|Boq:iR*RӜVf+,J/MK*O)m77rmɩ樹 ӊRۂ:sRzFry9.nRʓU#LlV75Rlvnr^|Rʳߑ3AyU#P/q5xf'#O :#0Q(/]pO8 W>UWa3mDznK,|gΏPyK&3.qeJ3~2BEg! H8<g,(+CF]u"`~ x""a9/re|CRT͚_wT=?Ƕi$݈l3tV^R&7QeYx`[ucg&J(ǼCx\bЃcS?Gia]󡾉$Ǜ@űmgE4ϟ^#"Y[溺sUݦ ëTUSK߉$эDo&p9 qnroFIl>m@8ʽ}4^KQ)~m\&C-vI9}>=DYj"Qȡ2[?m9y!\r\"?!WR%c %bx W$v8˻~ޑW"RXk_e jC:彤JهfY8ME 1c(.oWupڙ8Wy 8D="> ;ߏ8.o`.mfڽS=q9r5pc{Oc m=sc3'?D6btȻG/WPhX3AT@2S)(Ewx ?=6r5;]!B9_~QmI_RĩoQۻvq~ߡۚxxoϿP&}qܯϠ!ӏ%ysn;TQ2+<>OʗXa91Cy˯-/rK,w)l;>]Aޖҍ* ߣgKĈMޯn~J#0(Q!ɷۿ;4633Va؋!NszX!XXG >즶Sr=Z*P6aֳhF_סj%q}~}PNzO2.2({he0RK]kٻ_{ڌi7c=y79a>!<-6>K[nY߻=Zl2#Z|̌_jV~wײ{uyQk$u endstream endobj 183 0 obj <> endobj 184 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2285.0166 531.2598 Tm +[(Find thr)35 (eshold)]TJ +ET + endstream endobj 394 0 obj <> endobj 181 0 obj <> endobj 182 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2293.2378 687.752 Tm +[(Build lineage tr)35 (ees)]TJ +ET + endstream endobj 395 0 obj <> endobj 178 0 obj <> endobj 179 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2281.5684 302.8809 Tm +(Collapse)Tj +ET + endstream endobj 180 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2274.1973 280.3809 Tm +(duplicates)Tj +ET + endstream endobj 397 0 obj <> endobj 396 0 obj <> endobj 176 0 obj <> endobj 177 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 39.4245 0 0 38.4461 1718.4043 885.9873 Tm +(2)Tj +ET + endstream endobj 398 0 obj <> endobj 172 0 obj <> endobj 173 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2156.6572 324.4355 Tm +(Detect)Tj +ET + endstream endobj 174 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2162.6338 301.9355 Tm +[(cr)35 (oss)]TJ +ET + endstream endobj 175 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2124.6631 279.4355 Tm +(contamination)Tj +ET + endstream endobj 401 0 obj <> endobj 400 0 obj <> endobj 399 0 obj <> endobj 170 0 obj <> endobj 171 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 19.9996 -0.0992 0.0992 19.9996 451.5757 309.6696 Tm +(Samplesheet)Tj +ET + endstream endobj 402 0 obj <> endobj 169 0 obj <> endobj 167 0 obj <> endobj 168 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 1118.3033 330.0448 Tm +(Filter locus)Tj +ET + endstream endobj 403 0 obj <> endobj 165 0 obj <> endobj 166 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 985.0504 341.8153 Tm +(TRUST4)Tj +ET + endstream endobj 404 0 obj <> endobj 163 0 obj <> endobj 164 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 835.1841 335.327 Tm +[(r)35 (ef)35 (er)35 (ence)]TJ +ET + endstream endobj 405 0 obj <> endobj 161 0 obj <> endobj 162 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 814.9996 340.3456 Tm +(TRUST4)Tj +ET + endstream endobj 406 0 obj <> endobj 159 0 obj <> endobj 160 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 14.212 14.0718 -14.0718 14.212 637.6763 356.9491 Tm +[(F)60 (astp)]TJ +ET + endstream endobj 407 0 obj <> endobj 158 0 obj <> endobj 157 0 obj <> endobj 156 0 obj <> endobj 153 0 obj <> endobj 154 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2007.5967 350.8027 Tm +[(Remo)35 (v)35 (e)]TJ +ET + endstream endobj 155 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 2006.04 328.3027 Tm +(chimeric)Tj +ET + endstream endobj 409 0 obj <> endobj 408 0 obj <> endobj 151 0 obj <> endobj 152 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1558.1753 564.4551 Tm +[(Mak)45 (eDb)]TJ +ET + endstream endobj 410 0 obj <> endobj 149 0 obj <> endobj 150 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/TT0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 20 0 0 20 1367.9077 814.3496 Tm +(Samplesheet)Tj +ET + endstream endobj 411 0 obj <> endobj 26 0 obj <> endobj 412 0 obj [/View/Design] endobj 413 0 obj <>>> endobj 31 0 obj <> endobj 32 0 obj <> endobj 33 0 obj <> endobj 34 0 obj <> endobj 27 0 obj [26 0 R] endobj 414 0 obj <> endobj xref +0 415 +0000000004 65535 f +0000000016 00000 n +0000000147 00000 n +0000027505 00000 n +0000000000 00000 f +0000027556 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000065477 00000 n +0000065550 00000 n +0000065768 00000 n +0000067456 00000 n +0000133044 00000 n +0000198632 00000 n +0000264220 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000361299 00000 n +0000415499 00000 n +0000388991 00000 n +0000369351 00000 n +0000427429 00000 n +0000428099 00000 n +0000029431 00000 n +0000064265 00000 n +0000360697 00000 n +0000427617 00000 n +0000427740 00000 n +0000427863 00000 n +0000427986 00000 n +0000318091 00000 n +0000318380 00000 n +0000318670 00000 n +0000319058 00000 n +0000319405 00000 n +0000320135 00000 n +0000320516 00000 n +0000320806 00000 n +0000321096 00000 n +0000321386 00000 n +0000321676 00000 n +0000321966 00000 n +0000322436 00000 n +0000322726 00000 n +0000323209 00000 n +0000323499 00000 n +0000323885 00000 n +0000324175 00000 n +0000324465 00000 n +0000324754 00000 n +0000325043 00000 n +0000325333 00000 n +0000325623 00000 n +0000326006 00000 n +0000326296 00000 n +0000326586 00000 n +0000326875 00000 n +0000327165 00000 n +0000327455 00000 n +0000327745 00000 n +0000328035 00000 n +0000328325 00000 n +0000328614 00000 n +0000328968 00000 n +0000329257 00000 n +0000329547 00000 n +0000329837 00000 n +0000330126 00000 n +0000330416 00000 n +0000330706 00000 n +0000330996 00000 n +0000331286 00000 n +0000331576 00000 n +0000331862 00000 n +0000332152 00000 n +0000332518 00000 n +0000332807 00000 n +0000333259 00000 n +0000333981 00000 n +0000334326 00000 n +0000335055 00000 n +0000335406 00000 n +0000336139 00000 n +0000336488 00000 n +0000337218 00000 n +0000337592 00000 n +0000338322 00000 n +0000338612 00000 n +0000338982 00000 n +0000339370 00000 n +0000340101 00000 n +0000340449 00000 n +0000341179 00000 n +0000341553 00000 n +0000341842 00000 n +0000342196 00000 n +0000342558 00000 n +0000342849 00000 n +0000343138 00000 n +0000343428 00000 n +0000343792 00000 n +0000344526 00000 n +0000344874 00000 n +0000345606 00000 n +0000345980 00000 n +0000346338 00000 n +0000346697 00000 n +0000347065 00000 n +0000347355 00000 n +0000347646 00000 n +0000347937 00000 n +0000348455 00000 n +0000349189 00000 n +0000349565 00000 n +0000350299 00000 n +0000350649 00000 n +0000351383 00000 n +0000351732 00000 n +0000352023 00000 n +0000352314 00000 n +0000352703 00000 n +0000353434 00000 n +0000353801 00000 n +0000354092 00000 n +0000354383 00000 n +0000354675 00000 n +0000354967 00000 n +0000355700 00000 n +0000356050 00000 n +0000356342 00000 n +0000356682 00000 n +0000356973 00000 n +0000357264 00000 n +0000357623 00000 n +0000357914 00000 n +0000358304 00000 n +0000358737 00000 n +0000359027 00000 n +0000359318 00000 n +0000359609 00000 n +0000359900 00000 n +0000064330 00000 n +0000317514 00000 n +0000317564 00000 n +0000426970 00000 n +0000427033 00000 n +0000426508 00000 n +0000426571 00000 n +0000425650 00000 n +0000425713 00000 n +0000426053 00000 n +0000425587 00000 n +0000425523 00000 n +0000425460 00000 n +0000424979 00000 n +0000425042 00000 n +0000424504 00000 n +0000424567 00000 n +0000424010 00000 n +0000424073 00000 n +0000423535 00000 n +0000423598 00000 n +0000423053 00000 n +0000423116 00000 n +0000422990 00000 n +0000422510 00000 n +0000422573 00000 n +0000421258 00000 n +0000421321 00000 n +0000421650 00000 n +0000421985 00000 n +0000420799 00000 n +0000420862 00000 n +0000419948 00000 n +0000420011 00000 n +0000420342 00000 n +0000419474 00000 n +0000419537 00000 n +0000419004 00000 n +0000419067 00000 n +0000415001 00000 n +0000415064 00000 n +0000414525 00000 n +0000414588 00000 n +0000414048 00000 n +0000414111 00000 n +0000413567 00000 n +0000413630 00000 n +0000412680 00000 n +0000412743 00000 n +0000413093 00000 n +0000412217 00000 n +0000412280 00000 n +0000411737 00000 n +0000411800 00000 n +0000411255 00000 n +0000411318 00000 n +0000410771 00000 n +0000410834 00000 n +0000410287 00000 n +0000410350 00000 n +0000409804 00000 n +0000409867 00000 n +0000409309 00000 n +0000409372 00000 n +0000409245 00000 n +0000409181 00000 n +0000409117 00000 n +0000408614 00000 n +0000408677 00000 n +0000408143 00000 n +0000408206 00000 n +0000407646 00000 n +0000407709 00000 n +0000407163 00000 n +0000407226 00000 n +0000406680 00000 n +0000406743 00000 n +0000406197 00000 n +0000406260 00000 n +0000405688 00000 n +0000405751 00000 n +0000405203 00000 n +0000405266 00000 n +0000404715 00000 n +0000404778 00000 n +0000404651 00000 n +0000404587 00000 n +0000404524 00000 n +0000404063 00000 n +0000404126 00000 n +0000404000 00000 n +0000403936 00000 n +0000403873 00000 n +0000403809 00000 n +0000403746 00000 n +0000403682 00000 n +0000403619 00000 n +0000403555 00000 n +0000403492 00000 n +0000403428 00000 n +0000402967 00000 n +0000403030 00000 n +0000402904 00000 n +0000402841 00000 n +0000402777 00000 n +0000402714 00000 n +0000402650 00000 n +0000402587 00000 n +0000402523 00000 n +0000402460 00000 n +0000402397 00000 n +0000402333 00000 n +0000401864 00000 n +0000401927 00000 n +0000401800 00000 n +0000401737 00000 n +0000401673 00000 n +0000401610 00000 n +0000401546 00000 n +0000401483 00000 n +0000401420 00000 n +0000401357 00000 n +0000401294 00000 n +0000400782 00000 n +0000400845 00000 n +0000400311 00000 n +0000400374 00000 n +0000399824 00000 n +0000399887 00000 n +0000399761 00000 n +0000399697 00000 n +0000399634 00000 n +0000399570 00000 n +0000399507 00000 n +0000399443 00000 n +0000399380 00000 n +0000398930 00000 n +0000398993 00000 n +0000398469 00000 n +0000398532 00000 n +0000397612 00000 n +0000397675 00000 n +0000398011 00000 n +0000397548 00000 n +0000397485 00000 n +0000397006 00000 n +0000397069 00000 n +0000396548 00000 n +0000396611 00000 n +0000396100 00000 n +0000396163 00000 n +0000395652 00000 n +0000395715 00000 n +0000395588 00000 n +0000395525 00000 n +0000388542 00000 n +0000388605 00000 n +0000376630 00000 n +0000378455 00000 n +0000383434 00000 n +0000376693 00000 n +0000376169 00000 n +0000376232 00000 n +0000375675 00000 n +0000375738 00000 n +0000375612 00000 n +0000375131 00000 n +0000375194 00000 n +0000375068 00000 n +0000369288 00000 n +0000368810 00000 n +0000368873 00000 n +0000368332 00000 n +0000368395 00000 n +0000367854 00000 n +0000367917 00000 n +0000360810 00000 n +0000360873 00000 n +0000360633 00000 n +0000361236 00000 n +0000361730 00000 n +0000361991 00000 n +0000368269 00000 n +0000368747 00000 n +0000369225 00000 n +0000369488 00000 n +0000369515 00000 n +0000370011 00000 n +0000370459 00000 n +0000370529 00000 n +0000370802 00000 n +0000370942 00000 n +0000375549 00000 n +0000376106 00000 n +0000376567 00000 n +0000378505 00000 n +0000383017 00000 n +0000383551 00000 n +0000383617 00000 n +0000383648 00000 n +0000383953 00000 n +0000384030 00000 n +0000388928 00000 n +0000389415 00000 n +0000389674 00000 n +0000396037 00000 n +0000396485 00000 n +0000396943 00000 n +0000397422 00000 n +0000398406 00000 n +0000398343 00000 n +0000398867 00000 n +0000399317 00000 n +0000400248 00000 n +0000400719 00000 n +0000401231 00000 n +0000402270 00000 n +0000403365 00000 n +0000404461 00000 n +0000405140 00000 n +0000405625 00000 n +0000406134 00000 n +0000406617 00000 n +0000407100 00000 n +0000407583 00000 n +0000408080 00000 n +0000408551 00000 n +0000409054 00000 n +0000409741 00000 n +0000410224 00000 n +0000410708 00000 n +0000411192 00000 n +0000411674 00000 n +0000412154 00000 n +0000412617 00000 n +0000413504 00000 n +0000413441 00000 n +0000413985 00000 n +0000414462 00000 n +0000414938 00000 n +0000415436 00000 n +0000415639 00000 n +0000415666 00000 n +0000416027 00000 n +0000416262 00000 n +0000416332 00000 n +0000416607 00000 n +0000416717 00000 n +0000419411 00000 n +0000419885 00000 n +0000420736 00000 n +0000420673 00000 n +0000421195 00000 n +0000422447 00000 n +0000422384 00000 n +0000422321 00000 n +0000422927 00000 n +0000423472 00000 n +0000423947 00000 n +0000424441 00000 n +0000424916 00000 n +0000425397 00000 n +0000426445 00000 n +0000426382 00000 n +0000426907 00000 n +0000427366 00000 n +0000427499 00000 n +0000427531 00000 n +0000428124 00000 n +trailer <<361852DB396C4A3FBE064E56382FC84B>]>> startxref 428331 %%EOF \ No newline at end of file diff --git a/docs/images/metro-map-airrflow.pdf b/docs/images/metro-map-airrflow.pdf index b55e1477..aef6517c 100644 Binary files a/docs/images/metro-map-airrflow.pdf and b/docs/images/metro-map-airrflow.pdf differ diff --git a/docs/images/metro-map-airrflow.png b/docs/images/metro-map-airrflow.png index ac4ee67e..4e48cfb3 100644 Binary files a/docs/images/metro-map-airrflow.png and b/docs/images/metro-map-airrflow.png differ diff --git a/docs/images/metro-map-airrflow.svg b/docs/images/metro-map-airrflow.svg new file mode 100644 index 00000000..c48b04bf --- /dev/null +++ b/docs/images/metro-map-airrflow.svg @@ -0,0 +1,6280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ImmcantationSingle cellunselected RNA-seqCellranger FastpTRUST4Inidividual OverlapFastpvdjPostanalysis Postanalysis + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Repertoire and Clonotype Analysis and ReportingPDF + diff --git a/docs/images/mqc_fastqc_adapter.png b/docs/images/mqc_fastqc_adapter.png deleted file mode 100755 index 361d0e47..00000000 Binary files a/docs/images/mqc_fastqc_adapter.png and /dev/null differ diff --git a/docs/images/mqc_fastqc_counts.png b/docs/images/mqc_fastqc_counts.png deleted file mode 100755 index cb39ebb8..00000000 Binary files a/docs/images/mqc_fastqc_counts.png and /dev/null differ diff --git a/docs/images/mqc_fastqc_quality.png b/docs/images/mqc_fastqc_quality.png deleted file mode 100755 index a4b89bf5..00000000 Binary files a/docs/images/mqc_fastqc_quality.png and /dev/null differ diff --git a/docs/usage.md b/docs/usage.md index c3844547..906f7910 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -41,13 +41,13 @@ nextflow run nf-core/airrflow \ A typical command to run the pipeline from **single cell raw fastq files** is: ```bash -nextflow run nf-core/airrflow -r dev \ +nextflow run nf-core/airrflow \ -profile \ --mode fastq \ --input input_samplesheet.tsv \ --library_generation_method sc_10x_genomics \ --reference_10x reference/refdata-cellranger-vdj-GRCh38-alts-ensembl-5.0.0.tar.gz \ ---outdir ./results +--outdir results ``` A typical command for running the pipeline departing from **single-cell AIRR rearrangement tables or assembled bulk sequencing fasta** data is: @@ -87,9 +87,9 @@ The above pipeline run specified with a params file in yaml format: nextflow run nf-core/airrflow -profile docker -params-file params.yaml ``` -with `params.yaml` containing: +with: -```yaml +```yaml title="params.yaml" input: './samplesheet.csv' outdir: './results/' <...> @@ -121,7 +121,7 @@ If you wish to share such profile (such as upload as supplementary material for ## Input samplesheet -### Fastq input samplesheet (bulk sequencing) +### Fastq input samplesheet (bulk AIRR sequencing) The required input file for processing raw BCR or TCR bulk targeted sequencing data is a sample sheet in TSV format (tab separated). The columns `sample_id`, `filename_R1`, `filename_R2`, `subject_id`, `species`, `tissue`, `pcr_target_locus`, `single_cell`, `sex`, `age` and `biomaterial_provider` are required. An example samplesheet is: @@ -143,7 +143,7 @@ The required input file for processing raw BCR or TCR bulk targeted sequencing d - `age`: Subject biological age. - `single_cell`: TRUE or FALSE. -Other optional columns can be added. These columns will be available when building the contrasts for the repertoire comparison report. It is recommended that these columns also follow the AIRR nomenclature. Examples are: +Other optional columns can be added. These columns will be available as metadata in the final repertoire table. It is recommended that these columns also follow the AIRR nomenclature. Examples are: - `intervention`: Description of intervention. - `disease_diagnosis`: Diagnosis of subject. @@ -151,19 +151,19 @@ Other optional columns can be added. These columns will be available when buildi - `collection_time_point_reference`: Event in the study schedule to which `Sample collection time` relates to (e.g. primary vaccination, intervention start). - `cell_subset`: Commonly-used designation of isolated cell population. -The metadata specified in the input file will then be automatically annotated in a column with the same header in the tables generated by the pipeline. +It is possible to provide several fastq files per sample (e.g. sequenced over different chips or lanes). In this case the different fastq files per sample will be merged together prior to processing. Provide one fastq pair R1/R2 per row, and the same `sample_id` field for these rows. ### Fastq input samplesheet (single cell sequencing) -The required input file for processing raw BCR or TCR single cell targeted sequencing data is a sample sheet in TSV format (tab separated). The columns `sample_id`, `filename_R1`, `filename_R2`, `subject_id`, `species`, `tissue`, `pcr_target_locus`, `single_cell`, `sex`, `age` and `biomaterial_provider` are required. You can refer to the bulk fastq input section for documentation on the individual columns. +The required input file for processing raw BCR or TCR single cell targeted sequencing data is a sample sheet in TSV format (tab separated). The columns `sample_id`, `filename_R1`, `filename_R2`, `subject_id`, `species`, `tissue`, `pcr_target_locus`, `single_cell`, `sex`, `age` and `biomaterial_provider` are required. Any other columns you add will be available in the final repertoire file as extra metadata fields. You can refer to the bulk fastq input section for documentation on the individual columns. An example samplesheet is: -| sample_id | filename_R1 | filename_R2 | subject_id | species | pcr_target_locus | tissue | sex | age | biomaterial_provider | single_cell | intervention | collection_time_point_relative | cell_subset | -| --------- | ------------------------------- | ------------------------------- | ---------- | ------- | ---------------- | ------ | ------ | --- | -------------------- | ----------- | -------------- | ------------------------------ | ------------ | -| sample01 | sample1_S1_L001_R1_001.fastq.gz | sample1_S1_L001_R2_001.fastq.gz | Subject02 | human | IG | blood | NA | 53 | sequencing_facility | FALSE | Drug_treatment | Baseline | plasmablasts | -| sample02 | sample2_S1_L001_R1_001.fastq.gz | sample2_S1_L001_R2_001.fastq.gz | Subject02 | human | TR | blood | female | 78 | sequencing_facility | FALSE | Drug_treatment | Baseline | plasmablasts | +| sample_id | filename_R1 | filename_R2 | subject_id | species | pcr_target_locus | tissue | sex | age | biomaterial_provider | single_cell | +| --------- | -------------------------------- | -------------------------------- | ---------- | ------- | ---------------- | ------ | ------ | --- | -------------------- | ----------- | +| sample01 | sample01_S1_L001_R1_001.fastq.gz | sample01_S1_L001_R2_001.fastq.gz | Subject02 | human | IG | blood | NA | 53 | sequencing_facility | TRUE | +| sample02 | sample02_S1_L001_R1_001.fastq.gz | sample02_S1_L001_R2_001.fastq.gz | Subject02 | human | TR | blood | female | 78 | sequencing_facility | TRUE | -> FASTQ files must confirm the 10xGenomics cellranger naming conventions
>**`[SAMPLE-NAME]`_S1_L00`[LANE-NUMBER]` _`[READ-TYPE]`\_001.fastq.gz** +> FASTQ files must conform with the 10xGenomics cellranger naming conventions with the same sample name as provided in the sample*id column
>\*\*`[SAMPLE-NAME]`* S`[CHIP-NUMBER]`_ L00`[LANE-NUMBER]`_`[R1/R2]`\_001.fastq.gz\*\* > > Read type is one of > @@ -172,6 +172,13 @@ An example samplesheet is: > - `R1`: Read 1 > - `R2`: Read 2 +It is possible to provide several fastq files per sample (e.g. sequenced over different chips or lanes). In this case the different fastq files per sample will be provided to the same cellranger process. These rows should then have an identical `sample_id` field. + +### Fastq input samplesheet (untargeted bulk or sc RNA sequencing) + +When running the untargeted protocol, BCR or TCR sequences will be extracted from the untargeted bulk or single-cell RNA sequencing with tools such as [TRUST4](https://github.com/liulab-dfci/TRUST4). +The required input file is the same as for the [Fastq bulk AIRR samplesheet](#fastq-input-samplesheet-bulk-airr-sequencing) or [Fastq single-cell AIRR samplesheet](#fastq-input-samplesheet-single-cell-sequencing) depending on the input data type (bulk RNAseq or single-cell RNAseq). + ### Assembled input samplesheet (bulk or single-cell sequencing) The required input file for processing raw BCR or TCR bulk targeted sequencing data is a sample sheet in TSV format (tab separated). The columns `sample_id`, `filename`, `subject_id`, `species`, `tissue`, `single_cell`, `sex`, `age` and `biomaterial_provider` are required. All fields are explained in the previous section, with the only difference being that there is only one `filename` column for the assembled input samplesheet. The provided file will be different from assembled single-cell or bulk data: @@ -243,7 +250,7 @@ And similarly for TCR libraries: ```bash nextflow run nf-core/airrflow -r \ --profile nebnext_umi_bcr,docker \ +-profile nebnext_umi_tcr,docker \ --input input_samplesheet.tsv \ --cprimers https://bitbucket.org/kleinstein/immcantation/raw/354f49228a43b4c2858d67fb09886126b314e317/protocols/AbSeq/AbSeq_R1_Mouse_TR_Primers.fasta \ --internal_cregion_sequences https://bitbucket.org/kleinstein/immcantation/raw/354f49228a43b4c2858d67fb09886126b314e317/protocols/AbSeq/AbSeq_Mouse_TR_InternalCRegion.fasta \ @@ -468,6 +475,43 @@ nextflow run nf-core/airrflow -r dev \ - The 10xGenomics reference can be downloaded from the [download page](https://www.10xgenomics.com/support/software/cell-ranger/downloads) - To generate a V(D)J segment fasta file as reference from IMGT one can follow the [cellranger docs](https://support.10xgenomics.com/single-cell-vdj/software/pipelines/latest/advanced/references#imgt). +## Supported unselected RNA-seq based methods + +nf-core/airrflow supports unselected bulk or single-cell RNA-seq fastq files as input. [TRUST4](https://github.com/liulab-dfci/TRUST4) is used to extract TCR/BCR sequences from these files. The resulting AIRR tables are then fed into airrflow's Immcantation based workflow.
+To use unselected RNA-seq based input, specify `--library_generation_method trust4`. + +### Bulk RNA-seq + +A typical command to run the pipeline from **bulk RNA-seq fastq files** is: + +```bash +nextflow run nf-core/airrfow \ +-profile \ +--mode fastq \ +--input input_samplesheet.tsv \ +--library_generation_method trust4 \ +--outdir results +``` + +### Single-cell RNA-seq + +A typical command to run the pipeline from **single-cell RNA-seq fastq files** is: + +```bash +nextflow run nf-core/airrfow \ +-profile \ +--mode fastq \ +--input input_samplesheet.tsv \ +--library_generation_method trust4 \ +--umi_read R1 \ +--cell_barcode_read R1 \ +--read_format bc:0:15,um:16:27 \ +--outdir results +``` + +- If UMI's are present, the read containing them must be specified using the `--umi_read` parameter. +- The `--read_format` parameter can be used to specify the Cell Barcode and UMI position within the reads (see TRUST4 [docs](https://github.com/liulab-dfci/TRUST4?tab=readme-ov-file#10x-genomics-data-and-barcode-based-single-cell-data)). For scRNAseq with 10X Genomics the R1 read usually contains both the cell barcode (barcode) and UMI. So we specify "R1" for both `--umi_read` and `--cell_barcode_read`, and the positions of both the cell barcode and UMI with the `--read_format` parameter as in the example ("bc:0:15,um:16:27"). Then specify the R1 read in the filename_R1 column of the samplesheet, and the read containing the actual sequence (usually R2) in the filename_R2 column of the samplesheet. + ## Core Nextflow arguments :::note diff --git a/main.nf b/main.nf index 2f2ca54a..2d174a8c 100644 --- a/main.nf +++ b/main.nf @@ -9,8 +9,6 @@ ---------------------------------------------------------------------------------------- */ -nextflow.enable.dsl = 2 - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS / WORKFLOWS @@ -20,7 +18,6 @@ nextflow.enable.dsl = 2 include { AIRRFLOW } from './workflows/airrflow' include { PIPELINE_INITIALISATION } from './subworkflows/local/utils_nfcore_airrflow_pipeline' include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_airrflow_pipeline' - include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_airrflow_pipeline' /* @@ -52,10 +49,8 @@ workflow NFCORE_AIRRFLOW { AIRRFLOW ( samplesheet ) - emit: multiqc_report = AIRRFLOW.out.multiqc_report // channel: /path/to/multiqc_report.html - } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -66,13 +61,11 @@ workflow NFCORE_AIRRFLOW { workflow { main: - // // SUBWORKFLOW: Run initialisation tasks // PIPELINE_INITIALISATION ( params.version, - params.help, params.validate_params, params.monochrome_logs, args, @@ -86,7 +79,6 @@ workflow { NFCORE_AIRRFLOW ( PIPELINE_INITIALISATION.out.samplesheet ) - // // SUBWORKFLOW: Run completion tasks // diff --git a/modules.json b/modules.json index 3a6e053c..f04d35d8 100644 --- a/modules.json +++ b/modules.json @@ -17,7 +17,7 @@ }, "cellranger/vdj": { "branch": "master", - "git_sha": "3f5420aa22e00bd030a2556dfdffc9e164ec0ec5", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "fastp": { @@ -27,12 +27,17 @@ }, "fastqc": { "branch": "master", - "git_sha": "285a50500f9e02578d90b3ce6382ea3c30216acd", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "b7ebe95761cd389603f9cc0e0dc384c0f663815a", + "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", + "installed_by": ["modules"] + }, + "trust4": { + "branch": "master", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] } } @@ -41,17 +46,17 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "git_sha": "3aa0aec1d52d492fe241919f0c6100ebf0074082", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "92de218a329bfc9a9033116eb5f65fd270e72ba3", + "git_sha": "1b6b9a3338d011367137808b49b923515080e3ba", "installed_by": ["subworkflows"] }, - "utils_nfvalidation_plugin": { + "utils_nfschema_plugin": { "branch": "master", - "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "git_sha": "bbd5a41f4535a8defafe6080e00ea74c45f4f96c", "installed_by": ["subworkflows"] } } diff --git a/modules/local/airrflow_report/airrflow_report.nf b/modules/local/airrflow_report/airrflow_report.nf index 990e492e..5931831b 100644 --- a/modules/local/airrflow_report/airrflow_report.nf +++ b/modules/local/airrflow_report/airrflow_report.nf @@ -5,7 +5,7 @@ process AIRRFLOW_REPORT { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: tuple val(meta), path(tab) // sequence tsv table in AIRR format diff --git a/modules/local/changeo/changeo_makedb.nf b/modules/local/changeo/changeo_makedb.nf index 4862ba86..d0dadc66 100644 --- a/modules/local/changeo/changeo_makedb.nf +++ b/modules/local/changeo/changeo_makedb.nf @@ -21,10 +21,11 @@ process CHANGEO_MAKEDB { script: def args = task.ext.args ?: '' + def partial = meta.species.toLowerCase()=='mouse' && meta.locus.toLowerCase()=='tr' ? '--partial' : '' """ MakeDb.py igblast -i $igblast -s $reads -r \\ ${reference_fasta}/${meta.species.toLowerCase()}/vdj/ \\ - $args \\ + $args $partial \\ --outname ${meta.id} > ${meta.id}_makedb_command_log.txt cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/changeo/changeo_parsedb_select.nf b/modules/local/changeo/changeo_parsedb_select_locus.nf similarity index 72% rename from modules/local/changeo/changeo_parsedb_select.nf rename to modules/local/changeo/changeo_parsedb_select_locus.nf index 2bba4916..32805c26 100644 --- a/modules/local/changeo/changeo_parsedb_select.nf +++ b/modules/local/changeo/changeo_parsedb_select_locus.nf @@ -1,4 +1,4 @@ -process CHANGEO_PARSEDB_SELECT { +process CHANGEO_PARSEDB_SELECT_LOCUS { tag "$meta.id" label 'process_low' label 'immcantation' @@ -18,25 +18,21 @@ process CHANGEO_PARSEDB_SELECT { path "versions.yml" , emit: versions script: - def args = task.ext.args ?: '' - def args2 = task.ext.args2 ?: '' if (meta.locus.toUpperCase() == 'IG'){ """ - ParseDb.py select -d $tab $args --outname ${meta.id} > ${meta.id}_select_command_log.txt + ParseDb.py select -d $tab -f locus -u "IG[HKL]" --regex --outname ${meta.id} > ${meta.id}_select_command_log.txt cat <<-END_VERSIONS > versions.yml "${task.process}": - igblastn: \$( igblastn -version | grep -o "igblast[0-9\\. ]\\+" | grep -o "[0-9\\. ]\\+" ) changeo: \$( ParseDb.py --version | awk -F' ' '{print \$2}' ) END_VERSIONS """ } else if (meta.locus.toUpperCase() == 'TR'){ """ - ParseDb.py select -d $tab $args2 --outname ${meta.id} > "${meta.id}_command_log.txt" + ParseDb.py select -d $tab -f locus -u "TR[ABDG]" --regex --outname ${meta.id} > "${meta.id}_command_log.txt" cat <<-END_VERSIONS > versions.yml "${task.process}": - igblastn: \$( igblastn -version | grep -o "igblast[0-9\\. ]\\+" | grep -o "[0-9\\. ]\\+" ) changeo: \$( ParseDb.py --version | awk -F' ' '{print \$2}' ) END_VERSIONS """ diff --git a/modules/local/changeo/changeo_parsedb_split.nf b/modules/local/changeo/changeo_parsedb_split.nf index f67405bb..af950a77 100644 --- a/modules/local/changeo/changeo_parsedb_split.nf +++ b/modules/local/changeo/changeo_parsedb_split.nf @@ -13,7 +13,8 @@ process CHANGEO_PARSEDB_SPLIT { tuple val(meta), path(tab) // sequence tsv in AIRR format output: - tuple val(meta), path("*productive-T.tsv"), emit: tab // sequence tsv in AIRR format + tuple val(meta), path("*productive-T.tsv"), emit: tab //sequence tsv in AIRR format + tuple val(meta), path("*productive-F.tsv"), emit: unproductive, optional: true //optional non-productive sequences path("*_command_log.txt"), emit: logs //process logs path "versions.yml" , emit: versions diff --git a/modules/local/enchantr/collapse_duplicates.nf b/modules/local/enchantr/collapse_duplicates.nf index 618491ab..afd346dc 100644 --- a/modules/local/enchantr/collapse_duplicates.nf +++ b/modules/local/enchantr/collapse_duplicates.nf @@ -7,7 +7,7 @@ process COLLAPSE_DUPLICATES { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: tuple val(meta), path(tabs) // tuple [val(meta), sequence tsv in AIRR format ] diff --git a/modules/local/enchantr/define_clones.nf b/modules/local/enchantr/define_clones.nf index ae71b900..f234da66 100644 --- a/modules/local/enchantr/define_clones.nf +++ b/modules/local/enchantr/define_clones.nf @@ -24,7 +24,7 @@ process DEFINE_CLONES { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: tuple val(meta), path(tabs) // meta, sequence tsv in AIRR format @@ -59,7 +59,6 @@ process DEFINE_CLONES { 'threshold'=${thr}, \\ 'singlecell'='${params.singlecell}', \\ 'outdir'=getwd(), \\ - 'isotype_column'='${params.isotype_column}', \\ 'nproc'=${task.cpus}, \\ 'log'='${meta.id}_clone_command_log' ${args}))" diff --git a/modules/local/enchantr/detect_contamination.nf b/modules/local/enchantr/detect_contamination.nf index cec4deca..3716a8c3 100644 --- a/modules/local/enchantr/detect_contamination.nf +++ b/modules/local/enchantr/detect_contamination.nf @@ -8,7 +8,7 @@ process DETECT_CONTAMINATION { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: path(tabs) diff --git a/modules/local/enchantr/dowser_lineages.nf b/modules/local/enchantr/dowser_lineages.nf index 0559c496..2c92d290 100644 --- a/modules/local/enchantr/dowser_lineages.nf +++ b/modules/local/enchantr/dowser_lineages.nf @@ -24,7 +24,7 @@ process DOWSER_LINEAGES { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: tuple val(meta), path(tabs) diff --git a/modules/local/enchantr/find_threshold.nf b/modules/local/enchantr/find_threshold.nf index 4a9b0ab0..ecaf072f 100644 --- a/modules/local/enchantr/find_threshold.nf +++ b/modules/local/enchantr/find_threshold.nf @@ -24,7 +24,7 @@ process FIND_THRESHOLD { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: diff --git a/modules/local/enchantr/remove_chimeric.nf b/modules/local/enchantr/remove_chimeric.nf index 2df7e60c..b2b53073 100644 --- a/modules/local/enchantr/remove_chimeric.nf +++ b/modules/local/enchantr/remove_chimeric.nf @@ -8,7 +8,7 @@ process REMOVE_CHIMERIC { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: diff --git a/modules/local/enchantr/report_file_size.nf b/modules/local/enchantr/report_file_size.nf index 093a9e61..a198f47f 100644 --- a/modules/local/enchantr/report_file_size.nf +++ b/modules/local/enchantr/report_file_size.nf @@ -9,7 +9,7 @@ process REPORT_FILE_SIZE { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: path logs diff --git a/modules/local/enchantr/single_cell_qc.nf b/modules/local/enchantr/single_cell_qc.nf index 4170e51b..c331f70a 100644 --- a/modules/local/enchantr/single_cell_qc.nf +++ b/modules/local/enchantr/single_cell_qc.nf @@ -23,7 +23,7 @@ process SINGLE_CELL_QC { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: path(tabs) diff --git a/modules/local/enchantr/validate_input.nf b/modules/local/enchantr/validate_input.nf index 6ec12543..754a5c54 100644 --- a/modules/local/enchantr/validate_input.nf +++ b/modules/local/enchantr/validate_input.nf @@ -9,7 +9,7 @@ process VALIDATE_INPUT { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: file samplesheet diff --git a/modules/local/parse_logs.nf b/modules/local/parse_logs.nf index f811e427..8f4fb052 100644 --- a/modules/local/parse_logs.nf +++ b/modules/local/parse_logs.nf @@ -18,7 +18,7 @@ process PARSE_LOGS { path('assemble_pairs/*') //PRESTO_ASSEMBLEPAIRS logs path('deduplicates/*') //PRESTO_COLLAPSESEQ logs path('filter_representative_2/*') //PRESTO_SPLITSEQ logs - path('igblast/*') //CHANGEO_PARSEDB_SELECT logs + path('igblast/*') //CHANGEO_MAKEDB logs path('metadata.tsv') //METADATA output: diff --git a/modules/local/prepare_trust4_reference.nf b/modules/local/prepare_trust4_reference.nf new file mode 100644 index 00000000..e0c2306c --- /dev/null +++ b/modules/local/prepare_trust4_reference.nf @@ -0,0 +1,24 @@ +process PREPARE_TRUST4_REFERENCE { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::trust4=1.0.13" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/trust4:1.0.13--h43eeafb_0': + 'biocontainers/trust4:1.0.13--h43eeafb_0' }" + + input: + tuple val(meta), path(R1), path(R2) + path(reference_igblast) + + output: + path("trust4_reference.fa") , emit: trust4_reference + + script: + """ + cat ${reference_igblast}/fasta/imgt_${meta.species.toLowerCase()}_*.fasta \\ + ${reference_igblast}/fasta/imgt_${meta.species.toLowerCase()}_*.fasta >> trust4_reference.fa + """ + + +} diff --git a/modules/local/presto/presto_assemblepairs.nf b/modules/local/presto/presto_assemblepairs.nf index c6ba4287..e108f62a 100644 --- a/modules/local/presto/presto_assemblepairs.nf +++ b/modules/local/presto/presto_assemblepairs.nf @@ -14,7 +14,6 @@ process PRESTO_ASSEMBLEPAIRS { output: tuple val(meta), path("*_assemble-pass.fastq"), emit: reads path("*_command_log.txt"), emit: logs - path("*.log") path("*_table.tab") path "versions.yml" , emit: versions diff --git a/modules/local/presto/presto_assemblepairs_sequential.nf b/modules/local/presto/presto_assemblepairs_sequential.nf index 7d9cabb0..b47b9098 100644 --- a/modules/local/presto/presto_assemblepairs_sequential.nf +++ b/modules/local/presto/presto_assemblepairs_sequential.nf @@ -15,7 +15,6 @@ process PRESTO_ASSEMBLEPAIRS_SEQUENTIAL { output: tuple val(meta), path("*_assemble-pass.fastq"), emit: reads path("*_command_log.txt"), emit: logs - path("*.log") path("*_table.tab") path "versions.yml" , emit: versions diff --git a/modules/local/presto/presto_buildconsensus.nf b/modules/local/presto/presto_buildconsensus.nf index 2a85c3ea..9e6c6c4d 100644 --- a/modules/local/presto/presto_buildconsensus.nf +++ b/modules/local/presto/presto_buildconsensus.nf @@ -14,19 +14,16 @@ process PRESTO_BUILDCONSENSUS { output: tuple val(meta), path("*_R1_consensus-pass.fastq"), path("*_R2_consensus-pass.fastq"), emit: reads path("*_command_log.txt"), emit: logs - path("*_R1.log") - path("*_R2.log") path("*.tab"), emit: log_tab path "versions.yml" , emit: versions script: - def barcode_field = params.cluster_sets ? 'CLUSTER' : 'BARCODE' def args = task.ext.args ?: '' def args2 = task.ext.args2 ?: '' def args3 = task.ext.args3 ?: '' """ - BuildConsensus.py -s $R1 --bf ${barcode_field} --nproc ${task.cpus} --prcons ${params.primer_consensus} --maxerror ${params.buildconsensus_maxerror} --maxgap ${params.buildconsensus_maxgap} ${args} --outname ${meta.id}_R1 --log ${meta.id}_R1.log > ${meta.id}_command_log.txt - BuildConsensus.py -s $R2 --bf ${barcode_field} --nproc ${task.cpus} --prcons ${params.primer_consensus} --maxerror ${params.buildconsensus_maxerror} --maxgap ${params.buildconsensus_maxgap} ${args2} --outname ${meta.id}_R2 --log ${meta.id}_R2.log >> ${meta.id}_command_log.txt + BuildConsensus.py -s $R1 --nproc ${task.cpus} ${args} --outname ${meta.id}_R1 --log ${meta.id}_R1.log > ${meta.id}_command_log.txt + BuildConsensus.py -s $R2 --nproc ${task.cpus} ${args2} --outname ${meta.id}_R2 --log ${meta.id}_R2.log >> ${meta.id}_command_log.txt ParseLog.py -l ${meta.id}_R1.log ${meta.id}_R2.log ${args3} cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/presto/presto_clustersets.nf b/modules/local/presto/presto_clustersets.nf index 32061f0e..71868b5b 100644 --- a/modules/local/presto/presto_clustersets.nf +++ b/modules/local/presto/presto_clustersets.nf @@ -14,15 +14,16 @@ process PRESTO_CLUSTERSETS { output: tuple val(meta), path("*_R1_cluster-pass.fastq"), path("*_R2_cluster-pass.fastq"), emit: reads path "*_command_log.txt", emit: logs - path "*.log" path "*.tab", emit: log_tab path("versions.yml"), emit: versions script: + def args = task.ext.args ?: '' + def args2 = task.ext.args2 ?: '' """ - ClusterSets.py set --nproc ${task.cpus} -s $R1 --outname ${meta.id}_R1 --exec vsearch --log ${meta.id}_R1.log > ${meta.id}_command_log.txt - ClusterSets.py set --nproc ${task.cpus} -s $R2 --outname ${meta.id}_R2 --exec vsearch --log ${meta.id}_R2.log >> ${meta.id}_command_log.txt - ParseLog.py -l ${meta.id}_R1.log ${meta.id}_R2.log -f ID BARCODE SEQCOUNT CLUSTERS + ClusterSets.py set --nproc ${task.cpus} -s $R1 --outname ${meta.id}_R1 $args --log ${meta.id}_R1.log > ${meta.id}_command_log.txt + ClusterSets.py set --nproc ${task.cpus} -s $R2 --outname ${meta.id}_R2 $args --log ${meta.id}_R2.log >> ${meta.id}_command_log.txt + ParseLog.py -l ${meta.id}_R1.log ${meta.id}_R2.log $args2 cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/presto/presto_collapseseq.nf b/modules/local/presto/presto_collapseseq.nf index efbe4def..84177805 100644 --- a/modules/local/presto/presto_collapseseq.nf +++ b/modules/local/presto/presto_collapseseq.nf @@ -14,7 +14,6 @@ process PRESTO_COLLAPSESEQ { output: tuple val(meta), path("*_collapse-unique.fastq") , emit: reads path("*_command_log.txt") , emit: logs - path("*.log") path("*_table.tab") path("versions.yml"), emit: versions diff --git a/modules/local/presto/presto_filterseq.nf b/modules/local/presto/presto_filterseq.nf index a7733147..ee474865 100644 --- a/modules/local/presto/presto_filterseq.nf +++ b/modules/local/presto/presto_filterseq.nf @@ -15,8 +15,6 @@ process PRESTO_FILTERSEQ { tuple val(meta), path("*R1_quality-pass.fastq"), path("*R2_quality-pass.fastq") , emit: reads path "*_command_log_R?.txt" , emit: logs path "versions.yml" , emit: versions - path "*_R1.log" - path "*_R2.log" path "*.tab" , emit: log_tab script: diff --git a/modules/local/presto/presto_filterseq_postassembly.nf b/modules/local/presto/presto_filterseq_postassembly.nf index 0f821f5b..45dfea17 100644 --- a/modules/local/presto/presto_filterseq_postassembly.nf +++ b/modules/local/presto/presto_filterseq_postassembly.nf @@ -15,7 +15,6 @@ process PRESTO_FILTERSEQ_POSTASSEMBLY { tuple val(meta), path("*quality-pass.fastq") , emit: reads path "*_command_log.txt" , emit: logs path "versions.yml" , emit: versions - path "*.log" path "*.tab" , emit: log_tab script: diff --git a/modules/local/presto/presto_maskprimers.nf b/modules/local/presto/presto_maskprimers.nf index 48e66a84..26c88854 100644 --- a/modules/local/presto/presto_maskprimers.nf +++ b/modules/local/presto/presto_maskprimers.nf @@ -16,8 +16,6 @@ process PRESTO_MASKPRIMERS { output: tuple val(meta), path("*_R1_primers-pass.fastq"), path("*_R2_primers-pass.fastq") , emit: reads path "*_command_log_R?.txt", emit: logs - path "*_R1.log" - path "*_R2.log" path "*.tab", emit: log_tab path "versions.yml" , emit: versions @@ -28,8 +26,8 @@ process PRESTO_MASKPRIMERS { def primer_start_R1 = (params.index_file | params.umi_position == 'R1') ? "--start ${params.umi_length + params.cprimer_start} --barcode" : "--start ${params.cprimer_start}" def primer_start_R2 = (params.umi_position == 'R2') ? "--start ${params.umi_length + params.vprimer_start} --barcode" : "--start ${params.vprimer_start}" """ - MaskPrimers.py score --nproc ${task.cpus} -s $R1 -p ${cprimers} $primer_start_R1 $revpr --maxerror ${params.primer_r1_maxerror} --mode ${params.primer_mask_mode} --outname ${meta.id}_R1 --log ${meta.id}_R1.log > ${meta.id}_command_log_R1.txt - MaskPrimers.py score --nproc ${task.cpus} -s $R2 -p ${vprimers} $primer_start_R2 $revpr --maxerror ${params.primer_r2_maxerror} --mode ${params.primer_mask_mode} --outname ${meta.id}_R2 --log ${meta.id}_R2.log > ${meta.id}_command_log_R2.txt + MaskPrimers.py score --nproc ${task.cpus} -s $R1 -p ${cprimers} $primer_start_R1 $revpr --maxerror ${params.primer_r1_maxerror} --mode ${params.primer_r1_mask_mode} --outname ${meta.id}_R1 --log ${meta.id}_R1.log > ${meta.id}_command_log_R1.txt + MaskPrimers.py score --nproc ${task.cpus} -s $R2 -p ${vprimers} $primer_start_R2 $revpr --maxerror ${params.primer_r2_maxerror} --mode ${params.primer_r2_mask_mode} --outname ${meta.id}_R2 --log ${meta.id}_R2.log > ${meta.id}_command_log_R2.txt ParseLog.py -l ${meta.id}_R1.log ${meta.id}_R2.log -f ID PRIMER ERROR cat <<-END_VERSIONS > versions.yml @@ -41,8 +39,8 @@ process PRESTO_MASKPRIMERS { def primer_start_R1 = (params.index_file | params.umi_position == 'R1') ? "--start ${params.umi_length + params.vprimer_start} --barcode" : "--start ${params.vprimer_start}" def primer_start_R2 = (params.umi_position == 'R2') ? "--start ${params.umi_length + params.cprimer_start} --barcode" : "--start ${params.cprimer_start}" """ - MaskPrimers.py score --nproc ${task.cpus} -s $R1 -p ${vprimers} $primer_start_R1 $revpr --maxerror ${params.primer_r1_maxerror} --mode ${params.primer_mask_mode} --outname ${meta.id}_R1 --log ${meta.id}_R1.log > ${meta.id}_command_log_R1.txt - MaskPrimers.py score --nproc ${task.cpus} -s $R2 -p ${cprimers} $primer_start_R2 $revpr --maxerror ${params.primer_r2_maxerror} --mode ${params.primer_mask_mode} --outname ${meta.id}_R2 --log ${meta.id}_R2.log > ${meta.id}_command_log_R2.txt + MaskPrimers.py score --nproc ${task.cpus} -s $R1 -p ${vprimers} $primer_start_R1 $revpr --maxerror ${params.primer_r1_maxerror} --mode ${params.primer_r1_mask_mode} --outname ${meta.id}_R1 --log ${meta.id}_R1.log > ${meta.id}_command_log_R1.txt + MaskPrimers.py score --nproc ${task.cpus} -s $R2 -p ${cprimers} $primer_start_R2 $revpr --maxerror ${params.primer_r2_maxerror} --mode ${params.primer_r2_mask_mode} --outname ${meta.id}_R2 --log ${meta.id}_R2.log > ${meta.id}_command_log_R2.txt ParseLog.py -l "${meta.id}_R1.log" "${meta.id}_R2.log" -f ID PRIMER ERROR cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/presto/presto_maskprimers_align.nf b/modules/local/presto/presto_maskprimers_align.nf index 055e5d93..dce835dc 100644 --- a/modules/local/presto/presto_maskprimers_align.nf +++ b/modules/local/presto/presto_maskprimers_align.nf @@ -10,32 +10,37 @@ process PRESTO_MASKPRIMERS_ALIGN { input: tuple val(meta), path(R1) - path(cprimers) + path(primers) val(max_len) + val(barcode) val(max_error) val(mask_mode) + val(reverse_primers) + val(suffix) output: - tuple val(meta), path("*_R1_primers-pass.fastq") , emit: reads - path "*_command_log_R1.txt", emit: logs - path "*_R1.log" + tuple val(meta), path("*_primers-pass.fastq") , emit: reads + path "*.txt", emit: logs path "*.tab", emit: log_tab path "versions.yml" , emit: versions script: + def barcode = barcode ? '--barcode' : '' + def revpr = reverse_primers ? '--revpr' : '' def args = task.ext.args?: '' def args2 = task.ext.args2?: '' """ MaskPrimers.py align --nproc ${task.cpus} \\ -s $R1 \\ - -p ${cprimers} \\ + -p ${primers} \\ --maxlen ${max_len} \\ --maxerror ${max_error} \\ --mode ${mask_mode} \\ + $barcode \\ $args \\ - --outname ${meta.id}_R1 \\ - --log ${meta.id}_R1.log > ${meta.id}_command_log_R1.txt - ParseLog.py -l ${meta.id}_R1.log $args2 + --outname ${meta.id}_${suffix} \\ + --log ${meta.id}_${suffix}.log > ${meta.id}_command_log_${suffix}.txt + ParseLog.py -l ${meta.id}_${suffix}.log $args2 cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/presto/presto_maskprimers_extract.nf b/modules/local/presto/presto_maskprimers_extract.nf index 661389e0..fad8d624 100644 --- a/modules/local/presto/presto_maskprimers_extract.nf +++ b/modules/local/presto/presto_maskprimers_extract.nf @@ -9,28 +9,35 @@ process PRESTO_MASKPRIMERS_EXTRACT { 'biocontainers/presto:0.7.1--pyhdfd78af_0' }" input: - tuple val(meta), path(R2) + tuple val(meta), path(read) + val(extract_start) + val(extract_length) + val(extract_mode) + val(barcode) + val(suffix) output: - tuple val(meta), path("*_R2_primers-pass.fastq") , emit: reads - path "*_command_log_R2.txt", emit: logs - path "*_R2.log" + tuple val(meta), path("*_primers-pass.fastq") , emit: reads + path "*.txt", emit: logs path "*.tab", emit: log_tab path "versions.yml" , emit: versions script: def args = task.ext.args?: '' def args2 = task.ext.args2?: '' + def barcode = barcode ? '--barcode' : '' """ - MaskPrimers.py extract --nproc ${task.cpus} \\ - -s $R2 \\ - --start ${params.umi_length} \\ - --len ${params.primer_extract_len} \\ + MaskPrimers.py extract \\ + --nproc ${task.cpus} \\ + -s $read \\ + --start ${extract_start} \\ + --len ${extract_length} \\ + $barcode \\ $args \\ - --mode ${params.primer_mask_mode} \\ - --outname ${meta.id}_R2 \\ - --log ${meta.id}_R2.log >> ${meta.id}_command_log_R2.txt - ParseLog.py -l ${meta.id}_R2.log $args2 + --mode ${extract_mode} \\ + --outname ${meta.id}_${suffix} \\ + --log ${meta.id}_${suffix}.log >> ${meta.id}_command_log_${suffix}.txt + ParseLog.py -l *.log $args2 cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/presto/presto_maskprimers_postassembly.nf b/modules/local/presto/presto_maskprimers_postassembly.nf index 91427c90..ef5cd4c7 100644 --- a/modules/local/presto/presto_maskprimers_postassembly.nf +++ b/modules/local/presto/presto_maskprimers_postassembly.nf @@ -16,7 +16,6 @@ process PRESTO_MASKPRIMERS_POSTASSEMBLY { output: tuple val(meta), path("*REV_primers-pass.fastq") , emit: reads path "*command_log.txt", emit: logs - path "*.log" path "*.tab", emit: log_tab path "versions.yml" , emit: versions @@ -25,10 +24,10 @@ process PRESTO_MASKPRIMERS_POSTASSEMBLY { if (params.cprimer_position == "R1") { """ MaskPrimers.py score --nproc ${task.cpus} -s $reads -p ${cprimers} --start ${params.cprimer_start} --maxerror ${params.primer_r1_maxerror} \ - --mode ${params.primer_mask_mode} --outname ${meta.id}-FWD \ + --mode ${params.primer_r1_mask_mode} --outname ${meta.id}-FWD \ --log ${meta.id}-FWD.log > ${meta.id}_command_log.txt MaskPrimers.py score --nproc ${task.cpus} -s ${meta.id}-FWD_primers-pass.fastq -p ${vprimers} --start ${params.vprimer_start} --maxerror ${params.primer_r2_maxerror} \ - --mode ${params.primer_mask_mode} --outname ${meta.id}-REV $revpr \ + --mode ${params.primer_r2_mask_mode} --outname ${meta.id}-REV $revpr \ --log ${meta.id}-REV.log >> ${meta.id}_command_log.txt ParseLog.py -l ${meta.id}-FWD.log ${meta.id}-REV.log -f ID PRIMER ERROR @@ -40,10 +39,10 @@ process PRESTO_MASKPRIMERS_POSTASSEMBLY { } else if (params.cprimer_position == "R2") { """ MaskPrimers.py score --nproc ${task.cpus} -s $reads -p ${vprimers} --start ${params.vprimer_start} --maxerror ${params.primer_r1_maxerror} \ - --mode ${params.primer_mask_mode} --outname ${meta.id}-FWD \ + --mode ${params.primer_r1_mask_mode} --outname ${meta.id}-FWD \ --log ${meta.id}-FWD.log > ${meta.id}_command_log.txt MaskPrimers.py score --nproc ${task.cpus} -s ${meta.id}-FWD_primers-pass.fastq -p ${cprimers} --start ${params.cprimer_start} --maxerror ${params.primer_r2_maxerror} \ - --mode ${params.primer_mask_mode} --outname ${meta.id}-REV $revpr \ + --mode ${params.primer_r2_mask_mode} --outname ${meta.id}-REV $revpr \ --log ${meta.id}-REV.log >> ${meta.id}_command_log.txt ParseLog.py -l ${meta.id}-FWD.log ${meta.id}-REV.log -f ID PRIMER ERROR diff --git a/modules/local/presto/presto_maskprimers_score.nf b/modules/local/presto/presto_maskprimers_score.nf new file mode 100644 index 00000000..77b90cfc --- /dev/null +++ b/modules/local/presto/presto_maskprimers_score.nf @@ -0,0 +1,52 @@ +process PRESTO_MASKPRIMERS_SCORE { + tag "$meta.id" + label "process_high" + label 'immcantation' + + conda "bioconda::presto=0.7.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/presto:0.7.1--pyhdfd78af_0' : + 'biocontainers/presto:0.7.1--pyhdfd78af_0' }" + + input: + tuple val(meta), path(read) + path(primers) + val(primer_start) + val(barcode) + val(primer_maxerror) + val(primer_mask_mode) + val(reverse_primers) + val(suffix) + + output: + tuple val(meta), path("*_primers-pass.fastq"), emit: reads + path "*.txt", emit: logs + path "*.tab", emit: log_tab + path "versions.yml" , emit: versions + + + script: + def args = task.ext.args?: '' + def args2 = task.ext.args2?: '' + def revpr = reverse_primers ? '--revpr' : '' + def barcode = barcode ? '--barcode' : '' + """ + MaskPrimers.py score \\ + --nproc ${task.cpus} \\ + -s $read \\ + -p ${primers} \\ + --maxerror ${primer_maxerror} \\ + --mode ${primer_mask_mode} \\ + --start ${primer_start} \\ + $barcode $revpr \\ + $args \\ + --outname ${meta.id}_${suffix} \\ + --log ${meta.id}_${suffix}.log > ${meta.id}_command_log_${suffix}.txt + ParseLog.py -l *.log $args2 + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + presto: \$( MaskPrimers.py --version | awk -F' ' '{print \$2}' ) + END_VERSIONS + """ +} diff --git a/modules/local/presto/presto_pairseq.nf b/modules/local/presto/presto_pairseq.nf index 40ac33b1..cbd37cd3 100644 --- a/modules/local/presto/presto_pairseq.nf +++ b/modules/local/presto/presto_pairseq.nf @@ -10,6 +10,7 @@ process PRESTO_PAIRSEQ { input: tuple val(meta), path("${meta.id}_R1.fastq"), path("${meta.id}_R2.fastq") + val(barcode_position) output: tuple val(meta), path("*R1_pair-pass.fastq"), path("*R2_pair-pass.fastq") , emit: reads @@ -17,7 +18,7 @@ process PRESTO_PAIRSEQ { path "versions.yml" , emit: versions script: - def copyfield = (params.index_file | params.umi_position == 'R1') ? "--1f BARCODE" : "--2f BARCODE" + def copyfield = (barcode_position == 'R1')? '--1f BARCODE' : (barcode_position == 'R2')? '--2f BARCODE' : (barcode_position == 'R1R2')? '--1f BARCODE --2f BARCODE' : (barcode_position == 'clustersets')? '--1f CLUSTER --2f CLUSTER' : '' def args = task.ext.args?: '' """ PairSeq.py -1 ${meta.id}_R1.fastq -2 ${meta.id}_R2.fastq $copyfield $args > ${meta.id}_command_log.txt diff --git a/modules/local/reveal/add_meta_to_tab.nf b/modules/local/reveal/add_meta_to_tab.nf index 1c50d60e..889d929e 100644 --- a/modules/local/reveal/add_meta_to_tab.nf +++ b/modules/local/reveal/add_meta_to_tab.nf @@ -6,7 +6,7 @@ process ADD_META_TO_TAB { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" cache 'deep' // Without 'deep' this process would run when using -resume diff --git a/modules/local/reveal/filter_junction_mod3.nf b/modules/local/reveal/filter_junction_mod3.nf index 92ef4833..9408bd2d 100644 --- a/modules/local/reveal/filter_junction_mod3.nf +++ b/modules/local/reveal/filter_junction_mod3.nf @@ -6,7 +6,7 @@ process FILTER_JUNCTION_MOD3 { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: tuple val(meta), path(tab) // sequence tsv in AIRR format diff --git a/modules/local/reveal/filter_quality.nf b/modules/local/reveal/filter_quality.nf index 4675ed17..12a79ec6 100644 --- a/modules/local/reveal/filter_quality.nf +++ b/modules/local/reveal/filter_quality.nf @@ -6,7 +6,7 @@ process FILTER_QUALITY { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "nf-core/airrflow currently does not support Conda. Please use a container profile instead." } - container "docker.io/immcantation/airrflow:4.1.0" + container "docker.io/immcantation/airrflow:4.2.0" input: tuple val(meta), path(tab) // sequence tsv in AIRR format diff --git a/modules/nf-core/cellranger/vdj/environment.yml b/modules/nf-core/cellranger/vdj/environment.yml deleted file mode 100644 index 2ddcc0c6..00000000 --- a/modules/nf-core/cellranger/vdj/environment.yml +++ /dev/null @@ -1,5 +0,0 @@ -name: cellranger_vdj -channels: - - conda-forge - - bioconda - - defaults diff --git a/modules/nf-core/cellranger/vdj/main.nf b/modules/nf-core/cellranger/vdj/main.nf index 45a920f0..590d368f 100644 --- a/modules/nf-core/cellranger/vdj/main.nf +++ b/modules/nf-core/cellranger/vdj/main.nf @@ -2,7 +2,7 @@ process CELLRANGER_VDJ { tag "${meta.id}" label 'process_high' - container "nf-core/cellranger:7.1.0" + container "nf-core/cellranger:8.0.0" input: tuple val(meta), path(reads) diff --git a/modules/nf-core/cellranger/vdj/meta.yml b/modules/nf-core/cellranger/vdj/meta.yml index 3f4d7788..8fbd75e8 100644 --- a/modules/nf-core/cellranger/vdj/meta.yml +++ b/modules/nf-core/cellranger/vdj/meta.yml @@ -1,5 +1,6 @@ name: cellranger_vdj -description: Module to use Cell Ranger's pipelines analyze sequencing data produced from Chromium Single Cell Immune Profiling. +description: Module to use Cell Ranger's pipelines analyze sequencing data produced + from Chromium Single Cell Immune Profiling. keywords: - align - vdj @@ -9,40 +10,54 @@ keywords: - cellranger tools: - cellranger: - description: Cell Ranger processes data from 10X Genomics Chromium kits. `cellranger vdj` takes FASTQ files from `cellranger mkfastq` or `bcl2fastq` for V(D)J libraries and performs sequence assembly and paired clonotype calling. It uses the Chromium cellular barcodes and UMIs to assemble V(D)J transcripts per cell. Clonotypes and CDR3 sequences are output as a `.vloupe` file which can be loaded into Loupe V(D)J Browser. + description: Cell Ranger processes data from 10X Genomics Chromium kits. `cellranger + vdj` takes FASTQ files from `cellranger mkfastq` or `bcl2fastq` for V(D)J libraries + and performs sequence assembly and paired clonotype calling. It uses the Chromium + cellular barcodes and UMIs to assemble V(D)J transcripts per cell. Clonotypes + and CDR3 sequences are output as a `.vloupe` file which can be loaded into Loupe + V(D)J Browser. homepage: https://support.10xgenomics.com/single-cell-vdj/software/pipelines/latest/what-is-cell-ranger documentation: https://support.10xgenomics.com/single-cell-vdj/software/pipelines/latest/tutorial/tutorial-vdj tool_dev_url: https://support.10xgenomics.com/single-cell-vdj/software/pipelines/latest/tutorial/tutorial-vdj - licence: 10x Genomics EULA + licence: [10X Genomics EULA] + identifier: "" input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - reads: - type: file - description: | - List of input FastQ files of size 1 and 2 for single-end and paired-end data, - respectively. - pattern: "${Sample_Name}_S1_L00${Lane_Number}_${I1,I2,R1,R2}_001.fastq.gz" - - reference: - type: directory - description: Folder containing all the reference indices needed by Cell Ranger + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: | + List of input FastQ files of size 1 and 2 for single-end and paired-end data, + respectively. + pattern: "${Sample_Name}_S1_L00${Lane_Number}_${I1,I2,R1,R2}_001.fastq.gz" + - - reference: + type: directory + description: Folder containing all the reference indices needed by Cell Ranger output: - outs: - type: file - description: Files containing the outputs of Cell Ranger, see official 10X Genomics documentation for a complete list - pattern: "${meta.id}/outs/*" + - meta: + type: file + description: Files containing the outputs of Cell Ranger, see official 10X Genomics + documentation for a complete list + pattern: "${meta.id}/outs/*" + - "**/outs/**": + type: file + description: Files containing the outputs of Cell Ranger, see official 10X Genomics + documentation for a complete list + pattern: "${meta.id}/outs/*" - versions: - type: file - description: File containing software version - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software version + pattern: "versions.yml" authors: - "@ggabernet" - - "@Emiller88" + - "@edmundmiller" - "@klkeys" maintainers: - "@ggabernet" - - "@Emiller88" + - "@edmundmiller" - "@klkeys" diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml index 1787b38a..691d4c76 100644 --- a/modules/nf-core/fastqc/environment.yml +++ b/modules/nf-core/fastqc/environment.yml @@ -1,7 +1,5 @@ -name: fastqc channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::fastqc=0.12.1 diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index d79f1c86..d8989f48 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -26,7 +26,10 @@ process FASTQC { def rename_to = old_new_pairs*.join(' ').join(' ') def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ') - def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') + // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) + // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 + // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label + def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') / task.cpus // FastQC memory value allowed range (100 - 10000) def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml index ee5507e0..4827da7a 100644 --- a/modules/nf-core/fastqc/meta.yml +++ b/modules/nf-core/fastqc/meta.yml @@ -16,35 +16,44 @@ tools: homepage: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/ documentation: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/ licence: ["GPL-2.0-only"] + identifier: biotools:fastqc input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - reads: - type: file - description: | - List of input FastQ files of size 1 and 2 for single-end and paired-end data, - respectively. + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: | + List of input FastQ files of size 1 and 2 for single-end and paired-end data, + respectively. output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - html: - type: file - description: FastQC report - pattern: "*_{fastqc.html}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.html": + type: file + description: FastQC report + pattern: "*_{fastqc.html}" - zip: - type: file - description: FastQC report archive - pattern: "*_{fastqc.zip}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.zip": + type: file + description: FastQC report archive + pattern: "*_{fastqc.zip}" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@drpatelh" - "@grst" diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test index 70edae4d..e9d79a07 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -23,17 +23,14 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. - // looks like this:

Mon 2 Oct 2023
test.gz
- // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 - - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_single") } + { assert process.success }, + // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. + // looks like this:
Mon 2 Oct 2023
test.gz
+ // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -54,16 +51,14 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, - { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, - { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, - { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, - { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_paired") } + { assert process.success }, + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -83,13 +78,11 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_interleaved") } + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -109,13 +102,11 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_bam") } + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -138,22 +129,20 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, - { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, - { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, - { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, - { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, - { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, - { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, - { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, - { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_multiple") } + { assert process.success }, + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, + { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, + { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -173,21 +162,18 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_custom_prefix") } + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } test("sarscov2 single-end [fastq] - stub") { - options "-stub" - + options "-stub" when { process { """ @@ -201,12 +187,123 @@ nextflow_process { then { assertAll ( - { assert process.success }, - { assert snapshot(process.out.html.collect { file(it[1]).getName() } + - process.out.zip.collect { file(it[1]).getName() } + - process.out.versions ).match("fastqc_stub") } + { assert process.success }, + { assert snapshot(process.out).match() } ) } } + test("sarscov2 paired-end [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 interleaved [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 paired-end [bam] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 multiple [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 custom_prefix - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } } diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap index 86f7c311..d5db3092 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test.snap +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -1,88 +1,392 @@ { - "fastqc_versions_interleaved": { + "sarscov2 custom_prefix": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:07.293713" + "timestamp": "2024-07-22T11:02:16.374038" }, - "fastqc_stub": { + "sarscov2 single-end [fastq] - stub": { "content": [ - [ - "test.html", - "test.zip", - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:24.993809" + }, + "sarscov2 custom_prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:31:01.425198" + "timestamp": "2024-07-22T11:03:10.93942" }, - "fastqc_versions_multiple": { + "sarscov2 interleaved [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:55.797907" + "timestamp": "2024-07-22T11:01:42.355718" }, - "fastqc_versions_bam": { + "sarscov2 paired-end [bam]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:26.795862" + "timestamp": "2024-07-22T11:01:53.276274" }, - "fastqc_versions_single": { + "sarscov2 multiple [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:39:27.043675" + "timestamp": "2024-07-22T11:02:05.527626" }, - "fastqc_versions_paired": { + "sarscov2 paired-end [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:31.188871" + }, + "sarscov2 paired-end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:34.273566" + }, + "sarscov2 multiple [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:39:47.584191" + "timestamp": "2024-07-22T11:03:02.304411" }, - "fastqc_versions_custom_prefix": { + "sarscov2 single-end [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:19.095607" + }, + "sarscov2 interleaved [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:44.640184" + }, + "sarscov2 paired-end [bam] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:41:14.576531" + "timestamp": "2024-07-22T11:02:53.550742" } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index ca39fb67..6f5b867b 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -1,7 +1,5 @@ -name: multiqc channels: - conda-forge - bioconda - - defaults dependencies: - - bioconda::multiqc=1.21 + - bioconda::multiqc=1.25.1 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 47ac352f..cc0643e1 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -3,14 +3,16 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.21--pyhdfd78af_0' : - 'biocontainers/multiqc:1.21--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.25.1--pyhdfd78af_0' : + 'biocontainers/multiqc:1.25.1--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" path(multiqc_config) path(extra_multiqc_config) path(multiqc_logo) + path(replace_names) + path(sample_names) output: path "*multiqc_report.html", emit: report @@ -23,16 +25,22 @@ process MULTIQC { script: def args = task.ext.args ?: '' + def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' def config = multiqc_config ? "--config $multiqc_config" : '' def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' - def logo = multiqc_logo ? /--cl-config 'custom_logo: "${multiqc_logo}"'/ : '' + def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' + def replace = replace_names ? "--replace-names ${replace_names}" : '' + def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ $args \\ $config \\ + $prefix \\ $extra_config \\ $logo \\ + $replace \\ + $samples \\ . cat <<-END_VERSIONS > versions.yml @@ -44,7 +52,7 @@ process MULTIQC { stub: """ mkdir multiqc_data - touch multiqc_plots + mkdir multiqc_plots touch multiqc_report.html cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index 45a9bc35..b16c1879 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,5 +1,6 @@ name: multiqc -description: Aggregate results from bioinformatics analyses across many samples into a single report +description: Aggregate results from bioinformatics analyses across many samples into + a single report keywords: - QC - bioinformatics tools @@ -12,40 +13,59 @@ tools: homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ licence: ["GPL-3.0-or-later"] + identifier: biotools:multiqc input: - - multiqc_files: - type: file - description: | - List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - - multiqc_config: - type: file - description: Optional config yml for MultiQC - pattern: "*.{yml,yaml}" - - extra_multiqc_config: - type: file - description: Second optional config yml for MultiQC. Will override common sections in multiqc_config. - pattern: "*.{yml,yaml}" - - multiqc_logo: - type: file - description: Optional logo file for MultiQC - pattern: "*.{png}" + - - multiqc_files: + type: file + description: | + List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + - - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + - - extra_multiqc_config: + type: file + description: Second optional config yml for MultiQC. Will override common sections + in multiqc_config. + pattern: "*.{yml,yaml}" + - - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" + - - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + - - sample_names: + type: file + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" output: - report: - type: file - description: MultiQC report file - pattern: "multiqc_report.html" + - "*multiqc_report.html": + type: file + description: MultiQC report file + pattern: "multiqc_report.html" - data: - type: directory - description: MultiQC data dir - pattern: "multiqc_data" + - "*_data": + type: directory + description: MultiQC data dir + pattern: "multiqc_data" - plots: - type: file - description: Plots created by MultiQC - pattern: "*_data" + - "*_plots": + type: file + description: Plots created by MultiQC + pattern: "*_data" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@abhi18av" - "@bunop" diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test index f1c4242e..33316a7d 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -8,6 +8,8 @@ nextflow_process { tag "modules_nfcore" tag "multiqc" + config "./nextflow.config" + test("sarscov2 single-end [fastqc]") { when { @@ -17,6 +19,8 @@ nextflow_process { input[1] = [] input[2] = [] input[3] = [] + input[4] = [] + input[5] = [] """ } } @@ -41,6 +45,8 @@ nextflow_process { input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) input[2] = [] input[3] = [] + input[4] = [] + input[5] = [] """ } } @@ -66,6 +72,8 @@ nextflow_process { input[1] = [] input[2] = [] input[3] = [] + input[4] = [] + input[5] = [] """ } } diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index bfebd802..2fcbb5ff 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "multiqc_versions_single": { "content": [ [ - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.4" }, - "timestamp": "2024-02-29T08:48:55.657331" + "timestamp": "2024-10-02T17:51:46.317523" }, "multiqc_stub": { "content": [ @@ -17,25 +17,25 @@ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.4" }, - "timestamp": "2024-02-29T08:49:49.071937" + "timestamp": "2024-10-02T17:52:20.680978" }, "multiqc_versions_config": { "content": [ [ - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.4" }, - "timestamp": "2024-02-29T08:49:25.457567" + "timestamp": "2024-10-02T17:52:09.185842" } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/tests/nextflow.config b/modules/nf-core/multiqc/tests/nextflow.config new file mode 100644 index 00000000..c537a6a3 --- /dev/null +++ b/modules/nf-core/multiqc/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = null + } +} diff --git a/modules/nf-core/trust4/environment.yml b/modules/nf-core/trust4/environment.yml new file mode 100644 index 00000000..7e07e377 --- /dev/null +++ b/modules/nf-core/trust4/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - "bioconda::trust4=1.0.13" diff --git a/modules/nf-core/trust4/main.nf b/modules/nf-core/trust4/main.nf new file mode 100644 index 00000000..1d822fb8 --- /dev/null +++ b/modules/nf-core/trust4/main.nf @@ -0,0 +1,105 @@ +process TRUST4 { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::trust4=1.0.13" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/trust4:1.0.13--h43eeafb_0': + 'biocontainers/trust4:1.0.13--h43eeafb_0' }" + + input: + tuple val(meta), path(bam), path(reads) + tuple val(meta2), path(fasta) + tuple val(meta3), path(vdj_reference) + tuple val(meta4), val(barcode_read) + tuple val(meta5), val(umi_read) + + output: + tuple val(meta), path("*.tsv") , emit: tsv + tuple val(meta), path("*_airr.tsv") , emit: airr_files + tuple val(meta), path("${meta.id}_airr.tsv") , emit: airr_tsv + tuple val(meta), path("*_report.tsv") , emit: report_tsv + tuple val(meta), path("*.fa") , emit: fasta + tuple val(meta), path("*.out") , emit: out + tuple val(meta), path("*.fq") , emit: fq + tuple val(meta), path("**") , emit: outs + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def bam_mode = bam ? "-b ${bam}" : '' + def single_end_mode = reads && meta.single_end ? "-u ${reads}" : '' + // reference is optional for fastq input + def reference = vdj_reference ? "--ref ${vdj_reference}" : "" + // separate forward from reverse pairs + def (forward, reverse) = reads.collate(2).transpose() + def paired_end_mode = reads && (meta.single_end == false) ? "-1 ${forward[0]} -2 ${reverse[0]}" : '' + // read format is optional + def readFormat = params.read_format ? "--readFormat ${params.read_format}" : '' + // add barcode information if present + if (barcode_read) { + if (barcode_read == "R1") { + barcode = "--barcode ${forward[0]}" + } else if (barcode_read == "R2") { + barcode = "--barcode ${reverse[0]}" + } + } + else { + barcode = '' + } + // add umi information if present + if (umi_read) { + if (umi_read == "R1") { + umi = "--UMI ${forward[0]}" + } else if (umi_read == "R2") { + umi = "--UMI ${reverse[0]}" + } + } + else { + umi = '' + } + + """ + run-trust4 \\ + ${bam_mode} \\ + ${single_end_mode} \\ + ${paired_end_mode} \\ + ${barcode} \\ + ${readFormat} \\ + ${umi} \\ + -t $task.cpus \\ + -f ${fasta} \\ + -o ${prefix} \\ + ${reference} \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + trust4: \$(run-trust4 2>&1 | grep -o 'v[0-9.]*-r[0-9]*' | sed 's/^/TRUST4 using /' ) + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}_airr.tsv + touch ${prefix}_airr_align.tsv + touch ${prefix}_report.tsv + touch ${prefix}_assembled_reads.fa + touch ${prefix}_annot.fa + touch ${prefix}_cdr3.out + touch ${prefix}_raw.out + touch ${prefix}_final.out + touch ${prefix}_toassemble.fq + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + trust4: \$(run-trust4 2>&1 | grep -o 'v[0-9.]*-r[0-9]*' | sed 's/^/TRUST4 using /' ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/trust4/meta.yml b/modules/nf-core/trust4/meta.yml new file mode 100644 index 00000000..da2a5ff4 --- /dev/null +++ b/modules/nf-core/trust4/meta.yml @@ -0,0 +1,151 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "trust4" +description: Run TRUST4 on RNA-seq data +keywords: + - sort + - example + - genomics +tools: + - "trust4": + description: "TCR and BCR assembly from bulk or single-cell RNA-seq data" + homepage: "https://github.com/liulab-dfci/TRUST4" + documentation: "https://github.com/liulab-dfci/TRUST4" + tool_dev_url: "https://github.com/liulab-dfci/TRUST4" + licence: ["GPL v3"] + identifier: biotools:trust4 + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - bam: + type: file + description: BAM file from bulk or single-cell RNA-seq data + pattern: "*.bam" + - reads: + type: file + description: List of input FastQ files of size 1 and 2 for single-end and paired-end + data, respectively + - - meta2: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: Path to the fasta file coordinate and sequence of V/D/J/C genes + - - meta3: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - vdj_reference: + type: file + description: reference file of V/D/J genes + - - meta4: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - barcode_read: + type: file + description: barcode read file + - - meta5: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - umi_read: + type: file + description: umi read file +output: + - tsv: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "*.tsv": + type: file + description: tsv files created by TRUST4 + pattern: "*.tsv" + - airr_files: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "*_airr.tsv": + type: file + description: TRUST4 results in AIRR format + pattern: "*_airr.tsv" + - airr_tsv: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - ${meta.id}_airr.tsv: + type: file + description: TRUST4 results in AIRR format + pattern: "*_airr.tsv" + - report_tsv: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "*_report.tsv": + type: file + description: TRUST4 report in tsv format + pattern: "*_report.tsv" + - fasta: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "*.fa": + type: file + description: Fasta files created by TRUST4 + pattern: "*.fa" + - out: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "*.out": + type: file + description: Further report files + pattern: "*.out" + - fq: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "*.fq": + type: file + description: Fastq files created by TRUST4 + pattern: "*.fq" + - outs: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "**": + type: file + description: outputt files + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@mapo9, @Joaodemeirelles" +maintainers: + - "@mapo9" diff --git a/modules/nf-core/trust4/tests/main.nf.test b/modules/nf-core/trust4/tests/main.nf.test new file mode 100644 index 00000000..7b6c36da --- /dev/null +++ b/modules/nf-core/trust4/tests/main.nf.test @@ -0,0 +1,123 @@ +nextflow_process { + + name "Test Process TRUST4" + script "../main.nf" + process "TRUST4" + + tag "modules" + tag "modules_nfcore" + tag "trust4" + + test("sarscov2 - single_end") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [], // bam + [file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] // reads + ]) + input[1] = [[ id:'test'],[file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true)]] // fasta + input[2] = [[ id:'test'],[]] // ref + input[3] = [[ id:'test'],[]] // barcode + input[4] = [[ id:'test'],[]] // umi + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.airr_tsv, + process.out.fq, + process.out.fasta, + process.out.report_tsv, + process.out.versions, + ).match() }, + { assert process.out.out[0][1][0] ==~ ".*/test_cdr3.out" }, + { assert process.out.out[0][1][1] ==~ ".*/test_final.out" }, + { assert process.out.out[0][1][2] ==~ ".*/test_raw.out" }, + { assert process.out.tsv[0][1][0] ==~ ".*/test_airr.tsv" }, + { assert process.out.tsv[0][1][1] ==~ ".*/test_airr_align.tsv" }, + { assert process.out.tsv[0][1][2] ==~ ".*/test_report.tsv" } + ) + } + + } + + test("sarscov2 - paired_end") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [], // bam + [file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true)] // reads + ]) + input[1] = [[ id:'test'],[file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true)]] // fasta + input[2] = [[ id:'test'],[]] // ref + input[3] = [[ id:'test'], null] // barcode + input[4] = [[ id:'test'], null] // umi + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.airr_tsv, + process.out.fq, + process.out.fasta, + process.out.report_tsv, + process.out.versions, + ).match() }, + { assert process.out.out[0][1][0] ==~ ".*/test_cdr3.out" }, + { assert process.out.out[0][1][1] ==~ ".*/test_final.out" }, + { assert process.out.out[0][1][2] ==~ ".*/test_raw.out" }, + { assert process.out.tsv[0][1][0] ==~ ".*/test_airr.tsv" }, + { assert process.out.tsv[0][1][1] ==~ ".*/test_airr_align.tsv" }, + { assert process.out.tsv[0][1][2] ==~ ".*/test_report.tsv" } + ) + } + + } + + test("sarscov2 - single_end - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [], + [file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + input[1] = [[ id:'test'],[file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true)]] + input[2] = [[ id:'test'],[]] // ref + input[3] = [[ id:'test'],[]] // barcode + input[4] = [[ id:'test'],[]] // umi + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.versions).match("versions") }, + { assert process.out.out[0][1][0] ==~ ".*/test_cdr3.out" }, + { assert process.out.out[0][1][1] ==~ ".*/test_final.out" }, + { assert process.out.out[0][1][2] ==~ ".*/test_raw.out" }, + { assert process.out.tsv[0][1][0] ==~ ".*/test_airr.tsv" }, + { assert process.out.tsv[0][1][1] ==~ ".*/test_airr_align.tsv" }, + { assert process.out.tsv[0][1][2] ==~ ".*/test_report.tsv" } + ) + } + + } + +} diff --git a/modules/nf-core/trust4/tests/main.nf.test.snap b/modules/nf-core/trust4/tests/main.nf.test.snap new file mode 100644 index 00000000..75414757 --- /dev/null +++ b/modules/nf-core/trust4/tests/main.nf.test.snap @@ -0,0 +1,119 @@ +{ + "sarscov2 - single_end": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test_airr.tsv:md5,572c69a08a82acc5ff9a2bf95488b0a4" + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test_toassemble.fq:md5,bd7ab2f9ea96290e58e868e4aabccf1f" + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + [ + "test_annot.fa:md5,4b07aefcac3763f7f3d242d9371060df", + "test_assembled_reads.fa:md5,2c9601da894105f2fe6c068659214db3" + ] + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test_report.tsv:md5,51623a22f060007a69207b1ebdf3a7cd" + ] + ], + [ + "versions.yml:md5,ef2e18f5d083f09211fb613305df93e8" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-04T13:50:19.120375" + }, + "versions": { + "content": [ + [ + "versions.yml:md5,ef2e18f5d083f09211fb613305df93e8" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-04T13:48:46.513295" + }, + "sarscov2 - paired_end": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test_airr.tsv:md5,572c69a08a82acc5ff9a2bf95488b0a4" + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_toassemble_1.fq:md5,bd7ab2f9ea96290e58e868e4aabccf1f", + "test_toassemble_2.fq:md5,0211588305d478e10879fb35b93e13d5" + ] + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_annot.fa:md5,4207f198195fa19b505ffa67feba776a", + "test_assembled_reads.fa:md5,60f27ccec04b5b1826ecf1fd87fd4ad6" + ] + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + "test_report.tsv:md5,51623a22f060007a69207b1ebdf3a7cd" + ] + ], + [ + "versions.yml:md5,ef2e18f5d083f09211fb613305df93e8" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-04T13:50:24.230727" + } +} \ No newline at end of file diff --git a/modules/nf-core/trust4/tests/tags.yml b/modules/nf-core/trust4/tests/tags.yml new file mode 100644 index 00000000..cacc72be --- /dev/null +++ b/modules/nf-core/trust4/tests/tags.yml @@ -0,0 +1,2 @@ +trust4: + - "modules/nf-core/trust4/**" diff --git a/nextflow.config b/nextflow.config index e51ff966..2955ec03 100644 --- a/nextflow.config +++ b/nextflow.config @@ -52,12 +52,15 @@ params { filterseq_q = 20 // Mask primers - primer_r1_maxerror = 0.2 primer_r2_maxerror = 0.2 - primer_mask_mode = 'cut' + primer_r1_mask_mode = 'cut' + primer_r2_mask_mode = 'cut' + maskprimers_align_race = false maskprimers_align = false - primer_extract_len = 0 + maskprimers_extract = false + primer_r1_extract_len = 0 + primer_r2_extract_len = 0 primer_maxlen = 50 // Build consensus @@ -85,7 +88,7 @@ params { reference_fasta = "${params.pipelines_testdata_base_path}database-cache/imgtdb_base.zip" fetch_imgt = false save_databases = true - isotype_column = 'c_call' + skip_alignment_filter = false // ----------------------- // bulk filtering options @@ -123,13 +126,20 @@ params { // ----------------------- reference_10x = null + // ----------------------- + // raw RNA seq input options + // ----------------------- + cell_barcode_read = null + read_format = null + umi_read = null + // ----------------------- // generic nf-core options // ----------------------- // References - igenomes_base = 's3://ngi-igenomes/igenomes' + igenomes_base = 's3://ngi-igenomes/igenomes/' igenomes_ignore = true // MultiQC options @@ -149,47 +159,26 @@ params { monochrome_logs = false hook_url = null help = false + help_full = false + show_hidden = false version = false // Config options config_profile_name = null config_profile_description = null + custom_config_version = 'master' custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" config_profile_contact = null config_profile_url = null - // Max resource options - // Defaults only, expecting to be overwritten - max_memory = '128.GB' - max_cpus = 16 - max_time = '240.h' - // Schema validation default options - validationFailUnrecognisedParams = false - validationLenientMode = false - validationSchemaIgnoreParams = 'genomes,igenomes_base' - validationShowHiddenParams = false - validate_params = true - + validate_params = true } // Load base.config by default for all pipelines includeConfig 'conf/base.config' -// Load nf-core custom profiles from different Institutions -try { - includeConfig "${params.custom_config_base}/nfcore_custom.config" -} catch (Exception e) { - System.err.println("WARNING: Could not load nf-core/config profiles: ${params.custom_config_base}/nfcore_custom.config") -} - -// Load nf-core/airrflow custom profiles from different institutions. -try { - includeConfig "${params.custom_config_base}/pipeline/airrflow.config" -} catch (Exception e) { - System.err.println("WARNING: Could not load nf-core/config/airrflow profiles: ${params.custom_config_base}/pipeline/airrflow.config") -} profiles { debug { dumpHashes = true @@ -204,7 +193,7 @@ profiles { podman.enabled = false shifter.enabled = false charliecloud.enabled = false - conda.channels = ['conda-forge', 'bioconda', 'defaults'] + conda.channels = ['conda-forge', 'bioconda'] apptainer.enabled = false } mamba { @@ -304,32 +293,36 @@ profiles { test_fetchimgt { includeConfig 'conf/test_fetchimgt.config' } test_10x_sc { includeConfig 'conf/test_10x_sc.config' } test_clontech_umi { includeConfig 'conf/test_clontech_umi.config' } + test_maskprimers_extract { includeConfig 'conf/test_maskprimers_extract.config' } + test_maskprimers_align {includeConfig 'conf/test_maskprimers_align.config' } test_nebnext_umi { includeConfig 'conf/test_nebnext_umi.config' } + test_rnaseq_bulk { includeConfig 'conf/test_rnaseq_bulk.config' } + test_rnaseq_sc { includeConfig 'conf/test_rnaseq_sc.config' } nebnext_umi_tcr { includeConfig 'conf/nebnext_umi_tcr.config' } nebnext_umi_bcr { includeConfig 'conf/nebnext_umi_bcr.config' } clontech_umi_bcr { includeConfig 'conf/clontech_umi_bcr.config' } clontech_umi_tcr { includeConfig 'conf/clontech_umi_tcr.config' } } -// Set default registry for Apptainer, Docker, Podman and Singularity independent of -profile -// Will not be used unless Apptainer / Docker / Podman / Singularity are enabled -// Set to your registry if you have a mirror of containers -apptainer.registry = 'quay.io' -docker.registry = 'quay.io' -podman.registry = 'quay.io' -singularity.registry = 'quay.io' +// Load nf-core custom profiles from different Institutions +includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/nfcore_custom.config" : "/dev/null" -// Nextflow plugins -plugins { - id 'nf-validation@1.1.3' // Validation of pipeline parameters and creation of an input channel from a sample sheet -} +// Load nf-core/airrflow custom profiles from different institutions. +// Optionally, you can add a pipeline-specific nf-core config at https://github.com/nf-core/configs +// includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/pipeline/airrflow.config" : "/dev/null" + +// Set default registry for Apptainer, Docker, Podman, Charliecloud and Singularity independent of -profile +// Will not be used unless Apptainer / Docker / Podman / Charliecloud / Singularity are enabled +// Set to your registry if you have a mirror of containers +apptainer.registry = 'quay.io' +docker.registry = 'quay.io' +podman.registry = 'quay.io' +singularity.registry = 'quay.io' +charliecloud.registry = 'quay.io' // Load igenomes.config if required -if (!params.igenomes_ignore) { - includeConfig 'conf/igenomes.config' -} else { - params.genomes = [:] -} +includeConfig !params.igenomes_ignore ? 'conf/igenomes.config' : 'conf/igenomes_ignored.config' + // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -343,8 +336,15 @@ env { JULIA_DEPOT_PATH = "/usr/local/share/julia" } -// Capture exit codes from upstream processes when piping -process.shell = ['/bin/bash', '-euo', 'pipefail'] +// Set bash options +process.shell = """\ +bash + +set -e # Exit if a tool returns a non-zero status/exit code +set -u # Treat unset variables and parameters as an error +set -o pipefail # Returns the status of the last command to exit with a non-zero status or zero if all successfully execute +set -C # No clobber - prevent output redirection from overwriting files. +""" // Disable process selector warnings by default. Use debug profile to enable warnings. nextflow.enable.configProcessNamesValidation = false @@ -369,47 +369,50 @@ dag { manifest { name = 'nf-core/airrflow' - author = """Gisela Gabernet, Susanna Marquez, Alexander Peltzer, Simon Heumos""" + author = """Gisela Gabernet, Susanna Marquez, Alexander Peltzer""" homePage = 'https://github.com/nf-core/airrflow' description = """B and T cell repertoire analysis pipeline with the Immcantation framework.""" mainScript = 'main.nf' - nextflowVersion = '!>=23.04.0' - version = '4.1.0' - doi = '10.5281/zenodo.2642009' + nextflowVersion = '!>=24.04.2' + version = '4.2.0' + doi = 'https://doi.org/10.1371/journal.pcbi.1012265' } -// Load modules.config for DSL2 module specific options -includeConfig 'conf/modules.config' +// Nextflow plugins +plugins { + id 'nf-schema@2.1.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet +} -// Function to ensure that resource requirements don't go beyond -// a maximum limit -def check_max(obj, type) { - if (type == 'memory') { - try { - if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) - return params.max_memory as nextflow.util.MemoryUnit - else - return obj - } catch (all) { - println " ### ERROR ### Max memory '${params.max_memory}' is not valid! Using default value: $obj" - return obj - } - } else if (type == 'time') { - try { - if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1) - return params.max_time as nextflow.util.Duration - else - return obj - } catch (all) { - println " ### ERROR ### Max time '${params.max_time}' is not valid! Using default value: $obj" - return obj - } - } else if (type == 'cpus') { - try { - return Math.min( obj, params.max_cpus as int ) - } catch (all) { - println " ### ERROR ### Max cpus '${params.max_cpus}' is not valid! Using default value: $obj" - return obj - } +validation { + defaultIgnoreParams = ["genomes"] + help { + enabled = true + command = "nextflow run $manifest.name -profile --input samplesheet.csv --outdir " + fullParameter = "help_full" + showHiddenParameter = "show_hidden" + beforeText = """ +-\033[2m----------------------------------------------------\033[0m- + \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m +\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m +\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m +\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m + \033[0;32m`._,._,\'\033[0m +\033[0;35m ${manifest.name} ${manifest.version}\033[0m +-\033[2m----------------------------------------------------\033[0m- +""" + afterText = """${manifest.doi ? "* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} +* The nf-core framework + https://doi.org/10.1038/s41587-020-0439-x + +* Software dependencies + https://github.com/${manifest.name}/blob/master/CITATIONS.md +""" + } + summary { + beforeText = validation.help.beforeText + afterText = validation.help.afterText } } + +// Load modules.config for DSL2 module specific options +includeConfig 'conf/modules.config' diff --git a/nextflow_schema.json b/nextflow_schema.json index 1c32a276..aeac4cad 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -1,12 +1,12 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://raw.githubusercontent.com/nf-core/airrflow/master/nextflow_schema.json", "title": "nf-core/airrflow pipeline parameters", "description": "B and T cell repertoire analysis pipeline with the Immcantation framework.", "type": "object", - "definitions": { + "$defs": { "input_output_options": { - "title": "Input/output options", + "title": "Input output options", "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", @@ -61,7 +61,14 @@ "type": "string", "fa_icon": "fas fa-flask", "description": "Protocol used for the V(D)J amplicon sequencing library generation.", - "enum": ["specific_pcr_umi", "specific_pcr", "dt_5p_race", "dt_5p_race_umi", "sc_10x_genomics"], + "enum": [ + "specific_pcr_umi", + "specific_pcr", + "dt_5p_race", + "dt_5p_race_umi", + "sc_10x_genomics", + "trust4" + ], "help_text": "Available protocols are:\n- `specific_pcr_umi`: RT-PCR using transcript-specific primers containing UMIs.\n- `specific_pcr`: RT-PCR using transcript-specific primers.\n- `dt_5p_race_umi`: 5\u2019-RACE PCR using oligo-dT primers and template switch primers containing UMI.\n- `dt_5p_race`: 5\u2019-RACE PCR (i.e. RT is followed by a template switch (TS) step) using oligo-dT primers.\n- `sc_10x_genomics`:10x genomics library preparation protocol for scVDJ sequencing." }, "race_linker": { @@ -72,8 +79,8 @@ }, "fa_icon": "fas fa-flask" }, - "primer_handling": { - "title": "Primer handling", + "primer_input_and_positions": { + "title": "Primer input and positions", "type": "object", "description": "Define the primer region start and how to deal with the primer alignment.", "default": "", @@ -207,7 +214,7 @@ } }, "sequence_assembly_options": { - "title": "sequence assembly options", + "title": "Sequence Assembly options", "type": "object", "description": "Options for the pRESTO sequence assembly processes", "default": "", @@ -224,14 +231,6 @@ "description": "Maximum error for building the primer consensus in the pRESTO Buildconsensus step.", "fa_icon": "fas fa-align-left" }, - "primer_mask_mode": { - "type": "string", - "default": "cut", - "description": "Masking mode for the pRESTO MaskPrimer step. Available: cut, mask, trim, tag.", - "enum": ["cut", "mask", "tag", "trim"], - "help_text": "The primer masking modes will perform the following actions:\n\n* `cut`: remove both the primer region and the preceding sequence.\n* `mask`: replace the primer region with Ns and remove the preceding sequence.\n* `trim`: remove the region preceding the primer, but leave the primer region intact.\n* `tag`: leave the input sequence unmodified.", - "fa_icon": "fas fa-mask" - }, "buildconsensus_maxerror": { "type": "number", "default": 0.1, @@ -267,18 +266,52 @@ "fa_icon": "fas fa-align-center", "description": "Align primers instead of scoring them. Used for protocols without primer fixed positions." }, - "primer_extract_len": { - "type": "integer", - "default": 0, - "fa_icon": "fas fa-align-center", - "description": "Length of the extracted primers with MaskPrimer extract." - }, "primer_maxlen": { "type": "integer", "default": 50, "fa_icon": "fas fa-align-center", "description": "Maximum allowed primer length when aligning the primers." }, + "primer_r1_mask_mode": { + "type": "string", + "fa_icon": "fas fa-mask", + "description": "Masking mode for R1 primers.", + "enum": ["cut", "mask", "trim", "tag"], + "default": "cut", + "help_text": "See [pRESTO MaskPrimers](https://presto.readthedocs.io/en/stable/tools/MaskPrimers.html) for more information." + }, + "primer_r2_mask_mode": { + "type": "string", + "default": "cut", + "fa_icon": "fas fa-mask", + "enum": ["cut", "mask", "trim", "tag"], + "description": "Masking mode for R2 primers.", + "help_text": "See [pRESTO MaskPrimers](https://presto.readthedocs.io/en/stable/tools/MaskPrimers.html) for more information." + }, + "maskprimers_align_race": { + "type": "boolean", + "fa_icon": "fas fa-align-center", + "description": "Use MaskPrimers align for a 5' RACE protocol.", + "help_text": "It will align the C-primers with pRESTO MaskPrimers align, and extract the template-switch Oligo and/or linker with defined length in `--primer_r2_extract_len`." + }, + "maskprimers_extract": { + "type": "boolean", + "fa_icon": "fas fa-cut", + "description": "Use when primer sequences are unknown but when their approximate positions are known.", + "help_text": "Use in combination with `--primer_r1_extract_len` and `--primer_r2_extract_len` to define the sequence regions to cut corresponding to the approximate unknown primer sequence length prior to alignment. It is also possible to define a UMI barcode for extraction if it's position is unknown." + }, + "primer_r1_extract_len": { + "type": "integer", + "default": 0, + "fa_icon": "fas fa-cut", + "description": "R1 primer extract length when using `--maskprimers_extract`." + }, + "primer_r2_extract_len": { + "type": "integer", + "default": 0, + "fa_icon": "fas fa-cut", + "description": "R2 primer extract length when using `--maskprimers_extract`." + }, "assemblepairs_sequential": { "type": "boolean", "fa_icon": "fas fa-align-center", @@ -311,6 +344,11 @@ "default": "tag", "fa_icon": "fas fa-mask", "description": "Mask mode for C-region alignment." + }, + "skip_alignment_filter": { + "type": "boolean", + "fa_icon": "fas fa-fast-forward", + "description": "Skip filter step after alignment that ensures that locus should match the v_call chain, the sequence alignment should have at least 200 informative positions (excluding N or gaps), and maximum 10% N nucleotides in the alignment." } }, "fa_icon": "fas fa-align-center" @@ -336,31 +374,27 @@ "save_databases": { "type": "boolean", "description": "Save databases so you can use the cache in future runs.", - "fa_icon": "fas fa-file-download" + "fa_icon": "fas fa-file-download", + "default": true }, "reference_fasta": { "type": "string", "description": "Path to the germline reference fasta.", "help_text": "By default, we provide a pre-downloaded version of the IMGT database. It is also possible to provide a custom reference fasta database. To fetch a fresh version of IMGT, set the `--fetch_imgt` parameter instead.", - "fa_icon": "fas fa-database" + "fa_icon": "fas fa-database", + "default": "https://raw.githubusercontent.com/nf-core/test-datasets/airrflow/database-cache/imgtdb_base.zip" }, "reference_igblast": { "type": "string", "description": "Path to the cached igblast database.", "help_text": "By default, we provide a pre-downloaded version of the IMGT database. It is also possible to provide a custom reference fasta database. To fetch a fresh version of IMGT, set the `--fetch_imgt` parameter instead.", - "fa_icon": "fas fa-database" + "fa_icon": "fas fa-database", + "default": "https://raw.githubusercontent.com/nf-core/test-datasets/airrflow/database-cache/igblast_base.zip" }, "fetch_imgt": { "type": "boolean", "description": "Set this flag to fetch the IMGT reference data at runtime.", "fa_icon": "fas fa-cloud-download-alt" - }, - "isotype_column": { - "type": "string", - "description": "Set the column in the AIRR rearrangement file that isotype information should be gathered from.", - "default": "c_call", - "fa_icon": "fas fa-border-all", - "help_text": "Default is the `c_call` column. For bulk protocols one can use the c_primers or cregion columns (check `align_cregion`). The primer or cregions fasta file header need to contain the strings `IGHA`, `IGHD`, `IGHG`... for the isotypes to be properly parsed. This will be used for plotting mutation frequency by isotype in the clonal analysis report." } }, "fa_icon": "fas fa-edit" @@ -434,13 +468,13 @@ "default": "raxml", "description": "Lineage tree software to use to build trees within Dowser. If you change the default, also set the `lineage_tree_exec` parameter.", "enum": ["raxml", "igphyml"], - "fa_icon": "fas fa-pagelines" + "fa_icon": "fab fa-pagelines" }, "lineage_tree_exec": { "type": "string", "default": "/usr/local/bin/raxml-ng", "description": "Path to lineage tree building executable.", - "fa_icon": "fas fa-pagelines" + "fa_icon": "fab fa-pagelines" }, "singlecell": { "type": "string", @@ -478,6 +512,36 @@ "help_text": "Options for running raw single cell data.", "fa_icon": "fab fa-pagelines" }, + "rnaseq_based_analysis_options": { + "title": "Unselected RNA-seq based analysis options", + "type": "object", + "description": "Options specific for raw unselected RNA-seq input.", + "default": "", + "properties": { + "cell_barcode_read": { + "type": "string", + "description": "Specifies which read holds the barcodes", + "enum": ["R1", "R2"], + "fa_icon": "fas fa-terminal", + "help_text": "file containing the barcodes" + }, + "umi_read": { + "type": "string", + "description": "Indicate if UMI indices are recorded in the R1 (default) or R1 fastq file.", + "help_text": "file containing 10x Genomics-like UMIs", + "enum": ["R1", "R2"], + "fa_icon": "fas fa-barcode" + }, + "read_format": { + "type": "string", + "description": "Specifies where in the read the barcodes and UMIs can be found.", + "help_text": "For further information see the TRUST4 [docs](https://github.com/liulab-dfci/TRUST4?tab=readme-ov-file#10x-genomics-data-and-barcode-based-single-cell-data).", + "fa_icon": "fas fa-terminal" + } + }, + "help_text": "Options for running raw RNA seq data.", + "fa_icon": "fab fa-pagelines" + }, "report_options": { "title": "Report options", "type": "object", @@ -527,14 +591,6 @@ "fa_icon": "fas fa-dna", "description": "Options for the reference genome indices used to align reads.", "properties": { - "igenomes_base": { - "type": "string", - "format": "directory-path", - "description": "Directory / URL base for iGenomes references.", - "default": "s3://ngi-igenomes/igenomes", - "fa_icon": "fas fa-cloud-download-alt", - "hidden": true - }, "igenomes_ignore": { "type": "boolean", "description": "Do not load the iGenomes reference config.", @@ -542,6 +598,14 @@ "hidden": true, "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`.", "default": true + }, + "igenomes_base": { + "type": "string", + "format": "directory-path", + "description": "The base path to the igenomes reference files", + "fa_icon": "fas fa-ban", + "hidden": true, + "default": "s3://ngi-igenomes/igenomes/" } } }, @@ -594,41 +658,6 @@ } } }, - "max_job_request_options": { - "title": "Max job request options", - "type": "object", - "fa_icon": "fas fa-microchip", - "description": "Set the top limit for requested resources for any single job.", - "help_text": "If you are running on a smaller system, a pipeline step requesting more resources than are available may cause Nextflow to stop the run with an error. These options allow you to cap the maximum resources requested by any single job so that the pipeline will run on your system.\n\nNote that you can not _increase_ the resources requested by any job using these options. For that you will need your own configuration file. See [the nf-core website](https://nf-co.re/usage/configuration) for details.", - "properties": { - "max_cpus": { - "type": "integer", - "description": "Maximum number of CPUs that can be requested for any single job.", - "default": 16, - "fa_icon": "fas fa-microchip", - "hidden": true, - "help_text": "Use to set an upper-limit for the CPU requirement for each process. Should be an integer e.g. `--max_cpus 1`" - }, - "max_memory": { - "type": "string", - "description": "Maximum amount of memory that can be requested for any single job.", - "default": "128.GB", - "fa_icon": "fas fa-memory", - "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", - "hidden": true, - "help_text": "Use to set an upper-limit for the memory requirement for each process. Should be a string in the format integer-unit e.g. `--max_memory '8.GB'`" - }, - "max_time": { - "type": "string", - "description": "Maximum amount of time that can be requested for any single job.", - "default": "240.h", - "fa_icon": "far fa-clock", - "pattern": "^(\\d+\\.?\\s*(s|m|h|d|day)\\s*)+$", - "hidden": true, - "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" - } - } - }, "generic_options": { "title": "Generic options", "type": "object", @@ -636,12 +665,6 @@ "description": "Less common options for the pipeline, typically set in a config file.", "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", "properties": { - "help": { - "type": "boolean", - "description": "Display help text.", - "fa_icon": "fas fa-question-circle", - "hidden": true - }, "version": { "type": "boolean", "description": "Display version and exit.", @@ -722,27 +745,6 @@ "fa_icon": "fas fa-check-square", "hidden": true }, - "validationShowHiddenParams": { - "type": "boolean", - "fa_icon": "far fa-eye-slash", - "description": "Show all params when using `--help`", - "hidden": true, - "help_text": "By default, parameters set as _hidden_ in the schema are not shown on the command line when a user runs with `--help`. Specifying this option will tell the pipeline to show all parameters." - }, - "validationFailUnrecognisedParams": { - "type": "boolean", - "fa_icon": "far fa-check-circle", - "description": "Validation of parameters fails when an unrecognised parameter is found.", - "hidden": true, - "help_text": "By default, when an unrecognised parameter is found, it returns a warinig." - }, - "validationLenientMode": { - "type": "boolean", - "fa_icon": "far fa-check-circle", - "description": "Validation of parameters in lenient more.", - "hidden": true, - "help_text": "Allows string values that are parseable as numbers or booleans. For further information see [JSONSchema docs](https://github.com/everit-org/json-schema#lenient-mode)." - }, "pipelines_testdata_base_path": { "type": "string", "fa_icon": "far fa-check-circle", @@ -755,49 +757,82 @@ }, "allOf": [ { - "$ref": "#/definitions/input_output_options" + "$ref": "#/$defs/input_output_options" + }, + { + "$ref": "#/$defs/protocol" + }, + { + "$ref": "#/$defs/primer_input_and_positions" + }, + { + "$ref": "#/$defs/umi_barcode_handling" + }, + { + "$ref": "#/$defs/adapter_trimming" + }, + { + "$ref": "#/$defs/sequence_assembly_options" + }, + { + "$ref": "#/$defs/vdj_annotation_options" + }, + { + "$ref": "#/$defs/bulk_filtering_options" + }, + { + "$ref": "#/$defs/clonal_analysis_options" + }, + { + "$ref": "#/$defs/single_cell_analysis_options" + }, + { + "$ref": "#/$defs/rnaseq_based_analysis_options" + }, + { + "$ref": "#/$defs/report_options" }, { - "$ref": "#/definitions/protocol" + "$ref": "#/$defs/protocol" }, { - "$ref": "#/definitions/primer_handling" + "$ref": "#/$defs/primer_input_and_positions" }, { - "$ref": "#/definitions/umi_barcode_handling" + "$ref": "#/$defs/umi_barcode_handling" }, { - "$ref": "#/definitions/adapter_trimming" + "$ref": "#/$defs/adapter_trimming" }, { - "$ref": "#/definitions/sequence_assembly_options" + "$ref": "#/$defs/sequence_assembly_options" }, { - "$ref": "#/definitions/vdj_annotation_options" + "$ref": "#/$defs/vdj_annotation_options" }, { - "$ref": "#/definitions/bulk_filtering_options" + "$ref": "#/$defs/bulk_filtering_options" }, { - "$ref": "#/definitions/clonal_analysis_options" + "$ref": "#/$defs/clonal_analysis_options" }, { - "$ref": "#/definitions/report_options" + "$ref": "#/$defs/single_cell_analysis_options" }, { - "$ref": "#/definitions/reference_genome_options" + "$ref": "#/$defs/rnaseq_based_analysis_options" }, { - "$ref": "#/definitions/single_cell_analysis_options" + "$ref": "#/$defs/report_options" }, { - "$ref": "#/definitions/institutional_config_options" + "$ref": "#/$defs/reference_genome_options" }, { - "$ref": "#/definitions/max_job_request_options" + "$ref": "#/$defs/institutional_config_options" }, { - "$ref": "#/definitions/generic_options" + "$ref": "#/$defs/generic_options" } ] } diff --git a/subworkflows/local/fastq_input_check.nf b/subworkflows/local/fastq_input_check.nf index e14cfc21..91412b15 100644 --- a/subworkflows/local/fastq_input_check.nf +++ b/subworkflows/local/fastq_input_check.nf @@ -29,8 +29,8 @@ workflow FASTQ_INPUT_CHECK { ch_versions = SAMPLESHEET_CHECK.out.versions - // Merge multi-lane sample fastq for protocols except for 10x genomics (cellranger handles multi-fastq per sample) - if (params.library_generation_method == 'sc_10x_genomics') { + // Merge multi-lane sample fastq for protocols except for 10x genomics, trust4 (cellranger handles multi-fastq per sample) + if (params.library_generation_method == 'sc_10x_genomics' || params.library_generation_method == 'trust4') { ch_merged_reads = ch_reads.single.mix( ch_reads.multiple ) @@ -85,10 +85,9 @@ def create_fastq_channels(LinkedHashMap col) { } array = [ meta, [ file(col.filename_R1), file(col.filename_R2), file(col.filename_I1) ] ] } else { - array = [ meta, [ file(col.filename_R1), file(col.filename_R2) ] ] if (params.index_file) { - error "ERROR: --index_file was provided but the index file path is not specified in the samplesheet!" + error "ERROR: Index file path was provided but the index file path is not specified in the samplesheet!" } } return array diff --git a/subworkflows/local/presto_sans_umi.nf b/subworkflows/local/presto_sans_umi.nf index 8d75856d..0161d769 100644 --- a/subworkflows/local/presto_sans_umi.nf +++ b/subworkflows/local/presto_sans_umi.nf @@ -7,11 +7,14 @@ include { FASTP } from '../../modu //PRESTO include { PRESTO_ASSEMBLEPAIRS as PRESTO_ASSEMBLEPAIRS_SANS_UMI } from '../../modules/local/presto/presto_assemblepairs' include { PRESTO_FILTERSEQ_POSTASSEMBLY as PRESTO_FILTERSEQ_POSTASSEMBLY_SANS_UMI } from '../../modules/local/presto/presto_filterseq_postassembly' -include { PRESTO_MASKPRIMERS_POSTASSEMBLY as PRESTO_MASKPRIMERS_POSTASSEMBLY_SANS_UMI } from '../../modules/local/presto/presto_maskprimers_postassembly' -include { PRESTO_PARSEHEADERS_PRIMERS as PRESTO_PARSEHEADERS_PRIMERS_SANS_UMI } from '../../modules/local/presto/presto_parseheaders_primers' -include { PRESTO_PARSEHEADERS_METADATA as PRESTO_PARSEHEADERS_METADATA_SANS_UMI } from '../../modules/local/presto/presto_parseheaders_metadata' -include { PRESTO_COLLAPSESEQ as PRESTO_COLLAPSESEQ_SANS_UMI } from '../../modules/local/presto/presto_collapseseq' -include { PRESTO_SPLITSEQ as PRESTO_SPLITSEQ_SANS_UMI} from '../../modules/local/presto/presto_splitseq' +include { PRESTO_MASKPRIMERS_SCORE as PRESTO_MASKPRIMERS_SCORE_SANSUMI_FWD } from '../../modules/local/presto/presto_maskprimers_score' +include { PRESTO_MASKPRIMERS_SCORE as PRESTO_MASKPRIMERS_SCORE_SANSUMI_REV } from '../../modules/local/presto/presto_maskprimers_score' +include { PRESTO_MASKPRIMERS_ALIGN as PRESTO_MASKPRIMERS_ALIGN_SANSUMI_FWD } from '../../modules/local/presto/presto_maskprimers_align' +include { PRESTO_MASKPRIMERS_ALIGN as PRESTO_MASKPRIMERS_ALIGN_SANSUMI_REV } from '../../modules/local/presto/presto_maskprimers_align' +include { PRESTO_PARSEHEADERS_PRIMERS as PRESTO_PARSEHEADERS_PRIMERS_SANS_UMI } from '../../modules/local/presto/presto_parseheaders_primers' +include { PRESTO_PARSEHEADERS_METADATA as PRESTO_PARSEHEADERS_METADATA_SANS_UMI } from '../../modules/local/presto/presto_parseheaders_metadata' +include { PRESTO_COLLAPSESEQ as PRESTO_COLLAPSESEQ_SANS_UMI } from '../../modules/local/presto/presto_collapseseq' +include { PRESTO_SPLITSEQ as PRESTO_SPLITSEQ_SANS_UMI} from '../../modules/local/presto/presto_splitseq' workflow PRESTO_SANS_UMI { @@ -54,22 +57,128 @@ workflow PRESTO_SANS_UMI { ch_versions = ch_versions.mix(PRESTO_FILTERSEQ_POSTASSEMBLY_SANS_UMI.out.versions) // Mask primers - PRESTO_MASKPRIMERS_POSTASSEMBLY_SANS_UMI ( - PRESTO_FILTERSEQ_POSTASSEMBLY_SANS_UMI.out.reads, - ch_cprimers.collect(), - ch_vprimers.collect() - ) - ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_POSTASSEMBLY_SANS_UMI.out.versions) + def suffix_FWD = "R1" + def suffix_REV = "R2" + def barcode_R1 = false + def barcode_R2 = false + ch_reads = PRESTO_FILTERSEQ_POSTASSEMBLY_SANS_UMI.out.reads + if (params.maskprimers_align){ + if (params.cprimer_position == "R1") { + PRESTO_MASKPRIMERS_ALIGN_SANSUMI_FWD( + ch_reads, + ch_cprimers.collect(), + params.primer_maxlen, + params.primer_r1_maxerror, + params.primer_r1_mask_mode, + suffix_FWD + ) + PRESTO_MASKPRIMERS_ALIGN_SANSUMI_REV( + PRESTO_MASKPRIMERS_ALIGN_SANSUMI_FWD.out.reads, + ch_vprimers.collect(), + params.primer_maxlen, + params.primer_r2_maxerror, + params.primer_r2_mask_mode, + suffix_REV + ) + } else if (params.cprimer_position == "R2") { + PRESTO_MASKPRIMERS_ALIGN_SANSUMI_FWD( + ch_reads, + ch_vprimers.collect(), + params.primer_maxlen, + params.primer_r1_maxerror, + params.primer_r1_mask_mode, + suffix_FWD + ) + PRESTO_MASKPRIMERS_ALIGN_SANSUMI_REV( + PRESTO_MASKPRIMERS_ALIGN_SANSUMI_FWD.out.reads, + ch_cprimers.collect(), + params.primer_maxlen, + params.primer_r2_maxerror, + params.primer_r2_mask_mode, + suffix_REV + ) + } else { + error "Error in determining cprimer position. Please choose R1 or R2." + } + + ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_ALIGN_SANSUMI_FWD.out.versions) + + ch_maskprimers_logs = PRESTO_MASKPRIMERS_ALIGN_SANSUMI_FWD.out.logs + ch_maskprimers_logs = ch_maskprimers_logs.mix(PRESTO_MASKPRIMERS_ALIGN_SANSUMI_REV.out.logs) + + ch_masked_reads = PRESTO_MASKPRIMERS_ALIGN_SANSUMI_REV.out.reads + } else { + if (params.cprimer_position == "R1") { + def start_FWD = "${params.cprimer_start}" + def start_REV = "${params.vprimer_start}" + def revpr_FWD = false + PRESTO_MASKPRIMERS_SCORE_SANSUMI_FWD( + ch_reads, + ch_cprimers.collect(), + start_FWD, + barcode_R1, + params.primer_r1_maxerror, + params.primer_r1_mask_mode, + revpr_FWD, + suffix_FWD + ) + PRESTO_MASKPRIMERS_SCORE_SANSUMI_REV( + PRESTO_MASKPRIMERS_SCORE_SANSUMI_FWD.out.reads, + ch_vprimers.collect(), + start_REV, + barcode_R2, + params.primer_r2_maxerror, + params.primer_r2_mask_mode, + params.primer_revpr, + suffix_REV + ) + } else if (params.cprimer_position == "R2") { + def start_FWD = "${params.vprimer_start}" + def start_REV = "${params.cprimer_start}" + def revpr_FWD = false + + PRESTO_MASKPRIMERS_SCORE_SANSUMI_FWD( + ch_reads, + ch_vprimers.collect(), + start_FWD, + barcode_R1, + params.primer_r1_maxerror, + params.primer_r1_mask_mode, + revpr_FWD, + suffix_FWD + ) + PRESTO_MASKPRIMERS_SCORE_SANSUMI_REV( + PRESTO_MASKPRIMERS_SCORE_SANSUMI_FWD.out.reads, + ch_cprimers.collect(), + start_REV, + barcode_R2, + params.primer_r2_maxerror, + params.primer_r2_mask_mode, + params.primer_revpr, + suffix_REV + ) + } else { + error "Error in determining cprimer position. Please choose R1 or R2." + } + + ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_SCORE_SANSUMI_FWD.out.versions) + + ch_maskprimers_logs = PRESTO_MASKPRIMERS_SCORE_SANSUMI_FWD.out.logs + ch_maskprimers_logs = ch_maskprimers_logs.mix(PRESTO_MASKPRIMERS_SCORE_SANSUMI_REV.out.logs) + + ch_masked_reads = PRESTO_MASKPRIMERS_SCORE_SANSUMI_REV.out.reads + + } // Generate QC stats after reads paired and filtered but before collapsed FASTQC_POSTASSEMBLY_SANS_UMI ( - PRESTO_MASKPRIMERS_POSTASSEMBLY_SANS_UMI.out.reads + ch_masked_reads ) ch_versions = ch_versions.mix(FASTQC_POSTASSEMBLY_SANS_UMI.out.versions) // Annotate primers in C_PRIMER and V_PRIMER field PRESTO_PARSEHEADERS_PRIMERS_SANS_UMI ( - PRESTO_MASKPRIMERS_POSTASSEMBLY_SANS_UMI.out.reads + ch_masked_reads ) ch_versions = ch_versions.mix(PRESTO_PARSEHEADERS_PRIMERS_SANS_UMI.out.versions) @@ -99,7 +208,7 @@ workflow PRESTO_SANS_UMI { fastqc_postassembly_gz = FASTQC_POSTASSEMBLY_SANS_UMI.out.zip presto_assemblepairs_logs = PRESTO_ASSEMBLEPAIRS_SANS_UMI.out.logs.collect() presto_filterseq_logs = PRESTO_FILTERSEQ_POSTASSEMBLY_SANS_UMI.out.logs - presto_maskprimers_logs = PRESTO_MASKPRIMERS_POSTASSEMBLY_SANS_UMI.out.logs.collect() + presto_maskprimers_logs = ch_maskprimers_logs.collect() presto_collapseseq_logs = PRESTO_COLLAPSESEQ_SANS_UMI.out.logs.collect() presto_splitseq_logs = PRESTO_SPLITSEQ_SANS_UMI.out.logs.collect() } diff --git a/subworkflows/local/presto_umi.nf b/subworkflows/local/presto_umi.nf index 17caa68e..3034d236 100644 --- a/subworkflows/local/presto_umi.nf +++ b/subworkflows/local/presto_umi.nf @@ -7,28 +7,37 @@ include { FASTP } from '../../modules/n //PRESTO -include { PRESTO_FILTERSEQ as PRESTO_FILTERSEQ_UMI } from '../../modules/local/presto/presto_filterseq' -include { PRESTO_MASKPRIMERS as PRESTO_MASKPRIMERS_UMI } from '../../modules/local/presto/presto_maskprimers' -include { PRESTO_MASKPRIMERS_ALIGN as PRESTO_ALIGN_PRIMERS } from '../../modules/local/presto/presto_maskprimers_align' -include { PRESTO_MASKPRIMERS_EXTRACT } from '../../modules/local/presto/presto_maskprimers_extract' -include { PRESTO_MASKPRIMERS_ALIGN as PRESTO_ALIGN_CREGION } from '../../modules/local/presto/presto_maskprimers_align' -include { PRESTO_PAIRSEQ as PRESTO_PAIRSEQ_UMI } from '../../modules/local/presto/presto_pairseq' -include { PRESTO_PAIRSEQ as PRESTO_PAIRSEQ_ALIGN } from '../../modules/local/presto/presto_pairseq' -include { PRESTO_CLUSTERSETS as PRESTO_CLUSTERSETS_UMI } from '../../modules/local/presto/presto_clustersets' -include { PRESTO_PARSE_CLUSTER as PRESTO_PARSE_CLUSTER_UMI } from '../../modules/local/presto/presto_parse_cluster' -include { PRESTO_BUILDCONSENSUS as PRESTO_BUILDCONSENSUS_UMI} from '../../modules/local/presto/presto_buildconsensus' -include { PRESTO_BUILDCONSENSUS as PRESTO_BUILDCONSENSUS_ALIGN } from '../../modules/local/presto/presto_buildconsensus' +include { PRESTO_FILTERSEQ as PRESTO_FILTERSEQ_UMI } from '../../modules/local/presto/presto_filterseq' +include { PRESTO_MASKPRIMERS as PRESTO_MASKPRIMERS_UMI } from '../../modules/local/presto/presto_maskprimers' +include { PRESTO_MASKPRIMERS_ALIGN as PRESTO_ALIGN_PRIMERS } from '../../modules/local/presto/presto_maskprimers_align' +include { PRESTO_MASKPRIMERS_EXTRACT as PRESTO_MASKPRIMERS_EXTRACT } from '../../modules/local/presto/presto_maskprimers_extract' +include { PRESTO_MASKPRIMERS_ALIGN as PRESTO_ALIGN_CREGION } from '../../modules/local/presto/presto_maskprimers_align' +include { PRESTO_MASKPRIMERS_ALIGN as PRESTO_MASKPRIMERS_ALIGN_UMI_R1 } from '../../modules/local/presto/presto_maskprimers_align' +include { PRESTO_MASKPRIMERS_ALIGN as PRESTO_MASKPRIMERS_ALIGN_UMI_R2 } from '../../modules/local/presto/presto_maskprimers_align' +include { PRESTO_MASKPRIMERS_SCORE as PRESTO_MASKPRIMERS_SCORE_UMI_R1 } from '../../modules/local/presto/presto_maskprimers_score' +include { PRESTO_MASKPRIMERS_SCORE as PRESTO_MASKPRIMERS_SCORE_UMI_R2 } from '../../modules/local/presto/presto_maskprimers_score' +include { PRESTO_MASKPRIMERS_EXTRACT as PRESTO_MASKPRIMERS_EXTRACT_R1 } from '../../modules/local/presto/presto_maskprimers_extract' +include { PRESTO_MASKPRIMERS_EXTRACT as PRESTO_MASKPRIMERS_EXTRACT_R2 } from '../../modules/local/presto/presto_maskprimers_extract' +include { PRESTO_PAIRSEQ as PRESTO_PAIRSEQ_UMI } from '../../modules/local/presto/presto_pairseq' +include { PRESTO_PAIRSEQ as PRESTO_PAIRSEQ_ALIGN } from '../../modules/local/presto/presto_pairseq' +include { PRESTO_PAIRSEQ as PRESTO_PAIRSEQ_EXTRACT } from '../../modules/local/presto/presto_pairseq' +include { PRESTO_PAIRSEQ as PRESTO_PAIRSEQ_CLUSTERSETS } from '../../modules/local/presto/presto_pairseq' +include { PRESTO_CLUSTERSETS as PRESTO_CLUSTERSETS_UMI } from '../../modules/local/presto/presto_clustersets' +include { PRESTO_PARSE_CLUSTER as PRESTO_PARSE_CLUSTER_UMI } from '../../modules/local/presto/presto_parse_cluster' +include { PRESTO_BUILDCONSENSUS as PRESTO_BUILDCONSENSUS_UMI } from '../../modules/local/presto/presto_buildconsensus' +include { PRESTO_BUILDCONSENSUS as PRESTO_BUILDCONSENSUS_ALIGN_RACE } from '../../modules/local/presto/presto_buildconsensus' +include { PRESTO_BUILDCONSENSUS as PRESTO_BUILDCONSENSUS_EXTRACT } from '../../modules/local/presto/presto_buildconsensus' include { PRESTO_POSTCONSENSUS_PAIRSEQ as PRESTO_POSTCONSENSUS_PAIRSEQ_UMI } from '../../modules/local/presto/presto_postconsensus_pairseq' -include { PRESTO_ASSEMBLEPAIRS as PRESTO_ASSEMBLEPAIRS_UMI } from '../../modules/local/presto/presto_assemblepairs' -include { PRESTO_ASSEMBLEPAIRS_SEQUENTIAL } from '../../modules/local/presto/presto_assemblepairs_sequential' -include { PRESTO_PARSEHEADERS as PRESTO_PARSEHEADERS_COLLAPSE_UMI } from '../../modules/local/presto/presto_parseheaders' -include { PRESTO_PARSEHEADERS as PRESTO_PARSEHEADERS_CREGION } from '../../modules/local/presto/presto_parseheaders' -include { PRESTO_PARSEHEADERS_PRIMERS as PRESTO_PARSEHEADERS_PRIMERS_UMI } from '../../modules/local/presto/presto_parseheaders_primers' +include { PRESTO_ASSEMBLEPAIRS as PRESTO_ASSEMBLEPAIRS_UMI } from '../../modules/local/presto/presto_assemblepairs' +include { PRESTO_ASSEMBLEPAIRS_SEQUENTIAL } from '../../modules/local/presto/presto_assemblepairs_sequential' +include { PRESTO_PARSEHEADERS as PRESTO_PARSEHEADERS_COLLAPSE_UMI } from '../../modules/local/presto/presto_parseheaders' +include { PRESTO_PARSEHEADERS as PRESTO_PARSEHEADERS_CREGION } from '../../modules/local/presto/presto_parseheaders' +include { PRESTO_PARSEHEADERS_PRIMERS as PRESTO_PARSEHEADERS_PRIMERS_UMI } from '../../modules/local/presto/presto_parseheaders_primers' include { PRESTO_PARSEHEADERS_METADATA as PRESTO_PARSEHEADERS_METADATA_UMI } from '../../modules/local/presto/presto_parseheaders_metadata' -include { PRESTO_COLLAPSESEQ as PRESTO_COLLAPSESEQ_UMI } from '../../modules/local/presto/presto_collapseseq' -include { PRESTO_COLLAPSESEQ as PRESTO_COLLAPSESEQ_ALIGN } from '../../modules/local/presto/presto_collapseseq' -include { PRESTO_COLLAPSESEQ as PRESTO_COLLAPSESEQ_CREGION} from '../../modules/local/presto/presto_collapseseq' -include { PRESTO_SPLITSEQ as PRESTO_SPLITSEQ_UMI } from '../../modules/local/presto/presto_splitseq' +include { PRESTO_COLLAPSESEQ as PRESTO_COLLAPSESEQ_UMI } from '../../modules/local/presto/presto_collapseseq' +include { PRESTO_COLLAPSESEQ as PRESTO_COLLAPSESEQ_ALIGN } from '../../modules/local/presto/presto_collapseseq' +include { PRESTO_COLLAPSESEQ as PRESTO_COLLAPSESEQ_CREGION } from '../../modules/local/presto/presto_collapseseq' +include { PRESTO_SPLITSEQ as PRESTO_SPLITSEQ_UMI } from '../../modules/local/presto/presto_splitseq' workflow PRESTO_UMI { @@ -44,6 +53,11 @@ workflow PRESTO_UMI { ch_versions = Channel.empty() + // Validate params + if (params.maskprimers_align_race & params.umi_position == 'R1') {error "The maskprimers align race option is only supported with UMI barcodes in the R2 reads (reads containing V region)."} + if (params.maskprimers_align_race & params.cprimer_position == 'R2') {error "The maskprimers align race option is only supported with Cprimers in the R1 reads (reads containing C region)."} + + // Merge UMI from index file to R1 if provided if (params.index_file) { @@ -101,22 +115,33 @@ workflow PRESTO_UMI { PRESTO_FILTERSEQ_UMI ( GUNZIP_UMI.out.reads ) ch_versions = ch_versions.mix(PRESTO_FILTERSEQ_UMI.out.versions) + // Split reads into R1 and R2 + ch_reads_R1 = PRESTO_FILTERSEQ_UMI.out.reads + .map{ reads -> [reads[0], reads[1]] }.dump(tag: 'ch_reads_R1') + ch_reads_R2 = PRESTO_FILTERSEQ_UMI.out.reads + .map{ reads -> [reads[0], reads[2]] }.dump(tag: 'ch_reads_R2') + // Mask primers - if (params.maskprimers_align) { + if (params.maskprimers_align_race) { - ch_reads_R1 = PRESTO_FILTERSEQ_UMI.out.reads - .map{ reads -> [reads[0], reads[1]] }.dump(tag: 'ch_reads_R1') - ch_reads_R2 = PRESTO_FILTERSEQ_UMI.out.reads - .map{ reads -> [reads[0], reads[2]] }.dump(tag: 'ch_reads_R2') PRESTO_ALIGN_PRIMERS( ch_reads_R1, ch_cprimers.collect(), params.primer_maxlen, + false, params.primer_r1_maxerror, - params.primer_mask_mode + params.primer_r1_mask_mode, + false, + "R1" ) + PRESTO_MASKPRIMERS_EXTRACT( - ch_reads_R2 + ch_reads_R2, + params.umi_length, + params.primer_r2_extract_len, + params.primer_r2_mask_mode, + true, + "R2" ) ch_versions = ch_versions.mix(PRESTO_ALIGN_PRIMERS.out.versions) @@ -130,25 +155,249 @@ workflow PRESTO_UMI { ch_maskprimers_logs = PRESTO_ALIGN_PRIMERS.out.logs ch_maskprimers_logs = ch_maskprimers_logs.mix(PRESTO_MASKPRIMERS_EXTRACT.out.logs) - PRESTO_PAIRSEQ_ALIGN( ch_maskprimers_reads ) + def barcode_position = (params.umi_position == "R1" | params.index_file) ? "R1" : "R2" + + PRESTO_PAIRSEQ_ALIGN( + ch_maskprimers_reads, + barcode_position + ) ch_versions = ch_versions.mix(PRESTO_PAIRSEQ_ALIGN.out.versions) ch_for_clustersets = PRESTO_PAIRSEQ_ALIGN.out.reads ch_pairseq_logs = PRESTO_PAIRSEQ_ALIGN.out.logs - } else { + } else if (params.maskprimers_align) { - PRESTO_MASKPRIMERS_UMI ( - PRESTO_FILTERSEQ_UMI.out.reads, - ch_cprimers.collect(), - ch_vprimers.collect() + if (params.cprimer_position == "R1") { + def barcode_R1 = (params.index_file | params.umi_position == 'R1') ? true : false + + PRESTO_MASKPRIMERS_ALIGN_UMI_R1( + ch_reads_R1, + ch_cprimers.collect(), + params.primer_maxlen, + barcode_R1, + params.primer_r1_maxerror, + params.primer_r1_mask_mode, + false, + "R1" + ) + + def barcode_R2 = (params.umi_position == "R2") ? true : false + + PRESTO_MASKPRIMERS_ALIGN_UMI_R2( + ch_reads_R2, + ch_vprimers.collect(), + params.primer_maxlen, + barcode_R2, + params.primer_r2_maxerror, + params.primer_r2_mask_mode, + params.primer_revpr, + "R2" + ) + } else if (params.cprimer_position == "R2") { + def barcode_R1 = (params.index_file | params.umi_position == 'R1') ? true : false + + PRESTO_MASKPRIMERS_ALIGN_UMI_R1( + ch_reads_R1, + ch_vprimers.collect(), + params.primer_maxlen, + barcode_R1, + params.primer_r1_maxerror, + params.primer_r1_mask_mode, + false, + "R1" + ) + def barcode_R2 = (params.umi_position == "R2") ? true : false + + PRESTO_MASKPRIMERS_ALIGN_UMI_R2( + ch_reads_R2, + ch_cprimers.collect(), + params.primer_maxlen, + barcode_R2, + params.primer_r2_maxerror, + params.primer_r2_mask_mode, + params.primer_revpr, + "R2" + ) + } else { + error "Error in determining cprimer position. Please choose R1 or R2." + } + + ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_ALIGN_UMI_R1.out.versions) + ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_ALIGN_UMI_R2.out.versions) + + // Merge again R1 and R2 by sample ID. + ch_maskprimers_reads_R1 = PRESTO_MASKPRIMERS_ALIGN_UMI_R1.out.reads.map{ reads -> [reads[0].id, reads[0], reads[1]]}.dump(tag: 'ch_maskprimers_reads_R1') + ch_maskprimers_reads_R2 = PRESTO_MASKPRIMERS_ALIGN_UMI_R2.out.reads.map{ reads -> [reads[0].id, reads[0], reads[1]]}.dump(tag: 'ch_maskprimers_reads_R2') + ch_maskprimers_reads = ch_maskprimers_reads_R1.join(ch_maskprimers_reads_R2) + .map{ it -> [it[1], it[2], it[4]] }.dump(tag: 'ch_maskprimers_reads_after_remerge') + + ch_maskprimers_logs = PRESTO_MASKPRIMERS_ALIGN_UMI_R1.out.logs + ch_maskprimers_logs = ch_maskprimers_logs.mix(PRESTO_MASKPRIMERS_ALIGN_UMI_R2.out.logs) + + // Pre-consensus pair + def barcode_position = (params.umi_position == "R1" | params.index_file) ? "R1" : "R2" + + PRESTO_PAIRSEQ_UMI ( + ch_maskprimers_reads, + barcode_position + ) + + ch_versions = ch_versions.mix(PRESTO_PAIRSEQ_UMI.out.versions) + ch_for_clustersets = PRESTO_PAIRSEQ_UMI.out.reads + ch_pairseq_logs = PRESTO_PAIRSEQ_UMI.out.logs + + } else if (params.maskprimers_extract){ + + if (params.cprimer_position == "R1"){ + def barcode_R1 = (params.index_file | params.umi_position == 'R1') ? true : false + def cprimer_start = (params.index_file | params.umi_position == 'R1') ? "${params.umi_length + params.cprimer_start}" : "${params.cprimer_start}" + + PRESTO_MASKPRIMERS_EXTRACT_R1( + ch_reads_R1, + cprimer_start, + params.primer_r1_extract_len, + params.primer_r1_mask_mode, + barcode_R1, + "R1" + ) + + def barcode_R2 = (params.umi_position == "R2") ? true : false + def vprimer_start = (params.umi_position == "R2") ? "${params.umi_length + params.vprimer_start}" : "${params.vprimer_start}" + + PRESTO_MASKPRIMERS_EXTRACT_R2( + ch_reads_R2, + vprimer_start, + params.primer_r2_extract_len, + params.primer_r2_mask_mode, + barcode_R2, + "R2" + ) + } else if (params.cprimer_position == "R2") { + def barcode_R1 = (params.index_file | params.umi_position == 'R1') ? true : false + def vprimer_start = (params.index_file | params.umi_position == 'R1') ? "${params.umi_length + params.vprimer_start}" : "${params.vprimer_start}" + + PRESTO_MASKPRIMERS_EXTRACT_R1( + ch_reads_R1, + vprimer_start, + params.primer_r1_extract_len, + params.primer_r1_mask_mode, + barcode_R1, + "R1" + ) + + def barcode_R2 = (params.umi_position == "R2") ? true : false + def cprimer_start = (params.umi_position == "R2") ? "${params.umi_length + params.cprimer_start}" : "${params.cprimer_start}" + + PRESTO_MASKPRIMERS_EXTRACT_R2( + ch_reads_R2, + cprimer_start, + params.primer_r2_extract_len, + params.primer_r2_mask_mode, + barcode_R2, + "R2" + ) + } else { + error "Error in determining cprimer position. Please choose R1 or R2." + } + + ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_EXTRACT_R1.out.versions) + ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_EXTRACT_R2.out.versions) + + // Merge again R1 and R2 by sample ID. + ch_maskprimers_reads_R1 = PRESTO_MASKPRIMERS_EXTRACT_R1.out.reads.map{ reads -> [reads[0].id, reads[0], reads[1]]}.dump(tag: 'ch_maskprimers_reads_R1') + ch_maskprimers_reads_R2 = PRESTO_MASKPRIMERS_EXTRACT_R2.out.reads.map{ reads -> [reads[0].id, reads[0], reads[1]]}.dump(tag: 'ch_maskprimers_reads_R2') + ch_maskprimers_reads = ch_maskprimers_reads_R1.join(ch_maskprimers_reads_R2) + .map{ it -> [it[1], it[2], it[4]] }.dump(tag: 'ch_maskprimers_reads_after_remerge') + + ch_maskprimers_logs = PRESTO_MASKPRIMERS_EXTRACT_R1.out.logs + ch_maskprimers_logs = ch_maskprimers_logs.mix(PRESTO_MASKPRIMERS_EXTRACT_R2.out.logs) + + def barcode_position = (params.umi_position == "R1" | params.index_file) ? "R1" : "R2" + PRESTO_PAIRSEQ_EXTRACT( + ch_maskprimers_reads, + barcode_position ) - ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_UMI.out.versions) - ch_maskprimers_logs = PRESTO_MASKPRIMERS_UMI.out.logs + ch_versions = ch_versions.mix(PRESTO_PAIRSEQ_EXTRACT.out.versions) + ch_for_clustersets = PRESTO_PAIRSEQ_EXTRACT.out.reads + ch_pairseq_logs = PRESTO_PAIRSEQ_EXTRACT.out.logs + + } else { + + if (params.cprimer_position == "R1") { + def barcode_R1 = (params.index_file | params.umi_position == 'R1') ? true : false + def cprimer_start = (params.index_file | params.umi_position == 'R1') ? "${params.umi_length + params.cprimer_start}" : "${params.cprimer_start}" + PRESTO_MASKPRIMERS_SCORE_UMI_R1( + ch_reads_R1, + ch_cprimers.collect(), + cprimer_start, + barcode_R1, + params.primer_r1_maxerror, + params.primer_r1_mask_mode, + false, + "R1" + ) + + def barcode_R2 = (params.umi_position == "R2") ? true : false + def vprimer_start = (params.umi_position == "R2") ? "${params.umi_length + params.vprimer_start}" : "${params.vprimer_start}" + PRESTO_MASKPRIMERS_SCORE_UMI_R2( + ch_reads_R2, + ch_vprimers.collect(), + vprimer_start, + barcode_R2, + params.primer_r2_maxerror, + params.primer_r2_mask_mode, + params.primer_revpr, + "R2" + ) + } else if (params.cprimer_position == "R2") { + def barcode_R1 = (params.index_file | params.umi_position == 'R1') ? true : false + def vprimer_start = (params.index_file | params.umi_position == 'R1') ? "${params.umi_length + params.vprimer_start}" : "${params.vprimer_start}" + PRESTO_MASKPRIMERS_SCORE_UMI_R1( + ch_reads_R1, + ch_vprimers.collect(), + vprimer_start, + barcode_R1, + params.primer_r1_maxerror, + params.primer_r1_mask_mode, + revpr_R1, + "R1" + ) + def barcode_R2 = (params.umi_position == "R2") ? true : false + def cprimer_start = (params.umi_position == "R2") ? "${params.umi_length + params.cprimer_start}" : "${params.cprimer_start}" + + PRESTO_MASKPRIMERS_SCORE_UMI_R2( + ch_reads_R2, + ch_cprimers.collect(), + cprimer_start, + barcode_R2, + params.primer_r2_maxerror, + params.primer_r2_mask_mode, + params.primer_revpr, + "R2" + ) + } else { + error "Error in determining cprimer position. Please choose R1 or R2." + } + + ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_SCORE_UMI_R1.out.versions) + ch_versions = ch_versions.mix(PRESTO_MASKPRIMERS_SCORE_UMI_R2.out.versions) + + // Merge again R1 and R2 by sample ID. + ch_maskprimers_reads_R1 = PRESTO_MASKPRIMERS_SCORE_UMI_R1.out.reads.map{ reads -> [reads[0].id, reads[0], reads[1]]}.dump(tag: 'ch_maskprimers_reads_R1') + ch_maskprimers_reads_R2 = PRESTO_MASKPRIMERS_SCORE_UMI_R2.out.reads.map{ reads -> [reads[0].id, reads[0], reads[1]]}.dump(tag: 'ch_maskprimers_reads_R2') + ch_maskprimers_reads = ch_maskprimers_reads_R1.join(ch_maskprimers_reads_R2) + .map{ it -> [it[1], it[2], it[4]] }.dump(tag: 'ch_maskprimers_reads_after_remerge') + + ch_maskprimers_logs = PRESTO_MASKPRIMERS_SCORE_UMI_R1.out.logs + ch_maskprimers_logs = ch_maskprimers_logs.mix(PRESTO_MASKPRIMERS_SCORE_UMI_R2.out.logs) // Pre-consensus pair + def barcode_position = (params.umi_position == "R1" | params.index_file) ? "R1" : "R2" PRESTO_PAIRSEQ_UMI ( - PRESTO_MASKPRIMERS_UMI.out.reads + ch_maskprimers_reads, + barcode_position ) + ch_versions = ch_versions.mix(PRESTO_PAIRSEQ_UMI.out.versions) ch_for_clustersets = PRESTO_PAIRSEQ_UMI.out.reads ch_pairseq_logs = PRESTO_PAIRSEQ_UMI.out.logs @@ -168,23 +417,41 @@ workflow PRESTO_UMI { PRESTO_CLUSTERSETS_UMI.out.reads ) ch_versions = ch_versions.mix(PRESTO_PARSE_CLUSTER_UMI.out.versions) - ch_for_buildconsensus = PRESTO_PARSE_CLUSTER_UMI.out.reads ch_clustersets_logs = PRESTO_CLUSTERSETS_UMI.out.logs.collect() + // Combining the split cluster+UMI combination + PRESTO_PAIRSEQ_CLUSTERSETS ( + PRESTO_PARSE_CLUSTER_UMI.out.reads, + "clustersets" + ) + ch_versions = ch_versions.mix(PRESTO_PAIRSEQ_CLUSTERSETS.out.versions) + + ch_for_buildconsensus = PRESTO_PAIRSEQ_CLUSTERSETS.out.reads + } else { ch_for_buildconsensus = ch_for_clustersets ch_clustersets_logs = Channel.empty() } // Build consensus of sequences with same UMI barcode - if (params.maskprimers_align) { - PRESTO_BUILDCONSENSUS_ALIGN ( + if (params.maskprimers_align_race) { + // Only consider C_PRIMER frequency when building consensus + PRESTO_BUILDCONSENSUS_ALIGN_RACE ( + ch_for_buildconsensus + ) + ch_versions = ch_versions.mix(PRESTO_BUILDCONSENSUS_ALIGN_RACE.out.versions) + ch_postconsensus = PRESTO_BUILDCONSENSUS_ALIGN_RACE.out.reads + ch_buildconsensus_logs = PRESTO_BUILDCONSENSUS_ALIGN_RACE.out.logs + } else if (params.maskprimers_extract) { + // Do not consider primers when building consensus + PRESTO_BUILDCONSENSUS_EXTRACT( ch_for_buildconsensus ) - ch_versions = ch_versions.mix(PRESTO_BUILDCONSENSUS_ALIGN.out.versions) - ch_postconsensus = PRESTO_BUILDCONSENSUS_ALIGN.out.reads - ch_buildconsensus_logs = PRESTO_BUILDCONSENSUS_ALIGN.out.logs + ch_versions = ch_versions.mix(PRESTO_BUILDCONSENSUS_EXTRACT.out.versions) + ch_postconsensus = PRESTO_BUILDCONSENSUS_EXTRACT.out.reads + ch_buildconsensus_logs = PRESTO_BUILDCONSENSUS_EXTRACT.out.logs } else { + // Consider both primers frequency when building consensus PRESTO_BUILDCONSENSUS_UMI ( ch_for_buildconsensus ) @@ -224,8 +491,11 @@ workflow PRESTO_UMI { ch_assemblepairs_reads, ch_internal_cregion.collect(), params.cregion_maxlen, + false, params.cregion_maxerror, - params.cregion_mask_mode + params.cregion_mask_mode, + false, + "Cregion" ) ch_parseheaders_reads = PRESTO_ALIGN_CREGION.out.reads ch_versions = ch_versions.mix(PRESTO_ALIGN_CREGION.out.versions) @@ -246,7 +516,8 @@ workflow PRESTO_UMI { ch_versions = ch_versions.mix(PRESTO_PARSEHEADERS_COLLAPSE_UMI.out.versions) // Annotate primer fields and collapse duplicates - if (params.maskprimers_align) { + if (params.maskprimers_align_race) { + // Rename primer field to CREGION PRESTO_PARSEHEADERS_CREGION ( PRESTO_PARSEHEADERS_COLLAPSE_UMI.out.reads @@ -261,7 +532,18 @@ workflow PRESTO_UMI { ch_collapsed = PRESTO_COLLAPSESEQ_ALIGN.out.reads ch_collapse_logs = PRESTO_COLLAPSESEQ_ALIGN.out.logs + } else if (params.maskprimers_extract) { + + // Do not annotate primers + PRESTO_COLLAPSESEQ_UMI ( + PRESTO_PARSEHEADERS_COLLAPSE_UMI.out.reads + ) + ch_versions = ch_versions.mix(PRESTO_COLLAPSESEQ_UMI.out.versions) + ch_collapsed = PRESTO_COLLAPSESEQ_UMI.out.reads + ch_collapse_logs = PRESTO_COLLAPSESEQ_UMI.out.logs + } else { + // Annotate primers in C_PRIMER and V_PRIMER field PRESTO_PARSEHEADERS_PRIMERS_UMI ( PRESTO_PARSEHEADERS_COLLAPSE_UMI.out.reads diff --git a/subworkflows/local/repertoire_analysis_reporting.nf b/subworkflows/local/repertoire_analysis_reporting.nf index 2a796751..905c2d85 100644 --- a/subworkflows/local/repertoire_analysis_reporting.nf +++ b/subworkflows/local/repertoire_analysis_reporting.nf @@ -30,7 +30,7 @@ workflow REPERTOIRE_ANALYSIS_REPORTING { main: ch_versions = Channel.empty() - if (params.mode == "fastq" && params.library_generation_method != "sc_10x_genomics") { + if (params.mode == "fastq" && params.library_generation_method != "sc_10x_genomics" && params.library_generation_method != "trust4" ) { PARSE_LOGS( ch_presto_filterseq_logs, ch_presto_maskprimers_logs, diff --git a/subworkflows/local/rnaseq_input.nf b/subworkflows/local/rnaseq_input.nf new file mode 100644 index 00000000..9c42fc2e --- /dev/null +++ b/subworkflows/local/rnaseq_input.nf @@ -0,0 +1,136 @@ +include { PREPARE_TRUST4_REFERENCE } from '../../modules/local/prepare_trust4_reference' +include { TRUST4 } from '../../modules/nf-core/trust4/main' +include { FASTQ_INPUT_CHECK } from '../../subworkflows/local/fastq_input_check' +include { CHANGEO_PARSEDB_SELECT_LOCUS } from '../../modules/local/changeo/changeo_parsedb_select_locus' +include { CHANGEO_CONVERTDB_FASTA as CHANGEO_CONVERTDB_FASTA_FROM_AIRR } from '../../modules/local/changeo/changeo_convertdb_fasta' +include { FASTP } from '../../modules/nf-core/fastp/main' +include { RENAME_FASTQ as RENAME_FASTQ_TRUST4 } from '../../modules/local/rename_fastq' + + + +workflow RNASEQ_INPUT { + + take: + ch_input + ch_igblast_reference + + main: + + ch_versions = Channel.empty() + ch_logs = Channel.empty() + + // + // read in samplesheet, validate and stage input fies + // + FASTQ_INPUT_CHECK( + ch_input + ) + ch_versions = ch_versions.mix(FASTQ_INPUT_CHECK.out.versions) + + ch_reads = FASTQ_INPUT_CHECK.out.reads + + + // validate library generation method parameters + if (params.vprimers) { + error "The TRUST4 library generation method does not require V-region primers, please provide a reference file instead or select another library method option." + } else if (params.race_linker) { + error "The TRUST4 10X genomics library generation method does not require the --race_linker parameter, please provide a reference file instead or select another library method option." + } + if (params.cprimers) { + error "The TRUST4 library generation method does not require C-region primers, please provide a reference file instead or select another library method option." + } + if (params.umi_length > 0) { + error "TRUST4 library generation method does not require to set the UMI length, please provide a reference file instead or select another library method option." + } + if (params.reference_10x) { + error "The TRUST4 library generation method does not require this reference, please provide a compliant reference file instead or select another library method option." + } + + // Fastp + save_merged = false + FASTP ( + ch_reads, + [], + [], + save_merged + ) + ch_versions = ch_versions.mix(FASTP.out.versions) + + ch_rename_fastq = FASTP.out.reads.map { meta, reads -> [meta, reads[0], reads[1]] } + + // rename fastp output + RENAME_FASTQ_TRUST4( + ch_rename_fastq + ) + + ch_reads_fastp_filtered = RENAME_FASTQ_TRUST4.out.reads.dump(tag: "fastp_filtered") + + PREPARE_TRUST4_REFERENCE( + ch_reads_fastp_filtered.first(), + ch_igblast_reference + ) + + + // create trust4 input + ch_reads_trust4 = ch_reads_fastp_filtered.map{ meta, read_1, read_2 -> [ meta, [], [read_1, read_2] ] } + + PREPARE_TRUST4_REFERENCE.out.trust4_reference.dump(tag: "trust4_reference") + + ch_reads_trust4.dump(tag: "trust4_input") + + // create barcode and umi channels for nf-core trust4 module + barcode_channel = ch_reads_fastp_filtered.map { meta, read_1, read_2 -> [meta, params.cell_barcode_read] } + umi_channel = ch_reads_fastp_filtered.map { meta, read_1, read_2 -> [meta, params.umi_read] } + ch_reference_trust4 = PREPARE_TRUST4_REFERENCE.out.trust4_reference.map { reference -> [[id: "igblast_reference"], reference] } + + TRUST4( + ch_reads_trust4, + ch_reference_trust4.collect(), + Channel.of([[], []]).collect(), + barcode_channel, + umi_channel + ) + + ch_trust4_out = TRUST4.out.outs + + // check whether input is sc or bulk and extract respective airr file for downstream processing + ch_trust4_out + .branch { + meta, out_files -> + bulk : meta["single_cell"] == "false" + return [ meta, out_files.find { it.endsWith("${meta.id}_airr.tsv") } ] + sc : meta["single_cell"] == "true" + return [ meta, out_files.find { it.endsWith("${meta.id}_barcode_airr.tsv") } ] + } + .set { ch_trust4_airr_file } + + + // create channel with airr file + ch_trust4_airr_file.bulk.mix ( ch_trust4_airr_file.sc ).set { ch_trust4_airr } + + // select only provided locus + CHANGEO_PARSEDB_SELECT_LOCUS(ch_trust4_airr) + + + // convert airr tsv to fasta + CHANGEO_CONVERTDB_FASTA_FROM_AIRR( + CHANGEO_PARSEDB_SELECT_LOCUS.out.tab + ) + + ch_fasta = CHANGEO_CONVERTDB_FASTA_FROM_AIRR.out.fasta + + + emit: + versions = ch_versions + // fastp + fastp_reads_json = FASTP.out.json.collect{ meta,json -> json } + fastp_reads_html = FASTP.out.html.collect{ meta,html -> html } + // complete trust4 output + outs = ch_trust4_out + // trust4 airr file + airr = ch_trust4_airr + // trust4 output converted to FASTA format + fasta = ch_fasta + samplesheet = FASTQ_INPUT_CHECK.out.samplesheet + +} diff --git a/subworkflows/local/sequence_assembly.nf b/subworkflows/local/sequence_assembly.nf index d001b124..f7248463 100644 --- a/subworkflows/local/sequence_assembly.nf +++ b/subworkflows/local/sequence_assembly.nf @@ -67,18 +67,23 @@ workflow SEQUENCE_ASSEMBLY { // Validate library generation method parameter if (params.library_generation_method == 'specific_pcr_umi'){ - if (params.vprimers) { - ch_vprimers_fasta = Channel.fromPath(params.vprimers, checkIfExists: true) + if (!params.maskprimers_extract){ + if (params.vprimers) { + ch_vprimers_fasta = Channel.fromPath(params.vprimers, checkIfExists: true) + } else { + error "Please provide a V-region primers fasta file with the '--vprimers' option when using the 'specific_pcr_umi' library generation method." + } + if (params.cprimers) { + ch_cprimers_fasta = Channel.fromPath(params.cprimers, checkIfExists: true) + } else { + error "Please provide a C-region primers fasta file with the '--cprimers' option when using the 'specific_pcr_umi' library generation method." + } + if (params.race_linker) { + error "Please do not set '--race_linker' when using the 'specific_pcr_umi' library generation method." + } } else { - error "Please provide a V-region primers fasta file with the '--vprimers' option when using the 'specific_pcr_umi' library generation method." - } - if (params.cprimers) { - ch_cprimers_fasta = Channel.fromPath(params.cprimers, checkIfExists: true) - } else { - error "Please provide a C-region primers fasta file with the '--cprimers' option when using the 'specific_pcr_umi' library generation method." - } - if (params.race_linker) { - error "Please do not set '--race_linker' when using the 'specific_pcr_umi' library generation method." + ch_vprimers_fasta = Channel.of([]) + ch_cprimers_fasta = Channel.of([]) } if (params.umi_length < 2) { error "The 'specific_pcr_umi' library generation method requires setting the '--umi_length' to a value greater than 1." @@ -115,7 +120,7 @@ workflow SEQUENCE_ASSEMBLY { error "The oligo-dT 5'-RACE UMI library generation method does not accept V-region primers, please provide a linker with '--race_linker' instead or select another library method option." } else if (params.race_linker) { ch_vprimers_fasta = Channel.fromPath(params.race_linker, checkIfExists: true) - } else if (params.maskprimers_align) { + } else if (params.maskprimers_align_race) { ch_vprimers_fasta = Channel.of([]) } else { error "The oligo-dT 5'-RACE UMI library generation method requires a linker or Template Switch Oligo sequence, please provide it with the option '--race_linker'." @@ -138,7 +143,7 @@ workflow SEQUENCE_ASSEMBLY { error "The oligo-dT 5'-RACE library generation method does not accept V-region primers, please provide a linker with '--race_linker' instead or select another library method option." } else if (params.race_linker) { ch_vprimers_fasta = Channel.fromPath(params.race_linker, checkIfExists: true) - } else if (params.maskprimers_align) { + } else if (params.maskprimers_align_race) { ch_vprimers_fasta = Channel.of([]) } else { error "The oligo-dT 5'-RACE library generation method requires a linker or Template Switch Oligo sequence, please provide it with the option '--race_linker'." @@ -164,8 +169,6 @@ workflow SEQUENCE_ASSEMBLY { if (params.index_file & params.umi_position == 'R2') {error "Please do not set `--umi_position` option if index file with UMIs is provided."} if (params.umi_length < 0) {error "Please provide the UMI barcode length in the option `--umi_length`. To run without UMIs, set umi_length to 0."} if (!params.index_file & params.umi_start != 0) {error "Setting a UMI start position is only allowed when providing the UMIs in a separate index read file. If so, please provide the `--index_file` flag as well."} - if (params.maskprimers_align & params.umi_position == 'R1') {error "The maskprimers align option is only supported with UMI barcodes in the R2 reads (reads containing V region)."} - if (params.maskprimers_align & params.cprimer_position == 'R2') {error "The maskprimers align option is only supported with Cprimers in the R1 reads (reads containing C region)."} // // SUBWORKFLOW: Read in samplesheet, validate and stage input files diff --git a/subworkflows/local/utils_nfcore_airrflow_pipeline/main.nf b/subworkflows/local/utils_nfcore_airrflow_pipeline/main.nf index ebbb9e90..d3760821 100644 --- a/subworkflows/local/utils_nfcore_airrflow_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_airrflow_pipeline/main.nf @@ -8,29 +8,25 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { UTILS_NFVALIDATION_PLUGIN } from '../../nf-core/utils_nfvalidation_plugin' -include { paramsSummaryMap } from 'plugin/nf-validation' -include { fromSamplesheet } from 'plugin/nf-validation' -include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' +include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' +include { paramsSummaryMap } from 'plugin/nf-schema' +include { samplesheetToList } from 'plugin/nf-schema' include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' -include { dashedLine } from '../../nf-core/utils_nfcore_pipeline' -include { nfCoreLogo } from '../../nf-core/utils_nfcore_pipeline' include { imNotification } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' -include { workflowCitation } from '../../nf-core/utils_nfcore_pipeline' +include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW TO INITIALISE PIPELINE -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow PIPELINE_INITIALISATION { take: version // boolean: Display version and exit - help // boolean: Display help text validate_params // boolean: Boolean whether to validate parameters against the schema at runtime monochrome_logs // boolean: Do not use coloured log outputs nextflow_cli_args // array: List of positional nextflow CLI args @@ -54,16 +50,10 @@ workflow PIPELINE_INITIALISATION { // // Validate parameters and generate parameter summary to stdout // - pre_help_text = nfCoreLogo(monochrome_logs) - post_help_text = '\n' + workflowCitation() + '\n' + dashedLine(monochrome_logs) - def String workflow_command = "nextflow run ${workflow.manifest.name} -profile --input samplesheet.csv --outdir " - UTILS_NFVALIDATION_PLUGIN ( - help, - workflow_command, - pre_help_text, - post_help_text, + UTILS_NFSCHEMA_PLUGIN ( + workflow, validate_params, - "nextflow_schema.json" + null ) // @@ -72,6 +62,7 @@ workflow PIPELINE_INITIALISATION { UTILS_NFCORE_PIPELINE ( nextflow_cli_args ) + // // Custom validation for pipeline parameters // @@ -80,7 +71,9 @@ workflow PIPELINE_INITIALISATION { // // Create channel from input file provided through params.input // - ch_samplesheet = Channel.fromPath(input, checkIfExists: true) + Channel.fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) + + Channel.fromPath(input).set{ch_samplesheet} emit: samplesheet = ch_samplesheet @@ -88,9 +81,9 @@ workflow PIPELINE_INITIALISATION { } /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW FOR PIPELINE COMPLETION -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow PIPELINE_COMPLETION { @@ -105,7 +98,6 @@ workflow PIPELINE_COMPLETION { multiqc_report // string: Path to MultiQC report main: - summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") // @@ -113,11 +105,18 @@ workflow PIPELINE_COMPLETION { // workflow.onComplete { if (email || email_on_fail) { - completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs, multiqc_report.toList()) + completionEmail( + summary_params, + email, + email_on_fail, + plaintext_email, + outdir, + monochrome_logs, + multiqc_report.toList() + ) } completionSummary(monochrome_logs) - if (hook_url) { imNotification(summary_params, hook_url) } @@ -129,9 +128,9 @@ workflow PIPELINE_COMPLETION { } /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FUNCTIONS -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // // Check and validate pipeline parameters @@ -147,7 +146,7 @@ def validateInputSamplesheet(input) { def (metas, fastqs) = input[1..2] // Check that multiple runs of the same sample are of the same datatype i.e. single-end / paired-end - def endedness_ok = metas.collect{ it.single_end }.unique().size == 1 + def endedness_ok = metas.collect{ meta -> meta.single_end }.unique().size == 1 if (!endedness_ok) { error("Please check input samplesheet -> Multiple runs of a sample must be of the same datatype i.e. single-end or paired-end: ${metas[0].id}") } @@ -179,7 +178,6 @@ def genomeExistsError() { error(error_string) } } - // // Generate methods description for MultiQC // @@ -239,8 +237,10 @@ def methodsDescriptionText(mqc_methods_yaml) { // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers // Removing ` ` since the manifest.doi is a string and not a proper list def temp_doi_ref = "" - String[] manifest_doi = meta.manifest_map.doi.tokenize(",") - for (String doi_ref: manifest_doi) temp_doi_ref += "(doi: ${doi_ref.replace("https://doi.org/", "").replace(" ", "")}), " + def manifest_doi = meta.manifest_map.doi.tokenize(",") + manifest_doi.each { doi_ref -> + temp_doi_ref += "(doi: ${doi_ref.replace("https://doi.org/", "").replace(" ", "")}), " + } meta["doi_text"] = temp_doi_ref.substring(0, temp_doi_ref.length() - 2) } else meta["doi_text"] = "" meta["nodoi_text"] = meta.manifest_map.doi ? "" : "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " @@ -261,3 +261,4 @@ def methodsDescriptionText(mqc_methods_yaml) { return description_html.toString() } + diff --git a/subworkflows/local/vdj_annotation.nf b/subworkflows/local/vdj_annotation.nf index 692320ec..d15920a1 100644 --- a/subworkflows/local/vdj_annotation.nf +++ b/subworkflows/local/vdj_annotation.nf @@ -38,19 +38,24 @@ workflow VDJ_ANNOTATION { ch_assigned_tab = CHANGEO_MAKEDB.out.tab ch_assignment_logs = CHANGEO_MAKEDB.out.logs - // Apply quality filters: - // - locus should match v_call chain - // - seq alignment min length informative positions 200 - // - max 10% N nucleotides - FILTER_QUALITY( - ch_assigned_tab - ) - ch_logs = ch_logs.mix(FILTER_QUALITY.out.logs) - ch_versions = ch_versions.mix(FILTER_QUALITY.out.versions) + if (!params.skip_alignment_filter){ + // Apply quality filters: + // - locus should match v_call chain + // - seq alignment min length informative positions 200 + // - max 10% N nucleotides + FILTER_QUALITY( + ch_assigned_tab + ) + ch_for_parsedb_split = FILTER_QUALITY.out.tab + ch_logs = ch_logs.mix(FILTER_QUALITY.out.logs) + ch_versions = ch_versions.mix(FILTER_QUALITY.out.versions) + } else { + ch_for_parsedb_split = ch_assigned_tab + } if (params.productive_only) { CHANGEO_PARSEDB_SPLIT ( - FILTER_QUALITY.out.tab + ch_for_parsedb_split ) ch_logs = ch_logs.mix(CHANGEO_PARSEDB_SPLIT.out.logs) ch_versions = ch_versions.mix(CHANGEO_PARSEDB_SPLIT.out.versions) diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf index ac31f28f..0fcbf7b3 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf @@ -2,18 +2,13 @@ // Subworkflow with functionality that may be useful for any Nextflow pipeline // -import org.yaml.snakeyaml.Yaml -import groovy.json.JsonOutput -import nextflow.extension.FilesEx - /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW DEFINITION -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow UTILS_NEXTFLOW_PIPELINE { - take: print_version // boolean: print version dump_parameters // boolean: dump parameters @@ -26,7 +21,7 @@ workflow UTILS_NEXTFLOW_PIPELINE { // Print workflow version and exit on --version // if (print_version) { - log.info "${workflow.manifest.name} ${getWorkflowVersion()}" + log.info("${workflow.manifest.name} ${getWorkflowVersion()}") System.exit(0) } @@ -49,16 +44,16 @@ workflow UTILS_NEXTFLOW_PIPELINE { } /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FUNCTIONS -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // // Generate version string // def getWorkflowVersion() { - String version_string = "" + def version_string = "" as String if (workflow.manifest.version) { def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' version_string += "${prefix_v}${workflow.manifest.version}" @@ -76,13 +71,13 @@ def getWorkflowVersion() { // Dump pipeline parameters to a JSON file // def dumpParametersToJSON(outdir) { - def timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') - def filename = "params_${timestamp}.json" - def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") - def jsonStr = JsonOutput.toJson(params) - temp_pf.text = JsonOutput.prettyPrint(jsonStr) + def timestamp = new java.util.Date().format('yyyy-MM-dd_HH-mm-ss') + def filename = "params_${timestamp}.json" + def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") + def jsonStr = groovy.json.JsonOutput.toJson(params) + temp_pf.text = groovy.json.JsonOutput.prettyPrint(jsonStr) - FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") + nextflow.extension.FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") temp_pf.delete() } @@ -90,37 +85,40 @@ def dumpParametersToJSON(outdir) { // When running with -profile conda, warn if channels have not been set-up appropriately // def checkCondaChannels() { - Yaml parser = new Yaml() + def parser = new org.yaml.snakeyaml.Yaml() def channels = [] try { def config = parser.load("conda config --show channels".execute().text) channels = config.channels - } catch(NullPointerException | IOException e) { - log.warn "Could not verify conda channel configuration." - return + } + catch (NullPointerException e) { + log.warn("Could not verify conda channel configuration.") + return null + } + catch (IOException e) { + log.warn("Could not verify conda channel configuration.") + return null } // Check that all channels are present // This channel list is ordered by required channel priority. - def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def required_channels_in_order = ['conda-forge', 'bioconda'] def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean // Check that they are in the right order - def channel_priority_violation = false - def n = required_channels_in_order.size() - for (int i = 0; i < n - 1; i++) { - channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) - } + def channel_priority_violation = required_channels_in_order != channels.findAll { ch -> ch in required_channels_in_order } if (channels_missing | channel_priority_violation) { - log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " There is a problem with your Conda configuration!\n\n" + - " You will need to set-up the conda-forge and bioconda channels correctly.\n" + - " Please refer to https://bioconda.github.io/\n" + - " The observed channel order is \n" + - " ${channels}\n" + - " but the following channel order is required:\n" + - " ${required_channels_in_order}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + log.warn """\ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + There is a problem with your Conda configuration! + You will need to set-up the conda-forge and bioconda channels correctly. + Please refer to https://bioconda.github.io/ + The observed channel order is + ${channels} + but the following channel order is required: + ${required_channels_in_order} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + """.stripIndent(true) } } diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config b/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config index d0a926bf..a09572e5 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config @@ -3,7 +3,7 @@ manifest { author = """nf-core""" homePage = 'https://127.0.0.1' description = """Dummy pipeline""" - nextflowVersion = '!>=23.04.0' + nextflowVersion = '!>=23.04.0' version = '9.9.9' doi = 'https://doi.org/10.5281/zenodo.5070524' } diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index 14558c39..5cb7bafe 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -2,17 +2,13 @@ // Subworkflow with utility functions specific to the nf-core pipeline template // -import org.yaml.snakeyaml.Yaml -import nextflow.extension.FilesEx - /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW DEFINITION -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow UTILS_NFCORE_PIPELINE { - take: nextflow_cli_args @@ -25,23 +21,20 @@ workflow UTILS_NFCORE_PIPELINE { } /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FUNCTIONS -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // // Warn if a -profile or Nextflow config has not been provided to run the pipeline // def checkConfigProvided() { - valid_config = true + def valid_config = true as Boolean if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { - log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + - "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + - " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + - " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + - " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + - "Please refer to the quick start section and usage docs for the pipeline.\n " + log.warn( + "[${workflow.manifest.name}] You are attempting to run the pipeline without any custom configuration!\n\n" + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + "Please refer to the quick start section and usage docs for the pipeline.\n " + ) valid_config = false } return valid_config @@ -52,12 +45,14 @@ def checkConfigProvided() { // def checkProfileProvided(nextflow_cli_args) { if (workflow.profile.endsWith(',')) { - error "The `-profile` option cannot end with a trailing comma, please remove it and re-run the pipeline!\n" + - "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + error( + "The `-profile` option cannot end with a trailing comma, please remove it and re-run the pipeline!\n" + "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + ) } if (nextflow_cli_args[0]) { - log.warn "nf-core pipelines do not accept positional arguments. The positional argument `${nextflow_cli_args[0]}` has been detected.\n" + - "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + log.warn( + "nf-core pipelines do not accept positional arguments. The positional argument `${nextflow_cli_args[0]}` has been detected.\n" + "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + ) } } @@ -66,25 +61,21 @@ def checkProfileProvided(nextflow_cli_args) { // def workflowCitation() { def temp_doi_ref = "" - String[] manifest_doi = workflow.manifest.doi.tokenize(",") - // Using a loop to handle multiple DOIs + def manifest_doi = workflow.manifest.doi.tokenize(",") + // Handling multiple DOIs // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers // Removing ` ` since the manifest.doi is a string and not a proper list - for (String doi_ref: manifest_doi) temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" - return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + - "* The pipeline\n" + - temp_doi_ref + "\n" + - "* The nf-core framework\n" + - " https://doi.org/10.1038/s41587-020-0439-x\n\n" + - "* Software dependencies\n" + - " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" + manifest_doi.each { doi_ref -> + temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" + } + return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + temp_doi_ref + "\n" + "* The nf-core framework\n" + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + "* Software dependencies\n" + " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" } // // Generate workflow version string // def getWorkflowVersion() { - String version_string = "" + def version_string = "" as String if (workflow.manifest.version) { def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' version_string += "${prefix_v}${workflow.manifest.version}" @@ -102,8 +93,8 @@ def getWorkflowVersion() { // Get software versions for pipeline // def processVersionsFromYAML(yaml_file) { - Yaml yaml = new Yaml() - versions = yaml.load(yaml_file).collectEntries { k, v -> [ k.tokenize(':')[-1], v ] } + def yaml = new org.yaml.snakeyaml.Yaml() + def versions = yaml.load(yaml_file).collectEntries { k, v -> [k.tokenize(':')[-1], v] } return yaml.dumpAsMap(versions).trim() } @@ -113,8 +104,8 @@ def processVersionsFromYAML(yaml_file) { def workflowVersionToYAML() { return """ Workflow: - $workflow.manifest.name: ${getWorkflowVersion()} - Nextflow: $workflow.nextflow.version + ${workflow.manifest.name}: ${getWorkflowVersion()} + Nextflow: ${workflow.nextflow.version} """.stripIndent().trim() } @@ -122,11 +113,7 @@ def workflowVersionToYAML() { // Get channel of software versions used in pipeline in YAML format // def softwareVersionsToYAML(ch_versions) { - return ch_versions - .unique() - .map { processVersionsFromYAML(it) } - .unique() - .mix(Channel.of(workflowVersionToYAML())) + return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(Channel.of(workflowVersionToYAML())) } // @@ -134,25 +121,31 @@ def softwareVersionsToYAML(ch_versions) { // def paramsSummaryMultiqc(summary_params) { def summary_section = '' - for (group in summary_params.keySet()) { - def group_params = summary_params.get(group) // This gets the parameters of that particular group - if (group_params) { - summary_section += "

    $group

    \n" - summary_section += "
    \n" - for (param in group_params.keySet()) { - summary_section += "
    $param
    ${group_params.get(param) ?: 'N/A'}
    \n" + summary_params + .keySet() + .each { group -> + def group_params = summary_params.get(group) + // This gets the parameters of that particular group + if (group_params) { + summary_section += "

    ${group}

    \n" + summary_section += "
    \n" + group_params + .keySet() + .sort() + .each { param -> + summary_section += "
    ${param}
    ${group_params.get(param) ?: 'N/A'}
    \n" + } + summary_section += "
    \n" } - summary_section += "
    \n" } - } - String yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" - yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" - yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" - yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" - yaml_file_text += "plot_type: 'html'\n" - yaml_file_text += "data: |\n" - yaml_file_text += "${summary_section}" + def yaml_file_text = "id: '${workflow.manifest.name.replace('/', '-')}-summary'\n" as String + yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" + yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" + yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" + yaml_file_text += "plot_type: 'html'\n" + yaml_file_text += "data: |\n" + yaml_file_text += "${summary_section}" return yaml_file_text } @@ -161,7 +154,7 @@ def paramsSummaryMultiqc(summary_params) { // nf-core logo // def nfCoreLogo(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map String.format( """\n ${dashedLine(monochrome_logs)} @@ -180,7 +173,7 @@ def nfCoreLogo(monochrome_logs=true) { // Return dashed line // def dashedLine(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map return "-${colors.dim}----------------------------------------------------${colors.reset}-" } @@ -188,7 +181,7 @@ def dashedLine(monochrome_logs=true) { // ANSII colours used for terminal logging // def logColours(monochrome_logs=true) { - Map colorcodes = [:] + def colorcodes = [:] as Map // Reset / Meta colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" @@ -200,54 +193,54 @@ def logColours(monochrome_logs=true) { colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" // Regular Colors - colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" - colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" - colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" - colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" - colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" - colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" - colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" - colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" + colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" + colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" + colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" + colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" + colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" + colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" + colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" + colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" // Bold - colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" - colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" - colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" - colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" - colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" - colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" - colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" - colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" + colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" + colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" + colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" + colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" + colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" + colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" + colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" + colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" // Underline - colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" - colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" - colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" - colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" - colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" - colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" - colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" - colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" + colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" + colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" + colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" + colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" + colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" + colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" + colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" + colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" // High Intensity - colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" - colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" - colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" - colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" - colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" - colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" - colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" - colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" + colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" + colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" + colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" + colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" + colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" + colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" + colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" + colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" // Bold High Intensity - colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" - colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" - colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" - colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" - colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" - colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" - colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" - colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" + colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" + colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" + colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" + colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" + colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" + colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" + colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" + colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" return colorcodes } @@ -262,14 +255,15 @@ def attachMultiqcReport(multiqc_report) { mqc_report = multiqc_report.getVal() if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { if (mqc_report.size() > 1) { - log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" + log.warn("[${workflow.manifest.name}] Found multiple reports from process 'MULTIQC', will use only one") } mqc_report = mqc_report[0] } } - } catch (all) { + } + catch (Exception all) { if (multiqc_report) { - log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" + log.warn("[${workflow.manifest.name}] Could not attach MultiQC report to summary email") } } return mqc_report @@ -281,26 +275,35 @@ def attachMultiqcReport(multiqc_report) { def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs=true, multiqc_report=null) { // Set up the e-mail variables - def subject = "[$workflow.manifest.name] Successful: $workflow.runName" + def subject = "[${workflow.manifest.name}] Successful: ${workflow.runName}" if (!workflow.success) { - subject = "[$workflow.manifest.name] FAILED: $workflow.runName" + subject = "[${workflow.manifest.name}] FAILED: ${workflow.runName}" } def summary = [:] - for (group in summary_params.keySet()) { - summary << summary_params[group] - } + summary_params + .keySet() + .sort() + .each { group -> + summary << summary_params[group] + } def misc_fields = [:] misc_fields['Date Started'] = workflow.start misc_fields['Date Completed'] = workflow.complete misc_fields['Pipeline script file path'] = workflow.scriptFile misc_fields['Pipeline script hash ID'] = workflow.scriptId - if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository - if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId - if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision - misc_fields['Nextflow Version'] = workflow.nextflow.version - misc_fields['Nextflow Build'] = workflow.nextflow.build + if (workflow.repository) { + misc_fields['Pipeline repository Git URL'] = workflow.repository + } + if (workflow.commitId) { + misc_fields['Pipeline repository Git Commit'] = workflow.commitId + } + if (workflow.revision) { + misc_fields['Pipeline Git branch/tag'] = workflow.revision + } + misc_fields['Nextflow Version'] = workflow.nextflow.version + misc_fields['Nextflow Build'] = workflow.nextflow.build misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp def email_fields = [:] @@ -338,39 +341,41 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi // Render the sendmail template def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as nextflow.util.MemoryUnit - def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "${workflow.projectDir}", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] + def smail_fields = [email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "${workflow.projectDir}", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes()] def sf = new File("${workflow.projectDir}/assets/sendmail_template.txt") def sendmail_template = engine.createTemplate(sf).make(smail_fields) def sendmail_html = sendmail_template.toString() // Send the HTML e-mail - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map if (email_address) { try { - if (plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + if (plaintext_email) { +new org.codehaus.groovy.GroovyException('Send plaintext e-mail, not HTML') } // Try to send HTML e-mail using sendmail def sendmail_tf = new File(workflow.launchDir.toString(), ".sendmail_tmp.html") sendmail_tf.withWriter { w -> w << sendmail_html } - [ 'sendmail', '-t' ].execute() << sendmail_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" - } catch (all) { + ['sendmail', '-t'].execute() << sendmail_html + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Sent summary e-mail to ${email_address} (sendmail)-") + } + catch (Exception all) { // Catch failures and try with plaintext - def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] + def mail_cmd = ['mail', '-s', subject, '--content-type=text/html', email_address] mail_cmd.execute() << email_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Sent summary e-mail to ${email_address} (mail)-") } } // Write summary e-mail HTML to a file def output_hf = new File(workflow.launchDir.toString(), ".pipeline_report.html") output_hf.withWriter { w -> w << email_html } - FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html"); + nextflow.extension.FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html") output_hf.delete() // Write summary e-mail TXT to a file def output_tf = new File(workflow.launchDir.toString(), ".pipeline_report.txt") output_tf.withWriter { w -> w << email_txt } - FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt"); + nextflow.extension.FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt") output_tf.delete() } @@ -378,15 +383,17 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi // Print pipeline summary on completion // def completionSummary(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map if (workflow.success) { if (workflow.stats.ignoredCount == 0) { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Pipeline completed successfully${colors.reset}-") + } + else { + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-") } - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" + } + else { + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.red} Pipeline completed with errors${colors.reset}-") } } @@ -395,21 +402,30 @@ def completionSummary(monochrome_logs=true) { // def imNotification(summary_params, hook_url) { def summary = [:] - for (group in summary_params.keySet()) { - summary << summary_params[group] - } + summary_params + .keySet() + .sort() + .each { group -> + summary << summary_params[group] + } def misc_fields = [:] - misc_fields['start'] = workflow.start - misc_fields['complete'] = workflow.complete - misc_fields['scriptfile'] = workflow.scriptFile - misc_fields['scriptid'] = workflow.scriptId - if (workflow.repository) misc_fields['repository'] = workflow.repository - if (workflow.commitId) misc_fields['commitid'] = workflow.commitId - if (workflow.revision) misc_fields['revision'] = workflow.revision - misc_fields['nxf_version'] = workflow.nextflow.version - misc_fields['nxf_build'] = workflow.nextflow.build - misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) { + misc_fields['repository'] = workflow.repository + } + if (workflow.commitId) { + misc_fields['commitid'] = workflow.commitId + } + if (workflow.revision) { + misc_fields['revision'] = workflow.revision + } + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp def msg_fields = [:] msg_fields['version'] = getWorkflowVersion() @@ -434,13 +450,13 @@ def imNotification(summary_params, hook_url) { def json_message = json_template.toString() // POST - def post = new URL(hook_url).openConnection(); + def post = new URL(hook_url).openConnection() post.setRequestMethod("POST") post.setDoOutput(true) post.setRequestProperty("Content-Type", "application/json") - post.getOutputStream().write(json_message.getBytes("UTF-8")); - def postRC = post.getResponseCode(); - if (! postRC.equals(200)) { - log.warn(post.getErrorStream().getText()); + post.getOutputStream().write(json_message.getBytes("UTF-8")) + def postRC = post.getResponseCode() + if (!postRC.equals(200)) { + log.warn(post.getErrorStream().getText()) } } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/main.nf b/subworkflows/nf-core/utils_nfschema_plugin/main.nf new file mode 100644 index 00000000..4994303e --- /dev/null +++ b/subworkflows/nf-core/utils_nfschema_plugin/main.nf @@ -0,0 +1,46 @@ +// +// Subworkflow that uses the nf-schema plugin to validate parameters and render the parameter summary +// + +include { paramsSummaryLog } from 'plugin/nf-schema' +include { validateParameters } from 'plugin/nf-schema' + +workflow UTILS_NFSCHEMA_PLUGIN { + + take: + input_workflow // workflow: the workflow object used by nf-schema to get metadata from the workflow + validate_params // boolean: validate the parameters + parameters_schema // string: path to the parameters JSON schema. + // this has to be the same as the schema given to `validation.parametersSchema` + // when this input is empty it will automatically use the configured schema or + // "${projectDir}/nextflow_schema.json" as default. This input should not be empty + // for meta pipelines + + main: + + // + // Print parameter summary to stdout. This will display the parameters + // that differ from the default given in the JSON schema + // + if(parameters_schema) { + log.info paramsSummaryLog(input_workflow, parameters_schema:parameters_schema) + } else { + log.info paramsSummaryLog(input_workflow) + } + + // + // Validate the parameters using nextflow_schema.json or the schema + // given via the validation.parametersSchema configuration option + // + if(validate_params) { + if(parameters_schema) { + validateParameters(parameters_schema:parameters_schema) + } else { + validateParameters() + } + } + + emit: + dummy_emit = true +} + diff --git a/subworkflows/nf-core/utils_nfschema_plugin/meta.yml b/subworkflows/nf-core/utils_nfschema_plugin/meta.yml new file mode 100644 index 00000000..f7d9f028 --- /dev/null +++ b/subworkflows/nf-core/utils_nfschema_plugin/meta.yml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "utils_nfschema_plugin" +description: Run nf-schema to validate parameters and create a summary of changed parameters +keywords: + - validation + - JSON schema + - plugin + - parameters + - summary +components: [] +input: + - input_workflow: + type: object + description: | + The workflow object of the used pipeline. + This object contains meta data used to create the params summary log + - validate_params: + type: boolean + description: Validate the parameters and error if invalid. + - parameters_schema: + type: string + description: | + Path to the parameters JSON schema. + This has to be the same as the schema given to the `validation.parametersSchema` config + option. When this input is empty it will automatically use the configured schema or + "${projectDir}/nextflow_schema.json" as default. The schema should not be given in this way + for meta pipelines. +output: + - dummy_emit: + type: boolean + description: Dummy emit to make nf-core subworkflows lint happy +authors: + - "@nvnieuwk" +maintainers: + - "@nvnieuwk" diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test new file mode 100644 index 00000000..842dc432 --- /dev/null +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test @@ -0,0 +1,117 @@ +nextflow_workflow { + + name "Test Subworkflow UTILS_NFSCHEMA_PLUGIN" + script "../main.nf" + workflow "UTILS_NFSCHEMA_PLUGIN" + + tag "subworkflows" + tag "subworkflows_nfcore" + tag "subworkflows/utils_nfschema_plugin" + tag "plugin/nf-schema" + + config "./nextflow.config" + + test("Should run nothing") { + + when { + + params { + test_data = '' + } + + workflow { + """ + validate_params = false + input[0] = workflow + input[1] = validate_params + input[2] = "" + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } + + test("Should validate params") { + + when { + + params { + test_data = '' + outdir = 1 + } + + workflow { + """ + validate_params = true + input[0] = workflow + input[1] = validate_params + input[2] = "" + """ + } + } + + then { + assertAll( + { assert workflow.failed }, + { assert workflow.stdout.any { it.contains('ERROR ~ Validation of pipeline parameters failed!') } } + ) + } + } + + test("Should run nothing - custom schema") { + + when { + + params { + test_data = '' + } + + workflow { + """ + validate_params = false + input[0] = workflow + input[1] = validate_params + input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } + + test("Should validate params - custom schema") { + + when { + + params { + test_data = '' + outdir = 1 + } + + workflow { + """ + validate_params = true + input[0] = workflow + input[1] = validate_params + input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + """ + } + } + + then { + assertAll( + { assert workflow.failed }, + { assert workflow.stdout.any { it.contains('ERROR ~ Validation of pipeline parameters failed!') } } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config new file mode 100644 index 00000000..0907ac58 --- /dev/null +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config @@ -0,0 +1,8 @@ +plugins { + id "nf-schema@2.1.0" +} + +validation { + parametersSchema = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + monochromeLogs = true +} \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json similarity index 95% rename from subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json rename to subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json index 7626c1c9..331e0d2f 100644 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json @@ -1,10 +1,10 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://raw.githubusercontent.com/./master/nextflow_schema.json", "title": ". pipeline parameters", "description": "", "type": "object", - "definitions": { + "$defs": { "input_output_options": { "title": "Input/output options", "type": "object", @@ -87,10 +87,10 @@ }, "allOf": [ { - "$ref": "#/definitions/input_output_options" + "$ref": "#/$defs/input_output_options" }, { - "$ref": "#/definitions/generic_options" + "$ref": "#/$defs/generic_options" } ] } diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf b/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf deleted file mode 100644 index 2585b65d..00000000 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf +++ /dev/null @@ -1,62 +0,0 @@ -// -// Subworkflow that uses the nf-validation plugin to render help text and parameter summary -// - -/* -======================================================================================== - IMPORT NF-VALIDATION PLUGIN -======================================================================================== -*/ - -include { paramsHelp } from 'plugin/nf-validation' -include { paramsSummaryLog } from 'plugin/nf-validation' -include { validateParameters } from 'plugin/nf-validation' - -/* -======================================================================================== - SUBWORKFLOW DEFINITION -======================================================================================== -*/ - -workflow UTILS_NFVALIDATION_PLUGIN { - - take: - print_help // boolean: print help - workflow_command // string: default commmand used to run pipeline - pre_help_text // string: string to be printed before help text and summary log - post_help_text // string: string to be printed after help text and summary log - validate_params // boolean: validate parameters - schema_filename // path: JSON schema file, null to use default value - - main: - - log.debug "Using schema file: ${schema_filename}" - - // Default values for strings - pre_help_text = pre_help_text ?: '' - post_help_text = post_help_text ?: '' - workflow_command = workflow_command ?: '' - - // - // Print help message if needed - // - if (print_help) { - log.info pre_help_text + paramsHelp(workflow_command, parameters_schema: schema_filename) + post_help_text - System.exit(0) - } - - // - // Print parameter summary to stdout - // - log.info pre_help_text + paramsSummaryLog(workflow, parameters_schema: schema_filename) + post_help_text - - // - // Validate parameters relative to the parameter JSON schema - // - if (validate_params){ - validateParameters(parameters_schema: schema_filename) - } - - emit: - dummy_emit = true -} diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml b/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml deleted file mode 100644 index 3d4a6b04..00000000 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml +++ /dev/null @@ -1,44 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json -name: "UTILS_NFVALIDATION_PLUGIN" -description: Use nf-validation to initiate and validate a pipeline -keywords: - - utility - - pipeline - - initialise - - validation -components: [] -input: - - print_help: - type: boolean - description: | - Print help message and exit - - workflow_command: - type: string - description: | - The command to run the workflow e.g. "nextflow run main.nf" - - pre_help_text: - type: string - description: | - Text to print before the help message - - post_help_text: - type: string - description: | - Text to print after the help message - - validate_params: - type: boolean - description: | - Validate the parameters and error if invalid. - - schema_filename: - type: string - description: | - The filename of the schema to validate against. -output: - - dummy_emit: - type: boolean - description: | - Dummy emit to make nf-core subworkflows lint happy -authors: - - "@adamrtalbot" -maintainers: - - "@adamrtalbot" - - "@maxulysse" diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test deleted file mode 100644 index 5784a33f..00000000 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test +++ /dev/null @@ -1,200 +0,0 @@ -nextflow_workflow { - - name "Test Workflow UTILS_NFVALIDATION_PLUGIN" - script "../main.nf" - workflow "UTILS_NFVALIDATION_PLUGIN" - tag "subworkflows" - tag "subworkflows_nfcore" - tag "plugin/nf-validation" - tag "'plugin/nf-validation'" - tag "utils_nfvalidation_plugin" - tag "subworkflows/utils_nfvalidation_plugin" - - test("Should run nothing") { - - when { - - params { - monochrome_logs = true - test_data = '' - } - - workflow { - """ - help = false - workflow_command = null - pre_help_text = null - post_help_text = null - validate_params = false - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.success } - ) - } - } - - test("Should run help") { - - - when { - - params { - monochrome_logs = true - test_data = '' - } - workflow { - """ - help = true - workflow_command = null - pre_help_text = null - post_help_text = null - validate_params = false - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.success }, - { assert workflow.exitStatus == 0 }, - { assert workflow.stdout.any { it.contains('Input/output options') } }, - { assert workflow.stdout.any { it.contains('--outdir') } } - ) - } - } - - test("Should run help with command") { - - when { - - params { - monochrome_logs = true - test_data = '' - } - workflow { - """ - help = true - workflow_command = "nextflow run noorg/doesntexist" - pre_help_text = null - post_help_text = null - validate_params = false - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.success }, - { assert workflow.exitStatus == 0 }, - { assert workflow.stdout.any { it.contains('nextflow run noorg/doesntexist') } }, - { assert workflow.stdout.any { it.contains('Input/output options') } }, - { assert workflow.stdout.any { it.contains('--outdir') } } - ) - } - } - - test("Should run help with extra text") { - - - when { - - params { - monochrome_logs = true - test_data = '' - } - workflow { - """ - help = true - workflow_command = "nextflow run noorg/doesntexist" - pre_help_text = "pre-help-text" - post_help_text = "post-help-text" - validate_params = false - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.success }, - { assert workflow.exitStatus == 0 }, - { assert workflow.stdout.any { it.contains('pre-help-text') } }, - { assert workflow.stdout.any { it.contains('nextflow run noorg/doesntexist') } }, - { assert workflow.stdout.any { it.contains('Input/output options') } }, - { assert workflow.stdout.any { it.contains('--outdir') } }, - { assert workflow.stdout.any { it.contains('post-help-text') } } - ) - } - } - - test("Should validate params") { - - when { - - params { - monochrome_logs = true - test_data = '' - outdir = 1 - } - workflow { - """ - help = false - workflow_command = null - pre_help_text = null - post_help_text = null - validate_params = true - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.failed }, - { assert workflow.stdout.any { it.contains('ERROR ~ ERROR: Validation of pipeline parameters failed!') } } - ) - } - } -} diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml deleted file mode 100644 index 60b1cfff..00000000 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -subworkflows/utils_nfvalidation_plugin: - - subworkflows/nf-core/utils_nfvalidation_plugin/** diff --git a/workflows/airrflow.nf b/workflows/airrflow.nf index 4d228544..93bda121 100644 --- a/workflows/airrflow.nf +++ b/workflows/airrflow.nf @@ -43,6 +43,7 @@ include { CLONAL_ANALYSIS } from '../subworkflows/local/clonal_ana include { REPERTOIRE_ANALYSIS_REPORTING } from '../subworkflows/local/repertoire_analysis_reporting' include { SC_RAW_INPUT } from '../subworkflows/local/sc_raw_input' include { FASTQ_INPUT_CHECK } from '../subworkflows/local/fastq_input_check' +include { RNASEQ_INPUT } from '../subworkflows/local/rnaseq_input' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -54,7 +55,7 @@ include { FASTQ_INPUT_CHECK } from '../subworkflows/local/fastq_inpu // MODULE: Installed directly from nf-core/modules // include { MULTIQC } from '../modules/nf-core/multiqc/main' -include { paramsSummaryMap } from 'plugin/nf-validation' +include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_airrflow_pipeline' @@ -68,7 +69,7 @@ include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_airr workflow AIRRFLOW { take: - ch_input + ch_input // channel: samplesheet read in from --input main: @@ -94,24 +95,51 @@ workflow AIRRFLOW { ch_validated_samplesheet = SC_RAW_INPUT.out.samplesheet.collect() - ch_presto_filterseq_logs = Channel.empty() - ch_presto_maskprimers_logs = Channel.empty() - ch_presto_pairseq_logs = Channel.empty() - ch_presto_clustersets_logs = Channel.empty() - ch_presto_buildconsensus_logs = Channel.empty() - ch_presto_postconsensus_pairseq_logs = Channel.empty() - ch_presto_assemblepairs_logs = Channel.empty() - ch_presto_collapseseq_logs = Channel.empty() - ch_presto_splitseq_logs = Channel.empty() - ch_fastp_html = Channel.empty() - ch_fastp_json = Channel.empty() - ch_fastqc_postassembly_mqc = Channel.empty() - } else { - // Perform sequence assembly if input type is fastq from bulk sequencing data - SEQUENCE_ASSEMBLY( - ch_input, - DATABASES.out.igblast.collect() - ) + ch_presto_filterseq_logs = Channel.empty() + ch_presto_maskprimers_logs = Channel.empty() + ch_presto_pairseq_logs = Channel.empty() + ch_presto_clustersets_logs = Channel.empty() + ch_presto_buildconsensus_logs = Channel.empty() + ch_presto_postconsensus_pairseq_logs = Channel.empty() + ch_presto_assemblepairs_logs = Channel.empty() + ch_presto_collapseseq_logs = Channel.empty() + ch_presto_splitseq_logs = Channel.empty() + ch_fastp_html = Channel.empty() + ch_fastp_json = Channel.empty() + ch_fastqc_postassembly_mqc = Channel.empty() + + } else if (params.library_generation_method == "trust4") { + // Extract VDJ sequences from "general" RNA seq data using TRUST4 + + RNASEQ_INPUT ( + ch_input, + DATABASES.out.igblast.collect() + ) + + ch_fasta = RNASEQ_INPUT.out.fasta + ch_versions = ch_versions.mix(RNASEQ_INPUT.out.versions) + + ch_validated_samplesheet = RNASEQ_INPUT.out.samplesheet.collect() + + ch_presto_filterseq_logs = Channel.empty() + ch_presto_maskprimers_logs = Channel.empty() + ch_presto_pairseq_logs = Channel.empty() + ch_presto_clustersets_logs = Channel.empty() + ch_presto_buildconsensus_logs = Channel.empty() + ch_presto_postconsensus_pairseq_logs = Channel.empty() + ch_presto_assemblepairs_logs = Channel.empty() + ch_presto_collapseseq_logs = Channel.empty() + ch_presto_splitseq_logs = Channel.empty() + ch_fastp_html = RNASEQ_INPUT.out.fastp_reads_html + ch_fastp_json = RNASEQ_INPUT.out.fastp_reads_json + ch_fastqc_postassembly_mqc = Channel.empty() + } + else { + // Perform sequence assembly if input type is fastq from bulk sequencing data + SEQUENCE_ASSEMBLY( + ch_input, + DATABASES.out.igblast.collect() + ) ch_fasta = SEQUENCE_ASSEMBLY.out.fasta ch_versions = ch_versions.mix(SEQUENCE_ASSEMBLY.out.versions) @@ -246,7 +274,6 @@ workflow AIRRFLOW { ) } ch_versions = ch_versions.mix( REPERTOIRE_ANALYSIS_REPORTING.out.versions ) - ch_versions.dump(tag: "channel_versions") // // Collate and save software versions @@ -254,7 +281,7 @@ workflow AIRRFLOW { softwareVersionsToYAML(ch_versions) .collectFile( storeDir: "${params.outdir}/pipeline_info", - name: 'nf_core_pipeline_software_mqc_versions.yml', + name: 'nf_core_' + 'pipeline_software_' + 'mqc_' + 'versions.yml', sort: true, newLine: true ).set { ch_collated_versions } @@ -281,7 +308,9 @@ workflow AIRRFLOW { ch_multiqc_files.collect(), ch_multiqc_config.toList(), ch_multiqc_custom_config.toList(), - ch_report_logo.toList() + ch_report_logo.toList(), + [], + [] ) multiqc_report = MULTIQC.out.report.toList() } else {